aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore24
-rw-r--r--INSTALL-WIN32.md671
-rw-r--r--INSTALL.md101
-rw-r--r--Makefile.in149
-rw-r--r--README.dtrace.md393
-rw-r--r--README.systemtap.md72
-rw-r--r--[l---------]aclocal.m41873
-rw-r--r--bootstrap/bin/start.bootbin5324 -> 5254 bytes
-rw-r--r--bootstrap/bin/start_clean.bootbin5324 -> 5254 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11096 -> 11576 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin14388 -> 14388 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bool.beambin16160 -> 16156 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bsm.beambin13728 -> 13724 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_clean.beambin11468 -> 11468 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dead.beambin11880 -> 10180 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin5360 -> 5364 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin24968 -> 25032 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_except.beambin0 -> 3484 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin9516 -> 9516 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_listing.beambin2904 -> 2904 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_receive.beambin5832 -> 5832 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_split.beambin0 -> 2048 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_trim.beambin8568 -> 8568 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_type.beambin13820 -> 14032 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin14532 -> 14604 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin34328 -> 34536 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl.beambin30264 -> 30264 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_clauses.beambin2876 -> 2876 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_inline.beambin37300 -> 37572 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_trees.beambin18960 -> 18952 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin36920 -> 37460 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lib.beambin5468 -> 5468 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lint.beambin11632 -> 11632 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_parse.beambin37644 -> 37696 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin12124 -> 12124 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_scan.beambin6628 -> 6628 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/erl_bifs.beambin2100 -> 2156 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/rec_env.beambin4780 -> 4780 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_dsetel.beambin6996 -> 6996 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin47520 -> 46776 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_inline.beambin4212 -> 4208 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_expand_pmod.beambin8396 -> 8424 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_attributes.beambin3360 -> 3356 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_expand.beambin16504 -> 16292 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_codegen.beambin53752 -> 51696 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin50836 -> 51076 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin44748 -> 42764 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel_pp.beambin11828 -> 11828 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_life.beambin23528 -> 19924 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application.beambin2940 -> 3772 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_controller.beambin30684 -> 30996 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_master.beambin6352 -> 6352 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/auth.beambin6328 -> 6480 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin6732 -> 6716 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin25956 -> 26256 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log.beambin36248 -> 37260 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_1.beambin24896 -> 24896 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_server.beambin6408 -> 6408 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_ac.beambin26708 -> 26708 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_util.beambin10508 -> 10508 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erts_debug.beambin2808 -> 3316 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file.beambin12212 -> 14244 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin14196 -> 14248 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_server.beambin5124 -> 5328 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_sctp.beambin3372 -> 3528 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin32236 -> 32236 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_group.beambin17728 -> 17728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin11776 -> 11784 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin12540 -> 12500 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin19688 -> 20168 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_sctp.beambin1408 -> 1556 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp.beambin2664 -> 2684 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp_dist.beambin6256 -> 6256 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_udp.beambin1720 -> 1732 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_config.beambin8192 -> 8192 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin26424 -> 26424 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_dns.beambin19748 -> 19728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_gethost_native.beambin10500 -> 10484 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin13056 -> 13056 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_res.beambin14816 -> 14816 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_sctp.beambin2168 -> 2300 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp.beambin2472 -> 2492 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp_dist.beambin6540 -> 6540 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_udp.beambin1904 -> 1920 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel_config.beambin2720 -> 2720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin22720 -> 22720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/os.beambin5228 -> 5228 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/packages.beambin2244 -> 2244 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/pg2.beambin7696 -> 7696 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/rpc.beambin8748 -> 8748 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/standard_error.beambin3636 -> 3636 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin12360 -> 12332 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_drv.beambin10084 -> 10308 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_sup.beambin1768 -> 1764 bytes
-rw-r--r--bootstrap/lib/kernel/include/dist.hrl2
-rw-r--r--bootstrap/lib/kernel/include/dist_util.hrl2
-rw-r--r--bootstrap/lib/kernel/include/file.hrl11
-rw-r--r--bootstrap/lib/kernel/include/net_address.hrl2
-rw-r--r--bootstrap/lib/stdlib/ebin/array.beambin12036 -> 12036 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/base64.beambin4540 -> 4532 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin18220 -> 18060 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin13932 -> 13932 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin53204 -> 53456 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_server.beambin7020 -> 7020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin28864 -> 28864 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v8.beambin27508 -> 27516 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin50272 -> 50072 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dict.beambin9140 -> 9140 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph.beambin8320 -> 8320 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6800 -> 6808 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin24216 -> 24276 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_compile.beambin5076 -> 4896 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin23480 -> 23752 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_expand_records.beambin21812 -> 21900 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_internal.beambin5016 -> 5016 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin84792 -> 85172 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin71068 -> 71552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin23228 -> 23344 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin31776 -> 31784 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin15352 -> 15352 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_file_h.beambin5056 -> 5128 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_tty_h.beambin4936 -> 5008 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/escript.beambin17044 -> 17056 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin20048 -> 20008 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/eval_bits.beambin6748 -> 6748 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin30608 -> 30592 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filelib.beambin7280 -> 7308 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filename.beambin12560 -> 12412 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_sets.beambin8256 -> 8256 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_trees.beambin4992 -> 4992 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen.beambin3864 -> 4112 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_event.beambin12900 -> 17604 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_fsm.beambin9412 -> 15348 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_server.beambin12508 -> 17260 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib.beambin8900 -> 8896 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin12372 -> 12364 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lib.beambin9072 -> 9068 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin29204 -> 29204 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/log_mf_h.beambin2644 -> 2644 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin20316 -> 20180 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/orddict.beambin2748 -> 2748 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin9140 -> 7160 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pool.beambin3848 -> 3848 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proc_lib.beambin9200 -> 9200 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin69344 -> 69376 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin71592 -> 71584 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/queue.beambin5900 -> 5900 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/random.beambin1580 -> 1552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin12376 -> 12348 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/regexp.beambin8524 -> 0 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sets.beambin7020 -> 7020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin30568 -> 30628 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin41096 -> 41100 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/string.beambin4744 -> 4744 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin18136 -> 22940 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor_bridge.beambin1980 -> 2760 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin7328 -> 7328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/timer.beambin5452 -> 5452 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin11552 -> 11412 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin26824 -> 26800 bytes
-rw-r--r--configure.in16
-rw-r--r--erts/Makefile.in81
-rw-r--r--erts/aclocal.m4208
-rw-r--r--erts/autoconf/vxworks/sed.general1
-rwxr-xr-xerts/autoconf/win64.config.cache.static271
-rw-r--r--erts/configure.in455
-rw-r--r--erts/doc/src/Makefile18
-rw-r--r--erts/doc/src/absform.xml5
-rw-r--r--erts/doc/src/driver.xml10
-rw-r--r--erts/doc/src/driver_entry.xml48
-rw-r--r--erts/doc/src/erl.xml197
-rw-r--r--erts/doc/src/erl_driver.xml332
-rw-r--r--[-rwxr-xr-x]erts/doc/src/erl_ext_fig.gifbin3834 -> 3834 bytes
-rw-r--r--erts/doc/src/erl_nif.xml65
-rw-r--r--erts/doc/src/erlang.xml458
-rw-r--r--erts/doc/src/erlc.xml6
-rw-r--r--erts/doc/src/erlsrv.xml13
-rw-r--r--erts/doc/src/erts_alloc.xml58
-rw-r--r--erts/doc/src/make.dep32
-rw-r--r--erts/doc/src/match_spec.xml8
-rw-r--r--erts/doc/src/notes.xml757
-rw-r--r--erts/emulator/Makefile.in407
-rw-r--r--erts/emulator/beam/atom.h4
-rw-r--r--erts/emulator/beam/atom.names12
-rw-r--r--erts/emulator/beam/beam_bif_load.c125
-rw-r--r--erts/emulator/beam/beam_bp.c58
-rw-r--r--erts/emulator/beam/beam_bp.h17
-rw-r--r--erts/emulator/beam/beam_catches.c48
-rw-r--r--erts/emulator/beam/beam_debug.c32
-rw-r--r--erts/emulator/beam/beam_emu.c702
-rw-r--r--erts/emulator/beam/beam_load.c856
-rw-r--r--erts/emulator/beam/beam_load.h14
-rw-r--r--erts/emulator/beam/benchmark.c32
-rw-r--r--erts/emulator/beam/benchmark.h11
-rw-r--r--erts/emulator/beam/bif.c542
-rw-r--r--erts/emulator/beam/bif.h155
-rw-r--r--erts/emulator/beam/bif.tab33
-rw-r--r--erts/emulator/beam/big.c102
-rw-r--r--erts/emulator/beam/big.h2
-rw-r--r--erts/emulator/beam/binary.c12
-rw-r--r--erts/emulator/beam/break.c25
-rw-r--r--erts/emulator/beam/copy.c448
-rw-r--r--erts/emulator/beam/dist.c291
-rw-r--r--erts/emulator/beam/dtrace-wrapper.h111
-rw-r--r--erts/emulator/beam/erl_afit_alloc.c18
-rw-r--r--erts/emulator/beam/erl_alloc.c1373
-rw-r--r--erts/emulator/beam/erl_alloc.h203
-rw-r--r--erts/emulator/beam/erl_alloc.types80
-rw-r--r--erts/emulator/beam/erl_alloc_util.c1086
-rw-r--r--erts/emulator/beam/erl_alloc_util.h115
-rw-r--r--erts/emulator/beam/erl_ao_firstfit_alloc.c16
-rw-r--r--erts/emulator/beam/erl_arith.c8
-rw-r--r--erts/emulator/beam/erl_async.c772
-rw-r--r--erts/emulator/beam/erl_async.h66
-rw-r--r--erts/emulator/beam/erl_bestfit_alloc.c16
-rw-r--r--erts/emulator/beam/erl_bif_binary.c80
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c161
-rw-r--r--erts/emulator/beam/erl_bif_guard.c6
-rwxr-xr-x[-rw-r--r--]erts/emulator/beam/erl_bif_info.c420
-rw-r--r--erts/emulator/beam/erl_bif_lists.c104
-rw-r--r--erts/emulator/beam/erl_bif_op.c25
-rw-r--r--erts/emulator/beam/erl_bif_os.c118
-rw-r--r--erts/emulator/beam/erl_bif_port.c139
-rw-r--r--erts/emulator/beam/erl_bif_re.c135
-rw-r--r--erts/emulator/beam/erl_bif_timer.c11
-rw-r--r--erts/emulator/beam/erl_bif_trace.c174
-rw-r--r--erts/emulator/beam/erl_bits.c22
-rw-r--r--erts/emulator/beam/erl_cpu_topology.c23
-rw-r--r--erts/emulator/beam/erl_db.c183
-rw-r--r--erts/emulator/beam/erl_db_hash.c85
-rw-r--r--erts/emulator/beam/erl_db_hash.h5
-rw-r--r--erts/emulator/beam/erl_db_tree.c10
-rw-r--r--erts/emulator/beam/erl_db_util.c73
-rw-r--r--erts/emulator/beam/erl_db_util.h6
-rw-r--r--erts/emulator/beam/erl_debug.c268
-rw-r--r--erts/emulator/beam/erl_debug.h22
-rw-r--r--erts/emulator/beam/erl_driver.h125
-rw-r--r--erts/emulator/beam/erl_drv_thread.c8
-rw-r--r--erts/emulator/beam/erl_fun.h4
-rw-r--r--erts/emulator/beam/erl_gc.c156
-rw-r--r--erts/emulator/beam/erl_gc.h4
-rw-r--r--erts/emulator/beam/erl_goodfit_alloc.c18
-rw-r--r--erts/emulator/beam/erl_init.c391
-rw-r--r--erts/emulator/beam/erl_lock_check.c25
-rw-r--r--erts/emulator/beam/erl_lock_count.c29
-rw-r--r--erts/emulator/beam/erl_lock_count.h3
-rw-r--r--erts/emulator/beam/erl_message.c304
-rw-r--r--erts/emulator/beam/erl_message.h15
-rw-r--r--erts/emulator/beam/erl_monitors.c8
-rw-r--r--erts/emulator/beam/erl_mtrace.c8
-rw-r--r--erts/emulator/beam/erl_nif.c1196
-rw-r--r--erts/emulator/beam/erl_nif.h13
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h200
-rw-r--r--erts/emulator/beam/erl_nmgc.c1401
-rw-r--r--erts/emulator/beam/erl_nmgc.h364
-rw-r--r--erts/emulator/beam/erl_node_container_utils.h2
-rw-r--r--erts/emulator/beam/erl_node_tables.c26
-rw-r--r--erts/emulator/beam/erl_node_tables.h3
-rw-r--r--erts/emulator/beam/erl_port_task.c55
-rw-r--r--erts/emulator/beam/erl_process.c2820
-rw-r--r--erts/emulator/beam/erl_process.h259
-rw-r--r--erts/emulator/beam/erl_process_lock.c220
-rw-r--r--erts/emulator/beam/erl_process_lock.h37
-rw-r--r--erts/emulator/beam/erl_sched_spec_pre_alloc.c327
-rw-r--r--erts/emulator/beam/erl_sched_spec_pre_alloc.h240
-rw-r--r--erts/emulator/beam/erl_smp.h97
-rw-r--r--erts/emulator/beam/erl_term.h14
-rw-r--r--erts/emulator/beam/erl_thr_progress.c1377
-rw-r--r--erts/emulator/beam/erl_thr_progress.h317
-rw-r--r--erts/emulator/beam/erl_thr_queue.c762
-rw-r--r--erts/emulator/beam/erl_thr_queue.h209
-rw-r--r--erts/emulator/beam/erl_threads.h333
-rw-r--r--erts/emulator/beam/erl_time.h30
-rw-r--r--erts/emulator/beam/erl_time_sup.c188
-rw-r--r--erts/emulator/beam/erl_trace.c196
-rw-r--r--erts/emulator/beam/erl_unicode.c156
-rw-r--r--erts/emulator/beam/erl_vm.h27
-rw-r--r--erts/emulator/beam/erlang_dtrace.d3636
-rw-r--r--erts/emulator/beam/export.c8
-rw-r--r--erts/emulator/beam/external.c72
-rw-r--r--erts/emulator/beam/external.h4
-rw-r--r--erts/emulator/beam/fix_alloc.c287
-rwxr-xr-x[-rw-r--r--]erts/emulator/beam/global.h335
-rw-r--r--erts/emulator/beam/io.c478
-rw-r--r--erts/emulator/beam/module.c5
-rw-r--r--erts/emulator/beam/ops.tab132
-rw-r--r--erts/emulator/beam/packet_parser.c45
-rw-r--r--erts/emulator/beam/register.h4
-rw-r--r--erts/emulator/beam/sys.h385
-rw-r--r--erts/emulator/beam/time.c49
-rw-r--r--erts/emulator/beam/utils.c854
-rw-r--r--erts/emulator/drivers/common/efile_drv.c1179
-rw-r--r--erts/emulator/drivers/common/erl_efile.h49
-rw-r--r--erts/emulator/drivers/common/gzio.c2
-rw-r--r--erts/emulator/drivers/common/inet_drv.c1321
-rw-r--r--erts/emulator/drivers/common/ram_file_drv.c82
-rw-r--r--erts/emulator/drivers/common/zlib_drv.c29
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c24
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c300
-rw-r--r--erts/emulator/drivers/win32/registry_drv.c21
-rw-r--r--erts/emulator/drivers/win32/ttsl_drv.c38
-rw-r--r--erts/emulator/drivers/win32/win_con.c103
-rw-r--r--[-rwxr-xr-x]erts/emulator/drivers/win32/win_efile.c122
-rw-r--r--erts/emulator/hipe/hipe_abi.txt2
-rw-r--r--erts/emulator/hipe/hipe_amd64_bifs.m453
-rw-r--r--erts/emulator/hipe/hipe_amd64_primops.h2
-rw-r--r--erts/emulator/hipe/hipe_arm.c91
-rw-r--r--erts/emulator/hipe/hipe_arm_bifs.m455
-rw-r--r--erts/emulator/hipe/hipe_bif0.c96
-rw-r--r--erts/emulator/hipe/hipe_bif0.h2
-rw-r--r--erts/emulator/hipe/hipe_bif0.tab2
-rw-r--r--erts/emulator/hipe/hipe_bif1.c25
-rw-r--r--erts/emulator/hipe/hipe_bif2.c31
-rw-r--r--erts/emulator/hipe/hipe_bif2.tab1
-rw-r--r--erts/emulator/hipe/hipe_bif_list.m430
-rw-r--r--erts/emulator/hipe/hipe_gc.c336
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c94
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.c51
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.h2
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c47
-rw-r--r--erts/emulator/hipe/hipe_native_bif.h22
-rw-r--r--erts/emulator/hipe/hipe_ppc.c2
-rw-r--r--erts/emulator/hipe/hipe_ppc_asm.m411
-rw-r--r--erts/emulator/hipe/hipe_ppc_bifs.m459
-rw-r--r--erts/emulator/hipe/hipe_primops.h4
-rw-r--r--erts/emulator/hipe/hipe_process.h6
-rw-r--r--erts/emulator/hipe/hipe_risc_glue.h16
-rw-r--r--erts/emulator/hipe/hipe_sparc_bifs.m465
-rw-r--r--erts/emulator/hipe/hipe_stack.h9
-rw-r--r--erts/emulator/hipe/hipe_x86.h2
-rw-r--r--erts/emulator/hipe/hipe_x86_bifs.m457
-rw-r--r--erts/emulator/hipe/hipe_x86_glue.h19
-rw-r--r--erts/emulator/hipe/hipe_x86_primops.h3
-rw-r--r--erts/emulator/pcre/pcre.mk12
-rw-r--r--erts/emulator/sys/common/erl_check_io.c46
-rw-r--r--erts/emulator/sys/common/erl_check_io.h15
-rw-r--r--erts/emulator/sys/common/erl_mseg.c682
-rw-r--r--erts/emulator/sys/common/erl_mseg.h11
-rw-r--r--erts/emulator/sys/common/erl_poll.c199
-rw-r--r--erts/emulator/sys/common/erl_poll.h7
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h7
-rw-r--r--erts/emulator/sys/unix/sys.c321
-rw-r--r--erts/emulator/sys/vxworks/erl_vxworks_sys.h3
-rw-r--r--erts/emulator/sys/vxworks/sys.c21
-rw-r--r--erts/emulator/sys/win32/erl_poll.c12
-rw-r--r--erts/emulator/sys/win32/erl_win32_sys_ddll.c5
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h44
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h45
-rwxr-xr-x[-rw-r--r--]erts/emulator/sys/win32/sys.c194
-rw-r--r--erts/emulator/sys/win32/sys_env.c562
-rw-r--r--erts/emulator/sys/win32/sys_float.c5
-rw-r--r--erts/emulator/sys/win32/sys_interrupt.c12
-rw-r--r--erts/emulator/sys/win32/sys_time.c327
-rw-r--r--erts/emulator/test/Makefile15
-rw-r--r--erts/emulator/test/a_SUITE_data/timer_driver.c20
-rw-r--r--erts/emulator/test/alloc_SUITE_data/allocator_test.h2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.c25
-rw-r--r--erts/emulator/test/bif_SUITE.erl56
-rw-r--r--erts/emulator/test/big_SUITE.erl15
-rw-r--r--erts/emulator/test/binary_SUITE.erl9
-rw-r--r--erts/emulator/test/bs_construct_SUITE.erl8
-rw-r--r--erts/emulator/test/bs_utf_SUITE.erl12
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/busy_drv.c19
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c14
-rw-r--r--erts/emulator/test/call_trace_SUITE.erl59
-rw-r--r--erts/emulator/test/code_SUITE.erl247
-rw-r--r--erts/emulator/test/code_SUITE_data/fun_confusion.erl31
-rw-r--r--erts/emulator/test/code_SUITE_data/literals.erl23
-rw-r--r--erts/emulator/test/code_SUITE_data/versions.erl33
-rw-r--r--erts/emulator/test/ddll_SUITE_data/dummy_drv.c19
-rw-r--r--erts/emulator/test/ddll_SUITE_data/echo_drv.c26
-rw-r--r--erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c26
-rw-r--r--erts/emulator/test/ddll_SUITE_data/initfail_drv.c19
-rw-r--r--erts/emulator/test/ddll_SUITE_data/lock_drv.c26
-rw-r--r--erts/emulator/test/ddll_SUITE_data/noinit_drv.c21
-rw-r--r--erts/emulator/test/ddll_SUITE_data/wrongname_drv.c19
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl60
-rw-r--r--erts/emulator/test/distribution_SUITE.erl16
-rw-r--r--erts/emulator/test/driver_SUITE.erl186
-rw-r--r--erts/emulator/test/driver_SUITE_data/Makefile.src8
-rw-r--r--erts/emulator/test/driver_SUITE_data/async_blast_drv.c124
-rw-r--r--erts/emulator/test/driver_SUITE_data/caller_drv.c30
-rw-r--r--erts/emulator/test/driver_SUITE_data/chkio_drv.c90
-rw-r--r--erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c31
-rw-r--r--erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c15
-rw-r--r--erts/emulator/test/driver_SUITE_data/many_events_drv.c28
-rw-r--r--erts/emulator/test/driver_SUITE_data/monitor_drv.c15
-rw-r--r--erts/emulator/test/driver_SUITE_data/otp_6879_drv.c20
-rw-r--r--erts/emulator/test/driver_SUITE_data/otp_9302_drv.c6
-rw-r--r--erts/emulator/test/driver_SUITE_data/outputv_drv.c16
-rw-r--r--erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c13
-rw-r--r--erts/emulator/test/driver_SUITE_data/queue_drv.c23
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c72
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c80
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c78
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c11
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c78
-rw-r--r--erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c16
-rw-r--r--erts/emulator/test/driver_SUITE_data/thr_free_drv.c241
-rw-r--r--erts/emulator/test/driver_SUITE_data/timer_drv.c17
-rw-r--r--erts/emulator/test/emulator.spec1
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c26
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl67
-rw-r--r--erts/emulator/test/float_SUITE.erl131
-rw-r--r--erts/emulator/test/float_SUITE_data/fp_drv.c12
-rw-r--r--erts/emulator/test/fun_SUITE.erl18
-rw-r--r--erts/emulator/test/fun_r12_SUITE.erl97
-rw-r--r--erts/emulator/test/fun_r13_SUITE.erl97
-rw-r--r--erts/emulator/test/hibernate_SUITE.erl10
-rw-r--r--erts/emulator/test/mtx_SUITE.erl17
-rw-r--r--erts/emulator/test/nif_SUITE.erl56
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c32
-rw-r--r--erts/emulator/test/nif_SUITE_data/tester.c1
-rw-r--r--erts/emulator/test/node_container_SUITE.erl16
-rw-r--r--erts/emulator/test/port_SUITE.erl6
-rw-r--r--erts/emulator/test/port_SUITE_data/echo_drv.c30
-rw-r--r--erts/emulator/test/port_SUITE_data/exit_drv.c33
-rw-r--r--erts/emulator/test/port_SUITE_data/failure_drv.c29
-rw-r--r--erts/emulator/test/port_bif_SUITE.erl391
-rw-r--r--erts/emulator/test/port_bif_SUITE_data/control_drv.c25
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl20
-rw-r--r--erts/emulator/test/send_term_SUITE_data/send_term_drv.c20
-rw-r--r--erts/emulator/test/sensitive_SUITE.erl3
-rw-r--r--erts/emulator/test/smoke_test_SUITE.erl139
-rw-r--r--erts/emulator/test/statistics_SUITE.erl98
-rw-r--r--erts/emulator/test/system_info_SUITE.erl313
-rw-r--r--erts/emulator/test/system_profile_SUITE.erl163
-rw-r--r--erts/emulator/test/system_profile_SUITE_data/echo_drv.c30
-rw-r--r--erts/emulator/test/time_SUITE.erl55
-rw-r--r--erts/emulator/test/trace_port_SUITE.erl8
-rw-r--r--erts/emulator/test/trace_port_SUITE_data/echo_drv.c37
-rwxr-xr-xerts/emulator/utils/beam_makeops56
-rwxr-xr-xerts/emulator/utils/make_preload13
-rwxr-xr-xerts/emulator/utils/make_tables39
-rw-r--r--erts/emulator/valgrind/suppress.patched.3.6.0359
-rw-r--r--erts/emulator/valgrind/suppress.standard317
-rw-r--r--erts/emulator/zlib/Makefile23
-rw-r--r--erts/emulator/zlib/Makefile.in102
-rw-r--r--erts/emulator/zlib/zlib.mk74
-rw-r--r--erts/epmd/src/Makefile.in18
-rw-r--r--erts/epmd/test/Makefile6
-rw-r--r--erts/epmd/test/epmd_SUITE.erl2
-rw-r--r--erts/etc/common/Makefile.in297
-rw-r--r--erts/etc/common/dialyzer.c12
-rw-r--r--erts/etc/common/erlc.c11
-rw-r--r--erts/etc/common/erlexec.c220
-rw-r--r--erts/etc/common/escript.c5
-rw-r--r--erts/etc/common/heart.c46
-rw-r--r--erts/etc/common/inet_gethost.c21
-rw-r--r--erts/etc/unix/Install.src40
-rw-r--r--erts/etc/unix/cerl.src4
-rw-r--r--erts/etc/unix/erl.src.src4
-rw-r--r--erts/etc/unix/etp-commands34
-rw-r--r--erts/etc/unix/run_erl.c153
-rw-r--r--erts/etc/unix/to_erl.c9
-rw-r--r--erts/etc/win32/Makefile16
-rwxr-xr-xerts/etc/win32/cygwin_tools/vc/emu_cc.sh11
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_service.c3
-rw-r--r--erts/etc/win32/msys_tools/erl42
-rw-r--r--erts/etc/win32/msys_tools/erlc59
-rw-r--r--erts/etc/win32/msys_tools/javac.sh65
-rw-r--r--erts/etc/win32/msys_tools/make_bootstrap_ini.sh44
-rw-r--r--erts/etc/win32/msys_tools/make_local_ini.sh41
-rw-r--r--erts/etc/win32/msys_tools/msys2win_path.sh44
-rw-r--r--erts/etc/win32/msys_tools/reg_query.sh24
-rw-r--r--erts/etc/win32/msys_tools/vc/ar.sh47
-rw-r--r--erts/etc/win32/msys_tools/vc/cc.sh320
-rw-r--r--erts/etc/win32/msys_tools/vc/coffix.c161
-rw-r--r--erts/etc/win32/msys_tools/vc/emu_cc.sh95
-rw-r--r--erts/etc/win32/msys_tools/vc/ld.sh198
-rw-r--r--erts/etc/win32/msys_tools/vc/mc.sh87
-rw-r--r--erts/etc/win32/msys_tools/vc/rc.sh86
-rw-r--r--erts/etc/win32/msys_tools/win2msys_path.sh38
-rw-r--r--erts/etc/win32/nsis/Makefile31
-rwxr-xr-xerts/etc/win32/nsis/dll_version_helper.sh16
-rw-r--r--erts/etc/win32/nsis/erlang20.nsi63
-rw-r--r--[-rwxr-xr-x]erts/etc/win32/nsis/erlang_uninst.icobin766 -> 766 bytes
-rwxr-xr-xerts/etc/win32/nsis/find_redist.sh52
-rw-r--r--erts/etc/win32/port_entry.c2
-rw-r--r--erts/etc/win32/start_erl.c3
-rw-r--r--erts/etc/win32/win_erlexec.c5
-rw-r--r--erts/include/erl_int_sizes_config.h.in5
-rw-r--r--erts/include/internal/ethr_atomics.h337
-rw-r--r--erts/include/internal/ethr_mutex.h115
-rw-r--r--erts/include/internal/ethread.h1
-rw-r--r--erts/lib_src/Makefile.in61
-rw-r--r--erts/lib_src/common/erl_memory_trace_parser.c15
-rw-r--r--erts/lib_src/common/erl_misc_utils.c10
-rw-r--r--erts/lib_src/common/erl_printf.c6
-rw-r--r--erts/lib_src/common/erl_printf_format.c13
-rw-r--r--erts/lib_src/common/ethr_atomics.c363
-rw-r--r--erts/lib_src/common/ethr_aux.c2
-rw-r--r--erts/lib_src/common/ethr_mutex.c496
-rw-r--r--erts/lib_src/pthread/ethread.c49
-rwxr-xr-xerts/lib_src/utils/make_atomics_api308
-rw-r--r--erts/ntbuild.erl332
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin52880 -> 55108 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin26772 -> 42416 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin45172 -> 48604 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1432 -> 1448 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin32332 -> 40608 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin64884 -> 69952 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin22436 -> 23460 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin12608 -> 12804 bytes
-rw-r--r--erts/preloaded/src/Makefile8
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl336
-rw-r--r--erts/preloaded/src/erlang.erl438
-rw-r--r--erts/preloaded/src/init.erl14
-rw-r--r--erts/preloaded/src/prim_file.erl314
-rw-r--r--erts/preloaded/src/prim_inet.erl190
-rw-r--r--erts/preloaded/src/prim_zip.erl2
-rw-r--r--erts/preloaded/src/zlib.erl74
-rw-r--r--erts/start_scripts/Makefile18
-rw-r--r--erts/test/Makefile8
-rw-r--r--erts/test/erl_print_SUITE.erl8
-rw-r--r--erts/test/erl_print_SUITE_data/Makefile.src30
-rw-r--r--erts/test/erl_print_SUITE_data/erl_print_tests.c4
-rw-r--r--erts/test/erlc_SUITE.erl11
-rw-r--r--erts/test/erlexec_SUITE_data/Makefile.src8
-rw-r--r--erts/test/ethread_SUITE.erl94
-rw-r--r--erts/test/ethread_SUITE_data/Makefile.src8
-rw-r--r--erts/test/ethread_SUITE_data/ethread_tests.c12
-rw-r--r--erts/test/install_SUITE.erl4
-rw-r--r--erts/test/nt_SUITE.erl8
-rw-r--r--erts/test/otp_SUITE.erl116
-rw-r--r--erts/test/run_erl_SUITE.erl2
-rw-r--r--erts/test/utils/gccifier.c13
-rwxr-xr-xerts/test/utils/gccifier.sh26
-rw-r--r--erts/test/z_SUITE.erl29
-rw-r--r--erts/vsn.mk6
-rw-r--r--lib/.gitignore1
-rw-r--r--lib/Makefile60
-rw-r--r--lib/appmon/doc/src/Makefile14
-rw-r--r--lib/appmon/doc/src/appmon.xml8
-rw-r--r--lib/appmon/doc/src/appmon_chapter.xml8
-rw-r--r--lib/appmon/doc/src/make.dep26
-rw-r--r--lib/appmon/doc/src/notes.xml43
-rw-r--r--lib/appmon/priv/Makefile4
-rw-r--r--lib/appmon/src/Makefile8
-rw-r--r--lib/appmon/src/appmon.erl7
-rw-r--r--lib/appmon/src/appmon_a.erl7
-rw-r--r--lib/appmon/src/appmon_lb.erl9
-rw-r--r--lib/appmon/src/appmon_txt.erl7
-rw-r--r--lib/appmon/src/appmon_web.erl8
-rw-r--r--lib/appmon/vsn.mk2
-rw-r--r--lib/asn1/c_src/Makefile8
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c9
-rw-r--r--lib/asn1/doc/src/Makefile106
-rw-r--r--lib/asn1/doc/src/asn1ct.xml94
-rw-r--r--lib/asn1/doc/src/make.dep31
-rw-r--r--lib/asn1/doc/src/notes.xml77
-rw-r--r--lib/asn1/src/Makefile21
-rw-r--r--lib/asn1/src/asn1_db.erl263
-rw-r--r--lib/asn1/src/asn1ct.erl437
-rw-r--r--lib/asn1/src/asn1ct_check.erl172
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber.erl4
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl2
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl156
-rw-r--r--lib/asn1/src/asn1ct_gen.erl42
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl6
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl46
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl45
-rw-r--r--lib/asn1/src/asn1ct_name.erl89
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl39
-rw-r--r--lib/asn1/src/asn1ct_table.erl76
-rw-r--r--lib/asn1/src/asn1ct_value.erl79
-rw-r--r--lib/asn1/src/asn1rt_ber_bin_v2.erl4
-rw-r--r--lib/asn1/src/asn1rt_per_bin.erl46
-rw-r--r--lib/asn1/src/asn1rt_per_bin_rt2ct.erl41
-rw-r--r--lib/asn1/test/Makefile60
-rw-r--r--lib/asn1/test/asn1_SUITE.erl1533
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src2372
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Constraints.py6
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn0
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EnumN2N.asn125
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn18
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/InformationFramework.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/LDAP.asn10
-rw-r--r--lib/asn1/test/asn1_SUITE_data/LargeConstraints.py9
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/Nortel.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/UpperBounds.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn0
-rw-r--r--[-rwxr-xr-x]lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn0
-rw-r--r--lib/asn1/test/asn1_app_test.erl4
-rw-r--r--lib/asn1/test/asn1_bin_particular_SUITE.erl.src2
-rw-r--r--lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src291
-rw-r--r--lib/asn1/test/asn1_common_SUITE.erl.src95
-rw-r--r--lib/asn1/test/asn1_particular_SUITE.erl.src10
-rw-r--r--lib/asn1/test/asn1_test_lib.erl60
-rw-r--r--lib/asn1/test/ber_decode_error.erl13
-rw-r--r--lib/asn1/test/h323test.erl142
-rw-r--r--lib/asn1/test/pem_performance.erl37
-rw-r--r--lib/asn1/test/testChoExtension.erl12
-rw-r--r--lib/asn1/test/testChoExternal.erl14
-rw-r--r--lib/asn1/test/testChoOptional.erl15
-rw-r--r--lib/asn1/test/testChoOptionalImplicitTag.erl14
-rw-r--r--lib/asn1/test/testChoPrim.erl13
-rw-r--r--lib/asn1/test/testChoRecursive.erl13
-rw-r--r--lib/asn1/test/testChoTypeRefCho.erl14
-rw-r--r--lib/asn1/test/testChoTypeRefPrim.erl14
-rw-r--r--lib/asn1/test/testChoTypeRefSeq.erl13
-rw-r--r--lib/asn1/test/testChoTypeRefSet.erl13
-rw-r--r--lib/asn1/test/testChoiceIndefinite.erl15
-rw-r--r--lib/asn1/test/testCompactBitString.erl20
-rw-r--r--lib/asn1/test/testConstraints.erl108
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl20
-rw-r--r--lib/asn1/test/testDER.erl11
-rw-r--r--lib/asn1/test/testDeepTConstr.erl17
-rw-r--r--lib/asn1/test/testDef.erl13
-rw-r--r--lib/asn1/test/testDoubleEllipses.erl14
-rw-r--r--lib/asn1/test/testEnumExt.erl11
-rw-r--r--lib/asn1/test/testExternal.erl35
-rw-r--r--lib/asn1/test/testINSTANCE_OF.erl15
-rw-r--r--lib/asn1/test/testInfObj.erl40
-rw-r--r--lib/asn1/test/testInfObjectClass.erl16
-rw-r--r--lib/asn1/test/testMegaco.erl23
-rw-r--r--lib/asn1/test/testMergeCompile.erl22
-rw-r--r--lib/asn1/test/testMvrasn6.erl44
-rw-r--r--lib/asn1/test/testNBAPsystem.erl87
-rw-r--r--lib/asn1/test/testOpenTypeImplicitTag.erl13
-rw-r--r--lib/asn1/test/testParamBasic.erl20
-rw-r--r--lib/asn1/test/testParameterizedInfObj.erl14
-rw-r--r--lib/asn1/test/testPrim.erl15
-rw-r--r--lib/asn1/test/testPrimExternal.erl13
-rw-r--r--lib/asn1/test/testPrimStrings.erl19
-rw-r--r--lib/asn1/test/testRANAP.erl52
-rw-r--r--lib/asn1/test/testROSE.erl36
-rw-r--r--lib/asn1/test/testSSLspecs.erl71
-rw-r--r--lib/asn1/test/testSelectionTypes.erl11
-rw-r--r--lib/asn1/test/testSeq2738.erl11
-rw-r--r--lib/asn1/test/testSeqDefault.erl12
-rw-r--r--lib/asn1/test/testSeqExtension.erl13
-rw-r--r--lib/asn1/test/testSeqIndefinite.erl11
-rw-r--r--lib/asn1/test/testSeqOf.erl15
-rw-r--r--lib/asn1/test/testSeqOfCho.erl14
-rw-r--r--lib/asn1/test/testSeqOfIndefinite.erl34
-rw-r--r--lib/asn1/test/testSeqOfTag.erl15
-rw-r--r--lib/asn1/test/testSeqOptional.erl13
-rw-r--r--lib/asn1/test/testSeqPrim.erl12
-rw-r--r--lib/asn1/test/testSeqSetDefaultVal.erl11
-rw-r--r--lib/asn1/test/testSeqTag.erl13
-rw-r--r--lib/asn1/test/testSeqTypeRefCho.erl13
-rw-r--r--lib/asn1/test/testSeqTypeRefSeq.erl12
-rw-r--r--lib/asn1/test/testSeqTypeRefSet.erl12
-rw-r--r--lib/asn1/test/testSetDefault.erl13
-rw-r--r--lib/asn1/test/testSetExternal.erl14
-rw-r--r--lib/asn1/test/testSetIndefinite.erl11
-rw-r--r--lib/asn1/test/testSetOf.erl12
-rw-r--r--lib/asn1/test/testSetOfCho.erl12
-rw-r--r--lib/asn1/test/testSetOfExternal.erl12
-rw-r--r--lib/asn1/test/testSetOfTag.erl12
-rw-r--r--lib/asn1/test/testSetOptional.erl16
-rw-r--r--lib/asn1/test/testSetPrim.erl12
-rw-r--r--lib/asn1/test/testSetTag.erl13
-rw-r--r--lib/asn1/test/testSetTypeRefCho.erl12
-rw-r--r--lib/asn1/test/testSetTypeRefPrim.erl12
-rw-r--r--lib/asn1/test/testSetTypeRefSeq.erl12
-rw-r--r--lib/asn1/test/testSetTypeRefSet.erl12
-rw-r--r--lib/asn1/test/testTCAP.erl38
-rw-r--r--lib/asn1/test/testTcapsystem.erl90
-rw-r--r--lib/asn1/test/testTimer.erl8
-rw-r--r--lib/asn1/test/testTypeValueNotation.erl91
-rw-r--r--lib/asn1/test/testX420.erl39
-rw-r--r--lib/asn1/test/test_bad_values.erl29
-rw-r--r--lib/asn1/test/test_compile_options.erl13
-rw-r--r--lib/asn1/test/test_driver_load.erl23
-rw-r--r--lib/asn1/test/test_inline.erl81
-rw-r--r--lib/asn1/test/test_modified_x420.erl12
-rw-r--r--lib/asn1/test/test_partial_incomplete_decode.erl39
-rw-r--r--lib/asn1/test/test_selective_decode.erl11
-rw-r--r--lib/asn1/test/test_special_decode_performance.erl19
-rw-r--r--lib/asn1/test/test_undecoded_rest.erl60
-rw-r--r--lib/asn1/test/test_x691.erl17
-rw-r--r--lib/asn1/vsn.mk4
-rw-r--r--lib/common_test/doc/src/Makefile50
-rw-r--r--lib/common_test/doc/src/basics_chapter.xml82
-rw-r--r--lib/common_test/doc/src/common_test_app.xml269
-rw-r--r--lib/common_test/doc/src/config.gifbin0 -> 4963 bytes
-rw-r--r--lib/common_test/doc/src/config_file_chapter.xml21
-rw-r--r--lib/common_test/doc/src/cover_chapter.xml2
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml6
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml50
-rw-r--r--lib/common_test/doc/src/ct_run.xml25
-rw-r--r--lib/common_test/doc/src/event_handler_chapter.xml20
-rw-r--r--[-rwxr-xr-x]lib/common_test/doc/src/filestruct.gifbin2960 -> 2960 bytes
-rw-r--r--lib/common_test/doc/src/getting_started_chapter.xml231
-rw-r--r--lib/common_test/doc/src/html_logs.gifbin0 -> 10726 bytes
-rw-r--r--lib/common_test/doc/src/make.dep27
-rw-r--r--lib/common_test/doc/src/notes.xml459
-rw-r--r--lib/common_test/doc/src/part.xml1
-rw-r--r--lib/common_test/doc/src/ref_man.xml3
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml126
-rw-r--r--lib/common_test/doc/src/tc_execution.gifbin0 -> 9561 bytes
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml304
-rw-r--r--lib/common_test/include/ct.hrl13
-rw-r--r--lib/common_test/priv/Makefile.in16
-rwxr-xr-x[l---------]lib/common_test/priv/auxdir/config.guess1520
-rwxr-xr-x[l---------]lib/common_test/priv/auxdir/config.sub1631
-rwxr-xr-x[l---------]lib/common_test/priv/auxdir/install-sh520
-rw-r--r--lib/common_test/priv/ct_default.css201
-rw-r--r--lib/common_test/priv/jquery-latest.js154
-rw-r--r--lib/common_test/priv/jquery.tablesorter.min.js4
-rw-r--r--lib/common_test/src/Makefile23
-rw-r--r--lib/common_test/src/common_test.app.src11
-rw-r--r--lib/common_test/src/ct.erl620
-rw-r--r--lib/common_test/src/ct_config.erl258
-rw-r--r--lib/common_test/src/ct_config_plain.erl2
-rw-r--r--lib/common_test/src/ct_config_xml.erl2
-rw-r--r--lib/common_test/src/ct_conn_log_h.erl230
-rw-r--r--lib/common_test/src/ct_event.erl16
-rw-r--r--lib/common_test/src/ct_framework.erl832
-rw-r--r--lib/common_test/src/ct_ftp.erl6
-rw-r--r--lib/common_test/src/ct_gen_conn.erl256
-rw-r--r--lib/common_test/src/ct_hooks.erl41
-rw-r--r--lib/common_test/src/ct_logs.erl1237
-rw-r--r--lib/common_test/src/ct_make.erl2
-rw-r--r--lib/common_test/src/ct_master.erl15
-rw-r--r--lib/common_test/src/ct_master_logs.erl231
-rw-r--r--lib/common_test/src/ct_netconfc.erl1835
-rw-r--r--lib/common_test/src/ct_netconfc.hrl58
-rw-r--r--lib/common_test/src/ct_repeat.erl92
-rw-r--r--lib/common_test/src/ct_run.erl894
-rw-r--r--lib/common_test/src/ct_ssh.erl290
-rw-r--r--lib/common_test/src/ct_telnet.erl4
-rw-r--r--lib/common_test/src/ct_testspec.erl939
-rw-r--r--lib/common_test/src/ct_util.erl122
-rw-r--r--lib/common_test/src/ct_util.hrl19
-rw-r--r--lib/common_test/src/cth_conn_log.erl124
-rw-r--r--lib/common_test/src/cth_log_redirect.erl17
-rw-r--r--lib/common_test/src/cth_surefire.erl219
-rw-r--r--lib/common_test/src/vts.erl6
-rw-r--r--lib/common_test/test/Makefile23
-rw-r--r--lib/common_test/test/common_test.spec2
-rw-r--r--lib/common_test/test/ct_auto_compile_SUITE.erl187
-rw-r--r--lib/common_test/test/ct_auto_compile_SUITE_data/bad_SUITE.erl23
-rw-r--r--lib/common_test/test/ct_auto_compile_SUITE_data/dummy_SUITE.erl130
-rw-r--r--lib/common_test/test/ct_basic_html_SUITE.erl180
-rw-r--r--lib/common_test/test/ct_basic_html_SUITE_data/babbling_SUITE.erl130
-rw-r--r--lib/common_test/test/ct_config_SUITE.erl112
-rw-r--r--lib/common_test/test/ct_config_SUITE_data/config/config.txt3
-rw-r--r--lib/common_test/test/ct_config_SUITE_data/config/config.xml1
-rw-r--r--lib/common_test/test/ct_config_SUITE_data/config/shadow.txt12
-rw-r--r--lib/common_test/test/ct_config_SUITE_data/config/test/config_static_SUITE.erl90
-rw-r--r--lib/common_test/test/ct_config_info_SUITE.erl178
-rw-r--r--lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl168
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl224
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl14
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl154
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl72
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl86
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl7
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl11
-rw-r--r--lib/common_test/test/ct_group_info_SUITE.erl859
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl259
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl252
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl241
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl191
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl184
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl171
-rw-r--r--lib/common_test/test/ct_group_info_SUITE_data/vars.cfg19
-rw-r--r--lib/common_test/test/ct_groups_spec_SUITE.erl586
-rw-r--r--lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl124
-rw-r--r--lib/common_test/test/ct_groups_spec_SUITE_data/override.spec15
-rw-r--r--lib/common_test/test/ct_groups_test_2_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl148
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_data_dir_SUITE.erl67
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl64
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl548
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl130
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_data_dir_cth.erl95
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl101
-rw-r--r--lib/common_test/test/ct_misc_1_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE.erl124
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg6
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl1130
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/ns.erl506
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE.erl277
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec5
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec5
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/default.spec3
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec5
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl137
-rw-r--r--lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl26
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE.erl25
-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.erl74
-rw-r--r--lib/common_test/test/ct_testspec_1_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_testspec_2_SUITE.erl759
-rw-r--r--lib/common_test/test/ct_verbosity_SUITE.erl244
-rw-r--r--lib/common_test/test/ct_verbosity_SUITE_data/io_test_SUITE.erl156
-rw-r--r--lib/common_test/vsn.mk4
-rw-r--r--lib/compiler/doc/src/Makefile14
-rw-r--r--lib/compiler/doc/src/compile.xml11
-rw-r--r--lib/compiler/doc/src/make.dep19
-rw-r--r--lib/compiler/doc/src/notes.xml168
-rw-r--r--lib/compiler/src/Makefile10
-rw-r--r--lib/compiler/src/beam_asm.erl54
-rw-r--r--lib/compiler/src/beam_block.erl2
-rw-r--r--lib/compiler/src/beam_dead.erl65
-rw-r--r--lib/compiler/src/beam_dict.erl15
-rw-r--r--lib/compiler/src/beam_disasm.erl12
-rw-r--r--lib/compiler/src/beam_except.erl149
-rw-r--r--lib/compiler/src/beam_jump.erl2
-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_split.erl85
-rw-r--r--lib/compiler/src/beam_trim.erl2
-rw-r--r--lib/compiler/src/beam_type.erl19
-rw-r--r--lib/compiler/src/beam_utils.erl18
-rw-r--r--lib/compiler/src/beam_validator.erl32
-rw-r--r--lib/compiler/src/cerl_inline.erl26
-rw-r--r--lib/compiler/src/compile.erl71
-rw-r--r--lib/compiler/src/compiler.app.src4
-rw-r--r--lib/compiler/src/erl_bifs.erl3
-rw-r--r--lib/compiler/src/genop.tab2
-rw-r--r--lib/compiler/src/sys_core_fold.erl132
-rw-r--r--lib/compiler/src/sys_expand_pmod.erl4
-rw-r--r--lib/compiler/src/sys_pre_expand.erl57
-rw-r--r--lib/compiler/src/v3_codegen.erl56
-rw-r--r--lib/compiler/src/v3_core.erl23
-rw-r--r--lib/compiler/src/v3_kernel.erl307
-rw-r--r--lib/compiler/src/v3_kernel.hrl3
-rw-r--r--lib/compiler/src/v3_life.erl133
-rw-r--r--lib/compiler/test/Makefile13
-rw-r--r--lib/compiler/test/beam_disasm_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_expect_SUITE.erl67
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl27
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl4
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl7
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl21
-rw-r--r--lib/compiler/test/compilation_SUITE.erl51
-rw-r--r--lib/compiler/test/compilation_SUITE_data/on_load_inline.erl23
-rw-r--r--lib/compiler/test/compile_SUITE.erl115
-rw-r--r--lib/compiler/test/compile_SUITE_data/attributes.erl23
-rw-r--r--lib/compiler/test/compile_SUITE_data/simple-phony.mk3
-rw-r--r--lib/compiler/test/compiler.cover2
-rw-r--r--lib/compiler/test/core_SUITE.erl37
-rw-r--r--lib/compiler/test/core_SUITE_data/eval_is_boolean.core22
-rw-r--r--lib/compiler/test/core_SUITE_data/make_effect_seq.core51
-rw-r--r--lib/compiler/test/core_SUITE_data/nomatch_shadow.core28
-rw-r--r--lib/compiler/test/core_SUITE_data/reversed_annos.core49
-rw-r--r--lib/compiler/test/core_SUITE_data/seq_in_guard.core66
-rw-r--r--lib/compiler/test/core_SUITE_data/unsafe_case.core25
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl35
-rw-r--r--lib/compiler/test/fun_SUITE.erl52
-rw-r--r--lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S8
-rw-r--r--lib/compiler/test/inline_SUITE.erl3
-rw-r--r--lib/compiler/test/inline_SUITE_data/comma_splitter.erl18
-rw-r--r--lib/compiler/test/misc_SUITE.erl29
-rw-r--r--lib/compiler/test/parteval_SUITE.erl66
-rw-r--r--lib/compiler/test/parteval_SUITE_data/t1.erl140
-rw-r--r--lib/compiler/test/pmod_SUITE.erl5
-rw-r--r--lib/compiler/test/pmod_SUITE_data/pmod_basic.erl6
-rw-r--r--lib/compiler/test/test_lib.erl9
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl20
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/configure.in.src4
-rw-r--r--lib/cosEvent/doc/src/Makefile100
-rw-r--r--lib/cosEvent/doc/src/make.dep34
-rw-r--r--lib/cosEvent/doc/src/notes.xml20
-rw-r--r--lib/cosEvent/src/Makefile20
-rw-r--r--lib/cosEvent/test/Makefile10
-rw-r--r--lib/cosEvent/vsn.mk2
-rw-r--r--lib/cosEventDomain/doc/src/Makefile103
-rw-r--r--lib/cosEventDomain/doc/src/make.dep23
-rw-r--r--lib/cosEventDomain/doc/src/notes.xml20
-rw-r--r--lib/cosEventDomain/src/Makefile20
-rw-r--r--lib/cosEventDomain/test/Makefile6
-rw-r--r--lib/cosEventDomain/vsn.mk2
-rw-r--r--lib/cosFileTransfer/doc/src/Makefile103
-rw-r--r--lib/cosFileTransfer/doc/src/make.dep30
-rw-r--r--lib/cosFileTransfer/doc/src/notes.xml20
-rw-r--r--lib/cosFileTransfer/src/Makefile18
-rw-r--r--lib/cosFileTransfer/test/Makefile8
-rw-r--r--lib/cosFileTransfer/test/fileTransfer_SUITE.erl15
-rw-r--r--lib/cosFileTransfer/vsn.mk2
-rw-r--r--lib/cosNotification/doc/src/Makefile102
-rw-r--r--lib/cosNotification/doc/src/make.dep48
-rw-r--r--lib/cosNotification/doc/src/notes.xml20
-rw-r--r--lib/cosNotification/src/Makefile18
-rw-r--r--lib/cosNotification/test/Makefile11
-rw-r--r--lib/cosNotification/vsn.mk2
-rw-r--r--lib/cosProperty/doc/src/Makefile114
-rw-r--r--lib/cosProperty/doc/src/make.dep26
-rw-r--r--lib/cosProperty/doc/src/notes.xml20
-rw-r--r--lib/cosProperty/src/Makefile18
-rw-r--r--lib/cosProperty/test/Makefile10
-rw-r--r--lib/cosProperty/vsn.mk2
-rw-r--r--lib/cosTime/doc/src/Makefile102
-rw-r--r--lib/cosTime/doc/src/make.dep22
-rw-r--r--lib/cosTime/doc/src/notes.xml20
-rw-r--r--lib/cosTime/src/Makefile18
-rw-r--r--lib/cosTime/test/Makefile10
-rw-r--r--lib/cosTime/vsn.mk2
-rw-r--r--lib/cosTransactions/doc/src/Makefile102
-rw-r--r--lib/cosTransactions/doc/src/make.dep27
-rw-r--r--lib/cosTransactions/doc/src/notes.xml20
-rw-r--r--lib/cosTransactions/examples/Makefile6
-rw-r--r--lib/cosTransactions/src/Makefile16
-rw-r--r--lib/cosTransactions/test/Makefile10
-rw-r--r--lib/cosTransactions/vsn.mk2
-rw-r--r--lib/crypto/c_src/Makefile.in12
-rw-r--r--lib/crypto/c_src/crypto.c1056
-rw-r--r--lib/crypto/doc/src/Makefile18
-rw-r--r--lib/crypto/doc/src/crypto.xml295
-rw-r--r--lib/crypto/doc/src/make.dep20
-rw-r--r--lib/crypto/doc/src/notes.xml38
-rw-r--r--lib/crypto/src/Makefile8
-rw-r--r--lib/crypto/src/crypto.erl396
-rw-r--r--lib/crypto/test/Makefile6
-rw-r--r--lib/crypto/test/crypto_SUITE.erl563
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/Makefile14
-rw-r--r--lib/debugger/doc/src/debugger_chapter.xml2
-rw-r--r--lib/debugger/doc/src/int.xml2
-rw-r--r--lib/debugger/doc/src/make.dep29
-rw-r--r--lib/debugger/doc/src/notes.xml60
-rw-r--r--lib/debugger/priv/Makefile4
-rw-r--r--lib/debugger/src/Makefile10
-rw-r--r--lib/debugger/src/dbg_debugged.erl2
-rw-r--r--lib/debugger/src/dbg_ieval.erl15
-rw-r--r--lib/debugger/src/dbg_ieval.hrl2
-rw-r--r--lib/debugger/src/dbg_iload.erl8
-rw-r--r--lib/debugger/src/dbg_iserver.erl7
-rw-r--r--lib/debugger/src/dbg_ui_break_win.erl40
-rw-r--r--lib/debugger/src/dbg_ui_edit_win.erl16
-rw-r--r--lib/debugger/src/dbg_ui_filedialog_win.erl11
-rw-r--r--lib/debugger/src/dbg_ui_interpret.erl4
-rw-r--r--lib/debugger/src/dbg_ui_mon_win.erl15
-rw-r--r--lib/debugger/src/dbg_ui_settings.erl6
-rw-r--r--lib/debugger/src/dbg_ui_trace_win.erl21
-rw-r--r--lib/debugger/src/dbg_ui_win.erl11
-rw-r--r--lib/debugger/src/dbg_ui_winman.erl7
-rw-r--r--lib/debugger/src/dbg_wx_break_win.erl30
-rw-r--r--lib/debugger/src/dbg_wx_filedialog_win.erl9
-rw-r--r--lib/debugger/src/dbg_wx_settings.erl8
-rw-r--r--[-rwxr-xr-x]lib/debugger/src/dbg_wx_trace_win.erl3
-rw-r--r--[-rwxr-xr-x]lib/debugger/src/dbg_wx_winman.erl0
-rw-r--r--lib/debugger/src/debugger.app.src2
-rw-r--r--lib/debugger/test/Makefile10
-rw-r--r--lib/debugger/test/bs_construct_SUITE.erl12
-rw-r--r--lib/debugger/test/bs_match_misc_SUITE.erl4
-rw-r--r--lib/debugger/test/fun_SUITE.erl52
-rw-r--r--lib/debugger/test/int_break_SUITE.erl5
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl2
-rw-r--r--lib/debugger/test/test_lib.erl2
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/Makefile14
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/book.xml2
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/fascicules.xml0
-rwxr-xr-xlib/dialyzer/doc/src/make.dep20
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/notes.xml103
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/part.xml2
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/part_notes.xml2
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/doc/src/ref_man.xml2
-rw-r--r--[-rwxr-xr-x]lib/dialyzer/info0
-rw-r--r--lib/dialyzer/src/Makefile15
-rw-r--r--lib/dialyzer/src/dialyzer.erl34
-rw-r--r--lib/dialyzer/src/dialyzer.hrl26
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl371
-rw-r--r--lib/dialyzer/src/dialyzer_behaviours.erl362
-rw-r--r--lib/dialyzer/src/dialyzer_callgraph.erl613
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl79
-rw-r--r--lib/dialyzer/src/dialyzer_cl_parse.erl32
-rw-r--r--lib/dialyzer/src/dialyzer_codeserver.erl325
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl227
-rw-r--r--lib/dialyzer/src/dialyzer_coordinator.erl251
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl599
-rw-r--r--lib/dialyzer/src/dialyzer_gui.erl29
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.erl393
-rw-r--r--lib/dialyzer/src/dialyzer_options.erl26
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl158
-rw-r--r--lib/dialyzer/src/dialyzer_races.erl35
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl488
-rw-r--r--lib/dialyzer/src/dialyzer_timing.erl133
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl1091
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl61
-rw-r--r--lib/dialyzer/src/dialyzer_worker.erl189
-rw-r--r--lib/dialyzer/test/Makefile12
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs5
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return2
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args8
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks3
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour9
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old4
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return2
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks2
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec6
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_behaviour.erl11
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_correct.erl59
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_wrong.erl61
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl37
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl33
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl11
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl23
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl13
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl32
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl38
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl26
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl6
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl15
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl13
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl15
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl10
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl17
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl13
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl10
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/vars_in_beh_spec.erl10
-rw-r--r--lib/dialyzer/test/dialyzer_common.erl11
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/crash1
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques2
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/queue1
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl8
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/results/compiler1
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/inets33
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/mnesia4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes31
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_28
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/inf_loop22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/no_local_return3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/port_info_test3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash1
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/collapse_lists/a.erl9
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/collapse_lists/b.erl5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl267
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/deep_lc.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl7
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/maybe_servers.erl31
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/on_load.erl11
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl6
-rw-r--r--lib/dialyzer/test/underspecs_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/underspecs_SUITE_data/results/remote9
-rw-r--r--lib/dialyzer/test/underspecs_SUITE_data/src/remote/remotes1.erl61
-rw-r--r--lib/dialyzer/test/underspecs_SUITE_data/src/remote/some_known_remote.erl5
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_12
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2 (renamed from lib/docbuilder/doc/html/.gitignore)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_33
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl18
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl18
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl16
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/autoconf/vxworks/sed.general1
-rwxr-xr-xlib/diameter/bin/diameterc59
-rw-r--r--lib/diameter/configure.in1
-rw-r--r--lib/diameter/doc/src/Makefile30
-rw-r--r--lib/diameter/doc/src/diameter.xml135
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml32
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml157
-rw-r--r--lib/diameter/doc/src/notes.xml114
-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/code/GNUmakefile35
-rw-r--r--lib/diameter/examples/code/client.erl125
-rw-r--r--lib/diameter/examples/code/client_cb.erl103
-rw-r--r--lib/diameter/examples/code/peer.erl139
-rw-r--r--lib/diameter/examples/code/redirect.erl70
-rw-r--r--lib/diameter/examples/code/redirect_cb.erl63
-rw-r--r--lib/diameter/examples/code/relay.erl92
-rw-r--r--lib/diameter/examples/code/relay_cb.erl69
-rw-r--r--lib/diameter/examples/code/sctp.erl131
-rw-r--r--lib/diameter/examples/code/server.erl88
-rw-r--r--lib/diameter/examples/code/server_cb.erl115
-rw-r--r--lib/diameter/examples/dict/rfc4004_mip.dia280
-rw-r--r--lib/diameter/examples/dict/rfc4005_nas.dia740
-rw-r--r--lib/diameter/examples/dict/rfc4006_cc.dia349
-rw-r--r--lib/diameter/examples/dict/rfc4072_eap.dia150
-rw-r--r--lib/diameter/examples/dict/rfc4590_digest.dia45
-rw-r--r--lib/diameter/examples/dict/rfc4740_sip.dia446
-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.hrl15
-rw-r--r--lib/diameter/include/diameter_gen.hrl8
-rw-r--r--lib/diameter/make/rules.mk.in2
-rw-r--r--lib/diameter/src/.gitignore2
-rw-r--r--lib/diameter/src/Makefile247
-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_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_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_peer_fsm.erl777
-rw-r--r--lib/diameter/src/app/diameter_service.erl2903
-rw-r--r--lib/diameter/src/app/diameter_session.erl172
-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/modules.mk70
-rw-r--r--lib/diameter/src/base/diameter.app.src28
-rw-r--r--lib/diameter/src/base/diameter.appup.src34
-rw-r--r--lib/diameter/src/base/diameter.erl339
-rw-r--r--lib/diameter/src/base/diameter_app.erl (renamed from lib/diameter/src/app/diameter_app.erl)0
-rw-r--r--lib/diameter/src/base/diameter_callback.erl234
-rw-r--r--lib/diameter/src/base/diameter_capx.erl391
-rw-r--r--lib/diameter/src/base/diameter_codec.erl543
-rw-r--r--lib/diameter/src/base/diameter_config.erl691
-rw-r--r--lib/diameter/src/base/diameter_dbg.erl (renamed from lib/diameter/src/app/diameter_dbg.erl)0
-rw-r--r--lib/diameter/src/base/diameter_dict.erl (renamed from lib/diameter/src/app/diameter_dict.erl)0
-rw-r--r--lib/diameter/src/base/diameter_info.erl (renamed from lib/diameter/src/app/diameter_info.erl)0
-rw-r--r--lib/diameter/src/base/diameter_internal.hrl (renamed from lib/diameter/src/app/diameter_internal.hrl)0
-rw-r--r--lib/diameter/src/base/diameter_lib.erl (renamed from lib/diameter/src/app/diameter_lib.erl)0
-rw-r--r--lib/diameter/src/base/diameter_misc_sup.erl (renamed from lib/diameter/src/app/diameter_misc_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_peer.erl (renamed from lib/diameter/src/app/diameter_peer.erl)0
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl881
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm_sup.erl (renamed from lib/diameter/src/app/diameter_peer_fsm_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_reg.erl (renamed from lib/diameter/src/app/diameter_reg.erl)0
-rw-r--r--lib/diameter/src/base/diameter_service.erl2897
-rw-r--r--lib/diameter/src/base/diameter_service_sup.erl (renamed from lib/diameter/src/app/diameter_service_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_session.erl170
-rw-r--r--lib/diameter/src/base/diameter_stats.erl (renamed from lib/diameter/src/app/diameter_stats.erl)0
-rw-r--r--lib/diameter/src/base/diameter_sup.erl (renamed from lib/diameter/src/app/diameter_sup.erl)0
-rw-r--r--lib/diameter/src/base/diameter_sync.erl (renamed from lib/diameter/src/app/diameter_sync.erl)0
-rw-r--r--lib/diameter/src/base/diameter_types.erl596
-rw-r--r--lib/diameter/src/base/diameter_watchdog.erl595
-rw-r--r--lib/diameter/src/base/diameter_watchdog_sup.erl (renamed from lib/diameter/src/app/diameter_watchdog_sup.erl)0
-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.erl402
-rw-r--r--lib/diameter/src/compiler/diameter_dict_parser.yrl324
-rw-r--r--lib/diameter/src/compiler/diameter_dict_scanner.erl276
-rw-r--r--lib/diameter/src/compiler/diameter_dict_util.erl1358
-rw-r--r--lib/diameter/src/compiler/diameter_exprecs.erl275
-rw-r--r--lib/diameter/src/compiler/diameter_forms.hrl7
-rw-r--r--lib/diameter/src/compiler/diameter_make.erl172
-rw-r--r--lib/diameter/src/compiler/diameter_nowarn.erl41
-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/diameter_vsn.hrl22
-rw-r--r--lib/diameter/src/compiler/modules.mk27
-rw-r--r--lib/diameter/src/depend.sed51
-rw-r--r--lib/diameter/src/dict/base_accounting.dia69
-rw-r--r--lib/diameter/src/dict/base_rfc3588.dia461
-rw-r--r--lib/diameter/src/dict/relay.dia23
-rw-r--r--lib/diameter/src/gen/.gitignore2
-rw-r--r--lib/diameter/src/modules.mk104
-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_sctp.erl18
-rw-r--r--lib/diameter/src/transport/modules.mk29
-rw-r--r--lib/diameter/test/Makefile137
-rw-r--r--lib/diameter/test/depend.sed18
-rw-r--r--lib/diameter/test/diameter_app_SUITE.erl56
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl420
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl28
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/avps.dia25
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl76
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/recv.dia51
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/send.dia56
-rw-r--r--lib/diameter/test/diameter_codec_test.erl62
-rw-r--r--lib/diameter/test/diameter_compiler_SUITE.erl489
-rw-r--r--lib/diameter/test/diameter_dict_SUITE.erl15
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl43
-rw-r--r--lib/diameter/test/diameter_gen_sctp_SUITE.erl354
-rw-r--r--lib/diameter/test/diameter_reg_SUITE.erl13
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl61
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl13
-rw-r--r--lib/diameter/test/diameter_sync_SUITE.erl13
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl80
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl37
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl43
-rw-r--r--lib/diameter/test/diameter_util.erl20
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl13
-rw-r--r--lib/diameter/test/modules.mk11
-rw-r--r--lib/diameter/test/release.sed35
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/docbuilder/AUTHORS10
-rw-r--r--lib/docbuilder/Makefile37
-rw-r--r--lib/docbuilder/doc/src/Makefile132
-rw-r--r--lib/docbuilder/doc/src/block_tags.xml431
-rw-r--r--lib/docbuilder/doc/src/book.xml50
-rw-r--r--lib/docbuilder/doc/src/character_entities.xml546
-rw-r--r--lib/docbuilder/doc/src/docb_gen.xml213
-rw-r--r--lib/docbuilder/doc/src/docb_transform.xml224
-rw-r--r--lib/docbuilder/doc/src/docb_xml_check.xml59
-rw-r--r--lib/docbuilder/doc/src/docbuilder_app.xml57
-rw-r--r--lib/docbuilder/doc/src/fasc_dtds.xml115
-rw-r--r--lib/docbuilder/doc/src/gazonk17
-rw-r--r--lib/docbuilder/doc/src/header_tags.xml183
-rw-r--r--lib/docbuilder/doc/src/inline_tags.xml257
-rw-r--r--lib/docbuilder/doc/src/make.dep33
-rw-r--r--lib/docbuilder/doc/src/man.ps750
-rw-r--r--lib/docbuilder/doc/src/notes.xml256
-rw-r--r--lib/docbuilder/doc/src/overview.xml185
-rw-r--r--lib/docbuilder/doc/src/part.xml43
-rw-r--r--lib/docbuilder/doc/src/part_notes.xml37
-rw-r--r--lib/docbuilder/doc/src/ref_man.xml40
-rw-r--r--lib/docbuilder/doc/src/refman_dtds.xml667
-rw-r--r--lib/docbuilder/doc/src/user_guide_dtds.xml181
-rw-r--r--lib/docbuilder/dtd/Makefile91
-rw-r--r--lib/docbuilder/dtd/common.dtd87
-rw-r--r--lib/docbuilder/dtd/common.refs.dtd40
-rw-r--r--lib/docbuilder/dtd/erlref.dtd31
-rw-r--r--lib/docbuilder/dtd/xhtml-lat1.ent196
-rw-r--r--lib/docbuilder/etc/Makefile67
-rw-r--r--lib/docbuilder/info2
-rw-r--r--lib/docbuilder/src/Makefile121
-rw-r--r--lib/docbuilder/src/docb_edoc_xml_cb.erl1154
-rw-r--r--lib/docbuilder/src/docb_gen.erl142
-rw-r--r--lib/docbuilder/src/docb_html.erl393
-rw-r--r--lib/docbuilder/src/docb_html_layout.erl380
-rw-r--r--lib/docbuilder/src/docb_html_ref.erl79
-rw-r--r--lib/docbuilder/src/docb_html_util.erl542
-rw-r--r--lib/docbuilder/src/docb_html_util_iso.erl204
-rw-r--r--lib/docbuilder/src/docb_main.erl657
-rw-r--r--lib/docbuilder/src/docb_pretty_format.erl177
-rw-r--r--lib/docbuilder/src/docb_tr_application2html.erl286
-rw-r--r--lib/docbuilder/src/docb_tr_appref2html.erl48
-rw-r--r--lib/docbuilder/src/docb_tr_chapter2html.erl59
-rw-r--r--lib/docbuilder/src/docb_tr_cite2html.erl134
-rw-r--r--lib/docbuilder/src/docb_tr_comref2html.erl46
-rw-r--r--lib/docbuilder/src/docb_tr_cref2html.erl61
-rw-r--r--lib/docbuilder/src/docb_tr_erlref2html.erl46
-rw-r--r--lib/docbuilder/src/docb_tr_fileref2html.erl46
-rw-r--r--lib/docbuilder/src/docb_tr_first2html.erl46
-rw-r--r--lib/docbuilder/src/docb_tr_index2html.erl195
-rw-r--r--lib/docbuilder/src/docb_tr_part2html.erl237
-rw-r--r--lib/docbuilder/src/docb_tr_refs2kwic.erl156
-rw-r--r--lib/docbuilder/src/docb_tr_report2html.erl70
-rw-r--r--lib/docbuilder/src/docb_tr_term2html.erl124
-rw-r--r--lib/docbuilder/src/docb_transform.erl163
-rw-r--r--lib/docbuilder/src/docb_util.erl237
-rw-r--r--lib/docbuilder/src/docb_util.hrl34
-rw-r--r--lib/docbuilder/src/docb_xmerl_tree_cb.erl343
-rw-r--r--lib/docbuilder/src/docb_xmerl_xml_cb.erl88
-rw-r--r--lib/docbuilder/src/docb_xml_check.erl45
-rw-r--r--lib/docbuilder/src/docbuilder.app.src37
-rw-r--r--lib/docbuilder/src/docbuilder.appup.src1
-rw-r--r--lib/docbuilder/test/Makefile80
-rw-r--r--lib/docbuilder/test/docb.cover2
-rw-r--r--lib/docbuilder/test/docb_SUITE.erl50
-rwxr-xr-xlib/docbuilder/test/docb_SUITE_data/cdata_problem.xml22
-rw-r--r--lib/docbuilder/vsn.mk1
-rwxr-xr-xlib/docbuilder/xsd/application.xsd31
-rwxr-xr-xlib/docbuilder/xsd/appref.xsd27
-rwxr-xr-xlib/docbuilder/xsd/book.xsd292
-rwxr-xr-xlib/docbuilder/xsd/chapter.xsd45
-rwxr-xr-xlib/docbuilder/xsd/common.entities.xsd2
-rwxr-xr-xlib/docbuilder/xsd/common.header.xsd29
-rwxr-xr-xlib/docbuilder/xsd/common.image.xsd18
-rwxr-xr-xlib/docbuilder/xsd/common.refs.xsd102
-rwxr-xr-xlib/docbuilder/xsd/common.table.xsd42
-rwxr-xr-xlib/docbuilder/xsd/common.xsd212
-rwxr-xr-xlib/docbuilder/xsd/comref.xsd26
-rwxr-xr-xlib/docbuilder/xsd/cref.xsd35
-rwxr-xr-xlib/docbuilder/xsd/erlref.xsd26
-rwxr-xr-xlib/docbuilder/xsd/fascicules.xsd25
-rwxr-xr-xlib/docbuilder/xsd/fileref.xsd26
-rwxr-xr-xlib/docbuilder/xsd/part.xsd31
-rw-r--r--lib/edoc/doc/Makefile9
-rw-r--r--lib/edoc/doc/src/Makefile14
-rw-r--r--lib/edoc/doc/src/make.dep21
-rw-r--r--lib/edoc/doc/src/notes.xml15
-rw-r--r--lib/edoc/include/Makefile4
-rw-r--r--lib/edoc/priv/Makefile6
-rw-r--r--lib/edoc/src/Makefile8
-rw-r--r--lib/edoc/src/edoc_data.erl5
-rw-r--r--lib/edoc/src/edoc_lib.erl4
-rw-r--r--lib/edoc/test/Makefile10
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/eldap/.gitignore4
-rw-r--r--lib/eldap/AUTHORS7
-rw-r--r--lib/eldap/LICENSE21
-rw-r--r--lib/eldap/Makefile39
-rw-r--r--lib/eldap/README33
-rw-r--r--lib/eldap/asn1/ELDAPv3.asn1278
-rw-r--r--lib/eldap/doc/html/.gitignore (renamed from lib/docbuilder/doc/man3/.gitignore)0
-rw-r--r--lib/eldap/doc/man3/.gitignore (renamed from lib/docbuilder/doc/man6/.gitignore)0
-rw-r--r--lib/eldap/doc/pdf/.gitignore (renamed from lib/docbuilder/doc/pdf/.gitignore)0
-rw-r--r--lib/eldap/doc/src/Makefile115
-rw-r--r--lib/eldap/doc/src/book.xml47
-rw-r--r--lib/eldap/doc/src/eldap.xml342
-rw-r--r--lib/eldap/doc/src/fascicules.xml18
-rw-r--r--lib/eldap/doc/src/note.gif (renamed from lib/docbuilder/etc/note.gif)bin1539 -> 1539 bytes
-rw-r--r--lib/eldap/doc/src/notes.xml38
-rw-r--r--lib/eldap/doc/src/ref_man.xml37
-rw-r--r--lib/eldap/doc/src/release_notes.xml37
-rw-r--r--lib/eldap/doc/src/usersguide.xml38
-rw-r--r--lib/eldap/doc/src/warning.gif (renamed from lib/docbuilder/etc/warning.gif)bin1498 -> 1498 bytes
-rw-r--r--lib/eldap/ebin/.gitignore (renamed from lib/docbuilder/ebin/.gitignore)0
-rw-r--r--lib/eldap/include/eldap.hrl33
-rw-r--r--lib/eldap/info2
-rw-r--r--lib/eldap/src/Makefile110
-rw-r--r--lib/eldap/src/eldap.app.src8
-rw-r--r--lib/eldap/src/eldap.appup.src6
-rw-r--r--lib/eldap/src/eldap.erl1114
-rw-r--r--lib/eldap/test/Makefile83
-rw-r--r--lib/eldap/test/eldap.spec1
-rw-r--r--lib/eldap/test/eldap_basic_SUITE.erl222
-rw-r--r--lib/eldap/test/ldap_server/slapd.conf14
-rw-r--r--lib/eldap/vsn.mk1
-rw-r--r--lib/erl_docgen/Makefile5
-rw-r--r--lib/erl_docgen/doc/html/.gitignore0
-rw-r--r--lib/erl_docgen/doc/man6/.gitignore0
-rw-r--r--lib/erl_docgen/doc/pdf/.gitignore0
-rw-r--r--lib/erl_docgen/doc/src/Makefile136
-rw-r--r--lib/erl_docgen/doc/src/block_tags.xml431
-rw-r--r--lib/erl_docgen/doc/src/book.xml15
-rw-r--r--lib/erl_docgen/doc/src/character_entities.xml546
-rw-r--r--lib/erl_docgen/doc/src/convert.howto13
-rw-r--r--lib/erl_docgen/doc/src/doc-build.xml188
-rw-r--r--lib/erl_docgen/doc/src/docgen_xml_check.xml59
-rw-r--r--lib/erl_docgen/doc/src/erl_docgen.txt6
-rw-r--r--lib/erl_docgen/doc/src/erl_docgen_app.xml64
-rw-r--r--lib/erl_docgen/doc/src/example.txt17
-rw-r--r--lib/erl_docgen/doc/src/fasc_dtds.xml115
-rw-r--r--lib/erl_docgen/doc/src/fascicules.xml (renamed from lib/docbuilder/doc/src/fascicules.xml)0
-rw-r--r--lib/erl_docgen/doc/src/header_tags.xml181
-rw-r--r--lib/erl_docgen/doc/src/inline_tags.xml214
-rw-r--r--lib/erl_docgen/doc/src/man.gif (renamed from lib/docbuilder/doc/src/man.gif)bin6048 -> 6048 bytes
-rw-r--r--lib/erl_docgen/doc/src/notes.xml104
-rw-r--r--lib/erl_docgen/doc/src/overview.xml105
-rw-r--r--lib/erl_docgen/doc/src/part.xml43
-rw-r--r--lib/erl_docgen/doc/src/ref_man.xml36
-rw-r--r--lib/erl_docgen/doc/src/refman_dtds.xml667
-rw-r--r--lib/erl_docgen/doc/src/user_guide_dtds.xml181
-rw-r--r--lib/erl_docgen/info2
-rw-r--r--lib/erl_docgen/priv/Makefile2
-rw-r--r--lib/erl_docgen/priv/bin/Makefile4
-rw-r--r--lib/erl_docgen/priv/bin/specs_gen.escript4
-rwxr-xr-xlib/erl_docgen/priv/bin/xml_from_edoc.escript6
-rw-r--r--lib/erl_docgen/priv/css/Makefile8
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css29
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/Makefile99
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/application.dtd29
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/appref.dtd33
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/book.dtd73
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/bookinsidecover.dtd36
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/chapter.dtd36
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/cites.dtd35
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/common.entities.dtd24
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/common.header.dtd42
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/common.image.dtd21
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/common.table.dtd25
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/comref.dtd31
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/cref.dtd34
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/fascicules.dtd35
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/fileref.dtd31
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/part.dtd29
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/report.dtd138
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/terms.dtd36
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/xhtml1-frameset.dtd1235
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/xhtml1-strict.dtd978
-rw-r--r--lib/erl_docgen/priv/docbuilder_dtd/xhtml1-transitional.dtd1201
-rw-r--r--lib/erl_docgen/priv/dtd/Makefile101
-rw-r--r--lib/erl_docgen/priv/dtd/application.dtd (renamed from lib/docbuilder/dtd/application.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/appref.dtd (renamed from lib/docbuilder/dtd/appref.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/book.dtd (renamed from lib/docbuilder/dtd/book.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/bookinsidecover.dtd (renamed from lib/docbuilder/dtd/bookinsidecover.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/chapter.dtd (renamed from lib/docbuilder/dtd/chapter.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/cites.dtd (renamed from lib/docbuilder/dtd/cites.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/common.dtd (renamed from lib/erl_docgen/priv/docbuilder_dtd/common.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/common.entities.dtd (renamed from lib/docbuilder/dtd/common.entities.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/common.header.dtd (renamed from lib/docbuilder/dtd/common.header.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/common.image.dtd (renamed from lib/docbuilder/dtd/common.image.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/common.refs.dtd (renamed from lib/erl_docgen/priv/docbuilder_dtd/common.refs.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/common.table.dtd (renamed from lib/docbuilder/dtd/common.table.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/comref.dtd (renamed from lib/docbuilder/dtd/comref.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/cref.dtd (renamed from lib/docbuilder/dtd/cref.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/erlref.dtd (renamed from lib/erl_docgen/priv/docbuilder_dtd/erlref.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/fascicules.dtd (renamed from lib/docbuilder/dtd/fascicules.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/fileref.dtd (renamed from lib/docbuilder/dtd/fileref.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/part.dtd (renamed from lib/docbuilder/dtd/part.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/report.dtd (renamed from lib/docbuilder/dtd/report.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/terms.dtd (renamed from lib/docbuilder/dtd/terms.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/xhtml-special.ent (renamed from lib/docbuilder/dtd/xhtml-special.ent)0
-rw-r--r--lib/erl_docgen/priv/dtd/xhtml-symbol.ent (renamed from lib/docbuilder/dtd/xhtml-symbol.ent)0
-rw-r--r--lib/erl_docgen/priv/dtd/xhtml1-frameset.dtd (renamed from lib/docbuilder/dtd/xhtml1-frameset.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/xhtml1-strict.dtd (renamed from lib/docbuilder/dtd/xhtml1-strict.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd/xhtml1-transitional.dtd (renamed from lib/docbuilder/dtd/xhtml1-transitional.dtd)0
-rw-r--r--lib/erl_docgen/priv/dtd_html_entities/Makefile4
-rw-r--r--lib/erl_docgen/priv/dtd_man_entities/Makefile4
-rw-r--r--lib/erl_docgen/priv/images/Makefile8
-rw-r--r--lib/erl_docgen/priv/js/flipmenu/Makefile8
-rw-r--r--lib/erl_docgen/priv/xsl/Makefile4
-rw-r--r--lib/erl_docgen/priv/xsl/db_eix.xsl10
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl177
-rw-r--r--lib/erl_docgen/priv/xsl/db_man.xsl36
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf.xsl24
-rw-r--r--lib/erl_docgen/src/Makefile14
-rw-r--r--lib/erl_docgen/src/docgen_edoc_xml_cb.erl1171
-rw-r--r--lib/erl_docgen/src/docgen_otp_specs.erl713
-rw-r--r--lib/erl_docgen/src/docgen_xmerl_xml_cb.erl88
-rw-r--r--lib/erl_docgen/src/docgen_xml_check.erl45
-rw-r--r--lib/erl_docgen/src/erl_docgen.app.src4
-rw-r--r--lib/erl_docgen/src/otp_specs.erl713
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--[l---------]lib/erl_interface/aclocal.m41873
-rw-r--r--lib/erl_interface/configure.in56
-rw-r--r--lib/erl_interface/doc/src/Makefile18
-rw-r--r--lib/erl_interface/doc/src/make.dep24
-rw-r--r--lib/erl_interface/doc/src/notes.xml53
-rw-r--r--lib/erl_interface/src/Makefile.in56
-rwxr-xr-x[l---------]lib/erl_interface/src/auxdir/config.guess1520
-rwxr-xr-x[l---------]lib/erl_interface/src/auxdir/config.sub1631
-rwxr-xr-x[l---------]lib/erl_interface/src/auxdir/install-sh520
-rw-r--r--lib/erl_interface/src/legacy/global_names.c4
-rw-r--r--lib/erl_interface/src/misc/ei_format.c5
-rw-r--r--lib/erl_interface/test/Makefile8
-rw-r--r--lib/erl_interface/test/all_SUITE_data/Makefile.src4
-rw-r--r--lib/erl_interface/test/all_SUITE_data/gccifier.c16
-rw-r--r--lib/erl_interface/test/all_SUITE_data/init_tc.erl25
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl20
-rw-r--r--lib/erl_interface/test/erl_match_SUITE.erl30
-rw-r--r--lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c27
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/Makefile14
-rw-r--r--lib/et/doc/src/et_intro.xml4
-rw-r--r--lib/et/doc/src/notes.xml20
-rw-r--r--lib/et/examples/Makefile4
-rw-r--r--lib/et/src/Makefile16
-rw-r--r--lib/et/src/et_gs_contents_viewer.erl13
-rw-r--r--lib/et/src/et_gs_viewer.erl19
-rw-r--r--lib/et/src/et_wx_contents_viewer.erl23
-rw-r--r--lib/et/test/Makefile12
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/eunit/doc/overview.edoc8
-rw-r--r--lib/eunit/doc/src/Makefile14
-rw-r--r--lib/eunit/doc/src/make.dep19
-rw-r--r--lib/eunit/doc/src/notes.xml18
-rw-r--r--lib/eunit/examples/Makefile4
-rw-r--r--lib/eunit/include/eunit.hrl13
-rw-r--r--lib/eunit/src/Makefile24
-rw-r--r--lib/eunit/src/eunit.app.src1
-rw-r--r--lib/eunit/src/eunit.erl7
-rw-r--r--lib/eunit/src/eunit_data.erl39
-rw-r--r--lib/eunit/src/eunit_lib.erl94
-rw-r--r--lib/eunit/src/eunit_surefire.erl32
-rw-r--r--lib/eunit/src/eunit_test.erl26
-rw-r--r--lib/eunit/src/eunit_tty.erl59
-rw-r--r--lib/eunit/test/Makefile4
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/gs/contribs/bonk/Makefile16
-rw-r--r--lib/gs/contribs/bonk/bonk.erl8
-rw-r--r--lib/gs/contribs/cols/Makefile12
-rw-r--r--lib/gs/contribs/cols/cols.erl8
-rw-r--r--lib/gs/contribs/cols/highscore.erl9
-rw-r--r--lib/gs/contribs/mandel/Makefile12
-rw-r--r--lib/gs/contribs/mandel/mandel.erl7
-rw-r--r--lib/gs/contribs/othello/Makefile12
-rw-r--r--lib/gs/contribs/othello/othello_board.erl8
-rw-r--r--lib/gs/doc/src/Makefile14
-rw-r--r--lib/gs/doc/src/gs.xml6
-rw-r--r--lib/gs/doc/src/make.dep58
-rw-r--r--lib/gs/doc/src/notes.xml48
-rw-r--r--lib/gs/examples/Makefile8
-rw-r--r--lib/gs/examples/ball.erl8
-rw-r--r--lib/gs/examples/browser.erl10
-rw-r--r--lib/gs/examples/calc.erl7
-rw-r--r--lib/gs/examples/calc2.erl8
-rw-r--r--lib/gs/examples/color_demo.erl7
-rw-r--r--lib/gs/examples/color_demo2.erl6
-rw-r--r--lib/gs/examples/distrib_draw.erl7
-rw-r--r--lib/gs/examples/entry_demo.erl8
-rw-r--r--lib/gs/examples/event_test.erl5
-rw-r--r--lib/gs/examples/file_dialog.erl7
-rw-r--r--lib/gs/examples/focus_demo.erl7
-rw-r--r--lib/gs/examples/frac.erl5
-rw-r--r--lib/gs/examples/line_demo.erl8
-rw-r--r--lib/gs/examples/man.erl11
-rw-r--r--lib/gs/examples/menu_demo.erl8
-rw-r--r--lib/gs/examples/rubber.erl10
-rw-r--r--lib/gs/src/Makefile14
-rw-r--r--lib/gs/src/gs.erl10
-rw-r--r--lib/gs/src/gs_frontend.erl4
-rw-r--r--lib/gs/src/gs_make.erl3
-rw-r--r--lib/gs/src/gse.erl64
-rw-r--r--lib/gs/src/gstk.erl4
-rw-r--r--lib/gs/src/gstk_arc.erl3
-rw-r--r--lib/gs/src/gstk_canvas.erl4
-rw-r--r--lib/gs/src/gstk_editor.erl9
-rw-r--r--lib/gs/src/gstk_entry.erl3
-rw-r--r--lib/gs/src/gstk_generic.erl7
-rw-r--r--lib/gs/src/gstk_grid.erl3
-rw-r--r--lib/gs/src/gstk_gridline.erl4
-rw-r--r--lib/gs/src/gstk_image.erl7
-rw-r--r--lib/gs/src/gstk_menu.erl3
-rw-r--r--lib/gs/src/gstk_menuitem.erl3
-rw-r--r--lib/gs/src/gstk_port_handler.erl3
-rw-r--r--lib/gs/src/gstk_rectangle.erl3
-rw-r--r--lib/gs/src/gstk_window.erl3
-rw-r--r--lib/gs/src/tcl2erl.erl3
-rw-r--r--lib/gs/src/tool_file_dialog.erl12
-rw-r--r--lib/gs/src/tool_utils.erl10
-rw-r--r--lib/gs/tcl/Makefile.in6
-rw-r--r--lib/gs/vsn.mk2
-rw-r--r--lib/hipe/Makefile23
-rw-r--r--lib/hipe/amd64/Makefile9
-rw-r--r--lib/hipe/arm/Makefile9
-rw-r--r--lib/hipe/boot_ebin/.gitignore0
-rw-r--r--lib/hipe/cerl/Makefile15
-rw-r--r--lib/hipe/cerl/cerl_hipe_primops.hrl3
-rw-r--r--lib/hipe/cerl/cerl_hipeify.erl3
-rw-r--r--lib/hipe/cerl/cerl_hybrid_transform.erl153
-rw-r--r--lib/hipe/cerl/cerl_messagean.erl3
-rw-r--r--lib/hipe/cerl/cerl_to_icode.erl5
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl118
-rw-r--r--lib/hipe/cerl/erl_types.erl258
-rw-r--r--lib/hipe/doc/Makefile5
-rw-r--r--lib/hipe/doc/src/Makefile15
-rw-r--r--lib/hipe/doc/src/make.dep13
-rw-r--r--lib/hipe/doc/src/notes.xml123
-rw-r--r--lib/hipe/flow/Makefile15
-rw-r--r--lib/hipe/flow/cfg.hrl2
-rw-r--r--lib/hipe/icode/Makefile15
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl104
-rw-r--r--lib/hipe/icode/hipe_icode.hrl6
-rw-r--r--lib/hipe/icode/hipe_icode_coordinator.erl11
-rw-r--r--lib/hipe/icode/hipe_icode_inline_bifs.erl5
-rw-r--r--lib/hipe/icode/hipe_icode_mulret.erl6
-rw-r--r--[-rwxr-xr-x]lib/hipe/icode/hipe_icode_pp.erl2
-rw-r--r--[-rwxr-xr-x]lib/hipe/icode/hipe_icode_ssa.erl2
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl14
-rw-r--r--lib/hipe/main/Makefile15
-rw-r--r--lib/hipe/main/hipe.app.src4
-rw-r--r--lib/hipe/main/hipe.erl140
-rw-r--r--lib/hipe/misc/Makefile8
-rw-r--r--lib/hipe/native.mk4
-rw-r--r--lib/hipe/opt/Makefile11
-rw-r--r--lib/hipe/opt/hipe_schedule.erl4
-rw-r--r--lib/hipe/ppc/Makefile9
-rw-r--r--lib/hipe/regalloc/Makefile9
-rw-r--r--lib/hipe/rtl/Makefile87
-rw-r--r--lib/hipe/rtl/hipe_rtl.erl5
-rw-r--r--lib/hipe/rtl/hipe_rtl_arch.erl27
-rw-r--r--lib/hipe/rtl/hipe_rtl_lcm.erl21
-rw-r--r--lib/hipe/sparc/Makefile9
-rw-r--r--lib/hipe/sparc/hipe_rtl_to_sparc.erl36
-rw-r--r--lib/hipe/tools/Makefile8
-rw-r--r--lib/hipe/tools/hipe_ceach.erl74
-rw-r--r--lib/hipe/tools/hipe_profile.erl4
-rw-r--r--lib/hipe/tools/hipe_tool.erl14
-rw-r--r--lib/hipe/util/Makefile13
-rw-r--r--[-rwxr-xr-x]lib/hipe/util/hipe_dot.erl2
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/hipe/x86/Makefile9
-rw-r--r--lib/ic/c_src/Makefile.in14
-rw-r--r--lib/ic/doc/src/Makefile123
-rw-r--r--lib/ic/doc/src/ic_clib.xml14
-rw-r--r--lib/ic/doc/src/make.dep24
-rw-r--r--lib/ic/doc/src/notes.xml50
-rw-r--r--lib/ic/examples/pre_post_condition/Makefile8
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Makefile8
-rw-r--r--lib/ic/src/Makefile34
-rw-r--r--lib/ic/src/ic.erl2
-rw-r--r--lib/ic/src/ic_noc.erl21
-rw-r--r--lib/ic/src/ic_pp.erl39
-rw-r--r--lib/ic/src/ic_pragma.erl6
-rw-r--r--lib/ic/test/Makefile50
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src23
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src23
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src26
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src19
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src19
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE.erl2
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src19
-rw-r--r--lib/ic/vsn.mk2
-rw-r--r--lib/inets/Makefile29
-rw-r--r--lib/inets/doc/archive/rfc3986.txt3419
-rw-r--r--lib/inets/doc/src/Makefile113
-rw-r--r--lib/inets/doc/src/book.xml4
-rw-r--r--lib/inets/doc/src/fascicules.xml2
-rw-r--r--lib/inets/doc/src/ftp.xml21
-rw-r--r--lib/inets/doc/src/ftp_client.xml4
-rw-r--r--lib/inets/doc/src/http_uri.xml160
-rw-r--r--lib/inets/doc/src/httpc.xml209
-rw-r--r--lib/inets/doc/src/httpd.xml545
-rw-r--r--lib/inets/doc/src/httpd_conf.xml58
-rw-r--r--lib/inets/doc/src/httpd_socket.xml29
-rw-r--r--lib/inets/doc/src/httpd_util.xml4
-rw-r--r--lib/inets/doc/src/inets_services.xml4
-rw-r--r--lib/inets/doc/src/make.dep47
-rw-r--r--lib/inets/doc/src/mod_alias.xml92
-rw-r--r--lib/inets/doc/src/mod_auth.xml135
-rw-r--r--lib/inets/doc/src/notes.xml341
-rw-r--r--lib/inets/doc/src/notes_history.xml4
-rw-r--r--lib/inets/doc/src/part.xml4
-rw-r--r--lib/inets/doc/src/part_notes.xml4
-rw-r--r--lib/inets/doc/src/part_notes_history.xml4
-rw-r--r--lib/inets/doc/src/ref_man.xml9
-rw-r--r--lib/inets/doc/src/tftp.xml191
-rw-r--r--lib/inets/examples/httpd_load_test/Makefile2
-rw-r--r--lib/inets/examples/server_root/Makefile46
-rw-r--r--lib/inets/priv/Makefile4
-rw-r--r--lib/inets/priv/plt/.gitignore2
-rw-r--r--lib/inets/src/ftp/Makefile10
-rw-r--r--lib/inets/src/ftp/ftp.erl160
-rw-r--r--lib/inets/src/http_client/Makefile12
-rw-r--r--lib/inets/src/http_client/httpc.erl166
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl188
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl77
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl372
-rw-r--r--lib/inets/src/http_client/httpc_response.erl25
-rw-r--r--lib/inets/src/http_lib/Makefile10
-rw-r--r--lib/inets/src/http_lib/http_uri.erl172
-rw-r--r--lib/inets/src/http_lib/http_util.erl4
-rw-r--r--lib/inets/src/http_server/Makefile14
-rw-r--r--lib/inets/src/http_server/httpd_acceptor.erl20
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl110
-rw-r--r--lib/inets/src/http_server/httpd_file.erl6
-rw-r--r--lib/inets/src/http_server/httpd_log.erl126
-rw-r--r--lib/inets/src/http_server/httpd_request.erl6
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl31
-rw-r--r--lib/inets/src/http_server/httpd_response.erl44
-rw-r--r--lib/inets/src/http_server/httpd_script_env.erl59
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl19
-rw-r--r--lib/inets/src/http_server/httpd_util.erl53
-rw-r--r--lib/inets/src/http_server/mod_get.erl18
-rw-r--r--lib/inets/src/http_server/mod_log.erl12
-rw-r--r--lib/inets/src/http_server/mod_responsecontrol.erl55
-rw-r--r--lib/inets/src/inets_app/Makefile22
-rw-r--r--lib/inets/src/inets_app/inets.app.src7
-rw-r--r--lib/inets/src/inets_app/inets.appup.src78
-rw-r--r--lib/inets/src/inets_app/inets.erl269
-rw-r--r--lib/inets/src/inets_app/inets.mk4
-rw-r--r--lib/inets/src/inets_app/inets_app.erl4
-rw-r--r--lib/inets/src/inets_app/inets_internal.hrl6
-rw-r--r--lib/inets/src/inets_app/inets_service.erl4
-rw-r--r--lib/inets/src/inets_app/inets_sup.erl12
-rw-r--r--lib/inets/src/inets_app/inets_trace.erl357
-rw-r--r--lib/inets/src/tftp/Makefile23
-rw-r--r--lib/inets/src/tftp/tftp.erl2
-rw-r--r--lib/inets/test/Makefile16
-rw-r--r--lib/inets/test/ftp_suite_lib.erl82
-rw-r--r--lib/inets/test/ftp_windows_2003_server_test.erl22
-rw-r--r--lib/inets/test/httpc_SUITE.erl1009
-rw-r--r--lib/inets/test/httpd_1_1.erl108
-rw-r--r--lib/inets/test/httpd_SUITE.erl233
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl163
-rw-r--r--lib/inets/test/httpd_mod.erl268
-rw-r--r--lib/inets/test/httpd_test_lib.erl106
-rw-r--r--lib/inets/test/httpd_time_test.erl75
-rw-r--r--lib/inets/test/inets_app_test.erl16
-rw-r--r--lib/inets/test/inets_test_lib.erl314
-rw-r--r--lib/inets/test/inets_test_lib.hrl14
-rw-r--r--lib/inets/vsn.mk4
-rw-r--r--lib/inviso/doc/src/Makefile14
-rw-r--r--lib/inviso/doc/src/inviso.xml6
-rw-r--r--lib/inviso/doc/src/inviso_chapter.xml8
-rw-r--r--lib/inviso/doc/src/make.dep27
-rw-r--r--lib/inviso/doc/src/notes.xml23
-rw-r--r--lib/inviso/src/Makefile12
-rw-r--r--lib/inviso/src/inviso.erl1
-rw-r--r--lib/inviso/src/inviso_tool_lib.erl8
-rw-r--r--lib/inviso/test/Makefile8
-rw-r--r--lib/inviso/test/inviso_tool_SUITE.erl9
-rw-r--r--lib/inviso/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/Makefile18
-rw-r--r--lib/jinterface/doc/src/make.dep20
-rw-r--r--lib/jinterface/doc/src/notes.xml54
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile14
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java24
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java6
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java6
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java57
-rw-r--r--lib/jinterface/test/Makefile6
-rw-r--r--lib/jinterface/test/nc_SUITE.erl7
-rw-r--r--lib/jinterface/test/nc_SUITE_data/echo_server.java8
-rw-r--r--lib/jinterface/vsn.mk2
-rw-r--r--lib/kernel/doc/src/Makefile22
-rw-r--r--lib/kernel/doc/src/app.xml4
-rw-r--r--lib/kernel/doc/src/code.xml6
-rw-r--r--lib/kernel/doc/src/error_logger.xml4
-rw-r--r--lib/kernel/doc/src/file.xml114
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml95
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml63
-rw-r--r--lib/kernel/doc/src/gen_udp.xml57
-rw-r--r--lib/kernel/doc/src/heart.xml2
-rw-r--r--lib/kernel/doc/src/inet.xml103
-rw-r--r--lib/kernel/doc/src/kernel_app.xml13
-rw-r--r--lib/kernel/doc/src/make.dep28
-rw-r--r--lib/kernel/doc/src/net_kernel.xml4
-rw-r--r--lib/kernel/doc/src/notes.xml362
-rw-r--r--lib/kernel/doc/src/os.xml15
-rw-r--r--lib/kernel/doc/src/packages.xml6
-rw-r--r--lib/kernel/examples/Makefile4
-rw-r--r--lib/kernel/examples/uds_dist/c_src/uds_drv.c4
-rw-r--r--lib/kernel/include/dist.hrl2
-rw-r--r--lib/kernel/include/dist_util.hrl2
-rw-r--r--lib/kernel/include/file.hrl11
-rw-r--r--lib/kernel/include/net_address.hrl2
-rw-r--r--lib/kernel/src/Makefile16
-rw-r--r--lib/kernel/src/application.erl2
-rw-r--r--lib/kernel/src/application_controller.erl19
-rw-r--r--lib/kernel/src/auth.erl14
-rw-r--r--lib/kernel/src/code.erl42
-rw-r--r--lib/kernel/src/code_server.erl49
-rw-r--r--lib/kernel/src/disk_log.erl59
-rw-r--r--lib/kernel/src/disk_log.hrl4
-rw-r--r--lib/kernel/src/erts_debug.erl22
-rw-r--r--lib/kernel/src/file.erl204
-rw-r--r--lib/kernel/src/file_io_server.erl5
-rw-r--r--lib/kernel/src/file_server.erl11
-rw-r--r--lib/kernel/src/gen_sctp.erl43
-rw-r--r--lib/kernel/src/gen_tcp.erl14
-rw-r--r--lib/kernel/src/gen_udp.erl5
-rw-r--r--lib/kernel/src/global.erl35
-rw-r--r--lib/kernel/src/heart.erl4
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl18
-rw-r--r--lib/kernel/src/inet.erl112
-rw-r--r--lib/kernel/src/inet6_sctp.erl17
-rw-r--r--lib/kernel/src/inet6_tcp.erl8
-rw-r--r--lib/kernel/src/inet6_udp.erl6
-rw-r--r--lib/kernel/src/inet_int.hrl18
-rw-r--r--lib/kernel/src/inet_sctp.erl21
-rw-r--r--lib/kernel/src/inet_tcp.erl8
-rw-r--r--lib/kernel/src/inet_udp.erl4
-rw-r--r--lib/kernel/src/kernel.appup.src28
-rw-r--r--lib/kernel/src/rpc.erl2
-rw-r--r--lib/kernel/src/user_drv.erl10
-rw-r--r--lib/kernel/src/user_sup.erl8
-rw-r--r--lib/kernel/test/Makefile15
-rw-r--r--lib/kernel/test/application_SUITE.erl30
-rw-r--r--lib/kernel/test/application_SUITE_data/Makefile.src5
-rw-r--r--lib/kernel/test/application_SUITE_data/deadlock/deadlock.app8
-rw-r--r--lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl69
-rw-r--r--lib/kernel/test/bif_SUITE.erl94
-rw-r--r--lib/kernel/test/code_SUITE.erl63
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl24
-rw-r--r--lib/kernel/test/erl_boot_server_SUITE.erl2
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl18
-rw-r--r--lib/kernel/test/file_SUITE.erl171
-rw-r--r--lib/kernel/test/file_name_SUITE.erl52
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl1148
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl10
-rw-r--r--lib/kernel/test/gen_tcp_echo_SUITE.erl11
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl159
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl69
-rw-r--r--lib/kernel/test/global_SUITE.erl17
-rw-r--r--lib/kernel/test/inet_SUITE.erl8
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl13
-rwxr-xr-xlib/kernel/test/inet_res_SUITE_data/run-named36
-rw-r--r--lib/kernel/test/init_SUITE.erl4
-rw-r--r--lib/kernel/test/interactive_shell_SUITE.erl6
-rw-r--r--lib/kernel/test/kernel_SUITE.erl64
-rw-r--r--lib/kernel/test/os_SUITE.erl18
-rw-r--r--lib/kernel/test/pg2_SUITE.erl1
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl217
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl407
-rw-r--r--lib/kernel/test/seq_trace_SUITE_data/echo_drv.c21
-rw-r--r--lib/kernel/test/wrap_log_reader_SUITE.erl2
-rw-r--r--lib/kernel/test/zlib_SUITE.erl21
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/.gitignore3
-rw-r--r--lib/megaco/Makefile54
-rw-r--r--lib/megaco/configure.in5
-rw-r--r--lib/megaco/doc/src/Makefile136
-rw-r--r--lib/megaco/doc/src/make.dep59
-rw-r--r--lib/megaco/doc/src/megaco_run.xml4
-rw-r--r--lib/megaco/doc/src/notes.xml222
-rw-r--r--lib/megaco/examples/meas/Makefile132
-rw-r--r--lib/megaco/examples/meas/Makefile.in166
-rw-r--r--lib/megaco/examples/meas/meas.sh.skel41
-rw-r--r--lib/megaco/examples/meas/meas.sh.skel.src42
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone1.erl3
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone2.erl5
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone_lib.erl18
-rw-r--r--lib/megaco/examples/meas/modules.mk8
-rw-r--r--lib/megaco/examples/meas/mstone1.sh.skel239
-rw-r--r--lib/megaco/examples/meas/mstone1.sh.skel.src262
-rw-r--r--lib/megaco/examples/simple/Makefile6
-rw-r--r--lib/megaco/include/megaco_message_prev3a.hrl2
-rw-r--r--lib/megaco/include/megaco_message_prev3b.hrl2
-rw-r--r--lib/megaco/include/megaco_message_prev3c.hrl2
-rw-r--r--lib/megaco/include/megaco_message_v1.hrl2
-rw-r--r--lib/megaco/include/megaco_message_v2.hrl2
-rw-r--r--lib/megaco/include/megaco_message_v3.hrl2
-rw-r--r--lib/megaco/priv/plt/.gitignore2
-rw-r--r--lib/megaco/src/app/Makefile16
-rw-r--r--lib/megaco/src/app/megaco.appup.src54
-rw-r--r--lib/megaco/src/binary/Makefile10
-rw-r--r--lib/megaco/src/binary/depend.mk18
-rw-r--r--lib/megaco/src/engine/Makefile27
-rw-r--r--lib/megaco/src/engine/megaco_digit_map.erl6
-rw-r--r--lib/megaco/src/engine/modules.mk1
-rw-r--r--lib/megaco/src/flex/Makefile.in20
-rw-r--r--lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src39
-rw-r--r--lib/megaco/src/tcp/Makefile10
-rw-r--r--lib/megaco/src/text/Makefile10
-rw-r--r--lib/megaco/src/udp/Makefile10
-rw-r--r--lib/megaco/test/Makefile8
-rw-r--r--lib/megaco/test/megaco_codec_v1_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_v2_test.erl6
-rw-r--r--lib/megaco/test/megaco_mess_test.erl127
-rw-r--r--lib/megaco/test/megaco_profile.erl343
-rw-r--r--lib/megaco/test/megaco_test_lib.erl10
-rw-r--r--lib/megaco/vsn.mk4
-rw-r--r--lib/mnesia/doc/src/Makefile102
-rw-r--r--lib/mnesia/doc/src/company.erl45
-rw-r--r--lib/mnesia/doc/src/company_o.erl20
-rw-r--r--lib/mnesia/doc/src/make.dep46
-rw-r--r--lib/mnesia/doc/src/mnesia.xml15
-rw-r--r--lib/mnesia/doc/src/notes.xml114
-rw-r--r--lib/mnesia/examples/Makefile10
-rw-r--r--lib/mnesia/include/Makefile4
-rw-r--r--lib/mnesia/src/Makefile8
-rw-r--r--lib/mnesia/src/mnesia.appup.src12
-rw-r--r--lib/mnesia/src/mnesia.erl438
-rw-r--r--lib/mnesia/src/mnesia.hrl1
-rw-r--r--lib/mnesia/src/mnesia_backup.erl20
-rw-r--r--lib/mnesia/src/mnesia_bup.erl80
-rw-r--r--lib/mnesia/src/mnesia_controller.erl302
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl231
-rw-r--r--lib/mnesia/src/mnesia_event.erl8
-rw-r--r--lib/mnesia/src/mnesia_frag.erl12
-rw-r--r--lib/mnesia/src/mnesia_frag_hash.erl20
-rw-r--r--lib/mnesia/src/mnesia_index.erl6
-rw-r--r--lib/mnesia/src/mnesia_loader.erl32
-rw-r--r--lib/mnesia/src/mnesia_locker.erl376
-rw-r--r--lib/mnesia/src/mnesia_log.erl108
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl14
-rw-r--r--lib/mnesia/src/mnesia_schema.erl206
-rw-r--r--lib/mnesia/src/mnesia_tm.erl372
-rw-r--r--lib/mnesia/test/Makefile38
-rw-r--r--lib/mnesia/test/mnesia_atomicity_test.erl96
-rw-r--r--lib/mnesia/test/mnesia_consistency_test.erl22
-rw-r--r--lib/mnesia/test/mnesia_dirty_access_test.erl3
-rw-r--r--lib/mnesia/test/mnesia_evil_backup.erl8
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl60
-rw-r--r--lib/mnesia/test/mnesia_frag_hash_test.erl94
-rw-r--r--lib/mnesia/test/mnesia_install_test.erl25
-rw-r--r--lib/mnesia/test/mnesia_test_lib.erl104
-rw-r--r--lib/mnesia/test/mnesia_test_lib.hrl14
-rw-r--r--lib/mnesia/test/mnesia_trans_access_test.erl843
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/Makefile20
-rw-r--r--lib/observer/doc/src/etop.xml33
-rw-r--r--lib/observer/doc/src/make.dep29
-rw-r--r--lib/observer/doc/src/notes.xml119
-rw-r--r--lib/observer/doc/src/observer.xml58
-rw-r--r--lib/observer/doc/src/observer_ug.xml190
-rw-r--r--lib/observer/doc/src/part.xml3
-rw-r--r--lib/observer/doc/src/ref_man.xml3
-rw-r--r--lib/observer/doc/src/ttb_ug.xml2
-rw-r--r--lib/observer/priv/erlang_observer.pngbin0 -> 2679 bytes
-rw-r--r--lib/observer/src/Makefile62
-rw-r--r--lib/observer/src/crashdump_viewer_html.erl4
-rw-r--r--lib/observer/src/etop.erl8
-rw-r--r--lib/observer/src/etop_gui.erl9
-rw-r--r--lib/observer/src/observer.app.src12
-rw-r--r--lib/observer/src/observer.erl25
-rw-r--r--lib/observer/src/observer_app_wx.erl571
-rw-r--r--lib/observer/src/observer_defs.hrl47
-rw-r--r--lib/observer/src/observer_lib.erl429
-rw-r--r--lib/observer/src/observer_perf_wx.erl575
-rw-r--r--lib/observer/src/observer_pro_wx.erl600
-rw-r--r--lib/observer/src/observer_procinfo.erl313
-rw-r--r--lib/observer/src/observer_sys_wx.erl177
-rw-r--r--lib/observer/src/observer_trace_wx.erl866
-rw-r--r--lib/observer/src/observer_traceoptions_wx.erl675
-rw-r--r--lib/observer/src/observer_tv.hrl34
-rw-r--r--lib/observer/src/observer_tv_table.erl829
-rw-r--r--lib/observer/src/observer_tv_wx.erl353
-rw-r--r--lib/observer/src/observer_wx.erl614
-rw-r--r--lib/observer/src/ttb.erl75
-rw-r--r--lib/observer/test/Makefile6
-rw-r--r--lib/observer/test/client.erl2
-rw-r--r--lib/observer/test/crashdump_helper.erl2
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl57
-rw-r--r--lib/observer/test/etop_SUITE.erl15
-rw-r--r--lib/observer/test/server.erl3
-rw-r--r--lib/observer/test/ttb_SUITE.erl364
-rw-r--r--lib/observer/test/ttb_helper.erl2
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--[l---------]lib/odbc/aclocal.m41873
-rw-r--r--lib/odbc/c_src/Makefile.in14
-rw-r--r--lib/odbc/c_src/odbcserver.c60
-rw-r--r--lib/odbc/c_src/odbcserver.h2
-rw-r--r--lib/odbc/configure.in22
-rw-r--r--lib/odbc/doc/src/Makefile103
-rw-r--r--lib/odbc/doc/src/make.dep27
-rw-r--r--lib/odbc/doc/src/notes.xml38
-rw-r--r--lib/odbc/src/Makefile12
-rw-r--r--lib/odbc/src/odbc.appup.src6
-rw-r--r--lib/odbc/src/odbc.erl36
-rw-r--r--lib/odbc/test/Makefile4
-rw-r--r--lib/odbc/test/odbc_test_lib.erl3
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/orber/COSS/CosNaming/Makefile14
-rw-r--r--lib/orber/c_src/Makefile.in24
-rw-r--r--lib/orber/doc/src/Makefile105
-rw-r--r--lib/orber/doc/src/ch_install.xml136
-rw-r--r--lib/orber/doc/src/ch_security.xml91
-rw-r--r--lib/orber/doc/src/corba.xml16
-rw-r--r--lib/orber/doc/src/corba_object.xml11
-rw-r--r--lib/orber/doc/src/make.dep62
-rw-r--r--lib/orber/doc/src/notes.xml68
-rw-r--r--lib/orber/doc/src/orber.xml94
-rw-r--r--lib/orber/examples/Stack/Makefile8
-rw-r--r--lib/orber/java_src/Orber/Makefile4
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/Makefile6
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/blank.html0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/info_frames.html0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/main_frame.html0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/orber.tool0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/orber_help.txt0
-rw-r--r--[-rwxr-xr-x]lib/orber/priv/start_info.html0
-rw-r--r--lib/orber/src/Makefile16
-rw-r--r--lib/orber/src/orber.erl10
-rw-r--r--lib/orber/src/orber_diagnostics.erl2
-rw-r--r--lib/orber/src/orber_env.erl291
-rw-r--r--lib/orber/src/orber_ifr.erl4
-rw-r--r--lib/orber/src/orber_iiop_net.erl139
-rw-r--r--lib/orber/src/orber_iiop_pm.erl134
-rw-r--r--lib/orber/src/orber_socket.erl14
-rw-r--r--lib/orber/src/orber_tb.erl37
-rw-r--r--lib/orber/test/Makefile13
-rw-r--r--lib/orber/test/csiv2_SUITE.erl562
-rw-r--r--lib/orber/test/multi_ORB_SUITE.erl1363
-rw-r--r--lib/orber/test/orber_SUITE.erl38
-rw-r--r--lib/orber/test/orber_acl_SUITE.erl4
-rw-r--r--lib/orber/test/orber_nat_SUITE.erl307
-rw-r--r--lib/orber/test/orber_test_lib.erl899
-rw-r--r--lib/orber/vsn.mk2
-rw-r--r--lib/os_mon/c_src/Makefile.in10
-rw-r--r--lib/os_mon/c_src/cpu_sup.c14
-rw-r--r--lib/os_mon/c_src/memsup.c39
-rw-r--r--lib/os_mon/c_src/win32sysinfo.c30
-rw-r--r--lib/os_mon/doc/src/Makefile18
-rw-r--r--lib/os_mon/doc/src/make.dep21
-rw-r--r--lib/os_mon/doc/src/notes.xml48
-rw-r--r--lib/os_mon/mibs/Makefile18
-rw-r--r--lib/os_mon/src/Makefile10
-rw-r--r--lib/os_mon/src/cpu_sup.erl5
-rw-r--r--lib/os_mon/src/disksup.erl10
-rw-r--r--lib/os_mon/src/memsup.erl7
-rw-r--r--lib/os_mon/src/os_mon.erl20
-rw-r--r--lib/os_mon/src/os_mon_mib.erl6
-rw-r--r--lib/os_mon/src/os_mon_sysinfo.erl6
-rw-r--r--lib/os_mon/test/Makefile6
-rw-r--r--lib/os_mon/test/os_mon_mib_SUITE.erl2
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/otp_mibs/doc/src/Makefile14
-rw-r--r--lib/otp_mibs/doc/src/make.dep20
-rw-r--r--lib/otp_mibs/doc/src/notes.xml22
-rw-r--r--lib/otp_mibs/mibs/Makefile16
-rw-r--r--lib/otp_mibs/src/Makefile8
-rw-r--r--lib/otp_mibs/src/otp_mib.erl6
-rw-r--r--lib/otp_mibs/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/Makefile14
-rw-r--r--lib/parsetools/doc/src/make.dep21
-rw-r--r--lib/parsetools/doc/src/notes.xml22
-rw-r--r--lib/parsetools/include/yeccpre.hrl5
-rw-r--r--lib/parsetools/src/Makefile12
-rw-r--r--lib/parsetools/test/Makefile8
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl7
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/percept/doc/src/Makefile14
-rw-r--r--lib/percept/doc/src/make.dep34
-rw-r--r--lib/percept/doc/src/notes.xml15
-rw-r--r--[-rwxr-xr-x]lib/percept/doc/src/part_notes.xml0
-rw-r--r--lib/percept/priv/Makefile28
-rw-r--r--lib/percept/src/Makefile12
-rw-r--r--lib/percept/test/Makefile8
-rw-r--r--[-rwxr-xr-x]lib/percept/test/percept_SUITE_data/ipc-dist.datbin2098105 -> 2098105 bytes
-rw-r--r--lib/percept/vsn.mk2
-rw-r--r--lib/pman/doc/src/Makefile14
-rw-r--r--lib/pman/doc/src/make.dep26
-rw-r--r--lib/pman/doc/src/notes.xml37
-rw-r--r--lib/pman/doc/src/pman.xml8
-rw-r--r--lib/pman/doc/src/pman_chapter.xml8
-rw-r--r--lib/pman/priv/Makefile4
-rw-r--r--lib/pman/src/Makefile8
-rw-r--r--lib/pman/src/pman_buf_converter.erl3
-rw-r--r--lib/pman/src/pman_buf_printer.erl4
-rw-r--r--lib/pman/src/pman_main.erl4
-rw-r--r--lib/pman/src/pman_module_info.erl4
-rw-r--r--lib/pman/src/pman_shell.erl6
-rw-r--r--lib/pman/src/pman_tool.erl3
-rw-r--r--lib/pman/src/pman_win.erl12
-rw-r--r--lib/pman/vsn.mk2
-rw-r--r--lib/public_key/.gitignore7
-rw-r--r--[-rwxr-xr-x]lib/public_key/asn1/DSS.asn10
-rw-r--r--lib/public_key/asn1/Makefile31
-rw-r--r--lib/public_key/asn1/OTP-PKIX.asn145
-rw-r--r--[-rwxr-xr-x]lib/public_key/asn1/PKCS-1.asn13
-rw-r--r--lib/public_key/asn1/PKCS-8.asn1143
-rw-r--r--lib/public_key/asn1/PKCS-FRAME.set.asn2
-rw-r--r--lib/public_key/asn1/PKCS5v2-0.asn1142
-rw-r--r--lib/public_key/doc/src/Makefile100
-rw-r--r--lib/public_key/doc/src/make.dep21
-rw-r--r--lib/public_key/doc/src/notes.xml51
-rw-r--r--lib/public_key/doc/src/public_key.xml50
-rw-r--r--lib/public_key/include/public_key.hrl1
-rw-r--r--lib/public_key/src/Makefile18
-rw-r--r--lib/public_key/src/pubkey_cert.erl6
-rw-r--r--lib/public_key/src/pubkey_cert_records.erl11
-rw-r--r--lib/public_key/src/pubkey_pbe.erl213
-rw-r--r--lib/public_key/src/pubkey_pem.erl81
-rw-r--r--lib/public_key/src/pubkey_ssh.erl95
-rw-r--r--lib/public_key/src/public_key.app.src4
-rw-r--r--lib/public_key/src/public_key.appup.src66
-rw-r--r--lib/public_key/src/public_key.erl227
-rw-r--r--lib/public_key/test/Makefile15
-rw-r--r--lib/public_key/test/erl_make_certs.erl14
-rw-r--r--lib/public_key/test/pbe_SUITE.erl259
-rw-r--r--lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem11
-rw-r--r--lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem11
-rw-r--r--lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE.erl672
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesAnyPolicyTest11.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2.pem107
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePolicyTest1.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesanyPolicyTest11EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLIssuerNameCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLSignatureCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadSignedCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotAfterDateCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotBeforeDateCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCRLCert.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyOldWithNewCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyNewWithOldCACert.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20.pem120
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSACACert.pem48
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSAParametersInheritedCACert.pem38
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3.pem170
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4.pem170
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5.pem170
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7.pem211
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8.pem210
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9.pem263
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GeneralizedTimeCRLnextUpdateCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCAPanyPolicyMapping1to2CACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7.pem175
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8.pem175
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5.pem175
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2.pem134
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10.pem113
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12.pem166
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13.pem166
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15.pem164
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16.pem164
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17.pem163
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest20EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3.pem114
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8.pem112
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9.pem112
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6.pem104
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6EE.pem44
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23.pem116
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26.pem137
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18.pem115
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingCRLTest1EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingEETest1.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2.pem113
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15.pem114
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10.pem172
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4.pem214
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest3.pem262
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest5.pem266
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2.pem170
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedDNnameConstraintsTest20.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10.pem178
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8.pem230
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10.pem200
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11.pem200
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8.pem233
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9.pem233
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16.pem179
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7.pem178
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8.pem197
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20.pem134
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21.pem129
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10.pem117
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9.pem117
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2.pem58
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27.pem140
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31.pem226
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32.pem226
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34.pem205
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35.pem207
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10.pem150
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3.pem190
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4.pem190
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6.pem190
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9.pem162
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2.pem123
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3.pem123
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9.pem117
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4.pem159
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5.pem210
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6.pem159
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1.pem161
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3.pem216
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5.pem264
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6.pem217
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14.pem112
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsCRLTest12.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsTest12EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsCRLTest11.pem112
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsTest11EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15.pem156
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16.pem156
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17.pem146
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20EE.pem66
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21EE.pem66
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10.pem211
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11.pem262
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12.pem263
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5.pem159
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6.pem160
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9.pem210
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/LongSerialNumberCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Mapping1to2CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingFromanyPolicyCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingToanyPolicyCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingCRLTest1.pem76
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingbasicConstraintsCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NameOrderingCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NegativeSerialNumberCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoCRLCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoPoliciesCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoissuingDistributionPointCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OldCRLnextUpdateCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6.pem214
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3CACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subsubCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234CACert.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234subCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1anyPolicyMapping1to2CACert.pem69
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PanyPolicyMapping1to2CACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234CACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subCAP123Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subsubCAP123P12Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subCAP12Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P1Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubsubCAP12P2P1Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subCAP1Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subsubCAP1P2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCA2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP3CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280MandatoryAttributeTypesCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280OptionalAttributeTypesCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RevokedsubCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RolloverfromPrintableStringtoUTF8StringCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CRLSigningCert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCRLSigningCert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCertificateSigningCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TrustAnchorRootCertificate.pem59
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TwoCRLsCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UIDCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringCaseInsensitiveMatchCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringEncodedNamesCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLEntryExtensionCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLExtensionCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15.pem59
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16.pem124
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17.pem121
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18.pem115
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18EE.pem67
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19EE.pem68
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6.pem175
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3.pem175
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4.pem175
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1.pem134
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidCertificatePathTest1EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11.pem113
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14.pem165
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18.pem162
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest19EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4.pem112
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5.pem115
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5.pem141
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5EE.pem38
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4.pem104
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4EE.pem44
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22.pem116
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24.pem137
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25.pem137
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16.pem115
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17.pem115
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingUIDsTest6.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameUIDsTest6EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14.pem114
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11.pem172
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12EE.pem69
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13.pem117
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14.pem117
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3.pem214
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5.pem163
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6.pem163
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9.pem109
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7.pem113
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8.pem114
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest1.pem264
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest2.pem262
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest4.pem262
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedDNnameConstraintsTest19.pem130
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7.pem178
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9.pem197
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7.pem180
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15.pem127
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17.pem197
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6.pem127
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19.pem134
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSignaturesTest1.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7.pem146
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7EE.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36.pem111
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1.pem58
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4.pem110
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28.pem178
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28EE.pem66
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29.pem176
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30.pem143
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30EE.pem66
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33.pem226
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2.pem190
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5.pem190
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7.pem190
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8.pem162
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1.pem123
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4.pem121
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5EE.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7.pem120
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7EE.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2.pem162
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4.pem216
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsCRLTest13.pem112
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsTest13EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18EE.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19.pem167
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19EE.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13.pem262
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14.pem263
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8.pem108
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3.pem119
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest1EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest2EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest4EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/WrongCRLCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/anyPolicyCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsCriticalcAFalseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalcAFalseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/certs.pem118
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA1Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA2Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA3Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLIndicatorNoBaseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint1CACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint2CACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA1Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA2Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3cRLIssuerCert.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4cRLIssuerCert.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA5Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA6Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy0CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedsubCA2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA1Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCAIAP5Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subsubCA2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3.pem159
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3EE.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0subCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCACert.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCAIPM5Cert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCAIPM5Cert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedsubCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subsubCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubsubCACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalcRLSignFalseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalkeyCertSignFalseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalcRLSignFalseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalkeyCertSignFalseCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1CACert.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1SelfIssuedCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA1Cert.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA2Cert.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA3Cert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN2CACert.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3CACert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA1Cert.pem63
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA2Cert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN4CACert.pem64
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN5CACert.pem65
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS1CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS2CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA1Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA3Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI1CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI2CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsAttributeCertsCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsCACertsCACert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsUserCertsCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA1Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA2Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA3Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA4Cert.pem60
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0SelfIssuedCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCA2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA0Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA1Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA4Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA00Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA11Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA41Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA11XCert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA41XCert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pre2000CRLnextUpdateCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubsubCACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7CACert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subCARE2Cert.pem61
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubCARE2RE4Cert.pem62
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubsubCARE2RE4Cert.pem61
-rw-r--r--lib/public_key/test/public_key_SUITE.erl60
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/Makefile14
-rw-r--r--lib/reltool/doc/src/make.dep20
-rw-r--r--lib/reltool/doc/src/notes.xml160
-rw-r--r--lib/reltool/doc/src/reltool.xml91
-rw-r--r--lib/reltool/examples/Makefile4
-rw-r--r--lib/reltool/src/Makefile10
-rw-r--r--lib/reltool/src/reltool.erl6
-rw-r--r--lib/reltool/src/reltool.hrl98
-rw-r--r--lib/reltool/src/reltool_app_win.erl19
-rw-r--r--lib/reltool/src/reltool_mod_win.erl8
-rw-r--r--lib/reltool/src/reltool_server.erl2026
-rw-r--r--lib/reltool/src/reltool_sys_win.erl321
-rw-r--r--lib/reltool/src/reltool_target.erl176
-rw-r--r--lib/reltool/src/reltool_utils.erl95
-rw-r--r--lib/reltool/test/Makefile17
-rw-r--r--lib/reltool/test/reltool.spec1
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE.erl266
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/Makefile.src28
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/ebin/x.app7
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x1.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x2.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x3.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/ebin/y.app7
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y1.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y2.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y3.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/ebin/z.app7
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/src/z1.erl5
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/ebin/a.app1
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/src/a.erl49
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/src/a_sup.erl37
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl1841
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/Makefile.src49
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/ebin/x.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x1.erl5
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x2.erl5
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x3.erl5
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y1.erl5
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y2.erl5
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/ebin/z.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/src/z1.erl5
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/dupl_mod/a-1.0/ebin/a.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/ebin/someapp.app6
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/src/mymod.erl26
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/ebin/a.app1
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/src/a.erl49
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/src/a_sup.erl37
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/ebin/a.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/src/a.erl49
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/src/a_sup.erl37
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/sort_apps/x-1.0/ebin/x.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/sort_apps/y-1.0/ebin/y.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/sort_apps/z-1.0/ebin/z.app8
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/ebin/b.app6
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/rel/.gitignore0
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/src/b.erl4
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/ebin/b.app6
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/src/b.erl4
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/ebin/b.app6
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/src/b.erl4
-rw-r--r--lib/reltool/test/reltool_test_lib.erl6
-rw-r--r--lib/reltool/test/reltool_test_lib.hrl34
-rw-r--r--lib/reltool/test/reltool_wx_SUITE.erl43
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/c_src/Makefile.in83
-rw-r--r--lib/runtime_tools/c_src/dtrace_user.d33
-rw-r--r--lib/runtime_tools/c_src/dyntrace.c127
-rw-r--r--lib/runtime_tools/c_src/trace_file_drv.c90
-rw-r--r--lib/runtime_tools/c_src/trace_ip_drv.c51
-rw-r--r--lib/runtime_tools/doc/src/Makefile22
-rw-r--r--lib/runtime_tools/doc/src/dyntrace.xml209
-rw-r--r--lib/runtime_tools/doc/src/make.dep20
-rw-r--r--lib/runtime_tools/doc/src/notes.xml72
-rw-r--r--lib/runtime_tools/doc/src/ref_man.xml3
-rw-r--r--lib/runtime_tools/examples/dist.d62
-rw-r--r--lib/runtime_tools/examples/dist.systemtap76
-rw-r--r--lib/runtime_tools/examples/driver1.d114
-rw-r--r--lib/runtime_tools/examples/driver1.systemtap125
-rw-r--r--lib/runtime_tools/examples/efile_drv.d104
-rw-r--r--lib/runtime_tools/examples/efile_drv.systemtap112
-rw-r--r--lib/runtime_tools/examples/function-calls.d57
-rw-r--r--lib/runtime_tools/examples/function-calls.systemtap67
-rw-r--r--lib/runtime_tools/examples/garbage-collection.d39
-rw-r--r--lib/runtime_tools/examples/garbage-collection.systemtap49
-rw-r--r--lib/runtime_tools/examples/memory1.d41
-rw-r--r--lib/runtime_tools/examples/memory1.systemtap51
-rw-r--r--lib/runtime_tools/examples/messages.d94
-rw-r--r--lib/runtime_tools/examples/messages.systemtap87
-rw-r--r--lib/runtime_tools/examples/port1.d142
-rw-r--r--lib/runtime_tools/examples/port1.systemtap152
-rw-r--r--lib/runtime_tools/examples/process-scheduling.d35
-rw-r--r--lib/runtime_tools/examples/process-scheduling.systemtap45
-rw-r--r--lib/runtime_tools/examples/spawn-exit.d41
-rw-r--r--lib/runtime_tools/examples/spawn-exit.systemtap51
-rw-r--r--lib/runtime_tools/examples/user-probe-n.d44
-rw-r--r--lib/runtime_tools/examples/user-probe-n.systemtap53
-rw-r--r--lib/runtime_tools/examples/user-probe.d36
-rw-r--r--lib/runtime_tools/examples/user-probe.systemtap46
-rw-r--r--lib/runtime_tools/src/Makefile24
-rw-r--r--lib/runtime_tools/src/dbg.erl52
-rw-r--r--lib/runtime_tools/src/dyntrace.erl352
-rw-r--r--lib/runtime_tools/src/erts_alloc_config.erl12
-rw-r--r--lib/runtime_tools/src/inviso_rt.erl4
-rw-r--r--lib/runtime_tools/src/inviso_rt_lib.erl18
-rw-r--r--lib/runtime_tools/src/observer_backend.erl233
-rw-r--r--lib/runtime_tools/src/runtime_tools.app.src4
-rw-r--r--lib/runtime_tools/src/runtime_tools_sup.erl2
-rw-r--r--lib/runtime_tools/test/Makefile11
-rw-r--r--lib/runtime_tools/test/dyntrace_SUITE.erl224
-rw-r--r--lib/runtime_tools/test/inviso_SUITE.erl41
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/Makefile22
-rw-r--r--lib/sasl/doc/src/appup.xml61
-rw-r--r--lib/sasl/doc/src/make.dep22
-rw-r--r--lib/sasl/doc/src/notes.xml161
-rw-r--r--lib/sasl/doc/src/rb.xml6
-rw-r--r--lib/sasl/doc/src/rel.xml4
-rw-r--r--lib/sasl/doc/src/release_handler.xml91
-rw-r--r--lib/sasl/doc/src/systools.xml20
-rw-r--r--lib/sasl/examples/src/Makefile8
-rw-r--r--lib/sasl/examples/src/target_system.erl8
-rw-r--r--lib/sasl/src/Makefile10
-rw-r--r--lib/sasl/src/release_handler.erl460
-rw-r--r--lib/sasl/src/release_handler_1.erl133
-rw-r--r--lib/sasl/src/sasl.appup.src26
-rw-r--r--lib/sasl/src/systools.hrl5
-rw-r--r--lib/sasl/src/systools_make.erl420
-rw-r--r--lib/sasl/src/systools_rc.erl40
-rw-r--r--lib/sasl/src/systools_relup.erl153
-rw-r--r--lib/sasl/test/Makefile12
-rw-r--r--lib/sasl/test/alarm_handler_SUITE.erl62
-rw-r--r--lib/sasl/test/installer.erl580
-rw-r--r--lib/sasl/test/overload_SUITE.erl110
-rw-r--r--lib/sasl/test/rb_SUITE.erl409
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl630
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/Makefile.src39
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.app9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.appup4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1.erl22
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1_server.erl35
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1_sup.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/ebin/app1.app9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/ebin/app1.appup4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1.erl22
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1_server.erl35
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1_sup.erl17
-rw-r--r--[-rwxr-xr-x]lib/sasl/test/release_handler_SUITE_data/heart_restart.bat0
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/README8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.appup2
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a.erl56
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a_sup.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a.erl56
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a_sup.erl37
-rw-r--r--lib/sasl/test/sasl_SUITE.erl109
-rw-r--r--lib/sasl/test/systools_SUITE.erl2836
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-2.1/ebin/fe.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-500.18.7/ebin/fe.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-2.1.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-2.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup28
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.app6
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.appup12
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.app6
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.appup12
-rw-r--r--lib/sasl/test/systools_rc_SUITE.erl621
-rw-r--r--lib/sasl/test/test_lib.hrl3
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/Makefile28
-rw-r--r--lib/snmp/doc/src/Makefile164
-rw-r--r--lib/snmp/doc/src/depend.mk83
-rw-r--r--lib/snmp/doc/src/make.dep77
-rw-r--r--lib/snmp/doc/src/notes.xml1744
-rw-r--r--lib/snmp/doc/src/notes_history.xml1275
-rw-r--r--lib/snmp/doc/src/snmp.xml28
-rw-r--r--lib/snmp/doc/src/snmp_app.xml121
-rw-r--r--lib/snmp/doc/src/snmp_config.xml121
-rw-r--r--lib/snmp/doc/src/snmp_generic.xml81
-rw-r--r--lib/snmp/doc/src/snmp_manager_netif.xml43
-rw-r--r--lib/snmp/doc/src/snmpa.xml54
-rw-r--r--lib/snmp/doc/src/snmpa_network_interface_filter.xml6
-rw-r--r--lib/snmp/doc/src/snmpm.xml48
-rw-r--r--lib/snmp/doc/src/snmpm_network_interface_filter.xml13
-rw-r--r--lib/snmp/examples/ex1/Makefile2
-rw-r--r--lib/snmp/examples/ex2/Makefile2
-rw-r--r--lib/snmp/examples/ex2/snmp_ex2_manager.erl13
-rw-r--r--lib/snmp/include/snmp_types.hrl27
-rw-r--r--lib/snmp/mibs/Makefile.in24
-rw-r--r--lib/snmp/priv/conf/agent/Makefile6
-rw-r--r--lib/snmp/priv/conf/manager/Makefile6
-rw-r--r--lib/snmp/priv/plt/.gitignore3
-rw-r--r--lib/snmp/src/agent/Makefile14
-rw-r--r--lib/snmp/src/agent/depend.mk4
-rw-r--r--lib/snmp/src/agent/snmp_community_mib.erl21
-rw-r--r--lib/snmp/src/agent/snmp_framework_mib.erl27
-rw-r--r--lib/snmp/src/agent/snmp_generic_mnesia.erl7
-rw-r--r--lib/snmp/src/agent/snmp_notification_mib.erl19
-rw-r--r--lib/snmp/src/agent/snmp_standard_mib.erl30
-rw-r--r--lib/snmp/src/agent/snmp_target_mib.erl24
-rw-r--r--lib/snmp/src/agent/snmp_user_based_sm_mib.erl196
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl144
-rw-r--r--lib/snmp/src/agent/snmpa.erl28
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl766
-rw-r--r--lib/snmp/src/agent/snmpa_internal.hrl14
-rw-r--r--lib/snmp/src/agent/snmpa_local_db.erl14
-rw-r--r--lib/snmp/src/agent/snmpa_mib.erl14
-rw-r--r--lib/snmp/src/agent/snmpa_mib_lib.erl22
-rw-r--r--lib/snmp/src/agent/snmpa_mpd.erl28
-rw-r--r--lib/snmp/src/agent/snmpa_set_lib.erl86
-rw-r--r--lib/snmp/src/agent/snmpa_supervisor.erl42
-rw-r--r--lib/snmp/src/agent/snmpa_trap.erl28
-rw-r--r--lib/snmp/src/agent/snmpa_vacm.erl52
-rw-r--r--lib/snmp/src/app/Makefile14
-rw-r--r--lib/snmp/src/app/snmp.app.src3
-rw-r--r--lib/snmp/src/app/snmp.appup.src697
-rw-r--r--lib/snmp/src/app/snmp.erl9
-rw-r--r--lib/snmp/src/compile/Makefile14
-rw-r--r--lib/snmp/src/compile/depend.mk2
-rw-r--r--lib/snmp/src/compile/snmpc.src21
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl38
-rw-r--r--lib/snmp/src/manager/Makefile14
-rw-r--r--lib/snmp/src/manager/depend.mk9
-rw-r--r--lib/snmp/src/manager/modules.mk3
-rw-r--r--lib/snmp/src/manager/snmpm.erl25
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl2
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl8
-rw-r--r--lib/snmp/src/manager/snmpm_net_if_mt.erl1259
-rw-r--r--lib/snmp/src/misc/Makefile14
-rw-r--r--lib/snmp/src/misc/snmp_conf.erl17
-rw-r--r--lib/snmp/src/misc/snmp_config.erl95
-rw-r--r--lib/snmp/src/misc/snmp_log.erl110
-rw-r--r--lib/snmp/src/misc/snmp_note_store.erl17
-rw-r--r--lib/snmp/src/misc/snmp_pdus.erl110
-rw-r--r--lib/snmp/src/misc/snmp_verbosity.erl6
-rw-r--r--lib/snmp/test/Makefile17
-rw-r--r--lib/snmp/test/exp/.gitignore0
-rw-r--r--lib/snmp/test/exp/snmp_agent_bl_test.erl5654
-rw-r--r--lib/snmp/test/exp/snmp_agent_ms_test.erl5649
-rw-r--r--lib/snmp/test/exp/snmp_agent_mt_test.erl5649
-rw-r--r--lib/snmp/test/exp/snmp_agent_v1_test.erl2673
-rw-r--r--lib/snmp/test/exp/snmp_agent_v2_test.erl5649
-rw-r--r--lib/snmp/test/exp/snmp_agent_v3_test.erl5649
-rw-r--r--lib/snmp/test/modules.mk5
-rw-r--r--lib/snmp/test/snmp_SUITE.erl47
-rw-r--r--lib/snmp/test/snmp_agent_bl_test.erl5654
-rw-r--r--lib/snmp/test/snmp_agent_ms_test.erl5649
-rw-r--r--lib/snmp/test/snmp_agent_mt_test.erl5649
-rw-r--r--lib/snmp/test/snmp_agent_test.erl965
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl377
-rw-r--r--lib/snmp/test/snmp_agent_v1_test.erl2673
-rw-r--r--lib/snmp/test/snmp_agent_v2_test.erl5649
-rw-r--r--lib/snmp/test/snmp_agent_v3_test.erl5649
-rw-r--r--lib/snmp/test/snmp_app_test.erl43
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl124
-rw-r--r--lib/snmp/test/snmp_log_test.erl29
-rw-r--r--lib/snmp/test/snmp_manager_config_test.erl15
-rw-r--r--lib/snmp/test/snmp_manager_test.erl312
-rw-r--r--[-rwxr-xr-x]lib/snmp/test/snmp_manager_user_old.erl2
-rw-r--r--lib/snmp/test/snmp_pdus_test.erl176
-rw-r--r--lib/snmp/test/snmp_test_data/Test3.mib123
-rw-r--r--lib/snmp/test/snmp_test_lib.erl110
-rw-r--r--lib/snmp/test/snmp_test_mgr.erl15
-rw-r--r--lib/snmp/test/snmp_test_mgr_misc.erl15
-rw-r--r--lib/snmp/test/test-mibs/RMON-MIB.mib7782
-rw-r--r--lib/snmp/vsn.mk9
-rw-r--r--lib/ssh/doc/src/Makefile101
-rw-r--r--lib/ssh/doc/src/make.dep19
-rw-r--r--lib/ssh/doc/src/notes.xml128
-rw-r--r--lib/ssh/doc/src/ssh.xml84
-rw-r--r--lib/ssh/examples/Makefile4
-rwxr-xr-xlib/ssh/src/DSS.asn120
-rw-r--r--lib/ssh/src/Makefile75
-rwxr-xr-xlib/ssh/src/PKCS-1.asn1116
-rw-r--r--lib/ssh/src/prebuild.skip2
-rw-r--r--lib/ssh/src/ssh.app.src9
-rw-r--r--lib/ssh/src/ssh.appup.src22
-rw-r--r--lib/ssh/src/ssh.erl340
-rw-r--r--lib/ssh/src/ssh.hrl17
-rw-r--r--lib/ssh/src/ssh_acceptor.erl8
-rw-r--r--lib/ssh/src/ssh_auth.erl160
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_bits.erl6
-rw-r--r--lib/ssh/src/ssh_channel.erl30
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_connect.hrl6
-rw-r--r--lib/ssh/src/ssh_connection.erl23
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl298
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl170
-rw-r--r--lib/ssh/src/ssh_connection_sup.erl113
-rwxr-xr-xlib/ssh/src/ssh_dsa.erl95
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_file.erl641
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_io.erl2
-rw-r--r--lib/ssh/src/ssh_key_api.erl45
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_math.erl2
-rwxr-xr-xlib/ssh/src/ssh_rsa.erl298
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_sftp.erl0
-rw-r--r--lib/ssh/src/ssh_sftpd.erl36
-rw-r--r--lib/ssh/src/ssh_sftpd_file_api.erl62
-rw-r--r--lib/ssh/src/ssh_subsystem_sup.erl14
-rw-r--r--lib/ssh/src/ssh_system_sup.erl4
-rw-r--r--lib/ssh/src/ssh_transport.erl271
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_userauth.hrl2
-rw-r--r--lib/ssh/src/ssh_xfer.erl16
-rw-r--r--[-rwxr-xr-x]lib/ssh/src/ssh_xfer.hrl2
-rw-r--r--lib/ssh/src/sshc_sup.erl26
-rw-r--r--lib/ssh/test/Makefile15
-rw-r--r--lib/ssh/test/ssh_SUITE.erl72
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl318
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_rsa15
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key16
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub5
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl134
-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/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl130
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl57
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_test_lib.erl634
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl163
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/Makefile18
-rw-r--r--lib/ssl/doc/src/notes.xml142
-rw-r--r--lib/ssl/doc/src/ssl.xml58
-rw-r--r--lib/ssl/examples/certs/Makefile6
-rw-r--r--lib/ssl/examples/src/Makefile8
-rw-r--r--lib/ssl/examples/src/client_server.erl24
-rw-r--r--lib/ssl/src/Makefile31
-rw-r--r--lib/ssl/src/inet_tls_dist.erl16
-rw-r--r--lib/ssl/src/ssl.appup.src22
-rw-r--r--lib/ssl/src/ssl.erl100
-rw-r--r--lib/ssl/src/ssl_alert.erl4
-rw-r--r--lib/ssl/src/ssl_alert.hrl4
-rw-r--r--lib/ssl/src/ssl_app.erl7
-rw-r--r--lib/ssl/src/ssl_certificate.erl46
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl231
-rw-r--r--lib/ssl/src/ssl_cipher.erl396
-rw-r--r--lib/ssl/src/ssl_cipher.hrl46
-rw-r--r--lib/ssl/src/ssl_connection.erl994
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl1
-rw-r--r--lib/ssl/src/ssl_handshake.erl577
-rw-r--r--lib/ssl/src/ssl_handshake.hrl29
-rw-r--r--lib/ssl/src/ssl_internal.hrl10
-rw-r--r--lib/ssl/src/ssl_manager.erl254
-rw-r--r--lib/ssl/src/ssl_record.erl115
-rw-r--r--lib/ssl/src/ssl_record.hrl20
-rw-r--r--lib/ssl/src/ssl_session.erl127
-rw-r--r--lib/ssl/src/ssl_session_cache.erl20
-rw-r--r--lib/ssl/src/ssl_session_cache_api.erl25
-rw-r--r--lib/ssl/src/ssl_ssl3.erl54
-rw-r--r--lib/ssl/src/ssl_sup.erl1
-rw-r--r--lib/ssl/src/ssl_tls1.erl190
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl48
-rw-r--r--lib/ssl/test/Makefile12
-rw-r--r--lib/ssl/test/erl_make_certs.erl14
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl863
-rw-r--r--lib/ssl/test/ssl_cipher_SUITE.erl221
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl105
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl3
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl383
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl58
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl35
-rw-r--r--lib/ssl/test/ssl_test_lib.erl67
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl672
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/Makefile19
-rw-r--r--lib/stdlib/doc/src/binary.xml4
-rw-r--r--lib/stdlib/doc/src/digraph_utils.xml4
-rw-r--r--lib/stdlib/doc/src/ets.xml4
-rw-r--r--lib/stdlib/doc/src/filename.xml6
-rw-r--r--lib/stdlib/doc/src/gb_trees.xml18
-rw-r--r--lib/stdlib/doc/src/gen_event.xml80
-rw-r--r--lib/stdlib/doc/src/gen_fsm.xml55
-rw-r--r--lib/stdlib/doc/src/gen_server.xml49
-rw-r--r--lib/stdlib/doc/src/io.xml2
-rw-r--r--lib/stdlib/doc/src/io_protocol.xml22
-rw-r--r--lib/stdlib/doc/src/lists.xml4
-rw-r--r--lib/stdlib/doc/src/make.dep40
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml4
-rw-r--r--lib/stdlib/doc/src/notes.xml456
-rw-r--r--lib/stdlib/doc/src/random.xml5
-rw-r--r--lib/stdlib/doc/src/re.xml3
-rw-r--r--lib/stdlib/doc/src/ref_man.xml3
-rw-r--r--lib/stdlib/doc/src/regexp.xml381
-rw-r--r--lib/stdlib/doc/src/sofs.xml10
-rw-r--r--lib/stdlib/doc/src/specs.xml1
-rw-r--r--lib/stdlib/doc/src/supervisor.xml134
-rw-r--r--lib/stdlib/doc/src/supervisor_bridge.xml7
-rw-r--r--lib/stdlib/doc/src/unicode.xml3
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml10
-rw-r--r--lib/stdlib/examples/Makefile4
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl9
-rw-r--r--lib/stdlib/src/Makefile18
-rw-r--r--lib/stdlib/src/digraph_utils.erl4
-rw-r--r--lib/stdlib/src/epp.erl28
-rw-r--r--lib/stdlib/src/erl_compile.erl14
-rw-r--r--lib/stdlib/src/erl_eval.erl32
-rw-r--r--lib/stdlib/src/erl_expand_records.erl19
-rw-r--r--lib/stdlib/src/erl_internal.erl3
-rw-r--r--lib/stdlib/src/erl_lint.erl57
-rw-r--r--lib/stdlib/src/erl_parse.yrl12
-rw-r--r--lib/stdlib/src/erl_pp.erl10
-rw-r--r--lib/stdlib/src/error_logger_file_h.erl25
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl25
-rw-r--r--lib/stdlib/src/escript.erl32
-rw-r--r--lib/stdlib/src/filelib.erl3
-rw-r--r--lib/stdlib/src/filename.erl48
-rw-r--r--lib/stdlib/src/gen.erl26
-rw-r--r--lib/stdlib/src/gen_event.erl15
-rw-r--r--lib/stdlib/src/gen_fsm.erl43
-rw-r--r--lib/stdlib/src/gen_server.erl33
-rw-r--r--lib/stdlib/src/lib.erl4
-rw-r--r--lib/stdlib/src/ms_transform.erl19
-rw-r--r--lib/stdlib/src/otp_internal.erl151
-rw-r--r--lib/stdlib/src/qlc.erl5
-rw-r--r--lib/stdlib/src/random.erl42
-rw-r--r--lib/stdlib/src/re.erl2
-rw-r--r--lib/stdlib/src/regexp.erl557
-rw-r--r--lib/stdlib/src/shell.erl7
-rw-r--r--lib/stdlib/src/stdlib.app.src3
-rw-r--r--lib/stdlib/src/stdlib.appup.src28
-rw-r--r--lib/stdlib/src/supervisor.erl322
-rw-r--r--lib/stdlib/src/zip.erl2
-rw-r--r--lib/stdlib/test/Makefile11
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl18
-rw-r--r--lib/stdlib/test/dets_SUITE.erl195
-rw-r--r--lib/stdlib/test/digraph_utils_SUITE.erl5
-rw-r--r--lib/stdlib/test/dummy_via.erl94
-rw-r--r--lib/stdlib/test/edlin_expand_SUITE.erl10
-rw-r--r--lib/stdlib/test/epp_SUITE.erl33
-rw-r--r--lib/stdlib/test/epp_SUITE_data/bar.hrl4
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include/bar.hrl3
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include/foo.hrl4
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include_local.erl6
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl33
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl14
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl57
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl5
-rw-r--r--lib/stdlib/test/escript_SUITE.erl151
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl17
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl105
-rw-r--r--lib/stdlib/test/ets_SUITE.erl319
-rw-r--r--lib/stdlib/test/filename_SUITE.erl31
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl26
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl71
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl86
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl29
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl50
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl152
-rw-r--r--lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl1771
-rw-r--r--lib/stdlib/test/re_SUITE.erl56
-rw-r--r--lib/stdlib/test/shell_SUITE.erl43
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl64
-rw-r--r--lib/stdlib/test/stdlib_SUITE.erl63
-rw-r--r--lib/stdlib/test/supervisor_1.erl2
-rw-r--r--lib/stdlib/test/supervisor_2.erl42
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl576
-rw-r--r--lib/stdlib/test/supervisor_bridge_SUITE.erl42
-rw-r--r--lib/stdlib/test/supervisor_deadlock.erl45
-rw-r--r--lib/stdlib/test/tar_SUITE.erl31
-rw-r--r--lib/stdlib/test/unicode_SUITE.erl4
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/Makefile9
-rw-r--r--lib/syntax_tools/doc/overview.edoc6
-rw-r--r--lib/syntax_tools/doc/src/Makefile14
-rw-r--r--lib/syntax_tools/doc/src/make.dep22
-rw-r--r--lib/syntax_tools/doc/src/notes.xml47
-rw-r--r--lib/syntax_tools/examples/Makefile4
-rw-r--r--lib/syntax_tools/src/Makefile10
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl4
-rw-r--r--lib/syntax_tools/src/erl_comment_scan.erl2
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl4
-rw-r--r--lib/syntax_tools/src/erl_recomment.erl4
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl1931
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl4
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl8
-rw-r--r--lib/syntax_tools/src/igor.erl4
-rw-r--r--lib/syntax_tools/src/prettypr.erl4
-rw-r--r--lib/syntax_tools/test/Makefile8
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/test_server/doc/src/Makefile26
-rw-r--r--lib/test_server/doc/src/make.dep24
-rw-r--r--lib/test_server/doc/src/notes.xml192
-rw-r--r--lib/test_server/doc/src/test_server.xml2
-rw-r--r--lib/test_server/src/Makefile20
-rwxr-xr-x[l---------]lib/test_server/src/config.guess1520
-rwxr-xr-x[l---------]lib/test_server/src/config.sub1631
-rw-r--r--lib/test_server/src/configure.in34
-rw-r--r--lib/test_server/src/erl2html2.erl53
-rwxr-xr-x[l---------]lib/test_server/src/install-sh520
-rw-r--r--lib/test_server/src/test_server.app.src2
-rw-r--r--lib/test_server/src/test_server.erl958
-rw-r--r--lib/test_server/src/test_server_ctrl.erl684
-rw-r--r--lib/test_server/src/test_server_h.erl46
-rw-r--r--lib/test_server/src/test_server_node.erl33
-rw-r--r--lib/test_server/src/test_server_sup.erl70
-rw-r--r--lib/test_server/src/ts.erl100
-rw-r--r--lib/test_server/src/ts.hrl1
-rw-r--r--lib/test_server/src/ts_autoconf_win32.erl1
-rw-r--r--lib/test_server/src/ts_erl_config.erl71
-rw-r--r--lib/test_server/src/ts_install.erl142
-rw-r--r--lib/test_server/src/ts_install_cth.erl48
-rw-r--r--lib/test_server/src/ts_lib.erl48
-rw-r--r--lib/test_server/src/ts_make.erl12
-rw-r--r--lib/test_server/src/ts_run.erl29
-rw-r--r--lib/test_server/test/Makefile10
-rw-r--r--lib/test_server/test/test_server_SUITE_data/Makefile.src7
-rw-r--r--lib/test_server/vsn.mk3
-rw-r--r--lib/toolbar/doc/src/Makefile14
-rw-r--r--lib/toolbar/doc/src/make.dep26
-rw-r--r--lib/toolbar/doc/src/notes.xml37
-rw-r--r--lib/toolbar/doc/src/toolbar.xml7
-rw-r--r--lib/toolbar/doc/src/toolbar_chapter.xml7
-rw-r--r--lib/toolbar/src/Makefile8
-rw-r--r--lib/toolbar/src/canvasbutton.erl5
-rw-r--r--lib/toolbar/src/toolbar.erl3
-rw-r--r--lib/toolbar/src/toolbar_graphics.erl5
-rw-r--r--lib/toolbar/src/toolbar_toolconfig.erl7
-rw-r--r--lib/toolbar/vsn.mk2
-rw-r--r--lib/tools/c_src/Makefile.in37
-rw-r--r--lib/tools/c_src/erl_memory.c9
-rw-r--r--lib/tools/doc/src/Makefile14
-rw-r--r--lib/tools/doc/src/eprof.xml12
-rw-r--r--lib/tools/doc/src/make.dep33
-rw-r--r--lib/tools/doc/src/notes.xml104
-rw-r--r--lib/tools/emacs/Makefile24
-rw-r--r--lib/tools/emacs/erlang-flymake.el3
-rw-r--r--lib/tools/emacs/erlang.el62
-rw-r--r--lib/tools/emacs/test.erl.indented43
-rw-r--r--lib/tools/emacs/test.erl.orig43
-rw-r--r--lib/tools/examples/Makefile4
-rw-r--r--lib/tools/priv/Makefile6
-rw-r--r--lib/tools/src/Makefile8
-rw-r--r--lib/tools/src/cover.erl4
-rw-r--r--lib/tools/src/fprof.erl21
-rw-r--r--lib/tools/src/xref_compiler.erl9
-rw-r--r--lib/tools/src/xref_reader.erl25
-rw-r--r--lib/tools/src/xref_utils.erl4
-rw-r--r--lib/tools/test/Makefile8
-rw-r--r--lib/tools/test/cover_SUITE.erl64
-rw-r--r--lib/tools/test/cover_SUITE_data/otp_6115/f1.erl11
-rw-r--r--lib/tools/test/eprof_SUITE.erl10
-rw-r--r--lib/tools/test/eprof_SUITE_data/ed.script2
-rw-r--r--lib/tools/test/eprof_SUITE_data/eed.erl91
-rw-r--r--lib/tools/test/fprof_SUITE.erl18
-rw-r--r--lib/tools/test/lcnt_SUITE.erl3
-rw-r--r--lib/tools/test/xref_SUITE.erl113
-rw-r--r--lib/tools/test/xref_SUITE_data/fun_mfa_r14.beambin0 -> 1116 bytes
-rw-r--r--lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl18
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/tv/doc/src/Makefile99
-rw-r--r--lib/tv/doc/src/make.dep32
-rw-r--r--lib/tv/doc/src/notes.xml35
-rw-r--r--lib/tv/doc/src/table_visualizer_chapter.xml8
-rw-r--r--lib/tv/doc/src/tv.xml8
-rw-r--r--lib/tv/priv/Makefile4
-rw-r--r--lib/tv/src/Makefile8
-rw-r--r--lib/tv/src/tv_db.erl6
-rw-r--r--lib/tv/src/tv_db_search.erl46
-rw-r--r--lib/tv/src/tv_etsread.erl5
-rw-r--r--lib/tv/src/tv_info.erl10
-rw-r--r--lib/tv/src/tv_ip.erl8
-rw-r--r--lib/tv/src/tv_main.erl16
-rw-r--r--lib/tv/src/tv_mnesia_rpc.erl2
-rw-r--r--lib/tv/src/tv_new_table.erl12
-rw-r--r--lib/tv/src/tv_nodewin.erl11
-rw-r--r--lib/tv/src/tv_pb.erl5
-rw-r--r--lib/tv/src/tv_pb_funcs.erl8
-rw-r--r--lib/tv/src/tv_pc.erl3
-rw-r--r--lib/tv/src/tv_pc_menu_handling.erl6
-rw-r--r--lib/tv/src/tv_pd.erl7
-rw-r--r--lib/tv/src/tv_pd_display.erl9
-rw-r--r--lib/tv/src/tv_pd_frames.erl4
-rw-r--r--lib/tv/src/tv_pd_scale.erl4
-rw-r--r--lib/tv/src/tv_pg.erl3
-rw-r--r--lib/tv/src/tv_pg_gridfcns.erl6
-rw-r--r--lib/tv/src/tv_poll_dialog.erl10
-rw-r--r--lib/tv/src/tv_pw.erl3
-rw-r--r--lib/tv/src/tv_pw_window.erl6
-rw-r--r--lib/tv/src/tv_rec_edit.erl12
-rw-r--r--lib/tv/src/tv_utils.erl5
-rw-r--r--lib/tv/vsn.mk2
-rw-r--r--lib/typer/src/Makefile8
-rw-r--r--lib/typer/src/typer.erl29
-rw-r--r--lib/typer/vsn.mk2
-rw-r--r--lib/webtool/doc/src/Makefile18
-rw-r--r--lib/webtool/doc/src/make.dep20
-rw-r--r--lib/webtool/doc/src/notes.xml15
-rw-r--r--lib/webtool/priv/Makefile16
-rw-r--r--lib/webtool/src/Makefile8
-rw-r--r--lib/webtool/vsn.mk2
-rw-r--r--lib/wx/.gitignore2
-rw-r--r--lib/wx/Makefile74
-rw-r--r--lib/wx/Notes60
-rw-r--r--lib/wx/README35
-rw-r--r--lib/wx/TODO30
-rw-r--r--lib/wx/aclocal.m41872
-rw-r--r--lib/wx/api_gen/Makefile4
-rw-r--r--lib/wx/api_gen/README15
-rw-r--r--lib/wx/api_gen/gen_util.erl14
-rw-r--r--lib/wx/api_gen/gl_gen.erl22
-rw-r--r--lib/wx/api_gen/gl_gen_c.erl4
-rw-r--r--lib/wx/api_gen/gl_gen_erl.erl436
-rw-r--r--lib/wx/api_gen/gl_scan_doc.erl286
-rw-r--r--lib/wx/api_gen/glapi.conf8
-rw-r--r--lib/wx/api_gen/wx_doxygen.conf1
-rw-r--r--lib/wx/api_gen/wx_extra/wxEvtHandler.erl28
-rw-r--r--lib/wx/api_gen/wx_gen.erl9
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl53
-rw-r--r--lib/wx/api_gen/wx_gen_erl.erl576
-rw-r--r--lib/wx/api_gen/wxapi.conf71
-rw-r--r--lib/wx/c_src/Makefile.in31
-rw-r--r--lib/wx/c_src/egl_impl.cpp14
-rw-r--r--lib/wx/c_src/gen/gl_fdefs.h886
-rw-r--r--lib/wx/c_src/gen/gl_finit.h456
-rw-r--r--lib/wx/c_src/gen/gl_funcs.cpp2896
-rw-r--r--lib/wx/c_src/gen/glu_finit.h2
-rw-r--r--lib/wx/c_src/gen/wxe_derived_dest.h23
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp62
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp212
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h5473
-rw-r--r--lib/wx/c_src/wxe_driver.c22
-rw-r--r--lib/wx/c_src/wxe_impl.cpp24
-rw-r--r--lib/wx/c_src/wxe_return.cpp12
-rw-r--r--lib/wx/c_src/wxe_return.h4
-rwxr-xr-xlib/wx/configure.in147
-rw-r--r--lib/wx/doc/src/Makefile85
-rw-r--r--lib/wx/doc/src/make.dep13
-rw-r--r--lib/wx/doc/src/notes.xml48
-rw-r--r--lib/wx/examples/Makefile26
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/demo/Makefile33
-rw-r--r--lib/wx/examples/demo/demo.erl8
-rw-r--r--lib/wx/examples/demo/ex_aui.erl8
-rw-r--r--lib/wx/examples/demo/ex_button.erl8
-rw-r--r--lib/wx/examples/demo/ex_canvas.erl8
-rw-r--r--lib/wx/examples/demo/ex_canvas_paint.erl8
-rw-r--r--lib/wx/examples/demo/ex_choices.erl8
-rw-r--r--lib/wx/examples/demo/ex_cursor.erl8
-rw-r--r--lib/wx/examples/demo/ex_dialogs.erl8
-rw-r--r--lib/wx/examples/demo/ex_frame_utils.erl8
-rw-r--r--lib/wx/examples/demo/ex_gauge.erl8
-rw-r--r--lib/wx/examples/demo/ex_gl.erl8
-rw-r--r--lib/wx/examples/demo/ex_graphicsContext.erl8
-rw-r--r--lib/wx/examples/demo/ex_grid.erl8
-rw-r--r--lib/wx/examples/demo/ex_htmlWindow.erl8
-rw-r--r--lib/wx/examples/demo/ex_listCtrl.erl7
-rw-r--r--lib/wx/examples/demo/ex_notebook.erl9
-rw-r--r--lib/wx/examples/demo/ex_pickers.erl9
-rw-r--r--lib/wx/examples/demo/ex_popupMenu.erl9
-rw-r--r--lib/wx/examples/demo/ex_radioBox.erl7
-rw-r--r--lib/wx/examples/demo/ex_sashWindow.erl8
-rw-r--r--lib/wx/examples/demo/ex_sizers.erl8
-rw-r--r--lib/wx/examples/demo/ex_slider.erl8
-rw-r--r--lib/wx/examples/demo/ex_splitterWindow.erl8
-rw-r--r--lib/wx/examples/demo/ex_static.erl8
-rw-r--r--lib/wx/examples/demo/ex_textCtrl.erl8
-rw-r--r--lib/wx/examples/demo/ex_treeCtrl.erl8
-rw-r--r--lib/wx/examples/simple/Makefile30
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/hello.erl2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/menu.erl2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/minimal.erl2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/simple/sample.xpm0
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/Makefile33
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku.erl2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku.hrl2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku_board.erl8
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku_game.erl2
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/sudoku/sudoku_gui.erl8
-rw-r--r--[-rwxr-xr-x]lib/wx/examples/xrc/Makefile17
-rw-r--r--lib/wx/include/gl.hrl1329
-rw-r--r--lib/wx/include/glu.hrl4
-rw-r--r--lib/wx/include/wx.hrl448
-rwxr-xr-xlib/wx/install.es302
-rw-r--r--lib/wx/src/Makefile37
-rw-r--r--lib/wx/src/gen/gl.erl17693
-rw-r--r--lib/wx/src/gen/glu.erl667
-rw-r--r--lib/wx/src/gen/wxAcceleratorEntry.erl47
-rw-r--r--lib/wx/src/gen/wxAcceleratorTable.erl14
-rw-r--r--lib/wx/src/gen/wxArtProvider.erl24
-rw-r--r--lib/wx/src/gen/wxAuiDockArt.erl4
-rw-r--r--lib/wx/src/gen/wxAuiManager.erl130
-rw-r--r--lib/wx/src/gen/wxAuiManagerEvent.erl46
-rw-r--r--lib/wx/src/gen/wxAuiNotebook.erl100
-rw-r--r--lib/wx/src/gen/wxAuiNotebookEvent.erl22
-rw-r--r--lib/wx/src/gen/wxAuiPaneInfo.erl332
-rw-r--r--lib/wx/src/gen/wxAuiTabArt.erl4
-rw-r--r--lib/wx/src/gen/wxBitmap.erl152
-rw-r--r--lib/wx/src/gen/wxBitmapButton.erl56
-rw-r--r--lib/wx/src/gen/wxBitmapDataObject.erl32
-rw-r--r--lib/wx/src/gen/wxBoxSizer.erl12
-rw-r--r--lib/wx/src/gen/wxBrush.erl55
-rw-r--r--lib/wx/src/gen/wxBufferedDC.erl78
-rw-r--r--lib/wx/src/gen/wxBufferedPaintDC.erl45
-rw-r--r--lib/wx/src/gen/wxButton.erl42
-rw-r--r--lib/wx/src/gen/wxCalendarCtrl.erl114
-rw-r--r--lib/wx/src/gen/wxCalendarDateAttr.erl112
-rw-r--r--lib/wx/src/gen/wxCalendarEvent.erl10
-rw-r--r--lib/wx/src/gen/wxCaret.erl62
-rw-r--r--lib/wx/src/gen/wxCheckBox.erl59
-rw-r--r--lib/wx/src/gen/wxCheckListBox.erl33
-rw-r--r--lib/wx/src/gen/wxChildFocusEvent.erl7
-rw-r--r--lib/wx/src/gen/wxChoice.erl46
-rw-r--r--lib/wx/src/gen/wxChoicebook.erl114
-rw-r--r--lib/wx/src/gen/wxClientDC.erl23
-rw-r--r--lib/wx/src/gen/wxClipboard.erl46
-rw-r--r--lib/wx/src/gen/wxCloseEvent.erl25
-rw-r--r--lib/wx/src/gen/wxColourData.erl29
-rw-r--r--lib/wx/src/gen/wxColourDialog.erl29
-rw-r--r--lib/wx/src/gen/wxColourPickerCtrl.erl53
-rw-r--r--lib/wx/src/gen/wxColourPickerEvent.erl7
-rw-r--r--lib/wx/src/gen/wxComboBox.erl92
-rw-r--r--lib/wx/src/gen/wxCommandEvent.erl31
-rw-r--r--lib/wx/src/gen/wxContextMenuEvent.erl10
-rw-r--r--lib/wx/src/gen/wxControl.erl10
-rw-r--r--lib/wx/src/gen/wxControlWithItems.erl67
-rw-r--r--lib/wx/src/gen/wxCursor.erl37
-rw-r--r--lib/wx/src/gen/wxDC.erl376
-rw-r--r--lib/wx/src/gen/wxDataObject.erl4
-rw-r--r--lib/wx/src/gen/wxDateEvent.erl7
-rw-r--r--lib/wx/src/gen/wxDatePickerCtrl.erl33
-rw-r--r--lib/wx/src/gen/wxDialog.erl66
-rw-r--r--lib/wx/src/gen/wxDirDialog.erl31
-rw-r--r--lib/wx/src/gen/wxDirPickerCtrl.erl42
-rw-r--r--lib/wx/src/gen/wxDisplayChangedEvent.erl4
-rw-r--r--lib/wx/src/gen/wxEraseEvent.erl7
-rw-r--r--lib/wx/src/gen/wxEvent.erl34
-rw-r--r--lib/wx/src/gen/wxEvtHandler.erl30
-rw-r--r--lib/wx/src/gen/wxFileDataObject.erl14
-rw-r--r--lib/wx/src/gen/wxFileDialog.erl63
-rw-r--r--lib/wx/src/gen/wxFileDirPickerEvent.erl7
-rw-r--r--lib/wx/src/gen/wxFilePickerCtrl.erl44
-rw-r--r--lib/wx/src/gen/wxFindReplaceData.erl29
-rw-r--r--lib/wx/src/gen/wxFindReplaceDialog.erl29
-rw-r--r--lib/wx/src/gen/wxFlexGridSizer.erl61
-rw-r--r--lib/wx/src/gen/wxFocusEvent.erl7
-rw-r--r--lib/wx/src/gen/wxFont.erl102
-rw-r--r--lib/wx/src/gen/wxFontData.erl50
-rw-r--r--lib/wx/src/gen/wxFontDialog.erl17
-rw-r--r--lib/wx/src/gen/wxFontPickerCtrl.erl46
-rw-r--r--lib/wx/src/gen/wxFontPickerEvent.erl7
-rw-r--r--lib/wx/src/gen/wxFrame.erl96
-rw-r--r--lib/wx/src/gen/wxGBSizerItem.erl4
-rw-r--r--lib/wx/src/gen/wxGLCanvas.erl60
-rw-r--r--lib/wx/src/gen/wxGauge.erl62
-rw-r--r--lib/wx/src/gen/wxGenericDirCtrl.erl83
-rw-r--r--lib/wx/src/gen/wxGraphicsBrush.erl4
-rw-r--r--lib/wx/src/gen/wxGraphicsContext.erl267
-rw-r--r--lib/wx/src/gen/wxGraphicsFont.erl4
-rw-r--r--lib/wx/src/gen/wxGraphicsMatrix.erl66
-rw-r--r--lib/wx/src/gen/wxGraphicsObject.erl18
-rw-r--r--lib/wx/src/gen/wxGraphicsPath.erl124
-rw-r--r--lib/wx/src/gen/wxGraphicsPen.erl4
-rw-r--r--lib/wx/src/gen/wxGraphicsRenderer.erl51
-rw-r--r--lib/wx/src/gen/wxGrid.erl796
-rw-r--r--lib/wx/src/gen/wxGridBagSizer.erl210
-rw-r--r--lib/wx/src/gen/wxGridCellAttr.erl73
-rw-r--r--lib/wx/src/gen/wxGridCellBoolEditor.erl19
-rw-r--r--lib/wx/src/gen/wxGridCellBoolRenderer.erl8
-rw-r--r--lib/wx/src/gen/wxGridCellChoiceEditor.erl18
-rw-r--r--lib/wx/src/gen/wxGridCellEditor.erl43
-rw-r--r--lib/wx/src/gen/wxGridCellFloatEditor.erl17
-rw-r--r--lib/wx/src/gen/wxGridCellFloatRenderer.erl29
-rw-r--r--lib/wx/src/gen/wxGridCellNumberEditor.erl20
-rw-r--r--lib/wx/src/gen/wxGridCellNumberRenderer.erl8
-rw-r--r--lib/wx/src/gen/wxGridCellRenderer.erl10
-rw-r--r--lib/wx/src/gen/wxGridCellStringRenderer.erl8
-rw-r--r--lib/wx/src/gen/wxGridCellTextEditor.erl11
-rw-r--r--lib/wx/src/gen/wxGridEvent.erl28
-rw-r--r--lib/wx/src/gen/wxGridSizer.erl43
-rw-r--r--lib/wx/src/gen/wxHelpEvent.erl22
-rw-r--r--lib/wx/src/gen/wxHtmlEasyPrinting.erl74
-rw-r--r--lib/wx/src/gen/wxHtmlLinkEvent.erl7
-rw-r--r--lib/wx/src/gen/wxHtmlWindow.erl92
-rw-r--r--lib/wx/src/gen/wxIcon.erl37
-rw-r--r--lib/wx/src/gen/wxIconBundle.erl42
-rw-r--r--lib/wx/src/gen/wxIconizeEvent.erl7
-rw-r--r--lib/wx/src/gen/wxIdleEvent.erl30
-rw-r--r--lib/wx/src/gen/wxImage.erl452
-rw-r--r--lib/wx/src/gen/wxImageList.erl82
-rw-r--r--lib/wx/src/gen/wxJoystickEvent.erl55
-rw-r--r--lib/wx/src/gen/wxKeyEvent.erl46
-rw-r--r--lib/wx/src/gen/wxLayoutAlgorithm.erl35
-rw-r--r--lib/wx/src/gen/wxListBox.erl66
-rw-r--r--lib/wx/src/gen/wxListCtrl.erl300
-rw-r--r--lib/wx/src/gen/wxListEvent.erl43
-rw-r--r--lib/wx/src/gen/wxListItem.erl89
-rw-r--r--lib/wx/src/gen/wxListItemAttr.erl38
-rw-r--r--lib/wx/src/gen/wxListView.erl34
-rw-r--r--lib/wx/src/gen/wxListbook.erl114
-rw-r--r--lib/wx/src/gen/wxLogNull.erl8
-rw-r--r--lib/wx/src/gen/wxMDIChildFrame.erl45
-rw-r--r--lib/wx/src/gen/wxMDIClientWindow.erl26
-rw-r--r--lib/wx/src/gen/wxMDIParentFrame.erl60
-rw-r--r--lib/wx/src/gen/wxMask.erl46
-rw-r--r--lib/wx/src/gen/wxMaximizeEvent.erl4
-rw-r--r--lib/wx/src/gen/wxMemoryDC.erl29
-rw-r--r--lib/wx/src/gen/wxMenu.erl334
-rw-r--r--lib/wx/src/gen/wxMenuBar.erl89
-rw-r--r--lib/wx/src/gen/wxMenuEvent.erl13
-rw-r--r--lib/wx/src/gen/wxMenuItem.erl99
-rw-r--r--lib/wx/src/gen/wxMessageDialog.erl17
-rw-r--r--lib/wx/src/gen/wxMiniFrame.erl30
-rw-r--r--lib/wx/src/gen/wxMirrorDC.erl21
-rw-r--r--lib/wx/src/gen/wxMouseCaptureChangedEvent.erl7
-rw-r--r--lib/wx/src/gen/wxMouseEvent.erl127
-rw-r--r--lib/wx/src/gen/wxMoveEvent.erl7
-rw-r--r--lib/wx/src/gen/wxMultiChoiceDialog.erl24
-rw-r--r--lib/wx/src/gen/wxNavigationKeyEvent.erl28
-rw-r--r--lib/wx/src/gen/wxNcPaintEvent.erl4
-rw-r--r--lib/wx/src/gen/wxNotebook.erl123
-rw-r--r--lib/wx/src/gen/wxNotebookEvent.erl16
-rw-r--r--lib/wx/src/gen/wxNotifyEvent.erl13
-rw-r--r--lib/wx/src/gen/wxPageSetupDialog.erl21
-rw-r--r--lib/wx/src/gen/wxPageSetupDialogData.erl111
-rw-r--r--lib/wx/src/gen/wxPaintDC.erl23
-rw-r--r--lib/wx/src/gen/wxPaintEvent.erl4
-rw-r--r--lib/wx/src/gen/wxPalette.erl27
-rw-r--r--lib/wx/src/gen/wxPaletteChangedEvent.erl10
-rw-r--r--lib/wx/src/gen/wxPanel.erl32
-rw-r--r--lib/wx/src/gen/wxPasswordEntryDialog.erl18
-rw-r--r--lib/wx/src/gen/wxPen.erl54
-rw-r--r--lib/wx/src/gen/wxPickerBase.erl52
-rw-r--r--lib/wx/src/gen/wxPostScriptDC.erl28
-rw-r--r--lib/wx/src/gen/wxPreviewCanvas.erl4
-rw-r--r--lib/wx/src/gen/wxPreviewControlBar.erl29
-rw-r--r--lib/wx/src/gen/wxPreviewFrame.erl30
-rw-r--r--lib/wx/src/gen/wxPrintData.erl80
-rw-r--r--lib/wx/src/gen/wxPrintDialog.erl34
-rw-r--r--lib/wx/src/gen/wxPrintDialogData.erl83
-rw-r--r--lib/wx/src/gen/wxPrintPreview.erl67
-rw-r--r--lib/wx/src/gen/wxPrinter.erl45
-rw-r--r--lib/wx/src/gen/wxPrintout.erl66
-rw-r--r--lib/wx/src/gen/wxProgressDialog.erl32
-rw-r--r--lib/wx/src/gen/wxQueryNewPaletteEvent.erl10
-rw-r--r--lib/wx/src/gen/wxRadioBox.erl118
-rw-r--r--lib/wx/src/gen/wxRadioButton.erl38
-rw-r--r--lib/wx/src/gen/wxRegion.erl166
-rw-r--r--lib/wx/src/gen/wxSashEvent.erl19
-rw-r--r--lib/wx/src/gen/wxSashLayoutWindow.erl59
-rw-r--r--lib/wx/src/gen/wxSashWindow.erl56
-rw-r--r--lib/wx/src/gen/wxScreenDC.erl20
-rw-r--r--lib/wx/src/gen/wxScrollBar.erl56
-rw-r--r--lib/wx/src/gen/wxScrollEvent.erl10
-rw-r--r--lib/wx/src/gen/wxScrollWinEvent.erl10
-rw-r--r--lib/wx/src/gen/wxScrolledWindow.erl67
-rw-r--r--lib/wx/src/gen/wxSetCursorEvent.erl19
-rw-r--r--lib/wx/src/gen/wxShowEvent.erl10
-rw-r--r--lib/wx/src/gen/wxSingleChoiceDialog.erl27
-rw-r--r--lib/wx/src/gen/wxSizeEvent.erl7
-rw-r--r--lib/wx/src/gen/wxSizer.erl402
-rw-r--r--lib/wx/src/gen/wxSizerFlags.erl46
-rw-r--r--lib/wx/src/gen/wxSizerItem.erl134
-rw-r--r--lib/wx/src/gen/wxSlider.erl65
-rw-r--r--lib/wx/src/gen/wxSpinButton.erl47
-rw-r--r--lib/wx/src/gen/wxSpinCtrl.erl71
-rw-r--r--lib/wx/src/gen/wxSpinEvent.erl10
-rw-r--r--lib/wx/src/gen/wxSplashScreen.erl25
-rw-r--r--lib/wx/src/gen/wxSplitterEvent.erl19
-rw-r--r--lib/wx/src/gen/wxSplitterWindow.erl115
-rw-r--r--lib/wx/src/gen/wxStaticBitmap.erl36
-rw-r--r--lib/wx/src/gen/wxStaticBox.erl30
-rw-r--r--lib/wx/src/gen/wxStaticBoxSizer.erl29
-rw-r--r--lib/wx/src/gen/wxStaticLine.erl37
-rw-r--r--lib/wx/src/gen/wxStaticText.erl39
-rw-r--r--lib/wx/src/gen/wxStatusBar.erl88
-rw-r--r--lib/wx/src/gen/wxStdDialogButtonSizer.erl23
-rw-r--r--lib/wx/src/gen/wxStyledTextCtrl.erl1414
-rw-r--r--lib/wx/src/gen/wxStyledTextEvent.erl76
-rw-r--r--lib/wx/src/gen/wxSysColourChangedEvent.erl4
-rw-r--r--lib/wx/src/gen/wxSystemOptions.erl93
-rw-r--r--lib/wx/src/gen/wxSystemSettings.erl33
-rw-r--r--lib/wx/src/gen/wxTaskBarIcon.erl102
-rw-r--r--lib/wx/src/gen/wxTaskBarIconEvent.erl64
-rw-r--r--lib/wx/src/gen/wxTextAttr.erl103
-rw-r--r--lib/wx/src/gen/wxTextCtrl.erl186
-rw-r--r--lib/wx/src/gen/wxTextDataObject.erl22
-rw-r--r--lib/wx/src/gen/wxTextEntryDialog.erl24
-rw-r--r--lib/wx/src/gen/wxToggleButton.erl38
-rw-r--r--lib/wx/src/gen/wxToolBar.erl269
-rw-r--r--lib/wx/src/gen/wxToolTip.erl24
-rw-r--r--lib/wx/src/gen/wxToolbook.erl114
-rw-r--r--lib/wx/src/gen/wxTopLevelWindow.erl91
-rw-r--r--lib/wx/src/gen/wxTreeCtrl.erl318
-rw-r--r--lib/wx/src/gen/wxTreeEvent.erl28
-rw-r--r--lib/wx/src/gen/wxTreebook.erl136
-rw-r--r--lib/wx/src/gen/wxUpdateUIEvent.erl61
-rw-r--r--lib/wx/src/gen/wxWindow.erl796
-rw-r--r--lib/wx/src/gen/wxWindowCreateEvent.erl4
-rw-r--r--lib/wx/src/gen/wxWindowDC.erl23
-rw-r--r--lib/wx/src/gen/wxWindowDestroyEvent.erl4
-rw-r--r--lib/wx/src/gen/wxXmlResource.erl103
-rw-r--r--lib/wx/src/gen/wx_misc.erl78
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl5473
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl5471
-rw-r--r--lib/wx/src/wx.erl162
-rw-r--r--lib/wx/src/wx_object.erl110
-rw-r--r--lib/wx/src/wxe_master.erl11
-rw-r--r--lib/wx/src/wxe_server.erl43
-rw-r--r--lib/wx/test/Makefile20
-rw-r--r--lib/wx/test/wx_basic_SUITE.erl76
-rw-r--r--lib/wx/test/wx_class_SUITE.erl16
-rw-r--r--lib/wx/test/wx_event_SUITE.erl34
-rw-r--r--lib/wx/test/wx_obj_test.erl86
-rw-r--r--lib/wx/test/wx_test_lib.hrl7
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/test_html.erl0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test2.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test3.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test4.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/test5.xml0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/testdtd.dtd0
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/examples/xml/xmerl.xml0
-rw-r--r--lib/xmerl/doc/src/Makefile16
-rw-r--r--lib/xmerl/doc/src/make.dep24
-rw-r--r--lib/xmerl/doc/src/notes.xml169
-rw-r--r--[-rwxr-xr-x]lib/xmerl/doc/src/part_notes.xml2
-rw-r--r--lib/xmerl/doc/src/xmerl_sax_parser.xml7
-rw-r--r--lib/xmerl/doc/src/xmerl_ug.xmlsrc6
-rw-r--r--[-rwxr-xr-x]lib/xmerl/include/xmerl.hrl19
-rwxr-xr-xlib/xmerl/include/xmerl_xlink.hrl26
-rw-r--r--lib/xmerl/include/xmerl_xsd.hrl2
-rw-r--r--lib/xmerl/src/Makefile19
-rw-r--r--lib/xmerl/src/xmerl.erl2
-rw-r--r--lib/xmerl/src/xmerl_lib.erl3
-rw-r--r--lib/xmerl/src/xmerl_sax_parser.erl5
-rw-r--r--lib/xmerl/src/xmerl_sax_parser_base.erlsrc453
-rw-r--r--lib/xmerl/src/xmerl_scan.erl713
-rw-r--r--lib/xmerl/src/xmerl_uri.erl4
-rw-r--r--lib/xmerl/src/xmerl_validate.erl105
-rw-r--r--lib/xmerl/src/xmerl_xpath.erl114
-rw-r--r--lib/xmerl/src/xmerl_xpath_lib.erl6
-rw-r--r--lib/xmerl/src/xmerl_xpath_parse.yrl3
-rw-r--r--lib/xmerl/src/xmerl_xpath_pred.erl11
-rw-r--r--lib/xmerl/src/xmerl_xpath_scan.erl3
-rw-r--r--lib/xmerl/src/xmerl_xsd.erl67
-rw-r--r--lib/xmerl/test/Makefile24
-rw-r--r--lib/xmerl/test/xmerl_SUITE.erl36
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/misc.tar.gzbin47340 -> 48157 bytes
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl2
-rw-r--r--lib/xmerl/test/xmerl_test_lib.erl6
-rw-r--r--[-rwxr-xr-x]lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd0
-rw-r--r--lib/xmerl/vsn.mk2
-rw-r--r--[-rwxr-xr-x]lib/xmerl/xmerl.pub0
-rw-r--r--make/otp.mk.in28
-rw-r--r--make/otp_release_targets.mk12
-rw-r--r--make/otp_subdir.mk2
-rw-r--r--make/run_make.mk4
-rw-r--r--make/target.mk36
-rwxr-xr-xotp_build358
-rw-r--r--system/COPYRIGHT25
-rw-r--r--system/README13
-rw-r--r--system/doc/design_principles/Makefile8
-rw-r--r--system/doc/design_principles/appup_cookbook.xml61
-rw-r--r--system/doc/design_principles/make.dep31
-rw-r--r--system/doc/design_principles/release_handling.xml76
-rw-r--r--system/doc/design_principles/release_structure.xml20
-rw-r--r--system/doc/design_principles/spec_proc.xml4
-rw-r--r--system/doc/design_principles/sup_princ.xml25
-rw-r--r--system/doc/efficiency_guide/Makefile8
-rw-r--r--system/doc/efficiency_guide/commoncaveats.xml16
-rw-r--r--system/doc/efficiency_guide/make.dep16
-rw-r--r--system/doc/efficiency_guide/profiling.xml59
-rw-r--r--system/doc/embedded/Makefile8
-rw-r--r--system/doc/embedded/make.dep14
-rw-r--r--system/doc/getting_started/Makefile8
-rw-r--r--system/doc/getting_started/make.dep14
-rw-r--r--system/doc/installation_guide/Makefile2
-rw-r--r--system/doc/installation_guide/make.dep13
-rw-r--r--system/doc/oam/Makefile4
-rw-r--r--system/doc/oam/make.dep26
-rw-r--r--system/doc/programming_examples/Makefile4
-rw-r--r--system/doc/programming_examples/make.dep20
-rw-r--r--system/doc/reference_manual/Makefile8
-rw-r--r--system/doc/reference_manual/code_loading.xml6
-rw-r--r--system/doc/reference_manual/distributed.xml6
-rw-r--r--system/doc/reference_manual/expressions.xml40
-rw-r--r--system/doc/reference_manual/macros.xml4
-rw-r--r--system/doc/reference_manual/make.dep16
-rw-r--r--system/doc/reference_manual/modules.xml10
-rw-r--r--[-rwxr-xr-x]system/doc/reference_manual/typespec.xml2
-rw-r--r--system/doc/system_architecture_intro/Makefile8
-rw-r--r--system/doc/system_architecture_intro/make.dep13
-rw-r--r--system/doc/system_principles/Makefile8
-rw-r--r--system/doc/system_principles/create_target.xml497
-rw-r--r--system/doc/system_principles/create_target.xmlsrc267
-rw-r--r--system/doc/system_principles/make.dep14
-rw-r--r--system/doc/top/Makefile12
-rw-r--r--system/doc/top/src/erl_html_tools.erl10
-rw-r--r--system/doc/tutorial/Makefile8
-rw-r--r--system/doc/tutorial/c_portdriver.xmlsrc8
-rw-r--r--system/doc/tutorial/make.dep35
-rw-r--r--xcomp/README.md36
-rw-r--r--xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf9
-rw-r--r--xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf15
-rw-r--r--xcomp/erl-xcomp-mips-linux.conf9
-rw-r--r--xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf258
-rw-r--r--xcomp/erl-xcomp-vars.sh2
-rw-r--r--xcomp/erl-xcomp-vxworks_ppc32.conf9
-rw-r--r--xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf9
-rw-r--r--xcomp/erl-xcomp.conf.template9
3677 files changed, 272122 insertions, 175273 deletions
diff --git a/.gitignore b/.gitignore
index e5f0869f27..0986bb6e4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,9 +86,6 @@ lib/os_mon/priv/obj/win32/
lib/runtime_tools/c_src/win32/
lib/runtime_tools/priv/lib/
lib/runtime_tools/priv/obj/
-lib/ssl/c_src/win32/
-lib/ssl/priv/bin/win32/
-lib/ssl/priv/obj/win32/
lib/tools/bin/win32/
lib/tools/c_src/win32/
lib/tools/obj/win32/
@@ -100,6 +97,9 @@ make/win32/
# Used by ic & orber & cos* applications.
IDL-GENERATED
+# Used by applications that run javadoc (e.g. ic).
+JAVADOC-GENERATED
+
# Anchored from $ERL_TOP
/bin
/config.log
@@ -110,6 +110,7 @@ IDL-GENERATED
!/bootstrap/bin/*.boot
/bootstrap/lib/asn1
+/bootstrap/lib/common_test
/bootstrap/lib/hipe
/bootstrap/lib/ic
/bootstrap/lib/orber
@@ -119,6 +120,7 @@ IDL-GENERATED
/bootstrap/lib/syntax_tools
/bootstrap/lib/test_server
/bootstrap/lib/wx
+/bootstrap/lib/xmerl
/Makefile
/configure
@@ -284,13 +286,6 @@ IDL-GENERATED
/lib/os_mon/mibs/v1/OTP*.mib.v1
/lib/os_mon/priv/mibs/OTP*.bin
-# public_key
-
-/lib/public_key/asn1/*.asn1db
-/lib/public_key/asn1/*.erl
-/lib/public_key/asn1/*.hrl
-/lib/public_key/include/OTP-PUB-KEY.hrl
-
# ssh
/lib/ssh/src/*.asn1db
@@ -299,14 +294,6 @@ IDL-GENERATED
/lib/ssh/src/PKCS-1.erl
/lib/ssh/src/PKCS-1.hrl
-# ssl
-
-/lib/ssl/pkix/*.asn1db
-/lib/ssl/include/OTP-PKIX.hrl
-/lib/ssl/pkix/OTP-PKIX.erl
-/lib/ssl/pkix/OTP-PKIX.hrl
-/lib/ssl/pkix/ssl_pkix_oid.erl
-
# stdlib
/lib/stdlib/src/erl_parse.erl
@@ -337,6 +324,7 @@ IDL-GENERATED
/system/doc/top/PR.template
/system/doc/top/erlresolvelinks.js
/system/doc/programming_examples/funs.xml
+/system/doc/system_principles/create_target.xml
/system/doc/tutorial/c_port.xml
/system/doc/tutorial/c_portdriver.xml
/system/doc/tutorial/cnode.xml
diff --git a/INSTALL-WIN32.md b/INSTALL-WIN32.md
index 59b9086c39..ff253d3dfa 100644
--- a/INSTALL-WIN32.md
+++ b/INSTALL-WIN32.md
@@ -6,29 +6,31 @@ Introduction
This file describes how to build the Erlang emulator and the OTP
libraries on Windows. The instructions apply to versions of Windows
-supporting the Cygwin emulated gnuish environment for Windows. We've
-built on the following platforms: Windows 2000 Professional, Windows
-2003 server, Windows XP Home/Professional, and Windows Vista. Any
-Windows95'ish platform will surely get you into trouble, what I'm not
-sure of, but it certainly will...
-
-The procedure described uses Cygwin as a build environment, you run
-the bash shell in Cygwin and uses gnu make/configure/autoconf etc to
-do the build. The emulator C-source code is, however, mostly compiled
-with Microsoft Visual C++â„¢, producing a native Windows binary. This
-is the same procedure as we use to build the pre-built binaries. The
-fact that we use VC++ and not gcc is explained further in the FAQ
-section.
+supporting the Cygwin emulated gnuish environment for Windows or the
+Msys ditto. We've built on the following platforms: Windows 2003
+server, Windows XP Home/Professional, Windows Vista and Windows 7 (32
+and 64 bit). You can probably build on Windows 2000, but you will not
+be able to install the latest Microsoft SDK, so you have to go back to
+some earlier compiler. Any Windows95'ish platform will surely get you
+into trouble, what I'm not sure of, but it certainly will...
+
+The procedure described uses either Cygwin or Msys as a build
+environment, you run the bash shell in Cygwin/Msys and use gnu
+make/configure/autoconf etc to do the build. The emulator C-source
+code is, however, mostly compiled with Microsoft Visual C++â„¢,
+producing a native Windows binary. This is the same procedure as we
+use to build the pre-built binaries. The fact that we use VC++ and not
+gcc is explained further in the FAQ section.
I describe the build procedure to make it possible for open source
customers to build the emulator, given that they have the needed
tools. The binary Windows releases is still a preferred alternative if
one does not have Microsoft's development tools and/or don't want to
-install Cygwin.
+install Cygwin or Msys.
-To use Cygwin, one needs basic experience from a Unix environment, if
+To use Cygwin/Msys, one needs basic experience from a Unix environment, if
one does not know how to set environment variables, run programs etc
-in a Unix environment, one will be quite lost in the Cygwin
+in a Unix environment, one will be quite lost in the Cygwin os Msys
ditto. I can unfortunately not teach all the world how to use
Cygwin and bash, neither how to install Cygwin nor perform basic tasks
on a computer. Please refer to other documentation on the net for
@@ -41,11 +43,11 @@ to make the Erlang/OTP distribution for Windows better. Please submit
any suggestions and patches to the appropriate [mailing lists] [1] to let
them find their way into the next version of Erlang. If making changes
to the build system (like makefiles etc) please bear in mind that the
-same makefiles are used on Unix/VxWorks/OSEDelta, so that your changes
+same makefiles are used on Unix/VxWorks, so that your changes
don't break other platforms. That of course goes for C-code too, system
specific code resides in the `$ERL_TOP/erts/emulator/sys/win32` and
`$ERL_TOP/erts/etc/win32` directories mostly. The
-`$ERL_TOP/erts/emulator/beam directory` is for common code.
+`$ERL_TOP/erts/emulator/beam` directory is for common code.
Before the R9C release of Erlang/OTP, the Windows release was built
partly on a Unix (Solaris) box and partly on a Windows box, using Perl
@@ -61,6 +63,21 @@ their problems, please try to solve the problems and submit
solutions/workarounds. Remember, it's all about sharing, not about
demanding...
+Starting with R15B, our build system runs both on Cygwin and Msys
+(MinGW's fork of an early cygwin version). Msys is a smaller package
+to install and may on some machines run slightly faster. If Cygwin
+gives you trouble, try Msys instead, and v.v. Beginning with R15B
+there is also a native 64bit version of Erlang for 64bit Windows 7
+(only). These instructions apply to both the 32bit VM and the 64bit
+ditto.
+
+Note that even if you build a 64bit VM, most of the directories and
+files involved are still named win32. You can view the name win32 as
+meaning any windows version not beeing 16bit. A few occurences of the
+name Win64 are however present in the system, for example the
+installation file for a 64 bit windows version of Erlang is by default
+named `otp_win64_<version>.exe`.
+
Lets go then, I'll start with a little FAQ, based on in house questions
and misunderstandings.
@@ -70,10 +87,13 @@ Frequently Asked Questions
* Q: So, now I can build Erlang using GCC on Windows?
- A: No, unfortunately not. You'll need Microsoft's Visual C++ still, a
- Bourne-shell script (cc.sh) wraps the Visual C++ compiler and runs it
- from within the Cygwin environment. All other tools needed to build
- Erlang are free-ware/open source, but not the C compiler.
+ A: No, unfortunately not. You'll need Microsoft's Visual C++
+ still, a Bourne-shell script (cc.sh) wraps the Visual C++ compiler
+ and runs it from within the Cygwin environment. All other tools
+ needed to build Erlang are free-ware/open source, but not the C
+ compiler. The Windows SDK is however enough to build Erlang, you
+ do not need to buy Visual C++, just download the SDK (SDK version
+ 7.1 == Visual studio 2010).
* Q: Why haven't you got rid of VC++ then, you \*\*\*\*\*\*?
@@ -83,18 +103,22 @@ Frequently Asked Questions
directories). Unfortunately the development of the SMP version for
Windows broke the mingw build and we chose to focus on the VC++ build
as the performance has been much better in the VC++ versions. The
- mingw build will be back, but as long as VC++ gives better
+ mingw build will possibly be back, but as long as VC++ gives better
performance, the commercial build will be a VC++ one.
-* Q: OK, VC++ you need, but now you've started to demand a very recent
+* Q: OK, you need VC++, but now you've started to demand a very recent
(and expensive) version of Visual studio, not the old and stable VC++
6.0 that was used in earlier versions. Why?
- A: The SMP version of Erlang needs features in the Visual Studio 2005.
- Can't live without them. Besides the new compiler gives the Erlang
- emulator a ~40% performance boost(!). Alternatively you can build Erlang
- successfully using the free (proprietary) Visual Studio 2008 Express
- edition C++ compiler.
+ A: Well, it's not expensive, it's free (as in free beer). Just
+ download and install the latest Windows SDK from Microsoft and all
+ the tools you need are there. The included debugger (WinDbg) is
+ also quite usable, it's what I used when porting Erlang to 64bit
+ Windows. Another reason to use the latest Microsoft compilers is
+ DLL compatibility. DLL's using a new version of the standard
+ library might not load if the VM is compiled with an old VC++
+ version, why we should aim to use the latest freely available SDK
+ and compiler.
* Q: Can/will I build a Cygwin binary with the procedure you describe?
@@ -112,15 +136,15 @@ Frequently Asked Questions
* Q: Hah, I saw you, you used GCC even though you said you didn't!
- A: OK, I admit, one of the files is compiled using Cygwin's GCC and
- the resulting object code is then converted to MS VC++ compatible coff
- using a small C hack. It's because that particular file, `beam_emu.c`
- benefits immensely from being able to use the GCC labels-as-values
- extension, which boosts emulator performance by up to 50%. That does
- unfortunately not (yet) mean that all of OTP could be compiled using
- GCC, that particular source code does not do anything system specific
- and actually is adopted to the fact that GCC is used to compile it on
- Windows.
+ A: OK, I admit, one of the files is compiled using Cygwin's or
+ MinGW's GCC and the resulting object code is then converted to MS
+ VC++ compatible coff using a small C hack. It's because that
+ particular file, `beam_emu.c` benefits immensely from being able
+ to use the GCC labels-as-values extension, which boosts emulator
+ performance by up to 50%. That does unfortunately not (yet) mean
+ that all of OTP could be compiled using GCC, that particular
+ source code does not do anything system specific and actually is
+ adopted to the fact that GCC is used to compile it on Windows.
* Q: So now there's a MS VC++ project file somewhere and I can build OTP
using the nifty VC++ GUI?
@@ -135,31 +159,36 @@ Frequently Asked Questions
* Q: So how does it all work then?
- A: Cygwin is the environment, which closely resembles the environments
- found on any Unix machine. It's almost like you had a virtual Unix
- machine inside Windows. Configure, given certain parameters, then
- creates makefiles that are used by the Cygwin gnu-make to built the
- system. Most of the actual compilers etc are not, however, Cygwin
- tools, so I've written a couple of wrappers (Bourne-shell scripts),
- which reside in `$ERL_TOP/etc/win32/cygwin_tools` and they all do
- conversion of parameters and switches common in the Unix environment
- to fit the native Windows tools. Most notable is of course the paths,
- which in Cygwin are Unix-like paths with "forward slashes" (/) and no
- drive letters, the Cygwin specific command `cygpath` is used for most
- of the path conversions. Luckily most compilers accept forward slashes
- instead of backslashes as path separators, one still have to get the
- drive letters etc right, though. The wrapper scripts are not general
- in the sense that, for example, cc.sh would understand and translates
- every possible gcc option and passes correct options to cl.exe. The
- principle is that the scripts are powerful enough to allow building of
- Erlang/OTP, no more, no less. They might need extensions to cope with
- changes during the development of Erlang, that's one of the reasons I
- made them into shell-scripts and not Perl-scripts, I believe they are
- easier to understand and change that way. I might be wrong though,
- cause another reason I didn't write them in Perl is because I've never
- liked Perl and my Perl code is no pleasant reading...
-
- In `$ERL_TOP`, there is a script called `otp_build`, that script handles
+ A: Cygwin or Msys is the environment, which closely resembles the
+ environments found on any Unix machine. It's almost like you had a
+ virtual Unix machine inside Windows. Configure, given certain
+ parameters, then creates makefiles that are used by the
+ Cygwin/Msys gnu-make to built the system. Most of the actual
+ compilers etc are not, however, Cygwin/Msys tools, so I've written
+ a couple of wrappers (Bourne-shell scripts), which reside in
+ `$ERL_TOP/etc/win32/cygwin_tools` and
+ `$ERL_TOP/etc/win32/msys_tools`. They all do conversion of
+ parameters and switches common in the Unix environment to fit the
+ native Windows tools. Most notable is of course the paths, which
+ in Cygwin/Msys are Unix-like paths with "forward slashes" (/) and
+ no drive letters, the Cygwin specific command `cygpath` is used
+ for most of the path conversions in a Cygwin environment, other
+ tools are used (when needed) in the corresponding Msys
+ environment. Luckily most compilers accept forward slashes instead
+ of backslashes as path separators, but one still have to get the drive
+ letters etc right, though. The wrapper scripts are not general in
+ the sense that, for example, cc.sh would understand and translates
+ every possible gcc option and passes correct options to
+ cl.exe. The principle is that the scripts are powerful enough to
+ allow building of Erlang/OTP, no more, no less. They might need
+ extensions to cope with changes during the development of Erlang,
+ that's one of the reasons I made them into shell-scripts and not
+ Perl-scripts, I believe they are easier to understand and change
+ that way. I might be wrong though, cause another reason I didn't
+ write them in Perl is because I've never liked Perl and my Perl
+ code is no pleasant reading...
+
+ In `$ERL_TOP`, there is a script called `otp_build`. That script handles
the hassle of giving all the right parameters to `configure`/`make` and
also helps you set up the correct environment variables to work with
the Erlang source under Cygwin.
@@ -177,17 +206,19 @@ Frequently Asked Questions
A: Yes, we use the exactly same build procedure.
-* Q: Which version of Cygwin and other tools do you use then?
+* Q: Which version of Cygwin/Msys and other tools do you use then?
- A: For Cygwin we try to use the latest releases available when
- building. What versions you use shouldn't really matter, I try to
- include workarounds for the bugs I've found in different Cygwin
- releases, please help me to add workarounds for new Cygwin-related
- bugs as soon as you encounter them. Also please do submit bug reports
- to the appropriate Cygwin developers. The Cygwin GCC we used for %OTP-REL%
- was version 3.4.4. We used VC++ 8.0 (i.e. Visual studio 2005 SP1),
- Sun's JDK 1.5.0\_17, NSIS 2.37, and Win32 OpenSSL 0.9.8e. Please read
- the next section for details on what you need.
+ A: For Cygwin and Msys alike, we try to use the latest releases
+ available when building. What versions you use shouldn't really
+ matter, I try to include workarounds for the bugs I've found in
+ different Cygwin/Msys releases, please help me add workarounds
+ for new Cygwin/Msys-related bugs as soon as you encounter
+ them. Also please do submit bug reports to the appropriate Cygwin
+ and/or Msys developers. The GCC we used for %OTP-REL% was version
+ 4.7.0 (MinGW 64bit) and 4.3.4 (Cygwin 32bit). We used VC++ 10.0
+ (i.e. Visual studio 2010), Sun's JDK 1.5.0\_17 (32bit) and Sun's
+ JDK 1.7.0\_1 (64bit), NSIS 2.46, and Win32 OpenSSL 0.9.8r. Please
+ read the next section for details on what you need.
* Q: Can you help me setup X in Cygwin?
@@ -201,24 +232,21 @@ Frequently Asked Questions
described as much as I could about the installation of the needed
tools. Once the tools are installed, building is quite easy. I also
have tried to make this instruction understandable for people with
- limited Unix experience. Cygwin is a whole new environment to some
+ limited Unix experience. Cygwin/Msys is a whole new environment to some
Windows users, why careful explanation of environment variables etc
seemed to be in place. The short story, for the experienced and
impatient is:
- * Get and install complete Cygwin (latest)
-
- * (Buy and) Install Microsoft Visual studio 2005 and SP1 (or higher)
+ * Get and install complete Cygwin (latest) or complete MinGW with msys
- * Alternatively install the free MS Visual Studio 2008 Express [msvc++]
- and the Windows SDK [32bit-SDK] or [64bit-SDK] depending on the Windows
- platform you are running.
+ * Install Microsofts Windows SDK 7.1 (and .Net 4)
- * Get and install Sun's JDK 1.4.2
+ * Get and install Sun's JDK 1.5.0 or higher
* Get and install NSIS 2.01 or higher (up to 2.46 tried and working)
- * Get and install OpenSSL 0.9.7c or higher (up to 1.0.0a tried & working)
+ * Get, build and install OpenSSL 0.9.8r or higher (up to 1.0.0a
+ tried & working) with static libs.
* Get the Erlang source distribution (from
<http://www.erlang.org/download.html>) and unpack with Cygwin's `tar`.
@@ -251,10 +279,9 @@ Tools you Need and Their Environment
------------------------------------
You need some tools to be able to build Erlang/OTP on Windows. Most
-notably you'll need Cygwin and Microsoft VC++, but you also might want
-a Java compiler, the NSIS install system and OpenSSL. Only VC++ costs
-money, but then again it costs a lot of money, I know...
-Well' here's the list:
+notably you'll need Cygwin or Msys and Microsofts Windows SDK, but
+you also might want a Java compiler, the NSIS install system and
+OpenSSL. Well' here's the list:
* Cygwin, the very latest is usually best. Get all the development
tools and of course all the basic ditto. In fact getting the complete
@@ -263,6 +290,10 @@ Well' here's the list:
sure *not* to install a Cygwin'ish Java... The Cygwin jar command is
used but Sun's Java compiler and virtual machine...
+ If you are going to build a 64bit Windows version, you should make
+ sure to get MinGW's 64bit gcc installed with cygwin. It's in one of
+ the development packages.
+
URL: <http://www.cygwin.com>
Get the installer from the web site and use that to install
@@ -302,72 +333,205 @@ Well' here's the list:
haven't tried and know of no one that has. I expect
that you use bash in all shell examples.
-* Microsoft Visual Studio 2005 SP1. Please don't skip the service
- pack! The installer might update your environment so that you can run
- the `cl` command from the bash prompt, then again it might
- not... There is always a BAT file in VC\Bin under the installation
- directory (default `C:\Program Files\Microsoft Visual Studio 8`) called
- `VCVARS32.BAT`. Either add the environment settings in that file to the
- global environment settings in Windows or add the corresponding BASH
- environment settings to your `.profile`/`.bashrc`. For example, in my case
- I could add the following to `.profile`
-
- #Visual C++ Root directory as Cygwin style pathname
- VCROOT=/cygdrive/c/Program\ Files/Microsoft\ Visual\ Studio 8
-
- # Visual C++ Root directory as Windows style pathname
- WIN_VCROOT="C:\\Program Files\\Microsoft Visual Studio 8"
-
- # The PATH variable should be Cygwin'ish
- PATH=$VCROOT/Common7/IDE:$VCROOT/VC/BIN:$VCROOT/Common7/Tools:\
- $VCROOT/Common7/Tools/bin:$VCROOT/VC/PlatformSDK/bin:$VCROOT/SDK/v2.0/bin:\
- $VCROOT/VC/VCPackages:$PATH
-
- # Lib and INCLUDE should be Windows'ish
- # Note that semicolon (;) is used to separate Windows style paths but
- # colon (:) to separate Cygwin ditto!
-
- LIBPATH=$WIN_VCROOT\\VC\\ATLMFC\\LIB
-
- LIB=$WIN_VCROOT\\VC\\ATLMFC\\LIB\;$WIN_VCROOT\\VC\\LIB\;\
- $WIN_VCROOT\\VC\\PlatformSDK\\lib\;$WIN_VCROOT\\SDK\\v2.0\\lib
-
- INCLUDE=$WIN_VCROOT\\VC\\ATLMFC\\INCLUDE\;$WIN_VCROOT\\VC\\INCLUDE\;\
- $WIN_VCROOT\\VC\\PlatformSDK\\include
-
- export PATH LIB INCLUDE
-
- Make a simple hello world and try to compile it with the `cl` command
- from within bash. If that does not work, your environment needs
- fixing. Also remember to fix up the PATH environment, especially old
- Erlang installations might have inserted quoted paths that Cygwin does
- not understand. Remove or correct such paths. There should be no
- backslashes in your path environment variable in Cygwin bash, but LIB
- and INCLUDE should contain Windows style paths with semicolon,
- drive letters and backslashes.
-
- If you wish to use Visual Studio 2008, a couple things need to be tweaked,
- namely the fact that some of the SDK stuff is installed in (by default)
- `C:\Program Files\Microsoft SDKs\v6.0A` . Just ensure that that
- `C:\Program Files\Microsoft SDKs\v6.0A\Lib` is in `LIB` and
- `C:\Program Files\Microsoft SDKs\v6.0A\Include` is in `INCLUDE`. A symptom
- of not doing this is errors about finding kernel32.lib and windows.h.
-
- Additionally, if you encounter errors about mc.exe not being found, you must
- install the entire Windows SDK (the partial SDK included in visual studio
- apparently does not include it). After installing it you'll want to add
- something like: `/c/cygdrive/Program\ Files/Microsoft\ SDKs/v7.0/bin` to
- your `PATH` to allow the environment to find mc.exe. The next Visual Studio
- (2010) is expected to include this tool.
-
- Alternatively install the free MS Visual Studio 2008 Express [msvc++] and
- the Windows SDK [32bit-SDK] or [64bit-SDK] depending on the Windows
- platform you are running, which includes the missing mc.exe message
- compiler.
-
-[msvc++]: http://download.microsoft.com/download/E/8/E/E8EEB394-7F42-4963-A2D8-29559B738298/VS2008ExpressWithSP1ENUX1504728.iso
-[32bit-SDK]: http://download.microsoft.com/download/2/E/9/2E911956-F90F-4BFB-8231-E292A7B6F287/GRMSDK_EN_DVD.iso
-[64bit-SDK]: http://download.microsoft.com/download/2/E/9/2E911956-F90F-4BFB-8231-E292A7B6F287/GRMSDKX_EN_DVD.iso
+* Alternatively you download MinGW and Msys. You'll find the latest
+ installer at:
+
+ URL: <http://sourceforge.net/projects/mingw/files/Installer/mingw-get-inst/>
+
+ Make sure to install everything they've got.
+
+ To be able to build the 64bit VM, you will also need the 64bit
+ MinGW compiler from:
+
+ URL: <http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Automated%20Builds/>
+
+ The latest version should do it. Make sure you download the
+ `mingw-w64-bin_i686-mingw_<something>.zip`, not a linux
+ version. You unzip the package on top of your MinGW installation
+ (`c:\MinGW`) and that's it.
+
+ Setting up your environment in Msys is similar to setting it up in
+ Cygwin.
+
+* Microsofts Windows SDK version 7.1 (corresponding to VC++ 10.0 and
+ Visual Studio 2010). You'll find it here:
+
+ URL: <http://www.microsoft.com/download/en/details.aspx?id=8279>
+
+ but before you install that, you need to have .Net 4 installed,
+ you'll find that here:
+
+ URL: <http://www.microsoft.com/download/en/details.aspx?id=17851>
+
+ Use the web installer for the SDK, at least when I tried
+ downloading the whole package as an image, I got SDK 7.0 instead,
+ which is not what you want...
+
+ There will be a Windows command file in `%PROGRAMFILES%\Mirosoft
+ SDKs\Windows\v7.1\Bin\SetEnv.cmd` that set's the appropriate
+ environment for a Windows command prompt. This is not appropriate
+ for bash, so you'll need to convert it to bash-style environments
+ by editing your `.bash_profile`. In my case, where the SDK is
+ installed in the default directory and `%PROGRAMFILES%` is
+ `C:\Program Files`, the commands for setting up a 32bit build
+ environment (on a 64bit or 32bit machine) look like this (in cygwin):
+
+ # Some common paths
+ C_DRV=/cygdrive/c
+ PRG_FLS=$C_DRV/Program\ Files
+
+ # nsis
+ NSIS_BIN=$PRG_FLS/NSIS
+ # java
+ JAVA_BIN=$PRG_FLS/Java/jdk1.6.0_16/bin
+
+ ##
+ ## MS SDK
+ ##
+
+ CYGWIN=nowinsymlinks
+ MVS10="$PRG_FILES/Microsoft Visual Studio 10.0"
+ WIN_MVS10="C:\\Program Files\\Microsoft Visual Studio 10.0"
+ SDK10="$PRG_FILES/Microsoft SDKs/Windows/v7.1"
+ WIN_SDK10="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1"
+
+ PATH="$NSIS_BIN:\
+ $MVS10/Common7/IDE:\
+ $MVS10/Common7/Tools:\
+ $MVS10/VC/Bin:\
+ $MVS10/VC/Bin/VCPackages:\
+ $SDK10/Bin/NETFX 4.0 Tools:\
+ $SDK10/Bin:\
+ /usr/local/bin:/usr/bin:/bin:\
+ /cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:\
+ /cygdrive/c/WINDOWS/system32/Wbem:\
+ $JAVA_BIN"
+
+ LIBPATH="$WIN_MVS10\\VC\\LIB"
+
+ LIB="$WIN_MVS10\\VC\\LIB;$WIN_SDK10\\LIB"
+
+ INCLUDE="$WIN_MVS10\\VC\\INCLUDE;$WIN_SDK10\\INCLUDE;$WIN_SDK10\\INCLUDE\\gl"
+
+ export CYGWIN PATH LIBPATH LIB INCLUDE
+
+ If you're using Msys instead, the only thing you need to change is
+ the `C_DRV` setting, which would read:
+
+ C_DRV=/c
+
+ And of course you might need to change `C:\Program Files` etc if
+ you're using a non-english version of Windows (XP). Note that in
+ later versions of Windows, the national adoptions of the program
+ files directories etc are not on the file system but only in the
+ explorer, so even if explorer says that your programs reside in
+ e.g. `C:\Program`, they might still reside in `C:\Program Files`
+ in reality...
+
+ If you are building a 64 bit version of Erlang, you should set up
+ PATHs etc a little differently. I use the following script to
+ make things work in both Cygwin and Msys:
+
+ make_winpath()
+ {
+ P=$1
+ if [ "$IN_CYGWIN" = "true" ]; then
+ cygpath -d "$P"
+ else
+ (cd "$P" && /bin/cmd //C "for %i in (".") do @echo %~fsi")
+ fi
+ }
+
+ make_upath()
+ {
+ P=$1
+ if [ "$IN_CYGWIN" = "true" ]; then
+ cygpath "$P"
+ else
+ echo "$P" | /bin/sed 's,^\([a-zA-Z]\):\\,/\L\1/,;s,\\,/,g'
+ fi
+ }
+
+ # Some common paths
+ if [ -x /usr/bin/msysinfo ]; then
+ # Without this the path conversion won't work
+ COMSPEC='C:\Windows\SysWOW64\cmd.exe'
+ MSYSTEM=MINGW32
+ export MSYSTEM COMSPEC
+ IN_CYGWIN=false
+ else
+ CYGWIN=nowinsymlinks
+ export CYGWIN
+ IN_CYGWIN=true
+ fi
+
+ if [ "$IN_CYGWIN" = "true" ]; then
+ PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:\
+ /cygdrive/c/windows/system32:/cygdrive/c/windows:/cygdrive/c/windows/system32/Wbem
+ else
+ PATH=/usr/local/bin:/mingw/bin:/bin:/c/Windows/system32:/c/Windows:\
+ /c/Windows/System32/Wbem
+ fi
+
+ if [ "$IN_CYGWIN" = "true" ]; then
+ C_DRV=/cygdrive/c
+ else
+ C_DRV=/c
+ fi
+
+ PRG_FLS64=$C_DRV/Program\ Files
+ PRG_FLS32=$C_DRV/Program\ Files\ \(x86\)
+ VISUAL_STUDIO_ROOT32=$PRG_FLS32/Microsoft\ Visual\ Studio\ 10.0
+ MS_SDK_ROOT64=$PRG_FLS64/Microsoft\ SDKs/Windows/v7.1
+
+ # Okay, now mangle the paths and get rid of spaces by using short names
+ WIN_VCROOT32=`make_winpath "$VISUAL_STUDIO_ROOT32"`
+ VCROOT32=`make_upath $WIN_VCROOT32`
+ WIN_SDKROOT64=`make_winpath "$MS_SDK_ROOT64"`
+ SDKROOT64=`make_upath $WIN_SDKROOT64`
+ WIN_PROGRAMFILES32=`make_winpath "$PRG_FLS32"`
+ PROGRAMFILES32=`make_upath $WIN_PROGRAMFILES32`
+
+ WIN_PROGRAMFILES64=`make_winpath "$PRG_FLS64"`
+ PROGRAMFILES64=`make_upath $WIN_PROGRAMFILES64`
+
+ # nsis
+ NSIS_BIN=$PROGRAMFILES32/NSIS
+ # java
+ JAVA_BIN=$PROGRAMFILES64/Java/jdk1.7.0_01/bin
+
+ ## The PATH variable should be Unix'ish
+ VCPATH=$VCROOT32/Common7/IDE:$VCROOT32/VC/BIN/amd64:$VCROOT32/Common7/Tools:\
+ $VCROOT32/VC/VCPackages:$SDKROOT64/bin/NETFX4~1.0TO/x64:$SDKROOT64/bin/x64:\
+ $SDKROOT64/bin
+
+ ## Microsoft SDK libs
+
+ LIBPATH=$WIN_VCROOT32\\VC\\LIB\\amd64
+ LIB=$WIN_VCROOT32\\VC\\LIB\\amd64\;$WIN_SDKROOT64\\LIB\\X64
+ INCLUDE=$WIN_VCROOT32\\VC\\INCLUDE\;$WIN_SDKROOT64\\include\;\
+ $WIN_SDKROOT64\\include\\gl
+
+ # Put nsis, c compiler and java in path
+ PATH=$NSIS_BIN:$VCPATH:$PATH:$JAVA_BIN
+
+ # Make sure LIB and INCLUDE is available for others
+ export PATH LIBPATH LIB INCLUDE
+
+ All this is derived from the SetEnv.cmd command file mentioned
+ earlier. The bottom line is to set the PATH so that NSIS and
+ Microsoft SDK is found before the Msys/Cygwin tools and that Java
+ is last in the PATH.
+
+ Make a simple hello world (maybe one that prints out
+ `sizeof(void *)`) and try to compile it with the `cl` command from within
+ bash. If that does not work, your environment needs fixing. Also
+ remember to fix up the PATH environment, especially old Erlang
+ installations might have inserted quoted paths that Cygwin/Msys
+ does not understand. Remove or correct such paths. There should be
+ no backslashes in your path environment variable in Cygwin bash,
+ but LIB and INCLUDE should contain Windows style paths with
+ semicolon, drive letters and backslashes.
* Sun's Java JDK 1.5.0 or higher. Our Java code (jinterface, ic) is
written for JDK 1.5.0. Get it for Windows and install it, the JRE is
@@ -378,11 +542,11 @@ Well' here's the list:
Add javac *LAST* to your path environment in bash, in my case this means:
- PATH="$PATH:/cygdrive/c/Program Files/Java/jdk1.5.0_17/bin"
+ `PATH="$PATH:/cygdrive/c/Program Files/Java/jdk1.5.0_17/bin"`
No `CLASSPATH` or anything is needed. Type `javac` at the bash prompt
and you should get a list of available Java options. Make sure by
- typing `which java` that you use the Java you installed. Note however that
+ typing `type java` that you use the Java you installed. Note however that
Cygwin's `jar.exe` is used, that's why the JDK bin-directory should be
added last in the `PATH`.
@@ -402,78 +566,104 @@ Well' here's the list:
type makensis at the bash prompt and you should get a list of options
if everything is OK.
-* OpenSSL for Windows. This is if you want the SSL and crypto
- applications to compile (and run). Go to <http://www.openssl.org>, click
- on the `Related` link and then on the `Binaries` link (upper right
- corner of the page last time I looked), you can then reach the
- "Shining Lights Productions" Web site for Windows binaries
- distributions. Get the latest 32-bit installer, or use 0.9.7c if you get
- trouble with the latest, and install to C:\OpenSSL which is where the
- Makefiles are expecting to find it. It's a nifty installer. The rest should
- be handled by `configure`, you needn't put anything in the path or anything.
-
- If you want to build openssl for windows yourself (which might be
- possible, as you wouldn't be reading this if you weren't a
- compile-it-yourself person), you either have to put the resulting
- DLL's in your path or in the windows system directory and either
- specify where you put the includes etc with the configure-parameter
- `--with-ssl=<cygwin path to the root>` or put your installation directly
- under `c:\OpenSSL`. The directory structure under the installation root
- for OpenSSL is expected to be one with subdirectories named `include`,
- `bin` and `lib`, possibly with a `VC` subdirectory of `lib` containing
- the actual `.lib` files. Note that the cygwin distributed OpenSSL cannot be
- used, it results in cygwin depending binaries and it has unix style
- archives (`.a`, not `.lib`).
+* OpenSSL. This is if you want the SSL and crypto applications to
+ compile (and run). There are prebuilt binaries available, but I
+ strongly recommend building this yourself. It's quite easy.
-* Building with wxWidgets. Download wxWidgets-2.8.9 or higher patch
- release (2.9.\* is a developer release which currently does not work
- with wxErlang).
+ First get the source from
- Install or unpack it to `DRIVE:/PATH/cygwin/opt/local/pgm`.
- Open from explorer (i.e. by double clicking the file)
- `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\build\msw\wx.dsw`
- In Microsoft Visual Studio, click File/Open/File, locate and
- open: `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\include\wx\msw\setup.h`
- enable `wxUSE_GLCANVAS`, `wxUSE_POSTSCRIPT` and `wxUSE_GRAPHICS_CONTEXT`
- Build it by clicking Build/Batch Build and select all unicode release
- (and unicode debug) packages.
+ URL: <http://openssl.org/source/>
+
+ I would recommend using 0.9.8r.
+
+ Download the tar file and unpack it (using your bash prompt) into
+ a directory of your choise.
+
+ You will need a Windowish Perl for the build. ActiveState has one:
+
+ URL: <http://www.activestate.com/activeperl/downloads>
+
+ Download and install that. Disable options to associate it with
+ the .pl suffix and/or adding things to PATH, they are not needed.
+
+ Now fire up the Microsoft Windows SDK command prompt in RELEASE
+ mode for the architecture you are going to build. The easiest is
+ to copy the shortcut from the SDKs start menu item and edit the
+ command line in the shortcut (Right click->Properties) to end with
+ `/Release`. Make sure the banner when you double click your
+ shortcut (the text in the resulting command window) says
+ `Targeting Windows XP x64 Release` if you are going to do a 64 bit
+ build and `Targeting Windows XP x86 Release` if you are building a
+ 32 bit version.
+
+ Now cd to where you unpacked the OpenSSL source using your Release
+ Windows command prompt (it should be on the same drive as where
+ you are going to install it if everything is to work smothly).
+
+ C:\> cd <some dir>
+
+ Add ActiveState (or some other windows perl, not cygwins) to your PATH:
+
+ C:\...\> set PATH=C:\Perl\bin;%PATH%
+
+ Or if you installed the 64bit perl:
+
+ C:\...\> set PATH=C:\Perl64\bin;%PATH%
- Open `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\contrib/build/stc/stc.dsw`
- and batch build all unicode packages.
+ Configure OpenSSL for 32 bit:
- If you are using Visual C++ 9.0 or higher (Visual Studio 2008 onwards) you
- will also need to convert and re-create the project dependencies in the new
- .sln "Solution" format.
+ C:\...\> perl Configure VC-WIN32 --prefix=/OpenSSL
- * Open VSC++ & the project `wxMSW-2.8.11\build\msw\wx.dsw`, accepting the
- automatic conversion to the newer VC++ format and save as
- `\wxMSW-2.8.11\build\msw\wx.sln`
+ Or for 64 bit:
- * right-click on the project, and set up the project dependencies for
- `wx.dsw` to achieve the below build order
+ C:\...\> perl Configure VC-WIN64A --prefix=/OpenSSL-Win64
- jpeg, png, tiff, zlib, regex, expat, base, net, odbc, core,
- gl, html, media, qa, adv, dbgrid, xrc, aui, richtext, xml
+ Do some setup (for 32 bit):
- Build all unicode release (and unicode debug) packages either from the
- GUI or alternatively launch a new prompt from somewhere like Start ->
- Programs -> Microsoft Visual C++ -> Visual Studio Tools -> VS2008 Cmd Prompt
- and cd to where you unpacked wxMSW
+ C:\...\> ms\do_ms
- pushd c:\wxMSW*\build\msw
- vcbuild /useenv /platform:Win32 /M4 wx.sln "Unicode Release|Win32"
- vcbuild /useenv /platform:Win32 /M4 wx.sln "Unicode Debug|Win32"
+ The same for 64 bit:
- Open VSC++ & convert `C:\wxMSW-2.8.11\contrib\build\stc\stc.dsw` to
- `C:\wxMSW-2.8.11\contrib\build\stc\stc.sln`
+ C:\...\> ms\do_win64a
- * build the unicode release (and unicode debug) packages from the GUI or
- alternatively open a VS2008 Cmd Prompt and cd to where you unpacked wxMSW
+ Then build static libraries and install:
- pushd c:\wxMSW*\contrib\build\stc
- vcbuild /useenv /platform:Win32 /M4 stc.sln "Unicode Release|Win32"
- vcbuild /useenv /platform:Win32 /M4 stc.sln "Unicode Debug|Win32"
+ C:\...\> nmake -f ms\nt.mak
+ C:\...\> nmake -f ms\nt.mak install
+ That's it - you now have your perfectly consistent static build of
+ openssl. If you want to get rid of any possibly patented
+ algorithms in the lib, just read up on the OpenSSL FAQ and follow
+ the instructions.
+
+ The installation locations chosen are where configure will look
+ for OpenSSL, so try to keep them as is.
+
+* Building with wxWidgets. Download wxWidgets-2.8.9 or higher patch
+ release (2.9.\* is a developer release which currently does not work
+ with wxErlang).
+
+ Install or unpack it to `DRIVE:/PATH/cygwin/opt/local/pgm`.
+
+ edit: `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\include\wx\msw\setup.h`
+ enable `wxUSE_GLCANVAS`, `wxUSE_POSTSCRIPT` and `wxUSE_GRAPHICS_CONTEXT`
+
+ build: From a command prompt with the VC tools available (See the
+ instructions for OpenSSL build above for help on starting the
+ proper command prompt in RELEASE mode):
+
+ C:\...\> cd C:\cygwin\opt\local\pgm\wxMSW-2.8.11\build\msw
+ C:\...\> nmake BUILD=release SHARED=0 UNICODE=1 USE_OPENGL=1 USE_GDIPLUS=1 DIR_SUFFIX_CPU= -f makefile.vc
+ C:\...\> cd C:\cygwin\opt\local\pgm\wxMSW-2.8.11\contrib\build\stc
+ C:\...\> nmake BUILD=release SHARED=0 UNICODE=1 USE_OPENGL=1 USE_GDIPLUS=1 DIR_SUFFIX_CPU= -f makefile.vc
+
+ Or - if building a 64bit version:
+
+ C:\...\> cd C:\cygwin\opt\local\pgm\wxMSW-2.8.11\build\msw
+ C:\...\> nmake TARGET_CPU=amd64 BUILD=release SHARED=0 UNICODE=1 USE_OPENGL=1 USE_GDIPLUS=1 DIR_SUFFIX_CPU= -f makefile.vc
+ C:\...\> cd C:\cygwin\opt\local\pgm\wxMSW-2.8.11\contrib\build\stc
+ C:\...\> nmake TARGET_CPU=amd64 BUILD=release SHARED=0 UNICODE=1 USE_OPENGL=1 USE_GDIPLUS=1 DIR_SUFFIX_CPU= -f makefile.vc
+
* The Erlang source distribution (from <http://www.erlang.org/download.html>).
The same as for Unix platforms. Preferably use tar from within Cygwin to
unpack the source tar.gz (`tar zxf otp_src_%OTP-REL%.tar.gz`).
@@ -499,6 +689,9 @@ Well' here's the list:
erlang system without gs (which might be okay as you probably will use
wx anyway).
+ Note that there is no special 64bit version of TCL/TK needed, you
+ can use the 32bit program even for a 64bit build.
+
The Shell Environment
---------------------
@@ -526,6 +719,12 @@ the ksh variant:
$ cd $ERL_TOP
$ eval $(./otp_build env_win32)
+If you are building a 64 bit version, you supply `otp_build` with an architecture parameter:
+
+ $ cd $ERL_TOP
+ $ eval `./otp_build env_win32 x64`
+
+
This should do the final touch to the environment and building should
be easy after this. You could run `./otp_build env_win32` without
`eval` just to see what it does, and to see that the environment it
@@ -535,10 +734,11 @@ style short names instead), the variables `OVERRIDE_TARGET`, `CC`, `CXX`,
`$ERL_TOP/erts/etc/win32/cygwin_tools/vc` and
`$ERL_TOP/erts/etc/win32/cygwin_tool` are added first in the PATH.
-Try now a `which erlc`. That should result in the erlc wrapper script
+Try now a `type erlc`. That should result in the erlc wrapper script
(which does not have the .sh extension, for reasons best kept
-untold...). It should reside in `$ERL_TOP/erts/etc/win32/cygwin_tools`.
-You could also try `which cc.sh`, which `ar.sh` etc.
+untold...). It should reside in `$ERL_TOP/erts/etc/win32/cygwin_tools`
+or `$ERL_TOP/erts/etc/win32/msys_tools`. You could also try `which
+cc.sh`, which `ar.sh` etc.
Now you're ready to build...
@@ -546,8 +746,8 @@ Now you're ready to build...
Building and Installing
-----------------------
-Now it's assumed that you have executed `` eval `./otp_build env_win32` ``
-for this particular shell...
+Now it's assumed that you have executed `` eval `./otp_build env_win32` `` or
+`` eval `./otp_build env_win32 x64` `` for this particular shell...
Building is easiest using the `otp_build` script. That script takes care
of running configure, bootstrapping etc on Windows in a simple
@@ -639,6 +839,13 @@ Lets get into more detail:
$ release/win32/otp_win32_%OTP-REL% /S
...
+ or
+
+ $ cd $ERL_TOP
+ $ release/win32/otp_win64_%OTP-REL% /S
+ ...
+
+
and after a while Erlang/OTP-%OTP-REL% will have been installed in
`C:\Program Files\erl%ERTS-VSN%\`, with shortcuts in the menu etc.
@@ -761,6 +968,22 @@ Remember that:
That's basically all you need to get going.
+Using GIT
+---------
+
+You might want to check out versions of the source code from GitHUB. That is possible directly in cygwin, but not in Msys. There is a project MsysGIT:
+
+URL:<http://code.google.com/p/msysgit/>
+
+that makes a nice Git port. The msys prompt you get from MsysGIT is
+however not compatible with the full version from MinGW, so you will
+need to check out files using MsysGIT's command prompt and then switch
+to a common Msys command prompt for building. Also all test suites
+cannot be built as MsysGIT/Msys does not handle symbolic links. To
+build test suites on Windows, you will need Cygwin for now. Hopefully
+all symbolic links will disappear from our repository soon and this
+issue will disappear.
+
Final Words
-----------
My hope is that the possibility to build the whole system on Windows
@@ -778,11 +1001,15 @@ be good. The idea to do this came from his work, so credit is well
deserved.
Of course this would have been completely impossible without the
-excellent Cygwin package. The guys at Cygnus solutions and Redhat
-deserves a huge THANKS! as well as all the other people in the free
-software community who have helped in creating the magnificent
+excellent Cygwin. The guys at Cygnus solutions and
+Redhat deserve a huge THANKS! as well as all the other people in the
+free software community who have helped in creating the magnificent
software that constitutes Cygwin.
+Also the people developing the alternative command prompt Msys and
+the MinGW compiler are worth huge THANKS! The 64bit port would have
+been impossible without the 64bit MinGW compiler.
+
Good luck and Happy Hacking,
Patrik, OTP
@@ -791,7 +1018,7 @@ Copyright and License
%CopyrightBegin%
-Copyright Ericsson AB 2003-2010. All Rights Reserved.
+Copyright Ericsson AB 2003-2012. All Rights Reserved.
The 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/INSTALL.md b/INSTALL.md
index 8a3b71e4ec..34dd9fed8e 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -44,21 +44,31 @@ At Ericsson we have a "Daily Build and Test" that runs on:
* x86
* SuSE Linux/GNU 9.4, 10.1
* x86
-* SuSE Linux/GNU 10.0, 10.1
+* SuSE Linux/GNU 10.0, 10.1, 11.0
* x86
* x86\_64
-* SuSE Linux/GNU 11.0
- * x86\_64
+* openSuSE 11.4 (Celadon)
+ * x86\_64 (valgrind)
+* Fedora 7
+ * PowerPC
+* Fedora 14
+ * x86\_64
* Gentoo Linux/GNU 1.12.11.1
* x86
+* Ubuntu Linux/GNU 7.04, 10.04, 10.10, 11.0
+ * x86\_64
* MontaVista Linux/GNU 4.0.1
* PowerPC
-* FreeBSD 7.1
+* FreeBSD 8.2
* x86
-* Mac OS X 10.4.11 (Tiger), 10.5.8 (Leopard), 10.6.0 (Snow Leopard)
+* OpenBSD 5.0
+ * x86\_64
+* Mac OS X 10.5.8 (Leopard), 10.6.0 (Snow Leopard), 10.7.3 (Lion)
* x86
* Windows XP SP3, 2003, Vista, 7
* x86
+* Windows 7
+ * x86\_64
We also have the following "Daily Cross Builds":
@@ -132,7 +142,7 @@ These are the tools you will need in order to unpack and build Erlang/OTP.
* OpenSSL -- Optional, but needed for building the Erlang/OTP applications
`ssl` and `crypto`. You need the "development package" of OpenSSL, i.e.
including the header files. For building the application `ssl` the OpenSSL
- binary command program `openssl` is also needed. At least version 0.9.7
+ binary command program `openssl` is also needed. At least version 0.9.8
of OpenSSL is required. Can be downloaded from <http://www.openssl.org>.
* Sun Java jdk-1.5.0 or higher -- Optional but needed for building the
Erlang/OTP application `jinterface` and parts of `ic` and `orber`. Can
@@ -635,9 +645,6 @@ Use `hipe:help_options/0` to print out the available options.
Mac OS X (Darwin)
-----------------
-We test Mac OS X 10.4.11 (Tiger) and Mac OS X 10.5.x (Leopard) in our daily
-builds (but only on Intel processors).
-
Make sure that the command `hostname` returns a valid fully qualified host
name (this is configured in `/etc/hostconfig`).
@@ -646,6 +653,15 @@ If you develop linked-in drivers (shared library) you need to link using
include `-fno-common` in `CFLAGS` when compiling. Use `.so` as the library
suffix.
+Use the `--enable-darwin-64bit` configure flag to build a 64-bit
+binaries on Mac OS X.
+
+Building universal binaries on Mac OS X (obsolete information)
+--------------------------------------------------------------
+
+(This information was written when Mac OS X Leopard was the current
+release. It may no longer work.)
+
Universal 32bit binaries can be built on an Intel Mac using the
`--enable-darwin-universal` configure option. There still may occur
problems with certain applications using this option, but the base
@@ -674,6 +690,71 @@ test on).
Universal binaries and 64bit binaries are mutually exclusive options.
+Building a fast Erlang VM on Mac OS Lion
+----------------------------------------
+
+Starting with Xcode 4.2, Apple no longer includes a "real" `gcc`
+compiler (not based on the LLVM). Building with `llvm-gcc` or `clang`
+will work, but the performance of the Erlang run-time system will not
+be the best possible.
+
+Note that if you have `gcc-4.2` installed and included in `PATH`
+(from a previous version of Xcode), `configure` will automatically
+make sure that `gcc-4.2` will be used to compile `beam_emu.c`
+(the source file most in need of `gcc`).
+
+If you don't have `gcc-4.2.` and want to build a run-time system with
+the best possible performance, do like this:
+
+Install Xcode from the AppStore if it is not already installed.
+
+If you have Xcode 4.3, or later, you will also need to download
+"Command Line Tools" via the Downloads preference pane in Xcode.
+
+Some tools may still be lacking or out-of-date, we recommend using
+[Homebrew](https://github.com/mxcl/homebrew/wiki/installation) or
+Macports to update those tools.
+
+Install MacPorts (<http://www.macports.org/>). Then:
+
+ $ sudo port selfupdate
+ $ sudo port install gcc45 +universal
+
+### Building with wxErlang ###
+
+If you want to build the `wx` application, you will need to get wxMac-2.8.12
+(`wxMac-2.8.12.tar.gz` from
+<http://sourceforge.net/projects/wxwindows/files/2.8.12/>) and install it.
+
+Export the path for MacOSX10.6.sdk:
+
+ $ export SDK=/Developer/SDKs/MacOSX10.6.sdk
+
+In Xcode 4.3 the path has changed so use the following instead,
+
+ $ export SDK=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk
+
+Then configure and build wxMac:
+
+ $ arch_flags="-arch i386" ./configure CFLAGS="$arch_flags" CXXFLAGS="$arch_flags" CPPFLAGS="$arch_flags" LDFLAGS="$arch_flags" OBJCFLAGS="$arch_flags" OBJCXXFLAGS="$arch_flags" --prefix=/usr/local --with-macosx-sdk="$SDK" --with-macosx-version-min=10.6 --enable-unicode --with-opengl --disable-shared
+ $ make
+ $ sudo make install
+
+To link wx properly you will also need to build and install `wxStyledTextCtrl`:
+
+ $ cd contrib/src/stc
+ $ make
+ $ sudo make install
+
+### Finish up ###
+
+Build Erlang with the MacPorts GCC as the main compiler (using `clang`
+for the Objective-C Cocoa code in the `wx` application):
+
+ $ PATH=/usr/local/bin:$PATH CC=/opt/local/bin/gcc-mp-4.5 CXX=/opt/local/bin/g++-mp-4.5 ./configure --enable-m32-build make
+ $ sudo make install
+
+
How to Build a Debug Enabled Erlang RunTime System
--------------------------------------------------
@@ -720,7 +801,7 @@ Copyright and License
%CopyrightBegin%
-Copyright Ericsson AB 1998-2011. All Rights Reserved.
+Copyright Ericsson AB 1998-2012. All Rights Reserved.
The 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/Makefile.in b/Makefile.in
index 7baf5cc3aa..544233f097 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2011. All Rights Reserved.
+# Copyright Ericsson AB 1998-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -121,7 +121,7 @@ BINDIR = $(DESTDIR)$(EXTRA_PREFIX)$(bindir)
#
# Erlang base public files
#
-ERL_BASE_PUB_FILES=erl erlc epmd run_erl to_erl dialyzer typer escript run_test
+ERL_BASE_PUB_FILES=erl erlc epmd run_erl to_erl dialyzer typer escript ct_run run_test
# ERLANG_INST_LIBDIR is the top directory where the Erlang installation
# will be located when running.
@@ -157,20 +157,32 @@ ERLANG_LIBDIR = $(DESTDIR)$(ERLANG_INST_LIBDIR)
# Must be GNU make!
MAKE = @MAKE_PROG@
+NATIVE_LIBS_ENABLED = @NATIVE_LIBS_ENABLED@
+
+ifeq ($(NATIVE_LIBS_ENABLED),yes)
+HIPE_BOOTSTRAP_EBIN = boot_ebin
+else
+HIPE_BOOTSTRAP_EBIN = ebin
+endif
+
# This should be set to the target "arch-vendor-os"
-export TARGET = @TARGET@
+TARGET := @TARGET@
+include $(ERL_TOP)/make/target.mk
+export TARGET
BOOTSTRAP_ONLY = @BOOTSTRAP_ONLY@
CROSS_COMPILING = @CROSS_COMPILING@
ifeq ($(CROSS_COMPILING),yes)
INSTALL_CROSS = -cross
+TARGET_HOST=$(shell $(ERL_TOP)/erts/autoconf/config.guess)
else
ifneq ($(DESTDIR),)
INSTALL_CROSS = -cross
else
INSTALL_CROSS =
endif
+TARGET_HOST=
endif
# A BSD compatible install program
@@ -217,10 +229,11 @@ BOOTSTRAP_ROOT = $(ERL_TOP)
# depending on which system is preferred.)
LOCAL_PATH = $(ERL_TOP)/erts/bin/$(TARGET):$(ERL_TOP)/erts/bin
ifeq ($(TARGET),win32)
-WIN32_WRAPPER_PATH=$(ERL_TOP)/erts/etc/win32/cygwin_tools
BOOT_PREFIX=$(WIN32_WRAPPER_PATH):$(BOOTSTRAP_ROOT)/bootstrap/bin:
+TEST_PATH_PREFIX=$(WIN32_WRAPPER_PATH):$(ERL_TOP)/bin/win32:
else
BOOT_PREFIX=$(BOOTSTRAP_ROOT)/bootstrap/bin:
+TEST_PATH_PREFIX=$(ERL_TOP)/bin/$(TARGET_HOST):
endif
# ----------------------------------------------------------------------
@@ -322,7 +335,7 @@ all: cross_check_erl depend emulator libs start_scripts
endif
cross_check_erl:
- @PATH=$(BOOT_PREFIX)$${PATH} $(ERL_TOP)/make/cross_check_erl \
+ @PATH=$(BOOT_PREFIX)"$${PATH}" $(ERL_TOP)/make/cross_check_erl \
-target $(TARGET) -otp $(OTP) -erl_top $(ERL_TOP) \
-force $(ERL_XCOMP_FORCE_DIFFERENT_OTP)
@@ -369,16 +382,16 @@ noboot_install:
release: $(INST_DEP)
ifeq ($(OTP_SMALL_BUILD),true)
cd $(ERL_TOP)/lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) TESTROOT=$(RELEASE_ROOT) release
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) TESTROOT="$(RELEASE_ROOT)" release
else
cd $(ERL_TOP)/lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) release
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) BUILD_ALL=1 TESTROOT="$(RELEASE_ROOT)" release
endif
cd $(ERL_TOP)/erts && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) release
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) BUILD_ALL=1 TESTROOT="$(RELEASE_ROOT)" release
# ---------------------------------------------------------------
# Target only used when building commercial ERTS patches
@@ -386,22 +399,22 @@ endif
release_docs docs: mod2app
ifeq ($(OTP_SMALL_BUILD),true)
cd $(ERL_TOP)/lib && \
- PATH=$(ERL_TOP)/bin:$${PATH} ERL_TOP=$(ERL_TOP) \
- $(MAKE) TESTROOT=$(RELEASE_ROOT) $@
+ PATH=$(ERL_TOP)/bin:"$${PATH}" ERL_TOP=$(ERL_TOP) \
+ $(MAKE) TESTROOT="$(RELEASE_ROOT)" $@
else
cd $(ERL_TOP)/lib && \
- PATH=$(ERL_TOP)/bin:$${PATH} ERL_TOP=$(ERL_TOP) \
- $(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) $@
+ PATH=$(ERL_TOP)/bin:"$${PATH}" ERL_TOP=$(ERL_TOP) \
+ $(MAKE) BUILD_ALL=1 TESTROOT="$(RELEASE_ROOT)" $@
endif
cd $(ERL_TOP)/erts && \
- PATH=$(ERL_TOP)/bin:$${PATH} ERL_TOP=$(ERL_TOP) \
- $(MAKE) BUILD_ALL=1 TESTROOT=$(RELEASE_ROOT) $@
+ PATH=$(ERL_TOP)/bin:"$${PATH}" ERL_TOP=$(ERL_TOP) \
+ $(MAKE) BUILD_ALL=1 TESTROOT="$(RELEASE_ROOT)" $@
cd $(ERL_TOP)/system/doc && \
- PATH=$(ERL_TOP)/bin:$${PATH} \
- ERL_TOP=$(ERL_TOP) $(MAKE) TESTROOT=$(RELEASE_ROOT) $@
+ PATH=$(ERL_TOP)/bin:"$${PATH}" \
+ ERL_TOP=$(ERL_TOP) $(MAKE) TESTROOT="$(RELEASE_ROOT)" $@
mod2app:
- PATH=$(ERL_TOP)/bin:$${PATH} escript $(ERL_TOP)/lib/erl_docgen/priv/bin/xref_mod_app.escript -topdir $(ERL_TOP) -outfile $(ERL_TOP)/make/$(TARGET)/mod2app.xml
+ PATH=$(ERL_TOP)/bin:"$${PATH}" escript $(ERL_TOP)/lib/erl_docgen/priv/bin/xref_mod_app.escript -topdir $(ERL_TOP) -outfile $(ERL_TOP)/make/$(TARGET)/mod2app.xml
# ----------------------------------------------------------------------
ERLANG_EARS=$(BOOTSTRAP_ROOT)/bootstrap/erts
@@ -418,46 +431,46 @@ emulator:
libs:
ifeq ($(OTP_SMALL_BUILD),true)
cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt
else
cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
endif
kernel:
cd lib/kernel && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
stdlib:
cd lib/stdlib && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
compiler:
cd lib/compiler && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
hipe:
cd lib/hipe && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
typer:
cd lib/typer && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
syntax_tools:
cd lib/syntax_tools && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
preloaded:
cd erts/preloaded/src && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt BUILD_ALL=true
dep depend:
@@ -518,13 +531,13 @@ bootstrap_setup_target:
secondary_bootstrap_build:
cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt SECONDARY_BOOTSTRAP=true
secondary_bootstrap_copy:
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin ; fi
- for x in lib/hipe/ebin/*.beam; do \
+ for x in lib/hipe/$(HIPE_BOOTSTRAP_EBIN)/*.beam; do \
BN=`basename $$x`; \
TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin/$$BN; \
test -f $$TF && \
@@ -534,7 +547,6 @@ secondary_bootstrap_copy:
cp $$x $$TF; \
true; \
done
-# if test -f lib/hipe/ebin/hipe.beam ; then cp lib/hipe/ebin/*.beam $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/include ; fi
@@ -597,10 +609,22 @@ secondary_bootstrap_copy:
cp $$x $$TF; \
true; \
done
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl ; fi
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl/include ; fi
+ for x in lib/xmerl/include/*.hrl; do \
+ BN=`basename $$x`; \
+ TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl/include/$$BN; \
+ test -f $$TF && \
+ test '!' -z "`find $$x -newer $$TF -print`" && \
+ cp $$x $$TF; \
+ test '!' -f $$TF && \
+ cp $$x $$TF; \
+ true; \
+ done
tertiary_bootstrap_build:
cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) opt TERTIARY_BOOTSTRAP=true
tertiary_bootstrap_copy:
@@ -629,6 +653,8 @@ tertiary_bootstrap_copy:
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/wx/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/wx/include ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server ; fi
if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server/include ; fi
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test ; fi
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test/include ; fi
for x in lib/ic/ebin/*.beam; do \
BN=`basename $$x`; \
TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/ic/ebin/$$BN; \
@@ -694,6 +720,19 @@ tertiary_bootstrap_copy:
cp $$x $$TF; \
true; \
done
+# copy wx_object to remove undef behaviour warnings
+ for x in lib/wx/ebin/wx_object.beam; do \
+ BN=`basename $$x`; \
+ TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/wx/ebin/$$BN; \
+ test -f $$TF && \
+ test '!' -z "`find $$x -newer $$TF -print`" && \
+ cp $$x $$TF; \
+ test '!' -f $$TF && \
+ cp $$x $$TF; \
+ true; \
+ done
+
+# copy test includes to be able to compile tests with bootstrap compiler
for x in lib/test_server/include/*.hrl; do \
BN=`basename $$x`; \
TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/test_server/include/$$BN; \
@@ -704,6 +743,17 @@ tertiary_bootstrap_copy:
cp $$x $$TF; \
true; \
done
+
+ for x in lib/common_test/include/*.hrl; do \
+ BN=`basename $$x`; \
+ TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/common_test/include/$$BN; \
+ test -f $$TF && \
+ test '!' -z "`find $$x -newer $$TF -print`" && \
+ cp $$x $$TF; \
+ test '!' -f $$TF && \
+ cp $$x $$TF; \
+ true; \
+ done
# cp lib/syntax_tools/ebin/*.beam $(BOOTSTRAP_ROOT)/bootstrap/lib/syntax_tools/ebin
.PHONY: check_recreate_primary_bootstrap recreate_primary_bootstrap
@@ -826,13 +876,13 @@ KERNEL_PRELOAD_BEAMS=$(KERNEL_PRELOAD:%=$(BOOTSTRAP_TOP)/lib/kernel/ebin/%.beam)
start_scripts:
@cd erts/start_scripts \
- && ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} $(MAKE) script
+ && ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" $(MAKE) script
# Creates "erl" and "erlc" scripts in bin/erl which uses the libraries in lib
local_setup:
@rm -f bin/erl bin/erlc bin/cerl
@cd erts && \
- ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)$${PATH} \
+ ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) local_setup
@@ -854,7 +904,8 @@ tests release_tests: $(TEST_DIRS)
$(TEST_DIRS):
if test -f $@/Makefile; then \
- (cd $@; $(MAKE) TESTROOT=$(TESTSUITE_ROOT) release_tests) || exit $$?; \
+ (cd $@; $(MAKE) TESTROOT="$(TESTSUITE_ROOT)" \
+ PATH=$(TEST_PATH_PREFIX)$(BOOT_PREFIX)"$${PATH}" release_tests) || exit $$?; \
fi
#
@@ -867,29 +918,29 @@ INST_DEP += install.dirs install.emulator install.libs install.Install install.b
install: $(INST_DEP)
install-docs:
- ERL_TOP=$(ERL_TOP) INSTALLROOT=$(ERLANG_LIBDIR) PATH=$(BOOT_PREFIX)$${PATH} \
- $(MAKE) RELEASE_ROOT=$(ERLANG_LIBDIR) release_docs
+ ERL_TOP=$(ERL_TOP) INSTALLROOT="$(ERLANG_LIBDIR)" PATH=$(BOOT_PREFIX)"$${PATH}" \
+ $(MAKE) RELEASE_ROOT="$(ERLANG_LIBDIR)" release_docs
install.emulator:
cd erts && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) TESTROOT=$(ERLANG_LIBDIR) release
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) TESTROOT="$(ERLANG_LIBDIR)" release
install.libs:
ifeq ($(OTP_SMALL_BUILD),true)
cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) TESTROOT=$(ERLANG_LIBDIR) release
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) TESTROOT="$(ERLANG_LIBDIR)" release
else
cd lib && \
- ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)$${PATH} \
- $(MAKE) TESTROOT=$(ERLANG_LIBDIR) BUILD_ALL=true release
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) TESTROOT="$(ERLANG_LIBDIR)" BUILD_ALL=true release
endif
install.Install:
- (cd $(ERLANG_LIBDIR) \
- && ./Install $(INSTALL_CROSS) -minimal $(ERLANG_INST_LIBDIR))
+ (cd "$(ERLANG_LIBDIR)" \
+ && ./Install $(INSTALL_CROSS) -minimal "$(ERLANG_INST_LIBDIR)")
#
# Install erlang base public files
@@ -908,9 +959,9 @@ install.bin:
# Directories needed before we can install
#
install.dirs:
- test -d $(BINDIR) || ${MKSUBDIRS} $(BINDIR)
- ${MKSUBDIRS} $(ERLANG_LIBDIR)
- ${MKSUBDIRS} $(ERLANG_LIBDIR)/usr/lib
+ test -d "$(BINDIR)" || ${MKSUBDIRS} "$(BINDIR)"
+ ${MKSUBDIRS} "$(ERLANG_LIBDIR)"
+ ${MKSUBDIRS} "$(ERLANG_LIBDIR)/usr/lib"
.PHONY: strict_install
diff --git a/README.dtrace.md b/README.dtrace.md
new file mode 100644
index 0000000000..5bc042f9fc
--- /dev/null
+++ b/README.dtrace.md
@@ -0,0 +1,393 @@
+DTrace and Erlang/OTP
+=====================
+
+History
+-------
+
+The first implementation of DTrace probes for the Erlang virtual
+machine was presented at the [2008 Erlang User Conference] [4]. That
+work, based on the Erlang/OTP R12 release, was discontinued due to
+what appears to be miscommunication with the original developers.
+
+Several users have created Erlang port drivers, linked-in drivers, or
+NIFs that allow Erlang code to try to activate a probe,
+e.g. `foo_module:dtrace_probe("message goes here!")`.
+
+Goals
+-----
+
+1. Annotate as much of the Erlang VM as is practical.
+ * The initial goal is to trace file I/O operations.
+2. Support all platforms that implement DTrace: OS X, Solaris,
+ and (I hope) FreeBSD and NetBSD.
+3. To the extent that it's practical, support SystemTap on Linux
+ via DTrace provider compatibility.
+4. Allow Erlang code to supply annotations.
+
+Supported platforms
+-------------------
+
+* OS X 10.6.x / Snow Leopard. It should also work for 10.7 / Lion,
+ but I haven't personally tested it.
+* Solaris 10. I have done limited testing on Solaris 11 and
+ OpenIndiana release 151a, and both appear to work.
+* FreeBSD 9.0, though please see the "FreeBSD 9.0 Release Notes"
+ section below!
+* Linux via SystemTap compatibility. Please see the file
+ `README.systemtap.md` for more details.
+
+Just add the `--with-dynamic-trace=dtrace` option to your command when you
+run the `configure` script. If you are using systemtap, the configure option
+is `--with-dynamic-trace=systemtap`
+
+Status
+------
+
+As of R15B01, the dynamic trace code is included in the main OTP distribution,
+although it's considered experimental. The main development of the dtrace code
+still happens outside of Ericsson, but there is no need to fetch a patched
+version of OTP to get the basic funtionality.
+
+Implementation summary
+----------------------
+
+So far, most effort has been focused on the `efile_drv.c` code,
+which implements most file I/O on behalf of the Erlang virtual
+machine. This driver also presents a big challenge: its use of an I/O
+worker pool (enabled by using the `erl +A 8` flag, for example) makes
+it much more difficult to trace I/O activity because each of the
+following may be executed in a different Pthread:
+
+* I/O initiation (Erlang code)
+* I/O proxy process handling, e.g. read/write when file is not opened
+ in `raw` mode, operations executed by the code & file server processes.
+ (Erlang code)
+* `efile_drv` command setup (C code)
+* `efile_drv` command execution (C code)
+* `efile_drv` status return (C code)
+
+**TODO: keep this description up-to-date.**
+
+Example output from `lib/dtrace/examples/efile_drv.d` while executing
+`file:rename("old-name", "new-name")`:
+
+ efile_drv enter tag={3,84} user tag some-user-tag | RENAME (12) | args: old-name new-name , 0 0 (port #Port<0.59>)
+ async I/O worker tag={3,83} | RENAME (12) | efile_drv-int_entry
+ async I/O worker tag={3,83} | RENAME (12) | efile_drv-int_return
+ efile_drv return tag={3,83} user tag | RENAME (12) | errno 2
+
+... where the following key can help decipher the output:
+
+* `{3,83}` is the Erlang scheduler thread number (3) and operation
+ counter number (83) assigned to this I/O operation. Together,
+ these two numbers form a unique ID for the I/O operation.
+* `12` is the command number for the rename operation. See the
+ definition for `FILE_RENAME` in the source code file `efile_drv.c`
+ or the `BEGIN` section of the D script `lib/dtrace/examples/efile_drv.d`.
+* `old-name` and `new-name` are the two string arguments for the
+ source and destination of the `rename(2)` system call.
+ The two integer arguments are unused; the simple formatting code
+ prints the arguments anyway, 0 and 0.
+* The worker pool code was called on behalf of Erlang port `#Port<0.59>`.
+* The system call failed with a POSIX errno value of 2: `ENOENT`,
+ because the path `old-name` does not exist.
+* The `efile_drv-int_entry` and `efile_drv_int_return` probes are
+ provided in case the user is
+ interested in measuring only the latency of code executed by
+ `efile_drv` asynchronous functions by I/O worker pool threads
+ and the OS system call that they encapsulate.
+
+So, where does the `some-user-tag` string come from?
+
+At the moment, the user tag comes from code like the following:
+
+ put(dtrace_utag, "some-user-tag"),
+ file:rename("old-name", "new-name").
+
+This method of tagging I/O at the Erlang level is subject to change.
+
+Example DTrace probe specification
+----------------------------------
+
+ /**
+ * Fired when a message is sent from one local process to another.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * @param sender the PID (string form) of the sender
+ * @param receiver the PID (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__send(char *sender, char *receiver, uint32_t size,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a message is sent from a local process to a remote process.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * @param sender the PID (string form) of the sender
+ * @param node_name the Erlang node name (string form) of the receiver
+ * @param receiver the PID/name (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__send__remote(char *sender, char *node_name, char *receiver,
+ uint32_t size,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a message is queued to a local process. This probe
+ * will not fire if the sender's pid == receiver's pid.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * @param receiver the PID (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param queue_len length of the queue of the receiving process
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__queued(char *receiver, uint32_t size, uint32_t queue_len,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a message is 'receive'd by a local process and removed
+ * from its mailbox.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * @param receiver the PID (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param queue_len length of the queue of the receiving process
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__receive(char *receiver, uint32_t size, uint32_t queue_len,
+ int token_label, int token_previous, int token_current);
+
+ /* ... */
+
+ /* Async driver pool */
+
+ /**
+ * Show the post-add length of the async driver thread pool member's queue.
+ *
+ * NOTE: The port name is not available: additional lock(s) must
+ * be acquired in order to get the port name safely in an SMP
+ * environment. The same is true for the aio__pool_get probe.
+ *
+ * @param port the Port (string form)
+ * @param new queue length
+ */
+ probe aio_pool__add(char *, int);
+
+ /**
+ * Show the post-get length of the async driver thread pool member's queue.
+ *
+ * @param port the Port (string form)
+ * @param new queue length
+ */
+ probe aio_pool__get(char *, int);
+
+ /* Probes for efile_drv.c */
+
+ /**
+ * Entry into the efile_drv.c file I/O driver
+ *
+ * For a list of command numbers used by this driver, see the section
+ * "Guide to probe arguments" in ../../../README.md. That section
+ * also contains explanation of the various integer and string
+ * arguments that may be present when any particular probe fires.
+ *
+ * TODO: Adding the port string, args[10], is a pain. Making that
+ * port string available to all the other efile_drv.c probes
+ * will be more pain. Is the pain worth it? If yes, then
+ * add them everywhere else and grit our teeth. If no, then
+ * rip it out.
+ *
+ * @param thread-id number of the scheduler Pthread arg0
+ * @param tag number: {thread-id, tag} uniquely names a driver operation
+ * @param user-tag string arg2
+ * @param command number arg3
+ * @param string argument 1 arg4
+ * @param string argument 2 arg5
+ * @param integer argument 1 arg6
+ * @param integer argument 2 arg7
+ * @param integer argument 3 arg8
+ * @param integer argument 4 arg9
+ * @param port the port ID of the busy port args[10]
+ */
+ probe efile_drv__entry(int, int, char *, int, char *, char *,
+ int64_t, int64_t, int64_t, int64_t, char *);
+
+ /**
+ * Entry into the driver's internal work function. Computation here
+ * is performed by a async worker pool Pthread.
+ *
+ * @param thread-id number
+ * @param tag number
+ * @param command number
+ */
+ probe efile_drv__int_entry(int, int, int);
+
+ /**
+ * Return from the driver's internal work function.
+ *
+ * @param thread-id number
+ * @param tag number
+ * @param command number
+ */
+ probe efile_drv__int_return(int, int, int);
+
+ /**
+ * Return from the efile_drv.c file I/O driver
+ *
+ * @param thread-id number arg0
+ * @param tag number arg1
+ * @param user-tag string arg2
+ * @param command number arg3
+ * @param Success? 1 is success, 0 is failure arg4
+ * @param If failure, the errno of the error. arg5
+ */
+ probe efile_drv__return(int, int, char *, int, int, int);
+
+Guide to efile_drv.c probe arguments
+------------------------------------
+
+ /* Driver op code: used by efile_drv-entry arg3 */
+ /* used by efile_drv-int_entry arg3 */
+ /* used by efile_drv-int_return arg3 */
+ /* used by efile_drv-return arg3 */
+
+ #define FILE_OPEN 1 (probe arg3)
+ probe arg6 = C driver dt_i1 = flags;
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_READ 2 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+ probe arg8 = C driver dt_i3 = size;
+
+ #define FILE_LSEEK 3 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = offset;
+ probe arg8 = C driver dt_i3 = origin;
+
+ #define FILE_WRITE 4 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+ probe arg8 = C driver dt_i3 = size;
+
+ #define FILE_FSTAT 5 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+
+ #define FILE_PWD 6 (probe arg3)
+ none
+
+ #define FILE_READDIR 7 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_CHDIR 8 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_FSYNC 9 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+
+ #define FILE_MKDIR 10 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_DELETE 11 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_RENAME 12 (probe arg3)
+ probe arg4 = C driver dt_s1 = old_name;
+ probe arg5 = C driver dt_s2 = new_name;
+
+ #define FILE_RMDIR 13 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_TRUNCATE 14 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+
+ #define FILE_READ_FILE 15 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_WRITE_INFO 16 (probe arg3)
+ probe arg6 = C driver dt_i1 = mode;
+ probe arg7 = C driver dt_i2 = uid;
+ probe arg8 = C driver dt_i3 = gid;
+
+ #define FILE_LSTAT 19 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_READLINK 20 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_LINK 21 (probe arg3)
+ probe arg4 = C driver dt_s1 = existing_path;
+ probe arg5 = C driver dt_s2 = new_path;
+
+ #define FILE_SYMLINK 22 (probe arg3)
+ probe arg4 = C driver dt_s1 = existing_path;
+ probe arg5 = C driver dt_s2 = new_path;
+
+ #define FILE_CLOSE 23 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+
+ #define FILE_PWRITEV 24 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+ probe arg8 = C driver dt_i3 = size;
+
+ #define FILE_PREADV 25 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+ probe arg8 = C driver dt_i3 = size;
+
+ #define FILE_SETOPT 26 (probe arg3)
+ probe arg6 = C driver dt_i1 = opt_name;
+ probe arg7 = C driver dt_i2 = opt_specific_value;
+
+ #define FILE_IPREAD 27 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+ probe arg8 = C driver dt_i3 = offsets[0];
+ probe arg9 = C driver dt_i4 = size;
+
+ #define FILE_ALTNAME 28 (probe arg3)
+ probe arg4 = C driver dt_s1 = path;
+
+ #define FILE_READ_LINE 29 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = flags;
+ probe arg8 = C driver dt_i3 = read_offset;
+ probe arg9 = C driver dt_i4 = read_ahead;
+
+ #define FILE_FDATASYNC 30 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+
+ #define FILE_FADVISE 31 (probe arg3)
+ probe arg6 = C driver dt_i1 = fd;
+ probe arg7 = C driver dt_i2 = offset;
+ probe arg8 = C driver dt_i3 = length;
+ probe arg9 = C driver dt_i4 = advise_type;
+
+ [1]: http://www.erlang.org/euc/08/
diff --git a/README.systemtap.md b/README.systemtap.md
new file mode 100644
index 0000000000..c190bcc893
--- /dev/null
+++ b/README.systemtap.md
@@ -0,0 +1,72 @@
+SystemTap and Erlang/OTP
+========================
+
+Introduction
+------------
+
+SystemTap is DTrace for Linux. In fact Erlang's SystemTap support
+is build using SystemTap's DTrace compatibility's layer. For an
+introduction to Erlang DTrace support read README.dtrace.md.
+
+Requisites
+----------
+
+* Linux Kernel with UTRACE support
+
+ check for UTRACE support in your current kernel:
+
+ # grep CONFIG_UTRACE /boot/config-`uname -r`
+ CONFIG_UTRACE=y
+
+ Fedora 16 is known to contain UTRACE, for most other Linux distributions
+ a custom build kernel will be required.
+ Check Fedora's SystemTap documentation for additional required packages
+ (e.g. Kernel Debug Symbols)
+
+* SystemTap > 1.6
+
+ A the time of writing this, the latest released version of SystemTap is
+ version 1.6. Erlang's DTrace support requires a MACRO that was introduced
+ after that release. So either get a newer release or build SystemTap from
+ git yourself (see: http://sourceware.org/systemtap/getinvolved.html)
+
+Building Erlang
+---------------
+
+Configure and build Erlang with SystemTap support:
+
+ # ./configure --with-dynamic-trace=systemtap + whatever args you need
+ # make
+
+Testing
+-------
+
+SystemTap, unlike DTrace, needs to know what binary it is tracing and has to
+be able to read that binary before it starts tracing. Your probe script
+therefor has to reference the correct beam emulator and stap needs to be able
+to find that binary.
+The examples are written for "beam", but other versions such as "beam.smp" or
+"beam.debug.smp" might exist (depending on your configuration). Make sure you
+either specify the full the path of the binary in the probe or your "beam"
+binary is in the search path.
+
+All available probes can be listed like this:
+
+ # stap -L 'process("beam").mark("*")'
+
+or:
+
+ # PATH=/path/to/beam:$PATH stap -L 'process("beam").mark("*")'
+
+
+Probes in the dtrace.so NIF library like this:
+
+ # PATH=/path/to/dtrace/priv/lib:$PATH stap -L 'process("dtrace.so").mark("*")'
+
+Running SystemTap scripts
+-------------------------
+
+Adjust the process("beam") reference to your beam version and attach the script
+to a running "beam" instance:
+
+ # stap /path/to/probe/script/port1.systemtap -x <pid of beam>
diff --git a/aclocal.m4 b/aclocal.m4
index 32ceb26f5a..a76594d86f 120000..100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1 +1,1872 @@
-erts/aclocal.m4 \ No newline at end of file
+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
+
+AC_DEFUN(LM_PRECIOUS_VARS,
+[
+
+dnl ERL_TOP
+AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory])
+
+dnl Tools
+AC_ARG_VAR(CC, [C compiler])
+AC_ARG_VAR(CFLAGS, [C compiler flags])
+AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags])
+AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler])
+AC_ARG_VAR(CPP, [C/C++ preprocessor])
+AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags])
+AC_ARG_VAR(CXX, [C++ compiler])
+AC_ARG_VAR(CXXFLAGS, [C++ compiler flags])
+AC_ARG_VAR(LD, [linker (is often overridden by configure)])
+AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overriden by configure)])
+AC_ARG_VAR(LIBS, [libraries])
+AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)])
+AC_ARG_VAR(RANLIB, [ranlib])
+AC_ARG_VAR(AR, [ar])
+AC_ARG_VAR(GETCONF, [getconf])
+
+dnl Cross system root
+AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)])
+
+dnl Cross compilation variables
+AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for retrieving process CPU time: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+
+])
+
+AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
+[
+erl_xcomp_without_sysroot=no
+if test "$cross_compiling" = "yes"; then
+ test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes
+ test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot"
+else
+ erl_xcomp_sysroot=
+ erl_xcomp_isysroot=
+fi
+])
+
+AC_DEFUN(LM_CHECK_GETCONF,
+[
+if test "$cross_compiling" != "yes"; then
+ AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false])
+else
+ dnl First check if we got a `<HOST>-getconf' in $PATH
+ host_getconf="$host_alias-getconf"
+ AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false])
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ dnl We should perhaps give up if we have'nt found it by now, but at
+ dnl least in one Tilera MDE `getconf' under sysroot is a bourne
+ dnl shell script which we can use. We try to find `<HOST>-getconf'
+ dnl or `getconf' under sysconf, but only under sysconf since
+ dnl `getconf' in $PATH is almost guaranteed to be for the build
+ dnl machine.
+ GETCONF=
+ prfx="$erl_xcomp_sysroot"
+ AC_PATH_TOOL([GETCONF], [getconf], [false],
+ ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
+ fi
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_WINDOWS_ENVIRONMENT
+dnl
+dnl
+dnl Tries to determine thw windows build environment, i.e.
+dnl MIXED_CYGWIN_VC or MIXED_MSYS_VC
+dnl
+
+AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
+[
+MIXED_CYGWIN=no
+MIXED_MSYS=no
+
+AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment)
+if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_CYGWIN_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
+ elif test -x /usr/bin/msysinfo; then
+ CFLAGS="-O2"
+ MIXED_MSYS=yes
+ AC_MSG_RESULT([MSYS and VC])
+ MIXED_MSYS_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_VC=no
+ MIXED_MSYS_VC=no
+fi
+AC_SUBST(MIXED_CYGWIN_VC)
+AC_SUBST(MIXED_MSYS_VC)
+
+MIXED_VC=no
+if test "x$MIXED_MSYS_VC" = "xyes" -o "x$MIXED_CYGWIN_VC" = "xyes" ; then
+ MIXED_VC=yes
+fi
+
+AC_SUBST(MIXED_VC)
+
+if test "x$MIXED_MSYS" != "xyes"; then
+ AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
+ if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([yes])
+ MIXED_CYGWIN_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_MINGW=no
+ fi
+else
+ MIXED_CYGWIN_MINGW=no
+fi
+AC_SUBST(MIXED_CYGWIN_MINGW)
+
+AC_MSG_CHECKING(if we mix cygwin with any native compiler)
+if test "X$MIXED_CYGWIN" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_CYGWIN)
+
+AC_MSG_CHECKING(if we mix msys with another native compiler)
+if test "X$MIXED_MSYS" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_MSYS)
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_FIND_EMU_CC
+dnl
+dnl
+dnl Tries fairly hard to find a C compiler that can handle jump tables.
+dnl Defines the @EMU_CC@ variable for the makefiles and
+dnl inserts NO_JUMP_TABLE in the header if one cannot be found...
+dnl
+
+AC_DEFUN(LM_FIND_EMU_CC,
+ [AC_CACHE_CHECK(for a compiler that handles jumptables,
+ ac_cv_prog_emu_cc,
+ [
+AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+lbl1:
+ return 1;
+lbl2:
+ return 2;
+],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+
+if test $ac_cv_prog_emu_cc = no; then
+ for ac_progname in emu_cc.sh gcc-4.2 gcc; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_progname; then
+ ac_cv_prog_emu_cc=$ac_dir/$ac_progname
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ if test $ac_cv_prog_emu_cc != no; then
+ break
+ fi
+ done
+fi
+
+if test $ac_cv_prog_emu_cc != no; then
+ save_CC=$CC
+ save_CFLAGS=$CFLAGS
+ save_CPPFLAGS=$CPPFLAGS
+ CC=$ac_cv_prog_emu_cc
+ CFLAGS=""
+ CPPFLAGS=""
+ AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+ lbl1:
+ return 1;
+ lbl2:
+ return 2;
+ ],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+ CC=$save_CC
+ CFLAGS=$save_CFLAGS
+ CPPFLAGS=$save_CPPFLAGS
+fi
+])
+if test $ac_cv_prog_emu_cc = no; then
+ AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables])
+ EMU_CC=$CC
+else
+ EMU_CC=$ac_cv_prog_emu_cc
+fi
+AC_SUBST(EMU_CC)
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_INSTALL_DIR
+dnl
+dnl This macro may be used by any OTP application.
+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
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_PERL5
+dnl
+dnl Try to find perl version 5. If found set PERL to the absolute path
+dnl of the program, if not found set PERL to false.
+dnl
+dnl On some systems /usr/bin/perl is perl 4 and e.g.
+dnl /usr/local/bin/perl is perl 5. We try to handle this case by
+dnl putting a couple of
+dnl Tries to handle the case that there are two programs called perl
+dnl in the path and one of them is perl 5 and the other isn't.
+dnl
+AC_DEFUN(LM_PROG_PERL5,
+[AC_PATH_PROGS(PERL, perl5 perl, false,
+ /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH})
+changequote(, )dnl
+dnl[ That bracket is needed to balance the right bracket below
+if test "$PERL" = "false" || $PERL -e 'exit ($] >= 5)'; then
+changequote([, ])dnl
+ ac_cv_path_PERL=false
+ PERL=false
+dnl AC_MSG_WARN(perl version 5 not found)
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SO_BSDCOMPAT
+dnl
+dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux)
+dnl
+AC_DEFUN(LM_DECL_SO_BSDCOMPAT,
+[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat,
+AC_TRY_COMPILE([#include <sys/socket.h>], [int i = SO_BSDCOMPAT;],
+ ac_cv_decl_so_bsdcompat=yes,
+ ac_cv_decl_so_bsdcompat=no))
+
+case "${ac_cv_decl_so_bsdcompat}" in
+ "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[],
+ [Define if you have SO_BSDCOMPAT flag on sockets]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_INADDR_LOOPBACK
+dnl
+dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default
+dnl
+
+AC_DEFUN(LM_DECL_INADDR_LOOPBACK,
+[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h],
+ ac_cv_decl_inaddr_loopback,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>], [int i = INADDR_LOOPBACK;],
+ac_cv_decl_inaddr_loopback=yes, ac_cv_decl_inaddr_loopback=no)
+])
+
+if test ${ac_cv_decl_inaddr_loopback} = no; then
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h],
+ ac_cv_decl_inaddr_loopback_rpc,
+ AC_TRY_COMPILE([#include <rpc/types.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_rpc=yes,
+ ac_cv_decl_inaddr_loopback_rpc=no))
+
+ case "${ac_cv_decl_inaddr_loopback_rpc}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
+ [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h],
+ ac_cv_decl_inaddr_loopback_winsock2,
+ AC_TRY_COMPILE([#define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_winsock2=yes,
+ ac_cv_decl_inaddr_loopback_winsock2=no))
+ case "${ac_cv_decl_inaddr_loopback_winsock2}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[],
+ [Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ # couldn't find it anywhere
+ AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[],
+ [Define if you don't have a definition of INADDR_LOOPBACK]) ;;
+ esac;;
+ esac
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_SOCKADDR_SA_LEN
+dnl
+dnl Check if the sockaddr structure has the field sa_len
+dnl
+
+AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN,
+[AC_CACHE_CHECK([whether struct sockaddr has sa_len field],
+ ac_cv_struct_sockaddr_sa_len,
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>], [struct sockaddr s; s.sa_len = 10;],
+ ac_cv_struct_sockaddr_sa_len=yes, ac_cv_struct_sockaddr_sa_len=no))
+
+dnl FIXME convbreak
+case ${ac_cv_struct_sockaddr_sa_len} in
+ "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;;
+ *) ;;
+esac
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_EXCEPTION
+dnl
+dnl Check to see whether the system supports the matherr function
+dnl and its associated type "struct exception".
+dnl
+
+AC_DEFUN(LM_STRUCT_EXCEPTION,
+[AC_CACHE_CHECK([for struct exception (and matherr function)],
+ ac_cv_struct_exception,
+AC_TRY_COMPILE([#include <math.h>],
+ [struct exception x; x.type = DOMAIN; x.type = SING;],
+ ac_cv_struct_exception=yes, ac_cv_struct_exception=no))
+
+case "${ac_cv_struct_exception}" in
+ "yes" ) AC_DEFINE(USE_MATHERR,[1],[Define if you have matherr() function and struct exception type]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_IPV6
+dnl
+dnl Check for ipv6 support and what the in6_addr structure is called.
+dnl (early linux used in_addr6 insted of in6_addr)
+dnl
+
+AC_DEFUN(LM_SYS_IPV6,
+[AC_MSG_CHECKING(for IP version 6 support)
+AC_CACHE_VAL(ac_cv_sys_ipv6_support,
+[ok_so_far=yes
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no)
+
+if test $ok_so_far = yes; then
+ ac_cv_sys_ipv6_support=yes
+else
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in_addr6 a6; struct sockaddr_in6 s6;],
+ ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no)
+fi
+])dnl
+
+dnl
+dnl Have to use old style AC_DEFINE due to BC with old autoconf.
+dnl
+
+case ${ac_cv_sys_ipv6_support} in
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ ;;
+ in_addr6)
+ AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)])
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this])
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_MULTICAST
+dnl
+dnl Check for multicast support. Only checks for multicast options in
+dnl setsockopt(), no check is performed that multicasting actually works.
+dnl If options are found defines HAVE_MULTICAST_SUPPORT
+dnl
+
+AC_DEFUN(LM_SYS_MULTICAST,
+[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
+[AC_EGREP_CPP(yes,
+[#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP)
+yes
+#endif
+], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)])
+if test $ac_cv_sys_multicast_support = yes; then
+ AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1],
+ [Define if setsockopt() accepts multicast options])
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SYS_ERRLIST
+dnl
+dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared
+dnl in a system header file, stdio.h or errno.h.
+dnl
+
+AC_DEFUN(LM_DECL_SYS_ERRLIST,
+[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h],
+ ac_cv_decl_sys_errlist,
+[AC_TRY_COMPILE([#include <stdio.h>
+#include <errno.h>], [char *msg = *(sys_errlist + 1);],
+ ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)])
+if test $ac_cv_decl_sys_errlist = yes; then
+ AC_DEFINE(SYS_ERRLIST_DECLARED,[],
+ [define if the variable sys_errlist is declared in a system header file])
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes
+dnl [, action-if-found [, action-if-not-found]]] )
+dnl
+dnl Checks if the declaration "declaration" of "funname" conflicts
+dnl with the header files idea of how the function should be
+dnl declared. It is useful on systems which lack prototypes and you
+dnl need to provide your own (e.g. when you want to take the address
+dnl of a function). The 4'th argument is expanded if conflicting,
+dnl the 5'th argument otherwise
+dnl
+dnl
+
+AC_DEFUN(LM_CHECK_FUNC_DECL,
+[AC_MSG_CHECKING([for conflicting declaration of $1])
+AC_CACHE_VAL(ac_cv_func_decl_$1,
+[AC_TRY_COMPILE([#include <stdio.h>
+$3],[$2
+char *c = (char *)$1;
+], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")])
+if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$4], , :, [$4])
+else
+ AC_MSG_RESULT(no)
+ifelse([$5], , , [$5
+])dnl
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl AC_DOUBLE_MIDDLE_ENDIAN
+dnl
+dnl Checks whether doubles are represented in "middle-endian" format.
+dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
+dnl as well as DOUBLE_MIDDLE_ENDIAN.
+dnl
+dnl
+
+AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
+[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
+[# It does not; compile a test program.
+AC_RUN_IFELSE(
+[AC_LANG_SOURCE([[#include <stdlib.h>
+
+int
+main(void)
+{
+ int i = 0;
+ int zero = 0;
+ int bigendian;
+ int zero_index = 0;
+
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+
+ /* we'll use the one with 32-bit words */
+ union
+ {
+ double d;
+ unsigned int c[2];
+ } vint;
+
+ union
+ {
+ double d;
+ unsigned long c[2];
+ } vlong;
+
+ union
+ {
+ double d;
+ unsigned short c[2];
+ } vshort;
+
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ u.l = 1;
+ bigendian = (u.c[sizeof (long int) - 1] == 1);
+
+ zero_index = bigendian ? 1 : 0;
+
+ vint.d = 1.0;
+ vlong.d = 1.0;
+ vshort.d = 1.0;
+
+ if (sizeof(unsigned int) == 4)
+ {
+ if (vint.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned long) == 4)
+ {
+ if (vlong.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned short) == 4)
+ {
+ if (vshort.c[zero_index] != 0)
+ zero = 1;
+ }
+
+ exit (zero);
+}
+]])],
+ [ac_cv_c_double_middle_endian=no],
+ [ac_cv_c_double_middle_endian=yes],
+ [ac_cv_c_double_middle=unknown])])
+case $ac_cv_c_double_middle_endian in
+ yes)
+ m4_default([$1],
+ [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
+ [Define to 1 if your processor stores the words in a double in
+ middle-endian format (like some ARMs).])]) ;;
+ no)
+ $2 ;;
+ *)
+ m4_default([$3],
+ [AC_MSG_WARN([unknown double endianness
+presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
+esac
+])# AC_C_DOUBLE_MIDDLE_ENDIAN
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_THR_LIB
+dnl
+dnl This macro may be used by any OTP application.
+dnl
+dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also
+dnl checks for some pthread headers which will appear in DEFS or config.h.
+dnl
+
+AC_DEFUN(LM_CHECK_THR_LIB,
+[
+
+NEED_NPTL_PTHREAD_H=no
+
+dnl win32?
+AC_MSG_CHECKING([for native win32 threads])
+if test "X$host_os" = "Xwin32"; then
+ AC_MSG_RESULT(yes)
+ THR_DEFS="-DWIN32_THREADS"
+ THR_LIBS=
+ THR_LIB_NAME=win32_threads
+ THR_LIB_TYPE=win32_threads
+else
+ AC_MSG_RESULT(no)
+ THR_DEFS=
+ THR_LIBS=
+ THR_LIB_NAME=
+ THR_LIB_TYPE=posix_unknown
+
+dnl Try to find POSIX threads
+
+dnl The usual pthread lib...
+ AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
+
+dnl FreeBSD has pthreads in special c library, c_r...
+ if test "x$THR_LIBS" = "x"; then
+ AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r")
+ fi
+
+dnl On ofs1 the '-pthread' switch should be used
+ if test "x$THR_LIBS" = "x"; then
+ AC_MSG_CHECKING([if the '-pthread' switch can be used])
+ saved_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -pthread"
+ AC_TRY_LINK([#include <pthread.h>],
+ pthread_create((void*)0,(void*)0,(void*)0,(void*)0);,
+ [THR_DEFS="-pthread"
+ THR_LIBS="-pthread"])
+ CFLAGS=$saved_cflags
+ if test "x$THR_LIBS" != "x"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ if test "x$THR_LIBS" != "x"; then
+ THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
+ THR_LIB_NAME=pthread
+ case $host_os in
+ solaris*)
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
+ linux*)
+ THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
+
+ LM_CHECK_GETCONF
+ AC_MSG_CHECKING(for Native POSIX Thread Library)
+ libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
+ if test $? -eq 0; then
+ case "$libpthr_vsn" in
+ *nptl*|*NPTL*) nptl=yes;;
+ *) nptl=no;;
+ esac
+ elif test "$cross_compiling" = "yes"; then
+ case "$erl_xcomp_linux_nptl" in
+ "") nptl=cross;;
+ yes|no) nptl=$erl_xcomp_linux_nptl;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);;
+ esac
+ else
+ nptl=no
+ fi
+ AC_MSG_RESULT($nptl)
+ if test $nptl = cross; then
+ nptl=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $nptl = yes; then
+ THR_LIB_TYPE=posix_nptl
+ need_nptl_incldir=no
+ AC_CHECK_HEADER(nptl/pthread.h,
+ [need_nptl_incldir=yes
+ NEED_NPTL_PTHREAD_H=yes])
+ if test $need_nptl_incldir = yes; then
+ # Ahh...
+ nptl_path="$C_INCLUDE_PATH:$CPATH"
+ if test X$cross_compiling != Xyes; then
+ nptl_path="$nptl_path:/usr/local/include:/usr/include"
+ else
+ IROOT="$erl_xcomp_isysroot"
+ test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot"
+ test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot])
+ nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include"
+ fi
+ nptl_ws_path=
+ save_ifs="$IFS"; IFS=":"
+ for dir in $nptl_path; do
+ if test "x$dir" != "x"; then
+ nptl_ws_path="$nptl_ws_path $dir"
+ fi
+ done
+ IFS=$save_ifs
+ nptl_incldir=
+ for dir in $nptl_ws_path; do
+ AC_CHECK_HEADER($dir/nptl/pthread.h,
+ nptl_incldir=$dir/nptl)
+ if test "x$nptl_incldir" != "x"; then
+ THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
+ break
+ fi
+ done
+ if test "x$nptl_incldir" = "x"; then
+ AC_MSG_ERROR(Failed to locate nptl system include directory)
+ fi
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need THR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $THR_DEFS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h,
+ AC_DEFINE(HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ fi
+fi
+
+])
+
+AC_DEFUN(ERL_INTERNAL_LIBS,
+[
+
+ERTS_INTERNAL_X_LIBS=
+
+AC_CHECK_LIB(kstat, kstat_open,
+[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat])
+ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"])
+
+AC_SUBST(ERTS_INTERNAL_X_LIBS)
+
+])
+
+AC_DEFUN(ETHR_CHK_SYNC_OP,
+[
+ AC_MSG_CHECKING([for $3-bit $1()])
+ case "$2" in
+ "1") sync_call="$1(&var);";;
+ "2") sync_call="$1(&var, ($4) 0);";;
+ "3") sync_call="$1(&var, ($4) 0, ($4) 0);";;
+ esac
+ have_sync_op=no
+ AC_TRY_LINK([],
+ [
+ $4 res;
+ volatile $4 var;
+ res = $sync_call
+ ],
+ [have_sync_op=yes])
+ test $have_sync_op = yes && $5
+ AC_MSG_RESULT([$have_sync_op])
+])
+
+AC_DEFUN(ETHR_CHK_INTERLOCKED,
+[
+ ilckd="$1"
+ AC_MSG_CHECKING([for ${ilckd}()])
+ case "$2" in
+ "1") ilckd_call="${ilckd}(var);";;
+ "2") ilckd_call="${ilckd}(var, ($3) 0);";;
+ "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
+ "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
+ esac
+ have_interlocked_op=no
+ AC_TRY_LINK(
+ [
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <intrin.h>
+ ],
+ [
+ volatile $3 *var;
+ volatile $3 arr[2];
+
+ $ilckd_call
+ return 0;
+ ],
+ [have_interlocked_op=yes])
+ test $have_interlocked_op = yes && $4
+ AC_MSG_RESULT([$have_interlocked_op])
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_FIND_ETHR_LIB
+dnl
+dnl NOTE! This macro may be changed at any time! Should *only* be used by
+dnl ERTS!
+dnl
+dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link
+dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS
+dnl except that the ethread lib itself is not included), ETHR_DEFS to
+dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the
+dnl thread library which the ethread library is based on, and ETHR_LIB_NAME
+dnl to the name of the library where the ethread implementation is located.
+dnl ERL_FIND_ETHR_LIB currently searches for 'pthreads', and
+dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS,
+dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the
+dnl empty string.
+dnl
+
+AC_DEFUN(ERL_FIND_ETHR_LIB,
+[
+
+LM_CHECK_THR_LIB
+ERL_INTERNAL_LIBS
+
+ethr_have_native_atomics=no
+ethr_have_native_spinlock=no
+ETHR_THR_LIB_BASE="$THR_LIB_NAME"
+ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
+ETHR_DEFS="$THR_DEFS"
+ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS"
+ETHR_LIBS=
+ETHR_LIB_NAME=
+
+ethr_modified_default_stack_size=
+
+dnl Name of lib where ethread implementation is located
+ethr_lib_name=ethread
+
+case "$THR_LIB_NAME" in
+
+ win32_threads)
+ ETHR_THR_LIB_BASE_DIR=win
+ # * _WIN32_WINNT >= 0x0400 is needed for
+ # TryEnterCriticalSection
+ # * _WIN32_WINNT >= 0x0403 is needed for
+ # InitializeCriticalSectionAndSpinCount
+ # The ethread lib will refuse to build if _WIN32_WINNT < 0x0403.
+ #
+ # -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it
+ # and save it in ETHR_DEFS.
+ found_win32_winnt=no
+ for cppflag in $CPPFLAGS; do
+ case $cppflag in
+ -DWINVER*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ ;;
+ -D_WIN32_WINNT*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ found_win32_winnt=yes
+ ;;
+ *)
+ ;;
+ esac
+ done
+ if test $found_win32_winnt = no; then
+ AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS])
+ fi
+
+ AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
+
+ test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes
+ ;;
+
+ pthread)
+ ETHR_THR_LIB_BASE_DIR=pthread
+ AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
+ case $host_os in
+ openbsd*)
+ # The default stack size is insufficient for our needs
+ # on OpenBSD. We increase it to 256 kilo words.
+ ethr_modified_default_stack_size=256;;
+ linux*)
+ ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE"
+
+ if test X$cross_compiling = Xyes; then
+ case X$erl_xcomp_linux_usable_sigusrx in
+ X) usable_sigusrx=cross;;
+ Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);;
+ esac
+ case X$erl_xcomp_linux_usable_sigaltstack in
+ X) usable_sigaltstack=cross;;
+ Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);;
+ esac
+ else
+ # FIXME: Test for actual problems instead of kernel versions
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-1]]|2.[[0-1]].*)
+ usable_sigusrx=no
+ usable_sigaltstack=no;;
+ 2.[[2-3]]|2.[[2-3]].*)
+ usable_sigusrx=yes
+ usable_sigaltstack=no;;
+ *)
+ usable_sigusrx=yes
+ usable_sigaltstack=yes;;
+ esac
+ fi
+
+ AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used)
+ AC_MSG_RESULT($usable_sigusrx)
+ if test $usable_sigusrx = cross; then
+ usable_sigusrx=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigusrx = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
+ fi
+
+ AC_MSG_CHECKING(if sigaltstack can be used)
+ AC_MSG_RESULT($usable_sigaltstack)
+ if test $usable_sigaltstack = cross; then
+ usable_sigaltstack=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigaltstack = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need ETHR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $ETHR_DEFS"
+
+ dnl We need the thread library in order to find some functions
+ saved_libs="$LIBS"
+ LIBS="$LIBS $ETHR_X_LIBS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ if test $NEED_NPTL_PTHREAD_H = yes; then
+ AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \
+[Define if you need the <nptl/pthread.h> header file.])
+ fi
+
+ AC_CHECK_HEADER(sched.h, \
+ AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \
+[Define if you have the <sched.h> header file.]))
+
+ AC_CHECK_HEADER(sys/time.h, \
+ AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \
+[Define if you have the <sys/time.h> header file.]))
+
+ AC_TRY_COMPILE([#include <time.h>
+ #include <sys/time.h>],
+ [struct timeval *tv; return 0;],
+ AC_DEFINE(ETHR_TIME_WITH_SYS_TIME, 1, \
+[Define if you can safely include both <sys/time.h> and <time.h>.]))
+
+
+ dnl
+ dnl Check for functions
+ dnl
+
+ AC_CHECK_FUNC(pthread_spin_lock, \
+ [ethr_have_native_spinlock=yes \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
+[Define if you have the pthread_spin_lock function.])])
+
+ have_sched_yield=no
+ have_librt_sched_yield=no
+ AC_CHECK_FUNC(sched_yield, [have_sched_yield=yes])
+ if test $have_sched_yield = no; then
+ AC_CHECK_LIB(rt, sched_yield,
+ [have_librt_sched_yield=yes
+ ETHR_X_LIBS="$ETHR_X_LIBS -lrt"])
+ fi
+ if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.])
+ AC_MSG_CHECKING([whether sched_yield() returns an int])
+ sched_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #ifdef ETHR_HAVE_SCHED_H
+ #include <sched.h>
+ #endif
+ ],
+ [int sched_yield();],
+ [sched_yield_ret_int=yes])
+ AC_MSG_RESULT([$sched_yield_ret_int])
+ if test $sched_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_yield=no
+ AC_CHECK_FUNC(pthread_yield, [have_pthread_yield=yes])
+ if test $have_pthread_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.])
+ AC_MSG_CHECKING([whether pthread_yield() returns an int])
+ pthread_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [int pthread_yield();],
+ [pthread_yield_ret_int=yes])
+ AC_MSG_RESULT([$pthread_yield_ret_int])
+ if test $pthread_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_rwlock_init=no
+ AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes])
+ if test $have_pthread_rwlock_init = yes; then
+
+ ethr_have_pthread_rwlockattr_setkind_np=no
+ AC_CHECK_FUNC(pthread_rwlockattr_setkind_np,
+ [ethr_have_pthread_rwlockattr_setkind_np=yes])
+
+ if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \
+[Define if you have the pthread_rwlockattr_setkind_np() function.])
+
+ AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP])
+ ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
+ AC_TRY_LINK([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [
+ pthread_rwlockattr_t *attr;
+ return pthread_rwlockattr_setkind_np(attr,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+ ],
+ [ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes])
+ AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np])
+ if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \
+[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.])
+ fi
+ fi
+ fi
+
+ if test "$force_pthread_rwlocks" = "yes"; then
+
+ AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \
+[Define if you want to force usage of pthread rwlocks])
+
+ if test $have_pthread_rwlock_init = yes; then
+ AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.])
+ else
+ AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found])
+ fi
+ fi
+
+ AC_CHECK_FUNC(pthread_attr_setguardsize, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
+[Define if you have the pthread_attr_setguardsize function.]))
+
+ linux_futex=no
+ AC_MSG_CHECKING([for Linux futexes])
+ AC_TRY_LINK([
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <linux/futex.h>
+ #include <sys/time.h>
+ ],
+ [
+ int i = 1;
+ syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
+ (void*)0,(void*)0, 0);
+ syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
+ (void*)0,(void*)0, 0);
+ return 0;
+ ],
+ linux_futex=yes)
+ AC_MSG_RESULT([$linux_futex])
+ test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
+
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(long long)
+ AC_CHECK_SIZEOF(__int128_t)
+
+ if test "$ac_cv_sizeof_int" = "4"; then
+ int32="int"
+ elif test "$ac_cv_sizeof_long" = "4"; then
+ int32="long"
+ elif test "$ac_cv_sizeof_long_long" = "4"; then
+ int32="long long"
+ else
+ AC_MSG_ERROR([No 32-bit type found])
+ fi
+
+ if test "$ac_cv_sizeof_int" = "8"; then
+ int64="int"
+ elif test "$ac_cv_sizeof_long" = "8"; then
+ int64="long"
+ elif test "$ac_cv_sizeof_long_long" = "8"; then
+ int64="long long"
+ else
+ AC_MSG_ERROR([No 64-bit type found])
+ fi
+
+ int128=no
+ if test "$ac_cv_sizeof___int128_t" = "16"; then
+ int128="__int128_t"
+ fi
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32, 1, [Define if you have __sync_val_compare_and_swap() for 32-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH32, 1, [Define if you have __sync_add_and_fetch() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND32, 1, [Define if you have __sync_fetch_and_and() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR32, 1, [Define if you have __sync_fetch_and_or() for 32-bit integers]))
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64, 1, [Define if you have __sync_val_compare_and_swap() for 64-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH64, 1, [Define if you have __sync_add_and_fetch() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND64, 1, [Define if you have __sync_fetch_and_and() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR64, 1, [Define if you have __sync_fetch_and_or() for 64-bit integers]))
+
+ if test $int128 != no; then
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [128], [$int128], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128, 1, [Define if you have __sync_val_compare_and_swap() for 128-bit integers]))
+ fi
+
+ AC_MSG_CHECKING([for a usable libatomic_ops implementation])
+ case "x$with_libatomic_ops" in
+ xno | xyes | x)
+ libatomic_ops_include=
+ ;;
+ *)
+ if test -d "${with_libatomic_ops}/include"; then
+ libatomic_ops_include="-I$with_libatomic_ops/include"
+ CPPFLAGS="$CPPFLAGS $libatomic_ops_include"
+ else
+ AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found])
+ fi;;
+ esac
+ ethr_have_libatomic_ops=no
+ AC_TRY_LINK([#include "atomic_ops.h"],
+ [
+ volatile AO_t x;
+ AO_t y;
+ int z;
+
+ AO_nop_full();
+ AO_store(&x, (AO_t) 0);
+ z = AO_load(&x);
+ z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1);
+ ],
+ [ethr_have_native_atomics=yes
+ ethr_have_libatomic_ops=yes])
+ AC_MSG_RESULT([$ethr_have_libatomic_ops])
+ if test $ethr_have_libatomic_ops = yes; then
+ AC_CHECK_SIZEOF(AO_t, ,
+ [
+ #include <stdio.h>
+ #include "atomic_ops.h"
+ ])
+ AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used])
+
+ AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations])
+ if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations])
+ fi
+ ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
+ elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_MSG_ERROR([No usable libatomic_ops implementation found])
+ fi
+
+ case "$host_cpu" in
+ sparc | sun4u | sparc64 | sun4v)
+ case "$with_sparc_memory_order" in
+ "TSO")
+ AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
+ "PSO")
+ AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
+ "RMO"|"")
+ AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
+ *)
+ AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
+ esac
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
+ if test "$enable_x86_out_of_order" = "yes"; then
+ AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
+ fi
+ ethr_have_native_atomics=yes;;
+ macppc | ppc | "Power Macintosh")
+ ethr_have_native_atomics=yes;;
+ tile)
+ ethr_have_native_atomics=yes;;
+ *)
+ ;;
+ esac
+
+ test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
+
+ dnl Restore LIBS
+ LIBS=$saved_libs
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ ;;
+ *)
+ ;;
+esac
+
+AC_MSG_CHECKING([whether default stack size should be modified])
+if test "x$ethr_modified_default_stack_size" != "x"; then
+ AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size])
+ AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words])
+else
+ AC_MSG_RESULT([no])
+fi
+
+if test "x$ETHR_THR_LIB_BASE" != "x"; then
+ ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS"
+ ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS"
+ ETHR_LIB_NAME=$ethr_lib_name
+fi
+
+AC_CHECK_SIZEOF(void *)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers])
+
+AC_CHECK_SIZEOF(int)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int])
+AC_CHECK_SIZEOF(long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long])
+AC_CHECK_SIZEOF(long long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
+AC_CHECK_SIZEOF(__int64)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
+AC_CHECK_SIZEOF(__int128_t)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
+
+
+case X$erl_xcomp_bigendian in
+ X) ;;
+ Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);;
+esac
+
+AC_C_BIGENDIAN
+
+if test "$ac_cv_c_bigendian" = "yes"; then
+ AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
+fi
+
+case X$erl_xcomp_double_middle_endian in
+ X) ;;
+ Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
+esac
+
+AC_C_DOUBLE_MIDDLE_ENDIAN
+
+AC_ARG_ENABLE(native-ethr-impls,
+ AS_HELP_STRING([--disable-native-ethr-impls],
+ [disable native ethread implementations]),
+[ case "$enableval" in
+ no) disable_native_ethr_impls=yes ;;
+ *) disable_native_ethr_impls=no ;;
+ esac ], disable_native_ethr_impls=no)
+
+AC_ARG_ENABLE(x86-out-of-order,
+ AS_HELP_STRING([--enable-x86-out-of-order],
+ [enable x86/x84_64 out of order support (default disabled)]))
+
+test "X$disable_native_ethr_impls" = "Xyes" &&
+ AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
+
+AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
+ AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
+ [prefer gcc native ethread implementations]),
+[ case "$enableval" in
+ yes) enable_prefer_gcc_native_ethr_impls=yes ;;
+ *) enable_prefer_gcc_native_ethr_impls=no ;;
+ esac ], enable_prefer_gcc_native_ethr_impls=no)
+
+test $enable_prefer_gcc_native_ethr_impls = yes &&
+ AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
+
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
+AC_ARG_WITH(with_sparc_memory_order,
+ AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
+ [specify sparc memory order (defaults to RMO)]))
+
+ETHR_X86_SSE2_ASM=no
+case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in
+ yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64)
+ AC_MSG_CHECKING([for gcc sse2 asm support])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -msse2"
+ gcc_sse2_asm=no
+ AC_TRY_COMPILE([],
+ [
+ long long x, *y;
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
+ ],
+ [gcc_sse2_asm=yes])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$gcc_sse2_asm])
+ if test "$gcc_sse2_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
+ ETHR_X86_SSE2_ASM=yes
+ fi
+ ;;
+ *)
+ ;;
+esac
+
+case "$GCC-$host_cpu" in
+ yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
+ gcc_dw_cmpxchg_asm=no
+ AC_MSG_CHECKING([for gcc double word cmpxchg asm support])
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "pushl %%ebx\n\t"
+ "movl %8, %%ebx\n\t"
+#endif
+#if ETHR_SIZEOF_PTR == 4
+ "lock; cmpxchg8b %0\n\t"
+#else
+ "lock; cmpxchg16b %0\n\t"
+#endif
+ "setz %3\n\t"
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "popl %%ebx\n\t"
+#endif
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new[1]),
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "r"(new[0])
+#else
+ "b"(new[0])
+#endif
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test $gcc_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+#if !defined(__PIC__) || !__PIC__
+# error nope
+#endif
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new)
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
+ fi
+ fi
+ AC_MSG_RESULT([$gcc_dw_cmpxchg_asm])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
+ fi;;
+ *)
+ ;;
+esac
+
+AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
+[Define if you have all ethread defines])
+
+AC_SUBST(ETHR_X_LIBS)
+AC_SUBST(ETHR_LIBS)
+AC_SUBST(ETHR_LIB_NAME)
+AC_SUBST(ETHR_DEFS)
+AC_SUBST(ETHR_THR_LIB_BASE)
+AC_SUBST(ETHR_THR_LIB_BASE_DIR)
+AC_SUBST(ETHR_X86_SSE2_ASM)
+
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_TIME_CORRECTION
+dnl
+dnl In the presence of a high resolution realtime timer Erlang can adapt
+dnl its view of time relative to this timer. On solaris such a timer is
+dnl available with the syscall gethrtime(). On other OS's a fallback
+dnl solution using times() is implemented. (However on e.g. FreeBSD times()
+dnl is implemented using gettimeofday so it doesn't make much sense to
+dnl use it there...) On second thought, it seems to be safer to do it the
+dnl other way around. I.e. only use times() on OS's where we know it will
+dnl work...
+dnl
+
+AC_DEFUN(ERL_TIME_CORRECTION,
+[if test x$ac_cv_func_gethrtime = x; then
+ AC_CHECK_FUNC(gethrtime)
+fi
+if test x$clock_gettime_correction = xunknown; then
+ AC_TRY_COMPILE([#include <time.h>],
+ [struct timespec ts;
+ long long result;
+ clock_gettime(CLOCK_MONOTONIC,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);],
+ clock_gettime_compiles=yes,
+ clock_gettime_compiles=no)
+else
+ clock_gettime_compiles=no
+fi
+
+
+AC_CACHE_CHECK([how to correct for time adjustments], erl_cv_time_correction,
+[
+case $clock_gettime_correction in
+ yes)
+ erl_cv_time_correction=clock_gettime;;
+ no|unknown)
+ case $ac_cv_func_gethrtime in
+ yes)
+ erl_cv_time_correction=hrtime ;;
+ no)
+ case $host_os in
+ linux*)
+ case $clock_gettime_correction in
+ unknown)
+ if test x$clock_gettime_compiles = xyes; then
+ if test X$cross_compiling != Xyes; then
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-5]]|2.[[0-5]].*)
+ erl_cv_time_correction=times ;;
+ *)
+ erl_cv_time_correction=clock_gettime;;
+ esac
+ else
+ case X$erl_xcomp_linux_clock_gettime_correction in
+ X)
+ erl_cv_time_correction=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_linux_clock_gettime_correction = yes; then
+ erl_cv_time_correction=clock_gettime
+ else
+ erl_cv_time_correction=times
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_linux_clock_gettime_correction value: $erl_xcomp_linux_clock_gettime_correction]);;
+ esac
+ fi
+ else
+ erl_cv_time_correction=times
+ fi
+ ;;
+ *)
+ erl_cv_time_correction=times ;;
+ esac
+ ;;
+ *)
+ erl_cv_time_correction=none ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+])
+
+xrtlib=""
+case $erl_cv_time_correction in
+ times)
+ AC_DEFINE(CORRECT_USING_TIMES,[],
+ [Define if you do not have a high-res. timer & want to use times() instead])
+ ;;
+ clock_gettime|cross)
+ if test $erl_cv_time_correction = cross; then
+ erl_cv_time_correction=clock_gettime
+ AC_MSG_WARN([result clock_gettime guessed because of cross compilation])
+ fi
+ xrtlib="-lrt"
+ AC_DEFINE(GETHRTIME_WITH_CLOCK_GETTIME,[1],
+ [Define if you want to use clock_gettime to simulate gethrtime])
+ ;;
+esac
+dnl
+dnl Check if gethrvtime is working, and if to use procfs ioctl
+dnl or (yet to be written) write to the procfs ctl file.
+dnl
+
+AC_MSG_CHECKING([if gethrvtime works and how to use it])
+AC_TRY_RUN([
+/* gethrvtime procfs ioctl test */
+/* These need to be undef:ed to not break activation of
+ * micro level process accounting on /proc/self
+ */
+#ifdef _LARGEFILE_SOURCE
+# undef _LARGEFILE_SOURCE
+#endif
+#ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+
+int main() {
+ long msacct = PR_MSACCT;
+ int fd;
+ long long start, stop;
+ int i;
+ pid_t pid = getpid();
+ char proc_self[30] = "/proc/";
+
+ sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid);
+ if ( (fd = open(proc_self, O_WRONLY)) == -1)
+ exit(1);
+ if (ioctl(fd, PIOCSET, &msacct) < 0)
+ exit(2);
+ if (close(fd) < 0)
+ exit(3);
+ start = gethrvtime();
+ for (i = 0; i < 100; i++)
+ stop = gethrvtime();
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+}
+],
+erl_gethrvtime=procfs_ioctl,
+erl_gethrvtime=false,
+[
+case X$erl_xcomp_gethrvtime_procfs_ioctl in
+ X)
+ erl_gethrvtime=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then
+ erl_gethrvtime=procfs_ioctl
+ else
+ erl_gethrvtime=false
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);;
+esac
+])
+
+case $erl_gethrvtime in
+ procfs_ioctl)
+ AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1],
+ [define if gethrvtime() works and uses ioctl() to /proc/self])
+ AC_MSG_RESULT(uses ioctl to procfs)
+ ;;
+ *)
+ if test $erl_gethrvtime = cross; then
+ erl_gethrvtime=false
+ AC_MSG_RESULT(cross)
+ AC_MSG_WARN([result 'not working' guessed because of cross compilation])
+ else
+ AC_MSG_RESULT(not working)
+ fi
+
+ dnl
+ dnl Check if clock_gettime (linux) is working
+ dnl
+
+ AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time])
+ save_libs=$LIBS
+ LIBS="-lrt"
+ AC_TRY_RUN([
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <time.h>
+ int main() {
+ long long start, stop;
+ int i;
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0)
+ exit(1);
+ start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ for (i = 0; i < 100; i++)
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
+ stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+ }
+ ],
+ erl_clock_gettime=yes,
+ erl_clock_gettime=no,
+ [
+ case X$erl_xcomp_clock_gettime_cpu_time in
+ X) erl_clock_gettime=cross;;
+ Xyes|Xno) erl_clock_gettime=$erl_xcomp_clock_gettime_cpu_time;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);;
+ esac
+ ])
+ LIBS=$save_libs
+ case $host_os in
+ linux*)
+ AC_MSG_RESULT([no; not stable])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ AC_MSG_RESULT($erl_clock_gettime)
+ case $erl_clock_gettime in
+ yes)
+ AC_DEFINE(HAVE_CLOCK_GETTIME,[],
+ [define if clock_gettime() works for getting process time])
+ LIBRT=-lrt
+ ;;
+ cross)
+ erl_clock_gettime=no
+ AC_MSG_WARN([result no guessed because of cross compilation])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ LIBRT=$xrtlib
+ ;;
+ esac
+ ;;
+ esac
+ AC_SUBST(LIBRT)
+ ;;
+esac
+])dnl
+
+dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY
+dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
+dnl AC_LANG_JAVA instead...)
+AC_DEFUN(ERL_TRY_LINK_JAVA,
+[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
+changequote(, )dnl
+cat > conftest.java <<EOF
+$1
+class conftest { public static void main(String[] args) {
+ $2
+ ; return; }}
+EOF
+changequote([, ])dnl
+if AC_TRY_EVAL(java_link) && test -s conftest.class; then
+ ifelse([$3], , :, [rm -rf conftest*
+ $3])
+else
+ echo "configure: failed program was:" 1>&AC_FD_CC
+ cat conftest.java 1>&AC_FD_CC
+ echo "configure: PATH was $PATH" 1>&AC_FD_CC
+ifelse([$4], , , [ rm -rf conftest*
+ $4
+])dnl
+fi
+rm -f conftest*])
+#define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
+
+
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index 0b1fd8e039..3d2153e66d 100644
--- a/bootstrap/bin/start.boot
+++ b/bootstrap/bin/start.boot
Binary files differ
diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot
index 0b1fd8e039..3d2153e66d 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index c14ccc2e7b..7b1ee38ef8 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_block.beam b/bootstrap/lib/compiler/ebin/beam_block.beam
index 8983932f86..a7bb91adbb 100644
--- a/bootstrap/lib/compiler/ebin/beam_block.beam
+++ b/bootstrap/lib/compiler/ebin/beam_block.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bool.beam b/bootstrap/lib/compiler/ebin/beam_bool.beam
index e540fe227b..252257b71d 100644
--- a/bootstrap/lib/compiler/ebin/beam_bool.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bool.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bsm.beam b/bootstrap/lib/compiler/ebin/beam_bsm.beam
index bde0cff4cb..0c998c8e8c 100644
--- a/bootstrap/lib/compiler/ebin/beam_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_clean.beam b/bootstrap/lib/compiler/ebin/beam_clean.beam
index b902d84ffa..70523ca134 100644
--- a/bootstrap/lib/compiler/ebin/beam_clean.beam
+++ b/bootstrap/lib/compiler/ebin/beam_clean.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dead.beam b/bootstrap/lib/compiler/ebin/beam_dead.beam
index 449ce06f60..17cced3c1a 100644
--- a/bootstrap/lib/compiler/ebin/beam_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index 2811a0e705..81e62b0a7d 100644
--- a/bootstrap/lib/compiler/ebin/beam_dict.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dict.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index 0d4f028d48..ec48b89de7 100644
--- a/bootstrap/lib/compiler/ebin/beam_disasm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_disasm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_except.beam b/bootstrap/lib/compiler/ebin/beam_except.beam
new file mode 100644
index 0000000000..5bd28a35d9
--- /dev/null
+++ b/bootstrap/lib/compiler/ebin/beam_except.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index ea93fca2a0..4811360890 100644
--- a/bootstrap/lib/compiler/ebin/beam_jump.beam
+++ b/bootstrap/lib/compiler/ebin/beam_jump.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_listing.beam b/bootstrap/lib/compiler/ebin/beam_listing.beam
index f0503e4674..662edc0651 100644
--- a/bootstrap/lib/compiler/ebin/beam_listing.beam
+++ b/bootstrap/lib/compiler/ebin/beam_listing.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_receive.beam b/bootstrap/lib/compiler/ebin/beam_receive.beam
index 0836e118c9..43f41f6535 100644
--- a/bootstrap/lib/compiler/ebin/beam_receive.beam
+++ b/bootstrap/lib/compiler/ebin/beam_receive.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_split.beam b/bootstrap/lib/compiler/ebin/beam_split.beam
new file mode 100644
index 0000000000..296e6c4671
--- /dev/null
+++ b/bootstrap/lib/compiler/ebin/beam_split.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_trim.beam b/bootstrap/lib/compiler/ebin/beam_trim.beam
index 04d3416ef2..86f5d027f4 100644
--- a/bootstrap/lib/compiler/ebin/beam_trim.beam
+++ b/bootstrap/lib/compiler/ebin/beam_trim.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_type.beam b/bootstrap/lib/compiler/ebin/beam_type.beam
index e0a09eb146..3cb5f06859 100644
--- a/bootstrap/lib/compiler/ebin/beam_type.beam
+++ b/bootstrap/lib/compiler/ebin/beam_type.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index a8bb6ec1a2..523a6f03fb 100644
--- a/bootstrap/lib/compiler/ebin/beam_utils.beam
+++ b/bootstrap/lib/compiler/ebin/beam_utils.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 02226a600a..41523ed185 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl.beam b/bootstrap/lib/compiler/ebin/cerl.beam
index 399aeb6442..dcebe13bc8 100644
--- a/bootstrap/lib/compiler/ebin/cerl.beam
+++ b/bootstrap/lib/compiler/ebin/cerl.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_clauses.beam b/bootstrap/lib/compiler/ebin/cerl_clauses.beam
index e4db75d0e0..97e96c47bd 100644
--- a/bootstrap/lib/compiler/ebin/cerl_clauses.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_clauses.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_inline.beam b/bootstrap/lib/compiler/ebin/cerl_inline.beam
index e6f76ad0d4..eed98ecd2c 100644
--- a/bootstrap/lib/compiler/ebin/cerl_inline.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_trees.beam b/bootstrap/lib/compiler/ebin/cerl_trees.beam
index b2d79c924c..df3f351c8d 100644
--- a/bootstrap/lib/compiler/ebin/cerl_trees.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_trees.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index 4985e3d6da..c685035e23 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lib.beam b/bootstrap/lib/compiler/ebin/core_lib.beam
index 2421df60bd..1a60454b42 100644
--- a/bootstrap/lib/compiler/ebin/core_lib.beam
+++ b/bootstrap/lib/compiler/ebin/core_lib.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lint.beam b/bootstrap/lib/compiler/ebin/core_lint.beam
index de6f3e5c25..08fef1eb71 100644
--- a/bootstrap/lib/compiler/ebin/core_lint.beam
+++ b/bootstrap/lib/compiler/ebin/core_lint.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_parse.beam b/bootstrap/lib/compiler/ebin/core_parse.beam
index 11926c4a16..4f555d8036 100644
--- a/bootstrap/lib/compiler/ebin/core_parse.beam
+++ b/bootstrap/lib/compiler/ebin/core_parse.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam
index 9d812001b8..ef3504058a 100644
--- a/bootstrap/lib/compiler/ebin/core_pp.beam
+++ b/bootstrap/lib/compiler/ebin/core_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_scan.beam b/bootstrap/lib/compiler/ebin/core_scan.beam
index e0e4859095..245e59483d 100644
--- a/bootstrap/lib/compiler/ebin/core_scan.beam
+++ b/bootstrap/lib/compiler/ebin/core_scan.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/erl_bifs.beam b/bootstrap/lib/compiler/ebin/erl_bifs.beam
index b411e06c08..9234a54428 100644
--- a/bootstrap/lib/compiler/ebin/erl_bifs.beam
+++ b/bootstrap/lib/compiler/ebin/erl_bifs.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/rec_env.beam b/bootstrap/lib/compiler/ebin/rec_env.beam
index c04176da61..91a86d9855 100644
--- a/bootstrap/lib/compiler/ebin/rec_env.beam
+++ b/bootstrap/lib/compiler/ebin/rec_env.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
index 4a44c53aed..0764734cb1 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
index 2ed16cc07a..c878868598 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_inline.beam b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
index 3d6f3103e0..907c9d53a5 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_inline.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam b/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam
index 5142cdde01..1649b9f2ff 100644
--- a/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam
+++ b/bootstrap/lib/compiler/ebin/sys_expand_pmod.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam b/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
index 4b3e984ed4..a7ca15a033 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
index 9d1629d9d4..1a176b2e3f 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam
index dbc5fb5e3a..12026564d9 100644
--- a/bootstrap/lib/compiler/ebin/v3_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 817938781d..84c005edc9 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index a52d44b32e..cd4bf48540 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
index 4bec626689..485aa63dcb 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_life.beam b/bootstrap/lib/compiler/ebin/v3_life.beam
index d3ffc45a26..aa8b6b227b 100644
--- a/bootstrap/lib/compiler/ebin/v3_life.beam
+++ b/bootstrap/lib/compiler/ebin/v3_life.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application.beam b/bootstrap/lib/kernel/ebin/application.beam
index be05505c35..4485b9e1e8 100644
--- a/bootstrap/lib/kernel/ebin/application.beam
+++ b/bootstrap/lib/kernel/ebin/application.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_controller.beam b/bootstrap/lib/kernel/ebin/application_controller.beam
index 996836d78e..9c94dbd5c7 100644
--- a/bootstrap/lib/kernel/ebin/application_controller.beam
+++ b/bootstrap/lib/kernel/ebin/application_controller.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_master.beam b/bootstrap/lib/kernel/ebin/application_master.beam
index 98bd12a42f..4d1098bcec 100644
--- a/bootstrap/lib/kernel/ebin/application_master.beam
+++ b/bootstrap/lib/kernel/ebin/application_master.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/auth.beam b/bootstrap/lib/kernel/ebin/auth.beam
index 3796221d6b..33f1ab875b 100644
--- a/bootstrap/lib/kernel/ebin/auth.beam
+++ b/bootstrap/lib/kernel/ebin/auth.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam
index 580dc1f888..b7e4a46066 100644
--- a/bootstrap/lib/kernel/ebin/code.beam
+++ b/bootstrap/lib/kernel/ebin/code.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam
index 9ed647a94b..dc10d111d2 100644
--- a/bootstrap/lib/kernel/ebin/code_server.beam
+++ b/bootstrap/lib/kernel/ebin/code_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log.beam b/bootstrap/lib/kernel/ebin/disk_log.beam
index 15953c9931..fa221e7c9d 100644
--- a/bootstrap/lib/kernel/ebin/disk_log.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam
index a61ef2ad3f..5e286cdd48 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_1.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_1.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_server.beam b/bootstrap/lib/kernel/ebin/disk_log_server.beam
index 96c17f1586..d985f64937 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_server.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_ac.beam b/bootstrap/lib/kernel/ebin/dist_ac.beam
index d20390087d..3eae6b82a7 100644
--- a/bootstrap/lib/kernel/ebin/dist_ac.beam
+++ b/bootstrap/lib/kernel/ebin/dist_ac.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_util.beam b/bootstrap/lib/kernel/ebin/dist_util.beam
index 094d909535..7fc3325da4 100644
--- a/bootstrap/lib/kernel/ebin/dist_util.beam
+++ b/bootstrap/lib/kernel/ebin/dist_util.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam
index b812127f18..83a981cb1d 100644
--- a/bootstrap/lib/kernel/ebin/erts_debug.beam
+++ b/bootstrap/lib/kernel/ebin/erts_debug.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file.beam b/bootstrap/lib/kernel/ebin/file.beam
index 19251f8a4f..aa7dcf388d 100644
--- a/bootstrap/lib/kernel/ebin/file.beam
+++ b/bootstrap/lib/kernel/ebin/file.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_io_server.beam b/bootstrap/lib/kernel/ebin/file_io_server.beam
index b35b96d8f0..b8e2df2a2d 100644
--- a/bootstrap/lib/kernel/ebin/file_io_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_io_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_server.beam b/bootstrap/lib/kernel/ebin/file_server.beam
index 71e2ad8c0d..fd9a9924bb 100644
--- a/bootstrap/lib/kernel/ebin/file_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_sctp.beam b/bootstrap/lib/kernel/ebin/gen_sctp.beam
index 8777d4fd26..3092353498 100644
--- a/bootstrap/lib/kernel/ebin/gen_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index a9e0e2c0d1..96d7365006 100644
--- a/bootstrap/lib/kernel/ebin/global.beam
+++ b/bootstrap/lib/kernel/ebin/global.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global_group.beam b/bootstrap/lib/kernel/ebin/global_group.beam
index c6fe47b456..dd7d0e429e 100644
--- a/bootstrap/lib/kernel/ebin/global_group.beam
+++ b/bootstrap/lib/kernel/ebin/global_group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index b8d55c4e29..8e813f6964 100644
--- a/bootstrap/lib/kernel/ebin/group.beam
+++ b/bootstrap/lib/kernel/ebin/group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index b638157e11..028b5215a2 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index 0c4607063d..65f517ed39 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_sctp.beam b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
index 46d213bf9a..10c2644259 100644
--- a/bootstrap/lib/kernel/ebin/inet6_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp.beam b/bootstrap/lib/kernel/ebin/inet6_tcp.beam
index f9377be91b..4c80d1d71e 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
index 145e039f7e..1bc785fa37 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_udp.beam b/bootstrap/lib/kernel/ebin/inet6_udp.beam
index 582bf6e7c0..736c0157e5 100644
--- a/bootstrap/lib/kernel/ebin/inet6_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam
index d937ef4a7b..fc1e2c8387 100644
--- a/bootstrap/lib/kernel/ebin/inet_config.beam
+++ b/bootstrap/lib/kernel/ebin/inet_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index ee3fbaa584..555c8c307e 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_dns.beam b/bootstrap/lib/kernel/ebin/inet_dns.beam
index be1c7c4766..7f262cf20d 100644
--- a/bootstrap/lib/kernel/ebin/inet_dns.beam
+++ b/bootstrap/lib/kernel/ebin/inet_dns.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
index c53ecfb42a..4e6ce0fc5e 100644
--- a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
+++ b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index f8d3102da7..14ca272933 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_res.beam b/bootstrap/lib/kernel/ebin/inet_res.beam
index c0f00a0c12..9e8e9fa4de 100644
--- a/bootstrap/lib/kernel/ebin/inet_res.beam
+++ b/bootstrap/lib/kernel/ebin/inet_res.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_sctp.beam b/bootstrap/lib/kernel/ebin/inet_sctp.beam
index ed8ced75b0..098a2c9277 100644
--- a/bootstrap/lib/kernel/ebin/inet_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp.beam b/bootstrap/lib/kernel/ebin/inet_tcp.beam
index 20340e02b9..d16795f44d 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
index b382eebf92..22f2db4182 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_udp.beam b/bootstrap/lib/kernel/ebin/inet_udp.beam
index a9f7fbb7fa..917e3da3a7 100644
--- a/bootstrap/lib/kernel/ebin/inet_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel_config.beam b/bootstrap/lib/kernel/ebin/kernel_config.beam
index 40228eeeee..c5a63b6217 100644
--- a/bootstrap/lib/kernel/ebin/kernel_config.beam
+++ b/bootstrap/lib/kernel/ebin/kernel_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index 8c8786eeb9..a81f3e47d5 100644
--- a/bootstrap/lib/kernel/ebin/net_kernel.beam
+++ b/bootstrap/lib/kernel/ebin/net_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/os.beam b/bootstrap/lib/kernel/ebin/os.beam
index df333e054e..1291f1cdfa 100644
--- a/bootstrap/lib/kernel/ebin/os.beam
+++ b/bootstrap/lib/kernel/ebin/os.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/packages.beam b/bootstrap/lib/kernel/ebin/packages.beam
index c507624578..511c6a6e74 100644
--- a/bootstrap/lib/kernel/ebin/packages.beam
+++ b/bootstrap/lib/kernel/ebin/packages.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/pg2.beam b/bootstrap/lib/kernel/ebin/pg2.beam
index 4e6817fc97..439bbc24f2 100644
--- a/bootstrap/lib/kernel/ebin/pg2.beam
+++ b/bootstrap/lib/kernel/ebin/pg2.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/rpc.beam b/bootstrap/lib/kernel/ebin/rpc.beam
index 19391982e8..bfb80cf827 100644
--- a/bootstrap/lib/kernel/ebin/rpc.beam
+++ b/bootstrap/lib/kernel/ebin/rpc.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/standard_error.beam b/bootstrap/lib/kernel/ebin/standard_error.beam
index e0232d9e54..f34c1a9bd1 100644
--- a/bootstrap/lib/kernel/ebin/standard_error.beam
+++ b/bootstrap/lib/kernel/ebin/standard_error.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index df47a14304..f3aae4a980 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_drv.beam b/bootstrap/lib/kernel/ebin/user_drv.beam
index c2b4fef911..15b09a5f93 100644
--- a/bootstrap/lib/kernel/ebin/user_drv.beam
+++ b/bootstrap/lib/kernel/ebin/user_drv.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_sup.beam b/bootstrap/lib/kernel/ebin/user_sup.beam
index b68c8979ff..79dd095896 100644
--- a/bootstrap/lib/kernel/ebin/user_sup.beam
+++ b/bootstrap/lib/kernel/ebin/user_sup.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/include/dist.hrl b/bootstrap/lib/kernel/include/dist.hrl
index aea1ab81ba..5b52f6f294 100644
--- a/bootstrap/lib/kernel/include/dist.hrl
+++ b/bootstrap/lib/kernel/include/dist.hrl
@@ -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
diff --git a/bootstrap/lib/kernel/include/dist_util.hrl b/bootstrap/lib/kernel/include/dist_util.hrl
index f2b0598532..c3a7f97418 100644
--- a/bootstrap/lib/kernel/include/dist_util.hrl
+++ b/bootstrap/lib/kernel/include/dist_util.hrl
@@ -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
diff --git a/bootstrap/lib/kernel/include/file.hrl b/bootstrap/lib/kernel/include/file.hrl
index 3889bce393..bf97173122 100644
--- a/bootstrap/lib/kernel/include/file.hrl
+++ b/bootstrap/lib/kernel/include/file.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
@@ -25,10 +25,11 @@
{size :: non_neg_integer(), % Size of file in bytes.
type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
access :: 'read' | 'write' | 'read_write' | 'none',
- atime :: file:date_time(), % The local time the file was last read:
- % {{Year, Mon, Day}, {Hour, Min, Sec}}.
- mtime :: file:date_time(), % The local time the file was last written.
- ctime :: file:date_time(), % The interpretation of this time field
+ atime :: file:date_time() | integer(), % The local time the file was last read:
+ % {{Year, Mon, Day}, {Hour, Min, Sec}}.
+ % atime, ctime, mtime may also be unix epochs()
+ mtime :: file:date_time() | integer(), % The local time the file was last written.
+ ctime :: file:date_time() | integer(), % The interpretation of this time field
% is dependent on operating system.
% On Unix it is the last time the file
% or the inode was changed. On Windows,
diff --git a/bootstrap/lib/kernel/include/net_address.hrl b/bootstrap/lib/kernel/include/net_address.hrl
index 5342076507..9b9ea42931 100644
--- a/bootstrap/lib/kernel/include/net_address.hrl
+++ b/bootstrap/lib/kernel/include/net_address.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
diff --git a/bootstrap/lib/stdlib/ebin/array.beam b/bootstrap/lib/stdlib/ebin/array.beam
index ea41ab7a42..8741e4d5df 100644
--- a/bootstrap/lib/stdlib/ebin/array.beam
+++ b/bootstrap/lib/stdlib/ebin/array.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/base64.beam b/bootstrap/lib/stdlib/ebin/base64.beam
index 04a1388637..07877625dd 100644
--- a/bootstrap/lib/stdlib/ebin/base64.beam
+++ b/bootstrap/lib/stdlib/ebin/base64.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam
index 67a8554abe..afe3bcc466 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index bd37facf37..8c69197cbc 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index b53a1357ff..4a33312cc0 100644
--- a/bootstrap/lib/stdlib/ebin/dets.beam
+++ b/bootstrap/lib/stdlib/ebin/dets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_server.beam b/bootstrap/lib/stdlib/ebin/dets_server.beam
index c120ee12e3..26de164bd9 100644
--- a/bootstrap/lib/stdlib/ebin/dets_server.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index 0a9420daa2..e4cd1e8b2e 100644
--- a/bootstrap/lib/stdlib/ebin/dets_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v8.beam b/bootstrap/lib/stdlib/ebin/dets_v8.beam
index 3ede6f8d47..c8e1549256 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v8.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v8.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index 1ac657a547..8cfcb9f8f1 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v9.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v9.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dict.beam b/bootstrap/lib/stdlib/ebin/dict.beam
index c5676edc4a..35e67d6c59 100644
--- a/bootstrap/lib/stdlib/ebin/dict.beam
+++ b/bootstrap/lib/stdlib/ebin/dict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph.beam b/bootstrap/lib/stdlib/ebin/digraph.beam
index 78814b1ad3..2c1788668d 100644
--- a/bootstrap/lib/stdlib/ebin/digraph.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
index ac2c41d2b7..39cb9d90da 100644
--- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index d809fc21f6..2e2b3ef4ed 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_compile.beam b/bootstrap/lib/stdlib/ebin/erl_compile.beam
index deb6b97657..e449884f0b 100644
--- a/bootstrap/lib/stdlib/ebin/erl_compile.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_compile.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 6aff9793a6..6198c4f43a 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
index a5431e7f04..5c9663cd54 100644
--- a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_internal.beam b/bootstrap/lib/stdlib/ebin/erl_internal.beam
index 07e7f2a377..94a0a75c29 100644
--- a/bootstrap/lib/stdlib/ebin/erl_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index c0c8cd7cdd..875ccf94c2 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_parse.beam b/bootstrap/lib/stdlib/ebin/erl_parse.beam
index 097c378dbd..85fa455908 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index 4416e29c9f..2c32b68322 100644
--- a/bootstrap/lib/stdlib/ebin/erl_pp.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam
index c331d61d21..9e70ed846e 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index d9c3186502..7eacf3272c 100644
--- a/bootstrap/lib/stdlib/ebin/erl_tar.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_tar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam b/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
index f5609d124c..496e41c858 100644
--- a/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
+++ b/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam b/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
index 886bba634c..3c4c135495 100644
--- a/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
+++ b/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam
index ed0e6b0d66..e832f973d7 100644
--- a/bootstrap/lib/stdlib/ebin/escript.beam
+++ b/bootstrap/lib/stdlib/ebin/escript.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index bcd7a65cc8..642689d749 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/eval_bits.beam b/bootstrap/lib/stdlib/ebin/eval_bits.beam
index ac375672f6..73e20d9a8d 100644
--- a/bootstrap/lib/stdlib/ebin/eval_bits.beam
+++ b/bootstrap/lib/stdlib/ebin/eval_bits.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam
index 95fba9495b..633d8acd10 100644
--- a/bootstrap/lib/stdlib/ebin/file_sorter.beam
+++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/filelib.beam b/bootstrap/lib/stdlib/ebin/filelib.beam
index 5d8a6f7b07..20f48fe18e 100644
--- a/bootstrap/lib/stdlib/ebin/filelib.beam
+++ b/bootstrap/lib/stdlib/ebin/filelib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/filename.beam b/bootstrap/lib/stdlib/ebin/filename.beam
index 35031334c4..e371f3f478 100644
--- a/bootstrap/lib/stdlib/ebin/filename.beam
+++ b/bootstrap/lib/stdlib/ebin/filename.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gb_sets.beam b/bootstrap/lib/stdlib/ebin/gb_sets.beam
index d42fed4c30..dc4c752654 100644
--- a/bootstrap/lib/stdlib/ebin/gb_sets.beam
+++ b/bootstrap/lib/stdlib/ebin/gb_sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gb_trees.beam b/bootstrap/lib/stdlib/ebin/gb_trees.beam
index bbe958dc66..edf1805440 100644
--- a/bootstrap/lib/stdlib/ebin/gb_trees.beam
+++ b/bootstrap/lib/stdlib/ebin/gb_trees.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen.beam b/bootstrap/lib/stdlib/ebin/gen.beam
index 806515e2e0..0a39dc1c7e 100644
--- a/bootstrap/lib/stdlib/ebin/gen.beam
+++ b/bootstrap/lib/stdlib/ebin/gen.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_event.beam b/bootstrap/lib/stdlib/ebin/gen_event.beam
index 8137fe9570..23c4f53c30 100644
--- a/bootstrap/lib/stdlib/ebin/gen_event.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_event.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_fsm.beam b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
index 5f46d56d18..c2713544ff 100644
--- a/bootstrap/lib/stdlib/ebin/gen_fsm.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_server.beam b/bootstrap/lib/stdlib/ebin/gen_server.beam
index d5ab30b170..5d68dda4cf 100644
--- a/bootstrap/lib/stdlib/ebin/gen_server.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib.beam b/bootstrap/lib/stdlib/ebin/io_lib.beam
index 07cefba99e..b240aa157d 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
index ea2de10690..be283307f3 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam
index f2f40ef868..3865cfb227 100644
--- a/bootstrap/lib/stdlib/ebin/lib.beam
+++ b/bootstrap/lib/stdlib/ebin/lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index 3d422580e9..5e23551fb3 100644
--- a/bootstrap/lib/stdlib/ebin/lists.beam
+++ b/bootstrap/lib/stdlib/ebin/lists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/log_mf_h.beam b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
index 25a8d64b78..fdb417b71e 100644
--- a/bootstrap/lib/stdlib/ebin/log_mf_h.beam
+++ b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index 1ca5210612..bc16416161 100644
--- a/bootstrap/lib/stdlib/ebin/ms_transform.beam
+++ b/bootstrap/lib/stdlib/ebin/ms_transform.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/orddict.beam b/bootstrap/lib/stdlib/ebin/orddict.beam
index 76245fcd5e..6892fd2c9e 100644
--- a/bootstrap/lib/stdlib/ebin/orddict.beam
+++ b/bootstrap/lib/stdlib/ebin/orddict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index f22f936f42..1a9a55dc24 100644
--- a/bootstrap/lib/stdlib/ebin/otp_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/pool.beam b/bootstrap/lib/stdlib/ebin/pool.beam
index 43c8763e8f..3b1dbc3524 100644
--- a/bootstrap/lib/stdlib/ebin/pool.beam
+++ b/bootstrap/lib/stdlib/ebin/pool.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/proc_lib.beam b/bootstrap/lib/stdlib/ebin/proc_lib.beam
index 704bd8a23d..6b5c081480 100644
--- a/bootstrap/lib/stdlib/ebin/proc_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/proc_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index 4e1b8a80d1..716f28b661 100644
--- a/bootstrap/lib/stdlib/ebin/qlc.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
index 805f63930b..f51bc3ccbd 100644
--- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/queue.beam b/bootstrap/lib/stdlib/ebin/queue.beam
index 663b1a49ff..5ebb0f9cc6 100644
--- a/bootstrap/lib/stdlib/ebin/queue.beam
+++ b/bootstrap/lib/stdlib/ebin/queue.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/random.beam b/bootstrap/lib/stdlib/ebin/random.beam
index 1ee81ea68e..bc8c5ef31f 100644
--- a/bootstrap/lib/stdlib/ebin/random.beam
+++ b/bootstrap/lib/stdlib/ebin/random.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/re.beam b/bootstrap/lib/stdlib/ebin/re.beam
index 22d753562d..4b9cbb7cfc 100644
--- a/bootstrap/lib/stdlib/ebin/re.beam
+++ b/bootstrap/lib/stdlib/ebin/re.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/regexp.beam b/bootstrap/lib/stdlib/ebin/regexp.beam
deleted file mode 100644
index 023f2fb9b2..0000000000
--- a/bootstrap/lib/stdlib/ebin/regexp.beam
+++ /dev/null
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sets.beam b/bootstrap/lib/stdlib/ebin/sets.beam
index a08222f3d3..5ac7691a8f 100644
--- a/bootstrap/lib/stdlib/ebin/sets.beam
+++ b/bootstrap/lib/stdlib/ebin/sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam
index 50a60ed5b4..20b9938d06 100644
--- a/bootstrap/lib/stdlib/ebin/shell.beam
+++ b/bootstrap/lib/stdlib/ebin/shell.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index b1bc6498a6..a0c8c58c03 100644
--- a/bootstrap/lib/stdlib/ebin/sofs.beam
+++ b/bootstrap/lib/stdlib/ebin/sofs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam
index 5086591504..3ace8184d0 100644
--- a/bootstrap/lib/stdlib/ebin/string.beam
+++ b/bootstrap/lib/stdlib/ebin/string.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index 54ff535fc3..837027e93a 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
index 2fa7bc7050..6480117b9e 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sys.beam b/bootstrap/lib/stdlib/ebin/sys.beam
index 499d558dc0..724dfed4e6 100644
--- a/bootstrap/lib/stdlib/ebin/sys.beam
+++ b/bootstrap/lib/stdlib/ebin/sys.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/timer.beam b/bootstrap/lib/stdlib/ebin/timer.beam
index f60983e084..5f8f714a78 100644
--- a/bootstrap/lib/stdlib/ebin/timer.beam
+++ b/bootstrap/lib/stdlib/ebin/timer.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index 28e3c03640..7dcf140730 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index 59d4697510..2907ee286b 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/configure.in b/configure.in
index c8d4561a44..e906c17ecc 100644
--- a/configure.in
+++ b/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1998-2011. All Rights Reserved.
+dnl Copyright Ericsson AB 1998-2012. 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
@@ -225,6 +225,14 @@ AC_ARG_ENABLE(native-libs,
AS_HELP_STRING([--enable-native-libs],
[compile Erlang libraries to native code]))
+AC_ARG_WITH(dynamic-trace,
+AS_HELP_STRING([--with-dynamic-trace={dtrace|systemtap}],
+ [specify use of dynamic trace framework, dtrace or systemtap])
+AS_HELP_STRING([--without-dynamic-trace],
+ [don't enable any dynamic tracing (default)]))
+AC_ARG_ENABLE(vm-probes,
+AS_HELP_STRING([--enable-vm-probes],
+ [add dynamic trace probes to the Beam VM (only possible if --with-dynamic-trace is enabled, and then default)]))
AC_ARG_WITH(javac,
AS_HELP_STRING([--with-javac=JAVAC], [specify Java compiler to use])
AS_HELP_STRING([--with-javac], [use a Java compiler if found (default)])
@@ -361,6 +369,12 @@ if test X${enable_m32_build} = Xyes; then
export LDFLAGS
fi
+NATIVE_LIBS_ENABLED=
+if test X${enable_native_libs} = Xyes -a X${enable_hipe} != Xno; then
+ NATIVE_LIBS_ENABLED=yes
+fi
+AC_SUBST(NATIVE_LIBS_ENABLED)
+
export ERL_TOP
AC_CONFIG_SUBDIRS(lib erts)
diff --git a/erts/Makefile.in b/erts/Makefile.in
index 8b86fbadf2..5df6d71ef3 100644
--- a/erts/Makefile.in
+++ b/erts/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2010. All Rights Reserved.
+# Copyright Ericsson AB 2006-2012. All Rights Reserved.
#
# The 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,61 +25,37 @@ include vsn.mk
# ----------------------------------------------------------------------
# Other erts dirs than the emulator dir...
-ERTSDIRS = doc/src etc epmd lib_src
+ERTSDIRS = etc epmd lib_src
XINSTDIRS = preloaded
ifeq ($(NO_START_SCRIPTS),)
ERTSDIRS += start_scripts
endif
-# Until hybrid is nofrag, don't build it.
-#BUILD_HYBRID_EMU=@ERTS_BUILD_HYBRID_EMU@
-BUILD_HYBRID_EMU=no
-
EXTRA_FLAVORS=smp
-ifeq ($(BUILD_HYBRID_EMU),yes)
-EXTRA_FLAVORS += hybrid
-endif
-#
-# Some byggy 'make's get confused when a directory is created and used
-# for storing files which other files depend on during the same "make
-# session". As a workaround we do a 'make generate' (which creates
-# all directories) before doing 'make opt', etc...
-#
-
-ifneq ($(BUILD_HYBRID_EMU),yes)
+.PHONY: all
all: smp opt
-else
-all: hybrid smp opt
-endif
-debug opt docs clean:
- @ case $@ in \
- docs|clean) ;; \
- *) ( cd emulator && $(MAKE) generate TYPE=$@ FLAVOR=$(FLAVOR)) ;; \
- esac
- @ ( cd emulator && $(MAKE) $@ FLAVOR=$(FLAVOR))
- @for d in $(ERTSDIRS); do \
+.PHONY: docs
+docs:
+ ( cd doc/src && $(MAKE) $@ )
+
+.PHONY: debug opt clean
+debug opt clean:
+ for d in emulator $(ERTSDIRS); do \
if test -d $$d; then \
- ( cd $$d && $(MAKE) $@ ) || exit $$? ; \
+ ( cd $$d && $(MAKE) $@ FLAVOR=$(FLAVOR) ) || exit $$? ; \
fi ; \
- done
+ done
# ----------------------------------------------------------------------
# These are "convenience targets", provided as shortcuts for developers
# - don't use them in scripts or assume they will always stay like this!
#
+.PHONY: $(EXTRA_FLAVORS)
$(EXTRA_FLAVORS):
- @ ( cd emulator \
- && $(MAKE) generate TYPE=opt FLAVOR=$@ \
- && $(MAKE) opt FLAVOR=$@ )
-
-ifneq ($(BUILD_HYBRID_EMU),yes)
-hybrid:
- @echo '*** Omitted build of hybrid heap emulator'
- @echo '*** since target is $(TARGET)'
-endif
+ ( cd emulator && $(MAKE) opt FLAVOR=$@ )
# Make erl script and erlc in $(ERL_TOP)/bin which runs the compiled version
# Note that erlc is not a script and requires extra handling on cygwin.
@@ -88,6 +64,7 @@ endif
# The copying of beam.dll should be removed when the beam dll need no longer be
# in the same directory...
+.PHONY: local_setup
local_setup:
@cd start_scripts && $(MAKE)
@echo `ls $(ERL_TOP)/bin/`
@@ -110,8 +87,8 @@ local_setup:
cp $(ERL_TOP)/bin/$(TARGET)/escript.exe $(ERL_TOP)/bin/escript.exe; \
chmod 755 $(ERL_TOP)/bin/erl.exe $(ERL_TOP)/bin/erlc.exe \
$(ERL_TOP)/bin/werl.exe; \
- $(ERL_TOP)/erts/etc/win32/cygwin_tools/make_local_ini.sh \
- $(ERL_TOP); \
+ make_local_ini.sh $(ERL_TOP); \
+ cp $(ERL_TOP)/bin/erl.ini $(ERL_TOP)/bin/$(TARGET)/erl.ini; \
else \
sed -e "s;%FINAL_ROOTDIR%;$(ERL_TOP);" \
-e "s;erts-.*/bin;bin/$(TARGET);" \
@@ -135,11 +112,13 @@ local_setup:
$(ERL_TOP)/bin/start_clean.script
# Run the configure script
+.PHONY: configure
configure:
@set -e ; cd autoconf && $(MAKE)
# Remake the makefiles, if you already have configured but you have edited
# a "Makefile.in".
+.PHONY: makefiles
makefiles:
@set -e ; cd autoconf && $(MAKE) $@
@@ -147,21 +126,17 @@ makefiles:
# Release targets
#
-release release_docs:
-ifeq ($(BUILD_HYBRID_EMU),yes)
- @if test $@ = release; then ( cd emulator && $(MAKE) $@ FLAVOR=hybrid) fi
-else
- @if test $@ = release; then ( $(MAKE) hybrid ) fi
-endif
- @if test $@ = release; then ( cd emulator && $(MAKE) $@ FLAVOR=smp) fi
- @ (cd emulator && $(MAKE) $@ FLAVOR=plain)
- @for d in $(ERTSDIRS) $(XINSTDIRS); do \
+.PHONY: release
+release:
+ for f in plain $(EXTRA_FLAVORS) ; do \
+ ( cd emulator && $(MAKE) release FLAVOR=$$f ) \
+ done
+ for d in $(ERTSDIRS) $(XINSTDIRS); do \
if test -d $$d; then \
( cd $$d && $(MAKE) $@ ) || exit $$? ; \
fi ; \
done
-# ----------------------------------------------------------------------
-
-.PHONY: debug opt docs clean local_setup configure release \
- release_docs run_test_cases hybrid smp
+.PHONY: release_docs
+release_docs:
+ ( cd doc/src && $(MAKE) $@ )
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index 27f643921e..a76594d86f 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -59,6 +59,7 @@ AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only us
dnl Cross compilation variables
AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)])
AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
@@ -112,6 +113,94 @@ fi
dnl ----------------------------------------------------------------------
dnl
+dnl LM_WINDOWS_ENVIRONMENT
+dnl
+dnl
+dnl Tries to determine thw windows build environment, i.e.
+dnl MIXED_CYGWIN_VC or MIXED_MSYS_VC
+dnl
+
+AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
+[
+MIXED_CYGWIN=no
+MIXED_MSYS=no
+
+AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment)
+if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_CYGWIN_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
+ elif test -x /usr/bin/msysinfo; then
+ CFLAGS="-O2"
+ MIXED_MSYS=yes
+ AC_MSG_RESULT([MSYS and VC])
+ MIXED_MSYS_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_VC=no
+ MIXED_MSYS_VC=no
+fi
+AC_SUBST(MIXED_CYGWIN_VC)
+AC_SUBST(MIXED_MSYS_VC)
+
+MIXED_VC=no
+if test "x$MIXED_MSYS_VC" = "xyes" -o "x$MIXED_CYGWIN_VC" = "xyes" ; then
+ MIXED_VC=yes
+fi
+
+AC_SUBST(MIXED_VC)
+
+if test "x$MIXED_MSYS" != "xyes"; then
+ AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
+ if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([yes])
+ MIXED_CYGWIN_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_MINGW=no
+ fi
+else
+ MIXED_CYGWIN_MINGW=no
+fi
+AC_SUBST(MIXED_CYGWIN_MINGW)
+
+AC_MSG_CHECKING(if we mix cygwin with any native compiler)
+if test "X$MIXED_CYGWIN" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_CYGWIN)
+
+AC_MSG_CHECKING(if we mix msys with another native compiler)
+if test "X$MIXED_MSYS" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_MSYS)
+])
+
+dnl ----------------------------------------------------------------------
+dnl
dnl LM_FIND_EMU_CC
dnl
dnl
@@ -125,8 +214,10 @@ AC_DEFUN(LM_FIND_EMU_CC,
ac_cv_prog_emu_cc,
[
AC_TRY_COMPILE([],[
-#ifdef __llvm__
-#error "llvm is currently unable to compile beam_emu.c"
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
#endif
__label__ lbl1;
__label__ lbl2;
@@ -168,6 +259,11 @@ if test $ac_cv_prog_emu_cc != no; then
CFLAGS=""
CPPFLAGS=""
AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
__label__ lbl1;
__label__ lbl2;
int x = magic();
@@ -511,6 +607,103 @@ ifelse([$5], , , [$5
fi
])
+dnl ----------------------------------------------------------------------
+dnl
+dnl AC_DOUBLE_MIDDLE_ENDIAN
+dnl
+dnl Checks whether doubles are represented in "middle-endian" format.
+dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
+dnl as well as DOUBLE_MIDDLE_ENDIAN.
+dnl
+dnl
+
+AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
+[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
+[# It does not; compile a test program.
+AC_RUN_IFELSE(
+[AC_LANG_SOURCE([[#include <stdlib.h>
+
+int
+main(void)
+{
+ int i = 0;
+ int zero = 0;
+ int bigendian;
+ int zero_index = 0;
+
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+
+ /* we'll use the one with 32-bit words */
+ union
+ {
+ double d;
+ unsigned int c[2];
+ } vint;
+
+ union
+ {
+ double d;
+ unsigned long c[2];
+ } vlong;
+
+ union
+ {
+ double d;
+ unsigned short c[2];
+ } vshort;
+
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ u.l = 1;
+ bigendian = (u.c[sizeof (long int) - 1] == 1);
+
+ zero_index = bigendian ? 1 : 0;
+
+ vint.d = 1.0;
+ vlong.d = 1.0;
+ vshort.d = 1.0;
+
+ if (sizeof(unsigned int) == 4)
+ {
+ if (vint.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned long) == 4)
+ {
+ if (vlong.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned short) == 4)
+ {
+ if (vshort.c[zero_index] != 0)
+ zero = 1;
+ }
+
+ exit (zero);
+}
+]])],
+ [ac_cv_c_double_middle_endian=no],
+ [ac_cv_c_double_middle_endian=yes],
+ [ac_cv_c_double_middle=unknown])])
+case $ac_cv_c_double_middle_endian in
+ yes)
+ m4_default([$1],
+ [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
+ [Define to 1 if your processor stores the words in a double in
+ middle-endian format (like some ARMs).])]) ;;
+ no)
+ $2 ;;
+ *)
+ m4_default([$3],
+ [AC_MSG_WARN([unknown double endianness
+presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
+esac
+])# AC_C_DOUBLE_MIDDLE_ENDIAN
+
dnl ----------------------------------------------------------------------
dnl
@@ -1242,6 +1435,14 @@ if test "$ac_cv_c_bigendian" = "yes"; then
AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
fi
+case X$erl_xcomp_double_middle_endian in
+ X) ;;
+ Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
+esac
+
+AC_C_DOUBLE_MIDDLE_ENDIAN
+
AC_ARG_ENABLE(native-ethr-impls,
AS_HELP_STRING([--disable-native-ethr-impls],
[disable native ethread implementations]),
@@ -1366,9 +1567,6 @@ case "$GCC-$host_cpu" in
;;
esac
-test $enable_ethread_pre_pentium4_compatibility = yes &&
- AC_DEFINE(ETHR_PRE_PENTIUM4_COMPAT, 1, [Define if you want compatibility with x86 processors before pentium4.])
-
AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
[Define if you have all ethread defines])
diff --git a/erts/autoconf/vxworks/sed.general b/erts/autoconf/vxworks/sed.general
index 88697b788d..ac792b44b5 100644
--- a/erts/autoconf/vxworks/sed.general
+++ b/erts/autoconf/vxworks/sed.general
@@ -70,7 +70,6 @@ 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@||
diff --git a/erts/autoconf/win64.config.cache.static b/erts/autoconf/win64.config.cache.static
new file mode 100755
index 0000000000..a8a2bfb59c
--- /dev/null
+++ b/erts/autoconf/win64.config.cache.static
@@ -0,0 +1,271 @@
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+ac_cv_c_bigendian=${ac_cv_c_bigendian=no}
+ac_cv_c_compiler_gnu=${ac_cv_c_compiler_gnu=no}
+ac_cv_c_const=${ac_cv_c_const=yes}
+ac_cv_cxx_compiler_gnu=${ac_cv_cxx_compiler_gnu=no}
+ac_cv_decl_h_errno=${ac_cv_decl_h_errno=no}
+ac_cv_decl_inaddr_loopback=${ac_cv_decl_inaddr_loopback=no}
+ac_cv_decl_inaddr_loopback_rpc=${ac_cv_decl_inaddr_loopback_rpc=no}
+ac_cv_decl_inaddr_loopback_winsock2=${ac_cv_decl_inaddr_loopback_winsock2=yes}
+ac_cv_decl_so_bsdcompat=${ac_cv_decl_so_bsdcompat=no}
+ac_cv_decl_sys_errlist=${ac_cv_decl_sys_errlist=no}
+ac_cv_env_AR_set=set
+ac_cv_env_AR_value=ar.sh
+ac_cv_env_CCC_set=
+ac_cv_env_CCC_value=
+ac_cv_env_CC_set=set
+ac_cv_env_CC_value=cc.sh
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_CXXFLAGS_set=
+ac_cv_env_CXXFLAGS_value=
+ac_cv_env_CXX_set=set
+ac_cv_env_CXX_value=cc.sh
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_build_alias_set=set
+ac_cv_env_build_alias_value=win32
+ac_cv_env_host_alias_set=set
+ac_cv_env_host_alias_value=win32
+ac_cv_env_target_alias_set=set
+ac_cv_env_target_alias_value=win32
+ac_cv_exeext=${ac_cv_exeext=.exe}
+ac_cv_func___brk=${ac_cv_func___brk=no}
+ac_cv_func___sbrk=${ac_cv_func___sbrk=no}
+ac_cv_func__brk=${ac_cv_func__brk=no}
+ac_cv_func__doprnt=${ac_cv_func__doprnt=no}
+ac_cv_func__sbrk=${ac_cv_func__sbrk=no}
+ac_cv_func_accept=${ac_cv_func_accept=no}
+ac_cv_func_alloca_works=${ac_cv_func_alloca_works=yes}
+ac_cv_func_brk=${ac_cv_func_brk=no}
+ac_cv_func_clock_gettime=${ac_cv_func_clock_gettime=no}
+ac_cv_func_connect=${ac_cv_func_connect=no}
+ac_cv_func_decl_fread=${ac_cv_func_decl_fread=yes}
+ac_cv_func_dlopen=${ac_cv_func_dlopen=no}
+ac_cv_func_dup2=${ac_cv_func_dup2=yes}
+ac_cv_func_fdatasync=${ac_cv_func_fdatasync=no}
+ac_cv_func_finite=${ac_cv_func_finite=no}
+ac_cv_func_flockfile=${ac_cv_func_flockfile=no}
+ac_cv_func_fork=${ac_cv_func_fork=no}
+ac_cv_func_fork_works=${ac_cv_func_fork_works=no}
+ac_cv_func_fpsetmask=${ac_cv_func_fpsetmask=no}
+ac_cv_func_fstat=${ac_cv_func_fstat=yes}
+ac_cv_func_gethostbyaddr=${ac_cv_func_gethostbyaddr=no}
+ac_cv_func_gethostbyaddr_r=${ac_cv_func_gethostbyaddr_r=no}
+ac_cv_func_gethostbyname=${ac_cv_func_gethostbyname=yes}
+ac_cv_func_gethostbyname2=${ac_cv_func_gethostbyname2=no}
+ac_cv_func_gethostbyname_r=${ac_cv_func_gethostbyname_r=no}
+ac_cv_func_gethostname=${ac_cv_func_gethostname=no}
+ac_cv_func_gethrtime=${ac_cv_func_gethrtime=no}
+ac_cv_func_getifaddrs=${ac_cv_func_getifaddrs=no}
+ac_cv_func_getipnodebyaddr=${ac_cv_func_getipnodebyaddr=no}
+ac_cv_func_getipnodebyname=${ac_cv_func_getipnodebyname=no}
+ac_cv_func_getpagesize=${ac_cv_func_getpagesize=no}
+ac_cv_func_gettimeofday=${ac_cv_func_gettimeofday=no}
+ac_cv_func_gmtime_r=${ac_cv_func_gmtime_r=no}
+ac_cv_func_ieee_handler=${ac_cv_func_ieee_handler=no}
+ac_cv_func_inet_ntoa=${ac_cv_func_inet_ntoa=no}
+ac_cv_func_inet_pton=${ac_cv_func_inet_pton=yes}
+ac_cv_func_isinf=${ac_cv_func_isinf=no}
+ac_cv_func_isnan=${ac_cv_func_isnan=no}
+ac_cv_func_localtime_r=${ac_cv_func_localtime_r=no}
+ac_cv_func_mallopt=${ac_cv_func_mallopt=no}
+ac_cv_func_memchr=${ac_cv_func_memchr=yes}
+ac_cv_func_memcmp_working=${ac_cv_func_memcmp_working=yes}
+ac_cv_func_memcpy=${ac_cv_func_memcpy=no}
+ac_cv_func_memmove=${ac_cv_func_memmove=yes}
+ac_cv_func_memset=${ac_cv_func_memset=yes}
+ac_cv_func_mmap=${ac_cv_func_mmap=no}
+ac_cv_func_mmap_fixed_mapped=${ac_cv_func_mmap_fixed_mapped=no}
+ac_cv_func_mremap=${ac_cv_func_mremap=no}
+ac_cv_func_nl_langinfo=${ac_cv_func_nl_langinfo=no}
+ac_cv_func_openpty=${ac_cv_func_openpty=no}
+ac_cv_func_poll=${ac_cv_func_poll=no}
+ac_cv_func_posix2time=${ac_cv_func_posix2time=no}
+ac_cv_func_posix_fadvise=${ac_cv_func_posix_fadvise=no}
+ac_cv_func_pread=${ac_cv_func_pread=no}
+ac_cv_func_pwrite=${ac_cv_func_pwrite=no}
+ac_cv_func_res_gethostbyname=${ac_cv_func_res_gethostbyname=no}
+ac_cv_func_sbrk=${ac_cv_func_sbrk=no}
+ac_cv_func_sctp_bindx=${ac_cv_func_sctp_bindx=no}
+ac_cv_func_sctp_peeloff=${ac_cv_func_sctp_peeloff=no}
+ac_cv_func_select=${ac_cv_func_select=no}
+ac_cv_func_setlocale=${ac_cv_func_setlocale=yes}
+ac_cv_func_setsid=${ac_cv_func_setsid=no}
+ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed=yes}
+ac_cv_func_socket=${ac_cv_func_socket=no}
+ac_cv_func_strchr=${ac_cv_func_strchr=yes}
+ac_cv_func_strerror=${ac_cv_func_strerror=yes}
+ac_cv_func_strerror_r=${ac_cv_func_strerror_r=no}
+ac_cv_func_strlcat=${ac_cv_func_strlcat=no}
+ac_cv_func_strlcpy=${ac_cv_func_strlcpy=no}
+ac_cv_func_strncasecmp=${ac_cv_func_strncasecmp=no}
+ac_cv_func_strrchr=${ac_cv_func_strrchr=yes}
+ac_cv_func_strstr=${ac_cv_func_strstr=yes}
+ac_cv_func_uname=${ac_cv_func_uname=no}
+ac_cv_func_vfork=${ac_cv_func_vfork=no}
+ac_cv_func_vfork_works=${ac_cv_func_vfork_works=no}
+ac_cv_func_vprintf=${ac_cv_func_vprintf=yes}
+ac_cv_func_writev=${ac_cv_func_writev=no}
+ac_cv_have_decl_SCTPS_BOUND=${ac_cv_have_decl_SCTPS_BOUND=no}
+ac_cv_have_decl_SCTPS_COOKIE_ECHOED=${ac_cv_have_decl_SCTPS_COOKIE_ECHOED=no}
+ac_cv_have_decl_SCTPS_COOKIE_WAIT=${ac_cv_have_decl_SCTPS_COOKIE_WAIT=no}
+ac_cv_have_decl_SCTPS_ESTABLISHED=${ac_cv_have_decl_SCTPS_ESTABLISHED=no}
+ac_cv_have_decl_SCTPS_IDLE=${ac_cv_have_decl_SCTPS_IDLE=no}
+ac_cv_have_decl_SCTPS_LISTEN=${ac_cv_have_decl_SCTPS_LISTEN=no}
+ac_cv_have_decl_SCTPS_SHUTDOWN_ACK_SENT=${ac_cv_have_decl_SCTPS_SHUTDOWN_ACK_SENT=no}
+ac_cv_have_decl_SCTPS_SHUTDOWN_PENDING=${ac_cv_have_decl_SCTPS_SHUTDOWN_PENDING=no}
+ac_cv_have_decl_SCTPS_SHUTDOWN_RECEIVED=${ac_cv_have_decl_SCTPS_SHUTDOWN_RECEIVED=no}
+ac_cv_have_decl_SCTPS_SHUTDOWN_SENT=${ac_cv_have_decl_SCTPS_SHUTDOWN_SENT=no}
+ac_cv_have_decl_SCTP_ABORT=${ac_cv_have_decl_SCTP_ABORT=no}
+ac_cv_have_decl_SCTP_ADDR_CONFIRMED=${ac_cv_have_decl_SCTP_ADDR_CONFIRMED=no}
+ac_cv_have_decl_SCTP_ADDR_OVER=${ac_cv_have_decl_SCTP_ADDR_OVER=no}
+ac_cv_have_decl_SCTP_BOUND=${ac_cv_have_decl_SCTP_BOUND=no}
+ac_cv_have_decl_SCTP_CLOSED=${ac_cv_have_decl_SCTP_CLOSED=no}
+ac_cv_have_decl_SCTP_COOKIE_ECHOED=${ac_cv_have_decl_SCTP_COOKIE_ECHOED=no}
+ac_cv_have_decl_SCTP_COOKIE_WAIT=${ac_cv_have_decl_SCTP_COOKIE_WAIT=no}
+ac_cv_have_decl_SCTP_DELAYED_ACK_TIME=${ac_cv_have_decl_SCTP_DELAYED_ACK_TIME=no}
+ac_cv_have_decl_SCTP_EMPTY=${ac_cv_have_decl_SCTP_EMPTY=no}
+ac_cv_have_decl_SCTP_EOF=${ac_cv_have_decl_SCTP_EOF=no}
+ac_cv_have_decl_SCTP_ESTABLISHED=${ac_cv_have_decl_SCTP_ESTABLISHED=no}
+ac_cv_have_decl_SCTP_LISTEN=${ac_cv_have_decl_SCTP_LISTEN=no}
+ac_cv_have_decl_SCTP_SENDALL=${ac_cv_have_decl_SCTP_SENDALL=no}
+ac_cv_have_decl_SCTP_SHUTDOWN_ACK_SENT=${ac_cv_have_decl_SCTP_SHUTDOWN_ACK_SENT=no}
+ac_cv_have_decl_SCTP_SHUTDOWN_PENDING=${ac_cv_have_decl_SCTP_SHUTDOWN_PENDING=no}
+ac_cv_have_decl_SCTP_SHUTDOWN_RECEIVED=${ac_cv_have_decl_SCTP_SHUTDOWN_RECEIVED=no}
+ac_cv_have_decl_SCTP_SHUTDOWN_SENT=${ac_cv_have_decl_SCTP_SHUTDOWN_SENT=no}
+ac_cv_have_decl_SCTP_UNORDERED=${ac_cv_have_decl_SCTP_UNORDERED=no}
+ac_cv_have_decl_posix2time=${ac_cv_have_decl_posix2time=no}
+ac_cv_header_arpa_inet_h=${ac_cv_header_arpa_inet_h=no}
+ac_cv_header_arpa_nameser_h=${ac_cv_header_arpa_nameser_h=no}
+ac_cv_header_dirent_dirent_h=${ac_cv_header_dirent_dirent_h=no}
+ac_cv_header_dirent_ndir_h=${ac_cv_header_dirent_ndir_h=no}
+ac_cv_header_dirent_sys_dir_h=${ac_cv_header_dirent_sys_dir_h=no}
+ac_cv_header_dirent_sys_ndir_h=${ac_cv_header_dirent_sys_ndir_h=no}
+ac_cv_header_dlfcn_h=${ac_cv_header_dlfcn_h=no}
+ac_cv_header_fcntl_h=${ac_cv_header_fcntl_h=yes}
+ac_cv_header_gl_gl_h=${ac_cv_header_gl_gl_h=yes}
+ac_cv_header_ieeefp_h=${ac_cv_header_ieeefp_h=no}
+ac_cv_header_ifaddrs_h=${ac_cv_header_ifaddrs_h=no}
+ac_cv_header_inttypes_h=${ac_cv_header_inttypes_h=no}
+ac_cv_header_langinfo_h=${ac_cv_header_langinfo_h=no}
+ac_cv_header_limits_h=${ac_cv_header_limits_h=yes}
+ac_cv_header_mach_o_dyld_h=${ac_cv_header_mach_o_dyld_h=no}
+ac_cv_header_malloc_h=${ac_cv_header_malloc_h=yes}
+ac_cv_header_memory_h=${ac_cv_header_memory_h=yes}
+ac_cv_header_net_errno_h=${ac_cv_header_net_errno_h=no}
+ac_cv_header_net_if_dl_h=${ac_cv_header_net_if_dl_h=no}
+ac_cv_header_netdb_h=${ac_cv_header_netdb_h=no}
+ac_cv_header_netinet_in_h=${ac_cv_header_netinet_in_h=no}
+ac_cv_header_netpacket_packet_h=${ac_cv_header_netpacket_packet_h=no}
+ac_cv_header_poll_h=${ac_cv_header_poll_h=no}
+ac_cv_header_pty_h=${ac_cv_header_pty_h=no}
+ac_cv_header_stdc=${ac_cv_header_stdc=yes}
+ac_cv_header_stddef_h=${ac_cv_header_stddef_h=yes}
+ac_cv_header_stdint_h=${ac_cv_header_stdint_h=yes}
+ac_cv_header_stdlib_h=${ac_cv_header_stdlib_h=yes}
+ac_cv_header_string_h=${ac_cv_header_string_h=yes}
+ac_cv_header_strings_h=${ac_cv_header_strings_h=no}
+ac_cv_header_sys_devpoll_h=${ac_cv_header_sys_devpoll_h=no}
+ac_cv_header_sys_epoll_h=${ac_cv_header_sys_epoll_h=no}
+ac_cv_header_sys_event_h=${ac_cv_header_sys_event_h=no}
+ac_cv_header_sys_ioctl_h=${ac_cv_header_sys_ioctl_h=no}
+ac_cv_header_sys_param_h=${ac_cv_header_sys_param_h=no}
+ac_cv_header_sys_resource_h=${ac_cv_header_sys_resource_h=no}
+ac_cv_header_sys_select_h=${ac_cv_header_sys_select_h=no}
+ac_cv_header_sys_socket_h=${ac_cv_header_sys_socket_h=no}
+ac_cv_header_sys_socketio_h=${ac_cv_header_sys_socketio_h=no}
+ac_cv_header_sys_sockio_h=${ac_cv_header_sys_sockio_h=no}
+ac_cv_header_sys_stat_h=${ac_cv_header_sys_stat_h=yes}
+ac_cv_header_sys_stropts_h=${ac_cv_header_sys_stropts_h=no}
+ac_cv_header_sys_sysctl_h=${ac_cv_header_sys_sysctl_h=no}
+ac_cv_header_sys_time_h=${ac_cv_header_sys_time_h=no}
+ac_cv_header_sys_types_h=${ac_cv_header_sys_types_h=yes}
+ac_cv_header_sys_uio_h=${ac_cv_header_sys_uio_h=no}
+ac_cv_header_sys_wait_h=${ac_cv_header_sys_wait_h=no}
+ac_cv_header_syslog_h=${ac_cv_header_syslog_h=no}
+ac_cv_header_time=${ac_cv_header_time=no}
+ac_cv_header_unistd_h=${ac_cv_header_unistd_h=no}
+ac_cv_header_util_h=${ac_cv_header_util_h=no}
+ac_cv_header_utmp_h=${ac_cv_header_utmp_h=no}
+ac_cv_header_valgrind_valgrind_h=${ac_cv_header_valgrind_valgrind_h=no}
+ac_cv_header_vfork_h=${ac_cv_header_vfork_h=no}
+ac_cv_header_windows_h=${ac_cv_header_windows_h=yes}
+ac_cv_header_winsock2_h=${ac_cv_header_winsock2_h=yes}
+ac_cv_header_ws2tcpip_h=${ac_cv_header_ws2tcpip_h=yes}
+ac_cv_lib_dl_dlopen=${ac_cv_lib_dl_dlopen=no}
+ac_cv_lib_inet_main=${ac_cv_lib_inet_main=no}
+ac_cv_lib_kstat_kstat_open=${ac_cv_lib_kstat_kstat_open=no}
+ac_cv_lib_m_sin=${ac_cv_lib_m_sin=no}
+ac_cv_lib_nsl_gethostbyname=${ac_cv_lib_nsl_gethostbyname=no}
+ac_cv_lib_nsl_main=${ac_cv_lib_nsl_main=no}
+ac_cv_lib_resolv_res_gethostbyname=${ac_cv_lib_resolv_res_gethostbyname=no}
+ac_cv_lib_rt_clock_gettime=${ac_cv_lib_rt_clock_gettime=no}
+ac_cv_lib_socket_getpeername=${ac_cv_lib_socket_getpeername=no}
+ac_cv_lib_socket_main=${ac_cv_lib_socket_main=yes}
+ac_cv_lib_socket_socket=${ac_cv_lib_socket_socket=no}
+ac_cv_lib_util_openpty=${ac_cv_lib_util_openpty=no}
+ac_cv_lib_ws2_32_main=${ac_cv_lib_ws2_32_main=yes}
+ac_cv_member_struct_ErlDrvEntry_stop_select=${ac_cv_member_struct_ErlDrvEntry_stop_select=no}
+ac_cv_member_struct_sctp_paddrparams_spp_flags=${ac_cv_member_struct_sctp_paddrparams_spp_flags=no}
+ac_cv_member_struct_sctp_paddrparams_spp_pathmtu=${ac_cv_member_struct_sctp_paddrparams_spp_pathmtu=no}
+ac_cv_member_struct_sctp_paddrparams_spp_sackdelay=${ac_cv_member_struct_sctp_paddrparams_spp_sackdelay=no}
+ac_cv_member_struct_sctp_remote_error_sre_data=${ac_cv_member_struct_sctp_remote_error_sre_data=no}
+ac_cv_member_struct_sctp_send_failed_ssf_data=${ac_cv_member_struct_sctp_send_failed_ssf_data=no}
+ac_cv_objext=${ac_cv_objext=o}
+ac_cv_path_MKDIR=${ac_cv_path_MKDIR=/bin/mkdir}
+ac_cv_path_RM=${ac_cv_path_RM=/bin/rm}
+ac_cv_prog_AR=${ac_cv_prog_AR=ar.sh}
+ac_cv_prog_CC=${ac_cv_prog_CC=cc.sh}
+ac_cv_prog_CPP=${ac_cv_prog_CPP='cc.sh -E'}
+ac_cv_prog_CXX=${ac_cv_prog_CXX=cc.sh}
+ac_cv_prog_DED_LD=${ac_cv_prog_DED_LD=ld.sh}
+ac_cv_prog_JAVAC=${ac_cv_prog_JAVAC=javac.sh}
+ac_cv_prog_M4=${ac_cv_prog_M4=m4}
+ac_cv_prog_RANLIB=${ac_cv_prog_RANLIB=true}
+ac_cv_prog_cc_c89=${ac_cv_prog_cc_c89=}
+ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes}
+ac_cv_search_fdatasync=${ac_cv_search_fdatasync=no}
+ac_cv_search_opendir=${ac_cv_search_opendir=no}
+ac_cv_search_strerror=${ac_cv_search_strerror='none required'}
+ac_cv_sizeof___int64=${ac_cv_sizeof___int64=8}
+ac_cv_sizeof_char=${ac_cv_sizeof_char=1}
+ac_cv_sizeof_int=${ac_cv_sizeof_int=4}
+ac_cv_sizeof_long=${ac_cv_sizeof_long=4}
+ac_cv_sizeof_long_long=${ac_cv_sizeof_long_long=8}
+ac_cv_sizeof_off_t=${ac_cv_sizeof_off_t=4}
+ac_cv_sizeof_short=${ac_cv_sizeof_short=2}
+ac_cv_sizeof_size_t=${ac_cv_sizeof_size_t=8}
+ac_cv_sizeof_void_p=${ac_cv_sizeof_void_p=8}
+ac_cv_struct_exception=${ac_cv_struct_exception=no}
+ac_cv_struct_sockaddr_sa_len=${ac_cv_struct_sockaddr_sa_len=no}
+ac_cv_struct_tm=${ac_cv_struct_tm=time.h}
+ac_cv_type_off_t=${ac_cv_type_off_t=yes}
+ac_cv_type_pid_t=${ac_cv_type_pid_t=no}
+ac_cv_type_signal=${ac_cv_type_signal=void}
+ac_cv_type_size_t=${ac_cv_type_size_t=yes}
+ac_cv_type_uid_t=${ac_cv_type_uid_t=no}
+ac_cv_working_alloca_h=${ac_cv_working_alloca_h=no}
+erl_cv_time_correction=${erl_cv_time_correction=none}
+erts_cv___after_morecore_hook_can_track_malloc=${erts_cv___after_morecore_hook_can_track_malloc=no}
+erts_cv_fwrite_unlocked=${erts_cv_fwrite_unlocked=no}
+erts_cv_have__end_symbol=${erts_cv_have__end_symbol=no}
+erts_cv_have_end_symbol=${erts_cv_have_end_symbol=no}
+erts_cv_putc_unlocked=${erts_cv_putc_unlocked=no}
+erts_cv_windows_h_includes_winsock2_h=${erts_cv_windows_h_includes_winsock2_h=no}
diff --git a/erts/configure.in b/erts/configure.in
index fafa1c7e92..8d70a1b74a 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1997-2011. All Rights Reserved.
+dnl Copyright Ericsson AB 1997-2012. 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
@@ -157,14 +157,6 @@ AS_HELP_STRING([--without-termcap],
[],
[with_termcap=yes])
-
-AC_ARG_ENABLE(hybrid-heap,
-AS_HELP_STRING([--enable-hybrid-heap], [enable hybrid heap]),
-[ case "$enableval" in
- no) enable_hybrid_heap=no ;;
- *) enable_hybrid_heap=yes ;;
- esac ], enable_hybrid_heap=unknown)
-
AC_ARG_ENABLE(lock-checking,
AS_HELP_STRING([--enable-lock-checking], [enable lock checking]),
[ case "$enableval" in
@@ -191,7 +183,7 @@ AS_HELP_STRING([--disable-kernel-poll], [disable kernel poll support]),
AC_ARG_ENABLE(sctp,
-AS_HELP_STRING([--enable-sctp], [enable sctp support])
+AS_HELP_STRING([--enable-sctp], [enable sctp support (default)])
AS_HELP_STRING([--disable-sctp], [disable sctp support]),
[ case "$enableval" in
no) enable_sctp=no ;;
@@ -276,6 +268,61 @@ else
[Define to enable hrvtime() on Linux systems with perfctr extension])
fi
+
+AC_ARG_WITH(dynamic-trace,
+AS_HELP_STRING([--with-dynamic-trace={dtrace|systemtap}],
+ [specify use of dynamic trace framework, dtrace or systemtap])
+AS_HELP_STRING([--without-dynamic-trace],
+ [don't enable any dynamic tracing (default)]))
+
+if test X"$with_dynamic_trace" = X""; then
+ with_dynamic_trace=no
+fi
+
+case "$with_dynamic_trace" in
+ no) DYNAMIC_TRACE_FRAMEWORK=;;
+ dtrace)
+ AC_DEFINE(USE_DTRACE,[1],
+ [Define if you want to use dtrace for dynamic tracing])
+ DYNAMIC_TRACE_FRAMEWORK=dtrace;;
+ systemtap)
+ AC_DEFINE(USE_SYSTEMTAP,[1],
+ [Define if you want to use systemtap for dynamic tracing])
+ DYNAMIC_TRACE_FRAMEWORK=systemtap;;
+ *)
+ AC_MSG_ERROR(Unknown dynamic tracing framework specified with --with-dynamic-trace!);;
+esac
+
+if test X"$DYNAMIC_TRACE_FRAMEWORK" != X""; then
+ AC_DEFINE(USE_DYNAMIC_TRACE,[1],
+ [Define if you want to use dynamic tracing])
+fi
+
+AC_ARG_ENABLE(vm-probes,
+AS_HELP_STRING([--enable-vm-probes],
+ [add dynamic trace probes to the Beam VM (only possible if --with-dynamic-trace is enabled, and then default)]),
+ [ case "$enableval" in
+ no) use_vm_probes=no ;;
+ *)
+ if test X"$DYNAMIC_TRACE_FRAMEWORK" != X""; then
+ use_vm_probes=yes ;
+ else
+ AC_MSG_ERROR(Can not enable VM probes without any dynamic tracing framework!);
+ fi;;
+ esac ], if test X"$DYNAMIC_TRACE_FRAMEWORK" != X""; then
+ use_vm_probes=yes ;
+ else
+ use_vm_probes=no
+ fi)
+
+AC_SUBST(USE_VM_PROBES)
+if test X"$use_vm_probes" = X"yes"; then
+ USE_VM_PROBES=yes
+ AC_DEFINE(USE_VM_PROBES,[1],
+ [Define to enable VM dynamic trace probes])
+fi
+
+
AC_ARG_ENABLE(clock-gettime,
AS_HELP_STRING([--enable-clock-gettime],
[use clock-gettime for time correction]),
@@ -383,12 +430,6 @@ case $host_os in
# The ethread library requires _WIN32_WINNT of at least 0x0403.
# -D_WIN32_WINNT=* from CPPFLAGS is saved in ETHR_DEFS.
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0500 -DWINVER=0x0500"
- # _USE_32BIT_TIME_T is needed when using VC++ 2005 (ctime() will fail
- # otherwise since we pass it a 32-bit value).
- #
- # FIXME: Use time_t all the way and remove _USE_32BIT_TIME_T.
- AC_MSG_WARN([Reverting to 32-bit time_t])
- CPPFLAGS="$CPPFLAGS -D_USE_32BIT_TIME_T"
;;
darwin*)
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE"
@@ -398,53 +439,7 @@ case $host_os in
esac
-
-MIXED_CYGWIN=no
-
-AC_MSG_CHECKING(for mixed cygwin and native VC++ environment)
-if test "X$host" = "Xwin32" -a "x$GCC" != x"yes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_VC=yes
- CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_VC=no
-fi
-AC_SUBST(MIXED_CYGWIN_VC)
-
-AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
-if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_MINGW=yes
- CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_MINGW=no
-fi
-AC_SUBST(MIXED_CYGWIN_MINGW)
-
-AC_MSG_CHECKING(if we mix cygwin with any native compiler)
-if test "X$MIXED_CYGWIN" = "Xyes" ; then
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(MIXED_CYGWIN)
+LM_WINDOWS_ENVIRONMENT
dnl
dnl Flags to the C compiler
@@ -490,7 +485,6 @@ CFLAG_RUNTIME_LIBRARY_PATH="-Wl,-R"
case $host_os in
darwin*)
CFLAG_RUNTIME_LIBRARY_PATH=
- CFLAGS="$CFLAGS -no-cpp-precomp"
;;
win32)
CFLAG_RUNTIME_LIBRARY_PATH=
@@ -624,6 +618,8 @@ case $chk_arch_ in
armv5b) ARCH=arm;;
armv5teb) ARCH=arm;;
armv5tel) ARCH=arm;;
+ armv5tejl) ARCH=arm;;
+ armv7l) ARCH=arm;;
tile) ARCH=tile;;
*) ARCH=noarch;;
esac
@@ -1467,9 +1463,71 @@ AC_CHECK_HEADERS(fcntl.h limits.h unistd.h syslog.h dlfcn.h ieeefp.h \
sys/types.h sys/stropts.h sys/sysctl.h \
sys/ioctl.h sys/time.h sys/uio.h \
sys/socket.h sys/sockio.h sys/socketio.h \
- net/errno.h malloc.h arpa/nameser.h \
+ net/errno.h malloc.h arpa/nameser.h libdlpi.h \
pty.h util.h utmp.h langinfo.h poll.h sdkddkver.h)
+AC_CHECK_MEMBERS([struct ifreq.ifr_hwaddr], [], [],
+ [#ifdef __WIN32__
+ #else
+ #ifdef VXWORKS
+ #else
+ #include <net/if.h>
+ #endif
+ #endif
+ ])
+
+AC_CHECK_MEMBERS([struct ifreq.ifr_enaddr], [], [],
+ [#ifdef __WIN32__
+ #else
+ #ifdef VXWORKS
+ #else
+ #include <net/if.h>
+ #endif
+ #endif
+ ])
+
+dnl ----------------------------------------------------------------------
+dnl Check the availability for libdlpi
+dnl ----------------------------------------------------------------------
+AC_CHECK_LIB(dlpi, dlpi_open)
+if test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"; then
+ unset -v ac_cv_lib_dlpi_dlpi_open
+ dnl Try again now with -L/lib (or ditto 64) as argument to linker since
+ dnl gcc makes /usr/ccs/bin/ld ignore the crle configured linker default paths
+ dnl typically causing dlpi not being found on Solaris et.al
+ save_ldflags="$LDFLAGS"
+ try_dlpi_lib=/lib
+ if test x"$ac_cv_sizeof_void_p" = x"8"; then
+ if test -d /lib64; then
+ try_dlpi_lib=/lib64
+ elif test -d /lib/64; then
+ try_dlpi_lib=/lib/64
+ fi
+ fi
+ if test ! -f "$try_dlpi_lib/libdlpi.so" && \
+ test -f "$try_dlpi_lib/libdlpi.so.1"
+ then
+ dnl It looks like there is a missing symlink
+ dnl - let's be helpful and notify the user
+ dnl NOTE this help is far from perfect e.g if there would be no
+ dnl *.so.1 but a *.so.1.123 or *.so.2 this will be no help
+ AC_MSG_ERROR(
+ [Your OS installation is missing a symbolic link.
+ Maybe it lacks some development package(s)...
+ It can anyhow be fixed with the following command:
+ # ln -s libdlpi.so.1 $try_dlpi_lib/libdlpi.so
+ ])
+ fi
+ LDFLAGS="-L$try_dlpi_lib -R$try_dlpi_lib $LDFLAGS"
+ unset -v try_dlpi_lib
+ AC_MSG_NOTICE([Extending the search to include /lib])
+ AC_CHECK_LIB(dlpi, dlpi_open)
+ if test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"; then
+ LDFLAGS="$save_ldflags"
+ fi
+ unset -v save_ldflags
+fi
+
AC_CHECK_HEADER(sys/resource.h,
[AC_DEFINE(HAVE_SYS_RESOURCE_H, 1,
[Define to 1 if you have the <sys/resource.h> header file])
@@ -1486,7 +1544,7 @@ AC_CHECK_HEADER(sys/devpoll.h, have_kernel_poll=/dev/poll)
dnl Check for kernel SCTP support
AC_SUBST(LIBSCTP)
-if test "x$enable_sctp" = "xyes" ; then
+if test "x$enable_sctp" != "xno" ; then
AC_CHECK_HEADER(netinet/sctp.h,
[LIBSCTP=libsctp.so.1
AC_DEFINE(HAVE_SCTP_H, [1],
@@ -1496,8 +1554,24 @@ if test "x$enable_sctp" = "xyes" ; then
#include <sys/socket.h>
#endif
])
+fi
+
+if test x"$ac_cv_header_netinet_sctp_h" = x"yes"; then
+ AC_CHECK_FUNCS([sctp_bindx sctp_peeloff])
AC_CHECK_DECLS([SCTP_UNORDERED, SCTP_ADDR_OVER, SCTP_ABORT,
- SCTP_EOF, SCTP_SENDALL, SCTP_ADDR_CONFIRMED], [], [],
+ SCTP_EOF, SCTP_SENDALL, SCTP_ADDR_CONFIRMED,
+ SCTP_DELAYED_ACK_TIME,
+ SCTP_EMPTY,
+ SCTP_CLOSED, SCTPS_IDLE,
+ SCTP_BOUND, SCTPS_BOUND,
+ SCTP_LISTEN, SCTPS_LISTEN,
+ SCTP_COOKIE_WAIT, SCTPS_COOKIE_WAIT,
+ SCTP_COOKIE_ECHOED, SCTPS_COOKIE_ECHOED,
+ SCTP_ESTABLISHED, SCTPS_ESTABLISHED,
+ SCTP_SHUTDOWN_PENDING, SCTPS_SHUTDOWN_PENDING,
+ SCTP_SHUTDOWN_SENT, SCTPS_SHUTDOWN_SENT,
+ SCTP_SHUTDOWN_RECEIVED, SCTPS_SHUTDOWN_RECEIVED,
+ SCTP_SHUTDOWN_ACK_SENT, SCTPS_SHUTDOWN_ACK_SENT], [], [],
[#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -1564,6 +1638,7 @@ AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(size_t)
AC_CHECK_SIZEOF(off_t)
+AC_CHECK_SIZEOF(time_t)
BITS64=
@@ -1655,6 +1730,7 @@ case X$erl_xcomp_bigendian in
esac
AC_C_BIGENDIAN
+AC_C_DOUBLE_MIDDLE_ENDIAN
dnl fdatasync syscall (Unix only)
AC_CHECK_FUNCS([fdatasync])
@@ -1665,6 +1741,24 @@ dnl fdatasync requires linking against -lrt on SunOS <= 5.10.
dnl OpenSolaris 2009.06 is SunOS 5.11 and does not require -lrt.
AC_SEARCH_LIBS(fdatasync, [rt])
+
+dnl sendfile syscall
+case $host_os in
+ linux*|freebsd*|dragonfly*|darwin*)
+ AC_CHECK_FUNCS([sendfile])
+ ;;
+ solaris*)
+ AC_SEARCH_LIBS(sendfilev, sendfile,
+ AC_DEFINE([HAVE_SENDFILEV],[1],
+ [Define to 1 if you have the `sendfilev' function.]))
+ ;;
+ win32)
+ LIBS="$LIBS -lmswsock"
+ ;;
+ *)
+ ;;
+esac
+
dnl ----------------------------------------------------------------------
dnl Checks for library functions.
dnl ----------------------------------------------------------------------
@@ -1788,9 +1882,10 @@ AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlop
pread pwrite writev memmove strerror strerror_r strncasecmp \
gethrtime localtime_r gmtime_r inet_pton mmap mremap memcpy mallopt \
sbrk _sbrk __sbrk brk _brk __brk \
- flockfile fstat strlcpy strlcat setsid posix2time setlocale nl_langinfo poll])
+ flockfile fstat strlcpy strlcat setsid posix2time time2posix \
+ setlocale nl_langinfo poll])
-AC_CHECK_DECLS([posix2time],,,[#include <time.h>])
+AC_CHECK_DECLS([posix2time, time2posix],,,[#include <time.h>])
disable_vfork=false
if test "x$EMU_THR_LIB_NAME" != "x"; then
@@ -1850,6 +1945,64 @@ AC_CHECK_FUNCS([openpty])
AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h netpacket/packet.h)
AC_CHECK_FUNCS([getifaddrs])
+dnl Checks for variables in6addr_any and in6addr_loopback,
+dnl
+dnl They normally declared by netinet/in.h, according to POSIX,
+dnl but not on Windows 7 (Windows SDK 7.1). I would have liked
+dnl to just write AC_CHECK_DECL([in6addr_any], ...) but if doing so,
+dnl the configure check fails erroneously on Linux with the error
+dnl "cannot convert to a pointer type", on a line looking like
+dnl "char *p = (char *) in6addr_any;", so work around that
+dnl with some more code.
+AC_CACHE_CHECK(
+ [whether in6addr_any is declared],
+ [erts_cv_have_in6addr_any],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ ]],
+ [[printf("%d", in6addr_any.s6_addr[16]);]]
+ )],
+ [erts_cv_have_in6addr_any=yes],
+ [erts_cv_have_in6addr_any=no]
+ )]
+)
+
+case "$erts_cv_have_in6addr_any" in
+ yes)
+ AC_DEFINE([HAVE_IN6ADDR_ANY], [1],
+ [Define to 1 if you have the variable in6addr_any declared.])
+esac
+
+AC_CACHE_CHECK(
+ [whether in6addr_loopback is declared],
+ [erts_cv_have_in6addr_loopback],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ ]],
+ [[printf("%d", in6addr_loopback.s6_addr[16]);]]
+ )],
+ [erts_cv_have_in6addr_loopback=yes],
+ [erts_cv_have_in6addr_loopback=no]
+ )]
+)
+
+case "$erts_cv_have_in6addr_loopback" in
+ yes)
+ AC_DEFINE([HAVE_IN6ADDR_LOOPBACK], [1],
+ [Define to 1 if you have the variable in6addr_loopback declared.])
+esac
+
+AC_CHECK_DECLS([IN6ADDR_ANY_INIT, IN6ADDR_LOOPBACK_INIT], [], [],
+ [#include <netinet/in.h>])
+
dnl ----------------------------------------------------------------------
dnl Checks for features/quirks in the system that affects Erlang.
dnl ----------------------------------------------------------------------
@@ -2433,6 +2586,17 @@ case $ARCH-$OPSYS in
darwin_mcontext_leopard=no
;;
esac
+
+if test X${enable_fp_exceptions} = Xauto ; then
+ case $host_os in
+ darwin*)
+ enable_fp_exceptions=no
+ AC_MSG_NOTICE([Floating point exceptions disabled by default on MacOS X]) ;;
+ *)
+ ;;
+ esac
+fi
+
if test X${enable_fp_exceptions} = Xauto ; then
if test X${enable_hipe} = Xyes; then
enable_fp_exceptions=yes
@@ -2480,7 +2644,7 @@ static void new_fp_exception(void)
* Implement unmask_fpe() and check_fpe() based on CPU/OS combination
*/
-#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) && !defined(__CYGWIN__)
+#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
static void unmask_x87(void)
{
@@ -3024,33 +3188,6 @@ fi
AC_SUBST(TSP_APP)
#
-# Check if we should build hybrid emulator
-#
-
-AC_MSG_CHECKING([whether a hybrid heap emulator should be built])
-case $enable_hybrid_heap-$host_os in
- yes-*)
- AC_MSG_RESULT([yes; enabled by user])
- ERTS_BUILD_HYBRID_EMU=yes;;
- no-*)
- AC_MSG_RESULT([no; disabled by user])
- ERTS_BUILD_HYBRID_EMU=no;;
- *-win32|*-vxworks) # vxworks have their own "configure scripts"...
- AC_MSG_RESULT([no; default on this platform])
- ERTS_BUILD_HYBRID_EMU=no;;
- *)
- AC_MSG_RESULT([yes; default on this platform])
- ERTS_BUILD_HYBRID_EMU=yes;;
-esac
-
-
-if test $ERTS_BUILD_HYBRID_EMU = yes; then
- AC_DEFINE(ERTS_HAVE_HYBRID_EMU, 1, [Define if the hybrid emulator is built])
-fi
-
-AC_SUBST(ERTS_BUILD_HYBRID_EMU)
-
-#
# Check if we should enable HiPE.
#
@@ -3063,8 +3200,6 @@ dnl done up where floating point is checked, need to descide there already...
if test X${enable_hipe} = Xyes; then
if test X$ac_cv_sizeof_void_p != X4 -a X$ARCH != Xamd64 -a X$ARCH != Xppc64; then
AC_MSG_WARN([HiPE is not supported in 64-bit builds])
- elif test X$FPE != Xreliable -a X$ARCH != Xarm; then
- AC_MSG_WARN([HiPE is not supported on $ARCH without reliable floating-point exceptions])
else
HIPE_ENABLED=yes
AC_DEFINE(HIPE,[1],[Define to enable HiPE])
@@ -3493,6 +3628,74 @@ dnl
LM_FIND_EMU_CC
dnl
+dnl DTrace
+dnl
+case $DYNAMIC_TRACE_FRAMEWORK in
+ dtrace|systemtap)
+ AC_CHECK_TOOL(DTRACE, dtrace, none)
+ test "$DTRACE" = "none" && AC_MSG_ERROR([No dtrace utility found.]);
+ enable_dtrace_test=yes;;
+ *) enable_dtrace_test=no;;
+esac
+
+AC_SUBST(DTRACE)
+
+AC_SUBST(DTRACE_CPP)
+AC_SUBST(DTRACE_ENABLED)
+AC_SUBST(DTRACE_ENABLED_2STEP)
+DTRACE_CPP=-C
+DTRACE_ENABLED=
+DTRACE_ENABLED_2STEP=
+DTRACE_2STEP_TEST=./dtrace-test.o
+DTRACE_BITS_FLAG=
+case $OPSYS in
+ freebsd)
+ if test "$BITS64" = "yes" ; then
+ DTRACE_BITS_FLAG=-64
+ else
+ DTRACE_BITS_FLAG=-32
+ fi
+ ;;
+ *)
+ : # Nothing to do
+ ;;
+esac
+if test "$enable_dtrace_test" = "yes" ; then
+ if test "$DTRACE" = "dtrace" ; then
+ AC_CHECK_HEADERS(sys/sdt.h)
+ # The OS X version of dtrace prints a spurious line here.
+ if ! dtrace -h $DTRACE_CPP -Iemulator/beam -o ./foo-dtrace.h -s emulator/beam/erlang_dtrace.d; then
+ AC_MSG_ERROR([Could not precompile erlang_dtrace.d: dtrace -h failed])
+ fi
+ rm -f foo-dtrace.h
+
+ $RM -f $DTRACE_2STEP_TEST
+ if dtrace -G $DTRACE_CPP $DTRACE_BITS_FLAG -Iemulator/beam -o $DTRACE_2STEP_TEST -s emulator/beam/erlang_dtrace.d 2> /dev/null && \
+ test -f $DTRACE_2STEP_TEST ; then
+ rm $DTRACE_2STEP_TEST
+ DTRACE_ENABLED_2STEP=yes
+ AC_MSG_NOTICE([dtrace precompilation for 2-stage DTrace successful])
+ else
+ AC_MSG_NOTICE([dtrace precompilation for 1-stage DTrace successful])
+ fi
+ DTRACE_ENABLED=yes
+ case $OPSYS in
+ linux)
+ : # No extra libs to add to LIBS
+ ;;
+ freebsd)
+ LIBS="$LIBS -lelf"
+ ;;
+ *)
+ LIBS="$LIBS -ldtrace"
+ ;;
+ esac
+ else
+ AC_MSG_ERROR([Dtrace preprocessing test failed.])
+ fi
+fi
+
+dnl
dnl SSL, SSH and CRYPTO need the OpenSSL libraries
dnl
dnl Check flags --with-ssl, --without-ssl --with-ssl=PATH.
@@ -3535,7 +3738,7 @@ elif test "x$with_ssl_zlib" = "xyes" || test "x$with_ssl_zlib" = "x"; then
AC_MSG_WARN([Cannot search for zlib; missing cross system root (erl_xcomp_sysroot).])
SSL_LINK_WITH_ZLIB=no
STATIC_ZLIB_LIBS=
- elif test "x$MIXED_CYGWIN" = "xyes"; then
+ elif test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
SSL_LINK_WITH_ZLIB=no
STATIC_ZLIB_LIBS=
else
@@ -3647,16 +3850,23 @@ case "$erl_xcomp_without_sysroot-$with_ssl" in
AC_CHECK_PROG(REGTOOL, regtool, regtool, false)
if test "$ac_cv_prog_REGTOOL" != false; then
wrp="/machine/software/microsoft/windows/currentversion/"
- urp="uninstall/openssl_is1/inno setup: app path"
+ if test "x$ARCH" = "xamd64"; then
+ urp="uninstall/openssl (64-bit)_is1/inno setup: app path"
+ regtool_subsystem=-w
+ else
+ urp="uninstall/openssl (32-bit)_is1/inno setup: app path"
+ regtool_subsystem=-W
+ fi
rp="$wrp$urp"
- if regtool -q get "$rp" > /dev/null; then
+ if regtool -q $regtool_subsystem get "$rp" > /dev/null; then
true
else
- urp="uninstall/openssl (32-bit)_is1/inno setup: app path"
+ # Fallback to unspecified wordlength
+ urp="uninstall/openssl_is1/inno setup: app path"
rp="$wrp$urp"
fi
- if regtool -q get "$rp" > /dev/null; then
- ssl_install_dir=`regtool -q get "$rp"`
+ if regtool -q $regtool_subsystem get "$rp" > /dev/null; then
+ ssl_install_dir=`regtool -q $regtool_subsystem get "$rp"`
# Try hard to get rid of spaces...
if cygpath -d "$ssl_install_dir" > /dev/null 2>&1; then
ssl_install_dir=`cygpath -d "$ssl_install_dir"`
@@ -3664,6 +3874,20 @@ case "$erl_xcomp_without_sysroot-$with_ssl" in
extra_dir=`cygpath $ssl_install_dir`
fi
fi
+ elif test "x$MIXED_MSYS" = "xyes"; then
+ AC_CHECK_PROG(REGTOOL, reg_query.sh, reg_query.sh, false)
+ if test "$ac_cv_prog_REGTOOL" != false; then
+ if test "x$ARCH" = "xamd64"; then
+ rp="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/OpenSSL (64-bit)_is1"
+ else
+ rp="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/OpenSSL_is1"
+ fi
+ key="Inno Setup: App Path"
+ if "$ac_cv_prog_REGTOOL" "$rp" "$key" > /dev/null; then
+ ssl_install_dir=`"$ac_cv_prog_REGTOOL" "$rp" "$key"`
+ extra_dir=`win2msys_path.sh "$ssl_install_dir"`
+ fi
+ fi
fi
# We search for OpenSSL in the common OS standard locations.
SSL_APP=ssl
@@ -3672,14 +3896,25 @@ case "$erl_xcomp_without_sysroot-$with_ssl" in
SSL_CRYPTO_LIBNAME=crypto
SSL_SSL_LIBNAME=ssl
+
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ if test "x$ARCH" = "xamd64"; then
+ std_win_ssl_locations="/cygdrive/c/OpenSSL-Win64 /c/OpenSSL-Win64 /opt/local64/pgm/OpenSSL"
+ else
+ std_win_ssl_locations="/cygdrive/c/OpenSSL-Win32 /c/OpenSSL-Win32 /cygdrive/c/OpenSSL /c/OpenSSL /opt/local/pgm/OpenSSL"
+ fi
+ else
+ std_win_ssl_locations=""
+ fi
+
AC_MSG_CHECKING(for OpenSSL >= 0.9.7 in standard locations)
- for rdir in $extra_dir /cygdrive/c/OpenSSL $std_ssl_locations; do
+ for rdir in $extra_dir $std_win_ssl_locations $std_ssl_locations; do
dir="$erl_xcomp_sysroot$rdir"
if test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"; then
is_real_ssl=yes
SSL_ROOT="$dir"
- if test "x$MIXED_CYGWIN" = "xyes" ; then
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
if test -f "$dir/lib/VC/libeay32.lib"; then
SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
SSL_LIBDIR="$dir/lib/VC"
@@ -3754,7 +3989,7 @@ case "$erl_xcomp_without_sysroot-$with_ssl" in
])
CPPFLAGS=$old_CPPFLAGS
if test "x$ssl_found" = "xyes"; then
- if test "x$MIXED_CYGWIN" = "xyes" ; then
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
ssl_linkable=yes
else
saveCFLAGS="$CFLAGS"
@@ -3866,7 +4101,7 @@ dnl so it is - be adoptable
SSL_ROOT="$with_ssl"
SSL_CRYPTO_LIBNAME=crypto
SSL_SSL_LIBNAME=ssl
- if test "x$MIXED_CYGWIN" = "xyes" && test -d "$with_ssl/lib/VC"; then
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes" && test -d "$with_ssl/lib/VC"; then
if test -f "$with_ssl/lib/VC/libeay32.lib"; then
SSL_LIBDIR="$with_ssl/lib/VC"
SSL_CRYPTO_LIBNAME=libeay32
@@ -4280,7 +4515,6 @@ AH_BOTTOM([
#endif
])
-
dnl ----------------------------------------------------------------------
dnl Output the result.
dnl ----------------------------------------------------------------------
@@ -4289,7 +4523,6 @@ dnl Note that the output files are relative to $srcdir
AC_OUTPUT(
emulator/$host/Makefile:emulator/Makefile.in
- emulator/zlib/$host/Makefile:emulator/zlib/Makefile.in
epmd/src/$host/Makefile:epmd/src/Makefile.in
etc/common/$host/Makefile:etc/common/Makefile.in
include/internal/$host/ethread.mk:include/internal/ethread.mk.in
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile
index cfa5527474..13cf003aad 100644
--- a/erts/doc/src/Makefile
+++ b/erts/doc/src/Makefile
@@ -174,15 +174,15 @@ $(SPECDIR)/specs_erts_alloc.xml:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1"
release_spec:
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 4c84412dd6..4455d0ac92 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.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>
@@ -285,7 +285,8 @@
<item>If E is <c><![CDATA[fun Name / Arity]]></c>, then
Rep(E) = <c><![CDATA[{'fun',LINE,{function,Name,Arity}}]]></c>.</item>
<item>If E is <c><![CDATA[fun Module:Name/Arity]]></c>, then
- Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.</item>
+ Rep(E) = <c><![CDATA[{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}]]></c>.
+ (Before the R15 release: Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.)</item>
<item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c>
where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) =
<c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item>
diff --git a/erts/doc/src/driver.xml b/erts/doc/src/driver.xml
index 9f246c4a6c..52283879c7 100644
--- a/erts/doc/src/driver.xml
+++ b/erts/doc/src/driver.xml
@@ -30,11 +30,11 @@
</header>
<note><p>This document was written a long time ago. A lot of it is still
- valid, but some things have changed since it was first written.
- Updates of this document are planned for the future. The reader
- is encouraged to also read the
- <seealso marker="erl_driver">erl_driver</seealso>, and the
- <seealso marker="erl_driver">driver_entry</seealso> documentation.
+ interesting since it explains important concepts, but it was
+ written for an older driver interface so the examples do not
+ work anymore. The reader is encouraged to read
+ <seealso marker="erl_driver">erl_driver</seealso> and the
+ <seealso marker="driver_entry">driver_entry</seealso> documentation.
</p></note>
<section>
diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml
index 8bdd154cb9..a2efdf3ebc 100644
--- a/erts/doc/src/driver_entry.xml
+++ b/erts/doc/src/driver_entry.xml
@@ -34,18 +34,22 @@
<lib>driver_entry</lib>
<libsummary>The driver-entry structure used by erlang drivers.</libsummary>
<description>
- <p>As of erts version 5.5.3 the driver interface has been extended
- (see <seealso marker="driver_entry#extended_marker">extended marker</seealso>).
- The extended interface introduces
- <seealso marker="erl_driver#version_management">version management</seealso>,
- the possibility to pass capability flags
- (see <seealso marker="driver_entry#driver_flags">driver flags</seealso>)
- to the runtime system at driver initialization, and some new
- driver API functions. </p>
+ <p>
+ As of erts version 5.9 (OTP release R15B) the driver interface
+ has been changed with larger types for the callbacks
+ <seealso marker="#output">output</seealso>,
+ <seealso marker="#control">control</seealso> and
+ <seealso marker="#call">call</seealso>.
+ See driver <seealso marker="erl_driver#version_management">
+ version management</seealso> in
+ <seealso marker="erl_driver">erl_driver</seealso>.
+ </p>
<note>
<p>Old drivers (compiled with an <c>erl_driver.h</c> from an
- earlier erts version than 5.5.3) have to be recompiled
- (but do not have to use the extended interface).</p>
+ earlier erts version than 5.9) have to be updated and have
+ to use the extended interface (with
+ <seealso marker="erl_driver#version_management">version management
+ </seealso>).</p>
</note>
<p>The <c>driver_entry</c> structure is a C struct that all erlang
drivers define. It contains entry points for the erlang driver
@@ -53,7 +57,7 @@
the driver.</p>
<p>
<marker id="emulator"></marker>
- The <seealso marker="driver_entry">erl_driver</seealso> driver
+ The <seealso marker="erl_driver">erl_driver</seealso> driver
API functions need a port handle
that identifies the driver instance (and the port in the
emulator). This is only passed to the <c>start</c> function, but
@@ -84,7 +88,7 @@
the emulator, the driver is <em>not</em> allowed to modify the
<c>driver_entry</c>.</p>
<note>
- <p>Do <em>not</em> declare the <c>driver_entry</c><c>const</c>. This since the emulator needs to
+ <p>Do <em>not</em> declare the <c>driver_entry</c> <c>const</c>. This since the emulator needs to
modify the <c>handle</c>, and the <c>handle2</c>
fields. A statically allocated, and <c>const</c>
declared <c>driver_entry</c> may be located in
@@ -116,7 +120,7 @@ typedef struct erl_drv_entry {
void (*stop)(ErlDrvData drv_data);
/* called when port is closed, and when the
emulator is halted. */
- void (*output)(ErlDrvData drv_data, char *buf, int len);
+ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
/* called when we have output from erlang to
the port */
void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
@@ -130,8 +134,9 @@ typedef struct erl_drv_entry {
void (*finish)(void); /* called before unloading the driver -
DYNAMIC DRIVERS ONLY */
void *handle; /* Reserved -- Used by emulator internally */
- int (*control)(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen);
+ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen);
/* "ioctl" for drivers - invoked by
port_control/3 */
void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */
@@ -144,8 +149,9 @@ typedef struct erl_drv_entry {
closed, and there is data in the
driver queue that needs to be flushed
before 'stop' can be called */
- int (*call)(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned int *flags);
+ ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen, unsigned int *flags);
/* Works mostly like 'control', a synchronous
call into the driver. */
void (*event)(ErlDrvData drv_data, ErlDrvEvent event,
@@ -192,7 +198,7 @@ typedef struct erl_drv_entry {
<c>start</c>, then <c>stop</c> is the place to deallocate that
memory.</p>
</item>
- <tag><marker id="output"/>void (*output)(ErlDrvData drv_data, char *buf, int len)</tag>
+ <tag><marker id="output"/>void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)</tag>
<item>
<p>This is called when an erlang process has sent data to the
port. The data is pointed to by <c>buf</c>, and is
@@ -243,7 +249,7 @@ typedef struct erl_drv_entry {
emulator will modify this field; therefore, it is important
that the <c>driver_entry</c> isn't declared <c>const</c>.</p>
</item>
- <tag><marker id="control"></marker>int (*control)(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen)</tag>
+ <tag><marker id="control"></marker>ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)</tag>
<item>
<p>This is a special routine invoked with the erlang function
<c>port_control/3</c>. It works a little like an "ioctl" for
@@ -316,7 +322,7 @@ typedef struct erl_drv_entry {
opposed to the asynchronous function, which is called in
some thread (if multithreading is enabled).</p>
</item>
- <tag><marker id="call"/>int (*call)(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen, unsigned int *flags)</tag>
+ <tag><marker id="call"/>ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags)</tag>
<item>
<p>This function is called from <c>erlang:port_call/3</c>. It
works a lot like the <c>control</c> call-back, but uses the
@@ -452,7 +458,7 @@ typedef struct erl_drv_entry {
<title>SEE ALSO</title>
<p><seealso marker="erl_driver">erl_driver(3)</seealso>,
<seealso marker="kernel:erl_ddll">erl_ddll(3)</seealso>,
- <seealso marker="erts:erlang">erlang(3)</seealso>,
+ <seealso marker="erlang">erlang(3)</seealso>,
kernel(3)</p>
</section>
</cref>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 39c79a29df..8c028e1d14 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -41,25 +41,11 @@
to scroll back to text which has scrolled off the screen.
The <c><![CDATA[erl]]></c> program must be used, however, in pipelines or if
you want to redirect standard input or output.</p>
- <note><p>As of ERTS version 5.8 (OTP-R14A) the runtime system will by
- default bind schedulers to logical processors using the
- <c>default_bind</c> bind type if the amount of schedulers are
- at least equal to the amount of logical processors configured,
- binding of schedulers is supported, and a CPU topology is
- available at startup.
- </p><p>
- If the Erlang runtime system is the only operating system
- process that binds threads to logical processors, this
- improves the performance of the runtime system. However,
- if other operating system processes (as for example
- another Erlang runtime system) also bind threads to
- logical processors, there might be a performance penalty
- instead. If this is the case you, are are advised to
- unbind the schedulers using the
- <seealso marker="#+sbt">+sbtu</seealso> command line argument,
- or by invoking
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type,
- unbound)</seealso>.</p>
+ <note><p>As of ERTS version 5.9 (OTP-R15B) the runtime system will by
+ default <em>not</em> bind schedulers to logical processors.
+ For more information see documentation of the
+ <seealso marker="#+sbt">+sbt</seealso> system flag.
+ </p>
</note>
</description>
<funcs>
@@ -456,11 +442,7 @@
system with SMP support is available. <c>-smp auto</c> starts
the Erlang runtime system with SMP support enabled if it is
available and more than one logical processor are detected.
- <c>-smp disable</c> starts a runtime system without SMP support.
- By default <c>-smp auto</c> will be used unless a conflicting
- parameter has been passed, then <c>-smp disable</c> will be
- used. Currently only the <c>-hybrid</c> parameter conflicts
- with <c>-smp auto</c>.</p>
+ <c>-smp disable</c> starts a runtime system without SMP support.</p>
<p><em>NOTE</em>: The runtime system with SMP support will not
be available on all supported platforms. See also the
<seealso marker="#+S">+S</seealso> flag.</p>
@@ -551,7 +533,7 @@
<p>Force the <c>compressed</c> option on all ETS tables.
Only intended for test and evaluation.</p>
</item>
- <tag><c><![CDATA[+fnl]]></c></tag>
+ <tag><marker id="file_name_encoding"></marker><c><![CDATA[+fnl]]></c></tag>
<item>
<p>The VM works with file names as if they are encoded using the ISO-latin-1 encoding, disallowing Unicode characters with codepoints beyond 255. This is default on operating systems that have transparent file naming, i.e. all Unixes except MacOSX.</p>
</item>
@@ -679,41 +661,66 @@
</p>
<taglist>
<tag><c>u</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, unbound)</seealso>.
- </p></item>
+ <item>
+ <p><c>unbound</c> - Schedulers will not be bound to logical
+ processors, i.e., the operating system decides where the
+ scheduler threads execute, and when to migrate them. This is
+ the default.</p>
+ </item>
<tag><c>ns</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, no_spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>no_spread</c> - Schedulers with close scheduler
+ identifiers will be bound as close as possible in hardware.</p>
+ </item>
<tag><c>ts</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, thread_spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>thread_spread</c> - Thread refers to hardware threads
+ (e.g. Intel's hyper-threads). Schedulers with low scheduler
+ identifiers, will be bound to the first hardware thread of
+ each core, then schedulers with higher scheduler identifiers
+ will be bound to the second hardware thread of each core,
+ etc.</p>
+ </item>
<tag><c>ps</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, processor_spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>processor_spread</c> - Schedulers will be spread like
+ <c>thread_spread</c>, but also over physical processor chips.</p>
+ </item>
<tag><c>s</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>spread</c> - Schedulers will be spread as much as
+ possible.</p>
+ </item>
<tag><c>nnts</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, no_node_thread_spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>no_node_thread_spread</c> - Like <c>thread_spread</c>,
+ but if multiple NUMA (Non-Uniform Memory Access) nodes exists,
+ schedulers will be spread over one NUMA node at a time,
+ i.e., all logical processors of one NUMA node will be bound
+ to schedulers in sequence.</p>
+ </item>
<tag><c>nnps</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, no_node_processor_spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>no_node_processor_spread</c> - Like
+ <c>processor_spread</c>, but if multiple NUMA nodes exists,
+ schedulers will be spread over one NUMA node at a time, i.e.,
+ all logical processors of one NUMA node will be bound to
+ schedulers in sequence.</p>
+ </item>
<tag><c>tnnps</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, thread_no_node_processor_spread)</seealso>.
- </p></item>
+ <item>
+ <p><c>thread_no_node_processor_spread</c> - A combination of
+ <c>thread_spread</c>, and <c>no_node_processor_spread</c>.
+ Schedulers will be spread over hardware threads across NUMA
+ nodes, but schedulers will only be spread over processors
+ internally in one NUMA node at a time.</p>
+ </item>
<tag><c>db</c></tag>
- <item><p>Same as
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, default_bind)</seealso>.
- </p></item>
+ <item>
+ <p><c>default_bind</c> - Binds schedulers the default way.
+ Currently the default is <c>thread_no_node_processor_spread</c>
+ (which might change in the future).</p>
+ </item>
</taglist>
<p>Binding of schedulers is currently only supported on newer
Linux, Solaris, FreeBSD, and Windows systems.</p>
@@ -725,24 +732,57 @@
that the <c>+sct</c> flag may have to be passed before the
<c>+sbt</c> flag on the command line (in case no CPU topology
has been automatically detected).</p>
- <p>The runtime system will by default bind schedulers to logical
- processors using the <c>default_bind</c> bind type if the amount
- of schedulers are at least equal to the amount of logical
- processors configured, binding of schedulers is supported,
- and a CPU topology is available at startup.
+ <p>The runtime system will by default <em>not</em> bind schedulers
+ to logical processors.
</p>
- <p><em>NOTE:</em> If the Erlang runtime system is the only operating
- system process that binds threads to logical processors, this
- improves the performance of the runtime system. However, if other
- operating system processes (as for example another Erlang runtime
- system) also bind threads to logical processors, there might be a
- performance penalty instead. If this is the case you, are advised
- to unbind the schedulers using the <c>+sbtu</c> command line
- argument, or by invoking
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type,
- unbound)</seealso>.</p>
- <p>For more information, see
- <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, SchedulerBindType)</seealso>.
+ <p><em>NOTE:</em> If the Erlang runtime system is the only operating system
+ process that binds threads to logical processors, this
+ improves the performance of the runtime system. However,
+ if other operating system processes (as for example
+ another Erlang runtime system) also bind threads to
+ logical processors, there might be a performance penalty
+ instead. In some cases this performance penalty might be
+ severe. If this is the case, you are advised to not
+ bind the schedulers.</p>
+ <p>How schedulers are bound matters. For example, in
+ situations when there are fewer running processes than
+ schedulers online, the runtime system tries to migrate
+ processes to schedulers with low scheduler identifiers.
+ The more the schedulers are spread over the hardware,
+ the more resources will be available to the runtime
+ system in such situations.
+ </p>
+ <p>
+ <em>NOTE:</em> If a scheduler fails to bind, this
+ will often be silently ignored. This since it isn't always
+ possible to verify valid logical processor identifiers. If
+ an error is reported, it will be reported to the
+ <c>error_logger</c>. If you want to verify that the
+ schedulers actually have bound as requested, call
+ <seealso marker="erlang#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>.
+ </p>
+ </item>
+ <tag><marker id="+sbwt"><c>+sbwt none|very_short|short|medium|long|very_long</c></marker></tag>
+ <item>
+ <p>Set scheduler busy wait threshold. Default is <c>medium</c>.
+ The threshold determines how long schedulers should busy
+ wait when running out of work before going to sleep.
+ </p>
+ <p><em>NOTE:</em> This flag may be removed or changed at any time
+ without prior notice.
+ </p>
+ </item>
+ <tag><marker id="+scl"><c>+scl true|false</c></marker></tag>
+ <item>
+ <p>Enable or disable scheduler compaction of load. By default
+ scheduler compaction of load is enabled. When enabled, load
+ balancing will strive for a load distribution which causes
+ as many scheduler threads as possible to be fully loaded (i.e.,
+ not run out of work). This is accomplished by migrating load
+ (e.g. runnable processes) into a smaller set of schedulers
+ when schedulers frequently run out of work. When disabled,
+ the frequency with which schedulers run out of work will
+ not be taken into account by the load balancing logic.
</p>
</item>
<tag><marker id="+sct"><c>+sct CpuTopology</c></marker></tag>
@@ -760,6 +800,12 @@
<item><c><![CDATA[<IdDefs> = <LogicalIds><ThreadIds><CoreIds><ProcessorIds><NodeIds> | <LogicalIds><ThreadIds><CoreIds><NodeIds><ProcessorIds>]]></c></item>
<item><c><![CDATA[CpuTopology = <IdDefs>:<IdDefs> | <IdDefs>]]></c></item>
</list>
+ <p>Set a user defined CPU topology. The user defined
+ CPU topology will override any automatically detected
+ CPU topology. The CPU topology is used when
+ <seealso marker="#+sbt">binding schedulers to logical
+ processors</seealso>.
+ </p>
<p>Upper-case letters signify real identifiers and lower-case
letters signify fake identifiers only used for description
of the topology. Identifiers passed as real identifiers may
@@ -859,8 +905,19 @@
how the real CPU topology looks like is likely to
decrease the performance of the runtime system.</p>
<p>For more information, see
- <seealso marker="erlang#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>.</p>
+ <seealso marker="erlang#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>.</p>
</item>
+ <tag><marker id="+sws"><c>+sws default|legacy|proposal</c></marker></tag>
+ <item>
+ <p>Set scheduler wakeup strategy. Default is <c>legacy</c> (has been
+ used since OTP-R13B). The <c>proposal</c> strategy is the currently
+ proposed strategy for OTP-R16. Note that the <c>proposal</c> strategy
+ might change during OTP-R15.
+ </p>
+ <p><em>NOTE:</em> This flag may be removed or changed at any time
+ without prior notice.
+ </p>
+ </item>
<tag><marker id="+swt"><c>+swt very_low|low|medium|high|very_high</c></marker></tag>
<item>
<p>Set scheduler wakeup threshold. Default is <c>medium</c>.
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 2fb03954b6..187c263b60 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2011</year>
+ <year>2001</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,15 +37,18 @@
<p>As of erts version 5.5.3 the driver interface has been extended
(see <seealso marker="driver_entry#extended_marker">extended marker</seealso>).
The extended interface introduce
- <seealso marker="erl_driver#version_management">version management</seealso>,
+ <seealso marker="#version_management">version management</seealso>,
the possibility to pass capability flags
(see <seealso marker="driver_entry#driver_flags">driver flags</seealso>)
to the runtime system at driver initialization, and some new
driver API functions. </p>
<note>
- <p>Old drivers (compiled with an <c>erl_driver.h</c> from an
- earlier erts version than 5.5.3) have to be recompiled
- (but does not have to use the extended interface).</p>
+ <p>As of erts version 5.9 old drivers have to be recompiled
+ and have to use the extended interface. They also have to be
+ adjusted to the
+ <seealso marker="#rewrites_for_64_bits">64-bit capable driver interface.
+ </seealso>
+ </p>
</note>
<p>The driver calls back to the emulator, using the API
functions declared in <c>erl_driver.h</c>. They are used for
@@ -242,9 +245,9 @@
</p>
</item>
<tag>Adding / removing drivers</tag>
- <item>A driver can add and later remove drivers.</item>
+ <item><p>A driver can add and later remove drivers.</p></item>
<tag>Monitoring processes</tag>
- <item>A driver can monitor a process that does not own a port.</item>
+ <item><p>A driver can monitor a process that does not own a port.</p></item>
<tag><marker id="version_management">Version management</marker></tag>
<item>
<p>Version management is enabled for drivers that have set the
@@ -268,15 +271,203 @@
versions differ, or if the major versions are equal and the
minor version used by the driver is greater than the one used
by the runtime system.</p>
- <p>The emulator tries to check that a driver that doesn't use the
- extended driver interface isn't incompatible when loading it.
- It can, however, not make sure that it isn't incompatible. Therefore,
- when loading a driver that doesn't use the extended driver
- interface, there is a risk that it will be loaded also when
- the driver is incompatible. When the driver uses the extended driver
- interface, the emulator can verify that it isn't of an incompatible
- driver version. You are therefore advised to use the extended driver
- interface.</p>
+ <p>The emulator will refuse to load a driver that does not use
+ the extended driver interface since,
+ to allow for 64-bit capable drivers,
+ incompatible type changes for the callbacks
+ <seealso marker="driver_entry#output">output</seealso>,
+ <seealso marker="driver_entry#control">control</seealso> and
+ <seealso marker="driver_entry#call">call</seealso>
+ were introduced in release R15B. A driver written
+ with the old types would compile with warnings and when
+ called return garbage sizes to the emulator causing it
+ to read random memory and create huge incorrect result blobs.</p>
+ <p>Therefore it is not enough to just recompile drivers written with
+ version management for pre-R15B types; the types have to be changed
+ in the driver suggesting other rewrites especially regarding
+ size variables. Investigate all warnings when recompiling!</p>
+ <p>Also, the API driver functions <c>driver_output*</c>,
+ <c>driver_vec_to_buf</c>, <c>driver_alloc/realloc*</c>
+ and the <c>driver_*</c> queue functions were changed to have
+ larger length arguments and return values. This is a
+ lesser problem since code that passes smaller types
+ will get them auto converted in the calls and as long as
+ the driver does not handle sizes that overflow an <c>int</c>
+ all will work as before.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="rewrites_for_64_bits"/>
+ <title>
+ REWRITES FOR 64-BIT DRIVER INTERFACE
+ </title>
+ <p>
+ For erts-5.9 two new integer types
+ <seealso marker="#ErlDrvSizeT">ErlDrvSizeT</seealso> and
+ <seealso marker="#ErlDrvSSizeT">ErlDrvSSizeT</seealso>
+ were introduced that can hold 64-bit sizes if necessary.
+ </p>
+ <p>
+ To not update a driver and just recompile it probably works
+ when building for a 32-bit machine creating a false sense of security.
+ Hopefully that will generate many important warnings.
+ But when recompiling the same driver later on for a 64-bit machine
+ there <em>will</em> be warnings and almost certainly crashes.
+ So it is a BAD idea to postpone updating the driver and
+ not fixing the warnings!
+ </p>
+ <p>
+ When recompiling with <c>gcc</c> use the <c>-Wstrict-prototypes</c>
+ flag to get better warnings. Try to find a similar flag if you
+ are using some other compiler.
+ </p>
+ <p>
+ Here follows a checklist for rewriting a pre erts-5.9 driver,
+ most important first.
+ </p>
+ <taglist>
+ <tag>Return types for driver callbacks</tag>
+ <item>
+ <p>
+ Rewrite driver callback
+ <c><seealso marker="driver_entry#control">control</seealso></c>
+ to use return type <c>ErlDrvSSizeT</c> instead of <c>int</c>.
+ </p>
+ <p>
+ Rewrite driver callback
+ <c><seealso marker="driver_entry#call">call</seealso></c>
+ to use return type <c>ErlDrvSSizeT</c> instead of <c>int</c>.
+ </p>
+ <note>
+ <p>
+ These changes are essential to not crash the emulator
+ or worse cause malfunction.
+ Without them a driver may return garbage in the high 32 bits
+ to the emulator causing it to build a huge result from random
+ bytes either crashing on memory allocation or succeeding with
+ a random result from the driver call.
+ </p>
+ </note>
+ </item>
+ <tag>Arguments to driver callbacks</tag>
+ <item>
+ <p>
+ Driver callback
+ <c><seealso marker="driver_entry#output">output</seealso></c>
+ now gets <c>ErlDrvSizeT</c> as 3rd argument instead
+ of previously <c>int</c>.
+ </p>
+ <p>
+ Driver callback
+ <c><seealso marker="driver_entry#control">control</seealso></c>
+ now gets <c>ErlDrvSizeT</c> as 4th and 6th arguments instead
+ of previously <c>int</c>.
+ </p>
+ <p>
+ Driver callback
+ <c><seealso marker="driver_entry#call">call</seealso></c>
+ now gets <c>ErlDrvSizeT</c> as 4th and 6th arguments instead
+ of previously <c>int</c>.
+ </p>
+ <p>
+ Sane compiler's calling conventions probably make these changes
+ necessary only for a driver to handle data chunks that require
+ 64-bit size fields (mostly larger than 2 GB since that is what
+ an <c>int</c> of 32 bits can hold). But it is possible to think
+ of non-sane calling conventions that would make the driver
+ callbacks mix up the arguments causing malfunction.
+ </p>
+ <note>
+ <p>
+ The argument type change is from signed to unsigned which
+ may cause problems for e.g. loop termination conditions or
+ error conditions if you just change the types all over the place.
+ </p>
+ </note>
+ </item>
+ <tag>Larger <c>size</c> field in <c>ErlIOVec</c></tag>
+ <item>
+ <p>
+ The <c>size</c> field in
+ <seealso marker="#ErlIOVec"><c>ErlIOVec</c></seealso>
+ has been changed to <c>ErlDrvSizeT</c> from <c>int</c>.
+ Check all code that use that field.
+ </p>
+ <p>
+ Automatic type casting probably makes these changes necessary only
+ for a driver that encounters sizes larger than 32 bits.
+ </p>
+ <note>
+ <p>
+ The <c>size</c> field changed from signed to unsigned which
+ may cause problems for e.g. loop termination conditions or
+ error conditions if you just change the types all over the place.
+ </p>
+ </note>
+ </item>
+ <tag>Arguments and return values in the driver API</tag>
+ <item>
+ <p>
+ Many driver API functions have changed argument type
+ and/or return value to <c>ErlDrvSizeT</c> from mostly <c>int</c>.
+ Automatic type casting probably makes these changes necessary only
+ for a driver that encounters sizes larger than 32 bits.
+ </p>
+ <taglist>
+ <tag><seealso marker="#driver_output">driver_output</seealso></tag>
+ <item>3rd argument</item>
+ <tag><seealso marker="#driver_output2">driver_output2</seealso></tag>
+ <item>3rd and 5th arguments</item>
+ <tag>
+ <seealso marker="#driver_output_binary">driver_output_binary</seealso>
+ </tag>
+ <item>3rd 5th and 6th arguments</item>
+ <tag><seealso marker="#driver_outputv">driver_outputv</seealso></tag>
+ <item>3rd and 5th arguments</item>
+ <tag>
+ <seealso marker="#driver_vec_to_buf">driver_vec_to_buf</seealso>
+ </tag>
+ <item>3rd argument and return value</item>
+ <tag><seealso marker="#driver_alloc">driver_alloc</seealso></tag>
+ <item>1st argument</item>
+ <tag><seealso marker="#driver_realloc">driver_realloc</seealso></tag>
+ <item>2nd argument</item>
+ <tag>
+ <seealso marker="#driver_alloc_binary">driver_alloc_binary</seealso>
+ </tag>
+ <item>1st argument</item>
+ <tag>
+ <seealso marker="#driver_realloc_binary">driver_realloc_binary</seealso>
+ </tag>
+ <item>2nd argument</item>
+ <tag><seealso marker="#driver_enq">driver_enq</seealso></tag>
+ <item>3rd argument</item>
+ <tag><seealso marker="#driver_pushq">driver_pushq</seealso></tag>
+ <item>3rd argument</item>
+ <tag><seealso marker="#driver_deq">driver_deq</seealso></tag>
+ <item>2nd argument and return value</item>
+ <tag><seealso marker="#driver_sizeq">driver_sizeq</seealso></tag>
+ <item>return value</item>
+ <tag><seealso marker="#driver_enq_bin">driver_enq_bin</seealso></tag>
+ <item>3rd and 4th argument</item>
+ <tag><seealso marker="#driver_pushq_bin">driver_pushq_bin</seealso></tag>
+ <item>3rd and 4th argument</item>
+ <tag><seealso marker="#driver_enqv">driver_enqv</seealso></tag>
+ <item>3rd argument</item>
+ <tag><seealso marker="#driver_pushqv">driver_pushqv</seealso></tag>
+ <item>3rd argument</item>
+ <tag><seealso marker="#driver_peekqv">driver_peekqv</seealso></tag>
+ <item>return value</item>
+ </taglist>
+ <note>
+ <p>
+ This is a change from signed to unsigned which
+ may cause problems for e.g. loop termination conditions and
+ error conditions if you just change the types all over the place.
+ </p>
+ </note>
</item>
</taglist>
</section>
@@ -285,7 +476,11 @@
<title>DATA TYPES</title>
<taglist>
- <tag><marker id="ErlDrvSysInfo"/>ErlDrvSysInfo</tag>
+ <tag><marker id="ErlDrvSizeT"/>ErlDrvSizeT</tag>
+ <item><p>An unsigned integer type to be used as <c>size_t</c></p></item>
+ <tag><marker id="ErlDrvSSizeT"/>ErlDrvSSizeT</tag>
+ <item><p>A signed integer type the size of <c>ErlDrvSizeT</c></p></item>
+ <tag><marker id="ErlDrvSysInfo"/>ErlDrvSysInfo</tag>
<item>
<p/>
<code type="none">
@@ -332,12 +527,12 @@ typedef struct ErlDrvSysInfo {
<tag><c>erts_version</c></tag>
<item>A string containing the version number of the runtime system
(the same as returned by
- <seealso marker="erts:erlang#system_info_version">erlang:system_info(version)</seealso>).
+ <seealso marker="erlang#system_info_version">erlang:system_info(version)</seealso>).
</item>
<tag><c>otp_release</c></tag>
<item>A string containing the OTP release number
(the same as returned by
- <seealso marker="erts:erlang#system_info_otp_release">erlang:system_info(otp_release)</seealso>).
+ <seealso marker="erlang#system_info_otp_release">erlang:system_info(otp_release)</seealso>).
</item>
<tag><c>thread_support</c></tag>
<item>A value <c>!= 0</c> if the runtime system has thread support;
@@ -351,12 +546,12 @@ typedef struct ErlDrvSysInfo {
<item>The number of async threads in the async thread pool used
by <seealso marker="#driver_async">driver_async()</seealso>
(the same as returned by
- <seealso marker="erts:erlang#system_info_thread_pool_size">erlang:system_info(thread_pool_size)</seealso>).
+ <seealso marker="erlang#system_info_thread_pool_size">erlang:system_info(thread_pool_size)</seealso>).
</item>
<tag><c>scheduler_threads</c></tag>
<item>The number of scheduler threads used by the runtime system
(the same as returned by
- <seealso marker="erts:erlang#system_info_schedulers">erlang:system_info(schedulers)</seealso>).
+ <seealso marker="erlang#system_info_schedulers">erlang:system_info(schedulers)</seealso>).
</item>
<tag><c>nif_major_version</c></tag>
<item>The value of <c>ERL_NIF_MAJOR_VERSION</c> when the runtime system was compiled.
@@ -371,7 +566,7 @@ typedef struct ErlDrvSysInfo {
<p/>
<code type="none">
typedef struct ErlDrvBinary {
- int orig_size;
+ ErlDrvSint orig_size;
char orig_bytes[];
} ErlDrvBinary;
</code>
@@ -423,7 +618,7 @@ typedef struct ErlDrvBinary {
<item>
<p>The <c>ErlDrvData</c> is a handle to driver-specific data,
passed to the driver call-backs. It is a pointer, and is
- most often casted to a specific pointer in the driver.</p>
+ most often type casted to a specific pointer in the driver.</p>
</item>
<tag>SysIOVec</tag>
<item>
@@ -437,7 +632,7 @@ typedef struct ErlDrvBinary {
<code type="none">
typedef struct ErlIOVec {
int vsize;
- int size;
+ ErlDrvSizeT size;
SysIOVec* iov;
ErlDrvBinary** binv;
} ErlIOVec;
@@ -630,7 +825,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len)</nametext></name>
<fsummary>Send data from driver to port owner</fsummary>
<desc>
<marker id="driver_output"></marker>
@@ -650,7 +845,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, int hlen, char *buf, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len)</nametext></name>
<fsummary>Send data and binary data to port owner</fsummary>
<desc>
<marker id="driver_output2"></marker>
@@ -665,7 +860,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char *hbuf, int hlen, ErlDrvBinary* bin, int offset, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
<fsummary>Send data from a driver binary to port owner</fsummary>
<desc>
<marker id="driver_output_binary"></marker>
@@ -688,7 +883,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, int hlen, ErlIOVec *ev, int skip)</nametext></name>
+ <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
<fsummary>Send vectorized data to port owner</fsummary>
<desc>
<marker id="driver_outputv"></marker>
@@ -711,7 +906,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, char *buf, int len)</nametext></name>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len)</nametext></name>
<fsummary>Collect data segments into a buffer</fsummary>
<desc>
<marker id="driver_vec_to_buf"></marker>
@@ -738,7 +933,7 @@ typedef struct ErlIOVec {
<c>time</c> parameter is the time in milliseconds before the
timer expires.</p>
<p>When the timer reaches 0 and expires, the driver entry
- function <seealso marker="driver_entry#emulator">timeout</seealso> is called.</p>
+ function <seealso marker="driver_entry#timeout">timeout</seealso> is called.</p>
<p>Note that there is only one timer on each driver instance;
setting a new timer will replace an older one.</p>
<p>Return value is 0 (-1 only when the <c>timeout</c> driver
@@ -832,7 +1027,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>void *</ret><nametext>driver_alloc(size_t size)</nametext></name>
+ <name><ret>void *</ret><nametext>driver_alloc(ErlDrvSizeT size)</nametext></name>
<fsummary>Allocate memory</fsummary>
<desc>
<marker id="driver_alloc"></marker>
@@ -846,7 +1041,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>void *</ret><nametext>driver_realloc(void *ptr, size_t size)</nametext></name>
+ <name><ret>void *</ret><nametext>driver_realloc(void *ptr, ErlDrvSizeT size)</nametext></name>
<fsummary>Resize an allocated memory block</fsummary>
<desc>
<marker id="driver_realloc"></marker>
@@ -872,7 +1067,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>ErlDrvBinary*</ret><nametext>driver_alloc_binary(int size)</nametext></name>
+ <name><ret>ErlDrvBinary *</ret><nametext>driver_alloc_binary(ErlDrvSizeT size)</nametext></name>
<fsummary>Allocate a driver binary</fsummary>
<desc>
<marker id="driver_alloc_binary"></marker>
@@ -892,7 +1087,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>ErlDrvBinary*</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, int size)</nametext></name>
+ <name><ret>ErlDrvBinary *</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)</nametext></name>
<fsummary>Resize a driver binary</fsummary>
<desc>
<marker id="driver_realloc_binary"></marker>
@@ -958,7 +1153,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name>
<fsummary>Enqueue data in the driver queue</fsummary>
<desc>
<marker id="driver_enq"></marker>
@@ -982,7 +1177,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name>
<fsummary>Push data at the head of the driver queue</fsummary>
<desc>
<marker id="driver_pushq"></marker>
@@ -997,7 +1192,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_deq(ErlDrvPort port, int size)</nametext></name>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_deq(ErlDrvPort port, ErlDrvSizeT size)</nametext></name>
<fsummary>Dequeue data from the head of the driver queue</fsummary>
<desc>
<marker id="driver_deq"></marker>
@@ -1013,7 +1208,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_sizeq(ErlDrvPort port)</nametext></name>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_sizeq(ErlDrvPort port)</nametext></name>
<fsummary>Return the size of the driver queue</fsummary>
<desc>
<marker id="driver_sizeq"></marker>
@@ -1026,7 +1221,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
<fsummary>Enqueue binary in the driver queue</fsummary>
<desc>
<marker id="driver_enq_bin"></marker>
@@ -1043,7 +1238,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset, int len)</nametext></name>
+ <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
<fsummary>Push binary at the head of the driver queue</fsummary>
<desc>
<marker id="driver_pushq_bin"></marker>
@@ -1060,13 +1255,35 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>SysIOVec*</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_peekqv(ErlDrvPort port, ErlIOVec *ev)</nametext></name>
+ <fsummary>Get the driver queue as an IO vector</fsummary>
+ <desc>
+ <marker id="driver_peekqv"></marker>
+ <p>
+ This function retrieves the driver queue into a supplied
+ <c>ErlIOVec</c> <c>ev</c>. It also returns the queue size.
+ This is one of two ways to get data out of the queue.
+ </p>
+ <p>
+ If <c>ev</c> is <c>NULL</c> all ones i.e. <c>-1</c> type cast to
+ <c>ErlDrvSizeT</c> is returned.
+ </p>
+ <p>Nothing is removed from the queue by this function, that must be done
+ with <c>driver_deq</c>.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
+ </desc>
+ </func>
+ <func>
+ <name><ret>SysIOVec *</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name>
<fsummary>Get the driver queue as a vector</fsummary>
<desc>
<marker id="driver_peekq"></marker>
<p>This function retrieves the driver queue as a pointer to an
array of <c>SysIOVec</c>s. It also returns the number of
- elements in <c>vlen</c>. This is the only way to get data
+ elements in <c>vlen</c>. This is one of two ways to get data
out of the queue.</p>
<p>Nothing is removed from the queue by this function, that must be done
with <c>driver_deq</c>.</p>
@@ -1079,7 +1296,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, int skip)</nametext></name>
+ <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
<fsummary>Enqueue vector in the driver queue</fsummary>
<desc>
<marker id="driver_enqv"></marker>
@@ -1095,7 +1312,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec *ev, int skip)</nametext></name>
+ <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
<fsummary>Push vector at the head of the driver queue</fsummary>
<desc>
<marker id="driver_pushqv"></marker>
@@ -1264,7 +1481,7 @@ typedef struct ErlIOVec {
</desc>
</func>
<func>
- <name><ret>char*</ret><nametext>erl_errno_id(int error)</nametext></name>
+ <name><ret>char *</ret><nametext>erl_errno_id(int error)</nametext></name>
<fsummary>Get erlang error atom name from error number</fsummary>
<desc>
<marker id="erl_errno_id"></marker>
@@ -1494,7 +1711,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
term encoded with the
<seealso marker="erl_ext_dist">external format</seealso>,
i.e., a term that has been encoded by
- <seealso marker="erts:erlang#term_to_binary/2">erlang:term_to_binary</seealso>,
+ <seealso marker="erlang#term_to_binary/2">erlang:term_to_binary</seealso>,
<seealso marker="erl_interface:ei">erl_interface</seealso>, etc.
For example, if <c>binp</c> is a pointer to an <c>ErlDrvBinary</c>
that contains the term <c>{17, 4711}</c> encoded with the
@@ -1638,12 +1855,19 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
<fsummary>Cancel an asynchronous call</fsummary>
<desc>
<marker id="driver_async_cancel"></marker>
- <p>This function cancels an asynchronous operation, by removing
- it from the queue. Only functions in the queue can be
- cancelled; if a function is executing, it's too late to
- cancel it. The <c>async_free</c> function is also called.</p>
- <p>The return value is 1 if the operation was removed from the
- queue, otherwise 0.</p>
+ <p>This function used to cancel a scheduled asynchronous operation,
+ if it was still in the queue. It returned 1 if it succeeded, and
+ 0 if it failed.</p>
+ <p>Since it could not guarantee success, it was more or less useless.
+ The user had to implement synchronization of cancellation anyway.
+ It also unnecessarily complicated the implementation. Therefore,
+ as of OTP-R15B <c>driver_async_cancel()</c> is deprecated, and
+ scheduled for removal in OTP-R16. It will currently always fail,
+ and return 0.</p>
+ <warning><p><c>driver_async_cancel()</c> is deferred and will
+ be removed in the OTP-R16 release.</p>
+ </warning>
+
</desc>
</func>
<func>
@@ -1687,7 +1911,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
The driver defined handle is normally created in the
<seealso marker="driver_entry#start">driver start call-back</seealso>
when a port is created via
- <seealso marker="erts:erlang#open_port/2">erlang:open_port/2</seealso>. </item>
+ <seealso marker="erlang#open_port/2">erlang:open_port/2</seealso>. </item>
</taglist>
<p>The caller of <c>driver_create_port()</c> is allowed to
manipulate the newly created port when <c>driver_create_port()</c>
@@ -2455,7 +2679,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
<title>SEE ALSO</title>
<p><seealso marker="driver_entry">driver_entry(3)</seealso>,
<seealso marker="kernel:erl_ddll">erl_ddll(3)</seealso>,
- <seealso marker="erts:erlang">erlang(3)</seealso></p>
+ <seealso marker="erlang">erlang(3)</seealso></p>
<p>An Alternative Distribution Driver (ERTS User's
Guide Ch. 3)</p>
</section>
diff --git a/erts/doc/src/erl_ext_fig.gif b/erts/doc/src/erl_ext_fig.gif
index 14d6bbc871..14d6bbc871 100755..100644
--- a/erts/doc/src/erl_ext_fig.gif
+++ b/erts/doc/src/erl_ext_fig.gif
Binary files differ
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 980fc0cc39..f484e9eaf7 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2011</year>
+ <year>2001</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -136,9 +136,7 @@ ok
then retrieved by calling <seealso marker="#enif_priv_data">enif_priv_data</seealso>.</p>
<p>There is no way to explicitly unload a NIF library. A library will be
automatically unloaded when the module code that it belongs to is purged
- by the code server. A NIF library will also be unloaded if it is replaced
- by another version of the library by a second call to
- <c>erlang:load_nif/2</c> from the same module code.</p>
+ by the code server.</p>
</description>
<section>
<title>FUNCTIONALITY</title>
@@ -308,21 +306,9 @@ ok
initialization is needed.</p>
</item>
- <tag><marker id="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag>
- <item><p><c>reload</c> is called when the NIF library is loaded
- and there is already a previously loaded library for this
- module code.</p>
- <p>Works the same as <c>load</c>. The only difference is that
- <c>*priv_data</c> already contains the value set by the
- previous call to <c>load</c> or <c>reload</c>.</p>
- <p>The library will fail to load if <c>reload</c> returns
- anything other than 0 or if <c>reload</c> is NULL.</p>
- </item>
-
<tag><marker id="upgrade"/>int (*upgrade)(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)</tag>
<item><p><c>upgrade</c> is called when the NIF library is loaded
- and there is no previously loaded library for this module
- code, BUT there is old code of this module with a loaded NIF library.</p>
+ and there is old code of this module with a loaded NIF library.</p>
<p>Works the same as <c>load</c>. The only difference is that
<c>*old_priv_data</c> already contains the value set by the
last call to <c>load</c> or <c>reload</c> for the old module
@@ -339,6 +325,23 @@ ok
called for a replaced library as a consequence of <c>reload</c>.</p>
</item>
+ <tag><marker id="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag>
+ <note><p>The reload mechanism is <em>deprecated</em>. It was only intended
+ as a development feature. Do not use it as an upgrade method for
+ live production systems. It might be removed in future releases. Be sure
+ to pass <c>reload</c> as <c>NULL</c> to <seealso marker="#ERL_NIF_INIT">ERL_NIF_INIT</seealso>
+ to disable it when not used.</p>
+ </note>
+ <item><p><c>reload</c> is called when the NIF library is loaded
+ and there is already a previously loaded library for this
+ module code.</p>
+ <p>Works the same as <c>load</c>. The only difference is that
+ <c>*priv_data</c> already contains the value set by the
+ previous call to <c>load</c> or <c>reload</c>.</p>
+ <p>The library will fail to load if <c>reload</c> returns
+ anything other than 0 or if <c>reload</c> is NULL.</p>
+ </item>
+
</taglist>
</section>
@@ -469,7 +472,7 @@ typedef enum {
</section>
<funcs>
- <func><name><ret>void*</ret><nametext>enif_alloc(size_t size)</nametext></name>
+ <func><name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name>
<fsummary>Allocate dynamic memory.</fsummary>
<desc><p>Allocate memory of <c>size</c> bytes. Return NULL if allocation failed.</p></desc>
</func>
@@ -486,7 +489,7 @@ typedef enum {
<p>Return true on success or false if allocation failed.</p>
</desc>
</func>
- <func><name><ret>ErlNifEnv*</ret><nametext>enif_alloc_env()</nametext></name>
+ <func><name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name>
<fsummary>Create a new environment</fsummary>
<desc><p>Allocate a new process independent environment. The environment can
be used to hold terms that is not bound to any process. Such terms can
@@ -496,7 +499,7 @@ typedef enum {
<p>Return pointer to the new environment.</p>
</desc>
</func>
- <func><name><ret>void*</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name>
+ <func><name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name>
<fsummary>Allocate a memory managed resource object</fsummary>
<desc><p>Allocate a memory managed resource object of type <c>type</c> and size <c>size</c> bytes.</p></desc>
</func>
@@ -519,7 +522,7 @@ typedef enum {
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_broadcast">erl_drv_cond_broadcast</seealso>.
</p></desc>
</func>
- <func><name><ret>ErlNifCond*</ret><nametext>enif_cond_create(char *name)</nametext></name>
+ <func><name><ret>ErlNifCond *</ret><nametext>enif_cond_create(char *name)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_create">erl_drv_cond_create</seealso>.
</p></desc>
@@ -692,6 +695,10 @@ typedef enum {
<fsummary>Determine if a term is an exception</fsummary>
<desc><p>Return true if <c>term</c> is an exception.</p></desc>
</func>
+ <func><name><ret>int</ret><nametext>enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+ <fsummary>Determine if a term is a number (integer or float)</fsummary>
+ <desc><p>Return true if <c>term</c> is a number.</p></desc>
+ </func>
<func><name><ret>int</ret><nametext>enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a fun</fsummary>
<desc><p>Return true if <c>term</c> is a fun.</p></desc>
@@ -833,7 +840,7 @@ typedef enum {
<fsummary>Create an integer term from a long int</fsummary>
<desc><p>Create an integer term from a <c>long int</c>.</p></desc>
</func>
- <func><name><ret>unsigned char*</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name>
+ <func><name><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name>
<fsummary>Allocate and create a new binary term</fsummary>
<desc><p>Allocate a binary of size <c>size</c> bytes and create an owning
term. The binary data is mutable until the calling NIF returns. This is a
@@ -944,7 +951,7 @@ typedef enum {
<fsummary>Create an integer term from an unsigned long int</fsummary>
<desc><p>Create an integer term from an <c>unsigned long int</c>.</p></desc>
</func>
- <func><name><ret>ErlNifMutex*</ret><nametext>enif_mutex_create(char *name)</nametext></name>
+ <func><name><ret>ErlNifMutex *</ret><nametext>enif_mutex_create(char *name)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_create">erl_drv_mutex_create</seealso>.
</p></desc>
@@ -969,7 +976,7 @@ typedef enum {
<desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_unlock">erl_drv_mutex_unlock</seealso>.
</p></desc>
</func>
- <func><name><ret>ErlNifResourceType*</ret><nametext>enif_open_resource_type(ErlNifEnv* env,
+ <func><name><ret>ErlNifResourceType *</ret><nametext>enif_open_resource_type(ErlNifEnv* env,
const char* module_str, const char* name,
ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext></name>
<fsummary>Create or takeover a resource type</fsummary>
@@ -998,7 +1005,7 @@ typedef enum {
and <seealso marker="#upgrade">upgrade</seealso>.</p>
</desc>
</func>
- <func><name><ret>void*</ret><nametext>enif_priv_data(ErlNifEnv* env)</nametext></name>
+ <func><name><ret>void *</ret><nametext>enif_priv_data(ErlNifEnv* env)</nametext></name>
<fsummary>Get the private data of a NIF library</fsummary>
<desc><p>Return the pointer to the private data that was set by <c>load</c>,
<c>reload</c> or <c>upgrade</c>.</p>
@@ -1026,7 +1033,7 @@ typedef enum {
References made by <seealso marker="#enif_make_resource">enif_make_resource</seealso>
can only be removed by the garbage collector.</p></desc>
</func>
- <func><name><ret>ErlNifRWLock*</ret><nametext>enif_rwlock_create(char *name)</nametext></name>
+ <func><name><ret>ErlNifRWLock *</ret><nametext>enif_rwlock_create(char *name)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_create">erl_drv_rwlock_create</seealso>.
</p></desc>
@@ -1066,7 +1073,7 @@ typedef enum {
<desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrwlock">erl_drv_rwlock_tryrwlock</seealso>.
</p></desc>
</func>
- <func><name><ret>ErlNifPid*</ret><nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name>
+ <func><name><ret>ErlNifPid *</ret><nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name>
<fsummary>Get the pid of the calling process.</fsummary>
<desc><p>Initialize the pid variable <c>*pid</c> to represent the
calling process. Return <c>pid</c>.</p></desc>
@@ -1122,7 +1129,7 @@ typedef enum {
<desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_join">erl_drv_thread_join </seealso>.
</p></desc>
</func>
- <func><name><ret>ErlNifThreadOpts*</ret><nametext>enif_thread_opts_create(char *name)</nametext></name>
+ <func><name><ret>ErlNifThreadOpts *</ret><nametext>enif_thread_opts_create(char *name)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_create">erl_drv_thread_opts_create</seealso>.
</p></desc>
@@ -1147,7 +1154,7 @@ typedef enum {
<desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_destroy">erl_drv_tsd_key_destroy</seealso>.
</p></desc>
</func>
- <func><name><ret>void*</ret><nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name>
+ <func><name><ret>void *</ret><nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_get">erl_drv_tsd_get</seealso>.
</p></desc>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 45b66a4909..248b755969 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -215,9 +215,9 @@
representation of <c>Atom</c>. If <c>Encoding</c>
is <c>latin1</c>, there will be one byte for each character
in the text representation. If <c>Encoding</c> is <c>utf8</c> or
- <c>unicode</c>, the characters will encoded using UTF-8
+ <c>unicode</c>, the characters will be encoded using UTF-8
(meaning that characters from 16#80 up to 0xFF will be
- encode in two bytes).</p>
+ encoded in two bytes).</p>
<note><p>Currently, <c>atom_to_binary(Atom, latin1)</c> can
never fail because the text representation of an atom can only contain
@@ -268,7 +268,7 @@
<p>If <c>PosLen</c> in any way references outside the binary, a <c>badarg</c> exception is raised.</p>
- <p><c>Start</c> is zero-based, i.e:</p>
+ <p><c>Start</c> is zero-based, i.e.:</p>
<code>
1> Bin = &lt;&lt;1,2,3&gt;&gt;
2> binary_part(Bin,{0,2}).
@@ -724,9 +724,12 @@ false</pre>
size limit.</p>
</item>
<tag><c>{line_length, integer()}</c></tag>
- <item><p>Applies only to line oriented protocols
- (<c>line</c>, <c>http</c>). Lines longer than this
- will be truncated.</p>
+ <item><p>For packet type <c>line</c>, truncate lines longer
+ than the indicated length.</p>
+ <p>Option <c>line_length</c> also applies to <c>http*</c>
+ packet types as an alias for option <c>packet_size</c> in the
+ case when <c>packet_size</c> itself is not set. This usage is
+ only intended for backward compatibility.</p>
</item>
</taglist>
<pre>
@@ -770,9 +773,9 @@ false</pre>
turned off, nothing happens.</p>
<p>Once <c>demonitor(MonitorRef)</c> has returned it is
guaranteed that no <c>{'DOWN', MonitorRef, _, _, _}</c> message
- due to the monitor will be placed in the callers message queue
+ due to the monitor will be placed in the caller's message queue
in the future. A <c>{'DOWN', MonitorRef, _, _, _}</c> message
- might have been placed in the callers message queue prior to
+ might have been placed in the caller's message queue prior to
the call, though. Therefore, in most cases, it is advisable
to remove such a <c>'DOWN'</c> message from the message queue
after monitoring has been stopped.
@@ -802,8 +805,7 @@ false</pre>
<type>
<v>MonitorRef = reference()</v>
<v>OptionList = [Option]</v>
- <v>Option = flush</v>
- <v>Option = info</v>
+ <v>&nbsp;Option = flush | info</v>
</type>
<desc>
<p>The returned value is <c>true</c> unless <c>info</c> is part
@@ -816,7 +818,7 @@ false</pre>
<tag><c>flush</c></tag>
<item>
<p>Remove (one) <c>{_, MonitorRef, _, _, _}</c> message,
- if there is one, from the callers message queue after
+ if there is one, from the caller's message queue after
monitoring has been stopped.</p>
<p>Calling <c>demonitor(MonitorRef, [flush])</c>
is equivalent to the following, but more efficient:</p>
@@ -845,7 +847,7 @@ false</pre>
<item><p>The monitor was not found and could not be removed.
This probably because someone already has placed a
<c>'DOWN'</c> message corresponding to this monitor
- in the callers message queue.
+ in the caller's message queue.
</p>
</item>
</taglist>
@@ -1196,11 +1198,16 @@ true
</item>
<tag><c>{new_uniq, Uniq}</c></tag>
<item>
- <p><c>Uniq</c> (a binary) is a unique value for this fun.</p>
+ <p><c>Uniq</c> (a binary) is a unique value for this fun.
+ It is calculated from the compiled code for the entire module.</p>
</item>
<tag><c>{uniq, Uniq}</c></tag>
<item>
- <p><c>Uniq</c> (an integer) is a unique value for this fun.</p>
+ <p><c>Uniq</c> (an integer) is a unique value for this fun.
+ Starting in the R15 release, this integer is calculated from
+ the compiled code for the entire module. Before R15, this
+ integer was based on only the body of the fun.
+ </p>
</item>
</taglist>
</desc>
@@ -1425,29 +1432,69 @@ true
<name>halt()</name>
<fsummary>Halt the Erlang runtime system and indicate normal exit to the calling environment</fsummary>
<desc>
- <p>Halts the Erlang runtime system and indicates normal exit to
- the calling environment. Has no return value.</p>
+ <p>The same as
+ <seealso marker="#halt/2"><c>halt(0, [])</c></seealso>.</p>
<pre>
> <input>halt().</input>
-os_prompt%</pre>
+os_prompt% </pre>
</desc>
</func>
<func>
<name>halt(Status)</name>
<fsummary>Halt the Erlang runtime system</fsummary>
<type>
- <v>Status = integer() >= 0 | string()</v>
+ <v>Status = integer() >= 0 | string() | abort</v>
</type>
<desc>
- <p><c>Status</c> must be a non-negative integer, or a string.
- Halts the Erlang runtime system. Has no return value.
- If <c>Status</c> is an integer, it is returned as an exit
- status of Erlang to the calling environment.
- If <c>Status</c> is a string, produces an Erlang crash dump
- with <c>String</c> as slogan, and then exits with a non-zero
- status code.</p>
- <p>Note that on many platforms, only the status codes 0-255 are
- supported by the operating system.</p>
+ <p>The same as
+ <seealso marker="#halt/2"><c>halt(Status, [])</c></seealso>.</p>
+ <pre>
+> <input>halt(17).</input>
+os_prompt% <input>echo $?</input>
+17
+os_prompt% </pre>
+ </desc>
+ </func>
+ <func>
+ <name>halt(Status, Options)</name>
+ <fsummary>Halt the Erlang runtime system</fsummary>
+ <type>
+ <v>Status = integer() >= 0 | string() | abort</v>
+ <v>Options = [Option]</v>
+ <v>Option = {flush,boolean()} | term()</v>
+ </type>
+ <desc>
+ <p><c>Status</c> must be a non-negative integer, a string,
+ or the atom <c>abort</c>.
+ Halts the Erlang runtime system. Has no return value.
+ Depending on <c>Status</c>:
+ </p>
+ <taglist>
+ <tag>integer()</tag>
+ <item>The runtime system exits with the integer value <c>Status</c>
+ as status code to the calling environment (operating system).
+ </item>
+ <tag>string()</tag>
+ <item>An erlang crash dump is produced with <c>Status</c> as slogan,
+ and then the runtime system exits with status code <c>1</c>.
+ </item>
+ <tag><c>abort</c></tag>
+ <item>
+ The runtime system aborts producing a core dump, if that is
+ enabled in the operating system.
+ </item>
+ </taglist>
+ <p>Note that on many platforms, only the status codes 0-255 are
+ supported by the operating system.
+ </p>
+ <p>For integer <c>Status</c> the Erlang runtime system closes all ports
+ and allows async threads to finish their operations before exiting.
+ To exit without such flushing use
+ <c>Option</c> as <c>{flush,false}</c>.
+ </p>
+ <p>For statuses <c>string()</c> and <c>abort</c> the <c>flush</c>
+ option is ignored and flushing is <em>not</em> done.
+ </p>
</desc>
</func>
<func>
@@ -2816,6 +2863,10 @@ os_prompt%</pre>
<p>It can only be used to check the local time of day if
the time-zone info of the underlying operating system is
properly configured.</p>
+ <p>If you do not need the return value to be unique and
+ monotonically increasing, use
+ <seealso marker="kernel:os#timestamp/0">os:timestamp/0</seealso>
+ instead to avoid some overhead.</p>
</desc>
</func>
<func>
@@ -2862,7 +2913,7 @@ os_prompt%</pre>
<p>For external programs, the <c>PATH</c> is searched
(or an equivalent method is used to find programs,
depending on operating system). This is done by invoking
- the shell och certain platforms. The first space
+ the shell on certain platforms. The first space
separated token of the command will be considered as the
name of the executable (or driver). This (among other
things) makes this option unsuitable for running
@@ -2988,8 +3039,11 @@ os_prompt%</pre>
port process. Both <c>Name</c> and <c>Val</c> must be
strings. The one exception is <c>Val</c> being the atom
<c>false</c> (in analogy with <c>os:getenv/1</c>), which
- removes the environment variable. Not available on
- VxWorks.</p>
+ removes the environment variable.</p>
+ <p>If Unicode filename encoding is in effect (see the <seealso
+ marker="erts:erl#file_name_encoding">erl manual
+ page</seealso>), the strings (both <c>Name</c> and
+ <c>Value</c>) may contain characters with codepoints > 255.</p>
</item>
<tag><c>{args, [ string() ]}</c></tag>
<item>
@@ -3526,6 +3580,10 @@ os_prompt%</pre>
<p><c>Bytes</c> is the total number of bytes written to
the port.</p>
</item>
+ <tag><c>{os_pid, Integer | undefined}</c></tag>
+ <item>
+ <p><c>Integer</c> is the process identifier (or equivalent) of an OS process created with <c>open_port({spawn | spawn_executable, Command}, Options)</c>. If the port is not the result of spawning an OS process, the value is <c>undefined</c>.</p>
+ </item>
</taglist>
<p>Failure: <c>badarg</c> if <c>Port</c> is not a local port.</p>
</desc>
@@ -3715,12 +3773,6 @@ os_prompt%</pre>
<tag><c>process_flag(save_calls, N)</c></tag>
<item>
- <p>When there are runnable processes on priority <c>max</c>
- no processes on priority <c>low</c>, <c>normal</c>, or
- <c>high</c> will be selected for execution. As with the
- <c>high</c> priority, processes on lower priorities might
- execute in parallel with processes on priority <c>max</c>.
- </p>
<p><c>N</c> must be an integer in the interval 0..10000.
If <c>N</c> &gt; 0, call saving is made active for the
process, which means that information about the <c>N</c>
@@ -3908,7 +3960,7 @@ os_prompt%</pre>
<item>
<p>Return the current call stack back-trace (<em>stacktrace</em>)
of the process. The stack has the same format as returned by
- <seealso marker="#get_stacktrace/1">erlang:get_stacktrace/0</seealso>.
+ <seealso marker="#get_stacktrace/0">erlang:get_stacktrace/0</seealso>.
</p>
</item>
<tag><c>{dictionary, Dictionary}</c></tag>
@@ -3964,14 +4016,6 @@ os_prompt%</pre>
<p><c>Size</c> is the size in bytes of the process. This
includes call stack, heap and internal structures.</p>
</item>
- <tag><c>{message_binary, BinInfo}</c></tag>
- <item>
- <p><c>BinInfo</c> is a list containing miscellaneous information
- about binaries currently being referred to by the message
- area. This <c>InfoTuple</c> is only valid on an emulator
- using the hybrid heap type. This <c>InfoTuple</c> may be
- changed or removed without prior notice.</p>
- </item>
<tag><c>{message_queue_len, MessageQueueLen}</c></tag>
<item>
<p><c>MessageQueueLen</c> is the number of messages
@@ -4880,6 +4924,7 @@ true</pre>
<v>Type, Res -- see below</v>
</type>
<desc>
+ <p>All times are in milliseconds unless otherwise specified.</p>
<p>Returns information about the system as specified by
<c>Type</c>:</p>
<taglist>
@@ -4893,15 +4938,20 @@ true</pre>
<item>
<p>Returns
<c>{Total_Exact_Reductions, Exact_Reductions_Since_Last_Call}</c>.</p>
- <p><em>NOTE:</em><c>statistics(exact_reductions)</c> is
- a more expensive operation than
- <seealso marker="#statistics_reductions">statistics(reductions)</seealso>
- especially on an Erlang machine with SMP support.</p>
+ <note><p><c>statistics(exact_reductions)</c> is
+ a more expensive operation than
+ <seealso marker="#statistics_reductions">statistics(reductions)</seealso>
+ especially on an Erlang machine with SMP support.</p>
+ </note>
</item>
<tag><c>garbage_collection</c></tag>
<item>
<p>Returns <c>{Number_of_GCs, Words_Reclaimed, 0}</c>. This
information may not be valid for all implementations.</p>
+ <pre>
+> <input>statistics(garbage_collection).</input>
+{85,23961,0}
+</pre>
</item>
<tag><c>io</c></tag>
<item>
@@ -4913,12 +4963,18 @@ true</pre>
<tag><marker id="statistics_reductions"><c>reductions</c></marker></tag>
<item>
<p>Returns
- <c>{Total_Reductions, Reductions_Since_Last_Call}</c>.</p>
- <p><em>NOTE:</em> From erts version 5.5 (OTP release R11B)
- this value does not include reductions performed in current
- time slices of currently scheduled processes. If an
- exact value is wanted, use
- <seealso marker="#statistics_exact_reductions">statistics(exact_reductions)</seealso>.</p>
+ <c>{Total_Reductions, Reductions_Since_Last_Call}</c>.</p>
+ <note>
+ <p>From erts version 5.5 (OTP release R11B)
+ this value does not include reductions performed in current
+ time slices of currently scheduled processes. If an
+ exact value is wanted, use
+ <seealso marker="#statistics_exact_reductions">statistics(exact_reductions)</seealso>.</p>
+ </note>
+ <pre>
+> <input>statistics(reductions).</input>
+{2046,11}
+</pre>
</item>
<tag><c>run_queue</c></tag>
<item>
@@ -4931,7 +4987,74 @@ true</pre>
Note that the run-time is the sum of the run-time for all
threads in the Erlang run-time system and may therefore be greater
than the wall-clock time.</p>
+ <pre>
+> <input>statistics(runtime).</input>
+{1690,1620}
+</pre>
+ </item>
+ <tag><marker id="statistics_scheduler_wall_time"><c>scheduler_wall_time</c></marker></tag>
+ <item>
+ <p>Returns a list of tuples with
+ <c>{SchedulerId, ActiveTime, TotalTime}</c>, where <c>SchedulerId</c> is an integer id of the scheduler, <c>ActiveTime</c> is
+ the duration the scheduler has been busy, <c>TotalTime</c> is the total time duration since
+ <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso>
+ activation. The time unit is not defined and may be subject to change
+ between releases, operating systems and system restarts.
+ <c>scheduler_wall_time</c> should only be used to calculate relative
+ values for scheduler-utilization. <c>ActiveTime</c> can never exceed <c>TotalTime</c>.
+ </p>
+
+ <p>The definition of a busy scheduler is when it is not idle or not
+ scheduling (selecting) a process or port, meaning; executing process
+ code, executing linked-in-driver or NIF code, executing
+ built-in-functions or any other runtime handling, garbage collecting
+ or handling any other memory management. Note, a scheduler may also be
+ busy even if the operating system has scheduled out the scheduler
+ thread.
+ </p>
+
+ <p>
+ Returns <c>undefined</c> if the system flag <seealso marker="#system_flag_scheduler_wall_time">
+ scheduler_wall_time</seealso> is turned off.
+ </p>
+
+ <p>The list of scheduler information is unsorted and may appear in different order
+ between calls.
+ </p>
+ <p>Using <c>scheduler_wall_time</c> to calculate scheduler utilization.</p>
+<pre>
+> <input>erlang:system_flag(scheduler_wall_time, true).</input>
+false
+> <input>Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input>
+ok
+</pre>
+ <p>Some time later we will take another snapshot and calculate scheduler-utilization per scheduler.</p>
+<pre>
+> <input>Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input>
+ok
+> <input>lists:map(fun({{I, A0, T0}, {I, A1, T1}}) ->
+ {I, (A1 - A0)/(T1 - T0)} end, lists:zip(Ts0,Ts1)).</input>
+[{1,0.9743474730177548},
+ {2,0.9744843782751444},
+ {3,0.9995902361669045},
+ {4,0.9738012596572161},
+ {5,0.9717956667018103},
+ {6,0.9739235846420741},
+ {7,0.973237033077876},
+ {8,0.9741297293248656}]
+</pre>
+ <p>Using the same snapshots to calculate a total scheduler-utilization.</p>
+<pre>
+> <input>{A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) ->
+ {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), A/T.</input>
+0.9769136803764825
+</pre>
+
+ <note>
+ <p><c>scheduler_wall_time</c> is by default disabled. Use <c>erlang:system_flag(scheduler_wall_time, true)</c> to enable it. </p>
+ </note>
</item>
+
<tag><c>wall_clock</c></tag>
<item>
<p>Returns
@@ -4941,14 +5064,6 @@ true</pre>
opposed to runtime or CPU time.</p>
</item>
</taglist>
- <p>All times are in milliseconds.</p>
- <pre>
-> <input>statistics(runtime).</input>
-{1690,1620}
-> <input>statistics(reductions).</input>
-{2046,11}
-> <input>statistics(garbage_collection).</input>
-{85,23961,0}</pre>
</desc>
</func>
<func>
@@ -5071,6 +5186,14 @@ true</pre>
<v>Flag, Value, OldValue -- see below</v>
</type>
<desc>
+ <warning>
+ <p>The
+ <seealso marker="#system_flag_cpu_topology">cpu_topology</seealso>,
+ and
+ <seealso marker="#system_flag_scheduler_bind_type">scheduler_bind_type</seealso>
+ <c>Flag</c>s are <em>deprecated</em> and have been scheduled for
+ removal in erts-5.10/OTP-R16.</p>
+ </warning>
<p>Sets various system properties of the Erlang node. Returns
the old value of the flag.</p>
<taglist>
@@ -5081,6 +5204,12 @@ true</pre>
</item>
<tag><marker id="system_flag_cpu_topology"><c>erlang:system_flag(cpu_topology, CpuTopology)</c></marker></tag>
<item>
+ <p><em>NOTE:</em> This argument is <em>deprecated</em> and
+ scheduled for removal in erts-5.10/OTP-R16. Instead of using
+ this argument you are advised to use the <c>erl</c> command
+ line argument <seealso marker="erts:erl#+sct">+sct</seealso>.
+ When this argument has been removed a final CPU topology to use
+ will be determined at emulator boot time.</p>
<p>Sets the user defined <c>CpuTopology</c>. The user defined
CPU topology will override any automatically detected
CPU topology. By passing <c>undefined</c> as <c>CpuTopology</c>
@@ -5095,15 +5224,15 @@ true</pre>
to rebind according to the new CPU topology.
</p>
<p>The user defined CPU topology can also be set by passing
- the <seealso marker="erl#+sct">+sct</seealso> command
+ the <seealso marker="erts:erl#+sct">+sct</seealso> command
line argument to <c>erl</c>.
</p>
<p>For information on the <c>CpuTopology</c> type
and more, see the documentation of
<seealso marker="#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>,
- the <c>erl</c> <seealso marker="erl#+sct">+sct</seealso>
- emulator flag, and
- <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>.
+ and the <c>erl</c> <seealso marker="erts:erl#+sct">+sct</seealso>
+ and <seealso marker="erts:erl#+sbt">+sbt</seealso>
+ command line flags.
</p>
</item>
<tag><c>erlang:system_flag(fullsweep_after, Number)</c></tag>
@@ -5179,6 +5308,12 @@ true</pre>
</item>
<tag><marker id="system_flag_scheduler_bind_type"><c>erlang:system_flag(scheduler_bind_type, How)</c></marker></tag>
<item>
+ <p><em>NOTE:</em> This argument is <em>deprecated</em> and
+ scheduled for removal in erts-5.10/OTP-R16. Instead of using
+ this argument you are advised to use the <c>erl</c> command
+ line argument <seealso marker="erts:erl#+sbt">+sbt</seealso>.
+ When this argument has been removed a final scheduler bind type
+ to use will be determined at emulator boot time.</p>
<p>Controls if and how schedulers are bound to logical
processors.</p>
<p>When <c>erlang:system_flag(scheduler_bind_type, How)</c> is
@@ -5200,93 +5335,61 @@ true</pre>
the CPU topology needs to be known. If the runtime system fails
to automatically detect the CPU topology, it can be defined.
For more information on how to define the CPU topology, see
- <seealso marker="#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>.
+ the <c>erl</c> <seealso marker="erts:erl#+sct">+sct</seealso> command
+ line flag.
</p>
- <p>The runtime system will by default bind schedulers to logical
- processors using the <c>default_bind</c> bind type if the amount
- of schedulers are at least equal to the amount of logical
- processors configured, binding of schedulers is supported,
- and a CPU topology is available at startup.
+ <p>The runtime system will by default <em>not</em> bind schedulers
+ to logical processors.
</p>
<p><em>NOTE:</em> If the Erlang runtime system is the only
operating system process that binds threads to logical processors,
this improves the performance of the runtime system. However,
if other operating system processes (as for example another Erlang
runtime system) also bind threads to logical processors, there
- might be a performance penalty instead. If this is the case you,
- are are advised to unbind the schedulers using the
- <seealso marker="erl#+sbt">+sbtu</seealso> command line argument,
- or <c>erlang:system_flag(scheduler_bind_type, unbound)</c>.</p>
+ might be a performance penalty instead. In some cases this
+ performance penalty might be severe. If this is the case, you
+ are advised to not bind the schedulers.</p>
<p>Schedulers can be bound in different ways. The <c>How</c>
argument determines how schedulers are bound. <c>How</c> can
currently be one of:</p>
<taglist>
<tag><c>unbound</c></tag>
- <item>
- <p>Schedulers will not be bound to logical processors, i.e.,
- the operating system decides where the scheduler threads
- execute, and when to migrate them. This is the default.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt u</seealso>.
+ </p></item>
<tag><c>no_spread</c></tag>
- <item>
- <p>Schedulers with close scheduler identifiers will be bound
- as close as possible in hardware.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt ns</seealso>.
+ </p></item>
<tag><c>thread_spread</c></tag>
- <item>
- <p>Thread refers to hardware threads (e.g. Intels
- hyper-threads). Schedulers with low scheduler identifiers,
- will be bound to the first hardware thread of each core,
- then schedulers with higher scheduler identifiers will be
- bound to the second hardware thread of each core, etc.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt ts</seealso>.
+ </p></item>
<tag><c>processor_spread</c></tag>
- <item>
- <p>Schedulers will be spread like <c>thread_spread</c>, but
- also over physical processor chips.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt ps</seealso>.
+ </p></item>
<tag><c>spread</c></tag>
- <item>
- <p>Schedulers will be spread as much as possible.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt s</seealso>.
+ </p></item>
<tag><c>no_node_thread_spread</c></tag>
- <item>
- <p>Like <c>thread_spread</c>, but if multiple NUMA
- (Non-Uniform Memory Access) nodes exists,
- schedulers will be spread over one NUMA node at a time,
- i.e., all logical processors of one NUMA node will
- be bound to schedulers in sequence.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt nnts</seealso>.
+ </p></item>
<tag><c>no_node_processor_spread</c></tag>
- <item>
- <p>Like <c>processor_spread</c>, but if multiple NUMA
- nodes exists, schedulers will be spread over one
- NUMA node at a time, i.e., all logical processors of
- one NUMA node will be bound to schedulers in sequence.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt nnps</seealso>.
+ </p></item>
<tag><c>thread_no_node_processor_spread</c></tag>
- <item>
- <p>A combination of <c>thread_spread</c>, and
- <c>no_node_processor_spread</c>. Schedulers will be
- spread over hardware threads across NUMA nodes, but
- schedulers will only be spread over processors internally
- in one NUMA node at a time.</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt tnnps</seealso>.
+ </p></item>
<tag><c>default_bind</c></tag>
- <item>
- <p>Binds schedulers the default way. Currently the default
- is <c>thread_no_node_processor_spread</c> (which might change
- in the future).</p>
- </item>
+ <item><p>Same as the <c>erl</c> command line argument
+ <seealso marker="erts:erl#+sbt">+sbt db</seealso>.
+ </p></item>
</taglist>
- <p>How schedulers are bound matters. For example, in
- situations when there are fewer running processes than
- schedulers online, the runtime system tries to migrate
- processes to schedulers with low scheduler identifiers.
- The more the schedulers are spread over the hardware,
- the more resources will be available to the runtime
- system in such situations.
- </p>
<p>The value returned equals <c>How</c> before the
<c>scheduler_bind_type</c> flag was changed.</p>
<p>Failure:</p>
@@ -5305,17 +5408,25 @@ true</pre>
</item>
</taglist>
<p>The scheduler bind type can also be set by passing
- the <seealso marker="erl#+sbt">+sbt</seealso> command
+ the <seealso marker="erts:erl#+sbt">+sbt</seealso> command
line argument to <c>erl</c>.
</p>
<p>For more information, see
<seealso marker="#system_info_scheduler_bind_type">erlang:system_info(scheduler_bind_type)</seealso>,
<seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>,
- the <c>erl</c> <seealso marker="erl#+sbt">+sbt</seealso>
- emulator flag, and
- <seealso marker="#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>.
+ the <c>erl</c> <seealso marker="erts:erl#+sbt">+sbt</seealso>
+ and <seealso marker="erts:erl#+sct">+sct</seealso> command line
+ flags.
</p>
</item>
+ <tag><marker id="system_flag_scheduler_wall_time"><c>erlang:system_flag(scheduler_wall_time, Boolean)</c></marker></tag>
+ <item>
+ <p>Turns on/off scheduler wall time measurements. </p>
+ <p>For more information see,
+ <seealso marker="#statistics_scheduler_wall_time">erlang:statistics(scheduler_wall_time)</seealso>.
+ </p>
+ </item>
+
<tag><marker id="system_flag_schedulers_online"><c>erlang:system_flag(schedulers_online, SchedulersOnline)</c></marker></tag>
<item>
<p>Sets the amount of schedulers online. Valid range is
@@ -5327,6 +5438,7 @@ true</pre>
<seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>.
</p>
</item>
+
<tag><c>erlang:system_flag(trace_control_word, TCW)</c></tag>
<item>
<p>Sets the value of the node's trace control word to
@@ -5514,10 +5626,12 @@ true</pre>
<item>
<p>Returns the <c>CpuTopology</c> which currently is used by the
emulator. The CPU topology is used when binding schedulers
- to logical processors. The CPU topology used is the user defined
- CPU topology if such exist; otherwise, the automatically
- detected CPU topology if such exist. If no CPU topology
- exist <c>undefined</c> is returned.</p>
+ to logical processors. The CPU topology used is the
+ <seealso marker="erlang#system_info_cpu_topology_defined">user
+ defined CPU topology</seealso> if such exists; otherwise, the
+ <seealso marker="erlang#system_info_cpu_topology_detected">automatically
+ detected CPU topology</seealso> if such exists. If no CPU topology
+ exists, <c>undefined</c> is returned.</p>
<p>Types:</p>
<list type="bulleted">
<item><c>CpuTopology = LevelEntryList | undefined</c></item>
@@ -5564,8 +5678,8 @@ true</pre>
<item>
<p>Returns the user defined <c>CpuTopology</c>. For more
information see the documentation of
- <seealso marker="#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>
- and the documentation of the
+ the <c>erl</c> <seealso marker="erts:erl#+sct">+sct</seealso> command
+ line flag, and the documentation of the
<seealso marker="#system_info_cpu_topology">cpu_topology</seealso>
argument.
</p>
@@ -5633,6 +5747,29 @@ true</pre>
used by the runtime system. It will be on the form
<seealso marker="erts:erl_driver#version_management">"&lt;major ver&gt;.&lt;minor ver&gt;"</seealso>.</p>
</item>
+ <tag><c>dynamic_trace</c></tag>
+ <item>
+ <p>Returns an atom describing the dynamic trace framework
+ compiled into the virtual machine. It can currently be either
+ <c>dtrace</c>, <c>systemtap</c> or <c>none</c>. For a
+ commercial or standard build, this is always <c>none</c>,
+ the other return values indicate a custom configuration
+ (e.g. <c>./configure --with-dynamic-trace=dtrace</c>). See
+ the <seealso marker="runtime_tools:dyntrace">dyntrace
+ </seealso> manual page and the
+ <c>README.dtrace</c>/<c>README.systemtap</c> files in the
+ Erlang source code top directory for more information
+ about dynamic tracing.</p>
+ </item>
+ <tag><c>dynamic_trace_probes</c></tag>
+ <item>
+ <p>Returns a <c>boolean()</c> indicating if dynamic trace probes
+ (either dtrace or systemtap) are built into the
+ emulator. This can only be <c>true</c> if the virtual
+ machine was built for dynamic tracing
+ (i.e. <c>system_info(dynamic_trace)</c> returns
+ <c>dtrace</c> or <c>systemtap</c>).</p>
+ </item>
<tag><c>elib_malloc</c></tag>
<item>
<p>This option will be removed in a future release.
@@ -5643,7 +5780,7 @@ true</pre>
<item>
<p>Returns the value of the distribution buffer busy limit
in bytes. This limit can be set on startup by passing the
- <seealso marker="erl#+zdbbl">+zdbbl</seealso> command line
+ <seealso marker="erts:erl#+zdbbl">+zdbbl</seealso> command line
flag to <c>erl</c>.</p>
</item>
<tag><c>fullsweep_after</c></tag>
@@ -5665,10 +5802,6 @@ true</pre>
can spawn a process that does not use the default
settings.</p>
</item>
- <tag><c>global_heaps_size</c></tag>
- <item>
- <p>Returns the current size of the shared (global) heap.</p>
- </item>
<tag><c>heap_sizes</c></tag>
<item>
<p>Returns a list of integers representing valid heap sizes
@@ -5678,7 +5811,7 @@ true</pre>
<tag><c>heap_type</c></tag>
<item>
<p>Returns the heap type used by the current emulator.
- Currently the following heap types exist:</p>
+ Currently only the following heap type exists:</p>
<taglist>
<tag><c>private</c></tag>
<item>
@@ -5687,17 +5820,6 @@ true</pre>
allowed. Messages passed between processes are copied
between heaps.</p>
</item>
- <tag><c>shared</c></tag>
- <item>
- <p>One heap for use by all processes. Messages passed
- between processes are passed by reference.</p>
- </item>
- <tag><c>hybrid</c></tag>
- <item>
- <p>A hybrid of the <c>private</c> and <c>shared</c> heap
- types. A shared heap as well as private heaps are
- used.</p>
- </item>
</taglist>
</item>
<tag><c>info</c></tag>
@@ -5845,14 +5967,13 @@ true</pre>
<p>Returns information on how user has requested
schedulers to be bound or not bound.</p>
<p><em>NOTE:</em> Even though user has requested
- schedulers to be bound via
- <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>,
- they might have silently failed to bind. In order to
- inspect actual scheduler bindings call
+ schedulers to be bound, they might have silently failed
+ to bind. In order to inspect actual scheduler bindings call
<seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>.
</p>
<p>For more information, see
- <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>, and
+ the <c>erl</c> <seealso marker="erts:erl#+sbt">+sbt</seealso>
+ command line argument, and
<seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>.
</p>
</item>
@@ -5875,7 +5996,8 @@ true</pre>
<p>Note that only schedulers online can be bound to logical
processors.</p>
<p>For more information, see
- <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>,
+ the <c>erl</c> <seealso marker="erts:erl#+sbt">+sbt</seealso>
+ command line argument,
<seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>.
</p>
</item>
@@ -7099,7 +7221,7 @@ true</pre>
<c>Id</c> has no effect on the caller in the future (unless
the link is setup again). If caller is trapping exits, an
<c>{'EXIT', Id, _}</c> message due to the link might have
- been placed in the callers message queue prior to the call,
+ been placed in the caller's message queue prior to the call,
though. Note, the <c>{'EXIT', Id, _}</c> message can be the
result of the link, but can also be the result of <c>Id</c>
calling <c>exit/2</c>. Therefore, it <em>may</em> be
diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml
index ebf76a2afe..3358b8f115 100644
--- a/erts/doc/src/erlc.xml
+++ b/erts/doc/src/erlc.xml
@@ -129,12 +129,6 @@
This option will be ignored by compilers that have a
a single output format.</p>
</item>
- <tag>-hybrid</tag>
- <item>
- <p>Compile using the hybrid-heap emulator. This is mainly useful
- for compiling native code, which needs to be compiled with the same
- run-time system that it should be run on.</p>
- </item>
<tag>-smp</tag>
<item>
<p>Compile using the SMP emulator. This is mainly useful
diff --git a/erts/doc/src/erlsrv.xml b/erts/doc/src/erlsrv.xml
index c1ecbc7b77..b2f34ed247 100644
--- a/erts/doc/src/erlsrv.xml
+++ b/erts/doc/src/erlsrv.xml
@@ -357,11 +357,12 @@ The environment of an Erlang machine started
the console subsystem and programs running as window
applications. An application which runs in the console subsystem
(normal for port programs) uses the win32 function
- <c><![CDATA[SetConsoleCtrlHandler]]></c> to a control handler that returns
- TRUE in answer to the <c><![CDATA[CTRL_LOGOFF_EVENT]]></c>. Other
- applications just forward <c><![CDATA[WM_ENDSESSION]]></c> and
- <c><![CDATA[WM_QUERYENDSESSION]]></c> to the default window procedure. Here
- is a brief example in C of how to set the console control
+ <c><![CDATA[SetConsoleCtrlHandler]]></c> to register a control handler
+ that returns TRUE in answer to the <c><![CDATA[CTRL_LOGOFF_EVENT]]></c>
+ and <c><![CDATA[CTRL_SHUTDOWN_EVENT]]></c> events. Other applications
+ just forward <c><![CDATA[WM_ENDSESSION]]></c> and
+ <c><![CDATA[WM_QUERYENDSESSION]]></c> to the default window procedure.
+ Here is a brief example in C of how to set the console control
handler:</p>
<code type="none"><![CDATA[
#include <windows.h>
@@ -372,6 +373,8 @@ The environment of an Erlang machine started
BOOL WINAPI service_aware_handler(DWORD ctrl){
if(ctrl == CTRL_LOGOFF_EVENT)
return TRUE;
+ if(ctrl == CTRL_SHUTDOWN_EVENT)
+ return TRUE;
return FALSE;
}
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index 86e1e5168a..ec5e7d9b74 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -58,11 +58,8 @@
<item>Allocator used for memory blocks that are expected to be
long-lived, for example Erlang code.</item>
<tag><c>fix_alloc</c></tag>
- <item>A very fast allocator used for some fix-sized
- data. <c>fix_alloc</c> manages a set of memory pools from
- which memory blocks are handed out. <c>fix_alloc</c>
- allocates memory pools from <c>ll_alloc</c>. Memory pools
- that have been allocated are never deallocated.</item>
+ <item>A fast allocator used for some frequently used
+ fixed size data types.</item>
<tag><c>std_alloc</c></tag>
<item>Allocator used for most memory blocks not allocated via any of
the other allocators described above.</item>
@@ -83,7 +80,7 @@
where only small blocks are placed. Currently this allocator is
disabled by default.</item>
</taglist>
- <p><c>sys_alloc</c> and <c>fix_alloc</c> are always enabled and
+ <p><c>sys_alloc</c> is always enabled and
cannot be disabled. <c>mseg_alloc</c> is always enabled if it is
available and an allocator that uses it is enabled. All other
allocators can be <seealso marker="#M_e">enabled or disabled</seealso>.
@@ -104,7 +101,7 @@
<marker id="alloc_util"></marker>
<title>The alloc_util framework</title>
<p>Internally a framework called <c>alloc_util</c> is used for
- implementing allocators. <c>sys_alloc</c>, <c>fix_alloc</c>, and
+ implementing allocators. <c>sys_alloc</c>, and
<c>mseg_alloc</c> do not use this framework; hence, the
following does <em>not</em> apply to them.</p>
<p>An allocator manages multiple areas, called carriers, in which
@@ -212,6 +209,14 @@
This since it will only cause problems for other allocators.</p>
</item>
</taglist>
+ <p>Apart from the ordinary allocators described above a number of
+ pre-allocators are used for some specific data types. These
+ pre-allocators pre-allocate a fixed amount of memory for certain data
+ types when the run-time system starts. As long as pre-allocated memory
+ is available, it will be used. When no pre-allocated memory is
+ available, memory will be allocated in ordinary allocators. These
+ pre-allocators are typically much faster than the ordinary allocators,
+ but can only satisfy a limited amount of requests.</p>
</section>
<note><p>
@@ -272,18 +277,6 @@
Max cached segments. The maximum number of memory segments
stored in the memory segment cache. Valid range is
0-30. Default value is 5.</item>
- <tag><marker id="MMcci"><c><![CDATA[+MMcci <time>]]></c></marker></tag>
- <item>
- Cache check interval (in milliseconds). The memory segment
- cache is checked for segments to destroy at an interval
- determined by this parameter. Default value is 1000.</item>
- </taglist>
- <p>The following flags are available for configuration of
- <c>fix_alloc</c>:</p>
- <taglist>
- <tag><marker id="MFe"><c>+MFe true</c></marker></tag>
- <item>
- Enable <c>fix_alloc</c>. Note: <c>fix_alloc</c> cannot be disabled.</item>
</taglist>
<p>The following flags are available for configuration of
<c>sys_alloc</c>:</p>
@@ -322,7 +315,7 @@
based on <c>alloc_util</c>. If <c>u</c> is used as subsystem
identifier (i.e., <c><![CDATA[<S> = u]]></c>) all allocators based on
<c>alloc_util</c> will be effected. If <c>B</c>, <c>D</c>, <c>E</c>,
- <c>H</c>, <c>L</c>, <c>R</c>, <c>S</c>, or <c>T</c> is used as
+ <c>F</c>, <c>H</c>, <c>L</c>, <c>R</c>, <c>S</c>, or <c>T</c> is used as
subsystem identifier, only the specific allocator identified will be
effected:</p>
<taglist>
@@ -441,26 +434,23 @@
kilobytes). See <seealso marker="#mseg_mbc_sizes">the description
on how sizes for mseg_alloc multiblock carriers are decided</seealso>
in "the <c>alloc_util</c> framework" section.</item>
- <tag><marker id="M_t"><c><![CDATA[+M<S>t true|false|<amount>]]></c></marker></tag>
+ <tag><marker id="M_t"><c><![CDATA[+M<S>t true|false]]></c></marker></tag>
<item>
- <p>Multiple, thread specific instances of the allocator.
- This option will only have any effect on the runtime system
- with SMP support. Default behaviour on the runtime system with
- SMP support (<c>N</c> equals the number of scheduler threads):</p>
+ <p>Multiple, thread specific instances of the allocator.
+ This option will only have any effect on the runtime system
+ with SMP support. Default behaviour on the runtime system with
+ SMP support:</p>
<taglist>
- <tag><c>temp_alloc</c></tag>
- <item><c>N + 1</c> instances.</item>
<tag><c>ll_alloc</c></tag>
<item><c>1</c> instance.</item>
<tag>Other allocators</tag>
- <item><c>N</c> instances when <c>N</c> is less than or equal to
- <c>16</c>. <c>16</c> instances when <c>N</c> is greater than
- <c>16</c>.</item>
+ <item><c>NoSchedulers+1</c> instances. Each scheduler will use
+ a lock-free instance of its own and other threads will use
+ a common instance.</item>
</taglist>
- <p><c>temp_alloc</c> will always use <c>N + 1</c> instances when
- this option has been enabled regardless of the amount passed.
- Other allocators will use the same amount of instances as the
- amount passed as long as it isn't greater than <c>N</c>.</p>
+ <p>It was previously (before ERTS version 5.9) possible to configure
+ a smaller amount of thread specific instances than schedulers.
+ This is, however, not possible any more.</p>
</item>
</taglist>
<p>Currently the following flags are available for configuration of
diff --git a/erts/doc/src/make.dep b/erts/doc/src/make.dep
deleted file mode 100644
index 98bac78235..0000000000
--- a/erts/doc/src/make.dep
+++ /dev/null
@@ -1,32 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/gandalf/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: absform.tex alt_dist.tex book.tex crash_dump.tex \
- driver.tex driver_entry.tex epmd.tex erl.tex \
- erl_dist_protocol.tex erl_driver.tex erl_ext_dist.tex \
- erl_prim_loader.tex erl_set_memory_block.tex \
- erlang.tex erlc.tex erlsrv.tex erts_alloc.tex \
- escript.tex inet_cfg.tex init.tex match_spec.tex \
- part.tex ref_man.tex run_erl.tex start.tex \
- start_erl.tex tty.tex werl.tex zlib.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: erl_ext_fig.ps
-
diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml
index f0390c9db8..bdcf9c3816 100644
--- a/erts/doc/src/match_spec.xml
+++ b/erts/doc/src/match_spec.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -75,7 +75,7 @@
<item>MatchCondition ::= { GuardFunction } |
{ GuardFunction, ConditionExpression, ... }
</item>
- <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></c> |
+ <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> |
<c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> |
<c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> |
<c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> |
@@ -133,7 +133,7 @@
<item>MatchCondition ::= { GuardFunction } |
{ GuardFunction, ConditionExpression, ... }
</item>
- <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></c> |
+ <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> |
<c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> |
<c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> |
<c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> |
@@ -172,7 +172,7 @@
<title>Functions allowed in all types of match specifications</title>
<p>The different functions allowed in <c><![CDATA[match_spec]]></c> work like this:
</p>
- <p><em>is_atom, is_constant, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in
+ <p><em>is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in
Erlang, return <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>.
</p>
<p><em>is_record: </em>Takes an additional parameter, which SHALL
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 4cef9669dd..6b6a3374d1 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -30,6 +30,763 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 5.9.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If threads support for the runtime system had been
+ disabled at compile time (<c>--disable-threads</c> had
+ been passed to <c>configure</c>), and the <c>+A</c>
+ command line argument of <c>erl</c> was passed when
+ starting the runtime system, <seealso
+ marker="erl_driver#driver_system_info">driver_system_info()</seealso>
+ erroneously claimed that the runtime system had async
+ threads even though it had not.</p>
+ <p>
+ Due to this bug the file driver did not split tasks into
+ smaller chunks, but instead completed the whole task at
+ once, i.e., the scheduler got occupied with I/O for a
+ longer time than intended.</p>
+ <p>
+ Own Id: OTP-10059</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A proposal for a new scheduler wakeup strategy has been
+ implemented. For more information see the documentation
+ of the <seealso marker="erl#+sws">+sws</seealso> command
+ line argument of <c>erl</c>.</p>
+ <p>
+ Own Id: OTP-10033 Aux Id: Seq12025 </p>
+ </item>
+ <item>
+ <p>
+ A switch for configuration of busy wait length for
+ scheduler threads has been added. For more information
+ see the documentation of the <seealso
+ marker="erl#+sbwt">+sbwt</seealso> command line argument
+ of <c>erl</c>.</p>
+ <p>
+ Own Id: OTP-10044 Aux Id: Seq11976 </p>
+ </item>
+ <item>
+ <p>
+ The extra memory barriers introduced by bug-fix OTP-9281
+ were unnecessarily used also on tables without the
+ <c>write_concurrency</c> option enabled. This could
+ unnecessarily degrade performance of ETS tables without
+ <c>write_concurrency</c> on some hardware (e.g. PowerPC)
+ while not effecting performance at all on other hardware
+ (e.g. x86/x86_64).</p>
+ <p>
+ OTP-9281 (R14B03): ETS tables using the
+ <c>write_concurrency</c> option could potentially get
+ into an internally inconsistent state.</p>
+ <p>
+ Own Id: OTP-10048 Aux Id: OTP-9281 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 5.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>erlang:system_profile</c> errorneous profiled the
+ profiler process when observing runnable processes. This
+ has been corrected. </p>
+ <p>
+ Own Id: OTP-9849</p>
+ </item>
+ <item>
+ <p>Calling trace_info/2 asking for information about a
+ function that had native could could crash the run-time
+ system.</p>
+ <p>
+ Own Id: OTP-9886</p>
+ </item>
+ <item>
+ <p>
+ reduce smp locking time range in erts_garbage_collect
+ (thanks to Jovi Zhang)</p>
+ <p>
+ Own Id: OTP-9912</p>
+ </item>
+ <item>
+ <p>
+ Fix typo in supervisor behaviour doc (Thanks to Ricardo
+ Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9924</p>
+ </item>
+ <item>
+ <p>
+ Correct spelling of registered (Thanks to Richard
+ Carlsson)</p>
+ <p>
+ Own Id: OTP-9925</p>
+ </item>
+ <item>
+ <p>
+ erts: Remove unused variable (Thanks to Jovi Zhang)</p>
+ <p>
+ Own Id: OTP-9926</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in ETS with <c>compressed</c> option and
+ insertion of term containing large integers (>2G) on
+ 64-bit machines. Seen to cause emulator crash. (Thanks to
+ Diego Llarrull for excellent bug report)</p>
+ <p>
+ Own Id: OTP-9932</p>
+ </item>
+ <item>
+ <p>
+ Handle Linux OS where /sys/devices/system/node is only
+ readable by root. Fallback to /sys/devices/system/cpu for
+ topology info.</p>
+ <p>
+ Own Id: OTP-9978</p>
+ </item>
+ <item>
+ <p> When an escript ends now all printout to standard
+ output and standard error gets out on the terminal. This
+ bug has been corrected by changing the behaviour of
+ erlang:halt/0,1, which should fix the same problem for
+ other escript-like applications, i.e that data stored in
+ the output port driver buffers got lost when printing on
+ a TTY and exiting through erlang:halt/0,1. </p>
+ <p> The BIF:s erlang:halt/0,1 has gotten improved
+ semantics and there is a new BIF erlang:halt/2 to
+ accomplish something like the old semantics. See the
+ documentation. </p>
+ <p> Now erlang:halt/0 and erlang:halt/1 with an integer
+ argument will close all ports and allow all pending async
+ threads operations to finish before exiting the emulator.
+ Previously erlang:halt/0 and erlang:halt(0) would just
+ wait for pending async threads operations but not close
+ ports. And erlang:halt/1 with a non-zero integer argument
+ would not even wait for pending async threads operations.
+ </p>
+ <p> To roughly the old behaviour, to not wait for ports
+ and async threads operations when you exit the emulator,
+ you use erlang:halt/2 with an integer first argument and
+ an option list containing {flush,false} as the second
+ argument. Note that now is flushing not dependant of the
+ exit code, and you can not only flush async threads
+ operations which we deemed as a strange behaviour anyway.
+ </p>
+ <p>Also, erlang:halt/1,2 has gotten a new feature: If the
+ first argument is the atom 'abort' the emulator is
+ aborted producing a core dump, if the operating system so
+ allows. </p>
+ <p>
+ Own Id: OTP-9985</p>
+ </item>
+ <item>
+ <p>
+ Added check to inet driver to avoid building on operating
+ systems that do not yet have IPv6 compatible socket API.
+ (Thanks to Peer Stritzinger)</p>
+ <p>
+ Own Id: OTP-9996</p>
+ </item>
+ <item>
+ <p>
+ Fix bug when the number of CPUs actually found is lower
+ than the configured value. (Thanks to Benjamin
+ Herrenschmidt)</p>
+ <p>
+ Own Id: OTP-10004</p>
+ </item>
+ <item>
+ <p>
+ The runtime system without SMP support and without thread
+ support erroneously busy waited when no work was present.
+ This bug first appeared in <c>erts-5.9</c>.</p>
+ <p>
+ Own Id: OTP-10019</p>
+ </item>
+ <item>
+ <p>
+ Various typographical errors corrected in documentation
+ for common_test, driver, erl_driver and windows
+ installation instructions. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-10037</p>
+ </item>
+ <item>
+ <p>
+ Fix memory leak caused by race on exiting process</p>
+ <p>
+ Own Id: OTP-10041</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Add <c>erlang:statistics(scheduler_wall_time)</c> to
+ ensure correct determination of scheduler utilization.
+ Measuring scheduler utilization is strongly preferred
+ over CPU utilization, since CPU utilization gives very
+ poor indications of actual scheduler/vm usage.</p>
+ <p>
+ Own Id: OTP-9858</p>
+ </item>
+ <item>
+ <p>
+ ERTS internal API improvements. In some cases the amount
+ of atomic read operations needed have been reduced due to
+ this.</p>
+ <p>
+ Own Id: OTP-9922</p>
+ </item>
+ <item>
+ <p>
+ The DTrace source patch from Scott Lystig Fritchie is
+ integrated in the source tree. Using an emulator with
+ dtrace probe is still not supported for production use,
+ but may be a valuable debugging tool. Configure with
+ --with-dynamic-trace=dtrace (or
+ --with-dynamic-trace=systemtap) to create a build with
+ dtrace probes enabled. See runtime_tools for
+ documentation and examples.</p>
+ <p>
+ Own Id: OTP-10017</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ enif_make_copy may invalidate enif_inspect_binary.</p>
+ <p>
+ Own Id: OTP-9828</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 5.9.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A feature test for the <c>lwsync</c> instruction
+ performed on PowerPC hardware at runtime system startup
+ got into an eternal loop if the instruction was not
+ supported. This bug was introduced in erts-5.9/OTP-R15B.</p>
+ <p>
+ Own Id: OTP-9843</p>
+ </item>
+ <item>
+ <p>
+ I/O events could potentially be delayed for ever when
+ enabling kernel-poll on a non-SMP runtime system
+ executing on Solaris. When also combined with
+ async-threads the runtime system hung before completing
+ the boot phase. This bug was introduced in
+ erts-5.9/OTP-R15B.</p>
+ <p>
+ Own Id: OTP-9844</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 5.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Honor option <c>packet_size</c> for http packet parsing
+ by both TCP socket and <c>erlang:decode_packet</c>. This
+ gives the ability to accept HTTP headers larger than the
+ default setting, but also avoid DoS attacks by accepting
+ lines only up to whatever length you wish to allow. For
+ consistency, packet type <c>line</c> also honor option
+ <c>packet_size</c>. (Thanks to Steve Vinoski)</p>
+ <p>
+ Own Id: OTP-9389</p>
+ </item>
+ <item>
+ <p> A few contracts in the <c>lists</c> module have been
+ corrected. </p>
+ <p>
+ Own Id: OTP-9616</p>
+ </item>
+ <item>
+ <p>
+ The Unicode noncharacter code points 16#FFFE and 16#FFFE
+ were not allowed to be encoded or decoded using the
+ <c>unicode</c> module or bit syntax. That was
+ inconsistent with the other noncharacters 16#FDD0 to
+ 16#FDEF that could be encoded/decoded. To resolve the
+ inconsistency, 16#FFFE and 16#FFFE can now be encoded and
+ decoded. (Thanks to Alisdair Sullivan.)</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9624</p>
+ </item>
+ <item>
+ <p>
+ Make epp search directory of current file first when
+ including another file This completes a partial fix in
+ R11 that only worked for include_lib(). (Thanks to
+ Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9645</p>
+ </item>
+ <item>
+ <p>
+ Fixed memory leak in
+ <c>enif_inspect_io_list_as_binary</c> when applied on a
+ process independent environment.</p>
+ <p>
+ Own Id: OTP-9668</p>
+ </item>
+ <item>
+ <p>The number of beam catches allowed in code are no
+ longer statically defined and will grow according to its
+ need.</p>
+ <p>
+ Own Id: OTP-9692</p>
+ </item>
+ <item>
+ <p>
+ Add missing parenthesis in heart doc.</p>
+ <p>
+ Add missing spaces in the Reference Manual distributed
+ section.</p>
+ <p>
+ In the HTML version of the doc those spaces are necessary
+ to separate those words.</p>
+ <p>
+ Own Id: OTP-9693</p>
+ </item>
+ <item>
+ <p>
+ Fixes module erlang doc style: option description (Thanks
+ to Ricardo Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9697</p>
+ </item>
+ <item>
+ <p>
+ Specifying a scope to binary:match/3 when using multiple
+ searchstrings resulted in faulty return values. This is
+ now corrected.</p>
+ <p>
+ Own Id: OTP-9701</p>
+ </item>
+ <item>
+ <p>
+ The runtime system crashed if more than one thread tried
+ to exit the runtime system at the same time.</p>
+ <p>
+ Own Id: OTP-9705</p>
+ </item>
+ <item>
+ <p>
+ Fix documentation for erlang:process_flag/2</p>
+ <p>
+ For the subsection about process_flag(save_calls, N)
+ there's an unrelated paragraph about process priorities
+ which was copied from the preceeding subsection regarding
+ process_flag(priority, Level). (Thanks to Filipe David
+ Manana)</p>
+ <p>
+ Own Id: OTP-9714</p>
+ </item>
+ <item>
+ <p>
+ Calls to <c>erlang:system_flag(schedulers_online, N)</c>
+ and/or <c>erlang:system_flag(multi_scheduling,
+ block|unblock)</c> could cause internal data used by this
+ functionality to get into an inconsistent state. When
+ this happened various problems occurred. This bug was
+ quite hard to trigger, so hopefully no-one has been
+ effected by it.</p>
+ <p>
+ A spinlock used by the run-queue management sometimes got
+ heavily contended. This code has now been rewritten, and
+ the spinlock has been removed.</p>
+ <p>
+ Own Id: OTP-9727</p>
+ </item>
+ <item>
+ <p>
+ Use libdlpi to get physical address (Thanks to Trond
+ Norbye)</p>
+ <p>
+ Own Id: OTP-9818</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> An option list argument can now be passed to
+ <c>file:read_file_info/2, file:read_link_info/2</c> and
+ <c>file:write_file_info/3</c> and set time type
+ information in the call. Valid options are <c>{time,
+ local}, {time, universal}</c> and <c>{time, posix}</c>.
+ In the case of <c>posix</c> time no conversions are made
+ which makes the operation a bit faster. </p>
+ <p>
+ Own Id: OTP-7687</p>
+ </item>
+ <item>
+ <p>A number of memory allocation optimizations have been
+ implemented. Most optimizations reduce contention caused
+ by synchronization between threads during allocation and
+ deallocation of memory. Most notably:</p> <list> <item>
+ Synchronization of memory management in scheduler
+ specific allocator instances has been rewritten to use
+ lock-free synchronization. </item> <item> Synchronization
+ of memory management in scheduler specific pre-allocators
+ has been rewritten to use lock-free synchronization.
+ </item> <item> The 'mseg_alloc' memory segment allocator
+ now use scheduler specific instances instead of one
+ instance. Apart from reducing contention this also
+ ensures that memory allocators always create memory
+ segments on the local NUMA node on a NUMA system. </item>
+ </list>
+ <p>
+ Own Id: OTP-7775</p>
+ </item>
+ <item>
+ <p>
+ The ethread atomic memory operations API used by the
+ runtime system has been extended and improved.</p>
+ <p>
+ The ethread library now also performs runtime tests for
+ presence of hardware features, such as for example SSE2
+ instructions, instead of requiring this to be determined
+ at compile time.</p>
+ <p>
+ All uses of the old deprecated atomic API in the runtime
+ system have been replaced with the use of the new atomic
+ API. In a lot of places this change imply a relaxation of
+ memory barriers used.</p>
+ <p>
+ Own Id: OTP-9014</p>
+ </item>
+ <item>
+ <p>gen_sctp:open/0-2 may now return
+ {error,eprotonosupport} if SCTP is not supported</p>
+ <p>gen_sctp:peeloff/1 has been implemented and creates a
+ one-to-one socket which also are supported now</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9239</p>
+ </item>
+ <item>
+ <p>
+ Sendfile has been added to the file module's API.
+ sendfile/2 is used to read data from a file and send it
+ to a tcp socket using a zero copying mechanism if
+ available on that OS.</p>
+ <p>
+ Thanks to Tuncer Ayaz and Steve Vinovski for original
+ implementation</p>
+ <p>
+ Own Id: OTP-9240</p>
+ </item>
+ <item>
+ <p>
+ enif_get_reverse_list function added to nif API. This
+ function should be used to reverse small lists which are
+ deep within other structures making it impractical to do
+ the reverse in Erlang.</p>
+ <p>
+ Own Id: OTP-9392</p>
+ </item>
+ <item>
+ <p>
+ The deprecated concat_binary/1 BIF has been removed. Use
+ <c>list_to_binary</c> or <c>iolist_to_binary/1</c>
+ instead.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9421</p>
+ </item>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p>Line number and filename information are now included
+ in exception backtraces as a fourth element in the MFA
+ tuple. The information will be pretty-printed by the
+ shell and used by <c>common_test</c> to provide better
+ indication of where a test case.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9468</p>
+ </item>
+ <item>
+ <p>All binary constants used to be handled as heap
+ binaries (i.e. the entire binary would be copied when
+ sent to another process). Binary constants larger than 64
+ bytes are now refc binaries (i.e. the actual data in the
+ binary will not be copied when sent to another
+ process).</p>
+ <p>
+ Own Id: OTP-9486</p>
+ </item>
+ <item>
+ <p>
+ If a float and an integer is compared, the integer is
+ only converted to a float if the float datatype can
+ contain it. Otherwise the float is converted to an
+ integer.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9497</p>
+ </item>
+ <item>
+ <p>
+ Add NIF function enif_is_number</p>
+ <p>
+ This function allows for easily determining if a term
+ represents or not a number (integer, float, small or
+ big).(Thanks to Filipe David Manana)</p>
+ <p>
+ Own Id: OTP-9629</p>
+ </item>
+ <item>
+ <p>
+ The ERTS internal system block functionality has been
+ replaced by new functionality for blocking the system.
+ The old system block functionality had contention issues
+ and complexity issues. The new functionality piggy-backs
+ on thread progress tracking functionality needed by newly
+ introduced lock-free synchronization in the runtime
+ system. When the functionality for blocking the system
+ isn't used, there is more or less no overhead at all.
+ This since the functionality for tracking thread progress
+ is there and needed anyway.</p>
+ <p>
+ Own Id: OTP-9631</p>
+ </item>
+ <item>
+ <p>
+ An ERTS internal, generic, many to one, lock-free queue
+ for communication between threads has been introduced.
+ The many to one scenario is very common in ERTS, so it
+ can be used in a lot of places in the future. Currently
+ it is used by scheduling of certain jobs, and the async
+ thread pool, but more uses are planned for the future.</p>
+ <p>
+ Drivers using the driver_async functionality are not
+ automatically locked to the system anymore, and can be
+ unloaded as any dynamically linked in driver.</p>
+ <p>
+ Scheduling of ready async jobs is now also interleaved in
+ between other jobs. Previously all ready async jobs were
+ performed at once.</p>
+ <p>
+ Own Id: OTP-9632</p>
+ </item>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ <item>
+ <p>
+ Changed the internal BIF calling convention. Will make
+ simpler faster code and allow BIFs with an arbitrary
+ arity.</p>
+ <p>
+ Own Id: OTP-9662</p>
+ </item>
+ <item>
+ <p>
+ Windows native critical sections are now used internally
+ in the runtime system on Windows as mutex implementation.
+ This since they perform better under extreme contention
+ than our own implementation.</p>
+ <p>
+ Own Id: OTP-9671</p>
+ </item>
+ <item>
+ <p>
+ Convert some erl_nif macros into inline functions. Allow
+ for better compile time type checking. (Thanks to Tuncer
+ Ayaz)</p>
+ <p>
+ Own Id: OTP-9675</p>
+ </item>
+ <item>
+ <p>
+ The <c>+scl</c> command line flag has been added. It can
+ be used for disabling compaction of scheduler load. For
+ more information see the <c>erl(1)</c> documentation.</p>
+ <p>
+ Own Id: OTP-9695</p>
+ </item>
+ <item>
+ <p>The build system has been updated so that Erlang/OTP
+ can be built on Mac OS X Lion systems without a GCC
+ compiler. The INSTALL guide has been updated with
+ instructions on how to install a GCC compiler and build
+ Erlang/OTP with it, in order to get a run-time system
+ with better performance.</p>
+ <p>
+ Own Id: OTP-9712</p>
+ </item>
+ <item>
+ <p>
+ When loading a module, the system use to run on a single
+ scheduler during the entire loading process. This has
+ been changed to only take down the system just before
+ inserting the loaded code into the system tables,
+ resulting in a much shorter disruption if a module is
+ loaded in a busy system. (Suggested by Bob Ippolito.)</p>
+ <p>
+ Own Id: OTP-9720</p>
+ </item>
+ <item>
+ <p>
+ Possible to run HiPE without floating point exceptions
+ (FPE). Useful on platforms that lack reliable FPE. Slower
+ float operations compared to HiPE with FPE.</p>
+ <p>
+ Own Id: OTP-9724</p>
+ </item>
+ <item>
+ <p>
+ As of ERTS version 5.9 (OTP-R15B) the runtime system will
+ by default <em>not</em> bind schedulers to logical
+ processors.</p>
+ <p>
+ If the Erlang runtime system is the only operating system
+ process that binds threads to logical processors, this
+ improves the performance of the runtime system. However,
+ if other operating system processes (as for example
+ another Erlang runtime system) also bind threads to
+ logical processors, there might be a performance penalty
+ instead. In some cases this performance penalty might be
+ severe. Due to this, we change the default so that the
+ user must make an active decision in order to bind
+ schedulers.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9726</p>
+ </item>
+ <item>
+ <p>
+ The use of <c>erlang:system_flag(scheduler_bind_type,
+ _)</c> and <c>erlang:system_flag(cpu_topology, _)</c>
+ have been deprecated and scheduled for removal in
+ erts-5.10/OTP-R16. For more information see the
+ documentation of <c>erlang:system_flag/2</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9749</p>
+ </item>
+ <item>
+ <p>
+ An ancient workaround for a Windows bug was removed from
+ the open_port code, open_port({spawn,...}...) is now
+ faster. Thanks to Daniel Goertzen.</p>
+ <p>
+ Own Id: OTP-9766</p>
+ </item>
+ <item>
+ <p>
+ The use of deprecated 32bit time_t on 32bit Windows is
+ removed.</p>
+ <p>
+ Own Id: OTP-9767</p>
+ </item>
+ <item>
+ <p>
+ The NIF <c>reload</c> mechanism is deprecated. Do not use
+ it as an upgrade method for live production systems. It
+ might be removed in future releases. It can still serve
+ as a development feature but a warning message will be
+ logged each time it is used.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9771</p>
+ </item>
+ <item>
+ <p>The driver interface has been changed to enable 64-bit
+ aware drivers. Most importantly the return types for
+ ErlDrvEntry callbacks 'call' and 'control' has ben
+ enlarged which require drivers to be changed or they will
+ cause emulator crashes. See <seealso
+ marker="erl_driver#rewrites_for_64_bits"> Rewrites for
+ 64-bit driver interface </seealso> in the driver manual.
+ </p>
+ <p>Due to this driver <seealso
+ marker="erl_driver#version_management">version
+ management</seealso> is now mandatory. A driver that is
+ not written with version management or a driver that was
+ compiled with the wrong major version will be not be
+ loaded by the emulator.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9795</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 5.8.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 6cd9be5680..985ef72517 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2011. All Rights Reserved.
+# Copyright Ericsson AB 1996-2012. All Rights Reserved.
#
# The 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,26 +23,34 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@
HIPE_ENABLED=@HIPE_ENABLED@
+DTRACE_ENABLED=@DTRACE_ENABLED@
+DTRACE_ENABLED_2STEP=@DTRACE_ENABLED_2STEP@
+USE_VM_PROBES=@USE_VM_PROBES@
LIBS = @LIBS@
Z_LIB=@Z_LIB@
NO_INLINE_FUNCTIONS=false
OPCODE_TABLES = $(ERL_TOP)/lib/compiler/src/genop.tab beam/ops.tab
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+CONFIGURE_CFLAGS = @CFLAGS@
+
#
# Run this make file with TYPE set to the type of emulator you want.
# Different versions of the emulator for different uses. The default
# is "debug". For a normal version use "opt".
#
+DEFS=@DEFS@
THR_DEFS=@EMU_THR_DEFS@
M4FLAGS=
CREATE_DIRS=
LDFLAGS=@LDFLAGS@
+ARFLAGS=rc
ifeq ($(TYPE),debug)
PURIFY =
TYPEMARKER = .debug
-TYPE_FLAGS = @DEBUG_CFLAGS@ -DDEBUG
+TYPE_FLAGS = $(DEBUG_CFLAGS) -DDEBUG
ENABLE_ALLOC_TYPE_VARS += debug
ifeq ($(TARGET),win32)
TYPE_FLAGS += -DNO_JUMP_TABLE
@@ -53,7 +61,7 @@ else
ifeq ($(TYPE),purify)
PURIFY = purify $(PURIFY_BUILD_OPTIONS)
TYPEMARKER = .purify
-TYPE_FLAGS = @DEBUG_CFLAGS@ -DPURIFY -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS
+TYPE_FLAGS = $(DEBUG_CFLAGS) -DPURIFY -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS
ENABLE_ALLOC_TYPE_VARS += purify
else
@@ -67,14 +75,14 @@ else
ifeq ($(TYPE),purecov)
PURIFY = purecov --follow-child-processes=yes $(PURECOV_BUILD_OPTIONS)
TYPEMARKER = .purecov
-TYPE_FLAGS = @DEBUG_CFLAGS@ -DPURECOV -DNO_JUMP_TABLE
+TYPE_FLAGS = $(DEBUG_CFLAGS) -DPURECOV -DNO_JUMP_TABLE
ENABLE_ALLOC_TYPE_VARS += purecov
else
ifeq ($(TYPE),gcov)
PURIFY =
TYPEMARKER = .gcov
-TYPE_FLAGS = @DEBUG_CFLAGS@ -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE=
+TYPE_FLAGS = $(DEBUG_CFLAGS) -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE=
ifneq ($(findstring solaris,$(TARGET)),solaris)
LIBS += -lgcov
endif
@@ -84,7 +92,7 @@ else
ifeq ($(TYPE),valgrind)
PURIFY =
TYPEMARKER = .valgrind
-TYPE_FLAGS = @DEBUG_CFLAGS@ -DVALGRIND -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS
+TYPE_FLAGS = $(DEBUG_CFLAGS) -DVALGRIND -DNO_JUMP_TABLE -DERTS_MSEG_FAKE_SEGMENTS
ENABLE_ALLOC_TYPE_VARS += valgrind
else
@@ -128,13 +136,6 @@ ENABLE_ALLOC_TYPE_VARS += smp nofrag
M4FLAGS += -DERTS_SMP=1
else
-ifeq ($(FLAVOR),hybrid)
-FLAVOR_MARKER=.hybrid
-FLAVOR_FLAGS=-DHYBRID
-ENABLE_ALLOC_TYPE_VARS += hybrid
-else
-
-
# If flavor isn't one of the above, it *is* plain flavor...
override FLAVOR=plain
FLAVOR_MARKER=
@@ -143,10 +144,18 @@ ENABLE_ALLOC_TYPE_VARS += nofrag
M4FLAGS +=
endif
-endif
TF_MARKER=$(TYPEMARKER)$(FLAVOR_MARKER)
+ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no)
+VOID_EMULATOR = '*** SMP emulator disabled by configure'
+else
+ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no)
+VOID_EMULATOR = '*** valgrind emulator disabled by configure'
+else
+VOID_EMULATOR =
+endif
+endif
OPSYS=@OPSYS@
sol2CFLAGS=
@@ -187,7 +196,7 @@ else
EMU_CC = @EMU_CC@
endif
WFLAGS = @WFLAGS@
-CFLAGS = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) @DEFS@ $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS)
+CFLAGS = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) $(DEFS) $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS)
HCC = @HCC@
LD = @LD@
DEXPORT = @DEXPORT@
@@ -198,6 +207,7 @@ RM = @RM@
MKDIR = @MKDIR@
USING_MINGW=@MIXED_CYGWIN_MINGW@
+MIXED_MSYS=@MIXED_MSYS@
ifeq ($(TARGET),win32)
LIB_PREFIX=
@@ -237,9 +247,12 @@ ifeq ($(TARGET), win32)
GEN_OPT_FLGS = $(OPT_LEVEL)
UNROLL_FLG =
RC=rc.sh
+ifeq ($(MIXED_MSYS), yes)
+MAKE_PRELOAD_EXTRA = -msys
+endif
ifeq ($(USING_MINGW), yes)
-RES_EXT=@OBJEXT@
-MAKE_PRELOAD_EXTRA=-windres
+RES_EXT = @OBJEXT@
+MAKE_PRELOAD_EXTRA += " -windres"
else
RES_EXT=res
endif
@@ -259,30 +272,29 @@ CS_PURIFY =
CS_TYPE_FLAGS = $(subst QUANTIFY,FAKE_QUANTIFY, \
$(subst PURIFY,FAKE_PURIFY, $(TYPE_FLAGS)))
endif
-CS_CFLAGS_ = $(CS_TYPE_FLAGS) @DEFS@ $(WFLAGS)
+CS_CFLAGS_ = $(CS_TYPE_FLAGS) $(DEFS) $(WFLAGS)
ifeq ($(GCC),yes)
CS_CFLAGS = $(subst -O2, $(GEN_OPT_FLGS) $(UNROLL_FLG), $(CS_CFLAGS_))
else
CS_CFLAGS = $(CS_CFLAGS_)
endif
CS_LDFLAGS = $(LDFLAGS)
-CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal @ERTS_INTERNAL_X_LIBS@
+CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal$(TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
LIBS += @TERMCAP_LIB@ -L../lib/internal/$(TARGET) @ERTS_INTERNAL_X_LIBS@
ifdef Z_LIB
# Use shared zlib library
LIBS += $(Z_LIB)
+DEPLIBS =
else
+DEPLIBS=$(ZLIB_LIBRARY)
ifeq ($(TARGET),win32)
-LIBS += -L$(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE) -lz
-DEPLIBS = $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)/z.lib
+LIBS += -L$(ZLIB_OBJDIR) -lz
else
# Build on darwin fails if -lz is used
-LIBS += $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)/libz.a
-DEPLIBS = $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)/libz.a
+LIBS += $(ZLIB_LIBRARY)
endif
-
endif
ifeq ($(TARGET),win32)
@@ -309,12 +321,9 @@ LIBSCTP = @LIBSCTP@
ORG_THR_LIBS=@EMU_THR_LIBS@
THR_LIB_NAME=@EMU_THR_LIB_NAME@
-ifneq ($(strip $(THR_LIB_NAME)),)
-DEPLIBS += $(ERL_TOP)/erts/lib/internal/$(TARGET)/$(LIB_PREFIX)erts_internal_r$(TYPEMARKER)$(LIB_SUFFIX) \
- $(ERL_TOP)/erts/lib/internal/$(TARGET)/$(LIB_PREFIX)ethread$(TYPEMARKER)$(LIB_SUFFIX)
-else
-DEPLIBS += $(ERL_TOP)/erts/lib/internal/$(TARGET)/$(LIB_PREFIX)erts_internal$(TYPEMARKER)$(LIB_SUFFIX)
-endif
+ERTS_LIB_DIR = $(ERL_TOP)/erts/lib_src
+ERTS_LIB = $(ERTS_LIB_DIR)/obj/$(TARGET)/$(TYPE)/MADE
+DEPLIBS += $(ERTS_LIB)
THR_LIBS=$(subst -l$(THR_LIB_NAME),-l$(THR_LIB_NAME)$(TYPEMARKER), \
$(subst -lerts_internal_r,-lerts_internal_r$(TYPEMARKER),$(ORG_THR_LIBS)))
@@ -350,8 +359,7 @@ OBJDIR = obj/$(TTF_DIR)
CREATE_DIRS += $(OBJDIR) \
pcre/obj/$(TARGET)/$(TYPE) \
- zlib/obj/$(TARGET)/$(TYPE)
-
+ $(ZLIB_OBJDIR)
BINDIR = $(ERL_TOP)/bin/$(TARGET)
@@ -359,7 +367,6 @@ ERLANG_OSTYPE = @ERLANG_OSTYPE@
ENABLE_ALLOC_TYPE_VARS += @ERLANG_OSTYPE@
-EMULATOR_EXECUTABLE_ELIB = beam.elib$(TF_MARKER)
ifeq ($(TARGET), win32)
EMULATOR_EXECUTABLE = beam$(TF_MARKER).dll
else
@@ -375,15 +382,12 @@ else
UNIX_ONLY_BUILDS =
endif
-ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no)
+.PHONY: all
+ifdef VOID_EMULATOR
all:
- @echo '*** valgrind not found by configure'
+ @echo $(VOID_EMULATOR)' - omitted target all'
else
-ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no)
-all:
- @echo '*** Omitted build of emulator with smp support'
-else
-all: generate erts_lib zlib $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS)
+all: $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS)
ifeq ($(OMIT_OMIT_FP),yes)
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@@ -394,37 +398,25 @@ ifeq ($(OMIT_OMIT_FP),yes)
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
endif
endif
-endif
-
-ifdef Z_LIB
-zlib:
- @echo 'Skip zlib directory, use shared library'
-else
-zlib:
- @set -e ; cd zlib && $(MAKE) TYPE=$(TYPE) $(TYPE)
-endif
-
+include zlib/zlib.mk
include pcre/pcre.mk
-erts_lib:
- cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
+$(ERTS_LIB):
+ cd $(ERTS_LIB_DIR) && $(MAKE) $(TYPE)
+.PHONY: clean
clean:
-ifeq ($(TARGET),win32)
- $(RM) -f $(TARGET)/beams.rc
-endif
- $(RM) -f $(TARGET)/*.c $(TARGET)/*.h $(TARGET)/depend.mk
- $(RM) -f $(TARGET)/*/*/*.c $(TARGET)/*/*/*.h $(TARGET)/*/*/*.S
- $(RM) -f $(ERL_TOP)/erts/emulator/obj/$(TARGET)/*/*/*.o
- $(RM) -f $(BINDIR)/beam $(BINDIR)/beam.*
- $(RM) -rf $(BINDIR)/child_setup $(BINDIR)/child_setup.*
- $(RM) -f $(BINDIR)/hipe_mkliterals $(BINDIR)/hipe_mkliterals.*
- @set -e ; cd zlib && $(MAKE) clean
- rm -f $(OBJS) $(OBJDIR)/libepcre.a
-
-.PHONY: all zlib clean
-
+ $(RM) -f $(GENERATE)
+ $(RM) -rf $(TARGET)/*.c $(TARGET)/*.h $(TARGET)/*-GENERATED
+ $(RM) -rf $(TARGET)/*/*
+ $(RM) -rf obj/$(TARGET)
+ $(RM) -rf pcre/obj/$(TARGET) $(PCRE_GENINC)
+ $(RM) -rf zlib/obj/$(TARGET)
+ $(RM) -rf bin/$(TARGET)
+ cd $(ERTS_LIB_DIR) && $(MAKE) clean
+
+.PHONY: docs
docs:
# ----------------------------------------------------------------------
@@ -437,31 +429,29 @@ ifeq ($(TARGET),win32)
RELEASE_INCLUDES += sys/$(ERLANG_OSTYPE)/erl_win_dyn_driver.h
endif
-ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no)
-release_spec:
- @echo '*** valgrind not found by configure'
-else
-ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no)
+
+.PHONY: release_spec
+ifdef VOID_EMULATOR
release_spec:
- @echo '*** No emulator with smp support to install'
+ @echo $(VOID_EMULATOR)' - omitted target release_spec (install)'
else
release_spec: all
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/man
- $(INSTALL_DIR) $(RELSYSDIR)/doc
- $(INSTALL_DIR) $(RELSYSDIR)/bin
- $(INSTALL_DIR) $(RELEASE_PATH)/usr/include
- $(INSTALL_DATA) $(RELEASE_INCLUDES) $(RELEASE_PATH)/usr/include
- $(INSTALL_DATA) $(RELEASE_INCLUDES) $(RELSYSDIR)/include
- $(INSTALL_PROGRAM) $(BINDIR)/$(EMULATOR_EXECUTABLE) $(RELSYSDIR)/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/man"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc"
+ $(INSTALL_DIR) "$(RELSYSDIR)/bin"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/usr/include"
+ $(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELEASE_PATH)/usr/include"
+ $(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELSYSDIR)/include"
+ $(INSTALL_PROGRAM) $(BINDIR)/$(EMULATOR_EXECUTABLE) "$(RELSYSDIR)/bin"
ifeq ($(ERLANG_OSTYPE), unix)
- $(INSTALL_PROGRAM) $(BINDIR)/$(CS_EXECUTABLE) $(RELSYSDIR)/bin
-endif
+ $(INSTALL_PROGRAM) $(BINDIR)/$(CS_EXECUTABLE) "$(RELSYSDIR)/bin"
endif
endif
+.PHONY: release_docs_spec
release_docs_spec:
# ----------------------------------------------------------------------
@@ -470,48 +460,50 @@ release_docs_spec:
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
-.PHONY : generate
-
-GENERATE= $(TTF_DIR)/beam_opcodes.h \
- $(TARGET)/erl_bif_table.c \
- $(TARGET)/erl_version.h \
- $(TTF_DIR)/driver_tab.c \
- $(TTF_DIR)/erl_alloc_types.h
-
-ifeq ($(TARGET),win32)
-GENERATE += $(TARGET)/beams.rc
-else
-GENERATE += $(TARGET)/preload.c
-endif
+GENERATE =
+HIPE_ASM =
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
else
ifdef HIPE_ENABLED
-GENERATE += $(TTF_DIR)/hipe_x86_asm.h \
+HIPE_ASM += $(TTF_DIR)/hipe_x86_asm.h \
$(TTF_DIR)/hipe_amd64_asm.h \
$(TTF_DIR)/hipe_sparc_asm.h \
$(TTF_DIR)/hipe_ppc_asm.h \
- $(TTF_DIR)/hipe_arm_asm.h \
+ $(TTF_DIR)/hipe_arm_asm.h
+
+GENERATE += $(HIPE_ASM) \
$(TTF_DIR)/hipe_literals.h \
$(BINDIR)/hipe_mkliterals$(TF_MARKER)
endif
endif
-ifeq ($(FLAVOR)-@ERTS_BUILD_SMP_EMU@,smp-no)
-GENERATE=
-endif
-
+ifdef DTRACE_ENABLED
+# global.h causes problems by including dtrace-wrapper.h which includes
+# the autogenerated erlang_dtrace.h ... so make erlang_dtrace.h very early.
+generate: $(TARGET)/erlang_dtrace.h $(GENERATE)
+else
generate: $(GENERATE)
+endif
ifdef HIPE_ENABLED
OPCODE_TABLES += hipe/hipe_ops.tab
endif
-$(TTF_DIR)/beam_opcodes.h $(TTF_DIR)/beam_opcodes.c: $(OPCODE_TABLES) utils/beam_makeops
+$(TTF_DIR)/beam_cold.h \
+$(TTF_DIR)/beam_hot.h \
+$(TTF_DIR)/beam_opcodes.c \
+$(TTF_DIR)/beam_opcodes.h \
+$(TTF_DIR)/beam_pred_funcs.h \
+$(TTF_DIR)/beam_tr_funcs.h \
+ : $(TTF_DIR)/OPCODES-GENERATED
+$(TTF_DIR)/OPCODES-GENERATED: $(OPCODE_TABLES) utils/beam_makeops
LANG=C $(PERL) utils/beam_makeops \
-wordsize @EXTERNAL_WORD_SIZE@ \
-outdir $(TTF_DIR) \
- -emulator $(OPCODE_TABLES)
+ -DUSE_VM_PROBES=$(if $(USE_VM_PROBES),1,0) \
+ -emulator $(OPCODE_TABLES) && echo $? >$(TTF_DIR)/OPCODES-GENERATED
+GENERATE += $(TTF_DIR)/OPCODES-GENERATED
# bif and atom table
ATOMS= beam/atom.names
@@ -531,32 +523,44 @@ BIFS += hipe/hipe_perfctr.tab
endif
endif
-TABLES= $(TARGET)/erl_bif_table.c $(TARGET)/erl_bif_table.h \
- $(TARGET)/erl_bif_wrap.c $(TARGET)/erl_bif_list.h \
- $(TARGET)/erl_atom_table.c $(TARGET)/erl_atom_table.h \
- $(TARGET)/erl_pbifs.c
-
-$(TABLES): $(ATOMS) $(BIFS) utils/make_tables
+$(TARGET)/erl_bif_table.c \
+$(TARGET)/erl_bif_table.h \
+$(TARGET)/erl_bif_wrap.c \
+$(TARGET)/erl_bif_list.h \
+$(TARGET)/erl_atom_table.c \
+$(TARGET)/erl_atom_table.h \
+$(TARGET)/erl_pbifs.c \
+ : $(TARGET)/TABLES-GENERATED
+$(TARGET)/TABLES-GENERATED: $(ATOMS) $(BIFS) utils/make_tables
LANG=C $(PERL) utils/make_tables -src $(TARGET) -include $(TARGET)\
- $(ATOMS) $(BIFS)
+ $(ATOMS) $(BIFS) && echo $? >$(TARGET)/TABLES-GENERATED
+GENERATE += $(TARGET)/TABLES-GENERATED
$(TTF_DIR)/erl_alloc_types.h: beam/erl_alloc.types utils/make_alloc_types
LANG=C $(PERL) utils/make_alloc_types -src $< -dst $@ $(ENABLE_ALLOC_TYPE_VARS)
+GENERATE += $(TTF_DIR)/erl_alloc_types.h
# version include file
$(TARGET)/erl_version.h: ../vsn.mk
LANG=C $(PERL) utils/make_version -o $@ $(SYSTEM_VSN) $(VSN)$(SERIALNO) $(TARGET)
+GENERATE += $(TARGET)/erl_version.h
# driver table
$(TTF_DIR)/driver_tab.c: Makefile.in
LANG=C $(PERL) utils/make_driver_tab -o $@ $(DRV_OBJS)
+GENERATE += $(TTF_DIR)/driver_tab.c
+
+
# Preloaded code.
#
# This list must be consistent with PRE_LOADED_MODULES in
# lib/kernel/src/Makefile.
ifeq ($(TARGET),win32)
-$(TARGET)/beams.rc: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
+# On windows the preloaded objects are in a resource object.
+PRELOAD_OBJ = $(OBJDIR)/beams.$(RES_EXT)
+PRELOAD_SRC = $(TARGET)/beams.rc
+$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \
@@ -566,7 +570,9 @@ $(TARGET)/beams.rc: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
$(ERL_TOP)/erts/preloaded/ebin/erlang.beam
LANG=C $(PERL) utils/make_preload $(MAKE_PRELOAD_EXTRA) -rc $^ > $@
else
-$(TARGET)/preload.c: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
+PRELOAD_OBJ = $(OBJDIR)/preload.o
+PRELOAD_SRC = $(TARGET)/preload.c
+$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \
@@ -577,6 +583,22 @@ $(TARGET)/preload.c: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
LANG=C $(PERL) utils/make_preload -old $^ > $@
endif
+.PHONY : generate
+ifdef VOID_EMULATOR
+generate:
+ @echo $(VOID_EMULATOR)' - omitted target generate'
+else
+generate: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+
+$(TTF_DIR)/GENERATED: $(GENERATE)
+ echo $? >$(TTF_DIR)/GENERATED
+endif
+
+$(TARGET)/erlang_dtrace.h: beam/erlang_dtrace.d
+ dtrace -h -C -Ibeam -s $< -o ./erlang_dtrace.tmp
+ sed -e '/^#define[ ]*ERLANG_[A-Z0-9_]*(.*)/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' ./erlang_dtrace.tmp > $@
+ rm ./erlang_dtrace.tmp
+
# ----------------------------------------------------------------------
# Pattern rules
#
@@ -620,7 +642,6 @@ $(OBJDIR)/beam_emu.o: beam/beam_emu.c
$(EMU_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
endif
-
$(OBJDIR)/%.o: beam/%.c
$(CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
@@ -653,7 +674,7 @@ endif
#
CS_SRC = sys/$(ERLANG_OSTYPE)/erl_child_setup.c
-$(BINDIR)/$(CS_EXECUTABLE): $(CS_SRC)
+$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(CS_SRC) $(ERTS_LIB)
$(CS_PURIFY) $(CC) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \
$(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_SRC) $(CS_LIBS)
@@ -682,16 +703,7 @@ $(ERL_TOP)/lib/%.beam:
# Object files
#
-# On windows the preloaded objects are in a resource object.
-
-ifeq ($(TARGET),win32)
-PRELOAD = $(OBJDIR)/beams.$(RES_EXT)
-else
-PRELOAD = $(OBJDIR)/preload.o
-endif
-
-
-INIT_OBJS = $(OBJDIR)/erl_main.o $(PRELOAD)
+INIT_OBJS = $(OBJDIR)/erl_main.o $(PRELOAD_OBJ)
EMU_OBJS = \
$(OBJDIR)/beam_emu.o $(OBJDIR)/beam_opcodes.o \
@@ -721,14 +733,14 @@ RUN_OBJS = \
$(OBJDIR)/external.o $(OBJDIR)/dist.o \
$(OBJDIR)/binary.o $(OBJDIR)/erl_db.o \
$(OBJDIR)/erl_db_util.o $(OBJDIR)/erl_db_hash.o \
- $(OBJDIR)/erl_db_tree.o $(OBJDIR)/fix_alloc.o \
+ $(OBJDIR)/erl_db_tree.o $(OBJDIR)/erl_thr_progress.o \
$(OBJDIR)/big.o $(OBJDIR)/hash.o \
$(OBJDIR)/index.o $(OBJDIR)/atom.o \
$(OBJDIR)/module.o $(OBJDIR)/export.o \
$(OBJDIR)/register.o $(OBJDIR)/break.o \
$(OBJDIR)/erl_async.o $(OBJDIR)/erl_lock_check.o \
$(OBJDIR)/erl_gc.o $(OBJDIR)/erl_lock_count.o \
- $(OBJDIR)/erl_nmgc.o $(OBJDIR)/erl_posix_str.o \
+ $(OBJDIR)/erl_posix_str.o \
$(OBJDIR)/erl_bits.o $(OBJDIR)/erl_math.o \
$(OBJDIR)/erl_fun.o $(OBJDIR)/erl_bif_port.o \
$(OBJDIR)/erl_term.o $(OBJDIR)/erl_node_tables.o \
@@ -738,7 +750,8 @@ RUN_OBJS = \
$(OBJDIR)/erl_bif_re.o $(OBJDIR)/erl_unicode.o \
$(OBJDIR)/packet_parser.o $(OBJDIR)/safe_hash.o \
$(OBJDIR)/erl_zlib.o $(OBJDIR)/erl_nif.o \
- $(OBJDIR)/erl_bif_binary.o $(OBJDIR)/erl_ao_firstfit_alloc.o
+ $(OBJDIR)/erl_bif_binary.o $(OBJDIR)/erl_ao_firstfit_alloc.o \
+ $(OBJDIR)/erl_thr_queue.o $(OBJDIR)/erl_sched_spec_pre_alloc.o
ifeq ($(TARGET),win32)
DRV_OBJS = \
@@ -828,7 +841,21 @@ endif
BASE_OBJS = $(RUN_OBJS) $(EMU_OBJS) $(OS_OBJS) $(EXTRA_BASE_OBJS)
-OBJS = $(BASE_OBJS) $(DRV_OBJS)
+before_DTrace_OBJS = $(BASE_OBJS) $(DRV_OBJS)
+
+DTRACE_OBJS =
+ifdef DTRACE_ENABLED_2STEP
+DTRACE_OBJS = $(OBJDIR)/erlang_dtrace.o
+$(OBJDIR)/erlang_dtrace.o: $(before_DTrace_OBJS) $(TARGET)/erlang_dtrace.h
+ dtrace -G -C -Ibeam \
+ -s beam/erlang_dtrace.d \
+ -o $@ $(before_DTrace_OBJS)
+endif
+
+OBJS = $(before_DTrace_OBJS) $(DTRACE_OBJS)
+
+$(INIT_OBJS): $(TTF_DIR)/GENERATED
+$(OBJS): $(TTF_DIR)/GENERATED
########################################
# HiPE section
@@ -853,30 +880,54 @@ $(OBJDIR)/%.o: hipe/%.c
$(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
-$(OBJDIR)/hipe_mkliterals.o: $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_ppc_asm.h $(TTF_DIR)/beam_opcodes.h
+$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h \
+ $(TTF_DIR)/OPCODES-GENERATED $(TARGET)/TABLES-GENERATED
$(TTF_DIR)/hipe_literals.h: $(BINDIR)/hipe_mkliterals$(TF_MARKER)
$(BINDIR)/hipe_mkliterals$(TF_MARKER) -c > $@
-$(OBJDIR)/hipe_x86_glue.o: hipe/hipe_x86_glue.S $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_literals.h hipe/hipe_mode_switch.h
-$(TTF_DIR)/hipe_x86_bifs.S: hipe/hipe_x86_bifs.m4 hipe/hipe_x86_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
-$(OBJDIR)/hipe_x86_bifs.o: $(TTF_DIR)/hipe_x86_bifs.S $(TTF_DIR)/hipe_literals.h
-
-$(OBJDIR)/hipe_amd64_glue.o: hipe/hipe_amd64_glue.S $(TTF_DIR)/hipe_amd64_asm.h $(TTF_DIR)/hipe_literals.h hipe/hipe_mode_switch.h
-$(TTF_DIR)/hipe_amd64_bifs.S: hipe/hipe_amd64_bifs.m4 hipe/hipe_amd64_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
-$(OBJDIR)/hipe_amd64_bifs.o: $(TTF_DIR)/hipe_amd64_bifs.S $(TTF_DIR)/hipe_literals.h
-
-$(OBJDIR)/hipe_sparc_glue.o: hipe/hipe_sparc_glue.S $(TTF_DIR)/hipe_sparc_asm.h hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h
-$(TTF_DIR)/hipe_sparc_bifs.S: hipe/hipe_sparc_bifs.m4 hipe/hipe_sparc_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
-$(OBJDIR)/hipe_sparc_bifs.o: $(TTF_DIR)/hipe_sparc_bifs.S $(TTF_DIR)/hipe_literals.h
-
-$(OBJDIR)/hipe_ppc_glue.o: hipe/hipe_ppc_glue.S $(TTF_DIR)/hipe_ppc_asm.h hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h
-$(TTF_DIR)/hipe_ppc_bifs.S: hipe/hipe_ppc_bifs.m4 hipe/hipe_ppc_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
-$(OBJDIR)/hipe_ppc_bifs.o: $(TTF_DIR)/hipe_ppc_bifs.S $(TTF_DIR)/hipe_literals.h
-
-$(OBJDIR)/hipe_arm_glue.o: hipe/hipe_arm_glue.S $(TTF_DIR)/hipe_arm_asm.h hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h
-$(TTF_DIR)/hipe_arm_bifs.S: hipe/hipe_arm_bifs.m4 hipe/hipe_arm_asm.m4 hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
-$(OBJDIR)/hipe_arm_bifs.o: $(TTF_DIR)/hipe_arm_bifs.S $(TTF_DIR)/hipe_literals.h
+$(OBJDIR)/hipe_x86_glue.o: hipe/hipe_x86_glue.S \
+ $(TTF_DIR)/hipe_x86_asm.h $(TTF_DIR)/hipe_literals.h \
+ hipe/hipe_mode_switch.h
+$(TTF_DIR)/hipe_x86_bifs.S: hipe/hipe_x86_bifs.m4 hipe/hipe_x86_asm.m4 \
+ hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
+$(OBJDIR)/hipe_x86_bifs.o: $(TTF_DIR)/hipe_x86_bifs.S \
+ $(TTF_DIR)/hipe_literals.h
+
+$(OBJDIR)/hipe_amd64_glue.o: hipe/hipe_amd64_glue.S \
+ $(TTF_DIR)/hipe_amd64_asm.h $(TTF_DIR)/hipe_literals.h \
+ hipe/hipe_mode_switch.h
+$(TTF_DIR)/hipe_amd64_bifs.S: hipe/hipe_amd64_bifs.m4 hipe/hipe_amd64_asm.m4 \
+ hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
+$(OBJDIR)/hipe_amd64_bifs.o: $(TTF_DIR)/hipe_amd64_bifs.S \
+ $(TTF_DIR)/hipe_literals.h
+
+$(OBJDIR)/hipe_sparc_glue.o: hipe/hipe_sparc_glue.S \
+ $(TTF_DIR)/hipe_sparc_asm.h hipe/hipe_mode_switch.h \
+ $(TTF_DIR)/hipe_literals.h
+$(TTF_DIR)/hipe_sparc_bifs.S: hipe/hipe_sparc_bifs.m4 hipe/hipe_sparc_asm.m4 \
+ hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
+$(OBJDIR)/hipe_sparc_bifs.o: $(TTF_DIR)/hipe_sparc_bifs.S \
+ $(TTF_DIR)/hipe_literals.h
+
+$(OBJDIR)/hipe_ppc_glue.o: hipe/hipe_ppc_glue.S $(TTF_DIR)/hipe_ppc_asm.h \
+ hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h
+$(TTF_DIR)/hipe_ppc_bifs.S: hipe/hipe_ppc_bifs.m4 hipe/hipe_ppc_asm.m4 \
+ hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
+$(OBJDIR)/hipe_ppc_bifs.o: $(TTF_DIR)/hipe_ppc_bifs.S \
+ $(TTF_DIR)/hipe_literals.h
+
+$(OBJDIR)/hipe_arm_glue.o: hipe/hipe_arm_glue.S $(TTF_DIR)/hipe_arm_asm.h \
+ hipe/hipe_mode_switch.h $(TTF_DIR)/hipe_literals.h
+$(TTF_DIR)/hipe_arm_bifs.S: hipe/hipe_arm_bifs.m4 hipe/hipe_arm_asm.m4 \
+ hipe/hipe_bif_list.m4 $(TARGET)/erl_bif_list.h hipe/hipe_gbif_list.h
+$(OBJDIR)/hipe_arm_bifs.o: $(TTF_DIR)/hipe_arm_bifs.S \
+ $(TTF_DIR)/hipe_literals.h
+
+# Use -fomit-frame-pointer to work around gcc (v4.5.2) bug causing
+# "error: r7 cannot be used in asm here" for DEBUG build.
+$(OBJDIR)/hipe_arm.o: hipe/hipe_arm.c
+ $(CC) $(subst O2,O3, $(CFLAGS)) -fomit-frame-pointer $(INCLUDES) -c $< -o $@
# end of HiPE section
########################################
@@ -923,13 +974,6 @@ $(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
endif
-#
-# Create directories
-#
-
-$(CREATE_DIRS):
- $(MKDIR) -p $@
-
# ----------------------------------------------------------------------
# Dependencies
#
@@ -941,7 +985,7 @@ $(TARGET)/Makefile: Makefile.in
#SED_REPL_WIN_DRIVE=s|\([ ]\)\([A-Za-z]\):|\1/cygdrive/\2|g;s|^\([A-Za-z]\):|/cygdrive/\1|g
SED_REPL_O=s|^\([^:]*:\)|$$(OBJDIR)/\1|g
-SED_REPL_ELIB_O=s|^\([^:]*\).o[ ]*:|$$(OBJDIR)/\1.elib.o:|g
+SED_REPL_O_ZLIB=s|^\([^:]*:\)|$$(ZLIB_OBJDIR)/\1|g
SED_REPL_TTF_DIR=s|$(TTF_DIR)/|$$(TTF_DIR)/|g
SED_REPL_ERL_TOP=s|\([ ]\)$(ERL_TOP)/|\1$$(ERL_TOP)/|g;s|^$(ERL_TOP)/|$$(ERL_TOP)/|g
SED_REPL_POLL=s|$$(OBJDIR)/erl_poll.o|$$(OBJDIR)/erl_poll.kp.o $$(OBJDIR)/erl_poll.nkp.o|g
@@ -961,7 +1005,7 @@ SED_SUFFIX=
endif
SED_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_O);$(SED_REPL_TTF_DIR);$(SED_REPL_ERL_TOP)$(SED_SUFFIX)'
-SED_ELIB_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_ELIB_O);$(SED_REPL_TTF_DIR);$(SED_REPL_ERL_TOP)$(SED_SUFFIX)'
+SED_DEPEND_ZLIB=sed '$(SED_PREFIX)$(SED_REPL_O_ZLIB)'
ifdef HIPE_ENABLED
HIPE_SRC=$(wildcard hipe/*.c)
@@ -970,7 +1014,8 @@ HIPE_SRC=
endif
BEAM_SRC=$(wildcard beam/*.c)
-DRV_SRC=$(wildcard drivers/common/*.c) $(wildcard drivers/$(ERLANG_OSTYPE)/*.c)
+DRV_COMMON_SRC=$(wildcard drivers/common/*.c)
+DRV_OSTYPE_SRC=$(wildcard drivers/$(ERLANG_OSTYPE)/*.c)
ALL_SYS_SRC=$(wildcard sys/$(ERLANG_OSTYPE)/*.c) $(wildcard sys/common/*.c)
TARGET_SRC=$(wildcard $(TARGET)/*.c) $(wildcard $(TTF_DIR)/*.c)
@@ -981,7 +1026,7 @@ ifeq ($(TARGET),win32)
#DEP_CC=$(EMU_CC)
DEP_CC=$(CC)
-DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 -Idrivers/common
+DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 -Idrivers/common -Idrivers/$(ERLANG_OSTYPE)
# ifeq (@MIXED_CYGWIN_VC@,yes)
# VC++ used for compiling. If __GNUC__ is defined we will include
# other headers then when compiling which will result in faulty
@@ -1001,28 +1046,40 @@ MG_FLAG=-MG
endif
DEP_CC=$(CC)
-DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common
+DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLANG_OSTYPE)
SYS_SRC=$(ALL_SYS_SRC)
endif
+.PHONY: depend
+ifdef VOID_EMULATOR
depend:
+ @echo $(VOID_EMULATOR)' - omitted target depend'
+else
+depend: $(TTF_DIR)/depend.mk
+$(TTF_DIR)/depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
$(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \
- | $(SED_DEPEND) > $(TARGET)/depend.mk
- $(DEP_CC) $(DEP_FLAGS) $(DRV_SRC) \
- | $(SED_DEPEND) >> $(TARGET)/depend.mk
+ | $(SED_DEPEND) > $(TTF_DIR)/depend.mk
+ $(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \
+ | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ $(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) \
+ | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
$(DEP_CC) $(DEP_FLAGS) $(SYS_SRC) \
- | $(SED_DEPEND) >> $(TARGET)/depend.mk
+ | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
$(DEP_CC) $(DEP_FLAGS) $(TARGET_SRC) \
- | $(SED_DEPEND) >> $(TARGET)/depend.mk
-ifneq ($(TARGET),win32)
- $(DEP_CC) $(DEP_FLAGS) $(ELIB_C_FILES) \
- | $(SED_ELIB_DEPEND) >> $(TARGET)/depend.mk
-endif
+ | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ $(DEP_CC) $(DEP_FLAGS) $(ZLIB_SRC) \
+ | $(SED_DEPEND_ZLIB) >> $(TTF_DIR)/depend.mk
ifdef HIPE_ENABLED
$(DEP_CC) $(DEP_FLAGS) $(HIPE_SRC) \
- | $(SED_DEPEND) >> $(TARGET)/depend.mk
+ | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+endif
+ cd $(ERTS_LIB_DIR) && $(MAKE) depend
endif
--include $(TARGET)/depend.mk
-
-
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),generate)
+ifndef VOID_EMULATOR
+-include $(TTF_DIR)/depend.mk
+endif
+endif
+endif
diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h
index cb245a87b1..fd9c04d3d0 100644
--- a/erts/emulator/beam/atom.h
+++ b/erts/emulator/beam/atom.h
@@ -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
@@ -34,7 +34,7 @@
/* Internal atom cache needs MAX_ATOM_TABLE_SIZE to be less than an
unsigned 32 bit integer. See external.c(erts_encode_ext_dist_header_setup)
for more details. */
-#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (1UL << 32)) ? MAX_ATOM_INDEX + 1 : (1UL << 32))
+#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (UWORD_CONSTANT(1) << 32)) ? MAX_ATOM_INDEX + 1 : (UWORD_CONSTANT(1) << 32))
#else
#define MAX_ATOM_TABLE_SIZE (MAX_ATOM_INDEX + 1)
#endif
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index e7308dbf43..106fad030b 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2011. All Rights Reserved.
+# Copyright Ericsson AB 1996-2012. All Rights Reserved.
#
# The 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,8 @@ atom ac
atom active
atom all
atom all_but_first
+atom alloc_info
+atom alloc_sizes
atom allocated
atom allocated_areas
atom allocator
@@ -93,6 +95,7 @@ atom atom
atom atom_used
atom attributes
atom await_proc_exit
+atom await_sched_wall_time_modifications
atom awaiting_load
atom awaiting_unload
atom backtrace backtrace_depth
@@ -237,13 +240,14 @@ atom generational
atom get_seq_token
atom get_tcw
atom getenv
+atom gather_sched_wall_time_result
atom getting_linked
atom getting_unlinked
atom global
-atom global_heaps_size
atom Gt='>'
atom grun
atom group_leader
+atom have_dt_utag
atom heap_block_size
atom heap_size
atom heap_sizes
@@ -254,7 +258,6 @@ atom hide
atom high
atom hipe_architecture
atom http httph https http_response http_request http_header http_eoh http_error http_bin httph_bin
-atom hybrid
atom id
atom if_clause
atom imports
@@ -386,6 +389,7 @@ atom opt
atom or
atom ordered_set
atom orelse
+atom os_pid
atom os_type
atom os_version
atom ose_bg_proc
@@ -552,8 +556,10 @@ atom waiting
atom wall_clock
atom warning
atom warning_msg
+atom scheduler_wall_time
atom wordsize
atom write_concurrency
atom xor
+atom x86
atom yes
atom yield
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 2561d7a630..ada2d152b7 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -33,12 +33,14 @@
#include "beam_catches.h"
#include "erl_binary.h"
#include "erl_nif.h"
+#include "erl_thr_progress.h"
static void set_default_trace_pattern(Eterm module);
static Eterm check_process_code(Process* rp, Module* modp);
static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp);
static void delete_export_references(Eterm module);
static int purge_module(int module);
+static void decrement_refc(BeamInstr* code);
static int is_native(BeamInstr* code);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -49,11 +51,11 @@ load_module_2(BIF_ALIST_2)
{
Eterm reason;
Eterm* hp;
- int i;
int sz;
byte* code;
Eterm res;
byte* temp_alloc = NULL;
+ struct LoaderState* stp;
if (is_not_atom(BIF_ARG_1)) {
error:
@@ -63,49 +65,37 @@ load_module_2(BIF_ALIST_2)
if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) {
goto error;
}
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
-
- erts_export_consolidate();
-
hp = HAlloc(BIF_P, 3);
+
+ /*
+ * Read the BEAM file and prepare the module for loading.
+ */
+ stp = erts_alloc_loader_state();
sz = binary_size(BIF_ARG_2);
- if ((i = erts_load_module(BIF_P, 0,
- BIF_P->group_leader, &BIF_ARG_1, code, sz)) < 0) {
- switch (i) {
- case -1: reason = am_badfile; break;
- case -2: reason = am_nofile; break;
- case -3: reason = am_not_purged; break;
- case -4:
- reason = am_atom_put("native_code", sizeof("native_code")-1);
- break;
- case -5:
- {
- /*
- * The module contains an on_load function. The loader
- * has loaded the module as usual, except that the
- * export entries does not point into the module, so it
- * is not possible to call any code in the module.
- */
-
- ERTS_DECL_AM(on_load);
- reason = AM_on_load;
- break;
- }
- default: reason = am_badfile; break;
- }
+ reason = erts_prepare_loading(stp, BIF_P, BIF_P->group_leader,
+ &BIF_ARG_1, code, sz);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ if (reason != NIL) {
res = TUPLE2(hp, am_error, reason);
- goto done;
+ BIF_RET(res);
}
- set_default_trace_pattern(BIF_ARG_1);
- res = TUPLE2(hp, am_module, BIF_ARG_1);
+ /*
+ * Stop all other processes and finish the loading of the module.
+ */
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_thr_progress_block();
- done:
- erts_free_aligned_binary_bytes(temp_alloc);
- erts_smp_release_system();
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ reason = erts_finish_loading(stp, BIF_P, 0, &BIF_ARG_1);
+ if (reason != NIL) {
+ res = TUPLE2(hp, am_error, reason);
+ } else {
+ set_default_trace_pattern(BIF_ARG_1);
+ res = TUPLE2(hp, am_module, BIF_ARG_1);
+ }
+ erts_smp_thr_progress_unblock();
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
}
@@ -118,12 +108,12 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_export_consolidate();
purge_res = purge_module(atom_val(BIF_ARG_1));
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (purge_res < 0) {
@@ -152,12 +142,12 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
Eterm res;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_export_consolidate();
res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
return res;
}
@@ -239,7 +229,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
goto badarg;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
{
Module *modp = erts_get_module(BIF_ARG_1);
@@ -260,7 +250,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
}
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (res == am_badarg) {
@@ -352,7 +342,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (BIF_ARG_2 == am_true) {
int i;
@@ -391,7 +381,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
modp->catches = BEAM_CATCHES_NIL;
remove_from_address_table(code);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
}
@@ -429,10 +419,8 @@ check_process_code(Process* rp, Module* modp)
Uint mod_size;
BeamInstr* end;
Eterm* sp;
-#ifndef HYBRID /* FIND ME! */
struct erl_off_heap_header* oh;
int done_gc = 0;
-#endif
#define INSIDE(a) (start <= (a) && (a) < end)
@@ -491,7 +479,6 @@ check_process_code(Process* rp, Module* modp)
* See if there are funs that refer to the old version of the module.
*/
-#ifndef HYBRID /* FIND ME! */
rescan:
for (oh = MSO(rp).first; oh; oh = oh->next) {
if (thing_subtag(oh->thing_word) == FUN_SUBTAG) {
@@ -517,7 +504,6 @@ check_process_code(Process* rp, Module* modp)
}
}
}
-#endif
/*
* See if there are constants inside the module referenced by the process.
@@ -564,6 +550,7 @@ check_process_code(Process* rp, Module* modp)
} else {
Eterm* literals;
Uint lit_size;
+ struct erl_off_heap_header* oh;
/*
* Try to get rid of constants by by garbage collecting.
@@ -577,7 +564,9 @@ check_process_code(Process* rp, Module* modp)
(void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
literals = (Eterm *) modp->old_code[MI_LITERALS_START];
lit_size = (Eterm *) modp->old_code[MI_LITERALS_END] - literals;
- erts_garbage_collect_literals(rp, literals, lit_size);
+ oh = (struct erl_off_heap_header *)
+ modp->old_code[MI_LITERALS_OFF_HEAP];
+ erts_garbage_collect_literals(rp, literals, lit_size, oh);
}
}
return am_false;
@@ -585,7 +574,7 @@ check_process_code(Process* rp, Module* modp)
}
#define in_area(ptr,start,nbytes) \
- ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
static int
any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
@@ -655,9 +644,6 @@ purge_module(int module)
* Any code to purge?
*/
if (modp->old_code == 0) {
- if (display_loads) {
- erts_printf("No code to purge for %T\n", make_atom(module));
- }
return -1;
}
@@ -678,6 +664,7 @@ purge_module(int module)
end = (BeamInstr *)((char *)code + modp->old_code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->old_catches, code, modp->old_code_length);
+ decrement_refc(code);
erts_free(ERTS_ALC_T_CODE, (void *) code);
modp->old_code = NULL;
modp->old_code_length = 0;
@@ -687,6 +674,23 @@ purge_module(int module)
}
static void
+decrement_refc(BeamInstr* code)
+{
+ struct erl_off_heap_header* oh =
+ (struct erl_off_heap_header *) code[MI_LITERALS_OFF_HEAP];
+
+ while (oh) {
+ Binary* bptr;
+ ASSERT(thing_subtag(oh->thing_word) == REFC_BINARY_SUBTAG);
+ bptr = ((ProcBin*)oh)->val;
+ if (erts_refc_dectest(&bptr->refc, 0) == 0) {
+ erts_bin_free(bptr);
+ }
+ oh = oh->next;
+ }
+}
+
+static void
remove_from_address_table(BeamInstr* code)
{
int i;
@@ -728,10 +732,10 @@ delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp)
if (modp->code != NULL && modp->code[MI_NUM_BREAKPOINTS] > 0) {
if (c_p && c_p_locks)
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_clear_module_break(modp);
modp->code[MI_NUM_BREAKPOINTS] = 0;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
if (c_p && c_p_locks)
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
@@ -773,7 +777,7 @@ delete_export_references(Eterm module)
}
-int
+Eterm
beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
{
Module* modp = erts_put_module(module);
@@ -784,15 +788,12 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
*/
if (modp->code != NULL && modp->old_code != NULL) {
- return -3;
+ return am_not_purged;
} else if (modp->old_code == NULL) { /* Make the current version old. */
- if (display_loads) {
- erts_printf("saving old code\n");
- }
delete_code(c_p, c_p_locks, modp);
delete_export_references(module);
}
- return 0;
+ return NIL;
}
static int
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 773baad01f..d772bea02f 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -167,7 +167,7 @@ erts_bp_init(void) {
int
erts_set_trace_break(Eterm mfa[3], int specified, Binary *match_spec,
Eterm tracer_pid) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, match_spec,
(BeamInstr) BeamOp(op_i_trace_breakpoint), 0, tracer_pid);
}
@@ -175,7 +175,7 @@ erts_set_trace_break(Eterm mfa[3], int specified, Binary *match_spec,
int
erts_set_mtrace_break(Eterm mfa[3], int specified, Binary *match_spec,
Eterm tracer_pid) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, match_spec,
(BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
}
@@ -184,7 +184,7 @@ erts_set_mtrace_break(Eterm mfa[3], int specified, Binary *match_spec,
void
erts_set_mtrace_bif(BeamInstr *pc, Binary *match_spec, Eterm tracer_pid) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
set_function_break(NULL, pc, BREAK_IS_BIF, match_spec, (BeamInstr) BeamOp(op_i_mtrace_breakpoint), 0, tracer_pid);
}
@@ -198,35 +198,35 @@ void erts_clear_time_trace_bif(BeamInstr *pc) {
int
erts_set_debug_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, NULL,
(BeamInstr) BeamOp(op_i_debug_breakpoint), 0, NIL);
}
int
erts_set_count_break(Eterm mfa[3], int specified, enum erts_break_op count_op) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, NULL,
(BeamInstr) BeamOp(op_i_count_breakpoint), count_op, NIL);
}
int
erts_set_time_break(Eterm mfa[3], int specified, enum erts_break_op count_op) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return set_break(mfa, specified, NULL,
(BeamInstr) BeamOp(op_i_time_breakpoint), count_op, NIL);
}
int
erts_clear_trace_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_trace_breakpoint));
}
int
erts_clear_mtrace_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_mtrace_breakpoint));
}
@@ -238,41 +238,41 @@ erts_clear_mtrace_bif(BeamInstr *pc) {
int
erts_clear_debug_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_debug_breakpoint));
}
int
erts_clear_count_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_count_breakpoint));
}
int
erts_clear_time_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified,
(BeamInstr) BeamOp(op_i_time_breakpoint));
}
int
erts_clear_break(Eterm mfa[3], int specified) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
return clear_break(mfa, specified, 0);
}
int
erts_clear_module_break(Module *modp) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(modp);
return clear_module_break(modp, NULL, 0, 0);
}
int
erts_clear_function_break(Module *modp, BeamInstr *pc) {
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(modp);
return clear_function_break(modp, pc, BREAK_IS_ERL, 0);
}
@@ -495,16 +495,6 @@ erts_find_local_func(Eterm mfa[3]) {
return NULL;
}
-/* bp_hash */
-ERTS_INLINE Uint bp_sched2ix() {
-#ifdef ERTS_SMP
- ErtsSchedulerData *esdp;
- esdp = erts_get_scheduler_data();
- return esdp->no - 1;
-#else
- return 0;
-#endif
-}
static void bp_hash_init(bp_time_hash_t *hash, Uint n) {
Uint size = sizeof(bp_data_time_item_t)*n;
Uint i;
@@ -612,9 +602,13 @@ static void bp_hash_delete(bp_time_hash_t *hash) {
static void bp_time_diff(bp_data_time_item_t *item, /* out */
process_breakpoint_time_t *pbt, /* in */
Uint ms, Uint s, Uint us) {
- int dms,ds,dus;
+ int ds,dus;
+#ifdef DEBUG
+ int dms;
+
dms = ms - pbt->ms;
+#endif
ds = s - pbt->s;
dus = us - pbt->us;
@@ -622,7 +616,9 @@ static void bp_time_diff(bp_data_time_item_t *item, /* out */
* this is ok.
*/
+#ifdef DEBUG
ASSERT(dms >= 0 || ds >= 0 || dus >= 0);
+#endif
if (dus < 0) {
dus += 1000000;
@@ -975,7 +971,7 @@ static int set_function_break(Module *modp, BeamInstr *pc, int bif,
BpDataTime *bdt = (BpDataTime *) bd;
Uint i = 0;
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
if (count_op == erts_break_stop) {
bdt->pause = 1;
@@ -1333,15 +1329,19 @@ static BpData *get_break(Process *p, BeamInstr *pc, BeamInstr break_op) {
}
static BpData *is_break(BeamInstr *pc, BeamInstr break_op) {
- BpData **rs = (BpData **) pc[-4];
+ BpData **rs;
BpData *bd = NULL, *ebd = NULL;
ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
+ if (erts_is_native_break(pc)) {
+ return NULL;
+ }
+ rs = (BpData **) pc[-4];
if (! rs) {
return NULL;
}
- bd = ebd = rs[bp_sched2ix()];
+ bd = ebd = rs[erts_bp_sched2ix()];
ASSERT(bd);
if ( (break_op == 0) || (bd->this_instr == break_op)) {
return bd;
diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h
index 2ec5818688..167069552f 100644
--- a/erts/emulator/beam/beam_bp.h
+++ b/erts/emulator/beam/beam_bp.h
@@ -144,8 +144,6 @@ extern erts_smp_spinlock_t erts_bp_lock;
#define ErtsSmpBPUnlock(BDC)
#endif
-ERTS_INLINE Uint bp_sched2ix(void);
-
#ifdef ERTS_SMP
#define bp_sched2ix_proc(p) ((p)->scheduler_data->no - 1)
#else
@@ -247,4 +245,19 @@ BpData *erts_get_time_break(Process *p, BeamInstr *pc);
BeamInstr *erts_find_local_func(Eterm mfa[3]);
+ERTS_GLB_INLINE Uint erts_bp_sched2ix(void);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE Uint erts_bp_sched2ix(void)
+{
+#ifdef ERTS_SMP
+ ErtsSchedulerData *esdp;
+ esdp = erts_get_scheduler_data();
+ return esdp->no - 1;
+#else
+ return 0;
+#endif
+}
+#endif
+
#endif /* _BEAM_BP_H */
diff --git a/erts/emulator/beam/beam_catches.c b/erts/emulator/beam/beam_catches.c
index e795b4efbd..406ef1db5f 100644
--- a/erts/emulator/beam/beam_catches.c
+++ b/erts/emulator/beam/beam_catches.c
@@ -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
@@ -22,21 +22,27 @@
#endif
#include "sys.h"
#include "beam_catches.h"
+#include "global.h"
-/* XXX: should use dynamic reallocation */
-#define TABSIZ (16*1024)
-static struct {
+/* R14B04 has about 380 catches when starting erlang */
+#define DEFAULT_TABSIZE (1024)
+typedef struct {
BeamInstr *cp;
unsigned cdr;
-} beam_catches[TABSIZ];
+} beam_catch_t;
static int free_list;
static unsigned high_mark;
+static unsigned tabsize;
+static beam_catch_t *beam_catches;
void beam_catches_init(void)
{
+ tabsize = DEFAULT_TABSIZE;
free_list = -1;
high_mark = 0;
+
+ beam_catches = erts_alloc(ERTS_ALC_T_CODE, sizeof(beam_catch_t)*DEFAULT_TABSIZE);
}
unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr)
@@ -50,16 +56,21 @@ unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr)
* This avoids the need to initialise the free list in
* beam_catches_init(), which would cost O(TABSIZ) time.
*/
- if( (i = free_list) >= 0 ) {
+ if( free_list >= 0 ) {
+ i = free_list;
free_list = beam_catches[i].cdr;
- } else if( (i = high_mark) < TABSIZ ) {
- high_mark = i + 1;
+ } else if( high_mark < tabsize ) {
+ i = high_mark;
+ high_mark++;
} else {
- fprintf(stderr, "beam_catches_cons: no free slots :-(\r\n");
- exit(1);
+ /* No free slots and table is full: realloc table */
+ tabsize = 2*tabsize;
+ beam_catches = erts_realloc(ERTS_ALC_T_CODE, beam_catches, sizeof(beam_catch_t)*tabsize);
+ i = high_mark;
+ high_mark++;
}
- beam_catches[i].cp = cp;
+ beam_catches[i].cp = cp;
beam_catches[i].cdr = cdr;
return i;
@@ -67,10 +78,8 @@ unsigned beam_catches_cons(BeamInstr *cp, unsigned cdr)
BeamInstr *beam_catches_car(unsigned i)
{
- if( i >= TABSIZ ) {
- fprintf(stderr,
- "beam_catches_car: index %#x is out of range\r\n", i);
- abort();
+ if( i >= tabsize ) {
+ erl_exit(1, "beam_catches_delmod: index %#x is out of range\r\n", i);
}
return beam_catches[i].cp;
}
@@ -80,18 +89,15 @@ void beam_catches_delmod(unsigned head, BeamInstr *code, unsigned code_bytes)
unsigned i, cdr;
for(i = head; i != (unsigned)-1;) {
- if( i >= TABSIZ ) {
- fprintf(stderr,
- "beam_catches_delmod: index %#x is out of range\r\n", i);
- abort();
+ if( i >= tabsize ) {
+ erl_exit(1, "beam_catches_delmod: index %#x is out of range\r\n", i);
}
if( (char*)beam_catches[i].cp - (char*)code >= code_bytes ) {
- fprintf(stderr,
+ erl_exit(1,
"beam_catches_delmod: item %#x has cp %#lx which is not "
"in module's range [%#lx,%#lx[\r\n",
i, (long)beam_catches[i].cp,
(long)code, (long)((char*)code + code_bytes));
- abort();
}
beam_catches[i].cp = 0;
cdr = beam_catches[i].cdr;
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index fffb172c68..8041c92162 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -37,6 +37,7 @@
#include "beam_load.h"
#include "beam_bp.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
#ifdef ARCH_64
# define HEXF "%016bpX"
@@ -49,15 +50,18 @@ void dbg_bt(Process* p, Eterm* sp);
void dbg_where(BeamInstr* addr, Eterm x0, Eterm* reg);
static int print_op(int to, void *to_arg, int op, int size, BeamInstr* addr);
-Eterm
-erts_debug_same_2(Process* p, Eterm term1, Eterm term2)
+
+BIF_RETTYPE
+erts_debug_same_2(BIF_ALIST_2)
{
- return (term1 == term2) ? am_true : am_false;
+ return (BIF_ARG_1 == BIF_ARG_2) ? am_true : am_false;
}
-Eterm
-erts_debug_flat_size_1(Process* p, Eterm term)
+BIF_RETTYPE
+erts_debug_flat_size_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
Uint size = size_object(term);
if (IS_USMALL(0, size)) {
@@ -68,9 +72,13 @@ erts_debug_flat_size_1(Process* p, Eterm term)
}
}
-Eterm
-erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
+
+BIF_RETTYPE
+erts_debug_breakpoint_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm MFA = BIF_ARG_1;
+ Eterm bool = BIF_ARG_2;
Eterm* tp;
Eterm mfa[3];
int i;
@@ -107,7 +115,7 @@ erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
}
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (bool == am_true) {
res = make_small(erts_set_debug_break(mfa, specified));
@@ -115,7 +123,7 @@ erts_debug_breakpoint_2(Process* p, Eterm MFA, Eterm bool)
res = make_small(erts_clear_debug_break(mfa, specified));
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
return res;
@@ -175,9 +183,11 @@ erts_debug_instructions_0(BIF_ALIST_0)
return res;
}
-Eterm
-erts_debug_disassemble_1(Process* p, Eterm addr)
+BIF_RETTYPE
+erts_debug_disassemble_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm addr = BIF_ARG_1;
erts_dsprintf_buf_t *dsbufp;
Eterm* hp;
Eterm* tp;
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 5691f7aec1..6d3b15cd46 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,6 @@
#include "erl_vm.h"
#include "global.h"
#include "erl_process.h"
-#include "erl_nmgc.h"
#include "error.h"
#include "bif.h"
#include "big.h"
@@ -36,15 +35,17 @@
#include "dist.h"
#include "beam_bp.h"
#include "beam_catches.h"
+#include "erl_thr_progress.h"
#ifdef HIPE
#include "hipe_mode_switch.h"
#include "hipe_bif1.h"
#endif
+#include "dtrace-wrapper.h"
/* #define HARDDEBUG 1 */
#if defined(NO_JUMP_TABLE)
-# define OpCase(OpCode) case op_##OpCode: lb_##OpCode
+# define OpCase(OpCode) case op_##OpCode
# define CountCase(OpCode) case op_count_##OpCode
# define OpCode(OpCode) ((Uint*)op_##OpCode)
# define Goto(Rel) {Go = (int)(Rel); goto emulator_loop;}
@@ -52,7 +53,7 @@
#else
# define OpCase(OpCode) lb_##OpCode
# define CountCase(OpCode) lb_count_##OpCode
-# define Goto(Rel) goto *(Rel)
+# define Goto(Rel) goto *((void *)Rel)
# define LabelAddr(Label) &&Label
# define OpCode(OpCode) (&&lb_##OpCode)
#endif
@@ -70,7 +71,7 @@ do { \
} \
else \
erts_lc_check_exact(NULL, 0); \
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING); \
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking()); \
} while (0)
# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \
if ((P)) erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN)
@@ -198,7 +199,7 @@ do { \
} \
} while (0)
-#define ClauseFail() goto lb_jump_f
+#define ClauseFail() goto jump_f
#define SAVE_CP(X) \
do { \
@@ -233,6 +234,12 @@ BeamInstr beam_return_trace[1]; /* OpCode(i_return_trace) */
BeamInstr beam_exception_trace[1]; /* UGLY also OpCode(i_return_trace) */
BeamInstr beam_return_time_trace[1]; /* OpCode(i_return_time_trace) */
+
+/*
+ * We should warn only once for tuple funs.
+ */
+static erts_smp_atomic_t warned_for_tuple_funs;
+
/*
* All Beam instructions in numerical order.
*/
@@ -245,20 +252,6 @@ void** beam_ops;
extern int count_instructions;
#endif
-#if defined(HYBRID)
-#define SWAPIN \
- g_htop = global_htop; \
- g_hend = global_hend; \
- HTOP = HEAP_TOP(c_p); \
- E = c_p->stop
-
-#define SWAPOUT \
- global_htop = g_htop; \
- global_hend = g_hend; \
- HEAP_TOP(c_p) = HTOP; \
- c_p->stop = E
-
-#else
#define SWAPIN \
HTOP = HEAP_TOP(c_p); \
E = c_p->stop
@@ -286,8 +279,6 @@ extern int count_instructions;
#define LIGHT_SWAPIN HTOP = HEAP_TOP(c_p)
-#endif
-
#ifdef FORCE_HEAP_FRAGS
# define HEAP_SPACE_VERIFIED(Words) do { \
c_p->space_verified = (Words); \
@@ -303,44 +294,6 @@ extern int count_instructions;
PROCESS_MAIN_CHK_LOCKS((P)); \
ERTS_SMP_UNREQ_PROC_MAIN_LOCK((P))
-#if defined(HYBRID)
-# define POST_BIF_GC_SWAPIN_0(_p, _res) \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _res = erts_gc_after_bif_call((_p), (_res), NULL, 0); \
- } \
- SWAPIN
-
-# define POST_BIF_GC_SWAPIN(_p, _res, _regs, _arity) \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _regs[0] = r(0); \
- _res = erts_gc_after_bif_call((_p), (_res), _regs, (_arity)); \
- r(0) = _regs[0]; \
- } \
- SWAPIN
-#else
-# define POST_BIF_GC_SWAPIN_0(_p, _res) \
- ERTS_SMP_REQ_PROC_MAIN_LOCK((_p)); \
- PROCESS_MAIN_CHK_LOCKS((_p)); \
- ERTS_VERIFY_UNUSED_TEMP_ALLOC((_p)); \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _res = erts_gc_after_bif_call((_p), (_res), NULL, 0); \
- E = (_p)->stop; \
- } \
- HTOP = HEAP_TOP((_p))
-
-# define POST_BIF_GC_SWAPIN(_p, _res, _regs, _arity) \
- ERTS_VERIFY_UNUSED_TEMP_ALLOC((_p)); \
- ERTS_SMP_REQ_PROC_MAIN_LOCK((_p)); \
- PROCESS_MAIN_CHK_LOCKS((_p)); \
- if (((_p)->mbuf) || (MSO(_p).overhead >= BIN_VHEAP_SZ(_p)) ) { \
- _regs[0] = r(0); \
- _res = erts_gc_after_bif_call((_p), (_res), _regs, (_arity)); \
- r(0) = _regs[0]; \
- E = (_p)->stop; \
- } \
- HTOP = HEAP_TOP((_p))
-#endif
-
#define db(N) (N)
#define tb(N) (N)
#define xb(N) (*(Eterm *) (((unsigned char *)reg) + (N)))
@@ -487,36 +440,6 @@ extern int count_instructions;
CHECK_TERM(r(0)); \
} while (0)
-#ifdef HYBRID
-#ifdef INCREMENTAL
-#define TestGlobalHeap(Nh, Live, hp) \
- do { \
- unsigned need = (Nh); \
- ASSERT(global_heap <= g_htop && g_htop <= global_hend); \
- SWAPOUT; \
- reg[0] = r(0); \
- FCALLS -= need; \
- (hp) = IncAlloc(c_p,need,reg,(Live)); \
- r(0) = reg[0]; \
- SWAPIN; \
- } while (0)
-#else
-#define TestGlobalHeap(Nh, Live, hp) \
- do { \
- unsigned need = (Nh); \
- ASSERT(global_heap <= g_htop && g_htop <= global_hend); \
- if (g_hend - g_htop < need) { \
- SWAPOUT; \
- reg[0] = r(0); \
- FCALLS -= erts_global_garbage_collect(c_p, need, reg, (Live)); \
- r(0) = reg[0]; \
- SWAPIN; \
- } \
- (hp) = global_htop; \
- } while (0)
-#endif
-#endif /* HYBRID */
-
#define Init(N) make_blank(yb(N))
#define Init2(Y1, Y2) do { make_blank(Y1); make_blank(Y2); } while (0)
@@ -794,11 +717,11 @@ extern int count_instructions;
} \
} while (0)
-#define IsFunction2(F, A, Action) \
- do { \
- if (is_function_2(c_p, F, A) != am_true ) {\
- Action; \
- } \
+#define IsFunction2(F, A, Action) \
+ do { \
+ if (erl_is_function(c_p, F, A) != am_true ) { \
+ Action; \
+ } \
} while (0)
#define IsTupleOfArity(Src, Arity, Fail) \
@@ -1052,6 +975,7 @@ init_emulator(void)
#if defined(VXWORKS)
init_done = 0;
#endif
+ erts_smp_atomic_init_nob(&warned_for_tuple_funs, (erts_aint_t) 0);
process_main();
}
@@ -1080,6 +1004,101 @@ init_emulator(void)
# define REG_tmp_arg2
#endif
+#ifdef USE_VM_PROBES
+# define USE_VM_CALL_PROBES
+#endif
+
+#ifdef USE_VM_CALL_PROBES
+
+#define DTRACE_LOCAL_CALL(p, m, f, a) \
+ if (DTRACE_ENABLED(local_function_entry)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ int depth = STACK_START(p) - STACK_TOP(p); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE3(local_function_entry, process_name, mfa, depth); \
+ }
+
+#define DTRACE_GLOBAL_CALL(p, m, f, a) \
+ if (DTRACE_ENABLED(global_function_entry)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ int depth = STACK_START(p) - STACK_TOP(p); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE3(global_function_entry, process_name, mfa, depth); \
+ }
+
+#define DTRACE_RETURN(p, m, f, a) \
+ if (DTRACE_ENABLED(function_return)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ int depth = STACK_START(p) - STACK_TOP(p); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE3(function_return, process_name, mfa, depth); \
+ }
+
+#define DTRACE_BIF_ENTRY(p, m, f, a) \
+ if (DTRACE_ENABLED(bif_entry)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE2(bif_entry, process_name, mfa); \
+ }
+
+#define DTRACE_BIF_RETURN(p, m, f, a) \
+ if (DTRACE_ENABLED(bif_return)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE2(bif_return, process_name, mfa); \
+ }
+
+#define DTRACE_NIF_ENTRY(p, m, f, a) \
+ if (DTRACE_ENABLED(nif_entry)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE2(nif_entry, process_name, mfa); \
+ }
+
+#define DTRACE_NIF_RETURN(p, m, f, a) \
+ if (DTRACE_ENABLED(nif_return)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \
+ dtrace_fun_decode(p, m, f, a, \
+ process_name, mfa); \
+ DTRACE2(nif_return, process_name, mfa); \
+ }
+
+#else /* USE_VM_PROBES */
+
+#define DTRACE_LOCAL_CALL(p, m, f, a) do {} while (0)
+#define DTRACE_GLOBAL_CALL(p, m, f, a) do {} while (0)
+#define DTRACE_RETURN(p, m, f, a) do {} while (0)
+#define DTRACE_BIF_ENTRY(p, m, f, a) do {} while (0)
+#define DTRACE_BIF_RETURN(p, m, f, a) do {} while (0)
+#define DTRACE_NIF_ENTRY(p, m, f, a) do {} while (0)
+#define DTRACE_NIF_RETURN(p, m, f, a) do {} while (0)
+
+#endif /* USE_VM_PROBES */
+
+#ifdef USE_VM_PROBES
+void
+dtrace_drvport_str(ErlDrvPort drvport, char *port_buf)
+{
+ Port *port = erts_drvport2port(drvport);
+
+ erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
+ port_channel_no(port->id),
+ port_number(port->id));
+}
+#endif
/*
* process_main() is called twice:
* The first call performs some initialisation, including exporting
@@ -1094,7 +1113,7 @@ void process_main(void)
Process* c_p = NULL;
int reds_used;
#ifdef DEBUG
- Eterm pid;
+ ERTS_DECLARE_DUMMY(Eterm pid);
#endif
/*
@@ -1112,12 +1131,6 @@ void process_main(void)
*/
register Eterm* HTOP REG_htop = NULL;
-
-#ifdef HYBRID
- Eterm *g_htop;
- Eterm *g_hend;
-#endif
-
/* Stack pointer. Grows downwards; points
* to last item pushed (normally a saved
* continuation pointer).
@@ -1202,7 +1215,7 @@ void process_main(void)
c_p = schedule(c_p, reds_used);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
#ifdef DEBUG
- pid = c_p->id;
+ pid = c_p->id; /* Save for debugging purpouses */
#endif
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -1251,6 +1264,30 @@ void process_main(void)
#endif
SWAPIN;
ASSERT(VALID_INSTR(next));
+
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_scheduled)) {
+ DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(fun_buf, DTRACE_TERM_BUF_SIZE);
+ dtrace_proc_str(c_p, process_buf);
+
+ if (ERTS_PROC_IS_EXITING(c_p)) {
+ strcpy(fun_buf, "<exiting>");
+ } else {
+ BeamInstr *fptr = find_function_from_pc(c_p->i);
+ if (fptr) {
+ dtrace_fun_decode(c_p, (Eterm)fptr[0],
+ (Eterm)fptr[1], (Uint)fptr[2],
+ NULL, fun_buf);
+ } else {
+ erts_snprintf(fun_buf, sizeof(fun_buf),
+ "<unknown/%p>", next);
+ }
+ }
+
+ DTRACE2(process_scheduled, process_buf, fun_buf);
+ }
+#endif
Goto(next);
}
@@ -1427,6 +1464,7 @@ void process_main(void)
/* FALL THROUGH */
OpCase(i_call_only_f): {
SET_I((BeamInstr *) Arg(0));
+ DTRACE_LOCAL_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]);
Dispatch();
}
@@ -1438,6 +1476,7 @@ void process_main(void)
RESTORE_CP(E);
E = ADD_BYTE_OFFSET(E, Arg(1));
SET_I((BeamInstr *) Arg(0));
+ DTRACE_LOCAL_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]);
Dispatch();
}
@@ -1449,6 +1488,7 @@ void process_main(void)
OpCase(i_call_f): {
SET_CP(c_p, I+2);
SET_I((BeamInstr *) Arg(0));
+ DTRACE_LOCAL_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]);
Dispatch();
}
@@ -1465,6 +1505,12 @@ void process_main(void)
* is not loaded, it points to code which will invoke the error handler
* (see lb_call_error_handler below).
*/
+#ifdef USE_VM_CALL_PROBES
+ if (DTRACE_ENABLED(global_function_entry)) {
+ BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address);
+ DTRACE_GLOBAL_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]);
+ }
+#endif
Dispatchx();
OpCase(i_move_call_ext_cre): {
@@ -1474,6 +1520,12 @@ void process_main(void)
/* FALL THROUGH */
OpCase(i_call_ext_e):
SET_CP(c_p, I+2);
+#ifdef USE_VM_CALL_PROBES
+ if (DTRACE_ENABLED(global_function_entry)) {
+ BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address);
+ DTRACE_GLOBAL_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]);
+ }
+#endif
Dispatchx();
OpCase(i_move_call_ext_only_ecr): {
@@ -1481,6 +1533,12 @@ void process_main(void)
}
/* FALL THROUGH */
OpCase(i_call_ext_only_e):
+#ifdef USE_VM_CALL_PROBES
+ if (DTRACE_ENABLED(global_function_entry)) {
+ BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address);
+ DTRACE_GLOBAL_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]);
+ }
+#endif
Dispatchx();
OpCase(init_y): {
@@ -1516,7 +1574,16 @@ void process_main(void)
OpCase(return): {
+#ifdef USE_VM_CALL_PROBES
+ BeamInstr* fptr;
+#endif
SET_I(c_p->cp);
+
+#ifdef USE_VM_CALL_PROBES
+ if (DTRACE_ENABLED(function_return) && (fptr = find_function_from_pc(c_p->cp))) {
+ DTRACE_RETURN(c_p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]);
+ }
+#endif
/*
* We must clear the CP to make sure that a stale value do not
* create a false module dependcy preventing code upgrading.
@@ -1541,9 +1608,17 @@ void process_main(void)
PRE_BIF_SWAPOUT(c_p);
c_p->fcalls = FCALLS - 1;
- result = send_2(c_p, r(0), x(1));
+ reg[0] = r(0);
+ result = erl_send(c_p, r(0), x(1));
PreFetch(0, next);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 2);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
+ result = erts_gc_after_bif_call(c_p, result, reg, 2);
+ r(0) = reg[0];
+ E = c_p->stop;
+ }
+ HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
r(0) = result;
@@ -1551,10 +1626,9 @@ void process_main(void)
NextPF(0, next);
} else if (c_p->freason == TRAP) {
SET_CP(c_p, I+1);
- SET_I(*((BeamInstr **) (BeamInstr) ((c_p)->def_arg_reg + 3)));
+ SET_I(c_p->i);
SWAPIN;
- r(0) = c_p->def_arg_reg[0];
- x(1) = c_p->def_arg_reg[1];
+ r(0) = reg[0];
Dispatch();
}
goto find_func_info;
@@ -1778,6 +1852,7 @@ void process_main(void)
* remove it...
*/
ASSERT(!msgp->data.attached);
+ /* TODO: Add DTrace probe for this bad message situation? */
UNLINK_MESSAGE(c_p, msgp);
free_message(msgp);
goto loop_rec__;
@@ -1803,24 +1878,88 @@ void process_main(void)
save_calls(c_p, &exp_receive);
}
if (ERL_MESSAGE_TOKEN(msgp) == NIL) {
- SEQ_TRACE_TOKEN(c_p) = NIL;
+#ifdef USE_VM_PROBES
+ if (DT_UTAG(c_p) != NIL) {
+ if (DT_UTAG_FLAGS(c_p) & DT_UTAG_PERMANENT) {
+ SEQ_TRACE_TOKEN(c_p) = am_have_dt_utag;
+#ifdef DTRACE_TAG_HARDDEBUG
+ if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING)
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) stop spreading "
+ "tag %T with message %T\r\n",
+ c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
+#endif
+ } else {
+#ifdef DTRACE_TAG_HARDDEBUG
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) kill tag %T with "
+ "message %T\r\n",
+ c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
+#endif
+ DT_UTAG(c_p) = NIL;
+ SEQ_TRACE_TOKEN(c_p) = NIL;
+ }
+ } else {
+#endif
+ SEQ_TRACE_TOKEN(c_p) = NIL;
+#ifdef USE_VM_PROBES
+ }
+ DT_UTAG_FLAGS(c_p) &= ~DT_UTAG_SPREADING;
+#endif
} else if (ERL_MESSAGE_TOKEN(msgp) != am_undefined) {
Eterm msg;
SEQ_TRACE_TOKEN(c_p) = ERL_MESSAGE_TOKEN(msgp);
- ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p)));
- ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5);
- ASSERT(is_small(SEQ_TRACE_TOKEN_SERIAL(c_p)));
- ASSERT(is_small(SEQ_TRACE_TOKEN_LASTCNT(c_p)));
- ASSERT(is_small(SEQ_TRACE_TOKEN_FLAGS(c_p)));
- ASSERT(is_pid(SEQ_TRACE_TOKEN_SENDER(c_p)));
- c_p->seq_trace_lastcnt = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
- if (c_p->seq_trace_clock < unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p))) {
- c_p->seq_trace_clock = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
+#ifdef USE_VM_PROBES
+ if (ERL_MESSAGE_TOKEN(msgp) == am_have_dt_utag) {
+ if (DT_UTAG(c_p) == NIL) {
+ DT_UTAG(c_p) = ERL_MESSAGE_DT_UTAG(msgp);
+ }
+ DT_UTAG_FLAGS(c_p) |= DT_UTAG_SPREADING;
+#ifdef DTRACE_TAG_HARDDEBUG
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) receive tag (%T) "
+ "with message %T\r\n",
+ c_p->id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp));
+#endif
+ } else {
+#endif
+ ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p)));
+ ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5);
+ ASSERT(is_small(SEQ_TRACE_TOKEN_SERIAL(c_p)));
+ ASSERT(is_small(SEQ_TRACE_TOKEN_LASTCNT(c_p)));
+ ASSERT(is_small(SEQ_TRACE_TOKEN_FLAGS(c_p)));
+ ASSERT(is_pid(SEQ_TRACE_TOKEN_SENDER(c_p)));
+ c_p->seq_trace_lastcnt = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
+ if (c_p->seq_trace_clock < unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p))) {
+ c_p->seq_trace_clock = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
+ }
+ msg = ERL_MESSAGE_TERM(msgp);
+ seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE,
+ c_p->id, c_p);
+#ifdef USE_VM_PROBES
}
- msg = ERL_MESSAGE_TERM(msgp);
- seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE,
- c_p->id, c_p);
+#endif
+ }
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(message_receive)) {
+ Eterm token2 = NIL;
+ DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+
+ dtrace_proc_str(c_p, receiver_name);
+ token2 = SEQ_TRACE_TOKEN(c_p);
+ if (token2 != NIL && token2 != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token2));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2));
+ }
+ DTRACE6(message_receive,
+ receiver_name, size_object(ERL_MESSAGE_TERM(msgp)),
+ c_p->msg.len - 1, tok_label, tok_lastcnt, tok_serial);
}
+#endif
UNLINK_MESSAGE(c_p, msgp);
JOIN_MESSAGE(c_p);
CANCEL_TIMER(c_p);
@@ -2209,16 +2348,16 @@ void process_main(void)
OpCase(bif1_fbsd):
{
- Eterm (*bf)(Process*, Eterm);
- Eterm arg;
+ Eterm (*bf)(Process*, Eterm*);
+ Eterm tmp_reg[1];
Eterm result;
- GetArg1(2, arg);
+ GetArg1(2, tmp_reg[0]);
bf = (BifFunction) Arg(1);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, arg);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2237,17 +2376,17 @@ void process_main(void)
OpCase(bif1_body_bsd):
{
- Eterm (*bf)(Process*, Eterm);
+ Eterm (*bf)(Process*, Eterm*);
- Eterm arg;
+ Eterm tmp_reg[1];
Eterm result;
- GetArg1(1, arg);
+ GetArg1(1, tmp_reg[0]);
bf = (BifFunction) Arg(0);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, arg);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2256,7 +2395,7 @@ void process_main(void)
if (is_value(result)) {
StoreBifResult(2, result);
}
- reg[0] = arg;
+ reg[0] = tmp_reg[0];
SWAPOUT;
I = handle_error(c_p, I, reg, bf);
goto post_error_handling;
@@ -2380,14 +2519,15 @@ void process_main(void)
*/
OpCase(i_bif2_fbd):
{
- Eterm (*bf)(Process*, Eterm, Eterm);
+ Eterm tmp_reg[2] = {tmp_arg1, tmp_arg2};
+ Eterm (*bf)(Process*, Eterm*);
Eterm result;
bf = (BifFunction) Arg(1);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, tmp_arg1, tmp_arg2);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2405,13 +2545,14 @@ void process_main(void)
*/
OpCase(i_bif2_body_bd):
{
- Eterm (*bf)(Process*, Eterm, Eterm);
+ Eterm tmp_reg[2] = {tmp_arg1, tmp_arg2};
+ Eterm (*bf)(Process*, Eterm*);
Eterm result;
bf = (BifFunction) Arg(0);
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, tmp_arg1, tmp_arg2);
+ result = (*bf)(c_p, tmp_reg);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2431,77 +2572,9 @@ void process_main(void)
* The most general BIF call. The BIF may build any amount of data
* on the heap. The result is always returned in r(0).
*/
- OpCase(call_bif0_e):
+ OpCase(call_bif_e):
{
- Eterm (*bf)(Process*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
-
- PRE_BIF_SWAPOUT(c_p);
- c_p->fcalls = FCALLS - 1;
- if (FCALLS <= 0) {
- save_calls(c_p, (Export *) Arg(0));
- }
-
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- r(0) = (*bf)(c_p, I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(r(0)));
- ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN_0(c_p, r(0));
- FCALLS = c_p->fcalls;
- if (is_value(r(0))) {
- CHECK_TERM(r(0));
- Next(1);
- }
- else if (c_p->freason == TRAP) {
- goto call_bif_trap3;
- }
-
- /*
- * Error handling. SWAPOUT is not needed because it was done above.
- */
- ASSERT(c_p->stop == E);
- reg[0] = r(0);
- I = handle_error(c_p, I, reg, bf);
- goto post_error_handling;
- }
-
- OpCase(call_bif1_e):
- {
- Eterm (*bf)(Process*, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
- Eterm result;
- BeamInstr *next;
-
- c_p->fcalls = FCALLS - 1;
- if (FCALLS <= 0) {
- save_calls(c_p, (Export *) Arg(0));
- }
- PreFetch(1, next);
- PRE_BIF_SWAPOUT(c_p);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, r(0), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
- ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 1);
- FCALLS = c_p->fcalls;
- if (is_value(result)) {
- r(0) = result;
- CHECK_TERM(r(0));
- NextPF(1, next);
- } else if (c_p->freason == TRAP) {
- goto call_bif_trap3;
- }
-
- /*
- * Error handling. SWAPOUT is not needed because it was done above.
- */
- ASSERT(c_p->stop == E);
- reg[0] = r(0);
- I = handle_error(c_p, I, reg, bf);
- goto post_error_handling;
- }
-
- OpCase(call_bif2_e):
- {
- Eterm (*bf)(Process*, Eterm, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
+ Eterm (*bf)(Process*, Eterm*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
Eterm result;
BeamInstr *next;
@@ -2511,61 +2584,29 @@ void process_main(void)
save_calls(c_p, (Export *) Arg(0));
}
PreFetch(1, next);
- CHECK_TERM(r(0));
- CHECK_TERM(x(1));
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, r(0), x(1), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
- ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 2);
- FCALLS = c_p->fcalls;
- if (is_value(result)) {
- r(0) = result;
- CHECK_TERM(r(0));
- NextPF(1, next);
- } else if (c_p->freason == TRAP) {
- goto call_bif_trap3;
- }
-
- /*
- * Error handling. SWAPOUT is not needed because it was done above.
- */
- ASSERT(c_p->stop == E);
reg[0] = r(0);
- I = handle_error(c_p, I, reg, bf);
- goto post_error_handling;
- }
-
- OpCase(call_bif3_e):
- {
- Eterm (*bf)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
- Eterm result;
- BeamInstr *next;
-
- PRE_BIF_SWAPOUT(c_p);
- c_p->fcalls = FCALLS - 1;
- if (FCALLS <= 0) {
- save_calls(c_p, (Export *) Arg(0));
- }
- PreFetch(1, next);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = (*bf)(c_p, r(0), x(1), x(2), I);
+ result = (*bf)(c_p, reg, I);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_HOLE_CHECK(c_p);
- POST_BIF_GC_SWAPIN(c_p, result, reg, 3);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
+ Uint arity = ((Export *)Arg(0))->code[2];
+ result = erts_gc_after_bif_call(c_p, result, reg, arity);
+ E = c_p->stop;
+ }
+ HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
r(0) = result;
CHECK_TERM(r(0));
NextPF(1, next);
} else if (c_p->freason == TRAP) {
- call_bif_trap3:
SET_CP(c_p, I+2);
- SET_I(*((BeamInstr **) (UWord) ((c_p)->def_arg_reg + 3)));
+ SET_I(c_p->i);
SWAPIN;
- r(0) = c_p->def_arg_reg[0];
- x(1) = c_p->def_arg_reg[1];
- x(2) = c_p->def_arg_reg[2];
+ r(0) = reg[0];
Dispatch();
}
@@ -2573,7 +2614,6 @@ void process_main(void)
* Error handling. SWAPOUT is not needed because it was done above.
*/
ASSERT(c_p->stop == E);
- reg[0] = r(0);
I = handle_error(c_p, I, reg, bf);
goto post_error_handling;
}
@@ -2669,6 +2709,7 @@ void process_main(void)
lb_Cl_error: {
if (Arg(0) != 0) {
OpCase(jump_f): {
+ jump_f:
SET_I((BeamInstr *) Arg(0));
Goto(*I);
}
@@ -3242,7 +3283,7 @@ void process_main(void)
/* Fall through */
OpCase(error_action_code): {
- no_error_handler:
+ handle_error:
reg[0] = r(0);
SWAPOUT;
I = handle_error(c_p, NULL, reg, NULL);
@@ -3278,6 +3319,7 @@ void process_main(void)
*/
BifFunction vbf;
+ DTRACE_NIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
c_p->current = I-3; /* current and vbf set to please handle_error */
SWAPOUT;
c_p->fcalls = FCALLS - 1;
@@ -3299,6 +3341,8 @@ void process_main(void)
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(nif_bif_result));
PROCESS_MAIN_CHK_LOCKS(c_p);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+
+ DTRACE_NIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
goto apply_bif_or_nif_epilogue;
OpCase(apply_bif):
@@ -3318,6 +3362,8 @@ void process_main(void)
c_p->arity = 0; /* To allow garbage collection on ourselves
* (check_process_code/2).
*/
+ DTRACE_BIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
+
SWAPOUT;
c_p->fcalls = FCALLS - 1;
vbf = (BifFunction) Arg(0);
@@ -3326,64 +3372,25 @@ void process_main(void)
ASSERT(bif_nif_arity <= 3);
ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- switch (bif_nif_arity) {
- case 3:
- {
- Eterm (*bf)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, r(0), x(1), x(2), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- }
- break;
- case 2:
- {
- Eterm (*bf)(Process*, Eterm, Eterm, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, r(0), x(1), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- }
- break;
- case 1:
- {
- Eterm (*bf)(Process*, Eterm, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, r(0), I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- }
- break;
- case 0:
- {
- Eterm (*bf)(Process*, BeamInstr*) = vbf;
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- nif_bif_result = (*bf)(c_p, I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
- is_non_value(nif_bif_result));
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- break;
- }
- default:
- erl_exit(1, "apply_bif: invalid arity: %u\n",
- bif_nif_arity);
+ reg[0] = r(0);
+ {
+ Eterm (*bf)(Process*, Eterm*, BeamInstr*) = vbf;
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ nif_bif_result = (*bf)(c_p, reg, I);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
+ is_non_value(nif_bif_result));
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
}
+ DTRACE_BIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
+
apply_bif_or_nif_epilogue:
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
ERTS_HOLE_CHECK(c_p);
if (c_p->mbuf) {
- reg[0] = r(0);
nif_bif_result = erts_gc_after_bif_call(c_p, nif_bif_result,
reg, bif_nif_arity);
- r(0) = reg[0];
}
SWAPIN; /* There might have been a garbage collection. */
FCALLS = c_p->fcalls;
@@ -3394,17 +3401,14 @@ void process_main(void)
c_p->cp = 0;
Goto(*I);
} else if (c_p->freason == TRAP) {
- SET_I(*((BeamInstr **) (UWord) ((c_p)->def_arg_reg + 3)));
- r(0) = c_p->def_arg_reg[0];
- x(1) = c_p->def_arg_reg[1];
- x(2) = c_p->def_arg_reg[2];
+ SET_I(c_p->i);
+ r(0) = reg[0];
if (c_p->flags & F_HIBERNATE_SCHED) {
c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
}
Dispatch();
}
- reg[0] = r(0);
I = handle_error(c_p, c_p->cp, reg, vbf);
goto post_error_handling;
}
@@ -3447,7 +3451,7 @@ void process_main(void)
OpCase(i_func_info_IaaI): {
c_p->freason = EXC_FUNCTION_CLAUSE;
c_p->current = I + 2;
- goto lb_error_action_code;
+ goto handle_error;
}
OpCase(try_case_end_s):
@@ -3967,8 +3971,7 @@ void process_main(void)
* too big numbers).
*/
if (is_not_small(val) || val > make_small(0x10FFFFUL) ||
- (make_small(0xD800UL) <= val && val <= make_small(0xDFFFUL)) ||
- val == make_small(0xFFFEUL) || val == make_small(0xFFFFUL)) {
+ (make_small(0xD800UL) <= val && val <= make_small(0xDFFFUL))) {
goto badarg;
}
Next(2);
@@ -3987,8 +3990,8 @@ void process_main(void)
* the valid range).
*/
if (is_not_small(tmp_arg1) || tmp_arg1 > make_small(0x10FFFFUL) ||
- (make_small(0xD800UL) <= tmp_arg1 && tmp_arg1 <= make_small(0xDFFFUL)) ||
- tmp_arg1 == make_small(0xFFFEUL) || tmp_arg1 == make_small(0xFFFFUL)) {
+ (make_small(0xD800UL) <= tmp_arg1 &&
+ tmp_arg1 <= make_small(0xDFFFUL))) {
ErlBinMatchBuffer *mb = ms_matchbuffer(tmp_arg2);
mb->offset -= 32;
@@ -4921,7 +4924,12 @@ void process_main(void)
OpCase(fclearerror):
OpCase(i_fcheckerror):
erl_exit(1, "fclearerror/i_fcheckerror without fpe signals (beam_emu)");
+# define ERTS_NO_FPE_CHECK_INIT ERTS_FP_CHECK_INIT
+# define ERTS_NO_FPE_ERROR ERTS_FP_ERROR
#else
+# define ERTS_NO_FPE_CHECK_INIT(p)
+# define ERTS_NO_FPE_ERROR(p, a, b)
+
OpCase(fclearerror): {
BeamInstr *next;
@@ -4937,10 +4945,6 @@ void process_main(void)
ERTS_FP_ERROR(c_p, freg[0].fd, goto fbadarith);
NextPF(0, next);
}
-# undef ERTS_FP_CHECK_INIT
-# undef ERTS_FP_ERROR
-# define ERTS_FP_CHECK_INIT(p)
-# define ERTS_FP_ERROR(p, a, b)
#endif
@@ -4948,45 +4952,45 @@ void process_main(void)
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) + fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fsub_lll): {
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) - fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fmul_lll): {
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) * fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fdiv_lll): {
BeamInstr *next;
PreFetch(3, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(2)) = fb(Arg(0)) / fb(Arg(1));
- ERTS_FP_ERROR(c_p, fb(Arg(2)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(2)), goto fbadarith);
NextPF(3, next);
}
OpCase(i_fnegate_ll): {
BeamInstr *next;
PreFetch(2, next);
- ERTS_FP_CHECK_INIT(c_p);
+ ERTS_NO_FPE_CHECK_INIT(c_p);
fb(Arg(1)) = -fb(Arg(0));
- ERTS_FP_ERROR(c_p, fb(Arg(1)), goto fbadarith);
+ ERTS_NO_FPE_ERROR(c_p, fb(Arg(1)), goto fbadarith);
NextPF(2, next);
fbadarith:
@@ -5133,7 +5137,7 @@ void process_main(void)
if (I) {
Goto(*I);
}
- goto no_error_handler;
+ goto handle_error;
}
@@ -6064,6 +6068,12 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg)
save_calls(p, ep);
}
+#ifdef USE_VM_CALL_PROBES
+ if (DTRACE_ENABLED(global_function_entry)) {
+ BeamInstr *fptr = (BeamInstr *) ep->address;
+ DTRACE_GLOBAL_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]);
+ }
+#endif
return ep->address;
}
@@ -6113,6 +6123,12 @@ fixed_apply(Process* p, Eterm* reg, Uint arity)
save_calls(p, ep);
}
+#ifdef USE_VM_CALL_PROBES
+ if (DTRACE_ENABLED(global_function_entry)) {
+ BeamInstr *fptr = (BeamInstr *) ep->address;
+ DTRACE_GLOBAL_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]);
+ }
+#endif
return ep->address;
}
@@ -6162,6 +6178,15 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re
c_p->max_arg_reg = sizeof(c_p->def_arg_reg)/sizeof(c_p->def_arg_reg[0]);
}
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_hibernate)) {
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE);
+ dtrace_fun_decode(c_p, module, function, arity,
+ process_name, mfa);
+ DTRACE2(process_hibernate, process_name, mfa);
+ }
+#endif
/*
* Arrange for the process to be resumed at the given MFA with
* the stack cleared.
@@ -6237,6 +6262,9 @@ call_fun(Process* p, /* Current process. */
actual_arity = (int) code_ptr[-1];
if (actual_arity == arity+num_free) {
+ DTRACE_LOCAL_CALL(p, (Eterm)code_ptr[-3],
+ (Eterm)code_ptr[-2],
+ code_ptr[-1]);
if (num_free == 0) {
return code_ptr;
} else {
@@ -6254,7 +6282,7 @@ call_fun(Process* p, /* Current process. */
} else {
/*
* Something wrong here. First build a list of the arguments.
- */
+ */
if (is_non_value(args)) {
Uint sz = 2 * arity;
@@ -6329,6 +6357,7 @@ call_fun(Process* p, /* Current process. */
actual_arity = (int) ep->code[2];
if (arity == actual_arity) {
+ DTRACE_GLOBAL_CALL(p, ep->code[0], ep->code[1], (Uint)ep->code[2]);
return ep->address;
} else {
/*
@@ -6360,6 +6389,26 @@ call_fun(Process* p, /* Current process. */
if (!is_atom(module) || !is_atom(function)) {
goto badfun;
}
+
+ /*
+ * If this is the first time a tuple fun is used,
+ * send a warning to the logger.
+ */
+ if (erts_smp_atomic_xchg_nob(&warned_for_tuple_funs,
+ (erts_aint_t) 1) == 0) {
+ erts_dsprintf_buf_t* dsbufp;
+
+ dsbufp = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbufp, "Call to tuple fun {%T,%T}.\n\n"
+ "Tuple funs are deprecated and will be removed "
+ "in R16. Use \"fun M:F/A\" instead, for example "
+ "\"fun %T:%T/%d\".\n\n"
+ "(This warning will only be shown the first time "
+ "a tuple fun is called.)\n",
+ module, function, module, function, arity);
+ erts_send_warning_to_logger(p->group_leader, dsbufp);
+ }
+
if ((ep = erts_find_export_entry(module, function, arity)) == NULL) {
ep = erts_find_export_entry(erts_proc_get_error_handler(p),
am_undefined_function, 3);
@@ -6384,6 +6433,7 @@ call_fun(Process* p, /* Current process. */
reg[1] = function;
reg[2] = args;
}
+ DTRACE_GLOBAL_CALL(p, module, function, arity);
return ep->address;
} else {
badfun:
@@ -6446,10 +6496,8 @@ new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free)
hp = funp->env;
erts_refc_inc(&fe->refc, 2);
funp->thing_word = HEADER_FUN;
-#ifndef HYBRID /* FIND ME! */
funp->next = MSO(p).first;
MSO(p).first = (struct erl_off_heap_header*) funp;
-#endif
funp->fe = fe;
funp->num_free = num_free;
funp->creator = p->id;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index de4b32b238..dd788df6e4 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -206,6 +206,7 @@ typedef struct {
Eterm term; /* The tagged term (in the heap). */
Uint heap_size; /* (Exact) size on the heap. */
Uint offset; /* Offset from temporary location to final. */
+ ErlOffHeap off_heap; /* Start of linked list of ProcBins. */
Eterm* heap; /* Heap for term. */
} Literal;
@@ -245,7 +246,7 @@ typedef struct {
* This structure contains all information about the module being loaded.
*/
-typedef struct {
+typedef struct LoaderState {
/*
* The current logical file within the binary.
*/
@@ -253,6 +254,7 @@ typedef struct {
char* file_name; /* Name of file we are reading (usually chunk name). */
byte* file_p; /* Current pointer within file. */
unsigned file_left; /* Number of bytes left in file. */
+ ErlDrvBinary* bin; /* Binary holding BEAM file (or NULL) */
/*
* The following are used mainly for diagnostics.
@@ -287,7 +289,6 @@ typedef struct {
BeamInstr* code; /* Loaded code. */
int ci; /* Current index into loaded code. */
Label* labels;
- BeamInstr new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */
StringPatch* string_patches; /* Linked list of position into string table to patch. */
BeamInstr catches; /* Linked list of catch_yf instructions. */
unsigned loaded_size; /* Final size of code when loaded. */
@@ -351,11 +352,6 @@ typedef struct {
int loc_size; /* Size of location info in bytes (2/4) */
} LoaderState;
-typedef struct {
- unsigned num_functions; /* Number of functions. */
- Eterm* func_tab[1]; /* Pointers to each function. */
-} LoadedCode;
-
/*
* Layout of the line table.
*/
@@ -500,14 +496,14 @@ typedef struct {
} while (0)
-static int bin_load(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size);
-static void init_state(LoaderState* stp);
-static int insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module,
- BeamInstr* code, Uint size, BeamInstr catches);
+static void free_state(LoaderState* stp);
+static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
+ Eterm group_leader, Eterm module,
+ BeamInstr* code, Uint size);
+static int init_iff_file(LoaderState* stp, byte* code, Uint size);
static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
Uint num_types, Uint num_mandatory);
+static int verify_chunks(LoaderState* stp);
static int load_atom_table(LoaderState* stp);
static int load_import_table(LoaderState* stp);
static int read_export_table(LoaderState* stp);
@@ -598,7 +594,7 @@ define_file(LoaderState* stp, char* name, int idx)
stp->file_left = stp->chunks[idx].size;
}
-int
+Eterm
erts_load_module(Process *c_p,
ErtsProcLocks c_p_locks,
Eterm group_leader, /* Group leader or NIL if none. */
@@ -607,29 +603,17 @@ erts_load_module(Process *c_p,
* On return, contains the actual module name.
*/
byte* code, /* Points to the code to load */
- int size) /* Size of code to load. */
+ Uint size) /* Size of code to load. */
{
- ErlDrvBinary* bin;
- int result;
+ LoaderState* stp = erts_alloc_loader_state();
+ Eterm retval;
- if (size >= 4 && code[0] == 'F' && code[1] == 'O' &&
- code[2] == 'R' && code[3] == '1') {
- /*
- * The BEAM module is not compressed.
- */
- result = bin_load(c_p, c_p_locks, group_leader, modp, code, size);
- } else {
- /*
- * The BEAM module is compressed (or possibly invalid/corrupted).
- */
- if ((bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size)) == NULL) {
- return -1;
- }
- result = bin_load(c_p, c_p_locks, group_leader, modp,
- (byte*)bin->orig_bytes, bin->orig_size);
- driver_free_binary(bin);
+ retval = erts_prepare_loading(stp, c_p, group_leader, modp,
+ code, size);
+ if (retval != NIL) {
+ return retval;
}
- return result;
+ return erts_finish_loading(stp, c_p, c_p_locks, modp);
}
/* #define LOAD_MEMORY_HARD_DEBUG 1*/
@@ -644,31 +628,28 @@ extern void check_allocated_block(Uint type, void *blk);
#define CHKBLK(TYPE,BLK) /* nothing */
#endif
-static int
-bin_load(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size)
+Eterm
+erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader,
+ Eterm* modp, byte* code, Uint unloaded_size)
{
- LoaderState state;
- int rval = -1;
+ Eterm retval = am_badfile;
- init_state(&state);
- state.module = *modp;
- state.group_leader = group_leader;
-
- /*
- * Scan the IFF file.
- */
+ stp->module = *modp;
+ stp->group_leader = group_leader;
#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
erts_fprintf(stderr,"Loading a module\n");
#endif
+ /*
+ * Scan the IFF file.
+ */
+
CHKALLOC();
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- state.file_name = "IFF header for Beam file";
- state.file_p = bytes;
- state.file_left = unloaded_size;
- if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (!init_iff_file(stp, code, unloaded_size) ||
+ !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) ||
+ !verify_chunks(stp)) {
goto load_error;
}
@@ -676,38 +657,38 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the header for the code chunk.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "code chunk header", CODE_CHUNK);
- if (!read_code_header(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "code chunk header", CODE_CHUNK);
+ if (!read_code_header(stp)) {
goto load_error;
}
/*
* Initialize code area.
*/
- state.code_buffer_size = erts_next_heap_size(2048 + state.num_functions, 0);
- state.code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
- sizeof(BeamInstr) * state.code_buffer_size);
+ stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0);
+ stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
+ sizeof(BeamInstr) * stp->code_buffer_size);
- state.code[MI_NUM_FUNCTIONS] = state.num_functions;
- state.ci = MI_FUNCTIONS + state.num_functions + 1;
+ stp->code[MI_NUM_FUNCTIONS] = stp->num_functions;
+ stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
- state.code[MI_ATTR_PTR] = 0;
- state.code[MI_ATTR_SIZE] = 0;
- state.code[MI_ATTR_SIZE_ON_HEAP] = 0;
- state.code[MI_COMPILE_PTR] = 0;
- state.code[MI_COMPILE_SIZE] = 0;
- state.code[MI_COMPILE_SIZE_ON_HEAP] = 0;
- state.code[MI_NUM_BREAKPOINTS] = 0;
+ stp->code[MI_ATTR_PTR] = 0;
+ stp->code[MI_ATTR_SIZE] = 0;
+ stp->code[MI_ATTR_SIZE_ON_HEAP] = 0;
+ stp->code[MI_COMPILE_PTR] = 0;
+ stp->code[MI_COMPILE_SIZE] = 0;
+ stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
+ stp->code[MI_NUM_BREAKPOINTS] = 0;
/*
* Read the atom table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "atom table", ATOM_CHUNK);
- if (!load_atom_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "atom table", ATOM_CHUNK);
+ if (!load_atom_table(stp)) {
goto load_error;
}
@@ -715,9 +696,9 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the import table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "import table", IMP_CHUNK);
- if (!load_import_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "import table", IMP_CHUNK);
+ if (!load_import_table(stp)) {
goto load_error;
}
@@ -725,10 +706,10 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the lambda (fun) table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (state.chunks[LAMBDA_CHUNK].size > 0) {
- define_file(&state, "lambda (fun) table", LAMBDA_CHUNK);
- if (!read_lambda_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (stp->chunks[LAMBDA_CHUNK].size > 0) {
+ define_file(stp, "lambda (fun) table", LAMBDA_CHUNK);
+ if (!read_lambda_table(stp)) {
goto load_error;
}
}
@@ -737,10 +718,10 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the literal table.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (state.chunks[LITERAL_CHUNK].size > 0) {
- define_file(&state, "literals table (constant pool)", LITERAL_CHUNK);
- if (!read_literal_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (stp->chunks[LITERAL_CHUNK].size > 0) {
+ define_file(stp, "literals table (constant pool)", LITERAL_CHUNK);
+ if (!read_literal_table(stp)) {
goto load_error;
}
}
@@ -749,10 +730,10 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the line table (if present).
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (state.chunks[LINE_CHUNK].size > 0) {
- define_file(&state, "line table", LINE_CHUNK);
- if (!read_line_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (stp->chunks[LINE_CHUNK].size > 0) {
+ define_file(stp, "line table", LINE_CHUNK);
+ if (!read_line_table(stp)) {
goto load_error;
}
}
@@ -761,15 +742,15 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Load the code chunk.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- state.file_name = "code chunk";
- state.file_p = state.code_start;
- state.file_left = state.code_size;
- if (!load_code(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ stp->file_name = "code chunk";
+ stp->file_p = stp->code_start;
+ stp->file_left = stp->code_size;
+ if (!load_code(stp)) {
goto load_error;
}
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- if (!freeze_code(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ if (!freeze_code(stp)) {
goto load_error;
}
@@ -779,9 +760,49 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* loading the code, because it contains labels.)
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- define_file(&state, "export table", EXP_CHUNK);
- if (!read_export_table(&state)) {
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ define_file(stp, "export table", EXP_CHUNK);
+ if (!read_export_table(stp)) {
+ goto load_error;
+ }
+
+ /*
+ * Good so far.
+ */
+
+ retval = NIL;
+
+ load_error:
+ if (retval != NIL) {
+ free_state(stp);
+ }
+ return retval;
+}
+
+Eterm
+erts_finish_loading(LoaderState* stp, Process* c_p,
+ ErtsProcLocks c_p_locks, Eterm* modp)
+{
+ Eterm retval;
+
+ /*
+ * No other process may run since we will update the export
+ * table which is not protected by any locks.
+ */
+
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0 ||
+ erts_smp_thr_progress_is_blocking());
+
+ /*
+ * Make current code for the module old and insert the new code
+ * as current. This will fail if there already exists old code
+ * for the module.
+ */
+
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ retval = insert_new_code(c_p, c_p_locks, stp->group_leader, stp->module,
+ stp->code, stp->loaded_size);
+ if (retval != NIL) {
goto load_error;
}
@@ -790,104 +811,43 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* exported and imported functions. This can't fail.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- rval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module,
- state.code, state.loaded_size, state.catches);
- if (rval < 0) {
- goto load_error;
- }
- CHKBLK(ERTS_ALC_T_CODE,state.code);
- final_touch(&state);
+ erts_export_consolidate();
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
+ final_touch(stp);
/*
* Loading succeded.
*/
- CHKBLK(ERTS_ALC_T_CODE,state.code);
+ CHKBLK(ERTS_ALC_T_CODE,stp->code);
#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
erts_fprintf(stderr,"Loaded %T\n",*modp);
#if 0
- debug_dump_code(state.code,state.ci);
+ debug_dump_code(stp->code,stp->ci);
#endif
#endif
- rval = 0;
- state.code = NULL; /* Prevent code from being freed. */
- *modp = state.module;
+ stp->code = NULL; /* Prevent code from being freed. */
+ *modp = stp->module;
/*
* If there is an on_load function, signal an error to
* indicate that the on_load function must be run.
*/
- if (state.on_load) {
- rval = -5;
+ if (stp->on_load) {
+ retval = am_on_load;
}
load_error:
- if (state.code != 0) {
- erts_free(ERTS_ALC_T_CODE, state.code);
- }
- if (state.labels != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels);
- }
- if (state.atom != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom);
- }
- if (state.import != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.import);
- }
- if (state.export != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export);
- }
- if (state.lambdas != state.def_lambdas) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas);
- }
- if (state.literals != NULL) {
- int i;
- for (i = 0; i < state.num_literals; i++) {
- if (state.literals[i].heap != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literals[i].heap);
- }
- }
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literals);
- }
- while (state.literal_patches != NULL) {
- LiteralPatch* next = state.literal_patches->next;
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literal_patches);
- state.literal_patches = next;
- }
- while (state.string_patches != NULL) {
- StringPatch* next = state.string_patches->next;
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.string_patches);
- state.string_patches = next;
- }
- while (state.genop_blocks) {
- GenOpBlock* next = state.genop_blocks->next;
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.genop_blocks);
- state.genop_blocks = next;
- }
-
- if (state.line_item != 0) {
- erts_free(ERTS_ALC_T_LOADER_TMP, state.line_item);
- }
-
- if (state.line_instr != 0) {
- erts_free(ERTS_ALC_T_LOADER_TMP, state.line_instr);
- }
-
- if (state.func_line != 0) {
- erts_free(ERTS_ALC_T_LOADER_TMP, state.func_line);
- }
-
- if (state.fname != 0) {
- erts_free(ERTS_ALC_T_LOADER_TMP, state.fname);
- }
-
- return rval;
+ free_state(stp);
+ return retval;
}
-
-static void
-init_state(LoaderState* stp)
+LoaderState*
+erts_alloc_loader_state(void)
{
+ LoaderState* stp;
+
+ stp = erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(LoaderState));
+ stp->bin = NULL;
stp->function = THE_NON_VALUE; /* Function not known yet */
stp->arity = 0;
stp->specific_op = -1;
@@ -915,23 +875,94 @@ init_state(LoaderState* stp)
stp->line_instr = 0;
stp->func_line = 0;
stp->fname = 0;
+ return stp;
}
-static int
+static void
+free_state(LoaderState* stp)
+{
+ if (stp->bin != 0) {
+ driver_free_binary(stp->bin);
+ }
+ if (stp->code != 0) {
+ erts_free(ERTS_ALC_T_CODE, stp->code);
+ }
+ if (stp->labels != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->labels);
+ }
+ if (stp->atom != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->atom);
+ }
+ if (stp->import != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->import);
+ }
+ if (stp->export != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->export);
+ }
+ if (stp->lambdas != stp->def_lambdas) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->lambdas);
+ }
+ if (stp->literals != NULL) {
+ int i;
+ for (i = 0; i < stp->num_literals; i++) {
+ if (stp->literals[i].heap != NULL) {
+ erts_free(ERTS_ALC_T_LOADER_TMP,
+ (void *) stp->literals[i].heap);
+ }
+ }
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->literals);
+ }
+ while (stp->literal_patches != NULL) {
+ LiteralPatch* next = stp->literal_patches->next;
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->literal_patches);
+ stp->literal_patches = next;
+ }
+ while (stp->string_patches != NULL) {
+ StringPatch* next = stp->string_patches->next;
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->string_patches);
+ stp->string_patches = next;
+ }
+ while (stp->genop_blocks) {
+ GenOpBlock* next = stp->genop_blocks->next;
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->genop_blocks);
+ stp->genop_blocks = next;
+ }
+
+ if (stp->line_item != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->line_item);
+ }
+
+ if (stp->line_instr != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->line_instr);
+ }
+
+ if (stp->func_line != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->func_line);
+ }
+
+ if (stp->fname != 0) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname);
+ }
+
+ erts_free(ERTS_ALC_T_LOADER_TMP, stp);
+}
+
+static Eterm
insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches)
+ Eterm group_leader, Eterm module, BeamInstr* code,
+ Uint size)
{
Module* modp;
- int rval;
+ Eterm retval;
int i;
- if ((rval = beam_make_current_old(c_p, c_p_locks, module)) < 0) {
+ if ((retval = beam_make_current_old(c_p, c_p_locks, module)) != NIL) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp,
"Module %T must be purged before loading\n",
module);
erts_send_error_to_logger(group_leader, dsbufp);
- return rval;
+ return retval;
}
/*
@@ -942,7 +973,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
modp = erts_put_module(module);
modp->code = code;
modp->code_length = size;
- modp->catches = catches;
+ modp->catches = BEAM_CATCHES_NIL; /* Will be filled in later. */
/*
* Update address table (used for finding a function from a PC value).
@@ -964,27 +995,51 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
modules[i].end = (BeamInstr *) (((byte *)code) + size);
num_loaded_modules++;
mid_module = &modules[num_loaded_modules/2];
- return 0;
+ return NIL;
}
static int
-scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory)
+init_iff_file(LoaderState* stp, byte* code, Uint size)
{
- MD5_CTX context;
+ Uint form_id = MakeIffId('F', 'O', 'R', '1');
Uint id;
Uint count;
- int i;
+
+ if (size < 4) {
+ goto load_error;
+ }
/*
- * The binary must start with an IFF 'FOR1' chunk.
+ * Check if the module is compressed (or possibly invalid/corrupted).
*/
+ if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) {
+ stp->bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size);
+ if (stp->bin == NULL) {
+ goto load_error;
+ }
+ code = (byte*)stp->bin->orig_bytes;
+ size = stp->bin->orig_size;
+ if (size < 4) {
+ goto load_error;
+ }
+ }
- GetInt(stp, 4, id);
- if (id != MakeIffId('F', 'O', 'R', '1')) {
+ /*
+ * The binary must start with an IFF 'FOR1' chunk.
+ */
+ if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) {
LoadError0(stp, "not a BEAM file: no IFF 'FOR1' chunk");
}
/*
+ * Initialize our "virtual file system".
+ */
+
+ stp->file_name = "IFF header for Beam file";
+ stp->file_p = code + 4;
+ stp->file_left = size - 4;
+
+ /*
* Retrieve the chunk size and verify it. If the size is equal to
* or less than the size of the binary, it is ok and we will use it
* as the limit for the logical file size.
@@ -1005,6 +1060,21 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand
if (id != MakeIffId('B', 'E', 'A', 'M')) {
LoadError0(stp, "not a BEAM file: IFF form type is not 'BEAM'");
}
+ return 1;
+
+ load_error:
+ return 0;
+}
+
+/*
+ * Scan the IFF file. The header should have been verified by init_iff_file().
+ */
+static int
+scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory)
+{
+ Uint count;
+ Uint id;
+ int i;
/*
* Initialize the chunks[] array in the state.
@@ -1061,17 +1131,25 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand
stp->file_p += count;
stp->file_left -= count;
}
+ return 1;
- /*
- * At this point, we have read the entire IFF file, and we
- * know that it is syntactically correct.
- *
- * Now check that it contains all mandatory chunks. At the
- * same time calculate the MD5 for the module.
- */
+ load_error:
+ return 0;
+}
+
+/*
+ * Verify that all mandatory chunks are present and calculate
+ * MD5 for the module.
+ */
+
+static int
+verify_chunks(LoaderState* stp)
+{
+ int i;
+ MD5_CTX context;
MD5Init(&context);
- for (i = 0; i < num_mandatory; i++) {
+ for (i = 0; i < NUM_MANDATORY; i++) {
if (stp->chunks[i].start != NULL) {
MD5Update(&context, stp->chunks[i].start, stp->chunks[i].size);
} else {
@@ -1081,41 +1159,49 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand
LoadError1(stp, "mandatory chunk of type '%s' not found\n", sbuf);
}
}
- if (LITERAL_CHUNK < num_types) {
- if (stp->chunks[LAMBDA_CHUNK].start != 0) {
- byte* start = stp->chunks[LAMBDA_CHUNK].start;
- Uint left = stp->chunks[LAMBDA_CHUNK].size;
- /*
- * The idea here is to ignore the OldUniq field for the fun; it is
- * based on the old broken hash function, which can be different
- * on little endian and big endian machines.
- */
- if (left >= 4) {
- static byte zero[4];
- MD5Update(&context, start, 4);
- start += 4;
- left -= 4;
+ /*
+ * If there is a lambda chunk, include parts of it in the MD5.
+ */
+ if (stp->chunks[LAMBDA_CHUNK].start != 0) {
+ byte* start = stp->chunks[LAMBDA_CHUNK].start;
+ Uint left = stp->chunks[LAMBDA_CHUNK].size;
+
+ /*
+ * The idea here is to ignore the OldUniq field for the fun; it is
+ * based on the old broken hash function, which can be different
+ * on little endian and big endian machines.
+ */
+ if (left >= 4) {
+ static byte zero[4];
+ MD5Update(&context, start, 4);
+ start += 4;
+ left -= 4;
- while (left >= 24) {
- /* Include: Function Arity Index NumFree */
- MD5Update(&context, start, 20);
- /* Set to zero: OldUniq */
- MD5Update(&context, zero, 4);
- start += 24;
- left -= 24;
- }
- }
- /* Can't happen for a correct 'FunT' chunk */
- if (left > 0) {
- MD5Update(&context, start, left);
+ while (left >= 24) {
+ /* Include: Function Arity Index NumFree */
+ MD5Update(&context, start, 20);
+ /* Set to zero: OldUniq */
+ MD5Update(&context, zero, 4);
+ start += 24;
+ left -= 24;
}
}
- if (stp->chunks[LITERAL_CHUNK].start != 0) {
- MD5Update(&context, stp->chunks[LITERAL_CHUNK].start,
- stp->chunks[LITERAL_CHUNK].size);
+ /* Can't happen for a correct 'FunT' chunk */
+ if (left > 0) {
+ MD5Update(&context, start, left);
}
}
+
+
+ /*
+ * If there is a literal chunk, include it in the MD5.
+ */
+ if (stp->chunks[LITERAL_CHUNK].start != 0) {
+ MD5Update(&context, stp->chunks[LITERAL_CHUNK].start,
+ stp->chunks[LITERAL_CHUNK].size);
+ }
+
MD5Final(stp->mod_md5, &context);
return 1;
@@ -1348,7 +1434,7 @@ static int
read_literal_table(LoaderState* stp)
{
int i;
- BeamInstr uncompressed_sz;
+ uLongf uncompressed_sz;
byte* uncompressed = 0;
GetInt(stp, 4, uncompressed_sz);
@@ -1358,7 +1444,7 @@ read_literal_table(LoaderState* stp)
LoadError0(stp, "failed to uncompress literal table (constant pool)");
}
stp->file_p = uncompressed;
- stp->file_left = uncompressed_sz;
+ stp->file_left = (unsigned) uncompressed_sz;
GetInt(stp, 4, stp->num_literals);
stp->literals = (Literal *) erts_alloc(ERTS_ALC_T_LOADER_TMP,
stp->num_literals * sizeof(Literal));
@@ -1377,12 +1463,14 @@ read_literal_table(LoaderState* stp)
GetInt(stp, 4, sz); /* Size of external term format. */
GetString(stp, p, sz);
- if ((heap_size = erts_decode_ext_size(p, sz, 1)) < 0) {
+ if ((heap_size = erts_decode_ext_size(p, sz)) < 0) {
LoadError1(stp, "literal %d: bad external format", i);
}
hp = stp->literals[i].heap = erts_alloc(ERTS_ALC_T_LOADER_TMP,
heap_size*sizeof(Eterm));
- val = erts_decode_ext(&hp, NULL, &p);
+ stp->literals[i].off_heap.first = 0;
+ stp->literals[i].off_heap.overhead = 0;
+ val = erts_decode_ext(&hp, &stp->literals[i].off_heap, &p);
stp->literals[i].heap_size = hp - stp->literals[i].heap;
if (stp->literals[i].heap_size > heap_size) {
erl_exit(1, "overrun by %d word(s) for literal heap, term %d",
@@ -1408,7 +1496,7 @@ static int
read_line_table(LoaderState* stp)
{
unsigned version;
- unsigned flags;
+ ERTS_DECLARE_DUMMY(unsigned flags);
int num_line_items;
BeamInstr* lp;
int i;
@@ -1570,10 +1658,15 @@ read_code_header(LoaderState* stp)
/*
* Verify the number of the highest opcode used.
*/
-
GetInt(stp, 4, opcode_max);
if (opcode_max > MAX_GENERIC_OPCODE) {
- LoadError2(stp, "use of opcode %d; this emulator supports only up to %d",
+ LoadError2(stp,
+ "This BEAM file was compiled for a later version"
+ " of the run-time system than " ERLANG_OTP_RELEASE ".\n"
+ " To fix this, please recompile this module with an "
+ ERLANG_OTP_RELEASE " compiler.\n"
+ " (Use of opcode %d; this emulator supports "
+ "only up to %d.)",
opcode_max, MAX_GENERIC_OPCODE);
}
@@ -1594,7 +1687,6 @@ read_code_header(LoaderState* stp)
#endif
}
- stp->new_bs_put_strings = 0;
stp->catches = 0;
return 1;
@@ -2306,32 +2398,6 @@ load_code(LoaderState* stp)
stp->on_load = ci;
break;
case op_bs_put_string_II:
- {
- /*
- * At entry:
- *
- * code[ci-3] &&lb_i_new_bs_put_string_II
- * code[ci-2] length of string
- * code[ci-1] offset into string table
- *
- * Since we don't know the address of the string table yet,
- * just check the offset and length for validity, and use
- * the instruction field as a link field to link all put_string
- * instructions into a single linked list. At exit:
- *
- * code[ci-3] pointer to next i_new_bs_put_string instruction (or 0
- * if this is the last)
- */
- Uint offset = code[ci-1];
- Uint len = code[ci-2];
- unsigned strtab_size = stp->chunks[STR_CHUNK].size;
- if (offset > strtab_size || offset + len > strtab_size) {
- LoadError2(stp, "invalid string reference %d, size %d", offset, len);
- }
- code[ci-3] = stp->new_bs_put_strings;
- stp->new_bs_put_strings = ci - 3;
- }
- break;
case op_i_bs_match_string_rfII:
case op_i_bs_match_string_xfII:
new_string_patch(stp, ci-1);
@@ -3434,7 +3500,6 @@ gen_jump_tab(LoaderState* stp, GenOpArg S, GenOpArg Fail, GenOpArg Size, GenOpAr
}
size = max - min + 1;
-
/*
* Allocate structure and fill in the fixed fields.
*/
@@ -3466,7 +3531,7 @@ gen_jump_tab(LoaderState* stp, GenOpArg S, GenOpArg Fail, GenOpArg Size, GenOpAr
op->a[i] = Fail;
}
for (i = 0; i < Size.val; i += 2) {
- int index;
+ Sint index;
index = fixed_args+Rest[i].val-min;
ASSERT(fixed_args <= index && index < arity);
op->a[index] = Rest[i+1];
@@ -3868,14 +3933,12 @@ freeze_code(LoaderState* stp)
{
BeamInstr* code = stp->code;
Uint *literal_end = NULL;
- Uint index;
int i;
byte* str_table;
unsigned strtab_size = stp->chunks[STR_CHUNK].size;
unsigned attr_size = stp->chunks[ATTR_CHUNK].size;
unsigned compile_size = stp->chunks[COMPILE_CHUNK].size;
Uint size;
- unsigned catches;
Sint decoded_size;
Uint line_size;
@@ -3937,6 +4000,8 @@ freeze_code(LoaderState* stp)
Uint* low;
Uint* high;
LiteralPatch* lp;
+ struct erl_off_heap_header* off_heap = 0;
+ struct erl_off_heap_header** off_heap_last = &off_heap;
low = (Uint *) (code+stp->ci);
high = low + stp->total_literal_size;
@@ -3945,6 +4010,7 @@ freeze_code(LoaderState* stp)
ptr = low;
for (i = 0; i < stp->num_literals; i++) {
Uint offset;
+ struct erl_off_heap_header* t_off_heap;
sys_memcpy(ptr, stp->literals[i].heap,
stp->literals[i].heap_size*sizeof(Eterm));
@@ -3959,9 +4025,19 @@ freeze_code(LoaderState* stp)
*ptr++ = offset_ptr(val, offset);
break;
case TAG_PRIMARY_HEADER:
- ptr++;
- if (header_is_thing(val)) {
- ptr += thing_arityval(val);
+ if (header_is_transparent(val)) {
+ ptr++;
+ } else {
+ if (thing_subtag(val) == REFC_BINARY_SUBTAG) {
+ struct erl_off_heap_header* oh;
+
+ oh = (struct erl_off_heap_header*) ptr;
+ if (oh->next) {
+ Eterm** uptr = (Eterm **) (void *) &oh->next;
+ *uptr += offset;
+ }
+ }
+ ptr += 1 + thing_arityval(val);
}
break;
default:
@@ -3970,7 +4046,23 @@ freeze_code(LoaderState* stp)
}
}
ASSERT(ptr == high);
+
+ /*
+ * Re-link the off_heap list for this term onto the
+ * off_heap list for the entire module.
+ */
+ t_off_heap = stp->literals[i].off_heap.first;
+ if (t_off_heap) {
+ t_off_heap = (struct erl_off_heap_header *)
+ offset_ptr((UWord) t_off_heap, offset);
+ while (t_off_heap) {
+ *off_heap_last = t_off_heap;
+ off_heap_last = &t_off_heap->next;
+ t_off_heap = t_off_heap->next;
+ }
+ }
}
+ code[MI_LITERALS_OFF_HEAP] = (BeamInstr) off_heap;
lp = stp->literal_patches;
while (lp != 0) {
BeamInstr* op_ptr;
@@ -4053,7 +4145,7 @@ freeze_code(LoaderState* stp)
sys_memcpy(attr, stp->chunks[ATTR_CHUNK].start, stp->chunks[ATTR_CHUNK].size);
code[MI_ATTR_PTR] = (BeamInstr) attr;
code[MI_ATTR_SIZE] = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
- decoded_size = erts_decode_ext_size(attr, attr_size, 0);
+ decoded_size = erts_decode_ext_size(attr, attr_size);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of module attributes");
}
@@ -4071,7 +4163,7 @@ freeze_code(LoaderState* stp)
CHKBLK(ERTS_ALC_T_CODE,code);
code[MI_COMPILE_SIZE] = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
CHKBLK(ERTS_ALC_T_CODE,code);
- decoded_size = erts_decode_ext_size(compile_info, compile_size, 0);
+ decoded_size = erts_decode_ext_size(compile_info, compile_size);
CHKBLK(ERTS_ALC_T_CODE,code);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of compilation information");
@@ -4088,20 +4180,8 @@ freeze_code(LoaderState* stp)
((byte *) code) + size);
/*
- * Go through all i_new_bs_put_strings instructions, restore the pointer to
- * the instruction and convert string offsets to pointers (to the
- * FIRST character).
+ * Patch all instructions that refer to the string table.
*/
-
- index = stp->new_bs_put_strings;
- while (index != 0) {
- Uint next = code[index];
- code[index] = BeamOpCode(op_bs_put_string_II);
- code[index+2] = (BeamInstr) (str_table + code[index+2]);
- index = next;
- }
- CHKBLK(ERTS_ALC_T_CODE,code);
-
{
StringPatch* sp = stp->string_patches;
@@ -4142,21 +4222,6 @@ freeze_code(LoaderState* stp)
CHKBLK(ERTS_ALC_T_CODE,code);
/*
- * Fix all catch_yf instructions.
- */
- index = stp->catches;
- catches = BEAM_CATCHES_NIL;
- while (index != 0) {
- BeamInstr next = code[index];
- code[index] = BeamOpCode(op_catch_yf);
- catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
- code[index+2] = make_catch(catches);
- index = next;
- }
- stp->catches = catches;
- CHKBLK(ERTS_ALC_T_CODE,code);
-
- /*
* Save the updated code pointer and code size.
*/
@@ -4181,6 +4246,26 @@ final_touch(LoaderState* stp)
{
int i;
int on_load = stp->on_load;
+ unsigned catches;
+ Uint index;
+ BeamInstr* code = stp->code;
+ Module* modp;
+
+ /*
+ * Allocate catch indices and fix up all catch_yf instructions.
+ */
+
+ index = stp->catches;
+ catches = BEAM_CATCHES_NIL;
+ while (index != 0) {
+ BeamInstr next = code[index];
+ code[index] = BeamOpCode(op_catch_yf);
+ catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
+ code[index+2] = make_catch(catches);
+ index = next;
+ }
+ modp = erts_put_module(stp->module);
+ modp->catches = catches;
/*
* Export functions.
@@ -4897,6 +4982,8 @@ new_literal(LoaderState* stp, Eterm** hpp, Uint heap_size)
lit->heap_size = heap_size;
lit->heap = erts_alloc(ERTS_ALC_T_LOADER_TMP, heap_size*sizeof(Eterm));
lit->term = make_boxed(lit->heap);
+ lit->off_heap.first = 0;
+ lit->off_heap.overhead = 0;
*hpp = lit->heap;
return stp->num_literals++;
}
@@ -5356,10 +5443,13 @@ find_function_from_pc(BeamInstr* pc)
* Read a specific chunk from a Beam binary.
*/
-Eterm
-code_get_chunk_2(Process* p, Eterm Bin, Eterm Chunk)
+BIF_RETTYPE
+code_get_chunk_2(BIF_ALIST_2)
{
- LoaderState state;
+ Process* p = BIF_P;
+ Eterm Bin = BIF_ARG_1;
+ Eterm Chunk = BIF_ARG_2;
+ LoaderState* stp;
Uint chunk = 0;
ErlSubBin* sb;
Uint offset;
@@ -5371,15 +5461,16 @@ code_get_chunk_2(Process* p, Eterm Bin, Eterm Chunk)
Eterm real_bin;
byte* temp_alloc = NULL;
+ stp = erts_alloc_loader_state();
if ((start = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) {
error:
erts_free_aligned_binary_bytes(temp_alloc);
+ if (stp) {
+ free_state(stp);
+ }
BIF_ERROR(p, BADARG);
}
- state.module = THE_NON_VALUE; /* Suppress diagnostiscs */
- state.file_name = "IFF header for Beam file";
- state.file_p = start;
- state.file_left = binary_size(Bin);
+ stp->module = THE_NON_VALUE; /* Suppress diagnostics */
for (i = 0; i < 4; i++) {
Eterm* chunkp;
Eterm num;
@@ -5397,25 +5488,30 @@ code_get_chunk_2(Process* p, Eterm Bin, Eterm Chunk)
if (is_not_nil(Chunk)) {
goto error;
}
- if (!scan_iff_file(&state, &chunk, 1, 1)) {
- erts_free_aligned_binary_bytes(temp_alloc);
- return am_undefined;
+ if (!init_iff_file(stp, start, binary_size(Bin)) ||
+ !scan_iff_file(stp, &chunk, 1, 1) ||
+ stp->chunks[0].start == NULL) {
+ res = am_undefined;
+ goto done;
}
ERTS_GET_REAL_BIN(Bin, real_bin, offset, bitoffs, bitsize);
if (bitoffs) {
- res = new_binary(p, state.chunks[0].start, state.chunks[0].size);
+ res = new_binary(p, stp->chunks[0].start, stp->chunks[0].size);
} else {
sb = (ErlSubBin *) HAlloc(p, ERL_SUB_BIN_SIZE);
sb->thing_word = HEADER_SUB_BIN;
sb->orig = real_bin;
- sb->size = state.chunks[0].size;
+ sb->size = stp->chunks[0].size;
sb->bitsize = 0;
sb->bitoffs = 0;
- sb->offs = offset + (state.chunks[0].start - start);
+ sb->offs = offset + (stp->chunks[0].start - start);
sb->is_writable = 0;
res = make_binary(sb);
}
+
+ done:
erts_free_aligned_binary_bytes(temp_alloc);
+ free_state(stp);
return res;
}
@@ -5423,24 +5519,34 @@ code_get_chunk_2(Process* p, Eterm Bin, Eterm Chunk)
* Calculate the MD5 for a module.
*/
-Eterm
-code_module_md5_1(Process* p, Eterm Bin)
+BIF_RETTYPE
+code_module_md5_1(BIF_ALIST_1)
{
- LoaderState state;
+ Process* p = BIF_P;
+ Eterm Bin = BIF_ARG_1;
+ LoaderState* stp;
+ byte* bytes;
byte* temp_alloc = NULL;
+ Eterm res;
- if ((state.file_p = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) {
+ stp = erts_alloc_loader_state();
+ if ((bytes = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) {
+ free_state(stp);
BIF_ERROR(p, BADARG);
}
- state.module = THE_NON_VALUE; /* Suppress diagnostiscs */
- state.file_name = "IFF header for Beam file";
- state.file_left = binary_size(Bin);
-
- if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
- return am_undefined;
+ stp->module = THE_NON_VALUE; /* Suppress diagnostiscs */
+ if (!init_iff_file(stp, bytes, binary_size(Bin)) ||
+ !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) ||
+ !verify_chunks(stp)) {
+ res = am_undefined;
+ goto done;
}
+ res = new_binary(p, stp->mod_md5, sizeof(stp->mod_md5));
+
+ done:
erts_free_aligned_binary_bytes(temp_alloc);
- return new_binary(p, state.mod_md5, sizeof(state.mod_md5));
+ free_state(stp);
+ return res;
}
#define WORDS_PER_FUNCTION 6
@@ -5475,7 +5581,7 @@ stub_copy_info(LoaderState* stp,
if (size != 0) {
memcpy(info, stp->chunks[chunk].start, size);
*ptr_word = (BeamInstr) info;
- decoded_size = erts_decode_ext_size(info, size, 0);
+ decoded_size = erts_decode_ext_size(info, size);
if (decoded_size < 0) {
return 0;
}
@@ -5682,7 +5788,17 @@ patch_funentries(Eterm Patchlist)
fe = erts_get_fun_entry(Mod, uniq, index);
fe->native_address = (Uint *)native_address;
- erts_refc_dec(&fe->refc, 1);
+
+ /* Deliberate MEMORY LEAK of native fun entries!!!
+ *
+ * Uncomment line below when hipe code upgrade and purging works correctly.
+ * Today we may get cases when old (leaked) native code of a purged module
+ * gets called and tries to create instances of a deleted fun entry.
+ *
+ * Reproduced on a debug emulator with stdlib_test/qlc_SUITE:join_merge
+ *
+ * erts_refc_dec(&fe->refc, 1);
+ */
if (!patch(Addresses, (Uint) fe))
return 0;
@@ -5703,7 +5819,7 @@ patch_funentries(Eterm Patchlist)
Eterm
erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
{
- LoaderState state;
+ LoaderState* stp;
BeamInstr Funcs;
BeamInstr Patchlist;
Eterm* tp;
@@ -5716,16 +5832,15 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
int code_size;
int rval;
int i;
- ErlDrvBinary* bin = NULL;
byte* temp_alloc = NULL;
byte* bytes;
Uint size;
/*
- * Must initialize state.lambdas here because the error handling code
+ * Must initialize stp->lambdas here because the error handling code
* at label 'error' uses it.
*/
- init_state(&state);
+ stp = erts_alloc_loader_state();
if (is_not_atom(Mod)) {
goto error;
@@ -5749,47 +5864,35 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
size = binary_size(Beam);
/*
- * Uncompressed if needed.
- */
- if (!(size >= 4 && bytes[0] == 'F' && bytes[1] == 'O' &&
- bytes[2] == 'R' && bytes[3] == '1')) {
- bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)bytes, size);
- if (bin == NULL) {
- goto error;
- }
- bytes = (byte*)bin->orig_bytes;
- size = bin->orig_size;
- }
-
- /*
* Scan the Beam binary and read the interesting sections.
*/
- state.file_name = "IFF header for Beam file";
- state.file_p = bytes;
- state.file_left = size;
- state.module = Mod;
- state.group_leader = p->group_leader;
- state.num_functions = n;
- if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) {
+ stp->module = Mod;
+ stp->group_leader = p->group_leader;
+ stp->num_functions = n;
+ if (!init_iff_file(stp, bytes, size)) {
goto error;
}
- define_file(&state, "code chunk header", CODE_CHUNK);
- if (!read_code_header(&state)) {
+ if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) ||
+ !verify_chunks(stp)) {
goto error;
}
- define_file(&state, "atom table", ATOM_CHUNK);
- if (!load_atom_table(&state)) {
+ define_file(stp, "code chunk header", CODE_CHUNK);
+ if (!read_code_header(stp)) {
goto error;
}
- define_file(&state, "export table", EXP_CHUNK);
- if (!stub_read_export_table(&state)) {
+ define_file(stp, "atom table", ATOM_CHUNK);
+ if (!load_atom_table(stp)) {
+ goto error;
+ }
+ define_file(stp, "export table", EXP_CHUNK);
+ if (!stub_read_export_table(stp)) {
goto error;
}
- if (state.chunks[LAMBDA_CHUNK].size > 0) {
- define_file(&state, "lambda (fun) table", LAMBDA_CHUNK);
- if (!read_lambda_table(&state)) {
+ if (stp->chunks[LAMBDA_CHUNK].size > 0) {
+ define_file(stp, "lambda (fun) table", LAMBDA_CHUNK);
+ if (!read_lambda_table(stp)) {
goto error;
}
}
@@ -5799,8 +5902,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
*/
code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr);
- code_size += state.chunks[ATTR_CHUNK].size;
- code_size += state.chunks[COMPILE_CHUNK].size;
+ code_size += stp->chunks[ATTR_CHUNK].size;
+ code_size += stp->chunks[COMPILE_CHUNK].size;
code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
if (!code) {
goto error;
@@ -5818,6 +5921,9 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
code[MI_COMPILE_SIZE] = 0;
code[MI_COMPILE_SIZE_ON_HEAP] = 0;
code[MI_NUM_BREAKPOINTS] = 0;
+ code[MI_LITERALS_START] = 0;
+ code[MI_LITERALS_END] = 0;
+ code[MI_LITERALS_OFF_HEAP] = 0;
code[MI_ON_LOAD_FUNCTION_PTR] = 0;
ci = MI_FUNCTIONS + n + 1;
@@ -5890,12 +5996,12 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
*/
info = (byte *) fp;
- info = stub_copy_info(&state, ATTR_CHUNK, info,
+ info = stub_copy_info(stp, ATTR_CHUNK, info,
code+MI_ATTR_PTR, code+MI_ATTR_SIZE_ON_HEAP);
if (info == NULL) {
goto error;
}
- info = stub_copy_info(&state, COMPILE_CHUNK, info,
+ info = stub_copy_info(stp, COMPILE_CHUNK, info,
code+MI_COMPILE_PTR, code+MI_COMPILE_SIZE_ON_HEAP);
if (info == NULL) {
goto error;
@@ -5905,9 +6011,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the module in the module table.
*/
- rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size,
- BEAM_CATCHES_NIL);
- if (rval < 0) {
+ rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size);
+ if (rval != NIL) {
goto error;
}
@@ -5917,46 +6022,19 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
fp = code + ci;
for (i = 0; i < n; i++) {
- stub_final_touch(&state, fp);
+ stub_final_touch(stp, fp);
fp += WORDS_PER_FUNCTION;
}
if (patch_funentries(Patchlist)) {
erts_free_aligned_binary_bytes(temp_alloc);
- if (state.lambdas != state.def_lambdas) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas);
- }
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels);
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom);
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export);
- if (bin != NULL) {
- driver_free_binary(bin);
- }
+ free_state(stp);
return Mod;
}
error:
erts_free_aligned_binary_bytes(temp_alloc);
- if (code != NULL) {
- erts_free(ERTS_ALC_T_CODE, code);
- }
- if (state.labels != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels);
- }
- if (state.lambdas != state.def_lambdas) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas);
- }
- if (state.atom != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom);
- }
- if (state.export != NULL) {
- erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export);
- }
- if (bin != NULL) {
- driver_free_binary(bin);
- }
-
-
+ free_state(stp);
BIF_ERROR(p, BADARG);
}
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index 9d4a60fed1..997ba197db 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -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
@@ -23,7 +23,9 @@
#include "beam_opcodes.h"
#include "erl_process.h"
-int beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module);
+Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks,
+ Eterm module);
+
typedef struct gen_op_entry {
char* name;
@@ -101,16 +103,18 @@ extern Uint erts_total_code_size;
*/
#define MI_LITERALS_START 8
#define MI_LITERALS_END 9
+#define MI_LITERALS_OFF_HEAP 10
+
/*
* Pointer to the on_load function (or NULL if none).
*/
-#define MI_ON_LOAD_FUNCTION_PTR 10
+#define MI_ON_LOAD_FUNCTION_PTR 11
/*
* Pointer to the line table (or NULL if none).
*/
-#define MI_LINE_TABLE 11
+#define MI_LINE_TABLE 12
/*
* Start of function pointer table. This table contains pointers to
@@ -121,5 +125,5 @@ extern Uint erts_total_code_size;
* this table.
*/
-#define MI_FUNCTIONS 12
+#define MI_FUNCTIONS 13
#endif /* _BEAM_LOAD_H */
diff --git a/erts/emulator/beam/benchmark.c b/erts/emulator/beam/benchmark.c
index 7fbf44a03c..7ac14b8e8b 100644
--- a/erts/emulator/beam/benchmark.c
+++ b/erts/emulator/beam/benchmark.c
@@ -33,17 +33,6 @@ unsigned long long messages_copied;
unsigned long long messages_ego;
unsigned long long minor_gc;
unsigned long long major_gc;
-#ifdef HYBRID
-unsigned long long minor_global_gc;
-unsigned long long major_global_gc;
-unsigned long long gc_in_copy;
-#ifdef INCREMENTAL
-unsigned long long minor_gc_cycles;
-unsigned long long major_gc_cycles;
-unsigned long long minor_gc_stages;
-unsigned long long major_gc_stages;
-#endif
-#endif
#endif /* BM_COUNTERS */
#ifdef BM_TIMERS
@@ -191,17 +180,6 @@ void init_benchmarking()
messages_ego = 0;
minor_gc = 0;
major_gc = 0;
-#ifdef HYBRID
- minor_global_gc = 0;
- major_global_gc = 0;
- gc_in_copy = 0;
-#ifdef INCREMENTAL
- minor_gc_cycles = 0;
- major_gc_cycles = 0;
- minor_gc_stages = 0;
- major_gc_stages = 0;
-#endif
-#endif
#endif /* BM_COUNTERS */
#ifdef BM_HEAP_SIZES
@@ -243,16 +221,6 @@ void save_statistics()
erts_fprintf(file,"Number of processes spawned: %lld\n",processes_spawned);
erts_fprintf(file,"Number of local minor GCs: %lld\n",minor_gc);
erts_fprintf(file,"Number of local major GCs: %lld\n",major_gc);
-#ifdef HYBRID
- erts_fprintf(file,"Number of global minor GCs: %lld\n",minor_global_gc);
- erts_fprintf(file,"Number of global major GCs: %lld\n",major_global_gc);
-#ifdef INCREMENTAL
- erts_fprintf(file,"Number of minor GC-cycles: %lld\n",minor_gc_cycles);
- erts_fprintf(file,"Number of major GC-cycles: %lld\n",major_gc_cycles);
- erts_fprintf(file,"Number of minor GC-stages: %lld\n",minor_gc_stages);
- erts_fprintf(file,"Number of major GC-stages: %lld\n",major_gc_stages);
-#endif
-#endif
erts_fprintf(file,"Number of messages sent: %lld\n",messages_sent);
erts_fprintf(file,"Number of messages copied: %lld\n",messages_copied);
erts_fprintf(file,"Number of messages sent to self: %lld\n",messages_ego);
diff --git a/erts/emulator/beam/benchmark.h b/erts/emulator/beam/benchmark.h
index eedb06a1b6..003e821bce 100644
--- a/erts/emulator/beam/benchmark.h
+++ b/erts/emulator/beam/benchmark.h
@@ -99,17 +99,6 @@ extern unsigned long long messages_copied;
extern unsigned long long messages_ego;
extern unsigned long long minor_gc;
extern unsigned long long major_gc;
-#ifdef HYBRID
-extern unsigned long long minor_global_gc;
-extern unsigned long long major_global_gc;
-extern unsigned long long gc_in_copy;
-#ifdef INCREMENTAL
-extern unsigned long long minor_gc_cycles;
-extern unsigned long long major_gc_cycles;
-extern unsigned long long minor_gc_stages;
-extern unsigned long long major_gc_stages;
-#endif
-#endif
#define BM_COUNT(var) (var)++;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 5b3261077b..fc00b42454 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,12 +36,16 @@
#include "beam_bp.h"
#include "erl_db_util.h"
#include "register.h"
+#include "erl_thr_progress.h"
static Export* flush_monitor_message_trap = NULL;
static Export* set_cpu_topology_trap = NULL;
static Export* await_proc_exit_trap = NULL;
Export* erts_format_cpu_topology_trap = NULL;
+static Export *await_sched_wall_time_mod_trap;
+static erts_smp_atomic32_t sched_wall_time;
+
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
/*
@@ -559,7 +563,11 @@ erts_queue_monitor_message(Process *p,
ref_copy = copy_struct(ref, ref_size, &hp, ohp);
tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy);
- erts_queue_message(p, p_locksp, bp, tup, NIL);
+ erts_queue_message(p, p_locksp, bp, tup, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
static BIF_RETTYPE
@@ -869,8 +877,6 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
}
} else if (arg == am_scheduler && is_small(val)) {
Sint scheduler = signed_val(val);
- if (erts_common_run_queue && erts_no_schedulers > 1)
- goto error;
if (scheduler < 0 || erts_no_schedulers < scheduler)
goto error;
so.scheduler = (int) scheduler;
@@ -1107,9 +1113,9 @@ BIF_RETTYPE hibernate_3(BIF_ALIST_3)
/**********************************************************************/
-BIF_RETTYPE get_stacktrace_0(Process* p)
+BIF_RETTYPE get_stacktrace_0(BIF_ALIST_0)
{
- Eterm t = build_stacktrace(p, p->ftrace);
+ Eterm t = build_stacktrace(BIF_P, BIF_P->ftrace);
BIF_RET(t);
}
@@ -1119,10 +1125,10 @@ BIF_RETTYPE get_stacktrace_0(Process* p)
* the process, and the final error value will be {Term,StackTrace}.
*/
-BIF_RETTYPE error_1(Process* p, Eterm term)
+BIF_RETTYPE error_1(BIF_ALIST_1)
{
- p->fvalue = term;
- BIF_ERROR(p, EXC_ERROR);
+ BIF_P->fvalue = BIF_ARG_1;
+ BIF_ERROR(BIF_P, EXC_ERROR);
}
/**********************************************************************/
@@ -1131,12 +1137,12 @@ BIF_RETTYPE error_1(Process* p, Eterm term)
* in the stacktrace.
*/
-BIF_RETTYPE error_2(Process* p, Eterm value, Eterm args)
+BIF_RETTYPE error_2(BIF_ALIST_2)
{
- Eterm* hp = HAlloc(p, 3);
+ Eterm* hp = HAlloc(BIF_P, 3);
- p->fvalue = TUPLE2(hp, value, args);
- BIF_ERROR(p, EXC_ERROR_2);
+ BIF_P->fvalue = TUPLE2(hp, BIF_ARG_1, BIF_ARG_2);
+ BIF_ERROR(BIF_P, EXC_ERROR_2);
}
/**********************************************************************/
@@ -1146,10 +1152,10 @@ BIF_RETTYPE error_2(Process* p, Eterm value, Eterm args)
* It is useful in stub functions for NIFs.
*/
-BIF_RETTYPE nif_error_1(Process* p, Eterm term)
+BIF_RETTYPE nif_error_1(BIF_ALIST_1)
{
- p->fvalue = term;
- BIF_ERROR(p, EXC_ERROR);
+ BIF_P->fvalue = BIF_ARG_1;
+ BIF_ERROR(BIF_P, EXC_ERROR);
}
/**********************************************************************/
@@ -1159,12 +1165,12 @@ BIF_RETTYPE nif_error_1(Process* p, Eterm term)
* It is useful in stub functions for NIFs.
*/
-BIF_RETTYPE nif_error_2(Process* p, Eterm value, Eterm args)
+BIF_RETTYPE nif_error_2(BIF_ALIST_2)
{
- Eterm* hp = HAlloc(p, 3);
+ Eterm* hp = HAlloc(BIF_P, 3);
- p->fvalue = TUPLE2(hp, value, args);
- BIF_ERROR(p, EXC_ERROR_2);
+ BIF_P->fvalue = TUPLE2(hp, BIF_ARG_1, BIF_ARG_2);
+ BIF_ERROR(BIF_P, EXC_ERROR_2);
}
/**********************************************************************/
@@ -1183,8 +1189,12 @@ BIF_RETTYPE exit_1(BIF_ALIST_1)
* If there is an error in the argument format,
* return the atom 'badarg' instead.
*/
-Eterm
-raise_3(Process *c_p, Eterm class, Eterm value, Eterm stacktrace) {
+BIF_RETTYPE raise_3(BIF_ALIST_3)
+{
+ Process *c_p = BIF_P;
+ Eterm class = BIF_ARG_1;
+ Eterm value = BIF_ARG_2;
+ Eterm stacktrace = BIF_ARG_3;
Eterm reason;
Eterm l, *hp, *hp_end, *tp;
int depth, cnt;
@@ -1530,8 +1540,6 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2)
ErtsRunQueue *old;
ErtsRunQueue *new;
Sint sched;
- if (erts_common_run_queue && erts_no_schedulers > 1)
- goto error;
if (!is_small(BIF_ARG_2))
goto error;
sched = signed_val(BIF_ARG_2);
@@ -1730,10 +1738,10 @@ BIF_RETTYPE whereis_1(BIF_ALIST_1)
* erlang:'!'/2
*/
-Eterm
-ebif_bang_2(Process* p, Eterm To, Eterm Message)
+BIF_RETTYPE
+ebif_bang_2(BIF_ALIST_2)
{
- return send_2(p, To, Message);
+ return erl_send(BIF_P, BIF_ARG_1, BIF_ARG_2);
}
@@ -1940,7 +1948,11 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) {
if (ERTS_PROC_GET_SAVED_CALLS_BUF(p))
save_calls(p, &exp_send);
- if (SEQ_TRACE_TOKEN(p) != NIL) {
+ if (SEQ_TRACE_TOKEN(p) != NIL
+#ifdef USE_VM_PROBES
+ && SEQ_TRACE_TOKEN(p) != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(p);
seq_trace_output(SEQ_TRACE_TOKEN(p), msg,
SEQ_TRACE_SEND, portid, p);
@@ -2070,8 +2082,13 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) {
}
-Eterm
-send_3(Process *p, Eterm to, Eterm msg, Eterm opts) {
+BIF_RETTYPE send_3(BIF_ALIST_3)
+{
+ Process *p = BIF_P;
+ Eterm to = BIF_ARG_1;
+ Eterm msg = BIF_ARG_2;
+ Eterm opts = BIF_ARG_3;
+
int connect = !0;
int suspend = !0;
Eterm l = opts;
@@ -2135,8 +2152,13 @@ send_3(Process *p, Eterm to, Eterm msg, Eterm opts) {
BIF_ERROR(p, BADARG);
}
-Eterm
-send_2(Process *p, Eterm to, Eterm msg) {
+BIF_RETTYPE send_2(BIF_ALIST_2)
+{
+ return erl_send(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+Eterm erl_send(Process *p, Eterm to, Eterm msg)
+{
Sint result = do_send(p, to, msg, !0);
if (result > 0) {
@@ -3312,8 +3334,11 @@ time_to_parts(Eterm date, Sint* year, Sint* month, Sint* day,
/* return the universal time */
BIF_RETTYPE
-localtime_to_universaltime_2(Process *p, Eterm localtime, Eterm dst)
+localtime_to_universaltime_2(BIF_ALIST_2)
{
+ Process *p = BIF_P;
+ Eterm localtime = BIF_ARG_1;
+ Eterm dst = BIF_ARG_2;
Sint year, month, day;
Sint hour, minute, second;
int isdst;
@@ -3371,6 +3396,61 @@ BIF_RETTYPE universaltime_to_localtime_1(BIF_ALIST_1)
BIF_RET(TUPLE2(hp, res1, res2));
}
+/* convert calendar:universaltime_to_seconds/1 */
+
+BIF_RETTYPE universaltime_to_posixtime_1(BIF_ALIST_1)
+{
+ Sint year, month, day;
+ Sint hour, minute, second;
+
+ Sint64 seconds = 0;
+ Eterm *hp;
+ Uint hsz = 0;
+
+ if (!time_to_parts(BIF_ARG_1, &year, &month, &day,
+ &hour, &minute, &second))
+ BIF_ERROR(BIF_P, BADARG);
+
+ if (!univ_to_seconds(year, month, day, hour, minute, second, &seconds)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ erts_bld_sint64(NULL, &hsz, seconds);
+ hp = HAlloc(BIF_P, hsz);
+ BIF_RET(erts_bld_sint64(&hp, NULL, seconds));
+}
+
+/* convert calendar:seconds_to_universaltime/1 */
+
+BIF_RETTYPE posixtime_to_universaltime_1(BIF_ALIST_1)
+{
+ Sint year, month, day;
+ Sint hour, minute, second;
+ Eterm res1, res2;
+ Eterm* hp;
+
+ Sint64 time = 0;
+
+ if (!term_to_Sint64(BIF_ARG_1, &time)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ if (!seconds_to_univ(time, &year, &month, &day,
+ &hour, &minute, &second)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ hp = HAlloc(BIF_P, 4+4+3);
+ res1 = TUPLE3(hp,make_small(year),make_small(month),
+ make_small(day));
+ hp += 4;
+ res2 = TUPLE3(hp,make_small(hour),make_small(minute),
+ make_small(second));
+ hp += 4;
+ BIF_RET(TUPLE2(hp, res1, res2));
+}
+
+
/**********************************************************************/
@@ -3437,22 +3517,6 @@ BIF_RETTYPE garbage_collect_0(BIF_ALIST_0)
}
/**********************************************************************/
-/* Perform garbage collection of the message area */
-
-BIF_RETTYPE garbage_collect_message_area_0(BIF_ALIST_0)
-{
-#if defined(HYBRID) && !defined(INCREMENTAL)
- int reds = 0;
-
- FLAGS(BIF_P) |= F_NEED_FULLSWEEP;
- reds = erts_global_garbage_collect(BIF_P, 0, NULL, 0);
- BIF_RET2(am_true, reds);
-#else
- BIF_RET(am_false);
-#endif
-}
-
-/**********************************************************************/
/* Return a list of active ports */
BIF_RETTYPE ports_0(BIF_ALIST_0)
@@ -3562,9 +3626,10 @@ BIF_RETTYPE erts_debug_display_1(BIF_ALIST_1)
}
-Eterm
-display_string_1(Process* p, Eterm string)
+BIF_RETTYPE display_string_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm string = BIF_ARG_1;
int len = is_string(string);
char *str;
@@ -3580,8 +3645,7 @@ display_string_1(Process* p, Eterm string)
BIF_RET(am_true);
}
-Eterm
-display_nl_0(Process* p)
+BIF_RETTYPE display_nl_0(BIF_ALIST_0)
{
erts_fprintf(stderr, "\n");
BIF_RET(am_true);
@@ -3593,43 +3657,122 @@ display_nl_0(Process* p)
/* ARGSUSED */
BIF_RETTYPE halt_0(BIF_ALIST_0)
{
- VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt/0\n"));
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erl_exit(0, "");
- return NIL; /* Pedantic (lint does not know about erl_exit) */
+ VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt()\n"));
+ erl_halt(0);
+ ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined);
}
/**********************************************************************/
-#define MSG_SIZE 200
+#define HALT_MSG_SIZE 200
+static char halt_msg[HALT_MSG_SIZE];
/* stop the system with exit code */
/* ARGSUSED */
BIF_RETTYPE halt_1(BIF_ALIST_1)
{
Sint code;
- static char msg[MSG_SIZE];
- int i;
if (is_small(BIF_ARG_1) && (code = signed_val(BIF_ARG_1)) >= 0) {
- VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%d)\n", code));
+ VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1));
+ erl_halt((int)(- code));
+ ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined);
+ }
+ else if (ERTS_IS_ATOM_STR("abort", BIF_ARG_1)) {
+ VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1));
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erl_exit(-code, "");
- } else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) {
- if ((i = intlist_to_buf(BIF_ARG_1, msg, MSG_SIZE-1)) < 0) {
+ erl_exit(ERTS_ABORT_EXIT, "");
+ }
+ else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) {
+ int i;
+
+ if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE-1)) < 0) {
goto error;
}
- msg[i] = '\0';
- VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%s)\n", msg));
+ halt_msg[i] = '\0';
+ VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1));
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erl_exit(ERTS_DUMP_EXIT, "%s\n", msg);
- } else {
- error:
+ erl_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg);
+ }
+ else
+ goto error;
+ return NIL; /* Pedantic (lint does not know about erl_exit) */
+ error:
BIF_ERROR(BIF_P, BADARG);
+}
+
+/**********************************************************************/
+
+/* stop the system with exit code and flags */
+/* ARGSUSED */
+BIF_RETTYPE halt_2(BIF_ALIST_2)
+{
+ Sint code;
+ Eterm optlist = BIF_ARG_2;
+ int flush = 0;
+
+ for (optlist = BIF_ARG_2;
+ is_list(optlist);
+ optlist = CDR(list_val(optlist))) {
+ Eterm *tp, opt = CAR(list_val(optlist));
+ if (is_not_tuple(opt))
+ goto error;
+ tp = tuple_val(opt);
+ if (tp[0] != make_arityval(2))
+ goto error;
+ if (tp[1] == am_flush) {
+ if (tp[2] == am_true)
+ flush = 1;
+ else if (tp[2] == am_false)
+ flush = 0;
+ else
+ goto error;
+ }
+ else
+ goto error;
}
+ if (is_not_nil(optlist))
+ goto error;
+
+ if (is_small(BIF_ARG_1) && (code = signed_val(BIF_ARG_1)) >= 0) {
+ VERBOSE(DEBUG_SYSTEM,
+ ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2));
+ if (flush) {
+ erl_halt((int)(- code));
+ ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined);
+ }
+ else {
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erl_exit((int)(- code), "");
+ }
+ }
+ else if (ERTS_IS_ATOM_STR("abort", BIF_ARG_1)) {
+ VERBOSE(DEBUG_SYSTEM,
+ ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2));
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erl_exit(ERTS_ABORT_EXIT, "");
+ }
+ else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) {
+ int i;
+
+ if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE-1)) < 0) {
+ goto error;
+ }
+ halt_msg[i] = '\0';
+ VERBOSE(DEBUG_SYSTEM,
+ ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2));
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erl_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg);
+ }
+ else
+ goto error;
return NIL; /* Pedantic (lint does not know about erl_exit) */
+ error:
+ BIF_ERROR(BIF_P, BADARG);
}
+/**********************************************************************/
+
BIF_RETTYPE function_exported_3(BIF_ALIST_3)
{
if (is_not_atom(BIF_ARG_1) ||
@@ -3645,8 +3788,13 @@ BIF_RETTYPE function_exported_3(BIF_ALIST_3)
/**********************************************************************/
-BIF_RETTYPE is_builtin_3(Process* p, Eterm Mod, Eterm Name, Eterm Arity)
+BIF_RETTYPE is_builtin_3(BIF_ALIST_3)
{
+ Process* p = BIF_P;
+ Eterm Mod = BIF_ARG_1;
+ Eterm Name = BIF_ARG_2;
+ Eterm Arity = BIF_ARG_3;
+
if (is_not_atom(Mod) || is_not_atom(Name) || is_not_small(Arity)) {
BIF_ERROR(p, BADARG);
}
@@ -3711,9 +3859,11 @@ BIF_RETTYPE make_fun_3(BIF_ALIST_3)
BIF_RET(make_export(hp));
}
-Eterm
-fun_to_list_1(Process* p, Eterm fun)
+BIF_RETTYPE fun_to_list_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm fun = BIF_ARG_1;
+
if (is_not_any_fun(fun))
BIF_ERROR(p, BADARG);
BIF_RET(term2list_dsprintf(p, fun));
@@ -4009,11 +4159,11 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
H_MIN_SIZE = erts_next_heap_size(n, 0);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(make_small(oval));
@@ -4025,11 +4175,11 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
BIN_VH_MIN_SIZE = erts_next_heap_size(n, 0);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(make_small(oval));
@@ -4051,7 +4201,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
erts_backtrace_depth = n;
BIF_RET(make_small(oval));
} else if (BIF_ARG_1 == am_trace_control_word) {
- BIF_RET(db_set_trace_control_word_1(BIF_P, BIF_ARG_2));
+ BIF_RET(db_set_trace_control_word(BIF_P, BIF_ARG_2));
} else if (BIF_ARG_1 == am_sequential_tracer) {
Eterm old_value = erts_set_system_seq_tracer(BIF_P,
ERTS_PROC_LOCK_MAIN,
@@ -4063,27 +4213,47 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
Uint i;
ErlMessage* mp;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
for (i = 0; i < erts_max_processes; i++) {
if (process_tab[i] != (Process*) 0) {
Process* p = process_tab[i];
+#ifdef USE_VM_PROBES
+ p->seq_trace_token = (p->dt_utag != NIL) ? am_have_dt_utag : NIL;
+#else
p->seq_trace_token = NIL;
+#endif
p->seq_trace_clock = 0;
p->seq_trace_lastcnt = 0;
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
mp = p->msg.first;
while(mp != NULL) {
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_TOKEN(mp) = (ERL_MESSAGE_DT_UTAG(mp) != NIL) ? am_have_dt_utag : NIL;
+#else
ERL_MESSAGE_TOKEN(mp) = NIL;
+#endif
mp = mp->next;
}
}
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
+ } else if (BIF_ARG_1 == am_scheduler_wall_time) {
+ if (BIF_ARG_2 == am_true || BIF_ARG_2 == am_false) {
+ erts_aint32_t new = BIF_ARG_2 == am_true ? 1 : 0;
+ erts_aint32_t old = erts_smp_atomic32_xchg_nob(&sched_wall_time,
+ new);
+ Eterm ref = erts_sched_wall_time_request(BIF_P, 1, new);
+ ASSERT(is_value(ref));
+ BIF_TRAP2(await_sched_wall_time_mod_trap,
+ BIF_P,
+ ref,
+ old ? am_true : am_false);
+ }
} else if (ERTS_IS_ATOM_STR("scheduling_statistics", BIF_ARG_1)) {
int what;
if (ERTS_IS_ATOM_STR("disable", BIF_ARG_2))
@@ -4103,8 +4273,20 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
if (is_value(res))
BIF_RET(res);
} else if (ERTS_IS_ATOM_STR("cpu_topology", BIF_ARG_1)) {
+ erts_send_warning_to_logger_str(
+ BIF_P->group_leader,
+ "A call to erlang:system_flag(cpu_topology, _) was made.\n"
+ "The cpu_topology argument is deprecated and scheduled\n"
+ "for removal in erts-5.10/OTP-R16. For more information\n"
+ "see the erlang:system_flag/2 documentation.\n");
BIF_TRAP1(set_cpu_topology_trap, BIF_P, BIF_ARG_2);
} else if (ERTS_IS_ATOM_STR("scheduler_bind_type", BIF_ARG_1)) {
+ erts_send_warning_to_logger_str(
+ BIF_P->group_leader,
+ "A call to erlang:system_flag(scheduler_bind_type, _) was\n"
+ "made. The scheduler_bind_type argument is deprecated and\n"
+ "scheduled for removal in erts-5.10/OTP-R16. For more\n"
+ "information see the erlang:system_flag/2 documentation.\n");
return erts_bind_schedulers(BIF_P, BIF_ARG_2);
}
error:
@@ -4291,8 +4473,7 @@ void
erts_bif_prep_await_proc_exit_data_trap(Process *c_p, Eterm pid, Eterm ret)
{
if (skip_current_msgq(c_p)) {
- Eterm unused;
- ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p, pid, am_data, ret);
+ ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p, pid, am_data, ret);
}
}
@@ -4300,8 +4481,7 @@ void
erts_bif_prep_await_proc_exit_reason_trap(Process *c_p, Eterm pid)
{
if (skip_current_msgq(c_p)) {
- Eterm unused;
- ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p,
+ ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p,
pid, am_reason, am_undefined);
}
}
@@ -4316,7 +4496,6 @@ erts_bif_prep_await_proc_exit_apply_trap(Process *c_p,
{
ASSERT(is_atom(module) && is_atom(function));
if (skip_current_msgq(c_p)) {
- Eterm unused;
Eterm term;
Eterm *hp;
int i;
@@ -4328,7 +4507,7 @@ erts_bif_prep_await_proc_exit_apply_trap(Process *c_p,
hp += 2;
}
term = TUPLE3(hp, module, function, term);
- ERTS_BIF_PREP_TRAP3(unused, await_proc_exit_trap, c_p, pid, am_apply, term);
+ ERTS_BIF_PREP_TRAP3_NO_RET(await_proc_exit_trap, c_p, pid, am_apply, term);
}
}
@@ -4372,6 +4551,9 @@ void erts_init_bif(void)
am_format_cpu_topology,
1);
await_proc_exit_trap = erts_export_put(am_erlang,am_await_proc_exit,3);
+ await_sched_wall_time_mod_trap
+ = erts_export_put(am_erlang, am_await_sched_wall_time_modifications, 2);
+ erts_smp_atomic32_init_nob(&sched_wall_time, 0);
}
#ifdef HARDDEBUG
@@ -4448,3 +4630,193 @@ BIF_RETTYPE get_module_info_2(BIF_ALIST_2)
}
BIF_RET(ret);
}
+
+BIF_RETTYPE dt_put_tag_1(BIF_ALIST_1)
+{
+#ifdef USE_VM_PROBES
+ Eterm otag;
+ if (BIF_ARG_1 == am_undefined) {
+ otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P);
+ DT_UTAG(BIF_P) = NIL;
+ DT_UTAG_FLAGS(BIF_P) = 0;
+ if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) {
+ SEQ_TRACE_TOKEN(BIF_P) = NIL;
+ }
+ BIF_RET(otag);
+ }
+ if (!is_binary(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P);
+ DT_UTAG(BIF_P) = BIF_ARG_1;
+ DT_UTAG_FLAGS(BIF_P) |= DT_UTAG_PERMANENT;
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL) {
+ SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag;
+ }
+ BIF_RET(otag);
+#else
+ BIF_RET(am_undefined);
+#endif
+}
+
+BIF_RETTYPE dt_get_tag_0(BIF_ALIST_0)
+{
+#ifdef USE_VM_PROBES
+ BIF_RET((DT_UTAG(BIF_P) == NIL || !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_PERMANENT)) ? am_undefined : DT_UTAG(BIF_P));
+#else
+ BIF_RET(am_undefined);
+#endif
+}
+BIF_RETTYPE dt_get_tag_data_0(BIF_ALIST_0)
+{
+#ifdef USE_VM_PROBES
+ BIF_RET((DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P));
+#else
+ BIF_RET(am_undefined);
+#endif
+}
+BIF_RETTYPE dt_prepend_vm_tag_data_1(BIF_ALIST_1)
+{
+#ifdef USE_VM_PROBES
+ Eterm b;
+ Eterm *hp;
+ hp = HAlloc(BIF_P,2);
+ if (is_binary((DT_UTAG(BIF_P)))) {
+ Uint sz = binary_size(DT_UTAG(BIF_P));
+ int i;
+ unsigned char *p,*q;
+ byte *temp_alloc = NULL;
+ b = new_binary(BIF_P,NULL,sz+1);
+ q = binary_bytes(b);
+ p = erts_get_aligned_binary_bytes(DT_UTAG(BIF_P),&temp_alloc);
+ for(i=0;i<sz;++i) {
+ q[i] = p[i];
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ q[sz] = '\0';
+ } else {
+ b = new_binary(BIF_P,(byte *)"\0",1);
+ }
+ BIF_RET(CONS(hp,b,BIF_ARG_1));
+#else
+ BIF_RET(BIF_ARG_1);
+#endif
+}
+BIF_RETTYPE dt_append_vm_tag_data_1(BIF_ALIST_1)
+{
+#ifdef USE_VM_PROBES
+ Eterm b;
+ Eterm *hp;
+ hp = HAlloc(BIF_P,2);
+ if (is_binary((DT_UTAG(BIF_P)))) {
+ Uint sz = binary_size(DT_UTAG(BIF_P));
+ int i;
+ unsigned char *p,*q;
+ byte *temp_alloc = NULL;
+ b = new_binary(BIF_P,NULL,sz+1);
+ q = binary_bytes(b);
+ p = erts_get_aligned_binary_bytes(DT_UTAG(BIF_P),&temp_alloc);
+ for(i=0;i<sz;++i) {
+ q[i] = p[i];
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ q[sz] = '\0';
+ } else {
+ b = new_binary(BIF_P,(byte *)"\0",1);
+ }
+ BIF_RET(CONS(hp,BIF_ARG_1,b));
+#else
+ BIF_RET(BIF_ARG_1);
+#endif
+}
+BIF_RETTYPE dt_spread_tag_1(BIF_ALIST_1)
+{
+#ifdef USE_VM_PROBES
+ Eterm ret;
+ Eterm *hp;
+#endif
+ if (BIF_ARG_1 != am_true && BIF_ARG_1 != am_false) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+#ifdef USE_VM_PROBES
+ hp = HAlloc(BIF_P,3);
+ ret = TUPLE2(hp,make_small(DT_UTAG_FLAGS(BIF_P)),DT_UTAG(BIF_P));
+ if (DT_UTAG(BIF_P) != NIL) {
+ if (BIF_ARG_1 == am_true) {
+ DT_UTAG_FLAGS(BIF_P) |= DT_UTAG_SPREADING;
+#ifdef DTRACE_TAG_HARDDEBUG
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) start spreading tag %T\r\n",
+ BIF_P->id,DT_UTAG(BIF_P));
+#endif
+ } else {
+ DT_UTAG_FLAGS(BIF_P) &= ~DT_UTAG_SPREADING;
+#ifdef DTRACE_TAG_HARDDEBUG
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) stop spreading tag %T\r\n",
+ BIF_P->id,DT_UTAG(BIF_P));
+#endif
+ }
+ }
+ BIF_RET(ret);
+#else
+ BIF_RET(am_true);
+#endif
+}
+BIF_RETTYPE dt_restore_tag_1(BIF_ALIST_1)
+{
+#ifdef USE_VM_PROBES
+ Eterm *tpl;
+ Uint x;
+ if (is_not_tuple(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ tpl = tuple_val(BIF_ARG_1);
+ if(arityval(*tpl) != 2 || is_not_small(tpl[1]) || (is_not_binary(tpl[2]) && tpl[2] != NIL)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ if (tpl[2] == NIL) {
+ if (DT_UTAG(BIF_P) != NIL) {
+#ifdef DTRACE_TAG_HARDDEBUG
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) restore Killing tag!\r\n",
+ BIF_P->id);
+#endif
+ }
+ DT_UTAG(BIF_P) = NIL;
+ if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) {
+ SEQ_TRACE_TOKEN(BIF_P) = NIL;
+ }
+ DT_UTAG_FLAGS(BIF_P) = 0;
+ } else {
+ x = unsigned_val(tpl[1]) & (DT_UTAG_SPREADING | DT_UTAG_PERMANENT);
+#ifdef DTRACE_TAG_HARDDEBUG
+
+ if (!(x & DT_UTAG_SPREADING) && (DT_UTAG_FLAGS(BIF_P) &
+ DT_UTAG_SPREADING)) {
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) restore stop spreading "
+ "tag %T\r\n",
+ BIF_P->id, tpl[2]);
+ } else if ((x & DT_UTAG_SPREADING) &&
+ !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) {
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) restore start spreading "
+ "tag %T\r\n",BIF_P->id,tpl[2]);
+ }
+#endif
+ DT_UTAG_FLAGS(BIF_P) = x;
+ DT_UTAG(BIF_P) = tpl[2];
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL) {
+ SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag;
+ }
+ }
+#else
+ if (BIF_ARG_1 != am_true) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+#endif
+ BIF_RET(am_true);
+}
+
+
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index 8faa09feb8..d20089a9fb 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -26,14 +26,14 @@ extern Export* erts_format_cpu_topology_trap;
#define BIF_P A__p
-#define BIF_ALIST_0 Process* A__p
-#define BIF_ALIST_1 Process* A__p, Eterm A_1
-#define BIF_ALIST_2 Process* A__p, Eterm A_1, Eterm A_2
-#define BIF_ALIST_3 Process* A__p, Eterm A_1, Eterm A_2, Eterm A_3
+#define BIF_ALIST_0 Process* A__p, Eterm* BIF__ARGS
+#define BIF_ALIST_1 Process* A__p, Eterm* BIF__ARGS
+#define BIF_ALIST_2 Process* A__p, Eterm* BIF__ARGS
+#define BIF_ALIST_3 Process* A__p, Eterm* BIF__ARGS
-#define BIF_ARG_1 A_1
-#define BIF_ARG_2 A_2
-#define BIF_ARG_3 A_3
+#define BIF_ARG_1 (BIF__ARGS[0])
+#define BIF_ARG_2 (BIF__ARGS[1])
+#define BIF_ARG_3 (BIF__ARGS[2])
#define BUMP_ALL_REDS(p) do { \
if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) \
@@ -122,89 +122,106 @@ do { \
} while (0)
-#define ERTS_BIF_PREP_TRAP0(Ret, Trap, Proc) \
-do { \
- (Proc)->arity = 0; \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
+#define ERTS_BIF_PREP_TRAP0(Ret, Trap, Proc) \
+do { \
+ (Proc)->arity = 0; \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
} while (0)
-#define ERTS_BIF_PREP_TRAP1(Ret, Trap, Proc, A0) \
-do { \
- (Proc)->arity = 1; \
- (Proc)->def_arg_reg[0] = (Eterm) (A0); \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
+#define ERTS_BIF_PREP_TRAP1(Ret, Trap, Proc, A0) \
+do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
+ (Proc)->arity = 1; \
+ reg[0] = (Eterm) (A0); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
} while (0)
-#define ERTS_BIF_PREP_TRAP2(Ret, Trap, Proc, A0, A1) \
-do { \
- (Proc)->arity = 2; \
- (Proc)->def_arg_reg[0] = (Eterm) (A0); \
- (Proc)->def_arg_reg[1] = (Eterm) (A1); \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
- (Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
+#define ERTS_BIF_PREP_TRAP2(Ret, Trap, Proc, A0, A1) \
+do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
+ (Proc)->arity = 2; \
+ reg[0] = (Eterm) (A0); \
+ reg[1] = (Eterm) (A1); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
+} while (0)
+
+#define ERTS_BIF_PREP_TRAP3(Ret, Trap, Proc, A0, A1, A2) \
+do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
+ (Proc)->arity = 3; \
+ reg[0] = (Eterm) (A0); \
+ reg[1] = (Eterm) (A1); \
+ reg[2] = (Eterm) (A2); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
+ (Proc)->freason = TRAP; \
+ (Ret) = THE_NON_VALUE; \
} while (0)
-#define ERTS_BIF_PREP_TRAP3(Ret, Trap, Proc, A0, A1, A2)\
+#define ERTS_BIF_PREP_TRAP3_NO_RET(Trap, Proc, A0, A1, A2)\
do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((Proc))->x_reg_array; \
(Proc)->arity = 3; \
- (Proc)->def_arg_reg[0] = (Eterm) (A0); \
- (Proc)->def_arg_reg[1] = (Eterm) (A1); \
- (Proc)->def_arg_reg[2] = (Eterm) (A2); \
- *((UWord *) (UWord) ((Proc)->def_arg_reg + 3)) = (UWord) ((Trap)->address); \
+ reg[0] = (Eterm) (A0); \
+ reg[1] = (Eterm) (A1); \
+ reg[2] = (Eterm) (A2); \
+ (Proc)->i = (BeamInstr*) ((Trap)->address); \
(Proc)->freason = TRAP; \
- (Ret) = THE_NON_VALUE; \
} while (0)
-#define BIF_TRAP0(p, Trap_) do { \
- (p)->arity = 0; \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP0(p, Trap_) do { \
+ (p)->arity = 0; \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP1(Trap_, p, A0) do { \
- (p)->arity = 1; \
- (p)->def_arg_reg[0] = (A0); \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP1(Trap_, p, A0) do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((p))->x_reg_array; \
+ (p)->arity = 1; \
+ reg[0] = (A0); \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP2(Trap_, p, A0, A1) do { \
- (p)->arity = 2; \
- (p)->def_arg_reg[0] = (A0); \
- (p)->def_arg_reg[1] = (A1); \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP2(Trap_, p, A0, A1) do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((p))->x_reg_array; \
+ (p)->arity = 2; \
+ reg[0] = (A0); \
+ reg[1] = (A1); \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP3(Trap_, p, A0, A1, A2) do { \
- (p)->arity = 3; \
- (p)->def_arg_reg[0] = (A0); \
- (p)->def_arg_reg[1] = (A1); \
- (p)->def_arg_reg[2] = (A2); \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) ((Trap_)->address); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP3(Trap_, p, A0, A1, A2) do { \
+ Eterm* reg = ERTS_PROC_GET_SCHDATA((p))->x_reg_array; \
+ (p)->arity = 3; \
+ reg[0] = (A0); \
+ reg[1] = (A1); \
+ reg[2] = (A2); \
+ (p)->i = (BeamInstr*) ((Trap_)->address); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP_CODE_PTR_0(p, Code_) do { \
- (p)->arity = 0; \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) (Code_); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP_CODE_PTR_0(p, Code_) do { \
+ (p)->arity = 0; \
+ (p)->i = (BeamInstr*) (Code_); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
-#define BIF_TRAP_CODE_PTR_(p, Code_) do { \
- *((UWord *) (UWord) ((p)->def_arg_reg + 3)) = (UWord) (Code_); \
- (p)->freason = TRAP; \
- return THE_NON_VALUE; \
+#define BIF_TRAP_CODE_PTR_(p, Code_) do { \
+ (p)-> i = (BeamInstr*) (Code_); \
+ (p)->freason = TRAP; \
+ return THE_NON_VALUE; \
} while(0)
extern Export bif_return_trap_export;
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index ba30fa85b8..797bce43ab 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2011. All Rights Reserved.
+# Copyright Ericsson AB 1996-2012. All Rights Reserved.
#
# The 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,8 +99,6 @@ bif erlang:garbage_collect/0
bif 'erl.system':garbage_collect/0 ebif_garbage_collect_0
bif erlang:garbage_collect/1
bif 'erl.system':garbage_collect/1 ebif_garbage_collect_1
-bif erlang:garbage_collect_message_area/0
-bif 'erl.system':garbage_collect_message_area/0 ebif_garbage_collect_message_area_0
bif erlang:get/0
bif 'erl.lang.proc.pdict':get/0 ebif_get_0
bif erlang:get/1
@@ -115,6 +113,8 @@ bif erlang:halt/0
bif 'erl.lang.system':halt/0 ebif_halt_0
bif erlang:halt/1
bif 'erl.lang.system':halt/1 ebif_halt_1
+bif erlang:halt/2
+bif 'erl.lang.system':halt/2 ebif_halt_2
bif erlang:phash/2
bif erlang:phash2/1
bif erlang:phash2/2
@@ -160,10 +160,6 @@ bif erlang:md5_update/2
bif 'erl.util.crypt.md5':update/2 ebif_md5_update_2
bif erlang:md5_final/1
bif 'erl.util.crypt.md5':final/1 ebif_md5_final_1
-bif erlang:memory/0
-bif 'erl.lang':memory/0 ebif_memory_0
-bif erlang:memory/1
-bif 'erl.lang':memory/1 ebif_memory_1
bif erlang:module_loaded/1
bif 'erl.system.code':is_loaded/1 ebif_is_loaded_1 module_loaded_1
bif erlang:function_exported/3
@@ -810,6 +806,29 @@ bif file:native_name_encoding/0
#
bif erlang:check_old_code/1
+
+#
+# New in R15B
+#
+bif erlang:universaltime_to_posixtime/1
+bif erlang:posixtime_to_universaltime/1
+
+#
+# New in R15B01
+#
+
+# The dtrace BIF's are always present, but give dummy results if dynamic trace is not enabled in the build
+bif erlang:dt_put_tag/1
+bif erlang:dt_get_tag/0
+bif erlang:dt_get_tag_data/0
+bif erlang:dt_spread_tag/1
+bif erlang:dt_restore_tag/1
+
+# These are dummies even with enabled dynamic trace unless vm probes are enabled.
+# They are also internal, for dtrace tags sent to the VM's own drivers (efile)
+bif erlang:dt_prepend_vm_tag_data/1
+bif erlang:dt_append_vm_tag_data/1
+
#
# Obsolete
#
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index d18de9ae5d..5a5b162b9c 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -310,12 +310,12 @@
#define DREM(a1,a0,b,r) do { \
ErtsDigit __a1 = (a1); \
ErtsDigit __b = (b); \
- ErtsDigit __q0; \
+ ERTS_DECLARE_DUMMY(ErtsDigit __q0); \
DDIVREM((__a1 % __b), (a0), __b, __q0, r); \
} while(0)
#define DDIV(a1,a0,b,q) do { \
- ErtsDigit _tmp; \
+ ERTS_DECLARE_DUMMY(ErtsDigit _tmp); \
DDIVREM(a1,a0,b,q,_tmp); \
} while(0)
@@ -413,8 +413,8 @@
} while(0)
#define DDIV2(a1,a0,b1,b0,q) do { \
- ErtsDigit _tmp_r1; \
- ErtsDigit _tmp_r0; \
+ ERTS_DECLARE_DUMMY(ErtsDigit _tmp_r1); \
+ ERTS_DECLARE_DUMMY(ErtsDigit _tmp_r0); \
D2DIVREM(a1,a0,b1,b0,q,_tmp_r1,_tmp_r0); \
} while(0)
@@ -810,7 +810,9 @@ static dsize_t D_div(ErtsDigit* x, dsize_t xl, ErtsDigit d, ErtsDigit* q, ErtsDi
}
do {
- ErtsDigit q0, a0, b1, b0, b;
+ ErtsDigit q0, a0, b0;
+ ERTS_DECLARE_DUMMY(ErtsDigit b);
+ ERTS_DECLARE_DUMMY(ErtsDigit b1);
if (d > a1) {
a0 = *xp;
@@ -1323,7 +1325,7 @@ static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y,
return 1;
}
else {
- long ay = (y < 0) ? -y : y;
+ SWord ay = (y < 0) ? -y : y;
int bw = ay / D_EXP;
int sw = ay % D_EXP;
dsize_t rl;
@@ -1448,6 +1450,20 @@ erts_make_integer(Uint x, Process *p)
return uint_to_big(x,hp);
}
}
+/*
+ * As erts_make_integer, but from a whole UWord.
+ */
+Eterm
+erts_make_integer_from_uword(UWord x, Process *p)
+{
+ Eterm* hp;
+ if (IS_USMALL(0,x))
+ return make_small(x);
+ else {
+ hp = HAlloc(p, BIG_UWORD_HEAP_SIZE(x));
+ return uword_to_big(x,hp);
+ }
+}
/*
** convert Uint to bigint
@@ -1584,6 +1600,62 @@ big_to_double(Wterm x, double* resp)
return 0;
}
+/*
+ * Logic has been copied from erl_bif_guard.c and slightly
+ * modified to use a static instead of dynamic heap
+ */
+Eterm
+double_to_big(double x, Eterm *heap)
+{
+ int is_negative;
+ int ds;
+ ErtsDigit* xp;
+ Eterm res;
+ int i;
+ size_t sz;
+ Eterm* hp;
+ double dbase;
+
+ if (x >= 0) {
+ is_negative = 0;
+ } else {
+ is_negative = 1;
+ x = -x;
+ }
+
+ /* Unscale & (calculate exponent) */
+ ds = 0;
+ dbase = ((double) (D_MASK) + 1);
+ while (x >= 1.0) {
+ x /= dbase; /* "shift" right */
+ ds++;
+ }
+ sz = BIG_NEED_SIZE(ds); /* number of words including arity */
+
+ hp = heap;
+ res = make_big(hp);
+ xp = (ErtsDigit*) (hp + 1);
+
+ for (i = ds - 1; i >= 0; i--) {
+ ErtsDigit d;
+
+ x *= dbase; /* "shift" left */
+ d = x; /* trunc */
+ xp[i] = d; /* store digit */
+ x -= d; /* remove integer part */
+ }
+ while ((ds & (BIG_DIGITS_PER_WORD - 1)) != 0) {
+ xp[ds++] = 0;
+ }
+
+ if (is_negative) {
+ *hp = make_neg_bignum_header(sz-1);
+ } else {
+ *hp = make_pos_bignum_header(sz-1);
+ }
+ return res;
+}
+
/*
** Estimate the number of decimal digits (include sign)
@@ -1772,6 +1844,7 @@ dsize_t big_bytes(Eterm x)
/*
** Load a bignum from bytes
** xsz is the number of bytes in xp
+** *r is untouched if number fits in small
*/
Eterm bytes_to_big(byte *xp, dsize_t xsz, int xsgn, Eterm *r)
{
@@ -1780,7 +1853,7 @@ Eterm bytes_to_big(byte *xp, dsize_t xsz, int xsgn, Eterm *r)
ErtsDigit d;
int i;
- while(xsz >= sizeof(ErtsDigit)) {
+ while(xsz > sizeof(ErtsDigit)) {
d = 0;
for(i = sizeof(ErtsDigit); --i >= 0;)
d = (d << 8) | xp[i];
@@ -1795,11 +1868,20 @@ Eterm bytes_to_big(byte *xp, dsize_t xsz, int xsgn, Eterm *r)
d = 0;
for(i = xsz; --i >= 0;)
d = (d << 8) | xp[i];
+ if (++rsz == 1 && IS_USMALL(xsgn,d)) {
+ if (xsgn) d = -d;
+ return make_small(d);
+ }
*rwp = d;
rwp++;
- rsz++;
}
- return big_norm(r, rsz, (short) xsgn);
+ if (xsgn) {
+ *r = make_neg_bignum_header(rsz);
+ }
+ else {
+ *r = make_pos_bignum_header(rsz);
+ }
+ return make_big(r);
}
/*
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index 2afc37004f..7eb1e5afe2 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -140,10 +140,12 @@ Eterm big_lshift(Eterm, Sint, Eterm*);
int big_comp (Wterm, Wterm);
int big_ucomp (Eterm, Eterm);
int big_to_double(Wterm x, double* resp);
+Eterm double_to_big(double, Eterm*);
Eterm small_to_big(Sint, Eterm*);
Eterm uint_to_big(Uint, Eterm*);
Eterm uword_to_big(UWord, Eterm*);
Eterm erts_make_integer(Uint, Process *);
+Eterm erts_make_integer_from_uword(UWord x, Process *p);
dsize_t big_bytes(Eterm);
Eterm bytes_to_big(byte*, dsize_t, int, Eterm*);
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 1fb39c6c67..3d2725e239 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -47,7 +47,7 @@ erts_init_binary(void)
away. If not, this test is not very expensive... */
erl_exit(ERTS_ABORT_EXIT,
"Internal error: Address of orig_bytes[0] of a Binary"
- "is *not* 8-byte aligned\n");
+ " is *not* 8-byte aligned\n");
}
}
@@ -356,8 +356,10 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg)
{
Eterm bin;
Uint size;
- int offset;
byte* bytes;
+#ifdef DEBUG
+ int offset;
+#endif
if (is_nil(arg)) {
BIF_RET(new_binary(p,(byte*)"",0));
@@ -372,7 +374,11 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg)
}
bin = new_binary(p, (byte *)NULL, size);
bytes = binary_bytes(bin);
- offset = io_list_to_buf(arg, (char*) bytes, size);
+#ifdef DEBUG
+ offset =
+#endif
+ io_list_to_buf(arg, (char*) bytes, size);
+
ASSERT(offset == 0);
BIF_RET(bin);
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 432b3d0780..93aa2fb8d0 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,7 @@
#include "beam_load.h"
#include "erl_instrument.h"
#include "erl_bif_timer.h"
+#include "erl_thr_progress.h"
/* Forward declarations -- should really appear somewhere else */
static void process_killer(void);
@@ -94,7 +95,7 @@ process_killer(void)
erts_printf("(k)ill (n)ext (r)eturn:\n");
while(1) {
if ((j = sys_get_key(0)) <= 0)
- halt_0(0);
+ erl_exit(0, "");
switch(j) {
case 'k':
if (rp->status == P_WAITING) {
@@ -181,6 +182,7 @@ print_process_info(int to, void *to_arg, Process *p)
{
int garbing = 0;
int running = 0;
+ time_t tmp_t;
struct saved_calls *scb;
/* display the PID */
@@ -243,8 +245,8 @@ print_process_info(int to, void *to_arg, Process *p)
}
erts_print(to, to_arg, "Spawned by: %T\n", p->parent);
-
- erts_print(to, to_arg, "Started: %s", ctime((time_t*)&p->started.tv_sec));
+ tmp_t = p->started.tv_sec;
+ erts_print(to, to_arg, "Started: %s", ctime(&tmp_t));
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
erts_print(to, to_arg, "Message queue length: %d\n", p->msg.len);
@@ -644,6 +646,9 @@ bin_check(void)
void
erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
{
+#ifdef ERTS_SMP
+ ErtsThrPrgrData tpd_buf; /* in case we aren't a managed thread... */
+#endif
int fd;
time_t now;
size_t dumpnamebufsize = MAXPATHLEN;
@@ -653,20 +658,18 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
if (ERTS_SOMEONE_IS_CRASH_DUMPING)
return;
- /* Wait for all threads to block. If all threads haven't blocked
+#ifdef ERTS_SMP
+ /*
+ * Wait for all managed threads to block. If all threads haven't blocked
* after a minute, we go anyway and hope for the best...
*
* We do not release system again. We expect an exit() or abort() after
* dump has been written.
- *
- * NOTE: We allow gc therefore it is important not to lock *any*
- * process locks.
*/
- erts_smp_emergency_block_system(60000, ERTS_BS_FLG_ALLOW_GC);
+ erts_thr_progress_fatal_error_block(60000, &tpd_buf);
/* Either worked or not... */
/* Allow us to pass certain places without locking... */
-#ifdef ERTS_SMP
erts_smp_atomic32_set_mb(&erts_writing_erl_crash_dump, 1);
erts_smp_tsd_set(erts_is_crash_dumping_key, (void *) 1);
#else
@@ -675,7 +678,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
erts_sys_prepare_crash_dump();
- if (erts_sys_getenv("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
+ if (erts_sys_getenv_raw("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
dumpname = "erl_crash.dump";
else
dumpname = &dumpnamebuf[0];
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index 90201f3a90..36eda04de2 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,29 +26,13 @@
#include "global.h"
#include "erl_process.h"
#include "erl_gc.h"
-#include "erl_nmgc.h"
#include "big.h"
#include "erl_binary.h"
#include "erl_bits.h"
-
-#ifdef HYBRID
-MA_STACK_DECLARE(src);
-MA_STACK_DECLARE(dst);
-MA_STACK_DECLARE(offset);
-#endif
+#include "dtrace-wrapper.h"
static void move_one_frag(Eterm** hpp, Eterm* src, Uint src_sz, ErlOffHeap*);
-void
-init_copy(void)
-{
-#ifdef HYBRID
- MA_STACK_ALLOC(src);
- MA_STACK_ALLOC(dst);
- MA_STACK_ALLOC(offset);
-#endif
-}
-
/*
* Copy object "obj" to process p.
*/
@@ -59,6 +43,14 @@ copy_object(Eterm obj, Process* to)
Eterm* hp = HAlloc(to, size);
Eterm res;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(copy_object)) {
+ DTRACE_CHARBUF(proc_name, 64);
+
+ erts_snprintf(proc_name, sizeof(proc_name), "%T", to->id);
+ DTRACE2(copy_object, proc_name, size);
+ }
+#endif
res = copy_struct(obj, size, &hp, &to->off_heap);
#ifdef DEBUG
if (eq(obj, res) == 0) {
@@ -134,7 +126,7 @@ Uint size_object(Eterm obj)
case SUB_BINARY_SUBTAG:
{
Eterm real_bin;
- Uint offset; /* Not used. */
+ ERTS_DECLARE_DUMMY(Uint offset); /* Not used. */
Uint bitsize;
Uint bitoffs;
Uint extra_bytes;
@@ -213,6 +205,8 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
if (IS_CONST(obj))
return obj;
+ DTRACE1(copy_struct, (int32_t)sz);
+
hp = htop = *hpp;
hbot = htop + sz;
hstart = (char *)htop;
@@ -421,12 +415,10 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
while (i--) {
*htop++ = *objp++;
}
-#ifndef HYBRID /* FIND ME! */
funp = (ErlFunThing *) tp;
funp->next = off_heap->first;
off_heap->first = (struct erl_off_heap_header*) funp;
erts_refc_inc(&funp->fe->refc, 2);
-#endif
*argp = make_fun_rel(tp, dst_base);
}
break;
@@ -489,420 +481,6 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
return res;
}
-#ifdef HYBRID
-
-#ifdef BM_MESSAGE_SIZES
-# define BM_ADD(var,val) (var) += (val);
-#else
-# define BM_ADD(var,val)
-#endif
-
-#ifdef DEBUG
-# define CLEARMEM(PTR,SIZE) memset(PTR,0,SIZE*sizeof(Eterm))
-#else
-# define CLEARMEM(PTR,SIZE)
-#endif
-
-#ifdef INCREMENTAL
-#define GlobalAlloc(p, need, hp) \
-do { \
- Uint n = (need); \
- BM_ADD(words_copied,n); \
- BM_SWAP_TIMER(copy,system); \
- /* If a new collection cycle is started during copy, the message * \
- * will end up in the old generation and all allocations * \
- * thereafter must go directly into the old generation. */ \
- if (alloc_old) { \
- erts_incremental_gc((p),n,&dest,1); \
- (hp) = erts_inc_alloc(n); \
- } else { \
- (hp) = IncAlloc((p),n,&dest,1); \
- if (ma_gc_flags & GC_CYCLE_START) { \
- alloc_old = 1; \
- global_htop = global_heap; \
- (hp) = erts_inc_alloc(n); \
- } \
- } \
- CLEARMEM((hp),(n)); \
- BM_SWAP_TIMER(system,copy); \
-} while(0)
-
-#else /* no INCREMELNTAL */
-
-#define GlobalAlloc(p, need, hp) \
-do { \
- Uint n = (need); \
- total_need += n; \
- if (total_need >= global_heap_sz) \
- erl_exit(ERTS_ABORT_EXIT, "Copying a message (%d words) larger than the nursery simply won't work...\n", total_need); \
- if (global_hend - n < global_htop) { \
- BM_SWAP_TIMER(copy,system); \
- erts_global_garbage_collect((p),total_need,NULL,0); \
- BM_SWAP_TIMER(system,copy); \
- total_need = 0; \
- ma_src_top = 0; \
- ma_dst_top = 0; \
- ma_offset_top = 0; \
- goto copy_start; \
- } \
- (hp) = global_htop; \
- global_htop += n; \
- BM_ADD(words_copied,n); \
-} while(0)
-#endif /* INCREMENTAL */
-
-/* Copy a message to the message area. */
-Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
-{
- Eterm obj;
- Eterm dest;
-#ifdef INCREMENTAL
- int alloc_old = 0;
-#else
- int total_need = 0;
-#endif
-
- VERBOSE(DEBUG_MESSAGES,
- ("COPY START; %T is sending a message @ 0x%016x\n%T\n",
- from->id, orig, orig));
-
-#ifndef INCREMENTAL
- copy_start:
-#endif
- MA_STACK_PUSH(src,orig);
- MA_STACK_PUSH(dst,&dest);
- MA_STACK_PUSH(offset,offs);
-
- while (ma_src_top > 0) {
- obj = MA_STACK_POP(src);
-
- /* copy_struct_lazy should never be called with something that
- * do not need to be copied. Within the loop, nothing that do
- * not need copying should be placed in the src-stack.
- */
- ASSERT(!NO_COPY(obj));
-
- switch (primary_tag(obj)) {
- case TAG_PRIMARY_LIST: {
- Eterm *hp;
- Eterm *objp;
-
- GlobalAlloc(from,2,hp);
- objp = list_val(obj);
-
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_list(hp));
- MA_STACK_POP(dst);
-
- /* TODO: Byt ordningen nedan så att CDR pushas först. */
-
- if (NO_COPY(*objp)) {
- hp[0] = *objp;
-#ifdef INCREMENTAL
- if (ptr_within(ptr_val(*objp),inc_fromspc,inc_fromend))
- INC_STORE(gray,hp,2);
-#endif
- } else {
- MA_STACK_PUSH(src,*objp);
- MA_STACK_PUSH(dst,hp);
- MA_STACK_PUSH(offset,0);
- }
-
- objp++;
-
- if (NO_COPY(*objp)) {
- hp[1] = *objp;
-#ifdef INCREMENTAL
- if (ptr_within(ptr_val(*objp),inc_fromspc,inc_fromend))
- INC_STORE(gray,hp,2);
-#endif
- }
- else {
- MA_STACK_PUSH(src,*objp);
- MA_STACK_PUSH(dst,hp);
- MA_STACK_PUSH(offset,1);
- }
- continue;
- }
-
- case TAG_PRIMARY_BOXED: {
- Eterm *objp = boxed_val(obj);
-
- switch (*objp & _TAG_HEADER_MASK) {
- case ARITYVAL_SUBTAG: {
- Uint ari = arityval(*objp);
- Uint i;
- Eterm *hp;
- GlobalAlloc(from,ari + 1,hp);
- /* A GC above might invalidate the value of objp */
- objp = boxed_val(obj);
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_tuple(hp));
- MA_STACK_POP(dst);
- *hp = *objp++;
- for (i = 1; i <= ari; i++) {
- switch (primary_tag(*objp)) {
- case TAG_PRIMARY_LIST:
- case TAG_PRIMARY_BOXED:
- if (NO_COPY(*objp)) {
- hp[i] = *objp;
-#ifdef INCREMENTAL
- if (ptr_within(ptr_val(*objp),
- inc_fromspc,inc_fromend))
- INC_STORE(gray,hp,BOXED_NEED(hp,*hp));
-#endif
- objp++;
- } else {
- MA_STACK_PUSH(src,*objp++);
- MA_STACK_PUSH(dst,hp);
- MA_STACK_PUSH(offset,i);
- }
- break;
- default:
- hp[i] = *objp++;
- }
- }
- continue;
- }
-
- case REFC_BINARY_SUBTAG: {
- ProcBin *pb;
- Uint i = thing_arityval(*objp) + 1;
- Eterm *hp;
- GlobalAlloc(from,i,hp);
- /* A GC above might invalidate the value of objp */
- objp = boxed_val(obj);
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_binary(hp));
- MA_STACK_POP(dst);
- pb = (ProcBin*) hp;
- while (i--) {
- *hp++ = *objp++;
- }
- erts_refc_inc(&pb->val->refc, 2);
- pb->next = erts_global_offheap.first;
- erts_global_offheap.first = pb;
- OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
- continue;
- }
-
- case FUN_SUBTAG: {
- ErlFunThing *funp = (ErlFunThing*) objp;
- Uint i = thing_arityval(*objp) + 1;
- Uint j = i + 1 + funp->num_free;
- Uint k = i;
- Eterm *hp, *hp_start;
- GlobalAlloc(from,j,hp);
- /* A GC above might invalidate the value of objp */
- objp = boxed_val(obj);
- hp_start = hp;
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_fun(hp));
- MA_STACK_POP(dst);
- funp = (ErlFunThing*) hp;
- while (i--) {
- *hp++ = *objp++;
- }
-#ifndef HYBRID /* FIND ME! */
- funp->next = erts_global_offheap.first;
- erts_global_offheap.first = funp;
- erts_refc_inc(&funp->fe->refc, 2);
-#endif
- for (i = k; i < j; i++) {
- switch (primary_tag(*objp)) {
- case TAG_PRIMARY_LIST:
- case TAG_PRIMARY_BOXED:
- if (NO_COPY(*objp)) {
-#ifdef INCREMENTAL
- if (ptr_within(ptr_val(*objp),
- inc_fromspc,inc_fromend))
- INC_STORE(gray,hp,BOXED_NEED(hp,*hp));
-#endif
- *hp++ = *objp++;
- } else {
- MA_STACK_PUSH(src,*objp++);
- MA_STACK_PUSH(dst,hp_start);
- MA_STACK_PUSH(offset,i);
- hp++;
- }
- break;
- default:
- *hp++ = *objp++;
- }
- }
- continue;
- }
-
- case EXTERNAL_PID_SUBTAG:
- case EXTERNAL_PORT_SUBTAG:
- case EXTERNAL_REF_SUBTAG: {
- ExternalThing *etp;
- Uint i = thing_arityval(*objp) + 1;
- Eterm *hp;
- GlobalAlloc(from,i,hp);
- /* A GC above might invalidate the value of objp */
- objp = boxed_val(obj);
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_external(hp));
- MA_STACK_POP(dst);
- etp = (ExternalThing*) hp;
- while (i--) {
- *hp++ = *objp++;
- }
-
- etp->next = erts_global_offheap.first;
- erts_global_offheap.first = etp;
- erts_refc_inc(&etp->node->refc, 2);
- continue;
- }
-
- case SUB_BINARY_SUBTAG: {
- ErlSubBin *sb = (ErlSubBin *) objp;
- Eterm *hp;
- Eterm res_binary;
- Eterm real_bin = sb->orig;
- Uint bit_offset = sb->bitoffs;
- Uint bit_size = sb -> bitsize;
- Uint sub_offset = sb->offs;
- size_t size = sb->size;
- Uint extra_bytes;
- Uint real_size;
- Uint sub_binary_heapneed;
- if ((bit_size + bit_offset) > 8) {
- extra_bytes = 2;
- sub_binary_heapneed = ERL_SUB_BIN_SIZE;
- } else if ((bit_size + bit_offset) > 0) {
- extra_bytes = 1;
- sub_binary_heapneed = ERL_SUB_BIN_SIZE;
- } else {
- extra_bytes = 0;
- sub_binary_heapneed = 0;
- }
-
- real_size = size+extra_bytes;
- objp = binary_val(real_bin);
- if (thing_subtag(*objp) == HEAP_BINARY_SUBTAG) {
- ErlHeapBin *from_bin;
- ErlHeapBin *to_bin;
- Uint i = heap_bin_size(real_size);
- GlobalAlloc(from,i+sub_binary_heapneed,hp);
- from_bin = (ErlHeapBin *) objp;
- to_bin = (ErlHeapBin *) hp;
- to_bin->thing_word = header_heap_bin(real_size);
- to_bin->size = real_size;
- sys_memcpy(to_bin->data, ((byte *)from_bin->data) +
- sub_offset, real_size);
- res_binary = make_binary(to_bin);
- hp += i;
- } else {
- ProcBin *from_bin;
- ProcBin *to_bin;
-
- ASSERT(thing_subtag(*objp) == REFC_BINARY_SUBTAG);
- from_bin = (ProcBin *) objp;
- erts_refc_inc(&from_bin->val->refc, 2);
- GlobalAlloc(from,PROC_BIN_SIZE+sub_binary_heapneed,hp);
- to_bin = (ProcBin *) hp;
- to_bin->thing_word = HEADER_PROC_BIN;
- to_bin->size = real_size;
- to_bin->val = from_bin->val;
- to_bin->bytes = from_bin->bytes + sub_offset;
- to_bin->next = erts_global_offheap.first;
- erts_global_offheap.first = to_bin;
- OH_OVERHEAD(&erts_global_offheap, to_bin->size / sizeof(Eterm));
- res_binary=make_binary(to_bin);
- hp += PROC_BIN_SIZE;
- }
- if (extra_bytes != 0) {
- ErlSubBin* res;
- res = (ErlSubBin *) hp;
- res->thing_word = HEADER_SUB_BIN;
- res->size = size;
- res->bitsize = bit_size;
- res->bitoffs = bit_offset;
- res->offs = 0;
- res->is_writable = 0;
- res->orig = res_binary;
- res_binary = make_binary(hp);
- }
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),res_binary);
- MA_STACK_POP(dst);
- continue;
- }
-
- case BIN_MATCHSTATE_SUBTAG:
- erl_exit(ERTS_ABORT_EXIT,
- "copy_struct_lazy: matchstate term not allowed");
-
- default: {
- Uint size = thing_arityval(*objp) + 1;
- Eterm *hp;
- GlobalAlloc(from,size,hp);
- /* A GC above might invalidate the value of objp */
- objp = boxed_val(obj);
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_boxed(hp));
- MA_STACK_POP(dst);
- while (size--) {
- *hp++ = *objp++;
- }
- continue;
- }
- }
- continue;
- }
-
- case TAG_PRIMARY_HEADER:
- ASSERT((obj & _TAG_HEADER_MASK) == ARITYVAL_SUBTAG);
- {
- Eterm *objp = &obj;
- Uint ari = arityval(obj);
- Uint i;
- Eterm *hp;
- GlobalAlloc(from,ari + 1,hp);
- MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_tuple(hp));
- MA_STACK_POP(dst);
- *hp = *objp++;
- for (i = 1; i <= ari; i++) {
- switch (primary_tag(*objp)) {
- case TAG_PRIMARY_LIST:
- case TAG_PRIMARY_BOXED:
- if (NO_COPY(*objp)) {
-#ifdef INCREMENTAL
- if (ptr_within(ptr_val(*objp),inc_fromspc,inc_fromend))
- INC_STORE(gray,hp,ari + 1);
-#endif
- hp[i] = *objp++;
- } else {
- MA_STACK_PUSH(src,*objp++);
- MA_STACK_PUSH(dst,hp);
- MA_STACK_PUSH(offset,i);
- }
- break;
- default:
- hp[i] = *objp++;
- }
- }
- continue;
- }
-
- default:
- erl_exit(ERTS_ABORT_EXIT,
- "%s, line %d: Internal error in copy_struct_lazy: 0x%08x\n",
- __FILE__, __LINE__,obj);
- }
- }
-
- VERBOSE(DEBUG_MESSAGES,
- ("Copy allocated @ 0x%08lx:\n%T\n",
- (unsigned long)ptr_val(dest),dest));
-
- ma_gc_flags &= ~GC_CYCLE_START;
-
- ASSERT(eq(orig, dest));
- ASSERT(ma_src_top == 0);
- ASSERT(ma_dst_top == 0);
- ASSERT(ma_offset_top == 0);
- return dest;
-}
-
-#undef NO_COPY
-#endif /* HYBRID */
-
/*
* Copy a term that is guaranteed to be contained in a single
* heap block. The heap block is copied word by word, and any
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index ad042ec088..025258e8de 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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 @@
#include "bif.h"
#include "external.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
+#include "dtrace-wrapper.h"
/* Turn this on to get printouts of all distribution messages
* which go on the line
@@ -53,9 +55,9 @@
#endif
#if defined(ERTS_DIST_MSG_DBG) || defined(ERTS_RAW_DIST_MSG_DBG)
-static void bw(byte *buf, int sz)
+static void bw(byte *buf, ErlDrvSizeT sz)
{
- bin_write(ERTS_PRINT_STDERR,NULL,buf,sz);
+ bin_write(ERTS_PRINT_STDERR, NULL, buf, sz);
}
#endif
@@ -380,7 +382,11 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
Eterm tup;
Eterm *hp = erts_alloc_message_heap(3,&bp,&ohp,rp,&rp_locks);
tup = TUPLE2(hp, am_nodedown, name);
- erts_queue_message(rp, &rp_locks, bp, tup, NIL);
+ erts_queue_message(rp, &rp_locks, bp, tup, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
erts_smp_proc_unlock(rp, rp_locks);
}
@@ -430,11 +436,11 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
nodename = erts_this_dist_entry->sysname;
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC);
+ erts_smp_thr_progress_block();
erts_set_this_node(am_Noname, 0);
erts_is_alive = 0;
send_nodes_mon_msgs(NULL, am_nodedown, nodename, am_visible, nd_reason);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
else { /* recursive call via erts_do_exit_port() will end up here */
@@ -535,7 +541,7 @@ alloc_dist_obuf(Uint size)
Binary *bin = erts_bin_drv_alloc(obuf_size);
bin->flags = BIN_FLAG_DRV;
erts_refc_init(&bin->refc, 1);
- bin->orig_size = (long) obuf_size;
+ bin->orig_size = (SWord) obuf_size;
obuf = (ErtsDistOutputBuf *) &bin->orig_bytes[0];
#ifdef DEBUG
obuf->dbg_pattern = ERTS_DIST_OUTPUT_BUF_DBG_PATTERN;
@@ -739,19 +745,50 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message)
Eterm token = NIL;
Process *sender = dsdp->proc;
int res;
+#ifdef USE_VM_PROBES
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+ Uint msize = 0;
+ DTRACE_CHARBUF(node_name, 64);
+ DTRACE_CHARBUF(sender_name, 64);
+ DTRACE_CHARBUF(receiver_name, 64);
+#endif
UseTmpHeapNoproc(5);
- if (SEQ_TRACE_TOKEN(sender) != NIL) {
+ if (SEQ_TRACE_TOKEN(sender) != NIL
+#ifdef USE_VM_PROBES
+ && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender);
}
+#ifdef USE_VM_PROBES
+ *node_name = *sender_name = *receiver_name = '\0';
+ if (DTRACE_ENABLED(message_send) || DTRACE_ENABLED(message_send_remote)) {
+ erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname);
+ erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id);
+ erts_snprintf(receiver_name, sizeof(receiver_name), "%T", remote);
+ msize = size_object(message);
+ if (token != NIL && token != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ }
+#endif
if (token != NIL)
ctl = TUPLE4(&ctl_heap[0],
make_small(DOP_SEND_TT), am_Cookie, remote, token);
else
ctl = TUPLE3(&ctl_heap[0], make_small(DOP_SEND), am_Cookie, remote);
+ DTRACE6(message_send, sender_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
+ DTRACE7(message_send_remote, sender_name, node_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
res = dsig_send(dsdp, ctl, message, 0);
UnUseTmpHeapNoproc(5);
return res;
@@ -765,13 +802,41 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message)
Eterm token = NIL;
Process *sender = dsdp->proc;
int res;
+#ifdef USE_VM_PROBES
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+ Uint32 msize = 0;
+ DTRACE_CHARBUF(node_name, 64);
+ DTRACE_CHARBUF(sender_name, 64);
+ DTRACE_CHARBUF(receiver_name, 128);
+#endif
UseTmpHeapNoproc(6);
- if (SEQ_TRACE_TOKEN(sender) != NIL) {
+ if (SEQ_TRACE_TOKEN(sender) != NIL
+#ifdef USE_VM_PROBES
+ && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender);
}
+#ifdef USE_VM_PROBES
+ *node_name = *sender_name = *receiver_name = '\0';
+ if (DTRACE_ENABLED(message_send) || DTRACE_ENABLED(message_send_remote)) {
+ erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname);
+ erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id);
+ erts_snprintf(receiver_name, sizeof(receiver_name),
+ "{%T,%s}", remote_name, node_name);
+ msize = size_object(message);
+ if (token != NIL && token != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ }
+#endif
if (token != NIL)
ctl = TUPLE5(&ctl_heap[0], make_small(DOP_REG_SEND_TT),
@@ -779,6 +844,10 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message)
else
ctl = TUPLE4(&ctl_heap[0], make_small(DOP_REG_SEND),
sender->id, am_Cookie, remote_name);
+ DTRACE6(message_send, sender_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
+ DTRACE7(message_send_remote, sender_name, node_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
res = dsig_send(dsdp, ctl, message, 0);
UnUseTmpHeapNoproc(6);
return res;
@@ -792,9 +861,23 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
Eterm ctl;
DeclareTmpHeapNoproc(ctl_heap,6);
int res;
+#ifdef USE_VM_PROBES
+ Process *sender = dsdp->proc;
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+ DTRACE_CHARBUF(node_name, 64);
+ DTRACE_CHARBUF(sender_name, 64);
+ DTRACE_CHARBUF(remote_name, 128);
+ DTRACE_CHARBUF(reason_str, 128);
+#endif
UseTmpHeapNoproc(6);
- if (token != NIL) {
+ if (token != NIL
+#ifdef USE_VM_PROBES
+ && token != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(dsdp->proc);
seq_trace_output_exit(token, reason, SEQ_TRACE_SEND, remote, local);
ctl = TUPLE5(&ctl_heap[0],
@@ -802,6 +885,23 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
} else {
ctl = TUPLE4(&ctl_heap[0], make_small(DOP_EXIT), local, remote, reason);
}
+#ifdef USE_VM_PROBES
+ *node_name = *sender_name = *remote_name = '\0';
+ if (DTRACE_ENABLED(process_exit_signal_remote)) {
+ erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname);
+ erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id);
+ erts_snprintf(remote_name, sizeof(remote_name),
+ "{%T,%s}", remote, node_name);
+ erts_snprintf(reason_str, sizeof(reason), "%T", reason);
+ if (token != NIL && token != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ }
+#endif
+ DTRACE7(process_exit_signal_remote, sender_name, node_name,
+ remote_name, reason_str, tok_label, tok_lastcnt, tok_serial);
/* forced, i.e ignore busy */
res = dsig_send(dsdp, ctl, THE_NON_VALUE, 1);
UnUseTmpHeapNoproc(6);
@@ -868,16 +968,16 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote)
#define VALGRIND_PRINTF_XML VALGRIND_PRINTF
#endif
-# define PURIFY_MSG(msg) \
- do { \
- char buf__[1]; size_t bufsz__ = sizeof(buf__); \
- if (erts_sys_getenv("VALGRIND_LOG_XML", buf__, &bufsz__) >= 0) { \
- VALGRIND_PRINTF_XML("<erlang_error_log>" \
- "%s, line %d: %s</erlang_error_log>\n", \
- __FILE__, __LINE__, msg); \
- } else { \
- VALGRIND_PRINTF("%s, line %d: %s", __FILE__, __LINE__, msg); \
- } \
+# define PURIFY_MSG(msg) \
+ do { \
+ char buf__[1]; size_t bufsz__ = sizeof(buf__); \
+ if (erts_sys_getenv_raw("VALGRIND_LOG_XML", buf__, &bufsz__) >= 0) { \
+ VALGRIND_PRINTF_XML("<erlang_error_log>" \
+ "%s, line %d: %s</erlang_error_log>\n", \
+ __FILE__, __LINE__, msg); \
+ } else { \
+ VALGRIND_PRINTF("%s, line %d: %s", __FILE__, __LINE__, msg); \
+ } \
} while (0)
#else
# define PURIFY_MSG(msg)
@@ -896,9 +996,9 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote)
int erts_net_message(Port *prt,
DistEntry *dep,
byte *hbuf,
- int hlen,
+ ErlDrvSizeT hlen,
byte *buf,
- int len)
+ ErlDrvSizeT len)
{
#define DIST_CTL_DEFAULT_SIZE 64
ErtsDistExternal ede;
@@ -923,7 +1023,7 @@ int erts_net_message(Port *prt,
Uint tuple_arity;
int res;
#ifdef ERTS_DIST_MSG_DBG
- int orig_len = len;
+ ErlDrvSizeT orig_len = len;
#endif
UseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
@@ -939,7 +1039,7 @@ int erts_net_message(Port *prt,
UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
return 0;
}
- if (hlen > 0)
+ if (hlen != 0)
goto data_error;
if (len == 0) { /* HANDLE TICK !!! */
UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
@@ -967,7 +1067,7 @@ int erts_net_message(Port *prt,
res = erts_prepare_dist_ext(&ede, t, len, dep, dep->cache);
if (res >= 0)
- res = ctl_len = erts_decode_dist_ext_size(&ede, 0);
+ res = ctl_len = erts_decode_dist_ext_size(&ede);
else {
#ifdef ERTS_DIST_MSG_DBG
erts_fprintf(stderr, "DIST MSG DEBUG: erts_prepare_dist_ext() failed:\n");
@@ -1482,11 +1582,9 @@ int erts_net_message(Port *prt,
}
erts_cleanup_offheap(&off_heap);
-#ifndef HYBRID /* FIND ME! */
if (ctl != ctl_default) {
erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl);
}
-#endif
UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
ERTS_SMP_CHK_NO_PROC_LOCKS;
return 0;
@@ -1499,11 +1597,9 @@ int erts_net_message(Port *prt,
data_error:
PURIFY_MSG("data error");
erts_cleanup_offheap(&off_heap);
-#ifndef HYBRID /* FIND ME! */
if (ctl != ctl_default) {
erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl);
}
-#endif
UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
erts_do_exit_port(prt, dep->cid, am_killed);
ERTS_SMP_CHK_NO_PROC_LOCKS;
@@ -1618,6 +1714,18 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy)
if (!(dep->qflgs & ERTS_DE_QFLG_BUSY)) {
if (suspended)
resume = 1; /* was busy when we started, but isn't now */
+#ifdef USE_VM_PROBES
+ if (resume && DTRACE_ENABLED(dist_port_not_busy)) {
+ DTRACE_CHARBUF(port_str, 64);
+ DTRACE_CHARBUF(remote_str, 64);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", cid);
+ erts_snprintf(remote_str, sizeof(remote_str),
+ "%T", dep->sysname);
+ DTRACE3(dist_port_not_busy, erts_this_node_sysname,
+ port_str, remote_str);
+ }
+#endif
}
else {
/* Enqueue suspended process on dist entry */
@@ -1667,6 +1775,19 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy)
}
if (suspended) {
+#ifdef USE_VM_PROBES
+ if (!resume && DTRACE_ENABLED(dist_port_busy)) {
+ DTRACE_CHARBUF(port_str, 64);
+ DTRACE_CHARBUF(remote_str, 64);
+ DTRACE_CHARBUF(pid_str, 16);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", cid);
+ erts_snprintf(remote_str, sizeof(remote_str), "%T", dep->sysname);
+ erts_snprintf(pid_str, sizeof(pid_str), "%T", c_p->id);
+ DTRACE4(dist_port_busy, erts_this_node_sysname,
+ port_str, remote_str, pid_str);
+ }
+#endif
if (!resume && erts_system_monitor_flags.busy_dist_port)
monitor_generic(c_p, am_busy_dist_port, cid);
return ERTS_DSIG_SEND_YIELD;
@@ -1690,6 +1811,18 @@ dist_port_command(Port *prt, ErtsDistOutputBuf *obuf)
"(%beu bytes) passed.\n",
size);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(dist_output)) {
+ DTRACE_CHARBUF(port_str, 64);
+ DTRACE_CHARBUF(remote_str, 64);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", prt->id);
+ erts_snprintf(remote_str, sizeof(remote_str),
+ "%T", prt->dist_entry->sysname);
+ DTRACE4(dist_output, erts_this_node_sysname, port_str,
+ remote_str, size);
+ }
+#endif
prt->caller = NIL;
fpe_was_unmasked = erts_block_fpe();
(*prt->drv_ptr->output)((ErlDrvData) prt->drv_data,
@@ -1732,6 +1865,18 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf)
ASSERT(prt->drv_ptr->outputv);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(dist_outputv)) {
+ DTRACE_CHARBUF(port_str, 64);
+ DTRACE_CHARBUF(remote_str, 64);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", prt->id);
+ erts_snprintf(remote_str, sizeof(remote_str),
+ "%T", prt->dist_entry->sysname);
+ DTRACE4(dist_outputv, erts_this_node_sysname, port_str,
+ remote_str, size);
+ }
+#endif
prt->caller = NIL;
fpe_was_unmasked = erts_block_fpe();
(*prt->drv_ptr->outputv)((ErlDrvData) prt->drv_data, &eiov);
@@ -2051,6 +2196,18 @@ erts_dist_command(Port *prt, int reds_limit)
void
erts_dist_port_not_busy(Port *prt)
{
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(dist_port_not_busy)) {
+ DTRACE_CHARBUF(port_str, 64);
+ DTRACE_CHARBUF(remote_str, 64);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", prt->id);
+ erts_snprintf(remote_str, sizeof(remote_str),
+ "%T", prt->dist_entry->sysname);
+ DTRACE3(dist_port_not_busy, erts_this_node_sysname,
+ port_str, remote_str);
+ }
+#endif
erts_schedule_dist_command(prt, NULL);
}
@@ -2330,11 +2487,11 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
#endif
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC);
+ erts_smp_thr_progress_block();
erts_set_this_node(BIF_ARG_1, (Uint32) creation);
erts_is_alive = 1;
send_nodes_mon_msgs(NULL, am_nodeup, BIF_ARG_1, am_visible, NIL);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
@@ -2730,85 +2887,92 @@ BIF_RETTYPE is_alive_0(BIF_ALIST_0)
/**********************************************************************/
/* erlang:monitor_node(Node, Bool, Options) -> Bool */
-BIF_RETTYPE monitor_node_3(BIF_ALIST_3)
+static BIF_RETTYPE
+monitor_node(Process* p, Eterm Node, Eterm Bool, Eterm Options)
{
DistEntry *dep;
ErtsLink *lnk;
Eterm l;
- for (l = BIF_ARG_3; l != NIL && is_list(l); l = CDR(list_val(l))) {
+ for (l = Options; l != NIL && is_list(l); l = CDR(list_val(l))) {
Eterm t = CAR(list_val(l));
/* allow_passive_connect the only available option right now */
if (t != am_allow_passive_connect) {
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
}
if (l != NIL) {
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- if (is_not_atom(BIF_ARG_1) ||
- ((BIF_ARG_2 != am_true) && (BIF_ARG_2 != am_false)) ||
+ if (is_not_atom(Node) ||
+ ((Bool != am_true) && (Bool != am_false)) ||
((erts_this_node->sysname == am_Noname)
- && (BIF_ARG_1 != erts_this_node->sysname))) {
- BIF_ERROR(BIF_P, BADARG);
+ && (Node != erts_this_node->sysname))) {
+ BIF_ERROR(p, BADARG);
}
- dep = erts_sysname_to_connected_dist_entry(BIF_ARG_1);
+ dep = erts_sysname_to_connected_dist_entry(Node);
if (!dep) {
do_trap:
- BIF_TRAP3(dmonitor_node_trap, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ BIF_TRAP3(dmonitor_node_trap, p, Node, Bool, Options);
}
if (dep == erts_this_dist_entry)
goto done;
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_LINK);
erts_smp_de_rlock(dep);
if (ERTS_DE_IS_NOT_CONNECTED(dep)) {
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK);
erts_smp_de_runlock(dep);
goto do_trap;
}
erts_smp_de_links_lock(dep);
erts_smp_de_runlock(dep);
- if (BIF_ARG_2 == am_true) {
+ if (Bool == am_true) {
ASSERT(dep->cid != NIL);
lnk = erts_add_or_lookup_link(&(dep->node_links), LINK_NODE,
- BIF_P->id);
+ p->id);
++ERTS_LINK_REFC(lnk);
- lnk = erts_add_or_lookup_link(&(BIF_P->nlinks), LINK_NODE, BIF_ARG_1);
+ lnk = erts_add_or_lookup_link(&(p->nlinks), LINK_NODE, Node);
++ERTS_LINK_REFC(lnk);
}
else {
- lnk = erts_lookup_link(dep->node_links, BIF_P->id);
+ lnk = erts_lookup_link(dep->node_links, p->id);
if (lnk != NULL) {
if ((--ERTS_LINK_REFC(lnk)) == 0) {
erts_destroy_link(erts_remove_link(&(dep->node_links),
- BIF_P->id));
+ p->id));
}
}
- lnk = erts_lookup_link(BIF_P->nlinks, BIF_ARG_1);
+ lnk = erts_lookup_link(p->nlinks, Node);
if (lnk != NULL) {
if ((--ERTS_LINK_REFC(lnk)) == 0) {
- erts_destroy_link(erts_remove_link(&(BIF_P->nlinks),
- BIF_ARG_1));
+ erts_destroy_link(erts_remove_link(&(p->nlinks),
+ Node));
}
}
}
erts_smp_de_links_unlock(dep);
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK);
done:
erts_deref_dist_entry(dep);
BIF_RET(am_true);
}
+BIF_RETTYPE monitor_node_3(BIF_ALIST_3)
+{
+ BIF_RET(monitor_node(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3));
+}
+
+
/* monitor_node(Node, Bool) -> Bool */
BIF_RETTYPE monitor_node_2(BIF_ALIST_2)
{
- BIF_RET(monitor_node_3(BIF_P,BIF_ARG_1,BIF_ARG_2,NIL));
+ BIF_RET(monitor_node(BIF_P, BIF_ARG_1, BIF_ARG_2, NIL));
}
BIF_RETTYPE net_kernel_dflag_unicode_io_1(BIF_ALIST_1)
@@ -2964,7 +3128,11 @@ send_nodes_mon_msg(Process *rp,
}
ASSERT(hend == hp);
- erts_queue_message(rp, rp_locksp, bp, msg, NIL);
+ erts_queue_message(rp, rp_locksp, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
static void
@@ -2977,6 +3145,21 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas
ASSERT(is_immed(what));
ASSERT(is_immed(node));
ASSERT(is_immed(type));
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(dist_monitor)) {
+ DTRACE_CHARBUF(what_str, 12);
+ DTRACE_CHARBUF(node_str, 64);
+ DTRACE_CHARBUF(type_str, 12);
+ DTRACE_CHARBUF(reason_str, 64);
+
+ erts_snprintf(what_str, sizeof(what_str), "%T", what);
+ erts_snprintf(node_str, sizeof(node_str), "%T", node);
+ erts_snprintf(type_str, sizeof(type_str), "%T", type);
+ erts_snprintf(reason_str, sizeof(reason_str), "%T", reason);
+ DTRACE5(dist_monitor, erts_this_node_sysname,
+ what_str, node_str, type_str, reason_str);
+ }
+#endif
ERTS_SMP_LC_ASSERT(!c_p
|| (erts_proc_lc_my_proc_locks(c_p)
diff --git a/erts/emulator/beam/dtrace-wrapper.h b/erts/emulator/beam/dtrace-wrapper.h
new file mode 100644
index 0000000000..6ec0c91e21
--- /dev/null
+++ b/erts/emulator/beam/dtrace-wrapper.h
@@ -0,0 +1,111 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Dustin Sallings, Michal Ptaszek, Scott Lystig Fritchie 2011-2012.
+ * All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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 __DTRACE_WRAPPER_H
+#define __DTRACE_WRAPPER_H
+
+#define DTRACE_TERM_BUF_SIZE 256
+
+/*
+ * Some varieties of SystemTap macros do not like statically-sized
+ * char[N] buffers. (For example, CentOS 6's macros.)
+ * So, we'll play a game to humor them.
+ *
+ * The code necessary to play nice with CentOS 6's SystemTap looks
+ * stupid to a C programmer's eyes, so we hide the ugliness with this
+ * macro, which expands:
+ *
+ * DTRACE_CHARBUF(proc_name, 64);
+ *
+ * to become:
+ *
+ * char proc_name_BUFFER[64], *proc_name = proc_name_BUFFER;
+ */
+
+#define DTRACE_CHARBUF(name, size) \
+ char name##_BUFFER[size], *name = name##_BUFFER
+
+#define DTRACE_CHARBUF_NAME(name) name##_BUFFER
+
+#if defined(USE_DYNAMIC_TRACE) && defined(USE_VM_PROBES)
+
+#include "erlang_dtrace.h"
+
+#define DTRACE_ENABLED(name) \
+ erlang_##name##_enabled()
+#define DTRACE0(name) \
+ erlang_##name()
+#define DTRACE1(name, a0) \
+ erlang_##name(a0)
+#define DTRACE2(name, a0, a1) \
+ erlang_##name((a0), (a1))
+#define DTRACE3(name, a0, a1, a2) \
+ erlang_##name((a0), (a1), (a2))
+#define DTRACE4(name, a0, a1, a2, a3) \
+ erlang_##name((a0), (a1), (a2), (a3))
+#define DTRACE5(name, a0, a1, a2, a3, a4) \
+ erlang_##name((a0), (a1), (a2), (a3), (a4))
+#define DTRACE6(name, a0, a1, a2, a3, a4, a5) \
+ erlang_##name((a0), (a1), (a2), (a3), (a4), (a5))
+#define DTRACE7(name, a0, a1, a2, a3, a4, a5, a6) \
+ erlang_##name((a0), (a1), (a2), (a3), (a4), (a5), (a6))
+#define DTRACE10(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ erlang_##name((a0), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8), (a9))
+#define DTRACE11(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ erlang_##name((a0), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8), (a9), (a10))
+
+#if defined(_SDT_PROBE) && !defined(STAP_PROBE11)
+/* SLF: This is Ubuntu 11-style SystemTap hackery */
+/* work arround for missing STAP macro */
+#define STAP_PROBE11(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \
+ _SDT_PROBE(provider, name, 11, \
+ (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11))
+#define _SDT_ASM_OPERANDS_11(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \
+ _SDT_ASM_OPERANDS_10(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,arg10), \
+ _SDT_ARG(11, arg11)
+#endif
+
+#ifdef STAP_PROBE_ADDR
+/* SLF: This is CentOS 5-style SystemTap hackery */
+/* SystemTap compat mode cannot support 11 args. We'll ignore the 11th */
+#define STAP_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11) \
+ STAP_PROBE10(provider,probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10))
+#endif /* STAP_PROBE_ADDR */
+
+#else /* USE_DYNAMIC_TRACE && USE_VM_PROBES */
+
+/* Render all macros to do nothing */
+#define DTRACE_ENABLED(name) 0
+#define DTRACE0(name) do {} while (0)
+#define DTRACE1(name, a0) do {} while (0)
+#define DTRACE2(name, a0, a1) do {} while (0)
+#define DTRACE3(name, a0, a1, a2) do {} while (0)
+#define DTRACE4(name, a0, a1, a2, a3) do {} while (0)
+#define DTRACE5(name, a0, a1, a2, a3, a4) do {} while (0)
+#define DTRACE6(name, a0, a1, a2, a3, a4, a5) do {} while (0)
+#define DTRACE7(name, a0, a1, a2, a3, a4, a5, a6) do {} while (0)
+#define DTRACE10(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ do {} while (0)
+#define DTRACE11(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ do {} while (0)
+
+#endif /* USE_DYNAMIC_TRACE && USE_VM_PROBES */
+
+#endif /* __DTRACE_WRAPPER_H */
diff --git a/erts/emulator/beam/erl_afit_alloc.c b/erts/emulator/beam/erl_afit_alloc.c
index bcc7ea04ae..570cc59be2 100644
--- a/erts/emulator/beam/erl_afit_alloc.c
+++ b/erts/emulator/beam/erl_afit_alloc.c
@@ -65,16 +65,20 @@ erts_afalc_start(AFAllctr_t *afallctr,
AFAllctrInit_t *afinit,
AllctrInit_t *init)
{
- AFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ AFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) afallctr;
- init->sbmbct = 0; /* Small mbc not supported by afit */
+ sys_memcpy((void *) afallctr, (void *) &zero.allctr, sizeof(AFAllctr_t));
- sys_memcpy((void *) afallctr, (void *) &nulled_state, sizeof(AFAllctr_t));
+ init->sbmbct = 0; /* Small mbc not supported by afit */
allctr->mbc_header_size = sizeof(Carrier_t);
allctr->min_mbc_size = MIN_MBC_SZ;
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 9af80dd7a9..6fce032f9d 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2012. All Rights Reserved.
*
* The 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,6 +40,8 @@
#include "erl_mseg.h"
#include "erl_monitors.h"
#include "erl_bif_timer.h"
+#include "erl_cpu_topology.h"
+#include "erl_thr_queue.h"
#if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
#include "erl_check_io.h"
#endif
@@ -54,7 +56,14 @@
#include "erl_ao_firstfit_alloc.h"
-#define ERTS_ALC_DEFAULT_MAX_THR_PREF 16
+#if ERTS_MAX_NO_OF_SCHEDULERS > ERTS_AU_MAX_PREF_ALLOC_INSTANCES
+# error "Too many schedulers; cannot create that many pref alloc instances"
+#endif
+
+#define ERTS_ALC_FIX_TYPE_IX(T) \
+ (ERTS_ALC_T2N((T)) - ERTS_ALC_N_MIN_A_FIXED_SIZE)
+
+#define ERTS_ALC_DEFAULT_MAX_THR_PREF ERTS_MAX_NO_OF_SCHEDULERS
#if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)
#define AU_ALLOC_DEFAULT_ENABLE(X) 0
@@ -106,24 +115,43 @@ static ErtsAllocatorState_t eheap_alloc_state;
static ErtsAllocatorState_t binary_alloc_state;
static ErtsAllocatorState_t ets_alloc_state;
static ErtsAllocatorState_t driver_alloc_state;
+static ErtsAllocatorState_t fix_alloc_state;
-ErtsAlcType_t erts_fix_core_allocator_ix;
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-static void *(*fix_core_allocator)(ErtsAlcType_t, void *, Uint);
-static void *fix_core_extra;
-static void *fix_core_alloc(Uint size)
+typedef struct {
+ erts_smp_atomic32_t refc;
+ int only_sz;
+ Uint req_sched;
+ Process *proc;
+ Eterm ref;
+ Eterm ref_heap[REF_THING_SIZE];
+ int allocs[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+1+2];
+} ErtsAllocInfoReq;
+
+#define ERTS_ALC_INFO_A_ALLOC_UTIL (ERTS_ALC_A_MAX + 1)
+#define ERTS_ALC_INFO_A_MSEG_ALLOC (ERTS_ALC_A_MAX + 2)
+#define ERTS_ALC_INFO_A_MAX ERTS_ALC_INFO_A_MSEG_ALLOC
+
+#if !HALFWORD_HEAP
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq,
+ ErtsAllocInfoReq,
+ 5,
+ ERTS_ALC_T_AINFO_REQ)
+#else
+static ERTS_INLINE ErtsAllocInfoReq *
+aireq_alloc(void)
{
- void *res;
- res = (*fix_core_allocator)(ERTS_ALC_T_UNDEF, fix_core_extra, size);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_alloc(res,
- ERTS_ALC_A_FIXED_SIZE,
- erts_fix_core_allocator_ix,
- size);
- return res;
+ return erts_alloc(ERTS_ALC_T_AINFO_REQ, sizeof(ErtsAllocInfoReq));
+}
+
+static ERTS_INLINE void
+aireq_free(ErtsAllocInfoReq *ptr)
+{
+ erts_free(ERTS_ALC_T_AINFO_REQ, ptr);
}
#endif
+ErtsAlcType_t erts_fix_core_allocator_ix;
+
enum allctr_type {
GOODFIT,
BESTFIT,
@@ -181,6 +209,7 @@ typedef struct {
struct au_init binary_alloc;
struct au_init ets_alloc;
struct au_init driver_alloc;
+ struct au_init fix_alloc;
#if HALFWORD_HEAP
struct au_init sbmbc_low_alloc;
struct au_init std_low_alloc;
@@ -393,46 +422,52 @@ set_default_driver_alloc_opts(struct au_init *ip)
ip->init.util.ts = ERTS_ALC_MTA_DRIVER;
}
+static void
+set_default_fix_alloc_opts(struct au_init *ip,
+ size_t *fix_type_sizes)
+{
+ SET_DEFAULT_ALLOC_OPTS(ip);
+ ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
+ ip->thr_spec = 1;
+ ip->atype = BESTFIT;
+ ip->init.bf.ao = 1;
+ ip->init.util.name_prefix = "fix_";
+ ip->init.util.fix_type_size = fix_type_sizes;
+ ip->init.util.alloc_no = ERTS_ALC_A_FIXED_SIZE;
+#ifndef SMALL_MEMORY
+ ip->init.util.mmbcs = 128*1024; /* Main carrier size */
+#else
+ ip->init.util.mmbcs = 128*1024; /* Main carrier size */
+#endif
+ ip->init.util.ts = ERTS_ALC_MTA_FIXED_SIZE;
+}
+
#ifdef ERTS_SMP
static void
adjust_tpref(struct au_init *ip, int no_sched)
{
if (ip->thr_spec) {
- Uint allocs;
- if (ip->thr_spec < 0) {/* User specified amount */
- allocs = abs(ip->thr_spec);
- if (allocs > no_sched)
- allocs = no_sched;
- }
- else if (no_sched > ERTS_ALC_DEFAULT_MAX_THR_PREF)
- allocs = ERTS_ALC_DEFAULT_MAX_THR_PREF;
- else
- allocs = no_sched;
- if (allocs <= 1)
- ip->thr_spec = 0;
- else {
- ip->thr_spec = (int) allocs;
- ip->thr_spec *= -1; /* thread preferred */
-
- /* If default ... */
-
- /* ... shrink main multi-block carrier size */
- if (ip->default_.mmbcs)
- ip->init.util.mmbcs /= ERTS_MIN(4, allocs);
- /* ... shrink largest multi-block carrier size */
- if (ip->default_.lmbcs)
- ip->init.util.lmbcs /= ERTS_MIN(2, allocs);
- /* ... shrink smallest multi-block carrier size */
- if (ip->default_.smbcs)
- ip->init.util.smbcs /= ERTS_MIN(4, allocs);
- /* ... and more than three allocators shrink
- max mseg multi-block carriers */
- if (ip->default_.mmmbc && allocs > 2) {
- ip->init.util.mmmbc /= ERTS_MIN(4, allocs - 1);
- if (ip->init.util.mmmbc < 3)
- ip->init.util.mmmbc = 3;
- }
+ ip->thr_spec = no_sched;
+ ip->thr_spec *= -1; /* thread preferred */
+
+ /* If default ... */
+
+ /* ... shrink main multi-block carrier size */
+ if (ip->default_.mmbcs)
+ ip->init.util.mmbcs /= ERTS_MIN(4, no_sched);
+ /* ... shrink largest multi-block carrier size */
+ if (ip->default_.lmbcs)
+ ip->init.util.lmbcs /= ERTS_MIN(2, no_sched);
+ /* ... shrink smallest multi-block carrier size */
+ if (ip->default_.smbcs)
+ ip->init.util.smbcs /= ERTS_MIN(4, no_sched);
+ /* ... and more than three allocators shrink
+ max mseg multi-block carriers */
+ if (ip->default_.mmmbc && no_sched > 2) {
+ ip->init.util.mmmbc /= ERTS_MIN(4, no_sched - 1);
+ if (ip->init.util.mmmbc < 3)
+ ip->init.util.mmmbc = 3;
}
}
}
@@ -442,7 +477,7 @@ adjust_tpref(struct au_init *ip, int no_sched)
static void handle_args(int *, char **, erts_alc_hndl_args_init_t *);
static void
-set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init);
+set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu);
static void
start_au_allocator(ErtsAlcType_t alctr_n,
@@ -456,8 +491,6 @@ refuse_af_strategy(struct au_init *init)
init->atype = GOODFIT;
}
-static void init_thr_ix(int static_ixs);
-
#ifdef HARD_DEBUG
static void hdbg_init(void);
#endif
@@ -466,7 +499,7 @@ void
erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
{
UWord extra_block_size = 0;
- int i;
+ int i, ncpu;
erts_alc_hndl_args_init_t init = {
0,
#if HAVE_ERTS_MSEG
@@ -474,17 +507,38 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
#endif
ERTS_DEFAULT_TRIM_THRESHOLD,
ERTS_DEFAULT_TOP_PAD,
- ERTS_DEFAULT_ALCU_INIT
+ ERTS_DEFAULT_ALCU_INIT,
};
+ size_t fix_type_sizes[ERTS_ALC_NO_FIXED_SIZES] = {0};
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_PROC)]
+ = sizeof(Process);
+#if !HALFWORD_HEAP
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR_SH)]
+ = ERTS_MONITOR_SH_SIZE;
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NLINK_SH)]
+ = ERTS_LINK_SH_SIZE;
+#endif
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_EV_D_STATE)]
+ = sizeof(ErtsDrvEventDataState);
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
+ = sizeof(ErtsDrvSelectDataState);
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
+ = sizeof(ErlMessage);
+#ifdef ERTS_SMP
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
+ = sizeof(ErtsThrQElement_t);
+#endif
#ifdef HARD_DEBUG
hdbg_init();
#endif
erts_have_sbmbc_alloc = 0;
+ ncpu = eaiop->ncpu;
+ if (ncpu < 1)
+ ncpu = 1;
erts_sys_alloc_init();
- init_thr_ix(erts_no_schedulers);
erts_init_utils_mem();
set_default_sbmbc_alloc_opts(&init.sbmbc_alloc);
@@ -496,20 +550,23 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
set_default_binary_alloc_opts(&init.binary_alloc);
set_default_ets_alloc_opts(&init.ets_alloc);
set_default_driver_alloc_opts(&init.driver_alloc);
+ set_default_fix_alloc_opts(&init.fix_alloc,
+ fix_type_sizes);
if (argc && argv)
handle_args(argc, argv, &init);
- if (erts_no_schedulers <= 1) {
- init.sbmbc_alloc.thr_spec = 0;
- init.sl_alloc.thr_spec = 0;
- init.std_alloc.thr_spec = 0;
- init.ll_alloc.thr_spec = 0;
- init.eheap_alloc.thr_spec = 0;
- init.binary_alloc.thr_spec = 0;
- init.ets_alloc.thr_spec = 0;
- init.driver_alloc.thr_spec = 0;
- }
+#ifndef ERTS_SMP
+ init.sbmbc_alloc.thr_spec = 0;
+ init.sl_alloc.thr_spec = 0;
+ init.std_alloc.thr_spec = 0;
+ init.ll_alloc.thr_spec = 0;
+ init.eheap_alloc.thr_spec = 0;
+ init.binary_alloc.thr_spec = 0;
+ init.ets_alloc.thr_spec = 0;
+ init.driver_alloc.thr_spec = 0;
+ init.fix_alloc.thr_spec = 0;
+#endif
if (init.erts_alloc_config) {
/* Adjust flags that erts_alloc_config won't like */
@@ -522,6 +579,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.binary_alloc.thr_spec = 0;
init.ets_alloc.thr_spec = 0;
init.driver_alloc.thr_spec = 0;
+ init.fix_alloc.thr_spec = 0;
}
#ifdef ERTS_SMP
@@ -538,6 +596,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
adjust_tpref(&init.binary_alloc, erts_no_schedulers);
adjust_tpref(&init.ets_alloc, erts_no_schedulers);
adjust_tpref(&init.driver_alloc, erts_no_schedulers);
+ adjust_tpref(&init.fix_alloc, erts_no_schedulers);
#else
/* No thread specific if not smp */
@@ -556,6 +615,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
refuse_af_strategy(&init.binary_alloc);
refuse_af_strategy(&init.ets_alloc);
refuse_af_strategy(&init.driver_alloc);
+ refuse_af_strategy(&init.fix_alloc);
#ifdef ERTS_SMP
if (!init.temp_alloc.thr_spec)
@@ -564,6 +624,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
erts_mtrace_pre_init();
#if HAVE_ERTS_MSEG
+ init.mseg.nos = erts_no_schedulers;
erts_mseg_init(&init.mseg);
#endif
erts_alcu_init(&init.alloc_util);
@@ -583,20 +644,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
erts_allctrs_info[i].extra = NULL;
}
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-#if !defined(PURIFY) && !defined(VALGRIND)
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc = erts_fix_alloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc = erts_fix_realloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free = erts_fix_free;
- erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled = 1;
-#else
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc = erts_sys_alloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc = erts_sys_realloc;
- erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free = erts_sys_free;
- erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled = 0;
-#endif
-#endif
-
erts_allctrs[ERTS_ALC_A_SYSTEM].alloc = erts_sys_alloc;
erts_allctrs[ERTS_ALC_A_SYSTEM].realloc = erts_sys_realloc;
erts_allctrs[ERTS_ALC_A_SYSTEM].free = erts_sys_free;
@@ -621,20 +668,21 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ll_low_alloc.init.util.force = 1;
init.ll_low_alloc.init.util.low_mem = 1;
- set_au_allocator(ERTS_ALC_A_SBMBC_LOW, &init.sbmbc_low_alloc);
- set_au_allocator(ERTS_ALC_A_STANDARD_LOW, &init.std_low_alloc);
- set_au_allocator(ERTS_ALC_A_LONG_LIVED_LOW, &init.ll_low_alloc);
+ set_au_allocator(ERTS_ALC_A_SBMBC_LOW, &init.sbmbc_low_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_STANDARD_LOW, &init.std_low_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_LONG_LIVED_LOW, &init.ll_low_alloc, ncpu);
#endif /* HALFWORD */
- set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc);
- set_au_allocator(ERTS_ALC_A_SBMBC, &init.sbmbc_alloc);
- set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc);
- set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc);
- set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc);
- set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc);
- set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc);
- set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc);
- set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc);
+ set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_SBMBC, &init.sbmbc_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
if (!erts_allctrs[i].alloc)
@@ -650,10 +698,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
- if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled)
- erts_fix_core_allocator_ix = ERTS_FIX_CORE_ALLOCATOR;
- else
- erts_fix_core_allocator_ix = ERTS_ALC_A_SYSTEM;
erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
@@ -710,49 +754,40 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
&init.driver_alloc,
&driver_alloc_state);
- fix_core_allocator = erts_allctrs[erts_fix_core_allocator_ix].alloc;
- fix_core_extra = erts_allctrs[erts_fix_core_allocator_ix].extra;
+ start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
+ &init.fix_alloc,
+ &fix_alloc_state);
erts_mtrace_install_wrapper_functions();
extra_block_size += erts_instr_init(init.instr.stat, init.instr.map);
+#if !HALFWORD_HEAP
+ init_aireq_alloc();
+#endif
+
#ifdef DEBUG
extra_block_size += install_debug_functions();
#endif
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-
- erts_init_fix_alloc(extra_block_size, fix_core_alloc);
-
+}
-#if !defined(PURIFY) && !defined(VALGRIND)
- erts_set_fix_size(ERTS_ALC_T_PROC, sizeof(Process));
- erts_set_fix_size(ERTS_ALC_T_DB_TABLE, sizeof(DbTable));
- erts_set_fix_size(ERTS_ALC_T_ATOM, sizeof(Atom));
+void
+erts_alloc_late_init(void)
+{
- erts_set_fix_size(ERTS_ALC_T_MODULE, sizeof(Module));
- erts_set_fix_size(ERTS_ALC_T_REG_PROC, sizeof(RegProc));
- erts_set_fix_size(ERTS_ALC_T_FUN_ENTRY, sizeof(ErlFunEntry));
-#ifdef ERTS_ALC_T_DRV_EV_D_STATE
- erts_set_fix_size(ERTS_ALC_T_DRV_EV_D_STATE,
- sizeof(ErtsDrvEventDataState));
-#endif
-#ifdef ERTS_ALC_T_DRV_SEL_D_STATE
- erts_set_fix_size(ERTS_ALC_T_DRV_SEL_D_STATE,
- sizeof(ErtsDrvSelectDataState));
-#endif
-#if !HALFWORD_HEAP
- erts_set_fix_size(ERTS_ALC_T_EXPORT, sizeof(Export));
- erts_set_fix_size(ERTS_ALC_T_MONITOR_SH, ERTS_MONITOR_SH_SIZE*sizeof(Uint));
- erts_set_fix_size(ERTS_ALC_T_NLINK_SH, ERTS_LINK_SH_SIZE*sizeof(Uint));
-#endif
-#endif
-#endif
+}
+static void *
+erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size)
+{
+ erl_exit(ERTS_ABORT_EXIT,
+ "Attempt to reallocate a block of the fixed size type %s\n",
+ ERTS_ALC_T2TD(type));
}
+
static void
-set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
+set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
{
ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
@@ -764,6 +799,12 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
if (init->init.util.force)
init->enable = 1;
+ tspec->enabled = 0;
+ tspec->dd = 0;
+ tspec->aix = alctr_n;
+ tspec->size = 0;
+ ai->thr_spec = 0;
+
if (!init->enable) {
af->alloc = erts_sys_alloc;
af->realloc = erts_sys_realloc;
@@ -775,14 +816,14 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
return;
}
- tspec->enabled = 0;
- tspec->all_thr_safe = 0;
- ai->thr_spec = 0;
#ifdef USE_THREADS
+#ifdef ERTS_SMP
if (init->thr_spec) {
if (init->thr_spec > 0) {
af->alloc = erts_alcu_alloc_thr_spec;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv_thr_spec;
else
af->realloc = erts_alcu_realloc_thr_spec;
@@ -790,12 +831,14 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
}
else {
af->alloc = erts_alcu_alloc_thr_pref;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv_thr_pref;
else
af->realloc = erts_alcu_realloc_thr_pref;
af->free = erts_alcu_free_thr_pref;
- tspec->all_thr_safe = 1;
+ tspec->dd = 1;
}
tspec->enabled = 1;
@@ -803,9 +846,13 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
ai->thr_spec = tspec->size;
}
- else if (init->init.util.ts) {
+ else
+#endif
+ if (init->init.util.ts) {
af->alloc = erts_alcu_alloc_ts;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv_ts;
else
af->realloc = erts_alcu_realloc_ts;
@@ -815,7 +862,9 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
#endif
{
af->alloc = erts_alcu_alloc;
- if (init->init.util.ramv)
+ if (init->init.util.fix_type_size)
+ af->realloc = erts_realloc_fixed_size;
+ else if (init->init.util.ramv)
af->realloc = erts_alcu_realloc_mv;
else
af->realloc = erts_alcu_realloc;
@@ -838,12 +887,14 @@ start_au_allocator(ErtsAlcType_t alctr_n,
ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
+ ErtsAlcFixList_t *fix_lists = NULL;
+ size_t fix_list_size = 0;
if (!init->enable)
return;
if (init->thr_spec) {
- void *states = erts_sys_alloc(0,
+ char *states = erts_sys_alloc(0,
NULL,
((sizeof(Allctr_t *)
* (tspec->size + 1))
@@ -855,18 +906,40 @@ start_au_allocator(ErtsAlcType_t alctr_n,
"Failed to allocate allocator states for %salloc\n",
init->init.util.name_prefix);
tspec->allctr = (Allctr_t **) states;
- states = ((char *) states) + sizeof(Allctr_t *) * (tspec->size + 1);
+ states += sizeof(Allctr_t *) * (tspec->size + 1);
states = ((((UWord) states) & ERTS_CACHE_LINE_MASK)
- ? (void *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
+ ? (char *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
+ ERTS_CACHE_LINE_SIZE)
- : (void *) states);
- tspec->allctr[0] = init->thr_spec > 0 ? (Allctr_t *) state : (Allctr_t *) NULL;
+ : (char *) states);
+ tspec->allctr[0] = (Allctr_t *) state;
size = tspec->size;
for (i = 1; i < size; i++)
tspec->allctr[i] = (Allctr_t *)
&((ErtsAllocatorState_t *) states)[i-1];
}
+ if (init->init.util.fix_type_size) {
+ size_t tot_fix_list_size;
+ fix_list_size = sizeof(ErtsAlcFixList_t)*ERTS_ALC_NO_FIXED_SIZES;
+ fix_list_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(fix_list_size);
+ tot_fix_list_size = fix_list_size;
+ if (init->thr_spec)
+ tot_fix_list_size *= tspec->size;
+ fix_lists = erts_sys_alloc(0,
+ NULL,
+ (tot_fix_list_size
+ + ERTS_CACHE_LINE_SIZE - 1));
+ if (!fix_lists)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Failed to allocate fix lists for %salloc\n",
+ init->init.util.name_prefix);
+
+ if (((UWord) fix_lists) & ERTS_CACHE_LINE_MASK)
+ fix_lists = ((ErtsAlcFixList_t *)
+ ((((UWord) fix_lists) & ~ERTS_CACHE_LINE_MASK)
+ + ERTS_CACHE_LINE_SIZE));
+ }
+
for (i = 0; i < size; i++) {
void *as;
atype = init->atype;
@@ -877,25 +950,32 @@ start_au_allocator(ErtsAlcType_t alctr_n,
as0 = (void *) tspec->allctr[i];
if (!as0)
continue;
- if (i == 0) {
- if (atype == AFIT)
- atype = GOODFIT;
- init->init.util.ts = 1;
+ if (init->thr_spec < 0) {
+ init->init.util.ts = i == 0;
+ init->init.util.tspec = 0;
+ init->init.util.tpref = -1*init->thr_spec + 1;
}
else {
- if (init->thr_spec < 0) {
+ if (i != 0)
+ init->init.util.ts = 0;
+ else {
+ if (atype == AFIT)
+ atype = GOODFIT;
init->init.util.ts = 1;
- init->init.util.tspec = 0;
- init->init.util.tpref = -1*init->thr_spec;
}
- else {
- init->init.util.ts = 0;
- init->init.util.tspec = init->thr_spec + 1;
- init->init.util.tpref = 0;
- }
- }
+ init->init.util.tspec = init->thr_spec + 1;
+ init->init.util.tpref = 0;
+ }
+ }
+
+ if (fix_lists) {
+ init->init.util.fix = fix_lists;
+ fix_lists = ((ErtsAlcFixList_t *)
+ (((char *) fix_lists) + fix_list_size));
}
+ init->init.util.ix = i;
+
switch (atype) {
case GOODFIT:
as = (void *) erts_gfalc_start((GFAllctr_t *) as0,
@@ -931,11 +1011,8 @@ start_au_allocator(ErtsAlcType_t alctr_n,
af->extra = as;
}
- if (init->thr_spec) {
+ if (init->thr_spec)
af->extra = tspec;
- init->init.util.ts = 1;
- }
-
ai->extra = af->extra;
}
@@ -1018,7 +1095,7 @@ get_kb_value(char *param_end, char** argv, int* ip)
char *param = argv[*ip]+1;
char *value = get_value(param_end, argv, ip);
errno = 0;
- tmp = (Sint) strtol(value, &rest, 10);
+ tmp = (Sint) ErtsStrToSint(value, &rest, 10);
if (errno != 0 || rest == value || tmp < 0 || max < ((Uint) tmp))
bad_value(param, param_end, value);
if (max == (Uint) tmp)
@@ -1035,7 +1112,7 @@ get_byte_value(char *param_end, char** argv, int* ip)
char *param = argv[*ip]+1;
char *value = get_value(param_end, argv, ip);
errno = 0;
- tmp = (Sint) strtol(value, &rest, 10);
+ tmp = (Sint) ErtsStrToSint(value, &rest, 10);
if (errno != 0 || rest == value || tmp < 0)
bad_value(param, param_end, value);
return (Uint) tmp;
@@ -1049,40 +1126,12 @@ get_amount_value(char *param_end, char** argv, int* ip)
char *param = argv[*ip]+1;
char *value = get_value(param_end, argv, ip);
errno = 0;
- tmp = (Sint) strtol(value, &rest, 10);
+ tmp = (Sint) ErtsStrToSint(value, &rest, 10);
if (errno != 0 || rest == value || tmp < 0)
bad_value(param, param_end, value);
return (Uint) tmp;
}
-static int
-get_bool_or_possitive_amount_value(int *bool, Uint *amount,
- char *param_end, char** argv, int* ip)
-{
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- if (strcmp(value, "true") == 0) {
- *bool = 1;
- return 1;
- }
- else if (strcmp(value, "false") == 0) {
- *bool = 0;
- return 1;
- }
- else {
- Sint tmp;
- char *rest;
- errno = 0;
- tmp = (Sint) strtol(value, &rest, 10);
- if (errno != 0 || rest == value || tmp <= 0) {
- bad_value(param, param_end, value);
- return -1;
- }
- *amount = (Uint) tmp;
- return 0;
- }
-}
-
static void
handle_au_arg(struct au_init *auip,
char* sub_param,
@@ -1197,25 +1246,16 @@ handle_au_arg(struct au_init *auip,
goto bad_switch;
break;
case 't': {
- Uint no;
- int enable;
- int res = get_bool_or_possitive_amount_value(&enable,
- &no,
- sub_param+1,
- argv,
- ip);
- if (res > 0)
- auip->thr_spec = enable ? 1 : 0;
+ int res = get_bool_value(sub_param+1, argv, ip);
+ if (res > 0) {
+ auip->thr_spec = 1;
+ break;
+ }
else if (res == 0) {
- int allocs = (int) no;
- if (allocs < 0)
- allocs = INT_MIN;
- else {
- allocs *= -1;
- }
- auip->thr_spec = allocs;
+ auip->thr_spec = 0;
+ break;
}
- break;
+ goto bad_switch;
}
default:
bad_switch:
@@ -1234,6 +1274,7 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
&init->eheap_alloc,
&init->ll_alloc,
&init->driver_alloc,
+ &init->fix_alloc,
&init->sl_alloc,
&init->temp_alloc
};
@@ -1264,14 +1305,8 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
case 'E':
handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i);
break;
- case 'F': /* fix_alloc */
- if (has_prefix("e", param+2)) {
- arg = get_value(param+3, argv, &i);
- if (strcmp("true", arg) != 0)
- bad_value(param, param+3, arg);
- }
- else
- bad_param(param, param+2);
+ case 'F':
+ handle_au_arg(&init->fix_alloc, &argv[i][3], argv, &i);
break;
case 'H':
handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i);
@@ -1298,12 +1333,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
#endif
get_amount_value(argv[i]+6, argv, &i);
}
- else if (has_prefix("cci", argv[i]+3)) {
-#if HAVE_ERTS_MSEG
- init->mseg.cci =
-#endif
- get_amount_value(argv[i]+6, argv, &i);
- }
else {
bad_param(param, param+2);
}
@@ -1389,6 +1418,7 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
set_default_binary_alloc_opts(&init->binary_alloc);
set_default_ets_alloc_opts(&init->ets_alloc);
set_default_driver_alloc_opts(&init->driver_alloc);
+ set_default_driver_alloc_opts(&init->fix_alloc);
init->driver_alloc.enable = 0;
if (strcmp("r9c", arg) == 0) {
@@ -1523,43 +1553,78 @@ static char *type_no_str(ErtsAlcType_t n)
#define type_str(T) type_no_str(ERTS_ALC_T2N((T)))
-erts_tsd_key_t thr_ix_key;
-erts_spinlock_t alloc_thr_ix_lock;
-int last_thr_ix;
-int first_dyn_thr_ix;
-
-static void
-init_thr_ix(int static_ixs)
+void
+erts_alloc_register_scheduler(void *vesdp)
{
- erts_tsd_key_create(&thr_ix_key);
- erts_spinlock_init(&alloc_thr_ix_lock, "alloc_thr_ix_lock");
- last_thr_ix = -4711;
- first_dyn_thr_ix = static_ixs+1;
+ ErtsSchedulerData *esdp = (ErtsSchedulerData *) vesdp;
+ int ix = (int) esdp->no;
+ int aix;
+
+ for (aix = ERTS_ALC_A_MIN; aix <= ERTS_ALC_A_MAX; aix++) {
+ ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[aix];
+ esdp->alloc_data.deallctr[aix] = NULL;
+ esdp->alloc_data.pref_ix[aix] = -1;
+ if (tspec->enabled) {
+ if (!tspec->dd)
+ esdp->alloc_data.pref_ix[aix] = ix;
+ else {
+ Allctr_t *allctr = tspec->allctr[ix];
+ ASSERT(allctr);
+ esdp->alloc_data.deallctr[aix] = allctr;
+ esdp->alloc_data.pref_ix[aix] = ix;
+ }
+ }
+ }
}
-int
-erts_alc_get_thr_ix(void)
+#ifdef ERTS_SMP
+void
+erts_alloc_scheduler_handle_delayed_dealloc(void *vesdp,
+ int *need_thr_progress,
+ ErtsThrPrgrVal *thr_prgr_p,
+ int *more_work)
{
- int ix = (int)(long) erts_tsd_get(thr_ix_key);
- if (ix == 0) {
- erts_spin_lock(&alloc_thr_ix_lock);
- last_thr_ix++;
- if (last_thr_ix < 0)
- last_thr_ix = first_dyn_thr_ix;
- ix = last_thr_ix;
- erts_spin_unlock(&alloc_thr_ix_lock);
- erts_tsd_set(thr_ix_key, (void *)(long) ix);
+ ErtsSchedulerData *esdp = (ErtsSchedulerData *) vesdp;
+ int aix;
+ for (aix = ERTS_ALC_A_MIN; aix <= ERTS_ALC_A_MAX; aix++) {
+ Allctr_t *allctr;
+ if (esdp)
+ allctr = esdp->alloc_data.deallctr[aix];
+ else {
+ ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[aix];
+ if (tspec->enabled && tspec->dd)
+ allctr = tspec->allctr[0];
+ else
+ allctr = NULL;
+ }
+ if (allctr) {
+ erts_alcu_check_delayed_dealloc(allctr,
+ 1,
+ need_thr_progress,
+ thr_prgr_p,
+ more_work);
+ }
}
- ASSERT(ix > 0);
- return ix;
}
+#endif
-void erts_alloc_reg_scheduler_id(Uint id)
+erts_aint32_t
+erts_alloc_fix_alloc_shrink(int ix, erts_aint32_t flgs)
{
- int ix = (int) id;
- ASSERT(0 < ix && ix <= first_dyn_thr_ix);
- ASSERT(0 == (int) (long) erts_tsd_get(thr_ix_key));
- erts_tsd_set(thr_ix_key, (void *)(long) ix);
+#ifdef ERTS_SMP
+ ErtsAllocatorThrSpec_t *tspec;
+ tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE];
+ if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec && tspec->enabled)
+ return erts_alcu_fix_alloc_shrink(tspec->allctr[ix], flgs);
+ if (ix == 0 && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra)
+ return erts_alcu_fix_alloc_shrink(
+ erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra, flgs);
+#else
+ if (ix == 1 && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra)
+ return erts_alcu_fix_alloc_shrink(
+ erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra, flgs);
+#endif
+ return 0;
}
static void
@@ -1574,14 +1639,12 @@ erts_alloc_get_verify_unused_temp_alloc(Allctr_t **allctr)
if (erts_allctrs_info[ERTS_ALC_A_TEMPORARY].alloc_util
&& erts_allctrs_info[ERTS_ALC_A_TEMPORARY].thr_spec) {
ErtsAllocatorThrSpec_t *tspec;
+ int ix = ERTS_ALC_GET_THR_IX();
tspec = &erts_allctr_thr_spec[ERTS_ALC_A_TEMPORARY];
- if (!tspec->all_thr_safe) {
- int ix = erts_alc_get_thr_ix();
- if (ix < tspec->size) {
- *allctr = tspec->allctr[ix];
- return erts_alcu_verify_unused;
- }
+ if (ix < tspec->size) {
+ *allctr = tspec->allctr[ix];
+ return erts_alcu_verify_unused;
}
}
@@ -1680,7 +1743,7 @@ erts_realloc_n_enomem(ErtsAlcType_t n, void *ptr, Uint size)
}
static ERTS_INLINE UWord
-alcu_size(ErtsAlcType_t ai)
+alcu_size(ErtsAlcType_t ai, ErtsAlcUFixInfo_t *fi, int fisz)
{
UWord res = 0;
@@ -1690,22 +1753,20 @@ alcu_size(ErtsAlcType_t ai)
if (!erts_allctrs_info[ai].thr_spec) {
Allctr_t *allctr = erts_allctrs_info[ai].extra;
AllctrSize_t asize;
- erts_alcu_current_size(allctr, &asize);
+ erts_alcu_current_size(allctr, &asize, fi, fisz);
res += asize.blocks;
}
else {
ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[ai];
int i;
- ASSERT(tspec->all_thr_safe);
-
ASSERT(tspec->enabled);
for (i = tspec->size - 1; i >= 0; i--) {
Allctr_t *allctr = tspec->allctr[i];
AllctrSize_t asize;
if (allctr) {
- erts_alcu_current_size(allctr, &asize);
+ erts_alcu_current_size(allctr, &asize, fi, fisz);
res += asize.blocks;
}
}
@@ -1733,7 +1794,6 @@ alcu_is_low(ErtsAlcType_t ai)
int found_one = 0;
# endif
- ASSERT(tspec->all_thr_safe);
ASSERT(tspec->enabled);
for (i = tspec->size - 1; i >= 0; i--) {
@@ -1757,11 +1817,24 @@ alcu_is_low(ErtsAlcType_t ai)
}
#endif /* HALFWORD */
+static ERTS_INLINE void
+add_fix_values(UWord *ap, UWord *up, ErtsAlcUFixInfo_t *fi, ErtsAlcType_t type)
+{
+ int ix = ERTS_ALC_T2N(type) - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ASSERT(0 <= ix && ix < ERTS_ALC_NO_FIXED_SIZES);
+
+ *ap += (UWord) fi[ix].allocated;
+ *up += (UWord) fi[ix].used;
+}
+
Eterm
erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
{
+/*
+ * NOTE! When updating this function, make sure to also update
+ * erlang:memory/[0,1] in $ERL_TOP/erts/preloaded/src/erlang.erl
+ */
#define ERTS_MEM_NEED_ALL_ALCU (!erts_instr_stat && want_tot_or_sys)
- ErtsFixInfo efi;
struct {
int total;
int processes;
@@ -1800,6 +1873,9 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
Eterm res = THE_NON_VALUE;
ErtsAlcType_t ai;
int only_one_value = 0;
+ ErtsAlcUFixInfo_t fi[ERTS_ALC_NO_FIXED_SIZES] = {{0,0}};
+
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
/* Figure out whats wanted... */
@@ -1969,7 +2045,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++) {
switch (ai) {
case ERTS_ALC_A_SYSTEM:
- case ERTS_ALC_A_FIXED_SIZE:
case ERTS_ALC_A_SBMBC:
#if HALFWORD_HEAP
case ERTS_ALC_A_SBMBC_LOW:
@@ -2029,11 +2104,15 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
case ERTS_ALC_A_BINARY:
save = &size.binary;
break;
+ case ERTS_ALC_A_FIXED_SIZE:
+ asz = alcu_size(ai, fi, ERTS_ALC_NO_FIXED_SIZES);
+ size.total += asz;
+ continue;
default:
save = NULL;
break;
}
- asz = alcu_size(ai);
+ asz = alcu_size(ai, NULL, 0);
if (save)
*save = asz;
size.total += asz;
@@ -2053,80 +2132,65 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
if (ERTS_MEM_NEED_ALL_ALCU)
tmp = size.processes;
- else
- tmp = alcu_size(ERTS_ALC_A_EHEAP);
- tmp += erts_max_processes*sizeof(Process*);
-#ifdef HYBRID
+ else {
+ alcu_size(ERTS_ALC_A_FIXED_SIZE,
+ fi, ERTS_ALC_NO_FIXED_SIZES);
+ tmp = alcu_size(ERTS_ALC_A_EHEAP, NULL, 0);
+ }
tmp += erts_max_processes*sizeof(Process*);
-#endif
tmp += erts_bif_timer_memory_size();
tmp += erts_tot_link_lh_size();
size.processes = size.processes_used = tmp;
-#if HALFWORD_HEAP
- /* BUG: We ignore link and monitor memory */
-#else
- erts_fix_info(ERTS_ALC_T_NLINK_SH, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_PROC);
+#if !HALFWORD_HEAP
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_MONITOR_SH);
- erts_fix_info(ERTS_ALC_T_MONITOR_SH, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_NLINK_SH);
#endif
-
- erts_fix_info(ERTS_ALC_T_PROC, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
-
- erts_fix_info(ERTS_ALC_T_REG_PROC, &efi);
- size.processes += efi.total;
- size.processes_used += efi.used;
-
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_MSG_REF);
}
if (want.atom || want.atom_used) {
Uint reserved_atom_space, atom_space;
erts_atom_get_text_space_sizes(&reserved_atom_space, &atom_space);
size.atom = size.atom_used = atom_table_sz();
- erts_fix_info(ERTS_ALC_T_ATOM, &efi);
- if (want.atom) {
+ if (want.atom)
size.atom += reserved_atom_space;
- size.atom += efi.total;
- }
- if (want.atom_used) {
+ if (want.atom_used)
size.atom_used += atom_space;
- size.atom_used += efi.used;
- }
}
if (!ERTS_MEM_NEED_ALL_ALCU && want.binary)
- size.binary = alcu_size(ERTS_ALC_A_BINARY);
+ size.binary = alcu_size(ERTS_ALC_A_BINARY, NULL, 0);
if (want.code) {
size.code = module_table_sz();
- erts_fix_info(ERTS_ALC_T_MODULE, &efi);
- size.code += efi.used;
size.code += export_table_sz();
-#if HALFWORD_HEAP
size.code += export_list_size() * sizeof(Export);
-#else
- erts_fix_info(ERTS_ALC_T_EXPORT, &efi);
- size.code += efi.used;
-#endif
size.code += erts_fun_table_sz();
- erts_fix_info(ERTS_ALC_T_FUN_ENTRY, &efi);
- size.code += efi.used;
size.code += allocated_modules*sizeof(Range);
size.code += erts_total_code_size;
}
if (want.ets) {
if (!ERTS_MEM_NEED_ALL_ALCU)
- size.ets = alcu_size(ERTS_ALC_A_ETS);
+ size.ets = alcu_size(ERTS_ALC_A_ETS, NULL, 0);
size.ets += erts_get_ets_misc_mem_size();
}
@@ -2199,13 +2263,10 @@ struct aa_values {
Eterm
erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
{
-#define MAX_AA_VALUES \
- (20 + (ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE + 1))
-
+#define MAX_AA_VALUES (23)
struct aa_values values[MAX_AA_VALUES];
Eterm res = THE_NON_VALUE;
int i, length;
- ErtsFixInfo efi;
Uint reserved_atom_space, atom_space;
if (proc) {
@@ -2270,6 +2331,11 @@ erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
i++;
values[i].arity = 2;
+ values[i].name = "export_list";
+ values[i].ui[0] = export_list_size() * sizeof(Export);
+ i++;
+
+ values[i].arity = 2;
values[i].name = "register_table";
values[i].ui[0] = process_reg_sz();
i++;
@@ -2314,22 +2380,15 @@ erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
values[i].ui[0] = erts_tot_link_lh_size();
i++;
- {
- Uint n;
-
- for (n = ERTS_ALC_N_MIN_A_FIXED_SIZE;
- n <= ERTS_ALC_N_MAX_A_FIXED_SIZE;
- n++) {
- erts_fix_info(ERTS_ALC_N2T(n), &efi);
-
- values[i].arity = 3;
- values[i].name = ERTS_ALC_N2TD(n);
- values[i].ui[0] = efi.total;
- values[i].ui[1] = efi.used;
- i++;
- }
+ values[i].arity = 2;
+ values[i].name = "process_table";
+ values[i].ui[0] = erts_max_processes*sizeof(Process*);
+ i++;
- }
+ values[i].arity = 2;
+ values[i].name = "ets_misc";
+ values[i].ui[0] = erts_get_ets_misc_mem_size();
+ i++;
length = i;
ASSERT(length <= MAX_AA_VALUES);
@@ -2423,17 +2482,16 @@ erts_alloc_util_allocators(void *proc)
Uint sz;
int i;
/*
- * Currently all allocators except sys_alloc and fix_alloc are
+ * Currently all allocators except sys_alloc are
* alloc_util allocators.
*/
- sz = ((ERTS_ALC_A_MAX + 1 - ERTS_ALC_A_MIN) - 2)*2;
+ sz = ((ERTS_ALC_A_MAX + 1 - ERTS_ALC_A_MIN) - 1)*2;
ASSERT(sz > 0);
hp = HAlloc((Process *) proc, sz);
res = NIL;
for (i = ERTS_ALC_A_MAX; i >= ERTS_ALC_A_MIN; i--) {
switch (i) {
case ERTS_ALC_A_SYSTEM:
- case ERTS_ALC_A_FIXED_SIZE:
break;
default: {
char *alc_str = (char *) ERTS_ALC_A2AD(i);
@@ -2447,267 +2505,12 @@ erts_alloc_util_allocators(void *proc)
return res;
}
-Eterm
-erts_allocator_info_term(void *proc, Eterm which_alloc, int only_sz)
-{
-#define ERTS_AIT_RET(R) \
- do { res = (R); goto done; } while (0)
-#define ERTS_AIT_HALLOC(P, S) \
- do { hp = HAlloc((P), (S)); hp_end = hp + (S); } while (0)
-
- ErtsAlcType_t i;
- Uint sz = 0;
- Uint *hp = NULL;
- Uint *hp_end = NULL;
- Eterm res = am_undefined;
-
- if (is_not_atom(which_alloc))
- goto done;
-
- for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
- if (erts_is_atom_str((char *) ERTS_ALC_A2AD(i), which_alloc)) {
- if (!erts_allctrs_info[i].enabled)
- ERTS_AIT_RET(am_false);
- else {
- if (erts_allctrs_info[i].alloc_util) {
- Eterm ires, tmp;
- Eterm **hpp;
- Uint *szp;
- Eterm (*info_func)(Allctr_t *,
- int,
- int *,
- void *,
- Uint **,
- Uint *);
-
- info_func = (only_sz
- ? erts_alcu_sz_info
- : erts_alcu_info);
-
- if (erts_allctrs_info[i].thr_spec) {
- ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[i];
- int j;
- int block_system = !tspec->all_thr_safe;
-
- if (block_system) {
- erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
- }
- ASSERT(tspec->enabled);
-
- szp = &sz;
- hpp = NULL;
-
- while (1) {
- ires = NIL;
- for (j = tspec->size - 1; j >= 0; j--) {
- Allctr_t *allctr = tspec->allctr[j];
- if (allctr) {
- tmp = erts_bld_tuple(hpp,
- szp,
- 3,
- erts_bld_atom(hpp,
- szp,
- "instance"),
- make_small((Uint) j),
- (*info_func)(allctr,
- hpp != NULL,
- NULL,
- NULL,
- hpp,
- szp));
- ires = erts_bld_cons(hpp, szp, tmp, ires);
- }
- }
- if (hpp)
- break;
- ERTS_AIT_HALLOC((Process *) proc, sz);
- hpp = &hp;
- szp = NULL;
- }
-
- if (block_system) {
- erts_smp_release_system();
- erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
- }
- }
- else {
- Allctr_t *allctr = erts_allctrs_info[i].extra;
- szp = &sz;
- hpp = NULL;
- while (1) {
- ires = NIL;
- tmp = erts_bld_tuple(hpp,
- szp,
- 3,
- erts_bld_atom(hpp,
- szp,
- "instance"),
- make_small((Uint) 0),
- (*info_func)(allctr,
- hpp != NULL,
- NULL,
- NULL,
- hpp,
- szp));
- ires = erts_bld_cons(hpp, szp, tmp, ires);
- if (hpp)
- break;
- ERTS_AIT_HALLOC((Process *) proc, sz);
- hpp = &hp;
- szp = NULL;
- }
- }
- ERTS_AIT_RET(ires);
- }
- else {
- Eterm *szp, **hpp;
-
- switch (i) {
- case ERTS_ALC_A_SYSTEM: {
- SysAllocStat sas;
- Eterm opts_am;
- Eterm opts;
- Eterm as[4]; /* Ok even if !HEAP_ON_C_STACK, not really heap data on stack */
- Eterm ts[4]; /* Ok even if !HEAP_ON_C_STACK, not really heap data on stack */
- int l;
-
- if (only_sz)
- ERTS_AIT_RET(NIL);
-
- sys_alloc_stat(&sas);
- opts_am = am_atom_put("options", 7);
-
- szp = &sz;
- hpp = NULL;
-
- restart_sys_alloc:
- l = 0;
- as[l] = am_atom_put("e", 1);
- ts[l++] = am_true;
- as[l] = am_atom_put("m", 1);
- ts[l++] = am_atom_put("libc", 4);
- if(sas.trim_threshold >= 0) {
- as[l] = am_atom_put("tt", 2);
- ts[l++] = erts_bld_uint(hpp, szp,
- (Uint) sas.trim_threshold);
- }
- if(sas.top_pad >= 0) {
- as[l] = am_atom_put("tp", 2);
- ts[l++] = erts_bld_uint(hpp, szp, (Uint) sas.top_pad);
- }
-
- opts = erts_bld_2tup_list(hpp, szp, l, as, ts);
- res = erts_bld_2tup_list(hpp, szp, 1, &opts_am, &opts);
-
- if (szp) {
- ERTS_AIT_HALLOC((Process *) proc, sz);
- szp = NULL;
- hpp = &hp;
- goto restart_sys_alloc;
- }
- ERTS_AIT_RET(res);
- }
- case ERTS_ALC_A_FIXED_SIZE: {
- ErtsAlcType_t n;
- Eterm as[2], vs[2];
-
- if (only_sz)
- ERTS_AIT_RET(NIL);
-
- as[0] = am_atom_put("options", 7);
- as[1] = am_atom_put("pools", 5);
-
- szp = &sz;
- hpp = NULL;
-
- restart_fix_alloc:
-
- vs[0] = erts_bld_cons(hpp, szp,
- erts_bld_tuple(hpp, szp, 2,
- am_atom_put("e",
- 1),
- am_true),
- NIL);
-
- vs[1] = NIL;
- for (n = ERTS_ALC_N_MIN_A_FIXED_SIZE;
- n <= ERTS_ALC_N_MAX_A_FIXED_SIZE;
- n++) {
- ErtsFixInfo efi;
- erts_fix_info(ERTS_ALC_N2T(n), &efi);
-
- vs[1] = erts_bld_cons(
- hpp, szp,
- erts_bld_tuple(
- hpp, szp, 3,
- am_atom_put((char *) ERTS_ALC_N2TD(n),
- strlen(ERTS_ALC_N2TD(n))),
- erts_bld_uint(hpp, szp, efi.total),
- erts_bld_uint(hpp, szp, efi.used)),
- vs[1]);
-
- }
-
- res = erts_bld_2tup_list(hpp, szp, 2, as, vs);
- if (szp) {
- ERTS_AIT_HALLOC((Process *) proc, sz);
- szp = NULL;
- hpp = &hp;
- goto restart_fix_alloc;
- }
- ERTS_AIT_RET(res);
- }
- default:
- ASSERT(0);
- goto done;
- }
- }
- }
- }
- }
-
- if (ERTS_IS_ATOM_STR("mseg_alloc", which_alloc)) {
-#if HAVE_ERTS_MSEG
- if (only_sz)
- ERTS_AIT_RET(NIL);
- erts_mseg_info(NULL, NULL, 0, NULL, &sz);
- if (sz)
- ERTS_AIT_HALLOC((Process *) proc, sz);
- ERTS_AIT_RET(erts_mseg_info(NULL, NULL, 1, &hp, NULL));
-#else
- ERTS_AIT_RET(am_false);
-#endif
-
- }
- else if (ERTS_IS_ATOM_STR("alloc_util", which_alloc)) {
- if (only_sz)
- ERTS_AIT_RET(NIL);
- erts_alcu_au_info_options(NULL, NULL, NULL, &sz);
- if (sz)
- ERTS_AIT_HALLOC((Process *) proc, sz);
- ERTS_AIT_RET(erts_alcu_au_info_options(NULL, NULL, &hp, NULL));
- }
-
- done:
- if (hp) {
- ASSERT(hp_end >= hp);
- HRelease((Process *) proc, hp_end, hp);
- }
- return res;
-
-#undef ERTS_AIT_RET
-#undef ERTS_AIT_HALLOC
-}
-
void
erts_allocator_info(int to, void *arg)
{
ErtsAlcType_t a;
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_smp_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
for (a = ERTS_ALC_A_MIN; a <= ERTS_ALC_A_MAX; a++) {
int ai;
@@ -2748,22 +2551,6 @@ erts_allocator_info(int to, void *arg)
erts_print(to, arg, "option tp: %d\n", sas.top_pad);
break;
}
- case ERTS_ALC_A_FIXED_SIZE: {
- ErtsAlcType_t n;
- erts_print(to, arg, "option e: true\n");
-
- for (n = ERTS_ALC_N_MIN_A_FIXED_SIZE;
- n <= ERTS_ALC_N_MAX_A_FIXED_SIZE;
- n++) {
- ErtsFixInfo efi;
- erts_fix_info(ERTS_ALC_N2T(n), &efi);
- erts_print(to, arg, "%s: %lu %lu\n",
- ERTS_ALC_N2TD(n),
- efi.total,
- efi.used);
- }
- break;
- }
default:
ASSERT(0);
break;
@@ -2774,8 +2561,18 @@ erts_allocator_info(int to, void *arg)
}
#if HAVE_ERTS_MSEG
- erts_print(to, arg, "=allocator:mseg_alloc\n");
- erts_mseg_info(&to, arg, 0, NULL, NULL);
+ {
+#ifdef ERTS_SMP
+ int max = (int) erts_no_schedulers;
+#else
+ int max = 0;
+#endif
+ int i;
+ for (i = 0; i <= max; i++) {
+ erts_print(to, arg, "=allocator:mseg_alloc[%d]\n", i);
+ erts_mseg_info(i, &to, arg, 0, NULL, NULL);
+ }
+ }
#endif
erts_print(to, arg, "=allocator:alloc_util\n");
@@ -2829,7 +2626,7 @@ erts_allocator_options(void *proc)
use_mseg++;
#endif
if (erts_allctr_thr_spec[a].enabled)
- allctr = erts_allctr_thr_spec[a].allctr[1];
+ allctr = erts_allctr_thr_spec[a].allctr[0];
else
allctr = erts_allctrs_info[a].extra;
tmp = erts_alcu_info_options(allctr, NULL, NULL, hpp, szp);
@@ -2878,7 +2675,7 @@ erts_allocator_options(void *proc)
#if HAVE_ERTS_MSEG
if (use_mseg) {
atoms[length] = am_atom_put("mseg_alloc", 10);
- terms[length++] = erts_mseg_info_options(NULL, NULL, hpp, szp);
+ terms[length++] = erts_mseg_info_options(0, NULL, NULL, hpp, szp);
}
#endif
@@ -2962,16 +2759,18 @@ erts_allocator_options(void *proc)
void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size)
{
- UWord v = (UWord) erts_alloc(type, size + (ERTS_CACHE_LINE_SIZE-1));
+ UWord v = (UWord) erts_alloc(type, size + (ERTS_CACHE_LINE_SIZE-1)
+#ifdef VALGRIND
+ + sizeof(UWord)
+#endif
+ );
#ifdef VALGRIND
- { /* Avoid Leak_PossiblyLost */
- static UWord vg_root_set[10];
- static unsigned ix = 0;
- if (ix >= sizeof(vg_root_set) / sizeof(*vg_root_set)) {
- erl_exit(ERTS_ABORT_EXIT, "Too many erts_alloc_permanent_cache_aligned's\n");
- }
- vg_root_set[ix++] = v; /* not thread safe */
+ { /* Link them to avoid Leak_PossiblyLost */
+ static UWord* first_in_list = NULL;
+ *(UWord**)v = first_in_list;
+ first_in_list = (UWord*) v;
+ v += sizeof(UWord);
}
#endif
@@ -2982,6 +2781,318 @@ void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size)
return (void*)v;
}
+static void
+reply_alloc_info(void *vair)
+{
+ ErtsAllocInfoReq *air = (ErtsAllocInfoReq *) vair;
+ Uint sched_id = erts_get_scheduler_id();
+ int global_instances = air->req_sched == sched_id;
+ ErtsProcLocks rp_locks;
+ Process *rp = air->proc;
+ Eterm ref_copy = NIL, ai_list, msg;
+ Eterm *hp = NULL, *hp_end = NULL, *hp_start = NULL;
+ Eterm **hpp;
+ Uint sz, *szp;
+ ErlOffHeap *ohp = NULL;
+ ErlHeapFragment *bp = NULL;
+ int i;
+ Eterm (*info_func)(Allctr_t *,
+ int,
+ int *,
+ void *,
+ Uint **,
+ Uint *) = (air->only_sz
+ ? erts_alcu_sz_info
+ : erts_alcu_info);
+
+ rp_locks = air->req_sched == sched_id ? ERTS_PROC_LOCK_MAIN : 0;
+
+ sz = 0;
+ hpp = NULL;
+ szp = &sz;
+
+ while (1) {
+
+ if (hpp)
+ ref_copy = STORE_NC(hpp, ohp, air->ref);
+ else
+ *szp += REF_THING_SIZE;
+
+ ai_list = NIL;
+ for (i = 0; air->allocs[i] != ERTS_ALC_A_INVALID; i++);
+ for (i--; i >= 0; i--) {
+ int ai = air->allocs[i];
+ Allctr_t *allctr;
+ Eterm ainfo;
+ Eterm alloc_atom;
+ if (global_instances) {
+ switch (ai) {
+ case ERTS_ALC_A_SYSTEM: {
+ alloc_atom = erts_bld_atom(hpp, szp, "sys_alloc");
+ ainfo = NIL;
+ if (!air->only_sz) {
+ SysAllocStat sas;
+ if (hpp)
+ sys_alloc_stat(&sas);
+ if (szp) {
+ /* ensure ehough heap */
+ sas.top_pad = INT_MAX;
+ sas.trim_threshold = INT_MAX;
+ }
+ if (sas.top_pad >= 0) {
+ ainfo = erts_bld_cons(
+ hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp, "tp"),
+ erts_bld_uint(
+ hpp, szp,
+ (Uint) sas.top_pad)),
+ ainfo);
+ }
+ if (sas.trim_threshold >= 0) {
+ ainfo = erts_bld_cons(
+ hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp, "tt"),
+ erts_bld_uint(
+ hpp, szp,
+ (Uint) sas.trim_threshold)),
+ ainfo);
+ }
+ ainfo = erts_bld_cons(hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp,
+ "m"),
+ erts_bld_atom(hpp, szp,
+ "libc")),
+ ainfo);
+ ainfo = erts_bld_cons(hpp, szp,
+ erts_bld_tuple(
+ hpp, szp, 2,
+ erts_bld_atom(hpp, szp,
+ "e"),
+ am_true),
+ ainfo);
+ ainfo = erts_bld_tuple(hpp, szp, 2,
+ erts_bld_atom(hpp, szp,
+ "options"),
+ ainfo);
+ ainfo = erts_bld_cons(hpp, szp,ainfo,NIL);
+ }
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+ break;
+ }
+ case ERTS_ALC_INFO_A_ALLOC_UTIL:
+ alloc_atom = erts_bld_atom(hpp, szp, "alloc_util");
+ ainfo = (air->only_sz
+ ? NIL
+ : erts_alcu_au_info_options(NULL, NULL,
+ hpp, szp));
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+ break;
+ case ERTS_ALC_INFO_A_MSEG_ALLOC:
+ alloc_atom = erts_bld_atom(hpp, szp, "mseg_alloc");
+#if HAVE_ERTS_MSEG
+ ainfo = (air->only_sz
+ ? NIL
+ : erts_mseg_info(0, NULL, NULL, hpp != NULL,
+ hpp, szp));
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(0),
+ ainfo);
+#else
+ ainfo = erts_bld_tuple(hpp, szp, 2, alloc_atom,
+ am_false);
+#endif
+ break;
+ default:
+ alloc_atom = erts_bld_atom(hpp, szp,
+ (char *) ERTS_ALC_A2AD(ai));
+ if (!erts_allctrs_info[ai].enabled)
+ ainfo = erts_bld_tuple(hpp, szp, 2, alloc_atom,
+ am_false);
+ else if (erts_allctrs_info[ai].alloc_util) {
+ if (erts_allctrs_info[ai].thr_spec)
+ allctr = erts_allctr_thr_spec[ai].allctr[0];
+ else
+ allctr = erts_allctrs_info[ai].extra;
+ ainfo = info_func(allctr, hpp != NULL, NULL,
+ NULL, hpp, szp);
+ ainfo = erts_bld_tuple(hpp, szp, 3, alloc_atom,
+ make_small(0), ainfo);
+ }
+ else {
+ erl_exit(ERTS_ABORT_EXIT, "%s:%d: internal error\n",
+ __FILE__, __LINE__);
+ }
+ }
+ ai_list = erts_bld_cons(hpp, szp,
+ ainfo, ai_list);
+ }
+ switch (ai) {
+ case ERTS_ALC_A_SYSTEM:
+ case ERTS_ALC_INFO_A_ALLOC_UTIL:
+ break;
+ case ERTS_ALC_INFO_A_MSEG_ALLOC:
+#if HAVE_ERTS_MSEG && defined(ERTS_SMP)
+ alloc_atom = erts_bld_atom(hpp, szp, "mseg_alloc");
+ ainfo = (air->only_sz
+ ? NIL
+ : erts_mseg_info(sched_id, NULL, NULL,
+ hpp != NULL, hpp, szp));
+ ainfo = erts_bld_tuple(hpp, szp, 3,
+ alloc_atom,
+ make_small(sched_id),
+ ainfo);
+ ai_list = erts_bld_cons(hpp, szp, ainfo, ai_list);
+#endif
+ break;
+ default:
+ if (erts_allctrs_info[ai].thr_spec) {
+ alloc_atom = erts_bld_atom(hpp, szp,
+ (char *) ERTS_ALC_A2AD(ai));
+ allctr = erts_allctr_thr_spec[ai].allctr[sched_id];
+ ainfo = info_func(allctr, hpp != NULL, NULL,
+ NULL, hpp, szp);
+ ai_list = erts_bld_cons(hpp, szp,
+ erts_bld_tuple(
+ hpp, szp,
+ 3,
+ alloc_atom,
+ make_small(sched_id),
+ ainfo),
+ ai_list);
+ }
+ break;
+ }
+ msg = erts_bld_tuple(hpp, szp,
+ 3,
+ ref_copy,
+ make_small(sched_id),
+ ai_list);
+
+ }
+ if (hpp)
+ break;
+
+ hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ hp_start = hp;
+ hp_end = hp + sz;
+ szp = NULL;
+ hpp = &hp;
+ }
+ if (bp)
+ bp = erts_resize_message_buffer(bp, hp - hp_start, &msg, 1);
+ else {
+ ASSERT(hp);
+ HRelease(rp, hp_end, hp);
+ }
+
+ erts_queue_message(rp, &rp_locks, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
+
+ if (air->req_sched == sched_id)
+ rp_locks &= ~ERTS_PROC_LOCK_MAIN;
+
+ erts_smp_proc_unlock(rp, rp_locks);
+ erts_smp_proc_dec_refc(rp);
+
+ if (erts_smp_atomic32_dec_read_nob(&air->refc) == 0)
+ aireq_free(air);
+}
+
+int
+erts_request_alloc_info(struct process *c_p,
+ Eterm ref,
+ Eterm allocs,
+ int only_sz)
+{
+ ErtsAllocInfoReq *air = aireq_alloc();
+ Eterm req_ai[ERTS_ALC_A_MAX+1+2] = {0};
+ Eterm alist;
+ Eterm *hp;
+ int airix = 0, ai;
+
+ air->req_sched = erts_get_scheduler_id();
+
+ air->only_sz = only_sz;
+
+ air->proc = c_p;
+
+ if (is_not_internal_ref(ref))
+ return 0;
+
+ hp = &air->ref_heap[0];
+ air->ref = STORE_NC(&hp, NULL, ref);
+
+ if (is_not_list(allocs))
+ return 0;
+
+ alist = allocs;
+
+ while (is_list(alist)) {
+ int saved = 0;
+ Eterm* consp = list_val(alist);
+ Eterm alloc = CAR(consp);
+
+ for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++)
+ if (erts_is_atom_str((char *) erts_alc_a2ad[ai], alloc))
+ goto save_alloc;
+ if (erts_is_atom_str("mseg_alloc", alloc)) {
+ ai = ERTS_ALC_INFO_A_MSEG_ALLOC;
+ goto save_alloc;
+ }
+ if (erts_is_atom_str("alloc_util", alloc)) {
+ ai = ERTS_ALC_INFO_A_ALLOC_UTIL;
+ save_alloc:
+ if (req_ai[ai])
+ return 0;
+ air->allocs[airix++] = ai;
+ req_ai[ai] = 1;
+ saved = 1;
+ }
+
+ if (!saved)
+ return 0;
+
+ alist = CDR(consp);
+ }
+
+ if (is_not_nil(alist))
+ return 0;
+
+ air->allocs[airix] = ERTS_ALC_A_INVALID;
+
+ erts_smp_atomic32_init_nob(&air->refc,
+ (erts_aint32_t) erts_no_schedulers);
+
+ erts_smp_proc_add_refc(c_p, (Sint32) erts_no_schedulers);
+
+#ifdef ERTS_SMP
+ if (erts_no_schedulers > 1)
+ erts_schedule_multi_misc_aux_work(1,
+ erts_no_schedulers,
+ reply_alloc_info,
+ (void *) air);
+#endif
+
+ reply_alloc_info((void *) air);
+
+ return 1;
+}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Deprecated functions *
@@ -3012,10 +3123,10 @@ void *safe_realloc(void *ptr, Uint sz)
\* */
#define ERTS_ALC_TEST_ABORT erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n")
-unsigned long erts_alc_test(unsigned long op,
- unsigned long a1,
- unsigned long a2,
- unsigned long a3)
+UWord erts_alc_test(UWord op,
+ UWord a1,
+ UWord a2,
+ UWord a3)
{
switch (op >> 8) {
case 0x0: return erts_alcu_test(op, a1, a2);
@@ -3029,24 +3140,24 @@ unsigned long erts_alc_test(unsigned long op,
case 0xf00:
#ifdef USE_THREADS
if (((Allctr_t *) a1)->thread_safe)
- return (unsigned long) erts_alcu_alloc_ts(ERTS_ALC_T_UNDEF,
+ return (UWord) erts_alcu_alloc_ts(ERTS_ALC_T_UNDEF,
(void *) a1,
(Uint) a2);
else
#endif
- return (unsigned long) erts_alcu_alloc(ERTS_ALC_T_UNDEF,
+ return (UWord) erts_alcu_alloc(ERTS_ALC_T_UNDEF,
(void *) a1,
(Uint) a2);
case 0xf01:
#ifdef USE_THREADS
if (((Allctr_t *) a1)->thread_safe)
- return (unsigned long) erts_alcu_realloc_ts(ERTS_ALC_T_UNDEF,
+ return (UWord) erts_alcu_realloc_ts(ERTS_ALC_T_UNDEF,
(void *) a1,
(void *) a2,
(Uint) a3);
else
#endif
- return (unsigned long) erts_alcu_realloc(ERTS_ALC_T_UNDEF,
+ return (UWord) erts_alcu_realloc(ERTS_ALC_T_UNDEF,
(void *) a1,
(void *) a2,
(Uint) a3);
@@ -3076,7 +3187,7 @@ unsigned long erts_alc_test(unsigned long op,
if (argv[i][0] == '-' && argv[i][1] == 't')
handle_au_arg(&init, &argv[i][2], argv, &i);
else
- return (unsigned long) NULL;
+ return (UWord) NULL;
i++;
}
}
@@ -3117,25 +3228,25 @@ unsigned long erts_alc_test(unsigned long op,
break;
}
- return (unsigned long) allctr;
+ return (UWord) allctr;
}
case 0xf04:
erts_alcu_stop((Allctr_t *) a1);
erts_free(ERTS_ALC_T_UNDEF, (void *) a1);
break;
#ifdef USE_THREADS
- case 0xf05: return (unsigned long) 1;
- case 0xf06: return (unsigned long) ((Allctr_t *) a1)->thread_safe;
+ case 0xf05: return (UWord) 1;
+ case 0xf06: return (UWord) ((Allctr_t *) a1)->thread_safe;
#ifdef ETHR_NO_FORKSAFETY
- case 0xf07: return (unsigned long) 0;
+ case 0xf07: return (UWord) 0;
#else
- case 0xf07: return (unsigned long) ((Allctr_t *) a1)->thread_safe;
+ case 0xf07: return (UWord) ((Allctr_t *) a1)->thread_safe;
#endif
case 0xf08: {
ethr_mutex *mtx = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_mutex));
if (ethr_mutex_init(mtx) != 0)
ERTS_ALC_TEST_ABORT;
- return (unsigned long) mtx;
+ return (UWord) mtx;
}
case 0xf09: {
ethr_mutex *mtx = (ethr_mutex *) a1;
@@ -3154,7 +3265,7 @@ unsigned long erts_alc_test(unsigned long op,
ethr_cond *cnd = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(ethr_cond));
if (ethr_cond_init(cnd) != 0)
ERTS_ALC_TEST_ABORT;
- return (unsigned long) cnd;
+ return (UWord) cnd;
}
case 0xf0d: {
ethr_cond *cnd = (ethr_cond *) a1;
@@ -3180,7 +3291,7 @@ unsigned long erts_alc_test(unsigned long op,
(void *) a2,
NULL) != 0)
ERTS_ALC_TEST_ABORT;
- return (unsigned long) tid;
+ return (UWord) tid;
}
case 0xf11: {
ethr_tid *tid = (ethr_tid *) a1;
@@ -3197,13 +3308,13 @@ unsigned long erts_alc_test(unsigned long op,
default:
break;
}
- return (unsigned long) 0;
+ return (UWord) 0;
default:
break;
}
ASSERT(0);
- return ~((unsigned long) 0);
+ return ~((UWord) 0);
}
#ifdef DEBUG
@@ -3439,7 +3550,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func)
erl_exit(ERTS_ABORT_EXIT,
"ERROR: Fence at beginning of memory block (p=0x%u) "
"clobbered.\n",
- (unsigned long) ptr);
+ (UWord) ptr);
}
memcpy((void *) &post_pattern, (void *) (((char *)ptr)+sz), sizeof(UWord));
@@ -3456,12 +3567,12 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func)
erl_exit(ERTS_ABORT_EXIT,
"ERROR: Fence at end of memory block (p=0x%u, sz=%u) "
"clobbered.\n",
- (unsigned long) ptr, (unsigned long) sz);
+ (UWord) ptr, (UWord) sz);
if (found_type != GET_TYPE_OF_PATTERN(post_pattern))
erl_exit(ERTS_ABORT_EXIT,
"ERROR: Fence around memory block (p=0x%u, sz=%u) "
"clobbered.\n",
- (unsigned long) ptr, (unsigned long) sz);
+ (UWord) ptr, (UWord) sz);
ftype = type_no_str(found_type);
if (!ftype) {
@@ -3484,7 +3595,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func)
erl_exit(ERTS_ABORT_EXIT,
"ERROR: Memory block (p=0x%u, sz=%u) allocated as type \"%s\","
" but %s as type \"%s\".\n",
- (unsigned long) ptr, (unsigned long) sz, ftype, op_str, otype);
+ (UWord) ptr, (UWord) sz, ftype, op_str, otype);
}
#ifdef HARD_DEBUG
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index 80cb82c393..e475f9d8a2 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,10 @@
#define ERL_ALLOC_H__
#include "erl_alloc_types.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#define ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#include "erl_thr_progress.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
#include "erl_alloc_util.h"
#ifdef USE_THREADS
#include "erl_threads.h"
@@ -43,50 +47,47 @@
# define ERTS_ALC_INLINE
#endif
-#define ERTS_FIX_CORE_ALLOCATOR ERTS_ALC_A_LONG_LIVED
-extern ErtsAlcType_t erts_fix_core_allocator_ix;
-
-typedef struct {
- Uint total;
- Uint used;
-} ErtsFixInfo;
+#define ERTS_ALC_NO_FIXED_SIZES \
+ (ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE + 1)
void erts_sys_alloc_init(void);
void *erts_sys_alloc(ErtsAlcType_t, void *, Uint);
void *erts_sys_realloc(ErtsAlcType_t, void *, void *, Uint);
void erts_sys_free(ErtsAlcType_t, void *, void *);
-
-void erts_init_fix_alloc(Uint, void *(*)(Uint));
-Uint erts_get_fix_size(ErtsAlcType_t);
-void erts_set_fix_size(ErtsAlcType_t, Uint);
-void erts_fix_info(ErtsAlcType_t, ErtsFixInfo *);
-void *erts_fix_alloc(ErtsAlcType_t, void *, Uint);
-void *erts_fix_realloc(ErtsAlcType_t, void *, void*, Uint);
-void erts_fix_free(ErtsAlcType_t, void *, void*);
-
-
Eterm erts_memory(int *, void *, void *, Eterm);
Eterm erts_allocated_areas(int *, void *, void *);
Eterm erts_alloc_util_allocators(void *proc);
void erts_allocator_info(int, void *);
-Eterm erts_allocator_info_term(void *proc, Eterm which_alloc, int only_sz);
Eterm erts_allocator_options(void *proc);
+struct process;
+
+int erts_request_alloc_info(struct process *c_p, Eterm ref, Eterm allocs,
+ int only_sz);
+
#define ERTS_ALLOC_INIT_DEF_OPTS_INITER {0}
typedef struct {
- int dummy;
+ int ncpu;
} ErtsAllocInitOpts;
+typedef struct {
+ Allctr_t *deallctr[ERTS_ALC_A_MAX+1];
+ int pref_ix[ERTS_ALC_A_MAX+1];
+ int flist_ix[ERTS_ALC_A_MAX+1];
+ int pre_alc_ix;
+} ErtsSchedAllocData;
+
void erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop);
+void erts_alloc_late_init(void);
#if defined(GET_ERTS_ALC_TEST) || defined(ERTS_ALC_INTERNAL__)
/* Only for testing */
-unsigned long erts_alc_test(unsigned long,
- unsigned long,
- unsigned long,
- unsigned long);
+UWord erts_alc_test(UWord,
+ UWord,
+ UWord,
+ UWord);
#endif
#define ERTS_ALC_O_ALLOC 0
@@ -126,15 +127,22 @@ extern ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
typedef struct {
int enabled;
- int all_thr_safe;
+ int dd;
+ int aix;
int size;
Allctr_t **allctr;
} ErtsAllocatorThrSpec_t;
extern ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
-int erts_alc_get_thr_ix(void);
-void erts_alloc_reg_scheduler_id(Uint id);
+void erts_alloc_register_scheduler(void *vesdp);
+#ifdef ERTS_SMP
+void erts_alloc_scheduler_handle_delayed_dealloc(void *vesdp,
+ int *need_thr_progress,
+ ErtsThrPrgrVal *thr_prgr_p,
+ int *more_work);
+#endif
+erts_aint32_t erts_alloc_fix_alloc_shrink(int ix, erts_aint32_t flgs);
__decl_noreturn void erts_alloc_enomem(ErtsAlcType_t,Uint)
__noreturn;
@@ -252,6 +260,8 @@ void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size)
#endif /* #if ERTS_ALC_DO_INLINE || defined(ERTS_ALC_INTERNAL__) */
+#define ERTS_ALC_GET_THR_IX() ((int) erts_get_scheduler_id())
+
typedef void (*erts_alloc_verify_func_t)(Allctr_t *);
erts_alloc_verify_func_t
@@ -436,136 +446,41 @@ NAME##_free(TYPE *p) \
} \
}
-typedef struct {
- void *start;
- void *end;
- int chunks_mem_size;
-} erts_sched_pref_quick_alloc_data_t;
-
-#ifdef DEBUG
-#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P) \
-do { \
- ASSERT((void *) (C) < (void *) (P)); \
- ASSERT((void *) (P) \
- < (void *) (((char *) (C)) + (A)->chunks_mem_size)); \
-} while (0)
-#else
-#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P)
-#endif
+#include "erl_sched_spec_pre_alloc.h"
#define ERTS_SCHED_PREF_PRE_ALLOC_IMPL(NAME, TYPE, PASZ) \
-union erts_qa_##NAME##__ { \
+union erts_sspa_##NAME##__ { \
+ erts_sspa_blk_t next; \
TYPE type; \
- union erts_qa_##NAME##__ *next; \
}; \
-typedef struct { \
- erts_smp_spinlock_t lock; \
- union erts_qa_##NAME##__ *freelist; \
- union erts_qa_##NAME##__ pre_alloced[1]; \
-} erts_qa_##NAME##_chunk__; \
-static erts_sched_pref_quick_alloc_data_t *qa_data_##NAME##__; \
-static ERTS_INLINE erts_qa_##NAME##_chunk__ * \
-get_##NAME##_chunk_ix(int cix) \
-{ \
- char *ptr = (char *) qa_data_##NAME##__->start; \
- ptr += cix*qa_data_##NAME##__->chunks_mem_size; \
- return (erts_qa_##NAME##_chunk__ *) ptr; \
-} \
-static ERTS_INLINE erts_qa_##NAME##_chunk__ * \
-get_##NAME##_chunk_ptr(void *ptr) \
-{ \
- int cix; \
- size_t diff; \
- if (ptr < qa_data_##NAME##__->start || qa_data_##NAME##__->end <= ptr)\
- return NULL; \
- diff = ((char *) ptr) - ((char *) qa_data_##NAME##__->start); \
- cix = diff / qa_data_##NAME##__->chunks_mem_size; \
- return get_##NAME##_chunk_ix(cix); \
-} \
+ \
+static erts_sspa_data_t *sspa_data_##NAME##__; \
+ \
static void \
init_##NAME##_alloc(void) \
{ \
- size_t tot_size; \
- size_t chunk_mem_size; \
- char *chunk_start; \
- int cix; \
- int no_blocks = ERTS_PRE_ALLOC_SIZE((PASZ)); \
- int no_blocks_per_chunk = 2*((no_blocks-1)/erts_no_schedulers + 1); \
- no_blocks = no_blocks_per_chunk * erts_no_schedulers; \
- chunk_mem_size = sizeof(erts_qa_##NAME##_chunk__); \
- chunk_mem_size += (sizeof(union erts_qa_##NAME##__) \
- * (no_blocks_per_chunk - 1)); \
- chunk_mem_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(chunk_mem_size); \
- tot_size = sizeof(erts_sched_pref_quick_alloc_data_t); \
- tot_size += ERTS_CACHE_LINE_SIZE - 1; \
- tot_size += chunk_mem_size*erts_no_schedulers; \
- qa_data_##NAME##__ = erts_alloc(ERTS_ALC_T_PRE_ALLOC_DATA,tot_size);\
- chunk_start = (((char *) qa_data_##NAME##__) \
- + sizeof(erts_sched_pref_quick_alloc_data_t)); \
- if ((((UWord) chunk_start) & ERTS_CACHE_LINE_MASK) != ((UWord) 0)) \
- chunk_start = ((char *) \
- ((((UWord) chunk_start) & ~ERTS_CACHE_LINE_MASK) \
- + ERTS_CACHE_LINE_SIZE)); \
- qa_data_##NAME##__->chunks_mem_size = chunk_mem_size; \
- qa_data_##NAME##__->start = (void *) chunk_start; \
- qa_data_##NAME##__->end = (chunk_start \
- + chunk_mem_size*erts_no_schedulers); \
- for (cix = 0; cix < erts_no_schedulers; cix++) { \
- int i; \
- erts_qa_##NAME##_chunk__ *chunk = get_##NAME##_chunk_ix(cix); \
- erts_smp_spinlock_init(&chunk->lock, #NAME "_alloc_lock"); \
- chunk->freelist = &chunk->pre_alloced[0]; \
- for (i = 1; i < no_blocks_per_chunk; i++) { \
- ERTS_PRE_ALLOC_CLOBBER(&chunk->pre_alloced[i-1], \
- union erts_qa_##NAME##__); \
- chunk->pre_alloced[i-1].next = &chunk->pre_alloced[i]; \
- } \
- ERTS_PRE_ALLOC_CLOBBER(&chunk->pre_alloced[no_blocks_per_chunk-1],\
- union erts_qa_##NAME##__); \
- chunk->pre_alloced[no_blocks_per_chunk-1].next = NULL; \
- } \
+ sspa_data_##NAME##__ = \
+ erts_sspa_create(sizeof(union erts_sspa_##NAME##__), \
+ ERTS_PRE_ALLOC_SIZE((PASZ))); \
} \
-static ERTS_INLINE TYPE * \
+ \
+static TYPE * \
NAME##_alloc(void) \
{ \
- int cix = ((int) erts_get_scheduler_id()) - 1; \
- TYPE *res; \
- if (cix < 0) \
- res = NULL; \
- else { \
- erts_qa_##NAME##_chunk__ *chunk = get_##NAME##_chunk_ix(cix); \
- erts_smp_spin_lock(&chunk->lock); \
- if (!chunk->freelist) \
- res = NULL; \
- else { \
- res = &chunk->freelist->type; \
- chunk->freelist = chunk->freelist->next; \
- ERTS_SPPA_DBG_CHK_IN_CHNK(qa_data_##NAME##__, chunk, res); \
- } \
- erts_smp_spin_unlock(&chunk->lock); \
- } \
- return res; \
+ ErtsSchedulerData *esdp = erts_get_scheduler_data(); \
+ if (!esdp) \
+ return NULL; \
+ return (TYPE *) erts_sspa_alloc(sspa_data_##NAME##__, \
+ (int) esdp->no - 1); \
} \
-static ERTS_INLINE int \
+ \
+static int \
NAME##_free(TYPE *p) \
{ \
- erts_qa_##NAME##_chunk__ *chunk; \
- chunk = get_##NAME##_chunk_ptr((void *) p); \
- if (!chunk) \
- return 0; \
- else { \
- union erts_qa_##NAME##__ *up; \
- ERTS_SPPA_DBG_CHK_IN_CHNK(qa_data_##NAME##__, chunk, p); \
- up = ((union erts_qa_##NAME##__ *) \
- (((char *) p) \
- - ((char *) &((union erts_qa_##NAME##__ *) 0)->type))); \
- erts_smp_spin_lock(&chunk->lock); \
- ERTS_PRE_ALLOC_CLOBBER(up, union erts_qa_##NAME##__); \
- up->next = chunk->freelist; \
- chunk->freelist = up; \
- erts_smp_spin_unlock(&chunk->lock); \
- return 1; \
- } \
+ ErtsSchedulerData *esdp = erts_get_scheduler_data(); \
+ return erts_sspa_free(sspa_data_##NAME##__, \
+ esdp ? (int) esdp->no - 1 : -1, \
+ (char *) p); \
}
#ifdef DEBUG
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index eda0831441..4aa8fa82fb 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2011. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The 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,6 +50,15 @@
# command line argument to make_alloc_types. The variable X is false
# after a "+disable X" statement or if it has never been mentioned.
++if smp
++disable threads_no_smp
++else
++if threads
++enable threads_no_smp
++else
++disable threads_no_smp
++endif
++endif
# --- Allocator declarations -------------------------------------------------
#
@@ -133,29 +142,25 @@ class SYSTEM system_data
# should be deallocated before the emulator starts executing Erlang
# code again.
#
-# NOTE: When adding or removing a type which uses the FIXED_SIZE allocator,
-# also add or remove initialization of the type in erts_alloc_init()
-# (erl_alloc.c).
-#
# <TYPE> <ALLOCATOR> <CLASS> <DESCRIPTION>
type SBMBC SBMBC SYSTEM small_block_mbc
type PROC FIXED_SIZE PROCESSES proc
-type ATOM FIXED_SIZE ATOM atom_entry
-type MODULE FIXED_SIZE CODE module_entry
-type REG_PROC FIXED_SIZE PROCESSES reg_proc
+type ATOM LONG_LIVED ATOM atom_entry
+type MODULE LONG_LIVED CODE module_entry
+type REG_PROC STANDARD PROCESSES reg_proc
type LINK_LH STANDARD PROCESSES link_lh
type SUSPEND_MON STANDARD PROCESSES suspend_monitor
type PEND_SUSPEND SHORT_LIVED PROCESSES pending_suspend
type PROC_LIST SHORT_LIVED PROCESSES proc_list
-type FUN_ENTRY FIXED_SIZE CODE fun_entry
+type FUN_ENTRY LONG_LIVED CODE fun_entry
type ATOM_TXT LONG_LIVED ATOM atom_text
type BEAM_REGISTER EHEAP PROCESSES beam_register
type HEAP EHEAP PROCESSES heap
type OLD_HEAP EHEAP PROCESSES old_heap
type HEAP_FRAG EHEAP PROCESSES heap_frag
type TMP_HEAP TEMPORARY PROCESSES tmp_heap
-type MSG_REF SHORT_LIVED PROCESSES msg_ref
+type MSG_REF FIXED_SIZE PROCESSES msg_ref
type MSG_ROOTS TEMPORARY PROCESSES msg_roots
type ROOTSET TEMPORARY PROCESSES root_set
type LOADER_TMP TEMPORARY CODE loader_tmp
@@ -196,10 +201,10 @@ type LINEBUF STANDARD SYSTEM line_buf
type IOQ STANDARD SYSTEM io_queue
type BITS_BUF STANDARD SYSTEM bits_buf
type TMP_DIST_BUF TEMPORARY SYSTEM tmp_dist_buf
-type ASYNC_Q LONG_LIVED SYSTEM async_queue
+type ASYNC_DATA LONG_LIVED SYSTEM internal_async_data
type ESTACK TEMPORARY SYSTEM estack
type PORT_CALL_BUF TEMPORARY SYSTEM port_call_buf
-type DB_TABLE FIXED_SIZE ETS db_tab
+type DB_TABLE ETS ETS db_tab
type DB_FIXATION SHORT_LIVED ETS db_fixation
type DB_FIX_DEL SHORT_LIVED ETS fixed_del
type DB_TABLES LONG_LIVED ETS db_tabs
@@ -256,6 +261,23 @@ type TMP_CPU_IDS SHORT_LIVED SYSTEM tmp_cpu_ids
type EXT_TERM_DATA SHORT_LIVED PROCESSES external_term_data
type ZLIB STANDARD SYSTEM zlib
type CPU_GRPS_MAP LONG_LIVED SYSTEM cpu_groups_map
+type AUX_WORK_TMO LONG_LIVED SYSTEM aux_work_timeouts
+type MISC_AUX_WORK_Q LONG_LIVED SYSTEM misc_aux_work_q
+
++if threads_no_smp
+# Need thread safe allocs, but std_alloc and fix_alloc are not;
+# use driver_alloc which is...
+type THR_Q_EL DRIVER SYSTEM thr_q_element
+type THR_Q_EL_SL DRIVER SYSTEM sl_thr_q_element
+type MISC_AUX_WORK DRIVER SYSTEM misc_aux_work
++else
+type THR_Q_EL STANDARD SYSTEM thr_q_element
+type THR_Q_EL_SL FIXED_SIZE SYSTEM sl_thr_q_element
+type MISC_AUX_WORK SHORT_LIVED SYSTEM misc_aux_work
++endif
+type THR_Q STANDARD SYSTEM thr_queue
+type THR_Q_SL SHORT_LIVED SYSTEM short_lived_thr_queue
+type THR_Q_LL LONG_LIVED SYSTEM long_lived_thr_queue
+if smp
type ASYNC SHORT_LIVED SYSTEM async
@@ -269,10 +291,10 @@ type PORT_LOCK STANDARD SYSTEM port_lock
type DRIVER_LOCK STANDARD SYSTEM driver_lock
type XPORTS_LIST SHORT_LIVED SYSTEM extra_port_list
type PROC_LCK_WTR LONG_LIVED SYSTEM proc_lock_waiter
-type PROC_LCK_QS LONG_LIVED SYSTEM proc_lock_queues
type RUNQ_BLNS LONG_LIVED SYSTEM run_queue_balancing
-type MISC_AUX_WORK_Q LONG_LIVED SYSTEM misc_aux_work_q
-type MISC_AUX_WORK SHORT_LIVED SYSTEM misc_aux_work
+type THR_PRGR_IDATA LONG_LIVED SYSTEM thr_prgr_internal_data
+type THR_PRGR_DATA LONG_LIVED SYSTEM thr_prgr_data
+type T_THR_PRGR_DATA SHORT_LIVED SYSTEM temp_thr_prgr_data
+endif
#
@@ -285,12 +307,6 @@ type ETHR_STD STANDARD SYSTEM ethread_standard
type ETHR_SL SHORT_LIVED SYSTEM ethread_short_lived
type ETHR_LL LONG_LIVED SYSTEM ethread_long_lived
-+ifnot smp
-
-type ARCALLBACK LONG_LIVED SYSTEM async_ready_callback
-
-+endif
-
+endif
+if shared_heap
@@ -300,19 +316,6 @@ type ACTIVE_PROCS STANDARD PROCESSES active_procs
+endif
-+if hybrid
-
-type ACTIVE_PROCS STANDARD PROCESSES active_procs
-
-# Used for all memory involved in incremental gc of the message area
-# that is, young (x2) and old generation, forwarding pointers and blackmap
-type MESSAGE_AREA LONG_LIVED PROCESSES message_area
-
-# Used in MA_STACK (global.h) and INC_STORAGE (erl_nmgc.h)
-type OBJECT_STACK STANDARD PROCESSES object_stack
-
-+endif
-
+if smp
type SL_PTIMER SHORT_LIVED SYSTEM ptimer_sl
type LL_PTIMER STANDARD SYSTEM ptimer_ll
@@ -346,10 +349,11 @@ type DB_MS_PSDO_PROC LONG_LIVED_LOW ETS db_match_pseudo_proc
type SCHDLR_DATA LONG_LIVED_LOW SYSTEM scheduler_data
type LL_TEMP_TERM LONG_LIVED_LOW SYSTEM ll_temp_term
-# no FIXED_SIZE for low memory
-type EXPORT STANDARD_LOW CODE export_entry
+type EXPORT LONG_LIVED_LOW CODE export_entry
type MONITOR_SH STANDARD_LOW PROCESSES monitor_sh
type NLINK_SH STANDARD_LOW PROCESSES nlink_sh
+type AINFO_REQ STANDARD_LOW SYSTEM alloc_info_request
+type SCHED_WTIME_REQ STANDARD_LOW SYSTEM sched_wall_time_request
+else # "fullword"
@@ -362,9 +366,11 @@ type DB_MS_PSDO_PROC LONG_LIVED ETS db_match_pseudo_proc
type SCHDLR_DATA LONG_LIVED SYSTEM scheduler_data
type LL_TEMP_TERM LONG_LIVED SYSTEM ll_temp_term
-type EXPORT FIXED_SIZE CODE export_entry
+type EXPORT LONG_LIVED CODE export_entry
type MONITOR_SH FIXED_SIZE PROCESSES monitor_sh
type NLINK_SH FIXED_SIZE PROCESSES nlink_sh
+type AINFO_REQ SHORT_LIVED SYSTEM alloc_info_request
+type SCHED_WTIME_REQ SHORT_LIVED SYSTEM sched_wall_time_request
+endif
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index d51ed0c36d..97ba306a79 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -46,6 +46,7 @@
#include "erl_alloc_util.h"
#include "erl_mseg.h"
#include "erl_threads.h"
+#include "erl_thr_progress.h"
#ifdef ERTS_ENABLE_LOCK_COUNT
#include "erl_lock_count.h"
@@ -61,6 +62,13 @@
#warning "* * * * * * * * * *"
#endif
+#define ERTS_ALCU_DD_OPS_LIM_HIGH 20
+#define ERTS_ALCU_DD_OPS_LIM_LOW 2
+
+/* Fix alloc limit */
+#define ERTS_ALCU_FIX_MAX_LIST_SZ 1000
+#define ERTS_ALC_FIX_MAX_SHRINK_OPS 30
+
#define ALLOC_ZERO_EQ_NULL 0
static int atoms_initialized = 0;
@@ -269,7 +277,6 @@ static void check_blk_carrier(Allctr_t *, Block_t *);
#define HARD_CHECK_BLK_CARRIER(A, B)
#endif
-
/* Statistics updating ... */
#ifdef DEBUG
@@ -465,26 +472,34 @@ do { \
#ifdef DEBUG
#ifdef USE_THREADS
-#define ERTS_ALCU_DBG_CHK_THR_SPEC(A) \
+#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A) \
do { \
if (!(A)->thread_safe) { \
- if (!(A)->debug.saved_tid) \
+ if (!(A)->debug.saved_tid) { \
(A)->debug.tid = erts_thr_self(); \
+ (A)->debug.saved_tid = 1; \
+ } \
else { \
- ASSERT(ethr_equal_tids((A)->debug.tid, erts_thr_self())); \
+ ERTS_SMP_LC_ASSERT( \
+ ethr_equal_tids((A)->debug.tid, erts_thr_self()) \
+ || erts_thr_progress_is_blocking()); \
} \
} \
} while (0)
#else
-#define ERTS_ALCU_DBG_CHK_THR_SPEC(A)
+#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A)
#endif
#else
-#define ERTS_ALCU_DBG_CHK_THR_SPEC(A)
+#define ERTS_ALCU_DBG_CHK_THR_ACCESS(A)
#endif
static void make_name_atoms(Allctr_t *allctr);
+static Block_t *create_carrier(Allctr_t *, Uint, UWord);
+static void destroy_carrier(Allctr_t *, Block_t *);
+static void mbc_free(Allctr_t *allctr, void *p);
+
/* mseg ... */
@@ -651,6 +666,501 @@ static void destroy_sbmbc(Allctr_t *allctr, Block_t *blk);
static Block_t *create_carrier(Allctr_t *, Uint, UWord);
static void destroy_carrier(Allctr_t *, Block_t *);
+#if 0
+#define ERTS_DBG_CHK_FIX_LIST(A, FIX, IX, B) \
+ do { if ((FIX)) chk_fix_list((A), (FIX), (IX), (B)); } while (0)
+static void
+chk_fix_list(Allctr_t *allctr, ErtsAlcFixList_t *fix, int ix, int before)
+{
+ void *p;
+ int n;
+ for (n = 0, p = fix[ix].list; p; p = *((void **) p))
+ n++;
+ if (n != fix[ix].list_size) {
+ erts_fprintf(stderr, "FOUND IT ts=%d, sched=%d, ix=%d, n=%d, ls=%d %s!\n",
+ allctr->thread_safe, allctr->ix, ix, n, fix[ix].list_size, before ? "before" : "after");
+ abort();
+ }
+}
+#else
+#define ERTS_DBG_CHK_FIX_LIST(A, FIX, IX, B)
+#endif
+
+erts_aint32_t
+erts_alcu_fix_alloc_shrink(Allctr_t *allctr, erts_aint32_t flgs)
+{
+ int all_empty = 1;
+ erts_aint32_t res = 0;
+ int ix, o;
+ ErtsAlcFixList_t *fix = allctr->fix;
+ int flush = flgs == 0;
+
+#ifdef USE_THREADS
+ if (allctr->thread_safe)
+ erts_mtx_lock(&allctr->mutex);
+#endif
+
+ for (ix = 0; ix < ERTS_ALC_NO_FIXED_SIZES; ix++) {
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ if (flgs & ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM) {
+ fix[ix].limit = fix[ix].max_used;
+ if (fix[ix].limit < fix[ix].used)
+ fix[ix].limit = fix[ix].used;
+ fix[ix].max_used = fix[ix].used;
+ ASSERT(fix[ix].limit >= 0);
+
+ }
+ if (flush) {
+ fix[ix].limit = 0;
+ fix[ix].max_used = fix[ix].used;
+ ASSERT(fix[ix].limit >= 0);
+ }
+ for (o = 0; o < ERTS_ALC_FIX_MAX_SHRINK_OPS || flush; o++) {
+ Block_t *blk;
+ void *ptr;
+
+ if (!flush && fix[ix].limit >= fix[ix].allocated)
+ break;
+ if (fix[ix].list_size == 0)
+ break;
+ ptr = fix[ix].list;
+ fix[ix].list = *((void **) ptr);
+ fix[ix].list_size--;
+
+ blk = UMEM2BLK(ptr);
+
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, ptr);
+
+ fix[ix].allocated--;
+ }
+ if (fix[ix].list_size != 0) {
+ if (fix[ix].limit < fix[ix].allocated)
+ res |= ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC;
+ all_empty = 0;
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ }
+
+ if (all_empty && allctr->fix_shrink_scheduled) {
+ allctr->fix_shrink_scheduled = 0;
+ erts_set_aux_work_timeout(allctr->ix,
+ (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ 0);
+ }
+
+#ifdef USE_THREADS
+ if (allctr->thread_safe)
+ erts_mtx_unlock(&allctr->mutex);
+#endif
+
+ return res;
+}
+
+#ifdef ERTS_SMP
+
+#define ERTS_ALCU_DD_FIX_TYPE_OFFS \
+ ((sizeof(ErtsAllctrDDBlock_t)-1)/sizeof(UWord) + 1)
+
+#define ERTS_AU_PREF_ALLOC_IX_MASK \
+ ((((UWord) 1) << ERTS_AU_PREF_ALLOC_BITS) - 1)
+#define ERTS_AU_PREF_ALLOC_SIZE_MASK \
+ ((((UWord) 1) << (sizeof(UWord)*8 - ERTS_AU_PREF_ALLOC_BITS)) - 1)
+
+static ERTS_INLINE int
+get_pref_allctr(void *extra, Allctr_t **allctr)
+{
+ ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
+ int pref_ix;
+
+ pref_ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(sizeof(UWord) == sizeof(Allctr_t *));
+ ASSERT(0 <= pref_ix && pref_ix < tspec->size);
+
+ *allctr = tspec->allctr[pref_ix];
+ return pref_ix;
+}
+
+static ERTS_INLINE void *
+get_used_allctr(void *extra, void *p, Allctr_t **allctr, UWord *sizep)
+{
+ ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
+ void *ptr = (void *) (((char *) p) - sizeof(UWord));
+ UWord ainfo = *((UWord *) ptr);
+ int aix = (int) (ainfo & ERTS_AU_PREF_ALLOC_IX_MASK);
+ *allctr = tspec->allctr[aix];
+ if (sizep)
+ *sizep = ((ainfo >> ERTS_AU_PREF_ALLOC_BITS)
+ & ERTS_AU_PREF_ALLOC_SIZE_MASK);
+ return ptr;
+}
+
+static ERTS_INLINE void *
+put_used_allctr(void *p, int ix, UWord size)
+{
+ UWord ainfo = (size >= ERTS_AU_PREF_ALLOC_SIZE_MASK
+ ? ERTS_AU_PREF_ALLOC_SIZE_MASK
+ : size);
+ ainfo <<= ERTS_AU_PREF_ALLOC_BITS;
+ ainfo |= (UWord) ix;
+ *((UWord *) p) = ainfo;
+ return (void *) (((char *) p) + sizeof(UWord));
+}
+
+static void
+init_dd_queue(ErtsAllctrDDQueue_t *ddq)
+{
+ erts_atomic_init_nob(&ddq->tail.data.marker.atmc_next, ERTS_AINT_NULL);
+ erts_atomic_init_nob(&ddq->tail.data.last,
+ (erts_aint_t) &ddq->tail.data.marker);
+ erts_atomic_init_nob(&ddq->tail.data.um_refc[0], 0);
+ erts_atomic_init_nob(&ddq->tail.data.um_refc[1], 0);
+ erts_atomic32_init_nob(&ddq->tail.data.um_refc_ix, 0);
+ ddq->head.first = &ddq->tail.data.marker;
+ ddq->head.unref_end = &ddq->tail.data.marker;
+ ddq->head.next.thr_progress = erts_thr_progress_current();
+ ddq->head.next.thr_progress_reached = 1;
+ ddq->head.next.um_refc_ix = 1;
+ ddq->head.next.unref_end = &ddq->tail.data.marker;
+ ddq->head.used_marker = 1;
+}
+
+static ERTS_INLINE int
+ddq_managed_thread_enqueue(ErtsAllctrDDQueue_t *ddq, void *ptr, int cinit)
+{
+ erts_aint_t itmp;
+ ErtsAllctrDDBlock_t *enq, *this = ptr;
+
+ erts_atomic_init_nob(&this->atmc_next, ERTS_AINT_NULL);
+ /* Enqueue at end of list... */
+
+ enq = (ErtsAllctrDDBlock_t *) erts_atomic_read_nob(&ddq->tail.data.last);
+ itmp = erts_atomic_cmpxchg_relb(&enq->atmc_next,
+ (erts_aint_t) this,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL) {
+ /* We are required to move last pointer */
+#ifdef DEBUG
+ ASSERT(ERTS_AINT_NULL == erts_atomic_read_nob(&this->atmc_next));
+ ASSERT(((erts_aint_t) enq)
+ == erts_atomic_xchg_relb(&ddq->tail.data.last,
+ (erts_aint_t) this));
+#else
+ erts_atomic_set_relb(&ddq->tail.data.last, (erts_aint_t) this);
+#endif
+ return 1;
+ }
+ else {
+ /*
+ * We *need* to insert element somewhere in between the
+ * last element we read earlier and the actual last element.
+ */
+ int i = cinit;
+
+ while (1) {
+ erts_aint_t itmp2;
+ erts_atomic_set_nob(&this->atmc_next, itmp);
+ itmp2 = erts_atomic_cmpxchg_relb(&enq->atmc_next,
+ (erts_aint_t) this,
+ itmp);
+ if (itmp == itmp2)
+ return 0; /* inserted this */
+ if ((i & 1) == 0)
+ itmp = itmp2;
+ else {
+ enq = (ErtsAllctrDDBlock_t *) itmp2;
+ itmp = erts_atomic_read_acqb(&enq->atmc_next);
+ ASSERT(itmp != ERTS_AINT_NULL);
+ }
+ i++;
+ }
+ }
+}
+
+static ERTS_INLINE erts_aint_t
+check_insert_marker(ErtsAllctrDDQueue_t *ddq, erts_aint_t ilast)
+{
+ if (!ddq->head.used_marker
+ && ddq->head.unref_end == (ErtsAllctrDDBlock_t *) ilast) {
+ erts_aint_t itmp;
+ ErtsAllctrDDBlock_t *last = (ErtsAllctrDDBlock_t *) ilast;
+
+ erts_atomic_init_nob(&ddq->tail.data.marker.atmc_next, ERTS_AINT_NULL);
+ itmp = erts_atomic_cmpxchg_relb(&last->atmc_next,
+ (erts_aint_t) &ddq->tail.data.marker,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL) {
+ ilast = (erts_aint_t) &ddq->tail.data.marker;
+ ddq->head.used_marker = !0;
+ erts_atomic_set_relb(&ddq->tail.data.last, ilast);
+ }
+ }
+ return ilast;
+}
+
+static ERTS_INLINE int
+ddq_enqueue(ErtsAlcType_t type, ErtsAllctrDDQueue_t *ddq, void *ptr, int cinit)
+{
+ int last_elem;
+ int um_refc_ix = 0;
+ int managed_thread = erts_thr_progress_is_managed_thread();
+ if (!managed_thread) {
+ um_refc_ix = erts_atomic32_read_acqb(&ddq->tail.data.um_refc_ix);
+ while (1) {
+ int tmp_um_refc_ix;
+ erts_atomic_inc_acqb(&ddq->tail.data.um_refc[um_refc_ix]);
+ tmp_um_refc_ix = erts_atomic32_read_acqb(&ddq->tail.data.um_refc_ix);
+ if (tmp_um_refc_ix == um_refc_ix)
+ break;
+ erts_atomic_dec_relb(&ddq->tail.data.um_refc[um_refc_ix]);
+ um_refc_ix = tmp_um_refc_ix;
+ }
+ }
+
+ last_elem = ddq_managed_thread_enqueue(ddq, ptr, cinit);
+
+ if (!managed_thread)
+ erts_atomic_dec_relb(&ddq->tail.data.um_refc[um_refc_ix]);
+ return last_elem;
+}
+
+static ERTS_INLINE void *
+ddq_dequeue(ErtsAllctrDDQueue_t *ddq)
+{
+ ErtsAllctrDDBlock_t *blk;
+
+ if (ddq->head.first == ddq->head.unref_end)
+ return NULL;
+
+ blk = ddq->head.first;
+ if (blk == &ddq->tail.data.marker) {
+ ASSERT(ddq->head.used_marker);
+ ddq->head.used_marker = 0;
+ blk = ((ErtsAllctrDDBlock_t *)
+ erts_atomic_read_nob(&blk->atmc_next));
+ if (blk == ddq->head.unref_end) {
+ ddq->head.first = blk;
+ return NULL;
+ }
+ }
+
+ ddq->head.first = ((ErtsAllctrDDBlock_t *)
+ erts_atomic_read_nob(&blk->atmc_next));
+
+ ASSERT(ddq->head.first);
+
+ return (void *) blk;
+}
+
+static int
+ddq_check_incoming(ErtsAllctrDDQueue_t *ddq)
+{
+ erts_aint_t ilast = erts_atomic_read_nob(&ddq->tail.data.last);
+ if (((ErtsAllctrDDBlock_t *) ilast) == &ddq->tail.data.marker
+ && ddq->head.first == &ddq->tail.data.marker) {
+ /* Nothing more to do... */
+ return 0;
+ }
+
+ if (ddq->head.next.thr_progress_reached
+ || erts_thr_progress_has_reached(ddq->head.next.thr_progress)) {
+ int um_refc_ix;
+ ddq->head.next.thr_progress_reached = 1;
+ um_refc_ix = ddq->head.next.um_refc_ix;
+ if (erts_atomic_read_nob(&ddq->tail.data.um_refc[um_refc_ix]) == 0) {
+ /* Move unreferenced end pointer forward... */
+
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+
+ ddq->head.unref_end = ddq->head.next.unref_end;
+
+ ilast = check_insert_marker(ddq, ilast);
+
+ if (ddq->head.unref_end != (ErtsAllctrDDBlock_t *) ilast) {
+ ddq->head.next.unref_end = (ErtsAllctrDDBlock_t *) ilast;
+ ddq->head.next.thr_progress = erts_thr_progress_later(NULL);
+ erts_atomic32_set_relb(&ddq->tail.data.um_refc_ix,
+ um_refc_ix);
+ ddq->head.next.um_refc_ix = um_refc_ix == 0 ? 1 : 0;
+ ddq->head.next.thr_progress_reached = 0;
+ }
+ }
+ }
+ return 1;
+}
+
+static ERTS_INLINE void
+store_earliest_thr_prgr(ErtsThrPrgrVal *prev_val, ErtsAllctrDDQueue_t *ddq)
+{
+ if (!ddq->head.next.thr_progress_reached
+ && (*prev_val == ERTS_THR_PRGR_INVALID
+ || erts_thr_progress_cmp(ddq->head.next.thr_progress,
+ *prev_val) < 0)) {
+ *prev_val = ddq->head.next.thr_progress;
+ }
+}
+
+static ERTS_INLINE int
+handle_delayed_dealloc(Allctr_t *allctr,
+ int allctr_locked,
+ int use_limit,
+ int ops_limit,
+ int *need_thr_progress,
+ ErtsThrPrgrVal *thr_prgr_p,
+ int *need_more_work)
+{
+ int need_thr_prgr = 0;
+ int need_mr_wrk = 0;
+ int have_checked_incoming = 0;
+ int ops = 0;
+ ErtsAlcFixList_t *fix;
+ int res;
+ ErtsAllctrDDQueue_t *ddq;
+
+ if (allctr->thread_safe && !allctr_locked)
+ erts_mtx_lock(&allctr->mutex);
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
+
+ fix = allctr->fix;
+
+ ddq = &allctr->dd.q;
+
+ res = 0;
+
+ while (1) {
+ Block_t *blk;
+ void *ptr;
+ int ix;
+
+ if (use_limit && ++ops > ops_limit) {
+ if (ddq->head.first != ddq->head.unref_end) {
+ need_mr_wrk = 1;
+ if (need_more_work)
+ *need_more_work |= 1;
+ }
+ break;
+ }
+
+ dequeue:
+ ptr = ddq_dequeue(ddq);
+ if (!ptr) {
+ if (have_checked_incoming)
+ break;
+ need_thr_prgr = ddq_check_incoming(ddq);
+ if (need_thr_progress) {
+ *need_thr_progress |= need_thr_prgr;
+ if (need_thr_prgr)
+ store_earliest_thr_prgr(thr_prgr_p, ddq);
+
+ }
+ have_checked_incoming = 1;
+ goto dequeue;
+ }
+
+ res = 1;
+
+ INC_CC(allctr->calls.this_free);
+
+ if (fix) {
+ ErtsAlcType_t type;
+
+ type = (ErtsAlcType_t) ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS];
+ ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ fix[ix].used--;
+ if (fix[ix].allocated < fix[ix].limit
+ && fix[ix].list_size < ERTS_ALCU_FIX_MAX_LIST_SZ) {
+ *((void **) ptr) = fix[ix].list;
+ fix[ix].list = ptr;
+ fix[ix].list_size++;
+ if (!allctr->fix_shrink_scheduled) {
+ allctr->fix_shrink_scheduled = 1;
+ erts_set_aux_work_timeout(
+ allctr->ix,
+ (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ 1);
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ continue;
+ }
+ fix[ix].allocated--;
+ if (fix[ix].list && fix[ix].allocated > fix[ix].limit) {
+ blk = UMEM2BLK(ptr);
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, ptr);
+ ptr = fix[ix].list;
+ fix[ix].list = *((void **) ptr);
+ fix[ix].list_size--;
+ fix[ix].allocated--;
+ }
+ }
+
+ blk = UMEM2BLK(ptr);
+
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, ptr);
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ }
+
+ if (need_thr_progress && !(need_thr_prgr | need_mr_wrk)) {
+ need_thr_prgr = ddq_check_incoming(ddq);
+ *need_thr_progress |= need_thr_prgr;
+ if (need_thr_prgr)
+ store_earliest_thr_prgr(thr_prgr_p, ddq);
+ }
+
+ if (allctr->thread_safe && !allctr_locked)
+ erts_mtx_unlock(&allctr->mutex);
+ return res;
+}
+
+static ERTS_INLINE void
+enqueue_dealloc_other_instance(ErtsAlcType_t type,
+ Allctr_t *allctr,
+ void *ptr,
+ int cinit)
+{
+ if (allctr->fix)
+ ((UWord *) ptr)[ERTS_ALCU_DD_FIX_TYPE_OFFS] = (UWord) type;
+
+ if (ddq_enqueue(type, &allctr->dd.q, ptr, cinit))
+ erts_alloc_notify_delayed_dealloc(allctr->ix);
+}
+
+#endif
+
+#ifdef ERTS_SMP
+void
+erts_alcu_check_delayed_dealloc(Allctr_t *allctr,
+ int limit,
+ int *need_thr_progress,
+ ErtsThrPrgrVal *thr_prgr_p,
+ int *more_work)
+{
+ handle_delayed_dealloc(allctr,
+ 0,
+ limit,
+ ERTS_ALCU_DD_OPS_LIM_HIGH,
+ need_thr_progress,
+ thr_prgr_p,
+ more_work);
+}
+#endif
+
+#define ERTS_ALCU_HANDLE_DD_IN_OP(Allctr, Locked) \
+ handle_delayed_dealloc((Allctr), (Locked), 1, \
+ ERTS_ALCU_DD_OPS_LIM_LOW, NULL, NULL, NULL)
+
/* Multi block carrier alloc/realloc/free ... */
/* NOTE! mbc_alloc() may in case of memory shortage place the requested
@@ -680,8 +1190,21 @@ mbc_alloc_block(Allctr_t *allctr, Uint size, Uint *blk_szp, Uint32 *alcu_flgsp)
}
}
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
+
blk = (*allctr->get_free_block)(allctr, get_blk_sz, NULL, 0, *alcu_flgsp);
+#ifdef ERTS_SMP
+ if (!blk && allctr->dd.use) {
+ if (ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1))
+ blk = (*allctr->get_free_block)(allctr, get_blk_sz, NULL, 0,
+ *alcu_flgsp);
+ }
+#endif
+
if (!blk) {
if ((*alcu_flgsp) & ERTS_ALCU_FLG_SBMBC)
blk = create_sbmbc(allctr, get_blk_sz);
@@ -939,6 +1462,11 @@ mbc_realloc(Allctr_t *allctr, void *p, Uint size, Uint32 alcu_flgs)
Uint is_last_blk;
#endif /* #ifndef MBC_REALLOC_ALWAYS_MOVES */
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
+
ASSERT(p);
ASSERT(size);
ASSERT(size < allctr->sbc_threshold);
@@ -1005,7 +1533,6 @@ mbc_realloc(Allctr_t *allctr, void *p, Uint size, Uint32 alcu_flgs)
cand_blk,
cand_blk_sz,
alcu_flgs);
-
if (new_blk || cand_blk != blk)
goto move_into_new_blk;
}
@@ -1441,7 +1968,7 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
goto try_sys_alloc;
if (flags & CFLG_FORCE_MSEG)
goto try_mseg;
- if (erts_mseg_no() >= max_mseg_carriers)
+ if (erts_mseg_no(&allctr->mseg_opt) >= max_mseg_carriers)
goto try_sys_alloc;
if (flags & CFLG_SBC) {
if (allctr->sbcs.curr.norm.mseg.no >= allctr->max_mseg_sbcs)
@@ -1840,8 +2367,12 @@ static struct {
Eterm ycs;
/* Eterm sbmbcs; */
+
+ Eterm fix_types;
+
Eterm mbcs;
Eterm sbcs;
+
Eterm sys_alloc_carriers_size;
#if HAVE_ERTS_MSEG
Eterm mseg_alloc_carriers_size;
@@ -1871,6 +2402,8 @@ static struct {
#endif
} am;
+static Eterm fix_type_atoms[ERTS_ALC_NO_FIXED_SIZES];
+
static ERTS_INLINE void atom_init(Eterm *atom, char *name)
{
*atom = am_atom_put(name, strlen(name));
@@ -1891,6 +2424,7 @@ init_atoms(Allctr_t *allctr)
erts_mtx_lock(&init_atoms_mtx);
if (!atoms_initialized) {
+ int ix;
#ifdef DEBUG
Eterm *atom;
@@ -1933,8 +2467,12 @@ init_atoms(Allctr_t *allctr)
AM_INIT(ycs);
/*AM_INIT(sbmbcs);*/
+
+ AM_INIT(fix_types);
+
AM_INIT(mbcs);
AM_INIT(sbcs);
+
AM_INIT(sys_alloc_carriers_size);
#if HAVE_ERTS_MSEG
AM_INIT(mseg_alloc_carriers_size);
@@ -1965,6 +2503,13 @@ init_atoms(Allctr_t *allctr)
ASSERT(*atom != THE_NON_VALUE);
}
#endif
+
+ for (ix = 0; ix < ERTS_ALC_NO_FIXED_SIZES; ix++) {
+ ErtsAlcType_t n = ERTS_ALC_N_MIN_A_FIXED_SIZE + ix;
+ char *name = (char *) ERTS_ALC_N2TD(n);
+ size_t len = strlen(name);
+ fix_type_atoms[ix] = am_atom_put(name, len);
+ }
}
@@ -2043,6 +2588,48 @@ add_4tup(Uint **hpp, Uint *szp, Eterm *lp,
}
static Eterm
+sz_info_fix(Allctr_t *allctr,
+ int *print_to_p,
+ void *print_to_arg,
+ Uint **hpp,
+ Uint *szp)
+{
+ Eterm res;
+ int ix;
+ ErtsAlcFixList_t *fix = allctr->fix;
+
+ ASSERT(fix);
+
+ res = NIL;
+
+ for (ix = ERTS_ALC_NO_FIXED_SIZES-1; ix >= 0; ix--) {
+ ErtsAlcType_t n = ix + ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ Uint alloced = (fix[ix].type_size * fix[ix].allocated);
+ Uint used = fix[ix].type_size*fix[ix].used;
+
+ if (print_to_p) {
+ int to = *print_to_p;
+ void *arg = print_to_arg;
+ erts_print(to,
+ arg,
+ "fix type: %s %bpu %bpu\n",
+ (char *) ERTS_ALC_N2TD(n),
+ alloced,
+ used);
+ }
+
+ if (hpp || szp) {
+ add_3tup(hpp, szp, &res,
+ fix_type_atoms[ix],
+ bld_unstable_uint(hpp, szp, alloced),
+ bld_unstable_uint(hpp, szp, used));
+ }
+ }
+
+ return res;
+}
+
+static Eterm
sz_info_carriers(Allctr_t *allctr,
CarriersStats_t *cs,
char *prefix,
@@ -2482,9 +3069,7 @@ info_options(Allctr_t *allctr,
add_2tup(hpp, szp, &res, am.low, allctr->mseg_opt.low_mem ? am_true : am_false);
#endif
add_2tup(hpp, szp, &res, am.ramv, allctr->ramv ? am_true : am_false);
- add_2tup(hpp, szp, &res, am.t, (allctr->t
- ? bld_uint(hpp, szp, (Uint) allctr->t)
- : am_false));
+ add_2tup(hpp, szp, &res, am.t, (allctr->t ? am_true : am_false));
add_2tup(hpp, szp, &res, am.e, am_true);
}
@@ -2590,7 +3175,7 @@ erts_alcu_sz_info(Allctr_t *allctr,
Uint **hpp,
Uint *szp)
{
- Eterm res, sbmbcs, mbcs, sbcs;
+ Eterm res, sbmbcs, mbcs, sbcs, fix = THE_NON_VALUE;
res = THE_NON_VALUE;
@@ -2607,6 +3192,8 @@ erts_alcu_sz_info(Allctr_t *allctr,
erts_mtx_lock(&allctr->mutex);
#endif
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
+
if (hpp || szp)
ensure_atoms_initialized(allctr);
@@ -2619,6 +3206,8 @@ erts_alcu_sz_info(Allctr_t *allctr,
update_max_ever_values(&allctr->mbcs);
update_max_ever_values(&allctr->sbcs);
+ if (allctr->fix)
+ fix = sz_info_fix(allctr, print_to_p, print_to_arg, hpp, szp);
sbmbcs = sz_info_carriers(allctr, &allctr->sbmbcs, "sbmbcs ", print_to_p,
print_to_arg, hpp, szp);
mbcs = sz_info_carriers(allctr, &allctr->mbcs, "mbcs ", print_to_p,
@@ -2631,6 +3220,8 @@ erts_alcu_sz_info(Allctr_t *allctr,
add_2tup(hpp, szp, &res, am.sbcs, sbcs);
add_2tup(hpp, szp, &res, am.mbcs, mbcs);
add_2tup(hpp, szp, &res, am.sbmbcs, sbmbcs);
+ if (allctr->fix)
+ add_2tup(hpp, szp, &res, am.fix_types, fix);
}
if (begin_max_period) {
@@ -2656,7 +3247,7 @@ erts_alcu_info(Allctr_t *allctr,
Uint **hpp,
Uint *szp)
{
- Eterm res, sett, sbmbcs, mbcs, sbcs, calls;
+ Eterm res, sett, sbmbcs, mbcs, sbcs, calls, fix = THE_NON_VALUE;
res = THE_NON_VALUE;
@@ -2673,6 +3264,8 @@ erts_alcu_info(Allctr_t *allctr,
erts_mtx_lock(&allctr->mutex);
#endif
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
+
if (hpp || szp)
ensure_atoms_initialized(allctr);
@@ -2694,6 +3287,8 @@ erts_alcu_info(Allctr_t *allctr,
}
sett = info_options(allctr, print_to_p, print_to_arg, hpp, szp);
+ if (allctr->fix)
+ fix = sz_info_fix(allctr, print_to_p, print_to_arg, hpp, szp);
sbmbcs = info_carriers(allctr, &allctr->sbmbcs, "sbmbcs ", print_to_p,
print_to_arg, hpp, szp);
mbcs = info_carriers(allctr, &allctr->mbcs, "mbcs ", print_to_p,
@@ -2709,6 +3304,8 @@ erts_alcu_info(Allctr_t *allctr,
add_2tup(hpp, szp, &res, am.sbcs, sbcs);
add_2tup(hpp, szp, &res, am.mbcs, mbcs);
add_2tup(hpp, szp, &res, am.sbmbcs, sbmbcs);
+ if (allctr->fix)
+ add_2tup(hpp, szp, &res, am.fix_types, fix);
add_2tup(hpp, szp, &res, am.options, sett);
add_3tup(hpp, szp, &res,
am.versions,
@@ -2733,7 +3330,7 @@ erts_alcu_info(Allctr_t *allctr,
void
-erts_alcu_current_size(Allctr_t *allctr, AllctrSize_t *size)
+erts_alcu_current_size(Allctr_t *allctr, AllctrSize_t *size, ErtsAlcUFixInfo_t *fi, int fisz)
{
#ifdef USE_THREADS
@@ -2751,6 +3348,18 @@ erts_alcu_current_size(Allctr_t *allctr, AllctrSize_t *size)
size->blocks += allctr->sbmbcs.blocks.curr.size;
size->blocks += allctr->sbcs.blocks.curr.size;
+ if (fi) {
+ int ix;
+ for (ix = 0; ix < fisz; ix++) {
+ if (allctr->fix) {
+ fi[ix].allocated += (allctr->fix[ix].type_size
+ * allctr->fix[ix].allocated);
+ fi[ix].used += (allctr->fix[ix].type_size
+ * allctr->fix[ix].used);
+ }
+ }
+ }
+
#ifdef USE_THREADS
if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
@@ -2764,12 +3373,16 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
{
Allctr_t *allctr = (Allctr_t *) extra;
void *res;
+ ErtsAlcFixList_t *fix;
ASSERT(initialized);
ASSERT(allctr);
- ERTS_ALCU_DBG_CHK_THR_SPEC(allctr);
+ ERTS_SMP_LC_ASSERT(!allctr->thread_safe
+ || erts_lc_mtx_is_locked(&allctr->mutex));
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
#if ALLOC_ZERO_EQ_NULL
if (!size)
@@ -2778,18 +3391,61 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
INC_CC(allctr->calls.this_alloc);
+ fix = allctr->fix;
+ if (fix) {
+ int ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ fix[ix].used++;
+ res = fix[ix].list;
+ if (res) {
+ fix[ix].list_size--;
+ fix[ix].list = *((void **) res);
+ if (fix[ix].list && fix[ix].allocated > fix[ix].limit) {
+ void *p = fix[ix].list;
+ Block_t *blk;
+ fix[ix].list = *((void **) p);
+ fix[ix].list_size--;
+ blk = UMEM2BLK(p);
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, p);
+ fix[ix].allocated--;
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ return res;
+ }
+ if (size < 2*sizeof(UWord))
+ size += sizeof(UWord);
+ if (fix[ix].limit < fix[ix].used)
+ fix[ix].limit = fix[ix].used;
+ if (fix[ix].max_used < fix[ix].used)
+ fix[ix].max_used = fix[ix].used;
+ fix[ix].allocated++;
+ }
+
if (size >= allctr->sbc_threshold) {
+ Block_t *blk;
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
#if HALFWORD_HEAP
- Block_t *blk = create_carrier(allctr, size,
- CFLG_SBC | CFLG_FORCE_MSEG);
+ blk = create_carrier(allctr, size,
+ CFLG_SBC | CFLG_FORCE_MSEG);
#else
- Block_t *blk = create_carrier(allctr, size, CFLG_SBC);
+ blk = create_carrier(allctr, size, CFLG_SBC);
#endif
res = blk ? BLK2UMEM(blk) : NULL;
}
else
res = mbc_alloc(allctr, size);
+ if (!res && fix) {
+ int ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ fix[ix].allocated--;
+ fix[ix].used--;
+ }
return res;
}
@@ -2818,29 +3474,28 @@ erts_alcu_alloc_ts(ErtsAlcType_t type, void *extra, Uint size)
return res;
}
+#ifdef ERTS_SMP
+
void *
erts_alcu_alloc_thr_spec(ErtsAlcType_t type, void *extra, Uint size)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
+ int ix;
Allctr_t *allctr;
- int unlock;
void *res;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
erts_mtx_lock(&allctr->mutex);
- }
res = do_erts_alcu_alloc(type, allctr, size);
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
DEBUG_CHECK_ALIGNMENT(res);
@@ -2851,51 +3506,96 @@ erts_alcu_alloc_thr_spec(ErtsAlcType_t type, void *extra, Uint size)
void *
erts_alcu_alloc_thr_pref(ErtsAlcType_t type, void *extra, Uint size)
{
- ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
- Allctr_t *allctr;
+ int pref_ix;
+ Allctr_t *pref_allctr;
void *res;
- ASSERT(sizeof(UWord) == sizeof(Allctr_t *));
- ASSERT(ix > 0);
- if (ix >= tspec->size)
- ix = (ix % (tspec->size - 1)) + 1;
- allctr = tspec->allctr[ix];
- erts_mtx_lock(&allctr->mutex);
- res = do_erts_alcu_alloc(type, allctr, size + sizeof(UWord));
- if (res) {
- *((Allctr_t **) res) = allctr;
- res = (void *) (((char *) res) + sizeof(UWord));
- }
- erts_mtx_unlock(&allctr->mutex);
+ pref_ix = get_pref_allctr(extra, &pref_allctr);
+
+ if (pref_allctr->thread_safe)
+ erts_mtx_lock(&pref_allctr->mutex);
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(pref_allctr);
+
+ res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord));
+ if (pref_allctr->thread_safe)
+ erts_mtx_unlock(&pref_allctr->mutex);
+
+ if (res)
+ res = put_used_allctr(res, pref_ix, size);
+
DEBUG_CHECK_ALIGNMENT(res);
+
+
return res;
}
#endif
+#endif
+
/* ------------------------------------------------------------------------- */
static ERTS_INLINE void
do_erts_alcu_free(ErtsAlcType_t type, void *extra, void *p)
{
+ int ix;
Allctr_t *allctr = (Allctr_t *) extra;
ASSERT(initialized);
ASSERT(allctr);
- ERTS_ALCU_DBG_CHK_THR_SPEC(allctr);
+ ERTS_SMP_LC_ASSERT(!allctr->thread_safe
+ || erts_lc_mtx_is_locked(&allctr->mutex));
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
if (p) {
+ ErtsAlcFixList_t *fix = allctr->fix;
Block_t *blk;
INC_CC(allctr->calls.this_free);
+ if (fix) {
+ ix = type - ERTS_ALC_N_MIN_A_FIXED_SIZE;
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 1);
+ fix[ix].used--;
+ if (fix[ix].allocated < fix[ix].limit
+ && fix[ix].list_size < ERTS_ALCU_FIX_MAX_LIST_SZ) {
+ *((void **) p) = fix[ix].list;
+ fix[ix].list = p;
+ fix[ix].list_size++;
+ if (!allctr->fix_shrink_scheduled) {
+ allctr->fix_shrink_scheduled = 1;
+ erts_set_aux_work_timeout(
+ allctr->ix,
+ (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ 1);
+ }
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
+ return;
+ }
+ fix[ix].allocated--;
+ if (fix[ix].list && fix[ix].allocated > fix[ix].limit) {
+ blk = UMEM2BLK(p);
+ if (IS_SBC_BLK(blk))
+ destroy_carrier(allctr, blk);
+ else
+ mbc_free(allctr, p);
+ p = fix[ix].list;
+ fix[ix].list = *((void **) p);
+ fix[ix].list_size--;
+ fix[ix].allocated--;
+ }
+ }
+
blk = UMEM2BLK(p);
if (IS_SBC_BLK(blk))
destroy_carrier(allctr, blk);
else
mbc_free(allctr, p);
+ ERTS_DBG_CHK_FIX_LIST(allctr, fix, ix, 0);
}
}
@@ -2915,44 +3615,60 @@ erts_alcu_free_ts(ErtsAlcType_t type, void *extra, void *p)
erts_mtx_unlock(&allctr->mutex);
}
+#ifdef ERTS_SMP
+
void
erts_alcu_free_thr_spec(ErtsAlcType_t type, void *extra, void *p)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
- int unlock;
+ int ix;
Allctr_t *allctr;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
erts_mtx_lock(&allctr->mutex);
- }
do_erts_alcu_free(type, allctr, p);
- if (unlock)
+
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
}
void
-erts_alcu_free_thr_pref(ErtsAlcType_t type, void *unused, void *p)
+erts_alcu_free_thr_pref(ErtsAlcType_t type, void *extra, void *p)
{
if (p) {
- void *ptr = (void *) (((char *) p) - sizeof(UWord));
- Allctr_t *allctr = *((Allctr_t **) ptr);
- erts_mtx_lock(&allctr->mutex);
- do_erts_alcu_free(type, allctr, ptr);
- erts_mtx_unlock(&allctr->mutex);
+ Allctr_t *pref_allctr, *used_allctr;
+ void *ptr;
+
+ get_pref_allctr(extra, &pref_allctr);
+ ptr = get_used_allctr(extra, p, &used_allctr, NULL);
+ if (pref_allctr != used_allctr)
+ enqueue_dealloc_other_instance(type,
+ used_allctr,
+ ptr,
+ (used_allctr->dd.ix
+ - pref_allctr->dd.ix));
+ else {
+ if (used_allctr->thread_safe)
+ erts_mtx_lock(&used_allctr->mutex);
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(used_allctr);
+ do_erts_alcu_free(type, used_allctr, ptr);
+ if (used_allctr->thread_safe)
+ erts_mtx_unlock(&used_allctr->mutex);
+ }
}
}
#endif
+#endif
+
/* ------------------------------------------------------------------------- */
static ERTS_INLINE void *
@@ -2970,7 +3686,10 @@ do_erts_alcu_realloc(ErtsAlcType_t type,
ASSERT(allctr);
- ERTS_ALCU_DBG_CHK_THR_SPEC(allctr);
+ ERTS_SMP_LC_ASSERT(!allctr->thread_safe
+ || erts_lc_mtx_is_locked(&allctr->mutex));
+
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(allctr);
if (!p) {
res = do_erts_alcu_alloc(type, extra, size);
@@ -3063,6 +3782,10 @@ do_erts_alcu_realloc(ErtsAlcType_t type,
}
else {
Block_t *new_blk;
+#ifdef ERTS_SMP
+ if (allctr->dd.use)
+ ERTS_ALCU_HANDLE_DD_IN_OP(allctr, 1);
+#endif
if(IS_SBC_BLK(blk)) {
do_carrier_resize:
#if HALFWORD_HEAP
@@ -3166,30 +3889,29 @@ erts_alcu_realloc_mv_ts(ErtsAlcType_t type, void *extra, void *p, Uint size)
return res;
}
+#ifdef ERTS_SMP
+
void *
erts_alcu_realloc_thr_spec(ErtsAlcType_t type, void *extra,
void *ptr, Uint size)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
+ int ix;
Allctr_t *allctr;
- int unlock;
void *res;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
erts_mtx_lock(&allctr->mutex);
- }
res = do_erts_alcu_realloc(type, allctr, ptr, size, 0);
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
DEBUG_CHECK_ALIGNMENT(res);
@@ -3202,26 +3924,22 @@ erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t type, void *extra,
void *ptr, Uint size)
{
ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix = erts_alc_get_thr_ix();
+ int ix;
Allctr_t *allctr;
- int unlock;
void *res;
- ASSERT(ix > 0);
- if (ix < tspec->size) {
- allctr = tspec->allctr[ix];
- unlock = 0;
- }
- else {
- allctr = tspec->allctr[0];
- unlock = 1;
- erts_mtx_lock(&allctr->mutex);
- }
+ ix = ERTS_ALC_GET_THR_IX();
+
+ ASSERT(0 <= ix && ix < tspec->size);
+ allctr = tspec->allctr[ix];
+
+ if (allctr->thread_safe)
+ erts_mtx_lock(&allctr->mutex);
res = do_erts_alcu_alloc(type, allctr, size);
if (!res) {
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
res = erts_alcu_realloc_thr_spec(type, allctr, ptr, size);
}
@@ -3235,7 +3953,7 @@ erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t type, void *extra,
cpy_size = size;
sys_memcpy(res, ptr, cpy_size);
do_erts_alcu_free(type, allctr, ptr);
- if (unlock)
+ if (allctr->thread_safe)
erts_mtx_unlock(&allctr->mutex);
}
@@ -3244,129 +3962,106 @@ erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t type, void *extra,
return res;
}
-void *
-erts_alcu_realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size)
+static ERTS_INLINE void *
+realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size,
+ int force_move)
{
- ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix;
+ int pref_ix;
void *ptr, *res;
Allctr_t *pref_allctr, *used_allctr;
+ UWord old_user_size;
if (!p)
return erts_alcu_alloc_thr_pref(type, extra, size);
- ptr = (void *) (((char *) p) - sizeof(UWord));
- used_allctr = *((Allctr_t **) ptr);
+ pref_ix = get_pref_allctr(extra, &pref_allctr);
+ ptr = get_used_allctr(extra, p, &used_allctr, &old_user_size);
- ix = erts_alc_get_thr_ix();
- ASSERT(ix > 0);
- if (ix >= tspec->size)
- ix = (ix % (tspec->size - 1)) + 1;
- pref_allctr = tspec->allctr[ix];
ASSERT(used_allctr && pref_allctr);
- erts_mtx_lock(&used_allctr->mutex);
- res = do_erts_alcu_realloc(type,
- used_allctr,
- ptr,
- size + sizeof(UWord),
- (pref_allctr != used_allctr
- ? ERTS_ALCU_FLG_FAIL_REALLOC_MOVE
- : 0));
- erts_mtx_unlock(&used_allctr->mutex);
- if (res) {
- ASSERT(used_allctr == *((Allctr_t **) res));
- res = (void *) (((char *) res) + sizeof(UWord));
- DEBUG_CHECK_ALIGNMENT(res);
+ if (!force_move && used_allctr == pref_allctr) {
+ if (used_allctr->thread_safe)
+ erts_mtx_lock(&used_allctr->mutex);
+ ERTS_ALCU_DBG_CHK_THR_ACCESS(used_allctr);
+ res = do_erts_alcu_realloc(type,
+ used_allctr,
+ ptr,
+ size + sizeof(UWord),
+ 0);
+ if (used_allctr->thread_safe)
+ erts_mtx_unlock(&used_allctr->mutex);
+ if (res)
+ res = put_used_allctr(res, pref_ix, size);
}
else {
- erts_mtx_lock(&pref_allctr->mutex);
+ if (pref_allctr->thread_safe)
+ erts_mtx_lock(&pref_allctr->mutex);
res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord));
- erts_mtx_unlock(&pref_allctr->mutex);
+ if (pref_allctr->thread_safe && (!force_move
+ || used_allctr != pref_allctr))
+ erts_mtx_unlock(&pref_allctr->mutex);
if (res) {
Block_t *blk;
size_t cpy_size;
- *((Allctr_t **) res) = pref_allctr;
- res = (void *) (((char *) res) + sizeof(UWord));
+ res = put_used_allctr(res, pref_ix, size);
DEBUG_CHECK_ALIGNMENT(res);
- erts_mtx_lock(&used_allctr->mutex);
blk = UMEM2BLK(ptr);
- cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(UWord);
+ if (old_user_size != ERTS_AU_PREF_ALLOC_SIZE_MASK)
+ cpy_size = old_user_size;
+ else {
+ if (used_allctr->thread_safe && (!force_move
+ || used_allctr != pref_allctr))
+ erts_mtx_lock(&used_allctr->mutex);
+ ERTS_SMP_LC_ASSERT(!used_allctr->thread_safe ||
+ erts_lc_mtx_is_locked(&used_allctr->mutex));
+ cpy_size = BLK_SZ(blk);
+ if (used_allctr->thread_safe && (!force_move
+ || used_allctr != pref_allctr))
+ erts_mtx_unlock(&used_allctr->mutex);
+ cpy_size -= ABLK_HDR_SZ + sizeof(UWord);
+ }
if (cpy_size > size)
cpy_size = size;
sys_memcpy(res, p, cpy_size);
- do_erts_alcu_free(type, used_allctr, ptr);
- erts_mtx_unlock(&used_allctr->mutex);
+
+ if (!force_move || used_allctr != pref_allctr)
+ enqueue_dealloc_other_instance(type,
+ used_allctr,
+ ptr,
+ (used_allctr->dd.ix
+ - pref_allctr->dd.ix));
+ else {
+ do_erts_alcu_free(type, used_allctr, ptr);
+ ASSERT(pref_allctr == used_allctr);
+ if (pref_allctr->thread_safe)
+ erts_mtx_unlock(&pref_allctr->mutex);
+ }
}
}
return res;
}
+void *
+erts_alcu_realloc_thr_pref(ErtsAlcType_t type, void *extra, void *p, Uint size)
+{
+ return realloc_thr_pref(type, extra, p, size, 0);
+}
void *
erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t type, void *extra,
void *p, Uint size)
{
- ErtsAllocatorThrSpec_t *tspec = (ErtsAllocatorThrSpec_t *) extra;
- int ix;
- void *ptr, *res;
- Allctr_t *pref_allctr, *used_allctr;
-
- if (!p)
- return erts_alcu_alloc_thr_pref(type, extra, size);
-
- ptr = (void *) (((char *) p) - sizeof(UWord));
- used_allctr = *((Allctr_t **) ptr);
-
- ix = erts_alc_get_thr_ix();
- ASSERT(ix > 0);
- if (ix >= tspec->size)
- ix = (ix % (tspec->size - 1)) + 1;
- pref_allctr = tspec->allctr[ix];
- ASSERT(used_allctr && pref_allctr);
-
- erts_mtx_lock(&pref_allctr->mutex);
- res = do_erts_alcu_alloc(type, pref_allctr, size + sizeof(UWord));
- if (!res) {
- erts_mtx_unlock(&pref_allctr->mutex);
- res = erts_alcu_realloc_thr_pref(type, extra, p, size);
- }
- else {
- Block_t *blk;
- size_t cpy_size;
- Allctr_t *allctr;
-
- *((Allctr_t **) res) = pref_allctr;
- res = (void *) (((char *) res) + sizeof(UWord));
-
- DEBUG_CHECK_ALIGNMENT(res);
-
- if (used_allctr == pref_allctr)
- allctr = pref_allctr;
- else {
- erts_mtx_unlock(&pref_allctr->mutex);
- allctr = used_allctr;
- erts_mtx_lock(&allctr->mutex);
- }
-
- blk = UMEM2BLK(ptr);
- cpy_size = BLK_SZ(blk) - ABLK_HDR_SZ - sizeof(UWord);
- if (cpy_size > size)
- cpy_size = size;
- sys_memcpy(res, p, cpy_size);
- do_erts_alcu_free(type, allctr, ptr);
- erts_mtx_unlock(&allctr->mutex);
- }
-
- return res;
+ return realloc_thr_pref(type, extra, p, size, 1);
}
#endif
+#endif
+
/* ------------------------------------------------------------------------- */
int
@@ -3381,6 +4076,10 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
sys_memcpy((void *) &allctr->mseg_opt,
(void *) &erts_mseg_default_opt,
sizeof(ErtsMsegOpt_t));
+#ifdef ERTS_SMP
+ if (init->tspec || init->tpref)
+ allctr->mseg_opt.sched_spec = 1;
+#endif
# if HALFWORD_HEAP
allctr->mseg_opt.low_mem = init->low_mem;
# endif
@@ -3390,6 +4089,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
if (!allctr->name_prefix)
goto error;
+ allctr->ix = init->ix;
allctr->alloc_no = init->alloc_no;
if (allctr->alloc_no < ERTS_ALC_A_MIN
|| ERTS_ALC_A_MAX < allctr->alloc_no)
@@ -3431,6 +4131,18 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
goto error;
allctr->min_block_size = UNIT_CEILING(allctr->min_block_size
+ sizeof(UWord));
+#if ERTS_SMP
+ if (init->tpref) {
+ Uint sz = sizeof(Block_t);
+ sz += ERTS_ALCU_DD_FIX_TYPE_OFFS*sizeof(UWord);
+ if (init->fix)
+ sz += sizeof(UWord);
+ sz = UNIT_CEILING(sz);
+ if (sz > allctr->min_block_size)
+ allctr->min_block_size = sz;
+ }
+#endif
+
allctr->sbmbc_threshold = init->sbmbct;
@@ -3493,7 +4205,8 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
if (allctr->mbc_header_size < sizeof(Carrier_t))
goto error;
-#ifdef USE_THREADS
+#ifdef ERTS_SMP
+ allctr->dd.use = 0;
if (init->tpref) {
allctr->mbc_header_size = (UNIT_CEILING(allctr->mbc_header_size
+ FBLK_FTR_SZ
@@ -3507,6 +4220,10 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
+ sizeof(UWord))
- ABLK_HDR_SZ
- sizeof(UWord));
+
+ allctr->dd.use = 1;
+ init_dd_queue(&allctr->dd.q);
+ allctr->dd.ix = init->ix;
}
else
#endif
@@ -3548,6 +4265,21 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
}
+ if (init->fix) {
+ int i;
+ allctr->fix = init->fix;
+ allctr->fix_shrink_scheduled = 0;
+ for (i = 0; i < ERTS_ALC_NO_FIXED_SIZES; i++) {
+ allctr->fix[i].max_used = 0;
+ allctr->fix[i].limit = 0;
+ allctr->fix[i].type_size = init->fix_type_size[i];
+ allctr->fix[i].list_size = 0;
+ allctr->fix[i].list = NULL;
+ allctr->fix[i].allocated = 0;
+ allctr->fix[i].used = 0;
+ }
+ }
+
return 1;
error:
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index fed4d3dbe6..cedf4ccf85 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2012. All Rights Reserved.
*
* The 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,10 +20,13 @@
#ifndef ERL_ALLOC_UTIL__
#define ERL_ALLOC_UTIL__
-#define ERTS_ALCU_VSN_STR "2.2"
+#define ERTS_ALCU_VSN_STR "3.0"
#include "erl_alloc_types.h"
+#define ERTS_AU_PREF_ALLOC_BITS 11
+#define ERTS_AU_MAX_PREF_ALLOC_INSTANCES (1 << ERTS_AU_PREF_ALLOC_BITS)
+
typedef struct Allctr_t_ Allctr_t;
typedef struct {
@@ -35,6 +38,7 @@ typedef struct {
char *name_prefix;
ErtsAlcType_t alloc_no;
int force;
+ int ix;
int ts;
int tspec;
int tpref;
@@ -53,6 +57,9 @@ typedef struct {
UWord mbcgs;
UWord sbmbct;
UWord sbmbcs;
+
+ void *fix;
+ size_t *fix_type_size;
} AllctrInit_t;
typedef struct {
@@ -60,6 +67,11 @@ typedef struct {
UWord carriers;
} AllctrSize_t;
+typedef struct {
+ UWord allocated;
+ UWord used;
+} ErtsAlcUFixInfo_t;
+
#ifndef SMALL_MEMORY
#define ERTS_DEFAULT_ALCU_INIT { \
@@ -71,6 +83,7 @@ typedef struct {
NULL, \
ERTS_ALC_A_INVALID, /* (number) alloc_no: allocator number */\
0, /* (bool) force: force enabled */\
+ 0, /* (number) ix: instance index */\
1, /* (bool) ts: thread safe */\
0, /* (bool) tspec: thread specific */\
0, /* (bool) tpref: thread preferred */\
@@ -88,7 +101,10 @@ typedef struct {
1024*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
256, /* (bytes) sbmbct: small block mbc threshold */\
- 8*1024 /* (bytes) sbmbcs: small block mbc size */\
+ 8*1024, /* (bytes) sbmbcs: small block mbc size */ \
+ /* --- Data not options -------------------------------------------- */\
+ NULL, /* (ptr) fix */\
+ NULL /* (ptr) fix_type_size */\
}
#else /* if SMALL_MEMORY */
@@ -102,6 +118,7 @@ typedef struct {
NULL, \
ERTS_ALC_A_INVALID, /* (number) alloc_no: allocator number */\
0, /* (bool) force: force enabled */\
+ 0, /* (number) ix: instance index */\
1, /* (bool) ts: thread safe */\
0, /* (bool) tspec: thread specific */\
0, /* (bool) tpref: thread preferred */\
@@ -118,7 +135,10 @@ typedef struct {
128*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
256, /* (bytes) sbmbct: small block mbc threshold */\
- 8*1024 /* (bytes) sbmbcs: small block mbc size */\
+ 8*1024, /* (bytes) sbmbcs: small block mbc size */ \
+ /* --- Data not options -------------------------------------------- */\
+ NULL, /* (ptr) fix */\
+ NULL /* (ptr) fix_type_size */\
}
#endif
@@ -132,6 +152,7 @@ void * erts_alcu_alloc_ts(ErtsAlcType_t, void *, Uint);
void * erts_alcu_realloc_ts(ErtsAlcType_t, void *, void *, Uint);
void * erts_alcu_realloc_mv_ts(ErtsAlcType_t, void *, void *, Uint);
void erts_alcu_free_ts(ErtsAlcType_t, void *, void *);
+#ifdef ERTS_SMP
void * erts_alcu_alloc_thr_spec(ErtsAlcType_t, void *, Uint);
void * erts_alcu_realloc_thr_spec(ErtsAlcType_t, void *, void *, Uint);
void * erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t, void *, void *, Uint);
@@ -141,12 +162,18 @@ void * erts_alcu_realloc_thr_pref(ErtsAlcType_t, void *, void *, Uint);
void * erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t, void *, void *, Uint);
void erts_alcu_free_thr_pref(ErtsAlcType_t, void *, void *);
#endif
+#endif
Eterm erts_alcu_au_info_options(int *, void *, Uint **, Uint *);
Eterm erts_alcu_info_options(Allctr_t *, int *, void *, Uint **, Uint *);
Eterm erts_alcu_sz_info(Allctr_t *, int, int *, void *, Uint **, Uint *);
Eterm erts_alcu_info(Allctr_t *, int, int *, void *, Uint **, Uint *);
void erts_alcu_init(AlcUInit_t *);
-void erts_alcu_current_size(Allctr_t *, AllctrSize_t *);
+void erts_alcu_current_size(Allctr_t *, AllctrSize_t *,
+ ErtsAlcUFixInfo_t *, int);
+#ifdef ERTS_SMP
+void erts_alcu_check_delayed_dealloc(Allctr_t *, int, int *, ErtsThrPrgrVal *, int *);
+#endif
+erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
#endif
@@ -202,7 +229,7 @@ void erts_alcu_current_size(Allctr_t *, AllctrSize_t *);
extern int erts_have_sbmbc_alloc;
-typedef union {char c[8]; long l; double d;} Unit_t;
+typedef union {char c[ERTS_ALLOC_ALIGN_BYTES]; long l; double d;} Unit_t;
typedef struct Carrier_t_ Carrier_t;
struct Carrier_t_ {
@@ -246,7 +273,74 @@ typedef struct {
} blocks;
} CarriersStats_t;
+#ifdef ERTS_SMP
+
+typedef union ErtsAllctrDDBlock_t_ ErtsAllctrDDBlock_t;
+
+union ErtsAllctrDDBlock_t_ {
+ erts_atomic_t atmc_next;
+ ErtsAllctrDDBlock_t *ptr_next;
+};
+
+typedef struct {
+ ErtsAllctrDDBlock_t marker;
+ erts_atomic_t last;
+ erts_atomic_t um_refc[2];
+ erts_atomic32_t um_refc_ix;
+} ErtsDDTail_t;
+
+typedef struct {
+ /*
+ * This structure needs to be cache line aligned for best
+ * performance.
+ */
+ union {
+ /* Modified by threads returning memory to this allocator */
+ ErtsDDTail_t data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsDDTail_t))];
+ } tail;
+ /*
+ * Everything below this point is *only* accessed by the
+ * thread owning the allocator.
+ */
+ struct {
+ ErtsAllctrDDBlock_t *first;
+ ErtsAllctrDDBlock_t *unref_end;
+ struct {
+ ErtsThrPrgrVal thr_progress;
+ int thr_progress_reached;
+ int um_refc_ix;
+ ErtsAllctrDDBlock_t *unref_end;
+ } next;
+ int used_marker;
+ } head;
+} ErtsAllctrDDQueue_t;
+
+#endif
+
+typedef struct {
+ size_t type_size;
+ SWord list_size;
+ void *list;
+ SWord max_used;
+ SWord limit;
+ SWord allocated;
+ SWord used;
+} ErtsAlcFixList_t;
+
struct Allctr_t_ {
+#ifdef ERTS_SMP
+ struct {
+ /*
+ * We want the queue at the beginning of
+ * the Allctr_t struct, due to cache line
+ * alignment reasons.
+ */
+ ErtsAllctrDDQueue_t q;
+ int use;
+ int ix;
+ } dd;
+#endif
/* Allocator name prefix */
char * name_prefix;
@@ -254,6 +348,9 @@ struct Allctr_t_ {
/* Allocator number */
ErtsAlcType_t alloc_no;
+ /* Instance index */
+ int ix;
+
/* Alloc, realloc and free names as atoms */
struct {
Eterm alloc;
@@ -278,6 +375,7 @@ struct Allctr_t_ {
Uint mbc_growth_stages;
Uint sbmbc_threshold;
Uint sbmbc_size;
+
#if HAVE_ERTS_MSEG
ErtsMsegOpt_t mseg_opt;
#endif
@@ -315,6 +413,10 @@ struct Allctr_t_ {
void (*check_mbc) (Allctr_t *, Carrier_t *);
#endif
+ int fix_n_base;
+ int fix_shrink_scheduled;
+ ErtsAlcFixList_t *fix;
+
#ifdef USE_THREADS
/* Mutex for this allocator */
erts_mtx_t mutex;
@@ -323,6 +425,7 @@ struct Allctr_t_ {
Allctr_t *prev;
Allctr_t *next;
} ts_list;
+
#endif
int atoms_initialized;
diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.c b/erts/emulator/beam/erl_ao_firstfit_alloc.c
index 90d8ea7300..5bdb752d3a 100644
--- a/erts/emulator/beam/erl_ao_firstfit_alloc.c
+++ b/erts/emulator/beam/erl_ao_firstfit_alloc.c
@@ -170,14 +170,18 @@ erts_aoffalc_start(AOFFAllctr_t *alc,
AOFFAllctrInit_t* aoffinit,
AllctrInit_t *init)
{
- AOFFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ AOFFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) alc;
- sys_memcpy((void *) alc, (void *) &nulled_state, sizeof(AOFFAllctr_t));
+ sys_memcpy((void *) alc, (void *) &zero.allctr, sizeof(AOFFAllctr_t));
allctr->mbc_header_size = sizeof(Carrier_t);
allctr->min_mbc_size = MIN_MBC_SZ;
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index 64fad9fe0e..5150a8a507 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -164,14 +164,14 @@ BIF_RETTYPE bxor_2(BIF_ALIST_2)
BIF_RET(erts_bxor(BIF_P, BIF_ARG_1, BIF_ARG_2));
}
-BIF_RETTYPE bsl_2(Process* p, Eterm arg1, Eterm arg2)
+BIF_RETTYPE bsl_2(BIF_ALIST_2)
{
- BIF_RET(shift(p, arg1, arg2, 0));
+ BIF_RET(shift(BIF_P, BIF_ARG_1, BIF_ARG_2, 0));
}
-BIF_RETTYPE bsr_2(Process* p, Eterm arg1, Eterm arg2)
+BIF_RETTYPE bsr_2(BIF_ALIST_2)
{
- BIF_RET(shift(p, arg1, arg2, 1));
+ BIF_RET(shift(BIF_P, BIF_ARG_1, BIF_ARG_2, 1));
}
static Eterm
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index 91b64411d4..cb975d64b0 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2012. All Rights Reserved.
*
* The 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,10 +24,19 @@
#include "erl_sys_driver.h"
#include "global.h"
#include "erl_threads.h"
+#include "erl_thr_queue.h"
+#include "erl_async.h"
+#include "dtrace-wrapper.h"
+
+#define ERTS_MAX_ASYNC_READY_CALLS_IN_SEQ 20
+
+#define ERTS_ASYNC_PRINT_JOB 0
+
+#if !defined(ERTS_SMP) && defined(USE_THREADS) && !ERTS_USE_ASYNC_READY_Q
+# error "Need async ready queue in non-smp case"
+#endif
typedef struct _erl_async {
- struct _erl_async* next;
- struct _erl_async* prev;
DE_Handle* hndl; /* The DE_Handle is needed when port is gone */
Eterm port;
long async_id;
@@ -35,345 +44,534 @@ typedef struct _erl_async {
ErlDrvPDL pdl;
void (*async_invoke)(void*);
void (*async_free)(void*);
-} ErlAsync;
+#if ERTS_USE_ASYNC_READY_Q
+ Uint sched_id;
+ union {
+ ErtsThrQPrepEnQ_t *prep_enq;
+ ErtsThrQFinDeQ_t fin_deq;
+ } q;
+#endif
+} ErtsAsync;
+
+#if ERTS_USE_ASYNC_READY_Q
+
+/*
+ * We can do without the enqueue mutex since it isn't needed for
+ * thread safety. Its only purpose is to put async threads to sleep
+ * during a blast of ready async jobs. This in order to reduce
+ * contention on the enqueue end of the async ready queues. During
+ * such a blast without the enqueue mutex much cpu time is consumed
+ * by the async threads without them doing much progress which in turn
+ * slow down progress of scheduler threads.
+ */
+#define ERTS_USE_ASYNC_READY_ENQ_MTX 1
+
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
typedef struct {
- erts_mtx_t mtx;
- erts_cnd_t cv;
- erts_tid_t thr;
- int len;
-#ifndef ERTS_SMP
- int hndl;
+ erts_mtx_t enq_mtx;
+} ErtsAsyncReadyQXData;
+
#endif
- ErlAsync* head;
- ErlAsync* tail;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- int no;
+
+typedef struct {
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ union {
+ ErtsAsyncReadyQXData data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
+ sizeof(ErtsAsyncReadyQXData))];
+ } x;
#endif
-} AsyncQueue;
+ ErtsThrQ_t thr_q;
+ ErtsThrQFinDeQ_t fin_deq;
+} ErtsAsyncReadyQ;
+
-static erts_smp_spinlock_t async_id_lock;
-static long async_id = 0;
+typedef union {
+ ErtsAsyncReadyQ arq;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncReadyQ))];
+} ErtsAlgndAsyncReadyQ;
+#endif /* ERTS_USE_ASYNC_READY_Q */
-#ifndef ERTS_SMP
+typedef struct {
+ ErtsThrQ_t thr_q;
+ erts_tid_t thr_id;
+} ErtsAsyncQ;
-erts_mtx_t async_ready_mtx;
-static ErlAsync* async_ready_list = NULL;
+typedef union {
+ ErtsAsyncQ aq;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncQ))];
+} ErtsAlgndAsyncQ;
+typedef struct {
+ int no_initialized;
+ erts_mtx_t mtx;
+ erts_cnd_t cnd;
+ erts_atomic_t id;
+} ErtsAsyncInit;
+
+typedef struct {
+ union {
+ ErtsAsyncInit data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncInit))];
+ } init;
+ ErtsAlgndAsyncQ *queue;
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsAlgndAsyncReadyQ *ready_queue;
#endif
+} ErtsAsyncData;
/*
-** Initialize worker threads (if supported)
-*/
+ * Some compilers, e.g. GCC 4.2.1 and -O3, will optimize away DTrace
+ * calls if they're the last thing in the function. :-(
+ * Many thanks to Trond Norbye, via:
+ * https://github.com/memcached/memcached/commit/6298b3978687530bc9d219b6ac707a1b681b2a46
+ */
+static unsigned gcc_optimizer_hack = 0;
-/* Detach from driver */
-static void async_detach(DE_Handle* dh)
-{
- return;
-}
+int erts_async_max_threads; /* Initialized by erl_init.c */
+int erts_async_thread_suggested_stack_size; /* Initialized by erl_init.c */
+static ErtsAsyncData *async;
-#ifdef USE_THREADS
+#ifndef USE_THREADS
-static AsyncQueue* async_q;
+void
+erts_init_async(void)
+{
-static void* async_main(void*);
-static void async_add(ErlAsync*, AsyncQueue*);
+}
-#ifndef ERTS_SMP
-typedef struct ErtsAsyncReadyCallback_ ErtsAsyncReadyCallback;
-struct ErtsAsyncReadyCallback_ {
- struct ErtsAsyncReadyCallback_ *next;
- void (*callback)(void);
-};
+#else
-static ErtsAsyncReadyCallback *callbacks;
-static int async_handle;
+static void *async_main(void *);
-int erts_register_async_ready_callback(void (*funcp)(void))
+static ERTS_INLINE ErtsAsyncQ *
+async_q(int i)
{
- ErtsAsyncReadyCallback *cb = erts_alloc(ERTS_ALC_T_ARCALLBACK,
- sizeof(ErtsAsyncReadyCallback));
- cb->next = callbacks;
- cb->callback = funcp;
- erts_mtx_lock(&async_ready_mtx);
- callbacks = cb;
- erts_mtx_unlock(&async_ready_mtx);
- return async_handle;
+ return &async->queue[i].aq;
}
-#endif
-int init_async(int hndl)
-{
- erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
- AsyncQueue* q;
- int i;
+#if ERTS_USE_ASYNC_READY_Q
- thr_opts.detached = 0;
- thr_opts.suggested_stack_size = erts_async_thread_suggested_stack_size;
-
-#ifndef ERTS_SMP
- callbacks = NULL;
- async_handle = hndl;
- erts_mtx_init(&async_ready_mtx, "async_ready");
- async_ready_list = NULL;
-#endif
-
- async_id = 0;
- erts_smp_spinlock_init(&async_id_lock, "async_id");
-
- async_q = q = (AsyncQueue*)
- (erts_async_max_threads
- ? erts_alloc(ERTS_ALC_T_ASYNC_Q,
- erts_async_max_threads * sizeof(AsyncQueue))
- : NULL);
- for (i = 0; i < erts_async_max_threads; i++) {
- q->head = NULL;
- q->tail = NULL;
- q->len = 0;
-#ifndef ERTS_SMP
- q->hndl = hndl;
-#endif
-#ifdef ERTS_ENABLE_LOCK_CHECK
- q->no = i;
-#endif
- erts_mtx_init(&q->mtx, "asyncq");
- erts_cnd_init(&q->cv);
- erts_thr_create(&q->thr, async_main, (void*)q, &thr_opts);
- q++;
- }
- return 0;
+static ERTS_INLINE ErtsAsyncReadyQ *
+async_ready_q(Uint sched_id)
+{
+ return &async->ready_queue[((int)sched_id)-1].arq;
}
+#endif
-int exit_async()
+void
+erts_init_async(void)
{
- int i;
+ async = NULL;
+ if (erts_async_max_threads > 0) {
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
+#endif
+ erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
+ char *ptr;
+ size_t tot_size = 0;
+ int i;
+
+ tot_size += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncData));
+ tot_size += sizeof(ErtsAlgndAsyncQ)*erts_async_max_threads;
+#if ERTS_USE_ASYNC_READY_Q
+ tot_size += sizeof(ErtsAlgndAsyncReadyQ)*erts_no_schedulers;
+#endif
- /* terminate threads */
- for (i = 0; i < erts_async_max_threads; i++) {
- ErlAsync* a = (ErlAsync*) erts_alloc(ERTS_ALC_T_ASYNC,
- sizeof(ErlAsync));
- a->port = NIL;
- async_add(a, &async_q[i]);
- }
+ ptr = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_ASYNC_DATA,
+ tot_size);
- for (i = 0; i < erts_async_max_threads; i++) {
- erts_thr_join(async_q[i].thr, NULL);
- erts_mtx_destroy(&async_q[i].mtx);
- erts_cnd_destroy(&async_q[i].cv);
- }
-#ifndef ERTS_SMP
- erts_mtx_destroy(&async_ready_mtx);
+ async = (ErtsAsyncData *) ptr;
+ ptr += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsAsyncData));
+
+ async->init.data.no_initialized = 0;
+ erts_mtx_init(&async->init.data.mtx, "async_init_mtx");
+ erts_cnd_init(&async->init.data.cnd);
+ erts_atomic_init_nob(&async->init.data.id, 0);
+
+ async->queue = (ErtsAlgndAsyncQ *) ptr;
+ ptr += sizeof(ErtsAlgndAsyncQ)*erts_async_max_threads;
+
+#if ERTS_USE_ASYNC_READY_Q
+
+ qinit.live.queue = ERTS_THR_Q_LIVE_LONG;
+ qinit.live.objects = ERTS_THR_Q_LIVE_SHORT;
+ qinit.notify = erts_notify_check_async_ready_queue;
+
+ async->ready_queue = (ErtsAlgndAsyncReadyQ *) ptr;
+ ptr += sizeof(ErtsAlgndAsyncReadyQ)*erts_no_schedulers;
+
+ for (i = 1; i <= erts_no_schedulers; i++) {
+ ErtsAsyncReadyQ *arq = async_ready_q(i);
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ erts_mtx_init(&arq->x.data.enq_mtx, "async_enq_mtx");
#endif
- if (async_q)
- erts_free(ERTS_ALC_T_ASYNC_Q, (void *) async_q);
- return 0;
+ erts_thr_q_finalize_dequeue_state_init(&arq->fin_deq);
+ qinit.arg = (void *) (SWord) i;
+ erts_thr_q_initialize(&arq->thr_q, &qinit);
+ }
+
+#endif
+
+ /* Create async threads... */
+
+ thr_opts.detached = 0;
+ thr_opts.suggested_stack_size
+ = erts_async_thread_suggested_stack_size;
+
+ for (i = 0; i < erts_async_max_threads; i++) {
+ ErtsAsyncQ *aq = async_q(i);
+ erts_thr_create(&aq->thr_id, async_main, (void*) aq, &thr_opts);
+ }
+
+ /* Wait for async threads to initialize... */
+
+ erts_mtx_lock(&async->init.data.mtx);
+ while (async->init.data.no_initialized != erts_async_max_threads)
+ erts_cnd_wait(&async->init.data.cnd, &async->init.data.mtx);
+ erts_mtx_unlock(&async->init.data.mtx);
+
+ erts_mtx_destroy(&async->init.data.mtx);
+ erts_cnd_destroy(&async->init.data.cnd);
+
+ }
}
+#if ERTS_USE_ASYNC_READY_Q
-static void async_add(ErlAsync* a, AsyncQueue* q)
+void *
+erts_get_async_ready_queue(Uint sched_id)
{
+ return (void *) async ? async_ready_q(sched_id) : NULL;
+}
+
+#endif
+
+static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q)
+{
+#ifdef USE_VM_PROBES
+ int len;
+#endif
+
if (is_internal_port(a->port)) {
- ERTS_LC_ASSERT(erts_drvportid2port(a->port));
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsAsyncReadyQ *arq = async_ready_q(a->sched_id);
+ a->q.prep_enq = erts_thr_q_prepare_enqueue(&arq->thr_q);
+#endif
/* make sure the driver will stay around */
- driver_lock_driver(internal_port_index(a->port));
+ if (a->hndl)
+ erts_ddll_reference_referenced_driver(a->hndl);
}
- erts_mtx_lock(&q->mtx);
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "-> %ld\n", a->async_id);
+#endif
- if (q->len == 0) {
- q->head = a;
- q->tail = a;
- q->len = 1;
- erts_cnd_signal(&q->cv);
- }
- else { /* no need to signal (since the worker is working) */
- a->next = q->head;
- q->head->prev = a;
- q->head = a;
- q->len++;
+ erts_thr_q_enqueue(&q->thr_q, a);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(aio_pool_add)) {
+ DTRACE_CHARBUF(port_str, 16);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", a->port);
+ /* DTRACE TODO: Get the queue length from erts_thr_q_enqueue() ? */
+ len = -1;
+ DTRACE2(aio_pool_add, port_str, len);
}
- erts_mtx_unlock(&q->mtx);
+#endif
+ gcc_optimizer_hack++;
}
-static ErlAsync* async_get(AsyncQueue* q)
+static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q,
+ erts_tse_t *tse,
+ ErtsThrQPrepEnQ_t **prep_enq)
{
- ErlAsync* a;
+#if ERTS_USE_ASYNC_READY_Q
+ int saved_fin_deq = 0;
+ ErtsThrQFinDeQ_t fin_deq;
+#endif
+#ifdef USE_VM_PROBES
+ int len;
+#endif
- erts_mtx_lock(&q->mtx);
- while((a = q->tail) == NULL) {
- erts_cnd_wait(&q->cv, &q->mtx);
- }
+ while (1) {
+ ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(q);
+ if (a) {
+
+#if ERTS_USE_ASYNC_READY_Q
+ *prep_enq = a->q.prep_enq;
+ erts_thr_q_get_finalize_dequeue_data(q, &a->q.fin_deq);
+ if (saved_fin_deq)
+ erts_thr_q_append_finalize_dequeue_data(&a->q.fin_deq, &fin_deq);
+#endif
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(aio_pool_get)) {
+ DTRACE_CHARBUF(port_str, 16);
+
+ erts_snprintf(port_str, sizeof(port_str), "%T", a->port);
+ /* DTRACE TODO: Get the length from erts_thr_q_dequeue() ? */
+ len = -1;
+ DTRACE2(aio_pool_get, port_str, len);
+ }
+#endif
+ return a;
+ }
+
+ if (ERTS_THR_Q_DIRTY != erts_thr_q_clean(q)) {
+ ErtsThrQFinDeQ_t tmp_fin_deq;
+
+ erts_tse_reset(tse);
+
+#if ERTS_USE_ASYNC_READY_Q
+ chk_fin_deq:
+ if (erts_thr_q_get_finalize_dequeue_data(q, &tmp_fin_deq)) {
+ if (!saved_fin_deq) {
+ erts_thr_q_finalize_dequeue_state_init(&fin_deq);
+ saved_fin_deq = 1;
+ }
+ erts_thr_q_append_finalize_dequeue_data(&fin_deq,
+ &tmp_fin_deq);
+ }
+#endif
+
+ switch (erts_thr_q_inspect(q, 1)) {
+ case ERTS_THR_Q_DIRTY:
+ break;
+ case ERTS_THR_Q_NEED_THR_PRGR:
#ifdef ERTS_SMP
- ASSERT(a && q->tail == a);
+ {
+ ErtsThrPrgrVal prgr = erts_thr_q_need_thr_progress(q);
+ erts_thr_progress_wakeup(NULL, prgr);
+ /*
+ * We do no dequeue finalizing in hope that a new async
+ * job will arrive before we are woken due to thread
+ * progress...
+ */
+ erts_tse_wait(tse);
+ break;
+ }
#endif
- if (q->head == q->tail) {
- q->head = q->tail = NULL;
- q->len = 0;
- }
- else {
- q->tail->prev->next = NULL;
- q->tail = q->tail->prev;
- q->len--;
+ case ERTS_THR_Q_CLEAN:
+
+#if ERTS_USE_ASYNC_READY_Q
+ if (saved_fin_deq) {
+ if (erts_thr_q_finalize_dequeue(&fin_deq))
+ goto chk_fin_deq;
+ else
+ saved_fin_deq = 0;
+ }
+#endif
+
+ erts_tse_wait(tse);
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ }
}
- erts_mtx_unlock(&q->mtx);
- return a;
}
-
-static int async_del(long id)
+static ERTS_INLINE void call_async_ready(ErtsAsync *a)
{
- int i;
- /* scan all queue for an entry with async_id == 'id' */
-
- for (i = 0; i < erts_async_max_threads; i++) {
- ErlAsync* a;
- erts_mtx_lock(&async_q[i].mtx);
-
- a = async_q[i].head;
- while(a != NULL) {
- if (a->async_id == id) {
- if (a->prev != NULL)
- a->prev->next = a->next;
- else
- async_q[i].head = a->next;
- if (a->next != NULL)
- a->next->prev = a->prev;
- else
- async_q[i].tail = a->prev;
- async_q[i].len--;
- erts_mtx_unlock(&async_q[i].mtx);
- if (a->async_free != NULL)
- a->async_free(a->async_data);
- async_detach(a->hndl);
- erts_free(ERTS_ALC_T_ASYNC, a);
- return 1;
- }
- a = a->next;
+ Port *p = erts_id2port_sflgs(a->port,
+ NULL,
+ 0,
+ ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
+ if (!p) {
+ if (a->async_free)
+ a->async_free(a->async_data);
+ }
+ else {
+ if (async_ready(p, a->async_data)) {
+ if (a->async_free)
+ a->async_free(a->async_data);
}
- erts_mtx_unlock(&async_q[i].mtx);
+ erts_port_release(p);
}
- return 0;
+ if (a->hndl)
+ erts_ddll_dereference_driver(a->hndl);
}
-static void* async_main(void* arg)
+static ERTS_INLINE void async_reply(ErtsAsync *a, ErtsThrQPrepEnQ_t *prep_enq)
{
- AsyncQueue* q = (AsyncQueue*) arg;
+#if ERTS_USE_ASYNC_READY_Q
+ ErtsAsyncReadyQ *arq;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- {
- char buf[27];
- erts_snprintf(&buf[0], 27, "async %d", q->no);
- erts_lc_set_thread_name(&buf[0]);
- }
+ if (a->pdl)
+ driver_pdl_dec_refc(a->pdl);
+
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "=>> %ld\n", a->async_id);
#endif
- while(1) {
- ErlAsync* a = async_get(q);
+ arq = async_ready_q(a->sched_id);
- if (a->port == NIL) { /* TIME TO DIE SIGNAL */
- erts_free(ERTS_ALC_T_ASYNC, (void *) a);
- break;
- }
- else {
- (*a->async_invoke)(a->async_data);
- /* Major problem if the code for async_invoke
- or async_free is removed during a blocking operation */
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ erts_mtx_lock(&arq->x.data.enq_mtx);
+#endif
+
+ erts_thr_q_enqueue_prepared(&arq->thr_q, (void *) a, prep_enq);
+
+#if ERTS_USE_ASYNC_READY_ENQ_MTX
+ erts_mtx_unlock(&arq->x.data.enq_mtx);
+#endif
+
+#else /* ERTS_USE_ASYNC_READY_Q */
+
+ call_async_ready(a);
+ if (a->pdl)
+ driver_pdl_dec_refc(a->pdl);
+ erts_free(ERTS_ALC_T_ASYNC, (void *) a);
+
+#endif /* ERTS_USE_ASYNC_READY_Q */
+}
+
+
+static void
+async_wakeup(void *vtse)
+{
+ erts_tse_set((erts_tse_t *) vtse);
+}
+
+static erts_tse_t *async_thread_init(ErtsAsyncQ *aq)
+{
+ ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
+ erts_tse_t *tse = erts_tse_fetch();
#ifdef ERTS_SMP
- {
- Port *p;
- p = erts_id2port_sflgs(a->port,
- NULL,
- 0,
- ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
- if (!p) {
- if (a->async_free)
- (*a->async_free)(a->async_data);
- }
- else {
- if (async_ready(p, a->async_data)) {
- if (a->async_free)
- (*a->async_free)(a->async_data);
- }
- async_detach(a->hndl);
- erts_port_release(p);
- }
- if (a->pdl) {
- driver_pdl_dec_refc(a->pdl);
- }
- erts_free(ERTS_ALC_T_ASYNC, (void *) a);
- }
-#else
- if (a->pdl) {
- driver_pdl_dec_refc(a->pdl);
- }
- erts_mtx_lock(&async_ready_mtx);
- a->next = async_ready_list;
- async_ready_list = a;
- erts_mtx_unlock(&async_ready_mtx);
- sys_async_ready(q->hndl);
+ ErtsThrPrgrCallbacks callbacks;
+
+ callbacks.arg = (void *) tse;
+ callbacks.wakeup = async_wakeup;
+ callbacks.prepare_wait = NULL;
+ callbacks.wait = NULL;
+
+ erts_thr_progress_register_unmanaged_thread(&callbacks);
#endif
- }
- }
- return NULL;
+ qinit.live.queue = ERTS_THR_Q_LIVE_LONG;
+ qinit.live.objects = ERTS_THR_Q_LIVE_SHORT;
+ qinit.arg = (void *) tse;
+ qinit.notify = async_wakeup;
+#if ERTS_USE_ASYNC_READY_Q
+ qinit.auto_finalize_dequeue = 0;
+#endif
+
+ erts_thr_q_initialize(&aq->thr_q, &qinit);
+
+ /* Inform main thread that we are done initializing... */
+ erts_mtx_lock(&async->init.data.mtx);
+ async->init.data.no_initialized++;
+ erts_cnd_signal(&async->init.data.cnd);
+ erts_mtx_unlock(&async->init.data.mtx);
+
+ return tse;
}
+static void *async_main(void* arg)
+{
+ ErtsAsyncQ *aq = (ErtsAsyncQ *) arg;
+ erts_tse_t *tse = async_thread_init(aq);
+ while (1) {
+ ErtsThrQPrepEnQ_t *prep_enq;
+ ErtsAsync *a = async_get(&aq->thr_q, tse, &prep_enq);
+ if (is_nil(a->port))
+ break; /* Time to die */
+
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "<- %ld\n", a->async_id);
#endif
-#ifndef ERTS_SMP
+ a->async_invoke(a->async_data);
+
+ async_reply(a, prep_enq);
+ }
+
+ return NULL;
+}
+
+#endif /* USE_THREADS */
-int check_async_ready(void)
+void
+erts_exit_flush_async(void)
{
#ifdef USE_THREADS
- ErtsAsyncReadyCallback *cbs;
+ int i;
+ ErtsAsync a;
+ a.port = NIL;
+ /*
+ * Terminate threads in order to flush queues. We do not
+ * bother to clean everything up since we are about to
+ * terminate the runtime system and a cleanup would only
+ * delay the termination.
+ */
+ for (i = 0; i < erts_async_max_threads; i++)
+ async_add(&a, async_q(i));
+ for (i = 0; i < erts_async_max_threads; i++)
+ erts_thr_join(async->queue[i].aq.thr_id, NULL);
#endif
- ErlAsync* a;
- int count = 0;
+}
- erts_mtx_lock(&async_ready_mtx);
- a = async_ready_list;
- async_ready_list = NULL;
-#ifdef USE_THREADS
- cbs = callbacks;
-#endif
- erts_mtx_unlock(&async_ready_mtx);
-
- while(a != NULL) {
- ErlAsync* a_next = a->next;
- /* Every port not dead */
- Port *p = erts_id2port_sflgs(a->port,
- NULL,
- 0,
- ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
- if (!p) {
- if (a->async_free)
- (*a->async_free)(a->async_data);
- }
- else {
- count++;
- if (async_ready(p, a->async_data)) {
- if (a->async_free != NULL)
- (*a->async_free)(a->async_data);
- }
- async_detach(a->hndl);
- erts_port_release(p);
+#if defined(USE_THREADS) && ERTS_USE_ASYNC_READY_Q
+
+int erts_check_async_ready(void *varq)
+{
+ ErtsAsyncReadyQ *arq = (ErtsAsyncReadyQ *) varq;
+ int res = 1;
+ int i;
+
+ for (i = 0; i < ERTS_MAX_ASYNC_READY_CALLS_IN_SEQ; i++) {
+ ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(&arq->thr_q);
+ if (!a) {
+ res = 0;
+ break;
}
+
+#if ERTS_ASYNC_PRINT_JOB
+ erts_fprintf(stderr, "<<= %ld\n", a->async_id);
+#endif
+ erts_thr_q_append_finalize_dequeue_data(&arq->fin_deq, &a->q.fin_deq);
+ call_async_ready(a);
erts_free(ERTS_ALC_T_ASYNC, (void *) a);
- a = a_next;
}
-#ifdef USE_THREADS
- for (; cbs; cbs = cbs->next)
- (*cbs->callback)();
-#endif
- return count;
+
+ erts_thr_q_finalize_dequeue(&arq->fin_deq);
+
+ return res;
}
+int erts_async_ready_clean(void *varq, void *val)
+{
+ ErtsAsyncReadyQ *arq = (ErtsAsyncReadyQ *) varq;
+ ErtsThrQCleanState_t cstate;
+
+ cstate = erts_thr_q_clean(&arq->thr_q);
+
+ if (erts_thr_q_finalize_dequeue(&arq->fin_deq))
+ return ERTS_ASYNC_READY_DIRTY;
+
+ switch (cstate) {
+ case ERTS_THR_Q_DIRTY:
+ return ERTS_ASYNC_READY_DIRTY;
+ case ERTS_THR_Q_NEED_THR_PRGR:
+#ifdef ERTS_SMP
+ *((ErtsThrPrgrVal *) val)
+ = erts_thr_q_need_thr_progress(&arq->thr_q);
+ return ERTS_ASYNC_READY_NEED_THR_PRGR;
#endif
+ case ERTS_THR_Q_CLEAN:
+ break;
+ }
+ return ERTS_ASYNC_READY_CLEAN;
+}
+#endif
/*
** Schedule async_invoke on a worker thread
@@ -393,19 +591,29 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
void (*async_invoke)(void*), void* async_data,
void (*async_free)(void*))
{
- ErlAsync* a = (ErlAsync*) erts_alloc(ERTS_ALC_T_ASYNC, sizeof(ErlAsync));
- Port* prt = erts_drvport2port(ix);
+ ErtsAsync* a;
+ Port* prt;
long id;
unsigned int qix;
+#if ERTS_USE_ASYNC_READY_Q
+ Uint sched_id;
+ sched_id = erts_get_scheduler_id();
+ if (!sched_id)
+ sched_id = 1;
+#endif
+ prt = erts_drvport2port(ix);
if (!prt)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
- a->next = NULL;
- a->prev = NULL;
+ a = (ErtsAsync*) erts_alloc(ERTS_ALC_T_ASYNC, sizeof(ErtsAsync));
+
+#if ERTS_USE_ASYNC_READY_Q
+ a->sched_id = sched_id;
+#endif
a->hndl = (DE_Handle*)prt->drv_ptr->handle;
a->port = prt->id;
a->pdl = NULL;
@@ -413,12 +621,16 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
a->async_invoke = async_invoke;
a->async_free = async_free;
- erts_smp_spin_lock(&async_id_lock);
- async_id = (async_id + 1) & 0x7fffffff;
- if (async_id == 0)
- async_id++;
- id = async_id;
- erts_smp_spin_unlock(&async_id_lock);
+ if (!async)
+ id = 0;
+ else {
+ do {
+ id = erts_atomic_inc_read_nob(&async->init.data.id);
+ } while (id == 0);
+ if (id < 0)
+ id *= -1;
+ ASSERT(id > 0);
+ }
a->async_id = id;
@@ -437,7 +649,7 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
driver_pdl_inc_refc(prt->port_data_lock);
a->pdl = prt->port_data_lock;
}
- async_add(a, &async_q[qix]);
+ async_add(a, async_q(qix));
return id;
}
#endif
@@ -455,10 +667,16 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
int driver_async_cancel(unsigned int id)
{
-#ifdef USE_THREADS
- if (erts_async_max_threads > 0)
- return async_del(id);
-#endif
+ /*
+ * Not supported anymore. Always fail (which is backward
+ * compatible).
+ *
+ * This functionality could be implemented again. However,
+ * it is (and always has been) completely useless since
+ * it doesn't give you any guarantees whatsoever. The user
+ * needs to (and always have had to) synchronize in his/her
+ * own code in order to get any guarantees.
+ */
return 0;
}
diff --git a/erts/emulator/beam/erl_async.h b/erts/emulator/beam/erl_async.h
new file mode 100644
index 0000000000..95374a8fc9
--- /dev/null
+++ b/erts/emulator/beam/erl_async.h
@@ -0,0 +1,66 @@
+/*
+ * %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%
+ */
+
+#ifndef ERL_ASYNC_H__
+#define ERL_ASYNC_H__
+
+#define ERTS_MAX_NO_OF_ASYNC_THREADS 1024
+extern int erts_async_max_threads;
+#define ERTS_ASYNC_THREAD_MIN_STACK_SIZE 16 /* Kilo words */
+#define ERTS_ASYNC_THREAD_MAX_STACK_SIZE 8192 /* Kilo words */
+extern int erts_async_thread_suggested_stack_size;
+
+#ifdef USE_THREADS
+
+#ifdef ERTS_SMP
+/*
+ * With smp support we can choose to have, or not to
+ * have an async ready queue.
+ */
+#define ERTS_USE_ASYNC_READY_Q 1
+#endif
+
+#ifndef ERTS_SMP
+/* In non-smp case we *need* the async ready queue */
+# undef ERTS_USE_ASYNC_READY_Q
+# define ERTS_USE_ASYNC_READY_Q 1
+#endif
+
+#ifndef ERTS_USE_ASYNC_READY_Q
+# define ERTS_USE_ASYNC_READY_Q 0
+#endif
+
+#if ERTS_USE_ASYNC_READY_Q
+int erts_check_async_ready(void *);
+int erts_async_ready_clean(void *, void *);
+void *erts_get_async_ready_queue(Uint sched_id);
+#define ERTS_ASYNC_READY_CLEAN 0
+#define ERTS_ASYNC_READY_DIRTY 1
+#ifdef ERTS_SMP
+#define ERTS_ASYNC_READY_NEED_THR_PRGR 2
+#endif
+#endif /* ERTS_USE_ASYNC_READY_Q */
+
+#endif /* USE_THREADS */
+
+void erts_init_async(void);
+void erts_exit_flush_async(void);
+
+
+#endif /* ERL_ASYNC_H__ */
diff --git a/erts/emulator/beam/erl_bestfit_alloc.c b/erts/emulator/beam/erl_bestfit_alloc.c
index f2199d41a1..c50fdeb4e8 100644
--- a/erts/emulator/beam/erl_bestfit_alloc.c
+++ b/erts/emulator/beam/erl_bestfit_alloc.c
@@ -161,14 +161,18 @@ erts_bfalc_start(BFAllctr_t *bfallctr,
BFAllctrInit_t *bfinit,
AllctrInit_t *init)
{
- BFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ BFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) bfallctr;
- sys_memcpy((void *) bfallctr, (void *) &nulled_state, sizeof(BFAllctr_t));
+ sys_memcpy((void *) bfallctr, (void *) &zero.allctr, sizeof(BFAllctr_t));
bfallctr->address_order = bfinit->ao;
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 684fa5d12f..cc4f2be8eb 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -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
@@ -65,6 +65,10 @@ static Export binary_copy_trap_export;
static BIF_RETTYPE binary_copy_trap(BIF_ALIST_2);
static Uint max_loop_limit;
+static BIF_RETTYPE
+binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
+static BIF_RETTYPE
+binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
void erts_init_bif_binary(void)
{
@@ -1148,7 +1152,7 @@ static int do_binary_match(Process *p, Eterm subject, Uint hsstart, Uint hsend,
erts_free_aligned_binary_bytes(temp_alloc);
return DO_BIN_MATCH_RESTART;
} else {
- Eterm epos = erts_make_integer(pos+hsstart,p);
+ Eterm epos = erts_make_integer(pos,p);
Eterm erlen = erts_make_integer(rlen,p);
hp = HAlloc(p,3);
ret = TUPLE2(hp, epos, erlen);
@@ -1399,6 +1403,12 @@ static BIF_RETTYPE binary_matches_trap(BIF_ALIST_3)
BIF_RETTYPE binary_match_3(BIF_ALIST_3)
{
+ return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
Uint hsstart;
Uint hsend;
Eterm *tp;
@@ -1408,17 +1418,17 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
int runres;
Eterm result;
- if (is_not_binary(BIF_ARG_1)) {
+ if (is_not_binary(arg1)) {
goto badarg;
}
- if (parse_match_opts_list(BIF_ARG_3,BIF_ARG_1,&hsstart,&hsend)) {
+ if (parse_match_opts_list(arg3,arg1,&hsstart,&hsend)) {
goto badarg;
}
if (hsend == 0) {
BIF_RET(am_nomatch);
}
- if (is_tuple(BIF_ARG_2)) {
- tp = tuple_val(BIF_ARG_2);
+ if (is_tuple(arg2)) {
+ tp = tuple_val(arg2);
if (arityval(*tp) != 2 || is_not_atom(tp[1])) {
goto badarg;
}
@@ -1437,13 +1447,13 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
goto badarg;
}
bin_term = tp[2];
- } else if (do_binary_match_compile(BIF_ARG_2,&type,&bin)) {
+ } else if (do_binary_match_compile(arg2,&type,&bin)) {
goto badarg;
}
- runres = do_binary_match(BIF_P,BIF_ARG_1,hsstart,hsend,type,bin,NIL,&result);
+ runres = do_binary_match(p,arg1,hsstart,hsend,type,bin,NIL,&result);
if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) {
- Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE);
- bin_term = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), bin);
+ Eterm *hp = HAlloc(p, PROC_BIN_SIZE);
+ bin_term = erts_mk_magic_binary_term(&hp, &MSO(p), bin);
} else if (bin_term == NIL) {
erts_bin_free(bin);
}
@@ -1451,17 +1461,23 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
case DO_BIN_MATCH_OK:
BIF_RET(result);
case DO_BIN_MATCH_RESTART:
- BUMP_ALL_REDS(BIF_P);
- BIF_TRAP3(&binary_match_trap_export, BIF_P, BIF_ARG_1, result, bin_term);
+ BUMP_ALL_REDS(p);
+ BIF_TRAP3(&binary_match_trap_export, p, arg1, result, bin_term);
default:
goto badarg;
}
badarg:
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
{
+ return binary_matches(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
Uint hsstart, hsend;
Eterm *tp;
Eterm type;
@@ -1470,17 +1486,17 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
int runres;
Eterm result;
- if (is_not_binary(BIF_ARG_1)) {
+ if (is_not_binary(arg1)) {
goto badarg;
}
- if (parse_match_opts_list(BIF_ARG_3,BIF_ARG_1,&hsstart,&hsend)) {
+ if (parse_match_opts_list(arg3,arg1,&hsstart,&hsend)) {
goto badarg;
}
if (hsend == 0) {
BIF_RET(NIL);
}
- if (is_tuple(BIF_ARG_2)) {
- tp = tuple_val(BIF_ARG_2);
+ if (is_tuple(arg2)) {
+ tp = tuple_val(arg2);
if (arityval(*tp) != 2 || is_not_atom(tp[1])) {
goto badarg;
}
@@ -1499,14 +1515,14 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
goto badarg;
}
bin_term = tp[2];
- } else if (do_binary_match_compile(BIF_ARG_2,&type,&bin)) {
+ } else if (do_binary_match_compile(arg2,&type,&bin)) {
goto badarg;
}
- runres = do_binary_matches(BIF_P,BIF_ARG_1,hsstart,hsend,type,bin,
+ runres = do_binary_matches(p,arg1,hsstart,hsend,type,bin,
NIL,&result);
if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) {
- Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE);
- bin_term = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), bin);
+ Eterm *hp = HAlloc(p, PROC_BIN_SIZE);
+ bin_term = erts_mk_magic_binary_term(&hp, &MSO(p), bin);
} else if (bin_term == NIL) {
erts_bin_free(bin);
}
@@ -1514,26 +1530,26 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
case DO_BIN_MATCH_OK:
BIF_RET(result);
case DO_BIN_MATCH_RESTART:
- BUMP_ALL_REDS(BIF_P);
- BIF_TRAP3(&binary_matches_trap_export, BIF_P, BIF_ARG_1, result,
+ BUMP_ALL_REDS(p);
+ BIF_TRAP3(&binary_matches_trap_export, p, arg1, result,
bin_term);
default:
goto badarg;
}
badarg:
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
BIF_RETTYPE binary_match_2(BIF_ALIST_2)
{
- return binary_match_3(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
+ return binary_match(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
}
BIF_RETTYPE binary_matches_2(BIF_ALIST_2)
{
- return binary_matches_3(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
+ return binary_matches(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
}
@@ -1882,9 +1898,9 @@ static BIF_RETTYPE do_longest_common(Process *p, Eterm list, int direction)
cd = (CommonData *) ERTS_MAGIC_BIN_DATA(mb);
l = list;
while (is_list(l)) {
- Uint bitoffs;
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
Uint bitsize;
- Uint offset;
+ ERTS_DECLARE_DUMMY(Uint offset);
Eterm real_bin;
ProcBin* pb;
@@ -2361,7 +2377,7 @@ static BIF_RETTYPE do_binary_copy(Process *p, Eterm bin, Eterm en)
{
Uint n;
byte *bytes;
- Uint bit_offs;
+ ERTS_DECLARE_DUMMY(Uint bit_offs);
Uint bit_size;
size_t size;
Uint reds = get_reds(p, BINARY_COPY_LOOP_FACTOR);
@@ -2390,9 +2406,9 @@ static BIF_RETTYPE do_binary_copy(Process *p, Eterm bin, Eterm en)
if ((target_size - size) >= reds) {
Eterm orig;
- Uint offset;
- Uint bit_offset;
- Uint bit_size;
+ ERTS_DECLARE_DUMMY(Uint offset);
+ ERTS_DECLARE_DUMMY(Uint bit_offset);
+ ERTS_DECLARE_DUMMY(Uint bit_size);
CopyBinState *cbs;
Eterm *hp;
Eterm trap_term;
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index d714eacd06..c338ee1c4b 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2012. All Rights Reserved.
*
* The 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,7 @@
#include "big.h"
#include "dist.h"
#include "erl_version.h"
+#include "dtrace-wrapper.h"
#ifdef ERTS_SMP
#define DDLL_SMP 1
@@ -142,9 +143,11 @@ static void ddll_no_more_references(void *vdh);
* really load and add as LOADED {ok,loaded} {ok,pending_driver}
* {error, permanent} {error,load_error()}
*/
-BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
- Eterm name_term, Eterm options)
+BIF_RETTYPE erl_ddll_try_load_3(BIF_ALIST_3)
{
+ Eterm path_term = BIF_ARG_1;
+ Eterm name_term = BIF_ARG_2;
+ Eterm options = BIF_ARG_3;
char *path = NULL;
Uint path_len;
char *name = NULL;
@@ -236,7 +239,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
sys_strcpy(path+path_len,name);
#if DDLL_SMP
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
lock_drv_list();
#endif
if ((drv = lookup_driver(name)) != NULL) {
@@ -247,7 +250,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
} else {
dh = drv->handle;
if (dh->status == ERL_DE_OK) {
- int is_last = is_last_user(dh,p);
+ int is_last = is_last_user(dh, BIF_P);
if (reload == 1 && !is_last) {
/*Want reload if no other users,
but there are others...*/
@@ -261,7 +264,8 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
soft_error_term = am_inconsistent;
goto soft_error;
}
- if ((old = find_proc_entry(dh, p, ERL_DE_PROC_LOADED)) ==
+ if ((old = find_proc_entry(dh, BIF_P,
+ ERL_DE_PROC_LOADED)) ==
NULL) {
soft_error_term = am_not_loaded_by_this_process;
goto soft_error;
@@ -272,7 +276,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
}
/* Reload requested and granted */
dereference_all_processes(dh);
- set_driver_reloading(dh, p, path, name, flags);
+ set_driver_reloading(dh, BIF_P, path, name, flags);
if (dh->flags & ERL_DE_FL_KILL_PORTS) {
kill_ports = 1;
}
@@ -286,7 +290,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
soft_error_term = am_inconsistent;
goto soft_error;
}
- add_proc_loaded(dh,p);
+ add_proc_loaded(dh, BIF_P);
erts_ddll_reference_driver(dh);
monitor = 0;
ok_term = mkatom("already_loaded");
@@ -308,7 +312,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
notify_all(dh, drv->name,
ERL_DE_PROC_AWAIT_UNLOAD, am_UP,
am_unload_cancelled);
- add_proc_loaded(dh,p);
+ add_proc_loaded(dh, BIF_P);
erts_ddll_reference_driver(dh);
monitor = 0;
ok_term = mkatom("already_loaded");
@@ -325,7 +329,8 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
goto soft_error;
}
/* Load of granted unload... */
- add_proc_loaded_deref(dh,p); /* Dont reference, will happen after reload */
+ /* Don't reference, will happen after reload */
+ add_proc_loaded_deref(dh, BIF_P);
++monitor;
ok_term = am_pending_driver;
} else { /* ERL_DE_PERMANENT */
@@ -345,7 +350,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
goto soft_error;
} else {
dh->flags = flags;
- add_proc_loaded(dh,p);
+ add_proc_loaded(dh, BIF_P);
first_ddll_reference(dh);
monitor = 0;
ok_term = mkatom("loaded");
@@ -397,18 +402,18 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
#if DDLL_SMP
erts_ddll_reference_driver(dh);
unlock_drv_list();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
lock_drv_list();
erts_ddll_dereference_driver(dh);
#endif
- p->flags |= F_USING_DDLL;
+ BIF_P->flags |= F_USING_DDLL;
if (monitor) {
- Eterm mref = add_monitor(p, dh, ERL_DE_PROC_AWAIT_LOAD);
- hp = HAlloc(p,4);
+ Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_LOAD);
+ hp = HAlloc(BIF_P, 4);
t = TUPLE3(hp, am_ok, ok_term, mref);
} else {
- hp = HAlloc(p,3);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_ok, ok_term);
}
#if DDLL_SMP
@@ -416,33 +421,33 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
#endif
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
BIF_RET(t);
soft_error:
#if DDLL_SMP
unlock_drv_list();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
#endif
if (do_build_load_error) {
- soft_error_term = build_load_error(p, build_this_load_error);
+ soft_error_term = build_load_error(BIF_P, build_this_load_error);
}
- hp = HAlloc(p,3);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_error, soft_error_term);
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
BIF_RET(t);
error:
assert_drv_list_not_locked();
- ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
if (path != NULL) {
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
}
if (name != NULL) {
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
}
- BIF_ERROR(p,BADARG);
+ BIF_ERROR(BIF_P, BADARG);
}
/*
@@ -481,8 +486,10 @@ BIF_RETTYPE erl_ddll_try_load_3(Process *p, Eterm path_term,
any AWAIT_LOAD-waiters with {'DOWN', ref(), driver, name(), load_cancelled}
If the driver made itself permanent, {'UP', ref(), driver, name(), permanent}
*/
-Eterm erl_ddll_try_unload_2(Process *p, Eterm name_term, Eterm options)
+Eterm erl_ddll_try_unload_2(BIF_ALIST_2)
{
+ Eterm name_term = BIF_ARG_1;
+ Eterm options = BIF_ARG_2;
char *name = NULL;
Eterm ok_term = NIL;
Eterm soft_error_term = NIL;
@@ -495,7 +502,7 @@ Eterm erl_ddll_try_unload_2(Process *p, Eterm name_term, Eterm options)
Eterm l;
int kill_ports = 0;
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
for(l = options; is_list(l); l = CDR(list_val(l))) {
Eterm opt = CAR(list_val(l));
@@ -548,7 +555,7 @@ Eterm erl_ddll_try_unload_2(Process *p, Eterm name_term, Eterm options)
if (dh->flags & ERL_DE_FL_KILL_PORTS) {
kill_ports = 1;
}
- if ((pe = find_proc_entry(dh, p, ERL_DE_PROC_LOADED)) == NULL) {
+ if ((pe = find_proc_entry(dh, BIF_P, ERL_DE_PROC_LOADED)) == NULL) {
if (num_procs(dh, ERL_DE_PROC_LOADED) > 0) {
soft_error_term = am_not_loaded_by_this_process;
goto soft_error;
@@ -624,22 +631,22 @@ done:
#if DDLL_SMP
erts_ddll_reference_driver(dh);
unlock_drv_list();
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
lock_drv_list();
erts_ddll_dereference_driver(dh);
#endif
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- p->flags |= F_USING_DDLL;
+ BIF_P->flags |= F_USING_DDLL;
if (monitor > 0) {
- Eterm mref = add_monitor(p, dh, ERL_DE_PROC_AWAIT_UNLOAD);
- hp = HAlloc(p,4);
+ Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_UNLOAD);
+ hp = HAlloc(BIF_P, 4);
t = TUPLE3(hp, am_ok, ok_term, mref);
} else {
- hp = HAlloc(p,3);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_ok, ok_term);
}
if (kill_ports > 1) {
- ERTS_BIF_CHK_EXITED(p); /* May be exited by port killing */
+ ERTS_BIF_CHK_EXITED(BIF_P); /* May be exited by port killing */
}
#if DDLL_SMP
unlock_drv_list();
@@ -651,8 +658,8 @@ soft_error:
unlock_drv_list();
#endif
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
- hp = HAlloc(p,3);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ hp = HAlloc(BIF_P, 3);
t = TUPLE2(hp, am_error, soft_error_term);
BIF_RET(t);
@@ -661,21 +668,21 @@ soft_error:
if (name != NULL) {
erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
}
- erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
- BIF_ERROR(p,BADARG);
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ BIF_ERROR(BIF_P, BADARG);
}
/*
* A shadow of the "real" demonitor BIF
*/
-BIF_RETTYPE erl_ddll_demonitor_1(Process *p, Eterm ref)
+BIF_RETTYPE erl_ddll_demonitor_1(BIF_ALIST_1)
{
- if (is_not_internal_ref(ref)) {
- BIF_ERROR(p, BADARG);
+ if (is_not_internal_ref(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P, BADARG);
}
- if (p->flags & F_USING_DDLL) {
- erts_ddll_remove_monitor(p, ref, ERTS_PROC_LOCK_MAIN);
+ if (BIF_P->flags & F_USING_DDLL) {
+ erts_ddll_remove_monitor(BIF_P, BIF_ARG_1, ERTS_PROC_LOCK_MAIN);
}
BIF_RET(am_true);
}
@@ -683,18 +690,18 @@ BIF_RETTYPE erl_ddll_demonitor_1(Process *p, Eterm ref)
/*
* A shadow of the "real" monitor BIF
*/
-BIF_RETTYPE erl_ddll_monitor_2(Process *p, Eterm dr, Eterm what)
+BIF_RETTYPE erl_ddll_monitor_2(BIF_ALIST_2)
{
- if (dr != am_driver) {
- BIF_ERROR(p,BADARG);
+ if (BIF_ARG_1 != am_driver) {
+ BIF_ERROR(BIF_P, BADARG);
}
- return erts_ddll_monitor_driver(p, what, ERTS_PROC_LOCK_MAIN);
+ return erts_ddll_monitor_driver(BIF_P, BIF_ARG_2, ERTS_PROC_LOCK_MAIN);
}
/*
* Return list of loaded drivers {ok,[string()]}
*/
-Eterm erl_ddll_loaded_drivers_0(Process *p)
+BIF_RETTYPE erl_ddll_loaded_drivers_0(BIF_ALIST_0)
{
Eterm *hp;
int need = 3;
@@ -706,7 +713,7 @@ Eterm erl_ddll_loaded_drivers_0(Process *p)
for (drv = driver_list; drv; drv = drv->next) {
need += sys_strlen(drv->name)*2+2;
}
- hp = HAlloc(p,need);
+ hp = HAlloc(BIF_P, need);
for (drv = driver_list; drv; drv = drv->next) {
Eterm l;
l = buf_to_intlist(&hp, drv->name, sys_strlen(drv->name), NIL);
@@ -726,8 +733,11 @@ Eterm erl_ddll_loaded_drivers_0(Process *p)
* item is processes, driver_options, port_count, linked_in_driver,
* permanent, awaiting_load, awaiting_unload
*/
-Eterm erl_ddll_info_2(Process *p, Eterm name_term, Eterm item)
+BIF_RETTYPE erl_ddll_info_2(BIF_ALIST_2)
{
+ Process *p = BIF_P;
+ Eterm name_term = BIF_ARG_1;
+ Eterm item = BIF_ARG_2;
char *name = NULL;
Eterm res = NIL;
erts_driver_t *drv;
@@ -850,8 +860,10 @@ Eterm erl_ddll_info_2(Process *p, Eterm name_term, Eterm item)
* Backend for erl_ddll:format_error, handles all "soft" errors returned by builtins,
* possibly by calling the system specific error handler
*/
-Eterm erl_ddll_format_error_int_1(Process *p, Eterm code_term)
+BIF_RETTYPE erl_ddll_format_error_int_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm code_term = BIF_ARG_1;
char *errstring = NULL;
int errint;
int len;
@@ -1558,49 +1570,34 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
if ((res = erts_sys_ddll_load_driver_init(dh->handle,
&init_handle)) != ERL_DE_NO_ERROR) {
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_NO_INIT;
+ res = ERL_DE_LOAD_ERROR_NO_INIT;
+ goto error;
}
dp = erts_sys_ddll_call_init(init_handle);
if (dp == NULL) {
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_FAILED_INIT;
+ res = ERL_DE_LOAD_ERROR_FAILED_INIT;
+ goto error;
}
switch (dp->extended_marker) {
- case 0:
- /*
- * This may be an old driver that has been recompiled. If so,
- * at least the fields that existed in extended driver version
- * 1.0 should be zero. If not, a it is a bad driver. We cannot
- * be completely certain that this is a valid driver but this is
- * the best we can do with old drivers...
- */
- if (dp->major_version != 0
- || dp->minor_version != 0
- || dp->driver_flags != 0
- || dp->handle2 != NULL
- || dp->process_exit != NULL) {
- /* Old driver; needs to be recompiled... */
- return ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
- }
- break;
case ERL_DRV_EXTENDED_MARKER:
if (ERL_DRV_EXTENDED_MAJOR_VERSION != dp->major_version
|| ERL_DRV_EXTENDED_MINOR_VERSION < dp->minor_version) {
/* Incompatible driver version */
- return ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ goto error;
}
break;
default:
/* Old driver; needs to be recompiled... */
- return ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
+ goto error;
}
if (strcmp(name, dp->driver_name) != 0) {
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_BAD_NAME;
+ res = ERL_DE_LOAD_ERROR_BAD_NAME;
+ goto error;
}
erts_smp_atomic_init_nob(&(dh->refc), (erts_aint_t) 0);
dh->port_count = 0;
@@ -1615,11 +1612,14 @@ static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
*/
erts_free(ERTS_ALC_T_DDLL_HANDLE, dh->full_path);
dh->full_path = NULL;
- erts_sys_ddll_close(dh->handle);
- return ERL_DE_LOAD_ERROR_FAILED_INIT;
+ res = ERL_DE_LOAD_ERROR_FAILED_INIT;
+ goto error;
}
-
return ERL_DE_NO_ERROR;
+
+error:
+ erts_sys_ddll_close(dh->handle);
+ return res;
}
static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name)
@@ -1648,6 +1648,7 @@ static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name)
diver_list lock here!*/
if (q->finish) {
int fpe_was_unmasked = erts_block_fpe();
+ DTRACE1(driver_finish, q->name);
(*(q->finish))();
erts_unblock_fpe(fpe_was_unmasked);
}
@@ -1761,7 +1762,11 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type,
hp += REF_THING_SIZE;
mess = TUPLE5(hp,type,r,am_driver,driver_name,tag);
}
- erts_queue_message(proc, &rp_locks, bp, mess, am_undefined);
+ erts_queue_message(proc, &rp_locks, bp, mess, am_undefined
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(proc, rp_locks);
ERTS_SMP_CHK_NO_PROC_LOCKS;
}
diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c
index 01e6977a2c..a715756c15 100644
--- a/erts/emulator/beam/erl_bif_guard.c
+++ b/erts/emulator/beam/erl_bif_guard.c
@@ -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
@@ -52,7 +52,7 @@ BIF_RETTYPE abs_1(BIF_ALIST_1)
/* integer arguments */
if (is_small(BIF_ARG_1)) {
i0 = signed_val(BIF_ARG_1);
- i = labs(i0);
+ i = ERTS_SMALL_ABS(i0);
if (i0 == MIN_SMALL) {
hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE);
BIF_RET(uint_to_big(i, hp));
@@ -467,7 +467,7 @@ Eterm erts_gc_abs_1(Process* p, Eterm* reg, Uint live)
/* integer arguments */
if (is_small(arg)) {
i0 = signed_val(arg);
- i = labs(i0);
+ i = ERTS_SMALL_ABS(i0);
if (i0 == MIN_SMALL) {
if (ERTS_NEED_GC(p, BIG_UINT_HEAP_SIZE)) {
erts_garbage_collect(p, BIG_UINT_HEAP_SIZE, reg, live+1);
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index e17325b64f..45dc5fb11c 100644..100755
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2012. All Rights Reserved.
*
* The 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,6 @@
#include "erl_vm.h"
#include "global.h"
#include "erl_process.h"
-#include "erl_nmgc.h"
#include "error.h"
#include "erl_driver.h"
#include "bif.h"
@@ -39,6 +38,8 @@
#include "dist.h"
#include "erl_gc.h"
#include "erl_cpu_topology.h"
+#include "erl_async.h"
+#include "erl_thr_progress.h"
#ifdef HIPE
#include "hipe_arch.h"
#endif
@@ -52,6 +53,11 @@
#include <valgrind/memcheck.h>
#endif
+static Export* alloc_info_trap = NULL;
+static Export* alloc_sizes_trap = NULL;
+
+static Export *gather_sched_wall_time_res_trap;
+
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
/* Keep erts_system_version as a global variable for easy access from a core */
@@ -73,7 +79,6 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
#ifdef ERTS_SMP
" [smp:%beu:%beu]"
#endif
- " [rq:%beu]"
#ifdef USE_THREADS
" [async-threads:%d]"
#endif
@@ -83,12 +88,6 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
#ifdef ERTS_ENABLE_KERNEL_POLL
" [kernel-poll:%s]"
#endif
-#ifdef HYBRID
- " [hybrid heap]"
-#endif
-#ifdef INCREMENTAL
- " [incremental GC]"
-#endif
#ifdef ET_DEBUG
#if ET_DEBUG
" [type-assertions]"
@@ -109,6 +108,12 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
#ifdef VALGRIND
" [valgrind-compiled]"
#endif
+#ifdef USE_DTRACE
+ " [dtrace]"
+#endif
+#ifdef USE_SYSTEMTAP
+ " [systemtap]"
+#endif
"\n");
#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -119,6 +124,12 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
# define PERFMON_GETPCR _IOR('P', 2, unsigned long long)
#endif
+/* Cached, pre-built {OsType,OsFlavor} and {Major,Minor,Build} tuples */
+static Eterm os_type_tuple;
+static Eterm os_version_tuple;
+
+static BIF_RETTYPE port_info(Process* p, Eterm portid, Eterm item);
+
static Eterm
current_function(Process* p, Process* rp, Eterm** hpp, int full_info);
static Eterm current_stacktrace(Process* p, Process* rp, Eterm** hpp);
@@ -290,9 +301,7 @@ erts_print_system_version(int to, void *arg, Process *c_p)
#endif
return erts_print(to, arg, erts_system_version
#ifdef ERTS_SMP
- , total, online, erts_no_run_queues
-#else
- , 1
+ , total, online
#endif
#ifdef USE_THREADS
, erts_async_max_threads
@@ -560,9 +569,6 @@ static Eterm pi_args[] = {
am_min_bin_vheap_size,
am_current_location,
am_current_stacktrace,
-#ifdef HYBRID
- am_message_binary
-#endif
};
#define ERTS_PI_ARGS ((int) (sizeof(pi_args)/sizeof(Eterm)))
@@ -610,9 +616,6 @@ pi_arg2ix(Eterm arg)
case am_min_bin_vheap_size: return 28;
case am_current_location: return 29;
case am_current_stacktrace: return 30;
-#ifdef HYBRID
- case am_message_binary: return 31;
-#endif
default: return -1;
}
}
@@ -1065,12 +1068,8 @@ process_info_aux(Process *BIF_P,
if (rp != BIF_P) {
Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
if (is_value(msg)) {
- mq[i].copy_struct_size = (is_immed(msg)
-#ifdef HYBRID
- || NO_COPY(msg)
-#endif
- ? 0
- : size_object(msg));
+ mq[i].copy_struct_size = (is_immed(msg)? 0 :
+ size_object(msg));
}
else if (mq[i].msgp->data.attached) {
mq[i].copy_struct_size
@@ -1510,16 +1509,6 @@ process_info_aux(Process *BIF_P,
break;
}
-#ifdef HYBRID
- case am_message_binary: {
- Uint sz = 3;
- (void) bld_bin_list(NULL, &sz, erts_global_offheap.mso);
- hp = HAlloc(BIF_P, sz);
- res = bld_bin_list(&hp, NULL, erts_global_offheap.mso);
- break;
- }
-#endif
-
case am_sequential_trace_token:
res = copy_object(rp->seq_trace_token, BIF_P);
hp = HAlloc(BIF_P, 3);
@@ -1708,7 +1697,7 @@ static int check_if_xml(void)
{
char buf[1];
size_t bufsz = sizeof(buf);
- return erts_sys_getenv("VALGRIND_LOG_XML", buf, &bufsz) >= 0;
+ return erts_sys_getenv_raw("VALGRIND_LOG_XML", buf, &bufsz) >= 0;
}
#else
#define check_if_xml() 0
@@ -1728,9 +1717,19 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
sel = *tp++;
- if (sel == am_allocator_sizes && arity == 2) {
- return erts_allocator_info_term(BIF_P, *tp, 1);
- } else if (sel == am_wordsize && arity == 2) {
+ if (sel == am_allocator_sizes) {
+ switch (arity) {
+ case 2:
+ ERTS_BIF_PREP_TRAP1(ret, alloc_sizes_trap, BIF_P, *tp);
+ return ret;
+ case 3:
+ if (erts_request_alloc_info(BIF_P, tp[0], tp[1], 1))
+ return am_true;
+ default:
+ goto badarg;
+ }
+ }
+ else if (sel == am_wordsize && arity == 2) {
if (tp[0] == am_internal) {
return make_small(sizeof(Eterm));
}
@@ -1777,8 +1776,17 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
}
else
goto badarg;
- } else if (sel == am_allocator && arity == 2) {
- return erts_allocator_info_term(BIF_P, *tp, 0);
+ } else if (sel == am_allocator) {
+ switch (arity) {
+ case 2:
+ ERTS_BIF_PREP_TRAP1(ret, alloc_info_trap, BIF_P, *tp);
+ return ret;
+ case 3:
+ if (erts_request_alloc_info(BIF_P, tp[0], tp[1], 0))
+ return am_true;
+ default:
+ goto badarg;
+ }
} else if (ERTS_IS_ATOM_STR("internal_cpu_topology", sel) && arity == 2) {
return erts_get_cpu_topology_term(BIF_P, *tp);
} else if (ERTS_IS_ATOM_STR("cpu_topology", sel) && arity == 2) {
@@ -2100,7 +2108,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(am_undefined);
#endif
} else if (BIF_ARG_1 == am_trace_control_word) {
- BIF_RET(db_get_trace_control_word_0(BIF_P));
+ BIF_RET(db_get_trace_control_word(BIF_P));
} else if (ERTS_IS_ATOM_STR("ets_realloc_moves", BIF_ARG_1)) {
BIF_RET((erts_ets_realloc_always_moves) ? am_true : am_false);
} else if (ERTS_IS_ATOM_STR("ets_always_compress", BIF_ARG_1)) {
@@ -2160,7 +2168,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
/* Need to be the only thread running... */
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (BIF_ARG_1 == am_info)
info(ERTS_PRINT_DSBUF, (void *) dsbufp);
@@ -2171,7 +2179,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
else
distribution_info(ERTS_PRINT_DSBUF, (void *) dsbufp);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
ASSERT(dsbufp && dsbufp->str);
@@ -2183,7 +2191,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
i = 0;
/* Need to be the only thread running... */
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
for (dep = erts_visible_dist_entries; dep; dep = dep->next)
++i;
for (dep = erts_hidden_dist_entries; dep; dep = dep->next)
@@ -2206,7 +2214,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
res = CONS(hp, tpl, res);
hp += 2;
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
} else if (BIF_ARG_1 == am_system_version) {
@@ -2227,16 +2235,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
return erts_instr_get_type_info(BIF_P);
}
else if (BIF_ARG_1 == am_os_type) {
- Eterm type = am_atom_put(os_type, strlen(os_type));
- Eterm flav, tup;
- char *buf = erts_alloc(ERTS_ALC_T_TMP, 1024); /* More than enough */
-
- os_flavor(buf, 1024);
- flav = am_atom_put(buf, strlen(buf));
- hp = HAlloc(BIF_P, 3);
- tup = TUPLE2(hp, type, flav);
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
- BIF_RET(tup);
+ BIF_RET(os_type_tuple);
}
else if (BIF_ARG_1 == am_allocator) {
BIF_RET(erts_allocator_options((void *) BIF_P));
@@ -2262,16 +2261,7 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(am_false);
}
else if (BIF_ARG_1 == am_os_version) {
- int major, minor, build;
- Eterm tup;
-
- os_version(&major, &minor, &build);
- hp = HAlloc(BIF_P, 4);
- tup = TUPLE3(hp,
- make_small(major),
- make_small(minor),
- make_small(build));
- BIF_RET(tup);
+ BIF_RET(os_version_tuple);
}
else if (BIF_ARG_1 == am_version) {
int n = strlen(ERLANG_VERSION);
@@ -2337,36 +2327,8 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
#endif
} else if (BIF_ARG_1 == am_heap_sizes) {
return erts_heap_sizes(BIF_P);
- } else if (BIF_ARG_1 == am_global_heaps_size) {
-#ifdef HYBRID
- Uint hsz = 0;
- Uint sz = 0;
-
- sz += global_heap_sz;
-#ifdef INCREMENTAL
- /* The size of the old generation is a bit hard to define here...
- * The amount of live data in the last collection perhaps..? */
- sz = 0;
-#else
- if (global_old_hend && global_old_heap)
- sz += global_old_hend - global_old_heap;
-#endif
-
- sz *= sizeof(Eterm);
-
- (void) erts_bld_uint(NULL, &hsz, sz);
- hp = hsz ? HAlloc(BIF_P, hsz) : NULL;
- res = erts_bld_uint(&hp, NULL, sz);
-#else
- res = make_small(0);
-#endif
- return res;
} else if (BIF_ARG_1 == am_heap_type) {
-#if defined(HYBRID)
- return am_hybrid;
-#else
return am_private;
-#endif
} else if (ERTS_IS_ATOM_STR("cpu_topology", BIF_ARG_1)) {
res = erts_get_cpu_topology_term(BIF_P, am_used);
BIF_TRAP1(erts_format_cpu_topology_trap, BIF_P, res);
@@ -2641,8 +2603,12 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
res = erts_bld_uint(&hp, NULL, erts_dist_buf_busy_limit);
BIF_RET(res);
} else if (ERTS_IS_ATOM_STR("print_ethread_info", BIF_ARG_1)) {
+#if defined(ETHR_NATIVE_ATOMIC32_IMPL) \
+ || defined(ETHR_NATIVE_ATOMIC64_IMPL) \
+ || defined(ETHR_NATIVE_DW_ATOMIC_IMPL)
int i;
char **str;
+#endif
#ifdef ETHR_NATIVE_ATOMIC32_IMPL
erts_printf("32-bit native atomics: %s\n",
ETHR_NATIVE_ATOMIC32_IMPL);
@@ -2705,20 +2671,47 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
#endif
BIF_RET(am_true);
}
+ else if (ERTS_IS_ATOM_STR("dynamic_trace", BIF_ARG_1)) {
+#if defined(USE_DTRACE)
+ DECL_AM(dtrace);
+ BIF_RET(AM_dtrace);
+#elif defined(USE_SYSTEMTAP)
+ DECL_AM(systemtap);
+ BIF_RET(AM_systemtap);
+#else
+ BIF_RET(am_none);
+#endif
+ }
+ else if (ERTS_IS_ATOM_STR("dynamic_trace_probes", BIF_ARG_1)) {
+#if defined(USE_VM_PROBES)
+ BIF_RET(am_true);
+#else
+ BIF_RET(am_false);
+#endif
+ }
+#ifdef ERTS_SMP
+ else if (ERTS_IS_ATOM_STR("thread_progress", BIF_ARG_1)) {
+ erts_thr_progress_dbg_print_state();
+ BIF_RET(am_true);
+ }
+#endif
BIF_ERROR(BIF_P, BADARG);
}
-Eterm
-port_info_1(Process* p, Eterm pid)
+BIF_RETTYPE
+port_info_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm pid = BIF_ARG_1;
static Eterm keys[] = {
am_name,
am_links,
am_id,
am_connected,
am_input,
- am_output
+ am_output,
+ am_os_pid
};
Eterm items[ASIZE(keys)];
Eterm result = NIL;
@@ -2734,7 +2727,7 @@ port_info_1(Process* p, Eterm pid)
for (i = 0; i < ASIZE(keys); i++) {
Eterm item;
- item = port_info_2(p, pid, keys[i]);
+ item = port_info(p, pid, keys[i]);
if (is_non_value(item)) {
return THE_NON_VALUE;
}
@@ -2743,7 +2736,7 @@ port_info_1(Process* p, Eterm pid)
}
items[i] = item;
}
- reg_name = port_info_2(p, pid, am_registered_name);
+ reg_name = port_info(p, pid, am_registered_name);
/*
* Build the resulting list.
@@ -2775,28 +2768,32 @@ port_info_1(Process* p, Eterm pid)
** name String
** input Number of bytes input from port program
** output Number of bytes output to the port program
+** os_pid The child's process ID
*/
BIF_RETTYPE port_info_2(BIF_ALIST_2)
{
+ return port_info(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+static BIF_RETTYPE port_info(Process* p, Eterm portid, Eterm item)
+{
BIF_RETTYPE ret;
- Eterm portid = BIF_ARG_1;
Port *prt;
- Eterm item = BIF_ARG_2;
Eterm res;
Eterm* hp;
int count;
if (is_internal_port(portid))
- prt = erts_id2port(portid, BIF_P, ERTS_PROC_LOCK_MAIN);
+ prt = erts_id2port(portid, p, ERTS_PROC_LOCK_MAIN);
else if (is_atom(portid))
- erts_whereis_name(BIF_P, ERTS_PROC_LOCK_MAIN,
+ erts_whereis_name(p, ERTS_PROC_LOCK_MAIN,
portid, NULL, 0, 0, &prt);
else if (is_external_port(portid)
&& external_port_dist_entry(portid) == erts_this_dist_entry)
BIF_RET(am_undefined);
else {
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
if (!prt) {
@@ -2804,7 +2801,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
}
if (item == am_id) {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = make_small(internal_port_number(portid));
}
else if (item == am_links) {
@@ -2816,10 +2813,10 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
erts_doforall_links(prt->nlinks, &collect_one_link, &mic);
- hp = HAlloc(BIF_P, 3 + mic.sz);
+ hp = HAlloc(p, 3 + mic.sz);
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
- item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(p), mic.mi[i].entity);
res = CONS(hp, item, res);
hp += 2;
}
@@ -2835,11 +2832,11 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
erts_doforall_monitors(prt->monitors, &collect_one_origin_monitor, &mic);
- hp = HAlloc(BIF_P, 3 + mic.sz);
+ hp = HAlloc(p, 3 + mic.sz);
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
Eterm t;
- item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(p), mic.mi[i].entity);
t = TUPLE2(hp, am_process, item);
hp += 3;
res = CONS(hp, t, res);
@@ -2851,27 +2848,39 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
else if (item == am_name) {
count = sys_strlen(prt->name);
- hp = HAlloc(BIF_P, 3 + 2*count);
+ hp = HAlloc(p, 3 + 2*count);
res = buf_to_intlist(&hp, prt->name, count, NIL);
}
else if (item == am_connected) {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = prt->connected; /* internal pid */
}
else if (item == am_input) {
Uint hsz = 3;
Uint n = prt->bytes_in;
(void) erts_bld_uint(NULL, &hsz, n);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, n);
}
else if (item == am_output) {
Uint hsz = 3;
Uint n = prt->bytes_out;
(void) erts_bld_uint(NULL, &hsz, n);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, n);
}
+ else if (item == am_os_pid) {
+ if (prt->os_pid >= 0) {
+ Uint hsz = 3;
+ UWord n = prt->os_pid;
+ (void) erts_bld_uword(NULL, &hsz, n);
+ hp = HAlloc(p, hsz);
+ res = erts_bld_uword(&hp, NULL, n);
+ } else {
+ hp = HAlloc(p, 3);
+ res = am_undefined;
+ }
+ }
else if (item == am_registered_name) {
RegProc *reg;
reg = prt->reg;
@@ -2879,7 +2888,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
ERTS_BIF_PREP_RET(ret, NIL);
goto done;
} else {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = reg->name;
}
}
@@ -2891,7 +2900,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
Uint size = 0;
ErlHeapFragment* bp;
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
erts_doforall_links(prt->nlinks, &one_link_size, &size);
@@ -2908,18 +2917,18 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
hard to retrieve... */
(void) erts_bld_uint(NULL, &hsz, size);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, size);
}
else if (item == am_queue_size) {
Uint ioq_size = erts_port_ioq_size(prt);
Uint hsz = 3;
(void) erts_bld_uint(NULL, &hsz, ioq_size);
- hp = HAlloc(BIF_P, hsz);
+ hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, ioq_size);
}
else if (ERTS_IS_ATOM_STR("locking", item)) {
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
#ifndef ERTS_SMP
res = am_false;
#else
@@ -2938,7 +2947,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
#endif
}
else {
- ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(ret, p, BADARG);
goto done;
}
@@ -2952,9 +2961,12 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
}
-Eterm
-fun_info_2(Process* p, Eterm fun, Eterm what)
+BIF_RETTYPE
+fun_info_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm fun = BIF_ARG_1;
+ Eterm what = BIF_ARG_2;
Eterm* hp;
Eterm val;
@@ -3153,7 +3165,12 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
Eterm res;
Eterm* hp;
- if (BIF_ARG_1 == am_context_switches) {
+ if (BIF_ARG_1 == am_scheduler_wall_time) {
+ res = erts_sched_wall_time_request(BIF_P, 0, 0);
+ if (is_non_value(res))
+ BIF_RET(am_undefined);
+ BIF_TRAP1(gather_sched_wall_time_res_trap, BIF_P, res);
+ } else if (BIF_ARG_1 == am_context_switches) {
Eterm cs = erts_make_integer(erts_get_total_context_switches(), BIF_P);
hp = HAlloc(BIF_P, 3);
res = TUPLE2(hp, cs, SMALL_ZERO);
@@ -3200,7 +3217,7 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
res = TUPLE2(hp, b1, b2);
BIF_RET(res);
} else if (BIF_ARG_1 == am_runtime) {
- unsigned long u1, u2, dummy;
+ UWord u1, u2, dummy;
Eterm b1, b2;
elapsed_time_both(&u1,&dummy,&u2,&dummy);
b1 = erts_make_integer(u1,BIF_P);
@@ -3265,26 +3282,6 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
-BIF_RETTYPE memory_0(BIF_ALIST_0)
-{
- BIF_RETTYPE res = erts_memory(NULL, NULL, BIF_P, THE_NON_VALUE);
- switch (res) {
- case am_badarg: BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR); /* never... */
- case am_notsup: BIF_ERROR(BIF_P, EXC_NOTSUP);
- default: BIF_RET(res);
- }
-}
-
-BIF_RETTYPE memory_1(BIF_ALIST_1)
-{
- BIF_RETTYPE res = erts_memory(NULL, NULL, BIF_P, BIF_ARG_1);
- switch (res) {
- case am_badarg: BIF_ERROR(BIF_P, BADARG);
- case am_notsup: BIF_ERROR(BIF_P, EXC_NOTSUP);
- default: BIF_RET(res);
- }
-}
-
BIF_RETTYPE error_logger_warning_map_0(BIF_ALIST_0)
{
BIF_RET(erts_error_logger_warnings);
@@ -3386,6 +3383,15 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
BIF_RET(am_false);
#endif
}
+ else if (ERTS_IS_ATOM_STR("memory", BIF_ARG_1)) {
+ Eterm res;
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_thr_progress_block();
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ res = erts_memory(NULL, NULL, BIF_P, THE_NON_VALUE);
+ erts_smp_thr_progress_unblock();
+ BIF_RET(res);
+ }
}
else if (is_tuple(BIF_ARG_1)) {
Eterm* tp = tuple_val(BIF_ARG_1);
@@ -3588,6 +3594,7 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
static erts_smp_atomic_t hipe_test_reschedule_flag;
+
BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
{
/*
@@ -3638,10 +3645,10 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
if (ms > 0) {
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (block)
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
while (erts_milli_sleep((long) ms) != 0);
if (block)
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
}
BIF_RET(am_true);
@@ -3851,16 +3858,23 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
}
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
old_use_opt = !erts_disable_proc_not_running_opt;
erts_disable_proc_not_running_opt = !use_opt;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(old_use_opt ? am_true : am_false);
#else
BIF_ERROR(BIF_P, EXC_NOTSUP);
#endif
}
+ else if (ERTS_IS_ATOM_STR("wait", BIF_ARG_1)) {
+ if (ERTS_IS_ATOM_STR("deallocations", BIF_ARG_2)) {
+ if (erts_debug_wait_deallocations(BIF_P)) {
+ ERTS_BIF_YIELD_RETURN(BIF_P, am_ok);
+ }
+ }
+ }
}
BIF_ERROR(BIF_P, BADARG);
@@ -4019,7 +4033,7 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
Eterm* hp;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_SUSPEND);
data = erts_lcnt_get_data();
@@ -4037,17 +4051,17 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
erts_lcnt_clear_rt_opt(ERTS_LCNT_OPT_SUSPEND);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(res);
} else if (BIF_ARG_1 == am_clear) {
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_lcnt_clear_counters();
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_ok);
@@ -4055,48 +4069,52 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
Eterm* tp = tuple_val(BIF_ARG_1);
switch (arityval(tp[0])) {
- case 2:
+ case 2: {
+ int opt = 0;
+ int val = 0;
if (ERTS_IS_ATOM_STR("copy_save", tp[1])) {
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
- if (tp[2] == am_true) {
-
- res = erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_COPYSAVE) ? am_true : am_false;
-
- } else if (tp[2] == am_false) {
-
- res = erts_lcnt_clear_rt_opt(ERTS_LCNT_OPT_COPYSAVE) ? am_true : am_false;
-
- } else {
- erts_smp_release_system();
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
- BIF_ERROR(BIF_P, BADARG);
- }
- erts_smp_release_system();
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
- BIF_RET(res);
-
+ opt = ERTS_LCNT_OPT_COPYSAVE;
} else if (ERTS_IS_ATOM_STR("process_locks", tp[1])) {
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
- if (tp[2] == am_true) {
-
- res = erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_PROCLOCK) ? am_true : am_false;
-
- } else if (tp[2] == am_false) {
-
- res = erts_lcnt_set_rt_opt(ERTS_LCNT_OPT_PROCLOCK) ? am_true : am_false;
+ opt = ERTS_LCNT_OPT_PROCLOCK;
+ } else if (ERTS_IS_ATOM_STR("port_locks", tp[1])) {
+ opt = ERTS_LCNT_OPT_PORTLOCK;
+ } else if (ERTS_IS_ATOM_STR("suspend", tp[1])) {
+ opt = ERTS_LCNT_OPT_SUSPEND;
+ } else if (ERTS_IS_ATOM_STR("location", tp[1])) {
+ opt = ERTS_LCNT_OPT_LOCATION;
+ } else {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ if (tp[2] == am_true) {
+ val = 1;
+ } else if (tp[2] == am_false) {
+ val = 0;
+ } else {
+ BIF_ERROR(BIF_P, BADARG);
+ }
- } else {
- erts_smp_release_system();
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
- BIF_ERROR(BIF_P, BADARG);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_thr_progress_block();
+
+ if (val) {
+ res = erts_lcnt_set_rt_opt(opt) ? am_true : am_false;
+ } else {
+ res = erts_lcnt_clear_rt_opt(opt) ? am_true : am_false;
+ }
+#ifdef ERTS_SMP
+ if (res != tp[2]) {
+ if (opt == ERTS_LCNT_OPT_PORTLOCK) {
+ erts_lcnt_enable_io_lock_count(val);
+ } else if (opt == ERTS_LCNT_OPT_PROCLOCK) {
+ erts_lcnt_enable_proc_lock_count(val);
}
- erts_smp_release_system();
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
- BIF_RET(res);
- }
- break;
+ }
+#endif
+ erts_smp_thr_progress_unblock();
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ BIF_RET(res);
+ break;
+ }
default:
break;
@@ -4107,11 +4125,37 @@ BIF_RETTYPE erts_debug_lock_counters_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
+static void os_info_init(void)
+{
+ Eterm type = am_atom_put(os_type, strlen(os_type));
+ Eterm flav;
+ int major, minor, build;
+ char* buf = erts_alloc(ERTS_ALC_T_TMP, 1024); /* More than enough */
+ Eterm* hp;
+
+ os_flavor(buf, 1024);
+ flav = am_atom_put(buf, strlen(buf));
+ erts_free(ERTS_ALC_T_TMP, (void *) buf);
+ hp = erts_alloc(ERTS_ALC_T_LL_TEMP_TERM, (3+4)*sizeof(Eterm));
+ os_type_tuple = TUPLE2(hp, type, flav);
+ hp += 3;
+ os_version(&major, &minor, &build);
+ os_version_tuple = TUPLE3(hp,
+ make_small(major),
+ make_small(minor),
+ make_small(build));
+}
+
void
erts_bif_info_init(void)
{
erts_smp_atomic_init_nob(&available_internal_state, 0);
erts_smp_atomic_init_nob(&hipe_test_reschedule_flag, 0);
+ alloc_info_trap = erts_export_put(am_erlang, am_alloc_info, 1);
+ alloc_sizes_trap = erts_export_put(am_erlang, am_alloc_sizes, 1);
+ gather_sched_wall_time_res_trap
+ = erts_export_put(am_erlang, am_gather_sched_wall_time_result, 1);
process_info_init();
+ os_info_init();
}
diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c
index 47c48e74d6..1805366cfe 100644
--- a/erts/emulator/beam/erl_bif_lists.c
+++ b/erts/emulator/beam/erl_bif_lists.c
@@ -34,27 +34,7 @@
static Eterm keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List);
-/*
- * erlang:'++'/2
- */
-
-Eterm
-ebif_plusplus_2(Process* p, Eterm A, Eterm B)
-{
- return append_2(p, A, B);
-}
-
-/*
- * erlang:'--'/2
- */
-
-Eterm
-ebif_minusminus_2(Process* p, Eterm A, Eterm B)
-{
- return subtract_2(p, A, B);
-}
-
-BIF_RETTYPE append_2(BIF_ALIST_2)
+static BIF_RETTYPE append(Process* p, Eterm A, Eterm B)
{
Eterm list;
Eterm copy;
@@ -63,18 +43,18 @@ BIF_RETTYPE append_2(BIF_ALIST_2)
Eterm* hp;
int i;
- if ((i = list_length(BIF_ARG_1)) < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((i = list_length(A)) < 0) {
+ BIF_ERROR(p, BADARG);
}
if (i == 0) {
- BIF_RET(BIF_ARG_2);
- } else if (is_nil(BIF_ARG_2)) {
- BIF_RET(BIF_ARG_1);
+ BIF_RET(B);
+ } else if (is_nil(B)) {
+ BIF_RET(A);
}
need = 2*i;
- hp = HAlloc(BIF_P, need);
- list = BIF_ARG_1;
+ hp = HAlloc(p, need);
+ list = A;
copy = last = CONS(hp, CAR(list_val(list)), make_list(hp+2));
list = CDR(list_val(list));
hp += 2;
@@ -85,12 +65,31 @@ BIF_RETTYPE append_2(BIF_ALIST_2)
list = CDR(listp);
hp += 2;
}
- CDR(list_val(last)) = BIF_ARG_2;
+ CDR(list_val(last)) = B;
BIF_RET(copy);
}
+/*
+ * erlang:'++'/2
+ */
+
+Eterm
+ebif_plusplus_2(BIF_ALIST_2)
+{
+ return append(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+BIF_RETTYPE append_2(BIF_ALIST_2)
+{
+ return append(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+/*
+ * erlang:'--'/2
+ */
+
#define SMALL_VEC_SIZE 10
-BIF_RETTYPE subtract_2(BIF_ALIST_2)
+static Eterm subtract(Process* p, Eterm A, Eterm B)
{
Eterm list;
Eterm* hp;
@@ -103,17 +102,17 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
int n;
int m;
- if ((n = list_length(BIF_ARG_1)) < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((n = list_length(A)) < 0) {
+ BIF_ERROR(p, BADARG);
}
- if ((m = list_length(BIF_ARG_2)) < 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((m = list_length(B)) < 0) {
+ BIF_ERROR(p, BADARG);
}
if (n == 0)
BIF_RET(NIL);
if (m == 0)
- BIF_RET(BIF_ARG_1);
+ BIF_RET(A);
/* allocate element vector */
if (n <= SMALL_VEC_SIZE)
@@ -123,7 +122,7 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
/* PUT ALL ELEMENTS IN VP */
vp = vec_p;
- list = BIF_ARG_1;
+ list = A;
i = n;
while(i--) {
Eterm* listp = list_val(list);
@@ -132,7 +131,7 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
}
/* UNMARK ALL DELETED CELLS */
- list = BIF_ARG_2;
+ list = B;
m = 0; /* number of deleted elements */
while(is_list(list)) {
Eterm* listp = list_val(list);
@@ -153,11 +152,11 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
if (m == n) /* All deleted ? */
res = NIL;
else if (m == 0) /* None deleted ? */
- res = BIF_ARG_1;
+ res = A;
else { /* REBUILD LIST */
res = NIL;
need = 2*(n - m);
- hp = HAlloc(BIF_P, need);
+ hp = HAlloc(p, need);
vp = vec_p + n - 1;
while(vp >= vec_p) {
if (is_value(*vp)) {
@@ -172,6 +171,16 @@ BIF_RETTYPE subtract_2(BIF_ALIST_2)
BIF_RET(res);
}
+BIF_RETTYPE ebif_minusminus_2(BIF_ALIST_2)
+{
+ return subtract(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+BIF_RETTYPE subtract_2(BIF_ALIST_2)
+{
+ return subtract(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
BIF_RETTYPE lists_member_2(BIF_ALIST_2)
{
Eterm term;
@@ -278,11 +287,12 @@ BIF_RETTYPE lists_reverse_2(BIF_ALIST_2)
}
BIF_RETTYPE
-lists_keymember_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
+lists_keymember_3(BIF_ALIST_3)
{
Eterm res;
- res = keyfind(BIF_lists_keymember_3, p, Key, Pos, List);
+ res = keyfind(BIF_lists_keymember_3, BIF_P,
+ BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
if (is_value(res) && is_tuple(res)) {
return am_true;
} else {
@@ -291,23 +301,25 @@ lists_keymember_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
}
BIF_RETTYPE
-lists_keysearch_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
+lists_keysearch_3(BIF_ALIST_3)
{
Eterm res;
- res = keyfind(BIF_lists_keysearch_3, p, Key, Pos, List);
+ res = keyfind(BIF_lists_keysearch_3, BIF_P,
+ BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
if (is_non_value(res) || is_not_tuple(res)) {
return res;
} else { /* Tuple */
- Eterm* hp = HAlloc(p, 3);
+ Eterm* hp = HAlloc(BIF_P, 3);
return TUPLE2(hp, am_value, res);
}
}
BIF_RETTYPE
-lists_keyfind_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
+lists_keyfind_3(BIF_ALIST_3)
{
- return keyfind(BIF_lists_keyfind_3, p, Key, Pos, List);
+ return keyfind(BIF_lists_keyfind_3, BIF_P,
+ BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
}
static Eterm
diff --git a/erts/emulator/beam/erl_bif_op.c b/erts/emulator/beam/erl_bif_op.c
index deda7adc1f..13f8b1f63c 100644
--- a/erts/emulator/beam/erl_bif_op.c
+++ b/erts/emulator/beam/erl_bif_op.c
@@ -225,18 +225,23 @@ BIF_RETTYPE is_function_1(BIF_ALIST_1)
BIF_RETTYPE is_function_2(BIF_ALIST_2)
{
+ BIF_RET(erl_is_function(BIF_P, BIF_ARG_1, BIF_ARG_2));
+}
+
+Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2)
+{
Sint arity;
/*
* Verify argument 2 (arity); arity must be >= 0.
*/
- if (is_small(BIF_ARG_2)) {
- arity = signed_val(BIF_ARG_2);
+ if (is_small(arg2)) {
+ arity = signed_val(arg2);
if (arity < 0) {
error:
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- } else if (is_big(BIF_ARG_2) && !bignum_header_is_neg(*big_val(BIF_ARG_2))) {
+ } else if (is_big(arg2) && !bignum_header_is_neg(*big_val(arg2))) {
/* A positive bignum is OK, but can't possibly match. */
arity = -1;
} else {
@@ -244,20 +249,20 @@ BIF_RETTYPE is_function_2(BIF_ALIST_2)
goto error;
}
- if (is_fun(BIF_ARG_1)) {
- ErlFunThing* funp = (ErlFunThing *) fun_val(BIF_ARG_1);
+ if (is_fun(arg1)) {
+ ErlFunThing* funp = (ErlFunThing *) fun_val(arg1);
if (funp->arity == (Uint) arity) {
BIF_RET(am_true);
}
- } else if (is_export(BIF_ARG_1)) {
- Export* exp = (Export *) EXPAND_POINTER((export_val(BIF_ARG_1))[1]);
+ } else if (is_export(arg1)) {
+ Export* exp = (Export *) EXPAND_POINTER((export_val(arg1))[1]);
if (exp->code[2] == (Uint) arity) {
BIF_RET(am_true);
}
- } else if (is_tuple(BIF_ARG_1)) {
- Eterm* tp = tuple_val(BIF_ARG_1);
+ } else if (is_tuple(arg1)) {
+ Eterm* tp = tuple_val(arg1);
if (tp[0] == make_arityval(2) && is_atom(tp[1]) && is_atom(tp[2])) {
BIF_RET(am_true);
}
diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c
index 954b1f9729..d076640a8b 100644
--- a/erts/emulator/beam/erl_bif_os.c
+++ b/erts/emulator/beam/erl_bif_os.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2010. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -53,35 +53,31 @@ BIF_RETTYPE os_timestamp_0(BIF_ALIST_0)
}
-Eterm
-os_getpid_0(Process* p)
+BIF_RETTYPE os_getpid_0(BIF_ALIST_0)
{
char pid_string[21]; /* enough for a 64 bit number */
int n;
Eterm* hp;
sys_get_pid(pid_string); /* In sys.c */
n = sys_strlen(pid_string);
- hp = HAlloc(p, n*2);
+ hp = HAlloc(BIF_P, n*2);
BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL));
}
-Eterm
-os_getenv_0(Process* p)
+BIF_RETTYPE os_getenv_0(BIF_ALIST_0)
{
GETENV_STATE state;
char *cp;
Eterm* hp;
Eterm ret;
Eterm str;
- int len;
init_getenv_state(&state);
ret = NIL;
while ((cp = getenv_string(&state)) != NULL) {
- len = strlen(cp);
- hp = HAlloc(p, len*2+2);
- str = buf_to_intlist(&hp, cp, len, NIL);
+ str = erts_convert_native_to_filename(BIF_P,(byte *)cp);
+ hp = HAlloc(BIF_P, 2);
ret = CONS(hp, str, ret);
}
@@ -90,30 +86,30 @@ os_getenv_0(Process* p)
return ret;
}
-Eterm
-os_getenv_1(Process* p, Eterm key)
+#define STATIC_BUF_SIZE 1024
+BIF_RETTYPE os_getenv_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
Eterm str;
- int len, res;
+ Sint len;
+ int res;
char *key_str, *val;
- char buf[1024];
+ char buf[STATIC_BUF_SIZE];
size_t val_size = sizeof(buf);
- len = is_string(key);
- if (!len) {
+ key_str = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE,
+ ERTS_ALC_T_TMP,1,0,&len);
+
+ if (!key_str) {
BIF_ERROR(p, BADARG);
}
- /* Leave at least one byte in buf for value */
- key_str = len < sizeof(buf)-2 ? &buf[0] : erts_alloc(ERTS_ALC_T_TMP, len+1);
- if (intlist_to_buf(key, key_str, len) != len)
- erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
- key_str[len] = '\0';
if (key_str != &buf[0])
val = &buf[0];
else {
- val_size -= len + 1;
- val = &buf[len + 1];
+ /* len includes zero byte */
+ val_size -= len;
+ val = &buf[len];
}
res = erts_sys_getenv(key_str, val, &val_size);
@@ -121,7 +117,6 @@ os_getenv_1(Process* p, Eterm key)
no_var:
str = am_false;
} else {
- Eterm* hp;
if (res > 0) {
val = erts_alloc(ERTS_ALC_T_TMP, val_size);
while (1) {
@@ -134,9 +129,7 @@ os_getenv_1(Process* p, Eterm key)
val = erts_realloc(ERTS_ALC_T_TMP, val, val_size);
}
}
- if (val_size)
- hp = HAlloc(p, val_size*2);
- str = buf_to_intlist(&hp, val, val_size, NIL);
+ str = erts_convert_native_to_filename(p,(byte *)val);
}
if (key_str != &buf[0])
erts_free(ERTS_ALC_T_TMP, key_str);
@@ -145,46 +138,45 @@ os_getenv_1(Process* p, Eterm key)
BIF_RET(str);
}
-Eterm
-os_putenv_2(Process* p, Eterm key, Eterm value)
+BIF_RETTYPE os_putenv_2(BIF_ALIST_2)
{
- char def_buf[1024];
- char *buf = NULL;
- int sep_ix, i, key_len, value_len, tot_len;
- key_len = is_string(key);
- if (!key_len) {
- error:
- if (buf)
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
- BIF_ERROR(p, BADARG);
+ char def_buf_key[STATIC_BUF_SIZE];
+ char def_buf_value[STATIC_BUF_SIZE];
+ char *key_buf, *value_buf;
+
+ key_buf = erts_convert_filename_to_native(BIF_ARG_1,def_buf_key,
+ STATIC_BUF_SIZE,
+ ERTS_ALC_T_TMP,0,0,NULL);
+ if (!key_buf) {
+ BIF_ERROR(BIF_P, BADARG);
}
- if (is_nil(value))
- value_len = 0;
- else {
- value_len = is_string(value);
- if (!value_len)
- goto error;
+ value_buf = erts_convert_filename_to_native(BIF_ARG_2,def_buf_value,
+ STATIC_BUF_SIZE,
+ ERTS_ALC_T_TMP,1,0,
+ NULL);
+ if (!value_buf) {
+ if (key_buf != def_buf_key) {
+ erts_free(ERTS_ALC_T_TMP, key_buf);
+ }
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+
+ if (erts_sys_putenv(key_buf, value_buf)) {
+ if (key_buf != def_buf_key) {
+ erts_free(ERTS_ALC_T_TMP, key_buf);
+ }
+ if (value_buf != def_buf_value) {
+ erts_free(ERTS_ALC_T_TMP, value_buf);
+ }
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ if (key_buf != def_buf_key) {
+ erts_free(ERTS_ALC_T_TMP, key_buf);
}
- tot_len = key_len + 1 + value_len + 1;
- if (tot_len <= sizeof(def_buf))
- buf = &def_buf[0];
- else
- buf = erts_alloc(ERTS_ALC_T_TMP, tot_len);
- i = intlist_to_buf(key, buf, key_len);
- if (i != key_len)
- erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
- sep_ix = i;
- buf[i++] = '=';
- if (is_not_nil(value))
- i += intlist_to_buf(value, &buf[i], value_len);
- if (i != key_len + 1 + value_len)
- erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
- buf[i] = '\0';
- if (erts_sys_putenv(buf, sep_ix)) {
- goto error;
+ if (value_buf != def_buf_value) {
+ erts_free(ERTS_ALC_T_TMP, value_buf);
}
- if (buf != &def_buf[0])
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_RET(am_true);
}
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 3fd35dd963..f9009166c0 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2012. All Rights Reserved.
*
* The 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,6 +40,7 @@
#include "external.h"
#include "packet_parser.h"
#include "erl_bits.h"
+#include "dtrace-wrapper.h"
static int open_port(Process* p, Eterm name, Eterm settings, int *err_nump);
static byte* convert_environment(Process* p, Eterm env);
@@ -48,6 +49,9 @@ static void free_args(char **);
char *erts_default_arg0 = "default";
+static BIF_RETTYPE
+port_call(Process* p, Eterm arg1, Eterm arg2, Eterm arg3);
+
BIF_RETTYPE open_port_2(BIF_ALIST_2)
{
int port_num;
@@ -117,11 +121,9 @@ id_or_name2port(Process *c_p, Eterm id)
#define ERTS_PORT_COMMAND_FLAG_FORCE (((Uint32) 1) << 0)
#define ERTS_PORT_COMMAND_FLAG_NOSUSPEND (((Uint32) 1) << 1)
-static BIF_RETTYPE do_port_command(Process *BIF_P,
- Eterm BIF_ARG_1,
- Eterm BIF_ARG_2,
- Eterm BIF_ARG_3,
- Uint32 flags)
+static BIF_RETTYPE
+do_port_command(Process *BIF_P, Eterm arg1, Eterm arg2, Eterm arg3,
+ Uint32 flags)
{
BIF_RETTYPE res;
Port *p;
@@ -135,7 +137,7 @@ static BIF_RETTYPE do_port_command(Process *BIF_P,
profile_runnable_proc(BIF_P, am_inactive);
}
- p = id_or_name2port(BIF_P, BIF_ARG_1);
+ p = id_or_name2port(BIF_P, arg1);
if (!p) {
if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
trace_virtual_sched(BIF_P, am_in);
@@ -172,13 +174,13 @@ static BIF_RETTYPE do_port_command(Process *BIF_P,
monitor_generic(BIF_P, am_busy_port, p->id);
}
ERTS_BIF_PREP_YIELD3(res, bif_export[BIF_port_command_3], BIF_P,
- BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ arg1, arg2, arg3);
}
} else {
int wres;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
ERTS_SMP_CHK_NO_PROC_LOCKS;
- wres = erts_write_to_port(BIF_P->id, p, BIF_ARG_2);
+ wres = erts_write_to_port(BIF_P->id, p, arg2);
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
if (wres != 0) {
ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG);
@@ -237,27 +239,33 @@ BIF_RETTYPE port_command_3(BIF_ALIST_3)
BIF_RETTYPE port_call_2(BIF_ALIST_2)
{
- return port_call_3(BIF_P,BIF_ARG_1,make_small(0),BIF_ARG_2);
+ return port_call(BIF_P,BIF_ARG_1, make_small(0), BIF_ARG_2);
}
BIF_RETTYPE port_call_3(BIF_ALIST_3)
{
+ return port_call(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
Uint op;
Port *p;
Uint size;
byte *bytes;
byte *endp;
- size_t real_size;
+ ErlDrvSizeT real_size;
erts_driver_t *drv;
byte port_input[256]; /* Default input buffer to encode in */
byte port_result[256]; /* Buffer for result from port. */
byte* port_resp; /* Pointer to result buffer. */
char *prc;
- int ret;
+ ErlDrvSSizeT ret;
Eterm res;
Sint result_size;
Eterm *hp;
- Eterm *hp_end; /* To satisfy hybrid heap architecture */
+ Eterm *hp_end;
unsigned ret_flags = 0U;
int fpe_was_unmasked;
@@ -266,15 +274,15 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
/* trace of port scheduling with virtual process descheduling
* lock wait
*/
- if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
- trace_virtual_sched(BIF_P, am_out);
+ if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS)) {
+ trace_virtual_sched(c_p, am_out);
}
if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) {
- profile_runnable_proc(BIF_P, am_inactive);
+ profile_runnable_proc(c_p, am_inactive);
}
- p = id_or_name2port(BIF_P, BIF_ARG_1);
+ p = id_or_name2port(c_p, arg1);
if (!p) {
error:
if (port_resp != port_result &&
@@ -286,22 +294,22 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
/* Need to virtual schedule in the process if there
* was an error.
*/
- if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
- trace_virtual_sched(BIF_P, am_in);
+ if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS)) {
+ trace_virtual_sched(c_p, am_in);
}
if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) {
- profile_runnable_proc(BIF_P, am_active);
+ profile_runnable_proc(c_p, am_active);
}
if (p)
erts_port_release(p);
#ifdef ERTS_SMP
- ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_BIF_CHK_PENDING_EXIT(c_p, ERTS_PROC_LOCK_MAIN);
#else
- ERTS_BIF_CHK_EXITED(BIF_P);
+ ERTS_BIF_CHK_EXITED(c_p);
#endif
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(c_p, BADARG);
}
if ((drv = p->drv_ptr) == NULL) {
@@ -310,10 +318,10 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
if (drv->call == NULL) {
goto error;
}
- if (!term_to_Uint(BIF_ARG_2, &op)) {
+ if (!term_to_Uint(arg2, &op)) {
goto error;
}
- p->caller = BIF_P->id;
+ p->caller = c_p->id;
/* Lock taken, virtual schedule of port */
if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) {
@@ -323,19 +331,29 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(p)) {
profile_runnable_port(p, am_active);
}
- size = erts_encode_ext_size(BIF_ARG_3);
+ size = erts_encode_ext_size(arg3);
if (size > sizeof(port_input))
bytes = erts_alloc(ERTS_ALC_T_PORT_CALL_BUF, size);
endp = bytes;
- erts_encode_ext(BIF_ARG_3, &endp);
+ erts_encode_ext(arg3, &endp);
real_size = endp - bytes;
if (real_size > size) {
erl_exit(1, "%s, line %d: buffer overflow: %d word(s)\n",
__FILE__, __LINE__, endp - (bytes + size));
}
- erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_call)) {
+ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_pid_str(p->connected, process_str);
+ dtrace_port_str(p, port_str);
+ DTRACE5(driver_call, process_str, port_str, p->name, op, real_size);
+ }
+#endif
prc = (char *) port_resp;
fpe_was_unmasked = erts_block_fpe();
ret = drv->call((ErlDrvData)p->drv_data,
@@ -356,12 +374,12 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
port_resp = (byte *) prc;
p->caller = NIL;
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
+ erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
#ifdef HARDDEBUG
{
- int z;
- printf("real_size = %ld,%d, ret = %d\r\n",real_size,
- (int) real_size, ret);
+ ErlDrvSizeT z;
+ printf("real_size = %ld,%d, ret = %ld,%d\r\n", (unsigned long) real_size,
+ (int) real_size, (unsigned long)ret, (int) ret);
printf("[");
for(z = 0; z < real_size; ++z) {
printf("%d, ",(int) bytes[z]);
@@ -378,18 +396,18 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
/* Error or a binary without magic/ with wrong magic */
goto error;
}
- result_size = erts_decode_ext_size(port_resp, ret, 0);
+ result_size = erts_decode_ext_size(port_resp, ret);
if (result_size < 0) {
goto error;
}
- hp = HAlloc(BIF_P, result_size);
+ hp = HAlloc(c_p, result_size);
hp_end = hp + result_size;
endp = port_resp;
- res = erts_decode_ext(&hp, &MSO(BIF_P), &endp);
+ res = erts_decode_ext(&hp, &MSO(c_p), &endp);
if (res == THE_NON_VALUE) {
goto error;
}
- HRelease(BIF_P, hp_end, hp);
+ HRelease(c_p, hp_end, hp);
if (port_resp != port_result && !(ret_flags & DRIVER_CALL_KEEP_BUFFER)) {
driver_free(port_resp);
}
@@ -398,16 +416,16 @@ BIF_RETTYPE port_call_3(BIF_ALIST_3)
if (p)
erts_port_release(p);
#ifdef ERTS_SMP
- ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_BIF_CHK_PENDING_EXIT(c_p, ERTS_PROC_LOCK_MAIN);
#else
- ERTS_BIF_CHK_EXITED(BIF_P);
+ ERTS_BIF_CHK_EXITED(c_p);
#endif
- if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) {
- trace_virtual_sched(BIF_P, am_in);
+ if (IS_TRACED_FL(c_p, F_TRACE_SCHED_PROCS)) {
+ trace_virtual_sched(c_p, am_in);
}
if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) {
- profile_runnable_proc(BIF_P, am_active);
+ profile_runnable_proc(c_p, am_active);
}
return res;
@@ -532,6 +550,18 @@ BIF_RETTYPE port_connect_2(BIF_ALIST_2)
prt->connected = pid; /* internal pid */
erts_smp_port_unlock(prt);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(port_connect)) {
+ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(newprocess_str, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_pid_str(prt->connected, process_str);
+ erts_snprintf(port_str, sizeof(port_str), "%T", prt->id);
+ dtrace_proc_str(rp, newprocess_str);
+ DTRACE4(port_connect, process_str, port_str, prt->name, newprocess_str);
+ }
+#endif
BIF_RET(am_true);
}
@@ -688,7 +718,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
} else if (option == am_arg0) {
char *a0;
- if ((a0 = erts_convert_filename_to_native(*tp, ERTS_ALC_T_TMP, 1)) == NULL) {
+ if ((a0 = erts_convert_filename_to_native(*tp, NULL, 0, ERTS_ALC_T_TMP, 1, 1, NULL)) == NULL) {
goto badarg;
}
if (opts.argv == NULL) {
@@ -815,7 +845,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
goto badarg;
}
name = tp[1];
- if ((name_buf = erts_convert_filename_to_native(name,ERTS_ALC_T_TMP,0)) == NULL) {
+ if ((name_buf = erts_convert_filename_to_native(name, NULL, 0, ERTS_ALC_T_TMP,0,1, NULL)) == NULL) {
goto badarg;
}
opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
@@ -879,7 +909,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
}
opts.wd = (char *) dir;
} else {
- if ((opts.wd = erts_convert_filename_to_native(edir,ERTS_ALC_T_TMP,0)) == NULL) {
+ if ((opts.wd = erts_convert_filename_to_native(edir, NULL, 0, ERTS_ALC_T_TMP,0,1,NULL)) == NULL) {
goto badarg;
}
}
@@ -897,7 +927,16 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
port_num = erts_open_driver(driver, p->id, name_buf, &opts, err_nump);
+#ifdef USE_VM_PROBES
+ if (port_num >= 0 && DTRACE_ENABLED(port_open)) {
+ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);
+ dtrace_proc_str(p, process_str);
+ erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id);
+ DTRACE3(port_open, process_str, name_buf, port_str);
+ }
+#endif
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
if (port_num < 0) {
@@ -961,7 +1000,7 @@ static char **convert_args(Eterm l)
pp[i++] = erts_default_arg0;
while (is_list(l)) {
str = CAR(list_val(l));
- if ((b = erts_convert_filename_to_native(str,ERTS_ALC_T_TMP,1)) == NULL) {
+ if ((b = erts_convert_filename_to_native(str,NULL,0,ERTS_ALC_T_TMP,1,1,NULL)) == NULL) {
int j;
for (j = 1; j < i; ++j)
erts_free(ERTS_ALC_T_TMP, pp[j]);
@@ -996,8 +1035,9 @@ static byte* convert_environment(Process* p, Eterm env)
Eterm* hp;
Uint heap_size;
int n;
- Uint size;
+ Sint size;
byte* bytes;
+ int encoding = erts_get_native_filename_encoding();
if ((n = list_length(env)) < 0) {
return NULL;
@@ -1040,7 +1080,8 @@ static byte* convert_environment(Process* p, Eterm env)
if (is_not_nil(env)) {
goto done;
}
- if (erts_iolist_size(all, &size)) {
+
+ if ((size = erts_native_filename_need(all,encoding)) < 0) {
goto done;
}
@@ -1048,7 +1089,7 @@ static byte* convert_environment(Process* p, Eterm env)
* Put the result in a binary (no risk for a memory leak that way).
*/
(void) erts_new_heap_binary(p, NULL, size, &bytes);
- io_list_to_buf(all, (char*)bytes, size);
+ erts_native_filename_put(all,encoding,bytes);
done:
erts_free(ERTS_ALC_T_TMP, temp_heap);
@@ -1070,7 +1111,7 @@ struct packet_callback_args
};
#define in_area(ptr,start,nbytes) \
- ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
static Eterm
http_bld_string(struct packet_callback_args* pca, Uint **hpp, Uint *szp,
diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c
index 26891c4348..6b843d2e08 100644
--- a/erts/emulator/beam/erl_bif_re.c
+++ b/erts/emulator/beam/erl_bif_re.c
@@ -45,6 +45,7 @@ static Export *urun_trap_exportp = NULL;
static Export *ucompile_trap_exportp = NULL;
static BIF_RETTYPE re_exec_trap(BIF_ALIST_3);
+static BIF_RETTYPE re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
static void *erts_erts_pcre_malloc(size_t size) {
return erts_alloc(ERTS_ALC_T_RE_HEAP,size);
@@ -414,8 +415,8 @@ build_compile_result(Process *p, Eterm error_tag, pcre *result, int errcode, con
* Compile BIFs
*/
-BIF_RETTYPE
-re_compile_2(BIF_ALIST_2)
+static BIF_RETTYPE
+re_compile(Process* p, Eterm arg1, Eterm arg2)
{
Uint slen;
char *expr;
@@ -429,43 +430,49 @@ re_compile_2(BIF_ALIST_2)
int unicode = 0;
- if (parse_options(BIF_ARG_2,&options,NULL,&pflags,NULL,NULL)
+ if (parse_options(arg2,&options,NULL,&pflags,NULL,NULL)
< 0) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
if (pflags & PARSE_FLAG_UNIQUE_EXEC_OPT) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
unicode = (pflags & PARSE_FLAG_UNICODE) ? 1 : 0;
- if (pflags & PARSE_FLAG_UNICODE && !is_binary(BIF_ARG_1)) {
- BIF_TRAP2(ucompile_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2);
+ if (pflags & PARSE_FLAG_UNICODE && !is_binary(arg1)) {
+ BIF_TRAP2(ucompile_trap_exportp, p, arg1, arg2);
}
- if (erts_iolist_size(BIF_ARG_1, &slen)) {
- BIF_ERROR(BIF_P,BADARG);
+ if (erts_iolist_size(arg1, &slen)) {
+ BIF_ERROR(p,BADARG);
}
expr = erts_alloc(ERTS_ALC_T_RE_TMP_BUF, slen + 1);
- if (io_list_to_buf(BIF_ARG_1, expr, slen) != 0) {
+ if (io_list_to_buf(arg1, expr, slen) != 0) {
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
expr[slen]='\0';
result = erts_pcre_compile2(expr, options, &errcode,
&errstr, &errofset, default_table);
- ret = build_compile_result(BIF_P, am_error, result, errcode,
+ ret = build_compile_result(p, am_error, result, errcode,
errstr, errofset, unicode, 1);
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
BIF_RET(ret);
}
BIF_RETTYPE
+re_compile_2(BIF_ALIST_2)
+{
+ return re_compile(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+BIF_RETTYPE
re_compile_1(BIF_ALIST_1)
{
- return re_compile_2(BIF_P,BIF_ARG_1,NIL);
+ return re_compile(BIF_P, BIF_ARG_1, NIL);
}
/*
@@ -845,8 +852,8 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code)
/*
* The actual re:run/2,3 BIFs
*/
-BIF_RETTYPE
-re_run_3(BIF_ALIST_3)
+static BIF_RETTYPE
+re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
{
const pcre *code_tmp;
RestartContext restart;
@@ -865,15 +872,15 @@ re_run_3(BIF_ALIST_3)
Eterm capture[CAPSPEC_SIZE];
int is_list_cap;
- if (parse_options(BIF_ARG_3,&comp_options,&options,&pflags,&startoffset,capture)
+ if (parse_options(arg3,&comp_options,&options,&pflags,&startoffset,capture)
< 0) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
is_list_cap = ((pflags & PARSE_FLAG_CAPTURE_OPT) &&
(capture[CAPSPEC_TYPE] == am_list));
- if (is_not_tuple(BIF_ARG_2) || (arityval(*tuple_val(BIF_ARG_2)) != 4)) {
- if (is_binary(BIF_ARG_2) || is_list(BIF_ARG_2) || is_nil(BIF_ARG_2)) {
+ if (is_not_tuple(arg2) || (arityval(*tuple_val(arg2)) != 4)) {
+ if (is_binary(arg2) || is_list(arg2) || is_nil(arg2)) {
/* Compile from textual RE */
Uint slen;
char *expr;
@@ -884,19 +891,19 @@ re_run_3(BIF_ALIST_3)
int capture_count;
if (pflags & PARSE_FLAG_UNICODE &&
- (!is_binary(BIF_ARG_2) || !is_binary(BIF_ARG_1) ||
+ (!is_binary(arg2) || !is_binary(arg1) ||
(is_list_cap && !(pflags & PARSE_FLAG_GLOBAL)))) {
- BIF_TRAP3(urun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ BIF_TRAP3(urun_trap_exportp, p, arg1, arg2, arg3);
}
- if (erts_iolist_size(BIF_ARG_2, &slen)) {
- BIF_ERROR(BIF_P,BADARG);
+ if (erts_iolist_size(arg2, &slen)) {
+ BIF_ERROR(p,BADARG);
}
expr = erts_alloc(ERTS_ALC_T_RE_TMP_BUF, slen + 1);
- if (io_list_to_buf(BIF_ARG_2, expr, slen) != 0) {
+ if (io_list_to_buf(arg2, expr, slen) != 0) {
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
expr[slen]='\0';
result = erts_pcre_compile2(expr, comp_options, &errcode,
@@ -905,11 +912,11 @@ re_run_3(BIF_ALIST_3)
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
/* Compilation error gives badarg except in the compile
function */
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
if (pflags & PARSE_FLAG_GLOBAL) {
Eterm precompiled =
- build_compile_result(BIF_P, am_error,
+ build_compile_result(p, am_error,
result, errcode,
errstr, errofset,
(pflags &
@@ -917,13 +924,13 @@ re_run_3(BIF_ALIST_3)
0);
Eterm *hp,r;
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
- hp = HAlloc(BIF_P,4);
- /* BIF_ARG_2 is in the tuple just to make exceptions right */
- r = TUPLE3(hp,BIF_ARG_3,
+ hp = HAlloc(p,4);
+ /* arg2 is in the tuple just to make exceptions right */
+ r = TUPLE3(hp,arg3,
((pflags & PARSE_FLAG_UNIQUE_COMPILE_OPT) ?
am_true :
- am_false), BIF_ARG_2);
- BIF_TRAP3(grun_trap_exportp, BIF_P, BIF_ARG_1, precompiled, r);
+ am_false), arg2);
+ BIF_TRAP3(grun_trap_exportp, p, arg1, precompiled, r);
}
erts_pcre_fullinfo(result, NULL, PCRE_INFO_SIZE, &code_size);
@@ -935,31 +942,31 @@ re_run_3(BIF_ALIST_3)
erts_free(ERTS_ALC_T_RE_TMP_BUF, expr);
/*unicode = (pflags & PARSE_FLAG_UNICODE) ? 1 : 0;*/
} else {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
} else {
if (pflags & PARSE_FLAG_UNIQUE_COMPILE_OPT) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
- tp = tuple_val(BIF_ARG_2);
+ tp = tuple_val(arg2);
if (tp[1] != am_re_pattern || is_not_small(tp[2]) ||
is_not_small(tp[3]) || is_not_binary(tp[4])) {
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
if (unsigned_val(tp[3]) &&
- (!is_binary(BIF_ARG_1) ||
+ (!is_binary(arg1) ||
(is_list_cap && !(pflags & PARSE_FLAG_GLOBAL)))) { /* unicode */
- BIF_TRAP3(urun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2,
- BIF_ARG_3);
+ BIF_TRAP3(urun_trap_exportp, p, arg1, arg2,
+ arg3);
}
if (pflags & PARSE_FLAG_GLOBAL) {
Eterm *hp,r;
- hp = HAlloc(BIF_P,3);
- r = TUPLE2(hp,BIF_ARG_3,am_false);
- BIF_TRAP3(grun_trap_exportp, BIF_P, BIF_ARG_1, BIF_ARG_2,
+ hp = HAlloc(p,3);
+ r = TUPLE2(hp,arg3,am_false);
+ BIF_TRAP3(grun_trap_exportp, p, arg1, arg2,
r);
}
@@ -968,7 +975,7 @@ re_run_3(BIF_ALIST_3)
if ((code_tmp = (const pcre *)
erts_get_aligned_binary_bytes(tp[4], &temp_alloc)) == NULL) {
erts_free_aligned_binary_bytes(temp_alloc);
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
restart.code = erts_alloc(ERTS_ALC_T_RE_SUBJECT, code_size);
memcpy(restart.code, code_tmp, code_size);
@@ -980,7 +987,7 @@ re_run_3(BIF_ALIST_3)
restart.ovector = erts_alloc(ERTS_ALC_T_RE_SUBJECT, ovsize * sizeof(int));
restart.extra.flags = PCRE_EXTRA_TABLES | PCRE_EXTRA_LOOP_LIMIT;
restart.extra.tables = default_table;
- restart.extra.loop_limit = ERTS_BIF_REDS_LEFT(BIF_P) * LOOP_FACTOR;
+ restart.extra.loop_limit = ERTS_BIF_REDS_LEFT(p) * LOOP_FACTOR;
loop_limit_tmp = max_loop_limit; /* To lesser probability of race in debug
situation (erts_debug) */
if (restart.extra.loop_limit > loop_limit_tmp) {
@@ -996,7 +1003,7 @@ re_run_3(BIF_ALIST_3)
if ((restart.ret_info = build_capture(capture,restart.code)) == NULL) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
}
@@ -1004,7 +1011,7 @@ re_run_3(BIF_ALIST_3)
copying, also binary returns can be sub binaries in that case */
restart.flags = 0;
- if (is_binary(BIF_ARG_1)) {
+ if (is_binary(arg1)) {
Eterm real_bin;
Uint offset;
Eterm* bptr;
@@ -1012,9 +1019,9 @@ re_run_3(BIF_ALIST_3)
int bitsize;
ProcBin* pb;
- ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
+ ERTS_GET_REAL_BIN(arg1, real_bin, offset, bitoffs, bitsize);
- slength = binary_size(BIF_ARG_1);
+ slength = binary_size(arg1);
bptr = binary_val(real_bin);
if (bitsize != 0 || bitoffs != 0 || (*bptr != HEADER_PROC_BIN)) {
goto handle_iolist;
@@ -1027,24 +1034,24 @@ re_run_3(BIF_ALIST_3)
restart.flags |= RESTART_FLAG_SUBJECT_IN_BINARY;
} else {
handle_iolist:
- if (erts_iolist_size(BIF_ARG_1, &slength)) {
+ if (erts_iolist_size(arg1, &slength)) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
if (restart.ret_info != NULL) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ret_info);
}
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
restart.subject = erts_alloc(ERTS_ALC_T_RE_SUBJECT, slength);
- if (io_list_to_buf(BIF_ARG_1, restart.subject, slength) != 0) {
+ if (io_list_to_buf(arg1, restart.subject, slength) != 0) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ovector);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.code);
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.subject);
if (restart.ret_info != NULL) {
erts_free(ERTS_ALC_T_RE_SUBJECT, restart.ret_info);
}
- BIF_ERROR(BIF_P,BADARG);
+ BIF_ERROR(p,BADARG);
}
}
@@ -1056,7 +1063,7 @@ handle_iolist:
rc = erts_pcre_exec(restart.code, &(restart.extra), restart.subject, slength, startoffset,
options, restart.ovector, ovsize);
ASSERT(loop_count != 0xFFFFFFFF);
- BUMP_REDS(BIF_P, loop_count / LOOP_FACTOR);
+ BUMP_REDS(p, loop_count / LOOP_FACTOR);
if (rc == PCRE_ERROR_LOOP_LIMIT) {
/* Trap */
Binary *mbp = erts_create_magic_binary(sizeof(RestartContext),
@@ -1065,17 +1072,17 @@ handle_iolist:
Eterm magic_bin;
Eterm *hp;
memcpy(restartp,&restart,sizeof(RestartContext));
- BUMP_ALL_REDS(BIF_P);
- hp = HAlloc(BIF_P, PROC_BIN_SIZE);
- magic_bin = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), mbp);
+ BUMP_ALL_REDS(p);
+ hp = HAlloc(p, PROC_BIN_SIZE);
+ magic_bin = erts_mk_magic_binary_term(&hp, &MSO(p), mbp);
BIF_TRAP3(&re_exec_trap_export,
- BIF_P,
- BIF_ARG_1,
- BIF_ARG_2 /* To avoid GC of precompiled code, XXX: not utilized yet */,
+ p,
+ arg1,
+ arg2 /* To avoid GC of precompiled code, XXX: not utilized yet */,
magic_bin);
}
- res = build_exec_return(BIF_P, rc, &restart, BIF_ARG_1);
+ res = build_exec_return(p, rc, &restart, arg1);
cleanup_restart_context(&restart);
@@ -1083,9 +1090,15 @@ handle_iolist:
}
BIF_RETTYPE
+re_run_3(BIF_ALIST_3)
+{
+ return re_run(BIF_P,BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+BIF_RETTYPE
re_run_2(BIF_ALIST_2)
{
- return re_run_3(BIF_P,BIF_ARG_1, BIF_ARG_2, NIL);
+ return re_run(BIF_P,BIF_ARG_1, BIF_ARG_2, NIL);
}
/*
diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c
index db771bd216..d806be0704 100644
--- a/erts/emulator/beam/erl_bif_timer.c
+++ b/erts/emulator/beam/erl_bif_timer.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -26,6 +26,7 @@
#include "bif.h"
#include "error.h"
#include "big.h"
+#include "erl_thr_progress.h"
/****************************************************************************
** BIF Timer support
@@ -372,7 +373,11 @@ bif_timer_timeout(ErtsBifTimer* btm)
message = TUPLE3(hp, am_timeout, ref, message);
}
- erts_queue_message(rp, &rp_locks, bp, message, NIL);
+ erts_queue_message(rp, &rp_locks, bp, message, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -686,7 +691,7 @@ erts_bif_timer_foreach(void (*func)(Eterm, Eterm, ErlHeapFragment *, void *),
{
int i;
- ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
for (i = 0; i < TIMER_HASH_VEC_SZ; i++) {
ErtsBifTimer *btm;
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 7a08182e18..80f774523c 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2012. All Rights Reserved.
*
* The 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,7 @@
#include "erl_version.h"
#include "beam_bp.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
@@ -47,6 +48,11 @@ static Binary *erts_default_meta_match_spec;
static struct trace_pattern_flags erts_default_trace_pattern_flags;
static Eterm erts_default_meta_tracer_pid;
+static Eterm
+trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist);
+static BIF_RETTYPE
+system_monitor(Process *p, Eterm monitor_pid, Eterm list);
+
static void new_seq_trace_token(Process* p); /* help func for seq_trace_2*/
static int already_traced(Process *p, Process *tracee_p, Eterm tracer);
static int port_already_traced(Process *p, Port *tracee_port, Eterm tracer);
@@ -76,13 +82,19 @@ erts_bif_trace_init(void)
*/
Eterm
-trace_pattern_2(Process* p, Eterm MFA, Eterm Pattern)
+trace_pattern_2(BIF_ALIST_2)
{
- return trace_pattern_3(p,MFA,Pattern,NIL);
+ return trace_pattern(BIF_P, BIF_ARG_1, BIF_ARG_2, NIL);
}
Eterm
-trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
+trace_pattern_3(BIF_ALIST_3)
+{
+ return trace_pattern(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static Eterm
+trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
{
DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */
int i;
@@ -97,7 +109,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
Eterm meta_tracer_pid = p->id;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
UseTmpHeap(3,p);
/*
@@ -326,7 +338,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
done:
UnUseTmpHeap(3,p);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
return make_small(matches);
@@ -336,7 +348,7 @@ trace_pattern_3(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
MatchSetUnref(match_prog_set);
UnUseTmpHeap(3,p);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_ERROR(p, BADARG);
}
@@ -435,9 +447,12 @@ erts_trace_flags(Eterm List,
return 0;
}
-Eterm
-trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
+Eterm trace_3(BIF_ALIST_3)
{
+ Process* p = BIF_P;
+ Eterm pid_spec = BIF_ARG_1;
+ Eterm how = BIF_ARG_2;
+ Eterm list = BIF_ARG_3;
int on;
Eterm tracer = NIL;
int matches = 0;
@@ -630,7 +645,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
#ifdef ERTS_SMP
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
system_blocked = 1;
#endif
@@ -711,7 +726,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
#ifdef ERTS_SMP
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -726,7 +741,7 @@ trace_3(Process* p, Eterm pid_spec, Eterm how, Eterm list)
#ifdef ERTS_SMP
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -820,9 +835,11 @@ static int already_traced(Process *c_p, Process *tracee_p, Eterm tracer)
* Return information about a process or an external function being traced.
*/
-Eterm
-trace_info_2(Process* p, Eterm What, Eterm Key)
+Eterm trace_info_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm What = BIF_ARG_1;
+ Eterm Key = BIF_ARG_2;
Eterm res;
if (What == am_on_load) {
res = trace_info_on_load(p, Key);
@@ -1060,7 +1077,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
#ifdef ERTS_SMP
if ( (key == am_call_time) || (key == am_all)) {
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
}
#endif
@@ -1068,7 +1085,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
#ifdef ERTS_SMP
if ( (key == am_call_time) || (key == am_all)) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -1727,9 +1744,17 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2,
return THE_NON_VALUE;
}
if (build_result) {
+#ifdef USE_VM_PROBES
+ old_value = (SEQ_TRACE_TOKEN(p) == am_have_dt_utag) ? NIL : SEQ_TRACE_TOKEN(p);
+#else
old_value = SEQ_TRACE_TOKEN(p);
+#endif
}
+#ifdef USE_VM_PROBES
+ SEQ_TRACE_TOKEN(p) = (DT_UTAG(p) != NIL) ? am_have_dt_utag : NIL;
+#else
SEQ_TRACE_TOKEN(p) = NIL;
+#endif
return old_value;
}
else {
@@ -1742,7 +1767,11 @@ new_seq_trace_token(Process* p)
{
Eterm* hp;
- if (SEQ_TRACE_TOKEN(p) == NIL) {
+ if (SEQ_TRACE_TOKEN(p) == NIL
+#ifdef USE_VM_PROBES
+ || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
+#endif
+ ) {
hp = HAlloc(p, 6);
SEQ_TRACE_TOKEN(p) = TUPLE5(hp, make_small(0), /* Flags */
make_small(0), /* Label */
@@ -1752,23 +1781,24 @@ new_seq_trace_token(Process* p)
}
}
-BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
+BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item)
{
- Eterm item;
Eterm res;
Eterm* hp;
Uint current_flag;
- if (is_not_atom(BIF_ARG_1)) {
- BIF_ERROR(BIF_P, BADARG);
+ if (is_not_atom(item)) {
+ BIF_ERROR(p, BADARG);
}
- item = BIF_ARG_1;
-
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL) {
+ if (SEQ_TRACE_TOKEN(p) == NIL
+#ifdef USE_VM_PROBES
+ || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
+#endif
+ ) {
if ((item == am_send) || (item == am_receive) ||
(item == am_print) || (item == am_timestamp)) {
- hp = HAlloc(BIF_P,3);
+ hp = HAlloc(p,3);
res = TUPLE2(hp, item, am_false);
BIF_RET(res);
} else if ((item == am_label) || (item == am_serial)) {
@@ -1778,35 +1808,40 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
}
}
- if (BIF_ARG_1 == am_send) {
+ if (item == am_send) {
current_flag = SEQ_TRACE_SEND;
- } else if (BIF_ARG_1 == am_receive) {
+ } else if (item == am_receive) {
current_flag = SEQ_TRACE_RECEIVE;
- } else if (BIF_ARG_1 == am_print) {
+ } else if (item == am_print) {
current_flag = SEQ_TRACE_PRINT;
- } else if (BIF_ARG_1 == am_timestamp) {
+ } else if (item == am_timestamp) {
current_flag = SEQ_TRACE_TIMESTAMP;
} else {
current_flag = 0;
}
if (current_flag) {
- res = unsigned_val(SEQ_TRACE_TOKEN_FLAGS(BIF_P)) & current_flag ?
+ res = unsigned_val(SEQ_TRACE_TOKEN_FLAGS(p)) & current_flag ?
am_true : am_false;
} else if (item == am_label) {
- res = SEQ_TRACE_TOKEN_LABEL(BIF_P);
+ res = SEQ_TRACE_TOKEN_LABEL(p);
} else if (item == am_serial) {
- hp = HAlloc(BIF_P, 3);
- res = TUPLE2(hp, SEQ_TRACE_TOKEN_LASTCNT(BIF_P), SEQ_TRACE_TOKEN_SERIAL(BIF_P));
+ hp = HAlloc(p, 3);
+ res = TUPLE2(hp, SEQ_TRACE_TOKEN_LASTCNT(p), SEQ_TRACE_TOKEN_SERIAL(p));
} else {
error:
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- hp = HAlloc(BIF_P, 3);
+ hp = HAlloc(p, 3);
res = TUPLE2(hp, item, res);
BIF_RET(res);
}
+BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
+{
+ BIF_RET(erl_seq_trace_info(BIF_P, BIF_ARG_1));
+}
+
/*
seq_trace_print(Message) -> true | false
This function passes Message to the system_tracer
@@ -1817,8 +1852,13 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL)
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL
+#ifdef USE_VM_PROBES
+ || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
+#endif
+ ) {
BIF_RET(am_false);
+ }
seq_trace_update_send(BIF_P);
seq_trace_output(SEQ_TRACE_TOKEN(BIF_P), BIF_ARG_1,
SEQ_TRACE_PRINT, NIL, BIF_P);
@@ -1835,8 +1875,13 @@ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL)
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL
+#ifdef USE_VM_PROBES
+ || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
+#endif
+ ) {
BIF_RET(am_false);
+ }
if (!(is_atom(BIF_ARG_1) || is_small(BIF_ARG_1))) {
BIF_ERROR(BIF_P, BADARG);
}
@@ -1852,7 +1897,7 @@ void erts_system_monitor_clear(Process *c_p) {
#ifdef ERTS_SMP
if (c_p) {
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
}
#endif
erts_set_system_monitor(NIL);
@@ -1862,7 +1907,7 @@ void erts_system_monitor_clear(Process *c_p) {
erts_system_monitor_flags.busy_dist_port = 0;
#ifdef ERTS_SMP
if (c_p) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -1919,23 +1964,35 @@ static Eterm system_monitor_get(Process *p)
}
-BIF_RETTYPE system_monitor_0(Process *p) {
- BIF_RET(system_monitor_get(p));
+BIF_RETTYPE system_monitor_0(BIF_ALIST_0)
+{
+ BIF_RET(system_monitor_get(BIF_P));
}
-BIF_RETTYPE system_monitor_1(Process *p, Eterm spec) {
+BIF_RETTYPE system_monitor_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm spec = BIF_ARG_1;
+
if (spec == am_undefined) {
- BIF_RET(system_monitor_2(p, spec, NIL));
+ BIF_RET(system_monitor(p, spec, NIL));
} else if (is_tuple(spec)) {
Eterm *tp = tuple_val(spec);
if (tp[0] != make_arityval(2)) goto error;
- BIF_RET(system_monitor_2(p, tp[1], tp[2]));
+ BIF_RET(system_monitor(p, tp[1], tp[2]));
}
error:
BIF_ERROR(p, BADARG);
}
-BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
+BIF_RETTYPE system_monitor_2(BIF_ALIST_2)
+{
+ return system_monitor(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+static BIF_RETTYPE
+system_monitor(Process *p, Eterm monitor_pid, Eterm list)
+{
Eterm prev;
int system_blocked = 0;
@@ -1951,7 +2008,7 @@ BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
system_blocked = 1;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (!erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, monitor_pid, 0))
goto error;
@@ -1985,7 +2042,7 @@ BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
erts_system_monitor_flags.busy_port = !!busy_port;
erts_system_monitor_flags.busy_dist_port = !!busy_dist_port;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_RET(prev);
}
@@ -1993,7 +2050,7 @@ BIF_RETTYPE system_monitor_2(Process *p, Eterm monitor_pid, Eterm list) {
error:
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
@@ -2006,7 +2063,7 @@ void erts_system_profile_clear(Process *c_p) {
#ifdef ERTS_SMP
if (c_p) {
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
}
#endif
erts_set_system_profile(NIL);
@@ -2016,7 +2073,7 @@ void erts_system_profile_clear(Process *c_p) {
erts_system_profile_flags.exclusive = 0;
#ifdef ERTS_SMP
if (c_p) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
#endif
@@ -2053,11 +2110,16 @@ static Eterm system_profile_get(Process *p) {
}
}
-BIF_RETTYPE system_profile_0(Process *p) {
- BIF_RET(system_profile_get(p));
+BIF_RETTYPE system_profile_0(BIF_ALIST_0)
+{
+ BIF_RET(system_profile_get(BIF_P));
}
-BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
+BIF_RETTYPE system_profile_2(BIF_ALIST_2)
+{
+ Process *p = BIF_P;
+ Eterm profiler = BIF_ARG_1;
+ Eterm list = BIF_ARG_2;
Eterm prev;
int system_blocked = 0;
Process *profiler_p = NULL;
@@ -2075,7 +2137,7 @@ BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
system_blocked = 1;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* Check if valid process, no locks are taken */
@@ -2117,7 +2179,7 @@ BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
erts_system_profile_flags.runnable_procs = !!runnable_procs;
erts_system_profile_flags.exclusive = !!exclusive;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_RET(prev);
@@ -2126,7 +2188,7 @@ BIF_RETTYPE system_profile_2(Process *p, Eterm profiler, Eterm list) {
error:
if (system_blocked) {
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index 326a5c136b..b7c82935ff 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -845,8 +845,7 @@ erts_bs_put_utf8(ERL_BITS_PROTO_1(Eterm arg))
dst[1] = 0x80 | (val & 0x3F);
num_bits = 16;
} else if (val < 0x10000UL) {
- if ((0xD800 <= val && val <= 0xDFFF) ||
- val == 0xFFFE || val == 0xFFFF) {
+ if (0xD800 <= val && val <= 0xDFFF) {
return 0;
}
dst[0] = 0xE0 | (val >> 12);
@@ -886,8 +885,7 @@ erts_bs_put_utf16(ERL_BITS_PROTO_2(Eterm arg, Uint flags))
return 0;
}
val = unsigned_val(arg);
- if (val > 0x10FFFF || (0xD800 <= val && val <= 0xDFFF) ||
- val == 0xFFFE || val == 0xFFFF) {
+ if (val > 0x10FFFF || (0xD800 <= val && val <= 0xDFFF)) {
return 0;
}
@@ -1007,8 +1005,13 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
if (is_float(arg)) {
FloatDef *fdp = (FloatDef*)(float_val(arg) + 1);
+#ifdef DOUBLE_MIDDLE_ENDIAN
+ a = fdp->fw[1];
+ b = fdp->fw[0];
+#else
a = fdp->fw[0];
b = fdp->fw[1];
+#endif
} else if (is_small(arg)) {
u.f64 = (double) signed_val(arg);
a = u.i32[0];
@@ -1017,8 +1020,13 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
if (big_to_double(arg, &u.f64) < 0) {
return 0;
}
+#ifdef DOUBLE_MIDDLE_ENDIAN
+ a = u.i32[1];
+ b = u.i32[0];
+#else
a = u.i32[0];
b = u.i32[1];
+#endif
} else {
return 0;
}
@@ -1652,8 +1660,7 @@ erts_bs_get_utf8(ErlBinMatchBuffer* mb)
return THE_NON_VALUE;
}
result = (((result << 6) + a) << 6) + b - (Eterm) 0x000E2080UL;
- if ((0xD800 <= result && result <= 0xDFFF) ||
- result == 0xFFFE || result == 0xFFFF) {
+ if (0xD800 <= result && result <= 0xDFFF) {
return THE_NON_VALUE;
}
mb->offset += 24;
@@ -1723,9 +1730,6 @@ erts_bs_get_utf16(ErlBinMatchBuffer* mb, Uint flags)
w1 = (src[0] << 8) | src[1];
}
if (w1 < 0xD800 || w1 > 0xDFFF) {
- if (w1 == 0xFFFE || w1 == 0xFFFF) {
- return THE_NON_VALUE;
- }
mb->offset += 16;
return make_small(w1);
} else if (w1 > 0xDBFF) {
diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c
index 03c0ef904a..fe3693d0ca 100644
--- a/erts/emulator/beam/erl_cpu_topology.c
+++ b/erts/emulator/beam/erl_cpu_topology.c
@@ -486,10 +486,7 @@ erts_sched_check_cpu_bind_post_suspend(ErtsSchedulerData *esdp)
erts_thr_set_main_status(1, (int) esdp->no);
/* Make sure we check if we should bind to a cpu or not... */
- if (esdp->run_queue->flags & ERTS_RUNQ_FLG_SHARED_RUNQ)
- erts_smp_atomic32_set_nob(&esdp->chk_cpu_bind, 1);
- else
- esdp->run_queue->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND;
+ esdp->run_queue->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND;
}
#endif
@@ -502,11 +499,7 @@ erts_sched_check_cpu_bind(ErtsSchedulerData *esdp)
erts_cpu_groups_callback_list_t *cgcl;
erts_cpu_groups_callback_call_t *cgcc;
#ifdef ERTS_SMP
- if (erts_common_run_queue)
- erts_smp_atomic32_set_nob(&esdp->chk_cpu_bind, 0);
- else {
- esdp->run_queue->flags &= ~ERTS_RUNQ_FLG_CHK_CPU_BIND;
- }
+ esdp->run_queue->flags &= ~ERTS_RUNQ_FLG_CHK_CPU_BIND;
#endif
erts_smp_runq_unlock(esdp->run_queue);
erts_smp_rwmtx_rwlock(&cpuinfo_rwmtx);
@@ -1729,16 +1722,8 @@ erts_init_cpu_topology(void)
scheduler2cpu_map[ix].bound_id = -1;
}
- if (cpu_bind_order == ERTS_CPU_BIND_UNDEFINED) {
- int ncpus = erts_get_cpu_configured(cpuinfo);
- if (ncpus < 1 || erts_no_schedulers < ncpus)
- cpu_bind_order = ERTS_CPU_BIND_NONE;
- else
- cpu_bind_order = ((system_cpudata || user_cpudata)
- && (erts_bind_to_cpu(cpuinfo, -1) != -ENOTSUP)
- ? ERTS_CPU_BIND_DEFAULT_BIND
- : ERTS_CPU_BIND_NONE);
- }
+ if (cpu_bind_order == ERTS_CPU_BIND_UNDEFINED)
+ cpu_bind_order = ERTS_CPU_BIND_NONE;
reader_groups_map = add_cpu_groups(reader_groups,
reader_groups_callback,
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 0327850cb9..51bdf53823 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -129,8 +129,6 @@ static Uint meta_main_tab_slot_mask; /* The slot index part of an unnamed tab
static Uint meta_main_tab_seq_incr;
static Uint meta_main_tab_seq_cnt = 0; /* To give unique(-ish) table identifiers */
-
-
/*
** The meta hash table of all NAMED ets tables
*/
@@ -202,12 +200,17 @@ static int free_table_cont(Process *p,
int first,
int clean_meta_tab);
static void print_table(int to, void *to_arg, int show, DbTable* tb);
-static BIF_RETTYPE ets_select_delete_1(Process *p, Eterm a1);
-static BIF_RETTYPE ets_select_count_1(Process *p, Eterm a1);
-static BIF_RETTYPE ets_select_trap_1(Process *p, Eterm a1);
-static BIF_RETTYPE ets_delete_trap(Process *p, Eterm a1);
+static BIF_RETTYPE ets_select_delete_1(BIF_ALIST_1);
+static BIF_RETTYPE ets_select_count_1(BIF_ALIST_1);
+static BIF_RETTYPE ets_select_trap_1(BIF_ALIST_1);
+static BIF_RETTYPE ets_delete_trap(BIF_ALIST_1);
static Eterm table_info(Process* p, DbTable* tb, Eterm What);
+static BIF_RETTYPE ets_select1(Process* p, Eterm arg1);
+static BIF_RETTYPE ets_select2(Process* p, Eterm arg1, Eterm arg2);
+static BIF_RETTYPE ets_select3(Process* p, Eterm arg1, Eterm arg2, Eterm arg3);
+
+
/*
* Exported global
*/
@@ -248,7 +251,7 @@ free_dbtable(DbTable* tb)
ASSERT(is_immed(tb->common.heir_data));
erts_db_free(ERTS_ALC_T_DB_TABLE, tb, (void *) tb, sizeof(DbTable));
ERTS_ETS_MISC_MEM_ADD(-sizeof(DbTable));
- ERTS_THR_MEMORY_BARRIER;
+ ERTS_SMP_MEMORY_BARRIER;
}
#ifdef ERTS_SMP
@@ -277,8 +280,7 @@ static void schedule_free_dbtable(DbTable* tb)
ASSERT(scheds >= 1);
ASSERT(erts_refc_read(&tb->common.ref, 0) == 0);
erts_refc_init(&tb->common.ref, scheds);
- ERTS_THR_MEMORY_BARRIER;
- erts_smp_schedule_misc_aux_work(0, scheds, chk_free_dbtable, tb);
+ erts_schedule_multi_misc_aux_work(0, scheds, chk_free_dbtable, tb);
#else
free_dbtable(tb);
#endif
@@ -1296,8 +1298,13 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
UWord heir_data;
Uint32 status;
Sint keypos;
- int is_named, is_fine_locked, frequent_read, is_compressed;
+ int is_named, is_compressed;
+#ifdef ERTS_SMP
+ int is_fine_locked, frequent_read;
+#endif
+#ifdef DEBUG
int cret;
+#endif
DeclareTmpHeap(meta_tuple,3,BIF_P);
DbTableMethod* meth;
erts_smp_rwmtx_t *mmtl;
@@ -1312,8 +1319,10 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
status = DB_NORMAL | DB_SET | DB_PROTECTED;
keypos = 1;
is_named = 0;
+#ifdef ERTS_SMP
is_fine_locked = 0;
frequent_read = 0;
+#endif
heir = am_none;
heir_data = (UWord) am_undefined;
is_compressed = erts_ets_always_compress;
@@ -1342,18 +1351,31 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
keypos = signed_val(tp[2]);
}
else if (tp[1] == am_write_concurrency) {
+#ifdef ERTS_SMP
if (tp[2] == am_true) {
is_fine_locked = 1;
} else if (tp[2] == am_false) {
is_fine_locked = 0;
} else break;
+#else
+ if ((tp[2] != am_true) && (tp[2] != am_false)) {
+ break;
+ }
+#endif
}
else if (tp[1] == am_read_concurrency) {
+#ifdef ERTS_SMP
if (tp[2] == am_true) {
frequent_read = 1;
} else if (tp[2] == am_false) {
frequent_read = 0;
} else break;
+#else
+ if ((tp[2] != am_true) && (tp[2] != am_false)) {
+ break;
+ }
+#endif
+
}
else if (tp[1] == am_heir && tp[2] == am_none) {
heir = am_none;
@@ -1393,11 +1415,11 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
}
if (IS_HASH_TABLE(status)) {
meth = &db_hash;
- #ifdef ERTS_SMP
+#ifdef ERTS_SMP
if (is_fine_locked && !(status & DB_PRIVATE)) {
status |= DB_FINE_LOCKED;
}
- #endif
+#endif
}
else if (IS_TREE_TABLE(status)) {
meth = &db_tree;
@@ -1445,7 +1467,10 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
tb->common.fixations = NULL;
tb->common.compress = is_compressed;
- cret = meth->db_create(BIF_P, tb);
+#ifdef DEBUG
+ cret =
+#endif
+ meth->db_create(BIF_P, tb);
ASSERT(cret == DB_ERROR_NONE);
erts_smp_spin_lock(&meta_main_tab_main_lock);
@@ -1942,8 +1967,10 @@ BIF_RETTYPE ets_delete_object_2(BIF_ALIST_2)
/*
** This is for trapping, cannot be called directly.
*/
-static BIF_RETTYPE ets_select_delete_1(Process *p, Eterm a1)
+static BIF_RETTYPE ets_select_delete_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2109,7 +2136,7 @@ BIF_RETTYPE ets_slot_2(BIF_ALIST_2)
BIF_RETTYPE ets_match_1(BIF_ALIST_1)
{
- return ets_select_1(BIF_P, BIF_ARG_1);
+ return ets_select1(BIF_P, BIF_ARG_1);
}
BIF_RETTYPE ets_match_2(BIF_ALIST_2)
@@ -2125,7 +2152,7 @@ BIF_RETTYPE ets_match_2(BIF_ALIST_2)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_2(BIF_P, BIF_ARG_1, ms);
+ res = ets_select2(BIF_P, BIF_ARG_1, ms);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2143,7 +2170,7 @@ BIF_RETTYPE ets_match_3(BIF_ALIST_3)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
+ res = ets_select3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2151,6 +2178,12 @@ BIF_RETTYPE ets_match_3(BIF_ALIST_3)
BIF_RETTYPE ets_select_3(BIF_ALIST_3)
{
+ return ets_select3(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static BIF_RETTYPE
+ets_select3(Process* p, Eterm arg1, Eterm arg2, Eterm arg3)
+{
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2161,22 +2194,22 @@ BIF_RETTYPE ets_select_3(BIF_ALIST_3)
CHECK_TABLES();
/* Chunk size strictly greater than 0 */
- if (is_not_small(BIF_ARG_3) || (chunk_size = signed_val(BIF_ARG_3)) <= 0) {
- BIF_ERROR(BIF_P, BADARG);
+ if (is_not_small(arg3) || (chunk_size = signed_val(arg3)) <= 0) {
+ BIF_ERROR(p, BADARG);
}
- if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_READ, LCK_READ)) == NULL) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((tb = db_get_table(p, arg1, DB_READ, LCK_READ)) == NULL) {
+ BIF_ERROR(p, BADARG);
}
- safety = ITERATION_SAFETY(BIF_P,tb);
+ safety = ITERATION_SAFETY(p,tb);
if (safety == ITER_UNSAFE) {
local_fix_table(tb);
}
- cret = tb->common.meth->db_select_chunk(BIF_P, tb,
- BIF_ARG_2, chunk_size,
+ cret = tb->common.meth->db_select_chunk(p, tb,
+ arg2, chunk_size,
0 /* not reversed */,
&ret);
- if (DID_TRAP(BIF_P,ret) && safety != ITER_SAFE) {
- fix_table_locked(BIF_P, tb);
+ if (DID_TRAP(p,ret) && safety != ITER_SAFE) {
+ fix_table_locked(p, tb);
}
if (safety == ITER_UNSAFE) {
local_unfix_table(tb);
@@ -2188,22 +2221,24 @@ BIF_RETTYPE ets_select_3(BIF_ALIST_3)
ERTS_BIF_PREP_RET(result, ret);
break;
case DB_ERROR_SYSRES:
- ERTS_BIF_PREP_ERROR(result, BIF_P, SYSTEM_LIMIT);
+ ERTS_BIF_PREP_ERROR(result, p, SYSTEM_LIMIT);
break;
default:
- ERTS_BIF_PREP_ERROR(result, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(result, p, BADARG);
break;
}
- erts_match_set_release_result(BIF_P);
+ erts_match_set_release_result(p);
return result;
}
/* We get here instead of in the real BIF when trapping */
-static BIF_RETTYPE ets_select_trap_1(Process *p, Eterm a1)
+static BIF_RETTYPE ets_select_trap_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2248,6 +2283,11 @@ static BIF_RETTYPE ets_select_trap_1(Process *p, Eterm a1)
BIF_RETTYPE ets_select_1(BIF_ALIST_1)
{
+ return ets_select1(BIF_P, BIF_ARG_1);
+}
+
+static BIF_RETTYPE ets_select1(Process *p, Eterm arg1)
+{
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2261,28 +2301,27 @@ BIF_RETTYPE ets_select_1(BIF_ALIST_1)
* Make sure that the table exists.
*/
- if (!is_tuple(BIF_ARG_1)) {
- if (BIF_ARG_1 == am_EOT) {
+ if (!is_tuple(arg1)) {
+ if (arg1 == am_EOT) {
BIF_RET(am_EOT);
}
- BIF_ERROR(BIF_P, BADARG);
+ BIF_ERROR(p, BADARG);
}
- tptr = tuple_val(BIF_ARG_1);
+ tptr = tuple_val(arg1);
if (arityval(*tptr) < 1 ||
- (tb = db_get_table(BIF_P, tptr[1], DB_READ, LCK_READ)) == NULL) {
- BIF_ERROR(BIF_P, BADARG);
+ (tb = db_get_table(p, tptr[1], DB_READ, LCK_READ)) == NULL) {
+ BIF_ERROR(p, BADARG);
}
- safety = ITERATION_SAFETY(BIF_P,tb);
+ safety = ITERATION_SAFETY(p,tb);
if (safety == ITER_UNSAFE) {
local_fix_table(tb);
}
- cret = tb->common.meth->db_select_continue(BIF_P,tb,
- BIF_ARG_1, &ret);
+ cret = tb->common.meth->db_select_continue(p,tb, arg1, &ret);
- if (DID_TRAP(BIF_P,ret) && safety != ITER_SAFE) {
- fix_table_locked(BIF_P, tb);
+ if (DID_TRAP(p,ret) && safety != ITER_SAFE) {
+ fix_table_locked(p, tb);
}
if (safety == ITER_UNSAFE) {
local_unfix_table(tb);
@@ -2294,20 +2333,26 @@ BIF_RETTYPE ets_select_1(BIF_ALIST_1)
ERTS_BIF_PREP_RET(result, ret);
break;
case DB_ERROR_SYSRES:
- ERTS_BIF_PREP_ERROR(result, BIF_P, SYSTEM_LIMIT);
+ ERTS_BIF_PREP_ERROR(result, p, SYSTEM_LIMIT);
break;
default:
- ERTS_BIF_PREP_ERROR(result, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(result, p, BADARG);
break;
}
- erts_match_set_release_result(BIF_P);
+ erts_match_set_release_result(p);
return result;
}
BIF_RETTYPE ets_select_2(BIF_ALIST_2)
{
+ return ets_select2(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+static BIF_RETTYPE
+ets_select2(Process* p, Eterm arg1, Eterm arg2)
+{
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2320,19 +2365,19 @@ BIF_RETTYPE ets_select_2(BIF_ALIST_2)
* Make sure that the table exists.
*/
- if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_READ, LCK_READ)) == NULL) {
- BIF_ERROR(BIF_P, BADARG);
+ if ((tb = db_get_table(p, arg1, DB_READ, LCK_READ)) == NULL) {
+ BIF_ERROR(p, BADARG);
}
- safety = ITERATION_SAFETY(BIF_P,tb);
+ safety = ITERATION_SAFETY(p,tb);
if (safety == ITER_UNSAFE) {
local_fix_table(tb);
}
- cret = tb->common.meth->db_select(BIF_P, tb, BIF_ARG_2,
+ cret = tb->common.meth->db_select(p, tb, arg2,
0, &ret);
- if (DID_TRAP(BIF_P,ret) && safety != ITER_SAFE) {
- fix_table_locked(BIF_P, tb);
+ if (DID_TRAP(p,ret) && safety != ITER_SAFE) {
+ fix_table_locked(p, tb);
}
if (safety == ITER_UNSAFE) {
local_unfix_table(tb);
@@ -2344,21 +2389,23 @@ BIF_RETTYPE ets_select_2(BIF_ALIST_2)
ERTS_BIF_PREP_RET(result, ret);
break;
case DB_ERROR_SYSRES:
- ERTS_BIF_PREP_ERROR(result, BIF_P, SYSTEM_LIMIT);
+ ERTS_BIF_PREP_ERROR(result, p, SYSTEM_LIMIT);
break;
default:
- ERTS_BIF_PREP_ERROR(result, BIF_P, BADARG);
+ ERTS_BIF_PREP_ERROR(result, p, BADARG);
break;
}
- erts_match_set_release_result(BIF_P);
+ erts_match_set_release_result(p);
return result;
}
/* We get here instead of in the real BIF when trapping */
-static BIF_RETTYPE ets_select_count_1(Process *p, Eterm a1)
+static BIF_RETTYPE ets_select_count_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
BIF_RETTYPE result;
DbTable* tb;
int cret;
@@ -2499,7 +2546,7 @@ BIF_RETTYPE ets_select_reverse_3(BIF_ALIST_3)
BIF_RETTYPE ets_select_reverse_1(BIF_ALIST_1)
{
- return ets_select_1(BIF_P, BIF_ARG_1);
+ return ets_select1(BIF_P, BIF_ARG_1);
}
BIF_RETTYPE ets_select_reverse_2(BIF_ALIST_2)
@@ -2553,7 +2600,7 @@ BIF_RETTYPE ets_select_reverse_2(BIF_ALIST_2)
*/
BIF_RETTYPE ets_match_object_1(BIF_ALIST_1)
{
- return ets_select_1(BIF_P, BIF_ARG_1);
+ return ets_select1(BIF_P, BIF_ARG_1);
}
BIF_RETTYPE ets_match_object_2(BIF_ALIST_2)
@@ -2569,7 +2616,7 @@ BIF_RETTYPE ets_match_object_2(BIF_ALIST_2)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_2(BIF_P, BIF_ARG_1, ms);
+ res = ets_select2(BIF_P, BIF_ARG_1, ms);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2587,7 +2634,7 @@ BIF_RETTYPE ets_match_object_3(BIF_ALIST_3)
ms = TUPLE3(hp, BIF_ARG_2, NIL, ms);
hp += 4;
ms = CONS(hp, ms, NIL);
- res = ets_select_3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
+ res = ets_select3(BIF_P, BIF_ARG_1, ms, BIF_ARG_3);
UnUseTmpHeap(8,BIF_P);
return res;
}
@@ -2606,7 +2653,9 @@ BIF_RETTYPE ets_info_1(BIF_ALIST_1)
int i;
Eterm* hp;
/*Process* rp = NULL;*/
+ /* If/when we implement lockless private tables:
Eterm owner;
+ */
if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_INFO, LCK_READ)) == NULL) {
if (is_atom(BIF_ARG_1) || is_small(BIF_ARG_1)) {
@@ -2615,7 +2664,9 @@ BIF_RETTYPE ets_info_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
+ /* If/when we implement lockless private tables:
owner = tb->common.owner;
+ */
/* If/when we implement lockless private tables:
if ((tb->common.status & DB_PRIVATE) && owner != BIF_P->id) {
@@ -2802,10 +2853,10 @@ void init_db(void)
bits = erts_fit_in_bits(db_max_tabs-1);
if (bits > SMALL_BITS) {
erl_exit(1,"Max limit for ets tabled too high %u (max %u).",
- db_max_tabs, 1L<<SMALL_BITS);
+ db_max_tabs, ((Uint)1)<<SMALL_BITS);
}
- meta_main_tab_slot_mask = (1L<<bits) - 1;
- meta_main_tab_seq_incr = (1L<<bits);
+ meta_main_tab_slot_mask = (((Uint)1)<<bits) - 1;
+ meta_main_tab_seq_incr = (((Uint)1)<<bits);
size = sizeof(*meta_main_tab)*db_max_tabs;
meta_main_tab = erts_db_alloc_nt(ERTS_ALC_T_DB_TABLES, size);
@@ -2818,7 +2869,7 @@ void init_db(void)
SET_NEXT_FREE_SLOT(db_max_tabs-1, (Uint)-1);
meta_main_tab_first_free = 0;
- meta_name_tab_mask = (1L<<(bits-1)) - 1; /* At least half the size of main tab */
+ meta_name_tab_mask = (((Uint) 1)<<(bits-1)) - 1; /* At least half the size of main tab */
size = sizeof(struct meta_name_tab_entry)*(meta_name_tab_mask+1);
meta_name_tab = erts_db_alloc_nt(ERTS_ALC_T_DB_TABLES, size);
ERTS_ETS_MISC_MEM_ADD(size);
@@ -3521,8 +3572,10 @@ static void free_heir_data(DbTable* tb)
#endif
}
-static BIF_RETTYPE ets_delete_trap(Process *p, Eterm cont)
+static BIF_RETTYPE ets_delete_trap(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm cont = BIF_ARG_1;
int trap;
Eterm* ptr = big_val(cont);
DbTable *tb = *((DbTable **) (UWord) (ptr + 1));
@@ -3763,7 +3816,7 @@ void db_info(int to, void *to_arg, int show) /* Called by break handler */
Uint
erts_get_ets_misc_mem_size(void)
{
- ERTS_THR_MEMORY_BARRIER;
+ ERTS_SMP_MEMORY_BARRIER;
/* Memory not allocated in ets_alloc */
return (Uint) erts_smp_atomic_read_nob(&erts_ets_misc_mem_size);
}
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index e3380a57b2..2fea4671e1 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -105,10 +105,19 @@
#define NSEG_2 256 /* Size of second segment table */
#define NSEG_INC 128 /* Number of segments to grow after that */
+#ifdef ERTS_SMP
+# define DB_USING_FINE_LOCKING(TB) (((TB))->common.type & DB_FINE_LOCKED)
+#else
+# define DB_USING_FINE_LOCKING(TB) 0
+#endif
+
#ifdef ETHR_ORDERED_READ_DEPEND
-#define SEGTAB(tb) ((struct segment**)erts_smp_atomic_read_nob(&(tb)->segtab))
+#define SEGTAB(tb) ((struct segment**) erts_smp_atomic_read_nob(&(tb)->segtab))
#else
-#define SEGTAB(tb) ((struct segment**)erts_smp_atomic_read_rb(&(tb)->segtab))
+#define SEGTAB(tb) \
+ (DB_USING_FINE_LOCKING(tb) \
+ ? ((struct segment**) erts_smp_atomic_read_ddrb(&(tb)->segtab)) \
+ : ((struct segment**) erts_smp_atomic_read_nob(&(tb)->segtab)))
#endif
#define NACTIVE(tb) ((int)erts_smp_atomic_read_nob(&(tb)->nactive))
#define NITEMS(tb) ((int)erts_smp_atomic_read_nob(&(tb)->common.nitems))
@@ -126,7 +135,9 @@
*/
static ERTS_INLINE Uint hash_to_ix(DbTableHash* tb, HashValue hval)
{
- Uint mask = erts_smp_atomic_read_acqb(&tb->szm);
+ Uint mask = (DB_USING_FINE_LOCKING(tb)
+ ? erts_smp_atomic_read_acqb(&tb->szm)
+ : erts_smp_atomic_read_nob(&tb->szm));
Uint ix = hval & mask;
if (ix >= erts_smp_atomic_read_nob(&tb->nactive)) {
ix &= mask>>1;
@@ -312,15 +323,27 @@ struct ext_segment {
struct segment* segtab[1]; /* The segment table */
};
#define SIZEOF_EXTSEG(NSEGS) \
- (sizeof(struct ext_segment) - sizeof(struct segment*) + sizeof(struct segment*)*(NSEGS))
+ (offsetof(struct ext_segment,segtab) + sizeof(struct segment*)*(NSEGS))
-#ifdef DEBUG
-# include <stddef.h> /* offsetof */
+#if defined(DEBUG) || defined(VALGRIND)
# define EXTSEG(SEGTAB_PTR) \
((struct ext_segment*) (((char*)(SEGTAB_PTR)) - offsetof(struct ext_segment,segtab)))
#endif
+static ERTS_INLINE void SET_SEGTAB(DbTableHash* tb,
+ struct segment** segtab)
+{
+ if (DB_USING_FINE_LOCKING(tb))
+ erts_smp_atomic_set_wb(&tb->segtab, (erts_aint_t) segtab);
+ else
+ erts_smp_atomic_set_nob(&tb->segtab, (erts_aint_t) segtab);
+#ifdef VALGRIND
+ tb->top_ptr_to_segment_with_active_segtab = EXTSEG(segtab);
+#endif
+}
+
+
/* How the table segments relate to each other:
ext_segment: ext_segment: "plain" segment
@@ -649,7 +672,8 @@ int db_create_hash(Process *p, DbTable *tbl)
erts_smp_atomic_init_nob(&tb->szm, SEGSZ_MASK);
erts_smp_atomic_init_nob(&tb->nactive, SEGSZ);
erts_smp_atomic_init_nob(&tb->fixdel, (erts_aint_t)NULL);
- erts_smp_atomic_init_nob(&tb->segtab, (erts_aint_t) alloc_ext_seg(tb,0,NULL)->segtab);
+ erts_smp_atomic_init_nob(&tb->segtab, (erts_aint_t)NULL);
+ SET_SEGTAB(tb, alloc_ext_seg(tb,0,NULL)->segtab);
tb->nsegs = NSEG_1;
tb->nslots = SEGSZ;
@@ -2357,7 +2381,7 @@ static int alloc_seg(DbTableHash *tb)
struct ext_segment* eseg;
eseg = (struct ext_segment*) SEGTAB(tb)[seg_ix-1];
MY_ASSERT(eseg!=NULL && eseg->s.is_ext_segment);
- erts_smp_atomic_set_wb(&tb->segtab, (erts_aint_t) eseg->segtab);
+ SET_SEGTAB(tb, eseg->segtab);
tb->nsegs = eseg->nsegs;
}
ASSERT(seg_ix < tb->nsegs);
@@ -2429,7 +2453,7 @@ static int free_seg(DbTableHash *tb, int free_records)
MY_ASSERT(newtop->s.is_ext_segment);
if (newtop->prev_segtab != NULL) {
/* Time to use a smaller segtab */
- erts_smp_atomic_set_wb(&tb->segtab, (erts_aint_t)newtop->prev_segtab);
+ SET_SEGTAB(tb, newtop->prev_segtab);
tb->nsegs = seg_ix;
ASSERT(tb->nsegs == EXTSEG(SEGTAB(tb))->nsegs);
}
@@ -2446,7 +2470,7 @@ static int free_seg(DbTableHash *tb, int free_records)
if (seg_ix > 0) {
if (seg_ix < tb->nsegs) SEGTAB(tb)[seg_ix] = NULL;
} else {
- erts_smp_atomic_set_wb(&tb->segtab, (erts_aint_t)NULL);
+ SET_SEGTAB(tb, NULL);
}
#endif
tb->nslots -= SEGSZ;
@@ -2495,6 +2519,28 @@ static Eterm build_term_list(Process* p, HashDbTerm* ptr1, HashDbTerm* ptr2,
return list;
}
+static ERTS_INLINE int
+begin_resizing(DbTableHash* tb)
+{
+ if (DB_USING_FINE_LOCKING(tb))
+ return !erts_smp_atomic_xchg_acqb(&tb->is_resizing, 1);
+ else {
+ if (erts_smp_atomic_read_nob(&tb->is_resizing))
+ return 0;
+ erts_smp_atomic_set_nob(&tb->is_resizing, 1);
+ return 1;
+ }
+}
+
+static ERTS_INLINE void
+done_resizing(DbTableHash* tb)
+{
+ if (DB_USING_FINE_LOCKING(tb))
+ erts_smp_atomic_set_relb(&tb->is_resizing, 0);
+ else
+ erts_smp_atomic_set_nob(&tb->is_resizing, 0);
+}
+
/* Grow table with one new bucket.
** Allocate new segment if needed.
*/
@@ -2507,9 +2553,8 @@ static void grow(DbTableHash* tb, int nactive)
int from_ix;
int szm;
- if (erts_smp_atomic_xchg_acqb(&tb->is_resizing, 1)) {
+ if (!begin_resizing(tb))
return; /* already in progress */
- }
if (NACTIVE(tb) != nactive) {
goto abort; /* already done (race) */
}
@@ -2541,9 +2586,12 @@ static void grow(DbTableHash* tb, int nactive)
}
erts_smp_atomic_inc_nob(&tb->nactive);
if (from_ix == 0) {
- erts_smp_atomic_set_relb(&tb->szm, szm);
+ if (DB_USING_FINE_LOCKING(tb))
+ erts_smp_atomic_set_relb(&tb->szm, szm);
+ else
+ erts_smp_atomic_set_nob(&tb->szm, szm);
}
- erts_smp_atomic_set_relb(&tb->is_resizing, 0);
+ done_resizing(tb);
/* Finally, let's split the bucket. We try to do it in a smart way
to keep link order and avoid unnecessary updates of next-pointers */
@@ -2575,7 +2623,7 @@ static void grow(DbTableHash* tb, int nactive)
return;
abort:
- erts_smp_atomic_set_relb(&tb->is_resizing, 0);
+ done_resizing(tb);
}
@@ -2584,9 +2632,8 @@ abort:
*/
static void shrink(DbTableHash* tb, int nactive)
{
- if (erts_smp_atomic_xchg_acqb(&tb->is_resizing, 1)) {
+ if (!begin_resizing(tb))
return; /* already in progress */
- }
if (NACTIVE(tb) == nactive) {
erts_smp_rwmtx_t* lck;
int src_ix = nactive - 1;
@@ -2633,7 +2680,7 @@ static void shrink(DbTableHash* tb, int nactive)
}
/*else already done */
- erts_smp_atomic_set_relb(&tb->is_resizing, 0);
+ done_resizing(tb);
}
diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h
index e0285fa5ed..cddd8dfadd 100644
--- a/erts/emulator/beam/erl_db_hash.h
+++ b/erts/emulator/beam/erl_db_hash.h
@@ -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
@@ -58,6 +58,9 @@ typedef struct db_table_hash {
#ifdef ERTS_SMP
DbTableHashFineLocks* locks;
#endif
+#ifdef VALGRIND
+ struct ext_segment* top_ptr_to_segment_with_active_segtab;
+#endif
} DbTableHash;
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index c6f0d80e32..312050b931 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -344,8 +344,8 @@ static int do_partly_bound_can_match_lesser(Eterm a, Eterm b,
int *done);
static int do_partly_bound_can_match_greater(Eterm a, Eterm b,
int *done);
-static BIF_RETTYPE ets_select_reverse(Process *p, Eterm a1,
- Eterm a2, Eterm a3);
+static BIF_RETTYPE ets_select_reverse(BIF_ALIST_3);
+
/* Method interface functions */
static int db_first_tree(Process *p, DbTable *tbl,
@@ -844,8 +844,12 @@ static int db_slot_tree(Process *p, DbTable *tbl,
-static BIF_RETTYPE ets_select_reverse(Process *p, Eterm a1, Eterm a2, Eterm a3)
+static BIF_RETTYPE ets_select_reverse(BIF_ALIST_3)
{
+ Process *p = BIF_P;
+ Eterm a1 = BIF_ARG_1;
+ Eterm a2 = BIF_ARG_2;
+ Eterm a3 = BIF_ARG_3;
Eterm list;
Eterm result;
Eterm* hp;
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 7dfbb2ed02..42907e2e84 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -35,6 +35,7 @@
#include "bif.h"
#include "big.h"
#include "erl_binary.h"
+#include "erl_thr_progress.h"
#include "erl_db_util.h"
@@ -495,7 +496,7 @@ static erts_smp_atomic32_t trace_control_word;
/* This needs to be here, before the bif table... */
-static Eterm db_set_trace_control_word_fake_1(Process *p, Eterm val);
+static Eterm db_set_trace_control_word_fake_1(BIF_ALIST_1);
/*
** The table of callable bif's, i e guard bif's and
@@ -908,14 +909,18 @@ static void db_free_tmp_uncompressed(DbTerm* obj);
/*
** Pseudo BIF:s to be callable from the PAM VM.
*/
-
-BIF_RETTYPE db_get_trace_control_word_0(Process *p)
+BIF_RETTYPE db_get_trace_control_word(Process *p)
{
Uint32 tcw = (Uint32) erts_smp_atomic32_read_acqb(&trace_control_word);
BIF_RET(erts_make_integer((Uint) tcw, p));
}
-BIF_RETTYPE db_set_trace_control_word_1(Process *p, Eterm new)
+BIF_RETTYPE db_get_trace_control_word_0(BIF_ALIST_0)
+{
+ BIF_RET(db_get_trace_control_word(BIF_P));
+}
+
+BIF_RETTYPE db_set_trace_control_word(Process *p, Eterm new)
{
Uint val;
Uint32 old_tcw;
@@ -923,20 +928,27 @@ BIF_RETTYPE db_set_trace_control_word_1(Process *p, Eterm new)
BIF_ERROR(p, BADARG);
if (val != ((Uint32)val))
BIF_ERROR(p, BADARG);
-
+
old_tcw = (Uint32) erts_smp_atomic32_xchg_relb(&trace_control_word,
(erts_aint32_t) val);
BIF_RET(erts_make_integer((Uint) old_tcw, p));
}
-static Eterm db_set_trace_control_word_fake_1(Process *p, Eterm new)
+BIF_RETTYPE db_set_trace_control_word_1(BIF_ALIST_1)
{
+ BIF_RET(db_set_trace_control_word(BIF_P, BIF_ARG_1));
+}
+
+static Eterm db_set_trace_control_word_fake_1(BIF_ALIST_1)
+{
+ Process *p = BIF_P;
+ Eterm new = BIF_ARG_1;
Uint val;
if (!term_to_Uint(new, &val))
BIF_ERROR(p, BADARG);
if (val != ((Uint32)val))
BIF_ERROR(p, BADARG);
- BIF_RET(db_get_trace_control_word_0(p));
+ BIF_RET(db_get_trace_control_word(p));
}
/*
@@ -1221,7 +1233,7 @@ static Eterm erts_match_set_run_ets(Process *p, Binary *mpsp,
Eterm ret;
ret = db_prog_match(p, mpsp, args, NULL, NULL, num_args,
- ERTS_PAM_CONTIGUOUS_TUPLE | ERTS_PAM_COPY_RESULT,
+ ERTS_PAM_COPY_RESULT,
return_flags);
#if defined(HARDDEBUG)
if (is_non_value(ret)) {
@@ -1704,6 +1716,7 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
Process *current_scheduled;
ErtsSchedulerData *esdp;
Eterm (*bif)(Process*, ...);
+ Eterm bif_args[3];
int fail_label;
int atomic_trace;
#if HALFWORD_HEAP
@@ -1734,14 +1747,14 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
if (! atomic_trace) { \
erts_refc_inc(&bprog->refc, 2); \
erts_smp_proc_unlock((p), ERTS_PROC_LOCK_MAIN); \
- erts_smp_block_system(0); \
+ erts_smp_thr_progress_block(); \
atomic_trace = !0; \
} \
} while (0)
#define END_ATOMIC_TRACE(p) \
do { \
if (atomic_trace) { \
- erts_smp_release_system(); \
+ erts_smp_thr_progress_unblock(); \
erts_smp_proc_lock((p), ERTS_PROC_LOCK_MAIN); \
if (erts_refc_dectest(&bprog->refc, 0) == 0) {\
erts_bin_free(bprog); \
@@ -1957,7 +1970,7 @@ restart:
break;
case matchCall0:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc);
+ t = (*bif)(build_proc, bif_args);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -1968,7 +1981,7 @@ restart:
break;
case matchCall1:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc, esp[-1]);
+ t = (*bif)(build_proc, esp-1);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -1979,7 +1992,9 @@ restart:
break;
case matchCall2:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc, esp[-1], esp[-2]);
+ bif_args[0] = esp[-1];
+ bif_args[1] = esp[-2];
+ t = (*bif)(build_proc, bif_args);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -1991,7 +2006,10 @@ restart:
break;
case matchCall3:
bif = (Eterm (*)(Process*, ...)) *pc++;
- t = (*bif)(build_proc, esp[-1], esp[-2], esp[-3]);
+ bif_args[0] = esp[-1];
+ bif_args[1] = esp[-2];
+ bif_args[2] = esp[-3];
+ t = (*bif)(build_proc, bif_args);
if (is_non_value(t)) {
if (do_catch)
t = FAIL_TERM;
@@ -2185,7 +2203,11 @@ restart:
*esp++ = am_true;
break;
case matchIsSeqTrace:
- if (SEQ_TRACE_TOKEN(c_p) != NIL)
+ if (SEQ_TRACE_TOKEN(c_p) != NIL
+#ifdef USE_VM_PROBES
+ && SEQ_TRACE_TOKEN(c_p) != am_have_dt_utag
+#endif
+ )
*esp++ = am_true;
else
*esp++ = am_false;
@@ -2209,7 +2231,11 @@ restart:
--esp;
break;
case matchGetSeqToken:
- if (SEQ_TRACE_TOKEN(c_p) == NIL)
+ if (SEQ_TRACE_TOKEN(c_p) == NIL
+#ifdef USE_VM_PROBES
+ || SEQ_TRACE_TOKEN(c_p) == am_have_dt_utag
+#endif
+ )
*esp++ = NIL;
else {
Eterm sender = SEQ_TRACE_TOKEN_SENDER(c_p);
@@ -2846,7 +2872,9 @@ void* db_store_term_comp(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
Uint new_sz = offset + db_size_dbterm_comp(tb, obj);
byte* basep;
DbTerm* newp;
+#ifdef DEBUG
byte* top;
+#endif
ASSERT(tb->compress);
if (old != 0) {
@@ -2868,7 +2896,10 @@ void* db_store_term_comp(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
}
newp->size = size_object(obj);
- top = copy_to_comp(tb, obj, newp, new_sz);
+#ifdef DEBUG
+ top =
+#endif
+ copy_to_comp(tb, obj, newp, new_sz);
ASSERT(top <= basep + new_sz);
/* ToDo: Maybe realloc if ((basep+new_sz) - top) > WASTED_SPACE_LIMIT */
@@ -2964,7 +2995,7 @@ Eterm db_copy_from_comp(DbTableCommon* tb, DbTerm* bp, Eterm** hpp,
}
ASSERT((*hpp - hp) <= bp->size);
#ifdef DEBUG_CLONE
- ASSERT(eq_rel(make_tuple(hp),make_tuple(bp->debug_clone),bp->debug_clone));
+ ASSERT(eq_rel(make_tuple(hp),NULL,make_tuple(bp->debug_clone),bp->debug_clone));
#endif
return make_tuple(hp);
}
@@ -2987,7 +3018,7 @@ Eterm db_copy_element_from_ets(DbTableCommon* tb, Process* p,
hp += extra;
HRelease(p, endp, hp);
#ifdef DEBUG_CLONE
- ASSERT(eq_rel(copy, obj->debug_clone[pos], obj->debug_clone));
+ ASSERT(eq_rel(copy, NULL, obj->debug_clone[pos], obj->debug_clone));
#endif
return copy;
}
@@ -4970,7 +5001,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace)
static Eterm seq_trace_fake(Process *p, Eterm arg1)
{
- Eterm result = seq_trace_info_1(p,arg1);
+ Eterm result = erl_seq_trace_info(p, arg1);
if (is_tuple(result) && *tuple_val(result) == 2) {
return (tuple_val(result))[2];
}
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index bb1751d309..6a96e174e1 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -326,8 +326,10 @@ ERTS_GLB_INLINE int db_eq(DbTableCommon* tb, Eterm a, DbTerm* b)
(T)->common.owner == (P)->id)
/* Function prototypes */
-Eterm db_get_trace_control_word_0(Process *p);
-Eterm db_set_trace_control_word_1(Process *p, Eterm val);
+BIF_RETTYPE db_get_trace_control_word(Process* p);
+BIF_RETTYPE db_set_trace_control_word(Process* p, Eterm tcw);
+BIF_RETTYPE db_get_trace_control_word_0(BIF_ALIST_0);
+BIF_RETTYPE db_set_trace_control_word_1(BIF_ALIST_1);
void db_initialize_util(void);
Eterm db_getkey(int keypos, Eterm obj);
diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c
index d7d6fcf0a2..2121f72fd2 100644
--- a/erts/emulator/beam/erl_debug.c
+++ b/erts/emulator/beam/erl_debug.c
@@ -25,7 +25,6 @@
#include "erl_vm.h"
#include "global.h"
#include "erl_process.h"
-#include "erl_nmgc.h"
#include "big.h"
#include "bif.h"
#include "beam_catches.h"
@@ -33,34 +32,9 @@
#define WITHIN(ptr, x, y) ((x) <= (ptr) && (ptr) < (y))
-#if defined(HYBRID)
-#if defined(INCREMENTAL)
-/* Hybrid + Incremental */
-#define IN_HEAP(p, ptr) \
- (WITHIN((ptr), p->heap, p->hend) || \
- (OLD_HEAP(p) && WITHIN((ptr), OLD_HEAP(p), OLD_HEND(p))) || \
- WITHIN((ptr), global_heap, global_hend) || \
- (inc_fromspc && WITHIN((ptr), inc_fromspc, inc_fromend)) || \
- WITHIN((ptr), global_old_heap, global_old_hend))
-
-#define IN_MA(ptr) \
- (WITHIN((ptr), global_heap, global_hend) || \
- (inc_fromspc && WITHIN((ptr), inc_fromspc, inc_fromend)) || \
- WITHIN((ptr), global_old_heap, global_old_hend))
-#else
-/* Hybrid */
-#define IN_HEAP(p, ptr) \
- (WITHIN((ptr), p->heap, p->hend) || \
- (OLD_HEAP(p) && WITHIN((ptr), OLD_HEAP(p), OLD_HEND(p))) || \
- WITHIN((ptr), global_heap, global_hend) || \
- (global_old_heap && WITHIN((ptr),global_old_heap,global_old_hend)))
-#endif
-#else
-/* Private */
#define IN_HEAP(p, ptr) \
(WITHIN((ptr), p->heap, p->hend) || \
(OLD_HEAP(p) && WITHIN((ptr), OLD_HEAP(p), OLD_HEND(p))))
-#endif
#ifdef __GNUC__
@@ -266,13 +240,6 @@ static int verify_eterm(Process *p,Eterm element)
}
}
}
-#ifdef INCREMENTAL
- else {
- if (IN_MA(ptr))
- return 1;
- }
-#endif
-
return 0;
}
@@ -447,51 +414,12 @@ void verify_process(Process *p)
VERIFY_ETERM("fvalue",p->fvalue);
VERIFY_ETERM("ftrace",p->ftrace);
-#ifdef HYBRID
- VERIFY_AREA("rrma",p->rrma,p->nrr);
-#endif
-
VERBOSE(DEBUG_MEMORY,("...done\n"));
#undef VERIFY_AREA
#undef VERIFY_ETERM
}
-void verify_everything()
-{
-#ifdef HYBRID
- Uint i;
- Uint n = erts_num_active_procs;
-
-#ifdef INCREMENTAL_FREE_SIZES_NEEDS_TO_BE_TAGGED_AS_HEADERS_WITH_ARITY
- INC_Page *page = inc_used_mem;
-#endif
-
- for (i = 0; i < n; i++) {
- verify_process(erts_active_procs[i]);
- }
-
- erts_check_memory(NULL,global_heap,global_htop);
-
-#ifdef INCREMENTAL_FREE_SIZES_NEEDS_TO_BE_TAGGED_AS_HEADERS_WITH_ARITY
- while (page)
- {
- Eterm *end = page + INC_PAGE_SIZE;
- Eterm *pos = page->start;
-
- while( pos < end) {
- Eterm val = *pos++;
- if(is_header(val))
- pos += thing_arityval(val);
- else
- verify_eterm(NULL,val);
- }
- page = page->next;
- }
-#endif
-#endif /* HYBRID */
-}
-
/*
* print_untagged_memory will print the contents of given memory area.
*/
@@ -582,83 +510,6 @@ void print_tagged_memory(Eterm *pos, Eterm *end)
erts_printf("+-%s-+-%s-+\n",dashes,dashes);
}
-#ifdef HYBRID
-void print_ma_info(void)
-{
- erts_printf("Message Area (start - top - end): "
- "0x%0*lx - 0x%0*lx - 0x%0*lx\n",
- PTR_SIZE, (unsigned long)global_heap,
- PTR_SIZE, (unsigned long)global_htop,
- PTR_SIZE, (unsigned long)global_hend);
-#ifndef INCREMENTAL
- erts_printf(" High water: 0x%0*lx "
- "Old gen: 0x%0*lx - 0x%0*lx - 0x%0*lx\n",
- PTR_SIZE, (unsigned long)global_high_water,
- PTR_SIZE, (unsigned long)global_old_heap,
- PTR_SIZE, (unsigned long)global_old_htop,
- PTR_SIZE, (unsigned long)global_old_hend);
-#endif
-}
-
-void print_message_area(void)
-{
- Eterm *pos = global_heap;
- Eterm *end = global_htop;
-
- erts_printf("From: 0x%0*lx to 0x%0*lx\n",
- PTR_SIZE,(unsigned long)pos,PTR_SIZE,(unsigned long)end);
- erts_printf("(Old generation: 0x%0*lx to 0x%0*lx\n",
- PTR_SIZE, (unsigned long)global_old_heap,
- PTR_SIZE, (unsigned long)global_old_hend);
- erts_printf("| %-*s | %-*s |\n",PTR_SIZE,"Address",PTR_SIZE,"Contents");
- erts_printf("|-%s-|-%s-|\n",dashes,dashes);
- while( pos < end ) {
- Eterm val = pos[0];
- erts_printf("| 0x%0*lx | 0x%0*lx | ",
- PTR_SIZE,(unsigned long)pos,PTR_SIZE,(unsigned long)val);
- ++pos;
- if( is_arity_value(val) ) {
- erts_printf("Arity(%lu)", arityval(val));
- } else if( is_thing(val) ) {
- unsigned int ari = thing_arityval(val);
- erts_printf("Thing Arity(%u) Tag(%lu)", ari, thing_subtag(val));
- while( ari ) {
- erts_printf("\n| 0x%0*lx | 0x%0*lx | THING",
- PTR_SIZE, (unsigned long)pos,
- PTR_SIZE, (unsigned long)*pos);
- ++pos;
- --ari;
- }
- } else
- erts_printf("%.30T", val);
- erts_printf("\n");
- }
- erts_printf("+-%s-+-%s-+\n",dashes,dashes);
-}
-
-void check_message_area()
-{
- Eterm *pos = global_heap;
- Eterm *end = global_htop;
-
- while( pos < end ) {
- Eterm val = *pos++;
- if(is_header(val))
- pos += thing_arityval(val);
- else if(!is_immed(val))
- if ((ptr_val(val) < global_heap || ptr_val(val) >= global_htop) &&
- (ptr_val(val) < global_old_heap ||
- ptr_val(val) >= global_old_hend))
- {
- erts_printf("check_message_area: Stray pointer found\n");
- print_message_area();
- erts_printf("Crashing to make it look real...\n");
- pos = 0;
- }
- }
-}
-#endif /* HYBRID */
-
static void print_process_memory(Process *p);
static void print_process_memory(Process *p)
{
@@ -703,19 +554,6 @@ static void print_process_memory(Process *p)
erts_printf(" Fvalue: 0x%0*lx\n",PTR_SIZE,p->fvalue);
erts_printf(" Ftrace: 0x%0*lx\n",PTR_SIZE,p->ftrace);
-#ifdef HYBRID
- if (p->nrr > 0) {
- int i;
- erts_printf(" Remembered Roots:\n");
- for (i = 0; i < p->nrr; i++)
- if (p->rrsrc[i] != NULL)
- erts_printf("0x%0*lx -> 0x%0*lx\n",
- PTR_SIZE, (unsigned long)p->rrsrc[i],
- PTR_SIZE, (unsigned long)p->rrma[i]);
- erts_printf("\n");
- }
-#endif
-
erts_printf("+- %-*s -+ 0x%0*lx 0x%0*lx %s-%s-+\n",
PTR_SIZE, "Stack",
PTR_SIZE, (unsigned long)STACK_TOP(p),
@@ -757,92 +595,6 @@ void print_memory(Process *p)
if (p != NULL) {
print_process_memory(p);
}
-#ifdef HYBRID
- else {
- Uint i;
- Uint n = erts_num_active_procs;
-
- for (i = 0; i < n; i++) {
- Process *p = erts_active_procs[i];
- print_process_memory(p);
- }
-
- erts_printf("==================\n");
- erts_printf("|| Message area ||\n");
- erts_printf("==================\n");
- erts_printf("+-%s-+-%s-%s-%s-%s-+\n",
- dashes,dashes,dashes,dashes,dashes);
- erts_printf("| %-*s | 0x%0*lx - 0x%0*lx - 0x%0*lx%*s|\n",
- PTR_SIZE, "Young",
- PTR_SIZE, (unsigned long)global_heap,
- PTR_SIZE, (unsigned long)global_htop,
- PTR_SIZE, (unsigned long)global_hend,
- PTR_SIZE, "");
- erts_printf("+-%s-+-%s-%s-%s-%s-+\n",
- dashes,dashes,dashes,dashes,dashes);
-
- print_untagged_memory(global_heap,global_htop);
-
-
- erts_printf("+-%s-+-%s-%s-%s-%s-+\n",
- dashes,dashes,dashes,dashes,dashes);
- erts_printf("| %-*s | 0x%0*lx - 0x%0*lx %*s |\n",
- PTR_SIZE, "Old",
- PTR_SIZE, (unsigned long)global_old_heap,
- PTR_SIZE, (unsigned long)global_old_hend,
- 2 * PTR_SIZE, "");
- erts_printf("+-%s-+-%s-%s-%s-%s-+\n",
- dashes,dashes,dashes,dashes,dashes);
-
-#ifdef INCREMENTAL
- {
- INC_Page *page = inc_used_mem;
- /* Genom att g� igenom fri-listan f�rst kan vi markera de
- omr�den som inte �r allokerade och bara skriva ut de som
- lever.
- char markarea[INC_PAGESIZE];
- */
-
- while (page) {
- Eterm *ptr = (Eterm*)page->start;
- Eterm *end = (Eterm*)page->start + INC_PAGESIZE;
-
- erts_printf("| %*s | This: 0x%0*lx Next: 0x%0*lx %*s|\n",
- PTR_SIZE, "",
- PTR_SIZE, (unsigned long)page,
- PTR_SIZE, (unsigned long)page->next,
- 2 * PTR_SIZE - 8, "");
- print_untagged_memory(ptr,end);
- page = page->next;
- }
- }
-
- {
- INC_MemBlock *this = inc_free_list;
-
- erts_printf("-- %-*s --%s-%s-%s-%s-\n",PTR_SIZE+2,"Free list",
- dashes,dashes,dashes,dashes);
- while (this) {
- erts_printf("Block @ 0x%0*lx sz: %8d prev: 0x%0*lx next: 0x%0*lx\n",
- PTR_SIZE, (unsigned long)this,this->size,
- PTR_SIZE, (unsigned long)this->prev,
- PTR_SIZE, (unsigned long)this->next);
- this = this->next;
- }
- erts_printf("--%s---%s-%s-%s-%s--\n",
- dashes,dashes,dashes,dashes,dashes);
- }
-
- if (inc_fromspc != NULL) {
- erts_printf("-- fromspace - 0x%0*lx 0x%0*lx "
- "------------------------------\n",
- PTR_SIZE, (unsigned long)inc_fromspc,
- PTR_SIZE, (unsigned long)inc_fromend);
- print_untagged_memory(inc_fromspc,inc_fromend);
- }
-#endif /* INCREMENTAL */
- }
-#endif /* HYBRID */
}
void print_memory_info(Process *p)
@@ -869,26 +621,6 @@ void print_memory_info(Process *p)
erts_printf("|| Memory info ||\n");
erts_printf("=================\n");
}
-#ifdef HYBRID
- erts_printf("|- message area --%s-%s-%s-%s-|\n",
- dashes,dashes,dashes,dashes);
- erts_printf("| Young | 0x%0*lx - 0x%0*lx - 0x%0*lx %*s |\n",
- PTR_SIZE, (unsigned long)global_heap,
- PTR_SIZE, (unsigned long)global_htop,
- PTR_SIZE, (unsigned long)global_hend,
- PTR_SIZE, "");
- erts_printf("| Old | 0x%0*lx - 0x%0*lx %*s |\n",
- PTR_SIZE, (unsigned long)global_old_heap,
- PTR_SIZE, (unsigned long)global_old_hend,
- 2 * PTR_SIZE, "");
-#endif
-#ifdef INCREMENTAL
- if (inc_fromspc != NULL)
- erts_printf("| Frmsp | 0x%0*lx - 0x%0*lx %*s |\n",
- PTR_SIZE, (unsigned long)inc_fromspc,
- PTR_SIZE, (unsigned long)inc_fromend,
- 2 * PTR_SIZE, "");
-#endif
erts_printf("+-----------------%s-%s-%s-%s-+\n",dashes,dashes,dashes,dashes);
}
#if !HEAP_ON_C_STACK && defined(DEBUG)
diff --git a/erts/emulator/beam/erl_debug.h b/erts/emulator/beam/erl_debug.h
index bdfbaddbbf..a028a95fef 100644
--- a/erts/emulator/beam/erl_debug.h
+++ b/erts/emulator/beam/erl_debug.h
@@ -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
@@ -42,16 +42,15 @@
#define DEBUG_DEFAULT 0x0000 /* No flags are set per default */
#define DEBUG_SYSTEM 0x0001 /* Misc system info at startup and end */
#define DEBUG_PRIVATE_GC 0x0002 /* GC of private heaps */
-#define DEBUG_HYBRID_GC 0x0004 /* GC of the message area */
-#define DEBUG_ALLOCATION 0x0008 /* HAlloc. To find holes in the heap */
-#define DEBUG_MESSAGES 0x0010 /* Message passing */
-#define DEBUG_THREADS 0x0020 /* Thread-related stuff */
-#define DEBUG_PROCESSES 0x0040 /* Process creation and removal */
-#define DEBUG_MEMORY 0x0080 /* Display results of memory checks */
+#define DEBUG_ALLOCATION 0x0004 /* HAlloc. To find holes in the heap */
+#define DEBUG_MESSAGES 0x0008 /* Message passing */
+#define DEBUG_THREADS 0x0010 /* Thread-related stuff */
+#define DEBUG_PROCESSES 0x0020 /* Process creation and removal */
+#define DEBUG_MEMORY 0x0040 /* Display results of memory checks */
extern Uint32 verbose;
-void upp(byte*, int);
+void upp(byte*, size_t);
void pat(Eterm);
void pinfo(void);
void pp(Process*);
@@ -88,7 +87,6 @@ extern void erts_check_stack(Process *p);
extern void erts_check_heap(Process *p);
extern void erts_check_memory(Process *p, Eterm *start, Eterm *end);
extern void verify_process(Process *p);
-extern void verify_everything(void);
extern void print_tagged_memory(Eterm *start, Eterm *end);
extern void print_untagged_memory(Eterm *start, Eterm *end);
extern void print_memory(Process *p);
@@ -99,10 +97,4 @@ extern void erts_debug_use_tmp_heap(int, Process *);
extern void erts_debug_unuse_tmp_heap(int, Process *);
#endif
-#ifdef HYBRID
-extern void print_ma_info(void);
-extern void print_message_area(void);
-extern void check_message_area(void);
-#endif
-
#endif /* _ERL_DEBUG_H_ */
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index 401967a8de..1ae9a211d7 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -28,6 +28,14 @@
# include "config.h"
#endif
+#define ERL_DRV_DEPRECATED_FUNC
+#ifdef __GNUC__
+# if __GNUC__ >= 3
+# undef ERL_DRV_DEPRECATED_FUNC
+# define ERL_DRV_DEPRECATED_FUNC __attribute__((deprecated))
+# endif
+#endif
+
#ifdef SIZEOF_CHAR
# define SIZEOF_CHAR_SAVED__ SIZEOF_CHAR
# undef SIZEOF_CHAR
@@ -77,6 +85,7 @@
#include "erl_drv_nif.h"
#include <stdlib.h>
+#include <string.h> /* ssize_t on Mac OS X */
#if defined(VXWORKS)
# include <ioLib.h>
@@ -126,8 +135,8 @@ typedef struct {
#define DO_WRITE ERL_DRV_WRITE
#define ERL_DRV_EXTENDED_MARKER (0xfeeeeeed)
-#define ERL_DRV_EXTENDED_MAJOR_VERSION 1
-#define ERL_DRV_EXTENDED_MINOR_VERSION 5
+#define ERL_DRV_EXTENDED_MAJOR_VERSION 2
+#define ERL_DRV_EXTENDED_MINOR_VERSION 0
/*
* The emulator will refuse to load a driver with different major
@@ -152,10 +161,15 @@ typedef struct {
/*
* Integer types
*/
-
+#if defined(__WIN32__) && (SIZEOF_VOID_P == 8)
+typedef unsigned __int64 ErlDrvTermData;
+typedef unsigned __int64 ErlDrvUInt;
+typedef signed __int64 ErlDrvSInt;
+#else
typedef unsigned long ErlDrvTermData;
typedef unsigned long ErlDrvUInt;
typedef signed long ErlDrvSInt;
+#endif
#if defined(__WIN32__)
typedef unsigned __int64 ErlDrvUInt64;
@@ -170,13 +184,21 @@ typedef long long ErlDrvSInt64;
#error No 64-bit integer type
#endif
+#if defined(__WIN32__)
+typedef ErlDrvUInt ErlDrvSizeT;
+typedef ErlDrvSInt ErlDrvSSizeT;
+#else
+typedef size_t ErlDrvSizeT;
+typedef ssize_t ErlDrvSSizeT;
+#endif
+
/*
* A binary as seen in a driver. Note that a binary should never be
* altered by the driver when it has been sent to Erlang.
*/
typedef struct erl_drv_binary {
- long orig_size; /* total length of binary */
+ ErlDrvSInt orig_size; /* total length of binary */
char orig_bytes[1]; /* the data (char instead of byte!) */
} ErlDrvBinary;
@@ -236,7 +258,7 @@ typedef struct {
typedef struct erl_io_vec {
int vsize; /* length of vectors */
- int size; /* total size in bytes */
+ ErlDrvSizeT size; /* total size in bytes */
SysIOVec* iov;
ErlDrvBinary** binv;
} ErlIOVec;
@@ -277,8 +299,8 @@ typedef struct erl_drv_entry {
void (*stop)(ErlDrvData drv_data);
/* called when port is closed, and when the
emulator is halted. */
- void (*output)(ErlDrvData drv_data, char *buf, int len);
- /* called when we have output from erlang to
+ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
+ /* called when we have output from erlang to
the port */
void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
/* called when we have input from one of
@@ -291,10 +313,10 @@ typedef struct erl_drv_entry {
void (*finish)(void); /* called before unloading the driver -
DYNAMIC DRIVERS ONLY */
void *handle; /* Reserved -- Used by emulator internally */
- int (*control)(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen);
- /* "ioctl" for drivers - invoked by
- port_control/3 */
+ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len, char **rbuf,
+ ErlDrvSizeT rlen); /* "ioctl" for drivers - invoked by
+ port_control/3 */
void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */
void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev);
/* called when we have output from erlang
@@ -305,10 +327,12 @@ typedef struct erl_drv_entry {
closed, and there is data in the
driver queue that needs to be flushed
before 'stop' can be called */
- int (*call)(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned int *flags);
- /* Works mostly like 'control', a synchronous
- call into the driver. */
+ ErlDrvSSizeT (*call)(ErlDrvData drv_data,
+ unsigned int command, char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
+ unsigned int *flags); /* Works mostly like 'control',
+ a synchronous
+ call into the driver. */
void (*event)(ErlDrvData drv_data, ErlDrvEvent event,
ErlDrvEventData event_data);
/* Called when an event selected by
@@ -347,11 +371,17 @@ typedef struct erl_drv_entry {
#ifndef ERL_DRIVER_TYPES_ONLY
#if defined(VXWORKS)
-# define DRIVER_INIT(DRIVER_NAME) ErlDrvEntry* DRIVER_NAME ## _init(void)
+# define DRIVER_INIT(DRIVER_NAME) \
+ ErlDrvEntry* DRIVER_NAME ## _init(void); \
+ ErlDrvEntry* DRIVER_NAME ## _init(void)
#elif defined(__WIN32__)
-# define DRIVER_INIT(DRIVER_NAME) __declspec(dllexport) ErlDrvEntry* driver_init(void)
+# define DRIVER_INIT(DRIVER_NAME) \
+ __declspec(dllexport) ErlDrvEntry* driver_init(void); \
+ __declspec(dllexport) ErlDrvEntry* driver_init(void)
#else
-# define DRIVER_INIT(DRIVER_NAME) ErlDrvEntry* driver_init(void)
+# define DRIVER_INIT(DRIVER_NAME) \
+ ErlDrvEntry* driver_init(void); \
+ ErlDrvEntry* driver_init(void)
#endif
/*
@@ -360,14 +390,16 @@ typedef struct erl_drv_entry {
EXTERN int driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on);
EXTERN int driver_event(ErlDrvPort port, ErlDrvEvent event,
ErlDrvEventData event_data);
-EXTERN int driver_output(ErlDrvPort port, char *buf, int len);
-EXTERN int driver_output2(ErlDrvPort port, char *hbuf, int hlen,
- char *buf, int len);
-EXTERN int driver_output_binary(ErlDrvPort port, char *hbuf, int hlen,
- ErlDrvBinary* bin, int offset, int len);
-EXTERN int driver_outputv(ErlDrvPort port, char* hbuf, int hlen, ErlIOVec *ev,
- int skip);
-EXTERN int driver_vec_to_buf(ErlIOVec *ev, char *buf, int len);
+
+EXTERN int driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len);
+EXTERN int driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen,
+ char *buf, ErlDrvSizeT len);
+EXTERN int driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen,
+ ErlDrvBinary* bin,
+ ErlDrvSizeT offset, ErlDrvSizeT len);
+EXTERN int driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen,
+ ErlIOVec *ev, ErlDrvSizeT skip);
+EXTERN ErlDrvSizeT driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len);
EXTERN int driver_set_timer(ErlDrvPort port, unsigned long time);
EXTERN int driver_cancel_timer(ErlDrvPort port);
EXTERN int driver_read_timer(ErlDrvPort port, unsigned long *time_left);
@@ -428,8 +460,8 @@ EXTERN int get_port_flags(ErlDrvPort port);
* since the binary is a shared object it MUST be written once.
*/
-EXTERN ErlDrvBinary* driver_alloc_binary(int size);
-EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, int size);
+EXTERN ErlDrvBinary* driver_alloc_binary(ErlDrvSizeT size);
+EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size);
EXTERN void driver_free_binary(ErlDrvBinary *bin);
/* Referenc count on driver binaries */
@@ -438,24 +470,24 @@ EXTERN ErlDrvSInt driver_binary_inc_refc(ErlDrvBinary *dbp);
EXTERN ErlDrvSInt driver_binary_dec_refc(ErlDrvBinary *dbp);
/* Allocation interface */
-EXTERN void *driver_alloc(size_t size);
-EXTERN void *driver_realloc(void *ptr, size_t size);
+EXTERN void *driver_alloc(ErlDrvSizeT size);
+EXTERN void *driver_realloc(void *ptr, ErlDrvSizeT size);
EXTERN void driver_free(void *ptr);
/* Queue interface */
-EXTERN int driver_enq(ErlDrvPort port, char* buf, int len);
-EXTERN int driver_pushq(ErlDrvPort port, char* buf, int len);
-EXTERN int driver_deq(ErlDrvPort port, int size);
-EXTERN int driver_sizeq(ErlDrvPort port);
-EXTERN int driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset,
- int len);
-EXTERN int driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset,
- int len);
-
-EXTERN int driver_peekqv(ErlDrvPort port, ErlIOVec *ev);
+EXTERN int driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len);
+EXTERN int driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len);
+EXTERN ErlDrvSizeT driver_deq(ErlDrvPort port, ErlDrvSizeT size);
+EXTERN ErlDrvSizeT driver_sizeq(ErlDrvPort port);
+EXTERN int driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset,
+ ErlDrvSizeT len);
+EXTERN int driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset,
+ ErlDrvSizeT len);
+
+EXTERN ErlDrvSizeT driver_peekqv(ErlDrvPort port, ErlIOVec *ev);
EXTERN SysIOVec* driver_peekq(ErlDrvPort port, int *vlen);
-EXTERN int driver_enqv(ErlDrvPort port, ErlIOVec *ev, int skip);
-EXTERN int driver_pushqv(ErlDrvPort port, ErlIOVec *ev, int skip);
+EXTERN int driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip);
+EXTERN int driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip);
/*
* Add and remove driver entries.
@@ -582,8 +614,11 @@ EXTERN long driver_async(ErlDrvPort ix,
void* async_data,
void (*async_free)(void*));
-
-EXTERN int driver_async_cancel(unsigned int key);
+/*
+ * driver_async_cancel() is deprecated. It is scheduled for removal
+ * in OTP-R16. For more information see the erl_driver(3) documentation.
+ */
+EXTERN int driver_async_cancel(unsigned int key) ERL_DRV_DEPRECATED_FUNC;
/* Locks the driver in the machine "forever", there is
no unlock function. Note that this is almost never useful, as an open
@@ -614,6 +649,8 @@ EXTERN int erl_drv_getenv(char *key, char *value, size_t *value_size);
#endif
+/* also in global.h, but driver's can't include global.h */
+void dtrace_drvport_str(ErlDrvPort port, char *port_buf);
diff --git a/erts/emulator/beam/erl_drv_thread.c b/erts/emulator/beam/erl_drv_thread.c
index dc578f6d2a..a49a155701 100644
--- a/erts/emulator/beam/erl_drv_thread.c
+++ b/erts/emulator/beam/erl_drv_thread.c
@@ -158,7 +158,9 @@ erl_drv_mutex_create(char *name)
(sizeof(ErlDrvMutex)
+ (name ? sys_strlen(name) + 1 : 0)));
if (dmtx) {
- if (ethr_mutex_init(&dmtx->mtx) != 0) {
+ ethr_mutex_opt opt = ETHR_MUTEX_OPT_DEFAULT_INITER;
+ opt.posix_compliant = 1;
+ if (ethr_mutex_init_opt(&dmtx->mtx, &opt) != 0) {
erts_free(ERTS_ALC_T_DRV_MTX, (void *) dmtx);
dmtx = NULL;
}
@@ -226,7 +228,9 @@ erl_drv_cond_create(char *name)
(sizeof(ErlDrvCond)
+ (name ? sys_strlen(name) + 1 : 0)));
if (dcnd) {
- if (ethr_cond_init(&dcnd->cnd) != 0) {
+ ethr_cond_opt opt = ETHR_COND_OPT_DEFAULT_INITER;
+ opt.posix_compliant = 1;
+ if (ethr_cond_init_opt(&dcnd->cnd, &opt) != 0) {
erts_free(ERTS_ALC_T_DRV_CND, (void *) dcnd);
dcnd = NULL;
}
diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h
index 2f165afa06..54cfd6aa83 100644
--- a/erts/emulator/beam/erl_fun.h
+++ b/erts/emulator/beam/erl_fun.h
@@ -54,9 +54,7 @@ typedef struct erl_fun_entry {
typedef struct erl_fun_thing {
Eterm thing_word; /* Subtag FUN_SUBTAG. */
ErlFunEntry* fe; /* Pointer to fun entry. */
-#ifndef HYBRID /* FIND ME! */
struct erl_off_heap_header* next;
-#endif
#ifdef HIPE
UWord* native_address; /* Native code for the fun. */
#endif
@@ -83,9 +81,7 @@ ErlFunEntry* erts_get_fun_entry2(Eterm mod, int old_uniq, int old_index,
byte* uniq, int index, int arity);
void erts_erase_fun_entry(ErlFunEntry* fe);
-#ifndef HYBRID /* FIND ME! */
void erts_cleanup_funs(ErlFunThing* funp);
-#endif
void erts_cleanup_funs_on_purge(BeamInstr* start, BeamInstr* end);
void erts_dump_fun_entries(int, void *);
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index e3445bcdc5..52a6e52e6c 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -35,6 +35,7 @@
#include "hipe_stack.h"
#include "hipe_mode_switch.h"
#endif
+#include "dtrace-wrapper.h"
#define ERTS_INACT_WR_PB_LEAVE_MUCH_LIMIT 1
#define ERTS_INACT_WR_PB_LEAVE_MUCH_PERCENTAGE 20
@@ -315,7 +316,12 @@ erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
if (is_non_value(result)) {
if (p->freason == TRAP) {
- cost = erts_garbage_collect(p, 0, p->def_arg_reg, p->arity);
+ #if HIPE
+ if (regs == NULL) {
+ regs = ERTS_PROC_GET_SCHDATA(p)->x_reg_array;
+ }
+ #endif
+ cost = erts_garbage_collect(p, 0, regs, p->arity);
} else {
cost = erts_garbage_collect(p, 0, regs, arity);
}
@@ -344,7 +350,9 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
Uint reclaimed_now = 0;
int done = 0;
Uint ms1, s1, us1;
-
+#ifdef USE_VM_PROBES
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+#endif
if (IS_TRACED_FL(p, F_TRACE_GC)) {
trace_gc(p, am_gc_start);
}
@@ -352,12 +360,11 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
p->gcstatus = p->status;
p->status = P_GARBING;
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+
if (erts_system_monitor_long_gc != 0) {
get_now(&ms1, &s1, &us1);
}
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
-
- erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
ERTS_CHK_OFFHEAP(p);
@@ -365,15 +372,27 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
if (GEN_GCS(p) >= MAX_GEN_GCS(p)) {
FLAGS(p) |= F_NEED_FULLSWEEP;
}
-
+#ifdef USE_VM_PROBES
+ *pidbuf = '\0';
+ if (DTRACE_ENABLED(gc_major_start)
+ || DTRACE_ENABLED(gc_major_end)
+ || DTRACE_ENABLED(gc_minor_start)
+ || DTRACE_ENABLED(gc_minor_end)) {
+ dtrace_proc_str(p, pidbuf);
+ }
+#endif
/*
* Test which type of GC to do.
*/
while (!done) {
if ((FLAGS(p) & F_NEED_FULLSWEEP) != 0) {
+ DTRACE2(gc_major_start, pidbuf, need);
done = major_collection(p, need, objv, nobj, &reclaimed_now);
+ DTRACE2(gc_major_end, pidbuf, reclaimed_now);
} else {
+ DTRACE2(gc_minor_start, pidbuf, need);
done = minor_collection(p, need, objv, nobj, &reclaimed_now);
+ DTRACE2(gc_minor_end, pidbuf, reclaimed_now);
}
}
@@ -392,8 +411,6 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
trace_gc(p, am_gc_end);
}
- erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
-
if (erts_system_monitor_long_gc != 0) {
Uint ms2, s2, us2;
Sint t;
@@ -477,7 +494,6 @@ erts_garbage_collect_hibernate(Process* p)
p->gcstatus = p->status;
p->status = P_GARBING;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
ErtsGcQuickSanityCheck(p);
ASSERT(p->mbuf_sz == 0);
ASSERT(p->mbuf == 0);
@@ -591,12 +607,13 @@ erts_garbage_collect_hibernate(Process* p)
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
p->status = p->gcstatus;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
}
void
-erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
+erts_garbage_collect_literals(Process* p, Eterm* literals,
+ Uint lit_size,
+ struct erl_off_heap_header* oh)
{
Uint byte_lit_size = sizeof(Eterm)*lit_size;
Uint old_heap_size;
@@ -608,6 +625,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
Uint area_size;
Eterm* old_htop;
Uint n;
+ struct erl_off_heap_header** prev;
/*
* Set GC state.
@@ -616,7 +634,6 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
p->gcstatus = p->status;
p->status = P_GARBING;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_begin(ERTS_ACTIVITY_GC);
/*
* We assume that the caller has already done a major collection
@@ -642,6 +659,9 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
offset_heap(temp_lit, lit_size, offs, (char *) literals, byte_lit_size);
offset_heap(p->heap, p->htop - p->heap, offs, (char *) literals, byte_lit_size);
offset_rootset(p, offs, (char *) literals, byte_lit_size, p->arg_reg, p->arity);
+ if (oh) {
+ oh = (struct erl_off_heap_header *) ((Eterm *)(void *) oh + offs);
+ }
/*
* Now the literals are placed in memory that is safe to write into,
@@ -709,6 +729,45 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
p->old_htop = old_htop;
/*
+ * Prepare to sweep binaries. Since all MSOs on the new heap
+ * must be come before MSOs on the old heap, find the end of
+ * current MSO list and use that as a starting point.
+ */
+
+ if (oh) {
+ prev = &MSO(p).first;
+ while (*prev) {
+ prev = &(*prev)->next;
+ }
+ }
+
+ /*
+ * Sweep through all binaries in the temporary literal area.
+ */
+
+ while (oh) {
+ if (IS_MOVED_BOXED(oh->thing_word)) {
+ Binary* bptr;
+ struct erl_off_heap_header* ptr;
+
+ ptr = (struct erl_off_heap_header*) boxed_val(oh->thing_word);
+ ASSERT(thing_subtag(ptr->thing_word) == REFC_BINARY_SUBTAG);
+ bptr = ((ProcBin*)ptr)->val;
+
+ /*
+ * This binary has been copied to the heap.
+ * We must increment its reference count and
+ * link it into the MSO list for the process.
+ */
+
+ erts_refc_inc(&bptr->refc, 1);
+ *prev = ptr;
+ prev = &ptr->next;
+ }
+ oh = oh->next;
+ }
+
+ /*
* We no longer need this temporary area.
*/
erts_free(ERTS_ALC_T_TMP, (void *) temp_lit);
@@ -719,7 +778,6 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size)
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
p->status = p->gcstatus;
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_smp_locked_activity_end(ERTS_ACTIVITY_GC);
}
static int
@@ -868,7 +926,18 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* XXX: WARNING: If HiPE starts storing other non-Erlang values on the
* nstack, such as floats, then this will have to be changed.
*/
-#define offset_nstack(p,offs,area,area_size) offset_heap_ptr(hipe_nstack_start((p)),hipe_nstack_used((p)),(offs),(area),(area_size))
+static ERTS_INLINE void offset_nstack(Process* p, Sint offs,
+ char* area, Uint area_size)
+{
+ if (p->hipe.nstack) {
+ ASSERT(p->hipe.nsp && p->hipe.nstend);
+ offset_heap_ptr(hipe_nstack_start(p), hipe_nstack_used(p),
+ offs, area, area_size);
+ }
+ else {
+ ASSERT(!p->hipe.nsp && !p->hipe.nstend);
+ }
+}
#else /* !HIPE */
@@ -1064,6 +1133,15 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm));
p->stop = n_heap + new_sz - n;
+#ifdef USE_VM_PROBES
+ if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) {
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, pidbuf);
+ DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
+ }
+#endif
+
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
(void*)HEAP_START(p),
HEAP_SIZE(p) * sizeof(Eterm));
@@ -1285,6 +1363,15 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm));
p->stop = n_heap + new_sz - n;
+#ifdef USE_VM_PROBES
+ if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) {
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, pidbuf);
+ DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
+ }
+#endif
+
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
(void *) HEAP_START(p),
(HEAP_END(p) - HEAP_START(p)) * sizeof(Eterm));
@@ -1853,7 +1940,13 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
roots[n].sz = 1;
n++;
}
-
+#ifdef USE_VM_PROBES
+ if (is_not_immed(p->dt_utag)) {
+ roots[n].v = &p->dt_utag;
+ roots[n].sz = 1;
+ n++;
+ }
+#endif
ASSERT(is_nil(p->tracer_proc) ||
is_internal_pid(p->tracer_proc) ||
is_internal_port(p->tracer_proc));
@@ -1955,6 +2048,16 @@ grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj)
HEAP_TOP(p) = new_heap + heap_size;
HEAP_START(p) = new_heap;
}
+
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_heap_grow)) {
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, pidbuf);
+ DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
+ }
+#endif
+
HEAP_SIZE(p) = new_sz;
}
@@ -1964,7 +2067,6 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
Eterm* new_heap;
Uint heap_size = HEAP_TOP(p) - HEAP_START(p);
Sint offs;
-
Uint stack_size = p->hend - p->stop;
ASSERT(new_sz < p->heap_sz);
@@ -1993,6 +2095,16 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
HEAP_TOP(p) = new_heap + heap_size;
HEAP_START(p) = new_heap;
}
+
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_heap_shrink)) {
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, pidbuf);
+ DTRACE3(process_heap_shrink, pidbuf, HEAP_SIZE(p), new_sz);
+ }
+#endif
+
HEAP_SIZE(p) = new_sz;
}
@@ -2375,6 +2487,13 @@ offset_mqueue(Process *p, Sint offs, char* area, Uint area_size)
if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs);
}
+#ifdef USE_VM_PROBES
+ mesg = ERL_MESSAGE_DT_UTAG(mp);
+ if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
+ ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs);
+ }
+#endif
+
ASSERT((is_nil(ERL_MESSAGE_TOKEN(mp)) ||
is_tuple(ERL_MESSAGE_TOKEN(mp)) ||
is_atom(ERL_MESSAGE_TOKEN(mp))));
@@ -2394,6 +2513,9 @@ offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size,
offset_heap_ptr(&p->fvalue, 1, offs, area, area_size);
offset_heap_ptr(&p->ftrace, 1, offs, area, area_size);
offset_heap_ptr(&p->seq_trace_token, 1, offs, area, area_size);
+#ifdef USE_VM_PROBES
+ offset_heap_ptr(&p->dt_utag, 1, offs, area, area_size);
+#endif
offset_heap_ptr(&p->group_leader, 1, offs, area, area_size);
offset_mqueue(p, offs, area, area_size);
offset_heap_ptr(p->stop, (STACK_START(p) - p->stop), offs, area, area_size);
diff --git a/erts/emulator/beam/erl_gc.h b/erts/emulator/beam/erl_gc.h
index 807ef8ae8d..1801df359a 100644
--- a/erts/emulator/beam/erl_gc.h
+++ b/erts/emulator/beam/erl_gc.h
@@ -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,7 +62,7 @@ do { \
} while(0)
#define in_area(ptr,start,nbytes) \
- ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
extern Uint erts_test_long_gc_sleep;
diff --git a/erts/emulator/beam/erl_goodfit_alloc.c b/erts/emulator/beam/erl_goodfit_alloc.c
index 8322b233ac..e7d4ac2b67 100644
--- a/erts/emulator/beam/erl_goodfit_alloc.c
+++ b/erts/emulator/beam/erl_goodfit_alloc.c
@@ -190,16 +190,20 @@ erts_gfalc_start(GFAllctr_t *gfallctr,
GFAllctrInit_t *gfinit,
AllctrInit_t *init)
{
- GFAllctr_t nulled_state = {{0}};
- /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc
- warning. gcc warns if {0} is used as initializer of a struct when
- the first member is a struct (not if, for example, the third member
- is a struct). */
+ struct {
+ int dummy;
+ GFAllctr_t allctr;
+ } zero = {0};
+ /* The struct with a dummy element first is used in order to avoid (an
+ incorrect) gcc warning. gcc warns if {0} is used as initializer of
+ a struct when the first member is a struct (not if, for example,
+ the third member is a struct). */
+
Allctr_t *allctr = (Allctr_t *) gfallctr;
- init->sbmbct = 0; /* Small mbc not yet supported by goodfit */
+ sys_memcpy((void *) gfallctr, (void *) &zero.allctr, sizeof(GFAllctr_t));
- sys_memcpy((void *) gfallctr, (void *) &nulled_state, sizeof(GFAllctr_t));
+ init->sbmbct = 0; /* Small mbc not yet supported by goodfit */
allctr->mbc_header_size = sizeof(Carrier_t);
allctr->min_mbc_size = MIN_MBC_SZ;
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 8a297cded0..1eb3dba240 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2012. All Rights Reserved.
*
* The 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,6 @@
#include "erl_binary.h"
#include "dist.h"
#include "erl_mseg.h"
-#include "erl_nmgc.h"
#include "erl_threads.h"
#include "erl_bif_timer.h"
#include "erl_instrument.h"
@@ -42,6 +41,9 @@
#include "erl_misc_utils.h"
#include "packet_parser.h"
#include "erl_cpu_topology.h"
+#include "erl_thr_progress.h"
+#include "erl_thr_queue.h"
+#include "erl_async.h"
#ifdef HIPE
#include "hipe_mode_switch.h" /* for hipe_mode_switch_init() */
@@ -68,6 +70,8 @@ static void erl_init(int ncpu);
#define ERTS_MIN_COMPAT_REL 7
+static erts_atomic_t exiting;
+
#ifdef ERTS_SMP
erts_smp_atomic32_t erts_writing_erl_crash_dump;
erts_tsd_key_t erts_is_crash_dumping_key;
@@ -87,7 +91,6 @@ int erts_use_sender_punish;
*/
Uint display_items; /* no of items to display in traces etc */
-Uint display_loads; /* print info about loaded modules */
int H_MIN_SIZE; /* The minimum heap grain */
int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/
@@ -99,8 +102,6 @@ int erts_backtrace_depth; /* How many functions to show in a backtrace
* in error codes.
*/
-int erts_async_max_threads; /* number of threads for async support */
-int erts_async_thread_suggested_stack_size;
erts_smp_atomic32_t erts_max_gen_gcs;
Eterm erts_error_logger_warnings; /* What to map warning logs to, am_error,
@@ -109,7 +110,6 @@ Eterm erts_error_logger_warnings; /* What to map warning logs to, am_error,
int erts_compat_rel;
-static int use_multi_run_queue;
static int no_schedulers;
static int no_schedulers_online;
@@ -153,28 +153,6 @@ Export *erts_delay_trap = NULL;
int erts_use_r9_pids_ports;
-#ifdef HYBRID
-Eterm *global_heap;
-Eterm *global_hend;
-Eterm *global_htop;
-Eterm *global_saved_htop;
-Eterm *global_old_heap;
-Eterm *global_old_hend;
-ErlOffHeap erts_global_offheap;
-Uint global_heap_sz = SH_DEFAULT_SIZE;
-
-#ifndef INCREMENTAL
-Eterm *global_high_water;
-Eterm *global_old_htop;
-#endif
-
-Uint16 global_gen_gcs;
-Uint16 global_max_gen_gcs;
-Uint global_gc_flags;
-
-Uint global_heap_min_sz = SH_DEFAULT_SIZE;
-#endif
-
int ignore_break;
int replace_intr;
@@ -247,19 +225,16 @@ erl_init(int ncpu)
{
init_benchmarking();
-#ifdef ERTS_SMP
- erts_system_block_init();
-#endif
-
erts_init_monitors();
erts_init_gc();
erts_init_time();
erts_init_sys_common_misc();
erts_init_process(ncpu);
- erts_init_scheduling(use_multi_run_queue,
- no_schedulers,
+ erts_init_scheduling(no_schedulers,
no_schedulers_online);
erts_init_cpu_topology(); /* Must be after init_scheduling */
+ erts_alloc_late_init();
+
H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0);
BIN_VH_MIN_SIZE = erts_next_heap_size(BIN_VH_MIN_SIZE, 0);
@@ -281,8 +256,8 @@ erl_init(int ncpu)
erts_init_node_tables();
init_dist();
erl_drv_thr_init();
+ erts_init_async();
init_io();
- init_copy();
init_load();
erts_init_bif();
erts_init_bif_chksum();
@@ -303,45 +278,6 @@ erl_init(int ncpu)
}
static void
-init_shared_memory(int argc, char **argv)
-{
-#ifdef HYBRID
- int arg_size = 0;
-
- global_heap_sz = erts_next_heap_size(global_heap_sz,0);
-
- /* Make sure arguments will fit on the heap, no one else will check! */
- while (argc--)
- arg_size += 2 + strlen(argv[argc]);
- if (global_heap_sz < arg_size)
- global_heap_sz = erts_next_heap_size(arg_size,1);
-
-#ifndef INCREMENTAL
- global_heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP,
- sizeof(Eterm) * global_heap_sz);
- global_hend = global_heap + global_heap_sz;
- global_htop = global_heap;
- global_high_water = global_heap;
- global_old_hend = global_old_htop = global_old_heap = NULL;
-#endif
-
- global_gen_gcs = 0;
- global_max_gen_gcs = (Uint16) erts_smp_atomic32_read_nob(&erts_max_gen_gcs);
- global_gc_flags = erts_default_process_flags;
-
- erts_global_offheap.mso = NULL;
-#ifndef HYBRID /* FIND ME! */
- erts_global_offheap.funs = NULL;
-#endif
- erts_global_offheap.overhead = 0;
-#endif
-
-#ifdef INCREMENTAL
- erts_init_incgc();
-#endif
-}
-
-static void
erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char** argv)
{
int i;
@@ -435,7 +371,7 @@ static void
load_preloaded(void)
{
int i;
- int res;
+ Eterm res;
Preload* preload_p;
Eterm module_name;
byte* code;
@@ -454,8 +390,9 @@ load_preloaded(void)
name);
res = erts_load_module(NULL, 0, NIL, &module_name, code, length);
sys_preload_end(&preload_p[i]);
- if (res < 0)
- erl_exit(1,"Failed loading preloaded module %s\n", name);
+ if (res != NIL)
+ erl_exit(1,"Failed loading preloaded module %s (%T)\n",
+ name, res);
i++;
}
}
@@ -497,8 +434,6 @@ void erts_usage(void)
erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n");
- erts_fprintf(stderr, "-l turn on auto load tracing\n");
-
erts_fprintf(stderr, "-M<X> <Y> memory allocator switches,\n");
erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n");
@@ -513,8 +448,14 @@ void erts_usage(void)
erts_fprintf(stderr, "-rg amount set reader groups limit\n");
erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n");
erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n");
+ erts_fprintf(stderr, "-sbwt val set scheduler busy wait threshold, valid values are:\n");
+ erts_fprintf(stderr, " none|very_short|short|medium|long|very_long.\n");
+ erts_fprintf(stderr, "-scl bool enable/disable compaction of scheduler load,\n");
+ erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
erts_fprintf(stderr, "-sct cput set cpu topology,\n");
erts_fprintf(stderr, " see the erl(1) documentation for more info.\n");
+ erts_fprintf(stderr, "-sws val set scheduler wakeup strategy, valid values are:\n");
+ erts_fprintf(stderr, " default|legacy|proposal.\n");
erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n");
erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n");
erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n");
@@ -607,12 +548,13 @@ early_init(int *argc, char **argv) /*
int max_main_threads;
int max_reader_groups;
int reader_groups;
+ char envbuf[21]; /* enough for any 64-bit integer */
+ size_t envbufsz;
- use_multi_run_queue = 1;
+ erts_sched_compact_load = 1;
erts_printf_eterm_func = erts_printf_term;
erts_disable_tolerant_timeofday = 0;
display_items = 200;
- display_loads = 0;
erts_backtrace_depth = DEFAULT_BACKTRACE_SIZE;
erts_async_max_threads = 0;
erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE;
@@ -644,6 +586,10 @@ early_init(int *argc, char **argv) /*
erts_use_r9_pids_ports = 0;
erts_sys_pre_init();
+ erts_atomic_init_nob(&exiting, 0);
+#ifdef ERTS_SMP
+ erts_thr_progress_pre_init();
+#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_init();
@@ -675,6 +621,16 @@ early_init(int *argc, char **argv) /*
schdlrs = no_schedulers;
schdlrs_onln = no_schedulers_online;
+ envbufsz = sizeof(envbuf);
+
+ /* erts_sys_getenv(_raw)() not initialized yet; need erts_sys_getenv__() */
+ if (erts_sys_getenv__("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 0)
+ erts_async_max_threads = atoi(envbuf);
+ else
+ erts_async_max_threads = 0;
+ if (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)
+ erts_async_max_threads = ERTS_MAX_NO_OF_ASYNC_THREADS;
+
if (argc && argv) {
int i = 1;
while (i < *argc) {
@@ -702,6 +658,20 @@ early_init(int *argc, char **argv) /*
}
break;
}
+ case 'A': {
+ /* set number of threads in thread pool */
+ char *arg = get_arg(argv[i]+2, argv[i+1], &i);
+ if (((erts_async_max_threads = atoi(arg)) < 0) ||
+ (erts_async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)) {
+ erts_fprintf(stderr,
+ "bad number of async threads %s\n",
+ arg);
+ erts_usage();
+ VERBOSE(DEBUG_SYSTEM, ("using %d async-threads\n",
+ erts_async_max_threads));
+ }
+ break;
+ }
case 'S' : {
int tot, onln;
char *arg = get_arg(argv[i]+2, argv[i+1], &i);
@@ -761,17 +731,39 @@ early_init(int *argc, char **argv) /*
}
}
+#ifndef USE_THREADS
+ erts_async_max_threads = 0;
+#endif
+
#ifdef ERTS_SMP
no_schedulers = schdlrs;
no_schedulers_online = schdlrs_onln;
erts_no_schedulers = (Uint) no_schedulers;
#endif
+ erts_early_init_scheduling(no_schedulers);
+ alloc_opts.ncpu = ncpu;
erts_alloc_init(argc, argv, &alloc_opts); /* Handles (and removes)
-M flags. */
/* Require allocators */
- erts_early_init_scheduling();
+#ifdef ERTS_SMP
+ /*
+ * Thread progress management:
+ *
+ * * Managed threads:
+ * ** Scheduler threads (see erl_process.c)
+ * ** Aux thread (see erl_process.c)
+ * ** Sys message dispatcher thread (see erl_trace.c)
+ *
+ * * Unmanaged threads that need to register:
+ * ** Async threads (see erl_async.c)
+ */
+ erts_thr_progress_init(no_schedulers,
+ no_schedulers+2,
+ erts_async_max_threads);
+#endif
+ erts_thr_q_init();
erts_init_utils();
erts_early_init_cpu_topology(no_schedulers,
&max_main_threads,
@@ -851,27 +843,21 @@ erl_start(int argc, char **argv)
int have_break_handler = 1;
char envbuf[21]; /* enough for any 64-bit integer */
size_t envbufsz;
- int async_max_threads = erts_async_max_threads;
int ncpu = early_init(&argc, argv);
envbufsz = sizeof(envbuf);
- if (erts_sys_getenv(ERL_MAX_ETS_TABLES_ENV, envbuf, &envbufsz) == 0)
+ if (erts_sys_getenv_raw(ERL_MAX_ETS_TABLES_ENV, envbuf, &envbufsz) == 0)
user_requested_db_max_tabs = atoi(envbuf);
else
user_requested_db_max_tabs = 0;
envbufsz = sizeof(envbuf);
- if (erts_sys_getenv("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 0) {
+ if (erts_sys_getenv_raw("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 0) {
Uint16 max_gen_gcs = atoi(envbuf);
erts_smp_atomic32_set_nob(&erts_max_gen_gcs,
(erts_aint32_t) max_gen_gcs);
}
- envbufsz = sizeof(envbuf);
- if (erts_sys_getenv("ERL_THREAD_POOL_SIZE", envbuf, &envbufsz) == 0) {
- async_max_threads = atoi(envbuf);
- }
-
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__DARWIN__)
/*
* The default stack size on MacOS X is too small for pcre.
@@ -937,9 +923,6 @@ erl_start(int argc, char **argv)
erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
erts_usage();
}
- case 'l':
- display_loads++;
- break;
case 'L':
erts_no_line_info = 1;
break;
@@ -953,7 +936,6 @@ erl_start(int argc, char **argv)
switch (*ch) {
case 's': verbose |= DEBUG_SYSTEM; break;
case 'g': verbose |= DEBUG_PRIVATE_GC; break;
- case 'h': verbose |= DEBUG_HYBRID_GC; break;
case 'M': verbose |= DEBUG_MEMORY; break;
case 'a': verbose |= DEBUG_ALLOCATION; break;
case 't': verbose |= DEBUG_THREADS; break;
@@ -966,7 +948,6 @@ erl_start(int argc, char **argv)
erts_printf("Verbose level: ");
if (verbose & DEBUG_SYSTEM) erts_printf("SYSTEM ");
if (verbose & DEBUG_PRIVATE_GC) erts_printf("PRIVATE_GC ");
- if (verbose & DEBUG_HYBRID_GC) erts_printf("HYBRID_GC ");
if (verbose & DEBUG_MEMORY) erts_printf("PARANOID_MEMORY ");
if (verbose & DEBUG_ALLOCATION) erts_printf("ALLOCATION ");
if (verbose & DEBUG_THREADS) erts_printf("THREADS ");
@@ -994,12 +975,6 @@ erl_start(int argc, char **argv)
#ifdef HIPE
strcat(tmp, ",HIPE");
#endif
-#ifdef INCREMENTAL
- strcat(tmp, ",INCREMENTAL_GC");
-#endif
-#ifdef HYBRID
- strcat(tmp, ",HYBRID");
-#endif
erts_fprintf(stderr, "Erlang ");
if (tmp[1]) {
erts_fprintf(stderr, "(%s) ", tmp+1);
@@ -1160,6 +1135,29 @@ erl_start(int argc, char **argv)
erts_usage();
}
}
+ else if (has_prefix("bwt", sub_param)) {
+ arg = get_arg(sub_param+3, argv[i+1], &i);
+ if (erts_sched_set_busy_wait_threshold(arg) != 0) {
+ erts_fprintf(stderr, "bad scheduler busy wait threshold: %s\n",
+ arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM,
+ ("scheduler wakup threshold: %s\n", arg));
+ }
+ else if (has_prefix("cl", sub_param)) {
+ arg = get_arg(sub_param+2, argv[i+1], &i);
+ if (sys_strcmp("true", arg) == 0)
+ erts_sched_compact_load = 1;
+ else if (sys_strcmp("false", arg) == 0)
+ erts_sched_compact_load = 0;
+ else {
+ erts_fprintf(stderr,
+ "bad scheduler compact load value '%s'\n",
+ arg);
+ erts_usage();
+ }
+ }
else if (has_prefix("ct", sub_param)) {
arg = get_arg(sub_param+2, argv[i+1], &i);
res = erts_init_cpu_topology_string(arg);
@@ -1203,21 +1201,27 @@ erl_start(int argc, char **argv)
erts_usage();
}
}
- else if (sys_strcmp("mrq", sub_param) == 0)
- use_multi_run_queue = 1;
else if (sys_strcmp("nsp", sub_param) == 0)
erts_use_sender_punish = 0;
- else if (sys_strcmp("srq", sub_param) == 0)
- use_multi_run_queue = 0;
else if (sys_strcmp("wt", sub_param) == 0) {
arg = get_arg(sub_param+2, argv[i+1], &i);
- if (erts_sched_set_wakeup_limit(arg) != 0) {
+ if (erts_sched_set_wakeup_other_thresold(arg) != 0) {
erts_fprintf(stderr, "scheduler wakeup threshold: %s\n",
arg);
erts_usage();
}
VERBOSE(DEBUG_SYSTEM,
- ("scheduler wakup threshold: %s\n", arg));
+ ("scheduler wakeup threshold: %s\n", arg));
+ }
+ else if (sys_strcmp("ws", sub_param) == 0) {
+ arg = get_arg(sub_param+2, argv[i+1], &i);
+ if (erts_sched_set_wakeup_other_type(arg) != 0) {
+ erts_fprintf(stderr, "scheduler wakeup strategy: %s\n",
+ arg);
+ erts_usage();
+ }
+ VERBOSE(DEBUG_SYSTEM,
+ ("scheduler wakeup threshold: %s\n", arg));
}
else if (has_prefix("ss", sub_param)) {
/* suggested stack size (Kilo Words) for scheduler threads */
@@ -1301,17 +1305,8 @@ erl_start(int argc, char **argv)
break;
}
- case 'A':
- /* set number of threads in thread pool */
- arg = get_arg(argv[i]+2, argv[i+1], &i);
- if (((async_max_threads = atoi(arg)) < 0) ||
- (async_max_threads > ERTS_MAX_NO_OF_ASYNC_THREADS)) {
- erts_fprintf(stderr, "bad number of async threads %s\n", arg);
- erts_usage();
- }
-
- VERBOSE(DEBUG_SYSTEM, ("using %d async-threads\n",
- async_max_threads));
+ case 'A': /* Was handled in early init just read past it */
+ (void) get_arg(argv[i]+2, argv[i+1], &i);
break;
case 'a':
@@ -1400,10 +1395,6 @@ erl_start(int argc, char **argv)
i++;
}
-#ifdef USE_THREADS
- erts_async_max_threads = async_max_threads;
-#endif
-
/* Delayed check of +P flag */
if (erts_max_processes < ERTS_MIN_PROCESSES
|| erts_max_processes > ERTS_MAX_PROCESSES
@@ -1435,7 +1426,6 @@ erl_start(int argc, char **argv)
erl_init(ncpu);
- init_shared_memory(boot_argc, boot_argv);
load_preloaded();
erts_initialized = 1;
@@ -1449,6 +1439,10 @@ erl_start(int argc, char **argv)
erts_sys_main_thread(); /* May or may not return! */
#else
erts_thr_set_main_status(1, 1);
+#if ERTS_USE_ASYNC_READY_Q
+ erts_get_scheduler_data()->aux_work_data.async_ready.queue
+ = erts_get_async_ready_queue(1);
+#endif
set_main_stack_size();
process_main();
#endif
@@ -1472,8 +1466,31 @@ __decl_noreturn void erts_thr_fatal_error(int err, char *what)
#endif
static void
-system_cleanup(int exit_code)
+system_cleanup(int flush_async)
{
+ /*
+ * Make sure only one thread exits the runtime system.
+ */
+ if (erts_atomic_inc_read_nob(&exiting) != 1) {
+ /*
+ * Another thread is currently exiting the system;
+ * wait for it to do its job.
+ */
+#ifdef ERTS_SMP
+ if (erts_thr_progress_is_managed_thread()) {
+ /*
+ * The exiting thread might be waiting for
+ * us to block; need to update status...
+ */
+ erts_thr_progress_active(NULL, 0);
+ erts_thr_progress_prepare_wait(NULL);
+ }
+#endif
+ /* Wait forever... */
+ while (1)
+ erts_milli_sleep(10000000);
+ }
+
/* No cleanup wanted if ...
* 1. we are about to do an abnormal exit
* 2. we haven't finished initializing, or
@@ -1481,7 +1498,7 @@ system_cleanup(int exit_code)
* (in threaded non smp case).
*/
- if (exit_code != 0
+ if (!flush_async
|| !erts_initialized
#if defined(USE_THREADS) && !defined(ERTS_SMP)
|| !erts_equal_tids(main_thread, erts_thr_self())
@@ -1493,132 +1510,62 @@ system_cleanup(int exit_code)
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_check_exact(NULL, 0);
#endif
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC); /* We never release it... */
-#endif
-
-#ifdef HYBRID
- if (ma_src_stack) erts_free(ERTS_ALC_T_OBJECT_STACK,
- (void *)ma_src_stack);
- if (ma_dst_stack) erts_free(ERTS_ALC_T_OBJECT_STACK,
- (void *)ma_dst_stack);
- if (ma_offset_stack) erts_free(ERTS_ALC_T_OBJECT_STACK,
- (void *)ma_offset_stack);
- ma_src_stack = NULL;
- ma_dst_stack = NULL;
- ma_offset_stack = NULL;
- erts_cleanup_offheap(&erts_global_offheap);
-#endif
-
-#if defined(HYBRID) && !defined(INCREMENTAL)
- if (global_heap) {
- ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void*) global_heap,
- sizeof(Eterm) * global_heap_sz);
- }
- global_heap = NULL;
#endif
-#ifdef INCREMENTAL
- erts_cleanup_incgc();
-#endif
-
-#if defined(USE_THREADS)
- exit_async();
-#endif
-#if HAVE_ERTS_MSEG
- erts_mseg_exit();
-#endif
-
- /*
- * A lot more cleaning could/should have been done...
- */
-
+ erts_exit_flush_async();
}
-/*
- * Common exit function, all exits from the system go through here.
- * n <= 0 -> normal exit with status n;
- * n = 127 -> Erlang crash dump produced, exit with status 1;
- * other positive n -> Erlang crash dump and core dump produced.
- */
-
-__decl_noreturn void erl_exit0(char *file, int line, int n, char *fmt,...)
+static __decl_noreturn void __noreturn
+erl_exit_vv(int n, int flush_async, char *fmt, va_list args1, va_list args2)
{
unsigned int an;
- va_list args;
- va_start(args, fmt);
+ system_cleanup(flush_async);
save_statistics();
- system_cleanup(n);
-
an = abs(n);
if (erts_mtrace_enabled)
erts_mtrace_exit((Uint32) an);
/* Produce an Erlang core dump if error */
- if (n > 0 && erts_initialized &&
- (erts_no_crash_dump == 0 || n == ERTS_DUMP_EXIT)) {
- erl_crash_dump_v(file, line, fmt, args);
+ if (((n > 0 && erts_no_crash_dump == 0) || n == ERTS_DUMP_EXIT)
+ && erts_initialized) {
+ erl_crash_dump_v((char*) NULL, 0, fmt, args1);
}
- /* need to reinitialize va_args thing */
- va_end(args);
- va_start(args, fmt);
-
if (fmt != NULL && *fmt != '\0')
- erl_error(fmt, args); /* Print error message. */
- va_end(args);
+ erl_error(fmt, args2); /* Print error message. */
sys_tty_reset(n);
if (n == ERTS_INTR_EXIT)
exit(0);
- else if (n == 127)
+ else if (n == ERTS_DUMP_EXIT)
ERTS_EXIT_AFTER_DUMP(1);
else if (n > 0 || n == ERTS_ABORT_EXIT)
abort();
exit(an);
}
-__decl_noreturn void erl_exit(int n, char *fmt,...)
+/* Exit without flushing async threads */
+__decl_noreturn void __noreturn erl_exit(int n, char *fmt, ...)
{
- unsigned int an;
- va_list args;
-
- va_start(args, fmt);
-
- save_statistics();
-
- system_cleanup(n);
-
- an = abs(n);
-
- if (erts_mtrace_enabled)
- erts_mtrace_exit((Uint32) an);
-
- /* Produce an Erlang core dump if error */
- if (n > 0 && erts_initialized &&
- (erts_no_crash_dump == 0 || n == ERTS_DUMP_EXIT)) {
- erl_crash_dump_v((char*) NULL, 0, fmt, args);
- }
-
- /* need to reinitialize va_args thing */
- va_end(args);
- va_start(args, fmt);
-
- if (fmt != NULL && *fmt != '\0')
- erl_error(fmt, args); /* Print error message. */
- va_end(args);
- sys_tty_reset(n);
-
- if (n == ERTS_INTR_EXIT)
- exit(0);
- else if (n == ERTS_DUMP_EXIT)
- ERTS_EXIT_AFTER_DUMP(1);
- else if (n > 0 || n == ERTS_ABORT_EXIT)
- abort();
- exit(an);
+ va_list args1, args2;
+ va_start(args1, fmt);
+ va_start(args2, fmt);
+ erl_exit_vv(n, 0, fmt, args1, args2);
+ va_end(args2);
+ va_end(args1);
}
+/* Exit after flushing async threads */
+__decl_noreturn void __noreturn erl_exit_flush_async(int n, char *fmt, ...)
+{
+ va_list args1, args2;
+ va_start(args1, fmt);
+ va_start(args2, fmt);
+ erl_exit_vv(n, 1, fmt, args1, args2);
+ va_end(args2);
+ va_end(args1);
+}
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 587d82f2bb..b545ec07c0 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -110,10 +110,6 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "fun_tab", NULL },
{ "environ", NULL },
#endif
- { "asyncq", "address" },
-#ifndef ERTS_SMP
- { "async_ready", NULL },
-#endif
{ "efile_drv", "address" },
#if defined(ENABLE_CHILD_WAITER_THREAD) || defined(ERTS_SMP)
{ "child_status", NULL },
@@ -125,7 +121,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "drv_ev_state", "address" },
{ "safe_hash", "address" },
{ "pollset_rm_list", NULL },
- { "removed_fd_pre_alloc_lock", NULL },
+ { "removed_fd_pre_alloc_lock", "address" },
{ "state_prealloc", NULL },
{ "schdlr_sspnd", NULL },
{ "run_queue", "address" },
@@ -138,6 +134,7 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "alcu_init_atoms", NULL },
{ "mseg_init_atoms", NULL },
{ "drv_tsd", NULL },
+ { "async_enq_mtx", NULL },
#ifdef ERTS_SMP
{ "sys_msg_q", NULL },
{ "atom_tab", NULL },
@@ -151,10 +148,8 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "mtrace_op", NULL },
{ "instr_x", NULL },
{ "instr", NULL },
- { "fix_alloc", "index" },
{ "alcu_allocator", "index" },
{ "sbmbc_alloc", "index" },
- { "alcu_delayed_free", "index" },
{ "mseg", NULL },
#if HALFWORD_HEAP
{ "pmmap", NULL },
@@ -175,23 +170,19 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "timeofday", NULL },
{ "breakpoints", NULL },
{ "pollsets_lock", NULL },
- { "async_id", NULL },
{ "pix_lock", "address" },
{ "run_queues_lists", NULL },
- { "misc_aux_work_queue", "index" },
- { "misc_aux_work_pre_alloc_lock", "address" },
{ "sched_stat", NULL },
- { "run_queue_sleep_list", "address" },
-#endif
- { "alloc_thr_ix_lock", NULL },
-#ifdef ERTS_SMP
- { "proc_lck_qs_alloc", NULL },
#endif
+ { "async_init_mtx", NULL },
#ifdef __WIN32__
#ifdef DEBUG
{ "save_ops_lock", NULL },
#endif
#endif
+#ifdef USE_VM_PROBES
+ { "efile_drv dtrace mutex", NULL },
+#endif
{ "mtrace_buf", NULL },
{ "erts_alloc_hard_debug", NULL }
};
@@ -1261,7 +1252,7 @@ erts_lc_init_lock(erts_lc_lock_t *lck, char *name, Uint16 flags)
{
lck->id = erts_lc_get_lock_order_id(name);
- lck->extra = &lck->extra;
+ lck->extra = (UWord) &lck->extra;
ASSERT(is_not_immed(lck->extra));
lck->flags = flags;
lck->inited = ERTS_LC_INITITALIZED;
diff --git a/erts/emulator/beam/erl_lock_count.c b/erts/emulator/beam/erl_lock_count.c
index a36c53560e..741c0cb08e 100644
--- a/erts/emulator/beam/erl_lock_count.c
+++ b/erts/emulator/beam/erl_lock_count.c
@@ -49,7 +49,7 @@ const char *str_undefined = "undefined";
static ethr_tsd_key lcnt_thr_data_key;
static int lcnt_n_thr;
-static erts_lcnt_thread_data_t *lcnt_thread_data[1024];
+static erts_lcnt_thread_data_t *lcnt_thread_data[4096];
/* local functions */
@@ -240,7 +240,7 @@ void erts_lcnt_init() {
lcnt_lock();
- erts_lcnt_rt_options = ERTS_LCNT_OPT_PROCLOCK;
+ erts_lcnt_rt_options = ERTS_LCNT_OPT_PROCLOCK | ERTS_LCNT_OPT_LOCATION;
eltd = lcnt_thread_data_alloc();
@@ -312,7 +312,7 @@ void erts_lcnt_list_insert(erts_lcnt_lock_list_t *list, erts_lcnt_lock_t *lock)
}
void erts_lcnt_list_delete(erts_lcnt_lock_list_t *list, erts_lcnt_lock_t *lock) {
-
+
if (lock->next) lock->next->prev = lock->prev;
if (lock->prev) lock->prev->next = lock->next;
if (list->head == lock) list->head = lock->next;
@@ -334,6 +334,10 @@ void erts_lcnt_init_lock(erts_lcnt_lock_t *lock, char *name, Uint16 flag ) {
}
void erts_lcnt_init_lock_x(erts_lcnt_lock_t *lock, char *name, Uint16 flag, Eterm id) {
int i;
+ if (!name) {
+ lock->flag = 0;
+ return;
+ }
lcnt_lock();
lock->next = NULL;
@@ -363,6 +367,8 @@ void erts_lcnt_init_lock_x(erts_lcnt_lock_t *lock, char *name, Uint16 flag, Eter
void erts_lcnt_destroy_lock(erts_lcnt_lock_t *lock) {
erts_lcnt_lock_t *deleted_lock;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
+
lcnt_lock();
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_COPYSAVE) {
@@ -378,6 +384,7 @@ void erts_lcnt_destroy_lock(erts_lcnt_lock_t *lock) {
}
/* delete original */
erts_lcnt_list_delete(erts_lcnt_data->current_locks, lock);
+ lock->flag = 0;
lcnt_unlock();
}
@@ -389,6 +396,7 @@ void erts_lcnt_lock_opt(erts_lcnt_lock_t *lock, Uint16 option) {
erts_lcnt_thread_data_t *eltd;
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
eltd = lcnt_get_thread_data();
@@ -422,6 +430,7 @@ void erts_lcnt_lock(erts_lcnt_lock_t *lock) {
erts_lcnt_thread_data_t *eltd;
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
w_state = ethr_atomic_read(&lock->w_state);
ethr_atomic_inc( &lock->w_state);
@@ -452,6 +461,7 @@ void erts_lcnt_lock_unaquire(erts_lcnt_lock_t *lock) {
/* should check if this thread was "waiting" */
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
ethr_atomic_dec( &lock->w_state);
}
@@ -475,6 +485,7 @@ void erts_lcnt_lock_post_x(erts_lcnt_lock_t *lock, char *file, unsigned int line
#endif
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
#ifdef DEBUG
if (!(lock->flag & (ERTS_LCNT_LT_RWMUTEX | ERTS_LCNT_LT_RWSPINLOCK))) {
@@ -489,9 +500,13 @@ void erts_lcnt_lock_post_x(erts_lcnt_lock_t *lock, char *file, unsigned int line
ASSERT(eltd);
/* if lock was in conflict, time it */
-
- stats = lcnt_get_lock_stats(lock, file, line);
+ if (erts_lcnt_rt_options & ERTS_LCNT_OPT_LOCATION) {
+ stats = lcnt_get_lock_stats(lock, file, line);
+ } else {
+ stats = &lock->stats[0];
+ }
+
if (eltd->timer_set) {
lcnt_time(&timer);
@@ -510,6 +525,7 @@ void erts_lcnt_lock_post_x(erts_lcnt_lock_t *lock, char *file, unsigned int line
void erts_lcnt_unlock_opt(erts_lcnt_lock_t *lock, Uint16 option) {
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
if (option & ERTS_LCNT_LO_WRITE) ethr_atomic_dec(&lock->w_state);
if (option & ERTS_LCNT_LO_READ ) ethr_atomic_dec(&lock->r_state);
}
@@ -520,6 +536,7 @@ void erts_lcnt_unlock(erts_lcnt_lock_t *lock) {
erts_aint_t flowstate;
#endif
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
#ifdef DEBUG
/* flowstate */
flowstate = ethr_atomic_read(&lock->flowstate);
@@ -537,6 +554,7 @@ void erts_lcnt_unlock(erts_lcnt_lock_t *lock) {
void erts_lcnt_trylock_opt(erts_lcnt_lock_t *lock, int res, Uint16 option) {
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
/* Determine lock_state via res instead of state */
if (res != EBUSY) {
if (option & ERTS_LCNT_LO_WRITE) ethr_atomic_inc(&lock->w_state);
@@ -555,6 +573,7 @@ void erts_lcnt_trylock(erts_lcnt_lock_t *lock, int res) {
erts_aint_t flowstate;
#endif
if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
+ if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
if (res != EBUSY) {
#ifdef DEBUG
diff --git a/erts/emulator/beam/erl_lock_count.h b/erts/emulator/beam/erl_lock_count.h
index 6306580ae4..690551c71f 100644
--- a/erts/emulator/beam/erl_lock_count.h
+++ b/erts/emulator/beam/erl_lock_count.h
@@ -89,6 +89,7 @@
#define ERTS_LCNT_OPT_LOCATION (((Uint16) 1) << 1)
#define ERTS_LCNT_OPT_PROCLOCK (((Uint16) 1) << 2)
#define ERTS_LCNT_OPT_COPYSAVE (((Uint16) 1) << 3)
+#define ERTS_LCNT_OPT_PORTLOCK (((Uint16) 1) << 4)
typedef struct {
unsigned long s;
@@ -201,5 +202,7 @@ void erts_lcnt_clear_counters(void);
char *erts_lcnt_lock_type(Uint16 type);
erts_lcnt_data_t *erts_lcnt_get_data(void);
+#define ERTS_LCNT_LOCK_TYPE(lockp) ((lockp)->flag & ERTS_LCNT_LT_ALL)
+
#endif /* ifdef ERTS_ENABLE_LOCK_COUNT */
#endif /* ifndef ERTS_LOCK_COUNT_H__ */
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 82f272d28a..919567ab27 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2012. All Rights Reserved.
*
* The 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,8 @@
#include "global.h"
#include "erl_message.h"
#include "erl_process.h"
-#include "erl_nmgc.h"
#include "erl_binary.h"
+#include "dtrace-wrapper.h"
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
ErlMessage,
@@ -240,7 +240,7 @@ erts_msg_distext2heap(Process *pp,
Sint sz;
*bpp = NULL;
- sz = erts_decode_dist_ext_size(dist_extp, 0);
+ sz = erts_decode_dist_ext_size(dist_extp);
if (sz < 0)
goto decode_error;
if (is_not_nil(*tokenp)) {
@@ -302,8 +302,6 @@ notify_new_message(Process *receiver)
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_STATUS
& erts_proc_lc_my_proc_locks(receiver));
- ACTIVATE(receiver);
-
switch (receiver->status) {
case P_GARBING:
switch (receiver->gcstatus) {
@@ -335,6 +333,11 @@ erts_queue_dist_message(Process *rcvr,
Eterm token)
{
ErlMessage* mp;
+#ifdef USE_VM_PROBES
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+#endif
#ifdef ERTS_SMP
ErtsProcLocks need_locks;
#endif
@@ -376,15 +379,61 @@ erts_queue_dist_message(Process *rcvr,
message_free(mp);
msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext);
if (is_value(msg))
- erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(message_queued)) {
+ DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(rcvr, receiver_name);
+ if (token != NIL && token != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ DTRACE6(message_queued,
+ receiver_name, size_object(msg), rcvr->msg.len,
+ tok_label, tok_lastcnt, tok_serial);
+ }
+#endif
+ erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
else {
/* Enqueue message on external format */
ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
- ERL_MESSAGE_TOKEN(mp) = token;
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+ if (token == am_have_dt_utag) {
+ ERL_MESSAGE_TOKEN(mp) = NIL;
+ } else {
+#endif
+ ERL_MESSAGE_TOKEN(mp) = token;
+#ifdef USE_VM_PROBES
+ }
+#endif
mp->next = NULL;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(message_queued)) {
+ DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(rcvr, receiver_name);
+ if (token != NIL && token != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ /*
+ * TODO: We don't know the real size of the external message here.
+ * -1 will appear to a D script as 4294967295.
+ */
+ DTRACE6(message_queued, receiver_name, -1, rcvr->msg.len + 1,
+ tok_label, tok_lastcnt, tok_serial);
+ }
+#endif
mp->data.dist_ext = dist_ext;
LINK_MESSAGE(rcvr, mp);
@@ -398,7 +447,11 @@ erts_queue_message(Process* receiver,
ErtsProcLocks *receiver_locks,
ErlHeapFragment* bp,
Eterm message,
- Eterm seq_trace_token)
+ Eterm seq_trace_token
+#ifdef USE_VM_PROBES
+ , Eterm dt_utag
+#endif
+)
{
ErlMessage* mp;
#ifdef ERTS_SMP
@@ -439,6 +492,9 @@ erts_queue_message(Process* receiver,
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = seq_trace_token;
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_DT_UTAG(mp) = dt_utag;
+#endif
mp->next = NULL;
mp->data.heap_frag = bp;
@@ -462,12 +518,30 @@ erts_queue_message(Process* receiver,
LINK_MESSAGE(receiver, mp);
#endif
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(message_queued)) {
+ DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+
+ dtrace_proc_str(receiver, receiver_name);
+ if (seq_trace_token != NIL && is_tuple(seq_trace_token)) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(seq_trace_token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(seq_trace_token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(seq_trace_token));
+ }
+ DTRACE6(message_queued,
+ receiver_name, size_object(message), receiver->msg.len,
+ tok_label, tok_lastcnt, tok_serial);
+ }
+#endif
notify_new_message(receiver);
if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
trace_receive(receiver, message);
}
-
+
#ifndef ERTS_SMP
ERTS_HOLE_CHECK(receiver);
#endif
@@ -497,6 +571,9 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
Sint offs;
Uint sz;
ErlHeapFragment *bp;
+#ifdef USE_VM_PROBES
+ Eterm utag;
+#endif
#ifdef HARD_DEBUG
ProcBin *dbg_mso_start = off_heap->mso;
@@ -506,32 +583,56 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
ErlHeapFragment *dbg_bp;
Uint *dbg_hp, *dbg_thp_start;
Uint dbg_term_sz, dbg_token_sz;
+#ifdef USE_VM_PROBES
+ Eterm dbg_utag;
+ Uint dbg_utag_sz;
+#endif
#endif
bp = msg->data.heap_frag;
term = ERL_MESSAGE_TERM(msg);
token = ERL_MESSAGE_TOKEN(msg);
+#ifdef USE_VM_PROBES
+ utag = ERL_MESSAGE_DT_UTAG(msg);
+#endif
if (!bp) {
+#ifdef USE_VM_PROBES
+ ASSERT(is_immed(term) && is_immed(token) && is_immed(utag));
+#else
ASSERT(is_immed(term) && is_immed(token));
+#endif
return;
}
#ifdef HARD_DEBUG
dbg_term_sz = size_object(term);
dbg_token_sz = size_object(token);
+ dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz);
+#ifdef USE_VM_PROBES
+ dbg_utag_sz = size_object(utag);
+ dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz + dbg_utag_sz );
+#endif
/*ASSERT(dbg_term_sz + dbg_token_sz == erts_msg_used_frag_sz(msg));
Copied size may be smaller due to removed SubBins's or garbage.
Copied size may be larger due to duplicated shared terms.
*/
- dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz);
dbg_hp = dbg_bp->mem;
dbg_term = copy_struct(term, dbg_term_sz, &dbg_hp, &dbg_bp->off_heap);
dbg_token = copy_struct(token, dbg_token_sz, &dbg_hp, &dbg_bp->off_heap);
- dbg_thp_start = *hpp;
+#ifdef USE_VM_PROBES
+ dbg_utag = copy_struct(utag, dbg_utag_sz, &dbg_hp, &dbg_bp->off_heap);
+#endif
+ dbg_thp_start = *hpp;
#endif
if (bp->next != NULL) {
- move_multi_frags(hpp, off_heap, bp, msg->m, 2);
+ move_multi_frags(hpp, off_heap, bp, msg->m,
+#ifdef USE_VM_PROBES
+ 3
+#else
+ 2
+#endif
+ );
goto copy_done;
}
@@ -633,6 +734,16 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
ASSERT(hp > ptr_val(ERL_MESSAGE_TERM(msg)));
#endif
}
+#ifdef USE_VM_PROBES
+ if (is_not_immed(utag)) {
+ ASSERT(in_heapfrag(ptr_val(utag), bp));
+ ERL_MESSAGE_DT_UTAG(msg) = offset_ptr(utag, offs);
+#ifdef HARD_DEBUG
+ ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
+ ASSERT(hp > ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
+#endif
+ }
+#endif
copy_done:
@@ -699,6 +810,9 @@ copy_done:
#ifdef HARD_DEBUG
ASSERT(eq(ERL_MESSAGE_TERM(msg), dbg_term));
ASSERT(eq(ERL_MESSAGE_TOKEN(msg), dbg_token));
+#ifdef USE_VM_PROBES
+ ASSERT(eq(ERL_MESSAGE_DT_UTAG(msg), dbg_utag));
+#endif
free_message_buffer(dbg_bp);
#endif
@@ -713,7 +827,7 @@ erts_msg_attached_data_size_aux(ErlMessage *msg)
ASSERT(msg->data.dist_ext);
ASSERT(msg->data.dist_ext->heap_size < 0);
- sz = erts_decode_dist_ext_size(msg->data.dist_ext, 0);
+ sz = erts_decode_dist_ext_size(msg->data.dist_ext);
if (sz < 0) {
/* Bad external; remove it */
if (is_not_nil(ERL_MESSAGE_TOKEN(msg))) {
@@ -774,85 +888,102 @@ erts_send_message(Process* sender,
Uint msize;
ErlHeapFragment* bp = NULL;
Eterm token = NIL;
-
+#ifdef USE_VM_PROBES
+ DTRACE_CHARBUF(sender_name, 64);
+ DTRACE_CHARBUF(receiver_name, 64);
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+#endif
BM_STOP_TIMER(system);
BM_MESSAGE(message,sender,receiver);
BM_START_TIMER(send);
+ #ifdef USE_VM_PROBES
+ *sender_name = *receiver_name = '\0';
+ if (DTRACE_ENABLED(message_send)) {
+ erts_snprintf(sender_name, sizeof(DTRACE_CHARBUF_NAME(sender_name)), "%T", sender->id);
+ erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)), "%T", receiver->id);
+ }
+#endif
if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
Eterm* hp;
+ Eterm stoken = SEQ_TRACE_TOKEN(sender);
+ Uint seq_trace_size = 0;
+#ifdef USE_VM_PROBES
+ Uint dt_utag_size = 0;
+ Eterm utag = NIL;
+#endif
- BM_SWAP_TIMER(send,size);
+ BM_SWAP_TIMER(send,size);
msize = size_object(message);
- BM_SWAP_TIMER(size,send);
+ BM_SWAP_TIMER(size,send);
+
+#ifdef USE_VM_PROBES
+ if (stoken != am_have_dt_utag) {
+#endif
+
+ seq_trace_update_send(sender);
+ seq_trace_output(stoken, message, SEQ_TRACE_SEND,
+ receiver->id, sender);
+ seq_trace_size = 6; /* TUPLE5 */
+#ifdef USE_VM_PROBES
+ }
+ if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
+ dt_utag_size = size_object(DT_UTAG(sender));
+ } else if (stoken == am_have_dt_utag ) {
+ stoken = NIL;
+ }
+#endif
- seq_trace_update_send(sender);
- seq_trace_output(SEQ_TRACE_TOKEN(sender), message, SEQ_TRACE_SEND,
- receiver->id, sender);
- bp = new_message_buffer(msize + 6 /* TUPLE5 */);
+ bp = new_message_buffer(msize + seq_trace_size
+#ifdef USE_VM_PROBES
+ + dt_utag_size
+#endif
+ );
hp = bp->mem;
BM_SWAP_TIMER(send,copy);
- token = copy_struct(SEQ_TRACE_TOKEN(sender),
- 6 /* TUPLE5 */,
+ token = copy_struct(stoken,
+ seq_trace_size,
&hp,
&bp->off_heap);
message = copy_struct(message, msize, &hp, &bp->off_heap);
+#ifdef USE_VM_PROBES
+ if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
+ utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap);
+#ifdef DTRACE_TAG_HARDDEBUG
+ erts_fprintf(stderr,
+ "Dtrace -> (%T) Spreading tag (%T) with "
+ "message %T!\r\n",sender->id, utag, message);
+#endif
+ }
+#endif
BM_MESSAGE_COPIED(msize);
BM_SWAP_TIMER(copy,send);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(message_send)) {
+ if (stoken != NIL && stoken != am_have_dt_utag) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken));
+ }
+ DTRACE6(message_send, sender_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
+ }
+#endif
erts_queue_message(receiver,
receiver_locks,
bp,
message,
- token);
- BM_SWAP_TIMER(send,system);
-#ifdef HYBRID
- } else {
- ErlMessage* mp = message_alloc();
- BM_SWAP_TIMER(send,copy);
-#ifdef INCREMENTAL
- /* TODO: During GC activate processes if the message relies in
- * the fromspace and the sender is active. During major
- * collections add the message to the gray stack if it relies
- * in the old generation and the sender is active and the
- * receiver is inactive.
-
- if (!IS_CONST(message) && (ma_gc_flags & GC_CYCLE) &&
- (ptr_val(message) >= inc_fromspc &&
- ptr_val(message) < inc_fromend) && INC_IS_ACTIVE(sender))
- INC_ACTIVATE(receiver);
- else if (!IS_CONST(message) && (ma_gc_flags & GC_CYCLE) &&
- (ptr_val(message) >= global_old_heap &&
- ptr_val(message) < global_old_hend) &&
- INC_IS_ACTIVE(sender) && !INC_IS_ACTIVE(receiver))
- Mark message in blackmap and add it to the gray stack
- */
-
- if (!IS_CONST(message))
- INC_ACTIVATE(receiver);
-#endif
- LAZY_COPY(sender,message);
- BM_SWAP_TIMER(copy,send);
- ERL_MESSAGE_TERM(mp) = message;
- ERL_MESSAGE_TOKEN(mp) = NIL;
- mp->next = NULL;
- LINK_MESSAGE(receiver, mp);
- ACTIVATE(receiver);
-
- if (receiver->status == P_WAITING) {
- erts_add_to_runq(receiver);
- } else if (receiver->status == P_SUSPENDED) {
- receiver->rstatus = P_RUNABLE;
- }
- if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
- trace_receive(receiver, message);
- }
-
+ token
+#ifdef USE_VM_PROBES
+ , utag
+#endif
+ );
BM_SWAP_TIMER(send,system);
- return;
-#else
} else if (sender == receiver) {
/* Drop message if receiver has a pending exit ... */
#ifdef ERTS_SMP
@@ -874,9 +1005,14 @@ erts_send_message(Process* sender,
{
ErlMessage* mp = message_alloc();
+ DTRACE6(message_send, sender_name, receiver_name,
+ size_object(message), tok_label, tok_lastcnt, tok_serial);
mp->data.attached = NULL;
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = NIL;
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+#endif
mp->next = NULL;
/*
* We move 'in queue' to 'private queue' and place
@@ -908,7 +1044,13 @@ erts_send_message(Process* sender,
message = copy_struct(message, msize, &hp, ohp);
BM_MESSAGE_COPIED(msz);
BM_SWAP_TIMER(copy,send);
- erts_queue_message(receiver, receiver_locks, bp, message, token);
+ DTRACE6(message_send, sender_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
+ erts_queue_message(receiver, receiver_locks, bp, message, token
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
BM_SWAP_TIMER(send,system);
#else
ErlMessage* mp = message_alloc();
@@ -928,8 +1070,13 @@ erts_send_message(Process* sender,
message = copy_struct(message, msize, &hp, &receiver->off_heap);
BM_MESSAGE_COPIED(msize);
BM_SWAP_TIMER(copy,send);
+ DTRACE6(message_send, sender_name, receiver_name,
+ (uint32_t)msize, tok_label, tok_lastcnt, tok_serial);
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = NIL;
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+#endif
mp->next = NULL;
mp->data.attached = NULL;
LINK_MESSAGE(receiver, mp);
@@ -945,7 +1092,6 @@ erts_send_message(Process* sender,
BM_SWAP_TIMER(send,system);
#endif /* #ifndef ERTS_SMP */
return;
-#endif /* HYBRID */
}
}
@@ -968,7 +1114,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
Eterm temptoken;
ErlHeapFragment* bp = NULL;
- if (token != NIL) {
+ if (token != NIL
+#ifdef USE_VM_PROBES
+ && token != am_have_dt_utag
+#endif
+ ) {
ASSERT(is_tuple(token));
sz_reason = size_object(reason);
@@ -983,7 +1133,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, save, SEQ_TRACE_SEND, to->id, NULL);
temptoken = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, save, temptoken);
+ erts_queue_message(to, to_locksp, bp, save, temptoken
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
} else {
ErlOffHeap *ohp;
sz_reason = size_object(reason);
@@ -1000,7 +1154,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
? from
: copy_struct(from, sz_from, &hp, ohp));
save = TUPLE3(hp, am_EXIT, from_copy, mess);
- erts_queue_message(to, to_locksp, bp, save, NIL);
+ erts_queue_message(to, to_locksp, bp, save, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
}
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index 5aca0db6fe..3e9a24ee81 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2012. All Rights Reserved.
*
* The 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,11 +70,18 @@ typedef struct erl_mesg {
ErlHeapFragment *heap_frag;
void *attached;
} data;
+#ifdef USE_VM_PROBES
+ Eterm m[3]; /* m[0] = message, m[1] = seq trace token, m[3] = dynamic trace user tag */
+#else
Eterm m[2]; /* m[0] = message, m[1] = seq trace token */
+#endif
} ErlMessage;
#define ERL_MESSAGE_TERM(mp) ((mp)->m[0])
#define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1])
+#ifdef USE_VM_PROBES
+#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2])
+#endif
/* Size of default message buffer (erl_message.c) */
#define ERL_MESSAGE_BUF_SZ 500
@@ -221,7 +228,11 @@ ErlHeapFragment* erts_resize_message_buffer(ErlHeapFragment *, Uint,
Eterm *, Uint);
void free_message_buffer(ErlHeapFragment *);
void erts_queue_dist_message(Process*, ErtsProcLocks*, ErtsDistExternal *, Eterm);
-void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm);
+void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm
+#ifdef USE_VM_PROBES
+ , Eterm dt_utag
+#endif
+);
void erts_deliver_exit_message(Eterm, Process*, ErtsProcLocks *, Eterm, Eterm);
void erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm, unsigned);
void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp);
diff --git a/erts/emulator/beam/erl_monitors.c b/erts/emulator/beam/erl_monitors.c
index 47597f302b..1a84950120 100644
--- a/erts/emulator/beam/erl_monitors.c
+++ b/erts/emulator/beam/erl_monitors.c
@@ -948,8 +948,10 @@ static void erts_dump_links(ErtsLink *root, int indent)
erts_destroy_tmp_dsbuf(dsbufp);
}
-Eterm erts_debug_dump_monitors_1(Process *p, Eterm pid)
+Eterm erts_debug_dump_monitors_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm pid = BIF_ARG_1;
Process *rp;
DistEntry *dep;
rp = erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, pid, ERTS_PROC_LOCK_LINK);
@@ -976,8 +978,10 @@ Eterm erts_debug_dump_monitors_1(Process *p, Eterm pid)
}
}
-Eterm erts_debug_dump_links_1(Process *p, Eterm pid)
+Eterm erts_debug_dump_links_1(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm pid = BIF_ARG_1;
Process *rp;
DistEntry *dep;
if (is_internal_port(pid)) {
diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c
index b1478758a1..358c67bf20 100644
--- a/erts/emulator/beam/erl_mtrace.c
+++ b/erts/emulator/beam/erl_mtrace.c
@@ -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
@@ -503,12 +503,6 @@ write_trace_header(char *nodename, char *pid, char *hostname)
case ERTS_ALC_A_SYSTEM:
PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
break;
- case ERTS_ALC_A_FIXED_SIZE:
- if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled)
- PUT_UI16(tracep, ERTS_FIX_CORE_ALLOCATOR);
- else
- PUT_UI16(tracep, ERTS_ALC_A_SYSTEM);
- break;
default:
PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
break;
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index f3db3f9326..4109c20fa7 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2012. All Rights Reserved.
*
* The 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,11 @@
#include "error.h"
#include "big.h"
#include "beam_bp.h"
+#include "erl_thr_progress.h"
+#include "dtrace-wrapper.h"
+#if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP))
+#define HAVE_USE_DTRACE 1
+#endif
#include <limits.h>
#include <stddef.h> /* offsetof */
@@ -65,6 +70,9 @@ static void add_readonly_check(ErlNifEnv*, unsigned char* ptr, unsigned sz);
static int is_offheap(const ErlOffHeap* off_heap);
#endif
+#ifdef USE_VM_PROBES
+void dtrace_nifenv_str(ErlNifEnv *, char *);
+#endif
#define MIN_HEAP_FRAG_SZ 200
static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp);
@@ -130,10 +138,13 @@ static void pre_nif_noproc(ErlNifEnv* env, struct erl_module_nif* mod_nif)
env->tmp_obj_list = NULL;
}
-/* Temporary object header, auto-deallocated when NIF returns. */
+/* Temporary object header, auto-deallocated when NIF returns
+ * or when independent environment is cleared.
+ */
struct enif_tmp_obj_t {
struct enif_tmp_obj_t* next;
void (*dtor)(struct enif_tmp_obj_t*);
+ ErtsAlcType_t allocator;
/*char data[];*/
};
@@ -244,7 +255,7 @@ ErlNifEnv* enif_alloc_env(void)
msg_env->env.hp_end = phony_heap;
msg_env->env.heap_frag = NULL;
msg_env->env.mod_nif = NULL;
- msg_env->env.tmp_obj_list = (struct enif_tmp_obj_t*) 1; /* invalid non-NULL */
+ msg_env->env.tmp_obj_list = NULL;
msg_env->env.proc = &msg_env->phony_proc;
memset(&msg_env->phony_proc, 0, sizeof(Process));
HEAP_START(&msg_env->phony_proc) = phony_heap;
@@ -289,6 +300,7 @@ void enif_clear_env(ErlNifEnv* env)
menv->env.hp = menv->env.hp_end = HEAP_TOP(p);
ASSERT(!is_offheap(&MSO(p)));
+ free_tmp_objs(env);
}
int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ErlNifEnv* msg_env, ERL_NIF_TERM msg)
@@ -345,7 +357,11 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
if (flush_me) {
flush_env(env); /* Needed for ERTS_HOLE_CHECK */
}
- erts_queue_message(rp, &rp_locks, frags, msg, am_undefined);
+ erts_queue_message(rp, &rp_locks, frags, msg, am_undefined
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
if (rp_locks) {
ERTS_SMP_LC_ASSERT(rp_locks == (rp_had_locks | (ERTS_PROC_LOCK_MSGQ |
ERTS_PROC_LOCK_STATUS)));
@@ -435,24 +451,36 @@ int enif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term)
return term == THE_NON_VALUE;
}
+int enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)
+{
+ return is_number(term);
+}
+
+static ERTS_INLINE int is_proc_bound(ErlNifEnv* env)
+{
+ return env->mod_nif != NULL;
+}
+
static void aligned_binary_dtor(struct enif_tmp_obj_t* obj)
{
- erts_free_aligned_binary_bytes_extra((byte*)obj,ERTS_ALC_T_TMP);
+ erts_free_aligned_binary_bytes_extra((byte*)obj, obj->allocator);
}
int enif_inspect_binary(ErlNifEnv* env, Eterm bin_term, ErlNifBinary* bin)
{
+ ErtsAlcType_t allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF;
union {
struct enif_tmp_obj_t* tmp;
byte* raw_ptr;
}u;
u.tmp = NULL;
- bin->data = erts_get_aligned_binary_bytes_extra(bin_term, &u.raw_ptr, ERTS_ALC_T_TMP,
+ bin->data = erts_get_aligned_binary_bytes_extra(bin_term, &u.raw_ptr, allocator,
sizeof(struct enif_tmp_obj_t));
if (bin->data == NULL) {
return 0;
}
if (u.tmp != NULL) {
+ u.tmp->allocator = allocator;
u.tmp->next = env->tmp_obj_list;
u.tmp->dtor = &aligned_binary_dtor;
env->tmp_obj_list = u.tmp;
@@ -466,12 +494,13 @@ int enif_inspect_binary(ErlNifEnv* env, Eterm bin_term, ErlNifBinary* bin)
static void tmp_alloc_dtor(struct enif_tmp_obj_t* obj)
{
- erts_free(ERTS_ALC_T_TMP, obj);
+ erts_free(obj->allocator, obj);
}
int enif_inspect_iolist_as_binary(ErlNifEnv* env, Eterm term, ErlNifBinary* bin)
{
struct enif_tmp_obj_t* tobj;
+ ErtsAlcType_t allocator;
Uint sz;
if (is_binary(term)) {
return enif_inspect_binary(env,term,bin);
@@ -486,8 +515,10 @@ int enif_inspect_iolist_as_binary(ErlNifEnv* env, Eterm term, ErlNifBinary* bin)
if (erts_iolist_size(term, &sz)) {
return 0;
}
-
- tobj = erts_alloc(ERTS_ALC_T_TMP, sz + sizeof(struct enif_tmp_obj_t));
+
+ allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF;
+ tobj = erts_alloc(allocator, sz + sizeof(struct enif_tmp_obj_t));
+ tobj->allocator = allocator;
tobj->next = env->tmp_obj_list;
tobj->dtor = &tmp_alloc_dtor;
env->tmp_obj_list = tobj;
@@ -511,7 +542,7 @@ int enif_alloc_binary(size_t size, ErlNifBinary* bin)
}
refbin->flags = BIN_FLAG_DRV; /* BUGBUG: Flag? */
erts_refc_init(&refbin->refc, 1);
- refbin->orig_size = (long) size;
+ refbin->orig_size = (SWord) size;
bin->size = size;
bin->data = (unsigned char*) refbin->orig_bytes;
@@ -676,6 +707,7 @@ Eterm enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term,
ErlSubBin* sb;
Eterm orig;
Uint offset, bit_offset, bit_size;
+#ifdef DEBUG
unsigned src_size;
ASSERT(is_binary(bin_term));
@@ -683,6 +715,7 @@ Eterm enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term,
ASSERT(pos <= src_size);
ASSERT(size <= src_size);
ASSERT(pos + size <= src_size);
+#endif
sb = (ErlSubBin*) alloc_heap(env, ERL_SUB_BIN_SIZE);
ERTS_GET_REAL_BIN(bin_term, orig, offset, bit_offset, bit_size);
sb->thing_word = HEADER_SUB_BIN;
@@ -722,7 +755,8 @@ int enif_get_int(ErlNifEnv* env, Eterm term, int* ip)
{
#if SIZEOF_INT == ERTS_SIZEOF_ETERM
return term_to_Sint(term, (Sint*)ip);
-#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM
+#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \
+ (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM)
Sint i;
if (!term_to_Sint(term, &i) || i < INT_MIN || i > INT_MAX) {
return 0;
@@ -738,7 +772,8 @@ int enif_get_uint(ErlNifEnv* env, Eterm term, unsigned* ip)
{
#if SIZEOF_INT == ERTS_SIZEOF_ETERM
return term_to_Uint(term, (Uint*)ip);
-#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM
+#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \
+ (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM)
Uint i;
if (!term_to_Uint(term, &i) || i > UINT_MAX) {
return 0;
@@ -754,6 +789,13 @@ int enif_get_long(ErlNifEnv* env, Eterm term, long* ip)
return term_to_Sint(term, ip);
#elif SIZEOF_LONG == 8
return term_to_Sint64(term, ip);
+#elif SIZEOF_LONG == SIZEOF_INT
+ int tmp,ret;
+ ret = enif_get_int(env,term,&tmp);
+ if (ret) {
+ *ip = (long) tmp;
+ }
+ return ret;
#else
# error Unknown long word size
#endif
@@ -765,6 +807,14 @@ int enif_get_ulong(ErlNifEnv* env, Eterm term, unsigned long* ip)
return term_to_Uint(term, ip);
#elif SIZEOF_LONG == 8
return term_to_Uint64(term, ip);
+#elif SIZEOF_LONG == SIZEOF_INT
+ int ret;
+ unsigned int tmp;
+ ret = enif_get_uint(env,term,&tmp);
+ if (ret) {
+ *ip = (unsigned long) tmp;
+ }
+ return ret;
#else
# error Unknown long word size
#endif
@@ -825,7 +875,8 @@ ERL_NIF_TERM enif_make_int(ErlNifEnv* env, int i)
{
#if SIZEOF_INT == ERTS_SIZEOF_ETERM
return IS_SSMALL(i) ? make_small(i) : small_to_big(i,alloc_heap(env,2));
-#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM
+#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \
+ (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM)
return make_small(i);
#endif
}
@@ -834,7 +885,8 @@ ERL_NIF_TERM enif_make_uint(ErlNifEnv* env, unsigned i)
{
#if SIZEOF_INT == ERTS_SIZEOF_ETERM
return IS_USMALL(0,i) ? make_small(i) : uint_to_big(i,alloc_heap(env,2));
-#elif SIZEOF_LONG == ERTS_SIZEOF_ETERM
+#elif (SIZEOF_LONG == ERTS_SIZEOF_ETERM) || \
+ (SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM)
return make_small(i);
#endif
}
@@ -846,6 +898,8 @@ ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long i)
}
#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
return small_to_big(i, alloc_heap(env,2));
+#elif SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM
+ return make_small(i);
#elif SIZEOF_LONG == 8
ensure_heap(env,3);
return erts_sint64_to_big(i, &env->hp);
@@ -859,6 +913,8 @@ ERL_NIF_TERM enif_make_ulong(ErlNifEnv* env, unsigned long i)
}
#if SIZEOF_LONG == ERTS_SIZEOF_ETERM
return uint_to_big(i,alloc_heap(env,2));
+#elif SIZEOF_LONG_LONG == ERTS_SIZEOF_ETERM
+ return make_small(i);
#elif SIZEOF_LONG == 8
ensure_heap(env,3);
return erts_uint64_to_big(i, &env->hp);
@@ -1135,7 +1191,7 @@ static ErlNifResourceType* find_resource_type(Eterm module, Eterm name)
}
#define in_area(ptr,start,nbytes) \
- ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
static void close_lib(struct erl_module_nif* lib)
@@ -1183,7 +1239,7 @@ enif_open_resource_type(ErlNifEnv* env,
ErlNifResourceFlags op = flags;
Eterm module_am, name_am;
- ASSERT(erts_smp_is_system_blocked(0));
+ ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(module_str == NULL); /* for now... */
module_am = make_atom(env->mod_nif->mod->module);
name_am = enif_make_atom(env, name_str);
@@ -1462,6 +1518,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
Eterm ret = am_ok;
int veto;
struct erl_module_nif* lib = NULL;
+ int reload_warning = 0;
len = list_length(BIF_ARG_1);
if (len < 0) {
@@ -1477,7 +1534,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
/* Block system (is this the right place to do it?) */
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* Find calling module */
ASSERT(BIF_P->current != NULL);
@@ -1601,6 +1658,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
else {
mod->nif->entry = NULL; /* to prevent 'unload' callback */
erts_unload_nif(mod->nif);
+ reload_warning = 1;
}
}
else {
@@ -1647,7 +1705,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
}
else { /* Function traced, patch the original instruction word */
BpData** bps = (BpData**) code_ptr[1];
- BpData* bp = (BpData*) bps[bp_sched2ix()];
+ BpData* bp = (BpData*) bps[erts_bp_sched2ix()];
bp->orig_instr = (BeamInstr) BeamOp(op_call_nif);
}
code_ptr[5+1] = (BeamInstr) entry->funcs[i].fptr;
@@ -1666,9 +1724,18 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
erts_sys_ddll_free_error(&errdesc);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_free(ERTS_ALC_T_TMP, lib_name);
+
+ if (reload_warning) {
+ erts_dsprintf_buf_t* dsbufp = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbufp,
+ "Repeated calls to erlang:load_nif from module '%T'.\n\n"
+ "The NIF reload mechanism is deprecated and must not "
+ "be used in production systems.\n", mod_atom);
+ erts_send_warning_to_logger(BIF_P->group_leader, dsbufp);
+ }
BIF_RET(ret);
}
@@ -1678,7 +1745,7 @@ erts_unload_nif(struct erl_module_nif* lib)
{
ErlNifResourceType* rt;
ErlNifResourceType* next;
- ASSERT(erts_smp_is_system_blocked(0));
+ ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(lib != NULL);
ASSERT(lib->mod != NULL);
for (rt = resource_type_list.next;
@@ -1723,6 +1790,13 @@ void erl_nif_init()
resource_type_list.name = THE_NON_VALUE;
}
+#ifdef USE_VM_PROBES
+void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf)
+{
+ dtrace_pid_str(env->proc->id, process_buf);
+}
+#endif
+
#ifdef READONLY_CHECK
/* Use checksums to assert that NIFs do not write into inspected binaries
*/
@@ -1738,8 +1812,10 @@ struct readonly_check_t
};
static void add_readonly_check(ErlNifEnv* env, unsigned char* ptr, unsigned sz)
{
- struct readonly_check_t* obj = erts_alloc(ERTS_ALC_T_TMP,
+ ErtsAlcType_t allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF;
+ struct readonly_check_t* obj = erts_alloc(allocator,
sizeof(struct readonly_check_t));
+ obj->hdr.allocator = allocator;
obj->hdr.next = env->tmp_obj_list;
env->tmp_obj_list = &obj->hdr;
obj->hdr.dtor = &readonly_check_dtor;
@@ -1756,7 +1832,7 @@ static void readonly_check_dtor(struct enif_tmp_obj_t* o)
" %x != %x\r\nABORTING\r\n", chksum, obj->checksum);
abort();
}
- erts_free(ERTS_ALC_T_TMP, obj);
+ erts_free(obj->hdr.allocator, obj);
}
static unsigned calc_checksum(unsigned char* ptr, unsigned size)
{
@@ -1769,3 +1845,1079 @@ static unsigned calc_checksum(unsigned char* ptr, unsigned size)
#endif /* READONLY_CHECK */
+#ifdef HAVE_USE_DTRACE
+
+#define MESSAGE_BUFSIZ 1024
+
+static void get_string_maybe(ErlNifEnv *env, const ERL_NIF_TERM term,
+ char **ptr, char *buf, int bufsiz)
+{
+ ErlNifBinary str_bin;
+
+ if (!enif_inspect_iolist_as_binary(env, term, &str_bin) ||
+ str_bin.size > bufsiz) {
+ *ptr = NULL;
+ } else {
+ memcpy(buf, (char *) str_bin.data, str_bin.size);
+ buf[str_bin.size] = '\0';
+ *ptr = buf;
+ }
+}
+
+ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[])
+{
+ ErlNifBinary message_bin;
+ DTRACE_CHARBUF(messagebuf, MESSAGE_BUFSIZ + 1);
+
+ if (DTRACE_ENABLED(user_trace_s1)) {
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &message_bin) ||
+ message_bin.size > MESSAGE_BUFSIZ) {
+ return am_badarg;
+ }
+ memcpy(messagebuf, (char *) message_bin.data, message_bin.size);
+ messagebuf[message_bin.size] = '\0';
+ DTRACE1(user_trace_s1, messagebuf);
+ return am_true;
+ } else {
+ return am_false;
+ }
+}
+
+ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[])
+{
+ DTRACE_CHARBUF(procbuf, 32 + 1);
+ DTRACE_CHARBUF(user_tagbuf, MESSAGE_BUFSIZ + 1);
+ char *utbuf = NULL;
+ ErlNifSInt64 i1, i2, i3, i4;
+ DTRACE_CHARBUF(messagebuf1, MESSAGE_BUFSIZ + 1);
+ DTRACE_CHARBUF(messagebuf2, MESSAGE_BUFSIZ + 1);
+ DTRACE_CHARBUF(messagebuf3, MESSAGE_BUFSIZ + 1);
+ DTRACE_CHARBUF(messagebuf4, MESSAGE_BUFSIZ + 1);
+ char *mbuf1 = NULL, *mbuf2 = NULL, *mbuf3 = NULL, *mbuf4 = NULL;
+
+ if (DTRACE_ENABLED(user_trace_i4s4)) {
+ dtrace_nifenv_str(env, procbuf);
+ get_string_maybe(env, argv[0], &utbuf, user_tagbuf, MESSAGE_BUFSIZ);
+ if (! enif_get_int64(env, argv[1], &i1))
+ i1 = 0;
+ if (! enif_get_int64(env, argv[2], &i2))
+ i2 = 0;
+ if (! enif_get_int64(env, argv[3], &i3))
+ i3 = 0;
+ if (! enif_get_int64(env, argv[4], &i4))
+ i4 = 0;
+ get_string_maybe(env, argv[5], &mbuf1, messagebuf1, MESSAGE_BUFSIZ);
+ get_string_maybe(env, argv[6], &mbuf2, messagebuf2, MESSAGE_BUFSIZ);
+ get_string_maybe(env, argv[7], &mbuf3, messagebuf3, MESSAGE_BUFSIZ);
+ get_string_maybe(env, argv[8], &mbuf4, messagebuf4, MESSAGE_BUFSIZ);
+ DTRACE10(user_trace_i4s4, procbuf, utbuf,
+ i1, i2, i3, i4, mbuf1, mbuf2, mbuf3, mbuf4);
+ return am_true;
+ } else {
+ return am_false;
+ }
+}
+
+#define DTRACE10_LABEL(name, label, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ erlang_##name##label((a0), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8), (a9))
+#define N_STATEMENT(the_label) \
+ case the_label: \
+ if (DTRACE_ENABLED(user_trace_n##the_label)) { \
+ dtrace_nifenv_str(env, procbuf); \
+ get_string_maybe(env, argv[1], &utbuf, user_tagbuf, MESSAGE_BUFSIZ); \
+ if (! enif_get_int64(env, argv[2], &i1)) \
+ i1 = 0; \
+ if (! enif_get_int64(env, argv[3], &i2)) \
+ i2 = 0; \
+ if (! enif_get_int64(env, argv[4], &i3)) \
+ i3 = 0; \
+ if (! enif_get_int64(env, argv[5], &i4)) \
+ i4 = 0; \
+ get_string_maybe(env, argv[6], &mbuf1, messagebuf1, MESSAGE_BUFSIZ); \
+ get_string_maybe(env, argv[7], &mbuf2, messagebuf2, MESSAGE_BUFSIZ); \
+ get_string_maybe(env, argv[8], &mbuf3, messagebuf3, MESSAGE_BUFSIZ); \
+ get_string_maybe(env, argv[9], &mbuf4, messagebuf4, MESSAGE_BUFSIZ); \
+ DTRACE10_LABEL(user_trace_n, the_label, procbuf, utbuf, \
+ i1, i2, i3, i4, mbuf1, mbuf2, mbuf3, mbuf4); \
+ return am_true; \
+ } else { \
+ return am_false; \
+ } \
+ break
+
+ERL_NIF_TERM erl_nif_user_trace_n(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[])
+{
+ DTRACE_CHARBUF(procbuf, 32 + 1);
+ DTRACE_CHARBUF(user_tagbuf, MESSAGE_BUFSIZ + 1);
+ char *utbuf = NULL;
+ ErlNifSInt64 i1, i2, i3, i4;
+ DTRACE_CHARBUF(messagebuf1, MESSAGE_BUFSIZ + 1);
+ DTRACE_CHARBUF(messagebuf2, MESSAGE_BUFSIZ + 1);
+ DTRACE_CHARBUF(messagebuf3, MESSAGE_BUFSIZ + 1);
+ DTRACE_CHARBUF(messagebuf4, MESSAGE_BUFSIZ + 1);
+ char *mbuf1 = NULL, *mbuf2 = NULL, *mbuf3 = NULL, *mbuf4 = NULL;
+ ErlNifSInt64 label = 0;
+
+ if (! enif_get_int64(env, argv[0], &label) || label < 0 || label > 1023) {
+ return am_badarg;
+ }
+ switch (label) {
+ N_STATEMENT(0);
+ N_STATEMENT(1);
+ N_STATEMENT(2);
+ N_STATEMENT(3);
+ N_STATEMENT(4);
+ N_STATEMENT(5);
+ N_STATEMENT(6);
+ N_STATEMENT(7);
+ N_STATEMENT(8);
+ N_STATEMENT(9);
+ N_STATEMENT(10);
+ N_STATEMENT(11);
+ N_STATEMENT(12);
+ N_STATEMENT(13);
+ N_STATEMENT(14);
+ N_STATEMENT(15);
+ N_STATEMENT(16);
+ N_STATEMENT(17);
+ N_STATEMENT(18);
+ N_STATEMENT(19);
+ N_STATEMENT(20);
+ N_STATEMENT(21);
+ N_STATEMENT(22);
+ N_STATEMENT(23);
+ N_STATEMENT(24);
+ N_STATEMENT(25);
+ N_STATEMENT(26);
+ N_STATEMENT(27);
+ N_STATEMENT(28);
+ N_STATEMENT(29);
+ N_STATEMENT(30);
+ N_STATEMENT(31);
+ N_STATEMENT(32);
+ N_STATEMENT(33);
+ N_STATEMENT(34);
+ N_STATEMENT(35);
+ N_STATEMENT(36);
+ N_STATEMENT(37);
+ N_STATEMENT(38);
+ N_STATEMENT(39);
+ N_STATEMENT(40);
+ N_STATEMENT(41);
+ N_STATEMENT(42);
+ N_STATEMENT(43);
+ N_STATEMENT(44);
+ N_STATEMENT(45);
+ N_STATEMENT(46);
+ N_STATEMENT(47);
+ N_STATEMENT(48);
+ N_STATEMENT(49);
+ N_STATEMENT(50);
+ N_STATEMENT(51);
+ N_STATEMENT(52);
+ N_STATEMENT(53);
+ N_STATEMENT(54);
+ N_STATEMENT(55);
+ N_STATEMENT(56);
+ N_STATEMENT(57);
+ N_STATEMENT(58);
+ N_STATEMENT(59);
+ N_STATEMENT(60);
+ N_STATEMENT(61);
+ N_STATEMENT(62);
+ N_STATEMENT(63);
+ N_STATEMENT(64);
+ N_STATEMENT(65);
+ N_STATEMENT(66);
+ N_STATEMENT(67);
+ N_STATEMENT(68);
+ N_STATEMENT(69);
+ N_STATEMENT(70);
+ N_STATEMENT(71);
+ N_STATEMENT(72);
+ N_STATEMENT(73);
+ N_STATEMENT(74);
+ N_STATEMENT(75);
+ N_STATEMENT(76);
+ N_STATEMENT(77);
+ N_STATEMENT(78);
+ N_STATEMENT(79);
+ N_STATEMENT(80);
+ N_STATEMENT(81);
+ N_STATEMENT(82);
+ N_STATEMENT(83);
+ N_STATEMENT(84);
+ N_STATEMENT(85);
+ N_STATEMENT(86);
+ N_STATEMENT(87);
+ N_STATEMENT(88);
+ N_STATEMENT(89);
+ N_STATEMENT(90);
+ N_STATEMENT(91);
+ N_STATEMENT(92);
+ N_STATEMENT(93);
+ N_STATEMENT(94);
+ N_STATEMENT(95);
+ N_STATEMENT(96);
+ N_STATEMENT(97);
+ N_STATEMENT(98);
+ N_STATEMENT(99);
+ N_STATEMENT(100);
+ N_STATEMENT(101);
+ N_STATEMENT(102);
+ N_STATEMENT(103);
+ N_STATEMENT(104);
+ N_STATEMENT(105);
+ N_STATEMENT(106);
+ N_STATEMENT(107);
+ N_STATEMENT(108);
+ N_STATEMENT(109);
+ N_STATEMENT(110);
+ N_STATEMENT(111);
+ N_STATEMENT(112);
+ N_STATEMENT(113);
+ N_STATEMENT(114);
+ N_STATEMENT(115);
+ N_STATEMENT(116);
+ N_STATEMENT(117);
+ N_STATEMENT(118);
+ N_STATEMENT(119);
+ N_STATEMENT(120);
+ N_STATEMENT(121);
+ N_STATEMENT(122);
+ N_STATEMENT(123);
+ N_STATEMENT(124);
+ N_STATEMENT(125);
+ N_STATEMENT(126);
+ N_STATEMENT(127);
+ N_STATEMENT(128);
+ N_STATEMENT(129);
+ N_STATEMENT(130);
+ N_STATEMENT(131);
+ N_STATEMENT(132);
+ N_STATEMENT(133);
+ N_STATEMENT(134);
+ N_STATEMENT(135);
+ N_STATEMENT(136);
+ N_STATEMENT(137);
+ N_STATEMENT(138);
+ N_STATEMENT(139);
+ N_STATEMENT(140);
+ N_STATEMENT(141);
+ N_STATEMENT(142);
+ N_STATEMENT(143);
+ N_STATEMENT(144);
+ N_STATEMENT(145);
+ N_STATEMENT(146);
+ N_STATEMENT(147);
+ N_STATEMENT(148);
+ N_STATEMENT(149);
+ N_STATEMENT(150);
+ N_STATEMENT(151);
+ N_STATEMENT(152);
+ N_STATEMENT(153);
+ N_STATEMENT(154);
+ N_STATEMENT(155);
+ N_STATEMENT(156);
+ N_STATEMENT(157);
+ N_STATEMENT(158);
+ N_STATEMENT(159);
+ N_STATEMENT(160);
+ N_STATEMENT(161);
+ N_STATEMENT(162);
+ N_STATEMENT(163);
+ N_STATEMENT(164);
+ N_STATEMENT(165);
+ N_STATEMENT(166);
+ N_STATEMENT(167);
+ N_STATEMENT(168);
+ N_STATEMENT(169);
+ N_STATEMENT(170);
+ N_STATEMENT(171);
+ N_STATEMENT(172);
+ N_STATEMENT(173);
+ N_STATEMENT(174);
+ N_STATEMENT(175);
+ N_STATEMENT(176);
+ N_STATEMENT(177);
+ N_STATEMENT(178);
+ N_STATEMENT(179);
+ N_STATEMENT(180);
+ N_STATEMENT(181);
+ N_STATEMENT(182);
+ N_STATEMENT(183);
+ N_STATEMENT(184);
+ N_STATEMENT(185);
+ N_STATEMENT(186);
+ N_STATEMENT(187);
+ N_STATEMENT(188);
+ N_STATEMENT(189);
+ N_STATEMENT(190);
+ N_STATEMENT(191);
+ N_STATEMENT(192);
+ N_STATEMENT(193);
+ N_STATEMENT(194);
+ N_STATEMENT(195);
+ N_STATEMENT(196);
+ N_STATEMENT(197);
+ N_STATEMENT(198);
+ N_STATEMENT(199);
+ N_STATEMENT(200);
+ N_STATEMENT(201);
+ N_STATEMENT(202);
+ N_STATEMENT(203);
+ N_STATEMENT(204);
+ N_STATEMENT(205);
+ N_STATEMENT(206);
+ N_STATEMENT(207);
+ N_STATEMENT(208);
+ N_STATEMENT(209);
+ N_STATEMENT(210);
+ N_STATEMENT(211);
+ N_STATEMENT(212);
+ N_STATEMENT(213);
+ N_STATEMENT(214);
+ N_STATEMENT(215);
+ N_STATEMENT(216);
+ N_STATEMENT(217);
+ N_STATEMENT(218);
+ N_STATEMENT(219);
+ N_STATEMENT(220);
+ N_STATEMENT(221);
+ N_STATEMENT(222);
+ N_STATEMENT(223);
+ N_STATEMENT(224);
+ N_STATEMENT(225);
+ N_STATEMENT(226);
+ N_STATEMENT(227);
+ N_STATEMENT(228);
+ N_STATEMENT(229);
+ N_STATEMENT(230);
+ N_STATEMENT(231);
+ N_STATEMENT(232);
+ N_STATEMENT(233);
+ N_STATEMENT(234);
+ N_STATEMENT(235);
+ N_STATEMENT(236);
+ N_STATEMENT(237);
+ N_STATEMENT(238);
+ N_STATEMENT(239);
+ N_STATEMENT(240);
+ N_STATEMENT(241);
+ N_STATEMENT(242);
+ N_STATEMENT(243);
+ N_STATEMENT(244);
+ N_STATEMENT(245);
+ N_STATEMENT(246);
+ N_STATEMENT(247);
+ N_STATEMENT(248);
+ N_STATEMENT(249);
+ N_STATEMENT(250);
+ N_STATEMENT(251);
+ N_STATEMENT(252);
+ N_STATEMENT(253);
+ N_STATEMENT(254);
+ N_STATEMENT(255);
+ N_STATEMENT(256);
+ N_STATEMENT(257);
+ N_STATEMENT(258);
+ N_STATEMENT(259);
+ N_STATEMENT(260);
+ N_STATEMENT(261);
+ N_STATEMENT(262);
+ N_STATEMENT(263);
+ N_STATEMENT(264);
+ N_STATEMENT(265);
+ N_STATEMENT(266);
+ N_STATEMENT(267);
+ N_STATEMENT(268);
+ N_STATEMENT(269);
+ N_STATEMENT(270);
+ N_STATEMENT(271);
+ N_STATEMENT(272);
+ N_STATEMENT(273);
+ N_STATEMENT(274);
+ N_STATEMENT(275);
+ N_STATEMENT(276);
+ N_STATEMENT(277);
+ N_STATEMENT(278);
+ N_STATEMENT(279);
+ N_STATEMENT(280);
+ N_STATEMENT(281);
+ N_STATEMENT(282);
+ N_STATEMENT(283);
+ N_STATEMENT(284);
+ N_STATEMENT(285);
+ N_STATEMENT(286);
+ N_STATEMENT(287);
+ N_STATEMENT(288);
+ N_STATEMENT(289);
+ N_STATEMENT(290);
+ N_STATEMENT(291);
+ N_STATEMENT(292);
+ N_STATEMENT(293);
+ N_STATEMENT(294);
+ N_STATEMENT(295);
+ N_STATEMENT(296);
+ N_STATEMENT(297);
+ N_STATEMENT(298);
+ N_STATEMENT(299);
+ N_STATEMENT(300);
+ N_STATEMENT(301);
+ N_STATEMENT(302);
+ N_STATEMENT(303);
+ N_STATEMENT(304);
+ N_STATEMENT(305);
+ N_STATEMENT(306);
+ N_STATEMENT(307);
+ N_STATEMENT(308);
+ N_STATEMENT(309);
+ N_STATEMENT(310);
+ N_STATEMENT(311);
+ N_STATEMENT(312);
+ N_STATEMENT(313);
+ N_STATEMENT(314);
+ N_STATEMENT(315);
+ N_STATEMENT(316);
+ N_STATEMENT(317);
+ N_STATEMENT(318);
+ N_STATEMENT(319);
+ N_STATEMENT(320);
+ N_STATEMENT(321);
+ N_STATEMENT(322);
+ N_STATEMENT(323);
+ N_STATEMENT(324);
+ N_STATEMENT(325);
+ N_STATEMENT(326);
+ N_STATEMENT(327);
+ N_STATEMENT(328);
+ N_STATEMENT(329);
+ N_STATEMENT(330);
+ N_STATEMENT(331);
+ N_STATEMENT(332);
+ N_STATEMENT(333);
+ N_STATEMENT(334);
+ N_STATEMENT(335);
+ N_STATEMENT(336);
+ N_STATEMENT(337);
+ N_STATEMENT(338);
+ N_STATEMENT(339);
+ N_STATEMENT(340);
+ N_STATEMENT(341);
+ N_STATEMENT(342);
+ N_STATEMENT(343);
+ N_STATEMENT(344);
+ N_STATEMENT(345);
+ N_STATEMENT(346);
+ N_STATEMENT(347);
+ N_STATEMENT(348);
+ N_STATEMENT(349);
+ N_STATEMENT(350);
+ N_STATEMENT(351);
+ N_STATEMENT(352);
+ N_STATEMENT(353);
+ N_STATEMENT(354);
+ N_STATEMENT(355);
+ N_STATEMENT(356);
+ N_STATEMENT(357);
+ N_STATEMENT(358);
+ N_STATEMENT(359);
+ N_STATEMENT(360);
+ N_STATEMENT(361);
+ N_STATEMENT(362);
+ N_STATEMENT(363);
+ N_STATEMENT(364);
+ N_STATEMENT(365);
+ N_STATEMENT(366);
+ N_STATEMENT(367);
+ N_STATEMENT(368);
+ N_STATEMENT(369);
+ N_STATEMENT(370);
+ N_STATEMENT(371);
+ N_STATEMENT(372);
+ N_STATEMENT(373);
+ N_STATEMENT(374);
+ N_STATEMENT(375);
+ N_STATEMENT(376);
+ N_STATEMENT(377);
+ N_STATEMENT(378);
+ N_STATEMENT(379);
+ N_STATEMENT(380);
+ N_STATEMENT(381);
+ N_STATEMENT(382);
+ N_STATEMENT(383);
+ N_STATEMENT(384);
+ N_STATEMENT(385);
+ N_STATEMENT(386);
+ N_STATEMENT(387);
+ N_STATEMENT(388);
+ N_STATEMENT(389);
+ N_STATEMENT(390);
+ N_STATEMENT(391);
+ N_STATEMENT(392);
+ N_STATEMENT(393);
+ N_STATEMENT(394);
+ N_STATEMENT(395);
+ N_STATEMENT(396);
+ N_STATEMENT(397);
+ N_STATEMENT(398);
+ N_STATEMENT(399);
+ N_STATEMENT(400);
+ N_STATEMENT(401);
+ N_STATEMENT(402);
+ N_STATEMENT(403);
+ N_STATEMENT(404);
+ N_STATEMENT(405);
+ N_STATEMENT(406);
+ N_STATEMENT(407);
+ N_STATEMENT(408);
+ N_STATEMENT(409);
+ N_STATEMENT(410);
+ N_STATEMENT(411);
+ N_STATEMENT(412);
+ N_STATEMENT(413);
+ N_STATEMENT(414);
+ N_STATEMENT(415);
+ N_STATEMENT(416);
+ N_STATEMENT(417);
+ N_STATEMENT(418);
+ N_STATEMENT(419);
+ N_STATEMENT(420);
+ N_STATEMENT(421);
+ N_STATEMENT(422);
+ N_STATEMENT(423);
+ N_STATEMENT(424);
+ N_STATEMENT(425);
+ N_STATEMENT(426);
+ N_STATEMENT(427);
+ N_STATEMENT(428);
+ N_STATEMENT(429);
+ N_STATEMENT(430);
+ N_STATEMENT(431);
+ N_STATEMENT(432);
+ N_STATEMENT(433);
+ N_STATEMENT(434);
+ N_STATEMENT(435);
+ N_STATEMENT(436);
+ N_STATEMENT(437);
+ N_STATEMENT(438);
+ N_STATEMENT(439);
+ N_STATEMENT(440);
+ N_STATEMENT(441);
+ N_STATEMENT(442);
+ N_STATEMENT(443);
+ N_STATEMENT(444);
+ N_STATEMENT(445);
+ N_STATEMENT(446);
+ N_STATEMENT(447);
+ N_STATEMENT(448);
+ N_STATEMENT(449);
+ N_STATEMENT(450);
+ N_STATEMENT(451);
+ N_STATEMENT(452);
+ N_STATEMENT(453);
+ N_STATEMENT(454);
+ N_STATEMENT(455);
+ N_STATEMENT(456);
+ N_STATEMENT(457);
+ N_STATEMENT(458);
+ N_STATEMENT(459);
+ N_STATEMENT(460);
+ N_STATEMENT(461);
+ N_STATEMENT(462);
+ N_STATEMENT(463);
+ N_STATEMENT(464);
+ N_STATEMENT(465);
+ N_STATEMENT(466);
+ N_STATEMENT(467);
+ N_STATEMENT(468);
+ N_STATEMENT(469);
+ N_STATEMENT(470);
+ N_STATEMENT(471);
+ N_STATEMENT(472);
+ N_STATEMENT(473);
+ N_STATEMENT(474);
+ N_STATEMENT(475);
+ N_STATEMENT(476);
+ N_STATEMENT(477);
+ N_STATEMENT(478);
+ N_STATEMENT(479);
+ N_STATEMENT(480);
+ N_STATEMENT(481);
+ N_STATEMENT(482);
+ N_STATEMENT(483);
+ N_STATEMENT(484);
+ N_STATEMENT(485);
+ N_STATEMENT(486);
+ N_STATEMENT(487);
+ N_STATEMENT(488);
+ N_STATEMENT(489);
+ N_STATEMENT(490);
+ N_STATEMENT(491);
+ N_STATEMENT(492);
+ N_STATEMENT(493);
+ N_STATEMENT(494);
+ N_STATEMENT(495);
+ N_STATEMENT(496);
+ N_STATEMENT(497);
+ N_STATEMENT(498);
+ N_STATEMENT(499);
+ N_STATEMENT(500);
+ N_STATEMENT(501);
+ N_STATEMENT(502);
+ N_STATEMENT(503);
+ N_STATEMENT(504);
+ N_STATEMENT(505);
+ N_STATEMENT(506);
+ N_STATEMENT(507);
+ N_STATEMENT(508);
+ N_STATEMENT(509);
+ N_STATEMENT(510);
+ N_STATEMENT(511);
+ N_STATEMENT(512);
+ N_STATEMENT(513);
+ N_STATEMENT(514);
+ N_STATEMENT(515);
+ N_STATEMENT(516);
+ N_STATEMENT(517);
+ N_STATEMENT(518);
+ N_STATEMENT(519);
+ N_STATEMENT(520);
+ N_STATEMENT(521);
+ N_STATEMENT(522);
+ N_STATEMENT(523);
+ N_STATEMENT(524);
+ N_STATEMENT(525);
+ N_STATEMENT(526);
+ N_STATEMENT(527);
+ N_STATEMENT(528);
+ N_STATEMENT(529);
+ N_STATEMENT(530);
+ N_STATEMENT(531);
+ N_STATEMENT(532);
+ N_STATEMENT(533);
+ N_STATEMENT(534);
+ N_STATEMENT(535);
+ N_STATEMENT(536);
+ N_STATEMENT(537);
+ N_STATEMENT(538);
+ N_STATEMENT(539);
+ N_STATEMENT(540);
+ N_STATEMENT(541);
+ N_STATEMENT(542);
+ N_STATEMENT(543);
+ N_STATEMENT(544);
+ N_STATEMENT(545);
+ N_STATEMENT(546);
+ N_STATEMENT(547);
+ N_STATEMENT(548);
+ N_STATEMENT(549);
+ N_STATEMENT(550);
+ N_STATEMENT(551);
+ N_STATEMENT(552);
+ N_STATEMENT(553);
+ N_STATEMENT(554);
+ N_STATEMENT(555);
+ N_STATEMENT(556);
+ N_STATEMENT(557);
+ N_STATEMENT(558);
+ N_STATEMENT(559);
+ N_STATEMENT(560);
+ N_STATEMENT(561);
+ N_STATEMENT(562);
+ N_STATEMENT(563);
+ N_STATEMENT(564);
+ N_STATEMENT(565);
+ N_STATEMENT(566);
+ N_STATEMENT(567);
+ N_STATEMENT(568);
+ N_STATEMENT(569);
+ N_STATEMENT(570);
+ N_STATEMENT(571);
+ N_STATEMENT(572);
+ N_STATEMENT(573);
+ N_STATEMENT(574);
+ N_STATEMENT(575);
+ N_STATEMENT(576);
+ N_STATEMENT(577);
+ N_STATEMENT(578);
+ N_STATEMENT(579);
+ N_STATEMENT(580);
+ N_STATEMENT(581);
+ N_STATEMENT(582);
+ N_STATEMENT(583);
+ N_STATEMENT(584);
+ N_STATEMENT(585);
+ N_STATEMENT(586);
+ N_STATEMENT(587);
+ N_STATEMENT(588);
+ N_STATEMENT(589);
+ N_STATEMENT(590);
+ N_STATEMENT(591);
+ N_STATEMENT(592);
+ N_STATEMENT(593);
+ N_STATEMENT(594);
+ N_STATEMENT(595);
+ N_STATEMENT(596);
+ N_STATEMENT(597);
+ N_STATEMENT(598);
+ N_STATEMENT(599);
+ N_STATEMENT(600);
+ N_STATEMENT(601);
+ N_STATEMENT(602);
+ N_STATEMENT(603);
+ N_STATEMENT(604);
+ N_STATEMENT(605);
+ N_STATEMENT(606);
+ N_STATEMENT(607);
+ N_STATEMENT(608);
+ N_STATEMENT(609);
+ N_STATEMENT(610);
+ N_STATEMENT(611);
+ N_STATEMENT(612);
+ N_STATEMENT(613);
+ N_STATEMENT(614);
+ N_STATEMENT(615);
+ N_STATEMENT(616);
+ N_STATEMENT(617);
+ N_STATEMENT(618);
+ N_STATEMENT(619);
+ N_STATEMENT(620);
+ N_STATEMENT(621);
+ N_STATEMENT(622);
+ N_STATEMENT(623);
+ N_STATEMENT(624);
+ N_STATEMENT(625);
+ N_STATEMENT(626);
+ N_STATEMENT(627);
+ N_STATEMENT(628);
+ N_STATEMENT(629);
+ N_STATEMENT(630);
+ N_STATEMENT(631);
+ N_STATEMENT(632);
+ N_STATEMENT(633);
+ N_STATEMENT(634);
+ N_STATEMENT(635);
+ N_STATEMENT(636);
+ N_STATEMENT(637);
+ N_STATEMENT(638);
+ N_STATEMENT(639);
+ N_STATEMENT(640);
+ N_STATEMENT(641);
+ N_STATEMENT(642);
+ N_STATEMENT(643);
+ N_STATEMENT(644);
+ N_STATEMENT(645);
+ N_STATEMENT(646);
+ N_STATEMENT(647);
+ N_STATEMENT(648);
+ N_STATEMENT(649);
+ N_STATEMENT(650);
+ N_STATEMENT(651);
+ N_STATEMENT(652);
+ N_STATEMENT(653);
+ N_STATEMENT(654);
+ N_STATEMENT(655);
+ N_STATEMENT(656);
+ N_STATEMENT(657);
+ N_STATEMENT(658);
+ N_STATEMENT(659);
+ N_STATEMENT(660);
+ N_STATEMENT(661);
+ N_STATEMENT(662);
+ N_STATEMENT(663);
+ N_STATEMENT(664);
+ N_STATEMENT(665);
+ N_STATEMENT(666);
+ N_STATEMENT(667);
+ N_STATEMENT(668);
+ N_STATEMENT(669);
+ N_STATEMENT(670);
+ N_STATEMENT(671);
+ N_STATEMENT(672);
+ N_STATEMENT(673);
+ N_STATEMENT(674);
+ N_STATEMENT(675);
+ N_STATEMENT(676);
+ N_STATEMENT(677);
+ N_STATEMENT(678);
+ N_STATEMENT(679);
+ N_STATEMENT(680);
+ N_STATEMENT(681);
+ N_STATEMENT(682);
+ N_STATEMENT(683);
+ N_STATEMENT(684);
+ N_STATEMENT(685);
+ N_STATEMENT(686);
+ N_STATEMENT(687);
+ N_STATEMENT(688);
+ N_STATEMENT(689);
+ N_STATEMENT(690);
+ N_STATEMENT(691);
+ N_STATEMENT(692);
+ N_STATEMENT(693);
+ N_STATEMENT(694);
+ N_STATEMENT(695);
+ N_STATEMENT(696);
+ N_STATEMENT(697);
+ N_STATEMENT(698);
+ N_STATEMENT(699);
+ N_STATEMENT(700);
+ N_STATEMENT(701);
+ N_STATEMENT(702);
+ N_STATEMENT(703);
+ N_STATEMENT(704);
+ N_STATEMENT(705);
+ N_STATEMENT(706);
+ N_STATEMENT(707);
+ N_STATEMENT(708);
+ N_STATEMENT(709);
+ N_STATEMENT(710);
+ N_STATEMENT(711);
+ N_STATEMENT(712);
+ N_STATEMENT(713);
+ N_STATEMENT(714);
+ N_STATEMENT(715);
+ N_STATEMENT(716);
+ N_STATEMENT(717);
+ N_STATEMENT(718);
+ N_STATEMENT(719);
+ N_STATEMENT(720);
+ N_STATEMENT(721);
+ N_STATEMENT(722);
+ N_STATEMENT(723);
+ N_STATEMENT(724);
+ N_STATEMENT(725);
+ N_STATEMENT(726);
+ N_STATEMENT(727);
+ N_STATEMENT(728);
+ N_STATEMENT(729);
+ N_STATEMENT(730);
+ N_STATEMENT(731);
+ N_STATEMENT(732);
+ N_STATEMENT(733);
+ N_STATEMENT(734);
+ N_STATEMENT(735);
+ N_STATEMENT(736);
+ N_STATEMENT(737);
+ N_STATEMENT(738);
+ N_STATEMENT(739);
+ N_STATEMENT(740);
+ N_STATEMENT(741);
+ N_STATEMENT(742);
+ N_STATEMENT(743);
+ N_STATEMENT(744);
+ N_STATEMENT(745);
+ N_STATEMENT(746);
+ N_STATEMENT(747);
+ N_STATEMENT(748);
+ N_STATEMENT(749);
+ N_STATEMENT(750);
+ N_STATEMENT(751);
+ N_STATEMENT(752);
+ N_STATEMENT(753);
+ N_STATEMENT(754);
+ N_STATEMENT(755);
+ N_STATEMENT(756);
+ N_STATEMENT(757);
+ N_STATEMENT(758);
+ N_STATEMENT(759);
+ N_STATEMENT(760);
+ N_STATEMENT(761);
+ N_STATEMENT(762);
+ N_STATEMENT(763);
+ N_STATEMENT(764);
+ N_STATEMENT(765);
+ N_STATEMENT(766);
+ N_STATEMENT(767);
+ N_STATEMENT(768);
+ N_STATEMENT(769);
+ N_STATEMENT(770);
+ N_STATEMENT(771);
+ N_STATEMENT(772);
+ N_STATEMENT(773);
+ N_STATEMENT(774);
+ N_STATEMENT(775);
+ N_STATEMENT(776);
+ N_STATEMENT(777);
+ N_STATEMENT(778);
+ N_STATEMENT(779);
+ N_STATEMENT(780);
+ N_STATEMENT(781);
+ N_STATEMENT(782);
+ N_STATEMENT(783);
+ N_STATEMENT(784);
+ N_STATEMENT(785);
+ N_STATEMENT(786);
+ N_STATEMENT(787);
+ N_STATEMENT(788);
+ N_STATEMENT(789);
+ N_STATEMENT(790);
+ N_STATEMENT(791);
+ N_STATEMENT(792);
+ N_STATEMENT(793);
+ N_STATEMENT(794);
+ N_STATEMENT(795);
+ N_STATEMENT(796);
+ N_STATEMENT(797);
+ N_STATEMENT(798);
+ N_STATEMENT(799);
+ N_STATEMENT(800);
+ N_STATEMENT(801);
+ N_STATEMENT(802);
+ N_STATEMENT(803);
+ N_STATEMENT(804);
+ N_STATEMENT(805);
+ N_STATEMENT(806);
+ N_STATEMENT(807);
+ N_STATEMENT(808);
+ N_STATEMENT(809);
+ N_STATEMENT(810);
+ N_STATEMENT(811);
+ N_STATEMENT(812);
+ N_STATEMENT(813);
+ N_STATEMENT(814);
+ N_STATEMENT(815);
+ N_STATEMENT(816);
+ N_STATEMENT(817);
+ N_STATEMENT(818);
+ N_STATEMENT(819);
+ N_STATEMENT(820);
+ N_STATEMENT(821);
+ N_STATEMENT(822);
+ N_STATEMENT(823);
+ N_STATEMENT(824);
+ N_STATEMENT(825);
+ N_STATEMENT(826);
+ N_STATEMENT(827);
+ N_STATEMENT(828);
+ N_STATEMENT(829);
+ N_STATEMENT(830);
+ N_STATEMENT(831);
+ N_STATEMENT(832);
+ N_STATEMENT(833);
+ N_STATEMENT(834);
+ N_STATEMENT(835);
+ N_STATEMENT(836);
+ N_STATEMENT(837);
+ N_STATEMENT(838);
+ N_STATEMENT(839);
+ N_STATEMENT(840);
+ N_STATEMENT(841);
+ N_STATEMENT(842);
+ N_STATEMENT(843);
+ N_STATEMENT(844);
+ N_STATEMENT(845);
+ N_STATEMENT(846);
+ N_STATEMENT(847);
+ N_STATEMENT(848);
+ N_STATEMENT(849);
+ N_STATEMENT(850);
+ N_STATEMENT(851);
+ N_STATEMENT(852);
+ N_STATEMENT(853);
+ N_STATEMENT(854);
+ N_STATEMENT(855);
+ N_STATEMENT(856);
+ N_STATEMENT(857);
+ N_STATEMENT(858);
+ N_STATEMENT(859);
+ N_STATEMENT(860);
+ N_STATEMENT(861);
+ N_STATEMENT(862);
+ N_STATEMENT(863);
+ N_STATEMENT(864);
+ N_STATEMENT(865);
+ N_STATEMENT(866);
+ N_STATEMENT(867);
+ N_STATEMENT(868);
+ N_STATEMENT(869);
+ N_STATEMENT(870);
+ N_STATEMENT(871);
+ N_STATEMENT(872);
+ N_STATEMENT(873);
+ N_STATEMENT(874);
+ N_STATEMENT(875);
+ N_STATEMENT(876);
+ N_STATEMENT(877);
+ N_STATEMENT(878);
+ N_STATEMENT(879);
+ N_STATEMENT(880);
+ N_STATEMENT(881);
+ N_STATEMENT(882);
+ N_STATEMENT(883);
+ N_STATEMENT(884);
+ N_STATEMENT(885);
+ N_STATEMENT(886);
+ N_STATEMENT(887);
+ N_STATEMENT(888);
+ N_STATEMENT(889);
+ N_STATEMENT(890);
+ N_STATEMENT(891);
+ N_STATEMENT(892);
+ N_STATEMENT(893);
+ N_STATEMENT(894);
+ N_STATEMENT(895);
+ N_STATEMENT(896);
+ N_STATEMENT(897);
+ N_STATEMENT(898);
+ N_STATEMENT(899);
+ N_STATEMENT(900);
+ N_STATEMENT(901);
+ N_STATEMENT(902);
+ N_STATEMENT(903);
+ N_STATEMENT(904);
+ N_STATEMENT(905);
+ N_STATEMENT(906);
+ N_STATEMENT(907);
+ N_STATEMENT(908);
+ N_STATEMENT(909);
+ N_STATEMENT(910);
+ N_STATEMENT(911);
+ N_STATEMENT(912);
+ N_STATEMENT(913);
+ N_STATEMENT(914);
+ N_STATEMENT(915);
+ N_STATEMENT(916);
+ N_STATEMENT(917);
+ N_STATEMENT(918);
+ N_STATEMENT(919);
+ N_STATEMENT(920);
+ N_STATEMENT(921);
+ N_STATEMENT(922);
+ N_STATEMENT(923);
+ N_STATEMENT(924);
+ N_STATEMENT(925);
+ N_STATEMENT(926);
+ N_STATEMENT(927);
+ N_STATEMENT(928);
+ N_STATEMENT(929);
+ N_STATEMENT(930);
+ N_STATEMENT(931);
+ N_STATEMENT(932);
+ N_STATEMENT(933);
+ N_STATEMENT(934);
+ N_STATEMENT(935);
+ N_STATEMENT(936);
+ N_STATEMENT(937);
+ N_STATEMENT(938);
+ N_STATEMENT(939);
+ N_STATEMENT(940);
+ N_STATEMENT(941);
+ N_STATEMENT(942);
+ N_STATEMENT(943);
+ N_STATEMENT(944);
+ N_STATEMENT(945);
+ N_STATEMENT(946);
+ N_STATEMENT(947);
+ N_STATEMENT(948);
+ N_STATEMENT(949);
+ N_STATEMENT(950);
+ }
+ return am_error; /* NOTREACHED, shut up the compiler */
+}
+
+#endif /* HAVE_USE_DTRACE */
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index fea527f954..33e221b44c 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -87,7 +87,11 @@ typedef long long ErlNifSInt64;
typedef unsigned int ERL_NIF_TERM;
#else
# define ERL_NIF_VM_VARIANT "beam.vanilla"
+# if SIZEOF_LONG == SIZEOF_VOID_P
typedef unsigned long ERL_NIF_TERM;
+# elif SIZEOF_LONG_LONG == SIZEOF_VOID_P
+typedef unsigned long long ERL_NIF_TERM;
+# endif
#endif
struct enif_environment_t;
@@ -222,6 +226,15 @@ ERL_NIF_INIT_DECL(NAME) \
} \
ERL_NIF_INIT_EPILOGUE
+#if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP))
+#define HAVE_USE_DTRACE 1
+#endif
+
+#ifdef HAVE_USE_DTRACE
+ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM erl_nif_user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+#endif
#endif /* __ERL_NIF_H__ */
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index 4af9f61000..6396af09d0 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -137,6 +137,7 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_uint64,(ErlNifEnv*, ErlNifUInt64));
#endif
ERL_NIF_API_FUNC_DECL(int,enif_is_exception,(ErlNifEnv*, ERL_NIF_TERM term));
ERL_NIF_API_FUNC_DECL(int,enif_make_reverse_list,(ErlNifEnv*, ERL_NIF_TERM term, ERL_NIF_TERM *list));
+ERL_NIF_API_FUNC_DECL(int,enif_is_number,(ErlNifEnv*, ERL_NIF_TERM term));
/*
** Add new entries here to keep compatibility on Windows!!!
@@ -258,12 +259,206 @@ ERL_NIF_API_FUNC_DECL(int,enif_make_reverse_list,(ErlNifEnv*, ERL_NIF_TERM term,
# define enif_is_exception ERL_NIF_API_FUNC_MACRO(enif_is_exception)
# define enif_make_reverse_list ERL_NIF_API_FUNC_MACRO(enif_make_reverse_list)
+# define enif_is_number ERL_NIF_API_FUNC_MACRO(enif_is_number)
/*
** Add new entries here
*/
#endif
+
+#if defined(__GNUC__) && !(defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
+
+/* Inline functions for compile time type checking of arguments to
+ variadic functions.
+*/
+
+# define ERL_NIF_INLINE __inline__
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple1(ErlNifEnv* env,
+ ERL_NIF_TERM e1)
+{
+ return enif_make_tuple(env, 1, e1);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple2(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2)
+{
+ return enif_make_tuple(env, 2, e1, e2);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple3(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3)
+{
+ return enif_make_tuple(env, 3, e1, e2, e3);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple4(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4)
+{
+ return enif_make_tuple(env, 4, e1, e2, e3, e4);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple5(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5)
+{
+ return enif_make_tuple(env, 5, e1, e2, e3, e4, e5);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple6(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6)
+{
+ return enif_make_tuple(env, 6, e1, e2, e3, e4, e5, e6);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple7(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7)
+{
+ return enif_make_tuple(env, 7, e1, e2, e3, e4, e5, e6, e7);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple8(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8)
+{
+ return enif_make_tuple(env, 8, e1, e2, e3, e4, e5, e6, e7, e8);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple9(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8,
+ ERL_NIF_TERM e9)
+{
+ return enif_make_tuple(env, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list1(ErlNifEnv* env,
+ ERL_NIF_TERM e1)
+{
+ return enif_make_list(env, 1, e1);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list2(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2)
+{
+ return enif_make_list(env, 2, e1, e2);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list3(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3)
+{
+ return enif_make_list(env, 3, e1, e2, e3);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list4(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4)
+{
+ return enif_make_list(env, 4, e1, e2, e3, e4);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list5(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5)
+{
+ return enif_make_list(env, 5, e1, e2, e3, e4, e5);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list6(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6)
+{
+ return enif_make_list(env, 6, e1, e2, e3, e4, e5, e6);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list7(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7)
+{
+ return enif_make_list(env, 7, e1, e2, e3, e4, e5, e6, e7);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list8(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8)
+{
+ return enif_make_list(env, 8, e1, e2, e3, e4, e5, e6, e7, e8);
+}
+
+static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list9(ErlNifEnv* env,
+ ERL_NIF_TERM e1,
+ ERL_NIF_TERM e2,
+ ERL_NIF_TERM e3,
+ ERL_NIF_TERM e4,
+ ERL_NIF_TERM e5,
+ ERL_NIF_TERM e6,
+ ERL_NIF_TERM e7,
+ ERL_NIF_TERM e8,
+ ERL_NIF_TERM e9)
+{
+ return enif_make_list(env, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9);
+}
+
+# undef ERL_NIF_INLINE
+
+#else /* fallback with macros */
+
#ifndef enif_make_list1
# define enif_make_list1(ENV,E1) enif_make_list(ENV,1,E1)
# define enif_make_list2(ENV,E1,E2) enif_make_list(ENV,2,E1,E2)
@@ -283,6 +478,11 @@ ERL_NIF_API_FUNC_DECL(int,enif_make_reverse_list,(ErlNifEnv*, ERL_NIF_TERM term,
# define enif_make_tuple7(ENV,E1,E2,E3,E4,E5,E6,E7) enif_make_tuple(ENV,7,E1,E2,E3,E4,E5,E6,E7)
# define enif_make_tuple8(ENV,E1,E2,E3,E4,E5,E6,E7,E8) enif_make_tuple(ENV,8,E1,E2,E3,E4,E5,E6,E7,E8)
# define enif_make_tuple9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_tuple(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9)
+#endif
+
+#endif /* __GNUC__ && !WIN32 */
+
+#ifndef enif_make_pid
# define enif_make_pid(ENV, PID) ((const ERL_NIF_TERM)((PID)->pid))
diff --git a/erts/emulator/beam/erl_nmgc.c b/erts/emulator/beam/erl_nmgc.c
deleted file mode 100644
index d7bfb2ab12..0000000000
--- a/erts/emulator/beam/erl_nmgc.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- * %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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-#include "global.h"
-#include "erl_gc.h"
-#include "erl_binary.h"
-#include "erl_nmgc.h"
-#include "erl_debug.h"
-#if HIPE
-#include "hipe_stack.h"
-#endif
-
-
-#ifdef INCREMENTAL
-/***************************************************************************
- * *
- * Incremental Garbage Collector for the Message Area *
- * *
- ***************************************************************************/
-
-/*
- * The heap pointers are declared in erl_init.c
- * global_heap is the nursery
- * global_old_heap is the old generation
- */
-unsigned char *blackmap = NULL;
-INC_Page *inc_used_mem = NULL;
-INC_MemBlock *inc_free_list = NULL;
-Eterm *inc_fromspc;
-Eterm *inc_fromend;
-Eterm *inc_nursery_scn_ptr;
-Eterm **fwdptrs;
-Eterm *inc_alloc_limit;
-Process *inc_active_proc;
-Process *inc_active_last;
-int inc_words_to_go;
-
-static Eterm *inc_last_nursery;
-static int inc_pages = INC_NoPAGES;
-static INC_Page *inc_bibop = NULL;
-static int inc_used_pages;
-
-/* Used when growing the old generation */
-/*
-#define INC_ROOTSAVE 16384
-static Eterm *root_save[INC_ROOTSAVE];
-static int roots_saved = 0;
-*/
-
-INC_STORAGE_DECLARATION(,gray);
-
-static void inc_minor_gc(Process *p, int need, Eterm* objv, int nobj);
-static void inc_major_gc(Process *p, int need, Eterm* objv, int nobj);
-
-#ifdef INC_TIME_BASED
-#if USE_PERFCTR
-
-/*
- * This uses the Linux perfctr extension to virtualise the
- * time-stamp counter.
- */
-#include "libperfctr.h"
-static struct vperfctr *vperfctr;
-static double cpu_khz;
-static double tsc_to_cpu_mult;
-
-static void inc_start_hrvtime(void)
-{
- struct perfctr_info info;
- struct vperfctr_control control;
-
- if( vperfctr != NULL )
- return;
- vperfctr = vperfctr_open();
- if( vperfctr == NULL )
- return;
- if( vperfctr_info(vperfctr, &info) >= 0 ) {
- cpu_khz = (double)info.cpu_khz;
- tsc_to_cpu_mult = (double)(info.tsc_to_cpu_mult ? : 1);
- if( info.cpu_features & PERFCTR_FEATURE_RDTSC ) {
- memset(&control, 0, sizeof control);
- control.cpu_control.tsc_on = 1;
- if( vperfctr_control(vperfctr, &control) >= 0 )
- return;
- }
- }
- vperfctr_close(vperfctr);
- vperfctr = NULL;
-}
-
-#define inc_get_hrvtime() (((double)vperfctr_read_tsc(vperfctr) * tsc_to_cpu_mult) / cpu_khz)
-
-#endif /* USE_PERFCTR */
-#endif /* INC_TIME_BASED */
-
-#ifdef INC_TIME_BASED
-# define timeslice 1 /* milli seconds */
-# define WORK_MORE (inc_get_hrvtime() < start_time + timeslice)
-#else
-//# define inc_min_work 100 /* words */
-# define inc_min_work global_heap_sz + inc_pages * INC_FULLPAGE /* words */
-# define WORK_MORE (inc_words_to_go > 0)
-#endif
-
-void erts_init_incgc(void)
-{
- int i;
- int size = inc_pages * INC_FULLPAGE;
-
- /* Young generation */
- global_heap = (Eterm *)erts_alloc(ERTS_ALC_T_MESSAGE_AREA,
- sizeof(Eterm) * global_heap_sz);
- global_hend = global_heap + global_heap_sz;
- global_htop = global_heap;
- inc_alloc_limit = global_hend;
-
- /* Fromspace */
- inc_last_nursery = (Eterm *) erts_alloc(ERTS_ALC_T_MESSAGE_AREA,
- global_heap_sz * sizeof(Eterm));
- inc_fromspc = inc_fromend = NULL;
-
- /* Forward-pointers */
- fwdptrs = erts_alloc(ERTS_ALC_T_MESSAGE_AREA,
- global_heap_sz * sizeof(Eterm*));
- /* Old generation */
- global_old_heap = (Eterm *)erts_alloc(ERTS_ALC_T_MESSAGE_AREA,
- size * sizeof(Eterm));
- global_old_hend = global_old_heap + size;
-
- /* Pages i BiBOP */
- for (i = 0; i < inc_pages; i++)
- {
- INC_Page *this = (INC_Page*)(global_old_heap + i * INC_FULLPAGE);
- this->next = (INC_Page*)((Eterm*)this + INC_FULLPAGE);
- }
-
- inc_bibop = (INC_Page*)global_old_heap;
- ((INC_Page*)(global_old_heap + (inc_pages - 1) * INC_FULLPAGE))->next =
- NULL;
-
- inc_used_mem = inc_bibop;
- inc_bibop = inc_bibop->next;
- inc_used_mem->next = NULL;
- inc_used_pages = 1;
-
- /* Free-list */
- inc_free_list = (INC_MemBlock*)inc_used_mem->start;
- inc_free_list->size = INC_PAGESIZE;
- inc_free_list->prev = NULL;
- inc_free_list->next = NULL;
-
- /* Blackmap */
- blackmap = (unsigned char*)erts_alloc(ERTS_ALC_T_MESSAGE_AREA,
- INC_FULLPAGE * inc_pages);
- /* Gray stack */
- INC_STORAGE_INIT(gray);
-
- inc_active_proc = NULL;
- inc_active_last = NULL;
-
-#ifdef INC_TIME_BASED
- inc_start_hrvtime();
-#endif
-}
-
-void erts_cleanup_incgc(void)
-{
- INC_STORAGE_ERASE(gray);
-
- if (inc_fromspc)
- inc_last_nursery = inc_fromspc;
-
- erts_free(ERTS_ALC_T_MESSAGE_AREA,(void*)global_heap);
- erts_free(ERTS_ALC_T_MESSAGE_AREA,(void*)inc_last_nursery);
- erts_free(ERTS_ALC_T_MESSAGE_AREA,(void*)global_old_heap);
- erts_free(ERTS_ALC_T_MESSAGE_AREA,(void*)blackmap);
- erts_free(ERTS_ALC_T_MESSAGE_AREA,(void*)fwdptrs);
-}
-
-void erts_incremental_gc(Process* p, int need, Eterm* objv, int nobj)
-{
- int repeat_minor;
-#ifdef INC_TIME_BASED
- double start_time = inc_get_hrvtime();
- int work_left_before = inc_words_to_go;
-#endif
- /* Used when growing the fromspace */
- static char inc_growing_nurs = 0;
-
- BM_STOP_TIMER(system);
- //BM_MMU_READ();
- BM_RESET_TIMER(gc);
- BM_START_TIMER(gc);
-
- VERBOSE(DEBUG_HYBRID_GC,
- ("INCGC: Incremental GC START Caused by: %T Need: %d\n",
- p->id,need));
-
- ma_gc_flags |= GC_GLOBAL;
- ma_gc_flags &= ~GC_CYCLE_START;
-
-#ifndef INC_TIME_BASED
- /* Decide how much work to do this GC stage. The work is meassured
- * in number of words copied from the young generation to the old
- * plus number of work marked in the old generation.
- */
- if (ma_gc_flags & GC_MAJOR) {
- int wm = (need > inc_min_work) ? need : inc_min_work;
- inc_words_to_go = (int)((wm * (((inc_used_pages * INC_PAGESIZE) /
- (double)global_heap_sz) + 1)) + 0.5);
- }
- else
- inc_words_to_go = (need > inc_min_work) ? need : inc_min_work;
-#endif
-
- do {
- if (ma_gc_flags & GC_MAJOR) {
- /* This is a major collection cycle. */
- inc_major_gc(p,need,objv,nobj);
- } else if (ma_gc_flags & GC_CYCLE) {
- /* This is a minor collection cycle. */
- inc_minor_gc(p,need,objv,nobj);
- } else {
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Collection cycle START\n"));
- ma_gc_flags |= (GC_CYCLE | GC_CYCLE_START);
- inc_fromspc = global_heap;
- inc_fromend = global_htop;
- global_heap = global_htop = inc_last_nursery;
- global_hend = global_heap + global_heap_sz;
- inc_nursery_scn_ptr = global_heap;
-#ifdef INC_TIME_BASED
- work_left_before = inc_words_to_go = global_heap_sz;
-#endif
-#ifdef DEBUG
- inc_last_nursery = NULL;
-#endif
- memset(fwdptrs,0,global_heap_sz * sizeof(Eterm));
-
- {
- /* TODO: Alla processer ska v�l egentligen inte aktiveras h�r... */
- int i;
- for (i = 0; i < erts_num_active_procs; i++) {
- Process *cp = erts_active_procs[i];
- INC_ACTIVATE(cp);
- cp->scan_top = cp->high_water;
- }
- }
-
- if (ma_gc_flags & GC_NEED_MAJOR) {
- /* The previous collection cycle caused the old generation to
- * overflow. This collection cycle will therefore be a major
- * one.
- */
- BM_COUNT(major_gc_cycles);
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: MAJOR cycle\n"));
- inc_major_gc(p,need,objv,nobj);
- } else {
- BM_COUNT(minor_gc_cycles);
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: MINOR cycle\n"));
- inc_minor_gc(p,need,objv,nobj);
- }
- }
-
- repeat_minor = 0;
- if (!(ma_gc_flags & GC_CYCLE)) {
- inc_alloc_limit = global_hend;
- inc_last_nursery = inc_fromspc;
- inc_fromspc = inc_fromend = NULL;
- ASSERT(INC_STORAGE_EMPTY(gray));
-
- if (inc_growing_nurs) {
- /*
- * The previous collection cycle caused the nursery to
- * grow, now we have to grow the from-space as well.
- */
- inc_last_nursery =
- (Eterm*) erts_realloc(ERTS_ALC_T_MESSAGE_AREA,
- (void*)inc_last_nursery,
- sizeof(Eterm) * global_heap_sz);
- inc_growing_nurs = 0;
- }
-
- if (global_hend - global_htop <= need) {
- /*
- * Initiate a new GC cycle immediately and, if necessary,
- * enlarge the nursery.
- */
- if (global_heap_sz <= need) {
- VERBOSE(DEBUG_HYBRID_GC,
- ("INCGC: Allocating a larger nursery\n"));
- global_heap_sz = erts_next_heap_size(need * 1.5,0);
- inc_last_nursery =
- (Eterm*) erts_realloc(ERTS_ALC_T_MESSAGE_AREA,
- (void*)inc_last_nursery,
- sizeof(Eterm) * global_heap_sz);
- fwdptrs = erts_realloc(ERTS_ALC_T_MESSAGE_AREA,fwdptrs,
- global_heap_sz * sizeof(Eterm*));
- inc_growing_nurs = 1;
- }
- repeat_minor = 1;
- }
-
-#ifdef DEBUG
- /* Fill the from-space with bad things */
- memset(inc_last_nursery,DEBUG_BAD_BYTE,
- global_heap_sz * sizeof(Eterm));
-#endif
- }
- } while (repeat_minor);
-
-
- /* Clean up after garbage collection ********************************/
-
- if (inc_alloc_limit != global_hend) {
-
-#ifdef INC_TIME_BASED
- if ((work_left_before - inc_words_to_go) == 0) {
- inc_alloc_limit = global_htop + need;
- } else {
- inc_alloc_limit = (global_hend - global_htop) /
- (inc_words_to_go / (work_left_before - inc_words_to_go)) +
- global_htop;
- if (inc_alloc_limit > global_hend)
- inc_alloc_limit = global_hend;
- }
-#else
- inc_alloc_limit = (Eterm*)(global_htop + (need > inc_min_work) ?
- need : inc_min_work);
- if (inc_alloc_limit > global_hend)
- inc_alloc_limit = global_hend;
-#endif
- }
-
- ma_gc_flags &= ~GC_GLOBAL;
-
- /* INC_TIME_BASED: If this fails we have to increase the timeslice! */
- ASSERT(inc_alloc_limit - global_htop > need);
-
- BM_STOP_TIMER(gc);
-#ifdef BM_TIMERS
- minor_global_gc_time += gc_time;
- if (gc_time > max_global_minor_time)
- max_global_minor_time = gc_time;
-
- pause_times[(((gc_time * 1000) < MAX_PAUSE_TIME) ?
- (int)(gc_time * 1000) :
- MAX_PAUSE_TIME - 1)]++;
-#endif
- //BM_MMU_INIT();
- { static long long verif = 0;
- //erts_printf("innan verify: %d\n",++verif);
- if (verif==168) print_memory(NULL);
- verify_everything();
- //erts_printf("efter verify: %d\n",verif);
- }
- BM_START_TIMER(system);
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Incremental GC END\n"));
-}
-
-
-/***************************************************************************
- * *
- * Minor collection - Copy live data from young generation to old *
- * *
- ***************************************************************************/
-
-#define MINOR_SCAN(PTR,END) do { \
- ASSERT(PTR <= END); \
- while (WORK_MORE && PTR < END) { \
- Eterm val = *PTR; \
- Eterm *obj_ptr = ptr_val(val); \
- switch (primary_tag(val)) { \
- case TAG_PRIMARY_LIST: \
- if (ptr_within(obj_ptr,inc_fromspc,inc_fromend)) { \
- if (INC_IS_FORWARDED(obj_ptr)) { \
- *PTR = make_list(INC_FORWARD_VALUE(obj_ptr)); \
- } \
- else { \
- Eterm *hp = erts_inc_alloc(2); \
- INC_STORE(gray,hp,2); \
- INC_COPY_CONS(obj_ptr,hp,PTR); \
- } \
- } \
- break; \
- case TAG_PRIMARY_BOXED: \
- if (ptr_within(obj_ptr,inc_fromspc,inc_fromend)) { \
- if (INC_IS_FORWARDED(obj_ptr)) { \
- *PTR = make_boxed(INC_FORWARD_VALUE(obj_ptr)); \
- } \
- else { \
- Eterm *hp = erts_inc_alloc(BOXED_NEED(obj_ptr,*obj_ptr)); \
- INC_STORE(gray,hp,BOXED_NEED(obj_ptr,*obj_ptr)); \
- INC_COPY_BOXED(obj_ptr,hp,PTR); \
- } \
- } \
- break; \
- case TAG_PRIMARY_HEADER: \
- switch (val & _TAG_HEADER_MASK) { \
- case ARITYVAL_SUBTAG: break; \
- default: PTR += thing_arityval(val); break; \
- } \
- break; \
- } \
- PTR++; \
- } \
-} while(0)
-
-
-/* Returns: TRUE (1) if the need is greater than the available space
- * and the garbage collector needs to be restarted immediately. FALSE
- * (0) otherwise.
- */
-static void inc_minor_gc(Process* p, int need, Eterm* objv, int nobj)
-{
- BM_COUNT(minor_gc_stages);
-
- /* Start with looking at gray objects found in earlier collection
- * stages.
- */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Rescue gray found from nursery\n"));
- {
- INC_Object *obj = NULL;
- Eterm *ptr;
-
- while (WORK_MORE && !INC_STORAGE_EMPTY(gray)) {
- obj = INC_STORAGE_GET(gray);
- if ((*obj->this & _TAG_HEADER_MASK) == FUN_SUBTAG) {
- ptr = obj->this + thing_arityval(*obj->this) + 1;
- } else {
- ptr = obj->this;
- }
- MINOR_SCAN(ptr,obj->this + obj->size);
- }
- /* TODO: Se f�reg�ende uppdatering av gr� objekt */
- if (!WORK_MORE && obj != NULL)
- INC_STORE(gray,obj->this,obj->size);
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Scan root-set\n"));
- while (WORK_MORE && inc_active_proc) {
- Rootset rootset;
- Process *cp = inc_active_proc;
-
- ASSERT(INC_IS_ACTIVE(cp));
-
- /* TODO: Hur dyrt �r det att bygga nytt rootset varje g�ng? */
-
- /* TODO: Fundera p� ordningen! Rootset, Heap, Old heap... */
-
- /* TODO: Scanna stacken fr�n p->send till p->stop! [Brooks84] */
- /* Notera: Vi GC:ar inte de yngsta objekten - de som allokeras
- under GC-cykeln. Detta ger ynglingarna en chans att d� innan
- GC:n b�rjar kopiera dem. [StefanovicMcKinleyMoss@OOPSLA99] */
-
- /* TODO: N�r rootset �r scannat borde processen inte vara
- aktiv mer. Den b�r aktiveras i schedule, endast om en
- process har k�rt beh�ver vi scanna rootset igen. */
-
- /* MT: In a multithreaded system the process cp needs to be
- * locked here.
- */
-
- if (cp == p)
- rootset.n = setup_rootset(cp, objv, nobj, &rootset);
- else
- rootset.n = setup_rootset(cp, cp->arg_reg, cp->arity, &rootset);
-
- //MA_GENSWEEP_NSTACK(cp, old_htop, n_htop, objv, nobj);
-
- while (WORK_MORE && rootset.n--) {
- Eterm *g_ptr = rootset.v[rootset.n];
- Uint g_sz = rootset.sz[rootset.n];
-
- while (WORK_MORE && g_sz--) {
- Eterm gval = *g_ptr;
- switch (primary_tag(gval)) {
- case TAG_PRIMARY_LIST: {
- Eterm *ptr = list_val(gval);
- if (ptr_within(ptr,inc_fromspc,inc_fromend)) {
- if (INC_IS_FORWARDED(ptr)) {
- *g_ptr++ = make_list(INC_FORWARD_VALUE(ptr));
- }
- else {
- Eterm *hp = erts_inc_alloc(2);
- INC_STORE(gray,hp,2);
- INC_COPY_CONS(ptr,hp,g_ptr++);
- }
- }
- else
- ++g_ptr;
- continue;
- }
-
- case TAG_PRIMARY_BOXED: {
- Eterm *ptr = boxed_val(gval);
- if (ptr_within(ptr,inc_fromspc,inc_fromend)) {
- if (INC_IS_FORWARDED(ptr)) {
- *g_ptr++ = make_boxed(INC_FORWARD_VALUE(ptr));
- }
- else {
- Eterm *hp = erts_inc_alloc(BOXED_NEED(ptr,*ptr));
- INC_STORE(gray,hp,BOXED_NEED(ptr,*ptr));
- INC_COPY_BOXED(ptr,hp,g_ptr++);
- }
- }
- else
- ++g_ptr;
- continue;
- }
-
- default:
- g_ptr++;
- continue;
- }
- }
- }
-
- restore_one_rootset(cp, &rootset);
-
- /* MT: cp can be unlocked now. */
-
- /* VERBOSE(DEBUG_HYBRID_GC,("INCGC: Scan private nursery\n")); */
- if (cp->scan_top != HEAP_TOP(cp)) {
- Eterm *ptr = cp->scan_top;
- MINOR_SCAN(ptr,HEAP_TOP(cp));
- /* TODO: F�r att spara scan_top h�r m�ste alla ma-pekare
- * som hittas l�ggas till i cp->rrma.
- */
- //cp->scan_top = ptr;
- }
-
- /* VERBOSE(DEBUG_HYBRID_GC,("INCGC: Scan heap fragments\n")); */
- {
- ErlHeapFragment* bp = MBUF(cp);
-
- while (WORK_MORE && bp) {
- Eterm *ptr = bp->mem;
- if ((ARITH_HEAP(cp) >= bp->mem) &&
- (ARITH_HEAP(cp) < bp->mem + bp->size)) {
- MINOR_SCAN(ptr,ARITH_HEAP(cp));
- } else {
- MINOR_SCAN(ptr,bp->mem + bp->size);
- }
- bp = bp->next;
- }
- }
-
- /* VERBOSE(DEBUG_HYBRID_GC,("INCGC: Scan gray\n")); */
- {
- INC_Object *obj = NULL;
- Eterm *ptr;
- while (WORK_MORE && !INC_STORAGE_EMPTY(gray)) {
- obj = INC_STORAGE_GET(gray);
- if ((*obj->this & _TAG_HEADER_MASK) == FUN_SUBTAG) {
- ptr = obj->this + thing_arityval(*obj->this) + 1;
- } else {
- ptr = obj->this;
- }
- MINOR_SCAN(ptr,obj->this + obj->size);
- }
- /* TODO: INC_STORE(gray,ptr,obj->size-(ptr-obj->this)); Typ.. */
- if (!WORK_MORE && obj != NULL)
- INC_STORE(gray,obj->this,obj->size);
- }
-
- if (WORK_MORE) {
- //printf("Rootset after:\r\n");
- //print_one_rootset(&rootset);
- INC_DEACTIVATE(cp);
- }
- }
-
- /* Update new pointers in the nursery to new copies in old generation. */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Update nursery\n"));
- {
- Eterm *ptr = inc_nursery_scn_ptr;
- MINOR_SCAN(ptr,global_htop);
- inc_nursery_scn_ptr = ptr;
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Rescue gray found from nursery\n"));
- {
- INC_Object *obj = NULL;
- Eterm *ptr;
-
- while (WORK_MORE && !INC_STORAGE_EMPTY(gray)) {
- obj = INC_STORAGE_GET(gray);
- if ((*obj->this & _TAG_HEADER_MASK) == FUN_SUBTAG) {
- ptr = obj->this + thing_arityval(*obj->this) + 1;
- } else {
- ptr = obj->this;
- }
- MINOR_SCAN(ptr,obj->this + obj->size);
- }
- /* TODO: Se f�reg�ende uppdatering av gr� objekt */
- if (!WORK_MORE && obj != NULL)
- INC_STORE(gray,obj->this,obj->size);
- }
-
- /* Atomic phase */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Update copy stack\n"));
- {
- Uint i;
- for (i = 0; i < ma_dst_top; i++) {
- if (ptr_within(ma_dst_stack[i],inc_fromspc,inc_fromend)) {
- if (INC_IS_FORWARDED(ma_dst_stack[i]))
- ma_dst_stack[i] = INC_FORWARD_VALUE(ma_dst_stack[i]);
- }
- }
- }
-
- if (WORK_MORE) {
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Update offheap-lists\n"));
- {
- ExternalThing **prev = &erts_global_offheap.externals;
- ExternalThing *ptr = erts_global_offheap.externals;
-
- /* Atomic phase */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Sweep proc externals\n"));
- while (ptr) {
- Eterm *ppt = (Eterm*) ptr;
-
- if (ptr_within(ppt,global_old_heap,global_old_hend)) {
- prev = &ptr->next;
- ptr = ptr->next;
- } else if (ptr_within(ppt, inc_fromspc, inc_fromend) &&
- INC_IS_FORWARDED(ppt)) {
- ExternalThing *ro = (ExternalThing*)INC_FORWARD_VALUE(ppt);
- *prev = ro; /* Patch to moved pos */
- prev = &ro->next;
- ptr = ro->next;
- } else {
- erts_deref_node_entry(ptr->node);
- *prev = ptr = ptr->next;
- }
- }
- ASSERT(*prev == NULL);
- }
-
- {
- ProcBin **prev = &erts_global_offheap.mso;
- ProcBin *ptr = erts_global_offheap.mso;
-
- /* Atomic phase */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Sweep proc bins\n"));
- while (ptr) {
- Eterm *ppt = (Eterm*)ptr;
-
- if (ptr_within(ppt,global_old_heap,global_old_hend)) {
- prev = &ptr->next;
- ptr = ptr->next;
- } else if (ptr_within(ppt, inc_fromspc, inc_fromend) &&
- INC_IS_FORWARDED(ppt)) {
- ProcBin *ro = (ProcBin*)INC_FORWARD_VALUE(ppt);
- *prev = ro; /* Patch to moved pos */
- prev = &ro->next;
- ptr = ro->next;
- } else {
- Binary *bptr;
- *prev = ptr->next;
- bptr = ptr->val;
- if (erts_refc_dectest(&bptr->refc, 0) == 0)
- erts_bin_free(bptr);
- ptr = *prev;
- }
- }
- ASSERT(*prev == NULL);
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Minor collection cycle END\n"));
- ma_gc_flags &= ~GC_CYCLE;
- }
-}
-
-
-
-
-/***************************************************************************
- * *
- * Major collection - CopyMark - Copy young to old, Mark-Sweep old *
- * *
- ***************************************************************************/
-
-#define COPYMARK(PTR,END) do { \
- ASSERT(PTR <= END); \
- while (WORK_MORE && PTR < END) { \
- Eterm val = *PTR; \
- Eterm *obj_ptr = ptr_val(val); \
- switch (primary_tag(val)) { \
- case TAG_PRIMARY_LIST: \
- COPYMARK_CONS(obj_ptr,aging_htop,PTR,aging_end); break; \
- case TAG_PRIMARY_BOXED: \
- COPYMARK_BOXED(obj_ptr,aging_htop,PTR,aging_end); break; \
- case TAG_PRIMARY_HEADER: \
- switch (val & _TAG_HEADER_MASK) { \
- case ARITYVAL_SUBTAG: break; \
- default: \
- PTR += thing_arityval(val); \
- break; \
- } \
- break; \
- default: break; \
- } \
- PTR++; \
- } \
-} while(0);
-/* TODO:
- if (aging_htop + 10 > aging + INC_FULLPAGE) {
- aging->next = inc_used_mem;
- inc_used_mem = aging;
- }
-*/
-
-static void inc_major_gc(Process *p, int need, Eterm* objv, int nobj)
-{
- Eterm *free_start = NULL;
- Uint live = 0;
- Uint old_gen_sz = 0;
- static INC_Page *aging;
- static Eterm *aging_htop;
- static Eterm *aging_end;
- BM_NEW_TIMER(old_gc);
-
- BM_SWAP_TIMER(gc,old_gc);
- BM_COUNT(major_gc_stages);
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Major collection START\n"));
-
- ma_gc_flags |= GC_INCLUDE_ALL;
-
- if (ma_gc_flags & GC_NEED_MAJOR)
- {
- INC_Page *page = inc_used_mem;
-
- ma_gc_flags |= GC_MAJOR;
- ma_gc_flags &= ~GC_NEED_MAJOR;
-
- while (page)
- {
- memset(blackmap +
- ((void*)page - (void*)global_old_heap) / sizeof(void*),
- 0, INC_FULLPAGE);
- page = page->next;
- }
-
- if (inc_bibop) {
- aging = inc_bibop;
- inc_bibop = inc_bibop->next;
- aging->next = NULL;
- memset(blackmap +
- ((void*)aging - (void*)global_old_heap) / sizeof(void*),
- 1, INC_FULLPAGE);
- aging_htop = aging->start;
- aging_end = aging->start + INC_PAGESIZE;
- }
- else {
- /* There are no free pages.. Either fragmentation is a
- * problem or we are simply out of memory. Allocation in
- * the old generation will be done through the free-list
- * this GC cycle.
- */
- aging = NULL;
- aging_htop = aging_end = NULL;
- }
- }
-
- /* Start with looking at gray objects found in earlier collection
- * stages.
- */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark gray\n"));
- {
- INC_Object *obj = NULL;
-
- while (WORK_MORE && !INC_STORAGE_EMPTY(gray)) {
- Eterm *ptr;
-
- obj = INC_STORAGE_GET(gray);
- if ((*obj->this & _TAG_HEADER_MASK) == FUN_SUBTAG) {
- ptr = obj->this + thing_arityval(*obj->this) + 1;
- } else {
- ptr = obj->this;
- }
- COPYMARK(ptr,obj->this + obj->size);
- }
- /* TODO: Titta p� motsvarande i minor. */
- if (!WORK_MORE && obj != NULL)
- INC_STORE(gray,obj->this,obj->size);
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark roots\n"));
- while (WORK_MORE && inc_active_proc)
- {
- /* For each process: Scan all areas containing pointers to the
- * message area. When a process is done here, all it's
- * message-pointers should be to the old generation.
- */
- Rootset rootset;
- Process *cp = inc_active_proc;
-
- ASSERT(INC_IS_ACTIVE(cp));
-
- /* MT: In a multithreaded system the process cp needs to be
- * locked here.
- */
- if (cp == p)
- rootset.n = setup_rootset(cp, objv, nobj, &rootset);
- else
- rootset.n = setup_rootset(cp, cp->arg_reg, cp->arity, &rootset);
-
- while (WORK_MORE && rootset.n--)
- {
- Eterm *ptr = rootset.v[rootset.n];
- Eterm *end = ptr + rootset.sz[rootset.n];
-
- while (WORK_MORE && ptr < end) {
- Eterm val = *ptr;
- Eterm *obj_ptr = ptr_val(val);
-
- switch (primary_tag(val)) {
- case TAG_PRIMARY_LIST:
- {
- COPYMARK_CONS(obj_ptr,aging_htop,ptr,aging_end);
- break;
- }
-
- case TAG_PRIMARY_BOXED:
- {
- COPYMARK_BOXED(obj_ptr,aging_htop,ptr,aging_end);
- break;
- }
- }
- ptr++;
- }
- }
-
-#ifdef HIPE
- /* Atomic phase */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Native stack scan: %T\n",cp->id));
- aging_htop = ma_fullsweep_nstack(cp,aging_htop,aging_end);
-#endif
- restore_one_rootset(cp, &rootset);
-
- /* MT: cp can be unlocked now. But beware!! The message queue
- * might be updated with new pointers to the fromspace while
- * we work below. The send operation can not assume that all
- * active processes will look through their message queue
- * before deactivating as is the case in non-MT incremental
- * collection.
- */
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark process heap\n"));
- {
- Eterm *ptr = cp->scan_top;
- COPYMARK(ptr,cp->htop);
- //cp->scan_top = ptr;
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark heap fragments\n"));
- {
- ErlHeapFragment* bp = MBUF(cp);
-
- while (WORK_MORE && bp) {
- Eterm *ptr = bp->mem;
- Eterm *end;
-
- if ((ARITH_HEAP(cp) >= bp->mem) &&
- (ARITH_HEAP(cp) < bp->mem + bp->size)) {
- end = ARITH_HEAP(cp);
- } else {
- end = bp->mem + bp->size;
- }
-
- COPYMARK(ptr,end);
- bp = bp->next;
- }
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark gray stack\n"));
- {
- INC_Object *obj = NULL;
-
- while (WORK_MORE && !INC_STORAGE_EMPTY(gray)) {
- Eterm *ptr;
-
- obj = INC_STORAGE_GET(gray);
- if ((*obj->this & _TAG_HEADER_MASK) == FUN_SUBTAG) {
- ptr = obj->this + thing_arityval(*obj->this) + 1;
- } else {
- ptr = obj->this;
- }
- COPYMARK(ptr,obj->this + obj->size);
- }
- /* TODO: Titta p� motsvarande i minor. */
- if (!WORK_MORE && obj != NULL)
- INC_STORE(gray,obj->this,obj->size);
- }
-
- if (WORK_MORE) {
- INC_DEACTIVATE(cp);
- }
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark nursery\n"));
- {
- Eterm *ptr = inc_nursery_scn_ptr;
- COPYMARK(ptr,global_htop);
- inc_nursery_scn_ptr = ptr;
- }
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Copy-Mark gray found in nursery\n"));
- {
- INC_Object *obj = NULL;
-
- while (WORK_MORE && !INC_STORAGE_EMPTY(gray)) {
- Eterm *ptr;
-
- obj = INC_STORAGE_GET(gray);
- if ((*obj->this & _TAG_HEADER_MASK) == FUN_SUBTAG) {
- ptr = obj->this + thing_arityval(*obj->this) + 1;
- } else {
- ptr = obj->this;
- }
- COPYMARK(ptr,obj->this + obj->size);
- }
- /* TODO: Titta p� motsvarande i minor. */
- if (!WORK_MORE && obj != NULL)
- INC_STORE(gray,obj->this,obj->size);
- }
-
-
- /**********************************************************************/
- if (WORK_MORE) {
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Sweep phase\n"));
-
- /* Atomic phase */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Sweep externals in old generation\n"));
- {
- ExternalThing** prev = &erts_global_offheap.externals;
- ExternalThing* ptr = erts_global_offheap.externals;
-
- while (ptr) {
- Eterm* ppt = (Eterm *) ptr;
-
- if ((ptr_within(ppt, global_old_heap, global_old_hend) &&
- blackmap[ppt - global_old_heap] == 0) ||
- (ptr_within(ppt, inc_fromspc, inc_fromend) &&
- !INC_IS_FORWARDED(ppt)))
- {
- erts_deref_node_entry(ptr->node);
- *prev = ptr = ptr->next;
- } else if (ptr_within(ppt, inc_fromspc, inc_fromend)) {
- ExternalThing* ro = (ExternalThing*)INC_FORWARD_VALUE(ppt);
- *prev = ro; /* Patch to moved pos */
- prev = &ro->next;
- ptr = ro->next;
- } else {
- prev = &ptr->next;
- ptr = ptr->next;
- }
- }
- ASSERT(*prev == NULL);
- }
-
- /* Atomic phase */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Sweep refc bins in old generation\n"));
- {
- ProcBin** prev = &erts_global_offheap.mso;
- ProcBin* ptr = erts_global_offheap.mso;
-
- while (ptr) {
- Eterm *ppt = (Eterm*)ptr;
-
- if ((ptr_within(ppt, global_old_heap, global_old_hend) &&
- blackmap[ppt - global_old_heap] == 0) ||
- (ptr_within(ppt, inc_fromspc, inc_fromend) &&
- !INC_IS_FORWARDED(ppt)))
- {
- Binary* bptr;
- *prev = ptr->next;
- bptr = ptr->val;
- if (erts_refc_dectest(&bptr->refc, 0) == 0)
- erts_bin_free(bptr);
- ptr = *prev;
- } else if (ptr_within(ppt, inc_fromspc, inc_fromend)) {
- ProcBin* ro = (ProcBin*)INC_FORWARD_VALUE(ppt);
- *prev = ro; /* Patch to moved pos */
- prev = &ro->next;
- ptr = ro->next;
- } else {
- prev = &ptr->next;
- ptr = ptr->next;
- }
- }
- ASSERT(*prev == NULL);
- }
-
- /* TODO: Currently atomic phase - Can not be later of course. */
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Sweep old generation\n"));
- {
- INC_Page *page = inc_used_mem;
- INC_Page *prev = NULL;
- inc_free_list = NULL;
-
- while (page) {
- int scavenging = 0;
- int n = page->start - global_old_heap;
- int stop = n + INC_PAGESIZE;
-
- old_gen_sz += INC_PAGESIZE;
- while (n < stop) {
- if (blackmap[n] != 0) {
- if (scavenging) {
- Eterm *ptr = global_old_heap + n;
- scavenging = 0;
- if ((ptr - free_start) * sizeof(Eterm) >=
- sizeof(INC_MemBlock))
- {
- INC_MemBlock *new = (INC_MemBlock*)free_start;
- new->size = ptr - free_start;
- new->prev = NULL;
- new->next = inc_free_list;
- if (inc_free_list)
- inc_free_list->prev = new;
- inc_free_list = new;
- }
- }
- if (blackmap[n] == 255) {
- unsigned int size =
- *(unsigned int*)(((long)&blackmap[n]+4) & ~3);
- live += size;
- n += size;
- }
- else {
- live += blackmap[n];
- n += blackmap[n];
- }
- }
- else if (!scavenging) {
- free_start = global_old_heap + n;
- scavenging = 1;
- n++;
- }
- else {
- n++;
- }
- }
-
- if (scavenging) {
- if ((global_old_heap + n - free_start) * sizeof(Eterm) >
- sizeof(INC_MemBlock))
- {
- INC_MemBlock *new = (INC_MemBlock*)free_start;
- new->size = global_old_heap + n - free_start;
- new->prev = NULL;
- new->next = inc_free_list;
- if (inc_free_list)
- inc_free_list->prev = new;
- inc_free_list = new;
- }
- else if (free_start == page->start) {
- INC_Page *next = page->next;
-
- if (prev)
- prev->next = page->next;
- else
- inc_used_mem = page->next;
-
- page->next = inc_bibop;
- inc_bibop = page;
- inc_used_pages--;
- page = next;
- continue;
- }
- }
- prev = page;
- page = page->next;
- }
- }
- }
-
- ASSERT(inc_bibop);
- /*
- This code is not expected to work right now.
- if (!inc_bibop) {
- int i;
- int new_pages = inc_pages * 2;
- int size = sizeof(Eterm) * new_pages * INC_FULLPAGE;
- Eterm *new_heap = erts_alloc(ERTS_ALC_T_MESSAGE_AREA,size);
- Eterm *new_hend = new_heap + size;
- Eterm *new_htop;
- Eterm *last_page_end;
- INC_Page *new_used_mem;
- INC_Page *page;
-
- erts_printf("The last page has been allocated..\n");
- erts_printf("We need to copy things!\n");
-
- / * Create new, bigger bag of pages * /
- for (i = 0; i < new_pages; i++)
- {
- INC_Page *this =
- (INC_Page*)(new_heap + i * INC_FULLPAGE);
- this->next = (INC_Page*)((Eterm*)this + INC_FULLPAGE);
- }
- inc_bibop = (INC_Page*)new_heap;
- ((INC_Page*)(new_heap + (new_pages - 1) *
- INC_FULLPAGE))->next = NULL;
-
- new_used_mem = inc_bibop;
- inc_bibop = inc_bibop->next;
- new_used_mem->next = NULL;
-
- / * Move stuff from old bag to new * /
- inc_free_list = NULL;
- new_htop = new_used_mem->start;
- last_page_end = new_htop + INC_PAGESIZE;
- page = inc_used_mem;
- while (page)
- {
- Eterm *ptr = page->start;
- Eterm *page_end = ptr + INC_PAGESIZE;
- int n = offsetof(INC_Page,start) / sizeof(void*) +
- ((Eterm*)page - global_old_heap);
- while (ptr < page_end)
- {
- if (blackmap[n] > 0)
- {
- if (last_page_end - new_htop < blackmap[n])
- {
- INC_Page *new_page = inc_bibop;
- inc_bibop = inc_bibop->next;
- new_page->next = new_used_mem;
- new_used_mem = new_page;
- new_htop = new_page->start;
- last_page_end = new_htop + INC_PAGESIZE;
- }
-
- memcpy(new_htop,ptr,blackmap[n] * sizeof(Eterm));
- for (i = 0; i < blackmap[n]; i++)
- {
- *ptr++ = (Eterm)new_htop++;
- }
- //new_htop += blackmap[n];
- //ptr += blackmap[n];
- / *
- if (blackmap[n] == 255) Do the right thing...
- * /
- n += blackmap[n];
- }
- else
- {
- n++; ptr++;
- }
- }
- page = page->next;
- }
-
- page = inc_used_mem;
- while (page)
- {
- Eterm *ptr = page->start;
- Eterm *page_end = ptr + INC_PAGESIZE;
-
- / * TODO: If inc_used_mem is sorted in address order, this
- * pass can be done at the same time as copying. * /
- while (ptr < page_end)
- {
- if (ptr_within(ptr_val(*ptr),global_old_heap,global_old_hend))
- {
- *ptr = *((Eterm*)ptr_val(*ptr));
- }
- ptr++;
- }
- page = page->next;
- }
-
- printf("Restore rootset after heap move. Roots: %d\r\n",roots_saved);
- while (roots_saved--)
- {
- Eterm *ptr = root_save[roots_saved];
- *ptr = *((Eterm*)ptr_val(*ptr));
- }
-
- erts_free(ERTS_ALC_T_MESSAGE_AREA,(void*)global_old_heap);
-
- global_old_heap = new_heap;
- global_old_hend = new_hend;
- inc_used_mem = new_used_mem;
- inc_pages = new_pages;
-
- if ((last_page_end - new_htop) * sizeof(Eterm) >=
- sizeof(INC_MemBlock))
- {
- inc_free_list = (INC_MemBlock*)(new_htop);
- inc_free_list->size = last_page_end - new_htop;
- inc_free_list->prev = NULL;
- inc_free_list->next = NULL;
- }
- }
- */
-
- /* I vilka l�gen kan vi vilja sl�nga p� en extra sida.. ( < 25% kvar?)
- if ()
- {
- INC_Page *new_page = inc_bibop;
- INC_MemBlock *new_free =
- (INC_MemBlock*)new_page->start;
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Fetching new page\n"));
- inc_bibop = inc_bibop->next;
-
- new_page->next = inc_used_mem;
- if (inc_used_mem)
- inc_used_mem->prev = new_page;
- inc_used_mem = new_page;
-
- // kolla detta med normal sidstorlek! old_gen_sz += INC_PAGESIZE;
- //BM_SWAP_TIMER(gc,misc1);
- memset(blackmap +
- ((void*)new_page - (void*)global_old_heap) / sizeof(void*),
- 0, INC_FULLPAGE);
- //BM_SWAP_TIMER(misc1,gc);
-
- new_free->prev = NULL;
- new_free->next = inc_free_list;
- new_free->size = INC_PAGESIZE;
- if (inc_free_list)
- inc_free_list->prev = new_free;
- inc_free_list = new_free;
- //printf("Snatched a new page @ 0x%08x\r\n",(int)new_page);
- //print_free_list();
- found = new_free;
- }
- */
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Update copy stack\n"));
- {
- Uint i;
- for (i = 0; i < ma_dst_top; i++) {
- if (ptr_within(ma_dst_stack[i],inc_fromspc,inc_fromend)) {
- if (INC_IS_FORWARDED(ma_dst_stack[i]))
- ma_dst_stack[i] = INC_FORWARD_VALUE(ma_dst_stack[i]);
- }
- }
- }
-
- if (WORK_MORE)
- {
- int size_left = INC_PAGESIZE - (aging_htop - aging->start);
-
- if (size_left > sizeof(INC_MemBlock))
- {
- ((INC_MemBlock*)aging_htop)->size = size_left;
- ((INC_MemBlock*)aging_htop)->prev = NULL;
- ((INC_MemBlock*)aging_htop)->next = inc_free_list;
- if (inc_free_list)
- inc_free_list->prev = (INC_MemBlock*)aging_htop;
- inc_free_list = (INC_MemBlock*)aging_htop;
- }
- aging->next = inc_used_mem;
- inc_used_mem = aging;
- inc_used_pages++;
-
- ma_gc_flags &= ~GC_MAJOR;
- ma_gc_flags &= ~GC_CYCLE;
-
- VERBOSE(DEBUG_HYBRID_GC,("INCGC: Major collection cycle END\n"));
- }
-
- ma_gc_flags &= ~GC_INCLUDE_ALL;
-
- BM_STOP_TIMER(old_gc);
-#ifdef BM_TIMER
- major_global_gc_time += old_gc_time;
- if (old_gc_time > max_global_major_time)
- max_global_major_time = old_gc_time;
-
- if ((old_gc_time * 1000) < MAX_PAUSE_TIME)
- pause_times_old[(int)(old_gc_time * 1000)]++;
- else
- pause_times_old[MAX_PAUSE_TIME - 1]++;
-#endif
- BM_START_TIMER(gc);
-}
-
-
-
-/***************************************************************************
- * *
- * Allocation in the old generation. Used in minor colection and when *
- * copying the rest of a message after a GC. *
- * *
- ***************************************************************************/
-
-
-Eterm *erts_inc_alloc(int need)
-{
- INC_MemBlock *this = inc_free_list;
-
- ASSERT(need < INC_PAGESIZE);
- while (this && (this->size) < need)
- {
- this = this->next;
- }
-
- if (!this)
- {
- /* If a free block large enough is not found, a new page is
- * allocated. GC_NEED_MAJOR is set so that the next garbage
- * collection cycle will be a major one, that is, both
- * generations will be garbage collected.
- */
- INC_Page *new_page = inc_bibop;
- INC_MemBlock *new_free = (INC_MemBlock*)new_page->start;
-
- if (new_page)
- {
- VERBOSE(DEBUG_HYBRID_GC,
- ("INCGC: Allocation grabs a new page\n"));
- inc_bibop = inc_bibop->next;
- new_page->next = inc_used_mem;
- inc_used_mem = new_page;
- inc_used_pages++;
-
- new_free->prev = NULL;
- new_free->next = inc_free_list;
- new_free->size = INC_PAGESIZE;
- if (inc_free_list)
- inc_free_list->prev = new_free;
- inc_free_list = new_free;
-
- this = new_free;
- if (!(ma_gc_flags & GC_MAJOR))
- ma_gc_flags |= GC_NEED_MAJOR;
- }
- else
- {
- erl_exit(-1, "inc_alloc ran out of pages!\n");
- }
- }
-
- if (((this->size) - need) * sizeof(Eterm) >= sizeof(INC_MemBlock))
- {
- INC_MemBlock *rest = (INC_MemBlock*)((Eterm*)this + need);
-
- /* The order here IS important! */
- rest->next = this->next;
-
- if (rest->next)
- rest->next->prev = rest;
-
- rest->prev = this->prev;
-
- if (rest->prev)
- rest->prev->next = rest;
- else
- inc_free_list = rest;
-
- rest->size = this->size - need;
- }
- else
- {
- if (this->prev)
- this->prev->next = this->next;
- else
- inc_free_list = this->next;
-
- if (this->next)
- this->next->prev = this->prev;
- }
-
- if (ma_gc_flags & GC_MAJOR) {
- if (need > 254) {
- blackmap[(Eterm*)this - global_old_heap] = 255;
- *(int*)((long)(&blackmap[(Eterm*)this - global_old_heap]+4) & ~3) =
- need;
- } else
- blackmap[(Eterm*)this - global_old_heap] = need;
- }
- return (Eterm*)this;
-}
-#endif /* INCREMENTAL */
diff --git a/erts/emulator/beam/erl_nmgc.h b/erts/emulator/beam/erl_nmgc.h
deleted file mode 100644
index b207dd37fa..0000000000
--- a/erts/emulator/beam/erl_nmgc.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifndef __ERL_NMGC_H__
-#define __ERL_NMGC_H__
-
-#ifdef INCREMENTAL
-#include <stddef.h> /* offsetof() */
-#include "erl_process.h"
-
-#define INC_FULLPAGE (INC_PAGESIZE + offsetof(INC_Page,start) / sizeof(void*))
-
-#define BOXED_NEED(PTR,HDR) \
- (((HDR) & _HEADER_SUBTAG_MASK) == SUB_BINARY_SUBTAG ? \
- header_arity(HDR) + 2 : \
- ((HDR) & _HEADER_SUBTAG_MASK) == FUN_SUBTAG ? \
- header_arity(HDR) + ((ErlFunThing*)(PTR))->num_free + 2 : \
- header_arity(HDR) + 1)
-
-
-#define INC_DECREASE_WORK(n) inc_words_to_go -= (n);
-
-#define INC_COPY_CONS(FROM,TO,PTR) \
-do { \
- TO[0] = FROM[0]; \
- TO[1] = FROM[1]; \
- INC_MARK_FORWARD(FROM,TO); \
- *(PTR) = make_list(TO); \
- INC_DECREASE_WORK(2); \
- (TO) += 2; \
-} while(0)
-
-#define INC_COPY_BOXED(FROM,TO,PTR) \
-do { \
- Sint nelts; \
- Eterm hdr = *(FROM); \
- \
- ASSERT(is_header(hdr)); \
- INC_MARK_FORWARD(FROM,TO); \
- *(PTR) = make_boxed(TO); \
- *(TO)++ = *(FROM)++; \
- nelts = header_arity(hdr); \
- switch ((hdr) & _HEADER_SUBTAG_MASK) { \
- case SUB_BINARY_SUBTAG: nelts++; break; \
- case FUN_SUBTAG: nelts+=((ErlFunThing*)(FROM-1))->num_free+1; break;\
- } \
- INC_DECREASE_WORK(nelts + 1); \
- while (nelts--) \
- *(TO)++ = *(FROM)++; \
-} while(0)
-
-
-/* Things copied to the old generation are not marked in the blackmap.
- * This is ok since the page they are copied to (aging) is not part of
- * the sweep.
- */
-#define COPYMARK_CONS(FROM,TO,PTR,LIMIT) \
-do { \
- if (ptr_within(FROM,inc_fromspc,inc_fromend)) { \
- if (INC_IS_FORWARDED(FROM)) { \
- *PTR = make_list(INC_FORWARD_VALUE(FROM)); \
- } else if (TO + 2 <= LIMIT) { \
- INC_STORE(gray,TO,2); \
- INC_COPY_CONS(FROM,TO,PTR); \
- } else { \
- Eterm *hp = erts_inc_alloc(2); \
- INC_STORE(gray,hp,2); \
- INC_COPY_CONS(FROM,hp,PTR); \
- } \
- } else if (ptr_within(FROM,global_old_heap,global_old_hend) && \
- (blackmap[FROM - global_old_heap] == 0)) { \
- blackmap[FROM - global_old_heap] = 2; \
- INC_DECREASE_WORK(2); \
- INC_STORE(gray,FROM,2); \
- } \
-} while(0)
-
-#define COPYMARK_BOXED(FROM,TO,PTR,LIMIT) \
-do { \
- if (ptr_within(FROM,inc_fromspc,inc_fromend)) { \
- int size = BOXED_NEED(FROM,*FROM); \
- if (INC_IS_FORWARDED(FROM)) { \
- *PTR = make_boxed(INC_FORWARD_VALUE(FROM)); \
- } else if (TO + size <= LIMIT) { \
- INC_STORE(gray,TO,size); \
- INC_COPY_BOXED(FROM,TO,PTR); \
- } else { \
- Eterm *hp = erts_inc_alloc(size); \
- INC_STORE(gray,hp,size); \
- INC_COPY_BOXED(FROM,hp,PTR); \
- } \
- } else if (ptr_within(FROM,global_old_heap,global_old_hend) && \
- (blackmap[FROM - global_old_heap] == 0)) { \
- int size = BOXED_NEED(FROM,*FROM); \
- if (size > 254) { \
- blackmap[FROM - global_old_heap] = 255; \
- *(int*)((long)(&blackmap[FROM - \
- global_old_heap] + 4) & ~3) = size; \
- } else \
- blackmap[FROM - global_old_heap] = size; \
- INC_DECREASE_WORK(size); \
- INC_STORE(gray,FROM,size); \
- } \
-} while(0)
-
-#define INC_MARK_FORWARD(ptr,dst) fwdptrs[(ptr) - inc_fromspc] = (dst);
-#define INC_IS_FORWARDED(ptr) (fwdptrs[(ptr) - inc_fromspc] != 0)
-#define INC_FORWARD_VALUE(ptr) fwdptrs[(ptr) - inc_fromspc]
-
-/* Note for BM_TIMER: Active timer should always be 'system' when IncAlloc
- * is called!
- */
-#define IncAlloc(p, sz, objv, nobj) \
- (ASSERT_EXPR((sz) >= 0), \
- (((inc_alloc_limit - global_htop) <= (sz)) ? \
- erts_incremental_gc((p),(sz),(objv),(nobj)) : 0), \
- ASSERT_EXPR(global_hend - global_htop > (sz)), \
- global_htop += (sz), global_htop - (sz))
-
-
-/************************************************************************
- * INC_STORAGE, a dynamic circular storage for objects (INC_Object). *
- * Use INC_STORE to add objects to the storage. The storage can then *
- * be used either as a queue, using INC_STORAGE_GET to retreive *
- * values, or as a stack, using INC_STORAGE_POP. It is OK to mix calls *
- * to GET and POP if that is desired. *
- * An iterator can be declared to traverse the storage without removing *
- * any elements, and INC_STORAGE_STEP will then return each element in *
- * turn, oldest first. *
- ***********************************************************************/
-
-/* Declare a new storage; must be in the beginning of a block. Give
- * the storage a name that is used in all later calls to the storage.
- * If this is an external declaration of the storage, pass the keyword
- * external as the first argument, otherwise leave it empty.
- */
-#define INC_STORAGE_DECLARATION(ext,name) \
- ext INC_Storage *name##head; \
- ext INC_Storage *name##tail; \
- ext INC_Object *name##free; \
- ext INC_Object *name##last_free; \
- ext int name##size;
-
-
-/* Initialize the storage. Note that memory allocation is involved -
- * don't forget to erase the storage when you are done.
- */
-#define INC_STORAGE_INIT(name) do { \
- name##head = (INC_Storage*)erts_alloc(ERTS_ALC_T_OBJECT_STACK, \
- sizeof(INC_Storage)); \
- name##head->next = name##head; \
- name##head->prev = name##head; \
- name##tail = name##head; \
- name##free = name##head->data; \
- name##last_free = name##free + INC_STORAGE_SIZE - 1; \
- name##size = 0; \
-} while(0)
-
-
-/*
-#define INC_STORAGE_SWAP(s1,s2) do { \
- INC_Storage *tmphead = s1##head; \
- INC_Storage *tmptail = s1##tail; \
- INC_Object *tmpfree = s1##free; \
- INC_Object *tmplast = s1##last_free; \
- int tmpsize = s1##size; \
- s1##head = s2##head; \
- s1##tail = s2##tail; \
- s1##free = s2##free; \
- s1##last_free = s2##last_free; \
- s1##size = s2##size; \
- s2##head = tmphead; \
- s2##tail = tmptail; \
- s2##free = tmpfree; \
- s2##last_free = tmplast; \
- s2##size = tmpsize; \
-} while(0)
-*/
-
-
-/* Return and remove the youngest element - treat the storage as a
- * stack. Always check that there are elements in the queue before
- * using INC_STORAGE_POP!
- */
-#define INC_STORAGE_POP(name) (ASSERT_EXPR(name##size != 0), \
- name##size--, \
- (--name##free != name##head->data - 1) ? \
- name##free : (name##head = name##head->prev, \
- name##free = name##head->data + INC_STORAGE_SIZE - 1))
-
-
-/* Return and remove the oldest element - treat the storage as a
- * queue. Always check that there are elements in the queue before
- * using INC_STORAGE_GET!
- */
-#define INC_STORAGE_GET(name) (ASSERT_EXPR(name##size != 0), \
- name##size--, \
- (++name##last_free != name##tail->data + INC_STORAGE_SIZE) ? \
- name##last_free : (name##tail = name##tail->next, \
- name##last_free = name##tail->data))
-
-
-/* Advance the head to the next free location. If the storage is full,
- * a new storage is allocated and linked into the list.
- */
-#define INC_STORAGE_NEXT(name) do { \
- if (name##free == name##last_free) { \
- name##tail = (INC_Storage*)erts_alloc(ERTS_ALC_T_OBJECT_STACK, \
- sizeof(INC_Storage)); \
- memcpy(name##tail->data,name##head->data, \
- INC_STORAGE_SIZE * sizeof(INC_Object)); \
- name##tail->next = name##head->next; \
- name##head->next = name##tail; \
- name##tail->prev = name##tail->next->prev; \
- name##tail->next->prev = name##tail; \
- name##last_free = ((void*)name##tail + \
- ((void*)name##last_free - (void*)name##head)); \
- } \
- name##free++; \
- name##size++; \
- if (name##free == name##head->data + INC_STORAGE_SIZE) { \
- name##head = name##head->next; \
- name##free = name##head->data; \
- } \
-} while(0)
-
-
-/* The head of this storage is the next free location. This is where
- * the next element will be stored.
- */
-#define INC_STORAGE_HEAD(name) (name##free)
-
-
-/* Return the top - the youngest element in the storage. */
-/* #define INC_STORAGE_TOP(name) (name##free - 1 with some magic..) */
-
-
-/* True if the storage is empty, false otherwise */
-#define INC_STORAGE_EMPTY(name) (name##size == 0)
-
-
-/* Store a new element in the head of the storage and advance the head
- * to the next free location.
- */
-#define INC_STORE(name,ptr,sz) do { \
- INC_STORAGE_HEAD(name)->this = ptr; \
- INC_STORAGE_HEAD(name)->size = sz; \
- INC_STORAGE_NEXT(name); \
-} while(0)
-
-
-/* An iterator. Use it together with INC_STORAGE_STEP to browse throuh
- * the storage. Please note that it is not possible to remove an entry
- * in the middle of the storage, use GET or POP to remove enties.
- */
-#define INC_STORAGE_ITERATOR(name) \
- INC_Storage *name##iterator_head = name##tail; \
- INC_Object *name##iterator_current = name##last_free; \
- int name##iterator_left = name##size;
-
-
-/* Return the next element in the storage (sorted by age, oldest
- * first) or NULL if the storage is empty or the last element has been
- * returned already.
- */
-#define INC_STORAGE_STEP(name) (name##iterator_left == 0 ? NULL : \
- (name##iterator_left--, \
- (++name##iterator_current != name##iterator_head->data + \
- INC_STORAGE_SIZE) ? name##iterator_current : \
- (name##iterator_head = name##iterator_head->next, \
- name##iterator_current = name##iterator_head->data)))
-
-
-/* Erase the storage. */
-#define INC_STORAGE_ERASE(name)do { \
- name##head->prev->next = NULL; \
- while (name##head != NULL) { \
- name##tail = name##head; \
- name##head = name##head->next; \
- erts_free(ERTS_ALC_T_OBJECT_STACK,(void*)name##tail); \
- } \
- name##tail = NULL; \
- name##free = NULL; \
- name##last_free = NULL; \
- name##size = 0; \
-} while(0)
-
-/*
- * Structures used by the non-moving memory manager
- */
-
-typedef struct
-{
- Eterm *this;
- unsigned long size;
-} INC_Object;
-
-typedef struct inc_storage {
- struct inc_storage *next;
- struct inc_storage *prev;
- INC_Object data[INC_STORAGE_SIZE];
-} INC_Storage;
-
-typedef struct inc_mem_block
-{
- unsigned long size;
- struct inc_mem_block *prev;
- struct inc_mem_block *next;
-} INC_MemBlock;
-
-typedef struct inc_page
-{
- struct inc_page *next;
- Eterm start[1]; /* Has to be last in struct, this is where the data start */
-} INC_Page;
-
-
-/*
- * Heap pointers for the non-moving memory area.
- */
-extern INC_Page *inc_used_mem;
-extern INC_MemBlock *inc_free_list;
-extern unsigned char *blackmap;
-
-extern Eterm **fwdptrs;
-extern Eterm *inc_fromspc;
-extern Eterm *inc_fromend;
-extern Process *inc_active_proc;
-extern Process *inc_active_last;
-extern Eterm *inc_alloc_limit;
-extern int inc_words_to_go;
-
-INC_STORAGE_DECLARATION(extern,gray);
-INC_STORAGE_DECLARATION(extern,root);
-
-void erts_init_incgc(void);
-void erts_cleanup_incgc(void);
-void erts_incremental_gc(Process *p, int sz, Eterm* objv, int nobj);
-Eterm *erts_inc_alloc(int need);
-
-#else
-# define INC_STORE(lst,ptr,sz)
-# define INC_MARK_FORWARD(ptr)
-# define INC_IS_FORWARDED(ptr)
-# define INC_FORWARD_VALUE(ptr)
-#endif /* INCREMENTAL */
-
-#endif /* _ERL_NMGC_H_ */
diff --git a/erts/emulator/beam/erl_node_container_utils.h b/erts/emulator/beam/erl_node_container_utils.h
index 2c67e781e0..329a2204cc 100644
--- a/erts/emulator/beam/erl_node_container_utils.h
+++ b/erts/emulator/beam/erl_node_container_utils.h
@@ -176,7 +176,7 @@ extern int erts_use_r9_pids_ports;
* 32-bit CPU.
*/
-#define ERTS_MAX_PROCESSES ((1L << 27)-1)
+#define ERTS_MAX_PROCESSES ((SWORD_CONSTANT(1) << 27)-1)
#if (ERTS_MAX_PROCESSES > MAX_SMALL)
# error "The maximum number of processes must fit in a SMALL."
#endif
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index af3873995e..c7fd379367 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -26,6 +26,8 @@
#include "dist.h"
#include "big.h"
#include "error.h"
+#include "erl_thr_progress.h"
+#include "dtrace-wrapper.h"
Hash erts_dist_table;
Hash erts_node_table;
@@ -41,6 +43,8 @@ Sint erts_no_of_not_connected_dist_entries;
DistEntry *erts_this_dist_entry;
ErlNode *erts_this_node;
+char erts_this_node_sysname_BUFFER[256],
+ *erts_this_node_sysname = "uninitialized yet";
static Uint node_entries;
static Uint dist_entries;
@@ -701,6 +705,9 @@ erts_set_this_node(Eterm sysname, Uint creation)
(void) hash_erase(&erts_node_table, (void *) erts_this_node);
erts_this_node->sysname = sysname;
erts_this_node->creation = creation;
+ erts_this_node_sysname = erts_this_node_sysname_BUFFER;
+ erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname),
+ "%T", sysname);
(void) hash_put(&erts_node_table, (void *) erts_this_node);
erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
@@ -788,6 +795,9 @@ void erts_init_node_tables(void)
erts_this_node->sysname = am_Noname;
erts_this_node->creation = 0;
erts_this_node->dist_entry = erts_this_dist_entry;
+ erts_this_node_sysname = erts_this_node_sysname_BUFFER;
+ erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname),
+ "%T", erts_this_node->sysname);
(void) hash_put(&erts_node_table, (void *) erts_this_node);
@@ -839,9 +849,6 @@ static Eterm AM_dist_references;
static Eterm AM_node_references;
static Eterm AM_system;
static Eterm AM_timer;
-#ifdef HYBRID
-static Eterm AM_processes;
-#endif
static void setup_reference_table(void);
static Eterm reference_table_term(Uint **hpp, Uint *szp);
@@ -907,7 +914,7 @@ erts_get_node_and_dist_references(struct process *proc)
#endif
erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* No need to lock any thing since we are alone... */
if (references_atoms_need_init) {
@@ -926,9 +933,6 @@ erts_get_node_and_dist_references(struct process *proc)
INIT_AM(node_references);
INIT_AM(timer);
INIT_AM(system);
-#ifdef HYBRID
- INIT_AM(processes);
-#endif
references_atoms_need_init = 0;
}
@@ -951,7 +955,7 @@ erts_get_node_and_dist_references(struct process *proc)
delete_reference_table();
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
return res;
}
@@ -1291,12 +1295,6 @@ setup_reference_table(void)
SYSTEM_REF,
TUPLE2(&heap[0], AM_system, am_undefined));
-#ifdef HYBRID
- /* Insert Heap */
- insert_offheap(&erts_global_offheap,
- HEAP_REF,
- TUPLE2(&heap[0], AM_processes, am_undefined));
-#endif
UnUseTmpHeapNoproc(3);
/* Insert all processes */
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index b0a63ae035..4a015bdef9 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -169,6 +169,7 @@ extern Sint erts_no_of_not_connected_dist_entries;
extern DistEntry *erts_this_dist_entry;
extern ErlNode *erts_this_node;
+extern char *erts_this_node_sysname; /* must match erl_node_tables.c */
DistEntry *erts_channel_no_to_dist_entry(Uint);
DistEntry *erts_sysname_to_connected_dist_entry(Eterm);
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 6aa5161b08..0f1a0d441a 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2012. All Rights Reserved.
*
* The 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 "global.h"
#include "erl_port_task.h"
#include "dist.h"
+#include "dtrace-wrapper.h"
#if defined(DEBUG) && 0
#define HARD_DEBUG
@@ -61,6 +62,20 @@ do { \
(P)->sched.next = NULL; \
} while (0)
+#ifdef USE_VM_PROBES
+#define DTRACE_DRIVER(PROBE_NAME, PP) \
+ if (DTRACE_ENABLED(driver_ready_input)) { \
+ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \
+ \
+ dtrace_pid_str(PP->connected, process_str); \
+ dtrace_port_str(PP, port_str); \
+ DTRACE3(PROBE_NAME, process_str, port_str, PP->name); \
+ }
+#else
+#define DTRACE_DRIVER(PROBE_NAME, PP) do {} while(0)
+#endif
+
erts_smp_atomic_t erts_port_task_outstanding_io_tasks;
struct ErtsPortTaskQueue_ {
@@ -711,23 +726,6 @@ typedef struct {
int *resp;
} ErtsPortTaskExeBlockData;
-static void
-prepare_for_block(void *vd)
-{
- ErtsPortTaskExeBlockData *d = (ErtsPortTaskExeBlockData *) vd;
- erts_smp_runq_unlock(d->runq);
-}
-
-static void
-resume_after_block(void *vd)
-{
- ErtsPortTaskExeBlockData *d = (ErtsPortTaskExeBlockData *) vd;
- erts_smp_runq_lock(d->runq);
- if (d->resp)
- *d->resp = (erts_smp_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
- != (erts_aint_t) 0);
-}
-
/*
* Run all scheduled tasks for the first port in run queue. If
* new tasks appear while running reschedule port (free task is
@@ -748,15 +746,9 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
int reds = ERTS_PORT_REDS_EXECUTE;
erts_aint_t io_tasks_executed = 0;
int fpe_was_unmasked;
- ErtsPortTaskExeBlockData blk_data = {runq, NULL};
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
- erts_smp_activity_begin(ERTS_ACTIVITY_IO,
- prepare_for_block,
- resume_after_block,
- (void *) &blk_data);
-
ERTS_PT_CHK_PORTQ(runq);
pp = pop_port(runq);
@@ -846,12 +838,15 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
goto tasks_done;
case ERTS_PORT_TASK_TIMEOUT:
reds += ERTS_PORT_REDS_TIMEOUT;
- if (!(pp->status & ERTS_PORT_SFLGS_DEAD))
+ if (!(pp->status & ERTS_PORT_SFLGS_DEAD)) {
+ DTRACE_DRIVER(driver_timeout, pp);
(*pp->drv_ptr->timeout)((ErlDrvData) pp->drv_data);
+ }
break;
case ERTS_PORT_TASK_INPUT:
reds += ERTS_PORT_REDS_INPUT;
ASSERT((pp->status & ERTS_PORT_SFLGS_DEAD) == 0);
+ DTRACE_DRIVER(driver_ready_input, pp);
/* NOTE some windows drivers use ->ready_input for input and output */
(*pp->drv_ptr->ready_input)((ErlDrvData) pp->drv_data, ptp->event);
io_tasks_executed++;
@@ -859,12 +854,14 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
case ERTS_PORT_TASK_OUTPUT:
reds += ERTS_PORT_REDS_OUTPUT;
ASSERT((pp->status & ERTS_PORT_SFLGS_DEAD) == 0);
+ DTRACE_DRIVER(driver_ready_output, pp);
(*pp->drv_ptr->ready_output)((ErlDrvData) pp->drv_data, ptp->event);
io_tasks_executed++;
break;
case ERTS_PORT_TASK_EVENT:
reds += ERTS_PORT_REDS_EVENT;
ASSERT((pp->status & ERTS_PORT_SFLGS_DEAD) == 0);
+ DTRACE_DRIVER(driver_event, pp);
(*pp->drv_ptr->event)((ErlDrvData) pp->drv_data, ptp->event, ptp->event_data);
io_tasks_executed++;
break;
@@ -987,12 +984,6 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
#endif
done:
- blk_data.resp = &res;
- erts_smp_activity_end(ERTS_ACTIVITY_IO,
- prepare_for_block,
- resume_after_block,
- (void *) &blk_data);
-
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
ERTS_PORT_REDUCTIONS_EXECUTED(runq, reds);
@@ -1074,8 +1065,6 @@ erts_port_migrate(Port *prt, int *prt_locked,
ERTS_SMP_LC_CHK_RUNQ_LOCK(from_rq, *from_locked);
ERTS_SMP_LC_CHK_RUNQ_LOCK(to_rq, *to_locked);
- ASSERT(!erts_common_run_queue);
-
if (!*from_locked || !*to_locked) {
if (from_rq < to_rq) {
if (!*to_locked) {
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 5ceb4ce9a8..0fa2def5af 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,6 @@
#include "erl_vm.h"
#include "global.h"
#include "erl_process.h"
-#include "erl_nmgc.h"
#include "error.h"
#include "bif.h"
#include "erl_db.h"
@@ -39,6 +38,10 @@
#include "erl_binary.h"
#include "beam_bp.h"
#include "erl_cpu_topology.h"
+#include "erl_thr_progress.h"
+#include "erl_thr_queue.h"
+#include "erl_async.h"
+#include "dtrace-wrapper.h"
#define ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED (2000*CONTEXT_REDS)
#define ERTS_RUNQ_CALL_CHECK_BALANCE_REDS \
@@ -48,21 +51,22 @@
#define ERTS_SCHED_SPIN_UNTIL_YIELD 100
-#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT 10
+#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_VERY_LONG 40
+#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_VERY_LONG 1000
+#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_LONG 20
+#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_LONG 1000
+#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM 10
+#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_MEDIUM 1000
+#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_SHORT 10
+#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_SHORT 0
+#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_VERY_SHORT 5
+#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_VERY_SHORT 0
+#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_NONE 0
+#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_NONE 0
+
#define ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT 1000
-#define ERTS_SCHED_TSE_SLEEP_SPINCOUNT \
- (ERTS_SCHED_SYS_SLEEP_SPINCOUNT*ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT)
#define ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT 0
-#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH (200*CONTEXT_REDS)
-#define ERTS_WAKEUP_OTHER_LIMIT_HIGH (50*CONTEXT_REDS)
-#define ERTS_WAKEUP_OTHER_LIMIT_MEDIUM (10*CONTEXT_REDS)
-#define ERTS_WAKEUP_OTHER_LIMIT_LOW (CONTEXT_REDS)
-#define ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW (CONTEXT_REDS/10)
-
-#define ERTS_WAKEUP_OTHER_DEC 10
-#define ERTS_WAKEUP_OTHER_FIXED_INC (CONTEXT_REDS/10)
-
#if 0 || defined(DEBUG)
#define ERTS_FAKE_SCHED_BIND_PRINT_SORTED_CPU_DATA
#endif
@@ -101,6 +105,9 @@ do { \
#define ERTS_EMPTY_RUNQ(RQ) \
((RQ)->len == 0 && (RQ)->misc.start == NULL)
+#define ERTS_EMPTY_RUNQ_PORTS(RQ) \
+ ((RQ)->ports.info.len == 0 && (RQ)->misc.start == NULL)
+
extern BeamInstr beam_apply[];
extern BeamInstr beam_exit[];
extern BeamInstr beam_continue_exit[];
@@ -111,22 +118,28 @@ static Sint p_serial;
static Uint p_serial_mask;
static Uint p_serial_shift;
+int erts_sched_compact_load;
Uint erts_no_schedulers;
Uint erts_max_processes = ERTS_DEFAULT_MAX_PROCESSES;
Uint erts_process_tab_index_mask;
-static int wakeup_other_limit;
-
int erts_sched_thread_suggested_stack_size = -1;
#ifdef ERTS_ENABLE_LOCK_CHECK
ErtsLcPSDLocks erts_psd_required_locks[ERTS_PSD_SIZE];
#endif
-#ifdef ERTS_SMP
+static struct {
+ int aux_work;
+ int tse;
+ int sys_schedule;
+} sched_busy_wait;
+#ifdef ERTS_SMP
int erts_disable_proc_not_running_opt;
+static ErtsAuxWorkData *aux_thread_aux_work_data;
+
#define ERTS_SCHDLR_SSPND_CHNG_WAITER (((erts_aint32_t) 1) << 0)
#define ERTS_SCHDLR_SSPND_CHNG_MSB (((erts_aint32_t) 1) << 1)
#define ERTS_SCHDLR_SSPND_CHNG_ONLN (((erts_aint32_t) 1) << 2)
@@ -191,8 +204,6 @@ do { \
erts_sched_stat_t erts_sched_stat;
-ErtsRunQueue *erts_common_run_queue;
-
#ifdef USE_THREADS
static erts_tsd_key_t sched_data_key;
#endif
@@ -213,8 +224,6 @@ Uint erts_no_run_queues;
ErtsAlignedSchedulerData *erts_aligned_scheduler_data;
-#ifdef ERTS_SMP
-
typedef union {
ErtsSchedulerSleepInfo ssi;
char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsSchedulerSleepInfo))];
@@ -222,18 +231,11 @@ typedef union {
static ErtsAlignedSchedulerSleepInfo *aligned_sched_sleep_info;
-#endif
-
-#ifndef BM_COUNTERS
-static int processes_busy;
-#endif
-
Process** process_tab;
static Uint last_reductions;
static Uint last_exact_reductions;
Uint erts_default_process_flags;
Eterm erts_system_monitor;
-Eterm erts_system_monitor_msg_queue_len;
Eterm erts_system_monitor_long_gc;
Eterm erts_system_monitor_large_heap;
struct erts_system_monitor_flags_t erts_system_monitor_flags;
@@ -242,11 +244,6 @@ struct erts_system_monitor_flags_t erts_system_monitor_flags;
Eterm erts_system_profile;
struct erts_system_profile_flags_t erts_system_profile_flags;
-#ifdef HYBRID
-Uint erts_num_active_procs;
-Process** erts_active_procs;
-#endif
-
#if ERTS_MAX_PROCESSES > 0x7fffffff
#error "Need to store process_count in another type"
#endif
@@ -285,8 +282,9 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(proclist,
ERTS_ALC_T_PROC_LIST)
#define ERTS_SCHED_SLEEP_INFO_IX(IX) \
- (ASSERT_EXPR(0 <= (IX) && (IX) < erts_no_schedulers), \
- &aligned_sched_sleep_info[(IX)].ssi)
+ (ASSERT_EXPR(-1 <= ((int) (IX)) \
+ && ((int) (IX)) < ((int) erts_no_schedulers)), \
+ &aligned_sched_sleep_info[(IX)].ssi)
#define ERTS_FOREACH_RUNQ(RQVAR, DO) \
do { \
@@ -339,6 +337,55 @@ static void exec_misc_ops(ErtsRunQueue *);
static void print_function_from_pc(int to, void *to_arg, BeamInstr* x);
static int stack_element_dump(int to, void *to_arg, Process* p, Eterm* sp,
int yreg);
+
+static void aux_work_timeout(void *unused);
+static void aux_work_timeout_early_init(int no_schedulers);
+static void aux_work_timeout_late_init(void);
+static void setup_aux_work_timer(void);
+
+#if defined(DEBUG) || 0
+#define ERTS_DBG_CHK_AUX_WORK_VAL(V) dbg_chk_aux_work_val((V))
+static void
+dbg_chk_aux_work_val(erts_aint32_t value)
+{
+ erts_aint32_t valid = 0;
+
+ valid |= ERTS_SSI_AUX_WORK_SET_TMO;
+ valid |= ERTS_SSI_AUX_WORK_MISC;
+ valid |= ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM;
+ valid |= ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC;
+#if ERTS_USE_ASYNC_READY_Q
+ valid |= ERTS_SSI_AUX_WORK_ASYNC_READY;
+ valid |= ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+#endif
+#ifdef ERTS_SMP
+ valid |= ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP;
+ valid |= ERTS_SSI_AUX_WORK_MISC_THR_PRGR;
+ valid |= ERTS_SSI_AUX_WORK_DD;
+ valid |= ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+#endif
+#if HAVE_ERTS_MSEG
+ valid |= ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK;
+#endif
+#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
+ valid |= ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
+#endif
+#ifdef ERTS_SSI_AUX_WORK_REAP_PORTS
+ valid |= ERTS_SSI_AUX_WORK_REAP_PORTS;
+#endif
+
+ if (~valid & value)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Invalid aux_work value found: 0x%x\n",
+ ~valid & value);
+}
+#define ERTS_DBG_CHK_SSI_AUX_WORK(SSI) \
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&(SSI)->aux_work))
+#else
+#define ERTS_DBG_CHK_AUX_WORK_VAL(V)
+#define ERTS_DBG_CHK_SSI_AUX_WORK(SSI)
+#endif
+
#ifdef ERTS_SMP
static void handle_pending_exiters(ErtsProcList *);
@@ -420,12 +467,6 @@ erts_init_process(int ncpu)
process_tab = (Process**) erts_alloc(ERTS_ALC_T_PROC_TABLE,
erts_max_processes*sizeof(Process*));
sys_memzero(process_tab, erts_max_processes * sizeof(Process*));
-#ifdef HYBRID
- erts_active_procs = (Process**)
- erts_alloc(ERTS_ALC_T_ACTIVE_PROCS,
- erts_max_processes * sizeof(Process*));
- erts_num_active_procs = 0;
-#endif
erts_smp_mtx_init(&proc_tab_mtx, "proc_tab");
p_last = -1;
@@ -435,9 +476,6 @@ erts_init_process(int ncpu)
p_serial_shift = erts_fit_in_bits(erts_max_processes - 1);
p_serial_mask = ((~(~((Uint) 0) << proc_bits)) >> p_serial_shift);
erts_process_tab_index_mask = ~(~((Uint) 0) << p_serial_shift);
-#ifndef BM_COUNTERS
- processes_busy = 0;
-#endif
last_reductions = 0;
last_exact_reductions = 0;
erts_default_process_flags = 0;
@@ -484,6 +522,213 @@ erts_late_init_process(void)
}
+static void
+init_sched_wall_time(ErtsSchedWallTime *swtp)
+{
+ swtp->enabled = 0;
+ swtp->start = 0;
+ swtp->working.total = 0;
+ swtp->working.start = 0;
+ swtp->working.currently = 0;
+}
+
+static ERTS_INLINE Uint64
+sched_wall_time_ts(void)
+{
+#ifdef HAVE_GETHRTIME
+ return (Uint64) sys_gethrtime();
+#else
+ Uint64 res;
+ SysTimeval tv;
+ sys_gettimeofday(&tv);
+ res = (Uint64) tv.tv_sec*1000000;
+ res += (Uint64) tv.tv_usec;
+ return res;
+#endif
+}
+
+static ERTS_INLINE void
+sched_wall_time_change(ErtsSchedulerData *esdp, int working)
+{
+ if (esdp->sched_wall_time.enabled) {
+ Uint64 ts = sched_wall_time_ts();
+ if (working) {
+#ifdef DEBUG
+ ASSERT(!esdp->sched_wall_time.working.currently);
+ esdp->sched_wall_time.working.currently = 1;
+#endif
+ ts -= esdp->sched_wall_time.start;
+ esdp->sched_wall_time.working.start = ts;
+ }
+ else {
+#ifdef DEBUG
+ ASSERT(esdp->sched_wall_time.working.currently);
+ esdp->sched_wall_time.working.currently = 0;
+#endif
+ ts -= esdp->sched_wall_time.start;
+ ts -= esdp->sched_wall_time.working.start;
+ esdp->sched_wall_time.working.total += ts;
+ }
+ }
+}
+
+typedef struct {
+ int set;
+ int enable;
+ Process *proc;
+ Eterm ref;
+ Eterm ref_heap[REF_THING_SIZE];
+ Uint req_sched;
+ erts_smp_atomic32_t refc;
+} ErtsSchedWallTimeReq;
+
+#if !HALFWORD_HEAP
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(swtreq,
+ ErtsSchedWallTimeReq,
+ 5,
+ ERTS_ALC_T_SCHED_WTIME_REQ)
+#else
+static ERTS_INLINE ErtsSchedWallTimeReq *
+swtreq_alloc(void)
+{
+ return erts_alloc(ERTS_ALC_T_SCHED_WTIME_REQ,
+ sizeof(ErtsSchedWallTimeReq));
+}
+
+static ERTS_INLINE void
+swtreq_free(ErtsSchedWallTimeReq *ptr)
+{
+ erts_free(ERTS_ALC_T_SCHED_WTIME_REQ, ptr);
+}
+#endif
+
+static void
+reply_sched_wall_time(void *vswtrp)
+{
+ Uint64 working = 0, total = 0;
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsSchedWallTimeReq *swtrp = (ErtsSchedWallTimeReq *) vswtrp;
+ ErtsProcLocks rp_locks = (swtrp->req_sched == esdp->no
+ ? ERTS_PROC_LOCK_MAIN
+ : 0);
+ Process *rp = swtrp->proc;
+ Eterm ref_copy = NIL, msg;
+ Eterm *hp = NULL;
+ Eterm **hpp;
+ Uint sz, *szp;
+ ErlOffHeap *ohp = NULL;
+ ErlHeapFragment *bp = NULL;
+
+ ASSERT(esdp);
+
+ if (swtrp->set) {
+ if (!swtrp->enable && esdp->sched_wall_time.enabled)
+ esdp->sched_wall_time.enabled = 0;
+ else if (swtrp->enable && !esdp->sched_wall_time.enabled) {
+ Uint64 ts = sched_wall_time_ts();
+ esdp->sched_wall_time.enabled = 1;
+ esdp->sched_wall_time.start = ts;
+ esdp->sched_wall_time.working.total = 0;
+ esdp->sched_wall_time.working.start = 0;
+ esdp->sched_wall_time.working.currently = 1;
+ }
+ }
+
+ if (esdp->sched_wall_time.enabled) {
+ Uint64 ts = sched_wall_time_ts();
+ ASSERT(esdp->sched_wall_time.working.currently);
+ ts -= esdp->sched_wall_time.start;
+ total = ts;
+ ts -= esdp->sched_wall_time.working.start;
+ working = esdp->sched_wall_time.working.total + ts;
+ }
+
+ sz = 0;
+ hpp = NULL;
+ szp = &sz;
+
+ while (1) {
+ if (hpp)
+ ref_copy = STORE_NC(hpp, ohp, swtrp->ref);
+ else
+ *szp += REF_THING_SIZE;
+
+ if (swtrp->set)
+ msg = ref_copy;
+ else {
+ msg = (!esdp->sched_wall_time.enabled
+ ? am_notsup
+ : erts_bld_tuple(hpp, szp, 3,
+ make_small(esdp->no),
+ erts_bld_uint64(hpp, szp, working),
+ erts_bld_uint64(hpp, szp, total)));
+
+ msg = erts_bld_tuple(hpp, szp, 2, ref_copy, msg);
+ }
+ if (hpp)
+ break;
+
+ hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ szp = NULL;
+ hpp = &hp;
+ }
+
+ erts_queue_message(rp, &rp_locks, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
+
+ if (swtrp->req_sched == esdp->no)
+ rp_locks &= ~ERTS_PROC_LOCK_MAIN;
+
+ if (rp_locks)
+ erts_smp_proc_unlock(rp, rp_locks);
+
+ erts_smp_proc_dec_refc(rp);
+
+ if (erts_smp_atomic32_dec_read_nob(&swtrp->refc) == 0)
+ swtreq_free(vswtrp);
+}
+
+Eterm
+erts_sched_wall_time_request(Process *c_p, int set, int enable)
+{
+ ErtsSchedulerData *esdp = ERTS_PROC_GET_SCHDATA(c_p);
+ Eterm ref;
+ ErtsSchedWallTimeReq *swtrp;
+ Eterm *hp;
+
+ if (!set && !esdp->sched_wall_time.enabled)
+ return THE_NON_VALUE;
+
+ swtrp = swtreq_alloc();
+ ref = erts_make_ref(c_p);
+ hp = &swtrp->ref_heap[0];
+
+ swtrp->set = set;
+ swtrp->enable = enable;
+ swtrp->proc = c_p;
+ swtrp->ref = STORE_NC(&hp, NULL, ref);
+ swtrp->req_sched = esdp->no;
+ erts_smp_atomic32_init_nob(&swtrp->refc,
+ (erts_aint32_t) erts_no_schedulers);
+
+ erts_smp_proc_add_refc(c_p, (Sint32) erts_no_schedulers);
+
+#ifdef ERTS_SMP
+ if (erts_no_schedulers > 1)
+ erts_schedule_multi_misc_aux_work(1,
+ erts_no_schedulers,
+ reply_sched_wall_time,
+ (void *) swtrp);
+#endif
+
+ reply_sched_wall_time((void *) swtrp);
+
+ return ref;
+}
+
static ERTS_INLINE ErtsProcList *
proclist_create(Process *p)
{
@@ -577,6 +822,13 @@ erts_sched_finish_poke(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flags)
case ERTS_SSI_FLG_POLL_SLEEPING:
erts_sys_schedule_interrupt(1);
break;
+ case ERTS_SSI_FLG_POLL_SLEEPING|ERTS_SSI_FLG_TSE_SLEEPING:
+ /*
+ * Thread progress blocking while poll sleeping; need
+ * to signal on both...
+ */
+ erts_sys_schedule_interrupt(1);
+ /* fall through */
case ERTS_SSI_FLG_TSE_SLEEPING:
erts_tse_set(ssi->event);
break;
@@ -589,189 +841,894 @@ erts_sched_finish_poke(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flags)
}
}
+#endif
+
+static ERTS_INLINE void
+set_aux_work_flags_wakeup_nob(ErtsSchedulerSleepInfo *ssi,
+ erts_aint32_t flgs)
+{
+ erts_aint32_t old_flgs;
+
+ ERTS_DBG_CHK_SSI_AUX_WORK(ssi);
+
+ old_flgs = erts_atomic32_read_nob(&ssi->aux_work);
+ if ((old_flgs & flgs) == 0) {
+
+ old_flgs = erts_atomic32_read_bor_nob(&ssi->aux_work, flgs);
+
+ if ((old_flgs & flgs) == 0) {
+#ifdef ERTS_SMP
+ erts_sched_poke(ssi);
+#else
+ erts_sys_schedule_interrupt(1);
+#endif
+ }
+ }
+}
+
+static ERTS_INLINE void
+set_aux_work_flags_wakeup_relb(ErtsSchedulerSleepInfo *ssi,
+ erts_aint32_t flgs)
+{
+ erts_aint32_t old_flgs;
+
+ ERTS_DBG_CHK_SSI_AUX_WORK(ssi);
+
+ old_flgs = erts_atomic32_read_bor_relb(&ssi->aux_work, flgs);
+
+ if ((old_flgs & flgs) == 0) {
+#ifdef ERTS_SMP
+ erts_sched_poke(ssi);
+#else
+ erts_sys_schedule_interrupt(1);
+#endif
+ }
+}
+
+static ERTS_INLINE erts_aint32_t
+set_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs)
+{
+ return erts_atomic32_read_bor_nob(&ssi->aux_work, flgs);
+}
+
+static ERTS_INLINE erts_aint32_t
+unset_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs)
+{
+ return erts_atomic32_read_band_nob(&ssi->aux_work, ~flgs);
+}
+
+#ifdef ERTS_SMP
+
+static ERTS_INLINE void
+haw_thr_prgr_current_reset(ErtsAuxWorkData *awdp)
+{
+ awdp->current_thr_prgr = ERTS_THR_PRGR_INVALID;
+}
+
+static ERTS_INLINE ErtsThrPrgrVal
+haw_thr_prgr_current(ErtsAuxWorkData *awdp)
+{
+ ErtsThrPrgrVal current = awdp->current_thr_prgr;
+ if (current == ERTS_THR_PRGR_INVALID) {
+ current = erts_thr_progress_current();
+ awdp->current_thr_prgr = current;
+ }
+ return current;
+}
+
+static ERTS_INLINE void
+haw_thr_prgr_current_check_progress(ErtsAuxWorkData *awdp)
+{
+ ErtsThrPrgrVal current = awdp->current_thr_prgr;
+ if (current != ERTS_THR_PRGR_INVALID
+ && !erts_thr_progress_equal(current, erts_thr_progress_current())) {
+ /*
+ * We have used a previouly read current value that isn't the
+ * latest; need to poke ourselfs in order to guarantee no loss
+ * of wakeups.
+ */
+ erts_sched_poke(awdp->ssi);
+ }
+}
+
+static ERTS_INLINE erts_aint32_t
+handle_delayed_aux_work_wakeup(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ int jix, max_jix;
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP);
+
+ ERTS_THR_MEMORY_BARRIER;
+
+ max_jix = awdp->delayed_wakeup.jix;
+ awdp->delayed_wakeup.jix = -1;
+ for (jix = 0; jix <= max_jix; jix++) {
+ int sched = awdp->delayed_wakeup.job[jix].sched;
+ erts_aint32_t aux_work = awdp->delayed_wakeup.job[jix].aux_work;
+
+ ASSERT(awdp->delayed_wakeup.sched2jix[sched] == jix);
+ awdp->delayed_wakeup.sched2jix[sched] = -1;
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(sched-1),
+ aux_work);
+ }
+ return aux_work & ~ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP;
+}
+
+static ERTS_INLINE void
+schedule_aux_work_wakeup(ErtsAuxWorkData *awdp, int sched, erts_aint32_t aux_work)
+{
+ int jix = awdp->delayed_wakeup.sched2jix[sched];
+ if (jix >= 0) {
+ ASSERT(awdp->delayed_wakeup.job[jix].sched == sched);
+ awdp->delayed_wakeup.job[jix].aux_work |= aux_work;
+ }
+ else {
+ jix = ++awdp->delayed_wakeup.jix;
+ awdp->delayed_wakeup.sched2jix[sched] = jix;
+ awdp->delayed_wakeup.job[jix].sched = sched;
+ awdp->delayed_wakeup.job[jix].aux_work = aux_work;
+ }
+ set_aux_work_flags_wakeup_nob(awdp->ssi, ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP);
+}
+
+#endif
+
typedef struct erts_misc_aux_work_t_ erts_misc_aux_work_t;
struct erts_misc_aux_work_t_ {
- erts_misc_aux_work_t *next;
void (*func)(void *);
void *arg;
};
-typedef struct {
- erts_smp_mtx_t mtx;
- erts_misc_aux_work_t *first;
- erts_misc_aux_work_t *last;
-} erts_misc_aux_work_q_t;
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(misc_aux_work,
+ erts_misc_aux_work_t,
+ 200,
+ ERTS_ALC_T_MISC_AUX_WORK)
typedef union {
- erts_misc_aux_work_q_t data;
- char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_misc_aux_work_q_t))];
+ ErtsThrQ_t q;
+ char align[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQ_t))];
} erts_algnd_misc_aux_work_q_t;
static erts_algnd_misc_aux_work_q_t *misc_aux_work_queues;
-ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(misc_aux_work,
- erts_misc_aux_work_t,
- 200,
- ERTS_ALC_T_MISC_AUX_WORK)
+static void
+notify_aux_work(void *vssi)
+{
+ set_aux_work_flags_wakeup_nob((ErtsSchedulerSleepInfo *) vssi,
+ ERTS_SSI_AUX_WORK_MISC);
+}
static void
init_misc_aux_work(void)
{
int ix;
+ ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
+ qinit.notify = notify_aux_work;
init_misc_aux_work_alloc();
misc_aux_work_queues =
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_MISC_AUX_WORK_Q,
- erts_no_schedulers *
- sizeof(erts_algnd_misc_aux_work_q_t));
+ sizeof(erts_algnd_misc_aux_work_q_t)
+ * (erts_no_schedulers+1));
- for (ix = 0; ix < erts_no_schedulers; ix++) {
- erts_smp_mtx_init_x(&misc_aux_work_queues[ix].data.mtx,
- "misc_aux_work_queue",
- make_small(ix + 1));
- misc_aux_work_queues[ix].data.first = NULL;
- misc_aux_work_queues[ix].data.last = NULL;
+#ifdef ERTS_SMP
+ ix = 0; /* aux_thread + schedulers */
+#else
+ ix = 1; /* scheduler only */
+#endif
+
+ for (; ix <= erts_no_schedulers; ix++) {
+ qinit.arg = (void *) ERTS_SCHED_SLEEP_INFO_IX(ix-1);
+ erts_thr_q_initialize(&misc_aux_work_queues[ix].q, &qinit);
}
}
-static void
-handle_misc_aux_work(ErtsSchedulerData *esdp)
-{
- int ix = (int) esdp->no - 1;
- erts_misc_aux_work_t *mawp;
+static erts_aint32_t
+misc_aux_work_clean(ErtsThrQ_t *q,
+ ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ switch (erts_thr_q_clean(q)) {
+ case ERTS_THR_Q_DIRTY:
+ set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC);
+ return aux_work | ERTS_SSI_AUX_WORK_MISC;
+ case ERTS_THR_Q_NEED_THR_PRGR:
+#ifdef ERTS_SMP
+ set_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
+ erts_thr_progress_wakeup(awdp->esdp,
+ erts_thr_q_need_thr_progress(q));
+#endif
+ case ERTS_THR_Q_CLEAN:
+ break;
+ }
+ return aux_work;
+}
- erts_smp_mtx_lock(&misc_aux_work_queues[ix].data.mtx);
- mawp = misc_aux_work_queues[ix].data.first;
- misc_aux_work_queues[ix].data.first = NULL;
- misc_aux_work_queues[ix].data.last = NULL;
- erts_smp_mtx_unlock(&misc_aux_work_queues[ix].data.mtx);
+static ERTS_INLINE erts_aint32_t
+handle_misc_aux_work(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ ErtsThrQ_t *q = &misc_aux_work_queues[awdp->sched_id].q;
- while (mawp) {
- erts_misc_aux_work_t *free_mawp;
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC);
+ while (1) {
+ erts_misc_aux_work_t *mawp = erts_thr_q_dequeue(q);
+ if (!mawp)
+ break;
mawp->func(mawp->arg);
- free_mawp = mawp;
- mawp = mawp->next;
- misc_aux_work_free(free_mawp);
+ misc_aux_work_free(mawp);
}
+
+ return misc_aux_work_clean(q, awdp, aux_work & ~ERTS_SSI_AUX_WORK_MISC);
+}
+
+#ifdef ERTS_SMP
+
+static ERTS_INLINE erts_aint32_t
+handle_misc_aux_work_thr_prgr(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ if (!erts_thr_progress_has_reached_this(haw_thr_prgr_current(awdp),
+ awdp->misc.thr_prgr))
+ return aux_work & ~ERTS_SSI_AUX_WORK_MISC_THR_PRGR;
+
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
+
+ return misc_aux_work_clean(&misc_aux_work_queues[awdp->sched_id].q,
+ awdp,
+ aux_work & ~ERTS_SSI_AUX_WORK_MISC_THR_PRGR);
+}
+
+#endif
+
+static ERTS_INLINE void
+schedule_misc_aux_work(int sched_id,
+ void (*func)(void *),
+ void *arg)
+{
+ ErtsThrQ_t *q;
+ erts_misc_aux_work_t *mawp;
+
+#ifdef ERTS_SMP
+ ASSERT(0 <= sched_id && sched_id <= erts_no_schedulers);
+#else
+ ASSERT(sched_id == 1);
+#endif
+
+ q = &misc_aux_work_queues[sched_id].q;
+ mawp = misc_aux_work_alloc();
+ mawp->func = func;
+ mawp->arg = arg;
+ erts_thr_q_enqueue(q, mawp);
+}
+
+void
+erts_schedule_misc_aux_work(int sched_id,
+ void (*func)(void *),
+ void *arg)
+{
+ schedule_misc_aux_work(sched_id, func, arg);
}
void
-erts_smp_schedule_misc_aux_work(int ignore_self,
- int max_sched,
- void (*func)(void *),
- void *arg)
+erts_schedule_multi_misc_aux_work(int ignore_self,
+ int max_sched,
+ void (*func)(void *),
+ void *arg)
{
- int ix, ignore_ix = -1;
+ int id, self = 0;
if (ignore_self) {
ErtsSchedulerData *esdp = erts_get_scheduler_data();
if (esdp)
- ignore_ix = (int) esdp->no - 1;
+ self = (int) esdp->no;
}
- ASSERT(0 <= max_sched && max_sched <= erts_no_schedulers);
+ ASSERT(0 < max_sched && max_sched <= erts_no_schedulers);
- for (ix = 0; ix < max_sched; ix++) {
- erts_aint32_t aux_work;
- erts_misc_aux_work_t *mawp;
- ErtsSchedulerSleepInfo *ssi;
- if (ix == ignore_ix)
+ for (id = 1; id <= max_sched; id++) {
+ if (id == self)
continue;
+ schedule_misc_aux_work(id, func, arg);
+ }
+}
- mawp = misc_aux_work_alloc();
+#if ERTS_USE_ASYNC_READY_Q
- mawp->func = func;
- mawp->arg = arg;
- mawp->next = NULL;
+void
+erts_notify_check_async_ready_queue(void *vno)
+{
+ int ix = ((int) (SWord) vno) -1;
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(ix),
+ ERTS_SSI_AUX_WORK_ASYNC_READY);
+}
- erts_smp_mtx_lock(&misc_aux_work_queues[ix].data.mtx);
- if (!misc_aux_work_queues[ix].data.last)
- misc_aux_work_queues[ix].data.first = mawp;
- else
- misc_aux_work_queues[ix].data.last->next = mawp;
- misc_aux_work_queues[ix].data.last = mawp;
- erts_smp_mtx_unlock(&misc_aux_work_queues[ix].data.mtx);
-
- ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
- aux_work = erts_smp_atomic32_read_bor_nob(&ssi->aux_work,
- ERTS_SSI_AUX_WORK_MISC);
- if ((aux_work & ERTS_SSI_AUX_WORK_MISC) == 0)
- erts_sched_poke(ssi);
- }
+static ERTS_INLINE erts_aint32_t
+handle_async_ready(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi = awdp->ssi;
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY);
+ if (erts_check_async_ready(awdp->async_ready.queue)) {
+ if (set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY)
+ & ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN) {
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+ aux_work &= ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+ }
+ return aux_work;
+ }
+#ifdef ERTS_SMP
+ awdp->async_ready.need_thr_prgr = 0;
+#endif
+ set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+ return ((aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY)
+ | ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+}
+
+static ERTS_INLINE erts_aint32_t
+handle_async_ready_clean(ErtsAuxWorkData *awdp,
+ erts_aint32_t aux_work)
+{
+ void *thr_prgr_p;
+
+#ifdef ERTS_SMP
+ if (awdp->async_ready.need_thr_prgr
+ && !erts_thr_progress_has_reached_this(haw_thr_prgr_current(awdp),
+ awdp->async_ready.thr_prgr)) {
+ return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+ }
+
+ awdp->async_ready.need_thr_prgr = 0;
+ thr_prgr_p = (void *) &awdp->async_ready.thr_prgr;
+#else
+ thr_prgr_p = NULL;
+#endif
+
+ switch (erts_async_ready_clean(awdp->async_ready.queue, thr_prgr_p)) {
+ case ERTS_ASYNC_READY_CLEAN:
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN);
+ return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+#ifdef ERTS_SMP
+ case ERTS_ASYNC_READY_NEED_THR_PRGR:
+ erts_thr_progress_wakeup(awdp->esdp,
+ awdp->async_ready.thr_prgr);
+ awdp->async_ready.need_thr_prgr = 1;
+ return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN;
+#endif
+ default:
+ return aux_work;
+ }
+}
+
+#endif
+
+static ERTS_INLINE erts_aint32_t
+handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi = awdp->ssi;
+ erts_aint32_t res;
+
+ unset_aux_work_flags(ssi, (ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC));
+ aux_work &= ~(ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC);
+ res = erts_alloc_fix_alloc_shrink(awdp->sched_id, aux_work);
+ if (res) {
+ set_aux_work_flags(ssi, res);
+ aux_work |= res;
+ }
+
+ return aux_work;
}
+#ifdef ERTS_SMP
+
+void
+erts_alloc_notify_delayed_dealloc(int ix)
+{
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ if (esdp)
+ schedule_aux_work_wakeup(&esdp->aux_work_data,
+ ix,
+ ERTS_SSI_AUX_WORK_DD);
+ else
+ set_aux_work_flags_wakeup_relb(ERTS_SCHED_SLEEP_INFO_IX(ix-1),
+ ERTS_SSI_AUX_WORK_DD);
+}
+
+static ERTS_INLINE erts_aint32_t
+handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi = awdp->ssi;
+ int need_thr_progress = 0;
+ ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
+ int more_work = 0;
+
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD);
+ erts_alloc_scheduler_handle_delayed_dealloc((void *) awdp->esdp,
+ &need_thr_progress,
+ &wakeup,
+ &more_work);
+ if (more_work) {
+ if (set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD)
+ & ERTS_SSI_AUX_WORK_DD_THR_PRGR) {
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ aux_work &= ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+ }
+ return aux_work;
+ }
+
+ if (need_thr_progress) {
+ if (wakeup == ERTS_THR_PRGR_INVALID)
+ wakeup = erts_thr_progress_later(awdp->esdp);
+ awdp->dd.thr_prgr = wakeup;
+ set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ awdp->dd.thr_prgr = wakeup;
+ erts_thr_progress_wakeup(awdp->esdp, wakeup);
+ }
+ else if (awdp->dd.completed_callback) {
+ awdp->dd.completed_callback(awdp->dd.completed_arg);
+ awdp->dd.completed_callback = NULL;
+ awdp->dd.completed_arg = NULL;
+ }
+ return aux_work & ~ERTS_SSI_AUX_WORK_DD;
+}
+
+static ERTS_INLINE erts_aint32_t
+handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ ErtsSchedulerSleepInfo *ssi;
+ int need_thr_progress;
+ int more_work;
+ ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
+ ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
+
+ if (!erts_thr_progress_has_reached_this(current, awdp->dd.thr_prgr))
+ return aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+
+ ssi = awdp->ssi;
+ need_thr_progress = 0;
+ more_work = 0;
+
+ erts_alloc_scheduler_handle_delayed_dealloc((void *) awdp->esdp,
+ &need_thr_progress,
+ &wakeup,
+ &more_work);
+ if (more_work) {
+ set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD);
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ return ((aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR)
+ | ERTS_SSI_AUX_WORK_DD);
+ }
+
+ if (need_thr_progress) {
+ if (wakeup == ERTS_THR_PRGR_INVALID)
+ wakeup = erts_thr_progress_later(awdp->esdp);
+ awdp->dd.thr_prgr = wakeup;
+ erts_thr_progress_wakeup(awdp->esdp, wakeup);
+ }
+ else {
+ unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD_THR_PRGR);
+ if (awdp->dd.completed_callback) {
+ awdp->dd.completed_callback(awdp->dd.completed_arg);
+ awdp->dd.completed_callback = NULL;
+ awdp->dd.completed_arg = NULL;
+ }
+ }
+
+ return aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+}
+
+static erts_atomic32_t completed_dealloc_count;
+
+static void
+completed_dealloc(void *vproc)
+{
+ if (erts_atomic32_dec_read_mb(&completed_dealloc_count) == 0) {
+ erts_resume((Process *) vproc, (ErtsProcLocks) 0);
+ erts_smp_proc_dec_refc((Process *) vproc);
+ }
+}
+
+static void
+setup_completed_dealloc(void *vproc)
+{
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsAuxWorkData *awdp = (esdp
+ ? &esdp->aux_work_data
+ : aux_thread_aux_work_data);
+ erts_alloc_fix_alloc_shrink(awdp->sched_id, 0);
+ set_aux_work_flags_wakeup_nob(awdp->ssi, ERTS_SSI_AUX_WORK_DD);
+ awdp->dd.completed_callback = completed_dealloc;
+ awdp->dd.completed_arg = vproc;
+}
+
+static void
+prep_setup_completed_dealloc(void *vproc)
+{
+ erts_aint32_t count = (erts_aint32_t) (erts_no_schedulers+1);
+ if (erts_atomic32_dec_read_mb(&completed_dealloc_count) == count) {
+ /* scheduler threads */
+ erts_schedule_multi_misc_aux_work(0,
+ erts_no_schedulers,
+ setup_completed_dealloc,
+ vproc);
+ /* aux_thread */
+ erts_schedule_misc_aux_work(0,
+ setup_completed_dealloc,
+ vproc);
+ }
+}
+
+#endif /* ERTS_SMP */
+
+int
+erts_debug_wait_deallocations(Process *c_p)
+{
+#ifndef ERTS_SMP
+ erts_alloc_fix_alloc_shrink(1, 0);
+ return 1;
+#else
+ /* Only one process at a time can do this */
+ erts_aint32_t count = (erts_aint32_t) (2*(erts_no_schedulers+1));
+ if (0 == erts_atomic32_cmpxchg_mb(&completed_dealloc_count,
+ count,
+ 0)) {
+ erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
+ erts_smp_proc_inc_refc(c_p);
+ /* scheduler threads */
+ erts_schedule_multi_misc_aux_work(0,
+ erts_no_schedulers,
+ prep_setup_completed_dealloc,
+ (void *) c_p);
+ /* aux_thread */
+ erts_schedule_misc_aux_work(0,
+ prep_setup_completed_dealloc,
+ (void *) c_p);
+ return 1;
+ }
+ return 0;
+#endif
+}
+
+
#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
void
erts_smp_notify_check_children_needed(void)
{
int i;
+ for (i = 0; i < erts_no_schedulers; i++)
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(i),
+ ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
+}
+static ERTS_INLINE erts_aint32_t
+handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
+ erts_check_children();
+ return aux_work & ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
+}
+
+#endif
+
+static void
+notify_reap_ports_relb(void)
+{
+ int i;
for (i = 0; i < erts_no_schedulers; i++) {
- erts_aint32_t aux_work;
- ErtsSchedulerSleepInfo *ssi;
- ssi = ERTS_SCHED_SLEEP_INFO_IX(i);
- aux_work = erts_smp_atomic32_read_bor_nob(&ssi->aux_work,
- ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
- if (!(aux_work & ERTS_SSI_AUX_WORK_CHECK_CHILDREN))
- erts_sched_poke(ssi);
+ set_aux_work_flags_wakeup_relb(ERTS_SCHED_SLEEP_INFO_IX(i),
+ ERTS_SSI_AUX_WORK_REAP_PORTS);
}
}
-#endif
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
+erts_smp_atomic32_t erts_halt_progress;
+int erts_halt_code;
+
static ERTS_INLINE erts_aint32_t
-blockable_aux_work(ErtsSchedulerData *esdp,
- ErtsSchedulerSleepInfo *ssi,
- erts_aint32_t aux_work)
+handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
{
- if (aux_work & ERTS_SSI_BLOCKABLE_AUX_WORK_MASK) {
- if (aux_work & ERTS_SSI_AUX_WORK_MISC) {
- aux_work = erts_smp_atomic32_read_band_nob(&ssi->aux_work,
- ~ERTS_SSI_AUX_WORK_MISC);
- aux_work &= ~ERTS_SSI_AUX_WORK_MISC;
- handle_misc_aux_work(esdp);
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_REAP_PORTS);
+ awdp->esdp->run_queue->halt_in_progress = 1;
+ if (erts_smp_atomic32_dec_read_acqb(&erts_halt_progress) == 0) {
+ int i;
+ erts_smp_atomic32_set_nob(&erts_halt_progress, 1);
+ for (i = 0; i < erts_max_ports; i++) {
+ Port *prt = &erts_port[i];
+ erts_smp_port_state_lock(prt);
+ if ((prt->status & (ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ | ERTS_PORT_SFLG_HALT))) {
+ erts_smp_port_state_unlock(prt);
+ continue;
+ }
+ /* We need to set the halt flag - get the port lock */
+#ifdef ERTS_SMP
+ erts_smp_atomic_inc_nob(&prt->refc);
+#endif
+ erts_smp_port_state_unlock(prt);
+#ifdef ERTS_SMP
+ erts_smp_mtx_lock(prt->lock);
+#endif
+ if ((prt->status & (ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ | ERTS_PORT_SFLG_HALT))) {
+ erts_port_release(prt);
+ continue;
+ }
+ erts_port_status_bor_set(prt, ERTS_PORT_SFLG_HALT);
+ erts_smp_atomic32_inc_nob(&erts_halt_progress);
+ if (prt->status & (ERTS_PORT_SFLG_EXITING
+ | ERTS_PORT_SFLG_CLOSING)) {
+ erts_port_release(prt);
+ continue;
+ }
+ erts_do_exit_port(prt, prt->id, am_killed);
+ erts_port_release(prt);
}
-#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
- if (aux_work & ERTS_SSI_AUX_WORK_CHECK_CHILDREN) {
- aux_work = erts_smp_atomic32_band_nob(&ssi->aux_work,
- ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
- aux_work &= ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
- erts_check_children();
+ if (erts_smp_atomic32_dec_read_nob(&erts_halt_progress) == 0) {
+ erl_exit_flush_async(erts_halt_code, "");
}
-#endif
}
- return aux_work;
+ return aux_work & ~ERTS_SSI_AUX_WORK_REAP_PORTS;
+}
+
+#if HAVE_ERTS_MSEG
+
+static ERTS_INLINE erts_aint32_t
+handle_mseg_cache_check(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK);
+ erts_mseg_cache_check();
+ return aux_work & ~ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK;
}
#endif
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
static ERTS_INLINE erts_aint32_t
-nonblockable_aux_work(ErtsSchedulerData *esdp,
- ErtsSchedulerSleepInfo *ssi,
- erts_aint32_t aux_work)
+handle_setup_aux_work_timer(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
{
- if (aux_work & ERTS_SSI_NONBLOCKABLE_AUX_WORK_MASK) {
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_SET_TMO);
+ setup_aux_work_timer();
+ return aux_work & ~ERTS_SSI_AUX_WORK_SET_TMO;
+}
+static erts_aint32_t
+handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
+{
+#undef HANDLE_AUX_WORK
+#define HANDLE_AUX_WORK(FLG, HNDLR) \
+ ignore |= FLG; \
+ if (aux_work & FLG) { \
+ aux_work = HNDLR(awdp, aux_work); \
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \
+ if (!(aux_work & ~ignore)) { \
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \
+ return aux_work; \
+ } \
}
-}
+
+ erts_aint32_t aux_work = orig_aux_work;
+ erts_aint32_t ignore = 0;
+
+#ifdef ERTS_SMP
+ haw_thr_prgr_current_reset(awdp);
+#endif
+
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+ ASSERT(aux_work);
+
+ /*
+ * Handlers are *only* allowed to modify flags in return value
+ * and ssi flags that are explicity handled by the handler.
+ * Handlers are, e.g., not allowed to read the ssi flag field and
+ * then unconditionally return that value.
+ *
+ * Flag field returned should only contain flags for work that
+ * can continue immediately.
+ */
+
+ /*
+ * Keep ERTS_SSI_AUX_WORK flags in expected frequency order relative
+ * eachother. Most frequent first.
+ */
+#ifdef ERTS_SMP
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP,
+ handle_delayed_aux_work_wakeup);
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_DD,
+ handle_delayed_dealloc);
+ /* DD must be before DD_THR_PRGR */
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_DD_THR_PRGR,
+ handle_delayed_dealloc_thr_prgr);
#endif
+ HANDLE_AUX_WORK((ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM
+ | ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
+ handle_fix_alloc);
+
+#if ERTS_USE_ASYNC_READY_Q
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_ASYNC_READY,
+ handle_async_ready);
+ /* ASYNC_READY must be before ASYNC_READY_CLEAN */
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN,
+ handle_async_ready_clean);
+#endif
+
+#ifdef ERTS_SMP
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_MISC_THR_PRGR,
+ handle_misc_aux_work_thr_prgr);
+#endif
+ /* MISC_THR_PRGR must be before MISC */
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_MISC,
+ handle_misc_aux_work);
+
+#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_CHECK_CHILDREN,
+ handle_check_children);
+#endif
+
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_SET_TMO,
+ handle_setup_aux_work_timer);
+
+#if HAVE_ERTS_MSEG
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK,
+ handle_mseg_cache_check);
+#endif
+
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_REAP_PORTS,
+ handle_reap_ports);
+
+ ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
+
+#ifdef ERTS_SMP
+ if (waiting && !aux_work)
+ haw_thr_prgr_current_check_progress(awdp);
+#endif
+
+ return aux_work;
+
+#undef HANDLE_AUX_WORK
+
+}
+
+typedef struct {
+ union {
+ ErlTimer data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErlTimer))];
+ } timer;
+
+ int initialized;
+ erts_atomic32_t refc;
+ erts_atomic32_t type[1];
+} ErtsAuxWorkTmo;
+
+static ErtsAuxWorkTmo *aux_work_tmo;
+
+static void
+aux_work_timeout_early_init(int no_schedulers)
+{
+ int i;
+ UWord p;
+
+ /*
+ * This is done really early. Our own allocators have
+ * not been started yet.
+ */
+
+ p = (UWord) malloc((sizeof(ErtsAuxWorkTmo)
+ + sizeof(erts_atomic32_t)*(no_schedulers+1))
+ + ERTS_CACHE_LINE_SIZE-1);
+ if (p & ERTS_CACHE_LINE_MASK)
+ p = (p & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ ASSERT((p & ERTS_CACHE_LINE_MASK) == 0);
+
+ aux_work_tmo = (ErtsAuxWorkTmo *) p;
+ aux_work_tmo->initialized = 0;
+ erts_atomic32_init_nob(&aux_work_tmo->refc, 0);
+ for (i = 0; i <= no_schedulers; i++)
+ erts_atomic32_init_nob(&aux_work_tmo->type[i], 0);
+}
+
+void
+aux_work_timeout_late_init(void)
+{
+ aux_work_tmo->initialized = 1;
+ if (erts_atomic32_read_nob(&aux_work_tmo->refc)) {
+ aux_work_tmo->timer.data.active = 0;
+ erts_set_timer(&aux_work_tmo->timer.data,
+ aux_work_timeout,
+ NULL,
+ NULL,
+ 1000);
+ }
+}
+
static void
-prepare_for_block(void *vrq)
+aux_work_timeout(void *unused)
{
- erts_smp_runq_unlock((ErtsRunQueue *) vrq);
+ erts_aint32_t refc;
+ int i;
+#ifdef ERTS_SMP
+ i = 0;
+#else
+ i = 1;
+#endif
+
+ for (; i <= erts_no_schedulers; i++) {
+ erts_aint32_t type;
+ type = erts_atomic32_read_acqb(&aux_work_tmo->type[i]);
+ if (type)
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(i-1),
+ type);
+ }
+
+ refc = erts_atomic32_read_nob(&aux_work_tmo->refc);
+ ASSERT(refc >= 1);
+ if (refc != 1
+ || 1 != erts_atomic32_cmpxchg_relb(&aux_work_tmo->refc, 0, 1)) {
+ /* Setup next timeout... */
+ aux_work_tmo->timer.data.active = 0;
+ erts_set_timer(&aux_work_tmo->timer.data,
+ aux_work_timeout,
+ NULL,
+ NULL,
+ 1000);
+ }
}
static void
-resume_after_block(void *vrq)
+setup_aux_work_timer(void)
{
- erts_smp_runq_lock((ErtsRunQueue *) vrq);
+#ifndef ERTS_SMP
+ if (!erts_get_scheduler_data())
+ set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(0),
+ ERTS_SSI_AUX_WORK_SET_TMO);
+ else
+#endif
+ {
+ aux_work_tmo->timer.data.active = 0;
+ erts_set_timer(&aux_work_tmo->timer.data,
+ aux_work_timeout,
+ NULL,
+ NULL,
+ 1000);
+ }
}
+erts_aint32_t
+erts_set_aux_work_timeout(int ix, erts_aint32_t type, int enable)
+{
+ erts_aint32_t old, refc;
+
+#ifndef ERTS_SMP
+ ix = 1;
#endif
+ ERTS_DBG_CHK_AUX_WORK_VAL(type);
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
+// erts_fprintf(stderr, "t(%d, 0x%x, %d)\n", ix, type, enable);
+
+ if (!enable) {
+ old = erts_atomic32_read_band_mb(&aux_work_tmo->type[ix], ~type);
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
+ if (old != 0 && (old & ~type) == 0)
+ erts_atomic32_dec_relb(&aux_work_tmo->refc);
+ return old;
+ }
+
+ old = erts_atomic32_read_bor_mb(&aux_work_tmo->type[ix], type);
+ ERTS_DBG_CHK_AUX_WORK_VAL(erts_atomic32_read_nob(&aux_work_tmo->type[ix]));
+ if (old == 0 && type != 0) {
+ refc = erts_atomic32_inc_read_acqb(&aux_work_tmo->refc);
+ if (refc == 1) {
+ erts_atomic32_inc_acqb(&aux_work_tmo->refc);
+ if (aux_work_tmo->initialized)
+ setup_aux_work_timer();
+ }
+ }
+ return old;
+}
+
+
+
static ERTS_INLINE void
sched_waiting_sys(Uint no, ErtsRunQueue *rq)
{
@@ -800,8 +1757,6 @@ sched_active_sys(Uint no, ErtsRunQueue *rq)
Uint
erts_active_schedulers(void)
{
- /* RRRRRRRRR */
-
Uint as = erts_no_schedulers;
ERTS_ATOMIC_FOREACH_RUNQ(rq, as -= abs(rq->waiting));
@@ -988,6 +1943,10 @@ sched_set_sleeptype(ErtsSchedulerSleepInfo *ssi, erts_aint32_t sleep_type)
if (sleep_type == ERTS_SSI_FLG_TSE_SLEEPING)
erts_tse_reset(ssi->event);
+ else {
+ ASSERT(sleep_type == ERTS_SSI_FLG_POLL_SLEEPING);
+ erts_sys_schedule_interrupt(0);
+ }
while (1) {
oflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
@@ -1006,34 +1965,137 @@ sched_set_sleeptype(ErtsSchedulerSleepInfo *ssi, erts_aint32_t sleep_type)
(((FLGS) & (ERTS_SSI_FLG_WAITING|ERTS_SSI_FLG_SUSPENDED)) \
!= ERTS_SSI_FLG_WAITING)
+
+static void
+thr_prgr_wakeup(void *vssi)
+{
+ erts_sched_poke((ErtsSchedulerSleepInfo *) vssi);
+}
+
+static void
+thr_prgr_prep_wait(void *vssi)
+{
+ ErtsSchedulerSleepInfo *ssi = (ErtsSchedulerSleepInfo *) vssi;
+ erts_smp_atomic32_read_bor_acqb(&ssi->flags,
+ ERTS_SSI_FLG_SLEEPING);
+}
+
+static void
+thr_prgr_wait(void *vssi)
+{
+ ErtsSchedulerSleepInfo *ssi = (ErtsSchedulerSleepInfo *) vssi;
+ erts_aint32_t xflgs = ERTS_SSI_FLG_SLEEPING;
+
+ erts_tse_reset(ssi->event);
+
+ while (1) {
+ erts_aint32_t aflgs, nflgs;
+ nflgs = xflgs | ERTS_SSI_FLG_TSE_SLEEPING;
+ aflgs = erts_smp_atomic32_cmpxchg_acqb(&ssi->flags, nflgs, xflgs);
+ if (aflgs == xflgs) {
+ erts_tse_wait(ssi->event);
+ break;
+ }
+ if ((aflgs & ERTS_SSI_FLG_SLEEPING) == 0)
+ break;
+ xflgs = aflgs;
+ }
+}
+
+static void
+thr_prgr_fin_wait(void *vssi)
+{
+ ErtsSchedulerSleepInfo *ssi = (ErtsSchedulerSleepInfo *) vssi;
+ erts_smp_atomic32_read_band_nob(&ssi->flags,
+ ~(ERTS_SSI_FLG_SLEEPING
+ | ERTS_SSI_FLG_TSE_SLEEPING));
+}
+
+static void init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp);
+
+static void *
+aux_thread(void *unused)
+{
+ ErtsAuxWorkData *awdp = aux_thread_aux_work_data;
+ ErtsSchedulerSleepInfo *ssi = ERTS_SCHED_SLEEP_INFO_IX(-1);
+ erts_aint32_t aux_work;
+ ErtsThrPrgrCallbacks callbacks;
+ int thr_prgr_active = 1;
+
+ ssi->event = erts_tse_fetch();
+
+ callbacks.arg = (void *) ssi;
+ callbacks.wakeup = thr_prgr_wakeup;
+ callbacks.prepare_wait = thr_prgr_prep_wait;
+ callbacks.wait = thr_prgr_wait;
+ callbacks.finalize_wait = thr_prgr_fin_wait;
+
+ erts_thr_progress_register_managed_thread(NULL, &callbacks, 1);
+ init_aux_work_data(awdp, NULL, NULL);
+ awdp->ssi = ssi;
+
+ sched_prep_spin_wait(ssi);
+
+ while (1) {
+ erts_aint32_t flgs;
+
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!thr_prgr_active)
+ erts_thr_progress_active(NULL, thr_prgr_active = 1);
+ aux_work = handle_aux_work(awdp, aux_work, 1);
+ if (aux_work && erts_thr_progress_update(NULL))
+ erts_thr_progress_leader_update(NULL);
+ }
+
+ if (!aux_work) {
+ if (thr_prgr_active)
+ erts_thr_progress_active(NULL, thr_prgr_active = 0);
+ erts_thr_progress_prepare_wait(NULL);
+
+ flgs = sched_spin_wait(ssi, 0);
+
+ if (flgs & ERTS_SSI_FLG_SLEEPING) {
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_TSE_SLEEPING);
+ if (flgs & ERTS_SSI_FLG_SLEEPING) {
+ int res;
+ ASSERT(flgs & ERTS_SSI_FLG_TSE_SLEEPING);
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ do {
+ res = erts_tse_wait(ssi->event);
+ } while (res == EINTR);
+ }
+ }
+ erts_thr_progress_finalize_wait(NULL);
+ }
+
+ flgs = sched_prep_spin_wait(ssi);
+ }
+ return NULL;
+}
+
+#endif /* ERTS_SMP */
+
static void
scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
{
+ int working = 1;
ErtsSchedulerSleepInfo *ssi = esdp->ssi;
int spincount;
+ erts_aint32_t aux_work = 0;
+#ifdef ERTS_SMP
+ int thr_prgr_active = 1;
erts_aint32_t flgs;
-#if defined(ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK) \
- || defined(ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK)
- erts_aint32_t aux_work;
-#endif
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
- erts_smp_spin_lock(&rq->sleepers.lock);
flgs = sched_prep_spin_wait(ssi);
if (flgs & ERTS_SSI_FLG_SUSPENDED) {
/* Go suspend instead... */
- erts_smp_spin_unlock(&rq->sleepers.lock);
return;
}
- ssi->prev = NULL;
- ssi->next = rq->sleepers.list;
- if (rq->sleepers.list)
- rq->sleepers.list->prev = ssi;
- rq->sleepers.list = ssi;
- erts_smp_spin_unlock(&rq->sleepers.lock);
-
/*
* If all schedulers are waiting, one of them *should*
* be waiting in erl_sys_schedule()
@@ -1045,38 +2107,49 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
erts_smp_runq_unlock(rq);
- spincount = ERTS_SCHED_TSE_SLEEP_SPINCOUNT;
+ spincount = sched_busy_wait.tse;
tse_wait:
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
- tse_blockable_aux_work:
- aux_work = blockable_aux_work(esdp, ssi, aux_work);
-#endif
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
+ if (thr_prgr_active != working)
+ sched_wall_time_change(esdp, thr_prgr_active);
while (1) {
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-#ifndef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
-#endif
- nonblockable_aux_work(esdp, ssi, aux_work);
-#endif
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
+ aux_work = handle_aux_work(&esdp->aux_work_data, aux_work, 1);
+ if (aux_work && erts_thr_progress_update(esdp))
+ erts_thr_progress_leader_update(esdp);
+ }
- flgs = sched_spin_wait(ssi, spincount);
- if (flgs & ERTS_SSI_FLG_SLEEPING) {
- ASSERT(flgs & ERTS_SSI_FLG_WAITING);
- flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_TSE_SLEEPING);
+ if (aux_work)
+ flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
+ else {
+ if (thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 0);
+ sched_wall_time_change(esdp, 0);
+ }
+ erts_thr_progress_prepare_wait(esdp);
+
+ flgs = sched_spin_wait(ssi, spincount);
if (flgs & ERTS_SSI_FLG_SLEEPING) {
- int res;
- ASSERT(flgs & ERTS_SSI_FLG_TSE_SLEEPING);
ASSERT(flgs & ERTS_SSI_FLG_WAITING);
- do {
- res = erts_tse_wait(ssi->event);
- } while (res == EINTR);
+ flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_TSE_SLEEPING);
+ if (flgs & ERTS_SSI_FLG_SLEEPING) {
+ int res;
+ ASSERT(flgs & ERTS_SSI_FLG_TSE_SLEEPING);
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ do {
+ res = erts_tse_wait(ssi->event);
+ } while (res == EINTR);
+ }
}
+ erts_thr_progress_finalize_wait(esdp);
}
if (!(flgs & ERTS_SSI_FLG_WAITING)) {
@@ -1085,33 +2158,30 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
}
flgs = sched_prep_cont_spin_wait(ssi);
- spincount = ERTS_SCHED_TSE_SLEEP_SPINCOUNT;
+ spincount = sched_busy_wait.aux_work;
if (!(flgs & ERTS_SSI_FLG_WAITING)) {
ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
break;
}
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
- if (aux_work & ERTS_SSI_BLOCKABLE_AUX_WORK_MASK) {
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
- goto tse_blockable_aux_work;
- }
-#endif
-
}
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
-
if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+ if (!thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
+
erts_smp_runq_lock(rq);
sched_active(esdp->no, rq);
}
- else {
+ else
+#endif
+ {
erts_aint_t dt;
erts_smp_atomic32_set_relb(&function_calls, 0);
@@ -1119,14 +2189,23 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
sched_waiting_sys(esdp->no, rq);
+
erts_smp_runq_unlock(rq);
- spincount = ERTS_SCHED_SYS_SLEEP_SPINCOUNT;
+ ASSERT(working);
+ sched_wall_time_change(esdp, working = 0);
+
+ spincount = sched_busy_wait.sys_schedule;
+ if (spincount == 0)
+ goto sys_aux_work;
while (spincount-- > 0) {
sys_poll_aux_work:
+ if (working)
+ sched_wall_time_change(esdp, working = 0);
+
ASSERT(!erts_port_task_have_outstanding_io_tasks());
erl_sys_schedule(1); /* Might give us something to do */
@@ -1135,18 +2214,29 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
if (dt) erts_bump_timer(dt);
sys_aux_work:
-
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
- aux_work = blockable_aux_work(esdp, ssi, aux_work);
+#ifndef ERTS_SMP
+ erts_sys_schedule_interrupt(0);
#endif
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-#ifndef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
+
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!working)
+ sched_wall_time_change(esdp, working = 1);
+#ifdef ERTS_SMP
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
#endif
- nonblockable_aux_work(esdp, ssi, aux_work);
+ aux_work = handle_aux_work(&esdp->aux_work_data, aux_work, 1);
+#ifdef ERTS_SMP
+ if (aux_work && erts_thr_progress_update(esdp))
+ erts_thr_progress_leader_update(esdp);
#endif
+ }
+#ifndef ERTS_SMP
+ if (rq->len != 0 || rq->misc.start)
+ goto sys_woken;
+#else
flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
if (!(flgs & ERTS_SSI_FLG_WAITING)) {
ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
@@ -1168,10 +2258,12 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
goto tse_wait;
}
}
+#endif
}
erts_smp_runq_lock(rq);
+#ifdef ERTS_SMP
/*
* If we got new I/O tasks we aren't allowed to
* sleep in erl_sys_schedule().
@@ -1183,64 +2275,93 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
* Got to check that we still got I/O tasks; otherwise
* we have to wait in erl_sys_schedule() after all...
*/
- if (prepare_for_sys_schedule())
- goto do_sys_schedule;
-
- /*
- * Not allowed to wait in erl_sys_schedule;
- * do tse wait instead...
- */
- sched_change_waiting_sys_to_waiting(esdp->no, rq);
+ if (!prepare_for_sys_schedule()) {
+ /*
+ * Not allowed to wait in erl_sys_schedule;
+ * do tse wait instead...
+ */
+ sched_change_waiting_sys_to_waiting(esdp->no, rq);
+ erts_smp_runq_unlock(rq);
+ spincount = 0;
+ goto tse_wait;
+ }
+ }
+#endif
+ if (aux_work) {
erts_smp_runq_unlock(rq);
- spincount = 0;
- goto tse_wait;
+ goto sys_poll_aux_work;
}
- else {
- do_sys_schedule:
- erts_sys_schedule_interrupt(0);
- flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_POLL_SLEEPING);
- if (!(flgs & ERTS_SSI_FLG_SLEEPING)) {
- if (!(flgs & ERTS_SSI_FLG_WAITING))
- goto sys_locked_woken;
- erts_smp_runq_unlock(rq);
- flgs = sched_prep_cont_spin_wait(ssi);
- if (!(flgs & ERTS_SSI_FLG_WAITING)) {
- ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
- goto sys_woken;
- }
- ASSERT(!erts_port_task_have_outstanding_io_tasks());
- goto sys_poll_aux_work;
+#ifdef ERTS_SMP
+ flgs = sched_set_sleeptype(ssi, ERTS_SSI_FLG_POLL_SLEEPING);
+ if (!(flgs & ERTS_SSI_FLG_SLEEPING)) {
+ if (!(flgs & ERTS_SSI_FLG_WAITING)) {
+ ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
+ goto sys_locked_woken;
}
+ erts_smp_runq_unlock(rq);
+ flgs = sched_prep_cont_spin_wait(ssi);
+ if (!(flgs & ERTS_SSI_FLG_WAITING)) {
+ ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING));
+ goto sys_woken;
+ }
+ ASSERT(!erts_port_task_have_outstanding_io_tasks());
+ goto sys_poll_aux_work;
+ }
- ASSERT(flgs & ERTS_SSI_FLG_POLL_SLEEPING);
- ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+ ASSERT(flgs & ERTS_SSI_FLG_POLL_SLEEPING);
+ ASSERT(flgs & ERTS_SSI_FLG_WAITING);
+#endif
- erts_smp_runq_unlock(rq);
+ erts_smp_runq_unlock(rq);
- ASSERT(!erts_port_task_have_outstanding_io_tasks());
+ if (working)
+ sched_wall_time_change(esdp, working = 0);
- erl_sys_schedule(0);
+#ifdef ERTS_SMP
+ if (thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 0);
+#endif
- dt = erts_do_time_read_and_reset();
- if (dt) erts_bump_timer(dt);
+ ASSERT(!erts_port_task_have_outstanding_io_tasks());
- flgs = sched_prep_cont_spin_wait(ssi);
- if (flgs & ERTS_SSI_FLG_WAITING)
- goto sys_aux_work;
+ erl_sys_schedule(0);
- sys_woken:
+ dt = erts_do_time_read_and_reset();
+ if (dt) erts_bump_timer(dt);
+
+#ifndef ERTS_SMP
+ if (rq->len == 0 && !rq->misc.start)
+ goto sys_aux_work;
+ sys_woken:
+#else
+ flgs = sched_prep_cont_spin_wait(ssi);
+ if (flgs & ERTS_SSI_FLG_WAITING)
+ goto sys_aux_work;
+
+ sys_woken:
+ if (!thr_prgr_active)
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ erts_smp_runq_lock(rq);
+ sys_locked_woken:
+ if (!thr_prgr_active) {
+ erts_smp_runq_unlock(rq);
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
erts_smp_runq_lock(rq);
- sys_locked_woken:
- clear_sys_scheduling();
- if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
- erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
- sched_active_sys(esdp->no, rq);
}
+ clear_sys_scheduling();
+ if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
+ erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+#endif
+ if (!working)
+ sched_wall_time_change(esdp, working = 1);
+ sched_active_sys(esdp->no, rq);
}
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
}
+#ifdef ERTS_SMP
+
static ERTS_INLINE erts_aint32_t
ssi_flags_set_wake(ErtsSchedulerSleepInfo *ssi)
{
@@ -1258,10 +2379,10 @@ ssi_flags_set_wake(ErtsSchedulerSleepInfo *ssi)
}
static void
-wake_scheduler(ErtsRunQueue *rq, int incq, int one)
+wake_scheduler(ErtsRunQueue *rq, int incq)
{
ErtsSchedulerSleepInfo *ssi;
- ErtsSchedulerSleepList *sl;
+ erts_aint32_t flgs;
/*
* The unlocked run queue is not strictly necessary
@@ -1273,56 +2394,13 @@ wake_scheduler(ErtsRunQueue *rq, int incq, int one)
*/
ERTS_SMP_LC_ASSERT(!erts_smp_lc_runq_is_locked(rq));
- sl = &rq->sleepers;
-
- erts_smp_spin_lock(&sl->lock);
- ssi = sl->list;
- if (!ssi)
- erts_smp_spin_unlock(&sl->lock);
- else if (one) {
- erts_aint32_t flgs;
- if (ssi->prev)
- ssi->prev->next = ssi->next;
- else {
- ASSERT(sl->list == ssi);
- sl->list = ssi->next;
- }
- if (ssi->next)
- ssi->next->prev = ssi->prev;
+ ssi = rq->scheduler->ssi;
- erts_smp_spin_unlock(&sl->lock);
+ flgs = ssi_flags_set_wake(ssi);
+ erts_sched_finish_poke(ssi, flgs);
- flgs = ssi_flags_set_wake(ssi);
- erts_sched_finish_poke(ssi, flgs);
-
- if (incq && !erts_common_run_queue && (flgs & ERTS_SSI_FLG_WAITING))
- non_empty_runq(rq);
- }
- else {
- sl->list = NULL;
- erts_smp_spin_unlock(&sl->lock);
-
- ERTS_THR_MEMORY_BARRIER;
- do {
- ErtsSchedulerSleepInfo *wake_ssi = ssi;
- ssi = ssi->next;
- erts_sched_finish_poke(wake_ssi, ssi_flags_set_wake(wake_ssi));
- } while (ssi);
- }
-}
-
-static void
-wake_all_schedulers(void)
-{
- if (erts_common_run_queue)
- wake_scheduler(erts_common_run_queue, 0, 0);
- else {
- int ix;
- for (ix = 0; ix < erts_no_run_queues; ix++) {
- ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
- wake_scheduler(rq, 0, 1);
- }
- }
+ if (incq && (flgs & ERTS_SSI_FLG_WAITING))
+ non_empty_runq(rq);
}
#define ERTS_NO_USED_RUNQS_SHIFT 16
@@ -1415,7 +2493,7 @@ chk_wake_sched(ErtsRunQueue *crq, int ix, int activate)
erts_smp_xrunq_unlock(crq, wrq);
}
}
- wake_scheduler(wrq, 0, 1);
+ wake_scheduler(wrq, 0);
return 1;
}
return 0;
@@ -1463,7 +2541,7 @@ smp_notify_inc_runq(ErtsRunQueue *runq)
{
#ifdef ERTS_SMP
if (runq)
- wake_scheduler(runq, 1, 1);
+ wake_scheduler(runq, 1);
#endif
}
@@ -1478,19 +2556,12 @@ erts_sched_notify_check_cpu_bind(void)
{
#ifdef ERTS_SMP
int ix;
- if (erts_common_run_queue) {
- for (ix = 0; ix < erts_no_schedulers; ix++)
- erts_smp_atomic32_set_relb(&ERTS_SCHEDULER_IX(ix)->chk_cpu_bind, 1);
- wake_all_schedulers();
- }
- else {
- for (ix = 0; ix < erts_no_run_queues; ix++) {
- ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
- erts_smp_runq_lock(rq);
- rq->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND;
- erts_smp_runq_unlock(rq);
- wake_scheduler(rq, 0, 1);
- };
+ for (ix = 0; ix < erts_no_run_queues; ix++) {
+ ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
+ erts_smp_runq_lock(rq);
+ rq->flags |= ERTS_RUNQ_FLG_CHK_CPU_BIND;
+ erts_smp_runq_unlock(rq);
+ wake_scheduler(rq, 0);
}
#else
erts_sched_check_cpu_bind(erts_get_scheduler_data());
@@ -1759,7 +2830,7 @@ evacuate_run_queue(ErtsRunQueue *evac_rq, ErtsRunQueue *rq)
if (notify_to_rq)
smp_notify_inc_runq(rq);
- wake_scheduler(evac_rq, 0, 1);
+ wake_scheduler(evac_rq, 0);
}
static int
@@ -1777,6 +2848,9 @@ try_steal_task_from_victim(ErtsRunQueue *rq, int *rq_lockedp, ErtsRunQueue *vrq)
ERTS_SMP_LC_CHK_RUNQ_LOCK(rq, *rq_lockedp);
ERTS_SMP_LC_CHK_RUNQ_LOCK(vrq, vrq_locked);
+ if (rq->halt_in_progress)
+ goto try_steal_port;
+
/*
* Check for a runnable process to steal...
*/
@@ -1863,6 +2937,8 @@ try_steal_task_from_victim(ErtsRunQueue *rq, int *rq_lockedp, ErtsRunQueue *vrq)
vrq_locked = 1;
}
+ try_steal_port:
+
ERTS_SMP_LC_CHK_RUNQ_LOCK(rq, *rq_lockedp);
ERTS_SMP_LC_CHK_RUNQ_LOCK(vrq, vrq_locked);
@@ -1917,9 +2993,6 @@ static int
try_steal_task(ErtsRunQueue *rq)
{
int res, rq_locked, vix, active_rqs, blnc_rqs;
-
- if (erts_common_run_queue)
- return 0;
/*
* We are not allowed to steal jobs to this run queue
@@ -1981,7 +3054,8 @@ try_steal_task(ErtsRunQueue *rq)
erts_smp_runq_lock(rq);
if (!res)
- res = !ERTS_EMPTY_RUNQ(rq);
+ res = rq->halt_in_progress ?
+ !ERTS_EMPTY_RUNQ_PORTS(rq) : !ERTS_EMPTY_RUNQ(rq);
return res;
}
@@ -2211,6 +3285,9 @@ check_balance(ErtsRunQueue *c_rq)
mmax_len = run_queue_info[qix].max_len;
}
+ if (!erts_sched_compact_load)
+ goto all_active;
+
if (!forced && half_full_scheds != blnc_no_rqs) {
int min = 1;
if (min < half_full_scheds)
@@ -2546,49 +3623,339 @@ erts_debug_nbalance(void)
#endif
}
+/* Wakeup other schedulers */
+
+typedef enum {
+ ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_HIGH,
+ ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_HIGH,
+ ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM,
+ ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_LOW,
+ ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_LOW
+} ErtsSchedWakeupOtherThreshold;
+
+typedef enum {
+ ERTS_SCHED_WAKEUP_OTHER_TYPE_PROPOSAL,
+ ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY
+} ErtsSchedWakeupOtherType;
+
+/* First proposal */
+
+#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH (200*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_HIGH (50*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_MEDIUM (10*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_LOW (CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW (CONTEXT_REDS/10)
+
+#define ERTS_WAKEUP_OTHER_DEC_SHIFT_VERY_HIGH 3
+#define ERTS_WAKEUP_OTHER_DEC_SHIFT_HIGH 1
+#define ERTS_WAKEUP_OTHER_DEC_SHIFT_MEDIUM 0
+#define ERTS_WAKEUP_OTHER_DEC_SHIFT_LOW -2
+#define ERTS_WAKEUP_OTHER_DEC_SHIFT_VERY_LOW -5
+
+#define ERTS_WAKEUP_OTHER_DEC_SHIFT 2
+#define ERTS_WAKEUP_OTHER_FIXED_INC (CONTEXT_REDS/10)
+
+/* To be legacy */
+
+#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH_LEGACY (200*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_HIGH_LEGACY (50*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_MEDIUM_LEGACY (10*CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_LOW_LEGACY (CONTEXT_REDS)
+#define ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW_LEGACY (CONTEXT_REDS/10)
+
+#define ERTS_WAKEUP_OTHER_DEC_LEGACY 10
+#define ERTS_WAKEUP_OTHER_FIXED_INC_LEGACY (CONTEXT_REDS/10)
+
+#ifdef ERTS_SMP
+
+static struct {
+ ErtsSchedWakeupOtherThreshold threshold;
+ ErtsSchedWakeupOtherType type;
+ int limit;
+ int dec_shift;
+ int dec_mask;
+ void (*check)(ErtsRunQueue *rq);
+} wakeup_other;
+
+static void
+wakeup_other_check(ErtsRunQueue *rq)
+{
+ int wo_reds = rq->wakeup_other_reds;
+ if (wo_reds) {
+ int left_len = rq->len - 1;
+ if (left_len < 1) {
+ int wo_reduce = wo_reds << wakeup_other.dec_shift;
+ wo_reduce &= wakeup_other.dec_mask;
+ rq->wakeup_other -= wo_reduce;
+ if (rq->wakeup_other < 0)
+ rq->wakeup_other = 0;
+ }
+ else {
+ rq->wakeup_other += (left_len*wo_reds
+ + ERTS_WAKEUP_OTHER_FIXED_INC);
+ if (rq->wakeup_other > wakeup_other.limit) {
+ int empty_rqs =
+ erts_smp_atomic32_read_acqb(&no_empty_run_queues);
+ if (empty_rqs != 0)
+ wake_scheduler_on_empty_runq(rq);
+ rq->wakeup_other = 0;
+ }
+ }
+ rq->wakeup_other_reds = 0;
+ }
+}
+
+static void
+wakeup_other_set_limit(void)
+{
+ switch (wakeup_other.threshold) {
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_HIGH:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH;
+ wakeup_other.dec_shift = ERTS_WAKEUP_OTHER_DEC_SHIFT_VERY_HIGH;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_HIGH:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_HIGH;
+ wakeup_other.dec_shift = ERTS_WAKEUP_OTHER_DEC_SHIFT_HIGH;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM;
+ wakeup_other.dec_shift = ERTS_WAKEUP_OTHER_DEC_SHIFT_MEDIUM;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_LOW:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_LOW;
+ wakeup_other.dec_shift = ERTS_WAKEUP_OTHER_DEC_SHIFT_LOW;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_LOW:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW;
+ wakeup_other.dec_shift = ERTS_WAKEUP_OTHER_DEC_SHIFT_VERY_LOW;
+ break;
+ }
+ if (wakeup_other.dec_shift < 0)
+ wakeup_other.dec_mask = (1 << (sizeof(wakeup_other.dec_mask)*8
+ + wakeup_other.dec_shift)) - 1;
+ else {
+ wakeup_other.dec_mask = 0;
+ wakeup_other.dec_mask = ~wakeup_other.dec_mask;
+ }
+}
+
+static void
+wakeup_other_check_legacy(ErtsRunQueue *rq)
+{
+ int wo_reds = rq->wakeup_other_reds;
+ if (wo_reds) {
+ if (rq->len < 2) {
+ rq->wakeup_other -= ERTS_WAKEUP_OTHER_DEC_LEGACY*wo_reds;
+ if (rq->wakeup_other < 0)
+ rq->wakeup_other = 0;
+ }
+ else if (rq->wakeup_other < wakeup_other.limit)
+ rq->wakeup_other += rq->len*wo_reds + ERTS_WAKEUP_OTHER_FIXED_INC_LEGACY;
+ else {
+ if (erts_smp_atomic32_read_acqb(&no_empty_run_queues) != 0) {
+ wake_scheduler_on_empty_runq(rq);
+ rq->wakeup_other = 0;
+ }
+ rq->wakeup_other = 0;
+ }
+ }
+ rq->wakeup_other_reds = 0;
+}
+
+static void
+wakeup_other_set_limit_legacy(void)
+{
+ switch (wakeup_other.threshold) {
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_HIGH:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH_LEGACY;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_HIGH:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_HIGH_LEGACY;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM_LEGACY;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_LOW:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_LOW_LEGACY;
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_LOW:
+ wakeup_other.limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW_LEGACY;
+ break;
+ }
+}
+
+static void
+set_wakeup_other_data(void)
+{
+ switch (wakeup_other.type) {
+ case ERTS_SCHED_WAKEUP_OTHER_TYPE_PROPOSAL:
+ wakeup_other.check = wakeup_other_check;
+ wakeup_other_set_limit();
+ break;
+ case ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY:
+ wakeup_other.check = wakeup_other_check_legacy;
+ wakeup_other_set_limit_legacy();
+ break;
+ }
+}
+
+#endif
+
void
-erts_early_init_scheduling(void)
+erts_early_init_scheduling(int no_schedulers)
{
- wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM;
+ aux_work_timeout_early_init(no_schedulers);
+#ifdef ERTS_SMP
+ wakeup_other.threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM;
+ wakeup_other.type = ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY;
+#endif
+ sched_busy_wait.sys_schedule = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM;
+ sched_busy_wait.tse = (ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM
+ * ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT);
+ sched_busy_wait.aux_work = (ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM
+ * ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_MEDIUM);
}
int
-erts_sched_set_wakeup_limit(char *str)
+erts_sched_set_wakeup_other_thresold(char *str)
{
+ ErtsSchedWakeupOtherThreshold threshold;
if (sys_strcmp(str, "very_high") == 0)
- wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH;
+ threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_HIGH;
else if (sys_strcmp(str, "high") == 0)
- wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_HIGH;
+ threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_HIGH;
else if (sys_strcmp(str, "medium") == 0)
- wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM;
+ threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM;
else if (sys_strcmp(str, "low") == 0)
- wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_LOW;
+ threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_LOW;
else if (sys_strcmp(str, "very_low") == 0)
- wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW;
+ threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_VERY_LOW;
else
return EINVAL;
+#ifdef ERTS_SMP
+ wakeup_other.threshold = threshold;
+ set_wakeup_other_data();
+#endif
return 0;
}
-
-void
-erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
+int
+erts_sched_set_wakeup_other_type(char *str)
+{
+ ErtsSchedWakeupOtherType type;
+ if (sys_strcmp(str, "proposal") == 0)
+ type = ERTS_SCHED_WAKEUP_OTHER_TYPE_PROPOSAL;
+ else if (sys_strcmp(str, "default") == 0)
+ type = ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY;
+ else if (sys_strcmp(str, "legacy") == 0)
+ type = ERTS_SCHED_WAKEUP_OTHER_TYPE_LEGACY;
+ else
+ return EINVAL;
+#ifdef ERTS_SMP
+ wakeup_other.type = type;
+#endif
+ return 0;
+}
+
+int
+erts_sched_set_busy_wait_threshold(char *str)
{
- int ix, n;
+ int sys_sched;
+ int aux_work_fact;
-#ifndef ERTS_SMP
- mrq = 0;
+ if (sys_strcmp(str, "very_long") == 0) {
+ sys_sched = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_VERY_LONG;
+ aux_work_fact = ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_VERY_LONG;
+ }
+ else if (sys_strcmp(str, "long") == 0) {
+ sys_sched = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_LONG;
+ aux_work_fact = ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_LONG;
+ }
+ else if (sys_strcmp(str, "medium") == 0) {
+ sys_sched = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM;
+ aux_work_fact = ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_MEDIUM;
+ }
+ else if (sys_strcmp(str, "short") == 0) {
+ sys_sched = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_SHORT;
+ aux_work_fact = ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_SHORT;
+ }
+ else if (sys_strcmp(str, "very_short") == 0) {
+ sys_sched = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_VERY_SHORT;
+ aux_work_fact = ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_VERY_SHORT;
+ }
+ else if (sys_strcmp(str, "none") == 0) {
+ sys_sched = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_NONE;
+ aux_work_fact = ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_NONE;
+ }
+ else {
+ return EINVAL;
+ }
+
+ sched_busy_wait.sys_schedule = sys_sched;
+ sched_busy_wait.tse = sys_sched*ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT;
+ sched_busy_wait.aux_work = sys_sched*aux_work_fact;
+
+ return 0;
+}
+static void
+init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp)
+{
+ awdp->sched_id = esdp ? (int) esdp->no : 0;
+ awdp->esdp = esdp;
+ awdp->ssi = esdp ? esdp->ssi : NULL;
+#ifdef ERTS_SMP
+ awdp->misc.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
+ awdp->dd.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
+ awdp->dd.completed_callback = NULL;
+ awdp->dd.completed_arg = NULL;
+#endif
+#ifdef ERTS_USE_ASYNC_READY_Q
+#ifdef ERTS_SMP
+ awdp->async_ready.need_thr_prgr = 0;
+ awdp->async_ready.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
+#endif
+ awdp->async_ready.queue = NULL;
+#endif
+#ifdef ERTS_SMP
+ if (!dawwp) {
+ awdp->delayed_wakeup.job = NULL;
+ awdp->delayed_wakeup.sched2jix = NULL;
+ awdp->delayed_wakeup.jix = -1;
+ }
+ else {
+ int i;
+ awdp->delayed_wakeup.job = (ErtsDelayedAuxWorkWakeupJob *) dawwp;
+ dawwp += sizeof(ErtsDelayedAuxWorkWakeupJob)*(erts_no_schedulers+1);
+ awdp->delayed_wakeup.sched2jix = (int *) dawwp;
+ awdp->delayed_wakeup.jix = -1;
+ for (i = 0; i <= erts_no_schedulers; i++)
+ awdp->delayed_wakeup.sched2jix[i] = -1;
+ }
+#endif
+}
+
+void
+erts_init_scheduling(int no_schedulers, int no_schedulers_online)
+{
+ int ix, n, no_ssi;
+ char *daww_ptr;
+#ifdef ERTS_SMP
+ size_t daww_sz;
#endif
init_misc_op_list_alloc();
+#ifdef ERTS_SMP
+ set_wakeup_other_data();
+#endif
+
ASSERT(no_schedulers_online <= no_schedulers);
ASSERT(no_schedulers_online >= 1);
ASSERT(no_schedulers >= 1);
/* Create and initialize run queues */
- n = (int) (mrq ? no_schedulers : 1);
+ n = no_schedulers;
erts_aligned_run_queues =
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_RUNQS,
@@ -2613,14 +3980,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
erts_smp_mtx_init_x(&rq->mtx, "run_queue", make_small(ix + 1));
erts_smp_cnd_init(&rq->cnd);
-#ifdef ERTS_SMP
- erts_smp_spinlock_init(&rq->sleepers.lock, "run_queue_sleep_list");
- rq->sleepers.list = NULL;
-#endif
-
rq->waiting = 0;
rq->woken = 0;
- rq->flags = !mrq ? ERTS_RUNQ_FLG_SHARED_RUNQ : 0;
+ rq->flags = 0;
rq->check_balance_reds = ERTS_RUNQ_CALL_CHECK_BALANCE_REDS;
rq->full_reds_history_sum = 0;
for (rix = 0; rix < ERTS_FULL_REDS_HISTORY_SIZE; rix++) {
@@ -2632,6 +3994,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
rq->len = 0;
rq->wakeup_other = 0;
rq->wakeup_other_reds = 0;
+ rq->halt_in_progress = 0;
rq->procs.len = 0;
rq->procs.pending_exiters = NULL;
@@ -2666,8 +4029,6 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
rq->ports.end = NULL;
}
- erts_common_run_queue = !mrq ? ERTS_RUNQ_IX(0) : NULL;
-
#ifdef ERTS_SMP
if (erts_no_run_queues != 1) {
@@ -2684,27 +4045,44 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
n = (int) no_schedulers;
erts_no_schedulers = n;
-#ifdef ERTS_SMP
/* Create and initialize scheduler sleep info */
-
+#ifdef ERTS_SMP
+ no_ssi = n+1;
+#else
+ no_ssi = 1;
+#endif
aligned_sched_sleep_info =
- erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_SLP_INFO,
- n * sizeof(ErtsAlignedSchedulerSleepInfo));
-
- for (ix = 0; ix < n; ix++) {
- ErtsSchedulerSleepInfo *ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
+ erts_alloc_permanent_cache_aligned(
+ ERTS_ALC_T_SCHDLR_SLP_INFO,
+ no_ssi*sizeof(ErtsAlignedSchedulerSleepInfo));
+ for (ix = 0; ix < no_ssi; ix++) {
+ ErtsSchedulerSleepInfo *ssi = &aligned_sched_sleep_info[ix].ssi;
+#ifdef ERTS_SMP
#if 0 /* no need to initialize these... */
ssi->next = NULL;
ssi->prev = NULL;
#endif
erts_smp_atomic32_init_nob(&ssi->flags, 0);
ssi->event = NULL; /* initialized in sched_thread_func */
- erts_smp_atomic32_init_nob(&ssi->aux_work, 0);
+#endif
+ erts_atomic32_init_nob(&ssi->aux_work, 0);
}
+
+#ifdef ERTS_SMP
+ aligned_sched_sleep_info++;
#endif
/* Create and initialize scheduler specific data */
+#ifdef ERTS_SMP
+ daww_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE((sizeof(ErtsDelayedAuxWorkWakeupJob)
+ + sizeof(int))*(n+1));
+ daww_ptr = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_DATA,
+ daww_sz*n);
+#else
+ daww_ptr = NULL;
+#endif
+
erts_aligned_scheduler_data =
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_DATA,
n*sizeof(ErtsAlignedSchedulerData));
@@ -2714,7 +4092,6 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
#ifdef ERTS_SMP
erts_bits_init_state(&esdp->erl_bits_state);
esdp->match_pseudo_process = NULL;
- esdp->ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
esdp->free_process = NULL;
#endif
esdp->x_reg_array =
@@ -2728,6 +4105,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
esdp->num_tmp_heap_used = 0;
#endif
esdp->no = (Uint) ix+1;
+ esdp->ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
esdp->current_process = NULL;
esdp->current_port = NULL;
@@ -2736,21 +4114,30 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
erts_init_atom_cache_map(&esdp->atom_cache_map);
- if (erts_common_run_queue) {
- esdp->run_queue = erts_common_run_queue;
- esdp->run_queue->scheduler = NULL;
- }
- else {
- esdp->run_queue = ERTS_RUNQ_IX(ix);
- esdp->run_queue->scheduler = esdp;
- }
+ esdp->run_queue = ERTS_RUNQ_IX(ix);
+ esdp->run_queue->scheduler = esdp;
+ init_aux_work_data(&esdp->aux_work_data, esdp, daww_ptr);
#ifdef ERTS_SMP
- erts_smp_atomic32_init_nob(&esdp->chk_cpu_bind, 0);
+ daww_ptr += daww_sz;
#endif
+ init_sched_wall_time(&esdp->sched_wall_time);
}
+ init_misc_aux_work();
+#if !HALFWORD_HEAP
+ init_swtreq_alloc();
+#endif
+
+
#ifdef ERTS_SMP
+
+ erts_atomic32_init_nob(&completed_dealloc_count, 0); /* debug only */
+
+ aux_thread_aux_work_data =
+ erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_DATA,
+ sizeof(ErtsAuxWorkData));
+
erts_smp_mtx_init(&schdlr_sspnd.mtx, "schdlr_sspnd");
erts_smp_cnd_init(&schdlr_sspnd.cnd);
@@ -2760,8 +4147,7 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
schdlr_sspnd.msb.ongoing = 0;
erts_smp_atomic32_init_nob(&schdlr_sspnd.active, no_schedulers);
schdlr_sspnd.msb.procs = NULL;
- init_no_runqs(no_schedulers,
- erts_common_run_queue ? 1 : no_schedulers_online);
+ init_no_runqs(no_schedulers, no_schedulers_online);
balance_info.last_active_runqs = no_schedulers;
erts_smp_mtx_init(&balance_info.update_mtx, "migration_info_update");
balance_info.forced_check_balance = 0;
@@ -2774,16 +4160,9 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
balance_info.n = 0;
if (no_schedulers_online < no_schedulers) {
- if (erts_common_run_queue) {
- for (ix = no_schedulers_online; ix < no_schedulers; ix++)
- erts_smp_atomic32_read_bor_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
- ERTS_SSI_FLG_SUSPENDED);
- }
- else {
- for (ix = no_schedulers_online; ix < erts_no_run_queues; ix++)
- evacuate_run_queue(ERTS_RUNQ_IX(ix),
- ERTS_RUNQ_IX(ix % no_schedulers_online));
- }
+ for (ix = no_schedulers_online; ix < erts_no_run_queues; ix++)
+ evacuate_run_queue(ERTS_RUNQ_IX(ix),
+ ERTS_RUNQ_IX(ix % no_schedulers_online));
}
schdlr_sspnd.wait_curr_online = no_schedulers_online;
@@ -2812,6 +4191,8 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
/* init port tasks */
erts_port_task_init();
+ aux_work_timeout_late_init();
+
#ifndef ERTS_SMP
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
erts_scheduler_data->verify_unused_temp_alloc
@@ -2820,14 +4201,15 @@ erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online)
ERTS_VERIFY_UNUSED_TEMP_ALLOC(NULL);
#endif
#endif
+
+ erts_smp_atomic32_init_relb(&erts_halt_progress, -1);
+ erts_halt_code = 0;
}
ErtsRunQueue *
erts_schedid2runq(Uint id)
{
int ix;
- if (erts_common_run_queue)
- return erts_common_run_queue;
ix = (int) id - 1;
ASSERT(0 <= ix && ix < erts_no_run_queues);
return ERTS_RUNQ_IX(ix);
@@ -2946,18 +4328,6 @@ erts_get_max_no_executing_schedulers(void)
#ifdef ERTS_SMP
static void
-susp_sched_prep_block(void *unused)
-{
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-}
-
-static void
-susp_sched_resume_block(void *unused)
-{
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
-}
-
-static void
scheduler_ix_resume_wake(Uint ix)
{
ErtsSchedulerSleepInfo *ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
@@ -3061,10 +4431,8 @@ suspend_scheduler(ErtsSchedulerData *esdp)
long active_schedulers;
int curr_online = 1;
int wake = 0;
-#if defined(ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK) \
- || defined(ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK)
erts_aint32_t aux_work;
-#endif
+ int thr_prgr_active = 1;
/*
* Schedulers may be suspended in two different ways:
@@ -3086,6 +4454,8 @@ suspend_scheduler(ErtsSchedulerData *esdp)
if (erts_system_profile_flags.scheduler)
profile_scheduler(make_small(esdp->no), am_inactive);
+ sched_wall_time_change(esdp, 0);
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
flgs = sched_prep_spin_suspended(ssi, ERTS_SSI_FLG_SUSPENDED);
@@ -3132,43 +4502,53 @@ suspend_scheduler(ErtsSchedulerData *esdp)
wake = 0;
}
- flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
- if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
- break;
+ if (curr_online && !ongoing_multi_scheduling_block()) {
+ flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
+ if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
+ break;
+ }
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
- blockable_aux_work:
- blockable_aux_work(esdp, ssi, aux_work);
-#endif
-
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
while (1) {
erts_aint32_t flgs;
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
-#ifndef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read(&ssi->aux_work);
-#endif
- nonblockable_aux_work(esdp, ssi, aux_work);
-#endif
- flgs = sched_spin_suspended(ssi,
- ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT);
- if (flgs == (ERTS_SSI_FLG_SLEEPING
- | ERTS_SSI_FLG_WAITING
- | ERTS_SSI_FLG_SUSPENDED)) {
- flgs = sched_set_suspended_sleeptype(ssi);
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+ if (aux_work) {
+ if (!thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
+ aux_work = handle_aux_work(&esdp->aux_work_data,
+ aux_work,
+ 1);
+ if (aux_work && erts_thr_progress_update(esdp))
+ erts_thr_progress_leader_update(esdp);
+ }
+
+ if (!aux_work) {
+ if (thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 0);
+ sched_wall_time_change(esdp, 0);
+ }
+ erts_thr_progress_prepare_wait(esdp);
+ flgs = sched_spin_suspended(ssi,
+ ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT);
if (flgs == (ERTS_SSI_FLG_SLEEPING
- | ERTS_SSI_FLG_TSE_SLEEPING
| ERTS_SSI_FLG_WAITING
| ERTS_SSI_FLG_SUSPENDED)) {
- int res;
- do {
- res = erts_tse_wait(ssi->event);
- } while (res == EINTR);
+ flgs = sched_set_suspended_sleeptype(ssi);
+ if (flgs == (ERTS_SSI_FLG_SLEEPING
+ | ERTS_SSI_FLG_TSE_SLEEPING
+ | ERTS_SSI_FLG_WAITING
+ | ERTS_SSI_FLG_SUSPENDED)) {
+ int res;
+
+ do {
+ res = erts_tse_wait(ssi->event);
+ } while (res == EINTR);
+ }
}
+ erts_thr_progress_finalize_wait(esdp);
}
flgs = sched_prep_spin_suspended(ssi, (ERTS_SSI_FLG_WAITING
@@ -3178,20 +4558,8 @@ suspend_scheduler(ErtsSchedulerData *esdp)
changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if (changing & ~ERTS_SCHDLR_SSPND_CHNG_WAITER)
break;
-
-
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
- if (aux_work & ERTS_SSI_BLOCKABLE_AUX_WORK_MASK) {
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
- goto blockable_aux_work;
- }
-#endif
-
}
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
-
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
}
@@ -3216,6 +4584,11 @@ suspend_scheduler(ErtsSchedulerData *esdp)
if (erts_system_profile_flags.scheduler)
profile_scheduler(make_small(esdp->no), am_active);
+ if (!thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
+
erts_smp_runq_lock(esdp->run_queue);
non_empty_runq(esdp->run_queue);
@@ -3298,12 +4671,16 @@ erts_set_schedulers_online(Process *p,
Sint new_no,
Sint *old_no)
{
- int ix, res, no, have_unlocked_plocks;
+ ErtsSchedulerData *esdp;
+ int ix, res, no, have_unlocked_plocks, end_wait;
erts_aint32_t changing;
if (new_no < 1 || erts_no_schedulers < new_no)
return ERTS_SCHDLR_SSPND_EINVAL;
+ esdp = ERTS_PROC_GET_SCHDATA(p);
+ end_wait = 0;
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
have_unlocked_plocks = 0;
@@ -3329,10 +4706,6 @@ erts_set_schedulers_online(Process *p,
for (ix = online; ix < no; ix++)
erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
}
- else if (erts_common_run_queue) {
- for (ix = online; ix < no; ix++)
- scheduler_ix_resume_wake(ix);
- }
else {
if (plocks) {
have_unlocked_plocks = 1;
@@ -3380,15 +4753,6 @@ erts_set_schedulers_online(Process *p,
for (ix = no; ix < online; ix++)
erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
}
- else if (erts_common_run_queue) {
- for (ix = no; ix < online; ix++) {
- ErtsSchedulerSleepInfo *ssi;
- ssi = ERTS_SCHED_SLEEP_INFO_IX(ix);
- erts_smp_atomic32_read_bor_nob(&ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
- }
- wake_all_schedulers();
- }
else {
if (plocks) {
have_unlocked_plocks = 1;
@@ -3415,21 +4779,26 @@ erts_set_schedulers_online(Process *p,
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
for (ix = no; ix < online; ix++) {
ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
- wake_scheduler(rq, 0, 1);
+ wake_scheduler(rq, 0);
}
}
}
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
+ if (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online) {
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ if (plocks && !have_unlocked_plocks) {
+ have_unlocked_plocks = 1;
+ erts_smp_proc_unlock(p, plocks);
+ }
+ erts_thr_progress_active(esdp, 0);
+ erts_thr_progress_prepare_wait(esdp);
+ end_wait = 1;
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ }
+
while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
+
ASSERT(res != ERTS_SCHDLR_SSPND_DONE
? (ERTS_SCHDLR_SSPND_CHNG_WAITER
& erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
@@ -3437,10 +4806,15 @@ erts_set_schedulers_online(Process *p,
== erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)));
erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+
}
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ if (end_wait) {
+ erts_thr_progress_finalize_wait(esdp);
+ erts_thr_progress_active(esdp, 1);
+ }
if (have_unlocked_plocks)
erts_smp_proc_lock(p, plocks);
@@ -3498,44 +4872,58 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
res = ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED;
schdlr_sspnd.msb.wait_active = 2;
}
- if (erts_common_run_queue) {
- for (ix = 1; ix < online; ix++)
- erts_smp_atomic32_read_bor_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
- ERTS_SSI_FLG_SUSPENDED);
- wake_all_schedulers();
+
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ erts_smp_mtx_lock(&balance_info.update_mtx);
+ set_no_used_runqs(1);
+ for (ix = 0; ix < online; ix++) {
+ ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
+ erts_smp_runq_lock(rq);
+ ASSERT(!(rq->flags & ERTS_RUNQ_FLG_SUSPENDED));
+ ERTS_RUNQ_RESET_MIGRATION_PATHS(rq, 0x7);
+ erts_smp_runq_unlock(rq);
}
- else {
+ /*
+ * Evacuate all activities in all other run queues
+ * into the first run queue. Note order is important,
+ * online run queues has to be evacuated last.
+ */
+ for (ix = erts_no_run_queues-1; ix >= 1; ix--)
+ evacuate_run_queue(ERTS_RUNQ_IX(ix), ERTS_RUNQ_IX(0));
+ erts_smp_mtx_unlock(&balance_info.update_mtx);
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+
+ if (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
+ != schdlr_sspnd.msb.wait_active) {
+ ErtsSchedulerData *esdp;
+
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
- erts_smp_mtx_lock(&balance_info.update_mtx);
- set_no_used_runqs(1);
- for (ix = 0; ix < online; ix++) {
- ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
- erts_smp_runq_lock(rq);
- ASSERT(!(rq->flags & ERTS_RUNQ_FLG_SUSPENDED));
- ERTS_RUNQ_RESET_MIGRATION_PATHS(rq, 0x7);
- erts_smp_runq_unlock(rq);
+
+ if (plocks && !have_unlocked_plocks) {
+ have_unlocked_plocks = 1;
+ erts_smp_proc_unlock(p, plocks);
}
- /*
- * Evacuate all activities in all other run queues
- * into the first run queue. Note order is important,
- * online run queues has to be evacuated last.
- */
- for (ix = erts_no_run_queues-1; ix >= 1; ix--)
- evacuate_run_queue(ERTS_RUNQ_IX(ix), ERTS_RUNQ_IX(0));
- erts_smp_mtx_unlock(&balance_info.update_mtx);
+
+ esdp = ERTS_PROC_GET_SCHDATA(p);
+
+ erts_thr_progress_active(esdp, 0);
+ erts_thr_progress_prepare_wait(esdp);
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+
+ while (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
+ != schdlr_sspnd.msb.wait_active)
+ erts_smp_cnd_wait(&schdlr_sspnd.cnd,
+ &schdlr_sspnd.mtx);
+
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
+ erts_thr_progress_active(esdp, 1);
+ erts_thr_progress_finalize_wait(esdp);
+
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+
}
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
- while (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
- != schdlr_sspnd.msb.wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
ASSERT(res != ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED
? (ERTS_SCHDLR_SSPND_CHNG_WAITER
& erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
@@ -3615,12 +5003,6 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_MSB);
}
- else if (erts_common_run_queue) {
- for (ix = 1; ix < schdlr_sspnd.online; ix++)
- erts_smp_atomic32_read_band_nob(&ERTS_SCHED_SLEEP_INFO_IX(ix)->flags,
- ~ERTS_SSI_FLG_SUSPENDED);
- wake_all_schedulers();
- }
else {
int online = schdlr_sspnd.online;
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
@@ -3723,8 +5105,19 @@ erts_multi_scheduling_blockers(Process *p)
static void *
sched_thread_func(void *vesdp)
{
+ ErtsThrPrgrCallbacks callbacks;
+ ErtsSchedulerData *esdp = vesdp;
+ Uint no = esdp->no;
#ifdef ERTS_SMP
- Uint no = ((ErtsSchedulerData *) vesdp)->no;
+ ERTS_SCHED_SLEEP_INFO_IX(no - 1)->event = erts_tse_fetch();
+ callbacks.arg = (void *) esdp->ssi;
+ callbacks.wakeup = thr_prgr_wakeup;
+ callbacks.prepare_wait = thr_prgr_prep_wait;
+ callbacks.wait = thr_prgr_wait;
+ callbacks.finalize_wait = thr_prgr_fin_wait;
+
+ erts_thr_progress_register_managed_thread(esdp, &callbacks, 0);
+ erts_alloc_register_scheduler(vesdp);
#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
{
@@ -3733,22 +5126,30 @@ sched_thread_func(void *vesdp)
erts_lc_set_thread_name(&buf[0]);
}
#endif
- erts_alloc_reg_scheduler_id(no);
erts_tsd_set(sched_data_key, vesdp);
#ifdef ERTS_SMP
+#if HAVE_ERTS_MSEG
+ erts_mseg_late_init();
+#endif
+#if ERTS_USE_ASYNC_READY_Q
+ esdp->aux_work_data.async_ready.queue = erts_get_async_ready_queue(no);
+#endif
- erts_sched_init_check_cpu_bind((ErtsSchedulerData *) vesdp);
+ erts_sched_init_check_cpu_bind(esdp);
erts_proc_lock_prepare_proc_lock_waiter();
- ERTS_SCHED_SLEEP_INFO_IX(no - 1)->event = erts_tse_fetch();
-
-
#endif
- erts_register_blockable_thread();
+
#ifdef HIPE
hipe_thread_signal_init();
#endif
erts_thread_init_float();
+
+ if (no == 1) {
+ erts_thr_progress_active(esdp, 0);
+ erts_thr_progress_prepare_wait(esdp);
+ }
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)
@@ -3757,41 +5158,39 @@ sched_thread_func(void *vesdp)
if (--schdlr_sspnd.curr_online == schdlr_sspnd.wait_curr_online) {
erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- if (((ErtsSchedulerData *) vesdp)->no != 1)
+ if (no != 1)
erts_smp_cnd_signal(&schdlr_sspnd.cnd);
}
- if (((ErtsSchedulerData *) vesdp)->no == 1) {
- if (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online) {
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
- while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT,
- susp_sched_prep_block,
- susp_sched_resume_block,
- NULL);
- }
+ if (no == 1) {
+ while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
+ erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ if (no == 1) {
+ erts_thr_progress_finalize_wait(esdp);
+ erts_thr_progress_active(esdp, 1);
+ }
+
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
- ((ErtsSchedulerData *) vesdp)->verify_unused_temp_alloc
+ esdp->verify_unused_temp_alloc
= erts_alloc_get_verify_unused_temp_alloc(
- &((ErtsSchedulerData *) vesdp)->verify_unused_temp_alloc_data);
+ &esdp->verify_unused_temp_alloc_data);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(NULL);
#endif
process_main();
/* No schedulers should *ever* terminate */
- erl_exit(ERTS_ABORT_EXIT, "Scheduler thread number %beu terminated\n",
- ((ErtsSchedulerData *) vesdp)->no);
+ erl_exit(ERTS_ABORT_EXIT,
+ "Scheduler thread number %beu terminated\n",
+ no);
return NULL;
}
+static ethr_tid aux_tid;
+
void
erts_start_schedulers(void)
{
@@ -3811,8 +5210,6 @@ erts_start_schedulers(void)
res = ENOTSUP;
}
- erts_block_system(0);
-
while (actual < wanted) {
ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(actual);
actual++;
@@ -3825,7 +5222,12 @@ erts_start_schedulers(void)
}
erts_no_schedulers = actual;
- erts_release_system();
+
+ ERTS_THR_MEMORY_BARRIER;
+
+ res = ethr_thr_create(&aux_tid, aux_thread, NULL, &opts);
+ if (res != 0)
+ erl_exit(1, "Failed to create aux thread\n");
if (actual < 1)
erl_exit(1,
@@ -4279,7 +5681,7 @@ suspend_process_2(BIF_ALIST_2)
/* This is really a piece of cake without SMP support... */
if (!smon->active) {
- suspend_process(erts_common_run_queue, suspendee);
+ suspend_process(ERTS_RUNQ_IX(0), suspendee);
smon->active++;
res = am_true;
}
@@ -4849,8 +6251,6 @@ erts_proc_migrate(Process *p, ErtsProcLocks *plcks,
|| from_locked);
ERTS_SMP_LC_CHK_RUNQ_LOCK(from_rq, *from_locked);
ERTS_SMP_LC_CHK_RUNQ_LOCK(to_rq, *to_locked);
-
- ASSERT(!erts_common_run_queue);
/*
* If we have the lock on the run queue to migrate to,
@@ -5001,25 +6401,17 @@ erts_process_status(Process *c_p, ErtsProcLocks c_p_locks,
int i;
ErtsSchedulerData *esdp;
- if (erts_common_run_queue)
- erts_smp_runq_lock(erts_common_run_queue);
-
for (i = 0; i < erts_no_schedulers; i++) {
esdp = ERTS_SCHEDULER_IX(i);
- if (!erts_common_run_queue)
- erts_smp_runq_lock(esdp->run_queue);
+ erts_smp_runq_lock(esdp->run_queue);
if (esdp->free_process && esdp->free_process->id == rpid) {
res = am_free;
- if (!erts_common_run_queue)
- erts_smp_runq_unlock(esdp->run_queue);
+ erts_smp_runq_unlock(esdp->run_queue);
break;
}
- if (!erts_common_run_queue)
- erts_smp_runq_unlock(esdp->run_queue);
+ erts_smp_runq_unlock(esdp->run_queue);
}
- if (erts_common_run_queue)
- erts_smp_runq_unlock(erts_common_run_queue);
#endif
}
@@ -5177,6 +6569,15 @@ Process *schedule(Process *p, int calls)
int actual_reds;
int reds;
+#ifdef USE_VM_PROBES
+ if (p != NULL && DTRACE_ENABLED(process_unscheduled)) {
+ DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, process_buf);
+ DTRACE1(process_unscheduled, process_buf);
+ }
+#endif
+
if (ERTS_USE_MODIFIED_TIMING()) {
context_reds = ERTS_MODIFIED_TIMING_CONTEXT_REDS;
input_reductions = ERTS_MODIFIED_TIMING_INPUT_REDS;
@@ -5186,7 +6587,7 @@ Process *schedule(Process *p, int calls)
input_reductions = INPUT_REDUCTIONS;
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
/*
* Clean up after the process being scheduled out.
@@ -5324,17 +6725,16 @@ Process *schedule(Process *p, int calls)
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
+
check_activities_to_run: {
#ifdef ERTS_SMP
- if (!(rq->flags & ERTS_RUNQ_FLG_SHARED_RUNQ)
- && rq->check_balance_reds <= 0) {
+ if (rq->check_balance_reds <= 0)
check_balance(rq);
- }
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
if (rq->flags & ERTS_RUNQ_FLGS_IMMIGRATE_QMASK)
@@ -5342,58 +6742,51 @@ Process *schedule(Process *p, int calls)
continue_check_activities_to_run:
- if (rq->flags & (ERTS_RUNQ_FLG_SHARED_RUNQ
- | ERTS_RUNQ_FLG_CHK_CPU_BIND
+ if (rq->flags & (ERTS_RUNQ_FLG_CHK_CPU_BIND
| ERTS_RUNQ_FLG_SUSPENDED)) {
- if ((rq->flags & ERTS_RUNQ_FLG_SUSPENDED)
- || (erts_smp_atomic32_read_acqb(&esdp->ssi->flags)
- & ERTS_SSI_FLG_SUSPENDED)) {
+ if (rq->flags & ERTS_RUNQ_FLG_SUSPENDED) {
ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags)
& ERTS_SSI_FLG_SUSPENDED);
suspend_scheduler(esdp);
}
- if ((rq->flags & ERTS_RUNQ_FLG_CHK_CPU_BIND)
- || erts_smp_atomic32_read_acqb(&esdp->chk_cpu_bind)) {
+ if (rq->flags & ERTS_RUNQ_FLG_CHK_CPU_BIND)
erts_sched_check_cpu_bind(esdp);
- }
}
-#if defined(ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK) \
- || defined(ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK)
{
- ErtsSchedulerSleepInfo *ssi = esdp->ssi;
- erts_aint32_t aux_work = erts_smp_atomic32_read_nob(&ssi->aux_work);
- if (aux_work) {
+ erts_aint32_t aux_work;
+ int leader_update = erts_thr_progress_update(esdp);
+ aux_work = erts_atomic32_read_acqb(&esdp->ssi->aux_work);
+ if (aux_work | leader_update) {
erts_smp_runq_unlock(rq);
-#ifdef ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
- aux_work = blockable_aux_work(esdp, ssi, aux_work);
-#endif
-#ifdef ERTS_SCHED_NEED_NONBLOCKABLE_AUX_WORK
- nonblockable_aux_work(esdp, ssi, aux_work);
-#endif
+ if (leader_update)
+ erts_thr_progress_leader_update(esdp);
+ if (aux_work)
+ handle_aux_work(&esdp->aux_work_data, aux_work, 0);
erts_smp_runq_lock(rq);
}
}
-#endif
- erts_smp_chk_system_block(prepare_for_block,
- resume_after_block,
- (void *) rq);
-
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
-#endif
+#else /* ERTS_SMP */
+ {
+ erts_aint32_t aux_work;
+ aux_work = erts_atomic32_read_acqb(&esdp->ssi->aux_work);
+ if (aux_work)
+ handle_aux_work(&esdp->aux_work_data, aux_work, 0);
+ }
+#endif /* ERTS_SMP */
ASSERT(rq->len == rq->procs.len + rq->ports.info.len);
-#ifndef ERTS_SMP
+ if ((rq->len == 0 && !rq->misc.start)
+ || (rq->halt_in_progress
+ && rq->ports.info.len == 0 && !rq->misc.start)) {
- if (rq->len == 0 && !rq->misc.start)
- goto do_sys_schedule;
+#ifdef ERTS_SMP
-#else /* ERTS_SMP */
- if (rq->len == 0 && !rq->misc.start) {
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
rq->wakeup_other = 0;
@@ -5401,16 +6794,11 @@ Process *schedule(Process *p, int calls)
empty_runq(rq);
- if (rq->flags & (ERTS_RUNQ_FLG_SHARED_RUNQ
- | ERTS_RUNQ_FLG_SUSPENDED)) {
- if ((rq->flags & ERTS_RUNQ_FLG_SUSPENDED)
- || (erts_smp_atomic32_read_acqb(&esdp->ssi->flags)
- & ERTS_SSI_FLG_SUSPENDED)) {
- ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags)
- & ERTS_SSI_FLG_SUSPENDED);
- non_empty_runq(rq);
- goto continue_check_activities_to_run;
- }
+ if (rq->flags & ERTS_RUNQ_FLG_SUSPENDED) {
+ ASSERT(erts_smp_atomic32_read_nob(&esdp->ssi->flags)
+ & ERTS_SSI_FLG_SUSPENDED);
+ non_empty_runq(rq);
+ goto continue_check_activities_to_run;
}
else if (!(rq->flags & ERTS_RUNQ_FLG_INACTIVE)) {
/*
@@ -5424,26 +6812,17 @@ Process *schedule(Process *p, int calls)
}
}
+#endif
+
scheduler_wait(&fcalls, esdp, rq);
+#ifdef ERTS_SMP
non_empty_runq(rq);
+#endif
goto check_activities_to_run;
}
- else
-#endif /* ERTS_SMP */
- if (fcalls > input_reductions && prepare_for_sys_schedule()) {
- int runnable;
-
-#ifdef ERTS_SMP
- runnable = 1;
-#else
- do_sys_schedule:
- runnable = rq->len != 0;
- if (!runnable)
- sched_waiting_sys(esdp->no, rq);
-#endif
-
+ else if (fcalls > input_reductions && prepare_for_sys_schedule()) {
/*
* Schedule system-level activities.
*/
@@ -5453,11 +6832,11 @@ Process *schedule(Process *p, int calls)
ASSERT(!erts_port_task_have_outstanding_io_tasks());
-#ifdef ERTS_SMP
- /* erts_sys_schedule_interrupt(0); */
+#if 0 /* Not needed since we wont wait in sys schedule */
+ erts_sys_schedule_interrupt(0);
#endif
erts_smp_runq_unlock(rq);
- erl_sys_schedule(runnable);
+ erl_sys_schedule(1);
dt = erts_do_time_read_and_reset();
if (dt) erts_bump_timer(dt);
#ifdef ERTS_SMP
@@ -5465,8 +6844,6 @@ Process *schedule(Process *p, int calls)
clear_sys_scheduling();
goto continue_check_activities_to_run;
#else
- if (!runnable)
- sched_active_sys(esdp->no, rq);
goto check_activities_to_run;
#endif
}
@@ -5475,30 +6852,7 @@ Process *schedule(Process *p, int calls)
exec_misc_ops(rq);
#ifdef ERTS_SMP
- {
- int wo_reds = rq->wakeup_other_reds;
- if (wo_reds) {
- if (rq->len < 2) {
- rq->wakeup_other -= ERTS_WAKEUP_OTHER_DEC*wo_reds;
- if (rq->wakeup_other < 0)
- rq->wakeup_other = 0;
- }
- else if (rq->wakeup_other < wakeup_other_limit)
- rq->wakeup_other += rq->len*wo_reds + ERTS_WAKEUP_OTHER_FIXED_INC;
- else {
- if (erts_common_run_queue) {
- if (erts_common_run_queue->waiting)
- wake_scheduler(erts_common_run_queue, 0, 1);
- }
- else if (erts_smp_atomic32_read_acqb(&no_empty_run_queues) != 0) {
- wake_scheduler_on_empty_runq(rq);
- rq->wakeup_other = 0;
- }
- rq->wakeup_other = 0;
- }
- }
- rq->wakeup_other_reds = 0;
- }
+ wakeup_other.check(rq);
#endif
/*
@@ -5508,7 +6862,8 @@ Process *schedule(Process *p, int calls)
if (rq->ports.info.len) {
int have_outstanding_io;
have_outstanding_io = erts_port_task_execute(rq, &esdp->current_port);
- if (have_outstanding_io && fcalls > 2*input_reductions) {
+ if ((have_outstanding_io && fcalls > 2*input_reductions)
+ || rq->halt_in_progress) {
/*
* If we have performed more than 2*INPUT_REDUCTIONS since
* last call to erl_sys_schedule() and we still haven't
@@ -5661,7 +7016,6 @@ Process *schedule(Process *p, int calls)
#endif
ASSERT(p->status != P_SUSPENDED); /* Never run a suspended process */
- ACTIVATE(p);
reds = context_reds;
if (IS_TRACED(p)) {
@@ -5702,7 +7056,6 @@ Process *schedule(Process *p, int calls)
}
p->fcalls = reds;
- ASSERT(IS_ACTIVE(p));
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
return p;
}
@@ -5714,14 +7067,14 @@ erts_sched_stat_modify(int what)
int ix;
switch (what) {
case ERTS_SCHED_STAT_MODIFY_ENABLE:
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_sched_stat.enabled = 1;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case ERTS_SCHED_STAT_MODIFY_DISABLE:
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
erts_sched_stat.enabled = 1;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case ERTS_SCHED_STAT_MODIFY_CLEAR:
erts_smp_spin_lock(&erts_sched_stat.lock);
@@ -5781,20 +7134,9 @@ erts_sched_stat_term(Process *p, int total)
void
erts_schedule_misc_op(void (*func)(void *), void *arg)
{
- ErtsRunQueue *rq;
- ErtsMiscOpList *molp = misc_op_list_alloc();
ErtsSchedulerData *esdp = erts_get_scheduler_data();
-
- if (esdp) {
- rq = esdp->run_queue;
- } else {
- /*
- * This can only happen when the sys msg dispatcher
- * thread schedules misc ops (this happens *very*
- * seldom; only when trace drivers are unloaded).
- */
- rq = ERTS_RUNQ_IX(0);
- }
+ ErtsRunQueue *rq = esdp ? esdp->run_queue : ERTS_RUNQ_IX(0);
+ ErtsMiscOpList *molp = misc_op_list_alloc();
erts_smp_runq_lock(rq);
@@ -5887,7 +7229,7 @@ erts_get_exact_total_reductions(Process *c_p, Uint *redsp, Uint *diffp)
* Wait for other schedulers to schedule out their processes
* and update 'reductions'.
*/
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
for (reds = 0, ix = 0; ix < erts_no_run_queues; ix++)
reds += ERTS_RUNQ_IX(ix)->procs.reductions;
if (redsp)
@@ -5895,7 +7237,7 @@ erts_get_exact_total_reductions(Process *c_p, Uint *redsp, Uint *diffp)
if (diffp)
*diffp = reds - last_exact_reductions;
last_exact_reductions = reds;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
@@ -6061,9 +7403,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
ErtsRunQueue *rq, *notify_runq;
Process *p;
Sint arity; /* Number of arguments. */
-#ifndef HYBRID
Uint arg_size; /* Size of arguments. */
-#endif
Uint sz; /* Needed words on heap. */
Uint heap_need; /* Size needed on heap. */
Eterm res = THE_NON_VALUE;
@@ -6072,17 +7412,6 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
erts_smp_proc_lock(parent, ERTS_PROC_LOCKS_ALL_MINOR);
#endif
-#ifdef HYBRID
- /*
- * Copy the arguments to the global heap
- * Since global GC might occur we want to do this before adding the
- * new process to the process_tab.
- */
- BM_SWAP_TIMER(system,copy);
- LAZY_COPY(parent,args);
- BM_SWAP_TIMER(copy,system);
- heap_need = 0;
-#endif /* HYBRID */
/*
* Check for errors.
*/
@@ -6100,15 +7429,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
goto error;
}
+#ifdef BM_COUNTERS
processes_busy++;
+#endif
BM_COUNT(processes_spawned);
-#ifndef HYBRID
BM_SWAP_TIMER(system,size);
arg_size = size_object(args);
BM_SWAP_TIMER(size,system);
heap_need = arg_size;
-#endif
p->flags = erts_default_process_flags;
@@ -6159,9 +7488,6 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm)*sz);
p->old_hend = p->old_htop = p->old_heap = NULL;
p->high_water = p->heap;
-#ifdef INCREMENTAL
- p->scan_top = p->high_water;
-#endif
p->gen_gcs = 0;
p->stop = p->hend = p->heap + sz;
p->htop = p->heap;
@@ -6187,19 +7513,10 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
BM_STOP_TIMER(system);
BM_MESSAGE(args,p,parent);
BM_START_TIMER(system);
-#ifdef HYBRID
- p->arg_reg[2] = args;
-#ifdef INCREMENTAL
- p->active = 0;
- if (ptr_val(args) >= inc_fromspc && ptr_val(args) < inc_fromend)
- INC_ACTIVATE(p);
-#endif
-#else
BM_SWAP_TIMER(system,copy);
p->arg_reg[2] = copy_struct(args, arg_size, &p->htop, &p->off_heap);
BM_MESSAGE_COPIED(arg_size);
BM_SWAP_TIMER(copy,system);
-#endif
p->arity = 3;
p->fvalue = NIL;
@@ -6251,14 +7568,11 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->seq_trace_lastcnt = 0;
p->seq_trace_clock = 0;
SEQ_TRACE_TOKEN(p) = NIL;
- p->parent = parent->id == ERTS_INVALID_PID ? NIL : parent->id;
-
-#ifdef HYBRID
- p->rrma = NULL;
- p->rrsrc = NULL;
- p->nrr = 0;
- p->rrsz = 0;
+#ifdef USE_VM_PROBES
+ DT_UTAG(p) = NIL;
+ DT_UTAG_FLAGS(p) = 0;
#endif
+ p->parent = parent->id == ERTS_INVALID_PID ? NIL : parent->id;
INIT_HOLE_CHECK(p);
#ifdef DEBUG
@@ -6328,15 +7642,6 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
so->mref = mref;
}
-#ifdef HYBRID
- /*
- * Add process to the array of active processes.
- */
- ACTIVATE(p);
- p->active_index = erts_num_active_procs++;
- erts_active_procs[p->active_index] = p;
-#endif
-
#ifdef ERTS_SMP
p->scheduler_data = NULL;
p->is_exiting = 0;
@@ -6348,7 +7653,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->pending_exit.bp = NULL;
#endif
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
p->fp_exception = 0;
#endif
@@ -6383,6 +7688,16 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
VERBOSE(DEBUG_PROCESSES, ("Created a new process: %T\n",p->id));
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_spawn)) {
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_fun_decode(p, mod, func, arity, process_name, mfa);
+ DTRACE2(process_spawn, process_name, mfa);
+ }
+#endif
+
error:
erts_smp_proc_unlock(parent, ERTS_PROC_LOCKS_ALL_MINOR);
@@ -6437,9 +7752,6 @@ void erts_init_empty_process(Process *p)
p->reg = NULL;
p->heap_sz = 0;
p->high_water = NULL;
-#ifdef INCREMENTAL
- p->scan_top = NULL;
-#endif
p->old_hend = NULL;
p->old_htop = NULL;
p->old_heap = NULL;
@@ -6491,14 +7803,6 @@ void erts_init_empty_process(Process *p)
#endif
#endif
- ACTIVATE(p);
-
-#ifdef HYBRID
- p->rrma = NULL;
- p->rrsrc = NULL;
- p->nrr = 0;
- p->rrsz = 0;
-#endif
INIT_HOLE_CHECK(p);
#ifdef DEBUG
p->last_old_htop = NULL;
@@ -6522,7 +7826,7 @@ void erts_init_empty_process(Process *p)
p->run_queue = ERTS_RUNQ_IX(0);
#endif
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
p->fp_exception = 0;
#endif
@@ -6546,9 +7850,6 @@ erts_debug_verify_clean_empty_process(Process* p)
ASSERT(p->reg == NULL);
ASSERT(p->heap_sz == 0);
ASSERT(p->high_water == NULL);
-#ifdef INCREMENTAL
- ASSERT(p->scan_top == NULL);
-#endif
ASSERT(p->old_hend == NULL);
ASSERT(p->old_htop == NULL);
ASSERT(p->old_heap == NULL);
@@ -6696,22 +7997,6 @@ delete_process(Process* p)
ASSERT(!p->suspend_monitors);
p->fvalue = NIL;
-
-#ifdef HYBRID
- erts_active_procs[p->active_index] =
- erts_active_procs[--erts_num_active_procs];
- erts_active_procs[p->active_index]->active_index = p->active_index;
-#ifdef INCREMENTAL
- if (INC_IS_ACTIVE(p))
- INC_DEACTIVATE(p);
-#endif
-
- if (p->rrma != NULL) {
- erts_free(ERTS_ALC_T_ROOTSET,p->rrma);
- erts_free(ERTS_ALC_T_ROOTSET,p->rrsrc);
- }
-#endif
-
}
static ERTS_INLINE void
@@ -6834,7 +8119,11 @@ static ERTS_INLINE void
send_exit_message(Process *to, ErtsProcLocks *to_locksp,
Eterm exit_term, Uint term_size, Eterm token)
{
- if (token == NIL) {
+ if (token == NIL
+#ifdef USE_VM_PROBES
+ || token == am_have_dt_utag
+#endif
+ ) {
Eterm* hp;
Eterm mess;
ErlHeapFragment* bp;
@@ -6842,7 +8131,11 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp,
hp = erts_alloc_message_heap(term_size, &bp, &ohp, to, to_locksp);
mess = copy_struct(exit_term, term_size, &hp, ohp);
- erts_queue_message(to, to_locksp, bp, mess, NIL);
+ erts_queue_message(to, to_locksp, bp, mess, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
} else {
ErlHeapFragment* bp;
Eterm* hp;
@@ -6858,7 +8151,11 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp,
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, mess, SEQ_TRACE_SEND, to->id, NULL);
temp_token = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, mess, temp_token);
+ erts_queue_message(to, to_locksp, bp, mess, temp_token
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
}
@@ -6951,9 +8248,26 @@ send_exit_signal(Process *c_p, /* current process if and only
ASSERT(reason != THE_NON_VALUE);
+#ifdef USE_VM_PROBES
+ if(DTRACE_ENABLED(process_exit_signal) && is_pid(from)) {
+ DTRACE_CHARBUF(sender_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(receiver_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(reason_buf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_pid_str(from, sender_str);
+ dtrace_proc_str(rp, receiver_str);
+ erts_snprintf(reason_buf, sizeof(reason_buf) - 1, "%T", reason);
+ DTRACE3(process_exit_signal, sender_str, receiver_str, reason_buf);
+ }
+#endif
+
if (ERTS_PROC_IS_TRAPPING_EXITS(rp)
&& (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) {
- if (is_not_nil(token) && token_update)
+ if (is_not_nil(token)
+#ifdef USE_VM_PROBES
+ && token != am_have_dt_utag
+#endif
+ && token_update)
seq_trace_update_send(token_update);
if (is_value(exit_tuple))
send_exit_message(rp, rp_locks, exit_tuple, exit_tuple_sz, token);
@@ -7054,7 +8368,6 @@ send_exit_signal(Process *c_p, /* current process if and only
set_proc_exiting(rp,
is_immed(rsn) ? rsn : copy_object(rsn, rp),
NULL);
- ACTIVATE(rp);
if (old_status != P_RUNABLE && old_status != P_RUNNING)
erts_add_to_runq(rp);
}
@@ -7336,15 +8649,6 @@ static void doit_exit_link(ErtsLink *lnk, void *vpcontext)
if (rlnk)
erts_destroy_link(rlnk);
erts_deref_dist_entry(dep);
- } else {
-#ifndef ERTS_SMP
- /* XXX Is this possible? Shouldn't this link
- previously have been removed if the node
- had previously been disconnected. */
- ASSERT(0);
-#endif
- /* This is possible when smp support has been enabled,
- and dist port and process exits simultaneously. */
}
break;
@@ -7386,7 +8690,18 @@ erts_do_exit_process(Process* p, Eterm reason)
p->arity = 0; /* No live registers */
p->fvalue = reason;
-
+
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(process_exit)) {
+ DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(reason_buf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, process_buf);
+ erts_snprintf(reason_buf, DTRACE_TERM_BUF_SIZE - 1, "%T", reason);
+ DTRACE2(process_exit, process_buf, reason_buf);
+ }
+#endif
+
#ifdef ERTS_SMP
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
/* By locking all locks (main lock is already locked) when going
@@ -7623,7 +8938,9 @@ continue_exit_process(Process *p
pbt = ERTS_PROC_SET_CALL_TIME(p, ERTS_PROC_LOCKS_ALL, NULL);
erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL);
+#ifdef BM_COUNTERS
processes_busy--;
+#endif
if (dep) {
erts_do_net_exits(dep, reason);
@@ -8700,6 +10017,22 @@ init_processes_bif(void)
* Debug stuff
*/
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
+int
+erts_dbg_check_halloc_lock(Process *p)
+{
+ if (ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p))
+ return 1;
+ if (p->id == ERTS_INVALID_PID)
+ return 1;
+ if (p->scheduler_data && p == p->scheduler_data->match_pseudo_process)
+ return 1;
+ if (erts_thr_progress_is_blocking())
+ return 1;
+ return 0;
+}
+#endif
+
Eterm
erts_debug_processes(Process *c_p)
{
@@ -8934,3 +10267,30 @@ debug_processes_assert_error(char* expr, char* file, int line)
/* *\
* End of the processes/0 BIF implementation. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * A nice system halt closing all open port goes as follows:
+ * 1) This function schedules the aux work ERTS_SSI_AUX_WORK_REAP_PORTS
+ * on all schedulers, then schedules itself out.
+ * 2) All shedulers detect this and set the flag halt_in_progress
+ * on their run queue. The last scheduler sets all non-closed ports
+ * ERTS_PORT_SFLG_HALT. Global atomic erts_halt_progress is used
+ * as refcount to determine which is last.
+ * 3) While the run ques has flag halt_in_progress no processes
+ * will be scheduled, only ports.
+ * 4) When the last port closes that scheduler calls erlang:halt/1.
+ * The same global atomic is used as refcount.
+ *
+ * A BIF that calls this should make sure to schedule out to never come back:
+ * erl_halt((int)(- code));
+ * ERTS_BIF_YIELD1(bif_export[BIF_erlang_halt_1], BIF_P, NIL);
+ */
+void erl_halt(int code)
+{
+ if (-1 == erts_smp_atomic32_cmpxchg_acqb(&erts_halt_progress,
+ erts_no_schedulers,
+ -1)) {
+ erts_halt_code = code;
+ notify_reap_ports_relb();
+ }
+}
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 627f10b142..9e7a5a5c74 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,11 +53,18 @@ typedef struct process Process;
#include "erl_time.h"
#include "erl_atom_table.h"
#include "external.h"
+#include "erl_mseg.h"
+#include "erl_async.h"
#ifdef HIPE
#include "hipe_process.h"
#endif
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#define ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#include "erl_thr_progress.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+
struct ErtsNodesMonitor_;
struct port;
@@ -88,6 +95,7 @@ struct saved_calls {
};
extern Export exp_send, exp_receive, exp_timeout;
+extern int erts_sched_compact_load;
extern Uint erts_no_schedulers;
extern Uint erts_no_run_queues;
extern int erts_sched_thread_suggested_stack_size;
@@ -136,12 +144,10 @@ extern int erts_sched_thread_suggested_stack_size;
(((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 1))
#define ERTS_RUNQ_FLG_SUSPENDED \
(((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 2))
-#define ERTS_RUNQ_FLG_SHARED_RUNQ \
- (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 3))
#define ERTS_RUNQ_FLG_CHK_CPU_BIND \
- (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 4))
+ (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 3))
#define ERTS_RUNQ_FLG_INACTIVE \
- (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 5))
+ (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 4))
#define ERTS_RUNQ_FLGS_MIGRATION_QMASKS \
(ERTS_RUNQ_FLGS_EMIGRATE_QMASK \
@@ -242,30 +248,35 @@ typedef enum {
| ERTS_SSI_FLG_WAITING \
| ERTS_SSI_FLG_SUSPENDED)
-#define ERTS_SCHED_NEED_BLOCKABLE_AUX_WORK
-
-#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 0)
-#define ERTS_SSI_AUX_WORK_MISC (((erts_aint32_t) 1) << 1)
+/*
+ * Keep ERTS_SSI_AUX_WORK flags in expected frequency order relative
+ * eachother. Most frequent - lowest bit number.
+ */
-#define ERTS_SSI_BLOCKABLE_AUX_WORK_MASK \
- (ERTS_SSI_AUX_WORK_CHECK_CHILDREN \
- | ERTS_SSI_AUX_WORK_MISC)
-#define ERTS_SSI_NONBLOCKABLE_AUX_WORK_MASK \
- (0)
+#define ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP (((erts_aint32_t) 1) << 0)
+#define ERTS_SSI_AUX_WORK_DD (((erts_aint32_t) 1) << 1)
+#define ERTS_SSI_AUX_WORK_DD_THR_PRGR (((erts_aint32_t) 1) << 2)
+#define ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC (((erts_aint32_t) 1) << 3)
+#define ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM (((erts_aint32_t) 1) << 4)
+#define ERTS_SSI_AUX_WORK_ASYNC_READY (((erts_aint32_t) 1) << 5)
+#define ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN (((erts_aint32_t) 1) << 6)
+#define ERTS_SSI_AUX_WORK_MISC_THR_PRGR (((erts_aint32_t) 1) << 7)
+#define ERTS_SSI_AUX_WORK_MISC (((erts_aint32_t) 1) << 8)
+#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 9)
+#define ERTS_SSI_AUX_WORK_SET_TMO (((erts_aint32_t) 1) << 10)
+#define ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK (((erts_aint32_t) 1) << 11)
+#define ERTS_SSI_AUX_WORK_REAP_PORTS (((erts_aint32_t) 1) << 12)
typedef struct ErtsSchedulerSleepInfo_ ErtsSchedulerSleepInfo;
-typedef struct {
- erts_smp_spinlock_t lock;
- ErtsSchedulerSleepInfo *list;
-} ErtsSchedulerSleepList;
-
struct ErtsSchedulerSleepInfo_ {
+#ifdef ERTS_SMP
ErtsSchedulerSleepInfo *next;
ErtsSchedulerSleepInfo *prev;
erts_smp_atomic32_t flags;
erts_tse_t *event;
- erts_smp_atomic32_t aux_work;
+#endif
+ erts_atomic32_t aux_work;
};
/* times to reschedule low prio process before running */
@@ -320,10 +331,6 @@ struct ErtsRunQueue_ {
erts_smp_mtx_t mtx;
erts_smp_cnd_t cnd;
-#ifdef ERTS_SMP
- ErtsSchedulerSleepList sleepers;
-#endif
-
ErtsSchedulerData *scheduler;
int waiting; /* < 0 in sys schedule; > 0 on cnd variable */
int woken;
@@ -336,6 +343,7 @@ struct ErtsRunQueue_ {
int len;
int wakeup_other;
int wakeup_other_reds;
+ int halt_in_progress;
struct {
int len;
@@ -369,7 +377,6 @@ typedef union {
} ErtsAlignedRunQueue;
extern ErtsAlignedRunQueue *erts_aligned_run_queues;
-extern ErtsRunQueue *erts_common_run_queue;
#define ERTS_PROC_REDUCTIONS_EXECUTED(RQ, PRIO, REDS, AREDS) \
do { \
@@ -386,6 +393,59 @@ do { \
(RQ)->wakeup_other_reds += (REDS); \
} while (0)
+typedef struct {
+ int enabled;
+ Uint64 start;
+ struct {
+ Uint64 total;
+ Uint64 start;
+ int currently;
+ } working;
+} ErtsSchedWallTime;
+
+typedef struct {
+ int sched;
+ erts_aint32_t aux_work;
+} ErtsDelayedAuxWorkWakeupJob;
+
+typedef struct {
+ int sched_id;
+ ErtsSchedulerData *esdp;
+ ErtsSchedulerSleepInfo *ssi;
+#ifdef ERTS_SMP
+ ErtsThrPrgrVal current_thr_prgr;
+#endif
+ struct {
+ int ix;
+#ifdef ERTS_SMP
+ ErtsThrPrgrVal thr_prgr;
+#endif
+ } misc;
+#ifdef ERTS_SMP
+ struct {
+ ErtsThrPrgrVal thr_prgr;
+ void (*completed_callback)(void *);
+ void (*completed_arg)(void *);
+ } dd;
+#endif
+#ifdef ERTS_USE_ASYNC_READY_Q
+ struct {
+#ifdef ERTS_SMP
+ int need_thr_prgr;
+ ErtsThrPrgrVal thr_prgr;
+#endif
+ void *queue;
+ } async_ready;
+#endif
+#ifdef ERTS_SMP
+ struct {
+ int *sched2jix;
+ int jix;
+ ErtsDelayedAuxWorkWakeupJob *job;
+ } delayed_wakeup;
+#endif
+} ErtsAuxWorkData;
+
struct ErtsSchedulerData_ {
/*
* Keep X registers first (so we get as many low
@@ -399,8 +459,8 @@ struct ErtsSchedulerData_ {
ethr_tid tid; /* Thread id */
struct erl_bits_state erl_bits_state; /* erl_bits.c state */
void *match_pseudo_process; /* erl_db_util.c:db_prog_match() */
- ErtsSchedulerSleepInfo *ssi;
Process *free_process;
+ ErtsThrPrgrData thr_progress_data;
#endif
#if !HEAP_ON_C_STACK
Eterm tmp_heap[TMP_HEAP_SIZE];
@@ -409,20 +469,19 @@ struct ErtsSchedulerData_ {
Eterm cmp_tmp_heap[CMP_TMP_HEAP_SIZE];
Eterm erl_arith_tmp_heap[ERL_ARITH_TMP_HEAP_SIZE];
#endif
-
+ ErtsSchedulerSleepInfo *ssi;
Process *current_process;
Uint no; /* Scheduler number */
struct port *current_port;
ErtsRunQueue *run_queue;
int virtual_reds;
int cpu_id; /* >= 0 when bound */
-
+ ErtsAuxWorkData aux_work_data;
ErtsAtomCacheMap atom_cache_map;
-#ifdef ERTS_SMP
- /* NOTE: These fields are modified under held mutexes by other threads */
- erts_smp_atomic32_t chk_cpu_bind; /* Only used when common run queue */
-#endif
+ ErtsSchedAllocData alloc_data;
+
+ ErtsSchedWallTime sched_wall_time;
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
erts_alloc_verify_func_t verify_unused_temp_alloc;
@@ -568,7 +627,7 @@ struct process {
Uint min_heap_size; /* Minimum size of heap (in words). */
Uint min_vheap_size; /* Minimum size of virtual heap (in words). */
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
volatile unsigned long fp_exception;
#endif
@@ -636,6 +695,10 @@ struct process {
Uint seq_trace_lastcnt;
Eterm seq_trace_token; /* Sequential trace token (tuple size 5 see below) */
+#ifdef USE_VM_PROBES
+ Eterm dt_utag; /* Place to store the dynamc trace user tag */
+ Uint dt_utag_flags; /* flag field for the dt_utag */
+#endif
BeamInstr initial[3]; /* Initial module(0), function(1), arity(2), often used instead
of pointer to funcinfo instruction, hence the BeamInstr datatype */
BeamInstr* current; /* Current Erlang function, part of the funcinfo:
@@ -698,24 +761,6 @@ struct process {
#endif
#endif
-#ifdef HYBRID
- Eterm *rrma; /* Remembered roots to Message Area */
- Eterm **rrsrc; /* The source of the root */
- Uint nrr; /* Number of remembered roots */
- Uint rrsz; /* Size of root array */
-#endif
-
-#ifdef HYBRID
- Uint active; /* Active since last major collection? */
- Uint active_index; /* Index in the active process array */
-#endif
-
-#ifdef INCREMENTAL
- Process *active_next; /* Active processes to scan for roots */
- Process *active_prev; /* in collection of the message area */
- Eterm *scan_top;
-#endif
-
#ifdef CHECK_FOR_HOLES
Eterm* last_htop; /* No need to scan the heap below this point. */
ErlHeapFragment* last_mbuf; /* No need to scan beyond this mbuf. */
@@ -837,10 +882,6 @@ Eterm* erts_set_hole_marker(Eterm* ptr, Uint sz);
#endif
extern Process** process_tab;
-#ifdef HYBRID
-extern Uint erts_num_active_procs;
-extern Process** erts_active_procs;
-#endif
extern Uint erts_max_processes;
extern Uint erts_process_tab_index_mask;
extern Uint erts_default_process_flags;
@@ -951,6 +992,14 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
#define SEQ_TRACE_PRINT (1 << 2)
#define SEQ_TRACE_TIMESTAMP (1 << 3)
+#ifdef USE_VM_PROBES
+#define DT_UTAG_PERMANENT (1 << 0)
+#define DT_UTAG_SPREADING (1 << 1)
+#define DT_UTAG(P) ((P)->dt_utag)
+#define DT_UTAG_FLAGS(P) ((P)->dt_utag_flags)
+#endif
+
+
#ifdef ERTS_SMP
/* Status flags ... */
#define ERTS_PROC_SFLG_PENDADD2SCHEDQ (((Uint32) 1) << 0) /* Pending
@@ -1028,15 +1077,22 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
void erts_pre_init_process(void);
void erts_late_init_process(void);
-void erts_early_init_scheduling(void);
-void erts_init_scheduling(int, int, int);
+void erts_early_init_scheduling(int);
+void erts_init_scheduling(int, int);
+
+Eterm erts_sched_wall_time_request(Process *c_p, int set, int enable);
ErtsProcList *erts_proclist_create(Process *);
void erts_proclist_destroy(ErtsProcList *);
int erts_proclist_same(ErtsProcList *, Process *);
-int erts_sched_set_wakeup_limit(char *str);
+int erts_sched_set_wakeup_other_thresold(char *str);
+int erts_sched_set_wakeup_other_type(char *str);
+int erts_sched_set_busy_wait_threshold(char *str);
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
+int erts_dbg_check_halloc_lock(Process *p);
+#endif
#ifdef DEBUG
void erts_dbg_multi_scheduling_return_trap(Process *, Eterm);
#endif
@@ -1054,13 +1110,20 @@ erts_block_multi_scheduling(Process *, ErtsProcLocks, int, int);
int erts_is_multi_scheduling_blocked(void);
Eterm erts_multi_scheduling_blockers(Process *);
void erts_start_schedulers(void);
+void erts_alloc_notify_delayed_dealloc(int);
void erts_smp_notify_check_children_needed(void);
-void
-erts_smp_schedule_misc_aux_work(int ignore_self,
- int max_sched,
- void (*func)(void *),
- void *arg);
#endif
+#if ERTS_USE_ASYNC_READY_Q
+void erts_notify_check_async_ready_queue(void *);
+#endif
+void erts_schedule_misc_aux_work(int sched_id,
+ void (*func)(void *),
+ void *arg);
+void erts_schedule_multi_misc_aux_work(int ignore_self,
+ int max_sched,
+ void (*func)(void *),
+ void *arg);
+erts_aint32_t erts_set_aux_work_timeout(int, erts_aint32_t, int);
void erts_sched_notify_check_cpu_bind(void);
Uint erts_active_schedulers(void);
void erts_init_process(int);
@@ -1144,6 +1207,7 @@ Sint erts_test_next_pid(int, Uint);
Eterm erts_debug_processes(Process *c_p);
Eterm erts_debug_processes_bif_info(Process *c_p);
Uint erts_debug_nbalance(void);
+int erts_debug_wait_deallocations(Process *c_p);
#ifdef ERTS_SMP
# define ERTS_GET_SCHEDULER_DATA_FROM_PROC(PROC) ((PROC)->scheduler_data)
@@ -1214,16 +1278,11 @@ erts_psd_get(Process *p, int ix)
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsProcLocks locks = erts_proc_lc_my_proc_locks(p);
if (ERTS_LC_PSD_ANY_LOCK == erts_psd_required_locks[ix].get_locks)
- ERTS_SMP_LC_ASSERT(locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ ERTS_SMP_LC_ASSERT(locks || erts_thr_progress_is_blocking());
else {
locks &= erts_psd_required_locks[ix].get_locks;
ERTS_SMP_LC_ASSERT(erts_psd_required_locks[ix].get_locks == locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ || erts_thr_progress_is_blocking());
}
#endif
ASSERT(0 <= ix && ix < ERTS_PSD_SIZE);
@@ -1240,16 +1299,11 @@ erts_psd_set(Process *p, ErtsProcLocks plocks, int ix, void *data)
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsProcLocks locks = erts_proc_lc_my_proc_locks(p);
if (ERTS_LC_PSD_ANY_LOCK == erts_psd_required_locks[ix].set_locks)
- ERTS_SMP_LC_ASSERT(locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ ERTS_SMP_LC_ASSERT(locks || erts_thr_progress_is_blocking());
else {
locks &= erts_psd_required_locks[ix].set_locks;
ERTS_SMP_LC_ASSERT(erts_psd_required_locks[ix].set_locks == locks
- || erts_is_system_blocked(0)
- || (ERTS_IS_CRASH_DUMPING
- && erts_is_system_blocked(ERTS_BS_FLG_ALLOW_GC)));
+ || erts_thr_progress_is_blocking());
}
#endif
ASSERT(0 <= ix && ix < ERTS_PSD_SIZE);
@@ -1338,10 +1392,14 @@ ERTS_GLB_INLINE Eterm erts_get_current_pid(void);
ERTS_GLB_INLINE Uint erts_get_scheduler_id(void);
ERTS_GLB_INLINE ErtsRunQueue *erts_get_runq_proc(Process *p);
ERTS_GLB_INLINE ErtsRunQueue *erts_get_runq_current(ErtsSchedulerData *esdp);
+#ifndef ERTS_ENABLE_LOCK_COUNT
ERTS_GLB_INLINE void erts_smp_runq_lock(ErtsRunQueue *rq);
+#endif
ERTS_GLB_INLINE int erts_smp_runq_trylock(ErtsRunQueue *rq);
ERTS_GLB_INLINE void erts_smp_runq_unlock(ErtsRunQueue *rq);
+#ifndef ERTS_ENABLE_LOCK_COUNT
ERTS_GLB_INLINE void erts_smp_xrunq_lock(ErtsRunQueue *rq, ErtsRunQueue *xrq);
+#endif
ERTS_GLB_INLINE void erts_smp_xrunq_unlock(ErtsRunQueue *rq, ErtsRunQueue *xrq);
ERTS_GLB_INLINE void erts_smp_runqs_lock(ErtsRunQueue *rq1, ErtsRunQueue *rq2);
ERTS_GLB_INLINE void erts_smp_runqs_unlock(ErtsRunQueue *rq1, ErtsRunQueue *rq2);
@@ -1413,8 +1471,7 @@ erts_get_runq_proc(Process *p)
ASSERT(p->run_queue);
return p->run_queue;
#else
- ASSERT(erts_common_run_queue);
- return erts_common_run_queue;
+ return ERTS_RUNQ_IX(0);
#endif
}
@@ -1427,11 +1484,16 @@ erts_get_runq_current(ErtsSchedulerData *esdp)
esdp = erts_get_scheduler_data();
return esdp->run_queue;
#else
- ASSERT(erts_common_run_queue);
- return erts_common_run_queue;
+ return ERTS_RUNQ_IX(0);
#endif
}
+#ifdef ERTS_ENABLE_LOCK_COUNT
+
+#define erts_smp_runq_lock(rq) erts_smp_mtx_lock_x(&(rq)->mtx, __FILE__, __LINE__)
+
+#else
+
ERTS_GLB_INLINE void
erts_smp_runq_lock(ErtsRunQueue *rq)
{
@@ -1440,6 +1502,8 @@ erts_smp_runq_lock(ErtsRunQueue *rq)
#endif
}
+#endif
+
ERTS_GLB_INLINE int
erts_smp_runq_trylock(ErtsRunQueue *rq)
{
@@ -1458,6 +1522,31 @@ erts_smp_runq_unlock(ErtsRunQueue *rq)
#endif
}
+#ifdef ERTS_ENABLE_LOCK_COUNT
+
+#define erts_smp_xrunq_lock(rq, xrq) erts_smp_xrunq_lock_x((rq), (xrq), __FILE__, __LINE__)
+
+ERTS_GLB_INLINE void
+erts_smp_xrunq_lock_x(ErtsRunQueue *rq, ErtsRunQueue *xrq, char* file, int line)
+{
+#ifdef ERTS_SMP
+ ERTS_SMP_LC_ASSERT(erts_smp_lc_mtx_is_locked(&rq->mtx));
+ if (xrq != rq) {
+ if (erts_smp_mtx_trylock(&xrq->mtx) == EBUSY) {
+ if (rq < xrq)
+ erts_smp_mtx_lock_x(&xrq->mtx, file, line);
+ else {
+ erts_smp_mtx_unlock(&rq->mtx);
+ erts_smp_mtx_lock_x(&xrq->mtx, file, line);
+ erts_smp_mtx_lock_x(&rq->mtx, file, line);
+ }
+ }
+ }
+#endif
+}
+
+#else
+
ERTS_GLB_INLINE void
erts_smp_xrunq_lock(ErtsRunQueue *rq, ErtsRunQueue *xrq)
{
@@ -1477,6 +1566,8 @@ erts_smp_xrunq_lock(ErtsRunQueue *rq, ErtsRunQueue *xrq)
#endif
}
+#endif
+
ERTS_GLB_INLINE void
erts_smp_xrunq_unlock(ErtsRunQueue *rq, ErtsRunQueue *xrq)
{
@@ -1596,8 +1687,6 @@ erts_sched_poke(ErtsSchedulerSleepInfo *ssi)
erts_aint32_t flags;
ERTS_THR_MEMORY_BARRIER;
flags = erts_smp_atomic32_read_nob(&ssi->flags);
- ASSERT(!(flags & ERTS_SSI_FLG_SLEEPING)
- || (flags & ERTS_SSI_FLG_WAITING));
if (flags & ERTS_SSI_FLG_SLEEPING) {
flags = erts_smp_atomic32_read_band_nob(&ssi->flags, ~ERTS_SSI_FLGS_SLEEP);
erts_sched_finish_poke(ssi, flags);
@@ -1615,4 +1704,6 @@ erts_sched_poke(ErtsSchedulerSleepInfo *ssi)
#endif
-
+void erl_halt(int code);
+extern erts_smp_atomic32_t erts_halt_progress;
+extern int erts_halt_code;
diff --git a/erts/emulator/beam/erl_process_lock.c b/erts/emulator/beam/erl_process_lock.c
index 83379d7352..34d591df40 100644
--- a/erts/emulator/beam/erl_process_lock.c
+++ b/erts/emulator/beam/erl_process_lock.c
@@ -90,16 +90,6 @@ static void check_queue(erts_proc_lock_t *lck);
#error "The size of the 'uflgs' field of the erts_tse_t type is too small"
#endif
-struct erts_proc_lock_queues_t_ {
- erts_proc_lock_queues_t *next;
- erts_tse_t *queue[ERTS_PROC_LOCK_MAX_BIT+1];
-};
-
-static erts_proc_lock_queues_t zeroqs = {0};
-
-static erts_smp_spinlock_t qs_lock;
-static erts_proc_lock_queues_t *queue_free_list;
-
#ifdef ERTS_ENABLE_LOCK_CHECK
static struct {
Sint16 proc_lock_main;
@@ -120,16 +110,14 @@ void
erts_init_proc_lock(int cpus)
{
int i;
- erts_smp_spinlock_init(&qs_lock, "proc_lck_qs_alloc");
for (i = 0; i < ERTS_NO_OF_PIX_LOCKS; i++) {
#ifdef ERTS_ENABLE_LOCK_COUNT
- erts_smp_spinlock_init_x(&erts_pix_locks[i].u.spnlck,
- "pix_lock", make_small(i));
+ erts_mtx_init_x(&erts_pix_locks[i].u.mtx,
+ "pix_lock", make_small(i));
#else
- erts_smp_spinlock_init(&erts_pix_locks[i].u.spnlck, "pix_lock");
+ erts_mtx_init(&erts_pix_locks[i].u.mtx, "pix_lock");
#endif
}
- queue_free_list = NULL;
erts_thr_install_exit_handler(cleanup_tse);
#ifdef ERTS_ENABLE_LOCK_CHECK
lc_id.proc_lock_main = erts_lc_get_lock_order_id("proc_main");
@@ -156,16 +144,7 @@ erts_init_proc_lock(int cpus)
}
#ifdef ERTS_ENABLE_LOCK_CHECK
-static void
-check_unused_tse(erts_tse_t *wtr)
-{
- int i;
- erts_proc_lock_queues_t *queues = wtr->udata;
- ERTS_LC_ASSERT(wtr->uflgs == 0);
- for (i = 0; i <= ERTS_PROC_LOCK_MAX_BIT; i++)
- ERTS_LC_ASSERT(!queues->queue[i]);
-}
-#define CHECK_UNUSED_TSE(W) check_unused_tse((W))
+#define CHECK_UNUSED_TSE(W) ERTS_LC_ASSERT((W)->uflgs == 0)
#else
#define CHECK_UNUSED_TSE(W)
#endif
@@ -174,56 +153,21 @@ static ERTS_INLINE erts_tse_t *
tse_fetch(erts_pix_lock_t *pix_lock)
{
erts_tse_t *tse = erts_tse_fetch();
- if (!tse->udata) {
- erts_proc_lock_queues_t *qs;
-#if ERTS_PROC_LOCK_SPINLOCK_IMPL && !ERTS_PROC_LOCK_ATOMIC_IMPL
- if (pix_lock)
- erts_pix_unlock(pix_lock);
-#endif
- erts_smp_spin_lock(&qs_lock);
- qs = queue_free_list;
- if (qs) {
- queue_free_list = queue_free_list->next;
- erts_smp_spin_unlock(&qs_lock);
- }
- else {
- erts_smp_spin_unlock(&qs_lock);
- qs = erts_alloc(ERTS_ALC_T_PROC_LCK_QS,
- sizeof(erts_proc_lock_queues_t));
- sys_memcpy((void *) qs,
- (void *) &zeroqs,
- sizeof(erts_proc_lock_queues_t));
- }
- tse->udata = qs;
-#if ERTS_PROC_LOCK_SPINLOCK_IMPL && !ERTS_PROC_LOCK_ATOMIC_IMPL
- if (pix_lock)
- erts_pix_lock(pix_lock);
-#endif
- }
tse->uflgs = 0;
return tse;
}
static ERTS_INLINE void
-tse_return(erts_tse_t *tse, int force_free_q)
+tse_return(erts_tse_t *tse)
{
CHECK_UNUSED_TSE(tse);
- if (force_free_q || erts_tse_is_tmp(tse)) {
- erts_proc_lock_queues_t *qs = tse->udata;
- ASSERT(qs);
- erts_smp_spin_lock(&qs_lock);
- qs->next = queue_free_list;
- queue_free_list = qs;
- erts_smp_spin_unlock(&qs_lock);
- tse->udata = NULL;
- }
erts_tse_return(tse);
}
void
erts_proc_lock_prepare_proc_lock_waiter(void)
{
- tse_return(tse_fetch(NULL), 0);
+ tse_return(tse_fetch(NULL));
}
@@ -231,55 +175,49 @@ static void
cleanup_tse(void)
{
erts_tse_t *tse = erts_tse_fetch();
- if (tse) {
- if (tse->udata)
- tse_return(tse, 1);
- else
- erts_tse_return(tse);
- }
+ if (tse)
+ erts_tse_return(tse);
}
/*
* Waiters are queued in a circular double linked list;
- * where qs->queue[lock_ix] is the first waiter in queue, and
- * qs->queue[lock_ix]->prev is the last waiter in queue.
+ * where lck->queue[lock_ix] is the first waiter in queue, and
+ * lck->queue[lock_ix]->prev is the last waiter in queue.
*/
static ERTS_INLINE void
-enqueue_waiter(erts_proc_lock_queues_t *qs,
- int ix,
- erts_tse_t *wtr)
+enqueue_waiter(erts_proc_lock_t *lck, int ix, erts_tse_t *wtr)
{
- if (!qs->queue[ix]) {
- qs->queue[ix] = wtr;
+ if (!lck->queue[ix]) {
+ lck->queue[ix] = wtr;
wtr->next = wtr;
wtr->prev = wtr;
}
else {
- ERTS_LC_ASSERT(qs->queue[ix]->next && qs->queue[ix]->prev);
- wtr->next = qs->queue[ix];
- wtr->prev = qs->queue[ix]->prev;
+ ERTS_LC_ASSERT(lck->queue[ix]->next && lck->queue[ix]->prev);
+ wtr->next = lck->queue[ix];
+ wtr->prev = lck->queue[ix]->prev;
wtr->prev->next = wtr;
- qs->queue[ix]->prev = wtr;
+ lck->queue[ix]->prev = wtr;
}
}
static erts_tse_t *
-dequeue_waiter(erts_proc_lock_queues_t *qs, int ix)
+dequeue_waiter(erts_proc_lock_t *lck, int ix)
{
- erts_tse_t *wtr = qs->queue[ix];
- ERTS_LC_ASSERT(qs->queue[ix]);
+ erts_tse_t *wtr = lck->queue[ix];
+ ERTS_LC_ASSERT(lck->queue[ix]);
if (wtr->next == wtr) {
- ERTS_LC_ASSERT(qs->queue[ix]->prev == wtr);
- qs->queue[ix] = NULL;
+ ERTS_LC_ASSERT(lck->queue[ix]->prev == wtr);
+ lck->queue[ix] = NULL;
}
else {
ERTS_LC_ASSERT(wtr->next != wtr);
ERTS_LC_ASSERT(wtr->prev != wtr);
wtr->next->prev = wtr->prev;
wtr->prev->next = wtr->next;
- qs->queue[ix] = wtr->next;
+ lck->queue[ix] = wtr->next;
}
return wtr;
}
@@ -300,19 +238,18 @@ try_aquire(erts_proc_lock_t *lck, erts_tse_t *wtr)
ErtsProcLocks locks = wtr->uflgs;
int lock_no;
- ERTS_LC_ASSERT(lck->queues);
ERTS_LC_ASSERT(got_locks != locks);
for (lock_no = 0; lock_no <= ERTS_PROC_LOCK_MAX_BIT; lock_no++) {
ErtsProcLocks lock = ((ErtsProcLocks) 1) << lock_no;
if (locks & lock) {
ErtsProcLocks wflg, old_lflgs;
- if (lck->queues->queue[lock_no]) {
+ if (lck->queue[lock_no]) {
/* Others already waiting */
enqueue:
ERTS_LC_ASSERT(ERTS_PROC_LOCK_FLGS_READ_(lck)
& (lock << ERTS_PROC_LOCK_WAITER_SHIFT));
- enqueue_waiter(lck->queues, lock_no, wtr);
+ enqueue_waiter(lck, lock_no, wtr);
break;
}
wflg = lock << ERTS_PROC_LOCK_WAITER_SHIFT;
@@ -364,7 +301,6 @@ transfer_locks(Process *p,
for (lock_no = 0; tlocks && lock_no <= ERTS_PROC_LOCK_MAX_BIT; lock_no++) {
ErtsProcLocks lock = ((ErtsProcLocks) 1) << lock_no;
if (tlocks & lock) {
- erts_proc_lock_queues_t *qs = p->lock.queues;
/* Transfer lock */
#ifdef ERTS_ENABLE_LOCK_CHECK
tlocks &= ~lock;
@@ -372,9 +308,9 @@ transfer_locks(Process *p,
ERTS_LC_ASSERT(ERTS_PROC_LOCK_FLGS_READ_(&p->lock)
& (lock << ERTS_PROC_LOCK_WAITER_SHIFT));
transferred++;
- wtr = dequeue_waiter(qs, lock_no);
+ wtr = dequeue_waiter(&p->lock, lock_no);
ERTS_LC_ASSERT(wtr);
- if (!qs->queue[lock_no])
+ if (!p->lock.queue[lock_no])
unset_waiter |= lock;
ERTS_LC_ASSERT(wtr->uflgs & lock);
wtr->uflgs &= ~lock;
@@ -463,7 +399,6 @@ wait_for_locks(Process *p,
{
erts_pix_lock_t *pix_lock = pixlck ? pixlck : ERTS_PID2PIXLOCK(p->id);
erts_tse_t *wtr;
- erts_proc_lock_queues_t *qs;
/* Acquire a waiter object on which this thread can wait. */
wtr = tse_fetch(pix_lock);
@@ -479,18 +414,6 @@ wait_for_locks(Process *p,
ERTS_LC_ASSERT(erts_lc_pix_lock_is_locked(pix_lock));
- qs = wtr->udata;
- ASSERT(qs);
- /* Provide the process with waiter queues, if it doesn't have one. */
- if (!p->lock.queues) {
- qs->next = NULL;
- p->lock.queues = qs;
- }
- else {
- qs->next = p->lock.queues->next;
- p->lock.queues->next = qs;
- }
-
#ifdef ERTS_PROC_LOCK_HARD_DEBUG
check_queue(&p->lock);
#endif
@@ -504,7 +427,9 @@ wait_for_locks(Process *p,
check_queue(&p->lock);
#endif
- if (wtr->uflgs) {
+ if (wtr->uflgs == 0)
+ erts_pix_unlock(pix_lock);
+ else {
/* We didn't get them all; need to wait... */
ASSERT((wtr->uflgs & ~ERTS_PROC_LOCKS_ALL) == 0);
@@ -529,28 +454,12 @@ wait_for_locks(Process *p,
} while (res != 0);
}
- erts_pix_lock(pix_lock);
-
ASSERT(wtr->uflgs == 0);
}
- /* Recover some queues to store in the waiter. */
- ERTS_LC_ASSERT(p->lock.queues);
- if (p->lock.queues->next) {
- qs = p->lock.queues->next;
- p->lock.queues->next = qs->next;
- }
- else {
- qs = p->lock.queues;
- p->lock.queues = NULL;
- }
- wtr->udata = qs;
-
- erts_pix_unlock(pix_lock);
-
ERTS_LC_ASSERT(locks == (ERTS_PROC_LOCK_FLGS_READ_(&p->lock) & locks));
- tse_return(wtr, 0);
+ tse_return(wtr);
}
/*
@@ -669,7 +578,9 @@ proc_safelock(Process *a_proc,
ErtsProcLocks b_need_locks)
{
Process *p1, *p2;
+#ifdef ERTS_ENABLE_LOCK_CHECK
Eterm pid1, pid2;
+#endif
erts_pix_lock_t *pix_lck1, *pix_lck2;
ErtsProcLocks need_locks1, have_locks1, need_locks2, have_locks2;
ErtsProcLocks unlock_mask;
@@ -684,24 +595,32 @@ proc_safelock(Process *a_proc,
if (a_proc) {
if (a_proc->id < b_proc->id) {
p1 = a_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = a_proc->id;
+#endif
pix_lck1 = a_pix_lck;
need_locks1 = a_need_locks;
have_locks1 = a_have_locks;
p2 = b_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = b_proc->id;
+#endif
pix_lck2 = b_pix_lck;
need_locks2 = b_need_locks;
have_locks2 = b_have_locks;
}
else if (a_proc->id > b_proc->id) {
p1 = b_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = b_proc->id;
+#endif
pix_lck1 = b_pix_lck;
need_locks1 = b_need_locks;
have_locks1 = b_have_locks;
p2 = a_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = a_proc->id;
+#endif
pix_lck2 = a_pix_lck;
need_locks2 = a_need_locks;
have_locks2 = a_have_locks;
@@ -710,12 +629,16 @@ proc_safelock(Process *a_proc,
ERTS_LC_ASSERT(a_proc == b_proc);
ERTS_LC_ASSERT(a_proc->id == b_proc->id);
p1 = a_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = a_proc->id;
+#endif
pix_lck1 = a_pix_lck;
need_locks1 = a_need_locks | b_need_locks;
have_locks1 = a_have_locks | b_have_locks;
p2 = NULL;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = 0;
+#endif
pix_lck2 = NULL;
need_locks2 = 0;
have_locks2 = 0;
@@ -723,12 +646,16 @@ proc_safelock(Process *a_proc,
}
else {
p1 = b_proc;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid1 = b_proc->id;
+#endif
pix_lck1 = b_pix_lck;
need_locks1 = b_need_locks;
have_locks1 = b_have_locks;
p2 = NULL;
+#ifdef ERTS_ENABLE_LOCK_CHECK
pid2 = 0;
+#endif
pix_lck2 = NULL;
need_locks2 = 0;
have_locks2 = 0;
@@ -953,6 +880,7 @@ erts_pid2proc_safelock(Process *c_p,
void
erts_proc_lock_init(Process *p)
{
+ int i;
/* We always start with all locks locked */
#if ERTS_PROC_LOCK_ATOMIC_IMPL
erts_smp_atomic32_init_nob(&p->lock.flags,
@@ -960,7 +888,8 @@ erts_proc_lock_init(Process *p)
#else
p->lock.flags = ERTS_PROC_LOCKS_ALL;
#endif
- p->lock.queues = NULL;
+ for (i = 0; i <= ERTS_PROC_LOCK_MAX_BIT; i++)
+ p->lock.queue[i] = NULL;
p->lock.refc = 1;
#ifdef ERTS_ENABLE_LOCK_COUNT
erts_lcnt_proc_lock_init(p);
@@ -972,11 +901,8 @@ erts_proc_lock_init(Process *p)
erts_proc_lc_trylock(p, ERTS_PROC_LOCKS_ALL, 1);
#endif
#ifdef ERTS_PROC_LOCK_DEBUG
- {
- int i;
- for (i = 0; i <= ERTS_PROC_LOCK_MAX_BIT; i++)
- erts_smp_atomic32_init_nob(&p->lock.locked[i], (erts_aint32_t) 1);
- }
+ for (i = 0; i <= ERTS_PROC_LOCK_MAX_BIT; i++)
+ erts_smp_atomic32_init_nob(&p->lock.locked[i], (erts_aint32_t) 1);
#endif
}
@@ -984,7 +910,7 @@ erts_proc_lock_init(Process *p)
#ifdef ERTS_ENABLE_LOCK_COUNT
void erts_lcnt_proc_lock_init(Process *p) {
-
+ if (erts_lcnt_rt_options & ERTS_LCNT_OPT_PROCLOCK) {
if (p->id != ERTS_INVALID_PID) {
erts_lcnt_init_lock_x(&(p->lock.lcnt_main), "proc_main", ERTS_LCNT_LT_PROCLOCK, p->id);
erts_lcnt_init_lock_x(&(p->lock.lcnt_msgq), "proc_msgq", ERTS_LCNT_LT_PROCLOCK, p->id);
@@ -996,6 +922,12 @@ void erts_lcnt_proc_lock_init(Process *p) {
erts_lcnt_init_lock(&(p->lock.lcnt_link), "proc_link", ERTS_LCNT_LT_PROCLOCK);
erts_lcnt_init_lock(&(p->lock.lcnt_status), "proc_status", ERTS_LCNT_LT_PROCLOCK);
}
+ } else {
+ sys_memzero(&(p->lock.lcnt_main), sizeof(p->lock.lcnt_main));
+ sys_memzero(&(p->lock.lcnt_msgq), sizeof(p->lock.lcnt_msgq));
+ sys_memzero(&(p->lock.lcnt_link), sizeof(p->lock.lcnt_link));
+ sys_memzero(&(p->lock.lcnt_status), sizeof(p->lock.lcnt_status));
+ }
}
@@ -1090,6 +1022,26 @@ void erts_lcnt_proc_trylock(erts_proc_lock_t *lock, ErtsProcLocks locks, int res
}
}
+
+void erts_lcnt_enable_proc_lock_count(int enable) {
+ int i;
+
+ for (i = 0; i < erts_max_processes; ++i) {
+ Process* p = process_tab[i];
+ if (p) {
+ if (enable) {
+ if (!ERTS_LCNT_LOCK_TYPE(&(p->lock.lcnt_main))) {
+ erts_lcnt_proc_lock_init(p);
+ }
+ } else {
+ if (ERTS_LCNT_LOCK_TYPE(&(p->lock.lcnt_main))) {
+ erts_lcnt_proc_lock_destroy(p);
+ }
+ }
+ }
+ }
+}
+
#endif /* ifdef ERTS_ENABLE_LOCK_COUNT */
@@ -1419,21 +1371,21 @@ check_queue(erts_proc_lock_t *lck)
if (lflgs & wtr) {
int n;
erts_tse_t *wtr;
- ERTS_LC_ASSERT(lck->queues && lck->queues->queue[lock_no]);
- wtr = lck->queues->queue[lock_no];
+ ERTS_LC_ASSERT(lck->queue[lock_no]);
+ wtr = lck->queue[lock_no];
n = 0;
do {
wtr = wtr->next;
n++;
- } while (wtr != lck->queues->queue[lock_no]);
+ } while (wtr != lck->queue[lock_no]);
do {
wtr = wtr->prev;
n--;
- } while (wtr != lck->queues->queue[lock_no]);
+ } while (wtr != lck->queue[lock_no]);
ERTS_LC_ASSERT(n == 0);
}
else {
- ERTS_LC_ASSERT(!lck->queues || !lck->queues->queue[lock_no]);
+ ERTS_LC_ASSERT(!lck->queue[lock_no]);
}
}
}
diff --git a/erts/emulator/beam/erl_process_lock.h b/erts/emulator/beam/erl_process_lock.h
index cd3b2182fd..290084d8ca 100644
--- a/erts/emulator/beam/erl_process_lock.h
+++ b/erts/emulator/beam/erl_process_lock.h
@@ -56,15 +56,13 @@
typedef erts_aint32_t ErtsProcLocks;
-typedef struct erts_proc_lock_queues_t_ erts_proc_lock_queues_t;
-
typedef struct erts_proc_lock_t_ {
#if ERTS_PROC_LOCK_ATOMIC_IMPL
erts_smp_atomic32_t flags;
#else
ErtsProcLocks flags;
#endif
- erts_proc_lock_queues_t *queues;
+ erts_tse_t *queue[ERTS_PROC_LOCK_MAX_BIT+1];
Sint32 refc;
#ifdef ERTS_PROC_LOCK_DEBUG
erts_smp_atomic32_t locked[ERTS_PROC_LOCK_MAX_BIT+1];
@@ -215,6 +213,8 @@ void erts_lcnt_proc_lock_unaquire(erts_proc_lock_t *lock, ErtsProcLocks locks);
void erts_lcnt_proc_unlock(erts_proc_lock_t *lock, ErtsProcLocks locks);
void erts_lcnt_proc_trylock(erts_proc_lock_t *lock, ErtsProcLocks locks, int res);
+void erts_lcnt_enable_proc_lock_count(int enable);
+
#endif /* ERTS_ENABLE_LOCK_COUNT*/
@@ -255,8 +255,8 @@ void erts_proc_lc_unrequire_lock(Process *p, ErtsProcLocks locks);
typedef struct {
union {
- erts_smp_spinlock_t spnlck;
- char buf[64]; /* Try to get locks in different cache lines */
+ erts_mtx_t mtx;
+ char buf[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_mtx_t))];
} u;
} erts_pix_lock_t;
@@ -380,18 +380,18 @@ ERTS_GLB_INLINE void erts_proc_lock_op_debug(Process *, ErtsProcLocks, int);
ERTS_GLB_INLINE void erts_pix_lock(erts_pix_lock_t *pixlck)
{
ERTS_LC_ASSERT(pixlck);
- erts_smp_spin_lock(&pixlck->u.spnlck);
+ erts_mtx_lock(&pixlck->u.mtx);
}
ERTS_GLB_INLINE void erts_pix_unlock(erts_pix_lock_t *pixlck)
{
ERTS_LC_ASSERT(pixlck);
- erts_smp_spin_unlock(&pixlck->u.spnlck);
+ erts_mtx_unlock(&pixlck->u.mtx);
}
ERTS_GLB_INLINE int erts_lc_pix_lock_is_locked(erts_pix_lock_t *pixlck)
{
- return erts_smp_lc_spinlock_is_locked(&pixlck->u.spnlck);
+ return erts_lc_mtx_is_locked(&pixlck->u.mtx);
}
/*
@@ -651,7 +651,7 @@ ERTS_GLB_INLINE int erts_smp_proc_trylock(Process *, ErtsProcLocks);
ERTS_GLB_INLINE void erts_smp_proc_inc_refc(Process *);
ERTS_GLB_INLINE void erts_smp_proc_dec_refc(Process *);
-
+ERTS_GLB_INLINE void erts_smp_proc_add_refc(Process *, Sint32);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -737,6 +737,21 @@ ERTS_GLB_INLINE void erts_smp_proc_dec_refc(Process *p)
#endif
}
+ERTS_GLB_INLINE void erts_smp_proc_add_refc(Process *p, Sint32 refc)
+{
+#ifdef ERTS_SMP
+ Process *fp;
+ erts_pix_lock_t *pixlck = ERTS_PID2PIXLOCK(p->id);
+ erts_pix_lock(pixlck);
+ ERTS_LC_ASSERT(p->lock.refc > 0);
+ p->lock.refc += refc;
+ fp = p->lock.refc == 0 ? p : NULL;
+ erts_pix_unlock(pixlck);
+ if (fp)
+ erts_free_proc(fp);
+#endif
+}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
#ifdef ERTS_SMP
@@ -943,8 +958,6 @@ erts_pid2proc_opt(Process *c_p,
if (flags & ERTS_P2P_FLG_TRY_LOCK)
proc = ERTS_PROC_LOCK_BUSY;
else {
- if (flags & ERTS_P2P_FLG_SMP_INC_REFC)
- proc->lock.refc++;
#ifdef ERTS_ENABLE_LOCK_COUNT
erts_lcnt_proc_lock_unaquire(&proc->lock, lcnt_locks);
#endif
@@ -954,6 +967,8 @@ erts_pid2proc_opt(Process *c_p,
pid_need_locks,
pix_lock,
flags);
+ if (proc && (flags & ERTS_P2P_FLG_SMP_INC_REFC))
+ proc->lock.refc++;
}
}
}
diff --git a/erts/emulator/beam/erl_sched_spec_pre_alloc.c b/erts/emulator/beam/erl_sched_spec_pre_alloc.c
new file mode 100644
index 0000000000..a490aec734
--- /dev/null
+++ b/erts/emulator/beam/erl_sched_spec_pre_alloc.c
@@ -0,0 +1,327 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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: Scheduler specific pre-allocators. Each scheduler
+ * thread allocates memory in its own private chunk of
+ * memory. Memory blocks deallocated by remote
+ * schedulers (or other threads) are passed back to
+ * the chunk owner via a lock-free data structure.
+ *
+ * Author: Rickard Green
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef ERTS_SMP
+
+#include "erl_process.h"
+#include "erl_thr_progress.h"
+
+erts_sspa_data_t *
+erts_sspa_create(size_t blk_sz, int pa_size)
+{
+ erts_sspa_data_t *data;
+ size_t tot_size;
+ size_t chunk_mem_size;
+ char *p;
+ char *chunk_start;
+ int cix;
+ int no_blocks = pa_size;
+ int no_blocks_per_chunk;
+
+ if (erts_no_schedulers == 1)
+ no_blocks_per_chunk = no_blocks;
+ else {
+ int extra = (no_blocks - 1)/4 + 1;
+ if (extra == 0)
+ extra = 1;
+ no_blocks_per_chunk = no_blocks;
+ no_blocks_per_chunk += extra*erts_no_schedulers;
+ no_blocks_per_chunk /= erts_no_schedulers;
+ }
+ no_blocks = no_blocks_per_chunk * erts_no_schedulers;
+ chunk_mem_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_chunk_header_t));
+ chunk_mem_size += blk_sz * no_blocks_per_chunk;
+ chunk_mem_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(chunk_mem_size);
+ tot_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_data_t));
+ tot_size += chunk_mem_size*erts_no_schedulers;
+
+ p = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_PRE_ALLOC_DATA, tot_size);
+ data = (erts_sspa_data_t *) p;
+ p += ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_data_t));
+ chunk_start = p;
+
+ data->chunks_mem_size = chunk_mem_size;
+ data->start = chunk_start;
+ data->end = chunk_start + chunk_mem_size*erts_no_schedulers;
+
+ /* Initialize all chunks */
+ for (cix = 0; cix < erts_no_schedulers; cix++) {
+ erts_sspa_chunk_t *chnk = erts_sspa_cix2chunk(data, cix);
+ erts_sspa_chunk_header_t *chdr = &chnk->aligned.header;
+ erts_sspa_blk_t *blk;
+ int i;
+
+ erts_atomic_init_nob(&chdr->tail.data.last, (erts_aint_t) &chdr->tail.data.marker);
+ erts_atomic_init_nob(&chdr->tail.data.marker.next_atmc, ERTS_AINT_NULL);
+ erts_atomic_init_nob(&chdr->tail.data.um_refc[0], 0);
+ erts_atomic_init_nob(&chdr->tail.data.um_refc[1], 0);
+ erts_atomic32_init_nob(&chdr->tail.data.um_refc_ix, 0);
+
+ chdr->head.no_thr_progress_check = 0;
+ chdr->head.used_marker = 1;
+ chdr->head.first = &chdr->tail.data.marker;
+ chdr->head.unref_end = &chdr->tail.data.marker;
+ chdr->head.next.thr_progress = erts_thr_progress_current();
+ chdr->head.next.thr_progress_reached = 1;
+ chdr->head.next.um_refc_ix = 1;
+ chdr->head.next.unref_end = &chdr->tail.data.marker;
+
+ p = &chnk->data[0];
+ chdr->local.first = (erts_sspa_blk_t *) p;
+ blk = (erts_sspa_blk_t *) p;
+ for (i = 0; i < no_blocks_per_chunk; i++) {
+ blk = (erts_sspa_blk_t *) p;
+ p += blk_sz;
+ blk->next_ptr = (erts_sspa_blk_t *) p;
+ }
+
+ blk->next_ptr = NULL;
+ chdr->local.last = blk;
+ chdr->local.cnt = no_blocks_per_chunk;
+ chdr->local.lim = no_blocks_per_chunk / 3;
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+
+ return data;
+}
+
+static ERTS_INLINE void
+enqueue_remote_managed_thread(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *this,
+ int cinit)
+{
+ erts_aint_t itmp;
+ erts_sspa_blk_t *enq;
+
+ erts_atomic_init_nob(&this->next_atmc, ERTS_AINT_NULL);
+ /* Enqueue at end of list... */
+
+ enq = (erts_sspa_blk_t *) erts_atomic_read_nob(&chdr->tail.data.last);
+ itmp = erts_atomic_cmpxchg_relb(&enq->next_atmc,
+ (erts_aint_t) this,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL) {
+ /* We are required to move last pointer */
+#ifdef DEBUG
+ ASSERT(ERTS_AINT_NULL == erts_atomic_read_nob(&this->next_atmc));
+ ASSERT(((erts_aint_t) enq)
+ == erts_atomic_xchg_relb(&chdr->tail.data.last,
+ (erts_aint_t) this));
+#else
+ erts_atomic_set_relb(&chdr->tail.data.last, (erts_aint_t) this);
+#endif
+ }
+ else {
+ /*
+ * We *need* to insert element somewhere in between the
+ * last element we read earlier and the actual last element.
+ */
+ int i = cinit;
+
+ while (1) {
+ erts_aint_t itmp2;
+ erts_atomic_set_nob(&this->next_atmc, itmp);
+ itmp2 = erts_atomic_cmpxchg_relb(&enq->next_atmc,
+ (erts_aint_t) this,
+ itmp);
+ if (itmp == itmp2)
+ break; /* inserted this */
+ if ((i & 1) == 0)
+ itmp = itmp2;
+ else {
+ enq = (erts_sspa_blk_t *) itmp;
+ itmp = erts_atomic_read_acqb(&enq->next_atmc);
+ ASSERT(itmp != ERTS_AINT_NULL);
+ }
+ i++;
+ }
+ }
+}
+
+static ERTS_INLINE erts_aint_t
+check_insert_marker(erts_sspa_chunk_header_t *chdr, erts_aint_t ilast)
+{
+ if (!chdr->head.used_marker
+ && chdr->head.unref_end == (erts_sspa_blk_t *) ilast) {
+ erts_aint_t itmp;
+ erts_sspa_blk_t *last = (erts_sspa_blk_t *) ilast;
+
+ erts_atomic_init_nob(&chdr->tail.data.marker.next_atmc, ERTS_AINT_NULL);
+ itmp = erts_atomic_cmpxchg_relb(&last->next_atmc,
+ (erts_aint_t) &chdr->tail.data.marker,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL) {
+ ilast = (erts_aint_t) &chdr->tail.data.marker;
+ chdr->head.used_marker = !0;
+ erts_atomic_set_relb(&chdr->tail.data.last, ilast);
+ }
+ }
+ return ilast;
+}
+
+void
+erts_sspa_remote_free(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *blk,
+ int cinit)
+{
+ int um_refc_ix = 0;
+ int managed_thread = erts_thr_progress_is_managed_thread();
+ if (!managed_thread) {
+ um_refc_ix = erts_atomic32_read_acqb(&chdr->tail.data.um_refc_ix);
+ while (1) {
+ int tmp_um_refc_ix;
+ erts_atomic_inc_acqb(&chdr->tail.data.um_refc[um_refc_ix]);
+ tmp_um_refc_ix = erts_atomic32_read_acqb(&chdr->tail.data.um_refc_ix);
+ if (tmp_um_refc_ix == um_refc_ix)
+ break;
+ erts_atomic_dec_relb(&chdr->tail.data.um_refc[um_refc_ix]);
+ um_refc_ix = tmp_um_refc_ix;
+ }
+ }
+
+ enqueue_remote_managed_thread(chdr, blk, cinit);
+
+ if (!managed_thread)
+ erts_atomic_dec_relb(&chdr->tail.data.um_refc[um_refc_ix]);
+}
+
+static ERTS_INLINE void
+fetch_remote(erts_sspa_chunk_header_t *chdr, int max)
+{
+ int new_local = 0;
+
+ if (chdr->head.no_thr_progress_check < ERTS_SSPA_FORCE_THR_CHECK_PROGRESS)
+ chdr->head.no_thr_progress_check++;
+ else {
+ erts_aint_t ilast;
+
+ chdr->head.no_thr_progress_check = 0;
+
+ ilast = erts_atomic_read_nob(&chdr->tail.data.last);
+ if (((erts_sspa_blk_t *) ilast) == &chdr->tail.data.marker
+ && chdr->head.first == &chdr->tail.data.marker)
+ return;
+
+ if (chdr->head.next.thr_progress_reached
+ || erts_thr_progress_has_reached(chdr->head.next.thr_progress)) {
+ int um_refc_ix;
+ chdr->head.next.thr_progress_reached = 1;
+ um_refc_ix = chdr->head.next.um_refc_ix;
+ if (erts_atomic_read_nob(&chdr->tail.data.um_refc[um_refc_ix]) == 0) {
+
+ ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
+
+ /* Move unreferenced end pointer forward... */
+
+ chdr->head.unref_end = chdr->head.next.unref_end;
+
+ ilast = check_insert_marker(chdr, ilast);
+
+ if (chdr->head.unref_end != (erts_sspa_blk_t *) ilast) {
+ chdr->head.next.unref_end = (erts_sspa_blk_t *) ilast;
+ chdr->head.next.thr_progress = erts_thr_progress_later(NULL);
+ erts_atomic32_set_relb(&chdr->tail.data.um_refc_ix,
+ um_refc_ix);
+ chdr->head.next.um_refc_ix = um_refc_ix == 0 ? 1 : 0;
+ chdr->head.next.thr_progress_reached = 0;
+ }
+ }
+ }
+ }
+
+ if (new_local < max && chdr->head.first != chdr->head.unref_end) {
+ erts_sspa_blk_t *first, *this, *next, *last;
+ first = chdr->head.first;
+ if (first == &chdr->tail.data.marker) {
+ chdr->head.used_marker = 0;
+ first = ((erts_sspa_blk_t *)
+ erts_atomic_read_nob(&first->next_atmc));
+ chdr->head.first = first;
+ }
+ if (first != chdr->head.unref_end) {
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+
+ this = last = first;
+ do {
+ next = (erts_sspa_blk_t *) erts_atomic_read_nob(&this->next_atmc);
+ if (this == &chdr->tail.data.marker)
+ chdr->head.used_marker = 0;
+ else {
+ last->next_ptr = this;
+ last = this;
+ new_local++;
+ }
+ this = next;
+ } while (new_local < max && this != chdr->head.unref_end);
+ chdr->head.first = this;
+ if (!chdr->local.last)
+ chdr->local.first = first;
+ else
+ chdr->local.last->next_ptr = first;
+ chdr->local.last = last;
+ last->next_ptr = NULL;
+ chdr->local.cnt += new_local;
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+ }
+
+}
+
+erts_sspa_blk_t *
+erts_sspa_process_remote_frees(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *old_res)
+{
+ erts_sspa_blk_t *res = old_res;
+
+ fetch_remote(chdr, ERTS_SSPA_MAX_GET_NEW_LOCAL);
+
+ if (!res && chdr->local.first) {
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+
+ res = chdr->local.first;
+ chdr->local.first = res->next_ptr;
+ chdr->local.cnt--;
+ if (!chdr->local.first)
+ chdr->local.last = NULL;
+
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+
+ return res;
+}
+
+#endif /* ERTS_SMP */
diff --git a/erts/emulator/beam/erl_sched_spec_pre_alloc.h b/erts/emulator/beam/erl_sched_spec_pre_alloc.h
new file mode 100644
index 0000000000..bccb1aba7a
--- /dev/null
+++ b/erts/emulator/beam/erl_sched_spec_pre_alloc.h
@@ -0,0 +1,240 @@
+/*
+ * %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%
+ */
+
+/*
+ * Description: Scheduler specific pre-allocators. Each scheduler
+ * thread allocates memory in its own private chunk of
+ * memory. Memory blocks deallocated by remote
+ * schedulers (or other threads) are passed back to
+ * the chunk owner via a lock-free data structure.
+ *
+ * Author: Rickard Green
+ */
+
+#ifndef ERTS_SCHED_SPEC_PRE_ALLOC_H__
+#define ERTS_SCHED_SPEC_PRE_ALLOC_H__
+
+#ifdef ERTS_SMP
+
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#define ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#include "erl_thr_progress.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+
+#ifdef DEBUG
+#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P) \
+do { \
+ ASSERT((void *) (C) < (void *) (P)); \
+ ASSERT((void *) (P) \
+ < (void *) (((char *) (C)) + (A)->chunks_mem_size)); \
+} while (0)
+#else
+#define ERTS_SPPA_DBG_CHK_IN_CHNK(A, C, P)
+#endif
+
+#ifdef DEBUG
+extern Uint erts_no_schedulers;
+#endif
+
+#define ERTS_SSPA_FORCE_THR_CHECK_PROGRESS 10
+#define ERTS_SSPA_MAX_GET_NEW_LOCAL 5
+
+typedef struct {
+ char *start;
+ char *end;
+ int chunks_mem_size;
+} erts_sspa_data_t;
+
+typedef union erts_sspa_blk_t_ erts_sspa_blk_t;
+union erts_sspa_blk_t_ {
+ erts_atomic_t next_atmc;
+ erts_sspa_blk_t *next_ptr;
+};
+
+typedef struct {
+ erts_sspa_blk_t *first;
+ erts_sspa_blk_t *last;
+ int cnt;
+ int lim;
+} erts_sspa_local_freelist_t;
+
+typedef struct {
+ erts_sspa_blk_t marker;
+ erts_atomic_t last;
+ erts_atomic_t um_refc[2];
+ erts_atomic32_t um_refc_ix;
+} erts_sspa_tail_t;
+
+typedef struct {
+ /*
+ * This structure needs to be cache line aligned for best
+ * performance.
+ */
+ union {
+ /* Modified by threads returning memory to this chunk */
+ erts_sspa_tail_t data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_sspa_tail_t))];
+ } tail;
+ /*
+ * Everything below this point is *only* accessed by the
+ * thread owning this chunk.
+ */
+ struct {
+ int no_thr_progress_check;
+ int used_marker;
+ erts_sspa_blk_t *first;
+ erts_sspa_blk_t *unref_end;
+ struct {
+ ErtsThrPrgrVal thr_progress;
+ int thr_progress_reached;
+ int um_refc_ix;
+ erts_sspa_blk_t *unref_end;
+ } next;
+ } head;
+ erts_sspa_local_freelist_t local;
+} erts_sspa_chunk_header_t;
+
+typedef struct {
+ union {
+ erts_sspa_chunk_header_t header;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
+ sizeof(erts_sspa_chunk_header_t))];
+ } aligned;
+ char data[1];
+} erts_sspa_chunk_t;
+
+#ifdef DEBUG
+ERTS_GLB_INLINE void
+check_local_list(erts_sspa_chunk_header_t *chdr);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE void
+check_local_list(erts_sspa_chunk_header_t *chdr)
+{
+ erts_sspa_blk_t *blk;
+ int n = 0;
+ for (blk = chdr->local.first; blk; blk = blk->next_ptr)
+ n++;
+ ASSERT(n == chdr->local.cnt);
+}
+#endif
+#define ERTS_SSPA_DBG_CHK_LCL(CHDR) check_local_list((CHDR))
+#else
+#define ERTS_SSPA_DBG_CHK_LCL(CHDR)
+#endif
+
+erts_sspa_data_t *erts_sspa_create(size_t blk_sz,
+ int pa_size);
+void erts_sspa_remote_free(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *blk,
+ int cinit);
+erts_sspa_blk_t *erts_sspa_process_remote_frees(erts_sspa_chunk_header_t *chdr,
+ erts_sspa_blk_t *old_res);
+
+ERTS_GLB_INLINE erts_sspa_chunk_t *erts_sspa_cix2chunk(erts_sspa_data_t *data,
+ int cix);
+ERTS_GLB_INLINE int erts_sspa_ptr2cix(erts_sspa_data_t *data, void *ptr);
+ERTS_GLB_INLINE char *erts_sspa_alloc(erts_sspa_data_t *data, int cix);
+ERTS_GLB_INLINE int erts_sspa_free(erts_sspa_data_t *data, int cix, char *blk);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE erts_sspa_chunk_t *
+erts_sspa_cix2chunk(erts_sspa_data_t *data, int cix)
+{
+ ASSERT(0 <= cix && cix < erts_no_schedulers);
+ return (erts_sspa_chunk_t *) (data->start + cix*data->chunks_mem_size);
+}
+
+ERTS_GLB_INLINE int
+erts_sspa_ptr2cix(erts_sspa_data_t *data, void *ptr)
+{
+ int cix;
+ size_t diff;
+ if ((char *) ptr < data->start || data->end <= (char *) ptr)
+ return -1;
+ diff = ((char *) ptr) - data->start;
+ cix = (int) diff / data->chunks_mem_size;
+ ASSERT(0 <= cix && cix < erts_no_schedulers);
+ return cix;
+}
+
+ERTS_GLB_INLINE char *
+erts_sspa_alloc(erts_sspa_data_t *data, int cix)
+{
+ erts_sspa_chunk_t *chnk;
+ erts_sspa_chunk_header_t *chdr;
+ erts_sspa_blk_t *res;
+
+ chnk = erts_sspa_cix2chunk(data, cix);
+ chdr = &chnk->aligned.header;
+ res = chdr->local.first;
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ if (res) {
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ chdr->local.first = res->next_ptr;
+ chdr->local.cnt--;
+ if (!chdr->local.first)
+ chdr->local.last = NULL;
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+ if (chdr->local.cnt <= chdr->local.lim)
+ return (char *) erts_sspa_process_remote_frees(chdr, res);
+ else if (chdr->head.no_thr_progress_check < ERTS_SSPA_FORCE_THR_CHECK_PROGRESS)
+ chdr->head.no_thr_progress_check++;
+ ASSERT(res);
+ return (char *) res;
+}
+
+ERTS_GLB_INLINE int
+erts_sspa_free(erts_sspa_data_t *data, int cix, char *cblk)
+{
+ erts_sspa_chunk_t *chnk;
+ erts_sspa_chunk_header_t *chdr;
+ erts_sspa_blk_t *blk = (erts_sspa_blk_t *) cblk;
+ int chnk_cix = erts_sspa_ptr2cix(data, blk);
+
+ if (chnk_cix < 0)
+ return 0;
+
+ chnk = erts_sspa_cix2chunk(data, chnk_cix);
+ chdr = &chnk->aligned.header;
+ if (chnk_cix != cix) {
+ /* Remote chunk */
+ erts_sspa_remote_free(chdr, blk, chnk_cix - cix);
+ }
+ else {
+ /* Local chunk */
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ blk->next_ptr = chdr->local.first;
+ chdr->local.first = blk;
+ if (!chdr->local.last)
+ chdr->local.last = blk;
+ chdr->local.cnt++;
+ ERTS_SSPA_DBG_CHK_LCL(chdr);
+ }
+
+ return 1;
+}
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
+#endif /* ERTS_SMP */
+
+#endif /* ERTS_SCHED_SPEC_PRE_ALLOC_H__ */
diff --git a/erts/emulator/beam/erl_smp.h b/erts/emulator/beam/erl_smp.h
index a89ddfbcc1..a32e9d9d7c 100644
--- a/erts/emulator/beam/erl_smp.h
+++ b/erts/emulator/beam/erl_smp.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2012. All Rights Reserved.
*
* The 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,6 +61,11 @@ typedef erts_spinlock_t erts_smp_spinlock_t;
typedef erts_rwlock_t erts_smp_rwlock_t;
void erts_thr_fatal_error(int, char *); /* implemented in erl_init.c */
+#define ERTS_SMP_MEMORY_BARRIER ERTS_THR_MEMORY_BARRIER
+#define ERTS_SMP_WRITE_MEMORY_BARRIER ERTS_THR_WRITE_MEMORY_BARRIER
+#define ERTS_SMP_READ_MEMORY_BARRIER ERTS_THR_READ_MEMORY_BARRIER
+#define ERTS_SMP_DATA_DEPENDENCY_READ_MEMORY_BARRIER ERTS_THR_DATA_DEPENDENCY_READ_MEMORY_BARRIER
+
#else /* #ifdef ERTS_SMP */
#define ERTS_SMP_THR_OPTS_DEFAULT_INITER {0}
@@ -95,6 +100,11 @@ typedef struct { int gcc_is_buggy; } erts_smp_spinlock_t;
typedef struct { int gcc_is_buggy; } erts_smp_rwlock_t;
#endif
+#define ERTS_SMP_MEMORY_BARRIER
+#define ERTS_SMP_WRITE_MEMORY_BARRIER
+#define ERTS_SMP_READ_MEMORY_BARRIER
+#define ERTS_SMP_DATA_DEPENDENCY_READ_MEMORY_BARRIER
+
#endif /* #ifdef ERTS_SMP */
ERTS_GLB_INLINE void erts_smp_thr_init(erts_smp_thr_init_data_t *id);
@@ -206,13 +216,8 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#endif /* #ifdef ERTS_THR_HAVE_SIG_FUNCS */
/*
- * Functions implementing atomic operations with with no (nob),
- * full (mb), acquire (acqb), release (relb), read (rb), and
- * write (wb) memory barriers.
- *
- * If SMP support has been disabled, they are mapped to functions
- * that performs the same operation, but aren't atomic and don't
- * imply memory barriers.
+ * See "Documentation of atomics and memory barriers" at the top
+ * of erl_threads.h for info on atomics.
*/
#ifdef ERTS_SMP
@@ -239,6 +244,11 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#define erts_smp_dw_atomic_read_relb erts_dw_atomic_read_relb
#define erts_smp_dw_atomic_cmpxchg_relb erts_dw_atomic_cmpxchg_relb
+#define erts_smp_dw_atomic_init_ddrb erts_dw_atomic_init_ddrb
+#define erts_smp_dw_atomic_set_ddrb erts_dw_atomic_set_ddrb
+#define erts_smp_dw_atomic_read_ddrb erts_dw_atomic_read_ddrb
+#define erts_smp_dw_atomic_cmpxchg_ddrb erts_dw_atomic_cmpxchg_ddrb
+
#define erts_smp_dw_atomic_init_rb erts_dw_atomic_init_rb
#define erts_smp_dw_atomic_set_rb erts_dw_atomic_set_rb
#define erts_smp_dw_atomic_read_rb erts_dw_atomic_read_rb
@@ -307,6 +317,20 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#define erts_smp_atomic_xchg_relb erts_atomic_xchg_relb
#define erts_smp_atomic_cmpxchg_relb erts_atomic_cmpxchg_relb
+#define erts_smp_atomic_init_ddrb erts_atomic_init_ddrb
+#define erts_smp_atomic_set_ddrb erts_atomic_set_ddrb
+#define erts_smp_atomic_read_ddrb erts_atomic_read_ddrb
+#define erts_smp_atomic_inc_read_ddrb erts_atomic_inc_read_ddrb
+#define erts_smp_atomic_dec_read_ddrb erts_atomic_dec_read_ddrb
+#define erts_smp_atomic_inc_ddrb erts_atomic_inc_ddrb
+#define erts_smp_atomic_dec_ddrb erts_atomic_dec_ddrb
+#define erts_smp_atomic_add_read_ddrb erts_atomic_add_read_ddrb
+#define erts_smp_atomic_add_ddrb erts_atomic_add_ddrb
+#define erts_smp_atomic_read_bor_ddrb erts_atomic_read_bor_ddrb
+#define erts_smp_atomic_read_band_ddrb erts_atomic_read_band_ddrb
+#define erts_smp_atomic_xchg_ddrb erts_atomic_xchg_ddrb
+#define erts_smp_atomic_cmpxchg_ddrb erts_atomic_cmpxchg_ddrb
+
#define erts_smp_atomic_init_rb erts_atomic_init_rb
#define erts_smp_atomic_set_rb erts_atomic_set_rb
#define erts_smp_atomic_read_rb erts_atomic_read_rb
@@ -393,6 +417,20 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#define erts_smp_atomic32_xchg_relb erts_atomic32_xchg_relb
#define erts_smp_atomic32_cmpxchg_relb erts_atomic32_cmpxchg_relb
+#define erts_smp_atomic32_init_ddrb erts_atomic32_init_ddrb
+#define erts_smp_atomic32_set_ddrb erts_atomic32_set_ddrb
+#define erts_smp_atomic32_read_ddrb erts_atomic32_read_ddrb
+#define erts_smp_atomic32_inc_read_ddrb erts_atomic32_inc_read_ddrb
+#define erts_smp_atomic32_dec_read_ddrb erts_atomic32_dec_read_ddrb
+#define erts_smp_atomic32_inc_ddrb erts_atomic32_inc_ddrb
+#define erts_smp_atomic32_dec_ddrb erts_atomic32_dec_ddrb
+#define erts_smp_atomic32_add_read_ddrb erts_atomic32_add_read_ddrb
+#define erts_smp_atomic32_add_ddrb erts_atomic32_add_ddrb
+#define erts_smp_atomic32_read_bor_ddrb erts_atomic32_read_bor_ddrb
+#define erts_smp_atomic32_read_band_ddrb erts_atomic32_read_band_ddrb
+#define erts_smp_atomic32_xchg_ddrb erts_atomic32_xchg_ddrb
+#define erts_smp_atomic32_cmpxchg_ddrb erts_atomic32_cmpxchg_ddrb
+
#define erts_smp_atomic32_init_rb erts_atomic32_init_rb
#define erts_smp_atomic32_set_rb erts_atomic32_set_rb
#define erts_smp_atomic32_read_rb erts_atomic32_read_rb
@@ -445,6 +483,11 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#define erts_smp_dw_atomic_read_relb erts_no_dw_atomic_read
#define erts_smp_dw_atomic_cmpxchg_relb erts_no_dw_atomic_cmpxchg
+#define erts_smp_dw_atomic_init_ddrb erts_no_dw_atomic_init
+#define erts_smp_dw_atomic_set_ddrb erts_no_dw_atomic_set
+#define erts_smp_dw_atomic_read_ddrb erts_no_dw_atomic_read
+#define erts_smp_dw_atomic_cmpxchg_ddrb erts_no_dw_atomic_cmpxchg
+
#define erts_smp_dw_atomic_init_rb erts_no_dw_atomic_init
#define erts_smp_dw_atomic_set_rb erts_no_dw_atomic_set
#define erts_smp_dw_atomic_read_rb erts_no_dw_atomic_read
@@ -513,6 +556,20 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#define erts_smp_atomic_xchg_relb erts_no_atomic_xchg
#define erts_smp_atomic_cmpxchg_relb erts_no_atomic_cmpxchg
+#define erts_smp_atomic_init_ddrb erts_no_atomic_set
+#define erts_smp_atomic_set_ddrb erts_no_atomic_set
+#define erts_smp_atomic_read_ddrb erts_no_atomic_read
+#define erts_smp_atomic_inc_read_ddrb erts_no_atomic_inc_read
+#define erts_smp_atomic_dec_read_ddrb erts_no_atomic_dec_read
+#define erts_smp_atomic_inc_ddrb erts_no_atomic_inc
+#define erts_smp_atomic_dec_ddrb erts_no_atomic_dec
+#define erts_smp_atomic_add_read_ddrb erts_no_atomic_add_read
+#define erts_smp_atomic_add_ddrb erts_no_atomic_add
+#define erts_smp_atomic_read_bor_ddrb erts_no_atomic_read_bor
+#define erts_smp_atomic_read_band_ddrb erts_no_atomic_read_band
+#define erts_smp_atomic_xchg_ddrb erts_no_atomic_xchg
+#define erts_smp_atomic_cmpxchg_ddrb erts_no_atomic_cmpxchg
+
#define erts_smp_atomic_init_rb erts_no_atomic_set
#define erts_smp_atomic_set_rb erts_no_atomic_set
#define erts_smp_atomic_read_rb erts_no_atomic_read
@@ -599,6 +656,20 @@ ERTS_GLB_INLINE void erts_smp_thr_sigwait(const sigset_t *set, int *sig);
#define erts_smp_atomic32_xchg_relb erts_no_atomic32_xchg
#define erts_smp_atomic32_cmpxchg_relb erts_no_atomic32_cmpxchg
+#define erts_smp_atomic32_init_ddrb erts_no_atomic32_set
+#define erts_smp_atomic32_set_ddrb erts_no_atomic32_set
+#define erts_smp_atomic32_read_ddrb erts_no_atomic32_read
+#define erts_smp_atomic32_inc_read_ddrb erts_no_atomic32_inc_read
+#define erts_smp_atomic32_dec_read_ddrb erts_no_atomic32_dec_read
+#define erts_smp_atomic32_inc_ddrb erts_no_atomic32_inc
+#define erts_smp_atomic32_dec_ddrb erts_no_atomic32_dec
+#define erts_smp_atomic32_add_read_ddrb erts_no_atomic32_add_read
+#define erts_smp_atomic32_add_ddrb erts_no_atomic32_add
+#define erts_smp_atomic32_read_bor_ddrb erts_no_atomic32_read_bor
+#define erts_smp_atomic32_read_band_ddrb erts_no_atomic32_read_band
+#define erts_smp_atomic32_xchg_ddrb erts_no_atomic32_xchg
+#define erts_smp_atomic32_cmpxchg_ddrb erts_no_atomic32_cmpxchg
+
#define erts_smp_atomic32_init_rb erts_no_atomic32_set
#define erts_smp_atomic32_set_rb erts_no_atomic32_set
#define erts_smp_atomic32_read_rb erts_no_atomic32_read
@@ -822,6 +893,16 @@ erts_smp_cnd_wait(erts_smp_cnd_t *cnd, erts_smp_mtx_t *mtx)
#endif
}
+/*
+ * IMPORTANT note about erts_smp_cnd_signal() and erts_smp_cnd_broadcast()
+ *
+ * POSIX allow a call to `pthread_cond_signal' or `pthread_cond_broadcast'
+ * even though the associated mutex/mutexes isn't/aren't locked by the
+ * caller. Our implementation do not allow that in order to avoid a
+ * performance penalty. That is, all associated mutexes *need* to be
+ * locked by the caller of erts_smp_cnd_signal()/erts_smp_cnd_broadcast()!
+ */
+
ERTS_GLB_INLINE void
erts_smp_cnd_signal(erts_smp_cnd_t *cnd)
{
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 1d75fa313c..c270d13365 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -253,15 +253,15 @@ _ET_DECLARE_CHECKED(Eterm*,list_val,Wterm)
#define SMALL_BITS (28)
#define SMALL_DIGITS (8)
#endif
-#define MAX_SMALL ((1L << (SMALL_BITS-1))-1)
-#define MIN_SMALL (-(1L << (SMALL_BITS-1)))
+#define MAX_SMALL ((SWORD_CONSTANT(1) << (SMALL_BITS-1))-1)
+#define MIN_SMALL (-(SWORD_CONSTANT(1) << (SMALL_BITS-1)))
#define make_small(x) (((Uint)(x) << _TAG_IMMED1_SIZE) + _TAG_IMMED1_SMALL)
#define is_small(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
#define is_not_small(x) (!is_small((x)))
#define is_byte(x) (((x) & ((~(Uint)0 << (_TAG_IMMED1_SIZE+8)) + _TAG_IMMED1_MASK)) == _TAG_IMMED1_SMALL)
#define is_valid_bit_size(x) (((Sint)(x)) >= 0 && ((x) & 0x7F) == _TAG_IMMED1_SMALL)
#define is_not_valid_bit_size(x) (!is_valid_bit_size((x)))
-#define MY_IS_SSMALL(x) (((Uint) (((x) >> (SMALL_BITS-1)) + 1)) < 2)
+#define MY_IS_SSMALL(x) (((Uint) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2)
#define _unchecked_unsigned_val(x) ((x) >> _TAG_IMMED1_SIZE)
_ET_DECLARE_CHECKED(Uint,unsigned_val,Eterm)
#define unsigned_val(x) _ET_APPLY(unsigned_val,(x))
@@ -331,7 +331,13 @@ _ET_DECLARE_CHECKED(Uint,thing_subtag,Eterm)
* we now use a non-zero bit-pattern in debug mode.
*/
#if ET_DEBUG
-#define THE_NON_VALUE _make_header(0,_TAG_HEADER_FLOAT)
+# ifdef HIPE
+ /* A very large (or negative) value as work-around for ugly hipe-bifs
+ that return untagged integers (eg hipe_bs_put_utf8) */
+# define THE_NON_VALUE _make_header((Uint)~0,_TAG_HEADER_FLOAT)
+# else
+# define THE_NON_VALUE _make_header(0,_TAG_HEADER_FLOAT)
+# endif
#else
#define THE_NON_VALUE (0)
#endif
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
new file mode 100644
index 0000000000..88524bdd4c
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -0,0 +1,1377 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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: Thread progress information. Used by lock free algorithms
+ * to determine when all involved threads are guaranteed to
+ * have passed a specific point of execution.
+ *
+ * Usage instructions below.
+ *
+ * Author: Rickard Green
+ */
+
+/*
+ * ------ Usage instructions -----------------------------------------------
+ *
+ * This module keeps track of the progress of a set of managed threads. Only
+ * threads that behave well can be allowed to be managed. A managed thread
+ * should update its thread progress frequently. Currently only scheduler
+ * threads, the system-message-dispatcher threads, and the aux-thread are
+ * managed threads. We typically do not want any async threads as managed
+ * threads since they cannot guarantee a frequent update of thread progress,
+ * since they execute user implemented driver code that is assumed to be
+ * time consuming.
+ *
+ * erts_thr_progress_current() returns the global current thread progress
+ * value of managed threads. I.e., the latest progress value that all
+ * managed threads have reached. Thread progress values are opaque.
+ *
+ * erts_thr_progress_has_reached(VAL) returns a value != 0 if current
+ * global thread progress has reached or passed VAL.
+ *
+ * erts_thr_progress_later() returns a thread progress value in the future
+ * which no managed thread have yet reached.
+ *
+ * All threads issue a full memory barrier when reaching a new thread
+ * progress value. They only reach new thread progress values in specific
+ * controlled states when calling erts_thr_progress_update(). Schedulers
+ * call erts_thr_progress_update() in between execution of processes,
+ * when going to sleep and when waking up.
+ *
+ * Sleeping managed threads are considered to have reached next thread
+ * progress value immediately. They are not woken and do therefore not
+ * issue any memory barriers when reaching a new thread progress value.
+ * A sleeping thread do however immediately issue a memory barrier upon
+ * wakeup.
+ *
+ * Both managed and registered unmanaged threads may request wakeup when
+ * the global thread progress reach a certain value using
+ * erts_thr_progress_wakeup().
+ *
+ * Note that thread progress values are opaque, and that you are only
+ * allowed to use thread progress values retrieved from this API!
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stddef.h> /* offsetof() */
+#include "erl_thr_progress.h"
+#include "global.h"
+
+#ifdef ERTS_SMP
+
+#define ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE 0
+
+#ifdef DEBUG
+#undef ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE
+#define ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE 1
+#endif
+
+#define ERTS_THR_PRGR_PRINT_LEADER 0
+#define ERTS_THR_PRGR_PRINT_VAL 0
+#define ERTS_THR_PRGR_PRINT_BLOCKERS 0
+
+#define ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL 100
+
+#define ERTS_THR_PRGR_LFLG_BLOCK (((erts_aint32_t) 1) << 31)
+#define ERTS_THR_PRGR_LFLG_NO_LEADER (((erts_aint32_t) 1) << 30)
+#define ERTS_THR_PRGR_LFLG_ACTIVE_MASK (~(ERTS_THR_PRGR_LFLG_NO_LEADER \
+ | ERTS_THR_PRGR_LFLG_BLOCK))
+
+#define ERTS_THR_PRGR_LFLGS_ACTIVE(LFLGS) \
+ ((LFLGS) & ERTS_THR_PRGR_LFLG_ACTIVE_MASK)
+
+#define ERTS_THR_PRGR_LFLGS_ALL_WAITING(LFLGS) \
+ (((LFLGS) & (ERTS_THR_PRGR_LFLG_NO_LEADER \
+ |ERTS_THR_PRGR_LFLG_ACTIVE_MASK)) \
+ == ERTS_THR_PRGR_LFLG_NO_LEADER)
+
+/*
+ * We use a 64-bit value for thread progress. By this wrapping of
+ * the thread progress will more or less never occur.
+ *
+ * On 32-bit systems we therefore need a double word atomic.
+ */
+#undef read_acqb
+#define read_acqb erts_thr_prgr_read_acqb__
+#undef read_nob
+#define read_nob erts_thr_prgr_read_nob__
+
+#ifdef ARCH_64
+
+static ERTS_INLINE void
+set_mb(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_atomic_set_mb(atmc, val);
+}
+
+static ERTS_INLINE void
+set_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_atomic_set_nob(atmc, val);
+}
+
+static ERTS_INLINE void
+init_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_atomic_init_nob(atmc, val);
+}
+
+#else
+
+#undef dw_aint_to_val
+#define dw_aint_to_val erts_thr_prgr_dw_aint_to_val__
+
+static void
+val_to_dw_aint(erts_dw_aint_t *dw_aint, ErtsThrPrgrVal val)
+{
+#ifdef ETHR_SU_DW_NAINT_T__
+ dw_aint->dw_sint = (ETHR_SU_DW_NAINT_T__) val;
+#else
+ dw_aint->sint[ERTS_DW_AINT_LOW_WORD]
+ = (erts_aint_t) (val & 0xffffffff);
+ dw_aint->sint[ERTS_DW_AINT_HIGH_WORD]
+ = (erts_aint_t) ((val >> 32) & 0xffffffff);
+#endif
+}
+
+static ERTS_INLINE void
+set_mb(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_dw_aint_t dw_aint;
+ val_to_dw_aint(&dw_aint, val);
+ erts_dw_atomic_set_mb(atmc, &dw_aint);
+}
+
+static ERTS_INLINE void
+set_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_dw_aint_t dw_aint;
+ val_to_dw_aint(&dw_aint, val);
+ erts_dw_atomic_set_nob(atmc, &dw_aint);
+}
+
+static ERTS_INLINE void
+init_nob(ERTS_THR_PRGR_ATOMIC *atmc, ErtsThrPrgrVal val)
+{
+ erts_dw_aint_t dw_aint;
+ val_to_dw_aint(&dw_aint, val);
+ erts_dw_atomic_init_nob(atmc, &dw_aint);
+}
+
+#endif
+
+/* #define ERTS_THR_PROGRESS_STATE_DEBUG */
+
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+
+#ifdef __GNUC__
+#warning "Thread progress state debug is on"
+#endif
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_LEADER (((erts_aint32_t) 1) << 0)
+#define ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE (((erts_aint32_t) 1) << 1)
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_INIT(ID) \
+ erts_atomic32_init_nob(&intrnl->thr[(ID)].data.state_debug, \
+ ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE)
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(ID, ON) \
+do { \
+ erts_aint32_t state_debug__; \
+ state_debug__ = erts_atomic32_read_nob(&intrnl->thr[(ID)].data.state_debug); \
+ if ((ON)) \
+ state_debug__ |= ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE; \
+ else \
+ state_debug__ &= ~ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE; \
+ erts_atomic32_set_nob(&intrnl->thr[(ID)].data.state_debug, state_debug__); \
+} while (0)
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(ID, ON) \
+do { \
+ erts_aint32_t state_debug__; \
+ state_debug__ = erts_atomic32_read_nob(&intrnl->thr[(ID)].data.state_debug); \
+ if ((ON)) \
+ state_debug__ |= ERTS_THR_PROGRESS_STATE_DEBUG_LEADER; \
+ else \
+ state_debug__ &= ~ERTS_THR_PROGRESS_STATE_DEBUG_LEADER; \
+ erts_atomic32_set_nob(&intrnl->thr[(ID)].data.state_debug, state_debug__); \
+} while (0)
+
+#else
+
+#define ERTS_THR_PROGRESS_STATE_DEBUG_INIT(ID)
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(ID, ON)
+#define ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(ID, ON)
+
+#endif /* ERTS_THR_PROGRESS_STATE_DEBUG */
+
+#define ERTS_THR_PRGR_BLCKR_INVALID (~((erts_aint32_t) 0))
+#define ERTS_THR_PRGR_BLCKR_UNMANAGED (((erts_aint32_t) 1) << 31)
+
+#define ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING (((erts_aint32_t) 1) << 31)
+
+#define ERTS_THR_PRGR_BM_BITS 32
+#define ERTS_THR_PRGR_BM_SHIFT 5
+#define ERTS_THR_PRGR_BM_MASK 0x1f
+
+#define ERTS_THR_PRGR_WAKEUP_DATA_MASK (ERTS_THR_PRGR_WAKEUP_DATA_SIZE - 1)
+
+#define ERTS_THR_PRGR_WAKEUP_IX(V) \
+ ((int) ((V) & ERTS_THR_PRGR_WAKEUP_DATA_MASK))
+
+typedef struct {
+ erts_atomic32_t len;
+ int id[1];
+} ErtsThrPrgrManagedWakeupData;
+
+typedef struct {
+ erts_atomic32_t len;
+ int high_sz;
+ int low_sz;
+ erts_atomic32_t *high;
+ erts_atomic32_t *low;
+} ErtsThrPrgrUnmanagedWakeupData;
+
+typedef struct {
+ erts_atomic32_t lflgs;
+ erts_atomic32_t block_count;
+ erts_atomic_t blocker_event;
+ erts_atomic32_t pref_wakeup_used;
+ erts_atomic32_t managed_count;
+ erts_atomic32_t managed_id;
+ erts_atomic32_t unmanaged_id;
+} ErtsThrPrgrMiscData;
+
+typedef struct {
+ ERTS_THR_PRGR_ATOMIC current;
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ erts_atomic32_t state_debug;
+#endif
+} ErtsThrPrgrElement;
+
+typedef union {
+ ErtsThrPrgrElement data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrPrgrElement))];
+} ErtsThrPrgrArray;
+
+typedef struct {
+ union {
+ ErtsThrPrgrMiscData data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(
+ sizeof(ErtsThrPrgrMiscData))];
+ } misc;
+ ErtsThrPrgrArray *thr;
+ struct {
+ int no;
+ ErtsThrPrgrCallbacks *callbacks;
+ ErtsThrPrgrManagedWakeupData *data[ERTS_THR_PRGR_WAKEUP_DATA_SIZE];
+ } managed;
+ struct {
+ int no;
+ ErtsThrPrgrCallbacks *callbacks;
+ ErtsThrPrgrUnmanagedWakeupData *data[ERTS_THR_PRGR_WAKEUP_DATA_SIZE];
+ } unmanaged;
+} ErtsThrPrgrInternalData;
+
+static ErtsThrPrgrInternalData *intrnl;
+
+ErtsThrPrgr erts_thr_prgr__;
+
+erts_tsd_key_t erts_thr_prgr_data_key__;
+
+static void handle_wakeup_requests(ErtsThrPrgrVal current);
+static int got_sched_wakeups(void);
+static erts_aint32_t block_thread(ErtsThrPrgrData *tpd);
+
+static ERTS_INLINE void
+wakeup_managed(int id)
+{
+ ErtsThrPrgrCallbacks *cbp = &intrnl->managed.callbacks[id];
+ ASSERT(0 <= id && id < intrnl->managed.no);
+ cbp->wakeup(cbp->arg);
+}
+
+
+static ERTS_INLINE void
+wakeup_unmanaged(int id)
+{
+ ErtsThrPrgrCallbacks *cbp = &intrnl->unmanaged.callbacks[id];
+ ASSERT(0 <= id && id < intrnl->unmanaged.no);
+ cbp->wakeup(cbp->arg);
+}
+
+static ERTS_INLINE ErtsThrPrgrData *
+perhaps_thr_prgr_data(ErtsSchedulerData *esdp)
+{
+ if (esdp)
+ return &esdp->thr_progress_data;
+ else
+ return erts_tsd_get(erts_thr_prgr_data_key__);
+}
+
+static ERTS_INLINE ErtsThrPrgrData *
+thr_prgr_data(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(esdp);
+ ASSERT(tpd);
+ return tpd;
+}
+
+static void
+init_tmp_thr_prgr_data(ErtsThrPrgrData *tpd)
+{
+ tpd->id = -1;
+ tpd->is_managed = 0;
+ tpd->is_blocking = 0;
+ tpd->is_temporary = 1;
+
+ erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd);
+}
+
+static ERTS_INLINE ErtsThrPrgrData *
+tmp_thr_prgr_data(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(esdp);
+
+ if (!tpd) {
+ /*
+ * We only allocate the part up to the wakeup_request field
+ * which is the first field only used by registered threads
+ */
+ tpd = erts_alloc(ERTS_ALC_T_T_THR_PRGR_DATA,
+ offsetof(ErtsThrPrgrData, wakeup_request));
+ init_tmp_thr_prgr_data(tpd);
+ }
+
+ return tpd;
+}
+
+static ERTS_INLINE void
+return_tmp_thr_prgr_data(ErtsThrPrgrData *tpd)
+{
+ if (tpd->is_temporary) {
+ erts_tsd_set(erts_thr_prgr_data_key__, NULL);
+ erts_free(ERTS_ALC_T_T_THR_PRGR_DATA, tpd);
+ }
+}
+
+static ERTS_INLINE int
+block_count_dec(void)
+{
+ erts_aint32_t block_count;
+ block_count = erts_atomic32_dec_read_mb(&intrnl->misc.data.block_count);
+ if (block_count == 0) {
+ erts_tse_t *event;
+ event = ((erts_tse_t*)
+ erts_atomic_read_nob(&intrnl->misc.data.blocker_event));
+ if (event)
+ erts_tse_set(event);
+ return 1;
+ }
+
+ return (block_count & ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING) == 0;
+}
+
+static ERTS_INLINE int
+block_count_inc(void)
+{
+ erts_aint32_t block_count;
+ block_count = erts_atomic32_inc_read_mb(&intrnl->misc.data.block_count);
+ return (block_count & ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING) == 0;
+}
+
+
+void
+erts_thr_progress_pre_init(void)
+{
+ intrnl = NULL;
+ erts_tsd_key_create(&erts_thr_prgr_data_key__);
+ init_nob(&erts_thr_prgr__.current, 0);
+}
+
+void
+erts_thr_progress_init(int no_schedulers, int managed, int unmanaged)
+{
+ int i, j, um_low, um_high;
+ char *ptr;
+ size_t cb_sz, intrnl_sz, thr_arr_sz, m_wakeup_size, um_wakeup_size,
+ tot_size;
+
+ intrnl_sz = sizeof(ErtsThrPrgrInternalData);
+ intrnl_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(intrnl_sz);
+
+ cb_sz = sizeof(ErtsThrPrgrCallbacks)*(managed+unmanaged);
+ cb_sz = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(cb_sz);
+
+ thr_arr_sz = sizeof(ErtsThrPrgrArray)*managed;
+ ASSERT(thr_arr_sz == ERTS_ALC_CACHE_LINE_ALIGN_SIZE(thr_arr_sz));
+
+ m_wakeup_size = sizeof(ErtsThrPrgrManagedWakeupData);
+ m_wakeup_size += (managed - 1)*sizeof(int);
+ m_wakeup_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(m_wakeup_size);
+
+ um_low = (unmanaged - 1)/ERTS_THR_PRGR_BM_BITS + 1;
+ um_high = (um_low - 1)/ERTS_THR_PRGR_BM_BITS + 1;
+
+ um_wakeup_size = sizeof(ErtsThrPrgrUnmanagedWakeupData);
+ um_wakeup_size += (um_high + um_low)*sizeof(erts_atomic32_t);
+ um_wakeup_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(um_wakeup_size);
+
+ tot_size = intrnl_sz;
+ tot_size += cb_sz;
+ tot_size += thr_arr_sz;
+ tot_size += m_wakeup_size*ERTS_THR_PRGR_WAKEUP_DATA_SIZE;
+ tot_size += um_wakeup_size*ERTS_THR_PRGR_WAKEUP_DATA_SIZE;
+
+ ptr = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_THR_PRGR_IDATA,
+ tot_size);
+
+ intrnl = (ErtsThrPrgrInternalData *) ptr;
+ ptr += intrnl_sz;
+
+ erts_atomic32_init_nob(&intrnl->misc.data.lflgs,
+ ERTS_THR_PRGR_LFLG_NO_LEADER);
+ erts_atomic32_init_nob(&intrnl->misc.data.block_count,
+ (ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING
+ | (erts_aint32_t) managed));
+ erts_atomic_init_nob(&intrnl->misc.data.blocker_event, ERTS_AINT_NULL);
+ erts_atomic32_init_nob(&intrnl->misc.data.pref_wakeup_used, 0);
+ erts_atomic32_init_nob(&intrnl->misc.data.managed_count, 0);
+ erts_atomic32_init_nob(&intrnl->misc.data.managed_id, no_schedulers);
+ erts_atomic32_init_nob(&intrnl->misc.data.unmanaged_id, -1);
+
+ intrnl->thr = (ErtsThrPrgrArray *) ptr;
+ ptr += thr_arr_sz;
+ for (i = 0; i < managed; i++)
+ init_nob(&intrnl->thr[i].data.current, 0);
+
+ intrnl->managed.callbacks = (ErtsThrPrgrCallbacks *) ptr;
+ intrnl->unmanaged.callbacks = &intrnl->managed.callbacks[managed];
+ ptr += cb_sz;
+
+ intrnl->managed.no = managed;
+ for (i = 0; i < managed; i++) {
+ intrnl->managed.callbacks[i].arg = NULL;
+ intrnl->managed.callbacks[i].wakeup = NULL;
+ }
+
+ intrnl->unmanaged.no = unmanaged;
+ for (i = 0; i < unmanaged; i++) {
+ intrnl->unmanaged.callbacks[i].arg = NULL;
+ intrnl->unmanaged.callbacks[i].wakeup = NULL;
+ }
+
+ for (i = 0; i < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; i++) {
+ intrnl->managed.data[i] = (ErtsThrPrgrManagedWakeupData *) ptr;
+ erts_atomic32_init_nob(&intrnl->managed.data[i]->len, 0);
+ ptr += m_wakeup_size;
+ }
+
+ for (i = 0; i < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; i++) {
+ erts_atomic32_t *bm;
+ intrnl->unmanaged.data[i] = (ErtsThrPrgrUnmanagedWakeupData *) ptr;
+ erts_atomic32_init_nob(&intrnl->unmanaged.data[i]->len, 0);
+ bm = (erts_atomic32_t *) (ptr + sizeof(ErtsThrPrgrUnmanagedWakeupData));
+ intrnl->unmanaged.data[i]->high = bm;
+ intrnl->unmanaged.data[i]->high_sz = um_high;
+ for (j = 0; j < um_high; j++)
+ erts_atomic32_init_nob(&intrnl->unmanaged.data[i]->high[j], 0);
+ intrnl->unmanaged.data[i]->low
+ = &intrnl->unmanaged.data[i]->high[um_high];
+ intrnl->unmanaged.data[i]->low_sz = um_low;
+ for (j = 0; j < um_low; j++)
+ erts_atomic32_init_nob(&intrnl->unmanaged.data[i]->low[j], 0);
+ ptr += um_wakeup_size;
+ }
+ ERTS_THR_MEMORY_BARRIER;
+}
+
+static void
+init_wakeup_request_array(ErtsThrPrgrVal *w)
+{
+ int i;
+ ErtsThrPrgrVal current;
+
+ current = read_acqb(&erts_thr_prgr__.current);
+ for (i = 0; i < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; i++) {
+ w[i] = current - ((ErtsThrPrgrVal) (ERTS_THR_PRGR_WAKEUP_DATA_SIZE + i));
+ if (w[i] > current)
+ w[i]--;
+ }
+}
+
+void
+erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *callbacks)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ int is_blocking = 0;
+
+ if (tpd) {
+ if (!tpd->is_temporary)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Double register of thread\n",
+ __FILE__, __LINE__, __func__);
+ is_blocking = tpd->is_blocking;
+ return_tmp_thr_prgr_data(tpd);
+ }
+
+ /*
+ * We only allocate the part up to the leader field
+ * which is the first field only used by managed threads
+ */
+ tpd = erts_alloc(ERTS_ALC_T_THR_PRGR_DATA,
+ offsetof(ErtsThrPrgrData, leader));
+ tpd->id = (int) erts_atomic32_inc_read_nob(&intrnl->misc.data.unmanaged_id);
+ tpd->is_managed = 0;
+ tpd->is_blocking = is_blocking;
+ tpd->is_temporary = 0;
+ ASSERT(tpd->id >= 0);
+ if (tpd->id >= intrnl->unmanaged.no)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Too many unmanaged registered threads\n",
+ __FILE__, __LINE__, __func__);
+
+ init_wakeup_request_array(&tpd->wakeup_request[0]);
+ erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd);
+
+ ASSERT(callbacks->wakeup);
+
+ intrnl->unmanaged.callbacks[tpd->id] = *callbacks;
+}
+
+
+void
+erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp,
+ ErtsThrPrgrCallbacks *callbacks,
+ int pref_wakeup)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ int is_blocking = 0, managed;
+
+ if (tpd) {
+ if (!tpd->is_temporary)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Double register of thread\n",
+ __FILE__, __LINE__, __func__);
+ is_blocking = tpd->is_blocking;
+ return_tmp_thr_prgr_data(tpd);
+ }
+
+ if (esdp)
+ tpd = &esdp->thr_progress_data;
+ else
+ tpd = erts_alloc(ERTS_ALC_T_THR_PRGR_DATA, sizeof(ErtsThrPrgrData));
+
+ if (pref_wakeup
+ && !erts_atomic32_xchg_nob(&intrnl->misc.data.pref_wakeup_used, 1))
+ tpd->id = 0;
+ else if (esdp)
+ tpd->id = (int) esdp->no;
+ else
+ tpd->id = erts_atomic32_inc_read_nob(&intrnl->misc.data.managed_id);
+ ASSERT(tpd->id >= 0);
+ if (tpd->id >= intrnl->managed.no)
+ erl_exit(ERTS_ABORT_EXIT,
+ "%s:%d:%s(): Too many managed registered threads\n",
+ __FILE__, __LINE__, __func__);
+
+ tpd->is_managed = 1;
+ tpd->is_blocking = is_blocking;
+ tpd->is_temporary = 0;
+
+ init_wakeup_request_array(&tpd->wakeup_request[0]);
+
+ ERTS_THR_PROGRESS_STATE_DEBUG_INIT(tpd->id);
+
+ tpd->leader = 0;
+ tpd->active = 1;
+ tpd->previous.local = 0;
+ tpd->previous.current = ERTS_THR_PRGR_VAL_WAITING;
+ erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd);
+
+ erts_atomic32_inc_nob(&intrnl->misc.data.lflgs);
+
+ ASSERT(callbacks->wakeup);
+ ASSERT(callbacks->prepare_wait);
+ ASSERT(callbacks->wait);
+ ASSERT(callbacks->finalize_wait);
+
+ intrnl->managed.callbacks[tpd->id] = *callbacks;
+
+ callbacks->prepare_wait(callbacks->arg);
+ managed = erts_atomic32_inc_read_relb(&intrnl->misc.data.managed_count);
+ if (managed != intrnl->managed.no) {
+ /* Wait until all managed threads have registered... */
+ do {
+ callbacks->wait(callbacks->arg);
+ callbacks->prepare_wait(callbacks->arg);
+ managed = erts_atomic32_read_acqb(&intrnl->misc.data.managed_count);
+ } while (managed != intrnl->managed.no);
+ }
+ else {
+ int id;
+ /* All managed threads have registered; lets go... */
+ for (id = 0; id < managed; id++)
+ if (id != tpd->id)
+ wakeup_managed(id);
+ }
+ callbacks->finalize_wait(callbacks->arg);
+}
+
+static ERTS_INLINE int
+leader_update(ErtsThrPrgrData *tpd)
+{
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+ if (!tpd->leader) {
+ /* Probably need to block... */
+ block_thread(tpd);
+ }
+ else {
+ erts_aint32_t lflgs;
+ ErtsThrPrgrVal next;
+ int ix, sz, make_progress;
+
+ if (tpd->previous.current == ERTS_THR_PRGR_VAL_WAITING) {
+ /* Took over as leader from another thread */
+ tpd->previous.current = read_acqb(&erts_thr_prgr__.current);
+ tpd->previous.next = tpd->previous.current;
+ tpd->previous.next++;
+ if (tpd->previous.next == ERTS_THR_PRGR_VAL_WAITING)
+ tpd->previous.next = 0;
+ }
+
+ if (tpd->previous.local == tpd->previous.current) {
+ ErtsThrPrgrVal val = tpd->previous.current + 1;
+ if (val == ERTS_THR_PRGR_VAL_WAITING)
+ val = 0;
+ tpd->previous.local = val;
+ set_mb(&intrnl->thr[tpd->id].data.current, val);
+ }
+
+ next = tpd->previous.next;
+
+ make_progress = 1;
+ sz = intrnl->managed.no;
+ for (ix = 0; ix < sz; ix++) {
+ ErtsThrPrgrVal tmp;
+ tmp = read_nob(&intrnl->thr[ix].data.current);
+ if (tmp != next && tmp != ERTS_THR_PRGR_VAL_WAITING) {
+ make_progress = 0;
+ ASSERT(erts_thr_progress_has_passed__(next, tmp));
+ break;
+ }
+ }
+
+ if (make_progress) {
+ ErtsThrPrgrVal current = next;
+
+ next++;
+ if (next == ERTS_THR_PRGR_VAL_WAITING)
+ next = 0;
+
+ set_nob(&intrnl->thr[tpd->id].data.current, next);
+ set_mb(&erts_thr_prgr__.current, current);
+ tpd->previous.local = next;
+ tpd->previous.next = next;
+ tpd->previous.current = current;
+
+#if ERTS_THR_PRGR_PRINT_VAL
+ if (current % 1000 == 0)
+ erts_fprintf(stderr, "%b64u\n", current);
+#endif
+ handle_wakeup_requests(current);
+ }
+
+ if (tpd->active) {
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ (void) block_thread(tpd);
+ }
+ else {
+ tpd->leader = 0;
+ tpd->previous.current = ERTS_THR_PRGR_VAL_WAITING;
+#if ERTS_THR_PRGR_PRINT_LEADER
+ erts_fprintf(stderr, "L <- %d\n", tpd->id);
+#endif
+
+ ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(tpd->id, 0);
+
+ lflgs = erts_atomic32_read_bor_relb(&intrnl->misc.data.lflgs,
+ ERTS_THR_PRGR_LFLG_NO_LEADER);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ lflgs = block_thread(tpd);
+ if (ERTS_THR_PRGR_LFLGS_ACTIVE(lflgs) == 0 && got_sched_wakeups())
+ wakeup_managed(0);
+ }
+ }
+
+ return tpd->leader;
+}
+
+static int
+update(ErtsThrPrgrData *tpd)
+{
+ int res;
+ ErtsThrPrgrVal val;
+
+ if (tpd->leader)
+ res = 1;
+ else {
+ erts_aint32_t lflgs;
+ res = 0;
+ val = read_acqb(&erts_thr_prgr__.current);
+ if (tpd->previous.local == val) {
+ val++;
+ if (val == ERTS_THR_PRGR_VAL_WAITING)
+ val = 0;
+ tpd->previous.local = val;
+ set_mb(&intrnl->thr[tpd->id].data.current, val);
+ }
+
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ res = 1; /* Need to block in leader_update() */
+
+ if ((lflgs & ERTS_THR_PRGR_LFLG_NO_LEADER)
+ && (tpd->active || ERTS_THR_PRGR_LFLGS_ACTIVE(lflgs) == 0)) {
+ /* Try to take over leadership... */
+ erts_aint32_t olflgs;
+ olflgs = erts_atomic32_read_band_acqb(
+ &intrnl->misc.data.lflgs,
+ ~ERTS_THR_PRGR_LFLG_NO_LEADER);
+ if (olflgs & ERTS_THR_PRGR_LFLG_NO_LEADER) {
+ tpd->leader = 1;
+#if ERTS_THR_PRGR_PRINT_LEADER
+ erts_fprintf(stderr, "L -> %d\n", tpd->id);
+#endif
+ ERTS_THR_PROGRESS_STATE_DEBUG_SET_LEADER(tpd->id, 1);
+ }
+ }
+ res |= tpd->leader;
+ }
+ return res;
+}
+
+int
+erts_thr_progress_update(ErtsSchedulerData *esdp)
+{
+ return update(thr_prgr_data(esdp));
+}
+
+
+int
+erts_thr_progress_leader_update(ErtsSchedulerData *esdp)
+{
+ return leader_update(thr_prgr_data(esdp));
+}
+
+void
+erts_thr_progress_prepare_wait(ErtsSchedulerData *esdp)
+{
+ erts_aint32_t lflgs;
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+
+ block_count_dec();
+
+ tpd->previous.local = ERTS_THR_PRGR_VAL_WAITING;
+ set_mb(&intrnl->thr[tpd->id].data.current, ERTS_THR_PRGR_VAL_WAITING);
+
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (ERTS_THR_PRGR_LFLGS_ALL_WAITING(lflgs) && got_sched_wakeups())
+ wakeup_managed(0); /* Someone need to make progress */
+}
+
+void
+erts_thr_progress_finalize_wait(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+ ErtsThrPrgrVal current, val;
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+
+ /*
+ * We aren't allowed to continue until our thread
+ * progress is past global current.
+ */
+ val = current = read_acqb(&erts_thr_prgr__.current);
+ while (1) {
+ val++;
+ if (val == ERTS_THR_PRGR_VAL_WAITING)
+ val = 0;
+ tpd->previous.local = val;
+ set_mb(&intrnl->thr[tpd->id].data.current, val);
+ val = read_acqb(&erts_thr_prgr__.current);
+ if (current == val)
+ break;
+ current = val;
+ }
+ if (block_count_inc())
+ block_thread(tpd);
+ if (update(tpd))
+ leader_update(tpd);
+}
+
+void
+erts_thr_progress_active(ErtsSchedulerData *esdp, int on)
+{
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ erts_lc_check_exact(NULL, 0);
+#endif
+
+ ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(tpd->id, on);
+
+ if (on) {
+ ASSERT(!tpd->active);
+ tpd->active = 1;
+ erts_atomic32_inc_nob(&intrnl->misc.data.lflgs);
+ }
+ else {
+ ASSERT(tpd->active);
+ tpd->active = 0;
+ erts_atomic32_dec_nob(&intrnl->misc.data.lflgs);
+ if (update(tpd))
+ leader_update(tpd);
+ }
+
+#ifdef DEBUG
+ {
+ erts_aint32_t n = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ n &= ERTS_THR_PRGR_LFLG_ACTIVE_MASK;
+ ASSERT(tpd->active <= n && n <= intrnl->managed.no);
+ }
+#endif
+
+}
+
+static ERTS_INLINE int
+has_reached_wakeup(ErtsThrPrgrVal wakeup)
+{
+ /*
+ * Exactly the same as erts_thr_progress_has_reached(), but
+ * also verify valid wakeup requests in debug mode.
+ */
+ ErtsThrPrgrVal current;
+
+ current = read_acqb(&erts_thr_prgr__.current);
+
+#if ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE
+ {
+ ErtsThrPrgrVal limit;
+ /*
+ * erts_thr_progress_later() returns values which are
+ * equal to 'current + 2', or 'current + 3'. That is, users
+ * should never get a hold of values larger than that.
+ *
+ * That is, valid values are values less than 'current + 4'.
+ *
+ * Values larger than this won't work with the wakeup
+ * algorithm.
+ */
+
+ limit = current + 4;
+ if (limit == ERTS_THR_PRGR_VAL_WAITING)
+ limit = 0;
+ else if (limit < current) /* Wrapped */
+ limit += 1;
+
+ if (!erts_thr_progress_has_passed__(limit, wakeup))
+ erl_exit(ERTS_ABORT_EXIT,
+ "Invalid wakeup request value found:"
+ " current=%b64u, wakeup=%b64u, limit=%b64u",
+ current, wakeup, limit);
+ }
+#endif
+
+ if (current == wakeup)
+ return 1;
+ return erts_thr_progress_has_passed__(current, wakeup);
+}
+
+static void
+request_wakeup_managed(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value)
+{
+ ErtsThrPrgrManagedWakeupData *mwd;
+ int ix, wix;
+
+ /*
+ * Only managed threads that aren't in waiting state
+ * are allowed to call this function.
+ */
+
+ ASSERT(tpd->is_managed);
+ ASSERT(tpd->previous.local != ERTS_THR_PRGR_VAL_WAITING);
+
+ if (has_reached_wakeup(value)) {
+ wakeup_managed(tpd->id);
+ return;
+ }
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(value);
+ if (tpd->wakeup_request[wix] == value)
+ return; /* Already got a request registered */
+
+ ASSERT(erts_thr_progress_has_passed__(value,
+ tpd->wakeup_request[wix]));
+
+
+ if (tpd->previous.local == value) {
+ /*
+ * We have already confirmed this value. We need to request
+ * wakeup for a value later than our latest confirmed value in
+ * order to prevent progress from reaching the requested value
+ * while we are writing the request.
+ *
+ * It is ok to move the wakeup request forward since the only
+ * guarantee we make (and can make) is that the thread will be
+ * woken some time *after* the requested value has been reached.
+ */
+ value++;
+ if (value == ERTS_THR_PRGR_VAL_WAITING)
+ value = 0;
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(value);
+ if (tpd->wakeup_request[wix] == value)
+ return; /* Already got a request registered */
+
+ ASSERT(erts_thr_progress_has_passed__(value,
+ tpd->wakeup_request[wix]));
+ }
+
+ tpd->wakeup_request[wix] = value;
+
+ mwd = intrnl->managed.data[wix];
+
+ ix = erts_atomic32_inc_read_nob(&mwd->len) - 1;
+#if ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE
+ if (ix >= intrnl->managed.no)
+ erl_exit(ERTS_ABORT_EXIT, "Internal error: Too many wakeup requests\n");
+#endif
+ mwd->id[ix] = tpd->id;
+
+ ASSERT(!erts_thr_progress_has_reached(value));
+
+ /*
+ * This thread is guarranteed to issue a full memory barrier:
+ * - after the request has been written, but
+ * - before the global thread progress reach the (possibly
+ * increased) requested wakeup value.
+ */
+}
+
+static void
+request_wakeup_unmanaged(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value)
+{
+ int wix, ix, id, bit;
+ ErtsThrPrgrUnmanagedWakeupData *umwd;
+
+ ASSERT(!tpd->is_managed);
+
+ /*
+ * Thread progress *can* reach and pass our requested value while
+ * we are writing the request.
+ */
+
+ if (has_reached_wakeup(value)) {
+ wakeup_unmanaged(tpd->id);
+ return;
+ }
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(value);
+
+ if (tpd->wakeup_request[wix] == value)
+ return; /* Already got a request registered */
+
+ ASSERT(erts_thr_progress_has_passed__(value,
+ tpd->wakeup_request[wix]));
+
+ umwd = intrnl->unmanaged.data[wix];
+
+ id = tpd->id;
+
+ bit = id & ERTS_THR_PRGR_BM_MASK;
+ ix = id >> ERTS_THR_PRGR_BM_SHIFT;
+ ASSERT(0 <= ix && ix < umwd->low_sz);
+ erts_atomic32_read_bor_nob(&umwd->low[ix], 1 << bit);
+
+ bit = ix & ERTS_THR_PRGR_BM_MASK;
+ ix >>= ERTS_THR_PRGR_BM_SHIFT;
+ ASSERT(0 <= ix && ix < umwd->high_sz);
+ erts_atomic32_read_bor_nob(&umwd->high[ix], 1 << bit);
+
+ erts_atomic32_inc_mb(&umwd->len);
+
+ if (erts_thr_progress_has_reached(value))
+ wakeup_unmanaged(tpd->id);
+ else
+ tpd->wakeup_request[wix] = value;
+}
+
+void
+erts_thr_progress_wakeup(ErtsSchedulerData *esdp,
+ ErtsThrPrgrVal value)
+{
+ ErtsThrPrgrData *tpd = thr_prgr_data(esdp);
+ ASSERT(!tpd->is_temporary);
+ if (tpd->is_managed)
+ request_wakeup_managed(tpd, value);
+ else
+ request_wakeup_unmanaged(tpd, value);
+}
+
+static void
+wakeup_unmanaged_threads(ErtsThrPrgrUnmanagedWakeupData *umwd)
+{
+ int hix;
+ for (hix = 0; hix < umwd->high_sz; hix++) {
+ erts_aint32_t hmask = erts_atomic32_read_nob(&umwd->high[hix]);
+ if (hmask) {
+ int hbase = hix << ERTS_THR_PRGR_BM_SHIFT;
+ int hbit;
+ for (hbit = 0; hbit < ERTS_THR_PRGR_BM_BITS; hbit++) {
+ if (hmask & (1 << hbit)) {
+ erts_aint_t lmask;
+ int lix = hbase + hbit;
+ ASSERT(0 <= lix && lix < umwd->low_sz);
+ lmask = erts_atomic32_read_nob(&umwd->low[lix]);
+ if (lmask) {
+ int lbase = lix << ERTS_THR_PRGR_BM_SHIFT;
+ int lbit;
+ for (lbit = 0; lbit < ERTS_THR_PRGR_BM_BITS; lbit++) {
+ if (lmask & (1 << lbit)) {
+ int id = lbase + lbit;
+ wakeup_unmanaged(id);
+ }
+ }
+ erts_atomic32_set_nob(&umwd->low[lix], 0);
+ }
+ }
+ }
+ erts_atomic32_set_nob(&umwd->high[hix], 0);
+ }
+ }
+}
+
+
+static void
+handle_wakeup_requests(ErtsThrPrgrVal current)
+{
+ ErtsThrPrgrManagedWakeupData *mwd;
+ ErtsThrPrgrUnmanagedWakeupData *umwd;
+ int wix, len, i;
+
+ wix = ERTS_THR_PRGR_WAKEUP_IX(current);
+
+ mwd = intrnl->managed.data[wix];
+ len = erts_atomic32_read_nob(&mwd->len);
+ ASSERT(len >= 0);
+ if (len) {
+ for (i = 0; i < len; i++)
+ wakeup_managed(mwd->id[i]);
+ erts_atomic32_set_nob(&mwd->len, 0);
+ }
+
+ umwd = intrnl->unmanaged.data[wix];
+ len = erts_atomic32_read_nob(&umwd->len);
+ ASSERT(len >= 0);
+ if (len) {
+ wakeup_unmanaged_threads(umwd);
+ erts_atomic32_set_nob(&umwd->len, 0);
+ }
+
+}
+
+static int
+got_sched_wakeups(void)
+{
+ int wix;
+
+ ERTS_THR_MEMORY_BARRIER;
+
+ for (wix = 0; wix < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; wix++) {
+ ErtsThrPrgrManagedWakeupData **mwd = intrnl->managed.data;
+ if (erts_atomic32_read_nob(&mwd[wix]->len))
+ return 1;
+ }
+ for (wix = 0; wix < ERTS_THR_PRGR_WAKEUP_DATA_SIZE; wix++) {
+ ErtsThrPrgrUnmanagedWakeupData **umwd = intrnl->unmanaged.data;
+ if (erts_atomic32_read_nob(&umwd[wix]->len))
+ return 1;
+ }
+ return 0;
+}
+
+static erts_aint32_t
+block_thread(ErtsThrPrgrData *tpd)
+{
+ erts_aint32_t lflgs;
+ ErtsThrPrgrCallbacks *cbp = &intrnl->managed.callbacks[tpd->id];
+
+ do {
+ block_count_dec();
+
+ while (1) {
+ cbp->prepare_wait(cbp->arg);
+ lflgs = erts_atomic32_read_nob(&intrnl->misc.data.lflgs);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ cbp->wait(cbp->arg);
+ else
+ break;
+ }
+
+ } while (block_count_inc());
+
+ cbp->finalize_wait(cbp->arg);
+
+ return lflgs;
+}
+
+static erts_aint32_t
+thr_progress_block(ErtsThrPrgrData *tpd, int wait)
+{
+ erts_tse_t *event = NULL; /* Remove erroneous warning... sigh... */
+ erts_aint32_t lflgs, bc;
+
+ if (tpd->is_blocking++)
+ return (erts_aint32_t) 0;
+
+ while (1) {
+ lflgs = erts_atomic32_read_bor_nob(&intrnl->misc.data.lflgs,
+ ERTS_THR_PRGR_LFLG_BLOCK);
+ if (lflgs & ERTS_THR_PRGR_LFLG_BLOCK)
+ block_thread(tpd);
+ else
+ break;
+ }
+
+#if ERTS_THR_PRGR_PRINT_BLOCKERS
+ erts_fprintf(stderr, "block(%d)\n", tpd->id);
+#endif
+
+ ASSERT(ERTS_AINT_NULL
+ == erts_atomic_read_nob(&intrnl->misc.data.blocker_event));
+
+ if (wait) {
+ event = erts_tse_fetch();
+ erts_tse_reset(event);
+ erts_atomic_set_nob(&intrnl->misc.data.blocker_event,
+ (erts_aint_t) event);
+ }
+ if (tpd->is_managed)
+ erts_atomic32_dec_nob(&intrnl->misc.data.block_count);
+ bc = erts_atomic32_read_band_mb(&intrnl->misc.data.block_count,
+ ~ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING);
+ bc &= ~ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING;
+ if (wait) {
+ while (bc != 0) {
+ erts_tse_wait(event);
+ erts_tse_reset(event);
+ bc = erts_atomic32_read_acqb(&intrnl->misc.data.block_count);
+ }
+ }
+ return bc;
+
+}
+
+void
+erts_thr_progress_block(void)
+{
+ thr_progress_block(tmp_thr_prgr_data(NULL), 1);
+}
+
+void
+erts_thr_progress_fatal_error_block(SWord timeout,
+ ErtsThrPrgrData *tmp_tpd_bufp)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ erts_aint32_t bc;
+ SWord time_left = timeout;
+ SysTimeval to;
+
+ /*
+ * Counting poll intervals may give us a too long timeout
+ * if cpu is busy. If we got tolerant time of day we use it
+ * to prevent this.
+ */
+ if (!erts_disable_tolerant_timeofday) {
+ erts_get_timeval(&to);
+ to.tv_sec += timeout / 1000;
+ to.tv_sec += timeout % 1000;
+ }
+
+ if (!tpd) {
+ /*
+ * We stack allocate since failure to allocate memory may
+ * have caused the problem in the first place. This is ok
+ * since we never complete an unblock after a fatal error
+ * block.
+ */
+ tpd = tmp_tpd_bufp;
+ init_tmp_thr_prgr_data(tpd);
+ }
+
+ bc = thr_progress_block(tpd, 0);
+ if (bc == 0)
+ return; /* Succefully blocked all managed threads */
+
+ while (1) {
+ if (erts_milli_sleep(ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL) == 0)
+ time_left -= ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL;
+ bc = erts_atomic32_read_acqb(&intrnl->misc.data.block_count);
+ if (bc == 0)
+ break; /* Succefully blocked all managed threads */
+ if (time_left <= 0)
+ break; /* Timeout */
+ if (!erts_disable_tolerant_timeofday) {
+ SysTimeval now;
+ erts_get_timeval(&now);
+ if (now.tv_sec > to.tv_sec)
+ break; /* Timeout */
+ if (now.tv_sec == to.tv_sec && now.tv_usec >= to.tv_usec)
+ break; /* Timeout */
+ }
+ }
+}
+
+void
+erts_thr_progress_unblock(void)
+{
+ erts_tse_t *event;
+ int id, break_id, sz, wakeup;
+ ErtsThrPrgrData *tpd = thr_prgr_data(NULL);
+
+ ASSERT(tpd->is_blocking);
+ if (--tpd->is_blocking)
+ return;
+
+ sz = intrnl->managed.no;
+
+ wakeup = 1;
+ if (!tpd->is_managed)
+ id = break_id = tpd->id < 0 ? 0 : tpd->id % sz;
+ else {
+ break_id = tpd->id;
+ id = break_id + 1;
+ if (id >= sz)
+ id = 0;
+ if (id == break_id)
+ wakeup = 0;
+ erts_atomic32_inc_nob(&intrnl->misc.data.block_count);
+ }
+
+ event = ((erts_tse_t *)
+ erts_atomic_read_nob(&intrnl->misc.data.blocker_event));
+ ASSERT(event);
+ erts_atomic_set_nob(&intrnl->misc.data.blocker_event, ERTS_AINT_NULL);
+
+ erts_atomic32_read_bor_relb(&intrnl->misc.data.block_count,
+ ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING);
+#if ERTS_THR_PRGR_PRINT_BLOCKERS
+ erts_fprintf(stderr, "unblock(%d)\n", tpd->id);
+#endif
+ erts_atomic32_read_band_mb(&intrnl->misc.data.lflgs,
+ ~ERTS_THR_PRGR_LFLG_BLOCK);
+
+ if (wakeup) {
+ do {
+ ErtsThrPrgrVal tmp;
+ tmp = read_nob(&intrnl->thr[id].data.current);
+ if (tmp != ERTS_THR_PRGR_VAL_WAITING)
+ wakeup_managed(id);
+ if (++id >= sz)
+ id = 0;
+ } while (id != break_id);
+ }
+
+ return_tmp_thr_prgr_data(tpd);
+ erts_tse_return(event);
+}
+
+int
+erts_thr_progress_is_blocking(void)
+{
+ ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL);
+ return tpd && tpd->is_blocking;
+}
+
+void erts_thr_progress_dbg_print_state(void)
+{
+ int id;
+ int sz = intrnl->managed.no;
+
+ erts_fprintf(stderr, "--- thread progress ---\n");
+ erts_fprintf(stderr,"current=%b64u\n", erts_thr_progress_current());
+ for (id = 0; id < sz; id++) {
+ ErtsThrPrgrVal current = read_nob(&intrnl->thr[id].data.current);
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ erts_aint32_t state_debug;
+ char *active, *leader;
+
+ state_debug = erts_atomic32_read_nob(&intrnl->thr[id].data.state_debug);
+ active = (state_debug & ERTS_THR_PROGRESS_STATE_DEBUG_ACTIVE
+ ? "true"
+ : "false");
+ leader = (state_debug & ERTS_THR_PROGRESS_STATE_DEBUG_LEADER
+ ? "true"
+ : "false");
+#endif
+ if (current == ERTS_THR_PRGR_VAL_WAITING)
+ erts_fprintf(stderr,
+ " id=%d, current=WAITING"
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ ", active=%s, leader=%s"
+#endif
+ "\n", id
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ , active, leader
+#endif
+ );
+ else
+ erts_fprintf(stderr,
+ " id=%d, current=%b64u"
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ ", active=%s, leader=%s"
+#endif
+ "\n", id, current
+#ifdef ERTS_THR_PROGRESS_STATE_DEBUG
+ , active, leader
+#endif
+ );
+ }
+ erts_fprintf(stderr, "-----------------------\n");
+
+
+}
+
+#endif
diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h
new file mode 100644
index 0000000000..89486b065b
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_progress.h
@@ -0,0 +1,317 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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: Thread progress information. Used by lock free algorithms
+ * to determine when all involved threads are guaranteed to
+ * have passed a specific point of execution.
+ *
+ * Usage instructions can be found in ert_thr_progress.c
+ *
+ * Author: Rickard Green
+ */
+
+#if !defined(ERL_THR_PROGRESS_H__TSD_TYPE__)
+#define ERL_THR_PROGRESS_H__TSD_TYPE__
+
+#include "sys.h"
+
+#ifndef ERTS_SMP
+
+#define erts_smp_thr_progress_block() ((void) 0)
+#define erts_smp_thr_progress_unblock() ((void) 0)
+#define erts_smp_thr_progress_is_blocking() 1
+
+#else /* ERTS_SMP */
+
+#define erts_smp_thr_progress_block erts_thr_progress_block
+#define erts_smp_thr_progress_unblock erts_thr_progress_unblock
+#define erts_smp_thr_progress_is_blocking erts_thr_progress_is_blocking
+
+void erts_thr_progress_block(void);
+void erts_thr_progress_unblock(void);
+int erts_thr_progress_is_blocking(void);
+
+typedef Uint64 ErtsThrPrgrVal;
+
+#define ERTS_THR_PRGR_WAKEUP_DATA_SIZE 4 /* Need to be an even power of 2. */
+
+typedef struct {
+ int id;
+ int is_managed;
+ int is_blocking;
+ int is_temporary;
+
+ /* --- Part below only for registered threads --- */
+
+ ErtsThrPrgrVal wakeup_request[ERTS_THR_PRGR_WAKEUP_DATA_SIZE];
+
+ /* --- Part below only for managed threads --- */
+
+ int leader; /* Needs to be first in the managed threads part */
+ int active;
+ struct {
+ ErtsThrPrgrVal local;
+ ErtsThrPrgrVal next;
+ ErtsThrPrgrVal current;
+ } previous;
+} ErtsThrPrgrData;
+
+void erts_thr_progress_fatal_error_block(SWord timeout,
+ ErtsThrPrgrData *tmp_tpd_bufp);
+
+#endif /* ERTS_SMP */
+
+#endif
+
+#if !defined(ERL_THR_PROGRESS_H__) && !defined(ERL_THR_PROGRESS_TSD_TYPE_ONLY)
+#define ERL_THR_PROGRESS_H__
+
+#include "erl_threads.h"
+#include "erl_process.h"
+
+#ifdef ERTS_SMP
+
+#define ERTS_THR_PRGR_VAL_WAITING (~((ErtsThrPrgrVal) 0))
+#define ERTS_THR_PRGR_INVALID (~((ErtsThrPrgrVal) 0))
+
+extern erts_tsd_key_t erts_thr_prgr_data_key__;
+
+#ifdef ARCH_64
+# define ERTS_THR_PRGR_ATOMIC erts_atomic_t
+#else /* ARCH_32 */
+# define ERTS_THR_PRGR_ATOMIC erts_dw_atomic_t
+#endif
+
+typedef struct {
+ void *arg;
+ void (*wakeup)(void *);
+ void (*prepare_wait)(void *);
+ void (*wait)(void *);
+ void (*finalize_wait)(void *);
+} ErtsThrPrgrCallbacks;
+
+typedef struct {
+ ERTS_THR_PRGR_ATOMIC current;
+} ErtsThrPrgr;
+
+extern ErtsThrPrgr erts_thr_prgr__;
+
+void erts_thr_progress_pre_init(void);
+void erts_thr_progress_init(int no_schedulers, int managed, int unmanaged);
+void erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp,
+ ErtsThrPrgrCallbacks *,
+ int);
+void erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *);
+void erts_thr_progress_active(ErtsSchedulerData *esdp, int on);
+void erts_thr_progress_wakeup(ErtsSchedulerData *esdp,
+ ErtsThrPrgrVal value);
+int erts_thr_progress_update(ErtsSchedulerData *esdp);
+int erts_thr_progress_leader_update(ErtsSchedulerData *esdp);
+void erts_thr_progress_prepare_wait(ErtsSchedulerData *esdp);
+void erts_thr_progress_finalize_wait(ErtsSchedulerData *esdp);
+
+void erts_thr_progress_dbg_print_state(void);
+
+#ifdef ARCH_32
+#define ERTS_THR_PRGR_ATOMIC erts_dw_atomic_t
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_dw_aint_to_val__(erts_dw_aint_t *dw_aint);
+#endif
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_read_nob__(ERTS_THR_PRGR_ATOMIC *atmc);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *atmc);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_read_mb__(ERTS_THR_PRGR_ATOMIC *atmc);
+
+ERTS_GLB_INLINE int erts_thr_progress_is_managed_thread(void);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_current_to_later__(ErtsThrPrgrVal val);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_later(ErtsSchedulerData *);
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_current(void);
+ERTS_GLB_INLINE int erts_thr_progress_has_passed__(ErtsThrPrgrVal val1, ErtsThrPrgrVal val2);
+ERTS_GLB_INLINE int erts_thr_progress_has_reached_this(ErtsThrPrgrVal this, ErtsThrPrgrVal val);
+ERTS_GLB_INLINE int erts_thr_progress_equal(ErtsThrPrgrVal val1,
+ ErtsThrPrgrVal val2);
+ERTS_GLB_INLINE int erts_thr_progress_cmp(ErtsThrPrgrVal val1, ErtsThrPrgrVal val2);
+ERTS_GLB_INLINE int erts_thr_progress_has_reached(ErtsThrPrgrVal val);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+#ifdef ARCH_64
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_nob__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ return (ErtsThrPrgrVal) erts_atomic_read_nob(atmc);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ return (ErtsThrPrgrVal) erts_atomic_read_acqb(atmc);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_mb__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ return (ErtsThrPrgrVal) erts_atomic_read_mb(atmc);
+}
+
+#else /* ARCH_32 */
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_dw_aint_to_val__(erts_dw_aint_t *dw_aint)
+{
+#ifdef ETHR_SU_DW_NAINT_T__
+ return (ErtsThrPrgrVal) dw_aint->dw_sint;
+#else
+ ErtsThrPrgrVal res;
+ res = (ErtsThrPrgrVal) ((Uint32) dw_aint->sint[ERTS_DW_AINT_HIGH_WORD]);
+ res <<= 32;
+ res |= (ErtsThrPrgrVal) ((Uint32) dw_aint->sint[ERTS_DW_AINT_LOW_WORD]);
+ return res;
+#endif
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_nob__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ erts_dw_aint_t dw_aint;
+ erts_dw_atomic_read_nob(atmc, &dw_aint);
+ return erts_thr_prgr_dw_aint_to_val__(&dw_aint);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ erts_dw_aint_t dw_aint;
+ erts_dw_atomic_read_acqb(atmc, &dw_aint);
+ return erts_thr_prgr_dw_aint_to_val__(&dw_aint);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_prgr_read_mb__(ERTS_THR_PRGR_ATOMIC *atmc)
+{
+ erts_dw_aint_t dw_aint;
+ erts_dw_atomic_read_mb(atmc, &dw_aint);
+ return erts_thr_prgr_dw_aint_to_val__(&dw_aint);
+}
+
+#endif
+
+ERTS_GLB_INLINE int
+erts_thr_progress_is_managed_thread(void)
+{
+ ErtsThrPrgrData *tpd = erts_tsd_get(erts_thr_prgr_data_key__);
+ return tpd && tpd->is_managed;
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_progress_current_to_later__(ErtsThrPrgrVal val)
+{
+ if (val == (ERTS_THR_PRGR_VAL_WAITING-((ErtsThrPrgrVal)2)))
+ return ((ErtsThrPrgrVal) 0);
+ else if (val == (ERTS_THR_PRGR_VAL_WAITING-((ErtsThrPrgrVal)1)))
+ return ((ErtsThrPrgrVal) 1);
+ else
+ return val + ((ErtsThrPrgrVal) 2);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_progress_later(ErtsSchedulerData *esdp)
+{
+ ErtsThrPrgrData *tpd;
+ ErtsThrPrgrVal val;
+ if (esdp) {
+ tpd = &esdp->thr_progress_data;
+ managed_thread:
+ val = tpd->previous.local;
+ ERTS_THR_MEMORY_BARRIER;
+ }
+ else {
+ tpd = erts_tsd_get(erts_thr_prgr_data_key__);
+ if (tpd && tpd->is_managed)
+ goto managed_thread;
+ val = erts_thr_prgr_read_mb__(&erts_thr_prgr__.current);
+ }
+ ASSERT(val != ERTS_THR_PRGR_VAL_WAITING);
+ return erts_thr_progress_current_to_later__(val);
+}
+
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_progress_current(void)
+{
+ if (erts_thr_progress_is_managed_thread())
+ return erts_thr_prgr_read_nob__(&erts_thr_prgr__.current);
+ else
+ return erts_thr_prgr_read_acqb__(&erts_thr_prgr__.current);
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_has_passed__(ErtsThrPrgrVal val1, ErtsThrPrgrVal val0)
+{
+ if ((((((ErtsThrPrgrVal) 1) << 63) & val1)
+ ^ ((((ErtsThrPrgrVal) 1) << 63) & val0)) != 0) {
+ /* May have wrapped... */
+ if (val1 < (((ErtsThrPrgrVal) 1) << 62)
+ && val0 > (((ErtsThrPrgrVal) 3) << 62)) {
+ /*
+ * 'val1' has wrapped but 'val0' has not yet wrapped. While in
+ * these ranges 'current' is considered later than 'val0'.
+ */
+ return 1;
+ }
+ }
+ return val1 > val0;
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_has_reached_this(ErtsThrPrgrVal this, ErtsThrPrgrVal val)
+{
+ if (this == val)
+ return 1;
+ return erts_thr_progress_has_passed__(this, val);
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_equal(ErtsThrPrgrVal val1, ErtsThrPrgrVal val2)
+{
+ return val1 == val2 && val1 != ERTS_THR_PRGR_INVALID;
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_cmp(ErtsThrPrgrVal val1, ErtsThrPrgrVal val2)
+{
+ if (val1 == val2)
+ return 0;
+ if (erts_thr_progress_has_passed__(val1, val2))
+ return 1;
+ else
+ return -1;
+}
+
+ERTS_GLB_INLINE int
+erts_thr_progress_has_reached(ErtsThrPrgrVal val)
+{
+ ErtsThrPrgrVal current = erts_thr_progress_current();
+ return erts_thr_progress_has_reached_this(current, val);
+}
+
+#endif
+
+#endif /* ERTS_SMP */
+
+#endif
diff --git a/erts/emulator/beam/erl_thr_queue.c b/erts/emulator/beam/erl_thr_queue.c
new file mode 100644
index 0000000000..f07964a265
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_queue.c
@@ -0,0 +1,762 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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: Lock-free queue for communication between threads.
+ *
+ * Currently only a many-to-one version has been,
+ * implemented, i.e., many threads can enqueue but
+ * only one thread can dequeue at a time. It doesn't
+ * have to be the same thread dequeuing every time, but
+ * synchronization so that only one thread dequeues
+ * at a time has to be provided by other means.
+ *
+ * When/If the need for a many-to-many queue arises,
+ * this implementation can relatively easy be extended
+ * to support that too.
+ *
+ * Usage instructions below.
+ *
+ * Author: Rickard Green
+ */
+
+/*
+ * ------ Usage instructions -----------------------------------------------
+ *
+ * Dequeuing generates garbage that needs to be cleaned up.
+ * erts_thr_q_dequeue() automatically cleans, but garbage may have to be
+ * cleaned up also when the queue is empty. This is done by calling
+ * erts_thr_q_clean(). In the SMP case thread progress may have to be made
+ * before cleaning can continue. If so, erts_thr_q_need_thr_progress() in
+ * combination with erts_thr_progress_wakeup() can be used in order to
+ * request a wakeup at appropriate time.
+ *
+ * Enqueuing implies memory allocation and dequeuing implies memory
+ * deallocation. Memory allocation can be moved to another more suitable
+ * thread using erts_thr_q_prepare_enqueue() together with
+ * erts_thr_q_enqueue_prepared() instead of using erts_thr_q_enqueue().
+ * Memory deallocation can can be moved to another more suitable thread by
+ * disabling auto_finalize_dequeue when initializing the queue and then use
+ * erts_thr_q_get_finalize_dequeue_data() together
+ * erts_thr_q_finalize_dequeue() after dequeuing or cleaning.
+ *
+ * Ending the life of the queue using either erts_thr_q_destroy()
+ * or erts_thr_q_finalize() impies cleaning the queue. Both functions
+ * return the cleaning result and may have to be called multiple times
+ * until the queue is clean. Once one of these functions have been called
+ * enqueuing is not allowed. This has to be synchronized by the user.
+ * If auto_finalize_dequeue has been disabled, the finalize dequeue
+ * functionality has to be called after ending the life of the queue just
+ * as when dequeuing or cleaning on a queue that is alive.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "erl_thr_queue.h"
+
+#if defined(DEBUG)
+#define ERTS_THR_Q_DBG_CHK_DATA 1
+#else
+#define ERTS_THR_Q_DBG_CHK_DATA 0
+#endif
+
+#define ERTS_THR_Q_MAX_CLEAN_REACHED_HEAD_COUNT 100
+#define ERTS_THR_Q_MAX_SCHED_CLEAN_OPS 50
+#define ERTS_THR_Q_MAX_DEQUEUE_CLEAN_OPS 3
+
+#define ERTS_THR_Q_MAX_FINI_DEQ_OPS 50
+
+#ifdef ERTS_SMP
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(sl_element,
+ ErtsThrQElement_t,
+ 1000,
+ ERTS_ALC_T_THR_Q_EL_SL)
+#else
+
+static void
+init_sl_element_alloc(void)
+{
+}
+
+static ErtsThrQElement_t *
+sl_element_alloc(void)
+{
+ return erts_alloc(ERTS_ALC_T_THR_Q_EL_SL,
+ sizeof(ErtsThrQElement_t));
+}
+
+static void
+sl_element_free(ErtsThrQElement_t *p)
+{
+ erts_free(ERTS_ALC_T_THR_Q_EL_SL, p);
+}
+
+#endif
+
+typedef union {
+ ErtsThrQ_t q;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQ_t))];
+} ErtsAlignedThrQ_t;
+
+void
+erts_thr_q_init(void)
+{
+ init_sl_element_alloc();
+}
+
+static void noop_callback(void *arg) { }
+
+void
+erts_thr_q_initialize(ErtsThrQ_t *q, ErtsThrQInit_t *qi)
+{
+#ifndef USE_THREADS
+ q->init = *qi;
+ if (!q->init.notify)
+ q->init.notify = noop_callback;
+ q->first = NULL;
+ q->last = NULL;
+ q->q.blk = NULL;
+#else
+ erts_atomic_init_nob(&q->tail.data.marker.next.atmc, ERTS_AINT_NULL);
+ q->tail.data.marker.data.ptr = NULL;
+ erts_atomic_init_nob(&q->tail.data.last,
+ (erts_aint_t) &q->tail.data.marker);
+ erts_atomic_init_nob(&q->tail.data.um_refc[0], 0);
+ erts_atomic_init_nob(&q->tail.data.um_refc[1], 0);
+ erts_atomic32_init_nob(&q->tail.data.um_refc_ix, 0);
+ q->tail.data.live = qi->live.objects;
+ q->tail.data.arg = qi->arg;
+ q->tail.data.notify = qi->notify;
+ if (!q->tail.data.notify)
+ q->tail.data.notify = noop_callback;
+
+ q->head.head.ptr = &q->tail.data.marker;
+ q->head.live = qi->live.objects;
+ q->head.first = &q->tail.data.marker;
+ q->head.unref_end = &q->tail.data.marker;
+ q->head.clean_reached_head_count = 0;
+ q->head.deq_fini.automatic = qi->auto_finalize_dequeue;
+ q->head.deq_fini.start = NULL;
+ q->head.deq_fini.end = NULL;
+#ifdef ERTS_SMP
+ q->head.next.thr_progress = erts_thr_progress_current();
+ q->head.next.thr_progress_reached = 1;
+#endif
+ q->head.next.um_refc_ix = 1;
+ q->head.next.unref_end = &q->tail.data.marker;
+ q->head.used_marker = 1;
+ q->head.arg = qi->arg;
+ q->head.notify = q->tail.data.notify;
+ q->q.finalizing = 0;
+ q->q.live = qi->live.queue;
+ q->q.blk = NULL;
+#endif
+}
+
+ErtsThrQCleanState_t
+erts_thr_q_finalize(ErtsThrQ_t *q)
+{
+#ifdef USE_THREADS
+ q->q.finalizing = 1;
+#endif
+ while (erts_thr_q_dequeue(q));
+ return erts_thr_q_clean(q);
+}
+
+ErtsThrQ_t *
+erts_thr_q_create(ErtsThrQInit_t *qi)
+{
+ ErtsAlcType_t atype;
+ ErtsThrQ_t *q, *qblk;
+ UWord qw;
+
+ switch (qi->live.queue) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ atype = ERTS_ALC_T_THR_Q_SL;
+ break;
+ case ERTS_THR_Q_LIVE_LONG:
+ atype = ERTS_ALC_T_THR_Q_LL;
+ break;
+ default:
+ atype = ERTS_ALC_T_THR_Q;
+ break;
+ }
+
+ qw = (UWord) erts_alloc(atype,
+ sizeof(ErtsThrQ_t) + (ERTS_CACHE_LINE_SIZE-1));
+ qblk = (ErtsThrQ_t *) qw;
+ if (qw & ERTS_CACHE_LINE_MASK)
+ qw = (qw & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ ASSERT((qw & ERTS_CACHE_LINE_MASK) == 0);
+ q = (ErtsThrQ_t *) qw;
+ erts_thr_q_initialize(q, qi);
+ q->q.blk = qblk;
+ return q;
+}
+
+ErtsThrQCleanState_t
+erts_thr_q_destroy(ErtsThrQ_t *q)
+{
+ if (!q->q.blk)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Trying to destroy not created thread queue\n");
+ return erts_thr_q_finalize(q);
+}
+
+#ifdef USE_THREADS
+
+static void
+destroy(ErtsThrQ_t *q)
+{
+ ErtsAlcType_t atype;
+ switch (q->q.live) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ atype = ERTS_ALC_T_THR_Q_SL;
+ break;
+ case ERTS_THR_Q_LIVE_LONG:
+ atype = ERTS_ALC_T_THR_Q_LL;
+ break;
+ default:
+ atype = ERTS_ALC_T_THR_Q;
+ break;
+ }
+ erts_free(atype, q->q.blk);
+}
+
+#endif
+
+static ERTS_INLINE ErtsThrQElement_t *
+element_live_alloc(ErtsThrQLive_t live)
+{
+ switch (live) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ return sl_element_alloc();
+ default:
+ return (ErtsThrQElement_t *) erts_alloc(ERTS_ALC_T_THR_Q_EL,
+ sizeof(ErtsThrQElement_t));
+ }
+}
+
+static ERTS_INLINE ErtsThrQElement_t *
+element_alloc(ErtsThrQ_t *q)
+{
+ ErtsThrQLive_t live;
+#ifdef USE_THREADS
+ live = q->tail.data.live;
+#else
+ live = q->init.live.objects;
+#endif
+ return element_live_alloc(live);
+}
+
+static ERTS_INLINE void
+element_live_free(ErtsThrQLive_t live, ErtsThrQElement_t *el)
+{
+ switch (live) {
+ case ERTS_THR_Q_LIVE_SHORT:
+ sl_element_free(el);
+ break;
+ default:
+ erts_free(ERTS_ALC_T_THR_Q_EL, el);
+ }
+}
+
+static ERTS_INLINE void
+element_free(ErtsThrQ_t *q, ErtsThrQElement_t *el)
+{
+ ErtsThrQLive_t live;
+#ifdef USE_THREADS
+ live = q->head.live;
+#else
+ live = q->init.live.objects;
+#endif
+ element_live_free(live, el);
+}
+
+#ifdef USE_THREADS
+
+static ERTS_INLINE ErtsThrQElement_t *
+enqueue_managed(ErtsThrQ_t *q, ErtsThrQElement_t *this, int want_last)
+{
+ erts_aint_t ilast, itmp;
+
+ erts_atomic_init_nob(&this->next.atmc, ERTS_AINT_NULL);
+ /* Enqueue at end of list... */
+
+ ilast = erts_atomic_read_nob(&q->tail.data.last);
+ while (1) {
+ ErtsThrQElement_t *last = (ErtsThrQElement_t *) ilast;
+ itmp = erts_atomic_cmpxchg_mb(&last->next.atmc,
+ (erts_aint_t) this,
+ ERTS_AINT_NULL);
+ if (itmp == ERTS_AINT_NULL)
+ break;
+ ilast = itmp;
+ }
+
+ /* Move last pointer forward... */
+ while (1) {
+ if (want_last) {
+ if (erts_atomic_read_rb(&this->next.atmc) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ ilast = erts_atomic_read_rb(&q->tail.data.last);
+ return (ErtsThrQElement_t *) ilast;
+ }
+ }
+ else {
+ if (erts_atomic_read_nob(&this->next.atmc) != ERTS_AINT_NULL) {
+ /* Someone else will move it forward */
+ return NULL;
+ }
+ }
+ itmp = erts_atomic_cmpxchg_mb(&q->tail.data.last,
+ (erts_aint_t) this,
+ ilast);
+ if (ilast == itmp)
+ return want_last ? this : NULL;
+ ilast = itmp;
+ }
+}
+
+static ErtsThrQCleanState_t
+clean(ErtsThrQ_t *q, int max_ops, int do_notify)
+{
+ erts_aint_t ilast;
+ int um_refc_ix;
+ int ops;
+
+ for (ops = 0; ops < max_ops; ops++) {
+ ErtsThrQElement_t *tmp;
+ restart:
+ ASSERT(q->head.first);
+ if (q->head.first == q->head.head.ptr) {
+ q->head.clean_reached_head_count++;
+ if (q->head.clean_reached_head_count
+ >= ERTS_THR_Q_MAX_CLEAN_REACHED_HEAD_COUNT) {
+ q->head.clean_reached_head_count = 0;
+ break;
+ }
+ goto inspect_head;
+ }
+ if (q->head.first == q->head.unref_end)
+ break;
+ if (q->head.first == &q->tail.data.marker) {
+ q->head.used_marker = 0;
+ q->head.first = q->head.first->next.ptr;
+ goto restart;
+ }
+ tmp = q->head.first;
+ q->head.first = q->head.first->next.ptr;
+ if (q->head.deq_fini.automatic)
+ element_free(q, tmp);
+ else {
+ tmp->data.ptr = (void *) (UWord) q->head.live;
+ if (!q->head.deq_fini.start)
+ q->head.deq_fini.start = tmp;
+ else if (q->head.deq_fini.end->next.ptr == &q->tail.data.marker)
+ q->head.deq_fini.end->next.ptr = tmp;
+ q->head.deq_fini.end = tmp;
+ }
+ }
+
+ ilast = erts_atomic_read_nob(&q->tail.data.last);
+ if (q->head.first == ((ErtsThrQElement_t *) ilast)
+ && ((ErtsThrQElement_t *) ilast) == &q->tail.data.marker
+ && q->head.first == &q->tail.data.marker) {
+ /* Empty and clean queue */
+ if (q->q.finalizing)
+ destroy(q);
+ return ERTS_THR_Q_CLEAN;
+ }
+
+#ifdef ERTS_SMP
+ if (q->head.next.thr_progress_reached
+ || erts_thr_progress_has_reached(q->head.next.thr_progress)) {
+ q->head.next.thr_progress_reached = 1;
+#endif
+ um_refc_ix = q->head.next.um_refc_ix;
+ if (erts_atomic_read_acqb(&q->tail.data.um_refc[um_refc_ix]) == 0) {
+ /* Move unreferenced end pointer forward... */
+ q->head.clean_reached_head_count = 0;
+ q->head.unref_end = q->head.next.unref_end;
+
+ if (!q->head.used_marker
+ && q->head.unref_end == (ErtsThrQElement_t *) ilast) {
+ q->head.used_marker = 1;
+ ilast = (erts_aint_t) enqueue_managed(q,
+ &q->tail.data.marker,
+ 1);
+ if (q->head.head.ptr == q->head.unref_end) {
+ ErtsThrQElement_t *next;
+ next = ((ErtsThrQElement_t *)
+ erts_atomic_read_acqb(&q->head.head.ptr->next.atmc));
+ if (next == &q->tail.data.marker) {
+ q->head.head.ptr->next.ptr = &q->tail.data.marker;
+ q->head.head.ptr = &q->tail.data.marker;
+ }
+ }
+ }
+
+ if (q->head.unref_end == (ErtsThrQElement_t *) ilast)
+ ERTS_SMP_MEMORY_BARRIER;
+ else {
+ q->head.next.unref_end = (ErtsThrQElement_t *) ilast;
+#ifdef ERTS_SMP
+ q->head.next.thr_progress = erts_thr_progress_later(NULL);
+#endif
+ erts_atomic32_set_relb(&q->tail.data.um_refc_ix,
+ um_refc_ix);
+ q->head.next.um_refc_ix = um_refc_ix == 0 ? 1 : 0;
+#ifdef ERTS_SMP
+ q->head.next.thr_progress_reached = 0;
+#endif
+ }
+ }
+#ifdef ERTS_SMP
+ }
+#endif
+
+ if (q->head.first == q->head.head.ptr) {
+ inspect_head:
+ if (!q->head.used_marker) {
+ erts_aint_t inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL) {
+ q->head.used_marker = 1;
+ (void) enqueue_managed(q, &q->tail.data.marker, 0);
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == (erts_aint_t) &q->tail.data.marker) {
+ q->head.head.ptr->next.ptr = &q->tail.data.marker;
+ q->head.head.ptr = &q->tail.data.marker;
+ goto check_thr_progress;
+ }
+ }
+ }
+
+ if (q->q.finalizing) {
+ ilast = erts_atomic_read_nob(&q->tail.data.last);
+ if (q->head.first == ((ErtsThrQElement_t *) ilast)
+ && ((ErtsThrQElement_t *) ilast) == &q->tail.data.marker
+ && q->head.first == &q->tail.data.marker) {
+ destroy(q);
+ }
+ else {
+ goto dirty;
+ }
+ }
+ return ERTS_THR_Q_CLEAN;
+ }
+
+ if (q->head.first != q->head.unref_end)
+ goto dirty;
+
+check_thr_progress:
+
+#ifdef ERTS_SMP
+ if (q->head.next.thr_progress_reached)
+#endif
+ {
+ int um_refc_ix = q->head.next.um_refc_ix;
+ if (erts_atomic_read_acqb(&q->tail.data.um_refc[um_refc_ix]) == 0) {
+ dirty:
+ if (do_notify)
+ q->head.notify(q->head.arg);
+ return ERTS_THR_Q_DIRTY;
+ }
+ }
+
+ return ERTS_THR_Q_NEED_THR_PRGR;
+}
+
+#endif
+
+ErtsThrQCleanState_t
+erts_thr_q_clean(ErtsThrQ_t *q)
+{
+#ifdef USE_THREADS
+ return clean(q, ERTS_THR_Q_MAX_SCHED_CLEAN_OPS, 0);
+#else
+ return ERTS_THR_Q_CLEAN;
+#endif
+}
+
+ErtsThrQCleanState_t
+erts_thr_q_inspect(ErtsThrQ_t *q, int ensure_empty)
+{
+#ifndef USE_THREADS
+ return ERTS_THR_Q_CLEAN;
+#else
+ if (ensure_empty) {
+ erts_aint_t inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext != ERTS_AINT_NULL) {
+ if (&q->tail.data.marker != (ErtsThrQElement_t *) inext)
+ return ERTS_THR_Q_DIRTY;
+ else {
+ q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext;
+ q->head.head.ptr = (ErtsThrQElement_t *) inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext != ERTS_AINT_NULL)
+ return ERTS_THR_Q_DIRTY;
+ }
+ }
+ }
+
+ if (q->head.first == q->head.head.ptr) {
+ if (!q->head.used_marker) {
+ erts_aint_t inext;
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL)
+ return ERTS_THR_Q_DIRTY;
+ }
+ return ERTS_THR_Q_CLEAN;
+ }
+
+ if (q->head.first != q->head.unref_end)
+ return ERTS_THR_Q_DIRTY;
+
+#ifdef ERTS_SMP
+ if (q->head.next.thr_progress_reached)
+#endif
+ {
+ int um_refc_ix = q->head.next.um_refc_ix;
+ if (erts_atomic_read_acqb(&q->tail.data.um_refc[um_refc_ix]) == 0)
+ return ERTS_THR_Q_DIRTY;
+ }
+ return ERTS_THR_Q_NEED_THR_PRGR;
+#endif
+}
+
+static void
+enqueue(ErtsThrQ_t *q, void *data, ErtsThrQElement_t *this)
+{
+#ifndef USE_THREADS
+ ASSERT(data);
+
+ this->next.ptr = NULL;
+ this->data.ptr = data;
+
+ if (q->last)
+ q->last->next.ptr = this;
+ else {
+ q->first = q->last = this;
+ q->init.notify(q->init.arg);
+ }
+#else
+ int notify;
+ int um_refc_ix = 0;
+#ifdef ERTS_SMP
+ int unmanaged_thread;
+#endif
+
+#if ERTS_THR_Q_DBG_CHK_DATA
+ if (!data)
+ erl_exit(ERTS_ABORT_EXIT, "Missing data in enqueue\n");
+#endif
+
+ ASSERT(!q->q.finalizing);
+
+ this->data.ptr = data;
+
+#ifdef ERTS_SMP
+ unmanaged_thread = !erts_thr_progress_is_managed_thread();
+ if (unmanaged_thread)
+#endif
+ {
+ um_refc_ix = erts_atomic32_read_acqb(&q->tail.data.um_refc_ix);
+ while (1) {
+ int tmp_um_refc_ix;
+ erts_atomic_inc_acqb(&q->tail.data.um_refc[um_refc_ix]);
+ tmp_um_refc_ix = erts_atomic32_read_acqb(&q->tail.data.um_refc_ix);
+ if (tmp_um_refc_ix == um_refc_ix)
+ break;
+ erts_atomic_dec_relb(&q->tail.data.um_refc[um_refc_ix]);
+ um_refc_ix = tmp_um_refc_ix;
+ }
+ }
+
+ notify = this == enqueue_managed(q, this, 1);
+
+
+#ifdef ERTS_SMP
+ if (unmanaged_thread)
+#endif
+ {
+ if (notify)
+ erts_atomic_dec_relb(&q->tail.data.um_refc[um_refc_ix]);
+ else if (erts_atomic_dec_read_relb(&q->tail.data.um_refc[um_refc_ix]) == 0)
+ notify = 1;
+ }
+ if (notify)
+ q->tail.data.notify(q->tail.data.arg);
+#endif
+}
+
+void
+erts_thr_q_enqueue(ErtsThrQ_t *q, void *data)
+{
+ enqueue(q, data, element_alloc(q));
+}
+
+ErtsThrQPrepEnQ_t *
+erts_thr_q_prepare_enqueue(ErtsThrQ_t *q)
+{
+ return (ErtsThrQPrepEnQ_t *) element_alloc(q);
+}
+
+int
+erts_thr_q_get_finalize_dequeue_data(ErtsThrQ_t *q, ErtsThrQFinDeQ_t *fdp)
+{
+#ifndef USE_THREADS
+ return 0;
+#else
+#ifdef DEBUG
+ if (!q->head.deq_fini.start) {
+ ASSERT(!q->head.deq_fini.end);
+ }
+ else {
+ ErtsThrQElement_t *e = q->head.deq_fini.start;
+ ErtsThrQElement_t *end = q->head.deq_fini.end;
+ while (e != end) {
+ ASSERT(q->head.head.ptr != e);
+ ASSERT(q->head.first != e);
+ ASSERT(q->head.unref_end != e);
+ e = e->next.ptr;
+ }
+ }
+#endif
+ fdp->start = q->head.deq_fini.start;
+ fdp->end = q->head.deq_fini.end;
+ if (fdp->end)
+ fdp->end->next.ptr = NULL;
+ q->head.deq_fini.start = NULL;
+ q->head.deq_fini.end = NULL;
+ return fdp->start != NULL;
+#endif
+}
+
+void
+erts_thr_q_append_finalize_dequeue_data(ErtsThrQFinDeQ_t *fdp0,
+ ErtsThrQFinDeQ_t *fdp1)
+{
+#ifdef USE_THREADS
+ if (fdp1->start) {
+ if (fdp0->end)
+ fdp0->end->next.ptr = fdp1->start;
+ else
+ fdp0->start = fdp1->start;
+ fdp0->end = fdp1->end;
+ }
+#endif
+}
+
+
+int erts_thr_q_finalize_dequeue(ErtsThrQFinDeQ_t *state)
+{
+#ifdef USE_THREADS
+ ErtsThrQElement_t *start = state->start;
+ if (start) {
+ ErtsThrQLive_t live;
+ int i;
+ for (i = 0; i < ERTS_THR_Q_MAX_FINI_DEQ_OPS; i++) {
+ ErtsThrQElement_t *tmp;
+ if (!start)
+ break;
+ tmp = start;
+ start = start->next.ptr;
+ live = (ErtsThrQLive_t) (UWord) tmp->data.ptr;
+ element_live_free(live, tmp);
+ }
+ state->start = start;
+ if (start)
+ return 1; /* More to do */
+ state->end = NULL;
+ }
+#endif
+ return 0;
+}
+
+void
+erts_thr_q_finalize_dequeue_state_init(ErtsThrQFinDeQ_t *state)
+{
+#ifdef USE_THREADS
+ state->start = NULL;
+ state->end = NULL;
+#endif
+}
+
+
+void
+erts_thr_q_enqueue_prepared(ErtsThrQ_t *q, void *data, ErtsThrQPrepEnQ_t *prep)
+{
+ ASSERT(prep);
+ enqueue(q, data, (ErtsThrQElement_t *) prep);
+}
+
+void *
+erts_thr_q_dequeue(ErtsThrQ_t *q)
+{
+#ifndef USE_THREADS
+ void *res;
+ ErtsThrQElement_t *tmp;
+
+ if (!q->first)
+ return NULL;
+ tmp = q->first;
+ res = tmp->data.ptr;
+ q->first = tmp->next.ptr;
+ if (!q->first)
+ q->last = NULL;
+
+ element_free(q, tmp);
+
+ return res;
+#else
+ erts_aint_t inext;
+ void *res;
+
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL)
+ return NULL;
+ q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext;
+ q->head.head.ptr = (ErtsThrQElement_t *) inext;
+ if (q->head.head.ptr == &q->tail.data.marker) {
+ inext = erts_atomic_read_acqb(&q->head.head.ptr->next.atmc);
+ if (inext == ERTS_AINT_NULL)
+ return NULL;
+ q->head.head.ptr->next.ptr = (ErtsThrQElement_t *) inext;
+ q->head.head.ptr = (ErtsThrQElement_t *) inext;
+ }
+ res = q->head.head.ptr->data.ptr;
+#if ERTS_THR_Q_DBG_CHK_DATA
+ q->head.head.ptr->data.ptr = NULL;
+ if (!res)
+ erl_exit(ERTS_ABORT_EXIT, "Missing data in dequeue\n");
+#endif
+ clean(q,
+ (q->head.deq_fini.automatic
+ ? ERTS_THR_Q_MAX_DEQUEUE_CLEAN_OPS
+ : ERTS_THR_Q_MAX_SCHED_CLEAN_OPS), 1);
+ return res;
+#endif
+}
diff --git a/erts/emulator/beam/erl_thr_queue.h b/erts/emulator/beam/erl_thr_queue.h
new file mode 100644
index 0000000000..edcf2c3823
--- /dev/null
+++ b/erts/emulator/beam/erl_thr_queue.h
@@ -0,0 +1,209 @@
+/*
+ * %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%
+ */
+
+/*
+ * Description: Lock-free queue for communication between threads.
+ *
+ * Currently only a many-to-one version has been,
+ * implemented, i.e., many threads can enqueue but
+ * only one thread can dequeue at a time. It doesn't
+ * have to be the same thread dequeuing every time, but
+ * synchronization so that only one thread dequeues
+ * at a time has to be provided by other means.
+ *
+ * When/If the need for a many-to-many queue arises,
+ * this implementation can relatively easy be extended
+ * to support that too.
+ *
+ * Usage instructions can be found in erts_thr_queue.c
+ *
+ * Author: Rickard Green
+ */
+
+#ifndef ERL_THR_QUEUE_H__
+#define ERL_THR_QUEUE_H__
+
+#include "sys.h"
+#include "erl_threads.h"
+#include "erl_alloc.h"
+#include "erl_thr_progress.h"
+
+typedef enum {
+ ERTS_THR_Q_LIVE_UNDEF,
+ ERTS_THR_Q_LIVE_SHORT,
+ ERTS_THR_Q_LIVE_LONG
+} ErtsThrQLive_t;
+
+#define ERTS_THR_Q_INIT_DEFAULT \
+{ \
+ { \
+ ERTS_THR_Q_LIVE_UNDEF, \
+ ERTS_THR_Q_LIVE_SHORT \
+ }, \
+ NULL, \
+ NULL, \
+ 1 \
+}
+
+typedef struct ErtsThrQ_t_ ErtsThrQ_t;
+
+typedef struct {
+ struct {
+ ErtsThrQLive_t queue;
+ ErtsThrQLive_t objects;
+ } live;
+ void *arg;
+ void (*notify)(void *);
+ int auto_finalize_dequeue;
+} ErtsThrQInit_t;
+
+typedef struct ErtsThrQElement_t_ ErtsThrQElement_t;
+typedef struct ErtsThrQElement_t ErtsThrQPrepEnQ_t;
+
+typedef union {
+ erts_atomic_t atmc;
+ ErtsThrQElement_t *ptr;
+} ErtsThrQPtr_t;
+
+struct ErtsThrQElement_t_ {
+ ErtsThrQPtr_t next;
+ union {
+ erts_atomic_t atmc;
+ void *ptr;
+ } data;
+};
+
+typedef struct {
+ ErtsThrQElement_t *start;
+ ErtsThrQElement_t *end;
+} ErtsThrQFinDeQ_t;
+
+typedef enum {
+ ERTS_THR_Q_CLEAN,
+ ERTS_THR_Q_NEED_THR_PRGR,
+ ERTS_THR_Q_DIRTY,
+} ErtsThrQCleanState_t;
+
+#ifdef USE_THREADS
+
+typedef struct {
+ ErtsThrQElement_t marker;
+ erts_atomic_t last;
+ erts_atomic_t um_refc[2];
+ erts_atomic32_t um_refc_ix;
+ ErtsThrQLive_t live;
+#ifdef ERTS_SMP
+ erts_atomic32_t thr_prgr_clean_scheduled;
+#endif
+ void *arg;
+ void (*notify)(void *);
+} ErtsThrQTail_t;
+
+struct ErtsThrQ_t_ {
+ /*
+ * This structure needs to be cache line aligned for best
+ * performance.
+ */
+ union {
+ /* Modified by threads enqueuing */
+ ErtsThrQTail_t data;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsThrQTail_t))];
+ } tail;
+ /*
+ * Everything below this point is *only* accessed by the
+ * thread dequeuing.
+ */
+ struct {
+ ErtsThrQPtr_t head;
+ ErtsThrQLive_t live;
+ ErtsThrQElement_t *first;
+ ErtsThrQElement_t *unref_end;
+ int clean_reached_head_count;
+ struct {
+ int automatic;
+ ErtsThrQElement_t *start;
+ ErtsThrQElement_t *end;
+ } deq_fini;
+ struct {
+#ifdef ERTS_SMP
+ ErtsThrPrgrVal thr_progress;
+ int thr_progress_reached;
+#endif
+ int um_refc_ix;
+ ErtsThrQElement_t *unref_end;
+ } next;
+ int used_marker;
+ void *arg;
+ void (*notify)(void *);
+ } head;
+ struct {
+ int finalizing;
+ ErtsThrQLive_t live;
+ void *blk;
+ } q;
+};
+
+#else /* !USE_THREADS */
+
+struct ErtsThrQ_t_ {
+ ErtsThrQInit_t init;
+ ErtsThrQElement_t *first;
+ ErtsThrQElement_t *last;
+ struct {
+ void *blk;
+ } q;
+};
+
+#endif
+
+void erts_thr_q_init(void);
+void erts_thr_q_initialize(ErtsThrQ_t *, ErtsThrQInit_t *);
+ErtsThrQCleanState_t erts_thr_q_finalize(ErtsThrQ_t *);
+ErtsThrQ_t *erts_thr_q_create(ErtsThrQInit_t *);
+ErtsThrQCleanState_t erts_thr_q_destroy(ErtsThrQ_t *);
+ErtsThrQCleanState_t erts_thr_q_clean(ErtsThrQ_t *);
+ErtsThrQCleanState_t erts_thr_q_inspect(ErtsThrQ_t *, int);
+ErtsThrQPrepEnQ_t *erts_thr_q_prepare_enqueue(ErtsThrQ_t *);
+void erts_thr_q_enqueue_prepared(ErtsThrQ_t *, void *, ErtsThrQPrepEnQ_t *);
+void erts_thr_q_enqueue(ErtsThrQ_t *, void *);
+void * erts_thr_q_dequeue(ErtsThrQ_t *);
+int erts_thr_q_get_finalize_dequeue_data(ErtsThrQ_t *,
+ ErtsThrQFinDeQ_t *);
+void erts_thr_q_append_finalize_dequeue_data(ErtsThrQFinDeQ_t *,
+ ErtsThrQFinDeQ_t *);
+int erts_thr_q_finalize_dequeue(ErtsThrQFinDeQ_t *);
+void erts_thr_q_finalize_dequeue_state_init(ErtsThrQFinDeQ_t *);
+
+#ifdef ERTS_SMP
+ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_q_need_thr_progress(ErtsThrQ_t *q);
+#endif
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+#ifdef ERTS_SMP
+ERTS_GLB_INLINE ErtsThrPrgrVal
+erts_thr_q_need_thr_progress(ErtsThrQ_t *q)
+{
+ return q->head.next.thr_progress;
+}
+#endif
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
+#endif /* ERL_THR_QUEUE_H__ */
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index 12eaf39ec7..ee47c98009 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,235 @@
#ifndef ERL_THREAD_H__
#define ERL_THREAD_H__
+/*
+ * --- Documentation of atomics and memory barriers --------------------------
+ *
+ * The following explicit memory barriers exist:
+ *
+ * - ERTS_THR_MEMORY_BARRIER
+ * Full memory barrier. Orders both loads, and stores. No
+ * load or store is allowed to be reordered over the
+ * barrier.
+ * - ERTS_THR_WRITE_MEMORY_BARRIER
+ * Write barrier. Orders *only* stores. These are not
+ * allowed to be reordered over the barrier.
+ * - ERTS_THR_READ_MEMORY_BARRIER
+ * Read barrier. Orders *only* loads. These are not
+ * allowed to be reordered over the barrier.
+ * - ERTS_THR_DATA_DEPENDENCY_READ_MEMORY_BARRIER
+ * Data dependency read barrier. Orders *only* loads
+ * according to data dependency across the barrier.
+ *
+ * If thread support has been disabled, these barriers will become no-ops.
+ *
+ * If the prefix ERTS_THR_ is replaced with ERTS_SMP_, the barriers will
+ * be enabled only in the SMP enabled runtime system.
+ *
+ * --- Atomic operations ---
+ *
+ * Atomics operations exist for 32-bit, word size, and double word size
+ * integers. Function prototypes are listed below.
+ *
+ * Each function implementing an atomic operation exist with the following
+ * implied memory barrier semantics. Not all combinations are useful, but
+ * all of them exist for simplicity. <B> is suffix in function name:
+ *
+ * - <B> - Description
+ *
+ * - mb - Full memory barrier. Orders both loads, and
+ * stores before, and after the atomic operation.
+ * No load or store is allowed to be reordered
+ * over the atomic operation.
+ * - relb - Release barrier. Orders both loads, and
+ * stores appearing *before* the atomic
+ * operation. These are not allowed to be
+ * reordered over the atomic operation.
+ * - acqb - Acquire barrier. Orders both loads, and stores
+ * appearing *after* the atomic operation. These
+ * are not allowed to be reordered over the
+ * atomic operation.
+ * - wb - Write barrier. Orders *only* stores. These are
+ * not allowed to be reordered over the barrier.
+ * Store in atomic operation is ordered *after*
+ * the barrier.
+ * - rb - Read barrier. Orders *only* loads. These are
+ * not allowed to be reordered over the barrier.
+ * Load in atomic operation is ordered *before*
+ * the barrier.
+ * - ddrb - Data dependency read barrier. Orders *only*
+ * loads according to data dependency across the
+ * barrier. Load in atomic operation is ordered
+ * before the barrier.
+ *
+ * If thread support has been disabled, these functions are mapped to
+ * functions that performs the same operation, but aren't atomic
+ * and don't imply any memory barriers.
+ *
+ * If the atomic operations are prefixed with erts_smp_ instead of only
+ * erts_ the atomic operations will only be atomic in the SMP enabled
+ * runtime system, and will be mapped to non-atomic operations without
+ * memory barriers in the runtime system without SMP support. Atomic
+ * operations with erts_smp_ prefix should use the atomic types
+ * erts_smp_atomic32_t, erts_smp_atomic_t, and erts_smp_dw_atomic_t
+ * instead of erts_atomic32_t, erts_atomic_t, and erts_dw_atomic_t. The
+ * integer data types erts_aint32_t, erts_aint_t, and erts_dw_atomic_t
+ * are the same.
+ *
+ * --- 32-bit atomic operations ---
+ *
+ * The following 32-bit atomic operations exist. <B> should be
+ * replaced with a supported memory barrier (see above). Note
+ * that sizeof(erts_atomic32_t) might be larger than 4!
+ *
+ *
+ * Initialize (not necessarily the same as the set operation):
+ * void erts_atomic32_init_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Set value:
+ * void erts_atomic32_set_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Read; returns current value:
+ * erts_aint32_t erts_atomic32_read_<B>(erts_atomic32_t *atmc);
+ *
+ * Increment; returns resulting value:
+ * erts_aint32_t erts_atomic32_inc_read_<B>(erts_atomic32_t *atmc);
+ *
+ * Decrement; returns resulting value:
+ * erts_aint32_t erts_atomic32_dec_read_<B>(erts_atomic32_t *atmc);
+ *
+ * Increment:
+ * void erts_atomic32_inc_<B>(erts_atomic32_t *atmc);
+ *
+ * Decrement:
+ * void erts_atomic32_dec_<B>(erts_atomic32_t *atmc);
+ *
+ * Add value; returns resulting value:
+ * erts_aint32_t erts_atomic32_add_read_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Add value:
+ * void erts_atomic32_add_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Bitwise-or; returns previous value:
+ * erts_aint32_t erts_atomic32_read_bor_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Bitwise-and; returns previous value:
+ * erts_aint32_t erts_atomic32_read_band_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Exchange; returns previous value:
+ * erts_aint32_t erts_atomic32_xchg_<B>(erts_atomic32_t *atmc,
+ * erts_aint32_t val);
+ *
+ * Compare and exchange; returns previous or current value. If
+ * returned value equals 'exp' the value was changed to 'new';
+ * otherwise not:
+ * erts_aint32_t erts_atomic32_cmpxchg_<B>(erts_atomic32_t *a,
+ * erts_aint32_t new,
+ * erts_aint32_t exp);
+ *
+ * --- Word size atomic operations ---
+ *
+ * The following word size (same size as sizeof(void *)) atomic
+ * operations exist. <B> should be replaced with a supported
+ * memory barrier (see above). Note that sizeof(erts_atomic_t)
+ * might be larger than sizeof(void *)!
+ *
+ * Initialize (not necessarily the same as the set operation):
+ * void erts_atomic_init_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Set value;
+ * void erts_atomic_set_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Read; returns current value:
+ * erts_aint_t erts_atomic_read_<B>(erts_atomic_t *atmc);
+ *
+ * Increment; returns resulting value:
+ * erts_aint_t erts_atomic_inc_read_<B>(erts_atomic_t *atmc);
+ *
+ * Decrement; returns resulting value:
+ * erts_aint_t erts_atomic_dec_read_<B>(erts_atomic_t *atmc);
+ *
+ * Increment:
+ * void erts_atomic_inc_<B>(erts_atomic_t *atmc);
+ *
+ * Decrement:
+ * void erts_atomic_dec_<B>(erts_atomic_t *atmc);
+ *
+ * Add value; returns resulting value:
+ * erts_aint_t erts_atomic_add_read_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Add value:
+ * void erts_atomic_add_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Bitwise-or; returns previous value:
+ * erts_aint_t erts_atomic_read_bor_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Bitwise-and; returns previous value:
+ * erts_aint_t erts_atomic_read_band_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Exchange; returns previous value:
+ * erts_aint_t erts_atomic_xchg_<B>(erts_atomic_t *atmc,
+ * erts_aint_t val);
+ *
+ * Compare and exchange; returns previous or current value. If
+ * returned value equals 'exp' the value was changed to 'new';
+ * otherwise not:
+ * erts_aint_t erts_atomic_cmpxchg_<B>(erts_atomic_t *a,
+ * erts_aint_t new,
+ * erts_aint_t exp);
+ *
+ * --- Double word size atomic operations ---
+ *
+ * The following double word atomic operations exist. <B> should be
+ * replaced with a supported memory barrier (see above).
+ *
+ * Note that sizeof(erts_dw_atomic_t) usually is larger than
+ * 2*sizeof(void *)!
+ *
+ * The erts_dw_aint_t data type should be accessed as if it was defined
+ * like this:
+ *
+ * typedef struct {
+ * erts_aint_t sint[2];
+ * } erts_dw_aint_t;
+ *
+ * Most significant word is 'sint[ERTS_DW_AINT_HIGH_WORD]' and least
+ * significant word is 'sint[ERTS_DW_AINT_LOW_WORD]'.
+ *
+ *
+ * Initialize (not necessarily the same as the set operation):
+ * void erts_dw_atomic_init_<B>(erts_dw_atomic_t *var,
+ * erts_dw_aint_t *val);
+ *
+ * Set; value is written into 'val':
+ * void erts_dw_atomic_set_<B>(erts_dw_atomic_t *var,
+ * erts_dw_aint_t *val);
+ *
+ * Read; value is written into 'val':
+ * void erts_dw_atomic_read_<B>(erts_dw_atomic_t *var,
+ * erts_dw_aint_t *val);
+ *
+ * Compare and exchange; returns a value != 0 if exchange was
+ * made; otherwise 0. 'new_val' contains new value to set. If 'exp_act'
+ * contains the same value as in memory when the function is called,
+ * 'new' is written to memory; otherwise, not. If exchange was not
+ * made, 'exp_act' contains the actual value in memory:
+ * int erts_dw_atomic_cmpxchg_<B>(erts_dw_atomic_t *var,
+ * erts_dw_aint_t *new,
+ * erts_dw_aint_t *exp_act);
+ */
+
#define ERTS_SPIN_BODY ETHR_SPIN_BODY
#include "sys.h"
@@ -52,6 +281,9 @@ typedef Sint32 erts_no_atomic32_t;
#endif
#define ERTS_THR_MEMORY_BARRIER ETHR_MEMORY_BARRIER
+#define ERTS_THR_WRITE_MEMORY_BARRIER ETHR_WRITE_MEMORY_BARRIER
+#define ERTS_THR_READ_MEMORY_BARRIER ETHR_READ_MEMORY_BARRIER
+#define ERTS_THR_DATA_DEPENDENCY_READ_MEMORY_BARRIER ETHR_READ_DEPEND_MEMORY_BARRIER
#ifdef ERTS_ENABLE_LOCK_COUNT
#define erts_mtx_lock(L) erts_mtx_lock_x(L, __FILE__, __LINE__)
@@ -92,6 +324,8 @@ typedef struct {
#endif
} erts_rwmtx_t;
+#define ERTS_MTX_OPT_DEFAULT_INITER ETHR_MUTEX_OPT_DEFAULT_INITER
+#define ERTS_CND_OPT_DEFAULT_INITER ETHR_COND_OPT_DEFAULT_INITER
#define ERTS_RWMTX_OPT_DEFAULT_INITER ETHR_RWMUTEX_OPT_DEFAULT_INITER
#define ERTS_RWMTX_TYPE_NORMAL ETHR_RWMUTEX_TYPE_NORMAL
#define ERTS_RWMTX_TYPE_FREQUENT_READ ETHR_RWMUTEX_TYPE_FREQUENT_READ
@@ -111,6 +345,9 @@ typedef ethr_ts_event erts_tse_t;
#define erts_aint32_t ethr_sint32_t
#define erts_atomic32_t ethr_atomic32_t
+#define ERTS_DW_AINT_HIGH_WORD ETHR_DW_SINT_HIGH_WORD
+#define ERTS_DW_AINT_LOW_WORD ETHR_DW_SINT_LOW_WORD
+
/* spinlock */
typedef struct {
ethr_spinlock_t slck;
@@ -147,6 +384,9 @@ __decl_noreturn void __noreturn erts_thr_fatal_error(int, char *);
#else /* #ifdef USE_THREADS */
#define ERTS_THR_MEMORY_BARRIER
+#define ERTS_THR_WRITE_MEMORY_BARRIER
+#define ERTS_THR_READ_MEMORY_BARRIER
+#define ERTS_THR_DATA_DEPENDENCY_READ_MEMORY_BARRIER
#define ERTS_THR_OPTS_DEFAULT_INITER 0
typedef int erts_thr_opts_t;
@@ -193,6 +433,8 @@ typedef struct { int gcc_is_buggy; } erts_rwlock_t;
#endif /* #ifdef USE_THREADS */
+#define ERTS_AINT_NULL ((erts_aint_t) NULL)
+
#define ERTS_AINT_T_MAX (~(((erts_aint_t) 1) << (sizeof(erts_aint_t)*8-1)))
#define ERTS_AINT_T_MIN ((((erts_aint_t) 1) << (sizeof(erts_aint_t)*8-1)))
#define ERTS_AINT32_T_MAX (~(((erts_aint32_t) 1) << (sizeof(erts_aint32_t)*8-1)))
@@ -357,18 +599,13 @@ ERTS_GLB_INLINE void erts_thr_sigmask(int how, const sigset_t *set,
ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#endif /* #ifdef HAVE_ETHR_SIG_FUNCS */
+#ifdef USE_THREADS
+
/*
- * Functions implementing atomic operations with with no (nob),
- * full (mb), acquire (acqb), release (relb), read (rb), and
- * write (wb) memory barriers.
- *
- * If thread support has been disabled, they are mapped to
- * functions that performs the same operation, but aren't atomic
- * and don't imply memory barriers.
+ * See "Documentation of atomics and memory barriers" at the top
+ * of this file for info on atomics.
*/
-#ifdef USE_THREADS
-
/* Double word size atomics */
#define erts_dw_atomic_init_nob ethr_dw_atomic_init
@@ -391,6 +628,11 @@ ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#define erts_dw_atomic_read_relb ethr_dw_atomic_read_relb
#define erts_dw_atomic_cmpxchg_relb ethr_dw_atomic_cmpxchg_relb
+#define erts_dw_atomic_init_ddrb ethr_dw_atomic_init_ddrb
+#define erts_dw_atomic_set_ddrb ethr_dw_atomic_set_ddrb
+#define erts_dw_atomic_read_ddrb ethr_dw_atomic_read_ddrb
+#define erts_dw_atomic_cmpxchg_ddrb ethr_dw_atomic_cmpxchg_ddrb
+
#define erts_dw_atomic_init_rb ethr_dw_atomic_init_rb
#define erts_dw_atomic_set_rb ethr_dw_atomic_set_rb
#define erts_dw_atomic_read_rb ethr_dw_atomic_read_rb
@@ -459,6 +701,20 @@ ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#define erts_atomic_xchg_relb ethr_atomic_xchg_relb
#define erts_atomic_cmpxchg_relb ethr_atomic_cmpxchg_relb
+#define erts_atomic_init_ddrb ethr_atomic_init_ddrb
+#define erts_atomic_set_ddrb ethr_atomic_set_ddrb
+#define erts_atomic_read_ddrb ethr_atomic_read_ddrb
+#define erts_atomic_inc_read_ddrb ethr_atomic_inc_read_ddrb
+#define erts_atomic_dec_read_ddrb ethr_atomic_dec_read_ddrb
+#define erts_atomic_inc_ddrb ethr_atomic_inc_ddrb
+#define erts_atomic_dec_ddrb ethr_atomic_dec_ddrb
+#define erts_atomic_add_read_ddrb ethr_atomic_add_read_ddrb
+#define erts_atomic_add_ddrb ethr_atomic_add_ddrb
+#define erts_atomic_read_bor_ddrb ethr_atomic_read_bor_ddrb
+#define erts_atomic_read_band_ddrb ethr_atomic_read_band_ddrb
+#define erts_atomic_xchg_ddrb ethr_atomic_xchg_ddrb
+#define erts_atomic_cmpxchg_ddrb ethr_atomic_cmpxchg_ddrb
+
#define erts_atomic_init_rb ethr_atomic_init_rb
#define erts_atomic_set_rb ethr_atomic_set_rb
#define erts_atomic_read_rb ethr_atomic_read_rb
@@ -545,6 +801,20 @@ ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#define erts_atomic32_xchg_relb ethr_atomic32_xchg_relb
#define erts_atomic32_cmpxchg_relb ethr_atomic32_cmpxchg_relb
+#define erts_atomic32_init_ddrb ethr_atomic32_init_ddrb
+#define erts_atomic32_set_ddrb ethr_atomic32_set_ddrb
+#define erts_atomic32_read_ddrb ethr_atomic32_read_ddrb
+#define erts_atomic32_inc_read_ddrb ethr_atomic32_inc_read_ddrb
+#define erts_atomic32_dec_read_ddrb ethr_atomic32_dec_read_ddrb
+#define erts_atomic32_inc_ddrb ethr_atomic32_inc_ddrb
+#define erts_atomic32_dec_ddrb ethr_atomic32_dec_ddrb
+#define erts_atomic32_add_read_ddrb ethr_atomic32_add_read_ddrb
+#define erts_atomic32_add_ddrb ethr_atomic32_add_ddrb
+#define erts_atomic32_read_bor_ddrb ethr_atomic32_read_bor_ddrb
+#define erts_atomic32_read_band_ddrb ethr_atomic32_read_band_ddrb
+#define erts_atomic32_xchg_ddrb ethr_atomic32_xchg_ddrb
+#define erts_atomic32_cmpxchg_ddrb ethr_atomic32_cmpxchg_ddrb
+
#define erts_atomic32_init_rb ethr_atomic32_init_rb
#define erts_atomic32_set_rb ethr_atomic32_set_rb
#define erts_atomic32_read_rb ethr_atomic32_read_rb
@@ -597,6 +867,11 @@ ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#define erts_dw_atomic_read_relb erts_no_dw_atomic_read
#define erts_dw_atomic_cmpxchg_relb erts_no_dw_atomic_cmpxchg
+#define erts_dw_atomic_init_ddrb erts_no_dw_atomic_init
+#define erts_dw_atomic_set_ddrb erts_no_dw_atomic_set
+#define erts_dw_atomic_read_ddrb erts_no_dw_atomic_read
+#define erts_dw_atomic_cmpxchg_ddrb erts_no_dw_atomic_cmpxchg
+
#define erts_dw_atomic_init_rb erts_no_dw_atomic_init
#define erts_dw_atomic_set_rb erts_no_dw_atomic_set
#define erts_dw_atomic_read_rb erts_no_dw_atomic_read
@@ -665,6 +940,20 @@ ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#define erts_atomic_xchg_relb erts_no_atomic_xchg
#define erts_atomic_cmpxchg_relb erts_no_atomic_cmpxchg
+#define erts_atomic_init_ddrb erts_no_atomic_set
+#define erts_atomic_set_ddrb erts_no_atomic_set
+#define erts_atomic_read_ddrb erts_no_atomic_read
+#define erts_atomic_inc_read_ddrb erts_no_atomic_inc_read
+#define erts_atomic_dec_read_ddrb erts_no_atomic_dec_read
+#define erts_atomic_inc_ddrb erts_no_atomic_inc
+#define erts_atomic_dec_ddrb erts_no_atomic_dec
+#define erts_atomic_add_read_ddrb erts_no_atomic_add_read
+#define erts_atomic_add_ddrb erts_no_atomic_add
+#define erts_atomic_read_bor_ddrb erts_no_atomic_read_bor
+#define erts_atomic_read_band_ddrb erts_no_atomic_read_band
+#define erts_atomic_xchg_ddrb erts_no_atomic_xchg
+#define erts_atomic_cmpxchg_ddrb erts_no_atomic_cmpxchg
+
#define erts_atomic_init_rb erts_no_atomic_set
#define erts_atomic_set_rb erts_no_atomic_set
#define erts_atomic_read_rb erts_no_atomic_read
@@ -751,6 +1040,20 @@ ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);
#define erts_atomic32_xchg_relb erts_no_atomic32_xchg
#define erts_atomic32_cmpxchg_relb erts_no_atomic32_cmpxchg
+#define erts_atomic32_init_ddrb erts_no_atomic32_set
+#define erts_atomic32_set_ddrb erts_no_atomic32_set
+#define erts_atomic32_read_ddrb erts_no_atomic32_read
+#define erts_atomic32_inc_read_ddrb erts_no_atomic32_inc_read
+#define erts_atomic32_dec_read_ddrb erts_no_atomic32_dec_read
+#define erts_atomic32_inc_ddrb erts_no_atomic32_inc
+#define erts_atomic32_dec_ddrb erts_no_atomic32_dec
+#define erts_atomic32_add_read_ddrb erts_no_atomic32_add_read
+#define erts_atomic32_add_ddrb erts_no_atomic32_add
+#define erts_atomic32_read_bor_ddrb erts_no_atomic32_read_bor
+#define erts_atomic32_read_band_ddrb erts_no_atomic32_read_band
+#define erts_atomic32_xchg_ddrb erts_no_atomic32_xchg
+#define erts_atomic32_cmpxchg_ddrb erts_no_atomic32_cmpxchg
+
#define erts_atomic32_init_rb erts_no_atomic32_set
#define erts_atomic32_set_rb erts_no_atomic32_set
#define erts_atomic32_read_rb erts_no_atomic32_read
@@ -1128,6 +1431,16 @@ erts_cnd_wait(erts_cnd_t *cnd, erts_mtx_t *mtx)
#endif
}
+/*
+ * IMPORTANT note about erts_cnd_signal() and erts_cnd_broadcast()
+ *
+ * POSIX allow a call to `pthread_cond_signal' or `pthread_cond_broadcast'
+ * even though the associated mutex/mutexes isn't/aren't locked by the
+ * caller. Our implementation do not allow that in order to avoid a
+ * performance penalty. That is, all associated mutexes *need* to be
+ * locked by the caller of erts_cnd_signal()/erts_cnd_broadcast()!
+ */
+
ERTS_GLB_INLINE void
erts_cnd_signal(erts_cnd_t *cnd)
{
diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h
index 7a09d30ff6..6c6e193818 100644
--- a/erts/emulator/beam/erl_time.h
+++ b/erts/emulator/beam/erl_time.h
@@ -20,7 +20,11 @@
#ifndef ERL_TIME_H__
#define ERL_TIME_H__
-extern erts_smp_atomic_t do_time; /* set at clock interrupt */
+#define ERTS_SHORT_TIME_T_MAX ERTS_AINT32_T_MAX
+#define ERTS_SHORT_TIME_T_MIN ERTS_AINT32_T_MIN
+typedef erts_aint32_t erts_short_time_t;
+
+extern erts_smp_atomic32_t do_time; /* set at clock interrupt */
extern SysTimeval erts_first_emu_time;
/*
@@ -71,22 +75,32 @@ void erts_cancel_smp_ptimer(ErtsSmpPTimer *ptimer);
void erts_init_time(void);
void erts_set_timer(ErlTimer*, ErlTimeoutProc, ErlCancelProc, void*, Uint);
void erts_cancel_timer(ErlTimer*);
-void erts_bump_timer(erts_aint_t);
+void erts_bump_timer(erts_short_time_t);
Uint erts_timer_wheel_memory_size(void);
Uint erts_time_left(ErlTimer *);
-erts_aint_t erts_next_time(void);
+erts_short_time_t erts_next_time(void);
#ifdef DEBUG
void erts_p_slpq(void);
#endif
-ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void);
-ERTS_GLB_INLINE void erts_do_time_add(long);
+ERTS_GLB_INLINE erts_short_time_t erts_do_time_read_and_reset(void);
+ERTS_GLB_INLINE void erts_do_time_add(erts_short_time_t);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void) { return erts_smp_atomic_xchg_acqb(&do_time, 0L); }
-ERTS_GLB_INLINE void erts_do_time_add(long elapsed) { erts_smp_atomic_add_relb(&do_time, elapsed); }
+ERTS_GLB_INLINE erts_short_time_t erts_do_time_read_and_reset(void)
+{
+ erts_short_time_t time = erts_smp_atomic32_xchg_acqb(&do_time, 0);
+ if (time < 0)
+ erl_exit(ERTS_ABORT_EXIT, "Internal time management error\n");
+ return time;
+}
+
+ERTS_GLB_INLINE void erts_do_time_add(erts_short_time_t elapsed)
+{
+ erts_smp_atomic32_add_relb(&do_time, elapsed);
+}
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
@@ -105,7 +119,7 @@ void erts_get_now_cpu(Uint* megasec, Uint* sec, Uint* microsec);
#endif
void erts_get_timeval(SysTimeval *tv);
-long erts_get_time(void);
+erts_time_t erts_get_time(void);
void erts_get_emu_time(SysTimeval *);
ERTS_GLB_INLINE int erts_cmp_timeval(SysTimeval *t1p, SysTimeval *t2p);
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index ca4b54188e..f90daadadc 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -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
@@ -371,7 +371,7 @@ static void init_erts_deliver_time(const SysTimeval *inittv)
static void do_erts_deliver_time(const SysTimeval *current)
{
SysTimeval cur_time;
- long elapsed;
+ erts_time_t elapsed;
/* calculate and deliver appropriate number of ticks */
cur_time = *current;
@@ -385,7 +385,10 @@ static void do_erts_deliver_time(const SysTimeval *current)
this by simply pretend as if the time stood still. :) */
if (elapsed > 0) {
- erts_do_time_add(elapsed);
+
+ ASSERT(elapsed < ((erts_time_t) ERTS_SHORT_TIME_T_MAX));
+
+ erts_do_time_add((erts_short_time_t) elapsed);
last_delivered = cur_time;
}
}
@@ -421,11 +424,11 @@ erts_init_time_sup(void)
/* info functions */
void
-elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys,
- unsigned long *ms_user_diff, unsigned long *ms_sys_diff)
+elapsed_time_both(UWord *ms_user, UWord *ms_sys,
+ UWord *ms_user_diff, UWord *ms_sys_diff)
{
- unsigned long prev_total_user, prev_total_sys;
- unsigned long total_user, total_sys;
+ UWord prev_total_user, prev_total_sys;
+ UWord total_user, total_sys;
SysTimes now;
sys_times(&now);
@@ -456,9 +459,9 @@ elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys,
/* wall clock routines */
void
-wall_clock_elapsed_time_both(unsigned long *ms_total, unsigned long *ms_diff)
+wall_clock_elapsed_time_both(UWord *ms_total, UWord *ms_diff)
{
- unsigned long prev_total;
+ UWord prev_total;
SysTimeval tv;
erts_smp_mtx_lock(&erts_timeofday_mtx);
@@ -491,7 +494,7 @@ get_time(int *hour, int *minute, int *second)
the_clock = time((time_t *)0);
#ifdef HAVE_LOCALTIME_R
- localtime_r(&the_clock, (tm = &tmbuf));
+ tm = localtime_r(&the_clock, &tmbuf);
#else
tm = localtime(&the_clock);
#endif
@@ -513,7 +516,7 @@ get_date(int *year, int *month, int *day)
the_clock = time((time_t *)0);
#ifdef HAVE_LOCALTIME_R
- localtime_r(&the_clock, (tm = &tmbuf));
+ tm = localtime_r(&the_clock, &tmbuf);
#else
tm = localtime(&the_clock);
#endif
@@ -583,7 +586,44 @@ static const int mdays[14] = {0, 31, 28, 31, 30, 31, 30,
(((y) % 100) != 0)) || \
(((y) % 400) == 0))
-#define BASEYEAR 1970
+/* This is the earliest year we are sure to be able to handle
+ on all platforms w/o problems */
+#define BASEYEAR 1902
+
+/* A more "clever" mktime
+ * return 1, if successful
+ * return -1, if not successful
+ */
+
+static int erl_mktime(time_t *c, struct tm *tm) {
+ time_t clock;
+
+ clock = mktime(tm);
+
+ if (clock != -1) {
+ *c = clock;
+ return 1;
+ }
+
+ /* in rare occasions mktime returns -1
+ * when a correct value has been entered
+ *
+ * decrease seconds with one second
+ * if the result is -2, epochs should be -1
+ */
+
+ tm->tm_sec = tm->tm_sec - 1;
+ clock = mktime(tm);
+ tm->tm_sec = tm->tm_sec + 1;
+
+ *c = -1;
+
+ if (clock == -2) {
+ return 1;
+ }
+
+ return -1;
+}
/*
* gregday
@@ -592,10 +632,10 @@ static const int mdays[14] = {0, 31, 28, 31, 30, 31, 30,
* greater of equal to 1600 , and month [1-12] and day [1-31]
* are within range. Otherwise it returns -1.
*/
-static int long gregday(int year, int month, int day)
+static time_t gregday(int year, int month, int day)
{
- int long ndays = 0;
- int gyear, pyear, m;
+ Sint ndays = 0;
+ Sint gyear, pyear, m;
/* number of days in previous years */
gyear = year - 1600;
@@ -610,10 +650,77 @@ static int long gregday(int year, int month, int day)
if (is_leap_year(year) && (month > 2))
ndays++;
ndays += day - 1;
- return ndays - 135140; /* 135140 = Jan 1, 1970 */
+ return (time_t) (ndays - 135140); /* 135140 = Jan 1, 1970 */
}
+#define SECONDS_PER_MINUTE (60)
+#define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE)
+#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR)
+
+int seconds_to_univ(Sint64 time, Sint *year, Sint *month, Sint *day,
+ Sint *hour, Sint *minute, Sint *second) {
+
+ Sint y,mi;
+ Sint days = time / SECONDS_PER_DAY;
+ Sint secs = time % SECONDS_PER_DAY;
+ Sint tmp;
+
+ if (secs < 0) {
+ days--;
+ secs += SECONDS_PER_DAY;
+ }
+
+ tmp = secs % SECONDS_PER_HOUR;
+ *hour = secs / SECONDS_PER_HOUR;
+ *minute = tmp / SECONDS_PER_MINUTE;
+ *second = tmp % SECONDS_PER_MINUTE;
+
+ days += 719468;
+ y = (10000*((Sint64)days) + 14780) / 3652425;
+ tmp = days - (365 * y + y/4 - y/100 + y/400);
+
+ if (tmp < 0) {
+ y--;
+ tmp = days - (365*y + y/4 - y/100 + y/400);
+ }
+ mi = (100 * tmp + 52)/3060;
+ *month = (mi + 2) % 12 + 1;
+ *year = y + (mi + 2) / 12;
+ *day = tmp - (mi * 306 + 5)/10 + 1;
+
+ return 1;
+}
+
+int univ_to_seconds(Sint year, Sint month, Sint day, Sint hour, Sint minute, Sint second, Sint64 *time) {
+ Sint days;
+
+ if (!(IN_RANGE(1600, year, INT_MAX - 1) &&
+ IN_RANGE(1, month, 12) &&
+ IN_RANGE(1, day, (mdays[month] +
+ (month == 2
+ && (year % 4 == 0)
+ && (year % 100 != 0 || year % 400 == 0)))) &&
+ IN_RANGE(0, hour, 23) &&
+ IN_RANGE(0, minute, 59) &&
+ IN_RANGE(0, second, 59))) {
+ return 0;
+ }
+
+ days = gregday(year, month, day);
+ *time = SECONDS_PER_DAY;
+ *time *= days; /* don't try overflow it, it hurts */
+ *time += SECONDS_PER_HOUR * hour;
+ *time += SECONDS_PER_MINUTE * minute;
+ *time += second;
+
+ return 1;
+}
+
+#if defined(HAVE_TIME2POSIX) && defined(HAVE_DECL_TIME2POSIX) && \
+ !HAVE_DECL_TIME2POSIX
+extern time_t time2posix(time_t);
+#endif
int
local_to_univ(Sint *year, Sint *month, Sint *day,
@@ -644,15 +751,18 @@ local_to_univ(Sint *year, Sint *month, Sint *day,
t.tm_min = *minute;
t.tm_sec = *second;
t.tm_isdst = isdst;
- the_clock = mktime(&t);
- if (the_clock == -1) {
+
+ /* the nature of mktime makes this a bit interesting,
+ * up to four mktime calls could happen here
+ */
+
+ if (erl_mktime(&the_clock, &t) < 0) {
if (isdst) {
/* If this is a timezone without DST and the OS (correctly)
refuses to give us a DST time, we simulate the Linux/Solaris
behaviour of giving the same data as if is_dst was not set. */
t.tm_isdst = 0;
- the_clock = mktime(&t);
- if (the_clock == -1) {
+ if (erl_mktime(&the_clock, &t) < 0) {
/* Failed anyway, something else is bad - will be a badarg */
return 0;
}
@@ -661,11 +771,19 @@ local_to_univ(Sint *year, Sint *month, Sint *day,
return 0;
}
}
+
+#ifdef HAVE_TIME2POSIX
+ the_clock = time2posix(the_clock);
+#endif
+
#ifdef HAVE_GMTIME_R
- gmtime_r(&the_clock, (tm = &tmbuf));
+ tm = gmtime_r(&the_clock, &tmbuf);
#else
tm = gmtime(&the_clock);
#endif
+ if (!tm) {
+ return 0;
+ }
*year = tm->tm_year + 1900;
*month = tm->tm_mon +1;
*day = tm->tm_mday;
@@ -719,17 +837,20 @@ univ_to_local(Sint *year, Sint *month, Sint *day,
#endif
#ifdef HAVE_LOCALTIME_R
- localtime_r(&the_clock, (tm = &tmbuf));
+ tm = localtime_r(&the_clock, &tmbuf);
#else
tm = localtime(&the_clock);
#endif
- *year = tm->tm_year + 1900;
- *month = tm->tm_mon +1;
- *day = tm->tm_mday;
- *hour = tm->tm_hour;
- *minute = tm->tm_min;
- *second = tm->tm_sec;
- return 1;
+ if (tm) {
+ *year = tm->tm_year + 1900;
+ *month = tm->tm_mon +1;
+ *day = tm->tm_mday;
+ *hour = tm->tm_hour;
+ *minute = tm->tm_min;
+ *second = tm->tm_sec;
+ return 1;
+ }
+ return 0;
}
@@ -798,13 +919,14 @@ void erts_deliver_time(void) {
void erts_time_remaining(SysTimeval *rem_time)
{
- int ticks;
+ erts_time_t ticks;
SysTimeval cur_time;
- long elapsed;
+ erts_time_t elapsed;
/* erts_next_time() returns no of ticks to next timeout or -1 if none */
- if ((ticks = erts_next_time()) == -1) {
+ ticks = (erts_time_t) erts_next_time();
+ if (ticks == (erts_time_t) -1) {
/* timer queue empty */
/* this will cause at most 100000000 ticks */
rem_time->tv_sec = 100000;
@@ -839,7 +961,7 @@ void erts_get_timeval(SysTimeval *tv)
erts_smp_mtx_unlock(&erts_timeofday_mtx);
}
-long
+erts_time_t
erts_get_time(void)
{
SysTimeval sys_tv;
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 8833137112..009ca1eb52 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2012. All Rights Reserved.
*
* The 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,7 @@
#include "error.h"
#include "erl_binary.h"
#include "erl_bits.h"
+#include "erl_thr_progress.h"
#if 0
#define DEBUG_PRINTOUTS
@@ -124,8 +125,13 @@ do { \
enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, (FPID), (TPID), (MSG), (BP)); \
} while(0)
#else
+#ifdef USE_VM_PROBES
#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
- erts_queue_message((TPROC), NULL, (BP), (MSG), NIL)
+ erts_queue_message((TPROC), NULL, (BP), (MSG), NIL, NIL)
+#else
+#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
+ erts_queue_message((TPROC), NULL, (BP), (MSG), NIL)
+#endif
#endif
/*
@@ -159,7 +165,7 @@ static Uint active_sched;
void
erts_system_profile_setup_active_schedulers(void)
{
- ERTS_SMP_LC_ASSERT(erts_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_thr_progress_is_blocking());
active_sched = erts_active_schedulers();
}
@@ -543,7 +549,7 @@ send_to_port(Process *c_p, Eterm message,
*/
static void
-profile_send(Eterm message) {
+profile_send(Eterm from, Eterm message) {
Uint sz = 0;
ErlHeapFragment *bp = NULL;
Uint *hp = NULL;
@@ -553,6 +559,9 @@ profile_send(Eterm message) {
Eterm profiler = erts_get_system_profile();
+ /* do not profile profiler pid */
+ if (from == profiler) return;
+
if (is_internal_port(profiler)) {
Port *profiler_port = NULL;
@@ -579,7 +588,11 @@ profile_send(Eterm message) {
hp = erts_alloc_message_heap(sz, &bp, &off_heap, profile_p, 0);
msg = copy_struct(message, sz, &hp, &bp->off_heap);
- erts_queue_message(profile_p, NULL, bp, msg, NIL);
+ erts_queue_message(profile_p, NULL, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
}
@@ -990,9 +1003,13 @@ seq_trace_update_send(Process *p)
{
Eterm seq_tracer = erts_get_system_seq_tracer();
ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p))));
- if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL))
+ if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL)
+#ifdef USE_VM_PROBES
+ || (SEQ_TRACE_TOKEN(p) == am_have_dt_utag)
+#endif
+ ) {
return 0;
-
+ }
SEQ_TRACE_TOKEN_SENDER(p) = p->id; /* Internal pid */
SEQ_TRACE_TOKEN_SERIAL(p) =
make_small(++(p -> seq_trace_clock));
@@ -1174,7 +1191,11 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type,
enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SEQTRACE, NIL, NIL, mess, bp);
erts_smp_mtx_unlock(&smq_mtx);
#else
- erts_queue_message(tracer, NULL, bp, mess, NIL); /* trace_token must be NIL here */
+ erts_queue_message(tracer, NULL, bp, mess, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ ); /* trace_token must be NIL here */
#endif
}
}
@@ -1940,7 +1961,8 @@ trace_proc(Process *c_p, Process *t_p, Eterm what, Eterm data)
Eterm* hp;
int need;
- ERTS_SMP_LC_ASSERT((erts_proc_lc_my_proc_locks(t_p) != 0) || erts_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT((erts_proc_lc_my_proc_locks(t_p) != 0)
+ || erts_thr_progress_is_blocking());
if (is_internal_port(t_p->tracer_proc)) {
#define LOCAL_HEAP_SIZE (5+5)
DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE);
@@ -2092,8 +2114,7 @@ void save_calls(Process *p, Export *e)
* entries instead of the original BIF functions.
*/
Eterm
-erts_bif_trace(int bif_index, Process* p,
- Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I)
+erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I)
{
Eterm result;
int meta = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_META);
@@ -2107,10 +2128,10 @@ erts_bif_trace(int bif_index, Process* p,
* no tracing will occur. Doing the whole else branch will
* also do nothing, only slower.
*/
- Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*) = bif_table[bif_index].f;
- result = func(p, arg1, arg2, arg3, I);
+ Eterm (*func)(Process*, Eterm*, BeamInstr*) = bif_table[bif_index].f;
+ result = func(p, args, I);
} else {
- Eterm (*func)(Process*, Eterm, Eterm, Eterm, BeamInstr*);
+ Eterm (*func)(Process*, Eterm*, BeamInstr*);
Export* ep = bif_export[bif_index];
Uint32 flags = 0, flags_meta = 0;
int global = !!(erts_bif_trace_flags[bif_index] & BIF_TRACE_AS_GLOBAL);
@@ -2122,8 +2143,6 @@ erts_bif_trace(int bif_index, Process* p,
* export entry */
BeamInstr *cp = p->cp;
- Eterm args[3] = {arg1, arg2, arg3};
-
/*
* Make continuation pointer OK, it is not during direct BIF calls,
* but it is correct during apply of bif.
@@ -2155,7 +2174,7 @@ erts_bif_trace(int bif_index, Process* p,
func = bif_table[bif_index].f;
- result = func(p, arg1, arg2, arg3, I);
+ result = func(p, args, I);
if (applying && (flags & MATCH_SET_RETURN_TO_TRACE)) {
BeamInstr i_return_trace = beam_return_trace[0];
@@ -2467,7 +2486,11 @@ monitor_long_gc(Process *p, Uint time) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ erts_queue_message(monitor_p, NULL, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
#endif
}
@@ -2539,7 +2562,11 @@ monitor_large_heap(Process *p) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ erts_queue_message(monitor_p, NULL, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
#endif
}
@@ -2569,7 +2596,11 @@ monitor_generic(Process *p, Eterm type, Eterm spec) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ erts_queue_message(monitor_p, NULL, bp, msg, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
#endif
}
@@ -2618,7 +2649,7 @@ profile_scheduler(Eterm scheduler_id, Eterm state) {
make_small(active_sched), timestamp); hp += 7;
#ifndef ERTS_SMP
- profile_send(msg);
+ profile_send(NIL, msg);
UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
#undef LOCAL_HEAP_SIZE
#else
@@ -2653,7 +2684,7 @@ profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint M
timestamp = TUPLE3(hp, make_small(Ms), make_small(s), make_small(us)); hp += 4;
msg = TUPLE6(hp, am_profile, am_scheduler, scheduler_id, state, no_schedulers, timestamp); hp += 7;
#ifndef ERTS_SMP
- profile_send(msg);
+ profile_send(NIL, msg);
UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
#undef LOCAL_HEAP_SIZE
#else
@@ -2745,7 +2776,8 @@ trace_port(Port *t_p, Eterm what, Eterm data) {
Eterm mess;
Eterm* hp;
- ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(t_p) || erts_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(t_p)
+ || erts_thr_progress_is_blocking());
if (is_internal_port(t_p->tracer_proc)) {
#define LOCAL_HEAP_SIZE (5+5)
@@ -2919,11 +2951,11 @@ profile_runnable_port(Port *p, Eterm status) {
msg = TUPLE5(hp, am_profile, p->id, status, count, timestamp); hp += 6;
#ifndef ERTS_SMP
- profile_send(msg);
+ profile_send(p->id, msg);
UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
#undef LOCAL_HEAP_SIZE
#else
- enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp);
+ enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, p->id, NIL, msg, bp);
#endif
erts_smp_mtx_unlock(&smq_mtx);
}
@@ -2972,11 +3004,11 @@ profile_runnable_proc(Process *p, Eterm status){
timestamp = TUPLE3(hp, make_small(Ms), make_small(s), make_small(us)); hp += 4;
msg = TUPLE5(hp, am_profile, p->id, status, where, timestamp); hp += 6;
#ifndef ERTS_SMP
- profile_send(msg);
+ profile_send(p->id, msg);
UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE);
#undef LOCAL_HEAP_SIZE
#else
- enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp);
+ enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, p->id, NIL, msg, bp);
#endif
erts_smp_mtx_unlock(&smq_mtx);
}
@@ -3021,8 +3053,6 @@ static ErtsSysMsgQ *sys_message_queue_end;
static erts_tid_t sys_msg_dispatcher_tid;
static erts_cnd_t smq_cnd;
-static int dispatcher_waiting;
-
ERTS_QUALLOC_IMPL(smq_element, ErtsSysMsgQ, 20, ERTS_ALC_T_SYS_MSG_Q)
static void
@@ -3066,18 +3096,6 @@ enqueue_sys_msg(enum ErtsSysMsgType type,
erts_smp_mtx_unlock(&smq_mtx);
}
-static void
-prepare_for_block(void *unused)
-{
- erts_smp_mtx_unlock(&smq_mtx);
-}
-
-static void
-resume_after_block(void *unused)
-{
- erts_smp_mtx_lock(&smq_mtx);
-}
-
void
erts_queue_error_logger_message(Eterm from, Eterm msg, ErlHeapFragment *bp)
{
@@ -3143,10 +3161,10 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
&& !erts_system_monitor_flags.busy_port
&& !erts_system_monitor_flags.busy_dist_port)
break; /* Everything is disabled */
- erts_smp_block_system(ERTS_BS_FLG_ALLOW_GC);
+ erts_smp_thr_progress_block();
if (system_monitor == receiver || receiver == NIL)
erts_system_monitor_clear(NULL);
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case SYS_MSG_TYPE_SYSPROF:
if (receiver == NIL
@@ -3156,11 +3174,11 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
&& !erts_system_profile_flags.scheduler)
break;
/* Block system to clear flags */
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
if (system_profile == receiver || receiver == NIL) {
erts_system_profile_clear(NULL);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
break;
case SYS_MSG_TYPE_ERRLGR: {
char *no_elgger = "(no error logger present)";
@@ -3201,22 +3219,68 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
}
}
+static void
+sys_msg_dispatcher_wakeup(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ *wait_p = 0;
+ erts_smp_cnd_signal(&smq_cnd);
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
+static void
+sys_msg_dispatcher_prep_wait(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ *wait_p = 1;
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
+static void
+sys_msg_dispatcher_fin_wait(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ *wait_p = 0;
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
+static void
+sys_msg_dispatcher_wait(void *vwait_p)
+{
+ int *wait_p = (int *) vwait_p;
+ erts_smp_mtx_lock(&smq_mtx);
+ while (*wait_p)
+ erts_smp_cnd_wait(&smq_cnd, &smq_mtx);
+ erts_smp_mtx_unlock(&smq_mtx);
+}
+
static void *
sys_msg_dispatcher_func(void *unused)
{
+ ErtsThrPrgrCallbacks callbacks;
ErtsSysMsgQ *local_sys_message_queue = NULL;
+ int wait = 0;
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_set_thread_name("system message dispatcher");
#endif
- erts_register_blockable_thread();
- erts_smp_activity_begin(ERTS_ACTIVITY_IO, NULL, NULL, NULL);
+ callbacks.arg = (void *) &wait;
+ callbacks.wakeup = sys_msg_dispatcher_wakeup;
+ callbacks.prepare_wait = sys_msg_dispatcher_prep_wait;
+ callbacks.wait = sys_msg_dispatcher_wait;
+ callbacks.finalize_wait = sys_msg_dispatcher_fin_wait;
+
+ erts_thr_progress_register_managed_thread(NULL, &callbacks, 0);
while (1) {
+ int end_wait = 0;
ErtsSysMsgQ *smqp;
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
erts_smp_mtx_lock(&smq_mtx);
@@ -3228,20 +3292,16 @@ sys_msg_dispatcher_func(void *unused)
}
/* Fetch current trace message queue ... */
- erts_smp_activity_change(ERTS_ACTIVITY_IO,
- ERTS_ACTIVITY_WAIT,
- prepare_for_block,
- resume_after_block,
- NULL);
- dispatcher_waiting = 1;
+ if (!sys_message_queue) {
+ erts_smp_mtx_unlock(&smq_mtx);
+ end_wait = 1;
+ erts_thr_progress_active(NULL, 0);
+ erts_thr_progress_prepare_wait(NULL);
+ erts_smp_mtx_lock(&smq_mtx);
+ }
+
while (!sys_message_queue)
erts_smp_cnd_wait(&smq_cnd, &smq_mtx);
- dispatcher_waiting = 0;
- erts_smp_activity_change(ERTS_ACTIVITY_WAIT,
- ERTS_ACTIVITY_IO,
- prepare_for_block,
- resume_after_block,
- NULL);
local_sys_message_queue = sys_message_queue;
sys_message_queue = NULL;
@@ -3249,6 +3309,11 @@ sys_msg_dispatcher_func(void *unused)
erts_smp_mtx_unlock(&smq_mtx);
+ if (end_wait) {
+ erts_thr_progress_finalize_wait(NULL);
+ erts_thr_progress_active(NULL, 1);
+ }
+
/* Send trace messages ... */
ASSERT(local_sys_message_queue);
@@ -3259,6 +3324,9 @@ sys_msg_dispatcher_func(void *unused)
Process *proc = NULL;
Port *port = NULL;
+ if (erts_thr_progress_update(NULL))
+ erts_thr_progress_leader_update(NULL);
+
#ifdef DEBUG_PRINTOUTS
print_msg_type(smqp);
#endif
@@ -3318,7 +3386,11 @@ sys_msg_dispatcher_func(void *unused)
}
else {
queue_proc_msg:
- erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL);
+ erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
#ifdef DEBUG_PRINTOUTS
erts_fprintf(stderr, "delivered\n");
#endif
@@ -3372,7 +3444,6 @@ sys_msg_dispatcher_func(void *unused)
}
}
- erts_smp_activity_end(ERTS_ACTIVITY_IO, NULL, NULL, NULL);
return NULL;
}
@@ -3422,7 +3493,6 @@ init_sys_msg_dispatcher(void)
sys_message_queue_end = NULL;
erts_smp_cnd_init(&smq_cnd);
erts_smp_mtx_init(&smq_mtx, "sys_msg_q");
- dispatcher_waiting = 0;
erts_smp_thr_create(&sys_msg_dispatcher_tid,
sys_msg_dispatcher_func,
NULL,
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index 158eb361a4..127db4d4f6 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -47,7 +47,7 @@ typedef struct _restart_context {
static Uint max_loop_limit;
-static BIF_RETTYPE utf8_to_list(BIF_ALIST_1);
+static BIF_RETTYPE utf8_to_list(Process *p, Eterm arg1);
static BIF_RETTYPE finalize_list_to_list(Process *p,
byte *bytes,
Eterm rest,
@@ -227,8 +227,8 @@ static ERTS_INLINE int simple_loops_to_common(int cost)
static Sint aligned_binary_size(Eterm binary)
{
- unsigned char *bytes;
- Uint bitoffs;
+ ERTS_DECLARE_DUMMY(unsigned char *bytes);
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
Uint bitsize;
ERTS_GET_BINARY_BYTES(binary, bytes, bitoffs, bitsize);
@@ -348,12 +348,6 @@ static int copy_utf8_bin(byte *target, byte *source, Uint size,
return copied;
}
- if (((*source) == 0xEF) && (source[1] == 0xBF) &&
- ((source[2] == 0xBE) || (source[2] == 0xBF))) {
- *err_pos = source;
- return copied;
- }
-
*(target++) = *(source++);
*(target++) = *(source++);
*(target++) = *(source++);
@@ -714,9 +708,8 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x10000) {
- if ((x >= 0xD800 && x <= 0xDFFF) ||
- (x == 0xFFFE) ||
- (x == 0xFFFF)) { /* Invalid unicode range */
+ if (x >= 0xD800 && x <= 0xDFFF) {
+ /* Invalid unicode range */
*err = 1;
goto done;
}
@@ -901,7 +894,9 @@ static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,int pos,
static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3)
{
+#ifdef DEBUG
Eterm *real_bin;
+#endif
byte* bytes;
Eterm rest_term;
int left, sleft;
@@ -915,8 +910,10 @@ static BIF_RETTYPE characters_to_utf8_trap(BIF_ALIST_3)
/*erts_printf("Trap %T!\r\n",BIF_ARG_2);*/
ASSERT(is_binary(BIF_ARG_1));
+#ifdef DEBUG
real_bin = binary_val(BIF_ARG_1);
ASSERT(*real_bin == HEADER_PROC_BIN);
+#endif
pos = (int) binary_size(BIF_ARG_1);
bytes = binary_bytes(BIF_ARG_1);
sleft = left = allowed_iterations(BIF_P);
@@ -1230,10 +1227,6 @@ int erts_analyze_utf8(byte *source, Uint size,
((source[1] & 0x20) != 0)) {
return ERTS_UTF8_ERROR;
}
- if (((*source) == 0xEF) && (source[1] == 0xBF) &&
- ((source[2] == 0xBE) || (source[2] == 0xBF))) {
- return ERTS_UTF8_ERROR;
- }
source += 3;
size -= 3;
} else if (((*source) & ((byte) 0xF8)) == 0xF0) {
@@ -1730,7 +1723,7 @@ static BIF_RETTYPE do_bif_utf8_to_list(Process *p,
if (b_sz) {
ErlSubBin *sb;
Eterm orig;
- Uint offset;
+ ERTS_DECLARE_DUMMY(Uint offset);
ASSERT(state != ERTS_UTF8_OK);
hp = HAlloc(p, ERL_SUB_BIN_SIZE);
sb = (ErlSubBin *) hp;
@@ -1839,13 +1832,13 @@ static BIF_RETTYPE characters_to_list_trap_4(BIF_ALIST_1)
* Instead of building an utf8 buffer, we analyze the binary given and use that.
*/
-static BIF_RETTYPE utf8_to_list(BIF_ALIST_1)
+static BIF_RETTYPE utf8_to_list(Process* p, Eterm arg)
{
- if (!is_binary(BIF_ARG_1) || aligned_binary_size(BIF_ARG_1) < 0) {
- BIF_ERROR(BIF_P,BADARG);
+ if (!is_binary(arg) || aligned_binary_size(arg) < 0) {
+ BIF_ERROR(p, BADARG);
}
- return do_bif_utf8_to_list(BIF_P, BIF_ARG_1, 0U, 0U, 0U,
- ERTS_UTF8_ANALYZE_MORE,NIL);
+ return do_bif_utf8_to_list(p, arg, 0U, 0U, 0U,
+ ERTS_UTF8_ANALYZE_MORE, NIL);
}
@@ -2034,12 +2027,14 @@ BIF_RETTYPE binary_to_existing_atom_2(BIF_ALIST_2)
* string routines, that will certainly fail on some OS.
*/
-char *erts_convert_filename_to_native(Eterm name, ErtsAlcType_t alloc_type, int allow_empty)
+char *erts_convert_filename_to_native(Eterm name, char *statbuf, size_t statbuf_size, ErtsAlcType_t alloc_type, int allow_empty, int allow_atom, Sint *used)
{
int encoding = erts_get_native_filename_encoding();
char* name_buf = NULL;
- if (is_atom(name) || is_list(name) || (allow_empty && is_nil(name))) {
+ if ((allow_atom && is_atom(name)) ||
+ is_list(name) ||
+ (allow_empty && is_nil(name))) {
Sint need;
if ((need = erts_native_filename_need(name,encoding)) < 0) {
return NULL;
@@ -2049,7 +2044,13 @@ char *erts_convert_filename_to_native(Eterm name, ErtsAlcType_t alloc_type, int
} else {
++need;
}
- name_buf = (char *) erts_alloc(alloc_type, need);
+ if (used)
+ *used = (Sint) need;
+ if (need > statbuf_size) {
+ name_buf = (char *) erts_alloc(alloc_type, need);
+ } else {
+ name_buf = statbuf;
+ }
erts_native_filename_put(name,encoding,(byte *)name_buf);
name_buf[need-1] = 0;
if (encoding == ERL_FILENAME_WIN_WCHAR) {
@@ -2065,14 +2066,26 @@ char *erts_convert_filename_to_native(Eterm name, ErtsAlcType_t alloc_type, int
bytes = erts_get_aligned_binary_bytes(name, &temp_alloc);
if (encoding != ERL_FILENAME_WIN_WCHAR) {
/*Add 0 termination only*/
- name_buf = (char *) erts_alloc(alloc_type, size+1);
+ if (used)
+ *used = (Sint) size+1;
+ if (size+1 > statbuf_size) {
+ name_buf = (char *) erts_alloc(alloc_type, size+1);
+ } else {
+ name_buf = statbuf;
+ }
memcpy(name_buf,bytes,size);
name_buf[size]=0;
} else if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK ||
erts_get_user_requested_filename_encoding() == ERL_FILENAME_LATIN1) {
byte *p;
/* What to do now? Maybe latin1, so just take byte for byte instead */
- name_buf = (char *) erts_alloc(alloc_type, (size+1)*2);
+ if (used)
+ *used = (Sint) (size+1)*2;
+ if ((size+1)*2 > statbuf_size) {
+ name_buf = (char *) erts_alloc(alloc_type, (size+1)*2);
+ } else {
+ name_buf = statbuf;
+ }
p = (byte *) name_buf;
while (size--) {
*p++ = *bytes++;
@@ -2081,7 +2094,13 @@ char *erts_convert_filename_to_native(Eterm name, ErtsAlcType_t alloc_type, int
*p++ = 0;
*p++ = 0;
} else { /* WIN_WCHAR and valid UTF8 */
- name_buf = (char *) erts_alloc(alloc_type, (num_chars+1)*2);
+ if (used)
+ *used = (Sint) (num_chars+1)*2;
+ if ((num_chars+1)*2 > statbuf_size) {
+ name_buf = (char *) erts_alloc(alloc_type, (num_chars+1)*2);
+ } else {
+ name_buf = statbuf;
+ }
erts_copy_utf8_to_utf16_little((byte *) name_buf, bytes, num_chars);
name_buf[num_chars*2] = 0;
name_buf[num_chars*2+1] = 0;
@@ -2093,6 +2112,71 @@ char *erts_convert_filename_to_native(Eterm name, ErtsAlcType_t alloc_type, int
return name_buf;
}
+static int filename_len_16bit(byte *str)
+{
+ byte *p = str;
+ while(*p != '\0' || p[1] != '\0') {
+ p += 2;
+ }
+ return (p - str);
+}
+Eterm erts_convert_native_to_filename(Process *p, byte *bytes)
+{
+ Uint size,num_chars;
+ Eterm *hp;
+ byte *err_pos;
+ Uint num_built; /* characters */
+ Uint num_eaten; /* bytes */
+ Eterm ret;
+ int mac = 0;
+
+ switch (erts_get_native_filename_encoding()) {
+ case ERL_FILENAME_LATIN1:
+ goto noconvert;
+ case ERL_FILENAME_UTF8_MAC:
+ mac = 1;
+ case ERL_FILENAME_UTF8:
+ size = strlen((char *) bytes);
+ if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK) {
+ goto noconvert;
+ }
+ num_built = 0;
+ num_eaten = 0;
+ if (mac) {
+ ret = do_utf8_to_list_normalize(p, num_chars, bytes, size);
+ } else {
+ ret = do_utf8_to_list(p, num_chars, bytes, size, num_chars, &num_built, &num_eaten, NIL);
+ }
+ return ret;
+ case ERL_FILENAME_WIN_WCHAR:
+ size=filename_len_16bit(bytes);
+ if ((size % 2) != 0) { /* Panic fixup to avoid crashing the emulator */
+ size--;
+ hp = HAlloc(p, size+2);
+ ret = CONS(hp,make_small((Uint) bytes[size]),NIL);
+ hp += 2;
+ } else {
+ hp = HAlloc(p, size);
+ ret = NIL;
+ }
+ bytes += size-1;
+ while (size > 0) {
+ Uint x = ((Uint) *bytes--) << 8;
+ x |= ((Uint) *bytes--);
+ size -= 2;
+ ret = CONS(hp,make_small(x),ret);
+ hp += 2;
+ }
+ return ret;
+ default:
+ goto noconvert;
+ }
+ noconvert:
+ size = strlen((char *) bytes);
+ hp = HAlloc(p, 2 * size);
+ return erts_bin_bytes_to_list(NIL, hp, bytes, size, 0);
+}
+
Sint erts_native_filename_need(Eterm ioterm, int encoding)
{
@@ -2166,9 +2250,8 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
} else if (x < 0x800) {
need += 2;
} else if (x < 0x10000) {
- if ((x >= 0xD800 && x <= 0xDFFF) ||
- (x == 0xFFFE) ||
- (x == 0xFFFF)) { /* Invalid unicode range */
+ if (x >= 0xD800 && x <= 0xDFFF) {
+ /* Invalid unicode range */
DESTROY_ESTACK(stack);
return ((Sint) -1);
}
@@ -2314,9 +2397,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
*p++ = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x10000) {
- ASSERT(!((x >= 0xD800 && x <= 0xDFFF) ||
- (x == 0xFFFE) ||
- (x == 0xFFFF)));
+ ASSERT(!(x >= 0xD800 && x <= 0xDFFF));
*p++ = (((byte) (x >> 12)) |
((byte) 0xE0));
*p++ = ((((byte) (x >> 6)) & 0x3F) |
@@ -2580,11 +2661,11 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1)
BIF_RETTYPE prim_file_internal_normalize_utf8_1(BIF_ALIST_1)
{
- Eterm real_bin;
- Uint offset;
+ ERTS_DECLARE_DUMMY(Eterm real_bin);
+ ERTS_DECLARE_DUMMY(Uint offset);
Uint size,num_chars;
Uint bitsize;
- Uint bitoffs;
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
Eterm ret;
byte *temp_alloc = NULL;
byte *bytes;
@@ -2629,3 +2710,4 @@ BIF_RETTYPE file_native_name_encoding_0(BIF_ALIST_0)
BIF_RET(am_undefined);
}
}
+
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index e7fd144ec3..a0e12e57f2 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -29,19 +29,10 @@
/* #define FORCE_HEAP_FRAGS */
-#if defined(HYBRID)
-/* # define CHECK_FOR_HOLES */
-#endif
-
#if defined(DEBUG) && !defined(CHECK_FOR_HOLES) && !defined(__WIN32__)
# define CHECK_FOR_HOLES
#endif
-#if defined(HYBRID)
-/* # define INCREMENTAL 1 */ /* Incremental garbage collection */
-/* # define INC_TIME_BASED 1 */ /* Time-based incremental GC (vs Work-based) */
-#endif
-
#define BEAM 1
#define EMULATOR "BEAM"
#define SEQ_TRACE 1
@@ -55,7 +46,7 @@
heap data on the C stack or if we use the buffers in the scheduler data. */
#define TMP_HEAP_SIZE 128 /* Number of Eterm in the schedulers
small heap for transient heap data */
-#define CMP_TMP_HEAP_SIZE 2 /* cmp wants its own tmp-heap... */
+#define CMP_TMP_HEAP_SIZE 32 /* cmp wants its own tmp-heap... */
#define ERL_ARITH_TMP_HEAP_SIZE 4 /* as does erl_arith... */
#define BEAM_EMU_TMP_HEAP_SIZE 2 /* and beam_emu... */
@@ -70,24 +61,10 @@
#define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */
#define VH_DEFAULT_SIZE 32768 /* default virtual (bin) heap min size (words) */
-#ifdef HYBRID
-# define SH_DEFAULT_SIZE 2629425 /* default message area min size */
-#endif
-
-#ifdef INCREMENTAL
-# define INC_NoPAGES 256 /* Number of pages in the old generation */
-# define INC_PAGESIZE 32768 /* The size of each page */
-# define INC_STORAGE_SIZE 1024 /* The size of gray stack and similar */
-#endif
-
#define CP_SIZE 1
#define ErtsHAllocLockCheck(P) \
- ERTS_SMP_LC_ASSERT((ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks((P))) \
- || ((P)->id == ERTS_INVALID_PID) \
- || ((P)->scheduler_data \
- && (P) == (P)->scheduler_data->match_pseudo_process) \
- || erts_is_system_blocked(0))
+ ERTS_SMP_LC_ASSERT(erts_dbg_check_halloc_lock((P)))
#ifdef DEBUG
diff --git a/erts/emulator/beam/erlang_dtrace.d b/erts/emulator/beam/erlang_dtrace.d
new file mode 100644
index 0000000000..bdfde58845
--- /dev/null
+++ b/erts/emulator/beam/erlang_dtrace.d
@@ -0,0 +1,3636 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Dustin Sallings, Michal Ptaszek, Scott Lystig Fritchie 2011-2012.
+ * All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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 note on probe naming: if "__" appears in a provider probe
+ * definition, then two things happen during compilation:
+ *
+ * 1. The "__" will turn into a hypen, "-", for the probe name.
+ * 2. The "__" will turn into a single underscore, "_", for the
+ * macro names and function definitions that the compiler and
+ * C developers will see.
+ *
+ * We'll try to use the following naming convention. We're a bit
+ * limited because, as a USDT probe, we can only specify the 4th part
+ * of the probe name, e.g. erlang*:::mumble. The 2nd part of the
+ * probe name is always going to be "beam" or "beam.smp", and the 3rd
+ * part of the probe name will always be the name of the function
+ * that's calling the probe.
+ *
+ * So, all probes will be have names defined in this file using the
+ * convention category__name or category__sub_category__name. This
+ * will translate to probe names of category-name or
+ * category-sub_category-name.
+ *
+ * Each of "category", "sub_category", and "name" may have underscores
+ * but may not have hyphens.
+ */
+
+provider erlang {
+ /**
+ * Fired when a message is sent from one local process to another.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * @param sender the PID (string form) of the sender
+ * @param receiver the PID (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__send(char *sender, char *receiver, uint32_t size,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a message is sent from a local process to a remote process.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * @param sender the PID (string form) of the sender
+ * @param node_name the Erlang node name (string form) of the receiver
+ * @param receiver the PID/name (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__send__remote(char *sender, char *node_name, char *receiver,
+ uint32_t size,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a message is queued to a local process. This probe
+ * will not fire if the sender's pid == receiver's pid.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * NOTE: In cases of messages in external format (i.e. from another
+ * Erlang node), we probably don't know the message size
+ * without performing substantial extra computation. To
+ * avoid the extra CPU overhead, the message size may be
+ * reported as -1, which can appear to a D script as 4294967295.
+ *
+ * @param receiver the PID (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param queue_len length of the queue of the receiving process
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__queued(char *receiver, uint32_t size, uint32_t queue_len,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a message is 'receive'd by a local process and removed
+ * from its mailbox.
+ *
+ * NOTE: The 'size' parameter is in machine-dependent words and
+ * that the actual size of any binary terms in the message
+ * are not included.
+ *
+ * NOTE: In cases of messages in external format (i.e. from another
+ * Erlang node), we probably don't know the message size
+ * without performing substantial extra computation. To
+ * avoid the extra CPU overhead, the message size may be
+ * reported as -1, which can appear to a D script as 4294967295.
+ *
+ * @param receiver the PID (string form) of the receiver
+ * @param size the size of the message being delivered (words)
+ * @param queue_len length of the queue of the receiving process
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe message__receive(char *receiver, uint32_t size, uint32_t queue_len,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when an Eterm structure is being copied.
+ *
+ * NOTE: Due to the placement of this probe, the process ID of
+ * owner of the Eterm is not available.
+ *
+ * @param size the size of the structure
+ */
+ probe copy__struct(uint32_t size);
+
+ /**
+ * Fired when an Eterm is being copied onto a process.
+ *
+ * @param proc the PID (string form) of the recipient process
+ * @param size the size of the structure
+ */
+ probe copy__object(char *proc, uint32_t size);
+
+ /* PID, Module, Function, Arity */
+
+ /**
+ * Fired whenever a user function is being called locally.
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ * @param depth the stack depth
+ */
+ probe local__function__entry(char *p, char *mfa, int depth);
+
+ /**
+ * Fired whenever a user function is called externally
+ * (through an export entry).
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ * @param depth the stack depth
+ */
+ probe global__function__entry(char *p, char *mfa, int depth);
+
+ /**
+ * Fired whenever a user function returns.
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ * @param depth the stack depth
+ */
+ probe function__return(char *p, char *mfa, int depth);
+
+ /**
+ * Fired whenever a Built In Function is called.
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ */
+ probe bif__entry(char *p, char *mfa);
+
+ /**
+ * Fired whenever a Built In Function returns.
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ */
+ probe bif__return(char *p, char *mfa);
+
+ /**
+ * Fired whenever a Native Function is called.
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ */
+ probe nif__entry(char *p, char *mfa);
+
+ /**
+ * Fired whenever a Native Function returns.
+ *
+ * @param p the PID (string form) of the process
+ * @param mfa the m:f/a of the function
+ */
+ probe nif__return(char *p, char *mfa);
+
+ /**
+ * Fired when a major GC is starting.
+ *
+ * @param p the PID (string form) of the exiting process
+ * @param need the number of words needed on the heap
+ */
+ probe gc_major__start(char *p, int need);
+
+ /**
+ * Fired when a minor GC is starting.
+ *
+ * @param p the PID (string form) of the exiting process
+ * @param need the number of words needed on the heap
+ */
+ probe gc_minor__start(char *p, int need);
+
+ /**
+ * Fired when a major GC is starting.
+ *
+ * @param p the PID (string form) of the exiting process
+ * @param reclaimed the amount of space reclaimed
+ */
+ probe gc_major__end(char *p, int reclaimed);
+
+ /**
+ * Fired when a minor GC is starting.
+ *
+ * @param p the PID (string form) of the exiting process
+ * @param reclaimed the amount of space reclaimed
+ */
+ probe gc_minor__end(char *p, int reclaimed);
+
+ /**
+ * Fired when a process is spawned.
+ *
+ * @param p the PID (string form) of the new process.
+ * @param mfa the m:f/a of the function
+ */
+ probe process__spawn(char *p, char *mfa);
+
+ /**
+ * Fired when a process is exiting.
+ *
+ * @param p the PID (string form) of the exiting process
+ * @param reason the reason for the exit (may be truncated)
+ */
+ probe process__exit(char *p, char *reason);
+
+ /**
+ * Fired when exit signal is delivered to a local process.
+ *
+ * @param sender the PID (string form) of the exiting process
+ * @param receiver the PID (string form) of the process receiving EXIT signal
+ * @param reason the reason for the exit (may be truncated)
+ */
+ probe process__exit_signal(char *sender, char *receiver, char *reason);
+
+ /**
+ * Fired when exit signal is delivered to a remote process.
+ *
+ * @param sender the PID (string form) of the exiting process
+ * @param node_name the Erlang node name (string form) of the receiver
+ * @param receiver the PID (string form) of the process receiving EXIT signal
+ * @param reason the reason for the exit (may be truncated)
+ * @param token_label for the sender's sequential trace token
+ * @param token_previous count for the sender's sequential trace token
+ * @param token_current count for the sender's sequential trace token
+ */
+ probe process__exit_signal__remote(char *sender, char *node_name,
+ char *receiver, char *reason,
+ int token_label, int token_previous, int token_current);
+
+ /**
+ * Fired when a process is scheduled.
+ *
+ * @param p the PID (string form) of the newly scheduled process
+ * @param mfa the m:f/a of the function it should run next
+ */
+ probe process__scheduled(char *p, char *mfa);
+
+ /**
+ * Fired when a process is unscheduled.
+ *
+ * @param p the PID (string form) of the process that has been
+ * unscheduled.
+ */
+ probe process__unscheduled(char *p);
+
+ /**
+ * Fired when a process goes into hibernation.
+ *
+ * @param p the PID (string form) of the process entering hibernation
+ * @param mfa the m:f/a of the location to resume
+ */
+ probe process__hibernate(char *p, char *mfa);
+
+ /**
+ * Fired when a process is unblocked after a port has been unblocked.
+ *
+ * @param p the PID (string form) of the process that has been
+ * unscheduled.
+ * @param port the port that is no longer busy (i.e., is now unblocked)
+ */
+ probe process__port_unblocked(char *p, char *port);
+
+ /**
+ * Fired when process' heap is growing.
+ *
+ * @param p the PID (string form)
+ * @param old_size the size of the old heap
+ * @param new_size the size of the new heap
+ */
+ probe process__heap_grow(char *p, int old_size, int new_size);
+
+ /**
+ * Fired when process' heap is shrinking.
+ *
+ * @param p the PID (string form)
+ * @param old_size the size of the old heap
+ * @param new_size the size of the new heap
+ */
+ probe process__heap_shrink(char *p, int old_size, int new_size);
+
+ /* network distribution */
+
+ /**
+ * Fired when network distribution event monitor events are triggered.
+ *
+ * @param node the name of the reporting node
+ * @param what the type of event, e.g., nodeup, nodedown
+ * @param monitored_node the name of the monitored node
+ * @param type the type of node, e.g., visible, hidden
+ * @param reason the reason term, e.g., normal, connection_closed, term()
+ */
+ probe dist__monitor(char *node, char *what, char *monitored_node,
+ char *type, char *reason);
+
+ /**
+ * Fired when network distribution port is busy (i.e. blocked),
+ * usually due to the remote node not consuming distribution
+ * data quickly enough.
+ *
+ * @param node the name of the reporting node
+ * @param port the port ID of the busy port
+ * @param remote_node the name of the remote node.
+ * @param pid the PID (string form) of the local process that has
+ * become unschedulable until the port becomes unblocked.
+ */
+ probe dist__port_busy(char *node, char *port, char *remote_node,
+ char *pid);
+
+ /**
+ * Fired when network distribution's driver's "output" callback is called
+ *
+ * @param node the name of the reporting node
+ * @param port the port ID of the busy port
+ * @param remote_node the name of the remote node.
+ * @param bytes the number of bytes written
+ */
+ probe dist__output(char *node, char *port, char *remote_node, int bytes);
+
+ /**
+ * Fired when network distribution's driver's "outputv" callback is called
+ *
+ * @param node the name of the reporting node
+ * @param port the port ID of the busy port
+ * @param remote_node the name of the remote node.
+ * @param bytes the number of bytes written
+ */
+ probe dist__outputv(char *node, char *port, char *remote_node, int bytes);
+
+ /**
+ * Fired when network distribution port is no longer busy (i.e. blocked).
+ *
+ * NOTE: This probe may fire multiple times after the same single
+ * dist-port_busy probe firing.
+ *
+ * @param node the name of the reporting node
+ * @param port the port ID of the busy port
+ * @param remote_node the name of the remote node.
+ */
+ probe dist__port_not_busy(char *node, char *port, char *remote_node);
+
+ /* ports */
+
+ /**
+ * Fired when new port is opened.
+ *
+ * @param process the PID (string form)
+ * @param port_name the string used when the port was opened
+ * @param port the Port (string form) of the new port
+ */
+ probe port__open(char *process, char *port_name, char *port);
+
+ /**
+ * Fired when port_command is issued.
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param command_type type of the issued command, one of: "close", "command" or "connect"
+ */
+ probe port__command(char *process, char *port, char *port_name, char *command_type);
+
+ /**
+ * Fired when port_control is issued.
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param command_no command number that has been issued to the port
+ */
+ probe port__control(char *process, char *port, char *port_name, int command_no);
+
+ /**
+ * Fired when port is closed via port_close/1 (reason = 'normal')
+ * or is sent an exit signal.
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param reason Erlang term representing the exit signal, e.g. 'normal'
+ */
+ probe port__exit(char *process, char *port, char *port_name,
+ char *new_process);
+
+ /**
+ * Fired when port_connect is issued.
+ *
+ * @param process the PID (string form) of the current port owner
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param new_process the PID (string form) of the new port owner
+ */
+ probe port__connect(char *process, char *port, char *port_name,
+ char *new_process);
+
+ /**
+ * Fired when a port is busy (i.e. blocked)
+ *
+ * @param port the port ID of the busy port
+ */
+ probe port__busy(char *port);
+
+ /**
+ * Fired when a port is no longer busy (i.e. no longer blocked)
+ *
+ * @param port the port ID of the not busy port
+ */
+ probe port__not_busy(char *port);
+
+ /* drivers */
+
+ /**
+ * Fired when drivers's "init" callback is called.
+ *
+ * @param name the name of the driver
+ * @param major the major version number
+ * @param minor the minor version number
+ * @param flags the flags argument
+ */
+ probe driver__init(char *name, int major, int minor, int flags);
+
+ /**
+ * Fired when drivers's "start" callback is called.
+ *
+ * @param process the PID (string form) of the calling process
+ * @param name the name of the driver
+ * @param port the Port (string form) of the driver's port
+ */
+ probe driver__start(char *process, char *name, char *port);
+
+ /**
+ * Fired when drivers's "stop" callback is called.
+ *
+ * @param process the PID (string form) of the calling process
+ * @param name the name of the driver
+ * @param port the Port (string form) of the driver's port
+ */
+ probe driver__stop(char *process, char *name, char *port);
+
+ /**
+ * Fired when drivers's "finish" callback is called.
+ *
+ * @param name the name of the driver
+ */
+ probe driver__finish(char *name);
+
+ /**
+ * Fired when drivers's "flush" callback is called.
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__flush(char *process, char *port, char *port_name);
+
+ /**
+ * Fired when driver's "output" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param bytes the number of bytes written
+ */
+ probe driver__output(char *node, char *port, char *port_name, int bytes);
+
+ /**
+ * Fired when driver's "outputv" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param bytes the number of bytes written
+ */
+ probe driver__outputv(char *node, char *port, char *port_name, int bytes);
+
+ /**
+ * Fired when driver's "control" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param command the command #
+ * @param bytes the number of bytes written
+ */
+ probe driver__control(char *node, char *port, char *port_name,
+ int command, int bytes);
+
+ /**
+ * Fired when driver's "call" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ * @param command the command #
+ * @param bytes the number of bytes written
+ */
+ probe driver__call(char *node, char *port, char *port_name,
+ int command, int bytes);
+
+ /**
+ * Fired when driver's "event" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__event(char *node, char *port, char *port_name);
+
+ /**
+ * Fired when driver's "ready_input" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__ready_input(char *node, char *port, char *port_name);
+
+ /**
+ * Fired when driver's "read_output" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__ready_output(char *node, char *port, char *port_name);
+
+ /**
+ * Fired when driver's "timeout" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__timeout(char *node, char *port, char *port_name);
+
+ /**
+ * Fired when drivers's "ready_async" callback is called.
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__ready_async(char *process, char *port, char *port_name);
+
+ /**
+ * Fired when driver's "process_exit" callback is called
+ *
+ * @param process the PID (string form)
+ * @param port the Port (string form)
+ * @param port_name the string used when the port was opened
+ */
+ probe driver__process_exit(char *node, char *port, char *port_name);
+
+ /**
+ * Fired when driver's "stop_select" callback is called
+ *
+ * @param name the name of the driver
+ */
+ probe driver__stop_select(char *name);
+
+
+ /* Async driver pool */
+
+ /**
+ * Show the post-add length of the async driver thread pool member's queue.
+ *
+ * NOTE: The port name is not available: additional lock(s) must
+ * be acquired in order to get the port name safely in an SMP
+ * environment. The same is true for the aio__pool_get probe.
+ *
+ * @param port the Port (string form)
+ * @param new queue length
+ */
+ probe aio_pool__add(char *, int);
+
+ /**
+ * Show the post-get length of the async driver thread pool member's queue.
+ *
+ * @param port the Port (string form)
+ * @param new queue length
+ */
+ probe aio_pool__get(char *, int);
+
+ /* Probes for efile_drv.c */
+
+ /**
+ * Entry into the efile_drv.c file I/O driver
+ *
+ * For a list of command numbers used by this driver, see the section
+ * "Guide to probe arguments" in ../../../README.md. That section
+ * also contains explanation of the various integer and string
+ * arguments that may be present when any particular probe fires.
+ *
+ * NOTE: Not all Linux platforms (using SystemTap) can support
+ * arguments beyond arg9.
+ *
+ *
+ * TODO: Adding the port string, args[10], is a pain. Making that
+ * port string available to all the other efile_drv.c probes
+ * will be more pain. Is the pain worth it? If yes, then
+ * add them everywhere else and grit our teeth. If no, then
+ * rip it out.
+ *
+ * @param thread-id number of the scheduler Pthread arg0
+ * @param tag number: {thread-id, tag} uniquely names a driver operation
+ * @param user-tag string arg2
+ * @param command number arg3
+ * @param string argument 1 arg4
+ * @param string argument 2 arg5
+ * @param integer argument 1 arg6
+ * @param integer argument 2 arg7
+ * @param integer argument 3 arg8
+ * @param integer argument 4 arg9
+ * @param port the port ID of the busy port args[10]
+ */
+ probe efile_drv__entry(int, int, char *, int, char *, char *,
+ int64_t, int64_t, int64_t, int64_t, char *);
+
+ /**
+ * Entry into the driver's internal work function. Computation here
+ * is performed by a async worker pool Pthread.
+ *
+ * @param thread-id number
+ * @param tag number
+ * @param command number
+ */
+ probe efile_drv__int_entry(int, int, int);
+
+ /**
+ * Return from the driver's internal work function.
+ *
+ * @param thread-id number
+ * @param tag number
+ * @param command number
+ */
+ probe efile_drv__int_return(int, int, int);
+
+ /**
+ * Return from the efile_drv.c file I/O driver
+ *
+ * @param thread-id number arg0
+ * @param tag number arg1
+ * @param user-tag string arg2
+ * @param command number arg3
+ * @param Success? 1 is success, 0 is failure arg4
+ * @param If failure, the errno of the error. arg5
+ */
+ probe efile_drv__return(int, int, char *, int, int, int);
+
+/*
+ * NOTE:
+ * For formatting int64_t arguments within a D script, see:
+ *
+ * http://mail.opensolaris.org/pipermail/dtrace-discuss/2006-November/002830.html
+ * Summary:
+ * "1) you don't need the 'l' printf() modifiers with DTrace ever"
+ */
+
+/*
+ * NOTE: For file_drv_return + SMP + R14B03 (and perhaps other
+ * releases), the sched-thread-id will be the same as the
+ * work-thread-id: erl_async.c's async_main() function
+ * will call the asynchronous invoke function and then
+ * immediately call the drivers ready_async function while
+ * inside the same I/O worker pool thread.
+ * For R14B03's source, see erl_async.c lines 302-317.
+ */
+
+/*
+ * The set of probes for use by Erlang code ... moved to here from
+ * lib/runtime_tools/c_src/dtrace_user.d until a more portable solution
+ * is found. This move pollutes the Erlang VM with functions that are
+ * only used by the NIF shared library code in
+ * lib/runtime_tools/c_src/dyntrace.c. The reason this is necessary is
+ * in order to work around an issue on several platforms, including
+ * SystemTap 1.3 and Solaris. The Solaris issue is discussed in the
+ * `dtrace-discuss` mailing list thread on 01 Dec 2011 17:58:15.
+ */
+ /**
+ * If you use only a single probe, but you also embed that probe
+ * in many different places in your code, if that probe fires 100K
+ * or more times per second, then it *will* hurt when you have to
+ * enable that probe.
+ *
+ * However, if you have any different probes, then you can ensure
+ * that any probe on a hot code path will use separate probe(s)
+ * than everyone else ... and you can then enable many non-hot
+ * probes in production without worry about creating too much
+ * measurement overhead.
+ *
+ * In an ideal world, we would use the libusdt library to be able
+ * to create arbitrary DTrace probes with more convenient and
+ * meaningful names than "user_trace-n7". But libusdt doesn't
+ * (yet) support all of the platforms that DTrace does, and there
+ * is no known (yet) equivalent for SystemTap.
+ */
+ probe user_trace__n0(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n1(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n2(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n3(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n4(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n5(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n6(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n7(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n8(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n9(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n10(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n11(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n12(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n13(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n14(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n15(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n16(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n17(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n18(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n19(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n20(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n21(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n22(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n23(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n24(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n25(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n26(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n27(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n28(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n29(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n30(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n31(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n32(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n33(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n34(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n35(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n36(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n37(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n38(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n39(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n40(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n41(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n42(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n43(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n44(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n45(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n46(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n47(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n48(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n49(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n50(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n51(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n52(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n53(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n54(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n55(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n56(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n57(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n58(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n59(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n60(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n61(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n62(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n63(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n64(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n65(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n66(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n67(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n68(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n69(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n70(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n71(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n72(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n73(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n74(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n75(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n76(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n77(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n78(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n79(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n80(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n81(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n82(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n83(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n84(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n85(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n86(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n87(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n88(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n89(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n90(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n91(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n92(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n93(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n94(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n95(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n96(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n97(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n98(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n99(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n100(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n101(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n102(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n103(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n104(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n105(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n106(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n107(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n108(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n109(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n110(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n111(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n112(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n113(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n114(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n115(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n116(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n117(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n118(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n119(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n120(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n121(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n122(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n123(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n124(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n125(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n126(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n127(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n128(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n129(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n130(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n131(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n132(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n133(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n134(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n135(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n136(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n137(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n138(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n139(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n140(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n141(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n142(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n143(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n144(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n145(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n146(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n147(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n148(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n149(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n150(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n151(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n152(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n153(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n154(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n155(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n156(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n157(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n158(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n159(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n160(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n161(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n162(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n163(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n164(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n165(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n166(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n167(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n168(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n169(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n170(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n171(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n172(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n173(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n174(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n175(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n176(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n177(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n178(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n179(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n180(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n181(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n182(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n183(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n184(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n185(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n186(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n187(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n188(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n189(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n190(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n191(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n192(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n193(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n194(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n195(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n196(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n197(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n198(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n199(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n200(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n201(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n202(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n203(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n204(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n205(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n206(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n207(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n208(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n209(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n210(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n211(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n212(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n213(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n214(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n215(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n216(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n217(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n218(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n219(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n220(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n221(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n222(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n223(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n224(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n225(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n226(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n227(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n228(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n229(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n230(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n231(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n232(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n233(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n234(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n235(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n236(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n237(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n238(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n239(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n240(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n241(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n242(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n243(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n244(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n245(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n246(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n247(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n248(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n249(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n250(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n251(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n252(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n253(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n254(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n255(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n256(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n257(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n258(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n259(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n260(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n261(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n262(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n263(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n264(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n265(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n266(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n267(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n268(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n269(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n270(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n271(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n272(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n273(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n274(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n275(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n276(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n277(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n278(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n279(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n280(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n281(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n282(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n283(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n284(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n285(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n286(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n287(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n288(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n289(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n290(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n291(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n292(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n293(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n294(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n295(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n296(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n297(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n298(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n299(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n300(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n301(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n302(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n303(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n304(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n305(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n306(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n307(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n308(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n309(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n310(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n311(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n312(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n313(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n314(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n315(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n316(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n317(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n318(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n319(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n320(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n321(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n322(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n323(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n324(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n325(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n326(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n327(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n328(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n329(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n330(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n331(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n332(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n333(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n334(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n335(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n336(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n337(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n338(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n339(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n340(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n341(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n342(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n343(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n344(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n345(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n346(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n347(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n348(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n349(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n350(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n351(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n352(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n353(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n354(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n355(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n356(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n357(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n358(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n359(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n360(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n361(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n362(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n363(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n364(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n365(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n366(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n367(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n368(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n369(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n370(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n371(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n372(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n373(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n374(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n375(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n376(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n377(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n378(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n379(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n380(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n381(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n382(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n383(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n384(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n385(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n386(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n387(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n388(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n389(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n390(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n391(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n392(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n393(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n394(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n395(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n396(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n397(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n398(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n399(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n400(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n401(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n402(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n403(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n404(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n405(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n406(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n407(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n408(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n409(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n410(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n411(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n412(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n413(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n414(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n415(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n416(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n417(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n418(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n419(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n420(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n421(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n422(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n423(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n424(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n425(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n426(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n427(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n428(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n429(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n430(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n431(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n432(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n433(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n434(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n435(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n436(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n437(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n438(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n439(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n440(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n441(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n442(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n443(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n444(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n445(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n446(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n447(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n448(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n449(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n450(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n451(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n452(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n453(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n454(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n455(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n456(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n457(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n458(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n459(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n460(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n461(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n462(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n463(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n464(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n465(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n466(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n467(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n468(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n469(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n470(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n471(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n472(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n473(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n474(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n475(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n476(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n477(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n478(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n479(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n480(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n481(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n482(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n483(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n484(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n485(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n486(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n487(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n488(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n489(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n490(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n491(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n492(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n493(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n494(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n495(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n496(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n497(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n498(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n499(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n500(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n501(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n502(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n503(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n504(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n505(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n506(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n507(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n508(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n509(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n510(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n511(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n512(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n513(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n514(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n515(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n516(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n517(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n518(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n519(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n520(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n521(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n522(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n523(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n524(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n525(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n526(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n527(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n528(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n529(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n530(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n531(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n532(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n533(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n534(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n535(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n536(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n537(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n538(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n539(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n540(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n541(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n542(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n543(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n544(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n545(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n546(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n547(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n548(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n549(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n550(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n551(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n552(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n553(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n554(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n555(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n556(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n557(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n558(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n559(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n560(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n561(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n562(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n563(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n564(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n565(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n566(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n567(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n568(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n569(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n570(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n571(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n572(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n573(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n574(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n575(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n576(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n577(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n578(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n579(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n580(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n581(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n582(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n583(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n584(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n585(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n586(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n587(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n588(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n589(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n590(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n591(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n592(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n593(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n594(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n595(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n596(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n597(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n598(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n599(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n600(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n601(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n602(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n603(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n604(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n605(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n606(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n607(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n608(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n609(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n610(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n611(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n612(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n613(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n614(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n615(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n616(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n617(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n618(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n619(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n620(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n621(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n622(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n623(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n624(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n625(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n626(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n627(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n628(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n629(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n630(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n631(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n632(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n633(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n634(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n635(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n636(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n637(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n638(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n639(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n640(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n641(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n642(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n643(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n644(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n645(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n646(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n647(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n648(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n649(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n650(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n651(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n652(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n653(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n654(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n655(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n656(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n657(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n658(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n659(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n660(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n661(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n662(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n663(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n664(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n665(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n666(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n667(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n668(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n669(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n670(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n671(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n672(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n673(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n674(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n675(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n676(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n677(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n678(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n679(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n680(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n681(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n682(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n683(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n684(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n685(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n686(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n687(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n688(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n689(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n690(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n691(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n692(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n693(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n694(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n695(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n696(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n697(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n698(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n699(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n700(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n701(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n702(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n703(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n704(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n705(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n706(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n707(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n708(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n709(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n710(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n711(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n712(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n713(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n714(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n715(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n716(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n717(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n718(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n719(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n720(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n721(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n722(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n723(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n724(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n725(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n726(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n727(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n728(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n729(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n730(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n731(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n732(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n733(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n734(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n735(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n736(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n737(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n738(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n739(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n740(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n741(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n742(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n743(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n744(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n745(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n746(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n747(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n748(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n749(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n750(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n751(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n752(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n753(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n754(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n755(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n756(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n757(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n758(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n759(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n760(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n761(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n762(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n763(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n764(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n765(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n766(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n767(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n768(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n769(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n770(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n771(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n772(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n773(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n774(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n775(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n776(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n777(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n778(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n779(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n780(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n781(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n782(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n783(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n784(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n785(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n786(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n787(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n788(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n789(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n790(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n791(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n792(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n793(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n794(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n795(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n796(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n797(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n798(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n799(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n800(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n801(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n802(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n803(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n804(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n805(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n806(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n807(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n808(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n809(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n810(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n811(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n812(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n813(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n814(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n815(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n816(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n817(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n818(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n819(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n820(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n821(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n822(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n823(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n824(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n825(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n826(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n827(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n828(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n829(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n830(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n831(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n832(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n833(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n834(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n835(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n836(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n837(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n838(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n839(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n840(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n841(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n842(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n843(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n844(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n845(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n846(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n847(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n848(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n849(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n850(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n851(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n852(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n853(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n854(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n855(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n856(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n857(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n858(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n859(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n860(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n861(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n862(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n863(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n864(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n865(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n866(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n867(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n868(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n869(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n870(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n871(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n872(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n873(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n874(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n875(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n876(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n877(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n878(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n879(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n880(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n881(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n882(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n883(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n884(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n885(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n886(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n887(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n888(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n889(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n890(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n891(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n892(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n893(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n894(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n895(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n896(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n897(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n898(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n899(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n900(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n901(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n902(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n903(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n904(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n905(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n906(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n907(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n908(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n909(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n910(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n911(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n912(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n913(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n914(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n915(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n916(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n917(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n918(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n919(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n920(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n921(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n922(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n923(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n924(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n925(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n926(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n927(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n928(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n929(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n930(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n931(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n932(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n933(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n934(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n935(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n936(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n937(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n938(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n939(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n940(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n941(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n942(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n943(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n944(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n945(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n946(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n947(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n948(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n949(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ probe user_trace__n950(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+ /**
+ * Send a single string to a probe.
+ * This probe is deprecated.
+ *
+ * @param NUL-terminated string
+ */
+ probe user_trace__s1(char* message);
+
+ /**
+ * Multi-purpose probe: up to 4 NUL-terminated strings and 4
+ * 64-bit integer arguments.
+ * This probe is deprecated.
+ *
+ * @param proc, the PID (string form) of the sending process
+ * @param user_tag, the user tag of the sender
+ * @param i1, integer
+ * @param i2, integer
+ * @param i3, integer
+ * @param i4, integer
+ * @param s1, string/iolist. D's arg6 is NULL if not given by Erlang
+ * @param s2, string/iolist. D's arg7 is NULL if not given by Erlang
+ * @param s3, string/iolist. D's arg8 is NULL if not given by Erlang
+ * @param s4, string/iolist. D's arg9 is NULL if not given by Erlang
+ */
+ probe user_trace__i4s4(char *proc, char *user_tag,
+ int i1, int i2, int i3, int i4,
+ char *s1, char *s2, char *s3, char *s4);
+
+};
+
+#pragma D attributes Evolving/Evolving/Common provider erlang provider
+#pragma D attributes Private/Private/Common provider erlang module
+#pragma D attributes Private/Private/Common provider erlang function
+#pragma D attributes Evolving/Evolving/Common provider erlang name
+#pragma D attributes Evolving/Evolving/Common provider erlang args
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 5bc402fe22..fb0ee99119 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -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
@@ -208,7 +208,8 @@ erts_export_put(Eterm mod, Eterm func, unsigned int arity)
Export e;
int ix;
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ || erts_smp_thr_progress_is_blocking());
ASSERT(is_atom(mod));
ASSERT(is_atom(func));
e.code[0] = mod;
@@ -265,7 +266,8 @@ erts_export_consolidate(void)
HashInfo hi;
#endif
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ || erts_smp_thr_progress_is_blocking());
export_write_lock();
erts_index_merge(&secondary_export_table, &export_table);
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 6953e7fe7d..52f45b924f 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -46,7 +46,7 @@
#ifdef HIPE
#include "hipe_mode_switch.h"
#endif
-#define in_area(ptr,start,nbytes) ((Uint)((char*)(ptr) - (char*)(start)) < (nbytes))
+#define in_area(ptr,start,nbytes) ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
#define MAX_STRING_LEN 0xffff
@@ -88,7 +88,7 @@ static byte* enc_pid(ErtsAtomCacheMap *, Eterm, byte*, Uint32);
static byte* dec_term(ErtsDistExternal *, Eterm**, byte*, ErlOffHeap*, Eterm*);
static byte* dec_atom(ErtsDistExternal *, byte*, Eterm*);
static byte* dec_pid(ErtsDistExternal *, Eterm**, byte*, ErlOffHeap*, Eterm*);
-static Sint decoded_size(byte *ep, byte* endp, int only_heap_bins, int internal_tags);
+static Sint decoded_size(byte *ep, byte* endp, int internal_tags);
static Uint encode_size_struct2(ErtsAtomCacheMap *, Eterm, unsigned);
@@ -810,7 +810,7 @@ bad_dist_ext(ErtsDistExternal *edep)
}
Sint
-erts_decode_dist_ext_size(ErtsDistExternal *edep, int no_refc_bins)
+erts_decode_dist_ext_size(ErtsDistExternal *edep)
{
Sint res;
byte *ep;
@@ -829,7 +829,7 @@ erts_decode_dist_ext_size(ErtsDistExternal *edep, int no_refc_bins)
goto fail;
ep = edep->extp+1;
}
- res = decoded_size(ep, edep->ext_endp, no_refc_bins, 0);
+ res = decoded_size(ep, edep->ext_endp, 0);
if (res >= 0)
return res;
fail:
@@ -837,16 +837,16 @@ erts_decode_dist_ext_size(ErtsDistExternal *edep, int no_refc_bins)
return -1;
}
-Sint erts_decode_ext_size(byte *ext, Uint size, int no_refc_bins)
+Sint erts_decode_ext_size(byte *ext, Uint size)
{
if (size == 0 || *ext != VERSION_MAGIC)
return -1;
- return decoded_size(ext+1, ext+size, no_refc_bins, 0);
+ return decoded_size(ext+1, ext+size, 0);
}
Sint erts_decode_ext_size_ets(byte *ext, Uint size)
{
- Sint sz = decoded_size(ext, ext+size, 0, 1);
+ Sint sz = decoded_size(ext, ext+size, 1);
ASSERT(sz >= 0);
return sz;
}
@@ -968,7 +968,7 @@ BIF_RETTYPE erts_debug_dist_ext_to_term_2(BIF_ALIST_2)
ede.extp = binary_bytes(real_bin)+offset;
ede.ext_endp = ede.extp + size;
- hsz = erts_decode_dist_ext_size(&ede, 0);
+ hsz = erts_decode_dist_ext_size(&ede);
if (hsz < 0)
goto badarg;
@@ -988,16 +988,16 @@ BIF_RETTYPE erts_debug_dist_ext_to_term_2(BIF_ALIST_2)
}
-Eterm
-term_to_binary_1(Process* p, Eterm Term)
+BIF_RETTYPE term_to_binary_1(BIF_ALIST_1)
{
- return erts_term_to_binary(p, Term, 0, TERM_TO_BINARY_DFLAGS);
+ return erts_term_to_binary(BIF_P, BIF_ARG_1, 0, TERM_TO_BINARY_DFLAGS);
}
-
-Eterm
-term_to_binary_2(Process* p, Eterm Term, Eterm Flags)
+BIF_RETTYPE term_to_binary_2(BIF_ALIST_2)
{
+ Process* p = BIF_P;
+ Eterm Term = BIF_ARG_1;
+ Eterm Flags = BIF_ARG_2;
int level = 0;
Uint flags = TERM_TO_BINARY_DFLAGS;
@@ -1106,7 +1106,7 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size)
goto error;
size = (Sint) dest_len;
}
- res = decoded_size(state->extp, state->extp + size, 0, 0);
+ res = decoded_size(state->extp, state->extp + size, 0);
if (res < 0)
goto error;
return res;
@@ -1256,8 +1256,11 @@ BIF_RETTYPE binary_to_term_2(BIF_ALIST_2)
}
Eterm
-external_size_1(Process* p, Eterm Term)
+external_size_1(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm Term = BIF_ARG_1;
+
Uint size = erts_encode_ext_size(Term);
if (IS_USMALL(0, size)) {
BIF_RET(make_small(size));
@@ -1268,13 +1271,13 @@ external_size_1(Process* p, Eterm Term)
}
Eterm
-external_size_2(Process* p, Eterm Term, Eterm Flags)
+external_size_2(BIF_ALIST_2)
{
Uint size;
Uint flags = TERM_TO_BINARY_DFLAGS;
- while (is_list(Flags)) {
- Eterm arg = CAR(list_val(Flags));
+ while (is_list(BIF_ARG_2)) {
+ Eterm arg = CAR(list_val(BIF_ARG_2));
Eterm* tp;
if (is_tuple(arg) && *(tp = tuple_val(arg)) == make_arityval(2)) {
@@ -1293,19 +1296,19 @@ external_size_2(Process* p, Eterm Term, Eterm Flags)
}
} else {
error:
- BIF_ERROR(p, BADARG);
+ BIF_ERROR(BIF_P, BADARG);
}
- Flags = CDR(list_val(Flags));
+ BIF_ARG_2 = CDR(list_val(BIF_ARG_2));
}
- if (is_not_nil(Flags)) {
+ if (is_not_nil(BIF_ARG_2)) {
goto error;
}
- size = erts_encode_ext_size_2(Term, flags);
+ size = erts_encode_ext_size_2(BIF_ARG_1, flags);
if (IS_USMALL(0, size)) {
BIF_RET(make_small(size));
} else {
- Eterm* hp = HAlloc(p, BIG_UINT_HEAP_SIZE);
+ Eterm* hp = HAlloc(BIF_P, BIG_UINT_HEAP_SIZE);
BIF_RET(uint_to_big(size, hp));
}
}
@@ -1886,7 +1889,9 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags,
*ep++ = BINARY_INTERNAL_REF;
}
if (pb->flags) {
+ char* before_realloc = pb->val->orig_bytes;
erts_emasculate_writable_binary(pb);
+ bytes += (pb->val->orig_bytes - before_realloc);
}
erts_refc_inc(&pb->val->refc, 2);
@@ -2451,7 +2456,7 @@ dec_term_atom_common:
n = get_int32(ep);
ep += 4;
- if (n <= ERL_ONHEAP_BIN_LIMIT || off_heap == NULL) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
hb->thing_word = header_heap_bin(n);
@@ -2489,7 +2494,7 @@ dec_term_atom_common:
n = get_int32(ep);
bitsize = ep[4];
ep += 5;
- if (n <= ERL_ONHEAP_BIN_LIMIT || off_heap == NULL) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
hb->thing_word = header_heap_bin(n);
@@ -2623,14 +2628,12 @@ dec_term_atom_common:
}
old_uniq = unsigned_val(temp);
-#ifndef HYBRID /* FIND ME! */
/*
* It is safe to link the fun into the fun list only when
* no more validity tests can fail.
*/
funp->next = off_heap->first;
off_heap->first = (struct erl_off_heap_header*)funp;
-#endif
funp->fe = erts_put_fun_entry2(module, old_uniq, old_index,
uniq, index, arity);
@@ -2701,14 +2704,12 @@ dec_term_atom_common:
goto error;
}
-#ifndef HYBRID /* FIND ME! */
/*
* It is safe to link the fun into the fun list only when
* no more validity tests can fail.
*/
funp->next = off_heap->first;
off_heap->first = (struct erl_off_heap_header*)funp;
-#endif
old_uniq = unsigned_val(temp);
funp->fe = erts_put_fun_entry(module, old_uniq, old_index);
@@ -3058,7 +3059,7 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags)
}
static Sint
-decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
+decoded_size(byte *ep, byte* endp, int internal_tags)
{
int heap_size = 0;
int terms;
@@ -3115,6 +3116,9 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
case LARGE_BIG_EXT:
CHKSIZE(4);
n = get_int32(ep);
+ if (n > BIG_ARITY_MAX*sizeof(ErtsDigit)) {
+ return -1;
+ }
SKIP2(n,4+1); /* skip, size,sign,digits */
heap_size += 1+1+(n+sizeof(Eterm)-1)/sizeof(Eterm); /* XXX: 1 too much? */
break;
@@ -3220,7 +3224,7 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
CHKSIZE(4);
n = get_int32(ep);
SKIP2(n, 4);
- if (n <= ERL_ONHEAP_BIN_LIMIT || no_refc_bins) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
heap_size += heap_bin_size(n);
} else {
heap_size += PROC_BIN_SIZE;
@@ -3231,7 +3235,7 @@ decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
CHKSIZE(5);
n = get_int32(ep);
SKIP2(n, 5);
- if (n <= ERL_ONHEAP_BIN_LIMIT || no_refc_bins) {
+ if (n <= ERL_ONHEAP_BIN_LIMIT) {
heap_size += heap_bin_size(n) + ERL_SUB_BIN_SIZE;
} else {
heap_size += PROC_BIN_SIZE + ERL_SUB_BIN_SIZE;
diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h
index 671b8b8781..eddd4571dd 100644
--- a/erts/emulator/beam/external.h
+++ b/erts/emulator/beam/external.h
@@ -175,10 +175,10 @@ void *erts_dist_ext_trailer(ErtsDistExternal *);
void erts_destroy_dist_ext_copy(ErtsDistExternal *);
int erts_prepare_dist_ext(ErtsDistExternal *, byte *, Uint,
DistEntry *, ErtsAtomCache *);
-Sint erts_decode_dist_ext_size(ErtsDistExternal *, int);
+Sint erts_decode_dist_ext_size(ErtsDistExternal *);
Eterm erts_decode_dist_ext(Eterm **, ErlOffHeap *, ErtsDistExternal *);
-Sint erts_decode_ext_size(byte*, Uint, int);
+Sint erts_decode_ext_size(byte*, Uint);
Sint erts_decode_ext_size_ets(byte*, Uint);
Eterm erts_decode_ext(Eterm **, ErlOffHeap *, byte**);
Eterm erts_decode_ext_ets(Eterm **, ErlOffHeap *, byte*);
diff --git a/erts/emulator/beam/fix_alloc.c b/erts/emulator/beam/fix_alloc.c
deleted file mode 100644
index 5637281597..0000000000
--- a/erts/emulator/beam/fix_alloc.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-/* General purpose Memory allocator for fixed block size objects */
-/* This allocater is at least an order of magnitude faster than malloc() */
-
-
-#define NOPERBLOCK 20
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
-#include "erl_db.h"
-
-#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
-
-#if ERTS_ALC_MTA_FIXED_SIZE
-#include "erl_threads.h"
-#include "erl_smp.h"
-# ifdef ERTS_SMP
-# define FA_LOCK(FA) erts_smp_spin_lock(&(FA)->slck)
-# define FA_UNLOCK(FA) erts_smp_spin_unlock(&(FA)->slck)
-# else
-# define FA_LOCK(FA) erts_mtx_lock(&(FA)->mtx)
-# define FA_UNLOCK(FA) erts_mtx_unlock(&(FA)->mtx)
-# endif
-#else
-# define FA_LOCK(FA)
-# define FA_UNLOCK(FA)
-#endif
-
-typedef union {double d; long l;} align_t;
-
-typedef struct fix_alloc_block {
- struct fix_alloc_block *next;
- align_t mem[1];
-} FixAllocBlock;
-
-typedef struct fix_alloc {
- Uint item_size;
- void *freelist;
- Uint no_free;
- Uint no_blocks;
- FixAllocBlock *blocks;
-#if ERTS_ALC_MTA_FIXED_SIZE
-# ifdef ERTS_SMP
- erts_smp_spinlock_t slck;
-# else
- erts_mtx_t mtx;
-# endif
-#endif
-} FixAlloc;
-
-static void *(*core_alloc)(Uint);
-static Uint xblk_sz;
-
-static FixAlloc **fa;
-#define FA_SZ (1 + ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE)
-
-#define FIX_IX(N) ((N) - ERTS_ALC_N_MIN_A_FIXED_SIZE)
-
-#define FIX_POOL_SZ(I_SZ) \
- ((I_SZ)*NOPERBLOCK + sizeof(FixAllocBlock) - sizeof(align_t))
-
-#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE
-static int first_time;
-#endif
-
-void erts_init_fix_alloc(Uint extra_block_size,
- void *(*alloc)(Uint))
-{
- int i;
-
- xblk_sz = extra_block_size;
- core_alloc = alloc;
-
- fa = (FixAlloc **) (*core_alloc)(FA_SZ * sizeof(FixAlloc *));
- if (!fa)
- erts_alloc_enomem(ERTS_ALC_T_UNDEF, FA_SZ * sizeof(FixAlloc *));
-
- for (i = 0; i < FA_SZ; i++)
- fa[i] = NULL;
-#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE
- first_time = 1;
-#endif
-}
-
-Uint
-erts_get_fix_size(ErtsAlcType_t type)
-{
- Uint i = FIX_IX(ERTS_ALC_T2N(type));
- return i < FA_SZ && fa[i] ? fa[i]->item_size : 0;
-}
-
-void
-erts_set_fix_size(ErtsAlcType_t type, Uint size)
-{
- Uint sz;
- Uint i;
- FixAlloc *fs;
- ErtsAlcType_t t_no = ERTS_ALC_T2N(type);
- sz = xblk_sz + size;
-
-#ifdef DEBUG
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
-#endif
-
- while (sz % sizeof(align_t) != 0) /* Alignment */
- sz++;
-
- i = FIX_IX(t_no);
- fs = (FixAlloc *) (*core_alloc)(sizeof(FixAlloc));
- if (!fs)
- erts_alloc_n_enomem(t_no, sizeof(FixAlloc));
-
- fs->item_size = sz;
- fs->no_blocks = 0;
- fs->no_free = 0;
- fs->blocks = NULL;
- fs->freelist = NULL;
- if (fa[i])
- erl_exit(-1, "Attempt to overwrite existing fix size (%d)", i);
- fa[i] = fs;
-
-#if ERTS_ALC_MTA_FIXED_SIZE
-#ifdef ERTS_SMP
- erts_smp_spinlock_init_x(&fs->slck, "fix_alloc", make_small(i));
-#else
- erts_mtx_init_x(&fs->mtx, "fix_alloc", make_small(i));
-#endif
-#endif
-
-}
-
-void
-erts_fix_info(ErtsAlcType_t type, ErtsFixInfo *efip)
-{
- Uint i;
- FixAlloc *f;
-#ifdef DEBUG
- FixAllocBlock *b;
- void *fp;
-#endif
- Uint real_item_size;
- ErtsAlcType_t t_no = ERTS_ALC_T2N(type);
-
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
-
- i = FIX_IX(t_no);
- f = fa[i];
-
- efip->total = sizeof(FixAlloc *);
- efip->used = 0;
- if (!f)
- return;
-
- real_item_size = f->item_size - xblk_sz;
-
- FA_LOCK(f);
-
- efip->total += sizeof(FixAlloc);
- efip->total += f->no_blocks*FIX_POOL_SZ(real_item_size);
- efip->used = efip->total - f->no_free*real_item_size;
-
-#ifdef DEBUG
- ASSERT(efip->total >= efip->used);
- for(i = 0, b = f->blocks; b; i++, b = b->next);
- ASSERT(f->no_blocks == i);
- for (i = 0, fp = f->freelist; fp; i++, fp = *((void **) fp));
- ASSERT(f->no_free == i);
-#endif
-
- FA_UNLOCK(f);
-
-}
-
-void
-erts_fix_free(ErtsAlcType_t t_no, void *extra, void* ptr)
-{
- Uint i;
- FixAlloc *f;
-
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
-
- i = FIX_IX(t_no);
- f = fa[i];
-
- FA_LOCK(f);
- *((void **) ptr) = f->freelist;
- f->freelist = ptr;
- f->no_free++;
- FA_UNLOCK(f);
-}
-
-
-void *erts_fix_realloc(ErtsAlcType_t t_no, void *extra, void* ptr, Uint size)
-{
- erts_alc_fatal_error(ERTS_ALC_E_NOTSUP, ERTS_ALC_O_REALLOC, t_no);
- return NULL;
-}
-
-void *erts_fix_alloc(ErtsAlcType_t t_no, void *extra, Uint size)
-{
- void *ret;
- int i;
- FixAlloc *f;
-
-#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE
- ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no);
- ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);
- if (first_time) { /* Check that all sizes have been initialized */
- int i;
- for (i = 0; i < FA_SZ; i++)
- ASSERT(fa[i]);
- first_time = 0;
- }
-#endif
-
-
- i = FIX_IX(t_no);
- f = fa[i];
-
- ASSERT(f);
- ASSERT(f->item_size >= size);
-
- FA_LOCK(f);
- if (f->freelist == NULL) { /* Gotta alloc some more mem */
- char *ptr;
- FixAllocBlock *bl;
- Uint n;
-
-
- FA_UNLOCK(f);
- bl = (*core_alloc)(FIX_POOL_SZ(f->item_size));
- if (!bl)
- return NULL;
-
- FA_LOCK(f);
- bl->next = f->blocks; /* link in first */
- f->blocks = bl;
-
- n = NOPERBLOCK;
- ptr = (char *) &f->blocks->mem[0];
- while(n--) {
- *((void **) ptr) = f->freelist;
- f->freelist = (void *) ptr;
- ptr += f->item_size;
- }
-#if !ERTS_ALC_MTA_FIXED_SIZE
- ASSERT(f->no_free == 0);
-#endif
- f->no_free += NOPERBLOCK;
- f->no_blocks++;
- }
-
- ret = f->freelist;
- f->freelist = *((void **) f->freelist);
- ASSERT(f->no_free > 0);
- f->no_free--;
-
- FA_UNLOCK(f);
-
- return ret;
-}
-
-#endif /* #ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE */
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index a967aa0e3e..dbf95f5bd7 100644..100755
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,18 +42,12 @@
typedef struct port Port;
#include "erl_port_task.h"
-#define ERTS_MAX_NO_OF_ASYNC_THREADS 1024
-extern int erts_async_max_threads;
-#define ERTS_ASYNC_THREAD_MIN_STACK_SIZE 16 /* Kilo words */
-#define ERTS_ASYNC_THREAD_MAX_STACK_SIZE 8192 /* Kilo words */
-extern int erts_async_thread_suggested_stack_size;
-
typedef struct erts_driver_t_ erts_driver_t;
#define SMALL_IO_QUEUE 5 /* Number of fixed elements */
typedef struct {
- int size; /* total size in bytes */
+ ErlDrvSizeT size; /* total size in bytes */
SysIOVec* v_start;
SysIOVec* v_end;
@@ -69,9 +63,9 @@ typedef struct {
} ErlIOQueue;
typedef struct line_buf { /* Buffer used in line oriented I/O */
- int bufsiz; /* Size of character buffer */
- int ovlen; /* Length of overflow data */
- int ovsiz; /* Actual size of overflow buffer */
+ ErlDrvSizeT bufsiz; /* Size of character buffer */
+ ErlDrvSizeT ovlen; /* Length of overflow data */
+ ErlDrvSizeT ovsiz; /* Actual size of overflow buffer */
char data[1]; /* Starting point of buffer data,
data[0] is a flag indicating an unprocess CR,
The rest is the overflow buffer. */
@@ -178,7 +172,8 @@ struct port {
DistEntry *dist_entry; /* Dist entry used in DISTRIBUTION */
char *name; /* String used in the open */
erts_driver_t* drv_ptr;
- long drv_data;
+ UWord drv_data;
+ SWord os_pid; /* Child process ID */
ErtsProcList *suspended; /* List of suspended processes. */
LineBuf *linebuf; /* Buffer to hold data not ready for
process to get (line oriented I/O)*/
@@ -211,7 +206,7 @@ erts_port_runq(Port *prt)
rq1 = rq2;
}
#else
- return erts_common_run_queue;
+ return ERTS_RUNQ_IX(0);
#endif
}
@@ -329,12 +324,15 @@ struct erts_driver_t_ {
void (*stop)(ErlDrvData drv_data);
void (*finish)(void);
void (*flush)(ErlDrvData drv_data);
- void (*output)(ErlDrvData drv_data, char *buf, int len);
+ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); /* Might be NULL */
- int (*control)(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen); /* Might be NULL */
- int (*call)(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned int *flags); /* Might be NULL */
+ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen); /* Might be NULL */
+ ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen, /* Might be NULL */
+ unsigned int *flags);
void (*event)(ErlDrvData drv_data, ErlDrvEvent event,
ErlDrvEventData event_data);
void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
@@ -404,7 +402,7 @@ extern Eterm erts_ddll_monitor_driver(Process *p,
typedef struct binary {
ERTS_INTERNAL_BINARY_FIELDS
- long orig_size;
+ SWord orig_size;
char orig_bytes[1]; /* to be continued */
} Binary;
@@ -413,7 +411,7 @@ typedef struct binary {
typedef struct {
ERTS_INTERNAL_BINARY_FIELDS
- long orig_size;
+ SWord orig_size;
void (*destructor)(Binary *);
char magic_bin_data[1];
} ErtsMagicBinary;
@@ -547,7 +545,7 @@ ERTS_GLB_INLINE void erts_may_save_closed_port(Port *prt)
tombstone = (Eterm*) erts_smp_atomic_add_read_nob(&erts_dead_ports_ptr,
-(erts_aint_t)sizeof(Eterm));
ASSERT(tombstone+1 != NULL);
- ASSERT(prt->snapshot == erts_smp_atomic_read_nob(&erts_ports_snapshot) - 1);
+ ASSERT(prt->snapshot == erts_smp_atomic32_read_nob(&erts_ports_snapshot) - 1);
*tombstone = prt->id;
}
/*else no ongoing snapshot or port was already included or created after snapshot */
@@ -561,99 +559,12 @@ extern Eterm node_cookie;
extern erts_smp_atomic_t erts_bytes_out; /* no bytes written out */
extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */
extern Uint display_items; /* no of items to display in traces etc */
-extern Uint display_loads; /* print info about loaded modules */
extern int erts_backtrace_depth;
extern erts_smp_atomic32_t erts_max_gen_gcs;
extern int erts_disable_tolerant_timeofday;
-#ifdef HYBRID
-
-/* Message Area heap pointers */
-extern Eterm *global_heap; /* Heap start */
-extern Eterm *global_hend; /* Heap end */
-extern Eterm *global_htop; /* Heap top (heap pointer) */
-extern Eterm *global_saved_htop; /* Saved heap top (heap pointer) */
-extern Uint global_heap_sz; /* Heap size, in words */
-extern Eterm *global_old_heap; /* Old generation */
-extern Eterm *global_old_hend;
-extern ErlOffHeap erts_global_offheap; /* Global MSO (OffHeap) list */
-
-extern Uint16 global_gen_gcs;
-extern Uint16 global_max_gen_gcs;
-extern Uint global_gc_flags;
-
-#ifdef INCREMENTAL
-#define ACTIVATE(p)
-#define DEACTIVATE(p)
-#define IS_ACTIVE(p) 1
-
-#define INC_ACTIVATE(p) do { \
- if ((p)->active) { \
- if ((p)->active_next != NULL) { \
- (p)->active_next->active_prev = (p)->active_prev; \
- if ((p)->active_prev) { \
- (p)->active_prev->active_next = (p)->active_next; \
- } else { \
- inc_active_proc = (p)->active_next; \
- } \
- inc_active_last->active_next = (p); \
- (p)->active_next = NULL; \
- (p)->active_prev = inc_active_last; \
- inc_active_last = (p); \
- } \
- } else { \
- (p)->active_next = NULL; \
- (p)->active_prev = inc_active_last; \
- if (inc_active_last) { \
- inc_active_last->active_next = (p); \
- } else { \
- inc_active_proc = (p); \
- } \
- inc_active_last = (p); \
- (p)->active = 1; \
- } \
-} while(0);
-
-#define INC_DEACTIVATE(p) do { \
- ASSERT((p)->active == 1); \
- if ((p)->active_next == NULL) { \
- inc_active_last = (p)->active_prev; \
- } else { \
- (p)->active_next->active_prev = (p)->active_prev; \
- } \
- if ((p)->active_prev == NULL) { \
- inc_active_proc = (p)->active_next; \
- } else { \
- (p)->active_prev->active_next = (p)->active_next; \
- } \
- (p)->active = 0; \
-} while(0);
-
-#define INC_IS_ACTIVE(p) ((p)->active != 0)
-
-#else
-extern Eterm *global_old_htop;
-extern Eterm *global_high_water;
-#define ACTIVATE(p) (p)->active = 1;
-#define DEACTIVATE(p) (p)->active = 0;
-#define IS_ACTIVE(p) ((p)->active != 0)
-#define INC_ACTIVATE(p)
-#define INC_IS_ACTIVE(p) 1
-#endif /* INCREMENTAL */
-
-#else
-# define ACTIVATE(p)
-# define DEACTIVATE(p)
-# define IS_ACTIVE(p) 1
-# define INC_ACTIVATE(p)
-#endif /* HYBRID */
-
-#ifdef HYBRID
-extern Uint global_heap_min_sz;
-#endif
-
extern int bif_reductions; /* reductions + fcalls (when doing call_bif) */
extern int stackdump_on_exit;
@@ -810,6 +721,8 @@ do { \
/* Port uses port specific locking (opposed to driver specific locking) */
#define ERTS_PORT_SFLG_PORT_SPECIFIC_LOCK ((Uint32) (1 << 13))
#define ERTS_PORT_SFLG_INVALID ((Uint32) (1 << 14))
+/* Last port to terminate halts the emulator */
+#define ERTS_PORT_SFLG_HALT ((Uint32) (1 << 15))
#ifdef DEBUG
/* Only debug: make sure all flags aren't cleared unintentionally */
#define ERTS_PORT_SFLG_PORT_DEBUG ((Uint32) (1 << 31))
@@ -852,10 +765,16 @@ void erts_queue_monitor_message(Process *,
Eterm,
Eterm);
void erts_init_bif(void);
+Eterm erl_send(Process *p, Eterm to, Eterm msg);
+
+/* erl_bif_op.c */
+
+Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
/* erl_bif_port.c */
/* erl_bif_trace.c */
+Eterm erl_seq_trace_info(Process *p, Eterm arg1);
void erts_system_monitor_clear(Process *c_p);
void erts_system_profile_clear(Process *c_p);
@@ -867,8 +786,14 @@ typedef struct {
Eterm* fname_ptr; /* Pointer to fname table */
} FunctionInfo;
-int erts_load_module(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm* mod, byte* code, int size);
+struct LoaderState* erts_alloc_loader_state(void);
+Eterm erts_prepare_loading(struct LoaderState*, Process *c_p,
+ Eterm group_leader, Eterm* modp,
+ byte* code, Uint size);
+Eterm erts_finish_loading(struct LoaderState* stp, Process* c_p,
+ ErtsProcLocks c_p_locks, Eterm* modp);
+Eterm erts_load_module(Process *c_p, ErtsProcLocks c_p_locks,
+ Eterm group_leader, Eterm* mod, byte* code, Uint size);
void init_load(void);
BeamInstr* find_function_from_pc(BeamInstr* pc);
Eterm* erts_build_mfa_item(FunctionInfo* fi, Eterm* hp,
@@ -891,16 +816,10 @@ void loaded(int, void *);
/* config.c */
__decl_noreturn void __noreturn erl_exit(int n, char*, ...);
-__decl_noreturn void __noreturn erl_exit0(char *, int, int n, char*, ...);
+__decl_noreturn void __noreturn erl_exit_flush_async(int n, char*, ...);
void erl_error(char*, va_list);
-#define ERL_EXIT0(n,f) erl_exit0(__FILE__, __LINE__, n, f)
-#define ERL_EXIT1(n,f,a) erl_exit0(__FILE__, __LINE__, n, f, a)
-#define ERL_EXIT2(n,f,a,b) erl_exit0(__FILE__, __LINE__, n, f, a, b)
-#define ERL_EXIT3(n,f,a,b,c) erl_exit0(__FILE__, __LINE__, n, f, a, b, c)
-
/* copy.c */
-void init_copy(void);
Eterm copy_object(Eterm, Process*);
#if HALFWORD_HEAP
@@ -930,116 +849,6 @@ Eterm copy_shallow(Eterm*, Uint, Eterm**, ErlOffHeap*);
void move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
Eterm* refs, unsigned nrefs);
-#ifdef HYBRID
-#define RRMA_DEFAULT_SIZE 256
-#define RRMA_STORE(p,ptr,src) do { \
- ASSERT((p)->rrma != NULL); \
- ASSERT((p)->rrsrc != NULL); \
- (p)->rrma[(p)->nrr] = (ptr); \
- (p)->rrsrc[(p)->nrr++] = (src); \
- if ((p)->nrr == (p)->rrsz) \
- { \
- (p)->rrsz *= 2; \
- (p)->rrma = (Eterm *) erts_realloc(ERTS_ALC_T_ROOTSET, \
- (void*)(p)->rrma, \
- sizeof(Eterm) * (p)->rrsz); \
- (p)->rrsrc = (Eterm **) erts_realloc(ERTS_ALC_T_ROOTSET, \
- (void*)(p)->rrsrc, \
- sizeof(Eterm) * (p)->rrsz); \
- } \
-} while(0)
-
-/* Note that RRMA_REMOVE decreases the given index after deletion.
- * This is done so that a loop with an increasing index can call
- * remove without having to decrease the index to see the element
- * placed in the hole after the deleted element.
- */
-#define RRMA_REMOVE(p,index) do { \
- p->rrsrc[index] = p->rrsrc[--p->nrr]; \
- p->rrma[index--] = p->rrma[p->nrr]; \
- } while(0);
-
-
-/* The MessageArea STACKs are used while copying messages to the
- * message area.
- */
-#define MA_STACK_EXTERNAL_DECLARE(type,_s_) \
- typedef type ma_##_s_##_type; \
- extern ma_##_s_##_type *ma_##_s_##_stack; \
- extern Uint ma_##_s_##_top; \
- extern Uint ma_##_s_##_size;
-
-#define MA_STACK_DECLARE(_s_) \
- ma_##_s_##_type *ma_##_s_##_stack; Uint ma_##_s_##_top; Uint ma_##_s_##_size;
-
-#define MA_STACK_ALLOC(_s_) do { \
- ma_##_s_##_top = 0; \
- ma_##_s_##_size = 512; \
- ma_##_s_##_stack = (ma_##_s_##_type*)erts_alloc(ERTS_ALC_T_OBJECT_STACK, \
- sizeof(ma_##_s_##_type) * ma_##_s_##_size); \
-} while(0)
-
-
-#define MA_STACK_PUSH(_s_,val) do { \
- ma_##_s_##_stack[ma_##_s_##_top++] = (val); \
- if (ma_##_s_##_top == ma_##_s_##_size) \
- { \
- ma_##_s_##_size *= 2; \
- ma_##_s_##_stack = \
- (ma_##_s_##_type*) erts_realloc(ERTS_ALC_T_OBJECT_STACK, \
- (void*)ma_##_s_##_stack, \
- sizeof(ma_##_s_##_type) * ma_##_s_##_size); \
- } \
-} while(0)
-
-#define MA_STACK_POP(_s_) (ma_##_s_##_top != 0 ? ma_##_s_##_stack[--ma_##_s_##_top] : 0)
-#define MA_STACK_TOP(_s_) (ma_##_s_##_stack[ma_##_s_##_top - 1])
-#define MA_STACK_UPDATE(_s_,offset,value) \
- *(ma_##_s_##_stack[ma_##_s_##_top - 1] + (offset)) = (value)
-#define MA_STACK_SIZE(_s_) (ma_##_s_##_top)
-#define MA_STACK_ELM(_s_,i) ma_##_s_##_stack[i]
-
-MA_STACK_EXTERNAL_DECLARE(Eterm,src);
-MA_STACK_EXTERNAL_DECLARE(Eterm*,dst);
-MA_STACK_EXTERNAL_DECLARE(Uint,offset);
-
-
-#ifdef INCREMENTAL
-extern Eterm *ma_pending_stack;
-extern Uint ma_pending_top;
-extern Uint ma_pending_size;
-
-#define NO_COPY(obj) (IS_CONST(obj) || \
- (((ptr_val(obj) >= global_heap) && \
- (ptr_val(obj) < global_htop)) || \
- ((ptr_val(obj) >= inc_fromspc) && \
- (ptr_val(obj) < inc_fromend)) || \
- ((ptr_val(obj) >= global_old_heap) && \
- (ptr_val(obj) < global_old_hend))))
-
-#else
-
-#define NO_COPY(obj) (IS_CONST(obj) || \
- (((ptr_val(obj) >= global_heap) && \
- (ptr_val(obj) < global_htop)) || \
- ((ptr_val(obj) >= global_old_heap) && \
- (ptr_val(obj) < global_old_hend))))
-
-#endif /* INCREMENTAL */
-
-#define LAZY_COPY(from,obj) do { \
- if (!NO_COPY(obj)) { \
- BM_LAZY_COPY_START; \
- BM_COUNT(messages_copied); \
- obj = copy_struct_lazy(from,obj,0); \
- BM_LAZY_COPY_STOP; \
- } \
-} while(0)
-
-Eterm copy_struct_lazy(Process*, Eterm, Uint);
-
-#endif /* HYBRID */
-
/* Utilities */
extern void erts_delete_nodes_monitors(Process *, ErtsProcLocks);
extern Eterm erts_monitor_nodes(Process *, Eterm, Eterm);
@@ -1048,7 +857,8 @@ extern int erts_do_net_exits(DistEntry*, Eterm);
extern int distribution_info(int, void *);
extern int is_node_name_atom(Eterm a);
-extern int erts_net_message(Port *, DistEntry *, byte *, int, byte *, int);
+extern int erts_net_message(Port *, DistEntry *,
+ byte *, ErlDrvSizeT, byte *, ErlDrvSizeT);
extern void init_dist(void);
extern int stop_dist(void);
@@ -1121,7 +931,9 @@ void erts_init_gc(void);
int erts_garbage_collect(Process*, int, Eterm*, int);
void erts_garbage_collect_hibernate(Process* p);
Eterm erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity);
-void erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size);
+void erts_garbage_collect_literals(Process* p, Eterm* literals,
+ Uint lit_size,
+ struct erl_off_heap_header* oh);
Uint erts_next_heap_size(Uint, Uint);
Eterm erts_heap_sizes(Process* p);
@@ -1130,10 +942,6 @@ void erts_offset_heap_ptr(Eterm*, Uint, Sint, Eterm*, Eterm*);
void erts_offset_heap(Eterm*, Uint, Sint, Eterm*, Eterm*);
void erts_free_heap_frags(Process* p);
-#ifdef HYBRID
-int erts_global_garbage_collect(Process*, int, Eterm*, int);
-#endif
-
/* io.c */
struct erl_drv_port_data_lock {
@@ -1179,6 +987,10 @@ void erts_fire_port_monitor(Port *prt, Eterm ref);
void erts_smp_xports_unlock(Port *);
#endif
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_COUNT)
+void erts_lcnt_enable_io_lock_count(int enable);
+#endif
+
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
int erts_lc_is_port_locked(Port *);
#endif
@@ -1574,8 +1386,12 @@ Sint erts_native_filename_need(Eterm ioterm, int encoding);
void erts_copy_utf8_to_utf16_little(byte *target, byte *bytes, int num_chars);
int erts_analyze_utf8(byte *source, Uint size,
byte **err_pos, Uint *num_chars, int *left);
-char *erts_convert_filename_to_native(Eterm name, ErtsAlcType_t alloc_type, int allow_empty);
-
+char *erts_convert_filename_to_native(Eterm name, char *statbuf,
+ size_t statbuf_size,
+ ErtsAlcType_t alloc_type,
+ int allow_empty, int allow_atom,
+ Sint *used /* out */);
+Eterm erts_convert_native_to_filename(Process *p, byte *bytes);
#define ERTS_UTF8_OK 0
#define ERTS_UTF8_INCOMPLETE 1
#define ERTS_UTF8_ERROR 2
@@ -1641,8 +1457,7 @@ void monitor_generic(Process *p, Eterm type, Eterm spec);
Uint erts_trace_flag2bit(Eterm flag);
int erts_trace_flags(Eterm List,
Uint *pMask, Eterm *pTracer, int *pCpuTimestamp);
-Eterm erts_bif_trace(int bif_index, Process* p,
- Eterm arg1, Eterm arg2, Eterm arg3, BeamInstr *I);
+Eterm erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr *I);
#ifdef ERTS_SMP
void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp);
@@ -1655,7 +1470,7 @@ do { \
#define ERTS_SMP_CHK_PEND_TRACE_MSGS(ESDP)
#endif
-void bin_write(int, void*, byte*, int);
+void bin_write(int, void*, byte*, size_t);
int intlist_to_buf(Eterm, char*, int); /* most callers pass plain char*'s */
struct Sint_buf {
@@ -1671,7 +1486,7 @@ char* Sint_to_buf(Sint, struct Sint_buf*);
#define ERTS_IOLIST_OVERFLOW 1
#define ERTS_IOLIST_TYPE 2
-Eterm buf_to_intlist(Eterm**, char*, int, Eterm); /* most callers pass plain char*'s */
+Eterm buf_to_intlist(Eterm**, char*, size_t, Eterm); /* most callers pass plain char*'s */
int io_list_to_buf(Eterm, char*, int);
int io_list_to_buf2(Eterm, char*, int);
int erts_iolist_size(Eterm, Uint *);
@@ -1967,4 +1782,46 @@ erts_alloc_message_heap(Uint size,
# define UseTmpHeapNoproc(Size) /* Nothing */
# define UnUseTmpHeapNoproc(Size) /* Nothing */
#endif /* HEAP_ON_C_STACK */
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+#include "dtrace-wrapper.h"
+
+ERTS_GLB_INLINE void
+dtrace_pid_str(Eterm pid, char *process_buf)
+{
+ erts_snprintf(process_buf, DTRACE_TERM_BUF_SIZE, "<%lu.%lu.%lu>",
+ pid_channel_no(pid),
+ pid_number(pid),
+ pid_serial(pid));
+}
+
+ERTS_GLB_INLINE void
+dtrace_proc_str(Process *process, char *process_buf)
+{
+ dtrace_pid_str(process->id, process_buf);
+}
+
+ERTS_GLB_INLINE void
+dtrace_port_str(Port *port, char *port_buf)
+{
+ erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
+ port_channel_no(port->id),
+ port_number(port->id));
+}
+
+ERTS_GLB_INLINE void
+dtrace_fun_decode(Process *process,
+ Eterm module, Eterm function, int arity,
+ char *process_buf, char *mfa_buf)
+{
+ if (process_buf) {
+ dtrace_proc_str(process, process_buf);
+ }
+
+ erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%T/%d",
+ module, function, arity);
+}
+#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
#endif /* !__GLOBAL_H__ */
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 151c776a3d..35b194f927 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,6 +42,8 @@
#include "erl_bits.h"
#include "erl_version.h"
#include "error.h"
+#include "erl_async.h"
+#include "dtrace-wrapper.h"
extern ErlDrvEntry fd_driver_entry;
extern ErlDrvEntry vanilla_driver_entry;
@@ -163,8 +165,8 @@ erts_port_ioq_size(Port *pp)
typedef struct line_buf_context {
LineBuf **b;
char *buf;
- int left;
- int retlen;
+ ErlDrvSizeT left;
+ ErlDrvSizeT retlen;
} LineBufContext;
#define LINEBUF_EMPTY 0
@@ -179,6 +181,20 @@ typedef struct line_buf_context {
#define LINEBUF_INITIAL 100
+#ifdef USE_VM_PROBES
+#define DTRACE_FORMAT_COMMON_PID_AND_PORT(PID, PORT) \
+ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \
+ \
+ dtrace_pid_str((PID), process_str); \
+ dtrace_port_str((PORT), port_str);
+#define DTRACE_FORMAT_COMMON_PROC_AND_PORT(PID, PORT) \
+ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \
+ \
+ dtrace_proc_str((PID), process_str); \
+ dtrace_port_str((PORT), port_str);
+#endif
/* The 'number' field in a port now has two parts: the lowest bits
contain the index in the port table, and the higher bits are a counter
@@ -424,6 +440,7 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver,
sys_strcpy(new_name, name);
erts_smp_runq_lock(runq);
erts_smp_port_state_lock(prt);
+ prt->os_pid = -1;
prt->status = ERTS_PORT_SFLG_CONNECTED | xstatus;
prt->snapshot = erts_smp_atomic32_read_nob(&erts_ports_snapshot);
old_name = prt->name;
@@ -444,7 +461,7 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver,
prt->control_flags = 0;
prt->connected = pid;
- prt->drv_data = (long) drv_data;
+ prt->drv_data = (SWord) drv_data;
prt->bytes_in = 0;
prt->bytes_out = 0;
prt->dist_entry = NULL;
@@ -609,7 +626,11 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
port->lock = erts_alloc(ERTS_ALC_T_PORT_LOCK,
sizeof(erts_smp_mtx_t));
erts_smp_mtx_init_x(port->lock,
+#ifdef ERTS_ENABLE_LOCK_COUNT
+ (erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK) ? "port_lock" : NULL,
+#else
"port_lock",
+#endif
port->id);
xstatus |= ERTS_PORT_SFLG_PORT_SPECIFIC_LOCK;
}
@@ -638,16 +659,21 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
trace_sched_ports_where(port, am_in, am_start);
}
port->caller = pid;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_start)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(pid, port)
+ DTRACE3(driver_start, process_str, driver->name, port_str);
+ }
+#endif
fpe_was_unmasked = erts_block_fpe();
drv_data = (*driver->start)((ErlDrvPort)(port_ix),
name, opts);
erts_unblock_fpe(fpe_was_unmasked);
port->caller = NIL;
- erts_unblock_fpe(fpe_was_unmasked);
if (IS_TRACED_FL(port, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(port, am_out, am_start);
}
- if (error_number_ptr && ((long) drv_data) == (long) -2)
+ if (error_number_ptr && ((SWord) drv_data) == (SWord) -2)
*error_number_ptr = errno;
#ifdef ERTS_SMP
if (port->xports)
@@ -656,10 +682,10 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
#endif
}
- if (((long)drv_data) == -1 ||
- ((long)drv_data) == -2 ||
- ((long)drv_data) == -3) {
- int res = (int) ((long) drv_data);
+ if (((SWord)drv_data) == -1 ||
+ ((SWord)drv_data) == -2 ||
+ ((SWord)drv_data) == -3) {
+ int res = (int) ((SWord) drv_data);
if (res == -3 && error_number_ptr) {
*error_number_ptr = BADARG;
@@ -688,7 +714,7 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
erts_port_release(port);
return res;
}
- port->drv_data = (long) drv_data;
+ port->drv_data = (SWord) drv_data;
return port_ix;
}
@@ -743,7 +769,7 @@ driver_create_port(ErlDrvPort creator_port_ix, /* Creating port */
return (ErlDrvTermData) -1; /* pid does not exist */
}
if ((port_num = get_free_port()) < 0) {
- errno = ENFILE;
+ errno = SYSTEM_LIMIT;
erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK);
erts_smp_mtx_unlock(&erts_driver_list_lock);
return (ErlDrvTermData) -1;
@@ -762,7 +788,13 @@ driver_create_port(ErlDrvPort creator_port_ix, /* Creating port */
creator_port->xports = xplp;
port->lock = erts_alloc(ERTS_ALC_T_PORT_LOCK,
sizeof(erts_smp_mtx_t));
- erts_smp_mtx_init_locked_x(port->lock, "port_lock", port_id);
+ erts_smp_mtx_init_locked_x(port->lock,
+#ifdef ERTS_ENABLE_LOCK_COUNT
+ (erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK) ? "port_lock" : NULL,
+#else
+ "port_lock",
+#endif
+ port_id);
xstatus |= ERTS_PORT_SFLG_PORT_SPECIFIC_LOCK;
}
@@ -818,6 +850,11 @@ erts_smp_xports_unlock(Port *prt)
#define SET_VEC(iov, bv, bin, ptr, len, vlen) do { \
(iov)->iov_base = (ptr); \
(iov)->iov_len = (len); \
+ if (sizeof((iov)->iov_len) < sizeof(len) \
+ /* Check if (len) overflowed (iov)->iov_len */ \
+ && ((len) >> (sizeof((iov)->iov_len)*CHAR_BIT)) != 0) { \
+ goto L_overflow; \
+ } \
*(bv)++ = (bin); \
(iov)++; \
(vlen)++; \
@@ -828,13 +865,13 @@ io_list_to_vec(Eterm obj, /* io-list */
SysIOVec* iov, /* io vector */
ErlDrvBinary** binv, /* binary reference vector */
ErlDrvBinary* cbin, /* binary to store characters */
- int bin_limit) /* small binaries limit */
+ ErlDrvSizeT bin_limit) /* small binaries limit */
{
DECLARE_ESTACK(s);
Eterm* objp;
char *buf = cbin->orig_bytes;
- int len = cbin->orig_size;
- int csize = 0;
+ ErlDrvSizeT len = cbin->orig_size;
+ ErlDrvSizeT csize = 0;
int vlen = 0;
char* cptr = buf;
@@ -874,7 +911,7 @@ io_list_to_vec(Eterm obj, /* io-list */
Eterm real_bin;
Uint offset;
Eterm* bptr;
- int size;
+ ErlDrvSizeT size;
int bitoffs;
int bitsize;
@@ -949,9 +986,9 @@ io_list_to_vec(Eterm obj, /* io-list */
#define IO_LIST_VEC_COUNT(obj) \
do { \
- int _size = binary_size(obj); \
+ ErlDrvSizeT _size = binary_size(obj); \
Eterm _real; \
- Uint _offset; \
+ ERTS_DECLARE_DUMMY(Uint _offset); \
int _bitoffs; \
int _bitsize; \
ERTS_GET_REAL_BIN(obj, _real, _offset, _bitoffs, _bitsize); \
@@ -1104,7 +1141,7 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list)
Uint csize;
Uint pvsize;
Uint pcsize;
- int blimit;
+ ErlDrvSizeT blimit;
SysIOVec iv[SMALL_WRITE_VEC];
ErlDrvBinary* bv[SMALL_WRITE_VEC];
SysIOVec* ivp;
@@ -1146,15 +1183,31 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list)
ivp[0].iov_len = 0;
bvp[0] = NULL;
ev.vsize = io_list_to_vec(list, ivp+1, bvp+1, cbin, blimit);
+ if (ev.vsize < 0) {
+ if (ivp != iv) {
+ erts_free(ERTS_ALC_T_TMP, (void *) ivp);
+ }
+ if (bvp != bv) {
+ erts_free(ERTS_ALC_T_TMP, (void *) bvp);
+ }
+ driver_free_binary(cbin);
+ goto bad_value;
+ }
ev.vsize++;
#if 0
/* This assertion may say something useful, but it can
be falsified during the emulator test suites. */
- ASSERT((ev.vsize >= 0) && (ev.vsize == vsize));
+ ASSERT(ev.vsize == vsize);
#endif
ev.size = size; /* total size */
ev.iov = ivp;
ev.binv = bvp;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_outputv)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p)
+ DTRACE4(driver_outputv, process_str, port_str, p->name, size);
+ }
+#endif
fpe_was_unmasked = erts_block_fpe();
(*drv->outputv)((ErlDrvData)p->drv_data, &ev);
erts_unblock_fpe(fpe_was_unmasked);
@@ -1174,8 +1227,21 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list)
buf = erts_alloc(ERTS_ALC_T_TMP, size+1);
r = io_list_to_buf(list, buf, size);
+#ifdef USE_VM_PROBES
+ if(DTRACE_ENABLED(port_command)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p)
+ DTRACE4(port_command, process_str, port_str, p->name, "command");
+ }
+#endif
+
if (r >= 0) {
size -= r;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_output)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p)
+ DTRACE4(driver_output, process_str, port_str, p->name, size);
+ }
+#endif
fpe_was_unmasked = erts_block_fpe();
(*drv->output)((ErlDrvData)p->drv_data, buf, size);
erts_unblock_fpe(fpe_was_unmasked);
@@ -1199,6 +1265,12 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list)
*/
buf = erts_alloc(ERTS_ALC_T_TMP, size+1);
r = io_list_to_buf(list, buf, size);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_output)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p)
+ DTRACE4(driver_output, process_str, port_str, p->name, size);
+ }
+#endif
fpe_was_unmasked = erts_block_fpe();
(*drv->output)((ErlDrvData)p->drv_data, buf, size);
erts_unblock_fpe(fpe_was_unmasked);
@@ -1242,7 +1314,7 @@ void init_io(void)
pdl_init();
- if (erts_sys_getenv("ERL_MAX_PORTS", maxports, &maxportssize) == 0)
+ if (erts_sys_getenv_raw("ERL_MAX_PORTS", maxports, &maxportssize) == 0)
erts_max_ports = atoi(maxports);
else
erts_max_ports = sys_max_files();
@@ -1286,7 +1358,13 @@ void init_io(void)
erts_smp_atomic_init_nob(&erts_port[i].refc, 0);
erts_port[i].lock = NULL;
erts_port[i].xports = NULL;
- erts_smp_spinlock_init_x(&erts_port[i].state_lck, "port_state", make_small(i));
+ erts_smp_spinlock_init_x(&erts_port[i].state_lck,
+#ifdef ERTS_ENABLE_LOCK_COUNT
+ (erts_lcnt_rt_options & ERTS_LCNT_OPT_PORTLOCK) ? "port_state" : NULL,
+#else
+ "port_state",
+#endif
+ make_small(0));
#endif
erts_port[i].tracer_proc = NIL;
erts_port[i].trace_flags = 0;
@@ -1319,6 +1397,27 @@ void init_io(void)
erts_smp_mtx_unlock(&erts_driver_list_lock);
}
+#if defined(ERTS_ENABLE_LOCK_COUNT) && defined(ERTS_SMP)
+void erts_lcnt_enable_io_lock_count(int enable) {
+ int i;
+
+ for (i = 0; i < erts_max_ports; i++) {
+ Port* p = &erts_port[i];
+ if (enable) {
+ erts_lcnt_init_lock_x(&p->state_lck.lcnt, "port_state", ERTS_LCNT_LT_SPINLOCK, make_small(i));
+ if (p->lock) {
+ erts_lcnt_init_lock_x(&p->lock->lcnt, "port_lock", ERTS_LCNT_LT_MUTEX, make_small(i));
+ }
+ } else {
+ erts_lcnt_destroy_lock(&p->state_lck.lcnt);
+ if (p->lock) {
+ erts_lcnt_destroy_lock(&p->lock->lcnt);
+ }
+ }
+ }
+}
+#endif
+
/*
* Buffering of data when using line oriented I/O on ports
*/
@@ -1360,7 +1459,8 @@ int bufsiz;
* buf - A buffer containing the data to be read and split to lines.
* len - The number of bytes in buf.
*/
-static int init_linebuf_context(LineBufContext *lc, LineBuf **lb, char *buf, int len)
+static int init_linebuf_context(LineBufContext *lc, LineBuf **lb,
+ char *buf, ErlDrvSizeT len)
{
if(lc == NULL || lb == NULL)
return -1;
@@ -1513,7 +1613,11 @@ deliver_result(Eterm sender, Eterm pid, Eterm res)
hp = erts_alloc_message_heap(sz_res + 3, &bp, &ohp, rp, &rp_locks);
res = copy_struct(res, sz_res, &hp, ohp);
tuple = TUPLE2(hp, sender, res);
- erts_queue_message(rp, &rp_locks, bp, tuple, NIL);
+ erts_queue_message(rp, &rp_locks, bp, tuple, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -1529,10 +1633,10 @@ deliver_result(Eterm sender, Eterm pid, Eterm res)
*/
static void deliver_read_message(Port* prt, Eterm to,
- char *hbuf, int hlen,
- char *buf, int len, int eol)
+ char *hbuf, ErlDrvSizeT hlen,
+ char *buf, ErlDrvSizeT len, int eol)
{
- int need;
+ ErlDrvSizeT need;
Eterm listp;
Eterm tuple;
Process* rp;
@@ -1602,7 +1706,11 @@ static void deliver_read_message(Port* prt, Eterm to,
tuple = TUPLE2(hp, prt->id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -1612,8 +1720,8 @@ static void deliver_read_message(Port* prt, Eterm to,
* deliver_read_message, and takes the same parameters.
*/
static void deliver_linebuf_message(Port* prt, Eterm to,
- char* hbuf, int hlen,
- char *buf, int len)
+ char* hbuf, ErlDrvSizeT hlen,
+ char *buf, ErlDrvSizeT len)
{
LineBufContext lc;
int ret;
@@ -1656,14 +1764,14 @@ static void
deliver_vec_message(Port* prt, /* Port */
Eterm to, /* Receiving pid */
char* hbuf, /* "Header" buffer... */
- int hlen, /* ... and its length */
+ ErlDrvSizeT hlen, /* ... and its length */
ErlDrvBinary** binv, /* Vector of binaries */
SysIOVec* iov, /* I/O vector */
int vsize, /* Size of binv & iov */
- int csize) /* Size of characters in
+ ErlDrvSizeT csize) /* Size of characters in
iov (not hlen) */
{
- int need;
+ ErlDrvSizeT need;
Eterm listp;
Eterm tuple;
Process* rp;
@@ -1744,7 +1852,7 @@ deliver_vec_message(Port* prt, /* Port */
}
}
- if (hlen > 0) { /* Prepend the header */
+ if (hlen != 0) { /* Prepend the header */
Eterm* thp = hp;
listp = buf_to_intlist(&thp, hbuf, hlen, listp);
hp = thp;
@@ -1755,7 +1863,11 @@ deliver_vec_message(Port* prt, /* Port */
tuple = TUPLE2(hp, prt->id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -1764,10 +1876,10 @@ deliver_vec_message(Port* prt, /* Port */
static void deliver_bin_message(Port* prt, /* port */
Eterm to, /* receiving pid */
char* hbuf, /* "header" buffer */
- int hlen, /* and it's length */
+ ErlDrvSizeT hlen, /* and it's length */
ErlDrvBinary* bin, /* binary data */
- int offs, /* offset into binary */
- int len) /* length of binary */
+ ErlDrvSizeT offs, /* offset into binary */
+ ErlDrvSizeT len) /* length of binary */
{
SysIOVec vec;
@@ -1794,6 +1906,12 @@ static void flush_port(Port *p)
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
if (p->drv_ptr->flush != NULL) {
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_flush)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(p->connected, p)
+ DTRACE3(driver_flush, process_str, port_str, p->name);
+ }
+#endif
if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(p, am_in, am_flush);
}
@@ -1821,6 +1939,7 @@ terminate_port(Port *prt)
Eterm send_closed_port_id;
Eterm connected_id = NIL /* Initialize to silence compiler */;
erts_driver_t *drv;
+ int halt;
ERTS_SMP_CHK_NO_PROC_LOCKS;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
@@ -1828,6 +1947,8 @@ terminate_port(Port *prt)
ASSERT(!prt->nlinks);
ASSERT(!prt->monitors);
+ /* prt->status may be altered by kill_port()below */
+ halt = (prt->status & ERTS_PORT_SFLG_HALT) != 0;
if (prt->status & ERTS_PORT_SFLG_SEND_CLOSED) {
erts_port_status_band_set(prt, ~ERTS_PORT_SFLG_SEND_CLOSED);
send_closed_port_id = prt->id;
@@ -1846,6 +1967,12 @@ terminate_port(Port *prt)
drv = prt->drv_ptr;
if ((drv != NULL) && (drv->stop != NULL)) {
int fpe_was_unmasked = erts_block_fpe();
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_stop)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(prt->connected, prt)
+ DTRACE3(driver_stop, process_str, drv->name, port_str);
+ }
+#endif
(*drv->stop)((ErlDrvData)prt->drv_data);
erts_unblock_fpe(fpe_was_unmasked);
#ifdef ERTS_SMP
@@ -1879,6 +2006,10 @@ terminate_port(Port *prt)
* We don't want to send the closed message until after the
* port has been removed from the port table (in kill_port()).
*/
+ if (halt && (erts_smp_atomic32_dec_read_nob(&erts_halt_progress) == 0)) {
+ erts_smp_port_unlock(prt); /* We will exit and never return */
+ erl_exit_flush_async(erts_halt_code, "");
+ }
if (is_internal_port(send_closed_port_id))
deliver_result(send_closed_port_id, connected_id, am_closed);
@@ -2003,6 +2134,19 @@ erts_do_exit_port(Port *p, Eterm from, Eterm reason)
rreason = (reason == am_kill) ? am_killed : reason;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(port_exit)) {
+ DTRACE_CHARBUF(from_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);
+ DTRACE_CHARBUF(rreason_str, 64);
+
+ erts_snprintf(from_str, sizeof(from_str), "%T", from);
+ dtrace_port_str(p, port_str);
+ erts_snprintf(rreason_str, sizeof(rreason_str), "%T", rreason);
+ DTRACE4(port_exit, from_str, port_str, p->name, rreason_str);
+ }
+#endif
+
if ((p->status & (ERTS_PORT_SFLGS_DEAD
| ERTS_PORT_SFLG_EXITING
| ERTS_PORT_SFLG_IMMORTAL))
@@ -2103,6 +2247,13 @@ void erts_port_command(Process *proc,
if (tp[2] == am_close) {
erts_port_status_bor_set(port, ERTS_PORT_SFLG_SEND_CLOSED);
erts_do_exit_port(port, pid, am_normal);
+
+#ifdef USE_VM_PROBES
+ if(DTRACE_ENABLED(port_command)) {
+ DTRACE_FORMAT_COMMON_PROC_AND_PORT(proc, port)
+ DTRACE4(port_command, process_str, port_str, port->name, "close");
+ }
+#endif
goto done;
} else if (is_tuple_arity(tp[2], 2)) {
tp = tuple_val(tp[2]);
@@ -2110,6 +2261,12 @@ void erts_port_command(Process *proc,
if (erts_write_to_port(caller_id, port, tp[2]) == 0)
goto done;
} else if ((tp[1] == am_connect) && is_internal_pid(tp[2])) {
+#ifdef USE_VM_PROBES
+ if(DTRACE_ENABLED(port_command)) {
+ DTRACE_FORMAT_COMMON_PROC_AND_PORT(proc, port)
+ DTRACE4(port_command, process_str, port_str, port->name, "connect");
+ }
+#endif
port->connected = tp[2];
deliver_result(port->id, pid, am_connected);
goto done;
@@ -2155,8 +2312,9 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist)
int must_free = 0; /* True if the buffer should be freed. */
char port_result[ERL_ONHEAP_BIN_LIMIT]; /* Default buffer for result from port. */
char* port_resp; /* Pointer to result buffer. */
- int n;
- int (*control)(ErlDrvData, unsigned, char*, int, char**, int);
+ ErlDrvSSizeT n;
+ ErlDrvSSizeT (*control)
+ (ErlDrvData, unsigned, char*, ErlDrvSizeT, char**, ErlDrvSizeT);
int fpe_was_unmasked;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
@@ -2170,8 +2328,8 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist)
* and with its length in to_len.
*/
if (is_binary(iolist) && binary_bitoffset(iolist) == 0) {
- Uint bitoffs;
- Uint bitsize;
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
+ ERTS_DECLARE_DUMMY(Uint bitsize);
ERTS_GET_BINARY_BYTES(iolist, to_port, bitoffs, bitsize);
to_len = binary_size(iolist);
} else {
@@ -2211,6 +2369,15 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist)
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
ERTS_SMP_CHK_NO_PROC_LOCKS;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(port_control) || DTRACE_ENABLED(driver_control)) {
+ DTRACE_FORMAT_COMMON_PROC_AND_PORT(p, prt);
+ DTRACE4(port_control, process_str, port_str, prt->name, command);
+ DTRACE5(driver_control, process_str, port_str, prt->name,
+ command, to_len);
+ }
+#endif
+
/*
* Call the port's control routine.
*/
@@ -2351,6 +2518,10 @@ print_port_info(int to, void *arg, int i)
void
set_busy_port(ErlDrvPort port_num, int on)
{
+#ifdef USE_VM_PROBES
+ DTRACE_CHARBUF(port_str, 16);
+#endif
+
ERTS_SMP_CHK_NO_PROC_LOCKS;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(&erts_port[port_num]));
@@ -2358,12 +2529,26 @@ set_busy_port(ErlDrvPort port_num, int on)
if (on) {
erts_port_status_bor_set(&erts_port[port_num],
ERTS_PORT_SFLG_PORT_BUSY);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(port_busy)) {
+ erts_snprintf(port_str, sizeof(port_str),
+ "%T", erts_port[port_num].id);
+ DTRACE1(port_busy, port_str);
+ }
+#endif
} else {
ErtsProcList* plp = erts_port[port_num].suspended;
erts_port_status_band_set(&erts_port[port_num],
~ERTS_PORT_SFLG_PORT_BUSY);
erts_port[port_num].suspended = NULL;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(port_not_busy)) {
+ erts_snprintf(port_str, sizeof(port_str),
+ "%T", erts_port[port_num].id);
+ DTRACE1(port_not_busy, port_str);
+ }
+#endif
if (erts_port[port_num].dist_entry) {
/*
* Processes suspended on distribution ports are
@@ -2381,6 +2566,28 @@ set_busy_port(ErlDrvPort port_num, int on)
*/
if (plp) {
+#ifdef USE_VM_PROBES
+ /*
+ * Hrm, for blocked dist ports, plp always seems to be NULL.
+ * That's not so fun.
+ * Well, another way to get the same info is using a D
+ * script to correlate an earlier process-port_blocked+pid
+ * event with a later process-scheduled event. That's
+ * subject to the multi-CPU races with how events are
+ * handled, but hey, that way works most of the time.
+ */
+ if (DTRACE_ENABLED(process_port_unblocked)) {
+ DTRACE_CHARBUF(pid_str, 16);
+ ErtsProcList* plp2 = plp;
+
+ erts_snprintf(port_str, sizeof(port_str),
+ "%T", erts_port[port_num]);
+ while (plp2 != NULL) {
+ erts_snprintf(pid_str, sizeof(pid_str), "%T", plp2->pid);
+ DTRACE2(process_port_unblocked, pid_str, port_str);
+ }
+ }
+#endif
/* First proc should be resumed last */
if (plp->next) {
erts_resume_processes(plp->next);
@@ -2427,6 +2634,14 @@ void erts_raw_port_command(Port* p, byte* buf, Uint len)
p->drv_ptr->name ? p->drv_ptr->name : "unknown");
p->caller = NIL;
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_output)) {
+ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_port_str(p, port_str);
+ DTRACE4(driver_output, "-raw-", port_str, p->name, len);
+ }
+#endif
fpe_was_unmasked = erts_block_fpe();
(*p->drv_ptr->output)((ErlDrvData)p->drv_data, (char*) buf, (int) len);
erts_unblock_fpe(fpe_was_unmasked);
@@ -2442,6 +2657,12 @@ int async_ready(Port *p, void* data)
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
ASSERT(!(p->status & ERTS_PORT_SFLGS_DEAD));
if (p->drv_ptr->ready_async != NULL) {
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_ready_async)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(p->connected, p)
+ DTRACE3(driver_ready_async, process_str, port_str, p->name);
+ }
+#endif
(*p->drv_ptr->ready_async)((ErlDrvData)p->drv_data, data);
need_free = 0;
#ifdef ERTS_SMP
@@ -2636,7 +2857,11 @@ void driver_report_exit(int ix, int status)
hp += 3;
tuple = TUPLE2(hp, prt->id, tuple);
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
@@ -3035,6 +3260,8 @@ driver_deliver_term(ErlDrvPort port,
Uint size = ptr[1];
Uint offset = ptr[2];
+ erts_smp_atomic_add_nob(&erts_bytes_in, (erts_aint_t) size);
+
if (size <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hbp = (ErlHeapBin *) hp;
hp += heap_bin_size(size);
@@ -3066,6 +3293,9 @@ driver_deliver_term(ErlDrvPort port,
case ERL_DRV_BUF2BINARY: { /* char*, size */
byte *bufp = (byte *) ptr[0];
Uint size = (Uint) ptr[1];
+
+ erts_smp_atomic_add_nob(&erts_bytes_in, (erts_aint_t) size);
+
if (size <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hbp = (ErlHeapBin *) hp;
hp += heap_bin_size(size);
@@ -3082,7 +3312,7 @@ driver_deliver_term(ErlDrvPort port,
Binary* bp = erts_bin_nrml_alloc(size);
ASSERT(bufp);
bp->flags = 0;
- bp->orig_size = (long) size;
+ bp->orig_size = (SWord) size;
erts_refc_init(&bp->refc, 1);
sys_memcpy((void *) bp->orig_bytes, (void *) bufp, size);
pbp = (ProcBin *) hp;
@@ -3102,6 +3332,7 @@ driver_deliver_term(ErlDrvPort port,
}
case ERL_DRV_STRING: /* char*, length */
+ erts_smp_atomic_add_nob(&erts_bytes_in, (erts_aint_t) ptr[1]);
mess = buf_to_intlist(&hp, (char*)ptr[0], ptr[1], NIL);
ptr += 2;
break;
@@ -3186,7 +3417,11 @@ driver_deliver_term(ErlDrvPort port,
HRelease(rp, hp_end, hp);
}
/* send message */
- erts_queue_message(rp, &rp_locks, bp, mess, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, mess, am_undefined
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
}
else {
if (b2t.ix > b2t.used)
@@ -3239,8 +3474,8 @@ driver_send_term(ErlDrvPort ix, ErlDrvTermData to, ErlDrvTermData* data, int len
* and data is len length of bin starting from offset offs.
*/
-int driver_output_binary(ErlDrvPort ix, char* hbuf, int hlen,
- ErlDrvBinary* bin, int offs, int len)
+int driver_output_binary(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
+ ErlDrvBinary* bin, ErlDrvSizeT offs, ErlDrvSizeT len)
{
Port* prt = erts_drvport2port(ix);
@@ -3273,7 +3508,8 @@ int driver_output_binary(ErlDrvPort ix, char* hbuf, int hlen,
** Example: if hlen = 3 then the port owner will receive the data
** [H1,H2,H3 | T]
*/
-int driver_output2(ErlDrvPort ix, char* hbuf, int hlen, char* buf, int len)
+int driver_output2(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
+ char* buf, ErlDrvSizeT len)
{
Port* prt = erts_drvport2port(ix);
@@ -3310,27 +3546,29 @@ int driver_output2(ErlDrvPort ix, char* hbuf, int hlen, char* buf, int len)
/* Interface functions available to driver writers */
-int driver_output(ErlDrvPort ix, char* buf, int len)
+int driver_output(ErlDrvPort ix, char* buf, ErlDrvSizeT len)
{
ERTS_SMP_CHK_NO_PROC_LOCKS;
return driver_output2(ix, NULL, 0, buf, len);
}
-int driver_outputv(ErlDrvPort ix, char* hbuf, int hlen, ErlIOVec* vec, int skip)
+int driver_outputv(ErlDrvPort ix, char* hbuf, ErlDrvSizeT hlen,
+ ErlIOVec* vec, ErlDrvSizeT skip)
{
int n;
- int len;
- int size;
+ ErlDrvSizeT len;
+ ErlDrvSizeT size;
SysIOVec* iov;
ErlDrvBinary** binv;
Port* prt;
ERTS_SMP_CHK_NO_PROC_LOCKS;
- size = vec->size - skip; /* Size of remaining bytes in vector */
- ASSERT(size >= 0);
- if (size <= 0)
+ ASSERT(vec->size >= skip);
+ if (vec->size <= skip)
return driver_output2(ix, hbuf, hlen, NULL, 0);
+ size = vec->size - skip; /* Size of remaining bytes in vector */
+
ASSERT(hlen >= 0); /* debug only */
if (hlen < 0)
hlen = 0;
@@ -3374,17 +3612,14 @@ int driver_outputv(ErlDrvPort ix, char* hbuf, int hlen, ErlIOVec* vec, int skip)
** input is a vector a buffer and a max length
** return bytes copied
*/
-int driver_vec_to_buf(vec, buf, len)
-ErlIOVec* vec;
-char* buf;
-int len;
+ErlDrvSizeT driver_vec_to_buf(ErlIOVec *vec, char *buf, ErlDrvSizeT len)
{
SysIOVec* iov = vec->iov;
int n = vec->vsize;
- int orig_len = len;
+ ErlDrvSizeT orig_len = len;
while(n--) {
- int ilen = iov->iov_len;
+ size_t ilen = iov->iov_len;
if (ilen < len) {
sys_memcpy(buf, iov->iov_base, ilen);
len -= ilen;
@@ -3436,43 +3671,34 @@ driver_binary_dec_refc(ErlDrvBinary *dbp)
*/
ErlDrvBinary*
-driver_alloc_binary(int size)
+driver_alloc_binary(ErlDrvSizeT size)
{
Binary* bin;
- if (size < 0)
- return NULL;
-
bin = erts_bin_drv_alloc_fnf((Uint) size);
if (!bin)
return NULL; /* The driver write must take action */
bin->flags = BIN_FLAG_DRV;
erts_refc_init(&bin->refc, 1);
- bin->orig_size = (long) size;
+ bin->orig_size = (SWord) size;
return Binary2ErlDrvBinary(bin);
}
/* Reallocate space hold by binary */
-ErlDrvBinary* driver_realloc_binary(ErlDrvBinary* bin, int size)
+ErlDrvBinary* driver_realloc_binary(ErlDrvBinary* bin, ErlDrvSizeT size)
{
Binary* oldbin;
Binary* newbin;
- if (!bin || size < 0) {
+ if (!bin) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp,
- "Bad use of driver_realloc_binary(%p, %d): "
+ "Bad use of driver_realloc_binary(%p, %lu): "
"called with ",
- bin, size);
+ bin, (unsigned long)size);
if (!bin) {
erts_dsprintf(dsbufp, "NULL pointer as first argument");
- if (size < 0)
- erts_dsprintf(dsbufp, ", and ");
- }
- if (size < 0) {
- erts_dsprintf(dsbufp, "negative size as second argument");
- size = 0;
}
erts_send_warning_to_logger_nogl(dsbufp);
if (!bin)
@@ -3512,12 +3738,12 @@ ErlDrvBinary* dbin;
* Allocation/deallocation of memory for drivers
*/
-void *driver_alloc(size_t size)
+void *driver_alloc(ErlDrvSizeT size)
{
return erts_alloc_fnf(ERTS_ALC_T_DRV, (Uint) size);
}
-void *driver_realloc(void *ptr, size_t size)
+void *driver_realloc(void *ptr, ErlDrvSizeT size)
{
return erts_realloc_fnf(ERTS_ALC_T_DRV, ptr, (Uint) size);
}
@@ -3779,11 +4005,11 @@ static int expandq(ErlIOQueue* q, int n, int tail)
/* Put elements from vec at q tail */
-int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, int skip)
+int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip)
{
int n;
- int len;
- int size;
+ size_t len;
+ ErlDrvSizeT size;
SysIOVec* iov;
ErlDrvBinary** binv;
ErlDrvBinary* b;
@@ -3792,10 +4018,10 @@ int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, int skip)
if (q == NULL)
return -1;
- size = vec->size - skip;
- ASSERT(size >= 0); /* debug only */
- if (size <= 0)
+ ASSERT(vec->size >= skip); /* debug only */
+ if (vec->size <= skip)
return 0;
+ size = vec->size - skip;
iov = vec->iov;
binv = vec->binv;
@@ -3845,11 +4071,11 @@ int driver_enqv(ErlDrvPort ix, ErlIOVec* vec, int skip)
}
/* Put elements from vec at q head */
-int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, int skip)
+int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, ErlDrvSizeT skip)
{
int n;
- int len;
- int size;
+ size_t len;
+ ErlDrvSizeT size;
SysIOVec* iov;
ErlDrvBinary** binv;
ErlDrvBinary* b;
@@ -3858,8 +4084,10 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, int skip)
if (q == NULL)
return -1;
- if ((size = vec->size - skip) <= 0)
+ if (vec->size <= skip)
return 0;
+ size = vec->size - skip;
+
iov = vec->iov;
binv = vec->binv;
n = vec->vsize;
@@ -3914,15 +4142,14 @@ int driver_pushqv(ErlDrvPort ix, ErlIOVec* vec, int skip)
** Remove size bytes from queue head
** Return number of bytes that remain in queue
*/
-int driver_deq(ErlDrvPort ix, int size)
+ErlDrvSizeT driver_deq(ErlDrvPort ix, ErlDrvSizeT size)
{
ErlIOQueue* q = drvport2ioq(ix);
- int len;
- int sz;
+ ErlDrvSizeT len;
- if ((q == NULL) || (sz = (q->size - size)) < 0)
+ if ((q == NULL) || (q->size < size))
return -1;
- q->size = sz;
+ q->size -= size;
while (size > 0) {
ASSERT(q->v_head != q->v_tail);
@@ -3945,16 +4172,16 @@ int driver_deq(ErlDrvPort ix, int size)
q->v_head = q->v_tail = q->v_start;
q->b_head = q->b_tail = q->b_start;
}
- return sz;
+ return q->size;
}
-int driver_peekqv(ErlDrvPort ix, ErlIOVec *ev) {
+ErlDrvSizeT driver_peekqv(ErlDrvPort ix, ErlIOVec *ev) {
ErlIOQueue *q = drvport2ioq(ix);
ASSERT(ev);
if (! q) {
- return -1;
+ return (ErlDrvSizeT) -1;
} else {
if ((ev->vsize = q->v_tail - q->v_head) == 0) {
ev->size = 0;
@@ -3983,12 +4210,12 @@ SysIOVec* driver_peekq(ErlDrvPort ix, int* vlenp) /* length of io-vector */
}
-int driver_sizeq(ErlDrvPort ix)
+ErlDrvSizeT driver_sizeq(ErlDrvPort ix)
{
ErlIOQueue* q = drvport2ioq(ix);
if (q == NULL)
- return -1;
+ return (size_t) -1;
return q->size;
}
@@ -3996,7 +4223,8 @@ int driver_sizeq(ErlDrvPort ix)
/* Utils */
/* Enqueue a binary */
-int driver_enq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len)
+int driver_enq_bin(ErlDrvPort ix, ErlDrvBinary* bin,
+ ErlDrvSizeT offs, ErlDrvSizeT len)
{
SysIOVec iov;
ErlIOVec ev;
@@ -4013,7 +4241,7 @@ int driver_enq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len)
return driver_enqv(ix, &ev, 0);
}
-int driver_enq(ErlDrvPort ix, char* buffer, int len)
+int driver_enq(ErlDrvPort ix, char* buffer, ErlDrvSizeT len)
{
int code;
ErlDrvBinary* bin;
@@ -4029,7 +4257,8 @@ int driver_enq(ErlDrvPort ix, char* buffer, int len)
return code;
}
-int driver_pushq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len)
+int driver_pushq_bin(ErlDrvPort ix, ErlDrvBinary* bin,
+ ErlDrvSizeT offs, ErlDrvSizeT len)
{
SysIOVec iov;
ErlIOVec ev;
@@ -4046,7 +4275,7 @@ int driver_pushq_bin(ErlDrvPort ix, ErlDrvBinary* bin, int offs, int len)
return driver_pushqv(ix, &ev, 0);
}
-int driver_pushq(ErlDrvPort ix, char* buffer, int len)
+int driver_pushq(ErlDrvPort ix, char* buffer, ErlDrvSizeT len)
{
int code;
ErlDrvBinary* bin;
@@ -4075,7 +4304,7 @@ drv_cancel_timer(Port *prt)
erts_port_task_abort(prt->id, &prt->timeout_task);
}
-int driver_set_timer(ErlDrvPort ix, UWord t)
+int driver_set_timer(ErlDrvPort ix, unsigned long t)
{
Port* prt = erts_drvport2port(ix);
@@ -4423,6 +4652,12 @@ void erts_fire_port_monitor(Port *prt, Eterm ref)
ASSERT(callback != NULL);
ref_to_driver_monitor(ref,&drv_monitor);
DRV_MONITOR_UNLOCK_PDL(prt);
+#ifdef USE_VM_PROBES
+ if (DTRACE_ENABLED(driver_process_exit)) {
+ DTRACE_FORMAT_COMMON_PID_AND_PORT(prt->connected, prt)
+ DTRACE3(driver_process_exit, process_str, port_str, prt->name);
+ }
+#endif
fpe_was_unmasked = erts_block_fpe();
(*callback)((ErlDrvData) (prt->drv_data), &drv_monitor);
erts_unblock_fpe(fpe_was_unmasked);
@@ -4579,7 +4814,10 @@ int driver_lock_driver(ErlDrvPort ix)
erts_smp_mtx_lock(&erts_driver_list_lock);
- if (prt == NULL) return -1;
+ if (prt == NULL) {
+ erts_smp_mtx_unlock(&erts_driver_list_lock);
+ return -1;
+ }
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if ((dh = (DE_Handle*)prt->drv_ptr->handle ) == NULL) {
@@ -4764,7 +5002,7 @@ get_current_port(void)
*/
static void
-no_output_callback(ErlDrvData drv_data, char *buf, int len)
+no_output_callback(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
}
@@ -4815,16 +5053,11 @@ static int
init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle)
{
drv->name = de->driver_name;
- if (de->extended_marker == ERL_DRV_EXTENDED_MARKER) {
- drv->version.major = de->major_version;
- drv->version.minor = de->minor_version;
- drv->flags = de->driver_flags;
- }
- else {
- drv->version.major = 0;
- drv->version.minor = 0;
- drv->flags = 0;
- }
+ ASSERT(de->extended_marker == ERL_DRV_EXTENDED_MARKER);
+ ASSERT(de->major_version >= 2);
+ drv->version.major = de->major_version;
+ drv->version.minor = de->minor_version;
+ drv->flags = de->driver_flags;
drv->handle = handle;
#ifdef ERTS_SMP
if (drv->flags & ERL_DRV_FLAG_USE_PORT_LOCKING)
@@ -4857,11 +5090,8 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle)
drv->ready_output = de->ready_output ? de->ready_output : no_ready_output_callback;
drv->timeout = de->timeout ? de->timeout : no_timeout_callback;
drv->ready_async = de->ready_async;
- if (de->extended_marker == ERL_DRV_EXTENDED_MARKER)
- drv->process_exit = de->process_exit;
- else
- drv->process_exit = NULL;
- if (de->minor_version >= 3/*R13A*/ && de->stop_select)
+ drv->process_exit = de->process_exit;
+ if (de->stop_select)
drv->stop_select = de->stop_select;
else
drv->stop_select = no_stop_select_callback;
@@ -4871,6 +5101,8 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle)
else {
int res;
int fpe_was_unmasked = erts_block_fpe();
+ DTRACE4(driver_init, drv->name, drv->version.major, drv->version.minor,
+ drv->flags);
res = (*de->init)();
erts_unblock_fpe(fpe_was_unmasked);
return res;
@@ -4995,11 +5227,11 @@ int null_func(void)
int
erl_drv_putenv(char *key, char *value)
{
- return erts_write_env(key, value);
+ return erts_sys_putenv_raw(key, value);
}
int
erl_drv_getenv(char *key, char *value, size_t *value_size)
{
- return erts_sys_getenv(key, value, value_size);
+ return erts_sys_getenv_raw(key, value, value_size);
}
diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c
index 91e4ccce70..b93b1ad09a 100644
--- a/erts/emulator/beam/module.c
+++ b/erts/emulator/beam/module.c
@@ -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
@@ -108,7 +108,8 @@ erts_put_module(Eterm mod)
int index;
ASSERT(is_atom(mod));
- ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
+ ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ || erts_smp_thr_progress_is_blocking());
e.module = atom_val(mod);
index = index_put(&module_table, (void*) &e);
return (Module*) erts_index_lookup(&module_table, index);
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 34bd5d0653..9b168889dd 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -845,11 +845,11 @@ call_ext_only u==3 u$func:erlang:apply/3 => i_apply_only
# thus there is no need to generate any return instruction.
#
-call_ext_last u==1 Bif=u$bif:erlang:exit/1 D => call_bif1 Bif
-call_ext_last u==1 Bif=u$bif:erlang:throw/1 D => call_bif1 Bif
+call_ext_last u==1 Bif=u$bif:erlang:exit/1 D => call_bif Bif
+call_ext_last u==1 Bif=u$bif:erlang:throw/1 D => call_bif Bif
-call_ext_only u==1 Bif=u$bif:erlang:exit/1 => call_bif1 Bif
-call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif1 Bif
+call_ext_only u==1 Bif=u$bif:erlang:exit/1 => call_bif Bif
+call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif Bif
#
# The error/1 and error/2 BIFs never execute the instruction following them;
@@ -859,13 +859,13 @@ call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif1 Bif
# the continuation pointer on the stack.
#
-call_ext_last u==1 Bif=u$bif:erlang:error/1 D => call_bif1 Bif
-call_ext_last u==2 Bif=u$bif:erlang:error/2 D => call_bif2 Bif
+call_ext_last u==1 Bif=u$bif:erlang:error/1 D => call_bif Bif
+call_ext_last u==2 Bif=u$bif:erlang:error/2 D => call_bif Bif
call_ext_only Ar=u==1 Bif=u$bif:erlang:error/1 => \
- allocate u Ar | call_bif1 Bif
+ allocate u Ar | call_bif Bif
call_ext_only Ar=u==2 Bif=u$bif:erlang:error/2 => \
- allocate u Ar | call_bif2 Bif
+ allocate u Ar | call_bif Bif
#
# The yield/0 BIF is an instruction
@@ -883,30 +883,107 @@ call_ext_last u==3 u$func:erlang:hibernate/3 D => i_hibernate
call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate
#
+# If VM probes are not enabled, we want to short-circult calls to
+# the dt tag BIFs to make them as cheap as possible.
+#
+
+%unless USE_VM_PROBES
+
+call_ext Arity u$func:erlang:dt_get_tag/0 => \
+ move a=am_undefined r
+call_ext_last Arity u$func:erlang:dt_get_tag/0 D => \
+ move a=am_undefined r | deallocate D | return
+call_ext_only Arity u$func:erlang:dt_get_tag/0 => \
+ move a=am_undefined r | return
+
+move Any r | call_ext Arity u$func:erlang:dt_put_tag/1 => \
+ move a=am_undefined r
+move Any r | call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
+ move a=am_undefined r | deallocate D | return
+move Any r | call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
+ move a=am_undefined r | return
+call_ext Arity u$func:erlang:dt_put_tag/1 => \
+ move a=am_undefined r
+call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
+ move a=am_undefined r | deallocate D | return
+call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
+ move a=am_undefined r | return
+
+call_ext Arity u$func:erlang:dt_get_tag_data/0 => \
+ move a=am_undefined r
+call_ext_last Arity u$func:erlang:dt_get_tag_data/0 D => \
+ move a=am_undefined r | deallocate D | return
+call_ext_only Arity u$func:erlang:dt_get_tag_data/0 => \
+ move a=am_undefined r | return
+
+move Any r | call_ext Arity u$func:erlang:dt_spread_tag/1 => \
+ move a=am_true r
+move Any r | call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
+ move a=am_true r | deallocate D | return
+move Any r | call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
+ move a=am_true r | return
+call_ext Arity u$func:erlang:dt_spread_tag/1 => \
+ move a=am_true r
+call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
+ move a=am_true r | deallocate D | return
+call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
+ move a=am_true r | return
+
+move Any r | call_ext Arity u$func:erlang:dt_restore_tag/1 => \
+ move a=am_true r
+move Any r | call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
+ move a=am_true r | deallocate D | return
+move Any r | call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
+ move a=am_true r | return
+call_ext Arity u$func:erlang:dt_restore_tag/1 => \
+ move a=am_true r
+call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
+ move a=am_true r | deallocate D | return
+call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
+ move a=am_true r | return
+
+move Any r | call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+ move Any r
+move Any r | call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
+ move Any r | deallocate D | return
+move Any r | call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+ move Any r | return
+call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 =>
+call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
+ deallocate D | return
+call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+ return
+
+move Any r | call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+ move Any r
+move Any r | call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
+ move Any r | deallocate D | return
+move Any r | call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+ move Any r | return
+call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 =>
+call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
+ deallocate D | return
+call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+ return
+
+# Can happen after one of the transformations above.
+move Discarded r | move Something r => move Something r
+
+%endif
+
+#
# The general case for BIFs that have no special instructions.
# A BIF used in the tail must be followed by a return instruction.
#
# To make trapping and stack backtraces work correctly, we make sure that
# the continuation pointer is always stored on the stack.
-call_ext u==0 Bif=u$is_bif => call_bif0 Bif
-call_ext u==1 Bif=u$is_bif => call_bif1 Bif
-call_ext u==2 Bif=u$is_bif => call_bif2 Bif
-call_ext u==3 Bif=$is_bif => call_bif3 Bif
+call_ext u Bif=u$is_bif => call_bif Bif
-call_ext_last u==0 Bif=u$is_bif D => call_bif0 Bif | deallocate_return D
-call_ext_last u==1 Bif=u$is_bif D => call_bif1 Bif | deallocate_return D
-call_ext_last u==2 Bif=u$is_bif D => call_bif2 Bif | deallocate_return D
-call_ext_last u==3 Bif=u$is_bif D => call_bif3 Bif | deallocate_return D
+call_ext_last u Bif=u$is_bif D => call_bif Bif | deallocate_return D
-call_ext_only Ar=u==0 Bif=u$is_bif => \
- allocate u Ar | call_bif0 Bif | deallocate_return u
-call_ext_only Ar=u==1 Bif=u$is_bif => \
- allocate u Ar | call_bif1 Bif | deallocate_return u
-call_ext_only Ar=u==2 Bif=u$is_bif => \
- allocate u Ar | call_bif2 Bif | deallocate_return u
-call_ext_only Ar=u==3 Bif=u$is_bif => \
- allocate u Ar | call_bif3 Bif | deallocate_return u
+call_ext_only Ar=u Bif=u$is_bif => \
+ allocate u Ar | call_bif Bif | deallocate_return u
#
# Any remaining calls are calls to Erlang functions, not BIFs.
@@ -933,10 +1010,7 @@ i_apply_fun_only
i_hibernate
-call_bif0 e
-call_bif1 e
-call_bif2 e
-call_bif3 e
+call_bif e
#
# Calls to non-building and guard BIFs.
diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c
index a66d60aa22..f1cfa8df39 100644
--- a/erts/emulator/beam/packet_parser.c
+++ b/erts/emulator/beam/packet_parser.c
@@ -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
@@ -301,7 +301,11 @@ int packet_get_length(enum PacketParseType htype,
/* TCP_PB_LINE_LF: [Data ... \n] */
const char* ptr2;
if ((ptr2 = memchr(ptr, '\n', n)) == NULL) {
- if (n >= trunc_len && trunc_len!=0) { /* buffer full */
+ if (n > max_plen && max_plen != 0) { /* packet full */
+ DEBUGF((" => packet full (no NL)=%d\r\n", n));
+ goto error;
+ }
+ else if (n >= trunc_len && trunc_len!=0) { /* buffer full */
DEBUGF((" => line buffer full (no NL)=%d\r\n", n));
return trunc_len;
}
@@ -309,6 +313,10 @@ int packet_get_length(enum PacketParseType htype,
}
else {
int len = (ptr2 - ptr) + 1; /* including newline */
+ if (len > max_plen && max_plen!=0) {
+ DEBUGF((" => packet_size %d exceeded\r\n", max_plen));
+ goto error;
+ }
if (len > trunc_len && trunc_len!=0) {
DEBUGF((" => truncated line=%d\r\n", trunc_len));
return trunc_len;
@@ -397,33 +405,50 @@ int packet_get_length(enum PacketParseType htype,
const char* ptr1 = ptr;
int len = plen;
+ if (!max_plen) {
+ /* This is for backward compatibility with old user of decode_packet
+ * that might use option 'line_length' to limit accepted length of
+ * http lines.
+ */
+ max_plen = trunc_len;
+ }
+
while (1) {
const char* ptr2 = memchr(ptr1, '\n', len);
if (ptr2 == NULL) {
- if (n >= trunc_len && trunc_len!=0) { /* buffer full */
- plen = trunc_len;
- goto done;
+ if (max_plen != 0) {
+ if (n >= max_plen) /* packet full */
+ goto error;
}
goto more;
}
else {
plen = (ptr2 - ptr) + 1;
-
- if (*statep == 0)
+
+ if (*statep == 0) {
+ if (max_plen != 0 && plen > max_plen)
+ goto error;
goto done;
-
+ }
+
if (plen < n) {
if (SP(ptr2+1) && plen>2) {
/* header field value continue on next line */
ptr1 = ptr2+1;
len = n - plen;
}
- else
+ else {
+ if (max_plen != 0 && plen > max_plen)
+ goto error;
goto done;
+ }
}
- else
+ else {
+ if (max_plen != 0 && plen > max_plen)
+ goto error;
goto more;
+ }
}
}
}
diff --git a/erts/emulator/beam/register.h b/erts/emulator/beam/register.h
index 97bab3ab71..38e8cfbf28 100644
--- a/erts/emulator/beam/register.h
+++ b/erts/emulator/beam/register.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,7 @@ struct port;
typedef struct reg_proc
{
HashBucket bucket; /* MUST BE LOCATED AT TOP OF STRUCT!!! */
- Process *p; /* The process registerd (only one of this and
+ Process *p; /* The process registered (only one of this and
'pt' is non-NULL */
struct port *pt; /* The port registered */
Eterm name; /* Atom name */
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 669a601b35..2406c52f14 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,15 @@ typedef ERTS_SYS_FD_TYPE ErtsSysFdType;
# define ERTS_LIKELY(BOOL) (BOOL)
# define ERTS_UNLIKELY(BOOL) (BOOL)
#endif
+#ifdef __GNUC__
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+# define ERTS_DECLARE_DUMMY(X) X __attribute__ ((unused))
+# else
+# define ERTS_DECLARE_DUMMY(X) X
+# endif
+#else
+# define ERTS_DECLARE_DUMMY(X) X
+#endif
#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
# undef ERTS_CAN_INLINE
@@ -212,7 +221,8 @@ int real_printf(const char *fmt, ...);
*/
#if !((SIZEOF_VOID_P >= 4) && (SIZEOF_VOID_P == SIZEOF_SIZE_T) \
- && ((SIZEOF_VOID_P == SIZEOF_INT) || (SIZEOF_VOID_P == SIZEOF_LONG)))
+ && ((SIZEOF_VOID_P == SIZEOF_INT) || (SIZEOF_VOID_P == SIZEOF_LONG) || \
+ (SIZEOF_VOID_P == SIZEOF_LONG_LONG)))
#error Cannot handle this combination of int/long/void*/size_t sizes
#endif
@@ -246,6 +256,7 @@ typedef unsigned int Eterm;
typedef unsigned int Uint;
typedef int Sint;
#define ERTS_SIZEOF_ETERM SIZEOF_INT
+#define ErtsStrToSint strtol
#else
#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
#endif
@@ -253,9 +264,18 @@ typedef int Sint;
#if SIZEOF_VOID_P == SIZEOF_LONG
typedef unsigned long UWord;
typedef long SWord;
+#define SWORD_CONSTANT(Const) Const##L
+#define UWORD_CONSTANT(Const) Const##UL
#elif SIZEOF_VOID_P == SIZEOF_INT
typedef unsigned int UWord;
typedef int SWord;
+#define SWORD_CONSTANT(Const) Const
+#define UWORD_CONSTANT(Const) Const##U
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+typedef unsigned long long UWord;
+typedef long long SWord;
+#define SWORD_CONSTANT(Const) Const##LL
+#define UWORD_CONSTANT(Const) Const##ULL
#else
#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
#endif
@@ -266,12 +286,30 @@ typedef int SWord;
typedef unsigned long Eterm;
typedef unsigned long Uint;
typedef long Sint;
+#define SWORD_CONSTANT(Const) Const##L
+#define UWORD_CONSTANT(Const) Const##UL
#define ERTS_SIZEOF_ETERM SIZEOF_LONG
+#define ErtsStrToSint strtol
#elif SIZEOF_VOID_P == SIZEOF_INT
typedef unsigned int Eterm;
typedef unsigned int Uint;
typedef int Sint;
+#define SWORD_CONSTANT(Const) Const
+#define UWORD_CONSTANT(Const) Const##U
#define ERTS_SIZEOF_ETERM SIZEOF_INT
+#define ErtsStrToSint strtol
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+typedef unsigned long long Eterm;
+typedef unsigned long long Uint;
+typedef long long Sint;
+#define SWORD_CONSTANT(Const) Const##LL
+#define UWORD_CONSTANT(Const) Const##ULL
+#define ERTS_SIZEOF_ETERM SIZEOF_LONG_LONG
+#if defined(__WIN32__)
+#define ErtsStrToSint _strtoi64
+#else
+#define ErtsStrToSint strtoll
+#endif
#else
#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
#endif
@@ -473,16 +511,7 @@ __decl_noreturn void __noreturn erl_exit(int n, char*, ...);
/* Some special erl_exit() codes: */
#define ERTS_INTR_EXIT INT_MIN /* called from signal handler */
#define ERTS_ABORT_EXIT (INT_MIN + 1) /* no crash dump; only abort() */
-#define ERTS_DUMP_EXIT (127) /* crash dump; then exit() */
-
-
-#ifndef ERTS_SMP
-int check_async_ready(void);
-#ifdef USE_THREADS
-void sys_async_ready(int hndl);
-int erts_register_async_ready_callback(void (*funcp)(void));
-#endif
-#endif
+#define ERTS_DUMP_EXIT (INT_MIN + 2) /* crash dump; then exit() */
Eterm erts_check_io_info(void *p);
@@ -615,14 +644,12 @@ extern char *erts_sys_ddll_error(int code);
/*
* System interfaces for startup.
*/
+#include "erl_time.h"
-
-#ifdef ERTS_SMP
void erts_sys_schedule_interrupt(int set);
-void erts_sys_schedule_interrupt_timed(int set, long msec);
+#ifdef ERTS_SMP
+void erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec);
void erts_sys_main_thread(void);
-#else
-#define erts_sys_schedule_interrupt(Set)
#endif
extern void erts_sys_prepare_crash_dump(void);
@@ -638,17 +665,24 @@ Preload* sys_preloaded(void);
unsigned char* sys_preload_begin(Preload*);
void sys_preload_end(Preload*);
int sys_get_key(int);
-void elapsed_time_both(unsigned long *ms_user, unsigned long *ms_sys,
- unsigned long *ms_user_diff, unsigned long *ms_sys_diff);
-void wall_clock_elapsed_time_both(unsigned long *ms_total,
- unsigned long *ms_diff);
+void elapsed_time_both(UWord *ms_user, UWord *ms_sys,
+ UWord *ms_user_diff, UWord *ms_sys_diff);
+void wall_clock_elapsed_time_both(UWord *ms_total,
+ UWord *ms_diff);
void get_time(int *hour, int *minute, int *second);
void get_date(int *year, int *month, int *day);
void get_localtime(int *year, int *month, int *day,
int *hour, int *minute, int *second);
void get_universaltime(int *year, int *month, int *day,
int *hour, int *minute, int *second);
-int univ_to_local(Sint *year, Sint *month, Sint *day,
+int seconds_to_univ(Sint64 seconds,
+ Sint *year, Sint *month, Sint *day,
+ Sint *hour, Sint *minute, Sint *second);
+int univ_to_seconds(Sint year, Sint month, Sint day,
+ Sint hour, Sint minute, Sint second,
+ Sint64* seconds);
+int univ_to_local(
+ Sint *year, Sint *month, Sint *day,
Sint *hour, Sint *minute, Sint *second);
int local_to_univ(Sint *year, Sint *month, Sint *day,
Sint *hour, Sint *minute, Sint *second, int isdst);
@@ -669,16 +703,21 @@ int sys_double_to_chars(double, char*);
void sys_get_pid(char *);
/* erts_sys_putenv() returns, 0 on success and a value != 0 on failure. */
-int erts_sys_putenv(char *key_value, int sep_ix);
+int erts_sys_putenv(char *key, char *value);
+/* Simple variant used from drivers, raw eightbit interface */
+int erts_sys_putenv_raw(char *key, char *value);
/* erts_sys_getenv() returns 0 on success (length of value string in
*size), a value > 0 if value buffer is too small (*size is set to needed
size), and a value < 0 on failure. */
int erts_sys_getenv(char *key, char *value, size_t *size);
+/* Simple variant used from drivers, raw eightbit interface */
+int erts_sys_getenv_raw(char *key, char *value, size_t *size);
+/* erts_sys_getenv__() is only allowed to be used in early init phase */
+int erts_sys_getenv__(char *key, char *value, size_t *size);
/* Easier to use, but not as efficient, environment functions */
char *erts_read_env(char *key);
void erts_free_read_env(void *value);
-int erts_write_env(char *key, char *value);
/* utils.c */
@@ -697,291 +736,14 @@ int erts_write_env(char *key, char *value);
int sys_alloc_opt(int, int);
typedef struct {
- Sint trim_threshold;
- Sint top_pad;
- Sint mmap_threshold;
- Sint mmap_max;
+ int trim_threshold;
+ int top_pad;
+ int mmap_threshold;
+ int mmap_max;
} SysAllocStat;
void sys_alloc_stat(SysAllocStat *);
-/* Block the whole system... */
-
-#define ERTS_BS_FLG_ALLOW_GC (((Uint32) 1) << 0)
-#define ERTS_BS_FLG_ALLOW_IO (((Uint32) 1) << 1)
-
-/* Activities... */
-typedef enum {
- ERTS_ACTIVITY_UNDEFINED, /* Undefined activity */
- ERTS_ACTIVITY_WAIT, /* Waiting */
- ERTS_ACTIVITY_GC, /* Garbage collecting */
- ERTS_ACTIVITY_IO /* I/O including message passing to erl procs */
-} erts_activity_t;
-
-#ifdef ERTS_SMP
-
-typedef enum {
- ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED,
- ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY,
- ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY
-} erts_activity_error_t;
-
-typedef struct {
- erts_smp_atomic32_t do_block;
- struct {
- erts_smp_atomic32_t wait;
- erts_smp_atomic32_t gc;
- erts_smp_atomic32_t io;
- } in_activity;
-} erts_system_block_state_t;
-
-extern erts_system_block_state_t erts_system_block_state;
-
-int erts_is_system_blocked(erts_activity_t allowed_activities);
-void erts_block_me(void (*prepare)(void *), void (*resume)(void *), void *arg);
-void erts_register_blockable_thread(void);
-void erts_unregister_blockable_thread(void);
-void erts_note_activity_begin(erts_activity_t activity);
-void
-erts_check_block(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg);
-void erts_block_system(Uint32 allowed_activities);
-int erts_emergency_block_system(long timeout, Uint32 allowed_activities);
-void erts_release_system(void);
-void erts_system_block_init(void);
-void erts_set_activity_error(erts_activity_error_t, char *, int);
-#ifdef ERTS_ENABLE_LOCK_CHECK
-void erts_lc_activity_change_begin(void);
-void erts_lc_activity_change_end(void);
-int erts_lc_is_blocking(void);
-#define ERTS_LC_IS_BLOCKING \
- (erts_smp_pending_system_block() && erts_lc_is_blocking())
-#endif
-#endif
-
-#define erts_smp_activity_begin(NACT, PRP, RSM, ARG) \
- erts_smp_set_activity(ERTS_ACTIVITY_UNDEFINED, \
- (NACT), \
- 0, \
- (PRP), \
- (RSM), \
- (ARG), \
- __FILE__, \
- __LINE__)
-#define erts_smp_activity_change(OACT, NACT, PRP, RSM, ARG) \
- erts_smp_set_activity((OACT), \
- (NACT), \
- 0, \
- (PRP), \
- (RSM), \
- (ARG), \
- __FILE__, \
- __LINE__)
-#define erts_smp_activity_end(OACT, PRP, RSM, ARG) \
- erts_smp_set_activity((OACT), \
- ERTS_ACTIVITY_UNDEFINED, \
- 0, \
- (PRP), \
- (RSM), \
- (ARG), \
- __FILE__, \
- __LINE__)
-
-#define erts_smp_locked_activity_begin(NACT) \
- erts_smp_set_activity(ERTS_ACTIVITY_UNDEFINED, \
- (NACT), \
- 1, \
- NULL, \
- NULL, \
- NULL, \
- __FILE__, \
- __LINE__)
-#define erts_smp_locked_activity_change(OACT, NACT) \
- erts_smp_set_activity((OACT), \
- (NACT), \
- 1, \
- NULL, \
- NULL, \
- NULL, \
- __FILE__, \
- __LINE__)
-#define erts_smp_locked_activity_end(OACT) \
- erts_smp_set_activity((OACT), \
- ERTS_ACTIVITY_UNDEFINED, \
- 1, \
- NULL, \
- NULL, \
- NULL, \
- __FILE__, \
- __LINE__)
-
-
-ERTS_GLB_INLINE int erts_smp_is_system_blocked(erts_activity_t allowed_activities);
-ERTS_GLB_INLINE void erts_smp_block_system(Uint32 allowed_activities);
-ERTS_GLB_INLINE int erts_smp_emergency_block_system(long timeout,
- Uint32 allowed_activities);
-ERTS_GLB_INLINE void erts_smp_release_system(void);
-ERTS_GLB_INLINE int erts_smp_pending_system_block(void);
-ERTS_GLB_INLINE void erts_smp_chk_system_block(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg);
-ERTS_GLB_INLINE void
-erts_smp_set_activity(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg,
- char *file,
- int line);
-
-#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-
-
-ERTS_GLB_INLINE int
-erts_smp_is_system_blocked(erts_activity_t allowed_activities)
-{
-#ifdef ERTS_SMP
- return erts_is_system_blocked(allowed_activities);
-#else
- return 1;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_block_system(Uint32 allowed_activities)
-{
-#ifdef ERTS_SMP
- erts_block_system(allowed_activities);
-#endif
-}
-
-ERTS_GLB_INLINE int
-erts_smp_emergency_block_system(long timeout, Uint32 allowed_activities)
-{
-#ifdef ERTS_SMP
- return erts_emergency_block_system(timeout, allowed_activities);
-#else
- return 0;
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_release_system(void)
-{
-#ifdef ERTS_SMP
- erts_release_system();
-#endif
-}
-
-ERTS_GLB_INLINE int
-erts_smp_pending_system_block(void)
-{
-#ifdef ERTS_SMP
- return (int) erts_smp_atomic32_read_nob(&erts_system_block_state.do_block);
-#else
- return 0;
-#endif
-}
-
-
-ERTS_GLB_INLINE void
-erts_smp_chk_system_block(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg)
-{
-#ifdef ERTS_SMP
- if (erts_smp_pending_system_block())
- erts_block_me(prepare, resume, arg);
-#endif
-}
-
-ERTS_GLB_INLINE void
-erts_smp_set_activity(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg,
- char *file,
- int line)
-{
-#ifdef ERTS_SMP
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_activity_change_begin();
-#endif
- switch (old_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- break;
- case ERTS_ACTIVITY_WAIT:
- erts_smp_atomic32_dec_acqb(&erts_system_block_state.in_activity.wait);
- if (locked) {
- /* You are not allowed to leave activity waiting
- * without supplying the possibility to block
- * unlocked.
- */
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED,
- file, line);
- }
- break;
- case ERTS_ACTIVITY_GC:
- erts_smp_atomic32_dec_acqb(&erts_system_block_state.in_activity.gc);
- break;
- case ERTS_ACTIVITY_IO:
- erts_smp_atomic32_dec_acqb(&erts_system_block_state.in_activity.io);
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY,
- file, line);
- break;
- }
-
- /* We are not allowed to block when going to activity waiting... */
- if (new_activity != ERTS_ACTIVITY_WAIT && erts_smp_pending_system_block())
- erts_check_block(old_activity,new_activity,locked,prepare,resume,arg);
-
- switch (new_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- break;
- case ERTS_ACTIVITY_WAIT:
- erts_smp_atomic32_inc_mb(&erts_system_block_state.in_activity.wait);
- break;
- case ERTS_ACTIVITY_GC:
- erts_smp_atomic32_inc_mb(&erts_system_block_state.in_activity.gc);
- break;
- case ERTS_ACTIVITY_IO:
- erts_smp_atomic32_inc_mb(&erts_system_block_state.in_activity.io);
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY,
- file, line);
- break;
- }
-
- switch (new_activity) {
- case ERTS_ACTIVITY_WAIT:
- case ERTS_ACTIVITY_GC:
- case ERTS_ACTIVITY_IO:
- if (erts_smp_pending_system_block())
- erts_note_activity_begin(new_activity);
- break;
- default:
- break;
- }
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_activity_change_end();
-#endif
-
-#endif
-}
-
-#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
-
#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
#undef ERTS_REFC_DEBUG
#define ERTS_REFC_DEBUG
@@ -1246,6 +1008,19 @@ void erl_bin_write(unsigned char *, int, int);
#endif
+#ifdef __WIN32__
+#ifdef ARCH_64
+#define ERTS_ALLOC_ALIGN_BYTES 16
+#define ERTS_SMALL_ABS(Small) _abs64(Small)
+#else
+#define ERTS_ALLOC_ALIGN_BYTES 8
+#define ERTS_SMALL_ABS(Small) labs(Small)
+#endif
+#else
+#define ERTS_ALLOC_ALIGN_BYTES 8
+#define ERTS_SMALL_ABS(Small) labs(Small)
+#endif
+
#ifdef __WIN32__
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index 8fa8c1cfe0..932d157cd8 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -107,20 +107,31 @@ static ErlTimer *tiw_min_ptr;
/* Actual interval time chosen by sys_init_time() */
static int itime; /* Constant after init */
-erts_smp_atomic_t do_time; /* set at clock interrupt */
-static ERTS_INLINE erts_aint_t do_time_read(void) { return erts_smp_atomic_read_acqb(&do_time); }
-static ERTS_INLINE erts_aint_t do_time_update(void) { return do_time_read(); }
-static ERTS_INLINE void do_time_init(void) { erts_smp_atomic_init_nob(&do_time, 0L); }
+erts_smp_atomic32_t do_time; /* set at clock interrupt */
+static ERTS_INLINE erts_short_time_t do_time_read(void)
+{
+ return erts_smp_atomic32_read_acqb(&do_time);
+}
+
+static ERTS_INLINE erts_short_time_t do_time_update(void)
+{
+ return do_time_read();
+}
+
+static ERTS_INLINE void do_time_init(void)
+{
+ erts_smp_atomic32_init_nob(&do_time, 0);
+}
/* get the time (in units of itime) to the next timeout,
or -1 if there are no timeouts */
-static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */
+static erts_short_time_t next_time_internal(void) /* PRE: tiw_lock taken by caller */
{
int i, tm, nto;
- unsigned int min;
+ Uint32 min;
ErlTimer* p;
- erts_aint_t dt;
+ erts_short_time_t dt;
if (tiw_nto == 0)
return -1; /* no timeouts in wheel */
@@ -133,7 +144,7 @@ static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */
/* start going through wheel to find next timeout */
tm = nto = 0;
- min = (unsigned int) -1; /* max unsigned int */
+ min = (Uint32) -1; /* max Uint32 */
i = tiw_pos;
do {
p = tiw[i];
@@ -162,7 +173,11 @@ static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */
i = (i + 1) % TIW_SIZE;
} while (i != tiw_pos);
dt = do_time_read();
- return ((min >= dt) ? (min - dt) : 0);
+ if (min <= (Uint32) dt)
+ return 0;
+ if ((min - (Uint32) dt) > (Uint32) ERTS_SHORT_TIME_T_MAX)
+ return ERTS_SHORT_TIME_T_MAX;
+ return (erts_short_time_t) (min - (Uint32) dt);
}
static void remove_timer(ErlTimer *p) {
@@ -191,9 +206,9 @@ static void remove_timer(ErlTimer *p) {
}
/* Private export to erl_time_sup.c */
-erts_aint_t erts_next_time(void)
+erts_short_time_t erts_next_time(void)
{
- erts_aint_t ret;
+ erts_short_time_t ret;
erts_smp_mtx_lock(&tiw_lock);
(void)do_time_update();
@@ -202,7 +217,7 @@ erts_aint_t erts_next_time(void)
return ret;
}
-static ERTS_INLINE void bump_timer_internal(erts_aint_t dt) /* PRE: tiw_lock is write-locked */
+static ERTS_INLINE void bump_timer_internal(erts_short_time_t dt) /* PRE: tiw_lock is write-locked */
{
Uint keep_pos;
Uint count;
@@ -273,7 +288,7 @@ static ERTS_INLINE void bump_timer_internal(erts_aint_t dt) /* PRE: tiw_lock is
}
}
-void erts_bump_timer(erts_aint_t dt) /* dt is value from do_time */
+void erts_bump_timer(erts_short_time_t dt) /* dt is value from do_time */
{
erts_smp_mtx_lock(&tiw_lock);
bump_timer_internal(dt);
@@ -378,8 +393,8 @@ erts_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel,
insert_timer(p, t);
erts_smp_mtx_unlock(&tiw_lock);
#if defined(ERTS_SMP)
- if (t <= (Uint) LONG_MAX)
- erts_sys_schedule_interrupt_timed(1, (long) t);
+ if (t <= (Uint) ERTS_SHORT_TIME_T_MAX)
+ erts_sys_schedule_interrupt_timed(1, (erts_short_time_t) t);
#endif
}
@@ -419,7 +434,7 @@ Uint
erts_time_left(ErlTimer *p)
{
Uint left;
- erts_aint_t dt;
+ erts_short_time_t dt;
erts_smp_mtx_lock(&tiw_lock);
@@ -444,7 +459,7 @@ erts_time_left(ErlTimer *p)
}
#ifdef DEBUG
-void erts_p_slpq()
+void erts_p_slpq(void)
{
int i;
ErlTimer* p;
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 3f6accba2d..bd708ceee6 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,6 +42,10 @@
#include "erl_threads.h"
#include "erl_smp.h"
#include "erl_time.h"
+#include "erl_thr_progress.h"
+#include "erl_thr_queue.h"
+#include "erl_sched_spec_pre_alloc.h"
+#include "beam_bp.h"
#undef M_TRIM_THRESHOLD
#undef M_TOP_PAD
@@ -75,6 +79,7 @@ typedef struct {
#ifdef ERTS_SMP
+#if 0 /* Unused */
static void
dispatch_profile_msg_q(profile_sched_msg_q *psmq)
{
@@ -86,6 +91,7 @@ dispatch_profile_msg_q(profile_sched_msg_q *psmq)
profile_scheduler_q(make_small(msg->scheduler_id), msg->state, am_undefined, msg->Ms, msg->s, msg->us);
}
}
+#endif
#endif
@@ -1691,7 +1697,11 @@ static int do_send_to_logger(Eterm tag, Eterm gleader, char *buf, int len)
erts_queue_error_logger_message(from, tuple3, bp);
}
#else
- erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL);
+ erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL
+#ifdef USE_VM_PROBES
+ , NIL
+#endif
+ );
#endif
return 0;
}
@@ -2642,7 +2652,7 @@ tailrecur_ne:
FloatDef f1, f2;
Eterm big;
#if HEAP_ON_C_STACK
- Eterm big_buf[2]; /* If HEAP_ON_C_STACK */
+ Eterm big_buf[CMP_TMP_HEAP_SIZE]; /* If HEAP_ON_C_STACK */
#else
Eterm *big_buf = erts_get_scheduler_data()->cmp_tmp_heap;
#endif
@@ -2653,42 +2663,98 @@ tailrecur_ne:
Eterm aw = a;
Eterm bw = b;
#endif
+#define MAX_LOSSLESS_FLOAT ((double)((1LL << 53) - 2))
+#define MIN_LOSSLESS_FLOAT ((double)(((1LL << 53) - 2)*-1))
+#define BIG_ARITY_FLOAT_MAX (1024 / D_EXP) /* arity of max float as a bignum */
b_tag = tag_val_def(bw);
switch(_NUMBER_CODE(a_tag, b_tag)) {
case SMALL_BIG:
- big = small_to_big(signed_val(a), big_buf);
- j = big_comp(big, bw);
+ j = big_sign(bw) ? 1 : -1;
+ break;
+ case BIG_SMALL:
+ j = big_sign(aw) ? -1 : 1;
break;
case SMALL_FLOAT:
- f1.fd = signed_val(a);
GET_DOUBLE(bw, f2);
- j = float_comp(f1.fd, f2.fd);
- break;
- case BIG_SMALL:
- big = small_to_big(signed_val(b), big_buf);
- j = big_comp(aw, big);
+ if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ f1.fd = signed_val(aw);
+ j = float_comp(f1.fd, f2.fd);
+#if ERTS_SIZEOF_ETERM == 8
+ } else if (f2.fd > (double) (MAX_SMALL + 1)) {
+ // Float is a positive bignum, i.e. bigger
+ j = -1;
+ } else if (f2.fd < (double) (MIN_SMALL - 1)) {
+ // Float is a negative bignum, i.e. smaller
+ j = 1;
+ } else { // Float is a Sint but less precise
+ j = signed_val(aw) - (Sint) f2.fd;
+ }
+#else
+ } else {
+ // If float is positive it is bigger than small
+ j = (f2.fd > 0.0) ? -1 : 1;
+ }
+#endif // ERTS_SIZEOF_ETERM == 8
break;
+ case FLOAT_BIG:
+ {
+ Wterm tmp = aw;
+ aw = bw;
+ bw = tmp;
+ }/* fall through */
case BIG_FLOAT:
- if (big_to_double(aw, &f1.fd) < 0) {
- j = big_sign(a) ? -1 : 1;
+ GET_DOUBLE(bw, f2);
+ if ((f2.fd < (double) (MAX_SMALL + 1))
+ && (f2.fd > (double) (MIN_SMALL - 1))) {
+ // Float is a Sint
+ j = big_sign(aw) ? -1 : 1;
+ } else if (big_arity(aw) > BIG_ARITY_FLOAT_MAX
+ || pow(2.0,(big_arity(aw)-1)*D_EXP) > fabs(f2.fd)) {
+ // If bignum size shows that it is bigger than the abs float
+ j = big_sign(aw) ? -1 : 1;
+ } else if (big_arity(aw) < BIG_ARITY_FLOAT_MAX
+ && (pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) {
+ // If bignum size shows that it is smaller than the abs float
+ j = f2.fd < 0 ? 1 : -1;
+ } else if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ if (big_to_double(aw, &f1.fd) < 0) {
+ j = big_sign(aw) ? -1 : 1;
+ } else {
+ j = float_comp(f1.fd, f2.fd);
+ }
} else {
- GET_DOUBLE(bw, f2);
- j = float_comp(f1.fd, f2.fd);
+ big = double_to_big(f2.fd, big_buf);
+ j = big_comp(aw, big);
+ }
+ if (_NUMBER_CODE(a_tag, b_tag) == FLOAT_BIG) {
+ j = -j;
}
break;
case FLOAT_SMALL:
GET_DOUBLE(aw, f1);
- f2.fd = signed_val(b);
- j = float_comp(f1.fd, f2.fd);
- break;
- case FLOAT_BIG:
- if (big_to_double(bw, &f2.fd) < 0) {
- j = big_sign(b) ? 1 : -1;
- } else {
- GET_DOUBLE(aw, f1);
+ if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) {
+ // Float is within the no loss limit
+ f2.fd = signed_val(bw);
j = float_comp(f1.fd, f2.fd);
+#if ERTS_SIZEOF_ETERM == 8
+ } else if (f1.fd > (double) (MAX_SMALL + 1)) {
+ // Float is a positive bignum, i.e. bigger
+ j = 1;
+ } else if (f1.fd < (double) (MIN_SMALL - 1)) {
+ // Float is a negative bignum, i.e. smaller
+ j = -1;
+ } else { // Float is a Sint but less precise it
+ j = (Sint) f1.fd - signed_val(bw);
+ }
+#else
+ } else {
+ // If float is positive it is bigger than small
+ j = (f1.fd > 0.0) ? 1 : -1;
}
+#endif // ERTS_SIZEOF_ETERM == 8
break;
default:
j = b_tag - a_tag;
@@ -2803,9 +2869,9 @@ store_external_or_ref_in_proc_(Process *proc, Eterm ns)
return store_external_or_ref_(&hp, &MSO(proc), ns);
}
-void bin_write(int to, void *to_arg, byte* buf, int sz)
+void bin_write(int to, void *to_arg, byte* buf, size_t sz)
{
- int i;
+ size_t i;
for (i=0;i<sz;i++) {
if (IS_DIGIT(buf[i]))
@@ -2880,17 +2946,17 @@ char* Sint_to_buf(Sint n, struct Sint_buf *buf)
*/
Eterm
-buf_to_intlist(Eterm** hpp, char *buf, int len, Eterm tail)
+buf_to_intlist(Eterm** hpp, char *buf, size_t len, Eterm tail)
{
Eterm* hp = *hpp;
+ size_t i = len;
- buf += (len-1);
- while(len > 0) {
- tail = CONS(hp, make_small((byte)*buf), tail);
+ while(i != 0) {
+ --i;
+ tail = CONS(hp, make_small((Uint)(byte)buf[i]), tail);
hp += 2;
- buf--;
- len--;
}
+
*hpp = hp;
return tail;
}
@@ -3250,10 +3316,10 @@ erts_cancel_smp_ptimer(ErtsSmpPTimer *ptimer)
#endif
-static Sint trim_threshold;
-static Sint top_pad;
-static Sint mmap_threshold;
-static Sint mmap_max;
+static int trim_threshold;
+static int top_pad;
+static int mmap_threshold;
+static int mmap_max;
Uint tot_bin_allocated;
@@ -3276,8 +3342,8 @@ int
sys_alloc_opt(int opt, int value)
{
#if HAVE_MALLOPT
- Sint m_opt;
- Sint *curr_val;
+ int m_opt;
+ int *curr_val;
switch(opt) {
case SYS_ALLOC_OPT_TRIM_THRESHOLD:
@@ -3317,7 +3383,7 @@ sys_alloc_opt(int opt, int value)
}
if(mallopt(m_opt, value)) {
- *curr_val = (Sint) value;
+ *curr_val = value;
return 1;
}
@@ -3336,688 +3402,6 @@ sys_alloc_stat(SysAllocStat *sasp)
}
-#ifdef ERTS_SMP
-
-/* Local system block state */
-
-struct {
- int emergency;
- long emergency_timeout;
- erts_smp_cnd_t watchdog_cnd;
- erts_smp_tid_t watchdog_tid;
- int threads_to_block;
- int have_blocker;
- erts_smp_tid_t blocker_tid;
- int recursive_block;
- Uint32 allowed_activities;
- erts_smp_tsd_key_t blockable_key;
- erts_smp_mtx_t mtx;
- erts_smp_cnd_t cnd;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- int activity_changing;
- int checking;
-#endif
-} system_block_state;
-
-/* Global system block state */
-erts_system_block_state_t erts_system_block_state;
-
-
-static ERTS_INLINE int
-is_blockable_thread(void)
-{
- return erts_smp_tsd_get(system_block_state.blockable_key) != NULL;
-}
-
-static ERTS_INLINE int
-is_blocker(void)
-{
- return (system_block_state.have_blocker
- && erts_smp_equal_tids(system_block_state.blocker_tid,
- erts_smp_thr_self()));
-}
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
-int
-erts_lc_is_blocking(void)
-{
- int res;
- erts_smp_mtx_lock(&system_block_state.mtx);
- res = erts_smp_pending_system_block() && is_blocker();
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return res;
-}
-#endif
-
-static ERTS_INLINE void
-block_me(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg,
- int mtx_locked,
- int want_to_block,
- int update_act_changing,
- profile_sched_msg_q *psmq)
-{
- if (prepare)
- (*prepare)(arg);
-
- /* Locks might be held... */
-
- if (!mtx_locked)
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- if (erts_smp_pending_system_block() && !is_blocker()) {
- int is_blockable = is_blockable_thread();
- ASSERT(is_blockable);
-
- if (is_blockable)
- system_block_state.threads_to_block--;
-
- if (erts_system_profile_flags.scheduler && psmq) {
- ErtsSchedulerData *esdp = erts_get_scheduler_data();
- if (esdp) {
- profile_sched_msg *msg = NULL;
-
- ASSERT(psmq->n < 2);
- msg = &((psmq->msg)[psmq->n]);
- msg->scheduler_id = esdp->no;
- get_now(&(msg->Ms), &(msg->s), &(msg->us));
- msg->no_schedulers = 0;
- msg->state = am_inactive;
- psmq->n++;
- }
- }
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (update_act_changing)
- system_block_state.activity_changing--;
-#endif
-
- erts_smp_cnd_broadcast(&system_block_state.cnd);
-
- do {
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- } while (erts_smp_pending_system_block()
- && !(want_to_block && !system_block_state.have_blocker));
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (update_act_changing)
- system_block_state.activity_changing++;
-#endif
- if (erts_system_profile_flags.scheduler && psmq) {
- ErtsSchedulerData *esdp = erts_get_scheduler_data();
- if (esdp) {
- profile_sched_msg *msg = NULL;
-
- ASSERT(psmq->n < 2);
- msg = &((psmq->msg)[psmq->n]);
- msg->scheduler_id = esdp->no;
- get_now(&(msg->Ms), &(msg->s), &(msg->us));
- msg->no_schedulers = 0;
- msg->state = am_active;
- psmq->n++;
- }
- }
-
- if (is_blockable)
- system_block_state.threads_to_block++;
- }
-
- if (!mtx_locked)
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (resume)
- (*resume)(arg);
-}
-
-void
-erts_block_me(void (*prepare)(void *),
- void (*resume)(void *),
- void *arg)
-{
- profile_sched_msg_q psmq;
- psmq.n = 0;
- if (prepare)
- (*prepare)(arg);
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-#endif
-
- block_me(NULL, NULL, NULL, 0, 0, 0, &psmq);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
-
- if (resume)
- (*resume)(arg);
-}
-
-void
-erts_register_blockable_thread(void)
-{
- profile_sched_msg_q psmq;
- psmq.n = 0;
- if (!is_blockable_thread()) {
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.threads_to_block++;
- erts_smp_tsd_set(system_block_state.blockable_key,
- (void *) &erts_system_block_state);
-
- /* Someone might be waiting for us to block... */
- if (erts_smp_pending_system_block())
- block_me(NULL, NULL, NULL, 1, 0, 0, &psmq);
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
- }
-}
-
-void
-erts_unregister_blockable_thread(void)
-{
- if (is_blockable_thread()) {
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.threads_to_block--;
- ASSERT(system_block_state.threads_to_block >= 0);
- erts_smp_tsd_set(system_block_state.blockable_key, NULL);
-
- /* Someone might be waiting for us to block... */
- if (erts_smp_pending_system_block())
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- erts_smp_mtx_unlock(&system_block_state.mtx);
- }
-}
-
-void
-erts_note_activity_begin(erts_activity_t activity)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- if (erts_smp_pending_system_block()) {
- Uint32 broadcast = 0;
- switch (activity) {
- case ERTS_ACTIVITY_GC:
- broadcast = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_GC);
- break;
- case ERTS_ACTIVITY_IO:
- broadcast = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_IO);
- break;
- case ERTS_ACTIVITY_WAIT:
- broadcast = 1;
- break;
- default:
- abort();
- break;
- }
- if (broadcast)
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- }
- erts_smp_mtx_unlock(&system_block_state.mtx);
-}
-
-void
-erts_check_block(erts_activity_t old_activity,
- erts_activity_t new_activity,
- int locked,
- void (*prepare)(void *),
- void (*resume)(void *),
- void *arg)
-{
- int do_block;
- profile_sched_msg_q psmq;
-
- psmq.n = 0;
- if (!locked && prepare)
- (*prepare)(arg);
-
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- /* First check if it is ok to block... */
- if (!locked)
- do_block = 1;
- else {
- switch (old_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- do_block = 0;
- break;
- case ERTS_ACTIVITY_GC:
- do_block = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_GC);
- break;
- case ERTS_ACTIVITY_IO:
- do_block = (system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_IO);
- break;
- case ERTS_ACTIVITY_WAIT:
- /* You are not allowed to leave activity waiting
- * without supplying the possibility to block
- * unlocked.
- */
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED,
- __FILE__, __LINE__);
- do_block = 0;
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY,
- __FILE__, __LINE__);
- do_block = 0;
- break;
- }
- }
-
- if (do_block) {
- /* ... then check if it is necessary to block... */
-
- switch (new_activity) {
- case ERTS_ACTIVITY_UNDEFINED:
- do_block = 1;
- break;
- case ERTS_ACTIVITY_GC:
- do_block = !(system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_GC);
- break;
- case ERTS_ACTIVITY_IO:
- do_block = !(system_block_state.allowed_activities
- & ERTS_BS_FLG_ALLOW_IO);
- break;
- case ERTS_ACTIVITY_WAIT:
- /* No need to block if we are going to wait */
- do_block = 0;
- break;
- default:
- erts_set_activity_error(ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY,
- __FILE__, __LINE__);
- break;
- }
- }
-
- if (do_block) {
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (!locked) {
- /* Only system_block_state.mtx should be held */
- erts_lc_check_exact(&system_block_state.mtx.lc, 1);
- }
-#endif
-
- block_me(NULL, NULL, NULL, 1, 0, 1, &psmq);
-
- }
-
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
-
- if (!locked && resume)
- (*resume)(arg);
-}
-
-
-
-void
-erts_set_activity_error(erts_activity_error_t error, char *file, int line)
-{
- switch (error) {
- case ERTS_ACT_ERR_LEAVE_WAIT_UNLOCKED:
- erl_exit(1, "%s:%d: Fatal error: Leaving activity waiting without "
- "supplying the possibility to block unlocked.",
- file, line);
- break;
- case ERTS_ACT_ERR_LEAVE_UNKNOWN_ACTIVITY:
- erl_exit(1, "%s:%d: Fatal error: Leaving unknown activity.",
- file, line);
- break;
- case ERTS_ACT_ERR_ENTER_UNKNOWN_ACTIVITY:
- erl_exit(1, "%s:%d: Fatal error: Leaving unknown activity.",
- file, line);
- break;
- default:
- erl_exit(1, "%s:%d: Internal error in erts_smp_set_activity()",
- file, line);
- break;
- }
-
-}
-
-
-static ERTS_INLINE erts_aint32_t
-threads_not_under_control(void)
-{
- erts_aint32_t res = system_block_state.threads_to_block;
-
- ERTS_THR_MEMORY_BARRIER;
-
- /* Waiting is always an allowed activity... */
- res -= erts_smp_atomic32_read_nob(&erts_system_block_state.in_activity.wait);
-
- if (system_block_state.allowed_activities & ERTS_BS_FLG_ALLOW_GC)
- res -= erts_smp_atomic32_read_nob(&erts_system_block_state.in_activity.gc);
-
- if (system_block_state.allowed_activities & ERTS_BS_FLG_ALLOW_IO)
- res -= erts_smp_atomic32_read_nob(&erts_system_block_state.in_activity.io);
-
- if (res < 0) {
- ASSERT(0);
- return 0;
- }
- return res;
-}
-
-/*
- * erts_block_system() blocks all threads registered as blockable.
- * It doesn't return until either all threads have blocked (0 is returned)
- * or it has timed out (ETIMEDOUT) is returned.
- *
- * If allowed activities == 0, blocked threads will release all locks
- * before blocking.
- *
- * If allowed_activities is != 0, erts_block_system() will allow blockable
- * threads to continue executing as long as they are doing an allowed
- * activity. When they are done with the allowed activity they will block,
- * *but* they will block holding locks. Therefore, the thread calling
- * erts_block_system() must *not* try to aquire any locks that might be
- * held by blocked threads holding locks from allowed activities.
- *
- * Currently allowed_activities are:
- * * ERTS_BS_FLG_ALLOW_GC Thread continues with garbage
- * collection and blocks with
- * main process lock on current
- * process locked.
- * * ERTS_BS_FLG_ALLOW_IO Thread continues with I/O
- */
-
-void
-erts_block_system(Uint32 allowed_activities)
-{
- int do_block;
- profile_sched_msg_q psmq;
-
- psmq.n = 0;
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-#endif
-
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- do_block = erts_smp_pending_system_block();
- if (do_block
- && system_block_state.have_blocker
- && erts_smp_equal_tids(system_block_state.blocker_tid,
- erts_smp_thr_self())) {
- ASSERT(system_block_state.recursive_block >= 0);
- system_block_state.recursive_block++;
-
- /* You are not allowed to restrict allowed activites
- in a recursive block! */
- ERTS_SMP_LC_ASSERT((system_block_state.allowed_activities
- & ~allowed_activities) == 0);
- }
- else {
-
- erts_smp_atomic32_inc_nob(&erts_system_block_state.do_block);
-
- /* Someone else might be waiting for us to block... */
- if (do_block) {
- do_block_me:
- block_me(NULL, NULL, NULL, 1, 1, 0, &psmq);
- }
-
- ASSERT(!system_block_state.have_blocker);
- system_block_state.have_blocker = 1;
- system_block_state.blocker_tid = erts_smp_thr_self();
- system_block_state.allowed_activities = allowed_activities;
-
- if (is_blockable_thread())
- system_block_state.threads_to_block--;
-
- while (threads_not_under_control() && !system_block_state.emergency)
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
-
- if (system_block_state.emergency) {
- system_block_state.have_blocker = 0;
- goto do_block_me;
- }
- }
-
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0 )
- dispatch_profile_msg_q(&psmq);
-}
-
-/*
- * erts_emergency_block_system() should only be called when we are
- * about to write a crash dump...
- */
-
-int
-erts_emergency_block_system(long timeout, Uint32 allowed_activities)
-{
- int res = 0;
- long another_blocker;
-
- erts_smp_mtx_lock(&system_block_state.mtx);
-
- if (system_block_state.emergency) {
- /* Argh... */
- res = EINVAL;
- goto done;
- }
-
- another_blocker = erts_smp_pending_system_block();
- system_block_state.emergency = 1;
- erts_smp_atomic32_inc_nob(&erts_system_block_state.do_block);
-
- if (another_blocker) {
- if (is_blocker()) {
- erts_smp_atomic32_dec_nob(&erts_system_block_state.do_block);
- res = 0;
- goto done;
- }
- /* kick the other blocker */
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- while (system_block_state.have_blocker)
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- }
-
- ASSERT(!system_block_state.have_blocker);
- system_block_state.have_blocker = 1;
- system_block_state.blocker_tid = erts_smp_thr_self();
- system_block_state.allowed_activities = allowed_activities;
-
- if (is_blockable_thread())
- system_block_state.threads_to_block--;
-
- if (timeout < 0) {
- while (threads_not_under_control())
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- }
- else {
- system_block_state.emergency_timeout = timeout;
- erts_smp_cnd_signal(&system_block_state.watchdog_cnd);
-
- while (system_block_state.emergency_timeout >= 0
- && threads_not_under_control()) {
- erts_smp_cnd_wait(&system_block_state.cnd,
- &system_block_state.mtx);
- }
- }
- done:
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return res;
-}
-
-void
-erts_release_system(void)
-{
- long do_block;
- profile_sched_msg_q psmq;
-
- psmq.n = 0;
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-#endif
-
- erts_smp_mtx_lock(&system_block_state.mtx);
- ASSERT(is_blocker());
-
- ASSERT(system_block_state.recursive_block >= 0);
-
- if (system_block_state.recursive_block)
- system_block_state.recursive_block--;
- else {
- do_block = erts_smp_atomic32_dec_read_nob(&erts_system_block_state.do_block);
- system_block_state.have_blocker = 0;
- if (is_blockable_thread())
- system_block_state.threads_to_block++;
- else
- do_block = 0;
-
- /* Someone else might be waiting for us to block... */
- if (do_block)
- block_me(NULL, NULL, NULL, 1, 0, 0, &psmq);
- else
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- }
-
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_system_profile_flags.scheduler && psmq.n > 0)
- dispatch_profile_msg_q(&psmq);
-}
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
-
-void
-erts_lc_activity_change_begin(void)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.activity_changing++;
- erts_smp_mtx_unlock(&system_block_state.mtx);
-}
-
-void
-erts_lc_activity_change_end(void)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.activity_changing--;
- if (system_block_state.checking && !system_block_state.activity_changing)
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- erts_smp_mtx_unlock(&system_block_state.mtx);
-}
-
-#endif
-
-int
-erts_is_system_blocked(erts_activity_t allowed_activities)
-{
- int blkd;
-
- erts_smp_mtx_lock(&system_block_state.mtx);
- blkd = (erts_smp_pending_system_block()
- && system_block_state.have_blocker
- && erts_smp_equal_tids(system_block_state.blocker_tid,
- erts_smp_thr_self())
- && !(system_block_state.allowed_activities & ~allowed_activities));
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (blkd) {
- system_block_state.checking = 1;
- while (system_block_state.activity_changing)
- erts_smp_cnd_wait(&system_block_state.cnd, &system_block_state.mtx);
- system_block_state.checking = 0;
- blkd = !threads_not_under_control();
- }
-#endif
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return blkd;
-}
-
-static void *
-emergency_watchdog(void *unused)
-{
- erts_smp_mtx_lock(&system_block_state.mtx);
- while (1) {
- long timeout;
- while (system_block_state.emergency_timeout < 0)
- erts_smp_cnd_wait(&system_block_state.watchdog_cnd, &system_block_state.mtx);
- timeout = system_block_state.emergency_timeout;
- erts_smp_mtx_unlock(&system_block_state.mtx);
-
- if (erts_disable_tolerant_timeofday)
- erts_milli_sleep(timeout);
- else {
- SysTimeval to;
- erts_get_timeval(&to);
- to.tv_sec += timeout / 1000;
- to.tv_usec += timeout % 1000;
-
- while (1) {
- SysTimeval curr;
- erts_milli_sleep(timeout);
- erts_get_timeval(&curr);
- if (curr.tv_sec > to.tv_sec
- || (curr.tv_sec == to.tv_sec && curr.tv_usec >= to.tv_usec)) {
- break;
- }
- timeout = (to.tv_sec - curr.tv_sec)*1000;
- timeout += (to.tv_usec - curr.tv_usec)/1000;
- }
- }
-
- erts_smp_mtx_lock(&system_block_state.mtx);
- system_block_state.emergency_timeout = -1;
- erts_smp_cnd_broadcast(&system_block_state.cnd);
- }
- erts_smp_mtx_unlock(&system_block_state.mtx);
- return NULL;
-}
-
-void
-erts_system_block_init(void)
-{
- erts_smp_thr_opts_t thr_opts = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
- /* Local state... */
- system_block_state.emergency = 0;
- system_block_state.emergency_timeout = -1;
- erts_smp_cnd_init(&system_block_state.watchdog_cnd);
- system_block_state.threads_to_block = 0;
- system_block_state.have_blocker = 0;
- /* system_block_state.block_tid */
- system_block_state.recursive_block = 0;
- system_block_state.allowed_activities = 0;
- erts_smp_tsd_key_create(&system_block_state.blockable_key);
- erts_smp_mtx_init(&system_block_state.mtx, "system_block");
- erts_smp_cnd_init(&system_block_state.cnd);
-#ifdef ERTS_ENABLE_LOCK_CHECK
- system_block_state.activity_changing = 0;
- system_block_state.checking = 0;
-#endif
-
- thr_opts.suggested_stack_size = 8;
- erts_smp_thr_create(&system_block_state.watchdog_tid,
- emergency_watchdog,
- NULL,
- &thr_opts);
-
- /* Global state... */
-
- erts_smp_atomic32_init_nob(&erts_system_block_state.do_block, 0);
- erts_smp_atomic32_init_nob(&erts_system_block_state.in_activity.wait, 0);
- erts_smp_atomic32_init_nob(&erts_system_block_state.in_activity.gc, 0);
- erts_smp_atomic32_init_nob(&erts_system_block_state.in_activity.io, 0);
-
- /* Make sure blockable threads unregister when exiting... */
- erts_smp_install_exit_handler(erts_unregister_blockable_thread);
-}
-
-
-#endif /* #ifdef ERTS_SMP */
-
char *
erts_read_env(char *key)
{
@@ -4025,7 +3409,7 @@ erts_read_env(char *key)
char *value = erts_alloc(ERTS_ALC_T_TMP, value_len);
int res;
while (1) {
- res = erts_sys_getenv(key, value, &value_len);
+ res = erts_sys_getenv_raw(key, value, &value_len);
if (res <= 0)
break;
value = erts_realloc(ERTS_ALC_T_TMP, value, value_len);
@@ -4044,28 +3428,6 @@ erts_free_read_env(void *value)
erts_free(ERTS_ALC_T_TMP, value);
}
-int
-erts_write_env(char *key, char *value)
-{
- int ix, res;
- size_t key_len = sys_strlen(key), value_len = sys_strlen(value);
- char *key_value = erts_alloc_fnf(ERTS_ALC_T_TMP,
- key_len + 1 + value_len + 1);
- if (!key_value) {
- errno = ENOMEM;
- return -1;
- }
- sys_memcpy((void *) key_value, (void *) key, key_len);
- ix = key_len;
- key_value[ix++] = '=';
- sys_memcpy((void *) key_value, (void *) value, value_len);
- ix += value_len;
- key_value[ix] = '\0';
- res = erts_sys_putenv(key_value, key_len);
- erts_free(ERTS_ALC_T_TMP, key_value);
- return res;
-}
-
/*
* To be used to silence unused result warnings, but do not abuse it.
*/
@@ -4079,11 +3441,9 @@ void erts_silence_warn_unused_result(long unused)
* Handy functions when using a debugger - don't use in the code!
*/
-void upp(buf,sz)
-byte* buf;
-int sz;
+void upp(byte *buf, size_t sz)
{
- bin_write(ERTS_PRINT_STDERR,NULL,buf,sz);
+ bin_write(ERTS_PRINT_STDERR, NULL, buf, sz);
}
void pat(Eterm atom)
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 68987b3493..347247ee7b 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,6 +55,7 @@
#define FILE_READ_LINE 29
#define FILE_FDATASYNC 30
#define FILE_FADVISE 31
+#define FILE_SENDFILE 32
/* Return codes */
@@ -98,12 +99,20 @@
# include "config.h"
#endif
#include <stdlib.h>
+
+/* Need (NON)BLOCKING macros for sendfile */
+#ifndef WANT_NONBLOCKING
+#define WANT_NONBLOCKING
+#endif
+
#include "sys.h"
+
#include "erl_driver.h"
#include "erl_efile.h"
#include "erl_threads.h"
#include "zlib.h"
#include "gzio.h"
+#include "dtrace-wrapper.h"
#include <ctype.h>
#include <sys/types.h>
@@ -111,6 +120,39 @@ void erl_exit(int n, char *fmt, ...);
static ErlDrvSysInfo sys_info;
+/* For explanation of this var, see comment for same var in erl_async.c */
+static unsigned gcc_optimizer_hack = 0;
+
+#ifdef USE_VM_PROBES
+
+#define DTRACE_EFILE_BUFSIZ 128
+
+#define DTRACE_INVOKE_SETUP(op) \
+ do { DTRACE3(efile_drv_int_entry, d->sched_i1, d->sched_i2, op); } while (0)
+#define DTRACE_INVOKE_SETUP_BY_NAME(op) \
+ struct t_data *d = (struct t_data *) data ; \
+ DTRACE_INVOKE_SETUP(op)
+#define DTRACE_INVOKE_RETURN(op) \
+ do { DTRACE3(efile_drv_int_return, d->sched_i1, d->sched_i2, \
+ op); } while (0) ; gcc_optimizer_hack++ ;
+
+/* Assign human-friendlier id numbers to scheduler & I/O worker threads */
+int dt_driver_idnum = 0;
+int dt_driver_io_worker_base = 5000;
+erts_mtx_t dt_driver_mutex;
+pthread_key_t dt_driver_key;
+
+typedef struct {
+ int thread_num;
+ Uint64 tag;
+} dt_private;
+
+dt_private *get_dt_private(int);
+#else /* USE_VM_PROBES */
+#define DTRACE_INVOKE_SETUP(op) do {} while (0)
+#define DTRACE_INVOKE_SETUP_BY_NAME(op) do {} while (0)
+#define DTRACE_INVOKE_RETURN(op) do {} while (0)
+#endif /* USE_VM_PROBES */
/* #define TRACE 1 */
#ifdef TRACE
@@ -140,6 +182,22 @@ static ErlDrvSysInfo sys_info;
#define MUTEX_UNLOCK(m)
#endif
+
+/**
+ * On DARWIN sendfile can deadlock with close if called in
+ * different threads. So until Apple fixes so that sendfile
+ * is not buggy we disable usage of the async pool for
+ * DARWIN. The testcase t_sendfile_crashduring reproduces
+ * this error when using +A 10.
+ */
+#if defined(__APPLE__) && defined(__MACH__)
+#define USE_THRDS_FOR_SENDFILE 0
+#else
+#define USE_THRDS_FOR_SENDFILE (sys_info.async_threads > 0)
+#endif /* defined(__APPLE__) && defined(__MACH__) */
+
+
+
#if 0
/* Experimental, for forcing all file operations to use the same thread. */
static unsigned file_fixed_key = 1;
@@ -150,6 +208,9 @@ static ErlDrvSysInfo sys_info;
#ifdef FILENAMES_16BIT
+#ifdef USE_VM_PROBES
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
# define FILENAME_BYTELEN(Str) filename_len_16bit(Str)
# define FILENAME_COPY(To,From) filename_cpy_16bit((To),(From))
# define FILENAME_CHARSIZE 2
@@ -217,17 +278,26 @@ typedef unsigned char uchar;
static ErlDrvData file_start(ErlDrvPort port, char* command);
static int file_init(void);
static void file_stop(ErlDrvData);
-static void file_output(ErlDrvData, char* buf, int len);
-static int file_control(ErlDrvData, unsigned int command,
- char* buf, int len, char **rbuf, int rlen);
+static void file_output(ErlDrvData, char* buf, ErlDrvSizeT len);
+static ErlDrvSSizeT file_control(ErlDrvData, unsigned int command,
+ char* buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen);
static void file_timeout(ErlDrvData);
static void file_outputv(ErlDrvData, ErlIOVec*);
static void file_async_ready(ErlDrvData, ErlDrvThreadData);
static void file_flush(ErlDrvData);
+#ifdef HAVE_SENDFILE
+static void file_ready_output(ErlDrvData data, ErlDrvEvent event);
+static void file_stop_select(ErlDrvEvent event, void* _);
+#endif /* HAVE_SENDFILE */
enum e_timer {timer_idle, timer_again, timer_write};
+#ifdef HAVE_SENDFILE
+enum e_sendfile {sending, not_sending};
+static void free_sendfile(void *data);
+#endif /* HAVE_SENDFILE */
struct t_data;
@@ -242,6 +312,9 @@ typedef struct {
struct t_data *cq_head; /* Queue of incoming commands */
struct t_data *cq_tail; /* -""- */
enum e_timer timer_state;
+#ifdef HAVE_SENDFILE
+ enum e_sendfile sendfile_state;
+#endif /* HAVE_SENDFILE */
size_t read_bufsize;
ErlDrvBinary *read_binp;
size_t read_offset;
@@ -253,6 +326,10 @@ typedef struct {
ErlDrvPDL q_mtx; /* Mutex for the driver queue, known by the emulator. Also used for
mutual exclusion when accessing field(s) below. */
size_t write_buffered;
+#ifdef USE_VM_PROBES
+ int idnum; /* Unique ID # for this driver thread/desc */
+ char port_str[DTRACE_TERM_BUF_SIZE];
+#endif
} file_descriptor;
@@ -264,7 +341,11 @@ struct erl_drv_entry efile_driver_entry = {
file_stop,
file_output,
NULL,
+#ifdef HAVE_SENDFILE
+ file_ready_output,
+#else
NULL,
+#endif /* HAVE_SENDFILE */
"efile",
NULL,
NULL,
@@ -279,7 +360,13 @@ struct erl_drv_entry efile_driver_entry = {
ERL_DRV_EXTENDED_MAJOR_VERSION,
ERL_DRV_EXTENDED_MINOR_VERSION,
ERL_DRV_FLAG_USE_PORT_LOCKING,
+ NULL,
+ NULL,
+#ifdef HAVE_SENDFILE
+ file_stop_select
+#else
NULL
+#endif /* HAVE_SENDFILE */
};
@@ -340,6 +427,11 @@ struct t_data
void (*free)(void *);
int again;
int reply;
+#ifdef USE_VM_PROBES
+ int sched_i1;
+ Uint64 sched_i2;
+ char sched_utag[DTRACE_EFILE_BUFSIZ+1];
+#endif
int result_ok;
Efile_error errInfo;
int flags;
@@ -398,12 +490,20 @@ struct t_data
Sint64 length;
int advise;
} fadvise;
+#ifdef HAVE_SENDFILE
+ struct {
+ ErlDrvPort port;
+ ErlDrvPDL q_mtx;
+ int out_fd;
+ off_t offset;
+ Uint64 nbytes;
+ Uint64 written;
+ } sendfile;
+#endif /* HAVE_SENDFILE */
} c;
char b[1];
};
-
-
#define EF_ALLOC(S) driver_alloc((S))
#define EF_REALLOC(P, S) driver_realloc((P), (S))
#define EF_SAFE_ALLOC(S) ef_safe_alloc((S))
@@ -422,7 +522,7 @@ static void *ef_safe_alloc(Uint s)
static void *ef_safe_realloc(void *op, Uint s)
{
void *p = EF_REALLOC(op, s);
- if (!p) erl_exit(1, "efile drv: Can't reallocate %d bytes of memory\n", s);
+ if (!p) erl_exit(1, "efile drv: Can't reallocate %lu bytes of memory\n", (unsigned long)s);
return p;
}
@@ -432,7 +532,7 @@ static void *ef_safe_realloc(void *op, Uint s)
* ErlIOVec manipulation functions.
*/
-/* char EV_CHAR(ErlIOVec *ev, int p, int q) */
+/* char EV_CHAR_P(ErlIOVec *ev, int p, int q) */
#define EV_CHAR_P(ev, p, q) \
(((char *)(ev)->iov[(q)].iov_base) + (p))
@@ -485,7 +585,6 @@ static void *ef_safe_realloc(void *op, Uint s)
: 0)
-
#if 0
static void ev_clear(ErlIOVec *ev) {
@@ -613,7 +712,6 @@ static struct t_data *cq_deq(file_descriptor *desc) {
}
-
/*********************************************************************
* Driver entry point -> init
*/
@@ -628,6 +726,12 @@ file_init(void)
? atoi(buf)
: 0);
driver_system_info(&sys_info, sizeof(ErlDrvSysInfo));
+
+#ifdef USE_VM_PROBES
+ erts_mtx_init(&dt_driver_mutex, "efile_drv dtrace mutex");
+ pthread_key_create(&dt_driver_key, NULL);
+#endif /* USE_VM_PROBES */
+
return 0;
}
@@ -655,6 +759,9 @@ file_start(ErlDrvPort port, char* command)
desc->cq_head = NULL;
desc->cq_tail = NULL;
desc->timer_state = timer_idle;
+#ifdef HAVE_SENDFILE
+ desc->sendfile_state = not_sending;
+#endif
desc->read_bufsize = 0;
desc->read_binp = NULL;
desc->read_offset = 0;
@@ -664,6 +771,10 @@ file_start(ErlDrvPort port, char* command)
desc->write_error = 0;
MUTEX_INIT(desc->q_mtx, port); /* Refc is one, referenced by emulator now */
desc->write_buffered = 0;
+#ifdef USE_VM_PROBES
+ dtrace_drvport_str(port, desc->port_str);
+ get_dt_private(0); /* throw away return value */
+#endif /* USE_VM_PROBES */
return (ErlDrvData) desc;
}
@@ -683,8 +794,10 @@ static void do_close(int flags, SWord fd) {
static void invoke_close(void *data)
{
struct t_data *d = (struct t_data *) data;
+ DTRACE_INVOKE_SETUP(FILE_CLOSE);
d->again = 0;
do_close(d->flags, d->fd);
+ DTRACE_INVOKE_RETURN(FILE_CLOSE);
}
/*********************************************************************
@@ -762,7 +875,16 @@ static void reply_Uint_posix_error(file_descriptor *desc, Uint num,
driver_output2(desc->port, response, t-response, NULL, 0);
}
+static void reply_string_error(file_descriptor *desc, char* str) {
+ char response[256]; /* Response buffer. */
+ char* s;
+ char* t;
+ response[0] = FILE_RESP_ERROR;
+ for (s = str, t = response+1; *s; s++, t++)
+ *t = tolower(*s);
+ driver_output2(desc->port, response, t-response, NULL, 0);
+}
static int reply_error(file_descriptor *desc,
Efile_error *errInfo) /* The error codes. */
@@ -893,8 +1015,6 @@ static int reply_eof(file_descriptor *desc) {
driver_output2(desc->port, &c, 1, NULL, 0);
return 0;
}
-
-
static void invoke_name(void *data, int (*f)(Efile_error *, char *))
{
@@ -907,49 +1027,63 @@ static void invoke_name(void *data, int (*f)(Efile_error *, char *))
static void invoke_mkdir(void *data)
{
+ DTRACE_INVOKE_SETUP_BY_NAME(FILE_MKDIR);
invoke_name(data, efile_mkdir);
+ DTRACE_INVOKE_RETURN(FILE_MKDIR);
}
static void invoke_rmdir(void *data)
{
+ DTRACE_INVOKE_SETUP_BY_NAME(FILE_RMDIR);
invoke_name(data, efile_rmdir);
+ DTRACE_INVOKE_RETURN(FILE_RMDIR);
}
static void invoke_delete_file(void *data)
{
+ DTRACE_INVOKE_SETUP_BY_NAME(FILE_DELETE);
invoke_name(data, efile_delete_file);
+ DTRACE_INVOKE_RETURN(FILE_DELETE);
}
static void invoke_chdir(void *data)
{
+ DTRACE_INVOKE_SETUP_BY_NAME(FILE_CHDIR);
invoke_name(data, efile_chdir);
+ DTRACE_INVOKE_RETURN(FILE_CHDIR);
}
static void invoke_fdatasync(void *data)
{
struct t_data *d = (struct t_data *) data;
int fd = (int) d->fd;
+ DTRACE_INVOKE_SETUP(FILE_FDATASYNC);
d->again = 0;
d->result_ok = efile_fdatasync(&d->errInfo, fd);
+ DTRACE_INVOKE_RETURN(FILE_FDATASYNC);
}
static void invoke_fsync(void *data)
{
struct t_data *d = (struct t_data *) data;
int fd = (int) d->fd;
+ DTRACE_INVOKE_SETUP(FILE_FSYNC);
d->again = 0;
d->result_ok = efile_fsync(&d->errInfo, fd);
+ DTRACE_INVOKE_RETURN(FILE_FSYNC);
}
static void invoke_truncate(void *data)
{
struct t_data *d = (struct t_data *) data;
int fd = (int) d->fd;
+ DTRACE_INVOKE_SETUP(FILE_TRUNCATE);
d->again = 0;
d->result_ok = efile_truncate_file(&d->errInfo, &fd, d->flags);
+ DTRACE_INVOKE_RETURN(FILE_TRUNCATE);
}
static void invoke_read(void *data)
@@ -957,6 +1091,7 @@ static void invoke_read(void *data)
struct t_data *d = (struct t_data *) data;
int status, segment;
size_t size, read_size;
+ DTRACE_INVOKE_SETUP(FILE_READ);
segment = d->again && d->c.read.bin_size >= 2*FILE_SEGMENT_READ;
if (segment) {
@@ -991,6 +1126,7 @@ static void invoke_read(void *data)
} else {
d->again = 0;
}
+ DTRACE_INVOKE_RETURN(FILE_READ);
}
static void free_read(void *data)
@@ -1007,13 +1143,14 @@ static void invoke_read_line(void *data)
int status;
size_t read_size;
int local_loop = (d->again == 0);
+ DTRACE_INVOKE_SETUP(FILE_READ_LINE);
do {
size_t size = (d->c.read_line.binp)->orig_size -
d->c.read_line.read_offset - d->c.read_line.read_size;
if (size == 0) {
/* Need more place */
- size_t need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ?
+ ErlDrvSizeT need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ?
d->c.read_line.read_size + DEFAULT_LINEBUF_SIZE : DEFAULT_LINEBUF_SIZE;
ErlDrvBinary *newbin = driver_alloc_binary(need);
if (newbin == NULL) {
@@ -1098,6 +1235,7 @@ static void invoke_read_line(void *data)
break;
}
} while (local_loop);
+ DTRACE_INVOKE_RETURN(FILE_READ_LINE);
}
static void free_read_line(void *data)
@@ -1113,6 +1251,7 @@ static void invoke_read_file(void *data)
struct t_data *d = (struct t_data *) data;
size_t read_size;
int chop;
+ DTRACE_INVOKE_SETUP(FILE_READ_FILE);
if (! d->c.read_file.binp) { /* First invocation only */
int fd;
@@ -1149,12 +1288,14 @@ static void invoke_read_file(void *data)
&read_size);
if (d->result_ok) {
d->c.read_file.offset += read_size;
- if (chop) return; /* again */
+ if (chop) goto chop_done; /* again */
}
close:
efile_closefile((int) d->fd);
done:
d->again = 0;
+ chop_done:
+ DTRACE_INVOKE_RETURN(FILE_READ_FILE);
}
static void free_read_file(void *data)
@@ -1174,6 +1315,7 @@ static void invoke_preadv(void *data)
ErlIOVec *ev = &c->eiov;
size_t bytes_read_so_far = 0;
unsigned char *p = (unsigned char *)ev->iov[0].iov_base + 4+4+8*c->cnt;
+ DTRACE_INVOKE_SETUP(FILE_PREADV);
while (c->cnt < c->n) {
size_t read_size = ev->iov[1 + c->cnt].iov_len - c->size;
@@ -1195,7 +1337,7 @@ static void invoke_preadv(void *data)
bytes_read_so_far += bytes_read;
if (chop && bytes_read == read_size) {
c->size += bytes_read;
- return;
+ goto done;
}
ASSERT(bytes_read <= read_size);
ev->iov[1 + c->cnt].iov_len = bytes_read + c->size;
@@ -1206,7 +1348,7 @@ static void invoke_preadv(void *data)
if (d->again
&& bytes_read_so_far >= FILE_SEGMENT_READ
&& c->cnt < c->n) {
- return;
+ goto done;
}
} else {
/* In case of a read error, ev->size will not be correct,
@@ -1217,6 +1359,8 @@ static void invoke_preadv(void *data)
}
}
d->again = 0;
+ done:
+ DTRACE_INVOKE_RETURN(FILE_PREADV);
}
static void free_preadv(void *data) {
@@ -1238,6 +1382,7 @@ static void invoke_ipread(void *data)
size_t bytes_read = 0;
char buf[2*sizeof(Uint32)];
Uint32 offset, size;
+ DTRACE_INVOKE_SETUP(FILE_IPREAD);
/* Read indirection header */
if (! efile_pread(&d->errInfo, (int) d->fd, c->offsets[0],
@@ -1276,14 +1421,17 @@ static void invoke_ipread(void *data)
/* Read data block */
d->invoke = invoke_preadv;
invoke_preadv(data);
+ DTRACE_INVOKE_RETURN(FILE_IPREAD);
return;
error:
d->result_ok = 0;
d->again = 0;
+ DTRACE_INVOKE_RETURN(FILE_IPREAD);
return;
done:
d->result_ok = !0;
d->again = 0;
+ DTRACE_INVOKE_RETURN(FILE_IPREAD);
}
/* invoke_writev and invoke_pwritev are the only thread functions that
@@ -1306,6 +1454,7 @@ static void invoke_writev(void *data) {
size_t size;
size_t p;
int segment;
+ DTRACE_INVOKE_SETUP(FILE_WRITE);
segment = d->again && d->c.writev.size >= 2*FILE_SEGMENT_WRITE;
if (segment) {
@@ -1314,7 +1463,11 @@ static void invoke_writev(void *data) {
size = d->c.writev.size;
}
- /* Copy the io vector to avoid locking the port que while writing */
+ /* Copy the io vector to avoid locking the port que while writing,
+ * also, both we and efile_writev might/will change the SysIOVec
+ * when segmenting or due to partial write and we do not want to
+ * tamper with the actual queue that we get from driver_peekq
+ */
MUTEX_LOCK(d->c.writev.q_mtx); /* Lock before accessing the port queue */
iov0 = driver_peekq(d->c.writev.port, &iovlen);
@@ -1353,7 +1506,7 @@ static void invoke_writev(void *data) {
} else {
d->result_ok = efile_writev(&d->errInfo,
d->flags, (int) d->fd,
- iov, iovcnt, size);
+ iov, iovcnt);
}
} else if (iovlen == 0) {
d->result_ok = 1;
@@ -1375,6 +1528,7 @@ static void invoke_writev(void *data) {
TRACE_F(("w%lu", (unsigned long)size));
}
+ DTRACE_INVOKE_RETURN(FILE_WRITE);
}
static void free_writev(void *data) {
@@ -1388,34 +1542,40 @@ static void free_writev(void *data) {
static void invoke_pwd(void *data)
{
struct t_data *d = (struct t_data *) data;
+ DTRACE_INVOKE_SETUP(FILE_PWD);
d->again = 0;
d->result_ok = efile_getdcwd(&d->errInfo,d->drive, d->b+1,
RESBUFSIZE-1);
+ DTRACE_INVOKE_RETURN(FILE_PWD);
}
static void invoke_readlink(void *data)
{
struct t_data *d = (struct t_data *) data;
char resbuf[RESBUFSIZE]; /* Result buffer. */
+ DTRACE_INVOKE_SETUP(FILE_READLINK);
d->again = 0;
d->result_ok = efile_readlink(&d->errInfo, d->b, resbuf+1,
RESBUFSIZE-1);
if (d->result_ok != 0)
FILENAME_COPY((char *) d->b + 1, resbuf+1);
+ DTRACE_INVOKE_RETURN(FILE_READLINK);
}
static void invoke_altname(void *data)
{
struct t_data *d = (struct t_data *) data;
char resbuf[RESBUFSIZE]; /* Result buffer. */
+ DTRACE_INVOKE_SETUP(FILE_ALTNAME);
d->again = 0;
d->result_ok = efile_altname(&d->errInfo, d->b, resbuf+1,
RESBUFSIZE-1);
if (d->result_ok != 0)
FILENAME_COPY((char *) d->b + 1, resbuf+1);
+ DTRACE_INVOKE_RETURN(FILE_ALTNAME);
}
static void invoke_pwritev(void *data) {
@@ -1428,6 +1588,7 @@ static void invoke_pwritev(void *data) {
size_t p;
int segment;
size_t size, write_size;
+ DTRACE_INVOKE_SETUP(FILE_PWRITEV);
segment = d->again && c->size >= 2*FILE_SEGMENT_WRITE;
if (segment) {
@@ -1507,6 +1668,7 @@ static void invoke_pwritev(void *data) {
}
done:
EF_FREE(iov); /* Free our copy of the vector, nothing to restore */
+ DTRACE_INVOKE_RETURN(FILE_PWRITEV);
}
static void free_pwritev(void *data) {
@@ -1522,9 +1684,14 @@ static void invoke_flstat(void *data)
{
struct t_data *d = (struct t_data *) data;
+ DTRACE3(efile_drv_int_entry, d->sched_i1, d->sched_i2,
+ d->command == FILE_LSTAT ? FILE_LSTAT : FILE_FSTAT);
d->again = 0;
d->result_ok = efile_fileinfo(&d->errInfo, &d->info,
d->b, d->command == FILE_LSTAT);
+ DTRACE3(efile_drv_int_entry, d->sched_i1, d->sched_i2,
+ d->command == FILE_LSTAT ? FILE_LSTAT : FILE_FSTAT);
+ gcc_optimizer_hack++;
}
static void invoke_link(void *data)
@@ -1532,10 +1699,12 @@ static void invoke_link(void *data)
struct t_data *d = (struct t_data *) data;
char *name = d->b;
char *new_name;
+ DTRACE_INVOKE_SETUP(FILE_LINK);
d->again = 0;
new_name = name+FILENAME_BYTELEN(name)+FILENAME_CHARSIZE;
d->result_ok = efile_link(&d->errInfo, name, new_name);
+ DTRACE_INVOKE_RETURN(FILE_LINK);
}
static void invoke_symlink(void *data)
@@ -1543,10 +1712,12 @@ static void invoke_symlink(void *data)
struct t_data *d = (struct t_data *) data;
char *name = d->b;
char *new_name;
+ DTRACE_INVOKE_SETUP(FILE_SYMLINK);
d->again = 0;
new_name = name+FILENAME_BYTELEN(name)+FILENAME_CHARSIZE;
d->result_ok = efile_symlink(&d->errInfo, name, new_name);
+ DTRACE_INVOKE_RETURN(FILE_SYMLINK);
}
static void invoke_rename(void *data)
@@ -1554,24 +1725,29 @@ static void invoke_rename(void *data)
struct t_data *d = (struct t_data *) data;
char *name = d->b;
char *new_name;
+ DTRACE_INVOKE_SETUP(FILE_RENAME);
d->again = 0;
new_name = name+FILENAME_BYTELEN(name)+FILENAME_CHARSIZE;
d->result_ok = efile_rename(&d->errInfo, name, new_name);
+ DTRACE_INVOKE_RETURN(FILE_RENAME);
}
static void invoke_write_info(void *data)
{
struct t_data *d = (struct t_data *) data;
+ DTRACE_INVOKE_SETUP(FILE_WRITE_INFO);
d->again = 0;
d->result_ok = efile_write_info(&d->errInfo, &d->info, d->b);
+ DTRACE_INVOKE_RETURN(FILE_WRITE_INFO);
}
static void invoke_lseek(void *data)
{
struct t_data *d = (struct t_data *) data;
int status;
+ DTRACE_INVOKE_SETUP(FILE_LSEEK);
d->again = 0;
if (d->flags & EFILE_COMPRESSED) {
@@ -1596,6 +1772,7 @@ static void invoke_lseek(void *data)
&d->c.lseek.location);
}
d->result_ok = status;
+ DTRACE_INVOKE_RETURN(FILE_LSEEK);
}
static void invoke_readdir(void *data)
@@ -1606,6 +1783,7 @@ static void invoke_readdir(void *data)
size_t n = 0, total = 0;
struct t_readdir_buf *b = NULL;
int res = 0;
+ DTRACE_INVOKE_SETUP(FILE_READDIR);
d->again = 0;
d->errInfo.posix_errno = 0;
@@ -1641,13 +1819,14 @@ static void invoke_readdir(void *data)
} while(res);
d->result_ok = (d->errInfo.posix_errno == 0);
+ DTRACE_INVOKE_RETURN(FILE_READDIR);
}
static void invoke_open(void *data)
{
struct t_data *d = (struct t_data *) data;
-
int status = 1; /* Status of open call. */
+ DTRACE_INVOKE_SETUP(FILE_OPEN);
d->again = 0;
if ((d->flags & EFILE_COMPRESSED) == 0) {
@@ -1680,6 +1859,7 @@ static void invoke_open(void *data)
}
d->result_ok = status;
+ DTRACE_INVOKE_RETURN(FILE_OPEN);
}
static void invoke_fadvise(void *data)
@@ -1689,15 +1869,92 @@ static void invoke_fadvise(void *data)
off_t offset = (off_t) d->c.fadvise.offset;
off_t length = (off_t) d->c.fadvise.length;
int advise = (int) d->c.fadvise.advise;
+ DTRACE_INVOKE_SETUP(FILE_FADVISE);
d->again = 0;
d->result_ok = efile_fadvise(&d->errInfo, fd, offset, length, advise);
+ DTRACE_INVOKE_RETURN(FILE_FADVISE);
+}
+
+#ifdef HAVE_SENDFILE
+static void invoke_sendfile(void *data)
+{
+ struct t_data *d = (struct t_data *)data;
+ int fd = d->fd;
+ int out_fd = (int)d->c.sendfile.out_fd;
+ Uint64 nbytes = d->c.sendfile.nbytes;
+ int result = 0;
+ d->again = 0;
+
+ result = efile_sendfile(&d->errInfo, fd, out_fd, &d->c.sendfile.offset, &nbytes, NULL);
+
+ d->c.sendfile.written += nbytes;
+
+ if (result == 1 || (result == 0 && USE_THRDS_FOR_SENDFILE)) {
+ d->result_ok = 0;
+ } else if (result == 0 && (d->errInfo.posix_errno == EAGAIN
+ || d->errInfo.posix_errno == EINTR)) {
+ if ((d->c.sendfile.nbytes - nbytes) != 0) {
+ d->result_ok = 1;
+ if (d->c.sendfile.nbytes != 0)
+ d->c.sendfile.nbytes -= nbytes;
+ } else
+ d->result_ok = 0;
+ } else {
+ d->result_ok = -1;
+ }
+}
+
+static void free_sendfile(void *data) {
+ struct t_data *d = (struct t_data *)data;
+ if (USE_THRDS_FOR_SENDFILE) {
+ SET_NONBLOCKING(d->c.sendfile.out_fd);
+ } else {
+ MUTEX_LOCK(d->c.sendfile.q_mtx);
+ driver_deq(d->c.sendfile.port,1);
+ MUTEX_UNLOCK(d->c.sendfile.q_mtx);
+ driver_select(d->c.sendfile.port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, ERL_DRV_USE_NO_CALLBACK|ERL_DRV_WRITE, 0);
+ }
+ EF_FREE(data);
+}
+
+static void file_ready_output(ErlDrvData data, ErlDrvEvent event)
+{
+ file_descriptor* fd = (file_descriptor*) data;
+
+ switch (fd->d->command) {
+ case FILE_SENDFILE:
+ driver_select(fd->d->c.sendfile.port, event,
+ (int)ERL_DRV_WRITE,(int) 0);
+ invoke_sendfile((void *)fd->d);
+ file_async_ready(data, (ErlDrvThreadData)fd->d);
+ break;
+ default:
+ break;
+ }
}
+static void file_stop_select(ErlDrvEvent event, void* _)
+{
+
+}
+
+static int flush_sendfile(file_descriptor *desc,void *_) {
+ if (desc->sendfile_state == sending) {
+ desc->d->result_ok = -1;
+ desc->d->errInfo.posix_errno = ECONNABORTED;
+ file_async_ready((ErlDrvData)desc,(ErlDrvThreadData)desc->d);
+ }
+ return 1;
+}
+#endif /* HAVE_SENDFILE */
+
+
static void free_readdir(void *data)
{
struct t_data *d = (struct t_data *) data;
struct t_readdir_buf *b1 = d->c.read_dir.first_buf;
+
while (b1) {
struct t_readdir_buf *b2 = b1;
b1 = b1->next;
@@ -1755,6 +2012,10 @@ static void cq_execute(file_descriptor *desc) {
register void *void_ptr; /* Soft cast variable */
if (desc->timer_state == timer_again)
return;
+#ifdef HAVE_SENDFILE
+ if (desc->sendfile_state == sending)
+ return;
+#endif
if (! (d = cq_deq(desc)))
return;
TRACE_F(("x%i", (int) d->command));
@@ -1762,12 +2023,16 @@ static void cq_execute(file_descriptor *desc) {
DRIVER_ASYNC(d->level, desc, d->invoke, void_ptr=d, d->free);
}
-static int async_write(file_descriptor *desc, int *errp,
- int reply, Uint32 reply_size) {
+static struct t_data *async_write(file_descriptor *desc, int *errp,
+ int reply, Uint32 reply_size
+#ifdef USE_VM_PROBES
+ ,Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3
+#endif
+) {
struct t_data *d;
if (! (d = EF_ALLOC(sizeof(struct t_data) - 1))) {
if (errp) *errp = ENOMEM;
- return -1;
+ return NULL;
}
TRACE_F(("w%lu", (unsigned long)desc->write_buffered));
d->command = FILE_WRITE;
@@ -1776,6 +2041,13 @@ static int async_write(file_descriptor *desc, int *errp,
d->c.writev.port = desc->port;
d->c.writev.q_mtx = desc->q_mtx;
d->c.writev.size = desc->write_buffered;
+#ifdef USE_VM_PROBES
+ if (dt_i1 != NULL) {
+ *dt_i1 = d->fd;
+ *dt_i2 = d->flags;
+ *dt_i3 = d->c.writev.size;
+ }
+#endif
d->reply = reply;
d->c.writev.free_size = 0;
d->c.writev.reply_size = reply_size;
@@ -1784,18 +2056,49 @@ static int async_write(file_descriptor *desc, int *errp,
d->level = 1;
cq_enq(desc, d);
desc->write_buffered = 0;
- return 0;
+ return d;
}
-static int flush_write(file_descriptor *desc, int *errp) {
- int result;
+static int flush_write(file_descriptor *desc, int *errp
+#ifdef USE_VM_PROBES
+ , dt_private *dt_priv, char *dt_utag
+#endif
+) {
+ int result = 0;
+#ifdef USE_VM_PROBES
+ Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
+#endif
+ struct t_data *d = NULL;
+
MUTEX_LOCK(desc->q_mtx);
if (desc->write_buffered > 0) {
- result = async_write(desc, errp, 0, 0);
- } else {
- result = 0;
+ if ((d = async_write(desc, errp, 0, 0
+#ifdef USE_VM_PROBES
+ ,&dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
+ result = -1;
+ }
}
MUTEX_UNLOCK(desc->q_mtx);
+#ifdef USE_VM_PROBES
+ if (d != NULL) {
+ d->sched_i1 = dt_priv->thread_num;
+ d->sched_i2 = dt_priv->tag;
+ d->sched_utag[0] = '\0';
+ if (dt_utag != NULL) {
+ if (dt_utag[0] == '\0') {
+ dt_utag = NULL;
+ } else {
+ strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1);
+ d->sched_utag[sizeof(d->sched_utag) - 1] = '\0';
+ }
+ }
+ DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++,
+ dt_utag, FILE_WRITE,
+ NULL, NULL, dt_i1, dt_i2, dt_i3, 0, desc->port_str);
+ }
+#endif /* USE_VM_PROBES */
return result;
}
@@ -1808,9 +2111,17 @@ static int check_write_error(file_descriptor *desc, int *errp) {
return 0;
}
-static int flush_write_check_error(file_descriptor *desc, int *errp) {
+static int flush_write_check_error(file_descriptor *desc, int *errp
+#ifdef USE_VM_PROBES
+ , dt_private *dt_priv, char *dt_utag
+#endif
+ ) {
int r;
- if ( (r = flush_write(desc, errp)) != 0) {
+ if ( (r = flush_write(desc, errp
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ )) != 0) {
check_write_error(desc, NULL);
return r;
} else {
@@ -1818,12 +2129,16 @@ static int flush_write_check_error(file_descriptor *desc, int *errp) {
}
}
-static int async_lseek(file_descriptor *desc, int *errp, int reply,
- Sint64 offset, int origin) {
+static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply,
+ Sint64 offset, int origin
+#ifdef USE_VM_PROBES
+ , Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3
+#endif
+ ) {
struct t_data *d;
if (! (d = EF_ALLOC(sizeof(struct t_data)))) {
*errp = ENOMEM;
- return -1;
+ return NULL;
}
d->flags = desc->flags;
d->fd = desc->fd;
@@ -1831,11 +2146,18 @@ static int async_lseek(file_descriptor *desc, int *errp, int reply,
d->reply = reply;
d->c.lseek.offset = offset;
d->c.lseek.origin = origin;
+#ifdef USE_VM_PROBES
+ if (dt_i1 != NULL) {
+ *dt_i1 = d->fd;
+ *dt_i2 = d->c.lseek.offset;
+ *dt_i3 = d->c.lseek.origin;
+ }
+#endif
d->invoke = invoke_lseek;
d->free = free_data;
d->level = 1;
cq_enq(desc, d);
- return 0;
+ return d;
}
static void flush_read(file_descriptor *desc) {
@@ -1847,18 +2169,45 @@ static void flush_read(file_descriptor *desc) {
}
}
-static int lseek_flush_read(file_descriptor *desc, int *errp) {
+static int lseek_flush_read(file_descriptor *desc, int *errp
+#ifdef USE_VM_PROBES
+ ,dt_private *dt_priv, char *dt_utag
+#endif
+ ) {
int r = 0;
size_t read_size = desc->read_size;
+#ifdef USE_VM_PROBES
+ Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
+#endif
+ struct t_data *d;
+
+ flush_read(desc);
if (read_size != 0) {
- flush_read(desc);
- if ((r = async_lseek(desc, errp, 0,
- -((ssize_t)read_size), EFILE_SEEK_CUR))
- < 0) {
- return r;
- }
- } else {
- flush_read(desc);
+ if ((d = async_lseek(desc, errp, 0,
+ -((ssize_t)read_size), EFILE_SEEK_CUR
+#ifdef USE_VM_PROBES
+ , &dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
+ r = -1;
+ } else {
+#ifdef USE_VM_PROBES
+ d->sched_i1 = dt_priv->thread_num;
+ d->sched_i2 = dt_priv->tag;
+ d->sched_utag[0] = '\0';
+ if (dt_utag != NULL) {
+ if (dt_utag[0] == '\0') {
+ dt_utag = NULL;
+ } else {
+ strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1);
+ d->sched_utag[sizeof(d->sched_utag) - 1] = '\0';
+ }
+ }
+ DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++,
+ dt_utag, FILE_LSEEK,
+ NULL, NULL, dt_i1, dt_i2, dt_i3, 0, desc->port_str);
+#endif /* USE_VM_PROBES */
+ }
}
return r;
}
@@ -1875,11 +2224,23 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
struct t_data *d = (struct t_data *) data;
char header[5]; /* result code + count */
char resbuf[RESBUFSIZE]; /* Result buffer. */
-
+#ifdef USE_VM_PROBES
+ int sched_i1 = d->sched_i1, sched_i2 = d->sched_i2, command = d->command,
+ result_ok = d->result_ok,
+ posix_errno = d->result_ok ? 0 : d->errInfo.posix_errno;
+ DTRACE_CHARBUF(sched_utag, DTRACE_EFILE_BUFSIZ+1);
+
+ sched_utag[0] = '\0';
+ if (DTRACE_ENABLED(efile_drv_return)) {
+ strncpy(sched_utag, d->sched_utag, DTRACE_EFILE_BUFSIZ);
+ sched_utag[DTRACE_EFILE_BUFSIZ] = '\0';
+ }
+#endif /* USE_VM_PROBES */
TRACE_C('r');
if (try_again(desc, d)) {
+ /* DTRACE TODO: what kind of probe makes sense here? */
return;
}
@@ -2021,24 +2382,25 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
if (d->result_ok) {
resbuf[0] = FILE_RESP_INFO;
- put_int32(d->info.size_high, &resbuf[1 + (0 * 4)]);
- put_int32(d->info.size_low, &resbuf[1 + (1 * 4)]);
- put_int32(d->info.type, &resbuf[1 + (2 * 4)]);
-
- PUT_TIME(d->info.accessTime, resbuf + 1 + 3*4);
- PUT_TIME(d->info.modifyTime, resbuf + 1 + 9*4);
- PUT_TIME(d->info.cTime, resbuf + 1 + 15*4);
-
- put_int32(d->info.mode, &resbuf[1 + (21 * 4)]);
- put_int32(d->info.links, &resbuf[1 + (22 * 4)]);
- put_int32(d->info.major_device, &resbuf[1 + (23 * 4)]);
- put_int32(d->info.minor_device, &resbuf[1 + (24 * 4)]);
- put_int32(d->info.inode, &resbuf[1 + (25 * 4)]);
- put_int32(d->info.uid, &resbuf[1 + (26 * 4)]);
- put_int32(d->info.gid, &resbuf[1 + (27 * 4)]);
- put_int32(d->info.access, &resbuf[1 + (28 * 4)]);
-
-#define RESULT_SIZE (1 + (29 * 4))
+ put_int32(d->info.size_high, &resbuf[1 + ( 0 * 4)]);
+ put_int32(d->info.size_low, &resbuf[1 + ( 1 * 4)]);
+ put_int32(d->info.type, &resbuf[1 + ( 2 * 4)]);
+
+ /* Note 64 bit indexing in resbuf here */
+ put_int64(d->info.accessTime, &resbuf[1 + ( 3 * 4)]);
+ put_int64(d->info.modifyTime, &resbuf[1 + ( 5 * 4)]);
+ put_int64(d->info.cTime, &resbuf[1 + ( 7 * 4)]);
+
+ put_int32(d->info.mode, &resbuf[1 + ( 9 * 4)]);
+ put_int32(d->info.links, &resbuf[1 + (10 * 4)]);
+ put_int32(d->info.major_device, &resbuf[1 + (11 * 4)]);
+ put_int32(d->info.minor_device, &resbuf[1 + (12 * 4)]);
+ put_int32(d->info.inode, &resbuf[1 + (13 * 4)]);
+ put_int32(d->info.uid, &resbuf[1 + (14 * 4)]);
+ put_int32(d->info.gid, &resbuf[1 + (15 * 4)]);
+ put_int32(d->info.access, &resbuf[1 + (16 * 4)]);
+
+#define RESULT_SIZE (1 + (17 * 4))
TRACE_C('R');
driver_output2(desc->port, resbuf, RESULT_SIZE, NULL, 0);
#undef RESULT_SIZE
@@ -2076,6 +2438,9 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
if (d->reply) {
TRACE_C('K');
reply_ok(desc);
+#ifdef USE_VM_PROBES
+ result_ok = 1;
+#endif
}
free_data(data);
break;
@@ -2105,9 +2470,34 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
}
free_preadv(data);
break;
+#ifdef HAVE_SENDFILE
+ case FILE_SENDFILE:
+ if (d->result_ok == -1) {
+ if (d->errInfo.posix_errno == ECONNRESET ||
+ d->errInfo.posix_errno == ENOTCONN ||
+ d->errInfo.posix_errno == EPIPE)
+ reply_string_error(desc,"closed");
+ else
+ reply_error(desc, &d->errInfo);
+ desc->sendfile_state = not_sending;
+ free_sendfile(data);
+ } else if (d->result_ok == 0) {
+ reply_Sint64(desc, d->c.sendfile.written);
+ desc->sendfile_state = not_sending;
+ free_sendfile(data);
+ } else if (d->result_ok == 1) { // If we are using select to send the rest of the data
+ desc->sendfile_state = sending;
+ desc->d = d;
+ driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd,
+ ERL_DRV_USE_NO_CALLBACK|ERL_DRV_WRITE, 1);
+ }
+ break;
+#endif
default:
abort();
}
+ DTRACE6(efile_drv_return, sched_i1, sched_i2, sched_utag,
+ command, result_ok, posix_errno);
if (desc->write_buffered != 0 && desc->timer_state == timer_idle) {
desc->timer_state = timer_write;
driver_set_timer(desc->port, desc->write_delay);
@@ -2120,7 +2510,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
* Driver entry point -> output
*/
static void
-file_output(ErlDrvData e, char* buf, int count)
+file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
{
file_descriptor* desc = (file_descriptor*)e;
Efile_error errInfo; /* The error codes for the last operation. */
@@ -2130,7 +2520,15 @@ file_output(ErlDrvData e, char* buf, int count)
char* name; /* Points to the filename in buf. */
int command;
struct t_data *d = NULL;
-
+#ifdef USE_VM_PROBES
+ char *dt_utag = NULL;
+ char *dt_s1 = NULL, *dt_s2 = NULL;
+ Sint64 dt_i1 = 0;
+ Sint64 dt_i2 = 0;
+ Sint64 dt_i3 = 0;
+ Sint64 dt_i4 = 0;
+ dt_private *dt_priv = get_dt_private(0);
+#endif /* USE_VM_PROBES */
TRACE_C('o');
@@ -2145,6 +2543,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_mkdir;
d->free = free_data;
@@ -2156,6 +2558,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_rmdir;
d->free = free_data;
@@ -2167,6 +2573,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_delete_file;
d->free = free_data;
@@ -2184,6 +2594,11 @@ file_output(ErlDrvData e, char* buf, int count)
FILENAME_COPY(d->b, name);
FILENAME_COPY(d->b + namelen, new_name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_s2 = d->b + namelen;
+ dt_utag = buf + namelen + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->flags = desc->flags;
d->fd = fd;
d->command = command;
@@ -2197,6 +2612,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_chdir;
d->free = free_data;
@@ -2208,6 +2627,9 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1);
d->drive = *(uchar*)buf;
+#ifdef USE_VM_PROBES
+ dt_utag = buf + 1;
+#endif
d->command = command;
d->invoke = invoke_pwd;
d->free = free_data;
@@ -2223,6 +2645,10 @@ file_output(ErlDrvData e, char* buf, int count)
FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->dir_handle = NULL;
d->command = command;
d->invoke = invoke_readdir;
@@ -2247,6 +2673,10 @@ file_output(ErlDrvData e, char* buf, int count)
dir_handle = NULL;
resbuf[0] = FILE_RESP_LFNAME;
+#ifdef USE_VM_PROBES
+ dt_s1 = name;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
/* Fill the buffer with multiple directory listings before sending it to the
* receiving process. READDIR_CHUNKS is minimum number of files sent to the
* receiver.
@@ -2280,6 +2710,17 @@ file_output(ErlDrvData e, char* buf, int count)
reply_error(desc, &errInfo);
return;
}
+#ifdef USE_VM_PROBES
+ if (dt_utag != NULL && dt_utag[0] == '\0') {
+ dt_utag = NULL;
+ }
+
+ DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag,
+ dt_utag, command, name, dt_s2,
+ dt_i1, dt_i2, dt_i3, dt_i4, desc->port_str);
+ DTRACE6(efile_drv_return, dt_priv->thread_num, dt_priv->tag++,
+ dt_utag, command, 1, 0);
+#endif
TRACE_C('R');
driver_output2(desc->port, resbuf, 1, NULL, 0);
return;
@@ -2292,6 +2733,11 @@ file_output(ErlDrvData e, char* buf, int count)
d->flags = get_int32((uchar*)buf);
name = buf+4;
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_i1 = d->flags;
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_open;
d->free = free_data;
@@ -2304,6 +2750,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data));
d->fd = fd;
+#ifdef USE_VM_PROBES
+ dt_utag = name;
+ dt_i1 = fd;
+#endif
d->command = command;
d->invoke = invoke_fdatasync;
d->free = free_data;
@@ -2316,6 +2766,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data));
d->fd = fd;
+#ifdef USE_VM_PROBES
+ dt_utag = name;
+ dt_i1 = fd;
+#endif
d->command = command;
d->invoke = invoke_fsync;
d->free = free_data;
@@ -2332,6 +2786,14 @@ file_output(ErlDrvData e, char* buf, int count)
FILENAME_COPY(d->b, name);
d->fd = fd;
+#ifdef USE_VM_PROBES
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+ if (command == FILE_LSTAT) {
+ dt_s1 = d->b;
+ } else {
+ dt_i1 = fd;
+ }
+#endif
d->command = command;
d->invoke = invoke_flstat;
d->free = free_data;
@@ -2345,6 +2807,11 @@ file_output(ErlDrvData e, char* buf, int count)
d->flags = desc->flags;
d->fd = fd;
+#ifdef USE_VM_PROBES
+ dt_utag = name;
+ dt_i1 = fd;
+ dt_i2 = d->flags;
+#endif
d->command = command;
d->invoke = invoke_truncate;
d->free = free_data;
@@ -2355,15 +2822,23 @@ file_output(ErlDrvData e, char* buf, int count)
case FILE_WRITE_INFO:
{
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1
- + FILENAME_BYTELEN(buf+21*4) + FILENAME_CHARSIZE);
+ + FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE);
- d->info.mode = get_int32(buf + 0 * 4);
- d->info.uid = get_int32(buf + 1 * 4);
- d->info.gid = get_int32(buf + 2 * 4);
- GET_TIME(d->info.accessTime, buf + 3 * 4);
- GET_TIME(d->info.modifyTime, buf + 9 * 4);
- GET_TIME(d->info.cTime, buf + 15 * 4);
- FILENAME_COPY(d->b, buf+21*4);
+ d->info.mode = get_int32(buf + 0 * 4);
+ d->info.uid = get_int32(buf + 1 * 4);
+ d->info.gid = get_int32(buf + 2 * 4);
+ d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4));
+ d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4));
+ d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4));
+
+ FILENAME_COPY(d->b, buf + 9*4);
+#ifdef USE_VM_PROBES
+ dt_i1 = d->info.mode;
+ dt_i2 = d->info.uid;
+ dt_i3 = d->info.gid;
+ dt_s1 = d->b;
+ dt_utag = buf + 9 * 4 + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_write_info;
d->free = free_data;
@@ -2376,6 +2851,10 @@ file_output(ErlDrvData e, char* buf, int count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_readlink;
d->free = free_data;
@@ -2387,6 +2866,10 @@ file_output(ErlDrvData e, char* buf, int count)
{
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1);
FILENAME_COPY(d->b, name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_altname;
d->free = free_data;
@@ -2407,6 +2890,11 @@ file_output(ErlDrvData e, char* buf, int count)
FILENAME_COPY(d->b, name);
FILENAME_COPY(d->b + namelen, new_name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_s2 = d->b + namelen;
+ dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE;
+#endif
d->flags = desc->flags;
d->fd = fd;
d->command = command;
@@ -2428,6 +2916,11 @@ file_output(ErlDrvData e, char* buf, int count)
FILENAME_COPY(d->b, name);
FILENAME_COPY(d->b + namelen, new_name);
+#ifdef USE_VM_PROBES
+ dt_s1 = d->b;
+ dt_s2 = d->b + namelen;
+ dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE;
+#endif
d->flags = desc->flags;
d->fd = fd;
d->command = command;
@@ -2449,6 +2942,13 @@ file_output(ErlDrvData e, char* buf, int count)
d->c.fadvise.offset = get_int64((uchar*) buf);
d->c.fadvise.length = get_int64(((uchar*) buf) + sizeof(Sint64));
d->c.fadvise.advise = get_int32(((uchar*) buf) + 2 * sizeof(Sint64));
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->c.fadvise.offset;
+ dt_i3 = d->c.fadvise.length;
+ dt_i4 = d->c.fadvise.advise;
+ dt_utag = buf + 3 * sizeof(Sint64);
+#endif
goto done;
}
@@ -2462,6 +2962,22 @@ file_output(ErlDrvData e, char* buf, int count)
done:
if (d) {
+#ifdef USE_VM_PROBES
+ d->sched_i1 = dt_priv->thread_num;
+ d->sched_i2 = dt_priv->tag;
+ d->sched_utag[0] = '\0';
+ if (dt_utag != NULL) {
+ if (dt_utag[0] == '\0') {
+ dt_utag = NULL;
+ } else {
+ strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1);
+ d->sched_utag[sizeof(d->sched_utag) - 1] = '\0';
+ }
+ }
+ DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++,
+ dt_utag, command, dt_s1, dt_s2,
+ dt_i1, dt_i2, dt_i3, dt_i4, desc->port_str);
+#endif
cq_enq(desc, d);
}
}
@@ -2472,16 +2988,33 @@ file_output(ErlDrvData e, char* buf, int count)
static void
file_flush(ErlDrvData e) {
file_descriptor *desc = (file_descriptor *)e;
+#ifdef DEBUG
int r;
+#endif
+#ifdef USE_VM_PROBES
+ dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
+#endif
TRACE_C('f');
- r = flush_write(desc, NULL);
+#ifdef HAVE_SENDFILE
+ flush_sendfile(desc, NULL);
+#endif
+
+#ifdef DEBUG
+ r =
+#endif
+ flush_write(desc, NULL
+#ifdef USE_VM_PROBES
+ , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag
+#endif
+ );
/* Only possible reason for bad return value is ENOMEM, and
* there is nobody to tell...
*/
+#ifdef DEBUG
ASSERT(r == 0);
- r = 0; /* Avoiding warning */
+#endif
cq_execute(desc);
}
@@ -2490,16 +3023,23 @@ file_flush(ErlDrvData e) {
/*********************************************************************
* Driver entry point -> control
*/
-static int
+static ErlDrvSSizeT
file_control(ErlDrvData e, unsigned int command,
- char* buf, int len, char **rbuf, int rlen) {
+ char* buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) {
+ /*
+ * warning: variable ‘desc’ set but not used
+ * [-Wunused-but-set-variable]
+ * ... no kidding ...
+ *
+ *
file_descriptor *desc = (file_descriptor *)e;
switch (command) {
default:
return 0;
- } /* switch (command) */
+ }
ASSERT(0);
- desc = NULL; /* XXX Avoid warning while empty switch */
+ desc = NULL;
+ */
return 0;
}
@@ -2510,6 +3050,9 @@ static void
file_timeout(ErlDrvData e) {
file_descriptor *desc = (file_descriptor *)e;
enum e_timer timer_state = desc->timer_state;
+#ifdef USE_VM_PROBES
+ dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
+#endif
TRACE_C('t');
@@ -2524,12 +3067,18 @@ file_timeout(ErlDrvData e) {
driver_async(desc->port, KEY(desc), desc->invoke, desc->d, desc->free);
break;
case timer_write: {
- int r = flush_write(desc, NULL);
+#ifdef DEBUG
+ int r =
+#endif
+ flush_write(desc, NULL
+#ifdef USE_VM_PROBES
+ , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag
+#endif
+ );
/* Only possible reason for bad return value is ENOMEM, and
* there is nobody to tell...
*/
ASSERT(r == 0);
- r = 0; /* Avoiding warning */
cq_execute(desc);
} break;
} /* case */
@@ -2546,6 +3095,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
char command;
int p, q;
int err;
+ struct t_data *d = NULL;
+#ifdef USE_VM_PROBES
+ Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
+ Sint64 dt_i4 = 0;
+ char *dt_utag = NULL;
+ char *dt_s1 = NULL;
+ dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
+#endif
TRACE_C('v');
@@ -2565,18 +3122,19 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
switch (command) {
case FILE_CLOSE: {
+#ifdef USE_VM_PROBES
+ dt_utag = EV_CHAR_P(ev, p, q);
+#endif
flush_read(desc);
- if (flush_write_check_error(desc, &err) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (ev->size != 1) {
- /* Wrong command length */
- reply_posix_error(desc, EINVAL);
- goto done;
- }
if (desc->fd != FILE_FD_INVALID) {
- struct t_data *d;
if (! (d = EF_ALLOC(sizeof(struct t_data)))) {
reply_posix_error(desc, ENOMEM);
} else {
@@ -2584,6 +3142,10 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->reply = !0;
d->fd = desc->fd;
d->flags = desc->flags;
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+#endif
d->invoke = invoke_close;
d->free = free_data;
d->level = 2;
@@ -2599,8 +3161,21 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
case FILE_READ: {
Uint32 sizeH, sizeL;
size_t size, alloc_size;
- struct t_data *d;
- if (flush_write_check_error(desc, &err) < 0) {
+
+ if (!EV_GET_UINT32(ev, &sizeH, &p, &q)
+ || !EV_GET_UINT32(ev, &sizeL, &p, &q)) {
+ /* Wrong buffer length to contain the read count */
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+#ifdef USE_VM_PROBES
+ dt_utag = EV_CHAR_P(ev, p, q);
+#endif
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -2608,19 +3183,16 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
if (desc->read_bufsize == 0 && desc->read_binp != NULL && desc->read_size > 0) {
/* We have allocated a buffer for line mode but should not really have a
read-ahead buffer... */
- if (lseek_flush_read(desc, &err) < 0) {
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
}
#endif
- if (ev->size != 1+8
- || !EV_GET_UINT32(ev, &sizeH, &p, &q)
- || !EV_GET_UINT32(ev, &sizeL, &p, &q)) {
- /* Wrong buffer length to contain the read count */
- reply_posix_error(desc, EINVAL);
- goto done;
- }
#if SIZEOF_SIZE_T == 4
if (sizeH != 0) {
reply_posix_error(desc, EINVAL);
@@ -2696,6 +3268,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->c.read.bin_offset = desc->read_offset + desc->read_size;
d->c.read.bin_size = desc->read_binp->orig_size - d->c.read.bin_offset;
d->c.read.size = size;
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+ dt_i3 = d->c.read.size;
+#endif
driver_binary_inc_refc(d->c.read.binp);
d->invoke = invoke_read;
d->free = free_read;
@@ -2713,12 +3290,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
* allocated binary + dealing with offsets and lengts are done in file_async ready
* for this OP.
*/
- struct t_data *d;
- if (flush_write_check_error(desc, &err) < 0) {
+#ifdef USE_VM_PROBES
+ dt_utag = EV_CHAR_P(ev, p, q);
+#endif
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (ev->size != 1) {
+ if (ev->size != 1
+#ifdef USE_VM_PROBES
+ + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE
+#endif
+ ) {
/* Wrong command length */
reply_posix_error(desc, EINVAL);
goto done;
@@ -2774,8 +3361,16 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->c.read_line.binp = desc->read_binp;
d->c.read_line.read_offset = desc->read_offset;
d->c.read_line.read_size = desc->read_size;
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+ dt_i3 = d->c.read_line.read_offset;
+#endif
#if !ALWAYS_READ_LINE_AHEAD
d->c.read_line.read_ahead = (desc->read_bufsize > 0);
+#ifdef USE_VM_PROBES
+ dt_i4 = d->c.read_line.read_ahead;
+#endif
#endif
driver_binary_inc_refc(d->c.read.binp);
d->invoke = invoke_read_line;
@@ -2783,10 +3378,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->level = 1;
cq_enq(desc, d);
} goto done;
- case FILE_WRITE: {
- int skip = 1;
- int size = ev->size - skip;
- if (lseek_flush_read(desc, &err) < 0) {
+ case FILE_WRITE: { /* Dtrace: The dtrace user tag is not last in message,
+ but follows the message tag directly.
+ This is handled specially in prim_file.erl */
+ ErlDrvSizeT skip = 1;
+ ErlDrvSizeT size = ev->size - skip;
+
+#ifdef USE_VM_PROBES
+ dt_utag = EV_CHAR_P(ev, p, q);
+ skip += FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE;
+ size = ev->size - skip;
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -2794,7 +3401,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EBADF);
goto done;
}
- if (size <= 0) {
+ if (size == 0) {
reply_Uint(desc, size);
goto done;
}
@@ -2813,7 +3420,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
driver_set_timer(desc->port, desc->write_delay);
}
} else {
- if (async_write(desc, &err, !0, size) != 0) {
+ if ((d = async_write(desc, &err, !0, size
+#ifdef USE_VM_PROBES
+ , &dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
MUTEX_UNLOCK(desc->q_mtx);
reply_posix_error(desc, err);
goto done;
@@ -2823,24 +3434,49 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
} goto done; /* case FILE_WRITE */
- case FILE_PWRITEV: {
+ case FILE_PWRITEV: { /* Dtrace: The dtrace user tag is not last in message,
+ but follows the message tag directly.
+ This is handled specially in prim_file.erl */
Uint32 i, j, n;
size_t total;
- struct t_data *d;
- if (lseek_flush_read(desc, &err) < 0) {
- reply_Uint_posix_error(desc, 0, err);
- goto done;
- }
- if (flush_write_check_error(desc, &err) < 0) {
- reply_Uint_posix_error(desc, 0, err);
- goto done;
+#ifdef USE_VM_PROBES
+ char dt_tmp;
+ int dt_utag_bytes = 1;
+
+ dt_utag = EV_CHAR_P(ev, p, q);
+ /* This will work for UTF-8, but not for UTF-16 - extra reminder here */
+#ifdef FILENAMES_16BIT
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
+ while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') {
+ dt_utag_bytes++;
}
+#endif
if (ev->size < 1+4
+#ifdef USE_VM_PROBES
+ + dt_utag_bytes
+#endif
|| !EV_GET_UINT32(ev, &n, &p, &q)) {
/* Buffer too short to contain even the number of pos/size specs */
reply_Uint_posix_error(desc, 0, EINVAL);
goto done;
}
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
+ reply_Uint_posix_error(desc, 0, err);
+ goto done;
+ }
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
+ reply_Uint_posix_error(desc, 0, err);
+ goto done;
+ }
if (n == 0) {
/* Trivial case - nothing to write */
if (ev->size != 1+4) {
@@ -2850,7 +3486,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
goto done;
}
- if (ev->size < 1+4+8*(2*n)) {
+ if (ev->size < 1+4+8*(2*n)
+#ifdef USE_VM_PROBES
+ + dt_utag_bytes
+#endif
+ ) {
/* Buffer too short to contain even the pos/size specs */
reply_Uint_posix_error(desc, 0, EINVAL);
goto done;
@@ -2865,6 +3505,10 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->reply = !0;
d->fd = desc->fd;
d->flags = desc->flags;
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+#endif
d->c.pwritev.port = desc->port;
d->c.pwritev.q_mtx = desc->q_mtx;
d->c.pwritev.n = n;
@@ -2902,13 +3546,20 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
}
d->c.pwritev.size = total;
+#ifdef USE_VM_PROBES
+ dt_i3 = d->c.pwritev.size;
+#endif
d->c.pwritev.free_size = 0;
if (j == 0) {
/* Trivial case - nothing to write */
EF_FREE(d);
reply_Uint(desc, 0);
} else {
- size_t skip = 1 + 4 + 8*(2*n);
+ ErlDrvSizeT skip = 1 + 4 + 8 * (2*n)
+#ifdef USE_VM_PROBES
+ + dt_utag_bytes
+#endif
+ ;
if (skip + total != ev->size) {
/* Actual amount of data does not match
* total of all pos/size specs
@@ -2929,27 +3580,55 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
} goto done; /* case FILE_PWRITEV: */
- case FILE_PREADV: {
+ case FILE_PREADV: { /* Dtrace: The dtrace user tag is not last in message,
+ but follows the message tag directly.
+ This is handled specially in prim_file.erl */
register void * void_ptr;
Uint32 i, n;
- struct t_data *d;
ErlIOVec *res_ev;
- if (lseek_flush_read(desc, &err) < 0) {
+#ifdef USE_VM_PROBES
+ char dt_tmp;
+ int dt_utag_bytes = 1;
+ /* This will work for UTF-8, but not for UTF-16 - extra reminder here */
+#ifdef FILENAMES_16BIT
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
+ dt_utag = EV_CHAR_P(ev, p, q);
+ while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') {
+ dt_utag_bytes++;
+ }
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (flush_write_check_error(desc, &err) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
if (ev->size < 1+8
+#ifdef USE_VM_PROBES
+ + dt_utag_bytes
+#endif
|| !EV_GET_UINT32(ev, &n, &p, &q)
|| !EV_GET_UINT32(ev, &n, &p, &q)) {
/* Buffer too short to contain even the number of pos/size specs */
reply_posix_error(desc, EINVAL);
goto done;
}
- if (ev->size != 1+8+8*(2*n)) {
+ if (ev->size < 1+8+8*(2*n)
+#ifdef USE_VM_PROBES
+ + dt_utag_bytes
+#endif
+ ) {
/* Buffer wrong length to contain the pos/size specs */
reply_posix_error(desc, EINVAL);
goto done;
@@ -2969,6 +3648,10 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->reply = !0;
d->fd = desc->fd;
d->flags = desc->flags;
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+#endif
d->c.preadv.n = n;
d->c.preadv.cnt = 0;
d->c.preadv.size = 0;
@@ -2996,6 +3679,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#else
size = ((size_t)sizeH<<32) | sizeL;
#endif
+#ifdef USE_VM_PROBES
+ dt_i3 += size;
+#endif
if (! (res_ev->binv[i] = driver_alloc_binary(size))) {
reply_posix_error(desc, ENOMEM);
break;
@@ -3042,42 +3728,68 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
} goto done; /* case FILE_PREADV: */
case FILE_LSEEK: {
- Sint64 offset; /* Offset for seek */
+ Sint64 offset; /* Offset for seek */
Uint32 origin; /* Origin of seek. */
- if (lseek_flush_read(desc, &err) < 0) {
- reply_posix_error(desc, err);
+
+ if (ev->size < 1+8+4
+ || !EV_GET_UINT64(ev, &offset, &p, &q)
+ || !EV_GET_UINT32(ev, &origin, &p, &q)) {
+ /* Wrong length of buffer to contain offset and origin */
+ reply_posix_error(desc, EINVAL);
goto done;
}
- if (flush_write_check_error(desc, &err) < 0) {
+#ifdef USE_VM_PROBES
+ dt_utag = EV_CHAR_P(ev, p, q);
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (ev->size != 1+8+4
- || !EV_GET_UINT64(ev, &offset, &p, &q)
- || !EV_GET_UINT32(ev, &origin, &p, &q)) {
- /* Wrong length of buffer to contain offset and origin */
- reply_posix_error(desc, EINVAL);
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
+ reply_posix_error(desc, err);
goto done;
}
- if (async_lseek(desc, &err, !0, offset, origin) < 0) {
+ if ((d = async_lseek(desc, &err, !0, offset, origin
+#ifdef USE_VM_PROBES
+ , &dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
reply_posix_error(desc, err);
goto done;
}
} goto done;
case FILE_READ_FILE: {
- struct t_data *d;
char *filename;
if (ev->size < 1+1) {
/* Buffer contains empty name */
reply_posix_error(desc, ENOENT);
goto done;
}
+#ifndef USE_VM_PROBES
+ /* In the dtrace case, the iov has an extra element, the dtrace utag - we will need
+ another test to see that
+ the filename is in a single buffer: */
if (ev->size-1 != ev->iov[q].iov_len-p) {
/* Name not in one single buffer */
reply_posix_error(desc, EINVAL);
goto done;
}
+#else
+ if (((byte *)ev->iov[q].iov_base)[ev->iov[q].iov_len-1] != '\0') {
+ /* Name not in one single buffer */
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+#endif
filename = EV_CHAR_P(ev, p, q);
d = EF_ALLOC(sizeof(struct t_data) -1 + FILENAME_BYTELEN(filename) + FILENAME_CHARSIZE);
if (! d) {
@@ -3088,6 +3800,20 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->reply = !0;
/* Copy name */
FILENAME_COPY(d->b, filename);
+#ifdef USE_VM_PROBES
+ {
+ char dt_tmp;
+
+ /* This will work for UTF-8, but not for UTF-16 - extra reminder here */
+#ifdef FILENAMES_16BIT
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
+ while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0')
+ ;
+ dt_s1 = d->b;
+ dt_utag = EV_CHAR_P(ev, p, q);
+ }
+#endif
d->c.read_file.binp = NULL;
d->invoke = invoke_read_file;
d->free = free_read_file;
@@ -3107,7 +3833,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
char mode;
Sint64 hdr_offset;
Uint32 max_size;
- struct t_data *d;
ErlIOVec *res_ev;
int vsize;
if (! EV_GET_CHAR(ev, &mode, &p, &q)) {
@@ -3119,14 +3844,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EINVAL);
goto done;
}
- if (lseek_flush_read(desc, &err) < 0) {
- reply_posix_error(desc, err);
- goto done;
- }
- if (flush_write_check_error(desc, &err) < 0) {
- reply_posix_error(desc, err);
- goto done;
- }
if (ev->size < 1+1+8+4
|| !EV_GET_UINT64(ev, &hdr_offset, &p, &q)
|| !EV_GET_UINT32(ev, &max_size, &p, &q)) {
@@ -3135,6 +3852,25 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EINVAL);
goto done;
}
+#ifdef USE_VM_PROBES
+ dt_utag = EV_CHAR_P(ev, p, q);
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
+ reply_posix_error(desc, err);
+ goto done;
+ }
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
+ reply_posix_error(desc, err);
+ goto done;
+ }
/* Create the thread data structure with the contained ErlIOVec
* and corresponding binaries for the response
*/
@@ -3151,6 +3887,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->flags = desc->flags;
d->c.preadv.offsets[0] = hdr_offset;
d->c.preadv.size = max_size;
+#ifdef USE_VM_PROBES
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+ dt_i3 = d->c.preadv.offsets[0];
+ dt_i4 = d->c.preadv.size;
+#endif
res_ev = &d->c.preadv.eiov;
/* XXX possible alignment problems here for weird machines */
res_ev->iov = void_ptr = d + 1;
@@ -3165,16 +3907,24 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
case FILE_SETOPT: {
char opt;
+
if (ev->size < 1+1
|| !EV_GET_CHAR(ev, &opt, &p, &q)) {
/* Buffer too short to contain even the option type */
reply_posix_error(desc, EINVAL);
goto done;
}
+#ifdef USE_VM_PROBES
+ dt_i1 = opt;
+ dt_utag = EV_CHAR_P(ev, p, q);
+#endif
switch (opt) {
case FILE_OPT_DELAYED_WRITE: {
Uint32 sizeH, sizeL, delayH, delayL;
if (ev->size != 1+1+4*sizeof(Uint32)
+#ifdef USE_VM_PROBES
+ + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE
+#endif
|| !EV_GET_UINT32(ev, &sizeH, &p, &q)
|| !EV_GET_UINT32(ev, &sizeL, &p, &q)
|| !EV_GET_UINT32(ev, &delayH, &p, &q)
@@ -3201,12 +3951,18 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#else
desc->write_delay = ((unsigned long)delayH << 32) | delayL;
#endif
+#ifdef USE_VM_PROBES
+ dt_i2 = desc->write_delay;
+#endif
TRACE_C('K');
reply_ok(desc);
} goto done;
case FILE_OPT_READ_AHEAD: {
Uint32 sizeH, sizeL;
if (ev->size != 1+1+2*sizeof(Uint32)
+#ifdef USE_VM_PROBES
+ + FILENAME_BYTELEN(dt_utag)+FILENAME_CHARSIZE
+#endif
|| !EV_GET_UINT32(ev, &sizeH, &p, &q)
|| !EV_GET_UINT32(ev, &sizeL, &p, &q)) {
/* Buffer has wrong length to contain the option values */
@@ -3222,6 +3978,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#else
desc->read_bufsize = ((size_t)sizeH << 32) | sizeL;
#endif
+#ifdef USE_VM_PROBES
+ dt_i2 = desc->read_bufsize;
+#endif
TRACE_C('K');
reply_ok(desc);
} goto done;
@@ -3230,14 +3989,97 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
goto done;
} /* case FILE_OPT_DELAYED_WRITE: */
} ASSERT(0); goto done; /* case FILE_SETOPT: */
-
+
+ case FILE_SENDFILE: {
+
+#ifdef HAVE_SENDFILE
+ struct t_data *d;
+ Uint32 out_fd, offsetH, offsetL, hd_len, tl_len;
+ Uint64 nbytes;
+ char flags;
+
+ if (ev->size < 1 + 7 * sizeof(Uint32) + sizeof(char)
+ || !EV_GET_UINT32(ev, &out_fd, &p, &q)
+ || !EV_GET_CHAR(ev, &flags, &p, &q)
+ || !EV_GET_UINT32(ev, &offsetH, &p, &q)
+ || !EV_GET_UINT32(ev, &offsetL, &p, &q)
+ || !EV_GET_UINT64(ev, &nbytes, &p, &q)
+ || !EV_GET_UINT32(ev, &hd_len, &p, &q)
+ || !EV_GET_UINT32(ev, &tl_len, &p, &q)) {
+ /* Buffer has wrong length to contain all the needed values */
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+
+ if (hd_len != 0 || tl_len != 0 || flags != 0) {
+ // We do not allow header, trailers and/or flags right now
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+
+ d = EF_SAFE_ALLOC(sizeof(struct t_data));
+ d->fd = desc->fd;
+ d->command = command;
+ d->invoke = invoke_sendfile;
+ d->free = free_sendfile;
+ d->level = 2;
+
+ d->c.sendfile.out_fd = (int) out_fd;
+ d->c.sendfile.written = 0;
+ d->c.sendfile.port = desc->port;
+ d->c.sendfile.q_mtx = desc->q_mtx;
+
+ #if SIZEOF_OFF_T == 4
+ if (offsetH != 0) {
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+ d->c.sendfile.offset = (off_t) offsetL;
+ #else
+ d->c.sendfile.offset = ((off_t) offsetH << 32) | offsetL;
+ #endif
+
+ d->c.sendfile.nbytes = nbytes;
+
+ if (USE_THRDS_FOR_SENDFILE) {
+ SET_BLOCKING(d->c.sendfile.out_fd);
+ } else {
+ /**
+ * Write a place holder to queue in order to force file_flush
+ * to be called before the driver is closed.
+ */
+ char tmp[1] = "";
+ MUTEX_LOCK(d->c.sendfile.q_mtx);
+ if (driver_enq(d->c.sendfile.port, tmp, 1)) {
+ MUTEX_UNLOCK(d->c.sendfile.q_mtx);
+ reply_posix_error(desc, ENOMEM);
+ goto done;
+ }
+ MUTEX_UNLOCK(d->c.sendfile.q_mtx);
+ }
+
+ cq_enq(desc, d);
+#else
+ reply_posix_error(desc, ENOTSUP);
+#endif
+ goto done;
+ } /* case FILE_SENDFILE: */
+
} /* switch(command) */
-
- if (lseek_flush_read(desc, &err) < 0) {
+
+ if (lseek_flush_read(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (flush_write_check_error(desc, &err) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef USE_VM_PROBES
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
} else {
@@ -3255,5 +4097,50 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
done:
+ if (d != NULL) {
+#ifdef USE_VM_PROBES
+ /*
+ * If d == NULL, then either:
+ * 1). There was an error of some sort, or
+ * 2). The command given to us is actually implemented
+ * by file_output() instead.
+ *
+ * Case #1 is probably a TODO item, perhaps?
+ * Case #2 we definitely don't want to activate a probe.
+ */
+ d->sched_i1 = dt_priv->thread_num;
+ d->sched_i2 = dt_priv->tag;
+ d->sched_utag[0] = '\0';
+ if (dt_utag != NULL) {
+ if (dt_utag[0] == '\0') {
+ dt_utag = NULL;
+ } else {
+ strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1);
+ d->sched_utag[sizeof(d->sched_utag) - 1] = '\0';
+ }
+ }
+ DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++,
+ dt_utag, command, dt_s1, NULL, dt_i1, dt_i2, dt_i3, dt_i4,
+ desc->port_str);
+#endif
+ }
cq_execute(desc);
}
+
+#ifdef USE_VM_PROBES
+dt_private *
+get_dt_private(int base)
+{
+ dt_private *dt_priv = (dt_private *) pthread_getspecific(dt_driver_key);
+
+ if (dt_priv == NULL) {
+ dt_priv = EF_SAFE_ALLOC(sizeof(dt_private));
+ erts_mtx_lock(&dt_driver_mutex);
+ dt_priv->thread_num = (base + dt_driver_idnum++);
+ erts_mtx_unlock(&dt_driver_mutex);
+ dt_priv->tag = 0;
+ pthread_setspecific(dt_driver_key, dt_priv);
+ }
+ return dt_priv;
+}
+#endif /* USE_VM_PROBES */
diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h
index 3097ded3f1..69ad02633c 100644
--- a/erts/emulator/drivers/common/erl_efile.h
+++ b/erts/emulator/drivers/common/erl_efile.h
@@ -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
@@ -67,6 +67,11 @@
#define FILENAMES_16BIT 1
#endif
+// We use sendfilev if it exist on solaris
+#if !defined(HAVE_SENDFILE) && defined(HAVE_SENDFILEV)
+#define HAVE_SENDFILE
+#endif
+
/*
* An handle to an open directory. To be cast to the correct type
* in the system-dependent directory functions.
@@ -85,14 +90,15 @@ typedef struct _Efile_error {
/*
* This structure contains date and time.
*/
-typedef struct _Efile_time {
- unsigned year; /* (4 digits). */
- unsigned month; /* (1..12). */
- unsigned day; /* (1..31). */
- unsigned hour; /* (0..23). */
- unsigned minute; /* (0..59). */
- unsigned second; /* (0..59). */
-} Efile_time;
+
+//typedef struct _Efile_time {
+// unsigned year; /* (4 digits). */
+// unsigned month; /* (1..12). */
+// unsigned day; /* (1..31). */
+// unsigned hour; /* (0..23). */
+// unsigned minute; /* (0..59). */
+// unsigned second; /* (0..59). */
+//} Efile_time;
/*
@@ -111,13 +117,26 @@ typedef struct _Efile_info {
Uint32 inode; /* Inode number. */
Uint32 uid; /* User id of owner. */
Uint32 gid; /* Group id of owner. */
- Efile_time accessTime; /* Last time the file was accessed. */
- Efile_time modifyTime; /* Last time the file was modified. */
- Efile_time cTime; /* Creation time (Windows) or last
+ time_t accessTime; /* Last time the file was accessed. */
+ time_t modifyTime; /* Last time the file was modified. */
+ time_t cTime; /* Creation time (Windows) or last
* inode change (Unix).
*/
} Efile_info;
+
+#ifdef HAVE_SENDFILE
+/*
+ * Describes the structure of headers/trailers for sendfile
+ */
+struct t_sendfile_hdtl {
+ SysIOVec *headers;
+ int hdr_cnt;
+ SysIOVec *trailers;
+ int trl_cnt;
+};
+#endif /* HAVE_SENDFILE */
+
/*
* Functions.
*/
@@ -143,7 +162,7 @@ int efile_write_info(Efile_error* errInfo, Efile_info* pInfo, char *name);
int efile_write(Efile_error* errInfo, int flags, int fd,
char* buf, size_t count);
int efile_writev(Efile_error* errInfo, int flags, int fd,
- SysIOVec* iov, int iovcnt, size_t size);
+ SysIOVec* iov, int iovcnt);
int efile_read(Efile_error* errInfo, int flags, int fd,
char* buf, size_t count, size_t* pBytesRead);
int efile_seek(Efile_error* errInfo, int fd,
@@ -162,3 +181,7 @@ int efile_symlink(Efile_error* errInfo, char* old, char* new);
int efile_may_openfile(Efile_error* errInfo, char *name);
int efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length,
int advise);
+#ifdef HAVE_SENDFILE
+int efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd,
+ off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl *hdtl);
+#endif /* HAVE_SENDFILE */
diff --git a/erts/emulator/drivers/common/gzio.c b/erts/emulator/drivers/common/gzio.c
index 741cb6ae20..a9303d55bc 100644
--- a/erts/emulator/drivers/common/gzio.c
+++ b/erts/emulator/drivers/common/gzio.c
@@ -27,7 +27,9 @@
#endif
#ifdef __WIN32__
+#ifndef HAVE_CONFLICTING_FREAD_DECLARATION
#define HAVE_CONFLICTING_FREAD_DECLARATION
+#endif
#define FILENAMES_16BIT 1
#endif
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 426917bd2c..8f4fff0f40 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2012. All Rights Reserved.
*
* The 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,6 +80,13 @@
#endif
#ifdef __WIN32__
+#define LLU "%I64u"
+#else
+#define LLU "%llu"
+#endif
+typedef unsigned long long llu_t;
+
+#ifdef __WIN32__
#define STRNCASECMP strncasecmp
#define INCL_WINSOCK_API_TYPEDEFS 1
@@ -110,6 +117,77 @@
#undef EWOULDBLOCK
#undef ETIMEDOUT
+#ifdef EINPROGRESS
+#undef EINPROGRESS
+#endif
+#ifdef EALREADY
+#undef EALREADY
+#endif
+#ifdef ENOTSOCK
+#undef ENOTSOCK
+#endif
+#ifdef EDESTADDRREQ
+#undef EDESTADDRREQ
+#endif
+#ifdef EMSGSIZE
+#undef EMSGSIZE
+#endif
+#ifdef EPROTOTYPE
+#undef EPROTOTYPE
+#endif
+#ifdef ENOPROTOOPT
+#undef ENOPROTOOPT
+#endif
+#ifdef EPROTONOSUPPORT
+#undef EPROTONOSUPPORT
+#endif
+#ifdef EOPNOTSUPP
+#undef EOPNOTSUPP
+#endif
+#ifdef EAFNOSUPPORT
+#undef EAFNOSUPPORT
+#endif
+#ifdef EADDRINUSE
+#undef EADDRINUSE
+#endif
+#ifdef EADDRNOTAVAIL
+#undef EADDRNOTAVAIL
+#endif
+#ifdef ENETDOWN
+#undef ENETDOWN
+#endif
+#ifdef ENETUNREACH
+#undef ENETUNREACH
+#endif
+#ifdef ENETRESET
+#undef ENETRESET
+#endif
+#ifdef ECONNABORTED
+#undef ECONNABORTED
+#endif
+#ifdef ECONNRESET
+#undef ECONNRESET
+#endif
+#ifdef ENOBUFS
+#undef ENOBUFS
+#endif
+#ifdef EISCONN
+#undef EISCONN
+#endif
+#ifdef ENOTCONN
+#undef ENOTCONN
+#endif
+#ifdef ECONNREFUSED
+#undef ECONNREFUSED
+#endif
+#ifdef ELOOP
+#undef ELOOP
+#endif
+#ifdef EHOSTUNREACH
+#undef EHOSTUNREACH
+#endif
+
+
#define HAVE_MULTICAST_SUPPORT
#define ERRNO_BLOCK WSAEWOULDBLOCK
@@ -280,6 +358,57 @@ static unsigned long one_value = 1;
# define SCTP_EOF MSG_EOF
#endif
+/* More Solaris 10 fixes: */
+#if ! HAVE_DECL_SCTP_CLOSED && HAVE_DECL_SCTPS_IDLE
+# define SCTP_CLOSED SCTPS_IDLE
+# undef HAVE_DECL_SCTP_CLOSED
+# define HAVE_DECL_SCTP_CLOSED 1
+#endif
+#if ! HAVE_DECL_SCTP_BOUND && HAVE_DECL_SCTPS_BOUND
+# define SCTP_BOUND SCTPS_BOUND
+# undef HAVE_DECL_SCTP_BOUND
+# define HAVE_DECL_SCTP_BOUND 1
+#endif
+#if ! HAVE_DECL_SCTP_LISTEN && HAVE_DECL_SCTPS_LISTEN
+# define SCTP_LISTEN SCTPS_LISTEN
+# undef HAVE_DECL_SCTP_LISTEN
+# define HAVE_DECL_SCTP_LISTEN 1
+#endif
+#if ! HAVE_DECL_SCTP_COOKIE_WAIT && HAVE_DECL_SCTPS_COOKIE_WAIT
+# define SCTP_COOKIE_WAIT SCTPS_COOKIE_WAIT
+# undef HAVE_DECL_SCTP_COOKIE_WAIT
+# define HAVE_DECL_SCTP_COOKIE_WAIT 1
+#endif
+#if ! HAVE_DECL_SCTP_COOKIE_ECHOED && HAVE_DECL_SCTPS_COOKIE_ECHOED
+# define SCTP_COOKIE_ECHOED SCTPS_COOKIE_ECHOED
+# undef HAVE_DECL_SCTP_COOKIE_ECHOED
+# define HAVE_DECL_SCTP_COOKIE_ECHOED 1
+#endif
+#if ! HAVE_DECL_SCTP_ESTABLISHED && HAVE_DECL_SCTPS_ESTABLISHED
+# define SCTP_ESTABLISHED SCTPS_ESTABLISHED
+# undef HAVE_DECL_SCTP_ESTABLISHED
+# define HAVE_DECL_SCTP_ESTABLISHED 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_PENDING && HAVE_DECL_SCTPS_SHUTDOWN_PENDING
+# define SCTP_SHUTDOWN_PENDING SCTPS_SHUTDOWN_PENDING
+# undef HAVE_DECL_SCTP_SHUTDOWN_PENDING
+# define HAVE_DECL_SCTP_SHUTDOWN_PENDING 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_SENT && HAVE_DECL_SCTPS_SHUTDOWN_SENT
+# define SCTP_SHUTDOWN_SENT SCTPS_SHUTDOWN_SENT
+# undef HAVE_DECL_SCTP_SHUTDOWN_SENT
+# define HAVE_DECL_SCTP_SHUTDOWN_SENT 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_RECEIVED && HAVE_DECL_SCTPS_SHUTDOWN_RECEIVED
+# define SCTP_SHUTDOWN_RECEIVED SCTPS_SHUTDOWN_RECEIVED
+# undef HAVE_DECL_SCTP_SHUTDOWN_RECEIVED
+# define HAVE_DECL_SCTP_SHUTDOWN_RECEIVED 1
+#endif
+#if ! HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT && HAVE_DECL_SCTPS_SHUTDOWN_ACK_SENT
+# define SCTP_SHUTDOWN_ACK_SENT SCTPS_SHUTDOWN_ACK_SENT
+# undef HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT
+# define HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT 1
+#endif
/* New spelling in lksctp 2.6.22 or maybe even earlier:
* adaption -> adaptation
*/
@@ -294,12 +423,13 @@ static unsigned long one_value = 1;
# define sctp_adaptation_layer_event sctp_adaption_layer_event
#endif
-static void *h_libsctp = NULL;
#ifdef __GNUC__
static typeof(sctp_bindx) *p_sctp_bindx = NULL;
+static typeof(sctp_peeloff) *p_sctp_peeloff = NULL;
#else
static int (*p_sctp_bindx)(int sd, struct sockaddr *addrs,
int addrcnt, int flags) = NULL;
+static int (*p_sctp_peeloff)(int sd, sctp_assoc_t assoc_id) = NULL;
#endif
#endif /* SCTP supported */
@@ -393,6 +523,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
driver_select(port, e, mode | (on?ERL_DRV_USE:0), on)
#define sock_select(d, flags, onoff) do { \
+ ASSERT(!(d)->is_ignored); \
(d)->event_mask = (onoff) ? \
((d)->event_mask | (flags)) : \
((d)->event_mask & ~(flags)); \
@@ -415,6 +546,19 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
(((unsigned char*) (s))[1] << 8) | \
(((unsigned char*) (s))[0]))
+
+#ifdef VALGRIND
+# include <valgrind/memcheck.h>
+#else
+# define VALGRIND_MAKE_MEM_DEFINED(ptr,size)
+#endif
+
+/*
+ Magic errno value used locally for return of {error, system_limit}
+ - the emulator definition of SYSTEM_LIMIT is not available here.
+*/
+#define INET_ERRNO_SYSTEM_LIMIT (15 << 8)
+
/*----------------------------------------------------------------------------
** Interface constants.
**
@@ -427,7 +571,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_AF_ANY 3 /* INADDR_ANY or IN6ADDR_ANY_INIT */
#define INET_AF_LOOPBACK 4 /* INADDR_LOOPBACK or IN6ADDR_LOOPBACK_INIT */
-/* INET_REQ_GETTYPE enumeration */
+/* open and INET_REQ_GETTYPE enumeration */
#define INET_TYPE_STREAM 1
#define INET_TYPE_DGRAM 2
#define INET_TYPE_SEQPACKET 3
@@ -484,16 +628,21 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define INET_REQ_IFSET 23
#define INET_REQ_SUBSCRIBE 24
#define INET_REQ_GETIFADDRS 25
+#define INET_REQ_ACCEPT 26
+#define INET_REQ_LISTEN 27
+#define INET_REQ_IGNOREFD 28
+
/* TCP requests */
-#define TCP_REQ_ACCEPT 40
-#define TCP_REQ_LISTEN 41
+/* #define TCP_REQ_ACCEPT 40 MOVED */
+/* #define TCP_REQ_LISTEN 41 MERGED */
#define TCP_REQ_RECV 42
#define TCP_REQ_UNRECV 43
#define TCP_REQ_SHUTDOWN 44
/* UDP and SCTP requests */
#define PACKET_REQ_RECV 60 /* Common for UDP and SCTP */
-#define SCTP_REQ_LISTEN 61 /* Different from TCP; not for UDP */
+/* #define SCTP_REQ_LISTEN 61 MERGED Different from TCP; not for UDP */
#define SCTP_REQ_BINDX 62 /* Multi-home SCTP bind */
+#define SCTP_REQ_PEELOFF 63
/* INET_REQ_SUBSCRIBE sub-requests */
#define INET_SUBS_EMPTY_OUT_Q 1
@@ -507,7 +656,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
/* *_REQ_* replies */
#define INET_REP_ERROR 0
#define INET_REP_OK 1
-#define INET_REP_SCTP 2
+#define INET_REP 2
/* INET_REQ_SETOPTS and INET_REQ_GETOPTS options */
#define INET_OPT_REUSEADDR 0 /* enable/disable local address reuse */
@@ -628,10 +777,14 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
** End of interface constants.
**--------------------------------------------------------------------------*/
-#define INET_STATE_CLOSED 0
-#define INET_STATE_OPEN (INET_F_OPEN)
-#define INET_STATE_BOUND (INET_STATE_OPEN | INET_F_BOUND)
-#define INET_STATE_CONNECTED (INET_STATE_BOUND | INET_F_ACTIVE)
+#define INET_STATE_CLOSED (0)
+#define INET_STATE_OPEN (INET_F_OPEN)
+#define INET_STATE_BOUND (INET_STATE_OPEN | INET_F_BOUND)
+#define INET_STATE_CONNECTED (INET_STATE_BOUND | INET_F_ACTIVE)
+#define INET_STATE_LISTENING (INET_STATE_BOUND | INET_F_LISTEN)
+#define INET_STATE_CONNECTING (INET_STATE_BOUND | INET_F_CON)
+#define INET_STATE_ACCEPTING (INET_STATE_LISTENING | INET_F_ACC)
+#define INET_STATE_MULTI_ACCEPTING (INET_STATE_ACCEPTING | INET_F_MULTI_CLIENT)
#define IS_OPEN(d) \
(((d)->state & INET_F_OPEN) == INET_F_OPEN)
@@ -666,6 +819,11 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
/* Max interface name */
#define INET_IFNAMSIZ 16
+/* INET Ignore states */
+#define INET_IGNORE_NONE 0
+#define INET_IGNORE_READ 1
+#define INET_IGNORE_WRITE 1 << 1
+
/* Max length of Erlang Term Buffer (for outputting structured terms): */
#ifdef HAVE_SCTP
#define PACKET_ERL_DRV_TERM_DATA_LEN 512
@@ -674,7 +832,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#endif
-#define BIN_REALLOC_LIMIT(x) (((x)*3)/4) /* 75% */
+#define BIN_REALLOC_MARGIN(x) ((x)/4) /* 25% */
/* The general purpose sockaddr */
typedef union {
@@ -805,20 +963,13 @@ typedef struct {
double send_avg; /* average packet size sent */
subs_list empty_out_q_subs; /* Empty out queue subscribers */
+ int is_ignored; /* if a fd is ignored by the inet_drv.
+ This flag should be set to true when
+ the fd is used outside of inet_drv. */
} inet_descriptor;
-#define TCP_STATE_CLOSED INET_STATE_CLOSED
-#define TCP_STATE_OPEN (INET_F_OPEN)
-#define TCP_STATE_BOUND (TCP_STATE_OPEN | INET_F_BOUND)
-#define TCP_STATE_CONNECTED (TCP_STATE_BOUND | INET_F_ACTIVE)
-#define TCP_STATE_LISTEN (TCP_STATE_BOUND | INET_F_LISTEN)
-#define TCP_STATE_CONNECTING (TCP_STATE_BOUND | INET_F_CON)
-#define TCP_STATE_ACCEPTING (TCP_STATE_LISTEN | INET_F_ACC)
-#define TCP_STATE_MULTI_ACCEPTING (TCP_STATE_ACCEPTING | INET_F_MULTI_CLIENT)
-
-
#define TCP_MAX_PACKET_SIZE 0x4000000 /* 64 M */
#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
@@ -827,13 +978,14 @@ typedef struct {
static int tcp_inet_init(void);
static void tcp_inet_stop(ErlDrvData);
-static void tcp_inet_command(ErlDrvData, char*, int);
+static void tcp_inet_command(ErlDrvData, char*, ErlDrvSizeT);
static void tcp_inet_commandv(ErlDrvData, ErlIOVec*);
static void tcp_inet_flush(ErlDrvData drv_data);
static void tcp_inet_drv_input(ErlDrvData, ErlDrvEvent);
static void tcp_inet_drv_output(ErlDrvData data, ErlDrvEvent event);
static ErlDrvData tcp_inet_start(ErlDrvPort, char* command);
-static int tcp_inet_ctl(ErlDrvData, unsigned int, char*, int, char**, int);
+static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData, unsigned int,
+ char*, ErlDrvSizeT, char**, ErlDrvSizeT);
static void tcp_inet_timeout(ErlDrvData);
static void tcp_inet_process_exit(ErlDrvData, ErlDrvMonitor *);
static void inet_stop_select(ErlDrvEvent, void*);
@@ -874,25 +1026,19 @@ static struct erl_drv_entry tcp_inet_driver_entry =
inet_stop_select
};
-#define PACKET_STATE_CLOSED INET_STATE_CLOSED
-#define PACKET_STATE_OPEN (INET_F_OPEN)
-#define PACKET_STATE_BOUND (PACKET_STATE_OPEN | INET_F_BOUND)
-#define SCTP_STATE_LISTEN (PACKET_STATE_BOUND | INET_F_LISTEN)
-#define SCTP_STATE_CONNECTING (PACKET_STATE_BOUND | INET_F_CON)
-#define PACKET_STATE_CONNECTED (PACKET_STATE_BOUND | INET_F_ACTIVE)
static int packet_inet_init(void);
static void packet_inet_stop(ErlDrvData);
-static void packet_inet_command(ErlDrvData, char*, int);
+static void packet_inet_command(ErlDrvData, char*, ErlDrvSizeT);
static void packet_inet_drv_input(ErlDrvData data, ErlDrvEvent event);
static void packet_inet_drv_output(ErlDrvData data, ErlDrvEvent event);
static ErlDrvData udp_inet_start(ErlDrvPort, char* command);
#ifdef HAVE_SCTP
static ErlDrvData sctp_inet_start(ErlDrvPort, char* command);
#endif
-static int packet_inet_ctl(ErlDrvData, unsigned int, char*,
- int, char**, int);
+static ErlDrvSSizeT packet_inet_ctl(ErlDrvData, unsigned int, char*,
+ ErlDrvSizeT, char**, ErlDrvSizeT);
static void packet_inet_timeout(ErlDrvData);
#ifdef __WIN32__
static void packet_inet_event(ErlDrvData, ErlDrvEvent);
@@ -986,7 +1132,7 @@ typedef struct {
} tcp_descriptor;
/* send function */
-static int tcp_send(tcp_descriptor* desc, char* ptr, int len);
+static int tcp_send(tcp_descriptor* desc, char* ptr, ErlDrvSizeT len);
static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev);
static int tcp_recv(tcp_descriptor* desc, int request_len);
static int tcp_deliver(tcp_descriptor* desc, int len);
@@ -997,6 +1143,9 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event);
typedef struct {
inet_descriptor inet; /* common data structure (DON'T MOVE) */
int read_packets; /* Number of packets to read per invocation */
+ int i_bufsz; /* current input buffer size */
+ ErlDrvBinary* i_buf; /* current binary buffer */
+ char* i_ptr; /* current pos in buf */
} udp_descriptor;
@@ -1050,7 +1199,7 @@ static ErlDrvTermData am_tos;
static int inet_init(void);
-static int ctl_reply(int, char*, int, char**, int);
+static ErlDrvSSizeT ctl_reply(int, char*, ErlDrvSizeT, char**, ErlDrvSizeT);
struct erl_drv_entry inet_driver_entry =
{
@@ -1060,9 +1209,46 @@ struct erl_drv_entry inet_driver_entry =
NULL, /* output */
NULL, /* ready_input */
NULL, /* ready_output */
- "inet"
+ "inet",
+ NULL,
+ NULL, /* handle */
+ NULL, /* control */
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
+#if HAVE_IN6
+# if ! defined(HAVE_IN6ADDR_ANY) || ! HAVE_IN6ADDR_ANY
+# if HAVE_DECL_IN6ADDR_ANY_INIT
+static const struct in6_addr in6addr_any = { { IN6ADDR_ANY_INIT } };
+# else
+static const struct in6_addr in6addr_any =
+ { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
+# endif /* HAVE_IN6ADDR_ANY_INIT */
+# endif /* ! HAVE_DECL_IN6ADDR_ANY */
+
+# if ! defined(HAVE_IN6ADDR_LOOPBACK) || ! HAVE_IN6ADDR_LOOPBACK
+# if HAVE_DECL_IN6ADDR_LOOPBACK_INIT
+static const struct in6_addr in6addr_loopback =
+ { { IN6ADDR_LOOPBACK_INIT } };
+# else
+static const struct in6_addr in6addr_loopback =
+ { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } };
+# endif /* HAVE_IN6ADDR_LOOPBACk_INIT */
+# endif /* ! HAVE_DECL_IN6ADDR_LOOPBACK */
+#endif /* HAVE_IN6 */
+
/* XXX: is this a driver interface function ??? */
void erl_exit(int n, char*, ...);
@@ -1074,7 +1260,7 @@ void erl_exit(int n, char*, ...);
#ifdef FATAL_MALLOC
-static void *alloc_wrapper(size_t size){
+static void *alloc_wrapper(ErlDrvSizeT size){
void *ret = driver_alloc(size);
if(ret == NULL)
erl_exit(1,"Out of virtual memory in malloc (%s)", __FILE__);
@@ -1082,7 +1268,7 @@ static void *alloc_wrapper(size_t size){
}
#define ALLOC(X) alloc_wrapper(X)
-static void *realloc_wrapper(void *current, size_t size){
+static void *realloc_wrapper(void *current, ErlDrvSizeT size){
void *ret = driver_realloc(current,size);
if(ret == NULL)
erl_exit(1,"Out of virtual memory in realloc (%s)", __FILE__);
@@ -1311,11 +1497,11 @@ static InetDrvBufStk *get_bufstk(void)
return bs;
}
-static ErlDrvBinary* alloc_buffer(long minsz)
+static ErlDrvBinary* alloc_buffer(ErlDrvSizeT minsz)
{
InetDrvBufStk *bs = get_bufstk();
- DEBUGF(("alloc_buffer: %ld\r\n", minsz));
+ DEBUGF(("alloc_buffer: "LLU"\r\n", (llu_t)minsz));
if (bs && bs->buf.pos > 0) {
long size;
@@ -1391,7 +1577,7 @@ static void release_buffer(ErlDrvBinary* buf)
}
}
-static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, long newsz)
+static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, ErlDrvSizeT newsz)
{
return driver_realloc_binary(buf, newsz);
}
@@ -1420,8 +1606,9 @@ static ErlDrvData dummy_start(ErlDrvPort port, char* command)
return (ErlDrvData)port;
}
-static int dummy_ctl(ErlDrvData data, unsigned int cmd, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT dummy_ctl(ErlDrvData data, unsigned int cmd,
+ char* buf, ErlDrvSizeT len, char** rbuf,
+ ErlDrvSizeT rsize)
{
static char error[] = "no_winsock2";
@@ -1429,7 +1616,7 @@ static int dummy_ctl(ErlDrvData data, unsigned int cmd, char* buf, int len,
return ctl_reply(INET_REP_ERROR, error, sizeof(error), rbuf, rsize);
}
-static void dummy_command(ErlDrvData data, char* buf, int len)
+static void dummy_command(ErlDrvData data, char* buf, ErlDrvSizeT len)
{
}
@@ -1485,8 +1672,20 @@ static struct erl_drv_entry dummy_sctp_driver_entry =
#endif
+/* return lowercase string form of errno value */
+static char *errno_str(int err)
+{
+ switch (err) {
+ case INET_ERRNO_SYSTEM_LIMIT:
+ return "system_limit";
+ default:
+ return erl_errno_id(err);
+ }
+}
+
/* general control reply function */
-static int ctl_reply(int rep, char* buf, int len, char** rbuf, int rsize)
+static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
char* ptr;
@@ -1502,18 +1701,14 @@ static int ctl_reply(int rep, char* buf, int len, char** rbuf, int rsize)
}
/* general control error reply function */
-static int ctl_error(int err, char** rbuf, int rsize)
+static ErlDrvSSizeT ctl_error(int err, char** rbuf, ErlDrvSizeT rsize)
{
- char response[256]; /* Response buffer. */
- char* s;
- char* t;
+ char* s = errno_str(err);
- for (s = erl_errno_id(err), t = response; *s; s++, t++)
- *t = tolower(*s);
- return ctl_reply(INET_REP_ERROR, response, t-response, rbuf, rsize);
+ return ctl_reply(INET_REP_ERROR, s, strlen(s), rbuf, rsize);
}
-static int ctl_xerror(char* xerr, char** rbuf, int rsize)
+static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize)
{
int n = strlen(xerr);
return ctl_reply(INET_REP_ERROR, xerr, n, rbuf, rsize);
@@ -1522,14 +1717,7 @@ static int ctl_xerror(char* xerr, char** rbuf, int rsize)
static ErlDrvTermData error_atom(int err)
{
- char errstr[256];
- char* s;
- char* t;
-
- for (s = erl_errno_id(err), t = errstr; *s; s++, t++)
- *t = tolower(*s);
- *t = '\0';
- return driver_mk_atom(errstr);
+ return driver_mk_atom(errno_str(err));
}
@@ -1851,6 +2039,26 @@ static int inet_reply_ok(inet_descriptor* desc)
return driver_send_term(desc->port, caller, spec, i);
}
+#ifdef HAVE_SCTP
+static int inet_reply_ok_port(inet_descriptor* desc, ErlDrvTermData dport)
+{
+ ErlDrvTermData spec[2*LOAD_ATOM_CNT + 2*LOAD_PORT_CNT + 2*LOAD_TUPLE_CNT];
+ ErlDrvTermData caller = desc->caller;
+ int i = 0;
+
+ i = LOAD_ATOM(spec, i, am_inet_reply);
+ i = LOAD_PORT(spec, i, desc->dport);
+ i = LOAD_ATOM(spec, i, am_ok);
+ i = LOAD_PORT(spec, i, dport);
+ i = LOAD_TUPLE(spec, i, 2);
+ i = LOAD_TUPLE(spec, i, 3);
+ ASSERT(i == sizeof(spec)/sizeof(*spec));
+
+ desc->caller = 0;
+ return driver_send_term(desc->port, caller, spec, i);
+}
+#endif
+
/* send:
** {inet_reply, S, {error, Reason}}
*/
@@ -2389,14 +2597,19 @@ static ErlDrvTermData am_sctp_rtoinfo, /* Option names */
am_active, am_inactive,
/* For #sctp_status{}: */
- am_empty, am_closed,
+# if HAVE_DECL_SCTP_EMPTY
+ am_empty,
+# endif
+# if HAVE_DECL_SCTP_BOUND
+ am_bound,
+# endif
+# if HAVE_DECL_SCTP_LISTEN
+ am_listen,
+# endif
am_cookie_wait, am_cookie_echoed,
am_established, am_shutdown_pending,
am_shutdown_sent, am_shutdown_received,
am_shutdown_ack_sent;
- /* Not yet implemented in the Linux kernel:
- ** am_bound, am_listen;
- */
/*
** Parsing of "sctp_sndrcvinfo": ancillary data coming with received msgs.
@@ -2665,7 +2878,8 @@ static int sctp_parse_async_event
# ifdef HAVE_STRUCT_SCTP_REMOTE_ERROR_SRE_DATA
chunk = (char*) (&(sptr->sre_data));
# else
- chunk = ((char*)sptr) + sizeof(*sptr);
+ chunk = ((char*) &(sptr->sre_assoc_id))
+ + sizeof(sptr->sre_assoc_id);
# endif
chlen = sptr->sre_length - (chunk - (char *)sptr);
i = sctp_parse_error_chunk(spec, i, chunk, chlen);
@@ -2716,7 +2930,8 @@ static int sctp_parse_async_event
# ifdef HAVE_STRUCT_SCTP_SEND_FAILED_SSF_DATA
chunk = (char*) (&(sptr->ssf_data));
# else
- chunk = ((char*)sptr) + sizeof(*sptr);
+ chunk = ((char*) &(sptr->ssf_assoc_id))
+ + sizeof(sptr->ssf_assoc_id);
# endif
chlen = sptr->ssf_length - (chunk - (char*) sptr);
choff = chunk - bin->orig_bytes;
@@ -2930,6 +3145,7 @@ static int tcp_message(inet_descriptor* desc, const char* buf, int len)
int i = 0;
DEBUGF(("tcp_message(%ld): len = %d\r\n", (long)desc->port, len));
+ /* XXX fprintf(stderr,"tcp_message send.\r\n"); */
i = LOAD_ATOM(spec, i, am_tcp);
i = LOAD_PORT(spec, i, desc->dport);
@@ -3390,8 +3606,15 @@ static void inet_init_sctp(void) {
INIT_ATOM(inactive);
/* For #sctp_status{}: */
+# if HAVE_DECL_SCTP_EMPTY
INIT_ATOM(empty);
- INIT_ATOM(closed);
+# endif
+# if HAVE_DECL_SCTP_BOUND
+ INIT_ATOM(bound);
+# endif
+# if HAVE_DECL_SCTP_LISTEN
+ INIT_ATOM(listen);
+# endif
INIT_ATOM(cookie_wait);
INIT_ATOM(cookie_echoed);
INIT_ATOM(established);
@@ -3399,10 +3622,6 @@ static void inet_init_sctp(void) {
INIT_ATOM(shutdown_sent);
INIT_ATOM(shutdown_received);
INIT_ATOM(shutdown_ack_sent);
- /* Not yet implemented in the Linux kernel:
- ** INIT_ATOM(bound);
- ** INIT_ATOM(listen);
- */
}
#endif /* HAVE_SCTP */
@@ -3453,17 +3672,32 @@ static int inet_init()
/* Check the size of SCTP AssocID -- currently both this driver and the
Erlang part require 32 bit: */
ASSERT(sizeof(sctp_assoc_t)==ASSOC_ID_LEN);
-# ifndef LIBSCTP
-# error LIBSCTP not defined
-# endif
- if (erts_sys_ddll_open_noext(STRINGIFY(LIBSCTP), &h_libsctp, NULL) == 0) {
- void *ptr;
- if (erts_sys_ddll_sym(h_libsctp, "sctp_bindx", &ptr) == 0) {
- p_sctp_bindx = ptr;
- inet_init_sctp();
- add_driver_entry(&sctp_inet_driver_entry);
+# if defined(HAVE_SCTP_BINDX) && defined (HAVE_SCTP_PEELOFF)
+ p_sctp_bindx = sctp_bindx;
+ p_sctp_peeloff = sctp_peeloff;
+ inet_init_sctp();
+ add_driver_entry(&sctp_inet_driver_entry);
+# else
+# ifndef LIBSCTP
+# error LIBSCTP not defined
+# endif
+ {
+ static void *h_libsctp = NULL;
+
+ if (erts_sys_ddll_open_noext(STRINGIFY(LIBSCTP), &h_libsctp, NULL)
+ == 0) {
+ void *ptr;
+ if (erts_sys_ddll_sym(h_libsctp, "sctp_bindx", &ptr) == 0) {
+ p_sctp_bindx = ptr;
+ inet_init_sctp();
+ add_driver_entry(&sctp_inet_driver_entry);
+ if (erts_sys_ddll_sym(h_libsctp, "sctp_peeloff", &ptr) == 0) {
+ p_sctp_peeloff = ptr;
+ }
+ }
}
}
+# endif
#endif
/* remove the dummy inet driver */
@@ -3485,13 +3719,17 @@ static int inet_init()
** and is set to actual length of dst on return
** return NULL on error and ptr after port address on success
*/
-static char* inet_set_address(int family, inet_address* dst, char* src, int* len)
+static char* inet_set_address(int family, inet_address* dst,
+ char* src, ErlDrvSizeT* len)
{
short port;
if ((family == AF_INET) && (*len >= 2+4)) {
sys_memzero((char*)dst, sizeof(struct sockaddr_in));
port = get_int16(src);
+#ifndef NO_SA_LEN
+ dst->sai.sin_len = sizeof(struct sockaddr_in);
+#endif
dst->sai.sin_family = family;
dst->sai.sin_port = sock_htons(port);
sys_memcpy(&dst->sai.sin_addr, src+2, 4);
@@ -3502,6 +3740,9 @@ static char* inet_set_address(int family, inet_address* dst, char* src, int* len
else if ((family == AF_INET6) && (*len >= 2+16)) {
sys_memzero((char*)dst, sizeof(struct sockaddr_in6));
port = get_int16(src);
+#ifndef NO_SA_LEN
+ dst->sai6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
dst->sai6.sin6_family = family;
dst->sai6.sin6_port = sock_htons(port);
dst->sai6.sin6_flowinfo = 0; /* XXX this may be set as well ?? */
@@ -3512,7 +3753,7 @@ static char* inet_set_address(int family, inet_address* dst, char* src, int* len
#endif
return NULL;
}
-#ifdef HAVE_SCTP
+
/*
** Set an inaddr structure, address family comes from source data,
** or from argument if source data specifies constant address.
@@ -3521,7 +3762,7 @@ static char* inet_set_address(int family, inet_address* dst, char* src, int* len
** src = [TAG,P1,P0,X1,X2,...] when TAG = INET_AF_INET | INET_AF_INET6
*/
static char *inet_set_faddress(int family, inet_address* dst,
- char *src, int* len) {
+ char *src, ErlDrvSizeT* len) {
int tag;
if (*len < 1) return NULL;
@@ -3556,6 +3797,9 @@ static char *inet_set_faddress(int family, inet_address* dst,
return NULL;
}
sys_memzero((char*)dst, sizeof(struct sockaddr_in));
+#ifndef NO_SA_LEN
+ dst->sai.sin_len = sizeof(struct sockaddr_in6);
+#endif
dst->sai.sin_family = family;
dst->sai.sin_port = sock_htons(port);
dst->sai.sin_addr.s_addr = addr.s_addr;
@@ -3575,6 +3819,9 @@ static char *inet_set_faddress(int family, inet_address* dst,
return NULL;
}
sys_memzero((char*)dst, sizeof(struct sockaddr_in6));
+#ifndef NO_SA_LEN
+ dst->sai6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
dst->sai6.sin6_family = family;
dst->sai6.sin6_port = sock_htons(port);
dst->sai6.sin6_flowinfo = 0; /* XXX this may be set as well ?? */
@@ -3592,7 +3839,7 @@ static char *inet_set_faddress(int family, inet_address* dst,
}
return inet_set_address(family, dst, src, len);
}
-#endif /* HAVE_SCTP */
+
/* Get a inaddr structure
** src = inaddr structure
@@ -3636,7 +3883,13 @@ static void desc_close(inet_descriptor* desc)
desc->forced_events = 0;
desc->send_would_block = 0;
#endif
- driver_select(desc->port, (ErlDrvEvent)(long)desc->event, ERL_DRV_USE, 0);
+ // We should close the fd here, but the other driver might still
+ // be selecting on it.
+ if (!desc->is_ignored)
+ driver_select(desc->port,(ErlDrvEvent)(long)desc->event,
+ ERL_DRV_USE, 0);
+ else
+ inet_stop_select((ErlDrvEvent)(long)desc->event,NULL);
desc->event = INVALID_EVENT; /* closed by stop_select callback */
desc->s = INVALID_SOCKET;
desc->event_mask = 0;
@@ -3679,8 +3932,8 @@ static int erl_inet_close(inet_descriptor* desc)
}
-static int inet_ctl_open(inet_descriptor* desc, int domain, int type,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type,
+ char** rbuf, ErlDrvSizeT rsize)
{
if (desc->state != INET_STATE_CLOSED)
return ctl_xerror(EXBADSEQ, rbuf, rsize);
@@ -3700,8 +3953,8 @@ static int inet_ctl_open(inet_descriptor* desc, int domain, int type,
/* as inet_open but pass in an open socket (MUST BE OF RIGHT TYPE) */
-static int inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
- SOCKET s, char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
+ SOCKET s, char** rbuf, ErlDrvSizeT rsize)
{
inet_address name;
unsigned int sz = sizeof(name);
@@ -3876,6 +4129,7 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr)
addr->sa_family = AF_INET;
return ptr + sizeof(struct in_addr);
}
+#if defined(HAVE_IN6) && defined(AF_INET6)
case INET_AF_INET6: {
struct in6_addr *p = &((struct sockaddr_in6*)addr)->sin6_addr;
buf_check(ptr,end,sizeof(struct in6_addr));
@@ -3883,6 +4137,7 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr)
addr->sa_family = AF_INET6;
return ptr + sizeof(struct in6_addr);
}
+#endif
}
error:
return NULL;
@@ -3905,14 +4160,15 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr)
#if defined(__WIN32__) && defined(SIO_GET_INTERFACE_LIST)
-static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc,
+ char** rbuf, ErlDrvSizeT rsize)
{
char ifbuf[BUFSIZ];
char sbuf[BUFSIZ];
char* sptr;
INTERFACE_INFO* ifp;
DWORD len;
- int n;
+ ErlDrvSizeT n;
int err;
ifp = (INTERFACE_INFO*) ifbuf;
@@ -3942,8 +4198,8 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
/* input is an ip-address in string format i.e A.B.C.D
** scan the INTERFACE_LIST to get the options
*/
-static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, char* buf,
+ ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize)
{
char ifbuf[BUFSIZ];
int n;
@@ -4044,8 +4300,9 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
}
/* not supported */
-static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -4088,12 +4345,13 @@ static void free_ifconf(struct ifconf *ifcp) {
FREE(ifcp->ifc_buf);
}
-static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc,
+ char** rbuf, ErlDrvSizeT rsize)
{
struct ifconf ifc;
struct ifreq *ifrp;
char *sbuf, *sp;
- int i;
+ ErlDrvSizeT i;
/* Courtesy of Per Bergqvist and W. Richard Stevens */
@@ -4105,7 +4363,7 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
*sp++ = INET_REP_OK;
i = 0;
for (;;) {
- int n;
+ ErlDrvSizeT n;
ifrp = (struct ifreq *) VOIDP(ifc.ifc_buf + i);
n = sizeof(ifrp->ifr_name) + SIZEA(ifrp->ifr_addr);
@@ -4131,13 +4389,39 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
return sp - sbuf;
}
+#ifdef HAVE_LIBDLPI_H
+#include <libdlpi.h>
+static int hwaddr_libdlpi_lookup(const char *ifnm,
+ uchar_t *addr, size_t *alen)
+{
+ dlpi_handle_t handle;
+ dlpi_info_t linkinfo;
+ int ret = -1;
+
+ if (dlpi_open(ifnm, &handle, 0) != DLPI_SUCCESS) {
+ return -1;
+ }
+
+ if (dlpi_get_physaddr(handle, DL_CURR_PHYS_ADDR,
+ addr, alen) == DLPI_SUCCESS &&
+ dlpi_info(handle, &linkinfo, 0) == DLPI_SUCCESS)
+ {
+ ret = 0;
+ }
+
+ dlpi_close(handle);
+ return ret;
+}
+#endif
+
/* FIXME: temporary hack */
#ifndef IFHWADDRLEN
#define IFHWADDRLEN 6
#endif
-static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
char sbuf[BUFSIZ];
char* sptr;
@@ -4166,7 +4450,24 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
break;
case INET_IFOPT_HWADDR: {
-#ifdef SIOCGIFHWADDR
+#ifdef HAVE_LIBDLPI_H
+ /*
+ ** OpenSolaris have SIGCGIFHWADDR, but no ifr_hwaddr member..
+ ** The proper way to get the mac address would be to
+ ** use libdlpi...
+ */
+ uchar_t addr[DLPI_PHYSADDR_MAX];
+ size_t alen = sizeof(addr);
+
+ if (hwaddr_libdlpi_lookup(ifreq.ifr_name, addr, &alen) == 0) {
+ buf_check(sptr, s_end, 1+2+alen);
+ *sptr++ = INET_IFOPT_HWADDR;
+ put_int16(alen, sptr);
+ sptr += 2;
+ sys_memcpy(sptr, addr, alen);
+ sptr += alen;
+ }
+#elif defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR)
if (ioctl(desc->s, SIOCGIFHWADDR, (char *)&ifreq) < 0)
break;
buf_check(sptr, s_end, 1+2+IFHWADDRLEN);
@@ -4175,7 +4476,7 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
/* raw memcpy (fix include autoconf later) */
sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN);
sptr += IFHWADDRLEN;
-#elif defined(SIOCGENADDR)
+#elif defined(SIOCGENADDR) && defined(HAVE_STRUCT_IFREQ_IFR_ENADDR)
if (ioctl(desc->s, SIOCGENADDR, (char *)&ifreq) < 0)
break;
buf_check(sptr, s_end, 1+2+sizeof(ifreq.ifr_enaddr));
@@ -4314,8 +4615,9 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
}
-static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
struct ifreq ifreq;
int namlen;
@@ -4338,19 +4640,19 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
break;
case INET_IFOPT_HWADDR: {
- unsigned int len;
+ unsigned int hwalen;
buf_check(buf, b_end, 2);
- len = get_int16(buf); buf += 2;
- buf_check(buf, b_end, len);
+ hwalen = get_int16(buf); buf += 2;
+ buf_check(buf, b_end, hwalen);
#ifdef SIOCSIFHWADDR
/* raw memcpy (fix include autoconf later) */
sys_memset((char*)(&ifreq.ifr_hwaddr.sa_data),
'\0', sizeof(ifreq.ifr_hwaddr.sa_data));
- sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, len);
+ sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, hwalen);
(void) ioctl(desc->s, SIOCSIFHWADDR, (char *)&ifreq);
#endif
- buf += len;
+ buf += hwalen;
break;
}
@@ -4436,21 +4738,24 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
#else
-static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc,
+ char** rbuf, ErlDrvSizeT rsize)
{
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
-static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
-static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -4459,6 +4764,7 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len,
+#if defined(__WIN32__) || defined(HAVE_GETIFADDRS)
/* Latin-1 to utf8 */
static int utf8_len(const char *c, int m) {
@@ -4481,6 +4787,7 @@ static void utf8_encode(const char *c, int m, char *p) {
}
}
}
+#endif
#if defined(__WIN32__)
@@ -4505,8 +4812,8 @@ int eq_masked_bytes(char *a, char *b, int pref_len) {
return !0;
}
-static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
- char **rbuf_pp, int rsize)
+static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
+ char **rbuf_pp, ErlDrvSizeT rsize)
{
int i;
DWORD ret, n;
@@ -4516,7 +4823,7 @@ static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
char *buf_p;
char *buf_alloc_p;
- int buf_size =512;
+ ErlDrvSizeT buf_size = 512;
# define BUF_ENSURE(Size) \
do { \
int NEED_, GOT_ = buf_p - buf_alloc_p; \
@@ -4890,12 +5197,12 @@ done:
#elif defined(HAVE_GETIFADDRS)
-static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
- char **rbuf_pp, int rsize)
+static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
+ char **rbuf_pp, ErlDrvSizeT rsize)
{
struct ifaddrs *ifa_p, *ifa_free_p;
- int buf_size;
+ ErlDrvSizeT buf_size;
char *buf_p;
char *buf_alloc_p;
@@ -4998,8 +5305,8 @@ static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
#else
-static int inet_ctl_getifaddrs(inet_descriptor* desc_p,
- char **rbuf_pp, int rsize)
+static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
+ char **rbuf_pp, ErlDrvSizeT rsize)
{
return ctl_error(ENOTSUP, rbuf_pp, rsize);
}
@@ -5153,6 +5460,7 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
if (IS_SCTP(desc))
return sctp_set_opts(desc, ptr, len);
#endif
+ /* XXX { int i; for(i=0;i<len;++i) fprintf(stderr,"0x%02X, ", (unsigned) ptr[i]); fprintf(stderr,"\r\n");} */
while(len >= 5) {
opt = *ptr++;
@@ -5482,10 +5790,16 @@ skip_os_setopt:
if (desc->active != old_active)
sock_select(desc, (FD_READ|FD_CLOSE), (desc->active>0));
+ /* XXX: UDP sockets could also trigger immediate read here NIY */
if ((desc->stype==SOCK_STREAM) && desc->active) {
if (!old_active || (desc->htype != old_htype)) {
/* passive => active change OR header type change in active mode */
- return 1;
+ /* Return > 1 if only active changed to INET_ONCE -> direct read if
+ header type is unchanged. */
+ /* XXX fprintf(stderr,"desc->htype == %d, old_htype == %d,
+ desc->active == %d, old_active == %d\r\n",(int)desc->htype,
+ (int) old_htype, (int) desc->active, (int) old_active );*/
+ return 1+(desc->htype == old_htype && desc->active == INET_ONCE);
}
return 0;
}
@@ -5800,7 +6114,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
case SCTP_OPT_PRIMARY_ADDR:
case SCTP_OPT_SET_PEER_PRIMARY_ADDR:
{
- int alen;
+ ErlDrvSizeT alen;
char *after;
CHKLEN(curr, ASSOC_ID_LEN);
@@ -5842,7 +6156,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
}
case SCTP_OPT_PEER_ADDR_PARAMS:
{
- int alen;
+ ErlDrvSizeT alen;
char *after;
# ifdef HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_FLAGS
int eflags, cflags, hb_enable, hb_disable,
@@ -5929,6 +6243,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
type = SCTP_DEFAULT_SEND_PARAM;
arg_ptr = (char*) (&arg.sri);
arg_sz = sizeof ( arg.sri);
+ VALGRIND_MAKE_MEM_DEFINED(arg_ptr, arg_sz); /*suppress "uninitialised bytes"*/
break;
}
case SCTP_OPT_EVENTS:
@@ -5972,7 +6287,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
proto = IPPROTO_SCTP;
type = SCTP_DELAYED_ACK_TIME;
arg_ptr = (char*) (&arg.av);
- arg_sz = sizeof ( arg.es);
+ arg_sz = sizeof ( arg.av);
break;
}
# endif
@@ -6018,8 +6333,9 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
** ptr should point to a buffer with 9*len +1 to be safe!!
*/
-static int inet_fill_opts(inet_descriptor* desc,
- char* buf, int len, char** dest, int destlen)
+static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT len,
+ char** dest, ErlDrvSizeT destlen)
{
int type;
int proto;
@@ -6029,8 +6345,8 @@ static int inet_fill_opts(inet_descriptor* desc,
char* arg_ptr;
unsigned int arg_sz;
char *ptr = NULL;
- int dest_used = 0;
- int dest_allocated = destlen;
+ ErlDrvSizeT dest_used = 0;
+ ErlDrvSizeT dest_allocated = destlen;
char *orig_dest = *dest;
/* Ptr is a name parameter */
@@ -6045,7 +6361,7 @@ static int inet_fill_opts(inet_descriptor* desc,
#define PLACE_FOR(Size,Ptr) \
do { \
- int need = dest_used + (Size); \
+ ErlDrvSizeT need = dest_used + (Size); \
if (need > INET_MAX_OPT_BUFFER) { \
RETURN_ERROR(); \
} \
@@ -6066,7 +6382,7 @@ static int inet_fill_opts(inet_descriptor* desc,
/* Ptr is a name parameter */
#define TRUNCATE_TO(Size,Ptr) \
do { \
- int new_need = ((Ptr) - (*dest)) + (Size); \
+ ErlDrvSizeT new_need = ((Ptr) - (*dest)) + (Size); \
if (new_need > dest_used) { \
erl_exit(1,"Internal error in inet_drv, " \
"miscalculated buffer size"); \
@@ -6356,8 +6672,9 @@ static int load_paddrinfo (ErlDrvTermData * spec, int i,
/*
** "sctp_fill_opts": Returns {ok, Results}, or an error:
*/
-static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
- char** dest, int destlen)
+static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc,
+ char* buf, ErlDrvSizeT buflen,
+ char** dest, ErlDrvSizeT destlen)
{
/* In contrast to the generic "inet_fill_opts", the output here is
represented by tuples/records, which are formed in the "spec":
@@ -6736,7 +7053,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
2*LOAD_ATOM_CNT + LOAD_INT_CNT + 2*LOAD_TUPLE_CNT);
i = LOAD_ATOM (spec, i, am_sctp_adaptation_layer);
i = LOAD_ATOM (spec, i, am_sctp_setadaptation);
- i = LOAD_INT (spec, i, ad.ssb_adaptation_ind);
+ i = LOAD_INT (spec, i, sock_ntohl(ad.ssb_adaptation_ind));
i = LOAD_TUPLE (spec, i, 2);
i = LOAD_TUPLE (spec, i, 2);
break;
@@ -6747,7 +7064,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
unsigned int sz = sizeof(ap);
int n;
char *after;
- int alen;
+ ErlDrvSizeT alen;
if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL);
ap.spp_assoc_id = GET_ASSOC_ID(buf);
@@ -6879,7 +7196,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
break;
}
/* The following option is not available in Solaris 10: */
-# ifdef SCTP_DELAYED_ACK_TIME
+# if HAVE_DECL_SCTP_DELAYED_ACK_TIME
case SCTP_OPT_DELAYED_ACK_TIME:
{
struct sctp_assoc_value av;
@@ -6926,7 +7243,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
switch(st.sstat_state)
{
/* SCTP_EMPTY is not supported on SOLARIS10: */
-# ifdef SCTP_EMPTY
+# if HAVE_DECL_SCTP_EMPTY
case SCTP_EMPTY:
i = LOAD_ATOM (spec, i, am_empty);
break;
@@ -6934,14 +7251,16 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
case SCTP_CLOSED:
i = LOAD_ATOM (spec, i, am_closed);
break;
- /* The following states are not supported by Linux Kernel SCTP yet:
+# if HAVE_DECL_SCTP_BOUND
case SCTP_BOUND:
i = LOAD_ATOM (spec, i, am_bound);
break;
+# endif
+# if HAVE_DECL_SCTP_LISTEN
case SCTP_LISTEN:
i = LOAD_ATOM (spec, i, am_listen);
break;
- */
+# endif
case SCTP_COOKIE_WAIT:
i = LOAD_ATOM (spec, i, am_cookie_wait);
break;
@@ -6985,7 +7304,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
struct sctp_paddrinfo pai;
unsigned int sz = sizeof(pai);
char *after;
- int alen;
+ ErlDrvSizeT alen;
if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL);
pai.spinfo_assoc_id = GET_ASSOC_ID(buf);
@@ -7032,7 +7351,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
driver_send_term(desc->port, driver_caller(desc->port), spec, i);
FREE(spec);
- (*dest)[0] = INET_REP_SCTP;
+ (*dest)[0] = INET_REP;
return 1; /* Response length */
# undef PLACE_FOR
# undef RETURN_ERROR
@@ -7042,7 +7361,8 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
/* fill statistics reply, op codes from src and result in dest
** dst area must be a least 5*len + 1 bytes
*/
-static int inet_fill_stat(inet_descriptor* desc, char* src, int len, char* dst)
+static ErlDrvSSizeT inet_fill_stat(inet_descriptor* desc,
+ char* src, ErlDrvSizeT len, char* dst)
{
unsigned long val;
int op;
@@ -7075,7 +7395,7 @@ static int inet_fill_stat(inet_descriptor* desc, char* src, int len, char* dst)
val = (unsigned long) desc->send_avg;
break;
case INET_STAT_SEND_PND:
- val = driver_sizeq(desc->port);
+ val = (unsigned long) driver_sizeq(desc->port);
break;
case INET_STAT_RECV_OCT:
put_int32(desc->recv_oct[1], dst); /* write high 32bit */
@@ -7120,7 +7440,8 @@ send_empty_out_q_msgs(inet_descriptor* desc)
/* subscribe and fill subscription reply, op codes from src and
** result in dest dst area must be a least 5*len + 1 bytes
*/
-static int inet_subscribe(inet_descriptor* desc, char* src, int len, char* dst)
+static ErlDrvSSizeT inet_subscribe(inet_descriptor* desc,
+ char* src, ErlDrvSizeT len, char* dst)
{
unsigned long val;
int op;
@@ -7207,6 +7528,8 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
sys_memzero((char *)&desc->remote,sizeof(desc->remote));
+ desc->is_ignored = 0;
+
return (ErlDrvData)desc;
}
@@ -7218,14 +7541,14 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
/*
** common TCP/UDP/SCTP control command
*/
-static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
+ ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize)
{
switch (cmd) {
case INET_REQ_GETSTAT: {
char* dst;
- int i;
+ ErlDrvSizeT i;
int dstlen = 1; /* Reply code */
for (i = 0; i < len; i++) {
@@ -7265,7 +7588,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
}
case INET_REQ_GETOPTS: { /* get options */
- int replen;
+ ErlDrvSSizeT replen;
DEBUGF(("inet_ctl(%ld): GETOPTS\r\n", (long)desc->port));
#ifdef HAVE_SCTP
if (IS_SCTP(desc))
@@ -7310,17 +7633,27 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
case INET_REQ_SETOPTS: { /* set options */
DEBUGF(("inet_ctl(%ld): SETOPTS\r\n", (long)desc->port));
+ /* XXX fprintf(stderr,"inet_ctl(%ld): SETOPTS (len = %d)\r\n", (long)desc->port,(int) len); */
switch(inet_set_opts(desc, buf, len)) {
case -1:
return ctl_error(EINVAL, rbuf, rsize);
case 0:
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
- default: /* active/passive change!! */
+ case 1:
/*
* Let's hope that the descriptor really is a tcp_descriptor here.
*/
+ /* fprintf(stderr,"Triggered tcp_deliver by setopt.\r\n"); */
tcp_deliver((tcp_descriptor *) desc, 0);
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
+ default:
+ /* fprintf(stderr,"Triggered tcp_recv by setopt.\r\n"); */
+ /*
+ * Same as above, but active changed to once w/o header type
+ * change, so try a read instead of just deliver.
+ */
+ tcp_recv((tcp_descriptor *) desc, 0);
+ return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
}
@@ -7471,7 +7804,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
if (desc->state != INET_STATE_OPEN)
return ctl_xerror(EXBADPORT, rbuf, rsize);
- if (inet_set_address(desc->sfamily, &local, buf, &len) == NULL)
+ if (inet_set_faddress(desc->sfamily, &local, buf, &len) == NULL)
return ctl_error(EINVAL, rbuf, rsize);
if (IS_SOCKET_ERROR(sock_bind(desc->s,(struct sockaddr*) &local, len)))
@@ -7489,6 +7822,33 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
}
+ case INET_REQ_IGNOREFD: {
+ DEBUGF(("inet_ctl(%ld): IGNOREFD, IGNORED = %d\r\n",
+ (long)desc->port,(int)*buf));
+
+ /*
+ * FD can only be ignored for connected TCP connections for now,
+ * possible to add UDP and SCTP support if needed.
+ */
+ if (!IS_CONNECTED(desc))
+ return ctl_error(ENOTCONN, rbuf, rsize);
+
+ if (!desc->stype == SOCK_STREAM)
+ return ctl_error(EINVAL, rbuf, rsize);
+
+ if (*buf == 1 && !desc->is_ignored) {
+ sock_select(desc, (FD_READ|FD_WRITE|FD_CLOSE|ERL_DRV_USE_NO_CALLBACK), 0);
+ desc->is_ignored = INET_IGNORE_READ;
+ } else if (*buf == 0 && desc->is_ignored) {
+ int flags = (FD_READ|FD_CLOSE|((desc->is_ignored & INET_IGNORE_WRITE)?FD_WRITE:0));
+ desc->is_ignored = INET_IGNORE_NONE;
+ sock_select(desc, flags, 1);
+ } else
+ return ctl_error(EINVAL, rbuf, rsize);
+
+ return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
+ }
+
#ifndef VXWORKS
case INET_REQ_GETSERVBYNAME: { /* L1 Name-String L2 Proto-String */
@@ -7549,7 +7909,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len,
}
/* update statistics on output packets */
-static void inet_output_count(inet_descriptor* desc, int len)
+static void inet_output_count(inet_descriptor* desc, ErlDrvSizeT len)
{
unsigned long n = desc->send_cnt + 1;
unsigned long t = desc->send_oct[0] + len;
@@ -7569,7 +7929,7 @@ static void inet_output_count(inet_descriptor* desc, int len)
}
/* update statistics on input packets */
-static void inet_input_count(inet_descriptor* desc, int len)
+static void inet_input_count(inet_descriptor* desc, ErlDrvSizeT len)
{
unsigned long n = desc->recv_cnt + 1;
unsigned long t = desc->recv_oct[0] + len;
@@ -7692,7 +8052,7 @@ static void tcp_clear_input(tcp_descriptor* desc)
static void tcp_clear_output(tcp_descriptor* desc)
{
ErlDrvPort ix = desc->inet.port;
- int qsz = driver_sizeq(ix);
+ ErlDrvSizeT qsz = driver_sizeq(ix);
driver_deq(ix, qsz);
send_empty_out_q_msgs(INETP(desc));
@@ -7750,7 +8110,7 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args)
/* Copy a descriptor, by creating a new port with same settings
* as the descriptor desc.
- * return NULL on error (ENFILE no ports avail)
+ * return NULL on error (SYSTEM_LIMIT no ports avail)
*/
static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
ErlDrvTermData owner, int* err)
@@ -7789,7 +8149,7 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
/* The new port will be linked and connected to the original caller */
port = driver_create_port(port, owner, "tcp_inet", (ErlDrvData) copy_desc);
if ((long)port == -1) {
- *err = ENFILE;
+ *err = INET_ERRNO_SYSTEM_LIMIT;
FREE(copy_desc);
return NULL;
}
@@ -7807,22 +8167,22 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
static void tcp_close_check(tcp_descriptor* desc)
{
/* XXX:PaN - multiple clients to handle! */
- if (desc->inet.state == TCP_STATE_ACCEPTING) {
+ if (desc->inet.state == INET_STATE_ACCEPTING) {
inet_async_op *this_op = desc->inet.opt;
sock_select(INETP(desc), FD_ACCEPT, 0);
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
if (this_op != NULL) {
driver_demonitor_process(desc->inet.port, &(this_op->monitor));
}
async_error_am(INETP(desc), am_closed);
}
- else if (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ else if (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
int id,req;
ErlDrvTermData caller;
ErlDrvMonitor monitor;
sock_select(INETP(desc), FD_ACCEPT, 0);
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
while (deq_multi_op(desc,&id,&req,&caller,NULL,&monitor) == 0) {
driver_demonitor_process(desc->inet.port, &monitor);
send_async_error(desc->inet.port, desc->inet.dport, id, caller, am_closed);
@@ -7830,10 +8190,10 @@ static void tcp_close_check(tcp_descriptor* desc)
clean_multi_timers(&(desc->mtd), desc->inet.port);
}
- else if (desc->inet.state == TCP_STATE_CONNECTING) {
+ else if (desc->inet.state == INET_STATE_CONNECTING) {
async_error_am(INETP(desc), am_closed);
}
- else if (desc->inet.state == TCP_STATE_CONNECTED) {
+ else if (desc->inet.state == INET_STATE_CONNECTED) {
async_error_am_all(INETP(desc), am_closed);
}
}
@@ -7860,45 +8220,69 @@ static void tcp_inet_stop(ErlDrvData e)
/* TCP requests from Erlang */
-static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
+ char* buf, ErlDrvSizeT len,
+ char** rbuf, ErlDrvSizeT rsize)
{
tcp_descriptor* desc = (tcp_descriptor*)e;
+
switch(cmd) {
- case INET_REQ_OPEN: /* open socket and return internal index */
+ case INET_REQ_OPEN: { /* open socket and return internal index */
+ int domain;
DEBUGF(("tcp_inet_ctl(%ld): OPEN\r\n", (long)desc->inet.port));
- if ((len == 1) && (buf[0] == INET_AF_INET))
- return
- inet_ctl_open(INETP(desc), AF_INET, SOCK_STREAM, rbuf, rsize);
+ if (len != 2) return ctl_error(EINVAL, rbuf, rsize);
+ switch(buf[0]) {
+ case INET_AF_INET:
+ domain = AF_INET;
+ break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- else if ((len == 1) && (buf[0] == INET_AF_INET6))
- return
- inet_ctl_open(INETP(desc), AF_INET6, SOCK_STREAM, rbuf, rsize);
+ case INET_AF_INET6:
+ domain = AF_INET6;
+ break;
#else
- else if ((len == 1) && (buf[0] == INET_AF_INET6))
- return ctl_xerror("eafnosupport",rbuf,rsize);
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
#endif
- else
+ default:
return ctl_error(EINVAL, rbuf, rsize);
+ }
+ if (buf[1] != INET_TYPE_STREAM) return ctl_error(EINVAL, rbuf, rsize);
+ return inet_ctl_open(INETP(desc), domain, SOCK_STREAM, rbuf, rsize);
+ break;
+ }
- case INET_REQ_FDOPEN: /* pass in an open socket */
- DEBUGF(("tcp_inet_ctl(%ld): FDOPEN\r\n", (long)desc->inet.port));
- if ((len == 5) && (buf[0] == INET_AF_INET))
- return inet_ctl_fdopen(INETP(desc), AF_INET, SOCK_STREAM,
- (SOCKET) get_int32(buf+1), rbuf, rsize);
+ case INET_REQ_FDOPEN: { /* pass in an open socket */
+ int domain;
+ DEBUGF(("tcp_inet_ctl(%ld): FDOPEN\r\n", (long)desc->inet.port));
+ if (len != 6) return ctl_error(EINVAL, rbuf, rsize);
+ switch(buf[0]) {
+ case INET_AF_INET:
+ domain = AF_INET;
+ break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- else if ((len == 5) && (buf[0] == INET_AF_INET6))
- return inet_ctl_fdopen(INETP(desc), AF_INET6, SOCK_STREAM,
- (SOCKET) get_int32(buf+1), rbuf, rsize);
+ case INET_AF_INET6:
+ domain = AF_INET6;
+ break;
+#else
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
#endif
- else
+ default:
return ctl_error(EINVAL, rbuf, rsize);
+ }
+ if (buf[1] != INET_TYPE_STREAM) return ctl_error(EINVAL, rbuf, rsize);
+ return inet_ctl_fdopen(INETP(desc), domain, SOCK_STREAM,
+ (SOCKET) get_int32(buf+2), rbuf, rsize);
+ break;
+ }
- case TCP_REQ_LISTEN: { /* argument backlog */
+ case INET_REQ_LISTEN: { /* argument backlog */
int backlog;
DEBUGF(("tcp_inet_ctl(%ld): LISTEN\r\n", (long)desc->inet.port));
- if (desc->inet.state == TCP_STATE_CLOSED)
+ if (desc->inet.state == INET_STATE_CLOSED)
return ctl_xerror(EXBADPORT, rbuf, rsize);
if (!IS_OPEN(INETP(desc)))
return ctl_xerror(EXBADPORT, rbuf, rsize);
@@ -7909,7 +8293,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
backlog = get_int16(buf);
if (IS_SOCKET_ERROR(sock_listen(desc->inet.s, backlog)))
return ctl_error(sock_errno(), rbuf, rsize);
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -7945,13 +8329,13 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
((sock_errno() == ERRNO_BLOCK) || /* Winsock2 */
(sock_errno() == EINPROGRESS))) { /* Unix & OSE!! */
sock_select(INETP(desc), FD_CONNECT, 1);
- desc->inet.state = TCP_STATE_CONNECTING;
+ desc->inet.state = INET_STATE_CONNECTING;
if (timeout != INET_INFINITY)
driver_set_timer(desc->inet.port, timeout);
enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
}
else if (code == 0) { /* ok we are connected */
- desc->inet.state = TCP_STATE_CONNECTED;
+ desc->inet.state = INET_STATE_CONNECTED;
if (desc->inet.active)
sock_select(INETP(desc), (FD_READ|FD_CLOSE), 1);
enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
@@ -7963,7 +8347,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
}
- case TCP_REQ_ACCEPT: { /* do async accept */
+ case INET_REQ_ACCEPT: { /* do async accept */
char tbuf[2];
unsigned timeout;
inet_address remote;
@@ -7973,14 +8357,14 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
DEBUGF(("tcp_inet_ctl(%ld): ACCEPT\r\n", (long)desc->inet.port));
/* INPUT: Timeout(4) */
- if ((desc->inet.state != TCP_STATE_LISTEN && desc->inet.state != TCP_STATE_ACCEPTING &&
- desc->inet.state != TCP_STATE_MULTI_ACCEPTING) || len != 4) {
+ if ((desc->inet.state != INET_STATE_LISTENING && desc->inet.state != INET_STATE_ACCEPTING &&
+ desc->inet.state != INET_STATE_MULTI_ACCEPTING) || len != 4) {
return ctl_error(EINVAL, rbuf, rsize);
}
timeout = get_int32(buf);
- if (desc->inet.state == TCP_STATE_ACCEPTING) {
+ if (desc->inet.state == INET_STATE_ACCEPTING) {
unsigned long time_left = 0;
int oid = 0;
ErlDrvTermData ocaller = ERL_DRV_NIL;
@@ -8009,10 +8393,10 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
mtd = add_multi_timer(&(desc->mtd), desc->inet.port, caller,
timeout, &tcp_inet_multi_timeout);
}
- enq_multi_op(desc, tbuf, TCP_REQ_ACCEPT, caller, mtd, &monitor);
- desc->inet.state = TCP_STATE_MULTI_ACCEPTING;
+ enq_multi_op(desc, tbuf, INET_REQ_ACCEPT, caller, mtd, &monitor);
+ desc->inet.state = INET_STATE_MULTI_ACCEPTING;
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
- } else if (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ } else if (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
ErlDrvTermData caller = driver_caller(desc->inet.port);
MultiTimerData *mtd = NULL;
ErlDrvMonitor monitor;
@@ -8024,7 +8408,7 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
mtd = add_multi_timer(&(desc->mtd), desc->inet.port, caller,
timeout, &tcp_inet_multi_timeout);
}
- enq_multi_op(desc, tbuf, TCP_REQ_ACCEPT, caller, mtd, &monitor);
+ enq_multi_op(desc, tbuf, INET_REQ_ACCEPT, caller, mtd, &monitor);
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
} else {
n = sizeof(desc->inet.remote);
@@ -8036,8 +8420,8 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
&monitor) != 0) {
return ctl_xerror("noproc", rbuf, rsize);
}
- enq_async_w_tmo(INETP(desc), tbuf, TCP_REQ_ACCEPT, timeout, &monitor);
- desc->inet.state = TCP_STATE_ACCEPTING;
+ enq_async_w_tmo(INETP(desc), tbuf, INET_REQ_ACCEPT, timeout, &monitor);
+ desc->inet.state = INET_STATE_ACCEPTING;
sock_select(INETP(desc),FD_ACCEPT,1);
if (timeout != INET_INFINITY) {
driver_set_timer(desc->inet.port, timeout);
@@ -8064,8 +8448,8 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
driver_select(accept_desc->inet.port, accept_desc->inet.event,
ERL_DRV_READ, 1);
#endif
- accept_desc->inet.state = TCP_STATE_CONNECTED;
- enq_async(INETP(desc), tbuf, TCP_REQ_ACCEPT);
+ accept_desc->inet.state = INET_STATE_CONNECTED;
+ enq_async(INETP(desc), tbuf, INET_REQ_ACCEPT);
async_ok_port(INETP(desc), accept_desc->inet.dport);
}
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
@@ -8107,13 +8491,14 @@ static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
if (enq_async(INETP(desc), tbuf, TCP_REQ_RECV) < 0)
return ctl_error(EALREADY, rbuf, rsize);
- if (tcp_recv(desc, n) == 0) {
+ if (INETP(desc)->is_ignored || tcp_recv(desc, n) == 0) {
if (timeout == 0)
async_error_am(INETP(desc), am_timeout);
else {
if (timeout != INET_INFINITY)
- driver_set_timer(desc->inet.port, timeout);
- sock_select(INETP(desc),(FD_READ|FD_CLOSE),1);
+ driver_set_timer(desc->inet.port, timeout);
+ if (!INETP(desc)->is_ignored)
+ sock_select(INETP(desc),(FD_READ|FD_CLOSE),1);
}
}
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
@@ -8171,7 +8556,7 @@ static void tcp_inet_timeout(ErlDrvData e)
(long)desc->inet.port, desc->inet.s));
if ((state & INET_F_MULTI_CLIENT)) { /* Multi-client always means multi-timers */
fire_multi_timers(&(desc->mtd), desc->inet.port, e);
- } else if ((state & TCP_STATE_CONNECTED) == TCP_STATE_CONNECTED) {
+ } else if ((state & INET_STATE_CONNECTED) == INET_STATE_CONNECTED) {
if (desc->busy_on_send) {
ASSERT(IS_BUSY(INETP(desc)));
desc->inet.caller = desc->inet.busy_caller;
@@ -8191,20 +8576,20 @@ static void tcp_inet_timeout(ErlDrvData e)
async_error_am(INETP(desc), am_timeout);
}
}
- else if ((state & TCP_STATE_CONNECTING) == TCP_STATE_CONNECTING) {
+ else if ((state & INET_STATE_CONNECTING) == INET_STATE_CONNECTING) {
/* assume connect timeout */
/* close the socket since it's not usable (see man pages) */
erl_inet_close(INETP(desc));
async_error_am(INETP(desc), am_timeout);
}
- else if ((state & TCP_STATE_ACCEPTING) == TCP_STATE_ACCEPTING) {
+ else if ((state & INET_STATE_ACCEPTING) == INET_STATE_ACCEPTING) {
inet_async_op *this_op = desc->inet.opt;
/* timer is set on accept */
sock_select(INETP(desc), FD_ACCEPT, 0);
if (this_op != NULL) {
driver_demonitor_process(desc->inet.port, &(this_op->monitor));
}
- desc->inet.state = TCP_STATE_LISTEN;
+ desc->inet.state = INET_STATE_LISTENING;
async_error_am(INETP(desc), am_timeout);
}
DEBUGF(("tcp_inet_timeout(%ld) }\r\n", (long)desc->inet.port));
@@ -8222,7 +8607,7 @@ static void tcp_inet_multi_timeout(ErlDrvData e, ErlDrvTermData caller)
driver_demonitor_process(desc->inet.port, &monitor);
if (desc->multi_first == NULL) {
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
send_async_error(desc->inet.port, desc->inet.dport, id, caller, am_timeout);
}
@@ -8238,7 +8623,7 @@ static void tcp_inet_multi_timeout(ErlDrvData e, ErlDrvTermData caller)
** but distribution still uses the tcp_inet_command!!
*/
-static void tcp_inet_command(ErlDrvData e, char *buf, int len)
+static void tcp_inet_command(ErlDrvData e, char *buf, ErlDrvSizeT len)
{
tcp_descriptor* desc = (tcp_descriptor*)e;
desc->inet.caller = driver_caller(desc->inet.port);
@@ -8288,7 +8673,7 @@ static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp)
ErlDrvTermData who = driver_get_monitored_process(desc->inet.port,monitorp);
int state = desc->inet.state;
- if ((state & TCP_STATE_MULTI_ACCEPTING) == TCP_STATE_MULTI_ACCEPTING) {
+ if ((state & INET_STATE_MULTI_ACCEPTING) == INET_STATE_MULTI_ACCEPTING) {
int id,req;
MultiTimerData *timeout;
if (remove_multi_op(desc, &id, &req, who, &timeout, NULL) != 0) {
@@ -8299,15 +8684,15 @@ static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp)
}
if (desc->multi_first == NULL) {
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
- } else if ((state & TCP_STATE_ACCEPTING) == TCP_STATE_ACCEPTING) {
+ } else if ((state & INET_STATE_ACCEPTING) == INET_STATE_ACCEPTING) {
int did,drid;
ErlDrvTermData dcaller;
deq_async(INETP(desc), &did, &dcaller, &drid);
driver_cancel_timer(desc->inet.port);
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
}
@@ -8457,8 +8842,15 @@ static int tcp_remain(tcp_descriptor* desc, int* len)
else if (tlen == 0) { /* need unknown more */
*len = 0;
if (nsz == 0) {
- if (nfill == n)
- goto error;
+ if (nfill == n) {
+ if (desc->inet.psize != 0 && desc->inet.psize > nfill) {
+ if (tcp_expand_buffer(desc, desc->inet.psize) < 0)
+ return -1;
+ return desc->inet.psize;
+ }
+ else
+ goto error;
+ }
DEBUGF((" => restart more=%d\r\n", nfill - n));
return nfill - n;
}
@@ -8497,32 +8889,29 @@ static int tcp_deliver(tcp_descriptor* desc, int len)
}
while (len > 0) {
- int code = 0;
+ int code;
inet_input_count(INETP(desc), len);
/* deliver binary? */
if (len*4 >= desc->i_buf->orig_size*3) { /* >=75% */
+ code = tcp_reply_binary_data(desc, desc->i_buf,
+ (desc->i_ptr_start -
+ desc->i_buf->orig_bytes),
+ len);
+ if (code < 0)
+ return code;
+
/* something after? */
if (desc->i_ptr_start + len == desc->i_ptr) { /* no */
- code = tcp_reply_binary_data(desc, desc->i_buf,
- (desc->i_ptr_start -
- desc->i_buf->orig_bytes),
- len);
tcp_clear_input(desc);
}
else { /* move trail to beginning of a new buffer */
- ErlDrvBinary* bin;
+ ErlDrvBinary* bin = alloc_buffer(desc->i_bufsz);
char* ptr_end = desc->i_ptr_start + len;
int sz = desc->i_ptr - ptr_end;
- bin = alloc_buffer(desc->i_bufsz);
memcpy(bin->orig_bytes, ptr_end, sz);
-
- code = tcp_reply_binary_data(desc, desc->i_buf,
- (desc->i_ptr_start-
- desc->i_buf->orig_bytes),
- len);
free_buffer(desc->i_buf);
desc->i_buf = bin;
desc->i_ptr_start = desc->i_buf->orig_bytes;
@@ -8534,17 +8923,15 @@ static int tcp_deliver(tcp_descriptor* desc, int len)
code = tcp_reply_data(desc, desc->i_ptr_start, len);
/* XXX The buffer gets thrown away on error (code < 0) */
/* Windows needs workaround for this in tcp_inet_event... */
+ if (code < 0)
+ return code;
desc->i_ptr_start += len;
if (desc->i_ptr_start == desc->i_ptr)
tcp_clear_input(desc);
else
desc->i_remain = 0;
-
}
- if (code < 0)
- return code;
-
count++;
len = 0;
@@ -8849,8 +9236,8 @@ static void tcp_inet_event(ErlDrvData e, ErlDrvEvent event)
/* socket has input:
-** 1. TCP_STATE_ACCEPTING => non block accept ?
-** 2. TCP_STATE_CONNECTED => read input
+** 1. INET_STATE_ACCEPTING => non block accept ?
+** 2. INET_STATE_CONNECTED => read input
*/
static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
{
@@ -8858,8 +9245,10 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
#ifdef DEBUG
long port = (long) desc->inet.port; /* Used after driver_exit() */
#endif
+ ASSERT(!INETP(desc)->is_ignored);
DEBUGF(("tcp_inet_input(%ld) {s=%d\r\n", port, desc->inet.s));
- if (desc->inet.state == TCP_STATE_ACCEPTING) {
+ /* XXX fprintf(stderr,"tcp_inet_input(%ld) {s=%d}\r\n",(long) desc->inet.port, desc->inet.s); */
+ if (desc->inet.state == INET_STATE_ACCEPTING) {
SOCKET s;
unsigned int len;
inet_address remote;
@@ -8874,7 +9263,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
}
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
if (this_op != NULL) {
driver_demonitor_process(desc->inet.port, &(this_op->monitor));
@@ -8914,11 +9303,11 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
driver_select(accept_desc->inet.port, accept_desc->inet.event,
ERL_DRV_READ, 1);
#endif
- accept_desc->inet.state = TCP_STATE_CONNECTED;
+ accept_desc->inet.state = INET_STATE_CONNECTED;
ret = async_ok_port(INETP(desc), accept_desc->inet.dport);
goto done;
}
- } else if (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ } else if (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
SOCKET s;
unsigned int len;
inet_address remote;
@@ -8930,7 +9319,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
int times = 0;
#endif
- while (desc->inet.state == TCP_STATE_MULTI_ACCEPTING) {
+ while (desc->inet.state == INET_STATE_MULTI_ACCEPTING) {
len = sizeof(desc->inet.remote);
s = sock_accept(desc->inet.s, (struct sockaddr*) &remote, &len);
@@ -8950,7 +9339,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
if (desc->multi_first == NULL) {
sock_select(INETP(desc),FD_ACCEPT,0);
- desc->inet.state = TCP_STATE_LISTEN; /* restore state */
+ desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
if (timeout != NULL) {
@@ -8981,7 +9370,7 @@ static int tcp_inet_input(tcp_descriptor* desc, HANDLE event)
driver_select(accept_desc->inet.port, accept_desc->inet.event,
ERL_DRV_READ, 1);
#endif
- accept_desc->inet.state = TCP_STATE_CONNECTED;
+ accept_desc->inet.state = INET_STATE_CONNECTED;
ret = send_async_ok_port(desc->inet.port, desc->inet.dport,
id, caller, accept_desc->inet.dport);
}
@@ -9064,12 +9453,12 @@ static int tcp_send_error(tcp_descriptor* desc, int err)
*/
static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev)
{
- int sz;
+ ErlDrvSizeT sz;
char buf[4];
- int h_len;
- int n;
+ ErlDrvSizeT h_len;
+ ssize_t n;
ErlDrvPort ix = desc->inet.port;
- int len = ev->size;
+ ErlDrvSizeT len = ev->size;
switch(desc->inet.htype) {
case TCP_PB_1:
@@ -9117,9 +9506,13 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev)
else {
int vsize = (ev->vsize > MAX_VSIZE) ? MAX_VSIZE : ev->vsize;
- DEBUGF(("tcp_sendv(%ld): s=%d, about to send %d,%d bytes\r\n",
- (long)desc->inet.port, desc->inet.s, h_len, len));
- if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) {
+ DEBUGF(("tcp_sendv(%ld): s=%d, about to send "LLU","LLU" bytes\r\n",
+ (long)desc->inet.port, desc->inet.s, (llu_t)h_len, (llu_t)len));
+
+ if (INETP(desc)->is_ignored) {
+ INETP(desc)->is_ignored |= INET_IGNORE_WRITE;
+ n = 0;
+ } else if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) {
n = 0;
} else if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s, ev->iov,
vsize, &n, 0))) {
@@ -9140,14 +9533,17 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev)
return 0;
}
else {
- DEBUGF(("tcp_sendv(%ld): s=%d, only sent %d/%d of %d/%d bytes/items\r\n",
- (long)desc->inet.port, desc->inet.s, n, vsize, ev->size, ev->vsize));
+ DEBUGF(("tcp_sendv(%ld): s=%d, only sent "
+ LLU"/%d of "LLU"/%d bytes/items\r\n",
+ (long)desc->inet.port, desc->inet.s,
+ (llu_t)n, vsize, (llu_t)ev->size, ev->vsize));
}
DEBUGF(("tcp_sendv(%ld): s=%d, Send failed, queuing\r\n",
(long)desc->inet.port, desc->inet.s));
driver_enqv(ix, ev, n);
- sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1);
+ if (!INETP(desc)->is_ignored)
+ sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1);
}
return 0;
}
@@ -9155,7 +9551,7 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev)
/*
** Send non blocking data
*/
-static int tcp_send(tcp_descriptor* desc, char* ptr, int len)
+static int tcp_send(tcp_descriptor* desc, char* ptr, ErlDrvSizeT len)
{
int sz;
char buf[4];
@@ -9210,9 +9606,12 @@ static int tcp_send(tcp_descriptor* desc, char* ptr, int len)
iov[1].iov_base = ptr;
iov[1].iov_len = len;
- DEBUGF(("tcp_send(%ld): s=%d, about to send %d,%d bytes\r\n",
- (long)desc->inet.port, desc->inet.s, h_len, len));
- if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) {
+ DEBUGF(("tcp_send(%ld): s=%d, about to send "LLU","LLU" bytes\r\n",
+ (long)desc->inet.port, desc->inet.s, (llu_t)h_len, (llu_t)len));
+ if (INETP(desc)->is_ignored) {
+ INETP(desc)->is_ignored |= INET_IGNORE_WRITE;
+ n = 0;
+ } else if (desc->tcp_add_flags & TCP_ADDF_DELAY_SEND) {
sock_send(desc->inet.s, buf, 0, 0);
n = 0;
} else if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s,iov,2,&n,0))) {
@@ -9243,7 +9642,8 @@ static int tcp_send(tcp_descriptor* desc, char* ptr, int len)
n -= h_len;
driver_enq(ix, ptr+n, len-n);
}
- sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1);
+ if (!INETP(desc)->is_ignored)
+ sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1);
}
return 0;
}
@@ -9259,17 +9659,18 @@ static void tcp_inet_drv_input(ErlDrvData data, ErlDrvEvent event)
}
/* socket ready for ouput:
-** 1. TCP_STATE_CONNECTING => non block connect ?
-** 2. TCP_STATE_CONNECTED => write output
+** 1. INET_STATE_CONNECTING => non block connect ?
+** 2. INET_STATE_CONNECTED => write output
*/
static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
{
int ret = 0;
ErlDrvPort ix = desc->inet.port;
+ ASSERT(!INETP(desc)->is_ignored);
DEBUGF(("tcp_inet_output(%ld) {s=%d\r\n",
(long)desc->inet.port, desc->inet.s));
- if (desc->inet.state == TCP_STATE_CONNECTING) {
+ if (desc->inet.state == INET_STATE_CONNECTING) {
sock_select(INETP(desc),FD_CONNECT,0);
driver_cancel_timer(ix); /* posssibly cancel a timer */
@@ -9289,7 +9690,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
(struct sockaddr*) &desc->inet.remote, &sz);
if (IS_SOCKET_ERROR(code)) {
- desc->inet.state = TCP_STATE_BOUND; /* restore state */
+ desc->inet.state = INET_STATE_BOUND; /* restore state */
ret = async_error(INETP(desc), sock_errno());
goto done;
}
@@ -9302,7 +9703,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
(void *)&error, &sz);
if ((code < 0) || error) {
- desc->inet.state = TCP_STATE_BOUND; /* restore state */
+ desc->inet.state = INET_STATE_BOUND; /* restore state */
ret = async_error(INETP(desc), error);
goto done;
}
@@ -9310,7 +9711,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
#endif /* SO_ERROR */
#endif /* !__WIN32__ */
- desc->inet.state = TCP_STATE_CONNECTED;
+ desc->inet.state = INET_STATE_CONNECTED;
if (desc->inet.active)
sock_select(INETP(desc),(FD_READ|FD_CLOSE),1);
async_ok(INETP(desc));
@@ -9318,7 +9719,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
else if (IS_CONNECTED(INETP(desc))) {
for (;;) {
int vsize;
- int n;
+ ssize_t n;
SysIOVec* iov;
if ((iov = driver_peekq(ix, &vsize)) == NULL) {
@@ -9410,6 +9811,59 @@ static int should_use_so_bsdcompat(void)
#endif /* __linux__ */
#endif /* HAVE_SO_BSDCOMPAT */
+
+
+#ifdef HAVE_SCTP
+/* Copy a descriptor, by creating a new port with same settings
+ * as the descriptor desc.
+ * return NULL on error (ENFILE no ports avail)
+ */
+static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s, int* err)
+{
+ ErlDrvPort port = desc->inet.port;
+ udp_descriptor* copy_desc;
+
+ copy_desc = (udp_descriptor*) sctp_inet_start(port, NULL);
+
+ /* Setup event if needed */
+ if ((copy_desc->inet.s = s) != INVALID_SOCKET) {
+ if ((copy_desc->inet.event = sock_create_event(INETP(copy_desc))) ==
+ INVALID_EVENT) {
+ *err = sock_errno();
+ FREE(copy_desc);
+ return NULL;
+ }
+ }
+
+ /* Some flags must be inherited at this point */
+ copy_desc->inet.mode = desc->inet.mode;
+ copy_desc->inet.exitf = desc->inet.exitf;
+ copy_desc->inet.bit8f = desc->inet.bit8f;
+ copy_desc->inet.deliver = desc->inet.deliver;
+ copy_desc->inet.htype = desc->inet.htype;
+ copy_desc->inet.psize = desc->inet.psize;
+ copy_desc->inet.stype = desc->inet.stype;
+ copy_desc->inet.sfamily = desc->inet.sfamily;
+ copy_desc->inet.hsz = desc->inet.hsz;
+ copy_desc->inet.bufsz = desc->inet.bufsz;
+
+ /* The new port will be linked and connected to the caller */
+ port = driver_create_port(port, desc->inet.caller, "sctp_inet",
+ (ErlDrvData) copy_desc);
+ if ((long)port == -1) {
+ *err = ENFILE;
+ FREE(copy_desc);
+ return NULL;
+ }
+ copy_desc->inet.port = port;
+ copy_desc->inet.dport = driver_mk_port(port);
+ *err = 0;
+ return copy_desc;
+}
+#endif
+
+
+
static int packet_inet_init()
{
return 0;
@@ -9428,6 +9882,9 @@ static ErlDrvData packet_inet_start(ErlDrvPort port, char* args, int protocol)
return ERL_DRV_ERROR_ERRNO;
desc->read_packets = INET_PACKET_POLL;
+ desc->i_bufsz = 0;
+ desc->i_buf = NULL;
+ desc->i_ptr = NULL;
return drvd;
}
@@ -9452,6 +9909,10 @@ static void packet_inet_stop(ErlDrvData e)
*/
udp_descriptor * udesc = (udp_descriptor*) e;
inet_descriptor* descr = INETP(udesc);
+ if (udesc->i_buf != NULL) {
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
+ }
ASSERT(NO_SUBSCRIBERS(&(descr->empty_out_q_subs)));
inet_stop(descr);
@@ -9469,28 +9930,38 @@ static int packet_error(udp_descriptor* udesc, int err)
/*
** Various functions accessible via "port_control" on the Erlang side:
*/
-static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
- char** rbuf, int rsize)
+static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
+ ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize)
{
- int replen;
+ ErlDrvSSizeT replen;
udp_descriptor * udesc = (udp_descriptor *) e;
inet_descriptor* desc = INETP(udesc);
int type = SOCK_DGRAM;
- int af;
-#ifdef HAVE_SCTP
- if (IS_SCTP(desc)) type = SOCK_SEQPACKET;
-#endif
+ int af = AF_INET;
switch(cmd) {
case INET_REQ_OPEN: /* open socket and return internal index */
DEBUGF(("packet_inet_ctl(%ld): OPEN\r\n", (long)desc->port));
- if (len != 1) {
+ if (len != 2) {
return ctl_error(EINVAL, rbuf, rsize);
}
switch (buf[0]) {
case INET_AF_INET: af = AF_INET; break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- case INET_AF_INET6: af = AF_INET6; break;
+ case INET_AF_INET6: af = AF_INET6; break;
+#else
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
+#endif
+ default:
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ switch (buf[1]) {
+ case INET_TYPE_STREAM: type = SOCK_STREAM; break;
+ case INET_TYPE_DGRAM: type = SOCK_DGRAM; break;
+#ifdef HAVE_SCTP
+ case INET_TYPE_SEQPACKET: type = SOCK_SEQPACKET; break;
#endif
default:
return ctl_error(EINVAL, rbuf, rsize);
@@ -9517,18 +9988,35 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
return replen;
- case INET_REQ_FDOPEN: /* pass in an open (and bound) socket */
+ case INET_REQ_FDOPEN: { /* pass in an open (and bound) socket */
+ SOCKET s;
DEBUGF(("packet inet_ctl(%ld): FDOPEN\r\n", (long)desc->port));
- if ((len == 5) && (buf[0] == INET_AF_INET))
- replen = inet_ctl_fdopen(desc, AF_INET, SOCK_DGRAM,
- (SOCKET)get_int32(buf+1),rbuf,rsize);
+ if (len != 6) {
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ switch (buf[0]) {
+ case INET_AF_INET: af = AF_INET; break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- else if ((len == 5) && (buf[0] == INET_AF_INET6))
- replen = inet_ctl_fdopen(desc, AF_INET6, SOCK_DGRAM,
- (SOCKET)get_int32(buf+1),rbuf,rsize);
+ case INET_AF_INET6: af = AF_INET6; break;
+#else
+ case INET_AF_INET6:
+ return ctl_xerror("eafnosupport", rbuf, rsize);
+ break;
#endif
- else
+ default:
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ switch (buf[1]) {
+ case INET_TYPE_STREAM: type = SOCK_STREAM; break;
+ case INET_TYPE_DGRAM: type = SOCK_DGRAM; break;
+#ifdef HAVE_SCTP
+ case INET_TYPE_SEQPACKET: type = SOCK_SEQPACKET; break;
+#endif
+ default:
return ctl_error(EINVAL, rbuf, rsize);
+ }
+ s = (SOCKET)get_int32(buf+2);
+ replen = inet_ctl_fdopen(desc, af, type, s, rbuf, rsize);
if ((*rbuf)[0] != INET_REP_ERROR) {
if (desc->active)
@@ -9548,13 +10036,13 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
#endif
}
return replen;
+ }
case INET_REQ_CLOSE:
DEBUGF(("packet_inet_ctl(%ld): CLOSE\r\n", (long)desc->port));
erl_inet_close(desc);
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
- return 0;
case INET_REQ_CONNECT: {
@@ -9567,8 +10055,9 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
*/
int code;
char tbuf[2];
+#ifdef HAVE_SCTP
unsigned timeout;
-
+#endif
DEBUGF(("packet_inet_ctl(%ld): CONNECT\r\n", (long)desc->port));
/* INPUT: [ Timeout(4), Port(2), Address(N) ] */
@@ -9600,14 +10089,14 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
if (IS_SOCKET_ERROR(code) && (sock_errno() == EINPROGRESS)) {
/* XXX: Unix only -- WinSock would have a different cond! */
- desc->state = SCTP_STATE_CONNECTING;
+ desc->state = INET_STATE_CONNECTING;
if (timeout != INET_INFINITY)
driver_set_timer(desc->port, timeout);
enq_async(desc, tbuf, INET_REQ_CONNECT);
}
else if (code == 0) { /* OK we are connected */
sock_select(desc, FD_CONNECT, 0);
- desc->state = PACKET_STATE_CONNECTED;
+ desc->state = INET_STATE_CONNECTED;
enq_async(desc, tbuf, INET_REQ_CONNECT);
async_ok(desc);
}
@@ -9629,7 +10118,7 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
else if (len < 6)
return ctl_error(EINVAL, rbuf, rsize);
else {
- timeout = get_int32(buf); /* IGNORED */
+ /* Ignore timeout */
buf += 4;
len -= 4;
if (inet_set_address(desc->sfamily,
@@ -9653,11 +10142,11 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
}
#ifdef HAVE_SCTP
- case SCTP_REQ_LISTEN:
+ case INET_REQ_LISTEN:
{ /* LISTEN is only for SCTP sockets, not UDP. This code is borrowed
from the TCP section. Returns: {ok,[]} on success.
*/
- int flag;
+ int backlog;
DEBUGF(("packet_inet_ctl(%ld): LISTEN\r\n", (long)desc->port));
if (!IS_SCTP(desc))
@@ -9667,26 +10156,26 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
if (!IS_BOUND(desc))
return ctl_xerror(EXBADSEQ, rbuf, rsize);
- /* The arg is a binary value: 1:enable, 0:disable */
- if (len != 1)
+ if (len != 2)
return ctl_error(EINVAL, rbuf, rsize);
- flag = get_int8(buf);
+ backlog = get_int16(buf);
- if (IS_SOCKET_ERROR(sock_listen(desc->s, flag)))
+ if (IS_SOCKET_ERROR(sock_listen(desc->s, backlog)))
return ctl_error(sock_errno(), rbuf, rsize);
- desc->state = SCTP_STATE_LISTEN; /* XXX: not used? */
+ desc->state = INET_STATE_LISTENING; /* XXX: not used? */
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
case SCTP_REQ_BINDX:
{ /* Multi-homing bind for SCTP: */
- /* Construct the list of addresses we bind to. The curr limit is
- 256 addrs. Buff structure: Flags(1), ListItem,...:
+ /* Add additional addresses by calling sctp_bindx with one address
+ at a time, since this is what some OSes promise will work.
+ Buff structure: Flags(1), ListItem,...:
*/
- struct sockaddr addrs[256];
+ inet_address addr;
char* curr;
- int add_flag, n, rflag;
+ int add_flag, rflag;
if (!IS_SCTP(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
@@ -9695,32 +10184,67 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len,
add_flag = get_int8(curr);
curr++;
- for(n=0; n < 256 && curr < buf+len; n++)
+ /* Make the real flags: */
+ rflag = add_flag ? SCTP_BINDX_ADD_ADDR : SCTP_BINDX_REM_ADDR;
+
+ while (curr < buf+len)
{
- /* List item format: Port(2), IP(4|16) -- compatible with
- "inet_set_address": */
- inet_address tmp;
- int alen = buf + len - curr;
- curr = inet_set_address(desc->sfamily, &tmp, curr, &alen);
+ /* List item format: see "inet_set_faddress": */
+ ErlDrvSizeT alen = buf + len - curr;
+ curr = inet_set_faddress(desc->sfamily, &addr, curr, &alen);
if (curr == NULL)
return ctl_error(EINVAL, rbuf, rsize);
- /* Now: we need to squeeze "tmp" into the size of "sockaddr",
- which is smaller than "tmp" for IPv6 (extra IN6 info will
- be cut off): */
- memcpy(addrs + n, &tmp, sizeof(struct sockaddr));
+ /* Invoke the call: */
+ if (p_sctp_bindx(desc->s, (struct sockaddr *)&addr, 1,
+ rflag) < 0)
+ return ctl_error(sock_errno(), rbuf, rsize);
}
- /* Make the real flags: */
- rflag = add_flag ? SCTP_BINDX_ADD_ADDR : SCTP_BINDX_REM_ADDR;
-
- /* Invoke the call: */
- if (p_sctp_bindx(desc->s, addrs, n, rflag) < 0)
- return ctl_error(sock_errno(), rbuf, rsize);
desc->state = INET_STATE_BOUND;
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
+
+ case SCTP_REQ_PEELOFF:
+ {
+ Uint32 assoc_id;
+ udp_descriptor* new_udesc;
+ int err;
+ SOCKET new_socket;
+
+ DEBUGF(("packet_inet_ctl(%ld): PEELOFF\r\n", (long)desc->port));
+ if (!IS_SCTP(desc))
+ return ctl_xerror(EXBADPORT, rbuf, rsize);
+ if (!IS_OPEN(desc))
+ return ctl_xerror(EXBADPORT, rbuf, rsize);
+ if (!IS_BOUND(desc))
+ return ctl_xerror(EXBADSEQ, rbuf, rsize);
+ if (! p_sctp_peeloff)
+ return ctl_error(ENOTSUP, rbuf, rsize);
+
+ if (len != 4)
+ return ctl_error(EINVAL, rbuf, rsize);
+ assoc_id = get_int32(buf);
+
+ new_socket = p_sctp_peeloff(desc->s, assoc_id);
+ if (IS_SOCKET_ERROR(new_socket)) {
+ return ctl_error(sock_errno(), rbuf, rsize);
+ }
+
+ desc->caller = driver_caller(desc->port);
+ if ((new_udesc = sctp_inet_copy(udesc, new_socket, &err)) == NULL) {
+ sock_close(new_socket);
+ desc->caller = 0;
+ return ctl_error(err, rbuf, rsize);
+ }
+ new_udesc->inet.state = INET_STATE_CONNECTED;
+ new_udesc->inet.stype = SOCK_STREAM;
+
+ inet_reply_ok_port(desc, new_udesc->inet.dport);
+ (*rbuf)[0] = INET_REP;
+ return 1;
+ }
#endif /* HAVE_SCTP */
case PACKET_REQ_RECV:
@@ -9785,13 +10309,13 @@ static void packet_inet_timeout(ErlDrvData e)
** There is no destination address -- SCTYP send is performed over
** an existing association, using "sctp_sndrcvinfo" specified.
*/
-static void packet_inet_command(ErlDrvData e, char* buf, int len)
+static void packet_inet_command(ErlDrvData e, char* buf, ErlDrvSizeT len)
{
udp_descriptor * udesc= (udp_descriptor*) e;
inet_descriptor* desc = INETP(udesc);
char* ptr = buf;
char* qtr;
- int sz;
+ ErlDrvSizeT sz;
int code;
inet_address other;
@@ -9809,7 +10333,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, int len)
#ifdef HAVE_SCTP
if (IS_SCTP(desc))
{
- int data_len;
+ ErlDrvSizeT data_len;
struct iovec iov[1]; /* For real data */
struct msghdr mhdr; /* Message wrapper */
struct sctp_sndrcvinfo *sri; /* The actual ancilary data */
@@ -9845,6 +10369,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, int len)
mhdr.msg_iovlen = 1;
mhdr.msg_control = cmsg.ancd; /* For ancilary data */
mhdr.msg_controllen = cmsg.hdr.cmsg_len;
+ VALGRIND_MAKE_MEM_DEFINED(mhdr.msg_control, mhdr.msg_controllen); /*suppress "uninitialised bytes"*/
mhdr.msg_flags = 0; /* Not used with "sendmsg" */
/* Now do the actual sending. NB: "flags" in "sendmsg" itself are NOT
@@ -9919,12 +10444,8 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
{
inet_descriptor* desc = INETP(udesc);
int n;
- unsigned int len;
inet_address other;
char abuf[sizeof(inet_address)]; /* buffer address; enough??? */
- int sz;
- char* ptr;
- ErlDrvBinary* buf; /* binary */
int packet_count = udesc->read_packets;
int count = 0; /* number of packets delivered to owner */
#ifdef HAVE_SCTP
@@ -9935,23 +10456,39 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
#endif
while(packet_count--) {
- len = sizeof(other);
- sz = desc->bufsz;
- /* Allocate space for message and address. NB: "bufsz" is in "desc",
- but the "buf" itself is allocated separately:
- */
- if ((buf = alloc_buffer(sz+len)) == NULL)
- return packet_error(udesc, ENOMEM);
- ptr = buf->orig_bytes + len; /* pointer to message part */
+ unsigned int len = sizeof(other);
+
+ /* udesc->i_buf is only kept between SCTP fragments */
+ if (udesc->i_buf == NULL) {
+ udesc->i_bufsz = desc->bufsz + len;
+ if ((udesc->i_buf = alloc_buffer(udesc->i_bufsz)) == NULL)
+ return packet_error(udesc, ENOMEM);
+ /* pointer to message start */
+ udesc->i_ptr = udesc->i_buf->orig_bytes + len;
+ } else {
+ ErlDrvBinary* tmp;
+ int bufsz;
+ bufsz = desc->bufsz + (udesc->i_ptr - udesc->i_buf->orig_bytes);
+ if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) == NULL) {
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
+ return packet_error(udesc, ENOMEM);
+ } else {
+ udesc->i_ptr =
+ tmp->orig_bytes + (udesc->i_ptr - udesc->i_buf->orig_bytes);
+ udesc->i_buf = tmp;
+ udesc->i_bufsz = bufsz;
+ }
+ }
/* Note: On Windows NT, recvfrom() fails if the socket is connected. */
#ifdef HAVE_SCTP
/* For SCTP we must use recvmsg() */
if (IS_SCTP(desc)) {
- iov->iov_base = ptr; /* Data will come here */
- iov->iov_len = sz; /* Remaining buffer space */
+ iov->iov_base = udesc->i_ptr; /* Data will come here */
+ iov->iov_len = desc->bufsz; /* Remaining buffer space */
- mhdr.msg_name = &other; /* Peer addr comes into "other" */
+ mhdr.msg_name = &other; /* Peer addr comes into "other" */
mhdr.msg_namelen = len;
mhdr.msg_iov = iov;
mhdr.msg_iovlen = 1;
@@ -9961,42 +10498,28 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
/* Do the actual SCTP receive: */
n = sock_recvmsg(desc->s, &mhdr, 0);
+ len = mhdr.msg_namelen;
goto check_result;
}
#endif
/* Use recv() instead on connected sockets. */
if ((desc->state & INET_F_ACTIVE)) {
- n = sock_recv(desc->s, ptr, sz, 0);
+ n = sock_recv(desc->s, udesc->i_ptr, desc->bufsz, 0);
other = desc->remote;
+ goto check_result;
}
- else
- n = sock_recvfrom(desc->s, ptr, sz, 0, &other.sa, &len);
-
-#ifdef HAVE_SCTP
+ n = sock_recvfrom(desc->s, udesc->i_ptr, desc->bufsz,
+ 0, &other.sa, &len);
check_result:
-#endif
/* Analyse the result: */
- if (IS_SOCKET_ERROR(n)
-#ifdef HAVE_SCTP
- || (short_recv = (IS_SCTP(desc) && !(mhdr.msg_flags & MSG_EOR)))
- /* NB: here we check for EOR not being set -- this is an error as
- well, we don't support partial msgs:
- */
-#endif
- ) {
+ if (IS_SOCKET_ERROR(n)) {
int err = sock_errno();
- release_buffer(buf);
if (err != ERRNO_BLOCK) {
+ /* real error */
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
if (!desc->active) {
-#ifdef HAVE_SCTP
- if (short_recv) {
- async_error_am(desc, am_short_recv);
- } else {
- async_error(desc, err);
- }
-#else
async_error(desc, err);
-#endif
driver_cancel_timer(desc->port);
sock_select(desc,FD_READ,0);
}
@@ -10004,46 +10527,72 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
/* This is for an active desc only: */
packet_error_message(udesc, err);
}
+ return count;
}
- else if (!desc->active)
+ /* would block error - try again */
+ if (!desc->active
+#ifdef HAVE_SCTP
+ || short_recv
+#endif
+ ) {
sock_select(desc,FD_READ,1);
+ }
return count; /* strange, not ready */
}
- else {
- int offs;
- int nsz;
+
+#ifdef HAVE_SCTP
+ if (IS_SCTP(desc) && (short_recv = !(mhdr.msg_flags & MSG_EOR))) {
+ /* SCTP non-final message fragment */
+ inet_input_count(desc, n);
+ udesc->i_ptr += n;
+ continue; /* wait for more fragments */
+ }
+#endif
+
+ {
+ /* message received */
int code;
- unsigned int alen = len;
void * extra = NULL;
+ char * ptr;
+ int nsz;
inet_input_count(desc, n);
- inet_get_address(desc->sfamily, abuf, &other, &alen);
- /* Copy formatted address to the buffer allocated; "alen" is the
- actual length which must be <= than the original reserved "len".
+ udesc->i_ptr += n;
+ inet_get_address(desc->sfamily, abuf, &other, &len);
+ /* Copy formatted address to the buffer allocated; "len" is the
+ actual length which must be <= than the original reserved.
This means that the addr + data in the buffer are contiguous,
- but they may start not at the "orig_bytes", but with some "offs"
- from them:
+ but they may start not at the "orig_bytes", instead at "ptr":
*/
- ASSERT (alen <= len);
- sys_memcpy(ptr - alen, abuf, alen);
- ptr -= alen;
- nsz = n + alen; /* nsz = data + address */
- offs = ptr - buf->orig_bytes; /* initial pointer offset */
+ ASSERT (len <= sizeof(other));
+ ptr = udesc->i_buf->orig_bytes + sizeof(other) - len;
+ sys_memcpy(ptr, abuf, len);
+
+ nsz = udesc->i_ptr - ptr;
/* Check if we need to reallocate binary */
- if ((desc->mode == INET_MODE_BINARY) &&
- (desc->hsz < n) && (nsz < BIN_REALLOC_LIMIT(sz))) {
+ if ((desc->mode == INET_MODE_BINARY)
+ && (desc->hsz < (nsz - len))
+ && (nsz + BIN_REALLOC_MARGIN(desc->bufsz) < udesc->i_bufsz)) {
ErlDrvBinary* tmp;
- if ((tmp = realloc_buffer(buf,nsz+offs)) != NULL)
- buf = tmp;
+ int bufsz;
+ bufsz = udesc->i_ptr - udesc->i_buf->orig_bytes;
+ if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) != NULL) {
+ udesc->i_buf = tmp;
+ udesc->i_bufsz = bufsz;
+ udesc->i_ptr = NULL; /* not used from here */
+ }
}
#ifdef HAVE_SCTP
if (IS_SCTP(desc)) extra = &mhdr;
#endif
/* Actual parsing and return of the data received, occur here: */
- code = packet_reply_binary_data(desc, (unsigned int)alen,
- buf, offs, nsz, extra);
- free_buffer(buf);
+ code = packet_reply_binary_data(desc, len, udesc->i_buf,
+ (sizeof(other) - len),
+ nsz,
+ extra);
+ free_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
if (code < 0)
return count;
count++;
@@ -10053,7 +10602,17 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
return count; /* passive mode (read one packet only) */
}
}
+ } /* while(packet_count--) { */
+
+ /* we ran out of tries (packet_count) either on an active socket
+ * that got that many messages or an SCTP socket that got that
+ * many message fragments but still not the final
+ */
+#ifdef HAVE_SCTP
+ if (short_recv) {
+ sock_select(desc, FD_READ, 1);
}
+#endif
return count;
}
@@ -10063,7 +10622,7 @@ static void packet_inet_drv_output(ErlDrvData e, ErlDrvEvent event)
}
/* UDP/SCTP socket ready for output:
-** This is a Back-End for Non-Block SCTP Connect (SCTP_STATE_CONNECTING)
+** This is a Back-End for Non-Block SCTP Connect (INET_STATE_CONNECTING)
*/
static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
{
@@ -10074,7 +10633,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
DEBUGF(("packet_inet_output(%ld) {s=%d\r\n",
(long)desc->port, desc->s));
- if (desc->state == SCTP_STATE_CONNECTING) {
+ if (desc->state == INET_STATE_CONNECTING) {
sock_select(desc, FD_CONNECT, 0);
driver_cancel_timer(ix); /* posssibly cancel a timer */
@@ -10094,7 +10653,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
(struct sockaddr*) &desc->remote, &sz);
if (IS_SOCKET_ERROR(code)) {
- desc->state = PACKET_STATE_BOUND; /* restore state */
+ desc->state = INET_STATE_BOUND; /* restore state */
ret = async_error(desc, sock_errno());
goto done;
}
@@ -10107,7 +10666,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
(void *)&error, &sz);
if ((code < 0) || error) {
- desc->state = PACKET_STATE_BOUND; /* restore state */
+ desc->state = INET_STATE_BOUND; /* restore state */
ret = async_error(desc, error);
goto done;
}
@@ -10115,7 +10674,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event)
#endif /* SO_ERROR */
#endif /* !__WIN32__ */
- desc->state = PACKET_STATE_CONNECTED;
+ desc->state = INET_STATE_CONNECTED;
async_ok(desc);
}
else {
@@ -10522,7 +11081,7 @@ int erts_sock_connect(erts_sock_t socket, byte *ip_addr, int len, Uint16 port)
{
SOCKET s = (SOCKET) socket;
char buf[2 + 4];
- int blen = 6;
+ ErlDrvSizeT blen = 6;
inet_address addr;
if (socket == ERTS_SOCK_INVALID_SOCKET || len != 4)
diff --git a/erts/emulator/drivers/common/ram_file_drv.c b/erts/emulator/drivers/common/ram_file_drv.c
index abedcc933a..a109e40333 100644
--- a/erts/emulator/drivers/common/ram_file_drv.c
+++ b/erts/emulator/drivers/common/ram_file_drv.c
@@ -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
@@ -98,7 +98,7 @@ typedef unsigned char uchar;
static ErlDrvData rfile_start(ErlDrvPort, char*);
static int rfile_init(void);
static void rfile_stop(ErlDrvData);
-static void rfile_command(ErlDrvData, char*, int);
+static void rfile_command(ErlDrvData, char*, ErlDrvSizeT);
struct erl_drv_entry ram_file_driver_entry = {
@@ -108,7 +108,23 @@ struct erl_drv_entry ram_file_driver_entry = {
rfile_command,
NULL,
NULL,
- "ram_file_drv"
+ "ram_file_drv",
+ NULL,
+ NULL, /* handle */
+ NULL, /* control */
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
/* A File is represented as a array of bytes, this array is
@@ -121,9 +137,9 @@ typedef struct ram_file {
int flags; /* flags read/write */
ErlDrvBinary* bin; /* binary to hold binary file */
char* buf; /* buffer start (in binary) */
- int size; /* buffer size (allocated) */
- int cur; /* current position in buffer */
- int end; /* end position in buffer */
+ ErlDrvSSizeT size; /* buffer size (allocated) */
+ ErlDrvSSizeT cur; /* current position in buffer */
+ ErlDrvSSizeT end; /* end position in buffer */
} RamFile;
#ifdef LOADABLE
@@ -211,7 +227,7 @@ static int reply(RamFile *f, int ok, int err)
return 0;
}
-static int numeric_reply(RamFile *f, int result)
+static int numeric_reply(RamFile *f, ErlDrvSSizeT result)
{
char tmp[5];
@@ -231,7 +247,8 @@ static int numeric_reply(RamFile *f, int result)
/* install bin as the new binary reset all pointer */
-static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len)
+static void ram_file_set(RamFile *f, ErlDrvBinary *bin,
+ ErlDrvSSizeT bsize, ErlDrvSSizeT len)
{
f->size = bsize;
f->buf = bin->orig_bytes;
@@ -240,9 +257,9 @@ static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len)
f->bin = bin;
}
-static int ram_file_init(RamFile *f, char *buf, int count, int *error)
+static int ram_file_init(RamFile *f, char *buf, ErlDrvSSizeT count, int *error)
{
- int bsize;
+ ErlDrvSSizeT bsize;
ErlDrvBinary* bin;
if (count < 0) {
@@ -268,9 +285,9 @@ static int ram_file_init(RamFile *f, char *buf, int count, int *error)
return count;
}
-static int ram_file_expand(RamFile *f, int size, int *error)
+static ErlDrvSSizeT ram_file_expand(RamFile *f, ErlDrvSSizeT size, int *error)
{
- int bsize;
+ ErlDrvSSizeT bsize;
ErlDrvBinary* bin;
if (size < 0) {
@@ -298,10 +315,10 @@ static int ram_file_expand(RamFile *f, int size, int *error)
}
-static int ram_file_write(RamFile *f, char *buf, int len,
- int *location, int *error)
+static ErlDrvSSizeT ram_file_write(RamFile *f, char *buf, ErlDrvSSizeT len,
+ ErlDrvSSizeT *location, int *error)
{
- int cur = f->cur;
+ ErlDrvSSizeT cur = f->cur;
if (!(f->flags & RAM_FILE_MODE_WRITE)) {
*error = EBADF;
@@ -322,11 +339,11 @@ static int ram_file_write(RamFile *f, char *buf, int len,
return len;
}
-static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp,
- int *location, int *error)
+static ErlDrvSSizeT ram_file_read(RamFile *f, ErlDrvSSizeT len, ErlDrvBinary **bp,
+ ErlDrvSSizeT *location, int *error)
{
ErlDrvBinary* bin;
- int cur = f->cur;
+ ErlDrvSSizeT cur = f->cur;
if (!(f->flags & RAM_FILE_MODE_READ)) {
*error = EBADF;
@@ -352,9 +369,10 @@ static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp,
return len;
}
-static int ram_file_seek(RamFile *f, int offset, int whence, int *error)
+static ErlDrvSSizeT ram_file_seek(RamFile *f, ErlDrvSSizeT offset, int whence,
+ int *error)
{
- int pos;
+ ErlDrvSSizeT pos;
if (f->flags == 0) {
*error = EBADF;
@@ -389,13 +407,13 @@ static int ram_file_seek(RamFile *f, int offset, int whence, int *error)
static int ram_file_uuencode(RamFile *f)
{
- int code_len = UULINE(UNIX_LINE);
- int len = f->end;
- int usize = 4*((len+2)/3) + 2*((len+code_len-1)/code_len) + 2;
+ ErlDrvSSizeT code_len = UULINE(UNIX_LINE);
+ ErlDrvSSizeT len = f->end;
+ ErlDrvSSizeT usize = 4*((len+2)/3) + 2*((len+code_len-1)/code_len) + 2;
ErlDrvBinary* bin;
uchar* inp;
uchar* outp;
- int count = 0;
+ ErlDrvSSizeT count = 0;
if ((bin = driver_alloc_binary(usize)) == NULL)
return error_reply(f, ENOMEM);
@@ -447,8 +465,8 @@ static int ram_file_uuencode(RamFile *f)
static int ram_file_uudecode(RamFile *f)
{
- int len = f->end;
- int usize = ( (len+3) / 4 ) * 3;
+ ErlDrvSSizeT len = f->end;
+ ErlDrvSSizeT usize = ( (len+3) / 4 ) * 3;
ErlDrvBinary* bin;
uchar* inp;
uchar* outp;
@@ -510,7 +528,7 @@ static int ram_file_uudecode(RamFile *f)
static int ram_file_compress(RamFile *f)
{
- int size = f->end;
+ ErlDrvSSizeT size = f->end;
ErlDrvBinary* bin;
if ((bin = erts_gzdeflate_buffer(f->buf, size)) == NULL) {
@@ -528,7 +546,7 @@ static int ram_file_compress(RamFile *f)
static int ram_file_uncompress(RamFile *f)
{
- int size = f->end;
+ ErlDrvSSizeT size = f->end;
ErlDrvBinary* bin;
if ((bin = erts_gzinflate_buffer(f->buf, size)) == NULL) {
@@ -541,15 +559,15 @@ static int ram_file_uncompress(RamFile *f)
}
-static void rfile_command(ErlDrvData e, char* buf, int count)
+static void rfile_command(ErlDrvData e, char* buf, ErlDrvSizeT count)
{
RamFile* f = (RamFile*)e;
int error = 0;
ErlDrvBinary* bin;
char header[5]; /* result code + count */
- int offset;
- int origin; /* Origin of seek. */
- int n;
+ ErlDrvSSizeT offset;
+ ErlDrvSSizeT origin; /* Origin of seek. */
+ ErlDrvSSizeT n;
count--;
switch(*(uchar*)buf++) {
diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c
index f50899a730..60394b610b 100644
--- a/erts/emulator/drivers/common/zlib_drv.c
+++ b/erts/emulator/drivers/common/zlib_drv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2012. All Rights Reserved.
*
* The 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,8 +64,9 @@
static int zlib_init(void);
static ErlDrvData zlib_start(ErlDrvPort port, char* buf);
static void zlib_stop(ErlDrvData e);
-static int zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen);
+static void zlib_flush(ErlDrvData e);
+static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
static void zlib_outputv(ErlDrvData drv_data, ErlIOVec *ev);
ErlDrvEntry zlib_driver_entry = {
@@ -82,7 +83,7 @@ ErlDrvEntry zlib_driver_entry = {
NULL, /* timeout */
zlib_outputv,
NULL, /* read_async */
- NULL, /* flush */
+ zlib_flush,
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER,
@@ -162,12 +163,12 @@ static char* zlib_reason(int code, int* err)
}
-static int zlib_return(int code, char** rbuf, int rlen)
+static ErlDrvSSizeT zlib_return(int code, char** rbuf, ErlDrvSizeT rlen)
{
int msg_code = 0; /* 0=ok, 1=error */
char* dst = *rbuf;
char* src;
- int len = 0;
+ ErlDrvSizeT len = 0;
src = zlib_reason(code, &msg_code);
*dst++ = msg_code;
@@ -182,7 +183,8 @@ static int zlib_return(int code, char** rbuf, int rlen)
return len;
}
-static int zlib_value2(int msg_code, int value, char** rbuf, int rlen)
+static ErlDrvSSizeT zlib_value2(int msg_code, int value,
+ char** rbuf, ErlDrvSizeT rlen)
{
char* dst = *rbuf;
@@ -197,7 +199,7 @@ static int zlib_value2(int msg_code, int value, char** rbuf, int rlen)
return 5;
}
-static int zlib_value(int value, char** rbuf, int rlen)
+static ErlDrvSSizeT zlib_value(int value, char** rbuf, ErlDrvSizeT rlen)
{
return zlib_value2(2, value, rbuf, rlen);
}
@@ -409,8 +411,15 @@ static void zlib_stop(ErlDrvData e)
driver_free(d);
}
-static int zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen)
+static void zlib_flush(ErlDrvData drv_data)
+{
+ ZLibData* d = (ZLibData*) drv_data;
+
+ driver_deq(d->port, driver_sizeq(d->port));
+}
+
+static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
{
ZLibData* d = (ZLibData*)drv_data;
int res;
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index d782b044a9..b29f80a8ba 100644
--- a/erts/emulator/drivers/unix/ttsl_drv.c
+++ b/erts/emulator/drivers/unix/ttsl_drv.c
@@ -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
@@ -106,7 +106,7 @@ static int lpos; /* The current "cursor position" in the line buf
/* Main interface functions. */
static void ttysl_stop(ErlDrvData);
-static void ttysl_from_erlang(ErlDrvData, char*, int);
+static void ttysl_from_erlang(ErlDrvData, char*, ErlDrvSizeT);
static void ttysl_from_tty(ErlDrvData, ErlDrvEvent);
static void ttysl_stop_select(ErlDrvEvent, void*);
static Sint16 get_sint16(char*);
@@ -141,7 +141,8 @@ static void update_cols(void);
static int tty_init(int,int,int,int);
static int tty_set(int);
static int tty_reset(int);
-static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT ttysl_control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
#ifdef ERTS_NOT_USED
static RETSIGTYPE suspend(int);
#endif
@@ -242,7 +243,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
#ifndef HAVE_TERMCAP
return ERL_DRV_ERROR_GENERAL;
#else
- char *s, *t, c, *l;
+ char *s, *t, *l;
int canon, echo, sig; /* Terminal characteristics */
int flag;
extern int using_oldshell; /* set this to let the rest of erts know */
@@ -262,7 +263,6 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
s++;
/* Find end of this argument (start of next) and insert NUL. */
if ((t = strchr(s, ' '))) {
- c = *t;
*t = '\0';
}
if ((flag = ((*s == '+') ? 1 : ((*s == '-') ? -1 : 0)))) {
@@ -346,13 +346,13 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height)
*height = DEF_HEIGHT;
}
-static int ttysl_control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
char resbuff[2*sizeof(Uint32)];
- int res_size;
+ ErlDrvSizeT res_size;
switch (command) {
case CTRL_OP_GET_WINSIZE:
{
@@ -634,14 +634,14 @@ static int check_buf_size(byte *s, int n)
}
-static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, int count)
+static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count)
{
if (lpos > MAXSIZE)
put_chars((byte*)"\n", 1);
switch (buf[0]) {
case OP_PUTC:
- DEBUGLOG(("OP: Putc(%d)",count-1));
+ DEBUGLOG(("OP: Putc(%lu)",(unsigned long) count-1));
if (check_buf_size((byte*)buf+1, count-1) == 0)
return;
put_chars((byte*)buf+1, count-1);
diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c
index 4b3934657c..b250bac4dc 100644
--- a/erts/emulator/drivers/unix/unix_efile.c
+++ b/erts/emulator/drivers/unix/unix_efile.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -33,6 +33,9 @@
#include <sys/types.h>
#include <sys/uio.h>
#endif
+#if defined(HAVE_SENDFILE) && (defined(__linux__) || (defined(__sun) && defined(__SVR4)))
+#include <sys/sendfile.h>
+#endif
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
#define DARWIN 1
@@ -104,8 +107,8 @@ static void *ef_safe_alloc(Uint s)
{
void *p = EF_ALLOC(s);
if (!p) erl_exit(1,
- "unix efile drv: Can't allocate %d bytes of memory\n",
- s);
+ "unix efile drv: Can't allocate %lu bytes of memory\n",
+ (unsigned long)s);
return p;
}
@@ -115,8 +118,8 @@ static void *ef_safe_realloc(void *op, Uint s)
{
void *p = EF_REALLOC(op, s);
if (!p) erl_exit(1,
- "unix efile drv: Can't reallocate %d bytes of memory\n",
- s);
+ "unix efile drv: Can't reallocate %lu bytes of memory\n",
+ (unsigned long)s);
return p;
}
@@ -813,7 +816,6 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
char* name, int info_for_link)
{
struct stat statbuf; /* Information about the file */
- struct tm *timep; /* Broken-apart filetime. */
int result;
#ifdef VXWORKS
@@ -880,40 +882,17 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
else
pInfo->type = FT_OTHER;
-#if defined(HAVE_LOCALTIME_R) || defined(VXWORKS)
- {
- /* Use the reentrant version of localtime() */
- static struct tm local_tm;
-#define localtime(a) (localtime_r((a), &local_tm), &local_tm)
-#endif
-
-
-#define GET_TIME(dst, src) \
- timep = localtime(&statbuf.src); \
- (dst).year = timep->tm_year+1900; \
- (dst).month = timep->tm_mon+1; \
- (dst).day = timep->tm_mday; \
- (dst).hour = timep->tm_hour; \
- (dst).minute = timep->tm_min; \
- (dst).second = timep->tm_sec
-
- GET_TIME(pInfo->accessTime, st_atime);
- GET_TIME(pInfo->modifyTime, st_mtime);
- GET_TIME(pInfo->cTime, st_ctime);
-
-#undef GET_TIME
+ pInfo->accessTime = statbuf.st_atime;
+ pInfo->modifyTime = statbuf.st_mtime;
+ pInfo->cTime = statbuf.st_ctime;
-#if defined(HAVE_LOCALTIME_R) || defined(VXWORKS)
- }
-#endif
-
- pInfo->mode = statbuf.st_mode;
- pInfo->links = statbuf.st_nlink;
+ pInfo->mode = statbuf.st_mode;
+ pInfo->links = statbuf.st_nlink;
pInfo->major_device = statbuf.st_dev;
pInfo->minor_device = statbuf.st_rdev;
- pInfo->inode = statbuf.st_ino;
- pInfo->uid = statbuf.st_uid;
- pInfo->gid = statbuf.st_gid;
+ pInfo->inode = statbuf.st_ino;
+ pInfo->uid = statbuf.st_uid;
+ pInfo->gid = statbuf.st_gid;
return 1;
}
@@ -921,6 +900,8 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
int
efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name)
{
+ struct utimbuf tval;
+
CHECK_PATHLEN(name, errInfo);
#ifdef VXWORKS
@@ -973,38 +954,18 @@ efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name)
#endif /* !VXWORKS */
- if (pInfo->accessTime.year != -1 && pInfo->modifyTime.year != -1) {
- struct utimbuf tval;
- struct tm timebuf;
-
-#define MKTIME(tb, ts) \
- timebuf.tm_year = ts.year-1900; \
- timebuf.tm_mon = ts.month-1; \
- timebuf.tm_mday = ts.day; \
- timebuf.tm_hour = ts.hour; \
- timebuf.tm_min = ts.minute; \
- timebuf.tm_sec = ts.second; \
- timebuf.tm_isdst = -1; \
- if ((tb = mktime(&timebuf)) == (time_t) -1) { \
- errno = EINVAL; \
- return check_error(-1, errInfo); \
- }
+ tval.actime = pInfo->accessTime;
+ tval.modtime = pInfo->modifyTime;
- MKTIME(tval.actime, pInfo->accessTime);
- MKTIME(tval.modtime, pInfo->modifyTime);
-#undef MKTIME
-
#ifdef VXWORKS
- /* VxWorks' utime doesn't work when the file is a nfs mounted
- * one, don't report error if utime fails.
- */
- utime(name, &tval);
- return 1;
+ /* VxWorks' utime doesn't work when the file is a nfs mounted
+ * one, don't report error if utime fails.
+ */
+ utime(name, &tval);
+ return 1;
#else
- return check_error(utime(name, &tval), errInfo);
+ return check_error(utime(name, &tval), errInfo);
#endif
- }
- return 1;
}
@@ -1043,13 +1004,11 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */
* opened */
int fd, /* File descriptor to write to */
SysIOVec* iov, /* Vector of buffer structs.
- * The structs are unchanged
- * after the call */
- int iovcnt, /* Number of structs in vector */
- size_t size) /* Number of bytes to write */
+ * The structs may be changed i.e.
+ * due to incomplete writes */
+ int iovcnt) /* Number of structs in vector */
{
int cnt = 0; /* Buffers so far written */
- int p = 0; /* Position in next buffer */
ASSERT(iovcnt >= 0);
@@ -1060,66 +1019,47 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */
#endif
while (cnt < iovcnt) {
+ if ((! iov[cnt].iov_base) || (iov[cnt].iov_len <= 0)) {
+ /* Empty buffer - skip */
+ cnt++;
+ } else { /* Non-empty buffer */
+ ssize_t w; /* Bytes written in this call */
#ifdef HAVE_WRITEV
- int w; /* Bytes written in this call */
- int b = iovcnt - cnt; /* Buffers to write */
- if (b > MAXIOV)
- b = MAXIOV;
- if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {
- if (b == 1) {
- /* Degenerated io vector */
- do {
- w = write(fd, iov[cnt].iov_base + p, iov[cnt].iov_len - p);
- } while (w < 0 && errno == EINTR);
- } else {
- /* Non-empty vector first.
- * Adjust pos in first buffer in case of
- * previous incomplete writev */
- iov[cnt].iov_base += p;
- iov[cnt].iov_len -= p;
+ int b = iovcnt - cnt; /* Buffers to write */
+ /* Use as many buffers as MAXIOV allows */
+ if (b > MAXIOV)
+ b = MAXIOV;
+ if (b > 1) {
do {
w = writev(fd, &iov[cnt], b);
} while (w < 0 && errno == EINTR);
- iov[cnt].iov_base -= p;
- iov[cnt].iov_len += p;
- }
- if (w < 0)
- return check_error(-1, errInfo);
- } else {
- /* Empty vector first - skip */
- cnt++;
- continue;
- }
- ASSERT(w >= 0);
- /* Move forward to next vector to write */
- for (; cnt < iovcnt; cnt++) {
- if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {
- if (w < iov[cnt].iov_len)
- break;
- else
- w -= iov[cnt].iov_len;
- }
- }
- ASSERT(w >= 0);
- p = w > 0 ? w : 0; /* Skip p bytes next writev */
-#else /* #ifdef HAVE_WRITEV */
- if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {
- /* Non-empty vector */
- int w; /* Bytes written in this call */
- while (p < iov[cnt].iov_len) {
- do {
- w = write(fd, iov[cnt].iov_base + p, iov[cnt].iov_len - p);
- } while (w < 0 && errno == EINTR);
- if (w < 0)
- return check_error(-1, errInfo);
- p += w;
+ } else
+ /* Degenerated io vector - use regular write */
+#endif
+ {
+ do {
+ w = write(fd, iov[cnt].iov_base, iov[cnt].iov_len);
+ } while (w < 0 && errno == EINTR);
+ ASSERT(w <= iov[cnt].iov_len);
+ }
+ if (w < 0) return check_error(-1, errInfo);
+ /* Move forward to next buffer to write */
+ for (; cnt < iovcnt && w > 0; cnt++) {
+ if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {
+ if (w < iov[cnt].iov_len) {
+ /* Adjust the buffer for next write */
+ iov[cnt].iov_len -= w;
+ iov[cnt].iov_base += w;
+ w = 0;
+ break;
+ } else {
+ w -= iov[cnt].iov_len;
+ }
+ }
}
- }
- cnt++;
- p = 0;
-#endif /* #ifdef HAVE_WRITEV */
+ ASSERT(w == 0);
+ } /* else Non-empty buffer */
} /* while (cnt< iovcnt) */
- size = 0; /* Avoid compiler warning */
return 1;
}
@@ -1464,3 +1404,115 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset,
return check_error(0, errInfo);
#endif
}
+
+#ifdef HAVE_SENDFILE
+// For some reason the maximum size_t cannot be used as the max size
+// 3GB seems to work on all platforms
+#define SENDFILE_CHUNK_SIZE ((1UL << 30) -1)
+
+/*
+ * sendfile: The implementation of the sendfile system call varies
+ * a lot on different *nix platforms so to make the api similar in all
+ * we have to emulate some things in linux and play with variables on
+ * bsd/darwin.
+ *
+ * All of the calls will split a command which tries to send more than
+ * SENDFILE_CHUNK_SIZE of data at once.
+ *
+ * On platforms where *nbytes of 0 does not mean the entire file, this is
+ * simulated.
+ *
+ * It could be possible to implement header/trailer in sendfile. Though
+ * you would have to emulate it in linux and on BSD/Darwin some complex
+ * calculations have to be made when using a non blocking socket to figure
+ * out how much of the header/file/trailer was sent in each command.
+ *
+ * The semantics of the API is this:
+ * Return value: 1 if all data was sent and the function does not need to
+ * be called again. 0 if an error occures OR if there is more data which
+ * has to be sent (EAGAIN or EINTR will be set appropriately)
+ *
+ * The amount of data written in a call is returned through nbytes.
+ *
+ */
+
+int
+efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd,
+ off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl)
+{
+ Uint64 written = 0;
+#if defined(__linux__)
+ ssize_t retval;
+ do {
+ // check if *nbytes is 0 or greater than chunk size
+ if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE)
+ retval = sendfile(out_fd, in_fd, offset, SENDFILE_CHUNK_SIZE);
+ else
+ retval = sendfile(out_fd, in_fd, offset, *nbytes);
+ if (retval > 0) {
+ written += retval;
+ *nbytes -= retval;
+ }
+ } while (retval == SENDFILE_CHUNK_SIZE);
+ if (written != 0) {
+ // -1 is not returned by the linux API so we have to simulate it
+ retval = -1;
+ errno = EAGAIN;
+ }
+#elif defined(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV)
+ ssize_t retval;
+ size_t len;
+ sendfilevec_t fdrec;
+ fdrec.sfv_fd = in_fd;
+ fdrec.sfv_flag = 0;
+ do {
+ fdrec.sfv_off = *offset;
+ len = 0;
+ // check if *nbytes is 0 or greater than chunk size
+ if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE)
+ fdrec.sfv_len = SENDFILE_CHUNK_SIZE;
+ else
+ fdrec.sfv_len = *nbytes;
+ retval = sendfilev(out_fd, &fdrec, 1, &len);
+ if (retval != -1 || errno == EAGAIN || errno == EINTR) {
+ *offset += len;
+ *nbytes -= len;
+ written += len;
+ }
+ } while (len == SENDFILE_CHUNK_SIZE);
+#elif defined(DARWIN)
+ int retval;
+ off_t len;
+ do {
+ // check if *nbytes is 0 or greater than chunk size
+ if(*nbytes > SENDFILE_CHUNK_SIZE)
+ len = SENDFILE_CHUNK_SIZE;
+ else
+ len = *nbytes;
+ retval = sendfile(in_fd, out_fd, *offset, &len, NULL, 0);
+ if (retval != -1 || errno == EAGAIN || errno == EINTR) {
+ *offset += len;
+ *nbytes -= len;
+ written += len;
+ }
+ } while (len == SENDFILE_CHUNK_SIZE);
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+ off_t len;
+ int retval;
+ do {
+ if (*nbytes > SENDFILE_CHUNK_SIZE)
+ retval = sendfile(in_fd, out_fd, *offset, SENDFILE_CHUNK_SIZE,
+ NULL, &len, 0);
+ else
+ retval = sendfile(in_fd, out_fd, *offset, *nbytes, NULL, &len, 0);
+ if (retval != -1 || errno == EAGAIN || errno == EINTR) {
+ *offset += len;
+ *nbytes -= len;
+ written += len;
+ }
+ } while(len == SENDFILE_CHUNK_SIZE);
+#endif
+ *nbytes = written;
+ return check_error(retval, errInfo);
+}
+#endif /* HAVE_SENDFILE */
diff --git a/erts/emulator/drivers/win32/registry_drv.c b/erts/emulator/drivers/win32/registry_drv.c
index 05fd2ea55f..1fad34e380 100644
--- a/erts/emulator/drivers/win32/registry_drv.c
+++ b/erts/emulator/drivers/win32/registry_drv.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
@@ -84,7 +84,7 @@ static int maperror(DWORD error);
static int reg_init(void);
static ErlDrvData reg_start(ErlDrvPort, char*);
static void reg_stop(ErlDrvData);
-static void reg_from_erlang(ErlDrvData, char*, int);
+static void reg_from_erlang(ErlDrvData, char*, ErlDrvSizeT);
struct erl_drv_entry registry_driver_entry = {
reg_init,
@@ -95,10 +95,21 @@ struct erl_drv_entry registry_driver_entry = {
NULL,
"registry__drv__",
NULL,
+ NULL, /* handle */
+ NULL, /* control */
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
NULL,
NULL,
NULL,
- NULL
};
static int
@@ -158,7 +169,7 @@ reg_stop(ErlDrvData clientData)
}
static void
-reg_from_erlang(ErlDrvData clientData, char* buf, int count)
+reg_from_erlang(ErlDrvData clientData, char* buf, ErlDrvSizeT count)
{
RegPort* rp = (RegPort *) clientData;
int cmd;
@@ -301,7 +312,7 @@ reg_from_erlang(ErlDrvData clientData, char* buf, int count)
buf = (char *) &dword;
ASSERT(count == 4);
}
- result = RegSetValueEx(rp->hkey, name, 0, type, buf, count);
+ result = RegSetValueEx(rp->hkey, name, 0, type, buf, (DWORD)count);
reply(rp, result);
}
break;
diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c
index fd88dafd34..1a74d21e99 100644
--- a/erts/emulator/drivers/win32/ttsl_drv.c
+++ b/erts/emulator/drivers/win32/ttsl_drv.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
@@ -21,6 +21,9 @@
* smart line for output.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include <ctype.h>
#include <stdlib.h>
@@ -80,8 +83,9 @@ int lpos; /* The current "cursor position" in the line buf
static int ttysl_init(void);
static ErlDrvData ttysl_start(ErlDrvPort, char*);
static void ttysl_stop(ErlDrvData);
-static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int);
-static void ttysl_from_erlang(ErlDrvData, char*, int);
+static ErlDrvSSizeT ttysl_control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
+static void ttysl_from_erlang(ErlDrvData, char*, ErlDrvSizeT);
static void ttysl_from_tty(ErlDrvData, ErlDrvEvent);
static Sint16 get_sint16(char *s);
@@ -117,7 +121,19 @@ struct erl_drv_entry ttsl_driver_entry = {
NULL,
NULL,
ttysl_control,
- NULL
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
static int utf8_mode = 0;
@@ -151,13 +167,13 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height)
}
-static int ttysl_control(ErlDrvData drv_data,
+static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data,
unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
char resbuff[2*sizeof(Uint32)];
- int res_size;
+ ErlDrvSizeT res_size;
switch (command) {
case CTRL_OP_GET_WINSIZE:
{
@@ -173,7 +189,7 @@ static int ttysl_control(ErlDrvData drv_data,
res_size = 1;
break;
case CTRL_OP_SET_UNICODE_STATE:
- if (len > 0) {
+ if (len != 0) {
int m = (int) *buf;
*resbuff = (utf8_mode) ? 1 : 0;
res_size = 1;
@@ -435,14 +451,14 @@ static int check_buf_size(byte *s, int n)
}
-static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, int count)
+static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count)
{
if (lpos > MAXSIZE)
put_chars((byte*)"\n", 1);
switch (buf[0]) {
case OP_PUTC:
- DEBUGLOG(("OP: Putc(%d)",count-1));
+ DEBUGLOG(("OP: Putc(%I64u)",(unsigned long long)count-1));
if (check_buf_size((byte*)buf+1, count-1) == 0)
return;
put_chars((byte*)buf+1, count-1);
diff --git a/erts/emulator/drivers/win32/win_con.c b/erts/emulator/drivers/win32/win_con.c
index c788ad409d..5df399aa5d 100644
--- a/erts/emulator/drivers/win32/win_con.c
+++ b/erts/emulator/drivers/win32/win_con.c
@@ -21,6 +21,9 @@
#define _UNICODE 1
#include <tchar.h>
#include <stdio.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include <windowsx.h>
#include "resource.h"
@@ -34,6 +37,23 @@
#define REALLOC(X,Y) realloc(X,Y)
#define FREE(X) free(X)
+#if SIZEOF_VOID_P == 8
+#define WIN64 1
+#ifndef GCL_HBRBACKGROUND
+#define GCL_HBRBACKGROUND GCLP_HBRBACKGROUND
+#endif
+#define DIALOG_PROC_RET INT_PTR
+#define CF_HOOK_RET INT_PTR
+#define CC_HOOK_RET INT_PTR
+#define OFN_HOOK_RET INT_PTR
+#else
+#define DIALOG_PROC_RET BOOL
+#define CF_HOOK_RET UINT
+#define CC_HOOK_RET UINT
+#define OFN_HOOK_RET UINT
+#endif
+
+
#ifndef STATE_SYSTEM_INVISIBLE
/* Mingw problem with oleacc.h and WIN32_LEAN_AND_MEAN */
#define STATE_SYSTEM_INVISIBLE 0x00008000
@@ -150,7 +170,7 @@ static TCHAR *erlang_window_title = TEXT("Erlang");
static unsigned __stdcall ConThreadInit(LPVOID param);
static LRESULT CALLBACK ClientWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
-static BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
+static DIALOG_PROC_RET CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
static ScreenLine_t *ConNewLine(void);
static void DeleteTopLine(void);
static void ensure_line_below(void);
@@ -549,7 +569,7 @@ FrameWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
return 1;
case WM_SETFOCUS :
CreateCaret(hClientWnd, NULL, cxChar, cyChar);
- SetCaretPos(GetXFromCurrentY(GetDC(hwnd),0,cur_x), (cur_y-iVscrollPos)*cyChar);
+ SetCaretPos(GetXFromCurrentY(GetDC(hClientWnd),iHscrollPos,cur_x), (cur_y-iVscrollPos)*cyChar);
ShowCaret(hClientWnd);
return 0;
case WM_KILLFOCUS:
@@ -1608,7 +1628,7 @@ OnEditSelAll(HWND hwnd)
InvalidateRect(hwnd, NULL, TRUE);
}
-UINT APIENTRY CFHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
+CF_HOOK_RET APIENTRY CFHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
/* Hook procedure for font dialog box */
HWND hOwner;
@@ -1626,11 +1646,11 @@ UINT APIENTRY CFHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
SetWindowPos(hDlg,HWND_TOP,rcOwner.left + (rc.right / 2),
rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE);
- return 1;
+ return (CF_HOOK_RET) 1;
default:
break;
}
- return 0; /* Let the default procedure process the message */
+ return (CF_HOOK_RET) 0; /* Let the default procedure process the message */
}
static BOOL
@@ -1705,7 +1725,7 @@ ConSetFont(HWND hwnd)
InvalidateRect(hwnd, NULL, TRUE);
}
-UINT APIENTRY
+CC_HOOK_RET APIENTRY
CCHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
/* Hook procedure for choose color dialog box */
@@ -1724,11 +1744,11 @@ CCHookProc(HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
SetWindowPos(hDlg,HWND_TOP,rcOwner.left + (rc.right / 2),
rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE);
- return 1;
+ return (CC_HOOK_RET) 1;
default:
break;
}
- return 0; /* Let the default procedure process the message */
+ return (CC_HOOK_RET) 0; /* Let the default procedure process the message */
}
void ConChooseColor(HWND hwnd)
@@ -1758,7 +1778,8 @@ void ConChooseColor(HWND hwnd)
}
}
-UINT APIENTRY OFNHookProc(HWND hwndDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
+OFN_HOOK_RET APIENTRY OFNHookProc(HWND hwndDlg,UINT iMsg,
+ WPARAM wParam,LPARAM lParam)
{
/* Hook procedure for open file dialog box */
HWND hOwner,hDlg;
@@ -1777,11 +1798,11 @@ UINT APIENTRY OFNHookProc(HWND hwndDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
SetWindowPos(hDlg,HWND_TOP,rcOwner.left + (rc.right / 2),
rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE);
- return 1;
+ return (OFN_HOOK_RET) 1;
default:
break;
}
- return 0; /* the let default procedure process the message */
+ return (OFN_HOOK_RET) 0; /* the let default procedure process the message */
}
static void
@@ -1933,7 +1954,7 @@ write_outbuf(TCHAR *data, int num_chars)
return num_chars;
}
-BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+DIALOG_PROC_RET CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HWND hOwner;
RECT rc,rcOwner,rcDlg;
@@ -1953,17 +1974,17 @@ BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
rcOwner.top + (rc.bottom / 2),0,0,SWP_NOSIZE);
SetDlgItemText(hDlg, ID_VERSIONSTRING,
TEXT("Erlang emulator version ") TEXT(ERLANG_VERSION));
- return TRUE;
+ return (DIALOG_PROC_RET) TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg,0);
- return TRUE;
+ return (DIALOG_PROC_RET) TRUE;
}
break;
}
- return FALSE;
+ return (DIALOG_PROC_RET) FALSE;
}
static void
@@ -2117,7 +2138,7 @@ AddToCmdHistory(void)
}
}
-static TBBUTTON tbb[] =
+/*static TBBUTTON tbb[] =
{
0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0,
0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0,
@@ -2149,6 +2170,39 @@ static TBBUTTON tbb[] =
2, IDMENU_FONT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE, 0, 0, 0, 0,
3, IDMENU_ABOUT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE, 0, 0, 0, 0,
0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, 0,
+ };*/
+static TBBUTTON tbb[] =
+{
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP},
+ {0, IDMENU_COPY, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE},
+ {1, IDMENU_PASTE, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE},
+ {2, IDMENU_FONT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE},
+ {3, IDMENU_ABOUT, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE},
+ {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}
};
static TBADDBITMAP tbbitmap =
@@ -2156,6 +2210,17 @@ static TBADDBITMAP tbbitmap =
HINST_COMMCTRL, IDB_STD_SMALL_COLOR,
};
+#ifdef HARDDEBUG
+/* For really hard GUI startup debugging, place DEBUGBOX() macros in code
+ and get modal message boxes with the line number. */
+static void debug_box(int line) {
+ TCHAR buff[1024];
+ swprintf(buff,1024,TEXT("DBG:%d"),line);
+ MessageBox(NULL,buff,TEXT("DBG"),MB_OK|MB_APPLMODAL);
+}
+
+#define DEBUGBOX() debug_box(__LINE__)
+#endif
static HWND
InitToolBar(HWND hwndParent)
@@ -2169,7 +2234,6 @@ InitToolBar(HWND hwndParent)
COLORMAP colorMap;
colorMap.from = RGB(192, 192, 192);
colorMap.to = backgroundColor;
-
/* Create toolbar window with tooltips */
hwndTB = CreateWindowEx(0,TOOLBARCLASSNAME,(TCHAR *)NULL,
WS_CHILD|CCS_TOP|WS_CLIPSIBLINGS|TBSTYLE_TOOLTIPS,
@@ -2180,9 +2244,10 @@ InitToolBar(HWND hwndParent)
tbbitmap.hInst = NULL;
tbbitmap.nID = (UINT) CreateMappedBitmap(beam_module, 1,0, &colorMap, 1);
SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM) 4,
- (WPARAM) &tbbitmap);
+ (LPARAM) &tbbitmap);
+
SendMessage(hwndTB,TB_ADDBUTTONS, (WPARAM) 30,
- (LPARAM) (LPTBBUTTON) tbb);
+ (LPARAM) tbb);
if (toolbarVisible)
ShowWindow(hwndTB, SW_SHOW);
diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c
index 931bb196f1..606fa1d7de 100755..100644
--- a/erts/emulator/drivers/win32/win_efile.c
+++ b/erts/emulator/drivers/win32/win_efile.c
@@ -21,6 +21,9 @@
*/
#include <windows.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include <ctype.h>
#include <wchar.h>
@@ -42,6 +45,26 @@
#define INVALID_FILE_ATTRIBUTES ((DWORD) 0xFFFFFFFF)
#endif
+#define TICKS_PER_SECOND (10000000ULL)
+#define EPOCH_DIFFERENCE (11644473600LL)
+
+#define FILETIME_TO_EPOCH(epoch, ft) \
+ do { \
+ ULARGE_INTEGER ull; \
+ ull.LowPart = (ft).dwLowDateTime; \
+ ull.HighPart = (ft).dwHighDateTime; \
+ (epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_DIFFERENCE); \
+ } while(0)
+
+#define EPOCH_TO_FILETIME(ft, epoch) \
+ do { \
+ ULARGE_INTEGER ull; \
+ ull.QuadPart = (((epoch) + EPOCH_DIFFERENCE) * TICKS_PER_SECOND); \
+ (ft).dwLowDateTime = ull.LowPart; \
+ (ft).dwHighDateTime = ull.HighPart; \
+ } while(0)
+
+
static int check_error(int result, Efile_error* errInfo);
static int set_error(Efile_error* errInfo);
static int is_root_unc_name(const WCHAR *path);
@@ -861,14 +884,7 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
findbuf.cFileName[0] = L'\0';
pInfo->links = 1;
- pInfo->modifyTime.year = 1980;
- pInfo->modifyTime.month = 1;
- pInfo->modifyTime.day = 1;
- pInfo->modifyTime.hour = 0;
- pInfo->modifyTime.minute = 0;
- pInfo->modifyTime.second = 0;
-
- pInfo->accessTime = pInfo->modifyTime;
+ pInfo->cTime = pInfo->accessTime = pInfo->modifyTime = 0;
} else {
SYSTEMTIME SystemTime;
FILETIME LocalFTime;
@@ -902,34 +918,21 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
}
}
-#define GET_TIME(dst, src) \
-if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \
- !FileTimeToSystemTime(&LocalFTime, &SystemTime)) { \
- return set_error(errInfo); \
-} \
-(dst).year = SystemTime.wYear; \
-(dst).month = SystemTime.wMonth; \
-(dst).day = SystemTime.wDay; \
-(dst).hour = SystemTime.wHour; \
-(dst).minute = SystemTime.wMinute; \
-(dst).second = SystemTime.wSecond;
-
- GET_TIME(pInfo->modifyTime, ftLastWriteTime);
+ FILETIME_TO_EPOCH(pInfo->modifyTime, findbuf.ftLastWriteTime);
if (findbuf.ftLastAccessTime.dwLowDateTime == 0 &&
findbuf.ftLastAccessTime.dwHighDateTime == 0) {
pInfo->accessTime = pInfo->modifyTime;
} else {
- GET_TIME(pInfo->accessTime, ftLastAccessTime);
+ FILETIME_TO_EPOCH(pInfo->accessTime, findbuf.ftLastAccessTime);
}
if (findbuf.ftCreationTime.dwLowDateTime == 0 &&
findbuf.ftCreationTime.dwHighDateTime == 0) {
pInfo->cTime = pInfo->modifyTime;
} else {
- GET_TIME(pInfo->cTime, ftCreationTime);
+ FILETIME_TO_EPOCH(pInfo->cTime ,findbuf.ftCreationTime);
}
-#undef GET_TIME
FindClose(findhandle);
}
@@ -965,17 +968,12 @@ efile_write_info(Efile_error* errInfo,
char* name)
{
SYSTEMTIME timebuf;
- FILETIME LocalFileTime;
FILETIME ModifyFileTime;
FILETIME AccessFileTime;
FILETIME CreationFileTime;
HANDLE fd;
- FILETIME* mtime = NULL;
- FILETIME* atime = NULL;
- FILETIME* ctime = NULL;
DWORD attr;
DWORD tempAttr;
- BOOL modifyTime = FALSE;
WCHAR *wname = (WCHAR *) name;
/*
@@ -1000,57 +998,36 @@ efile_write_info(Efile_error* errInfo,
* Construct all file times.
*/
-#define MKTIME(tb, ts, ptr) \
- timebuf.wYear = ts.year; \
- timebuf.wMonth = ts.month; \
- timebuf.wDay = ts.day; \
- timebuf.wHour = ts.hour; \
- timebuf.wMinute = ts.minute; \
- timebuf.wSecond = ts.second; \
- timebuf.wMilliseconds = 0; \
- if (ts.year != -1) { \
- modifyTime = TRUE; \
- ptr = &tb; \
- if (!SystemTimeToFileTime(&timebuf, &LocalFileTime ) || \
- !LocalFileTimeToFileTime(&LocalFileTime, &tb)) { \
- errno = EINVAL; \
- return check_error(-1, errInfo); \
- } \
- }
-
- MKTIME(ModifyFileTime, pInfo->modifyTime, mtime);
- MKTIME(AccessFileTime, pInfo->accessTime, atime);
- MKTIME(CreationFileTime, pInfo->cTime, ctime);
-#undef MKTIME
+ EPOCH_TO_FILETIME(ModifyFileTime, pInfo->modifyTime);
+ EPOCH_TO_FILETIME(AccessFileTime, pInfo->accessTime);
+ EPOCH_TO_FILETIME(CreationFileTime, pInfo->cTime);
/*
* If necessary, set the file times.
*/
- if (modifyTime) {
- /*
- * If the has read only access, we must temporarily turn on
- * write access (this is necessary for native filesystems,
- * but not for NFS filesystems).
- */
+ /*
+ * If the has read only access, we must temporarily turn on
+ * write access (this is necessary for native filesystems,
+ * but not for NFS filesystems).
+ */
- if (tempAttr & FILE_ATTRIBUTE_READONLY) {
- tempAttr &= ~FILE_ATTRIBUTE_READONLY;
- if (!SetFileAttributesW(wname, tempAttr)) {
- return set_error(errInfo);
- }
+ if (tempAttr & FILE_ATTRIBUTE_READONLY) {
+ tempAttr &= ~FILE_ATTRIBUTE_READONLY;
+ if (!SetFileAttributesW(wname, tempAttr)) {
+ return set_error(errInfo);
}
+ }
- fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (fd != INVALID_HANDLE_VALUE) {
- BOOL result = SetFileTime(fd, ctime, atime, mtime);
- if (!result) {
- return set_error(errInfo);
- }
- CloseHandle(fd);
+ fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fd != INVALID_HANDLE_VALUE) {
+ BOOL result = SetFileTime(fd, &CreationFileTime, &AccessFileTime, &ModifyFileTime);
+ if (!result) {
+ return set_error(errInfo);
}
+ CloseHandle(fd);
}
/*
@@ -1138,8 +1115,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */
SysIOVec* iov, /* Vector of buffer structs.
* The structs are unchanged
* after the call */
- int iovcnt, /* Number of structs in vector */
- size_t size) /* Number of bytes to write */
+ int iovcnt) /* Number of structs in vector */
{
int cnt; /* Buffers so far written */
OVERLAPPED overlapped;
diff --git a/erts/emulator/hipe/hipe_abi.txt b/erts/emulator/hipe/hipe_abi.txt
index d0ec162342..9d4726de9d 100644
--- a/erts/emulator/hipe/hipe_abi.txt
+++ b/erts/emulator/hipe/hipe_abi.txt
@@ -62,7 +62,7 @@ exceptional condition, it puts an error code in p->freason
and returns THE_NON_VALUE (zero, except in debug mode).
If p->freason == TRAP, then the BIF redirects its call to some
-other function, given by p->def_arg_reg[].
+other function, given by p->i
The BIF and the new callee may have different arities.
The "hipe_${ARCH}_bifs.m4" macro files take care of these issues
diff --git a/erts/emulator/hipe/hipe_amd64_bifs.m4 b/erts/emulator/hipe/hipe_amd64_bifs.m4
index 0ba763cbea..ec25c0b9b7 100644
--- a/erts/emulator/hipe/hipe_amd64_bifs.m4
+++ b/erts/emulator/hipe/hipe_amd64_bifs.m4
@@ -20,24 +20,37 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_amd64_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
+
`#if THE_NON_VALUE == 0
#define TEST_GOT_EXN testq %rax, %rax
#else
#define TEST_GOT_EXN cmpq $THE_NON_VALUE, %rax
#endif'
-`#define TEST_GOT_MBUF movq P_MBUF(P), %rdx; testq %rdx, %rdx; jnz 3f; 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: call JOIN3(nbif_,ARITY,_gc_after_bif); jmp 2b'
+define(TEST_GOT_MBUF,`movq P_MBUF(P), %rdx # `TEST_GOT_MBUF'
+ testq %rdx, %rdx
+ jnz 3f
+2:')
+define(HANDLE_GOT_MBUF,`
+3: call nbif_$1_gc_after_bif # `HANDLE_GOT_MBUF'
+ jmp 2b')
+
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) movq $CSYM(F), P_BIF_CALLEE(P); call CSYM(hipe_debug_bif_wrapper)
+#else
+# define CALL_BIF(F) call CSYM(F)
+#endif'
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -54,7 +67,11 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ pushq %rsi
+ movq %rsp, %rsi /* Eterm* BIF__ARGS */
+ sub $(8), %rsp /* stack frame 16-byte alignment */
+ CALL_BIF($2)
+ add $(1*8 + 8), %rsp
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -82,7 +99,11 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ pushq %rdx
+ pushq %rsi
+ movq %rsp, %rsi /* Eterm* BIF__ARGS */
+ CALL_BIF($2)
+ add $(2*8), %rsp
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -111,7 +132,13 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ pushq %rcx
+ pushq %rdx
+ pushq %rsi
+ movq %rsp, %rsi /* Eterm* BIF__ARGS */
+ sub $(8), %rsp /* stack frame 16-byte alignment */
+ CALL_BIF($2)
+ add $(3*8 + 8), %rsp
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -124,13 +151,7 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -143,7 +164,7 @@ ASYM($1):
/* make the call on the C stack */
SWITCH_ERLANG_TO_C
- call CSYM($2)
+ CALL_BIF($2)
TEST_GOT_MBUF
SWITCH_C_TO_ERLANG
@@ -528,7 +549,9 @@ ASYM($1):
/*
* AMD64-specific primops.
*/
+#ifndef NO_FPE_SIGNALS
noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu)
+#endif /* NO_FPE_SIGNALS */
/*
* Implement gc_bif_interface_0 as nofail_primop_interface_0.
diff --git a/erts/emulator/hipe/hipe_amd64_primops.h b/erts/emulator/hipe/hipe_amd64_primops.h
index e3c7111997..55cb0eadb8 100644
--- a/erts/emulator/hipe/hipe_amd64_primops.h
+++ b/erts/emulator/hipe/hipe_amd64_primops.h
@@ -19,5 +19,7 @@
PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0)
+#ifndef NO_FPE_SIGNALS
PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception)
+#endif
PRIMOP_LIST(am_sse2_fnegate_mask, &sse2_fnegate_mask)
diff --git a/erts/emulator/hipe/hipe_arm.c b/erts/emulator/hipe/hipe_arm.c
index d52f429a9b..651d0e3a75 100644
--- a/erts/emulator/hipe/hipe_arm.c
+++ b/erts/emulator/hipe/hipe_arm.c
@@ -71,7 +71,7 @@ static struct segment {
} curseg;
#define in_area(ptr,start,nbytes) \
- ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
static void *new_code_mapping(void)
{
@@ -181,11 +181,9 @@ void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *
curseg.base = base;
curseg.code_pos = base;
curseg.tramp_pos = (unsigned int*)((char*)base + SEGMENT_NRBYTES);
-#if defined(__arm__)
curseg.tramp_pos -= 2;
curseg.tramp_pos[0] = 0xE51FF004; /* ldr pc, [pc,#-4] */
curseg.tramp_pos[1] = (unsigned int)&nbif_callemu;
-#endif
address = try_alloc(nrwords, nrcallees, callees, trampvec);
if (!address) {
@@ -214,11 +212,9 @@ static unsigned int *alloc_stub(Uint nrwords, unsigned int **tramp_callemu)
curseg.base = base;
curseg.code_pos = base;
curseg.tramp_pos = (unsigned int*)((char*)base + SEGMENT_NRBYTES);
-#if defined(__arm__)
curseg.tramp_pos -= 2;
curseg.tramp_pos[0] = 0xE51FF004; /* ldr pc, [pc,#-4] */
curseg.tramp_pos[1] = (unsigned int)&nbif_callemu;
-#endif
address = try_alloc(nrwords, 0, NIL, NULL);
if (!address) {
@@ -269,10 +265,8 @@ int hipe_patch_insn(void *address, Uint32 value, Eterm type)
void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
{
unsigned int *code;
-#if defined(__arm__)
unsigned int *tramp_callemu;
int callemu_offset;
-#endif
/*
* Native code calls BEAM via a stub looking as follows:
@@ -288,13 +282,6 @@ void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
* (Trampolines are allowed to modify r12, but they don't.)
*/
-#if !defined(__arm__)
- /* verify that 'ba' can reach nbif_callemu */
- if ((unsigned long)&nbif_callemu & ~0x01FFFFFCUL)
- abort();
-#endif
-
-#if defined(__arm__)
code = alloc_stub(4, &tramp_callemu);
callemu_offset = ((int)&nbif_callemu - ((int)&code[2] + 8)) >> 2;
if (!(callemu_offset >= -0x00800000 && callemu_offset <= 0x007FFFFF)) {
@@ -302,11 +289,7 @@ void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
if (!(callemu_offset >= -0x00800000 && callemu_offset <= 0x007FFFFF))
abort();
}
-#else
- code = alloc_stub(4, &trampoline);
-#endif
-#if defined(__arm__)
/* mov r0, #beamArity */
code[0] = 0xE3A00000 | (beamArity & 0xFF);
/* ldr r8, [pc,#0] // beamAddress */
@@ -315,16 +298,6 @@ void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
code[2] = 0xEA000000 | (callemu_offset & 0x00FFFFFF);
/* .long beamAddress */
code[3] = (unsigned int)beamAddress;
-#else
- /* addi r12,0,beamAddress@l */
- code[0] = 0x39800000 | ((unsigned long)beamAddress & 0xFFFF);
- /* addi r0,0,beamArity */
- code[1] = 0x38000000 | (beamArity & 0x7FFF);
- /* addis r12,r12,beamAddress@ha */
- code[2] = 0x3D8C0000 | at_ha((unsigned long)beamAddress);
- /* ba nbif_callemu */
- code[3] = 0x48000002 | (unsigned long)&nbif_callemu;
-#endif
hipe_flush_icache_range(code, 4*sizeof(int));
@@ -334,60 +307,32 @@ void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
static void patch_b(Uint32 *address, Sint32 offset, Uint32 AA)
{
Uint32 oldI = *address;
-#if defined(__arm__)
Uint32 newI = (oldI & 0xFF000000) | (offset & 0x00FFFFFF);
-#else
- Uint32 newI = (oldI & 0xFC000001) | ((offset & 0x00FFFFFF) << 2) | (AA & 2);
-#endif
*address = newI;
hipe_flush_icache_word(address);
}
int hipe_patch_call(void *callAddress, void *destAddress, void *trampoline)
{
-#if !defined(__arm__)
- if ((Uint32)destAddress == ((Uint32)destAddress & 0x01FFFFFC)) {
- /* The destination is in the [0,32MB[ range.
- We can reach it with a ba/bla instruction.
- This is the typical case for BIFs and primops.
- It's also common for trap-to-BEAM stubs (on ppc32). */
- patch_b((Uint32*)callAddress, (Uint32)destAddress >> 2, 2);
+ Sint32 destOffset = ((Sint32)destAddress - ((Sint32)callAddress+8)) >> 2;
+ if (destOffset >= -0x800000 && destOffset <= 0x7FFFFF) {
+ /* The destination is within a [-32MB,+32MB[ range from us.
+ We can reach it with a b/bl instruction.
+ This is typical for nearby Erlang code. */
+ patch_b((Uint32*)callAddress, destOffset, 0);
} else {
-#endif
-#if defined(__arm__)
- Sint32 destOffset = ((Sint32)destAddress - ((Sint32)callAddress+8)) >> 2;
-#else
- Sint32 destOffset = ((Sint32)destAddress - (Sint32)callAddress) >> 2;
-#endif
- if (destOffset >= -0x800000 && destOffset <= 0x7FFFFF) {
- /* The destination is within a [-32MB,+32MB[ range from us.
- We can reach it with a b/bl instruction.
- This is typical for nearby Erlang code. */
- patch_b((Uint32*)callAddress, destOffset, 0);
- } else {
- /* The destination is too distant for b/bl/ba/bla.
- Must do a b/bl to the trampoline. */
-#if defined(__arm__)
- Sint32 trampOffset = ((Sint32)trampoline - ((Sint32)callAddress+8)) >> 2;
-#else
- Sint32 trampOffset = ((Sint32)trampoline - (Sint32)callAddress) >> 2;
-#endif
- if (trampOffset >= -0x800000 && trampOffset <= 0x7FFFFF) {
- /* Update the trampoline's address computation.
- (May be redundant, but we can't tell.) */
-#if defined(__arm__)
- patch_imm32((Uint32*)trampoline+1, (Uint32)destAddress);
-#else
- patch_li((Uint32*)trampoline, (Uint32)destAddress);
-#endif
- /* Update this call site. */
- patch_b((Uint32*)callAddress, trampOffset, 0);
- } else
- return -1;
- }
-#if !defined(__arm__)
+ /* The destination is too distant for b/bl.
+ Must do a b/bl to the trampoline. */
+ Sint32 trampOffset = ((Sint32)trampoline - ((Sint32)callAddress+8)) >> 2;
+ if (trampOffset >= -0x800000 && trampOffset <= 0x7FFFFF) {
+ /* Update the trampoline's address computation.
+ (May be redundant, but we can't tell.) */
+ patch_imm32((Uint32*)trampoline+1, (Uint32)destAddress);
+ /* Update this call site. */
+ patch_b((Uint32*)callAddress, trampOffset, 0);
+ } else
+ return -1;
}
-#endif
return 0;
}
diff --git a/erts/emulator/hipe/hipe_arm_bifs.m4 b/erts/emulator/hipe/hipe_arm_bifs.m4
index 3664fb6502..17c013f1fb 100644
--- a/erts/emulator/hipe/hipe_arm_bifs.m4
+++ b/erts/emulator/hipe/hipe_arm_bifs.m4
@@ -20,18 +20,27 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_arm_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
.text
.p2align 2
-`#define JOIN3(A,B,C) A##B##C
-#define TEST_GOT_MBUF(ARITY) ldr r1, [P, #P_MBUF]; cmp r1, #0; blne JOIN3(nbif_,ARITY,_gc_after_bif)'
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) ldr r14, =F; str r14, [r0, #P_BIF_CALLEE]; bl hipe_debug_bif_wrapper
+#else
+# define CALL_BIF(F) bl F
+#endif'
+
+define(TEST_GOT_MBUF,`ldr r1, [P, #P_MBUF] /* `TEST_GOT_MBUF' */
+ cmp r1, #0
+ blne nbif_$1_gc_after_bif')
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
* Generate native interface for a BIF with 1-3 parameters and
* standard failure mode.
@@ -48,7 +57,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(1)
/* Restore registers. Check for exception. */
@@ -56,6 +67,7 @@ $1:
RESTORE_CONTEXT_BIF
beq nbif_1_simple_exception
NBIF_RET(1)
+ .ltorg /* needed by LDR in debug version of `CALL_BIF' */
.size $1, .-$1
.type $1, %function
#endif')
@@ -73,7 +85,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ str r2, [r0, #P_ARG1]
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(2)
/* Restore registers. Check for exception. */
@@ -81,6 +96,7 @@ $1:
RESTORE_CONTEXT_BIF
beq nbif_2_simple_exception
NBIF_RET(2)
+ .ltorg
.size $1, .-$1
.type $1, %function
#endif')
@@ -99,7 +115,11 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ str r2, [r0, #P_ARG1]
+ str r3, [r0, #P_ARG2]
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(3)
/* Restore registers. Check for exception. */
@@ -107,17 +127,12 @@ $1:
RESTORE_CONTEXT_BIF
beq nbif_3_simple_exception
NBIF_RET(3)
+ .ltorg
.size $1, .-$1
.type $1, %function
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -128,7 +143,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF(0)
/* Restore registers. Check for exception. */
@@ -136,6 +152,7 @@ $1:
RESTORE_CONTEXT_BIF
beq nbif_0_simple_exception
NBIF_RET(0)
+ .ltorg
.size $1, .-$1
.type $1, %function
#endif')
@@ -160,7 +177,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF(0)
/* Restore registers. */
@@ -182,7 +200,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(1)
/* Restore registers. Check for exception. */
@@ -207,7 +227,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl $2
+ str r1, [r0, #P_ARG0] /* Store BIF__ARGS in def_arg_reg[] */
+ str r2, [r0, #P_ARG1]
+ add r1, r0, #P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF(2)
/* Restore registers. Check for exception. */
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index e7fb850530..23ced284bf 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2012. All Rights Reserved.
*
* The 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,8 +174,13 @@ static inline unsigned char *bytearray_lvalue(Eterm bin, Eterm idx)
{
Sint i;
unsigned char *bytes;
+#ifndef DEBUG
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
+ ERTS_DECLARE_DUMMY(Uint bitsize);
+#else
Uint bitoffs;
Uint bitsize;
+#endif
if (is_not_binary(bin) ||
is_not_small(idx) ||
@@ -235,9 +240,15 @@ BIF_RETTYPE hipe_bifs_bitarray_2(BIF_ALIST_2)
BIF_RETTYPE hipe_bifs_bitarray_update_3(BIF_ALIST_3)
{
unsigned char *bytes, bytemask;
- Uint bitoffs, bitsize;
Uint bitnr, bytenr;
int set;
+#ifndef DEBUG
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
+ ERTS_DECLARE_DUMMY(Uint bitsize);
+#else
+ Uint bitoffs;
+ Uint bitsize;
+#endif
if (is_not_binary(BIF_ARG_1))
BIF_ERROR(BIF_P, BADARG);
@@ -267,8 +278,15 @@ BIF_RETTYPE hipe_bifs_bitarray_update_3(BIF_ALIST_3)
BIF_RETTYPE hipe_bifs_bitarray_sub_2(BIF_ALIST_2)
{
unsigned char *bytes, bytemask;
- Uint bitoffs, bitsize;
Uint bitnr, bytenr;
+#ifndef DEBUG
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
+ ERTS_DECLARE_DUMMY(Uint bitsize);
+#else
+ Uint bitoffs;
+ Uint bitsize;
+#endif
+
if (is_not_binary(BIF_ARG_1))
BIF_ERROR(BIF_P, BADARG);
@@ -397,10 +415,15 @@ BIF_RETTYPE hipe_bifs_enter_code_2(BIF_ALIST_2)
Uint nrbytes;
void *bytes;
void *address;
- Uint bitoffs;
- Uint bitsize;
Eterm trampolines;
Eterm *hp;
+#ifndef DEBUG
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
+ ERTS_DECLARE_DUMMY(Uint bitsize);
+#else
+ Uint bitoffs;
+ Uint bitsize;
+#endif
if (is_not_binary(BIF_ARG_1))
BIF_ERROR(BIF_P, BADARG);
@@ -985,6 +1008,26 @@ BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1)
BIF_RET(res);
}
+#ifdef NO_FPE_SIGNALS
+
+/*
+ This is the current solution to make hipe run without FPE.
+ The native code is the same except that a call to this primop
+ is made after _every_ float operation to check the result.
+ The native fcheckerror still done later will detect if an
+ "emulated" FPE has occured.
+ We use p->hipe.float_result to avoid passing a 'double' argument,
+ which has its own calling convention (on amd64 at least).
+ Simple and slow...
+*/
+void hipe_emulate_fpe(Process* p)
+{
+ if (!finite(p->hipe.float_result)) {
+ p->fp_exception = 1;
+ }
+}
+#endif
+
#if 0 /* XXX: unused */
/*
* At least parts of this should be inlined in native code.
@@ -1050,10 +1093,8 @@ BIF_RETTYPE hipe_bifs_make_fun_3(BIF_ALIST_3)
if (is_not_nil(free_vars))
BIF_ERROR(BIF_P, BADARG);
-#ifndef HYBRID /* FIND ME! */
funp->next = MSO(BIF_P).funs;
MSO(BIF_P).funs = funp;
-#endif
BIF_RET(make_fun(funp));
}
@@ -1714,6 +1755,41 @@ BIF_RETTYPE hipe_bifs_mark_referred_from_1(BIF_ALIST_1) /* get_refs_from */
BIF_RET(NIL);
}
+/* Called by init:restart after unloading all hipe compiled modules
+ * to work around bug causing execution of deallocated beam code.
+ * Can be removed when delete/purge of native modules works better.
+ * Test: Do init:restart in debug compiled vm with hipe compiled kernel.
+ */
+static void hipe_purge_all_refs(void)
+{
+ struct hipe_mfa_info **bucket;
+ unsigned int i, nrbuckets;
+
+ hipe_mfa_info_table_lock();
+
+ bucket = hipe_mfa_info_table.bucket;
+ nrbuckets = 1 << hipe_mfa_info_table.log2size;
+ for (i = 0; i < nrbuckets; ++i) {
+ while (bucket[i] != NULL) {
+ struct hipe_mfa_info* mfa = bucket[i];
+ bucket[i] = mfa->bucket.next;
+
+ while (mfa->refers_to) {
+ struct hipe_mfa_info_list *to = mfa->refers_to;
+ mfa->refers_to = to->next;
+ erts_free(ERTS_ALC_T_HIPE, to);
+ }
+ while (mfa->referred_from) {
+ struct ref* from = mfa->referred_from;
+ mfa->referred_from = from->next;
+ erts_free(ERTS_ALC_T_HIPE, from);
+ }
+ erts_free(ERTS_ALC_T_HIPE, mfa);
+ }
+ }
+ hipe_mfa_info_table_unlock();
+}
+
BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1)
{
struct mfa mfa;
@@ -1721,6 +1797,11 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1)
struct hipe_mfa_info_list *refers_to, *tmp_refers_to;
struct ref **prev, *ref;
+ if (BIF_ARG_1 == am_all) {
+ hipe_purge_all_refs();
+ BIF_RET(NIL);
+ }
+
if (!term_to_mfa(BIF_ARG_1, &mfa))
BIF_ERROR(BIF_P, BADARG);
hipe_mfa_info_table_lock();
@@ -1758,6 +1839,7 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1)
BIF_RET(NIL);
}
+
/* redirect_referred_from(CalleeMFA)
* Redirect all pending-redirect refs in CalleeMFA's referred_from.
* Then remove any pending-redirect && pending-remove refs from CalleeMFA's referred_from.
diff --git a/erts/emulator/hipe/hipe_bif0.h b/erts/emulator/hipe/hipe_bif0.h
index f02e8862dc..c512d66f9d 100644
--- a/erts/emulator/hipe/hipe_bif0.h
+++ b/erts/emulator/hipe/hipe_bif0.h
@@ -29,7 +29,7 @@ extern Uint *hipe_bifs_find_pc_from_mfa(Eterm mfa);
extern void hipe_mfa_info_table_init(void);
extern void *hipe_get_remote_na(Eterm m, Eterm f, unsigned int a);
-extern Eterm hipe_find_na_or_make_stub(Process*, Eterm, Eterm, Eterm);
+extern BIF_RETTYPE hipe_find_na_or_make_stub(BIF_ALIST_3);
extern int hipe_find_mfa_from_ra(const void *ra, Eterm *m, Eterm *f, unsigned int *a);
#if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
extern void *hipe_mfa_get_trampoline(Eterm m, Eterm f, unsigned int a);
diff --git a/erts/emulator/hipe/hipe_bif0.tab b/erts/emulator/hipe/hipe_bif0.tab
index b6c6bede23..ce641365e9 100644
--- a/erts/emulator/hipe/hipe_bif0.tab
+++ b/erts/emulator/hipe/hipe_bif0.tab
@@ -140,3 +140,5 @@ atom bs_put_utf16le
atom bs_get_utf16
atom bs_validate_unicode
atom bs_validate_unicode_retract
+atom emulate_fpe
+
diff --git a/erts/emulator/hipe/hipe_bif1.c b/erts/emulator/hipe/hipe_bif1.c
index 87cdfb8c7a..64de754e18 100644
--- a/erts/emulator/hipe/hipe_bif1.c
+++ b/erts/emulator/hipe/hipe_bif1.c
@@ -449,7 +449,7 @@ BIF_RETTYPE hipe_bifs_gc_info_0(BIF_ALIST_0)
BIF_RETTYPE hipe_bifs_shared_gc_info_0(BIF_ALIST_0)
{
#ifdef __BENCHMARK__
-#if !(defined(BM_COUNTERS) && defined(HYBRID))
+#if !(defined(BM_COUNTERS))
Uint minor_global_gc = 0;
Uint major_global_gc = 0;
#endif
@@ -459,17 +459,9 @@ BIF_RETTYPE hipe_bifs_shared_gc_info_0(BIF_ALIST_0)
#endif
Eterm *hp;
-#if defined(HYBRID)
- Uint tmp_used_heap = (Uint)((BIF_P->htop - BIF_P->heap) +
- (OLD_HTOP(BIF_P) - OLD_HEAP(BIF_P)) +
- MBUF_SIZE(BIF_P));
- Uint tmp_allocated_heap = (Uint)((BIF_P->hend - BIF_P->heap) +
- (OLD_HEND(BIF_P) - OLD_HEAP(BIF_P)) +
- MBUF_SIZE(BIF_P));
-#else
Uint tmp_used_heap = 0;
Uint tmp_allocated_heap = 0;
-#endif
+
hp = HAlloc(BIF_P, 7);
BIF_RET(TUPLE6(hp,
make_small((uint)minor_global_gc),
@@ -486,7 +478,7 @@ BIF_RETTYPE hipe_bifs_shared_gc_info_0(BIF_ALIST_0)
BIF_RETTYPE hipe_bifs_incremental_gc_info_0(BIF_ALIST_0)
{
#ifdef __BENCHMARK__
-#if !(defined(BM_COUNTERS) && defined(INCREMENTAL))
+#if !defined(BM_COUNTERS)
Uint minor_gc_cycles = 0;
Uint major_gc_cycles = 0;
Uint minor_gc_stages = 0;
@@ -512,17 +504,6 @@ BIF_RETTYPE hipe_bifs_gc_info_clear_0(BIF_ALIST_0)
#ifdef BM_COUNTERS
minor_gc = 0;
major_gc = 0;
-#ifdef HYBRID
- minor_global_gc = 0;
- major_global_gc = 0;
- gc_in_copy = 0;
-#ifdef INCREMENTAL
- minor_gc_cycles = 0;
- major_gc_cycles = 0;
- minor_gc_stages = 0;
- major_gc_stages = 0;
-#endif
-#endif
#endif
#ifdef BM_HEAP_SIZES
diff --git a/erts/emulator/hipe/hipe_bif2.c b/erts/emulator/hipe/hipe_bif2.c
index 2660f74a82..37a1cc193b 100644
--- a/erts/emulator/hipe/hipe_bif2.c
+++ b/erts/emulator/hipe/hipe_bif2.c
@@ -151,18 +151,25 @@ BIF_RETTYPE hipe_bifs_modeswitch_debug_off_0(BIF_ALIST_0)
BIF_RET(am_true);
}
-/* BIFs for handling the message area */
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
-BIF_RETTYPE hipe_bifs_show_message_area_0(BIF_ALIST_0)
+BIF_RETTYPE hipe_debug_bif_wrapper(BIF_ALIST_1);
+
+# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN)
+# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_unrequire_lock((P), ERTS_PROC_LOCK_MAIN)
+
+BIF_RETTYPE hipe_debug_bif_wrapper(BIF_ALIST_1)
{
-#ifdef HYBRID
-#ifdef DEBUG
- print_message_area();
-#else
- printf("Only available in debug compiled emulator\r\n");
-#endif
- BIF_RET(am_true);
-#else
- BIF_RET(am_false);
-#endif
+ typedef BIF_RETTYPE Bif(BIF_ALIST_1);
+ Bif* fp = (Bif*) (BIF_P->hipe.bif_callee);
+ BIF_RETTYPE res;
+ ERTS_SMP_UNREQ_PROC_MAIN_LOCK(BIF_P);
+ res = (*fp)(BIF_P, BIF__ARGS);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(BIF_P);
+ return res;
}
+
+#endif /* ERTS_ENABLE_LOCK_CHECK && ERTS_SMP */
+
diff --git a/erts/emulator/hipe/hipe_bif2.tab b/erts/emulator/hipe/hipe_bif2.tab
index 51323ce7af..aac27e8bed 100644
--- a/erts/emulator/hipe/hipe_bif2.tab
+++ b/erts/emulator/hipe/hipe_bif2.tab
@@ -29,4 +29,3 @@ bif hipe_bifs:show_term/1
bif hipe_bifs:in_native/0
bif hipe_bifs:modeswitch_debug_on/0
bif hipe_bifs:modeswitch_debug_off/0
-bif hipe_bifs:show_message_area/0
diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4
index 083788997b..942fa0c5cb 100644
--- a/erts/emulator/hipe/hipe_bif_list.m4
+++ b/erts/emulator/hipe/hipe_bif_list.m4
@@ -70,24 +70,18 @@
****************************************************************/
/*
+ * standard_bif_interface_0(nbif_name, cbif_name)
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
*
- * A BIF with implicit P parameter, 1-3 ordinary parameters,
+ * A BIF with implicit P parameter, 0-3 ordinary parameters,
* which may fail.
* HP and FCALLS may be read and updated.
* HP_LIMIT, NSP, NSP_LIMIT, and NRA may not be accessed.
*/
/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * A zero-arity BIF which may fail, otherwise
- * identical to standard_bif_interface_N.
- */
-
-/*
* nofail_primop_interface_0(nbif_name, cbif_name)
* nofail_primop_interface_1(nbif_name, cbif_name)
* nofail_primop_interface_2(nbif_name, cbif_name)
@@ -150,8 +144,7 @@
/*
* Zero-arity BIFs that can fail.
*/
-fail_bif_interface_0(nbif_memory_0, memory_0)
-fail_bif_interface_0(nbif_processes_0, processes_0)
+standard_bif_interface_0(nbif_processes_0, processes_0)
/*
* BIFs and primops that may do a GC (change heap limit and walk the native stack).
@@ -176,10 +169,10 @@ gc_bif_interface_0(nbif_hipe_bifs_nstack_used_size_0, hipe_bifs_nstack_used_size
/*
* Arithmetic operators called indirectly by the HiPE compiler.
*/
-standard_bif_interface_2(nbif_add_2, erts_mixed_plus)
-standard_bif_interface_2(nbif_sub_2, erts_mixed_minus)
-standard_bif_interface_2(nbif_mul_2, erts_mixed_times)
-standard_bif_interface_2(nbif_div_2, erts_mixed_div)
+standard_bif_interface_2(nbif_add_2, splus_2)
+standard_bif_interface_2(nbif_sub_2, sminus_2)
+standard_bif_interface_2(nbif_mul_2, stimes_2)
+standard_bif_interface_2(nbif_div_2, div_2)
standard_bif_interface_2(nbif_intdiv_2, intdiv_2)
standard_bif_interface_2(nbif_rem_2, rem_2)
standard_bif_interface_2(nbif_bsl_2, bsl_2)
@@ -252,6 +245,10 @@ noproc_primop_interface_5(nbif_bs_put_big_integer, hipe_bs_put_big_integer)
gc_bif_interface_0(nbif_check_get_msg, hipe_check_get_msg)
+#ifdef NO_FPE_SIGNALS
+nocons_nofail_primop_interface_0(nbif_emulate_fpe, hipe_emulate_fpe)
+#endif
+
/*
* SMP-specific stuff
*/
@@ -261,11 +258,6 @@ noproc_primop_interface_1(nbif_atomic_inc, hipe_atomic_inc)
',)dnl
/*
- * Implement standard_bif_interface_0 as nofail_primop_interface_0.
- */
-define(standard_bif_interface_0,`nofail_primop_interface_0($1, $2)')
-
-/*
* Standard BIFs.
* BIF_LIST(ModuleAtom,FunctionAtom,Arity,CFun,Index)
*/
diff --git a/erts/emulator/hipe/hipe_gc.c b/erts/emulator/hipe/hipe_gc.c
index 0199dea99e..07e4b8a4d6 100644
--- a/erts/emulator/hipe/hipe_gc.c
+++ b/erts/emulator/hipe/hipe_gc.c
@@ -46,9 +46,14 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
char *src, *oh;
Uint src_size, oh_size;
+ if (!p->hipe.nstack) {
+ ASSERT(!p->hipe.nsp && !p->hipe.nstend);
+ return n_htop;
+ }
if (!nstack_walk_init_check(p))
return n_htop;
+ ASSERT(p->hipe.nsp && p->hipe.nstend);
nsp = nstack_walk_nsp_begin(p);
nsp_end = p->hipe.nstgraylim;
if (nsp_end)
@@ -136,9 +141,14 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
char *heap;
Uint heap_size, mature_size;
+ if (!p->hipe.nstack) {
+ ASSERT(!p->hipe.nsp && !p->hipe.nstend);
+ return;
+ }
if (!nstack_walk_init_check(p))
return;
+ ASSERT(p->hipe.nsp && p->hipe.nstend);
nsp = nstack_walk_nsp_begin(p);
nsp_end = p->hipe.nstgraylim;
if (nsp_end) {
@@ -227,329 +237,3 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
}
abort();
}
-
-#ifdef HYBRID
-
-#ifdef INCREMENTAL
-Eterm *ma_fullsweep_nstack(Process *p, Eterm *n_htop, Eterm *n_hend)
-{
- /* known nstack walk state */
- Eterm *nsp;
- Eterm *nsp_end;
- const struct sdesc *sdesc;
- unsigned int sdesc_size;
- unsigned long ra;
- unsigned int i;
- unsigned int mask;
- /* arch-specific nstack walk state */
- struct nstack_walk_state walk_state;
-
- if (!nstack_walk_init_check(p))
- return n_htop;
-
- nsp = nstack_walk_nsp_begin(p);
- nsp_end = nstack_walk_nsp_end(p);
-
- sdesc = nstack_walk_init_sdesc(p, &walk_state);
-
- for (;;) {
- if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
- if (nsp == nsp_end)
- return n_htop;
- fprintf(stderr, "%s: passed end of stack\r\n", __FUNCTION__);
- break;
- }
- sdesc_size = nstack_walk_frame_size(sdesc);
- i = 0;
- mask = sdesc->livebits[0];
- for (;;) {
- if (mask & 1) {
- Eterm *nsp_i = nstack_walk_frame_index(nsp, i);
- Eterm val = *nsp_i;
- Eterm *obj_ptr = ptr_val(val);
- switch (primary_tag(val)) {
- case TAG_PRIMARY_LIST:
- COPYMARK_CONS(obj_ptr, n_htop, nsp_i, n_hend);
- break;
- case TAG_PRIMARY_BOXED:
- COPYMARK_BOXED(obj_ptr, n_htop, nsp_i, n_hend);
- break;
- default:
- break;
- }
- }
- if (++i >= sdesc_size)
- break;
- if (i & 31)
- mask >>= 1;
- else
- mask = sdesc->livebits[i >> 5];
- }
- ra = nstack_walk_frame_ra(nsp, sdesc);
- if (ra == (unsigned long)nbif_stack_trap_ra)
- ra = (unsigned long)p->hipe.ngra;
- sdesc = hipe_find_sdesc(ra);
- nsp = nstack_walk_next_frame(nsp, sdesc_size);
- }
- abort();
-}
-
-void ma_gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
-{
- /* known nstack walk state */
- Eterm *nsp;
- Eterm *nsp_end;
- const struct sdesc *sdesc;
- unsigned int sdesc_size;
- unsigned long ra;
- unsigned int i;
- unsigned int mask;
- /* arch-specific nstack walk state */
- struct nstack_walk_state walk_state;
-
- /* ma_gensweep-specific state */
- Eterm *low_water, *high_water, *surface;
- Eterm *n_htop;
- Eterm *old_htop;
-
- if (!nstack_walk_init_check(p))
- return;
-
- nsp = nstack_walk_nsp_begin(p);
- nsp_end = nstack_walk_nsp_end(p);
-
- low_water = global_heap;
- //high_water = global_high_water;
- surface = global_htop;
-
- old_htop = *ptr_old_htop;
- n_htop = *ptr_n_htop;
-
- sdesc = nstack_walk_init_sdesc(p, &walk_state);
-
- for (;;) {
- if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
- if (nsp == nsp_end) {
- *ptr_old_htop = old_htop;
- *ptr_n_htop = n_htop;
- return;
- }
- fprintf(stderr, "%s: passed end of stack\r\n", __FUNCTION__);
- break;
- }
- sdesc_size = nstack_walk_frame_size(sdesc);
- i = 0;
- mask = sdesc->livebits[0];
- for (;;) {
- if (mask & 1) {
- Eterm *nsp_i = nstack_walk_frame_index(nsp, i);
- Eterm gval = *nsp_i;
- if (is_boxed(gval)) {
- Eterm *ptr = boxed_val(gval);
- Eterm val = *ptr;
- if (MY_IS_MOVED(val)) {
- *nsp_i = val;
- } else if (ptr_within(ptr, low_water, high_water)) {
- MOVE_BOXED(ptr, val, old_htop, nsp_i);
- } else if (ptr_within(ptr, high_water, surface)) {
- MOVE_BOXED(ptr, val, n_htop, nsp_i);
- }
- } else if (is_list(gval)) {
- Eterm *ptr = list_val(gval);
- Eterm val = *ptr;
- if (is_non_value(val)) {
- *nsp_i = ptr[1];
- } else if (ptr_within(ptr, low_water, high_water)) {
- MOVE_CONS(ptr, val, old_htop, nsp_i);
- } else if (ptr_within(ptr, high_water, surface)) {
- MOVE_CONS(ptr, val, n_htop, nsp_i);
- }
- }
- }
- if (++i >= sdesc_size)
- break;
- if (i & 31)
- mask >>= 1;
- else
- mask = sdesc->livebits[i >> 5];
- }
- ra = nstack_walk_frame_ra(nsp, sdesc);
- if (ra == (unsigned long)nbif_stack_trap_ra)
- ra = (unsigned long)p->hipe.ngra;
- sdesc = hipe_find_sdesc(ra);
- nsp = nstack_walk_next_frame(nsp, sdesc_size);
- }
- abort();
-}
-
-#else /* not INCREMENTAL */
-
-Eterm *ma_fullsweep_nstack(Process *p, Eterm *n_htop)
-{
- /* known nstack walk state */
- Eterm *nsp;
- Eterm *nsp_end;
- const struct sdesc *sdesc;
- unsigned int sdesc_size;
- unsigned long ra;
- unsigned int i;
- unsigned int mask;
- /* arch-specific nstack walk state */
- struct nstack_walk_state walk_state;
-
- /* ma_fullsweep-specific state */
- Eterm *gheap = global_heap;
- Eterm *ghtop = global_htop;
- Eterm *goheap = global_old_heap;
- Eterm *gohtop = global_old_htop;
-
- if (!nstack_walk_init_check(p))
- return n_htop;
-
- nsp = nstack_walk_nsp_begin(p);
- nsp_end = nstack_walk_nsp_end(p);
-
- sdesc = nstack_walk_init_sdesc(p, &walk_state);
-
- for (;;) {
- if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
- if (nsp == nsp_end)
- return n_htop;
- fprintf(stderr, "%s: passed end of stack\r\n", __FUNCTION__);
- break;
- }
- sdesc_size = nstack_walk_frame_size(sdesc);
- i = 0;
- mask = sdesc->livebits[0];
- for (;;) {
- if (mask & 1) {
- Eterm *nsp_i = nstack_walk_frame_index(nsp, i);
- Eterm gval = *nsp_i;
- if (is_boxed(gval)) {
- Eterm *ptr = boxed_val(gval);
- Eterm val = *ptr;
- if (MY_IS_MOVED(val)) {
- *nsp_i = val;
- } else if (ptr_within(ptr, gheap, ghtop)) {
- MOVE_BOXED(ptr, val, n_htop, nsp_i);
- } else if (ptr_within(ptr, goheap, gohtop)) {
- MOVE_BOXED(ptr, val, n_htop, nsp_i);
- }
- } else if (is_list(gval)) {
- Eterm *ptr = list_val(gval);
- Eterm val = *ptr;
- if (is_non_value(val)) {
- *nsp_i = ptr[1];
- } else if (ptr_within(ptr, gheap, ghtop)) {
- MOVE_CONS(ptr, val, n_htop, nsp_i);
- } else if (ptr_within(ptr, gheap, ghtop)) {
- MOVE_CONS(ptr, val, n_htop, nsp_i);
- }
- }
- }
- if (++i >= sdesc_size)
- break;
- if (i & 31)
- mask >>= 1;
- else
- mask = sdesc->livebits[i >> 5];
- }
- ra = nstack_walk_frame_ra(nsp, sdesc);
- if (ra == (unsigned long)nbif_stack_trap_ra)
- ra = (unsigned long)p->hipe.ngra;
- sdesc = hipe_find_sdesc(ra);
- nsp = nstack_walk_next_frame(nsp, sdesc_size);
- }
- abort();
-}
-
-void ma_gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
-{
- /* known nstack walk state */
- Eterm *nsp;
- Eterm *nsp_end;
- const struct sdesc *sdesc;
- unsigned int sdesc_size;
- unsigned long ra;
- unsigned int i;
- unsigned int mask;
- /* arch-specific nstack walk state */
- struct nstack_walk_state walk_state;
-
- /* ma_gensweep-specific state */
- Eterm *low_water, *high_water, *surface;
- Eterm *n_htop;
- Eterm *old_htop;
-
- if (!nstack_walk_init_check(p))
- return;
-
- nsp = nstack_walk_nsp_begin(p);
- nsp_end = nstack_walk_nsp_end(p);
-
- low_water = global_heap;
- high_water = global_high_water;
- surface = global_htop;
-
- old_htop = *ptr_old_htop;
- n_htop = *ptr_n_htop;
-
- sdesc = nstack_walk_init_sdesc(p, &walk_state);
-
- for (;;) {
- if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
- if (nsp == nsp_end) {
- *ptr_old_htop = old_htop;
- *ptr_n_htop = n_htop;
- return;
- }
- fprintf(stderr, "%s: passed end of stack\r\n", __FUNCTION__);
- break;
- }
- sdesc_size = nstack_walk_frame_size(sdesc);
- i = 0;
- mask = sdesc->livebits[0];
- for (;;) {
- if (mask & 1) {
- Eterm *nsp_i = nstack_walk_frame_index(nsp, i);
- Eterm gval = *nsp_i;
- if (is_boxed(gval)) {
- Eterm *ptr = boxed_val(gval);
- Eterm val = *ptr;
- if (MY_IS_MOVED(val)) {
- *nsp_i = val;
- } else if (ptr_within(ptr, low_water, high_water)) {
- MOVE_BOXED(ptr, val, old_htop, nsp_i);
- } else if (ptr_within(ptr, high_water, surface)) {
- MOVE_BOXED(ptr, val, n_htop, nsp_i);
- }
- } else if (is_list(gval)) {
- Eterm *ptr = list_val(gval);
- Eterm val = *ptr;
- if (is_non_value(val)) {
- *nsp_i = ptr[1];
- } else if (ptr_within(ptr, low_water, high_water)) {
- MOVE_CONS(ptr, val, old_htop, nsp_i);
- } else if (ptr_within(ptr, high_water, surface)) {
- MOVE_CONS(ptr, val, n_htop, nsp_i);
- }
- }
- }
- if (++i >= sdesc_size)
- break;
- if (i & 31)
- mask >>= 1;
- else
- mask = sdesc->livebits[i >> 5];
- }
- ra = nstack_walk_frame_ra(nsp, sdesc);
- if (ra == (unsigned long)nbif_stack_trap_ra)
- ra = (unsigned long)p->hipe.ngra;
- sdesc = hipe_find_sdesc(ra);
- nsp = nstack_walk_next_frame(nsp, sdesc_size);
- }
- abort();
-}
-#endif /* INCREMENTAL */
-
-#endif /* HYBRID */
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index bced90785d..6e9041c84a 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -1,9 +1,8 @@
/*
* %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
@@ -212,6 +211,11 @@ static const unsigned int CRCTABLE[256] = {
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};
+/* For hipe cross compiler. Hard code all values.
+ No calls by hipe compiler to query the running emulator.
+*/
+static int is_xcomp = 0;
+
/*
* The algorithm for calculating the 32 bit CRC checksum is based upon
* documentation and algorithms provided by Dr. Ross N. Williams in the
@@ -243,7 +247,7 @@ crc_update_buf(unsigned int crc_value,
}
static unsigned int
-crc_update_int(unsigned int crc_value, const unsigned int *p)
+crc_update_int(unsigned int crc_value, const int *p)
{
return crc_update_buf(crc_value, p, sizeof *p);
}
@@ -256,7 +260,7 @@ crc_update_int(unsigned int crc_value, const unsigned int *p)
*/
static const struct literal {
const char *name;
- unsigned int value;
+ int value;
} literals[] = {
/* Field offsets in a process struct */
{ "P_HP", offsetof(struct process, htop) },
@@ -289,6 +293,14 @@ static const struct literal {
{ "P_NRA", offsetof(struct process, hipe.nra) },
#endif
{ "P_NARITY", offsetof(struct process, hipe.narity) },
+ { "P_FLOAT_RESULT",
+# ifdef NO_FPE_SIGNALS
+ offsetof(struct process, hipe.float_result)
+# endif
+ },
+# if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+ { "P_BIF_CALLEE", offsetof(struct process, hipe.bif_callee) },
+# endif
#endif /* HIPE */
/* process flags bits */
@@ -298,7 +310,7 @@ static const struct literal {
{ "FREASON_TRAP", TRAP },
/* special Erlang constants */
- { "THE_NON_VALUE", THE_NON_VALUE },
+ { "THE_NON_VALUE", (int)THE_NON_VALUE },
/* funs */
#ifdef HIPE
@@ -452,18 +464,14 @@ static const struct rts_param {
unsigned int nr;
const char *name;
unsigned int is_defined;
- unsigned int value;
+ int value;
} rts_params[] = {
{ 1, "P_OFF_HEAP_FUNS",
-#if !defined(HYBRID)
1, offsetof(struct process, off_heap.first)
-#endif
},
{ 4, "EFT_NEXT",
-#if !defined(HYBRID)
1, offsetof(struct erl_fun_thing, next)
-#endif
},
/* These are always defined, but their values depend on the
@@ -484,7 +492,7 @@ static const struct rts_param {
#endif
},
{ 14, "P_FP_EXCEPTION",
-#if !defined(NO_FPE_SIGNALS)
+#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
1, offsetof(struct process, fp_exception)
#endif
},
@@ -497,6 +505,15 @@ static const struct rts_param {
0
#endif
},
+ /* This flag is always defined, but its value is configuration-dependent. */
+ { 16, "ERTS_NO_FPE_SIGNALS",
+ 1,
+#if defined(NO_FPE_SIGNALS)
+ 1
+#else
+ 0
+#endif
+ },
/* This parameter is always defined, but its value depends on ERTS_SMP. */
{ 19, "MSG_MESSAGE",
1, offsetof(struct erl_mesg, m[0])
@@ -528,12 +545,12 @@ static void compute_crc(void)
static void c_define_literal(FILE *fp, const struct literal *literal)
{
- fprintf(fp, "#define %s %u\n", literal->name, literal->value);
+ fprintf(fp, "#define %s %d\n", literal->name, literal->value);
}
static void e_define_literal(FILE *fp, const struct literal *literal)
{
- fprintf(fp, "-define(%s, %u).\n", literal->name, literal->value);
+ fprintf(fp, "-define(%s, %d).\n", literal->name, literal->value);
}
static void print_literals(FILE *fp, void (*print_literal)(FILE*, const struct literal*))
@@ -560,7 +577,7 @@ static void print_atom_literals(FILE *fp, void (*print_atom_literal)(FILE*, cons
static void c_define_param(FILE *fp, const struct rts_param *param)
{
if (param->is_defined)
- fprintf(fp, "#define %s %u\n", param->name, param->value);
+ fprintf(fp, "#define %s %d\n", param->name, param->value);
}
static void c_case_param(FILE *fp, const struct rts_param *param)
@@ -568,7 +585,7 @@ static void c_case_param(FILE *fp, const struct rts_param *param)
fprintf(fp, " \\\n");
fprintf(fp, "\tcase %u: ", param->nr);
if (param->is_defined)
- fprintf(fp, "value = %u", param->value);
+ fprintf(fp, "value = %d", param->value);
else
fprintf(fp, "is_defined = 0");
fprintf(fp, "; break;");
@@ -576,7 +593,15 @@ static void c_case_param(FILE *fp, const struct rts_param *param)
static void e_define_param(FILE *fp, const struct rts_param *param)
{
- fprintf(fp, "-define(%s, hipe_bifs:get_rts_param(%u)).\n", param->name, param->nr);
+ if (is_xcomp) {
+ if (param->is_defined)
+ fprintf(fp, "-define(%s, %d).\n", param->name, param->value);
+ else
+ fprintf(fp, "-define(%s, []).\n", param->name);
+ }
+ else {
+ fprintf(fp, "-define(%s, hipe_bifs:get_rts_param(%u)).\n", param->name, param->nr);
+ }
}
static void print_params(FILE *fp, void (*print_param)(FILE*,const struct rts_param*))
@@ -613,19 +638,40 @@ static int do_e(FILE *fp, const char* this_exe)
fprintf(fp, "\n");
print_params(fp, e_define_param);
fprintf(fp, "\n");
- fprintf(fp, "-define(HIPE_SYSTEM_CRC, hipe_bifs:system_crc(%u)).\n", literals_crc);
+ if (is_xcomp) {
+ fprintf(fp, "-define(HIPE_SYSTEM_CRC, %u).\n", system_crc);
+ }
+ else {
+ fprintf(fp, "-define(HIPE_SYSTEM_CRC, hipe_bifs:system_crc(%u)).\n",
+ literals_crc);
+ }
return 0;
}
int main(int argc, const char **argv)
{
+ int i;
+ int (*do_func_ptr)(FILE *, const char*) = NULL;
+
compute_crc();
- if (argc == 2) {
- if (strcmp(argv[1], "-c") == 0)
- return do_c(stdout, argv[0]);
- if (strcmp(argv[1], "-e") == 0)
- return do_e(stdout, argv[0]);
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-c") == 0)
+ do_func_ptr = &do_c;
+ else if (strcmp(argv[i], "-e") == 0)
+ do_func_ptr = &do_e;
+ else if (strcmp(argv[i], "-x") == 0)
+ is_xcomp = 1;
+ else
+ goto error;
+ }
+ if (do_func_ptr) {
+ return do_func_ptr(stdout, argv[0]);
}
- fprintf(stderr, "usage: %s [-c | -e] > output-file\n", argv[0]);
+error:
+ fprintf(stderr, "usage: %s [-x] [-c | -e] > output-file\n"
+ "\t-c\tC header file\n"
+ "\t-e\tErlang header file\n"
+ "\t-x\tCross compile. No dependencies to compiling emulator\n",
+ argv[0]);
return 1;
}
diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c
index e5b8cf8a19..6a3ce5608f 100644
--- a/erts/emulator/hipe/hipe_mode_switch.c
+++ b/erts/emulator/hipe/hipe_mode_switch.c
@@ -35,6 +35,17 @@
#include "hipe_stack.h"
#include "hipe_bif0.h" /* hipe_mfa_info_table_init() */
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_require_lock((P), ERTS_PROC_LOCK_MAIN)
+# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P) \
+ if ((P)) erts_proc_lc_unrequire_lock((P), ERTS_PROC_LOCK_MAIN)
+#else
+# define ERTS_SMP_REQ_PROC_MAIN_LOCK(P)
+# define ERTS_SMP_UNREQ_PROC_MAIN_LOCK(P)
+#endif
+
+
/*
* Internal debug support.
* #define HIPE_DEBUG to the desired debug level:
@@ -318,33 +329,30 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
* Native code called a BIF, which "failed" with a TRAP to BEAM.
* Prior to returning, the BIF stored (see BIF_TRAP<N>):
- * the callee's address in p->def_arg_reg[3]
- * the callee's parameters in p->def_arg_reg[0..2]
+ * the callee's address in p->i
+ * the callee's parameters in reg[0..2]
* the callee's arity in p->arity (for BEAM gc purposes)
*
* We need to remove the BIF's parameters from the native
* stack: to this end hipe_${ARCH}_glue.S stores the BIF's
* arity in p->hipe.narity.
*
- * If the BIF emptied the stack (typically hibernate), p->hipe.nsp is
- * NULL and there is no need to get rid of stacked parameters.
+ * If the BIF emptied the stack (typically hibernate), p->hipe.nstack
+ * is NULL and there is no need to get rid of stacked parameters.
*/
unsigned int i, is_recursive = 0;
- /* Save p->arity, then update it with the original BIF's arity.
- Get rid of any stacked parameters in that call. */
- /* XXX: hipe_call_from_native_is_recursive() copies data to
- reg[], which is useless in the TRAP case. Maybe write a
- specialised hipe_trap_from_native_is_recursive() later. */
- if (p->hipe.nsp != NULL) {
- unsigned int callee_arity;
- callee_arity = p->arity;
- p->arity = p->hipe.narity; /* caller's arity */
- is_recursive = hipe_call_from_native_is_recursive(p, reg);
-
- p->i = (Eterm *)(p->def_arg_reg[3]);
- p->arity = callee_arity;
+ if (p->hipe.nstack != NULL) {
+ ASSERT(p->hipe.nsp != NULL);
+ is_recursive = hipe_trap_from_native_is_recursive(p);
}
+ else {
+ /* Some architectures (risc) need this re-reset of nsp as the
+ * BIF wrapper do not detect stack change and causes an obsolete
+ * stack pointer to be saved in p->hipe.nsp before return to us.
+ */
+ p->hipe.nsp = NULL;
+ }
/* Schedule next process if current process was hibernated or is waiting
for messages */
@@ -353,15 +361,14 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
goto do_schedule;
}
if (p->status == P_WAITING) {
+ for (i = 0; i < p->arity; ++i)
+ p->arg_reg[i] = reg[i];
goto do_schedule;
}
- for (i = 0; i < p->arity; ++i)
- reg[i] = p->def_arg_reg[i];
-
if (is_recursive)
hipe_push_beam_trap_frame(p, reg, p->arity);
-
+
result = HIPE_MODE_SWITCH_RES_CALL;
break;
}
@@ -470,7 +477,9 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[])
#if !(NR_ARG_REGS > 5)
int reds_in = p->def_arg_reg[5];
#endif
+ ERTS_SMP_UNREQ_PROC_MAIN_LOCK(p);
p = schedule(p, reds_in - p->fcalls);
+ ERTS_SMP_REQ_PROC_MAIN_LOCK(p);
#ifdef ERTS_SMP
p->hipe_smp.have_receive_locks = 0;
reg = p->scheduler_data->x_reg_array;
diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h
index dbc2386e14..a3e908a3b3 100644
--- a/erts/emulator/hipe/hipe_mode_switch.h
+++ b/erts/emulator/hipe/hipe_mode_switch.h
@@ -49,7 +49,7 @@
#include "error.h"
-int hipe_modeswitch_debug;
+extern int hipe_modeswitch_debug;
void hipe_mode_switch_init(void);
void hipe_set_call_trap(Uint *bfun, void *nfun, int is_closure);
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index dfb4ca794a..3be821f8f7 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -41,9 +41,9 @@
*/
/* for -Wmissing-prototypes :-( */
-extern Eterm hipe_check_process_code_2(Process*, Eterm, Eterm);
-extern Eterm hipe_garbage_collect_1(Process*, Eterm);
-extern Eterm hipe_show_nstack_1(Process*, Eterm);
+extern Eterm hipe_check_process_code_2(BIF_ALIST_2);
+extern Eterm hipe_garbage_collect_1(BIF_ALIST_1);
+extern Eterm hipe_show_nstack_1(BIF_ALIST_1);
/* Used when a BIF can trigger a stack walk. */
static __inline__ void hipe_set_narity(Process *p, unsigned int arity)
@@ -56,7 +56,7 @@ Eterm hipe_check_process_code_2(BIF_ALIST_2)
Eterm ret;
hipe_set_narity(BIF_P, 2);
- ret = check_process_code_2(BIF_P, BIF_ARG_1, BIF_ARG_2);
+ ret = check_process_code_2(BIF_P, BIF__ARGS);
hipe_set_narity(BIF_P, 0);
return ret;
}
@@ -66,7 +66,7 @@ Eterm hipe_garbage_collect_1(BIF_ALIST_1)
Eterm ret;
hipe_set_narity(BIF_P, 1);
- ret = garbage_collect_1(BIF_P, BIF_ARG_1);
+ ret = garbage_collect_1(BIF_P, BIF__ARGS);
hipe_set_narity(BIF_P, 0);
return ret;
}
@@ -76,7 +76,7 @@ Eterm hipe_show_nstack_1(BIF_ALIST_1)
Eterm ret;
hipe_set_narity(BIF_P, 1);
- ret = hipe_bifs_show_nstack_1(BIF_P, BIF_ARG_1);
+ ret = hipe_bifs_show_nstack_1(BIF_P, BIF__ARGS);
hipe_set_narity(BIF_P, 0);
return ret;
}
@@ -99,8 +99,10 @@ void hipe_gc(Process *p, Eterm need)
* has begun.
* XXX: BUG: native code should check return status
*/
-Eterm hipe_set_timeout(Process *p, Eterm timeout_value)
+BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1)
{
+ Process* p = BIF_P;
+ Eterm timeout_value = BIF_ARG_1;
#if !defined(ARCH_64)
Uint time_val;
#endif
@@ -187,6 +189,8 @@ void hipe_fclearerror_error(Process *p)
{
#if !defined(NO_FPE_SIGNALS)
erts_fp_check_init_error(&p->fp_exception);
+#else
+ erl_exit(ERTS_ABORT_EXIT, "Emulated FPE not cleared by HiPE");
#endif
}
@@ -286,8 +290,13 @@ static struct StackTrace *get_trace_from_exc(Eterm exc)
* This does what the (misnamed) Beam instruction 'raise_ss' does,
* namely, a proper re-throw of an exception that was caught by 'try'.
*/
-Eterm hipe_rethrow(Process *c_p, Eterm exc, Eterm value)
+
+BIF_RETTYPE hipe_rethrow(BIF_ALIST_2)
{
+ Process* c_p = BIF_P;
+ Eterm exc = BIF_ARG_1;
+ Eterm value = BIF_ARG_2;
+
c_p->fvalue = value;
if (c_p->freason == EXC_NULL) {
/* a safety check for the R10-0 case; should not happen */
@@ -411,8 +420,12 @@ Eterm hipe_bs_utf8_size(Eterm arg)
return make_small(4);
}
-Eterm hipe_bs_put_utf8(Process *p, Eterm arg, byte *base, unsigned int offset)
+BIF_RETTYPE hipe_bs_put_utf8(BIF_ALIST_3)
{
+ Process* p = BIF_P;
+ Eterm arg = BIF_ARG_1;
+ byte* base = (byte*) BIF_ARG_2;
+ Uint offset = (Uint) BIF_ARG_3;
byte *save_bin_buf;
Uint save_bin_offset;
int res;
@@ -468,13 +481,21 @@ Eterm hipe_bs_put_utf16(Process *p, Eterm arg, byte *base, unsigned int offset,
return new_offset;
}
-Eterm hipe_bs_put_utf16be(Process *p, Eterm arg, byte *base, unsigned int offset)
+BIF_RETTYPE hipe_bs_put_utf16be(BIF_ALIST_3)
{
+ Process *p = BIF_P;
+ Eterm arg = BIF_ARG_1;
+ byte *base = (byte*) BIF_ARG_2;
+ Uint offset = (Uint) BIF_ARG_3;
return hipe_bs_put_utf16(p, arg, base, offset, 0);
}
-Eterm hipe_bs_put_utf16le(Process *p, Eterm arg, byte *base, unsigned int offset)
+BIF_RETTYPE hipe_bs_put_utf16le(BIF_ALIST_3)
{
+ Process *p = BIF_P;
+ Eterm arg = BIF_ARG_1;
+ byte *base = (byte*) BIF_ARG_2;
+ Uint offset = (Uint) BIF_ARG_3;
return hipe_bs_put_utf16(p, arg, base, offset, BSF_LITTLE);
}
@@ -489,8 +510,10 @@ static int validate_unicode(Eterm arg)
return 1;
}
-Eterm hipe_bs_validate_unicode(Process *p, Eterm arg)
+BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1)
{
+ Process *p = BIF_P;
+ Eterm arg = BIF_ARG_1;
if (!validate_unicode(arg))
BIF_ERROR(p, BADARG);
return NIL;
diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h
index 13a02b84a2..9e3a156fbc 100644
--- a/erts/emulator/hipe/hipe_native_bif.h
+++ b/erts/emulator/hipe/hipe_native_bif.h
@@ -23,6 +23,7 @@
#ifndef HIPE_NATIVE_BIF_H
#define HIPE_NATIVE_BIF_H
+#include "bif.h"
#include "hipe_arch.h"
/*
@@ -71,27 +72,32 @@ AEXTERN(void,nbif_select_msg,(Process*));
AEXTERN(Eterm,nbif_cmp_2,(void));
AEXTERN(Eterm,nbif_eq_2,(void));
-Eterm hipe_nonclosure_address(Process*, Eterm, Uint);
-Eterm hipe_conv_big_to_float(Process*, Eterm);
+BIF_RETTYPE hipe_nonclosure_address(BIF_ALIST_2);
+BIF_RETTYPE hipe_conv_big_to_float(BIF_ALIST_1);
void hipe_fclearerror_error(Process*);
void hipe_select_msg(Process*);
void hipe_gc(Process*, Eterm);
-Eterm hipe_set_timeout(Process*, Eterm);
+BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1);
void hipe_handle_exception(Process*);
-Eterm hipe_rethrow(Process *c_p, Eterm exc, Eterm value);
+BIF_RETTYPE hipe_rethrow(BIF_ALIST_2);
char *hipe_bs_allocate(int);
Binary *hipe_bs_reallocate(Binary*, int);
int hipe_bs_put_small_float(Process*, Eterm, Uint, byte*, unsigned, unsigned);
void hipe_bs_put_bits(Eterm, Uint, byte*, unsigned, unsigned);
Eterm hipe_bs_utf8_size(Eterm);
-Eterm hipe_bs_put_utf8(Process*, Eterm, byte*, unsigned int);
+BIF_RETTYPE hipe_bs_put_utf8(BIF_ALIST_3);
Eterm hipe_bs_utf16_size(Eterm);
-Eterm hipe_bs_put_utf16be(Process*, Eterm, byte*, unsigned int);
-Eterm hipe_bs_put_utf16le(Process*, Eterm, byte*, unsigned int);
-Eterm hipe_bs_validate_unicode(Process*, Eterm);
+BIF_RETTYPE hipe_bs_put_utf16be(BIF_ALIST_3);
+BIF_RETTYPE hipe_bs_put_utf16le(BIF_ALIST_3);
+BIF_RETTYPE hipe_bs_validate_unicode(BIF_ALIST_1);
struct erl_bin_match_buffer;
int hipe_bs_validate_unicode_retract(struct erl_bin_match_buffer*, Eterm);
+#ifdef NO_FPE_SIGNALS
+AEXTERN(void,nbif_emulate_fpe,(Process*));
+void hipe_emulate_fpe(Process*);
+#endif
+
/*
* Stuff that is different in SMP and non-SMP.
*/
diff --git a/erts/emulator/hipe/hipe_ppc.c b/erts/emulator/hipe/hipe_ppc.c
index bc25061a16..2d8fd61e1e 100644
--- a/erts/emulator/hipe/hipe_ppc.c
+++ b/erts/emulator/hipe/hipe_ppc.c
@@ -80,7 +80,7 @@ static struct segment {
} curseg;
#define in_area(ptr,start,nbytes) \
- ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
/* Darwin breakage */
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
diff --git a/erts/emulator/hipe/hipe_ppc_asm.m4 b/erts/emulator/hipe/hipe_ppc_asm.m4
index 0eb5c441e6..343402f9f0 100644
--- a/erts/emulator/hipe/hipe_ppc_asm.m4
+++ b/erts/emulator/hipe/hipe_ppc_asm.m4
@@ -31,12 +31,23 @@ define(LOAD,ld)dnl
define(STORE,std)dnl
define(CMPI,cmpdi)dnl
define(WSIZE,8)dnl
+`#define STORE_IA(ADDR, DST, TMP) \
+ addis TMP, 0, ADDR@highest SEMI\
+ ori TMP, TMP, ADDR@higher SEMI\
+ rldicr TMP, TMP, 32, 31 SEMI\
+ oris TMP, TMP, ADDR@h SEMI\
+ ori TMP, TMP, ADDR@l SEMI\
+ std TMP, DST'
',`
/* 32-bit PowerPC */
define(LOAD,lwz)dnl
define(STORE,stw)dnl
define(CMPI,cmpwi)dnl
define(WSIZE,4)dnl
+`#define STORE_IA(ADDR, DST, TMP) \
+ lis TMP, ADDR@ha SEMI\
+ addi TMP, TMP, ADDR@l SEMI\
+ stw TMP, DST'
')dnl
`#define LOAD 'LOAD
`#define STORE 'STORE
diff --git a/erts/emulator/hipe/hipe_ppc_bifs.m4 b/erts/emulator/hipe/hipe_ppc_bifs.m4
index 203fefe1a1..7caf0c9a2d 100644
--- a/erts/emulator/hipe/hipe_ppc_bifs.m4
+++ b/erts/emulator/hipe/hipe_ppc_bifs.m4
@@ -20,21 +20,34 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_ppc_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) STORE_IA(CSYM(F), P_BIF_CALLEE(P), r29); bl CSYM(hipe_debug_bif_wrapper)
+#else
+# define CALL_BIF(F) bl CSYM(F)
+#endif'
+
.text
.p2align 2
-`#define TEST_GOT_MBUF LOAD r4, P_MBUF(P) SEMI CMPI r4, 0 SEMI bne- 3f SEMI 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: bl CSYM(JOIN3(nbif_,ARITY,_gc_after_bif)) SEMI b 2b'
+define(TEST_GOT_MBUF,`LOAD r4, P_MBUF(P) /* `TEST_GOT_MBUF' */
+ CMPI r4, 0
+ bne- 3f
+2:')
+define(HANDLE_GOT_MBUF,`
+3: bl CSYM(nbif_$1_gc_after_bif) /* `HANDLE_GOT_MBUF' */
+ b 2b')
+
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -49,7 +62,9 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) /* Store BIF__ARGS in def_arg_reg[] */
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -77,7 +92,10 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) /* Store BIF__ARGS in def_arg_reg[] */
+ STORE r5, P_ARG1(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -106,7 +124,11 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) /* Store BIF__ARGS in def_arg_reg[] */
+ STORE r5, P_ARG1(r3)
+ STORE r6, P_ARG2(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -121,13 +143,7 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -138,7 +154,8 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- bl CSYM($2)
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -173,7 +190,8 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl CSYM($2)
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. */
@@ -196,7 +214,9 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) /* Store BIF__ARGS in def_arg_reg[] */
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
@@ -224,7 +244,10 @@ ASYM($1):
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- bl CSYM($2)
+ STORE r4, P_ARG0(r3) /* Store BIF__ARGS in def_arg_reg[] */
+ STORE r5, P_ARG1(r3)
+ addi r4, r3, P_ARG0
+ CALL_BIF($2)
TEST_GOT_MBUF
/* Restore registers. Check for exception. */
diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h
index 94113ffcd8..38509c105b 100644
--- a/erts/emulator/hipe/hipe_primops.h
+++ b/erts/emulator/hipe/hipe_primops.h
@@ -77,6 +77,10 @@ PRIMOP_LIST(am_nonclosure_address, &nbif_nonclosure_address)
PRIMOP_LIST(am_conv_big_to_float, &nbif_conv_big_to_float)
PRIMOP_LIST(am_fclearerror_error, &nbif_fclearerror_error)
+#ifdef NO_FPE_SIGNALS
+PRIMOP_LIST(am_emulate_fpe, &nbif_emulate_fpe)
+#endif
+
#if defined(__sparc__)
#include "hipe_sparc_primops.h"
#endif
diff --git a/erts/emulator/hipe/hipe_process.h b/erts/emulator/hipe/hipe_process.h
index 5effacb398..4ee99d78a2 100644
--- a/erts/emulator/hipe/hipe_process.h
+++ b/erts/emulator/hipe/hipe_process.h
@@ -42,6 +42,12 @@ struct hipe_process_state {
void (*nra)(void); /* Native code return address. */
#endif
unsigned int narity; /* Arity of BIF call, for stack walks. */
+#ifdef NO_FPE_SIGNALS
+ double float_result; /* to be checked for inf/NaN by hipe_emulate_fpe */
+#endif
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+ void (*bif_callee)(void); /* When calling BIF's via debug wrapper */
+#endif
};
extern void hipe_arch_print_pcb(struct hipe_process_state *p);
diff --git a/erts/emulator/hipe/hipe_risc_glue.h b/erts/emulator/hipe/hipe_risc_glue.h
index e74023e3e9..cc2671c016 100644
--- a/erts/emulator/hipe/hipe_risc_glue.h
+++ b/erts/emulator/hipe/hipe_risc_glue.h
@@ -199,6 +199,22 @@ hipe_call_from_native_is_recursive(Process *p, Eterm reg[])
return 0;
}
+/* BEAM called native, which called BIF that returned trap
+ * Discard bif parameters.
+ * If tailcall, also clean up native stub continuation. */
+static __inline__ int
+hipe_trap_from_native_is_recursive(Process *p)
+{
+ if (p->hipe.narity > NR_ARG_REGS) {
+ p->hipe.nsp += (p->hipe.narity - NR_ARG_REGS);
+ }
+ if (p->hipe.nra != (void(*)(void))&nbif_return)
+ return 1;
+ hipe_pop_risc_nra_frame(p);
+ return 0;
+}
+
+
/* Native makes a call which needs to unload the parameters.
This differs from hipe_call_from_native_is_recursive() in
that it doesn't check for or pop the BEAM-calls-native frame.
diff --git a/erts/emulator/hipe/hipe_sparc_bifs.m4 b/erts/emulator/hipe/hipe_sparc_bifs.m4
index 03db7f3413..ca5af45d58 100644
--- a/erts/emulator/hipe/hipe_sparc_bifs.m4
+++ b/erts/emulator/hipe/hipe_sparc_bifs.m4
@@ -20,27 +20,42 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_sparc_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
.section ".text"
.align 4
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) set F, %o7; st %o7, [%o0+P_BIF_CALLEE]; call hipe_debug_bif_wrapper
+#else
+# define CALL_BIF(F) call F
+#endif'
+
/*
* Test for exception. This macro executes its delay slot.
*/
-`#define __TEST_GOT_EXN(LABEL) cmp %o0, THE_NON_VALUE; bz,pn %icc, LABEL
-#define TEST_GOT_EXN(ARITY) __TEST_GOT_EXN(JOIN3(nbif_,ARITY,_simple_exception))'
+define(TEST_GOT_EXN,`cmp %o0, THE_NON_VALUE ! `TEST_GOT_EXN'
+ bz,pn %icc, nbif_$1_simple_exception')
-`#define TEST_GOT_MBUF ld [P+P_MBUF], %o1; cmp %o1, 0; bne 3f; nop; 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: call JOIN3(nbif_,ARITY,_gc_after_bif); nop; b 2b; nop'
+define(TEST_GOT_MBUF,`ld [P+P_MBUF], %o1 ! `TEST_GOT_MBUF'
+ cmp %o1, 0
+ bne 3f
+ nop
+2:')
+define(HANDLE_GOT_MBUF,`
+3: call nbif_$1_gc_after_bif ! `HANDLE_GOT_MBUF'
+ nop
+ b 2b
+ nop')
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -55,7 +70,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -81,7 +98,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -108,7 +128,11 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ st %o3, [%o0+P_ARG2]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -121,13 +145,7 @@ $1:
.type $1, #function
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -138,7 +156,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_BIF
- call $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -171,7 +190,8 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- call $2
+ /* ignore empty BIF__ARGS */
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -195,7 +215,9 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
@@ -221,7 +243,10 @@ $1:
/* Save caller-save registers and call the C function. */
SAVE_CONTEXT_GC
- call $2
+ st %o1, [%o0+P_ARG0] ! Store BIF__ARGS in def_arg_reg
+ st %o2, [%o0+P_ARG1]
+ add %o0, P_ARG0, %o1
+ CALL_BIF($2)
nop
TEST_GOT_MBUF
diff --git a/erts/emulator/hipe/hipe_stack.h b/erts/emulator/hipe/hipe_stack.h
index 4c14b4a519..4e3076caf5 100644
--- a/erts/emulator/hipe/hipe_stack.h
+++ b/erts/emulator/hipe/hipe_stack.h
@@ -116,13 +116,4 @@ extern int hipe_fill_stacktrace(Process*, int, Eterm**);
extern Eterm *fullsweep_nstack(Process *p, Eterm *n_htop);
extern void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop);
-#ifdef HYBRID
-#ifdef INCREMENTAL
-extern Eterm *ma_fullsweep_nstack(Process *p, Eterm *n_htop, Eterm *n_hend);
-#else
-extern Eterm *ma_fullsweep_nstack(Process *p, Eterm *n_htop);
-#endif
-extern void ma_gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop);
-#endif /* HYBRID */
-
#endif /* HIPE_STACK_H */
diff --git a/erts/emulator/hipe/hipe_x86.h b/erts/emulator/hipe/hipe_x86.h
index f0f3c158af..97f09e38cd 100644
--- a/erts/emulator/hipe/hipe_x86.h
+++ b/erts/emulator/hipe/hipe_x86.h
@@ -49,7 +49,9 @@ static __inline__ int hipe_word32_address_ok(void *address)
#define hipe_arch_name am_x86
extern void nbif_inc_stack_0(void);
+#ifndef NO_FPE_SIGNALS
extern void nbif_handle_fp_exception(void);
+#endif
/* for hipe_bifs_enter_code_2 */
extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
diff --git a/erts/emulator/hipe/hipe_x86_bifs.m4 b/erts/emulator/hipe/hipe_x86_bifs.m4
index 1bb6488b00..3cb7d67be0 100644
--- a/erts/emulator/hipe/hipe_x86_bifs.m4
+++ b/erts/emulator/hipe/hipe_x86_bifs.m4
@@ -20,6 +20,7 @@ changecom(`/*', `*/')dnl
include(`hipe/hipe_x86_asm.m4')
+#`include' "config.h"
#`include' "hipe_literals.h"
`#if THE_NON_VALUE == 0
@@ -28,16 +29,27 @@ include(`hipe/hipe_x86_asm.m4')
#define TEST_GOT_EXN cmpl $THE_NON_VALUE,%eax
#endif'
-`#define TEST_GOT_MBUF movl P_MBUF(P), %edx; testl %edx, %edx; jnz 3f; 2:
-#define JOIN3(A,B,C) A##B##C
-#define HANDLE_GOT_MBUF(ARITY) 3: call JOIN3(nbif_,ARITY,_gc_after_bif); jmp 2b'
+`#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+# define CALL_BIF(F) movl $CSYM(F), P_BIF_CALLEE(P); call CSYM(hipe_debug_bif_wrapper)
+#else
+# define CALL_BIF(F) call CSYM(F)
+#endif'
+
+define(TEST_GOT_MBUF,`movl P_MBUF(P), %edx # `TEST_GOT_MBUF'
+ testl %edx, %edx
+ jnz 3f
+2:')
+define(HANDLE_GOT_MBUF,`
+3: call nbif_$1_gc_after_bif # `HANDLE_GOT_MBUF'
+ jmp 2b')
/*
* standard_bif_interface_1(nbif_name, cbif_name)
* standard_bif_interface_2(nbif_name, cbif_name)
* standard_bif_interface_3(nbif_name, cbif_name)
+ * standard_bif_interface_0(nbif_name, cbif_name)
*
- * Generate native interface for a BIF with 1-3 parameters and
+ * Generate native interface for a BIF with 0-3 parameters and
* standard failure mode.
*/
define(standard_bif_interface_1,
@@ -56,8 +68,10 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- NBIF_ARG(1,1,0)
- call CSYM($2)
+ NBIF_ARG(2,1,0)
+ lea 8(%esp), %eax
+ NBIF_ARG_REG(1,%eax) # BIF__ARGS
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -88,9 +102,11 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- NBIF_ARG(1,2,0)
- NBIF_ARG(2,2,1)
- call CSYM($2)
+ NBIF_ARG(2,2,0)
+ NBIF_ARG(3,2,1)
+ lea 8(%esp), %eax
+ NBIF_ARG_REG(1,%eax) # BIF__ARGS
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -121,10 +137,12 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- NBIF_ARG(1,3,0)
- NBIF_ARG(2,3,1)
- NBIF_ARG(3,3,2)
- call CSYM($2)
+ NBIF_ARG(2,3,0)
+ NBIF_ARG(3,3,1)
+ NBIF_ARG(4,3,2)
+ lea 8(%esp), %eax
+ NBIF_ARG_REG(1,%eax) # BIF__ARGS
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -139,13 +157,7 @@ ASYM($1):
TYPE_FUNCTION(ASYM($1))
#endif')
-/*
- * fail_bif_interface_0(nbif_name, cbif_name)
- *
- * Generate native interface for a BIF with 0 parameters and
- * standard failure mode.
- */
-define(fail_bif_interface_0,
+define(standard_bif_interface_0,
`
#ifndef HAVE_$1
#`define' HAVE_$1
@@ -158,7 +170,8 @@ ASYM($1):
/* make the call on the C stack */
NBIF_ARG_REG(0,P)
- call CSYM($2)
+ /* skip BIF__ARGS */
+ CALL_BIF($2)
TEST_GOT_MBUF
/* switch to native stack */
@@ -608,7 +621,9 @@ ASYM($1):
/*
* x86-specific primops.
*/
+#ifndef NO_FPE_SIGNALS
noproc_primop_interface_0(nbif_handle_fp_exception, erts_restore_fpu)
+#endif /* NO_FPE_SIGNALS */
/*
* Implement gc_bif_interface_0 as nofail_primop_interface_0.
diff --git a/erts/emulator/hipe/hipe_x86_glue.h b/erts/emulator/hipe/hipe_x86_glue.h
index a7b0f164be..b0db93267c 100644
--- a/erts/emulator/hipe/hipe_x86_glue.h
+++ b/erts/emulator/hipe/hipe_x86_glue.h
@@ -186,6 +186,25 @@ hipe_call_from_native_is_recursive(Process *p, Eterm reg[])
return 0;
}
+/* BEAM called native, which called BIF that returned trap
+ * Discard bif parameters.
+ * If tailcall, also clean up native stub continuation. */
+static __inline__ int
+hipe_trap_from_native_is_recursive(Process *p)
+{
+ Eterm nra = *(p->hipe.nsp++);
+
+ if (p->hipe.narity > NR_ARG_REGS) {
+ p->hipe.nsp += (p->hipe.narity - NR_ARG_REGS);
+ }
+ if (nra != (Eterm)nbif_return) {
+ *--(p->hipe.nsp) = nra;
+ return 1;
+ }
+ return 0;
+}
+
+
/* Native makes a call which needs to unload the parameters.
This differs from hipe_call_from_native_is_recursive() in
that it doesn't check for or pop the BEAM-calls-native frame.
diff --git a/erts/emulator/hipe/hipe_x86_primops.h b/erts/emulator/hipe/hipe_x86_primops.h
index 96d2336bc5..111b1fa8bd 100644
--- a/erts/emulator/hipe/hipe_x86_primops.h
+++ b/erts/emulator/hipe/hipe_x86_primops.h
@@ -19,4 +19,7 @@
PRIMOP_LIST(am_inc_stack_0, &nbif_inc_stack_0)
+#ifndef NO_FPE_SIGNALS
PRIMOP_LIST(am_handle_fp_exception, &nbif_handle_fp_exception)
+#endif
+
diff --git a/erts/emulator/pcre/pcre.mk b/erts/emulator/pcre/pcre.mk
index b752c11459..352137b341 100644
--- a/erts/emulator/pcre/pcre.mk
+++ b/erts/emulator/pcre/pcre.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2011. All Rights Reserved.
+# Copyright Ericsson AB 2012. All Rights Reserved.
#
# The 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,8 +17,6 @@
# %CopyrightEnd%
#
-ARFLAGS = rc
-
PCRE_O = \
pcre_latin_1_table.o \
pcre_compile.o \
@@ -43,7 +41,7 @@ pcre_xclass.o
PCRE_OBJS = $(PCRE_O:%=$(PCRE_OBJDIR)/%)
-GENINC = pcre/pcre_exec_loop_break_cases.inc
+PCRE_GENINC = $(ERL_TOP)/erts/emulator/pcre/pcre_exec_loop_break_cases.inc
PCRE_OBJDIR = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)
@@ -61,12 +59,12 @@ endif
$(PCRE_OBJDIR)/%.o: pcre/%.c
$(CC) -c $(PCRE_CFLAGS) -o $@ $<
-$(GENINC): pcre/pcre_exec.c
+$(PCRE_GENINC): pcre/pcre_exec.c
for x in `grep -n COST_CHK pcre/pcre_exec.c | grep -v 'COST_CHK(N)' | awk -F: '{print $$1}'`; \
do \
N=`expr $$x + 100`; \
echo "case $$N: goto L_LOOP_COUNT_$${x};"; \
- done > $(GENINC)
+ done > $(PCRE_GENINC)
# Dependencies.
@@ -79,7 +77,7 @@ $(PCRE_OBJDIR)/pcre_config.o: pcre/pcre_config.c pcre/pcre_internal.h \
$(PCRE_OBJDIR)/pcre_dfa_exec.o: pcre/pcre_dfa_exec.c pcre/pcre_internal.h \
pcre/local_config.h pcre/pcre.h pcre/ucp.h
$(PCRE_OBJDIR)/pcre_exec.o: pcre/pcre_exec.c pcre/pcre_internal.h \
- pcre/local_config.h pcre/pcre.h pcre/ucp.h $(GENINC)
+ pcre/local_config.h pcre/pcre.h pcre/ucp.h $(PCRE_GENINC)
$(PCRE_OBJDIR)/pcre_fullinfo.o: pcre/pcre_fullinfo.c pcre/pcre_internal.h \
pcre/local_config.h pcre/pcre.h pcre/ucp.h
$(PCRE_OBJDIR)/pcre_get.o: pcre/pcre_get.c pcre/pcre_internal.h \
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 57321259f9..c1336c60d9 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -35,6 +35,8 @@
#include "sys.h"
#include "global.h"
#include "erl_check_io.h"
+#include "erl_thr_progress.h"
+#include "dtrace-wrapper.h"
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
# define ERTS_DRV_EV_STATE_EXTRA_SIZE 128
@@ -66,6 +68,9 @@ typedef char EventStateFlags;
#define ERTS_CIO_POLL_CTL ERTS_POLL_EXPORT(erts_poll_control)
#define ERTS_CIO_POLL_WAIT ERTS_POLL_EXPORT(erts_poll_wait)
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#define ERTS_CIO_POLL_AS_INTR ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)
+#endif
#define ERTS_CIO_POLL_INTR ERTS_POLL_EXPORT(erts_poll_interrupt)
#define ERTS_CIO_POLL_INTR_TMD ERTS_POLL_EXPORT(erts_poll_interrupt_timed)
#define ERTS_CIO_NEW_POLLSET ERTS_POLL_EXPORT(erts_poll_create_pollset)
@@ -310,7 +315,8 @@ forget_removed(struct pollset_info* psi)
erts_smp_mtx_unlock(mtx);
if (drv_ptr) {
int was_unmasked = erts_block_fpe();
- (*drv_ptr->stop_select) (fd, NULL);
+ DTRACE1(driver_stop_select, drv_ptr->name);
+ (*drv_ptr->stop_select) ((ErlDrvEvent) fd, NULL);
erts_unblock_fpe(was_unmasked);
if (drv_ptr->handle) {
erts_ddll_dereference_driver(drv_ptr->handle);
@@ -492,6 +498,9 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
ErtsDrvEventState *state;
int wake_poller;
int ret;
+#ifdef USE_VM_PROBES
+ DTRACE_CHARBUF(name, 64);
+#endif
ERTS_SMP_LC_ASSERT(erts_drvport2port(ix)
&& erts_lc_is_port_locked(erts_drvport2port(ix)));
@@ -521,6 +530,10 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
if (IS_FD_UNKNOWN(state)) {
/* fast track to stop_select callback */
stop_select_fn = erts_drvport2port(ix)->drv_ptr->stop_select;
+#ifdef USE_VM_PROBES
+ strncpy(name, erts_drvport2port(ix)->drv_ptr->name, sizeof(name)-1);
+ name[sizeof(name)-1] = '\0';
+#endif
ret = 0;
goto done_unknown;
}
@@ -657,6 +670,10 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
/* Safe to close fd now as it is not in pollset
or there was no need to eject fd (kernel poll) */
stop_select_fn = drv_ptr->stop_select;
+#ifdef USE_VM_PROBES
+ strncpy(name, erts_drvport2port(ix)->drv_ptr->name, sizeof(name)-1);
+ name[sizeof(name)-1] = '\0';
+#endif
}
else {
/* Not safe to close fd, postpone stop_select callback. */
@@ -682,6 +699,7 @@ done_unknown:
erts_smp_mtx_unlock(fd_mtx(fd));
if (stop_select_fn) {
int was_unmasked = erts_block_fpe();
+ DTRACE1(driver_stop_select, name);
(*stop_select_fn)(e, NULL);
erts_unblock_fpe(was_unmasked);
}
@@ -1115,6 +1133,14 @@ eready(Eterm id, ErtsDrvEventState *state, ErlDrvEventData event_data)
static void bad_fd_in_pollset( ErtsDrvEventState *, Eterm, Eterm, ErtsPollEvents);
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void
+ERTS_CIO_EXPORT(erts_check_io_async_sig_interrupt)(void)
+{
+ ERTS_CIO_POLL_AS_INTR(pollset.ps);
+}
+#endif
+
void
ERTS_CIO_EXPORT(erts_check_io_interrupt)(int set)
{
@@ -1122,7 +1148,8 @@ ERTS_CIO_EXPORT(erts_check_io_interrupt)(int set)
}
void
-ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set, long msec)
+ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set,
+ erts_short_time_t msec)
{
ERTS_CIO_POLL_INTR_TMD(pollset.ps, set, msec);
}
@@ -1153,7 +1180,6 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
#endif
- erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
pollres_len = sizeof(pollres)/sizeof(ErtsPollResFd);
erts_smp_atomic_set_nob(&pollset.in_poll_wait, 1);
@@ -1163,7 +1189,6 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
#endif
- erts_smp_activity_end(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
erts_deliver_time(); /* sync the machine's idea of time */
@@ -1870,13 +1895,12 @@ ERTS_CIO_EXPORT(erts_check_io_debug)(void)
erts_printf("--- fds in pollset --------------------------------------\n");
-#ifdef ERTS_SMP
-# ifdef ERTS_ENABLE_LOCK_CHECK
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
-# endif
- erts_block_system(0); /* stop the world to avoid messy locking */
#endif
+ erts_smp_thr_progress_block(); /* stop the world to avoid messy locking */
+
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
counters.epep = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsPollEvents)*max_fds);
ERTS_POLL_EXPORT(erts_poll_get_selected_events)(pollset.ps, counters.epep, max_fds);
@@ -1898,9 +1922,7 @@ ERTS_CIO_EXPORT(erts_check_io_debug)(void)
safe_hash_for_each(&drv_ev_state_tab, &doit_erts_check_io_debug, (void *) &counters);
#endif
-#ifdef ERTS_SMP
- erts_release_system();
-#endif
+ erts_smp_thr_progress_unblock();
erts_printf("\n");
erts_printf("used fds=%d\n", counters.used_fds);
diff --git a/erts/emulator/sys/common/erl_check_io.h b/erts/emulator/sys/common/erl_check_io.h
index 9b45a63913..edab7947ba 100644
--- a/erts/emulator/sys/common/erl_check_io.h
+++ b/erts/emulator/sys/common/erl_check_io.h
@@ -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
@@ -40,10 +40,14 @@ Eterm erts_check_io_info_kp(void *);
Eterm erts_check_io_info_nkp(void *);
int erts_check_io_max_files_kp(void);
int erts_check_io_max_files_nkp(void);
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void erts_check_io_async_sig_interrupt_kp(void);
+void erts_check_io_async_sig_interrupt_nkp(void);
+#endif
void erts_check_io_interrupt_kp(int);
void erts_check_io_interrupt_nkp(int);
-void erts_check_io_interrupt_timed_kp(int, long);
-void erts_check_io_interrupt_timed_nkp(int, long);
+void erts_check_io_interrupt_timed_kp(int, erts_short_time_t);
+void erts_check_io_interrupt_timed_nkp(int, erts_short_time_t);
void erts_check_io_kp(int);
void erts_check_io_nkp(int);
void erts_init_check_io_kp(void);
@@ -56,8 +60,11 @@ int erts_check_io_debug_nkp(void);
Uint erts_check_io_size(void);
Eterm erts_check_io_info(void *);
int erts_check_io_max_files(void);
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void erts_check_io_async_sig_interrupt(void);
+#endif
void erts_check_io_interrupt(int);
-void erts_check_io_interrupt_timed(int, long);
+void erts_check_io_interrupt_timed(int, erts_short_time_t);
void erts_check_io(int);
void erts_init_check_io(void);
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index eaef6680dd..db2854fa40 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -36,14 +36,12 @@
#include "erl_threads.h"
#include "erl_mtrace.h"
#include "erl_time.h"
+#include "erl_alloc.h"
#include "big.h"
+#include "erl_thr_progress.h"
#if HAVE_ERTS_MSEG
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-# define ERTS_THREADS_NO_SMP
-#endif
-
#define SEGTYPE ERTS_MTRACE_SEGMENT_ID
#ifndef HAVE_GETPAGESIZE
@@ -75,16 +73,9 @@
static int atoms_initialized;
-static Uint cache_check_interval;
-
typedef struct mem_kind_t MemKind;
-static void check_cache(void *unused);
static void mseg_clear_cache(MemKind*);
-static int is_cache_check_scheduled;
-#ifdef ERTS_THREADS_NO_SMP
-static int is_cache_check_requested;
-#endif
#if HALFWORD_HEAP
static int initialize_pmmap(void);
@@ -138,7 +129,8 @@ const ErtsMsegOpt_t erts_mseg_default_opt = {
1, /* Use cache */
1, /* Preserv data */
0, /* Absolute shrink threshold */
- 0 /* Relative shrink threshold */
+ 0, /* Relative shrink threshold */
+ 0 /* Scheduler specific */
#if HALFWORD_HEAP
,0 /* need low memory */
#endif
@@ -157,11 +149,10 @@ typedef struct {
Uint32 no;
} CallCounter;
-static int is_init_done;
static Uint page_size;
static Uint page_shift;
-static struct {
+typedef struct {
CallCounter alloc;
CallCounter dealloc;
CallCounter realloc;
@@ -172,7 +163,9 @@ static struct {
#endif
CallCounter clear_cache;
CallCounter check_cache;
-} calls;
+} ErtsMsegCalls;
+
+typedef struct ErtsMsegAllctr_t_ ErtsMsegAllctr_t;
struct mem_kind_t {
cache_desc_t cache_descs[MAX_CACHE_SIZE];
@@ -201,25 +194,84 @@ struct mem_kind_t {
} max_ever;
} segments;
+ ErtsMsegAllctr_t *ma;
const char* name;
MemKind* next;
};/*MemKind*/
+struct ErtsMsegAllctr_t_ {
+ int ix;
+
+ int is_init_done;
+ int is_thread_safe;
+ erts_mtx_t mtx;
+
+ int is_cache_check_scheduled;
+
+ MemKind* mk_list;
+
#if HALFWORD_HEAP
-static MemKind low_mem, hi_mem;
+ MemKind low_mem;
+ MemKind hi_mem;
#else
-static MemKind the_mem;
+ MemKind the_mem;
#endif
-static MemKind* mk_list = NULL;
-static Uint max_cache_size;
-static Uint abs_max_cache_bad_fit;
-static Uint rel_max_cache_bad_fit;
+ Uint max_cache_size;
+ Uint abs_max_cache_bad_fit;
+ Uint rel_max_cache_bad_fit;
+
+ ErtsMsegCalls calls;
#if CAN_PARTLY_DESTROY
-static Uint min_seg_size;
+ Uint min_seg_size;
+#endif
+
+};
+
+typedef union {
+ ErtsMsegAllctr_t mseg_alloc;
+ char align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(ErtsMsegAllctr_t))];
+} ErtsAlgndMsegAllctr_t;
+
+static int no_mseg_allocators;
+static ErtsAlgndMsegAllctr_t *aligned_mseg_allctr;
+
+#ifdef ERTS_SMP
+
+#define ERTS_MSEG_ALLCTR_IX(IX) \
+ (&aligned_mseg_allctr[(IX)].mseg_alloc)
+
+#define ERTS_MSEG_ALLCTR_SS() \
+ ERTS_MSEG_ALLCTR_IX((int) erts_get_scheduler_id())
+
+#define ERTS_MSEG_ALLCTR_OPT(OPT) \
+ ((OPT)->sched_spec ? ERTS_MSEG_ALLCTR_SS() : ERTS_MSEG_ALLCTR_IX(0))
+
+#else
+
+#define ERTS_MSEG_ALLCTR_IX(IX) \
+ (&aligned_mseg_allctr[0].mseg_alloc)
+
+#define ERTS_MSEG_ALLCTR_SS() \
+ (&aligned_mseg_allctr[0].mseg_alloc)
+
+#define ERTS_MSEG_ALLCTR_OPT(OPT) \
+ (&aligned_mseg_allctr[0].mseg_alloc)
+
#endif
+#define ERTS_MSEG_LOCK(MA) \
+do { \
+ if ((MA)->is_thread_safe) \
+ erts_mtx_lock(&(MA)->mtx); \
+} while (0)
+
+#define ERTS_MSEG_UNLOCK(MA) \
+do { \
+ if ((MA)->is_thread_safe) \
+ erts_mtx_unlock(&(MA)->mtx); \
+} while (0)
#define ERTS_MSEG_ALLOC_STAT(C,SZ) \
do { \
@@ -250,104 +302,44 @@ do { \
#define ONE_GIGA (1000000000)
-#define ZERO_CC(CC) (calls.CC.no = 0, calls.CC.giga_no = 0)
+#define ZERO_CC(MA, CC) ((MA)->calls.CC.no = 0, \
+ (MA)->calls.CC.giga_no = 0)
-#define INC_CC(CC) (calls.CC.no == ONE_GIGA - 1 \
- ? (calls.CC.giga_no++, calls.CC.no = 0) \
- : calls.CC.no++)
+#define INC_CC(MA, CC) ((MA)->calls.CC.no == ONE_GIGA - 1 \
+ ? ((MA)->calls.CC.giga_no++, \
+ (MA)->calls.CC.no = 0) \
+ : (MA)->calls.CC.no++)
-#define DEC_CC(CC) (calls.CC.no == 0 \
- ? (calls.CC.giga_no--, \
- calls.CC.no = ONE_GIGA - 1) \
- : calls.CC.no--)
+#define DEC_CC(MA, CC) ((MA)->calls.CC.no == 0 \
+ ? ((MA)->calls.CC.giga_no--, \
+ (MA)->calls.CC.no = ONE_GIGA - 1) \
+ : (MA)->calls.CC.no--)
-static erts_mtx_t mseg_mutex; /* Also needed when !USE_THREADS */
static erts_mtx_t init_atoms_mutex; /* Also needed when !USE_THREADS */
-#ifdef USE_THREADS
-#ifdef ERTS_THREADS_NO_SMP
-static erts_tid_t main_tid;
-static int async_handle = -1;
-#endif
-
-static void thread_safe_init(void)
-{
- erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
- erts_mtx_init(&mseg_mutex, "mseg");
-
-#ifdef ERTS_THREADS_NO_SMP
- main_tid = erts_thr_self();
-#endif
-}
-
-#endif
-
-static ErlTimer cache_check_timer;
static ERTS_INLINE void
-schedule_cache_check(void)
-{
- if (!is_cache_check_scheduled && is_init_done) {
-#ifdef ERTS_THREADS_NO_SMP
- if (!erts_equal_tids(erts_thr_self(), main_tid)) {
- if (!is_cache_check_requested) {
- is_cache_check_requested = 1;
- sys_async_ready(async_handle);
- }
- }
- else
-#endif
- {
- cache_check_timer.active = 0;
- erts_set_timer(&cache_check_timer,
- check_cache,
- NULL,
- NULL,
- cache_check_interval);
- is_cache_check_scheduled = 1;
-#ifdef ERTS_THREADS_NO_SMP
- is_cache_check_requested = 0;
-#endif
- }
- }
-}
-
-#ifdef ERTS_THREADS_NO_SMP
-
-static void
-check_schedule_cache_check(void)
+schedule_cache_check(ErtsMsegAllctr_t *ma)
{
- erts_mtx_lock(&mseg_mutex);
- if (is_cache_check_requested
- && !is_cache_check_scheduled) {
- schedule_cache_check();
- }
- erts_mtx_unlock(&mseg_mutex);
-}
-
-#endif
-static void
-mseg_shutdown(void)
-{
- MemKind* mk;
- erts_mtx_lock(&mseg_mutex);
- for (mk=mk_list; mk; mk=mk->next) {
- mseg_clear_cache(mk);
+ if (!ma->is_cache_check_scheduled && ma->is_init_done) {
+ erts_set_aux_work_timeout(ma->ix,
+ ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK,
+ 1);
+ ma->is_cache_check_scheduled = 1;
}
- erts_mtx_unlock(&mseg_mutex);
}
static ERTS_INLINE void *
-mseg_create(MemKind* mk, Uint size)
+mseg_create(ErtsMsegAllctr_t *ma, MemKind* mk, Uint size)
{
void *seg;
ASSERT(size % page_size == 0);
#if HALFWORD_HEAP
- if (mk == &low_mem) {
+ if (mk == &ma->low_mem) {
seg = pmmap(size);
if ((unsigned long) seg & CHECK_POINTER_MASK) {
erts_fprintf(stderr,"Pointer mask failure (0x%08lx)\n",(unsigned long) seg);
@@ -371,28 +363,38 @@ mseg_create(MemKind* mk, Uint size)
#endif
}
- INC_CC(create);
+ INC_CC(ma, create);
return seg;
}
static ERTS_INLINE void
-mseg_destroy(MemKind* mk, void *seg, Uint size)
+mseg_destroy(ErtsMsegAllctr_t *ma, MemKind* mk, void *seg, Uint size)
{
+#ifdef DEBUG
int res;
+#endif
#if HALFWORD_HEAP
- if (mk == &low_mem) {
- res = pmunmap((void *) seg, size);
+ if (mk == &ma->low_mem) {
+#ifdef DEBUG
+ res =
+#endif
+ pmunmap((void *) seg, size);
}
else
#endif
{
#ifdef ERTS_MSEG_FAKE_SEGMENTS
erts_sys_free(ERTS_ALC_N_INVALID, NULL, seg);
+#ifdef DEBUG
res = 0;
+#endif
#elif HAVE_MMAP
- res = munmap((void *) seg, size);
+#ifdef DEBUG
+ res =
+#endif
+ munmap((void *) seg, size);
#else
# error "Missing mseg_destroy() implementation"
#endif
@@ -401,14 +403,14 @@ mseg_destroy(MemKind* mk, void *seg, Uint size)
ASSERT(size % page_size == 0);
ASSERT(res == 0);
- INC_CC(destroy);
+ INC_CC(ma, destroy);
}
#if HAVE_MSEG_RECREATE
static ERTS_INLINE void *
-mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
+mseg_recreate(ErtsMsegAllctr_t *ma, MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
{
void *new_seg;
@@ -416,7 +418,7 @@ mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
ASSERT(new_size % page_size == 0);
#if HALFWORD_HEAP
- if (mk == &low_mem) {
+ if (mk == &ma->low_mem) {
new_seg = (void *) pmremap((void *) old_seg,
(size_t) old_size,
(size_t) new_size);
@@ -447,19 +449,37 @@ mseg_recreate(MemKind* mk, void *old_seg, Uint old_size, Uint new_size)
#endif
}
- INC_CC(recreate);
+ INC_CC(ma, recreate);
return new_seg;
}
#endif /* #if HAVE_MSEG_RECREATE */
+#ifdef DEBUG
+#define ERTS_DBG_MA_CHK_THR_ACCESS(MA) \
+do { \
+ if ((MA)->is_thread_safe) \
+ ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&(MA)->mtx) \
+ || erts_smp_thr_progress_is_blocking() \
+ || ERTS_IS_CRASH_DUMPING); \
+ else \
+ ERTS_LC_ASSERT((MA)->ix == (int) erts_get_scheduler_id() \
+ || erts_smp_thr_progress_is_blocking() \
+ || ERTS_IS_CRASH_DUMPING); \
+} while (0)
+#define ERTS_DBG_MK_CHK_THR_ACCESS(MK) \
+ ERTS_DBG_MA_CHK_THR_ACCESS((MK)->ma)
+#else
+#define ERTS_DBG_MA_CHK_THR_ACCESS(MA)
+#define ERTS_DBG_MK_CHK_THR_ACCESS(MK)
+#endif
static ERTS_INLINE cache_desc_t *
alloc_cd(MemKind* mk)
{
cache_desc_t *cd = mk->free_cache_descs;
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (cd)
mk->free_cache_descs = cd->next;
return cd;
@@ -468,7 +488,7 @@ alloc_cd(MemKind* mk)
static ERTS_INLINE void
free_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
cd->next = mk->free_cache_descs;
mk->free_cache_descs = cd;
}
@@ -477,7 +497,7 @@ free_cd(MemKind* mk, cache_desc_t *cd)
static ERTS_INLINE void
link_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (mk->cache)
mk->cache->prev = cd;
cd->next = mk->cache;
@@ -496,7 +516,7 @@ link_cd(MemKind* mk, cache_desc_t *cd)
static ERTS_INLINE void
end_link_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (mk->cache_end)
mk->cache_end->next = cd;
cd->next = NULL;
@@ -515,7 +535,7 @@ end_link_cd(MemKind* mk, cache_desc_t *cd)
static ERTS_INLINE void
unlink_cd(MemKind* mk, cache_desc_t *cd)
{
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
if (cd->next)
cd->next->prev = cd->prev;
else
@@ -533,7 +553,7 @@ static ERTS_INLINE void
check_cache_limits(MemKind* mk)
{
cache_desc_t *cd;
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
mk->max_cached_seg_size = 0;
mk->min_cached_seg_size = ~((Uint) 0);
for (cd = mk->cache; cd; cd = cd->next) {
@@ -551,7 +571,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
int check_limits = force_check_limits;
Sint max_cached = ((Sint) mk->segments.current.watermark
- (Sint) mk->segments.current.no);
- ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&mseg_mutex));
+ ERTS_DBG_MK_CHK_THR_ACCESS(mk);
while (((Sint) mk->cache_size) > max_cached && ((Sint) mk->cache_size) > 0) {
ASSERT(mk->cache_end);
cd = mk->cache_end;
@@ -562,7 +582,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
}
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, cd->seg);
- mseg_destroy(mk, cd->seg, cd->size);
+ mseg_destroy(mk->ma, mk, cd->seg, cd->size);
unlink_cd(mk,cd);
free_cd(mk,cd);
}
@@ -571,7 +591,7 @@ adjust_cache_size(MemKind* mk, int force_check_limits)
check_cache_limits(mk);
}
-static void
+static Uint
check_one_cache(MemKind* mk)
{
if (mk->segments.current.watermark > mk->segments.current.no)
@@ -579,23 +599,37 @@ check_one_cache(MemKind* mk)
adjust_cache_size(mk, 0);
if (mk->cache_size)
- schedule_cache_check();
+ schedule_cache_check(mk->ma);
+ return mk->cache_size;
}
-static void check_cache(void* unused)
+static void do_cache_check(ErtsMsegAllctr_t *ma)
{
+ int empty_cache = 1;
MemKind* mk;
- erts_mtx_lock(&mseg_mutex);
- is_cache_check_scheduled = 0;
+ ERTS_MSEG_LOCK(ma);
- for (mk=mk_list; mk; mk=mk->next) {
- check_one_cache(mk);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
+ if (check_one_cache(mk))
+ empty_cache = 0;
}
- INC_CC(check_cache);
+ if (empty_cache) {
+ ma->is_cache_check_scheduled = 0;
+ erts_set_aux_work_timeout(ma->ix,
+ ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK,
+ 0);
+ }
+
+ INC_CC(ma, check_cache);
+
+ ERTS_MSEG_UNLOCK(ma);
+}
- erts_mtx_unlock(&mseg_mutex);
+void erts_mseg_cache_check(void)
+{
+ do_cache_check(ERTS_MSEG_ALLCTR_SS());
}
static void
@@ -611,42 +645,44 @@ mseg_clear_cache(MemKind* mk)
mk->segments.current.watermark = mk->segments.current.no;
- INC_CC(clear_cache);
+ INC_CC(mk->ma, clear_cache);
}
-static ERTS_INLINE MemKind* memkind(const ErtsMsegOpt_t *opt)
+static ERTS_INLINE MemKind* memkind(ErtsMsegAllctr_t *ma,
+ const ErtsMsegOpt_t *opt)
{
#if HALFWORD_HEAP
- return opt->low_mem ? &low_mem : &hi_mem;
+ return opt->low_mem ? &ma->low_mem : &ma->hi_mem;
#else
- return &the_mem;
+ return &ma->the_mem;
#endif
}
static void *
-mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
+mseg_alloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, Uint *size_p,
+ const ErtsMsegOpt_t *opt)
{
Uint max, min, diff_size, size;
cache_desc_t *cd, *cand_cd;
void *seg;
- MemKind* mk = memkind(opt);
+ MemKind* mk = memkind(ma, opt);
- INC_CC(alloc);
+ INC_CC(ma, alloc);
size = PAGE_CEILING(*size_p);
#if CAN_PARTLY_DESTROY
- if (size < min_seg_size)
- min_seg_size = size;
+ if (size < ma->min_seg_size)
+ ma->min_seg_size = size;
#endif
if (!opt->cache) {
create_seg:
adjust_cache_size(mk,0);
- seg = mseg_create(mk, size);
+ seg = mseg_create(ma, mk, size);
if (!seg) {
mseg_clear_cache(mk);
- seg = mseg_create(mk, size);
+ seg = mseg_create(ma, mk, size);
if (!seg)
size = 0;
}
@@ -667,10 +703,10 @@ mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
diff_size = mk->min_cached_seg_size - size;
- if (diff_size > abs_max_cache_bad_fit)
+ if (diff_size > ma->abs_max_cache_bad_fit)
goto create_seg;
- if (100*PAGES(diff_size) > rel_max_cache_bad_fit*PAGES(size))
+ if (100*PAGES(diff_size) > ma->rel_max_cache_bad_fit*PAGES(size))
goto create_seg;
}
@@ -708,8 +744,8 @@ mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
diff_size = cand_cd->size - size;
- if (diff_size > abs_max_cache_bad_fit
- || 100*PAGES(diff_size) > rel_max_cache_bad_fit*PAGES(size)) {
+ if (diff_size > ma->abs_max_cache_bad_fit
+ || 100*PAGES(diff_size) > ma->rel_max_cache_bad_fit*PAGES(size)) {
if (mk->max_cached_seg_size < cand_cd->size)
mk->max_cached_seg_size = cand_cd->size;
if (mk->min_cached_seg_size > cand_cd->size)
@@ -740,18 +776,18 @@ mseg_alloc(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
static void
-mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
+mseg_dealloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, Uint size,
const ErtsMsegOpt_t *opt)
{
- MemKind* mk = memkind(opt);
+ MemKind* mk = memkind(ma, opt);
cache_desc_t *cd;
ERTS_MSEG_DEALLOC_STAT(mk,size);
- if (!opt->cache || max_cache_size == 0) {
+ if (!opt->cache || ma->max_cache_size == 0) {
if (erts_mtrace_enabled)
erts_mtrace_crr_free(atype, SEGTYPE, seg);
- mseg_destroy(mk, seg, size);
+ mseg_destroy(ma, mk, seg, size);
}
else {
int check_limits = 0;
@@ -769,7 +805,7 @@ mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
}
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, cd->seg);
- mseg_destroy(mk, cd->seg, cd->size);
+ mseg_destroy(ma, mk, cd->seg, cd->size);
unlink_cd(mk,cd);
free_cd(mk,cd);
}
@@ -790,33 +826,34 @@ mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size,
if (check_limits)
check_cache_limits(mk);
- schedule_cache_check();
+ schedule_cache_check(ma);
}
- INC_CC(dealloc);
+ INC_CC(ma, dealloc);
}
static void *
-mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
- const ErtsMsegOpt_t *opt)
+mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
+ Uint old_size, Uint *new_size_p, const ErtsMsegOpt_t *opt)
{
- MemKind* mk = memkind(opt);
+ MemKind* mk;
void *new_seg;
Uint new_size;
if (!seg || !old_size) {
- new_seg = mseg_alloc(atype, new_size_p, opt);
- DEC_CC(alloc);
+ new_seg = mseg_alloc(ma, atype, new_size_p, opt);
+ DEC_CC(ma, alloc);
return new_seg;
}
if (!(*new_size_p)) {
- mseg_dealloc(atype, seg, old_size, opt);
- DEC_CC(dealloc);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
+ DEC_CC(ma, dealloc);
return NULL;
}
+ mk = memkind(ma, opt);
new_seg = seg;
new_size = PAGE_CEILING(*new_size_p);
@@ -826,8 +863,8 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
Uint shrink_sz = old_size - new_size;
#if CAN_PARTLY_DESTROY
- if (new_size < min_seg_size)
- min_seg_size = new_size;
+ if (new_size < ma->min_seg_size)
+ ma->min_seg_size = new_size;
#endif
if (shrink_sz < opt->abs_shrink_th
@@ -838,7 +875,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
#if CAN_PARTLY_DESTROY
- if (shrink_sz > min_seg_size
+ if (shrink_sz > ma->min_seg_size
&& mk->free_cache_descs
&& opt->cache) {
cache_desc_t *cd;
@@ -857,7 +894,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
new_size);
erts_mtrace_crr_alloc(cd->seg, SEGTYPE, SEGTYPE, cd->size);
}
- schedule_cache_check();
+ schedule_cache_check(ma);
}
else {
if (erts_mtrace_enabled)
@@ -866,7 +903,7 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
SEGTYPE,
seg,
new_size);
- mseg_destroy(mk, ((char *) seg) + new_size, shrink_sz);
+ mseg_destroy(ma, mk, ((char *) seg) + new_size, shrink_sz);
}
#elif HAVE_MSEG_RECREATE
@@ -875,14 +912,14 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
#else
- new_seg = mseg_alloc(atype, &new_size, opt);
+ new_seg = mseg_alloc(ma, atype, &new_size, opt);
if (!new_seg)
new_size = old_size;
else {
sys_memcpy(((char *) new_seg),
((char *) seg),
MIN(new_size, old_size));
- mseg_dealloc(atype, seg, old_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
}
#endif
@@ -892,34 +929,34 @@ mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size, Uint *new_size_p,
else {
if (!opt->preserv) {
- mseg_dealloc(atype, seg, old_size, opt);
- new_seg = mseg_alloc(atype, &new_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
+ new_seg = mseg_alloc(ma, atype, &new_size, opt);
}
else {
#if HAVE_MSEG_RECREATE
#if !CAN_PARTLY_DESTROY
do_recreate:
#endif
- new_seg = mseg_recreate(mk, (void *) seg, old_size, new_size);
+ new_seg = mseg_recreate(ma, mk, (void *) seg, old_size, new_size);
if (erts_mtrace_enabled)
erts_mtrace_crr_realloc(new_seg, atype, SEGTYPE, seg, new_size);
if (!new_seg)
new_size = old_size;
#else
- new_seg = mseg_alloc(atype, &new_size, opt);
+ new_seg = mseg_alloc(ma, atype, &new_size, opt);
if (!new_seg)
new_size = old_size;
else {
sys_memcpy(((char *) new_seg),
((char *) seg),
MIN(new_size, old_size));
- mseg_dealloc(atype, seg, old_size, opt);
+ mseg_dealloc(ma, atype, seg, old_size, opt);
}
#endif
}
}
- INC_CC(realloc);
+ INC_CC(ma, realloc);
*new_size_p = new_size;
@@ -937,7 +974,6 @@ static struct {
Eterm amcbf;
Eterm rmcbf;
Eterm mcs;
- Eterm cci;
Eterm memkind;
Eterm name;
@@ -973,13 +1009,13 @@ static void ERTS_INLINE atom_init(Eterm *atom, char *name)
#define AM_INIT(AM) atom_init(&am.AM, #AM)
static void
-init_atoms(void)
+init_atoms(ErtsMsegAllctr_t *ma)
{
#ifdef DEBUG
Eterm *atom;
#endif
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
erts_mtx_lock(&init_atoms_mutex);
if (!atoms_initialized) {
@@ -997,7 +1033,6 @@ init_atoms(void)
AM_INIT(amcbf);
AM_INIT(rmcbf);
AM_INIT(mcs);
- AM_INIT(cci);
AM_INIT(status);
AM_INIT(cached_segments);
@@ -1025,7 +1060,7 @@ init_atoms(void)
#endif
}
- erts_mtx_lock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
atoms_initialized = 1;
erts_mtx_unlock(&init_atoms_mutex);
}
@@ -1082,7 +1117,8 @@ add_4tup(Uint **hpp, Uint *szp, Eterm *lp,
}
static Eterm
-info_options(char *prefix,
+info_options(ErtsMsegAllctr_t *ma,
+ char *prefix,
int *print_to_p,
void *print_to_arg,
Uint **hpp,
@@ -1093,30 +1129,26 @@ info_options(char *prefix,
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
- erts_print(to, arg, "%samcbf: %beu\n", prefix, abs_max_cache_bad_fit);
- erts_print(to, arg, "%srmcbf: %beu\n", prefix, rel_max_cache_bad_fit);
- erts_print(to, arg, "%smcs: %beu\n", prefix, max_cache_size);
- erts_print(to, arg, "%scci: %beu\n", prefix, cache_check_interval);
+ erts_print(to, arg, "%samcbf: %beu\n", prefix, ma->abs_max_cache_bad_fit);
+ erts_print(to, arg, "%srmcbf: %beu\n", prefix, ma->rel_max_cache_bad_fit);
+ erts_print(to, arg, "%smcs: %beu\n", prefix, ma->max_cache_size);
}
if (hpp || szp) {
if (!atoms_initialized)
- init_atoms();
+ init_atoms(ma);
res = NIL;
add_2tup(hpp, szp, &res,
- am.cci,
- bld_uint(hpp, szp, cache_check_interval));
- add_2tup(hpp, szp, &res,
am.mcs,
- bld_uint(hpp, szp, max_cache_size));
+ bld_uint(hpp, szp, ma->max_cache_size));
add_2tup(hpp, szp, &res,
am.rmcbf,
- bld_uint(hpp, szp, rel_max_cache_bad_fit));
+ bld_uint(hpp, szp, ma->rel_max_cache_bad_fit));
add_2tup(hpp, szp, &res,
am.amcbf,
- bld_uint(hpp, szp, abs_max_cache_bad_fit));
+ bld_uint(hpp, szp, ma->abs_max_cache_bad_fit));
}
@@ -1124,18 +1156,18 @@ info_options(char *prefix,
}
static Eterm
-info_calls(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
+info_calls(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
if (print_to_p) {
-#define PRINT_CC(TO, TOA, CC) \
- if (calls.CC.giga_no == 0) \
- erts_print(TO, TOA, "mseg_%s calls: %b32u\n", #CC, calls.CC.no); \
- else \
+#define PRINT_CC(TO, TOA, CC) \
+ if (ma->calls.CC.giga_no == 0) \
+ erts_print(TO, TOA, "mseg_%s calls: %b32u\n", #CC, ma->calls.CC.no); \
+ else \
erts_print(TO, TOA, "mseg_%s calls: %b32u%09b32u\n", #CC, \
- calls.CC.giga_no, calls.CC.no)
+ ma->calls.CC.giga_no, ma->calls.CC.no)
int to = *print_to_p;
void *arg = print_to_arg;
@@ -1161,48 +1193,48 @@ info_calls(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
add_3tup(hpp, szp, &res,
am.mseg_check_cache,
- bld_unstable_uint(hpp, szp, calls.check_cache.giga_no),
- bld_unstable_uint(hpp, szp, calls.check_cache.no));
+ bld_unstable_uint(hpp, szp, ma->calls.check_cache.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.check_cache.no));
add_3tup(hpp, szp, &res,
am.mseg_clear_cache,
- bld_unstable_uint(hpp, szp, calls.clear_cache.giga_no),
- bld_unstable_uint(hpp, szp, calls.clear_cache.no));
+ bld_unstable_uint(hpp, szp, ma->calls.clear_cache.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.clear_cache.no));
#if HAVE_MSEG_RECREATE
add_3tup(hpp, szp, &res,
am.mseg_recreate,
- bld_unstable_uint(hpp, szp, calls.recreate.giga_no),
- bld_unstable_uint(hpp, szp, calls.recreate.no));
+ bld_unstable_uint(hpp, szp, ma->calls.recreate.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.recreate.no));
#endif
add_3tup(hpp, szp, &res,
am.mseg_destroy,
- bld_unstable_uint(hpp, szp, calls.destroy.giga_no),
- bld_unstable_uint(hpp, szp, calls.destroy.no));
+ bld_unstable_uint(hpp, szp, ma->calls.destroy.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.destroy.no));
add_3tup(hpp, szp, &res,
am.mseg_create,
- bld_unstable_uint(hpp, szp, calls.create.giga_no),
- bld_unstable_uint(hpp, szp, calls.create.no));
+ bld_unstable_uint(hpp, szp, ma->calls.create.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.create.no));
add_3tup(hpp, szp, &res,
am.mseg_realloc,
- bld_unstable_uint(hpp, szp, calls.realloc.giga_no),
- bld_unstable_uint(hpp, szp, calls.realloc.no));
+ bld_unstable_uint(hpp, szp, ma->calls.realloc.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.realloc.no));
add_3tup(hpp, szp, &res,
am.mseg_dealloc,
- bld_unstable_uint(hpp, szp, calls.dealloc.giga_no),
- bld_unstable_uint(hpp, szp, calls.dealloc.no));
+ bld_unstable_uint(hpp, szp, ma->calls.dealloc.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.dealloc.no));
add_3tup(hpp, szp, &res,
am.mseg_alloc,
- bld_unstable_uint(hpp, szp, calls.alloc.giga_no),
- bld_unstable_uint(hpp, szp, calls.alloc.no));
+ bld_unstable_uint(hpp, szp, ma->calls.alloc.giga_no),
+ bld_unstable_uint(hpp, szp, ma->calls.alloc.no));
}
return res;
}
static Eterm
-info_status(MemKind* mk, int *print_to_p, void *print_to_arg,
+info_status(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, void *print_to_arg,
int begin_new_max_period, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1258,7 +1290,7 @@ info_status(MemKind* mk, int *print_to_p, void *print_to_arg,
return res;
}
-static Eterm info_memkind(MemKind* mk, int *print_to_p, void *print_to_arg,
+static Eterm info_memkind(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, void *print_to_arg,
int begin_max_per, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1274,8 +1306,8 @@ static Eterm info_memkind(MemKind* mk, int *print_to_p, void *print_to_arg,
atoms[2] = am.calls;
values[0] = erts_bld_string(hpp, szp, mk->name);
}
- values[1] = info_status(mk, print_to_p, print_to_arg, begin_max_per, hpp, szp);
- values[2] = info_calls(print_to_p, print_to_arg, hpp, szp);
+ values[1] = info_status(ma, mk, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[2] = info_calls(ma, print_to_p, print_to_arg, hpp, szp);
if (hpp || szp)
res = bld_2tup_list(hpp, szp, 3, atoms, values);
@@ -1285,7 +1317,7 @@ static Eterm info_memkind(MemKind* mk, int *print_to_p, void *print_to_arg,
static Eterm
-info_version(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
+info_version(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1306,56 +1338,64 @@ info_version(int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
\* */
Eterm
-erts_mseg_info_options(int *print_to_p, void *print_to_arg,
+erts_mseg_info_options(int ix,
+ int *print_to_p, void *print_to_arg,
Uint **hpp, Uint *szp)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(ix);
Eterm res;
- erts_mtx_lock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
- res = info_options("option ", print_to_p, print_to_arg, hpp, szp);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
- erts_mtx_unlock(&mseg_mutex);
+ res = info_options(ma, "option ", print_to_p, print_to_arg, hpp, szp);
+
+ ERTS_MSEG_UNLOCK(ma);
return res;
}
Eterm
-erts_mseg_info(int *print_to_p,
+erts_mseg_info(int ix,
+ int *print_to_p,
void *print_to_arg,
int begin_max_per,
Uint **hpp,
Uint *szp)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(ix);
Eterm res = THE_NON_VALUE;
Eterm atoms[4];
Eterm values[4];
Uint n = 0;
- erts_mtx_lock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
if (hpp || szp) {
if (!atoms_initialized)
- init_atoms();
+ init_atoms(ma);
atoms[0] = am.version;
atoms[1] = am.options;
atoms[2] = am.memkind;
atoms[3] = am.memkind;
}
- values[n++] = info_version(print_to_p, print_to_arg, hpp, szp);
- values[n++] = info_options("option ", print_to_p, print_to_arg, hpp, szp);
+ values[n++] = info_version(ma, print_to_p, print_to_arg, hpp, szp);
+ values[n++] = info_options(ma, "option ", print_to_p, print_to_arg, hpp, szp);
#if HALFWORD_HEAP
- values[n++] = info_memkind(&low_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
- values[n++] = info_memkind(&hi_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[n++] = info_memkind(ma, &ma->low_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[n++] = info_memkind(ma, &ma->hi_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
#else
- values[n++] = info_memkind(&the_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[n++] = info_memkind(ma, &ma->the_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
#endif
if (hpp || szp)
res = bld_2tup_list(hpp, szp, n, atoms, values);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
return res;
}
@@ -1363,10 +1403,12 @@ erts_mseg_info(int *print_to_p,
void *
erts_mseg_alloc_opt(ErtsAlcType_t atype, Uint *size_p, const ErtsMsegOpt_t *opt)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
void *seg;
- erts_mtx_lock(&mseg_mutex);
- seg = mseg_alloc(atype, size_p, opt);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ seg = mseg_alloc(ma, atype, size_p, opt);
+ ERTS_MSEG_UNLOCK(ma);
return seg;
}
@@ -1377,12 +1419,14 @@ erts_mseg_alloc(ErtsAlcType_t atype, Uint *size_p)
}
void
-erts_mseg_dealloc_opt(ErtsAlcType_t atype, void *seg, Uint size,
- const ErtsMsegOpt_t *opt)
+erts_mseg_dealloc_opt(ErtsAlcType_t atype, void *seg,
+ Uint size, const ErtsMsegOpt_t *opt)
{
- erts_mtx_lock(&mseg_mutex);
- mseg_dealloc(atype, seg, size, opt);
- erts_mtx_unlock(&mseg_mutex);
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ mseg_dealloc(ma, atype, seg, size, opt);
+ ERTS_MSEG_UNLOCK(ma);
}
void
@@ -1392,44 +1436,60 @@ erts_mseg_dealloc(ErtsAlcType_t atype, void *seg, Uint size)
}
void *
-erts_mseg_realloc_opt(ErtsAlcType_t atype, void *seg, Uint old_size,
- Uint *new_size_p, const ErtsMsegOpt_t *opt)
+erts_mseg_realloc_opt(ErtsAlcType_t atype, void *seg,
+ Uint old_size, Uint *new_size_p,
+ const ErtsMsegOpt_t *opt)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
void *new_seg;
- erts_mtx_lock(&mseg_mutex);
- new_seg = mseg_realloc(atype, seg, old_size, new_size_p, opt);
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ new_seg = mseg_realloc(ma, atype, seg, old_size, new_size_p, opt);
+ ERTS_MSEG_UNLOCK(ma);
return new_seg;
}
void *
-erts_mseg_realloc(ErtsAlcType_t atype, void *seg, Uint old_size,
- Uint *new_size_p)
+erts_mseg_realloc(ErtsAlcType_t atype, void *seg,
+ Uint old_size, Uint *new_size_p)
{
- return erts_mseg_realloc_opt(atype, seg, old_size, new_size_p, &erts_mseg_default_opt);
+ return erts_mseg_realloc_opt(atype, seg, old_size, new_size_p,
+ &erts_mseg_default_opt);
}
void
erts_mseg_clear_cache(void)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_SS();
MemKind* mk;
- erts_mtx_lock(&mseg_mutex);
- for (mk=mk_list; mk; mk=mk->next) {
+
+start:
+
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
mseg_clear_cache(mk);
}
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
+
+ if (ma->ix != 0) {
+ ma = ERTS_MSEG_ALLCTR_IX(0);
+ goto start;
+ }
}
Uint
-erts_mseg_no(void)
+erts_mseg_no(const ErtsMsegOpt_t *opt)
{
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
MemKind* mk;
Uint n = 0;
- erts_mtx_lock(&mseg_mutex);
- for (mk=mk_list; mk; mk=mk->next) {
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
n += mk->segments.current.no;
}
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_UNLOCK(ma);
return n;
}
@@ -1439,7 +1499,7 @@ erts_mseg_unit_size(void)
return page_size;
}
-static void mem_kind_init(MemKind* mk, const char* name)
+static void mem_kind_init(ErtsMsegAllctr_t *ma, MemKind* mk, const char* name)
{
unsigned i;
@@ -1450,10 +1510,10 @@ static void mem_kind_init(MemKind* mk, const char* name)
mk->cache_size = 0;
mk->cache_hits = 0;
- if (max_cache_size > 0) {
- for (i = 0; i < max_cache_size - 1; i++)
+ if (ma->max_cache_size > 0) {
+ for (i = 0; i < ma->max_cache_size - 1; i++)
mk->cache_descs[i].next = &mk->cache_descs[i + 1];
- mk->cache_descs[max_cache_size - 1].next = NULL;
+ mk->cache_descs[ma->max_cache_size - 1].next = NULL;
mk->free_cache_descs = &mk->cache_descs[0];
}
else
@@ -1467,30 +1527,38 @@ static void mem_kind_init(MemKind* mk, const char* name)
mk->segments.max_ever.no = 0;
mk->segments.max_ever.sz = 0;
+ mk->ma = ma;
mk->name = name;
- mk->next = mk_list;
- mk_list = mk;
+ mk->next = ma->mk_list;
+ ma->mk_list = mk;
}
+
+
void
erts_mseg_init(ErtsMsegInit_t *init)
{
- atoms_initialized = 0;
- is_init_done = 0;
+ int i;
+ UWord x;
- /* Options ... */
+#ifdef ERTS_SMP
+ no_mseg_allocators = init->nos + 1;
+#else
+ no_mseg_allocators = 1;
+#endif
- abs_max_cache_bad_fit = init->amcbf;
- rel_max_cache_bad_fit = init->rmcbf;
- max_cache_size = init->mcs;
- cache_check_interval = init->cci;
+ x = (UWord) malloc(sizeof(ErtsAlgndMsegAllctr_t)
+ *no_mseg_allocators
+ + (ERTS_CACHE_LINE_SIZE-1));
+ if (x & ERTS_CACHE_LINE_MASK)
+ x = (x & ~ERTS_CACHE_LINE_MASK) + ERTS_CACHE_LINE_SIZE;
+ ASSERT((x & ERTS_CACHE_LINE_MASK) == 0);
+ aligned_mseg_allctr = (ErtsAlgndMsegAllctr_t *) x;
- /* */
+ atoms_initialized = 0;
-#ifdef USE_THREADS
- thread_safe_init();
-#endif
+ erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
#if HAVE_MMAP && !defined(MAP_ANON)
mmap_fd = open("/dev/zero", O_RDWR);
@@ -1512,34 +1580,55 @@ erts_mseg_init(ErtsMsegInit_t *init)
page_shift++;
}
- sys_memzero((void *) &calls, sizeof(calls));
+ for (i = 0; i < no_mseg_allocators; i++) {
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(i);
-#if CAN_PARTLY_DESTROY
- min_seg_size = ~((Uint) 0);
-#endif
+ ma->ix = i;
+
+ ma->is_init_done = 0;
+
+ if (i != 0)
+ ma->is_thread_safe = 0;
+ else {
+ ma->is_thread_safe = 1;
+ erts_mtx_init(&ma->mtx, "mseg");
+ }
+
+ ma->is_cache_check_scheduled = 0;
+
+ /* Options ... */
- if (max_cache_size > MAX_CACHE_SIZE)
- max_cache_size = MAX_CACHE_SIZE;
+ ma->abs_max_cache_bad_fit = init->amcbf;
+ ma->rel_max_cache_bad_fit = init->rmcbf;
+ ma->max_cache_size = init->mcs;
+
+ if (ma->max_cache_size > MAX_CACHE_SIZE)
+ ma->max_cache_size = MAX_CACHE_SIZE;
+
+ ma->mk_list = NULL;
#if HALFWORD_HEAP
- mem_kind_init(&low_mem, "low memory");
- mem_kind_init(&hi_mem, "high memory");
+ mem_kind_init(ma, &ma->low_mem, "low memory");
+ mem_kind_init(ma, &ma->hi_mem, "high memory");
#else
- mem_kind_init(&the_mem, "all memory");
+ mem_kind_init(ma, &ma->the_mem, "all memory");
#endif
- is_cache_check_scheduled = 0;
-#ifdef ERTS_THREADS_NO_SMP
- is_cache_check_requested = 0;
+ sys_memzero((void *) &ma->calls, sizeof(ErtsMsegCalls));
+
+#if CAN_PARTLY_DESTROY
+ ma->min_seg_size = ~((Uint) 0);
#endif
+ }
}
-static ERTS_INLINE Uint tot_cache_size(void)
+static ERTS_INLINE Uint tot_cache_size(ErtsMsegAllctr_t *ma)
{
MemKind* mk;
Uint sz = 0;
- for (mk=mk_list; mk; mk=mk->next) {
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ for (mk=ma->mk_list; mk; mk=mk->next) {
sz += mk->cache_size;
}
return sz;
@@ -1552,25 +1641,13 @@ static ERTS_INLINE Uint tot_cache_size(void)
void
erts_mseg_late_init(void)
{
-#ifdef ERTS_THREADS_NO_SMP
- int handle =
- erts_register_async_ready_callback(
- check_schedule_cache_check);
-#endif
- erts_mtx_lock(&mseg_mutex);
- is_init_done = 1;
-#ifdef ERTS_THREADS_NO_SMP
- async_handle = handle;
-#endif
- if (tot_cache_size())
- schedule_cache_check();
- erts_mtx_unlock(&mseg_mutex);
-}
-
-void
-erts_mseg_exit(void)
-{
- mseg_shutdown();
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_SS();
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
+ ma->is_init_done = 1;
+ if (tot_cache_size(ma))
+ schedule_cache_check(ma);
+ ERTS_MSEG_UNLOCK(ma);
}
#endif /* #if HAVE_ERTS_MSEG */
@@ -1599,12 +1676,13 @@ erts_mseg_test(unsigned long op,
erts_mseg_clear_cache();
return (unsigned long) 0;
case 0x405:
- return (unsigned long) erts_mseg_no();
+ return (unsigned long) erts_mseg_no(&erts_mseg_default_opt);
case 0x406: {
+ ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_IX(0);
unsigned long res;
- erts_mtx_lock(&mseg_mutex);
- res = (unsigned long) tot_cache_size();
- erts_mtx_unlock(&mseg_mutex);
+ ERTS_MSEG_LOCK(ma);
+ res = (unsigned long) tot_cache_size(ma);
+ ERTS_MSEG_UNLOCK(ma);
return res;
}
#else /* #if HAVE_ERTS_MSEG */
diff --git a/erts/emulator/sys/common/erl_mseg.h b/erts/emulator/sys/common/erl_mseg.h
index 8f116030a8..741080fb78 100644
--- a/erts/emulator/sys/common/erl_mseg.h
+++ b/erts/emulator/sys/common/erl_mseg.h
@@ -44,7 +44,7 @@ typedef struct {
Uint amcbf;
Uint rmcbf;
Uint mcs;
- Uint cci;
+ Uint nos;
} ErtsMsegInit_t;
#define ERTS_MSEG_INIT_DEFAULT_INITIALIZER \
@@ -60,6 +60,7 @@ typedef struct {
int preserv;
UWord abs_shrink_th;
UWord rel_shrink_th;
+ int sched_spec;
#if HALFWORD_HEAP
int low_mem;
#endif
@@ -75,14 +76,14 @@ void *erts_mseg_realloc(ErtsAlcType_t, void *, Uint, Uint *);
void *erts_mseg_realloc_opt(ErtsAlcType_t, void *, Uint, Uint *,
const ErtsMsegOpt_t *);
void erts_mseg_clear_cache(void);
-Uint erts_mseg_no(void);
+void erts_mseg_cache_check(void);
+Uint erts_mseg_no( const ErtsMsegOpt_t *);
Uint erts_mseg_unit_size(void);
void erts_mseg_init(ErtsMsegInit_t *init);
void erts_mseg_late_init(void); /* Have to be called after all allocators,
threads and timers have been initialized. */
-void erts_mseg_exit(void);
-Eterm erts_mseg_info_options(int *, void*, Uint **, Uint *);
-Eterm erts_mseg_info(int *, void*, int, Uint **, Uint *);
+Eterm erts_mseg_info_options(int, int *, void*, Uint **, Uint *);
+Eterm erts_mseg_info(int, int *, void*, int, Uint **, Uint *);
#endif /* #if HAVE_ERTS_MSEG */
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index 9bd64f5908..26858052c4 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -68,6 +68,7 @@
# endif
# endif
#endif
+#include "erl_thr_progress.h"
#include "erl_driver.h"
#include "erl_alloc.h"
@@ -114,7 +115,7 @@
#endif
#define ERTS_POLL_USE_WAKEUP_PIPE \
- (ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP))
+ (ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(USE_THREADS))
#ifdef ERTS_SMP
@@ -261,7 +262,6 @@ struct ErtsPollSet_ {
#ifdef ERTS_SMP
erts_atomic32_t polled;
erts_smp_mtx_t mtx;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
#endif
#if ERTS_POLL_USE_WAKEUP_PIPE
int wake_fds[2];
@@ -269,10 +269,8 @@ struct ErtsPollSet_ {
#if ERTS_POLL_USE_FALLBACK
int fallback_used;
#endif
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
erts_atomic32_t wakeup_state;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- volatile int wakeup_state;
#endif
erts_smp_atomic32_t timeout;
#ifdef ERTS_POLL_COUNT_AVOIDED_WAKEUPS
@@ -345,21 +343,16 @@ static void print_misc_debug_info(void);
static ERTS_INLINE void
reset_wakeup_state(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
- erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
- ERTS_THR_MEMORY_BARRIER;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- ps->wakeup_state = 0;
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ erts_atomic32_set_mb(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
#endif
}
static ERTS_INLINE int
is_woken(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
return erts_atomic32_read_acqb(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- return ps->wakeup_state != ERTS_POLL_NOT_WOKEN;
#else
return 0;
#endif
@@ -368,13 +361,9 @@ is_woken(ErtsPollSet ps)
static ERTS_INLINE int
is_interrupted_reset(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
return (erts_atomic32_xchg_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN)
== ERTS_POLL_WOKEN_INTR);
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- int res = ps->wakeup_state == ERTS_POLL_WOKEN_INTR;
- ps->wakeup_state = ERTS_POLL_NOT_WOKEN;
- return res;
#else
return 0;
#endif
@@ -383,16 +372,13 @@ is_interrupted_reset(ErtsPollSet ps)
static ERTS_INLINE void
woke_up(ErtsPollSet ps)
{
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
if (wakeup_state == ERTS_POLL_NOT_WOKEN)
(void) erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
ERTS_POLL_WOKEN,
ERTS_POLL_NOT_WOKEN);
ASSERT(erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN);
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- if (ps->wakeup_state == ERTS_POLL_NOT_WOKEN)
- ps->wakeup_state = ERTS_POLL_WOKEN;
#endif
}
@@ -403,28 +389,27 @@ woke_up(ErtsPollSet ps)
#if ERTS_POLL_USE_WAKEUP_PIPE
static ERTS_INLINE void
-wake_poller(ErtsPollSet ps, int interrupted)
+wake_poller(ErtsPollSet ps, int interrupted, int async_signal_safe)
{
- int wake = 0;
-#ifdef ERTS_SMP
- erts_aint32_t wakeup_state;
- if (!interrupted)
- wakeup_state = erts_atomic32_cmpxchg_relb(&ps->wakeup_state,
- ERTS_POLL_WOKEN,
- ERTS_POLL_NOT_WOKEN);
+ int wake;
+ if (async_signal_safe)
+ wake = 1;
else {
- /*
- * We might unnecessarily write to the pipe, however,
- * that isn't problematic.
- */
- wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
- erts_atomic32_set_relb(&ps->wakeup_state, ERTS_POLL_WOKEN_INTR);
+ erts_aint32_t wakeup_state;
+ if (!interrupted)
+ wakeup_state = erts_atomic32_cmpxchg_relb(&ps->wakeup_state,
+ ERTS_POLL_WOKEN,
+ ERTS_POLL_NOT_WOKEN);
+ else {
+ /*
+ * We might unnecessarily write to the pipe, however,
+ * that isn't problematic.
+ */
+ wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
+ erts_atomic32_set_relb(&ps->wakeup_state, ERTS_POLL_WOKEN_INTR);
+ }
+ wake = wakeup_state == ERTS_POLL_NOT_WOKEN;
}
- wake = wakeup_state == ERTS_POLL_NOT_WOKEN;
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- wake = ps->wakeup_state == ERTS_POLL_NOT_WOKEN;
- ps->wakeup_state = interrupted ? ERTS_POLL_WOKEN_INTR : ERTS_POLL_NOT_WOKEN;
-#endif
/*
* NOTE: This function might be called from signal handlers in the
* non-smp case; therefore, it has to be async-signal safe in
@@ -439,9 +424,17 @@ wake_poller(ErtsPollSet ps, int interrupted)
res = write(ps->wake_fds[1], "!", 1);
} while (res < 0 && errno == EINTR);
if (res <= 0 && errno != ERRNO_BLOCK) {
- fatal_error_async_signal_safe(__FILE__
- ":XXX:wake_poller(): "
- "Failed to write on wakeup pipe\n");
+ if (async_signal_safe)
+ fatal_error_async_signal_safe(__FILE__
+ ":XXX:wake_poller(): "
+ "Failed to write on wakeup pipe\n");
+ else
+ fatal_error("%s:%d:wake_poller(): "
+ "Failed to write to wakeup pipe fd=%d: "
+ "%s (%d)\n",
+ __FILE__, __LINE__,
+ ps->wake_fds[1],
+ erl_errno_id(errno), errno);
}
}
}
@@ -449,11 +442,18 @@ wake_poller(ErtsPollSet ps, int interrupted)
static ERTS_INLINE void
cleanup_wakeup_pipe(ErtsPollSet ps)
{
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ int intr = 0;
+#endif
int fd = ps->wake_fds[0];
int res;
do {
char buf[32];
res = read(fd, buf, sizeof(buf));
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ if (res > 0)
+ intr = 1;
+#endif
} while (res > 0 || (res < 0 && errno == EINTR));
if (res < 0 && errno != ERRNO_BLOCK) {
fatal_error("%s:%d:cleanup_wakeup_pipe(): "
@@ -463,6 +463,10 @@ cleanup_wakeup_pipe(ErtsPollSet ps)
fd,
erl_errno_id(errno), errno);
}
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+ if (intr)
+ erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_WOKEN_INTR);
+#endif
}
static void
@@ -1497,7 +1501,7 @@ ERTS_POLL_EXPORT(erts_poll_controlv)(ErtsPollSet ps,
#ifdef ERTS_SMP
if (final_do_wake)
- wake_poller(ps, 0);
+ wake_poller(ps, 0, 0);
#endif /* ERTS_SMP */
}
@@ -1520,7 +1524,7 @@ ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet ps,
#ifdef ERTS_SMP
if (*do_wake) {
- wake_poller(ps, 0);
+ wake_poller(ps, 0, 0);
}
#endif /* ERTS_SMP */
@@ -1893,9 +1897,9 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res,
}
static ERTS_INLINE int
-check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
+check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res)
{
- ASSERT(!*ps_locked);
+ int res;
if (erts_smp_atomic_read_nob(&ps->no_of_user_fds) == 0
&& tv->tv_usec == 0 && tv->tv_sec == 0) {
/* Nothing to poll and zero timeout; done... */
@@ -1915,16 +1919,23 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
timeout = INT_MAX;
if (max_res > ps->res_events_len)
grow_res_events(ps, max_res);
- return epoll_wait(ps->kp_fd, ps->res_events, max_res, (int)timeout);
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
+ res = epoll_wait(ps->kp_fd, ps->res_events, max_res, (int)timeout);
#elif ERTS_POLL_USE_KQUEUE /* --- kqueue ------------------------------ */
struct timespec ts;
- ts.tv_sec = tv->tv_sec;
- ts.tv_nsec = tv->tv_usec*1000;
if (max_res > ps->res_events_len)
grow_res_events(ps, max_res);
- return kevent(ps->kp_fd, NULL, 0, ps->res_events, max_res, &ts);
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
+ ts.tv_sec = tv->tv_sec;
+ ts.tv_nsec = tv->tv_usec*1000;
+ res = kevent(ps->kp_fd, NULL, 0, ps->res_events, max_res, &ts);
#endif /* ----------------------------------------- */
-
}
else /* use fallback (i.e. poll() or select()) */
#endif /* ERTS_POLL_USE_FALLBACK */
@@ -1938,7 +1949,7 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
*/
struct dvpoll poll_res;
int nfds = (int) erts_smp_atomic_read_nob(&ps->no_of_user_fds);
-#ifdef ERTS_SMP
+#if ERTS_POLL_USE_WAKEUP_PIPE
nfds++; /* Wakeup pipe */
#endif
if (timeout > INT_MAX)
@@ -1947,22 +1958,38 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
if (poll_res.dp_nfds > ps->res_events_len)
grow_res_events(ps, poll_res.dp_nfds);
poll_res.dp_fds = ps->res_events;
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
poll_res.dp_timeout = (int) timeout;
- return ioctl(ps->kp_fd, DP_POLL, &poll_res);
+ res = ioctl(ps->kp_fd, DP_POLL, &poll_res);
#elif ERTS_POLL_USE_POLL /* --- poll -------------------------------- */
if (timeout > INT_MAX)
timeout = INT_MAX;
- return poll(ps->poll_fds, ps->no_poll_fds, (int) timeout);
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
+ res = poll(ps->poll_fds, ps->no_poll_fds, (int) timeout);
#elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */
- int res;
+ SysTimeval to = *tv;
+
ps->res_input_fds = ps->input_fds;
ps->res_output_fds = ps->output_fds;
+
+#ifdef ERTS_SMP
+ if (to.tv_sec || to.tv_usec)
+ erts_thr_progress_prepare_wait(NULL);
+#endif
res = select(ps->max_fd + 1,
&ps->res_input_fds,
&ps->res_output_fds,
NULL,
- tv);
+ &to);
#ifdef ERTS_SMP
+ if (to.tv_sec || to.tv_usec)
+ erts_thr_progress_finalize_wait(NULL);
if (res < 0
&& errno == EBADF
&& ERTS_POLLSET_HAVE_UPDATE_REQUESTS(ps)) {
@@ -1978,15 +2005,16 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
* have triggered, we fake an EAGAIN error and let the caller
* restart us.
*/
- SysTimeval zero_tv = {0, 0};
- *ps_locked = 1;
+ to.tv_sec = 0;
+ to.tv_usec = 0;
ERTS_POLLSET_LOCK(ps);
handle_update_requests(ps);
+ ERTS_POLLSET_UNLOCK(ps);
res = select(ps->max_fd + 1,
&ps->res_input_fds,
&ps->res_output_fds,
NULL,
- &zero_tv);
+ &to);
if (res == 0) {
errno = EAGAIN;
res = -1;
@@ -1996,6 +2024,11 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res, int *ps_locked)
return res;
#endif /* ----------------------------------------- */
}
+#ifdef ERTS_SMP
+ if (timeout)
+ erts_thr_progress_finalize_wait(NULL);
+#endif
+ return res;
}
}
@@ -2007,7 +2040,9 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
{
int res, no_fds;
int ebadf = 0;
- int ps_locked;
+#ifdef ERTS_SMP
+ int ps_locked = 0;
+#endif
SysTimeval *tvp;
SysTimeval itv;
@@ -2049,8 +2084,7 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
}
#endif
- ps_locked = 0;
- res = check_fd_events(ps, tvp, no_fds, &ps_locked);
+ res = check_fd_events(ps, tvp, no_fds);
woke_up(ps);
@@ -2072,10 +2106,8 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
#endif
#ifdef ERTS_SMP
- if (!ps_locked) {
- ps_locked = 1;
- ERTS_POLLSET_LOCK(ps);
- }
+ ps_locked = 1;
+ ERTS_POLLSET_LOCK(ps);
#endif
no_fds = save_poll_result(ps, pr, no_fds, res, ebadf);
@@ -2111,19 +2143,26 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet ps,
void
ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet ps, int set)
{
-#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP)
- /*
- * NOTE: This function might be called from signal handlers in the
- * non-smp case; therefore, it has to be async-signal safe in
- * the non-smp case.
- */
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
if (!set)
reset_wakeup_state(ps);
else
- wake_poller(ps, 1);
+ wake_poller(ps, 1, 0);
#endif
}
+#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
+void
+ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)(ErtsPollSet ps)
+{
+ /*
+ * NOTE: This function is called from signal handlers, it,
+ * therefore, it has to be async-signal safe.
+ */
+ wake_poller(ps, 1, 1);
+}
+#endif
+
/*
* erts_poll_interrupt_timed():
* If 'set' != 0, interrupt thread blocked in erts_poll_wait() if it
@@ -2132,14 +2171,14 @@ ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet ps, int set)
void
ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet ps,
int set,
- long msec)
+ erts_short_time_t msec)
{
#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP)
if (!set)
reset_wakeup_state(ps);
else {
if (erts_smp_atomic32_read_acqb(&ps->timeout) > (erts_aint32_t) msec)
- wake_poller(ps, 1);
+ wake_poller(ps, 1, 0);
#ifdef ERTS_POLL_COUNT_AVOIDED_WAKEUPS
else {
if (ERTS_POLLSET_IS_POLLED(ps))
@@ -2266,10 +2305,8 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void)
erts_atomic32_init_nob(&ps->polled, 0);
erts_smp_mtx_init(&ps->mtx, "pollset");
#endif
-#ifdef ERTS_SMP
+#if defined(USE_THREADS) || ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
erts_atomic32_init_nob(&ps->wakeup_state, (erts_aint32_t) 0);
-#elif ERTS_POLL_ASYNC_INTERRUPT_SUPPORT
- ps->wakeup_state = 0;
#endif
#if ERTS_POLL_USE_WAKEUP_PIPE
create_wakeup_pipe(ps);
@@ -2450,7 +2487,7 @@ ERTS_POLL_EXPORT(erts_poll_info)(ErtsPollSet ps, ErtsPollInfo *pip)
pip->memory_size = size;
pip->poll_set_size = (int) erts_smp_atomic_read_nob(&ps->no_of_user_fds);
-#ifdef ERTS_SMP
+#if ERTS_POLL_USE_WAKEUP_PIPE
pip->poll_set_size++; /* Wakeup pipe */
#endif
diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h
index 725a77a152..8dde619105 100644
--- a/erts/emulator/sys/common/erl_poll.h
+++ b/erts/emulator/sys/common/erl_poll.h
@@ -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
@@ -216,11 +216,14 @@ typedef struct {
#endif
} ErtsPollInfo;
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+void ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)(ErtsPollSet);
+#endif
void ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet,
int);
void ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet,
int,
- long);
+ erts_short_time_t);
ErtsPollEvents ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet,
ErtsSysFdType,
ErtsPollEvents,
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index d8d51b192c..c8fcec8547 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -129,10 +129,12 @@
#define HAVE_ERTS_CHECK_IO_DEBUG
int erts_check_io_debug(void);
-
-#ifndef ENABLE_CHILD_WAITER_THREAD
+#ifndef ERTS_SMP
# undef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
# define ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#endif
+
+#ifndef ENABLE_CHILD_WAITER_THREAD
# ifdef ERTS_SMP
# define ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
void erts_check_children(void);
@@ -144,6 +146,7 @@ typedef void *GETENV_STATE;
/*
** For the erl_timer_sup module.
*/
+typedef time_t erts_time_t;
typedef struct timeval SysTimeval;
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 82d2c64d81..0e8395ea8a 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -52,6 +52,7 @@
#define ERTS_WANT_GOT_SIGUSR1
#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */
#include "sys.h"
+#include "erl_thr_progress.h"
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
#define __DARWIN__ 1
@@ -127,7 +128,6 @@ static ErtsSysReportExit *report_exit_list;
static ErtsSysReportExit *report_exit_transit_list;
#endif
-extern int check_async_ready(void);
extern int driver_interrupt(int, int);
extern void do_break(void);
@@ -263,8 +263,9 @@ int erts_use_kernel_poll = 0;
struct {
int (*select)(ErlDrvPort, ErlDrvEvent, int, int);
int (*event)(ErlDrvPort, ErlDrvEvent, ErlDrvEventData);
+ void (*check_io_as_interrupt)(void);
void (*check_io_interrupt)(int);
- void (*check_io_interrupt_tmd)(int, long);
+ void (*check_io_interrupt_tmd)(int, erts_short_time_t);
void (*check_io)(int);
Uint (*size)(void);
Eterm (*info)(void *);
@@ -302,6 +303,9 @@ init_check_io(void)
if (erts_use_kernel_poll) {
io_func.select = driver_select_kp;
io_func.event = driver_event_kp;
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+ io_func.check_io_as_interrupt = erts_check_io_async_sig_interrupt_kp;
+#endif
io_func.check_io_interrupt = erts_check_io_interrupt_kp;
io_func.check_io_interrupt_tmd = erts_check_io_interrupt_timed_kp;
io_func.check_io = erts_check_io_kp;
@@ -314,6 +318,9 @@ init_check_io(void)
else {
io_func.select = driver_select_nkp;
io_func.event = driver_event_nkp;
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+ io_func.check_io_as_interrupt = erts_check_io_async_sig_interrupt_nkp;
+#endif
io_func.check_io_interrupt = erts_check_io_interrupt_nkp;
io_func.check_io_interrupt_tmd = erts_check_io_interrupt_timed_nkp;
io_func.check_io = erts_check_io_nkp;
@@ -325,6 +332,11 @@ init_check_io(void)
}
}
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#define ERTS_CHK_IO_AS_INTR() (*io_func.check_io_as_interrupt)()
+#else
+#define ERTS_CHK_IO_AS_INTR() (*io_func.check_io_interrupt)(1)
+#endif
#define ERTS_CHK_IO_INTR (*io_func.check_io_interrupt)
#define ERTS_CHK_IO_INTR_TMD (*io_func.check_io_interrupt_tmd)
#define ERTS_CHK_IO (*io_func.check_io)
@@ -339,6 +351,11 @@ init_check_io(void)
max_files = erts_check_io_max_files();
}
+#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
+#define ERTS_CHK_IO_AS_INTR() erts_check_io_async_sig_interrupt()
+#else
+#define ERTS_CHK_IO_AS_INTR() erts_check_io_interrupt(1)
+#endif
#define ERTS_CHK_IO_INTR erts_check_io_interrupt
#define ERTS_CHK_IO_INTR_TMD erts_check_io_interrupt_timed
#define ERTS_CHK_IO erts_check_io
@@ -346,15 +363,15 @@ init_check_io(void)
#endif
-#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt(int set)
{
ERTS_CHK_IO_INTR(set);
}
+#ifdef ERTS_SMP
void
-erts_sys_schedule_interrupt_timed(int set, long msec)
+erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec)
{
ERTS_CHK_IO_INTR_TMD(set, msec);
}
@@ -534,7 +551,7 @@ erl_sys_init(void)
size_t bindirsz = sizeof(bindir);
Uint csp_path_sz;
- res = erts_sys_getenv("BINDIR", bindir, &bindirsz);
+ res = erts_sys_getenv_raw("BINDIR", bindir, &bindirsz);
if (res != 0) {
if (res < 0)
erl_exit(-1,
@@ -691,7 +708,7 @@ prepare_crash_dump(void)
}
envsz = sizeof(env);
- i = erts_sys_getenv("ERL_CRASH_DUMP_NICE", env, &envsz);
+ i = erts_sys_getenv_raw("ERL_CRASH_DUMP_NICE", env, &envsz);
if (i >= 0) {
int nice_val;
nice_val = i != 0 ? 0 : atoi(env);
@@ -702,7 +719,7 @@ prepare_crash_dump(void)
}
envsz = sizeof(env);
- i = erts_sys_getenv("ERL_CRASH_DUMP_SECONDS", env, &envsz);
+ i = erts_sys_getenv_raw("ERL_CRASH_DUMP_SECONDS", env, &envsz);
if (i >= 0) {
unsigned sec;
sec = (unsigned) i != 0 ? 0 : atoi(env);
@@ -731,7 +748,7 @@ break_requested(void)
erl_exit(ERTS_INTR_EXIT, "");
ERTS_SET_BREAK_REQUESTED;
- ERTS_CHK_IO_INTR(1); /* Make sure we don't sleep in poll */
+ ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
}
/* set up signal handlers for break and quit */
@@ -931,18 +948,13 @@ void
os_flavor(char* namebuf, /* Where to return the name. */
unsigned size) /* Size of name buffer. */
{
- static int called = 0;
- static struct utsname uts; /* Information about the system. */
-
- if (!called) {
- char* s;
+ struct utsname uts; /* Information about the system. */
+ char* s;
- (void) uname(&uts);
- called = 1;
- for (s = uts.sysname; *s; s++) {
- if (isupper((int) *s)) {
- *s = tolower((int) *s);
- }
+ (void) uname(&uts);
+ for (s = uts.sysname; *s; s++) {
+ if (isupper((int) *s)) {
+ *s = tolower((int) *s);
}
}
strcpy(namebuf, uts.sysname);
@@ -1021,14 +1033,15 @@ static struct driver_data {
/* Driver interfaces */
static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
-static int fd_control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT,
+ char **, ErlDrvSizeT);
static ErlDrvData vanilla_start(ErlDrvPort, char*, SysDriverOpts*);
static int spawn_init(void);
static void fd_stop(ErlDrvData);
static void stop(ErlDrvData);
static void ready_input(ErlDrvData, ErlDrvEvent);
static void ready_output(ErlDrvData, ErlDrvEvent);
-static void output(ErlDrvData, char*, int);
+static void output(ErlDrvData, char*, ErlDrvSizeT);
static void outputv(ErlDrvData, ErlIOVec*);
static void stop_select(ErlDrvEvent, void*);
@@ -1107,31 +1120,6 @@ struct erl_drv_entry vanilla_driver_entry = {
stop_select
};
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-static int async_drv_init(void);
-static ErlDrvData async_drv_start(ErlDrvPort, char*, SysDriverOpts*);
-static void async_drv_stop(ErlDrvData);
-static void async_drv_input(ErlDrvData, ErlDrvEvent);
-
-/* INTERNAL use only */
-
-struct erl_drv_entry async_driver_entry = {
- async_drv_init,
- async_drv_start,
- async_drv_stop,
- NULL,
- async_drv_input,
- NULL,
- "async",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
-};
-#endif
-
/* Handle SIGCHLD signals. */
#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
static RETSIGTYPE onchld(void)
@@ -1145,7 +1133,7 @@ static RETSIGTYPE onchld(int signum)
smp_sig_notify('C');
#else
children_died = 1;
- ERTS_CHK_IO_INTR(1); /* Make sure we don't sleep in poll */
+ ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
#endif
}
@@ -1175,6 +1163,8 @@ static int set_driver_data(int port_num,
report_exit_list = report_exit;
}
+ erts_port[port_num].os_pid = pid;
+
if (read_write & DO_READ) {
driver_data[ifd].packet_bytes = packet_bytes;
driver_data[ifd].port_num = port_num;
@@ -1366,9 +1356,9 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* op
int no_vfork;
size_t no_vfork_sz = sizeof(no_vfork);
- no_vfork = (erts_sys_getenv("ERL_NO_VFORK",
- (char *) &no_vfork,
- &no_vfork_sz) >= 0);
+ no_vfork = (erts_sys_getenv_raw("ERL_NO_VFORK",
+ (char *) &no_vfork,
+ &no_vfork_sz) >= 0);
#endif
switch (opts->read_write) {
@@ -1739,10 +1729,10 @@ static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
return -1;
}
-static int fd_control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
int fd = (int)(long)drv_data;
char resbuff[2*sizeof(Uint32)];
@@ -2014,18 +2004,20 @@ static void outputv(ErlDrvData e, ErlIOVec* ev)
int ix = driver_data[fd].port_num;
int pb = driver_data[fd].packet_bytes;
int ofd = driver_data[fd].ofd;
- int n;
- int sz;
+ ssize_t n;
+ ErlDrvSizeT sz;
char lb[4];
char* lbp;
- int len = ev->size;
+ ErlDrvSizeT len = ev->size;
/* (len > ((unsigned long)-1 >> (4-pb)*8)) */
+ /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/
if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) {
driver_failure_posix(ix, EINVAL);
return; /* -1; */
}
- put_int32(len, lb);
+ /* Handles 0 <= pb <= 4 only */
+ put_int32((Uint32) len, lb);
lbp = lb + (4-pb);
ev->iov[0].iov_base = lbp;
@@ -2056,14 +2048,14 @@ static void outputv(ErlDrvData e, ErlIOVec* ev)
}
-static void output(ErlDrvData e, char* buf, int len)
+static void output(ErlDrvData e, char* buf, ErlDrvSizeT len)
{
int fd = (int)(long)e;
int ix = driver_data[fd].port_num;
int pb = driver_data[fd].packet_bytes;
int ofd = driver_data[fd].ofd;
- int n;
- int sz;
+ ssize_t n;
+ ErlDrvSizeT sz;
char lb[4];
char* lbp;
struct iovec iv[2];
@@ -2316,87 +2308,6 @@ static void stop_select(ErlDrvEvent fd, void* _)
close((int)fd);
}
-/*
-** Async opertation support
-*/
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-static void
-sys_async_ready_failed(int fd, int r, int err)
-{
- char buf[120];
- sprintf(buf, "sys_async_ready(): Fatal error: fd=%d, r=%d, errno=%d\n",
- fd, r, err);
- erts_silence_warn_unused_result(write(2, buf, strlen(buf)));
- abort();
-}
-
-/* called from threads !! */
-void sys_async_ready(int fd)
-{
- int r;
- while (1) {
- r = write(fd, "0", 1); /* signal main thread fd MUST be async_fd[1] */
- if (r == 1) {
- DEBUGF(("sys_async_ready(): r = 1\r\n"));
- break;
- }
- if (r < 0 && errno == EINTR) {
- DEBUGF(("sys_async_ready(): r = %d\r\n", r));
- continue;
- }
- sys_async_ready_failed(fd, r, errno);
- }
-}
-
-static int async_drv_init(void)
-{
- async_fd[0] = -1;
- async_fd[1] = -1;
- return 0;
-}
-
-static ErlDrvData async_drv_start(ErlDrvPort port_num,
- char* name, SysDriverOpts* opts)
-{
- if (async_fd[0] != -1)
- return ERL_DRV_ERROR_GENERAL;
- if (pipe(async_fd) < 0)
- return ERL_DRV_ERROR_GENERAL;
-
- DEBUGF(("async_drv_start: %d\r\n", port_num));
-
- SET_NONBLOCKING(async_fd[0]);
- driver_select(port_num, async_fd[0], ERL_DRV_READ, 1);
-
- if (init_async(async_fd[1]) < 0)
- return ERL_DRV_ERROR_GENERAL;
- return (ErlDrvData)port_num;
-}
-
-static void async_drv_stop(ErlDrvData e)
-{
- int port_num = (int)(long)e;
-
- DEBUGF(("async_drv_stop: %d\r\n", port_num));
-
- exit_async();
-
- driver_select(port_num, async_fd[0], ERL_DRV_READ, 0);
-
- close(async_fd[0]);
- close(async_fd[1]);
- async_fd[0] = async_fd[1] = -1;
-}
-
-
-static void async_drv_input(ErlDrvData e, ErlDrvEvent fd)
-{
- char *buf[32];
- DEBUGF(("async_drv_input\r\n"));
- while (read((int) fd, (void *) buf, 32) > 0); /* fd MUST be async_fd[0] */
- check_async_ready(); /* invoke all async_ready */
-}
-#endif
void erts_do_break_handling(void)
{
@@ -2408,11 +2319,7 @@ void erts_do_break_handling(void)
* therefore, make sure that all threads but this one are blocked before
* proceeding!
*/
- erts_smp_block_system(0);
- /*
- * NOTE: since we allow gc we are not allowed to lock
- * (any) process main locks while blocking system...
- */
+ erts_smp_thr_progress_block();
/* during break we revert to initial settings */
/* this is done differently for oldshell */
@@ -2440,7 +2347,7 @@ void erts_do_break_handling(void)
tcsetattr(0,TCSANOW,&temp_mode);
}
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
/* Fills in the systems representation of the jam/beam process identifier.
@@ -2455,31 +2362,39 @@ void sys_get_pid(char *buffer){
}
int
-erts_sys_putenv(char *buffer, int sep_ix)
+erts_sys_putenv_raw(char *key, char *value) {
+ return erts_sys_putenv(key, value);
+}
+int
+erts_sys_putenv(char *key, char *value)
{
int res;
char *env;
+ Uint need = strlen(key) + strlen(value) + 2;
+
#ifdef HAVE_COPYING_PUTENV
- env = buffer;
+ env = erts_alloc(ERTS_ALC_T_TMP, need);
#else
- Uint sz = strlen(buffer)+1;
- env = erts_alloc(ERTS_ALC_T_PUTENV_STR, sz);
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, sz);
- strcpy(env,buffer);
+ env = erts_alloc(ERTS_ALC_T_PUTENV_STR, need);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, need);
#endif
+ strcpy(env,key);
+ strcat(env,"=");
+ strcat(env,value);
erts_smp_rwmtx_rwlock(&environ_rwmtx);
res = putenv(env);
erts_smp_rwmtx_rwunlock(&environ_rwmtx);
+#ifdef HAVE_COPYING_PUTENV
+ erts_free(ERTS_ALC_T_TMP, env);
+#endif
return res;
}
int
-erts_sys_getenv(char *key, char *value, size_t *size)
+erts_sys_getenv__(char *key, char *value, size_t *size)
{
- char *orig_value;
int res;
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- orig_value = getenv(key);
+ char *orig_value = getenv(key);
if (!orig_value)
res = -1;
else {
@@ -2494,6 +2409,20 @@ erts_sys_getenv(char *key, char *value, size_t *size)
res = 0;
}
}
+ return res;
+}
+
+int
+erts_sys_getenv_raw(char *key, char *value, size_t *size) {
+ return erts_sys_getenv(key, value, size);
+}
+
+int
+erts_sys_getenv(char *key, char *value, size_t *size)
+{
+ int res;
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ res = erts_sys_getenv__(key, value, size);
erts_smp_rwmtx_runlock(&environ_rwmtx);
return res;
}
@@ -2505,31 +2434,6 @@ sys_init_io(void)
erts_alloc(ERTS_ALC_T_FD_TAB, max_files * sizeof(struct fd_data));
erts_smp_atomic_add_nob(&sys_misc_mem_sz,
max_files * sizeof(struct fd_data));
-
-#ifdef USE_THREADS
-#ifdef ERTS_SMP
- if (init_async(-1) < 0)
- erl_exit(1, "Failed to initialize async-threads\n");
-#else
- {
- /* This is speical stuff, starting a driver from the
- * system routines, but is a nice way of handling stuff
- * the erlang way
- */
- SysDriverOpts dopts;
- int ret;
-
- sys_memset((void*)&dopts, 0, sizeof(SysDriverOpts));
- add_driver_entry(&async_driver_entry);
- ret = erts_open_driver(NULL, NIL, "async", &dopts, NULL);
- DEBUGF(("open_driver = %d\n", ret));
- if (ret < 0)
- erl_exit(1, "Failed to open async driver\n");
- erts_port[ret].status |= ERTS_PORT_SFLG_IMMORTAL;
- }
-#endif
-#endif
-
}
#if (0) /* unused? */
@@ -2756,15 +2660,7 @@ initiate_report_exit_status(ErtsSysReportExit *rep, int status)
rep->next = report_exit_transit_list;
rep->status = status;
report_exit_transit_list = rep;
- /*
- * We need the scheduler thread to call check_children().
- * If the scheduler thread is sleeping in a poll with a
- * timeout, we need to wake the scheduler thread. We use the
- * functionality of the async driver to do this, instead of
- * implementing yet another driver doing the same thing. A
- * little bit ugly, but it works...
- */
- sys_async_ready(async_fd[1]);
+ erts_sys_schedule_interrupt(1);
}
static int check_children(void)
@@ -2851,20 +2747,11 @@ erl_sys_schedule(int runnable)
{
#ifdef ERTS_SMP
ERTS_CHK_IO(!runnable);
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
#else
- ERTS_CHK_IO_INTR(0);
- if (runnable) {
- ERTS_CHK_IO(0); /* Poll for I/O */
- check_async_ready(); /* Check async completions */
- } else {
- int wait_for_io = !check_async_ready();
- if (wait_for_io)
- wait_for_io = !check_children();
- ERTS_CHK_IO(wait_for_io);
- }
- (void) check_children();
+ ERTS_CHK_IO(runnable ? 0 : !check_children());
#endif
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
+ (void) check_children();
}
@@ -2892,8 +2779,8 @@ smp_sig_notify(char c)
static void *
signal_dispatcher_thread_func(void *unused)
{
- int initialized = 0;
#if !CHLDWTHR
+ int initialized = 0;
int notify_check_children = 0;
#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
@@ -2921,20 +2808,20 @@ signal_dispatcher_thread_func(void *unused)
* to other threads.
*
* NOTE 2: The signal dispatcher thread is not a blockable
- * thread (i.e., it hasn't called
- * erts_register_blockable_thread()). This is
- * intentional. We want to be able to interrupt
- * writing of a crash dump by hitting C-c twice.
- * Since it isn't a blockable thread it is important
- * that it doesn't change the state of any data that
- * a blocking thread expects to have exclusive access
- * to (unless the signal dispatcher itself explicitly
- * is blocking all blockable threads).
+ * thread (i.e., not a thread managed by the
+ * erl_thr_progress module). This is intentional.
+ * We want to be able to interrupt writing of a crash
+ * dump by hitting C-c twice. Since it isn't a
+ * blockable thread it is important that it doesn't
+ * change the state of any data that a blocking thread
+ * expects to have exclusive access to (unless the
+ * signal dispatcher itself explicitly is blocking all
+ * blockable threads).
*/
switch (buf[i]) {
case 0: /* Emulator initialized */
- initialized = 1;
#if !CHLDWTHR
+ initialized = 1;
if (!notify_check_children)
#endif
break;
@@ -2969,7 +2856,7 @@ signal_dispatcher_thread_func(void *unused)
buf[i]);
}
}
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
}
return NULL;
}
@@ -3129,7 +3016,7 @@ erl_sys_args(int* argc, char** argv)
if (erts_use_kernel_poll) {
char no_kp[10];
size_t no_kp_sz = sizeof(no_kp);
- int res = erts_sys_getenv("ERL_NO_KERNEL_POLL", no_kp, &no_kp_sz);
+ int res = erts_sys_getenv_raw("ERL_NO_KERNEL_POLL", no_kp, &no_kp_sz);
if (res > 0
|| (res == 0
&& sys_strcmp("false", no_kp) != 0
diff --git a/erts/emulator/sys/vxworks/erl_vxworks_sys.h b/erts/emulator/sys/vxworks/erl_vxworks_sys.h
index ae46403600..3d53238ea6 100644
--- a/erts/emulator/sys/vxworks/erl_vxworks_sys.h
+++ b/erts/emulator/sys/vxworks/erl_vxworks_sys.h
@@ -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
@@ -158,6 +158,7 @@ typedef struct _vxworks_tms {
typedef long long SysHrTime;
+typedef time_t erts_time_t;
typedef struct timeval SysTimeval;
extern int sys_init_hrtime(void);
diff --git a/erts/emulator/sys/vxworks/sys.c b/erts/emulator/sys/vxworks/sys.c
index a59e4ec26a..739b026fb1 100644
--- a/erts/emulator/sys/vxworks/sys.c
+++ b/erts/emulator/sys/vxworks/sys.c
@@ -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,6 +238,12 @@ erl_sys_args(int* argc, char** argv)
ASSERT(max_files <= erts_vxworks_max_files);
}
+void
+erts_sys_schedule_interrupt(int set)
+{
+ erts_check_io_interrupt(set);
+}
+
/*
* Called from schedule() when it runs out of runnable processes,
* or when Erlang code has performed INPUT_REDUCTIONS reduction
@@ -246,7 +252,6 @@ erl_sys_args(int* argc, char** argv)
void
erl_sys_schedule(int runnable)
{
- erts_check_io_interrupt(0);
erts_check_io(!runnable);
}
@@ -309,7 +314,7 @@ static void request_break(void)
fprintf(stderr,"break!\n");
#endif
erts_break_requested = 1;
- erts_check_io_interrupt(1); /* Make sure we don't sleep in erts_poll_wait */
+ erts_check_io_async_sig_interrupt(1); /* Make sure we don't sleep in erts_poll_wait */
}
static void do_quit(void)
@@ -560,7 +565,7 @@ static void fd_stop(ErlDrvData);
static void stop(ErlDrvData);
static void ready_input(ErlDrvData fd, ErlDrvEvent ready_fd);
static void ready_output(ErlDrvData fd, ErlDrvEvent ready_fd);
-static void output(ErlDrvData fd, char *buf, int len);
+static void output(ErlDrvData fd, char *buf, ErlDrvSizeT len);
static void stop_select(ErlDrvEvent, void*);
struct erl_drv_entry spawn_driver_entry = {
@@ -1182,7 +1187,7 @@ static int sched_write(int port_num,int fd, char *buf, int len, int pb)
}
/* Fd is the value returned as drv_data by the start func */
-static void output(ErlDrvData drv_data, char *buf, int len)
+static void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
int buf_done, port_num, wval, pb, ofd;
byte lb[4];
@@ -1515,6 +1520,12 @@ erts_sys_getenv(char *key, char *value, size_t *size)
return res;
}
+int
+erts_sys_getenv__(char *key, char *value, size_t *size)
+{
+ return erts_sys_getenv(key, value, size);
+}
+
void
sys_init_io(void)
{
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index 735c420d8e..7a1d129cd5 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -442,8 +442,8 @@ poll_wait_timeout(ErtsPollSet ps, SysTimeval *tvp)
if (erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN)
return (DWORD) 0;
- if (timeout > ERTS_AINT32_T_MAX) /* Also prevents DWORD overflow */
- timeout = ERTS_AINT32_T_MAX;
+ if (timeout > ((time_t) ERTS_AINT32_T_MAX))
+ timeout = ERTS_AINT32_T_MAX; /* Also prevents DWORD overflow */
erts_smp_atomic32_set_relb(&ps->timeout, (erts_aint32_t) timeout);
return (DWORD) timeout;
@@ -1012,7 +1012,7 @@ void erts_poll_interrupt(ErtsPollSet ps, int set /* bool */)
void erts_poll_interrupt_timed(ErtsPollSet ps,
int set /* bool */,
- long msec)
+ erts_short_time_t msec)
{
HARDTRACEF(("In erts_poll_interrupt_timed(%d,%ld)",set,msec));
if (!set)
@@ -1159,7 +1159,13 @@ int erts_poll_wait(ErtsPollSet ps,
HARDDEBUGF(("Start waiting %d [%d]",num_h, (int) timeout));
ERTS_POLLSET_UNLOCK(ps);
+#ifdef ERTS_SMP
+ erts_thr_progress_prepare_wait(NULL);
+#endif
WaitForMultipleObjects(num_h, harr, FALSE, timeout);
+#ifdef ERTS_SMP
+ erts_thr_progress_finalize_wait(NULL);
+#endif
ERTS_POLLSET_LOCK(ps);
HARDDEBUGF(("Stop waiting %d [%d]",num_h, (int) timeout));
woke_up(ps);
diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
index a19f49af10..d00eed932b 100644
--- a/erts/emulator/sys/win32/erl_win32_sys_ddll.c
+++ b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
@@ -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
@@ -25,6 +25,9 @@
#include <windows.h>
#define GET_ERTS_ALC_TEST
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "global.h"
#include "erl_alloc.h"
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index ecb06868d5..ec5141838a 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -39,11 +39,11 @@ WDD_TYPEDEF(int, driver_exit, (ErlDrvPort, int));
WDD_TYPEDEF(int, driver_failure_eof, (ErlDrvPort));
WDD_TYPEDEF(int, driver_select, (ErlDrvPort, ErlDrvEvent, int, int));
WDD_TYPEDEF(int, driver_event, (ErlDrvPort, ErlDrvEvent,ErlDrvEventData));
-WDD_TYPEDEF(int, driver_output, (ErlDrvPort, char *, int));
-WDD_TYPEDEF(int, driver_output2, (ErlDrvPort, char *, int,char *, int));
-WDD_TYPEDEF(int, driver_output_binary, (ErlDrvPort, char *, int,ErlDrvBinary*, int, int));
-WDD_TYPEDEF(int, driver_outputv, (ErlDrvPort, char*, int, ErlIOVec *,int));
-WDD_TYPEDEF(int, driver_vec_to_buf, (ErlIOVec *, char *, int));
+WDD_TYPEDEF(int, driver_output, (ErlDrvPort, char *, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_output2, (ErlDrvPort, char *, ErlDrvSizeT ,char *, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_output_binary, (ErlDrvPort, char *, ErlDrvSizeT, ErlDrvBinary*, ErlDrvSizeT, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_outputv, (ErlDrvPort, char*, ErlDrvSizeT, ErlIOVec *, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_vec_to_buf, (ErlIOVec *, char *, ErlDrvSizeT));
WDD_TYPEDEF(int, driver_set_timer, (ErlDrvPort, unsigned long));
WDD_TYPEDEF(int, driver_cancel_timer, (ErlDrvPort));
WDD_TYPEDEF(int, driver_read_timer, (ErlDrvPort, unsigned long *));
@@ -51,22 +51,22 @@ WDD_TYPEDEF(char *, erl_errno_id, (int));
WDD_TYPEDEF(void, set_busy_port, (ErlDrvPort, int));
WDD_TYPEDEF(void, set_port_control_flags, (ErlDrvPort, int));
WDD_TYPEDEF(int, get_port_flags, (ErlDrvPort));
-WDD_TYPEDEF(ErlDrvBinary *, driver_alloc_binary, (int));
-WDD_TYPEDEF(ErlDrvBinary *, driver_realloc_binary, (ErlDrvBinary *, int));
+WDD_TYPEDEF(ErlDrvBinary *, driver_alloc_binary, (ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvBinary *, driver_realloc_binary, (ErlDrvBinary *, ErlDrvSizeT));
WDD_TYPEDEF(void, driver_free_binary, (ErlDrvBinary *));
-WDD_TYPEDEF(void *, driver_alloc, (size_t));
-WDD_TYPEDEF(void *, driver_realloc, (void *, size_t));
+WDD_TYPEDEF(void *, driver_alloc, (ErlDrvSizeT));
+WDD_TYPEDEF(void *, driver_realloc, (void *, ErlDrvSizeT));
WDD_TYPEDEF(void, driver_free, (void *));
-WDD_TYPEDEF(int, driver_enq, (ErlDrvPort, char*, int));
-WDD_TYPEDEF(int, driver_pushq, (ErlDrvPort, char*, int));
-WDD_TYPEDEF(int, driver_deq, (ErlDrvPort, int));
-WDD_TYPEDEF(int, driver_sizeq, (ErlDrvPort));
-WDD_TYPEDEF(int, driver_enq_bin, (ErlDrvPort, ErlDrvBinary *, int,int));
-WDD_TYPEDEF(int, driver_pushq_bin, (ErlDrvPort, ErlDrvBinary *, int,int));
-WDD_TYPEDEF(int, driver_peekqv, (ErlDrvPort, ErlIOVec *));
+WDD_TYPEDEF(int, driver_enq, (ErlDrvPort, char*, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_pushq, (ErlDrvPort, char*, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_deq, (ErlDrvPort, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_sizeq, (ErlDrvPort));
+WDD_TYPEDEF(int, driver_enq_bin, (ErlDrvPort, ErlDrvBinary *, ErlDrvSizeT, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_pushq_bin, (ErlDrvPort, ErlDrvBinary *, ErlDrvSizeT, ErlDrvSizeT));
+WDD_TYPEDEF(ErlDrvSizeT, driver_peekqv, (ErlDrvPort, ErlIOVec *));
WDD_TYPEDEF(SysIOVec *, driver_peekq, (ErlDrvPort, int *));
-WDD_TYPEDEF(int, driver_enqv, (ErlDrvPort, ErlIOVec *, int));
-WDD_TYPEDEF(int, driver_pushqv, (ErlDrvPort, ErlIOVec *, int));
+WDD_TYPEDEF(int, driver_enqv, (ErlDrvPort, ErlIOVec *, ErlDrvSizeT));
+WDD_TYPEDEF(int, driver_pushqv, (ErlDrvPort, ErlIOVec *, ErlDrvSizeT));
WDD_TYPEDEF(void, add_driver_entry, (ErlDrvEntry *));
WDD_TYPEDEF(int, remove_driver_entry, (ErlDrvEntry *));
WDD_TYPEDEF(ErlDrvTermData, driver_mk_atom, (char*));
@@ -83,10 +83,10 @@ WDD_TYPEDEF(void *, driver_dl_open, (char *));
WDD_TYPEDEF(void *, driver_dl_sym, (void *, char *));
WDD_TYPEDEF(int, driver_dl_close, (void *));
WDD_TYPEDEF(char *, driver_dl_error, (void));
-WDD_TYPEDEF(unsigned long, erts_alc_test, (unsigned long,
- unsigned long,
- unsigned long,
- unsigned long));
+WDD_TYPEDEF(ErlDrvUInt, erts_alc_test, (ErlDrvUInt,
+ ErlDrvUInt,
+ ErlDrvUInt,
+ ErlDrvUInt));
WDD_TYPEDEF(ErlDrvSInt, driver_binary_get_refc, (ErlDrvBinary *dbp));
WDD_TYPEDEF(ErlDrvSInt, driver_binary_inc_refc, (ErlDrvBinary *dbp));
WDD_TYPEDEF(ErlDrvSInt, driver_binary_dec_refc, (ErlDrvBinary *dbp));
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index 92d8577537..1e7b555f42 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -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
@@ -117,9 +117,30 @@ int erts_check_io_debug(void);
#define SYS_CLK_TCK 1000
#define SYS_CLOCK_RESOLUTION 1
+#if SIZEOF_TIME_T != 8
+# error "Unexpected sizeof(time_t)"
+#endif
+
+/*
+ * gcc uses a 4 byte time_t and vc++ uses an 8 byte time_t.
+ * Types seen in beam_emu.c *need* to have the same size
+ * as in the rest of the system...
+ */
+typedef __int64 erts_time_t;
+
+struct tm *sys_localtime_r(time_t *epochs, struct tm *ptm);
+struct tm *sys_gmtime_r(time_t *epochs, struct tm *ptm);
+time_t sys_mktime( struct tm *ptm);
+
+#define localtime_r sys_localtime_r
+#define HAVE_LOCALTIME_R 1
+#define gmtime_r sys_gmtime_r
+#define HAVE_GMTIME_R
+#define mktime sys_mktime
+
typedef struct {
- long tv_sec;
- long tv_usec;
+ erts_time_t tv_sec;
+ erts_time_t tv_usec;
} SysTimeval;
typedef struct {
@@ -150,8 +171,8 @@ extern clock_t sys_times(SysTimes *buffer);
extern char *win_build_environment(char *);
typedef struct {
- char *environment_strings;
- char *next_string;
+ WCHAR *environment_strings;
+ WCHAR *next_string;
} GETENV_STATE;
void erts_sys_env_init(void);
@@ -169,10 +190,12 @@ void erts_sys_env_init(void);
extern volatile int erl_fp_exception;
#include <float.h>
-#if defined (__GNUC__)
+/* I suspect this test isn't right, it might depend on the version of GCC
+ rather than if it's a MINGW gcc, but I havent been able to pinpoint the
+ exact point where _finite was added to the headers in cygwin... */
+#if defined (__GNUC__) && !defined(__MINGW32__)
int _finite(double x);
#endif
-#endif
/*#define NO_FPE_SIGNALS*/
#define erts_get_current_fp_exception() NULL
@@ -191,13 +214,6 @@ int _finite(double x);
#define erts_sys_block_fpe() 0
#define erts_sys_unblock_fpe(x) do{}while(0)
-#define SIZEOF_SHORT 2
-#define SIZEOF_INT 4
-#define SIZEOF_LONG 4
-#define SIZEOF_VOID_P 4
-#define SIZEOF_SIZE_T 4
-#define SIZEOF_OFF_T 4
-
/*
* Seems to be missing.
*/
@@ -210,3 +226,4 @@ typedef long ssize_t;
int init_async(int);
int exit_async(void);
#endif
+#endif
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index 3e151c26d5..29e2749800 100644..100755
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -68,9 +68,9 @@ static int async_write_file(struct async_io* aio, LPVOID buf, DWORD numToWrite);
static int get_overlapped_result(struct async_io* aio,
LPDWORD pBytesRead, BOOL wait);
static BOOL create_child_process(char *, HANDLE, HANDLE,
- HANDLE, LPHANDLE, BOOL,
- LPVOID, LPTSTR, unsigned,
- char **, int *);
+ HANDLE, LPHANDLE, LPDWORD, BOOL,
+ LPVOID, LPTSTR, unsigned,
+ char **, int *);
static int create_pipe(LPHANDLE, LPHANDLE, BOOL, BOOL);
static int application_type(const char* originalName, char fullPath[MAX_PATH],
BOOL search_in_path, BOOL handle_quotes,
@@ -216,6 +216,9 @@ void sys_tty_reset(int exit_code)
void erl_sys_args(int* argc, char** argv)
{
char *event_name;
+
+ erts_sys_env_init();
+
nohup = get_and_remove_option(argc, argv, "-nohup");
#ifdef DEBUG
@@ -471,7 +474,7 @@ static int spawn_init(void);
static int fd_init(void);
static void fd_stop(ErlDrvData);
static void stop(ErlDrvData);
-static void output(ErlDrvData, char*, int);
+static void output(ErlDrvData, char*, ErlDrvSizeT);
static void ready_input(ErlDrvData, ErlDrvEvent);
static void ready_output(ErlDrvData, ErlDrvEvent);
static void stop_select(ErlDrvEvent, void*);
@@ -566,51 +569,6 @@ struct erl_drv_entry vanilla_driver_entry = {
stop_select
};
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-
-static int async_drv_init(void);
-static ErlDrvData async_drv_start(ErlDrvPort, char*, SysDriverOpts*);
-static void async_drv_stop(ErlDrvData);
-static void async_drv_input(ErlDrvData, ErlDrvEvent);
-
-/* INTERNAL use only */
-
-void null_output(ErlDrvData drv_data, char* buf, int len)
-{
-}
-
-void null_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
-{
-}
-
-struct erl_drv_entry async_driver_entry = {
- async_drv_init,
- async_drv_start,
- async_drv_stop,
- null_output,
- async_drv_input,
- null_ready_output,
- "async",
- NULL, /* finish */
- NULL, /* handle */
- NULL, /* control */
- NULL, /* timeout */
- NULL, /* outputv */
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL,
- NULL, /* process_exit */
- stop_select
-};
-
-#endif
-
/*
* Initialises a DriverData structure.
*
@@ -1178,6 +1136,7 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
HANDLE hChildStdin = INVALID_HANDLE_VALUE; /* Child's stdin. */
HANDLE hChildStdout = INVALID_HANDLE_VALUE; /* Child's stout. */
HANDLE hChildStderr = INVALID_HANDLE_VALUE; /* Child's sterr. */
+ DWORD pid;
int close_child_stderr = 0;
DriverData* dp; /* Pointer to driver data. */
ErlDrvData retval = ERL_DRV_ERROR_GENERAL; /* Return value. */
@@ -1245,14 +1204,13 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
*/
DEBUGF(("Spawning \"%s\"\n", name));
- envir = win_build_environment(envir); /* Still an ansi environment, could be
- converted to unicode for spawn_executable, but
- that is not done (yet) */
+ envir = win_build_environment(envir); /* Always a unicode environment */
ok = create_child_process(name,
hChildStdin,
hChildStdout,
hChildStderr,
&dp->port_pid,
+ &pid,
opts->hide_window,
(LPVOID) envir,
(LPTSTR) opts->wd,
@@ -1296,6 +1254,9 @@ spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
#endif
retval = set_driver_data(dp, hFromChild, hToChild, opts->read_write,
opts->exit_status);
+ if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO)
+ /* We assume that this cannot generate a negative number */
+ erts_port[port_num].os_pid = (SWord) pid;
}
if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO)
@@ -1439,7 +1400,8 @@ create_child_process
HANDLE hStdin, /* The standard input handle for child. */
HANDLE hStdout, /* The standard output handle for child. */
HANDLE hStderr, /* The standard error handle for child. */
- LPHANDLE phPid, /* Pointer to variable to received PID. */
+ LPHANDLE phPid, /* Pointer to variable to received Process handle. */
+ LPDWORD pdwID, /* Pointer to variable to received Process ID */
BOOL hide, /* Hide the window unconditionally. */
LPVOID env, /* Environment for the child */
LPTSTR wd, /* Working dir for the child */
@@ -1521,7 +1483,8 @@ create_child_process
NULL,
NULL,
TRUE,
- createFlags | staticCreateFlags,
+ createFlags | staticCreateFlags |
+ CREATE_UNICODE_ENVIRONMENT,
env,
wd,
&siStartInfo,
@@ -1649,7 +1612,8 @@ create_child_process
NULL,
NULL,
TRUE,
- createFlags | staticCreateFlags,
+ createFlags | staticCreateFlags |
+ CREATE_UNICODE_ENVIRONMENT,
env,
(WCHAR *) wd,
&siStartInfo,
@@ -1671,22 +1635,12 @@ create_child_process
}
CloseHandle(piProcInfo.hThread); /* Necessary to avoid resource leak. */
*phPid = piProcInfo.hProcess;
-
+ *pdwID = piProcInfo.dwProcessId;
+
if (applType == APPL_DOS) {
WaitForSingleObject(hProcess, 50);
}
- /*
- * When an application spawns a process repeatedly, a new thread
- * instance will be created for each process but the previous
- * instances may not be cleaned up. This results in a significant
- * virtual memory loss each time the process is spawned. If there
- * is a WaitForInputIdle() call between CreateProcess() and
- * CloseHandle(), the problem does not occur. PSS ID Number: Q124121
- */
-
- WaitForInputIdle(piProcInfo.hProcess, 5000);
-
return ok;
}
@@ -2484,13 +2438,13 @@ threaded_exiter(LPVOID param)
*/
static void
-output(ErlDrvData drv_data, char* buf, int len)
+output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
/* long drv_data; /* The slot to use in the driver data table.
* For Windows NT, this is *NOT* a file handle.
* The handle is found in the driver data.
*/
-/* char *buf; /* Pointer to data to write to the port program. */
-/* int len; /* Number of bytes to write. */
+/* char *buf; /* Pointer to data to write to the port program. */
+/* ErlDrvSizeT len; /* Number of bytes to write. */
{
DriverData* dp;
int pb; /* The header size for this port. */
@@ -2825,30 +2779,6 @@ sys_init_io(void)
We estimate the number to twice the amount of ports.
We really dont know on windows, do we? */
max_files = 2*erts_max_ports;
-
-#ifdef USE_THREADS
-#ifdef ERTS_SMP
- if (init_async(-1) < 0)
- erl_exit(1, "Failed to initialize async-threads\n");
-#else
- {
- /* This is special stuff, starting a driver from the
- * system routines, but is a nice way of handling stuff
- * the erlang way
- */
- SysDriverOpts dopts;
- int ret;
-
- sys_memset((void*)&dopts, 0, sizeof(SysDriverOpts));
- add_driver_entry(&async_driver_entry);
- ret = erts_open_driver(NULL, NIL, "async", &dopts, NULL);
- DEBUGF(("open_driver = %d\n", ret));
- if (ret < 0)
- erl_exit(1, "Failed to open async driver\n");
- erts_port[ret].status |= ERTS_PORT_SFLG_IMMORTAL;
- }
-#endif
-#endif
}
#ifdef ERTS_SMP
@@ -3283,7 +3213,6 @@ erts_sys_pre_init(void)
}
#endif
erts_smp_atomic_init_nob(&sys_misc_mem_sz, 0);
- erts_sys_env_init();
}
void noinherit_std_handle(DWORD type)
@@ -3360,15 +3289,15 @@ void erl_sys_init(void)
SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
}
-#ifdef ERTS_SMP
void
erts_sys_schedule_interrupt(int set)
{
erts_check_io_interrupt(set);
}
+#ifdef ERTS_SMP
void
-erts_sys_schedule_interrupt_timed(int set, long msec)
+erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec)
{
erts_check_io_interrupt_timed(set, msec);
}
@@ -3382,76 +3311,7 @@ erts_sys_schedule_interrupt_timed(int set, long msec)
void
erl_sys_schedule(int runnable)
{
-#ifdef ERTS_SMP
erts_check_io(!runnable);
- ERTS_SMP_LC_ASSERT(!ERTS_LC_IS_BLOCKING);
-#else
- erts_check_io_interrupt(0);
- if (runnable) {
- erts_check_io(0); /* Poll for I/O */
- check_async_ready(); /* Check async completions */
- } else {
- erts_check_io(check_async_ready() ? 0 : 1);
- }
-#endif
-}
-
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
-/*
- * Async operation support.
- */
-
-static ErlDrvEvent async_drv_event;
-
-void
-sys_async_ready(int fd)
-{
- SetEvent((HANDLE)async_drv_event);
-}
-
-static int
-async_drv_init(void)
-{
- async_drv_event = (ErlDrvEvent) NULL;
- return 0;
-}
-
-static ErlDrvData
-async_drv_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
-{
- if (async_drv_event != (ErlDrvEvent) NULL) {
- return ERL_DRV_ERROR_GENERAL;
- }
- if ((async_drv_event = (ErlDrvEvent)CreateAutoEvent(FALSE)) == (ErlDrvEvent) NULL) {
- return ERL_DRV_ERROR_GENERAL;
- }
-
- driver_select(port_num, async_drv_event, ERL_DRV_READ|ERL_DRV_USE, 1);
- if (init_async(async_drv_event) < 0) {
- return ERL_DRV_ERROR_GENERAL;
- }
- return (ErlDrvData)port_num;
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
}
-static void
-async_drv_stop(ErlDrvData port_num)
-{
- exit_async();
- driver_select((ErlDrvPort)port_num, async_drv_event, ERL_DRV_READ|ERL_DRV_USE, 0);
- /*CloseHandle((HANDLE)async_drv_event);*/
- async_drv_event = (ErlDrvEvent) NULL;
-}
-
-
-static void
-async_drv_input(ErlDrvData port_num, ErlDrvEvent e)
-{
- check_async_ready();
-
- /*
- * Our event is auto-resetting.
- */
-}
-
-#endif
-
diff --git a/erts/emulator/sys/win32/sys_env.c b/erts/emulator/sys/win32/sys_env.c
index 02c8433a10..658a77c824 100644
--- a/erts/emulator/sys/win32/sys_env.c
+++ b/erts/emulator/sys/win32/sys_env.c
@@ -1,263 +1,299 @@
-/*
- * %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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_sys_driver.h"
-#include "erl_alloc.h"
-
-static char* merge_environment(char *current, char *add);
-static char* arg_to_env(char **arg);
-static char** env_to_arg(char *env);
-static char** find_arg(char **arg, char *str);
-static int compare(const void *a, const void *b);
-
-static erts_smp_rwmtx_t environ_rwmtx;
-
-void
-erts_sys_env_init(void)
-{
- erts_smp_rwmtx_init(&environ_rwmtx, "environ");
-}
-
-int
-erts_sys_putenv(char *key_value, int sep_ix)
-{
- int res;
- char sep = key_value[sep_ix];
- ASSERT(sep == '=');
- key_value[sep_ix] = '\0';
- erts_smp_rwmtx_rwlock(&environ_rwmtx);
- res = (SetEnvironmentVariable((LPCTSTR) key_value,
- (LPCTSTR) &key_value[sep_ix+1]) ? 0 : 1);
- erts_smp_rwmtx_rwunlock(&environ_rwmtx);
- key_value[sep_ix] = sep;
- return res;
-}
-
-int
-erts_sys_getenv(char *key, char *value, size_t *size)
-{
- size_t req_size = 0;
- int res = 0;
- DWORD new_size;
-
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- SetLastError(0);
- new_size = GetEnvironmentVariable((LPCTSTR) key,
- (LPTSTR) value,
- (DWORD) *size);
- res = !new_size && GetLastError() == ERROR_ENVVAR_NOT_FOUND ? -1 : 0;
- erts_smp_rwmtx_runlock(&environ_rwmtx);
- if (res < 0)
- return res;
- res = new_size > *size ? 1 : 0;
- *size = new_size;
- return res;
-}
-
-struct win32_getenv_state {
- char *env;
- char *next;
-};
-
-
-void init_getenv_state(GETENV_STATE *state)
-{
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- state->environment_strings = (char *) GetEnvironmentStrings();
- state->next_string = state->environment_strings;
-}
-
-char *getenv_string(GETENV_STATE *state)
-{
- ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
- if (state->next_string[0] == '\0')
- return NULL;
- else {
- char *res = state->next_string;
- state->next_string += sys_strlen(res) + 1;
- return res;
- }
-}
-
-void fini_getenv_state(GETENV_STATE *state)
-{
- FreeEnvironmentStrings(state->environment_strings);
- state->environment_strings = state->next_string = NULL;
- erts_smp_rwmtx_runlock(&environ_rwmtx);
-}
-
-char*
-win_build_environment(char* new_env)
-{
- if (new_env == NULL) {
- return NULL;
- } else {
- char *tmp, *merged;
-
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- tmp = GetEnvironmentStrings();
- merged = merge_environment(tmp, new_env);
-
- FreeEnvironmentStrings(tmp);
- erts_smp_rwmtx_runlock(&environ_rwmtx);
- return merged;
- }
-}
-
-static char*
-merge_environment(char *old, char *add)
-{
- char **a_arg = env_to_arg(add);
- char **c_arg = env_to_arg(old);
- char *ret;
- int i, j;
-
- for(i = 0; c_arg[i] != NULL; ++i)
- ;
-
- for(j = 0; a_arg[j] != NULL; ++j)
- ;
-
- c_arg = erts_realloc(ERTS_ALC_T_TMP,
- c_arg, (i+j+1) * sizeof(char *));
-
- for(j = 0; a_arg[j] != NULL; ++j){
- char **tmp;
- char *current = a_arg[j];
- char *eq_p = strchr(current,'=');
- int unset = (eq_p!=NULL && eq_p[1]=='\0');
-
- if ((tmp = find_arg(c_arg, current)) != NULL) {
- if (!unset) {
- *tmp = current;
- } else {
- *tmp = c_arg[--i];
- c_arg[i] = NULL;
- }
- } else if (!unset) {
- c_arg[i++] = current;
- c_arg[i] = NULL;
- }
- }
- ret = arg_to_env(c_arg);
- erts_free(ERTS_ALC_T_TMP, c_arg);
- erts_free(ERTS_ALC_T_TMP, a_arg);
- return ret;
-}
-
-static char**
-find_arg(char **arg, char *str)
-{
- char *tmp;
- int len;
-
- if ((tmp = strchr(str, '=')) != NULL) {
- tmp++;
- len = tmp - str;
- while (*arg != NULL){
- if (_strnicmp(*arg, str, len) == 0){
- return arg;
- }
- ++arg;
- }
- }
- return NULL;
-}
-
-static int
-compare(const void *a, const void *b)
-{
- char *s1 = *((char **) a);
- char *s2 = *((char **) b);
- char *e1 = strchr(s1,'=');
- char *e2 = strchr(s2,'=');
- int ret;
- int len;
-
- if(!e1)
- e1 = s1 + strlen(s1);
- if(!e2)
- e2 = s2 + strlen(s2);
-
- if((e1 - s1) > (e2 - s2))
- len = (e2 - s2);
- else
- len = (e1 - s1);
-
- ret = _strnicmp(s1,s2,len);
- if (ret == 0)
- return ((e1 - s1) - (e2 - s2));
- else
- return ret;
-}
-
-static char**
-env_to_arg(char *env)
-{
- char **ret;
- char *tmp;
- int i;
- int num_strings = 0;
-
- for(tmp = env; *tmp != '\0'; tmp += strlen(tmp)+1) {
- ++num_strings;
- }
- ret = erts_alloc(ERTS_ALC_T_TMP, sizeof(char *) * (num_strings + 1));
- i = 0;
- for(tmp = env; *tmp != '\0'; tmp += strlen(tmp)+1){
- ret[i++] = tmp;
- }
- ret[i] = NULL;
- return ret;
-}
-
-static char*
-arg_to_env(char **arg)
-{
- char *block;
- char *ptr;
- int i;
- int totlen = 1; /* extra '\0' */
-
- for(i = 0; arg[i] != NULL; ++i) {
- totlen += strlen(arg[i])+1;
- }
-
- /* sort the environment vector */
- qsort(arg, i, sizeof(char *), &compare);
-
- if (totlen == 1){
- block = erts_alloc(ERTS_ALC_T_ENVIRONMENT, 2);
- block[0] = block[1] = '\0';
- } else {
- block = erts_alloc(ERTS_ALC_T_ENVIRONMENT, totlen);
- ptr = block;
- for(i=0; arg[i] != NULL; ++i){
- strcpy(ptr, arg[i]);
- ptr += strlen(ptr)+1;
- }
- *ptr = '\0';
- }
- return block;
-}
+/*
+ * %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%
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "sys.h"
+#include "erl_sys_driver.h"
+#include "erl_alloc.h"
+
+static WCHAR *merge_environment(WCHAR *current, WCHAR *add);
+static WCHAR *arg_to_env(WCHAR **arg);
+static WCHAR **env_to_arg(WCHAR *env);
+static WCHAR **find_arg(WCHAR **arg, WCHAR *str);
+static int compare(const void *a, const void *b);
+
+static erts_smp_rwmtx_t environ_rwmtx;
+
+void
+erts_sys_env_init(void)
+{
+ erts_smp_rwmtx_init(&environ_rwmtx, "environ");
+}
+
+int
+erts_sys_putenv_raw(char *key, char *value)
+{
+ int res;
+ erts_smp_rwmtx_rwlock(&environ_rwmtx);
+ res = (SetEnvironmentVariable((LPCTSTR) key,
+ (LPCTSTR) value) ? 0 : 1);
+ erts_smp_rwmtx_rwunlock(&environ_rwmtx);
+ return res;
+}
+
+int
+erts_sys_putenv(char *key, char *value)
+{
+ int res;
+ WCHAR *wkey = (WCHAR *) key;
+ WCHAR *wvalue = (WCHAR *) value;
+ erts_smp_rwmtx_rwlock(&environ_rwmtx);
+ res = (SetEnvironmentVariableW(wkey,
+ wvalue) ? 0 : 1);
+ erts_smp_rwmtx_rwunlock(&environ_rwmtx);
+ return res;
+}
+
+int
+erts_sys_getenv(char *key, char *value, size_t *size)
+{
+ size_t req_size = 0;
+ int res = 0;
+ DWORD new_size;
+ WCHAR *wkey = (WCHAR *) key;
+ WCHAR *wvalue = (WCHAR *) value;
+ DWORD wsize = *size / (sizeof(WCHAR) / sizeof(char));
+
+ SetLastError(0);
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ new_size = GetEnvironmentVariableW(wkey,
+ wvalue,
+ (DWORD) wsize);
+ res = !new_size && GetLastError() == ERROR_ENVVAR_NOT_FOUND ? -1 : 0;
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ if (res < 0)
+ return res;
+ res = new_size > wsize ? 1 : 0;
+ *size = new_size * (sizeof(WCHAR) / sizeof(char));
+ return res;
+}
+int
+erts_sys_getenv__(char *key, char *value, size_t *size)
+{
+ size_t req_size = 0;
+ int res = 0;
+ DWORD new_size;
+
+ SetLastError(0);
+ new_size = GetEnvironmentVariable((LPCTSTR) key,
+ (LPTSTR) value,
+ (DWORD) *size);
+ res = !new_size && GetLastError() == ERROR_ENVVAR_NOT_FOUND ? -1 : 0;
+ if (res < 0)
+ return res;
+ res = new_size > *size ? 1 : 0;
+ *size = new_size;
+ return res;
+}
+
+int
+erts_sys_getenv_raw(char *key, char *value, size_t *size)
+{
+ int res;
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ res = erts_sys_getenv__(key, value, size);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ return res;
+}
+
+void init_getenv_state(GETENV_STATE *state)
+{
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ state->environment_strings = GetEnvironmentStringsW();
+ state->next_string = state->environment_strings;
+}
+
+char *getenv_string(GETENV_STATE *state)
+{
+ ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
+ if (state->next_string[0] == L'\0') {
+ return NULL;
+ } else {
+ WCHAR *res = state->next_string;
+ state->next_string += wcslen(res) + 1;
+ return (char *) res;
+ }
+}
+
+void fini_getenv_state(GETENV_STATE *state)
+{
+ FreeEnvironmentStringsW(state->environment_strings);
+ state->environment_strings = state->next_string = NULL;
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+}
+
+char*
+win_build_environment(char* new_env)
+{
+ if (new_env == NULL) {
+ return NULL;
+ } else {
+ WCHAR *tmp, *merged, *tmp_new;
+
+ tmp_new = (WCHAR *) new_env;
+
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+ tmp = GetEnvironmentStringsW();
+ merged = merge_environment(tmp, tmp_new);
+
+ FreeEnvironmentStringsW(tmp);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ return (char *) merged;
+ }
+}
+
+static WCHAR *
+merge_environment(WCHAR *old, WCHAR *add)
+{
+ WCHAR **a_arg = env_to_arg(add);
+ WCHAR **c_arg = env_to_arg(old);
+ WCHAR *ret;
+ int i, j;
+
+ for(i = 0; c_arg[i] != NULL; ++i)
+ ;
+
+ for(j = 0; a_arg[j] != NULL; ++j)
+ ;
+
+ c_arg = erts_realloc(ERTS_ALC_T_TMP,
+ c_arg, (i+j+1) * sizeof(WCHAR *));
+
+ for(j = 0; a_arg[j] != NULL; ++j){
+ WCHAR **tmp;
+ WCHAR *current = a_arg[j];
+ WCHAR *eq_p = wcschr(current,L'=');
+ int unset = (eq_p!=NULL && eq_p[1]==L'\0');
+
+ if ((tmp = find_arg(c_arg, current)) != NULL) {
+ if (!unset) {
+ *tmp = current;
+ } else {
+ *tmp = c_arg[--i];
+ c_arg[i] = NULL;
+ }
+ } else if (!unset) {
+ c_arg[i++] = current;
+ c_arg[i] = NULL;
+ }
+ }
+ ret = arg_to_env(c_arg);
+ erts_free(ERTS_ALC_T_TMP, c_arg);
+ erts_free(ERTS_ALC_T_TMP, a_arg);
+ return ret;
+}
+
+static WCHAR**
+find_arg(WCHAR **arg, WCHAR *str)
+{
+ WCHAR *tmp;
+ int len;
+
+ if ((tmp = wcschr(str, L'=')) != NULL) {
+ tmp++;
+ len = tmp - str;
+ while (*arg != NULL){
+ if (_wcsnicmp(*arg, str, len) == 0){
+ return arg;
+ }
+ ++arg;
+ }
+ }
+ return NULL;
+}
+
+static int
+compare(const void *a, const void *b)
+{
+ WCHAR *s1 = *((WCHAR **) a);
+ WCHAR *s2 = *((WCHAR **) b);
+ WCHAR *e1 = wcschr(s1,L'=');
+ WCHAR *e2 = wcschr(s2,L'=');
+ int ret;
+ int len;
+
+ if(!e1)
+ e1 = s1 + wcslen(s1);
+ if(!e2)
+ e2 = s2 + wcslen(s2);
+
+ if((e1 - s1) > (e2 - s2))
+ len = (e2 - s2);
+ else
+ len = (e1 - s1);
+
+ ret = _wcsnicmp(s1,s2,len);
+ if (ret == 0)
+ return ((e1 - s1) - (e2 - s2));
+ else
+ return ret;
+}
+
+static WCHAR**
+env_to_arg(WCHAR *env)
+{
+ WCHAR **ret;
+ WCHAR *tmp;
+ int i;
+ int num_strings = 0;
+
+ for(tmp = env; *tmp != '\0'; tmp += wcslen(tmp)+1) {
+ ++num_strings;
+ }
+ ret = erts_alloc(ERTS_ALC_T_TMP, sizeof(WCHAR *) * (num_strings + 1));
+ i = 0;
+ for(tmp = env; *tmp != '\0'; tmp += wcslen(tmp)+1){
+ ret[i++] = tmp;
+ }
+ ret[i] = NULL;
+ return ret;
+}
+
+static WCHAR *
+arg_to_env(WCHAR **arg)
+{
+ WCHAR *block;
+ WCHAR *ptr;
+ int i;
+ int totlen = 1; /* extra '\0' */
+
+ for(i = 0; arg[i] != NULL; ++i) {
+ totlen += wcslen(arg[i])+1;
+ }
+
+ /* sort the environment vector */
+ qsort(arg, i, sizeof(WCHAR *), &compare);
+
+ if (totlen == 1){
+ block = erts_alloc(ERTS_ALC_T_ENVIRONMENT, 2 * sizeof(WCHAR));
+ block[0] = block[1] = '\0';
+ } else {
+ block = erts_alloc(ERTS_ALC_T_ENVIRONMENT, totlen * sizeof(WCHAR));
+ ptr = block;
+ for(i=0; arg[i] != NULL; ++i){
+ wcscpy(ptr, arg[i]);
+ ptr += wcslen(ptr)+1;
+ }
+ *ptr = '\0';
+ }
+ return block;
+}
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index 9e67ca7f48..6558ad2d99 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.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
@@ -18,6 +18,9 @@
*/
/* Float conversions */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "signal.h"
diff --git a/erts/emulator/sys/win32/sys_interrupt.c b/erts/emulator/sys/win32/sys_interrupt.c
index 1d73edd30b..a507a19480 100644
--- a/erts/emulator/sys/win32/sys_interrupt.c
+++ b/erts/emulator/sys/win32/sys_interrupt.c
@@ -19,8 +19,12 @@
/*
* Purpose: Interrupt handling in windows.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "erl_alloc.h"
+#include "erl_thr_progress.h"
#include "erl_driver.h"
#include "../../drivers/win32/win_con.h"
@@ -52,14 +56,14 @@ void erts_do_break_handling(void)
* therefore, make sure that all threads but this one are blocked before
* proceeding!
*/
- erts_smp_block_system(0);
+ erts_smp_thr_progress_block();
/* call the break handling function, reset the flag */
do_break();
ResetEvent(erts_sys_break_event);
ERTS_UNSET_BREAK_REQUESTED;
- erts_smp_release_system();
+ erts_smp_thr_progress_unblock();
}
@@ -71,11 +75,11 @@ BOOL WINAPI ctrl_handler_ignore_break(DWORD dwCtrlType)
return TRUE;
break;
case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
if (nohup)
return TRUE;
/* else pour through... */
case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
erl_exit(0, "");
break;
}
@@ -123,11 +127,11 @@ BOOL WINAPI ctrl_handler(DWORD dwCtrlType)
SetEvent(erts_sys_break_event);
break;
case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
if (nohup)
return TRUE;
/* else pour through... */
case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
erl_exit(0, "");
break;
}
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index 50e43065b5..b5123dc45d 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.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
@@ -20,6 +20,9 @@
* Purpose: System-dependent time functions.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "assert.h"
@@ -32,28 +35,336 @@
/******************* Routines for time measurement *********************/
#define EPOCH_JULIAN_DIFF LL_LITERAL(11644473600)
+#define TICKS_PER_SECOND LL_LITERAL(10000000)
+#define SECONDS_PER_DAY LL_LITERAL(86400)
+
+#define ULI_TO_FILETIME(ft,ull) \
+ do { \
+ (ft).dwLowDateTime = (ull).LowPart; \
+ (ft).dwHighDateTime = (ull).HighPart; \
+ } while (0)
+
+#define FILETIME_TO_ULI(ull,ft) \
+ do { \
+ (ull).LowPart = (ft).dwLowDateTime; \
+ (ull).HighPart = (ft).dwHighDateTime; \
+ } while (0)
+
+#define EPOCH_TO_FILETIME(ft, epoch) \
+ do { \
+ ULARGE_INTEGER ull; \
+ ull.QuadPart = (((epoch) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND); \
+ ULI_TO_FILETIME(ft,ull); \
+ } while(0)
+
+#define FILETIME_TO_EPOCH(epoch, ft) \
+ do { \
+ ULARGE_INTEGER ull; \
+ FILETIME_TO_ULI(ull,ft); \
+ (epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_JULIAN_DIFF); \
+ } while(0)
+
static SysHrTime wrap = 0;
static DWORD last_tick_count = 0;
+/* Getting timezone information is a heavy operation, so we want to do this
+ only once */
+
+static TIME_ZONE_INFORMATION static_tzi;
+static int have_static_tzi = 0;
+
+static int days_in_month[2][13] = {
+ {0,31,28,31,30,31,30,31,31,30,31,30,31},
+ {0,31,29,31,30,31,30,31,31,30,31,30,31}};
+
int
sys_init_time(void)
{
+ if(GetTimeZoneInformation(&static_tzi) &&
+ static_tzi.StandardDate.wMonth != 0 &&
+ static_tzi.DaylightDate.wMonth != 0) {
+ have_static_tzi = 1;
+ }
return 1;
}
+/* Returns a switchtimes for DST as UTC filetimes given data from a
+ TIME_ZONE_INFORMATION, see sys_localtime_r for usage. */
+static void
+get_dst_switchtime(DWORD year,
+ SYSTEMTIME dstinfo, LONG bias,
+ FILETIME *utc_switchtime)
+{
+ DWORD occu;
+ DWORD weekday,wday_1st;
+ DWORD day, days_in;
+ FILETIME tmp,tmp2;
+ ULARGE_INTEGER ull;
+ int leap_year = 0;
+ if (dstinfo.wYear != 0) {
+ /* A year specific transition, in which case the data in the structure
+ is already properly set for a specific year. Compare year
+ with parameter and see if they correspond, in that case generate a
+ filetime directly, otherwise set the filetime to 0 */
+ if (year != dstinfo.wYear) {
+ utc_switchtime->dwLowDateTime = utc_switchtime->dwHighDateTime = 0;
+ return;
+ }
+ } else {
+ occu = dstinfo.wDay;
+ weekday = dstinfo.wDayOfWeek;
+
+ dstinfo.wDayOfWeek = 0;
+ dstinfo.wDay = 1;
+ dstinfo.wYear = year;
+
+ SystemTimeToFileTime(&dstinfo,&tmp);
+ ull.LowPart = tmp.dwLowDateTime;
+ ull.HighPart = tmp.dwHighDateTime;
+
+ ull.QuadPart /= (TICKS_PER_SECOND*SECONDS_PER_DAY); /* Julian Day */
+ wday_1st = (DWORD) ((ull.QuadPart + LL_LITERAL(1)) % LL_LITERAL(7));
+ day = (weekday >= wday_1st) ?
+ weekday - wday_1st + 1 :
+ weekday - wday_1st + 8;
+ --occu;
+ if (((dstinfo.wYear % 4) == 0 && (dstinfo.wYear % 100) > 0) ||
+ ((dstinfo.wYear % 400) == 0)) {
+ leap_year = 1;
+ }
+ days_in = days_in_month[leap_year][dstinfo.wMonth];
+ while (occu > 0 && (day + 7 <= days_in)) {
+ --occu;
+ day += 7;
+ }
+ dstinfo.wDay = day;
+ }
+ SystemTimeToFileTime(&dstinfo,&tmp);
+ /* correct for bias */
+ ull.LowPart = tmp.dwLowDateTime;
+ ull.HighPart = tmp.dwHighDateTime;
+ ull.QuadPart += (((LONGLONG) bias) * LL_LITERAL(60) * TICKS_PER_SECOND);
+ utc_switchtime->dwLowDateTime = ull.LowPart;
+ utc_switchtime->dwHighDateTime = ull.HighPart;
+ return;
+}
+
+/* This function gives approximately the correct year from a FILETIME
+ Around the actual new year, it may return the wrong value, but that's OK
+ as DST never switches around new year. */
+static DWORD
+approx_year(FILETIME ft)
+{
+ ULARGE_INTEGER ull;
+ FILETIME_TO_ULI(ull,ft);
+ ull.QuadPart /= LL_LITERAL(1000);
+ ull.QuadPart /= SECONDS_PER_DAY;
+ ull.QuadPart /= LL_LITERAL(3652425);
+ ull.QuadPart += 1601;
+ return (DWORD) ull.QuadPart;
+}
+
+struct tm *
+sys_localtime_r(time_t *epochs, struct tm *ptm)
+{
+ FILETIME ft,lft;
+ SYSTEMTIME st;
+
+ if ((((*epochs) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND) < 0LL) {
+ fprintf(stderr,"1\r\n"); fflush(stderr);
+ return NULL;
+ }
+
+ EPOCH_TO_FILETIME(ft,*epochs);
+ ptm->tm_isdst = 0;
+ if (have_static_tzi) {
+ FILETIME dst_start, dst_stop;
+ ULARGE_INTEGER ull;
+ DWORD year = approx_year(ft);
+ get_dst_switchtime(year,static_tzi.DaylightDate,
+ static_tzi.Bias+static_tzi.StandardBias,&dst_start);
+ get_dst_switchtime(year,static_tzi.StandardDate,
+ static_tzi.Bias+static_tzi.StandardBias+
+ static_tzi.DaylightBias,
+ &dst_stop);
+ FILETIME_TO_ULI(ull,ft);
+
+ if (CompareFileTime(&ft,&dst_start) >= 0 &&
+ CompareFileTime(&ft,&dst_stop) < 0) {
+ ull.QuadPart -=
+ ((LONGLONG) static_tzi.Bias+static_tzi.StandardBias+
+ static_tzi.DaylightBias) *
+ LL_LITERAL(60) * TICKS_PER_SECOND;
+ ptm->tm_isdst = 1;
+ } else {
+ ull.QuadPart -=
+ ((LONGLONG) static_tzi.Bias+static_tzi.StandardBias)
+ * LL_LITERAL(60) * TICKS_PER_SECOND;
+ }
+ ULI_TO_FILETIME(ft,ull);
+ } else {
+ if (!FileTimeToLocalFileTime(&ft,&lft)) {
+ return NULL;
+ }
+ ft = lft;
+ }
+
+ if (!FileTimeToSystemTime(&ft,&st)) {
+ return NULL;
+ }
+
+ ptm->tm_year = (int) st.wYear - 1900;
+ ptm->tm_mon = (int) st.wMonth - 1;
+ ptm->tm_mday = (int) st.wDay;
+ ptm->tm_hour = (int) st.wHour;
+ ptm->tm_min = (int) st.wMinute;
+ ptm->tm_sec = (int) st.wSecond;
+ ptm->tm_wday = (int) st.wDayOfWeek;
+ {
+ int yday = ptm->tm_mday - 1;
+ int m = ptm->tm_mon;
+ int leap_year = 0;
+ if (((st.wYear % 4) == 0 && (st.wYear % 100) > 0) ||
+ ((st.wYear % 400) == 0)) {
+ leap_year = 1;
+ }
+ while (m > 0) {
+ yday +=days_in_month[leap_year][m];
+ --m;
+ }
+ ptm->tm_yday = yday;
+ }
+ return ptm;
+}
+
+struct tm *
+sys_gmtime_r(time_t *epochs, struct tm *ptm)
+{
+ FILETIME ft;
+ SYSTEMTIME st;
+
+ if ((((*epochs) + EPOCH_JULIAN_DIFF) * TICKS_PER_SECOND) < 0LL) {
+ return NULL;
+ }
+
+ EPOCH_TO_FILETIME(ft,*epochs);
+
+ if (!FileTimeToSystemTime(&ft,&st)) {
+ return NULL;
+ }
+
+ ptm->tm_year = (int) st.wYear - 1900;
+ ptm->tm_mon = (int) st.wMonth - 1;
+ ptm->tm_mday = (int) st.wDay;
+ ptm->tm_hour = (int) st.wHour;
+ ptm->tm_min = (int) st.wMinute;
+ ptm->tm_sec = (int) st.wSecond;
+ ptm->tm_wday = (int) st.wDayOfWeek;
+ ptm->tm_isdst = 0;
+ {
+ int yday = ptm->tm_mday - 1;
+ int m = ptm->tm_mon;
+ int leap_year = 0;
+ if (((st.wYear % 4) == 0 && (st.wYear % 100) > 0) ||
+ ((st.wYear % 400) == 0)) {
+ leap_year = 1;
+ }
+ while (m > 0) {
+ yday +=days_in_month[leap_year][m];
+ --m;
+ }
+ ptm->tm_yday = yday;
+ }
+
+ return ptm;
+}
+
+time_t
+sys_mktime(struct tm *ptm)
+{
+ FILETIME ft;
+ SYSTEMTIME st;
+ int dst = 0;
+ time_t epochs;
+
+ memset(&st,0,sizeof(st));
+ /* Convert relevant parts of truct tm to SYSTEMTIME */
+ st.wYear = (USHORT) (ptm->tm_year + 1900);
+ st.wMonth = (USHORT) (ptm->tm_mon + 1);
+ st.wDay = (USHORT) ptm->tm_mday;
+ st.wHour = (USHORT) ptm->tm_hour;
+ st.wMinute = (USHORT) ptm->tm_min;
+ st.wSecond = (USHORT) ptm->tm_sec;
+
+ SystemTimeToFileTime(&st,&ft);
+
+ /* ft is now some kind of local file time, but it may be wrong depending
+ on what is in the tm_dst field. We need to manually convert it to
+ UTC before turning it into epochs */
+
+ if (have_static_tzi) {
+ FILETIME dst_start, dst_stop;
+ ULARGE_INTEGER ull_start,ull_stop,ull_ft;
+
+ FILETIME_TO_ULI(ull_ft,ft);
+
+ /* Correct everything except DST */
+ ull_ft.QuadPart += (static_tzi.Bias+static_tzi.StandardBias)
+ * LL_LITERAL(60) * TICKS_PER_SECOND;
+
+ /* Determine if DST is active */
+ if (ptm->tm_isdst >= 0) {
+ dst = ptm->tm_isdst;
+ } else if (static_tzi.DaylightDate.wMonth != 0){
+ /* This is how windows mktime does it, meaning it does not
+ take nonexisting local times into account */
+ get_dst_switchtime(st.wYear,static_tzi.DaylightDate,
+ static_tzi.Bias+static_tzi.StandardBias,
+ &dst_start);
+ get_dst_switchtime(st.wYear,static_tzi.StandardDate,
+ static_tzi.Bias+static_tzi.StandardBias+
+ static_tzi.DaylightBias,
+ &dst_stop);
+ FILETIME_TO_ULI(ull_start,dst_start);
+ FILETIME_TO_ULI(ull_stop,dst_stop);
+ if ((ull_ft.QuadPart >= ull_start.QuadPart) &&
+ (ull_ft.QuadPart < ull_stop.QuadPart)) {
+ /* We are in DST */
+ dst = 1;
+ }
+ }
+ /* Correct for DST */
+ if (dst) {
+ ull_ft.QuadPart += static_tzi.DaylightBias *
+ LL_LITERAL(60) * TICKS_PER_SECOND;
+ }
+ epochs = ((ull_ft.QuadPart / TICKS_PER_SECOND) - EPOCH_JULIAN_DIFF);
+ } else {
+ /* No DST, life is easy... */
+ FILETIME lft;
+ LocalFileTimeToFileTime(&ft,&lft);
+ FILETIME_TO_EPOCH(epochs,lft);
+ }
+ /* Normalize the struct tm */
+ sys_localtime_r(&epochs,ptm);
+ return epochs;
+}
+
void
sys_gettimeofday(SysTimeval *tv)
{
SYSTEMTIME t;
FILETIME ft;
- LONGLONG lft;
+ ULARGE_INTEGER ull;
GetSystemTime(&t);
SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / LL_LITERAL(10)) % LL_LITERAL(1000000));
- tv->tv_sec = (long) ((lft / LL_LITERAL(10000000)) - EPOCH_JULIAN_DIFF);
+ FILETIME_TO_ULI(ull,ft);
+ tv->tv_usec = (long) ((ull.QuadPart / LL_LITERAL(10)) %
+ LL_LITERAL(1000000));
+ tv->tv_sec = (long) ((ull.QuadPart / LL_LITERAL(10000000)) -
+ EPOCH_JULIAN_DIFF);
}
SysHrTime
@@ -88,9 +399,3 @@ sys_times(SysTimes *buffer) {
buffer->tms_stime = (clock_t) (system & LL_LITERAL(0x7FFFFFFF));
return kernel_ticks;
}
-
-
-
-
-
-
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 4d0c87bf12..03311423f0 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -61,7 +61,7 @@ MODULES= \
exception_SUITE \
float_SUITE \
fun_SUITE \
- fun_r12_SUITE \
+ fun_r13_SUITE \
gc_SUITE \
guard_SUITE \
hash_SUITE \
@@ -88,6 +88,7 @@ MODULES= \
send_term_SUITE \
sensitive_SUITE \
signal_SUITE \
+ smoke_test_SUITE \
statistics_SUITE \
system_info_SUITE \
system_profile_SUITE \
@@ -195,13 +196,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(EMAKEFILE) $(TEST_SPEC_FILES) \
- $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(NATIVE_ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(NO_OPT_ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(NATIVE_ERL_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/erts/emulator/test/a_SUITE_data/timer_driver.c b/erts/emulator/test/a_SUITE_data/timer_driver.c
index ef4dcdf501..44be94e0f0 100644
--- a/erts/emulator/test/a_SUITE_data/timer_driver.c
+++ b/erts/emulator/test/a_SUITE_data/timer_driver.c
@@ -17,7 +17,9 @@
#define CANCELLED 4
static ErlDrvData timer_start(ErlDrvPort, char*);
-static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData);
+static void timer_stop(ErlDrvData),
+ timer_read(ErlDrvData, char*, ErlDrvSizeT),
+ timer(ErlDrvData);
static ErlDrvEntry timer_driver_entry =
{
@@ -33,6 +35,16 @@ static ErlDrvEntry timer_driver_entry =
NULL,
timer,
NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -47,8 +59,9 @@ static ErlDrvData timer_start(ErlDrvPort port, char *buf)
}
/* set the timer, this is monitored from erlang measuring the time */
-static void timer_read(ErlDrvData port, char *buf, int len)
+static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len)
{
+ ErlDrvPort port = (ErlDrvPort) p;
char reply[1];
if (buf[0] == START_TIMER) {
@@ -62,8 +75,9 @@ static void timer_read(ErlDrvData port, char *buf, int len)
}
}
-static void timer_stop(ErlDrvData port)
+static void timer_stop(ErlDrvData p)
{
+ ErlDrvPort port = (ErlDrvPort) p;
driver_cancel_timer(port);
}
diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
index 8b34375980..cd4a91d34a 100644
--- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h
+++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
@@ -19,7 +19,7 @@
#ifndef ALLOCATOR_TEST_H__
#define ALLOCATOR_TEST_H__
-typedef unsigned long Ulong;
+typedef ErlDrvUInt Ulong;
#ifndef __WIN32__
Ulong erts_alc_test(Ulong, Ulong, Ulong, Ulong);
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
index 1e98844838..66971654a2 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
@@ -50,13 +50,32 @@ typedef struct {
ErlDrvData testcase_drv_start(ErlDrvPort port, char *command);
void testcase_drv_stop(ErlDrvData drv_data);
-void testcase_drv_run(ErlDrvData drv_data, char *buf, int len);
+void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
static ErlDrvEntry testcase_drv_entry = {
NULL,
testcase_drv_start,
testcase_drv_stop,
- testcase_drv_run
+ testcase_drv_run,
+ NULL,
+ NULL,
+ "testcase_drv",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
};
@@ -92,7 +111,7 @@ testcase_drv_stop(ErlDrvData drv_data)
}
void
-testcase_drv_run(ErlDrvData drv_data, char *buf, int len)
+testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data;
ErlDrvTermData result_atom;
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index c7617d3b90..99ed8f1748 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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 @@
types/1,
t_list_to_existing_atom/1,os_env/1,otp_7526/1,
binary_to_atom/1,binary_to_existing_atom/1,
- atom_to_binary/1,min_max/1]).
+ atom_to_binary/1,min_max/1, erlang_halt/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -36,7 +36,7 @@ all() ->
[types, t_list_to_existing_atom, os_env, otp_7526,
display,
atom_to_binary, binary_to_atom, binary_to_existing_atom,
- min_max].
+ min_max, erlang_halt].
groups() ->
[].
@@ -70,7 +70,7 @@ display(doc) ->
display(Config) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
{ok, Node} = test_server:start_node(display_huge_term,peer,
- [{args, "-pa "++Pa}]),
+ [{args, "-pa \""++Pa++"\""}]),
true = rpc:call(Node,?MODULE,display_huge,[]),
test_server:stop_node(Node),
ok.
@@ -438,7 +438,55 @@ min_max(Config) when is_list(Config) ->
ok.
+
+
+erlang_halt(Config) when is_list(Config) ->
+ try erlang:halt(undefined) of
+ _-> ?t:fail({erlang,halt,{undefined}})
+ catch error:badarg -> ok end,
+ try halt(undefined) of
+ _-> ?t:fail({halt,{undefined}})
+ catch error:badarg -> ok end,
+ try erlang:halt(undefined, []) of
+ _-> ?t:fail({erlang,halt,{undefined,[]}})
+ catch error:badarg -> ok end,
+ try halt(undefined, []) of
+ _-> ?t:fail({halt,{undefined,[]}})
+ catch error:badarg -> ok end,
+ try halt(0, undefined) of
+ _-> ?t:fail({halt,{0,undefined}})
+ catch error:badarg -> ok end,
+ try halt(0, [undefined]) of
+ _-> ?t:fail({halt,{0,[undefined]}})
+ catch error:badarg -> ok end,
+ try halt(0, [{undefined,true}]) of
+ _-> ?t:fail({halt,{0,[{undefined,true}]}})
+ catch error:badarg -> ok end,
+ try halt(0, [{flush,undefined}]) of
+ _-> ?t:fail({halt,{0,[{flush,undefined}]}})
+ catch error:badarg -> ok end,
+ try halt(0, [{flush,true,undefined}]) of
+ _-> ?t:fail({halt,{0,[{flush,true,undefined}]}})
+ catch error:badarg -> ok end,
+ H = hostname(),
+ {ok,N1} = slave:start(H, halt_node1),
+ {badrpc,nodedown} = rpc:call(N1, erlang, halt, []),
+ {ok,N2} = slave:start(H, halt_node2),
+ {badrpc,nodedown} = rpc:call(N2, erlang, halt, [0]),
+ {ok,N3} = slave:start(H, halt_node3),
+ {badrpc,nodedown} = rpc:call(N3, erlang, halt, [0,[]]),
+ ok.
+
+
+
%% Helpers
id(I) -> I.
+hostname() ->
+ hostname(atom_to_list(node())).
+
+hostname([$@ | Hostname]) ->
+ list_to_atom(Hostname);
+hostname([_C | Cs]) ->
+ hostname(Cs).
diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl
index 3487917677..413bd3bcae 100644
--- a/erts/emulator/test/big_SUITE.erl
+++ b/erts/emulator/test/big_SUITE.erl
@@ -26,7 +26,7 @@
shift_limit_1/1, powmod/1, system_limit/1, otp_6692/1]).
%% Internal exports.
--export([eval/1, funcall/2]).
+-export([eval/1]).
-export([init/3]).
-export([fac/1, fib/1, pow/2, gcd/2, lcm/2]).
@@ -162,12 +162,15 @@ multi_match([Node|Ns], Expr, Rs) ->
multi_match([], _, Rs) -> Rs.
eval(Expr) ->
- Fun = {?MODULE,funcall},
- {value,V,_} = erl_eval:expr(Expr, [], Fun), %Applied arithmetic BIFs.
- V = eval(Expr, Fun), %Real arithmetic instructions.
- V.
+ LFH = fun(Name, As) -> apply(?MODULE, Name, As) end,
+
+ %% Applied arithmetic BIFs.
+ {value,V,_} = erl_eval:expr(Expr, [], {value,LFH}),
-funcall(F, As) -> apply(?MODULE, F, As).
+ %% Real arithmetic instructions.
+ V = eval(Expr, LFH),
+
+ V.
%% Like a subset of erl_eval:expr/3, but uses real arithmetic instructions instead of
%% applying them (it does make a difference).
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index d9fc876482..c9f43bb00b 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1135,15 +1135,8 @@ sleeper() ->
?line receive after infinity -> ok end.
-gc_test(doc) -> "Test that binaries are garbage collected properly.";
-gc_test(suite) -> [];
+%% Test that binaries are garbage collected properly.
gc_test(Config) when is_list(Config) ->
- case erlang:system_info(heap_type) of
- private -> gc_test_1();
- hybrid -> {skip,"Hybrid heap"}
- end.
-
-gc_test_1() ->
%% Note: This test is only relevant for REFC binaries.
%% Therefore, we take care that all binaries are REFC binaries.
B = list_to_binary(lists:seq(0, ?heap_binary_size)),
diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl
index 7fdf36711b..dea02b1f4b 100644
--- a/erts/emulator/test/bs_construct_SUITE.erl
+++ b/erts/emulator/test/bs_construct_SUITE.erl
@@ -460,7 +460,6 @@ 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) ->
@@ -473,13 +472,6 @@ big_bin(B1, B2) ->
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>>,
diff --git a/erts/emulator/test/bs_utf_SUITE.erl b/erts/emulator/test/bs_utf_SUITE.erl
index 72c656c400..4ab7d674a6 100644
--- a/erts/emulator/test/bs_utf_SUITE.erl
+++ b/erts/emulator/test/bs_utf_SUITE.erl
@@ -64,8 +64,7 @@ end_per_group(_GroupName, Config) ->
utf8_roundtrip(Config) when is_list(Config) ->
?line utf8_roundtrip(0, 16#D7FF),
- ?line utf8_roundtrip(16#E000, 16#FFFD),
- ?line utf8_roundtrip(16#10000, 16#10FFFF),
+ ?line utf8_roundtrip(16#E000, 16#10FFFF),
ok.
utf8_roundtrip(First, Last) when First =< Last ->
@@ -91,8 +90,7 @@ utf16_roundtrip(Config) when is_list(Config) ->
do_utf16_roundtrip(Fun) ->
do_utf16_roundtrip(0, 16#D7FF, Fun),
- do_utf16_roundtrip(16#E000, 16#FFFD, Fun),
- do_utf16_roundtrip(16#10000, 16#10FFFF, Fun).
+ do_utf16_roundtrip(16#E000, 16#10FFFF, Fun).
do_utf16_roundtrip(First, Last, Fun) when First =< Last ->
Fun(First),
@@ -129,8 +127,7 @@ utf32_roundtrip(Config) when is_list(Config) ->
do_utf32_roundtrip(Fun) ->
do_utf32_roundtrip(0, 16#D7FF, Fun),
- do_utf32_roundtrip(16#E000, 16#FFFD, Fun),
- do_utf32_roundtrip(16#10000, 16#10FFFF, Fun).
+ do_utf32_roundtrip(16#E000, 16#10FFFF, Fun).
do_utf32_roundtrip(First, Last, Fun) when First =< Last ->
Fun(First),
@@ -158,7 +155,6 @@ utf32_little_roundtrip(Char) ->
utf8_illegal_sequences(Config) when is_list(Config) ->
?line fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line fail_range(16#FFFE, 16#FFFF), %Non-characters.
%% Illegal first character.
?line [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)],
@@ -251,7 +247,6 @@ fail_1(_) -> ok.
utf16_illegal_sequences(Config) when is_list(Config) ->
?line utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line utf16_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf16_fail_range(16#FFFE, 16#FFFF), %Non-characters.
?line lonely_hi_surrogate(16#D800, 16#DFFF),
?line leading_lo_surrogate(16#DC00, 16#DFFF),
@@ -300,7 +295,6 @@ leading_lo_surrogate(_, _, _) -> ok.
utf32_illegal_sequences(Config) when is_list(Config) ->
?line utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf32_fail_range(16#FFFE, 16#FFFF), %Non-characters.
?line utf32_fail_range(-100, -1),
ok.
diff --git a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c
index 1273d610ba..75106d3757 100644
--- a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c
+++ b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c
@@ -11,7 +11,8 @@
#define YES 1
static ErlDrvData busy_start(ErlDrvPort, char*);
-static void busy_stop(ErlDrvData), busy_from_erlang(ErlDrvData, char*, int);
+static void busy_stop(ErlDrvData),
+ busy_from_erlang(ErlDrvData, char*, ErlDrvSizeT);
ErlDrvEntry busy_driver_entry =
{
@@ -23,6 +24,20 @@ ErlDrvEntry busy_driver_entry =
NULL,
"busy_drv",
NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -73,7 +88,7 @@ static void busy_stop(ErlDrvData port)
}
static void
-busy_from_erlang(ErlDrvData port, char* buf, int count)
+busy_from_erlang(ErlDrvData port, char* buf, ErlDrvSizeT count)
{
if ((ErlDrvPort)port == slave_port) {
set_busy_port(slave_port, next_slave_state);
diff --git a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c
index 35919da2d0..9f6bd310c6 100644
--- a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c
+++ b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c
@@ -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
@@ -21,9 +21,9 @@
#include "erl_driver.h"
ErlDrvData start(ErlDrvPort port, char *command);
-void output(ErlDrvData drv_data, char *buf, int len);
-int control(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen);
+void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
+ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
static ErlDrvEntry busy_drv_entry = {
NULL /* init */,
@@ -61,7 +61,7 @@ ErlDrvData start(ErlDrvPort port, char *command)
return (ErlDrvData) port;
}
-void output(ErlDrvData drv_data, char *buf, int len)
+void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
int res;
ErlDrvPort port = (ErlDrvPort) drv_data;
@@ -76,8 +76,8 @@ void output(ErlDrvData drv_data, char *buf, int len)
driver_failure_atom(port, "driver_output_term failed");
}
-int control(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen)
+ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
{
switch (command) {
case 'B': /* busy */
diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl
index 3e2bee06d1..9d80b01748 100644
--- a/erts/emulator/test/call_trace_SUITE.erl
+++ b/erts/emulator/test/call_trace_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -165,10 +165,14 @@ worker_loop() ->
worker_foo(_Arg) ->
ok.
-basic(doc) ->
- "Basic test of the call tracing (we trace one process).";
-basic(suite) -> [];
-basic(Config) when is_list(Config) ->
+%% Basic test of the call tracing (we trace one process).
+basic(_Config) ->
+ case test_server:is_native(lists) of
+ true -> {skip,"lists is native"};
+ false -> basic()
+ end.
+
+basic() ->
?line start_tracer(),
?line trace_info(self(), flags),
?line trace_info(self(), tracer),
@@ -263,9 +267,15 @@ foo() -> foo0.
foo(X) -> X+1.
foo(X, Y) -> X+Y.
-flags(doc) -> "Test flags (arity, timestamp) for call_trace/3. "
- "Also, test the '{tracer,Pid}' option.";
-flags(Config) when is_list(Config) ->
+%% Test flags (arity, timestamp) for call_trace/3.
+%% Also, test the '{tracer,Pid}' option.
+flags(_Config) ->
+ case test_server:is_native(filename) of
+ true -> {skip,"filename is native"};
+ false -> flags()
+ end.
+
+flags() ->
?line Tracer = start_tracer_loop(),
?line trace_pid(self(), true, [call,{tracer,Tracer}]),
@@ -428,9 +438,14 @@ pam_foo(A, B) ->
{ok,A,B}.
-change_pam(doc) -> "Test changing PAM programs for a function.";
-change_pam(suite) -> [];
-change_pam(Config) when is_list(Config) ->
+%% Test changing PAM programs for a function.
+change_pam(_Config) ->
+ case test_server:is_native(lists) of
+ true -> {skip,"lists is native"};
+ false -> change_pam()
+ end.
+
+change_pam() ->
?line start_tracer(),
?line Self = self(),
@@ -468,10 +483,11 @@ change_pam_trace(Prog) ->
{match_spec,Prog} = trace_info({erlang,process_info,2}, match_spec),
ok.
-return_trace(doc) -> "Test the new return trace.";
-return_trace(suite) -> [];
-return_trace(Config) when is_list(Config) ->
- return_trace().
+return_trace(_Config) ->
+ case test_server:is_native(lists) of
+ true -> {skip,"lists is native"};
+ false -> return_trace()
+ end.
return_trace() ->
X = {save,me},
@@ -521,7 +537,7 @@ return_trace() ->
?line {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec),
?line lists:seq(2, 7),
- ?line atom_to_list(non_literal(nisse)),
+ ?line _ = atom_to_list(non_literal(nisse)),
?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}),
?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}),
@@ -539,10 +555,11 @@ return_trace() ->
nasty() ->
exit(good_bye).
-exception_trace(doc) -> "Test the new exception trace.";
-exception_trace(suite) -> [];
-exception_trace(Config) when is_list(Config) ->
- exception_trace().
+exception_trace(_Config) ->
+ case test_server:is_native(lists) of
+ true -> {skip,"lists is native"};
+ false -> exception_trace()
+ end.
exception_trace() ->
X = {save,me},
@@ -600,7 +617,7 @@ exception_trace() ->
trace_info({erlang,atom_to_list,1}, match_spec),
?line lists:seq(2, 7),
- ?line atom_to_list(non_literal(nisse)),
+ ?line _ = atom_to_list(non_literal(nisse)),
?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}),
?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}),
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index 29cbdedd17..74ce5e397a 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -20,30 +20,34 @@
-module(code_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- new_binary_types/1,
+ versions/1,new_binary_types/1,
t_check_process_code/1,t_check_old_code/1,
t_check_process_code_ets/1,
external_fun/1,get_chunk/1,module_md5/1,make_stub/1,
- make_stub_many_funs/1,constant_pools/1,
- false_dependency/1,coverage/1]).
+ make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1,
+ false_dependency/1,coverage/1,fun_confusion/1]).
+-define(line_trace, 1).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [new_binary_types, t_check_process_code,
+ [versions, new_binary_types, t_check_process_code,
t_check_process_code_ets, t_check_old_code, external_fun, get_chunk,
module_md5, make_stub, make_stub_many_funs,
- constant_pools, false_dependency, coverage].
+ constant_pools, constant_refc_binaries, false_dependency,
+ coverage, fun_confusion].
groups() ->
[].
init_per_suite(Config) ->
+ erts_debug:set_internal_state(available_internal_state, true),
Config.
end_per_suite(_Config) ->
+ catch erts_debug:set_internal_state(available_internal_state, false),
ok.
init_per_group(_GroupName, Config) ->
@@ -52,6 +56,60 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+%% Make sure that only two versions of a module can be loaded.
+versions(Config) when is_list(Config) ->
+ V1 = compile_version(1, Config),
+ V2 = compile_version(2, Config),
+ V3 = compile_version(3, Config),
+
+ {ok,P1,1} = load_version(V1, 1),
+ {ok,P2,2} = load_version(V2, 2),
+ {error,not_purged} = load_version(V2, 2),
+ {error,not_purged} = load_version(V3, 3),
+
+ 1 = check_version(P1),
+ 2 = check_version(P2),
+ 2 = versions:version(),
+
+ %% Kill processes, unload code.
+ P1 ! P2 ! done,
+ _ = monitor(process, P1),
+ _ = monitor(process, P2),
+ receive
+ {'DOWN',_,process,P1,normal} -> ok
+ end,
+ receive
+ {'DOWN',_,process,P2,normal} -> ok
+ end,
+ true = erlang:purge_module(versions),
+ true = erlang:delete_module(versions),
+ true = erlang:purge_module(versions),
+ ok.
+
+compile_version(Version, Config) ->
+ Data = ?config(data_dir, Config),
+ File = filename:join(Data, "versions"),
+ {ok,versions,Bin} = compile:file(File, [{d,'VERSION',Version},
+ binary,report]),
+ Bin.
+
+load_version(Code, Ver) ->
+ case erlang:load_module(versions, Code) of
+ {module,versions} ->
+ Pid = spawn_link(versions, loop, []),
+ Ver = versions:version(),
+ Ver = check_version(Pid),
+ {ok,Pid,Ver};
+ Error ->
+ Error
+ end.
+
+check_version(Pid) ->
+ Pid ! {self(),version},
+ receive
+ {Pid,version,Version} ->
+ Version
+ end.
new_binary_types(Config) when is_list(Config) ->
?line Data = ?config(data_dir, Config),
@@ -77,14 +135,7 @@ new_binary_types(Config) when is_list(Config) ->
bit_sized_binary(Bin))),
ok.
-t_check_process_code(doc) -> "Test check_process_code/2.";
t_check_process_code(Config) when is_list(Config) ->
- case erlang:system_info(heap_type) of
- private -> t_check_process_code_1(Config);
- hybrid -> {skip,"Hybrid heap"}
- end.
-
-t_check_process_code_1(Config) ->
?line Priv = ?config(priv_dir, Config),
?line Data = ?config(data_dir, Config),
?line File = filename:join(Data, "my_code_test"),
@@ -189,12 +240,10 @@ gc1() -> ok.
t_check_process_code_ets(doc) ->
"Test check_process_code/2 in combination with a fun obtained from an ets table.";
t_check_process_code_ets(Config) when is_list(Config) ->
- case {test_server:is_native(?MODULE),erlang:system_info(heap_type)} of
- {true,_} ->
- {skipped,"Native code"};
- {_,hybrid} ->
- {skipped,"Hybrid heap"};
- {false,private} ->
+ case test_server:is_native(?MODULE) of
+ true ->
+ {skip,"Native code"};
+ false ->
do_check_process_code_ets(Config)
end.
@@ -278,7 +327,8 @@ t_check_old_code(Config) when is_list(Config) ->
external_fun(Config) when is_list(Config) ->
?line false = erlang:function_exported(another_code_test, x, 1),
- ?line ExtFun = erlang:make_fun(id(another_code_test), x, 1),
+ AnotherCodeTest = id(another_code_test),
+ ExtFun = fun AnotherCodeTest:x/1,
?line {'EXIT',{undef,_}} = (catch ExtFun(answer)),
?line false = erlang:function_exported(another_code_test, x, 1),
?line false = lists:member(another_code_test, erlang:loaded()),
@@ -338,9 +388,7 @@ module_md5_ok(Code) ->
make_stub(Config) when is_list(Config) ->
- %% No old code to purge if hybrid heap because of skipped test cases,
- %% so we'll need a catch here.
- ?line (catch erlang:purge_module(my_code_test)),
+ catch erlang:purge_module(my_code_test),
?line Data = ?config(data_dir, Config),
?line File = filename:join(Data, "my_code_test"),
@@ -374,9 +422,7 @@ make_stub(Config) when is_list(Config) ->
ok.
make_stub_many_funs(Config) when is_list(Config) ->
- %% No old code to purge if hybrid heap because of skipped test cases,
- %% so we'll need a catch here.
- ?line (catch erlang:purge_module(many_funs)),
+ catch erlang:purge_module(many_funs),
?line Data = ?config(data_dir, Config),
?line File = filename:join(Data, "many_funs"),
@@ -403,7 +449,7 @@ make_stub_many_funs(Config) when is_list(Config) ->
constant_pools(Config) when is_list(Config) ->
?line Data = ?config(data_dir, Config),
?line File = filename:join(Data, "literals"),
- ?line {ok,literals,Code} = compile:file(File, [report,binary,constant_pool]),
+ ?line {ok,literals,Code} = compile:file(File, [report,binary]),
?line {module,literals} = erlang:load_module(literals,
make_sub_binary(Code)),
@@ -474,6 +520,131 @@ create_old_heap() ->
create_old_heap()
end.
+constant_refc_binaries(Config) when is_list(Config) ->
+ wait_for_memory_deallocations(),
+ Bef = memory_binary(),
+ io:format("Binary data (bytes) before test: ~p\n", [Bef]),
+
+ %% Compile the the literals module.
+ Data = ?config(data_dir, Config),
+ File = filename:join(Data, "literals"),
+ {ok,literals,Code} = compile:file(File, [report,binary]),
+
+ %% Load the code and make sure that the binary is a refc binary.
+ {module,literals} = erlang:load_module(literals, Code),
+ Bin = literals:binary(),
+ Sz = byte_size(Bin),
+ Check = erlang:md5(Bin),
+ io:format("Size of literal refc binary: ~p\n", [Sz]),
+ {refc_binary,Sz,_,_} = erts_debug:get_internal_state({binary_info,Bin}),
+ true = erlang:delete_module(literals),
+ false = erlang:check_process_code(self(), literals),
+ true = erlang:purge_module(literals),
+
+ %% Now try to provoke a memory leak.
+ provoke_mem_leak(10, Code, Check),
+
+ %% Calculate the change in allocated binary data.
+ erlang:garbage_collect(),
+ wait_for_memory_deallocations(),
+ Aft = memory_binary(),
+ io:format("Binary data (bytes) after test: ~p", [Aft]),
+ Diff = Aft - Bef,
+ if
+ Diff < 0 ->
+ io:format("~p less bytes", [abs(Diff)]);
+ Diff > 0 ->
+ io:format("~p more bytes", [Diff]);
+ true ->
+ ok
+ end,
+
+ %% Test for leaks. We must accept some natural variations in
+ %% the size of allocated binaries.
+ if
+ Diff > 64*1024 ->
+ ?t:fail(binary_leak);
+ true ->
+ ok
+ end.
+
+memory_binary() ->
+ try
+ erlang:memory(binary)
+ catch
+ error:notsup ->
+ 0
+ end.
+
+provoke_mem_leak(0, _, _) -> ok;
+provoke_mem_leak(N, Code, Check) ->
+ {module,literals} = erlang:load_module(literals, Code),
+
+ %% Create several processes with references to the literal binary.
+ Self = self(),
+ Pids = [spawn_link(fun() ->
+ create_binaries(Self, NumRefs, Check)
+ end) || NumRefs <- lists:seq(1, 10)],
+ [receive {started,Pid} -> ok end || Pid <- Pids],
+
+ %% Make the code old and remove references to the constant pool
+ %% in all processes.
+ true = erlang:delete_module(literals),
+ Ms = [spawn_monitor(fun() ->
+ false = erlang:check_process_code(Pid, literals)
+ end) || Pid <- Pids],
+ [receive
+ {'DOWN',R,process,P,normal} ->
+ ok
+ end || {P,R} <- Ms],
+
+ %% Purge the code.
+ true = erlang:purge_module(literals),
+
+ %% Tell the processes that the code has been purged.
+ [begin
+ monitor(process, Pid),
+ Pid ! purged
+ end || Pid <- Pids],
+
+ %% Wait for all processes to terminate.
+ [receive
+ {'DOWN',_,process,Pid,normal} ->
+ ok
+ end || Pid <- Pids],
+
+ %% We now expect that the binary has been deallocated.
+ provoke_mem_leak(N-1, Code, Check).
+
+create_binaries(Parent, NumRefs, Check) ->
+ Bin = literals:binary(),
+ Bins = lists:duplicate(NumRefs, Bin),
+ {bits,Bits} = literals:bits(),
+ Parent ! {started,self()},
+ receive
+ purged ->
+ %% The code has been purged. Now make sure that
+ %% the binaries haven't been corrupted.
+ Check = erlang:md5(Bin),
+ [Bin = B || B <- Bins],
+ <<42:13,Bin/binary>> = Bits,
+
+ %% Remove all references to the binaries
+ %% Doing it explicitly like this ensures that
+ %% the binaries are gone when the parent process
+ %% receives the 'DOWN' message.
+ erlang:garbage_collect()
+ end.
+
+wait_for_memory_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
+ end.
+
%% OTP-7559: c_p->cp could contain garbage and create a false dependency
%% to a module in a process. (Thanks to Richard Carlsson.)
false_dependency(Config) when is_list(Config) ->
@@ -555,6 +726,30 @@ coverage(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)),
ok.
+fun_confusion(Config) when is_list(Config) ->
+ Data = ?config(data_dir, Config),
+ Src = filename:join(Data, "fun_confusion"),
+ Mod = fun_confusion,
+
+ %% Load first version of module.
+ compile_load(Mod, Src, 1),
+ F1 = Mod:f(),
+ 1 = F1(),
+
+ %% Load second version of module.
+ compile_load(Mod, Src, 2),
+ F2 = Mod:f(),
+
+ %% F1 should refer to the old code, not the newly loaded code.
+ 1 = F1(),
+ 2 = F2(),
+ ok.
+
+compile_load(Mod, Src, Ver) ->
+ {ok,Mod,Code1} = compile:file(Src, [binary,{d,version,Ver}]),
+ {module,Mod} = code:load_binary(Mod, "fun_confusion.beam", Code1),
+ ok.
+
%% Utilities.
make_sub_binary(Bin) when is_binary(Bin) ->
diff --git a/erts/emulator/test/code_SUITE_data/fun_confusion.erl b/erts/emulator/test/code_SUITE_data/fun_confusion.erl
new file mode 100644
index 0000000000..16000861df
--- /dev/null
+++ b/erts/emulator/test/code_SUITE_data/fun_confusion.erl
@@ -0,0 +1,31 @@
+%%
+%% %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(fun_confusion).
+
+-export([f/0]).
+
+f() ->
+ fun() -> version() end.
+
+version() ->
+ %% Changing the value returned here should change
+ %% the identity of the fun in f/0.
+ ?version.
+
diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl
index 9f99b1a780..658427095e 100644
--- a/erts/emulator/test/code_SUITE_data/literals.erl
+++ b/erts/emulator/test/code_SUITE_data/literals.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
@@ -18,7 +18,7 @@
%%
-module(literals).
--export([a/0,b/0,huge_bignum/0]).
+-export([a/0,b/0,huge_bignum/0,binary/0,unused_binaries/0,bits/0]).
a() ->
{a,42.0,[7,38877938333399637266518333334747]}.
@@ -81,3 +81,22 @@ b() ->
huge_bignum() ->
36#9987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987779JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR073737676679877.
+
+-define(TIMES_FOUR(X), X,X,X,X).
+-define(BYTES_256, 0:256,1:256,2:256,3:256, 4:256,5:256,6:256,7:256).
+-define(KB_1, ?TIMES_FOUR(?BYTES_256)).
+-define(KB_4, ?TIMES_FOUR(?KB_1)).
+-define(KB_16, ?TIMES_FOUR(?KB_4)).
+-define(KB_64, ?TIMES_FOUR(?KB_16)).
+-define(KB_128, ?TIMES_FOUR(?KB_64)).
+-define(MB_1, ?TIMES_FOUR(?KB_128)).
+
+binary() ->
+ %% Too big to be a heap binary.
+ <<?MB_1>>.
+
+unused_binaries() ->
+ {<<?KB_128>>,<<?BYTES_256>>}.
+
+bits() ->
+ {bits,<<42:13,?MB_1>>}.
diff --git a/erts/emulator/test/code_SUITE_data/versions.erl b/erts/emulator/test/code_SUITE_data/versions.erl
new file mode 100644
index 0000000000..7a6fd8847d
--- /dev/null
+++ b/erts/emulator/test/code_SUITE_data/versions.erl
@@ -0,0 +1,33 @@
+%%
+%% %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(versions).
+-export([loop/0,version/0]).
+
+loop() ->
+ receive
+ {Pid,version} ->
+ Pid ! {self(),version,version()},
+ loop();
+ done ->
+ ok
+ end.
+
+version() ->
+ ?VERSION.
diff --git a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c
index e0d5067743..86f2abf1b1 100644
--- a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c
+++ b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c
@@ -7,7 +7,7 @@
static ErlDrvPort erlang_port;
static ErlDrvData dummy_start(ErlDrvPort, char*);
-static void dummy_read(ErlDrvData port, char *buf, int count);
+static void dummy_read(ErlDrvData port, char *buf, ErlDrvSizeT count);
static void dummy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int);
static ErlDrvEntry dummy_driver_entry = {
@@ -18,6 +18,21 @@ static ErlDrvEntry dummy_driver_entry = {
NULL,
NULL,
"dummy_drv",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -37,7 +52,7 @@ static ErlDrvData dummy_start(ErlDrvPort port,char *buf)
return (ErlDrvData)port;
}
-static void dummy_read(ErlDrvData port, char *buf, int count)
+static void dummy_read(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
driver_output(erlang_port, buf, count);
}
diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv.c b/erts/emulator/test/ddll_SUITE_data/echo_drv.c
index edf78a979d..2b3510c641 100644
--- a/erts/emulator/test/ddll_SUITE_data/echo_drv.c
+++ b/erts/emulator/test/ddll_SUITE_data/echo_drv.c
@@ -3,9 +3,10 @@
static ErlDrvPort erlang_port;
static ErlDrvData echo_start(ErlDrvPort, char *);
-static void from_erlang(ErlDrvData, char*, int);
-static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags);
+static void from_erlang(ErlDrvData, char*, ErlDrvSizeT);
+static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags);
static ErlDrvEntry echo_driver_entry = {
NULL, /* Init */
echo_start,
@@ -21,7 +22,15 @@ static ErlDrvEntry echo_driver_entry = {
NULL,
NULL,
NULL,
- echo_call
+ echo_call,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
};
DRIVER_INIT(echo_drv)
@@ -36,14 +45,15 @@ echo_start(ErlDrvPort port, char *buf)
}
static void
-from_erlang(ErlDrvData data, char *buf, int count)
+from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count)
{
driver_output((ErlDrvPort) data, buf, count);
}
-static int
-echo_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags)
+static ErlDrvSSizeT
+echo_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen,
+ unsigned *ret_flags)
{
*rbuf = buf;
*ret_flags |= DRIVER_CALL_KEEP_BUFFER;
diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c
index 3b2a44d907..26aa03a012 100644
--- a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c
+++ b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c
@@ -3,9 +3,10 @@
static ErlDrvPort erlang_port;
static ErlDrvData echo_start(ErlDrvPort, char *);
-static void from_erlang(ErlDrvData, char*, int);
-static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags);
+static void from_erlang(ErlDrvData, char*, ErlDrvSizeT);
+static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags);
static int echo_failing_init(void);
static ErlDrvEntry echo_driver_entry = {
@@ -23,7 +24,15 @@ static ErlDrvEntry echo_driver_entry = {
NULL,
NULL,
NULL,
- echo_call
+ echo_call,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
};
DRIVER_INIT(echo_drv)
@@ -43,14 +52,15 @@ echo_start(ErlDrvPort port, char *buf)
}
static void
-from_erlang(ErlDrvData data, char *buf, int count)
+from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count)
{
driver_output((ErlDrvPort) data, buf, count);
}
-static int
-echo_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags)
+static ErlDrvSSizeT
+echo_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen,
+ unsigned *ret_flags)
{
*rbuf = buf;
*ret_flags |= DRIVER_CALL_KEEP_BUFFER;
diff --git a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c
index b676ff5121..ad241b9c4f 100644
--- a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c
+++ b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c
@@ -3,7 +3,7 @@
static ErlDrvPort erlang_port;
static ErlDrvData easy_start(ErlDrvPort, char*);
-static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int);
+static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT);
static ErlDrvEntry easy_driver_entry =
{
@@ -14,6 +14,21 @@ static ErlDrvEntry easy_driver_entry =
NULL,
NULL,
"easy",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -34,7 +49,7 @@ static ErlDrvData easy_start(ErlDrvPort port, char *buf)
return (ErlDrvData)port;
}
-static void easy_read(ErlDrvData port, char *buf, int count)
+static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
driver_output(erlang_port, buf, count);
}
diff --git a/erts/emulator/test/ddll_SUITE_data/lock_drv.c b/erts/emulator/test/ddll_SUITE_data/lock_drv.c
index 2ec8fa3a29..d2605c5bfc 100644
--- a/erts/emulator/test/ddll_SUITE_data/lock_drv.c
+++ b/erts/emulator/test/ddll_SUITE_data/lock_drv.c
@@ -3,9 +3,10 @@
static ErlDrvPort erlang_port;
static ErlDrvData echo_start(ErlDrvPort, char *);
-static void from_erlang(ErlDrvData, char*, int);
-static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags);
+static void from_erlang(ErlDrvData, char*, ErlDrvSizeT);
+static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags);
static ErlDrvEntry echo_driver_entry = {
NULL, /* Init */
echo_start,
@@ -21,7 +22,15 @@ static ErlDrvEntry echo_driver_entry = {
NULL,
NULL,
NULL,
- echo_call
+ echo_call,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
};
DRIVER_INIT(echo_drv)
@@ -37,14 +46,15 @@ echo_start(ErlDrvPort port, char *buf)
}
static void
-from_erlang(ErlDrvData data, char *buf, int count)
+from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count)
{
driver_output((ErlDrvPort) data, buf, count);
}
-static int
-echo_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags)
+static ErlDrvSSizeT
+echo_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen,
+ unsigned *ret_flags)
{
ErlDrvPort port = (ErlDrvPort) drv_data;
driver_lock_driver(port);
diff --git a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c
index 931386a305..5abf5c4dc6 100644
--- a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c
+++ b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c
@@ -3,7 +3,7 @@
static ErlDrvPort erlang_port;
static ErlDrvData easy_start(ErlDrvPort, char*);
-static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int);
+static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT);
static ErlDrvEntry easy_driver_entry =
{
@@ -14,6 +14,21 @@ static ErlDrvEntry easy_driver_entry =
NULL,
NULL,
"easy",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -28,7 +43,7 @@ DRIVER_INIT(noinit_drv)
/*
* Provoke an error when loading the module.
*/
-int no_driver_init(void *handle)
+ErlDrvEntry* no_driver_init(void *handle)
#endif
{
erlang_port = (ErlDrvPort)-1;
@@ -46,7 +61,7 @@ static ErlDrvData easy_start(ErlDrvPort port,char *buf)
return (ErlDrvData)port;
}
-static void easy_read(ErlDrvData port, char *buf, int count)
+static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
driver_output(erlang_port, buf, count);
}
diff --git a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c
index 3a35820ee7..ac7efa30de 100644
--- a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c
+++ b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c
@@ -7,7 +7,7 @@
static ErlDrvPort erlang_port;
static ErlDrvData easy_start(ErlDrvPort, char*);
-static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int);
+static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT);
static ErlDrvEntry easy_driver_entry =
{
@@ -18,6 +18,21 @@ static ErlDrvEntry easy_driver_entry =
NULL,
NULL,
"easy",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -38,7 +53,7 @@ static ErlDrvData easy_start(ErlDrvPort port,char *buf)
return (ErlDrvData)port;
}
-static void easy_read(ErlDrvData port, char *buf, int count)
+static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
driver_output(erlang_port, buf, count);
}
diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl
index c0499554eb..4acbe8c6e0 100644
--- a/erts/emulator/test/decode_packet_SUITE.erl
+++ b/erts/emulator/test/decode_packet_SUITE.erl
@@ -26,12 +26,14 @@
-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,
- basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1]).
+ basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1,
+ otp_9389/1, otp_9389_line/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [basic, packet_size, neg, http, line, ssl, otp_8536].
+ [basic, packet_size, neg, http, line, ssl, otp_8536,
+ otp_9389, otp_9389_line].
groups() ->
[].
@@ -251,6 +253,28 @@ packet_size(Config) when is_list(Config) ->
?line {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>)
end,
lists:seq(-10,-1)),
+
+ %% Test OTP-9389, long HTTP header lines.
+ Opts = [{packet_size, 128}],
+ Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /",
+ string:chars($Y, 64), "\r\n\r\n"]),
+ <<Pkt1:50/binary, Pkt2/binary>> = Pkt,
+ ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} =
+ erlang:decode_packet(http, Pkt1, Opts),
+ ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest2} =
+ erlang:decode_packet(httph, Rest1, Opts),
+ ?line {more, undefined} = erlang:decode_packet(httph, Rest2, Opts),
+ ?line {ok, {http_header,_,"Link",_,_}, _} =
+ erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts),
+
+ Pkt3 = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /",
+ string:chars($Y, 129), "\r\n\r\n"]),
+ ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest3} =
+ erlang:decode_packet(http, Pkt3, Opts),
+ ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest4} =
+ erlang:decode_packet(httph, Rest3, Opts),
+ ?line {error, invalid} = erlang:decode_packet(httph, Rest4, Opts),
+
ok.
@@ -557,3 +581,35 @@ decode_pkt(Type,Bin,Opts) ->
%%io:format(" -> ~p\n",[Res]),
Res.
+otp_9389(doc) -> ["Verify line_length works correctly for HTTP headers"];
+otp_9389(suite) -> [];
+otp_9389(Config) when is_list(Config) ->
+ Opts = [{packet_size, 16384}, {line_length, 3000}],
+ Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /",
+ string:chars($X, 8192),
+ "\r\nContent-Length: 0\r\n\r\n"]),
+ <<Pkt1:5000/binary, Pkt2/binary>> = Pkt,
+ {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} =
+ erlang:decode_packet(http, Pkt1, Opts),
+ {ok, {http_header,_,'Host',_,"localhost"}, Rest2} =
+ erlang:decode_packet(httph, Rest1, Opts),
+ {more, undefined} = erlang:decode_packet(httph, Rest2, Opts),
+ {ok, {http_header,_,"Link",_,Link}, Rest3} =
+ erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts),
+ true = (length(Link) > 8000),
+ {ok, {http_header,_,'Content-Length',_,"0"}, <<"\r\n">>} =
+ erlang:decode_packet(httph, Rest3, Opts),
+ ok.
+
+otp_9389_line(doc) -> ["Verify packet_size works correctly for line mode"];
+otp_9389_line(suite) -> [];
+otp_9389_line(Config) when is_list(Config) ->
+ Opts = [{packet_size, 20}],
+ Line1 = <<"0123456789012345678\n">>,
+ Line2 = <<"0123456789\n">>,
+ Line3 = <<"01234567890123456789\n">>,
+ Pkt = list_to_binary([Line1, Line2, Line3]),
+ ?line {ok, Line1, Rest1} = erlang:decode_packet(line, Pkt, Opts),
+ ?line {ok, Line2, Rest2} = erlang:decode_packet(line, Rest1, Opts),
+ ?line {error, invalid} = erlang:decode_packet(line, Rest2, Opts),
+ ok.
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index 19281f6d58..2ddb4d76d9 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -18,7 +18,7 @@
%%
-module(distribution_SUITE).
--compile(r12).
+-compile(r13).
%% Tests distribution and the tcp driver.
@@ -37,7 +37,7 @@
dist_auto_connect_never/1, dist_auto_connect_once/1,
dist_parallel_send/1,
atom_roundtrip/1,
- atom_roundtrip_r12b/1,
+ atom_roundtrip_r13b/1,
contended_atom_cache_entry/1,
bad_dist_structure/1,
bad_dist_ext_receive/1,
@@ -62,7 +62,7 @@ all() ->
link_to_dead_new_node, applied_monitor_node,
ref_port_roundtrip, nil_roundtrip, stop_dist,
{group, trap_bif}, {group, dist_auto_connect},
- dist_parallel_send, atom_roundtrip, atom_roundtrip_r12b,
+ dist_parallel_send, atom_roundtrip, atom_roundtrip_r13b,
contended_atom_cache_entry, bad_dist_structure, {group, bad_dist_ext}].
groups() ->
@@ -1100,17 +1100,17 @@ atom_roundtrip(Config) when is_list(Config) ->
?line stop_node(Node),
?line ok.
-atom_roundtrip_r12b(Config) when is_list(Config) ->
- case ?t:is_release_available("r12b") of
+atom_roundtrip_r13b(Config) when is_list(Config) ->
+ case ?t:is_release_available("r13b") of
true ->
?line AtomData = atom_data(),
?line verify_atom_data(AtomData),
- ?line {ok, Node} = start_node(Config, [], "r12b"),
+ ?line {ok, Node} = start_node(Config, [], "r13b"),
?line do_atom_roundtrip(Node, AtomData),
?line stop_node(Node),
?line ok;
false ->
- ?line {skip,"No OTP R12B available"}
+ ?line {skip,"No OTP R13B available"}
end.
do_atom_roundtrip(Node, AtomData) ->
@@ -1890,7 +1890,7 @@ start_node(Name, Args, Rel) when is_atom(Name), is_list(Rel) ->
end,
test_server:start_node(Name, slave,
[{args,
- Args++" -setcookie "++Cookie++" -pa "++Pa}
+ Args++" -setcookie "++Cookie++" -pa \""++Pa++"\""}
| RelArg]);
start_node(Config, Args, Rel) when is_list(Config), is_list(Rel) ->
Name = list_to_atom((atom_to_list(?MODULE)
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index a77ea4f3be..643357263c 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -47,8 +47,8 @@
fd_change/1,
steal_control/1,
otp_6602/1,
- 'driver_system_info_ver1.0'/1,
- 'driver_system_info_ver1.1'/1,
+ driver_system_info_base_ver/1,
+ driver_system_info_prev_ver/1,
driver_system_info_current_ver/1,
driver_monitor/1,
@@ -75,7 +75,9 @@
smp_select/1,
driver_select_use/1,
thread_mseg_alloc_cache_clean/1,
- otp_9302/1]).
+ otp_9302/1,
+ thr_free_drv/1,
+ async_blast/1]).
-export([bin_prefix/2]).
@@ -133,8 +135,8 @@ all() ->
[outputv_errors, outputv_echo, queue_echo, {group, timer},
driver_unloaded, io_ready_exit, use_fallback_pollset,
bad_fd_in_pollset, driver_event, fd_change,
- steal_control, otp_6602, 'driver_system_info_ver1.0',
- 'driver_system_info_ver1.1',
+ steal_control, otp_6602, driver_system_info_base_ver,
+ driver_system_info_prev_ver,
driver_system_info_current_ver, driver_monitor,
{group, ioq_exit}, zero_extended_marker_garb_drv,
invalid_extended_marker_drv, larger_major_vsn_drv,
@@ -143,7 +145,9 @@ all() ->
otp_6879, caller, many_events, missing_callbacks,
smp_select, driver_select_use,
thread_mseg_alloc_cache_clean,
- otp_9302].
+ otp_9302,
+ thr_free_drv,
+ async_blast].
groups() ->
[{timer, [],
@@ -1079,19 +1083,19 @@ otp_6602(Config) when is_list(Config) ->
-define(EXPECTED_SYSTEM_INFO_NAMES, ?EXPECTED_SYSTEM_INFO_NAMES2).
-'driver_system_info_ver1.0'(doc) ->
+'driver_system_info_base_ver'(doc) ->
[];
-'driver_system_info_ver1.0'(suite) ->
+'driver_system_info_base_ver'(suite) ->
[];
-'driver_system_info_ver1.0'(Config) when is_list(Config) ->
- ?line driver_system_info_test(Config, sys_info_1_0_drv).
+'driver_system_info_base_ver'(Config) when is_list(Config) ->
+ ?line driver_system_info_test(Config, sys_info_base_drv).
-'driver_system_info_ver1.1'(doc) ->
+'driver_system_info_prev_ver'(doc) ->
[];
-'driver_system_info_ver1.1'(suite) ->
+'driver_system_info_prev_ver'(suite) ->
[];
-'driver_system_info_ver1.1'(Config) when is_list(Config) ->
- ?line driver_system_info_test(Config, sys_info_1_1_drv).
+'driver_system_info_prev_ver'(Config) when is_list(Config) ->
+ ?line driver_system_info_test(Config, sys_info_prev_drv).
driver_system_info_current_ver(doc) ->
[];
@@ -1804,13 +1808,13 @@ thread_mseg_alloc_cache_clean(Config) when is_list(Config) ->
?line {skipped, "driver_alloc() using too large single block threshold"};
{_, _, 0} ->
?line {skipped, "driver_alloc() using too low single block threshold"};
- {true, MsegAllocInfo, SBCT} ->
+ {true, _MsegAllocInfo, SBCT} ->
?line DrvName = 'thr_alloc_drv',
?line Path = ?config(data_dir, Config),
?line erl_ddll:start(),
?line ok = load_driver(Path, DrvName),
?line Port = open_port({spawn, DrvName}, []),
- ?line CCI = mseg_alloc_cci(MsegAllocInfo),
+ ?line CCI = 1000,
?line ?t:format("CCI = ~p~n", [CCI]),
?line CCC = mseg_alloc_ccc(),
?line ?t:format("CCC = ~p~n", [CCC]),
@@ -1831,7 +1835,7 @@ mseg_alloc_cci(MsegAllocInfo) ->
?line CCI.
mseg_alloc_ccc() ->
- mseg_alloc_ccc(erlang:system_info({allocator,mseg_alloc})).
+ mseg_alloc_ccc(mseg_inst_info(0)).
mseg_alloc_ccc(MsegAllocInfo) ->
?line {value,{memkind, MKL}} = lists:keysearch(memkind,1,MsegAllocInfo),
@@ -1841,7 +1845,7 @@ mseg_alloc_ccc(MsegAllocInfo) ->
?line GigaCCC*1000000000 + CCC.
mseg_alloc_cached_segments() ->
- mseg_alloc_cached_segments(erlang:system_info({allocator,mseg_alloc})).
+ mseg_alloc_cached_segments(mseg_inst_info(0)).
mseg_alloc_cached_segments(MsegAllocInfo) ->
MemName = case is_halfword_vm() of
@@ -1859,6 +1863,13 @@ mseg_alloc_cached_segments(MsegAllocInfo) ->
= lists:keysearch(cached_segments, 1, SL),
?line CS.
+mseg_inst_info(I) ->
+ {value, {instance, I, Value}}
+ = lists:keysearch(I,
+ 2,
+ erlang:system_info({allocator,mseg_alloc})),
+ Value.
+
is_halfword_vm() ->
case {erlang:system_info({wordsize, internal}),
erlang:system_info({wordsize, external})} of
@@ -1902,18 +1913,105 @@ otp_9302(Config) when is_list(Config) ->
?line port_command(Port, ""),
?line {msg, block} = get_port_msg(Port, infinity),
?line {msg, job} = get_port_msg(Port, infinity),
- ?line case erlang:system_info(thread_pool_size) of
- 0 ->
- {msg, cancel} = get_port_msg(Port, infinity);
- _ ->
- ok
- end,
- ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line C = case erlang:system_info(thread_pool_size) of
+ 0 ->
+ ?line {msg, cancel} = get_port_msg(Port, infinity),
+ ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line false;
+ _ ->
+ case get_port_msg(Port, infinity) of
+ {msg, cancel} -> %% Cancel always fail in Rel >= 15
+ ?line {msg, job} = get_port_msg(Port, infinity),
+ ?line false;
+ {msg, job} ->
+ ?line ok,
+ ?line true
+ end
+ end,
?line {msg, end_of_jobs} = get_port_msg(Port, infinity),
?line no_msg = get_port_msg(Port, 2000),
?line port_close(Port),
+ ?line case C of
+ true ->
+ ?line {comment, "Async job cancelled"};
+ false ->
+ ?line {comment, "Async job not cancelled"}
+ end.
+
+thr_free_drv(Config) when is_list(Config) ->
+ ?line Path = ?config(data_dir, Config),
+ ?line erl_ddll:start(),
+ ?line ok = load_driver(Path, thr_free_drv),
+ ?line MemBefore = driver_alloc_size(),
+% io:format("SID=~p", [erlang:system_info(scheduler_id)]),
+ ?line Port = open_port({spawn, thr_free_drv}, []),
+ ?line MemPeek = driver_alloc_size(),
+ ?line true = is_port(Port),
+ ?line ok = thr_free_drv_control(Port, 0),
+ ?line port_close(Port),
+ ?line MemAfter = driver_alloc_size(),
+ ?line io:format("MemPeek=~p~n", [MemPeek]),
+ ?line io:format("MemBefore=~p, MemAfter=~p~n", [MemBefore, MemAfter]),
+ ?line MemBefore = MemAfter,
+ ?line case MemPeek of
+ undefined -> ok;
+ _ ->
+ ?line true = MemPeek > MemBefore
+ end,
?line ok.
+thr_free_drv_control(Port, N) ->
+ case erlang:port_control(Port, 0, "") of
+ "done" ->
+ ok;
+ "more" ->
+ erlang:yield(),
+% io:format("N=~p, SID=~p", [N, erlang:system_info(scheduler_id)]),
+ thr_free_drv_control(Port, N+1)
+ end.
+
+async_blast(Config) when is_list(Config) ->
+ ?line Path = ?config(data_dir, Config),
+ ?line erl_ddll:start(),
+ ?line ok = load_driver(Path, async_blast_drv),
+ ?line SchedOnln = erlang:system_info(schedulers_online),
+ ?line MemBefore = driver_alloc_size(),
+ ?line Start = os:timestamp(),
+ ?line Blast = fun () ->
+ Port = open_port({spawn, async_blast_drv}, []),
+ true = is_port(Port),
+ port_command(Port, ""),
+ receive
+ {Port, done} ->
+ ok
+ end,
+ port_close(Port)
+ end,
+ ?line Ps = lists:map(fun (N) ->
+ spawn_opt(Blast,
+ [{scheduler,
+ (N rem SchedOnln)+ 1},
+ monitor])
+ end,
+ lists:seq(1, 100)),
+ ?line MemMid = driver_alloc_size(),
+ ?line lists:foreach(fun ({Pid, Mon}) ->
+ receive
+ {'DOWN',Mon,process,Pid,_} -> ok
+ end
+ end, Ps),
+ ?line End = os:timestamp(),
+ ?line MemAfter = driver_alloc_size(),
+ ?line io:format("MemBefore=~p, MemMid=~p, MemAfter=~p~n",
+ [MemBefore, MemMid, MemAfter]),
+ ?line AsyncBlastTime = timer:now_diff(End,Start)/1000000,
+ ?line io:format("AsyncBlastTime=~p~n", [AsyncBlastTime]),
+ ?line MemBefore = MemAfter,
+ ?line erlang:display({async_blast_time, AsyncBlastTime}),
+ ?line ok.
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Utilities
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2077,3 +2175,41 @@ start_node(Config) when is_list(Config) ->
stop_node(Node) ->
?t:stop_node(Node).
+
+wait_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_deallocations()
+ end.
+
+driver_alloc_size() ->
+ case erlang:system_info(smp_support) of
+ true ->
+ ok;
+ false ->
+ %% driver_alloc also used by elements in lock-free queues,
+ %% give these some time to be deallocated...
+ receive after 100 -> ok end
+ end,
+ wait_deallocations(),
+ case erlang:system_info({allocator_sizes, driver_alloc}) of
+ false ->
+ undefined;
+ 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, Sz0) ->
+ {value,{_,Sz,_,_}} = lists:keysearch(blocks_size, 1, L),
+ Sz0+Sz
+ end, 0, CS)
+ end.
diff --git a/erts/emulator/test/driver_SUITE_data/Makefile.src b/erts/emulator/test/driver_SUITE_data/Makefile.src
index 5b3ba1557e..9cc107cc66 100644
--- a/erts/emulator/test/driver_SUITE_data/Makefile.src
+++ b/erts/emulator/test/driver_SUITE_data/Makefile.src
@@ -12,10 +12,12 @@ MISC_DRVS = outputv_drv@dll@ \
many_events_drv@dll@ \
missing_callback_drv@dll@ \
thr_alloc_drv@dll@ \
- otp_9302_drv@dll@
+ otp_9302_drv@dll@ \
+ thr_free_drv@dll@ \
+ async_blast_drv@dll@
-SYS_INFO_DRVS = sys_info_1_0_drv@dll@ \
- sys_info_1_1_drv@dll@ \
+SYS_INFO_DRVS = sys_info_base_drv@dll@ \
+ sys_info_prev_drv@dll@ \
sys_info_curr_drv@dll@
VSN_MISMATCH_DRVS = zero_extended_marker_garb_drv@dll@ \
diff --git a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
new file mode 100644
index 0000000000..c2086c5860
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c
@@ -0,0 +1,124 @@
+/*
+ * %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_driver.h"
+
+#define NO_ASYNC_JOBS 10000
+
+static void stop(ErlDrvData drv_data);
+static ErlDrvData start(ErlDrvPort port,
+ char *command);
+static void output(ErlDrvData drv_data,
+ char *buf, ErlDrvSizeT len);
+static void ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data);
+
+static ErlDrvEntry async_blast_drv_entry = {
+ NULL /* init */,
+ start,
+ stop,
+ output,
+ NULL /* ready_input */,
+ NULL /* ready_output */,
+ "async_blast_drv",
+ NULL /* finish */,
+ NULL /* handle */,
+ NULL /* control */,
+ NULL /* timeout */,
+ NULL /* outputv */,
+ 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 /* handle_monitor */
+};
+
+typedef struct {
+ ErlDrvPort port;
+ ErlDrvTermData caller;
+ int counter;
+} async_blast_data_t;
+
+
+DRIVER_INIT(async_blast_drv)
+{
+ return &async_blast_drv_entry;
+}
+
+static void stop(ErlDrvData drv_data)
+{
+ driver_free((void *) drv_data);
+}
+
+static ErlDrvData start(ErlDrvPort port,
+ char *command)
+{
+ async_blast_data_t *abd;
+
+ abd = driver_alloc(sizeof(async_blast_data_t));
+ if (!abd)
+ return ERL_DRV_ERROR_GENERAL;
+
+ abd->port = port;
+ abd->counter = 0;
+ return (ErlDrvData) abd;
+}
+
+static void async_invoke(void *data)
+{
+
+}
+#include <stdio.h>
+
+static void ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data)
+{
+ async_blast_data_t *abd = (async_blast_data_t *) drv_data;
+ if (--abd->counter == 0) {
+ ErlDrvTermData spec[] = {
+ ERL_DRV_PORT, driver_mk_port(abd->port),
+ ERL_DRV_ATOM, driver_mk_atom("done"),
+ ERL_DRV_TUPLE, 2
+ };
+ driver_send_term(abd->port, abd->caller,
+ spec, sizeof(spec)/sizeof(spec[0]));
+ }
+}
+
+static void output(ErlDrvData drv_data,
+ char *buf, ErlDrvSizeT len)
+{
+ async_blast_data_t *abd = (async_blast_data_t *) drv_data;
+ if (abd->counter == 0) {
+ int i;
+ abd->caller = driver_caller(abd->port);
+ abd->counter = NO_ASYNC_JOBS;
+ for (i = 0; i < NO_ASYNC_JOBS; i++) {
+ if (0 > driver_async(abd->port, NULL, async_invoke, NULL, NULL)) {
+ driver_failure_atom(abd->port, "driver_async_failed");
+ break;
+ }
+ }
+ }
+}
diff --git a/erts/emulator/test/driver_SUITE_data/caller_drv.c b/erts/emulator/test/driver_SUITE_data/caller_drv.c
index a78d51966f..1ed20b0638 100644
--- a/erts/emulator/test/driver_SUITE_data/caller_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/caller_drv.c
@@ -23,17 +23,17 @@
static ErlDrvData start(ErlDrvPort port,
char *command);
static void output(ErlDrvData drv_data,
- char *buf, int len);
+ char *buf, ErlDrvSizeT len);
static void outputv(ErlDrvData drv_data,
ErlIOVec *ev);
-static int control(ErlDrvData drv_data,
- unsigned int command, char *buf,
- int len, char **rbuf, int rlen);
-static int call(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen,
- unsigned int *flags);
+static ErlDrvSSizeT control(ErlDrvData drv_data,
+ unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
+static ErlDrvSSizeT call(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
+ unsigned int *flags);
static ErlDrvEntry caller_drv_entry = {
NULL /* init */,
@@ -98,7 +98,7 @@ start(ErlDrvPort port, char *command)
}
static void
-output(ErlDrvData drv_data, char *buf, int len)
+output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
send_caller(drv_data, "output");
}
@@ -109,20 +109,20 @@ outputv(ErlDrvData drv_data, ErlIOVec *ev)
send_caller(drv_data, "outputv");
}
-static int
+static ErlDrvSSizeT
control(ErlDrvData drv_data,
unsigned int command, char *buf,
- int len, char **rbuf, int rlen)
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
{
send_caller(drv_data, "control");
return 0;
}
-static int
+static ErlDrvSSizeT
call(ErlDrvData drv_data,
unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
unsigned int *flags)
{
/* echo call */
diff --git a/erts/emulator/test/driver_SUITE_data/chkio_drv.c b/erts/emulator/test/driver_SUITE_data/chkio_drv.c
index bbdb09cfcb..40f1ad4fea 100644
--- a/erts/emulator/test/driver_SUITE_data/chkio_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/chkio_drv.c
@@ -141,8 +141,8 @@ static void chkio_drv_stop(ErlDrvData);
static void chkio_drv_ready_input(ErlDrvData, ErlDrvEvent);
static void chkio_drv_ready_output(ErlDrvData, ErlDrvEvent);
static void chkio_drv_ready_event(ErlDrvData, ErlDrvEvent, ErlDrvEventData);
-static int chkio_drv_control(ErlDrvData, unsigned int,
- char *, int, char **, int);
+static ErlDrvSSizeT chkio_drv_control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
static void chkio_drv_timeout(ErlDrvData);
static void chkio_drv_stop_select(ErlDrvEvent, void*);
@@ -188,7 +188,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp)
for (i = 0; i < CHKIO_FALLBACK_FDS; i++) {
if (cbdp->dev_null[i].fd >= 0) {
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->dev_null[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_null[i].fd,
DO_WRITE,
0) != 0) {
fprintf(stderr,
@@ -200,7 +200,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp)
}
if (cbdp->dev_zero[i].fd >= 0) {
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->dev_zero[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_zero[i].fd,
DO_READ,
0) != 0) {
fprintf(stderr,
@@ -212,7 +212,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp)
}
if (cbdp->pipe_in[i].fd >= 0) {
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->pipe_in[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_in[i].fd,
DO_READ,
0) != 0) {
fprintf(stderr,
@@ -224,7 +224,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp)
}
if (cbdp->pipe_out[i].fd >= 0) {
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->pipe_out[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_out[i].fd,
DO_WRITE,
0) != 0) {
fprintf(stderr,
@@ -249,11 +249,11 @@ stop_driver_event(ChkioDrvData *cddp)
cddp->test_data = NULL;
if (cdep->in_fd >= 0) {
- driver_event(cddp->port, (ErlDrvEvent) cdep->in_fd, NULL);
+ driver_event(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cdep->in_fd, NULL);
close(cdep->in_fd);
}
if (cdep->out_fd >= 0) {
- driver_event(cddp->port, (ErlDrvEvent) cdep->out_fd, NULL);
+ driver_event(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cdep->out_fd, NULL);
close(cdep->out_fd);
}
driver_free(cdep);
@@ -268,7 +268,7 @@ stop_fd_change(ChkioDrvData *cddp)
cddp->test_data = NULL;
driver_cancel_timer(cddp->port);
if (cfcp->fds[0] >= 0) {
- driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], DO_READ, 0);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cfcp->fds[0], DO_READ, 0);
close(cfcp->fds[0]);
close(cfcp->fds[1]);
}
@@ -282,8 +282,8 @@ stop_bad_fd_in_pollset(ChkioDrvData *cddp)
if (cddp->test_data) {
ChkioBadFdInPollset *bfipp = (ChkioBadFdInPollset *) cddp->test_data;
cddp->test_data = NULL;
- driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[0], DO_WRITE, 0);
- driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[1], DO_READ, 0);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) bfipp->fds[0], DO_WRITE, 0);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) bfipp->fds[1], DO_READ, 0);
driver_free((void *) bfipp);
}
}
@@ -296,21 +296,21 @@ stop_steal(ChkioDrvData *cddp)
cddp->test_data = NULL;
if (csp->driver_select_fds[0] >= 0)
driver_select(cddp->port,
- (ErlDrvEvent) csp->driver_select_fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[0],
DO_READ,
0);
if (csp->driver_select_fds[1] >= 0)
driver_select(cddp->port,
- (ErlDrvEvent) csp->driver_select_fds[1],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[1],
DO_WRITE,
0);
if (csp->driver_event_fds[0] >= 0)
driver_event(cddp->port,
- (ErlDrvEvent) csp->driver_event_fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[0],
NULL);
if (csp->driver_event_fds[1] >= 0)
driver_event(cddp->port,
- (ErlDrvEvent) csp->driver_event_fds[1],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[1],
NULL);
driver_free(csp);
}
@@ -353,7 +353,7 @@ static void free_smp_select(ChkioSmpSelect* pip, ErlDrvPort port)
abort();
}
case Selected:
- driver_select(port, (ErlDrvEvent)pip->read_fd, DO_READ, 0);
+ driver_select(port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 0);
/*fall through*/
case Opened:
close(pip->read_fd);
@@ -475,8 +475,8 @@ chkio_drv_stop(ErlDrvData drv_data) {
fprintf(stderr, "%s:%d: Failed to open /dev/null\n",
__FILE__, __LINE__);
}
- driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 1);
- driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 0);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fd, DO_WRITE, 1);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fd, DO_WRITE, 0);
close(fd);
@@ -491,7 +491,7 @@ chkio_drv_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
{
#ifdef UNIX
ChkioDrvData *cddp = (ChkioDrvData *) drv_data;
- int fd = (int) event;
+ int fd = (int) (ErlDrvSInt) event;
switch (cddp->test) {
case CHKIO_USE_FALLBACK_POLLSET: {
@@ -533,7 +533,7 @@ chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event)
{
#ifdef UNIX
ChkioDrvData *cddp = (ChkioDrvData *) drv_data;
- int fd = (int) event;
+ int fd = (int) (ErlDrvSInt) event;
switch (cddp->test) {
case CHKIO_USE_FALLBACK_POLLSET: {
@@ -630,7 +630,7 @@ chkio_drv_ready_event(ErlDrvData drv_data,
case CHKIO_DRIVER_EVENT: {
#ifdef HAVE_POLL_H
ChkioDriverEvent *cdep = cddp->test_data;
- int fd = (int) event;
+ int fd = (int) (ErlDrvSInt) event;
if (fd == cdep->in_fd) {
if (event_data->events == POLLIN
&& event_data->revents == POLLIN) {
@@ -679,7 +679,7 @@ chkio_drv_timeout(ErlDrvData drv_data)
int in_fd = cfcp->fds[0];
int out_fd = cfcp->fds[1];
if (in_fd >= 0) {
- if (driver_select(cddp->port, (ErlDrvEvent) in_fd, DO_READ, 0) < 0)
+ if (driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) in_fd, DO_READ, 0) < 0)
driver_failure_atom(cddp->port, "deselect_failed");
(void) write(out_fd, (void *) "!", 1);
close(out_fd);
@@ -689,7 +689,7 @@ chkio_drv_timeout(ErlDrvData drv_data)
driver_failure_posix(cddp->port, errno);
}
else {
- if (driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0],
+ if (driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cfcp->fds[0],
DO_READ, 1) < 0)
driver_failure_atom(cddp->port, "select_failed");
if (cfcp->fds[0] == in_fd)
@@ -709,14 +709,14 @@ chkio_drv_timeout(ErlDrvData drv_data)
#endif /* UNIX */
}
-static int
+static ErlDrvSSizeT
chkio_drv_control(ErlDrvData drv_data,
unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
char *res_str;
- int res_len = -1;
+ ErlDrvSSizeT res_len = -1;
#ifndef UNIX
#ifdef __WIN32__
res_str = "skip: windows_different";
@@ -854,7 +854,7 @@ chkio_drv_control(ErlDrvData drv_data,
int fds[2];
cbdp->dev_null[i].fd = open("/dev/null", O_WRONLY);
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->dev_null[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_null[i].fd,
DO_WRITE,
1) != 0) {
driver_failure_posix(cddp->port, errno);
@@ -862,7 +862,7 @@ chkio_drv_control(ErlDrvData drv_data,
}
cbdp->dev_zero[i].fd = open("/dev/zero", O_RDONLY);
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->dev_zero[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_zero[i].fd,
DO_READ,
1) != 0) {
driver_failure_posix(cddp->port, errno);
@@ -873,7 +873,7 @@ chkio_drv_control(ErlDrvData drv_data,
cbdp->pipe_in[i].fd = fds[0];
cbdp->pipe_out[i].fd = fds[1];
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->pipe_in[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_in[i].fd,
DO_READ,
1) != 0) {
driver_failure_posix(cddp->port, EIO);
@@ -882,7 +882,7 @@ chkio_drv_control(ErlDrvData drv_data,
if (i % 2 == 0)
(void) write(cbdp->pipe_out[i].fd, "!", 1);
if (driver_select(cddp->port,
- (ErlDrvEvent) cbdp->pipe_out[i].fd,
+ (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_out[i].fd,
DO_WRITE,
1) != 0) {
driver_failure_posix(cddp->port, EIO);
@@ -928,8 +928,8 @@ chkio_drv_control(ErlDrvData drv_data,
bfipp->fds[0] = fds[9];
bfipp->fds[1] = fds[10];
cddp->test_data = (void *) bfipp;
- driver_select(cddp->port, (ErlDrvEvent) fds[9], DO_WRITE, 1);
- driver_select(cddp->port, (ErlDrvEvent) fds[10], DO_READ, 1);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fds[9], DO_WRITE, 1);
+ driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fds[10], DO_READ, 1);
}
}
res_str = "ok";
@@ -965,7 +965,7 @@ chkio_drv_control(ErlDrvData drv_data,
cdep->in_ok = 0;
res = driver_event(cddp->port,
- (ErlDrvEvent) in_fd,
+ (ErlDrvEvent) (ErlDrvSInt) in_fd,
&cdep->in_data);
if (res < 0) {
res_str = "skip: driver_event() not supported";
@@ -985,7 +985,7 @@ chkio_drv_control(ErlDrvData drv_data,
cdep->out_ok = 0;
res = driver_event(cddp->port,
- (ErlDrvEvent) out_fd,
+ (ErlDrvEvent) (ErlDrvSInt) out_fd,
&cdep->out_data);
if (res < 0) {
close(out_fd);
@@ -1062,7 +1062,7 @@ chkio_drv_control(ErlDrvData drv_data,
csp->event_data[0].events = POLLIN;
csp->event_data[0].revents = 0;
res = driver_event(cddp->port,
- (ErlDrvEvent) csp->driver_event_fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[0],
&csp->event_data[0]);
if (res < 0)
driver_failure_atom(cddp->port,
@@ -1071,7 +1071,7 @@ chkio_drv_control(ErlDrvData drv_data,
csp->event_data[1].events = POLLOUT;
csp->event_data[1].revents = 0;
res = driver_event(cddp->port,
- (ErlDrvEvent) csp->driver_event_fds[1],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[1],
&csp->event_data[1]);
if (res < 0)
driver_failure_atom(cddp->port,
@@ -1083,7 +1083,7 @@ chkio_drv_control(ErlDrvData drv_data,
/* Steal with driver_select() */
if (res >= 0) {
res = driver_select(cddp->port,
- (ErlDrvEvent) csp->driver_select_fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[0],
DO_READ,
1);
if (res < 0)
@@ -1092,7 +1092,7 @@ chkio_drv_control(ErlDrvData drv_data,
}
if (res >= 0) {
res = driver_select(cddp->port,
- (ErlDrvEvent) csp->driver_select_fds[1],
+ (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[1],
DO_WRITE,
1);
if (res < 0)
@@ -1159,14 +1159,14 @@ chkio_drv_control(ErlDrvData drv_data,
csap->driver_event_fds[1] = write_fds[1];
res = driver_select(cddp->port,
- (ErlDrvEvent) csap->driver_select_fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) csap->driver_select_fds[0],
DO_READ,
1);
if (res < 0)
driver_failure_atom(cddp->port, "driver_select_failed");
if (res >= 0) {
res = driver_select(cddp->port,
- (ErlDrvEvent) csap->driver_select_fds[1],
+ (ErlDrvEvent) (ErlDrvSInt) csap->driver_select_fds[1],
DO_WRITE,
1);
if (res < 0)
@@ -1177,7 +1177,7 @@ chkio_drv_control(ErlDrvData drv_data,
csap->event_data[0].events = POLLIN;
csap->event_data[0].revents = 0;
res = driver_event(cddp->port,
- (ErlDrvEvent) csap->driver_event_fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) csap->driver_event_fds[0],
&csap->event_data[0]);
if (res < 0) {
close(csap->driver_event_fds[0]);
@@ -1190,7 +1190,7 @@ chkio_drv_control(ErlDrvData drv_data,
csap->event_data[1].events = POLLOUT;
csap->event_data[1].revents = 0;
res = driver_event(cddp->port,
- (ErlDrvEvent) csap->driver_event_fds[1],
+ (ErlDrvEvent) (ErlDrvSInt) csap->driver_event_fds[1],
&csap->event_data[1]);
if (res < 0)
driver_failure_atom(cddp->port,
@@ -1285,7 +1285,7 @@ chkio_drv_control(ErlDrvData drv_data,
}
else {
TRACEF(("%T: Select on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd));
- if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 1)) {
+ if (driver_select(cddp->port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 1)) {
fprintf(stderr, "driver_select failed for fd=%d\n", pip->read_fd);
abort();
}
@@ -1314,7 +1314,7 @@ chkio_drv_control(ErlDrvData drv_data,
op >>= 1;
if (op & 1) {
TRACEF(("%T: Deselect on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd));
- if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 0)) {
+ if (driver_select(cddp->port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 0)) {
fprintf(stderr, "driver_(de)select failed for fd=%d\n", pip->read_fd);
abort();
}
diff --git a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c
index 6afa46b3a2..e6a3edcd74 100644
--- a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c
@@ -40,8 +40,9 @@ static void io_ready_exit_ready_input(ErlDrvData, ErlDrvEvent);
static void io_ready_exit_ready_output(ErlDrvData, ErlDrvEvent);
static void io_ready_exit_drv_output(ErlDrvData, char *, int);
static void io_ready_exit_drv_finish(void);
-static int io_ready_exit_drv_control(ErlDrvData, unsigned int,
- char *, int, char **, int);
+static ErlDrvSSizeT io_ready_exit_drv_control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT,
+ char **, ErlDrvSizeT);
static ErlDrvEntry io_ready_exit_drv_entry = {
NULL, /* init */
@@ -56,7 +57,17 @@ static ErlDrvEntry io_ready_exit_drv_entry = {
io_ready_exit_drv_control,
NULL, /* timeout */
NULL, /* outputv */
- NULL /* ready_async */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0, /* ERL_DRV_FLAGs */
+ NULL, /* handle2 */
+ NULL, /* process_exit */
+ NULL /* stop_select */
};
/* -------------------------------------------------------------------------
@@ -83,7 +94,7 @@ io_ready_exit_drv_stop(ErlDrvData drv_data) {
#ifdef UNIX
if (oeddp->fds[0] >= 0) {
driver_select(oeddp->port,
- (ErlDrvEvent) oeddp->fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0],
DO_READ|DO_WRITE,
0);
close(oeddp->fds[0]);
@@ -109,15 +120,15 @@ io_ready_exit_ready_input(ErlDrvData drv_data, ErlDrvEvent event)
driver_failure_atom(oeddp->port, "ready_input_driver_failure");
}
-static int
+static ErlDrvSSizeT
io_ready_exit_drv_control(ErlDrvData drv_data,
unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
char *abuf;
char *res_str;
- int res_len;
+ ErlDrvSSizeT res_len;
IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data;
#ifndef UNIX
res_str = "nyiftos";
@@ -127,9 +138,9 @@ io_ready_exit_drv_control(ErlDrvData drv_data,
}
else {
res_str = "ok";
- write(oeddp->fds[1], "!", 1);
+ (void) write(oeddp->fds[1], "!", 1);
driver_select(oeddp->port,
- (ErlDrvEvent) oeddp->fds[0],
+ (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0],
DO_READ|DO_WRITE,
1);
}
diff --git a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c
index e49de388b4..b2cc1e785a 100644
--- a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c
@@ -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
@@ -91,7 +91,8 @@ static ErlDrvData start(ErlDrvPort port, char *command);
static void stop(ErlDrvData drv_data);
static void ready_input(ErlDrvData drv_data, ErlDrvEvent event);
static void ready_output(ErlDrvData drv_data, ErlDrvEvent event);
-static int control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
static void timeout(ErlDrvData drv_data);
static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data);
static void flush(ErlDrvData drv_data);
@@ -155,10 +156,10 @@ start(ErlDrvPort port, char *command)
return (ErlDrvData) ddp;
}
-static int control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+static ErlDrvSSizeT control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data;
char *res_str = "nyiftos";
@@ -227,7 +228,7 @@ static int control(ErlDrvData drv_data,
res_str = "ok";
done: {
- int res_len = strlen(res_str);
+ ErlDrvSSizeT res_len = strlen(res_str);
if (res_len > rlen) {
char *abuf = driver_alloc(sizeof(char)*res_len);
if (!abuf)
diff --git a/erts/emulator/test/driver_SUITE_data/many_events_drv.c b/erts/emulator/test/driver_SUITE_data/many_events_drv.c
index 7417dbf7f8..a34432a8fe 100644
--- a/erts/emulator/test/driver_SUITE_data/many_events_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/many_events_drv.c
@@ -3,14 +3,17 @@
#endif
#include <stdio.h>
+#include <string.h>
#include "erl_driver.h"
static ErlDrvPort erlang_port;
static ErlDrvData many_events_start(ErlDrvPort, char *);
-static void from_erlang(ErlDrvData, char*, int);
+static void from_erlang(ErlDrvData, char*, ErlDrvSizeT);
static void from_port(ErlDrvData drv_data, ErlDrvEvent event);
-static int many_events_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags);
+static ErlDrvSSizeT many_events_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
+ unsigned *ret_flags);
static ErlDrvEntry many_events_driver_entry = {
NULL, /* Init */
many_events_start,
@@ -26,7 +29,15 @@ static ErlDrvEntry many_events_driver_entry = {
NULL,
NULL,
NULL,
- many_events_call
+ many_events_call,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
};
DRIVER_INIT(many_events_drv)
@@ -41,7 +52,7 @@ many_events_start(ErlDrvPort port, char *buf)
}
static void
-from_erlang(ErlDrvData data, char *buf, int count)
+from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count)
{
int i;
int num;
@@ -87,9 +98,10 @@ static void from_port(ErlDrvData data, ErlDrvEvent ev)
return;
}
-static int
-many_events_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags)
+static ErlDrvSSizeT
+many_events_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen,
+ unsigned *ret_flags)
{
*rbuf = buf;
*ret_flags |= DRIVER_CALL_KEEP_BUFFER;
diff --git a/erts/emulator/test/driver_SUITE_data/monitor_drv.c b/erts/emulator/test/driver_SUITE_data/monitor_drv.c
index 1da6a56a72..3da067fd09 100644
--- a/erts/emulator/test/driver_SUITE_data/monitor_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/monitor_drv.c
@@ -21,8 +21,9 @@
#include "erl_driver.h"
static ErlDrvData monitor_drv_start(ErlDrvPort, char *);
-static int monitor_drv_control(ErlDrvData, unsigned int,
- char *, int, char **, int);
+static void monitor_drv_stop(ErlDrvData data);
+static ErlDrvSSizeT monitor_drv_control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor);
#define OP_I_AM_IPID 1
@@ -50,7 +51,7 @@ typedef struct {
static ErlDrvEntry monitor_drv_entry = {
NULL /* init */,
monitor_drv_start,
- NULL /* stop */,
+ monitor_drv_stop,
NULL /* output */,
NULL /* ready_input */,
NULL /* ready_output */,
@@ -122,16 +123,16 @@ static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor)
return;
}
-static int
+static ErlDrvSSizeT
monitor_drv_control(ErlDrvData drv_data,
unsigned int command,
- char *ibuf, int ilen,
- char **rbuf, int rlen)
+ char *ibuf, ErlDrvSizeT ilen,
+ char **rbuf, ErlDrvSizeT rlen)
{
MyDrvData *data = (MyDrvData *) drv_data;
char *answer = NULL;
char buff[64];
- int alen;
+ ErlDrvSSizeT alen;
switch (command) {
case OP_I_AM_IPID:
diff --git a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c
index 8c0a9aadfd..ff44145ca7 100644
--- a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c
@@ -20,11 +20,11 @@
#include <string.h>
#include "erl_driver.h"
-static int call(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen,
- unsigned int *flags);
+static ErlDrvSSizeT call(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
+ unsigned int *flags);
static ErlDrvEntry otp_6879_drv_entry = {
NULL /* init */,
@@ -57,11 +57,11 @@ DRIVER_INIT(otp_6879_drv)
}
-static int call(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen,
- unsigned int *flags)
+static ErlDrvSSizeT call(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
+ unsigned int *flags)
{
/* echo call */
if (len > rlen)
diff --git a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
index beee1b735f..221fd0ce51 100644
--- a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
@@ -28,7 +28,7 @@ static void stop(ErlDrvData drv_data);
static ErlDrvData start(ErlDrvPort port,
char *command);
static void output(ErlDrvData drv_data,
- char *buf, int len);
+ char *buf, ErlDrvSizeT len);
static void ready_async(ErlDrvData drv_data,
ErlDrvThreadData thread_data);
@@ -196,13 +196,13 @@ static void ready_async(ErlDrvData drv_data,
}
static void output(ErlDrvData drv_data,
- char *buf, int len)
+ char *buf, ErlDrvSizeT len)
{
Otp9302Data *data = (Otp9302Data *) drv_data;
ErlDrvTermData td_port = driver_mk_port(data->port);
ErlDrvTermData td_receiver = driver_caller(data->port);
ErlDrvTermData td_job = driver_mk_atom("job");
- unsigned int key = (unsigned int) data->port;
+ unsigned int key = (unsigned int) (ErlDrvSInt) data->port;
long id[5];
Otp9302AsyncData *ad[5];
int i;
diff --git a/erts/emulator/test/driver_SUITE_data/outputv_drv.c b/erts/emulator/test/driver_SUITE_data/outputv_drv.c
index 87f66ae413..3e3d4a3a03 100644
--- a/erts/emulator/test/driver_SUITE_data/outputv_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/outputv_drv.c
@@ -3,7 +3,9 @@
static ErlDrvPort erlang_port;
static ErlDrvData outputv_start(ErlDrvPort, char*);
-static void outputv_stop(ErlDrvData), outputv_read(ErlDrvData, char*, int), outputv(ErlDrvData, ErlIOVec*);
+static void outputv_stop(ErlDrvData),
+ outputv_read(ErlDrvData, char*, ErlDrvSizeT),
+ outputv(ErlDrvData, ErlIOVec*);
static ErlDrvEntry outputv_driver_entry =
{
@@ -19,6 +21,16 @@ static ErlDrvEntry outputv_driver_entry =
NULL,
NULL,
outputv,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -38,7 +50,7 @@ static ErlDrvData outputv_start(ErlDrvPort port, char *buf)
return (ErlDrvData)port;
}
-static void outputv_read(ErlDrvData port, char *buf, int count)
+static void outputv_read(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
erlang_port = (ErlDrvPort)-1;
}
diff --git a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c
index 3a5b5af13a..8e203f74ec 100644
--- a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c
@@ -66,7 +66,8 @@ typedef struct {
static ErlDrvData start(ErlDrvPort, char *);
static void stop(ErlDrvData);
-static int control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
static void ready_async(ErlDrvData, ErlDrvThreadData);
static void async_test(void *);
static void async_wait(void *);
@@ -121,10 +122,10 @@ static void stop(ErlDrvData drv_data)
driver_free(drv_data);
}
-static int control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+static ErlDrvSSizeT control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data;
unsigned int key = 0;
@@ -158,7 +159,7 @@ static int control(ErlDrvData drv_data,
}
done: {
- int res_len = strlen(res_str);
+ ErlDrvSSizeT res_len = strlen(res_str);
if (res_len > rlen) {
char *abuf = driver_alloc(sizeof(char)*res_len);
if (!abuf)
diff --git a/erts/emulator/test/driver_SUITE_data/queue_drv.c b/erts/emulator/test/driver_SUITE_data/queue_drv.c
index ded69f89f9..a02b57dc9a 100644
--- a/erts/emulator/test/driver_SUITE_data/queue_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/queue_drv.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <string.h>
#include "erl_driver.h"
#define put_int32(i, s) {((char*)(s))[0] = (char)((i) >> 24) & 0xff; \
@@ -33,9 +34,10 @@
static ErlDrvPort erlang_port;
static unsigned opcode; /* Opcode for next operation. */
static ErlDrvData queue_start(ErlDrvPort, char*);
-static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, int);
+static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, ErlDrvSizeT);
static void queue_outputv(ErlDrvData, ErlIOVec*);
-static int control(ErlDrvData, unsigned int, char*, int, char**, int);
+static ErlDrvSSizeT control(ErlDrvData, unsigned int,
+ char*, ErlDrvSizeT, char**, ErlDrvSizeT);
static ErlDrvBinary* read_head(ErlDrvPort, int bytes);
static ErlDrvEntry queue_driver_entry =
@@ -52,6 +54,16 @@ static ErlDrvEntry queue_driver_entry =
control,
NULL,
queue_outputv,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -73,7 +85,7 @@ static ErlDrvData queue_start(ErlDrvPort port, char *buf)
}
/* messages from Erlang */
-static void queue_read(ErlDrvData port, char *buf, int len)
+static void queue_read(ErlDrvData port, char *buf, ErlDrvSizeT len)
{
}
@@ -82,8 +94,9 @@ static void queue_stop(ErlDrvData port)
erlang_port = (ErlDrvPort) -1;
}
-static int
-control(ErlDrvData drv_data, unsigned command, char* buf, int len, char** rbuf, int rlen)
+static ErlDrvSSizeT
+control(ErlDrvData drv_data, unsigned command,
+ char* buf, ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rlen)
{
ErlDrvBinary* b;
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c
deleted file mode 100644
index 0504778086..0000000000
--- a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c
+++ /dev/null
@@ -1,72 +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$
- */
-
-/*
- * Author: Rickard Green
- *
- * Description: Driver that fakes driver version 1.0 and tests
- * driver_system_info().
- *
- */
-
-#include "sys_info_drv_impl.h"
-
-#define SYS_INFO_DRV_MAJOR_VSN 1
-#define SYS_INFO_DRV_MINOR_VSN 0
-#define SYS_INFO_DRV_NAME_STR "sys_info_1_0_drv"
-#define SYS_INFO_DRV_NAME sys_info_1_0_drv
-#define SYS_INFO_DRV_LAST_FIELD smp_support
-
-#define SYS_INFO_DRV_RES_FORMAT "ok: " \
- "drv_drv_vsn=%d.%d " \
- "emu_drv_vsn=%d.%d " \
- "erts_vsn=%s " \
- "otp_vsn=%s " \
- "thread=%s " \
- "smp=%s"
-
-
-static size_t
-sys_info_drv_max_res_len(ErlDrvSysInfo *sip)
-{
- size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1;
- slen += 2*20; /* drv_drv_vsn */
- slen += 2*20; /* emu_drv_vsn */
- slen += strlen(sip->erts_version) + 1;
- slen += strlen(sip->otp_release) + 1;
- slen += 5; /* threads */
- slen += 5; /* smp */
- return slen;
-}
-
-static size_t
-sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str)
-{
- return sprintf(str,
- SYS_INFO_DRV_RES_FORMAT,
- SYS_INFO_DRV_MAJOR_VSN,
- SYS_INFO_DRV_MINOR_VSN,
- sip->driver_major_version,
- sip->driver_minor_version,
- sip->erts_version,
- sip->otp_release,
- sip->thread_support ? "true" : "false",
- sip->smp_support ? "true" : "false");
-}
-
-#include "sys_info_drv_impl.c"
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c
deleted file mode 100644
index fa21828284..0000000000
--- a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c
+++ /dev/null
@@ -1,80 +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$
- */
-
-/*
- * Author: Rickard Green
- *
- * Description: Driver that fakes driver version 1.1 and tests
- * driver_system_info().
- *
- */
-
-#include "sys_info_drv_impl.h"
-
-#define SYS_INFO_DRV_MAJOR_VSN 1
-#define SYS_INFO_DRV_MINOR_VSN 1
-#define SYS_INFO_DRV_NAME_STR "sys_info_1_1_drv"
-#define SYS_INFO_DRV_NAME sys_info_1_1_drv
-#define SYS_INFO_DRV_LAST_FIELD scheduler_threads
-
-#define SYS_INFO_DRV_RES_FORMAT "ok: " \
- "drv_drv_vsn=%d.%d " \
- "emu_drv_vsn=%d.%d " \
- "erts_vsn=%s " \
- "otp_vsn=%s " \
- "thread=%s " \
- "smp=%s " \
- "async_thrs=%d " \
- "sched_thrs=%d"
-
-
-static size_t
-sys_info_drv_max_res_len(ErlDrvSysInfo *sip)
-{
- size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1;
- slen += 2*20; /* drv_drv_vsn */
- slen += 2*20; /* emu_drv_vsn */
- slen += strlen(sip->erts_version) + 1;
- slen += strlen(sip->otp_release) + 1;
- slen += 5; /* threads */
- slen += 5; /* smp */
- slen += 20; /* async_thrs */
- slen += 20; /* sched_thrs */
- return slen;
-}
-
-static size_t
-sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str)
-{
- return sprintf(str,
- SYS_INFO_DRV_RES_FORMAT,
- SYS_INFO_DRV_MAJOR_VSN,
- SYS_INFO_DRV_MINOR_VSN,
- sip->driver_major_version,
- sip->driver_minor_version,
- sip->erts_version,
- sip->otp_release,
- sip->thread_support ? "true" : "false",
- sip->smp_support ? "true" : "false",
- sip->async_threads,
- sip->scheduler_threads);
-}
-
-#include "sys_info_drv_impl.c"
-
-
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c
new file mode 100644
index 0000000000..c22a415c59
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c
@@ -0,0 +1,78 @@
+/* ``The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved via the world wide web at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+ * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+ * AB. All Rights Reserved.''
+ *
+ * $Id$
+ */
+
+/*
+ * Author: Rickard Green
+ *
+ * Description: Driver that fakes driver version 2.0 and tests
+ * driver_system_info().
+ *
+ */
+
+#include "sys_info_drv_impl.h"
+
+#define SYS_INFO_DRV_MAJOR_VSN 2
+#define SYS_INFO_DRV_MINOR_VSN 0
+#define SYS_INFO_DRV_NAME_STR "sys_info_base_drv"
+#define SYS_INFO_DRV_NAME sys_info_base_drv
+#define SYS_INFO_DRV_LAST_FIELD smp_support
+#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo)
+
+#define SYS_INFO_DRV_RES_FORMAT "ok: " \
+ "drv_drv_vsn=%d.%d " \
+ "emu_drv_vsn=%d.%d " \
+ "erts_vsn=%s " \
+ "otp_vsn=%s " \
+ "thread=%s " \
+ "smp=%s " \
+ "async_thrs=%d " \
+ "sched_thrs=%d"
+
+static size_t
+sys_info_drv_max_res_len(ErlDrvSysInfo *sip)
+{
+ size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1;
+ slen += 2*20; /* drv_drv_vsn */
+ slen += 2*20; /* emu_drv_vsn */
+ slen += strlen(sip->erts_version) + 1;
+ slen += strlen(sip->otp_release) + 1;
+ slen += 5; /* threads */
+ slen += 5; /* smp */
+ slen += 20; /* async_thrs */
+ slen += 20; /* sched_thrs */
+ return slen;
+}
+
+static size_t
+sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str)
+{
+ return sprintf(str,
+ SYS_INFO_DRV_RES_FORMAT,
+ SYS_INFO_DRV_MAJOR_VSN,
+ SYS_INFO_DRV_MINOR_VSN,
+ sip->driver_major_version,
+ sip->driver_minor_version,
+ sip->erts_version,
+ sip->otp_release,
+ sip->thread_support ? "true" : "false",
+ sip->smp_support ? "true" : "false",
+ sip->async_threads,
+ sip->scheduler_threads);
+}
+
+#include "sys_info_drv_impl.c"
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c
index 2d3203ae5d..c6c70a2075 100644
--- a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c
+++ b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c
@@ -46,7 +46,8 @@
#endif
static ErlDrvData start(ErlDrvPort, char *);
-static int control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT control(ErlDrvData, unsigned int,
+ char *, ErlDrvSizeT, char **, ErlDrvSizeT);
static ErlDrvEntry drv_entry = {
NULL /* init */,
@@ -84,13 +85,13 @@ start(ErlDrvPort port, char *command)
return (ErlDrvData) port;
}
-static int
+static ErlDrvSSizeT
control(ErlDrvData drv_data,
unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
- int res;
+ ErlDrvSSizeT res;
char *str;
size_t slen, slen2;
ErlDrvPort port = (ErlDrvPort) drv_data;
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c
new file mode 100644
index 0000000000..815d96cc97
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c
@@ -0,0 +1,78 @@
+/* ``The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved via the world wide web at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+ * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+ * AB. All Rights Reserved.''
+ *
+ * $Id$
+ */
+
+/*
+ * Author: Rickard Green
+ *
+ * Description: Driver that fakes driver version 2.0 and tests
+ * driver_system_info().
+ *
+ */
+
+#include "sys_info_drv_impl.h"
+
+#define SYS_INFO_DRV_MAJOR_VSN 2
+#define SYS_INFO_DRV_MINOR_VSN 0
+#define SYS_INFO_DRV_NAME_STR "sys_info_prev_drv"
+#define SYS_INFO_DRV_NAME sys_info_prev_drv
+#define SYS_INFO_DRV_LAST_FIELD scheduler_threads
+#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo)
+
+#define SYS_INFO_DRV_RES_FORMAT "ok: " \
+ "drv_drv_vsn=%d.%d " \
+ "emu_drv_vsn=%d.%d " \
+ "erts_vsn=%s " \
+ "otp_vsn=%s " \
+ "thread=%s " \
+ "smp=%s " \
+ "async_thrs=%d " \
+ "sched_thrs=%d"
+
+static size_t
+sys_info_drv_max_res_len(ErlDrvSysInfo *sip)
+{
+ size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1;
+ slen += 2*20; /* drv_drv_vsn */
+ slen += 2*20; /* emu_drv_vsn */
+ slen += strlen(sip->erts_version) + 1;
+ slen += strlen(sip->otp_release) + 1;
+ slen += 5; /* threads */
+ slen += 5; /* smp */
+ slen += 20; /* async_thrs */
+ slen += 20; /* sched_thrs */
+ return slen;
+}
+
+static size_t
+sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str)
+{
+ return sprintf(str,
+ SYS_INFO_DRV_RES_FORMAT,
+ SYS_INFO_DRV_MAJOR_VSN,
+ SYS_INFO_DRV_MINOR_VSN,
+ sip->driver_major_version,
+ sip->driver_minor_version,
+ sip->erts_version,
+ sip->otp_release,
+ sip->thread_support ? "true" : "false",
+ sip->smp_support ? "true" : "false",
+ sip->async_threads,
+ sip->scheduler_threads);
+}
+
+#include "sys_info_drv_impl.c"
diff --git a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c
index c7edbba7f6..95a6ae9bdf 100644
--- a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c
@@ -21,14 +21,8 @@
#include "erl_driver.h"
ErlDrvData start(ErlDrvPort port, char *command);
-int control(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen);
-
-static int call(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen,
- unsigned int *flags);
+ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
static ErlDrvEntry thr_alloc_drv_entry = {
NULL /* init */,
@@ -76,12 +70,12 @@ ErlDrvData start(ErlDrvPort port, char *command)
return (ErlDrvData) port;
}
-int control(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen)
+ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
{
ErlDrvPort port = (ErlDrvPort) drv_data;
char *result = "failure";
- int result_len;
+ ErlDrvSSizeT result_len;
if (len <= 20) {
int res;
ErlDrvTid tid;
diff --git a/erts/emulator/test/driver_SUITE_data/thr_free_drv.c b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c
new file mode 100644
index 0000000000..439fe6a184
--- /dev/null
+++ b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c
@@ -0,0 +1,241 @@
+/*
+ * %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 <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "erl_driver.h"
+
+#define BLOCKS_PER_THREAD 100000
+#define NO_THREADS 10
+#define BLOCKS_PER_CTRL 1000
+
+typedef struct {
+ ErlDrvMutex *mtx;
+ ErlDrvCond *cnd;
+ int b;
+ int *go;
+ int *skip;
+ void *blocks[BLOCKS_PER_THREAD];
+} test_thread_data;
+
+typedef struct {
+ ErlDrvPort port;
+ int b;
+ int go;
+ int skip;
+ test_thread_data ttd[NO_THREADS+1];
+ ErlDrvTid tids[NO_THREADS+1];
+} test_data;
+
+static ErlDrvData start(ErlDrvPort port, char *command);
+static void stop(ErlDrvData data);
+static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen);
+
+static ErlDrvEntry thr_free_drv_entry = {
+ NULL /* init */,
+ start,
+ stop,
+ NULL /* output */,
+ NULL /* ready_input */,
+ NULL /* ready_output */,
+ "thr_free_drv",
+ NULL /* finish */,
+ NULL /* handle */,
+ control,
+ NULL /* timeout */,
+ NULL /* outputv */,
+ 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 /* handle_monitor */
+};
+
+DRIVER_INIT(thr_free_drv)
+{
+ return &thr_free_drv_entry;
+}
+
+void *
+test_thread(void *vttd)
+{
+ test_thread_data *ttd = (test_thread_data *) vttd;
+ int i, skip;
+
+ erl_drv_mutex_lock(ttd->mtx);
+
+ while (!*ttd->go)
+ erl_drv_cond_wait(ttd->cnd, ttd->mtx);
+ skip = *ttd->skip;
+ erl_drv_mutex_unlock(ttd->mtx);
+
+ if (!skip) {
+ for (i = 0; i < BLOCKS_PER_THREAD; i++)
+ driver_free(ttd->blocks[i]);
+ }
+ return NULL;
+}
+
+ErlDrvData start(ErlDrvPort port, char *command)
+{
+ int join = 0, t, b, res;
+ test_thread_data *ttd;
+ test_data *td = driver_alloc(sizeof(test_data));
+ if (!td)
+ return ERL_DRV_ERROR_GENERAL;
+ ttd = td->ttd;
+ for (b = 0; b < BLOCKS_PER_THREAD; b++)
+ for (t = 0; t <= NO_THREADS; t++)
+ ttd[t].blocks[b] = NULL;
+ ttd[0].mtx = NULL;
+ ttd[0].cnd = NULL;
+
+ for (b = 0; b < BLOCKS_PER_THREAD; b++) {
+ for (t = 0; t <= NO_THREADS; t++) {
+ ttd[t].blocks[b] = driver_alloc(1);
+ if (ttd[t].blocks[b] == NULL)
+ goto fail;
+ }
+ }
+
+ td->b = -1;
+ td->go = 0;
+ td->skip = 0;
+
+ ttd[0].mtx = erl_drv_mutex_create("test_mutex");
+ if (!ttd[0].mtx)
+ goto fail;
+ ttd[0].cnd = erl_drv_cond_create("test_cnd");
+ if (!ttd[0].cnd)
+ goto fail;
+ ttd[0].go = &td->go;
+ ttd[0].skip = &td->skip;
+
+ for (t = 1; t <= NO_THREADS; t++) {
+ ttd[t].mtx = ttd[0].mtx;
+ ttd[t].cnd = ttd[0].cnd;
+ ttd[t].go = ttd[0].go;
+ ttd[t].skip = ttd[0].skip;
+ res = erl_drv_thread_create("test_thread",
+ &td->tids[t],
+ test_thread,
+ &ttd[t],
+ NULL);
+ if (res != 0)
+ goto fail;
+ join = t;
+ }
+
+ td->port = port;
+
+ return (ErlDrvData) td;
+
+fail:
+
+ if (join) {
+ erl_drv_mutex_lock(ttd[0].mtx);
+ td->go = 1;
+ td->skip = 1;
+ erl_drv_cond_broadcast(ttd[0].cnd);
+ erl_drv_mutex_unlock(ttd[0].mtx);
+ for (t = 1; t <= join; t++)
+ erl_drv_thread_join(td->tids[t], NULL);
+ }
+
+ if (ttd[0].mtx)
+ erl_drv_mutex_destroy(ttd[0].mtx);
+ if (ttd[0].cnd)
+ erl_drv_cond_destroy(ttd[0].cnd);
+
+ for (b = 0; b < BLOCKS_PER_THREAD; b++) {
+ for (t = 0; t <= NO_THREADS; t++) {
+ if (ttd[t].blocks[b] != NULL)
+ driver_free(ttd[t].blocks[b]);
+ }
+ }
+ driver_free(td);
+ return ERL_DRV_ERROR_GENERAL;
+}
+
+static void stop(ErlDrvData drv_data)
+{
+ test_data *td = (test_data *) drv_data;
+ int t, b;
+ for (t = 1; t <= NO_THREADS; t++)
+ erl_drv_thread_join(td->tids[t], NULL);
+ for (b = 0; b < BLOCKS_PER_THREAD; b++) {
+ if (td->ttd[0].blocks[b])
+ driver_free(td->ttd[0].blocks[b]);
+ }
+ erl_drv_mutex_destroy(td->ttd[0].mtx);
+ erl_drv_cond_destroy(td->ttd[0].cnd);
+ driver_free(td);
+}
+
+static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
+{
+ test_data *td = (test_data *) drv_data;
+ char *result = "failure";
+ int i, b;
+ int res;
+ ErlDrvSSizeT result_len;
+
+ if (td->b == -1) {
+ erl_drv_mutex_lock(td->ttd[0].mtx);
+ td->go = 1;
+ erl_drv_cond_broadcast(td->ttd[0].cnd);
+ erl_drv_mutex_unlock(td->ttd[0].mtx);
+ td->b = 0;
+ }
+
+ for (i = 0, b = td->b; i < BLOCKS_PER_CTRL && b < BLOCKS_PER_THREAD; i++, b++) {
+ driver_free(td->ttd[0].blocks[b]);
+ td->ttd[0].blocks[b] = NULL;
+ }
+
+ td->b = b;
+ if (b >= BLOCKS_PER_THREAD)
+ result = "done";
+ else
+ result = "more";
+
+ result_len = strlen(result);
+ if (result_len <= rlen) {
+ memcpy(*rbuf, result, result_len);
+ return result_len;
+ }
+ else {
+ *rbuf = driver_alloc(result_len);
+ if (!*rbuf) {
+ driver_failure_posix(td->port, ENOMEM);
+ return 0;
+ }
+ else {
+ memcpy(*rbuf, result, result_len);
+ return result_len;
+ }
+ }
+}
diff --git a/erts/emulator/test/driver_SUITE_data/timer_drv.c b/erts/emulator/test/driver_SUITE_data/timer_drv.c
index b96a95dd4c..8c3f203a64 100644
--- a/erts/emulator/test/driver_SUITE_data/timer_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/timer_drv.c
@@ -22,7 +22,9 @@
static ErlDrvPort erlang_port;
static ErlDrvData timer_start(ErlDrvPort, char*);
-static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData);
+static void timer_stop(ErlDrvData);
+static void timer_read(ErlDrvData, char*, ErlDrvSizeT);
+static void timer(ErlDrvData);
static ErlDrvEntry timer_driver_entry =
{
@@ -38,6 +40,16 @@ static ErlDrvEntry timer_driver_entry =
NULL,
timer,
NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
NULL
};
@@ -57,8 +69,9 @@ static ErlDrvData timer_start(ErlDrvPort port, char *buf)
}
/* set the timer, this is monitored from erlang measuring the time */
-static void timer_read(ErlDrvData port, char *buf, int len)
+static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len)
{
+ ErlDrvPort port = (ErlDrvPort) p;
char reply[1];
if (buf[0] == START_TIMER) {
diff --git a/erts/emulator/test/emulator.spec b/erts/emulator/test/emulator.spec
index 1ea751cc3b..7a6dd83020 100644
--- a/erts/emulator/test/emulator.spec
+++ b/erts/emulator/test/emulator.spec
@@ -1 +1,2 @@
+{enable_builtin_hooks, false}.
{suites,"../emulator_test",all}.
diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c
index 1e98844838..b4542f3e36 100644
--- a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c
@@ -50,13 +50,33 @@ typedef struct {
ErlDrvData testcase_drv_start(ErlDrvPort port, char *command);
void testcase_drv_stop(ErlDrvData drv_data);
-void testcase_drv_run(ErlDrvData drv_data, char *buf, int len);
+void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
static ErlDrvEntry testcase_drv_entry = {
NULL,
testcase_drv_start,
testcase_drv_stop,
- testcase_drv_run
+ testcase_drv_run,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* handle */
+ NULL, /* control */
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+
};
@@ -92,7 +112,7 @@ testcase_drv_stop(ErlDrvData drv_data)
}
void
-testcase_drv_run(ErlDrvData drv_data, char *buf, int len)
+testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data;
ErlDrvTermData result_atom;
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 4dc2fbaae2..87778dd0c2 100644
--- a/erts/emulator/test/erts_debug_SUITE.erl
+++ b/erts/emulator/test/erts_debug_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,13 +23,13 @@
-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,
- flat_size/1,flat_size_big/1,df/1,
+ test_size/1,flat_size_big/1,df/1,
instructions/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [flat_size, flat_size_big, df, instructions].
+ [test_size, flat_size_big, df, instructions].
groups() ->
[].
@@ -55,16 +55,58 @@ end_per_testcase(_Func, Config) ->
Dog=?config(watchdog, Config),
?t:timetrap_cancel(Dog).
-flat_size(Config) when is_list(Config) ->
- 0 = erts_debug:flat_size([]),
- 0 = erts_debug:flat_size(42),
- 2 = erts_debug:flat_size([a|b]),
- 1 = erts_debug:flat_size({}),
- 2 = erts_debug:flat_size({[]}),
- 3 = erts_debug:flat_size({a,b}),
- 7 = erts_debug:flat_size({a,[b,c]}),
+test_size(Config) when is_list(Config) ->
+ ConsCell1 = id([a|b]),
+ ConsCell2 = id(ConsCell1),
+ ConsCellSz = 2,
+
+ 0 = do_test_size([]),
+ 0 = do_test_size(42),
+ ConsCellSz = do_test_size(ConsCell1),
+ 1 = do_test_size({}),
+ 2 = do_test_size({[]}),
+ 3 = do_test_size({a,b}),
+ 7 = do_test_size({a,[b,c]}),
+
+ %% Test internal consistency of sizes, but without testing
+ %% exact sizes.
+ Const = id(42),
+ AnotherConst = id(7),
+
+ %% Fun environment size = 0 (the smallest fun possible)
+ SimplestFun = fun() -> ok end,
+ FunSz0 = do_test_size(SimplestFun),
+
+ %% Fun environment size = 1
+ FunSz1 = do_test_size(fun() -> Const end),
+ FunSz1 = FunSz0 + 1,
+
+ %% Fun environment size = 2
+ FunSz2 = do_test_size(fun() -> Const+AnotherConst end),
+ FunSz2 = FunSz1 + 1,
+
+ FunSz1 = do_test_size(fun() -> ConsCell1 end) - do_test_size(ConsCell1),
+
+ %% Test shared data structures.
+ do_test_size([ConsCell1|ConsCell1],
+ 3*ConsCellSz,
+ 2*ConsCellSz),
+ do_test_size(fun() -> {ConsCell1,ConsCell2} end,
+ FunSz2 + 2*ConsCellSz,
+ FunSz2 + ConsCellSz),
+ do_test_size({SimplestFun,SimplestFun},
+ 2*FunSz0+do_test_size({a,b}),
+ FunSz0+do_test_size({a,b})),
ok.
+do_test_size(Term) ->
+ Sz = erts_debug:flat_size(Term),
+ Sz = erts_debug:size(Term).
+
+do_test_size(Term, FlatSz, Sz) ->
+ FlatSz = erts_debug:flat_size(Term),
+ Sz = erts_debug:size(Term).
+
flat_size_big(Config) when is_list(Config) ->
%% Build a term whose external size only fits in a big num (on 32-bit CPU).
flat_size_big_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF).
@@ -96,3 +138,6 @@ instructions(Config) when is_list(Config) ->
?line Is = erts_debug:instructions(),
?line _ = [list_to_atom(I) || I <- Is],
ok.
+
+id(I) ->
+ I.
diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl
index 736510339f..abe01bf5ec 100644
--- a/erts/emulator/test/float_SUITE.erl
+++ b/erts/emulator/test/float_SUITE.erl
@@ -25,8 +25,9 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
- bad_float_unpack/1]).
+ bad_float_unpack/1, write/1, cmp_zero/1, cmp_integer/1, cmp_bignum/1]).
-export([otp_7178/1]).
+-export([hidden_inf/1]).
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
@@ -41,10 +42,12 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[fpe, fp_drv, fp_drv_thread, otp_7178, denormalized,
- match, bad_float_unpack].
+ match, bad_float_unpack, write, {group, comparison}
+ ,hidden_inf
+ ].
groups() ->
- [].
+ [{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}].
init_per_suite(Config) ->
Config.
@@ -187,6 +190,106 @@ bad_float_unpack(Config) when is_list(Config) ->
bad_float_unpack_match(<<F:64/float>>) -> F;
bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
+%% Exposes endianness issues.
+
+write(Config) when is_list(Config) ->
+ "1.0" = io_lib:write(1.0).
+
+cmp_zero(_Config) ->
+ cmp(0.5e-323,0).
+
+cmp_integer(_Config) ->
+ Axis = (1 bsl 53)-2.0, %% The point where floating points become unprecise
+ span_cmp(Axis,2,200),
+ cmp(Axis*Axis,round(Axis)).
+
+cmp_bignum(_Config) ->
+ span_cmp((1 bsl 58) - 1.0),%% Smallest bignum float
+
+ %% Test when the big num goes from I to I+1 in size
+ [span_cmp((1 bsl (32*I)) - 1.0) || I <- lists:seq(2,30)],
+
+ %% Test bignum greater then largest float
+ cmp((1 bsl (64*16)) - 1, (1 bsl (64*15)) * 1.0),
+ %% Test when num is much larger then float
+ [cmp((1 bsl (32*I)) - 1, (1 bsl (32*(I-2))) * 1.0) || I <- lists:seq(3,30)],
+ %% Test when float is much larger than num
+ [cmp((1 bsl (64*15)) * 1.0, (1 bsl (32*(I)))) || I <- lists:seq(1,29)],
+
+ %% Test that all int == float works as they should
+ [true = 1 bsl N == (1 bsl N)*1.0 || N <- lists:seq(0, 1023)],
+ [true = (1 bsl N)*-1 == (1 bsl N)*-1.0 || N <- lists:seq(0, 1023)].
+
+span_cmp(Axis) ->
+ span_cmp(Axis, 25).
+span_cmp(Axis, Length) ->
+ span_cmp(Axis, round(Axis) bsr 52, Length).
+span_cmp(Axis, Incr, Length) ->
+ [span_cmp(Axis, Incr, Length, 1 bsl (1 bsl I)) || I <- lists:seq(0,6)].
+%% This function creates tests around number axis. Both <, > and == is tested
+%% for both negative and positive numbers.
+%%
+%% Axis: The number around which to do the tests eg. (1 bsl 58) - 1.0
+%% Incr: How much to increment the test numbers inbetween each test.
+%% Length: Length/2 is the number of Incr away from Axis to test on the
+%% negative and positive plane.
+%% Diff: How much the float and int should differ when comparing
+span_cmp(Axis, Incr, Length, Diff) ->
+ [begin
+ cmp(round(Axis*-1.0)+Diff+I*Incr,Axis*-1.0+I*Incr),
+ cmp(Axis*-1.0+I*Incr,round(Axis*-1.0)-Diff+I*Incr)
+ end || I <- lists:seq((Length div 2)*-1,(Length div 2))],
+ [begin
+ cmp(round(Axis)+Diff+I*Incr,Axis+I*Incr),
+ cmp(Axis+I*Incr,round(Axis)-Diff+I*Incr)
+ end || I <- lists:seq((Length div 2)*-1,(Length div 2))].
+
+cmp(Big,Small) when is_float(Big) ->
+ BigGtSmall = lists:flatten(
+ io_lib:format("~f > ~p",[Big,Small])),
+ BigLtSmall = lists:flatten(
+ io_lib:format("~f < ~p",[Big,Small])),
+ BigEqSmall = lists:flatten(
+ io_lib:format("~f == ~p",[Big,Small])),
+ SmallGtBig = lists:flatten(
+ io_lib:format("~p > ~f",[Small,Big])),
+ SmallLtBig = lists:flatten(
+ io_lib:format("~p < ~f",[Small,Big])),
+ SmallEqBig = lists:flatten(
+ io_lib:format("~p == ~f",[Small,Big])),
+ cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
+ SmallEqBig,BigEqSmall);
+cmp(Big,Small) when is_float(Small) ->
+ BigGtSmall = lists:flatten(
+ io_lib:format("~p > ~f",[Big,Small])),
+ BigLtSmall = lists:flatten(
+ io_lib:format("~p < ~f",[Big,Small])),
+ BigEqSmall = lists:flatten(
+ io_lib:format("~p == ~f",[Big,Small])),
+ SmallGtBig = lists:flatten(
+ io_lib:format("~f > ~p",[Small,Big])),
+ SmallLtBig = lists:flatten(
+ io_lib:format("~f < ~p",[Small,Big])),
+ SmallEqBig = lists:flatten(
+ io_lib:format("~f == ~p",[Small,Big])),
+ cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
+ SmallEqBig,BigEqSmall).
+
+cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
+ SmallEqBig,BigEqSmall) ->
+ {_,_,_,true} = {Big,Small,BigGtSmall,
+ Big > Small},
+ {_,_,_,false} = {Big,Small,BigLtSmall,
+ Big < Small},
+ {_,_,_,false} = {Big,Small,SmallGtBig,
+ Small > Big},
+ {_,_,_,true} = {Big,Small,SmallLtBig,
+ Small < Big},
+ {_,_,_,false} = {Big,Small,SmallEqBig,
+ Small == Big},
+ {_,_,_,false} = {Big,Small,BigEqSmall,
+ Big == Small}.
+
id(I) -> I.
start_node(Config) when is_list(Config) ->
@@ -205,3 +308,25 @@ start_node(Config) when is_list(Config) ->
stop_node(Node) ->
?t:stop_node(Node).
+
+
+%% Test that operations that might hide infinite intermediate results
+%% do not supress the badarith.
+hidden_inf(Config) when is_list(Config) ->
+ ZeroP = 0.0,
+ ZeroN = id(ZeroP) * (-1),
+ [hidden_inf_1(A, B, Z, 9.23e307)
+ || A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
+ B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
+ Z <- [ZeroP, ZeroN]],
+ ok.
+
+hidden_inf_1(A, B, Zero, Huge) ->
+ {'EXIT',{badarith,_}} = (catch (B / (A / Zero))),
+ {'EXIT',{badarith,_}} = (catch (B * (A / Zero))),
+ {'EXIT',{badarith,_}} = (catch (B / (Huge * Huge))),
+ {'EXIT',{badarith,_}} = (catch (B * (Huge * Huge))),
+ {'EXIT',{badarith,_}} = (catch (B / (Huge + Huge))),
+ {'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))),
+ {'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))),
+ {'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))).
diff --git a/erts/emulator/test/float_SUITE_data/fp_drv.c b/erts/emulator/test/float_SUITE_data/fp_drv.c
index eb453f6cd6..b80385c3f9 100644
--- a/erts/emulator/test/float_SUITE_data/fp_drv.c
+++ b/erts/emulator/test/float_SUITE_data/fp_drv.c
@@ -22,6 +22,7 @@
# define PRINTF(X)
#endif
+#include <string.h>
#include <math.h>
#ifdef __WIN32__
#include <float.h>
@@ -37,7 +38,8 @@ int _finite(double x);
#define ERTS_FP_CONTROL_TEST 0
#define ERTS_FP_THREAD_TEST 1
-static int control(ErlDrvData, unsigned int, char *, int, char **, int);
+static ErlDrvSSizeT control(ErlDrvData, unsigned int, char *,
+ ErlDrvSizeT, char **, ErlDrvSizeT);
static ErlDrvEntry fp_drv_entry = {
NULL /* init */,
@@ -97,10 +99,10 @@ do_test(void *unused)
return "ok";
}
-static int control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen)
+static ErlDrvSSizeT control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
{
char *res_str;
PRINTF(("control(%p, %d, ...) called\r\n", drv_data, command));
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index 559e540016..839ad6a4f4 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -539,12 +539,6 @@ bad_md5(Bad) ->
{'EXIT',{badarg,_}} = (catch erlang:md5(Bad)).
refc(Config) when is_list(Config) ->
- case erlang:system_info(heap_type) of
- private -> refc_1();
- hybrid -> {skip,"Hybrid heap"}
- end.
-
-refc_1() ->
?line F1 = fun_factory(2),
?line {refc,2} = erlang:fun_info(F1, refc),
?line F2 = fun_factory(42),
@@ -570,12 +564,6 @@ fun_factory(Const) ->
fun(X) -> X + Const end.
refc_ets(Config) when is_list(Config) ->
- case erlang:system_info(heap_type) of
- private -> refc_ets_1();
- hybrid -> {skip,"Hybrid heap"}
- end.
-
-refc_ets_1() ->
?line F = fun(X) -> X + 33 end,
?line {refc,2} = erlang:fun_info(F, refc),
@@ -622,12 +610,6 @@ refc_ets_bag(F1, Options) ->
ok.
refc_dist(Config) when is_list(Config) ->
- case erlang:system_info(heap_type) of
- private -> refc_dist_1();
- hybrid -> {skip,"Hybrid heap"}
- end.
-
-refc_dist_1() ->
?line {ok,Node} = start_node(fun_SUITE_refc_dist),
?line process_flag(trap_exit, true),
?line Pid = spawn_link(Node,
diff --git a/erts/emulator/test/fun_r12_SUITE.erl b/erts/emulator/test/fun_r12_SUITE.erl
deleted file mode 100644
index 3b1dfc9825..0000000000
--- a/erts/emulator/test/fun_r12_SUITE.erl
+++ /dev/null
@@ -1,97 +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(fun_r12_SUITE).
--compile(r12).
-
--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,dist_old_release/1]).
-
--define(default_timeout, ?t:minutes(1)).
--include_lib("test_server/include/test_server.hrl").
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [dist_old_release].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-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.
-
-dist_old_release(Config) when is_list(Config) ->
- case ?t:is_release_available("r12b") of
- true -> do_dist_old(Config);
- false -> {skip,"No R12B found"}
- end.
-
-do_dist_old(Config) when is_list(Config) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- Name = fun_dist_r12,
- ?line {ok,Node} = ?t:start_node(Name, peer,
- [{args,"-pa "++Pa},
- {erl,[{release,"r12b"}]}]),
-
- ?line Pid = spawn_link(Node,
- fun() ->
- receive
- Fun when is_function(Fun) ->
- R12BFun = fun(H) -> cons(H, [b,c]) end,
- Fun(Fun, R12BFun)
- end
- end),
- Self = self(),
- Fun = fun(F, R12BFun) ->
- {pid,Self} = erlang:fun_info(F, pid),
- {module,?MODULE} = erlang:fun_info(F, module),
- Self ! {ok,F,R12BFun}
- end,
- ?line Pid ! Fun,
- ?line receive
- {ok,Fun,R12BFun} ->
- ?line [a,b,c] = R12BFun(a);
- Other ->
- ?line ?t:fail({bad_message,Other})
- end,
- ok.
-
-cons(H, T) ->
- [H|T].
diff --git a/erts/emulator/test/fun_r13_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl
new file mode 100644
index 0000000000..76ddf9fec9
--- /dev/null
+++ b/erts/emulator/test/fun_r13_SUITE.erl
@@ -0,0 +1,97 @@
+%%
+%% %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(fun_r13_SUITE).
+-compile(r13).
+
+-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,dist_old_release/1]).
+
+-define(default_timeout, ?t:minutes(1)).
+-include_lib("test_server/include/test_server.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [dist_old_release].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+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.
+
+dist_old_release(Config) when is_list(Config) ->
+ case ?t:is_release_available("r12b") of
+ true -> do_dist_old(Config);
+ false -> {skip,"No R12B found"}
+ end.
+
+do_dist_old(Config) when is_list(Config) ->
+ ?line Pa = filename:dirname(code:which(?MODULE)),
+ Name = fun_dist_r12,
+ ?line {ok,Node} = ?t:start_node(Name, peer,
+ [{args,"-pa "++Pa},
+ {erl,[{release,"r12b"}]}]),
+
+ ?line Pid = spawn_link(Node,
+ fun() ->
+ receive
+ Fun when is_function(Fun) ->
+ R12BFun = fun(H) -> cons(H, [b,c]) end,
+ Fun(Fun, R12BFun)
+ end
+ end),
+ Self = self(),
+ Fun = fun(F, R12BFun) ->
+ {pid,Self} = erlang:fun_info(F, pid),
+ {module,?MODULE} = erlang:fun_info(F, module),
+ Self ! {ok,F,R12BFun}
+ end,
+ ?line Pid ! Fun,
+ ?line receive
+ {ok,Fun,R12BFun} ->
+ ?line [a,b,c] = R12BFun(a);
+ Other ->
+ ?line ?t:fail({bad_message,Other})
+ end,
+ ok.
+
+cons(H, T) ->
+ [H|T].
diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl
index 82a0aad189..68bc3434d4 100644
--- a/erts/emulator/test/hibernate_SUITE.erl
+++ b/erts/emulator/test/hibernate_SUITE.erl
@@ -67,10 +67,7 @@ end_per_testcase(_Func, Config) ->
basic(Config) when is_list(Config) ->
Ref = make_ref(),
Info = {self(),Ref},
- ExpectedHeapSz = case erlang:system_info(heap_type) of
- private -> erts_debug:size([Info]);
- hybrid -> erts_debug:size([a|b])
- end,
+ ExpectedHeapSz = erts_debug:size([Info]),
?line Child = spawn_link(fun() -> basic_hibernator(Info) end),
?line hibernate_wake_up(100, ExpectedHeapSz, Child),
?line Child ! please_quit_now,
@@ -166,10 +163,7 @@ whats_up_calc(A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc) ->
dynamic_call(Config) when is_list(Config) ->
Ref = make_ref(),
Info = {self(),Ref},
- ExpectedHeapSz = case erlang:system_info(heap_type) of
- private -> erts_debug:size([Info]);
- hybrid -> erts_debug:size([a|b])
- end,
+ ExpectedHeapSz = erts_debug:size([Info]),
?line Child = spawn_link(fun() -> ?MODULE:dynamic_call_hibernator(Info, hibernate) end),
?line hibernate_wake_up(100, ExpectedHeapSz, Child),
?line Child ! please_quit_now,
diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl
index e0a7878bd8..024c3456a8 100644
--- a/erts/emulator/test/mtx_SUITE.erl
+++ b/erts/emulator/test/mtx_SUITE.erl
@@ -62,16 +62,29 @@ init_per_suite(Config) when is_list(Config) ->
Config.
end_per_suite(Config) when is_list(Config) ->
+ catch erts_debug:set_internal_state(available_internal_state, false),
Config.
init_per_testcase(_Case, Config) ->
Dog = ?t:timetrap(?t:minutes(15)),
+ %% Wait for deallocations to complete since we measure
+ %% runtime in test cases.
+ wait_deallocations(),
[{watchdog, Dog}|Config].
end_per_testcase(_Func, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog).
+wait_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_deallocations()
+ end.
+
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
@@ -109,7 +122,7 @@ long_rwlock(Config) when is_list(Config) ->
%% A very short run time is expected, since
%% threads in the test mostly wait
?t:format("RunTime=~p~n", [RunTime]),
- ?line true = RunTime < 100,
+ ?line true = RunTime < 400,
?line RunTimeStr = "Run-time during test was "++integer_to_list(RunTime)++" ms.",
case LLRes of
ok ->
@@ -268,7 +281,7 @@ hammer_sched_rwlock_test(FreqRead, LockCheck, Blocking, WaitLocked, WaitUnlocked
_ ->
{_, RunTime} = statistics(runtime),
?t:format("RunTime=~p~n", [RunTime]),
- ?line true = RunTime < 500,
+ ?line true = RunTime < 700,
{comment,
"Run-time during test was "
++ integer_to_list(RunTime)
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index d95789fa6e..6bd7361612 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -35,7 +35,9 @@
resource_takeover/1,
threading/1, send/1, send2/1, send3/1, send_threaded/1, neg/1,
is_checks/1,
- get_length/1, make_atom/1, make_string/1, reverse_list_test/1]).
+ get_length/1, make_atom/1, make_string/1, reverse_list_test/1,
+ otp_9668/1
+ ]).
-export([many_args_100/100]).
@@ -60,7 +62,9 @@ all() ->
iolist_as_binary, resource, resource_binary,
resource_takeover, threading, send, send2, send3,
send_threaded, neg, is_checks, get_length, make_atom,
- make_string,reverse_list_test].
+ make_string,reverse_list_test,
+ otp_9668
+ ].
groups() ->
[].
@@ -855,7 +859,13 @@ resource_holder(Pid,Reply,List) ->
threading(doc) -> ["Test the threading API functions (reuse tests from driver API)"];
-threading(Config) when is_list(Config) ->
+threading(Config) when is_list(Config) ->
+ case erlang:system_info(threads) of
+ true -> threading_do(Config);
+ false -> {skipped,"No thread support"}
+ end.
+
+threading_do(Config) ->
?line Data = ?config(data_dir, Config),
?line File = filename:join(Data, "tester"),
?line {ok,tester,ModBin} = compile:file(File, [binary,return_errors]),
@@ -1165,7 +1175,28 @@ is_checks(Config) when is_list(Config) ->
?line ensure_lib_loaded(Config, 1),
?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
- {hejsan, "hejsan", [$h,"ejs",<<"an">>]}),
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 12),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -12),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551617),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551617),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 99.146),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -99.146),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551616.2e2),
+ ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ self(), hd(erlang:ports()), [], [1,9,9,8],
+ {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551616.2e2),
try
?line error = check_is_exception(),
?line throw(expected_badarg)
@@ -1215,6 +1246,20 @@ reverse_list_test(Config) ->
?line RevList = reverse_list(List),
?line badarg = reverse_list(foo).
+otp_9668(doc) -> ["Memory leak of tmp-buffer when inspecting iolist or unaligned binary in unbound environment"];
+otp_9668(Config) ->
+ ensure_lib_loaded(Config, 1),
+ TmpMem = tmpmem(),
+ IOList = ["This",' ',<<"is">>,' ',[<<"an iolist">>,'.']],
+ otp_9668_nif(IOList),
+
+ <<_:5/bitstring,UnalignedBin:10/binary,_/bitstring>> = <<"Abuse me as unaligned">>,
+ otp_9668_nif(UnalignedBin),
+
+ ?line verify_tmpmem(TmpMem),
+ ok.
+
+
tmpmem() ->
case erlang:system_info({allocator,temp_alloc}) of
false -> undefined;
@@ -1303,7 +1348,7 @@ get_resource(_,_) -> ?nif_stub.
release_resource(_) -> ?nif_stub.
last_resource_dtor_call() -> ?nif_stub.
make_new_resource(_,_) -> ?nif_stub.
-check_is(_,_,_,_,_,_,_,_,_,_) -> ?nif_stub.
+check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub.
check_is_exception() -> ?nif_stub.
length_test(_,_,_,_,_) -> ?nif_stub.
make_atoms() -> ?nif_stub.
@@ -1324,6 +1369,7 @@ send_term(_,_) -> ?nif_stub.
reverse_list(_) -> ?nif_stub.
echo_int(_) -> ?nif_stub.
type_sizes() -> ?nif_stub.
+otp_9668_nif(_) -> ?nif_stub.
nif_stub_error(Line) ->
exit({nif_not_loaded,module,?MODULE,line,Line}).
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index cf2ec4aaf0..03092fef5e 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -345,8 +345,13 @@ static int test_double(ErlNifEnv* env, double d1)
#define TAG_BITS 4
#define SMALL_BITS (sizeof(void*)*8 - TAG_BITS)
+#ifdef _WIN64
+#define MAX_SMALL ((1LL << (SMALL_BITS-1))-1)
+#define MIN_SMALL (-(1LL << (SMALL_BITS-1)))
+#else
#define MAX_SMALL ((1L << (SMALL_BITS-1))-1)
#define MIN_SMALL (-(1L << (SMALL_BITS-1)))
+#endif
static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -832,6 +837,7 @@ static ERL_NIF_TERM release_resource(ErlNifEnv* env, int argc, const ERL_NIF_TER
* argv[7] an empty list
* argv[8] a non-empty list
* argv[9] a tuple
+ * argv[10] a number (small, big integer or float)
*/
static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -848,6 +854,7 @@ static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
if (!enif_is_list(env, argv[7])) return enif_make_badarg(env);
if (!enif_is_list(env, argv[8])) return enif_make_badarg(env);
if (!enif_is_tuple(env, argv[9])) return enif_make_badarg(env);
+ if (!enif_is_number(env, argv[10])) return enif_make_badarg(env);
return ok_atom;
}
@@ -1429,6 +1436,26 @@ static ERL_NIF_TERM reverse_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
return rev_list;
}
+static ERL_NIF_TERM otp_9668_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ /* Inspect in process independent env */
+ ErlNifEnv* myenv = enif_alloc_env();
+ ERL_NIF_TERM mycopy = enif_make_copy(myenv, argv[0]);
+ ErlNifBinary obin, cbin;
+
+ if ((enif_inspect_binary(env, argv[0], &obin)
+ && enif_inspect_binary(myenv, mycopy, &cbin))
+ ||
+ (enif_inspect_iolist_as_binary(env, argv[0], &obin)
+ && enif_inspect_iolist_as_binary(myenv, mycopy, &cbin)))
+ {
+ assert(obin.size == cbin.size);
+ assert(memcmp(obin.data, cbin.data, obin.size) == 0);
+ }
+ enif_free_env(myenv);
+ return atom_ok;
+}
+
static ErlNifFunc nif_funcs[] =
{
{"lib_version", 0, lib_version},
@@ -1455,7 +1482,7 @@ static ErlNifFunc nif_funcs[] =
{"release_resource", 1, release_resource},
{"last_resource_dtor_call", 0, last_resource_dtor_call},
{"make_new_resource", 2, make_new_resource},
- {"check_is", 10, check_is},
+ {"check_is", 11, check_is},
{"check_is_exception", 0, check_is_exception},
{"length_test", 5, length_test},
{"make_atoms", 0, make_atoms},
@@ -1476,7 +1503,8 @@ static ErlNifFunc nif_funcs[] =
{"send_term", 2, send_term},
{"reverse_list",1, reverse_list},
{"echo_int", 1, echo_int},
- {"type_sizes", 0, type_sizes}
+ {"type_sizes", 0, type_sizes},
+ {"otp_9668_nif", 1, otp_9668_nif}
};
ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload)
diff --git a/erts/emulator/test/nif_SUITE_data/tester.c b/erts/emulator/test/nif_SUITE_data/tester.c
index 08466d0f18..257b116322 100644
--- a/erts/emulator/test/nif_SUITE_data/tester.c
+++ b/erts/emulator/test/nif_SUITE_data/tester.c
@@ -61,6 +61,7 @@ static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
static ERL_NIF_TERM run(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
testcase_run(NULL);
+ testcase_cleanup(NULL);
return enif_make_atom(env, "ok");
}
diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl
index aa83459ef8..0bf2c03233 100644
--- a/erts/emulator/test/node_container_SUITE.erl
+++ b/erts/emulator/test/node_container_SUITE.erl
@@ -459,10 +459,6 @@ make_node_garbage(_, _, _, Ps) ->
end,
lists:foreach(fun (P) -> wait_until(fun () -> ProcIsCleanedUp(P) end) end,
Ps),
- ?line case erlang:system_info(heap_type) of
- shared -> ?line garbage_collect();
- _ -> ?line ok
- end,
?line ok.
@@ -605,17 +601,7 @@ node_controller_refc(Config) when is_list(Config) ->
% Get rid of all references to Node
?line exec(P, fun () -> exit(normal) end),
?line wait_until(fun () -> not is_process_alive(P) end),
- ?line case erlang:system_info(heap_type) of
- shared ->
- ?line garbage_collect();
- hybrid ->
- ?line lists:foreach(fun (Proc) -> garbage_collect(Proc) end,
- processes()),
- ?line erlang:garbage_collect_message_area();
- _ ->
- ?line lists:foreach(fun (Proc) -> garbage_collect(Proc) end,
- processes())
- end,
+ lists:foreach(fun (Proc) -> garbage_collect(Proc) end, processes()),
?line false = get_node_references({Node,Creation}),
?line false = get_dist_references(Node),
?line false = lists:member(Node, nodes(known)),
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 0a1ef5a78f..0b99b3438a 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -1244,8 +1244,8 @@ otp_3906_forker(N, Parent, Ref, Sup, Prog) ->
otp_4389(suite) -> [];
otp_4389(doc) -> [];
otp_4389(Config) when is_list(Config) ->
- case {os:type(),erlang:system_info(heap_type)} of
- {{unix, _},private} ->
+ case os:type() of
+ {unix, _} ->
?line Dog = test_server:timetrap(test_server:seconds(240)),
?line TCR = self(),
case get_true_cmd() of
@@ -1293,7 +1293,7 @@ otp_4389(Config) when is_list(Config) ->
?line {skipped, "\"true\" command not found"}
end;
_ ->
- {skip,"Only run on Unix and private heaps"}
+ {skip,"Only run on Unix"}
end.
get_true_cmd() ->
diff --git a/erts/emulator/test/port_SUITE_data/echo_drv.c b/erts/emulator/test/port_SUITE_data/echo_drv.c
index 25eda116fe..1d39c6a00c 100644
--- a/erts/emulator/test/port_SUITE_data/echo_drv.c
+++ b/erts/emulator/test/port_SUITE_data/echo_drv.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <string.h>
#include "erl_driver.h"
@@ -17,11 +18,9 @@ typedef struct _erl_drv_data EchoDrvData;
static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command);
static void echo_drv_stop(EchoDrvData *data_p);
-static void echo_drv_output(EchoDrvData *data_p, char *buf, int len);
+static void echo_drv_output(ErlDrvData drv_data, char *buf,
+ ErlDrvSizeT len);
static void echo_drv_finish(void);
-static int echo_drv_control(EchoDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen);
static ErlDrvEntry echo_drv_entry = {
NULL, /* init */
@@ -33,10 +32,20 @@ static ErlDrvEntry echo_drv_entry = {
"echo_drv",
echo_drv_finish,
NULL, /* handle */
- echo_drv_control,
+ NULL, /* control */
NULL, /* timeout */
NULL, /* outputv */
- NULL /* ready_async */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
@@ -68,7 +77,8 @@ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) {
static void echo_drv_stop(EchoDrvData *data_p) {
}
-static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) {
+static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
+ EchoDrvData *data_p = (EchoDrvData *) drv_data;
void *void_ptr;
ErlDrvPort port = void_ptr = data_p;
@@ -77,9 +87,3 @@ static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) {
static void echo_drv_finish() {
}
-
-static int echo_drv_control(EchoDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen) {
- return 0;
-}
diff --git a/erts/emulator/test/port_SUITE_data/exit_drv.c b/erts/emulator/test/port_SUITE_data/exit_drv.c
index 60f1b321bd..5f366b3545 100644
--- a/erts/emulator/test/port_SUITE_data/exit_drv.c
+++ b/erts/emulator/test/port_SUITE_data/exit_drv.c
@@ -5,11 +5,9 @@ typedef struct _erl_drv_data ExitDrvData;
static ExitDrvData *exit_drv_start(ErlDrvPort port, char *command);
static void exit_drv_stop(ExitDrvData *data_p);
-static void exit_drv_output(ExitDrvData *data_p, char *buf, int len);
+static void exit_drv_output(ExitDrvData *data_p, char *buf,
+ ErlDrvSizeT len);
static void exit_drv_finish(void);
-static int exit_drv_control(ExitDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen);
static ErlDrvEntry exit_drv_entry = {
NULL, /* init */
@@ -21,10 +19,20 @@ static ErlDrvEntry exit_drv_entry = {
"exit_drv",
exit_drv_finish,
NULL, /* handle */
- exit_drv_control,
+ NULL, /* control */
NULL, /* timeout */
NULL, /* outputv */
- NULL /* ready_async */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
DRIVER_INIT(exit_drv)
@@ -45,7 +53,7 @@ exit_drv_stop(ExitDrvData *datap)
}
static void
-exit_drv_output(ExitDrvData *datap, char *buf, int len)
+exit_drv_output(ExitDrvData *datap, char *buf, ErlDrvSizeT len)
{
driver_exit((ErlDrvPort) datap, 0);
}
@@ -55,14 +63,3 @@ exit_drv_finish(void)
{
}
-
-static int
-exit_drv_control(ExitDrvData *datap,
- unsigned int command,
- char *buf,
- int len,
- char **rbuf,
- int rlen)
-{
- return 0;
-}
diff --git a/erts/emulator/test/port_SUITE_data/failure_drv.c b/erts/emulator/test/port_SUITE_data/failure_drv.c
index 34d48e00f8..5826e6d5a9 100644
--- a/erts/emulator/test/port_SUITE_data/failure_drv.c
+++ b/erts/emulator/test/port_SUITE_data/failure_drv.c
@@ -5,10 +5,8 @@ typedef struct _erl_drv_data FailureDrvData;
static FailureDrvData *failure_drv_start(ErlDrvPort, char *);
static void failure_drv_stop(FailureDrvData *);
-static void failure_drv_output(FailureDrvData *, char *, int);
+static void failure_drv_output(ErlDrvData, char *, ErlDrvSizeT);
static void failure_drv_finish(void);
-static int failure_drv_control(FailureDrvData *, unsigned int,
- char *, int, char **, int);
static ErlDrvEntry failure_drv_entry = {
NULL, /* init */
@@ -18,12 +16,22 @@ static ErlDrvEntry failure_drv_entry = {
NULL, /* ready_input */
NULL, /* ready_output */
"failure_drv",
- failure_drv_finish,
+ NULL, /* finish */
NULL, /* handle */
- failure_drv_control,
+ NULL, /* control */
NULL, /* timeout */
NULL, /* outputv */
- NULL /* ready_async */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
@@ -46,7 +54,8 @@ static FailureDrvData *failure_drv_start(ErlDrvPort port, char *command) {
static void failure_drv_stop(FailureDrvData *data_p) {
}
-static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) {
+static void failure_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
+ FailureDrvData *data_p = (FailureDrvData *) drv_data;
void *void_ptr;
ErlDrvPort port = void_ptr = data_p;
@@ -55,9 +64,3 @@ static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) {
static void failure_drv_finish() {
}
-
-static int failure_drv_control(FailureDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen) {
- return 0;
-}
diff --git a/erts/emulator/test/port_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl
index d9c82aba0e..8feea87d7e 100644
--- a/erts/emulator/test/port_bif_SUITE.erl
+++ b/erts/emulator/test/port_bif_SUITE.erl
@@ -24,6 +24,7 @@
init_per_group/2,end_per_group/2, command/1,
command_e_1/1, command_e_2/1, command_e_3/1, command_e_4/1,
port_info1/1, port_info2/1,
+ port_info_os_pid/1,
connect/1, control/1, echo_to_busy/1]).
-export([do_command_e_1/1, do_command_e_2/1, do_command_e_4/1]).
@@ -41,7 +42,7 @@ all() ->
groups() ->
[{command_e, [],
[command_e_1, command_e_2, command_e_3, command_e_4]},
- {port_info, [], [port_info1, port_info2]}].
+ {port_info, [], [port_info1, port_info2, port_info_os_pid]}].
init_per_suite(Config) ->
Config.
@@ -65,15 +66,15 @@ end_per_testcase(_Func, Config) when is_list(Config) ->
test_server:timetrap_cancel(Dog).
command(Config) when is_list(Config) ->
- ?line load_control_drv(Config),
-
- ?line P = open_port({spawn, control_drv}, []),
- ?line do_command(P, "hello"),
- ?line do_command(P, <<"hello">>),
- ?line do_command(P, sub_bin(<<"1234kalle">>)),
- ?line do_command(P, unaligned_sub_bin(<<"blurf">>)),
- ?line do_command(P, ["bl"|unaligned_sub_bin(<<"urf">>)]),
- ?line true = erlang:port_close(P),
+ load_control_drv(Config),
+
+ P = open_port({spawn, control_drv}, []),
+ do_command(P, "hello"),
+ do_command(P, <<"hello">>),
+ do_command(P, sub_bin(<<"1234kalle">>)),
+ do_command(P, unaligned_sub_bin(<<"blurf">>)),
+ do_command(P, ["bl"|unaligned_sub_bin(<<"urf">>)]),
+ true = erlang:port_close(P),
ok.
do_command(P, Data) ->
@@ -94,139 +95,163 @@ do_command(P, Data) ->
%% port_command/2: badarg 1st arg
command_e_1(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Program = filename:join(DataDir, "port_test"),
+ DataDir = ?config(data_dir, Config),
+ Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
- ?line _ = spawn_link(?MODULE, do_command_e_1, [Program]),
- ?line receive
- {'EXIT', Pid, {badarg, _}} when is_pid(Pid) ->
- ok;
- Other ->
- ?line test_server:fail(Other)
- after 10000 ->
- ?line test_server:fail(timeout)
- end,
+ _ = spawn_link(?MODULE, do_command_e_1, [Program]),
+ receive
+ {'EXIT', Pid, {badarg, _}} when is_pid(Pid) ->
+ ok;
+ Other ->
+ test_server:fail(Other)
+ after 10000 ->
+ test_server:fail(timeout)
+ end,
ok.
do_command_e_1(Program) ->
- ?line _ = open_port({spawn, Program}, []),
- ?line erlang:port_command(apple, "plock"),
+ _ = open_port({spawn, Program}, []),
+ erlang:port_command(apple, "plock"),
exit(survived).
%% port_command/2: badarg 2nd arg
command_e_2(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Program = filename:join(DataDir, "port_test"),
+ DataDir = ?config(data_dir, Config),
+ Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
- ?line _ = spawn_link(?MODULE, do_command_e_2, [Program]),
- ?line receive
- {'EXIT', Pid, {badarg, _}} when is_pid(Pid) ->
- ok;
- Other ->
- ?line test_server:fail(Other)
- after 10000 ->
- ?line test_server:fail(timeout)
- end,
+ _ = spawn_link(?MODULE, do_command_e_2, [Program]),
+ receive
+ {'EXIT', Pid, {badarg, _}} when is_pid(Pid) ->
+ ok;
+ Other ->
+ test_server:fail(Other)
+ after 10000 ->
+ test_server:fail(timeout)
+ end,
ok.
do_command_e_2(Program) ->
- ?line P = open_port({spawn, Program}, []),
- ?line erlang:port_command(P, 1),
+ P = open_port({spawn, Program}, []),
+ erlang:port_command(P, 1),
exit(survived).
%% port_command/2: Posix signals trapped
command_e_3(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Program = filename:join(DataDir, "port_test"),
+ DataDir = ?config(data_dir, Config),
+ Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
- ?line P = open_port({spawn, Program}, [{packet, 1}]),
- ?line Data = lists:duplicate(257, $a),
- ?line erlang:port_command(P, Data),
- ?line receive
- {'EXIT', Port, einval} when is_port(Port) ->
- ok;
- Other ->
- test_server:fail(Other)
- after 10000 ->
- test_server:fail(timeout)
- end,
+ P = open_port({spawn, Program}, [{packet, 1}]),
+ Data = lists:duplicate(257, $a),
+ erlang:port_command(P, Data),
+ receive
+ {'EXIT', Port, einval} when is_port(Port) ->
+ ok;
+ Other ->
+ test_server:fail(Other)
+ after 10000 ->
+ test_server:fail(timeout)
+ end,
ok.
%% port_command/2: Posix exit signals not trapped
command_e_4(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Program = filename:join(DataDir, "port_test"),
+ DataDir = ?config(data_dir, Config),
+ Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
- ?line _ = spawn_link(?MODULE, do_command_e_4, [Program]),
- ?line receive
- {'EXIT', Pid, {einval, _}} when is_pid(Pid) ->
- ok;
- Other ->
- ?line test_server:fail(Other)
- after 10000 ->
- ?line test_server:fail(timeout)
- end,
+ _ = spawn_link(?MODULE, do_command_e_4, [Program]),
+ receive
+ {'EXIT', Pid, {einval, _}} when is_pid(Pid) ->
+ ok;
+ Other ->
+ test_server:fail(Other)
+ after 10000 ->
+ test_server:fail(timeout)
+ end,
ok.
do_command_e_4(Program) ->
- ?line P = open_port({spawn, Program}, [{packet, 1}]),
- ?line Data = lists:duplicate(257, $a),
- ?line erlang:port_command(P, Data),
+ P = open_port({spawn, Program}, [{packet, 1}]),
+ Data = lists:duplicate(257, $a),
+ erlang:port_command(P, Data),
exit(survived).
%% Tests the port_info/1 BIF
port_info1(Config) when is_list(Config) ->
- ?line load_control_drv(Config),
+ load_control_drv(Config),
Me=self(),
- ?line P = open_port({spawn, control_drv}, []),
- ?line A1 = erlang:port_info(P),
- ?line false = lists:keysearch(registered_name, 1, A1),
- ?line register(myport, P),
- ?line A = erlang:port_info(P),
- ?line {value,{registered_name,myport}}=
- lists:keysearch(registered_name, 1, A),
- ?line {value,{name,"control_drv"}}=lists:keysearch(name, 1, A),
- ?line {value,{links,[Me]}}=lists:keysearch(links, 1, A),
- ?line {value,{id,_IdNum}}=lists:keysearch(id, 1, A),
- ?line {value,{connected,_}}=lists:keysearch(connected, 1, A),
- ?line {value,{input,0}}=lists:keysearch(input, 1, A),
- ?line {value,{output,0}}=lists:keysearch(output, 1, A),
- ?line true=erlang:port_close(P),
+ P = open_port({spawn, control_drv}, []),
+ A1 = erlang:port_info(P),
+ false = lists:keysearch(registered_name, 1, A1),
+ register(myport, P),
+ A = erlang:port_info(P),
+ {value,{registered_name,myport}}= lists:keysearch(registered_name, 1, A),
+ {value,{name,"control_drv"}}=lists:keysearch(name, 1, A),
+ {value,{links,[Me]}}=lists:keysearch(links, 1, A),
+ {value,{id,_IdNum}}=lists:keysearch(id, 1, A),
+ {value,{connected,_}}=lists:keysearch(connected, 1, A),
+ {value,{input,0}}=lists:keysearch(input, 1, A),
+ {value,{output,0}}=lists:keysearch(output, 1, A),
+ {value,{os_pid,undefined}}=lists:keysearch(os_pid, 1, A), % linked-in driver doesn't have a OS pid
+ true=erlang:port_close(P),
ok.
%% Tests erlang:port_info/2"
port_info2(Config) when is_list(Config) ->
- ?line load_control_drv(Config),
+ load_control_drv(Config),
- ?line P = open_port({spawn,control_drv}, [binary]),
- ?line [] = erlang:port_info(P, registered_name),
- ?line register(myport, P),
- ?line {registered_name, myport} = erlang:port_info(P, registered_name),
+ P = open_port({spawn,control_drv}, [binary]),
+ [] = erlang:port_info(P, registered_name),
+ register(myport, P),
+ {registered_name, myport} = erlang:port_info(P, registered_name),
- ?line {name, "control_drv"}=erlang:port_info(P, name),
- ?line {id, _IdNum} = erlang:port_info(P, id),
+ {name, "control_drv"}=erlang:port_info(P, name),
+ {id, _IdNum} = erlang:port_info(P, id),
Me=self(),
- ?line {links, [Me]} = erlang:port_info(P, links),
- ?line {connected, Me} = erlang:port_info(P, connected),
- ?line {input, 0}=erlang:port_info(P, input),
- ?line {output,0}=erlang:port_info(P, output),
-
- ?line erlang:port_control(P, $i, "abc"),
- ?line receive
- {P,{data,<<"abc">>}} -> ok
- end,
- ?line {input,3} = erlang:port_info(P, input),
- ?line {output,0} = erlang:port_info(P, output),
-
- ?line Bin = list_to_binary(lists:duplicate(2047, 42)),
- ?line output_test(P, Bin, 3, 0),
+ {links, [Me]} = erlang:port_info(P, links),
+ {connected, Me} = erlang:port_info(P, connected),
+ {input, 0}=erlang:port_info(P, input),
+ {output,0}=erlang:port_info(P, output),
+ {os_pid, undefined}=erlang:port_info(P, os_pid), % linked-in driver doesn't have a OS pid
+
+ erlang:port_control(P, $i, "abc"),
+ receive
+ {P,{data,<<"abc">>}} -> ok
+ end,
+ {input,3} = erlang:port_info(P, input),
+ {output,0} = erlang:port_info(P, output),
+
+ Bin = list_to_binary(lists:duplicate(2047, 42)),
+ output_test(P, Bin, 3, 0),
- ?line true = erlang:port_close(P),
+ true = erlang:port_close(P),
+ ok.
+
+%% Tests the port_info/1,2 os_pid option BIF
+port_info_os_pid(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} ->
+ do_port_info_os_pid();
+ _ ->
+ {skip,"Only on Unix."}
+ end.
+
+do_port_info_os_pid() ->
+ P = open_port({spawn, "echo $$"}, [eof]),
+ A = erlang:port_info(P),
+ {os_pid, InfoOSPid} = erlang:port_info(P, os_pid),
+ EchoPidStr = receive
+ {P, {data, EchoPidStr0}} -> EchoPidStr0
+ after 10000 -> test_server:fail(timeout)
+ end,
+ {ok, [EchoPid], []} = io_lib:fread("~u\n", EchoPidStr),
+ {value,{os_pid, InfoOSPid}}=lists:keysearch(os_pid, 1, A),
+ EchoPid = InfoOSPid,
+ true = erlang:port_close(P),
ok.
output_test(_, _, Input, Output) when Output > 16#1fffffff ->
@@ -237,7 +262,7 @@ output_test(P, Bin, Input0, Output0) ->
{P,{data,Bin}} -> ok;
Other ->
io:format("~p", [Other]),
- ?line ?t:fail()
+ ?t:fail()
end,
Input = Input0 + size(Bin),
Output = Output0 + size(Bin),
@@ -254,109 +279,106 @@ output_test(P, Bin, Input0, Output0) ->
%% Tests the port_connect/2 BIF.
connect(Config) when is_list(Config) ->
- ?line load_control_drv(Config),
+ load_control_drv(Config),
- ?line P = open_port({spawn, control_drv}, []),
+ P = open_port({spawn, control_drv}, []),
register(myport, P),
- ?line true = erlang:port_connect(myport, self()),
+ true = erlang:port_connect(myport, self()),
%% Connect the port to another process.
Data = "hello, world",
Parent = self(),
- ?line Rec =
- fun(Me) -> receive
- {P,{data,Data}} ->
- Parent ! connect_ok,
- Me(Me)
- end
- end,
- ?line RecPid = spawn_link(fun() -> Rec(Rec) end),
- ?line true = erlang:port_connect(P, RecPid),
- ?line unlink(P),
+ Rec = fun(Me) ->
+ receive
+ {P,{data,Data}} ->
+ Parent ! connect_ok,
+ Me(Me)
+ end
+ end,
+ RecPid = spawn_link(fun() -> Rec(Rec) end),
+ true = erlang:port_connect(P, RecPid),
+ unlink(P),
%% Send a command to the port and make sure that the
%% other process receives the echo.
- ?line erlang:port_command(P, Data),
- ?line receive
- connect_ok -> ok
- end,
+ erlang:port_command(P, Data),
+ receive
+ connect_ok -> ok
+ end,
%% Tests some errors.
- ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(self(), self())),
- ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(self(), P)),
- ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, P)),
- ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, xxxx)),
- ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, [])),
+ {'EXIT',{badarg, _}}=(catch erlang:port_connect(self(), self())),
+ {'EXIT',{badarg, _}}=(catch erlang:port_connect(self(), P)),
+ {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, P)),
+ {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, xxxx)),
+ {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, [])),
- ?line process_flag(trap_exit, true),
- ?line exit(P, you_should_die),
- ?line receive
- {'EXIT',RecPid,you_should_die} -> ok;
- Other -> ?line ?t:fail({bad_message,Other})
- end,
+ process_flag(trap_exit, true),
+ exit(P, you_should_die),
+ receive
+ {'EXIT',RecPid,you_should_die} -> ok;
+ Other -> ?line ?t:fail({bad_message,Other})
+ end,
%% Done.
ok.
%% Tests port_control/3
control(Config) when is_list(Config) ->
- ?line load_control_drv(Config),
- ?line P = open_port({spawn, control_drv}, []),
+ load_control_drv(Config),
+ P = open_port({spawn, control_drv}, []),
%% Test invalid (out-of-range) arguments.
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(self(), 1, [])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(self(), 1, [])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, -1, [])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, -34887348739733833, [])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 16#100000000, [])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, a, [])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 'e', dum)),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, dum)),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, fun(X) -> X end)),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e,
- [fun(X) -> X end])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e,
- [1|fun(X) -> X end])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, -1, [])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, -34887348739733833, [])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 16#100000000, [])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, a, [])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 'e', dum)),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, dum)),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, fun(X) -> X end)),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, [fun(X) -> X end])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, [1|fun(X) -> X end])),
%% Test errors detected by the driver.
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 177, [])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 155,
- random_packet(1024))),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 177, [])),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 155, random_packet(1024))),
%% Test big op codes.
register(myport, P),
- ?line test_op(myport, 256),
- ?line test_op(P, 256),
- ?line test_op(P, 16#0033A837),
- ?line test_op(P, 16#0ab37938),
- ?line test_op(P, 16#eab37938),
- ?line test_op(P, 16#ffffFFFF),
+ test_op(myport, 256),
+ test_op(P, 256),
+ test_op(P, 16#0033A837),
+ test_op(P, 16#0ab37938),
+ test_op(P, 16#eab37938),
+ test_op(P, 16#ffffFFFF),
%% Test the echo function of the driver.
- ?line echo(P, 0),
- ?line echo(P, 1),
- ?line echo(P, 10),
- ?line echo(P, 13),
- ?line echo(P, 63),
- ?line echo(P, 64),
- ?line echo(P, 65),
- ?line echo(P, 127),
- ?line echo(P, 1023),
- ?line echo(P, 1024),
- ?line echo(P, 11243),
- ?line echo(P, 70000),
+ echo(P, 0),
+ echo(P, 1),
+ echo(P, 10),
+ echo(P, 13),
+ echo(P, 63),
+ echo(P, 64),
+ echo(P, 65),
+ echo(P, 127),
+ echo(P, 1023),
+ echo(P, 1024),
+ echo(P, 11243),
+ echo(P, 70000),
%% Done.
- ?line true=erlang:port_close(myport),
+ true = erlang:port_close(myport),
ok.
test_op(P, Op) ->
@@ -364,23 +386,23 @@ test_op(P, Op) ->
<<Op:32>> = list_to_binary(R).
echo_to_busy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line load_control_drv(Config),
- ?line P = open_port({spawn, control_drv}, []),
- ?line erlang:port_control(P, $b, [1]), % Set to busy.
+ Dog = test_server:timetrap(test_server:seconds(10)),
+ load_control_drv(Config),
+ P = open_port({spawn, control_drv}, []),
+ erlang:port_control(P, $b, [1]), % Set to busy.
Self = self(),
- ?line Echoer = spawn(fun() -> echoer(P, Self) end),
- ?line receive after 500 -> ok end,
- ?line erlang:port_control(P, $b, [0]), % Set to not busy.
- ?line receive
- {Echoer, done} ->
- ok;
- {Echoer, Other} ->
- test_server:fail(Other);
- Other ->
- test_server:fail({unexpected_message, Other})
- end,
- ?line test_server:timetrap_cancel(Dog),
+ Echoer = spawn(fun() -> echoer(P, Self) end),
+ receive after 500 -> ok end,
+ erlang:port_control(P, $b, [0]), % Set to not busy.
+ receive
+ {Echoer, done} ->
+ ok;
+ {Echoer, Other} ->
+ test_server:fail(Other);
+ Other ->
+ test_server:fail({unexpected_message, Other})
+ end,
+ test_server:timetrap_cancel(Dog),
ok.
echoer(P, ReplyTo) ->
@@ -405,9 +427,9 @@ echo(P, Size) ->
Packet = erlang:port_control(P, $e, [unaligned_sub_bin(Bin)]).
load_control_drv(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(DataDir, "control_drv").
+ DataDir = ?config(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(DataDir, "control_drv").
load_driver(Dir, Driver) ->
case erl_ddll:load_driver(Dir, Driver) of
@@ -459,4 +481,3 @@ sub_bin(Bin) when is_binary(Bin) ->
B.
id(I) -> I.
-
diff --git a/erts/emulator/test/port_bif_SUITE_data/control_drv.c b/erts/emulator/test/port_bif_SUITE_data/control_drv.c
index e9f57a887a..b937a8bb15 100644
--- a/erts/emulator/test/port_bif_SUITE_data/control_drv.c
+++ b/erts/emulator/test/port_bif_SUITE_data/control_drv.c
@@ -1,13 +1,15 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "erl_driver.h"
static ErlDrvPort erlang_port;
static ErlDrvData control_start(ErlDrvPort, char*);
static void control_stop(ErlDrvData);
-static void control_read(ErlDrvData, char*, int);
-static int control_control(ErlDrvData, unsigned int, char*, int, char**, int);
+static void control_read(ErlDrvData, char*, ErlDrvSizeT);
+static ErlDrvSSizeT control_control(ErlDrvData, unsigned int, char*,
+ ErlDrvSizeT, char**, ErlDrvSizeT);
static ErlDrvEntry control_driver_entry =
{
@@ -21,9 +23,19 @@ static ErlDrvEntry control_driver_entry =
NULL,
NULL,
control_control,
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
NULL,
NULL,
- NULL
};
DRIVER_INIT(control_drv)
@@ -41,7 +53,7 @@ static ErlDrvData control_start(ErlDrvPort port,char *buf)
return (ErlDrvData)port;
}
-static void control_read(ErlDrvData port, char *buf, int count)
+static void control_read(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
driver_output(erlang_port, buf, count);
}
@@ -51,8 +63,9 @@ static void control_stop(ErlDrvData port)
erlang_port = (ErlDrvPort)-1;
}
-static int control_control(ErlDrvData port, unsigned command, char* buf, int count,
- char** res, int res_size)
+static ErlDrvSSizeT control_control(ErlDrvData port, unsigned command,
+ char* buf, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size)
{
switch (command) {
case 'e':
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index debb54579b..8931562828 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -55,7 +55,7 @@
scheduler_suspend/1,
reader_groups/1]).
--define(DEFAULT_TIMEOUT, ?t:minutes(10)).
+-define(DEFAULT_TIMEOUT, ?t:minutes(15)).
-define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)).
@@ -519,16 +519,18 @@ bound_loop(NS, N, M, Sched) ->
bindings(Node, BindType) ->
Parent = self(),
Ref = make_ref(),
- spawn_link(Node,
- fun () ->
- enable_internal_state(),
- Res = (catch erts_debug:get_internal_state(
- {fake_scheduler_bindings, BindType})),
- Parent ! {Ref, Res}
- end),
+ Pid = spawn_link(Node,
+ fun () ->
+ enable_internal_state(),
+ Res = (catch erts_debug:get_internal_state(
+ {fake_scheduler_bindings,
+ BindType})),
+ Parent ! {Ref, Res}
+ end),
receive
{Ref, Res} ->
?t:format("~p: ~p~n", [BindType, Res]),
+ unlink(Pid),
Res
end.
@@ -1684,7 +1686,7 @@ do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) ->
EndWait = now(),
BalanceWait = timer:now_diff(EndWait,StartWait) div 1000,
erlang:display({balance_wait, BalanceWait}),
- Timeout = ?DEFAULT_TIMEOUT - ?t:seconds(10) - BalanceWait,
+ Timeout = ?DEFAULT_TIMEOUT - ?t:minutes(4) - BalanceWait,
Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of
true ->
stop_work(Low, Normal, High, Max),
diff --git a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c
index 165cce2e9d..b3feca79f0 100644
--- a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c
+++ b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c
@@ -24,7 +24,7 @@
static ErlDrvPort erlang_port;
static ErlDrvData send_term_drv_start(ErlDrvPort port, char *command);
static void send_term_drv_stop(ErlDrvData drv_data);
-static void send_term_drv_run(ErlDrvData drv_data, char *buf, int len);
+static void send_term_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
static int make_ext_term_list(ErlDrvTermData *td, int bad);
@@ -39,6 +39,22 @@ static ErlDrvEntry send_term_drv_entry = {
NULL,
NULL,
"send_term_drv",
+ NULL,
+ NULL, /* handle */
+ NULL, /* control */
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
DRIVER_INIT(send_term_drv)
@@ -64,7 +80,7 @@ static void send_term_drv_stop(ErlDrvData drv_data)
static void output_term(ErlDrvTermData* msg, int len);
static void fail_term(ErlDrvTermData* msg, int len, int line);
-static void send_term_drv_run(ErlDrvData port, char *buf, int count)
+static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count)
{
char buf7[1024];
ErlDrvTermData spec[1024];
diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl
index 634df367ca..e073eab596 100644
--- a/erts/emulator/test/sensitive_SUITE.erl
+++ b/erts/emulator/test/sensitive_SUITE.erl
@@ -160,8 +160,7 @@ recv_trace(Config) when is_list(Config) ->
?line {messages,Messages} = process_info(Tracer, messages),
[{trace,Parent,'receive',a},
{trace,Parent,'receive',{trace_delivered,_,_}},
- {trace,Parent,'receive',c},
- {trace,Parent,'receive',{trace_delivered,_,_}}] = Messages,
+ {trace,Parent,'receive',c}|_] = Messages,
?line unlink(Tracer), exit(Tracer, kill),
?line unlink(Sender), exit(Sender, kill),
diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl
new file mode 100644
index 0000000000..98f1cf1ad5
--- /dev/null
+++ b/erts/emulator/test/smoke_test_SUITE.erl
@@ -0,0 +1,139 @@
+%%
+%% %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(smoke_test_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+
+%-compile(export_all).
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2, end_per_testcase/2]).
+
+-export([boot_combo/1]).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(2)).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [boot_combo].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(Case, Config) when is_list(Config) ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ [{testcase, Case},{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+%%%
+%%% The test cases -------------------------------------------------------------
+%%%
+
+boot_combo(Config) when is_list(Config) ->
+ ZFlags = os:getenv("ERL_ZFLAGS"),
+ NOOP = fun () -> ok end,
+ A42 = fun () ->
+ case erlang:system_info(threads) of
+ true ->
+ 42 = erlang:system_info(thread_pool_size);
+ false ->
+ ok
+ end
+ end,
+ SMPDisable = fun () -> false = erlang:system_info(smp_support) end,
+ try
+ chk_boot(Config, "+Ktrue", NOOP),
+ chk_boot(Config, "+A42", A42),
+ chk_boot(Config, "-smp disable", SMPDisable),
+ chk_boot(Config, "+Ktrue +A42", A42),
+ chk_boot(Config, "-smp disable +A42",
+ fun () -> SMPDisable(), A42() end),
+ chk_boot(Config, "-smp disable +Ktrue", SMPDisable),
+ chk_boot(Config, "-smp disable +Ktrue +A42",
+ fun () -> SMPDisable(), A42() end),
+ %% A lot more combos could be implemented...
+ ok
+ after
+ os:putenv("ERL_ZFLAGS", case ZFlags of
+ false -> "";
+ _ -> ZFlags
+ end)
+ end.
+
+%%%
+%%% Aux functions --------------------------------------------------------------
+%%%
+
+chk_boot(Config, Args, Fun) ->
+ true = os:putenv("ERL_ZFLAGS", Args),
+ Success = make_ref(),
+ Parent = self(),
+ ?t:format("--- Testing ~s~n", [Args]),
+ {ok, Node} = start_node(Config),
+ Pid = spawn_link(Node, fun () ->
+ Fun(),
+ Parent ! {self(), Success}
+ end),
+ receive
+ {Pid, Success} ->
+ Node = node(Pid),
+ stop_node(Node),
+ ?t:format("--- Success!~n", []),
+ ok
+ end.
+
+start_node(Config) ->
+ start_node(Config, "").
+
+start_node(Config, Args) when is_list(Config) ->
+ ?line Pa = filename:dirname(code:which(?MODULE)),
+ ?line {A, B, C} = now(),
+ ?line Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-"
+ ++ atom_to_list(?config(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(A)
+ ++ "-"
+ ++ integer_to_list(B)
+ ++ "-"
+ ++ integer_to_list(C)),
+ ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
+
+stop_node(Node) ->
+ ?t:stop_node(Node).
+
diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl
index 0392312a6f..a93dd309c1 100644
--- a/erts/emulator/test/statistics_SUITE.erl
+++ b/erts/emulator/test/statistics_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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 @@
runtime_zero_diff/1,
runtime_update/1, runtime_diff/1,
run_queue_one/1,
+ scheduler_wall_time/1,
reductions/1, reductions_big/1, garbage_collection/1, io/1,
badarg/1]).
@@ -51,8 +52,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[{group, wall_clock}, {group, runtime}, reductions,
- reductions_big, {group, run_queue}, garbage_collection,
- io, badarg].
+ reductions_big, {group, run_queue}, scheduler_wall_time,
+ garbage_collection, io, badarg].
groups() ->
[{wall_clock, [],
@@ -266,11 +267,10 @@ run_queue_one(Config) when is_list(Config) ->
run_queue_one_test(Config) when is_list(Config) ->
- ?line Hog = spawn_link(?MODULE, hog, [self()]),
+ ?line _Hog = spawn_link(?MODULE, hog, [self()]),
?line receive
- hog_started ->
- Hog ! go
- end,
+ hog_started -> ok
+ end,
?line receive after 100 -> ok end, % Give hog a head start.
?line case statistics(run_queue) of
N when N >= 1 -> ok;
@@ -280,18 +280,88 @@ run_queue_one_test(Config) when is_list(Config) ->
%% CPU-bound process, going at low priority. It will always be ready
%% to run.
-
+
hog(Pid) ->
?line process_flag(priority, low),
?line Pid ! hog_started,
- ?line receive
- go -> hog_iter(0)
+ ?line Mon = erlang:monitor(process, Pid),
+ ?line hog_iter(0, Mon).
+
+hog_iter(N, Mon) when N > 0 ->
+ receive
+ {'DOWN', Mon, _, _, _} -> ok
+ after 0 ->
+ ?line hog_iter(N-1, Mon)
+ end;
+hog_iter(0, Mon) ->
+ ?line hog_iter(10000, Mon).
+
+%%% Tests of statistics(scheduler_wall_time).
+
+scheduler_wall_time(doc) ->
+ "Tests that statistics(scheduler_wall_time) works as intended";
+scheduler_wall_time(Config) when is_list(Config) ->
+ %% Should return undefined if system_flag is not turned on yet
+ undefined = statistics(scheduler_wall_time),
+ %% Turn on statistics
+ false = erlang:system_flag(scheduler_wall_time, true),
+ try
+ Schedulers = erlang:system_info(schedulers_online),
+ %% Let testserver and everyone else finish their work
+ timer:sleep(500),
+ %% Empty load
+ EmptyLoad = get_load(),
+ {false, _} = {lists:any(fun(Load) -> Load > 50 end, EmptyLoad),EmptyLoad},
+ MeMySelfAndI = self(),
+ StartHog = fun() ->
+ Pid = spawn(?MODULE, hog, [self()]),
+ receive hog_started -> MeMySelfAndI ! go end,
+ Pid
+ end,
+ P1 = StartHog(),
+ %% Max on one, the other schedulers empty (hopefully)
+ %% Be generous the process can jump between schedulers
+ %% which is ok and we don't want the test to fail for wrong reasons
+ _L1 = [S1Load|EmptyScheds1] = get_load(),
+ {true,_} = {S1Load > 50,S1Load},
+ {false,_} = {lists:any(fun(Load) -> Load > 50 end, EmptyScheds1),EmptyScheds1},
+ {true,_} = {lists:sum(EmptyScheds1) < 60,EmptyScheds1},
+
+ %% 50% load
+ HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)],
+ HalfLoad = lists:sum(get_load()) div Schedulers,
+ if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog
+ %% We want roughly 50% load
+ HalfLoad > 40, HalfLoad < 60 -> ok;
+ true -> exit({halfload, HalfLoad})
+ end,
+
+ %% 100% load
+ LastHogs = [StartHog() || _ <- lists:seq(1, Schedulers div 2)],
+ FullScheds = get_load(),
+ {false,_} = {lists:any(fun(Load) -> Load < 80 end, FullScheds),FullScheds},
+ FullLoad = lists:sum(FullScheds) div Schedulers,
+ if FullLoad > 90 -> ok;
+ true -> exit({fullload, FullLoad})
+ end,
+
+ [exit(Pid, kill) || Pid <- [P1|HalfHogs++LastHogs]],
+ AfterLoad = get_load(),
+ {false,_} = {lists:any(fun(Load) -> Load > 5 end, AfterLoad),AfterLoad},
+ true = erlang:system_flag(scheduler_wall_time, false)
+ after
+ erlang:system_flag(scheduler_wall_time, false)
end.
-hog_iter(N) when N > 0 ->
- ?line hog_iter(N-1);
-hog_iter(0) ->
- ?line hog_iter(10000).
+get_load() ->
+ Start = erlang:statistics(scheduler_wall_time),
+ timer:sleep(500),
+ End = erlang:statistics(scheduler_wall_time),
+ lists:reverse(lists:sort(load_percentage(lists:sort(Start),lists:sort(End)))).
+
+load_percentage([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) ->
+ [100*(WN-WP) div (TN-TP)|load_percentage(Ss, Ps)];
+load_percentage([], []) -> [].
garbage_collection(doc) ->
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index 9b782b35a2..0350eb671d 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -37,7 +37,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2, end_per_testcase/2]).
--export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1]).
+-export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1, memory/1]).
-define(DEFAULT_TIMEOUT, ?t:minutes(2)).
@@ -45,7 +45,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[process_count, system_version, misc_smoke_tests,
- heap_size, wordsize].
+ heap_size, wordsize, memory].
groups() ->
[].
@@ -187,3 +187,312 @@ wordsize(Config) when is_list(Config) ->
Other ->
exit({unexpected_wordsizes,Other})
end.
+
+memory(doc) -> ["Verify that erlang:memory/0 and memory results in crashdump produce are similar"];
+memory(Config) when is_list(Config) ->
+ %%
+ %% Verify that erlang:memory/0 and memory results in
+ %% crashdump produce are similar.
+ %%
+ %% erlang:memory/0 requests information from each scheduler
+ %% thread and puts the information together in erlang code
+ %% (erlang.erl).
+ %%
+ %% When a crash dump is written we cannot use the
+ %% erlang:memory/0 implementation. The crashdump implementation
+ %% is a pure C implementation inspecting all allocator instances
+ %% after the system has been blocked (erts_memory() in erl_alloc.c).
+ %%
+ %% Since we got two implementations, modifications can easily
+ %% cause them to produce different results.
+ %%
+ %% erts_debug:get_internal_state(memory) blocks the system and
+ %% execute the same code as the crash dump writing uses.
+ %%
+
+ erts_debug:set_internal_state(available_internal_state, true),
+ %% Use a large heap size on the controling process in
+ %% order to avoid changes in its heap size during
+ %% comparisons.
+ MinHeapSize = process_flag(min_heap_size, 1024*1024),
+ Prio = process_flag(priority, max),
+ try
+ erlang:memory(), %% first call will init stat atoms
+ garbage_collect(), %% blow up heap
+ memory_test(Config)
+ catch
+ error:notsup -> {skipped, "erlang:memory() not supported"}
+ after
+ process_flag(min_heap_size, MinHeapSize),
+ process_flag(priority, Prio),
+ catch erts_debug:set_internal_state(available_internal_state, false)
+ end.
+
+memory_test(_Config) ->
+
+ MWs = spawn_mem_workers(),
+
+ DPs = mem_workers_call(MWs,
+ fun () ->
+ mapn(fun (_) ->
+ spawn(fun () ->
+ receive
+ after infinity ->
+ ok
+ end
+ end)
+ end,
+ 1000 div erlang:system_info(schedulers_online))
+ end,
+ []),
+ cmp_memory(MWs, "spawn procs"),
+
+ Ps = lists:flatten(DPs),
+
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (P) -> link(P) end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "link procs"),
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (P) -> unlink(P) end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "unlink procs"),
+
+ DMs = mem_workers_call(MWs,
+ fun () ->
+ lists:map(fun (P) ->
+ monitor(process, P)
+ end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "monitor procs"),
+ Ms = lists:flatten(DMs),
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (M) ->
+ demonitor(M)
+ end, Ms)
+ end,
+ []),
+ cmp_memory(MWs, "demonitor procs"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ lists:foreach(fun (P) ->
+ P ! {a, "message", make_ref()}
+ end, Ps)
+ end,
+ []),
+ cmp_memory(MWs, "message procs"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ Mons = lists:map(fun (P) ->
+ exit(P, kill),
+ monitor(process, P)
+ end,
+ Ps),
+ lists:foreach(fun (Mon) ->
+ receive
+ {'DOWN', Mon, _, _, _} -> ok
+ end
+ end,
+ Mons)
+ end, []),
+ cmp_memory(MWs, "kill procs"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ put(binary_data,
+ mapn(fun (_) -> list_to_binary(lists:duplicate(256,$?)) end, 100))
+ end,
+ []),
+
+ cmp_memory(MWs, "store binary data"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ put(binary_data, false),
+ garbage_collect()
+ end,
+ []),
+ cmp_memory(MWs, "release binary data"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ list_to_atom("an ugly atom "++integer_to_list(erlang:system_info(scheduler_id))),
+ list_to_atom("another ugly atom "++integer_to_list(erlang:system_info(scheduler_id))),
+ list_to_atom("yet another ugly atom "++integer_to_list(erlang:system_info(scheduler_id)))
+ end,
+ []),
+ cmp_memory(MWs, "new atoms"),
+
+
+ mem_workers_call(MWs,
+ fun () ->
+ T = ets:new(?MODULE, []),
+ ets:insert(T, {gurka, lists:seq(1,10000)}),
+ ets:insert(T, {banan, lists:seq(1,1024)}),
+ ets:insert(T, {appelsin, make_ref()}),
+ put(ets_id, T)
+ end,
+ []),
+ cmp_memory(MWs, "store ets data"),
+
+ mem_workers_call(MWs,
+ fun () ->
+ ets:delete(get(ets_id)),
+ put(ets_id, false)
+ end,
+ []),
+ cmp_memory(MWs, "remove ets data"),
+
+ lists:foreach(fun (MW) ->
+ unlink(MW),
+ Mon = monitor(process, MW),
+ exit(MW, kill),
+ receive
+ {'DOWN', Mon, _, _, _} -> ok
+ end
+ end,
+ MWs),
+ ok.
+
+mem_worker() ->
+ receive
+ {call, From, Fun, Args} ->
+ From ! {reply, self(), apply(Fun, Args)},
+ mem_worker();
+ {cast, _From, Fun, Args} ->
+ apply(Fun, Args),
+ mem_worker()
+ end.
+
+mem_workers_call(MWs, Fun, Args) ->
+ lists:foreach(fun (MW) ->
+ MW ! {call, self(), Fun, Args}
+ end,
+ MWs),
+ lists:map(fun (MW) ->
+ receive
+ {reply, MW, Res} ->
+ Res
+ end
+ end,
+ MWs).
+
+mem_workers_cast(MWs, Fun, Args) ->
+ lists:foreach(fun (MW) ->
+ MW ! {cast, self(), Fun, Args}
+ end,
+ MWs).
+
+spawn_mem_workers() ->
+ spawn_mem_workers(erlang:system_info(schedulers_online)).
+
+spawn_mem_workers(0) ->
+ [];
+spawn_mem_workers(N) ->
+ [spawn_opt(fun () -> mem_worker() end,
+ [{scheduler, N rem erlang:system_info(schedulers_online) + 1},
+ link]) | spawn_mem_workers(N-1)].
+
+
+
+mem_get(X, Mem) ->
+ case lists:keyfind(X, 1, Mem) of
+ {X, Val} -> Val;
+ false -> false
+ end.
+
+cmp_memory(What, Mem1, Mem2, 1) ->
+ R1 = mem_get(What, Mem1),
+ R2 = mem_get(What, Mem2),
+ true = R1 == R2;
+cmp_memory(What, Mem1, Mem2, RelDiff) ->
+ %% We allow RealDiff diff
+ R1 = mem_get(What, Mem1),
+ R2 = mem_get(What, Mem2),
+ case R1 == R2 of
+ true ->
+ ok;
+ false ->
+ case R1 > R2 of
+ true ->
+ true = R2*RelDiff > R1;
+ false ->
+ true = R1*RelDiff > R2
+ end
+ end.
+
+pos_int(Val) when Val >= 0 ->
+ Val;
+pos_int(Val) ->
+ exit({not_pos_int, Val}).
+
+check_sane_memory(Mem) ->
+ Tot = pos_int(mem_get(total, Mem)),
+ Proc = pos_int(mem_get(processes, Mem)),
+ ProcUsed = pos_int(mem_get(processes_used, Mem)),
+ Sys = pos_int(mem_get(system, Mem)),
+ Atom = pos_int(mem_get(atom, Mem)),
+ AtomUsed = pos_int(mem_get(atom_used, Mem)),
+ Bin = pos_int(mem_get(binary, Mem)),
+ Code = pos_int(mem_get(code, Mem)),
+ Ets = pos_int(mem_get(ets, Mem)),
+
+ Tot = Proc + Sys,
+ true = Sys > Atom + Bin + Code + Ets,
+ true = Proc >= ProcUsed,
+ true = Atom >= AtomUsed,
+
+ case mem_get(maximum, Mem) of
+ false -> ok;
+ Max -> true = pos_int(Max) >= Tot
+ end,
+ ok.
+
+cmp_memory(MWs, Str) ->
+ erlang:display(Str),
+ lists:foreach(fun (MW) -> garbage_collect(MW) end, MWs),
+ garbage_collect(),
+ erts_debug:set_internal_state(wait, deallocations),
+
+ EDM = erts_debug:get_internal_state(memory),
+ EM = erlang:memory(),
+
+ io:format("~s:~n"
+ "erlang:memory() = ~p~n"
+ "crash dump memory = ~p~n",
+ [Str, EM, EDM]),
+
+ ?line check_sane_memory(EM),
+ ?line check_sane_memory(EDM),
+
+ %% We expect these to always give us exactly the same result
+
+ ?line cmp_memory(atom, EM, EDM, 1),
+ ?line cmp_memory(atom_used, EM, EDM, 1),
+ ?line cmp_memory(binary, EM, EDM, 1),
+ ?line cmp_memory(code, EM, EDM, 1),
+ ?line cmp_memory(ets, EM, EDM, 1),
+
+ %% Total, processes, processes_used, and system will seldom
+ %% give us exactly the same result since the two readings
+ %% aren't taken atomically.
+
+ ?line cmp_memory(total, EM, EDM, 1.05),
+ ?line cmp_memory(processes, EM, EDM, 1.05),
+ ?line cmp_memory(processes_used, EM, EDM, 1.05),
+ ?line cmp_memory(system, EM, EDM, 1.05),
+
+ ok.
+
+mapn(_Fun, 0) ->
+ [];
+mapn(Fun, N) ->
+ [Fun(N) | mapn(Fun, N-1)].
diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl
index 32089e8872..ba94a371be 100644
--- a/erts/emulator/test/system_profile_SUITE.erl
+++ b/erts/emulator/test/system_profile_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -27,6 +27,7 @@
system_profile_on_and_off/1,
runnable_procs/1,
runnable_ports/1,
+ dont_profile_profiler/1,
scheduler/1
]).
@@ -40,7 +41,7 @@
-define(default_timeout, ?t:minutes(1)).
init_per_testcase(_Case, Config) ->
- ?line Dog=?t:timetrap(?default_timeout),
+ Dog=?t:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
end_per_testcase(_Case, Config) ->
Dog=?config(watchdog, Config),
@@ -51,7 +52,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[system_profile_on_and_off, runnable_procs,
- runnable_ports, scheduler].
+ runnable_ports, scheduler, dont_profile_profiler].
groups() ->
[].
@@ -77,31 +78,31 @@ system_profile_on_and_off(suite) ->
system_profile_on_and_off(doc) ->
["Tests switching system_profiling on and off."];
system_profile_on_and_off(Config) when is_list(Config) ->
- ?line Pid = start_profiler_process(),
+ Pid = start_profiler_process(),
% Test runnable_ports on and off
- ?line undefined = erlang:system_profile(Pid, [runnable_ports]),
- ?line {Pid, [runnable_ports]} = erlang:system_profile(),
- ?line {Pid, [runnable_ports]} = erlang:system_profile(undefined, []),
+ undefined = erlang:system_profile(Pid, [runnable_ports]),
+ {Pid, [runnable_ports]} = erlang:system_profile(),
+ {Pid, [runnable_ports]} = erlang:system_profile(undefined, []),
% Test runnable_procs on and off
- ?line undefined = erlang:system_profile(Pid, [runnable_procs]),
- ?line {Pid, [runnable_procs]} = erlang:system_profile(),
- ?line {Pid, [runnable_procs]} = erlang:system_profile(undefined, []),
+ undefined = erlang:system_profile(Pid, [runnable_procs]),
+ {Pid, [runnable_procs]} = erlang:system_profile(),
+ {Pid, [runnable_procs]} = erlang:system_profile(undefined, []),
% Test scheduler on and off
- ?line undefined = erlang:system_profile(Pid, [scheduler]),
- ?line {Pid, [scheduler]} = erlang:system_profile(),
- ?line {Pid, [scheduler]} = erlang:system_profile(undefined, []),
+ undefined = erlang:system_profile(Pid, [scheduler]),
+ {Pid, [scheduler]} = erlang:system_profile(),
+ {Pid, [scheduler]} = erlang:system_profile(undefined, []),
% Test combined runnable_ports, runnable_procs, scheduler; on and off
- ?line undefined = erlang:system_profile(Pid, [scheduler, runnable_procs, runnable_ports]),
- ?line {Pid, [scheduler,runnable_procs,runnable_ports]} = erlang:system_profile(),
- ?line {Pid, [scheduler,runnable_procs,runnable_ports]} = erlang:system_profile(undefined, []),
+ undefined = erlang:system_profile(Pid, [scheduler, runnable_procs, runnable_ports]),
+ {Pid, [scheduler,runnable_procs,runnable_ports]} = erlang:system_profile(),
+ {Pid, [scheduler,runnable_procs,runnable_ports]} = erlang:system_profile(undefined, []),
% Test turned off and kill process
- ?line undefined = erlang:system_profile(),
- ?line exit(Pid,kill),
+ undefined = erlang:system_profile(),
+ exit(Pid,kill),
ok.
%% Test runnable_procs
@@ -111,25 +112,25 @@ runnable_procs(suite) ->
runnable_procs(doc) ->
["Tests system_profiling with runnable_procs."];
runnable_procs(Config) when is_list(Config) ->
- ?line Pid = start_profiler_process(),
+ Pid = start_profiler_process(),
% start a ring of processes
% FIXME: Set #laps and #nodes in config file
Nodes = 10,
Laps = 10,
- ?line Master = ring(Nodes),
- ?line undefined = erlang:system_profile(Pid, [runnable_procs]),
+ Master = ring(Nodes),
+ undefined = erlang:system_profile(Pid, [runnable_procs]),
% loop a message
- ?line ok = ring_message(Master, message, Laps),
- ?line Events = get_profiler_events(),
- ?line kill_em_all = kill_ring(Master),
- ?line erlang:system_profile(undefined, []),
+ ok = ring_message(Master, message, Laps),
+ Events = get_profiler_events(),
+ kill_em_all = kill_ring(Master),
+ erlang:system_profile(undefined, []),
put(master, Master),
put(laps, Laps),
- ?line true = has_runnable_event(Events),
+ true = has_runnable_event(Events),
Pids = sort_events_by_pid(Events),
- ?line ok = check_events(Pids),
+ ok = check_events(Pids),
erase(),
- ?line exit(Pid,kill),
+ exit(Pid,kill),
ok.
runnable_ports(suite) ->
@@ -137,21 +138,21 @@ runnable_ports(suite) ->
runnable_ports(doc) ->
["Tests system_profiling with runnable_port."];
runnable_ports(Config) when is_list(Config) ->
- ?line Pid = start_profiler_process(),
- ?line undefined = erlang:system_profile(Pid, [runnable_ports]),
- ?line EchoPid = echo(Config),
+ Pid = start_profiler_process(),
+ undefined = erlang:system_profile(Pid, [runnable_ports]),
+ EchoPid = echo(Config),
% FIXME: Set config to number_of_echos
Laps = 10,
put(laps, Laps),
- ?line ok = echo_message(EchoPid, Laps, message),
- ?line Events = get_profiler_events(),
- ?line kill_em_all = kill_echo(EchoPid),
- ?line erlang:system_profile(undefined, []),
- ?line true = has_runnable_event(Events),
+ ok = echo_message(EchoPid, Laps, message),
+ Events = get_profiler_events(),
+ kill_em_all = kill_echo(EchoPid),
+ erlang:system_profile(undefined, []),
+ true = has_runnable_event(Events),
Pids = sort_events_by_pid(Events),
- ?line ok = check_events(Pids),
+ ok = check_events(Pids),
erase(),
- ?line exit(Pid,kill),
+ exit(Pid,kill),
ok.
scheduler(suite) ->
@@ -160,46 +161,68 @@ scheduler(doc) ->
["Tests system_profiling with scheduler."];
scheduler(Config) when is_list(Config) ->
case {erlang:system_info(smp_support), erlang:system_info(schedulers_online)} of
- {false,_} -> ?line {skipped, "No need for scheduler test when smp support is disabled."};
- {_, 1} -> ?line {skipped, "No need for scheduler test when only one scheduler online."};
+ {false,_} -> {skipped, "No need for scheduler test when smp support is disabled."};
+ {_, 1} -> {skipped, "No need for scheduler test when only one scheduler online."};
_ ->
Nodes = 10,
- ?line ok = check_block_system(Nodes),
- ?line ok = check_multi_scheduling_block(Nodes),
- ok
+ ok = check_block_system(Nodes),
+ ok = check_multi_scheduling_block(Nodes)
end.
+% the profiler pid should not be profiled
+dont_profile_profiler(suite) ->
+ [];
+dont_profile_profiler(doc) ->
+ ["Ensure system profiler process is not profiled."];
+dont_profile_profiler(Config) when is_list(Config) ->
+ Pid = start_profiler_process(),
+
+ Nodes = 10,
+ Laps = 10,
+ Master = ring(Nodes),
+ undefined = erlang:system_profile(Pid, [runnable_procs]),
+ % loop a message
+ ok = ring_message(Master, message, Laps),
+ erlang:system_profile(undefined, []),
+ kill_em_all = kill_ring(Master),
+ Events = get_profiler_events(),
+ false = has_profiler_pid_event(Events, Pid),
+
+ exit(Pid,kill),
+ ok.
+
+
%%% Check scheduler profiling
check_multi_scheduling_block(Nodes) ->
- ?line Pid = start_profiler_process(),
- ?line undefined = erlang:system_profile(Pid, [scheduler]),
- ?line {ok, Supervisor} = start_load(Nodes),
- ?line erlang:system_flag(multi_scheduling, block),
- ?line erlang:system_flag(multi_scheduling, unblock),
- ?line {Pid, [scheduler]} = erlang:system_profile(undefined, []),
- ?line Events = get_profiler_events(),
- ?line true = has_scheduler_event(Events),
+ Pid = start_profiler_process(),
+ undefined = erlang:system_profile(Pid, [scheduler]),
+ {ok, Supervisor} = start_load(Nodes),
+ erlang:system_flag(multi_scheduling, block),
+ erlang:system_flag(multi_scheduling, unblock),
+ {Pid, [scheduler]} = erlang:system_profile(undefined, []),
+ Events = get_profiler_events(),
+ true = has_scheduler_event(Events),
stop_load(Supervisor),
- ?line exit(Pid,kill),
+ exit(Pid,kill),
erase(),
ok.
check_block_system(Nodes) ->
- ?line Dummy = spawn(?MODULE, profiler_process, [[]]),
- ?line Pid = start_profiler_process(),
- ?line undefined = erlang:system_profile(Pid, [scheduler]),
- ?line {ok, Supervisor} = start_load(Nodes),
+ Dummy = spawn(?MODULE, profiler_process, [[]]),
+ Pid = start_profiler_process(),
+ undefined = erlang:system_profile(Pid, [scheduler]),
+ {ok, Supervisor} = start_load(Nodes),
% FIXME: remove wait !!
wait(300),
- ?line undefined = erlang:system_monitor(Dummy, [busy_port]),
- ?line {Dummy, [busy_port]} = erlang:system_monitor(undefined, []),
- ?line {Pid, [scheduler]} = erlang:system_profile(undefined, []),
- ?line Events = get_profiler_events(),
- ?line true = has_scheduler_event(Events),
+ undefined = erlang:system_monitor(Dummy, [busy_port]),
+ {Dummy, [busy_port]} = erlang:system_monitor(undefined, []),
+ {Pid, [scheduler]} = erlang:system_profile(undefined, []),
+ Events = get_profiler_events(),
+ true = has_scheduler_event(Events),
stop_load(Supervisor),
- ?line exit(Pid,kill),
- ?line exit(Dummy,kill),
+ exit(Pid,kill),
+ exit(Dummy,kill),
erase(),
ok.
@@ -211,17 +234,17 @@ check_events([Pid | Pids]) ->
Laps = get(laps),
CheckPids = get(pids),
{Events, N} = get_pid_events(Pid),
- ?line ok = check_event_flow(Events),
- ?line ok = check_event_ts(Events),
+ ok = check_event_flow(Events),
+ ok = check_event_ts(Events),
IsMember = lists:member(Pid, CheckPids),
case Pid of
Master ->
io:format("Expected ~p and got ~p profile events from ~p: ok~n", [Laps*2+2, N, Pid]),
- ?line N = Laps*2 + 2,
+ N = Laps*2 + 2,
check_events(Pids);
Pid when IsMember == true ->
io:format("Expected ~p and got ~p profile events from ~p: ok~n", [Laps*2, N, Pid]),
- ?line N = Laps*2,
+ N = Laps*2,
check_events(Pids);
Pid ->
check_events(Pids)
@@ -448,6 +471,12 @@ has_runnable_event(Events) ->
end
end, Events).
+has_profiler_pid_event([], _) -> false;
+has_profiler_pid_event([{profile, Pid, _Activity, _MFA, _TS}|Events], Pid) -> true;
+has_profiler_pid_event([_|Events], Pid) ->
+ has_profiler_pid_event(Events, Pid).
+
+
wait(Time) -> receive after Time -> ok end.
%%%
diff --git a/erts/emulator/test/system_profile_SUITE_data/echo_drv.c b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c
index d968ff06f9..e0b6ff804c 100644
--- a/erts/emulator/test/system_profile_SUITE_data/echo_drv.c
+++ b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c
@@ -9,11 +9,9 @@ static EchoDrvData echo_drv_data, *echo_drv_data_p;
static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command);
static void echo_drv_stop(EchoDrvData *data_p);
-static void echo_drv_output(EchoDrvData *data_p, char *buf, int len);
+static void echo_drv_output(ErlDrvData drv_data, char *buf,
+ ErlDrvSizeT len);
static void echo_drv_finish(void);
-static int echo_drv_control(EchoDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen);
static ErlDrvEntry echo_drv_entry = {
NULL, /* init */
@@ -25,10 +23,21 @@ static ErlDrvEntry echo_drv_entry = {
"echo_drv",
echo_drv_finish,
NULL, /* handle */
- echo_drv_control,
+ NULL, /* control */
NULL, /* timeout */
NULL, /* outputv */
- NULL /* ready_async */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
+
};
DRIVER_INIT(echo_drv)
@@ -51,16 +60,11 @@ static void echo_drv_stop(EchoDrvData *data_p) {
echo_drv_data_p = NULL;
}
-static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) {
+static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
+ EchoDrvData* data_p = (EchoDrvData *) drv_data;
driver_output(data_p->erlang_port, buf, len);
}
static void echo_drv_finish() {
echo_drv_data_p = NULL;
}
-
-static int echo_drv_control(EchoDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen) {
- return 0;
-}
diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl
index bd48a0a7db..4d12e3449c 100644
--- a/erts/emulator/test/time_SUITE.erl
+++ b/erts/emulator/test/time_SUITE.erl
@@ -32,6 +32,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, univ_to_local/1, local_to_univ/1,
bad_univ_to_local/1, bad_local_to_univ/1,
+ univ_to_seconds/1, seconds_to_univ/1,
consistency/1,
now_unique/1, now_update/1, timestamp/1]).
@@ -59,7 +60,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[univ_to_local, local_to_univ, local_to_univ_utc,
- bad_univ_to_local, bad_local_to_univ, consistency,
+ bad_univ_to_local, bad_local_to_univ,
+ univ_to_seconds, seconds_to_univ,
+ consistency,
{group, now}, timestamp].
groups() ->
@@ -162,6 +165,30 @@ bad_test_local_to_univ([Local|Rest]) ->
bad_test_local_to_univ([]) ->
ok.
+
+%% Test universaltime to seconds conversions
+univ_to_seconds(Config) when is_list(Config) ->
+ test_univ_to_seconds(ok_utc_seconds()).
+
+test_univ_to_seconds([{Datetime, Seconds}|DSs]) ->
+ io:format("universaltime = ~p -> seconds = ~p", [Datetime, Seconds]),
+ Seconds = erlang:universaltime_to_posixtime(Datetime),
+ test_univ_to_seconds(DSs);
+test_univ_to_seconds([]) ->
+ ok.
+
+%% Test seconds to universaltime conversions
+seconds_to_univ(Config) when is_list(Config) ->
+ test_seconds_to_univ(ok_utc_seconds()).
+
+test_seconds_to_univ([{Datetime, Seconds}|DSs]) ->
+ io:format("universaltime = ~p <- seconds = ~p", [Datetime, Seconds]),
+ Datetime = erlang:posixtime_to_universaltime(Seconds),
+ test_seconds_to_univ(DSs);
+test_seconds_to_univ([]) ->
+ ok.
+
+
%% Test that the the different time functions return
%% consistent results. (See the test case for assumptions
%% and limitations.)
@@ -453,6 +480,32 @@ dst_dates() ->
{1998, 06, 3},
{1999, 06, 4}].
+%% exakt utc {date(), time()} which corresponds to the same seconds since 1 jan 1970
+%% negative seconds are ok
+%% generated with date --date='1979-05-28 12:30:35 UTC' +%s
+ok_utc_seconds() -> [
+ { {{1970, 1, 1},{ 0, 0, 0}}, 0 },
+ { {{1970, 1, 1},{ 0, 0, 1}}, 1 },
+ { {{1969,12,31},{23,59,59}}, -1 },
+ { {{1920,12,31},{23,59,59}}, -1546300801 },
+ { {{1600,02,19},{15,14,08}}, -11671807552 },
+ { {{1979,05,28},{12,30,35}}, 296742635 },
+ { {{1999,12,31},{23,59,59}}, 946684799 },
+ { {{2000, 1, 1},{ 0, 0, 0}}, 946684800 },
+ { {{2000, 1, 1},{ 0, 0, 1}}, 946684801 },
+
+ { {{2038, 1,19},{03,14,07}}, 2147483647 }, % Sint32 full - 1
+ { {{2038, 1,19},{03,14,08}}, 2147483648 }, % Sint32 full
+ { {{2038, 1,19},{03,14,09}}, 2147483649 }, % Sint32 full + 1
+
+ { {{2106, 2, 7},{ 6,28,14}}, 4294967294 }, % Uint32 full 0xFFFFFFFF - 1
+ { {{2106, 2, 7},{ 6,28,15}}, 4294967295 }, % Uint32 full 0xFFFFFFFF
+ { {{2106, 2, 7},{ 6,28,16}}, 4294967296 }, % Uint32 full 0xFFFFFFFF + 1
+ { {{2012,12, 6},{16,28,08}}, 1354811288 },
+ { {{2412,12, 6},{16,28,08}}, 13977592088 }
+ ].
+
+
%% The following dates should not be near the end or beginning of
%% a month, because they will be used to test when the dates are
%% different in UTC and local time.
diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl
index 0026da4979..f81cab3114 100644
--- a/erts/emulator/test/trace_port_SUITE.erl
+++ b/erts/emulator/test/trace_port_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,8 @@ end_per_testcase(_Func, Config) ->
call_trace(doc) -> "Test sending call trace messages to a port.";
call_trace(Config) when is_list(Config) ->
- case test_server:is_native(?MODULE) of
+ case test_server:is_native(?MODULE) orelse
+ test_server:is_native(lists) of
true ->
{skip,"Native code"};
false ->
@@ -128,7 +129,8 @@ bs_sum_c(<<>>, Acc) -> Acc.
return_trace(doc) -> "Test the new return trace.";
return_trace(Config) when is_list(Config) ->
- case test_server:is_native(?MODULE) of
+ case test_server:is_native(?MODULE) orelse
+ test_server:is_native(lists) of
true ->
{skip,"Native code"};
false ->
diff --git a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c
index 15c4ca11fe..a8d4ede4fe 100644
--- a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c
+++ b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c
@@ -25,12 +25,14 @@ static EchoDrvData echo_drv_data, *echo_drv_data_p;
**/
static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command);
-static void echo_drv_stop(EchoDrvData *data_p);
-static void echo_drv_output(EchoDrvData *data_p, char *buf, int len);
+static void echo_drv_stop(ErlDrvData drv_data);
+static void echo_drv_output(ErlDrvData drv_data, char *buf,
+ ErlDrvSizeT len);
static void echo_drv_finish(void);
-static int echo_drv_control(EchoDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen);
+static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen);
static ErlDrvEntry echo_drv_entry = {
NULL, /* init */
@@ -45,11 +47,19 @@ static ErlDrvEntry echo_drv_entry = {
echo_drv_control,
NULL, /* timeout */
NULL, /* outputv */
- NULL /* ready_async */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL
};
-
-
/* -------------------------------------------------------------------------
** Entry functions
**/
@@ -75,7 +85,8 @@ static void echo_drv_stop(EchoDrvData *data_p) {
echo_drv_data_p = NULL;
}
-static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) {
+static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
+ EchoDrvData* data_p = (EchoDrvData *) drv_data;
driver_output(data_p->erlang_port, buf, len);
switch (data_p->heavy) {
case heavy_off:
@@ -95,9 +106,11 @@ static void echo_drv_finish() {
echo_drv_data_p = NULL;
}
-static int echo_drv_control(EchoDrvData *data_p, unsigned int command,
- char *buf, int len,
- char **rbuf, int rlen) {
+static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen) {
+ EchoDrvData* data_p = (EchoDrvData *) drv_data;
switch (command) {
case 'h':
data_p->heavy = heavy_set;
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 58c36c3bdc..8fe2402ca8 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2011. All Rights Reserved.
+# Copyright Ericsson AB 1998-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,7 @@ my $verbose = 0;
my $hot = 1;
my $num_file_opcodes = 0;
my $wordsize = 32;
+my %defs; # Defines (from command line).
# This is shift counts and mask for the packer.
my $WHOLE_WORD = '';
@@ -96,6 +97,12 @@ my %unnumbered;
my %is_transformed;
#
+# Pre-processor.
+#
+my @if_val;
+my @if_line;
+
+#
# Code transformations.
#
my $te_max_vars = 0; # Max number of variables ever needed.
@@ -223,6 +230,7 @@ while (@ARGV && $ARGV[0] =~ /^-(.*)/) {
($outdir = shift), next if /^outdir/;
($wordsize = shift), next if /^wordsize/;
($verbose = 1), next if /^v/;
+ ($defs{$1} = $2), next if /^D(\w+)=(\w+)/;
die "$0: Bad option: -$_\n";
}
@@ -239,7 +247,43 @@ while (<>) {
}
next if /^\s*$/;
next if /^\#/;
-
+
+ #
+ # Handle %if.
+ #
+ if (/^\%if (\w+)/) {
+ my $name = $1;
+ my $val = $defs{$name};
+ defined $val or error("'$name' is undefined");
+ push @if_val, $val;
+ push @if_line, $.;
+ next;
+ } elsif (/^\%unless (\w+)/) {
+ my $name = $1;
+ my $val = $defs{$name};
+ defined $val or error("'$name' is undefined");
+ push @if_val, !$val;
+ push @if_line, $.;
+ next;
+ } elsif (/^\%else$/) {
+ unless (@if_line) {
+ error("%else without a preceding %if/%unless");
+ }
+ $if_line[$#if_line] = $.;
+ $if_val[$#if_val] = !$if_val[$#if_val];
+ next;
+ } elsif (/^\%endif$/) {
+ unless (@if_line) {
+ error("%endif without a preceding %if/%unless/%else");
+ }
+ pop @if_val;
+ pop @if_line;
+ next;
+ }
+ if (@if_val and not $if_val[$#if_val]) {
+ next;
+ }
+
#
# Handle assignments.
#
@@ -349,7 +393,13 @@ while (<>) {
$unnumbered{$name,$arity} = 1;
}
} continue {
- close(ARGV) if eof(ARGV);
+ if (eof(ARGV)) {
+ close(ARGV);
+ if (@if_line) {
+ error("Unterminated %if/%unless/%else at " .
+ "line $if_line[$#if_line]\n");
+ }
+ }
}
$num_file_opcodes = @gen_opname;
diff --git a/erts/emulator/utils/make_preload b/erts/emulator/utils/make_preload
index d22f08f993..4e329b24f8 100755
--- a/erts/emulator/utils/make_preload
+++ b/erts/emulator/utils/make_preload
@@ -2,7 +2,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
@@ -39,6 +39,7 @@ use File::Basename;
my $gen_rc = 0;
my $gen_old = 0;
my $windres = 0;
+my $msys = 0;
my $file;
my $progname = basename($0);
@@ -49,6 +50,8 @@ while (@ARGV && $ARGV[0] =~ /^-(\w+)/) {
$gen_rc = 1;
} elsif ($opt eq '-windres') {
$windres = 1;
+ } elsif ($opt eq '-msys') {
+ $msys = 1;
} elsif ($opt eq '-old') {
$gen_old = 1;
} else {
@@ -68,7 +71,12 @@ foreach $file (@ARGV) {
unless $file =~ /\.beam$/;
my $module = basename($file, ".beam");
if ($gen_rc) {
- my ($win_file) = split("\n", `(cygpath -d $file 2>/dev/null || cygpath -w $file)`);
+ my $win_file;
+ if ($msys) {
+ ($win_file) = split("\n", `(msys2win_path.sh $file)`);
+ } else {
+ ($win_file) = split("\n", `(cygpath -d $file 2>/dev/null || cygpath -w $file)`);
+ }
$win_file =~ s&\\&\\\\&g;
print "$num ERLANG_CODE \"$win_file\"\n";
push(@modules, " ", -s $file, "L, $num, ",
@@ -79,6 +87,7 @@ foreach $file (@ARGV) {
my $comment = '';
open(FILE, $file) or error("failed to read $file: $!");
+ binmode(FILE);
$_ = <FILE>;
$_ = beam_strip($_);
close(FILE);
diff --git a/erts/emulator/utils/make_tables b/erts/emulator/utils/make_tables
index 918ef62094..91efb4c023 100755
--- a/erts/emulator/utils/make_tables
+++ b/erts/emulator/utils/make_tables
@@ -181,8 +181,7 @@ for ($i = 0; $i < @bif; $i++) {
print "\n";
for ($i = 0; $i < @bif; $i++) {
- my $arity = $bif[$i]->[2];
- my $args = join(', ', 'Process*', ('Eterm') x $arity);
+ my $args = join(', ', 'Process*', 'Eterm*');
print "Eterm $bif[$i]->[3]($args);\n";
print "Eterm wrap_$bif[$i]->[3]($args, UWord *I);\n";
}
@@ -219,28 +218,10 @@ for ($i = 0; $i < @bif; $i++) {
next if $bif[$i]->[3] eq $bif[$i]->[4]; # Skip unwrapped bifs
my $arity = $bif[$i]->[2];
my $func = $bif[$i]->[3];
- my $arg;
print "Eterm\n";
- print "wrap_$func(Process* p";
- for ($arg = 1; $arg <= $arity; $arg++) {
- print ", Eterm arg$arg";
- }
- print ", UWord *I)\n";
+ print "wrap_$func(Process* p, Eterm* args, UWord* I)\n";
print "{\n";
- print " return erts_bif_trace($i, p";
- for ($arg = 1; $arg <= 3; $arg++) {
- if ($arg <= $arity) {
- print ", arg$arg";
- #} elsif ($arg == ($arity + 1)) {
- # # Place I in correct position
- # print ", (Eterm) I";
- } else {
- print ", 0";
- }
- }
- # I is always last, as well as in the correct position
- # Note that "last" and "correct position" may be the same...
- print ", I);\n";
+ print " return erts_bif_trace($i, p, args, I);\n";
print "}\n\n";
}
@@ -261,19 +242,9 @@ for ($i = 0; $i < @bif; $i++) {
my $orig_func = $1;
$orig_func = $implementation[$i] if $implementation[$i];
print "Eterm\n";
- print "$func(Process* p";
- for ($arg = 1; $arg <= $arity; $arg++) {
- print ", Eterm arg$arg";
- }
- print ")\n";
+ print "$func(Process* p, Eterm* BIF__ARGS)\n";
print "{\n";
- print " return $orig_func(p";
- for ($arg = 1; $arg <= 3; $arg++) {
- if ($arg <= $arity) {
- print ", arg$arg";
- }
- }
- print ");\n";
+ print " return $orig_func(p, BIF__ARGS);\n";
print "}\n\n";
}
diff --git a/erts/emulator/valgrind/suppress.patched.3.6.0 b/erts/emulator/valgrind/suppress.patched.3.6.0
new file mode 100644
index 0000000000..62ba032520
--- /dev/null
+++ b/erts/emulator/valgrind/suppress.patched.3.6.0
@@ -0,0 +1,359 @@
+# Valgrind suppression file updated to support the patched
+# Valgrind used in daily builds on ahmed.
+
+{
+ libc internal error
+ Memcheck:Addr8
+ obj:/lib64/ld-2.3.5.so
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:_dl_start
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr4
+ fun:__sigjmp_save
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__sigsetjmp
+ fun:__libc_start_main
+ obj:*
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:chkio_drv_timeout
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:io_ready_exit_drv_control
+ fun:erts_port_control
+ fun:port_control_3
+ fun:process_main
+}
+{
+ Leak in libc putenv
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:__add_to_environ
+ fun:putenv
+ fun:erts_sys_putenv
+ fun:os_putenv_2
+ ...
+}
+{
+ Leak in libc putenv
+ Memcheck:Leak
+ ...
+ fun:erts_alloc
+ fun:erts_sys_putenv
+ fun:os_putenv_2
+ ...
+}
+{
+ erronous warning
+ Memcheck:Leak
+ fun:malloc
+ fun:erts_sys_alloc
+ ...
+ fun:fix_core_alloc
+ fun:erts_init_fix_alloc
+ fun:erts_alloc_init
+ fun:early_init
+ fun:erl_start
+}
+{
+ pthread internal error
+ Memcheck:Param
+ futex(utime)
+ fun:__lll_mutex_unlock_wake
+}
+{
+ libc internal error
+ Memcheck:Param
+ socketcall.sendto(msg)
+ ...
+ fun:getifaddrs
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+PossiblyLost
+fun:realloc
+fun:erts_sys_realloc
+...
+fun:erts_realloc_fnf
+fun:erts_bin_realloc_fnf
+fun:driver_realloc_binary
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:erts_bin_drv_alloc_fnf
+fun:driver_alloc_binary
+}
+{
+pthread leak or erroneous valgrind warning
+Memcheck:Leak
+fun:calloc
+fun:allocate_dtv
+fun:_dl_allocate_tls
+fun:pthread_create@@GLIBC_2.2.5
+}
+{
+pthread leak or erroneous valgrind warning
+Memcheck:Leak
+fun:calloc
+fun:_dl_allocate_tls
+fun:pthread_create@@GLIBC_2.2.5
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_slow
+fun:deflate
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_fast
+fun:deflate
+}
+{
+zlib; ok accordnig to zlib (this one popped up with valgrind-3.6.0)
+Memcheck:Cond
+fun:deflate_slow
+fun:deflate
+fun:zlib_deflate
+fun:zlib_ctl
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_init_scheduling
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:init_db
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; sometimes pointer into block
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:driver_alloc
+fun:get_bufstk
+fun:alloc_buffer
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_nnmod
+ fun:BN_mod_inverse
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+}
+{
+ Crypto internal...
+ Memcheck:Value8
+ fun:BN_mod_exp_mont_consttime
+ fun:generate_key
+ fun:dh_generate_key_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+ fun:start_thread
+ fun:clone
+}
+
+{
+erts_bits_init_state; Why is this needed?
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_bits_init_state
+fun:erts_init_scheduling
+fun:erl_init
+fun:erl_start
+fun:main
+}
+
+{
+Prebuilt constant terms in os_info_init
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:os_info_init
+fun:erts_bif_info_init
+fun:erl_init
+fun:erl_start
+fun:main
+}
+
+{
+Permanent cache aligned malloc for array of mseg allocators
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_mseg_init
+fun:erts_alloc_init
+fun:early_init
+fun:erl_start
+fun:main
+}
+
+{
+Early permanent cache aligned erl_process:aux_work_tmo
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:aux_work_timeout_early_init
+fun:erts_early_init_scheduling
+fun:early_init
+fun:erl_start
+fun:main
+}
+
+{
+Early permanent cache aligned ts_event_pool
+Memcheck:Leak
+PossiblyLost
+fun:malloc
+fun:erts_sys_alloc
+fun:erts_alloc_fnf
+fun:ethr_std_alloc
+fun:ts_event_pool
+fun:init_ts_event_alloc
+fun:ethr_late_init_common__
+fun:ethr_late_init
+fun:erts_thr_late_init
+fun:early_init
+fun:erl_start
+fun:main
+}
+
+{
+Harmless leak of ErtsThrPrgrData from async threads in exiting emulator
+Memcheck:Leak
+...
+fun:erts_alloc
+fun:erts_thr_progress_register_unmanaged_thread
+fun:async_thread_init
+fun:async_main
+...
+}
+
diff --git a/erts/emulator/valgrind/suppress.standard b/erts/emulator/valgrind/suppress.standard
new file mode 100644
index 0000000000..5a129bfd10
--- /dev/null
+++ b/erts/emulator/valgrind/suppress.standard
@@ -0,0 +1,317 @@
+{
+ libc internal error
+ Memcheck:Addr8
+ obj:/lib64/ld-2.3.5.so
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:_dl_start
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr4
+ fun:__sigjmp_save
+ fun:__libc_start_main
+ obj:*
+}
+{
+ libc internal error
+ Memcheck:Addr8
+ fun:__sigsetjmp
+ fun:__libc_start_main
+ obj:*
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:chkio_drv_timeout
+}
+{
+ Intentional error in testcase
+ Memcheck:Param
+ pipe(filedes)
+ fun:pipe
+ fun:io_ready_exit_drv_control
+ fun:erts_port_control
+ fun:port_control_3
+ fun:process_main
+}
+{
+ Leak in libc putenv
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:__add_to_environ
+ fun:putenv
+ fun:erts_sys_putenv
+ fun:os_putenv_2
+ ...
+}
+{
+ Leak in libc putenv
+ Memcheck:Leak
+ ...
+ fun:erts_alloc
+ fun:erts_sys_putenv
+ fun:os_putenv_2
+ ...
+}
+{
+ erronous warning
+ Memcheck:Leak
+ fun:malloc
+ fun:erts_sys_alloc
+ fun:fix_core_alloc
+ fun:erts_init_fix_alloc
+ fun:erts_alloc_init
+ fun:early_init
+ fun:erl_start
+}
+{
+ pthread internal error
+ Memcheck:Param
+ futex(utime)
+ fun:__lll_mutex_unlock_wake
+}
+{
+ libc internal error
+ Memcheck:Param
+ socketcall.sendto(msg)
+ ...
+ fun:getifaddrs
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+fun:realloc
+fun:erts_sys_realloc
+...
+fun:erts_realloc_fnf
+fun:erts_bin_realloc_fnf
+fun:driver_realloc_binary
+}
+{
+inet_drv; pointer inside allocated block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:erts_bin_drv_alloc_fnf
+fun:driver_alloc_binary
+}
+{
+pthread leak or erroneous valgrind warning
+Memcheck:Leak
+fun:calloc
+fun:allocate_dtv
+fun:_dl_allocate_tls
+fun:pthread_create@@GLIBC_2.2.5
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_slow
+fun:deflate
+}
+{
+zlib; ok according to zlib developers
+Memcheck:Cond
+fun:longest_match
+fun:deflate_fast
+fun:deflate
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:erts_init_scheduling
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:init_db
+fun:erl_init
+fun:erl_start
+fun:main
+}
+{
+No leak; sometimes pointer into block
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc_fnf
+fun:driver_alloc
+fun:get_bufstk
+fun:alloc_buffer
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Cond
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/crypto.valgrind.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/libcrypto.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/openssl.*
+}
+{
+ Crypto internal...
+Memcheck:Value8
+obj:*/ssleay.*
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+}
+{
+ Crypto internal...
+ Memcheck:Cond
+ fun:memset
+ fun:BN_lshift
+ fun:BN_div
+ fun:BN_nnmod
+ fun:BN_mod_inverse
+ fun:BN_MONT_CTX_set
+ fun:BN_is_prime_fasttest_ex
+ fun:BN_generate_prime_ex
+ fun:DH_generate_parameters_ex
+ fun:DH_generate_parameters
+ fun:dh_generate_parameters_nif
+ fun:process_main
+}
+{
+ Crypto internal...
+ Memcheck:Value8
+ fun:BN_mod_exp_mont_consttime
+ fun:generate_key
+ fun:dh_generate_key_nif
+ fun:process_main
+ fun:sched_thread_func
+ fun:thr_wrapper
+ fun:start_thread
+ fun:clone
+}
+
+{
+Prebuilt constant terms in os_info_init (PossiblyLost)
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+...
+fun:erts_alloc
+fun:os_info_init
+fun:erts_bif_info_init
+fun:erl_init
+fun:erl_start
+fun:main
+}
+
+{
+Permanent cache aligned malloc for array of mseg allocators
+Memcheck:Leak
+fun:malloc
+fun:erts_mseg_init
+fun:erts_alloc_init
+fun:early_init
+fun:erl_start
+fun:main
+}
+
+{
+Early permanent cache aligned erl_process:aux_work_tmo
+Memcheck:Leak
+fun:malloc
+fun:aux_work_timeout_early_init
+fun:erts_early_init_scheduling
+fun:early_init
+fun:erl_start
+fun:main
+}
+
+{
+Early permanent cache aligned ts_event_pool
+Memcheck:Leak
+fun:malloc
+fun:erts_sys_alloc
+fun:erts_alloc_fnf
+fun:ethr_std_alloc
+fun:ts_event_pool
+fun:init_ts_event_alloc
+fun:ethr_late_init_common__
+fun:ethr_late_init
+fun:erts_thr_late_init
+fun:early_init
+fun:erl_start
+fun:main
+}
+
+{
+Harmless leak of ErtsThrPrgrData from async threads in exiting emulator
+Memcheck:Leak
+...
+fun:erts_alloc
+fun:erts_thr_progress_register_unmanaged_thread
+fun:async_thread_init
+fun:async_main
+...
+}
+
diff --git a/erts/emulator/zlib/Makefile b/erts/emulator/zlib/Makefile
deleted file mode 100644
index def8e1aa47..0000000000
--- a/erts/emulator/zlib/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Invoke with GNU make or clearmake -C gnu.
-#
-
-include $(ERL_TOP)/make/run_make.mk
diff --git a/erts/emulator/zlib/Makefile.in b/erts/emulator/zlib/Makefile.in
deleted file mode 100644
index b44a87551d..0000000000
--- a/erts/emulator/zlib/Makefile.in
+++ /dev/null
@@ -1,102 +0,0 @@
-# Makefile for zlib
-# Copyright (C) 1995-1996 Jean-loup Gailly.
-# For conditions of distribution and use, see copyright notice in zlib.h
-
-# %ExternalCopyright%
-
-# To compile and test, type:
-# ./configure; make test
-# The call of configure is optional if you don't have special requirements
-
-# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
-# make install
-# To install in $HOME instead of /usr/local, use:
-# make install prefix=$HOME
-
-ARFLAGS = rc
-CFLAGS = $(subst -O2, -O3, @CFLAGS@ @DEFS@ @EMU_THR_DEFS@)
-#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
-#CFLAGS=-g -DDEBUG
-#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
-# -Wstrict-prototypes -Wmissing-prototypes
-
-VER=1.0.4
-
-O = adler32.o compress.o crc32.o uncompr.o deflate.o trees.o \
- zutil.o inflate.o inftrees.o inffast.o
-OBJS = $(O:%=$(OBJDIR)/%)
-
-
-#### Begin OTP targets
-
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),gcov)
-CFLAGS = -O0 -fprofile-arcs -ftest-coverage @DEBUG_CFLAGS@ @DEFS@ @EMU_THR_DEFS@
-else # gcov
-ifeq ($(TYPE),debug)
-CFLAGS = @DEBUG_CFLAGS@ @DEFS@ @EMU_THR_DEFS@
-endif # debug
-endif # gcov
-
-# On windows we *need* a separate zlib during debug build
-OBJDIR= $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-ifeq ($(TARGET), win32)
-LIBRARY=$(OBJDIR)/z.lib
-else
-LIBRARY=$(OBJDIR)/libz.a
-endif
-
-all: $(LIBRARY)
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
-
-tests release_tests:
-
-docs release_docs release_docs_spec:
-
-clean:
- rm -f $(OBJS) $(OBJDIR)/libz.a
-
-#### end OTP targets
-
-ifeq ($(TARGET), win32)
-$(LIBRARY): $(OBJS)
- $(AR) -out:$@ $(OBJS)
-else
-$(LIBRARY): $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
- -@ ($(RANLIB) $@ || true) 2>/dev/null
-endif
-
-$(OBJDIR)/%.o: %.c
- $(CC) -c $(CFLAGS) -o $@ $<
-
-# DO NOT DELETE THIS LINE -- make depend depends on it.
-
-adler32.o: zlib.h zconf.h
-compress.o: zlib.h zconf.h
-crc32.o: zlib.h zconf.h
-deflate.o: deflate.h zutil.h zlib.h zconf.h
-example.o: zlib.h zconf.h
-gzio.o: zutil.h zlib.h zconf.h
-infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
-infcodes.o: zutil.h zlib.h zconf.h
-infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
-inffast.o: zutil.h zlib.h zconf.h inftrees.h
-inffast.o: infblock.h infcodes.h infutil.h inffast.h
-inflate.o: zutil.h zlib.h zconf.h infblock.h
-inftrees.o: zutil.h zlib.h zconf.h inftrees.h
-infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
-minigzip.o: zlib.h zconf.h
-trees.o: deflate.h zutil.h zlib.h zconf.h
-uncompr.o: zlib.h zconf.h
-zutil.o: zutil.h zlib.h zconf.h
diff --git a/erts/emulator/zlib/zlib.mk b/erts/emulator/zlib/zlib.mk
new file mode 100644
index 0000000000..fa1f159fae
--- /dev/null
+++ b/erts/emulator/zlib/zlib.mk
@@ -0,0 +1,74 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+# ----------------------------------------------------
+# Make include file for zlib
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2011-2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# ----------------------------------------------------
+# Copyright for zlib itself see copyright notice in zlib.h
+
+ZLIB_FILES = \
+ adler32 \
+ compress \
+ crc32 \
+ uncompr \
+ deflate \
+ trees \
+ zutil \
+ inflate \
+ inftrees \
+ inffast
+
+# On windows we *need* a separate zlib during debug build
+ZLIB_OBJDIR = $(ERL_TOP)/erts/emulator/zlib/obj/$(TARGET)/$(TYPE)
+
+ZLIB_OBJS = $(ZLIB_FILES:%=$(ZLIB_OBJDIR)/%.o)
+ZLIB_SRC = $(ZLIB_FILES:%=zlib/%.c)
+
+ifeq ($(TARGET), win32)
+ZLIB_LIBRARY = $(ZLIB_OBJDIR)/z.lib
+else
+ZLIB_LIBRARY = $(ZLIB_OBJDIR)/libz.a
+endif
+
+
+ifeq ($(TYPE),gcov)
+ZLIB_CFLAGS = -O0 -fprofile-arcs -ftest-coverage $(DEBUG_CFLAGS) $(DEFS) $(THR_DEFS)
+else # gcov
+ifeq ($(TYPE),debug)
+ZLIB_CFLAGS = $(DEBUG_CFLAGS) $(DEFS) $(THR_DEFS)
+else # debug
+ZLIB_CFLAGS = $(subst -O2, -O3, $(CONFIGURE_CFLAGS) $(DEFS) $(THR_DEFS))
+#ZLIB_CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#ZLIB_CFLAGS=-g -DDEBUG
+#ZLIB_CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+endif # debug
+endif # gcov
+
+ifeq ($(TARGET), win32)
+$(ZLIB_LIBRARY): $(ZLIB_OBJS)
+ $(AR) -out:$@ $(ZLIB_OBJS)
+else
+$(ZLIB_LIBRARY): $(ZLIB_OBJS)
+ $(AR) $(ARFLAGS) $@ $(ZLIB_OBJS)
+ -@ ($(RANLIB) $@ || true) 2>/dev/null
+endif
+
+$(ZLIB_OBJDIR)/%.o: zlib/%.c
+ $(CC) -c $(ZLIB_CFLAGS) -o $@ $<
diff --git a/erts/epmd/src/Makefile.in b/erts/epmd/src/Makefile.in
index 2f5296a5e8..577fc77c13 100644
--- a/erts/epmd/src/Makefile.in
+++ b/erts/epmd/src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2010. All Rights Reserved.
+# Copyright Ericsson AB 1998-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,7 @@ PURIFY =
TYPEMARKER = .debug
TYPE_FLAGS = -DDEBUG @DEBUG_FLAGS@
else
+
ifeq ($(TYPE),purify)
PURIFY = purify
TYPEMARKER =
@@ -33,6 +34,8 @@ else
TYPE_FLAGS = -O2 -DPURIFY
endif
else
+
+override TYPE = opt
PURIFY =
TYPEMARKER =
ifeq ($(findstring ose,$(TARGET)),ose)
@@ -65,6 +68,8 @@ ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPE
endif
endif
+ERTS_LIB = $(ERL_TOP)/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
+
CC = @CC@
WFLAGS = @WFLAGS@
CFLAGS = @CFLAGS@ @DEFS@ $(TYPE_FLAGS) $(WFLAGS) $(ERTS_INCL)
@@ -106,7 +111,7 @@ EPMD_OBJS = $(OBJDIR)/epmd.o \
#---------------------------------
-all: erts_lib $(BINDIR)/$(EPMD)
+all: $(BINDIR)/$(EPMD)
docs:
@@ -122,21 +127,20 @@ clean:
# Objects & executables
#
-$(BINDIR)/$(EPMD): $(EPMD_OBJS)
+$(BINDIR)/$(EPMD): $(EPMD_OBJS) $(ERTS_LIB)
$(PURIFY) $(LD) $(LDFLAGS) -o $@ $(EPMD_OBJS) $(LIBS)
$(OBJDIR)/%.o: %.c epmd.h epmd_int.h
$(CC) $(CFLAGS) $(EPMD_FLAGS) -o $@ -c $<
-erts_lib:
+$(ERTS_LIB):
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: all
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/bin
- $(INSTALL_PROGRAM) $(INSTALL_PROGS) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/bin"
+ $(INSTALL_PROGRAM) $(INSTALL_PROGS) "$(RELEASE_PATH)/erts-$(VSN)/bin"
release_docs_spec:
-
diff --git a/erts/epmd/test/Makefile b/erts/epmd/test/Makefile
index 54688fd90b..868b1c023b 100644
--- a/erts/epmd/test/Makefile
+++ b/erts/epmd/test/Makefile
@@ -71,10 +71,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: opt
- $(INSTALL_DIR) $(RELEPMDDIR)
+ $(INSTALL_DIR) "$(RELEPMDDIR)"
$(INSTALL_DATA) epmd.spec epmd.spec.vxworks $(ERL_FILES) \
- $(EMAKEFILE) $(RELEPMDDIR)
- chmod -R u+w $(RELEPMDDIR)
+ $(EMAKEFILE) "$(RELEPMDDIR)"
+ chmod -R u+w "$(RELEPMDDIR)"
release_docs_spec:
diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl
index 6889ec0b34..3f31cd979c 100644
--- a/erts/epmd/test/epmd_SUITE.erl
+++ b/erts/epmd/test/epmd_SUITE.erl
@@ -931,7 +931,7 @@ epmdrun(Epmd,Args0) ->
O ->
" "++O
end,
- osrun(Epmd ++ Args ++ " " ?EPMDARGS " -port " ++ integer_to_list(?PORT)).
+ osrun("\"" ++ Epmd ++ "\"" ++ Args ++ " " ?EPMDARGS " -port " ++ integer_to_list(?PORT)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index 4754328c0b..83fe97df8e 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+# Copyright Ericsson AB 1996-2012. All Rights Reserved.
#
# The 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,13 +22,14 @@ include $(ERL_TOP)/make/target.mk
ERTS_LIB_TYPEMARKER=.$(TYPE)
USING_MINGW=@MIXED_CYGWIN_MINGW@
-USING_VC=@MIXED_CYGWIN_VC@
+USING_VC=@MIXED_VC@
ifeq ($(TYPE),debug)
PURIFY =
TYPEMARKER = .debug
TYPE_FLAGS = -DDEBUG @DEBUG_FLAGS@
else
+
ifeq ($(TYPE),purify)
PURIFY = purify
TYPEMARKER =
@@ -38,6 +39,8 @@ else
TYPE_FLAGS = -g -O2 -DPURIFY
endif
else
+
+override TYPE=opt
PURIFY =
TYPEMARKER =
ERTS_LIB_TYPEMARKER=
@@ -61,6 +64,9 @@ LD = @LD@
LIBS = @LIBS@
LDFLAGS = @LDFLAGS@
+# For clock_gettime in heart
+RTLIBS = @LIBRT@
+
ifeq ($(TARGET),win32)
ifeq ($(TYPE),debug)
CFLAGS = $(subst -O2,-g,@CFLAGS@ @DEFS@ $(TYPE_FLAGS) @WFLAGS@ -I$(SYSDIR) \
@@ -101,6 +107,8 @@ else
ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ -lm
endif
+ERTS_LIB = $(ERL_TOP)/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
+
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -161,9 +169,8 @@ ERLSRV_OBJECTS= \
$(OBJDIR)/erlsrv_main.o \
$(OBJDIR)/erlsrv_util.o \
$(OBJDIR)/erlsrv_logmess.res
-MC_OUTPUTS= \
- $(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.rc
- MT_FLAG="-MT"
+MC_OUTPUTS=$(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.rc
+MT_FLAG="-MT"
else
ERLRES_OBJ=erl_res.o
ERLSRV_OBJECTS= \
@@ -173,9 +180,8 @@ ERLSRV_OBJECTS= \
$(OBJDIR)/erlsrv_main.o \
$(OBJDIR)/erlsrv_util.o \
$(OBJDIR)/erlsrv_logmess.o
-MC_OUTPUTS= \
- $(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.res
- MT_FLAG="-MD"
+MC_OUTPUTS=$(OBJDIR)/erlsrv_logmess.h $(OBJDIR)/erlsrv_logmess.res
+MT_FLAG="-MD"
endif
INET_GETHOST = $(BINDIR)/inet_gethost.exe
INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer.exe $(BINDIR)/dialyzer.exe $(BINDIR)/erlc.exe $(BINDIR)/start_erl.exe $(BINDIR)/escript.exe $(BINDIR)/ct_run.exe
@@ -232,14 +238,17 @@ endif
endif
endif
-etc: erts_lib $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN)
+.PHONY: etc
+etc: $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN)
# erlexec needs the erts_internal library...
-erts_lib:
+$(ERTS_LIB):
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
+.PHONY: docs
docs:
+.PHONY: clean
clean:
ifneq ($(INSTALL_PROGS),)
rm -f $(INSTALL_PROGS)
@@ -278,85 +287,9 @@ endif
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/vxcall.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/erl.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/werl.o
+ rm -f $(TEXTFILES)
rm -f *~ core
-#
-# Objects & executables
-#
-#$(OBJDIR)/%.o: %.c
-# $(CC) $(CFLAGS) -o $@ -c $<
-#
-#$(OBJDIR)/%.o: ../unix/%.c
-# $(CC) $(CFLAGS) -o $@ -c $<
-#
-#$(BINDIR)/%: $(OBJDIR)/%.o
-# $(PURIFY) $(LD) $(LDFLAGS) -o $@ $< $(LIBS)
-
-$(OBJDIR)/inet_gethost.o: inet_gethost.c
- $(CC) $(CFLAGS) -o $@ -c inet_gethost.c
-
-$(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ)
- $(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS)
-
-$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS)
-
-$(OBJDIR)/run_erl.o: ../unix/run_erl.c
- $(CC) $(CFLAGS) -o $@ -c ../unix/run_erl.c
-
-$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o
-
-$(OBJDIR)/to_erl.o: ../unix/to_erl.c
- $(CC) $(CFLAGS) -o $@ -c ../unix/to_erl.c
-
-$(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
- $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
-
-$(OBJDIR)/dyn_erl.o: ../unix/dyn_erl.c
- $(CC) $(CFLAGS) -o $@ -c ../unix/dyn_erl.c
-
-$(OBJDIR)/safe_string.o: ../unix/safe_string.c
- $(CC) $(CFLAGS) -o $@ -c ../unix/safe_string.c
-
-ifneq ($(TARGET),win32)
-$(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/$(ERLEXEC).o $(ERTS_INTERNAL_LIBS)
-
-$(OBJDIR)/$(ERLEXEC).o: $(ERLEXECDIR)/$(ERLEXEC).c
- $(CC) -I$(EMUDIR) $(CFLAGS) -o $@ -c $(ERLEXECDIR)/$(ERLEXEC).c
-endif
-$(BINDIR)/erlc@EXEEXT@: $(OBJDIR)/erlc.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
-
-$(OBJDIR)/erlc.o: erlc.c
- $(CC) $(CFLAGS) -o $@ -c erlc.c
-
-$(BINDIR)/dialyzer@EXEEXT@: $(OBJDIR)/dialyzer.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
-
-$(OBJDIR)/dialyzer.o: dialyzer.c
- $(CC) $(CFLAGS) -o $@ -c dialyzer.c
-
-$(BINDIR)/typer@EXEEXT@: $(OBJDIR)/typer.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
-
-$(OBJDIR)/typer.o: typer.c
- $(CC) $(CFLAGS) -o $@ -c typer.c
-
-$(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
-
-$(OBJDIR)/escript.o: escript.c
- $(CC) $(CFLAGS) -o $@ -c escript.c
-
-$(BINDIR)/ct_run@EXEEXT@: $(OBJDIR)/ct_run.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/ct_run.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
-
-$(OBJDIR)/ct_run.o: ct_run.c
- $(CC) $(CFLAGS) -o $@ -c ct_run.c
-
-
#------------------------------------------------------------------------
# Windows specific targets
# The windows platform is quite different from the others. erl/werl are small C programs
@@ -367,7 +300,7 @@ $(OBJDIR)/ct_run.o: ct_run.c
ifeq ($(TARGET),win32)
-$(BINDIR)/$(ERLEXEC): $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ)
+$(BINDIR)/$(ERLEXEC): $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) $(ERTS_LIB)
$(LD) -dll $(LDFLAGS) -o $@ $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) $(ERTS_INTERNAL_LIBS)
$(BINDIR)/erl@EXEEXT@: $(OBJDIR)/erl.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ)
@@ -382,58 +315,75 @@ $(BINDIR)/start_erl@EXEEXT@: $(OBJDIR)/start_erl.o
$(BINDIR)/Install@EXEEXT@: $(OBJDIR)/Install.o $(OBJDIR)/init_file.o
$(LD) $(LDFLAGS) -o $@ $(OBJDIR)/Install.o $(OBJDIR)/init_file.o
+# The service expects to be compiled with $(MT_FLAG) flag.
$(BINDIR)/erlsrv@EXEEXT@: $(ERLSRV_OBJECTS)
$(LD) $(LDFLAGS) $(MT_FLAG) -o $@ $(ERLSRV_OBJECTS)
-# The service expects to be compiled with $(MT_FLAG) flag.
-
-$(OBJDIR)/%.o: $(WINETC)/erlsrv/%.c $(ERLSRV_HEADERS)
- $(CC) $(CFLAGS) $(MT_FLAG) -o $@ -c $<
-
-$(OBJDIR)/erlsrv_util.o: $(WINETC)/erlsrv/erlsrv_util.c $(ERLSRV_HEADERS) \
-$(OBJDIR)/erlsrv_logmess.h
- $(CC) $(CFLAGS) -I$(OBJDIR) $(MT_FLAG) -o $@ -c $<
+# To fix a spooky parallel make build problem on Windows there are some
+# false dependencies on the $(MC), $(RC) and .o rules. The theory behind
+# is that the $(MC) and/or $(RC) compilers seems to temporarily create and
+# destroy a toplevel file vc100.pdb that simultaneous ordinary compilations
+# (that have been by flags explicitly ordered to not use .pdb files)
+# gets upset when that file vanishes from under their feet.
+#
+# The false dependencies are targeted to make make (pun intended) run
+# the $(MC) and $(RC) compilations to completion before all others.
+
+LOGMESS_GENERATED = $(OBJDIR)/LOGMESS-GENERATED
+$(MC_OUTPUTS): $(LOGMESS_GENERATED)
+$(LOGMESS_GENERATED): $(WINETC)/erlsrv/erlsrv_logmess.mc
+ $(MC) -o $(OBJDIR) $(WINETC)/erlsrv/erlsrv_logmess.mc && \
+ echo $? >$(LOGMESS_GENERATED)
+
+$(OBJDIR)/$(ERLRES_OBJ): $(WINETC)/erl.rc $(WINETC)/erlang.ico \
+ $(WINETC)/erl_icon.ico $(WINETC)/hrl_icon.ico \
+ $(WINETC)/beam_icon.ico $(LOGMESS_GENERATED)
+ $(RC) -o $@ -I$(WINETC) $(WINETC)/erl.rc
ifeq ($(USING_VC), yes)
-$(OBJDIR)/erlsrv_logmess.res: $(OBJDIR)/erlsrv_logmess.rc
+RC_GENERATED = $(OBJDIR)/erlsrv_logmess.res
+$(RC_GENERATED): $(OBJDIR)/erlsrv_logmess.rc $(OBJDIR)/$(ERLRES_OBJ)
$(RC) -o $(OBJDIR)/erlsrv_logmess.res -I$(OBJDIR) $(OBJDIR)/erlsrv_logmess.rc
else
-$(OBJDIR)/erlsrv_logmess.o: $(OBJDIR)/erlsrv_logmess.res
+RC_GENERATED = $(OBJDIR)/erlsrv_logmess.o
+$(RC_GENERATED): $(OBJDIR)/erlsrv_logmess.res $(OBJDIR)/$(ERLRES_OBJ)
$(RC) -o $(OBJDIR)/erlsrv_logmess.o -I$(OBJDIR) $(OBJDIR)/erlsrv_logmess.res
endif
-$(MC_OUTPUTS): $(WINETC)/erlsrv/erlsrv_logmess.mc
- $(MC) -o $(OBJDIR) $(WINETC)/erlsrv/erlsrv_logmess.mc
+# The service expects to be compiled with $(MT_FLAG) flag.
+$(OBJDIR)/%.o: $(WINETC)/erlsrv/%.c $(ERLSRV_HEADERS) $(RC_GENERATED)
+ $(CC) $(CFLAGS) $(MT_FLAG) -o $@ -c $<
+
+$(OBJDIR)/erlsrv_util.o: $(WINETC)/erlsrv/erlsrv_util.c $(ERLSRV_HEADERS) \
+ $(OBJDIR)/erlsrv_logmess.h $(RC_GENERATED)
+ $(CC) $(CFLAGS) -I$(OBJDIR) $(MT_FLAG) -o $@ -c $<
-$(OBJDIR)/werl.o: $(WINETC)/erl.c
+$(OBJDIR)/werl.o: $(WINETC)/erl.c $(WINETC)/init_file.h $(RC_GENERATED)
$(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \
-DWIN32_WERL -o $@ -c $(WINETC)/erl.c
-$(OBJDIR)/erl.o: $(WINETC)/erl.c
+$(OBJDIR)/erl.o: $(WINETC)/erl.c $(WINETC)/init_file.h $(RC_GENERATED)
$(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \
-o $@ -c $(WINETC)/erl.c
-$(OBJDIR)/erlexec.o: $(ERLEXECDIR)/erlexec.c
+$(OBJDIR)/erlexec.o: $(ERLEXECDIR)/erlexec.c $(RC_GENERATED)
$(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \
-o $@ -c $(ERLEXECDIR)/erlexec.c
-$(OBJDIR)/win_erlexec.o: $(WINETC)/win_erlexec.c
+$(OBJDIR)/win_erlexec.o: $(WINETC)/win_erlexec.c $(RC_GENERATED)
$(CC) $(CFLAGS) -DBUILD_TYPE=\"-$(TYPE)\" -DERL_RUN_SHARED_LIB=1 \
-o $@ -c $(WINETC)/win_erlexec.c
-$(OBJDIR)/init_file.o: $(WINETC)/init_file.c $(WINETC)/init_file.h
+$(OBJDIR)/init_file.o: $(WINETC)/init_file.c $(WINETC)/init_file.h $(RC_GENERATED)
$(CC) $(CFLAGS) -o $@ -c $(WINETC)/init_file.c
-$(OBJDIR)/Install.o: $(WINETC)/Install.c $(WINETC)/init_file.h
+$(OBJDIR)/Install.o: $(WINETC)/Install.c $(WINETC)/init_file.h $(RC_GENERATED)
$(CC) $(CFLAGS) -o $@ -c $(WINETC)/Install.c
-$(OBJDIR)/$(ERLRES_OBJ): $(WINETC)/erl.rc $(WINETC)/erlang.ico $(WINETC)/erl_icon.ico $(WINETC)/hrl_icon.ico $(WINETC)/beam_icon.ico
- $(RC) -o $@ -I$(WINETC) $(WINETC)/erl.rc
-
-$(OBJDIR)/start_erl.o: $(WINETC)/start_erl.c
+$(OBJDIR)/start_erl.o: $(WINETC)/start_erl.c $(RC_GENERATED)
$(CC) $(CFLAGS) -o $@ -c $(WINETC)/start_erl.c
-$(ENTRY_OBJ): $(ENTRY_SRC)
+$(ENTRY_OBJ): $(ENTRY_SRC) $(RC_GENERATED)
$(CC) $(CFLAGS) -o $@ -c $(ENTRY_SRC)
Install.ini: ../$(TARGET)/Install.src ../../vsn.mk $(TARGET)/Makefile
@@ -442,6 +392,8 @@ Install.ini: ../$(TARGET)/Install.src ../../vsn.mk $(TARGET)/Makefile
../$(TARGET)/Install.src > Install.ini
+else
+RC_GENERATED =
endif
#---------------------------------------------------------
# End of windows specific targets.
@@ -467,9 +419,9 @@ else
$(BINDIR)/heart@EXEEXT@: $(OBJDIR)/heart.o $(ENTRY_OBJ)
$(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/heart.o \
- $(ENTRY_OBJ) $(WINDSOCK)
+ $(RTLIBS) $(ENTRY_OBJ) $(WINDSOCK)
-$(OBJDIR)/heart.o: heart.c
+$(OBJDIR)/heart.o: heart.c $(RC_GENERATED)
$(CC) $(CFLAGS) -o $@ -c heart.c
endif
@@ -497,6 +449,84 @@ $(OBJDIR)/vxcall.o: $(VXETC)/vxcall.c
+#
+# Objects & executables
+#
+#$(OBJDIR)/%.o: %.c
+# $(CC) $(CFLAGS) -o $@ -c $<
+#
+#$(OBJDIR)/%.o: ../unix/%.c
+# $(CC) $(CFLAGS) -o $@ -c $<
+#
+#$(BINDIR)/%: $(OBJDIR)/%.o
+# $(PURIFY) $(LD) $(LDFLAGS) -o $@ $< $(LIBS)
+
+$(OBJDIR)/inet_gethost.o: inet_gethost.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c inet_gethost.c
+
+$(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o
+ $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS)
+
+$(OBJDIR)/run_erl.o: ../unix/run_erl.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c ../unix/run_erl.c
+
+$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o
+ $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o
+
+$(OBJDIR)/to_erl.o: ../unix/to_erl.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c ../unix/to_erl.c
+
+$(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
+ $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
+
+$(OBJDIR)/dyn_erl.o: ../unix/dyn_erl.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c ../unix/dyn_erl.c
+
+$(OBJDIR)/safe_string.o: ../unix/safe_string.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c ../unix/safe_string.c
+
+ifneq ($(TARGET),win32)
+$(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/$(ERLEXEC).o $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/$(ERLEXEC).o: $(ERLEXECDIR)/$(ERLEXEC).c $(RC_GENERATED)
+ $(CC) -I$(EMUDIR) $(CFLAGS) -o $@ -c $(ERLEXECDIR)/$(ERLEXEC).c
+endif
+$(BINDIR)/erlc@EXEEXT@: $(OBJDIR)/erlc.o $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/erlc.o: erlc.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c erlc.c
+
+$(BINDIR)/dialyzer@EXEEXT@: $(OBJDIR)/dialyzer.o $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/dialyzer.o: dialyzer.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c dialyzer.c
+
+$(BINDIR)/typer@EXEEXT@: $(OBJDIR)/typer.o $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/typer.o: typer.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c typer.c
+
+$(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/escript.o: escript.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c escript.c
+
+$(BINDIR)/ct_run@EXEEXT@: $(OBJDIR)/ct_run.o $(ERTS_LIB)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/ct_run.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/ct_run.o: ct_run.c $(RC_GENERATED)
+ $(CC) $(CFLAGS) -o $@ -c ct_run.c
+
+
+
Install: ../unix/Install.src ../../vsn.mk $(TARGET)/Makefile
sed -e 's;%I_VSN%;$(VSN);' \
-e 's;%EMULATOR%;$(EMULATOR);' \
@@ -515,55 +545,52 @@ erl.src: ../unix/erl.src.src ../../vsn.mk $(TARGET)/Makefile
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
+.PHONY: release_spec
release_spec: etc
ifneq ($(INSTALL_OBJS),)
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/obj
- $(INSTALL_DATA) $(INSTALL_OBJS) $(RELEASE_PATH)/erts-$(VSN)/obj
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/obj"
+ $(INSTALL_DATA) $(INSTALL_OBJS) "$(RELEASE_PATH)/erts-$(VSN)/obj"
endif
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/bin"
ifneq ($(TARGET), win32)
ifneq ($(findstring vxworks,$(TARGET)), vxworks)
ifneq ($(findstring ose,$(TARGET)), ose)
- $(INSTALL_SCRIPT) erl.src $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_SCRIPT) erl.src "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
endif
endif
ifneq ($(INSTALL_PROGS),)
- $(INSTALL_PROGRAM) $(INSTALL_PROGS) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_PROGRAM) $(INSTALL_PROGS) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
ifneq ($(INSTALL_TOP),)
- $(INSTALL_SCRIPT) $(INSTALL_TOP) $(RELEASE_PATH)
+ $(INSTALL_SCRIPT) $(INSTALL_TOP) "$(RELEASE_PATH)"
endif
ifneq ($(INSTALL_TOP_BIN),)
- $(INSTALL_PROGRAM) $(INSTALL_TOP_BIN) $(RELEASE_PATH)
+ $(INSTALL_PROGRAM) $(INSTALL_TOP_BIN) "$(RELEASE_PATH)"
endif
ifneq ($(INSTALL_MISC),)
- $(INSTALL_DIR) $(RELEASE_PATH)/misc
- $(INSTALL_SCRIPT) $(INSTALL_MISC) $(RELEASE_PATH)/misc
+ $(INSTALL_DIR) "$(RELEASE_PATH)/misc"
+ $(INSTALL_SCRIPT) $(INSTALL_MISC) "$(RELEASE_PATH)/misc"
endif
ifneq ($(INSTALL_ERL_OSE),)
- $(INSTALL_DIR) $(RELEASE_PATH)/build_erl_ose
+ $(INSTALL_DIR) "$(RELEASE_PATH)/build_erl_ose"
cd $(OSEETC) && $(TAR) erl_ose_$(SYSTEM_VSN).tar $(INSTALL_ERL_OSE)
- cd $(OSEETC) && $(INSTALL_SCRIPT) erl_ose_$(SYSTEM_VSN).tar $(RELEASE_PATH)/build_erl_ose
+ cd $(OSEETC) && $(INSTALL_SCRIPT) erl_ose_$(SYSTEM_VSN).tar "$(RELEASE_PATH)/build_erl_ose"
endif
ifneq ($(INSTALL_SRC),)
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/src
- $(INSTALL_DATA) $(INSTALL_SRC) $(RELEASE_PATH)/erts-$(VSN)/src
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/src"
+ $(INSTALL_DATA) $(INSTALL_SRC) "$(RELEASE_PATH)/erts-$(VSN)/src"
endif
ifneq ($(INSTALL_EMBEDDED_DATA),)
- $(INSTALL_DATA) $(INSTALL_EMBEDDED_DATA) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DATA) $(INSTALL_EMBEDDED_DATA) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
ifneq ($(INSTALL_LIBS),)
- $(INSTALL_DATA) $(INSTALL_LIBS) $(RELEASE_PATH)/erts-$(VSN)/bin
+ $(INSTALL_DATA) $(INSTALL_LIBS) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
ifneq ($(INSTALL_INCLUDES),)
- $(INSTALL_DIR) $(RELEASE_PATH)/erts-$(VSN)/include
- $(INSTALL_DATA) $(INSTALL_INCLUDES) $(RELEASE_PATH)/erts-$(VSN)/include
+ $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/include"
+ $(INSTALL_DATA) $(INSTALL_INCLUDES) "$(RELEASE_PATH)/erts-$(VSN)/include"
endif
+.PHONY: release_docs_spec
release_docs_spec:
-
-
-
-
-
diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c
index 04e9199ef3..70b11b1b36 100644
--- a/erts/etc/common/dialyzer.c
+++ b/erts/etc/common/dialyzer.c
@@ -189,6 +189,18 @@ main(int argc, char** argv)
argc--, argv++;
}
+ if (argc > 2 && strcmp(argv[1], "+P") == 0) {
+ PUSH2("+P", argv[2]);
+ argc--, argv++;
+ argc--, argv++;
+ } else PUSH2("+P", "1000000");
+
+ if (argc > 2 && strcmp(argv[1], "+sbt") == 0) {
+ PUSH2("+sbt", argv[2]);
+ argc--, argv++;
+ argc--, argv++;
+ }
+
PUSH("+B");
PUSH2("-boot", "start_clean");
PUSH3("-run", "dialyzer", "plain_cl");
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index 35c360a99d..9f05213c95 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -185,6 +185,7 @@ main(int argc, char** argv)
* Push initial arguments.
*/
+ PUSH("+sbtu");
PUSH("-noinput");
PUSH2("-mode", "minimal");
PUSH2("-boot", "start_clean");
@@ -251,13 +252,6 @@ main(int argc, char** argv)
}
}
break;
- case 'h':
- if (strcmp(argv[1], "-hybrid") == 0) {
- UNSHIFT(argv[1]);
- } else {
- usage();
- }
- break;
case 'I':
PUSH2("@i", process_opt(&argc, &argv, 0));
break;
@@ -341,7 +335,7 @@ main(int argc, char** argv)
/* Push the following options:
* o makedep_phony
*/
- buf = strsave("makedep_add_missing");
+ buf = strsave("makedep_phony");
PUSH2("@option", buf);
break;
default:
@@ -648,7 +642,6 @@ usage(void)
{"-d", "turn on debugging of erlc itself"},
{"-Dname", "define name"},
{"-Dname=value", "define name to have value"},
- {"-hybrid", "compile using hybrid-heap emulator"},
{"-help", "shows this help text"},
{"-I path", "where to search for include files"},
{"-M", "generate a rule for make(1) describing the dependencies"},
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 2bd576d8e8..cba7429fab 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -67,6 +67,7 @@ static const char plusM_au_allocs[]= {
'C', /* sbmbc_alloc */
'D', /* std_alloc */
'E', /* ets_alloc */
+ 'F', /* fix_alloc */
'H', /* eheap_alloc */
'L', /* ll_alloc */
'R', /* driver_alloc */
@@ -110,8 +111,6 @@ static char *plusM_other_switches[] = {
"Mamcbf",
"Mrmcbf",
"Mmcs",
- "Mcci",
- "Fe",
"Ye",
"Ym",
"Ytp",
@@ -122,8 +121,11 @@ static char *plusM_other_switches[] = {
/* +s arguments with values */
static char *pluss_val_switches[] = {
"bt",
+ "bwt",
+ "cl",
"ct",
"wt",
+ "ws",
"ss",
NULL
};
@@ -157,20 +159,13 @@ static char *plusz_val_switches[] = {
#endif
#define SMP_SUFFIX ".smp"
-#define HYBRID_SUFFIX ".hybrid"
-
-#ifdef __WIN32__
#define DEBUG_SUFFIX ".debug"
-#define EMU_TYPE_SUFFIX_LENGTH (strlen(HYBRID_SUFFIX)+(strlen(DEBUG_SUFFIX)))
-#else
-/* The length of the longest memory architecture suffix. */
-#define EMU_TYPE_SUFFIX_LENGTH strlen(HYBRID_SUFFIX)
-#endif
+#define EMU_TYPE_SUFFIX_LENGTH strlen(DEBUG_SUFFIX)
+
/*
* Define flags for different memory architectures.
*/
#define EMU_TYPE_SMP 0x0001
-#define EMU_TYPE_HYBRID 0x0002
#ifdef __WIN32__
#define EMU_TYPE_DEBUG 0x0004
@@ -184,7 +179,7 @@ void error(char* format, ...);
* Local functions.
*/
-#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_HYBRID_EMU)
+#if !defined(ERTS_HAVE_SMP_EMU)
static void usage_notsup(const char *switchname);
#endif
static void usage_msg(const char *msg);
@@ -250,7 +245,9 @@ static char* config_script = NULL; /* used by option -start_erl and -config */
static HANDLE this_module_handle;
static int run_werl;
-
+static WCHAR *utf8_to_utf16(unsigned char *bytes);
+static char *utf16_to_utf8(WCHAR *wstr);
+static WCHAR *latin1_to_utf16(char *str);
#endif
/*
@@ -268,8 +265,12 @@ static void
set_env(char *key, char *value)
{
#ifdef __WIN32__
- if (!SetEnvironmentVariable((LPCTSTR) key, (LPCTSTR) value))
+ WCHAR *wkey = latin1_to_utf16(key);
+ WCHAR *wvalue = utf8_to_utf16(value);
+ if (!SetEnvironmentVariableW(wkey, wvalue))
error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value);
+ efree(wkey);
+ efree(wvalue);
#else
size_t size = strlen(key) + 1 + strlen(value) + 1;
char *str = emalloc(size);
@@ -282,25 +283,33 @@ set_env(char *key, char *value)
#endif
}
+
static char *
get_env(char *key)
{
#ifdef __WIN32__
DWORD size = 32;
- char *value = NULL;
+ WCHAR *value = NULL;
+ WCHAR *wkey = latin1_to_utf16(key);
+ char *res;
while (1) {
DWORD nsz;
if (value)
efree(value);
- value = emalloc(size);
+ value = emalloc(size*sizeof(WCHAR));
SetLastError(0);
- nsz = GetEnvironmentVariable((LPCTSTR) key, (LPTSTR) value, size);
+ nsz = GetEnvironmentVariableW(wkey, value, size);
if (nsz == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
efree(value);
+ efree(wkey);
return NULL;
}
- if (nsz <= size)
- return value;
+ if (nsz <= size) {
+ efree(wkey);
+ res = utf16_to_utf8(value);
+ efree(value);
+ return res;
+ }
size = nsz;
}
#else
@@ -367,9 +376,6 @@ add_extra_suffixes(char *prog, int type)
if (type == EMU_TYPE_SMP) {
p = write_str(p, SMP_SUFFIX);
}
- else if (type == EMU_TYPE_HYBRID) {
- p = write_str(p, HYBRID_SUFFIX);
- }
#ifdef __WIN32__
if (dll) {
p = write_str(p, DLL_EXT);
@@ -535,13 +541,6 @@ int main(int argc, char **argv)
emu_type_passed |= EMU_TYPE_DEBUG;
emu_type |= EMU_TYPE_DEBUG;
#endif
- } else if (strcmp(argv[i], "-hybrid") == 0) {
- emu_type_passed |= EMU_TYPE_HYBRID;
-#ifdef ERTS_HAVE_HYBRID_EMU
- emu_type |= EMU_TYPE_HYBRID;
-#else
- usage_notsup("-hybrid");
-#endif
} else if (strcmp(argv[i], "-extra") == 0) {
break;
}
@@ -552,19 +551,6 @@ int main(int argc, char **argv)
erts_cpu_info_destroy(cpuinfo);
cpuinfo = NULL;
- if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
- /*
- * We have a conflict. Only using explicitly passed arguments
- * may solve it...
- */
- emu_type &= emu_type_passed;
- if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
- usage_msg("Hybrid heap emulator with SMP support selected. The "
- "combination hybrid heap and SMP support is currently "
- "not supported.");
- }
- }
-
if (malloc_lib) {
if (strcmp(malloc_lib, "libc") != 0)
usage("+MYm");
@@ -1115,9 +1101,6 @@ usage_aux(void)
"]"
#endif
"] "
-#ifdef ERTS_HAVE_HYBRID_EMU
- "[-hybrid] "
-#endif
"[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] "
"[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] "
"[+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
@@ -1135,7 +1118,7 @@ usage(const char *switchname)
usage_aux();
}
-#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_HYBRID_EMU)
+#if !defined(ERTS_HAVE_SMP_EMU)
static void
usage_notsup(const char *switchname)
{
@@ -1176,7 +1159,7 @@ start_epmd(char *epmd)
erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd", bindir);
arg1 = "-daemon";
#else
- erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd -daemon", bindir);
+ erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "\"%s" DIRSEP "epmd\" -daemon", bindir);
#endif
}
#ifdef __WIN32__
@@ -2111,4 +2094,147 @@ possibly_quote(char* arg)
return narg;
}
+/*
+ * Unicode helpers to handle environment and command line parameters on
+ * Windows. We internally handle all environment variables in UTF8,
+ * but put and get the environment using the WCHAR (limited UTF16) interface
+ *
+ * These are simplified to only handle Unicode characters that can fit in
+ * Windows simplified UTF16, i.e. characters that fit in 16 bits.
+ */
+
+static int utf8_len(unsigned char first)
+{
+ if ((first & ((unsigned char) 0x80)) == 0) {
+ return 1;
+ } else if ((first & ((unsigned char) 0xE0)) == 0xC0) {
+ return 2;
+ } else if ((first & ((unsigned char) 0xF0)) == 0xE0) {
+ return 3;
+ } else if ((first & ((unsigned char) 0xF8)) == 0xF0) {
+ return 4;
+ }
+ return 1; /* will be a '?' */
+}
+
+static WCHAR *utf8_to_utf16(unsigned char *bytes)
+{
+ unsigned int unipoint;
+ unsigned char *tmp = bytes;
+ WCHAR *target, *res;
+ int num = 0;
+
+ while (*tmp) {
+ num++;
+ tmp += utf8_len(*tmp);
+ }
+ res = target = emalloc((num + 1) * sizeof(WCHAR));
+ while (*bytes) {
+ if (((*bytes) & ((unsigned char) 0x80)) == 0) {
+ unipoint = (Uint) *bytes;
+ ++bytes;
+ } else if (((*bytes) & ((unsigned char) 0xE0)) == 0xC0) {
+ unipoint =
+ (((Uint) ((*bytes) & ((unsigned char) 0x1F))) << 6) |
+ ((Uint) (bytes[1] & ((unsigned char) 0x3F)));
+ bytes += 2;
+ } else if (((*bytes) & ((unsigned char) 0xF0)) == 0xE0) {
+ unipoint =
+ (((Uint) ((*bytes) & ((unsigned char) 0xF))) << 12) |
+ (((Uint) (bytes[1] & ((unsigned char) 0x3F))) << 6) |
+ ((Uint) (bytes[2] & ((unsigned char) 0x3F)));
+ if (unipoint > 0xFFFF) {
+ unipoint = (unsigned int) '?';
+ }
+ bytes +=3;
+ } else if (((*bytes) & ((unsigned char) 0xF8)) == 0xF0) {
+ unipoint = (unsigned int) '?'; /* Cannot put in a wchar */
+ bytes += 4;
+ } else {
+ unipoint = (unsigned int) '?';
+ }
+ *target++ = (WCHAR) unipoint;
+ }
+ *target = L'\0';
+ return res;
+}
+
+static int put_utf8(WCHAR ch, unsigned char *target, int sz, int *pos)
+{
+ Uint x = (Uint) ch;
+ if (x < 0x80) {
+ if (*pos >= sz) {
+ return -1;
+ }
+ target[(*pos)++] = (unsigned char) x;
+ }
+ else if (x < 0x800) {
+ if (((*pos) + 1) >= sz) {
+ return -1;
+ }
+ target[(*pos)++] = (((unsigned char) (x >> 6)) |
+ ((unsigned char) 0xC0));
+ target[(*pos)++] = (((unsigned char) (x & 0x3F)) |
+ ((unsigned char) 0x80));
+ } else {
+ if ((x >= 0xD800 && x <= 0xDFFF) ||
+ (x == 0xFFFE) ||
+ (x == 0xFFFF)) { /* Invalid unicode range */
+ return -1;
+ }
+ if (((*pos) + 2) >= sz) {
+ return -1;
+ }
+
+ target[(*pos)++] = (((unsigned char) (x >> 12)) |
+ ((unsigned char) 0xE0));
+ target[(*pos)++] = ((((unsigned char) (x >> 6)) & 0x3F) |
+ ((unsigned char) 0x80));
+ target[(*pos)++] = (((unsigned char) (x & 0x3F)) |
+ ((unsigned char) 0x80));
+ }
+ return 0;
+}
+
+static int need_bytes_for_utf8(WCHAR x)
+{
+ if (x < 0x80)
+ return 1;
+ else if (x < 0x800)
+ return 2;
+ else
+ return 3;
+}
+
+static WCHAR *latin1_to_utf16(char *str)
+{
+ int len = strlen(str);
+ int i;
+ WCHAR *wstr = emalloc((len+1) * sizeof(WCHAR));
+ for(i=0;i<len;++i)
+ wstr[i] = (WCHAR) str[i];
+ wstr[len] = L'\0';
+ return wstr;
+}
+
+static char *utf16_to_utf8(WCHAR *wstr)
+{
+ int len = wcslen(wstr);
+ char *result;
+ int i,pos;
+ int reslen = 0;
+ for(i=0;i<len;++i) {
+ reslen += need_bytes_for_utf8(wstr[i]);
+ }
+ result = emalloc(reslen+1);
+ pos = 0;
+ for(i=0;i<len;++i) {
+ if (put_utf8((int) wstr[i], result, reslen, &pos) < 0) {
+ break;
+ }
+ }
+ result[pos] = '\0';
+ return result;
+}
+
#endif
diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c
index 6ed79c91e3..9e80ec6656 100644
--- a/erts/etc/common/escript.c
+++ b/erts/etc/common/escript.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -377,7 +377,8 @@ main(int argc, char** argv)
last_opt = argv;
#ifdef __WIN32__
- if (_stricmp(basename, "escript.exe") == 0) {
+ if ( (_stricmp(basename, "escript.exe") == 0)
+ ||(_stricmp(basename, "escript") == 0)) {
#else
if (strcmp(basename, "escript") == 0) {
#endif
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 7a5746e630..70c2b3bb23 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The 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,9 +102,6 @@
* that can simulate gethrtime with clock_gettime, no use implementing
* a phony gethrtime in this file as the time questions are so infrequent.
*/
-#if defined(CORRET_USING_TIMES) || defined(GETHRTIME_WITH_CLOCK_GETTIME)
-# define HEART_CORRECT_USING_TIMES 1
-#endif
#include <stdio.h>
#include <stddef.h>
@@ -134,7 +131,7 @@
# include <sys/time.h>
# include <unistd.h>
# include <signal.h>
-# if defined(HEART_CORRECT_USING_TIMES)
+# if defined(CORRECT_USING_TIMES)
# include <sys/times.h>
# include <limits.h>
# endif
@@ -447,7 +444,8 @@ message_loop(erlin_fd, erlout_fd)
*/
timestamp(&now);
if (now > last_received + heart_beat_timeout) {
- print_error("heart-beat time-out.");
+ print_error("heart-beat time-out, no activity for %lu seconds",
+ (unsigned long) (now - last_received));
return R_TIMEOUT;
}
/*
@@ -685,14 +683,16 @@ do_terminate(reason)
print_error("Would reboot. Terminating.");
else {
kill_old_erlang();
- system(command);
+ /* suppress gcc warning with 'if' */
+ if(system(command));
print_error("Executed \"%s\". Terminating.",command);
}
free_env_val(command);
}
else {
kill_old_erlang();
- system((char*)&cmd[0]);
+ /* suppress gcc warning with 'if' */
+ if(system((char*)&cmd[0]));
print_error("Executed \"%s\". Terminating.",cmd);
}
}
@@ -1077,7 +1077,31 @@ time_t timestamp(time_t *res)
return r;
}
-#elif defined(HAVE_GETHRTIME)
+#elif defined(HAVE_GETHRTIME) || defined(GETHRTIME_WITH_CLOCK_GETTIME)
+
+#if defined(GETHRTIME_WITH_CLOCK_GETTIME)
+typedef long long SysHrTime;
+
+SysHrTime sys_gethrtime(void);
+
+SysHrTime sys_gethrtime(void)
+{
+ struct timespec ts;
+ long long result;
+ if (clock_gettime(CLOCK_MONOTONIC,&ts) != 0) {
+ print_error("Fatal, could not get clock_monotonic value, terminating! "
+ "errno = %d\n", errno);
+ exit(1);
+ }
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);
+ return (SysHrTime) result;
+}
+#else
+typedef hrtime_t SysHrTime;
+#define sys_gethrtime() gethrtime()
+#endif
+
void init_timestamp(void)
{
@@ -1085,14 +1109,14 @@ void init_timestamp(void)
time_t timestamp(time_t *res)
{
- hrtime_t ht = gethrtime();
+ SysHrTime ht = sys_gethrtime();
time_t r = (time_t) (ht / 1000000000);
if (res != NULL)
*res = r;
return r;
}
-#elif defined(HEART_CORRECT_USING_TIMES)
+#elif defined(CORRECT_USING_TIMES)
# ifdef NO_SYSCONF
# include <sys/param.h>
diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index 77bfd5e2bc..e923233ce9 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1141,14 +1141,12 @@ static Worker *pick_worker(void)
static Worker *pick_worker_greedy(AddrByte *domainbuff)
{
int i;
- int ql = 0;
int found = -1;
for (i=0; i < num_busy_workers; ++i) {
if (domaineq(busy_workers[i].domain, domainbuff)) {
if ((found < 0) || (busy_workers[i].que_size <
busy_workers[found].que_size)) {
found = i;
- ql = busy_workers[i].que_size;
}
}
}
@@ -1945,12 +1943,14 @@ static int worker_loop(void)
}
m = NULL;
#else
- write(1, reply, data_size); /* No signals expected */
+ /* expect no signals */
+ if (write(1, reply, data_size) < 0)
+ goto fail;
#endif
} /* for (;;) */
-#ifdef WIN32
fail:
+#ifdef WIN32
if (m != NULL) {
FREE(m);
}
@@ -1959,8 +1959,8 @@ static int worker_loop(void)
if (reply) {
FREE(reply);
}
- return 1;
#endif
+ return 1;
}
static int map_netdb_error(int netdb_code)
@@ -2561,7 +2561,8 @@ static void debugf(char *format, ...)
WriteFile(debug_console_allocated,buff,strlen(buff),&res,NULL);
}
#else
- write(2,buff,strlen(buff));
+ /* suppress warning with 'if' */
+ if(write(2,buff,strlen(buff)));
#endif
va_end(ap);
}
@@ -2583,7 +2584,8 @@ static void warning(char *format, ...)
WriteFile(GetStdHandle(STD_ERROR_HANDLE),buff,strlen(buff),&res,NULL);
}
#else
- write(2,buff,strlen(buff));
+ /* suppress warning with 'if' */
+ if(write(2,buff,strlen(buff)));
#endif
va_end(ap);
}
@@ -2605,7 +2607,8 @@ static void fatal(char *format, ...)
WriteFile(GetStdHandle(STD_ERROR_HANDLE),buff,strlen(buff),&res,NULL);
}
#else
- write(2,buff,strlen(buff));
+ /* suppress warning with 'if' */
+ if(write(2,buff,strlen(buff)));
#endif
va_end(ap);
#ifndef WIN32
diff --git a/erts/etc/unix/Install.src b/erts/etc/unix/Install.src
index 8f40c43874..58f7b38ed0 100644
--- a/erts/etc/unix/Install.src
+++ b/erts/etc/unix/Install.src
@@ -66,12 +66,12 @@ then
exit 1
fi
-if [ ! -d $ERL_ROOT/bin ]
+if [ ! -d "$ERL_ROOT/bin" ]
then
- mkdir $ERL_ROOT/bin
+ mkdir "$ERL_ROOT/bin"
fi
-cd $ERL_ROOT/erts-%I_VSN%/bin
+cd "$ERL_ROOT/erts-%I_VSN%/bin"
sed -e "s;%FINAL_ROOTDIR%;$TARGET_ERL_ROOT;" erl.src > erl
chmod 755 erl
@@ -79,18 +79,18 @@ chmod 755 erl
#
# Create start file for embedded system use,
#
-(cd $ERL_ROOT/erts-%I_VSN%/bin;
+(cd "$ERL_ROOT/erts-%I_VSN%/bin";
sed -e "s;%FINAL_ROOTDIR%;$TARGET_ERL_ROOT;" start.src > start;
chmod 755 start)
-cd $ERL_ROOT/bin
+cd "$ERL_ROOT/bin"
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/erl .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/erlc .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/dialyzer .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/typer .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/ct_run .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/escript .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/erl" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/erlc" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/dialyzer" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/typer" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/ct_run" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/escript" .
# Remove in R16B
ln -s ct_run run_test
@@ -107,15 +107,15 @@ fi
ln -s ../erts-%I_VSN%/bin/epmd epmd
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/run_erl .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/to_erl .
-cp -p $ERL_ROOT/erts-%I_VSN%/bin/start .
-sed -e "s;%EMU%;%EMULATOR%%EMULATOR_NUMBER%;" $ERL_ROOT/erts-%I_VSN%/bin/start_erl.src > start_erl
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/run_erl" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/to_erl" .
+cp -p "$ERL_ROOT/erts-%I_VSN%/bin/start" .
+sed -e "s;%EMU%;%EMULATOR%%EMULATOR_NUMBER%;" "$ERL_ROOT/erts-%I_VSN%/bin/start_erl.src" > start_erl
chmod 755 start_erl
echo ""
-echo %I_VSN% %I_SYSTEM_VSN% > $ERL_ROOT/releases/start_erl.data
-sed -e "s;%ERL_ROOT%;$TARGET_ERL_ROOT;" $ERL_ROOT/releases/RELEASES.src > $ERL_ROOT/releases/RELEASES
+echo %I_VSN% %I_SYSTEM_VSN% > "$ERL_ROOT/releases/start_erl.data"
+sed -e "s;%ERL_ROOT%;$TARGET_ERL_ROOT;" "$ERL_ROOT/releases/RELEASES.src" > "$ERL_ROOT/releases/RELEASES"
if [ "$start_option" = "query" ]
then
@@ -147,10 +147,10 @@ cp -p ../releases/%I_SYSTEM_VSN%/$Name.script start.script
# Fixing the man pages
#
-if [ -d $ERL_ROOT/man ]
+if [ -d "$ERL_ROOT/man" ]
then
- cd $ERL_ROOT
- ./misc/format_man_pages $ERL_ROOT
+ cd "$ERL_ROOT"
+ ./misc/format_man_pages "$ERL_ROOT"
fi
exit 0
diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src
index 0b2d6512ea..ffd48d5811 100644
--- a/erts/etc/unix/cerl.src
+++ b/erts/etc/unix/cerl.src
@@ -227,7 +227,7 @@ done
PATH=$BINDIR:$ROOTDIR/bin:$PATH
EXEC=$BINDIR/erlexec
-PROGNAME="$PROGNAME $cargs"
+PROGNAME="$PROGNAME$cargs"
EMU="$EMU$TYPE"
EMU_NAME=`$EXEC -emu_name_exit $eeargs`
@@ -302,7 +302,7 @@ else
# Set annotation level for gdb in emacs 22 and higher.
emacs_major=`$EMACS --version | head -1 | sed 's,^[^0-9]*\([0-9]*\).*,\1,g'`
if [ '!' -z "$emacs_major" -a $emacs_major -gt 21 ]; then
- GDBARGS="--annotate=3 "
+ GDBARGS="--annotate=1 "
fi
gdbcmd="$gdbcmd $GDBBP \
(insert-string \"source $ROOTDIR/erts/etc/unix/etp-commands\") \
diff --git a/erts/etc/unix/erl.src.src b/erts/etc/unix/erl.src.src
index 50603f12f4..fa187c5509 100644
--- a/erts/etc/unix/erl.src.src
+++ b/erts/etc/unix/erl.src.src
@@ -17,7 +17,7 @@
#
# %CopyrightEnd%
#
-ROOTDIR=%FINAL_ROOTDIR%
+ROOTDIR="%FINAL_ROOTDIR%"
BINDIR=$ROOTDIR/erts-%VSN%/bin
EMU=%EMULATOR%%EMULATOR_NUMBER%
PROGNAME=`echo $0 | sed 's/.*\///'`
@@ -25,4 +25,4 @@ export EMU
export ROOTDIR
export BINDIR
export PROGNAME
-exec $BINDIR/erlexec ${1+"$@"}
+exec "$BINDIR/erlexec" ${1+"$@"}
diff --git a/erts/etc/unix/etp-commands b/erts/etc/unix/etp-commands
index 6a01e0b7e0..1c886620bb 100644
--- a/erts/etc/unix/etp-commands
+++ b/erts/etc/unix/etp-commands
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2009. All Rights Reserved.
+# Copyright Ericsson AB 2005-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -1883,6 +1883,28 @@ document etp-ets-tables
%---------------------------------------------------------------------------
end
+define etp-ets-obj
+# Args: DbTerm*
+#
+ set $etp_ets_obj_i = 1
+ while $etp_ets_obj_i <= (($arg0)->tpl[0] >> 6)
+ if $etp_ets_obj_i == 1
+ printf "{"
+ else
+ printf ", "
+ end
+ set $etp_ets_elem = ($arg0)->tpl[$etp_ets_obj_i]
+ if ($etp_ets_elem & 3) == 0
+ printf "<compressed>"
+ else
+ etp-1 $etp_ets_elem 0
+ end
+ set $etp_ets_obj_i++
+ end
+ printf "}"
+end
+
+
define etp-ets-tabledump
# Args: int tableindex
#
@@ -1896,10 +1918,10 @@ define etp-ets-tabledump
if $etp_ets_tabledump_t->common.status & 0x130
# Hash table
set $etp_ets_tabledump_h = $etp_ets_tabledump_t->hash
- printf "%% nitems=%d\n", $etp_ets_tabledump_t->common.nitems
- while $etp_ets_tabledump_i < $etp_ets_tabledump_h->nactive
- set $etp_ets_tabledump_l = $etp_ets_tabledump_h->seg \
- [$etp_ets_tabledump_i>>8][$etp_ets_tabledump_i&0xFF]
+ printf "%% nitems=%d\n", (long) $etp_ets_tabledump_t->common.nitems
+ while $etp_ets_tabledump_i < (long) $etp_ets_tabledump_h->nactive
+ set $etp_ets_tabledump_seg = ((struct segment**)$etp_ets_tabledump_h->segtab)[$etp_ets_tabledump_i>>8]
+ set $etp_ets_tabledump_l = $etp_ets_tabledump_seg->buckets[$etp_ets_tabledump_i&0xFF]
if $etp_ets_tabledump_l
printf "%% Slot %d:\n", $etp_ets_tabledump_i
while $etp_ets_tabledump_l
@@ -1909,7 +1931,7 @@ define etp-ets-tabledump
printf "["
end
set $etp_ets_tabledump_n++
- etp-1 ((Eterm)($etp_ets_tabledump_l->dbterm.tpl)|0x2) 0
+ etp-ets-obj &($etp_ets_tabledump_l->dbterm)
if $etp_ets_tabledump_l->hvalue == ((unsigned long)-1)
printf "% *\n"
else
diff --git a/erts/etc/unix/run_erl.c b/erts/etc/unix/run_erl.c
index 8db8e09bee..6b350e8bd5 100644
--- a/erts/etc/unix/run_erl.c
+++ b/erts/etc/unix/run_erl.c
@@ -126,7 +126,7 @@
/* prototypes */
static void usage(char *);
static int create_fifo(char *name, int perm);
-static int open_pty_master(char **name);
+static int open_pty_master(char **name, int *sfd);
static int open_pty_slave(char *name);
static void pass_on(pid_t);
static void exec_shell(char **);
@@ -150,6 +150,10 @@ static int write_all(int fd, const char* buf, int len);
static int extract_ctrl_seq(char* buf, int len);
static void set_window_size(unsigned col, unsigned row);
+static ssize_t sf_write(int fd, const void *buffer, size_t len);
+static ssize_t sf_read(int fd, void *buffer, size_t len);
+static int sf_open(const char *path, int flags, mode_t mode);
+static int sf_close(int fd);
#ifdef DEBUG
static void show_terminal_settings(struct termios *t);
@@ -216,7 +220,7 @@ static char* outbuf_in;
int main(int argc, char **argv)
{
int childpid;
- int sfd;
+ int sfd = -1;
int fd;
char *p, *ptyslave=NULL;
int i = 1;
@@ -338,9 +342,9 @@ int main(int argc, char **argv)
strn_cat(fifo2, sizeof(fifo2), ".w");
/* Check that nobody is running run_erl already */
- if ((fd = open (fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
+ if ((fd = sf_open(fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
/* Open as client succeeded -- run_erl is already running! */
- close(fd);
+ sf_close(fd);
if (calculated_pipename) {
++highest_pipe_num;
strn_catf(pipename, sizeof(pipename), "%s.%d",
@@ -361,7 +365,7 @@ int main(int argc, char **argv)
* Open master pseudo-terminal
*/
- if ((mfd = open_pty_master(&ptyslave)) < 0) {
+ if ((mfd = open_pty_master(&ptyslave, &sfd)) < 0) {
ERRNO_ERR0(LOG_ERR,"Could not open pty master");
exit(1);
}
@@ -376,7 +380,7 @@ int main(int argc, char **argv)
}
if (childpid == 0) {
/* Child */
- close(mfd);
+ sf_close(mfd);
/* disassociate from control terminal */
#ifdef USE_SETPGRP_NOARGS /* SysV */
setpgrp();
@@ -386,15 +390,30 @@ int main(int argc, char **argv)
setsid();
#endif
/* Open the slave pty */
- if ((sfd = open_pty_slave(ptyslave)) < 0) {
- ERRNO_ERR1(LOG_ERR,"Could not open pty slave '%s'", ptyslave);
- exit(1);
+ if (sfd < 0) {
+ /* not allocated by open_pty_master */
+ if ((sfd = open_pty_slave(ptyslave)) < 0) {
+ ERRNO_ERR1(LOG_ERR,"Could not open pty slave '%s'", ptyslave);
+ exit(1);
+ }
+ /* But sfd may be one of the stdio fd's now, and we should be unmodern and not use dup2... */
+ /* easiest to dup it up... */
+ while (sfd < 3) {
+ sfd = dup(sfd);
+ }
}
- /* But sfd may be one of the stdio fd's now, and we should be unmodern and not use dup2... */
- /* easiest to dup it up... */
- while (sfd < 3) {
- sfd = dup(sfd);
+#if defined(HAVE_OPENPTY) && defined(TIOCSCTTY)
+ else {
+ /* sfd is from open_pty_master
+ * openpty -> fork -> login_tty (forkpty)
+ *
+ * It would be preferable to implement a portable
+ * forkpty instead of open_pty_master / open_pty_slave
+ */
+ /* login_tty(sfd); <- FAIL */
+ ioctl(sfd, TIOCSCTTY, (char *)NULL);
}
+#endif
#ifndef NO_SYSLOG
/* Before fiddling with file descriptors we make sure syslog is turned off
@@ -407,14 +426,14 @@ int main(int argc, char **argv)
#endif
/* Close stdio */
- close(0);
- close(1);
- close(2);
+ sf_close(0);
+ sf_close(1);
+ sf_close(2);
if (dup(sfd) != 0 || dup(sfd) != 1 || dup(sfd) != 2) {
status("Cannot dup\n");
}
- close(sfd);
+ sf_close(sfd);
exec_shell(argv+off_argv); /* exec_shell expects argv[2] to be */
/* the command name, so we have to */
/* adjust. */
@@ -466,7 +485,7 @@ static void pass_on(pid_t childpid)
* We can't open the writing side because nobody is reading and
* we'd either hang or get an error.
*/
- if ((rfd = open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
+ if ((rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2);
exit(1);
}
@@ -559,7 +578,7 @@ static void pass_on(pid_t childpid)
char* buf = outbuf_first();
len = outbuf_size();
- written = write(wfd, buf, len);
+ written = sf_write(wfd, buf, len);
if (written < 0 && errno == EAGAIN) {
/*
* Nothing was written - this is really strange because
@@ -570,7 +589,7 @@ static void pass_on(pid_t childpid)
* A write error. Assume that to_erl has terminated.
*/
clear_outbuf();
- close(wfd);
+ sf_close(wfd);
wfd = 0;
} else {
/* Delete the written part (or all) from the buffer. */
@@ -585,10 +604,10 @@ static void pass_on(pid_t childpid)
#ifdef DEBUG
status("Pty master read; ");
#endif
- if ((len = read(mfd, buf, BUFSIZ)) <= 0) {
- close(rfd);
- if(wfd) close(wfd);
- close(mfd);
+ if ((len = sf_read(mfd, buf, BUFSIZ)) <= 0) {
+ sf_close(rfd);
+ if(wfd) sf_close(wfd);
+ sf_close(mfd);
unlink(fifo1);
unlink(fifo2);
if (len < 0) {
@@ -619,10 +638,10 @@ static void pass_on(pid_t childpid)
#ifdef DEBUG
status("FIFO read; ");
#endif
- if ((len = read(rfd, buf, BUFSIZ)) < 0) {
- close(rfd);
- if(wfd) close(wfd);
- close(mfd);
+ if ((len = sf_read(rfd, buf, BUFSIZ)) < 0) {
+ sf_close(rfd);
+ if(wfd) sf_close(wfd);
+ sf_close(mfd);
unlink(fifo1);
unlink(fifo2);
ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO.");
@@ -631,8 +650,8 @@ static void pass_on(pid_t childpid)
if(!len) {
/* to_erl closed its end of the pipe */
- close(rfd);
- rfd = open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
+ sf_close(rfd);
+ rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
if (rfd < 0) {
ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2);
exit(1);
@@ -645,11 +664,11 @@ static void pass_on(pid_t childpid)
* from to_erl, to_erl should already be reading this pipe - open
* should succeed. But in case of error, we just ignore it.
*/
- if ((wfd = open(fifo1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
+ if ((wfd = sf_open(fifo1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
status("Client expected on FIFO %s, but can't open (len=%d)\n",
fifo1, len);
- close(rfd);
- rfd = open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
+ sf_close(rfd);
+ rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
if (rfd < 0) {
ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2);
exit(1);
@@ -683,9 +702,9 @@ static void pass_on(pid_t childpid)
}
else if (len>0 && write_all(mfd, buf, len) != len) {
ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
- close(rfd);
- if(wfd) close(wfd);
- close(mfd);
+ sf_close(rfd);
+ if(wfd) sf_close(wfd);
+ sf_close(mfd);
exit(1);
}
}
@@ -797,7 +816,7 @@ static int open_log(int log_num, int flags)
/* Create or continue on the current log file */
sn_printf(buf, sizeof(buf), "%s/%s%d", log_dir, LOG_STUBNAME, log_num);
- if((lfd = open(buf, flags, LOG_PERM))<0){
+ if((lfd = sf_open(buf, flags, LOG_PERM))<0){
ERRNO_ERR1(LOG_ERR,"Can't open log file '%s'.", buf);
exit(1);
}
@@ -841,7 +860,7 @@ static void write_to_log(int* lfd, int* log_num, char* buf, int len)
size = lseek(*lfd,0,SEEK_END);
if(size+len > log_maxsize) {
- close(*lfd);
+ sf_close(*lfd);
*log_num = next_log(*log_num);
*lfd = open_log(*log_num, O_RDWR|O_CREAT|O_TRUNC|O_SYNC);
}
@@ -872,7 +891,7 @@ static int create_fifo(char *name, int perm)
* Find a master device, open and return fd and slave device name.
*/
-static int open_pty_master(char **ptyslave)
+static int open_pty_master(char **ptyslave, int *sfdp)
{
int mfd;
@@ -882,7 +901,9 @@ static int open_pty_master(char **ptyslave)
# ifdef HAVE_WORKING_POSIX_OPENPT
if ((mfd = posix_openpt(O_RDWR)) >= 0) {
# elif defined(__sun) && defined(__SVR4)
- if ((mfd = open("/dev/ptmx", O_RDWR)) >= 0) {
+ mfd = sf_open("/dev/ptmx", O_RDWR, 0);
+
+ if (mfd >= 0) {
# endif
if ((*ptyslave = ptsname(mfd)) != NULL &&
grantpt(mfd) == 0 &&
@@ -890,12 +911,12 @@ static int open_pty_master(char **ptyslave)
return mfd;
}
- close(mfd);
+ sf_close(mfd);
}
/* fallback to openpty if it exist */
#endif
-#ifdef HAVE_OPENPTY
+#if defined(HAVE_OPENPTY)
# ifdef PATH_MAX
# define SLAVE_SIZE PATH_MAX
# else
@@ -903,11 +924,8 @@ static int open_pty_master(char **ptyslave)
# endif
{
static char slave[SLAVE_SIZE];
- int sfd;
# undef SLAVE_SIZE
-
- if (openpty(&mfd, &sfd, slave, NULL, NULL) == 0) {
- close(sfd);
+ if (openpty(&mfd, sfdp, slave, NULL, NULL) == 0) {
*ptyslave = slave;
return mfd;
}
@@ -939,7 +957,8 @@ static int open_pty_master(char **ptyslave)
for (minor = minorchars; *minor; minor++) {
ptyname[10] = *minor;
- if ((mfd = open(ptyname, O_RDWR, 0)) >= 0) {
+
+ if ((mfd = sf_open(ptyname, O_RDWR, 0)) >= 0) {
ptyname[9] = 's';
*ptyslave = ptyname;
return mfd;
@@ -957,7 +976,7 @@ static int open_pty_master(char **ptyslave)
ptyname[13] = *major;
for (minor = minorchars; *minor; minor++) {
ptyname[14] = *minor;
- if ((mfd = open(ptyname, O_RDWR, 0)) >= 0) {
+ if ((mfd = sf_open(ptyname, O_RDWR, 0)) >= 0) {
ttyname[12] = *major;
ttyname[13] = *minor;
*ptyslave = ttyname;
@@ -976,7 +995,7 @@ static int open_pty_master(char **ptyslave)
ptyname[8] = *major;
for (minor = minorchars; *minor; minor++) {
ptyname[9] = *minor;
- if ((mfd = open(ptyname, O_RDWR, 0)) >= 0) {
+ if ((mfd = sf_open(ptyname, O_RDWR, 0)) >= 0) {
ptyname[5] = 't';
*ptyslave = ptyname;
return mfd;
@@ -993,7 +1012,7 @@ static int open_pty_slave(char *name)
int sfd;
struct termios tty_rmode;
- if ((sfd = open(name, O_RDWR, 0)) < 0) {
+ if ((sfd = sf_open(name, O_RDWR, 0)) < 0) {
return -1;
}
@@ -1120,7 +1139,7 @@ static void daemon_init(void)
would be backward incompatible */
for (i = 0; i < maxfd; ++i ) {
- close(i);
+ sf_close(i);
}
OPEN_SYSLOG();
@@ -1246,7 +1265,7 @@ static int write_all(int fd, const char* buf, int len)
int left = len;
int written;
for (;;) {
- written = write(fd,buf,left);
+ written = sf_write(fd,buf,left);
if (written == left) {
return len;
}
@@ -1258,6 +1277,36 @@ static int write_all(int fd, const char* buf, int len)
}
}
+static ssize_t sf_read(int fd, void *buffer, size_t len) {
+ ssize_t n = 0;
+
+ do { n = read(fd, buffer, len); } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+static ssize_t sf_write(int fd, const void *buffer, size_t len) {
+ ssize_t n = 0;
+
+ do { n = write(fd, buffer, len); } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+static int sf_open(const char *path, int type, mode_t mode) {
+ int fd = 0;
+
+ do { fd = open(path, type, mode); } while(fd < 0 && errno == EINTR);
+
+ return fd;
+}
+static int sf_close(int fd) {
+ int res = 0;
+
+ do { res = close(fd); } while(fd < 0 && errno == EINTR);
+
+ return res;
+}
/* Extract any control sequences that are ment only for run_erl
* and should not be forwarded to the pty.
*/
diff --git a/erts/etc/unix/to_erl.c b/erts/etc/unix/to_erl.c
index 11fa3ff4cc..754b349338 100644
--- a/erts/etc/unix/to_erl.c
+++ b/erts/etc/unix/to_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -352,7 +352,10 @@ int main(int argc, char **argv)
* to trigger the version handshaking between to_erl and run_erl
* at the start of every new to_erl-session.
*/
- write(wfd, "\022", 1);
+
+ if (write(wfd, "\022", 1) < 0) {
+ fprintf(stderr, "Error in writing ^R to FIFO.\n");
+ }
/*
* read and write
@@ -412,7 +415,7 @@ int main(int argc, char **argv)
if (len) {
#ifdef DEBUG
- write(1, buf, len);
+ if(write(1, buf, len));
#endif
if (write_all(wfd, buf, len) != len) {
fprintf(stderr, "Error in writing to FIFO.\n");
diff --git a/erts/etc/win32/Makefile b/erts/etc/win32/Makefile
index 400e5c5bba..4218be1eff 100644
--- a/erts/etc/win32/Makefile
+++ b/erts/etc/win32/Makefile
@@ -59,14 +59,14 @@ opt debug all clean depend:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/bin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(ROOTSYSDIR)/usr/include
- $(INSTALL_DIR) $(ROOTSYSDIR)/usr/lib
- $(INSTALL_DIR) $(ROOTSYSDIR)/usr/lib/icons
- $(INSTALL_PROGRAM) $(INSTALL_PROGS) $(RELSYSDIR)/bin
- $(INSTALL_DATA) $(INSTALL_SRC) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INSTALL_ICONS) $(ROOTSYSDIR)/usr/lib/icons
+ $(INSTALL_DIR) "$(RELSYSDIR)/bin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(ROOTSYSDIR)/usr/include"
+ $(INSTALL_DIR) "$(ROOTSYSDIR)/usr/lib"
+ $(INSTALL_DIR) "$(ROOTSYSDIR)/usr/lib/icons"
+ $(INSTALL_PROGRAM) $(INSTALL_PROGS) "$(RELSYSDIR)/bin"
+ $(INSTALL_DATA) $(INSTALL_SRC) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INSTALL_ICONS) "$(ROOTSYSDIR)/usr/lib/icons"
release_docs release_docs_spec docs:
diff --git a/erts/etc/win32/cygwin_tools/vc/emu_cc.sh b/erts/etc/win32/cygwin_tools/vc/emu_cc.sh
index c74c35111b..6c179aed00 100755
--- a/erts/etc/win32/cygwin_tools/vc/emu_cc.sh
+++ b/erts/etc/win32/cygwin_tools/vc/emu_cc.sh
@@ -2,7 +2,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
@@ -17,6 +17,11 @@
#
# %CopyrightEnd%
#
+if [ X"$CONFIG_SUBTYPE" = X"win64" ]; then
+ GCC="x86_64-w64-mingw32-gcc.exe"
+else
+ GCC="gcc"
+fi
TOOLDIR=$ERL_TOP/erts/etc/win32/cygwin_tools/vc
COFFIX=$TOOLDIR/coffix
WTOOLDIR=`(cygpath -d $TOOLDIR 2>/dev/null || cygpath -w $TOOLDIR)`
@@ -71,7 +76,7 @@ if [ $SKIP_COFFIX = false ]; then
if [ "X$EMU_CC_SH_DEBUG_LOG" != "X" ]; then
echo "gcc -o $TEMPFILE -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer $CMD" >> $EMU_CC_SH_DEBUG_LOG 2>&1
fi
- eval gcc -o $TEMPFILE -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer $CMD
+ eval $GCC -o $TEMPFILE -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer $CMD
RES=$?
if [ $RES = 0 ]; then
$COFFIX.exe -e `(cygpath -d $TEMPFILE 2>/dev/null || cygpath -w $TEMPFILE)`
@@ -85,6 +90,6 @@ if [ $SKIP_COFFIX = false ]; then
rm -f $TEMPFILE
exit $RES
else
- eval gcc -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer -fno-tree-copyrename $CMD 2>/dev/null
+ eval $GCC -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer -fno-tree-copyrename $CMD 2>/dev/null
exit $?
fi
diff --git a/erts/etc/win32/erlsrv/erlsrv_service.c b/erts/etc/win32/erlsrv/erlsrv_service.c
index 242e2905a9..8b734b0c05 100644
--- a/erts/etc/win32/erlsrv/erlsrv_service.c
+++ b/erts/etc/win32/erlsrv/erlsrv_service.c
@@ -104,11 +104,10 @@ static VOID WINAPI handler(DWORD control){
log_debug(buffer);
switch(control){
case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_SHUTDOWN:
set_stop_pending(30000,1);
SetEvent(eventStop);
return;
- case SERVICE_CONTROL_SHUTDOWN:
- return;
default:
reset_current();
break;
diff --git a/erts/etc/win32/msys_tools/erl b/erts/etc/win32/msys_tools/erl
new file mode 100644
index 0000000000..525253fd84
--- /dev/null
+++ b/erts/etc/win32/msys_tools/erl
@@ -0,0 +1,42 @@
+#! /bin/sh
+#
+# %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%
+#
+# Note! This shellscript expects to be run in a cygwin environment,
+# it converts erlc command lines to native windows erlc commands, which
+# basically means running the command cygpath on whatever is a path...
+
+CMD=""
+for x in "$@"; do
+ case "$x" in
+ -I/*|-o/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ z=`echo $x | sed 's,^-\([Io]\)\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -$z\"$MPATH\"";;
+ /*)
+ MPATH=`msys2win_path.sh -m $x`;
+ CMD="$CMD \"$MPATH\"";;
+ *)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD \"$y\"";;
+ esac
+done
+ERL_TOP=`msys2win_path.sh -m $ERL_TOP`
+export ERL_TOP
+eval erl.exe $CMD
diff --git a/erts/etc/win32/msys_tools/erlc b/erts/etc/win32/msys_tools/erlc
new file mode 100644
index 0000000000..3f53ef7f4f
--- /dev/null
+++ b/erts/etc/win32/msys_tools/erlc
@@ -0,0 +1,59 @@
+#! /bin/sh
+#
+# %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%
+#
+
+
+CMD=""
+ECHO_ONLY=false
+for x in "$@"; do
+ case "$x" in
+ --echo_only)
+ ECHO_ONLY=true;;
+ -I/*|-o/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ z=`echo $x | sed 's,^-\([Io]\)\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -$z$MPATH";;
+ -pa/*)
+ y=`echo $x | sed 's,^-pa\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -pa $MPATH";;
+ /*)
+ MPATH=`msys2win_path.sh -m $x`;
+ CMD="$CMD \"$MPATH\"";;
+# Needed for +'{preproc_flags,whatever}'
+ +{preproc_flags,*})
+ y=`echo $x | sed 's,^+{preproc_flags\,"\(.*\)"},\1,g'`;
+ z=`eval $0 --echo_only $y`;
+ case "$z" in # Dont "doubledoublequote"
+ \"*\")
+ CMD="$CMD +'{preproc_flags,$z}'";;
+ *)
+ CMD="$CMD +'{preproc_flags,\"$z\"}'";;
+ esac;;
+ *)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD \"$y\"";;
+ esac
+done
+if [ $ECHO_ONLY = true ]; then
+ echo $CMD
+else
+ eval erlc.exe $CMD
+fi
diff --git a/erts/etc/win32/msys_tools/javac.sh b/erts/etc/win32/msys_tools/javac.sh
new file mode 100644
index 0000000000..2d884bc2c8
--- /dev/null
+++ b/erts/etc/win32/msys_tools/javac.sh
@@ -0,0 +1,65 @@
+#! /bin/sh
+#
+# %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%
+#
+# Note! This shellscript expects to be run in a cygwin environment,
+# it converts erlc command lines to native windows erlc commands, which
+# basically means running the command cygpath on whatever is a path...
+
+CMD=""
+save_IFS=$IFS
+IFS=":"
+NEWCLASSPATH=""
+for x in $CLASSPATH; do
+ TMP=`msys2win_path.sh -m $x`
+ if [ -z "$NEWCLASSPATH" ]; then
+ NEWCLASSPATH="$TMP"
+ else
+ NEWCLASSPATH="$NEWCLASSPATH;$TMP"
+ fi
+done
+IFS=$save_IFS
+CLASSPATH="$NEWCLASSPATH"
+export CLASSPATH
+#echo "CLASSPATH=$CLASSPATH"
+SAVE="$@"
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -I/*|-o/*|-d/*)
+ y=`echo $x | sed 's,^-[Iod]\(/.*\),\1,g'`;
+ z=`echo $x | sed 's,^-\([Iod]\)\(/.*\),\1,g'`;
+ #echo "Foooo:$z"
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -$z\"$MPATH\"";;
+ -d|-I|-o)
+ shift;
+ MPATH=`msys2win_path.sh -m $1`;
+ CMD="$CMD $x $MPATH";;
+ /*)
+ #echo "absolute:"$x;
+ MPATH=`msys2win_path.sh -m $x`;
+ CMD="$CMD \"$MPATH\"";;
+ *)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD \"$y\"";;
+ esac
+ shift
+done
+#echo javac.exe "$CMD"
+eval javac.exe "$CMD"
diff --git a/erts/etc/win32/msys_tools/make_bootstrap_ini.sh b/erts/etc/win32/msys_tools/make_bootstrap_ini.sh
new file mode 100644
index 0000000000..b61965f546
--- /dev/null
+++ b/erts/etc/win32/msys_tools/make_bootstrap_ini.sh
@@ -0,0 +1,44 @@
+#! /bin/bash
+#
+# %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%
+#
+# Create a local init-file for erlang in the build environment.
+if [ -z "$1" ]; then
+ echo "error: $0: No rootdir given"
+ exit 1
+else
+ RDIR=$1
+fi
+if [ -z "$2" ]; then
+ echo "error: $0: No bindir given"
+ exit 1
+else
+ BDIR=$2
+fi
+
+DRDIR=`msys2win_path.sh $RDIR | sed 's,\\\,\\\\\\\\,g'`
+DBDIR=`msys2win_path.sh $BDIR | sed 's,\\\,\\\\\\\\,g'`
+
+
+cat > $RDIR/bin/erl.ini <<EOF
+[erlang]
+Bindir=$DBDIR
+Progname=erl
+Rootdir=$DRDIR
+EOF
+
diff --git a/erts/etc/win32/msys_tools/make_local_ini.sh b/erts/etc/win32/msys_tools/make_local_ini.sh
new file mode 100644
index 0000000000..6c5d84c4f5
--- /dev/null
+++ b/erts/etc/win32/msys_tools/make_local_ini.sh
@@ -0,0 +1,41 @@
+#! /bin/bash
+#
+# %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%
+#
+# Create a local init-file for erlang in the build environment.
+if [ -z "$1" ]; then
+ if [ -z $ERL_TOP ]; then
+ echo "error: $0: No rootdir available"
+ exit 1
+ else
+ RDIR=$ERL_TOP
+ fi
+else
+ RDIR=$1
+fi
+
+DDIR=`msys2win_path.sh $RDIR | sed 's,\\\,\\\\\\\\,g'`
+
+
+cat > $RDIR/bin/erl.ini <<EOF
+[erlang]
+Bindir=$DDIR\\\\bin\\\\win32
+Progname=erl
+Rootdir=$DDIR
+EOF
+
diff --git a/erts/etc/win32/msys_tools/msys2win_path.sh b/erts/etc/win32/msys_tools/msys2win_path.sh
new file mode 100644
index 0000000000..679a9d6a8f
--- /dev/null
+++ b/erts/etc/win32/msys_tools/msys2win_path.sh
@@ -0,0 +1,44 @@
+#! /bin/bash
+MIXED=false
+ABSOLUTE=false
+done=false
+while [ $done = false ]; do
+ case "$1" in
+ -m)
+ MIXED=true;
+ shift;;
+ -a)
+ ABSOLUTE=true;
+ shift;;
+ *)
+ done=true;;
+ esac
+done
+if [ -z "$1" ]; then
+ echo "Usage: $0 <path>" >&2
+ exit 1;
+fi
+MSYS_PATH=`win2msys_path.sh "$1"` # Clean up spaces
+if [ $ABSOLUTE = true ]; then
+ MSYS_DIR=`dirname "$MSYS_PATH"`
+ MSYS_FILE=`basename "$MSYS_PATH"`
+ if [ X"$MSYS_FILE" = X".." ]; then
+ MSYS_DIR="$MSYS_DIR/$MSYS_FILE"
+ WIN_ADD=""
+ else
+ WIN_ADD="/$MSYS_FILE"
+ fi
+ SAVEDIR=`pwd`
+ cd $MSYS_DIR
+ CURRENT=`pwd`
+ cd $SAVEDIR
+ WINPATH=`cmd //C echo $CURRENT`
+ WINPATH="$WINPATH$WIN_ADD"
+else
+ WINPATH=`cmd //c echo $MSYS_PATH`
+fi
+if [ $MIXED = true ]; then
+ echo $WINPATH
+else
+ echo $WINPATH | sed 's,/,\\,g'
+fi \ No newline at end of file
diff --git a/erts/etc/win32/msys_tools/reg_query.sh b/erts/etc/win32/msys_tools/reg_query.sh
new file mode 100644
index 0000000000..ae6d5c3218
--- /dev/null
+++ b/erts/etc/win32/msys_tools/reg_query.sh
@@ -0,0 +1,24 @@
+#! /bin/sh
+BAT_FILE=/tmp/w$$.bat
+if [ -z "$1" -o -z "$2" ]; then
+ echo "Usage:" "$0" '<key> <valuename>'
+ exit 1
+fi
+BACKED=`echo "$1" | sed 's,/,\\\\,g'`
+# We need to get the 64bit part of the registry, hence we need to execute
+# a 64bit reg.exe, but c:\windows\system32 is redirected to 32bit versions
+# if we ate in the 32bit virtual environment, why we need to use the
+# sysnative trick to get to the 64bit executable of reg.exe (ouch!)
+if [ -d $WINDIR/sysnative ]; then
+ REG_CMD="$WINDIR\\sysnative\\reg.exe"
+else
+ REG_CMD="reg"
+fi
+cat > $BAT_FILE <<EOF
+@echo off
+$REG_CMD query "$BACKED" /v "$2"
+EOF
+#echo $BAT_FILE
+#cat $BAT_FILE
+RESULT=`cmd //C $BAT_FILE`
+echo $RESULT | sed "s,.*$2 REG_[^ ]* ,,"
diff --git a/erts/etc/win32/msys_tools/vc/ar.sh b/erts/etc/win32/msys_tools/vc/ar.sh
new file mode 100644
index 0000000000..f4c61e1d92
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/ar.sh
@@ -0,0 +1,47 @@
+#! /bin/sh
+#
+# %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%
+#
+CMD=""
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -out:)
+ shift
+ case "$1" in
+ /*)
+ MPATH=`msys2win_path.sh -m $1`;;
+ *)
+ MPATH=$1;;
+ esac
+ CMD="$CMD -out:\"$MPATH\"";;
+ -out:/*)
+ y=`echo $x | sed 's,^-out:\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -out:\"$MPATH\"";;
+ /*)
+ MPATH=`msys2win_path.sh -m $x`;
+ CMD="$CMD \"$MPATH\"";;
+ *)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD \"$y\"";;
+ esac
+ shift
+done
+
+eval lib.exe $CMD
diff --git a/erts/etc/win32/msys_tools/vc/cc.sh b/erts/etc/win32/msys_tools/vc/cc.sh
new file mode 100644
index 0000000000..38b3d2ee81
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/cc.sh
@@ -0,0 +1,320 @@
+#! /bin/sh
+#
+# %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%
+#
+# Icky cl wrapper that does it's best to behave like a Unixish cc.
+# Made to work for Erlang builds and to make configure happy, not really
+# general I suspect.
+# set -x
+# Save the command line for debug outputs
+
+SAVE="$@"
+
+# Constants
+COMMON_CFLAGS="-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -D_CRT_SECURE_NO_DEPRECATE"
+
+# Variables
+# The stdout and stderr for the compiler
+MSG_FILE=/tmp/cl.exe.$$.1
+ERR_FILE=/tmp/cl.exe.$$.2
+
+# "Booleans" determined during "command line parsing"
+# If the stdlib option is explicitly passed to this program
+MD_FORCED=false
+# If we're preprocession (only) i.e. -E
+PREPROCESSING=false
+# If we're generating dependencies (implies preprocesing)
+DEPENDENCIES=false
+# If this is supposed to be a debug build
+DEBUG_BUILD=false
+# If this is supposed to be an optimized build (there can only be one...)
+OPTIMIZED_BUILD=false
+# If we're linking or only compiling
+LINKING=true
+
+# This data is accumulated during command line "parsing"
+# The stdlibrary option, default multithreaded dynamic
+MD=-MD
+# Flags for debug compilation
+DEBUG_FLAGS=""
+# Flags for optimization
+OPTIMIZE_FLAGS=""
+# The specified output filename (if any), may be either object or exe.
+OUTFILE=""
+# Unspecified command line options for the compiler
+CMD=""
+# All the c source files, in unix style
+SOURCES=""
+# All the options to pass to the linker, kept in Unix style
+LINKCMD=""
+
+
+# Loop through the parameters and set the above variables accordingly
+# Also convert some cygwin filenames to "mixed style" dito (understood by the
+# compiler very well), except for anything passed to the linker, that script
+# handles those and the sources, which are also kept unixish for now
+
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -Wall)
+ ;;
+ -c)
+ LINKING=false;;
+ #CMD="$CMD -c";;
+ -MM)
+ PREPROCESSING=true;
+ LINKING=false;
+ DEPENDENCIES=true;;
+ -E)
+ PREPROCESSING=true;
+ LINKING=false;; # Obviously...
+ #CMD="$CMD -E";;
+ -Owx)
+ # Optimization hardcoded of wxErlang, needs to disable debugging too
+ OPTIMIZE_FLAGS="-Ob2ity -Gs -Zi";
+ DEBUG_FLAGS="";
+ DEBUG_BUILD=false;
+ if [ $MD_FORCED = false ]; then
+ MD=-MD;
+ fi
+ OPTIMIZED_BUILD=true;;
+ -O*)
+ # Optimization hardcoded, needs to disable debugging too
+ OPTIMIZE_FLAGS="-Ox -Zi";
+ DEBUG_FLAGS="";
+ DEBUG_BUILD=false;
+ if [ $MD_FORCED = false ]; then
+ MD=-MD;
+ fi
+ OPTIMIZED_BUILD=true;;
+ -g|-ggdb)
+ if [ $OPTIMIZED_BUILD = false ];then
+ # Hardcoded windows debug flags
+ DEBUG_FLAGS="-Z7";
+ if [ $MD_FORCED = false ]; then
+ MD=-MDd;
+ fi
+ LINKCMD="$LINKCMD -g";
+ DEBUG_BUILD=true;
+ fi;;
+ # Allow forcing of stdlib
+ -mt|-MT)
+ MD="-MT";
+ MD_FORCED=true;;
+ -md|-MD)
+ MD="-MD";
+ MD_FORCED=true;;
+ -ml|-ML)
+ MD="-ML";
+ MD_FORCED=true;;
+ -mdd|-MDD|-MDd)
+ MD="-MDd";
+ MD_FORCED=true;;
+ -mtd|-MTD|-MTd)
+ MD="-MTd";
+ MD_FORCED=true;;
+ -mld|-MLD|-MLd)
+ MD="-MLd";
+ MD_FORCED=true;;
+ -o)
+ shift;
+ OUTFILE="$1";;
+ -o*)
+ y=`echo $x | sed 's,^-[Io]\(.*\),\1,g'`;
+ OUTFILE="$y";;
+ -I/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ z=`echo $x | sed 's,^-\([Io]\)\(/.*\),\1,g'`;
+ MPATH=`echo $y`;
+ CMD="$CMD -$z\"$MPATH\"";;
+ -I*)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD $y";;
+ -D*)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD $y";;
+ -EH*)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD $y";;
+ -TP|-Tp)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD $y";;
+ -l*)
+ y=`echo $x | sed 's,^-l\(.*\),\1,g'`;
+ LINKCMD="$LINKCMD $x";;
+ /*.c)
+ SOURCES="$SOURCES $x";;
+ *.c)
+ SOURCES="$SOURCES $x";;
+ /*.cc)
+ SOURCES="$SOURCES $x";;
+ *.cc)
+ SOURCES="$SOURCES $x";;
+ /*.cpp)
+ SOURCES="$SOURCES $x";;
+ *.cpp)
+ SOURCES="$SOURCES $x";;
+ /*.o)
+ LINKCMD="$LINKCMD $x";;
+ *.o)
+ LINKCMD="$LINKCMD $x";;
+ *)
+ # Try to quote uninterpreted options
+ y=`echo $x | sed 's,",\\\",g'`;
+ LINKCMD="$LINKCMD $y";;
+ esac
+ shift
+done
+
+#Return code from compiler, linker.sh and finally this script...
+RES=0
+
+# Accumulated object names
+ACCUM_OBJECTS=""
+
+# A temporary object file location
+TMPOBJDIR=/tmp/tmpobj$$
+mkdir $TMPOBJDIR
+
+# Compile
+for x in $SOURCES; do
+ start_time=`date '+%s'`
+ # Compile each source
+ if [ $LINKING = false ]; then
+ # We should have an output defined, which is a directory
+ # or an object file
+ case $OUTFILE in
+ /*.o)
+ # Simple output, SOURCES should be one single
+ n=`echo $SOURCES | wc -w`;
+ if [ $n -gt 1 ]; then
+ echo "cc.sh:Error, multiple sources, one object output.";
+ exit 1;
+ else
+ output_filename=`echo $OUTFILE`;
+ fi;;
+ *.o)
+ # Relative path needs no translation
+ n=`echo $SOURCES | wc -w`
+ if [ $n -gt 1 ]; then
+ echo "cc.sh:Error, multiple sources, one object output."
+ exit 1
+ else
+ output_filename=$OUTFILE
+ fi;;
+ /*)
+ # Absolute directory
+ o=`echo $x | sed 's,.*/,,' | sed 's,\.c$,.o,'`
+ output_filename=`echo $OUTFILE`
+ output_filename="$output_filename/${o}";;
+ *)
+ # Relative_directory or empty string (.//x.o is valid)
+ o=`echo $x | sed 's,.*/,,' | sed 's,\.cp*$,.o,'`
+ output_filename="./${OUTFILE}/${o}";;
+ esac
+ else
+ # We are linking, which means we build objects in a temporary
+ # directory and link from there. We should retain the basename
+ # of each source to make examining the exe easier...
+ o=`echo $x | sed 's,.*/,,' | sed 's,\.c$,.o,'`
+ output_filename=$TMPOBJDIR/$o
+ ACCUM_OBJECTS="$ACCUM_OBJECTS $output_filename"
+ fi
+ # Now we know enough, lets try a compilation...
+ MPATH=`echo $x`
+ if [ $PREPROCESSING = true ]; then
+ output_flag="-E"
+ else
+ output_flag="-c -Fo`cmd //C echo ${output_filename}`"
+ fi
+ params="$COMMON_CFLAGS $MD $DEBUG_FLAGS $OPTIMIZE_FLAGS \
+ $CMD ${output_flag} $MPATH"
+ if [ "X$CC_SH_DEBUG_LOG" != "X" ]; then
+ echo cc.sh "$SAVE" >>$CC_SH_DEBUG_LOG
+ echo cl.exe $params >>$CC_SH_DEBUG_LOG
+ fi
+ eval cl.exe $params >$MSG_FILE 2>$ERR_FILE
+ RES=$?
+ if test $PREPROCESSING = false; then
+ cat $ERR_FILE >&2
+ tail -n +2 $MSG_FILE
+ else
+ tail -n +2 $ERR_FILE >&2
+ if test $DEPENDENCIES = true; then
+ if test `grep -v $x $MSG_FILE | grep -c '#line'` != "0"; then
+ o=`echo $x | sed 's,.*/,,' | sed 's,\.cp*$,.o,'`
+ echo -n $o':'
+# cat $MSG_FILE | grep '#line' | grep -v $x | awk -F\" '{printf("%s\n",$2)}' | sort -u | grep -v " " | xargs -n 1 win2msys_path.sh | awk '{printf("\\\n %s ",$0)}'
+ cat $MSG_FILE | grep '#line' | grep -v $x | awk -F\" '{printf("%s\n",$2)}' | sort -u | grep -v " " | sed 's,^\([A-Za-z]\):[\\/]*,/\1/,;s,\\\\*,/,g'| awk '{printf("\\\n %s ",$0)}'
+ echo
+ echo
+ after_sed=`date '+%s'`
+ echo Made dependencises for $x':' `expr $after_sed '-' $start_time` 's' >&2
+ fi
+ else
+ cat $MSG_FILE
+ fi
+ fi
+ rm -f $ERR_FILE $MSG_FILE
+ if [ $RES != 0 ]; then
+ rm -rf $TMPOBJDIR
+ exit $RES
+ fi
+done
+
+# If we got here, we succeeded in compiling (if there were anything to compile)
+# The output filename should name an executable if we're linking
+if [ $LINKING = true ]; then
+ case $OUTFILE in
+ "")
+ # Use the first source name to name the executable
+ first_source=""
+ for x in $SOURCES; do first_source=$x; break; done;
+ if [ -n "$first_source" ]; then
+ e=`echo $x | sed 's,.*/,,' | sed 's,\.c$,.exe,'`;
+ out_spec="-o $e";
+ else
+ out_spec="";
+ fi;;
+ *)
+ out_spec="-o $OUTFILE";;
+ esac
+ # Descide which standard library to link against
+ case $MD in
+ -ML)
+ stdlib="-lLIBC";;
+ -MLd)
+ stdlib="-lLIBCD";;
+ -MD)
+ stdlib="-lMSVCRT";;
+ -MDd)
+ stdlib="-lMSVCRTD";;
+ -MT)
+ stdlib="-lLIBCMT";;
+ -MTd)
+ stdlib="-lLIBMTD";;
+ esac
+ # And finally call the next script to do the linking...
+ params="$out_spec $LINKCMD $stdlib"
+ eval ld.sh $ACCUM_OBJECTS $params
+ RES=$?
+fi
+rm -rf $TMPOBJDIR
+
+exit $RES
diff --git a/erts/etc/win32/msys_tools/vc/coffix.c b/erts/etc/win32/msys_tools/vc/coffix.c
new file mode 100644
index 0000000000..1773b222fe
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/coffix.c
@@ -0,0 +1,161 @@
+/*
+ * %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%
+ */
+/*
+** This mini tool fixes an incompatibility between
+** Microsoft's tools, who dont like the virtual size being put in
+** the physical address field, but rely on the raw size field for
+** sizing the ".bss" section.
+** This fixes some of the problems with linking gcc compiled objects
+** together with MSVC dito.
+**
+** Courtesy DJ Delorie for describing the COFF file format on
+** http://www.delorie.com/djgpp/doc/coff/
+** The coff structures are fetched from Microsofts headers though.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <windows.h>
+#include <winnt.h> /* Structure definitions for PE (COFF) */
+
+static int dump_edit(char *filename, int edit);
+static int v_printf(char *format, ...);
+
+
+char *progname;
+int verbouse = 0;
+
+int main(int argc, char **argv)
+{
+ int findex = 1;
+ int edit = 0;
+ int ret;
+
+ progname = argv[0];
+ if (argc == 1) {
+ fprintf(stderr,"Format : %s [-e] [-v] <filename>\n", progname);
+ return 1;
+ }
+ for (findex = 1;
+ findex < argc && (*argv[findex] == '-' || *argv[findex] == '/');
+ ++findex)
+ switch (argv[findex][1]) {
+ case 'e':
+ case 'E':
+ edit = 1;
+ break;
+ case 'v':
+ case 'V':
+ verbouse = 1;
+ default:
+ fprintf(stderr, "%s: unknown option %s\n", progname, argv[findex]);
+ break;
+ }
+ if (findex == argc) {
+ fprintf(stderr,"%s: No filenames given.\n", progname);
+ return 1;
+ }
+ for(; findex < argc; ++findex)
+ if ((ret = dump_edit(argv[findex],edit)) != 0)
+ return ret;
+ return 0;
+}
+
+int dump_edit(char *filename, int edit)
+{
+ FILE *f = fopen(filename, (edit) ? "r+b" : "rb");
+ IMAGE_FILE_HEADER filhdr;
+ IMAGE_SECTION_HEADER scnhdr;
+ int i;
+
+ if (f == NULL) {
+ fprintf(stderr, "%s: cannot open %s.\n", progname, filename);
+ return 1;
+ }
+
+ if (fread(&filhdr, sizeof(filhdr), 1, f) == 0) {
+ fprintf(stderr,"%s: Could not read COFF header from %s,"
+ " is this a PE (COFF) file?\n", progname, filename);
+ fclose(f);
+ return 1;
+ }
+ v_printf("File: %s\n", filename);
+ v_printf("Magic number: 0x%08x\n", filhdr.Machine);
+ v_printf("Number of sections: %d\n",filhdr.NumberOfSections);
+
+ if (fseek(f, (long) filhdr.SizeOfOptionalHeader, SEEK_CUR) != 0) {
+ fprintf(stderr,"%s: Could not read COFF optional header from %s,"
+ " is this a PE (COFF) file?\n", progname, filename);
+ fclose(f);
+ return 1;
+ }
+
+ for (i = 0; i < filhdr.NumberOfSections; ++i) {
+ if (fread(&scnhdr, sizeof(scnhdr), 1, f) == 0) {
+ fprintf(stderr,"%s: Could not read section header from %s,"
+ " is this a PE (COFF) file?\n", progname, filename);
+ fclose(f);
+ return 1;
+ }
+ v_printf("Section %s:\n", scnhdr.Name);
+ v_printf("Physical address: 0x%08x\n", scnhdr.Misc.PhysicalAddress);
+ v_printf("Size: 0x%08x\n", scnhdr.SizeOfRawData);
+ if (scnhdr.Misc.PhysicalAddress != 0 &&
+ scnhdr.SizeOfRawData == 0) {
+ printf("Section header %s in file %s will confuse MSC linker, "
+ "virtual size is 0x%08x and raw size is 0\n",
+ scnhdr.Name, filename, scnhdr.Misc.PhysicalAddress,
+ scnhdr.SizeOfRawData);
+ if (edit) {
+ scnhdr.SizeOfRawData = scnhdr.Misc.PhysicalAddress;
+ scnhdr.Misc.PhysicalAddress = 0;
+ if (fseek(f, (long) -((long)sizeof(scnhdr)), SEEK_CUR) != 0 ||
+ fwrite(&scnhdr, sizeof(scnhdr), 1, f) == 0) {
+ fprintf(stderr,"%s: could not edit file %s.\n",
+ progname, filename);
+ fclose(f);
+ return 1;
+ }
+ printf("Edited object, virtual size is now 0, and "
+ "raw size is 0x%08x.\n", scnhdr.SizeOfRawData);
+ } else {
+ printf("Specify option '-e' to correct the problem.\n");
+ }
+ }
+ }
+ fclose(f);
+ return 0;
+}
+
+
+static int v_printf(char *format, ...)
+{
+ va_list ap;
+ int ret = 0;
+ if (verbouse) {
+ va_start(ap, format);
+ ret = vfprintf(stdout, format, ap);
+ va_end(ap);
+ }
+ return ret;
+}
+
diff --git a/erts/etc/win32/msys_tools/vc/emu_cc.sh b/erts/etc/win32/msys_tools/vc/emu_cc.sh
new file mode 100644
index 0000000000..68ce4e359f
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/emu_cc.sh
@@ -0,0 +1,95 @@
+#! /bin/sh
+#
+# %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%
+#
+if [ X"$CONFIG_SUBTYPE" = X"win64" ]; then
+ GCC="x86_64-w64-mingw32-gcc.exe"
+else
+ GCC="gcc"
+fi
+TOOLDIR=$ERL_TOP/erts/etc/win32/msys_tools/vc
+COFFIX=$TOOLDIR/coffix
+WTOOLDIR0=`win2msys_path.sh "$TOOLDIR"`
+WTOOLDIR=`cmd //C echo $WTOOLDIR0`
+# Do primitive 'make'
+newer_exe=`find $TOOLDIR -newer $COFFIX.c -name coffix.exe -print`
+if [ -z $newer_exe ]; then
+ echo recompiling $COFFIX.exe
+ cl.exe -Fe${WTOOLDIR}/coffix.exe ${WTOOLDIR}/coffix.c
+ rm -f $COFFIX.obj coffix.obj $COFFIX.pdb coffix.pdb
+fi
+
+# Try to find out the output filename and remove it from command line
+CMD=""
+OUTFILE=""
+INFILE=""
+SKIP_COFFIX=false
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -o/*)
+ OUTFILE=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;;
+ -o)
+ shift
+ OUTFILE=$1;;
+ -MM)
+ SKIP_COFFIX=true
+ CMD="$CMD \"$x\"";;
+ *.c)
+ INFILE="$INFILE $x";
+ CMD="$CMD \"$x\"";;
+ *)
+ CMD="$CMD \"$x\"";;
+ esac
+ shift
+done
+if [ -z "$INFILE" ]; then
+ echo 'emu_cc.sh: please give an input filename for the compiler' >&2
+ exit 1
+fi
+if [ -z "$OUTFILE" ]; then
+ OUTFILE=`echo $INFILE | sed 's,\.c$,.o,'`
+fi
+
+if [ $SKIP_COFFIX = false ]; then
+ n=`echo $INFILE | wc -w`;
+ if [ $n -gt 1 ]; then
+ echo "emu_cc.sh:Error, multiple sources, one object output.";
+ exit 1;
+ fi
+ TEMPFILE=/tmp/tmp_emu_cc$$.o
+ if [ "X$EMU_CC_SH_DEBUG_LOG" != "X" ]; then
+ echo "$GCC -o $TEMPFILE -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer $CMD" >> $EMU_CC_SH_DEBUG_LOG 2>&1
+ fi
+ eval $GCC -o $TEMPFILE -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer $CMD
+ RES=$?
+ if [ $RES = 0 ]; then
+ $COFFIX.exe -e `win2msys_path.sh $TEMPFILE`
+ RES=$?
+ if [ $RES = 0 ]; then
+ cp $TEMPFILE $OUTFILE
+ else
+ echo "emu_cc.sh: fatal: coffix failed!" >&2
+ fi
+ fi
+ rm -f $TEMPFILE
+ exit $RES
+else
+ eval $GCC -D__WIN32__ -DWIN32 -DWINDOWS -fomit-frame-pointer -fno-tree-copyrename $CMD 2>/dev/null
+ exit $?
+fi
diff --git a/erts/etc/win32/msys_tools/vc/ld.sh b/erts/etc/win32/msys_tools/vc/ld.sh
new file mode 100644
index 0000000000..0fcbf6f7d9
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/ld.sh
@@ -0,0 +1,198 @@
+#! /bin/sh
+# set -x
+#
+# %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%
+#
+# Save the command line for debug outputs
+
+SAVE="$@"
+kernel_libs="kernel32.lib advapi32.lib"
+gdi_libs="gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib"
+DEFAULT_LIBRARIES="$kernel_libs $gdi_libs"
+
+CMD=""
+STDLIB=MSVCRT.LIB
+DEBUG_BUILD=false
+STDLIB_FORCED=false
+BUILD_DLL=false
+OUTPUT_FILENAME=""
+
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -dll| -DLL)
+ BUILD_DLL=true;;
+ -L/*|-L.*)
+ y=`echo $x | sed 's,^-L\(.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -libpath:\"$MPATH\"";;
+ -lMSVCRT|-lmsvcrt)
+ STDLIB_FORCED=true;
+ STDLIB=MSVCRT.LIB;;
+ -lMSVCRTD|-lmsvcrtd)
+ STDLIB_FORCED=true;
+ STDLIB=MSVCRTD.LIB;;
+ -lLIBCMT|-llibcmt)
+ STDLIB_FORCED=true;
+ STDLIB=LIBCMT.LIB;;
+ -lLIBCMTD|-llibcmtd)
+ STDLIB_FORCED=true;
+ STDLIB=LIBCMTD.LIB;;
+ -lsocket)
+ DEFAULT_LIBRARIES="$DEFAULT_LIBRARIES WS2_32.LIB IPHLPAPI.LIB";;
+ -l*)
+ y=`echo $x | sed 's,^-l\(.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD \"${MPATH}.lib\"";;
+ -g)
+ DEBUG_BUILD=true;;
+ -pdb:none|-incremental:no)
+ ;;
+ -implib:*)
+ y=`echo $x | sed 's,^-implib:\(.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -implib:\"${MPATH}\"";;
+ -def:*)
+ y=`echo $x | sed 's,^-def:\(.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -def:\"${MPATH}\"";;
+ -o)
+ shift
+ MPATH=`msys2win_path.sh -m $1`;
+ OUTPUT_FILENAME="$MPATH";;
+ -o/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ OUTPUT_FILENAME="$MPATH";;
+ /*)
+ MPATH=`msys2win_path.sh -m $x`;
+ CMD="$CMD \"$MPATH\"";;
+ *)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD \"$y\"";;
+ esac
+ shift
+done
+if [ $DEBUG_BUILD = true ]; then
+ linktype="-debug -pdb:none"
+ if [ $STDLIB_FORCED = false ]; then
+ STDLIB=MSVCRTD.LIB
+ fi
+fi
+# Generate a PDB
+linkadd_pdb=""
+case "$OUTPUT_FILENAME" in
+ *.exe|*.EXE)
+ fn=`echo "$OUTPUT_FILENAME" | sed 's,[eE][xX][eE]$,,g'`;
+ linkadd_pdb="-pdb:\"${fn}pdb\"";;
+ *.dll|*.DLL)
+ fn=`echo "$OUTPUT_FILENAME" | sed 's,[dD][lL][lL]$,,g'`;
+ linkadd_pdb="-pdb:\"${fn}pdb\"";;
+ "")
+ linkadd_pdb="-pdb:\"a.pdb\"";;
+ *)
+ linkadd_pdb="-pdb:\"${OUTPUT_FILENAME}.pdb\"";;
+esac
+
+ linktype="-debug $linkadd_pdb"
+
+CHMOD_FILE=""
+
+if [ $BUILD_DLL = true ];then
+ case "$OUTPUT_FILENAME" in
+ *.exe|*.EXE)
+ echo "Warning, output set to .exe when building DLL" >&2
+ CHMOD_FILE="$OUTPUT_FILENAME";
+ CMD="-dll -out:\"$OUTPUT_FILENAME\" $CMD";
+ OUTPUTRES="${OUTPUT_FILENAME}\;2";
+ MANIFEST="${OUTPUT_FILENAME}.manifest";;
+ *.dll|*.DLL)
+ CMD="-dll -out:\"$OUTPUT_FILENAME\" $CMD";
+ OUTPUTRES="${OUTPUT_FILENAME}\;2";
+ MANIFEST="${OUTPUT_FILENAME}.manifest";;
+ "")
+ CMD="-dll -out:\"a.dll\" $CMD";
+ OUTPUTRES="a.dll\;2";
+ MANIFEST="a.dll.manifest";;
+ *)
+ CMD="-dll -out:\"${OUTPUT_FILENAME}.dll\" $CMD";
+ OUTPUTRES="${OUTPUT_FILENAME}.dll\;2";
+ MANIFEST="${OUTPUT_FILENAME}.dll.manifest";;
+ esac
+else
+ case "$OUTPUT_FILENAME" in
+ *.exe|*.EXE)
+ CHMOD_FILE="$OUTPUT_FILENAME";
+ CMD="-out:\"$OUTPUT_FILENAME\" $CMD";
+ OUTPUTRES="${OUTPUT_FILENAME}\;1"
+ MANIFEST="${OUTPUT_FILENAME}.manifest";;
+ *.dll|*.DLL)
+ echo "Warning, output set to .dll when building EXE" >&2
+ CMD="-out:\"$OUTPUT_FILENAME\" $CMD";
+ OUTPUTRES="${OUTPUT_FILENAME}\;1";
+ MANIFEST="${OUTPUT_FILENAME}.manifest";;
+ "")
+ CHMOD_FILE="a.exe";
+ CMD="-out:\"a.exe\" $CMD";
+ OUTPUTRES="a.exe\;1";
+ MANIFEST="a.exe.manifest";;
+ *)
+ CMD="-out:\"${OUTPUT_FILENAME}.exe\" $CMD";
+ OUTPUTRES="${OUTPUT_FILENAME}.exe\;1";
+ MANIFEST="${OUTPUT_FILENAME}.exe.manifest";;
+ esac
+fi
+
+p=$$
+CMD="$linktype -nologo -incremental:no $CMD $STDLIB $DEFAULT_LIBRARIES"
+if [ "X$LD_SH_DEBUG_LOG" != "X" ]; then
+ echo ld.sh "$SAVE" >>$LD_SH_DEBUG_LOG
+ echo link.exe $CMD >>$LD_SH_DEBUG_LOG
+fi
+eval link.exe "$CMD" >/tmp/link.exe.${p}.1 2>/tmp/link.exe.${p}.2
+RES=$?
+
+CMANIFEST=`win2msys_path.sh $MANIFEST`
+if [ "$RES" = "0" -a -f "$CMANIFEST" ]; then
+ # Add stuff to manifest to turn off "virtualization"
+ sed -n -i '1h;1!H;${;g;s,<trustInfo.*</trustInfo>.,,g;p;}' $CMANIFEST 2>/dev/null
+ sed -i "s/<\/assembly>/ <ms_asmv2:trustInfo xmlns:ms_asmv2=\"urn:schemas-microsoft-com:asm.v2\">\n <ms_asmv2:security>\n <ms_asmv2:requestedPrivileges>\n <ms_asmv2:requestedExecutionLevel level=\"AsInvoker\" uiAccess=\"false\"\/>\n <\/ms_asmv2:requestedPrivileges>\n <\/ms_asmv2:security>\n <\/ms_asmv2:trustInfo>\n<\/assembly>/" $CMANIFEST 2>/dev/null
+
+ eval mt.exe -nologo -manifest "$MANIFEST" -outputresource:"$OUTPUTRES" >>/tmp/link.exe.${p}.1 2>>/tmp/link.exe.${p}.2
+ RES=$?
+ if [ "$RES" != "0" ]; then
+ REMOVE=`echo "$OUTPUTRES" | sed 's,\\\;[12]$,,g'`
+ CREMOVE=`cygpath $REMOVE`
+ rm -f "$CREMOVE"
+ fi
+ rm -f "$CMANIFEST"
+fi
+
+# This works around some strange behaviour
+# in cygwin 1.7 Beta on Windows 7 with samba drive.
+# Configure will think the compiler failed if test -x fails,
+# which it might do as we might not be the owner of the
+# file.
+if [ '!' -z "$CHMOD_FILE" -a -s "$CHMOD_FILE" -a '!' -x "$CHMOD_FILE" ]; then
+ chmod +x $CHMOD_FILE
+fi
+
+tail -n +2 /tmp/link.exe.${p}.2 >&2
+cat /tmp/link.exe.${p}.1
+rm -f /tmp/link.exe.${p}.2 /tmp/link.exe.${p}.1
+exit $RES
diff --git a/erts/etc/win32/msys_tools/vc/mc.sh b/erts/etc/win32/msys_tools/vc/mc.sh
new file mode 100644
index 0000000000..27d985f73e
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/mc.sh
@@ -0,0 +1,87 @@
+#! /bin/sh
+# set -x
+#
+# %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%
+#
+# Save the command line for debug outputs
+SAVE="$@"
+CMD=""
+OUTPUT_DIRNAME=""
+
+# Find the correct mc.exe. This could be done by the configure script,
+# But as we seldom use the message compiler, it might as well be done here...
+MCC=""
+save_ifs=$IFS
+IFS=:
+for p in $PATH; do
+ if [ -f $p/mc.exe ]; then
+ if [ -n "`$p/mc.exe -? 2>&1 >/dev/null </dev/null \
+ | grep -i \"message compiler\"`" ]; then
+ MCC=`echo "$p/mc.exe" | sed 's/ /\\\\ /g'`
+ fi
+ fi
+done
+IFS=$save_ifs
+
+if [ -z "$MCC" ]; then
+ echo 'mc.exe not found!' >&2
+ exit 1
+fi
+
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -o)
+ shift
+ OUTPUT_DIRNAME="$1";;
+ -o/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ OUTPUT_DIRNAME="$y";;
+ -I)
+ shift
+ MPATH=`msys2win_path.sh -m $1`;
+ CMD="$CMD -I\"$MPATH\"";;
+ -I/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -I\"$MPATH\"";;
+ *)
+ MPATH=`msys2win_path.sh -m -a $x`;
+ CMD="$CMD \"$MPATH\"";;
+ esac
+ shift
+done
+p=$$
+if [ "X$MC_SH_DEBUG_LOG" != "X" ]; then
+ echo mc.sh "$SAVE" >>$MC_SH_DEBUG_LOG
+ echo mc.exe $CMD >>$MC_SH_DEBUG_LOG
+fi
+if [ -n "$OUTPUT_DIRNAME" ]; then
+ cd $OUTPUT_DIRNAME
+ RES=$?
+ if [ "$RES" != "0" ]; then
+ echo "mc.sh: Error: could not cd to $OUTPUT_DIRNAME">&2
+ exit $RES
+ fi
+fi
+eval $MCC "$CMD" >/tmp/mc.exe.${p}.1 2>/tmp/mc.exe.${p}.2
+RES=$?
+tail +2 /tmp/mc.exe.${p}.2 >&2
+cat /tmp/mc.exe.${p}.1
+rm -f /tmp/mc.exe.${p}.2 /tmp/mc.exe.${p}.1
+exit $RES
diff --git a/erts/etc/win32/msys_tools/vc/rc.sh b/erts/etc/win32/msys_tools/vc/rc.sh
new file mode 100644
index 0000000000..dfa9e324db
--- /dev/null
+++ b/erts/etc/win32/msys_tools/vc/rc.sh
@@ -0,0 +1,86 @@
+#! /bin/sh
+# set -x
+#
+# %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%
+#
+# Save the command line for debug outputs
+SAVE="$@"
+CMD=""
+OUTPUT_FILENAME=""
+
+# Find the correct rc.exe. This could be done by the configure script,
+# But as we seldom use the resource compiler, it might as well be done here...
+RCC=""
+save_ifs=$IFS
+IFS=:
+for p in $PATH; do
+ if [ -f $p/rc.exe ]; then
+ if [ -n "`$p/rc.exe -? 2>&1 | grep -i "resource compiler"`" ]; then
+ RCC=`echo "$p/rc.exe" | sed 's/ /\\\\ /g'`
+ fi
+ fi
+done
+IFS=$save_ifs
+
+if [ -z "$RCC" ]; then
+ echo 'rc.exe not found!' >&2
+ exit 1
+fi
+
+while test -n "$1" ; do
+ x="$1"
+ case "$x" in
+ -o)
+ shift
+ MPATH=`msys2win_path.sh -m $1`;
+ OUTPUT_FILENAME="$MPATH";;
+ -o/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ OUTPUT_FILENAME="$MPATH";;
+ -I)
+ shift
+ MPATH=`msys2win_path.sh -m $1`;
+ CMD="$CMD -I\"$MPATH\"";;
+ -I/*)
+ y=`echo $x | sed 's,^-[Io]\(/.*\),\1,g'`;
+ MPATH=`msys2win_path.sh -m $y`;
+ CMD="$CMD -I\"$MPATH\"";;
+ /*)
+ MPATH=`msys2win_path.sh -m $x`;
+ CMD="$CMD \"$MPATH\"";;
+ *)
+ y=`echo $x | sed 's,",\\\",g'`;
+ CMD="$CMD \"$y\"";;
+ esac
+ shift
+done
+p=$$
+if [ -n "$OUTPUT_FILENAME" ]; then
+ CMD="-Fo$OUTPUT_FILENAME $CMD"
+fi
+if [ "X$RC_SH_DEBUG_LOG" != "X" ]; then
+ echo rc.sh "$SAVE" >>$RC_SH_DEBUG_LOG
+ echo rc.exe $CMD >>$RC_SH_DEBUG_LOG
+fi
+eval $RCC "$CMD" >/tmp/rc.exe.${p}.1 2>/tmp/rc.exe.${p}.2
+RES=$?
+tail +2 /tmp/rc.exe.${p}.2 >&2
+cat /tmp/rc.exe.${p}.1
+rm -f /tmp/rc.exe.${p}.2 /tmp/rc.exe.${p}.1
+exit $RES
diff --git a/erts/etc/win32/msys_tools/win2msys_path.sh b/erts/etc/win32/msys_tools/win2msys_path.sh
new file mode 100644
index 0000000000..6558a15ecd
--- /dev/null
+++ b/erts/etc/win32/msys_tools/win2msys_path.sh
@@ -0,0 +1,38 @@
+#! /bin/bash
+if [ -z "$1" ]; then
+ echo "Usage: $0 <path>" >&2
+ exit 1;
+fi
+
+MSYS_PATH=`echo "$1" | sed 's,^\([a-zA-Z]\):\\\\,/\L\1/,;s,\\\\,/,g'`
+if [ -z "$MSYS_PATH" ]; then
+ echo "$0: Could not translate $1 to msys format" >&2
+ exit 2;
+fi
+
+DELBLANK=`echo "$MSYS_PATH" | sed 's, ,,g'`
+
+if [ "X$DELBLANK" != "X$MSYS_PATH" ]; then
+ if [ -d "$MSYS_PATH" ]; then
+ C1=`(cd "$MSYS_PATH" && cmd //C "for %i in (".") do @echo %~fsi")`
+ MSYS_PATH=`echo "$C1" | sed 's,^\([a-zA-Z]\):\\\\,/\L\1/,;s,\\\\,/,g'`
+ else
+ MSYS_DIR=`dirname "$MSYS_PATH"`
+ MSYS_FILE=`basename "$MSYS_PATH"`
+ if [ -d "$MSYS_DIR" ]; then
+ C1=`(cd "$MSYS_DIR" && cmd //C "for %i in (".") do @echo %~fsi")`
+ BAT_FILE=/tmp/w$$.bat
+ # I simply cannot get the quoting right for this,
+ # need an intermediate bat file
+ cat > $BAT_FILE <<EOF
+@echo off
+for %%i in ("$MSYS_FILE") do @echo %%~snxi
+EOF
+ C2=`(cd "$MSYS_DIR" && cmd //C $BAT_FILE)`
+ rm -f $BAT_FILE
+ MSYS_PATH=`echo "$C1/$C2" | sed 's,^\([a-zA-Z]\):\\\\,/\L\1/,;s,\\\\,/,g;s," ", ,g'`
+ fi
+ fi
+fi
+echo $MSYS_PATH
+exit 0 \ No newline at end of file
diff --git a/erts/etc/win32/nsis/Makefile b/erts/etc/win32/nsis/Makefile
index ae2343b420..4ed4ef2700 100644
--- a/erts/etc/win32/nsis/Makefile
+++ b/erts/etc/win32/nsis/Makefile
@@ -40,10 +40,29 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
TARGET_DIR = $(RELEASE_PATH)
-WTESTROOT=$(shell (cygpath -d $(RELEASE_PATH) 2>/dev/null || cygpath -w $(RELEASE_PATH)))
-WTARGET_DIR=$(shell (cygpath -d $(TARGET_DIR) 2>/dev/null || cygpath -d $(TARGET_DIR)))
+
+ifeq ($(MSYSTEM),MINGW32)
+
+ MAKENSISFLAGS = //V2
+ WTESTROOT=$(shell (msys2win_path.sh "$(RELEASE_PATH)"))
+ WTARGET_DIR=$(shell (msys2win_path.sh "$(TARGET_DIR)"))
+
+else
+
+ MAKENSISFLAGS = /V2
+ WTESTROOT=$(shell (cygpath -d "$(RELEASE_PATH)" 2>/dev/null || cygpath -w "$(RELEASE_PATH)"))
+ WTARGET_DIR=$(shell (cygpath -d "$(TARGET_DIR)" 2>/dev/null || cygpath -d "$(TARGET_DIR)"))
+
+endif
+
+ifeq ($(CONFIG_SUBTYPE),win64)
+ WINTYPE=win64
+else
+ WINTYPE=win32
+endif
REDIST_FILE=$(shell (sh ./find_redist.sh || echo ""))
+REDIST_TARGET=$(shell (sh ./find_redist.sh -n || echo ""))
REDIST_DLL_VERSION=$(shell (sh ./dll_version_helper.sh || echo ""))
REDIST_DLL_NAME=$(shell (sh ./dll_version_helper.sh -n || echo ""))
@@ -55,7 +74,7 @@ release_spec:
echo '!define ERTS_VERSION "$(VSN)"' >> $(VERSION_HEADER);\
echo '!define TESTROOT "$(WTESTROOT)"' >> $(VERSION_HEADER);\
echo '!define OUTFILEDIR "$(WTARGET_DIR)"' >> $(VERSION_HEADER);\
- if [ -f $(RELEASE_PATH)/docs/doc/index.html ];\
+ if [ -f "$(RELEASE_PATH)/docs/doc/index.html" ];\
then\
echo '!define HAVE_DOCS 1' >> $(VERSION_HEADER); \
fi;\
@@ -65,18 +84,20 @@ release_spec:
echo '!define ERTS_VERSION "$(VSN)"' >> $(VERSION_HEADER);\
echo '!define TESTROOT "$(WTESTROOT)"' >> $(VERSION_HEADER);\
echo '!define OUTFILEDIR "$(WTARGET_DIR)"' >> $(VERSION_HEADER);\
+ echo '!define WINTYPE "$(WINTYPE)"' >> $(VERSION_HEADER);\
if [ -f $(CUSTOM_MODERN) ];\
then \
echo '!define HAVE_CUSTOM_MODERN 1' >> $(VERSION_HEADER); \
fi;\
if [ '!' -z "$(REDIST_FILE)" -a '!' -z "$(REDIST_DLL_VERSION)" ];\
then \
- cp $(REDIST_FILE) $(RELEASE_PATH)/vcredist_x86.exe;\
+ cp $(REDIST_FILE) "$(RELEASE_PATH)/$(REDIST_TARGET);"\
echo '!define HAVE_REDIST_FILE 1' >> $(VERSION_HEADER); \
echo '!define REDIST_DLL_VERSION "$(REDIST_DLL_VERSION)"' >> $(VERSION_HEADER);\
echo '!define REDIST_DLL_NAME "$(REDIST_DLL_NAME)"' >> $(VERSION_HEADER);\
+ echo '!define REDIST_EXECUTABLE "$(REDIST_TARGET)"' >> $(VERSION_HEADER);\
fi;\
- if [ -f $(RELEASE_PATH)/docs/doc/index.html ];\
+ if [ -f "$(RELEASE_PATH)/docs/doc/index.html" ];\
then \
echo '!define HAVE_DOCS 1' >> $(VERSION_HEADER); \
fi;\
diff --git a/erts/etc/win32/nsis/dll_version_helper.sh b/erts/etc/win32/nsis/dll_version_helper.sh
index eecd4a72b5..96e4532b7a 100755
--- a/erts/etc/win32/nsis/dll_version_helper.sh
+++ b/erts/etc/win32/nsis/dll_version_helper.sh
@@ -36,11 +36,11 @@ int main(void)
}
EOF
-cl /MD hello.c > /dev/null 2>&1
+cl -MD hello.c > /dev/null 2>&1
if [ '!' -f hello.exe.manifest ]; then
# Gah - VC 2010 changes the way it handles DLL's and manifests... Again...
# need another way of getting the version
- DLLNAME=`dumpbin.exe /imports hello.exe | egrep MSVCR.*dll`
+ DLLNAME=`dumpbin.exe -imports hello.exe | egrep MSVCR.*dll`
DLLNAME=`echo $DLLNAME`
cat > helper.c <<EOF
#include <windows.h>
@@ -59,11 +59,7 @@ int main(void)
char *vs_verinfo;
unsigned int vs_ver_size;
- struct LANGANDCODEPAGE {
- WORD language;
- WORD codepage;
- } *translate;
-
+ WORD *translate;
unsigned int tr_size;
if (!(versize = GetFileVersionInfoSize(REQ_MODULE,&dummy))) {
@@ -79,10 +75,10 @@ int main(void)
fprintf(stderr,"No translation info in %s!\n",REQ_MODULE);
exit(3);
}
- n = tr_size/sizeof(translate);
+ n = tr_size/(2*sizeof(*translate));
for(i=0; i < n; ++i) {
sprintf(buff,"\\\\StringFileInfo\\\\%04x%04x\\\\FileVersion",
- translate[i].language,translate[i].codepage);
+ translate[i*2],translate[i*2+1]);
if (VerQueryValue(versinfo,buff,&vs_verinfo,&vs_ver_size)) {
printf("%s\n",(char *) vs_verinfo);
return 0;
@@ -92,7 +88,7 @@ int main(void)
return 0;
}
EOF
- cl /MD helper.c version.lib > /dev/null 2>&1
+ cl -MD helper.c version.lib > /dev/null 2>&1
if [ '!' -f helper.exe ]; then
echo "Failed to build helper program." >&2
exit 1
diff --git a/erts/etc/win32/nsis/erlang20.nsi b/erts/etc/win32/nsis/erlang20.nsi
index 941e8e6f5d..c5ada9e3b3 100644
--- a/erts/etc/win32/nsis/erlang20.nsi
+++ b/erts/etc/win32/nsis/erlang20.nsi
@@ -4,6 +4,25 @@
; Original example written by Joost Verburg
; Modified for Erlang by Patrik
+;
+; %CopyrightBegin%
+;
+; Copyright Ericsson AB 2012. All Rights Reserved.
+;
+; The contents of this file are subject to the Erlang Public License,
+; Version 1.1, (the "License"); you may not use this file except in
+; compliance with the License. You should have received a copy of the
+; Erlang Public License along with this software. If not, it can be
+; retrieved online at http://www.erlang.org/.
+;
+; Software distributed under the License is distributed on an "AS IS"
+; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+; the License for the specific language governing rights and limitations
+; under the License.
+;
+; %CopyrightEnd%
+;
+
; Verbosity does not come naturally with MUI, have to set it back now and then.
!verbose 1
!define MUI_MANUALVERBOSE 1
@@ -31,17 +50,24 @@ Var STARTMENU_FOLDER
!define MY_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
;General
- OutFile "${OUTFILEDIR}\otp_win32_${OTP_VERSION}.exe"
+ OutFile "${OUTFILEDIR}\otp_${WINTYPE}_${OTP_VERSION}.exe"
;Folder selection page
+!if ${WINTYPE} == "win64"
+ InstallDir "$PROGRAMFILES64\erl${ERTS_VERSION}"
+!else
InstallDir "$PROGRAMFILES\erl${ERTS_VERSION}"
-
+!endif
;Remember install folder
InstallDirRegKey HKLM "SOFTWARE\Ericsson\Erlang\${ERTS_VERSION}" ""
; Set the default start menu folder
+!if ${WINTYPE} == "win64"
+ !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${OTP_PRODUCT} ${OTP_VERSION} (x64)"
+!else
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${OTP_PRODUCT} ${OTP_VERSION}"
+!endif
;--------------------------------
;Modern UI Configuration
@@ -98,12 +124,15 @@ Var STARTMENU_FOLDER
Section "Microsoft redistributable libraries." SecMSRedist
SetOutPath "$INSTDIR"
- File "${TESTROOT}\vcredist_x86.exe"
+ File "${TESTROOT}\${REDIST_EXECUTABLE}"
; Set back verbosity...
!verbose 1
-; Run the setup program
- ExecWait '"$INSTDIR\vcredist_x86.exe"'
+; Run the setup program
+ IfSilent +3
+ ExecWait '"$INSTDIR\${REDIST_EXECUTABLE}"'
+ Goto +2
+ ExecWait '"$INSTDIR\${REDIST_EXECUTABLE}" /q'
!verbose 1
SectionEnd ; MSRedist
@@ -310,24 +339,32 @@ Function DllVersionGoodEnough
FunctionEnd
Function .onInit
- SectionGetFlags 0 $MYTEMP
- ;MessageBox MB_YESNO "Found $SYSDIR\${REDIST_DLL_NAME}" IDYES FoundLbl
- IfFileExists $SYSDIR\${REDIST_DLL_NAME} MaybeFoundInSystemLbl
- SearchSxsLbl:
- FindFirst $0 $1 $WINDIR\WinSxS\x86*
+ Var /GLOBAL archprefix
+ Var /GLOBAL sysnativedir
+ SectionGetFlags 0 $MYTEMP
+ StrCmpS ${WINTYPE} "win64" +1 +4
+ StrCpy $archprefix "amd64"
+ StrCpy $sysnativedir "$WINDIR\sysnative"
+ Goto +3
+ StrCpy $archprefix "x86"
+ StrCpy $sysnativedir $SYSDIR
+ ;MessageBox MB_YESNO "Found $sysnativedir\${REDIST_DLL_NAME}" IDYES FoundLbl
+ IfFileExists $sysnativedir\${REDIST_DLL_NAME} MaybeFoundInSystemLbl
+ SearchSxSLbl:
+ FindFirst $0 $1 $WINDIR\WinSxS\$archprefix*
LoopLbl:
StrCmp $1 "" NotFoundLbl
- IfFileExists $WINDIR\WinSxS\$1\${REDIST_DLL_NAME} MaybeFoundInSxsLbl
+ IfFileExists $WINDIR\WinSxS\$1\${REDIST_DLL_NAME} MaybeFoundInSxSLbl
FindNext $0 $1
Goto LoopLbl
- MaybeFoundInSxsLbl:
+ MaybeFoundInSxSLbl:
GetDllVersion $WINDIR\WinSxS\$1\${REDIST_DLL_NAME} $R0 $R1
Call DllVersionGoodEnough
FindNext $0 $1
IntCmp 2 $R0 LoopLbl
Goto FoundLbl
MaybeFoundInSystemLbl:
- GetDllVersion $SYSDIR\${REDIST_DLL_NAME} $R0 $R1
+ GetDllVersion $sysnativedir\${REDIST_DLL_NAME} $R0 $R1
Call DllVersionGoodEnough
IntCmp 2 $R0 SearchSxSLbl
FoundLbl:
diff --git a/erts/etc/win32/nsis/erlang_uninst.ico b/erts/etc/win32/nsis/erlang_uninst.ico
index edbd8a6f2c..edbd8a6f2c 100755..100644
--- a/erts/etc/win32/nsis/erlang_uninst.ico
+++ b/erts/etc/win32/nsis/erlang_uninst.ico
Binary files differ
diff --git a/erts/etc/win32/nsis/find_redist.sh b/erts/etc/win32/nsis/find_redist.sh
index bc4260ecba..7c449c9e4e 100755
--- a/erts/etc/win32/nsis/find_redist.sh
+++ b/erts/etc/win32/nsis/find_redist.sh
@@ -65,7 +65,6 @@ remove_path_element()
else
echo "${ACC}/$1"
fi
-
#echo "ACC=$ACC" >&2
#echo "1=$1" >&2
}
@@ -89,20 +88,39 @@ add_path_element()
echo "$PA"
}
+
CLPATH=`lookup_prog_in_path cl`
if [ -z "$CLPATH" ]; then
- echo "Can not locate cl.exe and vcredist_x86.exe - OK if using mingw" >&2
+ echo "Can not locate cl.exe and vcredist_x86/x64.exe - OK if using mingw" >&2
exit 1
fi
-#echo $CLPATH
+# Look to see if it's 64bit
+XX=`remove_path_element cl "$CLPATH"`
+YY=`remove_path_element amd64 "$XX"`
+if [ "$YY" != "$XX" ]; then
+ AMD64DIR=true
+ VCREDIST=vcredist_x64
+ COMPONENTS="cl amd64 bin vc"
+else
+ AMD64DIR=false
+ VCREDIST=vcredist_x86
+ COMPONENTS="cl bin vc"
+fi
+
+if [ X"$1" = X"-n" ]; then
+ echo $VCREDIST.exe
+ exit 0
+fi
+
+# echo $CLPATH
BPATH=$CLPATH
-for x in cl bin vc; do
- #echo $x
+for x in $COMPONENTS; do
+ # echo $x
NBPATH=`remove_path_element $x "$BPATH"`
if [ "$NBPATH" = "$BPATH" ]; then
- echo "Failed to locate vcredist_x86.exe because cl.exe was in an unexpected location" >&2
+ echo "Failed to locate $VCREDIST.exe because cl.exe was in an unexpected location" >&2
exit 2
fi
BPATH="$NBPATH"
@@ -115,7 +133,12 @@ fail=false
if [ '!' -z "$RCPATH" ]; then
BPATH=$RCPATH
allow_fail=false
- for x in rc bin @ANY v6.0A v7.0A v7.1; do
+ if [ $AMD64DIR = true ]; then
+ COMPONENTS="rc x64 bin @ANY v6.0A v7.0A v7.1"
+ else
+ COMPONENTS="rc bin @ANY v6.0A v7.0A v7.1"
+ fi
+ for x in $COMPONENTS; do
if [ $x = @ANY ]; then
allow_fail=true
else
@@ -131,6 +154,7 @@ if [ '!' -z "$RCPATH" ]; then
BPATH_LIST="$BPATH_LIST $BPATH"
fi
fi
+# echo "BPATH_LIST=$BPATH_LIST"
# Frantic search through two roots with different
# version directories. We want to be very specific about the
@@ -143,7 +167,7 @@ for BP in $BPATH_LIST; do
BPATH=$BP
fail=false
allow_fail=false
- for x in $verdir @ANY bootstrapper packages vcredist_x86 Redist VC @ALL vcredist_x86.exe; do
+ for x in $verdir @ANY bootstrapper packages $VCREDIST Redist VC @ALL $VCREDIST.exe; do
#echo "x=$x"
#echo "BPATH=$BPATH"
#echo "allow_fail=$allow_fail"
@@ -170,18 +194,18 @@ for BP in $BPATH_LIST; do
fi
done
-# shortcut for locating vcredist_x86.exe is to put it into $ERL_TOP
-if [ -f $ERL_TOP/vcredist_x86.exe ]; then
- echo $ERL_TOP/vcredist_x86.exe
+# shortcut for locating $VCREDIST.exe is to put it into $ERL_TOP
+if [ -f $ERL_TOP/$VCREDIST.exe ]; then
+ echo $ERL_TOP/$VCREDIST.exe
exit 0
fi
# or $ERL_TOP/.. to share across multiple builds
-if [ -f $ERL_TOP/../vcredist_x86.exe ]; then
- echo $ERL_TOP/../vcredist_x86.exe
+if [ -f $ERL_TOP/../$VCREDIST.exe ]; then
+ echo $ERL_TOP/../$VCREDIST.exe
exit 0
fi
-echo "Failed to locate vcredist_x86.exe because directory structure was unexpected" >&2
+echo "Failed to locate $VCREDIST.exe because directory structure was unexpected" >&2
exit 3
diff --git a/erts/etc/win32/port_entry.c b/erts/etc/win32/port_entry.c
index 49b5ad2f34..9c3e750cbc 100644
--- a/erts/etc/win32/port_entry.c
+++ b/erts/etc/win32/port_entry.c
@@ -45,6 +45,8 @@ extern void mainCRTStartup(void);
BOOL WINAPI erl_port_default_handler(DWORD ctrl){
if(ctrl == CTRL_LOGOFF_EVENT)
return TRUE;
+ if(ctrl == CTRL_SHUTDOWN_EVENT)
+ return TRUE;
return FALSE;
}
diff --git a/erts/etc/win32/start_erl.c b/erts/etc/win32/start_erl.c
index 28c8e55bd3..41b221d5bc 100644
--- a/erts/etc/win32/start_erl.c
+++ b/erts/etc/win32/start_erl.c
@@ -585,6 +585,9 @@ BOOL WINAPI LogoffHandlerRoutine( DWORD dwCtrlType )
if(dwCtrlType == CTRL_LOGOFF_EVENT) {
return TRUE;
}
+ if(dwCtrlType == CTRL_SHUTDOWN_EVENT) {
+ return TRUE;
+ }
return FALSE;
}
diff --git a/erts/etc/win32/win_erlexec.c b/erts/etc/win32/win_erlexec.c
index 0eed8e28b9..11cc6a30f7 100644
--- a/erts/etc/win32/win_erlexec.c
+++ b/erts/etc/win32/win_erlexec.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
@@ -30,6 +30,9 @@
#include <winuser.h>
#include <wincon.h>
#include <process.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include "sys.h"
#include "erl_driver.h"
diff --git a/erts/include/erl_int_sizes_config.h.in b/erts/include/erl_int_sizes_config.h.in
index 4b8a8e1b98..14d7c6a702 100644
--- a/erts/include/erl_int_sizes_config.h.in
+++ b/erts/include/erl_int_sizes_config.h.in
@@ -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,5 +32,8 @@
/* The number of bytes in a long long. */
#undef SIZEOF_LONG_LONG
+/* The size of a pointer. */
+#undef SIZEOF_VOID_P
+
/* Define if building a halfword-heap 64bit emulator (needed for NIF's) */
#undef HALFWORD_HEAP_EMULATOR
diff --git a/erts/include/internal/ethr_atomics.h b/erts/include/internal/ethr_atomics.h
index 0f3c26f1df..612894b8c1 100644
--- a/erts/include/internal/ethr_atomics.h
+++ b/erts/include/internal/ethr_atomics.h
@@ -10,7 +10,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2012. All Rights Reserved.
*
* The 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,12 +64,31 @@
* Appart from a function implementing the atomic operation
* with unspecified memory barrier semantics, there are
* functions implementing each operation with the following
- * memory barrier semantics:
- * - rb (read barrier)
- * - wb (write barrier)
- * - acqb (acquire barrier)
- * - relb (release barrier)
- * - mb (full memory barrier)
+ * implied memory barrier semantics:
+ * - mb - Full memory barrier. Orders both loads, and
+ * stores before, and after the atomic operation.
+ * No load or store is allowed to be reordered
+ * over the atomic operation.
+ * - relb - Release barrier. Orders both loads, and
+ * stores appearing *before* the atomic
+ * operation. These are not allowed to be
+ * reordered over the atomic operation.
+ * - acqb - Acquire barrier. Orders both loads, and stores
+ * appearing *after* the atomic operation. These
+ * are not allowed to be reordered over the
+ * atomic operation.
+ * - wb - Write barrier. Orders *only* stores. These are
+ * not allowed to be reordered over the barrier.
+ * Store in atomic operation is ordered *after*
+ * the barrier.
+ * - rb - Read barrier. Orders *only* loads. These are
+ * not allowed to be reordered over the barrier.
+ * Load in atomic operation is ordered *before*
+ * the barrier.
+ * - ddrb - Data dependency read barrier. Orders *only*
+ * loads according to data dependency across the
+ * barrier. Load in atomic operation is ordered
+ * before the barrier.
*
* We implement all of these operation/barrier
* combinations, regardless of whether they are useful
@@ -535,24 +554,28 @@ char **ethr_native_su_dw_atomic_ops(void);
#ifdef ETHR_NEED_DW_ATMC_PROTOTYPES__
ethr_sint_t *ethr_dw_atomic_addr(ethr_dw_atomic_t *var);
int ethr_dw_atomic_cmpxchg(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ethr_dw_atomic_cmpxchg_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ethr_dw_atomic_cmpxchg_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ethr_dw_atomic_cmpxchg_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ethr_dw_atomic_cmpxchg_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ethr_dw_atomic_cmpxchg_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ethr_dw_atomic_cmpxchg_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
void ethr_dw_atomic_set(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_set_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_set_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_set_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_set_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_set_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_set_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_read(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_read_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_read_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_read_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_read_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_read_relb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_read_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_init(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ethr_dw_atomic_init_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_init_rb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_init_wb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ethr_dw_atomic_init_acqb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
@@ -561,24 +584,28 @@ void ethr_dw_atomic_init_mb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
#if defined(ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__)
ethr_sint_t *ETHR_DW_ATOMIC_FUNC__(addr)(ethr_dw_atomic_t *var);
int ETHR_DW_ATOMIC_FUNC__(cmpxchg)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
+int ETHR_DW_ATOMIC_FUNC__(cmpxchg_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ETHR_DW_ATOMIC_FUNC__(cmpxchg_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ETHR_DW_ATOMIC_FUNC__(cmpxchg_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ETHR_DW_ATOMIC_FUNC__(cmpxchg_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ETHR_DW_ATOMIC_FUNC__(cmpxchg_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
int ETHR_DW_ATOMIC_FUNC__(cmpxchg_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val);
void ETHR_DW_ATOMIC_FUNC__(set)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(set_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(set_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(set_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(set_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(set_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(set_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(read)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(read_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(read_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(read_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(read_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(read_relb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(read_mb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(init)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
+void ETHR_DW_ATOMIC_FUNC__(init_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(init_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(init_wb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
void ETHR_DW_ATOMIC_FUNC__(init_acqb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val);
@@ -1491,6 +1518,15 @@ static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_mb)(ethr_dw_atomic_t *var, et
return res;
}
+static ETHR_INLINE int ETHR_DW_ATMC_FUNC__(cmpxchg_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_DW_ATMC_FUNC__(cmpxchg)(var, val, old_val);
+#else
+ return ETHR_DW_ATMC_FUNC__(cmpxchg_rb)(var, val, old_val);
+#endif
+}
+
/* --- set() --- */
@@ -1981,6 +2017,15 @@ static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_mb)(ethr_dw_atomic_t *var, ethr_
}
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(set_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_DW_ATMC_FUNC__(set)(var, val);
+#else
+ ETHR_DW_ATMC_FUNC__(set_rb)(var, val);
+#endif
+}
+
/* --- read() --- */
@@ -2309,6 +2354,15 @@ static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_mb)(ethr_dw_atomic_t *var, ethr
}
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(read_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_DW_ATMC_FUNC__(read)(var, val);
+#else
+ ETHR_DW_ATMC_FUNC__(read_rb)(var, val);
+#endif
+}
+
/* --- init() --- */
@@ -2607,6 +2661,15 @@ static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_mb)(ethr_dw_atomic_t *var, ethr
}
+static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_DW_ATMC_FUNC__(init)(var, val);
+#else
+ ETHR_DW_ATMC_FUNC__(init_rb)(var, val);
+#endif
+}
+
#endif /* ETHR_DW_ATMC_INLINE__ */
@@ -2616,78 +2679,91 @@ static ETHR_INLINE void ETHR_DW_ATMC_FUNC__(init_mb)(ethr_dw_atomic_t *var, ethr
#ifdef ETHR_NEED_ATMC_PROTOTYPES__
ethr_sint_t *ethr_atomic_addr(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_cmpxchg(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
+ethr_sint_t ethr_atomic_cmpxchg_ddrb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
ethr_sint_t ethr_atomic_cmpxchg_rb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
ethr_sint_t ethr_atomic_cmpxchg_wb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
ethr_sint_t ethr_atomic_cmpxchg_acqb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
ethr_sint_t ethr_atomic_cmpxchg_relb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
ethr_sint_t ethr_atomic_cmpxchg_mb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val);
ethr_sint_t ethr_atomic_xchg(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_xchg_ddrb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_xchg_rb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_xchg_wb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_xchg_acqb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_xchg_relb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_xchg_mb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_set(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_set_ddrb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_set_rb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_set_wb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_set_acqb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_set_relb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_set_mb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_init(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_init_ddrb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_init_rb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_init_wb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_init_acqb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_init_relb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_init_mb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_add_read(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_add_read_ddrb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_add_read_rb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_add_read_wb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_add_read_acqb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_add_read_relb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_add_read_mb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_read_ddrb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_read_rb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_read_wb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_read_acqb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_read_relb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_read_mb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_inc_read(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_inc_read_ddrb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_inc_read_rb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_inc_read_wb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_inc_read_acqb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_inc_read_relb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_inc_read_mb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_dec_read(ethr_atomic_t *var);
+ethr_sint_t ethr_atomic_dec_read_ddrb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_dec_read_rb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_dec_read_wb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_dec_read_acqb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_dec_read_relb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_dec_read_mb(ethr_atomic_t *var);
void ethr_atomic_add(ethr_atomic_t *var, ethr_sint_t val);
+void ethr_atomic_add_ddrb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_add_rb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_add_wb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_add_acqb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_add_relb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_add_mb(ethr_atomic_t *var, ethr_sint_t val);
void ethr_atomic_inc(ethr_atomic_t *var);
+void ethr_atomic_inc_ddrb(ethr_atomic_t *var);
void ethr_atomic_inc_rb(ethr_atomic_t *var);
void ethr_atomic_inc_wb(ethr_atomic_t *var);
void ethr_atomic_inc_acqb(ethr_atomic_t *var);
void ethr_atomic_inc_relb(ethr_atomic_t *var);
void ethr_atomic_inc_mb(ethr_atomic_t *var);
void ethr_atomic_dec(ethr_atomic_t *var);
+void ethr_atomic_dec_ddrb(ethr_atomic_t *var);
void ethr_atomic_dec_rb(ethr_atomic_t *var);
void ethr_atomic_dec_wb(ethr_atomic_t *var);
void ethr_atomic_dec_acqb(ethr_atomic_t *var);
void ethr_atomic_dec_relb(ethr_atomic_t *var);
void ethr_atomic_dec_mb(ethr_atomic_t *var);
ethr_sint_t ethr_atomic_read_band(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_band_ddrb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_band_rb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_band_wb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_band_acqb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_band_relb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_band_mb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_bor(ethr_atomic_t *var, ethr_sint_t val);
+ethr_sint_t ethr_atomic_read_bor_ddrb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_bor_rb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_bor_wb(ethr_atomic_t *var, ethr_sint_t val);
ethr_sint_t ethr_atomic_read_bor_acqb(ethr_atomic_t *var, ethr_sint_t val);
@@ -3551,6 +3627,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_mb)(ethr_atomic_t *var,
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(cmpxchg_ddrb)(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(cmpxchg)(var, val, old_val);
+#else
+ return ETHR_ATMC_FUNC__(cmpxchg_rb)(var, val, old_val);
+#endif
+}
+
/* --- xchg() --- */
@@ -3801,6 +3886,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_mb)(ethr_atomic_t *var, eth
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(xchg_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(xchg)(var, val);
+#else
+ return ETHR_ATMC_FUNC__(xchg_rb)(var, val);
+#endif
+}
+
/* --- set() --- */
@@ -3943,6 +4037,15 @@ static ETHR_INLINE void ETHR_ATMC_FUNC__(set_mb)(ethr_atomic_t *var, ethr_sint_t
#endif
}
+static ETHR_INLINE void ETHR_ATMC_FUNC__(set_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC_FUNC__(set)(var, val);
+#else
+ ETHR_ATMC_FUNC__(set_rb)(var, val);
+#endif
+}
+
/* --- init() --- */
@@ -4085,6 +4188,15 @@ static ETHR_INLINE void ETHR_ATMC_FUNC__(init_mb)(ethr_atomic_t *var, ethr_sint_
#endif
}
+static ETHR_INLINE void ETHR_ATMC_FUNC__(init_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC_FUNC__(init)(var, val);
+#else
+ ETHR_ATMC_FUNC__(init_rb)(var, val);
+#endif
+}
+
/* --- add_read() --- */
@@ -4335,6 +4447,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_mb)(ethr_atomic_t *var,
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(add_read_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(add_read)(var, val);
+#else
+ return ETHR_ATMC_FUNC__(add_read_rb)(var, val);
+#endif
+}
+
/* --- read() --- */
@@ -4489,6 +4610,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_mb)(ethr_atomic_t *var)
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_ddrb)(ethr_atomic_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(read)(var);
+#else
+ return ETHR_ATMC_FUNC__(read_rb)(var);
+#endif
+}
+
/* --- inc_read() --- */
@@ -4643,6 +4773,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_mb)(ethr_atomic_t *var)
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(inc_read_ddrb)(ethr_atomic_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(inc_read)(var);
+#else
+ return ETHR_ATMC_FUNC__(inc_read_rb)(var);
+#endif
+}
+
/* --- dec_read() --- */
@@ -4797,6 +4936,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_mb)(ethr_atomic_t *var)
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(dec_read_ddrb)(ethr_atomic_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(dec_read)(var);
+#else
+ return ETHR_ATMC_FUNC__(dec_read_rb)(var);
+#endif
+}
+
/* --- add() --- */
@@ -4939,6 +5087,15 @@ static ETHR_INLINE void ETHR_ATMC_FUNC__(add_mb)(ethr_atomic_t *var, ethr_sint_t
#endif
}
+static ETHR_INLINE void ETHR_ATMC_FUNC__(add_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC_FUNC__(add)(var, val);
+#else
+ ETHR_ATMC_FUNC__(add_rb)(var, val);
+#endif
+}
+
/* --- inc() --- */
@@ -5081,6 +5238,15 @@ static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_mb)(ethr_atomic_t *var)
#endif
}
+static ETHR_INLINE void ETHR_ATMC_FUNC__(inc_ddrb)(ethr_atomic_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC_FUNC__(inc)(var);
+#else
+ ETHR_ATMC_FUNC__(inc_rb)(var);
+#endif
+}
+
/* --- dec() --- */
@@ -5223,6 +5389,15 @@ static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_mb)(ethr_atomic_t *var)
#endif
}
+static ETHR_INLINE void ETHR_ATMC_FUNC__(dec_ddrb)(ethr_atomic_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC_FUNC__(dec)(var);
+#else
+ ETHR_ATMC_FUNC__(dec_rb)(var);
+#endif
+}
+
/* --- read_band() --- */
@@ -5473,6 +5648,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_mb)(ethr_atomic_t *var
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_band_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(read_band)(var, val);
+#else
+ return ETHR_ATMC_FUNC__(read_band_rb)(var, val);
+#endif
+}
+
/* --- read_bor() --- */
@@ -5723,6 +5907,15 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_mb)(ethr_atomic_t *var,
return res;
}
+static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_ddrb)(ethr_atomic_t *var, ethr_sint_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC_FUNC__(read_bor)(var, val);
+#else
+ return ETHR_ATMC_FUNC__(read_bor_rb)(var, val);
+#endif
+}
+
#endif /* ETHR_ATMC_INLINE__ */
@@ -5732,78 +5925,91 @@ static ETHR_INLINE ethr_sint_t ETHR_ATMC_FUNC__(read_bor_mb)(ethr_atomic_t *var,
#ifdef ETHR_NEED_ATMC32_PROTOTYPES__
ethr_sint32_t *ethr_atomic32_addr(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_cmpxchg(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
+ethr_sint32_t ethr_atomic32_cmpxchg_ddrb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
ethr_sint32_t ethr_atomic32_cmpxchg_rb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
ethr_sint32_t ethr_atomic32_cmpxchg_wb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
ethr_sint32_t ethr_atomic32_cmpxchg_acqb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
ethr_sint32_t ethr_atomic32_cmpxchg_relb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
ethr_sint32_t ethr_atomic32_cmpxchg_mb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val);
ethr_sint32_t ethr_atomic32_xchg(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_xchg_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_xchg_rb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_xchg_wb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_xchg_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_xchg_relb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_xchg_mb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_set(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_set_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_set_rb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_set_wb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_set_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_set_relb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_set_mb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_init(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_init_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_init_rb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_init_wb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_init_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_init_relb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_init_mb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_add_read(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_add_read_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_add_read_rb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_add_read_wb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_add_read_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_add_read_relb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_add_read_mb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_read_ddrb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_read_rb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_read_wb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_read_acqb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_read_relb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_read_mb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_inc_read(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_inc_read_ddrb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_inc_read_rb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_inc_read_wb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_inc_read_acqb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_inc_read_relb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_inc_read_mb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_dec_read(ethr_atomic32_t *var);
+ethr_sint32_t ethr_atomic32_dec_read_ddrb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_dec_read_rb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_dec_read_wb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_dec_read_acqb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_dec_read_relb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_dec_read_mb(ethr_atomic32_t *var);
void ethr_atomic32_add(ethr_atomic32_t *var, ethr_sint32_t val);
+void ethr_atomic32_add_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_add_rb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_add_wb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_add_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_add_relb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_add_mb(ethr_atomic32_t *var, ethr_sint32_t val);
void ethr_atomic32_inc(ethr_atomic32_t *var);
+void ethr_atomic32_inc_ddrb(ethr_atomic32_t *var);
void ethr_atomic32_inc_rb(ethr_atomic32_t *var);
void ethr_atomic32_inc_wb(ethr_atomic32_t *var);
void ethr_atomic32_inc_acqb(ethr_atomic32_t *var);
void ethr_atomic32_inc_relb(ethr_atomic32_t *var);
void ethr_atomic32_inc_mb(ethr_atomic32_t *var);
void ethr_atomic32_dec(ethr_atomic32_t *var);
+void ethr_atomic32_dec_ddrb(ethr_atomic32_t *var);
void ethr_atomic32_dec_rb(ethr_atomic32_t *var);
void ethr_atomic32_dec_wb(ethr_atomic32_t *var);
void ethr_atomic32_dec_acqb(ethr_atomic32_t *var);
void ethr_atomic32_dec_relb(ethr_atomic32_t *var);
void ethr_atomic32_dec_mb(ethr_atomic32_t *var);
ethr_sint32_t ethr_atomic32_read_band(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_band_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_band_rb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_band_wb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_band_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_band_relb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_band_mb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_bor(ethr_atomic32_t *var, ethr_sint32_t val);
+ethr_sint32_t ethr_atomic32_read_bor_ddrb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_bor_rb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_bor_wb(ethr_atomic32_t *var, ethr_sint32_t val);
ethr_sint32_t ethr_atomic32_read_bor_acqb(ethr_atomic32_t *var, ethr_sint32_t val);
@@ -6667,6 +6873,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_mb)(ethr_atomic32_t
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(cmpxchg_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(cmpxchg)(var, val, old_val);
+#else
+ return ETHR_ATMC32_FUNC__(cmpxchg_rb)(var, val, old_val);
+#endif
+}
+
/* --- xchg() --- */
@@ -6917,6 +7132,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_mb)(ethr_atomic32_t *va
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(xchg_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(xchg)(var, val);
+#else
+ return ETHR_ATMC32_FUNC__(xchg_rb)(var, val);
+#endif
+}
+
/* --- set() --- */
@@ -7059,6 +7283,15 @@ static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_mb)(ethr_atomic32_t *var, ethr_si
#endif
}
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(set_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC32_FUNC__(set)(var, val);
+#else
+ ETHR_ATMC32_FUNC__(set_rb)(var, val);
+#endif
+}
+
/* --- init() --- */
@@ -7201,6 +7434,15 @@ static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_mb)(ethr_atomic32_t *var, ethr_s
#endif
}
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(init_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC32_FUNC__(init)(var, val);
+#else
+ ETHR_ATMC32_FUNC__(init_rb)(var, val);
+#endif
+}
+
/* --- add_read() --- */
@@ -7451,6 +7693,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_mb)(ethr_atomic32_t
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(add_read_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(add_read)(var, val);
+#else
+ return ETHR_ATMC32_FUNC__(add_read_rb)(var, val);
+#endif
+}
+
/* --- read() --- */
@@ -7605,6 +7856,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_mb)(ethr_atomic32_t *va
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_ddrb)(ethr_atomic32_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(read)(var);
+#else
+ return ETHR_ATMC32_FUNC__(read_rb)(var);
+#endif
+}
+
/* --- inc_read() --- */
@@ -7759,6 +8019,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_mb)(ethr_atomic32_t
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(inc_read_ddrb)(ethr_atomic32_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(inc_read)(var);
+#else
+ return ETHR_ATMC32_FUNC__(inc_read_rb)(var);
+#endif
+}
+
/* --- dec_read() --- */
@@ -7913,6 +8182,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_mb)(ethr_atomic32_t
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(dec_read_ddrb)(ethr_atomic32_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(dec_read)(var);
+#else
+ return ETHR_ATMC32_FUNC__(dec_read_rb)(var);
+#endif
+}
+
/* --- add() --- */
@@ -8055,6 +8333,15 @@ static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_mb)(ethr_atomic32_t *var, ethr_si
#endif
}
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(add_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC32_FUNC__(add)(var, val);
+#else
+ ETHR_ATMC32_FUNC__(add_rb)(var, val);
+#endif
+}
+
/* --- inc() --- */
@@ -8197,6 +8484,15 @@ static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_mb)(ethr_atomic32_t *var)
#endif
}
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(inc_ddrb)(ethr_atomic32_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC32_FUNC__(inc)(var);
+#else
+ ETHR_ATMC32_FUNC__(inc_rb)(var);
+#endif
+}
+
/* --- dec() --- */
@@ -8339,6 +8635,15 @@ static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_mb)(ethr_atomic32_t *var)
#endif
}
+static ETHR_INLINE void ETHR_ATMC32_FUNC__(dec_ddrb)(ethr_atomic32_t *var)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ETHR_ATMC32_FUNC__(dec)(var);
+#else
+ ETHR_ATMC32_FUNC__(dec_rb)(var);
+#endif
+}
+
/* --- read_band() --- */
@@ -8589,6 +8894,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_mb)(ethr_atomic32_
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_band_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(read_band)(var, val);
+#else
+ return ETHR_ATMC32_FUNC__(read_band_rb)(var, val);
+#endif
+}
+
/* --- read_bor() --- */
@@ -8839,6 +9153,15 @@ static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_mb)(ethr_atomic32_t
return res;
}
+static ETHR_INLINE ethr_sint32_t ETHR_ATMC32_FUNC__(read_bor_ddrb)(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#ifdef ETHR_ORDERED_READ_DEPEND
+ return ETHR_ATMC32_FUNC__(read_bor)(var, val);
+#else
+ return ETHR_ATMC32_FUNC__(read_bor_rb)(var, val);
+#endif
+}
+
#endif /* ETHR_ATMC32_INLINE__ */
#endif /* ETHR_ATOMICS_H__ */
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index a0685ea3c0..86a1e9fbdf 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -22,6 +22,23 @@
* Author: Rickard Green
*/
+/*
+ * IMPORTANT note about ethr_cond_signal() and ethr_cond_broadcast()
+ *
+ * POSIX allow a call to `pthread_cond_signal' or `pthread_cond_broadcast'
+ * even though the associated mutex/mutexes isn't/aren't locked by the
+ * caller. We do not allow that by default in order to avoid a performance
+ * penalty on some platforms.
+ *
+ * Mutexes and condition variables can, however, be initialized as POSIX
+ * compliant. When initialized as such ethr_cond_signal(), and
+ * ethr_cond_broadcast() are allowed to be called even though the associated
+ * mutexes aren't locked. This will, however, incur a performance penalty on
+ * some platforms.
+ *
+ * POSIX compliant mutexes and condition variables *need* to be used together.
+ */
+
#ifndef ETHR_MUTEX_H__
#define ETHR_MUTEX_H__
@@ -40,6 +57,14 @@
#endif
#endif
+/* #define ETHR_DBG_WIN_MTX_WITH_PTHREADS */
+#ifdef ETHR_DBG_WIN_MTX_WITH_PTHREADS
+typedef pthread_mutex_t CRITICAL_SECTION;
+int TryEnterCriticalSection(CRITICAL_SECTION *);
+void EnterCriticalSection(CRITICAL_SECTION *);
+void LeaveCriticalSection(CRITICAL_SECTION *);
+#endif
+
#ifdef ETHR_MTX_HARD_DEBUG
# ifdef __GNUC__
# warning ETHR_MTX_HARD_DEBUG
@@ -140,13 +165,19 @@ struct ethr_mutex_base_ {
typedef struct {
int main_spincount;
int aux_spincount;
+ int posix_compliant;
} ethr_mutex_opt;
+#define ETHR_MUTEX_OPT_DEFAULT_INITER {-1, -1, 0}
+
typedef struct {
int main_spincount;
int aux_spincount;
+ int posix_compliant;
} ethr_cond_opt;
+#define ETHR_COND_OPT_DEFAULT_INITER {-1, -1, 0}
+
#ifdef ETHR_USE_OWN_MTX_IMPL__
typedef struct ethr_mutex_ ethr_mutex;
@@ -179,7 +210,7 @@ struct ethr_cond_ {
#endif
};
-#else /* pthread */
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
typedef struct ethr_mutex_ ethr_mutex;
struct ethr_mutex_ {
@@ -197,7 +228,36 @@ struct ethr_cond_ {
#endif
};
-#endif /* pthread */
+#elif defined(ETHR_WIN32_THREADS) || defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+# define ETHR_WIN_MUTEX__
+
+typedef struct ethr_mutex_ ethr_mutex;
+struct ethr_mutex_ {
+ int posix_compliant;
+ CRITICAL_SECTION cs;
+ ethr_ts_event *wakeups;
+ ethr_atomic32_t have_wakeups; /* only when posix compliant */
+ ethr_atomic32_t locked; /* only when posix compliant */
+ ethr_spinlock_t lock; /* only when posix compliant */
+#if ETHR_XCHK
+ int initialized;
+#endif
+};
+
+typedef struct ethr_cond_ ethr_cond;
+struct ethr_cond_ {
+ int posix_compliant;
+ CRITICAL_SECTION cs;
+ ethr_ts_event *waiters;
+ int spincount;
+#if ETHR_XCHK
+ int initialized;
+#endif
+};
+
+#else
+# error "no mutex implementation"
+#endif
int ethr_mutex_init_opt(ethr_mutex *, ethr_mutex_opt *);
int ethr_mutex_init(ethr_mutex *);
@@ -573,7 +633,7 @@ ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#else /* pthread_mutex */
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
@@ -605,7 +665,54 @@ ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#endif /* pthread_mutex */
+#elif defined(ETHR_WIN32_THREADS) || defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
+
+static ETHR_INLINE int
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
+{
+ if (!TryEnterCriticalSection(&mtx->cs))
+ return EBUSY;
+ if (mtx->posix_compliant)
+ ethr_atomic32_set(&mtx->locked, 1);
+ return 0;
+}
+
+static ETHR_INLINE void
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
+{
+ EnterCriticalSection(&mtx->cs);
+ if (mtx->posix_compliant)
+ ethr_atomic32_set(&mtx->locked, 1);
+}
+
+void ethr_mutex_cond_wakeup__(ethr_mutex *mtx);
+
+static ETHR_INLINE void
+ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
+{
+ if (mtx->posix_compliant) {
+ ethr_atomic32_set_mb(&mtx->locked, 0);
+ if (ethr_atomic32_read_acqb(&mtx->have_wakeups))
+ goto cond_wakeup;
+ else
+ goto leave_cs;
+ }
+
+ if (mtx->wakeups) {
+ cond_wakeup:
+ ethr_mutex_cond_wakeup__(mtx);
+ }
+ else {
+ leave_cs:
+ LeaveCriticalSection(&mtx->cs);
+ }
+}
+
+#endif /* ETHR_TRY_INLINE_FUNCS */
+
+#endif
#ifdef ETHR_USE_OWN_RWMTX_IMPL__
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 8ad0ded144..142c26c0ca 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -191,7 +191,6 @@ typedef DWORD ethr_tsd_key;
#undef ETHR_HAVE_ETHR_SIG_FUNCS
#define ETHR_USE_OWN_RWMTX_IMPL__
-#define ETHR_USE_OWN_MTX_IMPL__
#define ETHR_YIELD() (Sleep(0), 0)
diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in
index 12b8732735..aed889eaef 100644
--- a/erts/lib_src/Makefile.in
+++ b/erts/lib_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -138,7 +138,7 @@ INCLUDES=-I$(ERTS_INCL) -I$(ERTS_INCL)/$(TARGET) -I$(ERTS_INCL_INT) -I$(ERTS_INC
INCLUDES += -I../emulator/beam -I../emulator/sys/$(ERLANG_OSTYPE)
USING_MINGW=@MIXED_CYGWIN_MINGW@
-USING_VC=@MIXED_CYGWIN_VC@
+USING_VC=@MIXED_VC@
ifeq ($(USING_VC),yes)
LIB_SUFFIX=.lib
@@ -318,10 +318,14 @@ ETHREAD_LIB=
endif
+_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
#
# Everything to build
#
-all: $(CREATE_DIRS) $(ETHREAD_LIB) $(ERTS_LIBS) $(ERTS_INTERNAL_LIBS)
+.PHONY: all
+all: $(OBJ_DIR)/MADE
+
+$(OBJ_DIR)/MADE: $(ETHREAD_LIB) $(ERTS_LIBS) $(ERTS_INTERNAL_LIBS)
ifeq ($(OMIT_OMIT_FP),yes)
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@@ -331,6 +335,8 @@ ifeq ($(OMIT_OMIT_FP),yes)
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
endif
+ echo $? > $(OBJ_DIR)/MADE
+
#
# The libs ...
#
@@ -428,13 +434,6 @@ $(MTd_OBJ_DIR)/%.o: $(ETHR_THR_LIB_BASE_DIR)/%.c
$(CC) $(THR_DEFS) $(CFLAGS) -MTd $(INCLUDES) -c $< -o $@
#
-# Create directories
-#
-
-$(CREATE_DIRS):
- $(MKDIR) -p $@
-
-#
# Install
#
@@ -471,48 +470,50 @@ INTERNAL_RELEASE_LIBS= \
$(ETHREAD_LIB) \
$(ERTS_INTERNAL_LIBS)
+.PHONY: release_spec
release_spec: all
ifneq ($(strip $(RELEASE_INCLUDES)),)
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELEASE_PATH)/usr/include
- $(INSTALL_DATA) $(RELEASE_INCLUDES) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(RELEASE_INCLUDES) $(RELEASE_PATH)/usr/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/usr/include"
+ $(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELEASE_PATH)/usr/include"
endif
ifneq ($(strip $(INTERNAL_RELEASE_INCLUDES)),)
- $(INSTALL_DIR) $(RELSYSDIR)/include/internal
- $(INSTALL_DATA) $(INTERNAL_RELEASE_INCLUDES) $(RELSYSDIR)/include/internal
+ $(INSTALL_DIR) "$(RELSYSDIR)/include/internal"
+ $(INSTALL_DATA) $(INTERNAL_RELEASE_INCLUDES) "$(RELSYSDIR)/include/internal"
endif
ifneq ($(strip $(INTERNAL_X_RELEASE_INCLUDE_DIRS)),)
for xdir in $(INTERNAL_X_RELEASE_INCLUDE_DIRS); do \
- $(INSTALL_DIR) $(RELSYSDIR)/include/internal/$$xdir; \
+ $(INSTALL_DIR) "$(RELSYSDIR)/include/internal/$$xdir"; \
$(INSTALL_DATA) $(ERTS_INCL_INT)/$$xdir/*.h \
- $(RELSYSDIR)/include/internal/$$xdir; \
+ "$(RELSYSDIR)/include/internal/$$xdir"; \
done
endif
ifneq ($(strip $(RELEASE_LIBS)),)
- $(INSTALL_DIR) $(RELSYSDIR)/lib
- $(INSTALL_DIR) $(RELEASE_PATH)/usr/lib
- $(INSTALL_DATA) $(RELEASE_LIBS) $(RELSYSDIR)/lib
- $(INSTALL_DATA) $(RELEASE_LIBS) $(RELEASE_PATH)/usr/lib
+ $(INSTALL_DIR) "$(RELSYSDIR)/lib"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/usr/lib"
+ $(INSTALL_DATA) $(RELEASE_LIBS) "$(RELSYSDIR)/lib"
+ $(INSTALL_DATA) $(RELEASE_LIBS) "$(RELEASE_PATH)/usr/lib"
endif
ifneq ($(strip $(INTERNAL_RELEASE_LIBS)),)
- $(INSTALL_DIR) $(RELSYSDIR)/lib/internal
- $(INSTALL_DATA) $(INTERNAL_RELEASE_LIBS) $(RELSYSDIR)/lib/internal
+ $(INSTALL_DIR) "$(RELSYSDIR)/lib/internal"
+ $(INSTALL_DATA) $(INTERNAL_RELEASE_LIBS) "$(RELSYSDIR)/lib/internal"
endif
+.PHONY: docs
docs:
+.PHONY: release_docs_spec
release_docs_spec:
-
#
# Cleanup
#
+.PHONY: clean
clean:
$(RM) -rf ../lib/internal/$(TARGET)/*
$(RM) -rf ../lib/$(TARGET)/*
$(RM) -rf obj/$(TARGET)/*
- $(RM) -f $(TARGET)/depend.mk
#
# Make dependencies
@@ -554,9 +555,11 @@ SED_MDd_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_MDd_O);$(SED_REPL_TT_DIR);$(SED_REPL
SED_MT_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_MT_O);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET)'
SED_MTd_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_MTd_O);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET)'
-DEPEND_MK=$(TARGET)/depend.mk
+DEPEND_MK=$(OBJ_DIR)/depend.mk
-depend:
+.PHONY: depend
+depend: $(DEPEND_MK)
+$(DEPEND_MK):
@echo "Generating dependency file $(DEPEND_MK)..."
@echo "# Generated dependency rules" > $(DEPEND_MK);
@echo "# " >> $(DEPEND_MK);
@@ -629,6 +632,8 @@ endif
endif
@echo "# EOF" >> $(DEPEND_MK);
+ifneq ($(MAKECMDGOALS),clean)
-include $(DEPEND_MK)
+endif
# eof
diff --git a/erts/lib_src/common/erl_memory_trace_parser.c b/erts/lib_src/common/erl_memory_trace_parser.c
index 54c3dfadec..625c140cf9 100644
--- a/erts/lib_src/common/erl_memory_trace_parser.c
+++ b/erts/lib_src/common/erl_memory_trace_parser.c
@@ -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
@@ -368,12 +368,16 @@ emtp_state_destroy(emtp_state *statep)
#define GET_UI8(UI, BP) ((UI) = *((BP)++))
+#define SKIP_UI8(BP) ((BP)++)
+
#define GET_UI16(UI, BP) \
do { \
(UI) = ((( (usgnd_int_16) (BP)[0]) << 8) \
| ((usgnd_int_16) (BP)[1])); \
(BP) += UI16_SZ; \
} while(0)
+#define SKIP_UI16(BP) ((BP) += UI16_SZ)
+
#define GET_UI32(UI, BP) \
do { \
@@ -383,6 +387,7 @@ emtp_state_destroy(emtp_state *statep)
| ( (usgnd_int_32) (BP)[3])); \
(BP) += UI32_SZ; \
} while(0)
+#define SKIP_UI32(BP) ((BP) += UI32_SZ)
#define GET_UI64(UI, BP) \
do { \
@@ -396,6 +401,7 @@ emtp_state_destroy(emtp_state *statep)
| ( (usgnd_int_64) (BP)[7])); \
(BP) += UI64_SZ; \
} while(0)
+#define SKIP_UI64(BP) ((BP) += UI64_SZ)
#define GET_VSZ_UI16(UI, BP, MSB) \
do { \
@@ -1267,11 +1273,10 @@ parse_header(emtp_state *statep,
switch (statep->version.major) {
case 1: {
- usgnd_int_32 hdr_sz;
NEED(2*UI32_SZ + 2*UI16_SZ, trace_size);
GET_UI32(statep->flags, tracep);
- GET_UI32(hdr_sz, tracep); /* ignore this; may contain garbage! */
+ SKIP_UI32(tracep); /* ignore this; may contain garbage! */
GET_UI16(statep->max_allocator_ix, tracep);
GET_UI16(statep->max_block_type_ix, tracep);
@@ -1564,13 +1569,13 @@ parse_header(emtp_state *statep,
}
case ERTS_MT_BLOCK_TYPE_HDR_TAG: {
- usgnd_int_16 bt_ix, a_ix, btflgs;
+ usgnd_int_16 bt_ix, a_ix;
if (entry_sz
< UI8_SZ + 3*UI16_SZ + UI8_SZ + 0 + UI16_SZ)
ERROR(EMTP_PARSE_ERROR);
- GET_UI16(btflgs, c_p);
+ SKIP_UI16(c_p); /* bitflags */
GET_UI16(bt_ix, c_p);
if (bt_ix > statep->max_block_type_ix)
ERROR(EMTP_PARSE_ERROR);
diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c
index 5e94ff19db..3b123063fa 100644
--- a/erts/lib_src/common/erl_misc_utils.c
+++ b/erts/lib_src/common/erl_misc_utils.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -727,7 +727,7 @@ adjust_processor_nodes(erts_cpu_info_t *cpuinfo, int no_nodes)
prev = NULL;
this = &cpuinfo->topology[0];
- last = &cpuinfo->topology[cpuinfo->configured-1];
+ last = &cpuinfo->topology[cpuinfo->topology_size-1];
while (1) {
if (processor == this->processor) {
if (node != this->node)
@@ -834,8 +834,8 @@ read_topology(erts_cpu_info_t *cpuinfo)
ix = -1;
if (realpath(ERTS_SYS_NODE_PATH, npath)) {
- got_nodes = 1;
ndir = opendir(npath);
+ got_nodes = (ndir != NULL);
}
do {
@@ -939,7 +939,7 @@ read_topology(erts_cpu_info_t *cpuinfo)
if (res > 1) {
prev = this++;
- last = &cpuinfo->topology[cpuinfo->configured-1];
+ last = &cpuinfo->topology[cpuinfo->topology_size-1];
while (1) {
this->thread = ((this->node == prev->node
@@ -1094,7 +1094,7 @@ read_topology(erts_cpu_info_t *cpuinfo)
if (res > 1) {
prev = this++;
- last = &cpuinfo->topology[cpuinfo->configured-1];
+ last = &cpuinfo->topology[cpuinfo->topology_size-1];
while (1) {
this->thread = ((this->node == prev->node
diff --git a/erts/lib_src/common/erl_printf.c b/erts/lib_src/common/erl_printf.c
index 108a8bb531..2c177ee5ac 100644
--- a/erts/lib_src/common/erl_printf.c
+++ b/erts/lib_src/common/erl_printf.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2012. All Rights Reserved.
*
* The 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,6 +173,7 @@ typedef struct {
static int
write_sn(void *vwsnap, char* buf, size_t len)
{
+ int rv = 0;
write_sn_arg_t *wsnap = (write_sn_arg_t *) vwsnap;
ASSERT(wsnap);
ASSERT(len > 0);
@@ -180,12 +181,13 @@ write_sn(void *vwsnap, char* buf, size_t len)
size_t sz = len;
if (sz >= wsnap->len)
sz = wsnap->len;
+ rv = (int)sz;
memcpy((void *) wsnap->buf, (void *) buf, sz);
wsnap->buf += sz;
wsnap->len -= sz;
return sz;
}
- return 0;
+ return rv;
}
static int
diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c
index 473791dce4..71d2aa35d0 100644
--- a/erts/lib_src/common/erl_printf_format.c
+++ b/erts/lib_src/common/erl_printf_format.c
@@ -457,6 +457,15 @@ static int fmt_double(fmtfn_t fn,void*arg,double val,
return res;
}
+/* strnlen doesn't exist everywhere */
+static size_t my_strnlen(const char *s, size_t maxlen)
+{
+ size_t i = 0;
+ while (i < maxlen && s[i] != '\0')
+ i++;
+ return i;
+}
+
int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap)
{
char* ptr0 = fmt;
@@ -771,9 +780,7 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap)
case FMTC_s: {
char* str = va_arg(ap,char*);
- int len = strlen(str);
- if (precision >= 0 && precision < len)
- len = precision;
+ int len = (precision >= 0) ? my_strnlen(str,precision) : strlen(str);
if (width > 0 && !(fmt & FMTF_adj)) {
if (width > len)
BLANKS(fn, arg, width - len, count);
diff --git a/erts/lib_src/common/ethr_atomics.c b/erts/lib_src/common/ethr_atomics.c
index 5796bdc22e..c52166a7ec 100644
--- a/erts/lib_src/common/ethr_atomics.c
+++ b/erts/lib_src/common/ethr_atomics.c
@@ -10,7 +10,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2012. All Rights Reserved.
*
* The 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,12 +64,31 @@
* Appart from a function implementing the atomic operation
* with unspecified memory barrier semantics, there are
* functions implementing each operation with the following
- * memory barrier semantics:
- * - rb (read barrier)
- * - wb (write barrier)
- * - acqb (acquire barrier)
- * - relb (release barrier)
- * - mb (full memory barrier)
+ * implied memory barrier semantics:
+ * - mb - Full memory barrier. Orders both loads, and
+ * stores before, and after the atomic operation.
+ * No load or store is allowed to be reordered
+ * over the atomic operation.
+ * - relb - Release barrier. Orders both loads, and
+ * stores appearing *before* the atomic
+ * operation. These are not allowed to be
+ * reordered over the atomic operation.
+ * - acqb - Acquire barrier. Orders both loads, and stores
+ * appearing *after* the atomic operation. These
+ * are not allowed to be reordered over the
+ * atomic operation.
+ * - wb - Write barrier. Orders *only* stores. These are
+ * not allowed to be reordered over the barrier.
+ * Store in atomic operation is ordered *after*
+ * the barrier.
+ * - rb - Read barrier. Orders *only* loads. These are
+ * not allowed to be reordered over the barrier.
+ * Load in atomic operation is ordered *before*
+ * the barrier.
+ * - ddrb - Data dependency read barrier. Orders *only*
+ * loads according to data dependency across the
+ * barrier. Load in atomic operation is ordered
+ * before the barrier.
*
* We implement all of these operation/barrier
* combinations, regardless of whether they are useful
@@ -542,6 +561,17 @@ int ethr_dw_atomic_cmpxchg(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_s
}
#endif
+int ethr_dw_atomic_cmpxchg_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
+{
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_dw_atomic_cmpxchg_ddrb__(var, val, old_val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_dw_atomic_cmpxchg(var, val, old_val);
+#else
+ return ethr_dw_atomic_cmpxchg_rb(var, val, old_val);
+#endif
+}
+
int ETHR_DW_ATOMIC_FUNC__(cmpxchg_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val)
{
int res;
@@ -756,6 +786,17 @@ void ethr_dw_atomic_set(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
}
#endif
+void ethr_dw_atomic_set_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_dw_atomic_set_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_dw_atomic_set(var, val);
+#else
+ ethr_dw_atomic_set_rb(var, val);
+#endif
+}
+
void ETHR_DW_ATOMIC_FUNC__(set_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -910,6 +951,17 @@ void ethr_dw_atomic_read(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
}
#endif
+void ethr_dw_atomic_read_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_dw_atomic_read_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_dw_atomic_read(var, val);
+#else
+ ethr_dw_atomic_read_rb(var, val);
+#endif
+}
+
void ETHR_DW_ATOMIC_FUNC__(read_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -1061,6 +1113,17 @@ void ethr_dw_atomic_init(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
}
#endif
+void ethr_dw_atomic_init_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
+{
+#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_dw_atomic_init_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_dw_atomic_init(var, val);
+#else
+ ethr_dw_atomic_init_rb(var, val);
+#endif
+}
+
void ETHR_DW_ATOMIC_FUNC__(init_rb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val)
{
ETHR_ASSERT(var);
@@ -1221,6 +1284,17 @@ ethr_sint_t ethr_atomic_cmpxchg(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t
return res;
}
+ethr_sint_t ethr_atomic_cmpxchg_ddrb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_cmpxchg_ddrb__(var, val, old_val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_cmpxchg(var, val, old_val);
+#else
+ return ethr_atomic_cmpxchg_rb(var, val, old_val);
+#endif
+}
+
ethr_sint_t ethr_atomic_cmpxchg_rb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val)
{
ethr_sint_t res;
@@ -1332,6 +1406,17 @@ ethr_sint_t ethr_atomic_xchg(ethr_atomic_t *var, ethr_sint_t val)
return res;
}
+ethr_sint_t ethr_atomic_xchg_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_xchg_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_xchg(var, val);
+#else
+ return ethr_atomic_xchg_rb(var, val);
+#endif
+}
+
ethr_sint_t ethr_atomic_xchg_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ethr_sint_t res;
@@ -1437,6 +1522,17 @@ void ethr_atomic_set(ethr_atomic_t *var, ethr_sint_t val)
}
+void ethr_atomic_set_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_set_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic_set(var, val);
+#else
+ ethr_atomic_set_rb(var, val);
+#endif
+}
+
void ethr_atomic_set_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -1536,6 +1632,17 @@ void ethr_atomic_init(ethr_atomic_t *var, ethr_sint_t val)
}
+void ethr_atomic_init_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_init_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic_init(var, val);
+#else
+ ethr_atomic_init_rb(var, val);
+#endif
+}
+
void ethr_atomic_init_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ETHR_ASSERT(var);
@@ -1632,6 +1739,17 @@ ethr_sint_t ethr_atomic_add_read(ethr_atomic_t *var, ethr_sint_t val)
return res;
}
+ethr_sint_t ethr_atomic_add_read_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_add_read_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_add_read(var, val);
+#else
+ return ethr_atomic_add_read_rb(var, val);
+#endif
+}
+
ethr_sint_t ethr_atomic_add_read_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ethr_sint_t res;
@@ -1738,6 +1856,17 @@ ethr_sint_t ethr_atomic_read(ethr_atomic_t *var)
return res;
}
+ethr_sint_t ethr_atomic_read_ddrb(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_read_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_read(var);
+#else
+ return ethr_atomic_read_rb(var);
+#endif
+}
+
ethr_sint_t ethr_atomic_read_rb(ethr_atomic_t *var)
{
ethr_sint_t res;
@@ -1843,6 +1972,17 @@ ethr_sint_t ethr_atomic_inc_read(ethr_atomic_t *var)
return res;
}
+ethr_sint_t ethr_atomic_inc_read_ddrb(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_inc_read_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_inc_read(var);
+#else
+ return ethr_atomic_inc_read_rb(var);
+#endif
+}
+
ethr_sint_t ethr_atomic_inc_read_rb(ethr_atomic_t *var)
{
ethr_sint_t res;
@@ -1949,6 +2089,17 @@ ethr_sint_t ethr_atomic_dec_read(ethr_atomic_t *var)
return res;
}
+ethr_sint_t ethr_atomic_dec_read_ddrb(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_dec_read_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_dec_read(var);
+#else
+ return ethr_atomic_dec_read_rb(var);
+#endif
+}
+
ethr_sint_t ethr_atomic_dec_read_rb(ethr_atomic_t *var)
{
ethr_sint_t res;
@@ -2054,6 +2205,17 @@ void ethr_atomic_add(ethr_atomic_t *var, ethr_sint_t val)
}
+void ethr_atomic_add_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_add_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic_add(var, val);
+#else
+ ethr_atomic_add_rb(var, val);
+#endif
+}
+
void ethr_atomic_add_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -2154,6 +2316,17 @@ void ethr_atomic_inc(ethr_atomic_t *var)
}
+void ethr_atomic_inc_ddrb(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_inc_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic_inc(var);
+#else
+ ethr_atomic_inc_rb(var);
+#endif
+}
+
void ethr_atomic_inc_rb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -2254,6 +2427,17 @@ void ethr_atomic_dec(ethr_atomic_t *var)
}
+void ethr_atomic_dec_ddrb(ethr_atomic_t *var)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ ethr_atomic_dec_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic_dec(var);
+#else
+ ethr_atomic_dec_rb(var);
+#endif
+}
+
void ethr_atomic_dec_rb(ethr_atomic_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -2355,6 +2539,17 @@ ethr_sint_t ethr_atomic_read_band(ethr_atomic_t *var, ethr_sint_t val)
return res;
}
+ethr_sint_t ethr_atomic_read_band_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_read_band_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_read_band(var, val);
+#else
+ return ethr_atomic_read_band_rb(var, val);
+#endif
+}
+
ethr_sint_t ethr_atomic_read_band_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ethr_sint_t res;
@@ -2461,6 +2656,17 @@ ethr_sint_t ethr_atomic_read_bor(ethr_atomic_t *var, ethr_sint_t val)
return res;
}
+ethr_sint_t ethr_atomic_read_bor_ddrb(ethr_atomic_t *var, ethr_sint_t val)
+{
+#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS)
+ return ethr_atomic_read_bor_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic_read_bor(var, val);
+#else
+ return ethr_atomic_read_bor_rb(var, val);
+#endif
+}
+
ethr_sint_t ethr_atomic_read_bor_rb(ethr_atomic_t *var, ethr_sint_t val)
{
ethr_sint_t res;
@@ -2587,6 +2793,17 @@ ethr_sint32_t ethr_atomic32_cmpxchg(ethr_atomic32_t *var, ethr_sint32_t val, eth
return res;
}
+ethr_sint32_t ethr_atomic32_cmpxchg_ddrb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_cmpxchg_ddrb__(var, val, old_val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_cmpxchg(var, val, old_val);
+#else
+ return ethr_atomic32_cmpxchg_rb(var, val, old_val);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_cmpxchg_rb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val)
{
ethr_sint32_t res;
@@ -2675,6 +2892,17 @@ ethr_sint32_t ethr_atomic32_xchg(ethr_atomic32_t *var, ethr_sint32_t val)
return res;
}
+ethr_sint32_t ethr_atomic32_xchg_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_xchg_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_xchg(var, val);
+#else
+ return ethr_atomic32_xchg_rb(var, val);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_xchg_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ethr_sint32_t res;
@@ -2762,6 +2990,17 @@ void ethr_atomic32_set(ethr_atomic32_t *var, ethr_sint32_t val)
}
+void ethr_atomic32_set_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_set_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic32_set(var, val);
+#else
+ ethr_atomic32_set_rb(var, val);
+#endif
+}
+
void ethr_atomic32_set_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -2843,6 +3082,17 @@ void ethr_atomic32_init(ethr_atomic32_t *var, ethr_sint32_t val)
}
+void ethr_atomic32_init_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_init_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic32_init(var, val);
+#else
+ ethr_atomic32_init_rb(var, val);
+#endif
+}
+
void ethr_atomic32_init_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ETHR_ASSERT(var);
@@ -2921,6 +3171,17 @@ ethr_sint32_t ethr_atomic32_add_read(ethr_atomic32_t *var, ethr_sint32_t val)
return res;
}
+ethr_sint32_t ethr_atomic32_add_read_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_add_read_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_add_read(var, val);
+#else
+ return ethr_atomic32_add_read_rb(var, val);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_add_read_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ethr_sint32_t res;
@@ -3009,6 +3270,17 @@ ethr_sint32_t ethr_atomic32_read(ethr_atomic32_t *var)
return res;
}
+ethr_sint32_t ethr_atomic32_read_ddrb(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_read_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_read(var);
+#else
+ return ethr_atomic32_read_rb(var);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_read_rb(ethr_atomic32_t *var)
{
ethr_sint32_t res;
@@ -3097,6 +3369,17 @@ ethr_sint32_t ethr_atomic32_inc_read(ethr_atomic32_t *var)
return res;
}
+ethr_sint32_t ethr_atomic32_inc_read_ddrb(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_inc_read_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_inc_read(var);
+#else
+ return ethr_atomic32_inc_read_rb(var);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_inc_read_rb(ethr_atomic32_t *var)
{
ethr_sint32_t res;
@@ -3185,6 +3468,17 @@ ethr_sint32_t ethr_atomic32_dec_read(ethr_atomic32_t *var)
return res;
}
+ethr_sint32_t ethr_atomic32_dec_read_ddrb(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_dec_read_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_dec_read(var);
+#else
+ return ethr_atomic32_dec_read_rb(var);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_dec_read_rb(ethr_atomic32_t *var)
{
ethr_sint32_t res;
@@ -3272,6 +3566,17 @@ void ethr_atomic32_add(ethr_atomic32_t *var, ethr_sint32_t val)
}
+void ethr_atomic32_add_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_add_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic32_add(var, val);
+#else
+ ethr_atomic32_add_rb(var, val);
+#endif
+}
+
void ethr_atomic32_add_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -3354,6 +3659,17 @@ void ethr_atomic32_inc(ethr_atomic32_t *var)
}
+void ethr_atomic32_inc_ddrb(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_inc_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic32_inc(var);
+#else
+ ethr_atomic32_inc_rb(var);
+#endif
+}
+
void ethr_atomic32_inc_rb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -3436,6 +3752,17 @@ void ethr_atomic32_dec(ethr_atomic32_t *var)
}
+void ethr_atomic32_dec_ddrb(ethr_atomic32_t *var)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ ethr_atomic32_dec_ddrb__(var);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ethr_atomic32_dec(var);
+#else
+ ethr_atomic32_dec_rb(var);
+#endif
+}
+
void ethr_atomic32_dec_rb(ethr_atomic32_t *var)
{
ETHR_ASSERT(!ethr_not_inited__);
@@ -3519,6 +3846,17 @@ ethr_sint32_t ethr_atomic32_read_band(ethr_atomic32_t *var, ethr_sint32_t val)
return res;
}
+ethr_sint32_t ethr_atomic32_read_band_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_read_band_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_read_band(var, val);
+#else
+ return ethr_atomic32_read_band_rb(var, val);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_read_band_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ethr_sint32_t res;
@@ -3607,6 +3945,17 @@ ethr_sint32_t ethr_atomic32_read_bor(ethr_atomic32_t *var, ethr_sint32_t val)
return res;
}
+ethr_sint32_t ethr_atomic32_read_bor_ddrb(ethr_atomic32_t *var, ethr_sint32_t val)
+{
+#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS)
+ return ethr_atomic32_read_bor_ddrb__(var, val);
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ return ethr_atomic32_read_bor(var, val);
+#else
+ return ethr_atomic32_read_bor_rb(var, val);
+#endif
+}
+
ethr_sint32_t ethr_atomic32_read_bor_rb(ethr_atomic32_t *var, ethr_sint32_t val)
{
ethr_sint32_t res;
diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c
index 521640317e..89149b716b 100644
--- a/erts/lib_src/common/ethr_aux.c
+++ b/erts/lib_src/common/ethr_aux.c
@@ -40,7 +40,7 @@
#include <unistd.h>
#endif
-#define ERTS_TS_EV_ALLOC_DEFAULT_POOL_SIZE 100
+#define ERTS_TS_EV_ALLOC_DEFAULT_POOL_SIZE 4000
#define ERTS_TS_EV_ALLOC_POOL_SIZE 25
erts_cpu_info_t *ethr_cpu_info__;
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index 81fd6af80a..e363279f2e 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -223,9 +223,59 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx,
int try_write_lock);
#endif
+/* -- Utilities used by multiple implementations -- */
+
+#if defined(ETHR_USE_OWN_RWMTX_IMPL__) || defined(ETHR_USE_OWN_MTX_IMPL__) \
+ || defined(ETHR_WIN32_THREADS)
+
+static ETHR_INLINE void
+enqueue(ethr_ts_event **queue,
+ ethr_ts_event *tse_start,
+ ethr_ts_event *tse_end)
+{
+ if (!*queue) {
+ *queue = tse_start;
+ tse_start->prev = tse_end;
+ tse_end->next = tse_start;
+ }
+ else {
+ tse_end->next = *queue;
+ tse_start->prev = (*queue)->prev;
+ (*queue)->prev->next = tse_start;
+ (*queue)->prev = tse_end;
+ }
+}
+
+
+static ETHR_INLINE void
+dequeue(ethr_ts_event **queue,
+ ethr_ts_event *tse_start,
+ ethr_ts_event *tse_end)
+{
+ if (tse_start->prev == tse_end) {
+ ETHR_ASSERT(*queue == tse_start && tse_end->next == tse_start);
+ *queue = NULL;
+ }
+ else {
+ if (*queue == tse_start)
+ *queue = tse_end->next;
+ tse_end->next->prev = tse_start->prev;
+ tse_start->prev->next = tse_end->next;
+ }
+}
+
+#endif
+
#if defined(ETHR_USE_OWN_RWMTX_IMPL__) || defined(ETHR_USE_OWN_MTX_IMPL__)
-/* -- Utilities operating both on ordinary mutexes and read write mutexes -- */
+static ETHR_INLINE void
+insert(ethr_ts_event *tse_pred, ethr_ts_event *tse)
+{
+ tse->next = tse_pred->next;
+ tse->prev = tse_pred;
+ tse_pred->next->prev = tse;
+ tse_pred->next = tse;
+}
static ETHR_INLINE void
rwmutex_freqread_wtng_rdrs_inc(ethr_rwmutex *rwmtx, ethr_ts_event *tse)
@@ -355,51 +405,6 @@ rwmutex_freqread_rdrs_read(ethr_rwmutex *rwmtx, int ix)
return res;
}
-
-static ETHR_INLINE void
-enqueue(ethr_ts_event **queue,
- ethr_ts_event *tse_start,
- ethr_ts_event *tse_end)
-{
- if (!*queue) {
- *queue = tse_start;
- tse_start->prev = tse_end;
- tse_end->next = tse_start;
- }
- else {
- tse_end->next = *queue;
- tse_start->prev = (*queue)->prev;
- (*queue)->prev->next = tse_start;
- (*queue)->prev = tse_end;
- }
-}
-
-static ETHR_INLINE void
-insert(ethr_ts_event *tse_pred, ethr_ts_event *tse)
-{
- tse->next = tse_pred->next;
- tse->prev = tse_pred;
- tse_pred->next->prev = tse;
- tse_pred->next = tse;
-}
-
-static ETHR_INLINE void
-dequeue(ethr_ts_event **queue,
- ethr_ts_event *tse_start,
- ethr_ts_event *tse_end)
-{
- if (tse_start->prev == tse_end) {
- ETHR_ASSERT(*queue == tse_start && tse_end->next == tse_start);
- *queue = NULL;
- }
- else {
- if (*queue == tse_start)
- *queue = tse_end->next;
- tse_end->next->prev = tse_start->prev;
- tse_start->prev->next = tse_end->next;
- }
-}
-
static void
event_wait(struct ethr_mutex_base_ *mtxb,
ethr_ts_event *tse,
@@ -1244,7 +1249,7 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
return 0;
}
-#else
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
/* -- pthread mutex and condition variables -------------------------------- */
int
@@ -1261,6 +1266,12 @@ ethr_mutex_init(ethr_mutex *mtx)
}
int
+ethr_mutex_init_opt(ethr_mutex *mtx, ethr_mutex_opt *opt)
+{
+ return ethr_mutex_init(mtx);
+}
+
+int
ethr_mutex_destroy(ethr_mutex *mtx)
{
#if ETHR_XCHK
@@ -1293,6 +1304,12 @@ ethr_cond_init(ethr_cond *cnd)
}
int
+ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt)
+{
+ return ethr_cond_init(cnd);
+}
+
+int
ethr_cond_destroy(ethr_cond *cnd)
{
#if ETHR_XCHK
@@ -1354,7 +1371,388 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
return res;
}
-#endif /* pthread_mutex */
+#elif defined(ETHR_WIN32_THREADS) || defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+
+/*
+ * As of Vista/Server, 2008 Windows has condition variables that can be
+ * used with critical sections. However, we need to be able to run on
+ * older Windows versions too, so we need to implement condition variables
+ * ourselves.
+ */
+
+#ifdef ETHR_DBG_WIN_MTX_WITH_PTHREADS
+/*
+ * For debugging of this implementation on POSIX platforms...
+ */
+
+#define ethr_win_get_errno__() EINVAL
+#if defined(__GNUC__)
+#define __forceinline __inline__
+#else
+#define __forceinline
+#endif
+
+static int
+InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *cs, int sc)
+{
+ return 0 == pthread_mutex_init((pthread_mutex_t *) cs, NULL);
+}
+
+static void DeleteCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res = pthread_mutex_destroy((pthread_mutex_t *) cs);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+}
+
+int TryEnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res;
+ res = pthread_mutex_trylock((pthread_mutex_t *) cs);
+ if (res != 0 && res != EBUSY)
+ ETHR_FATAL_ERROR__(res);
+ return res == 0;
+}
+
+void EnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res = pthread_mutex_lock((pthread_mutex_t *) cs);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+}
+
+void LeaveCriticalSection(CRITICAL_SECTION *cs)
+{
+ int res = pthread_mutex_unlock((pthread_mutex_t *) cs);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+}
+
+#endif
+
+#define ETHR_CND_WAIT__ ((ethr_sint32_t) 0x11dead11)
+#define ETHR_CND_WAKEUP__ ((ethr_sint32_t) 0x11beef11)
+
+static __forceinline void
+cond_wakeup(ethr_ts_event *tse)
+{
+ ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs) == ETHR_CND_WAIT__);
+
+ ethr_atomic32_set_relb(&tse->uaflgs, ETHR_CND_WAKEUP__);
+ ethr_event_set(&tse->event);
+}
+
+void
+ethr_mutex_cond_wakeup__(ethr_mutex *mtx)
+{
+ /*
+ * Called by ethr_mutex_unlock() when we have
+ * cond signal/broadcast wakeups waiting to
+ * be completed.
+ */
+ ethr_ts_event *tse;
+
+ if (!mtx->posix_compliant) {
+ tse = mtx->wakeups;
+ dequeue(&mtx->wakeups, tse, tse);
+ }
+ else {
+ ethr_spin_lock(&mtx->lock);
+ tse = mtx->wakeups;
+ if (tse)
+ dequeue(&mtx->wakeups, tse, tse);
+ if (!mtx->wakeups)
+ ethr_atomic32_set_relb(&mtx->have_wakeups, 0);
+ ethr_spin_unlock(&mtx->lock);
+ }
+
+ LeaveCriticalSection(&mtx->cs);
+
+ ETHR_ASSERT(tse || mtx->posix_compliant);
+
+ /*
+ * We delay actual condition variable wakeup until
+ * this point when we have left the critical section.
+ * This in order to avoid that the other thread is
+ * woken and then right away have to go to sleep
+ * waiting for the critical section that we are in.
+ *
+ * We also only wake one thread at a time even if
+ * there are multiple threads waiting to be woken.
+ * Otherwise all but one will be woken and then right
+ * away have to go to sleep on the critical section.
+ * Since each wakeup is guaranteed to generate at
+ * least one lock/unlock sequence on this mutex, all
+ * threads will eventually be woken.
+ */
+
+ if (tse)
+ cond_wakeup(tse);
+}
+
+int
+ethr_mutex_init_opt(ethr_mutex *mtx, ethr_mutex_opt *opt)
+{
+ int spincount;
+#if ETHR_XCHK
+ if (!mtx) {
+ ETHR_ASSERT(0);
+ return EINVAL;
+ }
+ mtx->initialized = ETHR_MUTEX_INITIALIZED;
+#endif
+
+ spincount = opt ? opt->aux_spincount : 0;
+ if (spincount < 0)
+ spincount = 0;
+
+ if (!InitializeCriticalSectionAndSpinCount(&mtx->cs, spincount)) {
+#if ETHR_XCHK
+ mtx->initialized = 0;
+#endif
+ return ethr_win_get_errno__();
+ }
+
+ mtx->posix_compliant = opt ? opt->posix_compliant : 0;
+ mtx->wakeups = NULL;
+ if (mtx->posix_compliant) {
+ ethr_atomic32_init(&mtx->locked, 0);
+ ethr_atomic32_init(&mtx->have_wakeups, 0);
+ ethr_spinlock_init(&mtx->lock);
+ }
+ return 0;
+}
+
+int
+ethr_mutex_init(ethr_mutex *mtx)
+{
+ return ethr_mutex_init_opt(mtx, NULL);
+}
+
+int
+ethr_mutex_destroy(ethr_mutex *mtx)
+{
+ DeleteCriticalSection(&mtx->cs);
+ if (mtx->posix_compliant)
+ return ethr_spinlock_destroy(&mtx->lock);
+ else
+ return 0;
+}
+
+int
+ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
+{
+ void *udata;
+ ethr_ts_event *tse = ethr_get_ts_event();
+ int spincount;
+
+ udata = tse->udata;
+ tse->udata = (void *) mtx;
+ ethr_atomic32_set_relb(&tse->uaflgs, ETHR_CND_WAIT__);
+
+ EnterCriticalSection(&cnd->cs);
+ enqueue(&cnd->waiters, tse, tse);
+ LeaveCriticalSection(&cnd->cs);
+
+ ethr_mutex_unlock(mtx);
+
+ spincount = cnd->spincount;
+
+ while (ethr_atomic32_read_acqb(&tse->uaflgs) != ETHR_CND_WAKEUP__) {
+ ethr_event_reset(&tse->event);
+ if (ethr_atomic32_read_acqb(&tse->uaflgs) == ETHR_CND_WAKEUP__)
+ break;
+ ethr_event_swait(&tse->event, spincount);
+ spincount = 0;
+ }
+
+ tse->udata = udata;
+ ethr_leave_ts_event(tse);
+
+ ethr_mutex_lock(mtx);
+
+ return 0;
+}
+
+static __forceinline void
+posix_compliant_mtx_enqueue(ethr_mutex *mtx,
+ ethr_ts_event *tse_start,
+ ethr_ts_event *tse_end)
+{
+ ethr_ts_event *tse_wakeup = NULL; /* Avoid erroneous compiler warning... */
+ /*
+ * The associated mutex might not be locked, so we need to
+ * check if it is. If locked, enqueue for wakeup at unlock;
+ * otherwise, wakeup the first one now and enqueue the rest.
+ */
+ if (tse_start == tse_end && !ethr_atomic32_read(&mtx->locked)) {
+ tse_wakeup = tse_start;
+ wakeup:
+ cond_wakeup(tse_wakeup);
+ }
+ else {
+ int need_wakeup;
+ ethr_spin_lock(&mtx->lock);
+ if (!mtx->wakeups)
+ ethr_atomic32_set_mb(&mtx->have_wakeups, 1);
+ need_wakeup = !ethr_atomic32_read(&mtx->locked);
+ if (need_wakeup) {
+ if (tse_start == tse_end) {
+ if (!mtx->wakeups)
+ ethr_atomic32_set_relb(&mtx->have_wakeups, 0);
+ ethr_spin_unlock(&mtx->lock);
+ tse_wakeup = tse_start;
+ goto wakeup;
+ }
+ tse_wakeup = tse_start;
+ tse_start = tse_start->next;
+ }
+ enqueue(&mtx->wakeups, tse_start, tse_end);
+ ethr_spin_unlock(&mtx->lock);
+ if (need_wakeup)
+ goto wakeup;
+ }
+}
+
+static __forceinline void
+enqueue_cond_wakeups(ethr_ts_event *queue, int posix_compliant)
+{
+ if (queue) {
+ int more;
+ ethr_ts_event *q = queue;
+
+ /*
+ * Waiters may be using different mutexes...
+ */
+
+ do {
+ ethr_mutex *mtx;
+ ethr_ts_event *tse, *tse_start, *tse_end;
+
+ more = 0;
+ tse_start = q;
+ mtx = (ethr_mutex *) tse_start->udata;
+
+ ETHR_ASSERT(posix_compliant
+ ? mtx->posix_compliant
+ : !mtx->posix_compliant);
+
+ ETHR_ASSERT(ethr_atomic32_read(&tse_start->uaflgs)
+ == ETHR_CND_WAIT__);
+ ETHR_ASSERT(mtx->initialized == ETHR_MUTEX_INITIALIZED);
+
+ tse_end = tse_start->prev;
+
+ for (tse = tse_start->next; tse != tse_start; tse = tse->next) {
+
+ ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs)
+ == ETHR_CND_WAIT__);
+
+ if (mtx != (ethr_mutex *) tse->udata) {
+ tse_end = tse->prev;
+ dequeue(&q, tse_start, tse_end);
+ more = 1;
+ break;
+ }
+ }
+
+ if (posix_compliant)
+ posix_compliant_mtx_enqueue(mtx, tse_start, tse_end);
+ else
+ enqueue(&mtx->wakeups, tse_start, tse_end);
+
+ } while (more);
+ }
+}
+
+void
+ethr_cond_broadcast(ethr_cond *cnd)
+{
+ ethr_ts_event *waiters;
+
+ EnterCriticalSection(&cnd->cs);
+ waiters = cnd->waiters;
+ cnd->waiters = NULL;
+ LeaveCriticalSection(&cnd->cs);
+
+ if (cnd->posix_compliant)
+ enqueue_cond_wakeups(waiters, 1);
+ else
+ enqueue_cond_wakeups(waiters, 0);
+}
+
+void
+ethr_cond_signal(ethr_cond *cnd)
+{
+ ethr_mutex *mtx;
+ ethr_ts_event *tse;
+
+ EnterCriticalSection(&cnd->cs);
+ tse = cnd->waiters;
+ if (tse)
+ dequeue(&cnd->waiters, tse, tse);
+ LeaveCriticalSection(&cnd->cs);
+
+ if (tse) {
+ mtx = (ethr_mutex *) tse->udata;
+
+ ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs) == ETHR_CND_WAIT__);
+ ETHR_ASSERT(mtx->initialized == ETHR_MUTEX_INITIALIZED);
+ ETHR_ASSERT(cnd->posix_compliant
+ ? mtx->posix_compliant
+ : !mtx->posix_compliant);
+
+ if (cnd->posix_compliant)
+ posix_compliant_mtx_enqueue(mtx, tse, tse);
+ else
+ enqueue(&mtx->wakeups, tse, tse);
+ }
+}
+
+int
+ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt)
+{
+ int spincount;
+
+#if ETHR_XCHK
+ if (!cnd) {
+ ETHR_ASSERT(0);
+ return EINVAL;
+ }
+ cnd->initialized = ETHR_COND_INITIALIZED;
+#endif
+
+ spincount = opt ? opt->aux_spincount : 0;
+ if (spincount < 0)
+ spincount = 0;
+
+ if (!InitializeCriticalSectionAndSpinCount(&cnd->cs, spincount)) {
+#if ETHR_XCHK
+ cnd->initialized = 0;
+#endif
+ return ethr_win_get_errno__();
+ }
+
+ cnd->posix_compliant = opt ? opt->posix_compliant : 0;
+ cnd->waiters = NULL;
+ cnd->spincount = spincount;
+ return 0;
+}
+
+int
+ethr_cond_init(ethr_cond *cnd)
+{
+ return ethr_cond_init_opt(cnd, NULL);
+}
+
+int
+ethr_cond_destroy(ethr_cond *cnd)
+{
+ DeleteCriticalSection(&cnd->cs);
+ return 0;
+}
+
+#endif
/* -- Exported symbols of inline functions --------------------------------- */
@@ -1969,7 +2367,7 @@ dbg_unlock_wake(ethr_rwmutex *rwmtx,
exp = have_w ? ETHR_RWMTX_W_FLG__ : 0;
if (rwmtx->type != ETHR_RWMUTEX_TYPE_NORMAL)
- imask = ETHR_RWMTX_R_PEND_UNLCK_MASK__;
+ imask = ETHR_RWMTX_R_PEND_UNLCK_MASK__|ETHR_RWMTX_R_ABRT_UNLCK_FLG__;
else {
#ifdef ETHR_RLOCK_WITH_INC_DEC
imask = ETHR_RWMTX_RS_MASK__;
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index ad29249bac..fb7d135418 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -123,34 +123,53 @@ ethr_ts_event *ethr_get_tse__(void)
#if defined(ETHR_PPC_RUNTIME_CONF__)
-static volatile int lwsync_caused_sigill;
+#include <sys/wait.h>
static void
handle_lwsync_sigill(int signum)
{
- lwsync_caused_sigill = 1;
+ _exit(1);
}
static int
ppc_init__(void)
{
- struct sigaction act, oact;
- lwsync_caused_sigill = 0;
+ int pid;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = handle_lwsync_sigill;
- if (sigaction(SIGILL, &act, &oact) != 0)
- return errno;
+ /* If anything what so ever failes we assume no lwsync for safety */
+ ethr_runtime__.conf.have_lwsync = 0;
+
+ /*
+ * We perform the lwsync test (which might cause an illegal
+ * instruction signal) in a separate process in order to be
+ * completely certain that we do not mess up our own state.
+ */
+ pid = fork();
+ if (pid == 0) {
+ struct sigaction act, oact;
- __asm__ __volatile__ ("lwsync\n\t" : : : "memory");
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESETHAND;
+ act.sa_handler = handle_lwsync_sigill;
+ if (sigaction(SIGILL, &act, &oact) != 0)
+ _exit(2);
- act.sa_flags = 0;
- act.sa_handler = SIG_DFL;
- if (sigaction(SIGILL, &act, &oact) != 0)
- return errno;
+ __asm__ __volatile__ ("lwsync\n\t" : : : "memory");
+
+ _exit(0);
+ }
- ethr_runtime__.conf.have_lwsync = (int) !lwsync_caused_sigill;
+ if (pid != -1) {
+ while (1) {
+ int status, res;
+ res = waitpid(pid, &status, 0);
+ if (res == pid) {
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ ethr_runtime__.conf.have_lwsync = 1;
+ break;
+ }
+ }
+ }
return 0;
}
diff --git a/erts/lib_src/utils/make_atomics_api b/erts/lib_src/utils/make_atomics_api
index f4e71c7618..74736c5a2d 100755
--- a/erts/lib_src/utils/make_atomics_api
+++ b/erts/lib_src/utils/make_atomics_api
@@ -4,7 +4,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,9 @@
-define(DW_RTCHK_MACRO, "ETHR_RTCHK_USE_NATIVE_DW_ATOMIC_IMPL__").
%% Barrier versions we implement
--define(BARRIERS, [none, rb, wb, acqb, relb, mb]).
+-define(BARRIERS, [none, ddrb, rb, wb, acqb, relb, mb]).
+-define(NON_NATIVE_BARRIERS, [ddrb]).
+-define(NATIVE_BARRIERS, (?BARRIERS -- ?NON_NATIVE_BARRIERS)).
-define(ATOMIC_SIZES, ["dword", "word", "32"]).
@@ -381,7 +383,6 @@ do_func_header(#atomic_context{dw = true,
cmpxchg, Inline, Func) ->
[Inline, "int ", Func, "(", AtomicT, " *", Arg1, ", ", AintT, " *", Arg2, ", ", AintT, " *", Arg3, ")"].
-
xbarriers(_Op, none, _NB) ->
{"", ""};
@@ -455,7 +456,7 @@ try_barrier_order_first(mb) ->
try_barrier_order(B) ->
First = try_barrier_order_first(B),
- First ++ (?BARRIERS -- First).
+ First ++ (?NATIVE_BARRIERS -- First).
native_barrier_op(#atomic_context{'NATMC' = NATMC} = AC, If, ExtraDecl, Op, B, NB, TypeCasts) ->
NOpStr = opstr(native(Op)),
@@ -571,12 +572,12 @@ do_cmpxchg_fallback_define(#atomic_context{'NATMC' = NATMC,
NoneTryBarrierOrder = try_barrier_order(none),
%% First a sanity check
["
-#if (", NotDefCMPXCHG(hd(?BARRIERS)) ,
+#if (", NotDefCMPXCHG(hd(?NATIVE_BARRIERS)) ,
lists:map(fun (B) ->
[" \\
&& ", NotDefCMPXCHG(B)]
end,
- tl(?BARRIERS)), ")
+ tl(?NATIVE_BARRIERS)), ")
# error \"No native cmpxchg() op available\"
#endif
@@ -744,7 +745,7 @@ translate_have_defs(#atomic_context{dw = DW, 'NATMC' = NATMC}) ->
]
end]
end,
- ?BARRIERS)
+ ?NATIVE_BARRIERS)
end,
case DW of
true -> ?DW_ATOMIC_OPS;
@@ -801,6 +802,69 @@ rtchk_fallback_call(Return, #atomic_context{dw = DW,
false -> [RetVar, " ="]
end, [?DW_FUNC_MACRO, "(", opstr(Op), op_barrier_ext(B), ")"], Arg1, Arg2, Arg3, "").
+non_native_barrier(B) ->
+ lists:member(B, ?NON_NATIVE_BARRIERS).
+
+non_native_barrier_impl(AC, inline_implementation = Type, Op, B) ->
+ ["
+", func_header(AC, Type, false, Op, B), "
+{",
+ case B of
+ ddrb ->
+ ["
+#ifdef ETHR_ORDERED_READ_DEPEND
+ ", func_call(AC, Type, Op, none, true), "
+#else
+ ", func_call(AC, Type, Op, rb, true), "
+#endif
+"
+ ]
+ end,
+ "}
+"
+ ];
+non_native_barrier_impl(#atomic_context{have_native_atomic_ops = HaveNative} = AC,
+ implementation = Type,
+ Op,
+ B) ->
+ ["
+", func_header(AC, Type, false, Op, B), "
+{",
+ case B of
+ ddrb ->
+ ["
+#if defined(", HaveNative, ")
+ ", func_call(AC, Type, Op, B, true), "
+#elif defined(ETHR_ORDERED_READ_DEPEND)
+ ", func_call(AC, symbol_implementation, Op, none, true), "
+#else
+ ", func_call(AC, symbol_implementation, Op, rb, true), "
+#endif
+"
+ ]
+ end,
+ "}
+"
+ ].
+
+func_call(#atomic_context{'ATMC' = ATMC} = AC, inline_implementation, Op, B, RetStatement) ->
+ func_call(AC, Op, ["ETHR_", ATMC, "_FUNC__(", opstr(Op), op_barrier_ext(B), ")"], RetStatement);
+func_call(#atomic_context{atomic = Atomic} = AC, implementation, Op, B, RetStatement) ->
+ func_call(AC, Op, [Atomic, "_", opstr(Op), op_barrier_ext(B), "__"], RetStatement);
+func_call(#atomic_context{atomic = Atomic} = AC, symbol_implementation, Op, B, RetStatement) ->
+ func_call(AC, Op, [Atomic, "_", opstr(Op), op_barrier_ext(B)], RetStatement).
+
+func_call(#atomic_context{dw = DW, arg1 = Arg1, arg2 = Arg2, arg3 = Arg3} = AC, Op, Func, true) ->
+ op_call(Op, DW, case is_return_op(AC, Op) of
+ true -> "return";
+ false -> ""
+ end, Func, Arg1, Arg2, Arg3, "");
+func_call(#atomic_context{dw = DW, arg1 = Arg1, arg2 = Arg2, arg3 = Arg3, ret_var = RetVar} = AC, Op, Func, false) ->
+ op_call(Op, DW, case is_return_op(AC, Op) of
+ true -> [RetVar, " = "];
+ false -> ""
+ end, Func, Arg1, Arg2, Arg3, "").
+
make_implementations(#atomic_context{dw = DW,
ret_type = RetType,
ret_var = RetVar,
@@ -858,73 +922,78 @@ make_implementations(#atomic_context{dw = DW,
",
lists:map(fun (B) ->
- TryBarriers = try_barrier_order(B),
- ["
+ case non_native_barrier(B) of
+ true ->
+ non_native_barrier_impl(AC, inline_implementation, Op, B);
+ false ->
+ TryBarriers = try_barrier_order(B),
+ ["
", func_header(AC, inline_implementation, false, Op, B), "
{
",
- case is_return_op(AC, Op) of
- true ->
- [" ", RetType, " ", RetVar, ";\n"];
- _ -> ""
- end,
- case DW of
- true ->
- [RtchkBegin,
- "\n",
- su_dw_native_barrier_op(AC, "#if", Op, B, hd(TryBarriers)),
- lists:map(fun (NB) ->
- su_dw_native_barrier_op(AC, "#elif", Op, B, NB)
- end,
- tl(TryBarriers)),
- lists:map(fun (NB) ->
- dw_native_barrier_op(AC, "#elif", "", Op, B, NB)
- end,
- TryBarriers),
- case simple_fallback(AC, Op, B) of
- "" ->
- %% No simple fallback available;
- %% use cmpxchg() fallbacks...
- [cmpxchg_fallbacks(AC#atomic_context{'NATMC' = ["SU_", NATMC]}, true, Op, B),
- cmpxchg_fallbacks(AC, false, Op, B),
- "#else
+ case is_return_op(AC, Op) of
+ true ->
+ [" ", RetType, " ", RetVar, ";\n"];
+ _ -> ""
+ end,
+ case DW of
+ true ->
+ [RtchkBegin,
+ "\n",
+ su_dw_native_barrier_op(AC, "#if", Op, B, hd(TryBarriers)),
+ lists:map(fun (NB) ->
+ su_dw_native_barrier_op(AC, "#elif", Op, B, NB)
+ end,
+ tl(TryBarriers)),
+ lists:map(fun (NB) ->
+ dw_native_barrier_op(AC, "#elif", "", Op, B, NB)
+ end,
+ TryBarriers),
+ case simple_fallback(AC, Op, B) of
+ "" ->
+ %% No simple fallback available;
+ %% use cmpxchg() fallbacks...
+ [cmpxchg_fallbacks(AC#atomic_context{'NATMC' = ["SU_", NATMC]}, true, Op, B),
+ cmpxchg_fallbacks(AC, false, Op, B),
+ "#else
#error \"Missing implementation of ", Atomic, "_", opstr(Op), op_barrier_ext(B), "()!\"
#endif
"
- ];
- SimpleFallback ->
- ["#else\n", SimpleFallback, "#endif\n"]
- end,
- RtchkEnd(false, Op, B), "\n"];
- false ->
- [native_barrier_op(AC, "#if", "", Op, B, hd(TryBarriers), true),
- lists:map(fun (NB) ->
- native_barrier_op(AC, "#elif", "", Op, B, NB, true)
- end,
- tl(TryBarriers)),
- case simple_fallback(AC, Op, B) of
- "" ->
- %% No simple fallback available;
- %% use cmpxchg() fallbacks...
- [cmpxchg_fallbacks(AC, false, Op, B),
- "#else
+ ];
+ SimpleFallback ->
+ ["#else\n", SimpleFallback, "#endif\n"]
+ end,
+ RtchkEnd(false, Op, B), "\n"];
+ false ->
+ [native_barrier_op(AC, "#if", "", Op, B, hd(TryBarriers), true),
+ lists:map(fun (NB) ->
+ native_barrier_op(AC, "#elif", "", Op, B, NB, true)
+ end,
+ tl(TryBarriers)),
+ case simple_fallback(AC, Op, B) of
+ "" ->
+ %% No simple fallback available;
+ %% use cmpxchg() fallbacks...
+ [cmpxchg_fallbacks(AC, false, Op, B),
+ "#else
#error \"Missing implementation of ", Atomic, "_", opstr(Op), op_barrier_ext(B), "()!\"
#endif
"
- ];
- SimpleFallback ->
- ["#else\n", SimpleFallback, "#endif\n"]
- end]
- end,
- case is_return_op(AC, Op) of
- true ->
- [" return ", RetVar, ";\n"];
- false ->
- ""
- end,
- "}\n"]
+ ];
+ SimpleFallback ->
+ ["#else\n", SimpleFallback, "#endif\n"]
+ end]
+ end,
+ case is_return_op(AC, Op) of
+ true ->
+ [" return ", RetVar, ";\n"];
+ false ->
+ ""
+ end,
+ "}\n"]
+ end
end,
- ?BARRIERS)]
+ ?NATIVE_BARRIERS ++ ?NON_NATIVE_BARRIERS)] %% non-native needs to be after native...
end,
case DW of
true -> ?DW_ATOMIC_OPS;
@@ -1159,33 +1228,38 @@ int ethr_have_native_dw_atomic(void)
",
lists:map(fun (B) ->
- ["\n",
- func_header(AC, implementation,
- case DW of
- true -> ?DW_FUNC_MACRO;
- false -> false
- end, Op, B),
- "\n{\n",
- case is_return_op(AC, Op) of
- true -> [" ", RetType, " ", RetVar, ";\n"];
- false -> ""
- end,
- case Op of
- init -> "";
- _ -> [" ETHR_ASSERT(!ethr_not_inited__);\n"]
- end,
- [" ETHR_ASSERT(", Arg1, ");\n"],
- make_native_impl_op(AC, Op, B),
- make_amc_fallback_op(AC#atomic_context{arg1 = FallbackVar}, Op, B),
- make_locked_fallback_op(AC#atomic_context{arg1 = FallbackVar}, Op, B),
- case is_return_op(AC, Op) of
- true -> [" return ", RetVar, ";"
- ];
- false ->
- ""
- end,
- "\n}\n",
- make_symbol_to_fallback_impl(AC, Op, B)]
+ Macro = case DW of
+ true -> ?DW_FUNC_MACRO;
+ false -> false
+ end,
+ case non_native_barrier(B) of
+ true ->
+ non_native_barrier_impl(AC, implementation, Op, B);
+ false ->
+ ["\n",
+ func_header(AC, implementation, Macro, Op, B),
+ "\n{\n",
+ case is_return_op(AC, Op) of
+ true -> [" ", RetType, " ", RetVar, ";\n"];
+ false -> ""
+ end,
+ case Op of
+ init -> "";
+ _ -> [" ETHR_ASSERT(!ethr_not_inited__);\n"]
+ end,
+ [" ETHR_ASSERT(", Arg1, ");\n"],
+ make_native_impl_op(AC, Op, B),
+ make_amc_fallback_op(AC#atomic_context{arg1 = FallbackVar}, Op, B),
+ make_locked_fallback_op(AC#atomic_context{arg1 = FallbackVar}, Op, B),
+ case is_return_op(AC, Op) of
+ true -> [" return ", RetVar, ";"
+ ];
+ false ->
+ ""
+ end,
+ "\n}\n",
+ make_symbol_to_fallback_impl(AC, Op, B)]
+ end
end,
?BARRIERS)]
end,
@@ -1233,7 +1307,7 @@ static char *native_", DW, "atomic", Bits, "_ops[] = {",
#endif"
]
end,
- ?BARRIERS)
+ ?NATIVE_BARRIERS)
end,
case NBits of
"dw" -> ?DW_ATOMIC_OPS;
@@ -1390,25 +1464,51 @@ comments() ->
* Appart from a function implementing the atomic operation
* with unspecified memory barrier semantics, there are
* functions implementing each operation with the following
- * memory barrier semantics:
-",
+ * implied memory barrier semantics:",
lists:map(fun (none) ->
"";
- (rb) ->
- [" * - rb (read barrier)\n"];
- (wb) ->
- [" * - wb (write barrier)\n"];
+ (mb) ->
+ ["
+ * - mb - Full memory barrier. Orders both loads, and
+ * stores before, and after the atomic operation.
+ * No load or store is allowed to be reordered
+ * over the atomic operation."];
(acqb) ->
- [" * - acqb (acquire barrier)\n"];
+ ["
+ * - acqb - Acquire barrier. Orders both loads, and stores
+ * appearing *after* the atomic operation. These
+ * are not allowed to be reordered over the
+ * atomic operation."];
(relb) ->
- [" * - relb (release barrier)\n"];
- (mb) ->
- [" * - mb (full memory barrier)\n"];
+ ["
+ * - relb - Release barrier. Orders both loads, and
+ * stores appearing *before* the atomic
+ * operation. These are not allowed to be
+ * reordered over the atomic operation."];
+ (rb) ->
+ ["
+ * - rb - Read barrier. Orders *only* loads. These are
+ * not allowed to be reordered over the barrier.
+ * Load in atomic operation is ordered *before*
+ * the barrier. "];
+ (ddrb) ->
+ ["
+ * - ddrb - Data dependency read barrier. Orders *only*
+ * loads according to data dependency across the
+ * barrier. Load in atomic operation is ordered
+ * before the barrier."];
+ (wb) ->
+ ["
+ * - wb - Write barrier. Orders *only* stores. These are
+ * not allowed to be reordered over the barrier.
+ * Store in atomic operation is ordered *after*
+ * the barrier."];
(B) ->
[" * - ", a2l(B), "\n"]
end,
- ?BARRIERS),
- " *
+ lists:reverse(?BARRIERS)),
+ "
+ *
* We implement all of these operation/barrier
* combinations, regardless of whether they are useful
* or not (some of them are useless).
diff --git a/erts/ntbuild.erl b/erts/ntbuild.erl
deleted file mode 100644
index e48be58c17..0000000000
--- a/erts/ntbuild.erl
+++ /dev/null
@@ -1,332 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% To be used from makefiles on the unix side executing things on the NT-side
--module(ntbuild).
-
--export([nmake/1, omake/1, waitnode/1, restart/1,
- setdir/1, run_tests/1, run_command/1]).
--export([serv_nmake/2, serv_omake/2, serv_restart/0, serv_run_tests/2,
- serv_run_command/1]).
-
-waitnode([NtNode]) ->
- % First, wait for node to disappear.
- case wait_disappear(NtNode, 0) of
- ok ->
- case wait_appear(NtNode, 0) of
- ok ->
- halt(0);
- fail ->
- halt(1)
- end;
- fail ->
- halt(1)
- end.
-
-% Wait for nt node to appear within 5 minutes.
-wait_appear(_NtNode, 300) ->
- fail;
-wait_appear(NtNode, N) ->
- receive after 1000 -> ok end,
- case nt_node_alive(NtNode, quiet) of
- no ->
- wait_appear(NtNode, N+1);
- yes ->
- ok
- end.
-
-
-
-% Waits for nt node to disappear within 3 minutes.
-wait_disappear(NtNode, 300) ->
- fail;
-wait_disappear(NtNode, N) ->
- receive after 1000 -> ok end,
- case nt_node_alive(NtNode, quiet) of
- yes ->
- wait_disappear(NtNode, N+1);
- no ->
- ok
- end.
-
-restart([NtNode]) ->
- case nt_node_alive(NtNode) of
- yes ->
- case rpc:call(NtNode, ntbuild, serv_restart, []) of
- ok ->
- io:format("halt(0)~n"),
- halt();
- Error ->
- io:format("halt(1)~n"),
- halt(1)
- end;
- no ->
- halt(1)
- end.
-
-
-setdir([NtNode, Dir0]) ->
- Dir = atom_to_list(Dir0),
- case nt_node_alive(NtNode) of
- yes ->
- case rpc:call(NtNode, file, set_cwd, [Dir]) of
- ok ->
- io:format("halt(0)~n"),
- halt();
- Error ->
- io:format("halt(1) (Error: ~p) (~p not found) ~n", [Error, Dir]),
- halt(1)
- end;
- no ->
- halt(1)
- end.
-
-run_tests([NtNode, Vsn0, Logdir]) ->
- Vsn = atom_to_list(Vsn0),
- case nt_node_alive(NtNode) of
- yes ->
- case rpc:call(NtNode, ntbuild, serv_run_tests, [Vsn, Logdir]) of
- ok ->
- io:format("halt(0)~n"),
- halt();
- Error ->
- io:format("RPC To Windows Node Failed: ~p~n", [Error]),
- io:format("halt(1)~n"),
- halt(1)
- end;
- no ->
- halt(1)
- end.
-
-run_command([NtNode, Cmd]) ->
- case nt_node_alive(NtNode) of
- yes ->
- case rpc:call(NtNode, ntbuild, serv_run_command, [Cmd]) of
- ok ->
- io:format("halt(0)~n"),
- halt();
- Error ->
- io:format("RPC To Windows Node Failed: ~p~n", [Error]),
- io:format("halt(1)~n"),
- halt(1)
- end;
- no ->
- halt(1)
- end.
-
-nmake([NtNode, Path, Options]) ->
-% io:format("nmake2(~w,~w)~n",[Path, Options]),
- Dir=atom_to_list(Path),
- Opt=atom_to_list(Options),
- case nt_node_alive(NtNode) of
- yes ->
- case rpc:call(NtNode, ntbuild, serv_nmake, [Dir, Opt]) of
- ok ->
- io:format("halt(0)~n"),
- halt();
- Error ->
- io:format("Error: ~n", [Error]),
- halt(1)
- end;
- no ->
- halt(1)
- end.
-
-omake([NtNode, Path, Options]) ->
- Dir=atom_to_list(Path),
- Opt=atom_to_list(Options),
- case nt_node_alive(NtNode) of
- yes ->
- case rpc:call(NtNode, ntbuild, serv_omake, [Dir, Opt]) of
- ok ->
- io:format("halt(0)~n"),
- halt();
- Error ->
- io:format("RPC To Windows Node Failed: ~p~n", [Error]),
- io:format("~p ~p~n", [Dir, Opt]),
- io:format("halt(1)~n"),
- halt(1)
- end;
- no ->
- halt(1)
- end.
-
-
-
-
-
-nt_node_alive(NtNode) ->
- case net:ping(NtNode) of
- pong ->
- yes;
- pang ->
- io:format("The NT node (~p) is not up. ~n",[NtNode]),
- no
- end.
-
-nt_node_alive(NtNode, quiet) ->
- case net:ping(NtNode) of
- pong ->
- yes;
- pang ->
- no
- end.
-
-
-
-%%%
-%%% The 'serv_' functions. Theese are the routines run on the WinNT node.
-%%%
-
-%%-----------------------
-%% serv_run_tests()
-%% Runs the tests.
-serv_run_tests(Vsn, Logdir) ->
- {ok, Cwd}=file:get_cwd(),
- io:format("serv_run_tests ~p ~p ~n", [Vsn, Logdir]),
- Cmd0= "set central_log_dir=" ++ Logdir,
- Erl = "C:/progra~1/erl"++Vsn++"/bin/erl",
- Cmd1 = Erl++" -sname a -setcookie a -noshell -noinput -s ts install -s ts run -s ts save -s erlang halt",
-%% Dir = "C:/temp/test_suite/test_server",
- Cmd= Cmd0 ++ "/r/n" ++ Cmd1,
- Dir = "C:/temp/test_server/p7a/test_server",
- file:set_cwd(Dir),
- Res=run_make_bat(Dir, Cmd),
- file:set_cwd(Cwd),
- Res.
-
-%%-----------------------
-%% serv_run_command()
-%% Runs a command.
-serv_run_command(Cmd) ->
- {ok, Cwd}=file:get_cwd(),
- Res=run_make_bat("", Cmd),
- file:set_cwd(Cwd),
- Res.
-
-%%-----------------------
-%% serv_restart()
-%% Reboots the NT machine.
-serv_restart() ->
- Exe="\\erts\\install_nt\\reboot.exe",
- open_port({spawn, Exe}, [stream, eof, in]),
- ok.
-
-
-%%-----------------------
-%% serv_nmake(Path, Options)
-%% Runs `nmake' in the given directory.
-%% Result: ok | error
-serv_nmake(Path, Options) ->
- {ok, Cwd}=file:get_cwd(),
- Command="nmake -e -f Makefile.win32 " ++ Options ++ " 2>&1",
- Res=run_make_bat(Path, Command),
- file:set_cwd(Cwd),
- Res.
-
-%%-----------------------
-%% serv_omake(Path, Options)
-%% Runs `omake' in the given directory.
-%% Result: ok | error
-serv_omake(Path, Options) ->
- {ok, Cwd}=file:get_cwd(),
- Command="omake -W -E -EN -f Makefile.win32 " ++ Options ++ " 2>&1",
- Res=run_make_bat(Path, Command),
- file:set_cwd(Cwd),
- Res.
-
-
-read_output(Port, SoFar) ->
-% io:format("(read_output)~n"),
- case get_data_from_port(Port) of
- eof ->
- io:format("*** eof ***~n"),
- io:format("Never reached a real message"),
- halt(1);
- {ok, Data} ->
- case print_line([SoFar|Data]) of
- {ok, Rest} ->
- read_output(Port, Rest);
- {done, Res} ->
- Res
- end
- end.
-
-print_line(Data) ->
- print_line(Data, []).
-
-print_line([], Acc) ->
- {ok, lists:reverse(Acc)};
-print_line([$*,$o,$k,$*|Rest], _Acc) ->
- io:format("*ok*~n"),
- {done, ok};
-print_line([$*,$e,$r,$r,$o,$r|Rest], _Acc) ->
- io:format("*error*~n"),
- {done, error};
-print_line([$\r,$\n|Rest], Acc) ->
- io:format("~s~n", [lists:reverse(Acc)]),
- print_line(Rest, []);
-print_line([Chr|Rest], Acc) ->
- print_line(Rest, [Chr|Acc]).
-
-get_data_from_port(Port) ->
- receive
- {Port, {data, Bytes}} ->
- {ok, Bytes};
- {Port, eof} ->
- unlink(Port),
- exit(Port, die),
- eof;
- Other ->
- io:format("Strange message received: ~p~n", [Other]),
- get_data_from_port(Port)
- end.
-
-
-run_make_bat(Dir, Make) ->
- {Name, Exe, Script}=create_make_script(Dir, Make),
- io:format("Exe:~p Cwd:~p Script:~p ~n",[Exe, Dir, Script]),
- case file:write_file(Name, Script) of
- ok ->
- case catch open_port({spawn, Exe}, [stderr_to_stdout, stream, hide,
- eof, in]) of
- Port when port(Port) ->
- read_output(Port, []);
- Other ->
- io:format("Error, open_port failed: ~p~n", [Other]),
- {open_port, Other, Exe}
- end;
- Error ->
- {write_file, Error, Name}
- end.
-
-create_make_script(Dir, Make) when atom(Make) ->
- create_make_script(Dir, atom_to_list(Make));
-create_make_script(Dir, Make) ->
- {"run_make_bs.bat",
- "run_make_bs 2>&1",
- ["@echo off\r\n",
- "@cd ", Dir, "\r\n",
- Make++"\r\n",
- "if errorlevel 1 echo *run_make_bs error*\r\n",
- "if not errorlevel 1 echo *ok*\r\n"]}.
-
-
-
-
-
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index c7daf923c5..80fc79f396 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index f704135ce8..b78747bc84 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 4adb3dedf2..b588b450c9 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index 09216fd9d8..45a409738c 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 7ac18352c4..6400cda2b5 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index 78481e2b00..ad49f5e892 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index cad777b272..411fc8d524 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 44dd264346..7a1f896d36 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index 145638802f..d5f5ba3c37 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -68,10 +68,10 @@ copy:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(STATIC_TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(STATIC_TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 0b4db3d9d0..5ee3d03fef 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -49,7 +49,7 @@
prim_read_file_info/2, prim_get_cwd/2]).
%% Used by escript and code
--export([set_primary_archive/3, release_archives/0]).
+-export([set_primary_archive/4, release_archives/0]).
-include_lib("kernel/include/file.hrl").
@@ -129,7 +129,7 @@ start(Id, Pgm0, Hosts) ->
{error,Reason}
end.
-%% Hosts must be a list on form ['1.2.3.4' ...]
+%% Hosts must be a list of form ['1.2.3.4' ...]
start_it("inet", Id, Pid, Hosts) ->
process_flag(trap_exit, true),
?dbg(inet, {Id,Pid,Hosts}),
@@ -222,15 +222,16 @@ get_cwd(Drive) ->
check_file_result(get_cwd, Drive, request({get_cwd,[Drive]})).
-spec set_primary_archive(File :: string() | 'undefined',
- ArchiveBin :: binary() | 'undefined',
- FileInfo :: #file_info{} | 'undefined')
+ ArchiveBin :: binary() | 'undefined',
+ FileInfo :: #file_info{} | 'undefined',
+ ParserFun :: fun())
-> {ok, [string()]} | {error,_}.
-set_primary_archive(undefined, undefined, undefined) ->
- request({set_primary_archive, undefined, undefined, undefined});
-set_primary_archive(File, ArchiveBin, FileInfo)
+set_primary_archive(undefined, undefined, undefined, ParserFun) ->
+ request({set_primary_archive, undefined, undefined, undefined, ParserFun});
+set_primary_archive(File, ArchiveBin, FileInfo, ParserFun)
when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
- request({set_primary_archive, File, ArchiveBin, FileInfo}).
+ request({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}).
-spec release_archives() -> 'ok' | {'error', _}.
@@ -318,8 +319,11 @@ loop(State, Parent, Paths) ->
{get_cwd,[_]=Args} ->
{Res,State1} = handle_get_cwd(State, Args),
{Res,State1,Paths};
- {set_primary_archive,File,Bin,FileInfo} ->
- {Res,State1} = handle_set_primary_archive(State, File, Bin, FileInfo),
+ {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} ->
+ {Res,State1} =
+ handle_set_primary_archive(State, File,
+ ArchiveBin, FileInfo,
+ ParserFun),
{Res,State1,Paths};
release_archives ->
{Res,State1} = handle_release_archives(State),
@@ -359,8 +363,8 @@ handle_get_file(State = #state{loader = efile}, Paths, File) ->
handle_get_file(State = #state{loader = inet}, Paths, File) ->
?SAFE2(inet_get_file_from_port(State, File, Paths), State).
-handle_set_primary_archive(State= #state{loader = efile}, File, Bin, FileInfo) ->
- ?SAFE2(efile_set_primary_archive(State, File, Bin, FileInfo), State).
+handle_set_primary_archive(State= #state{loader = efile}, File, ArchiveBin, FileInfo, ParserFun) ->
+ ?SAFE2(efile_set_primary_archive(State, File, ArchiveBin, FileInfo, ParserFun), State).
handle_release_archives(State= #state{loader = efile}) ->
?SAFE2(efile_release_archives(State), State).
@@ -484,8 +488,10 @@ efile_get_file_from_port3(State, File, [P | Paths]) ->
efile_get_file_from_port3(State, _File, []) ->
{{error,enoent},State}.
-efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin, FileInfo) ->
- {Res, PS2} = prim_set_primary_archive(PS, File, Bin, FileInfo),
+efile_set_primary_archive(#state{prim_state = PS} = State, File,
+ ArchiveBin, FileInfo, ParserFun) ->
+ {Res, PS2} = prim_set_primary_archive(PS, File, ArchiveBin,
+ FileInfo, ParserFun),
{Res,State#state{prim_state = PS2}}.
efile_release_archives(#state{prim_state = PS} = State) ->
@@ -729,7 +735,7 @@ udp_options() ->
%% INET version IPv4 addresses
%%
ll_tcp_connect(LocalPort, IP, RemotePort) ->
- case ll_open_set_bind(tcp, ?INET_FAMILY, tcp_options(),
+ case ll_open_set_bind(tcp, ?INET_FAMILY, stream, tcp_options(),
?INET_ADDRESS, LocalPort) of
{ok,S} ->
case prim_inet:connect(S, IP, RemotePort, tcp_timeout()) of
@@ -743,11 +749,11 @@ ll_tcp_connect(LocalPort, IP, RemotePort) ->
%% Open and initialize an udp port for broadcast
%%
ll_udp_open(P) ->
- ll_open_set_bind(udp, ?INET_FAMILY, udp_options(), ?INET_ADDRESS, P).
+ ll_open_set_bind(udp, ?INET_FAMILY, dgram, udp_options(), ?INET_ADDRESS, P).
-ll_open_set_bind(Protocol, Family, SOpts, IP, Port) ->
- case prim_inet:open(Protocol, Family) of
+ll_open_set_bind(Protocol, Family, Type, SOpts, IP, Port) ->
+ case prim_inet:open(Protocol, Family, Type) of
{ok, S} ->
case prim_inet:setopts(S, SOpts) of
ok ->
@@ -791,7 +797,7 @@ prim_release_archives(PS) ->
prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) ->
Res =
case DictVal of
- {primary, _PrimZip, _FI} ->
+ {primary, _PrimZip, _FI, _ParserFun} ->
ok; % Keep primary archive
{Cache, _FI} ->
debug(PS, {release, cache, ArchiveFile}),
@@ -809,7 +815,7 @@ prim_do_release_archives(PS, [], []) ->
prim_do_release_archives(PS, [], Errors) ->
{{error, Errors}, PS#prim_state{primary_archive = undefined}}.
-prim_set_primary_archive(PS, undefined, undefined, undefined) ->
+prim_set_primary_archive(PS, undefined, undefined, undefined, _ParserFun) ->
debug(PS, {set_primary_archive, clean}),
case PS#prim_state.primary_archive of
undefined ->
@@ -817,48 +823,40 @@ prim_set_primary_archive(PS, undefined, undefined, undefined) ->
debug(PS, {return, Res}),
{Res, PS};
ArchiveFile ->
- {primary, PrimZip, _FI} = erase(ArchiveFile),
+ {primary, PrimZip, _FI, _ParserFun2} = erase(ArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
Res = {ok, []},
debug(PS2, {return, Res}),
{Res, PS2}
end;
-prim_set_primary_archive(PS, ArchiveFile, ArchiveBin, #file_info{} = FileInfo)
- when is_list(ArchiveFile), is_binary(ArchiveBin) ->
+
+prim_set_primary_archive(PS, ArchiveFile0, ArchiveBin,
+ #file_info{} = FileInfo, ParserFun)
+ when is_list(ArchiveFile0), is_binary(ArchiveBin) ->
%% Try the archive file
- debug(PS, {set_primary_archive, ArchiveFile, byte_size(ArchiveBin)}),
+ debug(PS, {set_primary_archive, ArchiveFile0, byte_size(ArchiveBin)}),
+ ArchiveFile = real_path(absname(ArchiveFile0)),
{Res3, PS3} =
case PS#prim_state.primary_archive of
undefined ->
- Fun =
- fun({Funny, _GI, _GB}, A) ->
- case Funny of
- ["", "nibe", RevApp] -> % Reverse ebin
- %% Collect ebin directories in archive
- Ebin = reverse(RevApp) ++ "/ebin",
- {true, [Ebin | A]};
- _ ->
- {true, A}
- end
- end,
- Ebins0 = [ArchiveFile],
- case open_archive({ArchiveFile, ArchiveBin}, FileInfo, Ebins0, Fun) of
- {ok, PrimZip, {RevEbins, FI, _}} ->
- Ebins = reverse(RevEbins),
+ case load_prim_archive(ArchiveFile, ArchiveBin, FileInfo) of
+ {ok, PrimZip, FI, Ebins} ->
debug(PS, {set_primary_archive, Ebins}),
- put(ArchiveFile, {primary, PrimZip, FI}),
- {{ok, Ebins}, PS#prim_state{primary_archive = ArchiveFile}};
+ put(ArchiveFile, {primary, PrimZip, FI, ParserFun}),
+ {{ok, Ebins},
+ PS#prim_state{primary_archive = ArchiveFile}};
Error ->
debug(PS, {set_primary_archive, Error}),
{Error, PS}
end;
OldArchiveFile ->
debug(PS, {set_primary_archive, clean}),
- {primary, PrimZip, _FI} = erase(OldArchiveFile),
+ {primary, PrimZip, _FI, _ParserFun} = erase(OldArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
- prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, FileInfo)
+ prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin,
+ FileInfo, ParserFun)
end,
debug(PS3, {return, Res3}),
{Res3, PS3}.
@@ -873,11 +871,11 @@ prim_get_file(PS, File) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_get_file, ArchiveFile, FileInArchive}),
- FunnyFile = funny_split(FileInArchive, $/),
+ FileComponents = path_split(FileInArchive),
Fun =
- fun({Funny, _GetInfo, GetBin}, Acc) ->
+ fun({Components, _GetInfo, GetBin}, Acc) ->
if
- Funny =:= FunnyFile ->
+ Components =:= FileComponents ->
{false, {ok, GetBin()}};
true ->
{true, Acc}
@@ -900,11 +898,11 @@ prim_list_dir(PS, Dir) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_list_dir, ArchiveFile, FileInArchive}),
- FunnyDir = funny_split(FileInArchive, $/),
+ DirComponents = path_split(FileInArchive),
Fun =
- fun({Funny, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
- case Funny of
- [RevName | FD] when FD =:= FunnyDir ->
+ fun({Components, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
+ case Components of
+ [RevName | DC] when DC =:= DirComponents ->
case RevName of
"" ->
%% The listed directory
@@ -914,16 +912,16 @@ prim_list_dir(PS, Dir) ->
Name = reverse(RevName),
{true, {Status, [Name | Names]}}
end;
- ["", RevName | FD] when FD =:= FunnyDir ->
+ ["", RevName | DC] when DC =:= DirComponents ->
%% Directory
Name = reverse(RevName),
{true, {Status, [Name | Names]}};
- [RevName] when FunnyDir =:= [""] ->
- %% Top file
+ [RevName] when DirComponents =:= [""] ->
+ %% File in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
- ["", RevName] when FunnyDir =:= [""] ->
- %% Top file
+ ["", RevName] when DirComponents =:= [""] ->
+ %% Directory in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
_ ->
@@ -962,15 +960,14 @@ prim_read_file_info(PS, File) ->
end;
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_read_file_info, File}),
- FunnyFile = funny_split(FileInArchive, $/),
+ FileComponents = path_split(FileInArchive),
Fun =
- fun({Funny, GetInfo, _GetBin}, Acc) ->
- case Funny of
- [H | T] when H =:= "",
- T =:= FunnyFile ->
+ fun({Components, GetInfo, _GetBin}, Acc) ->
+ case Components of
+ ["" | F] when F =:= FileComponents ->
%% Directory
{false, {ok, GetInfo()}};
- F when F =:= FunnyFile ->
+ F when F =:= FileComponents ->
%% Plain file
{false, {ok, GetInfo()}};
_ ->
@@ -1011,7 +1008,7 @@ apply_archive(PS, Fun, Acc, Archive) ->
%% put(Archive, {Error, FI}),
{Error, PS}
end;
- {primary, PrimZip, FI} ->
+ {primary, PrimZip, FI, ParserFun} ->
case prim_file:read_file_info(Archive) of
{ok, FI2}
when FI#file_info.mtime =:= FI2#file_info.mtime ->
@@ -1022,6 +1019,16 @@ apply_archive(PS, Fun, Acc, Archive) ->
debug(PS, {primary, Error}),
{Error, PS}
end;
+ {ok, FI2} ->
+ ok = clear_cache(Archive, {ok, PrimZip}),
+ case load_prim_archive(Archive, FI2, ParserFun) of
+ {ok, PrimZip2, FI3, _Ebins} ->
+ debug(PS, {cache, {update, Archive}}),
+ put(Archive, {primary, PrimZip2, FI3, ParserFun});
+ Error2 ->
+ debug(PS, {cache, {clear, Error2}})
+ end,
+ apply_archive(PS, Fun, Acc, Archive);
Error ->
debug(PS, {cache, {clear, Error}}),
clear_cache(Archive, {ok, PrimZip}),
@@ -1063,50 +1070,69 @@ open_archive(Archive, Acc, Fun) ->
{error, Reason}
end.
+%% Open the given archive and iterate through all files with an own
+%% wrapper fun in order to identify each file as a component list as
+%% returned from path_split/1.
+%%
+%% In the archive (zip) file, directory elements might or might not be
+%% present. To ensure consistency, a directory element is added if it
+%% does not already exist (ensure_virtual_dirs/6). NOTE that there will
+%% be no such directory element for the top directory of the archive.
open_archive(Archive, FileInfo, Acc, Fun) ->
FakeFI = FileInfo#file_info{type = directory},
Wrapper =
- fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open
- Funny = funny_split(N, $/),
- FunnyDirs2 =
- case Funny of
- ["" | FunnyDir] ->
- [FunnyDir | FunnyDirs];
+ fun({N, GI, GB}, {A, I, Dirs}) ->
+ Components = path_split(N),
+ Dirs2 =
+ case Components of
+ ["" | Dir] ->
+ %% This is a directory
+ [Dir | Dirs];
_ ->
- FunnyDirs
+ %% This is a regular file
+ Dirs
end,
- {Includes, FunnyDirs3, A2} =
- ensure_virtual_dirs(Funny, Fun, FakeFI, [{true, Funny}], FunnyDirs2, A),
- {_Continue, A3} = Fun({Funny, GI, GB}, A2),
- {true, Includes, {A3, I, FunnyDirs3}}
+ {Includes, Dirs3, A2} =
+ ensure_virtual_dirs(Components, Fun, FakeFI,
+ [{true, Components}], Dirs2, A),
+ {_Continue, A3} = Fun({Components, GI, GB}, A2),
+ {true, Includes, {A3, I, Dirs3}}
end,
prim_zip:open(Wrapper, {Acc, FakeFI, []}, Archive).
-ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
- case Funny of
- [_ | FunnyDir] ->
- case lists:member(FunnyDir, FunnyDirs) of % BIF
+ensure_virtual_dirs(Components, Fun, FakeFI, Includes, Dirs, Acc) ->
+ case Components of
+ [_] ->
+ %% Don't add virtual dir for top directory
+ {Includes, Dirs, Acc};
+ [_ | Dir] ->
+ case lists:member(Dir, Dirs) of % BIF
false ->
+ %% The directory does not yet exist - add it
GetInfo = fun() -> FakeFI end,
GetBin = fun() -> <<>> end,
- VirtualDir = ["" | FunnyDir],
+ VirtualDir = ["" | Dir],
Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes],
- FunnyDirs2 = [FunnyDir | FunnyDirs],
- {I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc),
+ Dirs2 = [Dir | Dirs],
+
+ %% Recursively ensure dir elements on all levels
+ {I, F, Acc2} = ensure_virtual_dirs(Dir, Fun, FakeFI,
+ Includes2, Dirs2, Acc),
+
{_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
{I, F, Acc3};
true ->
- {reverse(Includes), FunnyDirs, Acc}
- end;
- [] ->
- {reverse(Includes), FunnyDirs, Acc}
+ %% The directory element does already exist
+ %% Recursivly ensure dir elements on all levels
+ ensure_virtual_dirs(Dir,Fun,FakeFI,Includes,Dirs,Acc)
+ end
end.
foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
- fun({Funny, GI, GB}, A) ->
+ fun({Components, GI, GB}, A) ->
%% Allow partial iteration at foldl
- {Continue, A2} = Fun({Funny, GI, GB}, A),
+ {Continue, A2} = Fun({Components, GI, GB}, A),
{Continue, true, A2}
end,
prim_zip:foldl(Wrapper, Acc, PrimZip).
@@ -1202,17 +1228,32 @@ reverse([A, B]) ->
reverse([A, B | L]) ->
lists:reverse(L, [B, A]). % BIF
-%% Returns all lists in reverse order
-funny_split(List, Sep) ->
- funny_split(List, Sep, [], []).
-
-funny_split([Sep | Tail], Sep, Path, Paths) ->
- funny_split(Tail, Sep, [], [Path | Paths]);
-funny_split([Head | Tail], Sep, Path, Paths) ->
- funny_split(Tail, Sep, [Head | Path], Paths);
-funny_split([], _Sep, Path, Paths) ->
+%% Returns a reversed list of path components, each component itself a
+%% reversed list (string), e.g.
+%% /path/to/file -> ["elif","ot","htap",""]
+%% /path/to/dir/ -> ["","rid","ot","htap",""]
+%% Note the "" marking leading and trailing / (slash).
+path_split(List) ->
+ path_split(List, [], []).
+
+path_split([$/ | Tail], Path, Paths) ->
+ path_split(Tail, [], [Path | Paths]);
+path_split([Head | Tail], Path, Paths) ->
+ path_split(Tail, [Head | Path], Paths);
+path_split([], Path, Paths) ->
[Path | Paths].
+%% The opposite of path_split/1
+path_join(Paths) ->
+ path_join(Paths,[]).
+
+path_join([""],Acc) ->
+ Acc;
+path_join([Path],Acc) ->
+ reverse(Path) ++ Acc;
+path_join([Path|Paths],Acc) ->
+ path_join(Paths,"/" ++ reverse(Path) ++ Acc).
+
name_split(ArchiveFile, File0) ->
File = absname(File0),
do_name_split(ArchiveFile, File).
@@ -1235,26 +1276,22 @@ do_name_split(undefined, File) ->
%% False match. Assume plain file
{file, File}
end;
-do_name_split(ArchiveFile0, File) ->
+do_name_split(ArchiveFile, File) ->
%% Look first in primary archive
- ArchiveFile = absname(ArchiveFile0),
- case string_match(File, ArchiveFile, []) of
+ case string_match(real_path(File), ArchiveFile, []) of
no_match ->
%% Archive or plain file
do_name_split(undefined, File);
{match, _RevPrimArchiveFile, FileInArchive} ->
%% Primary archive
- case FileInArchive of
- [$/ | FileInArchive2] ->
- {archive, ArchiveFile, FileInArchive2};
- _ ->
- {archive, ArchiveFile, FileInArchive}
- end
+ {archive, ArchiveFile, FileInArchive}
end.
string_match([Char | File], [Char | Archive], RevTop) ->
string_match(File, Archive, [Char | RevTop]);
-string_match(File, [], RevTop) ->
+string_match([] = File, [], RevTop) ->
+ {match, RevTop, File};
+string_match([$/ | File], [], RevTop) ->
{match, RevTop, File};
string_match(_File, _Archive, _RevTop) ->
no_match.
@@ -1314,14 +1351,14 @@ absname(Name) ->
case prim_file:get_cwd() of
{ok, Cwd} ->
Cwd ++ "/" ++ Name2;
- {error, _} ->
+ {error, _} ->
Name2
end;
volumerelative ->
case prim_file:get_cwd() of
{ok, Cwd} ->
absname_vr(Name2, Cwd);
- {error, _} ->
+ {error, _} ->
Name2
end
end.
@@ -1380,22 +1417,12 @@ win32_pathtype(Name) ->
win32_pathtype([Char | List++Rest]);
[$/, $/|_] ->
absolute;
- [$\\, $/|_] ->
- absolute;
- [$/, $\\|_] ->
- absolute;
- [$\\, $\\|_] ->
- absolute;
[$/|_] ->
volumerelative;
- [$\\|_] ->
- volumerelative;
[C1, C2, List | Rest] when is_list(List) ->
- pathtype([C1, C2|List ++ Rest]);
+ win32_pathtype([C1, C2|List ++ Rest]);
[_Letter, $:, $/|_] ->
absolute;
- [_Letter, $:, $\\|_] ->
- absolute;
[_Letter, $:|_] ->
volumerelative;
_ ->
@@ -1408,8 +1435,6 @@ vxworks_first(Name) ->
{not_device, [], []};
[$/ | T] ->
vxworks_first2(device, T, [$/]);
- [$\\ | T] ->
- vxworks_first2(device, T, [$/]);
[H | T] when is_list(H) ->
vxworks_first(H ++ T);
[H | T] ->
@@ -1422,8 +1447,6 @@ vxworks_first2(Devicep, Name, FirstComp) ->
{Devicep, [], FirstComp};
[$/ |T ] ->
{Devicep, [$/ | T], FirstComp};
- [$\\ | T] ->
- {Devicep, [$/ | T], FirstComp};
[$: | T]->
{device, T, [$: | FirstComp]};
[H | T] when is_list(H) ->
@@ -1445,3 +1468,70 @@ normalize(Name, Acc) ->
[] ->
reverse(Acc)
end.
+
+%% Remove .. and . from the path, e.g.
+%% /path/./to/this/../file -> /path/to/file
+%% This includes resolving symlinks.
+%%
+%% This is done to ensure that paths are totally normalized before
+%% comparing to find out if a file is inside the primary archive or
+%% not.
+real_path(Name) ->
+ real_path(Name,reverse(path_split(Name)),[],[]).
+
+real_path(_Name,[],Acc,_Links) ->
+ path_join(Acc);
+real_path(Name,["."|Paths],Acc,Links) ->
+ real_path(Name,Paths,Acc,Links);
+real_path(Name,[".."|Paths],[""]=Acc,Links) ->
+ %% /.. -> / (can't get higher than root)
+ real_path(Name,Paths,Acc,Links);
+real_path(Name,[".."|Paths],[Prev|Acc],Links) when Prev=/=".." ->
+ real_path(Name,Paths,Acc,Links);
+real_path(Name,[Path|Paths],Acc,Links) ->
+ This = [Path|Acc],
+ ThisFile = path_join(This),
+ case lists:member(ThisFile,Links) of
+ true -> % circular!!
+ Name;
+ false ->
+ case prim_file:read_link(ThisFile) of
+ {ok,Link} ->
+ case reverse(path_split(Link)) of
+ [""|_] = LinkPaths ->
+ real_path(Name,LinkPaths++Paths,[],[ThisFile|Links]);
+ LinkPaths ->
+ real_path(Name,LinkPaths++Paths,Acc,[ThisFile|Links])
+ end;
+ _ ->
+ real_path(Name,Paths,This,Links)
+ end
+ end.
+
+load_prim_archive(ArchiveFile, ArchiveBin, #file_info{}=FileInfo) ->
+ Fun = fun({Components, _GI, _GB}, A) ->
+ case Components of
+ ["", "nibe", RevApp] -> % Reverse ebin
+ %% Collect ebin directories in archive
+ Ebin = lists:reverse(RevApp, "/ebin"),
+ {true, [Ebin | A]};
+ _ ->
+ {true, A}
+ end
+ end,
+ Ebins0 = [ArchiveFile],
+ case open_archive({ArchiveFile, ArchiveBin}, FileInfo,
+ Ebins0, Fun) of
+ {ok, PrimZip, {RevEbins, FI, _}} ->
+ Ebins = reverse(RevEbins),
+ {ok, PrimZip, FI, Ebins};
+ Error ->
+ Error
+ end;
+load_prim_archive(ArchiveFile, FileInfo, ParserFun) ->
+ case ParserFun(ArchiveFile) of
+ {ok, ArchiveBin} ->
+ load_prim_archive(ArchiveFile, ArchiveBin, FileInfo);
+ Error ->
+ Error
+ end.
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index ff3633a3cc..1cbce5b80b 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,6 +40,11 @@
-export([flush_monitor_message/2]).
-export([set_cpu_topology/1, format_cpu_topology/1]).
-export([await_proc_exit/3]).
+-export([memory/0, memory/1]).
+-export([alloc_info/1, alloc_sizes/1]).
+
+-export([gather_sched_wall_time_result/1,
+ await_sched_wall_time_modifications/2]).
-deprecated([hash/2]).
@@ -800,3 +805,434 @@ min(A, _) -> A.
Maximum :: term().
max(A, B) when A < B -> B;
max(A, _) -> A.
+
+
+%%
+%% erlang:memory/[0,1]
+%%
+%% NOTE! When updating these functions, make sure to also update
+%% erts_memory() in $ERL_TOP/erts/emulator/beam/erl_alloc.c
+%%
+
+-type memory_type() :: 'total' | 'processes' | 'processes_used' | 'system' | 'atom' | 'atom_used' | 'binary' | 'code' | 'ets' | 'low' | 'maximum'.
+
+-define(CARRIER_ALLOCS, [mseg_alloc, sbmbc_alloc, sbmbc_low_alloc]).
+-define(LOW_ALLOCS, [sbmbc_low_alloc, ll_low_alloc, std_low_alloc]).
+-define(ALL_NEEDED_ALLOCS, (erlang:system_info(alloc_util_allocators)
+ -- ?CARRIER_ALLOCS)).
+
+-record(memory, {total = 0,
+ processes = 0,
+ processes_used = 0,
+ system = 0,
+ atom = 0,
+ atom_used = 0,
+ binary = 0,
+ code = 0,
+ ets = 0,
+ low = 0,
+ maximum = 0}).
+
+-spec memory() -> [{memory_type(), non_neg_integer()}].
+memory() ->
+ case aa_mem_data(au_mem_data(?ALL_NEEDED_ALLOCS)) of
+ notsup ->
+ erlang:error(notsup);
+ Mem ->
+ InstrTail = case Mem#memory.maximum of
+ 0 -> [];
+ _ -> [{maximum, Mem#memory.maximum}]
+ end,
+ Tail = case Mem#memory.low of
+ 0 -> InstrTail;
+ _ -> [{low, Mem#memory.low} | InstrTail]
+ end,
+ [{total, Mem#memory.total},
+ {processes, Mem#memory.processes},
+ {processes_used, Mem#memory.processes_used},
+ {system, Mem#memory.system},
+ {atom, Mem#memory.atom},
+ {atom_used, Mem#memory.atom_used},
+ {binary, Mem#memory.binary},
+ {code, Mem#memory.code},
+ {ets, Mem#memory.ets} | Tail]
+ end.
+
+-spec memory(memory_type()|[memory_type()]) -> non_neg_integer() | [{memory_type(), non_neg_integer()}].
+memory(Type) when is_atom(Type) ->
+ {AA, ALCU, ChkSup, BadArgZero} = need_mem_info(Type),
+ case get_mem_data(ChkSup, ALCU, AA) of
+ notsup ->
+ erlang:error(notsup, [Type]);
+ Mem ->
+ Value = get_memval(Type, Mem),
+ case {BadArgZero, Value} of
+ {true, 0} -> erlang:error(badarg, [Type]);
+ _ -> Value
+ end
+ end;
+memory(Types) when is_list(Types) ->
+ {AA, ALCU, ChkSup, BadArgZeroList} = need_mem_info_list(Types),
+ case get_mem_data(ChkSup, ALCU, AA) of
+ notsup ->
+ erlang:error(notsup, [Types]);
+ Mem ->
+ case memory_result_list(Types, BadArgZeroList, Mem) of
+ badarg -> erlang:error(badarg, [Types]);
+ Result -> Result
+ end
+ end.
+
+memory_result_list([], [], _Mem) ->
+ [];
+memory_result_list([T|Ts], [BAZ|BAZs], Mem) ->
+ case memory_result_list(Ts, BAZs, Mem) of
+ badarg -> badarg;
+ TVs ->
+ V = get_memval(T, Mem),
+ case {BAZ, V} of
+ {true, 0} -> badarg;
+ _ -> [{T, V}| TVs]
+ end
+ end.
+
+get_mem_data(true, AlcUAllocs, NeedAllocatedAreas) ->
+ case memory_is_supported() of
+ false -> notsup;
+ true -> get_mem_data(false, AlcUAllocs, NeedAllocatedAreas)
+ end;
+get_mem_data(false, AlcUAllocs, NeedAllocatedAreas) ->
+ AlcUMem = case AlcUAllocs of
+ [] -> #memory{};
+ _ ->
+ au_mem_data(AlcUAllocs)
+ end,
+ case NeedAllocatedAreas of
+ true -> aa_mem_data(AlcUMem);
+ false -> AlcUMem
+ end.
+
+need_mem_info_list([]) ->
+ {false, [], false, []};
+need_mem_info_list([T|Ts]) ->
+ {MAA, MALCU, MChkSup, MBadArgZero} = need_mem_info_list(Ts),
+ {AA, ALCU, ChkSup, BadArgZero} = need_mem_info(T),
+ {case AA of
+ true -> true;
+ _ -> MAA
+ end,
+ ALCU ++ (MALCU -- ALCU),
+ case ChkSup of
+ true -> true;
+ _ -> MChkSup
+ end,
+ [BadArgZero|MBadArgZero]}.
+
+need_mem_info(Type) when Type == total;
+ Type == system ->
+ {true, ?ALL_NEEDED_ALLOCS, false, false};
+need_mem_info(Type) when Type == processes;
+ Type == processes_used ->
+ {true, [eheap_alloc, fix_alloc], true, false};
+need_mem_info(Type) when Type == atom;
+ Type == atom_used;
+ Type == code ->
+ {true, [], true, false};
+need_mem_info(binary) ->
+ {false, [binary_alloc], true, false};
+need_mem_info(ets) ->
+ {true, [ets_alloc], true, false};
+need_mem_info(low) ->
+ LowAllocs = ?LOW_ALLOCS -- ?CARRIER_ALLOCS,
+ {_, _, FeatureList, _} = erlang:system_info(allocator),
+ AlcUAllocs = case LowAllocs -- FeatureList of
+ [] -> LowAllocs;
+ _ -> []
+ end,
+ {false, AlcUAllocs, true, true};
+need_mem_info(maximum) ->
+ {true, [], true, true};
+need_mem_info(_) ->
+ {false, [], false, true}.
+
+get_memval(total, #memory{total = V}) -> V;
+get_memval(processes, #memory{processes = V}) -> V;
+get_memval(processes_used, #memory{processes_used = V}) -> V;
+get_memval(system, #memory{system = V}) -> V;
+get_memval(atom, #memory{atom = V}) -> V;
+get_memval(atom_used, #memory{atom_used = V}) -> V;
+get_memval(binary, #memory{binary = V}) -> V;
+get_memval(code, #memory{code = V}) -> V;
+get_memval(ets, #memory{ets = V}) -> V;
+get_memval(low, #memory{low = V}) -> V;
+get_memval(maximum, #memory{maximum = V}) -> V;
+get_memval(_, #memory{}) -> 0.
+
+memory_is_supported() ->
+ {_, _, FeatureList, _} = erlang:system_info(allocator),
+ case ((erlang:system_info(alloc_util_allocators)
+ -- ?CARRIER_ALLOCS)
+ -- FeatureList) of
+ [] -> true;
+ _ -> false
+ end.
+
+get_blocks_size([{blocks_size, Sz, _, _} | Rest], Acc) ->
+ get_blocks_size(Rest, Acc+Sz);
+get_blocks_size([{_, _, _, _} | Rest], Acc) ->
+ get_blocks_size(Rest, Acc);
+get_blocks_size([], Acc) ->
+ Acc.
+
+blocks_size([{Carriers, SizeList} | Rest], Acc) when Carriers == mbcs;
+ Carriers == sbcs;
+ Carriers == sbmbcs ->
+ blocks_size(Rest, get_blocks_size(SizeList, Acc));
+blocks_size([_ | Rest], Acc) ->
+ blocks_size(Rest, Acc);
+blocks_size([], Acc) ->
+ Acc.
+
+get_fix_proc([{ProcType, A1, U1}| Rest], {A0, U0}) when ProcType == proc;
+ ProcType == monitor_sh;
+ ProcType == nlink_sh;
+ ProcType == msg_ref ->
+ get_fix_proc(Rest, {A0+A1, U0+U1});
+get_fix_proc([_|Rest], Acc) ->
+ get_fix_proc(Rest, Acc);
+get_fix_proc([], Acc) ->
+ Acc.
+
+fix_proc([{fix_types, SizeList} | _Rest], Acc) ->
+ get_fix_proc(SizeList, Acc);
+fix_proc([_ | Rest], Acc) ->
+ fix_proc(Rest, Acc);
+fix_proc([], Acc) ->
+ Acc.
+
+is_low_alloc(_A, []) ->
+ false;
+is_low_alloc(A, [A|_As]) ->
+ true;
+is_low_alloc(A, [_A|As]) ->
+ is_low_alloc(A, As).
+
+is_low_alloc(A) ->
+ is_low_alloc(A, ?LOW_ALLOCS).
+
+au_mem_data(notsup, _) ->
+ notsup;
+au_mem_data(_, [{_, false} | _]) ->
+ notsup;
+au_mem_data(#memory{total = Tot,
+ processes = Proc,
+ processes_used = ProcU} = Mem,
+ [{eheap_alloc, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ processes = Proc+Sz,
+ processes_used = ProcU+Sz},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ system = Sys,
+ ets = Ets} = Mem,
+ [{ets_alloc, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ system = Sys+Sz,
+ ets = Ets+Sz},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ system = Sys,
+ binary = Bin} = Mem,
+ [{binary_alloc, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ system = Sys+Sz,
+ binary = Bin+Sz},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ processes = Proc,
+ processes_used = ProcU,
+ system = Sys} = Mem,
+ [{fix_alloc, _, Data} | Rest]) ->
+ {A, U} = fix_proc(Data, {0, 0}),
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ processes = Proc+A,
+ processes_used = ProcU+U,
+ system = Sys+Sz-A},
+ Rest);
+au_mem_data(#memory{total = Tot,
+ system = Sys,
+ low = Low} = Mem,
+ [{A, _, Data} | Rest]) ->
+ Sz = blocks_size(Data, 0),
+ au_mem_data(Mem#memory{total = Tot+Sz,
+ system = Sys+Sz,
+ low = case is_low_alloc(A) of
+ true -> Low+Sz;
+ false -> Low
+ end},
+ Rest);
+au_mem_data(EMD, []) ->
+ EMD.
+
+au_mem_data(Allocs) ->
+ Ref = make_ref(),
+ erlang:system_info({allocator_sizes, Ref, Allocs}),
+ receive_emd(Ref).
+
+receive_emd(_Ref, EMD, 0) ->
+ EMD;
+receive_emd(Ref, EMD, N) ->
+ receive
+ {Ref, _, Data} ->
+ receive_emd(Ref, au_mem_data(EMD, Data), N-1)
+ end.
+
+receive_emd(Ref) ->
+ receive_emd(Ref, #memory{}, erlang:system_info(schedulers)).
+
+aa_mem_data(#memory{} = Mem,
+ [{maximum, Max} | Rest]) ->
+ aa_mem_data(Mem#memory{maximum = Max},
+ Rest);
+aa_mem_data(#memory{} = Mem,
+ [{total, Tot} | Rest]) ->
+ aa_mem_data(Mem#memory{total = Tot,
+ system = 0}, % system will be adjusted later
+ Rest);
+aa_mem_data(#memory{atom = Atom,
+ atom_used = AtomU} = Mem,
+ [{atom_space, Alloced, Used} | Rest]) ->
+ aa_mem_data(Mem#memory{atom = Atom+Alloced,
+ atom_used = AtomU+Used},
+ Rest);
+aa_mem_data(#memory{atom = Atom,
+ atom_used = AtomU} = Mem,
+ [{atom_table, Sz} | Rest]) ->
+ aa_mem_data(Mem#memory{atom = Atom+Sz,
+ atom_used = AtomU+Sz},
+ Rest);
+aa_mem_data(#memory{ets = Ets} = Mem,
+ [{ets_misc, Sz} | Rest]) ->
+ aa_mem_data(Mem#memory{ets = Ets+Sz},
+ Rest);
+aa_mem_data(#memory{processes = Proc,
+ processes_used = ProcU,
+ system = Sys} = Mem,
+ [{ProcData, Sz} | Rest]) when ProcData == bif_timer;
+ ProcData == link_lh;
+ ProcData == process_table ->
+ aa_mem_data(Mem#memory{processes = Proc+Sz,
+ processes_used = ProcU+Sz,
+ system = Sys-Sz},
+ Rest);
+aa_mem_data(#memory{code = Code} = Mem,
+ [{CodeData, Sz} | Rest]) when CodeData == module_table;
+ CodeData == export_table;
+ CodeData == export_list;
+ CodeData == fun_table;
+ CodeData == module_refs;
+ CodeData == loaded_code ->
+ aa_mem_data(Mem#memory{code = Code+Sz},
+ Rest);
+aa_mem_data(EMD, [{_, _} | Rest]) ->
+ aa_mem_data(EMD, Rest);
+aa_mem_data(#memory{total = Tot,
+ processes = Proc,
+ system = Sys} = Mem,
+ []) when Sys =< 0 ->
+ %% Instrumented runtime system -> Sys = Tot - Proc
+ Mem#memory{system = Tot - Proc};
+aa_mem_data(EMD, []) ->
+ EMD.
+
+aa_mem_data(notsup) ->
+ notsup;
+aa_mem_data(EMD) ->
+ aa_mem_data(EMD, erlang:system_info(allocated_areas)).
+
+%%
+%% alloc_info/1 and alloc_sizes/1 are for internal use only (used by
+%% erlang:system_info({allocator|allocator_sizes, _})).
+%%
+
+alloc_info(Allocs) ->
+ get_alloc_info(allocator, Allocs).
+
+alloc_sizes(Allocs) ->
+ get_alloc_info(allocator_sizes, Allocs).
+
+get_alloc_info(Type, AAtom) when is_atom(AAtom) ->
+ [{AAtom, Result}] = get_alloc_info(Type, [AAtom]),
+ Result;
+get_alloc_info(Type, AList) when is_list(AList) ->
+ Ref = make_ref(),
+ erlang:system_info({Type, Ref, AList}),
+ receive_allocator(Ref,
+ erlang:system_info(schedulers),
+ mk_res_list(AList)).
+
+mk_res_list([]) ->
+ [];
+mk_res_list([Alloc | Rest]) ->
+ [{Alloc, []} | mk_res_list(Rest)].
+
+insert_instance(I, N, []) ->
+ [{instance, N, I}];
+insert_instance(I, N, [{instance, M, _}|_] = Rest) when N < M ->
+ [{instance, N, I} | Rest];
+insert_instance(I, N, [Prev|Rest]) ->
+ [Prev | insert_instance(I, N, Rest)].
+
+insert_info([], Ys) ->
+ Ys;
+insert_info([{A, false}|Xs], [{A, _IList}|Ys]) ->
+ insert_info(Xs, [{A, false}|Ys]);
+insert_info([{A, N, I}|Xs], [{A, IList}|Ys]) ->
+ insert_info(Xs, [{A, insert_instance(I, N, IList)}|Ys]);
+insert_info([{A1, _}|_] = Xs, [{A2, _} = Y | Ys]) when A1 /= A2 ->
+ [Y | insert_info(Xs, Ys)];
+insert_info([{A1, _, _}|_] = Xs, [{A2, _} = Y | Ys]) when A1 /= A2 ->
+ [Y | insert_info(Xs, Ys)].
+
+receive_allocator(_Ref, 0, Acc) ->
+ Acc;
+receive_allocator(Ref, N, Acc) ->
+ receive
+ {Ref, _, InfoList} ->
+ receive_allocator(Ref, N-1, insert_info(InfoList, Acc))
+ end.
+
+-spec await_sched_wall_time_modifications(Ref, Result) -> boolean() when
+ Ref :: reference(),
+ Result :: boolean().
+
+await_sched_wall_time_modifications(Ref, Result) ->
+ sched_wall_time(Ref, erlang:system_info(schedulers)),
+ Result.
+
+-spec gather_sched_wall_time_result(Ref) -> [{pos_integer(),
+ non_neg_integer(),
+ non_neg_integer()}] when
+ Ref :: reference().
+
+gather_sched_wall_time_result(Ref) when is_reference(Ref) ->
+ sched_wall_time(Ref, erlang:system_info(schedulers), []).
+
+sched_wall_time(_Ref, 0) ->
+ ok;
+sched_wall_time(Ref, N) ->
+ receive Ref -> sched_wall_time(Ref, N-1) end.
+
+sched_wall_time(_Ref, 0, Acc) ->
+ Acc;
+sched_wall_time(Ref, N, undefined) ->
+ receive {Ref, _} -> sched_wall_time(Ref, N-1, undefined) end;
+sched_wall_time(Ref, N, Acc) ->
+ receive
+ {Ref, undefined} -> sched_wall_time(Ref, N-1, undefined);
+ {Ref, SWT} -> sched_wall_time(Ref, N-1, [SWT|Acc])
+ end.
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index c9c434dea0..185b62a899 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -635,8 +635,16 @@ do_unload([M|Mods]) ->
catch erlang:purge_module(M),
do_unload(Mods);
do_unload([]) ->
+ purge_all_hipe_refs(),
ok.
+purge_all_hipe_refs() ->
+ case erlang:system_info(hipe_architecture) of
+ undefined -> ok;
+ _ -> hipe_bifs:remove_refs_from(all)
+ end.
+
+
sub([H|T],L) -> sub(T,del(H,L));
sub([],L) -> L.
@@ -1252,7 +1260,11 @@ get_arguments([]) ->
[].
to_strings([H|T]) when is_atom(H) -> [atom_to_list(H)|to_strings(T)];
-to_strings([H|T]) when is_binary(H) -> [binary_to_list(H)|to_strings(T)];
+to_strings([H|T]) when is_binary(H) -> [try
+ unicode:characters_to_list(H,file:native_name_encoding())
+ catch
+ _:_ -> binary_to_list(H)
+ end|to_strings(T)];
to_strings([]) -> [].
get_argument(Arg,Flags) ->
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 30b7a5246a..0fc56c8c8e 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% Generic file contents operations
-export([open/2, close/1, datasync/1, sync/1, advise/4, position/2, truncate/1,
- write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3, copy/3]).
+ write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3,
+ copy/3, sendfile/10]).
%% Specialized file operations
-export([open/1, open/3]).
@@ -44,13 +45,13 @@
rename/2, rename/3,
make_dir/1, make_dir/2,
del_dir/1, del_dir/2,
- read_file_info/1, read_file_info/2,
+ read_file_info/1, read_file_info/2, read_file_info/3,
altname/1, altname/2,
- write_file_info/2, write_file_info/3,
+ write_file_info/2, write_file_info/3, write_file_info/4,
make_link/2, make_link/3,
make_symlink/2, make_symlink/3,
read_link/1, read_link/2,
- read_link_info/1, read_link_info/2,
+ read_link_info/1, read_link_info/2, read_link_info/3,
list_dir/1, list_dir/2]).
%% How to start and stop the ?DRV port.
-export([start/0, stop/1]).
@@ -98,6 +99,7 @@
-define(FILE_READ_LINE, 29).
-define(FILE_FDATASYNC, 30).
-define(FILE_ADVISE, 31).
+-define(FILE_SENDFILE, 32).
%% Driver responses
-define(FILE_RESP_OK, 0).
@@ -266,7 +268,7 @@ advise(#file_descriptor{module = ?MODULE, data = {Port, _}},
%% Returns {error, Reason} | ok.
write(#file_descriptor{module = ?MODULE, data = {Port, _}}, Bytes) ->
- case drv_command(Port, [?FILE_WRITE,Bytes]) of
+ case drv_command_nt(Port, [?FILE_WRITE,erlang:dt_prepend_vm_tag_data(Bytes)],undefined) of
{ok, _Size} ->
ok;
Error ->
@@ -281,8 +283,8 @@ pwrite(#file_descriptor{module = ?MODULE, data = {Port, _}}, L)
pwrite_int(_, [], 0, [], []) ->
ok;
pwrite_int(Port, [], N, Spec, Data) ->
- Header = list_to_binary([<<?FILE_PWRITEV, N:32>> | reverse(Spec)]),
- case drv_command_raw(Port, [Header | reverse(Data)]) of
+ Header = list_to_binary([?FILE_PWRITEV, erlang:dt_prepend_vm_tag_data(<<N:32>>) | reverse(Spec)]),
+ case drv_command_nt(Port, [Header | reverse(Data)], undefined) of
{ok, _Size} ->
ok;
Error ->
@@ -400,7 +402,7 @@ pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, L)
pread_int(_, [], 0, []) ->
{ok, []};
pread_int(Port, [], N, Spec) ->
- drv_command(Port, [<<?FILE_PREADV, 0:32, N:32>> | reverse(Spec)]);
+ drv_command_nt(Port, [?FILE_PREADV, erlang:dt_prepend_vm_tag_data(<<0:32, N:32>>) | reverse(Spec)],undefined);
pread_int(Port, [{Offs, Size} | T], N, Spec)
when is_integer(Offs), is_integer(Size), 0 =< Size ->
if
@@ -421,9 +423,9 @@ pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Size)
if
-(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE,
Size < ?LARGEFILESIZE ->
- case drv_command(Port,
- <<?FILE_PREADV, 0:32, 1:32,
- Offs:64/signed, Size:64>>) of
+ case drv_command_nt(Port,
+ [?FILE_PREADV, erlang:dt_prepend_vm_tag_data(<<0:32, 1:32,
+ Offs:64/signed, Size:64>>)], undefined) of
{ok, [eof]} ->
eof;
{ok, [Data]} ->
@@ -537,7 +539,31 @@ write_file(File, Bin) when (is_list(File) orelse is_binary(File)) ->
end;
write_file(_, _) ->
{error, badarg}.
-
+
+
+%% Returns {error, Reason} | {ok, BytesCopied}
+%sendfile(_,_,_,_,_,_,_,_,_,_) ->
+% {error, enotsup};
+sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}},
+ Dest, Offset, Bytes, _ChunkSize, Headers, Trailers,
+ _Nodiskio, _MNowait, _Sync) ->
+ case erlang:port_get_data(Dest) of
+ Data when Data == inet_tcp; Data == inet6_tcp ->
+ ok = inet:lock_socket(Dest,true),
+ {ok, DestFD} = prim_inet:getfd(Dest),
+ try drv_command(Port, [<<?FILE_SENDFILE, DestFD:32,
+ 0:8,
+ Offset:64/unsigned,
+ Bytes:64/unsigned,
+ (iolist_size(Headers)):32/unsigned,
+ (iolist_size(Trailers)):32/unsigned>>,
+ Headers,Trailers])
+ after
+ ok = inet:lock_socket(Dest,false)
+ end;
+ _Else ->
+ {error,badarg}
+ end.
%%%-----------------------------------------------------------------
@@ -699,16 +725,33 @@ del_dir_int(Port, Dir) ->
-%% read_file_info/{1,2}
+%% read_file_info/{1,2,3}
read_file_info(File) ->
- read_file_info_int({?DRV, [binary]}, File).
+ read_file_info_int({?DRV, [binary]}, File, local).
read_file_info(Port, File) when is_port(Port) ->
- read_file_info_int(Port, File).
+ read_file_info_int(Port, File, local);
+read_file_info(File, Opts) ->
+ read_file_info_int({?DRV, [binary]}, File, plgv(time, Opts, local)).
+
+read_file_info(Port, File, Opts) when is_port(Port) ->
+ read_file_info_int(Port, File, plgv(time, Opts, local)).
+
+read_file_info_int(Port, File, TimeType) ->
+ try
+ case drv_command(Port, [?FILE_FSTAT, pathname(File)]) of
+ {ok, FI} -> {ok, FI#file_info{
+ ctime = from_seconds(FI#file_info.ctime, TimeType),
+ mtime = from_seconds(FI#file_info.mtime, TimeType),
+ atime = from_seconds(FI#file_info.atime, TimeType)
+ }};
+ Error -> Error
+ end
+ catch
+ error:_ -> {error, badarg}
+ end.
-read_file_info_int(Port, File) ->
- drv_command(Port, [?FILE_FSTAT, pathname(File)]).
%% altname/{1,2}
@@ -721,38 +764,61 @@ altname(Port, File) when is_port(Port) ->
altname_int(Port, File) ->
drv_command(Port, [?FILE_ALTNAME, pathname(File)]).
-%% write_file_info/{2,3}
+%% write_file_info/{2,3,4}
write_file_info(File, Info) ->
- write_file_info_int({?DRV, [binary]}, File, Info).
+ write_file_info_int({?DRV, [binary]}, File, Info, local).
write_file_info(Port, File, Info) when is_port(Port) ->
- write_file_info_int(Port, File, Info).
+ write_file_info_int(Port, File, Info, local);
+write_file_info(File, Info, Opts) ->
+ write_file_info_int({?DRV, [binary]}, File, Info, plgv(time, Opts, local)).
+
+write_file_info(Port, File, Info, Opts) when is_port(Port) ->
+ write_file_info_int(Port, File, Info, plgv(time, Opts, local)).
-write_file_info_int(Port,
- File,
+write_file_info_int(Port, File,
#file_info{mode=Mode,
uid=Uid,
gid=Gid,
atime=Atime0,
mtime=Mtime0,
- ctime=Ctime}) ->
- {Atime, Mtime} =
- case {Atime0, Mtime0} of
- {undefined, Mtime0} -> {erlang:localtime(), Mtime0};
- {Atime0, undefined} -> {Atime0, Atime0};
- Complete -> Complete
- end,
- drv_command(Port, [?FILE_WRITE_INFO,
- int_to_bytes(Mode),
- int_to_bytes(Uid),
- int_to_bytes(Gid),
- date_to_bytes(Atime),
- date_to_bytes(Mtime),
- date_to_bytes(Ctime),
- pathname(File)]).
+ ctime=Ctime0},
+ TimeType) ->
+
+ % Atime and/or Mtime might be undefined
+ % - use localtime() for atime, if atime is undefined
+ % - use atime as mtime if mtime is undefined
+ % - use mtime as ctime if ctime is undefined
+
+ try
+ Atime = file_info_validate_atime(Atime0, TimeType),
+ Mtime = file_info_validate_mtime(Mtime0, Atime),
+ Ctime = file_info_validate_ctime(Ctime0, Mtime),
+
+ drv_command(Port, [?FILE_WRITE_INFO,
+ int_to_int32bytes(Mode),
+ int_to_int32bytes(Uid),
+ int_to_int32bytes(Gid),
+ int_to_int64bytes(to_seconds(Atime, TimeType)),
+ int_to_int64bytes(to_seconds(Mtime, TimeType)),
+ int_to_int64bytes(to_seconds(Ctime, TimeType)),
+ pathname(File)])
+ catch
+ error:_ -> {error, badarg}
+ end.
+file_info_validate_atime(Atime, _) when Atime =/= undefined -> Atime;
+file_info_validate_atime(undefined, local) -> erlang:localtime();
+file_info_validate_atime(undefined, universal) -> erlang:universaltime();
+file_info_validate_atime(undefined, posix) -> erlang:universaltime_to_posixtime(erlang:universaltime()).
+
+file_info_validate_mtime(undefined, Atime) -> Atime;
+file_info_validate_mtime(Mtime, _) -> Mtime.
+
+file_info_validate_ctime(undefined, Mtime) -> Mtime;
+file_info_validate_ctime(Ctime, _) -> Ctime.
%% make_link/{2,3}
@@ -796,15 +862,31 @@ read_link_int(Port, Link) ->
%% read_link_info/{2,3}
read_link_info(Link) ->
- read_link_info_int({?DRV, [binary]}, Link).
+ read_link_info_int({?DRV, [binary]}, Link, local).
read_link_info(Port, Link) when is_port(Port) ->
- read_link_info_int(Port, Link).
+ read_link_info_int(Port, Link, local);
+
+read_link_info(Link, Opts) ->
+ read_link_info_int({?DRV, [binary]}, Link, plgv(time, Opts, local)).
-read_link_info_int(Port, Link) ->
- drv_command(Port, [?FILE_LSTAT, pathname(Link)]).
+read_link_info(Port, Link, Opts) when is_port(Port) ->
+ read_link_info_int(Port, Link, plgv(time, Opts, local)).
+read_link_info_int(Port, Link, TimeType) ->
+ try
+ case drv_command(Port, [?FILE_LSTAT, pathname(Link)]) of
+ {ok, FI} -> {ok, FI#file_info{
+ ctime = from_seconds(FI#file_info.ctime, TimeType),
+ mtime = from_seconds(FI#file_info.mtime, TimeType),
+ atime = from_seconds(FI#file_info.atime, TimeType)
+ }};
+ Error -> Error
+ end
+ catch
+ error:_ -> {error, badarg}
+ end.
%% list_dir/{1,2}
@@ -841,12 +923,17 @@ drv_open(Driver, Portopts) ->
%% Closes a port in a safe way. Returns ok.
drv_close(Port) ->
- try erlang:port_close(Port) catch error:_ -> ok end,
- receive %% Ugly workaround in case the caller==owner traps exits
- {'EXIT', Port, _Reason} ->
- ok
- after 0 ->
- ok
+ Save = erlang:dt_spread_tag(false),
+ try
+ try erlang:port_close(Port) catch error:_ -> ok end,
+ receive %% Ugly workaround in case the caller==owner traps exits
+ {'EXIT', Port, _Reason} ->
+ ok
+ after 0 ->
+ ok
+ end
+ after
+ erlang:dt_restore_tag(Save)
end.
@@ -856,9 +943,6 @@ drv_close(Port) ->
%% then closed after the result has been received.
%% Returns {ok, Result} or {error, Reason}.
-drv_command_raw(Port, Command) ->
- drv_command(Port, Command, false, undefined).
-
drv_command(Port, Command) ->
drv_command(Port, Command, undefined).
@@ -874,7 +958,8 @@ drv_command(Port, Command, R) ->
end.
drv_command(Port, Command, Validated, R) when is_port(Port) ->
- try erlang:port_command(Port, Command) of
+ Save = erlang:dt_spread_tag(false),
+ try erlang:port_command(Port, erlang:dt_append_vm_tag_data(Command)) of
true ->
drv_get_response(Port, R)
catch
@@ -893,6 +978,8 @@ drv_command(Port, Command, Validated, R) when is_port(Port) ->
end;
error:Reason ->
{error, Reason}
+ after
+ erlang:dt_restore_tag(Save)
end;
drv_command({Driver, Portopts}, Command, Validated, R) ->
case drv_open(Driver, Portopts) of
@@ -903,6 +990,25 @@ drv_command({Driver, Portopts}, Command, Validated, R) ->
Error ->
Error
end.
+drv_command_nt(Port, Command, R) when is_port(Port) ->
+ Save = erlang:dt_spread_tag(false),
+ try erlang:port_command(Port, Command) of
+ true ->
+ drv_get_response(Port, R)
+ catch
+ error:badarg ->
+ try erlang:iolist_size(Command) of
+ _ -> % Valid
+ {error, einval}
+ catch
+ error:_ ->
+ {error, badarg}
+ end;
+ error:Reason ->
+ {error, Reason}
+ after
+ erlang:dt_restore_tag(Save)
+ end.
@@ -1049,7 +1155,7 @@ translate_response(?FILE_RESP_DATA, List) ->
{_N, _Data} = ND = get_uint64(List),
{ok, ND};
translate_response(?FILE_RESP_INFO, List) when is_list(List) ->
- {ok, transform_info_ints(get_uint32s(List))};
+ {ok, transform_info(List)};
translate_response(?FILE_RESP_NUMERR, L0) ->
{N, L1} = get_uint64(L0),
{error, {N, list_to_atom(L1)}};
@@ -1103,27 +1209,37 @@ translate_response(?FILE_RESP_ALL_DATA, Data) ->
translate_response(X, Data) ->
{error, {bad_response_from_port, [X | Data]}}.
-transform_info_ints(Ints) ->
- [HighSize, LowSize, Type|Tail0] = Ints,
- Size = HighSize * 16#100000000 + LowSize,
- [Ay, Am, Ad, Ah, Ami, As|Tail1] = Tail0,
- [My, Mm, Md, Mh, Mmi, Ms|Tail2] = Tail1,
- [Cy, Cm, Cd, Ch, Cmi, Cs|Tail3] = Tail2,
- [Mode, Links, Major, Minor, Inode, Uid, Gid, Access] = Tail3,
+transform_info([
+ Hsize1, Hsize2, Hsize3, Hsize4,
+ Lsize1, Lsize2, Lsize3, Lsize4,
+ Type1, Type2, Type3, Type4,
+ Atime1, Atime2, Atime3, Atime4, Atime5, Atime6, Atime7, Atime8,
+ Mtime1, Mtime2, Mtime3, Mtime4, Mtime5, Mtime6, Mtime7, Mtime8,
+ Ctime1, Ctime2, Ctime3, Ctime4, Ctime5, Ctime6, Ctime7, Ctime8,
+ Mode1, Mode2, Mode3, Mode4,
+ Links1, Links2, Links3, Links4,
+ Major1, Major2, Major3, Major4,
+ Minor1, Minor2, Minor3, Minor4,
+ Inode1, Inode2, Inode3, Inode4,
+ Uid1, Uid2, Uid3, Uid4,
+ Gid1, Gid2, Gid3, Gid4,
+ Access1,Access2,Access3,Access4]) ->
#file_info {
- size = Size,
- type = file_type(Type),
- access = file_access(Access),
- atime = {{Ay, Am, Ad}, {Ah, Ami, As}},
- mtime = {{My, Mm, Md}, {Mh, Mmi, Ms}},
- ctime = {{Cy, Cm, Cd}, {Ch, Cmi, Cs}},
- mode = Mode,
- links = Links,
- major_device = Major,
- minor_device = Minor,
- inode = Inode,
- uid = Uid,
- gid = Gid}.
+ size = uint32(Hsize1,Hsize2,Hsize3,Hsize4)*16#100000000 + uint32(Lsize1,Lsize2,Lsize3,Lsize4),
+ type = file_type(uint32(Type1,Type2,Type3,Type4)),
+ access = file_access(uint32(Access1,Access2,Access3,Access4)),
+ atime = sint64(Atime1, Atime2, Atime3, Atime4, Atime5, Atime6, Atime7, Atime8),
+ mtime = sint64(Mtime1, Mtime2, Mtime3, Mtime4, Mtime5, Mtime6, Mtime7, Mtime8),
+ ctime = sint64(Ctime1, Ctime2, Ctime3, Ctime4, Ctime5, Ctime6, Ctime7, Ctime8),
+ mode = uint32(Mode1,Mode2,Mode3,Mode4),
+ links = uint32(Links1,Links2,Links3,Links4),
+ major_device = uint32(Major1,Major2,Major3,Major4),
+ minor_device = uint32(Minor1,Minor2,Minor3,Minor4),
+ inode = uint32(Inode1,Inode2,Inode3,Inode4),
+ uid = uint32(Uid1,Uid2,Uid3,Uid4),
+ gid = uint32(Gid1,Gid2,Gid3,Gid4)
+ }.
+
file_type(1) -> device;
file_type(2) -> directory;
@@ -1136,24 +1252,22 @@ file_access(1) -> write;
file_access(2) -> read;
file_access(3) -> read_write.
-int_to_bytes(Int) when is_integer(Int) ->
+int_to_int32bytes(Int) when is_integer(Int) ->
<<Int:32>>;
-int_to_bytes(undefined) ->
+int_to_int32bytes(undefined) ->
<<-1:32>>.
-date_to_bytes(undefined) ->
- <<-1:32, -1:32, -1:32, -1:32, -1:32, -1:32>>;
-date_to_bytes({{Y, Mon, D}, {H, Min, S}}) ->
- <<Y:32, Mon:32, D:32, H:32, Min:32, S:32>>.
+int_to_int64bytes(Int) when is_integer(Int) ->
+ <<Int:64/signed>>.
-%% uint64([[X1, X2, X3, X4] = Y1 | [X5, X6, X7, X8] = Y2]) ->
-%% (uint32(Y1) bsl 32) bor uint32(Y2).
-%% uint64(X1, X2, X3, X4, X5, X6, X7, X8) ->
-%% (uint32(X1, X2, X3, X4) bsl 32) bor uint32(X5, X6, X7, X8).
+sint64(I1,I2,I3,I4,I5,I6,I7,I8) when I1 > 127 ->
+ ((I1 bsl 56) bor (I2 bsl 48) bor (I3 bsl 40) bor (I4 bsl 32) bor
+ (I5 bsl 24) bor (I6 bsl 16) bor (I7 bsl 8) bor I8) - (1 bsl 64);
+sint64(I1,I2,I3,I4,I5,I6,I7,I8) ->
+ ((I1 bsl 56) bor (I2 bsl 48) bor (I3 bsl 40) bor (I4 bsl 32) bor
+ (I5 bsl 24) bor (I6 bsl 16) bor (I7 bsl 8) bor I8).
-%% uint32([X1,X2,X3,X4]) ->
-%% (X1 bsl 24) bor (X2 bsl 16) bor (X3 bsl 8) bor X4.
uint32(X1,X2,X3,X4) ->
(X1 bsl 24) bor (X2 bsl 16) bor (X3 bsl 8) bor X4.
@@ -1166,11 +1280,6 @@ get_uint64(L0) ->
get_uint32([X1,X2,X3,X4|List]) ->
{(((((X1 bsl 8) bor X2) bsl 8) bor X3) bsl 8) bor X4, List}.
-get_uint32s([X1,X2,X3,X4|Tail]) ->
- [uint32(X1,X2,X3,X4) | get_uint32s(Tail)];
-get_uint32s([]) -> [].
-
-
%% Binary mode
transform_ldata(<<0:32, 0:32>>) ->
@@ -1249,3 +1358,28 @@ reverse(L, T) -> lists:reverse(L, T).
% in list_to_binary, which is caught and generates the {error,badarg} return
pathname(File) ->
(catch prim_file:internal_name2native(File)).
+
+
+%% proplist:get_value/3
+plgv(K, [{K, V}|_], _) -> V;
+plgv(K, [_|KVs], D) -> plgv(K, KVs, D);
+plgv(_, [], D) -> D.
+
+%%
+%% We don't actually want this here
+%% We want to use posix time in all prim but erl_prim_loader makes that tricky
+%% It is probably needed to redo the whole erl_prim_loader
+
+from_seconds(Seconds, posix) when is_integer(Seconds) ->
+ Seconds;
+from_seconds(Seconds, universal) when is_integer(Seconds) ->
+ erlang:posixtime_to_universaltime(Seconds);
+from_seconds(Seconds, local) when is_integer(Seconds) ->
+ erlang:universaltime_to_localtime(erlang:posixtime_to_universaltime(Seconds)).
+
+to_seconds(Seconds, posix) when is_integer(Seconds) ->
+ Seconds;
+to_seconds({_,_} = Datetime, universal) ->
+ erlang:universaltime_to_posixtime(Datetime);
+to_seconds({_,_} = Datetime, local) ->
+ erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(Datetime)).
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 8f2e845b4f..91fcd3ac82 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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 @@
%% Primitive inet_drv interface
--export([open/1, open/2, fdopen/2, fdopen/3, close/1]).
--export([bind/3, listen/1, listen/2]).
+-export([open/3, fdopen/4, close/1]).
+-export([bind/3, listen/1, listen/2, peeloff/2]).
-export([connect/3, connect/4, async_connect/4]).
-export([accept/1, accept/2, async_accept/2]).
-export([shutdown/2]).
@@ -36,7 +36,8 @@
-export([recvfrom/2, recvfrom/3]).
-export([setopt/3, setopts/2, getopt/2, getopts/2, is_sockopt_val/2]).
-export([chgopt/3, chgopts/2]).
--export([getstat/2, getfd/1, getindex/1, getstatus/1, gettype/1,
+-export([getstat/2, getfd/1, ignorefd/2,
+ getindex/1, getstatus/1, gettype/1,
getifaddrs/1, getiflist/1, ifget/3, ifset/3,
gethostname/1]).
-export([getservbyname/3, getservbyport/3]).
@@ -56,58 +57,48 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-%% OPEN(tcp | udp | sctp, inet | inet6) ->
+%% OPEN(tcp | udp | sctp, inet | inet6, stream | dgram | seqpacket) ->
%% {ok, insock()} |
%% {error, Reason}
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-open(Protocol) -> open1(Protocol, ?INET_AF_INET).
+open(Protocol, Family, Type) ->
+ open(Protocol, Family, Type, ?INET_REQ_OPEN, []).
-open(Protocol, inet) -> open1(Protocol, ?INET_AF_INET);
-open(Protocol, inet6) -> open1(Protocol, ?INET_AF_INET6);
-open(_, _) -> {error, einval}.
+fdopen(Protocol, Family, Type, Fd) when is_integer(Fd) ->
+ open(Protocol, Family, Type, ?INET_REQ_FDOPEN, ?int32(Fd)).
-fdopen(Protocol, Fd) -> fdopen1(Protocol, ?INET_AF_INET, Fd).
-
-fdopen(Protocol, Fd, inet) -> fdopen1(Protocol, ?INET_AF_INET, Fd);
-fdopen(Protocol, Fd, inet6) -> fdopen1(Protocol, ?INET_AF_INET6, Fd);
-fdopen(_, _, _) -> {error, einval}.
-
-open1(Protocol, Family) ->
- case open0(Protocol) of
- {ok, S} ->
- case ctl_cmd(S, ?INET_REQ_OPEN, [Family]) of
- {ok, _} ->
- {ok,S};
- Error ->
- close(S), Error
- end;
- Error -> Error
+open(Protocol, Family, Type, Req, Data) ->
+ Drv = protocol2drv(Protocol),
+ AF = enc_family(Family),
+ T = enc_type(Type),
+ try erlang:open_port({spawn_driver,Drv}, [binary]) of
+ S ->
+ case ctl_cmd(S, Req, [AF,T,Data]) of
+ {ok,_} -> {ok,S};
+ {error,_}=Error ->
+ close(S),
+ Error
+ end
+ catch
+ %% The only (?) way to get here is to try to open
+ %% the sctp driver when it does not exist (badarg)
+ error:badarg -> {error, eprotonosupport};
+ %% system_limit if out of port slots
+ error:system_limit -> {error, system_limit}
end.
-fdopen1(Protocol, Family, Fd) when is_integer(Fd) ->
- case open0(Protocol) of
- {ok, S} ->
- case ctl_cmd(S,?INET_REQ_FDOPEN,[Family,?int32(Fd)]) of
- {ok, _} -> {ok,S};
- Error -> close(S), Error
- end;
- Error -> Error
- end.
+enc_family(inet) -> ?INET_AF_INET;
+enc_family(inet6) -> ?INET_AF_INET6.
-open0(Protocol) ->
- try erlang:open_port({spawn_driver,protocol2drv(Protocol)}, [binary]) of
- Port -> {ok,Port}
- catch
- error:Reason -> {error,Reason}
- end.
+enc_type(stream) -> ?INET_TYPE_STREAM;
+enc_type(dgram) -> ?INET_TYPE_DGRAM;
+enc_type(seqpacket) -> ?INET_TYPE_SEQPACKET.
protocol2drv(tcp) -> "tcp_inet";
protocol2drv(udp) -> "udp_inet";
-protocol2drv(sctp) -> "sctp_inet";
-protocol2drv(_) ->
- erlang:error(eprotonosupport).
+protocol2drv(sctp) -> "sctp_inet".
drv2protocol("tcp_inet") -> tcp;
drv2protocol("udp_inet") -> udp;
@@ -139,7 +130,7 @@ shutdown_1(S, How) ->
shutdown_2(S, How) ->
case ctl_cmd(S, ?TCP_REQ_SHUTDOWN, [How]) of
{ok, []} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
shutdown_pend_loop(S, N0) ->
@@ -193,9 +184,9 @@ close_pend_loop(S, N) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bind(S,IP,Port) when is_port(S), is_integer(Port), Port >= 0, Port =< 65535 ->
- case ctl_cmd(S,?INET_REQ_BIND,[?int16(Port),ip_to_bytes(IP)]) of
+ case ctl_cmd(S,?INET_REQ_BIND,enc_value(set, addr, {IP,Port})) of
{ok, [P1,P0]} -> {ok, ?u16(P1, P0)};
- Error -> Error
+ {error,_}=Error -> Error
end;
%% Multi-homed "bind": sctp_bindx(). The Op is 'add' or 'remove'.
@@ -215,14 +206,14 @@ bindx(S, AddFlag, Addrs) ->
case getprotocol(S) of
sctp ->
%% Really multi-homed "bindx". Stringified args:
- %% [AddFlag, (Port, IP)+]:
+ %% [AddFlag, (AddrBytes see enc_value_2(addr,X))+]:
Args =
[?int8(AddFlag)|
- [[?int16(Port)|ip_to_bytes(IP)] ||
+ [enc_value(set, addr, {IP,Port}) ||
{IP, Port} <- Addrs]],
case ctl_cmd(S, ?SCTP_REQ_BINDX, Args) of
{ok,_} -> {ok, S};
- Error -> Error
+ {error,_}=Error -> Error
end;
_ -> {error, einval}
end.
@@ -265,7 +256,7 @@ async_connect(S, IP, Port, Time) ->
case ctl_cmd(S, ?INET_REQ_CONNECT,
[enc_time(Time),?int16(Port),ip_to_bytes(IP)]) of
{ok, [R1,R0]} -> {ok, S, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -318,9 +309,9 @@ accept_opts(L, S) ->
end.
async_accept(L, Time) ->
- case ctl_cmd(L,?TCP_REQ_ACCEPT, [enc_time(Time)]) of
+ case ctl_cmd(L,?INET_REQ_ACCEPT, [enc_time(Time)]) of
{ok, [R1,R0]} -> {ok, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -334,16 +325,30 @@ async_accept(L, Time) ->
%% listening) is also accepted:
listen(S) -> listen(S, ?LISTEN_BACKLOG).
-
+
+listen(S, true) -> listen(S, ?LISTEN_BACKLOG);
+listen(S, false) -> listen(S, 0);
listen(S, BackLog) when is_port(S), is_integer(BackLog) ->
- case ctl_cmd(S, ?TCP_REQ_LISTEN, [?int16(BackLog)]) of
+ case ctl_cmd(S, ?INET_REQ_LISTEN, [?int16(BackLog)]) of
{ok, _} -> ok;
- Error -> Error
- end;
-listen(S, Flag) when is_port(S), is_boolean(Flag) ->
- case ctl_cmd(S, ?SCTP_REQ_LISTEN, enc_value(set, bool8, Flag)) of
- {ok,_} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% PEELOFF(insock(), AssocId) -> {ok,outsock()} | {error, Reason}
+%%
+%% SCTP: Peel off one association into a type stream socket
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+peeloff(S, AssocId) ->
+ case ctl_cmd(S, ?SCTP_REQ_PEELOFF, [?int32(AssocId)]) of
+ inet_reply ->
+ receive
+ {inet_reply,S,Res} -> Res
+ end;
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -395,12 +400,12 @@ sendto(S, IP, Port, Data) when is_port(S), Port >= 0, Port =< 65535 ->
true ->
receive
{inet_reply,S,Reply} ->
- ?DBG_FORMAT("prim_inet:send() -> ~p~n", [Reply]),
+ ?DBG_FORMAT("prim_inet:sendto() -> ~p~n", [Reply]),
Reply
end
catch
error:_ ->
- ?DBG_FORMAT("prim_inet:send() -> {error,einval}~n", []),
+ ?DBG_FORMAT("prim_inet:sendto() -> {error,einval}~n", []),
{error,einval}
end.
@@ -455,7 +460,7 @@ recv0(S, Length, Time) when is_port(S), is_integer(Length), Length >= 0 ->
async_recv(S, Length, Time) ->
case ctl_cmd(S, ?TCP_REQ_RECV, [enc_time(Time), ?int32(Length)]) of
{ok,[R1,R0]} -> {ok, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -501,7 +506,7 @@ recvfrom0(S, Length, Time)
{inet_async, S, Ref, Error={error, _}} ->
Error
end;
- Error ->
+ {error,_}=Error ->
Error % Front-end error
end;
recvfrom0(_, _, _) -> {error,einval}.
@@ -517,18 +522,18 @@ peername(S) when is_port(S) ->
{ok, [F, P1,P0 | Addr]} ->
{IP, _} = get_ip(F, Addr),
{ok, { IP, ?u16(P1, P0) }};
- Error -> Error
+ {error,_}=Error -> Error
end.
setpeername(S, {IP,Port}) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETPEER, [?int16(Port),ip_to_bytes(IP)]) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
setpeername(S, undefined) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETPEER, []) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -542,18 +547,18 @@ sockname(S) when is_port(S) ->
{ok, [F, P1, P0 | Addr]} ->
{IP, _} = get_ip(F, Addr),
{ok, { IP, ?u16(P1, P0) }};
- Error -> Error
+ {error,_}=Error -> Error
end.
setsockname(S, {IP,Port}) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETNAME, [?int16(Port),ip_to_bytes(IP)]) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
setsockname(S, undefined) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETNAME, []) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -573,7 +578,7 @@ setopts(S, Opts) when is_port(S) ->
{ok, Buf} ->
case ctl_cmd(S, ?INET_REQ_SETOPTS, Buf) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -599,12 +604,12 @@ getopts(S, Opts) when is_port(S), is_list(Opts) ->
{ok,Rep} ->
%% Non-SCTP: "Rep" contains the encoded option vals:
decode_opt_val(Rep);
- {error,sctp_reply} ->
+ inet_reply ->
%% SCTP: Need to receive the full value:
receive
{inet_reply,S,Res} -> Res
end;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -733,7 +738,7 @@ getifaddrs_ifget(S, IFs, IF, FlagsVals, Opts) ->
getiflist(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETIFLIST, []) of
{ok, Data} -> {ok, build_iflist(Data)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -751,7 +756,7 @@ ifget(S, Name, Opts) ->
{ok, Buf2} ->
case ctl_cmd(S, ?INET_REQ_IFGET, [Buf1,Buf2]) of
{ok, Data} -> decode_ifopts(Data,[]);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end;
@@ -773,7 +778,7 @@ ifset(S, Name, Opts) ->
{ok, Buf2} ->
case ctl_cmd(S, ?INET_REQ_IFSET, [Buf1,Buf2]) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end;
@@ -801,7 +806,7 @@ subscribe(S, Sub) when is_port(S), is_list(Sub) ->
{ok, Bytes} ->
case ctl_cmd(S, ?INET_REQ_SUBSCRIBE, Bytes) of
{ok, Data} -> decode_subs(Data);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -819,7 +824,7 @@ getstat(S, Stats) when is_port(S), is_list(Stats) ->
{ok, Bytes} ->
case ctl_cmd(S, ?INET_REQ_GETSTAT, Bytes) of
{ok, Data} -> decode_stats(Data);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -835,11 +840,26 @@ getstat(S, Stats) when is_port(S), is_list(Stats) ->
getfd(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETFD, []) of
{ok, [S3,S2,S1,S0]} -> {ok, ?u32(S3,S2,S1,S0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
+%% IGNOREFD(insock(),boolean()) -> {ok,integer()} | {error, Reason}
+%%
+%% steal internal file descriptor
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ignorefd(S,Bool) when is_port(S) ->
+ Val = if Bool -> 1; true -> 0 end,
+ case ctl_cmd(S, ?INET_REQ_IGNOREFD, [Val]) of
+ {ok, _} -> ok;
+ Error -> Error
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
%% GETIX(insock()) -> {ok,integer()} | {error, Reason}
%%
%% get internal socket index
@@ -873,7 +893,7 @@ gettype(S) when is_port(S) ->
_ -> undefined
end,
{ok, {Family, Type}};
- Error -> Error
+ {error,_}=Error -> Error
end.
getprotocol(S) when is_port(S) ->
@@ -901,7 +921,7 @@ getstatus(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETSTATUS, []) of
{ok, [S3,S2,S1,S0]} ->
{ok, dec_status(?u32(S3,S2,S1,S0))};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -943,7 +963,7 @@ getservbyname1(S,Name,Proto) ->
case ctl_cmd(S, ?INET_REQ_GETSERVBYNAME, [L1,Name,L2,Proto]) of
{ok, [P1,P0]} ->
{ok, ?u16(P1,P0)};
- Error ->
+ {error,_}=Error ->
Error
end
end.
@@ -971,7 +991,7 @@ getservbyport1(S,Port,Proto) ->
true ->
case ctl_cmd(S, ?INET_REQ_GETSERVBYPORT, [?int16(Port),L,Proto]) of
{ok, Name} -> {ok, Name};
- Error -> Error
+ {error,_}=Error -> Error
end
end.
@@ -985,7 +1005,7 @@ getservbyport1(S,Port,Proto) ->
unrecv(S, Data) ->
case ctl_cmd(S, ?TCP_REQ_UNRECV, Data) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2163,7 +2183,7 @@ ctl_cmd(Port, Cmd, Args) ->
Result =
try erlang:port_control(Port, Cmd, Args) of
[?INET_REP_OK|Reply] -> {ok,Reply};
- [?INET_REP_SCTP] -> {error,sctp_reply};
+ [?INET_REP] -> inet_reply;
[?INET_REP_ERROR|Err] -> {error,list_to_atom(Err)}
catch
error:_ -> {error,einval}
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index 392a9feb45..d29f17ae56 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -432,7 +432,7 @@ binary_io({file_info, B}, _) ->
is_binary(B) -> {regular, byte_size(B)};
B =:= directory -> {directory, 0}
end,
- Now = calendar:local_time(),
+ Now = erlang:localtime(),
#file_info{size = Size, type = Type, access = read_write,
atime = Now, mtime = Now, ctime = Now,
mode = 0, links = 1, major_device = 0,
diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl
index 210532edac..1faae1c1f4 100644
--- a/erts/preloaded/src/zlib.erl
+++ b/erts/preloaded/src/zlib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -349,10 +349,14 @@ getQSize(Z) ->
Compressed :: binary().
compress(Data) ->
Z = open(),
- deflateInit(Z, default),
- Bs = deflate(Z, Data, finish),
- deflateEnd(Z),
- close(Z),
+ Bs = try
+ deflateInit(Z, default),
+ B = deflate(Z, Data, finish),
+ deflateEnd(Z),
+ B
+ after
+ close(Z)
+ end,
iolist_to_binary(Bs).
-spec uncompress(Data) -> Decompressed when
@@ -364,10 +368,14 @@ uncompress(Data) ->
if
Size >= 8 ->
Z = open(),
- inflateInit(Z),
- Bs = inflate(Z, Data),
- inflateEnd(Z),
- close(Z),
+ Bs = try
+ inflateInit(Z),
+ B = inflate(Z, Data),
+ inflateEnd(Z),
+ B
+ after
+ close(Z)
+ end,
iolist_to_binary(Bs);
true ->
erlang:error(data_error)
@@ -383,10 +391,14 @@ uncompress(Data) ->
Compressed :: binary().
zip(Data) ->
Z = open(),
- deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default),
- Bs = deflate(Z, Data, finish),
- deflateEnd(Z),
- close(Z),
+ Bs = try
+ deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default),
+ B = deflate(Z, Data, finish),
+ deflateEnd(Z),
+ B
+ after
+ close(Z)
+ end,
iolist_to_binary(Bs).
-spec unzip(Data) -> Decompressed when
@@ -394,10 +406,14 @@ zip(Data) ->
Decompressed :: binary().
unzip(Data) ->
Z = open(),
- inflateInit(Z, -?MAX_WBITS),
- Bs = inflate(Z, Data),
- inflateEnd(Z),
- close(Z),
+ Bs = try
+ inflateInit(Z, -?MAX_WBITS),
+ B = inflate(Z, Data),
+ inflateEnd(Z),
+ B
+ after
+ close(Z)
+ end,
iolist_to_binary(Bs).
-spec gzip(Data) -> Compressed when
@@ -405,10 +421,14 @@ unzip(Data) ->
Compressed :: binary().
gzip(Data) ->
Z = open(),
- deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default),
- Bs = deflate(Z, Data, finish),
- deflateEnd(Z),
- close(Z),
+ Bs = try
+ deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default),
+ B = deflate(Z, Data, finish),
+ deflateEnd(Z),
+ B
+ after
+ close(Z)
+ end,
iolist_to_binary(Bs).
-spec gunzip(Data) -> Decompressed when
@@ -416,10 +436,14 @@ gzip(Data) ->
Decompressed :: binary().
gunzip(Data) ->
Z = open(),
- inflateInit(Z, 16+?MAX_WBITS),
- Bs = inflate(Z, Data),
- inflateEnd(Z),
- close(Z),
+ Bs = try
+ inflateInit(Z, 16+?MAX_WBITS),
+ B = inflate(Z, Data),
+ inflateEnd(Z),
+ B
+ after
+ close(Z)
+ end,
iolist_to_binary(Bs).
-spec collect(zstream()) -> iolist().
diff --git a/erts/start_scripts/Makefile b/erts/start_scripts/Makefile
index 4df7568484..55584bb057 100644
--- a/erts/start_scripts/Makefile
+++ b/erts/start_scripts/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
@@ -74,7 +74,7 @@ $(SS_ROOT)/start_clean.script \
$(SS_ROOT)/start_clean.boot: $(SS_ROOT)/start_clean.rel
$(INSTALL_DIR) $(SS_TMP)
( cd $(SS_TMP) && \
- $(ERLC) $(SASL_FLAGS) $(SCRIPT_PATH) -o $(SS_ROOT) $< )
+ $(ERLC) $(SASL_FLAGS) $(SCRIPT_PATH) +no_warn_sasl -o $(SS_ROOT) $< )
$(SS_ROOT)/start_sasl.script \
$(SS_ROOT)/start_sasl.boot: $(SS_ROOT)/start_sasl.rel
@@ -128,7 +128,7 @@ $(SS_ROOT)/start_all_example.rel: $(SS_ROOT)/start_all_example.rel.src \
$(ERL_TOP)/bin/start.script:
$(INSTALL_DIR) $(SS_TMP)
( cd $(SS_TMP) && \
- $(ERLC) $(SCRIPT_PATH) +otp_build -o $@ $(SS_ROOT)/start_clean.rel )
+ $(ERLC) $(SCRIPT_PATH) +no_warn_sasl +otp_build -o $@ $(SS_ROOT)/start_clean.rel )
$(ERL_TOP)/bin/start_sasl.script:
$(INSTALL_DIR) $(SS_TMP)
@@ -138,7 +138,7 @@ $(ERL_TOP)/bin/start_sasl.script:
$(ERL_TOP)/bin/start_clean.script:
$(INSTALL_DIR) $(SS_TMP)
( cd $(SS_TMP) && \
- $(ERLC) $(SCRIPT_PATH) +otp_build -o $@ $(SS_ROOT)/start_clean.rel )
+ $(ERLC) $(SCRIPT_PATH) +no_warn_sasl +otp_build -o $@ $(SS_ROOT)/start_clean.rel )
## Special target used from system/build/Makefile for source code release bootstrap.
bootstrap_scripts: $(SS_ROOT)/start_clean.rel
@@ -163,14 +163,14 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: script
- $(INSTALL_DIR) $(RELEASE_PATH)/releases/$(SYSTEM_VSN)
+ $(INSTALL_DIR) "$(RELEASE_PATH)/releases/$(SYSTEM_VSN)"
ifneq ($(findstring win32,$(TARGET)),win32)
- $(INSTALL_DATA) RELEASES.src $(RELEASE_PATH)/releases
+ $(INSTALL_DATA) RELEASES.src "$(RELEASE_PATH)/releases"
endif
$(INSTALL_DATA) $(INSTALL_SCRIPTS) $(REL_SCRIPTS) \
- $(RELEASE_PATH)/releases/$(SYSTEM_VSN)
- $(INSTALL_DATA) start_clean.script $(RELEASE_PATH)/releases/$(SYSTEM_VSN)/start.script
- $(INSTALL_DATA) start_clean.boot $(RELEASE_PATH)/releases/$(SYSTEM_VSN)/start.boot
+ "$(RELEASE_PATH)/releases/$(SYSTEM_VSN)"
+ $(INSTALL_DATA) start_clean.script "$(RELEASE_PATH)/releases/$(SYSTEM_VSN)/start.script"
+ $(INSTALL_DATA) start_clean.boot "$(RELEASE_PATH)/releases/$(SYSTEM_VSN)/start.boot"
release_docs_spec:
diff --git a/erts/test/Makefile b/erts/test/Makefile
index 68be3f2178..79be5497b0 100644
--- a/erts/test/Makefile
+++ b/erts/test/Makefile
@@ -86,10 +86,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) system.spec system.dynspec system.spec.vxworks \
- $(ERL_FILES) $(TARGET_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- tar cf - *_SUITE_data utils | (cd $(RELSYSDIR); tar xf -)
+ $(ERL_FILES) $(TARGET_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ tar cf - *_SUITE_data utils | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/erts/test/erl_print_SUITE.erl b/erts/test/erl_print_SUITE.erl
index ee1a200530..a49d8f069f 100644
--- a/erts/test/erl_print_SUITE.erl
+++ b/erts/test/erl_print_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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 @@
-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, fin_per_testcase/2]).
+ init_per_testcase/2, end_per_testcase/2]).
-export([erlang_display/1, integer/1, float/1,
string/1, character/1, snprintf/1, quote/1]).
@@ -247,7 +247,7 @@ init_per_testcase(Case, Config) ->
Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
[{testcase, Case}, {watchdog, Dog} |Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
@@ -303,7 +303,7 @@ read_case_data(Port, TestCase) ->
{Port, {data, {eol, [?PID_MARKER | PidStr]}}} ->
?line ?t:format("Port program pid: ~s~n", [PidStr]),
?line CaseProc = self(),
- ?line list_to_integer(PidStr), % Sanity check
+ ?line _ = list_to_integer(PidStr), % Sanity check
spawn_opt(fun () ->
port_prog_killer(CaseProc, PidStr)
end,
diff --git a/erts/test/erl_print_SUITE_data/Makefile.src b/erts/test/erl_print_SUITE_data/Makefile.src
index 109d55e572..96d71c7a98 100644
--- a/erts/test/erl_print_SUITE_data/Makefile.src
+++ b/erts/test/erl_print_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %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
@@ -20,23 +20,35 @@
include @erts_lib_include_internal_generated@@[email protected]
CC = @CC@
-CFLAGS = @ERTS_CFLAGS@
-LIBS = @ERTS_LIBS@
+CFLAGST = @ERTS_CFLAGS@
+LIBST = @ERTS_LIBS@
+CFLAGSF = @CFLAGS@
+LIBSF = @LIBS@
+CP=cp
+CHMOD=chmod
-EPTF_CFLAGS = -Wall $(CFLAGS) @DEFS@ -I@erts_lib_include_internal@ -I@erts_lib_include_internal_generated@
-EPTF_LIBS = $(LIBS) -L@erts_lib_internal_path@ -lerts_internal@type_marker@
+COMMON_CFLAGS = -Wall @DEFS@ -I@erts_lib_include_internal@ -I@erts_lib_include_internal_generated@
-EPTT_CFLAGS = -DTHREAD_SAFE $(ETHR_DEFS) $(EPTF_CFLAGS)
-EPTT_LIBS = $(LIBS) -L@erts_lib_internal_path@ -lerts_internal_r@type_marker@ $(ETHR_LIBS)
+EPTF_CFLAGS = $(CFLAGSF) $(COMMON_CFLAGS)
+EPTF_LIBS = -L@erts_lib_internal_path@ -lerts_internal@type_marker@ $(LIBSF)
+
+EPTT_CFLAGS = -DTHREAD_SAFE $(ETHR_DEFS) $(CFLAGST) $(COMMON_CFLAGS)
+EPTT_LIBS = -L@erts_lib_internal_path@ -lerts_internal_r@type_marker@ $(ETHR_LIBS) $(LIBST)
GCC = .@DS@gccifier -CC"$(CC)"
-PROGS = erl_print_tests.@emu_threads@@exe@
+PROGS = erl_print_tests.true@exe@ erl_print_tests.false@exe@
all: $(PROGS)
+@IFEQ@ (@cross@, yes)
+gccifier@exe@:
+ $(CP) ..@DS@utils@[email protected] gccifier@exe@
+ $(CHMOD) a+x gccifier@exe@
+@ELSE@
gccifier@exe@: ..@DS@utils@[email protected]
- $(CC) $(CFLAGS) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBS)
+ $(CC) $(CFLAGST) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBST)
+@ENDIF@
erl_print_tests.false@exe@: gccifier@exe@ erl_print_tests.c
$(GCC) $(EPTF_CFLAGS) -o erl_print_tests.false@exe@ erl_print_tests.c $(EPTF_LIBS)
diff --git a/erts/test/erl_print_SUITE_data/erl_print_tests.c b/erts/test/erl_print_SUITE_data/erl_print_tests.c
index 28ce78f4e1..82b0c21132 100644
--- a/erts/test/erl_print_SUITE_data/erl_print_tests.c
+++ b/erts/test/erl_print_SUITE_data/erl_print_tests.c
@@ -44,8 +44,8 @@
#endif
#ifdef __WIN32__
-#define signed_long_long LONGLONG
-#define unsigned_long_long ULONGLONG
+#define signed_long_long __int64
+#define unsigned_long_long unsigned __int64
#else
#define signed_long_long signed long long
#define unsigned_long_long unsigned long long
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index a9e28672e3..ada09db975 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -154,7 +154,8 @@ compile_mib(Config) when is_list(Config) ->
?line BadFile = filename:join(SrcDir, "BAD-MIB.mib"),
?line run(Config, Cmd, BadFile, "",
- ["Error: syntax error before: mibs\$", "compilation_failed_ERROR_"]),
+ ["BAD-MIB.mib: 1: syntax error before: mibs\$",
+ "compilation_failed_ERROR_"]),
%% Make sure that no -I option works.
@@ -237,6 +238,12 @@ num_d_options() ->
%% of arguments is 16383.
%% See: http://www.in-ulm.de/~mascheck/various/argmax/
5440;
+ {{unix,darwin},{Major,_,_}} when Major >= 11 ->
+ %% "getconf ARG_MAX" still reports 262144 (as in previous
+ %% version of MacOS X), but the useful space seem to have
+ %% shrunk significantly (or possibly the number of arguments).
+ %% 7673
+ 7500;
{_,_} ->
12000
end.
@@ -246,7 +253,7 @@ erlc() ->
false ->
test_server:fail("Can't find erlc");
Erlc ->
- Erlc
+ "\"" ++ Erlc ++ "\""
end.
%% Runs a command.
diff --git a/erts/test/erlexec_SUITE_data/Makefile.src b/erts/test/erlexec_SUITE_data/Makefile.src
index b751547b8f..970a905c32 100644
--- a/erts/test/erlexec_SUITE_data/Makefile.src
+++ b/erts/test/erlexec_SUITE_data/Makefile.src
@@ -20,6 +20,8 @@
CC = @CC@
CFLAGS = @ERTS_CFLAGS@
LIBS = @ERTS_LIBS@
+CP=cp
+CHMOD=chmod
ERLX_T_CFLAGS = -Wall $(ERLX_DEFS) $(CFLAGS) @DEFS@
@@ -29,8 +31,14 @@ PROGS = erlexec_tests@exe@
all: $(PROGS)
+@IFEQ@ (@cross@, yes)
+gccifier@exe@:
+ $(CP) ..@DS@utils@[email protected] gccifier@exe@
+ $(CHMOD) a+x gccifier@exe@
+@ELSE@
gccifier@exe@: ..@DS@utils@[email protected]
$(CC) $(CFLAGS) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBS)
+@ENDIF@
erlexec_tests@exe@: gccifier@exe@ erlexec_tests.c
$(GCC) $(ERLX_T_CFLAGS) -o erlexec_tests@exe@ erlexec_tests.c
diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl
index 4206bebfe7..24075286a8 100644
--- a/erts/test/ethread_SUITE.erl
+++ b/erts/test/ethread_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,7 +33,7 @@
-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, fin_per_testcase/2]).
+ init_per_testcase/2, end_per_testcase/2]).
-export([create_join_thread/1,
equal_tids/1,
@@ -68,9 +68,6 @@ tests() ->
atomic,
dw_atomic_massage].
-all(doc) -> [];
-all(suite) -> tests().
-
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
@@ -125,35 +122,37 @@ try_lock_mutex(suite) ->
try_lock_mutex(Config) ->
run_case(Config, "try_lock_mutex", "").
-wd_dispatch(P) ->
- receive
- bye ->
- ?line true = port_command(P, "-1 "),
- ?line bye;
- L when is_list(L) ->
- ?line true = port_command(P, L),
- ?line wd_dispatch(P)
- end.
-
-watchdog(Port) ->
- ?line process_flag(priority, max),
- ?line receive after 500 -> ok end,
-
- ?line random:seed(),
- ?line true = port_command(Port, "0 "),
- ?line lists:foreach(fun (T) ->
- erlang:send_after(T,
- self(),
- integer_to_list(T)
- ++ " ")
- end,
- lists:usort(lists:map(fun (_) ->
- random:uniform(4500)+500
- end,
- lists:duplicate(50,0)))),
- ?line erlang:send_after(5100, self(), bye),
-
- wd_dispatch(Port).
+%% Remove dead code?
+
+% wd_dispatch(P) ->
+% receive
+% bye ->
+% ?line true = port_command(P, "-1 "),
+% ?line bye;
+% L when is_list(L) ->
+% ?line true = port_command(P, L),
+% ?line wd_dispatch(P)
+% end.
+%
+% watchdog(Port) ->
+% ?line process_flag(priority, max),
+% ?line receive after 500 -> ok end,
+%
+% ?line random:seed(),
+% ?line true = port_command(Port, "0 "),
+% ?line lists:foreach(fun (T) ->
+% erlang:send_after(T,
+% self(),
+% integer_to_list(T)
+% ++ " ")
+% end,
+% lists:usort(lists:map(fun (_) ->
+% random:uniform(4500)+500
+% end,
+% lists:duplicate(50,0)))),
+% ?line erlang:send_after(5100, self(), bye),
+%
+% wd_dispatch(Port).
cond_wait(doc) ->
["Tests ethr_cond_wait with ethr_cond_signal and ethr_cond_broadcast."];
@@ -174,7 +173,15 @@ detached_thread(doc) ->
detached_thread(suite) ->
[];
detached_thread(Config) ->
- run_case(Config, "detached_thread", "").
+ case {os:type(), os:version()} of
+ {{unix,darwin}, {9, _, _}} ->
+ %% For some reason pthread_create() crashes when more
+ %% threads cannot be created, instead of returning an
+ %% error code on our MacOS X Leopard machine...
+ {skipped, "MacOS X Leopard cannot cope with this test..."};
+ _ ->
+ run_case(Config, "detached_thread", "")
+ end.
max_threads(doc) ->
["Tests maximum number of threads."];
@@ -239,11 +246,18 @@ dw_atomic_massage(Config) ->
%%
%%
-init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, Dog}|Config].
+init_per_testcase(Case, Config) ->
+ case inet:gethostname() of
+ {ok,"fenris"} when Case == max_threads ->
+ %% Cannot use os:type+os:version as not all
+ %% solaris10 machines are buggy.
+ {skip, "This machine is buggy"};
+ _Else ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, Dog}|Config]
+ end.
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
@@ -299,7 +313,7 @@ read_case_data(Port, TestCase) ->
{Port, {data, {eol, [?PID_MARKER | PidStr]}}} ->
?line ?t:format("Port program pid: ~s~n", [PidStr]),
?line CaseProc = self(),
- ?line list_to_integer(PidStr), % Sanity check
+ ?line _ = list_to_integer(PidStr), % Sanity check
spawn_opt(fun () ->
port_prog_killer(CaseProc, PidStr)
end,
diff --git a/erts/test/ethread_SUITE_data/Makefile.src b/erts/test/ethread_SUITE_data/Makefile.src
index 132b23344c..f93a31178b 100644
--- a/erts/test/ethread_SUITE_data/Makefile.src
+++ b/erts/test/ethread_SUITE_data/Makefile.src
@@ -23,6 +23,8 @@ include @erts_lib_include_internal_generated@@DS@erts_internal.mk
CC = @CC@
CFLAGS = @ERTS_CFLAGS@
LIBS = @ERTS_LIBS@
+CP=cp
+CHMOD=chmod
ETHR_T_CFLAGS = -Wall $(ETHR_DEFS) $(CFLAGS) @DEFS@ -I@erts_lib_include_internal@ -I@erts_lib_include_internal_generated@
ETHR_T_LIBS = $(LIBS) -L@erts_lib_internal_path@ $(ETHR_LIBS) $(ERTS_INTERNAL_X_LIBS)
@@ -33,8 +35,14 @@ PROGS = ethread_tests@exe@
all: $(PROGS)
+@IFEQ@ (@cross@, yes)
+gccifier@exe@:
+ $(CP) ..@DS@utils@[email protected] gccifier@exe@
+ $(CHMOD) a+x gccifier@exe@
+@ELSE@
gccifier@exe@: ..@DS@utils@[email protected]
$(CC) $(CFLAGS) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBS)
+@ENDIF@
ethread_tests@exe@: gccifier@exe@ ethread_tests.c
$(GCC) $(ETHR_T_CFLAGS) -o ethread_tests@exe@ ethread_tests.c -lerts_internal_r $(ETHR_T_LIBS)
diff --git a/erts/test/ethread_SUITE_data/ethread_tests.c b/erts/test/ethread_SUITE_data/ethread_tests.c
index 7e7e133d6c..ed96ecdbd2 100644
--- a/erts/test/ethread_SUITE_data/ethread_tests.c
+++ b/erts/test/ethread_SUITE_data/ethread_tests.c
@@ -82,6 +82,7 @@ static void
print_eol(void)
{
fprintf(stderr, EOL);
+ fflush(stderr);
}
static void print_line(char *frmt,...)
@@ -826,6 +827,7 @@ detached_thread_test(void)
* Tests
*/
#define MTT_TIMES 10
+#define MTT_HARD_LIMIT (80000)
static int mtt_terminate;
static ethr_mutex mtt_mutex;
@@ -866,14 +868,20 @@ mtt_create_join_threads(void)
while (1) {
if (ix >= no_tids) {
no_tids += 100;
+ if (no_tids > MTT_HARD_LIMIT) {
+ print_line("Hit the hard limit on number of threads (%d)!",
+ MTT_HARD_LIMIT);
+ break;
+ }
tids = (ethr_tid *) realloc((void *)tids, sizeof(ethr_tid)*no_tids);
ASSERT(tids);
}
res = ethr_thr_create(&tids[ix], mtt_thread, NULL, NULL);
- if (res != 0)
+ if (res != 0) {
break;
+ }
ix++;
- } while (res == 0);
+ }
no_threads = ix;
diff --git a/erts/test/install_SUITE.erl b/erts/test/install_SUITE.erl
index 214031a6fe..559d95007c 100644
--- a/erts/test/install_SUITE.erl
+++ b/erts/test/install_SUITE.erl
@@ -452,7 +452,7 @@ bin_dirname_fail(Config) when is_list(Config) ->
?line Be = Bs,
?line EBs = "/opt/lib/erlang/otp/bin",
?line EBe = EBs,
- ?line CMDPRFX = "PATH="++?config(data_dir,Config)++":"++os:getenv("PATH"),
+ ?line CMDPRFX = "PATH=\""++?config(data_dir,Config)++":"++os:getenv("PATH")++"\"",
ChkRes = fun (Res, #inst{test_prefix = TP,
destdir = D,
extra_prefix = EP,
@@ -485,7 +485,7 @@ bin_no_use_dirname_fail(Config) when is_list(Config) ->
?line EBs = "/opt/lib/erlang/otp/bin",
?line EBe = EBs,
?line RP = "../lib/erlang/otp/bin",
- ?line CMDPRFX = "PATH="++?config(data_dir,Config)++":"++os:getenv("PATH"),
+ ?line CMDPRFX = "PATH=\""++?config(data_dir,Config)++":"++os:getenv("PATH")++"\"",
ChkRes = fun (Res, #inst{test_prefix = TP,
destdir = D,
extra_prefix = EP,
diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl
index 7d6da28ad6..f9bd15a0ce 100644
--- a/erts/test/nt_SUITE.erl
+++ b/erts/test/nt_SUITE.erl
@@ -490,12 +490,12 @@ middleman(Waitfor) ->
match_event(_X, []) ->
nomatch;
match_event({Time,Cat,Fac,Sev,Mes},[{Pid,Ref,{Cat,Fac,Sev,MesRE}} | Tail]) ->
- case regexp:match(Mes,MesRE) of
- {match,_,_} ->
+ case re:run(Mes,MesRE,[{capture,none}]) of
+ match ->
%%io:format("Match!~n"),
{ok,{Pid,Ref,Time,Mes},Tail};
- _Z ->
- %%io:format("No match (~p)~n",[_Z]),
+ nomatch ->
+ %%io:format("No match~n"),
case match_event({Time,Cat,Fac,Sev,Mes},Tail) of
{ok,X,Rest} ->
{ok,X,[{Pid,Ref,{Cat,Fac,Sev,MesRE}} | Rest]};
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index d61fbbddcf..332733e075 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,21 +88,25 @@ undefined_functions(Config) when is_list(Config) ->
?line Undef1 = hipe_filter(Undef0),
?line Undef2 = ssl_crypto_filter(Undef1),
?line Undef3 = edoc_filter(Undef2),
- ?line Undef = eunit_filter(Undef3),
- ?line Undef = megaco_filter(Undef),
+ Undef4 = eunit_filter(Undef3),
+ Undef5 = dialyzer_filter(Undef4),
+ Undef = wx_filter(Undef5),
case Undef of
[] -> ok;
_ ->
+ Fd = open_log(Config, "undefined_functions"),
foreach(fun ({MFA1,MFA2}) ->
io:format("~s calls undefined ~s",
- [format_mfa(MFA1),format_mfa(MFA2)])
+ [format_mfa(Server, MFA1),
+ format_mfa(MFA2)]),
+ io:format(Fd, "~s ~s\n",
+ [format_mfa(Server, MFA1),
+ format_mfa(MFA2)])
end, Undef),
+ close_log(Fd),
?line ?t:fail({length(Undef),undefined_functions_in_otp})
-
- end,
-
- ok.
+ end.
hipe_filter(Undef) ->
case erlang:system_info(hipe_architecture) of
@@ -150,6 +154,9 @@ ssl_crypto_filter(Undef) ->
{{error,bad_name},{error,bad_name}} ->
filter(fun({_,{ssl,_,_}}) -> false;
({_,{crypto,_,_}}) -> false;
+ ({_,{ssh,_,_}}) -> false;
+ ({_,{ssh_connection,_,_}}) -> false;
+ ({_,{ssh_sftp,_,_}}) -> false;
(_) -> true
end, Undef);
{_,_} -> Undef
@@ -167,34 +174,33 @@ eunit_filter(Undef) ->
(_) -> true
end, Undef).
-megaco_filter(Undef) ->
- %% Intentional calls to undefined functions.
- filter(fun({{megaco_compact_text_encoder,encode_action_reply,3},
- {megaco_compact_text_encoder_v3,encode_action_reply,2}}) -> false;
- ({{megaco_compact_text_encoder,encode_action_request,3},
- {megaco_compact_text_encoder_v3,encode_action_request,2}}) -> false;
- ({{megaco_compact_text_encoder,encode_action_requests,3},
- {megaco_compact_text_encoder_v3,encode_action_requests,2}}) -> false;
- ({{megaco_compact_text_encoder,encode_command_request,3},
- {megaco_compact_text_encoder_v3,encode_command_request,2}}) -> false;
- ({{megaco_compact_text_encoder,encode_message,3},
- {megaco_compact_text_encoder_v3,encode_message,2}}) -> false;
- ({{megaco_compact_text_encoder,encode_transaction,3},
- {megaco_compact_text_encoder_v3,encode_transaction,2}}) -> false;
- ({{megaco_pretty_text_encoder,encode_action_reply,3},
- {megaco_pretty_text_encoder_v3,encode_action_reply,2}}) -> false;
- ({{megaco_pretty_text_encoder,encode_action_request,3},
- {megaco_pretty_text_encoder_v3,encode_action_request,2}}) -> false;
- ({{megaco_pretty_text_encoder,encode_action_requests,3},
- {megaco_pretty_text_encoder_v3,encode_action_requests,2}}) -> false;
- ({{megaco_pretty_text_encoder,encode_command_request,3},
- {megaco_pretty_text_encoder_v3,encode_command_request,2}}) -> false;
- ({{megaco_pretty_text_encoder,encode_message,3},
- {megaco_pretty_text_encoder_v3,encode_message,2}}) -> false;
- ({{megaco_pretty_text_encoder,encode_transaction,3},
- {megaco_pretty_text_encoder_v3,encode_transaction,2}}) -> false;
- (_) -> true
- end, Undef).
+dialyzer_filter(Undef) ->
+ case code:lib_dir(dialyzer) of
+ {error,bad_name} ->
+ filter(fun({_,{dialyzer_callgraph,_,_}}) -> false;
+ ({_,{dialyzer_codeserver,_,_}}) -> false;
+ ({_,{dialyzer_contracts,_,_}}) -> false;
+ ({_,{dialyzer_cl_parse,_,_}}) -> false;
+ ({_,{dialyzer_plt,_,_}}) -> false;
+ ({_,{dialyzer_succ_typings,_,_}}) -> false;
+ ({_,{dialyzer_utils,_,_}}) -> false;
+ (_) -> true
+ end, Undef);
+ _ -> Undef
+ end.
+
+wx_filter(Undef) ->
+ case code:lib_dir(wx) of
+ {error,bad_name} ->
+ filter(fun({_,{MaybeWxModule,_,_}}) ->
+ case atom_to_list(MaybeWxModule) of
+ "wx"++_ -> false;
+ _ -> true
+ end
+ end, Undef);
+ _ -> Undef
+ end.
+
deprecated_not_in_obsolete(Config) when is_list(Config) ->
?line Server = ?config(xref_server, Config),
@@ -211,7 +217,10 @@ deprecated_not_in_obsolete(Config) when is_list(Config) ->
_ ->
io:put_chars("The following functions have -deprecated() attributes,\n"
"but are not listed in otp_internal:obsolete/3.\n"),
- ?line print_mfas(L),
+ print_mfas(group_leader(), Server, L),
+ Fd = open_log(Config, "deprecated_not_obsolete"),
+ print_mfas(Fd, Server, L),
+ close_log(Fd),
?line ?t:fail({length(L),deprecated_but_not_obsolete})
end.
@@ -232,11 +241,13 @@ obsolete_but_not_deprecated(Config) when is_list(Config) ->
io:put_chars("The following functions are listed "
"in otp_internal:obsolete/3,\n"
"but don't have -deprecated() attributes.\n"),
- ?line print_mfas(L),
+ print_mfas(group_leader(), Server, L),
+ Fd = open_log(Config, "obsolete_not_deprecated"),
+ print_mfas(Fd, Server, L),
+ close_log(Fd),
?line ?t:fail({length(L),obsolete_but_not_deprecated})
end.
-
call_to_deprecated(Config) when is_list(Config) ->
Server = ?config(xref_server, Config),
?line {ok,DeprecatedCalls} = xref:q(Server, "strict(E || DF)"),
@@ -301,11 +312,28 @@ strong_components(Config) when is_list(Config) ->
%%% Common help functions.
%%%
-
-print_mfas([MFA|T]) ->
- io:format("~s\n", [format_mfa(MFA)]),
- print_mfas(T);
-print_mfas([]) -> ok.
+print_mfas(Fd, Server, MFAs) ->
+ [io:format(Fd, "~s\n", [format_mfa(Server, MFA)]) || MFA <- MFAs],
+ ok.
format_mfa({M,F,A}) ->
lists:flatten(io_lib:format("~s:~s/~p", [M,F,A])).
+
+format_mfa(Server, MFA) ->
+ MFAString = format_mfa(MFA),
+ AQ = "(App)" ++ MFAString,
+ AppPrefix = case xref:q(Server, AQ) of
+ {ok,[App]} -> "[" ++ atom_to_list(App) ++ "]";
+ _ -> ""
+ end,
+ AppPrefix ++ MFAString.
+
+open_log(Config, Name) ->
+ PrivDir = ?config(priv_dir, Config),
+ RunDir = filename:dirname(filename:dirname(PrivDir)),
+ Path = filename:join(RunDir, "system_"++Name++".log"),
+ {ok,Fd} = file:open(Path, [write]),
+ Fd.
+
+close_log(Fd) ->
+ ok = file:close(Fd).
diff --git a/erts/test/run_erl_SUITE.erl b/erts/test/run_erl_SUITE.erl
index 6350dc47dd..6838c8924d 100644
--- a/erts/test/run_erl_SUITE.erl
+++ b/erts/test/run_erl_SUITE.erl
@@ -250,7 +250,7 @@ defunct_2(Config, Perl) ->
?line ok = file:make_dir(LogDir),
?line Pipe = LogDir ++ "/",
?line RunErl = os:find_executable(run_erl),
- ?line Cmd = Perl ++ " " ++ RunErlTest ++ " " ++ RunErl ++ " " ++
+ ?line Cmd = Perl ++ " " ++ RunErlTest ++ " \"" ++ RunErl ++ "\" " ++
Defuncter ++ " " ++ Pipe ++ " " ++ LogDir,
?line io:format("~p", [Cmd]),
?line Res = os:cmd(Cmd),
diff --git a/erts/test/utils/gccifier.c b/erts/test/utils/gccifier.c
index 64de764260..a1019f9a72 100644
--- a/erts/test/utils/gccifier.c
+++ b/erts/test/utils/gccifier.c
@@ -73,17 +73,23 @@ save_arg(args_t *args, char *arg1, ...)
args->vec = (char **) (args->no
? realloc((void *) args->vec,
(sizeof(char *)
- *(args->no + ARGS_INCR + 1)))
+ *(args->no + ARGS_INCR + 2)))
: malloc((sizeof(char *)
- *(args->no + ARGS_INCR + 1))));
+ *(args->no + ARGS_INCR + 2))));
if (!args->vec)
enomem();
args->no += ARGS_INCR;
}
+ if (carg == arg1) {
+ args->vec[args->ix++] = "\"";
+ args->chars++;
+ }
args->vec[args->ix++] = carg;
args->chars += strlen(carg);
carg = va_arg(argp, char *);
}
+ args->vec[args->ix++] = "\"";
+ args->chars++;
args->vec[args->ix++] = " ";
args->chars++;
va_end(argp);
@@ -231,6 +237,9 @@ main(int argc, char *argv[])
CHECK_FIRST_LINK_ARG;
save_arg(&link_args, "-libpath:", arg, NULL);
}
+ else if (strcmp("-link",arg) == 0) {
+ CHECK_FIRST_LINK_ARG;
+ }
#endif /* #ifdef __WIN32__ */
else if (is_prefix("-l", &arg)) {
CHECK_FIRST_LINK_ARG;
diff --git a/erts/test/utils/gccifier.sh b/erts/test/utils/gccifier.sh
new file mode 100755
index 0000000000..4c6ba35db2
--- /dev/null
+++ b/erts/test/utils/gccifier.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2005-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+CC=`echo "$1" | sed -e "s/-CC//"`
+shift
+echo "->"
+echo "$CC $*"
+$CC $*
+echo ""
diff --git a/erts/test/z_SUITE.erl b/erts/test/z_SUITE.erl
index 8fceab32a6..78968ed405 100644
--- a/erts/test/z_SUITE.erl
+++ b/erts/test/z_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -166,9 +166,12 @@ core_search_conf(RunByTS, DBTop, XDir) ->
file_inspect(#core_search_conf{file = File}, Core) ->
FRes0 = os:cmd(File ++ " " ++ Core),
- FRes = case regexp:match(FRes0, Core) of
- {match, S, E} ->
+ FRes = case string:str(FRes0, Core) of
+ 0 ->
+ FRes0;
+ S ->
L = length(FRes0),
+ E = length(Core),
case S of
1 ->
lists:sublist(FRes0, E+1, L+1);
@@ -178,19 +181,13 @@ file_inspect(#core_search_conf{file = File}, Core) ->
" "
++
lists:sublist(FRes0, E+1, L+1)
- end;
- _ -> FRes0
+ end
end,
- case regexp:match(FRes, "[Tt][Ee][Xx][Tt]") of
+ case re:run(FRes, "text|ascii", [caseless,{capture,none}]) of
+ match ->
+ not_a_core;
nomatch ->
- case regexp:match(FRes, "[Aa][Ss][Cc][Ii][Ii]") of
- nomatch ->
- probably_a_core;
- _ ->
- not_a_core
- end;
- _ ->
- not_a_core
+ probably_a_core
end.
mk_readable(F) ->
@@ -239,8 +236,8 @@ format_core(#core_search_conf{file = false}, Core, Ignore) ->
[Ignore, Core] ++ mod_time_list(Core));
format_core(#core_search_conf{file = File}, Core, Ignore) ->
FRes = str_strip(os:cmd(File ++ " " ++ Core)),
- case catch regexp:match(FRes, Core) of
- {match, _, _} ->
+ case catch re:run(FRes, Core, [caseless,{capture,none}]) of
+ match ->
io:format(" ~s~s " ++ time_fstr() ++ "~n",
[Ignore, FRes] ++ mod_time_list(Core));
_ ->
diff --git a/erts/vsn.mk b/erts/vsn.mk
index d56d03146d..da0f03b24f 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The 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,8 +17,8 @@
# %CopyrightEnd%
#
-VSN = 5.9
-SYSTEM_VSN = R15A
+VSN = 5.9.2
+SYSTEM_VSN = R15B02
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/.gitignore b/lib/.gitignore
index 56b1ed2b84..4125111ebd 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -7,6 +7,7 @@
/common_test/doc/src/ct_rpc.xml
/common_test/doc/src/ct_snmp.xml
/common_test/doc/src/ct_ssh.xml
+/common_test/doc/src/ct_netconfc.xml
/common_test/doc/src/ct_telnet.xml
/common_test/doc/src/unix_telnet.xml
diff --git a/lib/Makefile b/lib/Makefile
index 7e52d6e32e..3753bd165b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2011. All Rights Reserved.
+# Copyright Ericsson AB 1996-2012. All Rights Reserved.
#
# The 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,53 +19,21 @@
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-#
-# Macros
-#
-ifeq ($(findstring vxworks,$(TARGET)),vxworks)
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
- OTHER_SUB_DIRECTORIES = \
- 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 diameter orber pman tv observer \
- cosTransactions cosEvent cosTime cosNotification cosProperty
- cosFileTransfer cosEventDomain
- endif
-else
-#
-# unix and win32
-# --------------
-#
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
- OTHER_SUB_DIRECTORIES = tools test_server common_test runtime_tools
- ifdef BUILD_ALL
- ifeq ($(findstring win32,$(TARGET)),win32) # BUILD_ALL on win32
- 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 \
- diameter \
- cosTransactions cosEvent cosTime cosNotification cosProperty \
- cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer docbuilder erl_docgen \
- common_test percept dialyzer
-# dialyzer
- OTHER_SUB_DIRECTORIES += hipe
- else # BUILD_ALL on unix
- OTHER_SUB_DIRECTORIES += \
- snmp otp_mibs appmon erl_interface asn1 jinterface wx debugger reltool gs inets \
+ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
+OTHER_SUB_DIRECTORIES = tools test_server common_test runtime_tools
+ifdef BUILD_ALL
+ OTHER_SUB_DIRECTORIES += \
+ 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 \
diameter \
cosTransactions cosEvent cosTime cosNotification \
cosProperty cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer docbuilder erl_docgen \
- common_test percept dialyzer
-# dialyzer
- OTHER_SUB_DIRECTORIES += hipe $(TSP_APP)
- endif
- endif
+ xmerl edoc eunit ssh inviso typer erl_docgen \
+ percept eldap dialyzer hipe
+ EXTRA_FILE := $(wildcard EXTRA-APPLICATIONS)
+ EXTRA_APPLICATIONS := $(if $(EXTRA_FILE),$(shell cat $(EXTRA_FILE)))
endif
ifdef BOOTSTRAP
@@ -76,9 +44,11 @@ else
SUB_DIRECTORIES = hipe parsetools asn1/src
else
ifdef TERTIARY_BOOTSTRAP
- SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools
+ SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools wx
else # Not bootstrap build
- SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
+ SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) \
+ $(OTHER_SUB_DIRECTORIES) \
+ $(EXTRA_APPLICATIONS)
endif
endif
endif
diff --git a/lib/appmon/doc/src/Makefile b/lib/appmon/doc/src/Makefile
index 743f123c06..2bf560ee6b 100644
--- a/lib/appmon/doc/src/Makefile
+++ b/lib/appmon/doc/src/Makefile
@@ -107,14 +107,14 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/appmon/doc/src/appmon.xml b/lib/appmon/doc/src/appmon.xml
index ae6147a387..6e04f8503f 100644
--- a/lib/appmon/doc/src/appmon.xml
+++ b/lib/appmon/doc/src/appmon.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,12 @@
<module>appmon</module>
<modulesummary>A graphical node and application process tree viewer.</modulesummary>
<description>
+ <warning>
+ <p>
+ The Appmon application has been superseded by the Observer application.
+ Appmon will be removed in R16.
+ </p>
+ </warning>
<p>The application monitor Appmon is a graphical utility used to
supervise applications executing either locally or on remote nodes.
The process tree of an application can furthermore be monitored.</p>
diff --git a/lib/appmon/doc/src/appmon_chapter.xml b/lib/appmon/doc/src/appmon_chapter.xml
index 0dab23b549..7ce22caaad 100644
--- a/lib/appmon/doc/src/appmon_chapter.xml
+++ b/lib/appmon/doc/src/appmon_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,12 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ The Appmon application has been superseded by the Observer application.
+ Appmon will be removed in R16.
+ </p>
+ </warning>
<p>The application monitor Appmon is a graphical node and application viewer. The tool shows an overview of all applications on all known nodes, and it is possible to view the process tree for an application running on any of the nodes.</p>
<note>
<p>If the Appmon code is not available at a node, for example an
diff --git a/lib/appmon/doc/src/make.dep b/lib/appmon/doc/src/make.dep
deleted file mode 100644
index ce0d7571a3..0000000000
--- a/lib/appmon/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: appmon.tex appmon_chapter.tex book.tex part.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: app_win.ps listbox_win.ps main_win.ps pinfo_win.ps
-
diff --git a/lib/appmon/doc/src/notes.xml b/lib/appmon/doc/src/notes.xml
index ace163bcad..04b2b0d8ba 100644
--- a/lib/appmon/doc/src/notes.xml
+++ b/lib/appmon/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,47 @@
</header>
<p>This document describes the changes made to the Appmon application.</p>
+<section><title>Appmon 2.1.14.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The GS applications is now deprecated and will be
+ removed in the R16 release. The following GS-based
+ applications have been superseded by the Observer
+ application and will removed in R16: Appmon, Pman,
+ Tv.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9907</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Appmon 2.1.14</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ <item>
+ <p>
+ Miscellaneous documentation build updates</p>
+ <p>
+ Own Id: OTP-9813</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Appmon 2.1.13</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/appmon/priv/Makefile b/lib/appmon/priv/Makefile
index 9af4fbd228..8920923c98 100644
--- a/lib/appmon/priv/Makefile
+++ b/lib/appmon/priv/Makefile
@@ -57,8 +57,8 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(HELP_FILES) $(TOOLBAR_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(HELP_FILES) $(TOOLBAR_FILES) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/appmon/src/Makefile b/lib/appmon/src/Makefile
index 43f4f085b8..9ee7c92a4d 100644
--- a/lib/appmon/src/Makefile
+++ b/lib/appmon/src/Makefile
@@ -92,10 +92,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/appmon/src/appmon.erl b/lib/appmon/src/appmon.erl
index 2b982cddf0..ba98a24400 100644
--- a/lib/appmon/src/appmon.erl
+++ b/lib/appmon/src/appmon.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% %CopyrightEnd%
-module(appmon).
-behaviour(gen_server).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%%%---------------------------------------------------------------------
%%% Appmon main module.
diff --git a/lib/appmon/src/appmon_a.erl b/lib/appmon/src/appmon_a.erl
index b0b5847343..6838a7a275 100644
--- a/lib/appmon/src/appmon_a.erl
+++ b/lib/appmon/src/appmon_a.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% %CopyrightEnd%
%%
-module(appmon_a).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%%----------------------------------------------------------------------
%%
diff --git a/lib/appmon/src/appmon_lb.erl b/lib/appmon/src/appmon_lb.erl
index 4e433f37c5..3ab6ce58e6 100644
--- a/lib/appmon/src/appmon_lb.erl
+++ b/lib/appmon/src/appmon_lb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,13 @@
%%% then pressing the load button, its application window is started.
-module(appmon_lb).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export ([
start/1,
diff --git a/lib/appmon/src/appmon_txt.erl b/lib/appmon/src/appmon_txt.erl
index 4e1785c53f..056265af90 100644
--- a/lib/appmon/src/appmon_txt.erl
+++ b/lib/appmon/src/appmon_txt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%%------------------------------------------------------------
-module(appmon_txt).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
-export([start/0, start/1, print/1, fprint/1]).
%% gen_server stuff
diff --git a/lib/appmon/src/appmon_web.erl b/lib/appmon/src/appmon_web.erl
index fb7144246c..048f7fa165 100644
--- a/lib/appmon/src/appmon_web.erl
+++ b/lib/appmon/src/appmon_web.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
@@ -578,9 +578,9 @@ htmlify_pid([],New)->
%% the HTTP protocol %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
urlify_pid(Pid) ->
- case regexp:first_match(Pid,"[<].*[>]") of
- {match,Start,Len}->
- "%3C"++string:substr(Pid,Start+1,Len-2)++"%3E";
+ case re:run(Pid,"[<](.*)[>]",[{capture,all_but_first,list}]) of
+ {match,[PidStr]}->
+ "%3C"++PidStr++"%3E";
_->
Pid
end.
diff --git a/lib/appmon/vsn.mk b/lib/appmon/vsn.mk
index fa17345daf..0654468b42 100644
--- a/lib/appmon/vsn.mk
+++ b/lib/appmon/vsn.mk
@@ -1 +1 @@
-APPMON_VSN = 2.1.13
+APPMON_VSN = 2.1.14.1
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 8c06be56f8..903cf32838 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -110,10 +110,10 @@ $(NIF_SHARED_OBJ_FILE): $(NIF_OBJ_FILES)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) $(RELSYSDIR)/priv/lib
- $(INSTALL_DIR) $(RELSYSDIR)/c_src
- $(INSTALL_DATA) *.c $(RELSYSDIR)/c_src
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
+ $(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src"
release_docs_spec:
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index 9c9f83bc2a..dbff14f9b3 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -580,7 +580,7 @@ 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;
+ int no_bits, ret;
if (desired_no == (no_bytes * 8)) {
if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused)
@@ -606,8 +606,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes,
== ASN1_ERROR
)
return ASN1_ERROR;
- ret2 = per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused);
- /* printf("ret2 = %d\n\r",ret2); */
+ per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused);
ret = CEIL(desired_no,8);
/* printf("ret = %d\n\r",ret); */
}
@@ -1198,7 +1197,7 @@ static ERL_NIF_TERM encode_per_complete(ErlNifEnv* env, int argc,
ErlNifBinary out_binary;
int complete_len;
if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary))
- return enif_make_atom(env, "badarg");
+ return enif_make_badarg(env);
if (!enif_alloc_binary(in_binary.size, &out_binary))
return enif_make_atom(env, "alloc_binary_failed");
diff --git a/lib/asn1/doc/src/Makefile b/lib/asn1/doc/src/Makefile
index d29225f6c9..9ef5750353 100644
--- a/lib/asn1/doc/src/Makefile
+++ b/lib/asn1/doc/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
@@ -27,15 +27,6 @@ include ../../vsn.mk
VSN=$(ASN1_VSN)
APPLICATION=asn1
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -86,34 +77,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex) \
- $(BOOK_FILES:%.xml=%.sgml) part.tex
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -126,8 +93,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -142,32 +107,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(GEN_XML) errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -179,43 +118,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(HTML_APPHISTORY) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
-
-
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index 0b9ec3df7f..3be58cbc8e 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>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -44,15 +44,15 @@
</description>
<funcs>
<func>
- <name>compile(Asn1module) -> ok | {error,Reason}</name>
- <name>compile(Asn1module , Options) -> ok | {error,Reason}</name>
+ <name>compile(Asn1module) -> ok | {error, Reason}</name>
+ <name>compile(Asn1module, Options) -> ok | {error, Reason}</name>
<fsummary>Compile an ASN.1 module and generate encode/decode functions according to the encoding rules BER or PER.</fsummary>
<type>
<v>Asn1module = atom() | string()</v>
<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 |
- nif | asn1config | undec_rest | {inline,OutputName} | inline |
+ <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string |
+ noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} | optimize |
+ 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>
@@ -158,7 +158,7 @@ File3.asn </pre>
of the BIT STRING type in Erlang. The notation:
</p>
<pre>
-BitString = {Unused,Binary},
+BitString = {Unused, Binary},
Unused = integer(),
Binary = binary()
</pre>
@@ -172,7 +172,7 @@ Binary = binary()
</seealso>.
</p>
</item>
- <tag><c>{n2n,EnumTypeName}</c></tag>
+ <tag><c>{n2n, EnumTypeName}</c></tag>
<item>
<p>
Tells the compiler to generate functions for conversion between
@@ -190,17 +190,17 @@ Binary = binary()
<c>.erl</c> file. If this option is omitted the generated Erlang module
will be compiled.</p>
</item>
- <tag><c>{i,IncludeDir}</c></tag>
+ <tag><c>{i, IncludeDir}</c></tag>
<item>
<p>Adds <c>IncludeDir</c> to the search-path for
<c>.asn1db</c> and asn1 source files. The compiler tries
to open a <c>.asn1db</c> file when a module imports
definitions from another ASN.1 module. If no
<c>.asn1db</c> file is found the asn1 source file is
- parsed. Several <c>{i,IncludeDir}</c> can be given.
+ parsed. Several <c>{i, IncludeDir}</c> can be given.
</p>
</item>
- <tag><c>{outdir,Dir}</c></tag>
+ <tag><c>{outdir, Dir}</c></tag>
<item>
<p>Specifies the directory <c>Dir</c> where all generated files
shall be placed. If omitted the files are placed in the
@@ -251,11 +251,11 @@ Binary = binary()
also have some following bytes. Now it is possible to get
those following bytes returned together with the decoded
value. If an asn1 spec is compiled with this option a tuple
- <c>{ok,Value,Rest}</c> is returned. <c>Rest</c> may be a
+ <c>{ok, Value, Rest}</c> is returned. <c>Rest</c> may be a
list or a binary. Earlier versions of the compiler ignored
those following bytes.</p>
</item>
- <tag><c>{inline,OutputName}</c></tag>
+ <tag><c>{inline, OutputName}</c></tag>
<item>
<p>Compiling with this option gives one output module
containing all asn1 run-time functionality. The asn1 specs
@@ -267,7 +267,7 @@ Binary = binary()
by the <c>igor</c> module of <c>syntax_tools</c>. By default
the functions generated from the first asn1 spec in the
<c>.set.asn</c> are exported, unless a
- <c>{export,[atom()]}</c> or <c>{export_all,true}</c> option
+ <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>
<p>When used together with <c>nif</c> for <c>ber_bin</c>, the
@@ -278,7 +278,7 @@ Binary = binary()
<tag><c>inline</c></tag>
<item>
<p>It is also possible to use the sole argument <c>inline</c>.
- It is as <c>{inline,OutputName}</c>, but the output file gets the
+ It is as <c>{inline, OutputName}</c>, but the output file gets the
default name of the source <c>.set.asn</c> file.</p>
</item>
<tag><c>{macro_name_prefix, Prefix}</c></tag>
@@ -322,7 +322,7 @@ Binary = binary()
</desc>
</func>
<func>
- <name>encode(Module,Type,Value)-> {ok,Bytes} | {error,Reason}</name>
+ <name>encode(Module, Type, Value)-> {ok, Bytes} | {error, Reason}</name>
<fsummary>Encode an ASN.1 value.</fsummary>
<type>
<v>Module = Type = atom()</v>
@@ -337,13 +337,13 @@ Binary = binary()
encode function only performs rudimentary tests that the input
<c>Value</c>
is a correct instance of <c>Type</c>. The length of strings is for example
- not always checked. Returns <c>{ok,Bytes}</c> if successful or
- <c>{error,Reason}</c> if an error occurred.
+ not always checked. Returns <c>{ok, Bytes}</c> if successful or
+ <c>{error, Reason}</c> if an error occurred.
</p>
</desc>
</func>
<func>
- <name>decode(Module,Type,Bytes) -> {ok,Value}|{error,Reason}</name>
+ <name>decode(Module, Type, Bytes) -> {ok, Value} | {error, Reason}</name>
<fsummary>Decode from Bytes into an ASN.1 value.</fsummary>
<type>
<v>Module = Type = atom()</v>
@@ -352,11 +352,11 @@ Binary = binary()
</type>
<desc>
<p>Decodes <c>Type</c> from <c>Module</c> from the list of bytes
- <c>Bytes</c>. Returns <c>{ok,Value}</c> if successful.</p>
+ <c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p>
</desc>
</func>
<func>
- <name>value(Module ,Type) -> {ok,Value} | {error,Reason}</name>
+ <name>value(Module, Type) -> {ok, Value} | {error, Reason}</name>
<fsummary>Create an ASN.1 value for test purposes.</fsummary>
<type>
<v>Module = Type = atom()</v>
@@ -371,26 +371,48 @@ Binary = binary()
</desc>
</func>
<func>
- <name>test(Module) -> ok | {error,Reason}</name>
- <name>test(Module,Type) -> ok | {error,Reason}</name>
- <name>test(Module,Type,Value) -> ok | {error,Reason}</name>
- <fsummary>Perform a test of encode and decode for types in an ASN.1 module.</fsummary>
+ <name>test(Module) -> ok | {error, Reason}</name>
+ <name>test(Module, Type | Options) -> ok | {error, Reason}</name>
+ <name>test(Module, Type, Value | Options) -> ok | {error, Reason}</name>
+ <fsummary>Perform a test of encode and decode for types in an ASN.1 module.</fsummary>
+ <type>
+ <v>Module = Type = atom()</v>
+ <v>Value = term()</v>
+ <v>Options = [{i, IncludeDir}]</v>
+ <v>Reason = term()</v>
+ </type>
<desc>
- <p>Performs a test of encode and decode of all types in <c>Module</c>.
+ <p>Performs a test of encode and decode of types in <c>Module</c>.
The generated functions are called by this function.
This function is useful during test to secure that the generated
- encode and decode functions and the general runtime support work
- as expected. <br></br>
-<c>test/1</c> iterates over all types in <c>Module</c>. <br></br>
-<c>test/2</c> tests type <c>Type</c> with a random value. <br></br>
-<c><![CDATA[test/3 tests type <c>Type]]></c> with <c>Value</c>. <br></br>
+ encode and decode functions and the general runtime support work
+ as expected.</p>
+
+ <list type="bulleted">
+ <item>
+ <p><c>test/1</c> iterates over all types in <c>Module</c>.</p>
+ </item>
+ <item>
+ <p><c>test/2</c> tests type <c>Type</c> with a random value.</p>
+ </item>
+ <item>
+ <p><c>test/3</c> tests type <c>Type</c> with <c>Value</c>.</p>
+ </item>
+ </list>
- Schematically the following happens for each type in the module.</p>
- <p></p>
+ <p>Schematically the following happens for each type in the module:
<code type="none">
-{ok,Value} = asn1ct:value(Module,Type),
-{ok,Bytes} = asn1ct:encode(Module,Type,Value),
-{ok,Value} = asn1ct:decode(Module,Type,Bytes). </code>
+{ok, Value} = asn1ct:value(Module, Type),
+{ok, Bytes} = asn1ct:encode(Module, Type, Value),
+{ok, Value} = asn1ct:decode(Module, Type, Bytes).</code></p>
+
+ <p>The <c>test</c> functions utilizes the <c>*.asn1db</c> files
+ for all included modules. If they are located in a different
+ directory than the current working directory, use the include
+ option to add paths. This is only needed when automatically
+ generating values. For static values using <c>Value</c> no
+ options are needed.</p>
+
</desc>
</func>
</funcs>
diff --git a/lib/asn1/doc/src/make.dep b/lib/asn1/doc/src/make.dep
deleted file mode 100644
index eb2c0e9a98..0000000000
--- a/lib/asn1/doc/src/make.dep
+++ /dev/null
@@ -1,31 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/gandalf/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: asn1_spec.tex asn1_ug.tex asn1ct.tex asn1rt.tex \
- book.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-asn1_spec.tex: Seq.asn Seq.asn1config
-
-book.tex: part.xml ref_man.xml
-
-asn1_ug.tex: ../../../../system/doc/definitions/cite.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: exclusive_Win_But.ps selective_TypeList.ps \
- selective_Window2.ps
-
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 52d770c9f6..b5422c9083 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -31,6 +31,83 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 1.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Some ASN.1 INTEGER type and SEQUENCE constructor variants
+ previously not handled by the ASN.1 compiler are now
+ correctly handled</p>
+ <p>
+ Own Id: OTP-9688</p>
+ </item>
+ <item>
+ <p>
+ An INTEGER with a value constraint where unions are used
+ e.g. X1 ::= INTEGER (1..4 | 6 | 8 | 10 | 20) is not
+ handled correctly. For PER the value is encoded in wrong
+ number of bits.</p>
+ <p>
+ Own Id: OTP-9946</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 1.6.19</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The linked-in driver used for ber decode and per encode
+ has been replaced with nifs. To enable the usage of nifs
+ pass the nif option to erlc or asn1rt:compile when
+ compiling. If you previously used the linked-in driver,
+ you have to recompile your ASN1 modules with the current
+ version of asn1 application as the linked-in driver
+ modules have been removed.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9419</p>
+ </item>
+ <item>
+ <p>
+ A few of the heavy calculations which are done for
+ encoding and decoding operations when dealing with
+ SEQUENCE OF and DEFAULT in runtime have been moved to be
+ done in compile time instead.</p>
+ <p>
+ Own Id: OTP-9440</p>
+ </item>
+ <item>
+ <p>
+ When compiling an ASN.1 ber module with the +nif option,
+ the module will use a new nif for ber encoding,
+ increasing performance by about 5%.</p>
+ <p>
+ Own Id: OTP-9441</p>
+ </item>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 1.6.18</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 3a59773d93..4bd49aa93b 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -58,7 +58,8 @@ CT_MODULES= \
asn1ct_gen_ber_bin_v2 \
asn1ct_value \
asn1ct_tok \
- asn1ct_parser2
+ asn1ct_parser2 \
+ asn1ct_table
RT_MODULES= \
asn1rt \
@@ -152,16 +153,16 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
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) $(ERL_FILES) $(HRL_FILES) $(APP_SRC) $(APPUP_SRC) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(EXAMPLES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(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
+#$(INSTALL_DIR) "$(RELSYSDIR)/include"
+#$(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl
index f680b3d064..843fc66c9c 100644
--- a/lib/asn1/src/asn1_db.erl
+++ b/lib/asn1/src/asn1_db.erl
@@ -1,167 +1,154 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, 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(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]).
+-export([dbstart/1,dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]).
+-export([dbget_all_mod/1,dbclear/0,dberase_module/1,dbstop/0]).
-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).
+-record(state, {parent, monitor, includes, table}).
-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)
+%% Interface
+dbstart(Includes) ->
+ Parent = self(),
+ case get(?MODULE) of
+ undefined ->
+ put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)),
+ true;
+ _Pid ->
+ req({new_includes, Includes})
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]));
- {From,{new_includes,[NewIncludes]}} ->
- From ! {asn1db,done},
- dbloop(NewIncludes,Tab)
+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}).
+dbclear() -> req(clear).
+dberase_module({module,M}) -> req({delete_mod, M}).
+dbstop() -> Resp = req(stop), erase(?MODULE), Resp.
+
+%% Internal functions
+req(Request) ->
+ DbPid = get(?MODULE),
+ Ref = erlang:monitor(process,DbPid),
+ get(?MODULE) ! {{Ref, self()}, Request},
+ receive
+ {{Ref,?MODULE}, Reply} ->
+ erlang:demonitor(Ref,[flush]),
+ Reply;
+ {'DOWN',Ref,_,_,Info} ->
+ exit({db_error,Info})
end.
+reply({Ref,From}, Response) ->
+ From ! {{Ref,?MODULE}, Response}.
-%%all(Tab, K) ->
-%% pickup(K, ets:match(Tab, {{K, '$1'}, '$2'})).
-%%pickup(K, []) -> [];
-%%pickup(K, [[V1,V2] |T]) ->
-%% [{{K,V1},V2} | pickup(K, T)].
+init(Parent, Includes) ->
+ MRef = erlang:monitor(process, Parent),
+ loop(#state{parent = Parent, monitor = MRef, includes = Includes,
+ table = ets:new(?MODULE, [])}).
-lookup(Tab, K) ->
- case ets:lookup(Tab, K) of
- [] -> undefined;
- [{K,V}] -> V
+loop(#state{parent = Parent, monitor = MRef, table = Table,
+ includes = Includes} = State) ->
+ receive
+ {From, {set, Mod, K2, V}} ->
+ [{_, Modtab}] = ets:lookup(Table, Mod),
+ ets:insert(Modtab, {K2, V}),
+ reply(From, ok),
+ loop(State);
+ {From, {get, Mod, K2}} ->
+ Result = case ets:lookup(Table, Mod) of
+ [] -> opentab(Table, Mod, Includes);
+ [{_, Modtab}] -> {ok, Modtab}
+ end,
+ case Result of
+ {ok, Newtab} -> reply(From, lookup(Newtab, K2));
+ _Error -> reply(From, undefined)
+ end,
+ loop(State);
+ {From, {all_mod, Mod}} ->
+ [{_, Modtab}] = ets:lookup(Table, Mod),
+ reply(From, ets:tab2list(Modtab)),
+ loop(State);
+ {From, {delete_mod, Mod}} ->
+ [{_, Modtab}] = ets:lookup(Table, Mod),
+ ets:delete(Modtab),
+ ets:delete(Table, Mod),
+ reply(From, ok),
+ loop(State);
+ {From, {save, OutFile, Mod}} ->
+ [{_,Mtab}] = ets:lookup(Table, Mod),
+ reply(From, ets:tab2file(Mtab, OutFile)),
+ loop(State);
+ {From, {load, Mod}} ->
+ Result = case ets:lookup(Table, Mod) of
+ [] -> opentab(Table, Mod, Includes);
+ [{_, Modtab}] -> {ok, Modtab}
+ end,
+ reply(From, Result),
+ loop(State);
+ {From, {new, Mod}} ->
+ case ets:lookup(Table, Mod) of
+ [{_, Modtab}] -> ets:delete(Modtab);
+ _ -> true
+ end,
+ ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []),
+ ets:insert(Table, {Mod, ModTableId}),
+ reply(From, ok),
+ loop(State);
+ {From, clear} ->
+ [ets:delete(Mt) || {_, Mt} <- ets:tab2list(Table)],
+ ets:delete(Table),
+ reply(From, cleared),
+ loop(State#state{table = ets:new(asn1, [set])});
+ {From, {new_includes, NewIncludes}} ->
+ reply(From, true),
+ loop(State#state{includes = NewIncludes});
+ {From, stop} ->
+ reply(From, stopped); %% Nothing to store
+ {'DOWN', MRef, process, Parent, Reason} ->
+ exit(Reason)
end.
+opentab(Tab, Mod, []) ->
+ opentab(Tab, Mod, ["."]);
+opentab(Tab, Mod, Includes) ->
+ Base = lists:concat([Mod, ".asn1db"]),
+ opentab2(Tab, Base, Mod, Includes, ok).
-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 ->
- req({new_includes,Args})
+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.
-
+lookup(Tab, K) ->
+ case ets:lookup(Tab, K) of
+ [] -> undefined;
+ [{K,V}] -> V
+ end.
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index 85bb5b2f28..99755a95a6 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -1,7 +1,8 @@
+%% vim: tabstop=8:shiftwidth=4
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,13 +25,13 @@
%%-compile(export_all).
%% Public exports
-export([compile/1, compile/2]).
--export([start/0, start/1, stop/0]).
+-export([start/0, start/1]).
-export([encode/2, encode/3, decode/3]).
--export([test/1, test/2, test/3, value/2]).
+-export([test/1, test/2, test/3, value/2, value/3]).
%% 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]).
+ vsn/0,
+ 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,
@@ -93,25 +94,24 @@ compile(File,Options) when is_list(Options) ->
end,
Options1 = optimize_ber_bin(Options),
Options2 = includes(File,Options1),
- Includes=[I||{i,I}<-Options2],
- case (catch input_file_type(File,Includes)) of
- {single_file,SuffixedFile} -> %% "e.g. "/tmp/File.asn"
- (catch compile1(SuffixedFile,Options2));
- {multiple_files_file,SetBase,FileName} ->
- FileList = get_file_list(FileName,Includes),
-%% io:format("FileList: ~p~n",[FileList]),
- case FileList of
- L when is_list(L) ->
- (catch compile_set(SetBase,FileList,Options2));
- Err ->
- Err
- end;
- Err = {input_file_error,_Reason} ->
- {error,Err};
- Err2 -> Err2
+ Includes = strip_includes(Options2),
+ in_process(fun() -> compile_proc(File, Includes, Options2) end).
+
+compile_proc(File, Includes, Options) ->
+ case input_file_type(File, Includes) of
+ {single_file, SuffixedFile} -> %% "e.g. "/tmp/File.asn"
+ compile1(SuffixedFile, Options);
+ {multiple_files_file, SetBase, FileName} ->
+ case get_file_list(FileName, Includes) of
+ FileList when is_list(FileList) ->
+ compile_set(SetBase, FileList, Options);
+ Err ->
+ Err
+ end;
+ Err = {input_file_error, _Reason} ->
+ {error, Err}
end.
-
compile1(File,Options) when is_list(Options) ->
verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File],Options),
verbose("Compiler Options: ~p~n",[Options],Options),
@@ -121,13 +121,13 @@ compile1(File,Options) when is_list(Options) ->
DbFile = outfile(Base,"asn1db",Options),
Includes = [I || {i,I} <- Options],
EncodingRule = get_rule(Options),
- create_ets_table(asn1_functab,[named_table]),
+ asn1ct_table:new(asn1_functab),
Continue1 = scan(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]),
+ asn1ct_table:delete(asn1_functab),
Ret = compile_erl(Continue4,OutFile,Options),
case inline(is_inline(Options),
inline_output(Options,filename:rootname(File)),
@@ -189,7 +189,7 @@ compile_set(SetBase,Files,Options)
DbFile = outfile(SetBase,"asn1db",Options),
Includes = [I || {i,I} <- Options],
EncodingRule = get_rule(Options),
- create_ets_table(asn1_functab,[named_table]),
+ asn1ct_table:new(asn1_functab),
ScanRes = scan_set(Files,Options),
ParseRes = parse_set(ScanRes,Options),
Result =
@@ -214,7 +214,7 @@ compile_set(SetBase,Files,Options)
{error,{'unexpected error in scan/parse phase',
lists:map(fun(X)->element(3,X) end,Other)}}
end,
- delete_tables([asn1_functab]),
+ asn1ct_table:delete(asn1_functab),
Result.
check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
@@ -226,7 +226,7 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
Options,InputModules),
Continue2 = generate(Continue1,OutFile,EncRule,Options),
- delete_tables([renamed_defs,original_imports,automatic_tags]),
+ asn1ct_table:delete([renamed_defs, original_imports, automatic_tags]),
Ret = compile_erl(Continue2,OutFile,Options),
case inline(is_inline(Options),
@@ -247,12 +247,11 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
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
+ case asn1ct_table:size(renamed_defs) of
+ 0 -> asn1ct_table: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,
@@ -272,7 +271,7 @@ merge_modules(ParseRes,CommonName) ->
%% causes an exit if duplicate definition names exist in a module
remove_name_collisions(Modules) ->
- create_ets_table(renamed_defs,[named_table]),
+ asn1ct_table:new(renamed_defs),
%% 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
@@ -304,7 +303,8 @@ remove_name_collisions2(ModName,[T|Ts],Ms,Acc) ->
%% 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}),
+ asn1ct_table: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
@@ -328,8 +328,8 @@ discover_dupl_in_mods(Name,Def,[M=#module{name=N,typeorval=TorV}|Ms],
%% 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}),
+ asn1ct_table:insert(renamed_defs,
+ {get_name_of_def(NewT), Name, N}),
{NewT,?dupl_uniquedefs bor RenamedOrDupl};
{Name,equal} ->
%% delete def
@@ -484,8 +484,9 @@ save_imports(ModuleList)->
[] ->
ok;
ImportsList2 ->
- create_ets_table(original_imports,[named_table]),
- lists:foreach(fun(X) -> ets:insert(original_imports,X) end,ImportsList2)
+ asn1ct_table:new(original_imports),
+ lists:foreach(fun(X) -> asn1ct_table:insert(original_imports, X) end,
+ ImportsList2)
end.
@@ -561,7 +562,7 @@ check_tagdefault(ModList) ->
case have_same_tagdefault(ModList) of
{true,TagDefault} -> TagDefault;
{false,TagDefault} ->
- create_ets_table(automatic_tags,[named_table]),
+ asn1ct_table:new(automatic_tags),
save_automatic_tagged_types(ModList),
TagDefault
end.
@@ -588,7 +589,7 @@ save_automatic_tagged_types([#module{tagdefault='AUTOMATIC',
typeorval=TorV}|Ms]) ->
Fun =
fun(T) ->
- ets:insert(automatic_tags,{get_name_of_def(T)})
+ asn1ct_table:insert(automatic_tags, {get_name_of_def(T)})
end,
lists:foreach(Fun,TorV),
save_automatic_tagged_types(Ms);
@@ -815,7 +816,9 @@ check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
asn1_db:dbsave(DbFile,M#module.name),
verbose("--~p--~n",[{generated,DbFile}],Options),
{true,{M,NewM,GenTypeOrVal}}
- end
+ end;
+ ErrorList = {error,_} ->
+ {false,ErrorList}
end;
check({false,M},_,_,_,_,_,_,_) ->
{false,M}.
@@ -827,22 +830,14 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
_ -> ok
end,
put(encoding_options,Options),
- create_ets_table(check_functions,[named_table]),
+ asn1ct_table:new(check_functions),
%% 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} -> warning("Error in configuration "
- "file: ~n~p~n",[Reason],Options,
- "Error in configuration file");
- {'EXIT',Reason} -> warning("Internal error when "
- "analyzing configuration "
- "file: ~n~p~n",[Reason],Options,
- "Internal error when "
- "analyzing configuration");
- _ -> ok
+ case specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of
+ {error, Reason} -> warning("Error in configuration file: ~n~p~n",
+ [Reason], Options,
+ "Error in configuration file");
+ _ -> ok
end,
Result =
@@ -859,7 +854,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
erase(encoding_options),
erase(tlv_format), % used in ber_bin, optimize
erase(class_default_type),% used in ber_bin, optimize
- ets:delete(check_functions),
+ asn1ct_table:delete(check_functions),
case Result of
{error,_} ->
{false,Result};
@@ -1181,17 +1176,28 @@ optimize_ber_bin(Options) ->
end.
includes(File,Options) ->
- Dir = filename:dirname(File),
- Options2 =
- case lists:member({i,"."},Options) of
- false -> Options ++ [{i,"."}];
- _ -> Options
- end,
- case lists:member({i,Dir}, Options2) of
- false -> Options2 ++ [{i,Dir}];
- _ -> Options2
+ Options2 = include_append(".", Options),
+ Options3 = include_append(filename:dirname(File), Options2),
+ case proplists:get_value(outdir, Options) of
+ undefined -> Options3;
+ OutDir -> include_prepend(OutDir, Options3)
end.
+include_append(Dir, Options) ->
+ option_add({i, Dir}, Options, fun(Opts) -> Opts ++ [{i, Dir}] end).
+
+include_prepend(Dir, Options) ->
+ option_add({i, Dir}, Options, fun(Opts) -> [{i, Dir}|Opts] end).
+
+option_add(Option, Options, Fun) ->
+ case lists:member(Option, Options) of
+ true -> Options;
+ false -> Fun(Options)
+ end.
+
+strip_includes(Includes) ->
+ [I || {i, I} <- Includes].
+
is_inline(Options) ->
case lists:member(inline,Options) of
true -> true;
@@ -1221,10 +1227,7 @@ 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} ->
- error("~p~n~s~n",[Exit,"error"],Options),
- error;
+ case compile(File, make_erl_options(Options)) of
{error,_Reason} ->
%% case occurs due to error in asn1ct_parser2,asn1ct_check
%% io:format("~p~n",[_Reason]),
@@ -1237,10 +1240,7 @@ compile(File, _OutFile, Options) ->
ok;
ScanRes when is_list(ScanRes) ->
io:format("~p~n",[ScanRes]),
- ok;
- Unknown ->
- error("~p~n~s~n",[Unknown,"error"],Options),
- error
+ ok
end.
%% Converts generic compiler options to specific options.
@@ -1339,17 +1339,6 @@ start() ->
start(Includes) when is_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).
@@ -1365,94 +1354,116 @@ 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
+test(Module) -> test_module(Module, []).
+
+test(Module, [] = Options) -> test_module(Module, Options);
+test(Module, [{i, _}|_] = Options) -> test_module(Module, Options);
+test(Module, Type) -> test_type(Module, Type, []).
+
+test(Module, Type, [] = Options) -> test_type(Module, Type, Options);
+test(Module, Type, [{i, _}|_] = Options) -> test_type(Module, Type, Options);
+test(Module, Type, Value) -> test_value(Module, Type, Value).
+
+test_module(Module, Includes) ->
+ in_process(fun() ->
+ start(strip_includes(Includes)),
+ case check(Module, Includes) of
+ {ok, NewTypes} -> test_each(Module, NewTypes);
+ Error -> Error
+ end
+ end).
+
+test_each(Module, [Type|Rest]) ->
+ case test_type(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}}}
+test_type(Module, Type, Includes) ->
+ in_process(fun() ->
+ start(strip_includes(Includes)),
+ case check(Module, Includes) of
+ {ok, _NewTypes} -> test_type(Module, Type);
+ Error -> Error
+ end
+ end).
+
+test_type(Module, Type) ->
+ case get_value(Module, Type) of
+ {ok, Val} -> test_value(Module, Type, Val);
+ {error, Reason} -> {error, {asn1, {value, Reason}}}
end.
+test_value(Module, Type, Value) ->
+ in_process(fun() ->
+ case catch encode(Module, Type, Value) of
+ {ok, Bytes} ->
+ M = to_atom(Module),
+ NewBytes = prepare_bytes(M:encoding_rule(), Bytes),
+ 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
+ end).
+
+value(Module, Type) -> value(Module, Type, []).
+
+value(Module, Type, Includes) ->
+ in_process(fun() ->
+ start(strip_includes(Includes)),
+ case check(Module, Includes) of
+ {ok, _NewTypes} -> get_value(Module, Type);
+ Error -> Error
+ end
+ end).
+
+get_value(Module, Type) ->
+ case asn1ct_value:from_type(Module, Type) of
+ {error, Reason} -> {error, Reason};
+ Result -> {ok, Result}
+ end.
-test(Module,Type,Value) ->
- case catch encode(Module,Type,Value) of
- {ok,Bytes} ->
- %% io:format("test 1: ~p~n",[{Bytes}]),
- M = if
- is_list(Module) ->
- list_to_atom(Module);
- true ->
- Module
- end,
- NewBytes =
- case M:encoding_rule() of
- ber ->
- lists:flatten(Bytes);
- ber_bin when is_binary(Bytes) ->
- Bytes;
- ber_bin ->
- list_to_binary(Bytes);
- ber_bin_v2 when is_binary(Bytes) ->
- Bytes;
- ber_bin_v2 ->
- list_to_binary(Bytes);
- per ->
- lists:flatten(Bytes);
- per_bin when is_binary(Bytes) ->
- Bytes;
- per_bin ->
- list_to_binary(Bytes);
- uper_bin ->
- 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}}}}
+check(Module, Includes) ->
+ case asn1_db:dbget(Module,'MODULE') of
+ undefined ->
+ {error, {file_not_found, lists:concat([Module, ".asn1db"])}};
+ M ->
+ TypeOrVal = M#module.typeorval,
+ State = #state{mname = M#module.name,
+ module = M#module{typeorval=[]},
+ options = Includes},
+ case asn1ct_check:check(State, TypeOrVal) of
+ {ok, {NewTypes, _, _, _, _, _}, _} -> {ok, NewTypes};
+ {error, Reason} -> {error, Reason}
+ end
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).
+to_atom(Term) when is_list(Term) -> list_to_atom(Term);
+to_atom(Term) when is_atom(Term) -> Term.
-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.
+prepare_bytes(ber, Bytes) -> lists:flatten(Bytes);
+prepare_bytes(ber_bin, Bytes) when is_binary(Bytes) -> Bytes;
+prepare_bytes(ber_bin, Bytes) -> list_to_binary(Bytes);
+prepare_bytes(ber_bin_v2, Bytes) when is_binary(Bytes) -> Bytes;
+prepare_bytes(ber_bin_v2, Bytes) -> list_to_binary(Bytes);
+prepare_bytes(per, Bytes) -> lists:flatten(Bytes);
+prepare_bytes(per_bin, Bytes) when is_binary(Bytes) -> Bytes;
+prepare_bytes(per_bin, Bytes) -> list_to_binary(Bytes);
+prepare_bytes(uper_bin, Bytes) -> Bytes.
vsn() ->
?vsn.
@@ -1484,38 +1495,6 @@ print_listing([],_) ->
ok.
-%% functions to administer ets tables
-
-%% Always creates a new table
-create_ets_table(Name,Options) when is_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) ->
case lists:member(asn1config,Options) of
true ->
@@ -1534,26 +1513,26 @@ partial_decode_prepare(ber_bin_v2,M,TsAndVs,Options) when is_tuple(TsAndVs) ->
_ -> M#module.name
end,
%% io:format("ModName: ~p~nM#module.name: ~p~n~n",[ModName,M#module.name]),
- CfgList = read_config_file(ModName),
- SelectedDecode = get_config_info(CfgList,selective_decode),
- ExclusiveDecode = get_config_info(CfgList,exclusive_decode),
- CommandList =
- create_partial_decode_gen_info(M#module.name,SelectedDecode),
- %% To convert CommandList to a proper list for the driver change
- %% the list:[[choosen,Tag1],skip,[skip_optional,Tag2]] to L =
- %% [5,2,Tag1,0,1,Tag2] where 5 is the length, and call
- %% port_control(asn1_driver_port,3,[L| Bin])
- save_config(partial_decode,CommandList),
- save_gen_state(selective_decode,SelectedDecode),
-% io:format("selective_decode: CommandList:~n~p~nSelectedDecode:~n~p~n",
-% [CommandList,SelectedDecode]),
- CommandList2 =
- create_partial_inc_decode_gen_info(M#module.name,ExclusiveDecode),
-% io:format("partial_incomplete_decode = ~p~n",[CommandList2]),
- Part_inc_tlv_tags = tlv_tags(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(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags);
+ case read_config_file(ModName) of
+ no_config_file ->
+ ok;
+ CfgList ->
+ SelectedDecode = get_config_info(CfgList,selective_decode),
+ ExclusiveDecode = get_config_info(CfgList,exclusive_decode),
+ CommandList = create_partial_decode_gen_info(M#module.name,
+ SelectedDecode),
+ %% To convert CommandList to a proper list for the driver change
+ %% the list:[[choosen,Tag1],skip,[skip_optional,Tag2]] to L =
+ %% [5,2,Tag1,0,1,Tag2] where 5 is the length, and call
+ %% port_control(asn1_driver_port,3,[L| Bin])
+ save_config(partial_decode,CommandList),
+ save_gen_state(selective_decode,SelectedDecode),
+ CommandList2 = create_partial_inc_decode_gen_info(M#module.name,
+ ExclusiveDecode),
+ Part_inc_tlv_tags = tlv_tags(CommandList2),
+ save_config(partial_incomplete_decode,Part_inc_tlv_tags),
+ save_gen_state(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags)
+ end;
partial_decode_prepare(_,_,_,_) ->
ok.
@@ -2032,7 +2011,7 @@ read_config_file(ModuleName) ->
read_config_file1(ModuleName,[]) ->
case filename:extension(ModuleName) of
".asn1config" ->
- throw({error,enoent});
+ no_config_file;
_ ->
read_config_file(lists:concat([ModuleName,".asn1config"]))
end;
@@ -2061,14 +2040,14 @@ get_config_info(CfgList,InfoType) ->
%% Before saving anything check if a table exists
%% The record gen_state is saved with the key {asn1_config,gen_state}
save_config(Key,Info) ->
- create_if_no_table(asn1_general,[named_table]),
- ets:insert(asn1_general,{{asn1_config,Key},Info}).
+ asn1ct_table:new_reuse(asn1_general),
+ asn1ct_table: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
+ case asn1ct_table:exists(asn1_general) of
+ false -> undefined;
+ true ->
+ case asn1ct_table:lookup(asn1_general,{asn1_config,Key}) of
[{_,Data}] -> Data;
Err -> % Err is [] when nothing was saved in the ets table
%% io:format("strange data from config file ~w~n",[Err]),
@@ -2595,3 +2574,21 @@ is_werr(S) when is_record(S, state) ->
is_werr(S#state.options);
is_werr(O) ->
lists:member(warnings_as_errors, O).
+
+
+in_process(Fun) ->
+ Parent = self(),
+ Pid = spawn_link(fun() -> process(Parent, Fun) end),
+ receive
+ {Pid, Result} -> Result;
+ {Pid, Class, Reason, Stack} ->
+ ST = try throw(x) catch throw:x -> erlang:get_stacktrace() end,
+ erlang:raise(Class, Reason, Stack ++ ST)
+ end.
+
+process(Parent, Fun) ->
+ try
+ Parent ! {self(), Fun()}
+ catch Class:Reason ->
+ Parent ! {self(), Class, Reason, erlang:get_stacktrace()}
+ end.
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index e318477234..59e82b7a57 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -1,7 +1,8 @@
+%% vim: tabstop=8:shiftwidth=4
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -94,8 +95,8 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
_Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used
%% table to save instances of parameterized objects,object sets
- asn1ct:create_ets_table(parameterized_objects,[named_table]),
- asn1ct:create_ets_table(inlined_objects,[named_table]),
+ asn1ct_table:new(parameterized_objects),
+ asn1ct_table:new(inlined_objects),
Terror = checkt(S,Types,[]),
@@ -144,17 +145,17 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
NewObjectSets,
[],[],[]),
?dbg("checko finished with errors:~n~p~n~n",[Oerror]),
- InlinedObjTuples = ets:tab2list(inlined_objects),
+ InlinedObjTuples = asn1ct_table:to_list(inlined_objects),
InlinedObjects = lists:map(Element2,InlinedObjTuples),
- ets:delete(inlined_objects),
- ParameterizedElems = ets:tab2list(parameterized_objects),
+ asn1ct_table:delete(inlined_objects),
+ ParameterizedElems = asn1ct_table:to_list(parameterized_objects),
ParObjectSets = lists:filter(fun({_OSName,objectset,_}) -> true;
(_)-> false end,ParameterizedElems),
ParObjectSetNames = lists:map(Element1,ParObjectSets),
ParTypes = lists:filter(fun({_TypeName,type,_}) -> true;
(_) -> false end, ParameterizedElems),
ParTypesNames = lists:map(Element1,ParTypes),
- ets:delete(parameterized_objects),
+ asn1ct_table:delete(parameterized_objects),
put(asn1_reference,undefined),
Exporterror = check_exports(S,S#state.module),
@@ -4176,7 +4177,7 @@ check_constraint(S,{'SizeConstraint',Lb}) ->
check_constraint(S,{'SingleValue', L}) when is_list(L) ->
F = fun(A) -> resolv_value(S,A) end,
- {'SingleValue',lists:map(F,L)};
+ {'SingleValue',lists:sort(lists:map(F,L))};
check_constraint(S,{'SingleValue', V}) when is_integer(V) ->
Val = resolv_value(S,V),
@@ -4398,22 +4399,22 @@ constraint_union(_S,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,Rest,Acc ++ AunionB);
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,Rest,Acc ++ AunionB);
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,Rest,Acc ++ AunionB);
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,Rest,Acc ++ AunionB);
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).
+ Acc.
constraint_union_sv(_S,SV) ->
Values=lists:map(fun({_,V})->V end,SV),
@@ -4466,63 +4467,33 @@ constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2=<Ub1->
constraint_union_vr([VR|Rest],Acc) ->
constraint_union_vr(Rest,[VR|Acc]).
-union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',VR={Lb,Ub}})
+union_sv_vr(_S,{'SingleValue',SV},VR)
when is_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}})
+ union_sv_vr(_S,{'SingleValue',[SV]},VR);
+union_sv_vr(_S,{'SingleValue',SV},{'ValueRange',{VLb,VUb}})
when is_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).
+ L = lists:sort(SV++[VLb,VUb]),
+ {Lb,L1} = case lists:member('MIN',L) of
+ true -> {'MIN',L--['MIN']}; % remove 'MIN' so it does not disturb
+ false -> {hd(L),tl(L)}
+ end,
+ Ub = case lists:member('MAX',L1) of
+ true -> 'MAX';
+ false -> lists:last(L1)
+ end,
+ case SV of
+ [H] -> H;
+ _ -> SV
+ end,
+ %% for now we through away the Singlevalues so that they don't disturb
+ %% in the code generating phase (the effective Valuerange is already
+ %% calculated. If we want to keep the Singlevalues as well for
+ %% use in code gen phases we need to introduce a new representation
+ %% like {'ValueRange',{Lb,Ub},[ListOfRanges|AntiValues|Singlevalues]
+ %% These could be used to generate guards which allows only the specific
+ %% values , not the full range
+ [{'ValueRange',{Lb,Ub}}].
-remove_val_from_list(Val,List) ->
- 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},
@@ -4923,12 +4894,7 @@ get_referenced(S,Emod,Ename,Pos) ->
%% May be an imported entity in module Emod or Emod may not exist
case asn1_db:dbget(Emod,'MODULE') of
undefined ->
- case parse_and_save(S,Emod) of
- ok ->
- get_referenced(S,Emod,Ename,Pos);
- _ ->
- throw({error,{asn1,{module_not_found,Emod}}})
- end;
+ throw({error,{asn1,{module_not_found,Emod}}});
_ ->
NewS = update_state(S,Emod),
get_imported(NewS,Ename,Emod,Pos)
@@ -4970,13 +4936,7 @@ get_imported(S,Name,Module,Pos) ->
parse_and_save(S,Imodule),
case asn1_db:dbget(Imodule,'MODULE') of
undefined ->
- case parse_and_save(S,Imodule) of
- ok ->
- %% check with cover
- get_referenced(S,Module,Name,Pos);
- _ ->
- throw({error,{asn1,{module_not_found,Imodule}}})
- end;
+ throw({error,{asn1,{module_not_found,Imodule}}});
Im when is_record(Im,module) ->
case is_exported(Im,Name) of
false ->
@@ -5116,16 +5076,16 @@ renamed_reference(S,#'Externaltypereference'{type=Name,module=Module}) ->
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 -> undefined;
- _ ->
- case ets:match(renamed_defs,{'$1',Name,Module}) of
+ case asn1ct_table:exists(renamed_defs) of
+ false -> undefined;
+ true ->
+ case asn1ct_table:match(renamed_defs, {'$1',Name,Module}) of
[] ->
- case ets:info(original_imports) of
- undefined ->
+ case asn1ct_table:exists(original_imports) of
+ false ->
undefined;
- _ ->
- case ets:match(original_imports,{Module,'$1'}) of
+ true ->
+ case asn1ct_table:match(original_imports, {Module,'$1'}) of
[] ->
undefined;
[[ImportsList]] ->
@@ -5253,6 +5213,9 @@ check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when is_integer(Num) ->
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,[{'NamedNumber',Id,{'Externalvaluereference',_,Mod,Name}}|T],Acc) ->
+ Val = dbget_ex(S,Mod,Name),
+ check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
check_int(_S,[],Acc) ->
lists:keysort(2,Acc).
@@ -6002,17 +5965,12 @@ tag_nums_root2([],Ext,Root2) ->
[0,Ext,Root2].
is_automatic_tagged_in_multi_file(Name) ->
- case ets:info(automatic_tags) of
- undefined ->
+ case asn1ct_table:exists(automatic_tags) of
+ false ->
%% this case when not multifile compilation
false;
- _ ->
-% case ets:member(automatic_tags,Name) of
- case ets:lookup(automatic_tags,Name) of
-% true ->
-% true;
-% _ ->
-% false
+ true ->
+ case asn1ct_table:lookup(automatic_tags, Name) of
[] -> false;
_ -> true
end
@@ -6033,17 +5991,25 @@ generate_automatic_tags1([H|T],[TagNo|TagNos]) when is_record(H,'ComponentType')
type={default,'IMPLICIT'},
form= 0 }]}, % PRIMITIVE
[H#'ComponentType'{typespec=NewTs}|generate_automatic_tags1(T,[TagNo+1|TagNos])];
-generate_automatic_tags1([ExtMark|T],[_TagNo|TagNos]) -> % EXTENSIONMARK
+generate_automatic_tags1([ExtMark = #'EXTENSIONMARK'{}|T],[_TagNo|TagNos]) ->
[ExtMark | generate_automatic_tags1(T,TagNos)];
+generate_automatic_tags1([H|T],TagList) -> % ExtensionAdditionGroup etc are just ignored
+ [H | generate_automatic_tags1(T,TagList)];
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]) ->
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Returns true if there is at least one ComponentType with a manually
+%% specified tag. No manual tag is indicated by typespec=#type{tag=[]}
+%% so we check if we find a tag =/= [] and return true in that case
+%% all other things in the componentlist like (EXTENSIONMARK,
+%% ExtensionAdditionGroup,...) except ComponentType is simply
+%% ignored/skipped
+any_manual_tag([#'ComponentType'{typespec=#type{tag=Tag}}|_Rest])
+ when Tag =/= []->
true;
+any_manual_tag([_|Rest]) ->
+ any_manual_tag(Rest);
any_manual_tag([]) ->
false.
diff --git a/lib/asn1/src/asn1ct_constructed_ber.erl b/lib/asn1/src/asn1ct_constructed_ber.erl
index 77b78dcac7..360de77663 100644
--- a/lib/asn1/src/asn1ct_constructed_ber.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber.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
@@ -1542,7 +1542,7 @@ mkfunname(Erule,TopType,Cname,WhatKind,DecOrEnc,Arity) ->
F = lists:concat(["fun '",DecOrEnc,"_",EType,"'/",Arity]),
{F, "?MODULE", F};
#'Externaltypereference'{module=Mod,type=EType} ->
- {lists:concat(["{'",Mod,"','",DecOrEnc,"_",EType,"'}"]),Mod,
+ {lists:concat(["fun '",Mod,"':'",DecOrEnc,"_",EType,"'/",Arity]),Mod,
lists:concat(["'",DecOrEnc,"_",EType,"'"])};
{constructed,bif} ->
F =
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index 243ff234a7..2c4b44996d 100644
--- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-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
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index e07680f10b..5f5138ef23 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -100,18 +100,26 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
case Ext of
{ext,_,NumExt} when NumExt > 0 ->
case extgroup_pos_and_length(CompList) of
- {extgrouppos,ExtGroupPos,ExtGroupLen} ->
- Elements = make_elements(ExtGroupPos+1,
- "Val1",lists:seq(1,ExtGroupLen)),
- emit([
- {next,val}," = case [X || X <- [",Elements,
- "],X =/= asn1_NOVALUE] of",nl,
- "[] -> ",{curr,val},";",nl,
- "_ -> setelement(",{asis,ExtGroupPos+1},",",
- {curr,val},",",
- "{extaddgroup,", Elements,"})",nl,
- "end,",nl]),
- asn1ct_name:new(val);
+ {extgrouppos,[]} -> % no extenstionAdditionGroup
+ ok;
+ {extgrouppos,ExtGroupPosLenList} ->
+ ExtGroupFun =
+ fun({ExtActualGroupPos,ExtGroupVirtualPos,ExtGroupLen}) ->
+ Elements =
+ make_elements(ExtGroupVirtualPos+1,
+ "Val1",
+ lists:seq(1,ExtGroupLen)),
+ emit([
+ {next,val}," = case [X || X <- [",Elements,
+ "],X =/= asn1_NOVALUE] of",nl,
+ "[] -> ",{curr,val},";",nl,
+ "_ -> setelement(",{asis,ExtActualGroupPos+1},",",
+ {curr,val},",",
+ "{extaddgroup,", Elements,"})",nl,
+ "end,",nl]),
+ asn1ct_name:new(val)
+ end,
+ lists:foreach(ExtGroupFun,ExtGroupPosLenList);
_ -> % no extensionAdditionGroup
ok
end,
@@ -279,9 +287,9 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{false,false,false}
end
end,
- NewCompList = wrap_compList(CompList),
+%% NewCompList = wrap_compList(CompList),
{AccTerm,AccBytes} =
- gen_dec_components_call(Erules,Typename,NewCompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
+ gen_dec_components_call(Erules,Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
case asn1ct_name:all(term) of
[] -> emit(MaybeComma2); % no components at all
_ -> emit({com,nl})
@@ -689,24 +697,28 @@ ext_length([],_,Acc) ->
Acc.
extgroup_pos_and_length(CompList) when is_list(CompList) ->
- noextgroup;
+ {extgrouppos,[]};
extgroup_pos_and_length({RootList,ExtList}) ->
- extgrouppos(ExtList,length(RootList)+1);
-extgroup_pos_and_length({Rl1,Ext,_Rl2}) ->
- extgrouppos(Ext,length(Rl1)+1).
-
-extgrouppos([{'ExtensionAdditionGroup',_Num}|T],Pos) ->
- extgrouppos(T,Pos,0);
-extgrouppos([_|T],Pos) ->
- extgrouppos(T,Pos+1);
-extgrouppos([],_) ->
- noextgroup.
-
-extgrouppos(['ExtensionAdditionGroupEnd'|_T],Pos,Len) ->
- {extgrouppos,Pos,Len};
-extgrouppos([_|T],Pos,Len) ->
- extgrouppos(T,Pos,Len+1).
-
+ ActualPos = length(RootList) +1,
+ %% position to get and deliver data in the record to the user
+ VirtualPos = ActualPos,
+ %% position to encode/decode the extaddgroup as an opentype sequence
+ extgrouppos(ExtList,ActualPos,VirtualPos,[]);
+extgroup_pos_and_length({RootList,ExtList,_Rl2}) ->
+ extgroup_pos_and_length({RootList,ExtList}).
+
+extgrouppos([{'ExtensionAdditionGroup',_Num}|T],ActualPos,VirtualPos,Acc) ->
+ extgrouppos(T,ActualPos,VirtualPos,0,Acc);
+extgrouppos([_|T],ActualPos,VirtualPos,Acc) ->
+ extgrouppos(T,ActualPos+1,VirtualPos+1,Acc);
+extgrouppos([],_,_,Acc) ->
+ {extgrouppos,lists:reverse(Acc)}.
+
+extgrouppos(['ExtensionAdditionGroupEnd'|T],ActualPos,VirtualPos,Len,Acc) ->
+ extgrouppos(T,ActualPos+1,VirtualPos+Len,[{ActualPos,VirtualPos,Len}|Acc]);
+extgrouppos([_|T],ActualPos,VirtualPos,Len,Acc) ->
+ extgrouppos(T,ActualPos,VirtualPos,Len+1,Acc).
+
gen_dec_extension_value(_) ->
@@ -817,19 +829,21 @@ add_textual_order1(Cs,NumIn) ->
end,
NumIn,Cs).
-gen_enc_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DynamicEnc,Ext) ->
- gen_enc_components_call(Erule,TopType,{Root1++Root2,ExtList},MaybeComma,DynamicEnc,Ext);
-gen_enc_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) ->
+gen_enc_components_call(Erule,TopType,{Root,ExtList},MaybeComma,DynamicEnc,Ext) ->
+ gen_enc_components_call(Erule,TopType,{Root,ExtList,[]},MaybeComma,DynamicEnc,Ext);
+gen_enc_components_call(Erule,TopType,CL={Root,ExtList,Root2},MaybeComma,DynamicEnc,Ext) ->
%% The type has extensionmarker
- Rpos = gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,noext),
+ Rpos = gen_enc_components_call1(Erule,TopType,Root++Root2,1,MaybeComma,DynamicEnc,noext),
case Ext of
{ext,_,ExtNum} when ExtNum > 0 ->
emit([nl,
",Extensions",nl]);
+
_ -> true
end,
%handle extensions
- NewExtList = wrap_extensionAdditionGroups(ExtList),
+ {extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL),
+ NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen),
gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,MaybeComma,DynamicEnc,Ext);
gen_enc_components_call(Erule,TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
%% The type has no extensionmarker
@@ -938,7 +952,7 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
Atype =
case Type of
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
- InnerType;
+ InnerType;
_ ->
asn1ct_gen:get_inner(Type#type.def)
end,
@@ -948,6 +962,7 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
emit(["?RT_PER:encode_open_type(dummy,?RT_PER:complete("]);
_ -> true
end,
+
case Atype of
{typefield,_} ->
case DynamicEnc of
@@ -1023,20 +1038,22 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
emit("))");
_ -> true
end.
-gen_dec_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
- gen_dec_components_call(Erule,TopType,{Root1++Root2,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals);
-gen_dec_components_call(Erule,TopType,{CompList,ExtList},MaybeComma,
+gen_dec_components_call(Erule,TopType,{Root,ExtList},MaybeComma,
DecInfObj,Ext,NumberOfOptionals) ->
+ gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},MaybeComma,DecInfObj,Ext,NumberOfOptionals);
+gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
%% The type has extensionmarker
- OptTable = create_optionality_table(CompList),
+
+ OptTable = create_optionality_table(Root1++Root2),
{Rpos,AccTerm,AccBytes} =
- gen_dec_components_call1(Erule,TopType, CompList, 1, OptTable,
+ gen_dec_components_call1(Erule,TopType, Root1++Root2, 1, OptTable,
MaybeComma,DecInfObj,noext,[],[],
NumberOfOptionals),
emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
asn1ct_name:new(bytes),
- NewExtList = wrap_extensionAdditionGroups(ExtList),
+ {extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL),
+ NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen),
{_Epos,AccTermE,AccBytesE} =
gen_dec_components_call1(Erule,TopType,NewExtList,Rpos, OptTable,
"",DecInfObj,Ext,[],[],NumberOfOptionals),
@@ -1233,8 +1250,7 @@ gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) ->
"} = ?RT_PER:decode_open_type(",{curr,bytes},
", []),",nl]),
emit([indent(2),"case (catch ObjFun(",
- {asis,Name},
- ",",{curr,tmpterm},",telltype,",
+ {asis,Name},",",{curr,tmpterm},",telltype,",
{asis,RestFieldNames},")) of", nl]),
emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
emit([indent(6),"exit({'Type not ",
@@ -1596,42 +1612,44 @@ 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}) ->
- {Root1,wrap_extensionAdditionGroups(Ext)};
-wrap_compList(CompList) ->
- CompList.
+%%wrap_compList({Root1,Ext,Root2}) ->
+%% {Root1,wrap_extensionAdditionGroups(Ext),Root2};
+%%wrap_compList({Root1,Ext}) ->
+%% {Root1,wrap_extensionAdditionGroups(Ext)};
+%%wrap_compList(CompList) ->
+%% CompList.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Will convert all componentTypes following 'ExtensionAdditionGroup'
%% up to the matching 'ExtensionAdditionGroupEnd' into one componentType
%% of type SEQUENCE with the componentTypes as components
%%
-wrap_extensionAdditionGroups(ExtCompList) ->
- wrap_extensionAdditionGroups(ExtCompList,[],0).
+wrap_extensionAdditionGroups(ExtCompList,ExtGroupPosLen) ->
+ wrap_extensionAdditionGroups(ExtCompList,ExtGroupPosLen,[],0,0).
-wrap_extensionAdditionGroups([{'ExtensionAdditionGroup',_Number}|Rest],Acc,0) ->
- {ExtGroupCompList=
- [#'ComponentType'{textual_order=TextPos}|_],
- ['ExtensionAdditionGroupEnd'|Rest2]} =
+wrap_extensionAdditionGroups([{'ExtensionAdditionGroup',_Number}|Rest],
+ [{ActualPos,_,_}|ExtGroupPosLenRest],Acc,_ExtAddGroupDiff,ExtGroupNum) ->
+ {ExtGroupCompList,['ExtensionAdditionGroupEnd'|Rest2]} =
lists:splitwith(fun(#'ComponentType'{}) -> true;
(_) -> false
end,
Rest),
- wrap_extensionAdditionGroups(Rest2,
+ wrap_extensionAdditionGroups(Rest2,ExtGroupPosLenRest,
[#'ComponentType'{
- name='ExtAddGroup', % FIXME: handles ony one ExtAddGroup
- typespec=#type{def=#'SEQUENCE'{
- extaddgroup=1,% FIXME: handles only one
+ name=list_to_atom("ExtAddGroup"++
+ integer_to_list(ExtGroupNum+1)),
+ typespec=#type{def=#'SEQUENCE'{
+ extaddgroup=ExtGroupNum+1,
components=ExtGroupCompList}},
- textual_order = TextPos,
- prop='OPTIONAL'}|Acc],length(ExtGroupCompList)-1);
-wrap_extensionAdditionGroups([H=#'ComponentType'{textual_order=Tord}|T],Acc,ExtAddGroupDiff) when is_integer(Tord) ->
- wrap_extensionAdditionGroups(T,[H#'ComponentType'{
- textual_order=Tord - ExtAddGroupDiff}|Acc],ExtAddGroupDiff);
-wrap_extensionAdditionGroups([H|T],Acc,ExtAddGroupDiff) ->
- wrap_extensionAdditionGroups(T,[H|Acc],ExtAddGroupDiff);
-wrap_extensionAdditionGroups([],Acc,_) ->
+ textual_order = ActualPos,
+ prop='OPTIONAL'}|Acc],length(ExtGroupCompList)-1,
+ ExtGroupNum+1);
+wrap_extensionAdditionGroups([H=#'ComponentType'{textual_order=Tord}|T],
+ ExtAddGrpLenPos,Acc,ExtAddGroupDiff,ExtGroupNum) when is_integer(Tord) ->
+ wrap_extensionAdditionGroups(T,ExtAddGrpLenPos,[H#'ComponentType'{
+ textual_order=Tord - ExtAddGroupDiff}|Acc],ExtAddGroupDiff,ExtGroupNum);
+wrap_extensionAdditionGroups([H|T],ExtAddGrpLenPos,Acc,ExtAddGroupDiff,ExtGroupNum) ->
+ wrap_extensionAdditionGroups(T,ExtAddGrpLenPos,[H|Acc],ExtAddGroupDiff,ExtGroupNum);
+wrap_extensionAdditionGroups([],_,Acc,_,_) ->
lists:reverse(Acc).
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 0f8833f716..64a3555f62 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -129,28 +129,39 @@ pgen_types(Rtmod,Erules,N2nConvEnums,Module,[H|T]) ->
end,
pgen_types(Rtmod,Erules,N2nConvEnums,Module,T).
+%% Enumerated type with extension marker
pgen_n2nconversion(_Erules,#typedef{name=TypeName,typespec=#type{def={'ENUMERATED',{NN1,NN2}}}}) ->
NN = NN1 ++ NN2,
- pgen_name2numfunc(TypeName,NN),
- pgen_num2namefunc(TypeName,NN);
+ pgen_name2numfunc(TypeName,NN, extension_marker),
+ pgen_num2namefunc(TypeName,NN, extension_marker);
+%% Without extension marker
+pgen_n2nconversion(_Erules,#typedef{name=TypeName,typespec=#type{def={'ENUMERATED',NN}}}) ->
+ pgen_name2numfunc(TypeName,NN, no_extension_marker),
+ pgen_num2namefunc(TypeName,NN, no_extension_marker);
pgen_n2nconversion(_Erules,_) ->
true.
-pgen_name2numfunc(_TypeName,[]) ->
+pgen_name2numfunc(_TypeName,[], _) ->
true;
-pgen_name2numfunc(TypeName,[{Atom,Number}]) ->
+pgen_name2numfunc(TypeName,[{Atom,Number}], extension_marker) ->
+ emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,";",nl]),
+ emit(["name2num_",TypeName,"({asn1_enum, Num}) -> Num.",nl,nl]);
+pgen_name2numfunc(TypeName,[{Atom,Number}], _) ->
emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,".",nl,nl]);
-pgen_name2numfunc(TypeName,[{Atom,Number}|NNRest]) ->
+pgen_name2numfunc(TypeName,[{Atom,Number}|NNRest], EM) ->
emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,";",nl]),
- pgen_name2numfunc(TypeName,NNRest).
+ pgen_name2numfunc(TypeName,NNRest, EM).
-pgen_num2namefunc(_TypeName,[]) ->
+pgen_num2namefunc(_TypeName,[], _) ->
true;
-pgen_num2namefunc(TypeName,[{Atom,Number}]) ->
+pgen_num2namefunc(TypeName,[{Atom,Number}], extension_marker) ->
+ emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},";",nl]),
+ emit(["num2name_",TypeName,"(ExtensionNum) -> {asn1_enum, ExtensionNum}.",nl,nl]);
+pgen_num2namefunc(TypeName,[{Atom,Number}], _) ->
emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},".",nl,nl]);
-pgen_num2namefunc(TypeName,[{Atom,Number}|NNRest]) ->
+pgen_num2namefunc(TypeName,[{Atom,Number}|NNRest], EM) ->
emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},";",nl]),
- pgen_num2namefunc(TypeName,NNRest).
+ pgen_num2namefunc(TypeName,NNRest, EM).
pgen_objects(_,_,_,[]) ->
true;
@@ -169,7 +180,7 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) ->
pgen_objectsets(Rtmod,Erules,Module,T).
pgen_check_defaultval(Erules,Module) ->
- CheckObjects = ets:tab2list(check_functions),
+ CheckObjects = asn1ct_table:to_list(check_functions),
case get(asndebug) of
true ->
FileName = lists:concat([Module,".table"]),
@@ -1598,7 +1609,7 @@ gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->
NameList = [Cname|TopType],
Name = list2name(NameList ++ [check]),
emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
- ets:insert(check_functions,{Name,Type}),
+ asn1ct_table:insert(check_functions, {Name, Type}),
%% Must look for check functions in InnerType,
%% that may be referenced or internal defined
%% constructed types not used elsewhere.
@@ -1744,10 +1755,9 @@ lookahead_reference(#'Externaltypereference'{module=M,type=T}) ->
end.
insert_once(Table,Object) ->
- _Info = ets:info(Table),
- case ets:lookup(Table,element(1,Object)) of
+ case asn1ct_table:lookup(Table, element(1, Object)) of
[] ->
- ets:insert(Table,Object); %returns true
+ asn1ct_table:insert(Table, Object); %returns true
_ -> false
end.
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 781271bae7..3ccfca3784 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -419,7 +419,7 @@ gen_decode_selected(Erules,Type,FuncName) ->
" {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,
+ emit(["};",nl," Err -> exit({error,{selective_decode,Err}})",nl,
" end.",nl]).
gen_decode_selected_type(_Erules,TypeDef) ->
@@ -1834,7 +1834,7 @@ 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}).
+ asn1ct_table:insert(asn1_functab, {F}).
%% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding
%% and therefore we only filter away the ExtensionAdditionGroup start and end markers
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index b90a0adf81..bd5b81991d 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -321,19 +321,13 @@ effective_constr(_,[]) ->
[];
effective_constr('SingleValue',List) ->
SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)),
- % sort and remove duplicates
- SortedSVList = lists:sort(SVList),
- RemoveDup = fun([],_) ->[];
- ([H],_) -> [H];
- ([H,H|T],F) -> F([H|T],F);
- ([H|T],F) -> [H|F(T,F)]
- end,
-
- case RemoveDup(SortedSVList,RemoveDup) of
+ %% Sort and remove duplicates before generating SingleValue or ValueRange
+ %% In case of ValueRange, also check for 'MIN and 'MAX'
+ case lists:usort(SVList) of
[N] ->
[{'SingleValue',N}];
- L when is_list(L) ->
- [{'ValueRange',{hd(L),lists:last(L)}}]
+ L when is_list(L) ->
+ [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}]
end;
effective_constr('ValueRange',List) ->
LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List),
@@ -358,6 +352,10 @@ greatest_common_range2({_,Int},VR={_Lb,_Ub}) when is_integer(Int) ->
greatest_common_range2({_,L},{Lb,Ub}) when is_list(L) ->
Min = least_Lb([Lb|L]),
Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range2({Lb1,Ub1},{Lb2,Ub2}) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
[{'ValueRange',{Min,Max}}].
mk_vr([{Type,I}]) when is_atom(Type), is_integer(I) ->
@@ -1401,19 +1399,21 @@ get_object_field(Name,ObjectFields) ->
%% have been specified within a SEQUENCE, therefore we construct a fake sequence type here
%% so that we can generate code for it
extaddgroup2sequence(ExtList) ->
- extaddgroup2sequence(ExtList,[]).
+ extaddgroup2sequence(ExtList,0,[]).
-extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],Acc) ->
+extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],ExtNum,Acc) ->
Number = case Number0 of undefined -> 1; _ -> Number0 end,
{ExtGroupComps,['ExtensionAdditionGroupEnd'|T2]} =
lists:splitwith(fun(Elem) -> is_record(Elem,'ComponentType') end,T),
- extaddgroup2sequence(T2,[#'ComponentType'{
- name='ExtAddGroup',
- typespec=#type{def=#'SEQUENCE'{
- extaddgroup=Number,
- components=ExtGroupComps}},
- prop='OPTIONAL'}|Acc]);
-extaddgroup2sequence([C|T],Acc) ->
- extaddgroup2sequence(T,[C|Acc]);
-extaddgroup2sequence([],Acc) ->
+ extaddgroup2sequence(T2,ExtNum+1,
+ [#'ComponentType'{
+ name=list_to_atom("ExtAddGroup"++
+ integer_to_list(ExtNum+1)),
+ typespec=#type{def=#'SEQUENCE'{
+ extaddgroup=Number,
+ components=ExtGroupComps}},
+ prop='OPTIONAL'}|Acc]);
+extaddgroup2sequence([C|T],ExtNum,Acc) ->
+ extaddgroup2sequence(T,ExtNum,[C|Acc]);
+extaddgroup2sequence([],_,Acc) ->
lists:reverse(Acc).
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 1a0a0e211d..16eec92847 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -670,18 +670,13 @@ effective_constr(_,[]) ->
[];
effective_constr('SingleValue',List) ->
SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)),
- % sort and remove duplicates
- RemoveDup = fun([],_) ->[];
- ([H],_) -> [H];
- ([H,H|T],F) -> F([H|T],F);
- ([H|T],F) -> [H|F(T,F)]
- end,
-
- case RemoveDup(SVList,RemoveDup) of
+ %% Sort and remove duplicates before generating SingleValue or ValueRange
+ %% In case of ValueRange, also check for 'MIN and 'MAX'
+ case lists:usort(SVList) of
[N] ->
[{'SingleValue',N}];
- L when is_list(L) ->
- [{'ValueRange',{hd(L),lists:last(L)}}]
+ L when is_list(L) ->
+ [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}]
end;
effective_constr('ValueRange',List) ->
LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List),
@@ -704,6 +699,10 @@ greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when is_integer(Int) ->
greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when is_list(L) ->
Min = least_Lb([Lb|L]),
Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range([{_,{Lb1,Ub1}}],[{_,{Lb2,Ub2}}]) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
[{'ValueRange',{Min,Max}}].
@@ -1804,19 +1803,21 @@ dec_enumerated_cases([],_,_) ->
%% have been specified within a SEQUENCE, therefore we construct a fake sequence type here
%% so that we can generate code for it
extaddgroup2sequence(ExtList) ->
- extaddgroup2sequence(ExtList,[]).
+ extaddgroup2sequence(ExtList,0,[]).
-extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],Acc) ->
+extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],ExtNum,Acc) ->
Number = case Number0 of undefined -> 1; _ -> Number0 end,
{ExtGroupComps,['ExtensionAdditionGroupEnd'|T2]} =
lists:splitwith(fun(Elem) -> is_record(Elem,'ComponentType') end,T),
- extaddgroup2sequence(T2,[#'ComponentType'{
- name='ExtAddGroup',
- typespec=#type{def=#'SEQUENCE'{
- extaddgroup=Number,
- components=ExtGroupComps}},
- prop='OPTIONAL'}|Acc]);
-extaddgroup2sequence([C|T],Acc) ->
- extaddgroup2sequence(T,[C|Acc]);
-extaddgroup2sequence([],Acc) ->
+ extaddgroup2sequence(T2,ExtNum+1,
+ [#'ComponentType'{
+ name=list_to_atom("ExtAddGroup"++
+ integer_to_list(ExtNum+1)),
+ typespec=#type{def=#'SEQUENCE'{
+ extaddgroup=Number,
+ components=ExtGroupComps}},
+ prop='OPTIONAL'}|Acc]);
+extaddgroup2sequence([C|T],ExtNum,Acc) ->
+ extaddgroup2sequence(T,ExtNum,[C|Acc]);
+extaddgroup2sequence([],_,Acc) ->
lists:reverse(Acc).
diff --git a/lib/asn1/src/asn1ct_name.erl b/lib/asn1/src/asn1ct_name.erl
index a6aa4255cc..3ab6f7b0ed 100644
--- a/lib/asn1/src/asn1ct_name.erl
+++ b/lib/asn1/src/asn1ct_name.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,8 +20,7 @@
-module(asn1ct_name).
%%-compile(export_all).
--export([name_server_loop/1,
- start/0,
+-export([start/0,
stop/0,
push/1,
pop/1,
@@ -35,38 +34,50 @@
new/1]).
start() ->
- start_server(asn1_ns, asn1ct_name,name_server_loop,[[]]).
+ Parent = self(),
+ case get(?MODULE) of
+ undefined ->
+ put(?MODULE, spawn_link(fun() ->
+ Ref = monitor(process, Parent),
+ name_server_loop({Ref,Parent},[])
+ end)),
+ ok;
+ _Pid ->
+ already_started
+ end.
-stop() -> stop_server(asn1_ns).
+stop() ->
+ req(stop),
+ erase(?MODULE).
-name_server_loop(Vars) ->
+name_server_loop({Ref, Parent} = Monitor,Vars) ->
%% io:format("name -- ~w~n",[Vars]),
receive
{From,{current,Variable}} ->
- From ! {asn1_ns,get_curr(Vars,Variable)},
- name_server_loop(Vars);
+ From ! {?MODULE,get_curr(Vars,Variable)},
+ name_server_loop(Monitor,Vars);
{From,{pop,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(pop_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,pop_var(Vars,Variable));
{From,{push,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(push_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,push_var(Vars,Variable));
{From,{delete,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(delete_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,delete_var(Vars,Variable));
{From,{new,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(new_var(Vars,Variable));
+ From ! {?MODULE,done},
+ name_server_loop(Monitor,new_var(Vars,Variable));
{From,{prev,Variable}} ->
- From ! {asn1_ns,get_prev(Vars,Variable)},
- name_server_loop(Vars);
+ From ! {?MODULE,get_prev(Vars,Variable)},
+ name_server_loop(Monitor,Vars);
{From,{next,Variable}} ->
- From ! {asn1_ns,get_next(Vars,Variable)},
- name_server_loop(Vars);
+ From ! {?MODULE,get_next(Vars,Variable)},
+ name_server_loop(Monitor,Vars);
+ {'DOWN', Ref, process, Parent, Reason} ->
+ exit(Reason);
{From,stop} ->
- unregister(asn1_ns),
- From ! {asn1_ns,stopped},
- exit(normal)
+ From ! {?MODULE,stopped}
end.
active(V) ->
@@ -76,12 +87,16 @@ active(V) ->
end.
req(Req) ->
- asn1_ns ! {self(), Req},
- receive {asn1_ns, Reply} -> Reply end.
+ get(?MODULE) ! {self(), Req},
+ receive
+ {?MODULE, Reply} -> Reply
+ after 5000 ->
+ exit(name_server_timeout)
+ end.
pop(V) -> req({pop,V}).
push(V) -> req({push,V}).
-clear() -> req(stop), start().
+clear() -> stop(), start().
curr(V) -> req({current,V}).
new(V) -> req({new,V}).
delete(V) -> req({delete,V}).
@@ -209,25 +224,3 @@ get_next(Vars,Variable) ->
_ ->
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 ->
- case catch register(Name, spawn(Mod,Fun, Args)) of
- {'EXIT',{badarg,_}} ->
- start_server(Name,Mod,Fun,Args);
- _ ->
- ok
- end;
- _Pid ->
- already_started
- end.
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 224a535e87..7301f49085 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -1,7 +1,8 @@
+%% vim: tabstop=8:shiftwidth=4
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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,14 +82,15 @@ parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->
case Rest3 of
[{'::=',_L7}, {'BEGIN',_L8}|Rest4] ->
{Exports, Rest5} = parse_Exports(Rest4),
- {Imports, Rest6} = parse_Imports(Rest5),
+ {{imports, Imports}, Rest6} = parse_Imports(Rest5),
+ put({get(asn1_module), imports}, Imports),
{#module{ pos = L1,
name = ModuleIdentifier,
defid = [], % fix this
tagdefault = TagDefault,
extensiondefault = ExtensionDefault,
exports = Exports,
- imports = Imports},Rest6};
+ imports = {imports, Imports}}, Rest6};
_ -> throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
[got,get_token(hd(Rest3)),expected,"::= BEGIN"]}})
end;
@@ -717,12 +719,12 @@ parse_DefinedType(Tokens=[{typereference,L1,TypeName},
{'EXIT',_Reason} ->
Rest2 = [T2,T3|Rest],
{#type{def = #'Externaltypereference'{pos=L1,
- module=get(asn1_module),
+ module=resolve_module(TypeName),
type=TypeName}},Rest2};
{asn1_error,_} ->
Rest2 = [T2,T3|Rest],
{#type{def = #'Externaltypereference'{pos=L1,
- module=get(asn1_module),
+ module=resolve_module(TypeName),
type=TypeName}},Rest2};
Result ->
Result
@@ -735,7 +737,7 @@ parse_DefinedType([{typereference,L1,Module},{'.',_},{typereference,_,TypeName}|
parse_DefinedType([{typereference,L1,TypeName}|Rest]) ->
case is_pre_defined_class(TypeName) of
false ->
- {#type{def = #'Externaltypereference'{pos=L1,module=get(asn1_module),
+ {#type{def = #'Externaltypereference'{pos=L1,module=resolve_module(TypeName),
type=TypeName}},Rest};
_ ->
throw({asn1_error,
@@ -758,6 +760,23 @@ parse_SelectionType(Tokens) ->
[got,get_token(hd(Tokens)),expected,'identifier <']}}).
+resolve_module(Type) ->
+ Current = get(asn1_module),
+ Imports = get({Current, imports}),
+ resolve_module(Type, Current, Imports).
+
+resolve_module(_Type, Current, undefined) ->
+ Current;
+resolve_module(Type, Current, Imports) ->
+ case [Mod || #'SymbolsFromModule'{symbols = S, module = Mod} <- Imports,
+ #'Externaltypereference'{type = T} <- S,
+ Type == T] of
+ [#'Externaltypereference'{type = Mod}|_] -> Mod;
+ %% This allows the same symbol to be imported several times
+ %% which ought to be checked elsewhere and flagged as an error
+ [] -> Current
+ end.
+
%% --------------------------
@@ -1539,7 +1558,7 @@ parse_DefinedObjectSet([{typereference,L1,ModuleName},{'.',_},
{{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),
+ {{objectset,L1,#'Externaltypereference'{pos=L1,module=resolve_module(ObjSetName),
type=ObjSetName}},Rest};
parse_DefinedObjectSet(Tokens) ->
throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
@@ -3203,17 +3222,17 @@ prioritize_error(ErrList) ->
tref2Exttref(#typereference{pos=Pos,val=Name}) ->
#'Externaltypereference'{pos=Pos,
- module=get(asn1_module),
+ module=resolve_module(Name),
type=Name}.
tref2Exttref(Pos,Name) ->
#'Externaltypereference'{pos=Pos,
- module=get(asn1_module),
+ module=resolve_module(Name),
type=Name}.
identifier2Extvalueref(#identifier{pos=Pos,val=Name}) ->
#'Externalvaluereference'{pos=Pos,
- module=get(asn1_module),
+ module=resolve_module(Name),
value=Name}.
%% lookahead_assignment/1 checks that the next sequence of tokens
diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl
new file mode 100644
index 0000000000..a5eb6d0413
--- /dev/null
+++ b/lib/asn1/src/asn1ct_table.erl
@@ -0,0 +1,76 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(asn1ct_table).
+
+%% Table abstraction module for ASN.1 compiler
+
+-export([new/1]).
+-export([new/2]).
+-export([new_reuse/1]).
+-export([new_reuse/2]).
+-export([exists/1]).
+-export([size/1]).
+-export([insert/2]).
+-export([lookup/2]).
+-export([match/2]).
+-export([to_list/1]).
+-export([delete/1]). % TODO: Remove (since we run in a separate process)
+
+
+%% Always creates a new table
+new(Table) -> new(Table, []).
+new(Table, Options) ->
+ TableId = case get(Table) of
+ undefined ->
+ ets:new(Table, Options);
+ _ ->
+ delete(Table),
+ ets:new(Table, Options)
+ end,
+ put(Table, TableId).
+
+%% Only create it if it doesn't exist yet
+new_reuse(Table) -> new_reuse(Table, []).
+new_reuse(Table, Options) ->
+ not exists(Table) andalso new(Table, Options).
+
+exists(Table) -> get(Table) =/= undefined.
+
+size(Table) -> ets:info(get(Table), size).
+
+insert(Table, Tuple) -> ets:insert(get(Table), Tuple).
+
+lookup(Table, Key) -> ets:lookup(get(Table), Key).
+
+match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec).
+
+to_list(Table) -> ets:tab2list(get(Table)).
+
+delete(Tables) when is_list(Tables) ->
+ [delete(T) || T <- Tables],
+ true;
+delete(Table) when is_atom(Table) ->
+ case get(Table) of
+ undefined ->
+ true;
+ TableId ->
+ ets:delete(TableId),
+ erase(Table)
+ end.
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index d099376b1b..9013baef92 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,58 +25,58 @@
-include("asn1_records.hrl").
%-compile(export_all).
--export([get_type/3]).
--export([i_random/1]).
-
+-export([from_type/2]).
%% Generate examples of values ******************************
%%****************************************x
-get_type(M,Typename,Tellname) ->
+from_type(M,Typename) ->
case asn1_db:dbget(M,Typename) of
undefined ->
- {asn1_error,{not_found,{M,Typename}}};
+ {error,{not_found,{M,Typename}}};
Tdef when is_record(Tdef,typedef) ->
Type = Tdef#typedef.typespec,
- get_type(M,[Typename],Type,Tellname);
+ from_type(M,[Typename],Type);
+ Vdef when is_record(Vdef,valuedef) ->
+ from_value(Vdef);
Err ->
- {asn1_error,{other,Err}}
+ {error,{other,Err}}
end.
-get_type(M,Typename,Type,Tellname) when is_record(Type,type) ->
+from_type(M,Typename,Type) when is_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);
+ from_type(Emod,Etype);
{_,user} ->
- case Tellname of
- yes -> {Typename,get_type(M,InnerType,no)};
- no -> get_type(M,InnerType,no)
- end;
+ from_type(M,InnerType);
{notype,_} ->
true;
{primitive,bif} ->
- get_type_prim(Type,get_encoding_rule(M));
+ from_type_prim(Type,get_encoding_rule(M));
'ASN1_OPEN_TYPE' ->
case Type#type.constraint of
[#'Externaltypereference'{type=TrefConstraint}] ->
- get_type(M,TrefConstraint,no);
+ from_type(M,TrefConstraint);
_ ->
ERule = get_encoding_rule(M),
open_type_value(ERule)
end;
{constructed,bif} when Typename == ['EXTERNAL'] ->
- Val=get_type_constructed(M,Typename,InnerType,Type),
+ Val=from_type_constructed(M,Typename,InnerType,Type),
asn1rt_check:transform_to_EXTERNAL1994(Val);
{constructed,bif} ->
- get_type_constructed(M,Typename,InnerType,Type)
+ from_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'
+from_type(M,Typename,#'ComponentType'{name = Name,typespec = Type}) ->
+ from_type(M,[Name|Typename],Type);
+from_type(_,_,_) -> % 'EXTENSIONMARK'
undefined.
+from_value(#valuedef{type = #type{def = 'INTEGER'}, value = Val}) ->
+ Val.
+
get_inner(A) when is_atom(A) -> A;
get_inner(Ext) when is_record(Ext,'Externaltypereference') -> Ext;
get_inner({typereference,_Pos,Name}) -> Name;
@@ -93,7 +93,7 @@ get_inner(T) when is_tuple(T) ->
-get_type_constructed(M,Typename,InnerType,D) when is_record(D,type) ->
+from_type_constructed(M,Typename,InnerType,D) when is_record(D,type) ->
case InnerType of
'SET' ->
get_sequence(M,Typename,D);
@@ -132,7 +132,7 @@ 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)|
+ [from_type(M,Typename,H)|
get_components(M,Typename,T)];
get_components(_,_,[]) ->
[].
@@ -145,10 +145,10 @@ get_choice(M,Typename,Type) ->
{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)};
+ {C#'ComponentType'.name,from_type(M,Typename,C)};
CompList when is_list(CompList) ->
C = lists:nth(random(length(CompList)),CompList),
- {C#'ComponentType'.name,get_type(M,Typename,C,no)}
+ {C#'ComponentType'.name,from_type(M,Typename,C)}
end.
get_sequence_of(M,Typename,Type,TypeSuffix) ->
@@ -157,14 +157,14 @@ get_sequence_of(M,Typename,Type,TypeSuffix) ->
C = Type#type.constraint,
S = size_random(C),
NewTypeName = [TypeSuffix|Typename],
- gen_list(M,NewTypeName,Oftype,no,S).
+ gen_list(M,NewTypeName,Oftype,S).
-gen_list(_,_,_,_,0) ->
+gen_list(_,_,_,0) ->
[];
-gen_list(M,Typename,Oftype,Tellname,N) ->
- [get_type(M,Typename,Oftype,no)|gen_list(M,Typename,Oftype,Tellname,N-1)].
+gen_list(M,Typename,Oftype,N) ->
+ [from_type(M,Typename,Oftype)|gen_list(M,Typename,Oftype,N-1)].
-get_type_prim(D,Erule) ->
+from_type_prim(D,Erule) ->
C = D#type.constraint,
case D#type.def of
'INTEGER' ->
@@ -198,6 +198,7 @@ get_type_prim(D,Erule) ->
NN = [X||{X,_} <- NNew],
case NN of
[] ->
+ io:format(user, "Enum = ~p~n", [Enum]),
asn1_EMPTY;
_ ->
case C of
@@ -412,14 +413,20 @@ 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
+get_constraint(C, Key) ->
+ case lists:keyfind(Key, 1, C) of
+ false -> no;
+ {'ValueRange', {Lb, Ub}} -> {check_external(Lb), check_external(Ub)};
+ {'SizeConstraint', N} -> N;
+ {Key, Value} -> Value
end.
+check_external(ExtRef) when is_record(ExtRef, 'Externalvaluereference') ->
+ #'Externalvaluereference'{module = Emod, value = Evalue} = ExtRef,
+ from_type(Emod, Evalue);
+check_external(Value) ->
+ Value.
+
get_encoding_rule(M) ->
Mod =
if is_list(M) ->
diff --git a/lib/asn1/src/asn1rt_ber_bin_v2.erl b/lib/asn1/src/asn1rt_ber_bin_v2.erl
index 17e66f77c9..420e3e1d91 100644
--- a/lib/asn1/src/asn1rt_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1rt_ber_bin_v2.erl
@@ -610,8 +610,8 @@ match_tags(Vlist = [{T,_V}|_], [T]) ->
Vlist;
match_tags(Tlv, []) ->
Tlv;
-match_tags({Tag,_V},[T|_Tt]) ->
- {error,{asn1,{wrong_tag,{Tag,T}}}}.
+match_tags(Tlv = {Tag,_V},[T|_Tt]) ->
+ exit({error,{asn1,{wrong_tag,{{expected,T},{got,Tag,Tlv}}}}}).
cindex(Ix,Val,Cname) ->
diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl
index a124c7553d..85988aa21d 100644
--- a/lib/asn1/src/asn1rt_per_bin.erl
+++ b/lib/asn1/src/asn1rt_per_bin.erl
@@ -18,7 +18,6 @@
%%
%%
-module(asn1rt_per_bin).
-
%% encoding / decoding of PER aligned
-include("asn1_records.hrl").
@@ -57,7 +56,7 @@
encode_NumericString/2, decode_NumericString/2,
encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
]).
--export([complete_bytes/1, getbits/2, getoctets/2]).
+-export([complete_bytes/1, getbits/2, getoctets/2, minimum_bits/1]).
-define('16K',16384).
-define('32K',32768).
@@ -695,21 +694,28 @@ encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
{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}];
+ Range =< (1 bsl (255*8)) ->
+ Octs = binary:encode_unsigned(Val2),
+ RangeOcts = binary:encode_unsigned(Range - 1),
+ OctsLen = erlang:byte_size(Octs),
+ RangeOctsLen = erlang:byte_size(RangeOcts),
+ LengthBitsNeeded = minimum_bits(RangeOctsLen - 1),
+ [{bits, LengthBitsNeeded, OctsLen - 1}, {octets, Octs}];
true ->
exit({not_supported,{integer_range,Range}})
end;
encode_constrained_number(Range,Val) ->
exit({error,{asn1,{integer_range,Range,value,Val}}}).
+%% For some reason the minimum bits needed in the length field in encoding of
+%% constrained whole numbers must always be atleast 2?
+minimum_bits(N) when N < 4 -> 2;
+minimum_bits(N) when N < 8 -> 3;
+minimum_bits(N) when N < 16 -> 4;
+minimum_bits(N) when N < 32 -> 5;
+minimum_bits(N) when N < 64 -> 6;
+minimum_bits(N) when N < 128 -> 7;
+minimum_bits(_N) -> 8.
decode_constrained_number(Buffer,{Lb,Ub}) ->
Range = Ub - Lb + 1,
@@ -738,18 +744,12 @@ decode_constrained_number(Buffer,{Lb,Ub}) ->
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};
+ Range =< (1 bsl (255*8)) ->
+ OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)),
+ RangeOctLen = length(OList),
+ {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}),
+ {Octs, RestBytes} = getoctets_as_list(Bytes, Len),
+ {binary:decode_unsigned(binary:list_to_bin(Octs)), RestBytes};
true ->
exit({not_supported,{integer_range,Range}})
end,
diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
index c7ead680ce..46d4bcb065 100644
--- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
+++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.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
@@ -18,7 +18,6 @@
%%
%%
-module(asn1rt_per_bin_rt2ct).
-
%% encoding / decoding of PER aligned
-include("asn1_records.hrl").
@@ -605,19 +604,13 @@ encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
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];
+ Range =< (1 bsl (255*8)) ->
+ Octs = binary:encode_unsigned(Val2),
+ RangeOcts = binary:encode_unsigned(Range - 1),
+ OctsLen = erlang:byte_size(Octs),
+ RangeOctsLen = erlang:byte_size(RangeOcts),
+ LengthBitsNeeded = asn1rt_per_bin:minimum_bits(RangeOctsLen - 1),
+ [10,LengthBitsNeeded,OctsLen-1,20,OctsLen,Octs];
true ->
exit({not_supported,{integer_range,Range}})
end;
@@ -661,18 +654,12 @@ decode_constrained_number(Buffer,{Lb,_Ub},Range) ->
getoctets(Buffer,1);
Range =< 65536 ->
getoctets(Buffer,2);
- Range =< 16#1000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,3}),
- {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#100000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,4}),
- {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#10000000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,5}),
- {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
+ Range =< (1 bsl (255*8)) ->
+ OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)),
+ RangeOctLen = length(OList),
+ {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}),
+ {Octs, RestBytes} = getoctets_as_bin(Bytes, Len),
+ {binary:decode_unsigned(Octs), RestBytes};
true ->
exit({not_supported,{integer_range,Range}})
end,
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index 7ecd544d4b..6e6374baf1 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The 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,11 +28,10 @@ MODULES= \
h323test \
choice_extension \
ber_decode_error \
- testExternal \
testPrim \
- testPrimStrings \
+ testPrimStrings \
testCompactBitString \
- testPrimExternal \
+ testPrimExternal \
testChoPrim \
testChoExtension \
testChoExternal \
@@ -86,15 +85,12 @@ MODULES= \
testMergeCompile \
testDeepTConstr \
testTimer \
- testRANAP \
testMegaco \
- testMvrasn6 \
testSeqSetDefaultVal \
testParamBasic \
testContextSwitchingTypes \
testTypeValueNotation \
testOpenTypeImplicitTag \
- testROSE \
testINSTANCE_OF \
test_partial_incomplete_decode \
testDER \
@@ -108,7 +104,6 @@ MODULES= \
test_inline \
testTcapsystem \
testNBAPsystem \
- test_bad_values \
test_compile_options \
testDoubleEllipses \
test_modified_x420 \
@@ -118,16 +113,9 @@ MODULES= \
asn1_app_test \
asn1_appup_test \
asn1_wrapper \
- asn1_SUITE \
- asn1_bin_SUITE \
- asn1_bin_v2_SUITE
+ asn1_SUITE
SUITE= asn1_SUITE.erl
-SUITE_BIN= asn1_bin_SUITE.erl
-SUITE_BIN_V2= asn1_bin_v2_SUITE.erl
-SUITE_SRC= asn1_SUITE.erl.src
-SUITE_BIN_SRC= asn1_bin_SUITE.erl.src
-SUITE_BIN_V2_SRC= asn1_bin_SUITE.erl.src
ERL_FILES= $(MODULES:%=%.erl)
@@ -156,30 +144,10 @@ $(EMAKEFILE): $(ERL_FILES) $(HRL_FILES)
tests debug opt: $(SUITE) $(SUITE_BIN) $(SUITE_BIN_V2) $(EMAKEFILE)
clean:
- rm -f $(SUITE) $(SUITE_BIN) $(SUITE_BIN_V2)
rm -f core
docs:
-#-----------------------------------------------------
-# Special Targets
-#-----------------------------------------------------
-$(SUITE): $(SUITE_SRC)
- sed -e 's;%BIN%;;' -e 's;%PER%;per;' -e 's;%BER%;ber;' $< > $@
- cat asn1_common_SUITE.erl.src >> $@
- cat asn1_particular_SUITE.erl.src >> $@
-
-
-$(SUITE_BIN): $(SUITE_SRC)
- sed -e 's;%BIN%;bin_;' -e 's;%PER%;per_bin;' -e 's;%BER%;ber_bin;' $< > $@
- echo "common() -> []." >> $@
- cat asn1_bin_particular_SUITE.erl.src >> $@
-
-$(SUITE_BIN_V2): $(SUITE_SRC)
- sed -e 's;%BIN%;bin_v2_;' -e 's;%PER%;per_bin;' -e 's;%BER%;ber_bin_v2;' $< > $@
- echo "common() -> []." >> $@
- cat asn1_bin_v2_particular_SUITE.erl.src >> $@
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -188,17 +156,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/asn1_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_SUITE_data
- $(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 -R u+w $(RELSYSDIR)
- cd asn1_SUITE_data; tar cfh $(RELSYSDIR)/asn1_SUITE_data.tar *
- cd $(RELSYSDIR)/asn1_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar
- cd $(RELSYSDIR)/asn1_bin_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar
- cd $(RELSYSDIR)/asn1_bin_v2_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar
- rm $(RELSYSDIR)/asn1_SUITE_data.tar
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/asn1_SUITE_data"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) asn1.spec asn1.cover $(INSTALL_PROGS) "$(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"
+ rm "$(RELSYSDIR)/asn1_SUITE_data.tar"
release_docs_spec:
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
new file mode 100644
index 0000000000..56f31de638
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -0,0 +1,1533 @@
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(only_per(Func),
+ if Rule == per orelse Rule == per_bin -> Func;
+ true -> ok
+ end).
+-define(only_ber(Func),
+ if Rule == ber orelse Rule == ber_bin orelse Rule == ber_bin_v2 -> Func;
+ true -> ok
+ end).
+-define(only_uper(Func),
+ case Rule of
+ uper_bin -> Func;
+ _ -> ok
+ end).
+-define(only_per_nif(Func),
+ case {Rule, lists:member(optimize, Opts)} of
+ {per_bin, true} -> Func;
+ _ -> ok
+ end).
+-define(only_ber_nif(Func),
+ case {Rule, lists:member(nif, Opts)} of
+ {ber_bin_v2, true} -> Func;
+ _ -> ok
+ end).
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+
+%%------------------------------------------------------------------------------
+%% Suite definition
+%%------------------------------------------------------------------------------
+
+suite() -> [{ct_hooks, [ts_install_cth]}].
+
+all() ->
+ [{group, parallel},
+ {group, app_test},
+ {group, appup_test},
+
+ % TODO: Investigate parallel running of these:
+ testComment,
+ testName2Number,
+ ticket_7407,
+ ticket7904,
+
+ {group, performance}].
+
+groups() ->
+ [{compile, parallel([]),
+ [c_syntax,
+ c_string,
+ c_implicit_before_choice]},
+
+ {ber, parallel([]),
+ [ber_choiceinseq,
+ % Uses 'SOpttest'
+ {group, [], [ber_optional,
+ ber_optional_keyed_list]}]},
+
+ {app_test, [], [{asn1_app_test, all}]},
+
+ {appup_test, [], [{asn1_appup_test, all}]},
+
+ {parallel, parallel([]),
+ [{group, compile},
+ {group, ber},
+ % Uses 'P-Record', 'Constraints', 'MEDIA-GATEWAY-CONTROL'...
+ {group, [], [parse,
+ test_driver_load,
+ test_undecoded_rest,
+ test_inline,
+ specialized_decodes,
+ special_decode_performance,
+ testMegaco,
+ testConstraints,
+ testCompactBitString]},
+ default,
+ % Uses 'Def', 'MULTIMEDIA-SYSTEM-CONTROL', 'H323-MESSAGES', 'Prim',
+ % 'Real'
+ {group, [], [testPrim,
+ rtUI,
+ testPrimStrings,
+ testInvokeMod,
+ per,
+ ber_other,
+ h323test,
+ per_GeneralString]},
+ testChoPrim,
+ testChoExtension,
+ testChoOptional,
+ testChoOptionalImplicitTag,
+ testChoRecursive,
+ testChoTypeRefCho,
+ testChoTypeRefPrim,
+ testChoTypeRefSeq,
+ testChoTypeRefSet,
+ testDef,
+ testOpt,
+ testSeqDefault,
+ % Uses 'External'
+ {group, [], [testChoExternal,
+ testPrimExternal,
+ testSeqExtension,
+ testSeqExternal,
+ testSeqOfExternal,
+ testSeqOfTag,
+ testSeqTag,
+ testSetExtension,
+ testSetExternal,
+ testSetOfExternal,
+ testSetOfTag,
+ testSetTag]},
+ testSeqOptional,
+ testSeqPrim,
+ testSeqTypeRefCho,
+ % Uses 'SeqTypeRefPrim'
+ {group, [], [testSeqTypeRefPrim,
+ testTypeValueNotation]},
+ testSeqTypeRefSeq,
+ testSeqTypeRefSet,
+ % Uses 'SeqOf'
+ {group, [], [testSeqOf,
+ testSeqOfIndefinite]}, % Uses 'Mvrasn*'
+ testSeqOfCho,
+ testSetDefault,
+ testExtensionAdditionGroup,
+ testSetOptional,
+ testSetPrim,
+ testSetTypeRefCho,
+ testSetTypeRefPrim,
+ testSetTypeRefSeq,
+ testSetTypeRefSet,
+ testSetOf,
+ testSetOfCho,
+ testEnumExt,
+ value_test,
+ value_bad_enum_test,
+ testSeq2738,
+ % Uses 'Constructed'
+ {group, [], [constructed,
+ ber_decode_error]},
+ % Uses 'SeqSetIndefinite'
+ {group, [], [testSeqIndefinite,
+ testSetIndefinite]},
+ testChoiceIndefinite,
+ per_open_type,
+ testInfObjectClass,
+ testParameterizedInfObj,
+ testMergeCompile,
+ testobj,
+ testDeepTConstr,
+ testExport,
+ testImport,
+ % Uses 'ParamBasic'
+ {group, [], [testParamBasic,
+ testDER]},
+ testMvrasn6,
+ testContextSwitchingTypes,
+ testOpenTypeImplicitTag,
+ duplicate_tags,
+ testROSE,
+ testINSTANCE_OF,
+ testTCAP,
+ test_ParamTypeInfObj,
+ test_WS_ParamClass,
+ test_Defed_ObjectIdentifier,
+ testSelectionType,
+ testSSLspecs,
+ testNortel,
+ % Uses 'PKCS7'
+ {group, [], [test_modified_x420,
+ testX420]},
+ testTcapsystem,
+ testNBAPsystem,
+ test_compile_options,
+ testDoubleEllipses,
+ test_x691,
+ ticket_6143,
+ testExtensionAdditionGroup,
+ test_OTP_9688]},
+
+ {performance, [],
+ [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,
+ smp]}].
+
+parallel(Options) ->
+ case erlang:system_info(smp_support) andalso
+ erlang:system_info(schedulers) > 1 of
+ true -> [parallel|Options];
+ false -> Options
+ end.
+
+%%------------------------------------------------------------------------------
+%% Init/end
+%%------------------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ true = code:add_patha(PrivDir),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_testcase(Func, Config) ->
+ CaseDir = filename:join([?config(priv_dir, Config), ?MODULE, Func]),
+ ok = filelib:ensure_dir(filename:join([CaseDir, dummy_file])),
+ true = code:add_patha(CaseDir),
+
+ Dog = case Func of
+ testX420 -> test_server:timetrap({minutes, 90});
+ _ -> test_server:timetrap({minutes, 60})
+ end,
+ [{case_dir, CaseDir}, {watchdog, Dog}|Config].
+
+end_per_testcase(_Func, Config) ->
+ true = code:del_path(?config(case_dir, Config)),
+ test_server:timetrap_cancel(?config(watchdog, Config)).
+
+%%------------------------------------------------------------------------------
+%% Test runners
+%%------------------------------------------------------------------------------
+
+test(Config, TestF) ->
+ test(Config, TestF, [per,
+ per_bin,
+ {per_bin, [optimize]},
+ uper_bin,
+ ber,
+ ber_bin,
+ ber_bin_v2,
+ % TODO: {ber_bin_v2, [optimize, nif]} ?
+ {ber_bin_v2, [nif]}]).
+
+test(Config, TestF, Rules) ->
+ Fun = fun(C, R, O) ->
+ M = element(2, erlang:fun_info(TestF, module)),
+ F = element(2, erlang:fun_info(TestF, name)),
+ io:format("Running ~p:~p with ~p...~n", [M, F, {R, O}]),
+ try
+ TestF(C, R, O)
+ catch
+ Class:Reason ->
+ NewReason = {Reason, [{rule, R}, {options, O}]},
+ erlang:raise(Class, NewReason,
+ erlang:get_stacktrace())
+ end
+ end,
+ Result = [run_case(Config, Fun, rule(Rule), opts(Rule)) || Rule <- Rules],
+ case lists:usort(Result) of
+ [true|_Skips] -> true; % At least one test ran
+ Skips -> {skip, [R || {skip, R} <- Skips]} % All skipped
+ end.
+
+rule(A) when is_atom(A) -> A;
+rule({A, _Opts} ) -> A.
+
+opts(Rule) when is_atom(Rule) -> [];
+opts({_Rule, Opts}) -> Opts.
+
+run_case(Config, Fun, Rule, Opts) ->
+ CaseDir = ?config(case_dir, Config),
+ Dir = filename:join([CaseDir, join(Rule, Opts)]),
+ ok = filelib:ensure_dir(filename:join([Dir, dummy_file])),
+ replace_path(CaseDir, Dir),
+ NewConfig = lists:keyreplace(case_dir, 1, Config, {case_dir, Dir}),
+
+ % Run the actual test function
+ Result = Fun(NewConfig, Rule, Opts),
+
+ replace_path(Dir, CaseDir),
+ case Result of
+ {skip, _Reason} -> Result;
+ _ -> true
+ end.
+
+replace_path(PathA, PathB) ->
+ true = code:del_path(PathA),
+ true = code:add_patha(PathB).
+
+join(Rule, Opts) ->
+ string:join([atom_to_list(Rule)|lists:map(fun atom_to_list/1, Opts)], "_").
+
+case_dir([], _Dir) ->
+ exit(no_case_dir);
+case_dir([{case_dir, _}|Config], Dir) ->
+ [{case_dir, Dir}|Config];
+case_dir([C|Config], Opt) ->
+ [C|case_dir(Config, Opt)].
+
+%%------------------------------------------------------------------------------
+%% Test cases
+%%------------------------------------------------------------------------------
+
+testPrim(Config) -> test(Config, fun testPrim/3).
+testPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["Prim", "Real"], Config, [Rule|Opts]),
+ testPrim:bool(Rule),
+ testPrim:int(Rule),
+ testPrim:enum(Rule),
+ testPrim:obj_id(Rule),
+ testPrim:rel_oid(Rule),
+ testPrim:null(Rule),
+ testPrim:real(Rule).
+
+testCompactBitString(Config) -> test(Config, fun testCompactBitString/3).
+testCompactBitString(Config, Rule, Opts) ->
+ asn1_test_lib:compile("PrimStrings", Config,
+ [Rule, compact_bit_string|Opts]),
+ testCompactBitString:compact_bit_string(Rule),
+ ?only_uper(testCompactBitString:bit_string_unnamed(Rule)),
+ ?only_per(testCompactBitString:bit_string_unnamed(Rule)),
+ ?only_per_nif(testCompactBitString:ticket_7734(Rule)),
+ ?only_per_nif(asn1_test_lib:compile("Constraints", Config,
+ [Rule, compact_bit_string|Opts])),
+ ?only_per_nif(testCompactBitString:otp_4869(Rule)).
+
+testPrimStrings(Config) -> test(Config, fun testPrimStrings/3).
+testPrimStrings(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]),
+ testPrimStrings_cases(Rule),
+ ?only_ber(testPrimStrings:more_strings(Rule)).
+
+testPrimStrings_cases(Rule) ->
+ testPrimStrings:bit_string(Rule),
+ testPrimStrings:bit_string_unnamed(Rule),
+ testPrimStrings:octet_string(Rule),
+ testPrimStrings:numeric_string(Rule),
+ testPrimStrings:other_strings(Rule),
+ testPrimStrings:universal_string(Rule),
+ testPrimStrings:bmp_string(Rule),
+ testPrimStrings:times(Rule),
+ testPrimStrings:utf8_string(Rule).
+
+testPrimExternal(Config) -> test(Config, fun testPrimExternal/3).
+testPrimExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "PrimExternal"], Config,
+ [Rule|Opts]),
+ testPrimExternal:external(Rule),
+ ?only_ber_nif(asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
+ [Rule|Opts])),
+ ?only_ber_nif(testPrimStrings_cases(Rule)),
+ ?only_ber_nif(testPrimStrings:more_strings(Rule)).
+
+testChoPrim(Config) -> test(Config, fun testChoPrim/3).
+testChoPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoPrim", Config, [Rule|Opts]),
+ testChoPrim:bool(Rule),
+ testChoPrim:int(Rule).
+
+testChoExtension(Config) -> test(Config, fun testChoExtension/3).
+testChoExtension(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoExtension", Config, [Rule|Opts]),
+ testChoExtension:extension(Rule).
+
+testChoExternal(Config) -> test(Config, fun testChoExternal/3).
+testChoExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "ChoExternal"], Config, [Rule|Opts]),
+ testChoExternal:external(Rule).
+
+testChoOptional(Config) -> test(Config, fun testChoOptional/3).
+testChoOptional(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoOptional", Config, [Rule|Opts]),
+ testChoOptional:optional(Rule).
+
+testChoOptionalImplicitTag(Config) ->
+ test(Config, fun testChoOptionalImplicitTag/3,
+ [ber, ber_bin, ber_bin_v2]).
+testChoOptionalImplicitTag(Config, Rule, Opts) ->
+ %% Only meaningful for ber & co
+ asn1_test_lib:compile("ChoOptionalImplicitTag", Config, [Rule|Opts]),
+ testChoOptionalImplicitTag:optional(Rule).
+
+testChoRecursive(Config) -> test(Config, fun testChoRecursive/3).
+testChoRecursive(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoRecursive", Config, [Rule|Opts]),
+ testChoRecursive:recursive(Rule).
+
+testChoTypeRefCho(Config) -> test(Config, fun testChoTypeRefCho/3).
+testChoTypeRefCho(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoTypeRefCho", Config, [Rule|Opts]),
+ testChoTypeRefCho:choice(Rule).
+
+testChoTypeRefPrim(Config) -> test(Config, fun testChoTypeRefPrim/3).
+testChoTypeRefPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoTypeRefPrim", Config, [Rule|Opts]),
+ testChoTypeRefPrim:prim(Rule).
+
+testChoTypeRefSeq(Config) -> test(Config, fun testChoTypeRefSeq/3).
+testChoTypeRefSeq(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoTypeRefSeq", Config, [Rule|Opts]),
+ testChoTypeRefSeq:seq(Rule).
+
+testChoTypeRefSet(Config) -> test(Config, fun testChoTypeRefSet/3).
+testChoTypeRefSet(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoTypeRefSet", Config, [Rule|Opts]),
+ testChoTypeRefSet:set(Rule).
+
+testDef(Config) -> test(Config, fun testDef/3).
+testDef(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Def", Config, [Rule|Opts]),
+ testDef:main(Rule).
+
+testOpt(Config) -> test(Config, fun testOpt/3).
+testOpt(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Opt", Config, [Rule|Opts]),
+ testOpt:main(Rule).
+
+testEnumExt(Config) -> test(Config, fun testEnumExt/3).
+testEnumExt(Config, Rule, Opts) ->
+ asn1_test_lib:compile("EnumExt", Config, [Rule|Opts]),
+ testEnumExt:main(Rule).
+
+%% Test of OTP-2523 ENUMERATED with extensionmark.
+testSeqDefault(Config) -> test(Config, fun testSeqDefault/3).
+testSeqDefault(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqDefault", Config, [Rule|Opts]),
+ testSeqDefault:main(Rule).
+
+testSeqExtension(Config) -> test(Config, fun testSeqExtension/3).
+testSeqExtension(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SeqExtension"], Config,
+ [Rule|Opts]),
+ testSeqExtension:main(Rule).
+
+testSeqExternal(Config) -> test(Config, fun testSeqExternal/3).
+testSeqExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SeqExternal"], Config, [Rule|Opts]),
+ testSeqExternal:main(Rule).
+
+testSeqOptional(Config) -> test(Config, fun testSeqOptional/3).
+testSeqOptional(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqOptional", Config, [Rule|Opts]),
+ testSeqOptional:main(Rule).
+
+testSeqPrim(Config) -> test(Config, fun testSeqPrim/3).
+testSeqPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqPrim", Config, [Rule|Opts]),
+ testSeqPrim:main(Rule).
+
+%% Test of OTP-2738 Detect corrupt optional component.
+testSeq2738(Config) -> test(Config, fun testSeq2738/3).
+testSeq2738(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Seq2738", Config, [Rule|Opts]),
+ testSeq2738:main(Rule).
+
+testSeqTag(Config) -> test(Config, fun testSeqTag/3).
+testSeqTag(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SeqTag"], Config, [Rule|Opts]),
+ testSeqTag:main(Rule).
+
+testSeqTypeRefCho(Config) -> test(Config, fun testSeqTypeRefCho/3).
+testSeqTypeRefCho(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqTypeRefCho", Config, [Rule|Opts]),
+ testSeqTypeRefCho:main(Rule).
+
+testSeqTypeRefPrim(Config) -> test(Config, fun testSeqTypeRefPrim/3).
+testSeqTypeRefPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqTypeRefPrim", Config, [Rule|Opts]),
+ testSeqTypeRefPrim:main(Rule).
+
+testSeqTypeRefSeq(Config) -> test(Config, fun testSeqTypeRefSeq/3).
+testSeqTypeRefSeq(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqTypeRefSeq", Config, [Rule|Opts]),
+ testSeqTypeRefSeq:main(Rule).
+
+testSeqTypeRefSet(Config) -> test(Config, fun testSeqTypeRefSet/3).
+testSeqTypeRefSet(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqTypeRefSet", Config, [Rule|Opts]),
+ testSeqTypeRefSet:main(Rule).
+
+testSeqOf(Config) -> test(Config, fun testSeqOf/3).
+testSeqOf(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["SeqOf", "SeqOfEnum", "XSeqOf"], Config,
+ [Rule|Opts]),
+ testSeqOf:main(Rule).
+
+testSeqOfCho(Config) -> test(Config, fun testSeqOfCho/3).
+testSeqOfCho(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqOfCho", Config, [Rule|Opts]),
+ testSeqOfCho:main(Rule).
+
+testSeqOfIndefinite(Config) ->
+ test(Config, fun testSeqOfIndefinite/3,
+ [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [nif]}]).
+testSeqOfIndefinite(Config, Rule, Opts) ->
+ Files = ["Mvrasn-Constants-1", "Mvrasn-DataTypes-1", "Mvrasn-21-4",
+ "Mvrasn-20-4", "Mvrasn-19-4", "Mvrasn-18-4", "Mvrasn-17-4",
+ "Mvrasn-15-4", "Mvrasn-14-4", "Mvrasn-11-4", "SeqOf"],
+ asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
+ testSeqOfIndefinite:main().
+
+testSeqOfExternal(Config) -> test(Config, fun testSeqOfExternal/3).
+testSeqOfExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SeqOfExternal"], Config,
+ [Rule|Opts]),
+ testSeqOfExternal:main(Rule).
+
+testSeqOfTag(Config) -> test(Config, fun testSeqOfTag/3).
+testSeqOfTag(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SeqOfTag"], Config, [Rule|Opts]),
+ testSeqOfTag:main(Rule).
+
+testSetDefault(Config) -> test(Config, fun testSetDefault/3).
+testSetDefault(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetDefault", Config, [Rule|Opts]),
+ testSetDefault:main(Rule).
+
+testParamBasic(Config) -> test(Config, fun testParamBasic/3).
+testParamBasic(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ParamBasic", Config, [Rule|Opts]),
+ testParamBasic:main(Rule).
+
+testSetExtension(Config) -> test(Config, fun testSetExtension/3).
+testSetExtension(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SetExtension"], Config,
+ [Rule|Opts]),
+ testSetExtension:main(Rule).
+
+testSetExternal(Config) -> test(Config, fun testSetExternal/3).
+testSetExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SetExternal"], Config, [Rule|Opts]),
+ testSetExternal:main(Rule).
+
+testSetOptional(Config) -> test(Config, fun testSetOptional/3).
+testSetOptional(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetOptional", Config, [Rule|Opts]),
+ testSetOptional:ticket_7533(Rule),
+ testSetOptional:main(Rule).
+
+testSetPrim(Config) -> test(Config, fun testSetPrim/3).
+testSetPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetPrim", Config, [Rule|Opts]),
+ testSetPrim:main(Rule).
+
+testSetTag(Config) -> test(Config, fun testSetTag/3).
+testSetTag(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SetTag"], Config, [Rule|Opts]),
+ testSetTag:main(Rule).
+
+testSetTypeRefCho(Config) -> test(Config, fun testSetTypeRefCho/3).
+testSetTypeRefCho(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetTypeRefCho", Config, [Rule|Opts]),
+ testSetTypeRefCho:main(Rule).
+
+testSetTypeRefPrim(Config) -> test(Config, fun testSetTypeRefPrim/3).
+testSetTypeRefPrim(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetTypeRefPrim", Config, [Rule|Opts]),
+ testSetTypeRefPrim:main(Rule).
+
+testSetTypeRefSeq(Config) -> test(Config, fun testSetTypeRefSeq/3).
+testSetTypeRefSeq(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetTypeRefSeq", Config, [Rule|Opts]),
+ testSetTypeRefSeq:main(Rule).
+
+testSetTypeRefSet(Config) -> test(Config, fun testSetTypeRefSet/3).
+testSetTypeRefSet(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetTypeRefSet", Config, [Rule|Opts]),
+ testSetTypeRefSet:main(Rule).
+
+testSetOf(Config) -> test(Config, fun testSetOf/3).
+testSetOf(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetOf", Config, [Rule|Opts]),
+ testSetOf:main(Rule).
+
+testSetOfCho(Config) -> test(Config, fun testSetOfCho/3).
+testSetOfCho(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SetOfCho", Config, [Rule|Opts]),
+ testSetOfCho:main(Rule).
+
+testSetOfExternal(Config) -> test(Config, fun testSetOfExternal/3).
+testSetOfExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SetOfExternal"], Config,
+ [Rule|Opts]),
+ testSetOfExternal:main(Rule).
+
+testSetOfTag(Config) -> test(Config, fun testSetOfTag/3).
+testSetOfTag(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External", "SetOfTag"], Config, [Rule|Opts]),
+ testSetOfTag:main(Rule).
+
+c_syntax(Config) ->
+ DataDir = ?config(data_dir, Config),
+ [{error, _} = asn1ct:compile(filename:join(DataDir, F))
+ || F <-["Syntax",
+ "BadTypeEnding",
+ "BadValueAssignment1",
+ "BadValueAssignment2",
+ "BadValueSet",
+ "ChoiceBadExtension",
+ "EnumerationBadExtension",
+ "Example",
+ "Export1",
+ "MissingEnd",
+ "SequenceBadComma",
+ "SequenceBadComponentName",
+ "SequenceBadComponentType",
+ "SeqBadComma"]].
+
+c_string(Config) ->
+ test(Config, fun c_string/3, [per, per_bin, ber, ber_bin, ber_bin_v2]).
+c_string(Config, Rule, Opts) ->
+ asn1_test_lib:compile("String", Config, [Rule|Opts]).
+
+c_implicit_before_choice(Config) ->
+ test(Config, fun c_implicit_before_choice/3,
+ [ber, ber_bin, ber_bin_v2]).
+c_implicit_before_choice(Config, Rule, Opts) ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ {error, _R2} = asn1ct:compile(filename:join(DataDir, "CCSNARG3"),
+ [Rule, {outdir, CaseDir}|Opts]).
+
+parse(Config) ->
+ [asn1_test_lib:compile(M, Config, [abs]) || M <- test_modules()].
+
+per(Config) ->
+ test(Config, fun per/3, [per, per_bin, {per_bin, [optimize]}]).
+per(Config, Rule, Opts) ->
+ [module_test(M, Config, Rule, Opts) || M <- per_modules()].
+
+ber_other(Config) ->
+ test(Config, fun ber_other/3, [ber, ber_bin, ber_bin_v2]).
+ber_other(Config, Rule, Opts) ->
+ [module_test(M, Config, Rule, Opts) || M <- ber_modules()].
+
+
+module_test(M, Config, Rule, Opts) ->
+ asn1_test_lib:compile(M, Config, [Rule|Opts]),
+ case asn1ct:test(list_to_atom(M), [{i, ?config(case_dir, Config)}]) of
+ ok -> ok;
+ Error ->
+ erlang:error({test_failed, M, Opts, Error})
+ end.
+
+
+ber_choiceinseq(Config) ->
+ test(Config, fun ber_choiceinseq/3, [ber, ber_bin, ber_bin_v2]).
+ber_choiceinseq(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoiceInSeq", Config, [Rule|Opts]).
+
+ber_optional(Config) ->
+ test(Config, fun ber_optional/3, [ber, ber_bin, ber_bin_v2]).
+ber_optional(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SOpttest", Config, [Rule|Opts]),
+ V = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE},
+ {'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE},
+ {'C', asn1_NOVALUE, 111, asn1_NOVALUE}},
+ {ok, B} = asn1_wrapper:encode('SOpttest', 'S', V),
+ Bytes = lists:flatten(B),
+ V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes),
+ V = element(2, V2).
+
+ber_optional_keyed_list(Config) ->
+ test(Config, fun ber_optional_keyed_list/3, [ber, ber_bin]).
+ber_optional_keyed_list(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SOpttest", Config, [Rule, keyed_list|Opts]),
+ Vrecord = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE},
+ {'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE},
+ {'C', asn1_NOVALUE, 111, asn1_NOVALUE}},
+ V = [{a, [{scriptKey, 10}]},
+ {b, []},
+ {c, [{callingPartysCategory, 111}]}],
+ {ok, B} = asn1_wrapper:encode('SOpttest', 'S', V),
+ Bytes = lists:flatten(B),
+ V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes),
+ Vrecord = element(2, V2).
+
+%% records used by test-case default
+-record('Def1', {bool0,
+ bool1 = asn1_DEFAULT,
+ bool2 = asn1_DEFAULT,
+ bool3 = asn1_DEFAULT}).
+
+default(Config) -> test(Config, fun default/3).
+default(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Def", Config, [Rule|Opts]),
+ {ok, Bytes1} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true}),
+ {ok, {'Def1', true, false, false, false}} =
+ asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes1)),
+
+ {ok, Bytes2} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true,
+ bool2 = false}),
+ {ok, {'Def1', true, false, false, false}} =
+ asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes2)).
+
+value_test(Config) -> test(Config, fun value_test/3).
+value_test(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ObjIdValues", Config, [Rule|Opts]),
+ {ok, _} = asn1ct:test('ObjIdValues', 'ObjIdType',
+ 'ObjIdValues':'mobileDomainId'()).
+
+value_bad_enum_test(Config) ->
+ case ?MODULE of
+ asn1_SUITE ->
+ {error, _} = asn1ct:compile(?config(data_dir, Config)
+ ++ "BadEnumValue1",
+ [{outdir, ?config(case_dir, Config)}]);
+ _ -> {skip, "Runs in asn1_SUITE only"}
+ end.
+
+constructed(Config) ->
+ test(Config, fun constructed/3, [ber, ber_bin, ber_bin_v2]).
+constructed(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
+ {ok, B} = asn1_wrapper:encode('Constructed', 'S', {'S', false}),
+ [40, 3, 1, 1, 0] = lists:flatten(B),
+ {ok, B1} = asn1_wrapper:encode('Constructed', 'S2', {'S2', false}),
+ [40, 5, 48, 3, 1, 1, 0] = lists:flatten(B1),
+ {ok, B2} = asn1_wrapper:encode('Constructed', 'I', 10),
+ [136, 1, 10] = lists:flatten(B2).
+
+ber_decode_error(Config) ->
+ test(Config, fun ber_decode_error/3, [ber, ber_bin, ber_bin_v2]).
+ber_decode_error(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
+ ber_decode_error:run(Opts).
+
+h323test(Config) -> test(Config, fun h323test/3).
+h323test(Config, Rule, Opts) ->
+ Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES",
+ "MULTIMEDIA-SYSTEM-CONTROL"],
+ asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
+ h323test:run(Rule).
+
+per_GeneralString(Config) ->
+ test(Config, fun per_GeneralString/3, [per, per_bin]).
+per_GeneralString(Config, Rule, Opts) ->
+ asn1_test_lib:compile("MULTIMEDIA-SYSTEM-CONTROL", Config, [Rule|Opts]),
+ UI = [109, 64, 1, 57],
+ {ok, _V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
+ 'MultimediaSystemControlMessage', UI).
+
+per_open_type(Config) -> test(Config, fun per_open_type/3, [per, per_bin]).
+per_open_type(Config, Rule, Opts) ->
+ asn1_test_lib:compile("OpenType", Config, [Rule|Opts]),
+ {ok, _} = asn1ct:test('OpenType', 'Ot', {'Stype', 10, true}).
+
+testConstraints(Config) -> test(Config, fun testConstraints/3).
+testConstraints(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Constraints", Config, [Rule|Opts]),
+ asn1_test_lib:compile("LargeConstraints", Config, [Rule|Opts]),
+ testConstraints:int_constraints(Rule).
+
+
+testSeqIndefinite(Config) ->
+ test(Config, fun testSeqIndefinite/3, [ber, ber_bin, ber_bin_v2,
+ {ber_bin_v2, [nif]}]).
+testSeqIndefinite(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
+ testSeqIndefinite:main(Rule).
+
+
+testSetIndefinite(Config) ->
+ test(Config, fun testSetIndefinite/3, [ber, ber_bin, ber_bin_v2,
+ {ber_bin_v2, [nif]}]).
+testSetIndefinite(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
+ testSetIndefinite:main(Rule).
+
+
+testChoiceIndefinite(Config) ->
+ test(Config, fun testChoiceIndefinite/3, [ber, ber_bin, ber_bin_v2,
+ {ber_bin_v2, [nif]}]).
+testChoiceIndefinite(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ChoiceIndef", Config, [Rule|Opts]),
+ testChoiceIndefinite:main(Rule).
+
+testInfObjectClass(Config) -> test(Config, fun testInfObjectClass/3).
+testInfObjectClass(Config, Rule, Opts) ->
+ Files = ["ErrorClass", "InfClass"],
+ InfObjFiles = ["RANAPextract1", "InfObj", "MAP-ExtensionDataTypes",
+ "Objects", "INAPv2extract"],
+ RANAPFiles = ["RANAP-CommonDataTypes", "RANAP-Constants",
+ "RANAP-Containers", "RANAP-IEs", "RANAP-PDU-Contents",
+ "RANAP-PDU-Descriptions"],
+ asn1_test_lib:compile_all(Files ++ InfObjFiles ++ RANAPFiles, Config,
+ [Rule|Opts]),
+ testInfObjectClass:main(Rule),
+ testInfObj:main(Rule).
+
+testParameterizedInfObj(Config) ->
+ test(Config, fun testParameterizedInfObj/3).
+testParameterizedInfObj(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Param", Config, [Rule|Opts]),
+ testParameterizedInfObj:main(Rule).
+
+testMergeCompile(Config) -> test(Config, fun testMergeCompile/3).
+testMergeCompile(Config, Rule, Opts) ->
+ Files = ["MS.set.asn", "RANAPSET.set.asn1", "Mvrasn4.set.asn",
+ "Mvrasn6.set.asn"],
+ asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
+ testMergeCompile:main(Rule),
+ testMergeCompile:mvrasn(Rule).
+
+testobj(Config) -> test(Config, fun testobj/3).
+testobj(Config, Rule, Opts) ->
+ asn1_test_lib:compile("RANAP", Config, [Rule|Opts]),
+ asn1_test_lib:compile_erlang("testobj", Config, []),
+ ok = testobj:run(),
+ ok = testParameterizedInfObj:ranap(Rule).
+
+testDeepTConstr(Config) -> test(Config, fun testDeepTConstr/3).
+testDeepTConstr(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["TConstrChoice", "TConstr"], Config,
+ [Rule|Opts]),
+ testDeepTConstr:main(Rule).
+
+testInvokeMod(Config) -> test(Config, fun testInvokeMod/3).
+testInvokeMod(Config, Rule, Opts) ->
+ asn1_test_lib:compile("PrimStrings", Config, [Rule|Opts]),
+ {ok, _Result2} = 'PrimStrings':encode('Bs1', [1, 0, 1, 0]).
+
+testExport(Config) ->
+ case ?MODULE of
+ asn1_SUITE ->
+ {error, {asn1, _Reason}} =
+ asn1ct:compile(filename:join(?config(data_dir, Config),
+ "IllegalExport"),
+ [{outdir, ?config(case_dir, Config)}]);
+ _ ->
+ {skip, "Runs in asn1_SUITE only"}
+ end.
+
+testImport(Config) ->
+ test(Config, fun testImport/3, [ber, ber_bin, ber_bin_v2]).
+testImport(Config, Rule, Opts) ->
+ {error, _} = asn1ct:compile(filename:join(?config(data_dir, Config),
+ "ImportsFrom"),
+ [Rule, {outdir, ?config(priv_dir, Config)}
+ |Opts]).
+
+testMegaco(Config) -> test(Config, fun testMegaco/3).
+testMegaco(Config, Rule, Opts) ->
+ {ok, Module1, Module2} = testMegaco:compile(Config, Rule, Opts),
+ ok = testMegaco:main(Module1, Config),
+ ok = testMegaco:main(Module2, Config).
+
+testMvrasn6(Config) -> test(Config, fun testMvrasn6/3).
+testMvrasn6(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["Mvrasn-21-4", "Mvrasn-20-6", "Mvrasn-19-6",
+ "Mvrasn-15-6", "Mvrasn-18-6", "Mvrasn-14-6",
+ "Mvrasn-11-6"], Config, [Rule|Opts]).
+
+testContextSwitchingTypes(Config) ->
+ test(Config, fun testContextSwitchingTypes/3).
+testContextSwitchingTypes(Config, Rule, Opts) ->
+ asn1_test_lib:compile("ContextSwitchingTypes", Config, [Rule|Opts]),
+ testContextSwitchingTypes:test(Config).
+
+testTypeValueNotation(Config) -> test(Config, fun testTypeValueNotation/3).
+testTypeValueNotation(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["SeqTypeRefPrim", "ValueTest"], Config,
+ [Rule|Opts]),
+ testTypeValueNotation:main(Rule, Opts).
+
+testOpenTypeImplicitTag(Config) ->
+ test(Config, fun testOpenTypeImplicitTag/3).
+testOpenTypeImplicitTag(Config, Rule, Opts) ->
+ asn1_test_lib:compile("OpenTypeImplicitTag", Config, [Rule|Opts]),
+ testOpenTypeImplicitTag:main(Rule).
+
+duplicate_tags(Config) ->
+ case ?MODULE of
+ asn1_SUITE ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ {error, {asn1, [{error, {type, _, _, 'SeqOpt1Imp', {asn1, {duplicates_of_the_tags, _}}}}]}} =
+ asn1ct:compile(filename:join(DataDir, "SeqOptional2"),
+ [abs, {outdir, CaseDir}]);
+ _ ->
+ {skip, "Runs in asn1_SUITE only"}
+ end.
+
+rtUI(Config) -> test(Config, fun rtUI/3, [per, per_bin, ber,
+ ber_bin, ber_bin_v2]).
+rtUI(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Prim", Config, [Rule|Opts]),
+ {ok, _} = asn1rt:info('Prim').
+
+testROSE(Config) -> test(Config, fun testROSE/3).
+testROSE(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Remote-Operations-Merged.set.asn1", Config,
+ [Rule|Opts]).
+
+testINSTANCE_OF(Config) -> test(Config, fun testINSTANCE_OF/3).
+testINSTANCE_OF(Config, Rule, Opts) ->
+ asn1_test_lib:compile("INSTANCEOF.asn1", Config, [Rule|Opts]),
+ testINSTANCE_OF:main(Rule).
+
+testTCAP(Config) ->
+ test(Config, fun testTCAP/3,
+ [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [nif]}]).
+testTCAP(Config, Rule, Opts) ->
+ testTCAP:compile(Config, [Rule|Opts]),
+ testTCAP:test(Rule, Config),
+ case Rule of
+ ber_bin_v2 -> testTCAP:compile_asn1config(Config, [Rule, asn1config]),
+ testTCAP:test_asn1config();
+ _ -> ok
+ end.
+
+testDER(Config) ->
+ test(Config, fun testDER/3, [ber, ber_bin, ber_bin_v2]).
+testDER(Config, Rule, Opts) ->
+ asn1_test_lib:compile("DERSpec", Config, [Rule, der|Opts]),
+ testDER:test(),
+ asn1_test_lib:compile("ParamBasic", Config, [Rule, der|Opts]),
+ testParamBasic:main(der),
+ asn1_test_lib:compile("Default", Config, [Rule, der|Opts]),
+ testSeqSetDefaultVal:main(Rule).
+
+specialized_decodes(Config) ->
+ test(Config, fun specialized_decodes/3, [ber_bin_v2]).
+specialized_decodes(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["PartialDecSeq.asn",
+ "PartialDecSeq2.asn",
+ "PartialDecSeq3.asn",
+ "PartialDecMyHTTP.asn",
+ "MEDIA-GATEWAY-CONTROL.asn",
+ "P-Record"],
+ Config, [Rule, optimize, asn1config|Opts]),
+ test_partial_incomplete_decode:test(Config),
+ test_selective_decode:test().
+
+special_decode_performance(Config) ->
+ test(Config, fun special_decode_performance/3,
+ [{ber_bin, [optimize]}, {ber_bin_v2, [optimize, nif]}]).
+special_decode_performance(Config, Rule, Opts) ->
+ Files = ["MEDIA-GATEWAY-CONTROL", "PartialDecSeq"],
+ asn1_test_lib:compile_all(Files, Config, [Rule, asn1config|Opts]),
+ test_special_decode_performance:go(all).
+
+
+test_driver_load(Config) ->
+ test(Config, fun test_driver_load/3, [{per_bin, [optimize]}]).
+test_driver_load(Config, Rule, Opts) ->
+ asn1_test_lib:compile("P-Record", Config, [Rule|Opts]),
+ test_driver_load:test(5).
+
+test_ParamTypeInfObj(Config) ->
+ asn1_test_lib:compile("IN-CS-1-Datatypes", Config, [ber_bin]).
+
+test_WS_ParamClass(Config) ->
+ asn1_test_lib:compile("InformationFramework", Config, [ber_bin]).
+
+test_Defed_ObjectIdentifier(Config) ->
+ asn1_test_lib:compile("UsefulDefinitions", Config, [ber_bin]).
+
+testSelectionType(Config) -> test(Config, fun testSelectionType/3).
+testSelectionType(Config, Rule, Opts) ->
+ asn1_test_lib:compile("SelectionType", Config, [Rule|Opts]),
+ {ok, _} = testSelectionTypes:test().
+
+testSSLspecs(Config) ->
+ test(Config, fun testSSLspecs/3, [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [optimize]}]).
+testSSLspecs(Config, Rule, Opts) ->
+ ok = testSSLspecs:compile(Config,
+ [Rule, compact_bit_string, der|Opts]),
+ testSSLspecs:run(Rule),
+
+ case code:which(asn1ct) of
+ cover_compiled ->
+ ok;
+ _ ->
+ ok = testSSLspecs:compile_inline(Config, Rule),
+ ok = testSSLspecs:run_inline(Rule)
+ end.
+
+testNortel(Config) -> test(Config, fun testNortel/3).
+testNortel(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Nortel", Config, [Rule|Opts]).
+
+test_undecoded_rest(Config) -> test(Config, fun test_undecoded_rest/3).
+test_undecoded_rest(Config, Rule, Opts) ->
+ asn1_test_lib:compile("P-Record", Config, [Rule|Opts]),
+ ok = test_undecoded_rest:test([], Config),
+ asn1_test_lib:compile("P-Record", Config, [Rule,undec_rest|Opts]),
+ case Rule of
+ ber_bin_v2 -> ok;
+ _ -> test_undecoded_rest:test(undec_rest, Config)
+ end.
+
+test_inline(Config) ->
+ test(Config, fun test_inline/3, [ber, ber_bin, ber_bin_v2]).
+test_inline(Config, Rule, Opts) ->
+ case code:which(asn1ct) of
+ cover_compiled ->
+ {skip, "Not runnable when cover compiled"};
+ _ ->
+ test_inline:compile(Config, Opts),
+ test_inline:main(Config, Rule),
+ test_inline:inline1(Config, Rule, Opts),
+ test_inline:performance2()
+ end.
+
+testTcapsystem(Config) ->
+ test(Config, fun testTcapsystem/3, [ber, ber_bin, ber_bin_v2]).
+testTcapsystem(Config, Rule, Opts) ->
+ testTcapsystem:compile(Config, [Rule|Opts]).
+
+testNBAPsystem(Config) -> test(Config, fun testNBAPsystem/3,
+ [per, per_bin, {per_bin, [optimize]}]).
+testNBAPsystem(Config, Rule, Opts) ->
+ testNBAPsystem:compile(Config, [Rule|Opts]),
+ testNBAPsystem:test(Rule, Config).
+
+test_compile_options(Config) ->
+ case code:which(asn1ct) of
+ cover_compiled ->
+ {skip, "Not runnable when cover compiled"};
+ _ ->
+ ok = test_compile_options:wrong_path(Config),
+ ok = test_compile_options:path(Config),
+ ok = test_compile_options:noobj(Config),
+ ok = test_compile_options:record_name_prefix(Config),
+ ok = test_compile_options:verbose(Config),
+ ok = test_compile_options:warnings_as_errors(Config)
+ end.
+
+testDoubleEllipses(Config) -> test(Config, fun testDoubleEllipses/3).
+testDoubleEllipses(Config, Rule, Opts) ->
+ asn1_test_lib:compile("DoubleEllipses", Config, [Rule|Opts]),
+ testDoubleEllipses:main(Rule).
+
+test_modified_x420(Config) ->
+ Files = [filename:join(modified_x420, F) || F <- ["PKCS7",
+ "InformationFramework",
+ "AuthenticationFramework"]],
+ asn1_test_lib:compile_all(Files, Config, [der]),
+ test_modified_x420:test_io(Config).
+
+testX420(Config) ->
+ test(Config, fun testX420/3, [ber, ber_bin, ber_bin_v2]).
+testX420(Config, Rule, Opts) ->
+ testX420:compile(Rule, [der|Opts], Config),
+ ok = testX420:ticket7759(Rule, Config),
+ testX420:compile(Rule, Opts, Config).
+
+test_x691(Config) ->
+ test(Config, fun test_x691/3,
+ [per, per_bin, uper_bin, {per_bin, [optimize]}]).
+test_x691(Config, Rule, Opts) ->
+ Files = ["P-RecordA1", "P-RecordA2", "P-RecordA3"],
+ asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
+ test_x691:cases(Rule, case Rule of
+ uper_bin -> unaligned;
+ _ -> aligned
+ end),
+ asn1_test_lib:ticket_7708(Config, []),
+ asn1_test_lib:ticket_7763(Config).
+
+ticket_6143(Config) ->
+ ok = test_compile_options:ticket_6143(Config).
+
+testExtensionAdditionGroup(Config) ->
+ %% FIXME problems with automatic tags [ber_bin], [ber_bin, optimize]
+ test(Config, fun testExtensionAdditionGroup/3,
+ [per_bin, {per_bin, [optimize]}, uper_bin]).
+testExtensionAdditionGroup(Config, Rule, Opts) ->
+ asn1_test_lib:compile("Extension-Addition-Group", Config, [Rule|Opts]),
+ asn1_test_lib:compile_erlang("extensionAdditionGroup", Config,
+ [debug_info]),
+ extensionAdditionGroup:run([Rule|Opts]),
+ extensionAdditionGroup:run2([Rule|Opts]),
+ asn1_test_lib:compile("EUTRA-RRC-Definitions", Config, [Rule, {record_name_prefix, "RRC-"}|Opts]),
+ extensionAdditionGroup:run3([Rule|Opts]).
+
+% 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() ->
+ ["BitStr",
+ "CAP",
+ "CommonDataTypes",
+ "Constraints",
+ "ContextSwitchingTypes",
+ "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
+ "Enum",
+ "From",
+ "H235-SECURITY-MESSAGES",
+ "H323-MESSAGES",
+ "Import",
+ "Int",
+ "MAP-commonDataTypes",
+ "Null",
+ "Octetstr",
+ "One",
+ "P-Record",
+ "P",
+ "Person",
+ "PrimStrings",
+ "Real",
+ "XSeq",
+ "XSeqOf",
+ "XSet",
+ "XSetOf",
+ "String",
+ "SwCDR",
+ "Time",
+ "SeqSetLib", % must be compiled before Seq and Set
+ "Seq",
+ "Set",
+ "SetOf",
+ "SeqOf",
+ "Prim",
+ "Cho",
+ "Def",
+ "Opt",
+ "ELDAPv3",
+ "LDAP"].
+
+test_OTP_9688(Config) ->
+ PrivDir = ?config(case_dir, Config),
+ Data = "
+OTP-9688 DEFINITIONS ::= BEGIN
+
+ foo INTEGER ::= 1
+ bar INTEGER ::= 42
+
+ Baz ::= INTEGER {x-y-z1(foo), x-y-z2(bar)}
+ Qux ::= SEQUENCE {flerpInfo SEQUENCE {x INTEGER (-10 | -9 | (0..4))} OPTIONAL}
+
+END
+",
+ File = filename:join(PrivDir, "OTP-9688.asn1"),
+ ok = file:write_file(File, Data),
+ %% Does it compile with changes to asn1ct_check and asn1ct_gen_per_rt2ct?
+ %% (see ticket)
+ ok = asn1ct:compile(File, [{outdir, PrivDir}]).
+
+
+timer_compile(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"],
+ Config, [Rule|Opts]).
+
+testTimer_ber(suite) -> [];
+testTimer_ber(Config) ->
+ timer_compile(Config,ber,[]),
+ testTimer:go(Config,ber).
+
+testTimer_ber_bin(suite) -> [];
+testTimer_ber_bin(Config) ->
+ timer_compile(Config,ber_bin,[]),
+ testTimer:go(Config,ber_bin).
+
+testTimer_ber_bin_opt(suite) -> [];
+testTimer_ber_bin_opt(Config) ->
+ timer_compile(Config,ber_bin,[optimize]),
+ testTimer:go(Config,ber_bin).
+
+testTimer_ber_bin_opt_driver(suite) -> [];
+testTimer_ber_bin_opt_driver(Config) ->
+ timer_compile(Config,ber_bin,[optimize,driver]),
+ testTimer:go(Config,ber_bin).
+
+testTimer_per(suite) -> [];
+testTimer_per(Config) ->
+ timer_compile(Config,per,[]),
+ testTimer:go(Config,per).
+
+testTimer_per_bin(suite) -> [];
+testTimer_per_bin(Config) ->
+ timer_compile(Config,per_bin,[]),
+ testTimer:go(Config,per_bin).
+
+testTimer_per_bin_opt(suite) -> [];
+testTimer_per_bin_opt(Config) ->
+ timer_compile(Config,per_bin,[optimize]),
+ testTimer:go(Config,per_bin).
+
+
+testTimer_uper_bin(suite) -> [];
+testTimer_uper_bin(Config) ->
+ timer_compile(Config,uper_bin,[]),
+ {comment,_} = testTimer:go(Config,uper_bin).
+
+%% Test of multiple-line comment, OTP-8043
+testComment(suite) -> [];
+testComment(Config) ->
+ asn1_test_lib:compile("Comment", Config, []),
+ {ok,Enc} = asn1_wrapper:encode('Comment','Seq',{'Seq',12,true}),
+ {ok,{'Seq',12,true}} = asn1_wrapper:decode('Comment','Seq',Enc),
+ ok.
+
+testName2Number(suite) -> [];
+testName2Number(Config) ->
+ N2NOptions = [{n2n,Type} || Type <- ['CauseMisc', 'CauseProtocol',
+ 'CauseRadioNetwork',
+ 'CauseTransport','CauseNas']],
+ asn1_test_lib:compile("S1AP-IEs", Config, N2NOptions),
+
+ 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'),
+ 'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5),
+
+ %% OTP-10144
+ %% Test that n2n option generates name2num and num2name functions supporting
+ %% values not within the extension root if the enumeration type has an
+ %% extension marker.
+ N2NOptionsExt = [{n2n, 'NoExt'}, {n2n, 'Ext'}, {n2n, 'Ext2'}],
+ asn1_test_lib:compile("EnumN2N", Config, N2NOptionsExt),
+ %% Previously, name2num and num2name was not generated if the type didn't
+ %% have an extension marker:
+ 0 = 'EnumN2N':name2num_NoExt('blue'),
+ 2 = 'EnumN2N':name2num_NoExt('green'),
+ blue = 'EnumN2N':num2name_NoExt(0),
+ green = 'EnumN2N':num2name_NoExt(2),
+
+ %% Test enumeration extension:
+ 7 = 'EnumN2N':name2num_Ext2('orange'),
+ orange = 'EnumN2N':num2name_Ext2(7),
+ %% 7 is not defined in Ext, only in Ext2.
+ {asn1_enum, 7} = 'EnumN2N':num2name_Ext(7),
+ 7 = 'EnumN2N':name2num_Ext({asn1_enum, 7}),
+ 42 = 'EnumN2N':name2num_Ext2({asn1_enum, 42}),
+ ok.
+
+ticket_7407(Config) ->
+ asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper_bin]),
+ asn1_test_lib:ticket_7407_code(true),
+
+ asn1_test_lib:compile("EUTRA-extract-7407", Config,
+ [uper_bin, no_final_padding]),
+ asn1_test_lib:ticket_7407_code(false).
+
+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]),
+
+ Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ ok = testNBAPsystem:compile(Config, [per_bin, optimize]),
+
+ enc_dec(NumOfProcs,Msg,2),
+
+ N = 10000,
+
+ {Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
+ {Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
+
+ ok = testNBAPsystem:compile(Config, [ber_bin, optimize, nif]),
+ {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
+
+ {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]~n"
+ "Encode/decode time sequential: ~p [microsecs]",
+ [NumOfProcs,Time1+Time3,Time1S+Time3S]))};
+ false ->
+ {skipped,"No smp support"}
+ end.
+
+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),
+
+ Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config],
+ [per_bin, optimize]),
+ 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) ->
+
+ Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ 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 pem_performance:cert_pem/0,N,S}).
+
+dsa_pem_performance(Config) when is_list(Config) ->
+ dsa_pem_performance({100000, 32});
+dsa_pem_performance({N,S}) ->
+ nif_vs_erlang_performance({fun pem_performance: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]).
+
+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;
+worker_loop(N, Msg) ->
+ {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions',
+ 'NBAP-PDU',
+ Msg),
+ {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
+ 'NBAP-PDU',
+ B),
+ worker_loop(N - 1, Msg).
+
+
+pforeach(Fun, List) ->
+ pforeach(Fun, List, []).
+pforeach(Fun, [], [{Pid,Ref}|Pids]) ->
+ receive
+ {'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}).
+
+ticket7904(Config) ->
+ asn1_test_lib:compile("RANAPextract1", Config, [per_bin, optimize]),
+
+ Val1 = #'InitiatingMessage'{procedureCode=1,
+ criticality=ignore,
+ value=#'Iu-ReleaseCommand'{
+ first=13,
+ second=true}},
+
+ {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1),
+ {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1).
diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src
deleted file mode 100644
index 124ee2d2bb..0000000000
--- a/lib/asn1/test/asn1_SUITE.erl.src
+++ /dev/null
@@ -1,2372 +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%').
--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() ->
- [
- {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.
-
-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).
-
-
-sequence(suite) -> [{sequence,all}].
-
-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').
-
-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),
- ?line ok = test_compile_options:warnings_as_errors(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),
- ?line ok = extensionAdditionGroup:run2(Erule),
- ?line ok = asn1ct:compile(filename:join(DataDir,"EUTRA-RRC-Definitions"),Erule ++ [{record_name_prefix,"RRC-"},{outdir,PrivDir}]),
- ?line ok = extensionAdditionGroup:run3(Erule)
- end,
- ?line [DoIt(Rule)|| Rule <- [[per_bin],[per_bin,optimize],[uper_bin]]],
- %% FIXME problems with automatic tags [ber_bin],[ber_bin,optimize]
- ?line code:set_path(Path).
-
-
-
-% parse_modules() ->
-% ["ImportsFrom"].
-
-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",
- "CAP",
- "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"
- ].
-
-
diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py
index b18c29bd89..87243121f7 100644
--- a/lib/asn1/test/asn1_SUITE_data/Constraints.py
+++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py
@@ -4,9 +4,14 @@ BEGIN
-- Single Value
SingleValue ::= INTEGER (1)
SingleValue2 ::= INTEGER (1..20)
+predefined INTEGER ::= 1
+SingleValue3 ::= INTEGER (predefined | 5 | 10)
Range2to19 ::= INTEGER (1<..<20)
Range10to20 ::= INTEGER (10..20)
ContainedSubtype ::= INTEGER (INCLUDES Range10to20)
+-- Some ranges for additional constrained number testing.
+LongLong ::= INTEGER (0..18446744073709551615)
+Range256to65536 ::= INTEGER (256..65536)
FixedSize ::= OCTET STRING (SIZE(10))
FixedSize2 ::= OCTET STRING (SIZE(10|20))
VariableSize ::= OCTET STRING (SIZE(1..10))
@@ -51,6 +56,7 @@ Thing ::= INTEGER {fred (0),fred2 (1),fred3 (2)}
AnotherThing ::= Thing (fred | fred2)
I ::= INTEGER (0|15..269) -- OTP-5457
+X1 ::= INTEGER (1..4 | 8 | 10 | 20) -- OTP-9946
-- OTP-5511
diff --git a/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn b/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn
index 5a5d310729..5a5d310729 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn
+++ b/lib/asn1/test/asn1_SUITE_data/DirectoryAbstractService.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1
new file mode 100644
index 0000000000..a724f2f3f5
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1
@@ -0,0 +1,25 @@
+EnumN2N DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+NoExt ::= ENUMERATED {
+ blue(0),
+ red(1),
+ green(2)
+}
+
+Ext ::= ENUMERATED {
+ blue(0),
+ red(1),
+ green(2),
+ ...
+}
+
+Ext2 ::= ENUMERATED {
+ blue(0),
+ red(1),
+ green(2),
+ ...,
+ orange(7)
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
index fc244c30a2..cacef8b922 100644
--- a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
@@ -79,4 +79,22 @@ Ax3 ::= SEQUENCE {
}
-- { a 253, b TRUE, s {sa 17, sb TRUE, sextaddgroup 11}}
+
+-- This is to test the case with more than one ExtensionAdditionGroup
+-- which did not work before
+
+AS-Config ::= SEQUENCE {
+ a INTEGER,
+ b BOOLEAN,
+ c OCTET STRING,
+ ...,
+ [[ sourceSystemInformationBlockType1Ext OCTET STRING OPTIONAL,
+ sourceOtherConfig-r9 INTEGER
+ ]],
+ [[ sourceSCellConfigList-r10 OCTET STRING OPTIONAL
+ ]]
+}
+
+
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn b/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn
index ef236e98a9..ef236e98a9 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn
+++ b/lib/asn1/test/asn1_SUITE_data/InformationFramework.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/LDAP.asn1 b/lib/asn1/test/asn1_SUITE_data/LDAP.asn1
index 4d845942e1..4d845942e1 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/LDAP.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/LDAP.asn1
diff --git a/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py b/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py
new file mode 100644
index 0000000000..68c7616b62
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py
@@ -0,0 +1,9 @@
+LargeConstraints DEFINITIONS ::=
+BEGIN
+
+-- Maximum number that can be encoded as a constrained whole number: 1 bsl (255*8)
+-- The number of octets needed to represent a number cannot be more than 255
+-- As the length field is encoded as a 8-bit bitfield.
+RangeMax ::= INTEGER (1..126238304966058622268417487065116999845484776053576109500509161826268184136202698801551568013761380717534054534851164138648904527931605160527688095259563605939964364716019515983399209962459578542172100149937763938581219604072733422507180056009672540900709554109516816573779593326332288314873251559077853068444977864803391962580800682760017849589281937637993445539366428356761821065267423102149447628375691862210717202025241630303118559188678304314076943801692528246980959705901641444238894928620825482303431806955690226308773426829503900930529395181208739591967195841536053143145775307050594328881077553168201547776)
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/Nortel.asn b/lib/asn1/test/asn1_SUITE_data/Nortel.asn
index a27c78a0b5..a27c78a0b5 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/Nortel.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Nortel.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn b/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn
index 247260495b..247260495b 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn
+++ b/lib/asn1/test/asn1_SUITE_data/UpperBounds.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn b/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn
index d9601bb7d0..d9601bb7d0 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn
+++ b/lib/asn1/test/asn1_SUITE_data/UsefulDefinitions.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn
index e3f6e83d6b..e3f6e83d6b 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-CommonDataTypes.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn
index 1411d455b7..1411d455b7 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Constants.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn
index fb08451103..fb08451103 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-Containers.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn
index 848d8f6099..848d8f6099 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-IEs.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn
index 9ecfa688a2..9ecfa688a2 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn
index b9be9934e4..b9be9934e4 100755..100644
--- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn
+++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn
diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl
index c3797f08b2..2c31c3259d 100644
--- a/lib/asn1/test/asn1_app_test.erl
+++ b/lib/asn1/test/asn1_app_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -138,7 +138,7 @@ check_asn1ct_modules(Extra) ->
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],
+ asn1ct_tok,asn1ct_parser2,asn1ct_table],
case Extra -- ASN1CTMods of
[] ->
ok;
diff --git a/lib/asn1/test/asn1_bin_particular_SUITE.erl.src b/lib/asn1/test/asn1_bin_particular_SUITE.erl.src
deleted file mode 100644
index 0e153238ad..0000000000
--- a/lib/asn1/test/asn1_bin_particular_SUITE.erl.src
+++ /dev/null
@@ -1,2 +0,0 @@
-
-particular() -> [].
diff --git a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src b/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
deleted file mode 100644
index 4c3c8c7808..0000000000
--- a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
+++ /dev/null
@@ -1,291 +0,0 @@
-
-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]),
-
- enc_dec(NumOfProcs,Msg,2),
-
- N = 10000,
-
- ?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,nif]),
- ?line {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
-
- ?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]~n"
- "Encode/decode time sequential: ~p [microsecs]",
- [NumOfProcs,Time1+Time3,Time1S+Time3S]))};
- false ->
- {skipped,"No smp support"}
- end.
-
-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]).
-
-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;
-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).
-
-
-pforeach(Fun, List) ->
- pforeach(Fun, List, []).
-pforeach(Fun, [], [{Pid,Ref}|Pids]) ->
- receive
- {'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}).
-
-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).
-
-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
deleted file mode 100644
index 12512606d8..0000000000
--- a/lib/asn1/test/asn1_common_SUITE.erl.src
+++ /dev/null
@@ -1,95 +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%
-%%
-%%
-
-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.
-
diff --git a/lib/asn1/test/asn1_particular_SUITE.erl.src b/lib/asn1/test/asn1_particular_SUITE.erl.src
deleted file mode 100644
index df76de914d..0000000000
--- a/lib/asn1/test/asn1_particular_SUITE.erl.src
+++ /dev/null
@@ -1,10 +0,0 @@
-
-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). \ No newline at end of file
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 26cbdeb940..96c04a9436 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,11 +19,67 @@
%%
-module(asn1_test_lib).
+-export([compile/3]).
+-export([compile_all/3]).
+-export([compile_erlang/3]).
+
-export([ticket_7407_compile/2,ticket_7407_code/1, ticket_7678/2,
- ticket_7708/2, ticket_7763/1, ticket_7876/3]).
+ ticket_7708/2, ticket_7763/1, ticket_7876/3]).
-include_lib("test_server/include/test_server.hrl").
+compile(File, Config, Options) -> compile_all([File], Config, Options).
+
+compile_all(Files, Config, Options) ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ [compile_file(filename:join(DataDir, F), [{outdir, CaseDir}|Options])
+ || F <- Files],
+ ok.
+
+compile_file(File, Options) ->
+ try
+ ok = asn1ct:compile(File, Options),
+ case should_load(File, Options) of
+ false ->
+ ok;
+ {module, Module} ->
+ code:purge(Module),
+ true = code:soft_purge(Module),
+ {module, Module} = code:load_file(Module)
+ end
+ catch
+ Class:Reason ->
+ erlang:error({compile_failed, {File, Options}, {Class, Reason}})
+ end.
+
+compile_erlang(Mod, Config, Options) ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ M = list_to_atom(Mod),
+ {ok, M} = compile:file(filename:join(DataDir, Mod),
+ [{i, CaseDir}, {outdir, CaseDir}|Options]).
+
+should_load(File, Options) ->
+ should_load(File, lists:member(abs, Options),
+ proplists:lookup(inline, Options)).
+
+should_load(_File, true, _Inline) ->
+ false;
+should_load(_File, _Abs, {inline, Module}) when Module /= true ->
+ {module, Module};
+should_load(File, _Abs, _Inline) ->
+ {module, list_to_atom(strip_extension(filename:basename(File)))}.
+
+strip_extension(File) ->
+ strip_extension(File, filename:extension(File)).
+
+strip_extension(File, "") ->
+ File;
+strip_extension(File, Ext) when Ext == ".asn"; Ext == ".set"; Ext == ".asn1"->
+ strip_extension(filename:rootname(File));
+strip_extension(File, _Ext) ->
+ File.
ticket_7407_compile(Config,Option) ->
diff --git a/lib/asn1/test/ber_decode_error.erl b/lib/asn1/test/ber_decode_error.erl
index a566e0b07f..ff6e386a88 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,19 +19,10 @@
%%
-module(ber_decode_error).
--export([run/1, compile/3]).
+-export([run/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++ "Constructed",
- [Rules,{outdir,OutDir}]++Options).
-
-
run([]) ->
?line {ok,B} = asn1_wrapper:encode('Constructed','S3',{'S3',17}),
?line [T,L|V] = lists:flatten(B),
diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl
index 5545dd45b9..b7a7d6e4df 100644
--- a/lib/asn1/test/h323test.erl
+++ b/lib/asn1/test/h323test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,58 +19,20 @@
%%
-module(h323test).
--compile(export_all).
--export([compile/3,run/1]).
+-export([run/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++ "H235-SECURITY-MESSAGES",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "H323-MESSAGES",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "MULTIMEDIA-SYSTEM-CONTROL",[Rules,{outdir,OutDir}]++Options).
-
-run(per_bin) ->
- run();
-run(per) ->
- run();
-run(_Rules) ->
- ok.
+run(per_bin) -> run();
+run(per) -> run();
+run(_Rules) -> ok.
run() ->
- ?line alerting(),
- ?line connect(),
+ alerting(),
+ connect(),
ok.
-arq() ->
- _AdmissionRequest = "27900007086000340036003300320038003700370101805337010180533600AC1F38C60693000D000445367AE75C5740120300AC1F38C6415004E0200100110000D7D22EA88D511C0200AC1F38C6C0580100".
-
-
-t0() ->
- Setup = "00B8060008914A0001010180533622C000000000074572696373736F6E0356302E3100010180533700AC1F38C206B80045367AE75C5740120300AC1F38C6415000411C110000D7D22EA88D511C0200AC1F3806C0583802150000080E1403001E80800A04000100AC1F38C661A820400000060401004E1403001E80801114000100AC1F38C72EE000AC1F38C72EE00100010063AA34AB"
-,
- ByteList = hexstr2bytes(Setup),
- asn1_wrapper:decode('H323-MESSAGES','H323-UU-PDU',ByteList).
-
-t1() ->
- AdmissionRequest = "27900007086000340036003300320038003700370101805337010180533600AC1F38C60693000D000445367AE75C5740120300AC1F38C6415004E0200100110000D7D22EA88D511C0200AC1F38C6C0580100",
- ByteList = hexstr2bytes(AdmissionRequest),
- asn1_wrapper:decode('H323-MESSAGES','RasMessage',ByteList).
-
-t2() ->
- Cs = "080200040504038090A56C059132303033700591323030347E00930500B8060008914A0001010180533622C000000000074572696373736F6E0356302E3100010180533700AC1F38C206B80045367AE75C5740120300AC1F38C6415000411C110000D7D22EA88D511C0200AC1F3806C0583802150000080E1403001E80800A04000100AC1F38C661A820400000060401004E1403001E80801114000100AC1F38C72EE000AC1F38C72EE00100010063AA34AB",
- ByteList = hexstr2bytes(Cs),
- asn1_wrapper:decode('H323-MESSAGES','H323-UU-PDU',ByteList).
-
-t3() ->
- Cs = "10b8060008914a0002044003004d0067006f006e018085cc22c0b500534c164d6963726f736f6674ae204e65744d656574696e67ae0003332e3000000101808c990088e1293a06b8001689edc5bf23d3118c2d00c04f4b1cd0000c07000a00000204dc40b500534c3c0200000028000000000000001b0000008138427484ccd211b4e300a0c90d0660100000001289edc5bf23d3118c2d00c04f4b1cd00000000000000000a615d9ee",
- ByteList = hexstr2bytes(Cs),
- asn1_wrapper:decode('H323-MESSAGES','H323-UU-PDU',ByteList).
-
dec_alerting() ->
Cs = "0380060008914a0002020120110000000000000000000000000000000000",
- _Slask="E83AE983",
ByteList = hexstr2bytes(Cs),
asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
@@ -78,95 +40,31 @@ enc_alerting(V) ->
asn1_wrapper:encode('H323-MESSAGES','H323-UserInformation',V).
alerting() ->
- ?line {ok,V} = dec_alerting(),
- ?line {ok,B} = enc_alerting(V),
- ?line ByteList = lists:flatten(B),
- ?line {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
+ {ok,V} = dec_alerting(),
+ {ok,B} = enc_alerting(V),
+ ByteList = lists:flatten(B),
+ {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
dec_connect() ->
Cs = "02c0060008914a00020088e1293a04a322c0b500534c164d6963726f736f6674ae204e65744d656474696e67ae0003332e3000001689edc5bf23d3118c2d00c04f4b1cd00900110000000000000000000000000000000000",
- _Slask="2f530a3f",
ByteList = hexstr2bytes(Cs),
asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
-
+
enc_connect(V) ->
asn1_wrapper:encode('H323-MESSAGES','H323-UserInformation',V).
connect() ->
- ?line {ok,V} = dec_connect(),
- ?line {ok,B} = enc_connect(V),
- ?line ByteList = lists:flatten(B),
- ?line {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
+ {ok,V} = dec_connect(),
+ {ok,B} = enc_connect(V),
+ ByteList = lists:flatten(B),
+ {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
-dec_h245_TCS() ->
- Cs ="02700106000881750003"
- "800d00003c000100000100000100000e"
- "807fff04b5428080010180000e483060"
- "0100800c96a88000002020b500534c48"
- "020000000000f4010000f40101000400"
- "0000000002000100401f000000100000"
- "000104002000f4010700000100000002"
- "00ff00000000c0004000f0000000cc01"
- "30ff880118ff00008000012040b38000"
- "0220c0b38000032020b500534c280200"
- "00000000a0000000a000040010000000"
- "000070000100401f0000580200000c00"
- "1000000000008000042020b500534c28"
- "020000000000a0000000a00004001000"
- "0000000071000100401f00003a070000"
- "25001000000000008000052020b50053"
- "4c280200000000008000000080000500"
- "14000000000072000100401f00000809"
- "000025001000000000008000062020b5"
- "00534c28020000000000800000008000"
- "050014000000000073000100401f0000"
- "7f0a00002b0010000000000080000722"
- "000b40000909a00120390c000a099001"
- "20390c000b09880120390c000c08a220"
- "3940000d089220390004800602070007"
- "00060004000500020001000000030000"
- "0a00000e800702070007000600040005"
- "000200010000000300000900000e8008"
- "02070007000600040005000200010000"
- "000300000c00000e8009020700070006"
- "00040005000200010000000300000b00"
- "000e800a020700070006000400050002"
- "00010000000300000d00000e0300000b"
- "01003280299d93369631bc",
- ByteList = hexstr2bytes(Cs),
- asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
- 'MultimediaSystemControlMessage',ByteList).
-
- hexstr2bytes([D1,D2|T]) ->
+hexstr2bytes([D1,D2|T]) ->
[dig2num(D1)*16+dig2num(D2)|hexstr2bytes(T)];
hexstr2bytes([]) ->
[].
-dig2num(D) when D >= $0, D =< $9 ->
- D - $0;
-dig2num(D) when D >= $a, D =< $f ->
- 10 + D - $a;
-dig2num(D) when D >= $A, D =< $F ->
- 10 + D - $A.
-
-bytes2hexstr(Bytes) ->
- bytes2hexstr(Bytes,[]).
-
-bytes2hexstr([B|Bytes],Acc) ->
- D1 = num2dig(B bsr 4),
- D2 = num2dig(B band 15),
- bytes2hexstr(Bytes,[D2,D1|Acc]);
-bytes2hexstr([],Acc) ->
- lists:reverse(Acc).
-
-num2dig(Num) when Num =< 9 ->
- $0 + Num;
-num2dig(Num) ->
- $a + Num - 10.
-
-
-
-
-
-
+dig2num(D) when D >= $0, D =< $9 -> D - $0;
+dig2num(D) when D >= $a, D =< $f -> 10 + D - $a;
+dig2num(D) when D >= $A, D =< $F -> 10 + D - $A.
diff --git a/lib/asn1/test/pem_performance.erl b/lib/asn1/test/pem_performance.erl
new file mode 100644
index 0000000000..87b8cbd61d
--- /dev/null
+++ b/lib/asn1/test/pem_performance.erl
@@ -0,0 +1,37 @@
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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([cert_pem/0]).
+-module([dsa_pem/0]).
+
+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/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl
index 5e149ed247..b75cfb6831 100644
--- a/lib/asn1/test/testChoExtension.erl
+++ b/lib/asn1/test/testChoExtension.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,21 +19,11 @@
%%
-module(testChoExtension).
--export([compile/3]).
-export([extension/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++ "ChoExtension",[Rules,{outdir,OutDir}] ++ Options).
-
-
-
extension(_Rules) ->
?line {ok,Bytes1} = asn1_wrapper:encode('ChoExtension','ChoExt1',{'ChoExt1',{bool,true}}),
diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl
index b6586b616b..b2d171f9c7 100644
--- a/lib/asn1/test/testChoExternal.erl
+++ b/lib/asn1/test/testChoExternal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,12 @@
-compile(Config,Rules,Optimize) ->
-
- ?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 ++ "ChoExternal",[Rules,{outdir,OutDir}]++Optimize).
+compile(Config, Rules, Optimize) ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ true = code:add_patha(CaseDir),
+ ok = asn1ct:compile(DataDir ++ "ChoExternal",
+ [Rules, {outdir, CaseDir}] ++ Optimize).
diff --git a/lib/asn1/test/testChoOptional.erl b/lib/asn1/test/testChoOptional.erl
index 61a1955d28..cbb8134e51 100644
--- a/lib/asn1/test/testChoOptional.erl
+++ b/lib/asn1/test/testChoOptional.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,29 +19,16 @@
%%
-module(testChoOptional).
-
--export([compile/3]).
-export([optional/1]).
%-include("ChoOptional.hrl").
-include_lib("test_server/include/test_server.hrl").
-include("External.hrl").
-
-record('Seq1',{bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}).
-record('Seq2',{int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}).
-record('Seq3',{cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}).
-
-compile(Config,Rules,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 ++ "ChoOptional",[Rules,{outdir,OutDir}]++Options).
-
-
-
optional(_Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('ChoOptional','Seq1',#'Seq1'{bool = true}),
diff --git a/lib/asn1/test/testChoOptionalImplicitTag.erl b/lib/asn1/test/testChoOptionalImplicitTag.erl
index e28353cb5a..efe335cabd 100644
--- a/lib/asn1/test/testChoOptionalImplicitTag.erl
+++ b/lib/asn1/test/testChoOptionalImplicitTag.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,28 +20,16 @@
-module(testChoOptionalImplicitTag).
--export([compile/2]).
-export([optional/1]).
%-include("ChoOptional.hrl").
-include_lib("test_server/include/test_server.hrl").
-include("External.hrl").
-
-record('Seq1',{bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}).
-record('Seq2',{int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}).
-record('Seq3',{cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}).
-
-compile(Config,Rules) ->
-
- ?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 ++ "ChoOptionalImplicitTag",[Rules,{outdir,OutDir}]).
-
-
-
optional(_Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq1',#'Seq1'{bool = true}),
diff --git a/lib/asn1/test/testChoPrim.erl b/lib/asn1/test/testChoPrim.erl
index f037db1c5d..936a38f76c 100644
--- a/lib/asn1/test/testChoPrim.erl
+++ b/lib/asn1/test/testChoPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,22 +19,11 @@
%%
-module(testChoPrim).
--export([compile/3]).
-export([bool/1]).
-export([int/1]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,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 ++ "ChoPrim",[Rules,{outdir,OutDir}]++Options).
-
-
-
bool(Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('ChoPrim','ChoCon',{bool0,true}),
diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl
index 36e23e2e03..22be26cbce 100644
--- a/lib/asn1/test/testChoRecursive.erl
+++ b/lib/asn1/test/testChoRecursive.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testChoRecursive).
--export([compile/3]).
-export([recursive/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,16 +27,6 @@
-record('ChoRec_something',{a, b, c}).
-record('ChoRec2_something',{a, b, c}).
-
-compile(Config,Rules,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 ++ "ChoRecursive",[Rules,{outdir,OutDir}]++Options).
-
-
-
recursive(_Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('ChoRecursive','ChoRec',{'ChoRec',{something,
diff --git a/lib/asn1/test/testChoTypeRefCho.erl b/lib/asn1/test/testChoTypeRefCho.erl
index f381d9078d..9bd732f462 100644
--- a/lib/asn1/test/testChoTypeRefCho.erl
+++ b/lib/asn1/test/testChoTypeRefCho.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,22 +19,10 @@
%%
-module(testChoTypeRefCho).
--export([compile/3]).
-export([choice/1]).
-include_lib("test_server/include/test_server.hrl").
-
-
-compile(Config,Rules,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 ++ "ChoTypeRefCho",[Rules,{outdir,OutDir}]++Options).
-
-
-
choice(_Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('ChoTypeRefCho','ChoTRcho',{choCho,{choInt,88}}),
diff --git a/lib/asn1/test/testChoTypeRefPrim.erl b/lib/asn1/test/testChoTypeRefPrim.erl
index 8fb9ed9f02..edef6192fe 100644
--- a/lib/asn1/test/testChoTypeRefPrim.erl
+++ b/lib/asn1/test/testChoTypeRefPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,22 +19,10 @@
%%
-module(testChoTypeRefPrim).
--export([compile/3]).
-export([prim/1]).
-include_lib("test_server/include/test_server.hrl").
-
-
-compile(Config,Rules,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 ++ "ChoTypeRefPrim",[Rules,{outdir,OutDir}]++Options).
-
-
-
prim(_Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR',{bool,true}),
diff --git a/lib/asn1/test/testChoTypeRefSeq.erl b/lib/asn1/test/testChoTypeRefSeq.erl
index 45d6209e79..bf2b66c73e 100644
--- a/lib/asn1/test/testChoTypeRefSeq.erl
+++ b/lib/asn1/test/testChoTypeRefSeq.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testChoTypeRefSeq).
--export([compile/3]).
-export([seq/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,16 +27,6 @@
-record('ChoSeqImp',{seqInt, seqOs}).
-record('ChoSeqExp',{seqInt, seqOs}).
-
-compile(Config,Rules,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 ++ "ChoTypeRefSeq",[Rules,{outdir,OutDir}]++Options).
-
-
-
seq(_Rules) ->
?line {ok,Bytes1} =
diff --git a/lib/asn1/test/testChoTypeRefSet.erl b/lib/asn1/test/testChoTypeRefSet.erl
index 9869549d7a..8a3e8bdbb0 100644
--- a/lib/asn1/test/testChoTypeRefSet.erl
+++ b/lib/asn1/test/testChoTypeRefSet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testChoTypeRefSet).
--export([compile/3]).
-export([set/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,16 +27,6 @@
-record('ChoSetImp',{setInt, setOs}).
-record('ChoSetExp',{setInt, setOs}).
-
-compile(Config,Rules,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 ++ "ChoTypeRefSet",[Rules,{outdir,OutDir}]++Options).
-
-
-
set(_Rules) ->
?line {ok,Bytes1} =
diff --git a/lib/asn1/test/testChoiceIndefinite.erl b/lib/asn1/test/testChoiceIndefinite.erl
index e5f3ee51c8..630efcf27a 100644
--- a/lib/asn1/test/testChoiceIndefinite.erl
+++ b/lib/asn1/test/testChoiceIndefinite.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,20 +19,10 @@
%%
-module(testChoiceIndefinite).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,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 ++ "ChoiceIndef",
- [Rules,{outdir,OutDir}]++Options).
-
main(per_bin) -> ok;
main(per) -> ok;
main(ber_bin_v2) ->
@@ -50,6 +40,3 @@ main(ber) ->
?line {ok,V} = asn1_wrapper:decode('ChoiceIndef','Seq',B),
?line {ok,V} = asn1_wrapper:decode('ChoiceIndef','Seq',Bi),
ok.
-
-
-
diff --git a/lib/asn1/test/testCompactBitString.erl b/lib/asn1/test/testCompactBitString.erl
index cd5586602b..9563a31bf3 100644
--- a/lib/asn1/test/testCompactBitString.erl
+++ b/lib/asn1/test/testCompactBitString.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,29 +19,11 @@
%%
-module(testCompactBitString).
--export([compile/3]).
-export([compact_bit_string/1, bit_string_unnamed/1,otp_4869/1,
ticket_7734/1]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,Option) ->
-
- ?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 ++ "PrimStrings",
- [Rules,{outdir,OutDir}]++Option),
- case Rules of
- per_bin ->
- ?line ok = asn1ct:compile(DataDir ++ "Constraints",
- [Rules,{outdir,OutDir}]++Option);
- _ -> ok
- end.
-
-
-
compact_bit_string(Rules) ->
%%==========================================================
diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl
index dcbc04f8d8..543c106e8a 100644
--- a/lib/asn1/test/testConstraints.erl
+++ b/lib/asn1/test/testConstraints.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,24 +19,11 @@
%%
-module(testConstraints).
--export([compile/3]).
-export([int_constraints/1,refed_NNL_name/1]).
-include_lib("test_server/include/test_server.hrl").
-
-
-compile(Config,Rules,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 ++ "Constraints",[Rules,{outdir,OutDir}]++Options).
-
-
-
-
int_constraints(Rules) ->
%%==========================================================
@@ -65,8 +52,6 @@ int_constraints(Rules) ->
?line {error,_Reason2} =
asn1_wrapper:encode('Constraints','SingleValue',1000)
end,
-
-
%%==========================================================
%% SingleValue2 ::= INTEGER (1..20)
@@ -99,7 +84,21 @@ int_constraints(Rules) ->
asn1_wrapper:encode('Constraints','SingleValue',1000)
end,
+ %%==========================================================
+ %% SingleValue3 ::= INTEGER (Predefined | 5 | 10)
+ %% Testcase for OTP-10139. A single value subtyping of an integer type
+ %% where one value is predefined.
+ %%==========================================================
+ ?line {ok,BytesSV3} = asn1_wrapper:encode('Constraints','SingleValue3',1),
+ ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue3',
+ lists:flatten(BytesSV3)),
+ ?line {ok,BytesSV3_2} = asn1_wrapper:encode('Constraints','SingleValue3',5),
+ ?line {ok,5} = asn1_wrapper:decode('Constraints','SingleValue3',
+ lists:flatten(BytesSV3_2)),
+ ?line {ok,BytesSV3_3} = asn1_wrapper:encode('Constraints','SingleValue3',10),
+ ?line {ok,10} = asn1_wrapper:decode('Constraints','SingleValue3',
+ lists:flatten(BytesSV3_3)),
%%==========================================================
%% Range2to19 ::= INTEGER (1<..<20)
@@ -129,7 +128,65 @@ int_constraints(Rules) ->
?line {error,_Reason6} =
asn1_wrapper:encode('Constraints','Range2to19',20)
end,
+
+ %%==========================================================
+ %% Tests for Range above 16^4 up to maximum supported by asn1 assuming the
+ %% octet length field is encoded on max 8 bits
+ %%==========================================================
+ LastNumWithoutLengthEncoding = 65536,
+ ?line {ok,BytesFoo} = asn1_wrapper:encode('Constraints','Range256to65536',
+ LastNumWithoutLengthEncoding),
+ ?line {ok,LastNumWithoutLengthEncoding} =
+ asn1_wrapper:decode('Constraints','Range256to65536',lists:flatten(BytesFoo)),
+
+ FirstNumWithLengthEncoding = 65537,
+ ?line {ok,BytesBar} = asn1_wrapper:encode('LargeConstraints','RangeMax',
+ FirstNumWithLengthEncoding),
+ ?line {ok,FirstNumWithLengthEncoding} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBar)),
+
+ FirstNumOver16_6 = 16777217,
+ ?line {ok, BytesBaz} =
+ asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_6),
+ ?line {ok, FirstNumOver16_6} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBaz)),
+ FirstNumOver16_8 = 4294967297,
+ ?line {ok, BytesQux} =
+ asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_8),
+ ?line {ok, FirstNumOver16_8} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesQux)),
+
+ FirstNumOver16_10 = 1099511627776,
+ ?line {ok, BytesBur} =
+ asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10),
+ ?line {ok, FirstNumOver16_10} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)),
+
+ FirstNumOver16_10 = 1099511627776,
+ ?line {ok, BytesBur} =
+ asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10),
+ ?line {ok, FirstNumOver16_10} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)),
+
+ HalfMax = 1 bsl (128*8),
+ ?line {ok, BytesHalfMax} =
+ asn1_wrapper:encode('LargeConstraints','RangeMax', HalfMax),
+ ?line {ok, HalfMax} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesHalfMax)),
+
+ Max = 1 bsl (255*8),
+ ?line {ok, BytesMax} =
+ asn1_wrapper:encode('LargeConstraints','RangeMax', Max),
+ ?line {ok, Max} =
+ asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesMax)),
+
+ %% Random number within longlong range
+ LongLong = 12672809400538808320,
+ ?line {ok, BytesLongLong} =
+ asn1_wrapper:encode('Constraints','LongLong', LongLong),
+ ?line {ok, LongLong} =
+ asn1_wrapper:decode('Constraints','LongLong',lists:flatten(BytesLongLong)),
%%==========================================================
%% Constraint Combinations (Duboisson p. 285)
@@ -140,17 +197,26 @@ int_constraints(Rules) ->
?line {ok,0} = asn1_wrapper:decode('Constraints','I',Bytes12),
?line {ok,Bytes13} = asn1_wrapper:encode('Constraints','I',20),
?line {ok,20} = asn1_wrapper:decode('Constraints','I',Bytes13),
-
+
+ %%==========================================================
+ %% Constraint Combinations (Duboisson p. 285)
+ %% X1 ::= INTEGER (1..4|8|10|20)
+ %%==========================================================
+
+ ?line {ok,Bytes14} = asn1_wrapper:encode('Constraints','X1',1),
+ ?line {ok,1} = asn1_wrapper:decode('Constraints','X1',Bytes14),
+ ?line {ok,Bytes15} = asn1_wrapper:encode('Constraints','X1',20),
+ ?line {ok,20} = asn1_wrapper:decode('Constraints','X1',Bytes15),
%%==========================================================
%% SIZE Constraint (Duboisson p. 268)
%% T ::= IA5String (SIZE (1|2, ..., SIZE (1|2|3)))
%% T2 ::= IA5String (SIZE (1|2, ..., 3))
%%==========================================================
- ?line {ok,Bytes14} = asn1_wrapper:encode('Constraints','T',"IA"),
- ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T',Bytes14),
- ?line {ok,Bytes15} = asn1_wrapper:encode('Constraints','T2',"IA"),
- ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T2',Bytes15).
+ ?line {ok,Bytes16} = asn1_wrapper:encode('Constraints','T',"IA"),
+ ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T',Bytes16),
+ ?line {ok,Bytes17} = asn1_wrapper:encode('Constraints','T2',"IA"),
+ ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T2',Bytes17).
refed_NNL_name(_Erule) ->
diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl
index 7d05e5c352..4f67942922 100644
--- a/lib/asn1/test/testContextSwitchingTypes.erl
+++ b/lib/asn1/test/testContextSwitchingTypes.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,29 +19,19 @@
%%
-module(testContextSwitchingTypes).
--export([compile/3]).
--export([test/0]).
+-export([test/1]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,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 ++ "ContextSwitchingTypes",
- [Rules,{outdir,OutDir}]++Options).
-
-
-test() ->
+test(Config) ->
?line ValT = 'ContextSwitchingTypes':'val1-T'(),
?line {ok,Bytes1} =
asn1_wrapper:encode('ContextSwitchingTypes','T',ValT),
?line {ok,Result1} =
asn1_wrapper:decode('ContextSwitchingTypes','T',Bytes1),
?line ok = check_EXTERNAL(Result1),
- ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T'),
+ ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T',
+ [{i, ?config(case_dir, Config)}]),
?line {ok,Bytes1_2} =
asn1_wrapper:encode('ContextSwitchingTypes','T',ValT2),
?line {ok,Result1_2} =
diff --git a/lib/asn1/test/testDER.erl b/lib/asn1/test/testDER.erl
index 630f7ecc14..395116bd34 100644
--- a/lib/asn1/test/testDER.erl
+++ b/lib/asn1/test/testDER.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,19 +19,10 @@
%%
-module(testDER).
--export([compile/3]).
-export([test/0]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rule,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 ++ "DERSpec",
- [Rule,der,{outdir,OutDir}]++Options).
-
test() ->
Val = {'Set',12,{version,214},true},
?line {ok,Bin}=asn1_wrapper:encode('DERSpec','Set',Val),
diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl
index 53d2b3040e..aa3afbb58f 100644
--- a/lib/asn1/test/testDeepTConstr.erl
+++ b/lib/asn1/test/testDeepTConstr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,23 +21,10 @@
-module(testDeepTConstr).
--export([compile/3,main/1]).
+-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++
- "TConstrChoice",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++
- "TConstr",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Erule) ->
Val1 = {'FilterItem',
{substrings,
diff --git a/lib/asn1/test/testDef.erl b/lib/asn1/test/testDef.erl
index 7942a358be..48f0015008 100644
--- a/lib/asn1/test/testDef.erl
+++ b/lib/asn1/test/testDef.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testDef).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -37,16 +36,6 @@
bool32 = asn1_DEFAULT,
bool33 = asn1_DEFAULT}).
-
-compile(Config,Rules,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",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,
diff --git a/lib/asn1/test/testDoubleEllipses.erl b/lib/asn1/test/testDoubleEllipses.erl
index 20be4ea215..9030a99ce2 100644
--- a/lib/asn1/test/testDoubleEllipses.erl
+++ b/lib/asn1/test/testDoubleEllipses.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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(testDoubleEllipses).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -34,17 +33,6 @@
-record('SetAlt',{a,d,b,e,c,f,g}).
-record('SetAltV2',{a,d,b,e,h,i,c,f,g}).
-
-
-
-compile(Config,Rules,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 ++ "DoubleEllipses",[Rules,{outdir,OutDir}]++Options).
-
-
main(_Rules) ->
%% SEQUENCE
?line {ok,Bytes} =
diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl
index 4ea0f3b8a1..c97116413a 100644
--- a/lib/asn1/test/testEnumExt.erl
+++ b/lib/asn1/test/testEnumExt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,19 +19,10 @@
%%
-module(testEnumExt).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++ "EnumExt",[Rules,{outdir,OutDir}]++Options).
-
-
main(Rules) when Rules == per; Rules == per_bin; Rules == uper_bin ->
io:format("main(~p)~n",[Rules]),
B32=[32],B64=[64],
diff --git a/lib/asn1/test/testExternal.erl b/lib/asn1/test/testExternal.erl
deleted file mode 100644
index 6e1fa0ee7d..0000000000
--- a/lib/asn1/test/testExternal.erl
+++ /dev/null
@@ -1,35 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(testExternal).
-
--export([compile/3]).
-
--include_lib("test_server/include/test_server.hrl").
-
-
-compile(Config,Rules,Options) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line test_server:format("Rules ~p~n",[Rules]),
- ?line ok = asn1ct:compile(DataDir ++ "External",[Rules,{outdir,OutDir}]++Options).
-
-
diff --git a/lib/asn1/test/testINSTANCE_OF.erl b/lib/asn1/test/testINSTANCE_OF.erl
index 6ae656da44..5986a00ec5 100644
--- a/lib/asn1/test/testINSTANCE_OF.erl
+++ b/lib/asn1/test/testINSTANCE_OF.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,21 +19,10 @@
%%
-module(testINSTANCE_OF).
--export([compile/3,main/1]).
+-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-
-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)),
-
- ?line ok = asn1ct:compile(DataDir ++ "INSTANCEOF.asn1",
- [Rules,{outdir,OutDir}]++Opt).
-
-
main(Erule) ->
?line {ok,Integer} = asn1_wrapper:encode('INSTANCEOF','Int',3),
diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl
index 9d73be9f23..03e70c730a 100644
--- a/lib/asn1/test/testInfObj.erl
+++ b/lib/asn1/test/testInfObj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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(testInfObj).
--export([compile/3,main/1,compile_RANAPfiles/3]).
+-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,42 +28,6 @@
-record('InitiatingMessage2',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{first,second}).
-compile(Config,Rules,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 ++
- "RANAPextract1",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "InfObj",[Rules,{outdir,OutDir}]++Options),
- %% test case for OTP-4792 optional open type
- ?line ok = asn1ct:compile(DataDir ++ "MAP-ExtensionDataTypes",[Rules,{outdir,OutDir}]++Options),
- %% OTP-6707
- ?line ok = asn1ct:compile(DataDir ++ "Objects",[Rules,{outdir,OutDir}]++Options),
- %% OTP-6717
- ?line ok = asn1ct:compile(DataDir ++ "INAPv2extract",[Rules,{outdir,OutDir}]++Options).
-
-
-compile_RANAPfiles(Config,Rules,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 ++ "RANAP-CommonDataTypes",
- [Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "RANAP-Constants",
- [Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "RANAP-Containers",
- [Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "RANAP-IEs",
- [Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "RANAP-PDU-Contents",
- [Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "RANAP-PDU-Descriptions",
- [Rules,{outdir,OutDir}]++Options).
-
-
main(_Erule) ->
Val1 = #'InitiatingMessage'{procedureCode=1,
criticality=ignore,
diff --git a/lib/asn1/test/testInfObjectClass.erl b/lib/asn1/test/testInfObjectClass.erl
index 07ebb7dbd0..e639066246 100644
--- a/lib/asn1/test/testInfObjectClass.erl
+++ b/lib/asn1/test/testInfObjectClass.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,22 +21,10 @@
-module(testInfObjectClass).
--export([compile/3,main/1]).
+-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-
-
-
-compile(Config,Rules,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 ++ "ErrorClass",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "InfClass",[Rules,{outdir,OutDir}]++Options).
-
-
main(Rule) ->
%% this test is added for OTP-4591, to test that elements in decoded
%% value has terms in right order.
diff --git a/lib/asn1/test/testMegaco.erl b/lib/asn1/test/testMegaco.erl
index ca2b1062d1..f4edcebb7e 100644
--- a/lib/asn1/test/testMegaco.erl
+++ b/lib/asn1/test/testMegaco.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,24 +108,17 @@ compile(_Config,ber,[optimize]) ->
compile(_Config,per,[optimize]) ->
{ok,no_module,no_module};
compile(Config,Erule,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 ++
- "MEDIA-GATEWAY-CONTROL.asn",
- [Erule,{outdir,OutDir}]++Options),
-
- ?line ok = asn1ct:compile(DataDir ++
- "OLD-MEDIA-GATEWAY-CONTROL.asn",
- [Erule,{outdir,OutDir}]++Options),
+ asn1_test_lib:compile("MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]),
+ asn1_test_lib:compile("OLD-MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]),
{ok,'OLD-MEDIA-GATEWAY-CONTROL','MEDIA-GATEWAY-CONTROL'}.
main(no_module,_) -> ok;
-main('OLD-MEDIA-GATEWAY-CONTROL',_) ->
+main('OLD-MEDIA-GATEWAY-CONTROL',Config) ->
% Msg = msg11(),
- {ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage'),
+ CaseDir = ?config(case_dir, Config),
+ {ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage',
+ [{i, CaseDir}]),
?line {ok,Bytes} = asn1_wrapper:encode('OLD-MEDIA-GATEWAY-CONTROL',
'MegacoMessage',Msg),
?line {ok,Msg} = asn1_wrapper:decode('OLD-MEDIA-GATEWAY-CONTROL',
@@ -176,7 +169,7 @@ request(Mid, TransId, ContextId, CmdReq) when is_list(CmdReq) ->
msg11() ->
TimeStamp = #'TimeNotation'{date = "19990729",
- time = "22010001"},
+ time = "22012001"},
Parm = #'EventParameter'{eventParameterName = "ds",
value = "916135551212"},
diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl
index 733cbc0eef..31aa3518f6 100644
--- a/lib/asn1/test/testMergeCompile.erl
+++ b/lib/asn1/test/testMergeCompile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,31 +20,13 @@
-module(testMergeCompile).
--export([compile/3,main/1,mvrasn/1]).
+-export([main/1,mvrasn/1]).
-include_lib("test_server/include/test_server.hrl").
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{protocolIEs,protocolExtensions}).
-compile(Config,Erule,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 ++
- "MS.set.asn",[Erule,{outdir,OutDir}]++Options),
-
- ?line ok = asn1ct:compile(DataDir ++
- "RANAPSET.set.asn1",[Erule,{outdir,OutDir}]++Options),
-
- ?line ok = asn1ct:compile(filename:join([DataDir,"Mvrasn4.set.asn"]),
- [Erule,{outdir,OutDir}]++Options),
-
- ?line ok = asn1ct:compile(filename:join([DataDir,"Mvrasn6.set.asn"]),
- [Erule,{outdir,OutDir}]++Options).
-
-
main(Erule) ->
%% test of module MS.set.asn that tests OTP-4492: different tagdefault in
%% modules and types with same name in modules
diff --git a/lib/asn1/test/testMvrasn6.erl b/lib/asn1/test/testMvrasn6.erl
deleted file mode 100644
index eaa667e6d7..0000000000
--- a/lib/asn1/test/testMvrasn6.erl
+++ /dev/null
@@ -1,44 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(testMvrasn6).
-
--export([compile/2]).
--export([main/0]).
-
--include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line Options = [Rules,{outdir,OutDir}],
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-21-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-20-6",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-19-6",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-15-6",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-18-6",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-14-6",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-11-6",Options).
-
-
-main() ->
- ok.
-
diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl
index 1269f94060..4e8381e51e 100644
--- a/lib/asn1/test/testNBAPsystem.erl
+++ b/lib/asn1/test/testNBAPsystem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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(testNBAPsystem).
--export([compile/3,test/2,cell_setup_req_msg/0]).
+-export([compile/2,test/2,cell_setup_req_msg/0]).
-include_lib("test_server/include/test_server.hrl").
@@ -78,19 +78,15 @@ powerRaiseLimit, dLPowerAveragingWindowSize, 'iE-Extensions' = asn1_NOVALUE}).
id, criticality, extensionValue}).
-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)),
- ?line DataDir2 = filename:join([DataDir,nbapsystem]),
-
- ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-CommonDataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-IEs.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-PDU-Contents.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-PDU-Discriptions.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-Constants.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-Containers.asn"]),[Rules,{outdir,OutDir}]++Opt).
+compile(Config, Options) ->
+ [asn1_test_lib:compile(filename:join([nbapsystem, M]), Config, Options)
+ || M <- ["NBAP-CommonDataTypes.asn",
+ "NBAP-IEs.asn",
+ "NBAP-PDU-Contents.asn",
+ "NBAP-PDU-Discriptions.asn",
+ "NBAP-Constants.asn",
+ "NBAP-Containers.asn"]],
+ ok.
test(_Erule,Config) ->
@@ -291,13 +287,7 @@ protocolIEs_051107() ->
criticality = ignore,
extensionValue = 'hsdpa-non-capable'}.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-compare(V,V) ->
+compare(V,V) ->
ok;
compare(V,L) when is_list(L) ->
compare(V,list_to_binary(L));
@@ -306,52 +296,7 @@ compare(_,_) ->
check_record_names(Msg,Config) ->
DataDir = ?config(data_dir,Config),
- OutDir = ?config(priv_dir,Config),
- io:format("check_record_names: compiling ~p~ninclude directory: ~p~n",
- [filename:join([DataDir,"test_records"]),OutDir]),
- ?line {ok,test_records} = compile:file(filename:join([DataDir,"test_records"]),
- [{i,OutDir}]),
- io:format("check_record_names: calling test_records:'check_record_names_OTP-5812'/1~n",[]),
- ?line ok = test_records:'check_record_names_OTP-5812'(Msg).
-
-% check_record_names({initiatingMessage,
-% #'InitiatingMessage'{procedureID = ProcedureID,
-% criticality = _Criticality,
-% messageDiscriminator = _MessageDisc,
-% transactionID = _TransactionID,
-% value = Value}}) ->
-
-% ?line ok = check_record_ProcedureID(ProcedureID),
-% ?line ok = check_record_Value(Value).
-
-% check_record_ProcedureID(#'ProcedureID'{}) ->
-% ok;
-% check_record_ProcedureID(_) -> false.
-
-% check_record_Value(#'ResourceStatusIndication'{protocolIEs = ProtocolIEs}) ->
-% ?line ok = check_record_ProtocolIEs(ProtocolIEs);
-% check_record_Value(_) -> false.
-
-% check_record_ProtocolIEs(#'ProtocolIE-Field'{value =IndicationType}) ->
-% ?line ok = check_record_NFResourceStatusInd(IndicationType);
-% check_record_ProtocolIEs(_) -> false.
-
-% check_record_NFResourceStatusInd({'no-Failure',#'No-Failure-ResourceStatusInd'{'local-Cell-InformationList'=[LCI]}}) ->
-% ?line ok = check_record_LCInfoResourceStatusInd(LCI);
-% check_record_NFResourceStatusInd(_) -> false.
-
-% check_record_LCInfoResourceStatusInd(#'Local-Cell-InformationItem-ResourceStatusInd'{commonChannelsCapacityConsumptionLaw=[CCCCL],dedicatedChannelsCapacityConsumptionLaw=[DCCCL],'iE-Extensions' = [LCIRE]}) ->
-% ?line ok = check_record_CCCCL(CCCCL),
-% ?line ok = check_record_DCCCL(DCCCL),
-% ?line ok = check_record_LCIRE(LCIRE).
-
-% check_record_CCCCL(#'CommonChannelsCapacityConsumptionLaw_SEQOF'{}) ->
-% ok;
-% check_record_CCCCL(_) -> false.
-
-% check_record_DCCCL(#'DedicatedChannelsCapacityConsumptionLaw_SEQOF'{}) ->
-% ok;
-% check_record_DCCCL(_) -> false.
-% check_record_LCIRE(#'ProtocolExtensionField'{}) ->
-% ok;
-% check_record_LCIRE(_) -> false.
+ CaseDir = ?config(case_dir,Config),
+ {ok, test_records} = compile:file(filename:join([DataDir, "test_records"]),
+ [{i, CaseDir}]),
+ ok = test_records:'check_record_names_OTP-5812'(Msg).
diff --git a/lib/asn1/test/testOpenTypeImplicitTag.erl b/lib/asn1/test/testOpenTypeImplicitTag.erl
index 8662744ed3..a37d8004ef 100644
--- a/lib/asn1/test/testOpenTypeImplicitTag.erl
+++ b/lib/asn1/test/testOpenTypeImplicitTag.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,21 +19,10 @@
%%
-module(testOpenTypeImplicitTag).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,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 ++ "OpenTypeImplicitTag",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes1} =
diff --git a/lib/asn1/test/testParamBasic.erl b/lib/asn1/test/testParamBasic.erl
index 4ba0029b54..b5780195b8 100644
--- a/lib/asn1/test/testParamBasic.erl
+++ b/lib/asn1/test/testParamBasic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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(testParamBasic).
--export([compile/3]).
--export([compile_der/2]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -30,22 +28,6 @@
-record('T21',{number, string}).
-record('T22',{number, string}).
-
-compile(Config,Rules,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 ++ "ParamBasic",
- [Rules,{outdir,OutDir}]++Options).
-
-compile_der(Config,Rules) ->
- ?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 ++ "ParamBasic",
- [der,Rules,{outdir,OutDir}]).
-
main(Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl
index b95d627d58..68faf08a61 100644
--- a/lib/asn1/test/testParameterizedInfObj.erl
+++ b/lib/asn1/test/testParameterizedInfObj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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(testParameterizedInfObj).
--export([compile/3,main/1,ranap/1]).
+-export([main/1,ranap/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -31,16 +31,6 @@
-record('Iu-ReleaseCommand',{protocolIEs,protocolExtensions}).
-compile(Config,Rules,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 ++ "Param",[Rules,{outdir,OutDir}]++Options).
-% ?line ok = asn1ct:compile(DataDir ++ "RANAP-CommonDataTypes",[Rules,{outdir,OutDir}]++Options).
-
-
main(Erule) ->
PERVal = #'AllocationOrRetentionPriority'
{priorityLevel = true,
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index 39c1e4d1d8..0d4427ba69 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testPrim).
--export([compile/3]).
-export([bool/1]).
-export([int/1]).
-export([enum/1]).
@@ -30,18 +29,6 @@
-include_lib("test_server/include/test_server.hrl").
-
-
-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)),
- ?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/testPrimExternal.erl b/lib/asn1/test/testPrimExternal.erl
index 23633177eb..65c3c3a31a 100644
--- a/lib/asn1/test/testPrimExternal.erl
+++ b/lib/asn1/test/testPrimExternal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,21 +19,10 @@
%%
-module(testPrimExternal).
--export([compile/3]).
-export([external/1]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,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 ++ "PrimExternal",[Rules,{outdir,OutDir}]++Options).
-
-
-
external(_Rules) ->
diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl
index 33652d6554..b1c5172b95 100644
--- a/lib/asn1/test/testPrimStrings.erl
+++ b/lib/asn1/test/testPrimStrings.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testPrimStrings).
--export([compile/3]).
-export([bit_string/1]).
-export([bit_string_unnamed/1]).
-export([octet_string/1]).
@@ -33,22 +32,6 @@
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,Option) ->
-
- ?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 ++ "PrimStrings",
- [Rules,{outdir,OutDir}]++Option),
- ?line {ok,IO} = file:open(test_config,write),
- io:format(IO,"~p.~n",[Config]),
- file:close(IO),
- ?line ok = asn1ct:compile(DataDir ++ "BitStr",
- [Rules, {outdir,OutDir}]++Option).
-
-
-
bit_string(Rules) ->
%%==========================================================
diff --git a/lib/asn1/test/testRANAP.erl b/lib/asn1/test/testRANAP.erl
deleted file mode 100644
index 52a58d850b..0000000000
--- a/lib/asn1/test/testRANAP.erl
+++ /dev/null
@@ -1,52 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(testRANAP).
-
--export([compile/3,testobj/1]).
-
--include_lib("test_server/include/test_server.hrl").
-
-
-compile(Config,Erule,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(filename:join(DataDir,"RANAP"),[Erule,{outdir,OutDir}]++Options),
- ?line {ok,testobj} = compile:file(filename:join(DataDir,"testobj"),[{i,OutDir},{outdir,OutDir}]++Options),
- ok.
-
-testobj(_Erule) ->
- ?line ok = testobj:run_com_id(),
- ?line ok = testobj:run_dir_tsf_2cn(),
- ?line ok = testobj:run_dir_tsf_2rnc(),
- ?line ok = testobj:run_init_ue(),
- ?line ok = testobj:run_iu_rel_cmd(),
- ?line ok = testobj:run_iu_rel_cmp(),
- ?line ok = testobj:run_rab_ass_rsp_delete(),
- ?line ok = testobj:run_rab_ass_rsp_setup(),
- ?line ok = testobj:run_rab_create(),
- ?line ok = testobj:run_rab_rel(),
- ?line ok = testobj:run_reset(),
- ?line ok = testobj:run_reset_res(),
- ?line ok = testobj:run_sm_cmd(),
- ?line ok = testobj:run_sm_cmp(),
- ?line ok = testobj:run_sm_rej().
diff --git a/lib/asn1/test/testROSE.erl b/lib/asn1/test/testROSE.erl
deleted file mode 100644
index a692ec7682..0000000000
--- a/lib/asn1/test/testROSE.erl
+++ /dev/null
@@ -1,36 +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%
-%%
-%%
--module(testROSE).
-
--export([compile/3]).
-
--include_lib("test_server/include/test_server.hrl").
-
-
-
-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)),
-
- ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Merged.set.asn1",
- [Rules,{outdir,OutDir}]++Opt).
-
diff --git a/lib/asn1/test/testSSLspecs.erl b/lib/asn1/test/testSSLspecs.erl
index 10623af51e..51ef134e5f 100644
--- a/lib/asn1/test/testSSLspecs.erl
+++ b/lib/asn1/test/testSSLspecs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,58 +20,37 @@
-module(testSSLspecs).
--export([compile/3,run/1,compile_inline/2,run_inline/1]).
+-export([compile/2,run/1,compile_inline/2,run_inline/1]).
-include_lib("test_server/include/test_server.hrl").
+compile(Config, Options) ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ NewOptions = [{i, DataDir}, {i, CaseDir}|Options],
-compile(Config,Rules,Options) ->
+ asn1_test_lib:compile_all(["SSL-PKIX", "PKIXAttributeCertificate"],
+ Config, NewOptions),
- ?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 ++
- "SSL-PKIX",[Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "PKIXAttributeCertificate",
- [Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options),
%% test case for OTP-4792 optional open type
- ?line ok = asn1ct:compile(DataDir ++ "PKIX1Algorithms88",
- [Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "PKIX1Explicit88",
- [Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "PKIX1Implicit88",
- [Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options),
+ asn1_test_lib:compile_all(["PKIX1Algorithms88", "PKIX1Explicit88",
+ "PKIX1Implicit88"],
+ Config, NewOptions),
+
%% OTP-6698, OTP-6702
- ?line ok = remove_db_files(OutDir),
- ?line ok = asn1ct:compile(DataDir ++ "PKIX1Explicit93",
- [Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "PKIX1Implicit93",
- [Rules,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options).
-
-compile_inline(Config,Rule) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- case Rule of
- BER when BER==ber_bin;BER==ber_bin_v2 ->
- Options = [der,compact_bit_string,optimize,
- asn1config,inline],
- ?line ok = remove_db_file_inline(OutDir),
- ?line ok = asn1ct:compile(DataDir ++ "OTP-PKIX.set.asn",
- [Rule,{outdir,OutDir},{i,DataDir},
- {i,OutDir}]++Options);
- _ ->
- ok
- end.
+ ok = remove_db_files(CaseDir),
+ asn1_test_lib:compile_all(["PKIX1Explicit93", "PKIX1Implicit93"],
+ Config, NewOptions).
+
+compile_inline(Config, Rule) when Rule == ber_bin; Rule == ber_bin_v2 ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ Options = [{i, CaseDir}, {i, DataDir}, Rule,
+ der, compact_bit_string, optimize, asn1config, inline],
+ ok = remove_db_file_inline(CaseDir),
+ asn1_test_lib:compile("OTP-PKIX.set.asn", Config, Options);
+compile_inline(_Config, _Rule) ->
+ ok.
remove_db_files(Dir) ->
?line ok = remove_db_file(Dir ++ "PKIX1Explicit93.asn1db"),
diff --git a/lib/asn1/test/testSelectionTypes.erl b/lib/asn1/test/testSelectionTypes.erl
index 893c31622f..6d1641388f 100644
--- a/lib/asn1/test/testSelectionTypes.erl
+++ b/lib/asn1/test/testSelectionTypes.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,19 +19,10 @@
%%
-module(testSelectionTypes).
--export([compile/3]).
-export([test/0]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rule,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 ++ "SelectionType",
- [Rule,{outdir,OutDir}]++Options).
-
test() ->
Val = ["PrintableString","PrintableString","PrintableString"],
?line {ok,Bin}=asn1_wrapper:encode('SelectionType','MendeleyevTable',Val),
diff --git a/lib/asn1/test/testSeq2738.erl b/lib/asn1/test/testSeq2738.erl
index 9cf9c8fcb4..cddfe4b311 100644
--- a/lib/asn1/test/testSeq2738.erl
+++ b/lib/asn1/test/testSeq2738.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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(testSeq2738).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -32,14 +31,6 @@
-compile(Config,Rules,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 ++ "Seq2738",[Rules,{outdir,OutDir}]++Options).
-
-
main(_Rules) ->
?line {ok,Bytes} =
diff --git a/lib/asn1/test/testSeqDefault.erl b/lib/asn1/test/testSeqDefault.erl
index edf07cf1c1..a772b749bd 100644
--- a/lib/asn1/test/testSeqDefault.erl
+++ b/lib/asn1/test/testSeqDefault.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSeqDefault).
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -37,15 +36,6 @@
-record('SeqIn',{boolIn, intIn}).
-compile(Config,Rules,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 ++ "SeqDefault",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl
index 538e2c250b..7c77ab87e9 100644
--- a/lib/asn1/test/testSeqExtension.erl
+++ b/lib/asn1/test/testSeqExtension.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSeqExtension).
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -31,16 +30,6 @@
-record('SeqExt4',{bool, int}).
-compile(Config,Rules,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 ++ "SeqExtension",
- [Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSeqIndefinite.erl b/lib/asn1/test/testSeqIndefinite.erl
index 9285d7b368..25742474bb 100644
--- a/lib/asn1/test/testSeqIndefinite.erl
+++ b/lib/asn1/test/testSeqIndefinite.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,20 +19,11 @@
%%
-module(testSeqIndefinite).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++ "SeqSetIndefinite",
- [Rules,{outdir,OutDir}]++Options).
-
main(per_bin) -> ok;
main(per) -> ok;
main(ber_bin_v2) ->
diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl
index 961e2d89d9..0c0bbc3e66 100644
--- a/lib/asn1/test/testSeqOf.erl
+++ b/lib/asn1/test/testSeqOf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqOf).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,18 +34,6 @@
-record('SeqEmp',{seq1}).
-record('Empty',{}).
-
-compile(Config,Rules,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 ++ "SeqOf",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "SeqOfEnum",[Rules,{outdir,OutDir}]++Options),
- ?line ok = asn1ct:compile(DataDir ++ "XSeqOf",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSeqOfCho.erl b/lib/asn1/test/testSeqOfCho.erl
index 05bd45580f..5b83c8bf21 100644
--- a/lib/asn1/test/testSeqOfCho.erl
+++ b/lib/asn1/test/testSeqOfCho.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqOfCho).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -31,17 +30,6 @@
-record('SeqOfChoEmbDef_SEQOF',{bool1, int1, seq1 = asn1_DEFAULT}).
-record('SeqOfChoEmbOpt_SEQOF',{bool1, int1, seq1 = asn1_NOVALUE}).
-
-
-compile(Config,Rules,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 ++ "SeqOfCho",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSeqOfIndefinite.erl b/lib/asn1/test/testSeqOfIndefinite.erl
index 0221581cf1..01ef36e0b4 100644
--- a/lib/asn1/test/testSeqOfIndefinite.erl
+++ b/lib/asn1/test/testSeqOfIndefinite.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,42 +19,10 @@
%%
-module(testSeqOfIndefinite).
--export([compile/3]).
-export([main/0]).
-include_lib("test_server/include/test_server.hrl").
-%-record('Seq1',{bool1, int1, seq1 = asn1_DEFAULT}).
-%-record('Seq2',{seq2 = asn1_DEFAULT, bool2, int2}).
-%-record('Seq3',{bool3, seq3 = asn1_DEFAULT, int3}).
-%-record('Seq4',{seq41 = asn1_DEFAULT, seq42 = asn1_DEFAULT, seq43 = asn1_DEFAULT}).
-%-record('SeqIn',{boolIn, intIn}).
-%-record('SeqCho',{bool1, int1, seq1 = asn1_DEFAULT}).
-%-record('SeqChoInline',{bool1, int1, seq1 = asn1_DEFAULT}).
-%-record('SeqChoOfInline_SEQOF',{bool1, int1, seq1 = asn1_DEFAULT}).
-%-record('SeqEmp',{seq1}).
-%-record('Empty',{}).
-
-
-
-compile(Config,Rules,Opts) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line Options = [Rules,{outdir,OutDir}]++Opts,
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-Constants-1",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-DataTypes-1",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-21-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-20-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-19-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-18-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-17-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-15-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-14-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-11-4",Options),
- ?line ok = asn1ct:compile(DataDir ++ "SeqOf",Options).
-
main() ->
?line ok = test(isd),
?line ok = test(isd2),
diff --git a/lib/asn1/test/testSeqOfTag.erl b/lib/asn1/test/testSeqOfTag.erl
index 4f56ab717b..2359df0c59 100644
--- a/lib/asn1/test/testSeqOfTag.erl
+++ b/lib/asn1/test/testSeqOfTag.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqOfTag).
-
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -45,17 +43,6 @@
-record('Imp',{os, bool}).
-record('Exp',{os, bool}).
-
-
-compile(Config,Rules,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 ++ "SeqOfTag",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSeqOptional.erl b/lib/asn1/test/testSeqOptional.erl
index 0125c9fb3e..8013f3c685 100644
--- a/lib/asn1/test/testSeqOptional.erl
+++ b/lib/asn1/test/testSeqOptional.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSeqOptional).
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -37,16 +36,6 @@
-record('SeqIn',{boolIn, intIn}).
-record('SeqChoOpt',{int, cho = asn1_NOVALUE}).
-
-compile(Config,Rules,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 ++ "SeqOptional",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSeqPrim.erl b/lib/asn1/test/testSeqPrim.erl
index ec48d1b779..c2451a7cd1 100644
--- a/lib/asn1/test/testSeqPrim.erl
+++ b/lib/asn1/test/testSeqPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqPrim).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -27,15 +26,6 @@
-record('Seq',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}).
-record('Empty',{}).
-compile(Config,Rules,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 ++ "SeqPrim",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl
index 5a1a443ebc..ab484db5f2 100644
--- a/lib/asn1/test/testSeqSetDefaultVal.erl
+++ b/lib/asn1/test/testSeqSetDefaultVal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSeqSetDefaultVal).
-include("External.hrl").
--export([compile/2]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -95,14 +94,6 @@
-record('S4_b',{ba = asn1_DEFAULT,
bb = asn1_DEFAULT}).
-
-compile(Config,Rules) ->
- ?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 ++ "Default",
- [Rules,der,{outdir,OutDir}]).
-
main(_Rules) ->
?line {ok,[48,0]} =
diff --git a/lib/asn1/test/testSeqTag.erl b/lib/asn1/test/testSeqTag.erl
index 60d3629840..9fdaae35dd 100644
--- a/lib/asn1/test/testSeqTag.erl
+++ b/lib/asn1/test/testSeqTag.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqTag).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,16 +34,6 @@
-record('Imp',{os, bool}).
-record('Exp',{os, bool}).
-
-compile(Config,Rules,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 ++ "SeqTag",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSeqTypeRefCho.erl b/lib/asn1/test/testSeqTypeRefCho.erl
index 9262fd1bfd..4b9eac7034 100644
--- a/lib/asn1/test/testSeqTypeRefCho.erl
+++ b/lib/asn1/test/testSeqTypeRefCho.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqTypeRefCho).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -27,16 +26,6 @@
-record('SeqTRcho',{seqCho, seqChoE, 'seqCho-E', 'seqChoE-E'}).
-
-compile(Config,Rules,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 ++ "SeqTypeRefCho",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSeqTypeRefSeq.erl b/lib/asn1/test/testSeqTypeRefSeq.erl
index 51b0f13c57..57ec6c19b1 100644
--- a/lib/asn1/test/testSeqTypeRefSeq.erl
+++ b/lib/asn1/test/testSeqTypeRefSeq.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqTypeRefSeq).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -46,15 +45,6 @@
-compile(Config,Rules,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 ++ "SeqTypeRefSeq",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSeqTypeRefSet.erl b/lib/asn1/test/testSeqTypeRefSet.erl
index a704ce3403..c06a0e7a2b 100644
--- a/lib/asn1/test/testSeqTypeRefSet.erl
+++ b/lib/asn1/test/testSeqTypeRefSet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSeqTypeRefSet).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -31,15 +30,6 @@
-compile(Config,Rules,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 ++ "SeqTypeRefSet",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes41} =
diff --git a/lib/asn1/test/testSetDefault.erl b/lib/asn1/test/testSetDefault.erl
index e36894327c..8aa205e0f0 100644
--- a/lib/asn1/test/testSetDefault.erl
+++ b/lib/asn1/test/testSetDefault.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetDefault).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -30,16 +29,6 @@
-record('SetIn',{boolIn, intIn}).
-
-compile(Config,Rules,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 ++ "SetDefault",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSetExternal.erl b/lib/asn1/test/testSetExternal.erl
index 41f32dcd90..30cddcacfb 100644
--- a/lib/asn1/test/testSetExternal.erl
+++ b/lib/asn1/test/testSetExternal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSetExternal).
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -33,17 +32,6 @@
%-record('Imp',{os, bool}).
%-record('Exp',{os, bool}).
-
-compile(Config,Rules,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 ++ "SetExternal",
- [Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSetIndefinite.erl b/lib/asn1/test/testSetIndefinite.erl
index bf8b242860..d8e2b6a9cf 100644
--- a/lib/asn1/test/testSetIndefinite.erl
+++ b/lib/asn1/test/testSetIndefinite.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,20 +19,11 @@
%%
-module(testSetIndefinite).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config,Rules,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 ++ "SeqSetIndefinite",
- [Rules,{outdir,OutDir}]++Options).
-
main(per_bin) -> ok;
main(per) -> ok;
main(ber_bin_v2) ->
diff --git a/lib/asn1/test/testSetOf.erl b/lib/asn1/test/testSetOf.erl
index 0769b9a344..08723fb468 100644
--- a/lib/asn1/test/testSetOf.erl
+++ b/lib/asn1/test/testSetOf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetOf).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -37,15 +36,6 @@
-compile(Config,Rules,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 ++ "SetOf",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSetOfCho.erl b/lib/asn1/test/testSetOfCho.erl
index 474742fbdb..c89bf9596e 100644
--- a/lib/asn1/test/testSetOfCho.erl
+++ b/lib/asn1/test/testSetOfCho.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetOfCho).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -33,15 +32,6 @@
-compile(Config,Rules,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 ++ "SetOfCho",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSetOfExternal.erl b/lib/asn1/test/testSetOfExternal.erl
index 9e2b01c698..6b280a2595 100644
--- a/lib/asn1/test/testSetOfExternal.erl
+++ b/lib/asn1/test/testSetOfExternal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSetOfExternal).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -32,15 +31,6 @@
-compile(Config,Rules,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 ++ "SetOfExternal",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSetOfTag.erl b/lib/asn1/test/testSetOfTag.erl
index c101306d7a..2c7a2f5473 100644
--- a/lib/asn1/test/testSetOfTag.erl
+++ b/lib/asn1/test/testSetOfTag.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSetOfTag).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -47,15 +46,6 @@
-compile(Config,Rules,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 ++ "SetOfTag",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
diff --git a/lib/asn1/test/testSetOptional.erl b/lib/asn1/test/testSetOptional.erl
index 035fa70424..4692941524 100644
--- a/lib/asn1/test/testSetOptional.erl
+++ b/lib/asn1/test/testSetOptional.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(testSetOptional).
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-export([ticket_7533/1,decoder/4]).
-include_lib("test_server/include/test_server.hrl").
@@ -36,16 +35,6 @@
-record('SetOpt3Exp',{bool3 = asn1_NOVALUE, set3 = asn1_NOVALUE, int3 = asn1_NOVALUE}).
-record('SetIn',{boolIn, intIn}).
-
-compile(Config,Rules,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 ++ "SetOptional",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes11} =
@@ -204,9 +193,8 @@ ticket_7533(Ber) when Ber == ber; Ber == ber_bin ->
io:format("Decode result: ~p~n",[Result]),
ok
after 10000 ->
- exit(Pid,normal),
io:format("Decode timeout~n",[]),
- error
+ exit(Pid,normal)
end;
ticket_7533(_) ->
ok.
diff --git a/lib/asn1/test/testSetPrim.erl b/lib/asn1/test/testSetPrim.erl
index e093c918e3..3234b65135 100644
--- a/lib/asn1/test/testSetPrim.erl
+++ b/lib/asn1/test/testSetPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetPrim).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -27,15 +26,6 @@
-record('Set',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}).
-record('Empty',{}).
-compile(Config,Rules,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 ++ "SetPrim",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSetTag.erl b/lib/asn1/test/testSetTag.erl
index 8df3e36815..8b9364d603 100644
--- a/lib/asn1/test/testSetTag.erl
+++ b/lib/asn1/test/testSetTag.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetTag).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,16 +34,6 @@
-record('Imp',{os, bool}).
-record('Exp',{os, bool}).
-
-compile(Config,Rules,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 ++ "SetTag",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSetTypeRefCho.erl b/lib/asn1/test/testSetTypeRefCho.erl
index 1f68a8fbc4..a0989926c7 100644
--- a/lib/asn1/test/testSetTypeRefCho.erl
+++ b/lib/asn1/test/testSetTypeRefCho.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetTypeRefCho).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,15 +27,6 @@
-record('SetTRcho',{setCho, setChoE, 'setCho-E', 'setChoE-E'}).
-compile(Config,Rules,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 ++ "SetTypeRefCho",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSetTypeRefPrim.erl b/lib/asn1/test/testSetTypeRefPrim.erl
index e6cec260e5..9c7fbd803e 100644
--- a/lib/asn1/test/testSetTypeRefPrim.erl
+++ b/lib/asn1/test/testSetTypeRefPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetTypeRefPrim).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -27,15 +26,6 @@
-record('SetTR',{octStr, octStrI, octStrE, 'octStr-I', 'octStrI-I', 'octStrE-I', 'octStr-E', 'octStrI-E', 'octStrE-E'}).
-compile(Config,Rules,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 ++ "SetTypeRefPrim",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testSetTypeRefSeq.erl b/lib/asn1/test/testSetTypeRefSeq.erl
index 0c1c9400bf..a3ef4b188d 100644
--- a/lib/asn1/test/testSetTypeRefSeq.erl
+++ b/lib/asn1/test/testSetTypeRefSeq.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetTypeRefSeq).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -31,15 +30,6 @@
-compile(Config,Rules,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 ++ "SetTypeRefSeq",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
?line {ok,Bytes41} =
diff --git a/lib/asn1/test/testSetTypeRefSet.erl b/lib/asn1/test/testSetTypeRefSet.erl
index 6544e77458..ce77316ef8 100644
--- a/lib/asn1/test/testSetTypeRefSet.erl
+++ b/lib/asn1/test/testSetTypeRefSet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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(testSetTypeRefSet).
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -46,15 +45,6 @@
-compile(Config,Rules,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 ++ "SetTypeRefSet",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
diff --git a/lib/asn1/test/testTCAP.erl b/lib/asn1/test/testTCAP.erl
index 5e29938a16..878ce7c070 100644
--- a/lib/asn1/test/testTCAP.erl
+++ b/lib/asn1/test/testTCAP.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,33 +19,23 @@
%%
-module(testTCAP).
--export([compile/3,test/2,compile_asn1config/3,test_asn1config/0]).
+-export([compile/2,test/2,compile_asn1config/2,test_asn1config/0]).
-include_lib("test_server/include/test_server.hrl").
+compile(Config, Options) ->
+ Files = ["Remote-Operations-Information-Objects",
+ "TCAPMessages",
+ "TCAPMessages-simple",
+ "TCAPPackage"],
+ asn1_test_lib:compile_all(Files, Config, Options),
+ asn1_test_lib:compile_erlang("TCAPPackage_msg", Config, []).
-
-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)),
-
- ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Information-Objects",[Rules,{outdir,OutDir}]++Opt),
-% ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Generic-ROS-PDUs",[Rules,{outdir,OutDir}]++Opt),
-% ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Useful-Definitions",[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "TCAPMessages",[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "TCAPMessages-simple",[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "TCAPPackage",[Rules,{outdir,OutDir}]++Opt),
- ?line compile:file(filename:join([DataDir,"TCAPPackage_msg"]),[{i,OutDir},{outdir,OutDir}]).
-
-compile_asn1config(Config,Rules,Opt) ->
- ?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 ++ "TCAPPackage",
- [Rules,{outdir,OutDir},{i,DataDir}]++Opt).
+compile_asn1config(Config, Options) ->
+ Files = ["Remote-Operations-Information-Objects",
+ "TCAPPackage"],
+ asn1_test_lib:compile_all(Files, Config, Options),
+ asn1_test_lib:compile_erlang("TCAPPackage_msg", Config, []).
test(Erule,_Config) when Erule==ber;Erule==ber_bin;Erule==ber_bin_v2 ->
% ?line OutDir = ?config(priv_dir,Config),
diff --git a/lib/asn1/test/testTcapsystem.erl b/lib/asn1/test/testTcapsystem.erl
index 2f13c11cd4..4979a385b2 100644
--- a/lib/asn1/test/testTcapsystem.erl
+++ b/lib/asn1/test/testTcapsystem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,54 +19,46 @@
%%
-module(testTcapsystem).
--export([compile/3]).
+-export([compile/2]).
-include_lib("test_server/include/test_server.hrl").
-
-
-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)),
- ?line DataDir2 = filename:join([DataDir,tcapsystem]),
-
- ?line ok = asn1ct:compile(filename:join([DataDir2,"DialoguePDUs.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ApplicationContexts.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-BS-Code.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-CallHandlingOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-CH-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-CommonDataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-DialogueInformation.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ER-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-Errors.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ExtensionDataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-GR-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-Group-Call-Operations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-LCS-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-LocationServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-MobileServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-MS-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-OM-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-OperationAndMaintenanceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-Protocol.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SecureTransportOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ShortMessageServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SM-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SS-Code.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SS-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ST-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SupplementaryServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-TS-Code.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"MobileDomainDefinitions.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"Remote-Operations-Generic-ROS-PDUs.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"Remote-Operations-Information-Objects.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"Remote-Operations-Useful-Definitions.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"TCAP-Examples.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"TCAPMessages.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"TCAP-Tools.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"TC-Notation-Extensions.asn"]),[Rules,{outdir,OutDir}]++Opt),
- ?line ok = asn1ct:compile(filename:join([DataDir2,"UnidialoguePDUs.asn"]),[Rules,{outdir,OutDir}]++Opt).
-
-
+compile(Config, Options) ->
+ [asn1_test_lib:compile(filename:join([tcapsystem, M]), Config, Options)
+ || M <- ["DialoguePDUs.asn",
+ "MAP-ApplicationContexts.asn",
+ "MAP-BS-Code.asn",
+ "MAP-CallHandlingOperations.asn",
+ "MAP-CH-DataTypes.asn",
+ "MAP-CommonDataTypes.asn",
+ "MAP-DialogueInformation.asn",
+ "MAP-ER-DataTypes.asn",
+ "MAP-Errors.asn",
+ "MAP-ExtensionDataTypes.asn",
+ "MAP-GR-DataTypes.asn",
+ "MAP-Group-Call-Operations.asn",
+ "MAP-LCS-DataTypes.asn",
+ "MAP-LocationServiceOperations.asn",
+ "MAP-MobileServiceOperations.asn",
+ "MAP-MS-DataTypes.asn",
+ "MAP-OM-DataTypes.asn",
+ "MAP-OperationAndMaintenanceOperations.asn",
+ "MAP-Protocol.asn",
+ "MAP-SecureTransportOperations.asn",
+ "MAP-ShortMessageServiceOperations.asn",
+ "MAP-SM-DataTypes.asn",
+ "MAP-SS-Code.asn",
+ "MAP-SS-DataTypes.asn",
+ "MAP-ST-DataTypes.asn",
+ "MAP-SupplementaryServiceOperations.asn",
+ "MAP-TS-Code.asn",
+ "MobileDomainDefinitions.asn",
+ "Remote-Operations-Generic-ROS-PDUs.asn",
+ "Remote-Operations-Information-Objects.asn",
+ "Remote-Operations-Useful-Definitions.asn",
+ "TCAP-Examples.asn",
+ "TCAPMessages.asn",
+ "TCAP-Tools.asn",
+ "TC-Notation-Extensions.asn",
+ "UnidialoguePDUs.asn"]],
+ ok.
diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl
index 74002e16e9..2d3b777558 100644
--- a/lib/asn1/test/testTimer.erl
+++ b/lib/asn1/test/testTimer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,12 +26,6 @@
-define(times, 5000).
-compile(Config,Enc,Options) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ok = asn1ct:compile(DataDir++"H235-SECURITY-MESSAGES",[Enc,{outdir,OutDir}]++Options),
- ok = asn1ct:compile(DataDir++"H323-MESSAGES",[Enc,{outdir,OutDir}]++Options).
-
val() ->
_Value = {'H323-UserInformation',{'H323-UU-PDU',
{callProceeding,
diff --git a/lib/asn1/test/testTypeValueNotation.erl b/lib/asn1/test/testTypeValueNotation.erl
index f0699370e0..cd5223ef23 100644
--- a/lib/asn1/test/testTypeValueNotation.erl
+++ b/lib/asn1/test/testTypeValueNotation.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,60 +19,43 @@
%%
-module(testTypeValueNotation).
--export([compile/3]).
-export([main/2]).
-include_lib("test_server/include/test_server.hrl").
--record('Seq',{octstr, int, bool, enum, bitstr, null, oid, vstr}).
-
-
-compile(Config,Rules,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 ++ "SeqTypeRefPrim",
- [Rules,{outdir,OutDir}]++Options),
- %% OTP-6695
- ?line ok = asn1ct:compile(DataDir ++ "ValueTest",
- [Rules,{outdir,OutDir}]++Options).
-
-
-main(Rules,Option) ->
-
- io:format("testTypeValueNotation:main/2 with arguments:~nRules: ~w, Option: ~w~n",[Rules,Option]),
- Value1 = #'Seq'{octstr = [1,2,3,4],
- int = 12,
- bool = true,
- enum = a,
- bitstr = [1,0,1,0],
- null = 'NULL',
- oid = {1,2,55},
- vstr = "Hello World"},
- Value2 = #'Seq'{octstr = {'OctStr',[1,2,3,4]},
- int = {'Int',12},
- bool = {'Bool',true},
- enum = {'Enum',a},
- bitstr = {'BitStr',[1,0,1,0]},
- null = {'Null','NULL'},
- oid = {'OId',{1,2,55}},
- vstr = {'VStr',"Hello World"}},
- case Option of
- optimize when Rules == per_bin; Rules == ber_bin ; Rules == uper_bin; Rules == ber_bin_v2 ->
- ?line {ok,Bytes} =
- asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value1),
- ?line {error,_Reason} =
- asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value2),
- ?line {ok,Value1} =
- asn1_wrapper:decode('SeqTypeRefPrim','Seq',Bytes);
- _ ->
- ?line {ok,Bytes} =
- asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value1),
- ?line {ok,Bytes} =
- asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value2),
- ?line {ok,Value1} =
- asn1_wrapper:decode('SeqTypeRefPrim','Seq',Bytes)
- end,
-
- ok.
+-record('Seq', {octstr, int, bool, enum, bitstr, null, oid, vstr}).
+
+main(Rule, Option) ->
+ Value1 = #'Seq'{octstr = [1, 2, 3, 4],
+ int = 12,
+ bool = true,
+ enum = a,
+ bitstr = [1, 0, 1, 0],
+ null = 'NULL',
+ oid = {1, 2, 55},
+ vstr = "Hello World"},
+ Value2 = #'Seq'{octstr = {'OctStr', [1, 2, 3, 4]},
+ int = {'Int', 12},
+ bool = {'Bool', true},
+ enum = {'Enum', a},
+ bitstr = {'BitStr', [1, 0, 1, 0]},
+ null = {'Null', 'NULL'},
+ oid = {'OId', {1, 2, 55}},
+ vstr = {'VStr', "Hello World"}},
+ main(Rule, Option, Value1, Value2).
+
+%% Value2 will fail for ber_bin_v2, per_bin with nifs (optimize) and uper_bin
+main(ber_bin_v2, _, Value1, Value2) -> encode_fail(Value1, Value2);
+main(per_bin, [optimize], Value1, Value2) -> encode_fail(Value1, Value2);
+main(uper_bin, [], Value1, Value2) -> encode_fail(Value1, Value2);
+main(_, _, Value1, Value2) -> encode_normal(Value1, Value2).
+
+encode_normal(Value1, Value2) ->
+ {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1),
+ {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value2),
+ {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes).
+
+encode_fail(Value1, Value2) ->
+ {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1),
+ {error, _Reason} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value2),
+ {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes).
diff --git a/lib/asn1/test/testX420.erl b/lib/asn1/test/testX420.erl
index 1d18e76c48..abdbbfe536 100644
--- a/lib/asn1/test/testX420.erl
+++ b/lib/asn1/test/testX420.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,32 +26,21 @@
-include_lib("test_server/include/test_server.hrl").
-compile(Erule,Options,Config) ->
-
+compile(Erule, Options, Config) ->
Specs = specs(),
- ?line 99 = length(Specs),
- ?line ok = compile_loop(Erule,Specs,Options,Config).
-
-
+ 99 = length(Specs),
+ ok = compile_loop(Erule,Specs,Options,Config).
-compile_loop(_Erule,[],_Options,_Config) ->
+compile_loop(_Erule, [], _Options, _Config) ->
ok;
-compile_loop(Erule,[Spec|Specs],Options,Config)
- when Erule == ber; Erule == ber_bin; Erule == ber_bin_v2;
- Erule == per ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- case asn1ct:compile(DataDir ++ "/x420/" ++ Spec,[Erule,{outdir,OutDir},
- {i,OutDir}]++Options) of
- ok ->
- compile_loop(Erule,Specs,Options,Config);
- Error ->
- Error
- end;
-compile_loop(_Erule,_Specs,_Options,_Config) ->
- ok.%%{skip,io_lib:format("Not tested for ~p",[Erule])}.
+compile_loop(Erule, [Spec|Specs], Options, Config)
+ when Erule == ber; Erule == ber_bin; Erule == ber_bin_v2; Erule == per ->
+ CaseDir = ?config(case_dir, Config),
+ asn1_test_lib:compile(filename:join([x420, Spec]), Config,
+ [Erule, {i, CaseDir}]),
+ compile_loop(Erule, Specs, Options, Config);
+compile_loop(_Erule, _Specs, _Options, _Config) ->
+ ok.
specs() ->
@@ -91,7 +80,7 @@ specs() ->
"Protected-Part-Descriptors", "ProtocolObjectIdentifiers",
"Raster-Gr-Coding-Attributes", "Raster-Gr-Presentation-Attributes",
"Raster-Gr-Profile-Attributes", "Reliable-Transfer-APDU",
- "Remote-Operations-Abstract-Syntaxes",
+ "Remote-Operations-Abstract-Syntaxes",
"Remote-Operations-Generic-ROS-PDUs",
"Remote-Operations-Information-Objects-extensions",
"Remote-Operations-Information-Objects",
diff --git a/lib/asn1/test/test_bad_values.erl b/lib/asn1/test/test_bad_values.erl
deleted file mode 100644
index d379a509ab..0000000000
--- a/lib/asn1/test/test_bad_values.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%
-%% %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%
-%%
-%%
--module(test_bad_values).
-
--export([tests/1]).
--include_lib("test_server/include/test_server.hrl").
-
-tests(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line {error,_R} = asn1ct:compile(DataDir ++ "BadEnumValue1",[{outdir,OutDir}]),
- ok.
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index a622d5bfd2..4e732308d8 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,10 +40,7 @@ wrong_path(Config) ->
comp(Parent,Config) ->
DataDir = ?config(data_dir,Config),
OutDir = ?config(priv_dir,Config),
- %%?line true = code:add_patha(?config(priv_dir,Config)),
- io:format("DataDir: ~p~n",[DataDir]),
?line Err=asn1ct:compile(DataDir++"NoImport",[{i,OutDir},{i,filename:join([DataDir,"subdir"])},{outdir,OutDir}]),
- io:format("compiling process terminated with value: ~p~n",[Err]),
Parent!Err.
%% OTP-5701
@@ -67,13 +64,7 @@ path(Config) ->
file:set_cwd(CWD),
ok.
-ticket_6143(Config) ->
- DataDir = ?config(data_dir,Config),
- OutDir = ?config(priv_dir,Config),
- io:format("DataDir: ~p~n",[DataDir]),
-
- ?line ok=asn1ct:compile(filename:join([DataDir,"AA1"]),[{i,DataDir},{outdir,OutDir}]),
- ok.
+ticket_6143(Config) -> asn1_test_lib:compile("AA1", Config, []).
noobj(Config) ->
DataDir = ?config(data_dir,Config),
diff --git a/lib/asn1/test/test_driver_load.erl b/lib/asn1/test/test_driver_load.erl
index 965f2473e9..e0e6602046 100644
--- a/lib/asn1/test/test_driver_load.erl
+++ b/lib/asn1/test/test_driver_load.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,29 +19,16 @@
%%
-module(test_driver_load).
--export([compile/2,test/2,encode/0]).
+-export([test/1,encode/0]).
-include_lib("test_server/include/test_server.hrl").
-test(per_bin,0) ->
+test(0) ->
ok;
-test(per_bin,N) ->
+test(N) ->
spawn(?MODULE,encode,[]),
- test(per_bin,N-1);
-test(_,_) ->
- ok.
-
-compile(Config,per_bin) ->
- ?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 ++ "P-Record",
- [per_bin,optimize,{outdir,OutDir}]);
-compile(_,Erule) ->
- {skip,lists:concat(["not implemented for version: ",Erule])}.
-
+ test(N-1).
encode() ->
?line Msg = msg(),
diff --git a/lib/asn1/test/test_inline.erl b/lib/asn1/test/test_inline.erl
index b7ec0d8921..62625572e3 100644
--- a/lib/asn1/test/test_inline.erl
+++ b/lib/asn1/test/test_inline.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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(test_inline).
--export([compile/3,main/1,inline1/3,performance/1,performance2/0]).
+-export([compile/2,main/2,inline1/3,performance/1,performance2/0]).
-export([mvrasn_inlined_encdec/2,mvrasn_encdec/2,
mi_encdec/2,m_encdec/2]).
@@ -27,52 +27,38 @@
-define(times, 5000).
-define(times2, 50000).
-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)),
- ?line true = code:add_patha(DataDir),
-
- ?line ok=asn1ct:compile(DataDir++"Mvrasn.set.asn",[{inline,mvrasn_inlined},{outdir,OutDir}]++Opt),
- ?line ok=asn1ct:compile(DataDir++"Mvrasn-11-6.asn",[{outdir,OutDir}]++Opt),
+compile(Config, Options) ->
+ CaseDir = ?config(case_dir, Config),
+ asn1_test_lib:compile("Mvrasn.set.asn", Config, [{inline, mvrasn_inlined}|Options]),
+ asn1_test_lib:compile("Mod.set.asn", Config, [{inline, m}|Options]),
+ ok = remove_inlined_files(CaseDir, [filename:join([CaseDir, X])||X<-["m.erl", "m.beam"]]),
+ asn1_test_lib:compile("Mod.set.asn", Config, [inline|Options]),
+ ok = remove_inlined_files(CaseDir, []).
- ?line ok=asn1ct:compile(DataDir++"Mod.set.asn",[{inline,m},{outdir,OutDir}]++Opt),
- ?line ok=remove_inlined_files(OutDir,[filename:join([OutDir,X])||X<-["m.erl","m.beam"]]),
- ?line ok=asn1ct:compile(DataDir++"Mod.set.asn",[inline,{outdir,OutDir}]++Opt),
- ?line ok=remove_inlined_files(OutDir,[]).
-
-inline1(Config,Rule,Opt) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ?line ok=asn1ct:compile(DataDir++"P-Record",
- [{inline,'inlined_P_Record'},
- {outdir,OutDir}]++Opt),
- ?line test_inline1(),
-
- ?line ok=remove_inlined_files2(OutDir,ber_bin_v2),
+inline1(Config, Rule, Opt) ->
+ CaseDir = ?config(case_dir, Config),
+
+ asn1_test_lib:compile("P-Record", Config, [{inline, 'inlined_P_Record'}|Opt]),
+ test_inline1(),
+
+ ok=remove_inlined_files2(CaseDir, ber_bin_v2),
case Rule of
- ber_bin_v2 ->
- ?line ok=asn1ct:compile(DataDir++"P-Record",
- [inline,asn1config,ber_bin,optimize,
- {outdir,OutDir}]++Opt),
- ?line test_inline2(Rule,'P-Record'),
- ?line remove_inlined_files3(OutDir,Rule),
- io:format("compiling ~p~nwith ~p~n",
- [DataDir ++ "p_record.set.asn",
- [inline,asn1config,ber_bin,optimize,{outdir,OutDir}]++Opt]),
- ?line ok = asn1ct:compile(DataDir ++ "p_record.set.asn",
- [inline,asn1config,ber_bin,optimize,
- {outdir,OutDir}]++Opt),
- ?line test_inline2(Rule,'p_record'),
- ?line remove_inlined_files4(OutDir,Rule);
- _ ->
- ok
+ ber_bin_v2 ->
+ asn1_test_lib:compile("P-Record", Config,
+ [ber_bin, inline, asn1config, optimize|Opt]),
+ test_inline2(Rule, 'P-Record'),
+ remove_inlined_files3(CaseDir, Rule),
+ asn1_test_lib:compile("p_record.set.asn", Config,
+ [ber_bin, inline, asn1config, optimize|Opt]),
+ test_inline2(Rule, 'p_record'),
+ remove_inlined_files4(CaseDir, Rule);
+ _ ->
+ ok
end.
-main(_Erule) ->
- ?line Val = val(),
+main(Config, _Erule) ->
+ Val = val(Config),
?line {ok,Bytes}=asn1_wrapper:encode(mvrasn_inlined,'InsertSubscriberDataArg',Val),
?line {ok,_Val2}=asn1_wrapper:decode(mvrasn_inlined,'InsertSubscriberDataArg',Bytes).
@@ -94,14 +80,13 @@ test_inline2(ber_bin_v2,Mod) ->
test_inline2(_,_) ->
ok.
-val() ->
- ?line {ok,Val} = asn1ct:value('Mvrasn-11-6','InsertSubscriberDataArg'),
+val(Config) ->
+ {ok,Val} = asn1ct:value('Mvrasn','InsertSubscriberDataArg',
+ [{i, ?config(case_dir, Config)}]),
Val.
performance(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line true = code:add_patha(?config(data_dir,Config)),
- ?line Val = val(),
+ Val = val(Config),
%% warm up
timer:tc(?MODULE,mvrasn_inlined_encdec,[2,Val]),
%% performance test
diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl
index 4e96db070b..2e9dfeee87 100644
--- a/lib/asn1/test/test_modified_x420.erl
+++ b/lib/asn1/test/test_modified_x420.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +20,10 @@
-module(test_modified_x420).
%-compile(export_all).
--export([compile/1, test_io/1]).
+-export([test_io/1]).
-include_lib("test_server/include/test_server.hrl").
-compile(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ok = asn1ct:compile(filename:join([DataDir,modified_x420,"PKCS7"]),[der,{outdir,OutDir}]),
- ok = asn1ct:compile(filename:join([DataDir,modified_x420,"InformationFramework"]),[der,{outdir,OutDir}]),
- ok = asn1ct:compile(filename:join([DataDir,modified_x420,"AuthenticationFramework"]),[der,{outdir,OutDir}]).
-
test_io(Config) ->
io:format("~p~n~n", [catch test(Config)]).
diff --git a/lib/asn1/test/test_partial_incomplete_decode.erl b/lib/asn1/test/test_partial_incomplete_decode.erl
index a2e0a96bd8..df56c27115 100644
--- a/lib/asn1/test/test_partial_incomplete_decode.erl
+++ b/lib/asn1/test/test_partial_incomplete_decode.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,40 +19,11 @@
%%
-module(test_partial_incomplete_decode).
--export([compile/3,test/2]).
+-export([test/1]).
-include_lib("test_server/include/test_server.hrl").
-
-
-compile(Config,Rule,Opt) when Rule == ber_bin_v2 ->
-
- ?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 ++ "PartialDecSeq.asn",
- [Rule,{outdir,OutDir},{i,DataDir},
- asn1config]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "PartialDecSeq2.asn",
- [Rule,{outdir,OutDir},{i,DataDir},
- asn1config]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "PartialDecSeq3.asn",
- [Rule,{outdir,OutDir},{i,DataDir},
- asn1config]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "PartialDecMyHTTP.asn",
- [Rule,{outdir,OutDir},{i,DataDir},
- asn1config]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "MEDIA-GATEWAY-CONTROL.asn",
- [Rule,{outdir,OutDir},{i,DataDir},
- asn1config]++Opt),
- ?line ok = asn1ct:compile(DataDir ++ "P-Record",
- [Rule,{outdir,OutDir},{i,DataDir},
- asn1config]++Opt);
-compile(_,Rule,_) ->
- {skip,lists:concat(["not implemented yet for version: ",Rule])}.
-
-test(ber_bin_v2,Config) ->
+test(Config) ->
FMsg = msg('F'),
?line {ok,Bytes} = asn1_wrapper:encode('PartialDecSeq','F',FMsg),
?line {ok,_} = asn1_wrapper:decode('PartialDecSeq','F',Bytes),
@@ -110,9 +81,7 @@ test(ber_bin_v2,Config) ->
%% test of MEDIA-GATEWAY-CONTROL
test_megaco(Config),
- ok;
-test(Erule,_) ->
- {skip,lists:concat(["not implemented yet for version: ",Erule])}.
+ ok.
test_megaco(Config) ->
?line DataDir = ?config(data_dir,Config),
diff --git a/lib/asn1/test/test_selective_decode.erl b/lib/asn1/test/test_selective_decode.erl
index e1e101b622..bb348611da 100644
--- a/lib/asn1/test/test_selective_decode.erl
+++ b/lib/asn1/test/test_selective_decode.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,12 +19,12 @@
%%
-module(test_selective_decode).
--export([test/2]).
+-export([test/0]).
-include_lib("test_server/include/test_server.hrl").
-test(ber_bin_v2,_Config) ->
+test() ->
FMsg = msg('F'),
?line {ok,Bytes} = asn1_wrapper:encode('PartialDecSeq','F',FMsg),
?line {ok,3} =
@@ -48,10 +48,7 @@ test(ber_bin_v2,_Config) ->
?line {ok,Bytes4} = asn1_wrapper:encode('P-Record','PersonnelRecord',
PRecMsg),
?line {ok,_} = 'P-Record':sel_dec(list_to_binary(Bytes4)),
-
- ok;
-test(Erule,_) ->
- {skip,lists:concat(["not implemented yet for version: ",Erule])}.
+ ok.
diff --git a/lib/asn1/test/test_special_decode_performance.erl b/lib/asn1/test/test_special_decode_performance.erl
index 60a95a3675..4ac0ff2b27 100644
--- a/lib/asn1/test/test_special_decode_performance.erl
+++ b/lib/asn1/test/test_special_decode_performance.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,25 +19,10 @@
%%
-module(test_special_decode_performance).
--export([compile/2,go/1,loop2/4,loop1/5]).
+-export([go/1,loop2/4,loop1/5]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rule) when Rule==ber_bin_v2 ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line asn1ct:compile(DataDir++"MEDIA-GATEWAY-CONTROL",
- [ber_bin,optimize,asn1config,{outdir,OutDir},
- {i,DataDir}]),
- ?line asn1ct:compile(DataDir++"PartialDecSeq",
- [ber_bin,optimize,asn1config,{outdir,OutDir},
- {i,DataDir}]);
-compile(_,Rule) ->
- {skip,lists:concat(["not implemented yet for version: ",Rule])}.
-
go(all) ->
{Time_S_s,Time_S_e,Time_S_c}=go(10000,'PartialDecSeq'),
{Time_MGC_s,Time_MGC_e,Time_MGC_c}=go(10000,'MEDIA-GATEWAY-CONTROL'),
diff --git a/lib/asn1/test/test_undecoded_rest.erl b/lib/asn1/test/test_undecoded_rest.erl
index 647fe2bb1c..36fd26ed59 100644
--- a/lib/asn1/test/test_undecoded_rest.erl
+++ b/lib/asn1/test/test_undecoded_rest.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,47 +19,35 @@
%%
-module(test_undecoded_rest).
--export([compile/3,test/1]).
+-export([test/2]).
-include_lib("test_server/include/test_server.hrl").
%% testing OTP-5104
-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)),
-
- ?line ok = asn1ct:compile(DataDir ++ "P-Record",[Rules,{outdir,OutDir}]++Opt).
-
-
-test(Opt) ->
- ?line {ok,Msg} = asn1ct:value('P-Record','PersonnelRecord'),
- ?line {ok,Bytes} = asn1_wrapper:encode('P-Record','PersonnelRecord',Msg),
- Bytes2 =
- fun(B) when is_list(B) ->
- B ++ [55,55,55];
- (B) when is_binary(B) ->
- iolist_to_binary([B,<<55,55,55>>])
- end (Bytes),
-
+test(Opt, Config) ->
+ {ok, Msg} = asn1ct:value('P-Record', 'PersonnelRecord',
+ [{i, ?config(case_dir, Config)}]),
+ {ok, Bytes} = asn1_wrapper:encode('P-Record', 'PersonnelRecord', Msg),
+ Bytes2 = if is_list(Bytes) ->
+ Bytes ++ [55, 55, 55];
+ is_binary(Bytes) ->
+ iolist_to_binary([Bytes, <<55, 55, 55>>])
+ end,
case Opt of
- undec_rest ->
- ?line {ok,Msg,R}=asn1_wrapper:decode('P-Record','PersonnelRecord',
- Bytes2),
- ?line case R of
- <<55,55,55>> ->ok;
- [55,55,55] -> ok;
- BStr when is_bitstring(BStr) ->
- PadLen = (8 - (bit_size(BStr) rem 8)) rem 8,
- case <<0:PadLen,BStr/bitstring>> of
- <<0,55,55,55>> -> ok
- end
- end;
- _ ->
- ?line {ok,Msg} = asn1_wrapper:decode('P-Record','PersonnelRecord',
- Bytes2)
+ undec_rest ->
+ {ok, Msg, R} = asn1_wrapper:decode('P-Record', 'PersonnelRecord',
+ Bytes2),
+ case R of
+ <<55, 55, 55>> -> ok;
+ [55, 55, 55] -> ok;
+ BStr when is_bitstring(BStr) ->
+ PadLen = (8 - (bit_size(BStr) rem 8)) rem 8,
+ <<0, 55, 55, 55>> = <<0:PadLen, BStr/bitstring>>
+ end;
+ _ ->
+ {ok, Msg} = asn1_wrapper:decode('P-Record', 'PersonnelRecord',
+ Bytes2)
end,
ok.
diff --git a/lib/asn1/test/test_x691.erl b/lib/asn1/test/test_x691.erl
index bc8a3495d8..dcfa211d80 100644
--- a/lib/asn1/test/test_x691.erl
+++ b/lib/asn1/test/test_x691.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,25 +19,10 @@
%%
-module(test_x691).
--export([compile/3]).
-export([cases/2]).
-include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,Option) ->
-
- ?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 ++ "P-RecordA1",
- [Rules, {outdir,OutDir}]++Option),
- ?line ok = asn1ct:compile(DataDir ++ "P-RecordA2",
- [Rules, {outdir,OutDir}]++Option),
- ?line ok = asn1ct:compile(DataDir ++ "P-RecordA3",
- [Rules, {outdir,OutDir}]++Option).
-
-
cases(Erule,Variant) ->
MsgA1 = a1(),
?line {ok,B1} = asn1_wrapper:encode('P-RecordA1','PersonnelRecord',MsgA1),
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index b1132155e6..04f4b22421 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.18
+#next version number to use is 2.0
+ASN1_VSN = 1.7
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile
index 3ea6ae65d5..99161ce68a 100644
--- a/lib/common_test/doc/src/Makefile
+++ b/lib/common_test/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2011. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -46,7 +46,8 @@ CT_MODULES = \
ct_rpc \
ct_snmp \
unix_telnet \
- ct_slave
+ ct_slave \
+ ct_netconfc
CT_XML_FILES = $(CT_MODULES:=.xml)
@@ -61,6 +62,7 @@ XML_PART_FILES = part.xml
XML_CHAPTER_FILES = \
basics_chapter.xml \
+ getting_started_chapter.xml \
install_chapter.xml \
write_test_chapter.xml \
test_structure_chapter.xml \
@@ -80,7 +82,10 @@ MAKE_EDOC = make_edoc
BOOK_FILES = book.xml
-GIF_FILES =
+GIF_FILES = \
+ tc_execution.gif \
+ config.gif \
+ html_logs.gif
INSTALL_NOTES = ../../notes.html
@@ -119,7 +124,7 @@ $(HTMLDIR)/%.gif: %.gif
docs: pdf html man
-$(CT_XML_FILES):
+$(CT_XML_FILES): %.xml: ../../src/%.erl
escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -preprocess true -i $(XMERL_DIR)/include \
-i ../../../test_server/include -i ../../include \
-i ../../../../erts/lib/kernel/include -i ../../../../lib/kernel/include \
@@ -138,12 +143,6 @@ man: $(MAN6_FILES) $(MAN3_FILES) $(MAN1_FILES)
debug opt:
-#
-# checkout make.dep before generating new dependecies
-#
-#make_doc_depend: xml
-# docdepend > make.dep
-
clean clean_docs:
rm -f $(CT_XML_FILES)
rm -rf $(HTMLDIR)/*
@@ -160,28 +159,19 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1DIR)/* $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6DIR)/* $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DATA) $(MAN1DIR)/* "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
release_spec:
release_tests_spec:
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-include make.dep
-# DO NOT DELETE
-
-
diff --git a/lib/common_test/doc/src/basics_chapter.xml b/lib/common_test/doc/src/basics_chapter.xml
index c1bb365b1f..ff6ea6c557 100644
--- a/lib/common_test/doc/src/basics_chapter.xml
+++ b/lib/common_test/doc/src/basics_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,54 +28,65 @@
<rev></rev>
<file>basics_chapter.xml</file>
</header>
-
+ <marker id="basics"></marker>
<section>
<title>Introduction</title>
- <p>
- The Common Test framework (CT) is a tool which can support
- implementation and automated execution of test cases towards different
- types of target systems. The framework is based on the OTP Test
- Server. Test cases can be run individually or in batches. Common
- Test also features a distributed testing mode with central
- control and logging. This feature makes it possible to test
- multiple systems independently in one common session. This
- can be very useful e.g. for running automated large-scale regression
- tests.
+ <p>The <em>Common Test</em> framework (CT) is a tool which supports
+ implementation and automated execution of test cases towards arbitrary
+ types of target systems. The CT framework is based on the OTP Test
+ Server and it's the main tool being used in all testing- and verification
+ activities that are part of Erlang/OTP system development- and maintenance.
+ </p>
+
+ <p>Test cases can be executed individually or in batches. Common Test
+ also features a distributed testing mode with central control and logging
+ (a feature that makes it possible to test multiple systems independently in
+ one common session, useful e.g. for running automated large-scale regression
+ tests).
</p>
<p>
The SUT (System Under Test) may consist of one or several target
- nodes. CT contains a generic test server which together with
- other test utilities is used to perform test case execution.
- It is possible to start the tests from the CT GUI or from an OS- or
- Erlang shell prompt. <em>Test suites</em> are files (Erlang
+ nodes. CT contains a generic test server which, together with
+ other test utilities, is used to perform test case execution.
+ It is possible to start the tests from a GUI or from the OS- or
+ Erlang shell. <em>Test suites</em> are files (Erlang
modules) that contain the <em>test cases</em> (Erlang functions)
to be executed. <em>Support modules</em> provide functions
that the test cases utilize in order to carry out the tests.
</p>
- <p>
- The main idea is that CT based test programs connect to
- the target system(s) via standard O&amp;M interfaces. CT
- provides implementations and wrappers of some of these O&amp;M
- interfaces and will be extended with more interfaces later.
- There are a number of target independent interfaces
- supported in CT such as Generic Telnet, FTP etc. which can be
- specialized or used directly for controlling instruments,
- traffic generators etc.</p>
+ <p>In a black-box testing scenario, CT based test programs connect to
+ the target system(s) via standard O&amp;M and CLI protocols. CT
+ provides implementations of, and wrapper interfaces to, some of these
+ protocols (most of which exist as stand-alone components and
+ applications in OTP). The wrappers simplify configuration and add
+ verbosity for logging purposes. CT will be continously extended with
+ useful support modules. (Note however that it's
+ a straightforward task to use any arbitrary Erlang/OTP component
+ for testing purposes with Common Test, without needing a CT wrapper
+ for it. It's as simple as calling Erlang functions). There
+ are a number of target independent interfaces supported in CT, such as
+ Generic Telnet, FTP, etc, which can be specialized or used
+ directly for controlling instruments, traffic load generators, etc.
+ </p>
<p>Common Test is also a very useful tool for white-box testing Erlang
- code since the test programs can call Erlang API functions directly.
- For black-box testing Erlang software, Erlang RPC as well as
- standard O&amp;M interfaces can be used.
+ code (e.g. module testing), since the test programs can call exported Erlang
+ functions directly and there's very little overhead required for
+ implementing basic test suites and executing simple tests. For black-box
+ testing Erlang software, Erlang RPC as well as standard O&amp;M interfaces
+ can for example be used.
</p>
<p>A test case can handle several connections towards one or
several target systems, instruments and traffic generators in
parallel in order to perform the necessary actions for a
test. The handling of many connections in parallel is one of
- the major strengths of Common Test!
+ the major strengths of Common Test (thanks to the efficient
+ support for concurrency in the Erlang runtime system - which CT users
+ can take great advantage of!).
</p>
</section>
@@ -130,8 +141,9 @@
individual test case.
</p>
<p>
- The test suite module must conform to a callback interface specified
- by the CT test server. See the
+ The test suite module must conform to a
+ <seealso marker="common_test">callback interface</seealso>
+ specified by the CT test server. See the
<seealso marker="write_test_chapter#intro">Writing Test Suites</seealso> chapter
for more information.
</p>
@@ -186,7 +198,7 @@
<taglist>
<tag>all()</tag>
- <item>Returns a list of all test cases in the suite. (Mandatory)</item>
+ <item>Returns a list of all test cases and groups in the suite. (Mandatory)</item>
<tag>suite()</tag>
<item>Info function used to return properties for the suite. (Optional)</item>
<tag>groups()</tag>
@@ -197,12 +209,14 @@
<tag>end_per_suite(Config)</tag>
<item>Suite level configuration function, executed after the last
test case. (Optional)</item>
+ <tag>group(GroupName)</tag>
+ <item>Info function used to return properties for a test case group. (Optional)</item>
<tag>init_per_group(GroupName, Config)</tag>
<item>Configuration function for a group, executed before the first
- test case. (Mandatory if groups are defined)</item>
+ test case. (Optional)</item>
<tag>end_per_group(GroupName, Config)</tag>
<item>Configuration function for a group, executed after the last
- test case. (Mandatory if groups are defined)</item>
+ test case. (Optional)</item>
<tag>init_per_testcase(TestCase, Config)</tag>
<item>Configuration function for a testcase, executed before each
test case. (Optional)</item>
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml
index f58b2ab0a9..a0fa45c71f 100644
--- a/lib/common_test/doc/src/common_test_app.xml
+++ b/lib/common_test/doc/src/common_test_app.xml
@@ -69,12 +69,25 @@
<funcs>
<func>
- <name>Module:all() -> TestCases | {skip,Reason} </name>
- <fsummary>Returns the list of all test cases in the module.</fsummary>
+ <name>Module:all() -> Tests | {skip,Reason} </name>
+ <fsummary>Returns the list of all test case groups and test cases
+ in the module.</fsummary>
<type>
- <v>TestCases = [atom() | {group,GroupName}]</v>
- <v>Reason = term()</v>
+ <v>Tests = [TestCase | {group,GroupName} |
+ {group,GroupName,Properties} |
+ {group,GroupName,Properties,SubGroups}]</v>
+ <v>TestCase = atom()</v>
<v>GroupName = atom()</v>
+ <v>Properties = [parallel | sequence | Shuffle | {RepeatType,N}] |
+ default</v>
+ <v>SubGroups = [{GroupName,Properties} |
+ {GroupName,Properties,SubGroups}]</v>
+ <v>Shuffle = shuffle | {shuffle,Seed}</v>
+ <v>Seed = {integer(),integer(),integer()}</v>
+ <v>RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+ repeat_until_any_ok | repeat_until_any_fail</v>
+ <v>N = integer() | forever</v>
+ <v>Reason = term()</v>
</type>
<desc>
@@ -85,9 +98,14 @@
This list also specifies the order the cases and groups will
be executed by Common Test. A test case is represented by an atom,
the name of the test case function. A test case group is
- represented by a <c>{group,GroupName}</c> tuple, where
- <c>GroupName</c>, an atom, is the name of the group (defined
- with <c>groups/0</c>).</p>
+ represented by a <c>group</c> tuple, where <c>GroupName</c>,
+ an atom, is the name of the group (defined in <c><seealso marker="#Module:groups-0">groups/0</seealso></c>).
+ Execution properties for groups may also be specified, both
+ for a top level group and for any of its sub-groups.
+ Group execution properties specified here, will override
+ properties in the group definition (see <c><seealso marker="#Module:groups-0">groups/0</seealso></c>).
+ (With value <c>default</c>, the group definition properties
+ will be used).</p>
<p> If <c>{skip,Reason}</c> is returned, all test cases
in the module will be skipped, and the <c>Reason</c> will
@@ -120,14 +138,16 @@
<desc>
<p> OPTIONAL </p>
- <p>See <seealso marker="write_test_chapter#test_case_groups">Test case
+ <p>Function for defining test case groups. Please see
+ <seealso marker="write_test_chapter#test_case_groups">Test case
groups</seealso> in the User's Guide for details.</p>
</desc>
</func>
<func>
<name>Module:suite() -> [Info] </name>
- <fsummary>Test suite info function (providing default data for the suite).</fsummary>
+ <fsummary>Test suite info function (providing default data
+ for the suite).</fsummary>
<type>
<v> Info = {timetrap,Time} | {require,Required} |
{require,Name,Required} | {userdata,UserData} |
@@ -142,7 +162,7 @@
<v> Func = atom()</v>
<v> Args = list()</v>
<v> Fun = fun()</v>
- <v> Required = Key | {Key,SubKeys}</v>
+ <v> Required = Key | {Key,SubKeys} | {Key,SubKey} | {Key,SubKey,SubKeys}</v>
<v> Key = atom()</v>
<v> SubKeys = SubKey | [SubKey]</v>
<v> SubKey = atom()</v>
@@ -160,28 +180,32 @@
<p>This is the test suite info function. It is supposed to
return a list of tagged tuples that specify various properties
- regarding the execution of this test suite (common for all
+ related to the execution of this test suite (common for all
test cases in the suite).</p>
<p>The <c>timetrap</c> tag sets the maximum time each
- 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
+ test case is allowed to execute (including <c><seealso marker="#Module:init_per_testcase-2">init_per_testcase/2</seealso></c>
+ and <c><seealso marker="#Module:end_per_testcase-2">end_per_testcase/2</seealso></c>). If the timetrap time is
exceeded, the test case fails with reason
- <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>
+ <c>timetrap_timeout</c>. A <c>TimeFunc</c> function can be used to
+ set a new timetrap by returning a <c>TimeVal</c>. It may also be
+ used to trigger a timetrap timeout by, at some point, returning a
+ value other than a <c>TimeVal</c>. (See the
+ <seealso marker="write_test_chapter#timetraps">User's Guide</seealso>
+ for details).
+ </p>
<p>The <c>require</c> tag specifies configuration variables
- that are required by test cases in the suite. If the required
- configuration variables are not found in any of the
- configuration files, all test cases are skipped. For more
+ that are required by test cases (and/or configuration functions)
+ in the suite. If the required configuration variables are not found
+ in any of the configuration files, all test cases are skipped. For more
information about the 'require' functionality, see the
reference manual for the function
- <c>ct:require/[1,2]</c>.</p>
+ <c><seealso marker="ct#require-1">ct:require/1/2</seealso></c>.</p>
<p>With <c>userdata</c>, it is possible for the user to
specify arbitrary test suite related information which can be
- read by calling <c>ct:userdata/2</c>.</p>
+ read by calling <c><seealso marker="ct#userdata-2">ct:userdata/2</seealso></c>.</p>
<p>The <c>ct_hooks</c> tag specifies which
<seealso marker="ct_hooks_chapter">Common Test Hooks</seealso>
@@ -196,8 +220,9 @@
</func>
<func>
- <name>Module:init_per_suite(Config) -> NewConfig | {skip,Reason} | {skip_and_save,Reason,SaveConfig}</name>
- <fsummary>Test suite initialization.</fsummary>
+ <name>Module:init_per_suite(Config) -> NewConfig | {skip,Reason} |
+ {skip_and_save,Reason,SaveConfig}</name>
+ <fsummary>Test suite initializations.</fsummary>
<type>
<v> Config = NewConfig = SaveConfig = [{Key,Value}]</v>
<v> Key = atom()</v>
@@ -208,15 +233,15 @@
<p> OPTIONAL </p>
- <p>This function is called as the first function in the
- suite. It typically contains initialization which is common for
+ <p>This configuration function is called as the first function in the
+ suite. It typically contains initializations which are common for
all test cases in the suite, and which shall only be done
- once. The <c>Config</c> parameter is the configuration
+ once. The <c>Config</c> parameter is the configuration data
which can be modified here. Whatever is returned from this
function is given as <c>Config</c> to all configuration functions
and test cases in the suite. If <c>{skip,Reason}</c>
- is returned, all test cases in the suite will be skipped and <c>Reason</c>
- printed in the overview log for the suite.</p>
+ is returned, all test cases in the suite will be skipped
+ and <c>Reason</c> printed in the overview log for the suite.</p>
<p>For information on <c>save_config</c> and <c>skip_and_save</c>,
please see
<seealso marker="dependencies_chapter#save_config">Dependencies
@@ -224,29 +249,110 @@
</desc>
</func>
- <func>
- <name>Module:end_per_suite(Config) -> void() | {save_config,SaveConfig}</name>
- <fsummary>Test suite finalization. </fsummary>
- <type>
- <v> Config = SaveConfig = [{Key,Value}]</v>
- <v> Key = atom()</v>
- <v> Value = term()</v>
- </type>
+ <func>
+ <name>Module:end_per_suite(Config) -> void() |
+ {save_config,SaveConfig}</name>
+ <fsummary>Test suite finalization. </fsummary>
+ <type>
+ <v> Config = SaveConfig = [{Key,Value}]</v>
+ <v> Key = atom()</v>
+ <v> Value = term()</v>
+ </type>
+
+ <desc>
+ <p> OPTIONAL </p>
+ <p>This function is called as the last test case in the
+ suite. It is meant to be used for cleaning up after
+ <c><seealso marker="#Module:init_per_suite-1">init_per_suite/1</seealso></c>.
+ For information on <c>save_config</c>, please see
+ <seealso marker="dependencies_chapter#save_config">Dependencies
+ between Test Cases and Suites</seealso> in the User's Guide.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:group(GroupName) -> [Info] </name>
+ <fsummary>Test case group info function (providing default data
+ for a test case group, i.e. its test cases and sub-groups).</fsummary>
+ <type>
+ <v> Info = {timetrap,Time} | {require,Required} |
+ {require,Name,Required} | {userdata,UserData} |
+ {silent_connections,Conns} | {stylesheet,CSSFile} |
+ {ct_hooks, CTHs}</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} | {Key,Subkey} | {Key,Subkey,SubKeys}</v>
+ <v> Key = atom()</v>
+ <v> SubKeys = SubKey | [SubKey]</v>
+ <v> SubKey = atom()</v>
+ <v> Name = atom()</v>
+ <v> UserData = term()</v>
+ <v> Conns = [atom()]</v>
+ <v> CSSFile = string()</v>
+ <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} |
+ {CTHModule, CTHInitArgs, CTHPriority}]</v>
+ <v> CTHModule = atom()</v>
+ <v> CTHInitArgs = term()</v>
+ </type>
<desc>
+
<p> OPTIONAL </p>
- <p>This function is called as the last test case in the
- suite. It is meant to be used for cleaning up after <c>init_per_suite/1</c>.
- For information on <c>save_config</c>, please see
- <seealso marker="dependencies_chapter#save_config">Dependencies between
- Test Cases and Suites</seealso> in the User's Guide.</p>
- </desc>
+ <p>This is the test case group info function. It is supposed to
+ return a list of tagged tuples that specify various properties
+ related to the execution of a test case group (i.e. its test cases
+ and sub-groups). Properties set by
+ <c><seealso marker="#Module:group-1">group/1</seealso></c> override
+ properties with the same key that have been previously set by
+ <c><seealso marker="#Module:suite-0">suite/0</seealso></c>.</p>
+
+ <p>The <c>timetrap</c> tag sets the maximum time each
+ test case is allowed to execute (including <c><seealso marker="#Module:init_per_testcase-2">init_per_testcase/2</seealso></c>
+ and <c><seealso marker="#Module:end_per_testcase-2">end_per_testcase/2</seealso></c>). If the timetrap time is
+ exceeded, the test case fails with reason
+ <c>timetrap_timeout</c>. A <c>TimeFunc</c> function can be used to
+ set a new timetrap by returning a <c>TimeVal</c>. It may also be
+ used to trigger a timetrap timeout by, at some point, returning a
+ value other than a <c>TimeVal</c>. (See the
+ <seealso marker="write_test_chapter#timetraps">User's Guide</seealso>
+ for details).</p>
+
+ <p>The <c>require</c> tag specifies configuration variables
+ that are required by test cases (and/or configuration functions)
+ in the suite. If the required configuration variables are not found
+ in any of the configuration files, all test cases in this group are skipped.
+ For more information about the 'require' functionality, see the
+ reference manual for the function
+ <c><seealso marker="ct#require-1">ct:require/1/2</seealso></c>.</p>
+
+ <p>With <c>userdata</c>, it is possible for the user to
+ specify arbitrary test case group related information which can be
+ read by calling <c><seealso marker="ct#userdata-2">ct:userdata/2</seealso></c>.</p>
+
+ <p>The <c>ct_hooks</c> tag specifies which
+ <seealso marker="ct_hooks_chapter">Common Test Hooks</seealso>
+ are to be run together with this suite.</p>
+
+ <p>Other tuples than the ones defined will simply be ignored.</p>
+
+ <p>For more information about the test case group info function,
+ see <seealso marker="write_test_chapter#suite">Test
+ case group info function</seealso> in the User's Guide.</p>
+ </desc>
</func>
<func>
- <name>Module:init_per_group(GroupName, Config) -> NewConfig | {skip,Reason}</name>
- <fsummary>Test case group initialization.</fsummary>
+ <name>Module:init_per_group(GroupName, Config) -> NewConfig |
+ {skip,Reason}</name>
+ <fsummary>Test case group initializations.</fsummary>
<type>
<v> GroupName = atom()</v>
<v> Config = NewConfig = [{Key,Value}]</v>
@@ -258,16 +364,16 @@
<p> OPTIONAL </p>
- <p>This function is called before execution of a test case group.
- It typically contains initialization which is common for
- all test cases in the group, and which shall only be performed
- once. <c>GroupName</c> is the name of the group, as specified in
- the group definition (see <c>groups/0</c>). The <c>Config</c>
- parameter is the configuration which can be modified here.
- Whatever is returned from this function is given as <c>Config</c>
- to all test cases in the group. If <c>{skip,Reason}</c> is returned,
- all test cases in the group will be skipped and <c>Reason</c> printed
- in the overview log for the group.</p>
+ <p>This configuration function is called before execution of a
+ test case group. It typically contains initializations which are
+ common for all test cases and sub-groups in the group, and which
+ shall only be performed once. <c>GroupName</c> is the name of the
+ group, as specified in the group definition (see <c><seealso marker="#Module:groups-0">groups/0</seealso></c>). The
+ <c>Config</c> parameter is the configuration data which can be modified
+ here. The return value of this function is given as <c>Config</c>
+ to all test cases and sub-groups in the group. If <c>{skip,Reason}</c>
+ is returned, all test cases in the group will be skipped and
+ <c>Reason</c> printed in the overview log for the group.</p>
<p>For information about test case groups, please see
<seealso marker="write_test_chapter#test_case_groups">Test case
@@ -276,7 +382,8 @@
</func>
<func>
- <name>Module:end_per_group(GroupName, Config) -> void() | {return_group_result,Status}</name>
+ <name>Module:end_per_group(GroupName, Config) -> void() |
+ {return_group_result,Status}</name>
<fsummary>Test case group finalization.</fsummary>
<type>
<v> GroupName = atom()</v>
@@ -290,10 +397,10 @@
<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>.
+ It is meant to be used for cleaning up after <c><seealso marker="#Module:init_per_group-2">init_per_group/2</seealso></c>.
By means of <c>{return_group_result,Status}</c>, it is possible to return a
status value for a nested sub-group. The status can be retrieved in
- <c>end_per_group/2</c> for the group on the level above. The status will also
+ <c><seealso marker="#Module:end_per_group-2">end_per_group/2</seealso></c> for the group on the level above. The status will also
be used by Common Test for deciding if execution of a group should proceed in
case the property <c>sequence</c> or <c>repeat_until_*</c> is set.</p>
@@ -305,7 +412,7 @@
<func>
<name>Module:init_per_testcase(TestCase, Config) -> NewConfig | {fail,Reason} | {skip,Reason}</name>
- <fsummary>Test case initialization.</fsummary>
+ <fsummary>Test case initializations.</fsummary>
<type>
<v> TestCase = atom()</v>
<v> Config = NewConfig = [{Key,Value}]</v>
@@ -344,7 +451,7 @@
<p> OPTIONAL </p>
<p> This function is called after each test case, and can be used
- to clean up after <c>init_per_testcase/2</c> and the test case.
+ to clean up after <c><seealso marker="#Module:init_per_testcase-2">init_per_testcase/2</seealso></c> and the test case.
Any return value (besides <c>{fail,Reason}</c> and <c>{save_config,SaveConfig}</c>)
is ignored. By returning <c>{fail,Reason}</c>, <c>TestCase</c> will be marked as
failed (even though it was actually successful in the sense that it returned
@@ -370,7 +477,7 @@
<v> Func = atom()</v>
<v> Args = list()</v>
<v> Fun = fun()</v>
- <v> Required = Key | {Key,SubKeys}</v>
+ <v> Required = Key | {Key,SubKeys} | {Key,Subkey} | {Key,Subkey,SubKeys}</v>
<v> Key = atom()</v>
<v> SubKeys = SubKey | [SubKey]</v>
<v> SubKey = atom()</v>
@@ -385,32 +492,38 @@
<p>This is the test case info function. It is supposed to
return a list of tagged tuples that specify various properties
- regarding the execution of this particular test case.</p>
+ related to the execution of this particular test case.
+ Properties set by <c><seealso marker="#Module:Testcase-0">Testcase/0</seealso></c> override
+ properties that have been previously set for the test case
+ by <c><seealso marker="#Module:group-1">group/1</seealso></c> or <c><seealso marker="#Module:suite-0">suite/0</seealso></c>.</p>
<p>The <c>timetrap</c> tag sets the maximum time the
- test case is allowed to take. If the timetrap time is
+ test case is allowed to execute. If the timetrap time is
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. 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>
+ <c>timetrap_timeout</c>. <c><seealso marker="#Module:init_per_testcase-2">init_per_testcase/2</seealso></c>
+ and <c><seealso marker="#Module:end_per_testcase-2">end_per_testcase/2</seealso></c> are included in the
+ timetrap time. A <c>TimeFunc</c> function can be used to
+ set a new timetrap by returning a <c>TimeVal</c>. It may also be
+ used to trigger a timetrap timeout by, at some point, returning a
+ value other than a <c>TimeVal</c>. (See the
+ <seealso marker="write_test_chapter#timetraps">User's Guide</seealso>
+ for details).</p>
<p>The <c>require</c> tag specifies configuration variables
- that are required by the test case. If the required
- configuration variables are not found in any of the
+ that are required by the test case (and/or <c>init/end_per_testcase/2</c>).
+ If the required configuration variables are not found in any of the
configuration files, the test case is skipped. For more
information about the 'require' functionality, see the
reference manual for the function
- <c>ct:require/[1,2]</c>.</p>
+ <c><seealso marker="ct#require-1">ct:require/1/2</seealso></c>.</p>
<p>If <c>timetrap</c> and/or <c>require</c> is not set, the
- default values specified in the <c>suite/0</c> return list
- will be used.</p>
+ default values specified by <c><seealso marker="#Module:suite-0">suite/0</seealso></c> (or
+ <c><seealso marker="#Module:group-1">group/1</seealso></c>) will be used.</p>
<p>With <c>userdata</c>, it is possible for the user to
specify arbitrary test case related information which can be
- read by calling <c>ct:userdata/3</c>.</p>
+ read by calling <c><seealso marker="ct#userdata-3">ct:userdata/3</seealso></c>.</p>
<p>Other tuples than the ones defined will simply be ignored.</p>
@@ -438,12 +551,12 @@
<p>This is the implementation of a test case. Here you must
call the functions you want to test, and do whatever you
need to check the result. If something fails, make sure the
- function causes a runtime error, or call <c>ct:fail/[0,1]</c>
- (which also causes the test case process to crash).</p>
+ function causes a runtime error, or call <c><seealso marker="ct#fail-1">ct:fail/1/2</seealso></c>
+ (which also causes the test case process to terminate).</p>
- <p>Elements from the <c>Config</c> parameter can be read
- with the <c>?config</c> macro. The <c>config</c>
- macro is defined in <c>ct.hrl</c></p>
+ <p>Elements from the <c>Config</c> list can e.g. be read
+ with <c>proplists:get_value/2</c> (or the macro <c>?config</c>
+ defined in <c>ct.hrl</c>).</p>
<p>You can return <c>{skip,Reason}</c> if you decide not to
run the test case after all. <c>Reason</c> will then be
diff --git a/lib/common_test/doc/src/config.gif b/lib/common_test/doc/src/config.gif
new file mode 100644
index 0000000000..ac8006c4fb
--- /dev/null
+++ b/lib/common_test/doc/src/config.gif
Binary files differ
diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml
index 6fc6638bf7..e843ed3ba4 100644
--- a/lib/common_test/doc/src/config_file_chapter.xml
+++ b/lib/common_test/doc/src/config_file_chapter.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>
@@ -78,7 +78,7 @@
test is skipped (unless a default value has been specified, see the
<seealso marker="write_test_chapter#info_function">test case info
function</seealso> chapter for details). There is also a function
- <c>ct:require/[1,2]</c> which can be called from a test case
+ <c><seealso marker="ct#require-1">ct:require/1/2</seealso></c> which can be called from a test case
in order to check if a specific variable is available. The return
value from this function must be checked explicitly and appropriate
action be taken depending on the result (e.g. to skip the test case
@@ -88,7 +88,7 @@
info-list should look like this:
<c>{require,CfgVarName}</c> or <c>{require,AliasName,CfgVarName}</c>.
The arguments <c>AliasName</c> and <c>CfgVarName</c> are the same as the
- arguments to <c>ct:require/[1,2]</c> which are described in the
+ arguments to <c><seealso marker="ct#require-1">ct:require/1/2</seealso></c> which are described in the
reference manual for <seealso marker="ct">ct</seealso>.
<c>AliasName</c> becomes an alias for the configuration variable,
and can be used as reference to the configuration data value.
@@ -101,7 +101,8 @@
(or test case) and improve readability.</item>
</list>
<p>To read the value of a config variable, use the function
- <c>get_config/[1,2,3]</c> which is also described in the reference
+ <c><seealso marker="ct#get_config-1">get_config/1/2/3</seealso></c>
+ which is also described in the reference
manual for <seealso marker="ct">ct</seealso>.</p>
<p>Example:</p>
<pre>
@@ -118,7 +119,7 @@
<section>
<title>Using configuration variables defined in multiple files</title>
<p>If a configuration variable is defined in multiple files and you
- want to access all possible values, you may use the <c>ct:get_config/3</c>
+ want to access all possible values, you may use the <c><seealso marker="ct#get_config-3">ct:get_config/3</seealso></c>
function and specify <c>all</c> in the options list. The values will then
be returned in a list and the order of the elements corresponds to the order
that the config files were specified at startup. Please see
@@ -130,7 +131,7 @@
<marker id="encrypted_config_files"></marker>
<p>It is possible to encrypt configuration files containing sensitive data
if these files must be stored in open and shared directories.</p>
- <p>Call <c>ct:encrypt_config_file/[2,3]</c> to have Common Test encrypt a
+ <p>Call <c><seealso marker="ct#encrypt_config_file-2">ct:encrypt_config_file/2/3</seealso></c> to have Common Test encrypt a
specified file using the DES3 function in the OTP <c>crypto</c> application.
The encrypted file can then be used as a regular configuration file,
in combination with other encrypted files or normal text files. The key
@@ -139,7 +140,7 @@
<c>decrypt_file</c> flag/option, or a key file in a predefined location.</p>
<p>Common Test also provides decryption functions,
- <c>ct:decrypt_config_file/[2,3]</c>, for recreating the original text
+ <c><seealso marker="ct#decrypt_config_file-2">ct:decrypt_config_file/2/3</seealso></c>, for recreating the original text
files.</p>
<p>Please see the <seealso marker="ct">ct</seealso> reference manual for
@@ -149,8 +150,8 @@
<section>
<title>Opening connections by using configuration data</title>
<p>There are two different methods for opening a connection
- by means of the support functions in e.g. <c>ct_ssh</c>, <c>ct_ftp</c>,
- and <c>ct_telnet</c>:</p>
+ by means of the support functions in e.g. <c><seealso marker="ct_ssh">ct_ssh</seealso></c>, <c><seealso marker="ct_ftp">ct_ftp</seealso></c>,
+ and <c><seealso marker="ct_telnet">ct_telnet</seealso></c>:</p>
<list>
<item>Using a configuration target name (an alias) as reference.</item>
<item>Using the configuration variable as reference.</item>
@@ -295,7 +296,7 @@
<pre>
[{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
- {lm_directory, "/test/loadmodules"}]</pre>
+ {lm_directory, "/test/loadmodules"}]</pre>
</section>
diff --git a/lib/common_test/doc/src/cover_chapter.xml b/lib/common_test/doc/src/cover_chapter.xml
index b7162cb542..fc609ee137 100644
--- a/lib/common_test/doc/src/cover_chapter.xml
+++ b/lib/common_test/doc/src/cover_chapter.xml
@@ -100,7 +100,7 @@
<p><c>$ ct_run -dir $TESTOBJS/db -cover $TESTOBJS/db/config/db.coverspec</c></p>
<p>You may also pass the cover specification file name in a
- call to <c>ct:run_test/1</c>, by adding a <c>{cover,CoverSpec}</c>
+ call to <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>, by adding a <c>{cover,CoverSpec}</c>
tuple to the <c>Opts</c> argument. Also, you can of course
enable code coverage in your test specifications (read
more in the chapter about
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index f9fc1858d0..b98c04a850 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -37,12 +37,6 @@
<description>
- <warning><p>This feature is in alpha release right now. This means that the
- interface may change in the future and that there may be bugs. We
- encourage you to use this feature, but be prepared
- that there might be bugs and that the interface might change
- inbetween releases.</p></warning>
-
<p>The <em>Common Test Hook</em> (henceforth called CTH) framework allows
extensions of the default behaviour of Common Test by means of callbacks
before and after all test suite calls. It is meant for advanced users of
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index 3b9620d0f2..c938851e0e 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2011</year><year>2011</year>
+ <year>2011</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,11 +32,6 @@
<marker id="general"></marker>
<section>
<title>General</title>
- <warning><p>This feature is in alpha release right now. This means that the
- interface may change in the future and that there may be bugs. We
- encourage you to use this feature, but be prepared
- that there might be bugs and that the interface might change
- inbetween releases.</p></warning>
<p>
The <em>Common Test Hook</em> (henceforth called CTH) framework allows
extensions of the default behaviour of Common Test by means of hooks
@@ -113,9 +108,10 @@
</section>
<section>
- <title>CTH Priority</title>
+ <title>CTH Execution order</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
+ they are installed for init calls, and then reversed for end calls.
+ 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
@@ -193,6 +189,22 @@
it.</p>
</section>
+ <section>
+ <title>External configuration data and Logging</title>
+ <p>It's possible in the CTH to read configuration data values
+ by calling <c><seealso marker="ct#get_config-1">ct:get_config/1/2/3</seealso></c> (as explained in the
+ <seealso marker="config_file_chapter#require_config_data">
+ External configuration data</seealso>
+ chapter). The config variables in question must, as always, first have been
+ <c>required</c> by means of a suite-, group-, or test case info function,
+ or the <c><seealso marker="ct#require-1">ct:require/1/2</seealso></c> function. Note that the latter can also be used
+ in CT hook functions.</p>
+ <p>The CT hook functions may call any of the logging functions available
+ in the <c>ct</c> interface to print information to the log files, or to
+ add comments in the suite overview page.
+ </p>
+ </section>
+
</section>
<marker id="manipulating"/>
@@ -205,11 +217,13 @@
functions for a CTH follow a common interface, this interface is
described below.</p>
- <p>It is only possible to hook into test function which exists in the test
- suite. So in order for a CTH to hook in before
- <seealso marker="common_test#Module:init_per_suite-1">init_per_suite</seealso>,
- the <seealso marker="common_test#Module:init_per_suite-1">init_per_suite</seealso>
- function must exist in the test suite.</p>
+ <p>Common Test will always call all available hook functions, even pre- and post
+ hooks for configuration functions that are not implemented in the suite.
+ For example, <c>pre_init_per_suite(x_SUITE, ...)</c> and
+ <c>post_init_per_suite(x_SUITE, ...)</c> will be called for test suite
+ <c>x_SUITE</c>, even if it doesn't export <c>init_per_suite/1</c>. This feature
+ makes it possible to use hooks as configuration fallbacks, or even
+ completely replace all configuration functions with hook functions.</p>
<marker id="pre"/>
<section>
@@ -433,6 +447,16 @@ terminate(State) ->
<seealso marker="sasl:sasl_app">SASL</seealso> events report
using the normal SASL mechanisms. </cell>
</row>
+ <row>
+ <cell>cth_surefire</cell>
+ <cell>no</cell>
+ <cell>Captures all test results and outputs them as surefire XML into
+ a file. The file which is created is by default called junit_report.xml.
+ The name can be by setting the path option for this hook. e.g.
+ <code>-ct_hooks cth_surefire [{path,"/tmp/report.xml"}]</code>
+ Surefire XML can forinstance be used by Jenkins to display test
+ results.</cell>
+ </row>
</table>
</section>
diff --git a/lib/common_test/doc/src/ct_run.xml b/lib/common_test/doc/src/ct_run.xml
index 9045646733..8061c840b0 100644
--- a/lib/common_test/doc/src/ct_run.xml
+++ b/lib/common_test/doc/src/ct_run.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -46,7 +46,7 @@
particular mode.</p>
<p>There is an interface function that corresponds to this program,
- called <c>ct:run_test/1</c>, for starting Common Test from the Erlang
+ called <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>, for starting Common Test from the Erlang
shell (or an Erlang program). Please see the <c>ct</c> man page for
details.</p>
@@ -88,11 +88,13 @@
[-step [config | keep_inactive]]
[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
[-userconfig CallbackModule1 ConfigString1 and CallbackModule2
- ConfigString2 and .. and CallbackModuleN ConfigStringN]
+ ConfigString2 and .. CallbackModuleN ConfigStringN]
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-label Label]
[-logdir LogDir]
[-logopts LogOpts]
+ [-verbosity GenVLevel | [Category1 VLevel1 and
+ Category2 VLevel2 and .. CategoryN VLevelN]]
[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
[-stylesheet CSSFile]
[-cover CoverCfgFile]
@@ -103,10 +105,14 @@
[-no_auto_compile]
[-muliply_timetraps Multiplier]
[-scale_timetraps]
+ [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]
[-repeat N [-force_stop]] |
[-duration HHMMSS [-force_stop]] |
[-until [YYMoMoDD]HHMMSS [-force_stop]]
- [-basic_html]</pre>
+ [-basic_html]
+ [-ct_hooks CTHModule1 CTHOpts1 and CTHModule2 CTHOpts2 and ..
+ CTHModuleN CTHOptsN]
+ </pre>
</section>
<section>
<title>Run tests using test specification</title>
@@ -119,6 +125,8 @@
[-label Label]
[-logdir LogDir]
[-logopts LogOpts]
+ [-verbosity GenVLevel | [Category1 VLevel1 and
+ Category2 VLevel2 and .. CategoryN VLevelN]]
[-allow_user_terms]
[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
[-stylesheet CSSFile]
@@ -130,10 +138,14 @@
[-no_auto_compile]
[-muliply_timetraps Multiplier]
[-scale_timetraps]
+ [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]
[-repeat N [-force_stop]] |
[-duration HHMMSS [-force_stop]] |
[-until [YYMoMoDD]HHMMSS [-force_stop]]
- [-basic_html]</pre>
+ [-basic_html]
+ [-ct_hooks CTHModule1 CTHOpts1 and CTHModule2 CTHOpts2 and ..
+ CTHModuleN CTHOptsN]
+ </pre>
</section>
<section>
<title>Run tests in web based GUI</title>
@@ -145,11 +157,14 @@
[-userconfig CallbackModule1 ConfigString1 and CallbackModule2
ConfigString2 and .. and CallbackModuleN ConfigStringN]
[-logopts LogOpts]
+ [-verbosity GenVLevel | [Category1 VLevel1 and
+ Category2 VLevel2 and .. CategoryN VLevelN]]
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-include InclDir1 InclDir2 .. InclDirN]
[-no_auto_compile]
[-muliply_timetraps Multiplier]
[-scale_timetraps]
+ [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]
[-basic_html]</pre>
</section>
<section>
diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml
index b41b233ce6..b95a18e47e 100644
--- a/lib/common_test/doc/src/event_handler_chapter.xml
+++ b/lib/common_test/doc/src/event_handler_chapter.xml
@@ -64,7 +64,7 @@
<marker id="usage"></marker>
<title>Usage</title>
<p>Event handlers may be installed by means of an <c>event_handler</c>
- start flag (<c>ct_run</c>) or option (<c>ct:run_test/1</c>), where the
+ start flag (<c>ct_run</c>) or option (<c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>), where the
argument specifies the names of one or more event handler modules.
Example:</p>
<p><c>$ ct_run -suite test/my_SUITE -event_handler handlers/my_evh1
@@ -78,7 +78,7 @@
example).</p>
<p>An event_handler tuple in the argument <c>Opts</c> has the following
- definition (see also <c>ct:run_test/1</c> in the reference manual):</p>
+ definition (see also <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c> in the reference manual):</p>
<pre>
{event_handler,EventHandlers}
@@ -174,6 +174,16 @@
are also given.
</p></item>
+ <item><c>#event{name = tc_logfile, data = {{Suite,Func},LogFileName}}</c>
+ <p><c>Suite = atom()</c>, name of the test suite.</p>
+ <p><c>Func = atom()</c>, name of test case or configuration function.</p>
+ <p><c>LogFileName = string()</c>, full name of test case log file.</p>
+ <p>This event is sent at the start of each test case (and configuration function
+ except <c>init/end_per_testcase</c>) and carries information about the
+ full name (i.e. the file name including the absolute directory path) of
+ the current test case log file.
+ </p></item>
+
<marker id="tc_done"/>
<item><c>#event{name = tc_done, data = {Suite,FuncOrGroup,Result}}</c>
<p><c>Suite = atom()</c>, name of the suite.</p>
@@ -195,7 +205,7 @@
{error,{RunTimeError,StackTrace}} |
{timetrap_timeout,integer()} |
{failed,{Suite,end_per_testcase,FailInfo}}</c>, reason for failure.</p>
- <p><c>RequireInfo = {not_available,atom()}</c>, why require has failed.</p>
+ <p><c>RequireInfo = {not_available,atom() | tuple()}</c>, why require has failed.</p>
<p><c>FailInfo = {timetrap_timeout,integer()} |
{RunTimeError,StackTrace} |
UserTerm</c>,
@@ -223,7 +233,7 @@
reason for auto skipping <c>Func</c>.</p>
<p><c>FailReason = {Suite,ConfigFunc,FailInfo}} |
{Suite,FailedCaseInSequence}</c>, reason for failure.</p>
- <p><c>RequireInfo = {not_available,atom()}</c>, why require has failed.</p>
+ <p><c>RequireInfo = {not_available,atom() | tuple()}</c>, why require has failed.</p>
<p><c>ConfigFunc = init_per_suite | init_per_group</c></p>
<p><c>FailInfo = {timetrap_timeout,integer()} |
{RunTimeError,StackTrace} |
@@ -298,7 +308,7 @@
manager can look like.</p>
<note><p>To ensure that printouts to standard out (or printouts made with
- <c>ct:log/2/3</c> or <c>ct:pal/2/3</c>) get written to the test case log
+ <c><seealso marker="ct#log-2">ct:log/2/3</seealso></c> or <c><seealso marker="ct:pal-2">ct:pal/2/3</seealso></c>) get written to the test case log
file, and not to the Common Test framework log, you can syncronize
with the Common Test server by matching on the <c>tc_start</c> and <c>tc_done</c>
events. In the period between these events, all IO gets directed to the
diff --git a/lib/common_test/doc/src/filestruct.gif b/lib/common_test/doc/src/filestruct.gif
index 2b06833d0b..2b06833d0b 100755..100644
--- a/lib/common_test/doc/src/filestruct.gif
+++ b/lib/common_test/doc/src/filestruct.gif
Binary files differ
diff --git a/lib/common_test/doc/src/getting_started_chapter.xml b/lib/common_test/doc/src/getting_started_chapter.xml
new file mode 100644
index 0000000000..891cbc49f3
--- /dev/null
+++ b/lib/common_test/doc/src/getting_started_chapter.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2007</year><year>2012</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>Getting Started</title>
+ <prepared>Peter Andersson</prepared>
+ <docno></docno>
+ <date>2011-12-12</date>
+ <rev></rev>
+ <file>getting_started_chapter.xml</file>
+ </header>
+
+ <section>
+ <title>Are you new around here?</title>
+ <p>
+ The purpose of this short chapter is to, with a "learning by example"
+ approach, give the newcomer a chance to get started quickly writing and
+ executing some first simple tests. The chapter will introduce some of the
+ basics, but leave most explanations and details for the later
+ chapters in this User's Guide. Hopefully though, after this chapter, you
+ will be inspired and unintimidated enough to go on and get into the
+ nitty-gritty that follows in this rather heavy User's Guide! If you're
+ not much into "learning by example" and prefer to get into more technical
+ detail right away, go ahead and skip to the next chapter. Again, the basics
+ presented here will be covered in detail in later chapters.
+ </p>
+ <p>
+ This chapter also tries to demonstrate how dead simple it actually is
+ to write a very basic (yet for many module testing purposes, often sufficiently
+ complex) test suite, and execute its test cases. This is not necessarily
+ obvious when you read the rest of the chapters in the User's Guide.
+ </p>
+ <p>
+ A quick note before we start: In order to understand what's discussed and
+ examplified here, it is recommended that you first read through the
+ opening <seealso marker="basics_chapter#basics">Common Test Basics</seealso>
+ chapter.
+ </p>
+ </section>
+
+ <section>
+ <title>Test case execution</title>
+ <p>Execution of test cases is handled this way:</p>
+
+ <p>
+ <image file="tc_execution.gif">
+ <icaption>
+ Successful vs unsuccessful test case execution.
+ </icaption>
+ </image>
+ </p>
+
+ <p>For each test case that Common Test is told to execute, it spawns a
+ dedicated process on which the test case function in question starts
+ running. (In parallel to the test case process, an idle waiting timer
+ process is started which is linked to the test case process. If the timer
+ process runs out of waiting time, it sends an exit signal to terminate
+ the test case process and this is what's called a <em>timetrap</em>).
+ </p>
+ <p>In scenario 1, the test case process terminates normally after case A has
+ finished executing its test code without detecting any errors. The test
+ case function simply returns a value and Common Test logs the test case as
+ successful.
+ </p>
+ <p>In scenario 2, an error is detected during test case execution
+ which causes the test case B function to generate an exception.
+ This causes the test case process to exit with reason
+ other than normal, and as a result, Common Test will log this as an
+ unsuccessful test case.
+ </p>
+ <p>As you can understand from the illustration above, Common Test requires
+ that a test case generates a runtime error to indicate failure (e.g.
+ by causing a bad match error or by calling <c>exit/1</c>, preferrably
+ through the <c><seealso marker="ct#fail-1">ct:fail/1,2</seealso></c> help function). A succesful execution is
+ indicated by means of a normal return from the test case function.
+ </p>
+ </section>
+
+ <section>
+ <title>A simple test suite</title>
+ <p>As you've seen in the basics chapter, the test suite module implements
+ <seealso marker="common_test">callback functions</seealso>
+ (mandatory or optional) for various purposes, e.g:
+ <list>
+ <item>Init/end configuration function for the test suite</item>
+ <item>Init/end configuration function for a test case</item>
+ <item>Init/end configuration function for a test case group</item>
+ <item>Test cases</item>
+ </list>
+ The configuration functions are optional and if you don't need them for
+ your test, a test suite with one simple test case could look like this:
+ </p>
+ <pre>
+ -module(my1st_SUITE).
+ -compile(export_all).
+
+ all() ->
+ [mod_exists].
+
+ mod_exists(_) ->
+ {module,mymod} = code:load_file(mymod).</pre>
+ <p>
+ In this example we check that the <c>mymod</c> module exists (i.e. can be
+ successfully loaded by the code server). If the operation fails, we will
+ get a bad match error which terminates the test case.
+ </p>
+ </section>
+
+ <section>
+ <title>A test suite with configuration functions</title>
+ <p>
+ If we need to perform configuration operations in order to run our test, we
+ implement configuration functions in our suite. The result from a
+ configuration function is configuration data, or simply <em><c>Config</c></em>.
+ This is a list of key-value tuples which get passed from the configuration
+ function to the test cases (possibly through configuration functions on
+ "lower level"). The data flow looks like this:
+ </p>
+
+ <p>
+ <image file="config.gif">
+ <icaption>
+ Config data flow in the suite.
+ </icaption>
+ </image>
+ </p>
+
+ <p>
+ Here's an example of a test suite which uses configuration functions
+ to open and close a log file for the test cases (an operation that would
+ be unnecessary and irrelevant to perform by each test case):
+ </p>
+ <pre>
+ -module(check_log_SUITE).
+ -export([all/0, init_per_suite/1, end_per_suite/1]).
+ -export([check_restart_result/1, check_no_errors/1]).
+
+ -define(value(Key,Config), proplists:get_value(Key,Config)).
+
+ all() -> [check_restart_result, check_no_errors].
+
+ init_per_suite(InitConfigData) ->
+ [{logref,open_log()} | InitConfigData].
+
+ end_per_suite(ConfigData) ->
+ close_log(?value(logref, ConfigData)).
+
+ check_restart_result(ConfigData) ->
+ TestData = read_log(restart, ?value(logref, ConfigData)),
+ {match,_Line} = search_for("restart successful", TestData).
+
+ check_no_errors(ConfigData) ->
+ TestData = read_log(all, ?value(logref, ConfigData)),
+ case search_for("error", TestData) of
+ {match,Line} -> ct:fail({error_found_in_log,Line});
+ nomatch -> ok
+ end.</pre>
+ <p>
+ In this example we have test cases that verify, by parsing a
+ log file, that our SUT has performed a successful restart and
+ that no unexpected errors have been printed.
+ </p>
+
+ <p>To execute the test cases in the test suite above, we could type this on
+ the Unix/Linux command line (assuming for this example that the suite module
+ is in the current working directory):
+ </p>
+ <pre>
+ $ ct_run -dir .</pre>
+ <p>or</p>
+ <pre>
+ $ ct_run -suite check_log_SUITE</pre>
+
+ <p>If we want to use the Erlang shell to run our test, we could evaluate this call:
+ </p>
+ <pre>
+ 1> ct:run_test([{dir, "."}]).</pre>
+ <p>or</p>
+ <pre>
+ 1> ct:run_test([{suite, "check_log_SUITE"}]).</pre>
+ <p>
+ The result from running our test is printed in log files in HTML format
+ (stored in unique log directories on different level). This illustration
+ shows the log file structure:
+ </p>
+
+ <p>
+ <image file="html_logs.gif">
+ <icaption>
+ HTML log file structure.
+ </icaption>
+ </image>
+ </p>
+ </section>
+
+ <section>
+ <title>What happens next?</title>
+ <p>
+ You will find detailed information about the basics introduced here in this
+ chapter in the following chapters in the User's Guide, as well as
+ presentations of many more useful features. Have fun!
+ </p>
+ </section>
+</chapter>
+
+
+
+
+
+
+
+
diff --git a/lib/common_test/doc/src/html_logs.gif b/lib/common_test/doc/src/html_logs.gif
new file mode 100644
index 0000000000..3a3fd86bde
--- /dev/null
+++ b/lib/common_test/doc/src/html_logs.gif
Binary files differ
diff --git a/lib/common_test/doc/src/make.dep b/lib/common_test/doc/src/make.dep
deleted file mode 100644
index e34075888d..0000000000
--- a/lib/common_test/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: basics_chapter.tex book.tex common_test_app.tex \
- config_file_chapter.tex cover_chapter.tex \
- ct.tex ct_cover.tex ct_ftp.tex ct_master.tex \
- ct_master_chapter.tex ct_rpc.tex ct_snmp.tex \
- ct_ssh.tex ct_telnet.tex dependencies_chapter.tex \
- event_handler_chapter.tex example_chapter.tex \
- install_chapter.tex part.tex ref_man.tex run_test.tex \
- run_test_chapter.tex test_structure_chapter.tex \
- unix_telnet.tex why_test_chapter.tex write_test_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index af96ef621f..050b8774ca 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -32,6 +32,465 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Common Test adds the test suite directories to the code
+ path before executing the tests. These directories should
+ also be removed from the code path at the end of the test
+ run, which, prior to this fix, was not performed.</p>
+ <p>
+ Own Id: OTP-9595</p>
+ </item>
+ <item>
+ <p>
+ An entry is now created in the index.html file (i.e. the
+ overview file for the test run) for each repeated test
+ during a test run. This was previously not the case. Note
+ that in the top level (logdir) index file, however, only
+ the last test result is listed. For example, given the
+ test spec:
+ [{merge_tests,false},{dirs,"test1"},{dirs,"test1"}]. In
+ the index file for the test run (under
+ Logdir/ct_run.Node.Date.Time), both tests are listed. In
+ the top level index file (under Logdir), only the last
+ test is listed (one has to find the previous results
+ through the all_runs.html file).</p>
+ <p>
+ Own Id: OTP-9634 Aux Id: seq11924 </p>
+ </item>
+ <item>
+ <p>
+ After a test case timeout or abortion, the
+ end_per_testcase function executes on a new dedicated
+ process. The group leader for this process should be set
+ to the IO server for the test case, which was not done
+ properly. The result of this error was that no warnings
+ about end_per_testcase failing or timing out were ever
+ printed in the test case log. Also, help functions such
+ as e.g. test_server:stop_node/1, attempting to
+ synchronize with the IO server, would hang. The fault has
+ been corrected.</p>
+ <p>
+ Own Id: OTP-9666</p>
+ </item>
+ <item>
+ <p>
+ The ct:get_status/0 function would cause the calling
+ process to receive 'DOWN' messages if no tests were
+ running at the time of the call. This bug has been fixed.</p>
+ <p>
+ Own Id: OTP-9830 Aux Id: seq11975 </p>
+ </item>
+ <item>
+ <p>
+ A deadlock situation could occur if Common Test is
+ forwarding error_handler printouts to Test Server at the
+ same time a new test case is starting. This error has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9894</p>
+ </item>
+ <item>
+ <p>
+ A link to the ct_run program is now created, as expected,
+ in the installation bin directory (default
+ /usr/local/bin) during 'make install'.</p>
+ <p>
+ Own Id: OTP-9898</p>
+ </item>
+ <item>
+ <p>
+ Using the repeat, duration or until option with
+ ct:run_test/1, would cause an infinite loop. This has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9899</p>
+ </item>
+ <item>
+ <p>
+ Two or more test cases executing in parallel and printing
+ to screen at the same time with ct:pal/2/3 or
+ ct:print/2/3 could write into each other's "slots" and
+ create a mess of mixed strings. In order to avoid this,
+ only a single IO message is now ever sent per printout
+ call.</p>
+ <p>
+ Own Id: OTP-9900 Aux Id: OTP-9904 </p>
+ </item>
+ <item>
+ <p>
+ When a test case was killed because of a timetrap
+ timeout, the current location (suite, case and line) was
+ not printed correctly in the log files. This has been
+ corrected.</p>
+ <p>
+ Own Id: OTP-9930 Aux Id: seq12002 </p>
+ </item>
+ <item>
+ <p>
+ The wrong exit location was printed in the log file when
+ ct:fail/1 or ct_fail/2 was called.</p>
+ <p>
+ Own Id: OTP-9933 Aux Id: seq12002 </p>
+ </item>
+ <item>
+ <p>
+ Test Server and Common Test would add new error handlers
+ with each test run and fail to remove previously added
+ ones. In the case of Test Server, this would only happen
+ if SASL was not running on the test node. This has been
+ fixed.</p>
+ <p>
+ Own Id: OTP-9941 Aux Id: seq12009 </p>
+ </item>
+ <item>
+ <p>
+ If a test case process was terminated due to an exit
+ signal from a linked process, Test Server failed to
+ report the correct name of the suite and case to the
+ framework. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9958 Aux Id: OTP-9855 </p>
+ </item>
+ <item>
+ <p>
+ When starting a test with ct_run and adding a directory
+ to the code path using -pa or -pz (preceding -erl_args),
+ Common Test would delete any existing directory in the
+ code path with the same base name (see
+ filename:basename/1) as the directory being added. This
+ has been fixed.</p>
+ <p>
+ Own Id: OTP-9964</p>
+ </item>
+ <item>
+ <p>
+ If passing two or more directories with the same base
+ name (see filename:basename/1) to Common Test with ct_run
+ -pa, only one of the directories would actually be added.</p>
+ <p>
+ Own Id: OTP-9975 Aux Id: seq12019 </p>
+ </item>
+ <item>
+ <p>
+ Configuration data required by the group info function
+ was deleted before the call to post_end_per_group, which
+ made it impossible for the hook function to read and use
+ the data in question. This has been fixed.</p>
+ <p>
+ Own Id: OTP-9989</p>
+ </item>
+ <item>
+ <p>
+ Disabling built-in hooks in a test specification was
+ ignored, this has now been fixed.</p>
+ <p>
+ Own Id: OTP-10009</p>
+ </item>
+ <item>
+ <p>
+ Various typographical errors corrected in documentation
+ for common_test, driver, erl_driver and windows
+ installation instructions. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-10037</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new optional feature has been introduced that enables
+ Common Test to generate priv_dir directory names that are
+ unique for each test case or config function. The name of
+ the option/flag is 'create_priv_dir' and it can be set to
+ value 'auto_per_run' (which is the default, existing,
+ behaviour), or 'auto_per_tc' or 'manual_per_tc'. If
+ 'auto_per_tc' is used, Test Server creates a dedicated
+ priv_dir automatically for each test case (which can be
+ very expensive in case of many and/or repeated cases). If
+ 'manual_per_tc' is used, the user needs to create the
+ priv_dir explicitly by calling the new function
+ ct:make_priv_dir/0.</p>
+ <p>
+ Own Id: OTP-9659 Aux Id: seq11930 </p>
+ </item>
+ <item>
+ <p>
+ A column for test case group name has been added to the
+ suite overview HTML log file.</p>
+ <p>
+ Own Id: OTP-9730 Aux Id: seq11952 </p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use the post_end_per_testcase CT
+ hook function to print a comment for a test case in the
+ overview log file, even if the test case gets killed by a
+ timetrap or unknown exit signal, or if the
+ end_per_testcase function times out.</p>
+ <p>
+ Own Id: OTP-9855 Aux Id: seq11979 </p>
+ </item>
+ <item>
+ <p>
+ The pre- and post CT hook functions are now always called
+ for all configuration functions, even for configuration
+ functions that are not implemented in the test suite.</p>
+ <p>
+ Own Id: OTP-9880 Aux Id: seq11993 </p>
+ </item>
+ <item>
+ <p>
+ Common Test will now print error information (with a time
+ stamp) in the test case log file immediately when a test
+ case fails. This makes it easier to see when, in time,
+ the fault actually occured, and aid the job of locating
+ relevant trace and debug printouts in the log.</p>
+ <p>
+ Own Id: OTP-9904 Aux Id: seq11985, OTP-9900 </p>
+ </item>
+ <item>
+ <p>
+ Test Server has been modified to check the SASL
+ errlog_type parameter when receiving an error logger
+ event, so that it doesn't print reports of type that the
+ user has disabled.</p>
+ <p>
+ Own Id: OTP-9955 Aux Id: seq12013 </p>
+ </item>
+ <item>
+ <p>
+ The test specification term 'skip_groups' was implemented
+ in Common Test v1.6. It was never documented however,
+ which has now been attended to. Please see the Test
+ Specifications chapter in the User's Guide for
+ information.</p>
+ <p>
+ Own Id: OTP-9972</p>
+ </item>
+ <item>
+ <p>
+ The Common Test Master has been updated to use a CSS
+ style sheet for the html log files.</p>
+ <p>
+ Own Id: OTP-9973</p>
+ </item>
+ <item>
+ <p>
+ If the init_per_group/2 and end_per_group/2 functions are
+ not implemented in the test suite, Common Test calls it's
+ own local init- and end functions - previously named
+ ct_init_per_group/2 and ct_end_per_group/2 - when a group
+ is executed. These functions have been renamed
+ init_per_group/2 and end_per_group/2 respectively. Note
+ that this may affect any user event handler identifying
+ events by the old names.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9986 Aux Id: OTP-9992 </p>
+ </item>
+ <item>
+ <p>
+ By specifying a user defined function ({M,F,A} or fun) as
+ timetrap value, either by means of an info function or by
+ calling ct:timetrap/1, it is now possible to set a
+ timetrap that will be triggered when the user function
+ returns.</p>
+ <p>
+ Own Id: OTP-9988 Aux Id: OTP-9501, seq11894 </p>
+ </item>
+ <item>
+ <p>
+ If the optional configuration functions init_per_suite/1
+ and end_per_suite/1 are not implemented in the test
+ suite, local Common Test versions of these functions are
+ called instead, and will be displayed in the overview log
+ file. Any printouts made by the pre- or
+ post_init_per_suite and pre- or post_end_per_suite hook
+ functions are saved in the log files for these functions.</p>
+ <p>
+ Own Id: OTP-9992</p>
+ </item>
+ <item>
+ <p>
+ A hook has been added to common test which outputs
+ surefire XML for usage together with CI tools such as
+ Jenkins. To enable the hook pass '-ct_hooks cth_surefire'
+ to ct_run. See the CTH documentation for more details.</p>
+ <p>
+ Own Id: OTP-9995</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A Getting Started chapter has been added to the Common
+ Test User's Guide.</p>
+ <p>
+ Own Id: OTP-9156</p>
+ </item>
+ <item>
+ <p>
+ The test case group info function has been implemented in
+ Common Test. Before execution of a test case group, a
+ call is now made to <c>TestSuite:group(GroupName)</c>.
+ The function returns a list of test properties, e.g. to
+ specify timetrap values, require configuration data, etc
+ (analogue to the test suite- and test case info
+ function). The scope of the properties set by
+ <c>group(GroupName)</c> is all test cases and sub-groups
+ of group <c>GroupName</c>.</p>
+ <p>
+ Own Id: OTP-9235</p>
+ </item>
+ <item>
+ <p>
+ Common Test hooks are now in a final supported version.
+ The Common Test hooks allow you to abstract out
+ initialization behaviour that is common to multiple test
+ suites into one place and also extend the behaviour of a
+ suite without changing the suite itself. For more
+ information see the Common Test user's guide.</p>
+ <p>
+ Own Id: OTP-9449</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 calls info functions also for the
+ <c>init/end_per_suite/1</c> and
+ <c>init/end_per_group/2</c> configuration functions.
+ These can be used e.g. to set timetraps and require
+ external configuration data relevant only for the
+ configuration functions in question (without affecting
+ properties set for groups and test cases in the suite).
+ The info function for <c>init/end_per_suite(Config)</c>
+ is <c>init/end_per_suite()</c>, and for
+ <c>init/end_per_group(GroupName,Config)</c> it's
+ <c>init/end_per_group(GroupName)</c>. Info functions can
+ not be used with <c>init/end_per_testcase(TestCase,
+ Config)</c>, since these configuration functions execute
+ on the test case process and will use the same properties
+ as the test case (i.e. properties set by the test case
+ info function, <c>TestCase()</c>).</p>
+ <p>
+ Own Id: OTP-9569</p>
+ </item>
+ <item>
+ <p>
+ It's now possible to read the full name of the test case
+ log file during execution. One way to do this is to
+ lookup it up as value of the key <c>tc_logfile</c> in the
+ test case <c>Config</c> list (which means it can also be
+ read by a pre- or post Common Test hook function). The
+ data is also sent with the event
+ <c>#event{name=tc_logfile,data={{Suite,Func},LogFileName}}</c>,
+ and can be read by any installed event handler.</p>
+ <p>
+ Own Id: OTP-9676 Aux Id: seq11941 </p>
+ </item>
+ <item>
+ <p>
+ The look of the HTML log files generated by Common Test
+ and Test Server has been improved (and made easier to
+ customize) by means of a CSS file.</p>
+ <p>
+ Own Id: OTP-9706</p>
+ </item>
+ <item>
+ <p>
+ Functions ct:fail(Format, Args) and ct:comment(Format,
+ Args) have been added in order to make printouts of
+ formatted error and comment strings easier (no need for
+ the user to call io_lib:format/2 explicitly).</p>
+ <p>
+ Own Id: OTP-9709 Aux Id: seq11951 </p>
+ </item>
+ <item>
+ <p>
+ The order in which ct hooks are executed for cleanup
+ hooks (i.e. *_end_per_* hooks) has been reversed.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9774 Aux Id: seq11913 </p>
+ </item>
+ <item>
+ <p>
+ Printouts to stdout may be captured during test case
+ execution. This is useful in order to e.g. read and parse
+ tty printouts from the SUT during test case execution (if
+ necessary, say, to determine the outcome of the test).
+ The capturing session is started with
+ <c>ct:capture_start/0</c>, and stopped with
+ <c>ct:capture_stop/0</c>. The list of buffered strings is
+ read and purged with <c>ct:capture_get/0/1</c>. It's
+ possible to filter out printouts made with
+ <c>ct:log/2/3</c> and <c>ct:pal/2/3</c> from the captured
+ list of strings. This is done by calling
+ <c>capture_get/1</c> with a list of log categories to
+ exclude.</p>
+ <p>
+ Own Id: OTP-9775</p>
+ </item>
+ <item>
+ <p>
+ The syntax for specifying test case groups in the all/0
+ list has been extended to include execution properties
+ for both groups and sub-groups. The properties specified
+ in all/0 for a group overrides the properties specified
+ in the group declaration (in groups/0). The main purpose
+ of this extension is to make it possible to run the same
+ set of tests, but with different properties, without
+ having to declare copies of the group in question. Also,
+ the same syntax may be used in test specifications in
+ order to change properties of groups at the time of
+ execution, without having to edit the test suite. Please
+ see the User's Guide for details and examples.</p>
+ <p>
+ Own Id: OTP-9809 Aux Id: OTP-9235 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ Fix problems in CT/TS due to line numbers in exceptions.</p>
+ <p>
+ Own Id: OTP-9203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.5.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/doc/src/part.xml b/lib/common_test/doc/src/part.xml
index 3284bcadaa..a74185221d 100644
--- a/lib/common_test/doc/src/part.xml
+++ b/lib/common_test/doc/src/part.xml
@@ -65,6 +65,7 @@
</description>
<xi:include href="basics_chapter.xml"/>
+ <xi:include href="getting_started_chapter.xml"/>
<xi:include href="install_chapter.xml"/>
<xi:include href="write_test_chapter.xml"/>
<xi:include href="test_structure_chapter.xml"/>
diff --git a/lib/common_test/doc/src/ref_man.xml b/lib/common_test/doc/src/ref_man.xml
index a9fdef7359..6fede88434 100644
--- a/lib/common_test/doc/src/ref_man.xml
+++ b/lib/common_test/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2003</year><year>2011</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -71,6 +71,7 @@
<xi:include href="ct_cover.xml"/>
<xi:include href="ct_ftp.xml"/>
<xi:include href="ct_ssh.xml"/>
+ <xi:include href="ct_netconfc.xml"/>
<xi:include href="ct_rpc.xml"/>
<xi:include href="ct_snmp.xml"/>
<xi:include href="ct_telnet.xml"/>
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index 57059f0ba2..058b27d622 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2011</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -242,12 +242,12 @@
<p>Common Test provides an Erlang API for running tests. The main (and most
flexible) function for specifying and executing tests is called
- <c>ct:run_test/1</c>. This function takes the same start parameters as
+ <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>. This function takes the same start parameters as
the <c>ct_run</c> program described above, only the flags are instead
given as options in a list of key-value tuples. E.g. a test specified
with <c>ct_run</c> like:</p>
<p><c>$ ct_run -suite ./my_SUITE -logdir ./results</c></p>
- <p>is with <c>ct:run_test/1</c> specified as:</p>
+ <p>is with <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c> specified as:</p>
<p><c>1> ct:run_test([{suite,"./my_SUITE"},{logdir,"./results"}]).</c></p>
<p>For detailed documentation, please see the <c>ct</c> manual page.</p>
</section>
@@ -266,9 +266,9 @@
for trying out various operations during test suite development.</p>
<p>To invoke the interactive shell mode, you can start an Erlang shell
- manually and call <c>ct:install/1</c> to install any configuration
+ manually and call <c><seealso marker="ct#install-1">ct:install/1</seealso></c> to install any configuration
data you might need (use <c>[]</c> as argument otherwise), then
- call <c>ct:start_interactive/0</c> to start Common Test. If you use
+ call <c><seealso marker="ct#start_interactive-0">ct:start_interactive/0</seealso></c> to start Common Test. If you use
the <c>ct_run</c> program, you may start the Erlang shell and Common Test
in the same go by using the <c>-shell</c> and, optionally, the <c>-config</c>
and/or <c>-userconfig</c> flag. Examples:
@@ -287,7 +287,8 @@
<p>If any functions using "required config data" (e.g. ct_telnet or
ct_ftp functions) are to be called from the erlang shell, config
- data must first be required with <c>ct:require/[1,2]</c>. This is
+ data must first be required with <c><seealso marker="ct#require-1">
+ ct:require/1/2</seealso></c>. This is
equivalent to a <c>require</c> statement in the <seealso
marker="write_test_chapter#suite">Test Suite Info
Function</seealso> or in the <seealso
@@ -314,11 +315,11 @@
is not supported.</p>
<p>If you wish to exit the interactive mode (e.g. to start an
- automated test run with <c>ct:run_test/1</c>), call the function
- <c>ct:stop_interactive/0</c>. This shuts down the
+ automated test run with <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>), call the function
+ <c><seealso marker="ct#stop_interactive-0">ct:stop_interactive/0</seealso></c>. This shuts down the
running <c>ct</c> application. Associations between
configuration names and data created with <c>require</c> are
- consequently deleted. <c>ct:start_interactive/0</c> will get you
+ consequently deleted. <c><seealso marker="ct#start_interactive-0">ct:start_interactive/0</seealso></c> will get you
back into interactive mode, but the previous state is not restored.</p>
</section>
@@ -326,7 +327,7 @@
<title>Step by step execution of test cases with the Erlang Debugger</title>
<p>By means of <c>ct_run -step [opts]</c>, or by passing the
- <c>{step,Opts}</c> option to <c>ct:run_test/1</c>, it is possible
+ <c>{step,Opts}</c> option to <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>, it is possible
to get the Erlang Debugger started automatically and use its
graphical interface to investigate the state of the current test
case and to execute it step by step and/or set execution breakpoints.</p>
@@ -412,10 +413,20 @@
the way from <c>init_per_suite</c> down to the test cases in the
sub group).</p>
+ <p>With the <c>GroupSpec</c> element (below) it's possible to specify
+ group execution properties that will override those specified in the
+ group definition (i.e. in <c>groups/0</c>). Execution properties for
+ sub-groups may be overridden as well. This feature makes it possible to
+ change properties of groups at the time of execution,
+ without even having to edit the test suite. More detailed documentation,
+ and examples, can be found in the
+ <seealso marker="write_test_chapter#test_case_groups">
+ Test case groups</seealso> chapter.</p>
+
<p>Below is the test specification syntax. Test specifications can
be used to run tests both in a single test host environment and
in a distributed Common Test environment (Large Scale
- Testing). The node parameters in the init term are only
+ Testing). The node parameters in the <c>init</c> term are only
relevant in the latter (see the
<seealso marker="ct_master_chapter#test_specifications">Large
Scale Testing</seealso> chapter for information). For details on
@@ -456,6 +467,9 @@
{logdir, LogDir}.
{logdir, NodeRefs, LogDir}.
+
+ {create_priv_dir, PrivDirOption}.
+ {create_priv_dir, NodeRefs, PrivDirOption}.
{event_handler, EventHandlers}.
{event_handler, NodeRefs, EventHandlers}.
@@ -475,14 +489,17 @@
{groups, DirRef, Suite, Groups}.
{groups, NodeRefsDirRef, Suite, Groups}.
- {groups, DirRef, Suite, Group, {cases,Cases}}.
- {groups, NodeRefsDirRef, Suite, Group, {cases,Cases}}.
+ {groups, DirRef, Suite, GroupSpec, {cases,Cases}}.
+ {groups, NodeRefsDirRef, Suite, GroupSpec, {cases,Cases}}.
{cases, DirRef, Suite, Cases}.
{cases, NodeRefs, DirRef, Suite, Cases}.
{skip_suites, DirRef, Suites, Comment}.
{skip_suites, NodeRefs, DirRef, Suites, Comment}.
+
+ {skip_groups, DirRef, Suite, GroupNames, Comment}.
+ {skip_groups, NodeRefs, DirRef, Suite, GroupNames, Comment}.
{skip_cases, DirRef, Suite, Cases, Comment}.
{skip_cases, NodeRefs, DirRef, Suite, Cases, Comment}.
@@ -502,6 +519,7 @@
DirAlias = atom()
Dir = string()
LogDir = string()
+ PrivDirOption = auto_per_run | auto_per_tc | manual_per_tc
EventHandlers = atom() | [atom()]
InitArgs = [term()]
CTHModules = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]
@@ -510,8 +528,10 @@
DirRef = DirAlias | Dir
Suites = atom() | [atom()] | all
Suite = atom()
- Groups = atom() | [atom()] | all
- Group = atom()
+ Groups = GroupSpec | [GroupSpec] | all
+ GroupSpec = GroupName | {GroupName,Properties} | {GroupName,Properties,GroupSpec}
+ GroupName = atom()
+ GroupNames = GroupName | [GroupName]
Cases = atom() | [atom()] | all
Comment = string() | ""
</pre>
@@ -556,9 +576,9 @@
<item>Lastly, all suites for systems t3 are to be completely skipped and this
should be explicitly noted in the log files.</item>
</list>
- <p>It is possible to specify initialization options for nodes defined in the
- test specification. Currently, there are options to start the node and/or to
- evaluate any function on the node.
+ <p>With the <c>init</c> term it's possible to specify initialization options
+ for nodes defined in the test specification. Currently, there are options
+ to start the node and/or to evaluate any function on the node.
See the <seealso marker="ct_master_chapter#ct_slave">Automatic startup of
the test target nodes</seealso> chapter for details.</p>
<p>It is possible for the user to provide a test specification that
@@ -567,7 +587,7 @@
<c>ct_run</c>. This forces Common Test to ignore unrecognizable terms.
Note that in this mode, Common Test is not able to check the specification
for errors as efficiently as if the scanner runs in default mode.
- If <c>ct:run_test/1</c> is used for starting the tests, the relaxed scanner
+ If <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c> is used for starting the tests, the relaxed scanner
mode is enabled by means of the tuple: <c>{allow_user_terms,true}</c></p>
</section>
@@ -644,14 +664,25 @@
to each individual test case log file for quick viewing with an HTML
browser.</p>
- <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. If SASL is running those logs will also be
- printed there by the
+ <p>The minor log files contain full details of every single test
+ case, each one in a separate file. This way, it should be
+ straightforward to compare the latest results to that of previous
+ test runs, even if the set of test cases changes. If SASL is running,
+ its logs will also be printed to the current minor log file by the
<seealso marker="common_test:ct_hooks_chapter#builtin_cths">
cth_log_redirect built-in hook</seealso>.
- </p>
+ </p>
+
+ <p>The full name of the minor log file (i.e. the name of the file
+ including the absolute directory path) can be read during execution
+ of the test case. It comes as value in the tuple
+ <c>{tc_logfile,LogFileName}</c> in the <c>Config</c> list (which means it
+ can also be read by a pre- or post Common Test hook function). Also,
+ at the start of a test case, this data is sent with an event
+ to any installed event handler. Please see the
+ <seealso marker="event_handler_chapter#event_handling">Event Handling</seealso>
+ chapter for details.
+ </p>
<p>Which information goes where is user configurable via the
test server controller. Three threshold values determine what
@@ -693,8 +724,15 @@
<section>
<marker id="html_stylesheet"></marker>
<title>HTML Style Sheets</title>
- <p>Common Test includes the <em>optional</em> feature to use
- HTML style sheets (CSS) for customizing user printouts. The
+ <p>Common Test uses a CSS file to control the look of the HTML
+ files generated during test runs. If, for some reason, the
+ log files are not displayed correctly in the HTML browser of your
+ choice, or you prefer the "pre Common Test v1.6 look"
+ of the log files (i.e. not using CSS), use the start flag/option
+ <c>basic_html</c> to revert to the old style.</p>
+
+ <p>Common Test includes an <em>optional</em> feature to allow
+ user HTML style sheets for customizing printouts. The
functions in <c>ct</c> that print to a test case HTML log
file (<c>log/3</c> and <c>pal/3</c>) accept <c>Category</c>
as first argument. With this argument it's possible to
@@ -708,22 +746,16 @@
look like this:</p>
<pre>
-&lt;style&gt;
- div.ct_internal { background:lightgrey; color:black }
- div.default { background:lightgreen; color:black }
- div.sys_config { background:blue; color:white }
- div.sys_state { background:yellow; color:black }
- div.error { background:red; color:white }
-&lt;/style&gt;
- </pre>
+ div.sys_config { background:blue; color:white }
+ div.sys_state { background:yellow; color:black }
+ div.error { background:red; color:white }</pre>
<p>To install the CSS file (Common Test inlines the definition in the
HTML code), the name may be provided when executing <c>ct_run</c>.
Example:</p>
<pre>
- $ ct_run -dir $TEST/prog -stylesheet $TEST/styles/test_categories.css
- </pre>
+ $ ct_run -dir $TEST/prog -stylesheet $TEST/styles/test_categories.css</pre>
<p>Categories in a CSS file installed with the <c>-stylesheet</c> flag
are on a global test level in the sense that they can be used in any
@@ -744,8 +776,7 @@
ct:log(sys_state, "Connections: ~p", [ConnectionInfo]),
...
ct:pal(error, "Error ~p detected! Info: ~p", [SomeFault,ErrorInfo]),
- ct:fail(SomeFault).
- </pre>
+ ct:fail(SomeFault).</pre>
<p>If the style sheet is installed as in this example, the categories are
private to the suite in question. They can be used by all test cases in the
@@ -769,21 +800,6 @@
<p>The <c>Category</c> argument in the example above may have the
value (atom) <c>sys_config</c> (white on blue), <c>sys_state</c>
(black on yellow) or <c>error</c> (white on red).</p>
-
- <p>If the <c>Category</c> argument is not specified, Common Test will
- use the CSS selector <c>div.default</c> for the
- printout. For this reason a user supplied style sheet must
- include this selector. Also the selector
- <c>div.ct_internal</c> must be included. Hence a minimal
- user style sheet should look like this (which is also the
- default style sheet Common Test uses if no user CSS file is
- provided):</p>
- <pre>
- &lt;style&gt;
- div.ct_internal { background:lightgrey; color:black }
- div.default { background:lightgreen; color:black }
- &lt;/style&gt;
- </pre>
</section>
<section>
@@ -928,7 +944,7 @@
<p>The <c>-silent_connections</c> tag (or
<c>silent_connections</c> tagged tuple in the call to
- <c>ct:run_test/1</c>) overrides any settings in the test
+ <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c>) overrides any settings in the test
suite.</p>
<p>Note that in the current Common Test version, the
diff --git a/lib/common_test/doc/src/tc_execution.gif b/lib/common_test/doc/src/tc_execution.gif
new file mode 100644
index 0000000000..7c89d7be57
--- /dev/null
+++ b/lib/common_test/doc/src/tc_execution.gif
Binary files differ
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index e35888e68f..1fae50577e 100644
--- a/lib/common_test/doc/src/write_test_chapter.xml
+++ b/lib/common_test/doc/src/write_test_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2011</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -29,7 +29,6 @@
<file>write_test_chapter.xml</file>
</header>
-
<section>
<marker id="intro"></marker>
<title>Support for test suite authors</title>
@@ -63,12 +62,19 @@
function in CT will not be able to locate it (at least not per default).
</p>
- <p>The <c>ct.hrl</c> header file must be included in all test suite files.
+ <p>It is also recommended that the <c>ct.hrl</c> header file is included
+ in all test suite modules.
</p>
<p>Each test suite module must export the function <c>all/0</c>
which returns the list of all test case groups and test cases
- in that module.
+ to be executed in that module.
+ </p>
+
+ <p>The callback functions that the test suite should implement, and
+ which will be described in more detail below, are
+ all listed in the <seealso marker="common_test">common_test
+ reference manual page</seealso>.
</p>
</section>
@@ -113,6 +119,14 @@
suite will be skipped automatically (so called <em>auto skipped</em>),
including <c>end_per_suite</c>.
</p>
+
+ <p>Note that if <c>init_per_suite</c> and <c>end_per_suite</c> do not exist
+ in the suite, Common Test calls dummy functions (with the same names)
+ instead, so that output generated by hook functions may be saved to the log
+ files for these dummies
+ (see the <seealso marker="ct_hooks_chapter#manipulating">Common Test Hooks</seealso>
+ chapter for more information).
+ </p>
</section>
<marker id="per_testcase"/>
@@ -159,7 +173,7 @@
</p>
<p>The <c>end_per_testcase/2</c> function is called even after a
- test case terminates due to a call to <c>ct:abort_current_testcase/1</c>,
+ test case terminates due to a call to <c><seealso marker="ct#abort_current_testcase-1">ct:abort_current_testcase/1</seealso></c>,
or after a timetrap timeout. However, <c>end_per_testcase</c>
will then execute on a different process than the test case
function, and in this situation, <c>end_per_testcase</c> will
@@ -229,7 +243,8 @@
<note><p>The test case function argument <c>Config</c> should not be
confused with the information that can be retrieved from
- configuration files (using ct:get_config/[1,2]). The Config argument
+ configuration files (using <c><seealso marker="ct#get_config-1">
+ ct:get_config/1/2</seealso></c>). The Config argument
should be used for runtime configuration of the test suite and the
test cases, while configuration files should typically contain data
related to the SUT. These two types of configuration data are handled
@@ -288,7 +303,7 @@
<item>
<p>
Use this to specify arbitrary data related to the testcase. This
- data can be retrieved at any time using the <c>ct:userdata/3</c>
+ data can be retrieved at any time using the <c><seealso marker="ct#userdata-3">ct:userdata/3</seealso></c>
utility function.
</p>
</item>
@@ -324,7 +339,8 @@
<pre>
testcase2() ->
- [{require, unix_telnet, {unix, [telnet, username, password]}},
+ [{require, unix_telnet, unix},
+ {require, {unix, [telnet, username, password]}},
{default_config, unix, [{telnet, "my_telnet_host"},
{username, "aladdin"},
{password, "sesame"}]}}].</pre>
@@ -332,7 +348,8 @@
</taglist>
<p>See the <seealso marker="config_file_chapter#require_config_data">Config files</seealso>
- chapter and the <c>ct:require/[1,2]</c> function in the
+ chapter and the <c><seealso marker="ct#require-1">
+ ct:require/1/2</seealso></c> function in the
<seealso marker="ct">ct</seealso> reference manual for more information about
<c>require</c>.</p>
@@ -369,10 +386,12 @@
<title>Test suite info function</title>
<p>The <c>suite/0</c> function can be used in a test suite
- module to set the default values for the <c>timetrap</c> and
- <c>require</c> tags. If a test case info function also specifies
- any of these tags, the default value is overruled. See above for
- more information.
+ module to e.g. set a default <c>timetrap</c> value and to
+ <c>require</c> external configuration data. If a test case-, or
+ group info function also specifies any of the info tags, it
+ overrides the default values set by <c>suite/0</c>. See the test
+ case info function above, and group info function below, for more
+ details.
</p>
<p>Other options that may be specified with the suite info list are:</p>
@@ -450,15 +469,68 @@
<pre>
all() -> [testcase1, {group,group1}, testcase2, {group,group2}].</pre>
- <p>Properties may be combined so that e.g. if <c>shuffle</c>,
- <c>repeat_until_any_fail</c> and <c>sequence</c> are all specified, the test
- cases in the group will be executed repeatedly and in random order until
- a test case fails, when execution is immediately stopped and the rest of
- the cases skipped.</p>
+ <p>It is also possible to specify execution properties with a group
+ tuple in <c>all/0</c>: <c>{group,GroupName,Properties}</c>. These
+ properties will override those specified in the group definition (see
+ <c>groups/0</c> above). This way, it's possible to run the same set of tests,
+ but with different properties, without having to make copies of the group
+ definition in question.</p>
+
+ <p>If a group contains sub-groups, the execution properties for these may
+ also be specified in the group tuple:
+ <c>{group,GroupName,Properties,SubGroups}</c>, where <c>SubGroups</c>
+ is a list of tuples, <c>{GroupName,Properties}</c>, or
+ <c>{GroupName,Properties,SubGroups}</c>, representing the sub-groups.
+ Any sub-groups defined in <c>group/0</c> for a group, that are not specified
+ in the <c>SubGroups</c> list, will simply execute with their pre-defined
+ properties.</p>
+
+ <p>Example:</p>
+ <pre>
+ groups() -> {tests1, [], [{tests2, [], [t2a,t2b]},
+ {tests3, [], [t31,t3b]}]}.</pre>
+ <p>To execute group 'tests1' twice with different properties for 'tests2'
+ each time:</p>
+ <pre>
+ all() ->
+ [{group, tests1, default, [{tests2, [parallel]}]},
+ {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}]}].</pre>
+ <p>Note that this is equivalent to this specification:</p>
+ <pre>
+ all() ->
+ [{group, tests1, default, [{tests2, [parallel]},
+ {tests3, default}]},
+ {group, tests1, default, [{tests2, [shuffle,{repeat,10}]},
+ {tests3, default}]}].</pre>
+ <p>The value <c>default</c> states that the pre-defined properties
+ should be used.</p>
+ <p>Here's an example of how to override properties in a scenario
+ with deeply nested groups:</p>
+ <pre>
+ groups() ->
+ [{tests1, [], [{group, tests2}]},
+ {tests2, [], [{group, tests3}]},
+ {tests3, [{repeat,2}], [t3a,t3b,t3c]}].
+
+ all() ->
+ [{group, tests1, default,
+ [{tests2, default,
+ [{tests3, [parallel,{repeat,100}]}]}]}].</pre>
+
+ <p>The syntax described above may also be used in Test Specifications
+ in order to change properties of groups at the time of execution,
+ without even having to edit the test suite (please see the
+ <seealso marker="run_test_chapter#test_specifications">Test
+ Specifications</seealso> chapter for more info).</p>
+
+ <p>As illustrated above, properties may be combined. If e.g.
+ <c>shuffle</c>, <c>repeat_until_any_fail</c> and <c>sequence</c>
+ are all specified, the test cases in the group will be executed
+ repeatedly, and in random order, until a test case fails. Then
+ execution is immediately stopped and the rest of the cases skipped.</p>
<p>Before execution of a group begins, the configuration function
- <c>init_per_group(GroupName, Config)</c> is called (the function is
- mandatory if one or more test case groups are defined). The list of tuples
+ <c>init_per_group(GroupName, Config)</c> is called. The list of tuples
returned from this function is passed to the test cases in the usual
manner by means of the <c>Config</c> argument. <c>init_per_group/2</c>
is meant to be used for initializations common for the test cases in the
@@ -466,6 +538,14 @@
<c>end_per_group(GroupName, Config</c> function is called. This function
is meant to be used for cleaning up after <c>init_per_group/2</c>.</p>
+ <p>Whenever a group is executed, if <c>init_per_group</c> and
+ <c>end_per_group</c> do not exist in the suite, Common Test calls
+ dummy functions (with the same names) instead. Output generated by
+ hook functions will be saved to the log files for these dummies
+ (see the <seealso marker="ct_hooks_chapter#manipulating">Common Test
+ Hooks</seealso> chapter for more information).
+ </p>
+
<note><p><c>init_per_testcase/2</c> and <c>end_per_testcase/2</c>
are always called for each individual test case, no matter if the case
belongs to a group or not.</p></note>
@@ -555,6 +635,25 @@
</section>
<section>
+ <title>Parallel test cases and IO</title>
+ <p>A parallel test case has a private IO server as its group leader.
+ (Please see the Erlang Run-Time System Application documentation for
+ a description of the group leader concept). The
+ central IO server process that handles the output from regular test
+ cases and configuration functions, does not respond to IO messages
+ during execution of parallel groups. This is important to understand
+ in order to avoid certain traps, like this one:</p>
+ <p>If a process, <c>P</c>, is spawned during execution of e.g.
+ <c>init_per_suite/1</c>, it will inherit the group leader of the
+ <c>init_per_suite</c> process. This group leader is the central IO server
+ process mentioned above. If, at a later time, <em>during parallel test case
+ execution</em>, some event triggers process <c>P</c> to call
+ <c>io:format/1/2</c>, that call will never return (since the group leader
+ is in a non-responsive state) and cause <c>P</c> to hang.
+ </p>
+ </section>
+
+ <section>
<title>Repeated groups</title>
<marker id="repeated_groups"></marker>
<p>A test case group may be repeated a certain number of times
@@ -641,10 +740,55 @@
</section>
<section>
+ <marker id="group_info"></marker>
+ <title>Group info function</title>
+
+ <p>The test case group info function, <c>group(GroupName)</c>,
+ serves the same purpose as the suite- and test case info
+ functions previously described in this chapter. The scope for
+ the group info, however, is all test cases and sub-groups in the
+ group in question (<c>GroupName</c>).</p>
+ <p>Example:</p>
+ <pre>
+ group(connection_tests) ->
+ [{require,login_data},
+ {timetrap,1000}].</pre>
+
+ <p>The group info properties override those set with the
+ suite info function, and may in turn be overridden by test
+ case info properties. Please see the test case info
+ function above for a list of valid info properties and more
+ general information.</p>
+ </section>
+
+ <section>
+ <title>Info functions for init- and end-configuration</title>
+ <p>It is possible to use info functions also for the <c>init_per_suite</c>,
+ <c>end_per_suite</c>, <c>init_per_group</c>, and <c>end_per_group</c>
+ functions, and it works the same way as with info functions
+ for test cases (see above). This is useful e.g. for setting
+ timetraps and requiring external configuration data relevant
+ only for the configuration function in question (without
+ affecting properties set for groups and test cases in the suite).</p>
+
+ <p>The info function <c>init/end_per_suite()</c> is called for
+ <c>init/end_per_suite(Config)</c>, and info function
+ <c>init/end_per_group(GroupName)</c> is called for
+ <c>init/end_per_group(GroupName,Config)</c>. Info functions
+ can not be used with <c>init/end_per_testcase(TestCase, Config)</c>,
+ however, since these configuration functions execute on the test case process
+ and will use the same properties as the test case (i.e. the properties
+ set by the test case info function, <c>TestCase()</c>). Please see the test case
+ info function above for a list of valid info properties and more
+ general information.
+ </p>
+ </section>
+
+ <section>
<marker id="data_priv_dir"></marker>
<title>Data and Private Directories</title>
- <p>The data directory (<c>data_dir</c>) is the directory where the
+ <p>The data directory, <c>data_dir</c>, is the directory where the
test module has its own files needed for the testing. The name
of the <c>data_dir</c> is the the name of the test suite followed
by <c>"_data"</c>. For example,
@@ -668,12 +812,39 @@
</p>
-->
<p>
- The <c>priv_dir</c> is the test suite's private directory. This
- directory should be used when a test case needs to write to
- files. The name of the private directory is generated by the test
- server, which also creates the directory.
+ <c>priv_dir</c> is the private directory for the test cases.
+ This directory may be used whenever a test case (or configuration function)
+ needs to write something to file. The name of the private directory is
+ generated by Common Test, which also creates the directory.
</p>
-
+ <p>By default, Common Test creates one central private directory
+ per test run that all test cases share. This may not always be suitable,
+ especially if the same test cases are executed multiple times during
+ a test run (e.g. if they belong to a test case group with repeat
+ property), and there's a risk that files in the private directory get
+ overwritten. Under these circumstances, it's possible to configure
+ Common Test to create one dedicated private directory per
+ test case and execution instead. This is accomplished by means of
+ the flag/option: <c>create_priv_dir</c> (to be used with the
+ <c>ct_run</c> program, the <c><seealso marker="ct#run_test-1">ct:run_test/1</seealso></c> function, or
+ as test specification term). There are three possible values
+ for this option:
+ <list>
+ <item><c>auto_per_run</c></item>
+ <item><c>auto_per_tc</c></item>
+ <item><c>manual_per_tc</c></item>
+ </list>
+ The first value indicates the default priv_dir behaviour, i.e.
+ one private directory created per test run. The two latter
+ values tell Common Test to generate a unique test directory name
+ per test case and execution. If the auto version is used, <em>all</em>
+ private directories will be created automatically. This can obviously
+ become very inefficient for test runs with many test cases and/or
+ repetitions. Therefore, in case the manual version is instead used, the
+ test case must tell Common Test to create priv_dir when it needs it.
+ It does this by calling the function <c><seealso marker="ct#make_priv_dir-0">ct:make_priv_dir/0</seealso></c>.
+ </p>
+
<note><p>You should not depend on current working directory for
reading and writing data files since this is not portable. All
scratch files are to be written in the <c>priv_dir</c> and all
@@ -704,34 +875,63 @@
<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
- in <c>suite/0</c> is the value that will be used for each test case
- in the suite (as well as for the configuration functions
- <c>init_per_suite/1</c> and <c>end_per_suite</c>). A timetrap timeout
- value set with the test case info function will override the value set
- by <c>suite/0</c>, but only for that particular test case.</p>
- <p>It is also possible to set/reset a timetrap during test case (or
- configuration function) execution. This is done by calling
- <c>ct:timetrap/1</c>. This function will cancel the current timetrap
- and start a new one.</p>
+ <c>timetrap</c> is specified either by the suite-, group-,
+ or test case info function. The timetrap timeout value defined by
+ <c>suite/0</c> is the value that will be used for each test case
+ in the suite (as well as for the configuration functions
+ <c>init_per_suite/1</c>, <c>end_per_suite/1</c>, <c>init_per_group/2</c>,
+ and <c>end_per_group/2</c>). A timetrap value defined by
+ <c>group(GroupName)</c> overrides one defined by <c>suite()</c>
+ and will be used for each test case in group <c>GroupName</c>, and any
+ of its sub-groups. If a timetrap value is defined by <c>group/1</c>
+ for a sub-group, it overrides that of its higher level groups. Timetrap
+ values set by individual test cases (by means of the test case info
+ function) overrides both group- and suite- level timetraps.</p>
+
+ <p>It is also possible to dynamically set/reset a timetrap during the
+ excution of a test case, or configuration function. This is done by calling
+ <c><seealso marker="ct#timetrap-1">ct:timetrap/1</seealso></c>. This function cancels the current timetrap
+ and starts a new one (that stays active until timeout, or end of the
+ current function).</p>
+
<p>Timetrap values can be extended with a multiplier value specified at
- startup with the <c>multiply_timetraps</c> option. It is also possible
- to let Test Server decide to scale up timetrap timeout values
- automatically, e.g. if tools such as cover or trace are running during
- the test. This feature is disabled by default and can be enabled with
- the <c>scale_timetraps</c> start option.</p>
+ startup with the <c>multiply_timetraps</c> option. It is also possible
+ to let the test server decide to scale up timetrap timeout values
+ automatically, e.g. if tools such as cover or trace are running during
+ the test. This feature is disabled by default and can be enabled with
+ the <c>scale_timetraps</c> start option.</p>
+
<p>If a test case needs to suspend itself for a time that also gets
- 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>
+ multipled by <c>multiply_timetraps</c> (and possibly also scaled up if
+ <c>scale_timetraps</c> is enabled), the function <c><seealso marker="ct#sleep-1">ct:sleep/1</seealso></c>
+ may be used (instead of e.g. <c>timer:sleep/1</c>).</p>
+
+ <p>A function (<c>fun/0</c> or <c>MFA</c>) may be specified as
+ timetrap value in the suite-, group- and test case info function, as
+ well as argument to the <c><seealso marker="ct#timetrap-1">ct:timetrap/1</seealso></c> function. Examples:</p>
+
+ <p><c>{timetrap,{my_test_utils,timetrap,[?MODULE,system_start]}}</c></p>
+ <p><c>ct:timetrap(fun() -> my_timetrap(TestCaseName, Config) end)</c></p>
+
+ <p>The user timetrap function may be used for two things:</p>
+ <list>
+ <item>To act as a timetrap - the timeout is triggered when the
+ function returns.</item>
+ <item>To return a timetrap time value (other than a function).</item>
+ </list>
+ <p>Before execution of the timetrap function (which is performed
+ on a parallel, dedicated timetrap process), Common Test cancels
+ any previously set timer for the test case or configuration function.
+ When the timetrap function returns, the timeout is triggered, <em>unless</em>
+ the return value is a valid timetrap time, such as an integer,
+ or a <c>{SecMinOrHourTag,Time}</c> tuple (see the
+ <seealso marker="common_test">common_test reference manual</seealso> for
+ details). If a time value is returned, a new timetrap is started
+ to generate a timeout after the specified time.</p>
+
+ <p>The user timetrap function may of course return a time value after a delay,
+ and if so, the effective timetrap time is the delay time <em>plus</em> the
+ returned time.</p>
</section>
<section>
diff --git a/lib/common_test/include/ct.hrl b/lib/common_test/include/ct.hrl
index 5a77108e1a..43b1b1c11f 100644
--- a/lib/common_test/include/ct.hrl
+++ b/lib/common_test/include/ct.hrl
@@ -19,3 +19,16 @@
-include_lib("test_server/include/test_server.hrl").
+%% the log level is used as argument to any CT logging function
+-define(MIN_IMPORTANCE, 0 ).
+-define(LOW_IMPORTANCE, 25).
+-define(STD_IMPORTANCE, 50).
+-define(HI_IMPORTANCE, 75).
+-define(MAX_IMPORTANCE, 99).
+
+%% verbosity thresholds to filter out logging printouts
+-define(MIN_VERBOSITY, 0 ). %% turn logging off
+-define(LOW_VERBOSITY, 25 ).
+-define(STD_VERBOSITY, 50 ).
+-define(HI_VERBOSITY, 75 ).
+-define(MAX_VERBOSITY, 100).
diff --git a/lib/common_test/priv/Makefile.in b/lib/common_test/priv/Makefile.in
index f4a0c181f9..2f06f7df65 100644
--- a/lib/common_test/priv/Makefile.in
+++ b/lib/common_test/priv/Makefile.in
@@ -59,6 +59,8 @@ ifneq ($(findstring win32,$(TARGET)),win32)
FILES = vts.tool
SCRIPTS =
IMAGES = tile1.jpg
+CSS = ct_default.css
+JS = jquery-latest.js jquery.tablesorter.min.js
#
# Rules
@@ -84,12 +86,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk
ifeq ($(XNIX),true)
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(JS) "$(RELSYSDIR)/priv"
else
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(JS) "$(RELSYSDIR)/priv"
endif
release_docs_spec:
@@ -105,6 +107,8 @@ else
#
FILES = vts.tool
IMAGES = tile1.jpg
+CSS = ct_default.css
+JS = jquery-latest.js jquery.tablesorter.min.js
#
# Rules
@@ -123,8 +127,8 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(JS) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/common_test/priv/auxdir/config.guess b/lib/common_test/priv/auxdir/config.guess
index fefabd7dd0..38a833903b 120000..100755
--- a/lib/common_test/priv/auxdir/config.guess
+++ b/lib/common_test/priv/auxdir/config.guess
@@ -1 +1,1519 @@
-../../../../erts/autoconf/config.guess \ No newline at end of file
+#! /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/common_test/priv/auxdir/config.sub b/lib/common_test/priv/auxdir/config.sub
index 90979e8924..f43233b104 120000..100755
--- a/lib/common_test/priv/auxdir/config.sub
+++ b/lib/common_test/priv/auxdir/config.sub
@@ -1 +1,1630 @@
-../../../../erts/autoconf/config.sub \ No newline at end of file
+#! /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/common_test/priv/auxdir/install-sh b/lib/common_test/priv/auxdir/install-sh
index 9422c370df..a5897de6ea 120000..100755
--- a/lib/common_test/priv/auxdir/install-sh
+++ b/lib/common_test/priv/auxdir/install-sh
@@ -1 +1,519 @@
-../../../../erts/autoconf/install-sh \ No newline at end of file
+#!/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/common_test/priv/ct_default.css b/lib/common_test/priv/ct_default.css
new file mode 100644
index 0000000000..1188f8f676
--- /dev/null
+++ b/lib/common_test/priv/ct_default.css
@@ -0,0 +1,201 @@
+/* Stylesheet for Common Test */
+
+body {
+ padding: 10px; margin: 10px;
+ -webkit-font-smoothing: antialiased;
+ background-color: #FBFFFC;
+}
+
+a:link {
+ color: #2B507D;
+}
+
+a:visited {
+ color: #85ABD5
+}
+
+h1 {
+ font-family: verdana, arial, sans-serif; font-size: 200%;
+ letter-spacing: -2px; word-spacing: 2px; font-weight: bold;
+ color: #3F3F3F;
+}
+
+h2 {
+ font-family: verdana, arial, sans-serif; font-size: 175%;
+ letter-spacing: -2px; word-spacing: 2px; font-weight: normal;
+ color: #3F3F3F;
+}
+
+h3 {
+ font-family: verdana, arial, sans-serif; font-size: 140%;
+ letter-spacing: -2px; word-spacing: 2px; font-weight: bold;
+ color: #3F3F3F;
+}
+
+h4 {
+ font-family: verdana, arial, sans-serif; font-size: 120%;
+ letter-spacing: -2px; word-spacing: 2px; font-weight: normal;
+ color: #3F3F3F;
+}
+
+p {
+ font-family: "Trebuchet MS", "Lucida Sans Unicode", verdana, arial, sans-serif;
+ font-size: .9em; color: #000000;
+}
+
+ul {
+ list-style-type: none;
+ padding: 0em;
+ margin: 1em;
+}
+li {
+ font-size: 0.95em; color: #000000;
+ margin: .3em 0;
+}
+
+pre {
+ color: black;
+ font-family: "Monaco", "Andale Mono", "Consolas", monospace;
+ font-size: .8em;
+ }
+
+code {
+ color: black;
+ font-family: "Monaco", "Andale Mono", "Consolas", monospace;
+ font-size: .8em;
+}
+
+div.mono_sm {
+ font-family: "Courier New", monospace; font-size: .75em;
+ word-spacing: 1px; color: #000000;
+}
+
+div.mono_la {
+ font-family: "Courier New", monospace; font-size: .8em;
+ color: #000000;
+}
+
+div.copyright {
+ padding: 20px 0px 0px 0px;
+ font-family: "Courier New", monospace; font-size: .7em;
+ color: #000000;
+}
+
+div.ct_internal {
+ background: lightgrey; color: black;
+ font-family: "Monaco", "Andale Mono", "Consolas", monospace;
+ font-size: .95em;
+ margin: .2em 0 0 0;
+}
+
+div.ct_error_notify {
+ background: #CC0000;
+ color: #FFFFFF;
+ font-family: "Monaco", "Andale Mono", "Consolas", monospace;
+ font-size: 1.05em;
+ margin: .2em 0 0 0;
+}
+
+div.default {
+ background: lightgreen; color: black;
+ font-family: "Monaco", "Andale Mono", "Consolas", monospace;
+ font-size: 1.05em;
+ margin: .2em 0 0 0;
+}
+
+div.label {
+ font-family: verdana, arial, sans-serif; font-size: 200%;
+ letter-spacing: -2.5px; word-spacing: 2px;
+ font-weight: bold; color: #2B507D;
+}
+
+table {
+ border-collapse: collapse; border: 6px solid #3F3F3F;
+ background: #FFFFFF;
+ font: .8em/1.2em "Lucida Sans Unicode", verdana, arial, sans-serif;
+ color: #222;
+}
+
+caption {
+ font-size: 1.3em; font-weight: bold;
+ text-align: center; padding: 1em 4px;
+}
+
+td, th {
+ padding: .5em 7px .5em 7px; line-height: 1.3em;
+ border-bottom: 3px solid #F5C4C1;
+ border-left: 2px dashed #809FFF;
+}
+
+th {
+ background: #3F3F3F; color: #fff;
+ font-family: arial, sans-serif; font-size: 120%;
+ letter-spacing: -0.5px;
+ font-weight: bold; text-align: center;
+ padding-right: .5em; vertical-align: top;
+}
+
+thead th {
+ background: #3F3F3F; color: #fff;
+ font-family: arial, sans-serif; font-size: 120%;
+ letter-spacing: -0.5px;
+ font-weight: bold; text-align: center;
+ padding-right: .5em; vertical-align: top;
+ text-decoration: underline;
+}
+
+tfoot td {
+ font-family: arial, sans-serif; font-size: 110%;
+ letter-spacing: -0.5px;
+ font-weight: bold;
+}
+
+.odd td {
+ background: #F3F3F3;
+}
+.odd th {
+ background: #F3F3F3;
+}
+
+td a, td a:link {
+ color: #2B507D;
+}
+
+td a:visited {
+ color: #85ABD5;
+}
+
+tr:hover th[scope=row], tr:hover td {
+ background-color: #D1D1D1;
+ color: #fff;
+}
+
+td a:hover, td a:focus {
+ color: #85ABD5;
+}
+
+th a, td a:active {
+ color: #85ABD5;
+}
+
+th + td {
+ padding-left: .5em;
+}
+
+#button_holder {
+ display: block; float: center;
+ font-family: arial, verdana, sans-serif;
+ font-size: 12px; text-shadow: 1px 1px lightgray;
+}
+
+.btn a {
+ padding: 6px 12px; float: center;
+ text-decoration: none; color: #3F3F3F;
+ font-weight: bold; border: 3px outset #3F3F3F;
+ background-color: #F3F3F3;
+}
+
+.btn a:hover {
+ color: #fff;
+ background-color: #809FFF;
+}
diff --git a/lib/common_test/priv/jquery-latest.js b/lib/common_test/priv/jquery-latest.js
new file mode 100644
index 0000000000..ac7e7009dc
--- /dev/null
+++ b/lib/common_test/priv/jquery-latest.js
@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/lib/common_test/priv/jquery.tablesorter.min.js b/lib/common_test/priv/jquery.tablesorter.min.js
new file mode 100644
index 0000000000..b8605df1e7
--- /dev/null
+++ b/lib/common_test/priv/jquery.tablesorter.min.js
@@ -0,0 +1,4 @@
+
+(function($){$.extend({tablesorter:new
+function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1
+var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery); \ No newline at end of file
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 125aa828fb..f7dce195d7 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2011. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The 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,14 +69,19 @@ MODULES= \
ct_slave \
ct_hooks\
ct_hooks_lock\
- cth_log_redirect
+ cth_log_redirect\
+ cth_surefire \
+ ct_netconfc \
+ ct_conn_log_h \
+ cth_conn_log
TARGET_MODULES= $(MODULES:%=$(EBIN)/%)
BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
ERL_FILES= $(MODULES:=.erl)
HRL_FILES = \
- ct_util.hrl
+ ct_util.hrl \
+ ct_netconfc.hrl
EXTERNAL_HRL_FILES = \
../include/ct.hrl \
../include/ct_event.hrl
@@ -132,12 +137,12 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) "$(RELSYSDIR)/include"
release_tests_spec: opt
$(INSTALL_DIR) $(RELEASE_PATH)/common_test_test
diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src
index 57606c01db..18c1dec784 100644
--- a/lib/common_test/src/common_test.app.src
+++ b/lib/common_test/src/common_test.app.src
@@ -1,7 +1,7 @@
% This is an -*- erlang -*- file.
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,12 +25,16 @@
ct_framework,
ct_ftp,
ct_gen_conn,
+ ct_hooks,
+ ct_hooks_lock,
ct_logs,
ct_make,
ct_master,
ct_master_event,
ct_master_logs,
ct_master_status,
+ ct_netconfc,
+ ct_conn_log_h,
ct_repeat,
ct_rpc,
ct_run,
@@ -45,7 +49,10 @@
ct_config,
ct_config_plain,
ct_config_xml,
- ct_slave
+ ct_slave,
+ cth_log_redirect,
+ cth_conn_log,
+ cth_surefire
]},
{registered, [ct_logs,
ct_util_server,
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index 69e15fa246..aa8813c391 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,6 +51,8 @@
-module(ct).
+-include("ct.hrl").
+
%% Command line user interface for running tests
-export([install/1, run/1, run/2, run/3,
run_test/1, run_testspec/1, step/3, step/4,
@@ -60,12 +62,15 @@
-export([require/1, require/2,
get_config/1, get_config/2, get_config/3,
reload_config/1,
- log/1, log/2, log/3,
- print/1, print/2, print/3,
- pal/1, pal/2, pal/3,
- fail/1, comment/1,
+ log/1, log/2, log/3, log/4,
+ print/1, print/2, print/3, print/4,
+ pal/1, pal/2, pal/3, pal/4,
+ capture_start/0, capture_stop/0, capture_get/0, capture_get/1,
+ fail/1, fail/2, comment/1, comment/2, make_priv_dir/0,
testcases/2, userdata/2, userdata/3,
- timetrap/1, sleep/1]).
+ timetrap/1, get_timetrap_info/0, sleep/1,
+ notify/2, sync_notify/2,
+ break/1, break/2, continue/0, continue/1]).
%% New API for manipulating with config handlers
-export([add_config/2, remove_config/2]).
@@ -108,7 +113,7 @@ install(Opts) ->
%%% Cases = atom() | [atom()]
%%% Result = [TestResult] | {error,Reason}
%%%
-%%% @doc Run the given testcase(s).
+%%% @doc Run the given test case(s).
%%%
%%% <p>Requires that <code>ct:install/1</code> has been run first.</p>
%%%
@@ -121,7 +126,7 @@ run(TestDir,Suite,Cases) ->
%%%-----------------------------------------------------------------
%%% @spec run(TestDir,Suite) -> Result
%%%
-%%% @doc Run all testcases in the given suite.
+%%% @doc Run all test cases in the given suite.
%%% @see run/3.
run(TestDir,Suite) ->
ct_run:run(TestDir,Suite).
@@ -130,7 +135,7 @@ run(TestDir,Suite) ->
%%% @spec run(TestDirs) -> Result
%%% TestDirs = TestDir | [TestDir]
%%%
-%%% @doc Run all testcases in all suites in the given directories.
+%%% @doc Run all test cases in all suites in the given directories.
%%% @see run/3.
run(TestDirs) ->
ct_run:run(TestDirs).
@@ -145,11 +150,14 @@ run(TestDirs) ->
%%% {silent_connections,Conns} | {stylesheet,CSSFile} |
%%% {cover,CoverSpecFile} | {step,StepOpts} |
%%% {event_handler,EventHandlers} | {include,InclDirs} |
-%%% {auto_compile,Bool} | {multiply_timetraps,M} | {scale_timetraps,Bool} |
+%%% {auto_compile,Bool} | {create_priv_dir,CreatePrivDir} |
+%%% {multiply_timetraps,M} | {scale_timetraps,Bool} |
%%% {repeat,N} | {duration,DurTime} | {until,StopTime} |
%%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} |
-%%% {refresh_logs,LogDir} | {logopts,LogOpts} | {basic_html,Bool} |
-%%% {ct_hooks, CTHs} | {enable_builtin_hooks,Bool}
+%%% {refresh_logs,LogDir} | {logopts,LogOpts} |
+%%% {verbosity,VLevels} | {basic_html,Bool} |
+%%% {ct_hooks, CTHs} | {enable_builtin_hooks,Bool} |
+%%% {release_shell,Bool}
%%% TestDirs = [string()] | string()
%%% Suites = [string()] | [atom()] | string() | atom()
%%% Cases = [atom()] | atom()
@@ -170,6 +178,7 @@ run(TestDirs) ->
%%% EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs}
%%% InitArgs = [term()]
%%% InclDirs = [string()] | string()
+%%% CreatePrivDir = auto_per_run | auto_per_tc | manual_per_tc
%%% M = integer()
%%% N = integer()
%%% DurTime = string(HHMMSS)
@@ -179,18 +188,30 @@ run(TestDirs) ->
%%% DecryptFile = string()
%%% LogOpts = [LogOpt]
%%% LogOpt = no_nl | no_src
+%%% VLevels = VLevel | [{Category,VLevel}]
+%%% VLevel = integer()
+%%% Category = atom()
%%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}]
%%% CTHModule = atom()
%%% CTHInitArgs = term()
-%%% Result = [TestResult] | {error,Reason}
-%%% @doc Run tests as specified by the combination of options in <code>Opts</code>.
+%%% Result = {Ok,Failed,{UserSkipped,AutoSkipped}} | TestRunnerPid | {error,Reason}
+%%% Ok = integer()
+%%% Failed = integer()
+%%% UserSkipped = integer()
+%%% AutoSkipped = integer()
+%%% TestRunnerPid = pid()
+%%% Reason = term()
+%%% @doc <p>Run tests as specified by the combination of options in <code>Opts</code>.
%%% The options are the same as those used with the
%%% <seealso marker="ct_run#ct_run"><code>ct_run</code></seealso> program.
%%% Note that here a <code>TestDir</code> can be used to point out the path to
%%% a <code>Suite</code>. Note also that the option <code>testcase</code>
%%% corresponds to the <code>-case</code> option in the <code>ct_run</code>
%%% program. Configuration files specified in <code>Opts</code> will be
-%%% installed automatically at startup.
+%%% installed automatically at startup.</p>
+%%% <p><code>TestRunnerPid</code> is returned if <code>release_shell == true</code>
+%%% (see the User's Guide for details).</p>
+%%% <p><code>Reason</code> indicates what type of error has been encountered.</p>
run_test(Opts) ->
ct_run:run_test(Opts).
@@ -262,27 +283,34 @@ stop_interactive() ->
%%%-----------------------------------------------------------------
%%% @spec require(Required) -> ok | {error,Reason}
-%%% Required = Key | {Key,SubKeys}
+%%% Required = Key | {Key,SubKeys} | {Key,SubKey,SubKeys}
%%% Key = atom()
%%% SubKeys = SubKey | [SubKey]
%%% SubKey = atom()
%%%
-%%% @doc Check if the required configuration is available.
+%%% @doc Check if the required configuration is available. It is possible
+%%% to specify arbitrarily deep tuples as <c>Required</c>. Note that it is
+%%% only the last element of the tuple which can be a list of <c>SubKey</c>s.
%%%
-%%% <p>Example: require the variable <code>myvar</code>:<br/>
-%%% <code>ok = ct:require(myvar)</code></p>
+%%% <p>Example 1: require the variable <code>myvar</code>:</p>
+%%% <pre>ok = ct:require(myvar).</pre>
%%%
%%% <p>In this case the config file must at least contain:</p>
-%%% <pre>
-%%% {myvar,Value}.</pre>
+%%% <pre>{myvar,Value}.</pre>
%%%
-%%% <p>Example: require the variable <code>myvar</code> with
-%%% subvariable <code>sub1</code>:<br/>
-%%% <code>ok = ct:require({myvar,sub1})</code></p>
+%%% <p>Example 2: require the key <code>myvar</code> with
+%%% subkeys <code>sub1</code> and <code>sub2</code>:</p>
+%%% <pre>ok = ct:require({myvar,[sub1,sub2]}).</pre>
%%%
%%% <p>In this case the config file must at least contain:</p>
-%%% <pre>
-%%% {myvar,[{sub1,Value}]}.</pre>
+%%% <pre>{myvar,[{sub1,Value},{sub2,Value}]}.</pre>
+%%%
+%%% <p>Example 3: require the key <code>myvar</code> with
+%%% subkey <code>sub1</code> with <code>subsub1</code>:</p>
+%%% <pre>ok = ct:require({myvar,sub1,sub2}).</pre>
+%%%
+%%% <p>In this case the config file must at least contain:</p>
+%%% <pre>{myvar,[{sub1,[{sub2,Value}]}]}.</pre>
%%%
%%% @see require/2
%%% @see get_config/1
@@ -294,30 +322,36 @@ require(Required) ->
%%%-----------------------------------------------------------------
%%% @spec require(Name,Required) -> ok | {error,Reason}
%%% Name = atom()
-%%% Required = Key | {Key,SubKeys}
+%%% Required = Key | {Key,SubKey} | {Key,SubKey,SubKey}
+%%% SubKey = Key
%%% Key = atom()
-%%% SubKeys = SubKey | [SubKey]
-%%% SubKey = atom()
%%%
%%% @doc Check if the required configuration is available, and give it
-%%% a name.
+%%% a name. The semantics for <c>Required</c> is the same as in
+%%% <c>required/1</c> except that it is not possible to specify a list
+%%% of <c>SubKey</c>s.
%%%
-%%% <p>If the requested data is available, the main entry will be
+%%% <p>If the requested data is available, the sub entry will be
%%% associated with <code>Name</code> so that the value of the element
%%% can be read with <code>get_config/1,2</code> provided
-%%% <code>Name</code> instead of the <code>Key</code>.</p>
+%%% <code>Name</code> instead of the whole <code>Required</code> term.</p>
%%%
%%% <p>Example: Require one node with a telnet connection and an
-%%% ftp connection. Name the node <code>a</code>:<br/> <code>ok =
-%%% ct:require(a,{node,[telnet,ftp]}).</code><br/> All references
-%%% to this node may then use the node name. E.g. you can fetch a
-%%% file over ftp like this:<br/>
-%%% <code>ok = ct:ftp_get(a,RemoteFile,LocalFile).</code></p>
+%%% ftp connection. Name the node <code>a</code>:
+%%% <pre>ok = ct:require(a,{machine,node}).</pre>
+%%% All references to this node may then use the node name.
+%%% E.g. you can fetch a file over ftp like this:</p>
+%%% <pre>ok = ct:ftp_get(a,RemoteFile,LocalFile).</pre>
%%%
%%% <p>For this to work, the config file must at least contain:</p>
-%%% <pre>
-%%% {node,[{telnet,IpAddr},
-%%% {ftp,IpAddr}]}.</pre>
+%%% <pre>{machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.</pre>
+%%%
+%%% <note>The behaviour of this function changed radically in common_test
+%%% 1.6.2. In order too keep some backwards compatability it is still possible
+%%% to do: <br/><c>ct:require(a,{node,[telnet,ftp]}).</c><br/>
+%%% This will associate the name <c>a</c> with the top level <c>node</c> entry.
+%%% For this to work, the config file must at least contain:<br/>
+%%% <c>{node,[{telnet,IpAddr},{ftp,IpAddr}]}.</c></note>
%%%
%%% @see require/1
%%% @see get_config/1
@@ -340,7 +374,7 @@ get_config(Required,Default) ->
%%%-----------------------------------------------------------------
%%% @spec get_config(Required,Default,Opts) -> ValueOrElement
-%%% Required = KeyOrName | {KeyOrName,SubKey}
+%%% Required = KeyOrName | {KeyOrName,SubKey} | {KeyOrName,SubKey,SubKey}
%%% KeyOrName = atom()
%%% SubKey = atom()
%%% Default = term()
@@ -358,25 +392,25 @@ get_config(Required,Default) ->
%%% <p>Example, given the following config file:</p>
%%% <pre>
%%% {unix,[{telnet,IpAddr},
-%%% {username,Username},
-%%% {password,Password}]}.</pre>
-%%% <p><code>get_config(unix,Default) ->
+%%% {user,[{username,Username},
+%%% {password,Password}]}]}.</pre>
+%%% <p><code>ct:get_config(unix,Default) ->
%%% [{telnet,IpAddr},
-%%% {username,Username},
-%%% {password,Password}]</code><br/>
-%%% <code>get_config({unix,telnet},Default) -> IpAddr</code><br/>
-%%% <code>get_config({unix,ftp},Default) -> Default</code><br/>
-%%% <code>get_config(unknownkey,Default) -> Default</code></p>
+%%% {user, [{username,Username},
+%%% {password,Password}]}]</code><br/>
+%%% <code>ct:get_config({unix,telnet},Default) -> IpAddr</code><br/>
+%%% <code>ct:get_config({unix,user,username},Default) -> Username</code><br/>
+%%% <code>ct:get_config({unix,ftp},Default) -> Default</code><br/>
+%%% <code>ct:get_config(unknownkey,Default) -> Default</code></p>
%%%
%%% <p>If a config variable key has been associated with a name (by
%%% means of <code>require/2</code> or a require statement), the name
%%% may be used instead of the key to read the value:</p>
%%%
-%%% <p><code>require(myhost,unix) -> ok</code><br/>
-%%% <code>get_config(myhost,Default) ->
-%%% [{telnet,IpAddr},
-%%% {username,Username},
-%%% {password,Password}]</code></p>
+%%% <p><code>ct:require(myuser,{unix,user}) -> ok.</code><br/>
+%%% <code>ct:get_config(myuser,Default) ->
+%%% [{username,Username},
+%%% {password,Password}]</code></p>
%%%
%%% <p>If a config variable is defined in multiple files and you want to
%%% access all possible values, use the <code>all</code> option. The
@@ -386,9 +420,7 @@ get_config(Required,Default) ->
%%%
%%% <p>If you want config elements (key-value tuples) returned as result
%%% instead of values, use the <code>element</code> option.
-%%% The returned elements will then be on the form <code>{KeyOrName,Value}</code>,
-%%% or (in case a subkey has been specified)
-%%% <code>{{KeyOrName,SubKey},Value}</code></p>
+%%% The returned elements will then be on the form <code>{Required,Value}</code></p>
%%%
%%% @see get_config/1
%%% @see get_config/2
@@ -399,7 +431,7 @@ get_config(Required,Default,Opts) ->
%%%-----------------------------------------------------------------
%%% @spec reload_config(Required) -> ValueOrElement
-%%% Required = KeyOrName | {KeyOrName,SubKey}
+%%% Required = KeyOrName | {KeyOrName,SubKey} | {KeyOrName,SubKey,SubKey}
%%% KeyOrName = atom()
%%% SubKey = atom()
%%% ValueOrElement = term()
@@ -418,106 +450,224 @@ reload_config(Required)->
%%%-----------------------------------------------------------------
%%% @spec log(Format) -> ok
-%%% @equiv log(default,Format,[])
+%%% @equiv log(default,50,Format,[])
log(Format) ->
- log(default,Format,[]).
+ log(default,?STD_IMPORTANCE,Format,[]).
%%%-----------------------------------------------------------------
%%% @spec log(X1,X2) -> ok
-%%% X1 = Category | Format
+%%% X1 = Category | Importance | Format
%%% X2 = Format | Args
-%%% @equiv log(Category,Format,Args)
+%%% @equiv log(Category,Importance,Format,Args)
log(X1,X2) ->
- {Category,Format,Args} =
- if is_atom(X1) -> {X1,X2,[]};
- is_list(X1) -> {default,X1,X2}
+ {Category,Importance,Format,Args} =
+ if is_atom(X1) -> {X1,?STD_IMPORTANCE,X2,[]};
+ is_integer(X1) -> {default,X1,X2,[]};
+ is_list(X1) -> {default,?STD_IMPORTANCE,X1,X2}
+ end,
+ log(Category,Importance,Format,Args).
+
+%%%-----------------------------------------------------------------
+%%% @spec log(X1,X2,X3) -> ok
+%%% X1 = Category | Importance
+%%% X2 = Importance | Format
+%%% X3 = Format | Args
+%%% @equiv log(Category,Importance,Format,Args)
+log(X1,X2,X3) ->
+ {Category,Importance,Format,Args} =
+ if is_atom(X1), is_integer(X2) -> {X1,X2,X3,[]};
+ is_atom(X1), is_list(X2) -> {X1,?STD_IMPORTANCE,X2,X3};
+ is_integer(X1) -> {default,X1,X2,X3}
end,
- log(Category,Format,Args).
+ log(Category,Importance,Format,Args).
%%%-----------------------------------------------------------------
-%%% @spec log(Category,Format,Args) -> ok
+%%% @spec log(Category,Importance,Format,Args) -> ok
%%% Category = atom()
+%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%%
-%%% @doc Printout from a testcase to the log.
+%%% @doc Printout from a test case to the log file.
%%%
-%%% <p>This function is meant for printing stuff directly from a
-%%% testcase (i.e. not from within the CT framework) in the test
-%%% log.</p>
+%%% <p>This function is meant for printing a string directly from a
+%%% test case to the test case log file.</p>
%%%
-%%% <p>Default <code>Category</code> is <code>default</code> and
-%%% default <code>Args</code> is <code>[]</code>.</p>
-log(Category,Format,Args) ->
- ct_logs:tc_log(Category,Format,Args).
+%%% <p>Default <code>Category</code> is <code>default</code>,
+%%% default <code>Importance</code> is <code>?STD_IMPORTANCE</code>,
+%%% and default value for <code>Args</code> is <code>[]</code>.</p>
+%%% <p>Please see the User's Guide for details on <code>Category</code>
+%%% and <code>Importance</code>.</p>
+log(Category,Importance,Format,Args) ->
+ ct_logs:tc_log(Category,Importance,Format,Args).
%%%-----------------------------------------------------------------
%%% @spec print(Format) -> ok
-%%% @equiv print(default,Format,[])
+%%% @equiv print(default,50,Format,[])
print(Format) ->
- print(default,Format,[]).
+ print(default,?STD_IMPORTANCE,Format,[]).
%%%-----------------------------------------------------------------
-%%% @equiv print(Category,Format,Args)
+%%% @spec print(X1,X2) -> ok
+%%% X1 = Category | Importance | Format
+%%% X2 = Format | Args
+%%% @equiv print(Category,Importance,Format,Args)
print(X1,X2) ->
- {Category,Format,Args} =
- if is_atom(X1) -> {X1,X2,[]};
- is_list(X1) -> {default,X1,X2}
+ {Category,Importance,Format,Args} =
+ if is_atom(X1) -> {X1,?STD_IMPORTANCE,X2,[]};
+ is_integer(X1) -> {default,X1,X2,[]};
+ is_list(X1) -> {default,?STD_IMPORTANCE,X1,X2}
end,
- print(Category,Format,Args).
+ print(Category,Importance,Format,Args).
%%%-----------------------------------------------------------------
-%%% @spec print(Category,Format,Args) -> ok
+%%% @spec print(X1,X2,X3) -> ok
+%%% X1 = Category | Importance
+%%% X2 = Importance | Format
+%%% X3 = Format | Args
+%%% @equiv print(Category,Importance,Format,Args)
+print(X1,X2,X3) ->
+ {Category,Importance,Format,Args} =
+ if is_atom(X1), is_integer(X2) -> {X1,X2,X3,[]};
+ is_atom(X1), is_list(X2) -> {X1,?STD_IMPORTANCE,X2,X3};
+ is_integer(X1) -> {default,X1,X2,X3}
+ end,
+ print(Category,Importance,Format,Args).
+
+%%%-----------------------------------------------------------------
+%%% @spec print(Category,Importance,Format,Args) -> ok
%%% Category = atom()
+%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%%
-%%% @doc Printout from a testcase to the console.
+%%% @doc Printout from a test case to the console.
%%%
-%%% <p>This function is meant for printing stuff from a testcase on
-%%% the console.</p>
+%%% <p>This function is meant for printing a string from a test case
+%%% to the console.</p>
%%%
-%%% <p>Default <code>Category</code> is <code>default</code> and
-%%% default <code>Args</code> is <code>[]</code>.</p>
-print(Category,Format,Args) ->
- ct_logs:tc_print(Category,Format,Args).
+%%% <p>Default <code>Category</code> is <code>default</code>,
+%%% default <code>Importance</code> is <code>?STD_IMPORTANCE</code>,
+%%% and default value for <code>Args</code> is <code>[]</code>.</p>
+%%% <p>Please see the User's Guide for details on <code>Category</code>
+%%% and <code>Importance</code>.</p>
+print(Category,Importance,Format,Args) ->
+ ct_logs:tc_print(Category,Importance,Format,Args).
%%%-----------------------------------------------------------------
%%% @spec pal(Format) -> ok
-%%% @equiv pal(default,Format,[])
+%%% @equiv pal(default,50,Format,[])
pal(Format) ->
- pal(default,Format,[]).
+ pal(default,?STD_IMPORTANCE,Format,[]).
%%%-----------------------------------------------------------------
%%% @spec pal(X1,X2) -> ok
-%%% X1 = Category | Format
+%%% X1 = Category | Importance | Format
%%% X2 = Format | Args
-%%% @equiv pal(Category,Format,Args)
+%%% @equiv pal(Category,Importance,Format,Args)
pal(X1,X2) ->
- {Category,Format,Args} =
- if is_atom(X1) -> {X1,X2,[]};
- is_list(X1) -> {default,X1,X2}
+ {Category,Importance,Format,Args} =
+ if is_atom(X1) -> {X1,?STD_IMPORTANCE,X2,[]};
+ is_integer(X1) -> {default,X1,X2,[]};
+ is_list(X1) -> {default,?STD_IMPORTANCE,X1,X2}
+ end,
+ pal(Category,Importance,Format,Args).
+
+%%%-----------------------------------------------------------------
+%%% @spec pal(X1,X2,X3) -> ok
+%%% X1 = Category | Importance
+%%% X2 = Importance | Format
+%%% X3 = Format | Args
+%%% @equiv pal(Category,Importance,Format,Args)
+pal(X1,X2,X3) ->
+ {Category,Importance,Format,Args} =
+ if is_atom(X1), is_integer(X2) -> {X1,X2,X3,[]};
+ is_atom(X1), is_list(X2) -> {X1,?STD_IMPORTANCE,X2,X3};
+ is_integer(X1) -> {default,X1,X2,X3}
end,
- pal(Category,Format,Args).
+ pal(Category,Importance,Format,Args).
%%%-----------------------------------------------------------------
-%%% @spec pal(Category,Format,Args) -> ok
+%%% @spec pal(Category,Importance,Format,Args) -> ok
%%% Category = atom()
+%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%%
-%%% @doc Print and log from a testcase.
+%%% @doc Print and log from a test case.
%%%
-%%% <p>This function is meant for printing stuff from a testcase both
-%%% in the log and on the console.</p>
+%%% <p>This function is meant for printing a string from a test case,
+%%% both to the test case log file and to the console.</p>
%%%
-%%% <p>Default <code>Category</code> is <code>default</code> and
-%%% default <code>Args</code> is <code>[]</code>.</p>
-pal(Category,Format,Args) ->
- ct_logs:tc_pal(Category,Format,Args).
+%%% <p>Default <code>Category</code> is <code>default</code>,
+%%% default <code>Importance</code> is <code>?STD_IMPORTANCE</code>,
+%%% and default value for <code>Args</code> is <code>[]</code>.</p>
+%%% <p>Please see the User's Guide for details on <code>Category</code>
+%%% and <code>Importance</code>.</p>
+pal(Category,Importance,Format,Args) ->
+ ct_logs:tc_pal(Category,Importance,Format,Args).
+%%%-----------------------------------------------------------------
+%%% @spec capture_start() -> ok
+%%%
+%%% @doc Start capturing all text strings printed to stdout during
+%%% execution of the test case.
+%%%
+%%% @see capture_stop/0
+%%% @see capture_get/1
+capture_start() ->
+ test_server:capture_start().
+
+%%%-----------------------------------------------------------------
+%%% @spec capture_stop() -> ok
+%%%
+%%% @doc Stop capturing text strings (a session started with
+%%% <code>capture_start/0</code>).
+%%%
+%%% @see capture_start/0
+%%% @see capture_get/1
+capture_stop() ->
+ test_server:capture_stop().
+
+%%%-----------------------------------------------------------------
+%%% @spec capture_get() -> ListOfStrings
+%%% ListOfStrings = [string()]
+%%%
+%%% @equiv capture_get([default])
+capture_get() ->
+ %% remove default log printouts (e.g. ct:log/2 printouts)
+ capture_get([default]).
+
+%%%-----------------------------------------------------------------
+%%% @spec capture_get(ExclCategories) -> ListOfStrings
+%%% ExclCategories = [atom()]
+%%% ListOfStrings = [string()]
+%%%
+%%% @doc Return and purge the list of text strings buffered
+%%% during the latest session of capturing printouts to stdout.
+%%% With <code>ExclCategories</code> it's possible to specify
+%%% log categories that should be ignored in <code>ListOfStrings</code>.
+%%% If <code>ExclCategories = []</code>, no filtering takes place.
+%%%
+%%% @see capture_start/0
+%%% @see capture_stop/0
+%%% @see log/3
+capture_get([ExclCat | ExclCategories]) ->
+ Strs = test_server:capture_get(),
+ CatsStr = [atom_to_list(ExclCat) |
+ [[$| | atom_to_list(EC)] || EC <- ExclCategories]],
+ {ok,MP} = re:compile("<div class=\"(" ++ lists:flatten(CatsStr) ++ ")\">.*"),
+ lists:flatmap(fun(Str) ->
+ case re:run(Str, MP) of
+ {match,_} -> [];
+ nomatch -> [Str]
+ end
+ end, Strs);
+
+capture_get([]) ->
+ test_server:capture_get().
%%%-----------------------------------------------------------------
%%% @spec fail(Reason) -> void()
@@ -526,20 +676,53 @@ pal(Category,Format,Args) ->
%%% @doc Terminate a test case with the given error
%%% <code>Reason</code>.
fail(Reason) ->
- exit({test_case_failed,Reason}).
+ try
+ exit({test_case_failed,Reason})
+ catch
+ Class:R ->
+ case erlang:get_stacktrace() of
+ [{?MODULE,fail,1,_}|Stk] -> ok;
+ Stk -> ok
+ end,
+ erlang:raise(Class, R, Stk)
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec fail(Format, Args) -> void()
+%%% Format = string()
+%%% Args = list()
+%%%
+%%% @doc Terminate a test case with an error message specified
+%%% by a format string and a list of values (used as arguments to
+%%% <code>io_lib:format/2</code>).
+fail(Format, Args) ->
+ try io_lib:format(Format, Args) of
+ Str ->
+ try
+ exit({test_case_failed,lists:flatten(Str)})
+ catch
+ Class:R ->
+ case erlang:get_stacktrace() of
+ [{?MODULE,fail,2,_}|Stk] -> ok;
+ Stk -> ok
+ end,
+ erlang:raise(Class, R, Stk)
+ end
+ catch
+ _:BadArgs ->
+ exit({BadArgs,{?MODULE,fail,[Format,Args]}})
+ end.
%%%-----------------------------------------------------------------
%%% @spec comment(Comment) -> void()
%%% Comment = term()
%%%
-%%% @doc Print the given <code>Comment</code> in the comment field of
+%%% @doc Print the given <code>Comment</code> in the comment field in
%%% the table on the test suite result page.
%%%
%%% <p>If called several times, only the last comment is printed.
-%%% <code>comment/1</code> is also overwritten by the return value
-%%% <code>{comment,Comment}</code> or by the function
-%%% <code>fail/1</code> (which prints <code>Reason</code> as a
-%%% comment).</p>
+%%% The test case return value <code>{comment,Comment}</code>
+%%% overwrites the string set by this function.</p>
comment(Comment) when is_list(Comment) ->
Formatted =
case (catch io_lib:format("~s",[Comment])) of
@@ -553,11 +736,43 @@ comment(Comment) ->
Formatted = io_lib:format("~p",[Comment]),
send_html_comment(lists:flatten(Formatted)).
+%%%-----------------------------------------------------------------
+%%% @spec comment(Format, Args) -> void()
+%%% Format = string()
+%%% Args = list()
+%%%
+%%% @doc Print the formatted string in the comment field in
+%%% the table on the test suite result page.
+%%%
+%%% <p>The <code>Format</code> and <code>Args</code> arguments are
+%%% used in call to <code>io_lib:format/2</code> in order to create
+%%% the comment string. The behaviour of <code>comment/2</code> is
+%%% otherwise the same as the <code>comment/1</code> function (see
+%%% above for details).</p>
+comment(Format, Args) when is_list(Format), is_list(Args) ->
+ Formatted =
+ case (catch io_lib:format(Format, Args)) of
+ {'EXIT',Reason} -> % bad args
+ exit({Reason,{?MODULE,comment,[Format,Args]}});
+ String ->
+ lists:flatten(String)
+ end,
+ send_html_comment(Formatted).
+
send_html_comment(Comment) ->
Html = "<font color=\"green\">" ++ Comment ++ "</font>",
ct_util:set_testdata({comment,Html}),
test_server:comment(Html).
+%%%-----------------------------------------------------------------
+%%% @spec make_priv_dir() -> ok | {error,Reason}
+%%% Reason = term()
+%%% @doc If the test has been started with the create_priv_dir
+%%% option set to manual_per_tc, in order for the test case to use
+%%% the private directory, it must first create it by calling
+%%% this function.
+make_priv_dir() ->
+ test_server:make_priv_dir().
%%%-----------------------------------------------------------------
%%% @spec get_target_name(Handle) -> {ok,TargetName} | {error,Reason}
@@ -606,7 +821,7 @@ listenv(Telnet) ->
%%% Testcases = list()
%%% Reason = term()
%%%
-%%% @doc Returns all testcases in the specified suite.
+%%% @doc Returns all test cases in the specified suite.
testcases(TestDir, Suite) ->
case make_and_load(TestDir, Suite) of
E = {error,_} ->
@@ -664,7 +879,8 @@ userdata(TestDir, Suite) ->
get_userdata(Info, "suite/0")
end.
-get_userdata({'EXIT',{undef,_}}, Spec) ->
+get_userdata({'EXIT',{Undef,_}}, Spec) when Undef == undef;
+ Undef == function_clause ->
{error,list_to_atom(Spec ++ " is not defined")};
get_userdata({'EXIT',Reason}, Spec) ->
{error,{list_to_atom("error in " ++ Spec),Reason}};
@@ -680,16 +896,27 @@ get_userdata(_BadTerm, Spec) ->
{error,list_to_atom(Spec ++ " must return a list")}.
%%%-----------------------------------------------------------------
-%%% @spec userdata(TestDir, Suite, Case) -> TCUserData | {error,Reason}
+%%% @spec userdata(TestDir, Suite, GroupOrCase) -> TCUserData | {error,Reason}
%%% TestDir = string()
%%% Suite = atom()
-%%% Case = atom()
+%%% GroupOrCase = {group,GroupName} | atom()
+%%% GroupName = atom()
%%% TCUserData = [term()]
%%% Reason = term()
%%%
%%% @doc Returns any data specified with the tag <code>userdata</code>
-%%% in the list of tuples returned from <code>Suite:Case/0</code>.
-userdata(TestDir, Suite, Case) ->
+%%% in the list of tuples returned from <code>Suite:group(GroupName)</code>
+%%% or <code>Suite:Case()</code>.
+userdata(TestDir, Suite, {group,GroupName}) ->
+ case make_and_load(TestDir, Suite) of
+ E = {error,_} ->
+ E;
+ _ ->
+ Info = (catch apply(Suite, group, [GroupName])),
+ get_userdata(Info, "group("++atom_to_list(GroupName)++")")
+ end;
+
+userdata(TestDir, Suite, Case) when is_atom(Case) ->
case make_and_load(TestDir, Suite) of
E = {error,_} ->
E;
@@ -702,8 +929,9 @@ userdata(TestDir, Suite, Case) ->
%%%-----------------------------------------------------------------
%%% @spec get_status() -> TestStatus | {error,Reason} | no_tests_running
%%% TestStatus = [StatusElem]
-%%% StatusElem = {current,{Suite,TestCase}} | {successful,Successful} |
+%%% StatusElem = {current,TestCaseInfo} | {successful,Successful} |
%%% {failed,Failed} | {skipped,Skipped} | {total,Total}
+%%% TestCaseInfo = {Suite,TestCase} | [{Suite,TestCase}]
%%% Suite = atom()
%%% TestCase = atom()
%%% Successful = integer()
@@ -715,7 +943,8 @@ userdata(TestDir, Suite, Case) ->
%%% Reason = term()
%%%
%%% @doc Returns status of ongoing test. The returned list contains info about
-%%% which test case is currently executing, as well as counters for
+%%% which test case is currently executing (a list of cases when a
+%%% parallel test case group is executing), as well as counters for
%%% successful, failed, skipped, and total test cases so far.
get_status() ->
case get_testdata(curr_tc) of
@@ -734,10 +963,16 @@ get_status() ->
get_testdata(Key) ->
case catch ct_util:get_testdata(Key) of
+ {error,ct_util_server_not_running} ->
+ no_tests_running;
Error = {error,_Reason} ->
Error;
{'EXIT',_Reason} ->
no_tests_running;
+ undefined ->
+ {error,no_testdata};
+ [CurrTC] when Key == curr_tc ->
+ {ok,CurrTC};
Data ->
{ok,Data}
end.
@@ -855,18 +1090,38 @@ remove_config(Callback, Config) ->
%%%-----------------------------------------------------------------
%%% @spec timetrap(Time) -> ok
-%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity
+%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity | Func
%%% Hours = integer()
%%% Mins = integer()
%%% Secs = integer()
%%% Millisecs = integer() | float()
-%%%
-%%% @doc <p>Use this function to set a new timetrap for the running test case.</p>
+%%% Func = {M,F,A} | fun()
+%%% M = atom()
+%%% F = atom()
+%%% A = list()
+%%%
+%%% @doc <p>Use this function to set a new timetrap for the running test case.
+%%% If the argument is <code>Func</code>, the timetrap will be triggered
+%%% when this function returns. <code>Func</code> may also return a new
+%%% <code>Time</code> value, which in that case will be the value for the
+%%% new timetrap.</p>
timetrap(Time) ->
test_server:timetrap_cancel(),
test_server:timetrap(Time).
%%%-----------------------------------------------------------------
+%%% @spec get_timetrap_info() -> {Time,Scale}
+%%% Time = integer() | infinity
+%%% Scale = true | false
+%%%
+%%% @doc <p>Read info about the timetrap set for the current test case.
+%%% <c>Scale</c> indicates if Common Test will attempt to automatically
+%%% compensate timetraps for runtime delays introduced by e.g. tools like
+%%% cover.</p>
+get_timetrap_info() ->
+ test_server:get_timetrap_info().
+
+%%%-----------------------------------------------------------------
%%% @spec sleep(Time) -> ok
%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity
%%% Hours = integer()
@@ -887,3 +1142,122 @@ sleep({seconds,Ss}) ->
sleep(trunc(Ss * 1000));
sleep(Time) ->
test_server:adjusted_sleep(Time).
+
+%%%-----------------------------------------------------------------
+%%% @spec notify(Name,Data) -> ok
+%%% Name = atom()
+%%% Data = term()
+%%%
+%%% @doc <p>Sends a asynchronous notification of type <c>Name</c> with
+%%% <c>Data</c>to the common_test event manager. This can later be
+%%% caught by any installed event manager. </p>
+%%% @see //stdlib/gen_event
+notify(Name,Data) ->
+ ct_event:notify(Name, Data).
+
+%%%-----------------------------------------------------------------
+%%% @spec sync_notify(Name,Data) -> ok
+%%% Name = atom()
+%%% Data = term()
+%%%
+%%% @doc <p>Sends a synchronous notification of type <c>Name</c> with
+%%% <c>Data</c>to the common_test event manager. This can later be
+%%% caught by any installed event manager. </p>
+%%% @see //stdlib/gen_event
+sync_notify(Name,Data) ->
+ ct_event:sync_notify(Name, Data).
+
+%%%-----------------------------------------------------------------
+%%% @spec break(Comment) -> ok | {error,Reason}
+%%% Comment = string()
+%%% Reason = {multiple_cases_running,TestCases} |
+%%% 'enable break with release_shell option'
+%%% TestCases = [atom()]
+%%%
+%%% @doc <p>This function will cancel all timetraps and pause the
+%%% execution of the current test case until the user calls the
+%%% <c>continue/0</c> function. It gives the user the opportunity
+%%% to interact with the erlang node running the tests, e.g. for
+%%% debugging purposes or for manually executing a part of the
+%%% test case. If a parallel group is executing, <c>break/2</c>
+%%% should be called instead.</p>
+break(Comment) ->
+ case {ct_util:get_testdata(starter),
+ ct_util:get_testdata(release_shell)} of
+ {ct,ReleaseSh} when ReleaseSh /= true ->
+ Warning = "ct:break/1 can only be used if release_shell == true.\n",
+ ct_logs:log("Warning!", Warning, []),
+ io:format(user, "Warning! " ++ Warning, []),
+ {error,'enable break with release_shell option'};
+ _ ->
+ case get_testdata(curr_tc) of
+ {ok,{_,TestCase}} ->
+ test_server:break(?MODULE, Comment);
+ {ok,Cases} when is_list(Cases) ->
+ {error,{'multiple cases running',
+ [TC || {_,TC} <- Cases]}};
+ Error = {error,_} ->
+ Error;
+ Error ->
+ {error,Error}
+ end
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec break(TestCase, Comment) -> ok | {error,Reason}
+%%% TestCase = atom()
+%%% Comment = string()
+%%% Reason = 'test case not running' |
+%%% 'enable break with release_shell option'
+%%%
+%%% @doc <p>This function works the same way as <c>break/1</c>,
+%%% only the <c>TestCase</c> argument makes it possible to
+%%% pause a test case executing in a parallel group. The
+%%% <c>continue/1</c> function should be used to resume
+%%% execution of <c>TestCase</c>.</p>
+break(TestCase, Comment) ->
+ case {ct_util:get_testdata(starter),
+ ct_util:get_testdata(release_shell)} of
+ {ct,ReleaseSh} when ReleaseSh /= true ->
+ Warning = "ct:break/2 can only be used if release_shell == true.\n",
+ ct_logs:log("Warning!", Warning, []),
+ io:format(user, "Warning! " ++ Warning, []),
+ {error,'enable break with release_shell option'};
+ _ ->
+ case get_testdata(curr_tc) of
+ {ok,Cases} when is_list(Cases) ->
+ case lists:keymember(TestCase, 2, Cases) of
+ true ->
+ test_server:break(?MODULE, TestCase, Comment);
+ false ->
+ {error,'test case not running'}
+ end;
+ {ok,{_,TestCase}} ->
+ test_server:break(?MODULE, TestCase, Comment);
+ Error = {error,_} ->
+ Error;
+ Error ->
+ {error,Error}
+ end
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec continue() -> ok
+%%%
+%%% @doc <p>This function must be called in order to continue after a
+%%% test case (not executing in a parallel group) has called
+%%% <c>break/1</c>.</p>
+continue() ->
+ test_server:continue().
+
+%%%-----------------------------------------------------------------
+%%% @spec continue(TestCase) -> ok
+%%% TestCase = atom()
+%%%
+%%% @doc <p>This function must be called in order to continue after a
+%%% test case has called <c>break/2</c>. If the paused test case,
+%%% <c>TestCase</c>, executes in a parallel group, this
+%%% function - rather than <c>continue/0</c> - must be used
+%%% in order to let the test case proceed.</p>
+continue(TestCase) ->
+ test_server:continue(TestCase).
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index fc51aea7f3..463b7d180c 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.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
@@ -122,8 +122,8 @@ return({To,Ref},Result) ->
loop(StartDir) ->
receive
- {{require,Name,Tag,SubTags},From} ->
- Result = do_require(Name,Tag,SubTags),
+ {{require,Name,Key},From} ->
+ Result = do_require(Name,Key),
return(From,Result),
loop(StartDir);
{{set_default_config,{Config,Scope}},From} ->
@@ -168,16 +168,19 @@ reload_config(KeyOrName) ->
call({reload_config, KeyOrName}).
process_default_configs(Opts) ->
- case lists:keysearch(config, 1, Opts) of
- {value,{_,Files=[File|_]}} when is_list(File) ->
- Files;
- {value,{_,File=[C|_]}} when is_integer(C) ->
- [File];
- {value,{_,[]}} ->
- [];
- false ->
- []
- end.
+ lists:flatmap(fun({config,[_|_] = FileOrFiles}) ->
+ case {io_lib:printable_list(FileOrFiles),
+ io_lib:printable_list(hd(FileOrFiles))} of
+ {true,true} ->
+ FileOrFiles;
+ {true,false} ->
+ [FileOrFiles];
+ _ ->
+ []
+ end;
+ (_) ->
+ []
+ end,Opts).
process_user_configs(Opts, Acc) ->
case lists:keytake(userconfig, 1, Opts) of
@@ -319,75 +322,58 @@ get_config(KeyOrName,Default) ->
get_config(KeyOrName,Default,[]).
get_config(KeyOrName,Default,Opts) when is_atom(KeyOrName) ->
- case lookup_config(KeyOrName) of
- [] ->
- Default;
- [{_Ref,Val}|_] = Vals ->
- case {lists:member(all,Opts),lists:member(element,Opts)} of
- {true,true} ->
- [{KeyOrName,V} || {_R,V} <- lists:sort(Vals)];
- {true,false} ->
- [V || {_R,V} <- lists:sort(Vals)];
- {false,true} ->
- {KeyOrName,Val};
- {false,false} ->
- Val
- end
+ case get_config({KeyOrName}, Default, Opts) of
+ %% If only an atom is given, then we need to unwrap the
+ %% key if it is returned
+ {{KeyOrName}, Val} ->
+ {KeyOrName, Val};
+ [{{KeyOrName}, _Val}|_] = Res ->
+ [{K, Val} || {{K},Val} <- Res, K == KeyOrName];
+ Else ->
+ Else
end;
-get_config({KeyOrName,SubKey},Default,Opts) ->
- case lookup_config(KeyOrName) of
+%% This useage of get_config is only used by internal ct functions
+%% and may change at any time
+get_config({DeepKey,SubKey}, Default, Opts) when is_tuple(DeepKey) ->
+ get_config(erlang:append_element(DeepKey, SubKey), Default, Opts);
+get_config(KeyOrName,Default,Opts) when is_tuple(KeyOrName) ->
+ case lookup_config(element(1,KeyOrName)) of
[] ->
- Default;
+ format_value([Default],KeyOrName,Opts);
Vals ->
- Vals1 = case [Val || {_Ref,Val} <- lists:sort(Vals)] of
- Result=[L|_] when is_list(L) ->
- case L of
- [{_,_}|_] ->
- Result;
- _ ->
- []
- end;
- _ ->
- []
- end,
- case get_subconfig([SubKey],Vals1,[],Opts) of
- {ok,[{_,SubVal}|_]=SubVals} ->
- case {lists:member(all,Opts),lists:member(element,Opts)} of
- {true,true} ->
- [{{KeyOrName,SubKey},Val} || {_,Val} <- SubVals];
- {true,false} ->
- [Val || {_SubKey,Val} <- SubVals];
- {false,true} ->
- {{KeyOrName,SubKey},SubVal};
- {false,false} ->
- SubVal
- end;
- _ ->
- Default
- end
+ NewVals =
+ lists:map(
+ fun({Val}) ->
+ get_config(tl(tuple_to_list(KeyOrName)),
+ Val,Default,Opts)
+ end,Vals),
+ format_value(NewVals,KeyOrName,Opts)
end.
-get_subconfig(SubKeys,Values) ->
- get_subconfig(SubKeys,Values,[],[]).
-
-get_subconfig(SubKeys,[Value|Rest],Mapped,Opts) ->
- case do_get_config(SubKeys,Value,[]) of
- {ok,SubMapped} ->
- case lists:member(all,Opts) of
- true ->
- get_subconfig(SubKeys,Rest,Mapped++SubMapped,Opts);
- false ->
- {ok,SubMapped}
- end;
- _Error ->
- get_subconfig(SubKeys,Rest,Mapped,Opts)
+get_config([],Vals,_Default,_Opts) ->
+ Vals;
+get_config([[]],Vals,Default,Opts) ->
+ get_config([],Vals,Default,Opts);
+%% This case is used by {require,{unix,[port,host]}} functionality
+get_config([SubKeys], Vals, Default, _Opts) when is_list(SubKeys) ->
+ case do_get_config(SubKeys, Vals, []) of
+ {ok, SubVals} ->
+ [SubVal || {_,SubVal} <- SubVals];
+
+ _ ->
+ Default
end;
-get_subconfig(SubKeys,[],[],_) ->
- {error,{not_available,SubKeys}};
-get_subconfig(_SubKeys,[],Mapped,_) ->
- {ok,Mapped}.
+get_config([Key|Rest], Vals, Default, Opts) ->
+ case do_get_config([Key], Vals, []) of
+ {ok, [{Key,NewVals}]} ->
+ get_config(Rest, NewVals, Default, Opts);
+ _ ->
+ Default
+ end.
+do_get_config([Key|_], Available, _Mapped) when not is_list(Available) ->
+ {error,{not_available,Key}};
do_get_config([Key|Required],Available,Mapped) ->
case lists:keysearch(Key,1,Available) of
{value,{Key,Value}} ->
@@ -403,8 +389,7 @@ do_get_config([],_Available,Mapped) ->
get_all_config() ->
ets:select(?attr_table,[{#ct_conf{name='$1',key='$2',value='$3',
default='$4',_='_'},
- [],
- [{{'$1','$2','$3','$4'}}]}]).
+ [],[{{'$1','$2','$3','$4'}}]}]).
lookup_config(KeyOrName) ->
case lookup_name(KeyOrName) of
@@ -415,13 +400,23 @@ lookup_config(KeyOrName) ->
end.
lookup_name(Name) ->
- ets:select(?attr_table,[{#ct_conf{ref='$1',value='$2',name=Name,_='_'},
- [],
- [{{'$1','$2'}}]}]).
+ ets:select(?attr_table,[{#ct_conf{value='$1',name=Name,_='_'},
+ [],[{{'$1'}}]}]).
lookup_key(Key) ->
- ets:select(?attr_table,[{#ct_conf{key=Key,ref='$1',value='$2',name='_UNDEF',_='_'},
- [],
- [{{'$1','$2'}}]}]).
+ ets:select(?attr_table,[{#ct_conf{key=Key,value='$1',name='_UNDEF',_='_'},
+ [],[{{'$1'}}]}]).
+
+format_value([SubVal|_] = SubVals, KeyOrName, Opts) ->
+ case {lists:member(all,Opts),lists:member(element,Opts)} of
+ {true,true} ->
+ [{KeyOrName,Val} || Val <- SubVals];
+ {true,false} ->
+ [Val || Val <- SubVals];
+ {false,true} ->
+ {KeyOrName,SubVal};
+ {false,false} ->
+ SubVal
+ end.
lookup_handler_for_config({Key, _Subkey}) ->
lookup_handler_for_config(Key);
@@ -475,65 +470,78 @@ release_allocated([H|T]) ->
release_allocated([]) ->
ok.
-allocate(Name,Key,SubKeys) ->
- case ets:match_object(?attr_table,#ct_conf{key=Key,name='_UNDEF',_='_'}) of
- [] ->
+allocate(Name,Key) ->
+ Ref = make_ref(),
+ case get_config(Key,Ref,[all,element]) of
+ [{_,Ref}] ->
{error,{not_available,Key}};
- Available ->
- case allocate_subconfig(Name,SubKeys,Available,false) of
- ok ->
- ok;
- Error ->
- Error
- end
+ Configs ->
+ associate(Name,Key,Configs),
+ ok
end.
-allocate_subconfig(Name,SubKeys,[C=#ct_conf{value=Value}|Rest],Found) ->
- case do_get_config(SubKeys,Value,[]) of
- {ok,_SubMapped} ->
- ets:insert(?attr_table,C#ct_conf{name=Name}),
- allocate_subconfig(Name,SubKeys,Rest,true);
- _Error ->
- allocate_subconfig(Name,SubKeys,Rest,Found)
- end;
-allocate_subconfig(_Name,_SubKeys,[],true) ->
+
+associate('_UNDEF',_Key,_Configs) ->
ok;
-allocate_subconfig(_Name,SubKeys,[],false) ->
- {error,{not_available,SubKeys}}.
+associate(Name,{Key,SubKeys},Configs) when is_atom(Key), is_list(SubKeys) ->
+ associate_int(Name,Configs,"true");
+associate(Name,_Key,Configs) ->
+ associate_int(Name,Configs,os:getenv("COMMON_TEST_ALIAS_TOP")).
+
+associate_int(Name,Configs,"true") ->
+ lists:map(fun({K,_Config}) ->
+ Cs = ets:match_object(
+ ?attr_table,
+ #ct_conf{key=element(1,K),
+ name='_UNDEF',_='_'}),
+ [ets:insert(?attr_table,C#ct_conf{name=Name})
+ || C <- Cs]
+ end,Configs);
+associate_int(Name,Configs,_) ->
+ lists:map(fun({K,Config}) ->
+ Key = if is_tuple(K) -> element(1,K);
+ is_atom(K) -> K
+ end,
+
+ Cs = ets:match_object(
+ ?attr_table,
+ #ct_conf{key=Key,
+ name='_UNDEF',_='_'}),
+ [ets:insert(?attr_table,C#ct_conf{name=Name,
+ value=Config})
+ || C <- Cs]
+ end,Configs).
+
+
delete_config(Default) ->
ets:match_delete(?attr_table,#ct_conf{default=Default,_='_'}),
ok.
-require(Key) when is_atom(Key) ->
- require({Key,[]});
-require({Key,SubKeys}) when is_atom(Key) ->
- allocate('_UNDEF',Key,to_list(SubKeys));
+require(Key) when is_atom(Key); is_tuple(Key) ->
+ allocate('_UNDEF',Key);
require(Key) ->
{error,{invalid,Key}}.
-require(Name,Key) when is_atom(Key) ->
- require(Name,{Key,[]});
-require(Name,{Key,SubKeys}) when is_atom(Name), is_atom(Key) ->
- call({require,Name,Key,to_list(SubKeys)});
+require(Name,Key) when is_atom(Name),is_atom(Key) orelse is_tuple(Key) ->
+ call({require,Name,Key});
require(Name,Keys) ->
{error,{invalid,{Name,Keys}}}.
-to_list(X) when is_list(X) -> X;
-to_list(X) -> [X].
-
-do_require(Name,Key,SubKeys) when is_list(SubKeys) ->
+do_require(Name,Key) ->
case get_key_from_name(Name) of
{error,_} ->
- allocate(Name,Key,SubKeys);
+ allocate(Name,Key);
{ok,Key} ->
%% already allocated - check that it has all required subkeys
- Vals = [Val || {_Ref,Val} <- lookup_name(Name)],
- case get_subconfig(SubKeys,Vals) of
- {ok,_SubMapped} ->
- ok;
- Error ->
- Error
+ R = make_ref(),
+ case get_config(Key,R,[]) of
+ R ->
+ {error,{not_available,Key}};
+ {error,_} = Error ->
+ Error;
+ _Error ->
+ ok
end;
{ok,OtherKey} ->
{error,{name_in_use,Name,OtherKey}}
@@ -760,13 +768,13 @@ check_config_files(Configs) ->
end,
lists:keysearch(error, 1, lists:flatten(lists:map(ConfigChecker, Configs))).
-prepare_user_configs([ConfigString|UserConfigs], Acc, new) ->
+prepare_user_configs([CallbackMod|UserConfigs], Acc, new) ->
prepare_user_configs(UserConfigs,
- [{list_to_atom(ConfigString), []}|Acc],
+ [{list_to_atom(CallbackMod),[]}|Acc],
cur);
prepare_user_configs(["and"|UserConfigs], Acc, _) ->
prepare_user_configs(UserConfigs, Acc, new);
-prepare_user_configs([ConfigString|UserConfigs], [{LastMod, LastList}|Acc], cur) ->
+prepare_user_configs([ConfigString|UserConfigs], [{LastMod,LastList}|Acc], cur) ->
prepare_user_configs(UserConfigs,
[{LastMod, [ConfigString|LastList]}|Acc],
cur);
diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl
index 6698332379..237df5c8f3 100644
--- a/lib/common_test/src/ct_config_plain.erl
+++ b/lib/common_test/src/ct_config_plain.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
diff --git a/lib/common_test/src/ct_config_xml.erl b/lib/common_test/src/ct_config_xml.erl
index 794174e663..6e0a016161 100644
--- a/lib/common_test/src/ct_config_xml.erl
+++ b/lib/common_test/src/ct_config_xml.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
diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl
new file mode 100644
index 0000000000..bf27238121
--- /dev/null
+++ b/lib/common_test/src/ct_conn_log_h.erl
@@ -0,0 +1,230 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_conn_log_h).
+
+%%%
+%%% A handler that can be connected to the error_logger event
+%%% handler. Writes all ct connection events. See comments in
+%%% cth_conn_log for more information.
+%%%
+
+-include("ct_util.hrl").
+
+-export([init/1,
+ handle_event/2, handle_call/2, handle_info/2,
+ terminate/2]).
+
+-record(state, {group_leader,logs=[]}).
+
+-define(WIDTH,80).
+
+%%%-----------------------------------------------------------------
+%%% Callbacks
+init({GL,Logs}) ->
+ open_files(Logs,#state{group_leader=GL}).
+
+open_files([{ConnMod,{LogType,Logs}}|T],State) ->
+ case do_open_files(Logs,[]) of
+ {ok,Fds} ->
+ open_files(T,State#state{logs=[{ConnMod,{LogType,Fds}} |
+ State#state.logs]});
+ Error ->
+ Error
+ end;
+open_files([],State) ->
+ {ok,State}.
+
+
+do_open_files([{Tag,File}|Logs],Acc) ->
+ case file:open(File, [write]) of
+ {ok,Fd} ->
+ do_open_files(Logs,[{Tag,Fd}|Acc]);
+ {error,Reason} ->
+ {error,{could_not_open_log,File,Reason}}
+ end;
+do_open_files([],Acc) ->
+ {ok,lists:reverse(Acc)}.
+
+handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() ->
+ {ok, State};
+handle_event({_Type,_GL,{Pid,{ct_connection,Action,ConnName},Report}},State) ->
+ Info = conn_info(Pid,#conn_log{name=ConnName,action=Action}),
+ write_report(now(),Info,Report,State),
+ {ok, State};
+handle_event({_Type,_GL,{Pid,Info=#conn_log{},Report}},State) ->
+ write_report(now(),conn_info(Pid,Info),Report,State),
+ {ok, State};
+handle_event({error_report,_,{Pid,_,[{ct_connection,ConnName}|R]}},State) ->
+ %% Error reports from connection
+ write_error(now(),conn_info(Pid,#conn_log{name=ConnName}),R,State),
+ {ok, State};
+handle_event(_, State) ->
+ {ok, State}.
+
+handle_info(_, State) ->
+ {ok, State}.
+
+handle_call(_Query, State) ->
+ {ok, {error, bad_query}, State}.
+
+terminate(_,#state{logs=Logs}) ->
+ [file:close(Fd) || {_,{_,Fds}} <- Logs, {_,Fd} <- Fds],
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% Writing reports
+write_report(Time,#conn_log{module=ConnMod}=Info,Data,State) ->
+ {LogType,Fd} = get_log(Info,State),
+ io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time),
+ format_title(LogType,Info),
+ format_data(ConnMod,LogType,Data)]).
+
+write_error(Time,#conn_log{module=ConnMod}=Info,Report,State) ->
+ case get_log(Info,State) of
+ {html,_} ->
+ %% The error will anyway be written in the html log by the
+ %% sasl error handler, so don't write it again.
+ ok;
+ {LogType,Fd} ->
+ io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time," ERROR"),
+ format_title(LogType,Info),
+ format_error(LogType,Report)])
+ end.
+
+get_log(Info,State) ->
+ case proplists:get_value(Info#conn_log.module,State#state.logs) of
+ {html,_} ->
+ {html,State#state.group_leader};
+ {LogType,Fds} ->
+ {LogType,get_fd(Info,Fds)};
+ undefined ->
+ {html,State#state.group_leader}
+ end.
+
+get_fd(#conn_log{name=undefined},Fds) ->
+ proplists:get_value(default,Fds);
+get_fd(#conn_log{name=ConnName},Fds) ->
+ case proplists:get_value(ConnName,Fds) of
+ undefined ->
+ proplists:get_value(default,Fds);
+ Fd ->
+ Fd
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Formatting
+format_head(ConnMod,LogType,Time) ->
+ format_head(ConnMod,LogType,Time,"").
+
+format_head(ConnMod,raw,Time,Text) ->
+ io_lib:format("~n~p, ~p~s, ",[now_to_time(Time),ConnMod,Text]);
+format_head(ConnMod,_,Time,Text) ->
+ Head = pad_char_end(?WIDTH,pretty_head(now_to_time(Time),ConnMod,Text),$=),
+ io_lib:format("~n~s",[Head]).
+
+format_title(raw,#conn_log{client=Client}=Info) ->
+ io_lib:format("Client ~p ~s ~s",[Client,actionstr(Info),serverstr(Info)]);
+format_title(_,Info) ->
+ Title = pad_char_end(?WIDTH,pretty_title(Info),$=),
+ io_lib:format("~n~s", [Title]).
+
+format_data(_,_,NoData) when NoData == ""; NoData == <<>> ->
+ "";
+format_data(ConnMod,LogType,Data) ->
+ ConnMod:format_data(LogType,Data).
+
+format_error(raw,Report) ->
+ io_lib:format("~n~p~n",[Report]);
+format_error(pretty,Report) ->
+ [io_lib:format("~n ~p: ~p",[K,V]) || {K,V} <- Report].
+
+
+
+
+%%%-----------------------------------------------------------------
+%%% Helpers
+conn_info(LoggingProc, #conn_log{client=undefined} = ConnInfo) ->
+ conn_info(ConnInfo#conn_log{client=LoggingProc});
+conn_info(_, ConnInfo) ->
+ conn_info(ConnInfo).
+
+conn_info(#conn_log{client=Client, module=undefined} = ConnInfo) ->
+ case ets:lookup(ct_connections,Client) of
+ [#conn{address=Address,callback=Callback}] ->
+ ConnInfo#conn_log{address=Address,module=Callback};
+ [] ->
+ ConnInfo
+ end;
+conn_info(ConnInfo) ->
+ ConnInfo.
+
+
+now_to_time({_,_,MicroS}=Now) ->
+ {calendar:now_to_local_time(Now),MicroS}.
+
+pretty_head({{{Y,Mo,D},{H,Mi,S}},MicroS},ConnMod,Text0) ->
+ Text = string:to_upper(atom_to_list(ConnMod) ++ Text0),
+ io_lib:format("= ~s ==== ~s-~s-~p::~s:~s:~s,~s ",
+ [Text,t(D),month(Mo),Y,t(H),t(Mi),t(S),
+ micro2milli(MicroS)]).
+
+pretty_title(#conn_log{client=Client}=Info) ->
+ io_lib:format("= Client ~p ~s Server ~s ",
+ [Client,actionstr(Info),serverstr(Info)]).
+
+actionstr(#conn_log{action=send}) -> "----->";
+actionstr(#conn_log{action=recv}) -> "<-----";
+actionstr(#conn_log{action=open}) -> "opened session to";
+actionstr(#conn_log{action=close}) -> "closed session to";
+actionstr(_) -> "<---->".
+
+serverstr(#conn_log{name=undefined,address=Address}) ->
+ io_lib:format("~p",[Address]);
+serverstr(#conn_log{name=Alias,address=Address}) ->
+ io_lib:format("~p(~p)",[Alias,Address]).
+
+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".
+
+micro2milli(X) ->
+ pad0(3,integer_to_list(X div 1000)).
+
+t(X) ->
+ pad0(2,integer_to_list(X)).
+
+pad0(N,Str) ->
+ M = length(Str),
+ lists:duplicate(N-M,$0) ++ Str.
+
+pad_char_end(N,Str,Char) ->
+ case length(lists:flatten(Str)) of
+ M when M<N -> Str ++ lists:duplicate(N-M,Char);
+ _ -> Str
+ end.
diff --git a/lib/common_test/src/ct_event.erl b/lib/common_test/src/ct_event.erl
index 3e79898ad1..998be35fda 100644
--- a/lib/common_test/src/ct_event.erl
+++ b/lib/common_test/src/ct_event.erl
@@ -31,7 +31,7 @@
%% API
-export([start_link/0, add_handler/0, add_handler/1, stop/0]).
--export([notify/1, sync_notify/1]).
+-export([notify/1, notify/2, sync_notify/1,sync_notify/2]).
-export([is_alive/0]).
%% gen_event callbacks
@@ -90,6 +90,13 @@ notify(Event) ->
end.
%%--------------------------------------------------------------------
+%% Function: notify(Name,Data) -> ok
+%% Description: Asynchronous notification to event manager.
+%%--------------------------------------------------------------------
+notify(Name, Data) ->
+ notify(#event{ name = Name, data = Data}).
+
+%%--------------------------------------------------------------------
%% Function: sync_notify(Event) -> ok
%% Description: Synchronous notification to event manager.
%%--------------------------------------------------------------------
@@ -102,6 +109,13 @@ sync_notify(Event) ->
end.
%%--------------------------------------------------------------------
+%% Function: sync_notify(Name,Data) -> ok
+%% Description: Synchronous notification to event manager.
+%%--------------------------------------------------------------------
+sync_notify(Name,Data) ->
+ sync_notify(#event{ name = Name, data = Data}).
+
+%%--------------------------------------------------------------------
%% Function: is_alive() -> true | false
%% Description: Check if Event Manager is alive.
%%--------------------------------------------------------------------
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 482c5242ce..4d47731239 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,15 +27,20 @@
-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([get_logopts/0, format_comment/1, overview_html_header/1]).
+-export([get_logopts/0, format_comment/1, get_html_wrapper/4]).
--export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]).
+-export([error_in_suite/1, init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2]).
-export([make_all_conf/3, make_conf/5]).
-include("ct_event.hrl").
-include("ct_util.hrl").
+-define(val(Key, List), proplists:get_value(Key, List)).
+-define(val(Key, List, Def), proplists:get_value(Key, List, Def)).
+-define(rev(L), lists:reverse(L)).
+
%%%-----------------------------------------------------------------
%%% @spec init_tc(Mod,Func,Args) -> {ok,NewArgs} | {error,Reason} |
%%% {skip,Reason} | {auto_skip,Reason}
@@ -48,6 +53,9 @@
%%% @doc Test server framework callback, called by the test_server
%%% when a new test case is started.
init_tc(Mod,Func,Config) ->
+ %% in case Mod == ct_framework, lookup the suite name
+ Suite = get_suite_name(Mod, Config),
+
%% check if previous testcase was interpreted and has left
%% a "dead" trace window behind - if so, kill it
case ct_util:get_testdata(interpret) of
@@ -57,55 +65,63 @@ init_tc(Mod,Func,Config) ->
_ ->
ok
end,
-
- %% check if we need to add defaults explicitly because
- %% there's no init_per_suite exported from Mod
- {InitFailed,DoInit} =
- case ct_util:get_testdata(curr_tc) of
- {Mod,{suite0_failed,_}=Failure} ->
- {Failure,false};
- {Mod,_} ->
- {false,false};
- _ when Func == init_per_suite ->
- {false,false};
- _ ->
- {false,true}
- end,
- case InitFailed of
- false ->
- ct_util:set_testdata({curr_tc,{Mod,Func}}),
- case ct_util:read_suite_data({seq,Mod,Func}) of
+
+ case ct_util:get_testdata(curr_tc) of
+ {Suite,{suite0_failed,{require,Reason}}} ->
+ {skip,{require_failed_in_suite0,Reason}};
+ {Suite,{suite0_failed,_}=Failure} ->
+ {skip,Failure};
+ _ ->
+ ct_util:update_testdata(curr_tc,
+ fun(undefined) ->
+ [{Suite,Func}];
+ (Running) ->
+ [{Suite,Func}|Running]
+ end, [create]),
+ case ct_util:read_suite_data({seq,Suite,Func}) of
undefined ->
- init_tc1(Mod,Func,Config,DoInit);
+ init_tc1(Mod,Suite,Func,Config);
Seq when is_atom(Seq) ->
- case ct_util:read_suite_data({seq,Mod,Seq}) of
+ case ct_util:read_suite_data({seq,Suite,Seq}) of
[Func|TCs] -> % this is the 1st case in Seq
- %% make sure no cases in this seq are marked as failed
- %% from an earlier execution in the same suite
- lists:foreach(fun(TC) ->
- ct_util:save_suite_data({seq,Mod,TC},Seq)
- end, TCs);
+ %% make sure no cases in this seq are
+ %% marked as failed from an earlier execution
+ %% in the same suite
+ lists:foreach(
+ fun(TC) ->
+ ct_util:save_suite_data({seq,Suite,TC},
+ Seq)
+ end, TCs);
_ ->
ok
end,
- init_tc1(Mod,Func,Config,DoInit);
+ init_tc1(Mod,Suite,Func,Config);
{failed,Seq,BadFunc} ->
{skip,{sequence_failed,Seq,BadFunc}}
- end;
- {_,{require,Reason}} ->
- {skip,{require_failed_in_suite0,Reason}};
- _ ->
- {skip,InitFailed}
+ end
end.
-init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
+init_tc1(?MODULE,_,error_in_suite,[Config0]) when is_list(Config0) ->
+ ct_logs:init_tc(false),
+ ct_event:notify(#event{name=tc_start,
+ node=node(),
+ data={?MODULE,error_in_suite}}),
+ case ?val(error, Config0) of
+ undefined ->
+ {skip,"unknown_error_in_suite"};
+ Reason ->
+ {skip,Reason}
+ end;
+
+init_tc1(Mod,Suite,Func,[Config0]) when is_list(Config0) ->
Config1 =
case ct_util:read_suite_data(last_saved_config) of
- {{Mod,LastFunc},SavedConfig} -> % last testcase
+ {{Suite,LastFunc},SavedConfig} -> % last testcase
[{saved_config,{LastFunc,SavedConfig}} |
lists:keydelete(saved_config,1,Config0)];
- {{LastSuite,InitOrEnd},SavedConfig} when InitOrEnd == init_per_suite ;
- InitOrEnd == end_per_suite ->
+ {{LastSuite,InitOrEnd},
+ SavedConfig} when InitOrEnd == init_per_suite ;
+ InitOrEnd == end_per_suite ->
%% last suite
[{saved_config,{LastSuite,SavedConfig}} |
lists:keydelete(saved_config,1,Config0)];
@@ -114,63 +130,57 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
end,
ct_util:delete_suite_data(last_saved_config),
Config = lists:keydelete(watchdog,1,Config1),
- if Func /= init_per_suite, DoInit /= true ->
- ok;
- true ->
+
+ if Func == init_per_suite ->
%% delete all default values used in previous suite
ct_config:delete_default_config(suite),
%% release all name -> key bindings (once per suite)
- ct_config:release_allocated()
+ ct_config:release_allocated();
+ Func /= init_per_suite ->
+ ok
end,
- TestCaseInfo =
- case catch apply(Mod,Func,[]) of
- Result when is_list(Result) -> Result;
- _ -> []
- end,
+
+ GroupPath = ?val(tc_group_path, Config, []),
+ AllGroups = [?val(tc_group_properties, Config, []) | GroupPath],
+
%% clear all config data default values set by previous
%% testcase info function (these should only survive the
%% testcase, not the whole suite)
- ct_config:delete_default_config(testcase),
- case add_defaults(Mod,Func,TestCaseInfo,DoInit) of
+ FuncSpec = group_or_func(Func,Config0),
+ if is_tuple(FuncSpec) -> % group
+ ok;
+ true ->
+ ct_config:delete_default_config(testcase)
+ end,
+ case add_defaults(Mod,Func,AllGroups) of
Error = {suite0_failed,_} ->
ct_logs:init_tc(false),
- FuncSpec = group_or_func(Func,Config0),
ct_event:notify(#event{name=tc_start,
node=node(),
data={Mod,FuncSpec}}),
- ct_util:set_testdata({curr_tc,{Mod,Error}}),
+ ct_util:set_testdata({curr_tc,{Suite,Error}}),
{error,Error};
{SuiteInfo,MergeResult} ->
case MergeResult of
- {error,Reason} when DoInit == false ->
+ {error,Reason} ->
ct_logs:init_tc(false),
- FuncSpec = group_or_func(Func,Config0),
ct_event:notify(#event{name=tc_start,
node=node(),
data={Mod,FuncSpec}}),
{skip,Reason};
_ ->
- init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit)
+ init_tc2(Mod,Suite,Func,SuiteInfo,MergeResult,Config)
end
end;
-init_tc1(_Mod,_Func,Args,_DoInit) ->
- {ok,Args}.
-init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) ->
- %% if first testcase fails when there's no init_per_suite
- %% we must do suite/0 configurations before skipping test
- MergedInfo =
- case MergeResult of
- {error,_} when DoInit == true ->
- SuiteInfo;
- _ ->
- MergeResult
- end,
+init_tc1(_Mod,_Suite,_Func,Args) ->
+ {ok,Args}.
+init_tc2(Mod,Suite,Func,SuiteInfo,MergeResult,Config) ->
%% timetrap must be handled before require
- MergedInfo1 = timetrap_first(MergedInfo, [], []),
+ MergedInfo = timetrap_first(MergeResult, [], []),
%% tell logger to use specified style sheet
- case lists:keysearch(stylesheet,1,MergedInfo++Config) of
+ case lists:keysearch(stylesheet,1,MergeResult++Config) of
{value,{stylesheet,SSFile}} ->
ct_logs:set_stylesheet(Func,add_data_dir(SSFile,Config));
_ ->
@@ -185,7 +195,7 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) ->
%% list of {Type,Bool} tuples, e.g. {telnet,true}),
case ct_util:get_overridden_silenced_connections() of
undefined ->
- case lists:keysearch(silent_connections,1,MergedInfo++Config) of
+ case lists:keysearch(silent_connections,1,MergeResult++Config) of
{value,{silent_connections,Conns}} ->
ct_util:silence_connections(Conns);
_ ->
@@ -194,66 +204,74 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) ->
Conns ->
ct_util:silence_connections(Conns)
end,
- if Func /= init_per_suite, DoInit /= true ->
- ct_logs:init_tc(false);
- true ->
- ct_logs:init_tc(true)
- end,
+ ct_logs:init_tc(Func == init_per_suite),
FuncSpec = group_or_func(Func,Config),
ct_event:notify(#event{name=tc_start,
node=node(),
data={Mod,FuncSpec}}),
-
- case catch configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of
+
+ case catch configure(MergedInfo,MergedInfo,SuiteInfo,
+ FuncSpec,[],Config) of
{suite0_failed,Reason} ->
- ct_util:set_testdata({curr_tc,{Mod,{suite0_failed,{require,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} ->
- %% suite0 configure finished now, report that
- %% first test case actually failed
- {skip,Reason};
- _ ->
- case get('$test_server_framework_test') of
- undefined ->
- ct_suite_init(Mod, FuncSpec, FinalConfig);
- Fun ->
- case Fun(init_tc, FinalConfig) of
- NewConfig when is_list(NewConfig) ->
- {ok,NewConfig};
- Else ->
- Else
- end
+ {ok,PostInitHook,Config1} ->
+ case get('$test_server_framework_test') of
+ undefined ->
+ ct_suite_init(Suite, FuncSpec, PostInitHook, Config1);
+ Fun ->
+ PostInitHookResult = do_post_init_hook(PostInitHook,
+ Config1),
+ case Fun(init_tc, [PostInitHookResult ++ Config1]) of
+ NewConfig when is_list(NewConfig) ->
+ {ok,NewConfig};
+ Else ->
+ Else
end
end
end.
-ct_suite_init(Mod, Func, [Config]) when is_list(Config) ->
- case ct_hooks:init_tc( Mod, Func, Config) of
+ct_suite_init(Suite, Func, PostInitHook, Config) when is_list(Config) ->
+ case ct_hooks:init_tc(Suite, Func, Config) of
NewConfig when is_list(NewConfig) ->
- {ok, [NewConfig]};
+ PostInitHookResult = do_post_init_hook(PostInitHook, NewConfig),
+ {ok, [PostInitHookResult ++ NewConfig]};
Else ->
Else
end.
-add_defaults(Mod,Func,FuncInfo,DoInit) ->
- case (catch Mod:suite()) of
+do_post_init_hook(PostInitHook, Config) ->
+ lists:flatmap(fun({Tag,Fun}) ->
+ case lists:keysearch(Tag,1,Config) of
+ {value,_} ->
+ [];
+ false ->
+ case Fun() of
+ {error,_} -> [];
+ Result -> [{Tag,Result}]
+ end
+ end
+ end, PostInitHook).
+
+add_defaults(Mod,Func, GroupPath) ->
+ Suite = get_suite_name(Mod, GroupPath),
+ case (catch Suite:suite()) of
{'EXIT',{undef,_}} ->
- SuiteInfo = merge_with_suite_defaults(Mod,[]),
+ SuiteInfo = merge_with_suite_defaults(Suite,[]),
SuiteInfoNoCTH = [I || I <- SuiteInfo, element(1,I) =/= ct_hooks],
- case add_defaults1(Mod,Func,FuncInfo,SuiteInfoNoCTH,DoInit) of
+ case add_defaults1(Mod,Func, GroupPath, SuiteInfoNoCTH) of
Error = {error,_} -> {SuiteInfo,Error};
MergedInfo -> {SuiteInfo,MergedInfo}
end;
{'EXIT',Reason} ->
ErrStr = io_lib:format("~n*** ERROR *** "
"~w:suite/0 failed: ~p~n",
- [Mod,Reason]),
+ [Suite,Reason]),
io:format(ErrStr, []),
io:format(user, ErrStr, []),
{suite0_failed,{exited,Reason}};
@@ -262,18 +280,18 @@ add_defaults(Mod,Func,FuncInfo,DoInit) ->
(_) -> false
end, SuiteInfo) of
true ->
- SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfo),
+ SuiteInfo1 = merge_with_suite_defaults(Suite, SuiteInfo),
SuiteInfoNoCTH = [I || I <- SuiteInfo1,
element(1,I) =/= ct_hooks],
- case add_defaults1(Mod,Func,FuncInfo,
- SuiteInfoNoCTH,DoInit) of
+ case add_defaults1(Mod,Func, GroupPath,
+ SuiteInfoNoCTH) 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]),
+ "~w:suite/0: ~p~n", [Suite,SuiteInfo]),
io:format(ErrStr, []),
io:format(user, ErrStr, []),
{suite0_failed,bad_return_value}
@@ -281,57 +299,157 @@ add_defaults(Mod,Func,FuncInfo,DoInit) ->
SuiteInfo ->
ErrStr = io_lib:format("~n*** ERROR *** "
"Invalid return value from "
- "~w:suite/0: ~p~n", [Mod,SuiteInfo]),
+ "~w:suite/0: ~p~n", [Suite,SuiteInfo]),
io:format(ErrStr, []),
io:format(user, ErrStr, []),
{suite0_failed,bad_return_value}
end.
-add_defaults1(_Mod,init_per_suite,[],SuiteInfo,_DoInit) ->
- SuiteInfo;
-
-add_defaults1(Mod,Func,FuncInfo,SuiteInfo,DoInit) ->
- %% mustn't re-require suite variables in test case info function,
- %% can result in weird behaviour (suite values get overwritten)
+add_defaults1(Mod,Func, GroupPath, SuiteInfo) ->
+ Suite = get_suite_name(Mod, GroupPath),
+ %% GroupPathInfo (for subgroup on level X) =
+ %% [LevelXGroupInfo, LevelX-1GroupInfo, ..., TopLevelGroupInfo]
+ GroupPathInfo =
+ lists:map(fun(GroupProps) ->
+ Name = ?val(name, GroupProps),
+ case catch Suite:group(Name) of
+ GrInfo when is_list(GrInfo) -> GrInfo;
+ _ -> []
+ end
+ end, GroupPath),
+ Args = if Func == init_per_group ; Func == end_per_group ->
+ [?val(name, hd(GroupPath))];
+ true ->
+ []
+ end,
+ TestCaseInfo =
+ case catch apply(Mod,Func,Args) of
+ TCInfo when is_list(TCInfo) -> TCInfo;
+ _ -> []
+ end,
+ %% let test case info (also for all config funcs) override group info,
+ %% and lower level group info override higher level info
+ TCAndGroupInfo = [TestCaseInfo | remove_info_in_prev(TestCaseInfo,
+ GroupPathInfo)],
+ %% find and save require terms found in suite info
SuiteReqs =
[SDDef || SDDef <- SuiteInfo,
((require == element(1,SDDef)) or
(default_config == element(1,SDDef)))],
- FuncReqs =
- [FIDef || FIDef <- FuncInfo,
- require == element(1,FIDef)],
- case [element(2,Clash) || Clash <- SuiteReqs,
- require == element(1, Clash),
- true == lists:keymember(element(2,Clash),2,
- FuncReqs)] of
+ case check_for_clashes(TestCaseInfo, GroupPathInfo, SuiteReqs) of
[] ->
- add_defaults2(Mod,Func,FuncInfo,SuiteInfo,SuiteReqs,DoInit);
+ add_defaults2(Mod,Func, TCAndGroupInfo,SuiteInfo,SuiteReqs);
Clashes ->
{error,{config_name_already_in_use,Clashes}}
end.
-add_defaults2(Mod,init_per_suite,IPSInfo,SuiteInfo,SuiteReqs,false) ->
- %% not common practise to use a test case info function for
- %% init_per_suite (usually handled by suite/0), but let's support
- %% it just in case...
- add_defaults2(Mod,init_per_suite,IPSInfo,SuiteInfo,SuiteReqs,true);
-
-add_defaults2(_Mod,_Func,FuncInfo,SuiteInfo,_,false) ->
- %% include require elements from test case info, but not from suite/0
- %% (since we've already required those vars)
- FuncInfo ++
- [SFDef || SFDef <- SuiteInfo,
- require /= element(1,SFDef),
- false == lists:keymember(element(1,SFDef),1,FuncInfo)];
-
-add_defaults2(_Mod,_Func,FuncInfo,SuiteInfo,SuiteReqs,true) ->
- %% We must include require elements from suite/0 here since
- %% there's no init_per_suite call before this first test case.
- %% Let other test case info elements override those from suite/0.
- FuncInfo ++ SuiteReqs ++
- [SDDef || SDDef <- SuiteInfo,
- require /= element(1,SDDef),
- false == lists:keymember(element(1,SDDef),1,FuncInfo)].
+get_suite_name(?MODULE, [Cfg|_]) when is_list(Cfg), Cfg /= [] ->
+ get_suite_name(?MODULE, Cfg);
+
+get_suite_name(?MODULE, Cfg) when is_list(Cfg), Cfg /= [] ->
+ case ?val(tc_group_properties, Cfg) of
+ undefined ->
+ case ?val(suite, Cfg) of
+ undefined -> ?MODULE;
+ Suite -> Suite
+ end;
+ GrProps ->
+ case ?val(suite, GrProps) of
+ undefined -> ?MODULE;
+ Suite -> Suite
+ end
+ end;
+get_suite_name(Mod, _) ->
+ Mod.
+
+%% Check that alias names are not already in use
+check_for_clashes(TCInfo, [CurrGrInfo|Path], SuiteInfo) ->
+ ReqNames = fun(Info) -> [element(2,R) || R <- Info,
+ size(R) == 3,
+ require == element(1,R)]
+ end,
+ ExistingNames = lists:flatten([ReqNames(L) || L <- [SuiteInfo|Path]]),
+ CurrGrReqNs = ReqNames(CurrGrInfo),
+ GrClashes = [Name || Name <- CurrGrReqNs,
+ true == lists:member(Name, ExistingNames)],
+ AllReqNs = CurrGrReqNs ++ ExistingNames,
+ TCClashes = [Name || Name <- ReqNames(TCInfo),
+ true == lists:member(Name, AllReqNs)],
+ TCClashes ++ GrClashes.
+
+%% Delete the info terms in Terms from all following info lists
+remove_info_in_prev(Terms, [[] | Rest]) ->
+ [[] | remove_info_in_prev(Terms, Rest)];
+remove_info_in_prev(Terms, [Info | Rest]) ->
+ UniqueInInfo = [U || U <- Info,
+ ((timetrap == element(1,U)) and
+ (not lists:keymember(timetrap,1,Terms))) or
+ ((require == element(1,U)) and
+ (not lists:member(U,Terms))) or
+ ((default_config == element(1,U)) and
+ (not keysmember([default_config,1,
+ element(2,U),2], Terms)))],
+ OtherTermsInInfo = [T || T <- Info,
+ timetrap /= element(1,T),
+ require /= element(1,T),
+ default_config /= element(1,T),
+ false == lists:keymember(element(1,T),1,
+ Terms)],
+ KeptInfo = UniqueInInfo ++ OtherTermsInInfo,
+ [KeptInfo | remove_info_in_prev(Terms ++ KeptInfo, Rest)];
+remove_info_in_prev(_, []) ->
+ [].
+
+keysmember([Key,Pos|Next], List) ->
+ case [Elem || Elem <- List, Key == element(Pos,Elem)] of
+ [] -> false;
+ Found -> keysmember(Next, Found)
+ end;
+keysmember([], _) -> true.
+
+
+add_defaults2(_Mod,init_per_suite, IPSInfo, SuiteInfo,SuiteReqs) ->
+ Info = lists:flatten([IPSInfo, SuiteReqs]),
+ lists:flatten([Info,remove_info_in_prev(Info, [SuiteInfo])]);
+
+add_defaults2(_Mod,init_per_group, IPGAndGroupInfo, SuiteInfo,SuiteReqs) ->
+ SuiteInfo1 =
+ remove_info_in_prev(lists:flatten([IPGAndGroupInfo,
+ SuiteReqs]), [SuiteInfo]),
+ %% don't require terms in prev groups (already processed)
+ case IPGAndGroupInfo of
+ [IPGInfo] ->
+ lists:flatten([IPGInfo,SuiteInfo1]);
+ [IPGInfo | [CurrGroupInfo | PrevGroupInfo]] ->
+ PrevGroupInfo1 = delete_require_terms(PrevGroupInfo),
+ lists:flatten([IPGInfo,CurrGroupInfo,PrevGroupInfo1,
+ SuiteInfo1])
+ end;
+
+add_defaults2(_Mod,_Func, TCAndGroupInfo, SuiteInfo,SuiteReqs) ->
+ %% Include require elements from test case info and current group,
+ %% but not from previous groups or suite/0 (since we've already required
+ %% those vars). Let test case info elements override group and suite
+ %% info elements.
+ SuiteInfo1 = remove_info_in_prev(lists:flatten([TCAndGroupInfo,
+ SuiteReqs]), [SuiteInfo]),
+ %% don't require terms in prev groups (already processed)
+ case TCAndGroupInfo of
+ [TCInfo] ->
+ lists:flatten([TCInfo,SuiteInfo1]);
+ [TCInfo | [CurrGroupInfo | PrevGroupInfo]] ->
+ PrevGroupInfo1 = delete_require_terms(PrevGroupInfo),
+ lists:flatten([TCInfo,CurrGroupInfo,PrevGroupInfo1,
+ SuiteInfo1])
+ end.
+
+delete_require_terms([Info | Prev]) ->
+ Info1 = [T || T <- Info,
+ require /= element(1,T),
+ default_config /= element(1,T)],
+ [Info1 | delete_require_terms(Prev)];
+delete_require_terms([]) ->
+ [].
merge_with_suite_defaults(Mod,SuiteInfo) ->
case lists:keysearch(suite_defaults,1,Mod:module_info(attributes)) of
@@ -355,18 +473,20 @@ timetrap_first([Trap = {timetrap,_} | Rest],Info,Found) ->
timetrap_first([Other | Rest],Info,Found) ->
timetrap_first(Rest,[Other | Info],Found);
timetrap_first([],Info,[]) ->
- [{timetrap,{minutes,30}} | lists:reverse(Info)];
+ [{timetrap,{minutes,30}} | ?rev(Info)];
timetrap_first([],Info,Found) ->
- lists:reverse(Found) ++ lists:reverse(Info).
+ ?rev(Found) ++ ?rev(Info).
-configure([{require,Required}|Rest],Info,SuiteInfo,Scope,Config) ->
+configure([{require,Required}|Rest],
+ Info,SuiteInfo,Scope,PostInitHook,Config) ->
case ct:require(Required) of
ok ->
- configure(Rest,Info,SuiteInfo,Scope,Config);
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,Config);
Error = {error,Reason} ->
- case required_default('_UNDEF',Required,Info,SuiteInfo,Scope) of
+ case required_default('_UNDEF',Required,Info,
+ SuiteInfo,Scope) of
ok ->
- configure(Rest,Info,SuiteInfo,Scope,Config);
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,Config);
_ ->
case lists:keymember(Required,2,SuiteInfo) of
true ->
@@ -376,14 +496,15 @@ configure([{require,Required}|Rest],Info,SuiteInfo,Scope,Config) ->
end
end
end;
-configure([{require,Name,Required}|Rest],Info,SuiteInfo,Scope,Config) ->
+configure([{require,Name,Required}|Rest],
+ Info,SuiteInfo,Scope,PostInitHook,Config) ->
case ct:require(Name,Required) of
ok ->
- configure(Rest,Info,SuiteInfo,Scope,Config);
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,Config);
Error = {error,Reason} ->
case required_default(Name,Required,Info,SuiteInfo,Scope) of
ok ->
- configure(Rest,Info,SuiteInfo,Scope,Config);
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,Config);
_ ->
case lists:keymember(Name,2,SuiteInfo) of
true ->
@@ -393,31 +514,35 @@ configure([{require,Name,Required}|Rest],Info,SuiteInfo,Scope,Config) ->
end
end
end;
-configure([{timetrap,off}|Rest],Info,SuiteInfo,Scope,Config) ->
- configure(Rest,Info,SuiteInfo,Scope,Config);
-configure([{timetrap,Time}|Rest],Info,SuiteInfo,Scope,Config) ->
- Dog = test_server:timetrap(Time),
- configure(Rest,Info,SuiteInfo,Scope,[{watchdog,Dog}|Config]);
-configure([{ct_hooks, Hook} | Rest], Info, SuiteInfo, Scope, Config) ->
- configure(Rest, Info, SuiteInfo, Scope, [{ct_hooks, Hook} | Config]);
-configure([_|Rest],Info,SuiteInfo,Scope,Config) ->
- configure(Rest,Info,SuiteInfo,Scope,Config);
-configure([],_,_,_,Config) ->
- {ok,[Config]}.
+configure([{timetrap,off}|Rest],Info,SuiteInfo,Scope,PostInitHook,Config) ->
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,Config);
+configure([{timetrap,Time}|Rest],Info,SuiteInfo,Scope,PostInitHook,Config) ->
+ PostInitHook1 =
+ [{watchdog,fun() -> case test_server:get_timetrap_info() of
+ undefined ->
+ test_server:timetrap(Time);
+ _ ->
+ {error,already_set}
+ end
+ end} | PostInitHook],
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook1,Config);
+configure([{ct_hooks,Hook}|Rest],Info,SuiteInfo,Scope,PostInitHook,Config) ->
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,[{ct_hooks,Hook}|Config]);
+configure([_|Rest],Info,SuiteInfo,Scope,PostInitHook,Config) ->
+ configure(Rest,Info,SuiteInfo,Scope,PostInitHook,Config);
+configure([],_,_,_,PostInitHook,Config) ->
+ {ok,PostInitHook,Config}.
%% the require element in Info may come from suite/0 and
-%% should be scoped 'suite', or come from the testcase info
-%% function and should then be scoped 'testcase'
-required_default(Name,Key,Info,SuiteInfo,{Func,true}) ->
- case try_set_default(Name,Key,SuiteInfo,suite) of
- ok ->
- ok;
- _ ->
- required_default(Name,Key,Info,[],{Func,false})
- end;
-required_default(Name,Key,Info,_,{init_per_suite,_}) ->
+%% should be scoped 'suite', or come from the group info
+%% function and be scoped 'group', or come from the testcase
+%% info function and then be scoped 'testcase'
+
+required_default(Name,Key,Info,_,init_per_suite) ->
try_set_default(Name,Key,Info,suite);
-required_default(Name,Key,Info,_,_) ->
+required_default(Name,Key,Info,_,{init_per_group,GrName,_}) ->
+ try_set_default(Name,Key,Info,{group,GrName});
+required_default(Name,Key,Info,_,_FuncSpec) ->
try_set_default(Name,Key,Info,testcase).
try_set_default(Name,Key,Info,Where) ->
@@ -467,10 +592,11 @@ end_tc(Mod,Func,{Result,[Args]}, Return) ->
end_tc(Mod,Func,self(),Result,Args,Return).
end_tc(Mod,Func,TCPid,Result,Args,Return) ->
- case lists:keysearch(watchdog,1,Args) of
- {value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog);
- false -> ok
- end,
+ %% in case Mod == ct_framework, lookup the suite name
+ Suite = get_suite_name(Mod, Args),
+
+ test_server:timetrap_cancel(),
+
%% 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
@@ -482,57 +608,78 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
end,
ct_util:delete_testdata(comment),
ct_util:delete_suite_data(last_saved_config),
- FuncSpec =
- case group_or_func(Func,Args) of
- {_,GroupName,_Props} = Group ->
- case lists:keysearch(save_config,1,Args) of
- {value,{save_config,SaveConfig}} ->
- ct_util:save_suite_data(
- last_saved_config,
- {Mod,{group,GroupName}},
- SaveConfig),
- Group;
- false ->
- Group
- end;
- _ ->
- case lists:keysearch(save_config,1,Args) of
- {value,{save_config,SaveConfig}} ->
- ct_util:save_suite_data(last_saved_config,
- {Mod,Func},SaveConfig),
- Func;
- false ->
- Func
- end
- end,
- ct_util:reset_silent_connections(),
+
+ FuncSpec = case group_or_func(Func,Args) of
+ {_,_GroupName,_} = Group -> Group;
+ _ -> Func
+ end,
case get('$test_server_framework_test') of
undefined ->
{FinalResult,FinalNotify} =
case ct_hooks:end_tc(
- Mod, FuncSpec, Args, Result, Return) of
+ Suite, FuncSpec, Args, Result, Return) of
'$ct_no_change' ->
{ok,Result};
FinalResult1 ->
{FinalResult1,FinalResult1}
end,
- % send sync notification so that event handlers may print
- % in the log file before it gets closed
+ %% send sync notification so that event handlers may print
+ %% in the log file before it gets closed
ct_event:sync_notify(#event{name=tc_done,
node=node(),
data={Mod,FuncSpec,
tag_cth(FinalNotify)}});
Fun ->
- % send sync notification so that event handlers may print
- % in the log file before it gets closed
+ %% send sync notification so that event handlers may print
+ %% in the log file before it gets closed
ct_event:sync_notify(#event{name=tc_done,
node=node(),
data={Mod,FuncSpec,tag(Result)}}),
FinalResult = Fun(end_tc, Return)
+ end,
+
+ case FuncSpec of
+ {_,GroupName,_Props} ->
+ if Func == end_per_group ->
+ ct_config:delete_default_config({group,GroupName});
+ true -> ok
+ end,
+ case lists:keysearch(save_config,1,Args) of
+ {value,{save_config,SaveConfig}} ->
+ ct_util:save_suite_data(last_saved_config,
+ {Suite,{group,GroupName}},
+ SaveConfig);
+ false ->
+ ok
+ end;
+ _ ->
+ case lists:keysearch(save_config,1,Args) of
+ {value,{save_config,SaveConfig}} ->
+ ct_util:save_suite_data(last_saved_config,
+ {Suite,Func},SaveConfig);
+ false ->
+ ok
+ end
end,
-
+ ct_util:reset_silent_connections(),
+
+ %% reset the curr_tc state, or delete this TC from the list of
+ %% executing cases (if in a parallel group)
+ ClearCurrTC = fun(Running = [_,_|_]) ->
+ lists:keydelete(Func,2,Running);
+ ({_,{suite0_failed,_}}) ->
+ undefined;
+ ([{_,CurrTC}]) when CurrTC == Func ->
+ undefined;
+ (undefined) ->
+ undefined;
+ (Unexpected) ->
+ exit({error,{reset_curr_tc,{Mod,Func},Unexpected}})
+ end,
+ ct_util:update_testdata(curr_tc,ClearCurrTC),
+
case FinalResult of
{skip,{sequence_failed,_,_}} ->
%% ct_logs:init_tc is never called for a skipped test case
@@ -548,7 +695,7 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
end,
case Func of
end_per_suite ->
- ct_util:match_delete_suite_data({seq,Mod,'_'});
+ ct_util:match_delete_suite_data({seq,Suite,'_'});
_ ->
ok
end,
@@ -648,31 +795,36 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
end
end,
- io:format(user, "~n- - - - - - - - - - - - - - - - "
- "- - - - - - - - - -~n", []),
+ PrintErr = fun(ErrFormat, ErrArgs) ->
+ Div = "~n- - - - - - - - - - - - - - - - "
+ "- - - - - - - - - -~n",
+ io:format(user, lists:concat([Div,ErrFormat,Div,"~n"]),
+ ErrArgs),
+ ct_logs:tc_log(ct_error_notify, "CT Error Notification",
+ ErrFormat, ErrArgs)
+ end,
case Loc of
- %% we don't use the line parse transform as we compile this
- %% module so location will be on form {M,F}
[{?MODULE,error_in_suite}] ->
- io:format(user, "Error in suite detected: ~s", [ErrStr]);
+ PrintErr("Error in suite detected: ~s", [ErrStr]);
- R when R == unknown; R == undefined ->
- io:format(user, "Error detected: ~s", [ErrStr]);
+ R when R == unknown; R == undefined ->
+ PrintErr("Error detected: ~s", [ErrStr]);
%% if a function specified by all/0 does not exist, we
%% pick up undef here
- [{LastMod,LastFunc}] ->
- io:format(user, "~w:~w could not be executed~n",
- [LastMod,LastFunc]),
- io:format(user, "Reason: ~s", [ErrStr]);
+ [{LastMod,LastFunc}|_] when ErrStr == "undef" ->
+ PrintErr("~w:~w could not be executed~nReason: ~s",
+ [LastMod,LastFunc,ErrStr]);
+
+ [{LastMod,LastFunc}|_] ->
+ PrintErr("~w:~w failed~nReason: ~s", [LastMod,LastFunc,ErrStr]);
[{LastMod,LastFunc,LastLine}|_] ->
%% print error to console, we are only
%% interested in the last executed expression
- io:format(user, "~w:~w failed on line ~w~n",
- [LastMod,LastFunc,LastLine]),
- io:format(user, "Reason: ~s", [ErrStr]),
-
+ PrintErr("~w:~w failed on line ~w~nReason: ~s",
+ [LastMod,LastFunc,LastLine,ErrStr]),
+
case ct_util:read_suite_data({seq,Mod,Func}) of
undefined ->
ok;
@@ -681,8 +833,6 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
mark_as_failed(Seq,Mod,Func,SeqTCs)
end
end,
- io:format(user, "~n- - - - - - - - - - - - - - - - "
- "- - - - - - - - - -~n~n", []),
ok.
%% cases in seq that have already run
@@ -704,11 +854,11 @@ mark_as_failed1(_,_,_,[]) ->
group_or_func(Func, Config) when Func == init_per_group;
Func == end_per_group ->
- case proplists:get_value(tc_group_properties,Config) of
+ case ?val(tc_group_properties, Config) of
undefined ->
{Func,unknown,[]};
GrProps ->
- GrName = proplists:get_value(name,GrProps),
+ GrName = ?val(name,GrProps),
{Func,GrName,proplists:delete(name,GrProps)}
end;
group_or_func(Func, _Config) ->
@@ -732,7 +882,7 @@ get_suite(Mod, all) ->
%% (and only) test case so we can report Error properly
[{?MODULE,error_in_suite,[[Error]]}];
ConfTests ->
- get_all(Mod, ConfTests)
+ get_all(Mod, ConfTests)
end;
_ ->
E = "Bad return value from "++atom_to_list(Mod)++":groups/0",
@@ -746,7 +896,7 @@ get_suite(Mod, all) ->
%% group
get_suite(Mod, Group={conf,Props,_Init,TCs,_End}) ->
- Name = proplists:get_value(name, Props),
+ Name = ?val(name, Props),
case catch apply(Mod, groups, []) of
{'EXIT',_} ->
[Group];
@@ -764,14 +914,25 @@ get_suite(Mod, Group={conf,Props,_Init,TCs,_End}) ->
%% a *subgroup* specified *only* as skipped (and not
%% as an explicit test) should not be returned, or
%% init/end functions for top groups will be executed
- case catch proplists:get_value(name, element(2, hd(ConfTests))) of
+ case catch ?val(name, element(2, hd(ConfTests))) of
Name -> % top group
delete_subs(ConfTests, ConfTests);
_ ->
[]
end;
false ->
- delete_subs(ConfTests, ConfTests)
+ ConfTests1 = delete_subs(ConfTests, ConfTests),
+ case ?val(override, Props) of
+ undefined ->
+ ConfTests1;
+ [] ->
+ ConfTests1;
+ ORSpec ->
+ ORSpec1 = if is_tuple(ORSpec) -> [ORSpec];
+ true -> ORSpec end,
+ search_and_override(ConfTests1,
+ ORSpec1, Mod)
+ end
end
end;
_ ->
@@ -793,13 +954,12 @@ get_all_cases(Suite) ->
{error,Error};
Tests ->
Cases = get_all_cases1(Suite, Tests),
- lists:reverse(
- lists:foldl(fun(TC, TCs) ->
- case lists:member(TC, TCs) of
+ ?rev(lists:foldl(fun(TC, TCs) ->
+ case lists:member(TC, TCs) of
true -> TCs;
- false -> [TC | TCs]
- end
- end, [], Cases))
+ false -> [TC | TCs]
+ end
+ end, [], Cases))
end.
get_all_cases1(Suite, [{conf,_Props,_Init,GrTests,_End} | Tests]) ->
@@ -918,14 +1078,14 @@ delete_subs([], All) ->
All.
delete_conf({conf,Props,_,_,_}, Confs) ->
- Name = proplists:get_value(name, Props),
+ Name = ?val(name, Props),
[Conf || Conf = {conf,Props0,_,_,_} <- Confs,
- Name =/= proplists:get_value(name, Props0)].
+ Name =/= ?val(name, Props0)].
is_sub({conf,Props,_,_,_}=Conf, [{conf,_,_,Tests,_} | Confs]) ->
- Name = proplists:get_value(name, Props),
+ Name = ?val(name, Props),
case lists:any(fun({conf,Props0,_,_,_}) ->
- case proplists:get_value(name, Props0) of
+ case ?val(name, Props0) of
N when N == Name ->
true;
_ ->
@@ -1036,8 +1196,8 @@ make_conf(Mod, Name, Props, TestSpec) ->
"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,init_per_group},
+ {?MODULE,end_per_group},
[{suite,Mod}]}
end,
{conf,[{name,Name}|Props++ExtraProps],InitConf,TestSpec,EndConf}.
@@ -1078,29 +1238,116 @@ expand_groups([H | T], ConfTests, Mod) ->
expand_groups([], _ConfTests, _Mod) ->
[];
expand_groups({group,Name}, ConfTests, Mod) ->
- FindConf =
- fun({conf,Props,_,_,_}) ->
- case proplists:get_value(name, Props) of
- Name -> true;
- _ -> false
+ expand_groups({group,Name,default,[]}, ConfTests, Mod);
+expand_groups({group,Name,default}, ConfTests, Mod) ->
+ expand_groups({group,Name,default,[]}, ConfTests, Mod);
+expand_groups({group,Name,ORProps}, ConfTests, Mod) when is_list(ORProps) ->
+ expand_groups({group,Name,ORProps,[]}, ConfTests, Mod);
+expand_groups({group,Name,ORProps,SubORSpec}, ConfTests, Mod) ->
+ FindConf =
+ fun(Conf = {conf,Props,Init,Ts,End}) ->
+ case ?val(name, Props) of
+ Name when ORProps == default ->
+ [Conf];
+ Name ->
+ [{conf,[{name,Name}|ORProps],Init,Ts,End}];
+ _ ->
+ []
end
end,
- case lists:filter(FindConf, ConfTests) of
- [ConfTest|_] ->
- expand_groups(ConfTest, ConfTests, Mod);
+ case lists:flatmap(FindConf, ConfTests) of
[] ->
- E = "Invalid reference to group "++
- atom_to_list(Name)++" in "++
- atom_to_list(Mod)++":all/0",
- throw({error,list_to_atom(E)})
+ throw({error,invalid_ref_msg(Name, Mod)});
+ Matching when SubORSpec == [] ->
+ Matching;
+ Matching ->
+ override_props(Matching, SubORSpec, Name,Mod)
end;
expand_groups(SeqOrTC, _ConfTests, _Mod) ->
SeqOrTC.
+%% search deep for the matching conf test and modify it and any
+%% sub tests according to the override specification
+search_and_override([Conf = {conf,Props,Init,Tests,End}], ORSpec, Mod) ->
+ Name = ?val(name, Props),
+ case lists:keysearch(Name, 1, ORSpec) of
+ {value,{Name,default}} ->
+ [Conf];
+ {value,{Name,ORProps}} ->
+ [{conf,[{name,Name}|ORProps],Init,Tests,End}];
+ {value,{Name,default,[]}} ->
+ [Conf];
+ {value,{Name,default,SubORSpec}} ->
+ override_props([Conf], SubORSpec, Name,Mod);
+ {value,{Name,ORProps,SubORSpec}} ->
+ override_props([{conf,[{name,Name}|ORProps],
+ Init,Tests,End}], SubORSpec, Name,Mod);
+ _ ->
+ [{conf,Props,Init,search_and_override(Tests,ORSpec,Mod),End}]
+ end.
+
+%% Modify the Tests element according to the override specification
+override_props([{conf,Props,Init,Tests,End} | Confs], SubORSpec, Name,Mod) ->
+ {Subs,SubORSpec1} = override_sub_props(Tests, [], SubORSpec, Mod),
+ [{conf,Props,Init,Subs,End} | override_props(Confs, SubORSpec1, Name,Mod)];
+override_props([], [], _,_) ->
+ [];
+override_props([], SubORSpec, Name,Mod) ->
+ Es = [invalid_ref_msg(Name, element(1,Spec), Mod) || Spec <- SubORSpec],
+ throw({error,Es}).
+
+override_sub_props([], New, ORSpec, _) ->
+ {?rev(New),ORSpec};
+override_sub_props([T = {conf,Props,Init,Tests,End} | Ts],
+ New, ORSpec, Mod) ->
+ Name = ?val(name, Props),
+ case lists:keysearch(Name, 1, ORSpec) of
+ {value,Spec} -> % group found in spec
+ Props1 =
+ case element(2, Spec) of
+ default -> Props;
+ ORProps -> [{name,Name} | ORProps]
+ end,
+ case catch element(3, Spec) of
+ Undef when Undef == [] ; 'EXIT' == element(1, Undef) ->
+ override_sub_props(Ts, [{conf,Props1,Init,Tests,End} | New],
+ lists:keydelete(Name, 1, ORSpec), Mod);
+ SubORSpec when is_list(SubORSpec) ->
+ case override_sub_props(Tests, [], SubORSpec, Mod) of
+ {Subs,[]} ->
+ override_sub_props(Ts, [{conf,Props1,Init,
+ Subs,End} | New],
+ lists:keydelete(Name, 1, ORSpec),
+ Mod);
+ {_,NonEmptySpec} ->
+ Es = [invalid_ref_msg(Name, element(1, GrRef),
+ Mod) || GrRef <- NonEmptySpec],
+ throw({error,Es})
+ end;
+ BadGrSpec ->
+ throw({error,{invalid_form,BadGrSpec}})
+ end;
+ _ -> % not a group in spec
+ override_sub_props(Ts, [T | New], ORSpec, Mod)
+ end;
+override_sub_props([TC | Ts], New, ORSpec, Mod) ->
+ override_sub_props(Ts, [TC | New], ORSpec, Mod).
+
+invalid_ref_msg(Name, Mod) ->
+ E = "Invalid reference to group "++
+ atom_to_list(Name)++" in "++
+ atom_to_list(Mod)++":all/0",
+ list_to_atom(E).
+
+invalid_ref_msg(Name0, Name1, Mod) ->
+ E = "Invalid reference to group "++
+ atom_to_list(Name1)++" from "++atom_to_list(Name0)++
+ " in "++atom_to_list(Mod)++":all/0",
+ list_to_atom(E).
%%!============================================================
%%! The support for sequences by means of using sequences/0
-%%! will be removed in OTP R14. The code below is only kept
+%%! will be removed in OTP R15. The code below is only kept
%%! for backwards compatibility. From OTP R13 groups with
%%! sequence property should be used instead!
%%!============================================================
@@ -1210,22 +1457,31 @@ error_in_suite(Config) ->
Reason = test_server:lookup_config(error,Config),
exit(Reason).
+%% if init_per_suite and end_per_suite are missing in the suite,
+%% these will be called instead (without any trace of them in the
+%% log files), only so that it's possible to call hook functions
+%% for configuration
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
%% if the group config functions are missing in the suite,
%% use these instead
-ct_init_per_group(GroupName, Config) ->
+init_per_group(GroupName, Config) ->
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, _) ->
+end_per_group(GroupName, _) ->
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.
-
%%%-----------------------------------------------------------------
%%% @spec report(What,Data) -> ok
@@ -1234,8 +1490,8 @@ report(What,Data) ->
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),
+ TestName = filename:basename(?val(topdir, Data), ".logs"),
+ RunDir = ?val(rundir, Data),
ct_logs:make_all_suites_index({TestName,RunDir}),
ok;
tests_start ->
@@ -1274,6 +1530,10 @@ report(What,Data) ->
tests_done ->
ok;
tc_start ->
+ %% Data = {{Suite,Func},LogFileName}
+ ct_event:sync_notify(#event{name=tc_logfile,
+ node=node(),
+ data=Data}),
ok;
tc_done ->
{_Suite,Case,Result} = Data,
@@ -1298,10 +1558,6 @@ 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,_}}}} ->
@@ -1337,11 +1593,23 @@ report(What,Data) ->
node=node(),
data=Data}),
ct_hooks:on_tc_skip(What, Data),
- if Case /= end_per_suite, Case /= end_per_group ->
+ if Case /= end_per_suite,
+ Case /= end_per_group ->
add_to_stats(auto_skipped);
true ->
ok
end;
+ framework_error ->
+ case Data of
+ {{M,F},E} ->
+ ct_event:sync_notify(#event{name=tc_done,
+ node=node(),
+ data={M,F,{framework_error,E}}});
+ _ ->
+ ct_event:sync_notify(#event{name=tc_done,
+ node=node(),
+ data=Data})
+ end;
_ ->
ok
end,
@@ -1411,30 +1679,6 @@ 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])),
- Label = case application:get_env(common_test, test_label) of
- {ok,Lbl} when Lbl =/= undefined ->
- "<H1><FONT color=\"green\">" ++ Lbl ++ "</FONT></H1>\n";
- _ ->
- ""
- end,
- Bgr = case ct_logs:basic_html() of
- true ->
- "";
- false ->
- CTPath = code:lib_dir(common_test),
- TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"),
- " background=\"" ++ TileFile ++ "\""
- end,
-
- ["<html>\n",
- "<head><title>Test ", TestName1, " results</title>\n",
- "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
- "</head>\n",
- "<body", Bgr, " bgcolor=\"white\" text=\"black\" ",
- "link=\"blue\" vlink=\"purple\" alink=\"red\">\n",
- Label,
- "<H2>Results from test ", TestName1, "</H2>\n"].
-
+%%% @spec get_html_wrapper(TestName, PrintLabel, Cwd) -> Header
+get_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
+ ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols).
diff --git a/lib/common_test/src/ct_ftp.erl b/lib/common_test/src/ct_ftp.erl
index 5db73066a3..723715c986 100644
--- a/lib/common_test/src/ct_ftp.erl
+++ b/lib/common_test/src/ct_ftp.erl
@@ -66,6 +66,7 @@
%%% {unix,[{ftp,IpAddr},
%%% {username,Username},
%%% {password,Password}]}.</pre>
+%%% @see ct:require/2
put(KeyOrName,LocalFile,RemoteFile) ->
Fun = fun(Ftp) -> send(Ftp,LocalFile,RemoteFile) end,
open_and_do(KeyOrName,Fun).
@@ -85,6 +86,7 @@ put(KeyOrName,LocalFile,RemoteFile) ->
%%%
%%% <p>The config file must be as for put/3.</p>
%%% @see put/3
+%%% @see ct:require/2
get(KeyOrName,RemoteFile,LocalFile) ->
Fun = fun(Ftp) -> recv(Ftp,RemoteFile,LocalFile) end,
open_and_do(KeyOrName,Fun).
@@ -105,6 +107,10 @@ get(KeyOrName,RemoteFile,LocalFile) ->
%%% simply use <code>Key</code>, the configuration variable name, to
%%% specify the target. Note that a connection that has no associated target
%%% name can only be closed with the handle value.</p>
+%%%
+%%% <p>See <c>ct:require/2</c> for how to create a new <c>Name</c></p>
+%%%
+%%% @see ct:require/2
open(KeyOrName) ->
case ct_util:get_key_from_name(KeyOrName) of
{ok,node} ->
diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl
index 5aab4dd2dd..1f01d84601 100644
--- a/lib/common_test/src/ct_gen_conn.erl
+++ b/lib/common_test/src/ct_gen_conn.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,7 @@
-compile(export_all).
-export([start/4, stop/1]).
--export([call/2, do_within_time/2]).
+-export([call/2, call/3, return/2, do_within_time/2]).
-ifdef(debug).
-define(dbg,true).
@@ -39,17 +39,24 @@
name,
address,
init_data,
+ reconnect = true,
+ forward = false,
+ use_existing = true,
+ old = false,
conn_pid,
cb_state,
ct_util_server}).
%%%-----------------------------------------------------------------
-%%% @spec start(Name,Address,InitData,CallbackMod) ->
+%%% @spec start(Address,InitData,CallbackMod,Opts) ->
%%% {ok,Handle} | {error,Reason}
%%% Name = term()
%%% CallbackMod = atom()
%%% InitData = term()
%%% Address = term()
+%%% Opts = [Opt]
+%%% Opt = {name,Name} | {use_existing_connection,boolean()} |
+%%% {reconnect,boolean()} | {forward_messages,boolean()}
%%%
%%% @doc Open a connection and start the generic connection owner process.
%%%
@@ -60,50 +67,67 @@
%%% <code>InitData</code> and returna
%%% <code>{ok,ConnectionPid,State}</code> or
%%% <code>{error,Reason}</code>.</p>
+%%%
+%%% If no name is given, the <code>Name</code> argument in init/3 will
+%%% have the value <code>undefined</code>.
+%%%
+%%% The callback modules must also export
+%%% ```
+%%% handle_msg(Msg,From,State) -> {reply,Reply,State} |
+%%% {noreply,State} |
+%%% {stop,Reply,State}
+%%% terminate(ConnectionPid,State) -> term()
+%%% close(Handle) -> term()
+%%% '''
+%%%
+%%% The <code>close/1</code> callback function is actually a callback
+%%% for ct_util, for closing registered connections when
+%%% ct_util_server is terminated. <code>Handle</code> is the Pid of
+%%% the ct_gen_conn process.
+%%%
+%%% If option <code>reconnect</code> is <code>true</code>, then the
+%%% callback must also export
+%%% ```
+%%% reconnect(Address,State) -> {ok,ConnectionPid,State}
+%%% '''
+%%%
+%%% If option <code>forward_messages</code> is <ocde>true</code>, then
+%%% the callback must also export
+%%% ```
+%%% handle_msg(Msg,State) -> {noreply,State} | {stop,State}
+%%% '''
+%%%
+%%% An old interface still exists. This is used by ct_telnet, ct_ftp
+%%% and ct_ssh. The start function then has an explicit
+%%% <code>Name</code> argument, and no <code>Opts</code> argument. The
+%%% callback must export:
+%%%
+%%% ```
+%%% init(Name,Address,InitData) -> {ok,ConnectionPid,State}
+%%% handle_msg(Msg,State) -> {Reply,State}
+%%% reconnect(Address,State) -> {ok,ConnectionPid,State}
+%%% terminate(ConnectionPid,State) -> term()
+%%% close(Handle) -> term()
+%%% '''
+%%%
+start(Address,InitData,CallbackMod,Opts) when is_list(Opts) ->
+ do_start(Address,InitData,CallbackMod,Opts);
start(Name,Address,InitData,CallbackMod) ->
- case ct_util:does_connection_exist(Name,Address,CallbackMod) of
- {ok,Pid} ->
- log("ct_gen_conn:start","Using existing connection!\n",[]),
- {ok,Pid};
- false ->
- Self = self(),
- Pid = spawn(fun() ->
- init_gen(Self, #gen_opts{callback=CallbackMod,
- name=Name,
- address=Address,
- init_data=InitData})
- end),
- MRef = erlang:monitor(process,Pid),
- receive
- {connected,Pid} ->
- erlang:demonitor(MRef, [flush]),
- ct_util:register_connection(Name,Address,CallbackMod,Pid),
- {ok,Pid};
- {Error,Pid} ->
- receive {'DOWN',MRef,process,_,_} -> ok end,
- Error;
- {'DOWN',MRef,process,_,Reason} ->
- log("ct_gen_conn:start",
- "Connection process died: ~p\n",
- [Reason]),
- {error,{connection_process_died,Reason}}
- end
- end.
-
+ do_start(Address,InitData,CallbackMod,[{name,Name},{old,true}]).
%%%-----------------------------------------------------------------
%%% @spec stop(Handle) -> ok
%%% Handle = handle()
%%%
-%%% @doc Close the telnet connection and stop the process managing it.
+%%% @doc Close the connection and stop the process managing it.
stop(Pid) ->
- call(Pid,stop).
+ call(Pid,stop,5000).
%%%-----------------------------------------------------------------
%%% @spec log(Heading,Format,Args) -> ok
%%%
%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:log/3
+%%% @see ct_logs:log/3
log(Heading,Format,Args) ->
log(log,[Heading,Format,Args]).
@@ -111,7 +135,7 @@ log(Heading,Format,Args) ->
%%% @spec start_log(Heading) -> ok
%%%
%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:start_log/1
+%%% @see ct_logs:start_log/1
start_log(Heading) ->
log(start_log,[Heading]).
@@ -119,7 +143,7 @@ start_log(Heading) ->
%%% @spec cont_log(Format,Args) -> ok
%%%
%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:cont_log/2
+%%% @see ct_logs:cont_log/2
cont_log(Format,Args) ->
log(cont_log,[Format,Args]).
@@ -127,7 +151,7 @@ cont_log(Format,Args) ->
%%% @spec end_log() -> ok
%%%
%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:end_log/0
+%%% @see ct_logs:end_log/0
end_log() ->
log(end_log,[]).
@@ -148,10 +172,10 @@ do_within_time(Fun,Timeout) ->
Silent = get(silent),
TmpPid = spawn_link(fun() -> put(silent,Silent),
R = Fun(),
- Self ! {self(),R}
+ Self ! {self(),R}
end),
ConnPid = get(conn_pid),
- receive
+ receive
{TmpPid,Result} ->
Result;
{'EXIT',ConnPid,_Reason}=M ->
@@ -159,7 +183,7 @@ do_within_time(Fun,Timeout) ->
exit(TmpPid,kill),
self() ! M,
{error,connection_closed}
- after
+ after
Timeout ->
exit(TmpPid,kill),
receive
@@ -176,12 +200,66 @@ do_within_time(Fun,Timeout) ->
%%%=================================================================
%%% Internal functions
-call(Pid,Msg) ->
+do_start(Address,InitData,CallbackMod,Opts0) ->
+ Opts = check_opts(Opts0,#gen_opts{callback=CallbackMod,
+ address=Address,
+ init_data=InitData}),
+ case ct_util:does_connection_exist(Opts#gen_opts.name,
+ Address,CallbackMod) of
+ {ok,Pid} when Opts#gen_opts.use_existing ->
+ log("ct_gen_conn:start","Using existing connection!\n",[]),
+ {ok,Pid};
+ {ok,Pid} when not Opts#gen_opts.use_existing ->
+ {error,{connection_exists,Pid}};
+ false ->
+ do_start(Opts)
+ end.
+
+do_start(Opts) ->
+ Self = self(),
+ Pid = spawn(fun() -> init_gen(Self, Opts) end),
+ MRef = erlang:monitor(process,Pid),
+ receive
+ {connected,Pid} ->
+ erlang:demonitor(MRef, [flush]),
+ ct_util:register_connection(Opts#gen_opts.name, Opts#gen_opts.address,
+ Opts#gen_opts.callback, Pid),
+ {ok,Pid};
+ {Error,Pid} ->
+ receive {'DOWN',MRef,process,_,_} -> ok end,
+ Error;
+ {'DOWN',MRef,process,_,Reason} ->
+ log("ct_gen_conn:start",
+ "Connection process died: ~p\n",
+ [Reason]),
+ {error,{connection_process_died,Reason}}
+ end.
+
+check_opts(Opts0) ->
+ check_opts(Opts0,#gen_opts{}).
+
+check_opts([{name,Name}|T],Opts) ->
+ check_opts(T,Opts#gen_opts{name=Name});
+check_opts([{reconnect,Bool}|T],Opts) ->
+ check_opts(T,Opts#gen_opts{reconnect=Bool});
+check_opts([{forward_messages,Bool}|T],Opts) ->
+ check_opts(T,Opts#gen_opts{forward=Bool});
+check_opts([{use_existing_connection,Bool}|T],Opts) ->
+ check_opts(T,Opts#gen_opts{use_existing=Bool});
+check_opts([{old,Bool}|T],Opts) ->
+ check_opts(T,Opts#gen_opts{old=Bool});
+check_opts([],Opts) ->
+ Opts.
+
+call(Pid, Msg) ->
+ call(Pid, Msg, infinity).
+
+call(Pid, Msg, Timeout) ->
MRef = erlang:monitor(process,Pid),
Ref = make_ref(),
Pid ! {Msg,{self(),Ref}},
receive
- {Ref, Result} ->
+ {Ref, Result} ->
erlang:demonitor(MRef, [flush]),
case Result of
{retry,_Data} ->
@@ -189,8 +267,15 @@ call(Pid,Msg) ->
Other ->
Other
end;
- {'DOWN',MRef,process,_,Reason} ->
+ {'DOWN',MRef,process,_,Reason} ->
{error,{process_down,Pid,Reason}}
+ after Timeout ->
+ erlang:demonitor(MRef, [flush]),
+ log("ct_gen_conn",
+ "Connection process ~p not responding. Killing now!",
+ [Pid]),
+ exit(Pid, kill),
+ {error,{process_down,Pid,forced_termination}}
end.
return({To,Ref},Result) ->
@@ -198,36 +283,47 @@ return({To,Ref},Result) ->
init_gen(Parent,Opts) ->
process_flag(trap_exit,true),
- CtUtilServer = whereis(ct_util_server),
- link(CtUtilServer),
put(silent,false),
- case catch (Opts#gen_opts.callback):init(Opts#gen_opts.name,
- Opts#gen_opts.address,
- Opts#gen_opts.init_data) of
+ try (Opts#gen_opts.callback):init(Opts#gen_opts.name,
+ Opts#gen_opts.address,
+ Opts#gen_opts.init_data) of
{ok,ConnPid,State} when is_pid(ConnPid) ->
link(ConnPid),
put(conn_pid,ConnPid),
+ CtUtilServer = whereis(ct_util_server),
+ link(CtUtilServer),
Parent ! {connected,self()},
loop(Opts#gen_opts{conn_pid=ConnPid,
cb_state=State,
ct_util_server=CtUtilServer});
{error,Reason} ->
Parent ! {{error,Reason},self()}
+ catch
+ throw:{error,Reason} ->
+ Parent ! {{error,Reason},self()}
end.
loop(Opts) ->
receive
{'EXIT',Pid,Reason} when Pid==Opts#gen_opts.conn_pid ->
- log("Connection down!\nOpening new!","Reason: ~p\nAddress: ~p\n",
- [Reason,Opts#gen_opts.address]),
- case reconnect(Opts) of
- {ok, NewPid, NewState} ->
- link(NewPid),
- put(conn_pid,NewPid),
- loop(Opts#gen_opts{conn_pid=NewPid,cb_state=NewState});
- Error ->
+ case Opts#gen_opts.reconnect of
+ true ->
+ log("Connection down!\nOpening new!",
+ "Reason: ~p\nAddress: ~p\n",
+ [Reason,Opts#gen_opts.address]),
+ case reconnect(Opts) of
+ {ok, NewPid, NewState} ->
+ link(NewPid),
+ put(conn_pid,NewPid),
+ loop(Opts#gen_opts{conn_pid=NewPid,cb_state=NewState});
+ Error ->
+ ct_util:unregister_connection(self()),
+ log("Reconnect failed. Giving up!","Reason: ~p\n",
+ [Error])
+ end;
+ false ->
ct_util:unregister_connection(self()),
- log("Reconnect failed. Giving up!","Reason: ~p\n",[Error])
+ log("Connection closed!","Reason: ~p\n",[Reason])
end;
{'EXIT',Pid,Reason} ->
case Opts#gen_opts.ct_util_server of
@@ -252,24 +348,40 @@ loop(Opts) ->
loop(Opts);
{{retry,{_Error,_Name,_CPid,Msg}}, From} ->
log("Rerunning command","Connection reestablished. Rerunning command...",[]),
- {Return,NewState} =
+ {Return,NewState} =
(Opts#gen_opts.callback):handle_msg(Msg,Opts#gen_opts.cb_state),
return(From, Return),
- loop(Opts#gen_opts{cb_state=NewState});
- {Msg,From={Pid,_Ref}} when is_pid(Pid) ->
- {Return,NewState} =
+ loop(Opts#gen_opts{cb_state=NewState});
+ {Msg,From={Pid,_Ref}} when is_pid(Pid), Opts#gen_opts.old==true ->
+ {Return,NewState} =
(Opts#gen_opts.callback):handle_msg(Msg,Opts#gen_opts.cb_state),
return(From, Return),
- loop(Opts#gen_opts{cb_state=NewState})
+ loop(Opts#gen_opts{cb_state=NewState});
+ {Msg,From={Pid,_Ref}} when is_pid(Pid) ->
+ case (Opts#gen_opts.callback):handle_msg(Msg,From,
+ Opts#gen_opts.cb_state) of
+ {reply,Reply,NewState} ->
+ return(From,Reply),
+ loop(Opts#gen_opts{cb_state=NewState});
+ {noreply,NewState} ->
+ loop(Opts#gen_opts{cb_state=NewState});
+ {stop,Reply,NewState} ->
+ ct_util:unregister_connection(self()),
+ (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid,
+ NewState),
+ return(From,Reply)
+ end;
+ Msg when Opts#gen_opts.forward==true ->
+ case (Opts#gen_opts.callback):handle_msg(Msg,Opts#gen_opts.cb_state) of
+ {noreply,NewState} ->
+ loop(Opts#gen_opts{cb_state=NewState});
+ {stop,NewState} ->
+ ct_util:unregister_connection(self()),
+ (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid,
+ NewState)
+ end
end.
-nozero({ok,S}) when is_list(S) ->
- {ok,[C || C <- S,
- C=/=0,
- C=/=13]};
-nozero(M) ->
- M.
-
reconnect(Opts) ->
(Opts#gen_opts.callback):reconnect(Opts#gen_opts.address,
Opts#gen_opts.cb_state).
@@ -277,10 +389,8 @@ reconnect(Opts) ->
log(Func,Args) ->
case get(silent) of
- true when not ?dbg->
+ true when not ?dbg->
ok;
_ ->
apply(ct_logs,Func,Args)
end.
-
-
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index ffafc582cf..1bcc63738e 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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 @@
%% @doc Called before any suites are started
-spec init(State :: term()) -> ok |
- {error, Reason :: term()}.
+ {fail, Reason :: term()}.
init(Opts) ->
call(get_new_hooks(Opts, undefined) ++ get_builtin_hooks(Opts),
ok, init, []).
@@ -70,8 +70,7 @@ terminate(Hooks) ->
{skip, Reason :: term()} |
{auto_skip, Reason :: term()} |
{fail, Reason :: term()}.
-init_tc(ct_framework, _Func, Args) ->
- Args;
+
init_tc(Mod, init_per_suite, Config) ->
Info = try proplists:get_value(ct_hooks, Mod:suite(),[]) of
List when is_list(List) ->
@@ -104,27 +103,21 @@ init_tc(_Mod, TC, Config) ->
{auto_skip, Reason :: term()} |
{fail, Reason :: term()} |
ok | '$ct_no_change'.
-end_tc(ct_framework, _Func, _Args, Result, _Return) ->
- Result;
end_tc(Mod, init_per_suite, Config, _Result, Return) ->
call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config],
'$ct_no_change');
-
end_tc(Mod, end_per_suite, Config, Result, _Return) ->
call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config],
'$ct_no_change');
-
end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) ->
call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config],
'$ct_no_change');
-
end_tc(Mod, {end_per_group, GroupName, Opts}, Config, Result, _Return) ->
Res = call(fun call_generic/3, Result,
[post_end_per_group, GroupName, Config], '$ct_no_change'),
maybe_stop_locker(Mod, GroupName,Opts),
Res;
-
end_tc(_Mod, TC, Config, Result, _Return) ->
call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config],
'$ct_no_change').
@@ -178,8 +171,9 @@ call_generic(#ct_hook_config{ module = Mod, state = State} = Hook,
call(Fun, Config, Meta) ->
maybe_lock(),
Hooks = get_hooks(),
- Res = call(get_new_hooks(Config, Fun) ++
- [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks],
+ Calls = get_new_hooks(Config, Fun) ++
+ [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks],
+ Res = call(resort(Calls,Hooks,Meta),
remove(?config_name,Config), Meta, Hooks),
maybe_unlock(),
Res.
@@ -198,14 +192,14 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
case lists:keyfind(NewId, #ct_hook_config.id, Hooks) of
false when NextFun =:= undefined ->
{Hooks ++ [NewHook],
- [{NewId, call_init} | Rest]};
+ Rest ++ [{NewId, call_init}]};
ExistingHook when is_tuple(ExistingHook) ->
{Hooks, Rest};
_ ->
{Hooks ++ [NewHook],
- [{NewId, call_init}, {NewId,NextFun} | Rest]}
+ Rest ++ [{NewId, call_init}, {NewId,NextFun}]}
end,
- call(resort(NewRest,NewHooks), Config, Meta, NewHooks)
+ call(resort(NewRest,NewHooks,Meta), Config, Meta, NewHooks)
catch Error:Reason ->
Trace = erlang:get_stacktrace(),
ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p",
@@ -221,7 +215,7 @@ call([{HookId, Fun} | Rest], Config, Meta, Hooks) ->
{NewConf, NewHook} = Fun(Hook, Config, Meta),
NewCalls = get_new_hooks(NewConf, Fun),
NewHooks = lists:keyreplace(HookId, #ct_hook_config.id, Hooks, NewHook),
- call(resort(NewCalls ++ Rest,NewHooks), %% Resort if call_init changed prio
+ call(resort(NewCalls ++ Rest,NewHooks,Meta), %% 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} ->
@@ -308,6 +302,18 @@ get_hooks() ->
%% 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.
+%% If we are doing a cleanup call i.e. {post,pre}_end_per_*, all priorities
+%% are reversed. Probably want to make this sorting algorithm pluginable
+%% as some point...
+resort(Calls,Hooks,[F|_R]) when F == post_end_per_testcase;
+ F == pre_end_per_group;
+ F == post_end_per_group;
+ F == pre_end_per_suite;
+ F == post_end_per_suite ->
+ lists:reverse(resort(Calls,Hooks));
+resort(Calls,Hooks,_Meta) ->
+ resort(Calls,Hooks).
+
resort(Calls, Hooks) ->
lists:sort(
fun({_,_,_},_) ->
@@ -347,11 +353,10 @@ pos(Id,[_|Rest],Num) ->
pos(Id,Rest,Num+1).
-
catch_apply(M,F,A, Default) ->
try
apply(M,F,A)
- catch error:Reason ->
+ catch _: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 ->
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index c1523509a5..0b7a8bb075 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,20 +28,25 @@
-module(ct_logs).
--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]).
+-export([init/2, close/2, init_tc/1, end_tc/1]).
+-export([get_log_dir/0, get_log_dir/1]).
+-export([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]).
-export([make_last_run_index/0]).
-export([make_all_suites_index/1,make_all_runs_index/1]).
+-export([get_ts_html_wrapper/4]).
+-export([xhtml/2, locate_priv_file/1, make_relative/1]).
+-export([insert_javascript/1]).
%% Logging stuff directly from testcase
--export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3,
- basic_html/0]).
+-export([tc_log/3, tc_log/4, tc_log_async/3, tc_print/3, tc_print/4,
+ tc_pal/3, tc_pal/4, ct_log/3, basic_html/0]).
%% Simulate logger process for use without ct environment running
-export([simulate/0]).
+-include("ct.hrl").
-include("ct_event.hrl").
-include("ct_util.hrl").
-include_lib("kernel/include/file.hrl").
@@ -75,9 +80,9 @@
%%% started. A new directory named ct_run.&lt;timestamp&gt; is created
%%% and all logs are stored under this directory.</p>
%%%
-init(Mode) ->
+init(Mode, Verbosity) ->
Self = self(),
- Pid = spawn_link(fun() -> logger(Self,Mode) end),
+ Pid = spawn_link(fun() -> logger(Self, Mode, Verbosity) end),
MRef = erlang:monitor(process,Pid),
receive
{started,Pid,Result} ->
@@ -162,7 +167,12 @@ clear_stylesheet(TC) ->
%%%-----------------------------------------------------------------
%%% @spec get_log_dir() -> {ok,Dir} | {error,Reason}
get_log_dir() ->
- call(get_log_dir).
+ call({get_log_dir,false}).
+
+%%%-----------------------------------------------------------------
+%%% @spec get_log_dir(ReturnAbsName) -> {ok,Dir} | {error,Reason}
+get_log_dir(ReturnAbsName) ->
+ call({get_log_dir,ReturnAbsName}).
%%%-----------------------------------------------------------------
%%% make_last_run_index() -> ok
@@ -205,6 +215,7 @@ cast(Msg) ->
%%% <p>This function is called by ct_framework:init_tc/3</p>
init_tc(RefreshLog) ->
call({init_tc,self(),group_leader(),RefreshLog}),
+ io:format(xhtml("", "<br />")),
ok.
%%%-----------------------------------------------------------------
@@ -230,7 +241,7 @@ end_tc(TCPid) ->
%%% activity it is. <code>Format</code> and <code>Args</code> is the
%%% data to log (as in <code>io:format(Format,Args)</code>).</p>
log(Heading,Format,Args) ->
- cast({log,self(),group_leader(),
+ cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
[{int_header(),[log_timestamp(now()),Heading]},
{Format,Args},
{int_footer(),[]}]}),
@@ -252,7 +263,7 @@ log(Heading,Format,Args) ->
%%% @see cont_log/2
%%% @see end_log/0
start_log(Heading) ->
- cast({log,self(),group_leader(),
+ cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
[{int_header(),[log_timestamp(now()),Heading]}]}),
ok.
@@ -267,7 +278,8 @@ cont_log([],[]) ->
ok;
cont_log(Format,Args) ->
maybe_log_timestamp(),
- cast({log,self(),group_leader(),[{Format,Args}]}),
+ cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
+ [{Format,Args}]}),
ok.
%%%-----------------------------------------------------------------
@@ -278,7 +290,8 @@ cont_log(Format,Args) ->
%%% @see start_log/1
%%% @see cont_log/2
end_log() ->
- cast({log,self(),group_leader(),[{int_footer(), []}]}),
+ cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
+ [{int_footer(), []}]}),
ok.
@@ -311,10 +324,16 @@ add_link(Heading,File,Type) ->
[filename:join("log_private",File),Type,File]).
-
%%%-----------------------------------------------------------------
%%% @spec tc_log(Category,Format,Args) -> ok
+%%% @equiv tc_log(Category,?STD_IMPORTANCE,Format,Args)
+tc_log(Category,Format,Args) ->
+ tc_log(Category,?STD_IMPORTANCE,Format,Args).
+
+%%%-----------------------------------------------------------------
+%%% @spec tc_log(Category,Importance,Format,Args) -> ok
%%% Category = atom()
+%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%%
@@ -323,41 +342,96 @@ add_link(Heading,File,Type) ->
%%% <p>This function is called by <code>ct</code> when logging
%%% stuff directly from a testcase (i.e. not from within the CT
%%% framework).</p>
-tc_log(Category,Format,Args) ->
- cast({log,self(),group_leader(),[{div_header(Category),[]},
- {Format,Args},
- {div_footer(),[]}]}),
+tc_log(Category,Importance,Format,Args) ->
+ tc_log(Category,Importance,"User",Format,Args).
+
+tc_log(Category,Importance,Printer,Format,Args) ->
+ cast({log,sync,self(),group_leader(),Category,Importance,
+ [{div_header(Category,Printer),[]},
+ {Format,Args},
+ {div_footer(),[]}]}),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% @spec tc_log_async(Category,Format,Args) -> ok
+%%% @equiv tc_log_async(Category,?STD_IMPORTANCE,Format,Args)
+tc_log_async(Category,Format,Args) ->
+ tc_log_async(Category,?STD_IMPORTANCE,Format,Args).
+
+%%%-----------------------------------------------------------------
+%%% @spec tc_log_async(Category,Importance,Format,Args) -> ok
+%%% Category = atom()
+%%% Importance = integer()
+%%% Format = string()
+%%% Args = list()
+%%%
+%%% @doc Internal use only.
+%%%
+%%% <p>This function is used to perform asynchronous printouts
+%%% towards the test server IO handler. This is necessary in order
+%%% to avoid deadlocks when e.g. the hook that handles SASL printouts
+%%% prints to the test case log file at the same time test server
+%%% asks ct_logs for an html wrapper.</p>
+tc_log_async(Category,Importance,Format,Args) ->
+ cast({log,async,self(),group_leader(),Category,Importance,
+ [{div_header(Category),[]},
+ {Format,Args},
+ {div_footer(),[]}]}),
ok.
+%%%-----------------------------------------------------------------
+%%% @spec tc_print(Category,Format,Args)
+%%% @equiv tc_print(Category,?STD_IMPORTANCE,Format,Args)
+tc_print(Category,Format,Args) ->
+ tc_print(Category,?STD_IMPORTANCE,Format,Args).
%%%-----------------------------------------------------------------
-%%% @spec tc_print(Category,Format,Args) -> ok
+%%% @spec tc_print(Category,Importance,Format,Args) -> ok
%%% Category = atom()
+%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%%
%%% @doc Console printout from a testcase.
%%%
%%% <p>This function is called by <code>ct</code> when printing
-%%% stuff a testcase on the user console.</p>
-tc_print(Category,Format,Args) ->
- print_heading(Category),
- io:format(user,Format,Args),
- io:format(user,"\n\n",[]),
- ok.
+%%% stuff from a testcase on the user console.</p>
+tc_print(Category,Importance,Format,Args) ->
+ VLvl = case ct_util:get_testdata({verbosity,Category}) of
+ undefined ->
+ ct_util:get_testdata({verbosity,'$unspecified'});
+ {error,bad_invocation} ->
+ ?MAX_VERBOSITY;
+ Val ->
+ Val
+ end,
+ if Importance >= (100-VLvl) ->
+ Head = get_heading(Category),
+ io:format(user, lists:concat([Head,Format,"\n\n"]), Args),
+ ok;
+ true ->
+ ok
+ end.
-print_heading(default) ->
- io:format(user,
- "----------------------------------------------------\n~s\n",
- [log_timestamp(now())]);
-print_heading(Category) ->
- io:format(user,
- "----------------------------------------------------\n~s ~w\n",
- [log_timestamp(now()),Category]).
+get_heading(default) ->
+ io_lib:format("\n-----------------------------"
+ "-----------------------\n~s\n",
+ [log_timestamp(now())]);
+get_heading(Category) ->
+ io_lib:format("\n-----------------------------"
+ "-----------------------\n~s ~w\n",
+ [log_timestamp(now()),Category]).
%%%-----------------------------------------------------------------
%%% @spec tc_pal(Category,Format,Args) -> ok
+%%% @equiv tc_pal(Category,?STD_IMPORTANCE,Format,Args) -> ok
+tc_pal(Category,Format,Args) ->
+ tc_pal(Category,?STD_IMPORTANCE,Format,Args).
+
+%%%-----------------------------------------------------------------
+%%% @spec tc_pal(Category,Importance,Format,Args) -> ok
%%% Category = atom()
+%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%%
@@ -366,16 +440,17 @@ print_heading(Category) ->
%%% <p>This function is called by <code>ct</code> when logging
%%% stuff directly from a testcase. The info is written both in the
%%% log and on the console.</p>
-tc_pal(Category,Format,Args) ->
- tc_print(Category,Format,Args),
- cast({log,self(),group_leader(),[{div_header(Category),[]},
- {Format,Args},
- {div_footer(),[]}]}),
+tc_pal(Category,Importance,Format,Args) ->
+ tc_print(Category,Importance,Format,Args),
+ cast({log,sync,self(),group_leader(),Category,Importance,
+ [{div_header(Category),[]},
+ {Format,Args},
+ {div_footer(),[]}]}),
ok.
%%%-----------------------------------------------------------------
-%%% @spec tc_pal(Category,Format,Args) -> ok
+%%% @spec ct_pal(Category,Format,Args) -> ok
%%% Category = atom()
%%% Format = string()
%%% Args = list()
@@ -399,8 +474,10 @@ int_footer() ->
"</div>".
div_header(Class) ->
- "<div class=\"" ++ atom_to_list(Class) ++ "\"><b>*** User " ++
- log_timestamp(now()) ++ " ***</b>".
+ div_header(Class,"User").
+div_header(Class,Printer) ->
+ "<div class=\"" ++ atom_to_list(Class) ++ "\"><b>*** " ++ Printer ++
+ " " ++ log_timestamp(now()) ++ " ***</b>".
div_footer() ->
"</div>".
@@ -411,7 +488,7 @@ maybe_log_timestamp() ->
{MS,S,_} ->
ok;
_ ->
- cast({log,self(),group_leader(),
+ cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
[{"<i>~s</i>",[log_timestamp({MS,S,US})]}]})
end.
@@ -432,9 +509,10 @@ log_timestamp({MS,S,US}) ->
orig_GL,
ct_log_fd,
tc_groupleaders,
- stylesheet}).
+ stylesheet,
+ async_print_jobs}).
-logger(Parent,Mode) ->
+logger(Parent, Mode, Verbosity) ->
register(?MODULE,self()),
%%! Below is a temporary workaround for the limitation of
@@ -448,7 +526,6 @@ logger(Parent,Mode) ->
timer:sleep(1000),
Time1 = calendar:local_time(),
Dir1 = make_dirname(Time1),
-
{Time1,Dir1};
false ->
{Time0,Dir0}
@@ -456,8 +533,45 @@ logger(Parent,Mode) ->
%%! <---
file:make_dir(Dir),
+ AbsDir = ?abs(Dir),
+ put(ct_run_dir, AbsDir),
+
+ case basic_html() of
+ true ->
+ put(basic_html, true);
+ BasicHtml ->
+ put(basic_html, BasicHtml),
+ %% copy stylesheet to log dir (both top dir and test run
+ %% dir) so logs are independent of Common Test installation
+ {ok,Cwd} = file:get_cwd(),
+ CTPath = code:lib_dir(common_test),
+ PrivFiles = [?css_default,?jquery_script,?tablesorter_script],
+ PrivFilesSrc = [filename:join(filename:join(CTPath, "priv"), F) ||
+ F <- PrivFiles],
+ PrivFilesDestTop = [filename:join(Cwd, F) || F <- PrivFiles],
+ PrivFilesDestRun = [filename:join(AbsDir, F) || F <- PrivFiles],
+ case copy_priv_files(PrivFilesSrc, PrivFilesDestTop) of
+ {error,Src1,Dest1,Reason1} ->
+ io:format(user, "ERROR! "++
+ "Priv file ~p could not be copied to ~p. "++
+ "Reason: ~p~n",
+ [Src1,Dest1,Reason1]),
+ exit({priv_file_error,Dest1});
+ ok ->
+ case copy_priv_files(PrivFilesSrc, PrivFilesDestRun) of
+ {error,Src2,Dest2,Reason2} ->
+ io:format(user, "ERROR! "++
+ "Priv file ~p could not be copied to ~p. "++
+ "Reason: ~p~n",
+ [Src2,Dest2,Reason2]),
+ exit({priv_file_error,Dest2});
+ ok ->
+ ok
+ end
+ end
+ end,
ct_event:notify(#event{name=start_logging,node=node(),
- data=?abs(Dir)}),
+ data=AbsDir}),
make_all_runs_index(start),
make_all_suites_index(start),
case Mode of
@@ -471,57 +585,83 @@ logger(Parent,Mode) ->
[log_timestamp(now()),"Common Test Logger started"]),
Parent ! {started,self(),{Time,filename:absname("")}},
set_evmgr_gl(CtLogFd),
+
+ %% save verbosity levels in dictionary for fast lookups
+ io:format(CtLogFd, "\nVERBOSITY LEVELS:\n", []),
+ case proplists:get_value('$unspecified', Verbosity) of
+ undefined -> ok;
+ GenLvl -> io:format(CtLogFd, "~-25s~3w~n",
+ ["general level",GenLvl])
+ end,
+ [begin put({verbosity,Cat},VLvl),
+ if Cat == '$unspecified' ->
+ ok;
+ true ->
+ io:format(CtLogFd, "~-25w~3w~n", [Cat,VLvl])
+ end
+ end || {Cat,VLvl} <- Verbosity],
+ io:nl(CtLogFd),
+
logger_loop(#logger_state{parent=Parent,
- log_dir=Dir,
+ log_dir=AbsDir,
start_time=Time,
orig_GL=group_leader(),
ct_log_fd=CtLogFd,
- tc_groupleaders=[]}).
+ tc_groupleaders=[],
+ async_print_jobs=[]}).
+
+copy_priv_files([SrcF | SrcFs], [DestF | DestFs]) ->
+ case file:copy(SrcF, DestF) of
+ {error,Reason} ->
+ {error,SrcF,DestF,Reason};
+ _ ->
+ copy_priv_files(SrcFs, DestFs)
+ end;
+copy_priv_files([], []) ->
+ ok.
logger_loop(State) ->
receive
- {log,Pid,GL,List} ->
- case get_groupleader(Pid,GL,State) of
- {tc_log,TCGL,TCGLs} ->
- case erlang:is_process_alive(TCGL) of
- true ->
- %% we have to build one io-list of all strings
- %% before printing, or other io printouts (made in
- %% parallel) may get printed between this header
- %% and footer
- Fun =
- fun({Str,Args},IoList) ->
- case catch io_lib:format(Str,Args) of
- {'EXIT',_Reason} ->
- Fd = State#logger_state.ct_log_fd,
- io:format(Fd,
- "Logging fails! "
- "Str: ~p, Args: ~p~n",
- [Str,Args]),
- %% stop the testcase, we need
- %% to see the fault
- exit(Pid,{log_printout_error,Str,Args}),
- [];
- IoStr when IoList == [] ->
- [IoStr];
- IoStr ->
- [IoList,"\n",IoStr]
- end
- end,
- io:format(TCGL,"~s",[lists:foldl(Fun,[],List)]),
- logger_loop(State#logger_state{tc_groupleaders=TCGLs});
- false ->
- %% Group leader is dead, so write to the CtLog instead
- Fd = State#logger_state.ct_log_fd,
- [begin io:format(Fd,Str,Args),io:nl(Fd) end ||
+ {log,SyncOrAsync,Pid,GL,Category,Importance,List} ->
+ VLvl = case Category of
+ ct_internal ->
+ ?MAX_VERBOSITY;
+ _ ->
+ case get({verbosity,Category}) of
+ undefined -> get({verbosity,'$unspecified'});
+ Val -> Val
+ end
+ end,
+ if Importance >= (100-VLvl) ->
+ case get_groupleader(Pid, GL, State) of
+ {tc_log,TCGL,TCGLs} ->
+ case erlang:is_process_alive(TCGL) of
+ true ->
+ State1 = print_to_log(SyncOrAsync, Pid,
+ TCGL, List, State),
+ logger_loop(State1#logger_state{
+ tc_groupleaders = TCGLs});
+ false ->
+ %% Group leader is dead, so write to the
+ %% CtLog instead
+ Fd = State#logger_state.ct_log_fd,
+ [begin io:format(Fd,Str,Args),
+ io:nl(Fd) end || {Str,Args} <- List],
+ logger_loop(State)
+ end;
+ {ct_log,Fd,TCGLs} ->
+ [begin io:format(Fd,Str,Args),io:nl(Fd) end ||
{Str,Args} <- List],
- logger_loop(State)
+ logger_loop(State#logger_state{
+ tc_groupleaders = TCGLs})
end;
- {ct_log,Fd,TCGLs} ->
- [begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List],
- logger_loop(State#logger_state{tc_groupleaders=TCGLs})
- end;
+ true ->
+ logger_loop(State)
+ end;
{{init_tc,TCPid,GL,RefreshLog},From} ->
+ %% make sure no IO for this test case from the
+ %% CT logger gets rejected
+ test_server:permit_io(GL, self()),
print_style(GL, State#logger_state.stylesheet),
set_evmgr_gl(GL),
TCGLs = add_tc_gl(TCPid,GL,State),
@@ -531,33 +671,51 @@ logger_loop(State) ->
make_last_run_index(State#logger_state.start_time)
end,
return(From,ok),
- logger_loop(State#logger_state{tc_groupleaders=TCGLs});
+ logger_loop(State#logger_state{tc_groupleaders = TCGLs});
{{end_tc,TCPid},From} ->
set_evmgr_gl(State#logger_state.ct_log_fd),
return(From,ok),
- logger_loop(State#logger_state{tc_groupleaders=rm_tc_gl(TCPid,State)});
- {get_log_dir,From} ->
+ logger_loop(State#logger_state{tc_groupleaders =
+ rm_tc_gl(TCPid,State)});
+ {{get_log_dir,true},From} ->
return(From,{ok,State#logger_state.log_dir}),
logger_loop(State);
+ {{get_log_dir,false},From} ->
+ return(From,{ok,filename:basename(State#logger_state.log_dir)}),
+ logger_loop(State);
{make_last_run_index,From} ->
make_last_run_index(State#logger_state.start_time),
- return(From,State#logger_state.log_dir),
+ return(From,filename:basename(State#logger_state.log_dir)),
logger_loop(State);
- {set_stylesheet,_,SSFile} when State#logger_state.stylesheet == SSFile ->
+ {set_stylesheet,_,SSFile} when State#logger_state.stylesheet ==
+ SSFile ->
logger_loop(State);
{set_stylesheet,TC,SSFile} ->
Fd = State#logger_state.ct_log_fd,
- io:format(Fd, "~p loading external style sheet: ~s~n", [TC,SSFile]),
- logger_loop(State#logger_state{stylesheet=SSFile});
+ io:format(Fd, "~p loading external style sheet: ~s~n",
+ [TC,SSFile]),
+ logger_loop(State#logger_state{stylesheet = SSFile});
{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);
+ {'DOWN',Ref,_,_Pid,_} ->
+ %% there might be print jobs executing in parallel with ct_logs
+ %% and whenever one is finished (indicated by 'DOWN'), the
+ %% next job should be spawned
+ case lists:delete(Ref, State#logger_state.async_print_jobs) of
+ [] ->
+ logger_loop(State#logger_state{async_print_jobs = []});
+ Jobs ->
+ [Next|JobsRev] = lists:reverse(Jobs),
+ Jobs1 = [print_next(Next)|lists:reverse(JobsRev)],
+ logger_loop(State#logger_state{async_print_jobs = Jobs1})
+ end;
stop ->
io:format(State#logger_state.ct_log_fd,
int_header()++int_footer(),
@@ -566,6 +724,60 @@ logger_loop(State) ->
ok
end.
+create_io_fun(FromPid, State) ->
+ %% we have to build one io-list of all strings
+ %% before printing, or other io printouts (made in
+ %% parallel) may get printed between this header
+ %% and footer
+ Fd = State#logger_state.ct_log_fd,
+ fun({Str,Args}, IoList) ->
+ case catch io_lib:format(Str,Args) of
+ {'EXIT',_Reason} ->
+ io:format(Fd, "Logging fails! Str: ~p, Args: ~p~n",
+ [Str,Args]),
+ %% stop the testcase, we need to see the fault
+ exit(FromPid, {log_printout_error,Str,Args}),
+ [];
+ IoStr when IoList == [] ->
+ [IoStr];
+ IoStr ->
+ [IoList,"\n",IoStr]
+ end
+ end.
+
+print_to_log(sync, FromPid, TCGL, List, State) ->
+ IoFun = create_io_fun(FromPid, State),
+ %% in some situations (exceptions), the printout is made from the
+ %% test server IO process and there's no valid group leader to send to
+ IoProc = if FromPid /= TCGL -> TCGL;
+ true -> State#logger_state.ct_log_fd
+ end,
+ io:format(IoProc, "~s", [lists:foldl(IoFun, [], List)]),
+ State;
+
+print_to_log(async, FromPid, TCGL, List, State) ->
+ IoFun = create_io_fun(FromPid, State),
+ %% in some situations (exceptions), the printout is made from the
+ %% test server IO process and there's no valid group leader to send to
+ IoProc = if FromPid /= TCGL -> TCGL;
+ true -> State#logger_state.ct_log_fd
+ end,
+ Printer = fun() ->
+ test_server:permit_io(IoProc, self()),
+ io:format(IoProc, "~s", [lists:foldl(IoFun, [], List)])
+ end,
+ case State#logger_state.async_print_jobs of
+ [] ->
+ {_Pid,Ref} = spawn_monitor(Printer),
+ State#logger_state{async_print_jobs = [Ref]};
+ Queue ->
+ State#logger_state{async_print_jobs = [Printer|Queue]}
+ end.
+
+print_next(PrintFun) ->
+ {_Pid,Ref} = spawn_monitor(PrintFun),
+ Ref.
+
%% #logger_state.tc_groupleaders == [{Pid,{Type,GLPid}},...]
%% Type = tc | io
%%
@@ -657,7 +869,7 @@ set_evmgr_gl(GL) ->
open_ctlog() ->
{ok,Fd} = file:open(?ct_log_name,[write]),
- io:format(Fd,header("Common Test Framework"),[]),
+ io:format(Fd, header("Common Test Framework Log", {[],[1,2],[]}), []),
case file:consult(ct_run:variables_file_name("../")) of
{ok,Vars} ->
io:format(Fd, config_table(Vars), []);
@@ -672,17 +884,22 @@ open_ctlog() ->
end,
print_style(Fd,undefined),
io:format(Fd,
- "<br><br><h2>Progress Log</h2>\n"
- "<pre>\n",[]),
+ xhtml("<br><br><h2>Progress Log</h2>\n<pre>\n",
+ "<br /><br /><h4>PROGRESS LOG</h4>\n<pre>\n"), []),
Fd.
print_style(Fd,undefined) ->
- io:format(Fd,
- "<style>\n"
- "div.ct_internal { background:lightgrey; color:black }\n"
- "div.default { background:lightgreen; color:black }\n"
- "</style>\n",
- []);
+ case basic_html() of
+ true ->
+ io:format(Fd,
+ "<style>\n"
+ "div.ct_internal { background:lightgrey; color:black; }\n"
+ "div.default { background:lightgreen; color:black; }\n"
+ "</style>\n",
+ []);
+ _ ->
+ ok
+ end;
print_style(Fd,StyleSheet) ->
case file:read_file(StyleSheet) of
@@ -692,20 +909,19 @@ print_style(Fd,StyleSheet) ->
0 -> string:str(Str,"<STYLE>");
N0 -> N0
end,
- case Pos0 of
- 0 -> print_style_error(Fd,StyleSheet,missing_style_tag);
- _ ->
- Pos1 = case string:str(Str,"</style>") of
- 0 -> string:str(Str,"</STYLE>");
- N1 -> N1
- end,
- case Pos1 of
- 0 ->
- print_style_error(Fd,StyleSheet,missing_style_end_tag);
- _ ->
- Style = string:sub_string(Str,Pos0,Pos1+7),
- io:format(Fd,"~s\n",[Style])
- end
+ Pos1 = case string:str(Str,"</style>") of
+ 0 -> string:str(Str,"</STYLE>");
+ N1 -> N1
+ end,
+ if (Pos0 == 0) and (Pos1 /= 0) ->
+ print_style_error(Fd,StyleSheet,missing_style_start_tag);
+ (Pos0 /= 0) and (Pos1 == 0) ->
+ print_style_error(Fd,StyleSheet,missing_style_end_tag);
+ Pos0 /= 0 ->
+ Style = string:sub_string(Str,Pos0,Pos1+7),
+ io:format(Fd,"~s\n",[Style]);
+ Pos0 == 0 ->
+ io:format(Fd,"<style>~s</style>\n",[Str])
end;
{error,Reason} ->
print_style_error(Fd,StyleSheet,Reason)
@@ -723,7 +939,7 @@ print_style_error(Fd,StyleSheet,Reason) ->
print_style(Fd,undefined).
close_ctlog(Fd) ->
- io:format(Fd,"</pre>",[]),
+ io:format(Fd,"\n</pre>\n",[]),
io:format(Fd,footer(),[]),
file:close(Fd).
@@ -804,33 +1020,48 @@ insert_dir(D,[D1|Ds]) ->
insert_dir(D,[]) ->
[D].
-make_last_run_index([Name|Rest], Result, TotSucc, TotFail, UserSkip, AutoSkip,
- TotNotBuilt, Missing) ->
- case last_test(Name) of
+make_last_run_index([Name|Rest], Result, TotSucc, TotFail,
+ UserSkip, AutoSkip, TotNotBuilt, Missing) ->
+ case get_run_dirs(Name) of
false ->
%% Silently skip.
- make_last_run_index(Rest, Result, TotSucc, TotFail, UserSkip, AutoSkip,
- TotNotBuilt, Missing);
- LastLogDir ->
+ make_last_run_index(Rest, Result, TotSucc, TotFail,
+ UserSkip, AutoSkip, TotNotBuilt, Missing);
+ LogDirs ->
SuiteName = filename:rootname(filename:basename(Name)),
- case make_one_index_entry(SuiteName, LastLogDir, "-", false, Missing) of
- {Result1,Succ,Fail,USkip,ASkip,NotBuilt} ->
- %% for backwards compatibility
- AutoSkip1 = case catch AutoSkip+ASkip of
- {'EXIT',_} -> undefined;
- Res -> Res
- end,
- make_last_run_index(Rest, [Result|Result1], TotSucc+Succ,
- TotFail+Fail, UserSkip+USkip, AutoSkip1,
- TotNotBuilt+NotBuilt, Missing);
- error ->
- make_last_run_index(Rest, Result, TotSucc, TotFail, UserSkip, AutoSkip,
- TotNotBuilt, Missing)
- end
+ {Result1,TotSucc1,TotFail1,UserSkip1,AutoSkip1,TotNotBuilt1} =
+ make_last_run_index1(SuiteName, LogDirs, Result,
+ TotSucc, TotFail,
+ UserSkip, AutoSkip,
+ TotNotBuilt, Missing),
+ make_last_run_index(Rest, Result1, TotSucc1, TotFail1,
+ UserSkip1, AutoSkip1,
+ TotNotBuilt1, Missing)
end;
+
make_last_run_index([], Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, _) ->
{ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, false)],
{TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}}.
+
+make_last_run_index1(SuiteName, [LogDir | LogDirs], Result, TotSucc, TotFail,
+ UserSkip, AutoSkip, TotNotBuilt, Missing) ->
+ case make_one_index_entry(SuiteName, LogDir, "-", false, Missing) of
+ {Result1,Succ,Fail,USkip,ASkip,NotBuilt} ->
+ %% for backwards compatibility
+ AutoSkip1 = case catch AutoSkip+ASkip of
+ {'EXIT',_} -> undefined;
+ Res -> Res
+ end,
+ make_last_run_index1(SuiteName, LogDirs, [Result|Result1], TotSucc+Succ,
+ TotFail+Fail, UserSkip+USkip, AutoSkip1,
+ TotNotBuilt+NotBuilt, Missing);
+ error ->
+ make_last_run_index1(SuiteName, LogDirs, Result, TotSucc, TotFail,
+ UserSkip, AutoSkip, TotNotBuilt, Missing)
+ end;
+make_last_run_index1(_, [], Result, TotSucc, TotFail,
+ UserSkip, AutoSkip, TotNotBuilt, _) ->
+ {Result,TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}.
make_one_index_entry(SuiteName, LogDir, Label, All, Missing) ->
case count_cases(LogDir) of
@@ -854,8 +1085,8 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
CrashDumpName = SuiteName ++ "_erl_crash.dump",
case filelib:is_file(CrashDumpName) of
true ->
- ["&nbsp;<A HREF=\"", CrashDumpName,
- "\">(CrashDump)</A>"];
+ ["&nbsp;<a href=\"", CrashDumpName,
+ "\">(CrashDump)</a>"];
false ->
""
end
@@ -869,32 +1100,41 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
0 -> "-";
_ -> NodeOrDate
end,
- N = ["<TD ALIGN=right><FONT SIZE=-1>",Node1,"</FONT></TD>\n"],
- L = ["<TD ALIGN=center><FONT SIZE=-1><B>",Label,"</FONT></B></TD>\n"],
- T = ["<TD><FONT SIZE=-1>",timestamp(CtRunDir),"</FONT></TD>\n"],
+ TS = timestamp(CtRunDir),
+ N = xhtml(["<td align=right><font size=\"-1\">",Node1,
+ "</font></td>\n"],
+ ["<td align=right>",Node1,"</td>\n"]),
+ L = xhtml(["<td align=center><font size=\"-1\"><b>",Label,
+ "</font></b></td>\n"],
+ ["<td align=center><b>",Label,"</b></td>\n"]),
+ T = xhtml(["<td><font size=\"-1\">",TS,"</font></td>\n"],
+ ["<td>",TS,"</td>\n"]),
CtLogFile = filename:join(CtRunDir,?ct_log_name),
OldRunsLink =
case OldRuns of
[] -> "none";
- _ -> "<A HREF=\""++?all_runs_name++"\">Old Runs</A>"
+ _ -> "<a href=\""++?all_runs_name++"\">Old Runs</a>"
end,
- A=["<TD><FONT SIZE=-1><A HREF=\"",CtLogFile,"\">CT Log</A></FONT></TD>\n",
- "<TD><FONT SIZE=-1>",OldRunsLink,"</FONT></TD>\n"],
+ A = xhtml(["<td><font size=\"-1\"><a href=\"",CtLogFile,
+ "\">CT Log</a></font></td>\n",
+ "<td><font size=\"-1\">",OldRunsLink,"</font></td>\n"],
+ ["<td><a href=\"",CtLogFile,"\">CT Log</a></td>\n",
+ "<td>",OldRunsLink,"</td>\n"]),
{L,T,N,A};
false ->
{"","","",""}
end,
NotBuiltStr =
if NotBuilt == 0 ->
- ["<TD ALIGN=right>",integer_to_list(NotBuilt),"</TD>\n"];
+ ["<td align=right>",integer_to_list(NotBuilt),"</td>\n"];
true ->
- ["<TD ALIGN=right><A HREF=\"",filename:join(CtRunDir,?ct_log_name),"\">",
- integer_to_list(NotBuilt),"</A></TD>\n"]
+ ["<td align=right><a href=\"",filename:join(CtRunDir,?ct_log_name),"\">",
+ integer_to_list(NotBuilt),"</a></td>\n"]
end,
FailStr =
if Fail > 0 ->
- ["<FONT color=\"red\">",
- integer_to_list(Fail),"</FONT>"];
+ ["<font color=\"red\">",
+ integer_to_list(Fail),"</font>"];
true ->
integer_to_list(Fail)
end,
@@ -902,31 +1142,33 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
if AutoSkip == undefined -> {UserSkip,"?","?"};
true ->
ASStr = if AutoSkip > 0 ->
- ["<FONT color=\"brown\">",
- integer_to_list(AutoSkip),"</FONT>"];
+ ["<font color=\"brown\">",
+ integer_to_list(AutoSkip),"</font>"];
true -> integer_to_list(AutoSkip)
end,
{UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr}
end,
- ["<TR valign=top>\n",
- "<TD><FONT SIZE=-1><A HREF=\"",LogFile,"\">",SuiteName,"</A>",CrashDumpLink,"</FONT></TD>\n",
- Lbl,
- Timestamp,
- "<TD ALIGN=right>",integer_to_list(Success),"</TD>\n",
- "<TD ALIGN=right>",FailStr,"</TD>\n",
- "<TD ALIGN=right>",integer_to_list(AllSkip),
- " (",UserSkipStr,"/",AutoSkipStr,")</TD>\n",
- NotBuiltStr,
- Node,
- AllInfo,
- "</TR>\n"].
+ [xhtml("<tr valign=top>\n",
+ ["<tr class=\"",odd_or_even(),"\">\n"]),
+ xhtml("<td><font size=\"-1\"><a href=\"", "<td><a href=\""),
+ LogFile,"\">",SuiteName,"</a>", CrashDumpLink,
+ xhtml("</font></td>\n", "</td>\n"),
+ Lbl, Timestamp,
+ "<td align=right>",integer_to_list(Success),"</td>\n",
+ "<td align=right>",FailStr,"</td>\n",
+ "<td align=right>",integer_to_list(AllSkip),
+ " (",UserSkipStr,"/",AutoSkipStr,")</td>\n",
+ NotBuiltStr, Node, AllInfo, "</tr>\n"].
+
total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) ->
{Label,TimestampCell,AllInfo} =
case All of
true ->
- {"<TD>&nbsp;</TD>\n",
- "<TD>&nbsp;</TD>\n",
- "<TD>&nbsp;</TD>\n<TD>&nbsp;</TD>\n"};
+ {"<td>&nbsp;</td>\n",
+ "<td>&nbsp;</td>\n",
+ "<td>&nbsp;</td>\n"
+ "<td>&nbsp;</td>\n"
+ "<td>&nbsp;</td>\n"};
false ->
{"","",""}
end,
@@ -936,17 +1178,15 @@ total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) ->
true -> {UserSkip+AutoSkip,
integer_to_list(UserSkip),integer_to_list(AutoSkip)}
end,
- ["<TR valign=top>\n",
- "<TD><B>Total</B></TD>",
- Label,
- TimestampCell,
- "<TD ALIGN=right><B>",integer_to_list(Success),"<B></TD>\n",
- "<TD ALIGN=right><B>",integer_to_list(Fail),"<B></TD>\n",
- "<TD ALIGN=right>",integer_to_list(AllSkip),
- " (",UserSkipStr,"/",AutoSkipStr,")</TD>\n",
- "<TD ALIGN=right><B>",integer_to_list(NotBuilt),"<B></TD>\n",
- AllInfo,
- "</TR>\n"].
+ [xhtml("<tr valign=top>\n",
+ ["</tbody>\n<tfoot>\n<tr class=\"",odd_or_even(),"\">\n"]),
+ "<td><b>Total</b></td>\n", Label, TimestampCell,
+ "<td align=right><b>",integer_to_list(Success),"<b></td>\n",
+ "<td align=right><b>",integer_to_list(Fail),"<b></td>\n",
+ "<td align=right>",integer_to_list(AllSkip),
+ " (",UserSkipStr,"/",AutoSkipStr,")</td>\n",
+ "<td align=right><b>",integer_to_list(NotBuilt),"<b></td>\n",
+ AllInfo, "</tr>\n</tfoot>\n"].
not_built(_BaseName,_LogDir,_All,[]) ->
0;
@@ -1003,24 +1243,34 @@ index_header(Label, StartTime) ->
Head =
case Label of
undefined ->
- header("Test Results", format_time(StartTime));
+ header("Test Results", format_time(StartTime),
+ {[],[1],[2,3,4,5]});
_ ->
- header("Test Results for \"" ++ Label ++ "\"",
- format_time(StartTime))
+ header("Test Results for '" ++ Label ++ "'",
+ format_time(StartTime),
+ {[],[1],[2,3,4,5]})
end,
[Head |
- ["<CENTER>\n",
- "<P><A HREF=\"",?ct_log_name,"\">Common Test Framework Log</A></P>",
- "<TABLE border=\"3\" cellpadding=\"5\" "
- "BGCOLOR=\"",?table_color3,"\">\n"
- "<th><B>Test Name</B></th>\n",
- "<th><font color=\"",?table_color3,"\">_</font>Ok"
- "<font color=\"",?table_color3,"\">_</font></th>\n"
+ ["<center>\n",
+ xhtml(["<p><a href=\"",?ct_log_name,
+ "\">Common Test Framework Log</a></p>"],
+ ["<br />"
+ "<div id=\"button_holder\" class=\"btn\">\n"
+ "<a href=\"",?ct_log_name,
+ "\">COMMON TEST FRAMEWORK LOG</a>\n</div>"]),
+ xhtml("<br>\n", "<br /><br /><br />\n"),
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color3,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
+ "<th><b>Test Name</b></th>\n",
+ xhtml(["<th><font color=\"",?table_color3,"\">_</font>Ok"
+ "<font color=\"",?table_color3,"\">_</font></th>\n"],
+ "<th>Ok</th>\n"),
"<th>Failed</th>\n",
- "<th>Skipped<br>(User/Auto)</th>\n"
- "<th>Missing<br>Suites</th>\n"
- "\n"]].
-
+ "<th>Skipped", xhtml("<br>", "<br />"), "(User/Auto)</th>\n"
+ "<th>Missing", xhtml("<br>", "<br />"), "Suites</th>\n",
+ xhtml("", "</tr>\n</thead>\n<tbody>\n")]].
all_suites_index_header() ->
{ok,Cwd} = file:get_cwd(),
@@ -1028,114 +1278,148 @@ all_suites_index_header() ->
all_suites_index_header(IndexDir) ->
LogDir = filename:basename(IndexDir),
- AllRuns = "All test runs in \"" ++ LogDir ++ "\"",
- [header("Test Results") |
- ["<CENTER>\n",
- "<A HREF=\"",?all_runs_name,"\">",AllRuns,"</A>\n",
- "<br><br>\n",
- "<TABLE border=\"3\" cellpadding=\"5\" "
- "BGCOLOR=\"",?table_color2,"\">\n"
+ AllRuns = xhtml(["All test runs in \"" ++ LogDir ++ "\""],
+ "ALL RUNS"),
+ AllRunsLink = xhtml(["<a href=\"",?all_runs_name,"\">",AllRuns,"</a>\n"],
+ ["<div id=\"button_holder\" class=\"btn\">\n"
+ "<a href=\"",?all_runs_name,"\">",AllRuns,"</a>\n</div>"]),
+ [header("Test Results", {[3],[1,2,8,9,10],[4,5,6,7]}) |
+ ["<center>\n",
+ AllRunsLink,
+ xhtml("<br><br>\n", "<br /><br />\n"),
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color2,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
"<th>Test Name</th>\n",
"<th>Label</th>\n",
"<th>Test Run Started</th>\n",
- "<th><font color=\"",?table_color2,"\">_</font>Ok"
- "<font color=\"",?table_color2,"\">_</font></th>\n"
+ xhtml(["<th><font color=\"",?table_color2,"\">_</font>Ok"
+ "<font color=\"",?table_color2,"\">_</font></th>\n"],
+ "<th>Ok</th>\n"),
"<th>Failed</th>\n",
"<th>Skipped<br>(User/Auto)</th>\n"
"<th>Missing<br>Suites</th>\n"
"<th>Node</th>\n",
"<th>CT Log</th>\n",
"<th>Old Runs</th>\n",
- "\n"]].
+ xhtml("", "</tr>\n</thead>\n<tbody>\n")]].
all_runs_header() ->
{ok,Cwd} = file:get_cwd(),
LogDir = filename:basename(Cwd),
Title = "All test runs in \"" ++ LogDir ++ "\"",
- [header(Title) |
- ["<CENTER><TABLE border=\"3\" cellpadding=\"5\" "
- "BGCOLOR=\"",?table_color1,"\">\n"
- "<th><B>History</B></th>\n"
- "<th><B>Node</B></th>\n"
- "<th><B>Label</B></th>\n"
+ IxLink = [xhtml(["<p><a href=\"",?index_name,
+ "\">Test Index Page</a></p>"],
+ ["<div id=\"button_holder\" class=\"btn\">\n"
+ "<a href=\"",?index_name,
+ "\">TEST INDEX PAGE</a>\n</div>"]),
+ xhtml("<br>\n", "<br /><br />\n")],
+ [header(Title, {[1],[2,3,5],[4,6,7,8,9,10]}) |
+ ["<center>\n", IxLink,
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color1,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
+ "<th><b>History</b></th>\n"
+ "<th><b>Node</b></th>\n"
+ "<th><b>Label</b></th>\n"
"<th>Tests</th>\n"
- "<th><B>Test Names</B></th>\n"
- "<th>Total</th>\n"
- "<th><font color=\"",?table_color1,"\">_</font>Ok"
- "<font color=\"",?table_color1,"\">_</font></th>\n"
+ "<th><b>Test Names</b></th>\n"
+ "<th>Total</th>\n",
+ xhtml(["<th><font color=\"",?table_color1,"\">_</font>Ok"
+ "<font color=\"",?table_color1,"\">_</font></th>\n"],
+ "<th>Ok</th>\n"),
"<th>Failed</th>\n"
"<th>Skipped<br>(User/Auto)</th>\n"
- "<th>Missing<br>Suites</th>\n"
- "\n"]].
+ "<th>Missing<br>Suites</th>\n",
+ xhtml("", "</tr>\n</thead>\n<tbody>\n")]].
-header(Title) ->
- header1(Title, "").
-header(Title, SubTitle) ->
- header1(Title, SubTitle).
+header(Title, TableCols) ->
+ header1(Title, "", TableCols).
+header(Title, SubTitle, TableCols) ->
+ header1(Title, SubTitle, TableCols).
-header1(Title, SubTitle) ->
+header1(Title, SubTitle, TableCols) ->
SubTitleHTML = if SubTitle =/= "" ->
- ["<CENTER>\n",
- "<H2>" ++ SubTitle ++ "</H2>\n",
- "</CENTER>\n<BR>\n"];
- true -> "<BR>\n"
+ ["<center>\n",
+ "<h3>" ++ SubTitle ++ "</h3>\n",
+ xhtml("</center>\n<br>\n", "</center>\n<br />\n")];
+ true -> xhtml("<br>", "<br />")
end,
- ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
- "<HTML>\n",
- "<HEAD>\n",
-
- "<TITLE>" ++ Title ++ " " ++ SubTitle ++ "</TITLE>\n",
- "<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\">\n",
-
- "</HEAD>\n",
-
+ CSSFile = xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?css_default)) end),
+ JQueryFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?jquery_script)) end),
+ TableSorterFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?tablesorter_script)) end),
+ [xhtml(["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<html>\n"],
+ ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n",
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n",
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]),
+ "<!-- autogenerated by '"++atom_to_list(?MODULE)++"' -->\n",
+ "<head>\n",
+ "<title>" ++ Title ++ " " ++ SubTitle ++ "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ xhtml("",
+ ["<link rel=\"stylesheet\" href=\"",CSSFile,"\" type=\"text/css\">\n"]),
+ xhtml("",
+ ["<script type=\"text/javascript\" src=\"",JQueryFile,
+ "\"></script>\n"]),
+ xhtml("",
+ ["<script type=\"text/javascript\" src=\"",TableSorterFile,
+ "\"></script>\n"]),
+ xhtml(fun() -> "" end,
+ fun() -> insert_javascript({tablesorter,?sortable_table_name,
+ TableCols})
+ end),
+ "</head>\n",
body_tag(),
-
- "<!-- ---- DOCUMENT TITLE ---- -->\n",
-
- "<CENTER>\n",
- "<H1>" ++ Title ++ "</H1>\n",
- "</CENTER>\n",
- SubTitleHTML,
-
- "<!-- ---- CONTENT ---- -->\n"].
+ "<center>\n",
+ "<h1>" ++ Title ++ "</h1>\n",
+ "</center>\n",
+ SubTitleHTML,"\n"].
index_footer() ->
- ["</TABLE>\n"
- "</CENTER>\n" | footer()].
+ ["</table>\n"
+ "</center>\n" | footer()].
+
+all_runs_index_footer() ->
+ ["</tbody>\n</table>\n"
+ "</center>\n" | footer()].
footer() ->
- ["<P><CENTER>\n"
- "<BR><BR>\n"
- "<HR>\n"
- "<P><FONT SIZE=-1>\n"
+ ["<center>\n",
+ xhtml("<br><br>\n<hr>\n", "<br /><br />\n"),
+ xhtml("<p><font size=\"-1\">\n", "<div class=\"copyright\">"),
"Copyright &copy; ", year(),
- " <A HREF=\"http://erlang.ericsson.se\">Open Telecom Platform</A><BR>\n"
- "Updated: <!date>", current_time(), "<!/date><BR>\n"
- "</FONT>\n"
- "</CENTER>\n"
- "</body>\n"].
+ " <a href=\"http://www.erlang.org\">Open Telecom Platform</a>",
+ xhtml("<br>\n", "<br />\n"),
+ "Updated: <!date>", current_time(), "<!/date>",
+ xhtml("<br>\n", "<br />\n"),
+ xhtml("</font></p>\n", "</div>\n"),
+ "</center>\n"
+ "</body>\n"
+ "</html>\n"].
body_tag() ->
- case basic_html() of
- true ->
- "<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" "
- "vlink=\"#800080\" alink=\"#FF0000\">\n";
- false ->
- CTPath = code:lib_dir(common_test),
- TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"),
- "<body background=\"" ++ TileFile ++ "\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" "
- "vlink=\"#800080\" alink=\"#FF0000\">\n"
- end.
+ CTPath = code:lib_dir(common_test),
+ TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"),
+ xhtml("<body background=\"" ++ TileFile ++
+ "\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" "
+ "vlink=\"#800080\" alink=\"#FF0000\">\n",
+ "<body>\n").
current_time() ->
format_time(calendar:local_time()).
format_time({{Y, Mon, D}, {H, Min, S}}) ->
Weekday = weekday(calendar:day_of_the_week(Y, Mon, D)),
- lists:flatten(io_lib:format("~s ~s ~p ~w ~2.2.0w:~2.2.0w:~2.2.0w",
+ lists:flatten(io_lib:format("~s ~s ~2.2.0w ~w ~2.2.0w:~2.2.0w:~2.2.0w",
[Weekday, month(Mon), D, Y, H, Min, S])).
weekday(1) -> "Mon";
@@ -1258,20 +1542,29 @@ config_table(Vars) ->
[config_table_header()|config_table1(Vars)].
config_table_header() ->
- ["<h2>Configuration</h2>\n",
- "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color1,
- "\"\n",
- "<tr><th>Key</th><th>Value</th></tr>\n"].
+ [
+ xhtml(["<h2>Configuration</h2>\n"
+ "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color1,"\"\n"],
+ ["<h4>CONFIGURATION</h4>\n",
+ "<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n"]),
+ "<tr><th>Key</th><th>Value</th></tr>\n",
+ xhtml("", "</thead>\n<tbody>\n")
+ ].
config_table1([{Key,Value}|Vars]) ->
- ["<tr><td>", atom_to_list(Key), "</td>\n",
- "<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n" |
+ [xhtml(["<tr><td>", atom_to_list(Key), "</td>\n",
+ "<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n"],
+ ["<tr class=\"", odd_or_even(), "\">\n",
+ "<td>", atom_to_list(Key), "</td>\n",
+ "<td>", io_lib:format("~p",[Value]), "</td>\n</tr>\n"]) |
config_table1(Vars)];
config_table1([]) ->
- ["</table>\n"].
+ ["</tbody>\n</table>\n"].
make_all_runs_index(When) ->
+ put(basic_html, basic_html()),
AbsName = ?abs(?all_runs_name),
notify_and_lock_file(AbsName),
if When == start -> ok;
@@ -1280,9 +1573,9 @@ make_all_runs_index(When) ->
Dirs = filelib:wildcard(logdir_prefix()++"*.*"),
DirsSorted = (catch sort_all_runs(Dirs)),
Header = all_runs_header(),
- BasicHtml = basic_html(),
- Index = [runentry(Dir, BasicHtml) || Dir <- DirsSorted],
- Result = file:write_file(AbsName,Header++Index++index_footer()),
+ Index = [runentry(Dir) || Dir <- DirsSorted],
+ Result = file:write_file(AbsName,Header++Index++
+ all_runs_index_footer()),
if When == start -> ok;
true -> io:put_chars("done\n")
end,
@@ -1309,22 +1602,22 @@ sort_all_runs(Dirs) ->
interactive_link() ->
[Dir|_] = lists:reverse(filelib:wildcard(logdir_prefix()++"*.*")),
CtLog = filename:join(Dir,"ctlog.html"),
- Body = ["Log from last interactive run: <A HREF=\"",CtLog,"\">",
- timestamp(Dir),"</A>"],
+ Body = ["Log from last interactive run: <a href=\"",CtLog,"\">",
+ timestamp(Dir),"</a>"],
file:write_file("last_interactive.html",Body),
io:format("~n~nUpdated ~s\n"
"Any CT activities will be logged here\n",
[?abs("last_interactive.html")]).
-runentry(Dir, BasicHtml) ->
+runentry(Dir) ->
TotalsFile = filename:join(Dir,?totals_name),
TotalsStr =
case read_totals_file(TotalsFile) of
{Node,Label,Logs,{TotSucc,TotFail,UserSkip,AutoSkip,NotBuilt}} ->
TotFailStr =
if TotFail > 0 ->
- ["<FONT color=\"red\">",
- integer_to_list(TotFail),"</FONT>"];
+ ["<font color=\"red\">",
+ integer_to_list(TotFail),"</font>"];
true ->
integer_to_list(TotFail)
end,
@@ -1332,8 +1625,8 @@ runentry(Dir, BasicHtml) ->
if AutoSkip == undefined -> {UserSkip,"?","?"};
true ->
ASStr = if AutoSkip > 0 ->
- ["<FONT color=\"brown\">",
- integer_to_list(AutoSkip),"</FONT>"];
+ ["<font color=\"brown\">",
+ integer_to_list(AutoSkip),"</font>"];
true -> integer_to_list(AutoSkip)
end,
{UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr}
@@ -1365,30 +1658,49 @@ runentry(Dir, BasicHtml) ->
lists:flatten(io_lib:format("~s...",[Trunc]))
end,
Total = TotSucc+TotFail+AllSkip,
- A = ["<TD ALIGN=center><FONT SIZE=-1>",Node,"</FONT></TD>\n",
- "<TD ALIGN=center><FONT SIZE=-1><B>",Label,"</B></FONT></TD>\n",
- "<TD ALIGN=right>",NoOfTests,"</TD>\n"],
- B = if BasicHtml ->
- ["<TD ALIGN=center><FONT SIZE=-1>",TestNamesTrunc,"</FONT></TD>\n"];
- true ->
- ["<TD ALIGN=center TITLE='",TestNames,"'><FONT SIZE=-1> ",
- TestNamesTrunc,"</FONT></TD>\n"]
- end,
- C = ["<TD ALIGN=right>",integer_to_list(Total),"</TD>\n",
- "<TD ALIGN=right>",integer_to_list(TotSucc),"</TD>\n",
- "<TD ALIGN=right>",TotFailStr,"</TD>\n",
- "<TD ALIGN=right>",integer_to_list(AllSkip),
- " (",UserSkipStr,"/",AutoSkipStr,")</TD>\n",
- "<TD ALIGN=right>",integer_to_list(NotBuilt),"</TD>\n"],
+ A = xhtml(["<td align=center><font size=\"-1\">",Node,
+ "</font></td>\n",
+ "<td align=center><font size=\"-1\"><b>",Label,
+ "</b></font></td>\n",
+ "<td align=right>",NoOfTests,"</td>\n"],
+ ["<td align=center>",Node,"</td>\n",
+ "<td align=center><b>",Label,"</b></td>\n",
+ "<td align=right>",NoOfTests,"</td>\n"]),
+ B = xhtml(["<td align=center title='",TestNames,"'><font size=\"-1\"> ",
+ TestNamesTrunc,"</font></td>\n"],
+ ["<td align=center title='",TestNames,"'> ",
+ TestNamesTrunc,"</td>\n"]),
+ C = ["<td align=right>",integer_to_list(Total),"</td>\n",
+ "<td align=right>",integer_to_list(TotSucc),"</td>\n",
+ "<td align=right>",TotFailStr,"</td>\n",
+ "<td align=right>",integer_to_list(AllSkip),
+ " (",UserSkipStr,"/",AutoSkipStr,")</td>\n",
+ "<td align=right>",integer_to_list(NotBuilt),"</td>\n"],
A++B++C;
_ ->
- ["<TD ALIGN=center><FONT size=-1 color=\"red\">",
- "Test data missing or corrupt","</FONT></TD>\n"]
+ A = xhtml(["<td align=center><font size=\"-1\" color=\"red\">"
+ "Test data missing or corrupt</font></td>\n",
+ "<td align=center><font size=\"-1\">?</font></td>\n",
+ "<td align=right>?</td>\n"],
+ ["<td align=center><font color=\"red\">"
+ "Test data missing or corrupt</font></td>\n",
+ "<td align=center>?</td>\n",
+ "<td align=right>?</td>\n"]),
+ B = xhtml(["<td align=center><font size=\"-1\">?</font></td>\n"],
+ ["<td align=center>?</td>\n"]),
+ C = ["<td align=right>?</td>\n",
+ "<td align=right>?</td>\n",
+ "<td align=right>?</td>\n",
+ "<td align=right>?</td>\n",
+ "<td align=right>?</td>\n"],
+ A++B++C
end,
Index = filename:join(Dir,?index_name),
- ["<TR>\n"
- "<TD><FONT SIZE=-1><A HREF=\"",Index,"\">",timestamp(Dir),"</A>",TotalsStr,"</FONT></TD>\n"
- "</TR>\n"].
+ [xhtml("<tr>\n", ["<tr class=\"",odd_or_even(),"\">\n"]),
+ xhtml(["<td><font size=\"-1\"><a href=\"",Index,"\">",timestamp(Dir),"</a>",
+ TotalsStr,"</font></td>\n"],
+ ["<td><a href=\"",Index,"\">",timestamp(Dir),"</a>",TotalsStr,"</td>\n"]),
+ "</tr>\n"].
write_totals_file(Name,Label,Logs,Totals) ->
AbsName = ?abs(Name),
@@ -1482,6 +1794,7 @@ timestamp(Dir) ->
%% 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) ->
+ put(basic_html, basic_html()),
AbsIndexName = ?abs(?index_name),
notify_and_lock_file(AbsIndexName),
LogDirs = filelib:wildcard(logdir_prefix()++".*/*"++?logdir_ext),
@@ -1493,6 +1806,7 @@ make_all_suites_index(When) when is_atom(When) ->
%% This updates the top level index file using cached data from
%% the initial index file creation.
make_all_suites_index(NewTestData = {_TestName,DirName}) ->
+ put(basic_html, basic_html()),
%% AllLogDirs = [{TestName,Label,Missing,{LastLogDir,Summary},OldDirs}|...]
{AbsIndexName,LogDirData} = ct_util:get_testdata(test_index),
@@ -1533,8 +1847,8 @@ make_all_suites_index(NewTestData = {_TestName,DirName}) ->
sort_logdirs([Dir|Dirs],Groups) ->
TestName = filename:rootname(filename:basename(Dir)),
case filelib:wildcard(filename:join(Dir,"run.*")) of
- [RunDir] ->
- Groups1 = insert_test(TestName,{filename:basename(RunDir),RunDir},Groups),
+ RunDirs = [_|_] ->
+ Groups1 = sort_logdirs1(TestName,RunDirs,Groups),
sort_logdirs(Dirs,Groups1);
_ -> % ignore missing run directory
sort_logdirs(Dirs,Groups)
@@ -1542,6 +1856,12 @@ sort_logdirs([Dir|Dirs],Groups) ->
sort_logdirs([],Groups) ->
lists:keysort(1,sort_each_group(Groups)).
+sort_logdirs1(TestName,[RunDir|RunDirs],Groups) ->
+ Groups1 = insert_test(TestName,{filename:basename(RunDir),RunDir},Groups),
+ sort_logdirs1(TestName,RunDirs,Groups1);
+sort_logdirs1(_,[],Groups) ->
+ Groups.
+
insert_test(Test,IxDir,[{Test,IxDirs}|Groups]) ->
[{Test,[IxDir|IxDirs]}|Groups];
insert_test(Test,IxDir,[]) ->
@@ -1794,7 +2114,7 @@ simulate() ->
simulate_logger_loop() ->
receive
- {log,_,_,List} ->
+ {log,_,_,_,_,_,List} ->
S = [[io_lib:format(Str,Args),io_lib:nl()] || {Str,Args} <- List],
io:format("~s",[S]),
simulate_logger_loop();
@@ -1833,21 +2153,49 @@ notify_and_unlock_file(File) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec last_test(Dir) -> string() | false
+%%% @spec get_run_dirs(Dir) -> [string()] | false
+%%%
+%%% @doc
+%%%
+get_run_dirs(Dir) ->
+ case filelib:wildcard(filename:join(Dir, "run.[1-2]*")) of
+ [] ->
+ false;
+ RunDirs ->
+ lists:sort(RunDirs)
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec xhtml(HTML, XHTML) -> HTML | XHTML
%%%
%%% @doc
%%%
-last_test(Dir) ->
- last_test(filelib:wildcard(filename:join(Dir, "run.[1-2]*")), false).
-
-last_test([Run|Rest], false) ->
- last_test(Rest, Run);
-last_test([Run|Rest], Latest) when Run > Latest ->
- last_test(Rest, Run);
-last_test([_|Rest], Latest) ->
- last_test(Rest, Latest);
-last_test([], Latest) ->
- Latest.
+xhtml(HTML, XHTML) when is_function(HTML),
+ is_function(XHTML) ->
+ case get(basic_html) of
+ true -> HTML();
+ _ -> XHTML()
+ end;
+xhtml(HTML, XHTML) ->
+ case get(basic_html) of
+ true -> HTML;
+ _ -> XHTML
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec odd_or_even() -> "odd" | "even"
+%%%
+%%% @doc
+%%%
+odd_or_even() ->
+ case get(odd_or_even) of
+ even ->
+ put(odd_or_even, odd),
+ "even";
+ _ ->
+ put(odd_or_even, even),
+ "odd"
+ end.
%%%-----------------------------------------------------------------
%%% @spec basic_html() -> true | false
@@ -1861,3 +2209,254 @@ basic_html() ->
_ ->
false
end.
+
+%%%-----------------------------------------------------------------
+%%% @spec locate_priv_file(FileName) -> PrivFile
+%%%
+%%% @doc
+%%%
+locate_priv_file(FileName) ->
+ {ok,CWD} = file:get_cwd(),
+ PrivFileInCwd = filename:join(CWD, FileName),
+ case filelib:is_file(PrivFileInCwd) of
+ true ->
+ PrivFileInCwd;
+ false ->
+ PrivResultFile =
+ case {whereis(?MODULE),self()} of
+ {Self,Self} ->
+ %% executed on the ct_logs process
+ filename:join(get(ct_run_dir), FileName);
+ _ ->
+ %% executed on other process than ct_logs
+ {ok,RunDir} = get_log_dir(true),
+ filename:join(RunDir, FileName)
+ end,
+ case filelib:is_file(PrivResultFile) of
+ true ->
+ PrivResultFile;
+ false ->
+ %% last resort, try use css file in CT installation
+ CTPath = code:lib_dir(common_test),
+ filename:join(filename:join(CTPath, "priv"), FileName)
+ end
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec make_relative(AbsDir, Cwd) -> RelDir
+%%%
+%%% @doc Return directory path to File (last element of AbsDir), which
+%%% is the path relative to Cwd. Examples when Cwd == "/ldisk/test/logs":
+%%% make_relative("/ldisk/test/logs/run/trace.log") -> "run/trace.log"
+%%% make_relative("/ldisk/test/trace.log") -> "../trace.log"
+%%% make_relative("/ldisk/test/logs/trace.log") -> "trace.log"
+make_relative(AbsDir) ->
+ {ok,Cwd} = file:get_cwd(),
+ make_relative(AbsDir, Cwd).
+
+make_relative(AbsDir, Cwd) ->
+ DirTokens = filename:split(AbsDir),
+ CwdTokens = filename:split(Cwd),
+ filename:join(make_relative1(DirTokens, CwdTokens)).
+
+make_relative1([T | DirTs], [T | CwdTs]) ->
+ make_relative1(DirTs, CwdTs);
+make_relative1(Last = [_File], []) ->
+ Last;
+make_relative1(Last = [_File], CwdTs) ->
+ Ups = ["../" || _ <- CwdTs],
+ Ups ++ Last;
+make_relative1(DirTs, []) ->
+ DirTs;
+make_relative1(DirTs, CwdTs) ->
+ Ups = ["../" || _ <- CwdTs],
+ Ups ++ DirTs.
+
+%%%-----------------------------------------------------------------
+%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd) -> {Mode,Header,Footer}
+%%%
+%%% @doc
+%%%
+get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
+ TestName1 = if is_list(TestName) ->
+ lists:flatten(TestName);
+ true ->
+ lists:flatten(io_lib:format("~p", [TestName]))
+ end,
+ Basic = basic_html(),
+ LabelStr =
+ if not PrintLabel ->
+ "";
+ true ->
+ case {Basic,application:get_env(common_test, test_label)} of
+ {true,{ok,Lbl}} when Lbl =/= undefined ->
+ "<h1><font color=\"green\">" ++ Lbl ++ "</font></h1>\n";
+ {_,{ok,Lbl}} when Lbl =/= undefined ->
+ "<div class=\"label\">'" ++ Lbl ++ "'</div>\n";
+ _ ->
+ ""
+ end
+ end,
+ CTPath = code:lib_dir(common_test),
+ {ok,CtLogdir} = get_log_dir(true),
+ AllRuns = make_relative(filename:join(filename:dirname(CtLogdir),
+ ?all_runs_name), Cwd),
+ TestIndex = make_relative(filename:join(filename:dirname(CtLogdir),
+ ?index_name), Cwd),
+ case Basic of
+ true ->
+ TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"),
+ Bgr = " background=\"" ++ TileFile ++ "\"",
+ Copyright =
+ ["<p><font size=\"-1\">\n",
+ "Copyright &copy; ", year(),
+ " <a href=\"http://www.erlang.org\">",
+ "Open Telecom Platform</a><br>\n",
+ "Updated: <!date>", current_time(), "<!/date>",
+ "<br>\n</font></p>\n"],
+ {basic_html,
+ ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<html>\n",
+ "<head><title>", TestName1, "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "</head>\n",
+ "<body", Bgr, " bgcolor=\"white\" text=\"black\" ",
+ "link=\"blue\" vlink=\"purple\" alink=\"red\">\n",
+ LabelStr, "\n"],
+ ["<center>\n<br><hr><p>\n",
+ "<a href=\"", AllRuns,
+ "\">Test run history\n</a> | ",
+ "<a href=\"", TestIndex,
+ "\">Top level test index\n</a>\n</p>\n",
+ Copyright,"</center>\n</body>\n</html>\n"]};
+ _ ->
+ Copyright =
+ ["<div class=\"copyright\">",
+ "Copyright &copy; ", year(),
+ " <a href=\"http://www.erlang.org\">",
+ "Open Telecom Platform</a><br />\n",
+ "Updated: <!date>", current_time(), "<!/date>",
+ "<br />\n</div>\n"],
+ CSSFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?css_default),
+ Cwd)
+ end),
+ JQueryFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?jquery_script),
+ Cwd)
+ end),
+ TableSorterFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?tablesorter_script),
+ Cwd)
+ end),
+ TableSorterScript =
+ xhtml(fun() -> "" end,
+ fun() -> insert_javascript({tablesorter,
+ ?sortable_table_name,
+ TableCols}) end),
+ {xhtml,
+ ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n",
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n",
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n",
+ "<head>\n<title>", TestName1, "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "<link rel=\"stylesheet\" href=\"", CSSFile, "\" type=\"text/css\">\n",
+ "<script type=\"text/javascript\" src=\"", JQueryFile, "\"></script>\n",
+ "<script type=\"text/javascript\" src=\"", TableSorterFile, "\"></script>\n"] ++
+ TableSorterScript ++ ["</head>\n","<body>\n", LabelStr, "\n"],
+ ["<center>\n<br /><hr /><p>\n",
+ "<a href=\"", AllRuns,
+ "\">Test run history\n</a> | ",
+ "<a href=\"", TestIndex,
+ "\">Top level test index\n</a>\n</p>\n",
+ Copyright,"</center>\n</body>\n</html>\n"]}
+ end.
+
+insert_javascript({tablesorter,_TableName,undefined}) ->
+ [];
+
+insert_javascript({tablesorter,TableName,
+ {DateCols,TextCols,ValCols}}) ->
+ Headers =
+ lists:flatten(
+ lists:sort(
+ lists:flatmap(fun({Sorter,Cols}) ->
+ [lists:flatten(
+ io_lib:format(" ~w: "
+ "{ sorter: '~s' },\n",
+ [Col-1,Sorter])) || Col<-Cols]
+ end, [{"CTDateSorter",DateCols},
+ {"CTTextSorter",TextCols},
+ {"CTValSorter",ValCols}]))),
+ Headers1 = string:substr(Headers, 1, length(Headers)-2),
+
+ ["<script type=\"text/javascript\">\n",
+ "// Parser for date format, e.g: Wed Jul 4 2012 11:24:15\n",
+ "var monthNames = {};\n",
+ "monthNames[\"Jan\"] = \"01\"; monthNames[\"Feb\"] = \"02\";\n",
+ "monthNames[\"Mar\"] = \"03\"; monthNames[\"Apr\"] = \"04\";\n",
+ "monthNames[\"May\"] = \"05\"; monthNames[\"Jun\"] = \"06\";\n",
+ "monthNames[\"Jul\"] = \"07\"; monthNames[\"Aug\"] = \"08\";\n",
+ "monthNames[\"Sep\"] = \"09\"; monthNames[\"Oct\"] = \"10\";\n",
+ "monthNames[\"Nov\"] = \"11\"; monthNames[\"Dec\"] = \"12\";\n",
+ "$.tablesorter.addParser({\n",
+ " id: 'CTDateSorter',\n",
+ " is: function(s) {\n",
+ " return false; },\n",
+ " format: function(s) {\n",
+ %% place empty cells, "-" and "?" at the bottom
+ " if (s.length < 2) return 999999999;\n",
+ " else {\n",
+ %% match out each date element
+ " var date = s.match(/(\\w{3})\\s(\\w{3})\\s(\\d{2})\\s(\\d{4})\\s(\\d{2}):(\\d{2}):(\\d{2})/);\n",
+ " var y = date[4]; var mo = monthNames[date[2]]; var d = String(date[3]);\n",
+ " var h = String(date[5]); var mi = String(date[6]); var sec = String(date[7]);\n",
+ " return (parseInt('' + y + mo + d + h + mi + sec)); }},\n",
+ " type: 'numeric' });\n",
+
+ "// Parser for general text format\n",
+ "$.tablesorter.addParser({\n",
+ " id: 'CTTextSorter',\n",
+ " is: function(s) {\n",
+ " return false; },\n",
+ " format: function(s) {\n",
+ %% place empty cells, "?" and "-" at the bottom
+ " if (s.length < 1) return 'zzzzzzzz';\n",
+ " else if (s == \"?\") return 'zzzzzzz';\n",
+ " else if (s == \"-\") return 'zzzzzz';\n",
+ " else if (s == \"FAILED\") return 'A';\n",
+ " else if (s == \"SKIPPED\") return 'B';\n",
+ " else if (s == \"OK\") return 'C';\n",
+ " else return '' + s; },\n",
+ " type: 'text' });\n",
+
+ "// Parser for numerical values\n",
+ "$.tablesorter.addParser({\n",
+ " id: 'CTValSorter',\n",
+ " is: function(s) {\n",
+ " return false; },\n",
+ " format: function(s) {\n"
+ %% place empty cells and "?" at the bottom
+ " if (s.length < 1) return '-2';\n",
+ " else if (s == \"?\") return '-1';\n",
+ %% look for skip value, eg "3 (2/1)"
+ " else if ((s.search(/(\\d{1,})\\s/)) >= 0) {\n",
+ " var num = s.match(/(\\d{1,})\\s/);\n",
+ %% return only the total skip value for sorting
+ " return (parseInt('' + num[1])); }\n",
+ " else if ((s.search(/(\\d{1,})\\.(\\d{3})s/)) >= 0) {\n",
+ " var num = s.match(/(\\d{1,})\\.(\\d{3})/);\n",
+ " if (num[1] == \"0\") return (parseInt('' + num[2]));\n",
+ " else return (parseInt('' + num[1] + num[2])); }\n",
+ " else return '' + s; },\n",
+ " type: 'numeric' });\n",
+
+ "$(document).ready(function() {\n",
+ " $(\"#",TableName,"\").tablesorter({\n",
+ " headers: { \n", Headers1, "\n }\n });\n",
+ " $(\"#",TableName,"\").trigger(\"update\");\n",
+ " $(\"#",TableName,"\").trigger(\"appendCache\");\n",
+ "});\n</script>\n"].
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index 40e9e99f37..8ddb91d355 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -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
diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl
index 2ea2ba106a..042c5ba267 100644
--- a/lib/common_test/src/ct_master.erl
+++ b/lib/common_test/src/ct_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,7 @@
-export([run/1,run/3,run/4]).
-export([run_on_node/2,run_on_node/3]).
-export([run_test/1,run_test/2]).
+-export([basic_html/1]).
-export([abort/0,abort/1,progress/0]).
@@ -277,7 +278,17 @@ abort(Node) when is_atom(Node) ->
progress() ->
call(progress).
-
+%%%-----------------------------------------------------------------
+%%% @spec basic_html(Bool) -> ok
+%%% Bool = true | false
+%%%
+%%% @doc If set to true, the ct_master logs will be written on a
+%%% primitive html format, not using the Common Test CSS style
+%%% sheet.
+basic_html(Bool) ->
+ application:set_env(common_test_master, basic_html, Bool),
+ ok.
+
%%%-----------------------------------------------------------------
%%% MASTER, runs on central controlling node.
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl
index 244faace06..9e61d5b16f 100644
--- a/lib/common_test/src/ct_master_logs.erl
+++ b/lib/common_test/src/ct_master_logs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,10 @@
%%% node.</p>
-module(ct_master_logs).
--export([start/2, make_all_runs_index/0, log/3, nodedir/2, stop/0]).
+-export([start/2, make_all_runs_index/0, log/3, nodedir/2,
+ stop/0]).
+
+-include("ct_util.hrl").
-record(state, {log_fd, start_time, logdir, rundir,
nodedir_ix_fd, nodes, nodedirs=[]}).
@@ -87,6 +90,41 @@ init(Parent,LogDir,Nodes) ->
RunDirAbs = filename:join(LogDir,RunDir),
file:make_dir(RunDirAbs),
write_details_file(RunDirAbs,{node(),Nodes}),
+
+ case basic_html() of
+ true ->
+ put(basic_html, true);
+ BasicHtml ->
+ put(basic_html, BasicHtml),
+ %% copy priv files to log dir (both top dir and test run
+ %% dir) so logs are independent of Common Test installation
+ CTPath = code:lib_dir(common_test),
+ PrivFiles = [?css_default,?jquery_script,?tablesorter_script],
+ PrivFilesSrc = [filename:join(filename:join(CTPath, "priv"), F) ||
+ F <- PrivFiles],
+ PrivFilesDestTop = [filename:join(LogDir, F) || F <- PrivFiles],
+ PrivFilesDestRun = [filename:join(RunDirAbs, F) || F <- PrivFiles],
+ case copy_priv_files(PrivFilesSrc, PrivFilesDestTop) of
+ {error,Src1,Dest1,Reason1} ->
+ io:format(user, "ERROR! "++
+ "Priv file ~p could not be copied to ~p. "++
+ "Reason: ~p~n",
+ [Src1,Dest1,Reason1]),
+ exit({priv_file_error,Dest1});
+ ok ->
+ case copy_priv_files(PrivFilesSrc, PrivFilesDestRun) of
+ {error,Src2,Dest2,Reason2} ->
+ io:format(user, "ERROR! "++
+ "Priv file ~p could not be copied to ~p. "++
+ "Reason: ~p~n",
+ [Src2,Dest2,Reason2]),
+ exit({priv_file_error,Dest2});
+ ok ->
+ ok
+ end
+ end
+ end,
+
make_all_runs_index(LogDir),
CtLogFd = open_ct_master_log(RunDirAbs),
NodeStr =
@@ -110,6 +148,16 @@ init(Parent,LogDir,Nodes) ->
{N,""}
end,Nodes)}).
+copy_priv_files([SrcF | SrcFs], [DestF | DestFs]) ->
+ case file:copy(SrcF, DestF) of
+ {error,Reason} ->
+ {error,SrcF,DestF,Reason};
+ _ ->
+ copy_priv_files(SrcFs, DestFs)
+ end;
+copy_priv_files([], []) ->
+ ok.
+
loop(State) ->
receive
{log,_From,List} ->
@@ -154,7 +202,7 @@ loop(State) ->
open_ct_master_log(Dir) ->
FullName = filename:join(Dir,?ct_master_log_name),
{ok,Fd} = file:open(FullName,[write]),
- io:format(Fd,header("Common Test Master Log"),[]),
+ io:format(Fd,header("Common Test Master Log", {[],[1,2],[]}),[]),
%% maybe add config info here later
io:format(Fd, config_table([]), []),
io:format(Fd,
@@ -164,8 +212,9 @@ open_ct_master_log(Dir) ->
"</style>\n",
[]),
io:format(Fd,
- "<br><h2>Progress Log</h2>\n"
- "<pre>\n",[]),
+ xhtml("<br><h2>Progress Log</h2>\n<pre>\n",
+ "<br /><h2>Progress Log</h2>\n<pre>\n"),
+ []),
Fd.
close_ct_master_log(Fd) ->
@@ -178,20 +227,15 @@ config_table(Vars) ->
config_table_header() ->
["<h2>Configuration</h2>\n",
- "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color,
- "\"\n",
- "<tr><th>Key</th><th>Value</th></tr>\n"].
-
-%%
-%% keep for possible later use
-%%
-%%config_table1([{Key,Value}|Vars]) ->
-%% ["<tr><td>", atom_to_list(Key), "</td>\n",
-%% "<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n" |
-%% config_table1(Vars)];
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color,"\"\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n"]),
+ "<tr><th>Key</th><th>Value</th></tr>\n",
+ xhtml("", "</thead>\n<tbody>\n")].
config_table1([]) ->
- ["</table>\n"].
+ ["</tbody>\n</table>\n"].
int_header() ->
"<div class=\"ct_internal\"><b>*** CT MASTER ~s *** ~s</b>".
@@ -210,10 +254,10 @@ open_nodedir_index(Dir,StartTime) ->
print_nodedir(Node,RunDir,Fd) ->
Index = filename:join(RunDir,"index.html"),
io:format(Fd,
- ["<TR>\n"
- "<TD ALIGN=center>",atom_to_list(Node),"</TD>\n",
- "<TD ALIGN=left><A HREF=\"",Index,"\">",Index,"</A></TD>\n",
- "</TR>\n"],[]),
+ ["<tr>\n"
+ "<td align=center>",atom_to_list(Node),"</td>\n",
+ "<td align=left><a href=\"",Index,"\">",Index,"</a></td>\n",
+ "</tr>\n"],[]),
ok.
close_nodedir_index(Fd) ->
@@ -221,14 +265,16 @@ close_nodedir_index(Fd) ->
file:close(Fd).
nodedir_index_header(StartTime) ->
- [header("Log Files " ++ format_time(StartTime)) |
- ["<CENTER>\n",
- "<P><A HREF=\"",?ct_master_log_name,"\">Common Test Master Log</A></P>",
- "<TABLE border=\"3\" cellpadding=\"5\" ",
- "BGCOLOR=\"",?table_color,"\">\n",
- "<th><B>Node</B></th>\n",
- "<th><B>Log</B></th>\n",
- "\n"]].
+ [header("Log Files " ++ format_time(StartTime), {[],[1,2],[]}) |
+ ["<center>\n",
+ "<p><a href=\"",?ct_master_log_name,"\">Common Test Master Log</a></p>",
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
+ "<th><b>Node</b></th>\n",
+ "<th><b>Log</b></th>\n",
+ xhtml("", "</tr>\n</thead>\n<tbody>\n")]].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% All Run Index functions %%%
@@ -279,21 +325,23 @@ runentry(Dir) ->
{"unknown",""}
end,
Index = filename:join(Dir,?nodedir_index_name),
- ["<TR>\n"
- "<TD ALIGN=center><A HREF=\"",Index,"\">",timestamp(Dir),"</A></TD>\n",
- "<TD ALIGN=center>",MasterStr,"</TD>\n",
- "<TD ALIGN=center>",NodesStr,"</TD>\n",
- "</TR>\n"].
+ ["<tr>\n"
+ "<td align=center><a href=\"",Index,"\">",timestamp(Dir),"</a></td>\n",
+ "<td align=center>",MasterStr,"</td>\n",
+ "<td align=center>",NodesStr,"</td>\n",
+ "</tr>\n"].
all_runs_header() ->
- [header("Master Test Runs") |
- ["<CENTER>\n",
- "<TABLE border=\"3\" cellpadding=\"5\" "
- "BGCOLOR=\"",?table_color,"\">\n"
- "<th><B>History</B></th>\n"
- "<th><B>Master Host</B></th>\n"
- "<th><B>Test Nodes</B></th>\n"
- "\n"]].
+ [header("Master Test Runs", {[1],[2,3],[]}) |
+ ["<center>\n",
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
+ "<th><b>History</b></th>\n"
+ "<th><b>Master Host</b></th>\n"
+ "<th><b>Test Nodes</b></th>\n",
+ xhtml("", "</tr></thead>\n<tbody>\n")]].
timestamp(Dir) ->
[S,Min,H,D,M,Y|_] = lists:reverse(string:tokens(Dir,".-_")),
@@ -317,52 +365,71 @@ read_details_file(Dir) ->
%%% Internal functions
%%%--------------------------------------------------------------------
-header(Title) ->
- ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
- "<HTML>\n",
- "<HEAD>\n",
-
- "<TITLE>" ++ Title ++ "</TITLE>\n",
- "<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\">\n",
-
- "</HEAD>\n",
-
+header(Title, TableCols) ->
+ CSSFile = xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?css_default)) end),
+ JQueryFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?jquery_script)) end),
+ TableSorterFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?tablesorter_script)) end),
+
+ [xhtml(["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<html>\n"],
+ ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n",
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n",
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]),
+ "<!-- autogenerated by '"++atom_to_list(?MODULE)++"' -->\n",
+ "<head>\n",
+ "<title>" ++ Title ++ "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ xhtml("",
+ ["<link rel=\"stylesheet\" href=\"",CSSFile,"\" type=\"text/css\">"]),
+ xhtml("",
+ ["<script type=\"text/javascript\" src=\"",JQueryFile,
+ "\"></script>\n"]),
+ xhtml("",
+ ["<script type=\"text/javascript\" src=\"",TableSorterFile,
+ "\"></script>\n"]),
+ xhtml(fun() -> "" end,
+ fun() -> ct_logs:insert_javascript({tablesorter,
+ ?sortable_table_name,
+ TableCols}) end),
+ "</head>\n",
body_tag(),
-
- "<!-- ---- DOCUMENT TITLE ---- -->\n",
-
- "<CENTER>\n",
- "<H1>" ++ Title ++ "</H1>\n",
- "</CENTER>\n",
-
- "<!-- ---- CONTENT ---- -->\n"].
+ "<center>\n",
+ "<h1>" ++ Title ++ "</h1>\n",
+ "</center>\n"].
index_footer() ->
- ["</TABLE>\n"
- "</CENTER>\n" | footer()].
+ ["</tbody>\n</table>\n"
+ "</center>\n" | footer()].
footer() ->
- ["<P><CENTER>\n"
- "<HR>\n"
- "<P><FONT SIZE=-1>\n"
+ ["<center>\n",
+ xhtml("<br><hr>\n", "<br />\n"),
+ xhtml("<p><font size=\"-1\">\n", "<div class=\"copyright\">"),
"Copyright &copy; ", year(),
- " <A HREF=\"http://erlang.ericsson.se\">Open Telecom Platform</A><BR>\n"
- "Updated: <!date>", current_time(), "<!/date><BR>\n"
- "</FONT>\n"
- "</CENTER>\n"
+ " <a href=\"http://www.erlang.org\">Open Telecom Platform</a>",
+ xhtml("<br>\n", "<br />\n"),
+ "Updated: <!date>", current_time(), "<!/date>",
+ xhtml("<br>\n", "<br />\n"),
+ xhtml("</font></p>\n", "</div>\n"),
+ "</center>\n"
"</body>\n"].
body_tag() ->
- "<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\""
- "vlink=\"#800080\" alink=\"#FF0000\">\n".
+ xhtml("<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" "
+ "vlink=\"#800080\" alink=\"#FF0000\">\n",
+ "<body>\n").
current_time() ->
format_time(calendar:local_time()).
format_time({{Y, Mon, D}, {H, Min, S}}) ->
Weekday = weekday(calendar:day_of_the_week(Y, Mon, D)),
- lists:flatten(io_lib:format("~s ~s ~p ~w ~2.2.0w:~2.2.0w:~2.2.0w",
+ lists:flatten(io_lib:format("~s ~s ~2.2.0w ~w ~2.2.0w:~2.2.0w:~2.2.0w",
[Weekday, month(Mon), D, Y, H, Min, S])).
weekday(1) -> "Mon";
@@ -404,6 +471,23 @@ log_timestamp(Now) ->
lists:flatten(io_lib:format("~2.2.0w:~2.2.0w:~2.2.0w",
[H,M,S])).
+basic_html() ->
+ case application:get_env(common_test_master, basic_html) of
+ {ok,true} ->
+ true;
+ _ ->
+ false
+ end.
+
+xhtml(HTML, XHTML) ->
+ ct_logs:xhtml(HTML, XHTML).
+
+locate_priv_file(File) ->
+ ct_logs:locate_priv_file(File).
+
+make_relative(Dir) ->
+ ct_logs:make_relative(Dir).
+
force_write_file(Name,Contents) ->
force_delete(Name),
file:write_file(Name,Contents).
@@ -452,3 +536,4 @@ cast(Msg) ->
_Pid ->
?MODULE ! Msg
end.
+
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
new file mode 100644
index 0000000000..52fe9599ce
--- /dev/null
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -0,0 +1,1835 @@
+%%----------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% File: ct_netconfc.erl
+%%
+%% Description:
+%% This file contains the Netconf client interface
+%%
+%% @author Support
+%%
+%% @doc Netconf client module.
+%%
+%% <p>The Netconf client is compliant with RFC4741 and RFC4742.</p>
+%%
+%% <p> For each server to test against, the following entry can be
+%% added to a configuration file:</p>
+%%
+%% <p>`{server_id(),options()}.'</p>
+%%
+%% <p> The `server_id()' or an associated `target_name()' (see
+%% {@link ct}) shall then be used in calls to {@link open/2}.</p>
+%%
+%% <p>If no configuration exists for a server, a session can still be
+%% opened by calling {@link open/2} with all necessary options given
+%% in the call. The first argument to {@link open/2} can then be any
+%% atom.</p>
+%%
+%% == Logging ==
+%%
+%% The netconf server uses the `error_logger' for logging of netconf
+%% traffic. A special purpose error handler is implemented in
+%% `ct_conn_log_h'. To use this error handler, add the `cth_conn_log'
+%% hook in your test suite, e.g.
+%%
+%% ```
+%% suite() ->
+%% [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].
+%%'''
+%%
+%% The `conn_mod()' is the name of the common_test module implementing
+%% the connection protocol, e.g. `ct_netconfc'.
+%%
+%% The hook option `log_type' specifies the type of logging:
+%%
+%% <dl>
+%% <dt>`raw'</dt>
+%% <dd>The sent and received netconf data is logged to a separate
+%% text file as is without any formatting. A link to the file is
+%% added to the test case HTML log.</dd>
+%%
+%% <dt>`pretty'</dt>
+%% <dd>The sent and received netconf data is logged to a separate
+%% text file with XML data nicely indented. A link to the file is
+%% added to the test case HTML log.</dd>
+%%
+%% <dt>`html (default)'</dt>
+%% <dd>The sent and received netconf traffic is pretty printed
+%% directly in the test case HTML log.</dd>
+%%
+%% <dt>`silent'</dt>
+%% <dd>Netconf traffic is not logged.</dd>
+%% </dl>
+%%
+%% By default, all netconf traffic is logged in one single log
+%% file. However, it is possible to have different connections logged
+%% in separate files. To do this, use the hook option `hosts' and
+%% list the names of the servers/connections that will be used in the
+%% suite. Note that the connections must be named for this to work,
+%% i.e. they must be opened with {@link open/2}.
+%%
+%% The `hosts' option has no effect if `log_type' is set to `html' or
+%% `silent'.
+%%
+%% The hook options can also be specified in a configuration file with
+%% the configuration variable `ct_conn_log':
+%%
+%% ```
+%% {ct_conn_log,[{conn_mod(),hook_options()}]}.
+%% '''
+%%
+%% For example:
+%%
+%% ```
+%% {ct_conn_log,[{ct_netconfc,[{log_type,pretty},
+%% {hosts,[key_or_name()]}]}]}
+%% '''
+%%
+%% <b>Note</b> that hook options specified in a configuration file
+%% will overwrite the hardcoded hook options in the test suite.
+%%
+%% === Logging example 1 ===
+%%
+%% The following `ct_hooks' statement will cause pretty printing of
+%% netconf traffic to separate logs for the connections named
+%% `nc_server1' and `nc_server2'. Any other connections will be logged
+%% to default netconf log.
+%%
+%% ```
+%% suite() ->
+%% [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,pretty}},
+%% {hosts,[nc_server1,nc_server2]}]}
+%% ]}]}].
+%%'''
+%%
+%% Connections must be opened like this:
+%%
+%% ```
+%% open(nc_server1,[...]),
+%% open(nc_server2,[...]).
+%% '''
+%%
+%% === Logging example 2 ===
+%%
+%% The following configuration file will cause raw logging of all
+%% netconf traffic into one single text file.
+%%
+%% ```
+%% {ct_conn_log,[{ct_netconfc,[{log_type,raw}]}]}.
+%% '''
+%%
+%% The `ct_hooks' statement must look like this:
+%%
+%% ```
+%% suite() ->
+%% [{ct_hooks, [{cth_conn_log, []}]}].
+%% '''
+%%
+%% The same `ct_hooks' statement without the configuration file would
+%% cause HTML logging of all netconf connections into the test case
+%% HTML log.
+%%
+%% == Notifications ==
+%%
+%% The netconf client is also compliant with RFC5277 NETCONF Event
+%% Notifications, which defines a mechanism for an asynchronous
+%% message notification delivery service for the netconf protocol.
+%%
+%% Specific functions to support this are {@link
+%% create_subscription/6} and {@link get_event_streams/3}. (The
+%% functions also exist with other arities.)
+%%
+%% @end
+%%----------------------------------------------------------------------
+-module(ct_netconfc).
+
+-include("ct_netconfc.hrl").
+-include("ct_util.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+%%----------------------------------------------------------------------
+%% External exports
+%%----------------------------------------------------------------------
+-export([open/1,
+ open/2,
+ only_open/1,
+ only_open/2,
+ hello/1,
+ hello/2,
+ close_session/1,
+ close_session/2,
+ kill_session/2,
+ kill_session/3,
+ send/2,
+ send/3,
+ send_rpc/2,
+ send_rpc/3,
+ lock/2,
+ lock/3,
+ unlock/2,
+ unlock/3,
+ get/2,
+ get/3,
+ get_config/3,
+ get_config/4,
+ edit_config/3,
+ edit_config/4,
+ delete_config/2,
+ delete_config/3,
+ copy_config/3,
+ copy_config/4,
+ action/2,
+ action/3,
+ create_subscription/1,
+ create_subscription/2,
+ create_subscription/3,
+ create_subscription/4,
+ create_subscription/5,
+ create_subscription/6,
+ get_event_streams/2,
+ get_event_streams/3,
+ get_capabilities/1,
+ get_capabilities/2,
+ get_session_id/1,
+ get_session_id/2]).
+
+%%----------------------------------------------------------------------
+%% Exported types
+%%----------------------------------------------------------------------
+-export_type([hook_options/0,
+ conn_mod/0,
+ log_type/0,
+ key_or_name/0,
+ notification/0]).
+
+%%----------------------------------------------------------------------
+%% Internal exports
+%%----------------------------------------------------------------------
+%% ct_gen_conn callbacks
+-export([init/3,
+ handle_msg/3,
+ handle_msg/2,
+ terminate/2,
+ close/1]).
+
+%% ct_conn_log callback
+-export([format_data/2]).
+
+%%----------------------------------------------------------------------
+%% Internal defines
+%%----------------------------------------------------------------------
+-define(APPLICATION,?MODULE).
+-define(VALID_SSH_OPTS,[user, password, user_dir]).
+-define(DEFAULT_STREAM,"NETCONF").
+
+-define(error(ConnName,Report),
+ error_logger:error_report([{ct_connection,ConnName},
+ {client,self()},
+ {module,?MODULE},
+ {line,?LINE} |
+ Report])).
+
+-define(is_timeout(T), (is_integer(T) orelse T==infinity)).
+-define(is_filter(F),
+ (is_atom(F) orelse (is_tuple(F) andalso is_atom(element(1,F))))).
+-define(is_string(S), (is_list(S) andalso is_integer(hd(S)))).
+
+%%----------------------------------------------------------------------
+%% Records
+%%----------------------------------------------------------------------
+%% Client state
+-record(state, {host,
+ port,
+ connection, % #connection
+ capabilities,
+ session_id,
+ msg_id = 1,
+ hello_status,
+ buff = <<>>,
+ pending = [], % [#pending]
+ event_receiver}).% pid
+
+%% Run-time client options.
+-record(options, {ssh = [], % Options for the ssh application
+ host,
+ port = ?DEFAULT_PORT,
+ timeout = ?DEFAULT_TIMEOUT,
+ name}).
+
+%% Connection reference
+-record(connection, {reference, % {CM,Ch}
+ host,
+ port,
+ name}).
+
+%% Pending replies from server
+-record(pending, {tref, % timer ref (returned from timer:xxx)
+ ref, % pending ref
+ msg_id,
+ op,
+ caller}).% pid which sent the request
+
+%%----------------------------------------------------------------------
+%% Type declarations
+%%----------------------------------------------------------------------
+-type client() :: handle() | server_id() | target_name().
+-type handle() :: term().
+%% An opaque reference for a connection (netconf session). See {@link
+%% ct} for more information.
+
+-type server_id() :: atom().
+%% A `ServerId' which exists in a configuration file.
+-type target_name() :: atom().
+%% A name which is associated to a `server_id()' via a
+%% `require' statement or a call to {@link ct:require/2} in the
+%% test suite.
+-type key_or_name() :: server_id() | target_name().
+
+-type options() :: [option()].
+%% Options used for setting up ssh connection to a netconf server.
+
+-type option() :: {ssh,host()} | {port,inet:port_number()} | {user,string()} |
+ {password,string()} | {user_dir,string()} |
+ {timeout,timeout()}.
+-type host() :: inet:host_name() | inet:ip_address().
+
+-type notification() :: {notification, xml_attributes(), notification_content()}.
+-type notification_content() :: [event_time()|simple_xml()].
+-type event_time() :: {eventTime,xml_attributes(),[xs_datetime()]}.
+
+-type stream_name() :: string().
+-type streams() :: [{stream_name(),[stream_data()]}].
+-type stream_data() :: {description,string()} |
+ {replaySupport,string()} |
+ {replayLogCreationTime,string()} |
+ {replayLogAgedTime,string()}.
+%% See XML Schema for Event Notifications found in RFC5277 for further
+%% detail about the data format for the string values.
+
+-type hook_options() :: [hook_option()].
+%% Options that can be given to `cth_conn_log' in the `ct_hook' statement.
+-type hook_option() :: {log_type,log_type()} |
+ {hosts,[key_or_name()]}.
+-type log_type() :: raw | pretty | html | silent.
+%-type error_handler() :: module().
+-type conn_mod() :: ct_netconfc.
+
+-type error_reason() :: term().
+
+-type simple_xml() :: {xml_tag(), xml_attributes(), xml_content()} |
+ {xml_tag(), xml_content()} |
+ xml_tag().
+%% <p>This type is further described in the documentation for the
+%% <tt>Xmerl</tt> application.</p>
+-type xml_tag() :: atom().
+-type xml_attributes() :: [{xml_attribute_tag(),xml_attribute_value()}].
+-type xml_attribute_tag() :: atom().
+-type xml_attribute_value() :: string().
+-type xml_content() :: [simple_xml() | iolist()].
+-type xpath() :: {xpath,string()}.
+
+-type netconf_db() :: running | startup | candidate.
+-type xs_datetime() :: string().
+%% This date and time identifyer has the same format as the XML type
+%% dateTime and compliant to RFC3339. The format is
+%% ```[-]CCYY-MM-DDThh:mm:ss[.s][Z|(+|-)hh:mm]'''
+
+%%----------------------------------------------------------------------
+%% External interface functions
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+-spec open(Options) -> Result when
+ Options :: options(),
+ Result :: {ok,handle()} | {error,error_reason()}.
+%% @doc Open a netconf session and exchange `hello' messages.
+%%
+%% If the server options are specified in a configuration file, or if
+%% a named client is needed for logging purposes (see {@section
+%% Logging}) use {@link open/2} instead.
+%%
+%% The opaque `handler()' reference which is returned from this
+%% function is required as client identifier when calling any other
+%% function in this module.
+%%
+%% The `timeout' option (milli seconds) is used when setting up
+%% the ssh connection and when waiting for the hello message from the
+%% server. It is not used for any other purposes during the lifetime
+%% of the connection.
+%%
+%% @end
+%%----------------------------------------------------------------------
+open(Options) ->
+ open(Options,#options{},[],true).
+
+%%----------------------------------------------------------------------
+-spec open(KeyOrName, ExtraOptions) -> Result when
+ KeyOrName :: key_or_name(),
+ ExtraOptions :: options(),
+ Result :: {ok,handle()} | {error,error_reason()}.
+%% @doc Open a named netconf session and exchange `hello' messages.
+%%
+%% If `KeyOrName' is a configured `server_id()' or a
+%% `target_name()' associated with such an ID, then the options
+%% for this server will be fetched from the configuration file.
+%
+%% The `ExtraOptions' argument will be added to the options found in
+%% the configuration file. If the same options are given, the values
+%% from the configuration file will overwrite `ExtraOptions'.
+%%
+%% If the server is not specified in a configuration file, use {@link
+%% open/1} instead.
+%%
+%% The opaque `handle()' reference which is returned from this
+%% function can be used as client identifier when calling any other
+%% function in this module. However, if `KeyOrName' is a
+%% `target_name()', i.e. if the server is named via a call to
+%% `ct:require/2' or a `require' statement in the test
+%% suite, then this name may be used instead of the `handle()'.
+%%
+%% The `timeout' option (milli seconds) is used when setting up
+%% the ssh connection and when waiting for the hello message from the
+%% server. It is not used for any other purposes during the lifetime
+%% of the connection.
+%%
+%% @see ct:require/2
+%% @end
+%%----------------------------------------------------------------------
+open(KeyOrName, ExtraOpts) ->
+ open(KeyOrName, ExtraOpts, true).
+
+open(KeyOrName, ExtraOpts, Hello) ->
+ SortedExtra = lists:keysort(1,ExtraOpts),
+ SortedConfig = lists:keysort(1,ct:get_config(KeyOrName,[])),
+ AllOpts = lists:ukeymerge(1,SortedConfig,SortedExtra),
+ open(AllOpts,#options{name=KeyOrName},[{name,KeyOrName}],Hello).
+
+open(OptList,InitOptRec,NameOpt,Hello) ->
+ case check_options(OptList,undefined,undefined,InitOptRec) of
+ {Host,Port,Options} ->
+ case ct_gen_conn:start({Host,Port},Options,?MODULE,
+ NameOpt ++ [{reconnect,false},
+ {use_existing_connection,false},
+ {forward_messages,true}]) of
+ {ok,Client} when Hello==true ->
+ case hello(Client,Options#options.timeout) of
+ ok ->
+ {ok,Client};
+ Error ->
+ Error
+ end;
+ Other ->
+ Other
+ end;
+ Error ->
+ Error
+ end.
+
+
+%%----------------------------------------------------------------------
+-spec only_open(Options) -> Result when
+ Options :: options(),
+ Result :: {ok,handle()} | {error,error_reason()}.
+%% @doc Open a netconf session, but don't send `hello'.
+%%
+%% As {@link open/1} but does not send a `hello' message.
+%%
+%% @end
+%%----------------------------------------------------------------------
+only_open(Options) ->
+ open(Options,#options{},[],false).
+
+%%----------------------------------------------------------------------
+-spec only_open(KeyOrName,ExtraOptions) -> Result when
+ KeyOrName :: key_or_name(),
+ ExtraOptions :: options(),
+ Result :: {ok,handle()} | {error,error_reason()}.
+%% @doc Open a name netconf session, but don't send `hello'.
+%%
+%% As {@link open/2} but does not send a `hello' message.
+%%
+%% @end
+%%----------------------------------------------------------------------
+only_open(KeyOrName, ExtraOpts) ->
+ open(KeyOrName, ExtraOpts, false).
+
+%%----------------------------------------------------------------------
+%% @spec hello(Client) -> Result
+%% @equiv hello(Client, infinity)
+hello(Client) ->
+ hello(Client,?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec hello(Client,Timeout) -> Result when
+ Client :: handle(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Exchange `hello' messages with the server.
+%%
+%% Sends a `hello' message to the server and waits for the return.
+%%
+%% @end
+%%----------------------------------------------------------------------
+hello(Client,Timeout) ->
+ call(Client, {hello, Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec get_session_id(Client) -> Result
+%% @equiv get_session_id(Client, infinity)
+get_session_id(Client) ->
+ get_session_id(Client, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec get_session_id(Client, Timeout) -> Result when
+ Client :: client(),
+ Timeout :: timeout(),
+ Result :: pos_integer() | {error,error_reason()}.
+%% @doc Returns the session id associated with the given client.
+%%
+%% @end
+%%----------------------------------------------------------------------
+get_session_id(Client, Timeout) ->
+ call(Client, get_session_id, Timeout).
+
+%%----------------------------------------------------------------------
+%% @spec get_capabilities(Client) -> Result
+%% @equiv get_capabilities(Client, infinity)
+get_capabilities(Client) ->
+ get_capabilities(Client, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec get_capabilities(Client, Timeout) -> Result when
+ Client :: client(),
+ Timeout :: timeout(),
+ Result :: [string()] | {error,error_reason()}.
+%% @doc Returns the server side capabilities
+%%
+%% The following capability identifiers, defined in RFC 4741, can be returned:
+%%
+%% <ul>
+%% <li>`"urn:ietf:params:netconf:base:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:writable-running:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:candidate:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:confirmed-commit:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:rollback-on-error:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:startup:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:url:1.0"'</li>
+%% <li>`"urn:ietf:params:netconf:capability:xpath:1.0"'</li>
+%% </ul>
+%%
+%% Note, additional identifiers may exist, e.g. server side namespace.
+%%
+%% @end
+%%----------------------------------------------------------------------
+get_capabilities(Client, Timeout) ->
+ call(Client, get_capabilities, Timeout).
+
+%% @private
+send(Client, SimpleXml) ->
+ send(Client, SimpleXml, ?DEFAULT_TIMEOUT).
+%% @private
+send(Client, SimpleXml, Timeout) ->
+ call(Client,{send, Timeout, SimpleXml}).
+
+%% @private
+send_rpc(Client, SimpleXml) ->
+ send_rpc(Client, SimpleXml, ?DEFAULT_TIMEOUT).
+%% @private
+send_rpc(Client, SimpleXml, Timeout) ->
+ call(Client,{send_rpc, SimpleXml, Timeout}).
+
+
+
+%%----------------------------------------------------------------------
+%% @spec lock(Client, Target) -> Result
+%% @equiv lock(Client, Target, infinity)
+lock(Client, Target) ->
+ lock(Client, Target,?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec lock(Client, Target, Timeout) -> Result when
+ Client :: client(),
+ Target :: netconf_db(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Unlock configuration target.
+%%
+%% Which target parameters that can be used depends on if
+%% `:candidate' and/or `:startup' are supported by the
+%% server. If successfull, the configuration system of the device is
+%% not available to other clients (Netconf, CORBA, SNMP etc). Locks
+%% are intended to be short-lived.
+%%
+%% The operations {@link kill_session/2} or {@link kill_session/3} can
+%% be used to force the release of a lock owned by another Netconf
+%% session. How this is achieved by the server side is implementation
+%% specific.
+%%
+%% @end
+%%----------------------------------------------------------------------
+lock(Client, Target, Timeout) ->
+ call(Client,{send_rpc_op,lock,[Target],Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec unlock(Client, Target) -> Result
+%% @equiv unlock(Client, Target, infinity)
+unlock(Client, Target) ->
+ unlock(Client, Target,?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec unlock(Client, Target, Timeout) -> Result when
+ Client :: client(),
+ Target :: netconf_db(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Unlock configuration target.
+%%
+%% If the client earlier has aquired a lock, via {@link lock/2} or
+%% {@link lock/3}, this operation release the associated lock. To be
+%% able to access another target than `running', the server must
+%% support `:candidate' and/or `:startup'.
+%%
+%% @end
+%%----------------------------------------------------------------------
+unlock(Client, Target, Timeout) ->
+ call(Client, {send_rpc_op, unlock, [Target], Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec get(Client, Filter) -> Result
+%% @equiv get(Client, Filter, infinity)
+get(Client, Filter) ->
+ get(Client, Filter, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec get(Client, Filter, Timeout) -> Result when
+ Client :: client(),
+ Filter :: simple_xml() | xpath(),
+ Timeout :: timeout(),
+ Result :: {ok,simple_xml()} | {error,error_reason()}.
+%% @doc Get data.
+%%
+%% This operation returns both configuration and state data from the
+%% server.
+%%
+%% Filter type `xpath' can only be used if the server supports
+%% `:xpath'.
+%%
+%% @end
+%%----------------------------------------------------------------------
+get(Client, Filter, Timeout) ->
+ call(Client,{send_rpc_op, get, [Filter], Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec get_config(Client, Source, Filter) -> Result
+%% @equiv get_config(Client, Source, Filter, infinity)
+get_config(Client, Source, Filter) ->
+ get_config(Client, Source, Filter, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec get_config(Client, Source, Filter, Timeout) -> Result when
+ Client :: client(),
+ Source :: netconf_db(),
+ Filter :: simple_xml() | xpath(),
+ Timeout :: timeout(),
+ Result :: {ok,simple_xml()} | {error,error_reason()}.
+%% @doc Get configuration data.
+%%
+%% To be able to access another source than `running', the server
+%% must advertise `:candidate' and/or `:startup'.
+%%
+%% Filter type `xpath' can only be used if the server supports
+%% `:xpath'.
+%%
+%%
+%% @end
+%%----------------------------------------------------------------------
+get_config(Client, Source, Filter, Timeout) ->
+ call(Client, {send_rpc_op, get_config, [Source, Filter], Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec edit_config(Client, Target, Config) -> Result
+%% @equiv edit_config(Client, Target, Config, infinity)
+edit_config(Client, Target, Config) ->
+ edit_config(Client, Target, Config, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec edit_config(Client, Target, Config, Timeout) -> Result when
+ Client :: client(),
+ Target :: netconf_db(),
+ Config :: simple_xml(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Edit configuration data.
+%%
+%% Per default only the running target is available, unless the server
+%% include `:candidate' or `:startup' in its list of
+%% capabilities.
+%%
+%% @end
+%%----------------------------------------------------------------------
+edit_config(Client, Target, Config, Timeout) ->
+ call(Client, {send_rpc_op, edit_config, [Target,Config], Timeout}).
+
+
+%%----------------------------------------------------------------------
+%% @spec delete_config(Client, Target) -> Result
+%% @equiv delete_config(Client, Target, infinity)
+delete_config(Client, Target) ->
+ delete_config(Client, Target, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec delete_config(Client, Target, Timeout) -> Result when
+ Client :: client(),
+ Target :: startup | candidate,
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Delete configuration data.
+%%
+%% The running configuration cannot be deleted and `:candidate'
+%% or `:startup' must be advertised by the server.
+%%
+%% @end
+%%----------------------------------------------------------------------
+delete_config(Client, Target, Timeout) when Target == startup;
+ Target == candidate ->
+ call(Client,{send_rpc_op, delete_config, [Target], Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec copy_config(Client, Source, Target) -> Result
+%% @equiv copy_config(Client, Source, Target, infinity)
+copy_config(Client, Source, Target) ->
+ copy_config(Client, Source, Target, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec copy_config(Client, Target, Source, Timeout) -> Result when
+ Client :: client(),
+ Target :: netconf_db(),
+ Source :: netconf_db(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Copy configuration data.
+%%
+%% Which source and target options that can be issued depends on the
+%% capabilities supported by the server. I.e. `:candidate' and/or
+%% `:startup' are required.
+%%
+%% @end
+%%----------------------------------------------------------------------
+copy_config(Client, Target, Source, Timeout) ->
+ call(Client,{send_rpc_op, copy_config, [Target, Source], Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec action(Client, Action) -> Result
+%% @equiv action(Client, Action, infinity)
+action(Client,Action) ->
+ action(Client,Action,?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec action(Client, Action, Timeout) -> Result when
+ Client :: client(),
+ Action :: simple_xml(),
+ Timeout :: timeout(),
+ Result :: {ok,simple_xml()} | {error,error_reason()}.
+%% @doc Execute an action.
+%%
+%% @end
+%%----------------------------------------------------------------------
+action(Client,Action,Timeout) ->
+ call(Client,{send_rpc_op, action, [Action], Timeout}).
+
+%%----------------------------------------------------------------------
+create_subscription(Client) ->
+ create_subscription(Client,?DEFAULT_STREAM,?DEFAULT_TIMEOUT).
+
+create_subscription(Client,Timeout)
+ when ?is_timeout(Timeout) ->
+ create_subscription(Client,?DEFAULT_STREAM,Timeout);
+create_subscription(Client,Stream)
+ when is_list(Stream) ->
+ create_subscription(Client,Stream,?DEFAULT_TIMEOUT);
+create_subscription(Client,Filter)
+ when ?is_filter(Filter) ->
+ create_subscription(Client,?DEFAULT_STREAM,Filter,
+ ?DEFAULT_TIMEOUT).
+
+create_subscription(Client,Stream,Timeout)
+ when is_list(Stream) andalso
+ ?is_timeout(Timeout) ->
+ call(Client,{send_rpc_op,{create_subscription,self()},
+ [Stream,undefined,undefined,undefined],
+ Timeout});
+create_subscription(Client,StartTime,StopTime)
+ when is_list(StartTime) andalso
+ is_list(StopTime) ->
+ create_subscription(Client,?DEFAULT_STREAM,StartTime,StopTime,
+ ?DEFAULT_TIMEOUT);
+create_subscription(Client,Filter,Timeout)
+ when ?is_filter(Filter) andalso
+ ?is_timeout(Timeout) ->
+ create_subscription(Client,?DEFAULT_STREAM,Filter,Timeout);
+create_subscription(Client,Stream,Filter)
+ when is_list(Stream) andalso
+ ?is_filter(Filter) ->
+ create_subscription(Client,Stream,Filter,?DEFAULT_TIMEOUT).
+
+create_subscription(Client,StartTime,StopTime,Timeout)
+ when is_list(StartTime) andalso
+ is_list(StopTime) andalso
+ ?is_timeout(Timeout) ->
+ create_subscription(Client,?DEFAULT_STREAM,StartTime,StopTime,Timeout);
+create_subscription(Client,Stream,StartTime,StopTime)
+ when is_list(Stream) andalso
+ is_list(StartTime) andalso
+ is_list(StopTime) ->
+ create_subscription(Client,Stream,StartTime,StopTime,?DEFAULT_TIMEOUT);
+create_subscription(Client,Filter,StartTime,StopTime)
+ when ?is_filter(Filter) andalso
+ is_list(StartTime) andalso
+ is_list(StopTime) ->
+ create_subscription(Client,?DEFAULT_STREAM,Filter,
+ StartTime,StopTime,?DEFAULT_TIMEOUT);
+create_subscription(Client,Stream,Filter,Timeout)
+ when is_list(Stream) andalso
+ ?is_filter(Filter) andalso
+ ?is_timeout(Timeout) ->
+ call(Client,{send_rpc_op,{create_subscription,self()},
+ [Stream,Filter,undefined,undefined],
+ Timeout}).
+
+create_subscription(Client,Stream,StartTime,StopTime,Timeout)
+ when is_list(Stream) andalso
+ is_list(StartTime) andalso
+ is_list(StopTime) andalso
+ ?is_timeout(Timeout) ->
+ call(Client,{send_rpc_op,{create_subscription,self()},
+ [Stream,undefined,StartTime,StopTime],
+ Timeout});
+create_subscription(Client,Stream,Filter,StartTime,StopTime)
+ when is_list(Stream) andalso
+ ?is_filter(Filter) andalso
+ is_list(StartTime) andalso
+ is_list(StopTime) ->
+ create_subscription(Client,Stream,Filter,StartTime,StopTime,?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec create_subscription(Client, Stream, Filter,StartTime, StopTime, Timeout) ->
+ Result when
+ Client :: client(),
+ Stream :: stream_name(),
+ Filter :: simple_xml(),
+ StartTime :: xs_datetime(),
+ StopTime :: xs_datetime(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Create a subscription for event notifications.
+%%
+%% This function sets up a subscription for netconf event
+%% notifications of the given stream type, matching the given
+%% filter. The calling process will receive notifications as messages
+%% of type `notification()'.
+%%
+%% <dl>
+%% <dt>Stream:</dt>
+%% <dd> An optional parameter that indicates which stream of events
+%% is of interest. If not present, events in the default NETCONF
+%% stream will be sent.</dd>
+%%
+%% <dt>Filter:</dt>
+%% <dd>An optional parameter that indicates which subset of all
+%% possible events is of interest. The format of this parameter is
+%% the same as that of the filter parameter in the NETCONF protocol
+%% operations. If not present, all events not precluded by other
+%% parameters will be sent. See section 3.6 for more information on
+%% filters.</dd>
+%%
+%% <dt>StartTime:</dt>
+%% <dd>An optional parameter used to trigger the replay feature and
+%% indicate that the replay should start at the time specified. If
+%% `StartTime' is not present, this is not a replay subscription.
+%% It is not valid to specify start times that are later than the
+%% current time. If the `StartTime' specified is earlier than the
+%% log can support, the replay will begin with the earliest
+%% available notification. This parameter is of type dateTime and
+%% compliant to [RFC3339]. Implementations must support time
+%% zones.</dd>
+%%
+%% <dt>StopTime:</dt>
+%% <dd>An optional parameter used with the optional replay feature
+%% to indicate the newest notifications of interest. If `StopTime'
+%% is not present, the notifications will continue until the
+%% subscription is terminated. Must be used with and be later than
+%% `StartTime'. Values of `StopTime' in the future are valid. This
+%% parameter is of type dateTime and compliant to [RFC3339].
+%% Implementations must support time zones.</dd>
+%% </dl>
+%%
+%% See RFC5277 for further details about the event notification
+%% mechanism.
+%%
+%% @end
+%%----------------------------------------------------------------------
+create_subscription(Client,Stream,Filter,StartTime,StopTime,Timeout) ->
+ call(Client,{send_rpc_op,{create_subscription, self()},
+ [Stream,Filter,StartTime,StopTime],
+ Timeout}).
+
+%%----------------------------------------------------------------------
+%% @spec get_event_streams(Client, Timeout) -> Result
+%% @equiv get_event_streams(Client, [], Timeout)
+get_event_streams(Client,Timeout) when is_integer(Timeout); Timeout==infinity ->
+ get_event_streams(Client,[],Timeout);
+
+%%----------------------------------------------------------------------
+%% @spec get_event_streams(Client, Streams) -> Result
+%% @equiv get_event_streams(Client, Streams, infinity)
+get_event_streams(Client,Streams) when is_list(Streams) ->
+ get_event_streams(Client,Streams,?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec get_event_streams(Client, Streams, Timeout)
+ -> Result when
+ Client :: client(),
+ Streams :: [stream_name()],
+ Timeout :: timeout(),
+ Result :: {ok,streams()} | {error,error_reason()}.
+%% @doc Send a request to get the given event streams.
+%%
+%% `Streams' is a list of stream names. The following filter will
+%% be sent to the netconf server in a `get' request:
+%%
+%% ```
+%% <netconf xmlns="urn:ietf:params:xml:ns:netmod:notification">
+%% <streams>
+%% <stream>
+%% <name>StreamName1</name>
+%% </stream>
+%% <stream>
+%% <name>StreamName2</name>
+%% </stream>
+%% ...
+%% </streams>
+%% </netconf>
+%% '''
+%%
+%% If `Streams' is an empty list, ALL streams will be requested
+%% by sending the following filter:
+%%
+%% ```
+%% <netconf xmlns="urn:ietf:params:xml:ns:netmod:notification">
+%% <streams/>
+%% </netconf>
+%% '''
+%%
+%% If more complex filtering is needed, a use {@link get/2} or {@link
+%% get/3} and specify the exact filter according to XML Schema for
+%% Event Notifications found in RFC5277.
+%%
+%% @end
+%%----------------------------------------------------------------------
+get_event_streams(Client,Streams,Timeout) ->
+ call(Client,{get_event_streams,Streams,Timeout}).
+
+
+%%----------------------------------------------------------------------
+%% @spec close_session(Client) -> Result
+%% @equiv close_session(Client, infinity)
+close_session(Client) ->
+ close_session(Client, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec close_session(Client, Timeout) -> Result when
+ Client :: client(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Request graceful termination of the session associated with the client.
+%%
+%% When a netconf server receives a `close-session' request, it
+%% will gracefully close the session. The server will release any
+%% locks and resources associated with the session and gracefully
+%% close any associated connections. Any NETCONF requests received
+%% after a `close-session' request will be ignored.
+%%
+%% @end
+%%----------------------------------------------------------------------
+close_session(Client, Timeout) ->
+ call(Client,{send_rpc_op, close_session, [], Timeout}).
+
+
+%%----------------------------------------------------------------------
+%% @spec kill_session(Client, SessionId) -> Result
+%% @equiv kill_session(Client, SessionId, infinity)
+kill_session(Client, SessionId) ->
+ kill_session(Client, SessionId, ?DEFAULT_TIMEOUT).
+
+%%----------------------------------------------------------------------
+-spec kill_session(Client, SessionId, Timeout) -> Result when
+ Client :: client(),
+ SessionId :: pos_integer(),
+ Timeout :: timeout(),
+ Result :: ok | {error,error_reason()}.
+%% @doc Force termination of the session associated with the supplied
+%% session id.
+%%
+%% The server side shall abort any operations currently in process,
+%% release any locks and resources associated with the session, and
+%% close any associated connections.
+%%
+%% Only if the server is in the confirmed commit phase, the
+%% configuration will be restored to its state before entering the
+%% confirmed commit phase. Otherwise, no configuration roll back will
+%% be performed.
+%%
+%% If the given `SessionId' is equal to the current session id,
+%% an error will be returned.
+%%
+%% @end
+%% ----------------------------------------------------------------------
+kill_session(Client, SessionId, Timeout) ->
+ call(Client,{send_rpc_op, kill_session, [SessionId], Timeout}).
+
+
+%%----------------------------------------------------------------------
+%% Callback functions
+%%----------------------------------------------------------------------
+
+%% @private
+init(_KeyOrName,{_Host,_Port},Options) ->
+ case ssh_open(Options) of
+ {ok, Connection} ->
+ log(Connection,open),
+ {ConnPid,_} = Connection#connection.reference,
+ {ok, ConnPid, #state{connection = Connection}};
+ {error,Reason}->
+ {error,Reason}
+ end.
+
+%% @private
+terminate(_, #state{connection=Connection}) ->
+ ssh_close(Connection),
+ log(Connection,close),
+ ok.
+
+%% @private
+handle_msg({hello,Timeout}, From,
+ #state{connection=Connection,hello_status=HelloStatus} = State) ->
+ case do_send(Connection, client_hello()) of
+ ok ->
+ case HelloStatus of
+ undefined ->
+ {Ref,TRef} = set_request_timer(Timeout),
+ {noreply, State#state{hello_status=#pending{tref=TRef,
+ ref=Ref,
+ caller=From}}};
+ received ->
+ {reply, ok, State#state{hello_status=done}};
+ {error,Reason} ->
+ {stop, {error,Reason}, State}
+ end;
+ Error ->
+ {stop, Error, State}
+ end;
+handle_msg(_, _From, #state{session_id=undefined} = State) ->
+ %% Hello is not yet excanged - this shall never happen
+ {reply,{error,waiting_for_hello},State};
+handle_msg(get_capabilities, _From, #state{capabilities = Caps} = State) ->
+ {reply, Caps, State};
+handle_msg(get_session_id, _From, #state{session_id = Id} = State) ->
+ {reply, Id, State};
+handle_msg({send, Timeout, SimpleXml}, From,
+ #state{connection=Connection,pending=Pending} = State) ->
+ case do_send(Connection, SimpleXml) of
+ ok ->
+ {Ref,TRef} = set_request_timer(Timeout),
+ {noreply, State#state{pending=[#pending{tref=TRef,
+ ref=Ref,
+ caller=From} | Pending]}};
+ Error ->
+ {reply, Error, State}
+ end;
+handle_msg({send_rpc, SimpleXml, Timeout}, From, State) ->
+ do_send_rpc(undefined, SimpleXml, Timeout, From, State);
+handle_msg({send_rpc_op, Op, Data, Timeout}, From, State) ->
+ SimpleXml = encode_rpc_operation(Op,Data),
+ do_send_rpc(Op, SimpleXml, Timeout, From, State);
+handle_msg({get_event_streams=Op,Streams,Timeout}, From, State) ->
+ Filter = {netconf,?NETMOD_NOTIF_NAMESPACE_ATTR,
+ [{streams,[{stream,[{name,[Name]}]} || Name <- Streams]}]},
+ SimpleXml = encode_rpc_operation(get,[Filter]),
+ do_send_rpc(Op, SimpleXml, Timeout, From, State).
+
+handle_msg({ssh_cm, _CM, {data, _Ch, _Type, Data}}, State) ->
+ handle_data(Data, State);
+handle_msg({ssh_cm, _CM, _SshCloseMsg}, State) ->
+ %% _SshCloseMsg can probably be one of
+ %% {eof,Ch}
+ %% {exit_status,Ch,Status}
+ %% {exit_signal,Ch,ExitSignal,ErrorMsg,LanguageString}
+ %% {signal,Ch,Signal}
+
+ %% This might e.g. happen if the server terminates the connection,
+ %% as in kill-session (or if ssh:close is called from somewhere
+ %% unexpected).
+
+ %%! Log this??
+ %%! Currently the log will say that the client closed the
+ %%! connection - due to terminate/2
+
+ {stop, State};
+handle_msg({Ref,timeout},
+ #state{hello_status=#pending{ref=Ref,caller=Caller}} = State) ->
+ ct_gen_conn:return(Caller,{error,{hello_session_failed,timeout}}),
+ {stop,State#state{hello_status={error,timeout}}};
+handle_msg({Ref,timeout},#state{pending=Pending} = State) ->
+ {value,#pending{caller=Caller},Pending1} =
+ lists:keytake(Ref,#pending.ref,Pending),
+ ct_gen_conn:return(Caller,{error,timeout}),
+ {noreply,State#state{pending=Pending1}}.
+
+%% @private
+%% Called by ct_util_server to close registered connections before terminate.
+close(Client) ->
+ case get_handle(Client) of
+ {ok,Pid} ->
+ case ct_gen_conn:stop(Pid) of
+ {error,{process_down,Pid,noproc}} ->
+ {error,already_closed};
+ Result ->
+ Result
+ end;
+ Error ->
+ Error
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Internal functions
+%%----------------------------------------------------------------------
+call(Client, Msg) ->
+ call(Client, Msg, infinity).
+call(Client, Msg, Timeout) ->
+ case get_handle(Client) of
+ {ok,Pid} ->
+ case ct_gen_conn:call(Pid,Msg,Timeout) of
+ {error,{process_down,Client,noproc}} ->
+ {error,no_such_client};
+ {error,{process_down,Client,normal}} ->
+ {error,closed};
+ {error,{process_down,Client,Reason}} ->
+ {error,{closed,Reason}};
+ Other ->
+ Other
+ end;
+ Error ->
+ Error
+ end.
+
+get_handle(Client) when is_pid(Client) ->
+ {ok,Client};
+get_handle(Client) ->
+ case ct_util:get_connections(Client, ?MODULE) of
+ {ok,[{Pid,_}]} ->
+ {ok,Pid};
+ {ok,[]} ->
+ {error,{no_connection_found,Client}};
+ {ok,Conns} ->
+ {error,{multiple_connections_found,Client,Conns}};
+ Error ->
+ Error
+ end.
+
+check_options([], undefined, _Port, _Options) ->
+ {error, no_host_address};
+check_options([], _Host, undefined, _Options) ->
+ {error, no_port};
+check_options([], Host, Port, Options) ->
+ {Host,Port,Options};
+check_options([{ssh, Host}|T], _, Port, #options{} = Options) ->
+ check_options(T, Host, Port, Options#options{host=Host});
+check_options([{port,Port}|T], Host, _, #options{} = Options) ->
+ check_options(T, Host, Port, Options#options{port=Port});
+check_options([{timeout, Timeout}|T], Host, Port, Options)
+ when is_integer(Timeout); Timeout==infinity ->
+ check_options(T, Host, Port, Options#options{timeout = Timeout});
+check_options([{X,_}=Opt|T], Host, Port, #options{ssh=SshOpts}=Options) ->
+ case lists:member(X,?VALID_SSH_OPTS) of
+ true ->
+ check_options(T, Host, Port, Options#options{ssh=[Opt|SshOpts]});
+ false ->
+ {error, {invalid_option, Opt}}
+ end.
+
+%%%-----------------------------------------------------------------
+set_request_timer(infinity) ->
+ {undefined,undefined};
+set_request_timer(T) ->
+ Ref = make_ref(),
+ {ok,TRef} = timer:send_after(T,{Ref,timeout}),
+ {Ref,TRef}.
+
+
+%%%-----------------------------------------------------------------
+client_hello() ->
+ {hello, ?NETCONF_NAMESPACE_ATTR,
+ [{capabilities,
+ [{capability,[?NETCONF_BASE_CAP++?NETCONF_BASE_CAP_VSN]}]}]}.
+
+%%%-----------------------------------------------------------------
+
+encode_rpc_operation(Lock,[Target]) when Lock==lock; Lock==unlock ->
+ {Lock,[{target,[Target]}]};
+encode_rpc_operation(get,[Filter]) ->
+ {get,filter(Filter)};
+encode_rpc_operation(get_config,[Source,Filter]) ->
+ {'get-config',[{source,[Source]}] ++ filter(Filter)};
+encode_rpc_operation(edit_config,[Target,Config]) ->
+ {'edit-config',[{target,[Target]},{config,[Config]}]};
+encode_rpc_operation(delete_config,[Target]) ->
+ {'delete-config',[{target,[Target]}]};
+encode_rpc_operation(copy_config,[Target,Source]) ->
+ {'copy-config',[{target,[Target]},{source,[Source]}]};
+encode_rpc_operation(action,[Action]) ->
+ {action,?ACTION_NAMESPACE_ATTR,[{data,[Action]}]};
+encode_rpc_operation(kill_session,[SessionId]) ->
+ {'kill-session',[{'session-id',[integer_to_list(SessionId)]}]};
+encode_rpc_operation(close_session,[]) ->
+ 'close-session';
+encode_rpc_operation({create_subscription,_},
+ [Stream,Filter,StartTime,StopTime]) ->
+ {'create-subscription',?NETCONF_NOTIF_NAMESPACE_ATTR,
+ [{stream,[Stream]}] ++
+ filter(Filter) ++
+ maybe_element(startTime,StartTime) ++
+ maybe_element(stopTime,StopTime)}.
+
+filter(undefined) ->
+ [];
+filter({xpath,Filter}) when ?is_string(Filter) ->
+ [{filter,[{type,"xpath"},{select, Filter}],[]}];
+filter(Filter) ->
+ [{filter,[{type,"subtree"}],[Filter]}].
+
+maybe_element(_,undefined) ->
+ [];
+maybe_element(Tag,Value) ->
+ [{Tag,[Value]}].
+
+%%%-----------------------------------------------------------------
+%%% Send XML data to server
+do_send_rpc(PendingOp,SimpleXml,Timeout,Caller,
+ #state{connection=Connection,msg_id=MsgId,pending=Pending} = State) ->
+ case do_send_rpc(Connection, MsgId, SimpleXml) of
+ ok ->
+ {Ref,TRef} = set_request_timer(Timeout),
+ {noreply, State#state{msg_id=MsgId+1,
+ pending=[#pending{tref=TRef,
+ ref=Ref,
+ msg_id=MsgId,
+ op=PendingOp,
+ caller=Caller} | Pending]}};
+ Error ->
+ {reply, Error, State#state{msg_id=MsgId+1}}
+ end.
+
+do_send_rpc(Connection, MsgId, SimpleXml) ->
+ do_send(Connection,
+ {rpc,
+ [{'message-id',MsgId} | ?NETCONF_NAMESPACE_ATTR],
+ [SimpleXml]}).
+
+do_send(Connection, SimpleXml) ->
+ Xml=to_xml_doc(SimpleXml),
+ log(Connection,send,Xml),
+ ssh_send(Connection, Xml).
+
+to_xml_doc(Simple) ->
+ Prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+ Xml = list_to_binary(xmerl:export_simple([Simple],
+ xmerl_xml,
+ [#xmlAttribute{name=prolog,
+ value=Prolog}])),
+ <<Xml/binary,?END_TAG/binary>>.
+
+%%%-----------------------------------------------------------------
+%%% Parse and handle received XML data
+handle_data(NewData,#state{connection=Connection,buff=Buff} = State) ->
+ log(Connection,recv,NewData),
+ Data = <<Buff/binary,NewData/binary>>,
+ case xmerl_sax_parser:stream(<<>>,
+ [{continuation_fun,fun sax_cont/1},
+ {continuation_state,{Data,Connection,false}},
+ {event_fun,fun sax_event/3},
+ {event_state,[]}]) of
+ {ok, Simple, Rest} ->
+ decode(Simple,State#state{buff=Rest});
+ {fatal_error,_Loc,Reason,_EndTags,_EventState} ->
+ ?error(Connection#connection.name,[{parse_error,Reason},
+ {data,Data}]),
+ case Reason of
+ {could_not_fetch_data,Msg} ->
+ handle_msg(Msg,State#state{buff = <<>>});
+ _Other ->
+ Pending1 =
+ case State#state.pending of
+ [] ->
+ [];
+ Pending ->
+ %% Assuming the first request gets the
+ %% first answer
+ P=#pending{tref=TRef,caller=Caller} =
+ lists:last(Pending),
+ timer:cancel(TRef),
+ Reason1 = {failed_to_parse_received_data,Reason},
+ ct_gen_conn:return(Caller,{error,Reason1}),
+ lists:delete(P,Pending)
+ end,
+ {noreply,State#state{pending=Pending1,buff = <<>>}}
+ end
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Parsing of XML data
+%% Contiuation function for the sax parser
+sax_cont(done) ->
+ {<<>>,done};
+sax_cont({Data,Connection,false}) ->
+ case binary:split(Data,[?END_TAG],[]) of
+ [All] ->
+ %% No end tag found. Remove what could be a part
+ %% of an end tag from the data and save for next
+ %% iteration
+ SafeSize = size(All)-5,
+ <<New:SafeSize/binary,Save:5/binary>> = All,
+ {New,{Save,Connection,true}};
+ [_Msg,_Rest]=Msgs ->
+ %% We have at least one full message. Any excess data will
+ %% be returned from xmerl_sax_parser:stream/2 in the Rest
+ %% parameter.
+ {list_to_binary(Msgs),done}
+ end;
+sax_cont({Data,Connection,true}) ->
+ case ssh_receive_data() of
+ {ok,Bin} ->
+ log(Connection,recv,Bin),
+ sax_cont({<<Data/binary,Bin/binary>>,Connection,false});
+ {error,Reason} ->
+ throw({could_not_fetch_data,Reason})
+ end.
+
+
+
+%% Event function for the sax parser. It builds a simple XML structure.
+%% Care is taken to keep namespace attributes and prefixes as in the original XML.
+sax_event(Event,_Loc,State) ->
+ sax_event(Event,State).
+
+sax_event({startPrefixMapping, Prefix, Uri},Acc) ->
+ %% startPrefixMapping will always come immediately before the
+ %% startElement where the namespace is defined.
+ [{xmlns,{Prefix,Uri}}|Acc];
+sax_event({startElement,_Uri,_Name,QN,Attrs},Acc) ->
+ %% Pick out any namespace attributes inserted due to a
+ %% startPrefixMapping event.The rest of Acc will then be only
+ %% elements.
+ {NsAttrs,NewAcc} = split_attrs_and_elements(Acc,[]),
+ Tag = qn_to_tag(QN),
+ [{Tag,NsAttrs ++ parse_attrs(Attrs),[]}|NewAcc];
+sax_event({endElement,_Uri,_Name,_QN},[{Name,Attrs,Cont},{Parent,PA,PC}|Acc]) ->
+ [{Parent,PA,[{Name,Attrs,lists:reverse(Cont)}|PC]}|Acc];
+sax_event(endDocument,[{Tag,Attrs,Cont}]) ->
+ {Tag,Attrs,lists:reverse(Cont)};
+sax_event({characters,String},[{Name,Attrs,Cont}|Acc]) ->
+ [{Name,Attrs,[String|Cont]}|Acc];
+sax_event(_Event,State) ->
+ State.
+
+split_attrs_and_elements([{xmlns,{Prefix,Uri}}|Rest],Attrs) ->
+ split_attrs_and_elements(Rest,[{xmlnstag(Prefix),Uri}|Attrs]);
+split_attrs_and_elements(Elements,Attrs) ->
+ {Attrs,Elements}.
+
+xmlnstag([]) ->
+ xmlns;
+xmlnstag(Prefix) ->
+ list_to_atom("xmlns:"++Prefix).
+
+qn_to_tag({[],Name}) ->
+ list_to_atom(Name);
+qn_to_tag({Prefix,Name}) ->
+ list_to_atom(Prefix ++ ":" ++ Name).
+
+parse_attrs([{_Uri, [], Name, Value}|Attrs]) ->
+ [{list_to_atom(Name),Value}|parse_attrs(Attrs)];
+parse_attrs([{_Uri, Prefix, Name, Value}|Attrs]) ->
+ [{list_to_atom(Prefix ++ ":" ++ Name),Value}|parse_attrs(Attrs)];
+parse_attrs([]) ->
+ [].
+
+
+%%%-----------------------------------------------------------------
+%%% Decoding of parsed XML data
+decode({Tag,Attrs,_}=E, #state{connection=Connection,pending=Pending}=State) ->
+ ConnName = Connection#connection.name,
+ case get_local_name_atom(Tag) of
+ 'rpc-reply' ->
+ case get_msg_id(Attrs) of
+ undefined ->
+ case Pending of
+ [#pending{msg_id=MsgId}] ->
+ ?error(ConnName,[{warning,rpc_reply_missing_msg_id},
+ {assuming,MsgId}]),
+ decode_rpc_reply(MsgId,E,State);
+ _ ->
+ ?error(ConnName,[{error,rpc_reply_missing_msg_id}]),
+ {noreply,State}
+ end;
+ MsgId ->
+ decode_rpc_reply(MsgId,E,State)
+ end;
+ hello ->
+ case State#state.hello_status of
+ undefined ->
+ case decode_hello(E) of
+ {ok,SessionId,Capabilities} ->
+ {noreply,State#state{session_id = SessionId,
+ capabilities = Capabilities,
+ hello_status = received}};
+ {error,Reason} ->
+ {noreply,State#state{hello_status = {error,Reason}}}
+ end;
+ #pending{tref=TRef,caller=Caller} ->
+ timer:cancel(TRef),
+ case decode_hello(E) of
+ {ok,SessionId,Capabilities} ->
+ ct_gen_conn:return(Caller,ok),
+ {noreply,State#state{session_id = SessionId,
+ capabilities = Capabilities,
+ hello_status = done}};
+ {error,Reason} ->
+ ct_gen_conn:return(Caller,{error,Reason}),
+ {stop,State#state{hello_status={error,Reason}}}
+ end;
+ Other ->
+ ?error(ConnName,[{got_unexpected_hello,E},
+ {hello_status,Other}]),
+ {noreply,State}
+ end;
+ notification ->
+ EventReceiver = State#state.event_receiver,
+ EventReceiver ! E,
+ {noreply,State};
+ Other ->
+ %% Result of send/2, when not sending an rpc request - or
+ %% if netconf server sends noise. Can handle this only if
+ %% there is just one pending that matches (i.e. has
+ %% undefined msg_id and op)
+ case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of
+ [#pending{tref=TRef,
+ caller=Caller}] ->
+ timer:cancel(TRef),
+ ct_gen_conn:return(Caller,E),
+ {noreply,State#state{pending=[]}};
+ _ ->
+ ?error(ConnName,[{got_unexpected_msg,Other},
+ {expecting,Pending}]),
+ {noreply,State}
+ end
+
+ end.
+
+get_msg_id(Attrs) ->
+ case lists:keyfind('message-id',1,Attrs) of
+ {_,Str} ->
+ list_to_integer(Str);
+ false ->
+ undefined
+ end.
+
+decode_rpc_reply(MsgId,{_,Attrs,Content0}=E,#state{pending=Pending} = State) ->
+ case lists:keytake(MsgId,#pending.msg_id,Pending) of
+ {value, #pending{tref=TRef,op=Op,caller=Caller}, Pending1} ->
+ timer:cancel(TRef),
+ Content = forward_xmlns_attr(Attrs,Content0),
+ {CallerReply,{ServerReply,State2}} =
+ do_decode_rpc_reply(Op,Content,State#state{pending=Pending1}),
+ ct_gen_conn:return(Caller,CallerReply),
+ {ServerReply,State2};
+ false ->
+ %% Result of send/2, when receiving a correct
+ %% rpc-reply. Can handle this only if there is just one
+ %% pending that matches (i.e. has undefined msg_id and op)
+ case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of
+ [#pending{tref=TRef,
+ msg_id=undefined,
+ op=undefined,
+ caller=Caller}] ->
+ timer:cancel(TRef),
+ ct_gen_conn:return(Caller,E),
+ {noreply,State#state{pending=[]}};
+ _ ->
+ ConnName = (State#state.connection)#connection.name,
+ ?error(ConnName,[{got_unexpected_msg_id,MsgId},
+ {expecting,Pending}]),
+ {noreply,State}
+ end
+ end.
+
+do_decode_rpc_reply(Op,Result,State)
+ when Op==lock; Op==unlock; Op==edit_config; Op==delete_config;
+ Op==copy_config; Op==kill_session ->
+ {decode_ok(Result),{noreply,State}};
+do_decode_rpc_reply(Op,Result,State)
+ when Op==get; Op==get_config; Op==action ->
+ {decode_data(Result),{noreply,State}};
+do_decode_rpc_reply(close_session,Result,State) ->
+ case decode_ok(Result) of
+ ok -> {ok,{stop,State}};
+ Other -> {Other,{noreply,State}}
+ end;
+do_decode_rpc_reply({create_subscription,Caller},Result,State) ->
+ case decode_ok(Result) of
+ ok ->
+ {ok,{noreply,State#state{event_receiver=Caller}}};
+ Other ->
+ {Other,{noreply,State}}
+ end;
+do_decode_rpc_reply(get_event_streams,Result,State) ->
+ {decode_streams(decode_data(Result)),{noreply,State}};
+do_decode_rpc_reply(undefined,Result,State) ->
+ {Result,{noreply,State}}.
+
+
+
+decode_ok([{Tag,Attrs,Content}]) ->
+ case get_local_name_atom(Tag) of
+ ok ->
+ ok;
+ 'rpc-error' ->
+ {error,forward_xmlns_attr(Attrs,Content)};
+ _Other ->
+ {error,{unexpected_rpc_reply,[{Tag,Attrs,Content}]}}
+ end;
+decode_ok(Other) ->
+ {error,{unexpected_rpc_reply,Other}}.
+
+decode_data([{Tag,Attrs,Content}]) ->
+ case get_local_name_atom(Tag) of
+ data ->
+ %% Since content of data has nothing from the netconf
+ %% namespace, we remove the parent's xmlns attribute here
+ %% - just to make the result cleaner
+ {ok,forward_xmlns_attr(remove_xmlnsattr_for_tag(Tag,Attrs),Content)};
+ 'rpc-error' ->
+ {error,forward_xmlns_attr(Attrs,Content)};
+ _Other ->
+ {error,{unexpected_rpc_reply,[{Tag,Attrs,Content}]}}
+ end;
+decode_data(Other) ->
+ {error,{unexpected_rpc_reply,Other}}.
+
+get_qualified_name(Tag) ->
+ case string:tokens(atom_to_list(Tag),":") of
+ [TagStr] -> {[],TagStr};
+ [PrefixStr,TagStr] -> {PrefixStr,TagStr}
+ end.
+
+get_local_name_atom(Tag) ->
+ {_,TagStr} = get_qualified_name(Tag),
+ list_to_atom(TagStr).
+
+
+%% Remove the xmlns attr that points to the tag. I.e. if the tag has a
+%% prefix, remove {'xmlns:prefix',_}, else remove default {xmlns,_}.
+remove_xmlnsattr_for_tag(Tag,Attrs) ->
+ {Prefix,_TagStr} = get_qualified_name(Tag),
+ XmlnsTag = xmlnstag(Prefix),
+ case lists:keytake(XmlnsTag,1,Attrs) of
+ {value,_,NoNsAttrs} ->
+ NoNsAttrs;
+ false ->
+ Attrs
+ end.
+
+%% Take all xmlns attributes from the parent's attribute list and
+%% forward into all childrens' attribute lists. But do not overwrite
+%% any.
+forward_xmlns_attr(ParentAttrs,Children) ->
+ do_forward_xmlns_attr(get_all_xmlns_attrs(ParentAttrs,[]),Children).
+
+do_forward_xmlns_attr(XmlnsAttrs,[{ChT,ChA,ChC}|Children]) ->
+ ChA1 = add_xmlns_attrs(XmlnsAttrs,ChA),
+ [{ChT,ChA1,ChC} | do_forward_xmlns_attr(XmlnsAttrs,Children)];
+do_forward_xmlns_attr(_XmlnsAttrs,[]) ->
+ [].
+
+add_xmlns_attrs([{Key,_}=A|XmlnsAttrs],ChA) ->
+ case lists:keymember(Key,1,ChA) of
+ true ->
+ add_xmlns_attrs(XmlnsAttrs,ChA);
+ false ->
+ add_xmlns_attrs(XmlnsAttrs,[A|ChA])
+ end;
+add_xmlns_attrs([],ChA) ->
+ ChA.
+
+get_all_xmlns_attrs([{xmlns,_}=Default|Attrs],XmlnsAttrs) ->
+ get_all_xmlns_attrs(Attrs,[Default|XmlnsAttrs]);
+get_all_xmlns_attrs([{Key,_}=Attr|Attrs],XmlnsAttrs) ->
+ case atom_to_list(Key) of
+ "xmlns:"++_Prefix ->
+ get_all_xmlns_attrs(Attrs,[Attr|XmlnsAttrs]);
+ _ ->
+ get_all_xmlns_attrs(Attrs,XmlnsAttrs)
+ end;
+get_all_xmlns_attrs([],XmlnsAttrs) ->
+ XmlnsAttrs.
+
+
+%% Decode server hello to pick out session id and capabilities
+decode_hello({hello,_Attrs,Hello}) ->
+ case lists:keyfind('session-id',1,Hello) of
+ {'session-id',_,[SessionId]} ->
+ case lists:keyfind(capabilities,1,Hello) of
+ {capabilities,_,Capabilities} ->
+ case decode_caps(Capabilities,[],false) of
+ {ok,Caps} ->
+ {ok,list_to_integer(SessionId),Caps};
+ Error ->
+ Error
+ end;
+ false ->
+ {error,{incorrect_hello,capabilities_not_found}}
+ end;
+ false ->
+ {error,{incorrect_hello,no_session_id_found}}
+ end.
+
+decode_caps([{capability,[],[?NETCONF_BASE_CAP++Vsn=Cap]} |Caps], Acc, _) ->
+ case Vsn of
+ ?NETCONF_BASE_CAP_VSN ->
+ decode_caps(Caps, [Cap|Acc], true);
+ _ ->
+ {error,{incompatible_base_capability_vsn,Vsn}}
+ end;
+decode_caps([{capability,[],[Cap]}|Caps],Acc,Base) ->
+ decode_caps(Caps,[Cap|Acc],Base);
+decode_caps([H|_T],_,_) ->
+ {error,{unexpected_capability_element,H}};
+decode_caps([],_,false) ->
+ {error,{incorrect_hello,no_base_capability_found}};
+decode_caps([],Acc,true) ->
+ {ok,lists:reverse(Acc)}.
+
+
+%% Return a list of {Name,Data}, where data is a {Tag,Value} list for each stream
+decode_streams({error,Reason}) ->
+ {error,Reason};
+decode_streams({ok,[{netconf,_,Streams}]}) ->
+ {ok,decode_streams(Streams)};
+decode_streams([{streams,_,Streams}]) ->
+ decode_streams(Streams);
+decode_streams([{stream,_,Stream} | Streams]) ->
+ {name,_,[Name]} = lists:keyfind(name,1,Stream),
+ [{Name,[{Tag,Value} || {Tag,_,[Value]} <- Stream, Tag /= name]}
+ | decode_streams(Streams)];
+decode_streams([]) ->
+ [].
+
+
+%%%-----------------------------------------------------------------
+%%% Logging
+
+log(Connection,Action) ->
+ log(Connection,Action,<<>>).
+log(#connection{host=Host,port=Port,name=Name},Action,Data) ->
+ error_logger:info_report(#conn_log{client=self(),
+ address={Host,Port},
+ name=Name,
+ action=Action,
+ module=?MODULE},
+ Data).
+
+
+%% Log callback - called from the error handler process
+format_data(raw,Data) ->
+ io_lib:format("~n~s~n",[hide_password(Data)]);
+format_data(pretty,Data) ->
+ io_lib:format("~n~s~n",[indent(Data)]);
+format_data(html,Data) ->
+ io_lib:format("~n~s~n",[html_format(Data)]).
+
+%%%-----------------------------------------------------------------
+%%% Hide password elements from XML data
+hide_password(Bin) ->
+ re:replace(Bin,<<"(<password[^>]*>)[^<]*(</password>)">>,<<"\\1*****\\2">>,
+ [global,{return,binary}]).
+
+%%%-----------------------------------------------------------------
+%%% HTML formatting
+html_format(Bin) ->
+ binary:replace(indent(Bin),<<"<">>,<<"&lt;">>,[global]).
+
+%%%-----------------------------------------------------------------
+%%% Indentation of XML code
+indent(Bin) ->
+ String = normalize(hide_password(Bin)),
+ IndentedString =
+ case erase(part_of_line) of
+ undefined ->
+ indent1(String,[]);
+ Part ->
+ indent1(lists:reverse(Part)++String,erase(indent))
+ end,
+ list_to_binary(IndentedString).
+
+%% Normalizes the XML document by removing all space and newline
+%% between two XML tags.
+%% Returns a list, no matter if the input was a list or a binary.
+normalize(Str) ->
+ re:replace(Str,<<">[ \r\n\t]+<">>,<<"><">>,[global,{return,list}]).
+
+
+indent1("<?"++Rest1,Indent1) ->
+ %% Prolog
+ {Line,Rest2,Indent2} = indent_line(Rest1,Indent1,[$?,$<]),
+ Line++indent1(Rest2,Indent2);
+indent1("</"++Rest1,Indent1) ->
+ %% Stop tag
+ {Line,Rest2,Indent2} = indent_line1(Rest1,Indent1,[$/,$<]),
+ "\n"++Line++indent1(Rest2,Indent2);
+indent1("<"++Rest1,Indent1) ->
+ %% Start- or empty tag
+ put(tag,get_tag(Rest1)),
+ {Line,Rest2,Indent2} = indent_line(Rest1,Indent1,[$<]),
+ "\n"++Line++indent1(Rest2,Indent2);
+indent1([H|T],Indent) ->
+ [H|indent1(T,Indent)];
+indent1([],_Indent) ->
+ [].
+
+indent_line("?>"++Rest,Indent,Line) ->
+ %% Prolog
+ {lists:reverse(Line)++"?>",Rest,Indent};
+indent_line("/></"++Rest,Indent,Line) ->
+ %% Empty tag, and stop of parent tag -> one step out in indentation
+ {Indent++lists:reverse(Line)++"/>","</"++Rest,Indent--" "};
+indent_line("/>"++Rest,Indent,Line) ->
+ %% Empty tag, then probably next tag -> keep indentation
+ {Indent++lists:reverse(Line)++"/>",Rest,Indent};
+indent_line("></"++Rest,Indent,Line) ->
+ LastTag = erase(tag),
+ case get_tag(Rest) of
+ LastTag ->
+ %% Start and stop tag, but no content
+ indent_line1(Rest,Indent,[$/,$<,$>|Line]);
+ _ ->
+ %% Stop tag completed, and then stop tag of parent -> one step out
+ {Indent++lists:reverse(Line)++">","</"++Rest,Indent--" "}
+ end;
+indent_line("><"++Rest,Indent,Line) ->
+ %% Stop tag completed, and new tag comming -> keep indentation
+ {Indent++lists:reverse(Line)++">","<"++Rest," "++Indent};
+indent_line("</"++Rest,Indent,Line) ->
+ %% Stop tag starting -> search for end of this tag
+ indent_line1(Rest,Indent,[$/,$<|Line]);
+indent_line([H|T],Indent,Line) ->
+ indent_line(T,Indent,[H|Line]);
+indent_line([],Indent,Line) ->
+ %% The line is not complete - will be continued later
+ put(part_of_line,Line),
+ put(indent,Indent),
+ {[],[],Indent}.
+
+indent_line1("></"++Rest,Indent,Line) ->
+ %% Stop tag completed, and then stop tag of parent -> one step out
+ {Indent++lists:reverse(Line)++">","</"++Rest,Indent--" "};
+indent_line1(">"++Rest,Indent,Line) ->
+ %% Stop tag completed -> keep indentation
+ {Indent++lists:reverse(Line)++">",Rest,Indent};
+indent_line1([H|T],Indent,Line) ->
+ indent_line1(T,Indent,[H|Line]);
+indent_line1([],Indent,Line) ->
+ %% The line is not complete - will be continued later
+ put(part_of_line,Line),
+ put(indent,Indent),
+ {[],[],Indent}.
+
+get_tag("/>"++_) ->
+ [];
+get_tag(">"++_) ->
+ [];
+get_tag([H|T]) ->
+ [H|get_tag(T)];
+get_tag([]) ->
+ %% The line is not complete - will be continued later.
+ [].
+
+
+%%%-----------------------------------------------------------------
+%%% SSH stuff
+ssh_receive_data() ->
+ receive
+ {ssh_cm, _CM, {data, _Ch, _Type, Data}} ->
+ {ok, Data};
+ {ssh_cm, _CM, {Closed, _Ch}} = X when Closed == closed; Closed == eof ->
+ {error,X};
+ {_Ref,timeout} = X ->
+ {error,X}
+ end.
+
+ssh_open(#options{host=Host,timeout=Timeout,port=Port,ssh=SshOpts,name=Name}) ->
+ case ssh:connect(Host, Port,
+ [{user_interaction,false},
+ {silently_accept_hosts, true}|SshOpts]) of
+ {ok,CM} ->
+ case ssh_connection:session_channel(CM, Timeout) of
+ {ok,Ch} ->
+ case ssh_connection:subsystem(CM, Ch, "netconf", Timeout) of
+ success ->
+ {ok, #connection{reference = {CM,Ch},
+ host = Host,
+ port = Port,
+ name = Name}};
+ failure ->
+ ssh:close(CM),
+ {error,{ssh,could_not_execute_netconf_subsystem}}
+ end;
+ {error, Reason} ->
+ ssh:close(CM),
+ {error,{ssh,could_not_open_channel,Reason}};
+ Other ->
+ %% Bug in ssh?? got {closed,0} here once...
+ {error,{ssh,unexpected_from_session_channel,Other}}
+ end;
+ {error,Reason} ->
+ {error,{ssh,could_not_connect_to_server,Reason}}
+ end.
+
+ssh_send(#connection{reference = {CM,Ch}}, Data) ->
+ case ssh_connection:send(CM, Ch, Data) of
+ ok -> ok;
+ {error,Reason} -> {error,{ssh,failed_to_send_data,Reason}}
+ end.
+
+ssh_close(#connection{reference = {CM,_Ch}}) ->
+ ssh:close(CM).
+
+
+%%----------------------------------------------------------------------
+%% END OF MODULE
+%%----------------------------------------------------------------------
diff --git a/lib/common_test/src/ct_netconfc.hrl b/lib/common_test/src/ct_netconfc.hrl
new file mode 100644
index 0000000000..295a61a98b
--- /dev/null
+++ b/lib/common_test/src/ct_netconfc.hrl
@@ -0,0 +1,58 @@
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% File: ct_netconfc.hrl
+%%
+%% Description:
+%% This file defines constant values and records used by the
+%% netconf client ct_netconfc.
+%%
+%% @author Support
+%% @doc Netconf Client Interface.
+%% @end
+%%----------------------------------------------------------------------
+%%----------------------------------------------------------------------
+
+
+%% Default port number (RFC 4742/IANA).
+-define(DEFAULT_PORT, 830).
+
+%% Default timeout to wait for netconf server to reply to a request
+-define(DEFAULT_TIMEOUT, infinity). %% msec
+
+%% Namespaces
+-define(NETCONF_NAMESPACE_ATTR,[{xmlns,?NETCONF_NAMESPACE}]).
+-define(ACTION_NAMESPACE_ATTR,[{xmlns,?ACTION_NAMESPACE}]).
+-define(NETCONF_NOTIF_NAMESPACE_ATTR,[{xmlns,?NETCONF_NOTIF_NAMESPACE}]).
+-define(NETMOD_NOTIF_NAMESPACE_ATTR,[{xmlns,?NETMOD_NOTIF_NAMESPACE}]).
+
+-define(NETCONF_NAMESPACE,"urn:ietf:params:xml:ns:netconf:base:1.0").
+-define(ACTION_NAMESPACE,"urn:com:ericsson:ecim:1.0").
+-define(NETCONF_NOTIF_NAMESPACE,
+ "urn:ietf:params:xml:ns:netconf:notification:1.0").
+-define(NETMOD_NOTIF_NAMESPACE,"urn:ietf:params:xml:ns:netmod:notification").
+
+%% Capabilities
+-define(NETCONF_BASE_CAP,"urn:ietf:params:netconf:base:").
+-define(NETCONF_BASE_CAP_VSN,"1.0").
+
+%% Misc
+-define(END_TAG,<<"]]>]]>">>).
+
+-define(FORMAT(_F, _A), lists:flatten(io_lib:format(_F, _A))).
diff --git a/lib/common_test/src/ct_repeat.erl b/lib/common_test/src/ct_repeat.erl
index be3c485b75..a47309c6ee 100644
--- a/lib/common_test/src/ct_repeat.erl
+++ b/lib/common_test/src/ct_repeat.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,72 +41,86 @@ loop_test(If,Args) when is_list(Args) ->
case get_loop_info(Args) of
no_loop ->
false;
- {error,E} ->
+ E = {error,_} ->
io:format("Common Test error: ~p\n\n",[E]),
file:set_cwd(Cwd),
E;
{repeat,N} ->
io:format("\nCommon Test: Will repeat tests ~w times.\n\n",[N]),
Args1 = [{loop_info,[{repeat,1,N}]} | Args],
- loop(If,repeat,0,N,undefined,Args1,undefined),
- file:set_cwd(Cwd);
+ Result = loop(If,repeat,0,N,undefined,Args1,undefined,[]),
+ file:set_cwd(Cwd),
+ Result;
{stop_time,StopTime} ->
- case remaining_time(StopTime) of
- 0 ->
- io:format("\nCommon Test: No time left to run tests.\n\n",[]),
- ok;
- Secs ->
- io:format("\nCommon Test: Will repeat tests for ~s.\n\n",
- [ts(Secs)]),
- TPid =
- case lists:keymember(force_stop,1,Args) of
- true ->
- CtrlPid = self(),
- spawn(fun() -> stop_after(CtrlPid,Secs) end);
- false ->
- undefined
- end,
- Args1 = [{loop_info,[{stop_time,Secs,StopTime,1}]} | Args],
- loop(If,stop_time,0,Secs,StopTime,Args1,TPid)
- end,
- file:set_cwd(Cwd)
+ Result =
+ case remaining_time(StopTime) of
+ 0 ->
+ io:format("\nCommon Test: "
+ "No time left to run tests.\n\n",[]),
+ {error,not_enough_time};
+ Secs ->
+ io:format("\nCommon Test: "
+ "Will repeat tests for ~s.\n\n",[ts(Secs)]),
+ TPid =
+ case lists:keymember(force_stop,1,Args) of
+ true ->
+ CtrlPid = self(),
+ spawn(fun() -> stop_after(CtrlPid,Secs) end);
+ false ->
+ undefined
+ end,
+ Args1 = [{loop_info,[{stop_time,Secs,StopTime,1}]} | Args],
+ loop(If,stop_time,0,Secs,StopTime,Args1,TPid,[])
+ end,
+ file:set_cwd(Cwd),
+ Result
end.
-loop(_,repeat,N,N,_,_Args,_) ->
- ok;
+loop(_,repeat,N,N,_,_Args,_,AccResult) ->
+ lists:reverse(AccResult);
-loop(If,Type,N,Data0,Data1,Args,TPid) ->
+loop(If,Type,N,Data0,Data1,Args,TPid,AccResult) ->
Pid = spawn_tester(If,self(),Args),
receive
{'EXIT',Pid,Reason} ->
- io:format("Test run crashed! This could be an internal error "
- "- please report!\n\n"
- "~p\n\n",[Reason]),
- cancel(TPid),
- {error,Reason};
+ case Reason of
+ {user_error,What} ->
+ io:format("\nTest run failed!\nReason: ~p\n\n\n", [What]),
+ cancel(TPid),
+ {error,What};
+ _ ->
+ io:format("Test run crashed! This could be an internal error "
+ "- please report!\n\n"
+ "~p\n\n\n",[Reason]),
+ cancel(TPid),
+ {error,Reason}
+ end;
{Pid,{error,Reason}} ->
- io:format("\nTest run failed!\nReason: ~p\n\n",[Reason]),
+ io:format("\nTest run failed!\nReason: ~p\n\n\n",[Reason]),
cancel(TPid),
{error,Reason};
{Pid,Result} ->
if Type == repeat ->
- io:format("\nTest run ~w(~w) complete.\n\n",[N+1,Data0]),
+ io:format("\nTest run ~w(~w) complete.\n\n\n",[N+1,Data0]),
lists:keydelete(loop_info,1,Args),
Args1 = [{loop_info,[{repeat,N+2,Data0}]} | Args],
- loop(If,repeat,N+1,Data0,Data1,Args1,TPid);
+ loop(If,repeat,N+1,Data0,Data1,Args1,TPid,[Result|AccResult]);
Type == stop_time ->
case remaining_time(Data1) of
0 ->
- io:format("\nTest time (~s) has run out.\n\n",[ts(Data0)]),
+ io:format("\nTest time (~s) has run out.\n\n\n",
+ [ts(Data0)]),
cancel(TPid),
- Result;
+ lists:reverse([Result|AccResult]);
Secs ->
io:format("\n~s of test time remaining, "
- "starting run #~w...\n\n",[ts(Secs),N+2]),
+ "starting run #~w...\n\n\n",
+ [ts(Secs),N+2]),
lists:keydelete(loop_info,1,Args),
ST = {stop_time,Data0,Data1,N+2},
Args1 = [{loop_info,[ST]} | Args],
- loop(If,stop_time,N+1,Data0,Data1,Args1,TPid)
+ loop(If,stop_time,N+1,Data0,Data1,Args1,TPid,
+ [Result|AccResult])
end
end
end.
@@ -116,7 +130,7 @@ spawn_tester(script,Ctrl,Args) ->
spawn_tester(func,Ctrl,Opts) ->
Tester = fun() ->
- case catch ct_run:run_test1(Opts) of
+ case catch ct_run:run_test2(Opts) of
{'EXIT',Reason} ->
exit(Reason);
Result ->
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 0a9bb5af67..d80d216f9e 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,14 +37,22 @@
%% Misc internal functions
--export([variables_file_name/1,script_start1/2,run_test1/1]).
+-export([variables_file_name/1,script_start1/2,run_test2/1]).
+-include("ct.hrl").
-include("ct_event.hrl").
-include("ct_util.hrl").
-define(abs(Name), filename:absname(Name)).
-define(testdir(Name, Suite), ct_util:get_testdir(Name, Suite)).
+-define(EXIT_STATUS_TEST_SUCCESSFUL, 0).
+-define(EXIT_STATUS_TEST_CASE_FAILED, 1).
+-define(EXIT_STATUS_TEST_RUN_FAILED, 2).
+
+-define(default_verbosity, [{default,?MAX_VERBOSITY},
+ {'$unspecified',?MAX_VERBOSITY}]).
+
-record(opts, {label,
profile,
vts,
@@ -54,17 +62,22 @@
step,
logdir,
logopts = [],
+ basic_html,
+ verbosity = [],
config = [],
event_handlers = [],
ct_hooks = [],
- enable_builtin_hooks = true,
+ enable_builtin_hooks,
include = [],
- silent_connections,
+ auto_compile,
+ silent_connections = [],
stylesheet,
multiply_timetraps = 1,
scale_timetraps = false,
+ create_priv_dir,
testspecs = [],
- tests}).
+ tests,
+ starter}).
%%%-----------------------------------------------------------------
%%% @spec script_start() -> void()
@@ -101,7 +114,8 @@ script_start() ->
end, Flags)
end,
%% used for purpose of testing the run_test interface
- io:format(user, "~n-------------------- START ARGS --------------------~n", []),
+ io:format(user, "~n-------------------- START ARGS "
+ "--------------------~n", []),
io:format(user, "--- Init args:~n~p~n", [FlagFilter(Init)]),
io:format(user, "--- CT args:~n~p~n", [FlagFilter(CtArgs)]),
EnvArgs = opts2args(EnvStartOpts),
@@ -109,7 +123,8 @@ script_start() ->
[EnvStartOpts,EnvArgs]),
Merged = merge_arguments(CtArgs ++ EnvArgs),
io:format(user, "--- Merged args:~n~p~n", [FlagFilter(Merged)]),
- io:format(user, "----------------------------------------------------~n~n", []),
+ io:format(user, "-----------------------------------"
+ "-----------------~n~n", []),
Merged;
_ ->
merge_arguments(CtArgs)
@@ -121,46 +136,100 @@ script_start() ->
script_start(Args) ->
Tracing = start_trace(Args),
- Res =
- case ct_repeat:loop_test(script, Args) of
- false ->
- {ok,Cwd} = file:get_cwd(),
- CTVsn =
- case filename:basename(code:lib_dir(common_test)) of
- CTBase when is_list(CTBase) ->
- case string:tokens(CTBase, "-") of
- ["common_test",Vsn] -> " v"++Vsn;
- _ -> ""
- end
- end,
- io:format("~nCommon Test~s starting (cwd is ~s)~n~n", [CTVsn,Cwd]),
- Self = self(),
- Pid = spawn_link(fun() -> script_start1(Self, Args) end),
- receive
- {'EXIT',Pid,Reason} ->
- case Reason of
- {user_error,What} ->
- io:format("\nTest run failed!\nReason: ~p\n\n", [What]),
- {error,What};
- _ ->
- io:format("Test run crashed! This could be an internal error "
- "- please report!\n\n"
- "~p\n\n", [Reason]),
- {error,Reason}
- end;
- {Pid,{error,Reason}} ->
- io:format("\nTest run failed! Reason:\n~p\n\n",[Reason]),
- {error,Reason};
- {Pid,Result} ->
- Result
- end;
- Result ->
- Result
- end,
+ case ct_repeat:loop_test(script, Args) of
+ false ->
+ {ok,Cwd} = file:get_cwd(),
+ CTVsn =
+ case filename:basename(code:lib_dir(common_test)) of
+ CTBase when is_list(CTBase) ->
+ case string:tokens(CTBase, "-") of
+ ["common_test",Vsn] -> " v"++Vsn;
+ _ -> ""
+ end
+ end,
+ io:format("~nCommon Test~s starting (cwd is ~s)~n~n",
+ [CTVsn,Cwd]),
+ Self = self(),
+ Pid = spawn_link(fun() -> script_start1(Self, Args) end),
+ receive
+ {'EXIT',Pid,Reason} ->
+ case Reason of
+ {user_error,What} ->
+ io:format("\nTest run failed!\nReason: ~p\n\n\n",
+ [What]),
+ finish(Tracing, ?EXIT_STATUS_TEST_RUN_FAILED, Args);
+ _ ->
+ io:format("Test run crashed! "
+ "This could be an internal error "
+ "- please report!\n\n"
+ "~p\n\n\n", [Reason]),
+ finish(Tracing, ?EXIT_STATUS_TEST_RUN_FAILED, Args)
+ end;
+ {Pid,{error,Reason}} ->
+ io:format("\nTest run failed! Reason:\n~p\n\n\n",[Reason]),
+ finish(Tracing, ?EXIT_STATUS_TEST_RUN_FAILED, Args);
+ {Pid,Result} ->
+ io:nl(),
+ finish(Tracing, analyze_test_result(Result, Args), Args)
+ end;
+ {error,_LoopReason} ->
+ finish(Tracing, ?EXIT_STATUS_TEST_RUN_FAILED, Args);
+ Result ->
+ io:nl(),
+ finish(Tracing, analyze_test_result(Result, Args), Args)
+ end.
+
+%% analyze the result of one test run, or many (in case of looped test)
+analyze_test_result(ok, _) ->
+ ?EXIT_STATUS_TEST_SUCCESSFUL;
+analyze_test_result({error,_Reason}, _) ->
+ ?EXIT_STATUS_TEST_RUN_FAILED;
+analyze_test_result({_Ok,Failed,{_UserSkipped,AutoSkipped}}, Args) ->
+ if Failed > 0 ->
+ ?EXIT_STATUS_TEST_CASE_FAILED;
+ true ->
+ case AutoSkipped of
+ 0 ->
+ ?EXIT_STATUS_TEST_SUCCESSFUL;
+ _ ->
+ case get_start_opt(exit_status,
+ fun([ExitOpt]) -> ExitOpt end,
+ Args) of
+ undefined ->
+ ?EXIT_STATUS_TEST_CASE_FAILED;
+ "ignore_config" ->
+ ?EXIT_STATUS_TEST_SUCCESSFUL
+ end
+ end
+ end;
+analyze_test_result([Result|Rs], Args) ->
+ case analyze_test_result(Result, Args) of
+ ?EXIT_STATUS_TEST_SUCCESSFUL ->
+ analyze_test_result(Rs, Args);
+ Other ->
+ Other
+ end;
+analyze_test_result([], _) ->
+ ?EXIT_STATUS_TEST_SUCCESSFUL;
+analyze_test_result(Unknown, _) ->
+ io:format("\nTest run failed! Reason:\n~p\n\n\n",[Unknown]),
+ ?EXIT_STATUS_TEST_RUN_FAILED.
+
+finish(Tracing, ExitStatus, Args) ->
stop_trace(Tracing),
timer:sleep(1000),
- io:nl(),
- Res.
+ %% it's possible to tell CT to finish execution with a call
+ %% to a different function than the normal halt/1 BIF
+ %% (meant to be used mainly for reading the CT exit status)
+ case get_start_opt(halt_with,
+ fun([HaltMod,HaltFunc]) -> {list_to_atom(HaltMod),
+ list_to_atom(HaltFunc)} end,
+ Args) of
+ undefined ->
+ halt(ExitStatus);
+ {M,F} ->
+ apply(M, F, [ExitStatus])
+ end.
script_start1(Parent, Args) ->
%% read general start flags
@@ -172,18 +241,23 @@ script_start1(Parent, 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),
+ Verbosity = verbosity_args2opts(Args),
MultTT = get_start_opt(multiply_timetraps,
fun([MT]) -> list_to_integer(MT) end, 1, Args),
ScaleTT = get_start_opt(scale_timetraps,
fun([CT]) -> list_to_atom(CT);
([]) -> true
end, false, Args),
+ CreatePrivDir = get_start_opt(create_priv_dir,
+ fun([PD]) -> list_to_atom(PD);
+ ([]) -> auto_per_tc
+ end, 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),
+ ([]) -> undefined
+ end, undefined, Args),
%% check flags and set corresponding application env variables
@@ -201,7 +275,7 @@ script_start1(Parent, Args) ->
end
end,
%% no_auto_compile + include
- IncludeDirs =
+ {AutoCompile,IncludeDirs} =
case proplists:get_value(no_auto_compile, Args) of
undefined ->
application:set_env(common_test, auto_compile, true),
@@ -217,45 +291,52 @@ script_start1(Parent, Args) ->
case os:getenv("CT_INCLUDE_PATH") of
false ->
application:set_env(common_test, include, InclDirs),
- InclDirs;
+ {undefined,InclDirs};
CtInclPath ->
AllInclDirs =
string:tokens(CtInclPath,[$:,$ ,$,]) ++ InclDirs,
application:set_env(common_test, include, AllInclDirs),
- AllInclDirs
+ {undefined,AllInclDirs}
end;
_ ->
application:set_env(common_test, auto_compile, false),
- []
+ {false,[]}
end,
%% silent connections
SilentConns =
get_start_opt(silent_connections,
- fun(["all"]) -> [];
+ fun(["all"]) -> [all];
(Conns) -> [list_to_atom(Conn) || Conn <- Conns]
- end, Args),
+ end, [], Args),
%% stylesheet
Stylesheet = get_start_opt(stylesheet,
fun([SS]) -> ?abs(SS) end, Args),
%% basic_html - used by ct_logs
- case proplists:get_value(basic_html, Args) of
- undefined ->
- application:set_env(common_test, basic_html, false);
- _ ->
- application:set_env(common_test, basic_html, true)
- end,
+ BasicHtml = case proplists:get_value(basic_html, Args) of
+ undefined ->
+ application:set_env(common_test, basic_html, false),
+ undefined;
+ _ ->
+ application:set_env(common_test, basic_html, true),
+ true
+ end,
StartOpts = #opts{label = Label, profile = Profile,
vts = Vts, shell = Shell, cover = Cover,
logdir = LogDir, logopts = LogOpts,
+ basic_html = BasicHtml,
+ verbosity = Verbosity,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
enable_builtin_hooks = EnableBuiltinHooks,
+ auto_compile = AutoCompile,
include = IncludeDirs,
silent_connections = SilentConns,
stylesheet = Stylesheet,
multiply_timetraps = MultTT,
- scale_timetraps = ScaleTT},
+ scale_timetraps = ScaleTT,
+ create_priv_dir = CreatePrivDir,
+ starter = script},
%% check if log files should be refreshed or go on to run tests...
Result = run_or_refresh(StartOpts, Args),
@@ -319,15 +400,30 @@ script_start2(StartOpts = #opts{vts = undefined,
AllLogOpts = merge_vals([StartOpts#opts.logopts,
SpecStartOpts#opts.logopts]),
+ AllVerbosity =
+ merge_keyvals([StartOpts#opts.verbosity,
+ SpecStartOpts#opts.verbosity]),
+ AllSilentConns =
+ merge_vals([StartOpts#opts.silent_connections,
+ SpecStartOpts#opts.silent_connections]),
+ Cover =
+ choose_val(StartOpts#opts.cover,
+ SpecStartOpts#opts.cover),
+ MultTT =
+ choose_val(StartOpts#opts.multiply_timetraps,
+ SpecStartOpts#opts.multiply_timetraps),
+ ScaleTT =
+ choose_val(StartOpts#opts.scale_timetraps,
+ SpecStartOpts#opts.scale_timetraps),
+
+ CreatePrivDir =
+ choose_val(StartOpts#opts.create_priv_dir,
+ SpecStartOpts#opts.create_priv_dir),
+
+ AllEvHs =
+ merge_vals([StartOpts#opts.event_handlers,
+ SpecStartOpts#opts.event_handlers]),
- Cover = choose_val(StartOpts#opts.cover,
- SpecStartOpts#opts.cover),
- MultTT = choose_val(StartOpts#opts.multiply_timetraps,
- SpecStartOpts#opts.multiply_timetraps),
- ScaleTT = choose_val(StartOpts#opts.scale_timetraps,
- SpecStartOpts#opts.scale_timetraps),
- AllEvHs = merge_vals([StartOpts#opts.event_handlers,
- SpecStartOpts#opts.event_handlers]),
AllCTHooks = merge_vals(
[StartOpts#opts.ct_hooks,
SpecStartOpts#opts.ct_hooks]),
@@ -337,9 +433,36 @@ script_start2(StartOpts = #opts{vts = undefined,
StartOpts#opts.enable_builtin_hooks,
SpecStartOpts#opts.enable_builtin_hooks),
+ Stylesheet =
+ choose_val(StartOpts#opts.stylesheet,
+ SpecStartOpts#opts.stylesheet),
+
AllInclude = merge_vals([StartOpts#opts.include,
SpecStartOpts#opts.include]),
application:set_env(common_test, include, AllInclude),
+
+ AutoCompile =
+ case choose_val(StartOpts#opts.auto_compile,
+ SpecStartOpts#opts.auto_compile) of
+ undefined ->
+ true;
+ ACBool ->
+ application:set_env(common_test,
+ auto_compile,
+ ACBool),
+ ACBool
+ end,
+
+ BasicHtml =
+ case choose_val(StartOpts#opts.basic_html,
+ SpecStartOpts#opts.basic_html) of
+ undefined ->
+ false;
+ BHBool ->
+ application:set_env(common_test, basic_html,
+ BHBool),
+ BHBool
+ end,
{TS,StartOpts#opts{label = Label,
profile = Profile,
@@ -347,14 +470,20 @@ script_start2(StartOpts = #opts{vts = undefined,
cover = Cover,
logdir = LogDir,
logopts = AllLogOpts,
+ basic_html = BasicHtml,
+ verbosity = AllVerbosity,
+ silent_connections = AllSilentConns,
config = SpecStartOpts#opts.config,
event_handlers = AllEvHs,
ct_hooks = AllCTHooks,
enable_builtin_hooks =
EnableBuiltinHooks,
+ stylesheet = Stylesheet,
+ auto_compile = AutoCompile,
include = AllInclude,
multiply_timetraps = MultTT,
- scale_timetraps = ScaleTT}}
+ scale_timetraps = ScaleTT,
+ create_priv_dir = CreatePrivDir}}
end;
_ ->
{undefined,StartOpts}
@@ -503,6 +632,7 @@ script_start4(#opts{label = Label, profile = Profile,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
logopts = LogOpts,
+ verbosity = Verbosity,
enable_builtin_hooks = EnableBuiltinHooks,
logdir = LogDir, testspecs = Specs}, _Args) ->
%% label - used by ct_logs
@@ -520,7 +650,8 @@ script_start4(#opts{label = Label, profile = Profile,
{ct_hooks, CTHooks},
{enable_builtin_hooks,EnableBuiltinHooks}]) of
ok ->
- ct_util:start(interactive, LogDir),
+ ct_util:start(interactive, LogDir,
+ add_verbosity_defaults(Verbosity)),
ct_util:set_testdata({logopts, LogOpts}),
log_ts_names(Specs),
io:nl(),
@@ -537,7 +668,7 @@ script_start4(#opts{vts = true, cover = Cover}, _) ->
%% Add support later (maybe).
io:format("\nCan't run cover in vts mode.\n\n", [])
end,
- erlang:halt();
+ {error,no_cover_in_vts_mode};
script_start4(#opts{shell = true, cover = Cover}, _) ->
case Cover of
@@ -546,7 +677,8 @@ script_start4(#opts{shell = true, cover = Cover}, _) ->
_ ->
%% Add support later (maybe).
io:format("\nCan't run cover in interactive mode.\n\n", [])
- end;
+ end,
+ {error,no_cover_in_interactive_mode};
script_start4(Opts = #opts{tests = Tests}, Args) ->
do_run(Tests, [], Opts, Args).
@@ -563,10 +695,12 @@ script_usage() ->
"\n\t[-dir TestDir1 TestDir2 .. TestDirN] |"
"\n\t[-suite Suite [-case Case]]"
"\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
+ "\n\t[-verbosity GenVLvl | [CategoryVLvl1 .. CategoryVLvlN]]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
"\n\t[-multiply_timetraps N]"
"\n\t[-scale_timetraps]"
+ "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
"\n\t[-basic_html]\n\n"),
io:format("Run tests from command line:\n\n"
"\tct_run [-dir TestDir1 TestDir2 .. TestDirN] |"
@@ -576,16 +710,18 @@ script_usage() ->
"\n\t[-userconfig CallbackModule ConfigFile1 .. ConfigFileN]"
"\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]"
"\n\t[-logdir LogDir]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
+ "\n\t[-verbosity GenVLvl | [CategoryVLvl1 .. CategoryVLvlN]]"
"\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]"
- "\n\t[-stylesheet CSSFile]"
+ "\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]"
"\n\t[-multiply_timetraps N]"
"\n\t[-scale_timetraps]"
+ "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
"\n\t[-basic_html]"
"\n\t[-repeat N [-force_stop]] |"
"\n\t[-duration HHMMSS [-force_stop]] |"
@@ -595,17 +731,19 @@ script_usage() ->
"\n\t[-config ConfigFile1 ConfigFile2 .. ConfigFileN]"
"\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]"
"\n\t[-logdir LogDir]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
+ "\n\t[-verbosity GenVLvl | [CategoryVLvl1 .. CategoryVLvlN]]"
"\n\t[-allow_user_terms]"
"\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]"
"\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]"
"\n\t[-multiply_timetraps N]"
"\n\t[-scale_timetraps]"
+ "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
"\n\t[-basic_html]"
"\n\t[-repeat N [-force_stop]] |"
"\n\t[-duration HHMMSS [-force_stop]] |"
@@ -683,7 +821,7 @@ run_test(StartOpts) when is_list(StartOpts) ->
Ref = monitor(process, CTPid),
receive
{'DOWN',Ref,process,CTPid,{user_error,Error}} ->
- Error;
+ {error,Error};
{'DOWN',Ref,process,CTPid,Other} ->
Other
end.
@@ -720,8 +858,10 @@ run_test2(StartOpts) ->
(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)
+ 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,
@@ -729,6 +869,19 @@ run_test2(StartOpts) ->
%% logopts
LogOpts = get_start_opt(logopts, value, [], StartOpts),
+ %% verbosity
+ Verbosity =
+ get_start_opt(verbosity,
+ fun(VLvls) when is_list(VLvls) ->
+ lists:map(fun(VLvl = {_Cat,_Lvl}) ->
+ VLvl;
+ (Lvl) ->
+ {'$unspecified',Lvl}
+ end, VLvls);
+ (VLvl) when is_integer(VLvl) ->
+ [{'$unspecified',VLvl}]
+ end, [], StartOpts),
+
%% config & userconfig
CfgFiles = ct_config:get_config_file_list(StartOpts),
@@ -763,13 +916,13 @@ run_test2(StartOpts) ->
fun(EBH) when EBH == true;
EBH == false ->
EBH
- end, true, StartOpts),
+ end, undefined, StartOpts),
%% silent connections
SilentConns = get_start_opt(silent_connections,
- fun(all) -> [];
+ fun(all) -> [all];
(Conns) -> Conns
- end, StartOpts),
+ end, [], StartOpts),
%% stylesheet
Stylesheet = get_start_opt(stylesheet,
fun(SS) -> ?abs(SS) end,
@@ -782,8 +935,11 @@ run_test2(StartOpts) ->
MultiplyTT = get_start_opt(multiply_timetraps, value, 1, StartOpts),
ScaleTT = get_start_opt(scale_timetraps, value, false, StartOpts),
+ %% create unique priv dir names
+ CreatePrivDir = get_start_opt(create_priv_dir, value, StartOpts),
+
%% auto compile & include files
- Include =
+ {AutoCompile,Include} =
case proplists:get_value(auto_compile, StartOpts) of
undefined ->
application:set_env(common_test, auto_compile, true),
@@ -799,16 +955,16 @@ run_test2(StartOpts) ->
case os:getenv("CT_INCLUDE_PATH") of
false ->
application:set_env(common_test, include, InclDirs),
- InclDirs;
+ {undefined,InclDirs};
CtInclPath ->
InclDirs1 = string:tokens(CtInclPath, [$:,$ ,$,]),
AllInclDirs = InclDirs1++InclDirs,
application:set_env(common_test, include, AllInclDirs),
- AllInclDirs
+ {undefined,AllInclDirs}
end;
ACBool ->
application:set_env(common_test, auto_compile, ACBool),
- []
+ {ACBool,[]}
end,
%% decrypt config file
@@ -822,11 +978,14 @@ run_test2(StartOpts) ->
end,
%% basic html - used by ct_logs
- case proplists:get_value(basic_html, StartOpts) of
- undefined ->
- application:set_env(common_test, basic_html, false);
- BasicHtmlBool ->
- application:set_env(common_test, basic_html, BasicHtmlBool)
+ BasicHtml =
+ case proplists:get_value(basic_html, StartOpts) of
+ undefined ->
+ application:set_env(common_test, basic_html, false),
+ undefined;
+ BasicHtmlBool ->
+ application:set_env(common_test, basic_html, BasicHtmlBool),
+ BasicHtmlBool
end,
%% stepped execution
@@ -834,15 +993,20 @@ run_test2(StartOpts) ->
Opts = #opts{label = Label, profile = Profile,
cover = Cover, step = Step, logdir = LogDir,
- logopts = LogOpts, config = CfgFiles,
+ logopts = LogOpts, basic_html = BasicHtml,
+ config = CfgFiles,
+ verbosity = Verbosity,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
enable_builtin_hooks = EnableBuiltinHooks,
+ auto_compile = AutoCompile,
include = Include,
silent_connections = SilentConns,
stylesheet = Stylesheet,
multiply_timetraps = MultiplyTT,
- scale_timetraps = ScaleTT},
+ scale_timetraps = ScaleTT,
+ create_priv_dir = CreatePrivDir,
+ starter = ct},
%% test specification
case proplists:get_value(spec, StartOpts) of
@@ -871,7 +1035,7 @@ run_spec_file(Relaxed,
log_ts_names(AbsSpecs),
case catch ct_testspec:collect_tests_from_file(AbsSpecs, Relaxed) of
{Error,CTReason} when Error == error ; Error == 'EXIT' ->
- exit(CTReason);
+ exit({error,CTReason});
TS ->
SpecOpts = get_data_for_node(TS, node()),
Label = choose_val(Opts#opts.label,
@@ -882,6 +1046,12 @@ run_spec_file(Relaxed,
SpecOpts#opts.logdir),
AllLogOpts = merge_vals([Opts#opts.logopts,
SpecOpts#opts.logopts]),
+ Stylesheet = choose_val(Opts#opts.stylesheet,
+ SpecOpts#opts.stylesheet),
+ AllVerbosity = merge_keyvals([Opts#opts.verbosity,
+ SpecOpts#opts.verbosity]),
+ AllSilentConns = merge_vals([Opts#opts.silent_connections,
+ SpecOpts#opts.silent_connections]),
AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]),
Cover = choose_val(Opts#opts.cover,
SpecOpts#opts.cover),
@@ -889,29 +1059,56 @@ run_spec_file(Relaxed,
SpecOpts#opts.multiply_timetraps),
ScaleTT = choose_val(Opts#opts.scale_timetraps,
SpecOpts#opts.scale_timetraps),
+ CreatePrivDir = choose_val(Opts#opts.create_priv_dir,
+ SpecOpts#opts.create_priv_dir),
AllEvHs = merge_vals([Opts#opts.event_handlers,
SpecOpts#opts.event_handlers]),
AllInclude = merge_vals([Opts#opts.include,
SpecOpts#opts.include]),
-
AllCTHooks = merge_vals([Opts#opts.ct_hooks,
- SpecOpts#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),
+ AutoCompile = case choose_val(Opts#opts.auto_compile,
+ SpecOpts#opts.auto_compile) of
+ undefined ->
+ true;
+ ACBool ->
+ application:set_env(common_test, auto_compile,
+ ACBool),
+ ACBool
+ end,
+
+ BasicHtml = case choose_val(Opts#opts.basic_html,
+ SpecOpts#opts.basic_html) of
+ undefined ->
+ false;
+ BHBool ->
+ application:set_env(common_test, basic_html,
+ BHBool),
+ BHBool
+ end,
+
Opts1 = Opts#opts{label = Label,
profile = Profile,
cover = Cover,
logdir = which(logdir, LogDir),
logopts = AllLogOpts,
+ stylesheet = Stylesheet,
+ basic_html = BasicHtml,
+ verbosity = AllVerbosity,
+ silent_connections = AllSilentConns,
config = AllConfig,
event_handlers = AllEvHs,
+ auto_compile = AutoCompile,
include = AllInclude,
testspecs = AbsSpecs,
multiply_timetraps = MultTT,
scale_timetraps = ScaleTT,
+ create_priv_dir = CreatePrivDir,
ct_hooks = AllCTHooks,
enable_builtin_hooks = EnableBuiltinHooks
},
@@ -922,20 +1119,20 @@ run_spec_file(Relaxed,
{Run,Skip} = ct_testspec:prepare_tests(TS, node()),
reformat_result(catch do_run(Run, Skip, Opts1, StartOpts));
{error,GCFReason} ->
- exit(GCFReason)
+ exit({error,GCFReason})
end
end.
run_prepared(Run, Skip, Opts = #opts{logdir = LogDir,
- config = CfgFiles },
+ config = CfgFiles},
StartOpts) ->
LogDir1 = which(logdir, LogDir),
case check_and_install_configfiles(CfgFiles, LogDir1, Opts) of
ok ->
reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1},
StartOpts));
- {error,Reason} ->
- exit(Reason)
+ {error,_Reason} = Error ->
+ exit(Error)
end.
check_config_file(Callback, File)->
@@ -943,7 +1140,7 @@ check_config_file(Callback, File)->
false ->
case code:load_file(Callback) of
{module,_} -> ok;
- {error,Why} -> exit({cant_load_callback_module,Why})
+ {error,Why} -> exit({error,{cant_load_callback_module,Why}})
end;
_ ->
ok
@@ -954,16 +1151,17 @@ check_config_file(Callback, File)->
{ok,{config,_}}->
File;
{error,{wrong_config,Message}}->
- exit({wrong_config,{Callback,Message}});
+ exit({error,{wrong_config,{Callback,Message}}});
{error,{nofile,File}}->
- exit({no_such_file,?abs(File)})
+ exit({error,{no_such_file,?abs(File)}})
end.
run_dir(Opts = #opts{logdir = LogDir,
config = CfgFiles,
event_handlers = EvHandlers,
ct_hooks = CTHook,
- enable_builtin_hooks = EnableBuiltinHooks }, StartOpts) ->
+ enable_builtin_hooks = EnableBuiltinHooks},
+ StartOpts) ->
LogDir1 = which(logdir, LogDir),
Opts1 = Opts#opts{logdir = LogDir1},
AbsCfgFiles =
@@ -976,7 +1174,8 @@ run_dir(Opts = #opts{logdir = LogDir,
{module,Callback}->
ok;
{error,_}->
- exit({no_such_module,Callback})
+ exit({error,{no_such_module,
+ Callback}})
end
end,
{Callback,
@@ -989,7 +1188,7 @@ run_dir(Opts = #opts{logdir = LogDir,
{ct_hooks, CTHook},
{enable_builtin_hooks,EnableBuiltinHooks}], LogDir1) of
ok -> ok;
- {error,IReason} -> exit(IReason)
+ {error,_IReason} = IError -> exit(IError)
end,
case {proplists:get_value(dir, StartOpts),
proplists:get_value(suite, StartOpts),
@@ -1031,7 +1230,7 @@ run_dir(Opts = #opts{logdir = LogDir,
[], Opts1, StartOpts));
{undefined,[Hd,_|_],_GsAndCs} when not is_integer(Hd) ->
- exit(multiple_suites_and_cases);
+ exit({error,multiple_suites_and_cases});
{undefined,Suite=[Hd|Tl],GsAndCs} when is_integer(Hd) ;
(is_list(Hd) and (Tl == [])) ;
@@ -1041,10 +1240,10 @@ run_dir(Opts = #opts{logdir = LogDir,
[], Opts1, StartOpts));
{[Hd,_|_],_Suites,[]} when is_list(Hd) ; not is_integer(Hd) ->
- exit(multiple_dirs_and_suites);
+ exit({error,multiple_dirs_and_suites});
{undefined,undefined,GsAndCs} when GsAndCs /= [] ->
- exit(incorrect_start_options);
+ exit({error,incorrect_start_options});
{Dir,Suite,GsAndCs} when is_integer(hd(Dir)) ;
(is_atom(Dir) and (Dir /= undefined)) ;
@@ -1053,7 +1252,7 @@ run_dir(Opts = #opts{logdir = LogDir,
Dir1 = if is_atom(Dir) -> atom_to_list(Dir);
true -> Dir end,
if Suite == undefined ->
- exit(incorrect_start_options);
+ exit({error,incorrect_start_options});
is_integer(hd(Suite)) ;
(is_atom(Suite) and (Suite /= undefined)) ;
@@ -1072,7 +1271,7 @@ run_dir(Opts = #opts{logdir = LogDir,
is_list(Suite) -> % multiple suites
case [suite_to_test(Dir1, S) || S <- Suite] of
[_,_|_] when GsAndCs /= [] ->
- exit(multiple_suites_and_cases);
+ exit({error,multiple_suites_and_cases});
[{Dir2,Mod}] when GsAndCs /= [] ->
reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts));
@@ -1083,10 +1282,10 @@ run_dir(Opts = #opts{logdir = LogDir,
end;
{undefined,undefined,[]} ->
- exit(no_test_specified);
+ exit({error,no_test_specified});
{Dir,Suite,GsAndCs} ->
- exit({incorrect_start_options,{Dir,Suite,GsAndCs}})
+ exit({error,{incorrect_start_options,{Dir,Suite,GsAndCs}}})
end.
%%%-----------------------------------------------------------------
@@ -1131,7 +1330,7 @@ run_testspec2(File) when is_list(File), is_integer(hd(File)) ->
run_testspec2(TestSpec) ->
case catch ct_testspec:collect_tests_from_list(TestSpec, false) of
{E,CTReason} when E == error ; E == 'EXIT' ->
- exit(CTReason);
+ exit({error,CTReason});
TS ->
Opts = get_data_for_node(TS, node()),
@@ -1153,8 +1352,8 @@ run_testspec2(TestSpec) ->
include = AllInclude},
{Run,Skip} = ct_testspec:prepare_tests(TS, node()),
reformat_result(catch do_run(Run, Skip, Opts1, []));
- {error,GCFReason} ->
- exit(GCFReason)
+ {error,_GCFReason} = GCFError ->
+ exit(GCFError)
end
end.
@@ -1162,15 +1361,21 @@ get_data_for_node(#testspec{label = Labels,
profile = Profiles,
logdir = LogDirs,
logopts = LogOptsList,
+ basic_html = BHs,
+ stylesheet = SSs,
+ verbosity = VLvls,
+ silent_connections = SilentConnsList,
cover = CoverFs,
config = Cfgs,
userconfig = UsrCfgs,
event_handler = EvHs,
ct_hooks = CTHooks,
enable_builtin_hooks = EnableBuiltinHooks,
+ auto_compile = ACs,
include = Incl,
multiply_timetraps = MTs,
- scale_timetraps = STs}, Node) ->
+ scale_timetraps = STs,
+ create_priv_dir = PDs}, Node) ->
Label = proplists:get_value(Node, Labels),
Profile = proplists:get_value(Node, Profiles),
LogDir = case proplists:get_value(Node, LogDirs) of
@@ -1181,26 +1386,44 @@ get_data_for_node(#testspec{label = Labels,
undefined -> [];
LOs -> LOs
end,
+ BasicHtml = proplists:get_value(Node, BHs),
+ Stylesheet = proplists:get_value(Node, SSs),
+ Verbosity = case proplists:get_value(Node, VLvls) of
+ undefined -> [];
+ Lvls -> Lvls
+ end,
+ SilentConns = case proplists:get_value(Node, SilentConnsList) of
+ undefined -> [];
+ SCs -> SCs
+ end,
Cover = proplists:get_value(Node, CoverFs),
MT = proplists:get_value(Node, MTs),
ST = proplists:get_value(Node, STs),
+ CreatePrivDir = proplists:get_value(Node, PDs),
ConfigFiles = [{?ct_config_txt,F} || {N,F} <- Cfgs, N==Node] ++
[CBF || {N,CBF} <- UsrCfgs, N==Node],
EvHandlers = [{H,A} || {N,H,A} <- EvHs, N==Node],
FiltCTHooks = [Hook || {N,Hook} <- CTHooks, N==Node],
+ AutoCompile = proplists:get_value(Node, ACs),
Include = [I || {N,I} <- Incl, N==Node],
#opts{label = Label,
profile = Profile,
logdir = LogDir,
logopts = LogOpts,
+ basic_html = BasicHtml,
+ stylesheet = Stylesheet,
+ verbosity = Verbosity,
+ silent_connections = SilentConns,
cover = Cover,
config = ConfigFiles,
event_handlers = EvHandlers,
ct_hooks = FiltCTHooks,
enable_builtin_hooks = EnableBuiltinHooks,
+ auto_compile = AutoCompile,
include = Include,
multiply_timetraps = MT,
- scale_timetraps = ST}.
+ scale_timetraps = ST,
+ create_priv_dir = CreatePrivDir}.
refresh_logs(LogDir) ->
{ok,Cwd} = file:get_cwd(),
@@ -1238,6 +1461,14 @@ choose_val(V0, _V1) ->
merge_vals(Vs) ->
lists:append(Vs).
+merge_keyvals(Vs) ->
+ make_unique(lists:append(Vs)).
+
+make_unique([Elem={Key,_} | Elems]) ->
+ [Elem | make_unique(proplists:delete(Key, Elems))];
+make_unique([]) ->
+ [].
+
listify([C|_]=Str) when is_integer(C) -> [Str];
listify(L) when is_list(L) -> L;
listify(E) -> [E].
@@ -1347,7 +1578,8 @@ do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc),
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,
+ #opts{label = Label, profile = Profile, cover = Cover,
+ verbosity = VLvls} = Opts,
%% label - used by ct_logs
TestLabel =
if Label == undefined -> undefined;
@@ -1368,7 +1600,7 @@ do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) ->
case code:which(test_server) of
non_existing ->
- exit({error,no_path_to_test_server});
+ {error,no_path_to_test_server};
_ ->
Opts1 = if Cover == undefined ->
Opts;
@@ -1384,81 +1616,136 @@ do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) ->
%% which framework it runs under.
case os:getenv("TEST_SERVER_FRAMEWORK") of
false ->
- os:putenv("TEST_SERVER_FRAMEWORK", "ct_framework");
+ os:putenv("TEST_SERVER_FRAMEWORK", "ct_framework"),
+ os:putenv("TEST_SERVER_FRAMEWORK_NAME", "common_test");
"ct_framework" ->
ok;
Other ->
- erlang:display(list_to_atom("Note: TEST_SERVER_FRAMEWORK = " ++ Other))
+ erlang:display(
+ list_to_atom(
+ "Note: TEST_SERVER_FRAMEWORK = " ++ Other))
end,
- case ct_util:start(Opts#opts.logdir) of
+ Verbosity = add_verbosity_defaults(VLvls),
+ case ct_util:start(Opts#opts.logdir, Verbosity) of
{error,interactive_mode} ->
io:format("CT is started in interactive mode. "
- "To exit this mode, run ct:stop_interactive().\n"
+ "To exit this mode, "
+ "run ct:stop_interactive().\n"
"To enter the interactive mode again, "
"run ct:start_interactive()\n\n",[]),
{error,interactive_mode};
_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
- [] ->
- Conns = ct_util:override_silence_all_connections(),
- ct_logs:log("Silent connections", "~p", [Conns]);
- Conns when is_list(Conns) ->
- ct_util:override_silence_connections(Conns),
- ct_logs:log("Silent connections", "~p", [Conns]);
- _ ->
- ok
- end,
- log_ts_names(Opts1#opts.testspecs),
- TestSuites = suite_tuples(Tests),
-
- {_TestSuites1,SuiteMakeErrors,AllMakeErrors} =
- case application:get_env(common_test, auto_compile) of
- {ok,false} ->
- {TestSuites1,SuitesNotFound} =
- verify_suites(TestSuites),
- {TestSuites1,SuitesNotFound,SuitesNotFound};
- _ ->
- {SuiteErrs,HelpErrs} = auto_compile(TestSuites),
- {TestSuites,SuiteErrs,SuiteErrs++HelpErrs}
- end,
+ ct_util:set_testdata({starter,Opts#opts.starter}),
+ compile_and_run(Tests, Skip,
+ Opts1#opts{verbosity=Verbosity}, Args)
+ end
+ end.
- case continue(AllMakeErrors) of
- true ->
- SavedErrors = save_make_errors(SuiteMakeErrors),
- ct_repeat:log_loop_info(Args),
+compile_and_run(Tests, Skip, Opts, Args) ->
+ %% 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
+ [] ->
+ ok;
+ Conns ->
+ case lists:member(all, Conns) of
+ true ->
+ Conns1 = ct_util:override_silence_all_connections(),
+ ct_logs:log("Silent connections", "~p", [Conns1]);
+ false ->
+ ct_util:override_silence_connections(Conns),
+ ct_logs:log("Silent connections", "~p", [Conns])
+ end
+ end,
+ log_ts_names(Opts#opts.testspecs),
+ TestSuites = suite_tuples(Tests),
+
+ {_TestSuites1,SuiteMakeErrors,AllMakeErrors} =
+ case application:get_env(common_test, auto_compile) of
+ {ok,false} ->
+ {TestSuites1,SuitesNotFound} =
+ verify_suites(TestSuites),
+ {TestSuites1,SuitesNotFound,SuitesNotFound};
+ _ ->
+ {SuiteErrs,HelpErrs} = auto_compile(TestSuites),
+ {TestSuites,SuiteErrs,SuiteErrs++HelpErrs}
+ end,
+
+ case continue(AllMakeErrors) of
+ true ->
+ SavedErrors = save_make_errors(SuiteMakeErrors),
+ ct_repeat:log_loop_info(Args),
+
+ {Tests1,Skip1} = final_tests(Tests,Skip,SavedErrors),
+
+ ReleaseSh = proplists:get_value(release_shell, Args),
+ ct_util:set_testdata({release_shell,ReleaseSh}),
+ possibly_spawn(ReleaseSh == true, Tests1, Skip1, Opts);
+ false ->
+ io:nl(),
+ ct_util:stop(clean),
+ BadMods =
+ lists:foldr(
+ fun({{_,_},Ms}, Acc) ->
+ Ms ++ lists:foldl(
+ fun(M, Acc1) ->
+ lists:delete(M, Acc1)
+ end, Acc, Ms)
+ end, [], AllMakeErrors),
+ {error,{make_failed,BadMods}}
+ end.
- {Tests1,Skip1} = final_tests(Tests,Skip,SavedErrors),
+%% keep the shell as the top controlling process
+possibly_spawn(false, Tests, Skip, Opts) ->
+ TestResult = (catch do_run_test(Tests, Skip, Opts)),
+ case TestResult of
+ {EType,_} = Error when EType == user_error;
+ EType == error ->
+ ct_util:stop(clean),
+ exit(Error);
+ _ ->
+ ct_util:stop(normal),
+ TestResult
+ end;
- R = (catch do_run_test(Tests1, Skip1, Opts1)),
- case R of
- {EType,_} = Error when EType == user_error ;
+%% we must return control to the shell now, so we spawn
+%% a test supervisor process to keep an eye on the test run
+possibly_spawn(true, Tests, Skip, Opts) ->
+ CTUtilSrv = whereis(ct_util_server),
+ Supervisor =
+ fun() ->
+ process_flag(trap_exit, true),
+ link(CTUtilSrv),
+ TestRun =
+ fun() ->
+ TestResult = (catch do_run_test(Tests, Skip, Opts)),
+ case TestResult of
+ {EType,_} = Error when EType == user_error;
EType == error ->
ct_util:stop(clean),
exit(Error);
_ ->
ct_util:stop(normal),
- R
- end;
- false ->
- io:nl(),
- ct_util:stop(clean),
- BadMods =
- lists:foldr(
- fun({{_,_},Ms}, Acc) ->
- Ms ++ lists:foldl(
- fun(M, Acc1) ->
- lists:delete(M, Acc1)
- end, Acc, Ms)
- end, [], AllMakeErrors),
- {error,{make_failed,BadMods}}
- end
- end
- end.
+ exit({ok,TestResult})
+ end
+ end,
+ TestRunPid = spawn_link(TestRun),
+ receive
+ {'EXIT',TestRunPid,{ok,TestResult}} ->
+ io:format(user, "~nCommon Test returned ~p~n~n",
+ [TestResult]);
+ {'EXIT',TestRunPid,Error} ->
+ exit(Error)
+ end
+ end,
+ unlink(CTUtilSrv),
+ SupPid = spawn(Supervisor),
+ io:format(user, "~nTest control handed over to process ~p~n~n",
+ [SupPid]),
+ SupPid.
%% attempt to compile the modules specified in TestSuites
auto_compile(TestSuites) ->
@@ -1474,11 +1761,13 @@ auto_compile(TestSuites) ->
end,
SuiteMakeErrors =
lists:flatmap(fun({TestDir,Suite} = TS) ->
- case run_make(suites, TestDir, Suite, UserInclude) of
+ case run_make(suites, TestDir,
+ Suite, UserInclude) of
{error,{make_failed,Bad}} ->
[{TS,Bad}];
{error,_} ->
- [{TS,[filename:join(TestDir,"*_SUITE")]}];
+ [{TS,[filename:join(TestDir,
+ "*_SUITE")]}];
_ ->
[]
end
@@ -1517,23 +1806,29 @@ verify_suites(TestSuites) ->
{[DS|Found],NotFound};
true ->
Beam = filename:join(TestDir,
- atom_to_list(Suite)++".beam"),
+ atom_to_list(Suite)++
+ ".beam"),
case filelib:is_regular(Beam) of
true ->
{[DS|Found],NotFound};
false ->
case code:is_loaded(Suite) of
{file,SuiteFile} ->
- %% test suite is already loaded and
- %% since auto_compile == false,
+ %% test suite is already
+ %% loaded and since
+ %% auto_compile == false,
%% let's assume the user has
- %% loaded the beam file explicitly
- ActualDir = filename:dirname(SuiteFile),
- {[{ActualDir,Suite}|Found],NotFound};
+ %% loaded the beam file
+ %% explicitly
+ ActualDir =
+ filename:dirname(SuiteFile),
+ {[{ActualDir,Suite}|Found],
+ NotFound};
false ->
Name =
filename:join(TestDir,
- atom_to_list(Suite)),
+ atom_to_list(
+ Suite)),
io:format(user,
"Suite ~w not found"
"in directory ~s~n",
@@ -1551,7 +1846,8 @@ verify_suites(TestSuites) ->
ActualDir = filename:dirname(SuiteFile),
{[{ActualDir,Suite}|Found],NotFound};
false ->
- io:format(user, "Directory ~s is invalid~n", [Dir]),
+ io:format(user, "Directory ~s is "
+ "invalid~n", [Dir]),
Name = filename:join(Dir, atom_to_list(Suite)),
{Found,[{DS,[Name]}|NotFound]}
end
@@ -1565,7 +1861,8 @@ save_make_errors([]) ->
save_make_errors(Errors) ->
Suites = get_bad_suites(Errors,[]),
ct_logs:log("MAKE RESULTS",
- "Error compiling or locating the following suites: ~n~p",[Suites]),
+ "Error compiling or locating the "
+ "following suites: ~n~p",[Suites]),
%% save the info for logger
file:write_file(?missing_suites_info,term_to_binary(Errors)),
Errors.
@@ -1586,8 +1883,9 @@ step(TestDir, Suite, Case) ->
%%%-----------------------------------------------------------------
%%% @hidden
%%% @equiv ct:step/4
-step(TestDir, Suite, Case, Opts) when is_list(TestDir), is_atom(Suite), is_atom(Case),
- Suite =/= all, Case =/= all ->
+step(TestDir, Suite, Case, Opts) when is_list(TestDir),
+ is_atom(Suite), is_atom(Case),
+ Suite =/= all, Case =/= all ->
do_run([{TestDir,Suite,Case}], [{step,Opts}]).
@@ -1660,6 +1958,14 @@ final_tests1([{TestDir,Suite,GrsOrCs}|Tests], Final, Skip, Bad) when
({skipped,Group,TCs}) ->
[ct_framework:make_conf(TestDir, Suite,
Group, [skipped], TCs)];
+ ({GrSpec = {Group,_},TCs}) ->
+ Props = [{override,GrSpec}],
+ [ct_framework:make_conf(TestDir, Suite,
+ Group, Props, TCs)];
+ ({GrSpec = {Group,_,_},TCs}) ->
+ Props = [{override,GrSpec}],
+ [ct_framework:make_conf(TestDir, Suite,
+ Group, Props, TCs)];
({Group,TCs}) ->
[ct_framework:make_conf(TestDir, Suite,
Group, [], TCs)];
@@ -1697,9 +2003,11 @@ continue(_MakeErrors) ->
case set_group_leader_same_as_shell() of
true ->
S = self(),
- io:format("Failed to compile or locate one or more test suites\n"
+ io:format("Failed to compile or locate one "
+ "or more test suites\n"
"Press \'c\' to continue or \'a\' to abort.\n"
- "Will continue in 15 seconds if no answer is given!\n"),
+ "Will continue in 15 seconds if no "
+ "answer is given!\n"),
Pid = spawn(fun() ->
case io:get_line('(c/a) ') of
"c\n" ->
@@ -1731,32 +2039,39 @@ set_group_leader_same_as_shell() ->
end
end,
case [P || P <- processes(), GS2or3(P),
- true == lists:keymember(shell,1,element(2,process_info(P,dictionary)))] of
+ true == lists:keymember(shell,1,
+ element(2,process_info(P,dictionary)))] of
[GL|_] ->
group_leader(GL, self());
[] ->
false
end.
-check_and_add([{TestDir0,M,_} | Tests], Added) ->
+check_and_add([{TestDir0,M,_} | Tests], Added, PA) ->
case locate_test_dir(TestDir0, M) of
{ok,TestDir} ->
case lists:member(TestDir, Added) of
true ->
- check_and_add(Tests, Added);
+ check_and_add(Tests, Added, PA);
false ->
- true = code:add_patha(TestDir),
- check_and_add(Tests, [TestDir|Added])
+ case lists:member(rm_trailing_slash(TestDir),
+ code:get_path()) of
+ false ->
+ true = code:add_patha(TestDir),
+ check_and_add(Tests, [TestDir|Added], [TestDir|PA]);
+ true ->
+ check_and_add(Tests, [TestDir|Added], PA)
+ end
end;
{error,_} ->
{error,{invalid_directory,TestDir0}}
end;
-check_and_add([], _) ->
- ok.
+check_and_add([], _, PA) ->
+ {ok,PA}.
do_run_test(Tests, Skip, Opts) ->
- case check_and_add(Tests, []) of
- ok ->
+ case check_and_add(Tests, [], []) of
+ {ok,AddedToPath} ->
ct_util:set_testdata({stats,{0,0,{0,0}}}),
ct_util:set_testdata({cover,undefined}),
test_server_ctrl:start_link(local),
@@ -1771,12 +2086,14 @@ do_run_test(Tests, Skip, Opts) ->
incl_mods = CovIncl,
cross = CovCross,
src = _CovSrc}} ->
- ct_logs:log("COVER INFO","Using cover specification file: ~s~n"
+ ct_logs:log("COVER INFO",
+ "Using cover specification file: ~s~n"
"App: ~w~n"
"Cross cover: ~w~n"
"Including ~w modules~n"
"Excluding ~w modules",
- [CovFile,CovApp,CovCross,length(CovIncl),length(CovExcl)]),
+ [CovFile,CovApp,CovCross,
+ length(CovIncl),length(CovExcl)]),
%% cover export file will be used for export and import
%% between tests so make sure it doesn't exist initially
@@ -1784,7 +2101,8 @@ do_run_test(Tests, Skip, Opts) ->
true ->
DelResult = file:delete(CovExport),
ct_logs:log("COVER INFO",
- "Warning! Export file ~s already exists. "
+ "Warning! "
+ "Export file ~s already exists. "
"Deleting with result: ~p",
[CovExport,DelResult]);
false ->
@@ -1800,7 +2118,8 @@ do_run_test(Tests, Skip, Opts) ->
%% start cover on specified nodes
if (CovNodes /= []) and (CovNodes /= undefined) ->
ct_logs:log("COVER INFO",
- "Nodes included in cover session: ~w",
+ "Nodes included in cover "
+ "session: ~w",
[CovNodes]),
cover:start(CovNodes);
true ->
@@ -1825,15 +2144,27 @@ do_run_test(Tests, Skip, Opts) ->
ct_logs:log("TEST INFO","~w test(s), ~w suite(s)",
[NoOfTests,NoOfSuites]);
true ->
- io:format("~nTEST INFO: ~w test(s), ~w case(s) in ~w suite(s)~n~n",
+ io:format("~nTEST INFO: ~w test(s), ~w case(s) "
+ "in ~w suite(s)~n~n",
[NoOfTests,NoOfCases,NoOfSuites]),
- ct_logs:log("TEST INFO","~w test(s), ~w case(s) in ~w suite(s)",
+ ct_logs:log("TEST INFO","~w test(s), ~w case(s) "
+ "in ~w suite(s)",
[NoOfTests,NoOfCases,NoOfSuites])
end,
-
+ %% if the verbosity level is set lower than ?STD_IMPORTANCE, tell
+ %% test_server to ignore stdout printouts to the test case log file
+ case proplists:get_value(default, Opts#opts.verbosity) of
+ VLvl when is_integer(VLvl), (?STD_IMPORTANCE < (100-VLvl)) ->
+ test_server_ctrl:reject_io_reqs(true);
+ _Lower ->
+ ok
+ end,
test_server_ctrl:multiply_timetraps(Opts#opts.multiply_timetraps),
test_server_ctrl:scale_timetraps(Opts#opts.scale_timetraps),
+ test_server_ctrl:create_priv_dir(choose_val(
+ Opts#opts.create_priv_dir,
+ auto_per_run)),
ct_event:notify(#event{name=start_info,
node=node(),
data={NoOfTests,NoOfSuites,NoOfCases}}),
@@ -1850,9 +2181,17 @@ do_run_test(Tests, Skip, Opts) ->
end,
lists:foreach(fun(Suite) ->
maybe_cleanup_interpret(Suite, Opts#opts.step)
- end, CleanUp);
+ end, CleanUp),
+ [code:del_path(Dir) || Dir <- AddedToPath],
+
+ case ct_util:get_testdata(stats) of
+ Stats = {_Ok,_Failed,{_UserSkipped,_AutoSkipped}} ->
+ Stats;
+ _ ->
+ {error,test_result_unknown}
+ end;
Error ->
- Error
+ exit(Error)
end.
delete_dups([S | Suites]) ->
@@ -2281,7 +2620,7 @@ ct_hooks_args2opts(Args) ->
Acc
end,[],Args).
-ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) ->
+ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) when Arg /= "and" ->
ct_hooks_args2opts(Rest,[{list_to_atom(CTH),
parse_cth_args(Arg),
parse_cth_args(Prio)}|Acc]);
@@ -2309,7 +2648,6 @@ parse_cth_args(String) ->
String
end.
-
event_handler_args2opts(Args) ->
case proplists:get_value(event_handler, Args) of
undefined ->
@@ -2332,6 +2670,42 @@ event_handler_init_args2opts([EH, Arg]) ->
event_handler_init_args2opts([]) ->
[].
+verbosity_args2opts(Args) ->
+ case proplists:get_value(verbosity, Args) of
+ undefined ->
+ [];
+ VArgs ->
+ GetVLvls =
+ fun("and", {new,SoFar}) when is_list(SoFar) ->
+ {new,SoFar};
+ ("and", {Lvl,SoFar}) when is_list(SoFar) ->
+ {new,[{'$unspecified',list_to_integer(Lvl)} | SoFar]};
+ (CatOrLvl, {new,SoFar}) when is_list(SoFar) ->
+ {CatOrLvl,SoFar};
+ (Lvl, {Cat,SoFar}) ->
+ {new,[{list_to_atom(Cat),list_to_integer(Lvl)} | SoFar]}
+ end,
+ case lists:foldl(GetVLvls, {new,[]}, VArgs) of
+ {new,Parsed} ->
+ Parsed;
+ {Lvl,Parsed} ->
+ [{'$unspecified',list_to_integer(Lvl)} | Parsed]
+ end
+ end.
+
+add_verbosity_defaults(VLvls) ->
+ case {proplists:get_value('$unspecified', VLvls),
+ proplists:get_value(default, VLvls)} of
+ {undefined,undefined} ->
+ ?default_verbosity ++ VLvls;
+ {Lvl,undefined} ->
+ [{default,Lvl} | VLvls];
+ {undefined,_Lvl} ->
+ [{'$unspecified',?MAX_VERBOSITY} | VLvls];
+ _ ->
+ VLvls
+ end.
+
%% This function reads pa and pz arguments, converts dirs from relative
%% to absolute, and re-inserts them in the code path. The order of the
%% dirs in the code path remain the same. Note however that since this
@@ -2339,31 +2713,38 @@ event_handler_init_args2opts([]) ->
%% relative dirs "post run_test erl_args" is not kept!
rel_to_abs(CtArgs) ->
{PA,PZ} = get_pa_pz(CtArgs, [], []),
- io:format(user, "~n", []),
[begin
- code:del_path(filename:basename(D)),
- Abs = filename:absname(D),
- code:add_pathz(Abs),
- if D /= Abs ->
+ Dir = rm_trailing_slash(D),
+ Abs = make_abs(Dir),
+ if Dir /= Abs ->
+ code:del_path(Dir),
+ code:del_path(Abs),
io:format(user, "Converting ~p to ~p and re-inserting "
"with add_pathz/1~n",
- [D, Abs]);
+ [Dir, Abs]);
true ->
- ok
- end
+ code:del_path(Dir)
+ end,
+ code:add_pathz(Abs)
end || D <- PZ],
[begin
- code:del_path(filename:basename(D)),
- Abs = filename:absname(D),
- code:add_patha(Abs),
- if D /= Abs ->
+ Dir = rm_trailing_slash(D),
+ Abs = make_abs(Dir),
+ if Dir /= Abs ->
+ code:del_path(Dir),
+ code:del_path(Abs),
io:format(user, "Converting ~p to ~p and re-inserting "
"with add_patha/1~n",
- [D, Abs]);
- true ->ok
- end
+ [Dir, Abs]);
+ true ->
+ code:del_path(Dir)
+ end,
+ code:add_patha(Abs)
end || D <- PA],
- io:format(user, "~n", []).
+ io:format(user, "~n", []).
+
+rm_trailing_slash(Dir) ->
+ filename:join(filename:split(Dir)).
get_pa_pz([{pa,Dirs} | Args], PA, PZ) ->
get_pa_pz(Args, PA ++ Dirs, PZ);
@@ -2374,11 +2755,28 @@ get_pa_pz([_ | Args], PA, PZ) ->
get_pa_pz([], PA, PZ) ->
{PA,PZ}.
+make_abs(RelDir) ->
+ Tokens = filename:split(filename:absname(RelDir)),
+ filename:join(lists:reverse(make_abs1(Tokens, []))).
+
+make_abs1([".."|Dirs], [_Dir|Path]) ->
+ make_abs1(Dirs, Path);
+make_abs1(["."|Dirs], Path) ->
+ make_abs1(Dirs, Path);
+make_abs1([Dir|Dirs], Path) ->
+ make_abs1(Dirs, [Dir|Path]);
+make_abs1([], Path) ->
+ Path.
+
%% This function translates ct:run_test/1 start options
%% to ct_run start arguments (on the init arguments format) -
%% this is useful mainly for testing the ct_run start functions.
opts2args(EnvStartOpts) ->
- lists:flatmap(fun({config,CfgFiles}) ->
+ lists:flatmap(fun({exit_status,ExitStatusOpt}) when is_atom(ExitStatusOpt) ->
+ [{exit_status,[atom_to_list(ExitStatusOpt)]}];
+ ({halt_with,{HaltM,HaltF}}) ->
+ [{halt_with,[atom_to_list(HaltM),atom_to_list(HaltF)]}];
+ ({config,CfgFiles}) ->
[{ct_config,[CfgFiles]}];
({userconfig,{CBM,CfgStr=[X|_]}}) when is_integer(X) ->
[{userconfig,[atom_to_list(CBM),CfgStr]}];
@@ -2386,10 +2784,14 @@ opts2args(EnvStartOpts) ->
[{userconfig,[atom_to_list(CBM) | CfgStrs]}];
({userconfig,UserCfg}) when is_list(UserCfg) ->
Strs =
- lists:map(fun({CBM,CfgStr=[X|_]}) when is_integer(X) ->
- [atom_to_list(CBM),CfgStr,"and"];
- ({CBM,CfgStrs}) when is_list(CfgStrs) ->
- [atom_to_list(CBM) | CfgStrs] ++ ["and"]
+ lists:map(fun({CBM,CfgStr=[X|_]})
+ when is_integer(X) ->
+ [atom_to_list(CBM),
+ CfgStr,"and"];
+ ({CBM,CfgStrs})
+ when is_list(CfgStrs) ->
+ [atom_to_list(CBM) | CfgStrs] ++
+ ["and"]
end, UserCfg),
[_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)),
[{userconfig,lists:reverse(StrsR)}];
@@ -2411,6 +2813,10 @@ opts2args(EnvStartOpts) ->
[{scale_timetraps,[]}];
({scale_timetraps,false}) ->
[];
+ ({create_priv_dir,auto_per_run}) ->
+ [];
+ ({create_priv_dir,PD}) when is_atom(PD) ->
+ [{create_priv_dir,[atom_to_list(PD)]}];
({force_stop,true}) ->
[{force_stop,[]}];
({force_stop,false}) ->
@@ -2420,7 +2826,7 @@ opts2args(EnvStartOpts) ->
({decrypt,{file,File}}) ->
[{ct_decrypt_file,[File]}];
({basic_html,true}) ->
- ({basic_html,[]});
+ [{basic_html,[]}];
({basic_html,false}) ->
[];
({event_handler,EH}) when is_atom(EH) ->
@@ -2433,12 +2839,32 @@ opts2args(EnvStartOpts) ->
({event_handler,{EHs,Arg}}) when is_list(EHs) ->
ArgStr = lists:flatten(io_lib:format("~p", [Arg])),
Strs = lists:map(fun(EH) ->
- [atom_to_list(EH),ArgStr,"and"]
+ [atom_to_list(EH),
+ ArgStr,"and"]
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]}];
+ ({verbosity,?default_verbosity}) ->
+ [];
+ ({verbosity,VLvl}) when is_integer(VLvl) ->
+ [{verbosity,[integer_to_list(VLvl)]}];
+ ({verbosity,VLvls}) when is_list(VLvls) ->
+ VLvlArgs =
+ lists:flatmap(fun({'$unspecified',Lvl}) ->
+ [integer_to_list(Lvl),
+ "and"];
+ ({Cat,Lvl}) ->
+ [atom_to_list(Cat),
+ integer_to_list(Lvl),
+ "and"];
+ (Lvl) ->
+ [integer_to_list(Lvl),
+ "and"]
+ end, VLvls),
+ [_LastAnd|VLvlArgsR] = lists:reverse(VLvlArgs),
+ [{verbosity,lists:reverse(VLvlArgsR)}];
({ct_hooks,[]}) ->
[];
({ct_hooks,CTHs}) when is_list(CTHs) ->
diff --git a/lib/common_test/src/ct_ssh.erl b/lib/common_test/src/ct_ssh.erl
index aebb28bc42..d0d94e1e6e 100644
--- a/lib/common_test/src/ct_ssh.erl
+++ b/lib/common_test/src/ct_ssh.erl
@@ -133,10 +133,11 @@ connect(KeyOrName, ExtraOpts) when is_list(ExtraOpts) ->
%%% is used to identify the connection, this name may
%%% be used as connection reference for subsequent calls.
%%% It's only possible to have one open connection at a time
-%%% associated with <code>Name</code>. If <code>Key</code> is
+%%% associated with <code>Name</code>. If <code>Key</code> is
%%% used, the returned handle must be used for subsequent calls
%%% (multiple connections may be opened using the config
-%%% data specified by <code>Key</code>).</p>
+%%% data specified by <code>Key</code>). See <c>ct:require/2</c>
+%%% for how to create a new <c>Name</c></p>
%%%
%%% <p><code>ConnType</code> will always override the type
%%% specified in the address tuple in the configuration data (and
@@ -152,6 +153,8 @@ connect(KeyOrName, ExtraOpts) when is_list(ExtraOpts) ->
%%% The extra options will override any existing options with the
%%% same key in the config data. For details on valid SSH
%%% options, see the documentation for the OTP ssh application.</p>
+%%%
+%%% @see ct:require/2
connect(KeyOrName, ConnType, ExtraOpts) ->
case ct:get_config(KeyOrName) of
undefined ->
@@ -182,19 +185,22 @@ connect(KeyOrName, ConnType, ExtraOpts) ->
undefined ->
{ssh,undefined,AllOpts};
SFTPAddr ->
- log(heading(connect,KeyOrName),
- "Note: Opening ssh connection to sftp host.\n",
+ try_log(heading(connect,KeyOrName),
+ "Note: Opening ssh connection "
+ "to sftp host.\n",
[]),
{ssh,SFTPAddr,
- [{ssh,SFTPAddr}|proplists:delete(sftp, AllOpts)]}
+ [{ssh,SFTPAddr} |
+ proplists:delete(sftp, AllOpts)]}
end;
undefined when ConnType == sftp ->
case proplists:get_value(ssh, AllOpts) of
undefined ->
{sftp,undefined,AllOpts};
SSHAddr ->
- log(heading(connect,KeyOrName),
- "Note: Opening sftp connection to ssh host.\n",
+ try_log(heading(connect,KeyOrName),
+ "Note: Opening sftp connection "
+ "to ssh host.\n",
[]),
{sftp,SSHAddr,
[{sftp,SSHAddr}|proplists:delete(ssh, AllOpts)]}
@@ -209,15 +215,15 @@ connect(KeyOrName, ConnType, ExtraOpts) ->
[{not_available,{KeyOrName,ConnType1}}]),
{error,{not_available,{KeyOrName,ConnType1}}};
{_,undefined} ->
- log(heading(connect,KeyOrName),
- "Opening ~w connection to ~p:22\n",
- [ConnType1,Addr]),
+ try_log(heading(connect,KeyOrName),
+ "Opening ~w connection to ~p:22\n",
+ [ConnType1,Addr]),
ct_gen_conn:start(KeyOrName, {ConnType1,Addr,22},
AllOpts1, ?MODULE);
{_,Port} ->
- log(heading(connect,KeyOrName),
- "Opening ~w connection to ~p:~w\n",
- [ConnType1,Addr,Port]),
+ try_log(heading(connect,KeyOrName),
+ "Opening ~w connection to ~p:~w\n",
+ [ConnType1,Addr,Port]),
ct_gen_conn:start(KeyOrName, {ConnType1,Addr,Port},
AllOpts1, ?MODULE)
end
@@ -232,7 +238,7 @@ connect(KeyOrName, ConnType, ExtraOpts) ->
disconnect(SSH) ->
case get_handle(SSH) of
{ok,Pid} ->
- log(heading(disconnect,SSH), "Handle: ~p", [Pid]),
+ try_log(heading(disconnect,SSH), "Handle: ~p", [Pid], 5000),
case ct_gen_conn:stop(Pid) of
{error,{process_down,Pid,noproc}} ->
{error,already_closed};
@@ -968,8 +974,9 @@ init(KeyOrName, {ConnType,Addr,Port}, AllOpts) ->
Error;
Ok ->
SSHRef = element(2, Ok),
- log(heading(init,KeyOrName),
- "Opened ~w connection:\nHost: ~p (~p)\nUser: ~p\nPassword: ~p\n",
+ try_log(heading(init,KeyOrName),
+ "Opened ~w connection:\n"
+ "Host: ~p (~p)\nUser: ~p\nPassword: ~p\n",
[ConnType,Addr,Port,User,lists:duplicate(length(Password),$*)]),
{ok,SSHRef,#state{ssh_ref=SSHRef, conn_type=ConnType,
target=KeyOrName}}
@@ -978,25 +985,26 @@ init(KeyOrName, {ConnType,Addr,Port}, AllOpts) ->
%% @hidden
handle_msg(sftp_connect, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(sftp_connect,Target), "SSH Ref: ~p", [SSHRef]),
+ try_log(heading(sftp_connect,Target), "SSH Ref: ~p", [SSHRef]),
{ssh_sftp:start_channel(SSHRef),State};
handle_msg({session_open,TO}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(session_open,Target), "SSH Ref: ~p, Timeout: ~p", [SSHRef,TO]),
+ try_log(heading(session_open,Target), "SSH Ref: ~p, Timeout: ~p",
+ [SSHRef,TO]),
{ssh_connection:session_channel(SSHRef, TO),State};
handle_msg({session_close,Chn}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(session_close,Target), "SSH Ref: ~p, Chn: ~p", [SSHRef,Chn]),
+ try_log(heading(session_close,Target), "SSH Ref: ~p, Chn: ~p", [SSHRef,Chn]),
{ssh_connection:close(SSHRef, Chn),State};
handle_msg({exec,Chn,Command,TO}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
Chn1 =
if Chn == undefined ->
- log(heading(exec,Target),
- "Opening channel for exec, SSH Ref: ~p", [SSHRef]),
+ try_log(heading(exec,Target),
+ "Opening channel for exec, SSH Ref: ~p", [SSHRef]),
case ssh_connection:session_channel(SSHRef, TO) of
{ok,C} -> C;
CErr -> CErr
@@ -1009,9 +1017,9 @@ handle_msg({exec,Chn,Command,TO}, State) ->
log(heading(exec,Target), "Opening channel failed: ~p", [ChnError]),
{ChnError,State};
_ ->
- log(heading(exec,Target),
- "SSH Ref: ~p, Chn: ~p, Command: ~p, Timeout: ~p",
- [SSHRef,Chn1,Command,TO]),
+ try_log(heading(exec,Target),
+ "SSH Ref: ~p, Chn: ~p, Command: ~p, Timeout: ~p",
+ [SSHRef,Chn1,Command,TO]),
case ssh_connection:exec(SSHRef, Chn1, Command, TO) of
success ->
Result = do_recv_response(SSHRef, Chn1, [], close, TO),
@@ -1024,24 +1032,24 @@ handle_msg({exec,Chn,Command,TO}, State) ->
handle_msg({receive_response,Chn,End,TO}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(receive_response,Target),
- "SSH Ref: ~p, Chn: ~p, Timeout: ~p", [SSHRef,Chn,TO]),
+ try_log(heading(receive_response,Target),
+ "SSH Ref: ~p, Chn: ~p, Timeout: ~p", [SSHRef,Chn,TO]),
Result = do_recv_response(SSHRef, Chn, [], End, TO),
{Result,State};
handle_msg({send,Chn,Type,Data,TO}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(send,Target),
- "SSH Ref: ~p, Chn: ~p, Type: ~p, Timeout: ~p~n"
- "Data: ~p", [SSHRef,Chn,Type,TO,Data]),
+ try_log(heading(send,Target),
+ "SSH Ref: ~p, Chn: ~p, Type: ~p, Timeout: ~p~n"
+ "Data: ~p", [SSHRef,Chn,Type,TO,Data]),
Result = ssh_connection:send(SSHRef, Chn, Type, Data, TO),
{Result,State};
handle_msg({send_and_receive,Chn,Type,Data,End,TO}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(send_and_receive,Target),
- "SSH Ref: ~p, Chn: ~p, Type: ~p, Timeout: ~p~n"
- "Data: ~p", [SSHRef,Chn,Type,TO,Data]),
+ try_log(heading(send_and_receive,Target),
+ "SSH Ref: ~p, Chn: ~p, Type: ~p, Timeout: ~p~n"
+ "Data: ~p", [SSHRef,Chn,Type,TO,Data]),
case ssh_connection:send(SSHRef, Chn, Type, Data, TO) of
ok ->
Result = do_recv_response(SSHRef, Chn, [], End, TO),
@@ -1052,137 +1060,162 @@ handle_msg({send_and_receive,Chn,Type,Data,End,TO}, State) ->
handle_msg({subsystem,Chn,Subsystem,TO}, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
- log(heading(subsystem,Target),
- "SSH Ref: ~p, Chn: ~p, Subsys: ~p, Timeout: ~p",
- [SSHRef,Chn,Subsystem,TO]),
+ try_log(heading(subsystem,Target),
+ "SSH Ref: ~p, Chn: ~p, Subsys: ~p, Timeout: ~p",
+ [SSHRef,Chn,Subsystem,TO]),
Result = ssh_connection:subsystem(SSHRef, Chn, Subsystem, TO),
{Result,State};
%% --- SFTP Commands ---
handle_msg({read_file,Srv,File}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:read_file(ref(Srv,SSHRef), File),S};
handle_msg({write_file,Srv,File,Iolist}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:write_file(ref(Srv,SSHRef), File, Iolist),S};
handle_msg({list_dir,Srv,Path}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:list_dir(ref(Srv,SSHRef), Path),S};
handle_msg({open,Srv,File,Mode}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:open(ref(Srv,SSHRef), File, Mode),S};
handle_msg({opendir,Srv,Path}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:opendir(ref(Srv,SSHRef), Path),S};
handle_msg({close,Srv,Handle}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:close(ref(Srv,SSHRef), Handle),S};
handle_msg({read,Srv,Handle,Len}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:read(ref(Srv,SSHRef), Handle, Len),S};
handle_msg({pread,Srv,Handle,Position,Length}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:pread(ref(Srv,SSHRef),Handle,Position,Length),S};
handle_msg({aread,Srv,Handle,Len}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:aread(ref(Srv,SSHRef), Handle, Len),S};
handle_msg({apread,Srv,Handle,Position,Length}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:apread(ref(Srv,SSHRef), Handle, Position, Length),S};
handle_msg({write,Srv,Handle,Data}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:write(ref(Srv,SSHRef), Handle, Data),S};
handle_msg({pwrite,Srv,Handle,Position,Data}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:pwrite(ref(Srv,SSHRef), Handle, Position, Data),S};
handle_msg({awrite,Srv,Handle,Data}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:awrite(ref(Srv,SSHRef), Handle, Data),S};
handle_msg({apwrite,Srv,Handle,Position,Data}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:apwrite(ref(Srv,SSHRef), Handle, Position, Data),S};
handle_msg({position,Srv,Handle,Location}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:position(ref(Srv,SSHRef), Handle, Location),S};
handle_msg({read_file_info,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:read_file_info(ref(Srv,SSHRef), Name),S};
handle_msg({get_file_info,Srv,Handle}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:get_file_info(ref(Srv,SSHRef), Handle),S};
handle_msg({read_link_info,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:read_link_info(ref(Srv,SSHRef), Name),S};
handle_msg({write_file_info,Srv,Name,Info}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:write_file_info(ref(Srv,SSHRef), Name, Info),S};
handle_msg({read_link,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:read_link(ref(Srv,SSHRef), Name),S};
handle_msg({make_symlink,Srv,Name,Target}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:make_symlink(ref(Srv,SSHRef), Name, Target),S};
handle_msg({rename,Srv,OldName,NewName}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:rename(ref(Srv,SSHRef), OldName, NewName),S};
handle_msg({delete,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:delete(ref(Srv,SSHRef), Name),S};
handle_msg({make_dir,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:make_dir(ref(Srv,SSHRef), Name),S};
handle_msg({del_dir,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
- log(heading(sftp,S#state.target),
- "SSH Ref: ~p, Server: ~p~nCmd: ~p", [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
+ try_log(heading(sftp,S#state.target),
+ "SSH Ref: ~p, Server: ~p~nCmd: ~p",
+ [SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:del_dir(ref(Srv,SSHRef), Name),S}.
%% @hidden
@@ -1197,12 +1230,12 @@ close(SSHRef) ->
terminate(SSHRef, State) ->
case State#state.conn_type of
ssh ->
- log(heading(disconnect_ssh,State#state.target),
- "SSH Ref: ~p",[SSHRef]),
+ try_log(heading(disconnect_ssh,State#state.target),
+ "SSH Ref: ~p",[SSHRef], 5000),
ssh:close(SSHRef);
sftp ->
- log(heading(disconnect_sftp,State#state.target),
- "SFTP Ref: ~p",[SSHRef]),
+ try_log(heading(disconnect_sftp,State#state.target),
+ "SFTP Ref: ~p",[SSHRef], 5000),
ssh_sftp:stop_channel(SSHRef)
end.
@@ -1217,7 +1250,7 @@ do_recv_response(SSH, Chn, Data, End, Timeout) ->
{ssh_cm, SSH, {open,Chn,RemoteChn,{session}}} ->
debug("RECVD open"),
{ok,{open,Chn,RemoteChn,{session}}};
-
+
{ssh_cm, SSH, {closed,Chn}} ->
ssh_connection:close(SSH, Chn),
debug("CLSD~n~p ~p", [SSH,Chn]),
@@ -1245,38 +1278,38 @@ do_recv_response(SSH, Chn, Data, End, Timeout) ->
{ssh_cm, SSH, {exit_signal,Chn,Signal,Err,_Lang}} ->
debug("RECVD exit_signal~n~p ~p~n~p ~p", [SSH,Chn,Signal,Err]),
do_recv_response(SSH, Chn, Data, End, Timeout);
-%% {ok,{exit_signal,Chn,Signal,Err,_Lang}};
+ %% {ok,{exit_signal,Chn,Signal,Err,_Lang}};
{ssh_cm, SSH, {exit_status,Chn,Status}} ->
debug("RECVD exit_status~n~p ~p~n~p", [SSH,Chn,Status]),
do_recv_response(SSH, Chn, Data, End, Timeout);
-%% {ok,{exit_status,Chn,_Status}};
+ %% {ok,{exit_status,Chn,_Status}};
-%% --- INTERACTIVE MESSAGES - NOT HANDLED ---
-%%
-%% {ssh_cm, SSH, {subsystem,Chn,WantReply,Name}} ->
-%% debug("RECVD SUBS WNTRPLY~n~p ~p~n~p~n~p",
-%% [SSH,Chn,WantReply]),
-%% ssh_connection:reply_request(SSH, WantReply, success, Chn),
-%% do_recv_response(SSH, Chn, Data, End, Timeout);
-
-%% {ssh_cm, SSH, {shell,WantReply}} ->
-%% debug("RECVD SHELL WNTRPLY~n~p ~p~n~p~n~p",
-%% [SSH,Chn,WantReply]),
-%% ssh_connection:reply_request(SSH, WantReply, success, Chn),
-%% do_recv_response(SSH,Chn,Data,End,Timeout);
-
-%% {ssh_cm, SSH, {pty,Chn,WantReply,Pty}} ->
-%% debug("RECVD PTY WNTRPLY~n~p ~p~n~p~n~p",
-%% [SSH,Chn,WantReply,Pty]),
-%% ssh_connection:reply_request(SSH, WantReply, success, Chn),
-%% do_recv_response(SSH, Chn, Data, End, Timeout);
-
-%% {ssh_cm, SSH, WCh={window_change,_Chn,_Width,_Height,_PixWidth,_PixHeight}} ->
-%% debug("RECVD WINCH"),
-%% {ok,WCh};
-
+ %% --- INTERACTIVE MESSAGES - NOT HANDLED ---
+ %%
+ %% {ssh_cm, SSH, {subsystem,Chn,WantReply,Name}} ->
+ %% debug("RECVD SUBS WNTRPLY~n~p ~p~n~p~n~p",
+ %% [SSH,Chn,WantReply]),
+ %% ssh_connection:reply_request(SSH, WantReply, success, Chn),
+ %% do_recv_response(SSH, Chn, Data, End, Timeout);
+
+ %% {ssh_cm, SSH, {shell,WantReply}} ->
+ %% debug("RECVD SHELL WNTRPLY~n~p ~p~n~p~n~p",
+ %% [SSH,Chn,WantReply]),
+ %% ssh_connection:reply_request(SSH, WantReply, success, Chn),
+ %% do_recv_response(SSH,Chn,Data,End,Timeout);
+
+ %% {ssh_cm, SSH, {pty,Chn,WantReply,Pty}} ->
+ %% debug("RECVD PTY WNTRPLY~n~p ~p~n~p~n~p",
+ %% [SSH,Chn,WantReply,Pty]),
+ %% ssh_connection:reply_request(SSH, WantReply, success, Chn),
+ %% do_recv_response(SSH, Chn, Data, End, Timeout);
+
+ %% {ssh_cm, SSH, WCh={window_change,_Chn,_Width,_Height,_PixWidth,_PixHeight}} ->
+ %% debug("RECVD WINCH"),
+ %% {ok,WCh};
+
Other ->
debug("UNEXPECTED MESSAGE~n~p ~p~n~p", [SSH,Chn,Other]),
do_recv_response(SSH, Chn, Data, End, Timeout)
@@ -1307,9 +1340,12 @@ get_handle(SSH) ->
%%%-----------------------------------------------------------------
%%%
call(SSH, Msg) ->
+ call(SSH, Msg, infinity).
+
+call(SSH, Msg, Timeout) ->
case get_handle(SSH) of
{ok,Pid} ->
- ct_gen_conn:call(Pid, Msg);
+ ct_gen_conn:call(Pid, Msg, Timeout);
Error ->
Error
end.
@@ -1318,13 +1354,13 @@ call(SSH, Msg) ->
%%%
ref(sftp, SSHRef) -> SSHRef;
ref(Server, _) -> Server.
-
+
%%%-----------------------------------------------------------------
%%%
mod(Cmd) ->
[Op,_Server|Args] = tuple_to_list(Cmd),
list_to_tuple([Op|Args]).
-
+
%%%-----------------------------------------------------------------
%%%
heading(Function, Ref) ->
@@ -1335,6 +1371,20 @@ heading(Function, Ref) ->
log(Heading, Str, Args) ->
ct_gen_conn:log(Heading, Str, Args).
+%%%-----------------------------------------------------------------
+%%%
+try_log(Heading, Str, Args) ->
+ try_log(Heading, Str, Args, infinity).
+
+try_log(Heading, Str, Args, Timeout) ->
+ case ct_util:is_silenced(ssh, Timeout) of
+ true ->
+ ok;
+ false ->
+ ct_gen_conn:log(Heading, Str, Args);
+ _Error ->
+ ok
+ end.
%%%-----------------------------------------------------------------
%%%
@@ -1342,5 +1392,5 @@ debug(Str) ->
debug(Str, []).
debug(_Str, _Args) ->
-%% io:format("~n--- ct_ssh debug ---~n" ++ _Str ++ "~n", _Args),
+ %% io:format("~n--- ct_ssh debug ---~n" ++ _Str ++ "~n", _Args),
ok.
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index 71a784870c..e37a657617 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.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
@@ -155,6 +155,8 @@ open(KeyOrName,ConnType,TargetMod) ->
%%% <p><code>TargetMod</code> is a module which exports the functions
%%% <code>connect(Ip,Port,KeepAlive,Extra)</code> and <code>get_prompt_regexp()</code>
%%% for the given <code>TargetType</code> (e.g. <code>unix_telnet</code>).</p>
+%%%
+%%% @see ct:require/2
open(KeyOrName,ConnType,TargetMod,Extra) ->
case ct:get_config({KeyOrName,ConnType}) of
undefined ->
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index 317910d5c8..a8b67d0329 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,8 @@
-include("ct_util.hrl").
+-define(testspec_fields, record_info(fields, testspec)).
+
%%%------------------------------------------------------------------
%%% NOTE:
%%% Multiple testspecs may be used as input with the result that
@@ -46,7 +48,8 @@
%%% Version 1 - extract and return all tests and skips for Node
%%% (incl all_nodes)
%%%-------------------------------------------------------------------
-prepare_tests(TestSpec,Node) when is_record(TestSpec,testspec), is_atom(Node) ->
+prepare_tests(TestSpec,Node) when is_record(TestSpec,testspec),
+ is_atom(Node) ->
case lists:keysearch(Node,1,prepare_tests(TestSpec)) of
{value,{Node,Run,Skip}} ->
{Run,Skip};
@@ -249,22 +252,23 @@ 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},
- Relaxed),
- collect_tests_from_file1(Specs,TestSpec1,Relaxed);
+ case collect_tests(Terms,
+ TestSpec#testspec{spec_dir=SpecDir},
+ Relaxed) of
+ TS = #testspec{tests=Tests, logdir=LogDirs} when Specs == [] ->
+ LogDirs1 = lists:delete(".",LogDirs) ++ ["."],
+ TS#testspec{tests=lists:flatten(Tests), logdir=LogDirs1};
+ TS = #testspec{alias = As, nodes = Ns} ->
+ TS1 = TS#testspec{alias = lists:reverse(As),
+ nodes = lists:reverse(Ns)},
+ collect_tests_from_file1(Specs,TS1,Relaxed)
+ end;
{error,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},_) ->
- TS#testspec{config=lists:reverse(Cfgs),
- event_handler=lists:reverse(EvHs),
- include=lists:reverse(Incl),
- tests=lists:flatten(Tests)}.
+ end.
collect_tests_from_list(Terms,Relaxed) ->
collect_tests_from_list(Terms,[node()],Relaxed).
@@ -278,30 +282,163 @@ collect_tests_from_list(Terms,Nodes,Relaxed) when is_list(Nodes) ->
E = {error,_} ->
E;
TS ->
- #testspec{config=Cfgs,event_handler=EvHs,include=Incl,tests=Tests} = TS,
- TS#testspec{config=lists:reverse(Cfgs),
- event_handler=lists:reverse(EvHs),
- include=lists:reverse(Incl),
- tests=lists:flatten(Tests)}
+ #testspec{tests=Tests, logdir=LogDirs} = TS,
+ LogDirs1 = lists:delete(".",LogDirs) ++ ["."],
+ TS#testspec{tests=lists:flatten(Tests), logdir=LogDirs1}
end.
collect_tests(Terms,TestSpec,Relaxed) ->
put(relaxed,Relaxed),
- TestSpec1 = get_global(Terms,TestSpec),
- TestSpec2 = get_all_nodes(Terms,TestSpec1),
- {Terms2, TestSpec3} = filter_init_terms(Terms, [], TestSpec2),
+ Terms1 = replace_names(Terms),
+ TestSpec1 = get_global(Terms1,TestSpec),
+ TestSpec2 = get_all_nodes(Terms1,TestSpec1),
+ {Terms2, TestSpec3} = filter_init_terms(Terms1, [], TestSpec2),
add_tests(Terms2,TestSpec3).
-get_global([{merge_tests, Bool} | Ts], Spec) ->
- get_global(Ts,Spec#testspec{ merge_tests = Bool });
+%% replace names (atoms) in the testspec matching those in 'define' terms by
+%% searching recursively through tuples and lists
+replace_names(Terms) ->
+ Defs =
+ lists:flatmap(fun(Def={define,Name,_Replacement}) ->
+ %% check that name follows convention
+ if not is_atom(Name) ->
+ throw({illegal_name_in_testspec,Name});
+ true ->
+ [First|_] = atom_to_list(Name),
+ if ((First == $?) or (First == $$)
+ or (First == $_)
+ or ((First >= $A)
+ and (First =< $Z))) ->
+ [Def];
+ true ->
+ throw({illegal_name_in_testspec,
+ Name})
+ end
+ end;
+ (_) -> []
+ end, Terms),
+ DefProps = replace_names_in_defs(Defs,[]),
+ replace_names(Terms,[],DefProps).
+
+replace_names_in_defs([Def|Left],ModDefs) ->
+ [{define,Name,Replacement}] = replace_names([Def],[],ModDefs),
+ replace_names_in_defs(Left,[{Name,Replacement}|ModDefs]);
+replace_names_in_defs([],ModDefs) ->
+ ModDefs.
+
+replace_names([Term|Ts],Modified,Defs) when is_tuple(Term) ->
+ [TypeTag|Data] = tuple_to_list(Term),
+ Term1 = list_to_tuple([TypeTag|replace_names_in_elems(Data,[],Defs)]),
+ replace_names(Ts,[Term1|Modified],Defs);
+replace_names([Term|Ts],Modified,Defs) when is_atom(Term) ->
+ case proplists:get_value(Term,Defs) of
+ undefined ->
+ replace_names(Ts,[Term|Modified],Defs);
+ Replacement ->
+ replace_names(Ts,[Replacement|Modified],Defs)
+ end;
+replace_names([Term=[Ch|_]|Ts],Modified,Defs) when is_integer(Ch) ->
+ %% Term *could* be a string, attempt to search through it
+ Term1 = replace_names_in_string(Term,Defs),
+ replace_names(Ts,[Term1|Modified],Defs);
+replace_names([Term|Ts],Modified,Defs) ->
+ replace_names(Ts,[Term|Modified],Defs);
+replace_names([],Modified,_Defs) ->
+ lists:reverse(Modified).
+
+replace_names_in_elems([Elem|Es],Modified,Defs) when is_tuple(Elem) ->
+ Elem1 = list_to_tuple(replace_names_in_elems(tuple_to_list(Elem),[],Defs)),
+ replace_names_in_elems(Es,[Elem1|Modified],Defs);
+replace_names_in_elems([Elem|Es],Modified,Defs) when is_atom(Elem) ->
+ case proplists:get_value(Elem,Defs) of
+ undefined ->
+ %% if Term is a node name, check it for replacements as well
+ Elem1 = replace_names_in_node(Elem,Defs),
+ replace_names_in_elems(Es,[Elem1|Modified],Defs);
+ Replacement ->
+ replace_names_in_elems(Es,[Replacement|Modified],Defs)
+ end;
+replace_names_in_elems([Elem=[Ch|_]|Es],Modified,Defs) when is_integer(Ch) ->
+ %% Term *could* be a string, attempt to search through it
+ case replace_names_in_string(Elem,Defs) of
+ Elem ->
+ List = replace_names_in_elems(Elem,[],Defs),
+ replace_names_in_elems(Es,[List|Modified],Defs);
+ Elem1 ->
+ replace_names_in_elems(Es,[Elem1|Modified],Defs)
+ end;
+replace_names_in_elems([Elem|Es],Modified,Defs) when is_list(Elem) ->
+ List = replace_names_in_elems(Elem,[],Defs),
+ replace_names_in_elems(Es,[List|Modified],Defs);
+replace_names_in_elems([Elem|Es],Modified,Defs) ->
+ replace_names_in_elems(Es,[Elem|Modified],Defs);
+replace_names_in_elems([],Modified,_Defs) ->
+ lists:reverse(Modified).
+
+replace_names_in_string(Term,Defs=[{Name,Replacement=[Ch|_]}|Ds])
+ when is_integer(Ch) ->
+ try re:replace(Term,[$'|atom_to_list(Name)]++"'",
+ Replacement,[{return,list}]) of
+ Term -> % no match, proceed
+ replace_names_in_string(Term,Ds);
+ Term1 ->
+ replace_names_in_string(Term1,Defs)
+ catch
+ _:_ -> Term % Term is not a string
+ end;
+replace_names_in_string(Term,[_|Ds]) ->
+ replace_names_in_string(Term,Ds);
+replace_names_in_string(Term,[]) ->
+ Term.
+
+replace_names_in_node(Node,Defs) ->
+ String = atom_to_list(Node),
+ case lists:member($@,String) of
+ true ->
+ list_to_atom(replace_names_in_node1(String,Defs));
+ false ->
+ Node
+ end.
+
+replace_names_in_node1(NodeStr,Defs=[{Name,Replacement}|Ds]) ->
+ ReplStr = case Replacement of
+ [Ch|_] when is_integer(Ch) -> Replacement;
+ _ when is_atom(Replacement) -> atom_to_list(Replacement);
+ _ -> false
+ end,
+ if ReplStr == false ->
+ replace_names_in_node1(NodeStr,Ds);
+ true ->
+ case re:replace(NodeStr,atom_to_list(Name),
+ ReplStr,[{return,list}]) of
+ NodeStr -> % no match, proceed
+ replace_names_in_node1(NodeStr,Ds);
+ NodeStr1 ->
+ replace_names_in_node1(NodeStr1,Defs)
+ end
+ end;
+replace_names_in_node1(NodeStr,[]) ->
+ NodeStr.
+
+
+%% global terms that will be used for analysing all other terms in the spec
+get_global([{merge_tests,Bool} | Ts], Spec) ->
+ get_global(Ts,Spec#testspec{merge_tests=Bool});
+
+%% the 'define' term replaces the 'alias' and 'node' terms, but we need to keep
+%% the latter two for backwards compatibility...
get_global([{alias,Ref,Dir}|Ts],Spec=#testspec{alias=Refs}) ->
get_global(Ts,Spec#testspec{alias=[{Ref,get_absdir(Dir,Spec)}|Refs]});
get_global([{node,Ref,Node}|Ts],Spec=#testspec{nodes=Refs}) ->
- get_global(Ts,Spec#testspec{nodes=[{Ref,Node}|lists:keydelete(Node,2,Refs)]});
-get_global([_|Ts],Spec) -> get_global(Ts,Spec);
-get_global([],Spec) -> Spec.
+ get_global(Ts,Spec#testspec{nodes=[{Ref,Node} |
+ lists:keydelete(Node,2,Refs)]});
-get_absfile(Callback, FullName,#testspec{spec_dir=SpecDir}) ->
+get_global([_|Ts],Spec) ->
+ get_global(Ts,Spec);
+get_global([],Spec=#testspec{nodes=Ns, alias=As}) ->
+ Spec#testspec{nodes=lists:reverse(Ns), alias=lists:reverse(As)}.
+
+get_absfile(Callback,FullName,#testspec{spec_dir=SpecDir}) ->
% we need to temporary switch to new cwd here, because
% otherwise config files cannot be found
{ok, OldWd} = file:get_cwd(),
@@ -329,29 +466,45 @@ get_absfile(FullName,#testspec{spec_dir=SpecDir}) ->
get_absdir(Dir,#testspec{spec_dir=SpecDir}) ->
get_absname(Dir,SpecDir).
-get_absname(TestDir,SpecDir) ->
- AbsName = filename:absname(TestDir,SpecDir),
- TestDirName = filename:basename(AbsName),
- Path = filename:dirname(AbsName),
- TopDir = filename:basename(Path),
- Path1 =
- case TopDir of
- "." ->
- [_|Rev] = lists:reverse(filename:split(Path)),
- filename:join(lists:reverse(Rev));
- ".." ->
- [_,_|Rev] = lists:reverse(filename:split(Path)),
- filename:join(lists:reverse(Rev));
- _ ->
- Path
- end,
- filename:join(Path1,TestDirName).
+get_absname(Dir,SpecDir) ->
+ AbsName = filename:absname(Dir,SpecDir),
+ shorten_path(AbsName,SpecDir).
+
+shorten_path(Path,SpecDir) ->
+ case shorten_split_path(filename:split(Path),[]) of
+ [] ->
+ [Root|_] = filename:split(SpecDir),
+ Root;
+ Short ->
+ filename:join(Short)
+ end.
+
+shorten_split_path([".."|Path],SoFar) ->
+ shorten_split_path(Path,tl(SoFar));
+shorten_split_path(["."|Path],SoFar) ->
+ shorten_split_path(Path,SoFar);
+shorten_split_path([Dir|Path],SoFar) ->
+ shorten_split_path(Path,[Dir|SoFar]);
+shorten_split_path([],SoFar) ->
+ lists:reverse(SoFar).
%% go through all tests and register all nodes found
get_all_nodes([{suites,Nodes,_,_}|Ts],Spec) when is_list(Nodes) ->
get_all_nodes(Ts,save_nodes(Nodes,Spec));
get_all_nodes([{suites,Node,_,_}|Ts],Spec) ->
get_all_nodes(Ts,save_nodes([Node],Spec));
+get_all_nodes([{groups,[Char|_],_,_,_}|Ts],Spec) when is_integer(Char) ->
+ get_all_nodes(Ts,Spec);
+get_all_nodes([{groups,Nodes,_,_,_}|Ts],Spec) when is_list(Nodes) ->
+ get_all_nodes(Ts,save_nodes(Nodes,Spec));
+get_all_nodes([{groups,Nodes,_,_,_,_}|Ts],Spec) when is_list(Nodes) ->
+ get_all_nodes(Ts,save_nodes(Nodes,Spec));
+get_all_nodes([{groups,_,_,_,{cases,_}}|Ts],Spec) ->
+ get_all_nodes(Ts,Spec);
+get_all_nodes([{groups,Node,_,_,_}|Ts],Spec) ->
+ get_all_nodes(Ts,save_nodes([Node],Spec));
+get_all_nodes([{groups,Node,_,_,_,_}|Ts],Spec) ->
+ get_all_nodes(Ts,save_nodes([Node],Spec));
get_all_nodes([{cases,Nodes,_,_,_}|Ts],Spec) when is_list(Nodes) ->
get_all_nodes(Ts,save_nodes(Nodes,Spec));
get_all_nodes([{cases,Node,_,_,_}|Ts],Spec) ->
@@ -360,74 +513,93 @@ get_all_nodes([{skip_suites,Nodes,_,_,_}|Ts],Spec) when is_list(Nodes) ->
get_all_nodes(Ts,save_nodes(Nodes,Spec));
get_all_nodes([{skip_suites,Node,_,_,_}|Ts],Spec) ->
get_all_nodes(Ts,save_nodes([Node],Spec));
+get_all_nodes([{skip_groups,[Char|_],_,_,_,_}|Ts],Spec) when is_integer(Char) ->
+ get_all_nodes(Ts,Spec);
+get_all_nodes([{skip_groups,Nodes,_,_,_,_}|Ts],Spec) when is_list(Nodes) ->
+ get_all_nodes(Ts,save_nodes(Nodes,Spec));
+get_all_nodes([{skip_groups,Node,_,_,_,_}|Ts],Spec) ->
+ get_all_nodes(Ts,save_nodes([Node],Spec));
+get_all_nodes([{skip_groups,Nodes,_,_,_,_,_}|Ts],Spec) when is_list(Nodes) ->
+ get_all_nodes(Ts,save_nodes(Nodes,Spec));
+get_all_nodes([{skip_groups,Node,_,_,_,_,_}|Ts],Spec) ->
+ get_all_nodes(Ts,save_nodes([Node],Spec));
get_all_nodes([{skip_cases,Nodes,_,_,_,_}|Ts],Spec) when is_list(Nodes) ->
get_all_nodes(Ts,save_nodes(Nodes,Spec));
get_all_nodes([{skip_cases,Node,_,_,_,_}|Ts],Spec) ->
get_all_nodes(Ts,save_nodes([Node],Spec));
-get_all_nodes([_|Ts],Spec) ->
+get_all_nodes([_Other|Ts],Spec) ->
get_all_nodes(Ts,Spec);
get_all_nodes([],Spec) ->
Spec.
-filter_init_terms([{init, InitOptions}|Ts], NewTerms, Spec)->
- filter_init_terms([{init, list_nodes(Spec), InitOptions}|Ts], NewTerms, Spec);
-filter_init_terms([{init, NodeRef, InitOptions}|Ts], NewTerms, Spec)
- when is_atom(NodeRef)->
- filter_init_terms([{init, [NodeRef], InitOptions}|Ts], NewTerms, Spec);
-filter_init_terms([{init, NodeRefs, InitOption}|Ts], NewTerms, Spec) when is_tuple(InitOption) ->
- filter_init_terms([{init, NodeRefs, [InitOption]}|Ts], NewTerms, Spec);
-filter_init_terms([{init, [NodeRef|NodeRefs], InitOptions}|Ts], NewTerms, Spec=#testspec{init=InitData})->
- NodeStartOptions = case lists:keyfind(node_start, 1, InitOptions) of
- {node_start, NSOptions}->
- case lists:keyfind(callback_module, 1, NSOptions) of
- {callback_module, _Callback}->
- NSOptions;
- false->
- [{callback_module, ct_slave}|NSOptions]
- end;
- false->
- []
- end,
- EvalTerms = case lists:keyfind(eval, 1, InitOptions) of
- {eval, MFA} when is_tuple(MFA)->
- [MFA];
- {eval, MFAs} when is_list(MFAs)->
- MFAs;
- false->
- []
- end,
+filter_init_terms([{init,InitOptions}|Ts],NewTerms,Spec) ->
+ filter_init_terms([{init,list_nodes(Spec),InitOptions}|Ts],
+ NewTerms,Spec);
+filter_init_terms([{init,all_nodes,InitOptions}|Ts],NewTerms,Spec) ->
+ filter_init_terms([{init,list_nodes(Spec),InitOptions}|Ts],
+ NewTerms,Spec);
+filter_init_terms([{init,NodeRef,InitOptions}|Ts],
+ NewTerms,Spec) when is_atom(NodeRef) ->
+ filter_init_terms([{init,[NodeRef],InitOptions}|Ts],NewTerms,Spec);
+filter_init_terms([{init,NodeRefs,InitOption}|Ts],
+ NewTerms,Spec) when is_tuple(InitOption) ->
+ filter_init_terms([{init,NodeRefs,[InitOption]}|Ts],NewTerms,Spec);
+filter_init_terms([{init,[NodeRef|NodeRefs],InitOptions}|Ts],
+ NewTerms,Spec=#testspec{init=InitData}) ->
+ NodeStartOptions =
+ case lists:keyfind(node_start,1,InitOptions) of
+ {node_start,NSOptions}->
+ case lists:keyfind(callback_module,1,NSOptions) of
+ {callback_module,_Callback}->
+ NSOptions;
+ false->
+ [{callback_module,ct_slave}|NSOptions]
+ end;
+ false->
+ []
+ end,
+ EvalTerms = case lists:keyfind(eval,1,InitOptions) of
+ {eval,MFA} when is_tuple(MFA) ->
+ [MFA];
+ {eval,MFAs} when is_list(MFAs) ->
+ MFAs;
+ false->
+ []
+ end,
Node = ref2node(NodeRef,Spec#testspec.nodes),
- InitData2 = add_option({node_start, NodeStartOptions}, Node, InitData, true),
- InitData3 = add_option({eval, EvalTerms}, Node, InitData2, false),
- filter_init_terms([{init, NodeRefs, InitOptions}|Ts], NewTerms, Spec#testspec{init=InitData3});
-filter_init_terms([{init, [], _}|Ts], NewTerms, Spec)->
- filter_init_terms(Ts, NewTerms, Spec);
-filter_init_terms([Term|Ts], NewTerms, Spec)->
- filter_init_terms(Ts, [Term|NewTerms], Spec);
-filter_init_terms([], NewTerms, Spec)->
- {lists:reverse(NewTerms), Spec}.
-
-add_option({Key, Value}, Node, List, WarnIfExists) when is_list(Value)->
- OldOptions = case lists:keyfind(Node, 1, List) of
- {Node, Options}->
+ InitData2 = add_option({node_start,NodeStartOptions},Node,InitData,true),
+ InitData3 = add_option({eval,EvalTerms},Node,InitData2,false),
+ filter_init_terms([{init,NodeRefs,InitOptions}|Ts],
+ NewTerms,Spec#testspec{init=InitData3});
+filter_init_terms([{init,[],_}|Ts],NewTerms,Spec) ->
+ filter_init_terms(Ts,NewTerms,Spec);
+filter_init_terms([Term|Ts],NewTerms,Spec) ->
+ filter_init_terms(Ts,[Term|NewTerms],Spec);
+filter_init_terms([],NewTerms,Spec) ->
+ {lists:reverse(NewTerms),Spec}.
+
+add_option({Key,Value},Node,List,WarnIfExists) when is_list(Value) ->
+ OldOptions = case lists:keyfind(Node,1,List) of
+ {Node,Options}->
Options;
false->
[]
end,
- NewOption = case lists:keyfind(Key, 1, OldOptions) of
- {Key, OldOption} when WarnIfExists, OldOption/=[]->
- io:format("There is an option ~w=~w already defined for node ~p, skipping new ~w~n",
- [Key, OldOption, Node, Value]),
+ NewOption = case lists:keyfind(Key,1,OldOptions) of
+ {Key,OldOption} when WarnIfExists,OldOption/=[]->
+ io:format("There is an option ~w=~w already "
+ "defined for node ~p, skipping new ~w~n",
+ [Key,OldOption,Node,Value]),
OldOption;
- {Key, OldOption}->
+ {Key,OldOption}->
OldOption ++ Value;
false->
Value
end,
- lists:keystore(Node, 1, List,
- {Node, lists:keystore(Key, 1, OldOptions, {Key, NewOption})});
-add_option({Key, Value}, Node, List, WarnIfExists)->
- add_option({Key, [Value]}, Node, List, WarnIfExists).
+ lists:keystore(Node,1,List,
+ {Node,lists:keystore(Key,1,OldOptions,{Key,NewOption})});
+add_option({Key,Value},Node,List,WarnIfExists) ->
+ add_option({Key,[Value]},Node,List,WarnIfExists).
save_nodes(Nodes,Spec=#testspec{nodes=NodeRefs}) ->
NodeRefs1 =
@@ -446,252 +618,18 @@ save_nodes(Nodes,Spec=#testspec{nodes=NodeRefs}) ->
end
end
end,NodeRefs,Nodes),
- Spec#testspec{nodes=NodeRefs1}.
+ Spec#testspec{nodes=NodeRefs1}.
list_nodes(#testspec{nodes=NodeRefs}) ->
lists:map(fun({_Ref,Node}) -> Node end, NodeRefs).
-
-%% ---------------------------------------------------------
-%% / \
-%% | When adding tests, remember to update valid_terms/0 also! |
-%% \ /
-%% ---------------------------------------------------------
-
-
-%% Associate a "global" logdir with all nodes
-%% except those with specific logdir, e.g:
-%% ["/tmp/logdir",{ct1@finwe,"/tmp/logdir2"}]
-%% means all nodes should write to /tmp/logdir
-%% except ct1@finwe that should use /tmp/logdir2.
-
-%% --- logdir ---
-add_tests([{logdir,all_nodes,Dir}|Ts],Spec) ->
- Dirs = Spec#testspec.logdir,
- Tests = [{logdir,N,get_absdir(Dir,Spec)} ||
- N <- list_nodes(Spec),
- lists:keymember(ref2node(N,Spec#testspec.nodes),
- 1,Dirs) == false],
- add_tests(Tests++Ts,Spec);
-add_tests([{logdir,Nodes,Dir}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,logdir,[Dir],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{logdir,Node,Dir}|Ts],Spec) ->
- Dirs = Spec#testspec.logdir,
- Dirs1 = [{ref2node(Node,Spec#testspec.nodes),get_absdir(Dir,Spec)} |
- lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,Dirs)],
- add_tests(Ts,Spec#testspec{logdir=Dirs1});
-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,
- Tests = [{label,N,Lbl} || N <- list_nodes(Spec),
- lists:keymember(ref2node(N,Spec#testspec.nodes),
- 1,Labels) == false],
- add_tests(Tests++Ts,Spec);
-add_tests([{label,Nodes,Lbl}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,label,[Lbl],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{label,Node,Lbl}|Ts],Spec) ->
- Labels = Spec#testspec.label,
- Labels1 = [{ref2node(Node,Spec#testspec.nodes),Lbl} |
- lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,Labels)],
- add_tests(Ts,Spec#testspec{label=Labels1});
-add_tests([{label,Lbl}|Ts],Spec) ->
- add_tests([{label,all_nodes,Lbl}|Ts],Spec);
-
-%% --- cover ---
-add_tests([{cover,all_nodes,File}|Ts],Spec) ->
- Tests = lists:map(fun(N) -> {cover,N,File} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{cover,Nodes,File}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,cover,[File],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{cover,Node,File}|Ts],Spec) ->
- CoverFs = Spec#testspec.cover,
- CoverFs1 = [{ref2node(Node,Spec#testspec.nodes),get_absfile(File,Spec)} |
- lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,CoverFs)],
- add_tests(Ts,Spec#testspec{cover=CoverFs1});
-add_tests([{cover,File}|Ts],Spec) ->
- add_tests([{cover,all_nodes,File}|Ts],Spec);
-
-%% --- multiply_timetraps ---
-add_tests([{multiply_timetraps,all_nodes,MT}|Ts],Spec) ->
- Tests = lists:map(fun(N) -> {multiply_timetraps,N,MT} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{multiply_timetraps,Nodes,MT}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,multiply_timetraps,[MT],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{multiply_timetraps,Node,MT}|Ts],Spec) ->
- MTs = Spec#testspec.multiply_timetraps,
- MTs1 = [{ref2node(Node,Spec#testspec.nodes),MT} |
- lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,MTs)],
- add_tests(Ts,Spec#testspec{multiply_timetraps=MTs1});
-add_tests([{multiply_timetraps,MT}|Ts],Spec) ->
- add_tests([{multiply_timetraps,all_nodes,MT}|Ts],Spec);
-
-%% --- scale_timetraps ---
-add_tests([{scale_timetraps,all_nodes,ST}|Ts],Spec) ->
- Tests = lists:map(fun(N) -> {scale_timetraps,N,ST} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{scale_timetraps,Nodes,ST}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,scale_timetraps,[ST],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{scale_timetraps,Node,ST}|Ts],Spec) ->
- STs = Spec#testspec.scale_timetraps,
- STs1 = [{ref2node(Node,Spec#testspec.nodes),ST} |
- lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,STs)],
- add_tests(Ts,Spec#testspec{scale_timetraps=STs1});
-add_tests([{scale_timetraps,ST}|Ts],Spec) ->
- add_tests([{scale_timetraps,all_nodes,ST}|Ts],Spec);
-
-%% --- config ---
-add_tests([{config,all_nodes,Files}|Ts],Spec) ->
- Tests = lists:map(fun(N) -> {config,N,Files} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{config,Nodes,Files}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,config,[Files],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{config,Node,[F|Fs]}|Ts],Spec) when is_list(F) ->
- Cfgs = Spec#testspec.config,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{config,Node,Fs}|Ts],
- Spec#testspec{config=[{Node1,get_absfile(F,Spec)}|Cfgs]});
-add_tests([{config,_Node,[]}|Ts],Spec) ->
- add_tests(Ts,Spec);
-add_tests([{config,Node,F}|Ts],Spec) ->
- add_tests([{config,Node,[F]}|Ts],Spec);
-add_tests([{config,Files}|Ts],Spec) ->
- add_tests([{config,all_nodes,Files}|Ts],Spec);
-
-
-%% --- userconfig ---
-add_tests([{userconfig,all_nodes,CBF}|Ts],Spec) ->
- Tests = lists:map(fun(N) -> {userconfig,N,CBF} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{userconfig,Nodes,CBF}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,userconfig,[CBF],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{userconfig,Node,[{Callback, Config}|CBF]}|Ts],Spec) ->
- Cfgs = Spec#testspec.userconfig,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{userconfig,Node,CBF}|Ts],
- Spec#testspec{userconfig=[{Node1,{Callback,
- get_absfile(Callback, Config ,Spec)}}|Cfgs]});
-add_tests([{userconfig,_Node,[]}|Ts],Spec) ->
- add_tests(Ts,Spec);
-add_tests([{userconfig,Node,CBF}|Ts],Spec) ->
- add_tests([{userconfig,Node,[CBF]}|Ts],Spec);
-add_tests([{userconfig,CBF}|Ts],Spec) ->
- add_tests([{userconfig,all_nodes,CBF}|Ts],Spec);
-
-%% --- event_handler ---
-add_tests([{event_handler,all_nodes,Hs}|Ts],Spec) ->
- Tests = lists:map(fun(N) -> {event_handler,N,Hs,[]} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{event_handler,all_nodes,Hs,Args}|Ts],Spec) when is_list(Args) ->
- Tests = lists:map(fun(N) -> {event_handler,N,Hs,Args} end, list_nodes(Spec)),
- add_tests(Tests++Ts,Spec);
-add_tests([{event_handler,Hs}|Ts],Spec) ->
- add_tests([{event_handler,all_nodes,Hs,[]}|Ts],Spec);
-add_tests([{event_handler,HsOrNodes,HsOrArgs}|Ts],Spec) ->
- case is_noderef(HsOrNodes,Spec#testspec.nodes) of
- true -> % HsOrNodes == Nodes, HsOrArgs == Hs
- case {HsOrNodes,HsOrArgs} of
- {Nodes,Hs} when is_list(Nodes) ->
- Ts1 = separate(Nodes,event_handler,[Hs,[]],Ts,
- Spec#testspec.nodes),
- add_tests(Ts1,Spec);
- {_Node,[]} ->
- add_tests(Ts,Spec);
- {Node,HOrHs} ->
- EvHs = Spec#testspec.event_handler,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- case HOrHs of
- [H|Hs] when is_atom(H) ->
- add_tests([{event_handler,Node,Hs}|Ts],
- Spec#testspec{event_handler=[{Node1,H,[]}|EvHs]});
- H when is_atom(H) ->
- add_tests(Ts,Spec#testspec{event_handler=[{Node1,H,[]}|EvHs]})
- end
- end;
- false -> % HsOrNodes == Hs, HsOrArgs == Args
- add_tests([{event_handler,all_nodes,HsOrNodes,HsOrArgs}|Ts],Spec)
- end;
-add_tests([{event_handler,Nodes,Hs,Args}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,event_handler,[Hs,Args],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{event_handler,Node,[H|Hs],Args}|Ts],Spec) when is_atom(H) ->
- EvHs = Spec#testspec.event_handler,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{event_handler,Node,Hs,Args}|Ts],
- Spec#testspec{event_handler=[{Node1,H,Args}|EvHs]});
-add_tests([{event_handler,_Node,[],_Args}|Ts],Spec) ->
- add_tests(Ts,Spec);
-add_tests([{event_handler,Node,H,Args}|Ts],Spec) when is_atom(H) ->
- EvHs = Spec#testspec.event_handler,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests(Ts,Spec#testspec{event_handler=[{Node1,H,Args}|EvHs]});
-
-%% --- ct_hooks --
-add_tests([{ct_hooks, all_nodes, Hooks} | Ts], Spec) ->
- Tests = [{ct_hooks,N,Hooks} || N <- list_nodes(Spec)],
- add_tests(Tests ++ Ts, Spec);
-add_tests([{ct_hooks, Node, [Hook|Hooks]}|Ts], Spec) ->
- SuiteCbs = Spec#testspec.ct_hooks,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{ct_hooks, Node, Hooks} | Ts],
- Spec#testspec{ct_hooks = [{Node1,Hook} | SuiteCbs]});
-add_tests([{ct_hooks, _Node, []}|Ts], Spec) ->
- add_tests(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)),
- add_tests(Tests++Ts,Spec);
-add_tests([{include,Nodes,InclDirs}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,include,[InclDirs],Ts,Spec#testspec.nodes),
- add_tests(Ts1,Spec);
-add_tests([{include,Node,[D|Ds]}|Ts],Spec) when is_list(D) ->
- Dirs = Spec#testspec.include,
- Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{include,Node,Ds}|Ts],
- Spec#testspec{include=[{Node1,get_absdir(D,Spec)}|Dirs]});
-add_tests([{include,_Node,[]}|Ts],Spec) ->
- add_tests(Ts,Spec);
-add_tests([{include,Node,D}|Ts],Spec) ->
- add_tests([{include,Node,[D]}|Ts],Spec);
-add_tests([{include,InclDirs}|Ts],Spec) ->
- add_tests([{include,all_nodes,InclDirs}|Ts],Spec);
+%% -----------------------------------------------------
+%% / \
+%% | When adding test/config terms, remember to update |
+%% | valid_terms/0 also! |
+%% \ /
+%% -----------------------------------------------------
%% --- suites ---
add_tests([{suites,all_nodes,Dir,Ss}|Ts],Spec) ->
@@ -704,7 +642,7 @@ add_tests([{suites,Nodes,Dir,Ss}|Ts],Spec) when is_list(Nodes) ->
add_tests([{suites,Node,Dir,Ss}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = insert_suites(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Ss,Tests, Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
@@ -724,20 +662,22 @@ add_tests([{groups,Dir,Suite,Gs,{cases,TCs}}|Ts],Spec) ->
add_tests([{groups,Nodes,Dir,Suite,Gs}|Ts],Spec) when is_list(Nodes) ->
Ts1 = separate(Nodes,groups,[Dir,Suite,Gs],Ts,Spec#testspec.nodes),
add_tests(Ts1,Spec);
-add_tests([{groups,Nodes,Dir,Suite,Gs,{cases,TCs}}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,groups,[Dir,Suite,Gs,{cases,TCs}],Ts,Spec#testspec.nodes),
+add_tests([{groups,Nodes,Dir,Suite,Gs,{cases,TCs}}|Ts],
+ Spec) when is_list(Nodes) ->
+ Ts1 = separate(Nodes,groups,[Dir,Suite,Gs,{cases,TCs}],Ts,
+ Spec#testspec.nodes),
add_tests(Ts1,Spec);
add_tests([{groups,Node,Dir,Suite,Gs}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = insert_groups(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Suite,Gs,all,Tests,
Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
add_tests([{groups,Node,Dir,Suite,Gs,{cases,TCs}}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = insert_groups(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Suite,Gs,TCs,Tests,
Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
@@ -753,7 +693,7 @@ add_tests([{cases,Nodes,Dir,Suite,Cs}|Ts],Spec) when is_list(Nodes) ->
add_tests([{cases,Node,Dir,Suite,Cs}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = insert_cases(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Suite,Cs,Tests, Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
@@ -768,7 +708,7 @@ add_tests([{skip_suites,Nodes,Dir,Ss,Cmt}|Ts],Spec) when is_list(Nodes) ->
add_tests([{skip_suites,Node,Dir,Ss,Cmt}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = skip_suites(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Ss,Cmt,Tests,
Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
@@ -777,7 +717,8 @@ add_tests([{skip_suites,Node,Dir,Ss,Cmt}|Ts],Spec) ->
add_tests([{skip_groups,all_nodes,Dir,Suite,Gs,Cmt}|Ts],Spec) ->
add_tests([{skip_groups,list_nodes(Spec),Dir,Suite,Gs,Cmt}|Ts],Spec);
add_tests([{skip_groups,all_nodes,Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],Spec) ->
- add_tests([{skip_groups,list_nodes(Spec),Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],Spec);
+ add_tests([{skip_groups,list_nodes(Spec),Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],
+ Spec);
add_tests([{skip_groups,Dir,Suite,Gs,Cmt}|Ts],Spec) ->
add_tests([{skip_groups,all_nodes,Dir,Suite,Gs,Cmt}|Ts],Spec);
add_tests([{skip_groups,Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],Spec) ->
@@ -785,20 +726,22 @@ add_tests([{skip_groups,Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],Spec) ->
add_tests([{skip_groups,Nodes,Dir,Suite,Gs,Cmt}|Ts],Spec) when is_list(Nodes) ->
Ts1 = separate(Nodes,skip_groups,[Dir,Suite,Gs,Cmt],Ts,Spec#testspec.nodes),
add_tests(Ts1,Spec);
-add_tests([{skip_groups,Nodes,Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],Spec) when is_list(Nodes) ->
- Ts1 = separate(Nodes,skip_groups,[Dir,Suite,Gs,{cases,TCs},Cmt],Ts,Spec#testspec.nodes),
+add_tests([{skip_groups,Nodes,Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],
+ Spec) when is_list(Nodes) ->
+ Ts1 = separate(Nodes,skip_groups,[Dir,Suite,Gs,{cases,TCs},Cmt],Ts,
+ Spec#testspec.nodes),
add_tests(Ts1,Spec);
add_tests([{skip_groups,Node,Dir,Suite,Gs,Cmt}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = skip_groups(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Suite,Gs,all,Cmt,Tests,
Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
add_tests([{skip_groups,Node,Dir,Suite,Gs,{cases,TCs},Cmt}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = skip_groups(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Suite,Gs,TCs,Cmt,Tests,
Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
@@ -814,45 +757,101 @@ add_tests([{skip_cases,Nodes,Dir,Suite,Cs,Cmt}|Ts],Spec) when is_list(Nodes) ->
add_tests([{skip_cases,Node,Dir,Suite,Cs,Cmt}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = skip_cases(ref2node(Node,Spec#testspec.nodes),
- ref2dir(Dir,Spec#testspec.alias),
+ ref2dir(Dir,Spec),
Suite,Cs,Cmt,Tests,Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
+%% --- various configuration terms ---
+add_tests([{config,Nodes,CfgDir,Files}|Ts],Spec) when is_list(Nodes);
+ Nodes == all_nodes ->
+ add_tests([{config,Nodes,{CfgDir,Files}}|Ts],Spec);
+add_tests([{config,Node,CfgDir,FileOrFiles}|Ts],Spec) ->
+ add_tests([{config,Node,{CfgDir,FileOrFiles}}|Ts],Spec);
+add_tests([{config,CfgDir=[Ch|_],Files}|Ts],Spec) when is_integer(Ch) ->
+ add_tests([{config,all_nodes,{CfgDir,Files}}|Ts],Spec);
+
+add_tests([{event_handler,Nodes,Hs,Args}|Ts],Spec) when is_list(Nodes);
+ Nodes == all_nodes ->
+ add_tests([{event_handler,Nodes,{Hs,Args}}|Ts],Spec);
+add_tests([{event_handler,Node,HOrHs,Args}|Ts],Spec) ->
+ add_tests([{event_handler,Node,{HOrHs,Args}}|Ts],Spec);
+
+add_tests([{enable_builtin_hooks,Bool}|Ts],Spec) ->
+ add_tests(Ts, Spec#testspec{enable_builtin_hooks = Bool});
+
+add_tests([{release_shell,Bool}|Ts],Spec) ->
+ add_tests(Ts, Spec#testspec{release_shell = Bool});
+
%% --- handled/errors ---
+add_tests([{define,_,_}|Ts],Spec) -> % handled
+ add_tests(Ts,Spec);
+
add_tests([{alias,_,_}|Ts],Spec) -> % handled
add_tests(Ts,Spec);
add_tests([{node,_,_}|Ts],Spec) -> % handled
add_tests(Ts,Spec);
-add_tests([{merge_tests, _} | Ts], Spec) -> % handled
+add_tests([{merge_tests, _} | Ts], Spec) -> % handled
add_tests(Ts,Spec);
-%% check if it's a CT term that has bad format or if the user seems to
-%% have added something of his/her own, which we'll let pass if relaxed
-%% mode is enabled.
-add_tests([Other|Ts],Spec) when is_tuple(Other) ->
- [Name|_] = tuple_to_list(Other),
- case lists:keymember(Name,1,valid_terms()) of
- true -> % halt
- throw({error,{bad_term_in_spec,Other}});
- false -> % ignore
- case get(relaxed) of
- true ->
- %% warn if name resembles a CT term
- case resembles_ct_term(Name,size(Other)) of
- true ->
- io:format("~nSuspicious term, please check:~n"
- "~p~n", [Other]);
- false ->
- ok
- end,
- add_tests(Ts,Spec);
- false ->
- throw({error,{undefined_term_in_spec,Other}})
- end
+%% --------------------------------------------------
+%% / \
+%% | General add_tests/2 clauses below will work for |
+%% | most test spec configuration terms |
+%% \ /
+%% --------------------------------------------------
+
+%% create one test entry per known node and reinsert
+add_tests([Term={Tag,all_nodes,Data}|Ts],Spec) ->
+ case check_term(Term) of
+ valid ->
+ Tests = [{Tag,Node,Data} || Node <- list_nodes(Spec),
+ should_be_added(Tag,Node,Data,Spec)],
+ add_tests(Tests++Ts,Spec);
+ invalid -> % ignore term
+ add_tests(Ts,Spec)
end;
-
+%% create one test entry per node in Nodes and reinsert
+add_tests([{Tag,[],Data}|Ts],Spec) ->
+ add_tests([{Tag,all_nodes,Data}|Ts],Spec);
+add_tests([{Tag,String=[Ch|_],Data}|Ts],Spec) when is_integer(Ch) ->
+ add_tests([{Tag,all_nodes,{String,Data}}|Ts],Spec);
+add_tests([{Tag,NodesOrOther,Data}|Ts],Spec) when is_list(NodesOrOther) ->
+ case lists:all(fun(Test) -> is_node(Test,Spec#testspec.nodes)
+ end, NodesOrOther) of
+ true ->
+ Ts1 = separate(NodesOrOther,Tag,[Data],Ts,Spec#testspec.nodes),
+ add_tests(Ts1,Spec);
+ false ->
+ add_tests([{Tag,all_nodes,{NodesOrOther,Data}}|Ts],Spec)
+ end;
+%% update data for testspec term of type Tag
+add_tests([Term={Tag,NodeOrOther,Data}|Ts],Spec) ->
+ case is_node(NodeOrOther,Spec#testspec.nodes) of
+ true ->
+ case check_term(Term) of
+ valid ->
+ Node = ref2node(NodeOrOther,Spec#testspec.nodes),
+ NodeIxData =
+ update_recorded(Tag,Node,Spec) ++
+ handle_data(Tag,Node,Data,Spec),
+ add_tests(Ts,mod_field(Spec,Tag,NodeIxData));
+ invalid -> % ignore term
+ add_tests(Ts,Spec)
+ end;
+ false ->
+ add_tests([{Tag,all_nodes,{NodeOrOther,Data}}|Ts],Spec)
+ end;
+%% this test should be added for all known nodes
+add_tests([Term={Tag,Data}|Ts],Spec) ->
+ case check_term(Term) of
+ valid ->
+ add_tests([{Tag,all_nodes,Data}|Ts],Spec);
+ invalid ->
+ add_tests(Ts,Spec)
+ end;
+%% some other data than a tuple
add_tests([Other|Ts],Spec) ->
case get(relaxed) of
true ->
@@ -864,6 +863,118 @@ add_tests([Other|Ts],Spec) ->
add_tests([],Spec) -> % done
Spec.
+%% check if it's a CT term that has bad format or if the user seems to
+%% have added something of his/her own, which we'll let pass if relaxed
+%% mode is enabled.
+check_term(Term) ->
+ Size = size(Term),
+ [Name|_] = tuple_to_list(Term),
+ Valid = valid_terms(),
+ case lists:member({Name,Size},Valid) of
+ true ->
+ valid;
+ false ->
+ case lists:keymember(Name,1,Valid) of
+ true -> % halt
+ throw({error,{bad_term_in_spec,Term}});
+ false -> % ignore
+ case get(relaxed) of
+ true ->
+ %% warn if name resembles a CT term
+ case resembles_ct_term(Name,size(Term)) of
+ true ->
+ io:format("~nSuspicious term, "
+ "please check:~n"
+ "~p~n", [Term]),
+ invalid;
+ false ->
+ invalid
+ end;
+ false ->
+ throw({error,{undefined_term_in_spec,Term}})
+ end
+ end
+ end.
+
+%% specific data handling before saving in testspec record, e.g.
+%% converting relative paths to absolute for directories and files
+%% (introduce a clause *only* if the data value needs processing)
+handle_data(logdir,Node,Dir,Spec) ->
+ [{Node,ref2dir(Dir,Spec)}];
+handle_data(cover,Node,File,Spec) ->
+ [{Node,get_absfile(File,Spec)}];
+handle_data(include,Node,Dirs=[D|_],Spec) when is_list(D) ->
+ [{Node,ref2dir(Dir,Spec)} || Dir <- Dirs];
+handle_data(include,Node,Dir=[Ch|_],Spec) when is_integer(Ch) ->
+ handle_data(include,Node,[Dir],Spec);
+handle_data(config,Node,File=[Ch|_],Spec) when is_integer(Ch) ->
+ handle_data(config,Node,[File],Spec);
+handle_data(config,Node,{CfgDir,File=[Ch|_]},Spec) when is_integer(Ch) ->
+ handle_data(config,Node,{CfgDir,[File]},Spec);
+handle_data(config,Node,Files=[F|_],Spec) when is_list(F) ->
+ [{Node,get_absfile(File,Spec)} || File <- Files];
+handle_data(config,Node,{CfgDir,Files=[F|_]},Spec) when is_list(F) ->
+ [{Node,filename:join(ref2dir(CfgDir,Spec),File)} || File <- Files];
+handle_data(userconfig,Node,CBs,Spec) when is_list(CBs) ->
+ [{Node,{Callback,get_absfile(Callback,Config,Spec)}} ||
+ {Callback,Config} <- CBs];
+handle_data(userconfig,Node,CB,Spec) when is_tuple(CB) ->
+ handle_data(userconfig,Node,[CB],Spec);
+handle_data(event_handler,Node,H,Spec) when is_atom(H) ->
+ handle_data(event_handler,Node,{[H],[]},Spec);
+handle_data(event_handler,Node,{H,Args},Spec) when is_atom(H) ->
+ handle_data(event_handler,Node,{[H],Args},Spec);
+handle_data(event_handler,Node,Hs,_Spec) when is_list(Hs) ->
+ [{Node,EvH,[]} || EvH <- Hs];
+handle_data(event_handler,Node,{Hs,Args},_Spec) when is_list(Hs) ->
+ [{Node,EvH,Args} || EvH <- Hs];
+handle_data(ct_hooks,Node,Hooks,_Spec) when is_list(Hooks) ->
+ [{Node,Hook} || Hook <- Hooks ];
+handle_data(ct_hooks,Node,Hook,_Spec) ->
+ [{Node,Hook}];
+handle_data(stylesheet,Node,CSSFile,Spec) ->
+ [{Node,get_absfile(CSSFile,Spec)}];
+handle_data(verbosity,Node,VLvls,_Spec) when is_integer(VLvls) ->
+ [{Node,[{'$unspecified',VLvls}]}];
+handle_data(verbosity,Node,VLvls,_Spec) when is_list(VLvls) ->
+ VLvls1 = lists:map(fun(VLvl = {_Cat,_Lvl}) -> VLvl;
+ (Lvl) -> {'$unspecified',Lvl} end, VLvls),
+ [{Node,VLvls1}];
+handle_data(silent_connections,Node,all,_Spec) ->
+ [{Node,[all]}];
+handle_data(silent_connections,Node,Conn,_Spec) when is_atom(Conn) ->
+ [{Node,[Conn]}];
+handle_data(silent_connections,Node,Conns,_Spec) ->
+ [{Node,Conns}];
+handle_data(_Tag,Node,Data,_Spec) ->
+ [{Node,Data}].
+
+%% check if duplicates should be saved or not
+should_be_added(Tag,Node,_Data,Spec) ->
+ if
+ %% list terms *without* possible duplicates here
+ Tag == logdir; Tag == logopts;
+ Tag == basic_html; Tag == label;
+ Tag == auto_compile; Tag == stylesheet;
+ Tag == verbosity; Tag == silent_connections ->
+ lists:keymember(ref2node(Node,Spec#testspec.nodes),1,
+ read_field(Spec,Tag)) == false;
+ %% for terms *with* possible duplicates
+ true ->
+ true
+ end.
+
+%% check if previous elements for Node should be deleted
+update_recorded(Tag,Node,Spec) ->
+ if Tag == config; Tag == userconfig; Tag == event_handler;
+ Tag == ct_hooks; Tag == include ->
+ read_field(Spec,Tag);
+ true ->
+ %% delete previous value for Tag
+ lists:keydelete(Node,1,read_field(Spec,Tag))
+ end.
+
+%% create one test term per node
separate(Nodes,Tag,Data,Tests,Refs) ->
Separated = separate(Nodes,Tag,Data,Refs),
Separated ++ Tests.
@@ -871,14 +982,36 @@ separate([N|Ns],Tag,Data,Refs) ->
[list_to_tuple([Tag,ref2node(N,Refs)|Data])|separate(Ns,Tag,Data,Refs)];
separate([],_,_,_) ->
[].
-
+
+%% read the value for FieldName in record Rec#testspec
+read_field(Rec, FieldName) ->
+ catch lists:foldl(fun(F, Pos) when F == FieldName ->
+ throw(element(Pos, Rec));
+ (_,Pos) ->
+ Pos+1
+ end,2,?testspec_fields).
+
+%% modify the value for FieldName in record Rec#testspec
+mod_field(Rec, FieldName, NewVal) ->
+ [_testspec|RecList] = tuple_to_list(Rec),
+ RecList1 =
+ (catch lists:foldl(fun(F, {Prev,[_OldVal|Rest]}) when F == FieldName ->
+ throw(lists:reverse(Prev) ++ [NewVal|Rest]);
+ (_,{Prev,[Field|Rest]}) ->
+ {[Field|Prev],Rest}
+ end,{[],RecList},?testspec_fields)),
+ list_to_tuple([testspec|RecList1]).
%% Representation:
%% {{Node,Dir},[{Suite1,[GrOrCase11,GrOrCase12,...]},
%% {Suite2,[GrOrCase21,GrOrCase22,...]},...]}
%% {{Node,Dir},[{Suite1,{skip,Cmt}},
%% {Suite2,[{GrOrCase21,{skip,Cmt}},GrOrCase22,...]},...]}
-%% GrOrCase = {GroupName,[Case1,Case2,...]} | Case
+%% GrOrCase = {GroupSpec,[Case1,Case2,...]} | Case
+%% GroupSpec = {GroupName,OverrideProps} |
+%% {GroupName,OverrideProps,SubGroupSpec}
+%% OverrideProps = Props | default
+%% SubGroupSpec = GroupSpec | []
insert_suites(Node,Dir,[S|Ss],Tests, MergeTests) ->
Tests1 = insert_cases(Node,Dir,S,all,Tests,MergeTests),
@@ -889,7 +1022,7 @@ insert_suites(Node,Dir,S,Tests,MergeTests) ->
insert_suites(Node,Dir,[S],Tests,MergeTests).
insert_groups(Node,Dir,Suite,Group,Cases,Tests,MergeTests)
- when is_atom(Group) ->
+ when is_atom(Group); is_tuple(Group) ->
insert_groups(Node,Dir,Suite,[Group],Cases,Tests,MergeTests);
insert_groups(Node,Dir,Suite,Groups,Cases,Tests,false) when
((Cases == all) or is_list(Cases)) and is_list(Groups) ->
@@ -1075,33 +1208,40 @@ ref2node(all_nodes,_Refs) ->
ref2node(master,_Refs) ->
master;
ref2node(RefOrNode,Refs) ->
- case string:chr(atom_to_list(RefOrNode),$@) of
- 0 -> % a ref
+ case lists:member($@,atom_to_list(RefOrNode)) of
+ false -> % a ref
case lists:keysearch(RefOrNode,1,Refs) of
{value,{RefOrNode,Node}} ->
Node;
false ->
throw({error,{noderef_missing,RefOrNode}})
end;
- _ -> % a node
+ true -> % a node
RefOrNode
end.
-ref2dir(Ref,Refs) when is_atom(Ref) ->
+ref2dir(Ref,Spec) ->
+ ref2dir(Ref,Spec#testspec.alias,Spec).
+
+ref2dir(Ref,Refs,Spec) when is_atom(Ref) ->
case lists:keysearch(Ref,1,Refs) of
{value,{Ref,Dir}} ->
- Dir;
+ get_absdir(Dir,Spec);
false ->
throw({error,{alias_missing,Ref}})
end;
-ref2dir(Dir,_) when is_list(Dir) ->
- Dir.
-
-is_noderef(What,Nodes) when is_atom(What) ->
- is_noderef([What],Nodes);
-is_noderef([master|_],_Nodes) ->
+ref2dir(Dir,_,Spec) when is_list(Dir) ->
+ get_absdir(Dir,Spec);
+ref2dir(What,_,_) ->
+ throw({error,{invalid_directory_name,What}}).
+
+is_node(What,Nodes) when is_atom(What) ->
+ is_node([What],Nodes);
+is_node([master|_],_Nodes) ->
true;
-is_noderef([What|_],Nodes) ->
+is_node(What={N,H},Nodes) when is_atom(N), is_atom(H) ->
+ is_node([What],Nodes);
+is_node([What|_],Nodes) ->
case lists:keymember(What,1,Nodes) or
lists:keymember(What,2,Nodes) of
true ->
@@ -1109,24 +1249,32 @@ is_noderef([What|_],Nodes) ->
false ->
false
end;
-is_noderef([],_) ->
+is_node([],_) ->
false.
valid_terms() ->
[
+ {define,3},
{node,3},
{cover,2},
{cover,3},
{config,2},
{config,3},
+ {config,4},
{userconfig,2},
{userconfig,3},
{alias,3},
- {merge_tests,1},
+ {merge_tests,2},
{logdir,2},
{logdir,3},
{logopts,2},
{logopts,3},
+ {basic_html,2},
+ {basic_html,3},
+ {verbosity,2},
+ {verbosity,3},
+ {silent_connections,2},
+ {silent_connections,3},
{label,2},
{label,3},
{event_handler,2},
@@ -1134,13 +1282,18 @@ valid_terms() ->
{event_handler,4},
{ct_hooks,2},
{ct_hooks,3},
- {enable_builtin_hooks,1},
+ {enable_builtin_hooks,2},
+ {release_shell,2},
{multiply_timetraps,2},
{multiply_timetraps,3},
{scale_timetraps,2},
{scale_timetraps,3},
{include,2},
{include,3},
+ {auto_compile,2},
+ {auto_compile,3},
+ {stylesheet,2},
+ {stylesheet,3},
{suites,3},
{suites,4},
{groups,4},
@@ -1154,7 +1307,9 @@ valid_terms() ->
{skip_groups,6},
{skip_groups,7},
{skip_cases,5},
- {skip_cases,6}
+ {skip_cases,6},
+ {create_priv_dir,2},
+ {create_priv_dir,3}
].
%% this function "guesses" if the user has misspelled a term name
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index 3b6ad6f98d..cf891ed043 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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 @@
%%%
-module(ct_util).
--export([start/0,start/1,start/2,stop/1,update_last_run_index/0]).
+-export([start/0,start/1,start/2,start/3,
+ stop/1,update_last_run_index/0]).
-export([register_connection/4,unregister_connection/1,
does_connection_exist/3,get_key_from_name/1]).
@@ -36,14 +37,15 @@
save_suite_data_async/3, save_suite_data_async/2,
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,
- set_testdata_async/1, update_testdata/2]).
+ delete_testdata/0, delete_testdata/1,
+ set_testdata/1, get_testdata/1, get_testdata/2,
+ set_testdata_async/1, update_testdata/2, update_testdata/3]).
-export([override_silence_all_connections/0, override_silence_connections/1,
get_overridden_silenced_connections/0,
delete_overridden_silenced_connections/0,
- silence_all_connections/0, silence_connections/1, is_silenced/1,
- reset_silent_connections/0]).
+ silence_all_connections/0, silence_connections/1,
+ is_silenced/1, is_silenced/2, reset_silent_connections/0]).
-export([get_mode/0, create_table/3, read_opts/0]).
@@ -64,9 +66,13 @@
-export([get_profile_data/0, get_profile_data/1,
get_profile_data/2, open_url/3]).
+-include("ct.hrl").
-include("ct_event.hrl").
-include("ct_util.hrl").
+-define(default_verbosity, [{default,?MAX_VERBOSITY},
+ {'$unspecified',?MAX_VERBOSITY}]).
+
-record(suite_data, {key,name,value}).
%%%-----------------------------------------------------------------
@@ -85,18 +91,21 @@
%%%
%%% @see ct
start() ->
- start(normal,".").
+ start(normal, ".", ?default_verbosity).
start(LogDir) when is_list(LogDir) ->
- start(normal,LogDir);
+ start(normal, LogDir, ?default_verbosity);
start(Mode) ->
- start(Mode,".").
+ start(Mode, ".", ?default_verbosity).
+
+start(LogDir, Verbosity) when is_list(LogDir) ->
+ start(normal, LogDir, Verbosity).
-start(Mode,LogDir) ->
+start(Mode, LogDir, Verbosity) ->
case whereis(ct_util_server) of
undefined ->
S = self(),
- Pid = spawn_link(fun() -> do_start(S,Mode,LogDir) end),
+ Pid = spawn_link(fun() -> do_start(S, Mode, LogDir, Verbosity) end),
receive
{Pid,started} -> Pid;
{Pid,Error} -> exit(Error);
@@ -113,7 +122,7 @@ start(Mode,LogDir) ->
end
end.
-do_start(Parent,Mode,LogDir) ->
+do_start(Parent, Mode, LogDir, Verbosity) ->
process_flag(trap_exit,true),
register(ct_util_server,self()),
create_table(?conn_table,#conn.handle),
@@ -173,7 +182,7 @@ do_start(Parent,Mode,LogDir) ->
false ->
ok
end,
- {StartTime,TestLogDir} = ct_logs:init(Mode),
+ {StartTime,TestLogDir} = ct_logs:init(Mode, Verbosity),
ct_event:notify(#event{name=test_start,
node=node(),
@@ -193,7 +202,7 @@ do_start(Parent,Mode,LogDir) ->
self() ! {{stop,{self(),{user_error,CTHReason}}},
{Parent,make_ref()}}
end,
- loop(Mode,[],StartDir).
+ loop(Mode, [{{verbosity,Cat},Lvl} || {Cat,Lvl} <- Verbosity], StartDir).
create_table(TableName,KeyPos) ->
create_table(TableName,set,KeyPos).
@@ -243,7 +252,10 @@ delete_testdata(Key) ->
call({delete_testdata, Key}).
update_testdata(Key, Fun) ->
- call({update_testdata, Key, Fun}).
+ update_testdata(Key, Fun, []).
+
+update_testdata(Key, Fun, Opts) ->
+ call({update_testdata, Key, Fun, Opts}).
set_testdata(TestData) ->
call({set_testdata, TestData}).
@@ -254,6 +266,9 @@ set_testdata_async(TestData) ->
get_testdata(Key) ->
call({get_testdata, Key}).
+get_testdata(Key, Timeout) ->
+ call({get_testdata, Key}, Timeout).
+
set_cwd(Dir) ->
call({set_cwd,Dir}).
@@ -321,7 +336,7 @@ loop(Mode,TestData,StartDir) ->
return(From,undefined)
end,
loop(From,TestData,StartDir);
- {{update_testdata,Key,Fun},From} ->
+ {{update_testdata,Key,Fun,Opts},From} ->
TestData1 =
case lists:keysearch(Key,1,TestData) of
{value,{Key,Val}} ->
@@ -329,8 +344,15 @@ loop(Mode,TestData,StartDir) ->
return(From,NewVal),
[{Key,NewVal}|lists:keydelete(Key,1,TestData)];
_ ->
- return(From,undefined),
- TestData
+ case lists:member(create,Opts) of
+ true ->
+ InitVal = Fun(undefined),
+ return(From,InitVal),
+ [{Key,InitVal}|TestData];
+ false ->
+ return(From,undefined),
+ TestData
+ end
end,
loop(From,TestData1,StartDir);
{{set_cwd,Dir},From} ->
@@ -369,14 +391,25 @@ loop(Mode,TestData,StartDir) ->
{'EXIT',_Pid,normal} ->
loop(Mode,TestData,StartDir);
{'EXIT',Pid,Reason} ->
- %% Let process crash in case of error, this shouldn't happen!
- io:format("\n\nct_util_server got EXIT from ~p: ~p\n\n",
- [Pid,Reason]),
- file:set_cwd(StartDir),
- exit(Reason)
+ case ets:lookup(?conn_table,Pid) of
+ [#conn{address=A,callback=CB}] ->
+ %% A connection crashed - remove the connection but don't die
+ ct_logs:tc_log_async(ct_error_notify,
+ "Connection process died: "
+ "Pid: ~p, Address: ~p, Callback: ~p\n"
+ "Reason: ~p\n\n",
+ [Pid,A,CB,Reason]),
+ catch CB:close(Pid),
+ loop(Mode,TestData,StartDir);
+ _ ->
+ %% Let process crash in case of error, this shouldn't happen!
+ io:format("\n\nct_util_server got EXIT from ~p: ~p\n\n",
+ [Pid,Reason]),
+ file:set_cwd(StartDir),
+ exit(Reason)
+ end
end.
-
close_connections([#conn{handle=Handle,callback=CB}|Conns]) ->
CB:close(Handle),
close_connections(Conns);
@@ -508,7 +541,7 @@ close_connections() ->
%%%
%%% @doc
override_silence_all_connections() ->
- Protocols = [telnet,ftp,rpc,snmp],
+ Protocols = [telnet,ftp,rpc,snmp,ssh],
override_silence_connections(Protocols),
Protocols.
@@ -545,7 +578,10 @@ silence_connections(Conns) when is_list(Conns) ->
set_testdata({silent_connections,Conns1}).
is_silenced(Conn) ->
- case get_testdata(silent_connections) of
+ is_silenced(Conn, infinity).
+
+is_silenced(Conn, Timeout) ->
+ case get_testdata(silent_connections, Timeout) of
Conns when is_list(Conns) ->
case lists:keysearch(Conn,1,Conns) of
{value,{Conn,true}} ->
@@ -553,6 +589,8 @@ is_silenced(Conn) ->
_ ->
false
end;
+ Error = {error,_} ->
+ Error;
_ ->
false
end.
@@ -827,15 +865,29 @@ get_profile_data(Profile, Key, StartDir) ->
%%%-----------------------------------------------------------------
%%% Internal functions
call(Msg) ->
- MRef = erlang:monitor(process,whereis(ct_util_server)),
- Ref = make_ref(),
- ct_util_server ! {Msg,{self(),Ref}},
- receive
- {Ref, Result} ->
- erlang:demonitor(MRef, [flush]),
- Result;
- {'DOWN',MRef,process,_,Reason} ->
- {error,{ct_util_server_down,Reason}}
+ call(Msg, infinity).
+
+call(Msg, Timeout) ->
+ case {self(),whereis(ct_util_server)} of
+ {_,undefined} ->
+ {error,ct_util_server_not_running};
+ {Pid,Pid} ->
+ %% the caller is ct_util_server, which must
+ %% be a mistake
+ {error,bad_invocation};
+ {Self,Pid} ->
+ MRef = erlang:monitor(process, Pid),
+ Ref = make_ref(),
+ ct_util_server ! {Msg,{Self,Ref}},
+ receive
+ {Ref, Result} ->
+ erlang:demonitor(MRef, [flush]),
+ Result;
+ {'DOWN',MRef,process,_,Reason} ->
+ {error,{ct_util_server_down,Reason}}
+ after
+ Timeout -> {error,timeout}
+ end
end.
return({To,Ref},Result) ->
diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl
index bde832811a..196b5e46d0 100644
--- a/lib/common_test/src/ct_util.hrl
+++ b/lib/common_test/src/ct_util.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,18 +34,25 @@
profile=[],
logdir=["."],
logopts=[],
+ basic_html=[],
+ verbosity=[],
+ silent_connections=[],
cover=[],
config=[],
userconfig=[],
event_handler=[],
ct_hooks=[],
enable_builtin_hooks=true,
+ release_shell=false,
include=[],
+ auto_compile=[],
+ stylesheet=[],
multiply_timetraps=[],
scale_timetraps=[],
+ create_priv_dir=[],
alias=[],
tests=[],
- merge_tests = true }).
+ merge_tests=true}).
-record(cover, {app=none,
level=details,
@@ -63,3 +70,11 @@
-define(ct_config_txt, ct_config_plain).
-define(ct_profile_file, ".common_test").
+
+-define(css_default, "ct_default.css").
+-define(sortable_table_name, "SortableTable").
+-define(jquery_script, "jquery-latest.js").
+-define(tablesorter_script, "jquery.tablesorter.min.js").
+
+%% Logging information for error handler
+-record(conn_log, {client, name, address, action, module}).
diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl
new file mode 100644
index 0000000000..3af89db3a5
--- /dev/null
+++ b/lib/common_test/src/cth_conn_log.erl
@@ -0,0 +1,124 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% CT hook for logging of connections.
+%%
+%% HookOptions can be hardcoded in the test suite:
+%%
+%% suite() ->
+%% [{ct_hooks, [{cth_conn_log,
+%% [{ct_netconfc:conn_mod(),ct_netconfc:hook_options()}]}]}].
+%%
+%% or specified in a configuration file:
+%%
+%% {ct_conn_log,[{ct_netconfc:conn_mod(),ct_netconfc:hook_options()}]}.
+%%
+%% The conn_mod() is the common test module implementing the protocol,
+%% e.g. ct_netconfc, ct_telnet, etc. This module must log by calling
+%%
+%% error_logger:info_report(ConnLogInfo,Data).
+%% ConnLogInfo = #conn_log{} | {ct_connection,Action,ConnName}
+%% Action = open | close | send | recv | term()
+%% ConnName = atom() - The 'KeyOrName' argument used when opening the connection
+%%
+%% ct_conn_log_h will print to html log or separate file (depending on
+%% log_type() option). conn_mod() must implement and export
+%%
+%% format_data(log_type(), Data).
+%%
+%% If logging to separate file, ct_conn_log_h will also log error
+%% reports which are witten like this:
+%%
+%% error_logger:error_report([{ct_connection,ConnName} | Report]).
+%%
+%%----------------------------------------------------------------------
+-module(cth_conn_log).
+
+-include_lib("common_test/include/ct.hrl").
+
+-export([init/2,
+ pre_init_per_testcase/3,
+ post_end_per_testcase/4]).
+
+-spec init(Id, HookOpts) -> Result when
+ Id :: term(),
+ HookOpts :: ct:hook_options(),
+ Result :: {ok,[{ct_netconfc:conn_mod(),
+ {ct_netconfc:log_type(),[ct_netconfc:key_or_name()]}}]}.
+init(_Id, HookOpts) ->
+ ConfOpts = ct:get_config(ct_conn_log,[]),
+ {ok,merge_log_info(ConfOpts,HookOpts)}.
+
+merge_log_info([{Mod,ConfOpts}|ConfList],HookList) ->
+ {Opts,HookList1} =
+ case lists:keytake(Mod,1,HookList) of
+ false ->
+ {ConfOpts,HookList};
+ {value,{_,HookOpts},HL1} ->
+ {ConfOpts ++ HookOpts, HL1} % ConfOpts overwrites HookOpts!
+ end,
+ [{Mod,get_log_opts(Opts)} | merge_log_info(ConfList,HookList1)];
+merge_log_info([],HookList) ->
+ [{Mod,get_log_opts(Opts)} || {Mod,Opts} <- HookList].
+
+get_log_opts(Opts) ->
+ LogType = proplists:get_value(log_type,Opts,html),
+ Hosts = proplists:get_value(hosts,Opts,[]),
+ {LogType,Hosts}.
+
+
+pre_init_per_testcase(TestCase,Config,CthState) ->
+ Logs =
+ lists:map(
+ fun({ConnMod,{LogType,Hosts}}) ->
+ case LogType of
+ LogType when LogType==raw; LogType==pretty ->
+ Dir = ?config(priv_dir,Config),
+ TCStr = atom_to_list(TestCase),
+ ConnModStr = atom_to_list(ConnMod),
+ DefLogName = TCStr ++ "-" ++ ConnModStr ++ ".txt",
+ DefLog = filename:join(Dir,DefLogName),
+ Ls = [{Host,
+ filename:join(Dir,TCStr ++ "-"++
+ atom_to_list(Host) ++ "-" ++
+ ConnModStr ++
+ ".txt")}
+ || Host <- Hosts]
+ ++[{default,DefLog}],
+ Str =
+ "<table borders=1>"
+ "<b>" ++ ConnModStr ++ " logs:</b>\n" ++
+ [io_lib:format(
+ "<tr><td>~p</td><td><a href=~p>~s</a></td></tr>",
+ [S,L,filename:basename(L)])
+ || {S,L} <- Ls] ++
+ "</table>",
+ io:format(Str,[]),
+ {ConnMod,{LogType,Ls}};
+ _ ->
+ {ConnMod,{LogType,[]}}
+ end
+ end,
+ CthState),
+ error_logger:add_report_handler(ct_conn_log_h,{group_leader(),Logs}),
+ {Config,CthState}.
+
+post_end_per_testcase(_TestCase,_Config,Return,CthState) ->
+ error_logger:delete_report_handler(ct_conn_log_h),
+ {Return,CthState}.
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
index 14663b7738..77f57c6195 100644
--- a/lib/common_test/src/cth_log_redirect.erl
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The 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,22 +31,22 @@
%% Event handler Callbacks
-export([init/1,
handle_event/2, handle_call/2, handle_info/2,
- terminate/2]).
+ terminate/1]).
id(_Opts) ->
?MODULE.
init(?MODULE, _Opts) ->
error_logger:add_report_handler(?MODULE),
- tc_log.
+ tc_log_async.
-post_init_per_group(Group, Config, Result, tc_log) ->
+post_init_per_group(Group, Config, Result, tc_log_async) ->
case lists:member(parallel,proplists:get_value(
tc_group_properties,Config,[])) of
true ->
{Result, {set_log_func(ct_log),Group}};
false ->
- {Result, tc_log}
+ {Result, tc_log_async}
end;
post_init_per_group(_Group, _Config, Result, State) ->
{Result, State}.
@@ -58,14 +58,14 @@ post_end_per_testcase(_TC, _Config, Result, State) ->
{Result, State}.
pre_end_per_group(Group, Config, {ct_log, Group}) ->
- {Config, set_log_func(tc_log)};
+ {Config, set_log_func(tc_log_async)};
pre_end_per_group(_Group, Config, State) ->
{Config, State}.
%% Copied and modified from sasl_report_tty_h.erl
init(_Type) ->
- {ok, tc_log}.
+ {ok, tc_log_async}.
handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() ->
{ok, State};
@@ -101,7 +101,8 @@ handle_call({set_logfunc,NewLogFunc},_) ->
{ok, NewLogFunc, NewLogFunc};
handle_call(_Query, _State) -> {error, bad_query}.
-terminate(_Reason, _Type) ->
+terminate(_State) ->
+ error_logger:delete_report_handler(?MODULE),
[].
tag_event(Event) ->
diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl
new file mode 100644
index 0000000000..76b0f0b5ea
--- /dev/null
+++ b/lib/common_test/src/cth_surefire.erl
@@ -0,0 +1,219 @@
+%%% @doc Common Test Framework functions handling test specifications.
+%%%
+%%% <p>This module creates a junit report of the test run if plugged in
+%%% as a suite_callback.</p>
+
+-module(cth_surefire).
+
+%% Suite Callbacks
+-export([id/1, init/2]).
+
+-export([pre_init_per_suite/3]).
+-export([post_init_per_suite/4]).
+-export([pre_end_per_suite/3]).
+-export([post_end_per_suite/4]).
+
+-export([pre_init_per_group/3]).
+-export([post_init_per_group/4]).
+-export([pre_end_per_group/3]).
+-export([post_end_per_group/4]).
+
+-export([pre_init_per_testcase/3]).
+-export([post_end_per_testcase/4]).
+
+-export([on_tc_fail/3]).
+-export([on_tc_skip/3]).
+
+-export([terminate/1]).
+
+-record(state, { filepath, axis, properties, package, hostname,
+ curr_suite, curr_suite_ts, curr_group = [], curr_tc,
+ curr_log_dir, timer, tc_log,
+ test_cases = [],
+ test_suites = [] }).
+
+-record(testcase, { log, group, classname, name, time, failure, timestamp }).
+-record(testsuite, { errors, failures, hostname, name, tests,
+ time, timestamp, id, package,
+ properties, testcases }).
+
+id(Opts) ->
+ filename:absname(proplists:get_value(path, Opts, "junit_report.xml")).
+
+init(Path, Opts) ->
+ {ok, Host} = inet:gethostname(),
+ #state{ filepath = Path,
+ hostname = proplists:get_value(hostname,Opts,Host),
+ package = proplists:get_value(package,Opts),
+ axis = proplists:get_value(axis,Opts,[]),
+ properties = proplists:get_value(properties,Opts,[]),
+ timer = now() }.
+
+pre_init_per_suite(Suite,Config,#state{ test_cases = [] } = State) ->
+ {Config, init_tc(State#state{ curr_suite = Suite, curr_suite_ts = now() },
+ Config) };
+pre_init_per_suite(Suite,Config,State) ->
+ %% Have to close the previous suite
+ pre_init_per_suite(Suite,Config,close_suite(State)).
+
+post_init_per_suite(_Suite,Config, Result, State) ->
+ {Result, end_tc(init_per_suite,Config,Result,State)}.
+
+pre_end_per_suite(_Suite,Config,State) -> {Config, init_tc(State, Config)}.
+
+post_end_per_suite(_Suite,Config,Result,State) ->
+ {Result, end_tc(end_per_suite,Config,Result,State)}.
+
+pre_init_per_group(Group,Config,State) ->
+ {Config, init_tc(State#state{ curr_group = [Group|State#state.curr_group]},
+ Config)}.
+
+post_init_per_group(_Group,Config,Result,State) ->
+ {Result, end_tc(init_per_group,Config,Result,State)}.
+
+pre_end_per_group(_Group,Config,State) -> {Config, init_tc(State, Config)}.
+
+post_end_per_group(_Group,Config,Result,State) ->
+ NewState = end_tc(end_per_group, Config, Result, State),
+ {Result, NewState#state{ curr_group = tl(NewState#state.curr_group)}}.
+
+pre_init_per_testcase(_TC,Config,State) -> {Config, init_tc(State, Config)}.
+
+post_end_per_testcase(TC,Config,Result,State) ->
+ {Result, end_tc(TC,Config, Result,State)}.
+
+on_tc_fail(_TC, _Res, State = #state{test_cases = []}) ->
+ State;
+on_tc_fail(_TC, Res, State) ->
+ TCs = State#state.test_cases,
+ TC = hd(TCs),
+ NewTC = TC#testcase{
+ failure =
+ {fail,lists:flatten(io_lib:format("~p",[Res]))} },
+ State#state{ test_cases = [NewTC | tl(TCs)]}.
+
+on_tc_skip(Tc,{Type,_Reason} = Res, State) when Type == tc_auto_skip ->
+ do_tc_skip(Res, end_tc(Tc,[],Res,init_tc(State,[])));
+on_tc_skip(_Tc, _Res, State = #state{test_cases = []}) ->
+ State;
+on_tc_skip(_Tc, Res, State) ->
+ do_tc_skip(Res, State).
+
+do_tc_skip(Res, State) ->
+ TCs = State#state.test_cases,
+ TC = hd(TCs),
+ NewTC = TC#testcase{
+ failure =
+ {skipped,lists:flatten(io_lib:format("~p",[Res]))} },
+ State#state{ test_cases = [NewTC | tl(TCs)]}.
+
+init_tc(State, Config) when is_list(Config) == false ->
+ State#state{ timer = now(), tc_log = "" };
+init_tc(State, Config) ->
+ State#state{ timer = now(),
+ tc_log = proplists:get_value(tc_logfile, Config, [])}.
+
+end_tc(Func, Config, Res, State) when is_atom(Func) ->
+ end_tc(atom_to_list(Func), Config, Res, State);
+end_tc(Name, _Config, _Res, State = #state{ curr_suite = Suite,
+ curr_group = Groups,
+ timer = TS, tc_log = Log } ) ->
+ ClassName = atom_to_list(Suite),
+ PGroup = string:join([ atom_to_list(Group)||
+ Group <- lists:reverse(Groups)],"."),
+ TimeTakes = io_lib:format("~f",[timer:now_diff(now(),TS) / 1000000]),
+ State#state{ test_cases = [#testcase{ log = Log,
+ timestamp = now_to_string(TS),
+ classname = ClassName,
+ group = PGroup,
+ name = Name,
+ time = TimeTakes,
+ failure = passed }| State#state.test_cases]}.
+close_suite(#state{ test_cases = [] } = State) ->
+ State;
+close_suite(#state{ test_cases = TCs } = State) ->
+ Total = length(TCs),
+ Succ = length(lists:filter(fun(#testcase{ failure = F }) ->
+ F == passed
+ end,TCs)),
+ Fail = Total - Succ,
+ TimeTaken = timer:now_diff(now(),State#state.curr_suite_ts) / 1000000,
+ Suite = #testsuite{ name = atom_to_list(State#state.curr_suite),
+ package = State#state.package,
+ time = io_lib:format("~f",[TimeTaken]),
+ timestamp = now_to_string(State#state.curr_suite_ts),
+ errors = Fail, tests = Total,
+ testcases = lists:reverse(TCs) },
+ State#state{ test_cases = [],
+ test_suites = [Suite | State#state.test_suites]}.
+
+terminate(State = #state{ test_cases = [] }) ->
+ {ok,D} = file:open(State#state.filepath,[write,{encoding,utf8}]),
+ io:format(D, "<?xml version=\"1.0\" encoding= \"UTF-8\" ?>", []),
+ io:format(D, to_xml(State), []),
+ catch file:sync(D),
+ catch file:close(D);
+terminate(State) ->
+ %% Have to close the last suite
+ terminate(close_suite(State)).
+
+
+
+to_xml(#testcase{ group = Group, classname = CL, log = L, name = N, time = T, timestamp = TS, failure = F}) ->
+ ["<testcase ",
+ [["group=\"",Group,"\""]||Group /= ""]," "
+ "name=\"",N,"\" "
+ "time=\"",T,"\" "
+ "timestamp=\"",TS,"\" "
+ "log=\"",L,"\">",
+ case F of
+ passed ->
+ [];
+ {skipped,Reason} ->
+ ["<skipped type=\"skip\" message=\"Test ",N," in ",CL,
+ " skipped!\">", sanitize(Reason),"</skipped>"];
+ {fail,Reason} ->
+ ["<failure message=\"Test ",N," in ",CL," failed!\" type=\"crash\">",
+ sanitize(Reason),"</failure>"]
+ end,"</testcase>"];
+to_xml(#testsuite{ package = P, hostname = H, errors = E, time = Time,
+ timestamp = TS, tests = T, name = N, testcases = Cases }) ->
+ ["<testsuite ",
+ [["package=\"",P,"\" "]||P /= undefined],
+ [["hostname=\"",P,"\" "]||H /= undefined],
+ [["name=\"",N,"\" "]||N /= undefined],
+ [["time=\"",Time,"\" "]||Time /= undefined],
+ [["timestamp=\"",TS,"\" "]||TS /= undefined],
+ "errors=\"",integer_to_list(E),"\" "
+ "tests=\"",integer_to_list(T),"\">",
+ [to_xml(Case) || Case <- Cases],
+ "</testsuite>"];
+to_xml(#state{ test_suites = TestSuites, axis = Axis, properties = Props }) ->
+ ["<testsuites>",properties_to_xml(Axis,Props),
+ [to_xml(TestSuite) || TestSuite <- TestSuites],"</testsuites>"].
+
+properties_to_xml(Axis,Props) ->
+ ["<properties>",
+ [["<property name=\"",Name,"\" axis=\"yes\" value=\"",Value,"\" />"] || {Name,Value} <- Axis],
+ [["<property name=\"",Name,"\" value=\"",Value,"\" />"] || {Name,Value} <- Props],
+ "</properties>"
+ ].
+
+sanitize([$>|T]) ->
+ "&gt;" ++ sanitize(T);
+sanitize([$<|T]) ->
+ "&lt;" ++ sanitize(T);
+sanitize([$"|T]) ->
+ "&quot;" ++ sanitize(T);
+sanitize([$'|T]) ->
+ "&apos;" ++ sanitize(T);
+sanitize([$&|T]) ->
+ "&amp;" ++ sanitize(T);
+sanitize([H|T]) ->
+ [H|sanitize(T)];
+sanitize([]) ->
+ [].
+
+now_to_string(Now) ->
+ {{YY,MM,DD},{HH,Mi,SS}} = calendar:now_to_local_time(Now),
+ io_lib:format("~p-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",[YY,MM,DD,HH,Mi,SS]).
diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl
index cc8a932887..b340c6fdd1 100644
--- a/lib/common_test/src/vts.erl
+++ b/lib/common_test/src/vts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -766,10 +766,6 @@ 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) ->
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index b7b099069c..7628ada61a 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2011. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
#
# The 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,19 +29,28 @@ MODULES= \
ct_test_support_eh \
ct_userconfig_callback \
ct_smoke_test_SUITE \
+ ct_priv_dir_SUITE \
ct_event_handler_SUITE \
+ ct_config_info_SUITE \
ct_groups_test_1_SUITE \
ct_groups_test_2_SUITE \
+ ct_group_info_SUITE \
+ ct_groups_spec_SUITE \
ct_sequence_1_SUITE \
ct_repeat_1_SUITE \
ct_testspec_1_SUITE \
+ ct_testspec_2_SUITE \
ct_skip_SUITE \
ct_error_SUITE \
ct_test_server_if_1_SUITE \
ct_config_SUITE \
ct_master_SUITE \
ct_misc_1_SUITE \
- ct_hooks_SUITE
+ ct_hooks_SUITE \
+ ct_netconfc_SUITE \
+ ct_basic_html_SUITE \
+ ct_auto_compile_SUITE \
+ ct_verbosity_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -93,10 +102,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec:
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_DATA) common_test.spec $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
+ $(INSTALL_DATA) common_test.spec "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/common_test/test/common_test.spec b/lib/common_test/test/common_test.spec
index 8755b08117..8bec66d6f2 100644
--- a/lib/common_test/test/common_test.spec
+++ b/lib/common_test/test/common_test.spec
@@ -1 +1 @@
-{suites,"../common_test_test",all}. \ No newline at end of file
+{suites,"../common_test_test",all}.
diff --git a/lib/common_test/test/ct_auto_compile_SUITE.erl b/lib/common_test/test/ct_auto_compile_SUITE.erl
new file mode 100644
index 0000000000..cc546ed30d
--- /dev/null
+++ b/lib/common_test/test/ct_auto_compile_SUITE.erl
@@ -0,0 +1,187 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_auto_compile_SUITE
+%%%
+%%% Description:
+%%%
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_auto_compile_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [ac_flag, ac_spec].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+ac_flag(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ file:copy(filename:join(DataDir, "bad_SUITE.erl"),
+ filename:join(PrivDir, "bad_SUITE.erl")),
+ Suite = filename:join(DataDir, "dummy_SUITE"),
+ compile:file(Suite, [{outdir,PrivDir}]),
+ {Opts,ERPid} = setup([{dir,PrivDir},
+ {auto_compile,false},
+ {label,"ac_flag"}],
+ Config),
+
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(ac_flag,
+ reformat(Events, ?eh),
+ PrivDir,
+ Opts),
+
+ TestEvents = events_to_check(ac_flag),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+ac_spec(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ file:copy(filename:join(DataDir, "bad_SUITE.erl"),
+ filename:join(PrivDir, "bad_SUITE.erl")),
+ TestSpec = [{label,ac_spec},
+ {auto_compile,false},
+ {suites,PrivDir,all}],
+ FileName = filename:join(?config(priv_dir, Config),"ac_spec.spec"),
+ {ok,Dev} = file:open(FileName, [write]),
+ [io:format(Dev, "~p.~n", [Term]) || Term <- TestSpec],
+ file:close(Dev),
+
+ {Opts,ERPid} = setup([{spec,FileName}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(ac_spec,
+ reformat(Events, ?eh),
+ PrivDir,
+ Opts),
+
+ TestEvents = events_to_check(ac_spec),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+ %reformat(Events, _EH) ->
+ % Events.
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(ac_flag) ->
+ [
+ {ct_test_support_eh,start_logging,{'DEF','RUNDIR'}},
+ {ct_test_support_eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {ct_test_support_eh,start_info,{1,1,3}},
+ {ct_test_support_eh,tc_start,{dummy_SUITE,init_per_suite}},
+ {ct_test_support_eh,tc_done,{dummy_SUITE,init_per_suite,ok}},
+ {ct_test_support_eh,test_stats,{1,1,{1,0}}},
+ {ct_test_support_eh,tc_start,{dummy_SUITE,end_per_suite}},
+ {ct_test_support_eh,tc_done,{dummy_SUITE,end_per_suite,ok}},
+ {ct_test_support_eh,test_done,{'DEF','STOP_TIME'}},
+ {ct_test_support_eh,stop_logging,[]}
+ ];
+
+test_events(ac_spec) ->
+ [
+ {ct_test_support_eh,start_logging,{'DEF','RUNDIR'}},
+ {ct_test_support_eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {ct_test_support_eh,start_info,{1,1,3}},
+ {ct_test_support_eh,tc_start,{dummy_SUITE,init_per_suite}},
+ {ct_test_support_eh,tc_done,{dummy_SUITE,init_per_suite,ok}},
+ {ct_test_support_eh,test_stats,{1,1,{1,0}}},
+ {ct_test_support_eh,tc_start,{dummy_SUITE,end_per_suite}},
+ {ct_test_support_eh,tc_done,{dummy_SUITE,end_per_suite,ok}},
+ {ct_test_support_eh,test_done,{'DEF','STOP_TIME'}},
+ {ct_test_support_eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_auto_compile_SUITE_data/bad_SUITE.erl b/lib/common_test/test/ct_auto_compile_SUITE_data/bad_SUITE.erl
new file mode 100644
index 0000000000..6ebcb3570e
--- /dev/null
+++ b/lib/common_test/test/ct_auto_compile_SUITE_data/bad_SUITE.erl
@@ -0,0 +1,23 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+-module(bad_SUITE).
+
+-compile(export_all).
+
+bad_bad_suite
diff --git a/lib/common_test/test/ct_auto_compile_SUITE_data/dummy_SUITE.erl b/lib/common_test/test/ct_auto_compile_SUITE_data/dummy_SUITE.erl
new file mode 100644
index 0000000000..0b1eafc31d
--- /dev/null
+++ b/lib/common_test/test/ct_auto_compile_SUITE_data/dummy_SUITE.erl
@@ -0,0 +1,130 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+-module(dummy_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [ok,fail,skip].
+
+
+ok(_Config) ->
+ ok.
+
+fail(Config) ->
+ tuple_to_list(Config),
+ ok.
+
+skip(_Config) ->
+ {skip,"should be skipped"}.
diff --git a/lib/common_test/test/ct_basic_html_SUITE.erl b/lib/common_test/test/ct_basic_html_SUITE.erl
new file mode 100644
index 0000000000..a5f2e6197e
--- /dev/null
+++ b/lib/common_test/test/ct_basic_html_SUITE.erl
@@ -0,0 +1,180 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_basic_html_SUITE
+%%%
+%%% Description:
+%%%
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_basic_html_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [basic_flag, basic_spec].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+basic_flag(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suites = [filename:join(DataDir, "babbling_SUITE")],
+ {Opts,ERPid} = setup([{suite,Suites},
+ {basic_html,true},
+ {label,"basic_flag"}],
+ Config),
+
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(basic_flag,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(basic_flag),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+basic_spec(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ TestSpec = [{label,basic_spec},
+ {basic_html,true},
+ {suites,DataDir,babbling_SUITE}],
+ FileName = filename:join(?config(priv_dir, Config),"basic_spec.spec"),
+ {ok,Dev} = file:open(FileName, [write]),
+ [io:format(Dev, "~p.~n", [Term]) || Term <- TestSpec],
+ file:close(Dev),
+
+ {Opts,ERPid} = setup([{spec,FileName}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(basic_spec,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(basic_spec),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+ %reformat(Events, _EH) ->
+ % Events.
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(basic_flag) ->
+ [
+ {ct_test_support_eh,start_logging,{'DEF','RUNDIR'}},
+ {ct_test_support_eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {ct_test_support_eh,start_info,{1,1,3}},
+ {ct_test_support_eh,tc_start,{babbling_SUITE,init_per_suite}},
+ {ct_test_support_eh,tc_done,{babbling_SUITE,init_per_suite,ok}},
+ {ct_test_support_eh,test_stats,{1,1,{1,0}}},
+ {ct_test_support_eh,tc_start,{babbling_SUITE,end_per_suite}},
+ {ct_test_support_eh,tc_done,{babbling_SUITE,end_per_suite,ok}},
+ {ct_test_support_eh,test_done,{'DEF','STOP_TIME'}},
+ {ct_test_support_eh,stop_logging,[]}
+ ];
+
+test_events(basic_spec) ->
+ [
+ {ct_test_support_eh,start_logging,{'DEF','RUNDIR'}},
+ {ct_test_support_eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {ct_test_support_eh,start_info,{1,1,3}},
+ {ct_test_support_eh,tc_start,{babbling_SUITE,init_per_suite}},
+ {ct_test_support_eh,tc_done,{babbling_SUITE,init_per_suite,ok}},
+ {ct_test_support_eh,test_stats,{1,1,{1,0}}},
+ {ct_test_support_eh,tc_start,{babbling_SUITE,end_per_suite}},
+ {ct_test_support_eh,tc_done,{babbling_SUITE,end_per_suite,ok}},
+ {ct_test_support_eh,test_done,{'DEF','STOP_TIME'}},
+ {ct_test_support_eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_basic_html_SUITE_data/babbling_SUITE.erl b/lib/common_test/test/ct_basic_html_SUITE_data/babbling_SUITE.erl
new file mode 100644
index 0000000000..d67383c606
--- /dev/null
+++ b/lib/common_test/test/ct_basic_html_SUITE_data/babbling_SUITE.erl
@@ -0,0 +1,130 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+-module(babbling_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [ok,fail,skip].
+
+
+ok(_Config) ->
+ ok.
+
+fail(Config) ->
+ tuple_to_list(Config),
+ ok.
+
+skip(_Config) ->
+ {skip,"should be skipped"}.
diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl
index 8ce75f582a..83b8c00458 100644
--- a/lib/common_test/test/ct_config_SUITE.erl
+++ b/lib/common_test/test/ct_config_SUITE.erl
@@ -88,7 +88,8 @@ require(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
run_test(config_static_SUITE,
Config,
- {config, filename:join(DataDir, "config/config.txt")},
+ [{config, filename:join(DataDir, "config/shadow.txt")},
+ {config, filename:join(DataDir, "config/config.txt")}],
["config_static_SUITE"]).
install_config(Config) when is_list(Config) ->
@@ -106,7 +107,8 @@ userconfig_static(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
run_test(config_static_SUITE,
Config,
- {userconfig, {ct_config_xml, filename:join(DataDir, "config/config.xml")}},
+ [{userconfig, {ct_config_xml, filename:join(DataDir, "config/config.xml")}},
+ {config, filename:join(DataDir, "config/shadow.txt")}],
["config_static_SUITE"]).
userconfig_dynamic(Config) when is_list(Config) ->
@@ -121,7 +123,8 @@ testspec_legacy(Config) when is_list(Config) ->
make_spec(DataDir, ConfigDir,
"spec_legacy.spec",
[config_static_SUITE],
- [{config, filename:join(DataDir, "config/config.txt")}]),
+ [{config, filename:join(DataDir, "config/shadow.txt")},
+ {config, filename:join(DataDir, "config/config.txt")}]),
run_test(config_static_SUITE,
Config,
{spec, filename:join(ConfigDir, "spec_legacy.spec")},
@@ -134,7 +137,8 @@ testspec_static(Config) when is_list(Config) ->
make_spec(DataDir, ConfigDir,
"spec_static.spec",
[config_static_SUITE],
- [{userconfig, {ct_config_xml, filename:join(DataDir, "config/config.xml")}}]),
+ [{userconfig, {ct_config_xml, filename:join(DataDir, "config/config.xml")}},
+ {config, filename:join(DataDir, "config/shadow.txt")}]),
run_test(config_static_SUITE,
Config,
{spec, filename:join(ConfigDir, "spec_static.spec")},
@@ -179,13 +183,15 @@ run_test(Name, Config, CTConfig, SuiteNames)->
ExpEvents = events_to_check(Name),
ok = ct_test_support:verify_events(ExpEvents, TestEvents, Config).
-setup_env(Test, Config, CTConfig) ->
+setup_env(Test, Config, CTConfig) when is_list(CTConfig) ->
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}}, CTConfig],
+ Opts = Opts0 ++ [Test,{event_handler,{?eh,EvHArgs}} | CTConfig],
ERPid = ct_test_support:start_event_receiver(Config),
- {Opts,ERPid}.
+ {Opts,ERPid};
+setup_env(Test, Config, CTConfig) ->
+ setup_env(Test, Config, [CTConfig]).
reformat_events(Events, EH) ->
ct_test_support:reformat(Events, EH).
@@ -202,40 +208,49 @@ events_to_check(_, 0) ->
events_to_check(Test, N) ->
expected_events(Test) ++ events_to_check(Test, N-1).
+-define(ok(Name,Suite,Stat),{?eh,tc_start,{Suite,Name}},
+ {?eh,tc_done,{Suite,Name,ok}},
+ {?eh,test_stats,Stat}).
+-define(nok(Name,Suite,Reason,Stat),{?eh,tc_start,{Suite,Name}},
+ {?eh,tc_done,{Suite,Name,Reason}},
+ {?eh,test_stats,Stat}).
+
+-define(sok(Name,Stat),?ok(Name,config_static_SUITE,Stat)).
+-define(snok(Name,Reason,Stat),?nok(Name,config_static_SUITE,Reason,Stat)).
+
+-define(dok(Name,Stat),?ok(Name,config_dynamic_SUITE,Stat)).
+-define(dnok(Name,Reason,Stat),?nok(Name,config_dynamic_SUITE,Reason,Stat)).
+
expected_events(config_static_SUITE)->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,8}},
+ {?eh,start_info,{1,1,'_'}},
{?eh,tc_start,{config_static_SUITE,init_per_suite}},
{?eh,tc_done,{config_static_SUITE,init_per_suite,ok}},
- {?eh,tc_start,{config_static_SUITE,test_get_config_simple}},
- {?eh,tc_done,{config_static_SUITE,test_get_config_simple,ok}},
- {?eh,test_stats,{1,0,{0,0}}},
- {?eh,tc_start,{config_static_SUITE,test_get_config_nested}},
- {?eh,tc_done,{config_static_SUITE,test_get_config_nested,ok}},
- {?eh,test_stats,{2,0,{0,0}}},
- {?eh,tc_start,{config_static_SUITE,test_default_suitewide}},
- {?eh,tc_done,{config_static_SUITE,test_default_suitewide,ok}},
- {?eh,test_stats,{3,0,{0,0}}},
- {?eh,tc_start,{config_static_SUITE,test_config_name_already_in_use1}},
- {?eh,tc_done,
- {config_static_SUITE,test_config_name_already_in_use1,{skipped,{config_name_already_in_use,[x1]}}}},
- {?eh,test_stats,{3,0,{1,0}}},
- {?eh,tc_start,{config_static_SUITE,test_default_tclocal}},
- {?eh,tc_done,{config_static_SUITE,test_default_tclocal,ok}},
- {?eh,test_stats,{4,0,{1,0}}},
- {?eh,tc_start,{config_static_SUITE,test_config_name_already_in_use2}},
- {?eh,tc_done,
- {config_static_SUITE,test_config_name_already_in_use2,
- {skipped,{config_name_already_in_use,[x1,alias]}}}},
- {?eh,test_stats,{4,0,{2,0}}},
- {?eh,tc_start,{config_static_SUITE,test_alias_tclocal}},
- {?eh,tc_done,{config_static_SUITE,test_alias_tclocal,ok}},
- {?eh,test_stats,{5,0,{2,0}}},
- {?eh,tc_start,{config_static_SUITE,test_get_config_undefined}},
- {?eh,tc_done,{config_static_SUITE,test_get_config_undefined,ok}},
- {?eh,test_stats,{6,0,{2,0}}},
+ ?sok(test_get_config_simple,{1,0,{0,0}}),
+ ?sok(test_get_config_nested,{2,0,{0,0}}),
+ ?sok(test_get_config_deep_nested,{3,0,{0,0}}),
+ ?sok(test_default_suitewide,{4,0,{0,0}}),
+ ?snok(test_config_name_already_in_use1,
+ {skipped,{config_name_already_in_use,[x1]}},{4,0,{1,0}}),
+ ?sok(test_default_tclocal,{5,0,{1,0}}),
+ ?snok(test_config_name_already_in_use2,
+ {skipped,{config_name_already_in_use,[alias,x1]}},{5,0,{2,0}}),
+ ?sok(test_alias_tclocal,{6,0,{2,0}}),
+ ?sok(test_get_config_undefined,{7,0,{2,0}}),
+ ?sok(test_require_subvals,{8,0,{2,0}}),
+ ?snok(test_require_subvals2,
+ {skipped,{require_failed,
+ {not_available,{gen_cfg,[a,b,c,d]}}}},{8,0,{2,1}}),
+ ?sok(test_require_deep_config,{9,0,{2,1}}),
+ ?sok(test_shadow_all,{10,0,{2,1}}),
+ ?sok(test_element,{11,0,{2,1}}),
+ ?sok(test_shadow_all_element,{12,0,{2,1}}),
+ ?sok(test_internal_deep,{13,0,{2,1}}),
+ ?sok(test_alias_tclocal_nested,{14,0,{2,1}}),
+ ?sok(test_alias_tclocal_nested_backward_compat,{15,0,{2,1}}),
+ ?sok(test_alias_tclocal_nested_backward_compat_subvals,{16,0,{2,1}}),
{?eh,tc_start,{config_static_SUITE,end_per_suite}},
{?eh,tc_done,{config_static_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
@@ -246,29 +261,14 @@ expected_events(config_dynamic_SUITE)->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,5}},
+ {?eh,start_info,{1,1,'_'}},
{?eh,tc_start,{config_dynamic_SUITE,init_per_suite}},
{?eh,tc_done,{config_dynamic_SUITE,init_per_suite,ok}},
- {?eh,tc_start,{config_dynamic_SUITE,test_get_known_variable}},
- {?eh,tc_done,
- {config_dynamic_SUITE,test_get_known_variable,ok}},
- {?eh,test_stats,{1,0,{0,0}}},
- {?eh,tc_start,{config_dynamic_SUITE,test_localtime_update}},
- {?eh,tc_done,{config_dynamic_SUITE,test_localtime_update,ok}},
- {?eh,test_stats,{2,0,{0,0}}},
- {?eh,tc_start,{config_dynamic_SUITE,test_server_pid}},
- {?eh,tc_done,{config_dynamic_SUITE,test_server_pid,ok}},
- {?eh,test_stats,{3,0,{0,0}}},
- {?eh,tc_start,
- {config_dynamic_SUITE,test_disappearable_variable}},
- {?eh,tc_done,
- {config_dynamic_SUITE,test_disappearable_variable,ok}},
- {?eh,test_stats,{4,0,{0,0}}},
- {?eh,tc_start,
- {config_dynamic_SUITE,test_disappearable_variable_alias}},
- {?eh,tc_done,
- {config_dynamic_SUITE,test_disappearable_variable_alias,ok}},
- {?eh,test_stats,{5,0,{0,0}}},
+ ?dok(test_get_known_variable,{1,0,{0,0}}),
+ ?dok(test_localtime_update,{2,0,{0,0}}),
+ ?dok(test_server_pid,{3,0,{0,0}}),
+ ?dok(test_disappearable_variable,{4,0,{0,0}}),
+ ?dok(test_disappearable_variable_alias,{5,0,{0,0}}),
{?eh,tc_start,{config_dynamic_SUITE,end_per_suite}},
{?eh,tc_done,{config_dynamic_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
diff --git a/lib/common_test/test/ct_config_SUITE_data/config/config.txt b/lib/common_test/test/ct_config_SUITE_data/config/config.txt
index fcbffcd7f3..e4bcc5ba6b 100644
--- a/lib/common_test/test/ct_config_SUITE_data/config/config.txt
+++ b/lib/common_test/test/ct_config_SUITE_data/config/config.txt
@@ -2,7 +2,8 @@
{gen_cfg,
[
{a,a_value},
- {b,b_value}
+ {b,b_value},
+ {c,[{d,d_value}]}
]}.
{gen_cfg2,
[
diff --git a/lib/common_test/test/ct_config_SUITE_data/config/config.xml b/lib/common_test/test/ct_config_SUITE_data/config/config.xml
index 0a3e5f2e31..8eeff1482f 100644
--- a/lib/common_test/test/ct_config_SUITE_data/config/config.xml
+++ b/lib/common_test/test/ct_config_SUITE_data/config/config.xml
@@ -3,6 +3,7 @@
<gen_cfg>
<a>a_value</a>
<b>b_value</b>
+ <c><d>d_value</d></c>
</gen_cfg>
<gen_cfg2>
<c>"Hello, world!"</c>
diff --git a/lib/common_test/test/ct_config_SUITE_data/config/shadow.txt b/lib/common_test/test/ct_config_SUITE_data/config/shadow.txt
new file mode 100644
index 0000000000..865bf9255a
--- /dev/null
+++ b/lib/common_test/test/ct_config_SUITE_data/config/shadow.txt
@@ -0,0 +1,12 @@
+{x, suite}.
+{gen_cfg3,
+ [
+ {l,
+ [
+ {m,
+ [
+ {n, "n"},
+ {o, 'o'}
+ ]}
+ ]}
+ ]}.
diff --git a/lib/common_test/test/ct_config_SUITE_data/config/test/config_static_SUITE.erl b/lib/common_test/test/ct_config_SUITE_data/config/test/config_static_SUITE.erl
index 8751a2e8f3..d7119d7fde 100644
--- a/lib/common_test/test/ct_config_SUITE_data/config/test/config_static_SUITE.erl
+++ b/lib/common_test/test/ct_config_SUITE_data/config/test/config_static_SUITE.erl
@@ -46,7 +46,7 @@ suite() ->
{require, gen_cfg3},
{require, alias, gen_cfg},
%% x1 default value
- {x1, {x,suite}}
+ {default_config, x1, {x,suite}}
].
init_per_suite(Config) ->
@@ -55,14 +55,24 @@ init_per_suite(Config) ->
end_per_suite(_) ->
ok.
-all() -> [test_get_config_simple, test_get_config_nested, test_default_suitewide,
+all() -> [test_get_config_simple, test_get_config_nested,
+ test_get_config_deep_nested, test_default_suitewide,
test_config_name_already_in_use1, test_default_tclocal,
test_config_name_already_in_use2, test_alias_tclocal,
- test_get_config_undefined].
-
-init_per_testcase(_, Config) ->
+ test_get_config_undefined,
+ test_require_subvals,test_require_subvals2,test_require_deep_config,
+ test_shadow_all,test_element,test_shadow_all_element,
+ test_internal_deep, test_alias_tclocal_nested,
+ test_alias_tclocal_nested_backward_compat,
+ test_alias_tclocal_nested_backward_compat_subvals
+].
+
+init_per_testcase(_,Config) ->
Config.
+end_per_testcase(test_alias_tclocal_nested_backward_compat, _) ->
+ os:putenv("COMMON_TEST_ALIAS_TOP",""),
+ ok;
end_per_testcase(_, _) ->
ok.
@@ -76,6 +86,11 @@ test_get_config_nested(_)->
a_value = ct:get_config({gen_cfg, a}),
ok.
+%% test getting a deep nested value
+test_get_config_deep_nested(_)->
+ d_value = ct:get_config({gen_cfg, c, d}),
+ ok.
+
%% test suite-wide default value
test_default_suitewide(_)->
suite = ct:get_config(x1),
@@ -112,12 +127,73 @@ test_config_name_already_in_use2(_) ->
%% test aliases
test_alias_tclocal() ->
[{require,newalias,gen_cfg}].
-test_alias_tclocal(_) ->
- A = [{a,a_value},{b,b_value}] = ct:get_config(newalias),
+test_alias_tclocal(C) when is_list(C) ->
+ test_alias_tclocal(newalias);
+test_alias_tclocal(Alias) when is_atom(Alias) ->
+ A = [{a,a_value},{b,b_value},{c,[{d,d_value}]}] = ct:get_config(Alias),
A = ct:get_config(gen_cfg),
+ B = b_value = ct:get_config({Alias,b}),
+ B = ct:get_config({gen_cfg,b}),
+ ok.
+
+%% test nested aliases
+test_alias_tclocal_nested() ->
+ [{require,newalias2,{gen_cfg,c}}].
+test_alias_tclocal_nested(_) ->
+ A = [{d,d_value}] = ct:get_config(newalias2),
+ A = ct:get_config({gen_cfg,c}),
+ B = d_value = ct:get_config({newalias2,d}),
+ B = ct:get_config({gen_cfg,c,d}),
ok.
+%% test nested aliases backward compat option
+test_alias_tclocal_nested_backward_compat() ->
+ os:putenv("COMMON_TEST_ALIAS_TOP","true"),
+ [{require,newalias3,{gen_cfg,c}}].
+test_alias_tclocal_nested_backward_compat(_) ->
+ test_alias_tclocal(newalias3).
+
+%% test nested aliases backward compat option
+test_alias_tclocal_nested_backward_compat_subvals() ->
+ [{require,newalias4,{gen_cfg,[c]}}].
+test_alias_tclocal_nested_backward_compat_subvals(_) ->
+ test_alias_tclocal(newalias4).
+
%% test for getting undefined variables
test_get_config_undefined(_) ->
undefined = ct:get_config(y1),
ok.
+
+test_require_subvals() ->
+ [{require, {gen_cfg,[a,b,c]}}].
+test_require_subvals(_) ->
+ ok.
+
+test_require_subvals2() ->
+ [{require, {gen_cfg,[a,b,c,d]}}].
+test_require_subvals2(_) ->
+ ct:fail("Test should've been skipped, you shouldn't see this!"),
+ ok.
+
+test_require_deep_config() ->
+ [{require, {gen_cfg3, m, n}}].
+test_require_deep_config(_) ->
+ ok.
+
+
+test_shadow_all(_) ->
+ ["n","N"] = ct:get_config({gen_cfg3,l, m, n}, [], [all]).
+
+test_element(_) ->
+ {{gen_cfg3,l, m, n},"n"} = ct:get_config({gen_cfg3,l, m, n}, [], [element]).
+
+test_shadow_all_element(_) ->
+ [{{gen_cfg3,l, m, n},"n"},{{gen_cfg3,l, m, n},"N"}] =
+ ct:get_config({gen_cfg3,l, m, n}, [], [all,element]).
+
+%% The tests below are needed to verify that things like ct:telnet can use
+%% nested configs
+test_internal_deep(_) ->
+ "n" = ct:get_config({{gen_cfg3,l,m},n}),
+ a_value = ct:get_config({{gen_cfg},a}),
+ undefined = ct:get_config({{gen_cfg3,l,m},p}).
diff --git a/lib/common_test/test/ct_config_info_SUITE.erl b/lib/common_test/test/ct_config_info_SUITE.erl
new file mode 100644
index 0000000000..40da377ee5
--- /dev/null
+++ b/lib/common_test/test/ct_config_info_SUITE.erl
@@ -0,0 +1,178 @@
+%%
+%% %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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_config_info_SUITE
+%%%
+%%% Description: Test how Common Test handles info functions
+%%% for the config functions.
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_config_info_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ config_info
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+config_info(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "config_info_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {label,config_info}], Config),
+ ok = execute(config_info, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+
+test_events(config_info) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,6}},
+ {?eh,tc_done,{config_info_1_SUITE,init_per_suite,ok}},
+
+ [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,
+ {init_per_group,unknown,[]},
+ {failed,{timetrap_timeout,350}}}},
+ {?eh,tc_auto_skip,{config_info_1_SUITE,t11,
+ {failed,{config_info_1_SUITE,init_per_group,{timetrap_timeout,350}}}}},
+ {?eh,tc_auto_skip,{config_info_1_SUITE,end_per_group,
+ {failed,{config_info_1_SUITE,init_per_group,
+ {timetrap_timeout,350}}}}}],
+
+ [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{config_info_1_SUITE,t21,ok}},
+ {?eh,tc_start,{config_info_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,
+ {end_per_group,unknown,[]},
+ {failed,{timetrap_timeout,450}}}}],
+ [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,{init_per_group,g3,[]},ok}},
+ [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,
+ {init_per_group,unknown,[]},
+ {failed,{timetrap_timeout,400}}}},
+ {?eh,tc_auto_skip,{config_info_1_SUITE,t41,
+ {failed,{config_info_1_SUITE,init_per_group,
+ {timetrap_timeout,400}}}}},
+ {?eh,tc_auto_skip,{config_info_1_SUITE,end_per_group,
+ {failed,{config_info_1_SUITE,init_per_group,
+ {timetrap_timeout,400}}}}}],
+ {?eh,tc_start,{config_info_1_SUITE,t31}},
+ {?eh,tc_done,{config_info_1_SUITE,t31,
+ {skipped,{failed,{config_info_1_SUITE,init_per_testcase,
+ {timetrap_timeout,250}}}}}},
+ {?eh,tc_start,{config_info_1_SUITE,t32}},
+ {?eh,tc_done,{config_info_1_SUITE,t32,
+ {failed,{config_info_1_SUITE,end_per_testcase,
+ {timetrap_timeout,250}}}}},
+
+ [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_done,{config_info_1_SUITE,t51,ok}},
+ {?eh,tc_start,{config_info_1_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,
+ {end_per_group,unknown,[]},
+ {failed,{timetrap_timeout,400}}}}],
+ {?eh,tc_start,{config_info_1_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{config_info_1_SUITE,{end_per_group,g3,[]},ok}}],
+
+ {?eh,tc_start,{config_info_1_SUITE,end_per_suite}},
+ {?eh,tc_done,{config_info_1_SUITE,end_per_suite,
+ {failed,{timetrap_timeout,300}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl b/lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl
new file mode 100644
index 0000000000..53a233b7a4
--- /dev/null
+++ b/lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl
@@ -0,0 +1,168 @@
+%%
+%% %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(config_info_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%%-----------------------------------------------------------------
+
+suite() ->
+ [{timetrap,500}].
+
+%%%-----------------------------------------------------------------
+
+group(_) ->
+ [{timetrap,250}].
+
+%%%-----------------------------------------------------------------
+
+init_per_suite() ->
+ ct:pal("init_per_suite info called", []),
+ [{timetrap,1000},
+ {require,suite_data},
+ {default_config,suite_data,suite_data_val}].
+
+init_per_suite(Config) ->
+ suite_data_val = ct:get_config(suite_data),
+ ct:sleep(750),
+ Config.
+
+%%%-----------------------------------------------------------------
+
+end_per_suite() ->
+ ct:pal("end_per_suite info called", []),
+ [{timetrap,300},
+ {require,suite_data2},
+ {default_config,suite_data2,suite_data2_val}].
+
+end_per_suite(_Config) ->
+ suite_data2_val = ct:get_config(suite_data2),
+ ct:sleep(500),
+ ok.
+
+%%%-----------------------------------------------------------------
+
+init_per_group(g1) ->
+ ct:pal("init_per_group(g1) info called", []),
+ [{timetrap,350}];
+init_per_group(G) ->
+ ct:pal("init_per_group(~w) info called", [G]),
+ [{timetrap,400}].
+
+init_per_group(g1, _Config) ->
+ ct:sleep(1000);
+init_per_group(g4, _Config) ->
+ ct:sleep(1000);
+init_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = proplists:delete(name, GrProps),
+ ct:comment(io_lib:format("init( ~w ): ~p", [G, GrProps1])),
+ ct:pal("init( ~w ): ~p", [G, GrProps1]),
+ Config.
+
+%%%-----------------------------------------------------------------
+
+end_per_group(g2) ->
+ ct:pal("end_per_group(g2) info called", []),
+ [{timetrap,450}];
+end_per_group(G) ->
+ ct:pal("end_per_group(~w) info called", [G]),
+ [{timetrap,400}].
+
+end_per_group(g2, _Config) ->
+ ct:sleep(1000);
+end_per_group(g5, _Config) ->
+ ct:sleep(1000);
+end_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = proplists:delete(name, GrProps),
+ ct:comment(io_lib:format("end( ~w ): ~p", [G, GrProps1])),
+ ct:pal("end( ~w ): ~p", [G, GrProps1]),
+ ok.
+
+%%%-----------------------------------------------------------------
+init_per_testcase() ->
+ [{timetrap,750}].
+
+init_per_testcase(t1, _Config) ->
+ ct:sleep(1000);
+init_per_testcase(t31, _Config) ->
+ ct:sleep(1000);
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%%-----------------------------------------------------------------
+
+end_per_testcase() ->
+ [{timetrap,600}].
+
+end_per_testcase(t2, _Config) ->
+ ct:sleep(1000);
+end_per_testcase(t32, _Config) ->
+ ct:sleep(1000);
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% TEST DECLARATIONS
+%%--------------------------------------------------------------------
+
+groups() ->
+ [
+ {g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[{g4,[],[t41]}, t31, t32, {g5,[],[t51]}]}
+ ].
+
+all() ->
+ [
+ {group,g1},
+ {group,g2},
+ {group,g3}
+ ].
+
+%%-----------------------------------------------------------------
+%% TEST CASES
+%%-----------------------------------------------------------------
+
+t1(_) ->
+ exit(should_not_execute).
+
+t2(_) ->
+ ok.
+
+t11(_) ->
+ exit(should_not_execute).
+
+t21(_) ->
+ ok.
+
+t31(_) ->
+ exit(should_not_execute).
+
+t32(_) ->
+ ok.
+
+t41(_) ->
+ exit(should_not_execute).
+
+t51(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index c1a455c6d8..338e76264e 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -61,7 +61,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[cfg_error, lib_error, no_compile, timetrap_end_conf,
timetrap_normal, timetrap_extended, timetrap_parallel,
- timetrap_fun].
+ timetrap_fun, misc_errors].
groups() ->
[].
@@ -249,6 +249,24 @@ timetrap_fun(Config) when is_list(Config) ->
TestEvents = events_to_check(timetrap_fun),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
+%%%-----------------------------------------------------------------
+%%%
+misc_errors(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suites = [Join(DataDir, "misc_error_1_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(misc_errors,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(misc_errors),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
@@ -493,7 +511,7 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_9_SUITE,tc1}},
{?eh,tc_done,{cfg_error_9_SUITE,tc1,
{skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,
- tc1_should_be_skipped}}}}},
+ {tc1_should_be_skipped,'_'}}}}}},
{?eh,test_stats,{9,0,{0,15}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc2}},
{?eh,tc_done,{cfg_error_9_SUITE,tc2,
@@ -535,12 +553,7 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_9_SUITE,tc13}},
{?eh,tc_done,{cfg_error_9_SUITE,tc13,
{failed,{cfg_error_9_SUITE,end_per_testcase,
- {'EXIT',{{badmatch,undefined},
- [{cfg_error_9_SUITE,end_per_testcase,2},
- {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,9}]}}}}}},
+ {'EXIT',{{badmatch,undefined},'_'}}}}}},
{?eh,test_stats,{12,3,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc14}},
{?eh,tc_done,
@@ -568,8 +581,8 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_11_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_11_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_11_SUITE,tc1}},
- {?eh,tc_done,{cfg_error_11_SUITE,tc1,
- {skipped,{config_name_already_in_use,[dummy0]}}}},
+ {?eh,tc_done, {cfg_error_11_SUITE,tc1,
+ {skipped,{config_name_already_in_use,[dummy_alias]}}}},
{?eh,test_stats,{12,6,{1,19}}},
{?eh,tc_start,{cfg_error_11_SUITE,tc2}},
{?eh,tc_done,{cfg_error_11_SUITE,tc2,ok}},
@@ -577,7 +590,7 @@ test_events(cfg_error) ->
{?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,tc_done,{ct_framework,init_tc,{framework_error,{timetrap,500}}}},
{?eh,test_stats,{13,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc2}},
{?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed,
@@ -687,7 +700,7 @@ test_events(timetrap_end_conf) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,6}},
+ {?eh,start_info,{1,1,9}},
{?eh,tc_start,{timetrap_1_SUITE,init_per_suite}},
{?eh,tc_done,{timetrap_1_SUITE,init_per_suite,ok}},
{?eh,tc_start,{timetrap_1_SUITE,tc1}},
@@ -714,6 +727,18 @@ test_events(timetrap_end_conf) ->
{?eh,tc_done,
{timetrap_1_SUITE,tc6,{failed,{testcase_aborted,testing_end_conf}}}},
{?eh,test_stats,{0,6,{0,0}}},
+ {?eh,tc_start,{timetrap_1_SUITE,tc7}},
+ {?eh,tc_done,
+ {timetrap_1_SUITE,tc7,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,7,{0,0}}},
+ {?eh,tc_start,{timetrap_1_SUITE,tc8}},
+ {?eh,tc_done,
+ {timetrap_1_SUITE,tc8,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,8,{0,0}}},
+ {?eh,tc_start,{timetrap_1_SUITE,tc9}},
+ {?eh,tc_done,
+ {timetrap_1_SUITE,tc9,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,9,{0,0}}},
{?eh,tc_start,{timetrap_1_SUITE,end_per_suite}},
{?eh,tc_done,{timetrap_1_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
@@ -823,78 +848,161 @@ test_events(timetrap_parallel) ->
test_events(timetrap_fun) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,start_info,{4,4,17}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,24}},
+ {?eh,tc_start,{timetrap_4_SUITE,init_per_suite}},
{?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_done,{timetrap_4_SUITE,tc0,
+ {failed,{timetrap_timeout,{'$approx',1000}}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
{?eh,tc_start,{timetrap_4_SUITE,tc1}},
- {?eh,tc_done,
- {timetrap_4_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_done,{timetrap_4_SUITE,tc1,
+ {failed,{timetrap_timeout,{'$approx',2000}}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
{?eh,tc_start,{timetrap_4_SUITE,tc2}},
- {?eh,tc_done,
- {timetrap_4_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_done,{timetrap_4_SUITE,tc2,
+ {failed,{timetrap_timeout,{'$approx',500}}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
{?eh,tc_start,{timetrap_4_SUITE,tc3}},
- {?eh,tc_done,
- {timetrap_4_SUITE,tc3,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_done,{timetrap_4_SUITE,tc3,
+ {failed,{timetrap_timeout,{'$approx',1000}}}}},
{?eh,test_stats,{0,4,{0,0}}},
+ {?eh,tc_start,{timetrap_4_SUITE,end_per_suite}},
{?eh,tc_done,{timetrap_4_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{timetrap_5_SUITE,init_per_suite}},
{?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,tc_done,{timetrap_5_SUITE,tc0,
+ {failed,{timetrap_timeout,{'$approx',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_done,{timetrap_5_SUITE,tc1,{user_timetrap_error,
+ {kaboom,'_'}}}},
+ {?eh,test_stats,{0,6,{0,0}}},
{?eh,tc_start,{timetrap_5_SUITE,tc2}},
- {?eh,tc_done,
- {timetrap_5_SUITE,tc2,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc2,{user_timetrap_error,
+ {kaboom,'_'}}}},
+ {?eh,test_stats,{0,7,{0,0}}},
{?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_done,{timetrap_5_SUITE,tc3,
+ {failed,{timetrap_timeout,{'$approx',2000}}}}},
+ {?eh,test_stats,{0,8,{0,0}}},
{?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_done,{timetrap_5_SUITE,tc4,
+ {failed,{timetrap_timeout,{'$approx',500}}}}},
+ {?eh,test_stats,{0,9,{0,0}}},
{?eh,tc_start,{timetrap_5_SUITE,tc5}},
- {?eh,tc_done,
- {timetrap_5_SUITE,tc5,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc5,
+ {failed,{timetrap_timeout,{'$approx',1000}}}}},
+ {?eh,test_stats,{0,10,{0,0}}},
{?eh,tc_start,{timetrap_5_SUITE,tc6}},
- {?eh,tc_done,
- {timetrap_5_SUITE,tc6,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc6,
+ {failed,{timetrap_timeout,{'$approx',41000}}}}},
+ {?eh,test_stats,{0,11,{0,0}}},
{?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,tc7,
+ {failed,{timetrap_timeout,{'$approx',3000}}}}},
+ {?eh,test_stats,{0,12,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc8}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc8,
+ {failed,{timetrap_timeout,{'$approx',7000}}}}},
+ {?eh,test_stats,{0,13,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc9}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc9,
+ {failed,{timetrap_timeout,{'$approx',2000}}}}},
+ {?eh,test_stats,{0,14,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc10}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc10,
+ {failed,{timetrap_timeout,{'$approx',1500}}}}},
+ {?eh,test_stats,{0,15,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc11}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc11,
+ {failed,{timetrap_timeout,{'$approx',1500}}}}},
+ {?eh,test_stats,{0,16,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc12}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc12,
+ {failed,{timetrap_timeout,{'$approx',1000}}}}},
+ {?eh,test_stats,{0,17,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc13}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc13,
+ {failed,{timetrap_timeout,{'$approx',500}}}}},
+ {?eh,test_stats,{0,18,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc14}},
+ {?eh,tc_done,{timetrap_5_SUITE,tc14,
+ {failed,{timetrap_timeout,{'$approx',1000}}}}},
+ {?eh,test_stats,{0,19,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,end_per_suite}},
{?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_6_SUITE,init_per_suite,{user_timetrap_error,
+ {kaboom,'_'}}}},
+ {?eh,tc_auto_skip,{timetrap_6_SUITE,tc0,
+ {failed,{timetrap_6_SUITE,init_per_suite,
+ {user_timetrap_error,{kaboom,'_'}}}}}},
+ {?eh,test_stats,{0,19,{0,1}}},
+ {?eh,tc_auto_skip,{timetrap_6_SUITE,end_per_suite,
+ {failed,{timetrap_6_SUITE,init_per_suite,
+ {user_timetrap_error,{kaboom,'_'}}}}}},
+
+ {?eh,tc_start,{timetrap_7_SUITE,init_per_suite}},
{?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_done,{timetrap_7_SUITE,tc0,
+ {failed,{timetrap_timeout,{'$approx',7000}}}}},
+ {?eh,test_stats,{0,20,{0,1}}},
{?eh,tc_start,{timetrap_7_SUITE,tc1}},
- {?eh,tc_done,
- {timetrap_7_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_done,{timetrap_7_SUITE,tc1,
+ {failed,{timetrap_timeout,{'$approx',2000}}}}},
+ {?eh,test_stats,{0,21,{0,1}}},
{?eh,tc_start,{timetrap_7_SUITE,tc2}},
- {?eh,tc_done,
- {timetrap_7_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_done,{timetrap_7_SUITE,tc2,
+ {failed,{timetrap_timeout,{'$approx',500}}}}},
+ {?eh,test_stats,{0,22,{0,1}}},
{?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,tc3,
+ {failed,{timetrap_timeout,{'$approx',7000}}}}},
+ {?eh,test_stats,{0,23,{0,1}}},
+ {?eh,tc_start,{timetrap_7_SUITE,end_per_suite}},
{?eh,tc_done,{timetrap_7_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
+ ];
+
+test_events(misc_errors) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,7}},
+ {?eh,tc_start,{misc_error_1_SUITE,ct_fail_1}},
+ {?eh,tc_done,{misc_error_1_SUITE,ct_fail_1,
+ {failed,{error,{test_case_failed,{error,this_is_expected}}}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{misc_error_1_SUITE,ct_fail_2}},
+ {?eh,tc_done,{misc_error_1_SUITE,ct_fail_2,
+ {failed,{error,{test_case_failed,"this_is_expected"}}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ {?eh,tc_start,{misc_error_1_SUITE,ct_fail_3}},
+ {?eh,tc_done,{misc_error_1_SUITE,ct_fail_3,
+ {failed,{error,{test_case_failed,this_is_expected}}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{misc_error_1_SUITE,ts_fail_1}},
+ {?eh,tc_done,{misc_error_1_SUITE,ts_fail_1,
+ {failed,{error,{suite_failed,this_is_expected}}}}},
+ {?eh,test_stats,{0,4,{0,0}}},
+ {?eh,tc_start,{misc_error_1_SUITE,ts_fail_2}},
+ {?eh,tc_done,{misc_error_1_SUITE,ts_fail_2,
+ {failed,{error,{suite_failed,this_is_expected}}}}},
+ {?eh,test_stats,{0,5,{0,0}}},
+ {?eh,tc_start,{misc_error_1_SUITE,killed_by_signal_1}},
+ {?eh,tc_done,{misc_error_1_SUITE,killed_by_signal_1,i_die_now}},
+ {?eh,test_stats,{0,6,{0,0}}},
+ {?eh,tc_start,{misc_error_1_SUITE,killed_by_signal_2}},
+ {?eh,tc_done,{misc_error_1_SUITE,killed_by_signal_2,
+ {failed,testcase_aborted_or_killed}}},
+ {?eh,test_stats,{0,7,{0,0}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
].
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl
index ce94533110..879561ebb9 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_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
@@ -29,10 +29,7 @@
suite() ->
[{timetrap,{seconds,2}},
{require, dummy0}, {default_config, dummy0, "suite/0"},
- {require, dummy1}, {default_config, dummy1, "suite/0"},
- {require, dummy2}, {default_config, dummy2, "suite/0"}].
-
-
+ {require, dummy_alias, dummy1}, {default_config, dummy1, "suite/0"}].
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config0) ->
@@ -119,16 +116,17 @@ groups() ->
%% Reason = term()
%%--------------------------------------------------------------------
all() ->
- [tc1, tc2].
+ [tc1,tc2].
tc1() ->
- [{require, dummy0}, {default_config, dummy0, "tc1"}].
+ [{require, dummy0}, {default_config, dummy0, "tc1"},
+ {require, dummy_alias, dummy2}, {default_config, dummy2, "tc1"}].
tc1(_) ->
dummy.
tc2() ->
- [{timetrap,1}].
+ [{timetrap,10}].
tc2(_) ->
dummy.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl
new file mode 100644
index 0000000000..99c3ed05ec
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl
@@ -0,0 +1,154 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(misc_error_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,3}}].
+
+%%--------------------------------------------------------------------
+%% 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(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_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() ->
+ [ct_fail_1, ct_fail_2, ct_fail_3, ts_fail_1, ts_fail_2,
+ killed_by_signal_1, killed_by_signal_2].
+
+ct_fail_1(_) ->
+ ct:fail({error,this_is_expected}),
+ exit(this_should_not_be_seen),
+ ok.
+
+ct_fail_2(_) ->
+ ct:fail("~w", [this_is_expected]),
+ exit(this_should_not_be_seen),
+ ok.
+
+ct_fail_3(_) ->
+ fail_me(fun() -> ct:fail(this_is_expected) end),
+ exit(this_should_not_be_seen),
+ ok.
+
+ts_fail_1(_) ->
+ test_server:fail(this_is_expected),
+ exit(this_should_not_be_seen),
+ ok.
+
+ts_fail_2(_) ->
+ fail_me(fun() -> test_server:fail(this_is_expected) end),
+ exit(this_should_not_be_seen),
+ ok.
+
+fail_me(Fun) ->
+ Fun(),
+ ok.
+
+killed_by_signal_1(_) ->
+ spawn_link(fun() -> ct:sleep(100),
+ exit(i_die_now)
+ end),
+ ct:sleep(1000),
+ exit(this_should_not_be_seen).
+
+killed_by_signal_2(_) ->
+ TCPid = self(),
+ spawn_link(fun() -> ct:sleep(100),
+ exit(TCPid, kill)
+ end),
+ ct:sleep(1000),
+ exit(this_should_not_be_seen).
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl
index cb3109349b..a98382965f 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The 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,23 +83,11 @@ init_per_testcase(TC, Config) ->
ets:insert(?MODULE, {last_case,fail}),
init_per_testcase1(TC, Config).
-init_per_testcase1(tc1, Config) ->
- [{tc,tc1}|Config];
-
-init_per_testcase1(tc2, Config) ->
- [{tc,tc2}|Config];
-
-init_per_testcase1(tc3, Config) ->
- [{tc,tc3}|Config];
-
init_per_testcase1(tc4, Config) ->
[{tc,tc4},{default_timeout,5000}|Config];
-init_per_testcase1(tc5, Config) ->
- [{tc,tc5}|Config];
-
-init_per_testcase1(tc6, Config) ->
- [{tc,tc6}|Config].
+init_per_testcase1(TC, Config) ->
+ [{tc,TC}|Config].
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config0) ->
@@ -145,7 +133,28 @@ end_per_testcase1(tc5, Config) ->
end_per_testcase1(tc6, Config) ->
ct:pal("end_per_testcase(tc6): ~p", [Config]),
tc6 = ?config(tc, Config),
- exit(end_per_tc_fail_after_abort).
+ exit(end_per_tc_fail_after_abort);
+
+end_per_testcase1(tc7, Config) ->
+ ct:pal("end_per_testcase(tc7): ~p", [Config]),
+ tc7 = ?config(tc, Config),
+ {failed,timetrap_timeout} = ?config(tc_status, Config),
+ ok;
+
+end_per_testcase1(tc8, Config) ->
+ ct:pal("end_per_testcase(tc8): ~p", [Config]),
+ tc8 = ?config(tc, Config),
+ {failed,timetrap_timeout} = ?config(tc_status, Config),
+ ok;
+
+end_per_testcase1(tc9, Config) ->
+ ct:pal("end_per_testcase(tc9): ~p", [Config]),
+ tc9 = ?config(tc, Config),
+ %% check that it's possible to send and receive synchronously
+ %% with the group leader process for end_per_testcase
+ test_server:stop_node(dummy@somehost),
+ ok.
+
%%--------------------------------------------------------------------
%% Function: groups() -> [Group]
@@ -170,25 +179,46 @@ groups() ->
%% Reason = term()
%%--------------------------------------------------------------------
all() ->
- [tc1, tc2, tc3, tc4, tc5, tc6].
+ [tc1, tc2, tc3, tc4, tc5, tc6, tc7, tc8, tc9].
tc1(_) ->
- timer:sleep(2000).
+ timer:sleep(2000),
+ ok.
tc2(_) ->
timer:sleep(2000).
tc3(_) ->
spawn(ct, abort_current_testcase, [testing_end_conf]),
- timer:sleep(2000).
+ timer:sleep(2000),
+ ok.
tc4(_) ->
spawn(ct, abort_current_testcase, [testing_end_conf]),
- timer:sleep(2000).
+ timer:sleep(2000),
+ ok.
tc5(_) ->
- timer:sleep(2000).
+ timer:sleep(2000),
+ ok.
tc6(_) ->
spawn(ct, abort_current_testcase, [testing_end_conf]),
timer:sleep(2000).
+
+tc7(_) ->
+ sleep(2000),
+ ok.
+
+tc8(_) ->
+ timetrap_helper:sleep(2000),
+ ok.
+
+tc9(_) ->
+ sleep(2000),
+ ok.
+
+%%%-----------------------------------------------------------------
+sleep(T) ->
+ timer:sleep(T),
+ 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
index c5d4b5062e..5b931c351f 100644
--- 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
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -108,7 +108,8 @@ groups() ->
%% Reason = term()
%%--------------------------------------------------------------------
all() ->
- [tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7].
+ [tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7,tc8,tc9,
+ tc10,tc11,tc12,tc13,tc14].
tc0(_) ->
ct:comment(io_lib:format("TO after ~w sec", [?TO])),
@@ -126,30 +127,89 @@ tc2(_) ->
exit(this_should_not_execute).
tc3() ->
- [{timetrap,{timetrap_utils,timetrap_err_mfa,[]}}].
-tc3(_) ->
- exit(this_should_not_execute).
+ [{timetrap,{timetrap_utils,timetrap_val,[{seconds,2}]}}].
+tc3(_) ->
+ ct:comment("TO after ~2 sec"),
+ ct:sleep({seconds,10}),
+ ok.
tc4() ->
- [{timetrap,fun() -> timetrap_utils:timetrap_err_fun() end}].
-tc4(_) ->
- exit(this_should_not_execute).
+ [{timetrap,fun() -> 500 end}].
+tc4(_) ->
+ ct:comment("TO after 500 ms"),
+ ct:sleep({seconds,10}),
+ ok.
tc5() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,[1000,ok]}}].
+tc5(_) ->
+ ct:comment("TO after ~1 sec"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc6() ->
[{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,40},
{seconds,1}]}}].
-tc5(_) ->
+tc6(_) ->
ct:comment("TO after 40+1 sec"),
ct:sleep({seconds,42}),
ok.
-tc6() ->
+tc7() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,[1000,2000]}}].
+tc7(_) ->
+ ct:comment("TO after ~3 sec"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc8() ->
[{timetrap,fun() -> ct:sleep(6000), 1000 end}].
-tc6(_) ->
+tc8(_) ->
ct:comment("TO after 6+1 sec"),
- ct:sleep({seconds,10}).
+ ct:sleep({seconds,10}),
+ ok.
-tc7(_) ->
+tc9() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,
+ [500,fun() -> {seconds,2} end]}}].
+tc9(_) ->
+ ct:comment("TO after ~2 sec (2.5 sec in reality)"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc10() ->
+ [{timetrap,500}].
+tc10(_) ->
+ ct:timetrap({timetrap_utils,timetrap_val,[1500]}),
+ ct:comment("TO after ~1.5 sec"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc11() ->
+ [{timetrap,2000}].
+tc11(_) ->
+ ct:timetrap(fun() -> 1500 end),
+ ct:comment("TO after ~1.5 sec"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc12() ->
+ [{timetrap,500}].
+tc12(_) ->
+ ct:timetrap({timetrap_utils,timetrap_timeout,[1000,ok]}),
+ ct:comment("TO after ~1 sec"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc13() ->
+ [{timetrap,2000}].
+tc13(_) ->
+ ct:timetrap(fun() -> ct:sleep(500), ok end),
+ ct:comment("TO after ~500 ms"),
+ ct:sleep({seconds,10}),
+ ok.
+
+tc14(_) ->
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_7_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl
index b25b7770a7..922d49c086 100644
--- 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
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -114,7 +114,7 @@ all() ->
tc0(_) ->
ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])),
- ct:sleep({seconds,5}),
+ ct:sleep({seconds,10}),
ok.
tc1() ->
@@ -133,5 +133,5 @@ tc2(_) ->
tc3(_) ->
ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])),
- ct:sleep({seconds,5}),
+ ct:sleep({seconds,10}),
ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl
new file mode 100644
index 0000000000..1389acca11
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl
@@ -0,0 +1,7 @@
+-module(timetrap_helper).
+
+-export([sleep/1]).
+
+sleep(T) ->
+ timer:sleep(T),
+ 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
index fcde6cd701..413ea342a8 100644
--- 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
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,24 +20,15 @@
-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_group_info_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE.erl
new file mode 100644
index 0000000000..c56fa952e8
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE.erl
@@ -0,0 +1,859 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_group_info_SUITE
+%%%
+%%% Description:
+%%% Test that the group info function works as expected with regards
+%%% to timetraps and require (and default config values).
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_group_info_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ timetrap_all,
+ timetrap_group,
+ timetrap_group_case,
+ timetrap_all_no_ips,
+ timetrap_all_no_ipg,
+ require,
+ require_default,
+ require_no_ips,
+ require_no_ipg
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_all(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_timetrap_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {label,timetrap_all}], Config),
+ ok = execute(timetrap_all, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_group(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_timetrap_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{group,[g1,g3,g7]},
+ {label,timetrap_group}], Config),
+ ok = execute(timetrap_group, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_group_case(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_timetrap_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{group,g4},{testcase,t41},
+ {label,timetrap_group_case}], Config),
+ ok = execute(timetrap_group_case, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_all_no_ips(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_timetrap_2_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {label,timetrap_all_no_ips}], Config),
+ ok = execute(timetrap_all_no_ips, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_all_no_ipg(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_timetrap_3_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {label,timetrap_all_no_ipg}], Config),
+ ok = execute(timetrap_all_no_ipg, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+require(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_require_1_SUITE"),
+ CfgFile = filename:join(DataDir, "vars.cfg"),
+ {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile},
+ {label,require}], Config),
+ ok = execute(require, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+require_default(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_require_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {label,require_default}], Config),
+ ok = execute(require_default, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+require_no_ips(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_require_2_SUITE"),
+ CfgFile = filename:join(DataDir, "vars.cfg"),
+ {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile},
+ {label,require_no_ips}], Config),
+ ok = execute(require_no_ips, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+require_no_ipg(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "group_require_3_SUITE"),
+ CfgFile = filename:join(DataDir, "vars.cfg"),
+ {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile},
+ {label,require_no_ipg}], Config),
+ ok = execute(require_no_ipg, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+
+test_events(timetrap_all) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,14}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,init_per_suite,ok}},
+
+ {?eh,tc_done,{group_timetrap_1_SUITE,t1,{failed,{timetrap_timeout,1000}}}},
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t11,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t21,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g2,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_1_SUITE,t2,{failed,{timetrap_timeout,1000}}}},
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g3,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t41,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g4,[]},ok}}],
+ {?eh,tc_done,{group_timetrap_1_SUITE,t31,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t51,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g5,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g3,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_1_SUITE,t3,{failed,{timetrap_timeout,250}}}},
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g6,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t61,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g6,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g6,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g7,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g7,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g8,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g8,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t81,{failed,{timetrap_timeout,750}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g8,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g8,[]},ok}}],
+ {?eh,tc_done,{group_timetrap_1_SUITE,t71,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g9,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g9,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t91,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g9,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g9,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g7,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g7,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g10,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g10,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t101,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g10,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g10,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g11,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g11,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t111,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,14,{0,0}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g11,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g11,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_group) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,7}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t11,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g3,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t41,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g4,[]},ok}}],
+ {?eh,tc_done,{group_timetrap_1_SUITE,t31,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t51,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g5,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g3,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g7,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g7,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g8,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g8,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t81,{failed,{timetrap_timeout,750}}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g8,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g8,[]},ok}}],
+ {?eh,tc_done,{group_timetrap_1_SUITE,t71,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g9,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g9,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t91,{failed,{timetrap_timeout,250}}}},
+ {?eh,test_stats,{0,7,{0,0}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g9,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g9,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g7,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g7,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_group_case) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,init_per_suite,ok}},
+
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g3,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,t41,{failed,{timetrap_timeout,250}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g4,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g3,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_all_no_ips) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,14}},
+
+ {?eh,tc_done,{group_timetrap_2_SUITE,t1,{failed,{timetrap_timeout,1000}}}},
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t11,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t21,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g2,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_2_SUITE,t2,{failed,{timetrap_timeout,1000}}}},
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g3,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t41,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g4,[]},ok}}],
+ {?eh,tc_done,{group_timetrap_2_SUITE,t31,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t51,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g5,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g3,[]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_2_SUITE,t3,{failed,{timetrap_timeout,250}}}},
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g6,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t61,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g6,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g6,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g7,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g7,[]},ok}},
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g8,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g8,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t81,{failed,{timetrap_timeout,750}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g8,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g8,[]},ok}}],
+ {?eh,tc_done,{group_timetrap_2_SUITE,t71,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g9,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g9,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t91,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g9,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g9,[]},ok}}],
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g7,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g7,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g10,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g10,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t101,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g10,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g10,[]},ok}}],
+
+ [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g11,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g11,[]},ok}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,t111,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,14,{0,0}}},
+ {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g11,[]}}},
+ {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g11,[]},ok}}],
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_all_no_ipg) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,14}},
+
+ {?eh,tc_done,{group_timetrap_3_SUITE,t1,{failed,{timetrap_timeout,1000}}}},
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t11,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t21,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_3_SUITE,t2,{failed,{timetrap_timeout,1000}}}},
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t41,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}],
+ {?eh,tc_done,{group_timetrap_3_SUITE,t31,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t51,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}],
+ {?eh,tc_start,{ct_framework,{end_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ {?eh,tc_done,{group_timetrap_3_SUITE,t3,{failed,{timetrap_timeout,250}}}},
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t61,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t81,{failed,{timetrap_timeout,750}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}],
+ {?eh,tc_done,{group_timetrap_3_SUITE,t71,{failed,{timetrap_timeout,500}}}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t91,{failed,{timetrap_timeout,250}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}],
+ {?eh,tc_start,{ct_framework,{end_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t101,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_timetrap_3_SUITE,t111,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,14,{0,0}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}],
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(require) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,13}},
+ {?eh,tc_done,{group_require_1_SUITE,init_per_suite,ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t1,ok}},
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t11,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t21,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g2,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g3,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t31,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g3,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g4,[]},
+ {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,t41,
+ {require_failed,{name_in_use,common2_alias,common2}}}},
+ {?eh,test_stats,{4,0,{0,1}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group,
+ {require_failed,{name_in_use,common2_alias,common2}}}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g5,[]},ok}},
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g6,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t61,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g6,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g6,[]},ok}}],
+ {?eh,tc_done,{group_require_1_SUITE,t51,ok}},
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g7,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g7,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t71,ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t72,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g7,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g7,[]},ok}}],
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g5,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g8,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,
+ {init_per_group,g8,[]},
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,t81,
+ {require_failed,{not_available,non_existing}}}},
+ {?eh,test_stats,{8,0,{0,2}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group,
+ {require_failed,{not_available,non_existing}}}}],
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g9,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g9,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t91,
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,test_stats,{8,0,{0,3}}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g9,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g9,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g10,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g10,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t101,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g10,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g10,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g11,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g11,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t111,ok}},
+ {?eh,test_stats,{10,0,{0,3}}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g11,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g11,[]},ok}}],
+
+ {?eh,tc_done,{group_require_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(require_default) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,13}},
+ {?eh,tc_done,{group_require_1_SUITE,init_per_suite,ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t1,ok}},
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t11,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t21,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g2,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g3,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t31,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g3,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,
+ {init_per_group,g4,[]},
+ {skipped,{require_failed,{not_available,common3}}}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,t41,
+ {require_failed,{not_available,common3}}}},
+ {?eh,test_stats,{4,0,{0,1}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group,
+ {require_failed,{not_available,common3}}}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g5,[]},ok}},
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g6,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t61,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g6,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g6,[]},ok}}],
+ {?eh,tc_done,{group_require_1_SUITE,t51,ok}},
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g7,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g7,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t71,ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t72,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g7,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g7,[]},ok}}],
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g5,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g8,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,
+ {init_per_group,g8,[]},
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,t81,
+ {require_failed,{not_available,non_existing}}}},
+ {?eh,test_stats,{8,0,{0,2}}},
+ {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group,
+ {require_failed,{not_available,non_existing}}}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g9,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g9,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t91,
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,test_stats,{8,0,{0,3}}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g9,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g9,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g10,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g10,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t101,ok}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g10,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g10,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g11,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g11,[]},ok}},
+ {?eh,tc_done,{group_require_1_SUITE,t111,ok}},
+ {?eh,test_stats,{10,0,{0,3}}},
+ {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g11,[]}}},
+ {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g11,[]},ok}}],
+
+ {?eh,tc_done,{group_require_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(require_no_ips) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,13}},
+ {?eh,tc_done,{group_require_2_SUITE,t1,ok}},
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t11,ok}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t21,ok}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g2,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g3,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t31,ok}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g3,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g4,[]},
+ {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}},
+ {?eh,tc_auto_skip,{group_require_2_SUITE,t41,
+ {require_failed,{name_in_use,common2_alias,common2}}}},
+ {?eh,test_stats,{4,0,{0,1}}},
+ {?eh,tc_auto_skip,{group_require_2_SUITE,end_per_group,
+ {require_failed,{name_in_use,common2_alias,common2}}}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g5,[]},ok}},
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g6,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t61,ok}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g6,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g6,[]},ok}}],
+ {?eh,tc_done,{group_require_2_SUITE,t51,ok}},
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g7,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g7,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t71,ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t72,ok}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g7,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g7,[]},ok}}],
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g5,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g8,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,
+ {init_per_group,g8,[]},
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,tc_auto_skip,{group_require_2_SUITE,t81,
+ {require_failed,{not_available,non_existing}}}},
+ {?eh,test_stats,{8,0,{0,2}}},
+ {?eh,tc_auto_skip,{group_require_2_SUITE,end_per_group,
+ {require_failed,{not_available,non_existing}}}}],
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g9,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g9,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t91,
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,test_stats,{8,0,{0,3}}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g9,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g9,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g10,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g10,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t101,ok}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g10,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g10,[]},ok}}],
+
+ [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g11,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g11,[]},ok}},
+ {?eh,tc_done,{group_require_2_SUITE,t111,ok}},
+ {?eh,test_stats,{10,0,{0,3}}},
+ {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g11,[]}}},
+ {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g11,[]},ok}}],
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(require_no_ipg) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,13}},
+ {?eh,tc_done,{group_require_3_SUITE,t1,ok}},
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g1,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g1,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t11,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g1,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g2,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g2,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t21,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g2,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g3,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g3,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t31,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g3,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g4,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g4,[{suite,group_require_3_SUITE}]},
+ {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}},
+ {?eh,tc_auto_skip,{group_require_3_SUITE,t41,
+ {require_failed,{name_in_use,common2_alias,common2}}}},
+ {?eh,test_stats,{4,0,{0,1}}},
+ {?eh,tc_auto_skip,{ct_framework,end_per_group,
+ {require_failed,{name_in_use,common2_alias,common2}}}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g5,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g5,[{suite,group_require_3_SUITE}]},ok}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,g6,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g6,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t61,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g6,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}],
+ {?eh,tc_done,{group_require_3_SUITE,t51,ok}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,g7,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g7,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t71,ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t72,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g7,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}],
+ {?eh,tc_start,{ct_framework,{end_per_group,g5,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g8,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g8,[{suite,group_require_3_SUITE}]},
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,tc_auto_skip,{group_require_3_SUITE,t81,
+ {require_failed,{not_available,non_existing}}}},
+ {?eh,test_stats,{8,0,{0,2}}},
+ {?eh,tc_auto_skip,{ct_framework,end_per_group,
+ {require_failed,{not_available,non_existing}}}}],
+ [{?eh,tc_start,{ct_framework,{init_per_group,g9,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g9,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t91,
+ {skipped,{require_failed,{not_available,non_existing}}}}},
+ {?eh,test_stats,{8,0,{0,3}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g9,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g10,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g10,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t101,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g10,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}],
+
+ [{?eh,tc_start,{ct_framework,{init_per_group,g11,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,g11,[{suite,group_require_3_SUITE}]},ok}},
+ {?eh,tc_done,{group_require_3_SUITE,t111,ok}},
+ {?eh,test_stats,{10,0,{0,3}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,g11,[{suite,group_require_3_SUITE}]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}],
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl
new file mode 100644
index 0000000000..16df897752
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl
@@ -0,0 +1,259 @@
+%%
+%% %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(group_require_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% CONFIG FUNCS
+%%%-----------------------------------------------------------------
+
+init_per_suite(Config) ->
+ ct:comment(io_lib:format("init( ~w ): ~p", [?MODULE, suite()])),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ Info = case catch group(G) of {'EXIT',_} -> []; I -> I end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])),
+ if Info /= [] -> verify_cfg(G); true -> ok end,
+ Config.
+
+end_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ Info = case catch group(G) of {'EXIT',_} -> []; I -> I end,
+ ct:comment(io_lib:format("end( ~w )", [G])),
+ if Info /= [] -> verify_cfg(G); true -> ok end,
+ ok.
+
+init_per_testcase(t101, Config) ->
+ Config;
+init_per_testcase(t111, Config) ->
+ Config;
+init_per_testcase(TestCase, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = if GrProps == undefined -> []; true -> GrProps end,
+ verify_cfg(proplists:get_value(name, GrProps1)),
+ if TestCase == t72 -> verify_cfg(TestCase); true -> ok end,
+ Info = case catch apply(?MODULE,TestCase,[]) of
+ {'EXIT',_} -> [];
+ I -> I
+ end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])),
+ Config.
+
+end_per_testcase(t101, Config) ->
+ ok;
+end_per_testcase(t111, Config) ->
+ ok;
+end_per_testcase(TestCase, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = if GrProps == undefined -> []; true -> GrProps end,
+ verify_cfg(proplists:get_value(name, GrProps1)),
+ if TestCase == t72 -> verify_cfg(TestCase); true -> ok end,
+ ok.
+
+verify_cfg(undefined) ->
+ ok;
+verify_cfg(Name) ->
+ Key = list_to_atom(atom_to_list(Name) ++ "_cfg"),
+ Alias = list_to_atom(atom_to_list(Name) ++ "_cfg_alias"),
+ Val = list_to_atom(atom_to_list(Name) ++ "_cfg_val"),
+ ct:pal("Reading ~p & ~p. Expecting ~p.", [Key,Alias,Val]),
+ Val = ct:get_config(Key),
+ Val = ct:get_config(Alias),
+ suite_cfg_val = ct:get_config(suite_cfg),
+ suite_cfg_val = ct:get_config(suite_cfg_alias).
+
+
+
+%%%------------------------------------------------------------------
+%%% TEST DECLARATIONS
+%%%------------------------------------------------------------------
+
+groups() ->
+ [{g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[t31]},
+ {g4,[],[t41]},
+
+ {g5,[],[{group,g6},t51,{group,g7}]},
+
+ {g6,[],[t61]},
+ {g7,[],[t71,t72]},
+
+ {g8,[],[t81]},
+ {g9,[],[t91]},
+ {g10,[],[t101]},
+ {g11,[],[t111]}
+ ].
+
+
+all() ->
+ [t1,
+ {group,g1},
+ {group,g2},
+ {group,g3},
+ {group,g4},
+ {group,g5},
+ {group,g8},
+ {group,g9},
+ {group,g10},
+ {group,g11}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% INFO FUNCS
+%%%-----------------------------------------------------------------
+
+suite() -> [{require,suite_cfg},
+ {require,suite_cfg_alias,suite_cfg},
+ {require,common1},
+ {default_config,suite_cfg,suite_cfg_val},
+ {default_config,common1,common1_val}].
+
+group(g1) -> [{require,g1_cfg},
+ {require,g1_cfg_alias,g1_cfg},
+ {default_config,g1_cfg,g1_cfg_val}];
+
+group(g2) -> [{require,g2_cfg},
+ {require,g2_cfg_alias,g2_cfg},
+ {require,common1},
+ {require,common2},
+ {default_config,g2_cfg,g2_cfg_val},
+ {default_config,common1,common1_val},
+ {default_config,common2,common2_val}];
+
+group(g3) -> [{require,g3_cfg},
+ {require,g3_cfg_alias,g3_cfg},
+ {require,common2},
+ {require,common2_alias,common2},
+ {default_config,g3_cfg,g3_cfg_val},
+ {default_config,common2,common2_val}];
+
+group(g4) -> [{require,g4_cfg},
+ {require,g4_cfg_alias,g4_cfg},
+ {require,common2_alias,common3},
+ {default_config,g4_cfg,g4_cfg_val}];
+
+group(g5) -> [{require,g5_cfg},
+ {require,g5_cfg_alias,g5_cfg},
+ {default_config,g5_cfg,g5_cfg_val}];
+
+group(g6) -> [{require,g6_cfg},
+ {require,g6_cfg_alias,g6_cfg},
+ {default_config,g6_cfg,g6_cfg_val}];
+
+group(g7) -> [{require,g7_cfg},
+ {require,g7_cfg_alias,g7_cfg},
+ {default_config,g7_cfg,g7_cfg_val}];
+
+group(g8) -> [{require,non_existing}];
+
+group(g9) -> [{require,g9_cfg},
+ {require,g9_cfg_alias,g9_cfg},
+ {default_config,g9_cfg,g9_cfg_val}];
+
+group(G) when G /= g11 -> [].
+
+t72() -> [{require,t72_cfg},
+ {require,t72_cfg_alias,t72_cfg},
+ {default_config,t72_cfg,t72_cfg_val}].
+
+t91() -> [{require,non_existing}].
+
+
+%%%------------------------------------------------------------------
+%%% TEST CASES
+%%%------------------------------------------------------------------
+
+t1(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+t11(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ suite_cfg_val = ct:get_config(suite_cfg_alias),
+ g1_cfg_val = ct:get_config(g1_cfg),
+ g1_cfg_val = ct:get_config(g1_cfg_alias).
+
+t21(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g2_cfg_val = ct:get_config(g2_cfg),
+ g2_cfg_val = ct:get_config(g2_cfg_alias),
+ common1_val = ct:get_config(common1),
+ common2_val = ct:get_config(common2).
+
+t31(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g3_cfg_val = ct:get_config(g3_cfg),
+ g3_cfg_val = ct:get_config(g3_cfg_alias),
+ common2_val = ct:get_config(common2),
+ common2_val = ct:get_config(common2_alias).
+
+t41(_) ->
+ exit(should_be_skipped).
+
+t51(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias).
+
+t61(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g6_cfg_val = ct:get_config(g6_cfg),
+ g6_cfg_val = ct:get_config(g6_cfg_alias).
+
+t71(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g7_cfg_val = ct:get_config(g7_cfg),
+ g7_cfg_val = ct:get_config(g7_cfg_alias).
+
+t72(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g7_cfg_val = ct:get_config(g7_cfg),
+ g7_cfg_val = ct:get_config(g7_cfg_alias),
+ t72_cfg_val = ct:get_config(t72_cfg).
+
+t81(_) ->
+ exit(should_be_skipped).
+
+t91(_) ->
+ exit(should_be_skipped).
+
+t101(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+t111(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl
new file mode 100644
index 0000000000..adb53ff564
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl
@@ -0,0 +1,252 @@
+%%
+%% %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(group_require_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% CONFIG FUNCS
+%%%-----------------------------------------------------------------
+
+init_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ Info = case catch group(G) of {'EXIT',_} -> []; I -> I end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])),
+ if Info /= [] -> verify_cfg(G); true -> ok end,
+ Config.
+
+end_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ Info = case catch group(G) of {'EXIT',_} -> []; I -> I end,
+ ct:comment(io_lib:format("end( ~w )", [G])),
+ if Info /= [] -> verify_cfg(G); true -> ok end,
+ ok.
+
+init_per_testcase(t101, Config) ->
+ Config;
+init_per_testcase(t111, Config) ->
+ Config;
+init_per_testcase(TestCase, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = if GrProps == undefined -> []; true -> GrProps end,
+ verify_cfg(proplists:get_value(name, GrProps1)),
+ if TestCase == t72 -> verify_cfg(TestCase); true -> ok end,
+ Info = case catch apply(?MODULE,TestCase,[]) of
+ {'EXIT',_} -> [];
+ I -> I
+ end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])),
+ Config.
+
+end_per_testcase(t101, Config) ->
+ ok;
+end_per_testcase(t111, Config) ->
+ ok;
+end_per_testcase(TestCase, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = if GrProps == undefined -> []; true -> GrProps end,
+ verify_cfg(proplists:get_value(name, GrProps1)),
+ if TestCase == t72 -> verify_cfg(TestCase); true -> ok end,
+ ok.
+
+verify_cfg(undefined) ->
+ ok;
+verify_cfg(Name) ->
+ Key = list_to_atom(atom_to_list(Name) ++ "_cfg"),
+ Alias = list_to_atom(atom_to_list(Name) ++ "_cfg_alias"),
+ Val = list_to_atom(atom_to_list(Name) ++ "_cfg_val"),
+ ct:pal("Reading ~p & ~p. Expecting ~p.", [Key,Alias,Val]),
+ Val = ct:get_config(Key),
+ Val = ct:get_config(Alias),
+ suite_cfg_val = ct:get_config(suite_cfg),
+ suite_cfg_val = ct:get_config(suite_cfg_alias).
+
+
+
+%%%------------------------------------------------------------------
+%%% TEST DECLARATIONS
+%%%------------------------------------------------------------------
+
+groups() ->
+ [{g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[t31]},
+ {g4,[],[t41]},
+
+ {g5,[],[{group,g6},t51,{group,g7}]},
+
+ {g6,[],[t61]},
+ {g7,[],[t71,t72]},
+
+ {g8,[],[t81]},
+ {g9,[],[t91]},
+ {g10,[],[t101]},
+ {g11,[],[t111]}
+ ].
+
+
+all() ->
+ [t1,
+ {group,g1},
+ {group,g2},
+ {group,g3},
+ {group,g4},
+ {group,g5},
+ {group,g8},
+ {group,g9},
+ {group,g10},
+ {group,g11}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% INFO FUNCS
+%%%-----------------------------------------------------------------
+
+suite() -> [{require,suite_cfg},
+ {require,suite_cfg_alias,suite_cfg},
+ {require,common1},
+ {default_config,suite_cfg,suite_cfg_val},
+ {default_config,common1,common1_val}].
+
+group(g1) -> [{require,g1_cfg},
+ {require,g1_cfg_alias,g1_cfg},
+ {default_config,g1_cfg,g1_cfg_val}];
+
+group(g2) -> [{require,g2_cfg},
+ {require,g2_cfg_alias,g2_cfg},
+ {require,common1},
+ {require,common2},
+ {default_config,g2_cfg,g2_cfg_val},
+ {default_config,common1,common1_val},
+ {default_config,common2,common2_val}];
+
+group(g3) -> [{require,g3_cfg},
+ {require,g3_cfg_alias,g3_cfg},
+ {require,common2},
+ {require,common2_alias,common2},
+ {default_config,g3_cfg,g3_cfg_val},
+ {default_config,common2,common2_val}];
+
+group(g4) -> [{require,g4_cfg},
+ {require,g4_cfg_alias,g4_cfg},
+ {require,common2_alias,common3},
+ {default_config,g4_cfg,g4_cfg_val}];
+
+group(g5) -> [{require,g5_cfg},
+ {require,g5_cfg_alias,g5_cfg},
+ {default_config,g5_cfg,g5_cfg_val}];
+
+group(g6) -> [{require,g6_cfg},
+ {require,g6_cfg_alias,g6_cfg},
+ {default_config,g6_cfg,g6_cfg_val}];
+
+group(g7) -> [{require,g7_cfg},
+ {require,g7_cfg_alias,g7_cfg},
+ {default_config,g7_cfg,g7_cfg_val}];
+
+group(g8) -> [{require,non_existing}];
+
+group(g9) -> [{require,g9_cfg},
+ {require,g9_cfg_alias,g9_cfg},
+ {default_config,g9_cfg,g9_cfg_val}];
+
+group(G) when G /= g11 -> [].
+
+t72() -> [{require,t72_cfg},
+ {require,t72_cfg_alias,t72_cfg},
+ {default_config,t72_cfg,t72_cfg_val}].
+
+t91() -> [{require,non_existing}].
+
+
+%%%------------------------------------------------------------------
+%%% TEST CASES
+%%%------------------------------------------------------------------
+
+t1(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+t11(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ suite_cfg_val = ct:get_config(suite_cfg_alias),
+ g1_cfg_val = ct:get_config(g1_cfg),
+ g1_cfg_val = ct:get_config(g1_cfg_alias).
+
+t21(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g2_cfg_val = ct:get_config(g2_cfg),
+ g2_cfg_val = ct:get_config(g2_cfg_alias),
+ common1_val = ct:get_config(common1),
+ common2_val = ct:get_config(common2).
+
+t31(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g3_cfg_val = ct:get_config(g3_cfg),
+ g3_cfg_val = ct:get_config(g3_cfg_alias),
+ common2_val = ct:get_config(common2),
+ common2_val = ct:get_config(common2_alias).
+
+t41(_) ->
+ exit(should_be_skipped).
+
+t51(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias).
+
+t61(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g6_cfg_val = ct:get_config(g6_cfg),
+ g6_cfg_val = ct:get_config(g6_cfg_alias).
+
+t71(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g7_cfg_val = ct:get_config(g7_cfg),
+ g7_cfg_val = ct:get_config(g7_cfg_alias).
+
+t72(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g7_cfg_val = ct:get_config(g7_cfg),
+ g7_cfg_val = ct:get_config(g7_cfg_alias),
+ t72_cfg_val = ct:get_config(t72_cfg).
+
+t81(_) ->
+ exit(should_be_skipped).
+
+t91(_) ->
+ exit(should_be_skipped).
+
+t101(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+t111(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl
new file mode 100644
index 0000000000..1f2dfd2a30
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl
@@ -0,0 +1,241 @@
+%%
+%% %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(group_require_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% CONFIG FUNCS
+%%%-----------------------------------------------------------------
+
+%% init_per_suite(Config) ->
+%% Config.
+%% end_per_suite(_) ->
+%% ok.
+
+init_per_testcase(t101, Config) ->
+ Config;
+init_per_testcase(t111, Config) ->
+ Config;
+init_per_testcase(TestCase, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = if GrProps == undefined -> []; true -> GrProps end,
+ verify_cfg(proplists:get_value(name, GrProps1)),
+ if TestCase == t72 -> verify_cfg(TestCase); true -> ok end,
+ Info = case catch apply(?MODULE,TestCase,[]) of
+ {'EXIT',_} -> [];
+ I -> I
+ end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])),
+ Config.
+
+end_per_testcase(t101, _Config) ->
+ ok;
+end_per_testcase(t111, _Config) ->
+ ok;
+end_per_testcase(TestCase, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = if GrProps == undefined -> []; true -> GrProps end,
+ verify_cfg(proplists:get_value(name, GrProps1)),
+ if TestCase == t72 -> verify_cfg(TestCase); true -> ok end,
+ ok.
+
+verify_cfg(undefined) ->
+ ok;
+verify_cfg(Name) ->
+ Key = list_to_atom(atom_to_list(Name) ++ "_cfg"),
+ Alias = list_to_atom(atom_to_list(Name) ++ "_cfg_alias"),
+ Val = list_to_atom(atom_to_list(Name) ++ "_cfg_val"),
+ ct:pal("Reading ~p & ~p. Expecting ~p.", [Key,Alias,Val]),
+ Val = ct:get_config(Key),
+ Val = ct:get_config(Alias),
+ suite_cfg_val = ct:get_config(suite_cfg),
+ suite_cfg_val = ct:get_config(suite_cfg_alias).
+
+
+
+%%%------------------------------------------------------------------
+%%% TEST DECLARATIONS
+%%%------------------------------------------------------------------
+
+groups() ->
+ [{g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[t31]},
+ {g4,[],[t41]},
+
+ {g5,[],[{group,g6},t51,{group,g7}]},
+
+ {g6,[],[t61]},
+ {g7,[],[t71,t72]},
+
+ {g8,[],[t81]},
+ {g9,[],[t91]},
+ {g10,[],[t101]},
+ {g11,[],[t111]}
+ ].
+
+
+all() ->
+ [t1,
+ {group,g1},
+ {group,g2},
+ {group,g3},
+ {group,g4},
+ {group,g5},
+ {group,g8},
+ {group,g9},
+ {group,g10},
+ {group,g11}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% INFO FUNCS
+%%%-----------------------------------------------------------------
+
+suite() -> [{require,suite_cfg},
+ {require,suite_cfg_alias,suite_cfg},
+ {require,common1},
+ {default_config,suite_cfg,suite_cfg_val},
+ {default_config,common1,common1_val}].
+
+group(g1) -> [{require,g1_cfg},
+ {require,g1_cfg_alias,g1_cfg},
+ {default_config,g1_cfg,g1_cfg_val}];
+
+group(g2) -> [{require,g2_cfg},
+ {require,g2_cfg_alias,g2_cfg},
+ {require,common1},
+ {require,common2},
+ {default_config,g2_cfg,g2_cfg_val},
+ {default_config,common1,common1_val},
+ {default_config,common2,common2_val}];
+
+group(g3) -> [{require,g3_cfg},
+ {require,g3_cfg_alias,g3_cfg},
+ {require,common2},
+ {require,common2_alias,common2},
+ {default_config,g3_cfg,g3_cfg_val},
+ {default_config,common2,common2_val}];
+
+group(g4) -> [{require,g4_cfg},
+ {require,g4_cfg_alias,g4_cfg},
+ {require,common2_alias,common3},
+ {default_config,g4_cfg,g4_cfg_val}];
+
+group(g5) -> [{require,g5_cfg},
+ {require,g5_cfg_alias,g5_cfg},
+ {default_config,g5_cfg,g5_cfg_val}];
+
+group(g6) -> [{require,g6_cfg},
+ {require,g6_cfg_alias,g6_cfg},
+ {default_config,g6_cfg,g6_cfg_val}];
+
+group(g7) -> [{require,g7_cfg},
+ {require,g7_cfg_alias,g7_cfg},
+ {default_config,g7_cfg,g7_cfg_val}];
+
+group(g8) -> [{require,non_existing}];
+
+group(g9) -> [{require,g9_cfg},
+ {require,g9_cfg_alias,g9_cfg},
+ {default_config,g9_cfg,g9_cfg_val}];
+
+group(G) when G /= g11 -> [].
+
+t72() -> [{require,t72_cfg},
+ {require,t72_cfg_alias,t72_cfg},
+ {default_config,t72_cfg,t72_cfg_val}].
+
+t91() -> [{require,non_existing}].
+
+
+%%%------------------------------------------------------------------
+%%% TEST CASES
+%%%------------------------------------------------------------------
+
+t1(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+t11(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ suite_cfg_val = ct:get_config(suite_cfg_alias),
+ g1_cfg_val = ct:get_config(g1_cfg),
+ g1_cfg_val = ct:get_config(g1_cfg_alias).
+
+t21(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g2_cfg_val = ct:get_config(g2_cfg),
+ g2_cfg_val = ct:get_config(g2_cfg_alias),
+ common1_val = ct:get_config(common1),
+ common2_val = ct:get_config(common2).
+
+t31(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g3_cfg_val = ct:get_config(g3_cfg),
+ g3_cfg_val = ct:get_config(g3_cfg_alias),
+ common2_val = ct:get_config(common2),
+ common2_val = ct:get_config(common2_alias).
+
+t41(_) ->
+ exit(should_be_skipped).
+
+t51(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias).
+
+t61(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g6_cfg_val = ct:get_config(g6_cfg),
+ g6_cfg_val = ct:get_config(g6_cfg_alias).
+
+t71(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g7_cfg_val = ct:get_config(g7_cfg),
+ g7_cfg_val = ct:get_config(g7_cfg_alias).
+
+t72(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg),
+ g5_cfg_val = ct:get_config(g5_cfg_alias),
+ g7_cfg_val = ct:get_config(g7_cfg),
+ g7_cfg_val = ct:get_config(g7_cfg_alias),
+ t72_cfg_val = ct:get_config(t72_cfg).
+
+t81(_) ->
+ exit(should_be_skipped).
+
+t91(_) ->
+ exit(should_be_skipped).
+
+t101(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+t111(_) ->
+ suite_cfg_val = ct:get_config(suite_cfg).
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl
new file mode 100644
index 0000000000..0a81edf729
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl
@@ -0,0 +1,191 @@
+%%
+%% %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(group_timetrap_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% CONFIG FUNCS
+%%%-----------------------------------------------------------------
+
+init_per_suite(Config) ->
+ ct:comment(io_lib:format("init( ~w ): ~p", [?MODULE, suite()])),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ Info = case catch group(G) of {'EXIT',_} -> []; I -> I end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])),
+ Config.
+
+end_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ ct:comment(io_lib:format("end( ~w )", [G])),
+ ok.
+
+init_per_testcase(TestCase, Config) ->
+ Info = case catch apply(?MODULE,TestCase,[]) of
+ {'EXIT',_} -> [];
+ I -> I
+ end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])),
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%%------------------------------------------------------------------
+%%% TEST DECLARATIONS
+%%%------------------------------------------------------------------
+
+groups() ->
+ [{g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[{group,g4},t31,{group,g5}]},
+
+ {g4,[],[t41]},
+ {g5,[],[t51]},
+
+ {g6,[],[t61]},
+ {g7,[],[{group,g8},t71,{group,g9}]},
+
+ {g8,[],[t81]},
+ {g9,[],[t91]},
+
+ {g10,[],[t101]},
+ {g11,[],[t111]}
+ ].
+
+
+all() ->
+ [t1,
+ {group,g1},
+ {group,g2},
+ t2,
+ {group,g3},
+ t3,
+ {group,g6},
+ {group,g7},
+ {group,g10},
+ {group,g11}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% INFO FUNCS
+%%%-----------------------------------------------------------------
+
+suite() -> [{timetrap,1000}].
+
+group(g1) -> [{timetrap,500}];
+
+group(g2) -> [{timetrap,1500}];
+
+group(g3) -> [{timetrap,500}];
+
+group(g4) -> [{timetrap,250}];
+
+group(g5) -> [{timetrap,1500}];
+
+group(g6) -> [{timetrap,250}];
+
+group(g7) -> [{timetrap,250}];
+
+group(g8) -> [{timetrap,250}];
+
+group(G) when G /= g11 -> [].
+
+t3() -> [{timetrap,250}].
+
+t61() -> [{timetrap,500}].
+
+t71() -> [{timetrap,500}].
+
+t81() -> [{timetrap,750}].
+
+t91() -> [{timetrap,250}].
+
+%%%------------------------------------------------------------------
+%%% TEST CASES
+%%%------------------------------------------------------------------
+
+t1(_) ->
+ ct:sleep(3000),
+ exit(should_timeout).
+
+t11(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t21(_) ->
+ ct:sleep(3000),
+ exit(should_timeout).
+
+t2(_) ->
+ ct:sleep(1250),
+ exit(should_timeout).
+
+t31(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t41(_) ->
+ ct:sleep(350),
+ exit(should_timeout).
+
+t51(_) ->
+ ct:sleep(2000),
+ exit(should_timeout).
+
+t3(_) ->
+ ct:sleep(500),
+ exit(should_timeout).
+
+t61(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t71(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t81(_) ->
+ ct:sleep(1000),
+ exit(should_timeout).
+
+t91(_) ->
+ ct:sleep(350),
+ exit(should_timeout).
+
+t101(_) ->
+ ct:sleep(1500),
+ exit(should_timeout).
+
+t111(_) ->
+ ct:sleep(1500),
+ exit(should_timeout).
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl
new file mode 100644
index 0000000000..1ebe8bd510
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl
@@ -0,0 +1,184 @@
+%%
+%% %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(group_timetrap_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% CONFIG FUNCS
+%%%-----------------------------------------------------------------
+
+init_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ Info = case catch group(G) of {'EXIT',_} -> []; I -> I end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])),
+ Config.
+
+end_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ _GrProps1 = proplists:delete(name, GrProps),
+ ct:comment(io_lib:format("end( ~w )", [G])),
+ ok.
+
+init_per_testcase(TestCase, Config) ->
+ Info = case catch apply(?MODULE,TestCase,[]) of
+ {'EXIT',_} -> [];
+ I -> I
+ end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])),
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%%------------------------------------------------------------------
+%%% TEST DECLARATIONS
+%%%------------------------------------------------------------------
+
+groups() ->
+ [{g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[{group,g4},t31,{group,g5}]},
+
+ {g4,[],[t41]},
+ {g5,[],[t51]},
+
+ {g6,[],[t61]},
+ {g7,[],[{group,g8},t71,{group,g9}]},
+
+ {g8,[],[t81]},
+ {g9,[],[t91]},
+
+ {g10,[],[t101]},
+ {g11,[],[t111]}
+ ].
+
+
+all() ->
+ [t1,
+ {group,g1},
+ {group,g2},
+ t2,
+ {group,g3},
+ t3,
+ {group,g6},
+ {group,g7},
+ {group,g10},
+ {group,g11}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% INFO FUNCS
+%%%-----------------------------------------------------------------
+
+suite() -> [{timetrap,1000}].
+
+group(g1) -> [{timetrap,500}];
+
+group(g2) -> [{timetrap,1500}];
+
+group(g3) -> [{timetrap,500}];
+
+group(g4) -> [{timetrap,250}];
+
+group(g5) -> [{timetrap,1500}];
+
+group(g6) -> [{timetrap,250}];
+
+group(g7) -> [{timetrap,250}];
+
+group(g8) -> [{timetrap,250}];
+
+group(G) when G /= g11 -> [].
+
+t3() -> [{timetrap,250}].
+
+t61() -> [{timetrap,500}].
+
+t71() -> [{timetrap,500}].
+
+t81() -> [{timetrap,750}].
+
+t91() -> [{timetrap,250}].
+
+%%%------------------------------------------------------------------
+%%% TEST CASES
+%%%------------------------------------------------------------------
+
+t1(_) ->
+ ct:sleep(3000),
+ exit(should_timeout).
+
+t11(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t21(_) ->
+ ct:sleep(3000),
+ exit(should_timeout).
+
+t2(_) ->
+ ct:sleep(1250),
+ exit(should_timeout).
+
+t31(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t41(_) ->
+ ct:sleep(350),
+ exit(should_timeout).
+
+t51(_) ->
+ ct:sleep(2000),
+ exit(should_timeout).
+
+t3(_) ->
+ ct:sleep(500),
+ exit(should_timeout).
+
+t61(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t71(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t81(_) ->
+ ct:sleep(1000),
+ exit(should_timeout).
+
+t91(_) ->
+ ct:sleep(350),
+ exit(should_timeout).
+
+t101(_) ->
+ ct:sleep(1500),
+ exit(should_timeout).
+
+t111(_) ->
+ ct:sleep(1500),
+ exit(should_timeout).
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl
new file mode 100644
index 0000000000..66d29802e2
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl
@@ -0,0 +1,171 @@
+%%
+%% %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(group_timetrap_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% CONFIG FUNCS
+%%%-----------------------------------------------------------------
+
+init_per_testcase(TestCase, Config) ->
+ Info = case catch apply(?MODULE,TestCase,[]) of
+ {'EXIT',_} -> [];
+ I -> I
+ end,
+ ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])),
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%%------------------------------------------------------------------
+%%% TEST DECLARATIONS
+%%%------------------------------------------------------------------
+
+groups() ->
+ [{g1,[],[t11]},
+ {g2,[],[t21]},
+ {g3,[],[{group,g4},t31,{group,g5}]},
+
+ {g4,[],[t41]},
+ {g5,[],[t51]},
+
+ {g6,[],[t61]},
+ {g7,[],[{group,g8},t71,{group,g9}]},
+
+ {g8,[],[t81]},
+ {g9,[],[t91]},
+
+ {g10,[],[t101]},
+ {g11,[],[t111]}
+ ].
+
+
+all() ->
+ [t1,
+ {group,g1},
+ {group,g2},
+ t2,
+ {group,g3},
+ t3,
+ {group,g6},
+ {group,g7},
+ {group,g10},
+ {group,g11}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% INFO FUNCS
+%%%-----------------------------------------------------------------
+
+suite() -> [{timetrap,1000}].
+
+group(g1) -> [{timetrap,500}];
+
+group(g2) -> [{timetrap,1500}];
+
+group(g3) -> [{timetrap,500}];
+
+group(g4) -> [{timetrap,250}];
+
+group(g5) -> [{timetrap,1500}];
+
+group(g6) -> [{timetrap,250}];
+
+group(g7) -> [{timetrap,250}];
+
+group(g8) -> [{timetrap,250}];
+
+group(G) when G /= g11 -> [].
+
+t3() -> [{timetrap,250}].
+
+t61() -> [{timetrap,500}].
+
+t71() -> [{timetrap,500}].
+
+t81() -> [{timetrap,750}].
+
+t91() -> [{timetrap,250}].
+
+%%%------------------------------------------------------------------
+%%% TEST CASES
+%%%------------------------------------------------------------------
+
+t1(_) ->
+ ct:sleep(3000),
+ exit(should_timeout).
+
+t11(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t21(_) ->
+ ct:sleep(3000),
+ exit(should_timeout).
+
+t2(_) ->
+ ct:sleep(1250),
+ exit(should_timeout).
+
+t31(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t41(_) ->
+ ct:sleep(350),
+ exit(should_timeout).
+
+t51(_) ->
+ ct:sleep(2000),
+ exit(should_timeout).
+
+t3(_) ->
+ ct:sleep(500),
+ exit(should_timeout).
+
+t61(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t71(_) ->
+ ct:sleep(750),
+ exit(should_timeout).
+
+t81(_) ->
+ ct:sleep(1000),
+ exit(should_timeout).
+
+t91(_) ->
+ ct:sleep(350),
+ exit(should_timeout).
+
+t101(_) ->
+ ct:sleep(1500),
+ exit(should_timeout).
+
+t111(_) ->
+ ct:sleep(1500),
+ exit(should_timeout).
+
+
diff --git a/lib/common_test/test/ct_group_info_SUITE_data/vars.cfg b/lib/common_test/test/ct_group_info_SUITE_data/vars.cfg
new file mode 100644
index 0000000000..8a1960d121
--- /dev/null
+++ b/lib/common_test/test/ct_group_info_SUITE_data/vars.cfg
@@ -0,0 +1,19 @@
+{suite_cfg,suite_cfg_val}.
+{g1_cfg,g1_cfg_val}.
+{g2_cfg,g2_cfg_val}.
+{g3_cfg,g3_cfg_val}.
+{g4_cfg,g4_cfg_val}.
+{g5_cfg,g5_cfg_val}.
+{g6_cfg,g6_cfg_val}.
+{g7_cfg,g7_cfg_val}.
+{g8_cfg,g8_cfg_val}.
+{g9_cfg,g9_cfg_val}.
+{g10_cfg,g10_cfg_val}.
+{g11_cfg,g11_cfg_val}.
+
+{t72_cfg,t72_cfg_val}.
+{t91_cfg,t91_cfg_val}.
+
+{common1,common1_val}.
+{common2,common2_val}.
+{common3,common3_val}.
diff --git a/lib/common_test/test/ct_groups_spec_SUITE.erl b/lib/common_test/test/ct_groups_spec_SUITE.erl
new file mode 100644
index 0000000000..5a6d5ac0ac
--- /dev/null
+++ b/lib/common_test/test/ct_groups_spec_SUITE.erl
@@ -0,0 +1,586 @@
+%%
+%% %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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_groups_spec_SUITE
+%%%
+%%% Description:
+%%% Test that overriding default group properties with group terms
+%%% in all/0 and in test specifications works as expected.
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_groups_spec_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ simple_group_opt,
+ simple_group_case_opt,
+ override_with_all,
+ override_with_spec
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+simple_group_opt(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "groups_spec_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{group,[g1,g5]},
+ {label,simple_group_opt}], Config),
+ ok = execute(simple_group_opt, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+simple_group_case_opt(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "groups_spec_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{group,g5},{testcase,[t52,t54]},
+ {label,simple_group_case_opt}], Config),
+ ok = execute(simple_group_case_opt, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+override_with_all(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "groups_spec_1_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,override_with_all}], Config),
+ ok = execute(override_with_all, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+override_with_spec(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Spec = filename:join(DataDir, "override.spec"),
+ {Opts,ERPid} = setup([{spec,Spec},{label,override_with_spec}], Config),
+ ok = execute(override_with_spec, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+
+test_events(simple_group_opt) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{1,1,7}},
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}},
+ {?eh,test_stats,{2,1,{0,0}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}},
+
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t51}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t52}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t53}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t54}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}},
+ {?eh,test_stats,{4,3,{0,0}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}],
+
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(simple_group_case_opt) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{1,1,2}},
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}},
+
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t52}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t54}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}],
+
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(override_with_all) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{1,1,45}},
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+
+ %% TEST: {group,g1,default}
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}},
+ {?eh,test_stats,{2,1,{0,0}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[]},ok}}],
+
+ %% TEST: {group,g1,[sequence]}
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t13,{failed,{groups_spec_1_SUITE,t12}}}},
+ {?eh,test_stats,{3,2,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]},ok}}],
+
+ %% TEST: {group,g1,[parallel],[]}
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t11}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t12}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t13}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}},
+ {?eh,test_stats,{5,3,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]},ok}}]},
+
+ %% TEST: {group,g2,[],[]}
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}},
+ {?eh,test_stats,{6,3,{0,1}}},
+
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t31}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t32}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t33}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t33,ok}},
+ {?eh,test_stats,{8,4,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]},ok}}]},
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}},
+ {?eh,test_stats,{8,5,{0,1}}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}},
+ {?eh,test_stats,{9,5,{0,1}}},
+
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t51}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t52}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t53}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t54}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}},
+ {?eh,test_stats,{11,7,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]},
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}},
+ {?eh,test_stats,{11,8,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}},
+ {?eh,test_stats,{12,8,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}],
+
+ %% TEST: {group,g2,default,[{g3,[sequence]}]}
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}},
+ {?eh,test_stats,{13,8,{0,1}}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}},
+ {?eh,test_stats,{14,9,{0,2}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t41,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t51,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t52,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t42,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t23,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,test_stats,{14,10,{0,9}}},
+
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}],
+
+ %% TEST: {group,g2,[],[{g4,[sequence],[{g5,[sequence]}]},{g3,[sequence]}]}
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}},
+ {?eh,test_stats,{15,10,{0,9}}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}},
+ {?eh,test_stats,{16,11,{0,10}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}},
+ {?eh,test_stats,{16,12,{0,10}}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}},
+ {?eh,test_stats,{17,12,{0,10}}},
+
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t52}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t52}}}},
+ {?eh,test_stats,{18,13,{0,12}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}},
+ {?eh,test_stats,{18,14,{0,12}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}},
+ {?eh,test_stats,{19,14,{0,12}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}],
+
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(override_with_spec) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{7,4,49}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE, {g1,default}}.
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}},
+ {?eh,test_stats,{2,1,{0,0}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE, [{g1,[sequence]},
+ %% {g1,[parallel],[]}]}.
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t13,{failed,{groups_spec_1_SUITE,t12}}}},
+ {?eh,test_stats,{3,2,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]},ok}}],
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t11}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t12}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t13}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}},
+ {?eh,test_stats,{5,3,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]},ok}}]},
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE, {g2,[],[]}}.
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t21}},
+ {?eh,test_stats,{6,3,{0,1}}},
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t31}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t32}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t33}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t33,ok}},
+ {?eh,test_stats,{8,4,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]},ok}}]},
+ {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}},
+ {?eh,test_stats,{8,5,{0,1}}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}},
+ {?eh,test_stats,{9,5,{0,1}}},
+ {parallel,
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t51}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t52}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t53}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,t54}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}},
+ {?eh,test_stats,{11,7,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]},
+ {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}},
+ {?eh,test_stats,{11,8,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}},
+ {?eh,test_stats,{12,8,{0,1}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE, {g2,default,[{g3,[sequence]}]}}
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}},
+ {?eh,test_stats,{13,8,{0,1}}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}},
+ {?eh,test_stats,{14,9,{0,2}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t41,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t51,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t52,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t42,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t23,{failed,{groups_spec_1_SUITE,t22}}}},
+ {?eh,test_stats,{14,10,{0,9}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE,
+ %% {g2,[],[{g4,[sequence],[{g5,[sequence]}]},{g3,[sequence]}]}}.
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}},
+ {?eh,test_stats,{15,10,{0,9}}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}},
+ {?eh,test_stats,{16,11,{0,10}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}},
+ {?eh,test_stats,{16,12,{0,10}}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}},
+ {?eh,test_stats,{17,12,{0,10}}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t52}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t52}}}},
+ {?eh,test_stats,{18,13,{0,12}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}},
+ {?eh,test_stats,{18,14,{0,12}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}},
+ {?eh,test_stats,{19,14,{0,12}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE, {g1,[sequence]}, {cases,[t12,t13]}}
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}},
+ {?eh,tc_auto_skip,{groups_spec_1_SUITE,t13,{failed,{groups_spec_1_SUITE,t12}}}},
+ {?eh,test_stats,{19,15,{0,13}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ %% TEST: {groups, dir, groups_spec_1_SUITE, {g5,[]}, {cases,[t53,t54]}}
+ {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}},
+ [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}},
+ {?eh,test_stats,{20,16,{0,13}}},
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[]},ok}}],
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}],
+ {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}},
+ {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}],
+ {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
+
diff --git a/lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl b/lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl
new file mode 100644
index 0000000000..ae6065bae4
--- /dev/null
+++ b/lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl
@@ -0,0 +1,124 @@
+%%
+%% %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(groups_spec_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% INFO FUNCS
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,1000}].
+
+group(_) ->
+ [{timetrap,2000}].
+
+%%--------------------------------------------------------------------
+%% CONFIG FUNCS
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = proplists:delete(name, GrProps),
+ ct:comment(io_lib:format("init( ~w ): ~p", [G, GrProps1])),
+ ct:pal("init( ~w ): ~p", [G, GrProps1]),
+ Config.
+
+end_per_group(G, Config) ->
+ GrProps = proplists:get_value(tc_group_properties, Config),
+ GrProps1 = proplists:delete(name, GrProps),
+ ct:comment(io_lib:format("end( ~w ): ~p", [G, GrProps1])),
+ ct:pal("end( ~w ): ~p", [G, GrProps1]),
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% TEST DECLARATIONS
+%%--------------------------------------------------------------------
+
+groups() ->
+ [
+ {g1,[],[t11,t12,t13]},
+ {g2,[sequence],[t21,{group,g3},t22,{group,g4},t23]},
+ {g3,[parallel],[t31,t32,t33]},
+ {g4,[],[t41,{group,g5},t42]},
+ {g5,[parallel],[t51,t52,t53,t54]}
+ ].
+
+all() ->
+ [
+ {group,g1,default},
+ {group,g1,[sequence]},
+ {group,g1,[parallel],[]},
+
+ {group,g2,[],[]},
+ {group,g2,default,[{g3,[sequence]}]},
+ {group,g2,[],[{g4,[sequence],[{g5,[sequence]}]},{g3,[sequence]}]}
+ ].
+
+%%-----------------------------------------------------------------
+%% TEST CASES
+%%-----------------------------------------------------------------
+
+t11(_) ->
+ ok.
+t12(_) ->
+ exit(crashes).
+t13(_) ->
+ ok.
+
+t21(_) ->
+ ok.
+t22(_) ->
+ exit(crashes).
+t23(_) ->
+ ok.
+
+t31(_) ->
+ ok.
+t32(_) ->
+ exit(crashes).
+t33(_) ->
+ ok.
+
+t41(_) ->
+ ok.
+t42(_) ->
+ exit(crashes).
+
+t51(_) ->
+ ok.
+t52(_) ->
+ ct:sleep(3000).
+t53(_) ->
+ exit(crashes).
+t54(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_groups_spec_SUITE_data/override.spec b/lib/common_test/test/ct_groups_spec_SUITE_data/override.spec
new file mode 100644
index 0000000000..1bfc6405c9
--- /dev/null
+++ b/lib/common_test/test/ct_groups_spec_SUITE_data/override.spec
@@ -0,0 +1,15 @@
+{merge_tests,false}.
+
+{alias,dir,"."}.
+
+{groups, dir, groups_spec_1_SUITE, {g1,default}}.
+{groups, dir, groups_spec_1_SUITE, [{g1,[sequence]},
+ {g1,[parallel],[]}]}.
+
+{groups, dir, groups_spec_1_SUITE, {g2,[],[]}}.
+{groups, dir, groups_spec_1_SUITE, {g2,default,[{g3,[sequence]}]}}.
+{groups, dir, groups_spec_1_SUITE, {g2,[],[{g4,[sequence],[{g5,[sequence]}]},
+ {g3,[sequence]}]}}.
+
+{groups, dir, groups_spec_1_SUITE, {g1,[sequence]}, {cases,[t12,t13]}}.
+{groups, dir, groups_spec_1_SUITE, {g5,[]}, {cases,[t53,t54]}}.
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 940d791b15..1b2ad12e2f 100644
--- a/lib/common_test/test/ct_groups_test_2_SUITE.erl
+++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -171,16 +171,16 @@ test_events(missing_conf) ->
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?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,tc_start,{ct_framework,{init_per_group,group1,[]}}},
+ {?eh,tc_done,{ct_framework,{init_per_group,group1,[]},ok}},
{?eh,tc_start,{missing_conf_SUITE,tc1}},
{?eh,tc_done,{missing_conf_SUITE,tc1,ok}},
{?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,{2,0,{0,0}}},
- {?eh,tc_start,{ct_framework,ct_end_per_group}},
- {?eh,tc_done,{ct_framework,ct_end_per_group,ok}},
+ {?eh,tc_start,{ct_framework,{end_per_group,group1,[]}}},
+ {?eh,tc_done,{ct_framework,{end_per_group,group1,[]},ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
];
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 5c99f0f9f7..405df1e978 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,10 +83,10 @@ all(suite) ->
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, prio_cth
+ fail_n_skip_with_minimal_cth, prio_cth, no_config,
+ data_dir
]
- )
- .
+ ).
%%--------------------------------------------------------------------
@@ -214,6 +214,16 @@ prio_cth(Config) when is_list(Config) ->
[{empty_cth,[1000],1000},{empty_cth,[900],900},
{prio_cth,[1100,100],100},{prio_cth,[1100]}],Config).
+no_config(Config) when is_list(Config) ->
+ do_test(no_config, "ct_no_config_SUITE.erl",
+ [verify_config_cth],Config).
+
+data_dir(Config) when is_list(Config) ->
+ do_test(data_dir, "ct_data_dir_SUITE.erl",
+ [verify_data_dir_cth],Config).
+
+
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -1046,33 +1056,137 @@ test_events(prio_cth) ->
[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]]) ++
+ lists:reverse(
+ [[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]]) ++
+ lists:reverse(
+ [[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]]) ++
+ lists:reverse(
+ [[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]]) ++
+ lists:reverse(
+ [[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]]) ++
+ lists:reverse(
+ [[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(no_config) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,init,[verify_config_cth,[]]}},
+ {?eh,start_info,{1,1,2}},
+ {?eh,tc_start,{ct_framework,init_per_suite}},
+ {?eh,cth,{empty_cth,pre_init_per_suite,
+ [ct_no_config_SUITE,'$proplist',[]]}},
+ {?eh,cth,{empty_cth,post_init_per_suite,
+ [ct_no_config_SUITE,'$proplist','$proplist',[]]}},
+ {?eh,tc_done,{ct_framework,init_per_suite,ok}},
+ {?eh,tc_start,{ct_no_config_SUITE,test_case_1}},
+ {?eh,cth,{empty_cth,pre_init_per_testcase,
+ [test_case_1,'$proplist',[]]}},
+ {?eh,cth,{empty_cth,post_end_per_testcase,
+ [test_case_1,'$proplist',ok,[]]}},
+ {?eh,tc_done,{ct_no_config_SUITE,test_case_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,test_group,'$proplist'}}},
+ {?eh,cth,{empty_cth,pre_init_per_group,
+ [test_group,'$proplist',[]]}},
+ {?eh,cth,{empty_cth,post_init_per_group,
+ [test_group,'$proplist','$proplist',[]]}},
+ {?eh,tc_done,{ct_framework,
+ {init_per_group,test_group,'$proplist'},ok}},
+ {?eh,tc_start,{ct_no_config_SUITE,test_case_2}},
+ {?eh,cth,{empty_cth,pre_init_per_testcase,
+ [test_case_2,'$proplist',[]]}},
+ {?eh,cth,{empty_cth,post_end_per_testcase,
+ [test_case_2,'$proplist',ok,[]]}},
+ {?eh,tc_done,{ct_no_config_SUITE,test_case_2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,test_group,'$proplist'}}},
+ {?eh,cth,{empty_cth,pre_end_per_group,
+ [test_group,'$proplist',[]]}},
+ {?eh,cth,{empty_cth,post_end_per_group,
+ [test_group,'$proplist',ok,[]]}},
+ {?eh,tc_done,{ct_framework,{end_per_group,test_group,'$proplist'},ok}}],
+ {?eh,tc_start,{ct_framework,end_per_suite}},
+ {?eh,cth,{empty_cth,pre_end_per_suite,
+ [ct_no_config_SUITE,'$proplist',[]]}},
+ {?eh,cth,{empty_cth,post_end_per_suite,
+ [ct_no_config_SUITE,'$proplist',ok,[]]}},
+ {?eh,tc_done,{ct_framework,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(data_dir) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,init,[verify_data_dir_cth,[]]}},
+ {?eh,start_info,{1,1,2}},
+ {?eh,tc_start,{ct_framework,init_per_suite}},
+ {?eh,cth,{empty_cth,pre_init_per_suite,
+ [ct_data_dir_SUITE,'$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,cth,{empty_cth,post_init_per_suite,
+ [ct_data_dir_SUITE,'$proplist','$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,tc_done,{ct_framework,init_per_suite,ok}},
+ {?eh,tc_start,{ct_data_dir_SUITE,test_case_1}},
+ {?eh,cth,{empty_cth,pre_init_per_testcase,
+ [test_case_1,'$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,cth,{empty_cth,post_end_per_testcase,
+ [test_case_1,'$proplist',ok,[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,tc_done,{ct_data_dir_SUITE,test_case_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ [{?eh,tc_start,{ct_framework,{init_per_group,test_group,'$proplist'}}},
+ {?eh,cth,{empty_cth,pre_init_per_group,
+ [test_group,'$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,cth,{empty_cth,post_init_per_group,
+ [test_group,'$proplist','$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,tc_done,{ct_framework,
+ {init_per_group,test_group,'$proplist'},ok}},
+ {?eh,tc_start,{ct_data_dir_SUITE,test_case_2}},
+ {?eh,cth,{empty_cth,pre_init_per_testcase,
+ [test_case_2,'$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,cth,{empty_cth,post_end_per_testcase,
+ [test_case_2,'$proplist',ok,[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,tc_done,{ct_data_dir_SUITE,test_case_2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{ct_framework,{end_per_group,test_group,'$proplist'}}},
+ {?eh,cth,{empty_cth,pre_end_per_group,
+ [test_group,'$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,cth,{empty_cth,post_end_per_group,
+ [test_group,'$proplist',ok,[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,tc_done,{ct_framework,{end_per_group,test_group,'$proplist'},ok}}],
+ {?eh,tc_start,{ct_framework,end_per_suite}},
+ {?eh,cth,{empty_cth,pre_end_per_suite,
+ [ct_data_dir_SUITE,'$proplist',[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,cth,{empty_cth,post_end_per_suite,
+ [ct_data_dir_SUITE,'$proplist',ok,[{data_dir_name,"ct_data_dir_SUITE_data"}]]}},
+ {?eh,tc_done,{ct_framework,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_data_dir_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_data_dir_SUITE.erl
new file mode 100644
index 0000000000..66074c20c0
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_data_dir_SUITE.erl
@@ -0,0 +1,67 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_data_dir_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+-define(data_dir_name, atom_to_list(?MODULE)++"_data").
+
+suite() ->
+ [{timetrap, {seconds,1}},
+ {ct_hooks, [verify_data_dir_cth]}].
+
+all() ->
+ [test_case_1, {group,test_group}].
+
+groups() ->
+ [{test_group,[],[test_case_2]}].
+
+init_per_testcase(_, Config) ->
+ check_dirs(Config),
+ Config.
+
+end_per_testcase(_, Config) ->
+ check_dirs(Config),
+ ok.
+
+test_case_1(Config) ->
+ check_dirs(Config),
+ ok.
+
+test_case_2(Config) ->
+ check_dirs(Config),
+ ok.
+
+check_dirs(Config) ->
+ %% check priv_dir
+ PrivDir = proplists:get_value(priv_dir, Config),
+ "log_private" = filename:basename(PrivDir),
+ {ok,_} = file:list_dir(PrivDir),
+
+ %% check data_dir
+ DataDir = proplists:get_value(data_dir, Config),
+ DataDirName = ?data_dir_name,
+ DataDirName = filename:basename(DataDir),
+ ok.
+
+
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl
new file mode 100644
index 0000000000..fb8c420b8e
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl
@@ -0,0 +1,64 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_no_config_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+%%% This suite is used to verify 2 things:
+%%%
+%%% 1) All hook pre/post functions get called, even if no init/end
+%%% config functions exist in the suite (new from ver 1.6.1, R15B01).
+%%%
+%%% 2) The hook functions can read Config list elements, as well as
+%%% required config variables, even if no init/end config
+%%% functions exist.
+
+suite() ->
+ [{timetrap, {seconds,1}},
+ {ct_hooks, [verify_config_cth]},
+ {require,suite_cfg},
+ {default_config,suite_cfg,?MODULE}].
+
+group(test_group) ->
+ [{require,group_cfg},
+ {default_config,group_cfg,test_group}].
+
+test_case_1() ->
+ [{require,test_case_1_cfg},
+ {default_config,test_case_1_cfg,test_case_1}].
+
+test_case_2() ->
+ [{require,test_case_2_cfg},
+ {default_config,test_case_2_cfg,test_case_2}].
+
+all() ->
+ [test_case_1, {group,test_group}].
+
+groups() ->
+ [{test_group,[],[test_case_2]}].
+
+test_case_1(Config) ->
+ ok.
+
+test_case_2(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 7befcfa57c..9ee2a90896 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
@@ -1,277 +1,277 @@
-%%
-%% %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%
-%%
-
-%%% @doc Common Test Example Suite Callback module.
-%%%
-%%% <p>This module gives an example of a common test CTH (Common Test Hook).
-%%% There are many ways to add a CTH to a test run, you can do it either in
-%%% the command line using -ct_hook, in a test spec using
-%%% {ct_hook,M} or in the suite it self by returning ct_hook
-%%% from either suite/0, init_per_suite/1, init_per_group/2 and
-%%% init_per_testcase/2. The scope of the CTH is determined by where is it
-%%% started. If it is started in the command line or test spec then it will
-%%% be stopped at the end of all tests. If it is started in init_per_suite,
-%%% it will be stopped after end_per_suite and so on. See terminate
-%%% documentation for a table describing the scoping machanics.
-%%%
-%%% All of callbacks except init/1 in a CTH are optional.</p>
-
--module(empty_cth).
-
-%% CT Hooks
--export([id/1]).
--export([init/2]).
-
--export([pre_init_per_suite/3]).
--export([post_init_per_suite/4]).
--export([pre_end_per_suite/3]).
--export([post_end_per_suite/4]).
-
--export([pre_init_per_group/3]).
--export([post_init_per_group/4]).
--export([pre_end_per_group/3]).
--export([post_end_per_group/4]).
-
--export([pre_init_per_testcase/3]).
--export([post_end_per_testcase/4]).
-
--export([on_tc_fail/3]).
--export([on_tc_skip/3]).
-
--export([terminate/1]).
-
--include_lib("common_test/src/ct_util.hrl").
--include_lib("common_test/include/ct_event.hrl").
-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 Common Test Example Suite Callback module.
+%%%
+%%% <p>This module gives an example of a common test CTH (Common Test Hook).
+%%% There are many ways to add a CTH to a test run, you can do it either in
+%%% the command line using -ct_hook, in a test spec using
+%%% {ct_hook,M} or in the suite it self by returning ct_hook
+%%% from either suite/0, init_per_suite/1, init_per_group/2 and
+%%% init_per_testcase/2. The scope of the CTH is determined by where is it
+%%% started. If it is started in the command line or test spec then it will
+%%% be stopped at the end of all tests. If it is started in init_per_suite,
+%%% it will be stopped after end_per_suite and so on. See terminate
+%%% documentation for a table describing the scoping machanics.
+%%%
+%%% All of callbacks except init/1 in a CTH are optional.</p>
+
+-module(empty_cth).
+
+%% CT Hooks
+-export([id/1]).
+-export([init/2]).
+
+-export([pre_init_per_suite/3]).
+-export([post_init_per_suite/4]).
+-export([pre_end_per_suite/3]).
+-export([post_end_per_suite/4]).
+
+-export([pre_init_per_group/3]).
+-export([post_init_per_group/4]).
+-export([pre_end_per_group/3]).
+-export([post_end_per_group/4]).
+
+-export([pre_init_per_testcase/3]).
+-export([post_end_per_testcase/4]).
+
+-export([on_tc_fail/3]).
+-export([on_tc_skip/3]).
+
+-export([terminate/1]).
+
+-include_lib("common_test/src/ct_util.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
-type config() :: proplists:proplist().
--type reason() :: term().
--type skip_or_fail() :: {skip, reason()} |
- {auto_skip, reason()} |
- {fail, reason()} |
- {'EXIT',reason()}.
-
--record(state, { id = ?MODULE :: term()}).
-
-%% @doc Always called before any other callback function. Use this to initiate
-%% any common state. It should return an state for this CTH.
+-type reason() :: term().
+-type skip_or_fail() :: {skip, reason()} |
+ {auto_skip, reason()} |
+ {fail, reason()} |
+ {'EXIT',reason()}.
+
+-record(state, { id = ?MODULE :: term()}).
+
+%% @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 :: proplists:proplist()) ->
- {ok, State :: #state{}}.
-init(Id, Opts) ->
- gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, init, [Id, 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.
+ {ok, State :: #state{}}.
+init(Id, Opts) ->
+ gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, init, [Id, 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 :: proplists:proplist()) ->
- Id :: term().
-id(Opts) ->
- gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, id, [Opts]}}),
- now().
-
-%% @doc Called before init_per_suite is called. Note that this callback is
-%% only called if the CTH is added before init_per_suite is run (eg. in a test
-%% specification, suite/0 function etc).
-%% You can change the config in the this function.
--spec pre_init_per_suite(Suite :: atom(),
- Config :: config(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-pre_init_per_suite(Suite,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_init_per_suite,
- [Suite,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after init_per_suite.
-%% you can change the return value in this function.
--spec post_init_per_suite(Suite :: atom(),
- Config :: config(),
- Return :: config() | skip_or_fail(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-post_init_per_suite(Suite,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_init_per_suite,
- [Suite,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called before end_per_suite. The config/state can be changed here,
-%% though it will only affect the *end_per_suite function.
--spec pre_end_per_suite(Suite :: atom(),
- Config :: config() | skip_or_fail(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-pre_end_per_suite(Suite,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_end_per_suite,
- [Suite,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after end_per_suite. Note that the config cannot be
-%% changed here, only the status of the suite.
--spec post_end_per_suite(Suite :: atom(),
- Config :: config(),
- Return :: term(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-post_end_per_suite(Suite,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_end_per_suite,
- [Suite,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called before each init_per_group.
-%% You can change the config in this function.
--spec pre_init_per_group(Group :: atom(),
- Config :: config(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-pre_init_per_group(Group,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_init_per_group,
- [Group,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after each init_per_group.
-%% You can change the return value in this function.
--spec post_init_per_group(Group :: atom(),
- Config :: config(),
- Return :: config() | skip_or_fail(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-post_init_per_group(Group,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_init_per_group,
- [Group,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called after each end_per_group. The config/state can be changed here,
-%% though it will only affect the *end_per_group functions.
--spec pre_end_per_group(Group :: atom(),
- Config :: config() | skip_or_fail(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-pre_end_per_group(Group,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_end_per_group,
- [Group,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after each end_per_group. Note that the config cannot be
-%% changed here, only the status of the group.
--spec post_end_per_group(Group :: atom(),
- Config :: config(),
- Return :: term(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-post_end_per_group(Group,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_end_per_group,
- [Group,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called before each test case.
-%% You can change the config in this function.
--spec pre_init_per_testcase(TC :: atom(),
- Config :: config(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-pre_init_per_testcase(TC,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_init_per_testcase,
- [TC,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after each test case. Note that the config cannot be
-%% changed here, only the status of the test case.
--spec post_end_per_testcase(TC :: atom(),
- Config :: config(),
- Return :: term(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-post_end_per_testcase(TC,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_end_per_testcase,
- [TC,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
-%% post_end_per_group and post_end_per_tc if the suite, group or test case failed.
-%% This function should be used for extra cleanup which might be needed.
-%% It is not possible to modify the config or the status of the test run.
--spec on_tc_fail(TC :: init_per_suite | end_per_suite |
- init_per_group | end_per_group | atom(),
- Reason :: term(), State :: #state{}) ->
- NewState :: #state{}.
-on_tc_fail(TC, Reason, State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, on_tc_fail,
- [TC,Reason,State]}}),
- State.
-
-%% @doc Called when a test case is skipped by either user action
-%% or due to an init function failing. Test case can be
-%% end_per_suite, init_per_group, end_per_group and the actual test cases.
--spec on_tc_skip(TC :: end_per_suite |
- init_per_group | end_per_group | atom(),
- {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} |
- {tc_user_skip, {skipped, Reason :: term()}},
- State :: #state{}) ->
- NewState :: #state{}.
-on_tc_skip(TC, Reason, State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, on_tc_skip,
- [TC,Reason,State]}}),
- State.
-
-%% @doc Called when the scope of the CTH is done, this depends on
-%% when the CTH was specified. This translation table describes when this
-%% function is called.
-%%
-%% | Started in | terminate called |
-%% |---------------------|-------------------------|
-%% | command_line | after all tests are run |
-%% | test spec | after all tests are run |
-%% | suite/0 | after SUITE is done |
-%% | init_per_suite/1 | after SUITE is done |
-%% | init_per_group/2 | after group is done |
-%% |-----------------------------------------------|
-%%
--spec terminate(State :: #state{}) ->
- term().
-terminate(State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, terminate, [State]}}),
- ok.
+ Id :: term().
+id(Opts) ->
+ gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, id, [Opts]}}),
+ now().
+
+%% @doc Called before init_per_suite is called. Note that this callback is
+%% only called if the CTH is added before init_per_suite is run (eg. in a test
+%% specification, suite/0 function etc).
+%% You can change the config in the this function.
+-spec pre_init_per_suite(Suite :: atom(),
+ Config :: config(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+pre_init_per_suite(Suite,Config,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, pre_init_per_suite,
+ [Suite,Config,State]}}),
+ {Config, State}.
+
+%% @doc Called after init_per_suite.
+%% you can change the return value in this function.
+-spec post_init_per_suite(Suite :: atom(),
+ Config :: config(),
+ Return :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+post_init_per_suite(Suite,Config,Return,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_init_per_suite,
+ [Suite,Config,Return,State]}}),
+ {Return, State}.
+
+%% @doc Called before end_per_suite. The config/state can be changed here,
+%% though it will only affect the *end_per_suite function.
+-spec pre_end_per_suite(Suite :: atom(),
+ Config :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+pre_end_per_suite(Suite,Config,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, pre_end_per_suite,
+ [Suite,Config,State]}}),
+ {Config, State}.
+
+%% @doc Called after end_per_suite. Note that the config cannot be
+%% changed here, only the status of the suite.
+-spec post_end_per_suite(Suite :: atom(),
+ Config :: config(),
+ Return :: term(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+post_end_per_suite(Suite,Config,Return,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_end_per_suite,
+ [Suite,Config,Return,State]}}),
+ {Return, State}.
+
+%% @doc Called before each init_per_group.
+%% You can change the config in this function.
+-spec pre_init_per_group(Group :: atom(),
+ Config :: config(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+pre_init_per_group(Group,Config,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, pre_init_per_group,
+ [Group,Config,State]}}),
+ {Config, State}.
+
+%% @doc Called after each init_per_group.
+%% You can change the return value in this function.
+-spec post_init_per_group(Group :: atom(),
+ Config :: config(),
+ Return :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+post_init_per_group(Group,Config,Return,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_init_per_group,
+ [Group,Config,Return,State]}}),
+ {Return, State}.
+
+%% @doc Called after each end_per_group. The config/state can be changed here,
+%% though it will only affect the *end_per_group functions.
+-spec pre_end_per_group(Group :: atom(),
+ Config :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+pre_end_per_group(Group,Config,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, pre_end_per_group,
+ [Group,Config,State]}}),
+ {Config, State}.
+
+%% @doc Called after each end_per_group. Note that the config cannot be
+%% changed here, only the status of the group.
+-spec post_end_per_group(Group :: atom(),
+ Config :: config(),
+ Return :: term(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+post_end_per_group(Group,Config,Return,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_end_per_group,
+ [Group,Config,Return,State]}}),
+ {Return, State}.
+
+%% @doc Called before each test case.
+%% You can change the config in this function.
+-spec pre_init_per_testcase(TC :: atom(),
+ Config :: config(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+pre_init_per_testcase(TC,Config,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, pre_init_per_testcase,
+ [TC,Config,State]}}),
+ {Config, State}.
+
+%% @doc Called after each test case. Note that the config cannot be
+%% changed here, only the status of the test case.
+-spec post_end_per_testcase(TC :: atom(),
+ Config :: config(),
+ Return :: term(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+post_end_per_testcase(TC,Config,Return,State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_end_per_testcase,
+ [TC,Config,Return,State]}}),
+ {Return, State}.
+
+%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% post_end_per_group and post_end_per_tc if the suite, group or test case failed.
+%% This function should be used for extra cleanup which might be needed.
+%% It is not possible to modify the config or the status of the test run.
+-spec on_tc_fail(TC :: init_per_suite | end_per_suite |
+ init_per_group | end_per_group | atom(),
+ Reason :: term(), State :: #state{}) ->
+ NewState :: #state{}.
+on_tc_fail(TC, Reason, State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, on_tc_fail,
+ [TC,Reason,State]}}),
+ State.
+
+%% @doc Called when a test case is skipped by either user action
+%% or due to an init function failing. Test case can be
+%% end_per_suite, init_per_group, end_per_group and the actual test cases.
+-spec on_tc_skip(TC :: end_per_suite |
+ init_per_group | end_per_group | atom(),
+ {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} |
+ {tc_user_skip, {skipped, Reason :: term()}},
+ State :: #state{}) ->
+ NewState :: #state{}.
+on_tc_skip(TC, Reason, State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, on_tc_skip,
+ [TC,Reason,State]}}),
+ State.
+
+%% @doc Called when the scope of the CTH is done, this depends on
+%% when the CTH was specified. This translation table describes when this
+%% function is called.
+%%
+%% | Started in | terminate called |
+%% |---------------------|-------------------------|
+%% | command_line | after all tests are run |
+%% | test spec | after all tests are run |
+%% | suite/0 | after SUITE is done |
+%% | init_per_suite/1 | after SUITE is done |
+%% | init_per_group/2 | after group is done |
+%% |-----------------------------------------------|
+%%
+-spec terminate(State :: #state{}) ->
+ term().
+terminate(State) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, terminate, [State]}}),
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl
new file mode 100644
index 0000000000..f6de69f321
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl
@@ -0,0 +1,130 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(verify_config_cth).
+
+-include_lib("common_test/src/ct_util.hrl").
+
+%% CT Hooks
+-compile(export_all).
+
+-define(val(K, L), proplists:get_value(K, L)).
+
+id(Opts) ->
+ ?MODULE.
+
+init(Id, Opts) ->
+ {ok, State} = empty_cth:init(Id, Opts),
+ {ok, State}.
+
+pre_init_per_suite(Suite, Config, State) ->
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:pre_init_per_suite(Suite,
+ [{pre_init_per_suite,true} | Config],
+ State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ true = ?val(pre_init_per_suite, Return),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:post_init_per_suite(Suite,
+ Config,
+ [{post_init_per_suite,true} | Return],
+ State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ true = ?val(post_init_per_suite, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:pre_end_per_suite(Suite,
+ [{pre_end_per_suite,true} | Config],
+ State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ true = ?val(pre_end_per_suite, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Group,Config,State) ->
+ true = ?val(post_init_per_suite, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:pre_init_per_group(Group,
+ [{pre_init_per_group,true} | Config],
+ State).
+
+post_init_per_group(Group,Config,Return,State) ->
+ true = ?val(pre_init_per_group, Return),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:post_init_per_group(Group,
+ Config,
+ [{post_init_per_group,true} | Return],
+ State).
+
+pre_end_per_group(Group,Config,State) ->
+ true = ?val(post_init_per_group, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:pre_end_per_group(Group,
+ [{pre_end_per_group,true} | Config],
+ State).
+
+post_end_per_group(Group,Config,Return,State) ->
+ true = ?val(pre_end_per_group, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:post_end_per_group(Group,Config,Return,State).
+
+pre_init_per_testcase(TC,Config,State) ->
+ true = ?val(post_init_per_suite, Config),
+ case ?val(name, ?val(tc_group_properties, Config)) of
+ undefined ->
+ ok;
+ _ ->
+ true = ?val(post_init_per_group, Config),
+ test_group = ct:get_config(group_cfg)
+ end,
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ CfgKey = list_to_atom(atom_to_list(TC) ++ "_cfg"),
+ TC = ct:get_config(CfgKey),
+ empty_cth:pre_init_per_testcase(TC,
+ [{pre_init_per_testcase,true} | Config],
+ State).
+
+post_end_per_testcase(TC,Config,Return,State) ->
+ true = ?val(post_init_per_suite, Config),
+ true = ?val(pre_init_per_testcase, Config),
+ case ?val(name, ?val(tc_group_properties, Config)) of
+ undefined ->
+ ok;
+ _ ->
+ true = ?val(post_init_per_group, Config),
+ test_group = ct:get_config(group_cfg)
+ end,
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ CfgKey = list_to_atom(atom_to_list(TC) ++ "_cfg"),
+ TC = ct:get_config(CfgKey),
+ 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/verify_data_dir_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_data_dir_cth.erl
new file mode 100644
index 0000000000..279a04b9a9
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_data_dir_cth.erl
@@ -0,0 +1,95 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(verify_data_dir_cth).
+
+-include_lib("common_test/src/ct_util.hrl").
+
+%% CT Hooks
+-compile(export_all).
+
+-define(val(K, L), proplists:get_value(K, L)).
+
+check_dirs(State,Config) ->
+ DataDirName = ?val(data_dir_name, State),
+ %% check priv_dir
+ PrivDir = proplists:get_value(priv_dir, Config),
+ "log_private" = filename:basename(PrivDir),
+ {ok,_} = file:list_dir(PrivDir),
+
+ %% check data_dir
+ DataDir = proplists:get_value(data_dir, Config),
+ DataDirName = filename:basename(DataDir),
+ ok.
+
+id(_Opts) ->
+ ?MODULE.
+
+init(Id, _Opts) ->
+ {ok, _State} = empty_cth:init(Id, []),
+ {ok, [{data_dir_name,"ct_data_dir_SUITE_data"}]}.
+
+pre_init_per_suite(Suite,Config,State) ->
+ check_dirs(State,Config),
+ empty_cth:pre_init_per_suite(Suite,Config,State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ check_dirs(State,Return),
+ empty_cth:post_init_per_suite(Suite,Config,Return,State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ check_dirs(State,Config),
+ empty_cth:pre_end_per_suite(Suite,Config,State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ check_dirs(State,Config),
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Group,Config,State) ->
+ check_dirs(State,Config),
+ empty_cth:pre_init_per_group(Group,Config,State).
+
+post_init_per_group(Group,Config,Return,State) ->
+ check_dirs(State,Return),
+ empty_cth:post_init_per_group(Group,Config,Return,State).
+
+pre_end_per_group(Group,Config,State) ->
+ check_dirs(State,Config),
+ empty_cth:pre_end_per_group(Group,Config,State).
+
+post_end_per_group(Group,Config,Return,State) ->
+ check_dirs(State,Config),
+ empty_cth:post_end_per_group(Group,Config,Return,State).
+
+pre_init_per_testcase(TC,Config,State) ->
+ check_dirs(State,Config),
+ empty_cth:pre_init_per_testcase(TC,Config,State).
+
+post_end_per_testcase(TC,Config,Return,State) ->
+ check_dirs(State,Config),
+ 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_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index 1471cc1e0c..27243a0067 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -98,7 +98,7 @@ end_per_group(_GroupName, Config) ->
%%--------------------------------------------------------------------
%% TEST CASES
%%--------------------------------------------------------------------
-ct_master_test(Config) when is_list(Config)->
+ct_master_test(Config) when is_list(Config) ->
NodeNames = proplists:get_value(node_names, Config),
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
@@ -106,19 +106,14 @@ ct_master_test(Config) when is_list(Config)->
FileName = filename:join(PrivDir, "ct_master_spec.spec"),
Suites = [master_SUITE],
TSFile = make_spec(DataDir, FileName, NodeNames, Suites, Config),
+
ERPid = ct_test_support:start_event_receiver(Config),
- spawn(ct@ancalagon,
- fun() ->
- dbg:tracer(),dbg:p(all,c),
- dbg:tpl(erlang, spawn_link, 4,x),
- receive ok -> ok end
- end),
- [{TSFile, ok}] = run_test(ct_master_test, FileName, Config),
+ [{TSFile,ok}] = run_test(ct_master_test, FileName, Config),
Events = ct_test_support:get_events(ERPid, Config),
- ct_test_support:log_events(groups_suite_1,
+ ct_test_support:log_events(ct_master_test,
reformat(Events, ?eh),
PrivDir, []),
@@ -134,48 +129,59 @@ ct_master_test(Config) when is_list(Config)->
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
-make_spec(DataDir, FileName, NodeNames, Suites, Config)->
- {ok, HostName} = inet:gethostname(),
+make_spec(DataDir, FileName, NodeNames, Suites, Config) ->
+ {ok,HostName} = inet:gethostname(),
- N = lists:map(fun(NodeName)->
+ N = lists:map(fun(NodeName) ->
{node, NodeName, list_to_atom(atom_to_list(NodeName)++"@"++HostName)}
end,
NodeNames),
- C = lists:map(fun(NodeName)->
- Rnd = random:uniform(2),
- if Rnd == 1->
- {config, NodeName, filename:join(DataDir, "master/config.txt")};
- true->
- {userconfig, NodeName, {ct_config_xml, filename:join(DataDir, "master/config.xml")}}
- end
- end,
- NodeNames),
-
- NS = lists:map(fun(NodeName)->
- {init, NodeName, [
- {node_start, [{startup_functions, []}, {monitor_master, true}]},
- {eval, {erlang, nodes, []}}
- ]
- }
- end,
- NodeNames),
-
+ C = lists:map(
+ fun(NodeName) ->
+ Rnd = random:uniform(2),
+ if Rnd == 1->
+ {config,NodeName,filename:join(DataDir,
+ "master/config.txt")};
+ true ->
+ {userconfig,NodeName,
+ {ct_config_xml,filename:join(DataDir,
+ "master/config.xml")}}
+ end
+ end,
+ NodeNames),
+
+ CM = [{config,master,filename:join(DataDir,"master/config.txt")}],
+
+ NS = lists:map(
+ fun(NodeName) ->
+ {init,NodeName,[
+ {node_start,[{startup_functions,[]},
+ {monitor_master,true}]},
+ {eval,{erlang,nodes,[]}}
+ ]
+ }
+ end,
+ NodeNames),
+
S = [{suites, NodeNames, filename:join(DataDir, "master"), Suites}],
-
+
PrivDir = ?config(priv_dir, Config),
- LD = lists:map(fun(NodeName)->
- {logdir, NodeName, get_log_dir(os:type(),PrivDir, NodeName)}
- end,
- NodeNames) ++ [{logdir, master, PrivDir}],
+
+ LD = lists:map(
+ fun(NodeName) ->
+ {logdir,NodeName,get_log_dir(os:type(),PrivDir, NodeName)}
+ end,
+ NodeNames) ++ [{logdir,master,PrivDir}],
+
EvHArgs = [{cbm,ct_test_support},{trace_level,?config(trace_level,Config)}],
EH = [{event_handler,master,[?eh],EvHArgs}],
-
+
Include = [{include,filename:join([DataDir,"master/include"])}],
+
+ ct_test_support:write_testspec(N++Include++EH++C++CM++S++LD++NS, FileName).
- 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);
@@ -188,8 +194,15 @@ get_log_dir(_,PrivDir,NodeName) ->
file:make_dir(LogDir),
LogDir.
-run_test(_Name, FileName, Config)->
- [{FileName, ok}] = ct_test_support:run(ct_master, run, [FileName], Config).
+run_test(_Name, FileName, Config) ->
+ %% run the test twice, using different html versions
+ [{FileName,ok}] = ct_test_support:run({ct_master,run,[FileName]},
+ [{ct_master,basic_html,[true]}],
+ Config),
+ timer:sleep(5000),
+ [{FileName,ok}] = ct_test_support:run({ct_master,run,[FileName]},
+ [{ct_master,basic_html,[false]}],
+ Config).
reformat(Events, EH) ->
ct_test_support:reformat(Events, EH).
@@ -220,5 +233,5 @@ add_host(NodeName) ->
{ok, HostName} = inet:gethostname(),
list_to_atom(atom_to_list(NodeName)++"@"++HostName).
-expected_events(_)->
+expected_events(_) ->
[].
diff --git a/lib/common_test/test/ct_misc_1_SUITE.erl b/lib/common_test/test/ct_misc_1_SUITE.erl
index cb17af9ab5..d2318de445 100644
--- a/lib/common_test/test/ct_misc_1_SUITE.erl
+++ b/lib/common_test/test/ct_misc_1_SUITE.erl
@@ -106,7 +106,7 @@ beam_me_up(Config) when is_list(Config) ->
{Opts,ERPid} = setup([{suite,Suites},{auto_compile,false}], Config),
- ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ {_Ok,_Fail,_Skip} = ct_test_support:run(ct, run_test, [Opts], Config),
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(beam_me_up,
diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl
new file mode 100644
index 0000000000..e6e8d5b09c
--- /dev/null
+++ b/lib/common_test/test/ct_netconfc_SUITE.erl
@@ -0,0 +1,124 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_netconfc_SUITE
+%%%
+%%% Description:
+%%% Test ct_netconfc module
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_netconfc_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ default
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+default(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "netconfc1_SUITE"),
+ CfgFile = filename:join(DataDir, "netconfc1.cfg"),
+ {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile},
+ {label,default}], Config),
+
+ ok = execute(default, Opts, ERPid, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name,Config),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test,Config) ->
+ {module,_} = code:load_abs(filename:join(?config(data_dir,Config),
+ netconfc1_SUITE)),
+ TCs = netconfc1_SUITE:all(),
+ code:purge(netconfc1_SUITE),
+ code:delete(netconfc1_SUITE),
+
+ OneTest =
+ [{?eh,start_logging,{'DEF','RUNDIR'}}] ++
+ [{?eh,tc_done,{netconfc1_SUITE,TC,ok}} || TC <- TCs] ++
+ [{?eh,stop_logging,[]}],
+
+ %% 2 tests (ct:run_test + script_start) is default
+ OneTest ++ OneTest.
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg
new file mode 100644
index 0000000000..6466571623
--- /dev/null
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{netconf1,[{ssh,"localhost"},
+ {port,2060},
+ {user,"xxx"},
+ {password,"xxx"}]}.
+{ct_conn_log,[{ct_netconfc,[{log_type,pretty}]}]}. %overrides args to cth_conn_log
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
new file mode 100644
index 0000000000..79768a9a6a
--- /dev/null
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -0,0 +1,1130 @@
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% File: ct_netconfc_SUITE.erl
+%%
+%% Description:
+%% This file contains the test cases for the ct_netconfc API.
+%%
+%% @author Support
+%% @doc Netconf Client Interface.
+%% @end
+%%----------------------------------------------------------------------
+%%----------------------------------------------------------------------
+-module(netconfc1_SUITE).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/src/ct_netconfc.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-compile(export_all).
+
+%% Default timetrap timeout (set in init_per_testcase).
+-define(default_timeout, ?t:minutes(1)).
+
+-define(NS,ns).
+-define(LOCALHOST, "127.0.0.1").
+-define(SSH_PORT, 2060).
+
+-define(DEFAULT_SSH_OPTS,[{ssh,?LOCALHOST},
+ {port,?SSH_PORT},
+ {user,"xxx"},
+ {password,"xxx"}]).
+-define(DEFAULT_SSH_OPTS(Dir), ?DEFAULT_SSH_OPTS++[{user_dir,Dir}]).
+
+-define(ok,ok).
+
+suite() ->
+ [{ct_hooks, [{cth_conn_log,
+ [{ct_netconfc,[{log_type,html}, %will be overwritten by config
+ {hosts,[my_named_connection,netconf1]}]
+ }]
+ }]
+ }].
+
+all() ->
+ case os:find_executable("ssh") of
+ false ->
+ {skip, "SSH not installed on host"};
+ _ ->
+ [hello,
+ hello_from_server_first,
+ hello_named,
+ hello_configured,
+ hello_configured_extraopts,
+ hello_required,
+ hello_required_exists,
+ hello_global_pwd,
+ hello_no_session_id,
+ hello_incomp_base_vsn,
+ hello_no_base_cap,
+ hello_no_caps,
+ no_server_hello,
+ no_client_hello,
+ get_session_id,
+ get_capabilities,
+ faulty_user,
+ faulty_passwd,
+ faulty_port,
+ no_host,
+ no_port,
+ invalid_opt,
+ get,
+ get_xpath,
+ get_config,
+ get_config_xpath,
+ edit_config,
+ copy_config,
+ delete_config,
+ lock,
+ unlock,
+ kill_session,
+ get_no_such_client,
+ action,
+ send_any_rpc,
+ send_any,
+ hide_password,
+ not_proper_xml,
+ prefixed_namespace,
+ receive_chunked_data,
+ timeout_receive_chunked_data,
+ close_while_waiting_for_chunked_data,
+ connection_crash,
+ get_event_streams,
+ create_subscription,
+ receive_event]
+ end.
+
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_testcase(_Case, Config) ->
+ ets:delete_all_objects(ns_tab),
+ Dog = test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+init_per_suite(Config) ->
+ case catch {crypto:start(), ssh:start()} of
+ {ok, ok} ->
+ {ok, _} = get_id_keys(Config),
+ make_dsa_files(Config),
+ Server = ?NS:start(?config(data_dir,Config)),
+ [{server,Server}|Config];
+ _ ->
+ {skip, "Crypto and/or SSH could not be started!"}
+ end.
+
+end_per_suite(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ?NS:stop(?config(server,Config)),
+ ssh:stop(),
+ crypto:stop(),
+ remove_id_keys(PrivDir),
+ Config.
+
+hello(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hello_from_server_first(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:hello(1),
+ {ok,Client} = ct_netconfc:only_open(?DEFAULT_SSH_OPTS(DataDir)),
+ ct:sleep(500),
+ ?NS:expect(hello),
+ ?ok = ct_netconfc:hello(Client),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hello_named(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(any_name,DataDir),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hello_configured() ->
+ [{require, netconf1}].
+hello_configured(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_configured_success(netconf1,DataDir),
+ ?NS:expect_do_reply('close-session',close,ok),
+ {error, {no_such_name,netconf1}} = ct_netconfc:close_session(netconf1),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hello_configured_extraopts() ->
+ [{require, netconf1}].
+hello_configured_extraopts(Config) ->
+ DataDir = ?config(data_dir,Config),
+ %% Test that the cofiguration overwrites the ExtraOpts parameter
+ %% to ct_netconfc:open/2.
+ {ok,Client} = open_configured_success(netconf1,DataDir,[{password,"faulty"}]),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hello_required() ->
+ [{require, my_named_connection, netconf1}].
+hello_required(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,_Client} = open_configured_success(my_named_connection,DataDir),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(my_named_connection),
+ ok.
+
+hello_required_exists() ->
+ [{require, my_named_connection, netconf1}].
+hello_required_exists(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,_Client1} = open_configured_success(my_named_connection,DataDir),
+
+ %% Check that same name can not be used twice
+ {error,{connection_exists,_Client1}} =
+ ct_netconfc:open(my_named_connection,[{user_dir,DataDir}]),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(my_named_connection),
+
+ %% Then check that it can be used again after the first is closed
+ {ok,_Client2} = open_configured_success(my_named_connection,DataDir),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(my_named_connection),
+ ok.
+
+hello_global_pwd(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir,[{user,"any-user"},
+ {password,"global-xxx"}]),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hello_no_session_id(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:hello(no_session_id),
+ ?NS:expect(hello),
+ {error,{incorrect_hello,no_session_id_found}} = open(DataDir),
+ ok.
+
+hello_incomp_base_vsn(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:hello(1,{base,"1.1"}),
+ ?NS:expect(hello),
+ {error,{incompatible_base_capability_vsn,"1.1"}} = open(DataDir),
+ ok.
+
+hello_no_base_cap(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:hello(1,no_base),
+ ?NS:expect(hello),
+ {error,{incorrect_hello,no_base_capability_found}} = open(DataDir),
+ ok.
+
+hello_no_caps(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:hello(1,no_caps),
+ ?NS:expect(hello),
+ {error,{incorrect_hello,capabilities_not_found}} = open(DataDir),
+ ok.
+
+no_server_hello(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:expect(hello),
+ {error,{hello_session_failed,timeout}} = open(DataDir,[{timeout,2000}]),
+ ok.
+
+no_client_hello(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?NS:hello(1),
+ {ok,Client} = ct_netconfc:only_open(?DEFAULT_SSH_OPTS(DataDir)),
+
+ %% Allow server hello to arrive
+ ct:sleep(500),
+
+ %% Tell server to receive a get request and then die without
+ %% replying since no hello has been received. (is this correct
+ %% behavoiur??)
+ ?NS:expect_do(get,close),
+ {error,closed} = ct_netconfc:get(Client,whatever),
+ ok.
+
+get_session_id(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ 1 = ct_netconfc:get_session_id(Client),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+get_capabilities(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ Caps = ct_netconfc:get_capabilities(Client),
+ BaseCap = ?NETCONF_BASE_CAP ++ ?NETCONF_BASE_CAP_VSN,
+ [BaseCap,"urn:ietf:params:netconf:capability:writable-running:1.0" |_] = Caps,
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+faulty_user(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {error,{ssh,could_not_connect_to_server,
+ "Unable to connect using the available authentication methods"}} =
+ open(DataDir,[{user,"yyy"}]),
+ ok.
+
+faulty_passwd(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {error,{ssh,could_not_connect_to_server,
+ "Unable to connect using the available authentication methods"}} =
+ open(DataDir,[{password,"yyy"}]),
+ ok.
+
+faulty_port(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {error,{ssh,could_not_connect_to_server,econnrefused}} =
+ open(DataDir,[{port,2062}]),
+ ok.
+
+no_host(Config) ->
+ DataDir = ?config(data_dir,Config),
+ Opts = lists:keydelete(ssh,1,?DEFAULT_SSH_OPTS(DataDir)),
+ {error,no_host_address} = ct_netconfc:open(Opts),
+ ok.
+
+no_port(Config) ->
+ DataDir = ?config(data_dir,Config),
+ Opts = lists:keydelete(port,1,?DEFAULT_SSH_OPTS(DataDir)),
+ {error,no_port} = ct_netconfc:open(Opts),
+ ok.
+
+invalid_opt(Config) ->
+ DataDir = ?config(data_dir,Config),
+ Opts1 = ?DEFAULT_SSH_OPTS(DataDir) ++ [{timeout,invalidvalue}],
+ {error,{invalid_option,{timeout,invalidvalue}}} = ct_netconfc:open(Opts1),
+ Opts2 = ?DEFAULT_SSH_OPTS(DataDir) ++ [{some_other_opt,true}],
+ {error,{invalid_option,{some_other_opt,true}}} = ct_netconfc:open(Opts2),
+ ok.
+
+get(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ ?NS:expect_reply('get',{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+get_xpath(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ ?NS:expect_reply({'get',xpath},{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client,{xpath,"/server"}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+get_config(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ ?NS:expect_reply('get-config',{data,Data}),
+ {ok,Data} = ct_netconfc:get_config(Client,running,
+ {server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+get_config_xpath(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ ?NS:expect_reply({'get-config',xpath},{data,Data}),
+ {ok,Data} = ct_netconfc:get_config(Client,running,{xpath,"/server"}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+edit_config(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_reply('edit-config',ok),
+ ?ok = ct_netconfc:edit_config(Client,running,
+ {server,[{xmlns,"myns"}],
+ [{name,["myserver"]}]}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+copy_config(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_reply('copy-config',ok),
+ ?ok = ct_netconfc:copy_config(Client,startup,running),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+delete_config(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_reply('delete-config',ok),
+ ?ok = ct_netconfc:delete_config(Client,startup),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+lock(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_reply('lock',ok),
+ ?ok = ct_netconfc:lock(Client,running),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+unlock(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_reply('unlock',ok),
+ ?ok = ct_netconfc:unlock(Client,running),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+kill_session(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ ?NS:hello(2),
+ ?NS:expect(hello),
+ {ok,_OtherClient} = open(DataDir),
+
+ ?NS:expect_do_reply('kill-session',{kill,2},ok),
+ ?ok = ct_netconfc:kill_session(Client,2),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+
+ ok.
+
+get_no_such_client(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ case ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}) of
+ {error,no_such_client} ->
+ ok;
+ {error,closed} ->
+ %% Means that the Client process was not terminated before the call.
+ %% Give it one more go.
+ {error,no_such_client} =
+ ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]})
+ end,
+ ok.
+
+action(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{myactionreturn,[{xmlns,"myns"}],["value"]}],
+ ?NS:expect_reply(action,{data,Data}),
+ {ok,Data} = ct_netconfc:action(Client,{myaction,[{xmlns,"myns"}],[]}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+send_any_rpc(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ GetConf = {'get-config',
+ [{source,["running"]},
+ {filter,[{type,"subtree"}],
+ [{server,[{xmlns,"myns"}],[]}]}]},
+ ?NS:expect_reply('get-config',{data,Data}),
+ [{data,?NETCONF_NAMESPACE_ATTR,Data}] = ct_netconfc:send_rpc(Client,GetConf),
+
+ EditConf = {'edit-config',
+ [{target,["running"]},
+ {config,[{server,[{xmlns,"myns"}],
+ [{name,["myserver"]}]}]}]},
+ ?NS:expect_reply('edit-config',ok),
+ [{ok,?NETCONF_NAMESPACE_ATTR,[]}] = ct_netconfc:send_rpc(Client,EditConf),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+send_any(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ %% Correct get-config rpc
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ RpcAttr1 = ?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}],
+ RpcGetConf = {rpc,RpcAttr1,
+ [{'get-config',
+ [{source,["running"]},
+ {filter,[{type,"subtree"}],
+ [{server,[{xmlns,"myns"}],[]}]}]}]},
+ ?NS:expect_reply('get-config',{data,Data}),
+ {'rpc-reply',RpcAttr1,[{data,_,Data}]} = ct_netconfc:send(Client,RpcGetConf),
+
+ %% Correct edit-config rpc
+ RpcAttr2 = ?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"2"}],
+ RpcEditConf = {rpc,RpcAttr2,
+ [{'edit-config',
+ [{target,["running"]},
+ {config,[{server,[{xmlns,"myns"}],
+ [{name,["myserver"]}]}]}]}]},
+ ?NS:expect_reply('edit-config',ok),
+ {'rpc-reply',RpcAttr2,[{ok,_,[]}]} = ct_netconfc:send(Client,RpcEditConf),
+
+ %% Send any data
+ ?NS:expect_reply(any,{ok,[],[]}),
+ {ok,_,[]} = ct_netconfc:send(Client,{any,[],[]}),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+hide_password(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Password = "my_very_secret_password",
+ Data = [{passwords,[{xmlns,"myns"}],
+ [{password,[{xmlns,"pwdns"}],[Password]},
+ {password,[],[Password]}]}],
+ ?NS:expect_reply('get',{data,Data}),
+ ct:capture_start(), % in case of html logging
+ {ok,Data} = ct_netconfc:get(Client,{passwords,[{xmlns,"myns"}],[]}),
+ ct:capture_stop(),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+
+ Log = filename:join(?config(priv_dir,Config),"hide_password-netconf.txt"),
+
+ Text =
+ case file:read_file(Log) of
+ {ok,Bin} ->
+ Bin;
+ _NoLog ->
+ %% Assume html logging
+ list_to_binary(ct:capture_get())
+ end,
+
+ nomatch = binary:match(Text,list_to_binary(Password)),
+
+ ok.
+
+not_proper_xml(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ NS = list_to_binary(?NETCONF_NAMESPACE),
+ NotProper = <<"<rpc-reply message-id=\"1\" xmlns=\"",
+ NS/binary,"\"><data></rpc-reply>">>,
+ ?NS:expect_reply('get',NotProper),
+ {error,{failed_to_parse_received_data,_}} =
+ ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+prefixed_namespace(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ NS = list_to_binary(?NETCONF_NAMESPACE),
+
+ %% Test that data element can be properly decoded and that
+ %% prefixed namespace attributes (exepct the netconf namespace)
+ %% are forwarded to the content of the data element - i.e. that
+ %% the xmlns:my is forwarded from the rpc-reply element to the
+ %% server element below.
+ Data = <<"<nc:rpc-reply message-id=\"1\" xmlns:nc=\"",
+ NS/binary,"\" xmlns:my=\"myns\"><nc:data><my:server>",
+ "<my:name my:lang=\"en\">myserver</my:name></my:server>"
+ "</nc:data></nc:rpc-reply>">>,
+ ?NS:expect_reply('get',Data),
+ {ok,[{'my:server',[{'xmlns:my',"myns"}],
+ [{'my:name',[{'my:lang',"en"}],["myserver"]}]}]} =
+ ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}),
+
+ Ok = <<"<nc:rpc-reply message-id=\"2\" xmlns:nc=\"",
+ NS/binary,"\"><nc:ok/></nc:rpc-reply>">>,
+ ?NS:expect_reply('edit-config',Ok),
+ ?ok = ct_netconfc:edit_config(Client,running,
+ {server,[{xmlns,"myns"}],
+ [{name,["myserver"]}]}),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+%% Test that the client can parse data which is received in chunks,
+%% i.e. when the complete rpc-reply is not contained in one single ssh
+%% data message.
+receive_chunked_data(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ %% Construct the data to return from netconf server
+ Data = [{servers,[{xmlns,"myns"}],
+ [{server,[],[{name,[],["server0"]}]},
+ {server,[],[{name,[],["server1"]}]},
+ {server,[],[{name,[],["server2"]}]},
+ {server,[],[{name,[],["server3"]}]},
+ {server,[],[{name,[],["server4"]}]},
+ {server,[],[{name,[],["server5"]}]},
+ {server,[],[{name,[],["server6"]}]},
+ {server,[],[{name,[],["server7"]}]},
+ {server,[],[{name,[],["server8"]}]},
+ {server,[],[{name,[],["server9"]}]}]
+ }],
+ Rpc = {'rpc-reply',?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}],
+ [{data,Data}]},
+ Xml = list_to_binary(xmerl:export_simple_element(Rpc,xmerl_xml)),
+ Netconf =
+ <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
+ Xml/binary,"\n",?END_TAG/binary>>,
+
+ %% Split the data in some chunks
+ PartLength = size(Netconf) div 3,
+ <<Part1:PartLength/binary,Part2:PartLength/binary,Part3:PartLength/binary,
+ Part4/binary>> = Netconf,
+
+ %% Spawn a process which will wait a bit for the client to send
+ %% the request (below), then order the server to the chunks of the
+ %% rpc-reply one by one.
+ spawn(fun() -> timer:sleep(500),?NS:hupp(send,Part1),
+ timer:sleep(100),?NS:hupp(send,Part2),
+ timer:sleep(100),?NS:hupp(send,Part3),
+ timer:sleep(100),?NS:hupp(send,Part4)
+ end),
+
+ %% Order server to expect a get - then the process above will make
+ %% sure the rpc-reply is sent.
+ ?NS:expect('get'),
+ {ok,Data} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+%% Same as receive_chunked_data, but timeout waiting for last part.
+timeout_receive_chunked_data(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ %% Construct the data to return from netconf server
+ Data = [{servers,[{xmlns,"myns"}],
+ [{server,[],[{name,[],["server0"]}]},
+ {server,[],[{name,[],["server1"]}]},
+ {server,[],[{name,[],["server2"]}]},
+ {server,[],[{name,[],["server3"]}]},
+ {server,[],[{name,[],["server4"]}]},
+ {server,[],[{name,[],["server5"]}]},
+ {server,[],[{name,[],["server6"]}]},
+ {server,[],[{name,[],["server7"]}]},
+ {server,[],[{name,[],["server8"]}]},
+ {server,[],[{name,[],["server9"]}]}]
+ }],
+ Rpc = {'rpc-reply',?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}],
+ [{data,Data}]},
+ Xml = list_to_binary(xmerl:export_simple_element(Rpc,xmerl_xml)),
+ Netconf =
+ <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
+ Xml/binary,"\n",?END_TAG/binary>>,
+
+ %% Split the data in some chunks
+ PartLength = size(Netconf) div 3,
+ <<Part1:PartLength/binary,Part2:PartLength/binary,_Part3:PartLength/binary,
+ _Part4/binary>> = Netconf,
+
+ %% Spawn a process which will wait a bit for the client to send
+ %% the request (below), then order the server to the chunks of the
+ %% rpc-reply one by one.
+ spawn(fun() -> timer:sleep(500),?NS:hupp(send,Part1),
+ timer:sleep(100),?NS:hupp(send,Part2)
+ end),
+
+ %% Order server to expect a get - then the process above will make
+ %% sure the rpc-reply is sent - but only a part of it - then timeout.
+ ?NS:expect('get'),
+ {error,timeout} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},2000),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+%% Same as receive_chunked_data, but timeout waiting for last part.
+close_while_waiting_for_chunked_data(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ %% Construct the data to return from netconf server
+ Data = [{servers,[{xmlns,"myns"}],
+ [{server,[],[{name,[],["server0"]}]},
+ {server,[],[{name,[],["server1"]}]},
+ {server,[],[{name,[],["server2"]}]},
+ {server,[],[{name,[],["server3"]}]},
+ {server,[],[{name,[],["server4"]}]},
+ {server,[],[{name,[],["server5"]}]},
+ {server,[],[{name,[],["server6"]}]},
+ {server,[],[{name,[],["server7"]}]},
+ {server,[],[{name,[],["server8"]}]},
+ {server,[],[{name,[],["server9"]}]}]
+ }],
+ Rpc = {'rpc-reply',?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}],
+ [{data,Data}]},
+ Xml = list_to_binary(xmerl:export_simple_element(Rpc,xmerl_xml)),
+ Netconf =
+ <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
+ Xml/binary,"\n",?END_TAG/binary>>,
+
+ %% Split the data in some chunks
+ PartLength = size(Netconf) div 3,
+ <<Part1:PartLength/binary,Part2:PartLength/binary,_Part3:PartLength/binary,
+ _Part4/binary>> = Netconf,
+
+ %% Spawn a process which will wait a bit for the client to send
+ %% the request (below), then order the server to the chunks of the
+ %% rpc-reply one by one.
+ spawn(fun() -> timer:sleep(500),?NS:hupp(send,Part1),
+ timer:sleep(100),?NS:hupp(send,Part2),
+ timer:sleep(100),?NS:hupp(kill)
+ end),
+
+ %% Order server to expect a get - then the process above will make
+ %% sure the rpc-reply is sent - but only a part of it - then close.
+ ?NS:expect('get'),
+ {error,closed} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},2000),
+ ok.
+
+connection_crash(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+
+ %% Test that if the test survives killing the connection
+ %% process. Earlier this caused ct_util_server to terminate, and
+ %% this aborting the complete test run.
+ spawn(fun() -> timer:sleep(500),exit(Client,kill) end),
+ ?NS:expect(get),
+ {error,{closed,killed}}=ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}),
+ ok.
+
+get_event_streams(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ StreamNames = ["NETCONF","stream1","stream2"],
+ Streams = [{N,[{description,"descr of " ++ N}]} || N <- StreamNames],
+ StreamsXml = [{stream,[{name,[N]}|[{Tag,[Value]} || {Tag,Value} <- Data]]}
+ || {N,Data} <- Streams],
+ ReplyData = [{netconf,?NETMOD_NOTIF_NAMESPACE_ATTR,[{streams,StreamsXml}]}],
+ ?NS:expect_reply('get',{data,ReplyData}),
+ {ok,Streams} = ct_netconfc:get_event_streams(Client,StreamNames),
+
+ ?NS:expect_reply('get',{data,ReplyData}),
+ {ok,Streams} = ct_netconfc:get_event_streams(Client,StreamNames,5000),
+
+ ?NS:expect('get'),
+ {error,timeout} = ct_netconfc:get_event_streams(Client,100),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
+create_subscription(Config) ->
+ DataDir = ?config(data_dir,Config),
+
+ %% All defaults
+ {ok,Client1} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream]},ok),
+ ?ok = ct_netconfc:create_subscription(Client1),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client1),
+
+ %% All defaults with timeout
+ {ok,Client1a} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream]},ok),
+ ?ok = ct_netconfc:create_subscription(Client1a,5000),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client1a),
+
+ %% All defaults timing out
+ {ok,Client1b} = open_success(DataDir),
+ ?NS:expect({'create-subscription',[stream]}),
+ {error,timeout} = ct_netconfc:create_subscription(Client1b,100),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client1b),
+
+ %% Stream
+ {ok,Client2} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream]},ok),
+ Stream = "some_stream",
+ ?ok = ct_netconfc:create_subscription(Client2,Stream),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client2),
+
+ %% Filter
+ {ok,Client3} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,filter]},ok),
+ Filter = {notification,?NETMOD_NOTIF_NAMESPACE_ATTR,
+ [eventTime]},
+ ?ok = ct_netconfc:create_subscription(Client3,Filter),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client3),
+
+ %% Filter with timeout
+ {ok,Client3a} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,filter]},ok),
+ ?ok = ct_netconfc:create_subscription(Client3a,Filter,5000),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client3a),
+
+ %% Filter timing out
+ {ok,Client3b} = open_success(DataDir),
+ ?NS:expect({'create-subscription',[stream,filter]}),
+ {error,timeout}=ct_netconfc:create_subscription(Client3b,Filter,100),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client3b),
+
+ %% Stream and filter
+ {ok,Client4} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,filter]},ok),
+ ?ok = ct_netconfc:create_subscription(Client4,Stream,Filter),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client4),
+
+ %% Start/stop time
+ {ok,Client5} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,startTime,stopTime]},ok),
+ StartTime = xs_datetime({D,{H,M,S}}= calendar:local_time()),
+ StopTime = xs_datetime({D,{H+2,M,S}}),
+ ?ok = ct_netconfc:create_subscription(Client5,StartTime,StopTime),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client5),
+
+ %% Start/stop time with timeout
+ {ok,Client5a} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,startTime,stopTime]},ok),
+ ?ok = ct_netconfc:create_subscription(Client5a,StartTime,StopTime,5000),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client5a),
+
+ %% Start/stop time timing out
+ {ok,Client5b} = open_success(DataDir),
+ ?NS:expect({'create-subscription',[stream,startTime,stopTime]}),
+ {error,timeout} =
+ ct_netconfc:create_subscription(Client5b,StartTime,StopTime,100),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client5b),
+
+ %% Stream and start/stop time
+ {ok,Client6} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,startTime,stopTime]},ok),
+ ?ok = ct_netconfc:create_subscription(Client6,Stream,StartTime,StopTime),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client6),
+
+ %% Filter and start/stop time
+ {ok,Client7} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,filter,startTime,stopTime]},
+ ok),
+ ?ok = ct_netconfc:create_subscription(Client7,Filter,
+ StartTime,StopTime),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client7),
+
+ %% Stream, filter and start/stop time
+ {ok,Client8} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream,filter,startTime,stopTime]},
+ ok),
+ ?ok = ct_netconfc:create_subscription(Client8,Stream,Filter,
+ StartTime,StopTime),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client8),
+
+ ok.
+
+receive_event(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ ?NS:expect_reply({'create-subscription',[stream]},ok),
+ ?ok = ct_netconfc:create_subscription(Client),
+
+ ?NS:hupp(send_event),
+
+ receive
+ %% Matching ?NS:make_msg(event)
+ {notification,?NETCONF_NOTIF_NAMESPACE_ATTR,
+ [{eventTime,[],[_Time]},
+ {event,[{xmlns,"http://my.namespaces.com/event"}],
+ [{severity,_,_},
+ {description,_,_}]}]} ->
+ ok;
+ Other ->
+ ct:fail({got_unexpected_while_waiting_for_event, Other})
+ after 3000 ->
+ ct:fail(timeout_waiting_for_event)
+ end,
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+
+ ok.
+
+%%%-----------------------------------------------------------------
+
+break(_Config) ->
+ test_server:break("break test case").
+
+br() ->
+ test_server:break("").
+
+%%%-----------------------------------------------------------------
+%% Open a netconf session which is not specified in a config file
+open_success(Dir) ->
+ open_success(Dir,[]).
+
+%% Open a netconf session which is not specified in a config file, and
+%% give som extra options in addition to the test defaults.
+open_success(Dir,ExtraOpts) when is_list(Dir), is_list(ExtraOpts) ->
+ ?NS:hello(1), % tell server to send hello with session id 1
+ ?NS:expect(hello), % tell server to expect a hello message from client
+ open(Dir,ExtraOpts);
+
+%% Open a named netconf session which is not specified in a config file
+open_success(KeyOrName,Dir) when is_atom(KeyOrName), is_list(Dir) ->
+ ?NS:hello(1),
+ ?NS:expect(hello),
+ ct_netconfc:open(KeyOrName,?DEFAULT_SSH_OPTS(Dir)).
+
+open(Dir) ->
+ open(Dir,[]).
+open(Dir,ExtraOpts) ->
+ Opts = lists:ukeymerge(1,lists:keysort(1,ExtraOpts),
+ lists:keysort(1,?DEFAULT_SSH_OPTS(Dir))),
+ ct_netconfc:open(Opts).
+
+%%%-----------------------------------------------------------------
+%%% Open a netconf session which is specified in a config file
+%%% KeyOrName is the config key (server_id()) or name given in a
+%%% require statement (target_name()).
+open_configured_success(KeyOrName,Dir) when is_atom(KeyOrName) ->
+ open_configured_success(KeyOrName,Dir,[]).
+open_configured_success(KeyOrName,Dir,ExtraOpts) when is_atom(KeyOrName) ->
+ ?NS:hello(1),
+ ?NS:expect(hello),
+ ct_netconfc:open(KeyOrName,[{user_dir,Dir}|ExtraOpts]).
+
+%%%-----------------------------------------------------------------
+%%% Convert erlang datetime to the simplest variant of XML dateTime
+xs_datetime({{Y,M,D},{H,Mi,S}}) ->
+ lists:flatten(
+ io_lib:format("~p-~s-~sT~s:~s:~s",[Y,pad(M),pad(D),pad(H),pad(Mi),pad(S)])).
+
+pad(I) when I<10 ->
+ "0"++integer_to_list(I);
+pad(I) ->
+ integer_to_list(I).
+
+
+%%%-----------------------------------------------------------------
+%%% BEGIN SSH key management
+%% copy private keys to given dir from ~/.ssh
+get_id_keys(Config) ->
+ DstDir = ?config(priv_dir, Config),
+ 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 later on. Use make_dsa_files instead.
+remove_id_keys(Config) ->
+ Dir = ?config(priv_dir, Config),
+ file:delete(filename:join(Dir, "id_rsa")),
+ file:delete(filename:join(Dir, "id_dsa")).
+
+
+make_dsa_files(Config) ->
+ make_dsa_files(Config, rfc4716_public_key).
+make_dsa_files(Config, Type) ->
+ {DSA, EncodedKey} = 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),
+
+ 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.
+
+%%--------------------------------------------------------------------
+%% 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)}.
+
+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}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 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.
+
+copyfile(SrcDir, DstDir, Fn) ->
+ file:copy(filename:join(SrcDir, Fn),
+ filename:join(DstDir, Fn)).
+
+%%% END SSH key management
+%%%-----------------------------------------------------------------
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
new file mode 100644
index 0000000000..665b0e556c
--- /dev/null
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
@@ -0,0 +1,506 @@
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 netconf server used for testing of netconfc
+-module(ns).
+
+%-compile(export_all).
+-include_lib("common_test/src/ct_netconfc.hrl").
+
+
+%%%-----------------------------------------------------------------
+%%% API
+-export([start/1,
+ stop/1,
+ hello/1,
+ hello/2,
+ expect/1,
+ expect_reply/2,
+ expect_do/2,
+ expect_do_reply/3,
+ hupp/1,
+ hupp/2]).
+
+%%%-----------------------------------------------------------------
+%%% ssh_channel callbacks
+-export([init/1,
+ terminate/2,
+ handle_ssh_msg/2,
+ handle_msg/2]).
+
+%%%-----------------------------------------------------------------
+%% Server specifications
+-define(SERVER_DATA_NAMESPACE, "ClientTest").
+-define(CAPABILITIES,?CAPABILITIES_VSN("1.0")).
+-define(CAPABILITIES_VSN(Vsn),
+ [
+ ?NETCONF_BASE_CAP ++ Vsn,
+ "urn:ietf:params:netconf:capability:writable-running:1.0",
+ "urn:ietf:params:netconf:capability:candidate:1.0",
+ "urn:ietf:params:netconf:capability:confirmed-commit:1.0",
+ "urn:ietf:params:netconf:capability:rollback-on-error:1.0",
+ "urn:ietf:params:netconf:capability:startup:1.0",
+ "urn:ietf:params:netconf:capability:url:1.0",
+ "urn:ietf:params:netconf:capability:xpath:1.0",
+ "urn:ietf:params:netconf:capability:notification:1.0",
+ "urn:ietf:params:netconf:capability:interleave:1.0",
+ ?ACTION_NAMESPACE,
+ ?SERVER_DATA_NAMESPACE
+ ]).
+-define(SSH_PORT, 2060).
+-define(ssh_config(Dir),[{port, ?SSH_PORT},
+ {interface, {127,0,0,1}},
+ {system_dir, Dir},
+ {user_dir, Dir},
+ {user_passwords, [{"xxx","xxx"}]},
+ {password, "global-xxx"}]).
+
+%% Some help for debugging
+%-define(dbg(F,A),io:format(F,A)).
+-define(dbg(F,A),ok).
+-define(dbg_event(Event,Expect),
+ ?dbg("Event: ~p~nExpected: ~p~n",[Event,Expect])).
+
+%% State
+-record(session, {cb,
+ connection,
+ buffer = <<>>,
+ session_id}).
+
+
+%%%-----------------------------------------------------------------
+%%% API
+
+%% Start the netconf server and use the given directory as system_dir
+%% and user_dir
+start(Dir) ->
+ spawn(fun() -> init_server(Dir) end).
+
+%% Stop the netconf server
+stop(Pid) ->
+ Pid ! {stop,self()},
+ receive stopped -> ok end.
+
+%% Set the session id for the hello message.
+%% If this is not called prior to starting the session, no hello
+%% message will be sent.
+%% 'Stuff' indicates some special handling to e.g. provoke error cases
+hello(SessionId) ->
+ hello(SessionId,undefined).
+hello(SessionId,Stuff) ->
+ insert(hello,{SessionId,Stuff}).
+
+%% Tell server to expect the given message without doing any further
+%% actions. To be called directly before sending a request.
+expect(Expect) ->
+ expect_do_reply(Expect,undefined,undefined).
+
+%% Tell server to expect the given message and reply with the give
+%% reply. To be called directly before sending a request.
+expect_reply(Expect,Reply) ->
+ expect_do_reply(Expect,undefined,Reply).
+
+%% Tell server to expect the given message and perform an action. To
+%% be called directly before sending a request.
+expect_do(Expect,Do) ->
+ expect_do_reply(Expect,Do,undefined).
+
+%% Tell server to expect the given message, perform an action and
+%% reply with the given reply. To be called directly before sending a
+%% request.
+expect_do_reply(Expect,Do,Reply) ->
+ add_expect({Expect,Do,Reply}).
+
+%% Hupp the server - i.e. tell it to do something -
+%% e.g. hupp(send_event) will cause send_event(State) to be called on
+%% the session channel process.
+hupp(send_event) ->
+ hupp(send,[make_msg(event)]);
+hupp(kill) ->
+ hupp(fun hupp_kill/1,[]).
+
+hupp(send,Data) ->
+ hupp(fun hupp_send/2,[Data]);
+hupp(Fun,Args) when is_function(Fun) ->
+ [{_,Pid}] = lookup(channel_process),
+ Pid ! {hupp,Fun,Args}.
+
+%%%-----------------------------------------------------------------
+%%% Main loop of the netconf server
+init_server(Dir) ->
+ ets:new(ns_tab,[set,named_table,public]),
+ Config = ?ssh_config(Dir),
+ {_,Host} = lists:keyfind(interface, 1, Config),
+ {_,Port} = lists:keyfind(port, 1, Config),
+ Opts = lists:filter(fun({Key,_}) ->
+ lists:member(Key,[system_dir,
+ password,
+ user_passwords,
+ pwdfun])
+ end,
+ Config),
+ {ok, Daemon} =
+ ssh:daemon(Host, Port,
+ [{subsystems,[{"netconf",{?MODULE,[]}}]}
+ |Opts]),
+ loop(Daemon).
+
+loop(Daemon) ->
+ receive
+ {stop,From} ->
+ ssh:stop_daemon(Daemon),
+ From ! stopped
+ end.
+
+%%----------------------------------------------------------------------
+%% Behaviour callback functions (ssh_channel)
+%%----------------------------------------------------------------------
+init([]) ->
+ {ok, undefined}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+handle_ssh_msg({ssh_cm,CM,{data, Ch, _Type = 0, Data}}, State) ->
+ %% erlang:display({self(),data,CM,Ch,State}),
+ data_for_channel(CM, Ch, Data, State);
+handle_ssh_msg({ssh_cm,CM,{closed, Ch}}, State) ->
+ %% erlang:display({self(),closed,CM,Ch,State}),
+ stop_channel(CM, Ch, State);
+handle_ssh_msg({ssh_cm,CM,{eof, Ch}}, State) ->
+ %% erlang:display({self(),eof,CM,Ch,State}),
+ data_for_channel(CM,Ch, <<>>, State).
+
+
+handle_msg({'EXIT', _Pid, _Reason}, State) ->
+ {ok, State};
+handle_msg({ssh_channel_up,Ch,CM},undefined) ->
+ %% erlang:display({self(),up,CM,Ch}),
+ ConnRef = {CM,Ch},
+ SessionId = maybe_hello(ConnRef),
+ insert(channel_process,self()), % used to hupp the server
+ {ok, #session{connection = ConnRef,
+ session_id = SessionId}};
+handle_msg({hupp,Fun,Args},State) ->
+ {ok,apply(Fun,Args ++ [State])}.
+
+data_for_channel(CM, Ch, Data, State) ->
+ try data(Data, State) of
+ {ok, NewState} ->
+ case erase(stop) of
+ true ->
+ stop_channel(CM, Ch, NewState);
+ _ ->
+ {ok, NewState}
+ end
+ catch
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ error_logger:error_report([{?MODULE, data_for_channel},
+ {request, Data},
+ {reason, {Class, Reason}},
+ {stacktrace, Stacktrace}]),
+ stop_channel(CM, Ch, State)
+ end.
+
+data(Data, State = #session{connection = ConnRef,
+ buffer = Buffer}) ->
+ AllData = <<Buffer/binary,Data/binary>>,
+ case find_endtag(AllData) of
+ {ok,Msgs,Rest} ->
+ [check_expected(ConnRef,Msg) || Msg <- Msgs],
+ {ok,State#session{buffer=Rest}};
+ need_more ->
+ {ok,State#session{buffer=AllData}}
+ end.
+
+stop_channel(CM, Ch, State) ->
+ ssh:close(CM),
+ {stop, Ch, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% Functions to trigg via hupp/1:
+
+%% Send data spontaneously - e.g. an event
+hupp_send(Data,State = #session{connection = ConnRef}) ->
+ send(ConnRef,Data),
+ State.
+hupp_kill(State = #session{connection = ConnRef}) ->
+ kill(ConnRef),
+ State.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+
+
+%%% Send ssh data to the client
+send({CM,Ch},Data) ->
+ ssh_connection:send(CM, Ch, Data).
+
+%%% Kill ssh connection
+kill({CM,_Ch}) ->
+ ssh:close(CM).
+
+add_expect(Add) ->
+ case lookup(expect) of
+ [] ->
+ insert(expect,[Add]);
+ [{expect,First}] ->
+ insert(expect,First ++ [Add])
+ end,
+ ok.
+
+insert(Key,Value) ->
+ ets:insert(ns_tab,{Key,Value}).
+lookup(Key) ->
+ ets:lookup(ns_tab,Key).
+
+maybe_hello(ConnRef) ->
+ case lookup(hello) of
+ [{hello,{SessionId,Stuff}}] ->
+ %% erlang:display({SessionId,Stuff}),
+ ets:delete(ns_tab,hello),
+ insert({session,SessionId},ConnRef),
+ reply(ConnRef,{hello,SessionId,Stuff}),
+ SessionId;
+ [] ->
+ undefined
+ end.
+
+find_endtag(Data) ->
+ case binary:split(Data,[?END_TAG],[global]) of
+ [Data] ->
+ need_more;
+ Msgs ->
+ {ok,lists:sublist(Msgs,length(Msgs)-1),lists:last(Msgs)}
+ end.
+
+check_expected(ConnRef,Msg) ->
+ case lookup(expect) of
+ [{expect,[{Expect,Do,Reply}|Rest]}] ->
+ insert(expect,Rest),
+ %% erlang:display({got,io_lib:format("~s",[Msg])}),
+ %% erlang:display({expected,Expect}),
+ match(Msg,Expect),
+ do(ConnRef, Do),
+ reply(ConnRef,Reply);
+ Expected ->
+ exit({error,{got_unexpected,Msg,Expected}})
+ end.
+
+match(Msg,Expect) ->
+ ?dbg("Match: ~p~n",[Msg]),
+ {ok,ok,<<>>} = xmerl_sax_parser:stream(Msg,[{event_fun,fun event/3},
+ {event_state,Expect}]).
+
+event(Event,_Loc,Expect) ->
+ ?dbg_event(Event,Expect),
+ event(Event,Expect).
+
+event(startDocument,Expect) -> match(Expect);
+event({startElement,_,Name,_,Attrs},[{se,Name}|Match]) ->
+ msg_id(Name,Attrs),
+ Match;
+event({startElement,_,Name,_,Attrs},[ignore,{se,Name}|Match]) ->
+ msg_id(Name,Attrs),
+ Match;
+event({startElement,_,Name,_,Attrs},[{se,Name,As}|Match]) ->
+ msg_id(Name,Attrs),
+ match_attrs(Name,As,Attrs),
+ Match;
+event({startElement,_,Name,_,Attrs},[ignore,{se,Name,As}|Match]) ->
+ msg_id(Name,Attrs),
+ match_attrs(Name,As,Attrs),
+ Match;
+event({startPrefixMapping,_,Ns},[{ns,Ns}|Match]) -> Match;
+event({startPrefixMapping,_,Ns},[ignore,{ns,Ns}|Match]) -> Match;
+event({endPrefixMapping,_},Match) -> Match;
+event({endElement,_,Name,_},[{ee,Name}|Match]) -> Match;
+event({endElement,_,Name,_},[ignore,{ee,Name}|Match]) -> Match;
+event(endDocument,Match) when Match==[]; Match==[ignore] -> ok;
+event(_,[ignore|_]=Match) -> Match;
+event(Event,Match) -> throw({nomatch,{Event,Match}}).
+
+msg_id("rpc",Attrs) ->
+ case lists:keyfind("message-id",3,Attrs) of
+ {_,_,_,Str} -> put(msg_id,Str);
+ false -> erase(msg_id)
+ end;
+msg_id(_,_) ->
+ ok.
+
+match_attrs(Name,[{Key,Value}|As],Attrs) ->
+ case lists:keyfind(atom_to_list(Key),3,Attrs) of
+ {_,_,_,Value} -> match_attrs(Name,As,Attrs);
+ false -> throw({missing_attr,Key,Name,Attrs});
+ _ -> throw({faulty_attr_value,Key,Name,Attrs})
+ end;
+match_attrs(_,[],_) ->
+ ok.
+
+do(ConnRef, close) ->
+ ets:match_delete(ns_tab,{{session,'_'},ConnRef}),
+ put(stop,true);
+do(_ConnRef, {kill,SessionId}) ->
+ case lookup({session,SessionId}) of
+ [{_,Owner}] ->
+ ets:delete(ns_tab,{session,SessionId}),
+ kill(Owner);
+ _ ->
+ exit({no_session_to_kill,SessionId})
+ end;
+do(_, undefined) ->
+ ok.
+
+reply(_,undefined) ->
+ ?dbg("no reply~n",[]),
+ ok;
+reply(ConnRef,Reply) ->
+ ?dbg("Reply: ~p~n",[Reply]),
+ send(ConnRef, make_msg(Reply)).
+
+from_simple(Simple) ->
+ list_to_binary(xmerl:export_simple_element(Simple,xmerl_xml)).
+
+xml(Content) ->
+ <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
+ Content/binary,"\n",?END_TAG/binary>>.
+
+rpc_reply(Content) when is_binary(Content) ->
+ MsgId = case erase(msg_id) of
+ undefined -> <<>>;
+ Id -> list_to_binary([" message-id=\"",Id,"\""])
+ end,
+ <<"<rpc-reply xmlns=\"",?NETCONF_NAMESPACE,"\"",MsgId/binary,">\n",
+ Content/binary,"\n</rpc-reply>">>;
+rpc_reply(Content) ->
+ rpc_reply(list_to_binary(Content)).
+
+session_id(no_session_id) ->
+ <<>>;
+session_id(SessionId0) ->
+ SessionId = list_to_binary(integer_to_list(SessionId0)),
+ <<"<session-id>",SessionId/binary,"</session-id>\n">>.
+
+capabilities(undefined) ->
+ CapsXml = list_to_binary([["<capability>",C,"</capability>\n"]
+ || C <- ?CAPABILITIES]),
+ <<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>;
+capabilities({base,Vsn}) ->
+ CapsXml = list_to_binary([["<capability>",C,"</capability>\n"]
+ || C <- ?CAPABILITIES_VSN(Vsn)]),
+ <<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>;
+capabilities(no_base) ->
+ [_|Caps] = ?CAPABILITIES,
+ CapsXml = list_to_binary([["<capability>",C,"</capability>\n"] || C <- Caps]),
+ <<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>;
+capabilities(no_caps) ->
+ <<>>.
+
+%%%-----------------------------------------------------------------
+%%% Match received netconf message from the client. Add a new clause
+%%% for each new message to recognize. The clause argument shall match
+%%% the Expect argument in expect/1, expect_reply/2 or
+%%% expect_do_reply/3.
+%%%
+%%% match(term()) -> [Match].
+%%% Match = ignore | {se,Name} | {se,Name,Attrs} | {ee,Name} | {ns,Namespace}
+%%% Name = string()
+%%% Attrs = [{atom(),string()}]
+%%% Namespace = string()
+%%%
+%%% 'se' means start element, 'ee' means end element - i.e. to match
+%%% an XML element you need one 'se' entry and one 'ee' entry with the
+%%% same name in the match list.
+match(hello) ->
+ [ignore,{se,"hello"},ignore,{ee,"hello"},ignore];
+match('close-session') ->
+ [ignore,{se,"rpc"},{se,"close-session"},
+ {ee,"close-session"},{ee,"rpc"},ignore];
+match('edit-config') ->
+ [ignore,{se,"rpc"},{se,"edit-config"},{se,"target"},ignore,{ee,"target"},
+ {se,"config"},ignore,{ee,"config"},{ee,"edit-config"},{ee,"rpc"},ignore];
+match('get') ->
+ match({get,subtree});
+match({'get',FilterType}) ->
+ [ignore,{se,"rpc"},{se,"get"},{se,"filter",[{type,atom_to_list(FilterType)}]},
+ ignore,{ee,"filter"},{ee,"get"},{ee,"rpc"},ignore];
+match('get-config') ->
+ match({'get-config',subtree});
+match({'get-config',FilterType}) ->
+ [ignore,{se,"rpc"},{se,"get-config"},{se,"source"},ignore,{ee,"source"},
+ {se,"filter",[{type,atom_to_list(FilterType)}]},ignore,{ee,"filter"},
+ {ee,"get-config"},{ee,"rpc"},ignore];
+match('copy-config') ->
+ [ignore,{se,"rpc"},{se,"copy-config"},{se,"target"},ignore,{ee,"target"},
+ {se,"source"},ignore,{ee,"source"},{ee,"copy-config"},{ee,"rpc"},ignore];
+match('delete-config') ->
+ [ignore,{se,"rpc"},{se,"delete-config"},{se,"target"},ignore,{ee,"target"},
+ {ee,"delete-config"},{ee,"rpc"},ignore];
+match('lock') ->
+ [ignore,{se,"rpc"},{se,"lock"},{se,"target"},ignore,{ee,"target"},
+ {ee,"lock"},{ee,"rpc"},ignore];
+match('unlock') ->
+ [ignore,{se,"rpc"},{se,"unlock"},{se,"target"},ignore,{ee,"target"},
+ {ee,"unlock"},{ee,"rpc"},ignore];
+match('kill-session') ->
+ [ignore,{se,"rpc"},{se,"kill-session"},{se,"session-id"},ignore,
+ {ee,"session-id"},{ee,"kill-session"},{ee,"rpc"},ignore];
+match(action) ->
+ [ignore,{se,"rpc"},{ns,?ACTION_NAMESPACE},{se,"action"},{se,"data"},ignore,
+ {ee,"data"},{ee,"action"},{ee,"rpc"},ignore];
+match({'create-subscription',Content}) ->
+ [ignore,{se,"rpc"},{ns,?NETCONF_NOTIF_NAMESPACE},
+ {se,"create-subscription"}] ++
+ lists:flatmap(fun(X) ->
+ [{se,atom_to_list(X)},ignore,{ee,atom_to_list(X)}]
+ end, Content) ++
+ [{ee,"create-subscription"},{ee,"rpc"},ignore];
+match(any) ->
+ [ignore].
+
+
+
+%%%-----------------------------------------------------------------
+%%% Make message to send to the client.
+%%% Add a new clause for each new message that shall be sent. The
+%%% clause shall match the Reply argument in expect_reply/2 or
+%%% expect_do_reply/3.
+make_msg({hello,SessionId,Stuff}) ->
+ SessionIdXml = session_id(SessionId),
+ CapsXml = capabilities(Stuff),
+ xml(<<"<hello xmlns=\"",?NETCONF_NAMESPACE,"\">\n",CapsXml/binary,
+ SessionIdXml/binary,"</hello>">>);
+make_msg(ok) ->
+ xml(rpc_reply("<ok/>"));
+make_msg({data,Data}) ->
+ xml(rpc_reply(from_simple({data,Data})));
+make_msg(event) ->
+ xml(<<"<notification xmlns=\"",?NETCONF_NOTIF_NAMESPACE,"\">"
+ "<eventTime>2012-06-14T14:50:54+02:00</eventTime>"
+ "<event xmlns=\"http://my.namespaces.com/event\">"
+ "<severity>major</severity>"
+ "<description>Something terrible happened</description>"
+ "</event>"
+ "</notification>">>);
+make_msg(Xml) when is_binary(Xml) ->
+ xml(Xml);
+make_msg(Simple) when is_tuple(Simple) ->
+ xml(from_simple(Simple)).
diff --git a/lib/common_test/test/ct_priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE.erl
new file mode 100644
index 0000000000..426b2d9a55
--- /dev/null
+++ b/lib/common_test/test/ct_priv_dir_SUITE.erl
@@ -0,0 +1,277 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_priv_dir_SUITE
+%%%
+%%% Description:
+%%% Test that it works to use the create_priv_dir option.
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_priv_dir_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ default,
+ auto_per_run,
+ auto_per_tc,
+ manual_per_tc,
+ spec_default,
+ spec_auto_per_run,
+ spec_auto_per_run,
+ spec_manual_per_tc
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+default(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "priv_dir_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{testcase,default},
+ {label,default}], Config),
+ ok = execute(default, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+auto_per_run(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "priv_dir_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{testcase,default},
+ {label,auto_per_run},
+ {create_priv_dir,auto_per_run}], Config),
+ ok = execute(auto_per_run, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+auto_per_tc(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "priv_dir_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{testcase,auto_per_tc},
+ {label,auto_per_tc},
+ {create_priv_dir,auto_per_tc}], Config),
+ ok = execute(auto_per_tc, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+manual_per_tc(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "priv_dir_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{testcase,manual_per_tc},
+ {label,manual_per_tc},
+ {create_priv_dir,manual_per_tc}], Config),
+ ok = execute(manual_per_tc, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+spec_default(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Spec = filename:join(DataDir, "default.spec"),
+ {Opts,ERPid} = setup([{spec,Spec},
+ {label,spec_default}], Config),
+ ok = execute(spec_default, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+spec_auto_per_run(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Spec = filename:join(DataDir, "auto_per_run.spec"),
+ {Opts,ERPid} = setup([{spec,Spec},
+ {label,spec_auto_per_run}], Config),
+ ok = execute(spec_auto_per_run, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+spec_auto_per_tc(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Spec = filename:join(DataDir, "auto_per_tc.spec"),
+ {Opts,ERPid} = setup([{spec,Spec},
+ {label,spec_auto_per_tc}], Config),
+ ok = execute(spec_auto_per_tc, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+spec_manual_per_tc(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Spec = filename:join(DataDir, "manual_per_tc.spec"),
+ {Opts,ERPid} = setup([{spec,Spec},
+ {label,spec_manual_per_tc}], Config),
+ ok = execute(spec_manual_per_tc, Opts, ERPid, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+
+test_events(DEF) when DEF == default ; DEF == auto_per_run ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{priv_dir_SUITE,init_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{priv_dir_SUITE,default}},
+ {?eh,tc_done,{priv_dir_SUITE,default,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{priv_dir_SUITE,end_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(auto_per_tc) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{priv_dir_SUITE,init_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{priv_dir_SUITE,auto_per_tc}},
+ {?eh,tc_done,{priv_dir_SUITE,auto_per_tc,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{priv_dir_SUITE,end_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(manual_per_tc) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{priv_dir_SUITE,init_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{priv_dir_SUITE,manual_per_tc}},
+ {?eh,tc_done,{priv_dir_SUITE,manual_per_tc,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{priv_dir_SUITE,end_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(SPECDEF) when SPECDEF == spec_default ;
+ SPECDEF == spec_auto_per_run ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{priv_dir_SUITE,init_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{priv_dir_SUITE,default}},
+ {?eh,tc_done,{priv_dir_SUITE,default,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{priv_dir_SUITE,end_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(spec_auto_per_tc) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{priv_dir_SUITE,init_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{priv_dir_SUITE,auto_per_tc}},
+ {?eh,tc_done,{priv_dir_SUITE,auto_per_tc,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{priv_dir_SUITE,end_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(spec_manual_per_tc) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{priv_dir_SUITE,init_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{priv_dir_SUITE,manual_per_tc}},
+ {?eh,tc_done,{priv_dir_SUITE,manual_per_tc,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{priv_dir_SUITE,end_per_suite}},
+ {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}].
+
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec
new file mode 100644
index 0000000000..4dde0ed1f4
--- /dev/null
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec
@@ -0,0 +1,5 @@
+{create_priv_dir, auto_per_run}.
+
+{alias, curr, "./"}.
+
+{cases, curr, priv_dir_SUITE, default}. \ No newline at end of file
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec
new file mode 100644
index 0000000000..c265500865
--- /dev/null
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec
@@ -0,0 +1,5 @@
+{create_priv_dir, auto_per_tc}.
+
+{alias, curr, "./"}.
+
+{cases, curr, priv_dir_SUITE, auto_per_tc}. \ No newline at end of file
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/default.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/default.spec
new file mode 100644
index 0000000000..2f053e792f
--- /dev/null
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/default.spec
@@ -0,0 +1,3 @@
+{alias, curr, "./"}.
+
+{cases, curr, priv_dir_SUITE, default}. \ No newline at end of file
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec
new file mode 100644
index 0000000000..4f98734d5f
--- /dev/null
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec
@@ -0,0 +1,5 @@
+{create_priv_dir, manual_per_tc}.
+
+{alias, curr, "./"}.
+
+{cases, curr, priv_dir_SUITE, manual_per_tc}. \ No newline at end of file
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
new file mode 100644
index 0000000000..7704a29768
--- /dev/null
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
@@ -0,0 +1,137 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(priv_dir_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [].
+
+default(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ "log_private" = filename:basename(PrivDir),
+ {ok,_} = file:list_dir(PrivDir).
+
+auto_per_tc(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ["log_private",_] = string:tokens(filename:basename(PrivDir), "."),
+ {ok,_} = file:list_dir(PrivDir).
+
+manual_per_tc(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ["log_private",_] = string:tokens(filename:basename(PrivDir), "."),
+ {error,_} = file:list_dir(PrivDir),
+ ok = ct:make_priv_dir(),
+ {ok,_} = file:list_dir(PrivDir).
+
diff --git a/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl
index fb8d31edd4..4c5b880e39 100644
--- a/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl
@@ -1,11 +1,21 @@
-%%%-------------------------------------------------------------------
-%%% @author Peter Andersson <[email protected]>
-%%% @copyright (C) 2010, Peter Andersson
-%%% @doc
-%%%
-%%% @end
-%%% Created : 11 Aug 2010 by Peter Andersson <[email protected]>
-%%%-------------------------------------------------------------------
+%%
+%% %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(repeat_1_SUITE).
-compile(export_all).
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 4471915e69..8e4852369d 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
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,39 +228,42 @@ test_events(ts_if_1) ->
{failed,{error,{suite0_failed,{exited,suite0_goes_boom}}}}}},
{?eh,tc_start,{ct_framework,error_in_suite}},
- {?eh,test_stats,{3,6,{3,7}}},
+ {?eh,test_stats,{3,5,{4,7}}},
{?eh,tc_start,{ct_framework,error_in_suite}},
- {?eh,test_stats,{3,7,{3,7}}},
+ {?eh,test_stats,{3,5,{5,7}}},
{?eh,tc_start,{ts_if_5_SUITE,init_per_suite}},
{?eh,tc_done,{ts_if_5_SUITE,init_per_suite,
{skipped,{require_failed_in_suite0,{not_available,undef_variable}}}}},
{?eh,tc_auto_skip,{ts_if_5_SUITE,my_test_case,
{require_failed_in_suite0,{not_available,undef_variable}}}},
- {?eh,test_stats,{3,7,{3,8}}},
+ {?eh,test_stats,{3,5,{5,8}}},
{?eh,tc_auto_skip,{ts_if_5_SUITE,end_per_suite,
{require_failed_in_suite0,{not_available,undef_variable}}}},
- {?eh,tc_start,{ts_if_6_SUITE,tc1}},
- {?eh,tc_done,{ts_if_6_SUITE,tc1,{failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}},
- {?eh,test_stats,{3,7,{4,8}}},
+ {?eh,tc_start,{ct_framework,init_per_suite}},
+ {?eh,tc_done,{ct_framework,init_per_suite,
+ {failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}},
+ {?eh,tc_auto_skip,{ts_if_6_SUITE,tc1,
+ {failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}},
+ {?eh,test_stats,{3,5,{5,9}}},
{?eh,tc_start,{ts_if_7_SUITE,tc1}},
{?eh,tc_done,{ts_if_7_SUITE,tc1,ok}},
- {?eh,test_stats,{4,7,{4,8}}},
+ {?eh,test_stats,{4,5,{5,9}}},
{?eh,tc_start,{ts_if_8_SUITE,tc1}},
{?eh,tc_done,{ts_if_8_SUITE,tc1,{failed,{error,failed_on_purpose}}}},
- {?eh,test_stats,{4,8,{4,8}}},
+ {?eh,test_stats,{4,6,{5,9}}},
{?eh,tc_user_skip,{skipped_by_spec_1_SUITE,all,"should be skipped"}},
- {?eh,test_stats,{4,8,{5,8}}},
+ {?eh,test_stats,{4,6,{6,9}}},
{?eh,tc_start,{skipped_by_spec_2_SUITE,init_per_suite}},
{?eh,tc_done,{skipped_by_spec_2_SUITE,init_per_suite,ok}},
{?eh,tc_user_skip,{skipped_by_spec_2_SUITE,tc1,"should be skipped"}},
- {?eh,test_stats,{4,8,{6,8}}},
+ {?eh,test_stats,{4,6,{7,9}}},
{?eh,tc_start,{skipped_by_spec_2_SUITE,end_per_suite}},
{?eh,tc_done,{skipped_by_spec_2_SUITE,end_per_suite,ok}},
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 bda7d91161..06fa6ac638 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
@@ -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
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 6df02d12b7..80cca4a1cc 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +29,14 @@
-export([init_per_suite/1, init_per_suite/2, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2,
write_testspec/2, write_testspec/3,
- run/2, run/4, get_opts/1, wait_for_ct_stop/1]).
+ run/2, run/3, 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/4,
join_abs_dirs/2]).
+-export([ct_test_halt/1]).
+
-include_lib("kernel/include/file.hrl").
%%%-----------------------------------------------------------------
@@ -223,14 +225,15 @@ get_opts(Config) ->
%%%-----------------------------------------------------------------
%%%
-run(Opts, Config) ->
+run(Opts, Config) when is_list(Opts) ->
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]),
-
+ CtRunTestResult = rpc:call(CTNode, ct, run_test, [Opts]),
+ test_server:format(Level, "~n[RUN #1] Got return value ~p~n",
+ [CtRunTestResult]),
case rpc:call(CTNode, erlang, whereis, [ct_util_server]) of
undefined ->
ok;
@@ -242,26 +245,59 @@ run(Opts, Config) ->
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]),
- test_server:format(Level, "[RUN #2] Calling ct_run:script_start() on ~p~n", [CTNode]),
- Result2 = rpc:call(CTNode, ct_run, script_start, []),
- case {Result1,Result2} of
- {ok,ok} ->
+ Opts1 = [{halt_with,{?MODULE,ct_test_halt}} | Opts],
+ test_server:format(Level, "Saving start opts on ~p: ~p~n",
+ [CTNode, Opts1]),
+ rpc:call(CTNode, application, set_env,
+ [common_test, run_test_start_opts, Opts1]),
+ test_server:format(Level, "[RUN #2] Calling ct_run:script_start() on ~p~n",
+ [CTNode]),
+ ExitStatus = rpc:call(CTNode, ct_run, script_start, []),
+ test_server:format(Level, "[RUN #2] Got exit status value ~p~n",
+ [ExitStatus]),
+ case {CtRunTestResult,ExitStatus} of
+ {{_Ok,Failed,{_UserSkipped,_AutoSkipped}},1} when Failed > 0 ->
ok;
- {E,_} when E =/= ok ->
- E;
- {_,E} when E =/= ok ->
- E
+ {{_Ok,0,{_UserSkipped,AutoSkipped}},ExitStatus} when AutoSkipped > 0 ->
+ case proplists:get_value(exit_status, Opts1) of
+ ignore_config when ExitStatus == 1 ->
+ {error,{wrong_exit_status,ExitStatus}};
+ _ ->
+ ok
+ end;
+ {{error,_}=Error,ExitStatus} ->
+ if ExitStatus /= 2 ->
+ {error,{wrong_exit_status,ExitStatus}};
+ ExitStatus == 2 ->
+ Error
+ end;
+ {{_Ok,0,{_UserSkipped,_AutoSkipped}},0} ->
+ ok;
+ Unexpected ->
+ {error,{unexpected_return_value,Unexpected}}
end.
run(M, F, A, Config) ->
+ run({M,F,A}, [], Config).
+
+run({M,F,A}, InitCalls, 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",
+ lists:foreach(
+ fun({IM,IF,IA}) ->
+ test_server:format(Level, "~nInit call ~w:~w(~p) on ~p...~n",
+ [IM, IF, IA, CTNode]),
+ Result = rpc:call(CTNode, IM, IF, IA),
+ test_server:format(Level, "~n...with result: ~p~n", [Result])
+ end, InitCalls),
+ test_server:format(Level, "~nStarting test with ~w:~w(~p) on ~p~n",
[M, F, A, CTNode]),
rpc:call(CTNode, M, F, A).
+%% this is the last function that ct_run:script_start() calls, so the
+%% return value here is what rpc:call/4 above returns
+ct_test_halt(ExitStatus) ->
+ ExitStatus.
%%%-----------------------------------------------------------------
%%% wait_for_ct_stop/1
@@ -1001,6 +1037,12 @@ result_match({SkipOrFail,{ErrorInd,{Why,'_'}}},
result_match({SkipOrFail,{ErrorInd,{EMod,EFunc,{Why,'_'}}}},
{SkipOrFail,{ErrorInd,{EMod,EFunc,{Why,_Stack}}}}) ->
true;
+result_match({failed,{timetrap_timeout,{'$approx',Num}}},
+ {failed,{timetrap_timeout,Value}}) ->
+ if Value >= trunc(Num-0.02*Num),
+ Value =< trunc(Num+0.02*Num) -> true;
+ true -> false
+ end;
result_match(Result, Result) ->
true;
result_match(_, _) ->
diff --git a/lib/common_test/test/ct_testspec_1_SUITE.erl b/lib/common_test/test/ct_testspec_1_SUITE.erl
index b6dcf63fdf..693e8c6567 100644
--- a/lib/common_test/test/ct_testspec_1_SUITE.erl
+++ b/lib/common_test/test/ct_testspec_1_SUITE.erl
@@ -621,7 +621,9 @@ setup_and_execute(TCName, TestSpec, Config) ->
ok = ct_test_support:run(Opts, Config),
TestSpec1 = [{logdir,proplists:get_value(logdir,Opts)},
{label,proplists:get_value(label,TestTerms)} | TestSpec],
- ok = ct_test_support:run(ct, run_testspec, [TestSpec1], Config),
+ {_Ok,_Failed,{_USkipped,_ASkipped}} =
+ ct_test_support:run(ct, run_testspec, [TestSpec1], Config),
+
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(TCName,
diff --git a/lib/common_test/test/ct_testspec_2_SUITE.erl b/lib/common_test/test/ct_testspec_2_SUITE.erl
new file mode 100644
index 0000000000..411529b52a
--- /dev/null
+++ b/lib/common_test/test/ct_testspec_2_SUITE.erl
@@ -0,0 +1,759 @@
+%%
+%% %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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_testspec_2_SUITE
+%%%
+%%% Description:
+%%% Test test specifications
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_testspec_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/src/ct_util.hrl").
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%% suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [basic_compatible_no_nodes,
+ basic_compatible_nodes,
+ unknown_terms,
+ no_merging,
+ multiple_specs,
+ misc_config_terms,
+ define_names_1].
+
+
+%%--------------------------------------------------------------------
+%% VALID TEST SPEC TERMS (R15B02):
+%%
+%% {node,3}
+%% {cover,2}
+%% {cover,3}
+%% {config,2}
+%% {config,3}
+%% {config,4}
+%% {userconfig,2}
+%% {userconfig,3}
+%% {alias,3}
+%% {merge_tests,2}
+%% {logdir,2}
+%% {logdir,3}
+%% {logopts,2}
+%% {logopts,3}
+%% {basic_html,2}
+%% {basic_html,3}
+%% {verbosity,2}
+%% {verbosity,3}
+%% {silent_connections,2}
+%% {silent_connections,3}
+%% {label,2}
+%% {label,3}
+%% {event_handler,2}
+%% {event_handler,3}
+%% {event_handler,4}
+%% {ct_hooks,2}
+%% {ct_hooks,3}
+%% {enable_builtin_hooks,2}
+%% {release_shell,2}
+%% {multiply_timetraps,2}
+%% {multiply_timetraps,3}
+%% {scale_timetraps,2}
+%% {scale_timetraps,3}
+%% {include,2}
+%% {include,3}
+%% {auto_compile,2}
+%% {auto_compile,3}
+%% {stylesheet,2}
+%% {stylesheet,3}
+%% {suites,3}
+%% {suites,4}
+%% {groups,4}
+%% {groups,5}
+%% {groups,6}
+%% {cases,4}
+%% {cases,5}
+%% {skip_suites,4}
+%% {skip_suites,5}
+%% {skip_groups,5}
+%% {skip_groups,6}
+%% {skip_groups,7}
+%% {skip_cases,5}
+%% {skip_cases,6}
+%% {create_priv_dir,2}
+%%
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+basic_compatible_no_nodes(_Config) ->
+
+ AliasDir1 = "../tests/to1",
+ AliasDir2 = "../tests/to2",
+ CfgDir1 = "../cfgs/to1/x.cfg",
+ CfgDir2 = ["../cfgs/to2/x.cfg","../cfgs/to2/y.cfg"],
+ LogDir = "../logs",
+ IncludeDir1 = "../../include",
+ IncludeDir2 = ["../tests/to1/include","../tests/to2/include"],
+
+ Spec =
+ [
+ {label,"basic_compatible_no_nodes"},
+ {alias,to1,AliasDir1},
+ {alias,to2,AliasDir2},
+ {config,CfgDir1},
+ {config,CfgDir2},
+ {userconfig,{?MODULE,"cfg_str1"}},
+ {userconfig,{?MODULE,"cfg_str2"}},
+ {logdir,LogDir},
+ {logopts,[no_nl]},
+ {event_handler,evh1,[1]},
+ {event_handler,[evh2,evh3],[[2,3]]},
+ {ct_hooks,[{cth_mod1,[]}]},
+ {ct_hooks,[{cth_mod2,[]}]},
+ {multiply_timetraps,2},
+ {include,IncludeDir1},
+ {include,IncludeDir2},
+ {suites,to1,[x_SUITE]},
+ {groups,to1,y_SUITE,[g1,g2]},
+ {cases,to1,y_SUITE,[tc1,tc2]},
+ {skip_suites,to1,z_SUITE,"skipped"},
+ {suites,to2,[x_SUITE,y_SUITE]},
+ {skip_groups,to2,x_SUITE,[g1,g2],"skipped"},
+ {skip_cases,to2,y_SUITE,[tc1,tc2],"skipped"}
+ ],
+
+ {ok,SpecDir} = file:get_cwd(),
+
+ ListResult = ct_testspec:collect_tests_from_list(Spec, false),
+ ct:pal("TESTSPEC RECORD FROM LIST:~n~p~n", [rec2proplist(ListResult)]),
+ SpecFile = ct_test_support:write_testspec(Spec,SpecDir,
+ "basic_compatible_no_nodes.spec"),
+ FileResult = ct_testspec:collect_tests_from_file([SpecFile], false),
+ ct:pal("TESTSPEC RECORD FROM FILE:~n~p~n", [rec2proplist(FileResult)]),
+
+ Node = node(),
+ LogDirV = get_absdir(filename:join(SpecDir,"../logs")),
+ Alias1V = get_absdir(filename:join(SpecDir,AliasDir1)),
+ Alias2V = get_absdir(filename:join(SpecDir,AliasDir2)),
+ CFGs = [{Node,get_absdir(filename:join(SpecDir,CfgDir))} ||
+ CfgDir <- [CfgDir1 | CfgDir2]],
+ Incls = [{Node,get_absdir(filename:join(SpecDir,IncludeDir))} ||
+ IncludeDir <- [IncludeDir1 | IncludeDir2]],
+
+ Verify = #testspec{spec_dir = SpecDir,
+ nodes = [{undefined,Node}],
+ init = [],
+ label = [{Node,"basic_compatible_no_nodes"}],
+ logdir = [{Node,LogDirV},"."],
+ logopts = [{Node,[no_nl]}],
+ basic_html = [],
+ cover = [],
+ config = CFGs,
+ userconfig = [{Node,{?MODULE,"cfg_str1"}},
+ {Node,{?MODULE,"cfg_str2"}}],
+ event_handler = [{Node,evh1,[1]},
+ {Node,evh2,[[2,3]]},
+ {Node,evh3,[[2,3]]}],
+ ct_hooks = [{Node,{cth_mod1,[]}},
+ {Node,{cth_mod2,[]}}],
+ enable_builtin_hooks = true,
+ release_shell = false,
+ include = Incls,
+ auto_compile = [],
+ stylesheet = [],
+ multiply_timetraps = [{Node,2}],
+ scale_timetraps = [],
+ create_priv_dir = [],
+ alias = [{to1,Alias1V},{to2,Alias2V}],
+ tests = [{{Node,Alias1V},
+ [{x_SUITE,[all]},
+ {y_SUITE,[{g1,all},{g2,all},tc1,tc2]},
+ {z_SUITE,[{all,{skip,"skipped"}}]}]},
+ {{Node,Alias2V},
+ [{x_SUITE,[all,
+ {{g1,all},{skip,"skipped"}},
+ {{g2,all},{skip,"skipped"}}]},
+ {y_SUITE,[all,
+ {tc1,{skip,"skipped"}},
+ {tc2,{skip,"skipped"}}]}]}],
+ merge_tests = true},
+
+ verify_result(Verify,ListResult,FileResult).
+
+%%%-----------------------------------------------------------------
+%%%
+basic_compatible_nodes(_Config) ->
+
+ Node1 = node1@host1,
+ Node2 = node2@host2,
+ TODir1 = "../tests/to1",
+ TODir2 = "../tests/to2",
+ CfgDir1 = "../cfgs/to1/x.cfg",
+ CfgDir2 = ["../cfgs/to2/x.cfg","../cfgs/to2/y.cfg"],
+ LogDir = "../logs",
+ MasterLogDir = "../master_logs",
+ IncludeDir1 = "../../include",
+ IncludeDir2 = ["../tests/to1/include","../tests/to2/include"],
+
+ Spec =
+ [
+ {node,n1,Node1},
+ {node,n2,Node2},
+ {init,[n1],[{node_start,[{callback_module,cbm}]}]},
+ {init,n2,[{node_start,[]}]},
+ {init,all_nodes,{eval,{mod,func,[]}}},
+ {label,"basic_compatible_nodes"},
+ {label,n1,basic_compatible_nodes_1},
+ {config,n1,CfgDir1},
+ {config,n2,CfgDir2},
+ {userconfig,{?MODULE,"cfg_str1"}},
+ {userconfig,{?MODULE,"cfg_str2"}},
+ {logdir,all_nodes,LogDir},
+ {logdir,master,MasterLogDir},
+ {logopts,node2@host2,[no_nl]},
+ {event_handler,master,evh1,[1]},
+ {event_handler,[n1,n2],[evh2,evh3],[[2,3]]},
+ {ct_hooks,all_nodes,[{cth_mod1,[]}]},
+ {ct_hooks,[{cth_mod2,[]}]},
+ {multiply_timetraps,node1@host1,2},
+ {include,n1,IncludeDir1},
+ {include,[n1,n2],IncludeDir2},
+ {suites,n1,TODir1,[x_SUITE]},
+ {groups,n1,TODir1,y_SUITE,[g1,g2]},
+ {cases,n1,TODir1,y_SUITE,[tc1,tc2]},
+ {skip_suites,n1,TODir1,z_SUITE,"skipped"},
+ {suites,n2,TODir2,[x_SUITE,y_SUITE]},
+ {skip_groups,n2,TODir2,x_SUITE,[g1,g2],"skipped"},
+ {skip_cases,n2,TODir2,y_SUITE,[tc1,tc2],"skipped"}
+ ],
+
+ {ok,SpecDir} = file:get_cwd(),
+
+ ListResult = ct_testspec:collect_tests_from_list(Spec, false),
+ ct:pal("TESTSPEC RECORD FROM LIST:~n~p~n", [rec2proplist(ListResult)]),
+ SpecFile = ct_test_support:write_testspec(Spec,SpecDir,
+ "basic_compatible_nodes.spec"),
+ FileResult = ct_testspec:collect_tests_from_file([SpecFile], false),
+ ct:pal("TESTSPEC RECORD FROM FILE:~n~p~n", [rec2proplist(FileResult)]),
+
+ Node = node(),
+ LogDirV = get_absdir(filename:join(SpecDir,"../logs")),
+ MasterLogDirV = get_absdir(filename:join(SpecDir,"../master_logs")),
+ TO1V = get_absdir(filename:join(SpecDir,TODir1)),
+ TO2V = get_absdir(filename:join(SpecDir,TODir2)),
+ CFGs = [{Node1,get_absdir(filename:join(SpecDir,CfgDir1))} |
+ [{Node2,get_absdir(filename:join(SpecDir,CfgDir))} || CfgDir <- CfgDir2]],
+ Incls = [{Node1,get_absdir(filename:join(SpecDir,IncludeDir1))} |
+ [{Node1,get_absdir(filename:join(SpecDir,IncludeDir))} ||
+ IncludeDir <- IncludeDir2] ++
+ [{Node2,get_absdir(filename:join(SpecDir,IncludeDir))} ||
+ IncludeDir <- IncludeDir2]],
+
+ Verify = #testspec{spec_dir = SpecDir,
+ nodes = [{undefined,Node},{n1,Node1},{n2,Node2}],
+ init = [{Node1,[{node_start,[{callback_module,cbm}]},
+ {eval,[{mod,func,[]}]}]},
+ {Node2,[{node_start,[{callback_module,ct_slave}]},
+ {eval,[{mod,func,[]}]}]},
+ {Node,[{node_start,[]},
+ {eval,[{mod,func,[]}]}]}],
+ label = [{Node,"basic_compatible_nodes"},
+ {Node2,"basic_compatible_nodes"},
+ {Node1,basic_compatible_nodes_1}],
+ logdir = [{Node,LogDirV},{Node1,LogDirV},{Node2,LogDirV},
+ {master,MasterLogDirV},"."],
+ logopts = [{Node2,[no_nl]}],
+ basic_html = [],
+ cover = [],
+ config = CFGs,
+ userconfig = [{Node,{?MODULE,"cfg_str1"}},
+ {Node1,{?MODULE,"cfg_str1"}},
+ {Node2,{?MODULE,"cfg_str1"}},
+ {Node,{?MODULE,"cfg_str2"}},
+ {Node1,{?MODULE,"cfg_str2"}},
+ {Node2,{?MODULE,"cfg_str2"}}],
+ event_handler = [{master,evh1,[1]},
+ {Node1,evh2,[[2,3]]},
+ {Node1,evh3,[[2,3]]},
+ {Node2,evh2,[[2,3]]},
+ {Node2,evh3,[[2,3]]}],
+ ct_hooks = [{Node,{cth_mod1,[]}},
+ {Node1,{cth_mod1,[]}},
+ {Node2,{cth_mod1,[]}},
+ {Node,{cth_mod2,[]}},
+ {Node1,{cth_mod2,[]}},
+ {Node2,{cth_mod2,[]}}],
+ enable_builtin_hooks = true,
+ release_shell = false,
+ include = Incls,
+ auto_compile = [],
+ stylesheet = [],
+ multiply_timetraps = [{Node1,2}],
+ scale_timetraps = [],
+ create_priv_dir = [],
+ tests = [{{Node1,TO1V},
+ [{x_SUITE,[all]},
+ {y_SUITE,[{g1,all},{g2,all},tc1,tc2]},
+ {z_SUITE,[{all,{skip,"skipped"}}]}]},
+ {{Node2,TO2V},
+ [{x_SUITE,[all,
+ {{g1,all},{skip,"skipped"}},
+ {{g2,all},{skip,"skipped"}}]},
+ {y_SUITE,[all,
+ {tc1,{skip,"skipped"}},
+ {tc2,{skip,"skipped"}}]}]}],
+ merge_tests = true},
+
+ verify_result(Verify,ListResult,FileResult).
+
+%%%-----------------------------------------------------------------
+%%%
+unknown_terms(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+
+ Spec1 = [{suites,PrivDir,all},
+ {userdata,"I've got news for you"}],
+ {error,{undefined_term_in_spec,{userdata,_}}} =
+ (catch ct_testspec:collect_tests_from_list(Spec1, false)),
+ true = is_record(ct_testspec:collect_tests_from_list(Spec1, true),
+ testspec),
+
+ Spec2 = [{logdir,{logdir,PrivDir}}],
+ {error,{invalid_directory_name,_}} =
+ (catch ct_testspec:collect_tests_from_list(Spec2, false)),
+
+ Spec3 = [{suite,PrivDir,all}],
+ {error,{undefined_term_in_spec,{suite,_,_}}} =
+ (catch ct_testspec:collect_tests_from_list(Spec3, false)),
+ true = is_record(ct_testspec:collect_tests_from_list(Spec3, true), testspec),
+
+ Spec4 = [{suites,PrivDir,all},
+ {skip_suites,PrivDir,x_SUITE}],
+ {error,{bad_term_in_spec,{skip_suites,_,_}}} =
+ (catch ct_testspec:collect_tests_from_list(Spec4, false)),
+ {error,{bad_term_in_spec,{skip_suites,_,_}}} =
+ (catch ct_testspec:collect_tests_from_list(Spec4, true)),
+
+ Spec5 = [{configs,all_nodes,PrivDir}],
+ {error,{undefined_term_in_spec,{configs,_,_}}} =
+ (catch ct_testspec:collect_tests_from_list(Spec5, false)),
+ true = is_record(ct_testspec:collect_tests_from_list(Spec5, true), testspec),
+
+ ok.
+
+%%%-----------------------------------------------------------------
+%%%
+no_merging(_Config) ->
+ Node1 = node1@host1,
+ Node2 = node2@host2,
+ TODir1 = "../tests/to1",
+ TODir2 = "../tests/to2",
+ Spec =
+ [
+ {merge_tests,false},
+ {node,n1,Node1},
+ {node,n2,Node2},
+ {suites,n1,TODir1,[x_SUITE]},
+ {groups,n1,TODir1,y_SUITE,[g1,g2]},
+ {cases,n1,TODir1,y_SUITE,[tc1,tc2]},
+ {skip_suites,n1,TODir1,z_SUITE,"skipped"},
+ {suites,n2,TODir2,[x_SUITE,y_SUITE]},
+ {skip_groups,n2,TODir2,x_SUITE,[g1,g2],"skipped"},
+ {skip_cases,n2,TODir2,y_SUITE,[tc1,tc2],"skipped"}
+ ],
+
+ {ok,SpecDir} = file:get_cwd(),
+
+ ListResult = ct_testspec:collect_tests_from_list(Spec, false),
+ ct:pal("TESTSPEC RECORD FROM LIST:~n~p~n", [rec2proplist(ListResult)]),
+ SpecFile = ct_test_support:write_testspec(Spec,SpecDir,
+ "no_merging.spec"),
+ FileResult = ct_testspec:collect_tests_from_file([SpecFile], false),
+ ct:pal("TESTSPEC RECORD FROM FILE:~n~p~n", [rec2proplist(FileResult)]),
+
+ Node = node(),
+ TO1V = get_absdir(filename:join(SpecDir,TODir1)),
+ TO2V = get_absdir(filename:join(SpecDir,TODir2)),
+
+ Verify = #testspec{merge_tests = false,
+ spec_dir = SpecDir,
+ nodes = [{undefined,Node},{n1,Node1},{n2,Node2}],
+ tests = [{{Node1,TO1V},
+ [{x_SUITE,[all]}]},
+ {{Node1,TO1V},
+ [{y_SUITE,[{g1,all},{g2,all}]}]},
+ {{Node1,TO1V},
+ [{y_SUITE,[tc1,tc2]}]},
+ {{Node1,TO1V},
+ [{z_SUITE,[{all,{skip,"skipped"}}]}]},
+ {{Node2,TO2V},
+ [{x_SUITE,[all]}]},
+ {{Node2,TO2V},
+ [{y_SUITE,[all]}]},
+ {{Node2,TO2V},
+ [{x_SUITE,[{{g1,all},{skip,"skipped"}},
+ {{g2,all},{skip,"skipped"}}]}]},
+ {{Node2,TO2V},
+ [{y_SUITE,[{tc1,{skip,"skipped"}},
+ {tc2,{skip,"skipped"}}]}]}]},
+
+ verify_result(Verify,ListResult,FileResult).
+
+%%%-----------------------------------------------------------------
+%%%
+multiple_specs(_Config) ->
+ Node1 = node1@host1,
+ Node2 = node2@host2,
+ TODir1 = "../tests/to1",
+ TODir2 = "../tests/to2",
+ CfgDir1 = "../cfgs/to1/x.cfg",
+ CfgDir2 = ["../cfgs/to2/x.cfg","../cfgs/to2/y.cfg"],
+ LogDir = "../logs",
+ Spec1 =
+ [
+ {node,n1,Node1},
+ {node,n2,Node2},
+ {alias,to1,TODir1},
+ {alias,to2,TODir2},
+ {label,"multiple_specs1"},
+ {config,n1,CfgDir1},
+ {config,n2,CfgDir2},
+ {logdir,all_nodes,LogDir}
+ ],
+ Spec2 =
+ [
+ {merge_tests,false},
+ {label,"multiple_specs2"},
+ {suites,n1,TODir1,[x_SUITE]},
+ {groups,n1,TODir1,y_SUITE,[g1,g2]},
+ {cases,n1,TODir1,y_SUITE,[tc1,tc2]},
+ {skip_suites,n1,TODir1,z_SUITE,"skipped"},
+ {suites,n2,TODir2,[x_SUITE,y_SUITE]},
+ {skip_groups,n2,TODir2,x_SUITE,[g1,g2],"skipped"},
+ {skip_cases,n2,TODir2,y_SUITE,[tc1,tc2],"skipped"}
+ ],
+
+ {ok,SpecDir} = file:get_cwd(),
+ SpecFile1 = ct_test_support:write_testspec(Spec1,SpecDir,
+ "multiple_specs.1.spec"),
+ SpecFile2 = ct_test_support:write_testspec(Spec2,SpecDir,
+ "multiple_specs.2.spec"),
+ FileResult = ct_testspec:collect_tests_from_file([SpecFile1,SpecFile2],
+ false),
+ ct:pal("TESTSPEC RECORD FROM FILE:~n~p~n", [rec2proplist(FileResult)]),
+
+ Node = node(),
+ TO1V = get_absdir(filename:join(SpecDir,TODir1)),
+ TO2V = get_absdir(filename:join(SpecDir,TODir2)),
+ CFGs = [{Node1,get_absdir(filename:join(SpecDir,CfgDir1))} |
+ [{Node2,get_absdir(filename:join(SpecDir,CfgDir))} || CfgDir <- CfgDir2]],
+ LogDirV = get_absdir(filename:join(SpecDir,"../logs")),
+
+ Verify = #testspec{merge_tests = false,
+ spec_dir = SpecDir,
+ nodes = [{undefined,Node},{n1,Node1},{n2,Node2}],
+ alias = [{to1,TO1V},{to2,TO2V}],
+ label = [{Node,"multiple_specs1"},
+ {Node1,"multiple_specs1"},
+ {Node2,"multiple_specs1"}],
+ logdir = [{Node,LogDirV},{Node1,LogDirV},{Node2,LogDirV},"."],
+ config = CFGs,
+ tests = [{{Node1,TO1V},
+ [{x_SUITE,[all]}]},
+ {{Node1,TO1V},
+ [{y_SUITE,[{g1,all},{g2,all}]}]},
+ {{Node1,TO1V},
+ [{y_SUITE,[tc1,tc2]}]},
+ {{Node1,TO1V},
+ [{z_SUITE,[{all,{skip,"skipped"}}]}]},
+ {{Node2,TO2V},
+ [{x_SUITE,[all]}]},
+ {{Node2,TO2V},
+ [{y_SUITE,[all]}]},
+ {{Node2,TO2V},
+ [{x_SUITE,[{{g1,all},{skip,"skipped"}},
+ {{g2,all},{skip,"skipped"}}]}]},
+ {{Node2,TO2V},
+ [{y_SUITE,[{tc1,{skip,"skipped"}},
+ {tc2,{skip,"skipped"}}]}]}]},
+
+ verify_result(Verify,FileResult,FileResult).
+
+%%%-----------------------------------------------------------------
+%%%
+misc_config_terms(_Config) ->
+ CfgDir = "../cfgs/to1",
+
+ Spec =
+ [{node,x,n1@h1},{node,y,n2@h2},
+
+ {config,CfgDir,"a.cfg"},
+ {config,n1@h1,CfgDir,"b.cfg"},
+ {config,all_nodes,CfgDir,"c.cfg"},
+ {config,all_nodes,filename:join(CfgDir,"d.cfg")},
+
+ {basic_html,true},
+ {basic_html,n1@h1,false},
+ {basic_html,n2@h2,true},
+
+ {silent_connections,n1@h1,all},
+ {silent_connections,n2@h2,[ssh]},
+
+ {enable_builtin_hooks,false},
+
+ {release_shell,true},
+
+ {auto_compile,false},
+ {auto_compile,n1@h1,true},
+ {auto_compile,n2@h2,false},
+
+ {stylesheet,"../css"},
+ {stylesheet,n1@h1,"./n1/css"},
+ {stylesheet,n2@h2,"./n2/css"},
+
+ {create_priv_dir,[auto_per_tc]},
+ {create_priv_dir,n1@h1,[manual_per_tc]},
+ {create_priv_dir,n2@h2,[auto_per_run]}
+ ],
+
+ {ok,SpecDir} = file:get_cwd(),
+
+ ListResult = ct_testspec:collect_tests_from_list(Spec, false),
+ ct:pal("TESTSPEC RECORD FROM LIST:~n~p~n", [rec2proplist(ListResult)]),
+ SpecFile = ct_test_support:write_testspec(Spec,SpecDir,
+ "misc_config_terms.spec"),
+ FileResult = ct_testspec:collect_tests_from_file([SpecFile], false),
+ ct:pal("TESTSPEC RECORD FROM FILE:~n~p~n", [rec2proplist(FileResult)]),
+
+ Node = node(),
+ CfgA = get_absdir(filename:join(filename:join(SpecDir,CfgDir), "a.cfg")),
+ CfgB = get_absdir(filename:join(filename:join(SpecDir,CfgDir), "b.cfg")),
+ CfgC = get_absdir(filename:join(filename:join(SpecDir,CfgDir), "c.cfg")),
+ CfgD = get_absdir(filename:join(filename:join(SpecDir,CfgDir), "d.cfg")),
+ CSS = get_absdir(filename:join(SpecDir,"../css")),
+ CSS1 = get_absdir(filename:join(SpecDir,"./n1/css")),
+ CSS2 = get_absdir(filename:join(SpecDir,"./n2/css")),
+
+ Verify = #testspec{spec_dir = SpecDir,
+ nodes = [{undefined,Node},{x,n1@h1},{y,n2@h2}],
+ basic_html = [{Node,true},{n1@h1,false},{n2@h2,true}],
+ silent_connections = [{n1@h1,[all]},{n2@h2,[ssh]}],
+ config = [{Node,CfgA},
+ {n1@h1,CfgA},
+ {n2@h2,CfgA},
+ {n1@h1,CfgB},
+ {Node,CfgC},
+ {n1@h1,CfgC},
+ {n2@h2,CfgC},
+ {Node,CfgD},
+ {n1@h1,CfgD},
+ {n2@h2,CfgD}],
+ enable_builtin_hooks = false,
+ release_shell = true,
+ auto_compile = [{Node,false},
+ {n1@h1,true},
+ {n2@h2,false}],
+ stylesheet = [{Node,CSS},
+ {n1@h1,CSS1},
+ {n2@h2,CSS2}],
+ create_priv_dir = [{Node,[auto_per_tc]},
+ {n1@h1,[manual_per_tc]},
+ {n2@h2,[auto_per_run]}]
+ },
+
+ verify_result(Verify,ListResult,FileResult).
+
+%%%-----------------------------------------------------------------
+%%%
+define_names_1(_Config) ->
+ Spec =
+ [
+ {define,'HOST','eniac'},
+ {define,'NODE1',testnode1},
+ {define,'NODE2',testnode2},
+ {define,'NODES',['NODE1@HOST',
+ 'NODE2@HOST']},
+ {define,'TOPDIR',".."},
+ {define,'TO1',"to1"},
+ {define,'TO2',"to2"},
+ {define,'LOGDIR',"'TOPDIR'/logdir"},
+ {define,'LOGDIR1',"'TOPDIR'/logdir1"},
+ {define,'LOGDIR2',"'TOPDIR'/logdir2"},
+ {define,'CFGDIR',"'TOPDIR'/cfgs"},
+ {define,'CFGFILES',["cfgX","cfgY"]},
+ {define,'TESTDIR',"'TOPDIR'/test"},
+ {define,'TO1DIR',"'TESTDIR'/'TO1'"},
+ {define,'TO2DIR',"'TESTDIR'/'TO2'"},
+ {define,'EXSUITE',ex_SUITE},
+ {define,'EXGRS',[g1,g2]},
+
+ {logdir,'LOGDIR'},
+ {logdir,'NODE1@HOST','LOGDIR1'},
+ {logdir,'NODE2@HOST','LOGDIR2'},
+
+ {config,["a.cfg","b.cfg"]},
+ {config,'NODES',"./'CFGDIR'/c.cfg"},
+ {config,'CFGDIR',["d.cfg","e.cfg"]},
+ {config,'NODE2@HOST','CFGDIR','CFGFILES'},
+
+ {suites,'NODE1@HOST','TO1DIR',all},
+ {suites,'NODES','TO2DIR',all},
+
+ {groups,'TO1DIR','EXSUITE','EXGRS'}
+ ],
+
+ {ok,SpecDir} = file:get_cwd(),
+
+ ListResult = ct_testspec:collect_tests_from_list(Spec, false),
+ ct:pal("TESTSPEC RECORD FROM LIST:~n~p~n", [rec2proplist(ListResult)]),
+ SpecFile = ct_test_support:write_testspec(Spec,SpecDir,
+ "define_names_1.spec"),
+ FileResult = ct_testspec:collect_tests_from_file([SpecFile], false),
+ ct:pal("TESTSPEC RECORD FROM FILE:~n~p~n", [rec2proplist(FileResult)]),
+
+ N = node(),
+ N1 = testnode1@eniac,
+ N2 = testnode2@eniac,
+ Join = fun(Dir) -> shorten_path(filename:join(SpecDir,Dir),SpecDir) end,
+
+ Verify = #testspec{spec_dir = SpecDir,
+ nodes = [{undefined,N2},
+ {undefined,N1},
+ {undefined,N}],
+ config = [{N2,Join("a.cfg")},{N2,Join("b.cfg")},
+ {N1,Join("a.cfg")},{N1,Join("b.cfg")},
+ {N,Join("a.cfg")},{N,Join("b.cfg")},
+ {N1,Join("../cfgs/c.cfg")},{N2,Join("../cfgs/c.cfg")},
+ {N2,Join("../cfgs/d.cfg")},{N2,Join("../cfgs/e.cfg")},
+ {N1,Join("../cfgs/d.cfg")},{N1,Join("../cfgs/e.cfg")},
+ {N,Join("../cfgs/d.cfg")},{N,Join("../cfgs/e.cfg")},
+ {N2,Join("../cfgs/cfgX")},{N2,Join("../cfgs/cfgY")}],
+ logdir = [{N,Join("../logdir")},
+ {N1,Join("../logdir1")},
+ {N2,Join("../logdir2")},
+ "."],
+ tests = [{{N1,Join("../test/to1")},[{all,[all]}]},
+ {{N1,Join("../test/to2")},[{all,[all]}]},
+ {{N2,Join("../test/to2")},[{all,[all]}]},
+ {{N2,Join("../test/to1")},
+ [{ex_SUITE,[{g1,all},{g2,all}]}]},
+ {{N,Join("../test/to1")},
+ [{ex_SUITE,[{g1,all},{g2,all}]}]}]
+ },
+ verify_result(Verify,ListResult,FileResult).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+verify_result(Verify,ListResult,FileResult) ->
+ {_,TSLTuples} = rec2proplist(ListResult),
+ {_,TSFTuples} = rec2proplist(FileResult),
+ {_,VTuples} = rec2proplist(Verify),
+ VResult =
+ (catch lists:foldl(fun({Tag,Val},{[{Tag,Val}|TSL],[{Tag,Val}|TSF]}) ->
+ {TSL,TSF};
+ ({Tag,Val},{[{_Tag,TSLVal}|_TSL],[{Tag,Val}|_TSF]}) ->
+ exit({ts_list_mismatch,Tag,Val,TSLVal});
+ ({Tag,Val},{[{Tag,Val}|_TSL],[{_Tag,TSFVal}|_TSF]}) ->
+ exit({ts_file_mismatch,Tag,Val,TSFVal});
+ ({Tag,Val},{_,[{_Tag,TSFVal}|_TSF]}) ->
+ exit({ts_mismatch,Tag,Val,TSFVal})
+ end, {TSLTuples,TSFTuples}, VTuples)),
+ case VResult of
+ {'EXIT',Reason} ->
+ ct:fail(Reason);
+ _ ->
+ ok
+ end,
+ ok.
+
+
+check_parameter(S="cfg_str1") ->
+ {ok,{config,S}};
+check_parameter(S="cfg_str2") ->
+ {ok,{config,S}}.
+read_config(S) ->
+ {ok,[{cfg,S}]}.
+
+rec2proplist(E={error,_What}) ->
+ exit({invalid_testspec_record,E});
+rec2proplist(Rec) ->
+ [RecName|RecList] = tuple_to_list(Rec),
+ FieldNames =
+ if RecName == testspec ->
+ record_info(fields, testspec);
+ true ->
+ undefined
+ end,
+ {RecName,combine_names_and_vals(FieldNames,RecList)}.
+
+combine_names_and_vals([FN|FNs], [V|Vs]) ->
+ [{FN,V} | combine_names_and_vals(FNs, Vs)];
+combine_names_and_vals([], []) ->
+ [];
+combine_names_and_vals(_, _) ->
+ [].
+
+get_absdir(Dir) ->
+ shorten_path(filename:absname(Dir),Dir).
+
+shorten_path(Path,SpecDir) ->
+ case shorten_split_path(filename:split(Path),[]) of
+ [] ->
+ [Root|_] = filename:split(SpecDir),
+ Root;
+ Short ->
+ filename:join(Short)
+ end.
+
+shorten_split_path([".."|Path],SoFar) ->
+ shorten_split_path(Path,tl(SoFar));
+shorten_split_path(["."|Path],SoFar) ->
+ shorten_split_path(Path,SoFar);
+shorten_split_path([Dir|Path],SoFar) ->
+ shorten_split_path(Path,[Dir|SoFar]);
+shorten_split_path([],SoFar) ->
+ lists:reverse(SoFar).
diff --git a/lib/common_test/test/ct_verbosity_SUITE.erl b/lib/common_test/test/ct_verbosity_SUITE.erl
new file mode 100644
index 0000000000..349319de94
--- /dev/null
+++ b/lib/common_test/test/ct_verbosity_SUITE.erl
@@ -0,0 +1,244 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_verbosity_SUITE
+%%%
+%%% Description:
+%%% Test that verbosity levels vs the importance parameter works as
+%%% expected.
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_verbosity_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ no_levels,
+ general_level_low,
+ general_level_std,
+ general_level_hi,
+ change_default,
+ combine_categories,
+ testspec_only,
+ merge_with_testspec
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+no_levels(Config) ->
+ TC = no_levels,
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "io_test_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,TC}], Config),
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+general_level_low(Config) ->
+ TC = general_level_low,
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "io_test_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,TC},
+ {verbosity,0}], Config),
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+general_level_std(Config) ->
+ TC = general_level_std,
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "io_test_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,TC},
+ {verbosity,50}], Config),
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+general_level_hi(Config) ->
+ TC = general_level_high,
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "io_test_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,TC},
+ {verbosity,100}], Config),
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+change_default(Config) ->
+ TC = change_default,
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "io_test_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,TC},
+ {verbosity,[{default,49}]}], Config),
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+combine_categories(Config) ->
+ TC = combine_categories,
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "io_test_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{label,TC},
+ {verbosity,[{error,?HI_VERBOSITY},
+ {default,?LOW_VERBOSITY}]}], Config),
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+testspec_only(Config) ->
+ TC = testspec_only,
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ TestSpec = [{verbosity,[{default,1},{error,75},100]},
+ {suites,DataDir,[io_test_SUITE]},
+ {label,TC}],
+
+ TestSpecName = ct_test_support:write_testspec(TestSpec, PrivDir,
+ "verbosity_1_spec"),
+ {Opts,ERPid} = setup([{spec,TestSpecName}], Config),
+
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+merge_with_testspec(Config) ->
+ TC = merge_with_testspec,
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ TestSpec = [{verbosity,[{default,100},{error,100}]},
+ {suites,DataDir,[io_test_SUITE]},
+ {label,TC}],
+
+ TestSpecName = ct_test_support:write_testspec(TestSpec, PrivDir,
+ "verbosity_2_spec"),
+
+ %% below should override verbosity categories in testspec
+ {Opts,ERPid} = setup([{spec,TestSpecName},
+ {verbosity,[{default,0},0]}],
+ Config),
+
+ ok = execute(TC, Opts, ERPid, Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+
+test_events(_) ->
+ [
+ {?eh,tc_done,{io_test_SUITE,tc1,ok}},
+ {?eh,tc_done,{io_test_SUITE,tc2,ok}},
+ {?eh,tc_done,{io_test_SUITE,tc3,ok}},
+
+ {parallel,
+ [
+ {?eh,tc_start,{io_test_SUITE,tc1}},
+ {?eh,tc_start,{io_test_SUITE,tc2}},
+ {?eh,tc_start,{io_test_SUITE,tc3}},
+ {?eh,tc_done,{io_test_SUITE,tc1,ok}},
+ {?eh,tc_done,{io_test_SUITE,tc2,ok}},
+ {?eh,tc_done,{io_test_SUITE,tc3,ok}},
+ {parallel,
+ [
+ {?eh,tc_start,{io_test_SUITE,tc1}},
+ {?eh,tc_start,{io_test_SUITE,tc2}},
+ {?eh,tc_start,{io_test_SUITE,tc3}},
+ {?eh,tc_done,{io_test_SUITE,tc1,ok}},
+ {?eh,tc_done,{io_test_SUITE,tc2,ok}},
+ {?eh,tc_done,{io_test_SUITE,tc3,ok}},
+ {?eh,test_stats,{9,0,{0,0}}}
+ ]}
+ ]},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
+
diff --git a/lib/common_test/test/ct_verbosity_SUITE_data/io_test_SUITE.erl b/lib/common_test/test/ct_verbosity_SUITE_data/io_test_SUITE.erl
new file mode 100644
index 0000000000..946e1c1989
--- /dev/null
+++ b/lib/common_test/test/ct_verbosity_SUITE_data/io_test_SUITE.erl
@@ -0,0 +1,156 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(io_test_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,10}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1, [parallel], [tc1,tc2,tc3,{group,g2}]},
+ {g2, [parallel], [tc1,tc2,tc3]}].
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2,tc3,{group,g1}].
+
+tc1(_C) ->
+ io:format("This is an io:format(~p)~n", [[]]),
+ ct:log("ct:log(default)", []),
+ ct:log(?STD_IMPORTANCE, "ct:log(default,~p)", [?STD_IMPORTANCE]),
+ ct:log(error, "ct:log(error)", []),
+ ct:log(error, ?STD_IMPORTANCE, "ct:log(error,~p)", [?STD_IMPORTANCE]),
+ ct:log(1, "ct:log(default,~p)", [1]),
+ ct:log(error, 1, "ct:log(error,~p)", [1]),
+ ct:log(99, "ct:log(default,~p)", [99]),
+ ct:log(error, 99, "ct:log(error,~p)", [99]),
+ ok.
+
+tc2(_C) ->
+ io:format("This is an io:format(~p)~n", [[]]),
+ ct:pal("ct:pal(default)", []),
+ ct:pal(?STD_IMPORTANCE, "ct:pal(default,~p)", [?STD_IMPORTANCE]),
+ ct:pal(error, "ct:pal(error)", []),
+ ct:pal(error, ?STD_IMPORTANCE, "ct:pal(error,~p)", [?STD_IMPORTANCE]),
+ ct:pal(1, "ct:pal(default,~p)", [1]),
+ ct:pal(error, 1, "ct:pal(error,~p)", [1]),
+ ct:pal(99, "ct:pal(default,~p)", [99]),
+ ct:pal(error, 99, "ct:pal(error,~p)", [99]),
+ ok.
+
+tc3(_C) ->
+ io:format("This is an io:format(~p)~n", [[]]),
+ ct:print("ct:print(default)", []),
+ ct:print(?STD_IMPORTANCE, "ct:print(default,~p)", [?STD_IMPORTANCE]),
+ ct:print(error, "ct:print(error)", []),
+ ct:print(error, ?STD_IMPORTANCE, "ct:print(error,~p)", [?STD_IMPORTANCE]),
+ ct:print(1, "ct:print(default,~p)", [1]),
+ ct:print(error, 1, "ct:print(error,~p)", [1]),
+ ct:print(99, "ct:print(default,~p)", [99]),
+ ct:print(error, 99, "ct:print(error,~p)", [99]),
+ ok.
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 4782a32933..877aa775fd 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1,3 +1 @@
-COMMON_TEST_VSN = 1.5.5
-
-
+COMMON_TEST_VSN = 1.6.2
diff --git a/lib/compiler/doc/src/Makefile b/lib/compiler/doc/src/Makefile
index ee41a7074f..308e9c4d02 100644
--- a/lib/compiler/doc/src/Makefile
+++ b/lib/compiler/doc/src/Makefile
@@ -99,14 +99,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 522c1dc411..be9eb1cd75 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -294,6 +294,12 @@ module.beam: module.erl \
describing what it is doing.</p>
</item>
+ <tag><c>{source,FileName}</c></tag>
+ <item>
+ <p>Sets the value of the source, as returned by
+ <c>module_info(compile)</c>.</p>
+ </item>
+
<tag><c>{outdir,Dir}</c></tag>
<item>
<p>Sets a new directory for the object code. The current
@@ -333,7 +339,8 @@ module.beam: module.erl \
<tag><c>{d,Macro,Value}</c></tag>
<item>
<p>Defines a macro <c>Macro</c> to have the value
- <c>Value</c>. The default is <c>true</c>).</p>
+ <c>Value</c>. <c>Macro</c> is of type atom, and <c>Value</c> can be any term.
+ The default <c>Value</c> is <c>true</c>.</p>
</item>
<tag><c>{parse_transform,Module}</c></tag>
diff --git a/lib/compiler/doc/src/make.dep b/lib/compiler/doc/src/make.dep
deleted file mode 100644
index f5c097afad..0000000000
--- a/lib/compiler/doc/src/make.dep
+++ /dev/null
@@ -1,19 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex compile.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 740cbcf8eb..e2a921a6f2 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -31,6 +31,174 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 4.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ In rare circumstance, the compiler could crash when
+ compiling a case statement. (Thanks to Hakan Mattsson.)</p>
+ <p>
+ Own Id: OTP-9842</p>
+ </item>
+ <item>
+ <p>Calling a guard test (such as is_list/1) from the
+ top-level in a guard, would cause a compiler crash if
+ there was a local definition with the same name.
+ Corrected to reject the program with an error
+ message.</p>
+ <p>
+ Own Id: OTP-9866</p>
+ </item>
+ <item>
+ <p>Using <c>get/1</c> in a <c>try</c> block could in some
+ cases cause an internal compiler error. (Thanks to Eric
+ Merritt.)</p>
+ <p>
+ Own Id: OTP-9867</p>
+ </item>
+ <item>
+ <p>
+ An unexported on_load function would not get run if the
+ module was compiled with the <c>inline</c> option.
+ (Thanks to Yiannis Tsiouris.)</p>
+ <p>
+ Own Id: OTP-9910</p>
+ </item>
+ <item>
+ <p>
+ Fixed a discrepancy in compile_info</p>
+ <p>
+ The BEAM disassembler used the atom 'none' to signify the
+ absence of a compile_info chunk in a .beam file. This
+ clashed with the type declaration of the compile_info
+ field of a #beam_file{} record as containing a list. Now
+ [] signifies the absence of this chunk. This simplifies
+ the code and avoids a dialyzer warning.</p>
+ <p>
+ Own Id: OTP-9917</p>
+ </item>
+ <item>
+ <p>
+ Fix typo in `compile' doc: unmatched parenthesis (Thanks
+ to Ricardo Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9919</p>
+ </item>
+ <item>
+ <p>In a <c>try</c>...<c>catch</c> statement that always
+ returned <c>false</c>, the compiler would remove calls to
+ BIFs that could not cause an exception (such as
+ <c>put/2</c>). Example of such code: <c>try put(K, V),
+ false catch _:_ -&gt; false end.</c></p>
+ <p>
+ Own Id: OTP-9982</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 4.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add '-callback' attributes in stdlib's behaviours</p>
+ <p>
+ Replace the behaviour_info(callbacks) export in stdlib's
+ behaviours with -callback' attributes for all the
+ callbacks. Update the documentation with information on
+ the callback attribute Automatically generate
+ 'behaviour_info' function from '-callback' attributes</p>
+ <p>
+ 'behaviour_info(callbacks)' is a special function that is
+ defined in a module which describes a behaviour and
+ returns a list of its callbacks.</p>
+ <p>
+ This function is now automatically generated using the
+ '-callback' specs. An error is returned by lint if user
+ defines both '-callback' attributes and the
+ behaviour_info/1 function. If no type info is needed for
+ a callback use a generic spec for it. Add '-callback'
+ attribute to language syntax</p>
+ <p>
+ Behaviours may define specs for their callbacks using the
+ familiar spec syntax, replacing the '-spec' keyword with
+ '-callback'. Simple lint checks are performed to ensure
+ that no callbacks are defined twice and all types
+ referred are declared.</p>
+ <p>
+ These attributes can be then used by tools to provide
+ documentation to the behaviour or find discrepancies in
+ the callback definitions in the callback module.</p>
+ <p>
+ Add callback specs into 'application' module in kernel
+ Add callback specs to tftp module following internet
+ documentation Add callback specs to inets_service module
+ following possibly deprecated comments</p>
+ <p>
+ Own Id: OTP-9621</p>
+ </item>
+ <item>
+ <p>
+ The calculation of the 'uniq' value for a fun (see
+ <c>erlang:fun_info/1</c>) was too weak and has been
+ strengthened. It used to be based on the only the code
+ for the fun body, but it is now based on the MD5 of the
+ BEAM code for the module.</p>
+ <p>
+ Own Id: OTP-9667</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Variables are now now allowed in '<c>fun M:F/A</c>' as
+ suggested by Richard O'Keefe in EEP-23.</p>
+ <p>The representation of '<c>fun M:F/A</c>' in the
+ abstract format has been changed in an incompatible way.
+ Tools that directly read or manipulate the abstract
+ format (such as parse transforms) may need to be updated.
+ The compiler can handle both the new and the old format
+ (i.e. extracting the abstract format from a pre-R15 BEAM
+ file and compiling it using compile:forms/1,2 will work).
+ The <c>syntax_tools</c> application can also handle both
+ formats.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9643</p>
+ </item>
+ <item>
+ <p>
+ <c>filename:find_src/1,2</c> will now work on stripped
+ BEAM files (reported by Per Hedeland). The HiPE compiler
+ will also work on stripped BEAM files. The BEAM compiler
+ will no longer include compilation options given in the
+ source code itself in <c>M:module_info(compile)</c>
+ (because those options will be applied anyway if the
+ module is re-compiled).</p>
+ <p>
+ Own Id: OTP-9752</p>
+ </item>
+ <item>
+ <p>Inlining binary matching could cause an internal
+ compiler error. (Thanks to Rene Kijewski for reporting
+ this bug.)</p>
+ <p>
+ Own Id: OTP-9770</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 4.7.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index 1238d113e1..56c45d369c 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -53,12 +53,14 @@ MODULES = \
beam_dead \
beam_dict \
beam_disasm \
+ beam_except \
beam_flatten \
beam_jump \
beam_listing \
beam_opcodes \
beam_peep \
beam_receive \
+ beam_split \
beam_trim \
beam_type \
beam_utils \
@@ -161,11 +163,11 @@ $(EBIN)/cerl_inline.beam: $(ESRC)/cerl_inline.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(EXTRA_FILES) \
- $(YRL_FILE) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(INSTALL_FILES) $(RELSYSDIR)/ebin
+ $(YRL_FILE) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(INSTALL_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index 6e63c4d0f2..a7c8508321 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.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
@@ -146,8 +146,10 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
Essentials0 = [AtomChunk,CodeChunk,StringChunk,ImportChunk,
ExpChunk,LambdaChunk,LiteralChunk],
- Essentials = [iolist_to_binary(C) || C <- Essentials0],
- {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, Essentials),
+ Essentials1 = [iolist_to_binary(C) || C <- Essentials0],
+ MD5 = module_md5(Essentials1),
+ Essentials = finalize_fun_table(Essentials1, MD5),
+ {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, MD5),
AttrChunk = chunk(<<"Attr">>, Attributes),
CompileChunk = chunk(<<"CInf">>, Compile),
@@ -166,6 +168,24 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
end,
build_form(<<"BEAM">>, Chunks).
+%% finalize_fun_table(Essentials, MD5) -> FinalizedEssentials
+%% Update the 'old_uniq' field in the entry for each fun in the
+%% 'FunT' chunk. We'll use part of the MD5 for the module as a
+%% unique value.
+
+finalize_fun_table(Essentials, MD5) ->
+ [finalize_fun_table_1(E, MD5) || E <- Essentials].
+
+finalize_fun_table_1(<<"FunT",Keep:8/binary,Table0/binary>>, MD5) ->
+ <<Uniq:27,_:101/bits>> = MD5,
+ Table = finalize_fun_table_2(Table0, Uniq, <<>>),
+ <<"FunT",Keep/binary,Table/binary>>;
+finalize_fun_table_1(Chunk, _) -> Chunk.
+
+finalize_fun_table_2(<<Keep:20/binary,0:32,T/binary>>, Uniq, Acc) ->
+ finalize_fun_table_2(T, Uniq, <<Acc/binary,Keep/binary,Uniq:32>>);
+finalize_fun_table_2(<<>>, _, Acc) -> Acc.
+
%% Build an IFF form.
build_form(Id, Chunks0) when byte_size(Id) =:= 4, is_list(Chunks0) ->
@@ -202,7 +222,7 @@ flatten_exports(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) ->
+build_attributes(Opts, SourceFile, Attr, MD5) ->
Misc = case member(slim, Opts) of
false ->
{{Y,Mo,D},{H,Mi,S}} = erlang:universaltime(),
@@ -210,7 +230,7 @@ build_attributes(Opts, SourceFile, Attr, Essentials) ->
true -> []
end,
Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
- {term_to_binary(calc_vsn(Attr, Essentials)),term_to_binary(Compile)}.
+ {term_to_binary(set_vsn_attribute(Attr, MD5)),term_to_binary(Compile)}.
build_line_table(Dict) ->
{NumLineInstrs,NumFnames0,Fnames0,NumLines,Lines0} =
@@ -243,32 +263,30 @@ encode_line_items([], _) -> [].
%% We'll not change an existing 'vsn' attribute.
%%
-calc_vsn(Attr, Essentials0) ->
+set_vsn_attribute(Attr, MD5) ->
case keymember(vsn, 1, Attr) of
true -> Attr;
false ->
- Essentials = filter_essentials(Essentials0),
- <<Number:128>> = erlang:md5(Essentials),
+ <<Number:128>> = MD5,
[{vsn,[Number]}|Attr]
end.
+module_md5(Essentials0) ->
+ Essentials = filter_essentials(Essentials0),
+ erlang:md5(Essentials).
+
%% filter_essentials([Chunk]) -> [Chunk']
%% Filter essentials so that we obtain the same MD5 as code:module_md5/1 and
-%% beam_lib:md5/1 would calculate for this module.
+%% beam_lib:md5/1 would calculate for this module. Note that at this
+%% point, the 'old_uniq' entry for each fun in the 'FunT' chunk is zeroed,
+%% so there is no need to go through the 'FunT' chunk.
-filter_essentials([<<"FunT",_Sz:4/binary,Entries:4/binary,Table0/binary>>|T]) ->
- Table = filter_funtab(Table0, <<0:32>>),
- [Entries,Table|filter_essentials(T)];
filter_essentials([<<_Tag:4/binary,Sz:32,Data:Sz/binary,_Padding/binary>>|T]) ->
[Data|filter_essentials(T)];
filter_essentials([<<>>|T]) ->
filter_essentials(T);
filter_essentials([]) -> [].
-filter_funtab(<<Important:20/binary,_OldUniq:4/binary,T/binary>>, Zero) ->
- [Important,Zero|filter_funtab(T, Zero)];
-filter_funtab(<<>>, _) -> [].
-
bif_type(fnegate, 1) -> {op,fnegate};
bif_type(fadd, 2) -> {op,fadd};
bif_type(fsub, 2) -> {op,fsub};
@@ -310,8 +328,8 @@ make_op({test,Cond,Fail,Ops}, Dict) when is_list(Ops) ->
encode_op(Cond, [Fail|Ops], Dict);
make_op({test,Cond,Fail,Live,[Op|Ops],Dst}, Dict) when is_list(Ops) ->
encode_op(Cond, [Fail,Op,Live|Ops++[Dst]], 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,{f,Lbl},_Index,_OldUniq,NumFree}, Dict0) ->
+ {Fun,Dict} = beam_dict:lambda(Lbl, NumFree, Dict0),
make_op({make_fun2,Fun}, Dict);
make_op({kill,Y}, Dict) ->
make_op({init,Y}, Dict);
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index 432d1e7eea..cd568097fa 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.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
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index 9f81a6ab43..5f12a98f09 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -131,10 +131,9 @@
-import(lists, [mapfoldl/3,reverse/1]).
module({Mod,Exp,Attr,Fs0,_}, _Opts) ->
- Fs1 = [split_blocks(F) || F <- Fs0],
- {Fs2,Lc1} = beam_clean:clean_labels(Fs1),
- {Fs,Lc} = mapfoldl(fun function/2, Lc1, Fs2),
- %%{Fs,Lc} = {Fs2,Lc1},
+ {Fs1,Lc1} = beam_clean:clean_labels(Fs0),
+ {Fs,Lc} = mapfoldl(fun function/2, Lc1, Fs1),
+ %%{Fs,Lc} = {Fs1,Lc1},
{ok,{Mod,Exp,Attr,Fs,Lc}}.
function({function,Name,Arity,CLabel,Is0}, Lc0) ->
@@ -160,64 +159,6 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
erlang:raise(Class, Error, Stack)
end.
-%% 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.
-
-split_blocks({function,Name,Arity,CLabel,Is0}) ->
- Is = split_blocks(Is0, []),
- {function,Name,Arity,CLabel,Is}.
-
-split_blocks([{block,Bl}|Is], Acc0) ->
- Acc = split_block(Bl, [], Acc0),
- split_blocks(Is, Acc);
-split_blocks([I|Is], Acc) ->
- split_blocks(Is, [I|Acc]);
-split_blocks([], Acc) -> reverse(Acc).
-
-split_block([{set,[R],[_,_,_]=As,{bif,is_record,{f,Lbl}}}|Is], Bl, Acc) ->
- %% is_record/3 must be translated by beam_clean; therefore,
- %% it must be outside of any block.
- split_block(Is, [], [{bif,is_record,{f,Lbl},As,R}|make_block(Bl, Acc)]);
-split_block([{set,[R],As,{bif,N,{f,Lbl}=Fail}}|Is], Bl, Acc) when Lbl =/= 0 ->
- split_block(Is, [], [{bif,N,Fail,As,R}|make_block(Bl, Acc)]);
-split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)
- when Lbl =/= 0 ->
- 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).
-
-make_block([], Acc) -> Acc;
-make_block([{set,[D],Ss,{bif,Op,Fail}}|Bl]=Bl0, Acc) ->
- %% If the last instruction in the block is a comparison or boolean operator
- %% (such as '=:='), move it out of the block to facilitate further
- %% optimizations.
- Arity = length(Ss),
- case erl_internal:comp_op(Op, Arity) orelse
- erl_internal:new_type_test(Op, Arity) orelse
- erl_internal:bool_op(Op, Arity) of
- false ->
- [{block,reverse(Bl0)}|Acc];
- true ->
- I = {bif,Op,Fail,Ss,D},
- case Bl =:= [] of
- true -> [I|Acc];
- false -> [I,{block,reverse(Bl)}|Acc]
- end
- end;
-make_block([{set,[Dst],[Src],move}|Bl], Acc) ->
- %% Make optimization of {move,Src,Dst}, {jump,...} possible.
- I = {move,Src,Dst},
- case Bl =:= [] of
- true -> [I|Acc];
- false -> [I,{block,reverse(Bl)}|Acc]
- end;
-make_block(Bl, Acc) -> [{block,reverse(Bl)}|Acc].
-
%% 'move' instructions outside of blocks may thwart the jump optimizer.
%% Move them back into the block.
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index ee76623976..531968b3c8 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -22,7 +22,7 @@
-export([new/0,opcode/2,highest_opcode/1,
atom/2,local/4,export/4,import/4,
- string/2,lambda/5,literal/2,line/2,fname/2,
+ string/2,lambda/3,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,
line_table/1]).
@@ -133,13 +133,18 @@ string(Str, Dict) when is_list(Str) ->
{NextOffset-Offset,Dict}
end.
-%% Returns the index for a funentry (adding it to the table if necessary).
-%% lambda(Lbl, Index, Uniq, NumFree, Dict) -> {Index,Dict'}
--spec lambda(label(), non_neg_integer(), integer(), non_neg_integer(), bdict()) ->
+%% Returns the index for a fun entry.
+%% lambda(Lbl, NumFree, Dict) -> {Index,Dict'}
+-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, Index, OldUniq, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
+lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
OldIndex = length(Lambdas0),
+ %% Set Index the same as OldIndex.
+ Index = OldIndex,
+ %% Initialize OldUniq to 0. It will be set to an unique value
+ %% based on the MD5 checksum of the BEAM code for the module.
+ OldUniq = 0,
Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
{OldIndex,Dict#asm{lambdas=Lambdas}}.
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 7103d2390f..62bdc74cc8 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -182,10 +182,14 @@ process_chunks(F) ->
Literals = beam_disasm_literals(LiteralBin),
Code = beam_disasm_code(CodeBin, Atoms, mk_imports(ImportsList),
StrBin, Lambdas, Literals, Module),
- Attributes = optional_chunk(F, attributes),
+ Attributes =
+ case optional_chunk(F, attributes) of
+ none -> [];
+ Atts when is_list(Atts) -> Atts
+ end,
CompInfo =
case optional_chunk(F, "CInf") of
- none -> none;
+ none -> [];
CompInfoBin when is_binary(CompInfoBin) ->
binary_to_term(CompInfoBin)
end,
@@ -198,7 +202,7 @@ process_chunks(F) ->
end.
%%-----------------------------------------------------------------------
-%% Retrieve an optional chunk or none if the chunk doesn't exist.
+%% Retrieve an optional chunk or return 'none' if the chunk doesn't exist.
%%-----------------------------------------------------------------------
optional_chunk(F, ChunkTag) ->
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
new file mode 100644
index 0000000000..fb1a43cd9e
--- /dev/null
+++ b/lib/compiler/src/beam_except.erl
@@ -0,0 +1,149 @@
+%%
+%% %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_except).
+-export([module/2]).
+
+%%% Rewrite certain calls to erlang:error/{1,2} to specialized
+%%% instructions:
+%%%
+%%% erlang:error({badmatch,Value}) => badmatch Value
+%%% erlang:error({case_clause,Value}) => case_end Value
+%%% erlang:error({try_clause,Value}) => try_case_end Value
+%%% erlang:error(if_clause) => if_end
+%%% erlang:error(function_clause, Args) => jump FuncInfoLabel
+%%%
+
+-import(lists, [reverse/1]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = [function(F) || F <- Fs0],
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}) ->
+ try
+ Is = function_1(Is0),
+ {function,Name,Arity,CLabel,Is}
+ catch
+ Class:Error ->
+ Stack = erlang:get_stacktrace(),
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+-record(st,
+ {lbl, %func_info label
+ loc %location for func_info
+ }).
+
+function_1(Is0) ->
+ case Is0 of
+ [{label,Lbl},{line,Loc}|_] ->
+ St = #st{lbl=Lbl,loc=Loc},
+ translate(Is0, St, []);
+ [{label,_}|_] ->
+ %% No line numbers. The source must be a .S file.
+ %% There is no need to do anything.
+ Is0
+ end.
+
+translate([{call_ext,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) ->
+ translate_1(Ar, I, Is, St, Acc);
+translate([{call_ext_only,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) ->
+ translate_1(Ar, I, Is, St, Acc);
+translate([{call_ext_last,Ar,{extfunc,erlang,error,Ar},_}=I|Is], St, Acc) ->
+ translate_1(Ar, I, Is, St, Acc);
+translate([I|Is], St, Acc) ->
+ translate(Is, St, [I|Acc]);
+translate([], _, Acc) ->
+ reverse(Acc).
+
+translate_1(Ar, I, Is, St, [{line,_}=Line|Acc1]=Acc0) ->
+ case dig_out(Ar, Acc1) of
+ no ->
+ translate(Is, St, [I|Acc0]);
+ {yes,function_clause,Acc2} ->
+ case {Line,St} of
+ {{line,Loc},#st{lbl=Fi,loc=Loc}} ->
+ Instr = {jump,{f,Fi}},
+ translate(Is, St, [Instr|Acc2]);
+ {_,_} ->
+ %% This must be "error(function_clause, Args)" in
+ %% the Erlang source code. Don't translate.
+ translate(Is, St, [I|Acc0])
+ end;
+ {yes,Instr,Acc2} ->
+ translate(Is, St, [Instr,Line|Acc2])
+ end.
+
+dig_out(Ar, [{kill,_}|Is]) ->
+ dig_out(Ar, Is);
+dig_out(1, [{block,Bl0}|Is]) ->
+ case dig_out_block(reverse(Bl0)) of
+ no -> no;
+ {yes,What,[]} ->
+ {yes,What,Is};
+ {yes,What,Bl} ->
+ {yes,What,[{block,Bl}|Is]}
+ end;
+dig_out(2, [{block,Bl}|Is]) ->
+ case dig_out_block_fc(Bl) of
+ no -> no;
+ {yes,What} -> {yes,What,Is}
+ end;
+dig_out(_, _) -> no.
+
+dig_out_block([{set,[{x,0}],[{atom,if_clause}],move}]) ->
+ {yes,if_end,[]};
+dig_out_block([{set,[{x,0}],[{literal,{Exc,Value}}],move}|Is]) ->
+ translate_exception(Exc, {literal,Value}, Is, 0);
+dig_out_block([{set,[{x,0}],[Tuple],move},
+ {set,[],[Value],put},
+ {set,[],[{atom,Exc}],put},
+ {set,[Tuple],[],{put_tuple,2}}|Is]) ->
+ translate_exception(Exc, Value, Is, 3);
+dig_out_block([{set,[],[Value],put},
+ {set,[],[{atom,Exc}],put},
+ {set,[{x,0}],[],{put_tuple,2}}|Is]) ->
+ translate_exception(Exc, Value, Is, 3);
+dig_out_block(_) -> no.
+
+translate_exception(badmatch, Val, Is, Words) ->
+ {yes,{badmatch,Val},fix_block(Is, Words)};
+translate_exception(case_clause, Val, Is, Words) ->
+ {yes,{case_end,Val},fix_block(Is, Words)};
+translate_exception(try_clause, Val, Is, Words) ->
+ {yes,{try_case_end,Val},fix_block(Is, Words)};
+translate_exception(_, _, _, _) -> no.
+
+fix_block(Is, 0) ->
+ reverse(Is);
+fix_block(Is0, Words) ->
+ [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] = reverse(Is0),
+ [{set,[],[],{alloc,Live,{F1,F2,Needed-Words,F3}}}|Is].
+
+dig_out_block_fc([{set,[],[],{alloc,Live,_}}|Bl]) ->
+ dig_out_fc(Bl, Live-1, nil);
+dig_out_block_fc(_) -> no.
+
+dig_out_fc([{set,[Dst],[{x,Reg},Dst0],put_list}|Is], Reg, Dst0) ->
+ dig_out_fc(Is, Reg-1, Dst);
+dig_out_fc([{set,[{x,0}],[{atom,function_clause}],move}], -1, {x,1}) ->
+ {yes,function_clause};
+dig_out_fc(_, _, _) -> no.
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 537f8ca81b..db67d24514 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.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
diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl
index 2941f6135c..50d1f3cdb1 100644
--- a/lib/compiler/src/beam_listing.erl
+++ b/lib/compiler/src/beam_listing.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
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index c483d85a97..bd1f44f66b 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.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
diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl
new file mode 100644
index 0000000000..cacaaebffe
--- /dev/null
+++ b/lib/compiler/src/beam_split.erl
@@ -0,0 +1,85 @@
+%%
+%% %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_split).
+-export([module/2]).
+
+-import(lists, [reverse/1]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
+ Fs = [split_blocks(F) || F <- Fs0],
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+%% 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.
+
+split_blocks({function,Name,Arity,CLabel,Is0}) ->
+ Is = split_blocks(Is0, []),
+ {function,Name,Arity,CLabel,Is}.
+
+split_blocks([{block,Bl}|Is], Acc0) ->
+ Acc = split_block(Bl, [], Acc0),
+ split_blocks(Is, Acc);
+split_blocks([I|Is], Acc) ->
+ split_blocks(Is, [I|Acc]);
+split_blocks([], Acc) -> reverse(Acc).
+
+split_block([{set,[R],[_,_,_]=As,{bif,is_record,{f,Lbl}}}|Is], Bl, Acc) ->
+ %% is_record/3 must be translated by beam_clean; therefore,
+ %% it must be outside of any block.
+ split_block(Is, [], [{bif,is_record,{f,Lbl},As,R}|make_block(Bl, Acc)]);
+split_block([{set,[R],As,{bif,N,{f,Lbl}=Fail}}|Is], Bl, Acc) when Lbl =/= 0 ->
+ split_block(Is, [], [{bif,N,Fail,As,R}|make_block(Bl, Acc)]);
+split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)
+ when Lbl =/= 0 ->
+ 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).
+
+make_block([], Acc) -> Acc;
+make_block([{set,[D],Ss,{bif,Op,Fail}}|Bl]=Bl0, Acc) ->
+ %% If the last instruction in the block is a comparison or boolean operator
+ %% (such as '=:='), move it out of the block to facilitate further
+ %% optimizations.
+ Arity = length(Ss),
+ case erl_internal:comp_op(Op, Arity) orelse
+ erl_internal:new_type_test(Op, Arity) orelse
+ erl_internal:bool_op(Op, Arity) of
+ false ->
+ [{block,reverse(Bl0)}|Acc];
+ true ->
+ I = {bif,Op,Fail,Ss,D},
+ case Bl =:= [] of
+ true -> [I|Acc];
+ false -> [I,{block,reverse(Bl)}|Acc]
+ end
+ end;
+make_block([{set,[Dst],[Src],move}|Bl], Acc) ->
+ %% Make optimization of {move,Src,Dst}, {jump,...} possible.
+ I = {move,Src,Dst},
+ case Bl =:= [] of
+ true -> [I|Acc];
+ false -> [I,{block,reverse(Bl)}|Acc]
+ end;
+make_block(Bl, Acc) -> [{block,reverse(Bl)}|Acc].
diff --git a/lib/compiler/src/beam_trim.erl b/lib/compiler/src/beam_trim.erl
index 25e6ffbb73..5f4fa3b1f8 100644
--- a/lib/compiler/src/beam_trim.erl
+++ b/lib/compiler/src/beam_trim.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
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 7fdb8d072a..d307d192b2 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.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
@@ -29,10 +29,17 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
{ok,{Mod,Exp,Attr,Fs,Lc}}.
function({function,Name,Arity,CLabel,Asm0}) ->
- Asm1 = beam_utils:live_opt(Asm0),
- Asm2 = opt(Asm1, [], tdb_new()),
- Asm = beam_utils:delete_live_annos(Asm2),
- {function,Name,Arity,CLabel,Asm}.
+ try
+ Asm1 = beam_utils:live_opt(Asm0),
+ Asm2 = opt(Asm1, [], tdb_new()),
+ Asm = beam_utils:delete_live_annos(Asm2),
+ {function,Name,Arity,CLabel,Asm}
+ catch
+ Class:Error ->
+ Stack = erlang:get_stacktrace(),
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
%% opt([Instruction], Accumulator, TypeDb) -> {[Instruction'],TypeDb'}
%% Keep track of type information; try to simplify.
@@ -168,6 +175,8 @@ simplify_float_1([{set,[D0],[A,B],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0, Ts0,
simplify_float_1([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
Acc = flush_all(Rs0, Is0, Acc0),
simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]);
+simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) ->
+ simplify_float_1(Is, Ts, Rs, [I|Acc]);
simplify_float_1([I|Is]=Is0, Ts0, Rs0, Acc0) ->
Ts = update(I, Ts0),
{Rs,Acc} = flush(Rs0, Is0, Acc0),
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index f281ad5eac..194f089ba1 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,8 +474,15 @@ check_liveness(R, [{make_fun2,_,_,_,NumFree}|Is], St) ->
end;
check_liveness(R, [{try_end,Y}|Is], St) ->
case R of
- Y -> {killed,St};
- _ -> check_liveness(R, Is, St)
+ Y ->
+ {killed,St};
+ {y,_} ->
+ %% y registers will be used if an exception occurs and
+ %% control transfers to the label given in the previous
+ %% try/2 instruction.
+ {used,St};
+ _ ->
+ check_liveness(R, Is, St)
end;
check_liveness(R, [{catch_end,Y}|Is], St) ->
case R of
@@ -734,6 +741,9 @@ live_opt([{badmatch,Src}=I|Is], _, D, Acc) ->
live_opt([{case_end,Src}=I|Is], _, D, Acc) ->
Regs = x_live([Src], 0),
live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{try_case_end,Src}=I|Is], _, D, Acc) ->
+ Regs = x_live([Src], 0),
+ live_opt(Is, Regs, D, [I|Acc]);
live_opt([if_end=I|Is], _, D, Acc) ->
Regs = 0,
live_opt(Is, Regs, D, [I|Acc]);
@@ -795,8 +805,6 @@ live_opt([{deallocate,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{kill,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{try_case_end,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
live_opt([{try_end,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{loop_rec_end,_}=I|Is], Regs, D, Acc) ->
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index fe3b1680d9..9f0bca9dd5 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.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
@@ -670,10 +670,20 @@ valfun_4({get_tuple_element,Src,I,Dst}, Vst) ->
valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
%% If source and destination registers are the same, match state
%% is OK as input.
- _ = get_move_term_type(Ctx, Vst0),
+ CtxType = get_move_term_type(Ctx, Vst0),
verify_live(Live, Vst0),
Vst1 = prune_x_regs(Live, Vst0),
- Vst = branch_state(Fail, Vst1),
+ BranchVst = case CtxType of
+ {match_context,_,_} ->
+ %% The failure branch will never be taken when Ctx
+ %% is a match context. Therefore, the type for Ctx
+ %% at the failure label must not be match_context
+ %% (or we could reject legal code).
+ set_type_reg(term, Ctx, Vst1);
+ _ ->
+ Vst1
+ end,
+ Vst = branch_state(Fail, BranchVst),
set_type_reg(bsm_match_state(NeedSlots), Ctx, Vst);
valfun_4({test,bs_start_match2,{f,Fail},Live,[Src,Slots],Dst}, Vst0) ->
assert_term(Src, Vst0),
@@ -773,15 +783,27 @@ valfun_4({bs_utf16_size,{f,Fail},A,Dst}, Vst) ->
valfun_4({bs_bits_to_bytes,{f,Fail},Src,Dst}, Vst) ->
assert_term(Src, Vst),
set_type_reg({integer,[]}, Dst, branch_state(Fail, Vst));
-valfun_4({bs_init2,{f,Fail},_,Heap,Live,_,Dst}, Vst0) ->
+valfun_4({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
verify_live(Live, Vst0),
+ if
+ is_integer(Sz) ->
+ ok;
+ true ->
+ assert_term(Sz, Vst0)
+ end,
Vst1 = heap_alloc(Heap, Vst0),
Vst2 = branch_state(Fail, Vst1),
Vst3 = prune_x_regs(Live, Vst2),
Vst = bs_zero_bits(Vst3),
set_type_reg(binary, Dst, Vst);
-valfun_4({bs_init_bits,{f,Fail},_,Heap,Live,_,Dst}, Vst0) ->
+valfun_4({bs_init_bits,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
verify_live(Live, Vst0),
+ if
+ is_integer(Sz) ->
+ ok;
+ true ->
+ assert_term(Sz, Vst0)
+ end,
Vst1 = heap_alloc(Heap, Vst0),
Vst2 = branch_state(Fail, Vst1),
Vst3 = prune_x_regs(Live, Vst2),
diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl
index c15103999f..2e7554c1ff 100644
--- a/lib/compiler/src/cerl_inline.erl
+++ b/lib/compiler/src/cerl_inline.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1262,8 +1262,9 @@ i_receive_1(E, Cs, T, B, S) ->
i_module(E, Ctxt, Ren, Env, S) ->
%% Cf. `i_letrec'. Note that we pass a dummy constant value for the
%% "body" parameter.
+ Exps = i_module_exports(E),
{Es, _, Xs1, S1} = i_letrec(module_defs(E), void(),
- module_exports(E), Ctxt, Ren, Env, S),
+ Exps, Ctxt, Ren, Env, S),
%% Sanity check:
case Es of
[] ->
@@ -1276,6 +1277,27 @@ i_module(E, Ctxt, Ren, Env, S) ->
E1 = update_c_module(E, module_name(E), Xs1, module_attrs(E), Es),
{E1, count_size(weight(module), S1)}.
+i_module_exports(E) ->
+ %% If a function is named in an `on_load' attribute, we will
+ %% pretend that it is exported to ensure that it will not be removed.
+ Exps = module_exports(E),
+ Attrs = module_attrs(E),
+ case i_module_on_load(Attrs) of
+ none ->
+ Exps;
+ [{_,_}=FA] ->
+ ordsets:add_element(c_var(FA), Exps)
+ end.
+
+i_module_on_load([{Key,Val}|T]) ->
+ case concrete(Key) of
+ on_load ->
+ concrete(Val);
+ _ ->
+ i_module_on_load(T)
+ end;
+i_module_on_load([]) -> none.
+
%% 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
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index bfa7c6cedd..7365706b94 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -146,10 +146,17 @@ env_default_opts() ->
do_compile(Input, Opts0) ->
Opts = expand_opts(Opts0),
- Self = self(),
- Serv = spawn_link(fun() -> internal(Self, Input, Opts) end),
+ {Pid,Ref} =
+ spawn_monitor(fun() ->
+ exit(try
+ internal(Input, Opts)
+ catch
+ error:Reason ->
+ {error,Reason}
+ end)
+ end),
receive
- {Serv,Rep} -> Rep
+ {'DOWN',Ref,process,Pid,Rep} -> Rep
end.
expand_opts(Opts0) ->
@@ -175,6 +182,8 @@ expand_opt(r12, Os) ->
[no_recv_opt,no_line_info|Os];
expand_opt(r13, Os) ->
[no_recv_opt,no_line_info|Os];
+expand_opt(r14, Os) ->
+ [no_line_info|Os];
expand_opt({debug_info_key,_}=O, Os) ->
[encrypt_debug_info,O|Os];
expand_opt(no_float_opt, Os) ->
@@ -235,21 +244,20 @@ format_error({module_name,Mod,Filename}) ->
code=[],
core_code=[],
abstract_code=[], %Abstract code for debugger.
- options=[] :: [option()],
+ options=[] :: [option()], %Options for compilation
+ mod_options=[] :: [option()], %Options for module_info
errors=[],
warnings=[]}).
-internal(Master, Input, Opts) ->
- Master ! {self(), try internal(Input, Opts)
- catch error:Reason -> {error, Reason}
- end}.
-
-internal({forms,Forms}, Opts) ->
- {_,Ps} = passes(forms, Opts),
- internal_comp(Ps, "", "", #compile{code=Forms,options=Opts});
+internal({forms,Forms}, Opts0) ->
+ {_,Ps} = passes(forms, Opts0),
+ Source = proplists:get_value(source, Opts0, ""),
+ Opts1 = proplists:delete(source, Opts0),
+ Compile = #compile{code=Forms,options=Opts1,mod_options=Opts1},
+ internal_comp(Ps, Source, "", Compile);
internal({file,File}, Opts) ->
{Ext,Ps} = passes(file, Opts),
- Compile = #compile{options=Opts},
+ Compile = #compile{options=Opts,mod_options=Opts},
internal_comp(Ps, File, Ext, Compile).
internal_comp(Passes, File, Suffix, St0) ->
@@ -625,11 +633,15 @@ asm_passes() ->
[{unless,no_postopt,
[{pass,beam_block},
{iff,dblk,{listing,"block"}},
+ {unless,no_except,{pass,beam_except}},
+ {iff,dexcept,{listing,"except"}},
{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.
+ {pass,beam_split},
+ {iff,dsplit,{listing,"split"}},
+ {unless,no_dead,{pass,beam_dead}},
{iff,ddead,{listing,"dead"}},
{unless,no_jopt,{pass,beam_jump}},
{iff,djmp,{listing,"jump"}},
@@ -1228,12 +1240,13 @@ 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) ->
+beam_asm(#compile{ifile=File,code=Code0,
+ abstract_code=Abst,mod_options=Opts0}=St) ->
Source = filename:absname(File),
Opts1 = lists:map(fun({debug_info_key,_}) -> {debug_info_key,'********'};
(Other) -> Other
end, Opts0),
- Opts2 = [O || O <- Opts1, is_informative_option(O)],
+ Opts2 = [O || O <- Opts1, effects_code_generation(O)],
case beam_asm:module(Code0, Abst, Source, Opts2) of
{ok,Code} -> {ok,St#compile{code=Code,abstract_code=[]}}
end.
@@ -1303,15 +1316,23 @@ embed_native_code(St, {Architecture,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.
+%% effects_code_generation(Option) -> true|false.
+%% Determine whether the option could have any effect on the
+%% generated code in the BEAM file (as opposed to how
+%% errors will be reported).
+
+effects_code_generation(Option) ->
+ case Option of
+ beam -> false;
+ report_warnings -> false;
+ report_errors -> false;
+ return_errors-> false;
+ return_warnings-> false;
+ binary -> false;
+ verbose -> false;
+ {cwd,_} -> false;
+ _ -> true
+ end.
save_binary(#compile{code=none}=St) -> {ok,St};
save_binary(#compile{module=Mod,ofile=Outfile,
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index 4ac879c9a4..1133882728 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -1,7 +1,7 @@
% This is an -*- erlang -*- file.
%% %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,14 @@
beam_dead,
beam_dict,
beam_disasm,
+ beam_except,
beam_flatten,
beam_jump,
beam_listing,
beam_opcodes,
beam_peep,
beam_receive,
+ beam_split,
beam_trim,
beam_type,
beam_utils,
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index 2514c06360..9ad2378d00 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.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
@@ -136,6 +136,7 @@ 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(math, pi, 0) -> true;
is_pure(_, _, _) -> false.
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index 39c1e8297f..75ac91907a 100644
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -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
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 6ea67741fa..18fba7962b 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -150,14 +150,26 @@ guard(Expr, Sub) ->
opt_guard_try(#c_seq{arg=Arg,body=Body0}=Seq) ->
Body = opt_guard_try(Body0),
case {Arg,Body} of
- {#c_call{},#c_literal{val=false}} ->
- %% We have sequence consisting of a call (evaluted
- %% for a possible exception only), followed by 'false'.
- %% Since the sequence is inside a try block that will
+ {#c_call{module=#c_literal{val=Mod},
+ name=#c_literal{val=Name},
+ args=Args},#c_literal{val=false}} ->
+ %% We have sequence consisting of a call (evaluated
+ %% for a possible exception and/or side effect only),
+ %% followed by 'false'.
+ %% Since the sequence is inside a try block that will
%% default to 'false' if any exception occurs, not
%% evalutating the call will not change the behaviour
- %% of the guard.
- Body;
+ %% provided that the call has no side effects.
+ case erl_bifs:is_pure(Mod, Name, length(Args)) of
+ false ->
+ %% Not a pure BIF (meaning that this is not
+ %% a guard and that we must keep the call).
+ Seq#c_seq{body=Body};
+ true ->
+ %% The BIF has no side effects, so it can
+ %% be safely removed.
+ Body
+ end;
{_,_} ->
Seq#c_seq{body=Body}
end;
@@ -1747,36 +1759,26 @@ opt_bool_clauses([_|_], _, _) ->
%% end. NewVar ->
%% erlang:error(badarg)
%% end.
-%%
-%% We add the extra match-all clause at the end only if Expr is
-%% not guaranteed to evaluate to a boolean.
opt_bool_not(#c_case{arg=Arg,clauses=Cs0}=Case0) ->
case Arg of
#c_call{anno=Anno,module=#c_literal{val=erlang},
name=#c_literal{val='not'},
args=[Expr]} ->
- Cs = opt_bool_not(Anno, Expr, Cs0),
+ Cs = [opt_bool_not_invert(C) || C <- Cs0] ++
+ [#c_clause{anno=[compiler_generated],
+ pats=[#c_var{name=cor_variable}],
+ guard=#c_literal{val=true},
+ body=#c_call{anno=Anno,
+ module=#c_literal{val=erlang},
+ name=#c_literal{val=error},
+ args=[#c_literal{val=badarg}]}}],
Case = Case0#c_case{arg=Expr,clauses=Cs},
opt_bool_not(Case);
_ ->
opt_bool_case_redundant(Case0)
end.
-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{anno=Anno,
- module=#c_literal{val=erlang},
- name=#c_literal{val=error},
- args=[#c_literal{val=badarg}]}}];
- true -> []
- end,
- [opt_bool_not_invert(C) || C <- Cs] ++ Tail.
-
opt_bool_not_invert(#c_clause{pats=[#c_literal{val=Bool}]}=C) ->
C#c_clause{pats=[#c_literal{val=not Bool}]}.
@@ -2065,32 +2067,7 @@ opt_case_in_let_2(V, Arg0,
(_) -> false end, Es), %Only variables in tuple
false = core_lib:is_var_used(V, B), %Built tuple must not be used.
Arg1 = tuple_to_values(Arg0, length(Es)), %Might fail.
- #c_let{vars=Es,arg=Arg1,body=B};
-opt_case_in_let_2(_, Arg, Cs) ->
- %% simplify_bool_case(Case0) -> Case
- %% Remove unecessary cases like
- %%
- %% case BoolExpr of
- %% true -> true;
- %% false -> false;
- %% ....
- %% end
- %%
- %% where BoolExpr is an expression that can only return true
- %% or false (or throw an exception).
-
- true = is_bool_case(Cs) andalso is_bool_expr(Arg),
- Arg.
-
-is_bool_case([A,B|_]) ->
- (is_bool_clause(true, A) andalso is_bool_clause(false, B))
- orelse (is_bool_clause(false, A) andalso is_bool_clause(true, B)).
-
-is_bool_clause(Bool, #c_clause{pats=[#c_literal{val=Bool}],
- guard=#c_literal{val=true},
- body=#c_literal{val=Bool}}) ->
- true;
-is_bool_clause(_, _) -> false.
+ #c_let{vars=Es,arg=Arg1,body=B}.
%% is_simple_case_arg(Expr) -> true|false
%% Determine whether the Expr is simple enough to be worth
@@ -2612,14 +2589,14 @@ bsm_maybe_ctx_to_binary(V, B) ->
body=B}
end.
-previous_ctx_to_binary(V, #c_seq{arg=#c_primop{name=Name,args=As}}) ->
- case {Name,As} of
- {#c_literal{val=bs_context_to_binary},[#c_var{name=V}]} ->
+previous_ctx_to_binary(V, Core) ->
+ case Core of
+ #c_seq{arg=#c_primop{name=#c_literal{val=bs_context_to_binary},
+ args=[#c_var{name=V}]}} ->
true;
- {_,_} ->
+ _ ->
false
- end;
-previous_ctx_to_binary(_, _) -> false.
+ end.
%% bsm_leftmost(Cs) -> none | ArgumentNumber
%% Find the leftmost argument that does binary matching. Return
@@ -2641,9 +2618,9 @@ bsm_leftmost_2([_|Ps], Cs, N, Pos) ->
bsm_leftmost_2([], Cs, _, Pos) ->
bsm_leftmost_1(Cs, Pos).
-%% bsm_notempty(Cs, Pos) -> true|false
+%% bsm_nonempty(Cs, Pos) -> true|false
%% Check if at least one of the clauses matches a non-empty
-%% binary in the given argumet position.
+%% binary in the given argument position.
%%
bsm_nonempty([#c_clause{pats=Ps}|Cs], Pos) ->
case nth(Pos, Ps) of
@@ -2704,7 +2681,7 @@ bsm_ensure_no_partition_2([P|_], 1, _, Vstate, State) ->
%%
%% But if the clauses can't be freely rearranged, as in
%%
- %% b(Var, <<>>) -> ...
+ %% b(Var, <<X>>) -> ...
%% b(1, 2) -> ...
%%
%% we do have a problem.
@@ -2764,22 +2741,20 @@ add_bin_opt_info(Core, Term) ->
end.
add_warning(Core, Term) ->
- Anno = core_lib:get_anno(Core),
- case lists:member(compiler_generated, Anno) of
- true -> ok;
+ case is_compiler_generated(Core) of
+ true ->
+ ok;
false ->
- case get_line(Anno) of
- Line when Line >= 0 -> %Must be positive.
- File = get_file(Anno),
- Key = {?MODULE,warnings},
- case get(Key) of
- [{File,[{Line,?MODULE,Term}]}|_] ->
- ok; %We already have
+ Anno = core_lib:get_anno(Core),
+ Line = get_line(Anno),
+ File = get_file(Anno),
+ Key = {?MODULE,warnings},
+ case get(Key) of
+ [{File,[{Line,?MODULE,Term}]}|_] ->
+ ok; %We already have
%an identical warning.
- Ws ->
- put(Key, [{File,[{Line,?MODULE,Term}]}|Ws])
- end;
- _ -> ok %Compiler-generated code.
+ Ws ->
+ put(Key, [{File,[{Line,?MODULE,Term}]}|Ws])
end
end.
@@ -2793,14 +2768,7 @@ get_file([]) -> "no_file". % should not happen
is_compiler_generated(Core) ->
Anno = core_lib:get_anno(Core),
- case lists:member(compiler_generated, Anno) of
- true -> true;
- false ->
- case get_line(Anno) of
- Line when Line >= 0 -> false;
- _ -> true
- end
- end.
+ member(compiler_generated, Anno).
get_warnings() ->
ordsets:from_list((erase({?MODULE,warnings}))).
diff --git a/lib/compiler/src/sys_expand_pmod.erl b/lib/compiler/src/sys_expand_pmod.erl
index 4fee26f2a6..da644b4f0b 100644
--- a/lib/compiler/src/sys_expand_pmod.erl
+++ b/lib/compiler/src/sys_expand_pmod.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
@@ -317,6 +317,8 @@ expr({'try',Line,Es0,Scs0,Ccs0,As0},St) ->
Ccs1 = icr_clauses(Ccs0,St),
As1 = exprs(As0,St),
{'try',Line,Es1,Scs1,Ccs1,As1};
+expr({'fun',_,{function,_,_,_}}=ExtFun,_St) ->
+ ExtFun;
expr({'fun',Line,Body,Info},St) ->
case Body of
{clauses,Cs0} ->
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 0fa1fea09f..6cea783090 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -31,8 +31,6 @@
-import(ordsets, [from_list/1,add_element/2,union/2]).
-import(lists, [member/2,foldl/3,foldr/3]).
--compile({nowarn_deprecated_function, {erlang,hash,2}}).
-
-include("../include/erl_bits.hrl").
-record(expand, {module=[], %Module name
@@ -44,12 +42,11 @@
compile=[], %Compile flags
attributes=[], %Attributes
callbacks=[], %Callbacks
- defined=[], %Defined functions
+ defined, %Defined functions (gb_set)
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
}).
@@ -86,7 +83,7 @@ module(Fs0, Opts0) ->
{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;
+ true -> gb_sets:to_list(St2#expand.defined);
false -> St2#expand.exports
end,
%% Generate all functions from stored info.
@@ -109,10 +106,11 @@ expand_pmod(Fs0, St0) ->
true ->
Ps0
end,
+ Def = gb_sets:to_list(St0#expand.defined),
{Fs1,Xs,Ds} = sys_expand_pmod:forms(Fs0, Ps,
St0#expand.exports,
- St0#expand.defined),
- St1 = St0#expand{exports=Xs, defined=Ds},
+ Def),
+ St1 = St0#expand{exports=Xs,defined=gb_sets:from_list(Ds)},
{Fs2,St2} = add_instance(Ps, Fs1, St1),
{Fs3,St3} = ensure_new(Base, Ps0, Fs2, St2),
{Fs3,St3#expand{attributes = [{abstract, 0, [true]}
@@ -121,7 +119,7 @@ expand_pmod(Fs0, St0) ->
get_base(As) ->
case lists:keyfind(extends, 1, As) of
- {extends,[Base]} when is_atom(Base) ->
+ {extends,_,[Base]} when is_atom(Base) ->
Base;
_ ->
[]
@@ -162,7 +160,7 @@ add_func(Name, Args, Body, Fs, St) ->
F = {function,0,Name,A,[{clause,0,Args,[],Body}]},
NA = {Name,A},
{[F|Fs],St#expand{exports=add_element(NA, St#expand.exports),
- defined=add_element(NA, St#expand.defined)}}.
+ defined=gb_sets:add_element(NA, St#expand.defined)}}.
%% define_function(Form, State) -> State.
%% Add function to defined if form is a function.
@@ -171,7 +169,7 @@ define_functions(Forms, #expand{defined=Predef}=St) ->
Fs = foldl(fun({function,_,N,A,_Cs}, Acc) -> [{N,A}|Acc];
(_, Acc) -> Acc
end, Predef, Forms),
- St#expand{defined=ordsets:from_list(Fs)}.
+ St#expand{defined=gb_sets:from_list(Fs)}.
module_attrs(#expand{attributes=Attributes}=St) ->
Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes],
@@ -190,7 +188,7 @@ module_predef_func_beh_info(#expand{callbacks=Callbacks,defined=Defined,
PreDef=[{behaviour_info,1}],
PreExp=PreDef,
{[gen_beh_info(Callbacks)],
- St#expand{defined=union(from_list(PreDef), Defined),
+ St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), Defined),
exports=union(from_list(PreExp), Exports)}}.
gen_beh_info(Callbacks) ->
@@ -218,7 +216,8 @@ module_predef_funcs_mod_info(St) ->
[{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),
+ St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef),
+ St#expand.defined),
exports=union(from_list(PreExp), St#expand.exports)}}.
%% forms(Forms, State) ->
@@ -538,32 +537,34 @@ lc_tq(_Line, [], St0) ->
%% 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}=Function, 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 ->
+ {As,St1} = new_vars(A, Lf, St0),
+ Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
fun_tq(Lf, {clauses,Cs}, St1);
false ->
- Index = St0#expand.fun_index,
- Uniq = erlang:hash(Cs, (1 bsl 27)-1),
- {Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,Function,{Index,Uniq,Fname}},
- St2#expand{fun_index=Index+1}}
+ {Fname,St1} = new_fun_name(St0),
+ Index = Uniq = 0,
+ {{'fun',Lf,Function,{Index,Uniq,Fname}},St1}
end;
-fun_tq(L, {function,M,F,A}, St) ->
- {{call,L,{remote,L,{atom,L,erlang},{atom,L,make_fun}},
- [{atom,L,M},{atom,L,F},{integer,L,A}]},St};
+fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) ->
+ %% This is the old format for external funs, generated by a pre-R15
+ %% compiler. That means that a tool, such as the debugger or xref,
+ %% directly invoked this module with the abstract code from a
+ %% pre-R15 BEAM file. Be helpful, and translate it to the new format.
+ fun_tq(L, {function,{atom,L,M},{atom,L,F},{integer,L,A}}, St);
+fun_tq(Lf, {function,_,_,_}=ExtFun, St) ->
+ {{'fun',Lf,ExtFun},St};
fun_tq(Lf, {clauses,Cs0}, St0) ->
- Uniq = erlang:hash(Cs0, (1 bsl 27)-1),
{Cs1,St1} = fun_clauses(Cs0, St0),
- Index = St1#expand.fun_index,
{Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},
- St2#expand{fun_index=Index+1}}.
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
+ {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},St2}.
fun_clauses([{clause,L,H0,G0,B0}|Cs0], St0) ->
{H,St1} = head(H0, St0),
@@ -722,4 +723,4 @@ imported(F, A, St) ->
end.
defined(F, A, St) ->
- ordsets:is_element({F,A}, St#expand.defined).
+ gb_sets:is_element({F,A}, St#expand.defined).
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index e7dae67085..be15495672 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,6 @@
%% Main codegen structure.
-record(cg, {lcount=1, %Label counter
- finfo, %Function info label
bfail, %Fail label for BIFs
break, %Break label
recv, %Receive label
@@ -126,7 +125,6 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
stk=[]}, 0, Vdb),
{B,_Aft,St} = cg_list(Les, 0, Vdb, Bef,
St3#cg{bfail=0,
- finfo=Fi,
ultimate_failure=UltimateMatchFail,
is_top_block=true}),
{Name,Arity} = NameArity,
@@ -147,8 +145,6 @@ cg({match,M,Rs}, Le, Vdb, Bef, St) ->
match_cg(M, Rs, Le, Vdb, Bef, St);
cg({guard_match,M,Rs}, Le, Vdb, Bef, St) ->
guard_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) ->
@@ -294,39 +290,6 @@ match_cg({block,Es}, Le, _Fail, Bef, St) ->
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 ++ [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++[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++[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 ++ [line(Le),{try_case_end,R}],
- Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
-
%% bsm_rename_ctx([Clause], Var) -> [Clause]
%% We know from an annotation that the register for a binary can
%% be reused for the match context because the two are not truly
@@ -1460,20 +1423,7 @@ set_cg([{var,R}], Con, Le, Vdb, Bef, St) ->
Other ->
[{move,Other,Ret}]
end,
- {Ais,clear_dead(Int, Le#l.i, Vdb),St};
-set_cg([], {binary,Segs}, Le, Vdb, Bef, St) ->
- Fail = {f,St#cg.bfail},
- Target = find_scratch_reg(Bef#sr.reg),
- Temp = find_scratch_reg(put_reg(Target, Bef#sr.reg)),
- PutCode = cg_bin_put(Segs, Fail, Bef),
- MaxRegs = max_reg(Bef#sr.reg),
- Code = cg_binary(PutCode, Target, Temp, Fail, MaxRegs, Le#l.a),
- Aft = clear_dead(Bef, Le#l.i, Vdb),
- {Code,Aft,St};
-set_cg([], _, Le, Vdb, Bef, St) ->
- %% This should have been stripped by compiler, just cleanup.
- {[],clear_dead(Bef, Le#l.i, Vdb), St}.
-
+ {Ais,clear_dead(Int, Le#l.i, Vdb),St}.
%%%
%%% Code generation for constructing binaries.
@@ -2104,7 +2054,7 @@ line_1(_, 0) ->
%% Missing line number or line number 0.
{line,[]};
line_1(Name, Line) ->
- {line,[{location,Name,abs(Line)}]}.
+ {line,[{location,Name,Line}]}.
find_loc([Line|T], File, _) when is_integer(Line) ->
find_loc(T, File, Line);
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 6f3590b156..01042cc56f 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -573,6 +573,13 @@ expr({'catch',L,E0}, St0) ->
expr({'fun',L,{function,F,A},{_,_,_}=Id}, St) ->
Lanno = lineno_anno(L, St),
{#c_var{anno=Lanno++[{id,Id}],name={F,A}},[],St};
+expr({'fun',L,{function,M,F,A}}, St0) ->
+ {As,Aps,St1} = safe_list([M,F,A], St0),
+ Lanno = lineno_anno(L, St1),
+ {#icall{anno=#a{anno=Lanno},
+ module=#c_literal{val=erlang},
+ name=#c_literal{val=make_fun},
+ args=As},Aps,St1};
expr({'fun',L,{clauses,Cs},Id}, St) ->
fun_tq(Id, Cs, L, St);
expr({call,L,{remote,_,M,F},As0}, #core{wanted=Wanted}=St0) ->
@@ -816,6 +823,13 @@ bitstr({bin_element,_,E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
{_,_} ->
throw(bad_binary)
end,
+ case Size1 of
+ #c_var{} -> ok;
+ #c_literal{val=Sz} when is_integer(Sz), Sz >= 0 -> ok;
+ #c_literal{val=undefined} -> ok;
+ #c_literal{val=all} -> ok;
+ _ -> throw(bad_binary)
+ end,
{#c_bitstr{val=E1,size=Size1,
unit=#c_literal{val=Unit},
type=#c_literal{val=Type},
@@ -2078,7 +2092,12 @@ bitstr_vars(Segs, Vs) ->
lineno_anno(L, St) ->
{line, Line} = erl_parse:get_attribute(L, line),
- [Line] ++ St#core.file.
+ if
+ Line < 0 ->
+ [-Line] ++ St#core.file ++ [compiler_generated];
+ true ->
+ [Line] ++ St#core.file
+ end.
get_ianno(Ce) ->
case get_anno(Ce) of
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 4e06b464a4..b184987625 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,14 +83,11 @@
-import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,member/2,
keymember/3,keyfind/3]).
-import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
-
--compile({nowarn_deprecated_function, {erlang,hash,2}}).
+-import(cerl, [c_tuple/1]).
-include("core_parse.hrl").
-include("v3_kernel.hrl").
--define(EXPENSIVE_BINARY_LIMIT, 256).
-
%% These are not defined in v3_kernel.hrl.
get_kanno(Kthing) -> element(2, Kthing).
set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
@@ -121,7 +118,6 @@ copy_anno(Kdst, Ksrc) ->
funs=[], %Fun functions
free=[], %Free variables
ws=[] :: [warning()], %Warnings.
- lit, %Constant pool for literals.
guard_refc=0}). %> 0 means in guard
-spec module(cerl:c_module(), [compile:option()]) ->
@@ -130,7 +126,7 @@ copy_anno(Kdst, Ksrc) ->
module(#c_module{anno=A,name=M,exports=Es,attrs=As,defs=Fs}, _Options) ->
Kas = attributes(As),
Kes = map(fun (#c_var{name={_,_}=Fname}) -> Fname end, Es),
- St0 = #kern{lit=dict:new()},
+ St0 = #kern{},
{Kfs,St} = mapfoldl(fun function/2, St0, Fs),
{ok,#k_mdef{anno=A,name=M#c_literal.val,exports=Kes,attributes=Kas,
body=Kfs ++ St#kern.funs},lists:sort(St#kern.ws)}.
@@ -251,26 +247,20 @@ expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) ->
expr(Fun, Sub, St);
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
-expr(#c_literal{}=Lit, Sub, St) ->
- Core = handle_literal(Lit),
- expr(Core, Sub, St);
-expr(#k_literal{val=Val0}=Klit, _Sub, #kern{lit=Literals0}=St) ->
- %% Share identical literals to save some space and time during compilation.
- case dict:find(Val0, Literals0) of
- {ok,Val} ->
- {Klit#k_literal{val=Val},[],St};
- error ->
- Literals = dict:store(Val0, Val0, Literals0),
- {Klit,[],St#kern{lit=Literals}}
- end;
-expr(#k_nil{}=V, _Sub, St) ->
- {V,[],St};
-expr(#k_int{}=V, _Sub, St) ->
- {V,[],St};
-expr(#k_float{}=V, _Sub, St) ->
- {V,[],St};
-expr(#k_atom{}=V, _Sub, St) ->
- {V,[],St};
+expr(#c_literal{anno=A,val=V}, _Sub, St) ->
+ Klit = case V of
+ [] ->
+ #k_nil{anno=A};
+ V when is_integer(V) ->
+ #k_int{anno=A,val=V};
+ V when is_float(V) ->
+ #k_float{anno=A,val=V};
+ V when is_atom(V) ->
+ #k_atom{anno=A,val=V};
+ _ ->
+ #k_literal{anno=A,val=V}
+ end,
+ {Klit,[],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.
@@ -288,11 +278,12 @@ expr(#c_binary{anno=A,segments=Cv}, Sub, St0) ->
{#k_binary{anno=A,segs=Kv},Ep,St1}
catch
throw:bad_element_size ->
+ St1 = add_warning(get_line(A), bad_segment_size, A, St0),
Erl = #c_literal{val=erlang},
Name = #c_literal{val=error},
Args = [#c_literal{val=badarg}],
Error = #c_call{anno=A,module=Erl,name=Name,args=Args},
- expr(Error, Sub, St0)
+ expr(Error, Sub, St1)
end;
expr(#c_fun{anno=A,vars=Cvs,body=Cb}, Sub0, #kern{ff=OldFF,func=Func}=St0) ->
FA = case OldFF of
@@ -424,10 +415,11 @@ expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) ->
end;
expr(#c_primop{anno=A,name=#c_literal{val=match_fail},args=Cargs0}, Sub, St0) ->
Cargs = translate_match_fail(Cargs0, Sub, A, St0),
- %% This special case will disappear.
{Kargs,Ap,St} = atomic_list(Cargs, Sub, St0),
Ar = length(Cargs),
- Call = #k_call{anno=A,op=#k_internal{name=match_fail,arity=Ar},args=Kargs},
+ Call = #k_call{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=error},
+ arity=Ar},args=Kargs},
{Call,Ap,St};
expr(#c_primop{anno=A,name=#c_literal{val=N},args=Cargs}, Sub, St0) ->
{Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
@@ -457,14 +449,14 @@ expr(#ireceive_accept{anno=A}, _Sub, St) -> {#k_receive_accept{anno=A},[],St}.
translate_match_fail(Args, Sub, Anno, St) ->
case Args of
[#c_tuple{es=[#c_literal{val=function_clause}|As]}] ->
- translate_match_fail_1(Anno, Args, As, Sub, St);
+ translate_match_fail_1(Anno, As, Sub, St);
[#c_literal{val=Tuple}] when is_tuple(Tuple) ->
%% The inliner may have created a literal out of
%% the original #c_tuple{}.
case tuple_to_list(Tuple) of
[function_clause|As0] ->
As = [#c_literal{val=E} || E <- As0],
- translate_match_fail_1(Anno, Args, As, Sub, St);
+ translate_match_fail_1(Anno, As, Sub, St);
_ ->
Args
end;
@@ -473,7 +465,7 @@ translate_match_fail(Args, Sub, Anno, St) ->
Args
end.
-translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) ->
+translate_match_fail_1(Anno, As, Sub, #kern{ff=FF}) ->
AnnoFunc = case keyfind(function_name, 1, Anno) of
false ->
none; %Force rewrite.
@@ -483,10 +475,10 @@ translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) ->
case {AnnoFunc,FF} of
{Same,Same} ->
%% Still in the correct function.
- Args;
+ translate_fc(As);
{{F,_},F} ->
%% Still in the correct function.
- Args;
+ translate_fc(As);
_ ->
%% Wrong function or no function_name annotation.
%%
@@ -495,9 +487,12 @@ translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) ->
%% the current function). match_fail(function_clause) will
%% only work at the top level of the function it was originally
%% defined in, so we will need to rewrite it to a case_clause.
- [#c_tuple{es=[#c_literal{val=case_clause},#c_tuple{es=As}]}]
+ [c_tuple([#c_literal{val=case_clause},c_tuple(As)])]
end.
+translate_fc(Args) ->
+ [#c_literal{val=function_clause},make_list(Args)].
+
%% call_type(Module, Function, Arity) -> call | bif | apply | error.
%% Classify the call.
call_type(#c_literal{val=M}, #c_literal{val=F}, Ar) when is_atom(M), is_atom(F) ->
@@ -607,7 +602,6 @@ 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.
@@ -916,9 +910,8 @@ match_guard_1([#iclause{anno=A,osub=Osub,guard=G,body=B}|Cs0], Def0, St0) ->
true ->
%% The true clause body becomes the default.
{Kb,Pb,St1} = body(B, Osub, St0),
- Line = get_line(A),
- St2 = maybe_add_warning(Cs0, Line, St1),
- St = maybe_add_warning(Def0, Line, St2),
+ St2 = maybe_add_warning(Cs0, A, St1),
+ St = maybe_add_warning(Def0, A, St2),
{[],pre_seq(Pb, Kb),St};
false ->
{Kg,St1} = guard(G, Osub, St0),
@@ -929,15 +922,18 @@ match_guard_1([#iclause{anno=A,osub=Osub,guard=G,body=B}|Cs0], Def0, St0) ->
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 ->
+maybe_add_warning([C|_], MatchAnno, St) ->
+ maybe_add_warning(C, MatchAnno, St);
+maybe_add_warning([], _MatchAnno, St) -> St;
+maybe_add_warning(fail, _MatchAnno, St) -> St;
+maybe_add_warning(Ke, MatchAnno, St) ->
+ case is_compiler_generated(Ke) of
+ true ->
+ St;
+ false ->
+ Anno = get_kanno(Ke),
Line = get_line(Anno),
+ MatchLine = get_line(MatchAnno),
Warn = case MatchLine of
none -> nomatch_shadow;
_ -> {nomatch_shadow,MatchLine}
@@ -1119,7 +1115,6 @@ select_bin_int([#iclause{pats=[#k_bin_seg{anno=A,type=integer,
end,
select_assert_match_possible(Bits, Val, Fl),
P = #k_bin_int{anno=A,size=Sz,unit=U,flags=Fl,val=Val,next=N},
- select_assert_match_possible(Bits, Val, Fl),
case member(native, Fl) of
true -> throw(not_possible);
false -> ok
@@ -1261,8 +1256,6 @@ match_clause([U|Us], [C|_]=Cs0, Def, St0) ->
sub_size_var(#k_bin_seg{size=#k_var{name=Name}=Kvar}=BinSeg, [#iclause{isub=Sub}|_]) ->
BinSeg#k_bin_seg{size=Kvar#k_var{name=get_vsub(Name, Sub)}};
-sub_size_var(#k_bin_int{size=#k_var{name=Name}=Kvar}=BinSeg, [#iclause{isub=Sub}|_]) ->
- BinSeg#k_bin_int{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
@@ -1380,7 +1373,6 @@ arg_con(Arg) ->
#k_tuple{} -> k_tuple;
#k_binary{} -> k_binary;
#k_bin_end{} -> k_bin_end;
- #k_bin_int{} -> k_bin_int;
#k_bin_seg{} -> k_bin_seg;
#k_var{} -> k_var
end.
@@ -1391,15 +1383,9 @@ arg_val(Arg) ->
#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_int{} ->
- 0;
- #k_bin_end{} -> 0;
- #k_binary{} -> 0
+ {set_kanno(S, []),U,T,Fs}
end.
%% ubody_used_vars(Expr, State) -> [UsedVar]
@@ -1429,14 +1415,12 @@ ubody(#ivalues{anno=A,args=As}, return, St) ->
{#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),
- if St#kern.guard_refc > 0 ->
+ case is_in_guard(St) of
+ true ->
{#k_guard_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St};
- true ->
+ false ->
{#k_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St}
end;
-ubody(#ivalues{anno=A,args=As}, {guard_break,_Vbs}, St) ->
- Au = lit_list_vars(As),
- {#k_guard_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
@@ -1453,12 +1437,7 @@ ubody(E, {break,_Rs} = Break, St0) ->
false ->
{Ea,Pa,St1} = force_atomic(E, St0),
ubody(pre_seq(Pa, #ivalues{args=[Ea]}), Break, St1)
- end;
-ubody(E, {guard_break,_Rs} = GuardBreak, St0) ->
- %%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]),
- %% Exiting expressions need no trailing break.
- {Ea,Pa,St1} = force_atomic(E, St0),
- ubody(pre_seq(Pa, #ivalues{args=[Ea]}), GuardBreak, St1).
+ end.
iletrec_funs(#iletrec{defs=Fs}, St0) ->
%% Use union of all free variables.
@@ -1496,7 +1475,6 @@ iletrec_funs_gen(Fs, FreeVs, St) ->
%% is_exit_expr(Kexpr) -> boolean().
%% Test whether Kexpr always exits and never returns.
-is_exit_expr(#k_call{op=#k_internal{name=match_fail,arity=1}}) -> true;
is_exit_expr(#k_receive_next{}) -> true;
is_exit_expr(_) -> false.
@@ -1511,64 +1489,21 @@ is_enter_expr(#k_receive{}) -> true;
is_enter_expr(#k_receive_next{}) -> true;
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).
+%% uexpr(Expr, Break, State) -> {Expr,[UsedVar],State}.
+%% Tag an expression with its used variables.
+%% Break = return | {break,[RetVar]}.
-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) ->
+uexpr(#k_test{anno=A,op=Op,args=As}=Test, {break,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 = {guard_break,Rs},
- {B1,Bu,St1} = umatch(B0, Br, St0),
- {#k_guard_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(#iset{anno=A,vars=Vs,arg=E0,body=B0}, {break,_}=Br, St0) ->
+ Ns = lit_list_vars(Vs),
+ {E1,Eu,St1} = uexpr(E0, {break,Vs}, St0),
+ {B1,Bu,St2} = uexpr(B0, Br, St1),
+ Used = union(Eu, subtract(Bu, Ns)),
+ {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2};
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!
@@ -1600,10 +1535,11 @@ uexpr(#k_match{anno=A,vars=Vs0,body=B0}, Br, St0) ->
Vs = handle_reuse_annos(Vs0, St0),
Rs = break_rets(Br),
{B1,Bu,St1} = umatch(B0, Br, St0),
- if St0#kern.guard_refc > 0 ->
+ case is_in_guard(St1) of
+ true ->
{#k_guard_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},
vars=Vs,body=B1,ret=Rs},Bu,St1};
- true ->
+ false ->
{#k_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},
vars=Vs,body=B1,ret=Rs},Bu,St1}
end;
@@ -1620,24 +1556,27 @@ 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_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0}=Try,
+ {break,Rs0}=Br, St0) ->
+ case is_in_guard(St0) of
+ true ->
+ {[#k_var{name=X}],#k_var{name=X}} = {Vs,B0}, %Assertion.
+ #k_atom{val=false} = H0, %Assertion.
+ {A1,Bu,St1} = uexpr(A0, Br, St0),
+ {Try#k_try{anno=#k{us=Bu,ns=lit_list_vars(Rs0),a=A},
+ arg=A1,ret=Rs0},Bu,St1};
+ false ->
+ {Avs,St1} = new_vars(length(Vs), St0),
+ {A1,Au,St2} = ubody(A0, {break,Avs}, St1),
+ {B1,Bu,St3} = ubody(B0, Br, St2),
+ {H1,Hu,St4} = ubody(H0, Br, St3),
+ {Rs1,St5} = ensure_return_vars(Rs0, St4),
+ 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}
+ end;
uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
return, St0) ->
{Avs,St1} = new_vars(length(Vs), St0), %Need dummy names here
@@ -1658,37 +1597,38 @@ uexpr(#k_catch{anno=A,body=B0}, {break,Rs0}, St0) ->
{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) ->
+uexpr(#ifun{anno=A,vars=Vs,body=B0}, {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} =
+ {Fname,St} =
case lists:keyfind(id, 1, A) of
- {id,Id} ->
- {Id, St1};
+ {id,{_,_,Fname0}} ->
+ {Fname0,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}
+ %% No id annotation. Must invent a fun name.
+ new_fun_name(St1)
end,
Fun = #k_fdef{anno=#k{us=[],ns=[],a=A},func=Fname,arity=Arity,
vars=Vs ++ Fvs,body=B1},
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
{#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},
- Free,add_local_function(Fun, St3)};
-uexpr(Lit, {break,Rs}, St) ->
+ Free,add_local_function(Fun, St)};
+uexpr(Lit, {break,Rs0}, St0) ->
%% Transform literals to puts here.
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
Used = lit_vars(Lit),
+ {Rs,St1} = ensure_return_vars(Rs0, St0),
{#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)},
- arg=Lit,ret=Rs},Used,St}.
+ arg=Lit,ret=Rs},Used,St1}.
add_local_function(_, #kern{funs=ignore}=St) -> St;
add_local_function(F, #kern{funs=Funs}=St) -> St#kern{funs=[F|Funs]}.
@@ -1745,6 +1685,11 @@ bif_returns(#k_internal{name=N,arity=Ar}, Rs, St0) ->
{Ns,St1} = new_vars(bif_vals(N, Ar) - length(Rs), St0),
{Rs ++ Ns,St1}.
+%% ensure_return_vars([Ret], State) -> {[Ret],State}.
+
+ensure_return_vars([], St) -> new_vars(1, St);
+ensure_return_vars([_]=Rs, St) -> {Rs,St}.
+
%% umatch(Match, Break, State) -> {Match,[UsedVar],State}.
%% Tag a match expression with its used variables.
@@ -1777,7 +1722,8 @@ umatch(#k_guard{anno=A,clauses=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#kern{guard_refc=St0#kern.guard_refc+1}),
+ {G1,Gu,St1} = uexpr(G0, {break,[]},
+ St0#kern{guard_refc=St0#kern.guard_refc+1}),
%%ok = io:fwrite("~w: ~p~n", [?LINE,G1]),
{B1,Bu,St2} = umatch(B0, Br, St1#kern{guard_refc=St1#kern.guard_refc-1}),
Used = union(Gu, Bu),
@@ -1825,7 +1771,6 @@ lit_list_vars(Ps) ->
pat_vars(#k_var{name=N}) -> {[],[N]};
%%pat_vars(#k_char{}) -> {[],[]};
-%%pat_vars(#k_string{}) -> {[],[]};
pat_vars(#k_literal{}) -> {[],[]};
pat_vars(#k_int{}) -> {[],[]};
pat_vars(#k_float{}) -> {[],[]};
@@ -1852,34 +1797,6 @@ pat_list_vars(Ps) ->
{union(Used0, Used),union(New0, New)} end,
{[],[]}, Ps).
-%% handle_literal(Literal, Anno) -> Kernel
-%% Examine the literal. Complex (heap-based) literals such as lists,
-%% tuples, and binaries should be kept as literals and put into the constant pool.
-%%
-%% (If necessary, this function could be extended to go through the literal
-%% and convert huge binary literals to bit syntax expressions. We don't do that
-%% because v3_core does not produce huge binary literals, and the optimizations in
-%% sys_core_fold don't do much optimizations of binaries. IF THAT CHANGE IS MADE,
-%% ALSO CHANGE sys_core_dsetel.)
-
-handle_literal(#c_literal{anno=A,val=V}) ->
- case V of
- [_|_] ->
- #k_literal{anno=A,val=V};
- [] ->
- #k_nil{anno=A};
- V when is_tuple(V) ->
- #k_literal{anno=A,val=V};
- V when is_bitstring(V) ->
- #k_literal{anno=A,val=V};
- V when is_integer(V) ->
- #k_int{anno=A,val=V};
- V when is_float(V) ->
- #k_float{anno=A,val=V};
- V when is_atom(V) ->
- #k_atom{anno=A,val=V}
- end.
-
make_list(Es) ->
foldr(fun(E, Acc) ->
#c_cons{hd=E,tl=Acc}
@@ -1891,6 +1808,11 @@ integers(N, M) when N =< M ->
[N|integers(N + 1, M)];
integers(_, _) -> [].
+%% is_in_guard(State) -> true|false.
+
+is_in_guard(#kern{guard_refc=Refc}) ->
+ Refc > 0.
+
%%%
%%% Handling of errors and warnings.
%%%
@@ -1906,12 +1828,17 @@ format_error({nomatch_shadow,Line}) ->
format_error(nomatch_shadow) ->
"this clause cannot match because a previous clause always matches";
format_error(bad_call) ->
- "invalid module and/or function name; this call will always fail".
+ "invalid module and/or function name; this call will always fail";
+format_error(bad_segment_size) ->
+ "binary construction will fail because of a type mismatch".
add_warning(none, Term, Anno, #kern{ws=Ws}=St) ->
File = get_file(Anno),
St#kern{ws=[{File,[{?MODULE,Term}]}|Ws]};
-add_warning(Line, Term, Anno, #kern{ws=Ws}=St) when Line >= 0 ->
+add_warning(Line, Term, Anno, #kern{ws=Ws}=St) ->
File = get_file(Anno),
- St#kern{ws=[{File,[{Line,?MODULE,Term}]}|Ws]};
-add_warning(_, _, _, St) -> St.
+ St#kern{ws=[{File,[{Line,?MODULE,Term}]}|Ws]}.
+
+is_compiler_generated(Ke) ->
+ Anno = get_kanno(Ke),
+ member(compiler_generated, Anno).
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index 37f2fdcf7e..fb8baf398b 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,6 @@
-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}).
diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl
index a1d92af9f8..2cc3493570 100644
--- a/lib/compiler/src/v3_life.erl
+++ b/lib/compiler/src/v3_life.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,19 +89,8 @@ function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) ->
end.
%% 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};
+%% Handle a body.
+
body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
%%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
A = get_kanno(Ke),
@@ -123,53 +112,14 @@ guard(#k_try{anno=A,arg=Ts,vars=[#k_var{name=X}],body=#k_var{name=X},
%% 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),
+ {T,MaxI,Pdb1} = 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) ->
- Name = bif_op(Op),
- Ar = length(As),
- case is_gc_bif(Name, Ar) of
- false ->
- #l{ke={bif,Name,atomic_list(As),var_list(Rs)},i=I,a=A#k.a};
- true ->
- #l{ke={gc_bif,Name,atomic_list(As),var_list(Rs)},i=I,a=A#k.a}
- end;
-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_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% 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={guard_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).
+ #l{ke={protected,T,var_list(Rs)},i=I,a=A#k.a,vdb=Pdb2}.
%% expr(Kexpr, I, Vdb) -> Expr.
+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};
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) ->
@@ -187,25 +137,11 @@ expr(#k_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
Mdb = vdb_sub(I, I+1, Vdb),
M = match(Kb, A#k.us, I+1, [], Mdb),
#l{ke={guard_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, locked, 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_try{}=Try, I, Vdb) ->
+ case is_in_guard() of
+ false -> body_try(Try, I, Vdb);
+ true -> guard(Try, I, Vdb)
+ end;
expr(#k_try_enter{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}, I, Vdb) ->
%% Lock variables that are alive before the catch and used afterwards.
%% Don't lock variables that are only used inside the try.
@@ -254,6 +190,27 @@ expr(#k_guard_break{anno=A,args=As}, I, Vdb) ->
expr(#k_return{anno=A,args=As}, I, _Vdb) ->
#l{ke={return,atomic_list(As)},i=I,a=A#k.a}.
+body_try(#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, locked, 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}.
+
%% call_op(Op) -> Op.
%% bif_op(Op) -> Op.
%% test_op(Op) -> Op.
@@ -353,25 +310,6 @@ guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Ctxt, Vdb0) ->
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_literal{anno=Anno,val={Atom,Val}}, I, A) when is_atom(Atom) ->
- match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom},#k_literal{val=Val}]}, I, A);
-match_fail(#k_literal{anno=Anno,val={Atom}}, I, A) when is_atom(Atom) ->
- match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom}]}, I, A);
-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_literal) -> literal;
@@ -403,7 +341,6 @@ atomic(#k_int{val=I}) -> {integer,I};
atomic(#k_float{val=F}) -> {float,F};
atomic(#k_atom{val=N}) -> {atom,N};
%%atomic(#k_char{val=C}) -> {char,C};
-%%atomic(#k_string{val=S}) -> {string,S};
atomic(#k_nil{}) -> nil.
atomic_list(Ks) -> [atomic(K) || K <- Ks].
@@ -565,3 +502,7 @@ vdb_sub(Min, Max, Vdb) ->
true -> Vd
end || {V,F,L}=Vd <- Vdb, F < Min, L >= Min ].
+%% is_in_guard() -> true|false.
+
+is_in_guard() ->
+ get(guard_refc) > 0.
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index b90adaf917..e047166ade 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -10,6 +10,7 @@ MODULES= \
apply_SUITE \
beam_validator_SUITE \
beam_disasm_SUITE \
+ beam_expect_SUITE \
bs_bincomp_SUITE \
bs_bit_binaries_SUITE \
bs_construct_SUITE \
@@ -29,7 +30,6 @@ MODULES= \
misc_SUITE \
num_bif_SUITE \
pmod_SUITE \
- parteval_SUITE \
receive_SUITE \
record_SUITE \
trycatch_SUITE \
@@ -39,6 +39,7 @@ MODULES= \
NO_OPT= \
andor \
apply \
+ beam_expect \
bs_construct \
bs_match \
bs_utf \
@@ -153,12 +154,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) compiler.spec compiler.cover \
- $(EMAKEFILE) $(ERL_FILES) $(CORE_FILES) $(RELSYSDIR)
+ $(EMAKEFILE) $(ERL_FILES) $(CORE_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \
- $(INLINE_ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INLINE_ERL_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/compiler/test/beam_disasm_SUITE.erl b/lib/compiler/test/beam_disasm_SUITE.erl
index 44574ae64a..62afc80ca6 100644
--- a/lib/compiler/test/beam_disasm_SUITE.erl
+++ b/lib/compiler/test/beam_disasm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The 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,6 @@ stripped(Config) when is_list(Config) ->
?line true = is_list(Attr),
?line true = is_list(CompileInfo),
?line {ok, {tmp, _}} = beam_lib:strip(BeamName),
- ?line {beam_file, tmp, _, none, none, [_|_]} =
+ ?line {beam_file, tmp, _, [], [], [_|_]} =
beam_disasm:file(BeamName),
ok.
diff --git a/lib/compiler/test/beam_expect_SUITE.erl b/lib/compiler/test/beam_expect_SUITE.erl
new file mode 100644
index 0000000000..6f216eac4f
--- /dev/null
+++ b/lib/compiler/test/beam_expect_SUITE.erl
@@ -0,0 +1,67 @@
+%%
+%% %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_expect_SUITE).
+
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ coverage/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [coverage].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+coverage(_) ->
+ File = {file,"fake.erl"},
+ ok = fc(a),
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[[x]],[File,{line,2}]}|_]}} =
+ (catch fc([x])),
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[y],[File,{line,2}]}|_]}} =
+ (catch fc(y)),
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} =
+ (catch fc([a,b,c])),
+
+ {'EXIT',{undef,[{erlang,error,[a,b,c],_}|_]}} =
+ (catch erlang:error(a, b, c)),
+ ok.
+
+-file("fake.erl", 1).
+fc(a) -> %Line 2
+ ok; %Line 3
+fc(L) when length(L) > 2 -> %Line 4
+ %% Not the same as a "real" function_clause error.
+ error(function_clause, [L]). %Line 6
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 556dc54a8f..902867bc19 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -79,21 +79,18 @@ beam_files(Config) when is_list(Config) ->
%% a grammatical error in the output of the io:format/2 call below. ;-)
?line [_,_|_] = Fs = filelib:wildcard(Wc),
?line io:format("~p files\n", [length(Fs)]),
- beam_files_1(Fs, 0).
-
-beam_files_1([F|Fs], Errors) ->
- ?line case beam_validator:file(F) of
- ok ->
- beam_files_1(Fs, Errors);
- {error,Es} ->
- io:format("File: ~s", [F]),
- io:format("Error: ~p\n", [Es]),
- beam_files_1(Fs, Errors+1)
- end;
-beam_files_1([], 0) -> ok;
-beam_files_1([], Errors) ->
- ?line io:format("~p error(s)", [Errors]),
- ?line ?t:fail().
+ test_lib:p_run(fun do_beam_file/1, Fs).
+
+
+do_beam_file(F) ->
+ case beam_validator:file(F) of
+ ok ->
+ ok;
+ {error,Es} ->
+ io:format("File: ~s", [F]),
+ io:format("Error: ~p\n", [Es]),
+ error
+ end.
compiler_bug(Config) when is_list(Config) ->
%% Check that the compiler returns an error if we try to
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index 31c7890f26..e8b30f44ce 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -468,6 +468,10 @@ opt(Config) when is_list(Config) ->
?line {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>),
?line {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>),
+ %% Test constant propagation - there should be a warning.
+ BadSz = 2.5,
+ {'EXIT',_} = (catch <<<<N,56,0,2>>:BadSz/binary>>),
+
case id(false) of
true -> ?line opt_dont_call_me();
false -> ok
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index f8c71a0257..01b7568122 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -342,6 +342,10 @@ partitioned_bs_match(Config) when is_list(Config) ->
?line fc(partitioned_bs_match_2, [4,<<0:17>>],
catch partitioned_bs_match_2(4, <<0:17>>)),
+
+ anything = partitioned_bs_match_3(anything, <<42>>),
+ ok = partitioned_bs_match_3(1, 2),
+
ok.
partitioned_bs_match(_, <<42:8,T/binary>>) ->
@@ -356,6 +360,9 @@ partitioned_bs_match_2(1, <<B:8,T/binary>>) ->
partitioned_bs_match_2(Len, <<_:8,T/binary>>) ->
{Len,T}.
+partitioned_bs_match_3(Var, <<_>>) -> Var;
+partitioned_bs_match_3(1, 2) -> ok.
+
function_clause(Config) when is_list(Config) ->
?line ok = function_clause_1(<<0,7,0,7,42>>),
?line fc(function_clause_1, [<<0,1,2,3>>],
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index f30a4d3fef..94549ad0d3 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -264,18 +264,10 @@ literals(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf8,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf8,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/little-utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf16,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>),
?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFE/utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#FFFF/little-utf32,I/utf8>>),
B = 16#10FFFF+1,
?line {'EXIT',{badarg,_}} = (catch <<B/utf8>>),
@@ -286,20 +278,11 @@ literals(Config) when is_list(Config) ->
%% Matching of bad literals.
?line error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8
- ?line error = bad_literal_match(<<239,191,190>>), %16#FFFE in UTF-8
- ?line error = bad_literal_match(<<239,191,191>>), %16#FFFF in UTF-8
?line error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8
- ?line error = bad_literal_match(<<255,254>>), %16#FFFE in UTF-16
- ?line error = bad_literal_match(<<255,255>>), %16#FFFF in UTF-16
-
?line error = bad_literal_match(<<16#D800:32>>),
- ?line error = bad_literal_match(<<16#FFFE:32>>),
- ?line error = bad_literal_match(<<16#FFFF:32>>),
?line error = bad_literal_match(<<16#110000:32>>),
?line error = bad_literal_match(<<16#D800:32/little>>),
- ?line error = bad_literal_match(<<16#FFFE:32/little>>),
- ?line error = bad_literal_match(<<16#FFFF:32/little>>),
?line error = bad_literal_match(<<16#110000:32/little>>),
ok.
@@ -314,11 +297,7 @@ match_literal(<<"bj\366rn"/big-utf16>>) -> bjorn_utf16be;
match_literal(<<"bj\366rn"/little-utf16>>) -> bjorn_utf16le.
bad_literal_match(<<16#D800/utf8>>) -> ok;
-bad_literal_match(<<16#FFFE/utf8>>) -> ok;
-bad_literal_match(<<16#FFFF/utf8>>) -> ok;
bad_literal_match(<<16#110000/utf8>>) -> ok;
-bad_literal_match(<<16#FFFE/utf16>>) -> ok;
-bad_literal_match(<<16#FFFF/utf16>>) -> ok;
bad_literal_match(<<16#D800/utf32>>) -> ok;
bad_literal_match(<<16#110000/utf32>>) -> ok;
bad_literal_match(<<16#D800/little-utf32>>) -> ok;
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index 1343fbd1c9..fed7bec7d4 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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 @@ all() ->
trycatch_4, opt_crash, otp_5404, otp_5436, otp_5481,
otp_5553, otp_5632, otp_5714, otp_5872, otp_6121,
otp_6121a, otp_6121b, otp_7202, otp_7345, on_load,
- string_table,otp_8949_a,otp_8949_a].
+ string_table,otp_8949_a,otp_8949_a,split_cases].
groups() ->
[{vsn, [], [vsn_1, vsn_2, vsn_3]}].
@@ -159,6 +159,7 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) ->
?comp(convopts).
?comp(otp_7202).
?comp(on_load).
+?comp(on_load_inline).
beam_compiler_7(doc) ->
"Code snippet submitted from Ulf Wiger which fails in R3 Beam.";
@@ -427,9 +428,9 @@ self_compile_1(Config, Prefix, Opts) ->
%% Compile the compiler again using the newly compiled compiler.
%% (In another node because reloading the compiler would disturb cover.)
CompilerB = Prefix++"compiler_b",
- ?line CompB = make_compiler_dir(Priv, Prefix++"compiler_b"),
+ CompB = make_compiler_dir(Priv, CompilerB),
?line VsnB = VsnA ++ ".0",
- ?line self_compile_node(CompilerB, CompA, CompB, VsnB, Opts),
+ self_compile_node(CompA, CompB, VsnB, Opts),
%% Compare compiler directories.
?line compare_compilers(CompA, CompB),
@@ -438,21 +439,26 @@ self_compile_1(Config, Prefix, Opts) ->
?line CompilerC = Prefix++"compiler_c",
?line CompC = make_compiler_dir(Priv, CompilerC),
?line VsnC = VsnB ++ ".0",
- ?line self_compile_node(CompilerC, CompB, CompC, VsnC, Opts),
+ self_compile_node(CompB, CompC, VsnC, Opts),
?line compare_compilers(CompB, CompC),
?line test_server:timetrap_cancel(Dog),
ok.
-self_compile_node(NodeName0, CompilerDir, OutDir, Version, Opts) ->
- ?line NodeName = list_to_atom(NodeName0),
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
+self_compile_node(CompilerDir, OutDir, Version, Opts) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(15)),
?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++
" -pa " ++ CompilerDir,
- ?line {ok,Node} = start_node(NodeName, Pa),
?line Files = compiler_src(),
- ?line ok = rpc:call(Node, ?MODULE, compile_compiler, [Files,OutDir,Version,Opts]),
- ?line test_server:stop_node(Node),
+
+ %% We don't want the cover server started on the other node,
+ %% because it will load the same cover-compiled code as on this
+ %% node. Use a shielded node to prevent the cover server from
+ %% being started.
+ ?t:run_on_shielded_node(
+ fun() ->
+ compile_compiler(Files, OutDir, Version, Opts)
+ end, Pa),
?line test_server:timetrap_cancel(Dog),
ok.
@@ -465,9 +471,12 @@ compile_compiler(Files, OutDir, Version, InlineOpts) ->
{d,'COMPILER_VSN',"\""++Version++"\""},
nowarn_shadow_vars,
{i,filename:join(code:lib_dir(stdlib), "include")}|InlineOpts],
- lists:foreach(fun(File) ->
- {ok,_} = compile:file(File, Opts)
- end, Files).
+ test_lib:p_run(fun(File) ->
+ case compile:file(File, Opts) of
+ {ok,_} -> ok;
+ _ -> error
+ end
+ end, Files).
compiler_src() ->
filelib:wildcard(filename:join([code:lib_dir(compiler), "src", "*.erl"])).
@@ -657,5 +666,19 @@ otp_8949_b(A, B) ->
id(Var)
end.
+split_cases(_) ->
+ dummy1 = do_split_cases(x),
+ {'EXIT',{{badmatch,b},_}} = (catch do_split_cases(y)),
+ ok.
+
+do_split_cases(A) ->
+ case A of
+ x ->
+ Z = dummy1;
+ _ ->
+ Z = dummy2,
+ a=b
+ end,
+ Z.
id(I) -> I.
diff --git a/lib/compiler/test/compilation_SUITE_data/on_load_inline.erl b/lib/compiler/test/compilation_SUITE_data/on_load_inline.erl
new file mode 100644
index 0000000000..322843b61e
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/on_load_inline.erl
@@ -0,0 +1,23 @@
+-module(on_load_inline).
+-export([?MODULE/0]).
+-on_load(on_load/0).
+-compile(inline).
+
+?MODULE() ->
+ [{pid,Pid}] = ets:lookup(on_load_executed, pid),
+ exit(Pid, kill),
+ ok.
+
+on_load() ->
+ Parent = self(),
+ spawn(fun() ->
+ T = ets:new(on_load_executed, [named_table]),
+ ets:insert(T, {pid,self()}),
+ Parent ! done,
+ receive
+ wait_forever -> ok
+ end
+ end),
+ receive
+ done -> ok
+ end.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 8c6a623dfb..2cd75944f4 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,12 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
app_test/1,
- file_1/1, module_mismatch/1, big_file/1, outdir/1,
+ file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
other_output/1, package_forms/1, encrypted_abstr/1,
bad_record_use1/1, bad_record_use2/1, strict_record/1,
- missing_testheap/1, cover/1, env/1, core/1, asm/1]).
+ missing_testheap/1, cover/1, env/1, core/1, asm/1,
+ sys_pre_attributes/1]).
-export([init/3]).
@@ -41,11 +42,12 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [app_test, file_1, module_mismatch, big_file, outdir,
+ [app_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, package_forms, encrypted_abstr,
{group, bad_record_use}, strict_record,
- missing_testheap, cover, env, core, asm].
+ missing_testheap, cover, env, core, asm,
+ sys_pre_attributes].
groups() ->
[{bad_record_use, [],
@@ -74,15 +76,28 @@ app_test(Config) when is_list(Config) ->
file_1(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:minutes(5)),
+
+ process_flag(trap_exit, true),
+
?line {Simple, Target} = files(Config, "file_1"),
?line {ok, Cwd} = file:get_cwd(),
?line ok = file:set_cwd(filename:dirname(Target)),
- ?line {ok,simple} = compile:file(Simple), %Smoke test only.
+
+ %% Native from BEAM without compilation info.
?line {ok,simple} = compile:file(Simple, [slim]), %Smoke test only.
- ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
- ?line {ok,simple} = compile:file(Simple, [debug_info]),
+
+ %% Native from BEAM with compilation info.
+ ?line {ok,simple} = compile:file(Simple), %Smoke test only.
+ ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
+
+ ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
+
+ ?line compile_and_verify(Simple, Target, []),
+ ?line compile_and_verify(Simple, Target, [native]),
+ ?line compile_and_verify(Simple, Target, [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, []),
@@ -90,9 +105,37 @@ file_1(Config) when is_list(Config) ->
%% Cleanup.
?line ok = file:delete(Target),
?line ok = file:del_dir(filename:dirname(Target)),
+
+ %% There should not be any messages in the messages.
+ receive
+ Any ->
+ ?t:fail({unexpected,Any})
+ after 10 ->
+ ok
+ end,
+
?line test_server:timetrap_cancel(Dog),
ok.
+forms_2(Config) when is_list(Config) ->
+ Src = "/foo/bar",
+ AbsSrc = filename:absname(Src),
+ {ok,simple,Binary} = compile:forms([{attribute,1,module,simple}],
+ [binary,{source,Src}]),
+ code:load_binary(simple, Src, Binary),
+ Info = simple:module_info(compile),
+
+ %% Test that the proper source is returned.
+ AbsSrc = proplists:get_value(source, Info),
+
+ %% Ensure that the options are not polluted with 'source'.
+ [] = proplists:get_value(options, Info),
+
+ %% Cleanup.
+ true = code:delete(simple),
+ false = code:purge(simple),
+ ok.
+
module_mismatch(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
?line File = filename:join(DataDir, "wrong_module_name.erl"),
@@ -113,10 +156,9 @@ big_file(Config) when is_list(Config) ->
?line Big = filename:join(DataDir, "big.erl"),
?line Target = filename:join(PrivDir, "big.beam"),
?line ok = file:set_cwd(PrivDir),
- ?line {ok,big} = compile:file(Big, []),
- ?line {ok,big} = compile:file(Big, [r9,debug_info]),
- ?line {ok,big} = compile:file(Big, [no_postopt]),
- ?line true = exists(Target),
+ ?line compile_and_verify(Big, Target, []),
+ ?line compile_and_verify(Big, Target, [debug_info]),
+ ?line compile_and_verify(Big, Target, [no_postopt]),
%% Cleanup.
?line ok = file:delete(Target),
@@ -200,6 +242,12 @@ makedep(Config) when is_list(Config) ->
[makedep,{makedep_output,Target}|IncludeOptions]),
?line {ok,Mf6} = file:read_file(Target),
?line BasicMf2 = makedep_canonicalize_result(Mf6, DataDir),
+ %% Rule with creating phony target.
+ ?line PhonyMfName = SimpleRootname ++ "-phony.mk",
+ ?line {ok,PhonyMf} = file:read_file(PhonyMfName),
+ ?line {ok,_,Mf7} = compile:file(Simple,
+ [binary,makedep,makedep_phony|IncludeOptions]),
+ ?line PhonyMf = makedep_canonicalize_result(Mf7, DataDir),
?line ok = file:delete(Target),
?line ok = file:del_dir(filename:dirname(Target)),
@@ -775,3 +823,46 @@ do_asm(Beam, Outdir) ->
[M,Class,Error,erlang:get_stacktrace()]),
error
end.
+
+sys_pre_attributes(Config) ->
+ DataDir = ?config(data_dir, Config),
+ File = filename:join(DataDir, "attributes.erl"),
+ Mod = attributes,
+ CommonOpts = [binary,report,verbose,
+ {parse_transform,sys_pre_attributes}],
+ PreOpts = [{attribute,delete,deleted}],
+ PostOpts = [{attribute,insert,inserted,"value"}],
+ PrePostOpts = [{attribute,replace,replaced,42},
+ {attribute,replace,replace_nonexisting,new}],
+ {ok,Mod,Code} = compile:file(File, PrePostOpts ++ PreOpts ++
+ PostOpts ++ CommonOpts),
+ code:load_binary(Mod, File, Code),
+ Attr = Mod:module_info(attributes),
+ io:format("~p", [Attr]),
+ {inserted,"value"} = lists:keyfind(inserted, 1, Attr),
+ {replaced,[42]} = lists:keyfind(replaced, 1, Attr),
+ {replace_nonexisting,[new]} = lists:keyfind(replace_nonexisting, 1, Attr),
+ false = lists:keymember(deleted, 1, Attr),
+
+ %% Cover more code.
+ {ok,Mod,_} = compile:file(File, PostOpts ++ CommonOpts),
+ {ok,Mod,_} = compile:file(File, CommonOpts -- [verbose]),
+ {ok,Mod,_} = compile:file(File, PreOpts ++ CommonOpts),
+ {ok,Mod,_} = compile:file(File,
+ [{attribute,replace,replaced,42}|CommonOpts]),
+ {ok,Mod,_} = compile:file(File, PrePostOpts ++ PreOpts ++
+ PostOpts ++ CommonOpts --
+ [report,verbose]),
+ ok.
+
+%%%
+%%% Utilities.
+%%%
+
+compile_and_verify(Name, Target, Opts) ->
+ Mod = list_to_atom(filename:basename(Name, ".erl")),
+ {ok,Mod} = compile:file(Name, Opts),
+ {ok,{Mod,[{compile_info,CInfo}]}} =
+ beam_lib:chunks(Target, [compile_info]),
+ {options,BeamOpts} = lists:keyfind(options, 1, CInfo),
+ Opts = BeamOpts.
diff --git a/lib/compiler/test/compile_SUITE_data/attributes.erl b/lib/compiler/test/compile_SUITE_data/attributes.erl
new file mode 100644
index 0000000000..9c3451d272
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/attributes.erl
@@ -0,0 +1,23 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(attributes).
+-deleted(dummy).
+-replaced(dummy).
+
diff --git a/lib/compiler/test/compile_SUITE_data/simple-phony.mk b/lib/compiler/test/compile_SUITE_data/simple-phony.mk
new file mode 100644
index 0000000000..c84bcedd2a
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/simple-phony.mk
@@ -0,0 +1,3 @@
+simple.beam: $(srcdir)/simple.erl $(srcdir)/include/simple.hrl
+
+$(srcdir)/include/simple.hrl:
diff --git a/lib/compiler/test/compiler.cover b/lib/compiler/test/compiler.cover
index 9fc4c7dd43..3fd7fc1937 100644
--- a/lib/compiler/test/compiler.cover
+++ b/lib/compiler/test/compiler.cover
@@ -1,5 +1,5 @@
{incl_app,compiler,details}.
%% -*- erlang -*-
-{excl_mods,[sys_pre_attributes,core_scan,core_parse]}.
+{excl_mods,compiler,[core_scan,core_parse]}.
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 26173c62b8..06185bfc34 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,9 @@
-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,
- dehydrated_itracer/1,nested_tries/1]).
+ dehydrated_itracer/1,nested_tries/1,
+ seq_in_guard/1,make_effect_seq/1,eval_is_boolean/1,
+ unsafe_case/1,nomatch_shadow/1,reversed_annos/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -41,7 +43,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [dehydrated_itracer, nested_tries].
+ [dehydrated_itracer,nested_tries,seq_in_guard,make_effect_seq,
+ eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos].
groups() ->
[].
@@ -61,19 +64,19 @@ end_per_group(_GroupName, Config) ->
?comp(dehydrated_itracer).
?comp(nested_tries).
+?comp(seq_in_guard).
+?comp(make_effect_seq).
+?comp(eval_is_boolean).
+?comp(unsafe_case).
+?comp(nomatch_shadow).
+?comp(reversed_annos).
try_it(Mod, Conf) ->
- ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)),
- ?line Out = ?config(priv_dir,Conf),
- ?line io:format("Compiling: ~s\n", [Src]),
- ?line CompRc0 = compile:file(Src, [from_core,{outdir,Out},report,time]),
- ?line io:format("Result: ~p\n",[CompRc0]),
- ?line {ok,Mod} = CompRc0,
-
- ?line {module,Mod} = code:load_abs(filename:join(Out, Mod)),
- ?line ok = Mod:Mod(),
- ok.
-
-
-
-
+ Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)),
+ compile_and_load(Src, []),
+ compile_and_load(Src, [no_copt]).
+
+compile_and_load(Src, Opts) ->
+ {ok,Mod,Bin} = compile:file(Src, [from_core,report,time,binary|Opts]),
+ {module,Mod} = code:load_binary(Mod, Mod, Bin),
+ ok = Mod:Mod().
diff --git a/lib/compiler/test/core_SUITE_data/eval_is_boolean.core b/lib/compiler/test/core_SUITE_data/eval_is_boolean.core
new file mode 100644
index 0000000000..6a68b1414d
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/eval_is_boolean.core
@@ -0,0 +1,22 @@
+module 'eval_is_boolean' ['eval_is_boolean'/0]
+ attributes []
+'eval_is_boolean'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ case call 'erlang':'is_boolean'(call 'erlang':'make_ref'()) of
+ <'false'> when 'true' ->
+ 'ok'
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'eval_is_boolean',0}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/make_effect_seq.core b/lib/compiler/test/core_SUITE_data/make_effect_seq.core
new file mode 100644
index 0000000000..9941e63b76
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/make_effect_seq.core
@@ -0,0 +1,51 @@
+module 'make_effect_seq' ['make_effect_seq'/0]
+ attributes []
+'make_effect_seq'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ let <_cor0> =
+ catch
+ apply 't'/1
+ ('a')
+ in
+ case _cor0 of
+ <{'EXIT',{'badarg',_cor3}}> when 'true' ->
+ let <_cor4> =
+ apply 't'/1
+ ({'a','b','c'})
+ in
+ case _cor4 of
+ <'ok'> when 'true' ->
+ ( _cor4
+ -| ['compiler_generated'] )
+ ( <_cor2> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor2})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'make_effect_seq',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <T> when 'true' ->
+ do
+ {'ok',call 'erlang':'element'(2, T)}
+ 'ok'
+ ( <_cor2> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor2})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/nomatch_shadow.core b/lib/compiler/test/core_SUITE_data/nomatch_shadow.core
new file mode 100644
index 0000000000..565d9dc0f3
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/nomatch_shadow.core
@@ -0,0 +1,28 @@
+module 'nomatch_shadow' ['nomatch_shadow'/0]
+ attributes []
+'nomatch_shadow'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ apply 't'/1
+ (42)
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'nomatch_shadow',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <42> when 'true' ->
+ 'ok'
+ <42> when 'true' ->
+ 'ok'
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/reversed_annos.core b/lib/compiler/test/core_SUITE_data/reversed_annos.core
new file mode 100644
index 0000000000..95b3cd52d6
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/reversed_annos.core
@@ -0,0 +1,49 @@
+module 'reversed_annos' ['reversed_annos'/0]
+ attributes []
+'reversed_annos'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ case apply 't'/1
+ (['a']) of
+ <'ok'> when 'true' ->
+ let <_cor2> =
+ apply 't'/1
+ (['a'|['b']])
+ in
+ case _cor2 of
+ <'ok'> when 'true' ->
+ ( _cor2
+ -| ['compiler_generated'] )
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'reversed_annos',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <[_cor2|_cor3]> when 'true' ->
+ 'ok'
+ %% Cover v3_kernel:get_line/1.
+ ( <['a']> when 'true' ->
+ 'error'
+ -| [{'file',"reversed_annos.erl"},11] )
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/seq_in_guard.core b/lib/compiler/test/core_SUITE_data/seq_in_guard.core
new file mode 100644
index 0000000000..44686a7187
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/seq_in_guard.core
@@ -0,0 +1,66 @@
+module 'seq_in_guard' ['seq_in_guard'/0,
+ 't'/1]
+ attributes []
+'seq_in_guard'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ let <_cor0> =
+ catch
+ %% Line 5
+ apply 't'/1
+ ({})
+ in %% Line 5
+ case _cor0 of
+ <{'EXIT',{'function_clause',_cor4}}> when 'true' ->
+ let <_cor2> =
+ catch
+ %% Line 6
+ apply 't'/1
+ ('atom')
+ in %% Line 6
+ case _cor2 of
+ <{'EXIT',{'function_clause',_cor5}}> when 'true' ->
+ %% Line 7
+ apply 't'/1
+ ({'a','b'})
+ ( <_cor3> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor3})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'seq_in_guard',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ %% Line 9
+ fun (_cor0) ->
+ case _cor0 of
+ <X>
+ when try
+ do
+ call 'erlang':'element'
+ (2, X)
+ 'true'
+ of <Try> ->
+ Try
+ catch <T,R> ->
+ 'false' ->
+ %% Line 10
+ 'ok'
+ ( <_cor3> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor3})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/unsafe_case.core b/lib/compiler/test/core_SUITE_data/unsafe_case.core
new file mode 100644
index 0000000000..84cb2c310a
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/unsafe_case.core
@@ -0,0 +1,25 @@
+module 'unsafe_case' ['unsafe_case'/0]
+ attributes []
+'unsafe_case'/0 =
+ fun () ->
+ case apply 't'/1
+ (42) of
+ <{'ok',42}> when 'true' ->
+ 'ok'
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <X>
+ when call 'erlang':'>'
+ (_cor0,
+ 0) ->
+ {'ok',X}
+ %% The default case is intentionally missing
+ %% to cover v3_kernel:build_match/2.
+ end
+end
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index ac14d36e82..54bd52947e 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -21,7 +21,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1,
- eq/1,nested_call_in_case/1,coverage/1]).
+ eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -32,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
[t_element, setelement, t_length, append, t_apply, bifs,
- eq, nested_call_in_case, coverage].
+ eq, nested_call_in_case, guard_try_catch, coverage].
groups() ->
[].
@@ -207,6 +207,23 @@ nested_call_in_case(Config) when is_list(Config) ->
?line {'EXIT',_} = (catch Mod:a(not_a_list, 42)),
ok.
+guard_try_catch(_Config) ->
+ false = do_guard_try_catch(key, value),
+ value = get(key),
+ ok.
+
+do_guard_try_catch(K, V) ->
+ %% This try...catch block looks like a guard.
+ %% Make sure that it is not optimized like a guard
+ %% (the put/2 call must not be optimized away).
+ try
+ put(K, V),
+ false
+ catch
+ _:_ ->
+ false
+ end.
+
coverage(Config) when is_list(Config) ->
?line {'EXIT',{{case_clause,{a,b,c}},_}} =
(catch cover_will_match_list_type({a,b,c})),
@@ -214,6 +231,7 @@ coverage(Config) when is_list(Config) ->
(catch cover_will_match_list_type({a,b,c,d})),
?line a = cover_remove_non_vars_alias({a,b,c}),
?line error = cover_will_match_lit_list(),
+ {ok,[a]} = cover_is_safe_bool_expr(a),
%% Make sure that we don't attempt to make literals
%% out of pids. (Putting a pid into a #c_literal{}
@@ -249,4 +267,17 @@ cover_will_match_lit_list() ->
error
end.
+cover_is_safe_bool_expr(X) ->
+ %% Use a try...catch that looks like a try...catch in a guard.
+ try
+ %% let V = [X] in {ok,V}
+ %% is_safe_simple([X]) ==> true
+ %% is_safe_bool_expr([X]) ==> false
+ V = [X],
+ {ok,V}
+ catch
+ _:_ ->
+ false
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 368a5815bf..6067ee8e06 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -20,7 +20,11 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1]).
+ test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
+ external/1]).
+
+%% Internal export.
+-export([call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [test1, overwritten_fun, otp_7202, bif_fun].
+ [test1,overwritten_fun,otp_7202,bif_fun,external].
groups() ->
[].
@@ -45,7 +49,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
%%% The help functions below are copied from emulator:bs_construct_SUITE.
-define(T(B, L), {B, ??B, L}).
@@ -152,4 +155,47 @@ bif_fun(Config) when is_list(Config) ->
?line F = fun abs/1,
?line 5 = F(-5),
ok.
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
index c0bf04ed8f..cffb792920 100644
--- a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
+++ b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
@@ -19,10 +19,10 @@
{get_tuple_element,{x,0},1,{x,2}}.
{get_tuple_element,{x,0},2,{x,3}}.
{get_tuple_element,{x,0},3,{x,4}}.
- {gc_bif,'+',{f,0},5,[{x,1},{x,2}],{x,0}}.
- {gc_bif,'+',{f,0},5,[{x,0},{x,3}],{x,0}}.
- {gc_bif,'+',{f,0},5,[{x,0},{x,4}],{x,0}}.
- {gc_bif,'+',{f,0},5,[{x,0},{x,5}],{x,0}}.
+ {gc_bif,'+',{f,0},6,[{x,1},{x,2}],{x,0}}.
+ {gc_bif,'+',{f,0},6,[{x,0},{x,3}],{x,0}}.
+ {gc_bif,'+',{f,0},6,[{x,0},{x,4}],{x,0}}.
+ {gc_bif,'+',{f,0},6,[{x,0},{x,5}],{x,0}}.
return.
{label,3}.
{badmatch,{x,0}}.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index 086fba2649..2e17d3fde6 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -33,7 +33,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
[attribute, bsdecode, bsdes, barnes2, decode1, smith,
- itracer, pseudoknot, lists, really_inlined, otp_7223,
+ itracer, pseudoknot, comma_splitter, lists, really_inlined, otp_7223,
coverage].
groups() ->
@@ -78,6 +78,7 @@ attribute(Config) when is_list(Config) ->
?comp(smith).
?comp(itracer).
?comp(pseudoknot).
+?comp(comma_splitter).
try_inline(Mod, Config) ->
?line Src = filename:join(?config(data_dir, Config), atom_to_list(Mod)),
diff --git a/lib/compiler/test/inline_SUITE_data/comma_splitter.erl b/lib/compiler/test/inline_SUITE_data/comma_splitter.erl
new file mode 100644
index 0000000000..eaa89e0edc
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/comma_splitter.erl
@@ -0,0 +1,18 @@
+-module(comma_splitter).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ {<<"def">>,<<"cba">>} = split_at_comma(<<"abc, def">>, <<>>),
+ ok.
+
+strip_leading_ws(<<N, Rest/binary>>) when N =< $\s ->
+ strip_leading_ws(Rest);
+strip_leading_ws(B) ->
+ B.
+
+split_at_comma(<<>>, Accu) ->
+ {<<>>, Accu};
+split_at_comma(<<$,, Rest/binary>>, Accu) ->
+ {strip_leading_ws(Rest), Accu};
+split_at_comma(<<C, Rest/binary>>, Accu) ->
+ split_at_comma(Rest, <<C, Accu/binary>>).
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index 9b414cade6..b53d0dba1d 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -190,6 +190,24 @@ silly_coverage(Config) when is_list(Config) ->
{label,2}|non_proper_list]}],99},
?line expect_error(fun() -> beam_block:module(BlockInput, []) end),
+ %% beam_type
+ TypeInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {line,loc},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list]}],99},
+ expect_error(fun() -> beam_type:module(TypeInput, []) end),
+
+ %% beam_except
+ ExceptInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {line,loc},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list]}],99},
+ expect_error(fun() -> beam_except:module(ExceptInput, []) end),
+
%% beam_bool
BoolInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
@@ -253,8 +271,15 @@ expect_error(Fun) ->
io:format("~p", [Any]),
?t:fail(call_was_supposed_to_fail)
catch
- _:_ ->
- io:format("~p\n", [erlang:get_stacktrace()])
+ Class:Reason ->
+ Stk = erlang:get_stacktrace(),
+ io:format("~p:~p\n~p\n", [Class,Reason,Stk]),
+ case {Class,Reason} of
+ {error,undef} ->
+ ?t:fail(not_supposed_to_fail_with_undef);
+ {_,_} ->
+ ok
+ end
end.
confused_literals(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/parteval_SUITE.erl b/lib/compiler/test/parteval_SUITE.erl
deleted file mode 100644
index 6b1ae38c1b..0000000000
--- a/lib/compiler/test/parteval_SUITE.erl
+++ /dev/null
@@ -1,66 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(parteval_SUITE).
-
--include_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, pe2/1]).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [pe2].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% (This is more general than needed, since we once compiled the same
-%% source code with and without a certain option.)
-compile_and_load(Srcname, Outdir, Module, Options) ->
- ?line Objname = filename:join(Outdir, "t1") ++ code:objfile_extension(),
- ?line {ok, Module} =
- compile:file(Srcname,
- [{d, 'M', Module}, {outdir, Outdir}] ++ Options),
- ?line {ok, B} = file:read_file(Objname),
- ?line {module, Module} = code:load_binary(Module, Objname, B),
- B.
-
-pe2(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Srcname = filename:join(DataDir, "t1.erl"),
- ?line compile_and_load(Srcname, PrivDir, t1, []),
-
- ?line {Correct, Actual} = t1:run(),
- ?line Correct = Actual,
- ok.
diff --git a/lib/compiler/test/parteval_SUITE_data/t1.erl b/lib/compiler/test/parteval_SUITE_data/t1.erl
deleted file mode 100644
index 5e4a40f103..0000000000
--- a/lib/compiler/test/parteval_SUITE_data/t1.erl
+++ /dev/null
@@ -1,140 +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%
-%%
--module(?M).
-
--compile(export_all).
-
-%%% The arity-0 functions are all called from the test suite.
-
-f2() ->
- size({1,2}).
-
-i() ->
- case [] of
- [] ->
- ok;
- X ->
- hopp
- end.
-
-e() ->
- case 4+5 of
-% X when X>10 -> kvock; % not removed by BEAM opt.
- {X,X} when list(X) ->
- kvack;
- 9 ->
- ok;
- _ ->
- ko
- end.
-
-f() ->
- element(2,{a,b,c,d}),
- erlang:element(2,{a,b,c,d}),
- "hej" ++ "hopp".
-
-g(X) ->
- if
- float(3.4) ->
- hej;
- X == 5, 4==4 ->
- japp;
- 4 == 4, size({1,2}) == 1 ->
- ok
- end.
-
-g() ->
- {g(3),g(5)}.
-
-bliff() ->
- if
- 3==4 ->
- himm
- end.
-
-fi() ->
- case 4 of
- X when 4==3 ->
- {X};
- 4 ->
- 4;
- _ ->
- ok
- end.
-
-iff() when 3==2 ->
- if
- 3 == 4 ->
- baff;
- 3 == 3 ->
- nipp
- end.
-
-sleep(I) -> receive after I -> ok end.
-
-sleep() ->
- sleep(45).
-
-s() ->
- case 4 of
- 3 ->
- ok
- end.
-
-error_reason(R) when atom(R) ->
- R;
-error_reason(R) when tuple(R) ->
- error_reason(element(1, R)).
-
-plusplus() ->
- ?MODULE ++ " -> mindre snygg felhantering".
-
-call_it(F) ->
- case (catch apply(?MODULE, F, [])) of
- {'EXIT', R0} ->
- {'EXIT', error_reason(R0)};
- V ->
- V
- end.
-
-run() ->
- L = [{f2, 2},
- {i, ok},
- {e, ok},
- {f, "hejhopp"},
- {g, {hej, hej}},
- {bliff, {'EXIT', if_clause}},
- {fi, 4},
- {iff, {'EXIT', function_clause}},
- {sleep, ok},
- {s, {'EXIT', case_clause},
- {plusplus, {'EXIT', badarg}}}],
- Actual = [call_it(F) || {F, _} <- L],
- Correct = [C || {_, C} <- L],
- {Correct, Actual}.
-
-
-%%% Don't call, only compile.
-t(A) ->
- receive
- A when 1==2 ->
- ok;
- B ->
- B
- end.
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
index 9a317b5762..5dd09a7245 100644
--- a/lib/compiler/test/pmod_SUITE.erl
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -96,6 +96,11 @@ basic_1(Config, Opts) ->
?line error = Prop4:bar_bar({s,a,b}),
?line error = Prop4:bar_bar([]),
+ %% Call from a fun.
+ Fun = fun(Arg) -> Prop4:bar(Arg) end,
+ ?line ok = Fun({s,0}),
+
+ [{y,[1,2]},{x,[5,19]}] = Prop4:collapse([{y,[2,1]},{x,[19,5]}]),
ok.
otp_8447(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl b/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl
index 0d46cffe00..19cce452dc 100644
--- a/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl
+++ b/lib/compiler/test/pmod_SUITE_data/pmod_basic.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
@@ -21,6 +21,7 @@
-export([lookup/1,or_props/1,prepend/1,append/1,stupid_sum/0]).
-export([bar/1,bar_bar/1]).
-export([bc1/0, bc2/0]).
+-export([collapse/1]).
lookup(Key) ->
proplists:lookup(Key, Props).
@@ -77,3 +78,6 @@ bc1() ->
bc2() ->
<< <<A:1>> || A <- [1,0,1,0] >>.
+
+collapse(L) ->
+ lists:keymap(fun lists:sort/1, 2, L).
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 53d8c04169..2295592a38 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -77,7 +77,14 @@ get_data_dir(Config) ->
%% Will fail the test case if there were any errors.
p_run(Test, List) ->
- N = erlang:system_info(schedulers) + 1,
+ N = case ?t:is_cover() of
+ false ->
+ erlang:system_info(schedulers);
+ true ->
+ %% Cover is running. Using more than one process
+ %% will probably only slow down compilation.
+ 1
+ end,
p_run_loop(Test, List, N, [], 0, 0).
p_run_loop(_, [], _, [], Errors, Ws) ->
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 760cf17225..29119c0f5d 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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 @@
catch_oops/1,after_oops/1,eclectic/1,rethrow/1,
nested_of/1,nested_catch/1,nested_after/1,
nested_horrid/1,last_call_optimization/1,bool/1,
- plain_catch_coverage/1,andalso_orelse/1]).
+ plain_catch_coverage/1,andalso_orelse/1,get_in_try/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,7 +35,7 @@ all() ->
[basic, lean_throw, try_of, try_after, catch_oops,
after_oops, eclectic, rethrow, nested_of, nested_catch,
nested_after, nested_horrid, last_call_optimization,
- bool, plain_catch_coverage, andalso_orelse].
+ bool, plain_catch_coverage, andalso_orelse, get_in_try].
groups() ->
[].
@@ -928,3 +928,17 @@ andalso_orelse_2({Type,Keyval}) ->
zero() ->
0.0.
+
+get_in_try(_) ->
+ undefined = get_valid_line([a], []),
+ ok.
+
+get_valid_line([_|T]=Path, Annotations) ->
+ try
+ get(Path)
+ %% beam_dead used to optimize away an assignment to {y,1}
+ %% because it didn't appear to be used.
+ catch
+ _:not_found ->
+ get_valid_line(T, Annotations)
+ end.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 04290c0a7f..c9c28cf9a2 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 4.7.5
+COMPILER_VSN = 4.8.1
diff --git a/lib/configure.in.src b/lib/configure.in.src
index 792a7f932a..fea3c7bffa 100644
--- a/lib/configure.in.src
+++ b/lib/configure.in.src
@@ -1,7 +1,7 @@
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1999-2010. All Rights Reserved.
+dnl Copyright Ericsson AB 1999-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
@@ -17,7 +17,7 @@ dnl
dnl %CopyrightEnd%
dnl
-dnl Turn of caching
+dnl Turn off caching
define([AC_CACHE_LOAD], )dnl
define([AC_CACHE_SAVE], )dnl
diff --git a/lib/cosEvent/doc/src/Makefile b/lib/cosEvent/doc/src/Makefile
index 4b76a64b7d..4a0a7429e9 100644
--- a/lib/cosEvent/doc/src/Makefile
+++ b/lib/cosEvent/doc/src/Makefile
@@ -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
@@ -26,13 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(COSEVENT_VSN)
APPLICATION=cosEvent
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
# ----------------------------------------------------
# Release directory specification
@@ -98,32 +91,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -136,8 +107,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -153,31 +122,6 @@ clean clean_docs:
rm -f errs core *~
rm -f $(JD_HTML) $(JD_PACK)
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -192,42 +136,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosEvent/doc/src/make.dep b/lib/cosEvent/doc/src/make.dep
deleted file mode 100644
index b8a95c2d58..0000000000
--- a/lib/cosEvent/doc/src/make.dep
+++ /dev/null
@@ -1,34 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosEventChannelAdmin.tex CosEventChannelAdmin_ConsumerAdmin.tex \
- CosEventChannelAdmin_EventChannel.tex CosEventChannelAdmin_ProxyPullConsumer.tex \
- CosEventChannelAdmin_ProxyPullSupplier.tex \
- CosEventChannelAdmin_ProxyPushConsumer.tex \
- CosEventChannelAdmin_ProxyPushSupplier.tex \
- CosEventChannelAdmin_SupplierAdmin.tex book.tex \
- ch_contents.tex ch_event_service.tex ch_introduction.tex \
- cosEventApp.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-CosEventChannelAdmin.tex: ../../src/CosEventChannelAdmin.idl
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: e_s_components.ps e_s_models.ps
-
diff --git a/lib/cosEvent/doc/src/notes.xml b/lib/cosEvent/doc/src/notes.xml
index 1da5399755..de98a44b6a 100644
--- a/lib/cosEvent/doc/src/notes.xml
+++ b/lib/cosEvent/doc/src/notes.xml
@@ -32,7 +32,25 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>cosEvent 2.1.12</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>cosEvent 2.1.11</title>
<section>
diff --git a/lib/cosEvent/src/Makefile b/lib/cosEvent/src/Makefile
index c774d18380..1825beacc5 100644
--- a/lib/cosEvent/src/Makefile
+++ b/lib/cosEvent/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
@@ -164,7 +164,7 @@ debug:
@${MAKE} TYPE=debug opt
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -197,14 +197,14 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) ../info $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) ../info "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosEvent/test/Makefile b/lib/cosEvent/test/Makefile
index c3f07c156f..d5350d8293 100644
--- a/lib/cosEvent/test/Makefile
+++ b/lib/cosEvent/test/Makefile
@@ -141,11 +141,11 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
+ $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
$(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- $(RELSYSDIR)/$(IDLOUTDIR)
+ "$(RELSYSDIR)/$(IDLOUTDIR)"
diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk
index 85d3cf552b..2cd943e4b2 100644
--- a/lib/cosEvent/vsn.mk
+++ b/lib/cosEvent/vsn.mk
@@ -1,3 +1,3 @@
-COSEVENT_VSN = 2.1.11
+COSEVENT_VSN = 2.1.12
diff --git a/lib/cosEventDomain/doc/src/Makefile b/lib/cosEventDomain/doc/src/Makefile
index 6a0d3c353a..4e54b0fb55 100644
--- a/lib/cosEventDomain/doc/src/Makefile
+++ b/lib/cosEventDomain/doc/src/Makefile
@@ -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
@@ -28,14 +28,6 @@ VSN=$(COSEVENTDOMAIN_VSN)
APPLICATION=cosEventDomain
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -93,33 +85,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -132,8 +101,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -149,32 +116,6 @@ clean clean_docs:
rm -f errs core *~
rm -f $(JD_HTML) $(JD_PACK)
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -189,42 +130,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosEventDomain/doc/src/make.dep b/lib/cosEventDomain/doc/src/make.dep
deleted file mode 100644
index 2f3f1ae53d..0000000000
--- a/lib/cosEventDomain/doc/src/make.dep
+++ /dev/null
@@ -1,23 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosEventDomainAdmin.tex CosEventDomainAdmin_EventDomain.tex \
- CosEventDomainAdmin_EventDomainFactory.tex \
- book.tex ch_QoS.tex ch_contents.tex ch_event_domain_service.tex \
- ch_introduction.tex cosEventDomainApp.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/cosEventDomain/doc/src/notes.xml b/lib/cosEventDomain/doc/src/notes.xml
index 585761ce65..fa96792c33 100644
--- a/lib/cosEventDomain/doc/src/notes.xml
+++ b/lib/cosEventDomain/doc/src/notes.xml
@@ -31,7 +31,25 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>cosEventDomain 1.1.12</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>cosEventDomain 1.1.11</title>
<section>
diff --git a/lib/cosEventDomain/src/Makefile b/lib/cosEventDomain/src/Makefile
index 91bef4e7e6..41a31b332f 100644
--- a/lib/cosEventDomain/src/Makefile
+++ b/lib/cosEventDomain/src/Makefile
@@ -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
@@ -137,7 +137,7 @@ debug:
@${MAKE} TYPE=debug opt
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -166,14 +166,14 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) ../info $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) ../info "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosEventDomain/test/Makefile b/lib/cosEventDomain/test/Makefile
index 160c8565e8..9349067eb5 100644
--- a/lib/cosEventDomain/test/Makefile
+++ b/lib/cosEventDomain/test/Makefile
@@ -98,8 +98,8 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
+ $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk
index 7df47cef2e..5ad421e319 100644
--- a/lib/cosEventDomain/vsn.mk
+++ b/lib/cosEventDomain/vsn.mk
@@ -1,3 +1,3 @@
-COSEVENTDOMAIN_VSN = 1.1.11
+COSEVENTDOMAIN_VSN = 1.1.12
diff --git a/lib/cosFileTransfer/doc/src/Makefile b/lib/cosFileTransfer/doc/src/Makefile
index 2286db43ff..706dec00ce 100644
--- a/lib/cosFileTransfer/doc/src/Makefile
+++ b/lib/cosFileTransfer/doc/src/Makefile
@@ -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
@@ -26,14 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(COSFILETRANSFER_VSN)
APPLICATION=cosFileTransfer
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
# ----------------------------------------------------
# Release directory specification
@@ -97,33 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -136,8 +105,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -152,32 +119,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -192,42 +133,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosFileTransfer/doc/src/make.dep b/lib/cosFileTransfer/doc/src/make.dep
deleted file mode 100644
index 3be0c185c3..0000000000
--- a/lib/cosFileTransfer/doc/src/make.dep
+++ /dev/null
@@ -1,30 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosFileTransfer_Directory.tex CosFileTransfer_File.tex \
- CosFileTransfer_FileIterator.tex CosFileTransfer_FileTransferSession.tex \
- CosFileTransfer_VirtualFileSystem.tex book.tex \
- ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex ch_system.tex cosFileTransferApp.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosFileTransfer.ps
-
diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml
index c7a4fd4504..f38597db10 100644
--- a/lib/cosFileTransfer/doc/src/notes.xml
+++ b/lib/cosFileTransfer/doc/src/notes.xml
@@ -30,7 +30,25 @@
<file>notes.xml</file>
</header>
- <section><title>cosFileTransfer 1.1.12</title>
+ <section><title>cosFileTransfer 1.1.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosFileTransfer 1.1.12</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/cosFileTransfer/src/Makefile b/lib/cosFileTransfer/src/Makefile
index 17e82f9bc2..1bb765db73 100644
--- a/lib/cosFileTransfer/src/Makefile
+++ b/lib/cosFileTransfer/src/Makefile
@@ -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
@@ -147,7 +147,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -176,12 +176,12 @@ $(TARGET_FILES): IDL-GENERATED
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) $(GEN_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosFileTransfer/test/Makefile b/lib/cosFileTransfer/test/Makefile
index b46fb35356..177ad7616b 100644
--- a/lib/cosFileTransfer/test/Makefile
+++ b/lib/cosFileTransfer/test/Makefile
@@ -126,8 +126,8 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
+ $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
diff --git a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
index e94c307ef8..79a234bd28 100644
--- a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
+++ b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
@@ -131,10 +131,10 @@ end_per_testcase(_Case, Config) ->
ok.
init_per_suite(Config) ->
- case code:which(crypto) of
- Res when is_atom(Res) ->
+ case crypto_works() of
+ false ->
{skip,"Could not start crypto!"};
- _Else ->
+ true ->
orber:jump_start(),
cosProperty:install(),
cosProperty:start(),
@@ -165,6 +165,15 @@ init_per_suite(Config) ->
end
end.
+crypto_works() ->
+ try crypto:start() of
+ {error,{already_started,crypto}} -> true;
+ ok -> true
+ catch
+ error:_ ->
+ false
+ end.
+
end_per_suite(Config) ->
ssl:stop(),
crypto:stop(),
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
index fe0226e3b3..6d0c6669a3 100644
--- a/lib/cosFileTransfer/vsn.mk
+++ b/lib/cosFileTransfer/vsn.mk
@@ -1 +1 @@
-COSFILETRANSFER_VSN = 1.1.12
+COSFILETRANSFER_VSN = 1.1.13
diff --git a/lib/cosNotification/doc/src/Makefile b/lib/cosNotification/doc/src/Makefile
index bfdd2f1f8c..d970818928 100644
--- a/lib/cosNotification/doc/src/Makefile
+++ b/lib/cosNotification/doc/src/Makefile
@@ -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
@@ -28,14 +28,6 @@ VSN=$(COSNOTIFICATION_VSN)
APPLICATION=cosNotification
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -122,33 +114,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -161,8 +130,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -177,32 +144,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -217,41 +158,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosNotification/doc/src/make.dep b/lib/cosNotification/doc/src/make.dep
deleted file mode 100644
index 031a2b3e98..0000000000
--- a/lib/cosNotification/doc/src/make.dep
+++ /dev/null
@@ -1,48 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosNotification.tex CosNotification_AdminPropertiesAdmin.tex \
- CosNotification_QoSAdmin.tex CosNotifyChannelAdmin_ConsumerAdmin.tex \
- CosNotifyChannelAdmin_EventChannel.tex CosNotifyChannelAdmin_EventChannelFactory.tex \
- CosNotifyChannelAdmin_ProxyConsumer.tex CosNotifyChannelAdmin_ProxyPullConsumer.tex \
- CosNotifyChannelAdmin_ProxyPullSupplier.tex \
- CosNotifyChannelAdmin_ProxyPushConsumer.tex \
- CosNotifyChannelAdmin_ProxyPushSupplier.tex \
- CosNotifyChannelAdmin_ProxySupplier.tex CosNotifyChannelAdmin_SequenceProxyPullConsumer.tex \
- CosNotifyChannelAdmin_SequenceProxyPullSupplier.tex \
- CosNotifyChannelAdmin_SequenceProxyPushConsumer.tex \
- CosNotifyChannelAdmin_SequenceProxyPushSupplier.tex \
- CosNotifyChannelAdmin_StructuredProxyPullConsumer.tex \
- CosNotifyChannelAdmin_StructuredProxyPullSupplier.tex \
- CosNotifyChannelAdmin_StructuredProxyPushConsumer.tex \
- CosNotifyChannelAdmin_StructuredProxyPushSupplier.tex \
- CosNotifyChannelAdmin_SupplierAdmin.tex CosNotifyComm_NotifyPublish.tex \
- CosNotifyComm_NotifySubscribe.tex CosNotifyFilter_Filter.tex \
- CosNotifyFilter_FilterAdmin.tex CosNotifyFilter_FilterFactory.tex \
- CosNotifyFilter_MappingFilter.tex book.tex \
- ch_BNF.tex ch_QoS.tex ch_contents.tex ch_example.tex \
- ch_install.tex ch_introduction.tex ch_system.tex \
- cosNotificationApp.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: eventstructure.ps
-
-book.dvi: notificationFlow.ps
-
diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml
index a54230c9f7..c79d040f9a 100644
--- a/lib/cosNotification/doc/src/notes.xml
+++ b/lib/cosNotification/doc/src/notes.xml
@@ -31,7 +31,25 @@
<file>notes.xml</file>
</header>
- <section><title>cosNotification 1.1.17</title>
+ <section><title>cosNotification 1.1.18</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosNotification 1.1.17</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosNotification/src/Makefile b/lib/cosNotification/src/Makefile
index b976ab94f3..7b8b73aa11 100644
--- a/lib/cosNotification/src/Makefile
+++ b/lib/cosNotification/src/Makefile
@@ -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
@@ -328,7 +328,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -367,12 +367,12 @@ $(GEN_YECC_ERL_FILES) $(GEN_YECC_HRL_FILES): cosNotification_Grammar.yrl
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) $(GEN_FILES) $(IDL_FILES) $(YECC_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILES) $(YECC_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) $(YECC_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILES) $(YECC_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosNotification/test/Makefile b/lib/cosNotification/test/Makefile
index f509370430..17b60a8e9f 100644
--- a/lib/cosNotification/test/Makefile
+++ b/lib/cosNotification/test/Makefile
@@ -128,6 +128,7 @@ ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
-pa $(ERL_TOP)/lib/orber/include \
-pa $(ERL_TOP)/internal_tools/test_server/ebin \
+ -pa $(ERL_TOP)/lib/cosEvent/ebin \
-pa $(ERL_TOP)/lib/cosNotification/ebin \
-pa $(ERL_TOP)/lib/cosNotification/test/idl_output \
-pa $(ERL_TOP)/lib/cosTime/ebin \
@@ -182,11 +183,11 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
+ $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
$(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- $(RELSYSDIR)/$(IDLOUTDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
+ "$(RELSYSDIR)/$(IDLOUTDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk
index b32919a2ef..e7c5465fe4 100644
--- a/lib/cosNotification/vsn.mk
+++ b/lib/cosNotification/vsn.mk
@@ -1,2 +1,2 @@
-COSNOTIFICATION_VSN = 1.1.17
+COSNOTIFICATION_VSN = 1.1.18
diff --git a/lib/cosProperty/doc/src/Makefile b/lib/cosProperty/doc/src/Makefile
index baf995d35e..9bfacc27bd 100644
--- a/lib/cosProperty/doc/src/Makefile
+++ b/lib/cosProperty/doc/src/Makefile
@@ -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
@@ -28,14 +28,6 @@ VSN=$(COSPROPERTY_VSN)
APPLICATION=cosProperty
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -99,35 +91,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
MAN6_FILES = $(XML_REF6_FILES:%.xml=$(MAN6DIR)/%.6)
-
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_REF6_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -140,8 +107,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -156,42 +121,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-tex_users_guide: $(TEX_FILES_USERS_GUIDE)
-tex_ref_man: $(TEX_FILES_REF_MAN)
-tex: tex_users_guide tex_ref_man $(TEX_FILES_BOOK)
-
-$(DOCDIR)/latexlog: $(BOOK_FILES:%.xml=%.dvi)
- -fgrep -i "latex warning" $(BOOK_FILES:%.xml=%.log) >$(DOCDIR)/latexlog
-
-clean_tex:
- -rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
-
-clean:
- rm -f ../html/* $(MAN3_FILES) $(MAN6_FILES) $(TEX_FILES_USERS_GUIDE)
- rm -f *xmls_output *xmls_errs
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -206,41 +135,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosProperty/doc/src/make.dep b/lib/cosProperty/doc/src/make.dep
deleted file mode 100644
index 383af54244..0000000000
--- a/lib/cosProperty/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosPropertyService_PropertiesIterator.tex \
- CosPropertyService_PropertyNamesIterator.tex \
- CosPropertyService_PropertySet.tex CosPropertyService_PropertySetDef.tex \
- CosPropertyService_PropertySetDefFactory.tex \
- CosPropertyService_PropertySetFactory.tex \
- book.tex ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex cosProperty.tex part.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/cosProperty/doc/src/notes.xml b/lib/cosProperty/doc/src/notes.xml
index 85b2119e9d..f5f737e2a3 100644
--- a/lib/cosProperty/doc/src/notes.xml
+++ b/lib/cosProperty/doc/src/notes.xml
@@ -31,7 +31,25 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>cosProperty 1.1.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>cosProperty 1.1.14</title>
<section>
diff --git a/lib/cosProperty/src/Makefile b/lib/cosProperty/src/Makefile
index d12554b18d..cb2c56743c 100644
--- a/lib/cosProperty/src/Makefile
+++ b/lib/cosProperty/src/Makefile
@@ -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
@@ -147,7 +147,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -176,12 +176,12 @@ $(TARGET_FILES): IDL-GENERATED
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) $(GEN_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosProperty/test/Makefile b/lib/cosProperty/test/Makefile
index f6e0d0dbba..d85b8a655a 100644
--- a/lib/cosProperty/test/Makefile
+++ b/lib/cosProperty/test/Makefile
@@ -120,11 +120,11 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
-# $(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
+ $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
+# $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
# $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
-# $(RELSYSDIR)/$(IDLOUTDIR)
+# "$(RELSYSDIR)/$(IDLOUTDIR)"
diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk
index ecc4a2746c..a4b1a2c94e 100644
--- a/lib/cosProperty/vsn.mk
+++ b/lib/cosProperty/vsn.mk
@@ -1,2 +1,2 @@
-COSPROPERTY_VSN = 1.1.14
+COSPROPERTY_VSN = 1.1.15
diff --git a/lib/cosTime/doc/src/Makefile b/lib/cosTime/doc/src/Makefile
index 83abc5e7c2..f89c022c4a 100644
--- a/lib/cosTime/doc/src/Makefile
+++ b/lib/cosTime/doc/src/Makefile
@@ -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
@@ -28,14 +28,6 @@ VSN=$(COSTIME_VSN)
APPLICATION=cosTime
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -93,33 +85,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -132,8 +101,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -148,32 +115,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -188,41 +129,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosTime/doc/src/make.dep b/lib/cosTime/doc/src/make.dep
deleted file mode 100644
index 69a584ab95..0000000000
--- a/lib/cosTime/doc/src/make.dep
+++ /dev/null
@@ -1,22 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosTime_TIO.tex CosTime_TimeService.tex CosTime_UTO.tex \
- CosTimerEvent_TimerEventHandler.tex CosTimerEvent_TimerEventService.tex \
- book.tex ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex cosTime.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/cosTime/doc/src/notes.xml b/lib/cosTime/doc/src/notes.xml
index 3698e4813e..c70978df2b 100644
--- a/lib/cosTime/doc/src/notes.xml
+++ b/lib/cosTime/doc/src/notes.xml
@@ -32,7 +32,25 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>cosTime 1.1.12</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>cosTime 1.1.11</title>
<section>
diff --git a/lib/cosTime/src/Makefile b/lib/cosTime/src/Makefile
index 1793822fb6..35f16edcef 100644
--- a/lib/cosTime/src/Makefile
+++ b/lib/cosTime/src/Makefile
@@ -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
@@ -162,7 +162,7 @@ cleanb:
rm -f errs core *~
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -195,12 +195,12 @@ $(TARGET_FILES): IDL-GENERATED
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) $(GEN_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosTime/test/Makefile b/lib/cosTime/test/Makefile
index a07b27eecb..ab4d140537 100644
--- a/lib/cosTime/test/Makefile
+++ b/lib/cosTime/test/Makefile
@@ -126,11 +126,11 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
-# $(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
+ $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
+# $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
# $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
-# $(RELSYSDIR)/$(IDLOUTDIR)
+# "$(RELSYSDIR)/$(IDLOUTDIR)"
diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk
index 4d982f3013..14d3b61bc6 100644
--- a/lib/cosTime/vsn.mk
+++ b/lib/cosTime/vsn.mk
@@ -1,2 +1,2 @@
-COSTIME_VSN = 1.1.11
+COSTIME_VSN = 1.1.12
diff --git a/lib/cosTransactions/doc/src/Makefile b/lib/cosTransactions/doc/src/Makefile
index 1af9ed24b7..4edad9829b 100644
--- a/lib/cosTransactions/doc/src/Makefile
+++ b/lib/cosTransactions/doc/src/Makefile
@@ -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
@@ -28,14 +28,6 @@ VSN=$(COSTRANSACTIONS_VSN)
APPLICATION=cosTransactions
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -97,33 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -136,8 +105,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -152,32 +119,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -192,41 +133,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/cosTransactions/doc/src/make.dep b/lib/cosTransactions/doc/src/make.dep
deleted file mode 100644
index bd45aea286..0000000000
--- a/lib/cosTransactions/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosTransactions_Control.tex CosTransactions_Coordinator.tex \
- CosTransactions_RecoveryCoordinator.tex CosTransactions_Resource.tex \
- CosTransactions_SubtransactionAwareResource.tex \
- CosTransactions_Terminator.tex CosTransactions_TransactionFactory.tex \
- book.tex ch_contents.tex ch_example.tex ch_install.tex \
- ch_introduction.tex ch_skeletons.tex cosTransactions.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ch_example.tex: ../../../../system/doc/definitions/term.defs
-
diff --git a/lib/cosTransactions/doc/src/notes.xml b/lib/cosTransactions/doc/src/notes.xml
index 29addf424d..f3a7a83fb0 100644
--- a/lib/cosTransactions/doc/src/notes.xml
+++ b/lib/cosTransactions/doc/src/notes.xml
@@ -32,7 +32,25 @@
<file>notes.xml</file>
</header>
- <section>
+ <section><title>cosTransactions 1.2.12</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
<title>cosTransactions 1.2.11</title>
<section>
<title>Improvements and New Features</title>
diff --git a/lib/cosTransactions/examples/Makefile b/lib/cosTransactions/examples/Makefile
index 24cd12202a..0408cad75d 100644
--- a/lib/cosTransactions/examples/Makefile
+++ b/lib/cosTransactions/examples/Makefile
@@ -149,9 +149,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(IDL_FILES) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(INETRC_EXAMPLE) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(IDL_FILES) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(INETRC_EXAMPLE) "$(RELSYSDIR)/examples"
@tar cf - java_output | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/cosTransactions/src/Makefile b/lib/cosTransactions/src/Makefile
index 4b77251c3c..0922a21641 100644
--- a/lib/cosTransactions/src/Makefile
+++ b/lib/cosTransactions/src/Makefile
@@ -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
@@ -141,7 +141,7 @@ debug:
@${MAKE} TYPE=debug
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -170,11 +170,11 @@ $(TARGET_FILES): IDL-GENERATED
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) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILE) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILE) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/cosTransactions/test/Makefile b/lib/cosTransactions/test/Makefile
index 0bc8c007da..80f4b6c624 100644
--- a/lib/cosTransactions/test/Makefile
+++ b/lib/cosTransactions/test/Makefile
@@ -142,11 +142,11 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
+ $(COVER_FILE) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
$(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- $(RELSYSDIR)/$(IDLOUTDIR)
+ "$(RELSYSDIR)/$(IDLOUTDIR)"
diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk
index 3960c58c5b..7ca604b589 100644
--- a/lib/cosTransactions/vsn.mk
+++ b/lib/cosTransactions/vsn.mk
@@ -1 +1 @@
-COSTRANSACTIONS_VSN = 1.2.11
+COSTRANSACTIONS_VSN = 1.2.12
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 285537643e..cfc9a447e0 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -85,7 +85,7 @@ 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) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
+CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPTO_LIBNAME)
else
SSL_DED_LD_RUNTIME_LIBRARY_PATH=
CRYPTO_LINK_LIB=$(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a
@@ -133,11 +133,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/obj
- $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_DATA) $(NIF_MAKEFILE) $(RELSYSDIR)/priv/obj
- $(INSTALL_PROGRAM) $(OBJS) $(RELSYSDIR)/priv/obj
- $(INSTALL_PROGRAM) $(NIF_LIB) $(RELSYSDIR)/priv/lib
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_PROGRAM) $(OBJS) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib"
release_docs_spec:
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index c781ccb302..a24747a872 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2012. All Rights Reserved.
*
* The 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,6 +53,21 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224)\
+ && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */
+# define HAVE_SHA224
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256)
+# define HAVE_SHA256
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA384) && defined(NID_sha384)\
+ && !defined(OPENSSL_NO_SHA512) /* disabled like this in my sha.h (?) */
+# define HAVE_SHA384
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA512) && defined(NID_sha512)
+# define HAVE_SHA512
+#endif
+
#ifdef VALGRIND
# include <valgrind/memcheck.h>
@@ -124,18 +139,40 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
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 sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_mac_nif(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[]);
@@ -146,13 +183,13 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI
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[]);
-static ERL_NIF_TERM rsa_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -180,12 +217,33 @@ static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr,
#endif /* OPENSSL_THREADS */
/* helpers */
+static void init_digest_types(ErlNifEnv* env);
static void hmac_md5(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
unsigned char *hmacbuf);
static void hmac_sha1(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
unsigned char *hmacbuf);
+#ifdef HAVE_SHA224
+static void hmac_sha224(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
+#ifdef HAVE_SHA256
+static void hmac_sha256(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
+#ifdef HAVE_SHA384
+static void hmac_sha384(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
+#ifdef HAVE_SHA512
+static void hmac_sha512(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
static int library_refc = 0; /* number of users of this dynamic library */
@@ -199,19 +257,41 @@ static ErlNifFunc nif_funcs[] = {
{"sha_init", 0, sha_init},
{"sha_update", 2, sha_update},
{"sha_final", 1, sha_final},
+ {"sha224_nif", 1, sha224_nif},
+ {"sha224_init_nif", 0, sha224_init_nif},
+ {"sha224_update_nif", 2, sha224_update_nif},
+ {"sha224_final_nif", 1, sha224_final_nif},
+ {"sha256_nif", 1, sha256_nif},
+ {"sha256_init_nif", 0, sha256_init_nif},
+ {"sha256_update_nif", 2, sha256_update_nif},
+ {"sha256_final_nif", 1, sha256_final_nif},
+ {"sha384_nif", 1, sha384_nif},
+ {"sha384_init_nif", 0, sha384_init_nif},
+ {"sha384_update_nif", 2, sha384_update_nif},
+ {"sha384_final_nif", 1, sha384_final_nif},
+ {"sha512_nif", 1, sha512_nif},
+ {"sha512_init_nif", 0, sha512_init_nif},
+ {"sha512_update_nif", 2, sha512_update_nif},
+ {"sha512_final_nif", 1, sha512_final_nif},
{"md4", 1, md4},
{"md4_init", 0, md4_init},
{"md4_update", 2, md4_update},
{"md4_final", 1, md4_final},
{"md5_mac_n", 3, md5_mac_n},
{"sha_mac_n", 3, sha_mac_n},
+ {"sha224_mac_nif", 3, sha224_mac_nif},
+ {"sha256_mac_nif", 3, sha256_mac_nif},
+ {"sha384_mac_nif", 3, sha384_mac_nif},
+ {"sha512_mac_nif", 3, sha512_mac_nif},
{"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},
@@ -224,13 +304,13 @@ static ErlNifFunc nif_funcs[] = {
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 3, mod_exp_nif},
{"dss_verify", 4, dss_verify},
- {"rsa_verify", 4, rsa_verify},
+ {"rsa_verify_nif", 4, rsa_verify_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
{"exor", 2, exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rc2_40_cbc_crypt", 4, rc2_40_cbc_crypt},
+ {"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
{"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
@@ -256,7 +336,12 @@ ERL_NIF_INIT(crypto,nif_funcs,load,reload,upgrade,unload)
#define SHA_CTX_LEN (sizeof(SHA_CTX))
#define SHA_LEN 20
#define SHA_LEN_96 12
+#define SHA224_LEN (224/8)
+#define SHA256_LEN (256/8)
+#define SHA384_LEN (384/8)
+#define SHA512_LEN (512/8)
#define HMAC_INT_LEN 64
+#define HMAC_INT2_LEN 128
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
@@ -266,6 +351,10 @@ static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_sha;
+static ERL_NIF_TERM atom_sha224;
+static ERL_NIF_TERM atom_sha256;
+static ERL_NIF_TERM atom_sha384;
+static ERL_NIF_TERM atom_sha512;
static ERL_NIF_TERM atom_md5;
static ERL_NIF_TERM atom_ripemd160;
static ERL_NIF_TERM atom_error;
@@ -282,6 +371,8 @@ static ERL_NIF_TERM atom_not_suitable_generator;
static ERL_NIF_TERM atom_check_failed;
static ERL_NIF_TERM atom_unknown;
static ERL_NIF_TERM atom_none;
+static ERL_NIF_TERM atom_notsup;
+static ERL_NIF_TERM atom_digest;
static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info)
@@ -336,6 +427,10 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_true = enif_make_atom(env,"true");
atom_false = enif_make_atom(env,"false");
atom_sha = enif_make_atom(env,"sha");
+ atom_sha224 = enif_make_atom(env,"sha224");
+ atom_sha256 = enif_make_atom(env,"sha256");
+ atom_sha384 = enif_make_atom(env,"sha384");
+ atom_sha512 = enif_make_atom(env,"sha512");
atom_md5 = enif_make_atom(env,"md5");
atom_ripemd160 = enif_make_atom(env,"ripemd160");
atom_error = enif_make_atom(env,"error");
@@ -351,6 +446,10 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_check_failed = enif_make_atom(env,"check_failed");
atom_unknown = enif_make_atom(env,"unknown");
atom_none = enif_make_atom(env,"none");
+ atom_notsup = enif_make_atom(env,"notsup");
+ atom_digest = enif_make_atom(env,"digest");
+
+ init_digest_types(env);
*priv_data = NULL;
library_refc++;
@@ -515,6 +614,251 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+#ifdef HAVE_SHA224
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ SHA224((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,SHA224_LEN, &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAVE_SHA224
+ ERL_NIF_TERM ret;
+ SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+#ifdef HAVE_SHA224
+ SHA256_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
+ memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
+ SHA224_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+#ifdef HAVE_SHA224
+ ErlNifBinary ctx_bin;
+ SHA256_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
+ SHA224_Final(enif_make_new_binary(env, SHA224_LEN, &ret), &ctx_clone);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+#ifdef HAVE_SHA256
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ SHA256((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,SHA256_LEN, &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAVE_SHA256
+ ERL_NIF_TERM ret;
+ SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+#ifdef HAVE_SHA256
+ SHA256_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
+ memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
+ SHA256_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+#ifdef HAVE_SHA256
+ ErlNifBinary ctx_bin;
+ SHA256_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
+ SHA256_Final(enif_make_new_binary(env, SHA256_LEN, &ret), &ctx_clone);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+#ifdef HAVE_SHA384
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ SHA384((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,SHA384_LEN, &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAVE_SHA384
+ ERL_NIF_TERM ret;
+ SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+#ifdef HAVE_SHA384
+ SHA512_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
+ memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
+ SHA384_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+#ifdef HAVE_SHA384
+ ErlNifBinary ctx_bin;
+ SHA512_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
+ SHA384_Final(enif_make_new_binary(env, SHA384_LEN, &ret), &ctx_clone);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+#ifdef HAVE_SHA512
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ SHA512((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,SHA512_LEN, &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAVE_SHA512
+ ERL_NIF_TERM ret;
+ SHA512_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+#ifdef HAVE_SHA512
+ SHA512_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
+ memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
+ SHA512_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+#ifdef HAVE_SHA512
+ ErlNifBinary ctx_bin;
+ SHA512_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
+ SHA512_Final(enif_make_new_binary(env, SHA512_LEN, &ret), &ctx_clone);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+
static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
ErlNifBinary ibin;
@@ -595,6 +939,95 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA224
+ unsigned char hmacbuf[SHA224_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA256
+ unsigned char hmacbuf[SHA256_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA384
+ unsigned char hmacbuf[SHA384_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+
+static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA512
+ unsigned char hmacbuf[SHA512_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key) */
ErlNifBinary key;
@@ -603,6 +1036,18 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
const EVP_MD *md;
if (argv[0] == atom_sha) md = EVP_sha1();
+#ifdef HAVE_SHA224
+ else if (argv[0] == atom_sha224) md = EVP_sha224();
+#endif
+#ifdef HAVE_SHA256
+ else if (argv[0] == atom_sha256) md = EVP_sha256();
+#endif
+#ifdef HAVE_SHA384
+ else if (argv[0] == atom_sha384) md = EVP_sha384();
+#endif
+#ifdef HAVE_SHA512
+ else if (argv[0] == atom_sha512) md = EVP_sha512();
+#endif
else if (argv[0] == atom_md5) md = EVP_md5();
else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
else goto badarg;
@@ -693,6 +1138,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;
@@ -735,6 +1199,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;
@@ -745,8 +1234,7 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 16
|| !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)
- || text.size % 16 != 0) {
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
return enif_make_badarg(env);
}
@@ -999,14 +1487,43 @@ static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin)
}
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigestType,Data,Signature,Key=[P, Q, G, Y]) */
+{/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */
ErlNifBinary data_bin, sign_bin;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ unsigned char* digest;
ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
DSA *dsa;
int i;
+ if (argv[0] == atom_sha) {
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != SHA_DIGEST_LENGTH) {
+
+ return enif_make_badarg(env);
+ }
+ digest = data_bin.data;
+ }
+ else {
+ if (!inspect_mpint(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ digest = hmacbuf;
+ }
+ }
+ else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
+ && data_bin.size == SHA_DIGEST_LENGTH) {
+ digest = data_bin.data;
+ }
+ else {
+ return enif_make_badarg(env);
+ }
+
if (!inspect_mpint(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_p)
@@ -1017,23 +1534,13 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_y)
|| !enif_is_empty_list(env,tail)) {
- badarg:
+
if (dsa_p) BN_free(dsa_p);
if (dsa_q) BN_free(dsa_q);
if (dsa_g) BN_free(dsa_g);
if (dsa_y) BN_free(dsa_y);
return enif_make_badarg(env);
}
- if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- }
- else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
- memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
- }
- else {
- goto badarg;
- }
dsa = DSA_new();
dsa->p = dsa_p;
@@ -1041,51 +1548,173 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
dsa->g = dsa_g;
dsa->priv_key = NULL;
dsa->pub_key = dsa_y;
- i = DSA_verify(0, hmacbuf, SHA_DIGEST_LENGTH,
+ i = DSA_verify(0, digest, SHA_DIGEST_LENGTH,
sign_bin.data+4, sign_bin.size-4, dsa);
DSA_free(dsa);
return(i > 0) ? atom_true : atom_false;
}
-static ERL_NIF_TERM rsa_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data, Signature, Key=[E,N]) */
+
+static void md5_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ MD5(in, in_len, out);
+}
+static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA1(in, in_len, out);
+}
+#ifdef HAVE_SHA224
+static void sha224_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA224(in, in_len, out);
+}
+#endif
+#ifdef HAVE_SHA256
+static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA256(in, in_len, out);
+}
+#endif
+#ifdef HAVE_SHA384
+static void sha384_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA384(in, in_len, out);
+}
+#endif
+#ifdef HAVE_SHA512
+static void sha512_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA512(in, in_len, out);
+}
+#endif
+
+struct digest_type_t {
+ const char* type_str;
+ unsigned len; /* 0 if notsup */
+ int NID_type;
+ void (*funcp)(unsigned char* in, unsigned int in_len, unsigned char* out);
+ ERL_NIF_TERM type_atom;
+};
+
+struct digest_type_t digest_types[] =
+{
+ {"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest},
+ {"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest},
+ {"sha224",
+#ifdef HAVE_SHA224
+ SHA224_LEN, NID_sha224, sha224_digest
+#else
+ 0
+#endif
+ },
+ {"sha256",
+#ifdef HAVE_SHA256
+ SHA256_LEN, NID_sha256, sha256_digest
+#else
+ 0
+#endif
+ },
+ {"sha384",
+#ifdef HAVE_SHA384
+ SHA384_LEN, NID_sha384, sha384_digest
+#else
+ 0
+#endif
+ },
+ {"sha512",
+#ifdef HAVE_SHA512
+ SHA512_LEN, NID_sha512, sha512_digest
+#else
+ 0
+#endif
+ },
+ {NULL}
+};
+
+static void init_digest_types(ErlNifEnv* env)
+{
+ struct digest_type_t* p = digest_types;
+
+ for (p = digest_types; p->type_str; p++) {
+ p->type_atom = enif_make_atom(env, p->type_str);
+ }
+
+}
+
+static struct digest_type_t* get_digest_type(ERL_NIF_TERM type)
+{
+ struct digest_type_t* p = NULL;
+ for (p = digest_types; p->type_str; p++) {
+ if (type == p->type_atom) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Data|{digest,Digest}, Signature, Key=[E,N]) */
ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ unsigned char hmacbuf[SHA512_LEN];
ERL_NIF_TERM head, tail, ret;
- int i, is_sha;
- RSA* rsa = RSA_new();
+ int i;
+ RSA* rsa;
+ const ERL_NIF_TERM type = argv[0];
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
+ struct digest_type_t* digp = NULL;
+ unsigned char* digest = NULL;
+
+ digp = get_digest_type(type);
+ if (!digp) {
+ return enif_make_badarg(env);
+ }
+ if (!digp->len) {
+ return atom_notsup;
+ }
- if (argv[0] == atom_sha) is_sha = 1;
- else if (argv[0] == atom_md5) is_sha = 0;
- else goto badarg;
+ rsa = RSA_new();
- if (!inspect_mpint(env, argv[1], &data_bin)
- || !inspect_mpint(env, argv[2], &sign_bin)
+ if (!inspect_mpint(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_mpint(env, head, &rsa->e)
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &rsa->n)
|| !enif_is_empty_list(env, tail)) {
- badarg:
+
ret = enif_make_badarg(env);
+ goto done;
}
- else {
- if (is_sha) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
- sign_bin.data+4, sign_bin.size-4, rsa);
- }
- else {
- MD5(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_md5, hmacbuf, MD5_DIGEST_LENGTH,
- sign_bin.data+4, sign_bin.size-4, rsa);
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != digp->len) {
+
+ ret = enif_make_badarg(env);
+ goto done;
}
- ret = (i==1 ? atom_true : atom_false);
+ digest = data_bin.data;
}
+ else if (inspect_mpint(env, argv[1], &data_bin)) {
+ digest = hmacbuf;
+ digp->funcp(data_bin.data+4, data_bin.size-4, digest);
+ }
+ else {
+ ret = enif_make_badarg(env);
+ goto done;
+ }
+
+ i = RSA_verify(digp->NID_type, digest, digp->len,
+ sign_bin.data+4, sign_bin.size-4, rsa);
+
+ ret = (i==1 ? atom_true : atom_false);
+
+done:
RSA_free(rsa);
return ret;
}
+
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
@@ -1189,73 +1818,114 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
return enif_make_tuple2(env,new_state,new_data);
}
-static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,IVec,Data,IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
RC2_KEY rc2_key;
ERL_NIF_TERM ret;
-
+ unsigned char iv_copy[8];
+
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || key_bin.size != 5
+ || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
|| !enif_inspect_binary(env, argv[1], &ivec_bin)
|| ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
-
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 8 != 0) {
return enif_make_badarg(env);
}
-
- RC2_set_key(&rc2_key, 5, key_bin.data, 40);
+
+ RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8);
+ memcpy(iv_copy, ivec_bin.data, 8);
RC2_cbc_encrypt(data_bin.data,
- enif_make_new_binary(env, data_bin.size, &ret),
+ enif_make_new_binary(env, data_bin.size, &ret),
data_bin.size, &rc2_key,
- ivec_bin.data,
+ iv_copy,
(argv[3] == atom_true));
-
return ret;
-}
+}
-static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type,Data,Key=[E,N,D]) */
- ErlNifBinary data_bin, ret_bin;
+static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
+{
+ /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
ERL_NIF_TERM head, tail;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- unsigned rsa_s_len;
- RSA *rsa = RSA_new();
- int i, is_sha;
-
- if (argv[0] == atom_sha) is_sha = 1;
- else if (argv[0] == atom_md5) is_sha = 0;
- else goto badarg;
- if (!inspect_mpint(env,argv[1],&data_bin)
- || !enif_get_list_cell(env, argv[2], &head, &tail)
+ if (!enif_get_list_cell(env, key, &head, &tail)
|| !get_bn_from_mpint(env, head, &rsa->e)
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &rsa->n)
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &rsa->d)
- || !enif_is_empty_list(env,tail)) {
- badarg:
- RSA_free(rsa);
+ || (!enif_is_empty_list(env, tail) &&
+ (!enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->q)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->dmp1)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->dmq1)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->iqmp)
+ || !enif_is_empty_list(env, tail)))) {
+ return 0;
+ }
+ return 1;
+}
+
+static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Data|{digest,Digest}, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+ ErlNifBinary data_bin, ret_bin;
+ unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ unsigned rsa_s_len;
+ RSA* rsa;
+ int i;
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
+ struct digest_type_t *digp;
+ unsigned char* digest;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- enif_alloc_binary(RSA_size(rsa), &ret_bin);
- if (is_sha) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(hmacbuf, SHA_DIGEST_LENGTH);
- i = RSA_sign(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
- ret_bin.data, &rsa_s_len, rsa);
+ if (!digp->len) {
+ return atom_notsup;
+ }
+
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != digp->len) {
+
+ return enif_make_badarg(env);
+ }
+ digest = data_bin.data;
}
else {
- MD5(data_bin.data+4, data_bin.size-4, hmacbuf);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(hmacbuf, MD5_DIGEST_LENGTH);
- i = RSA_sign(NID_md5, hmacbuf,MD5_DIGEST_LENGTH,
- ret_bin.data, &rsa_s_len, rsa);
+ if (!inspect_mpint(env,argv[1],&data_bin)) {
+ return enif_make_badarg(env);
+ }
+ digest = hmacbuf;
+ digp->funcp(data_bin.data+4, data_bin.size-4, digest);
}
+
+ rsa = RSA_new();
+ if (!get_rsa_private_key(env, argv[2], rsa)) {
+ RSA_free(rsa);
+ return enif_make_badarg(env);
+ }
+
+
+ enif_alloc_binary(RSA_size(rsa), &ret_bin);
+
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(digest, digp->len);
+ i = RSA_sign(digp->NID_type, digest, digp->len,
+ ret_bin.data, &rsa_s_len, rsa);
+
RSA_free(rsa);
if (i) {
ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
- if (rsa_s_len != data_bin.size) {
+ if (rsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, rsa_s_len);
ERL_VALGRIND_ASSERT_MEM_DEFINED(ret_bin.data, rsa_s_len);
}
@@ -1267,15 +1937,49 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
}
+
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigesType, Data, Key=[P,Q,G,PrivKey]) */
+{/* (DigesType|none, Data|{digest,Digest}, Key=[P,Q,G,PrivKey]) */
ErlNifBinary data_bin, ret_bin;
ERL_NIF_TERM head, tail;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned int dsa_s_len;
- DSA* dsa = DSA_new();
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
+ unsigned char* digest = NULL;
+ DSA* dsa;
int i;
+ if (argv[0] == atom_sha) {
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != SHA_DIGEST_LENGTH) {
+
+ return enif_make_badarg(env);
+ }
+ digest = data_bin.data;
+ }
+ else {
+ if (!inspect_mpint(env,argv[1],&data_bin)) {
+ return enif_make_badarg(env);
+ }
+ SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ digest = hmacbuf;
+ }
+ }
+ else if (argv[0] == atom_none
+ && enif_inspect_binary(env,argv[1],&data_bin)
+ && data_bin.size == SHA_DIGEST_LENGTH) {
+
+ digest = data_bin.data;
+ }
+ else {
+ return enif_make_badarg(env);
+ }
+
+ dsa = DSA_new();
+
dsa->pub_key = NULL;
if (!enif_get_list_cell(env, argv[2], &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa->p)
@@ -1286,23 +1990,12 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa->priv_key)
|| !enif_is_empty_list(env,tail)) {
- goto badarg;
- }
- if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- }
- else if (argv[0] == atom_none && enif_inspect_binary(env,argv[1],&data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
- memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
- }
- else {
- badarg:
DSA_free(dsa);
return enif_make_badarg(env);
}
enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
+ i = DSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH,
ret_bin.data, &dsa_s_len, dsa);
DSA_free(dsa);
if (i) {
@@ -1316,6 +2009,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
}
+
static int rsa_pad(ERL_NIF_TERM term, int* padding)
{
if (term == atom_rsa_pkcs1_padding) {
@@ -1381,20 +2075,13 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
}
static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data, PublKey=[E,N,D], Padding, IsEncrypt) */
+{/* (Data, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Padding, IsEncrypt) */
ErlNifBinary data_bin, ret_bin;
- ERL_NIF_TERM head, tail;
int padding, i;
RSA* rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
- || !enif_get_list_cell(env, argv[1], &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->e)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->n)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->d)
- || !enif_is_empty_list(env,tail)
+ || !get_rsa_private_key(env, argv[1], rsa)
|| !rsa_pad(argv[2], &padding)) {
RSA_free(rsa);
@@ -1784,3 +2471,166 @@ static void hmac_sha1(unsigned char *key, int klen,
SHA1_Final((unsigned char *) hmacbuf, &ctx);
}
+#ifdef HAVE_SHA224
+static void hmac_sha224(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA256_CTX ctx;
+ char ipad[HMAC_INT_LEN];
+ char opad[HMAC_INT_LEN];
+ unsigned char nkey[SHA224_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT_LEN) {
+ SHA224(key, klen, nkey);
+ key = nkey;
+ klen = SHA224_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA224_Init(&ctx);
+ SHA224_Update(&ctx, ipad, HMAC_INT_LEN);
+ SHA224_Update(&ctx, dbuf, dlen);
+ SHA224_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA224_Init(&ctx);
+ SHA224_Update(&ctx, opad, HMAC_INT_LEN);
+ SHA224_Update(&ctx, hmacbuf, SHA224_DIGEST_LENGTH);
+ SHA224_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
+
+#ifdef HAVE_SHA256
+static void hmac_sha256(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA256_CTX ctx;
+ char ipad[HMAC_INT_LEN];
+ char opad[HMAC_INT_LEN];
+ unsigned char nkey[SHA256_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT_LEN) {
+ SHA256(key, klen, nkey);
+ key = nkey;
+ klen = SHA256_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, ipad, HMAC_INT_LEN);
+ SHA256_Update(&ctx, dbuf, dlen);
+ SHA256_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, opad, HMAC_INT_LEN);
+ SHA256_Update(&ctx, hmacbuf, SHA256_DIGEST_LENGTH);
+ SHA256_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
+
+#ifdef HAVE_SHA384
+static void hmac_sha384(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA512_CTX ctx;
+ char ipad[HMAC_INT2_LEN];
+ char opad[HMAC_INT2_LEN];
+ unsigned char nkey[SHA384_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT2_LEN) {
+ SHA384(key, klen, nkey);
+ key = nkey;
+ klen = SHA384_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT2_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA384_Init(&ctx);
+ SHA384_Update(&ctx, ipad, HMAC_INT2_LEN);
+ SHA384_Update(&ctx, dbuf, dlen);
+ SHA384_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA384_Init(&ctx);
+ SHA384_Update(&ctx, opad, HMAC_INT2_LEN);
+ SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH);
+ SHA384_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
+
+#ifdef HAVE_SHA512
+static void hmac_sha512(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA512_CTX ctx;
+ char ipad[HMAC_INT2_LEN];
+ char opad[HMAC_INT2_LEN];
+ unsigned char nkey[SHA512_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT2_LEN) {
+ SHA512(key, klen, nkey);
+ key = nkey;
+ klen = SHA512_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT2_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, ipad, HMAC_INT2_LEN);
+ SHA512_Update(&ctx, dbuf, dlen);
+ SHA512_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, opad, HMAC_INT2_LEN);
+ SHA512_Update(&ctx, hmacbuf, SHA512_DIGEST_LENGTH);
+ SHA512_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index 03aaba939b..00ae70fb4a 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -100,16 +100,16 @@ clean clean_docs clean_tex:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6DIR)/* $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 4c20f81cae..045ad4c050 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -256,6 +256,57 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>hash(Type, Data) -> Digest</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512</v>
+ <v>Data = iodata()</v>
+ <v>Digest = binary()</v>
+ </type>
+ <desc>
+ <p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hash_init(Type) -> Context</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512</v>
+ </type>
+ <desc>
+ <p>Initializes the context for streaming hash operations. <c>Type</c> determines
+ which digest to use. The returned context should be used as argument
+ to <seealso marker="#hash_update/2">hash_update</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hash_update(Context, Data) -> NewContext</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Data = iodata()</v>
+ </type>
+ <desc>
+ <p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
+ must have been generated using <seealso marker="#hash_init/1">hash_init</seealso>
+ or a previous call to this function. <c>Data</c> can be any length. <c>NewContext</c>
+ must be passed into the next call to <c>hash_update</c>
+ or <seealso marker="#hash_final/1">hash_final</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hash_final(Context) -> Digest</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Digest = binary()</v>
+ </type>
+ <desc>
+ <p>Finalizes the hash operation referenced by <c>Context</c> returned
+ from a previous call to <seealso marker="#hash_update/2">hash_update</seealso>.
+ The size of <c>Digest</c> is determined by the type of hash
+ function used to generate it.</p>
+ </desc>
+ </func>
+ <func>
<name>md5_mac(Key, Data) -> Mac</name>
<fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
<type>
@@ -334,14 +385,16 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>sha_mac(Key, Data) -> Mac</name>
+ <name>sha_mac(Key, Data, MacLength) -> Mac</name>
<fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
<type>
<v>Key = Data = iolist() | binary()</v>
<v>Mac = binary()</v>
+ <v>MacLenength = integer() =&lt; 20 </v>
</type>
<desc>
<p>Computes an <c>SHA MAC</c> message authentification code
- from <c>Key</c> and <c>Data</c>, where the length of the Mac
+ from <c>Key</c> and <c>Data</c>, where the default length of the Mac
is 160 bits (20 bytes).</p>
</desc>
</func>
@@ -404,6 +457,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>
@@ -421,7 +519,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>
@@ -437,6 +535,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>
@@ -564,16 +694,14 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<func>
<name>aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher</name>
- <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name>
- <fsummary>Encrypt <c>Text</c>according to AES in Cipher Feedback mode or Cipher Block Chaining mode</fsummary>
+ <fsummary>Encrypt <c>Text</c>according to AES in Cipher Feedback mode</fsummary>
<type>
<v>Key = Text = iolist() | binary()</v>
<v>IVec = Cipher = binary()</v>
</type>
<desc>
<p>Encrypts <c>Text</c> according to AES in Cipher Feedback
- mode (CFB) or Cipher Block Chaining mode (CBC). <c>Text</c>
- must be a multiple of 128 bits (16 bytes). <c>Key</c> is the
+ mode (CFB). <c>Key</c> is the
AES key, and <c>IVec</c> is an arbitrary initializing vector.
The lengths of <c>Key</c> and <c>IVec</c> must be 128 bits
(16 bytes).</p>
@@ -581,15 +709,45 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>aes_cfb_128_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Feedback mode</fsummary>
+ <type>
+ <v>Key = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to AES in Cipher Feedback Mode (CFB).
+ <c>Key</c> is the AES 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 128 bits (16 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to AES in Cipher Block Chaining mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to AES in Cipher Block Chaining
+ mode (CBC). <c>Text</c>
+ must be a multiple of 128 bits (16 bytes). <c>Key</c> is the
+ AES key, and <c>IVec</c> is an arbitrary initializing vector.
+ The lengths of <c>Key</c> and <c>IVec</c> must be 128 bits
+ (16 bytes).</p>
+ </desc>
+ </func>
+ <func>
<name>aes_cbc_128_decrypt(Key, IVec, Cipher) -> Text</name>
- <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Feedback mode or Cipher Block Chaining mode</fsummary>
+ <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Block Chaining mode</fsummary>
<type>
<v>Key = Cipher = iolist() | binary()</v>
<v>IVec = Text = binary()</v>
</type>
<desc>
- <p>Decrypts <c>Cipher</c> according to Cipher Feedback Mode (CFB)
- or Cipher Block Chaining mode (CBC).
+ <p>Decrypts <c>Cipher</c> according to AES in Cipher Block
+ Chaining mode (CBC).
<c>Key</c> is the AES 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. <c>Cipher</c>
@@ -786,46 +944,58 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
- <name>rsa_sign(Data, Key) -> Signature</name>
- <name>rsa_sign(DigestType, Data, Key) -> Signature</name>
+ <name>rsa_sign(DataOrDigest, Key) -> Signature</name>
+ <name>rsa_sign(DigestType, DataOrDigest, Key) -> Signature</name>
<fsummary>Sign the data using rsa with the given key.</fsummary>
<type>
+ <v>DataOrDigest = Data | {digest,Digest}</v>
<v>Data = Mpint</v>
- <v>Key = [E, N, D]</v>
+ <v>Digest = binary()</v>
+ <v>Key = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</v>
<v>E, N, D = Mpint</v>
<d>Where <c>E</c> is the public exponent, <c>N</c> is public modulus and
<c>D</c> is the private exponent.</d>
- <v>DigestType = md5 | sha</v>
+ <v>P1, P2, E1, E2, C = Mpint</v>
+ <d>The longer key format contains redundant information that will make
+ the calculation faster. <c>P1,P2</c> are first and second prime factors.
+ <c>E1,E2</c> are first and second exponents. <c>C</c> is the CRT coefficient.
+ Terminology is taken from RFC 3447.</d>
+ <v>DigestType = md5 | sha | sha224 | sha256 | sha384 | sha512</v>
<d>The default <c>DigestType</c> is sha.</d>
<v>Mpint = binary()</v>
<v>Signature = binary()</v>
</type>
<desc>
- <p>Calculates a <c>DigestType</c> digest of the <c>Data</c>
- and creates a RSA signature with the private key <c>Key</c>
- of the digest.</p>
+ <p>Creates a RSA signature with the private key <c>Key</c>
+ of a digest. The digest is either calculated as a
+ <c>DigestType</c> digest of <c>Data</c> or a precalculated
+ binary <c>Digest</c>.</p>
</desc>
</func>
<func>
- <name>rsa_verify(Data, Signature, Key) -> Verified</name>
- <name>rsa_verify(DigestType, Data, Signature, Key) -> Verified </name>
+ <name>rsa_verify(DataOrDigest, Signature, Key) -> Verified</name>
+ <name>rsa_verify(DigestType, DataOrDigest, Signature, Key) -> Verified </name>
<fsummary>Verify the digest and signature using rsa with given public key.</fsummary>
<type>
<v>Verified = boolean()</v>
+ <v>DataOrDigest = Data | {digest|Digest}</v>
<v>Data, Signature = Mpint</v>
+ <v>Digest = binary()</v>
<v>Key = [E, N]</v>
<v>E, N = Mpint</v>
<d>Where <c>E</c> is the public exponent and <c>N</c> is public modulus.</d>
- <v>DigestType = md5 | sha</v>
- <d> The default <c>DigestType</c> is sha.</d>
+ <v>DigestType = md5 | sha | sha224 | sha256 | sha384 | sha512</v>
+ <d>The default <c>DigestType</c> is sha.</d>
<v>Mpint = binary()</v>
</type>
<desc>
- <p>Calculates a <c>DigestType</c> digest of the <c>Data</c>
- and verifies that the digest matches the RSA signature using the
+ <p>Verifies that a digest matches the RSA signature using the
signer's public key <c>Key</c>.
- </p>
+ The digest is either calculated as a <c>DigestType</c>
+ digest of <c>Data</c> or a precalculated binary <c>Digest</c>.</p>
+ <p>May throw exception <c>notsup</c> in case the chosen <c>DigestType</c>
+ is not supported by the underlying OpenSSL implementation.</p>
</desc>
</func>
@@ -862,10 +1032,15 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<fsummary>Decrypts ChipherText using the private Key.</fsummary>
<type>
<v>ChipherText = binary()</v>
- <v>PrivateKey = [E, N, D]</v>
+ <v>PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</v>
<v>E, N, D = Mpint</v>
<d>Where <c>E</c> is the public exponent, <c>N</c> is public modulus and
<c>D</c> is the private exponent.</d>
+ <v>P1, P2, E1, E2, C = Mpint</v>
+ <d>The longer key format contains redundant information that will make
+ the calculation faster. <c>P1,P2</c> are first and second prime factors.
+ <c>E1,E2</c> are first and second exponents. <c>C</c> is the CRT coefficient.
+ Terminology is taken from RFC 3447.</d>
<v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
<v>PlainText = binary()</v>
</type>
@@ -884,10 +1059,15 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<fsummary>Encrypts Msg using the private Key.</fsummary>
<type>
<v>PlainText = binary()</v>
- <v>PrivateKey = [E, N, D]</v>
- <v>E, N, D = Mpint</v>
+ <v>PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</v>
+ <v>E, N, D = Mpint</v>
<d>Where <c>E</c> is the public exponent, <c>N</c> is public modulus and
<c>D</c> is the private exponent.</d>
+ <v>P1, P2, E1, E2, C = Mpint</v>
+ <d>The longer key format contains redundant information that will make
+ the calculation faster. <c>P1,P2</c> are first and second prime factors.
+ <c>E1,E2</c> are first and second exponents. <c>C</c> is the CRT coefficient.
+ Terminology is taken from RFC 3447.</d>
<v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
<v>ChipherText = binary()</v>
</type>
@@ -926,49 +1106,80 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
- <name>dss_sign(Data, Key) -> Signature</name>
- <name>dss_sign(DigestType, Data, Key) -> Signature</name>
+ <name>dss_sign(DataOrDigest, Key) -> Signature</name>
+ <name>dss_sign(DigestType, DataOrDigest, Key) -> Signature</name>
<fsummary>Sign the data using dsa with given private key.</fsummary>
<type>
- <v>DigestType = sha | none (default is sha)</v>
- <v>Data = Mpint | ShaDigest</v>
+ <v>DigestType = sha</v>
+ <v>DataOrDigest = Mpint | {digest,Digest}</v>
<v>Key = [P, Q, G, X]</v>
<v>P, Q, G, X = Mpint</v>
<d> Where <c>P</c>, <c>Q</c> and <c>G</c> are the dss
parameters and <c>X</c> is the private key.</d>
- <v>ShaDigest = binary() with length 20 bytes</v>
+ <v>Digest = binary() with length 20 bytes</v>
<v>Signature = binary()</v>
</type>
<desc>
- <p>Creates a DSS signature with the private key <c>Key</c> of a digest.
- If <c>DigestType</c> is 'sha', the digest is calculated as SHA1 of <c>Data</c>.
- If <c>DigestType</c> is 'none', <c>Data</c> is the precalculated SHA1 digest.</p>
+ <p>Creates a DSS signature with the private key <c>Key</c> of
+ a digest. The digest is either calculated as a SHA1
+ digest of <c>Data</c> or a precalculated binary <c>Digest</c>.</p>
+ <p>A deprecated feature is having <c>DigestType = 'none'</c>
+ in which case <c>DataOrDigest</c> is a precalculated SHA1
+ digest.</p>
</desc>
</func>
<func>
- <name>dss_verify(Data, Signature, Key) -> Verified</name>
- <name>dss_verify(DigestType, Data, Signature, Key) -> Verified</name>
+ <name>dss_verify(DataOrDigest, Signature, Key) -> Verified</name>
+ <name>dss_verify(DigestType, DataOrDigest, Signature, Key) -> Verified</name>
<fsummary>Verify the data and signature using dsa with given public key.</fsummary>
<type>
<v>Verified = boolean()</v>
- <v>DigestType = sha | none</v>
+ <v>DigestType = sha</v>
+ <v>DataOrDigest = Mpint | {digest,Digest}</v>
<v>Data = Mpint | ShaDigest</v>
<v>Signature = Mpint</v>
<v>Key = [P, Q, G, Y]</v>
<v>P, Q, G, Y = Mpint</v>
<d> Where <c>P</c>, <c>Q</c> and <c>G</c> are the dss
parameters and <c>Y</c> is the public key.</d>
- <v>ShaDigest = binary() with length 20 bytes</v>
+ <v>Digest = binary() with length 20 bytes</v>
</type>
<desc>
- <p>Verifies that a digest matches the DSS signature using the public key <c>Key</c>.
- If <c>DigestType</c> is 'sha', the digest is calculated as SHA1 of <c>Data</c>.
- If <c>DigestType</c> is 'none', <c>Data</c> is the precalculated SHA1 digest.</p>
+ <p>Verifies that a digest matches the DSS signature using the
+ public key <c>Key</c>. The digest is either calculated as a SHA1
+ digest of <c>Data</c> or is a precalculated binary <c>Digest</c>.</p>
+ <p>A deprecated feature is having <c>DigestType = 'none'</c>
+ in which case <c>DataOrDigest</c> is a precalculated SHA1
+ digest binary.</p>
</desc>
</func>
<func>
+ <name>rc2_cbc_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to RC2 in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>Ivec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to RC2 in CBC mode.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rc2_cbc_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypts <c>Cipher</c>according to RC2 in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>Ivec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to RC2 in CBC mode.</p>
+ </desc>
+ </func>
+
+ <func>
<name>rc4_encrypt(Key, Data) -> Result</name>
<fsummary>Encrypt data using RC4</fsummary>
<type>
diff --git a/lib/crypto/doc/src/make.dep b/lib/crypto/doc/src/make.dep
deleted file mode 100644
index 73b090bbb6..0000000000
--- a/lib/crypto/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex crypto.tex crypto_app.tex licenses.tex \
- ref_man.tex usersguide.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 763f79e02d..3a44550ae2 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -30,6 +30,44 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ public_key, ssl and crypto now supports PKCS-8</p>
+ <p>
+ Own Id: OTP-9312</p>
+ </item>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p>
+ Add DES and Triple DES cipher feedback (CFB) mode
+ functions to <c>crypto</c>. (Thanks to Paul Guyot)</p>
+ <p>
+ Own Id: OTP-9640</p>
+ </item>
+ <item>
+ <p>
+ Add sha256, sha384 and sha512 support for
+ <c>crypto:rsa_verify</c>.</p>
+ <p>
+ Own Id: OTP-9778</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 2.0.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile
index 0e886ce8bf..ddafb9168f 100644
--- a/lib/crypto/src/Makefile
+++ b/lib/crypto/src/Makefile
@@ -83,11 +83,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) \
- $(APPUP_TARGET) $(RELSYSDIR)/ebin
+ $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index c3e13d6b91..0089e79a4f 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,16 +22,25 @@
-module(crypto).
-export([start/0, stop/0, info/0, info_lib/0, version/0]).
+-export([hash/2, hash_init/1, hash_update/2, hash_final/1]).
-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
-export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
-%-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([sha224/1, sha224_init/0, sha224_update/2, sha224_final/1]).
+-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
+-export([sha384/1, sha384_init/0, sha384_update/2, sha384_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/3, sha_mac_96/2]).
+-export([sha224_mac/2, sha224_mac/3]).
+-export([sha256_mac/2, sha256_mac/3]).
+-export([sha384_mac/2, sha384_mac/3]).
+-export([sha512_mac/2, sha512_mac/3]).
-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]).
@@ -40,7 +49,7 @@
-export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]).
-export([exor/2]).
-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
--export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
+-export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
-export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]).
-export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]).
-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
@@ -62,14 +71,19 @@
-define(FUNC_LIST, [md4, md4_init, md4_update, md4_final,
md5, md5_init, md5_update, md5_final,
sha, sha_init, sha_update, sha_final,
-%% sha256, sha256_init, sha256_update, sha256_final,
-%% sha512, sha512_init, sha512_update, sha512_final,
+ sha224, sha224_init, sha224_update, sha224_final,
+ sha256, sha256_init, sha256_update, sha256_final,
+ sha384, sha384_init, sha384_update, sha384_final,
+ sha512, sha512_init, sha512_update, sha512_final,
md5_mac, md5_mac_96,
sha_mac, sha_mac_96,
+ sha224_mac, sha256_mac, sha384_mac, sha512_mac,
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,
@@ -79,7 +93,7 @@
dss_verify,dss_sign,
rsa_verify,rsa_sign,
rsa_public_encrypt,rsa_private_decrypt,
- rsa_private_encrypt,rsa_public_decrypt,
+ rsa_private_encrypt,rsa_public_decrypt,
dh_generate_key, dh_compute_key,
aes_cbc_128_encrypt, aes_cbc_128_decrypt,
exor,
@@ -87,12 +101,13 @@
rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
%% idea_cbc_encrypt, idea_cbc_decrypt,
aes_cbc_256_encrypt, aes_cbc_256_decrypt,
- aes_ctr_encrypt, aes_ctr_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'.
+-type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
-type dss_digest_type() :: 'none' | 'sha'.
+-type data_or_digest() :: binary() | {digest, binary()}.
-type crypto_integer() :: binary() | integer().
-define(nif_stub,nif_stub_error(?LINE)).
@@ -167,7 +182,7 @@ info_lib() -> ?nif_stub.
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
version() -> ?CRYPTO_VSN.
-
+
%% Below Key and Data are binaries or IO-lists. IVec is a binary.
%% Output is always a binary. Context is a binary.
@@ -175,6 +190,45 @@ version() -> ?CRYPTO_VSN.
%% MESSAGE DIGESTS
%%
+-spec hash(_, iodata()) -> binary().
+hash(md5, Data) -> md5(Data);
+hash(md4, Data) -> md4(Data);
+hash(sha, Data) -> sha(Data);
+hash(sha224, Data) -> sha224(Data);
+hash(sha256, Data) -> sha256(Data);
+hash(sha384, Data) -> sha384(Data);
+hash(sha512, Data) -> sha512(Data).
+
+-spec hash_init('md5'|'md4'|'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
+
+hash_init(md5) -> {md5, md5_init()};
+hash_init(md4) -> {md4, md4_init()};
+hash_init(sha) -> {sha, sha_init()};
+hash_init(sha224) -> {sha224, sha224_init()};
+hash_init(sha256) -> {sha256, sha256_init()};
+hash_init(sha384) -> {sha384, sha384_init()};
+hash_init(sha512) -> {sha512, sha512_init()}.
+
+-spec hash_update(_, iodata()) -> any().
+
+hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
+hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
+hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
+hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
+hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
+hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
+hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+
+-spec hash_final(_) -> binary().
+
+hash_final({md5,Context}) -> md5_final(Context);
+hash_final({md4,Context}) -> md4_final(Context);
+hash_final({sha,Context}) -> sha_final(Context);
+hash_final({sha224,Context}) -> sha224_final(Context);
+hash_final({sha256,Context}) -> sha256_final(Context);
+hash_final({sha384,Context}) -> sha384_final(Context);
+hash_final({sha512,Context}) -> sha512_final(Context).
+
%%
%% MD5
%%
@@ -215,6 +269,141 @@ sha_init() -> ?nif_stub.
sha_update(_Context, _Data) -> ?nif_stub.
sha_final(_Context) -> ?nif_stub.
+%
+%% SHA224
+%%
+-spec sha224(iodata()) -> binary().
+-spec sha224_init() -> binary().
+-spec sha224_update(binary(), iodata()) -> binary().
+-spec sha224_final(binary()) -> binary().
+
+sha224(Data) ->
+ case sha224_nif(Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha224_init() ->
+ case sha224_init_nif() of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha224_update(Context, Data) ->
+ case sha224_update_nif(Context, Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha224_final(Context) ->
+ case sha224_final_nif(Context) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha224_nif(_Data) -> ?nif_stub.
+sha224_init_nif() -> ?nif_stub.
+sha224_update_nif(_Context, _Data) -> ?nif_stub.
+sha224_final_nif(_Context) -> ?nif_stub.
+
+%
+%% SHA256
+%%
+-spec sha256(iodata()) -> binary().
+-spec sha256_init() -> binary().
+-spec sha256_update(binary(), iodata()) -> binary().
+-spec sha256_final(binary()) -> binary().
+
+sha256(Data) ->
+ case sha256_nif(Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha256_init() ->
+ case sha256_init_nif() of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha256_update(Context, Data) ->
+ case sha256_update_nif(Context, Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha256_final(Context) ->
+ case sha256_final_nif(Context) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha256_nif(_Data) -> ?nif_stub.
+sha256_init_nif() -> ?nif_stub.
+sha256_update_nif(_Context, _Data) -> ?nif_stub.
+sha256_final_nif(_Context) -> ?nif_stub.
+
+%
+%% SHA384
+%%
+-spec sha384(iodata()) -> binary().
+-spec sha384_init() -> binary().
+-spec sha384_update(binary(), iodata()) -> binary().
+-spec sha384_final(binary()) -> binary().
+
+sha384(Data) ->
+ case sha384_nif(Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha384_init() ->
+ case sha384_init_nif() of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha384_update(Context, Data) ->
+ case sha384_update_nif(Context, Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha384_final(Context) ->
+ case sha384_final_nif(Context) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha384_nif(_Data) -> ?nif_stub.
+sha384_init_nif() -> ?nif_stub.
+sha384_update_nif(_Context, _Data) -> ?nif_stub.
+sha384_final_nif(_Context) -> ?nif_stub.
+
+%
+%% SHA512
+%%
+-spec sha512(iodata()) -> binary().
+-spec sha512_init() -> binary().
+-spec sha512_update(binary(), iodata()) -> binary().
+-spec sha512_final(binary()) -> binary().
+
+sha512(Data) ->
+ case sha512_nif(Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha512_init() ->
+ case sha512_init_nif() of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha512_update(Context, Data) ->
+ case sha512_update_nif(Context, Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha512_final(Context) ->
+ case sha512_final_nif(Context) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha512_nif(_Data) -> ?nif_stub.
+sha512_init_nif() -> ?nif_stub.
+sha512_update_nif(_Context, _Data) -> ?nif_stub.
+sha512_final_nif(_Context) -> ?nif_stub.
%%
%% MESSAGE AUTHENTICATION CODES
@@ -256,12 +445,79 @@ md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
sha_mac(Key, Data) ->
sha_mac_n(Key,Data,20).
+sha_mac(Key, Data, Size) ->
+ sha_mac_n(Key, Data, Size).
+
sha_mac_96(Key, Data) ->
sha_mac_n(Key,Data,12).
sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
%%
+%% SHA224_MAC
+%%
+-spec sha224_mac(iodata(), iodata()) -> binary().
+
+sha224_mac(Key, Data) ->
+ sha224_mac(Key, Data, 224 div 8).
+
+sha224_mac(Key, Data, Size) ->
+ case sha224_mac_nif(Key, Data, Size) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha224_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
+%%
+%% SHA256_MAC
+%%
+-spec sha256_mac(iodata(), iodata()) -> binary().
+
+sha256_mac(Key, Data) ->
+ sha256_mac(Key, Data, 256 div 8).
+
+sha256_mac(Key, Data, Size) ->
+ case sha256_mac_nif(Key, Data, Size) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
+%%
+%% SHA384_MAC
+%%
+-spec sha384_mac(iodata(), iodata()) -> binary().
+
+sha384_mac(Key, Data) ->
+ sha384_mac(Key, Data, 384 div 8).
+
+sha384_mac(Key, Data, Size) ->
+ case sha384_mac_nif(Key, Data, Size) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha384_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
+%%
+%% SHA512_MAC
+%%
+-spec sha512_mac(iodata(), iodata()) -> binary().
+
+sha512_mac(Key, Data) ->
+ sha512_mac(Key, Data, 512 div 8).
+
+sha512_mac(Key, Data, MacSz) ->
+ case sha512_mac_nif(Key, Data, MacSz) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
+%%
%% CRYPTO FUNCTIONS
%%
@@ -294,6 +550,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().
@@ -326,6 +609,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().
@@ -455,10 +758,10 @@ mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub.
%%
%% DSS, RSA - verify
%%
--spec dss_verify(binary(), binary(), [binary()]) -> boolean().
--spec dss_verify(dss_digest_type(), binary(), binary(), [binary()]) -> boolean().
--spec rsa_verify(binary(), binary(), [binary()]) -> boolean().
--spec rsa_verify(rsa_digest_type(), binary(), binary(), [binary()]) ->
+-spec dss_verify(data_or_digest(), binary(), [binary()]) -> boolean().
+-spec dss_verify(dss_digest_type(), data_or_digest(), binary(), [binary()]) -> boolean().
+-spec rsa_verify(data_or_digest(), binary(), [binary()]) -> boolean().
+-spec rsa_verify(rsa_digest_type(), data_or_digest(), binary(), [binary()]) ->
boolean().
%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
@@ -468,35 +771,41 @@ dss_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub.
% Key = [E,N] E=PublicExponent N=PublicModulus
rsa_verify(Data,Signature,Key) ->
- rsa_verify(sha, Data,Signature,Key).
-rsa_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub.
+ rsa_verify_nif(sha, Data,Signature,Key).
+rsa_verify(Type, DataOrDigest, Signature, Key) ->
+ case rsa_verify_nif(Type, DataOrDigest, Signature, Key) of
+ notsup -> erlang:error(notsup);
+ Bool -> Bool
+ end.
+
+rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
%%
%% DSS, RSA - sign
%%
%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
--spec dss_sign(binary(), [binary()]) -> binary().
--spec dss_sign(dss_digest_type(), binary(), [binary()]) -> binary().
--spec rsa_sign(binary(), [binary()]) -> binary().
--spec rsa_sign(rsa_digest_type(), binary(), [binary()]) -> binary().
-
-dss_sign(Data,Key) ->
- dss_sign(sha,Data,Key).
-dss_sign(Type, Data, Key) ->
- case dss_sign_nif(Type,Data,Key) of
- error -> erlang:error(badkey, [Data, Key]);
+-spec dss_sign(data_or_digest(), [binary()]) -> binary().
+-spec dss_sign(dss_digest_type(), data_or_digest(), [binary()]) -> binary().
+-spec rsa_sign(data_or_digest(), [binary()]) -> binary().
+-spec rsa_sign(rsa_digest_type(), data_or_digest(), [binary()]) -> binary().
+
+dss_sign(DataOrDigest,Key) ->
+ dss_sign(sha,DataOrDigest,Key).
+dss_sign(Type, DataOrDigest, Key) ->
+ case dss_sign_nif(Type,DataOrDigest,Key) of
+ error -> erlang:error(badkey, [DataOrDigest, Key]);
Sign -> Sign
end.
dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
-rsa_sign(Data,Key) ->
- rsa_sign(sha, Data, Key).
-rsa_sign(Type, Data, Key) ->
- case rsa_sign_nif(Type,Data,Key) of
- error -> erlang:error(badkey, [Type,Data,Key]);
+rsa_sign(DataOrDigest,Key) ->
+ rsa_sign(sha, DataOrDigest, Key).
+rsa_sign(Type, DataOrDigest, Key) ->
+ case rsa_sign_nif(Type,DataOrDigest,Key) of
+ error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
Sign -> Sign
end.
@@ -638,16 +947,25 @@ rc4_encrypt(_Key, _Data) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+
+%% RC2 block cipher
+
+rc2_cbc_encrypt(Key, IVec, Data) ->
+ rc2_cbc_crypt(Key,IVec,Data,true).
+
+rc2_cbc_decrypt(Key, IVec, Data) ->
+ rc2_cbc_crypt(Key,IVec,Data,false).
+
+rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
%%
-%% RC2 - 40 bits block cipher
+%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
%%
-rc2_40_cbc_encrypt(Key, IVec, Data) ->
- rc2_40_cbc_crypt(Key,IVec,Data,true).
-
-rc2_40_cbc_decrypt(Key, IVec, Data) ->
- rc2_40_cbc_crypt(Key,IVec,Data,false).
+rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
+ rc2_cbc_crypt(Key,IVec,Data,true).
-rc2_40_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
+ rc2_cbc_crypt(Key,IVec,Data,false).
%%
%% DH Diffie-Hellman functions
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index 3150bd472d..ec8136b455 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -75,9 +75,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: $(TEST_TARGET)
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) crypto.spec crypto.cover $(RELTEST_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) crypto.spec crypto.cover $(RELTEST_FILES) "$(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 486751766b..1b5bc44dde 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,12 @@
sha_update/1,
hmac_update_sha/1,
hmac_update_sha_n/1,
+ hmac_update_sha256/1,
+ hmac_update_sha512/1,
hmac_update_md5/1,
hmac_update_md5_io/1,
hmac_update_md5_n/1,
+ hmac_rfc4231/1,
sha256/1,
sha256_update/1,
sha512/1,
@@ -44,7 +47,12 @@
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,
+ rc2_cbc/1,
aes_cfb/1,
aes_cbc/1,
aes_cbc_iter/1,
@@ -56,35 +64,40 @@
rsa_verify_test/1,
dsa_verify_test/1,
rsa_sign_test/1,
+ rsa_sign_hash_test/1,
dsa_sign_test/1,
+ dsa_sign_hash_test/1,
rsa_encrypt_decrypt/1,
dh/1,
exor_test/1,
rc4_test/1,
rc4_stream_test/1,
blowfish_cfb64/1,
- smp/1,
- cleanup/1]).
+ smp/1]).
-export([hexstr2bin/1]).
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, aes_ctr_stream, des_cbc_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,
- smp].
-
-groups() ->
- [].
+ [link_test, {group, info}].
+
+groups() ->
+ [{info, [sequence],[info, {group, rest}]},
+ {rest, [],
+ [md5, md5_update, md4, md4_update, md5_mac,
+ md5_mac_io, sha, sha_update,
+ hmac_update_sha, hmac_update_sha_n, hmac_update_sha256, hmac_update_sha512,
+ hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
+ hmac_rfc4231,
+ des_cbc, aes_cfb, aes_cbc,
+ aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
+ rand_uniform_test, strong_rand_test,
+ rsa_verify_test, dsa_verify_test, rsa_sign_test,
+ rsa_sign_hash_test, dsa_sign_test, dsa_sign_hash_test,
+ rsa_encrypt_decrypt, dh, exor_test,
+ rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64,
+ smp]}].
init_per_suite(Config) ->
Config.
@@ -98,11 +111,15 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(info, Config) ->
+ Config;
init_per_testcase(_Name,Config) ->
io:format("init_per_testcase\n"),
?line crypto:start(),
Config.
+end_per_testcase(info, Config) ->
+ Config;
end_per_testcase(_Name,Config) ->
io:format("end_per_testcase\n"),
?line crypto:stop(),
@@ -190,13 +207,6 @@ info(Config) when is_list(Config) ->
?line crypto:stop()
end.
-cleanup(doc) ->
- ["Cleanup (dummy)."];
-cleanup(suite) ->
- [];
-cleanup(Config) when is_list(Config) ->
- Config.
-
%%
%%
md5(doc) ->
@@ -292,7 +302,7 @@ sha(Config) when is_list(Config) ->
hexstr2bin("84983E441C3BD26EBAAE4AA1F95129E5E54670F1")).
-%%
+%%
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." ];
@@ -332,6 +342,44 @@ hmac_update_sha(Config) when is_list(Config) ->
?line Mac = crypto:hmac_final(Ctx3),
?line Exp = crypto:sha_mac(Key, lists:flatten([Data, Data2])),
?line m(Exp, Mac).
+
+hmac_update_sha256(doc) ->
+ ["Generate an SHA256 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:sha256_mac." ];
+hmac_update_sha256(suite) ->
+ [];
+hmac_update_sha256(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f"),
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(sha256, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final(Ctx3),
+ ?line Exp = crypto:sha256_mac(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac).
+
+hmac_update_sha512(doc) ->
+ ["Generate an SHA512 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:sha512_mac." ];
+hmac_update_sha512(suite) ->
+ [];
+hmac_update_sha512(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f"),
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(sha512, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final(Ctx3),
+ ?line Exp = crypto:sha512_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. "
@@ -343,7 +391,7 @@ hmac_update_md5(Config) when is_list(Config) ->
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 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),
@@ -351,7 +399,272 @@ hmac_update_md5(Config) when is_list(Config) ->
?line Mac2 = crypto:hmac_final(CtxD),
?line Exp2 = crypto:md5_mac(Key2, lists:flatten([Long1, Long2, Long3])),
?line m(Exp2, Mac2).
+
+hmac_rfc4231(doc) ->
+ ["Generate an HMAC using crypto:shaXXX_mac and hmac_init, hmac_update, and hmac_final. "
+ "Testvectors are take from RFC4231." ];
+hmac_rfc4231(suite) ->
+ [];
+hmac_rfc4231(Config) when is_list(Config) ->
+ %% Test Case 1
+ Case1Key = binary:copy(<<16#0b>>, 20),
+ Case1Data = <<"Hi There">>,
+ Case1Exp224 = hexstr2bin("896fb1128abbdf196832107cd49df33f"
+ "47b4b1169912ba4f53684b22"),
+ Case1Exp256 = hexstr2bin("b0344c61d8db38535ca8afceaf0bf12b"
+ "881dc200c9833da726e9376c2e32cff7"),
+ Case1Exp384 = hexstr2bin("afd03944d84895626b0825f4ab46907f"
+ "15f9dadbe4101ec682aa034c7cebc59c"
+ "faea9ea9076ede7f4af152e8b2fa9cb6"),
+ Case1Exp512 = hexstr2bin("87aa7cdea5ef619d4ff0b4241a1d6cb0"
+ "2379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4"
+ "be9d914eeb61f1702e696c203a126854"),
+
+ ?line Case1Ctx224 = crypto:hmac_init(sha224, Case1Key),
+ ?line Case1Ctx224_2 = crypto:hmac_update(Case1Ctx224, Case1Data),
+ ?line Case1Mac224_1 = crypto:hmac_final(Case1Ctx224_2),
+ ?line Case1Mac224_2 = crypto:sha224_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp224, Case1Mac224_1),
+ ?line m(Case1Exp224, Case1Mac224_2),
+
+ ?line Case1Ctx256 = crypto:hmac_init(sha256, Case1Key),
+ ?line Case1Ctx256_2 = crypto:hmac_update(Case1Ctx256, Case1Data),
+ ?line Case1Mac256_1 = crypto:hmac_final(Case1Ctx256_2),
+ ?line Case1Mac256_2 = crypto:sha256_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp256, Case1Mac256_1),
+ ?line m(Case1Exp256, Case1Mac256_2),
+
+ ?line Case1Ctx384 = crypto:hmac_init(sha384, Case1Key),
+ ?line Case1Ctx384_2 = crypto:hmac_update(Case1Ctx384, Case1Data),
+ ?line Case1Mac384_1 = crypto:hmac_final(Case1Ctx384_2),
+ ?line Case1Mac384_2 = crypto:sha384_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp384, Case1Mac384_1),
+ ?line m(Case1Exp384, Case1Mac384_2),
+
+ ?line Case1Ctx512 = crypto:hmac_init(sha512, Case1Key),
+ ?line Case1Ctx512_2 = crypto:hmac_update(Case1Ctx512, Case1Data),
+ ?line Case1Mac512_1 = crypto:hmac_final(Case1Ctx512_2),
+ ?line Case1Mac512_2 = crypto:sha512_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp512, Case1Mac512_1),
+ ?line m(Case1Exp512, Case1Mac512_2),
+
+ %% Test Case 2
+ Case2Key = <<"Jefe">>,
+ Case2Data = <<"what do ya want for nothing?">>,
+ Case2Exp224 = hexstr2bin("a30e01098bc6dbbf45690f3a7e9e6d0f"
+ "8bbea2a39e6148008fd05e44"),
+ Case2Exp256 = hexstr2bin("5bdcc146bf60754e6a042426089575c7"
+ "5a003f089d2739839dec58b964ec3843"),
+ Case2Exp384 = hexstr2bin("af45d2e376484031617f78d2b58a6b1b"
+ "9c7ef464f5a01b47e42ec3736322445e"
+ "8e2240ca5e69e2c78b3239ecfab21649"),
+ Case2Exp512 = hexstr2bin("164b7a7bfcf819e2e395fbe73b56e0a3"
+ "87bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fd"
+ "caeab1a34d4a6b4b636e070a38bce737"),
+
+ ?line Case2Ctx224 = crypto:hmac_init(sha224, Case2Key),
+ ?line Case2Ctx224_2 = crypto:hmac_update(Case2Ctx224, Case2Data),
+ ?line Case2Mac224_1 = crypto:hmac_final(Case2Ctx224_2),
+ ?line Case2Mac224_2 = crypto:sha224_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp224, Case2Mac224_1),
+ ?line m(Case2Exp224, Case2Mac224_2),
+
+ ?line Case2Ctx256 = crypto:hmac_init(sha256, Case2Key),
+ ?line Case2Ctx256_2 = crypto:hmac_update(Case2Ctx256, Case2Data),
+ ?line Case2Mac256_1 = crypto:hmac_final(Case2Ctx256_2),
+ ?line Case2Mac256_2 = crypto:sha256_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp256, Case2Mac256_1),
+ ?line m(Case2Exp256, Case2Mac256_2),
+
+ ?line Case2Ctx384 = crypto:hmac_init(sha384, Case2Key),
+ ?line Case2Ctx384_2 = crypto:hmac_update(Case2Ctx384, Case2Data),
+ ?line Case2Mac384_1 = crypto:hmac_final(Case2Ctx384_2),
+ ?line Case2Mac384_2 = crypto:sha384_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp384, Case2Mac384_1),
+ ?line m(Case2Exp384, Case2Mac384_2),
+
+ ?line Case2Ctx512 = crypto:hmac_init(sha512, Case2Key),
+ ?line Case2Ctx512_2 = crypto:hmac_update(Case2Ctx512, Case2Data),
+ ?line Case2Mac512_1 = crypto:hmac_final(Case2Ctx512_2),
+ ?line Case2Mac512_2 = crypto:sha512_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp512, Case2Mac512_1),
+ ?line m(Case2Exp512, Case2Mac512_2),
+
+ %% Test Case 3
+ Case3Key = binary:copy(<<16#aa>>, 20),
+ Case3Data = binary:copy(<<16#dd>>, 50),
+ Case3Exp224 = hexstr2bin("7fb3cb3588c6c1f6ffa9694d7d6ad264"
+ "9365b0c1f65d69d1ec8333ea"),
+ Case3Exp256 = hexstr2bin("773ea91e36800e46854db8ebd09181a7"
+ "2959098b3ef8c122d9635514ced565fe"),
+ Case3Exp384 = hexstr2bin("88062608d3e6ad8a0aa2ace014c8a86f"
+ "0aa635d947ac9febe83ef4e55966144b"
+ "2a5ab39dc13814b94e3ab6e101a34f27"),
+ Case3Exp512 = hexstr2bin("fa73b0089d56a284efb0f0756c890be9"
+ "b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807"
+ "b946a337bee8942674278859e13292fb"),
+
+ ?line Case3Ctx224 = crypto:hmac_init(sha224, Case3Key),
+ ?line Case3Ctx224_2 = crypto:hmac_update(Case3Ctx224, Case3Data),
+ ?line Case3Mac224_1 = crypto:hmac_final(Case3Ctx224_2),
+ ?line Case3Mac224_2 = crypto:sha224_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp224, Case3Mac224_1),
+ ?line m(Case3Exp224, Case3Mac224_2),
+
+ ?line Case3Ctx256 = crypto:hmac_init(sha256, Case3Key),
+ ?line Case3Ctx256_2 = crypto:hmac_update(Case3Ctx256, Case3Data),
+ ?line Case3Mac256_1 = crypto:hmac_final(Case3Ctx256_2),
+ ?line Case3Mac256_2 = crypto:sha256_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp256, Case3Mac256_1),
+ ?line m(Case3Exp256, Case3Mac256_2),
+
+ ?line Case3Ctx384 = crypto:hmac_init(sha384, Case3Key),
+ ?line Case3Ctx384_2 = crypto:hmac_update(Case3Ctx384, Case3Data),
+ ?line Case3Mac384_1 = crypto:hmac_final(Case3Ctx384_2),
+ ?line Case3Mac384_2 = crypto:sha384_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp384, Case3Mac384_1),
+ ?line m(Case3Exp384, Case3Mac384_2),
+
+ ?line Case3Ctx512 = crypto:hmac_init(sha512, Case3Key),
+ ?line Case3Ctx512_2 = crypto:hmac_update(Case3Ctx512, Case3Data),
+ ?line Case3Mac512_1 = crypto:hmac_final(Case3Ctx512_2),
+ ?line Case3Mac512_2 = crypto:sha512_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp512, Case3Mac512_1),
+ ?line m(Case3Exp512, Case3Mac512_2),
+
+ %% Test Case 4
+ Case4Key = list_to_binary(lists:seq(1, 16#19)),
+ Case4Data = binary:copy(<<16#cd>>, 50),
+ Case4Exp224 = hexstr2bin("6c11506874013cac6a2abc1bb382627c"
+ "ec6a90d86efc012de7afec5a"),
+ Case4Exp256 = hexstr2bin("82558a389a443c0ea4cc819899f2083a"
+ "85f0faa3e578f8077a2e3ff46729665b"),
+ Case4Exp384 = hexstr2bin("3e8a69b7783c25851933ab6290af6ca7"
+ "7a9981480850009cc5577c6e1f573b4e"
+ "6801dd23c4a7d679ccf8a386c674cffb"),
+ Case4Exp512 = hexstr2bin("b0ba465637458c6990e5a8c5f61d4af7"
+ "e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063"
+ "a5f19741120c4f2de2adebeb10a298dd"),
+
+ ?line Case4Ctx224 = crypto:hmac_init(sha224, Case4Key),
+ ?line Case4Ctx224_2 = crypto:hmac_update(Case4Ctx224, Case4Data),
+ ?line Case4Mac224_1 = crypto:hmac_final(Case4Ctx224_2),
+ ?line Case4Mac224_2 = crypto:sha224_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp224, Case4Mac224_1),
+ ?line m(Case4Exp224, Case4Mac224_2),
+
+ ?line Case4Ctx256 = crypto:hmac_init(sha256, Case4Key),
+ ?line Case4Ctx256_2 = crypto:hmac_update(Case4Ctx256, Case4Data),
+ ?line Case4Mac256_1 = crypto:hmac_final(Case4Ctx256_2),
+ ?line Case4Mac256_2 = crypto:sha256_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp256, Case4Mac256_1),
+ ?line m(Case4Exp256, Case4Mac256_2),
+
+ ?line Case4Ctx384 = crypto:hmac_init(sha384, Case4Key),
+ ?line Case4Ctx384_2 = crypto:hmac_update(Case4Ctx384, Case4Data),
+ ?line Case4Mac384_1 = crypto:hmac_final(Case4Ctx384_2),
+ ?line Case4Mac384_2 = crypto:sha384_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp384, Case4Mac384_1),
+ ?line m(Case4Exp384, Case4Mac384_2),
+
+ ?line Case4Ctx512 = crypto:hmac_init(sha512, Case4Key),
+ ?line Case4Ctx512_2 = crypto:hmac_update(Case4Ctx512, Case4Data),
+ ?line Case4Mac512_1 = crypto:hmac_final(Case4Ctx512_2),
+ ?line Case4Mac512_2 = crypto:sha512_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp512, Case4Mac512_1),
+ ?line m(Case4Exp512, Case4Mac512_2),
+
+ %% Test Case 6
+ Case6Key = binary:copy(<<16#aa>>, 131),
+ Case6Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>,
+ Case6Exp224 = hexstr2bin("95e9a0db962095adaebe9b2d6f0dbce2"
+ "d499f112f2d2b7273fa6870e"),
+ Case6Exp256 = hexstr2bin("60e431591ee0b67f0d8a26aacbf5b77f"
+ "8e0bc6213728c5140546040f0ee37f54"),
+ Case6Exp384 = hexstr2bin("4ece084485813e9088d2c63a041bc5b4"
+ "4f9ef1012a2b588f3cd11f05033ac4c6"
+ "0c2ef6ab4030fe8296248df163f44952"),
+ Case6Exp512 = hexstr2bin("80b24263c7c1a3ebb71493c1dd7be8b4"
+ "9b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e52"
+ "95e64f73f63f0aec8b915a985d786598"),
+
+ ?line Case6Ctx224 = crypto:hmac_init(sha224, Case6Key),
+ ?line Case6Ctx224_2 = crypto:hmac_update(Case6Ctx224, Case6Data),
+ ?line Case6Mac224_1 = crypto:hmac_final(Case6Ctx224_2),
+ ?line Case6Mac224_2 = crypto:sha224_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp224, Case6Mac224_1),
+ ?line m(Case6Exp224, Case6Mac224_2),
+
+ ?line Case6Ctx256 = crypto:hmac_init(sha256, Case6Key),
+ ?line Case6Ctx256_2 = crypto:hmac_update(Case6Ctx256, Case6Data),
+ ?line Case6Mac256_1 = crypto:hmac_final(Case6Ctx256_2),
+ ?line Case6Mac256_2 = crypto:sha256_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp256, Case6Mac256_1),
+ ?line m(Case6Exp256, Case6Mac256_2),
+
+ ?line Case6Ctx384 = crypto:hmac_init(sha384, Case6Key),
+ ?line Case6Ctx384_2 = crypto:hmac_update(Case6Ctx384, Case6Data),
+ ?line Case6Mac384_1 = crypto:hmac_final(Case6Ctx384_2),
+ ?line Case6Mac384_2 = crypto:sha384_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp384, Case6Mac384_1),
+ ?line m(Case6Exp384, Case6Mac384_2),
+
+ ?line Case6Ctx512 = crypto:hmac_init(sha512, Case6Key),
+ ?line Case6Ctx512_2 = crypto:hmac_update(Case6Ctx512, Case6Data),
+ ?line Case6Mac512_1 = crypto:hmac_final(Case6Ctx512_2),
+ ?line Case6Mac512_2 = crypto:sha512_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp512, Case6Mac512_1),
+ ?line m(Case6Exp512, Case6Mac512_2),
+ %% Test Case 7
+ Case7Key = binary:copy(<<16#aa>>, 131),
+ Case7Data = <<"This is a test using a larger than block-size key and a larger t",
+ "han block-size data. The key needs to be hashed before being use",
+ "d by the HMAC algorithm.">>,
+ Case7Exp224 = hexstr2bin("3a854166ac5d9f023f54d517d0b39dbd"
+ "946770db9c2b95c9f6f565d1"),
+ Case7Exp256 = hexstr2bin("9b09ffa71b942fcb27635fbcd5b0e944"
+ "bfdc63644f0713938a7f51535c3a35e2"),
+ Case7Exp384 = hexstr2bin("6617178e941f020d351e2f254e8fd32c"
+ "602420feb0b8fb9adccebb82461e99c5"
+ "a678cc31e799176d3860e6110c46523e"),
+ Case7Exp512 = hexstr2bin("e37b6a775dc87dbaa4dfa9f96e5e3ffd"
+ "debd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15"
+ "134676fb6de0446065c97440fa8c6a58"),
+
+ ?line Case7Ctx224 = crypto:hmac_init(sha224, Case7Key),
+ ?line Case7Ctx224_2 = crypto:hmac_update(Case7Ctx224, Case7Data),
+ ?line Case7Mac224_1 = crypto:hmac_final(Case7Ctx224_2),
+ ?line Case7Mac224_2 = crypto:sha224_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp224, Case7Mac224_1),
+ ?line m(Case7Exp224, Case7Mac224_2),
+
+ ?line Case7Ctx256 = crypto:hmac_init(sha256, Case7Key),
+ ?line Case7Ctx256_2 = crypto:hmac_update(Case7Ctx256, Case7Data),
+ ?line Case7Mac256_1 = crypto:hmac_final(Case7Ctx256_2),
+ ?line Case7Mac256_2 = crypto:sha256_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp256, Case7Mac256_1),
+ ?line m(Case7Exp256, Case7Mac256_2),
+
+ ?line Case7Ctx384 = crypto:hmac_init(sha384, Case7Key),
+ ?line Case7Ctx384_2 = crypto:hmac_update(Case7Ctx384, Case7Data),
+ ?line Case7Mac384_1 = crypto:hmac_final(Case7Ctx384_2),
+ ?line Case7Mac384_2 = crypto:sha384_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp384, Case7Mac384_1),
+ ?line m(Case7Exp384, Case7Mac384_2),
+
+ ?line Case7Ctx512 = crypto:hmac_init(sha512, Case7Key),
+ ?line Case7Ctx512_2 = crypto:hmac_update(Case7Ctx512, Case7Data),
+ ?line Case7Mac512_1 = crypto:hmac_final(Case7Ctx512_2),
+ ?line Case7Mac512_2 = crypto:sha512_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp512, Case7Mac512_1),
+ ?line m(Case7Exp512, Case7Mac512_2).
hmac_update_md5_io(doc) ->
["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. "
@@ -547,6 +860,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.";
@@ -566,6 +913,81 @@ des_ecb(Config) when is_list(Config) ->
?line m(Cipher5, <<"he time ">>),
?line Cipher6 = crypto:des_ecb_decrypt(Key, hexstr2bin("893d51ec4b563b53")),
?line m(Cipher6, <<"for all ">>).
+%%
+%%
+rc2_cbc(doc) ->
+ "Encrypt and decrypt according to RC2 CBC and check the result. "
+ "Example stripped out from public_key application test";
+rc2_cbc(Config) when is_list(Config) ->
+
+ Key = <<146,210,160,124,215,227,153,239,227,17,222,140,3,93,27,191>>,
+ IV = <<72,91,135,182,25,42,35,210>>,
+
+ Cipher = <<36,245,206,158,168,230,58,69,148,137,32,192,250,41,237,181,181,251, 192,2,175,135,177,171,57,30,111,117,159,149,15,28,88,158,28,81,28,115, 85,219,241,82,117,222,91,85,73,117,164,25,182,52,191,64,123,57,26,19, 211,27,253,31,194,219,231,104,247,240,172,130,119,21,225,154,101,247, 32,216,42,216,133,169,78,22,97,27,227,26,196,224,172,168,17,9,148,55, 203,91,252,40,61,226,236,221,215,160,78,63,13,181,68,57,196,241,185, 207, 116,129,152,237,60,139,247,153,27,146,161,246,222,98,185,222,152, 187,135, 236,86,34,7,110,91,230,173,34,160,242,202,222,121,127,181,140, 101,203,195, 190,88,250,86,147,127,87,72,126,171,16,71,47,110,248,88, 14,29,143,161,152, 129,236,148,22,152,186,208,119,70,8,174,193,203,100, 193,203,200,117,102,242, 134,142,96,125,135,200,217,190,76,117,50,70, 209,186,101,241,200,91,40,193,54, 90,195,38,47,59,197,38,234,86,223,16, 51,253,204,129,20,171,66,21,241,26,135,216, 196,114,110,91,15,53,40, 164,201,136,113,95,247,51,181,208,241,68,168,98,151,36, 155,72,24,57, 42,191,14,125,204,10,167,214,233,138,115,125,234,121,134,227,26,247, 77,200,117,110,117,111,168,156,206,67,159,149,189,173,150,193,91,199, 216,153,22, 189,137,185,89,160,13,131,132,58,109,28,110,246,252,251,14, 232,91,38,52,29,101,188,69,123,50,0,130,178,93,73,239,118,7,77,35,59, 253,10,159,45,86,142,37,78,232,48>>,
+ Text = <<48,130,1,85,2,1,0,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,4,130,1,63,48,130, 1,59,2,1,0,2,65,0,222,187,252,44,9,214,27,173,162,169,70,47,36,34,78,84,204, 107,60,192,117,95,21,206,49,142,245,126,121,223,23,2,107,106,133,204,161,36, 40,2,114,69,4,93,242,5,42,50,154,47,154,211,209,123,120,161,5,114,173,155,34, 191,52,59,2,3,1,0,1,2,64,45,144,169,106,220,236,71,39,67,82,123,192,35,21,61, 143,13,110,150,180,12,142,210,40,39,109,70,125,132,51,6,66,159,134,112,85, 155,243,118,221,65,133,127,99,151,194,252,141,149,224,229,62,214,45,228,32, 184,85,67,14,228,161,184,161,2,33,0,255,202,240,131,130,57,49,224,115,255,83, 79,6,165,212,21,179,212,20,188,97,74,69,68,163,223,247,237,39,24,23,235,2,33, 0,222,234,48,36,33,23,219,45,59,136,55,245,143,29,165,48,255,131,207,146,131, 104,13,163,54,131,236,78,88,54,16,241,2,33,0,230,2,99,129,173,176,166,131, 241,106,143,76,9,107,70,41,121,185,228,39,124,200,159,62,216,169,5,180,111, 169,255,159,2,33,0,151,193,70,212,209,210,179,219,175,83,165,4,255,81,103,76, 92,39,24,0,222,132,208,3,244,241,10,198,171,54,227,129,2,32,43,250,20,31,16, 189,168,116,225,1,125,132,94,130,118,124,28,56,232,39,69,218,244,33,240,200, 205,9,215,101,35,135,7,7,7,7,7,7,7>>,
+
+ Text = crypto:rc2_cbc_decrypt(Key, IV, Cipher),
+ Cipher = crypto:rc2_cbc_encrypt(Key, IV, Text).
+
+%%
+%%
+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)).
%%
%%
@@ -605,10 +1027,19 @@ aes_cfb(Config) when is_list(Config) ->
?line Key = hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
?line IVec = hexstr2bin("000102030405060708090a0b0c0d0e0f"),
?line Plain = hexstr2bin("6bc1bee22e409f96e93d7e117393172a"),
- ?line Cipher = crypto:aes_cfb_128_encrypt(Key, IVec, Plain),
- ?line m(Cipher, hexstr2bin("3b3fd92eb72dad20333449f8e83cfb4a")),
- ?line m(Plain,
- crypto:aes_cfb_128_decrypt(Key, IVec, Cipher)).
+ ?line Cipher = hexstr2bin("3b3fd92eb72dad20333449f8e83cfb4a"),
+
+ %% Try all prefixes of plain and cipher.
+ aes_cfb_do(byte_size(Plain), Plain, Cipher, Key, IVec).
+
+aes_cfb_do(N, Plain, Cipher, Key, IVec) when N >= 0 ->
+ <<P:N/binary, _/binary>> = Plain,
+ <<C:N/binary, _/binary>> = Cipher,
+ ?line C = crypto:aes_cfb_128_encrypt(Key, IVec, P),
+ ?line P = crypto:aes_cfb_128_decrypt(Key, IVec, C),
+ aes_cfb_do(N-1, Plain, Cipher, Key, IVec);
+aes_cfb_do(_, _, _, _, _) -> ok.
+
%%
%%
@@ -1095,6 +1526,33 @@ rsa_sign_test(Config) when is_list(Config) ->
ok.
+rsa_sign_hash_test(doc) ->
+ "rsa_sign_hash testing";
+rsa_sign_hash_test(suite) ->
+ [];
+rsa_sign_hash_test(Config) when is_list(Config) ->
+ PubEx = 65537,
+ PrivEx = 7531712708607620783801185371644749935066152052780368689827275932079815492940396744378735701395659435842364793962992309884847527234216715366607660219930945,
+ Mod = 7919488123861148172698919999061127847747888703039837999377650217570191053151807772962118671509138346758471459464133273114654252861270845708312601272799123,
+ Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
+ "09812312908312378623487263487623412039812 huagasd">>,
+
+ PrivKey = [crypto:mpint(PubEx), crypto:mpint(Mod), crypto:mpint(PrivEx)],
+ PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)],
+ MD5 = crypto:md5(sized_binary(Msg)),
+ SHA = crypto:sha(sized_binary(Msg)),
+ ?line Sig1 = crypto:rsa_sign(sha, {digest,SHA}, PrivKey),
+ ?line m(crypto:rsa_verify(sha, {digest,SHA}, sized_binary(Sig1),PubKey), true),
+
+ ?line Sig2 = crypto:rsa_sign(md5, {digest,MD5}, PrivKey),
+ ?line m(crypto:rsa_verify(md5, {digest,MD5}, sized_binary(Sig2),PubKey), true),
+
+ ?line m(Sig1 =:= Sig2, false),
+ ?line m(crypto:rsa_verify(md5, {digest,MD5}, sized_binary(Sig1),PubKey), false),
+ ?line m(crypto:rsa_verify(sha, {digest,SHA}, sized_binary(Sig2),PubKey), false),
+
+ ok.
+
dsa_sign_test(doc) ->
"dsa_sign testing";
dsa_sign_test(suite) ->
@@ -1125,6 +1583,37 @@ dsa_sign_test(Config) when is_list(Config) ->
ok.
+dsa_sign_hash_test(doc) ->
+ "dsa_sign_hash testing";
+dsa_sign_hash_test(suite) ->
+ [];
+dsa_sign_hash_test(Config) when is_list(Config) ->
+ Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
+ "09812312908312378623487263487623412039812 huagasd">>,
+ SHA = crypto:sha(sized_binary(Msg)),
+
+ PubKey = _Y = 25854665488880835237281628794585130313500176551981812527054397586638455298000483144002221850980183404910190346416063318160497344811383498859129095184158800144312512447497510551471331451396405348497845813002058423110442376886564659959543650802132345311573634832461635601376738282831340827591903548964194832978,
+ PrivKey = _X = 441502407453038284293378221372000880210588566361,
+ ParamP = 109799869232806890760655301608454668257695818999841877165019612946154359052535682480084145133201304812979481136659521529774182959764860329095546511521488413513097576425638476458000255392402120367876345280670101492199681798674053929238558140260669578407351853803102625390950534052428162468100618240968893110797,
+ ParamQ = 1349199015905534965792122312016505075413456283393,
+ ParamG = 18320614775012672475365915366944922415598782131828709277168615511695849821411624805195787607930033958243224786899641459701930253094446221381818858674389863050420226114787005820357372837321561754462061849169568607689530279303056075793886577588606958623645901271866346406773590024901668622321064384483571751669,
+
+ Params = [crypto:mpint(ParamP), crypto:mpint(ParamQ), crypto:mpint(ParamG)],
+ ?line Sig1 = crypto:dss_sign(sha, {digest,SHA}, Params ++ [crypto:mpint(PrivKey)]),
+
+ ?line m(crypto:dss_verify(none, SHA, sized_binary(Sig1),
+ Params ++ [crypto:mpint(PubKey)]), true),
+
+ ?line m(crypto:dss_verify(sized_binary(one_bit_wrong(Msg)), sized_binary(Sig1),
+ Params ++ [crypto:mpint(PubKey)]), false),
+
+ ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(one_bit_wrong(Sig1)),
+ Params ++ [crypto:mpint(PubKey)]), false),
+
+ %%?line Bad = crypto:dss_sign(sized_binary(Msg), [Params, crypto:mpint(PubKey)]),
+
+ ok.
+
rsa_encrypt_decrypt(doc) ->
["Test rsa_public_encrypt and rsa_private_decrypt functions."];
@@ -1233,8 +1722,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),
@@ -1248,14 +1737,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."];
@@ -1309,7 +1798,9 @@ 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, 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 },
+ hmac_update_md5, hmac_update_sha, hmac_update_sha256, hmac_update_sha512,
+ hmac_rfc4231,
+ 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 33fa9b1ec3..7e82e47d38 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.0.4
+CRYPTO_VSN = 2.1
diff --git a/lib/debugger/doc/src/Makefile b/lib/debugger/doc/src/Makefile
index 1c0bbaf9d2..bc11ed7f46 100644
--- a/lib/debugger/doc/src/Makefile
+++ b/lib/debugger/doc/src/Makefile
@@ -110,12 +110,12 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- (/bin/cp -rf $(HTMLDIR) $(RELSYSDIR)/doc)
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ (/bin/cp -rf $(HTMLDIR) "$(RELSYSDIR)/doc")
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/debugger/doc/src/debugger_chapter.xml b/lib/debugger/doc/src/debugger_chapter.xml
index 2d812b0236..de7784b240 100644
--- a/lib/debugger/doc/src/debugger_chapter.xml
+++ b/lib/debugger/doc/src/debugger_chapter.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>
diff --git a/lib/debugger/doc/src/int.xml b/lib/debugger/doc/src/int.xml
index c9d815755d..0794685f34 100644
--- a/lib/debugger/doc/src/int.xml
+++ b/lib/debugger/doc/src/int.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>
diff --git a/lib/debugger/doc/src/make.dep b/lib/debugger/doc/src/make.dep
deleted file mode 100644
index c11fd3c21c..0000000000
--- a/lib/debugger/doc/src/make.dep
+++ /dev/null
@@ -1,29 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex debugger.tex debugger_chapter.tex \
- i.tex int.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: part.xml ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: images/attach.ps images/cond_break_dialog.ps \
- images/function_break_dialog.ps images/interpret.ps \
- images/line_break_dialog.ps images/monitor.ps \
- images/view.ps
-
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 93e447848a..593bf715bf 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -32,6 +32,66 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 3.2.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed disappearing breakpoints bug, reported by Ricardo
+ Catalinas Jim�nez.</p>
+ <p>
+ Own Id: OTP-9950</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Debugger 3.2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix "OK" spelling in debugger messages and variables</p>
+ <p>
+ Simple code refactor in the debugger: renames all the
+ occurrences of "Ok" to "OK" in the code, variable names
+ and strings. This improves the consistency of the code
+ and follows the GTK UI where "OK" is always used.(Thanks
+ to Ricardo Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9699</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Variables are now now allowed in '<c>fun M:F/A</c>' as
+ suggested by Richard O'Keefe in EEP-23.</p>
+ <p>The representation of '<c>fun M:F/A</c>' in the
+ abstract format has been changed in an incompatible way.
+ Tools that directly read or manipulate the abstract
+ format (such as parse transforms) may need to be updated.
+ The compiler can handle both the new and the old format
+ (i.e. extracting the abstract format from a pre-R15 BEAM
+ file and compiling it using compile:forms/1,2 will work).
+ The <c>syntax_tools</c> application can also handle both
+ formats.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9643</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 3.2.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/debugger/priv/Makefile b/lib/debugger/priv/Makefile
index 1036a5666b..2f3002331b 100644
--- a/lib/debugger/priv/Makefile
+++ b/lib/debugger/priv/Makefile
@@ -54,8 +54,8 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(TOOLBAR_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(TOOLBAR_FILES) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/debugger/src/Makefile b/lib/debugger/src/Makefile
index 6dc7d0d783..1f9d6f2058 100644
--- a/lib/debugger/src/Makefile
+++ b/lib/debugger/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
@@ -129,9 +129,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(TOOLBOX_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(TARGET_TOOLBOX_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(TOOLBOX_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(TARGET_TOOLBOX_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl
index 18dcd92ff3..4d9ffc4f3b 100644
--- a/lib/debugger/src/dbg_debugged.erl
+++ b/lib/debugger/src/dbg_debugged.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
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index df725ed9e5..2e88c35741 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -768,6 +768,21 @@ expr({make_fun,Line,Name,Cs}, Bs, #ieval{module=Module}=Ieval) ->
end,
{value,Fun,Bs};
+%% Construct an external fun.
+expr({make_ext_fun,Line,MFA0}, Bs0, Ieval0) ->
+ {[M,F,A],Bs} = eval_list(MFA0, Bs0, Ieval0),
+ try erlang:make_fun(M, F, A) of
+ Value ->
+ {value,Value,Bs}
+ catch
+ error:badarg ->
+ Ieval1 = Ieval0#ieval{line=Line},
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=erlang,function=make_fun,
+ arguments=[M,F,A],line=-1},
+ exception(error, badarg, Bs, Ieval, true)
+ end;
+
%% Common test adaptation
expr({call_remote,0,ct_line,line,As0,Lc}, Bs0, Ieval0) ->
{As,_Bs} = eval_list(As0, Bs0, Ieval0),
diff --git a/lib/debugger/src/dbg_ieval.hrl b/lib/debugger/src/dbg_ieval.hrl
index ea6189ad02..1abf39d247 100644
--- a/lib/debugger/src/dbg_ieval.hrl
+++ b/lib/debugger/src/dbg_ieval.hrl
@@ -1,7 +1,7 @@
%%
%% %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
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index ce5631e45f..3c95ef8068 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -369,6 +369,14 @@ expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}, _Lc) ->
As = new_vars(A, Line),
Cs = [{clause,Line,As,[],[{local_call,Line,F,As,true}]}],
{make_fun,Line,Name,Cs};
+expr({'fun',Line,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Lc)
+ when 0 =< A, A =< 255 ->
+ %% New format in R15 for fun M:F/A (literal values).
+ {value,Line,erlang:make_fun(M, F, A)};
+expr({'fun',Line,{function,M,F,A}}, _Lc) ->
+ %% New format in R15 for fun M:F/A (one or more variables).
+ MFA = expr_list([M,F,A]),
+ {make_ext_fun,Line,MFA};
expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,self}},[]}, _Lc) ->
{dbg,Line,self,[]};
expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,get_stacktrace}},[]}, _Lc) ->
diff --git a/lib/debugger/src/dbg_iserver.erl b/lib/debugger/src/dbg_iserver.erl
index 1bb73a43b9..31a856545f 100644
--- a/lib/debugger/src/dbg_iserver.erl
+++ b/lib/debugger/src/dbg_iserver.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -188,10 +188,7 @@ handle_call({new_break, Point, Options}, _From, State) ->
handle_call(all_breaks, _From, State) ->
{reply, State#state.breaks, State};
handle_call({all_breaks, Mod}, _From, State) ->
- Reply = lists:filter(fun({{M,_L}, _Options}) ->
- M =/= Mod
- end,
- State#state.breaks),
+ Reply = [Break || Break = {{M, _},_} <- State#state.breaks, M =:= Mod],
{reply, Reply, State};
%% From Meta process
diff --git a/lib/debugger/src/dbg_ui_break_win.erl b/lib/debugger/src/dbg_ui_break_win.erl
index 4039bf785f..11d810ccab 100644
--- a/lib/debugger/src/dbg_ui_break_win.erl
+++ b/lib/debugger/src/dbg_ui_break_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,18 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_break_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/5,
@@ -81,12 +93,12 @@ create_win(GS, {X, Y}, function, Mod, _Line) ->
{pack_x, 2}, {pack_y, 3},
{selectmode, multiple}]),
- %% Add Ok and Cancel buttons
- {Wbtn, Hbtn} = dbg_ui_win:min_size(["Ok","Cancel"], 70, 30),
+ %% Add OK and Cancel buttons
+ {Wbtn, Hbtn} = dbg_ui_win:min_size(["OK","Cancel"], 70, 30),
Bot = gs:frame(Frm, [{pack_x, {1, 3}}, {pack_y, 4}]),
- Ok = gs:button(Bot, [{x, Pad}, {y, Pad},
+ OK = gs:button(Bot, [{x, Pad}, {y, Pad},
{width, Wbtn}, {height, Hbtn},
- {label, {text,"Ok"}}, {font, Font}]),
+ {label, {text,"OK"}}, {font, Font}]),
Cancel = gs:button(Bot, [{x, W-Pad-Wbtn}, {y, Pad},
{width, Wbtn}, {height, Hbtn},
{label, {text,"Cancel"}}, {font, Font}]),
@@ -95,7 +107,7 @@ create_win(GS, {X, Y}, function, Mod, _Line) ->
gs:config(Win, [{width, Wfrm}, {height, Hfrm}, {map, true}]),
#winInfo{type=function, win=Win,
packer=Frm, entries=Entries, trigger=enable,
- ok=Ok, cancel=Cancel, listbox=Lb, funcs=[]};
+ ok=OK, cancel=Cancel, listbox=Lb, funcs=[]};
create_win(GS, {X, Y}, Type, Mod, Line) ->
Pad = 8,
W = 230,
@@ -161,12 +173,12 @@ create_win(GS, {X, Y}, Type, Mod, Line) ->
{align, w}, {group, Grp},
{data, {trigger, delete}}]),
- %% Add Ok and Cancel buttons
- {Wbtn, Hbtn} = dbg_ui_win:min_size(["Ok","Cancel"], 70, 30),
+ %% Add OK and Cancel buttons
+ {Wbtn, Hbtn} = dbg_ui_win:min_size(["OK","Cancel"], 70, 30),
Ybtn = Yacc + Pad + Hfrm + Pad,
- Ok = gs:button(Win, [{x, Pad}, {y, Ybtn},
+ OK = gs:button(Win, [{x, Pad}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
- {label, {text,"Ok"}}, {font, Font}]),
+ {label, {text,"OK"}}, {font, Font}]),
gs:button(Win, [{x, W-Pad-Wbtn}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
{label, {text,"Cancel"}}, {font, Font}]),
@@ -175,7 +187,7 @@ create_win(GS, {X, Y}, Type, Mod, Line) ->
gs:config(Win, [{width, W}, {height, Hwin}, {map, true}]),
#winInfo{type=Type, win=Win,
- entries=Entries, trigger=enable, ok=Ok}.
+ entries=Entries, trigger=enable, ok=OK}.
%%--------------------------------------------------------------------
%% update_functions(WinInfo, Funcs) -> WinInfo
@@ -229,7 +241,7 @@ handle_event({gs, LB, keypress, window, [Key|_]}, WinInfo) ->
Key/='Tab', Key/='Return' ->
ignore;
true ->
- handle_event({gs, LB, click, listbox, ["Ok"]}, WinInfo)
+ handle_event({gs, LB, click, listbox, ["OK"]}, WinInfo)
end;
handle_event({gs, Ent, keypress, Data, [Key|_]}, WinInfo) ->
case WinInfo#winInfo.type of
@@ -249,14 +261,14 @@ handle_event({gs, Ent, keypress, Data, [Key|_]}, WinInfo) ->
case next_entry(Ent, WinInfo#winInfo.entries) of
last ->
gs:config(WinInfo#winInfo.ok, flash),
- handle_event({gs, Ent, click, Data, ["Ok"]}, WinInfo);
+ handle_event({gs, Ent, click, Data, ["OK"]}, WinInfo);
Next ->
gs:config(Next, {setfocus, true}),
ignore
end;
_Type -> ignore
end;
-handle_event({gs, _Id, click, _Data, ["Ok"|_]}, WinInfo) ->
+handle_event({gs, _Id, click, _Data, ["OK"|_]}, WinInfo) ->
case check_input(WinInfo#winInfo.entries) of
error -> ignore;
Data when WinInfo#winInfo.type/=function ->
diff --git a/lib/debugger/src/dbg_ui_edit_win.erl b/lib/debugger/src/dbg_ui_edit_win.erl
index badaf4bef4..2e9a685b57 100644
--- a/lib/debugger/src/dbg_ui_edit_win.erl
+++ b/lib/debugger/src/dbg_ui_edit_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,12 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_edit_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/5, get_window/1,
@@ -64,13 +70,13 @@ create_win(GS, {X, Y}, Title, Prompt, {Type, Value}) ->
{text, Value},
{keypress, true}]),
- %% Ok and Cancel buttons
+ %% OK and Cancel buttons
W = Pad + Wlbl + Went + Pad,
{Wbtn, Hbtn} = dbg_ui_win:min_size(["Cancel"], 70, 30),
Ybtn = Pad + Hlbl + Pad,
Btn = gs:button(Win, [{x, Pad}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
- {label, {text,"Ok"}}, {font, Font}]),
+ {label, {text,"OK"}}, {font, Font}]),
gs:button(Win, [{x, W-Pad-Wbtn}, {y, Ybtn},
{width, Wbtn}, {height, Hbtn},
{label, {text,"Cancel"}}, {font, Font}]),
@@ -100,8 +106,8 @@ handle_event({gs, _Id, destroy, _Data, _Arg}, _WinInfo) ->
stopped;
handle_event({gs, Id, keypress, Data, ['Return'|_]}, WinInfo) ->
gs:config(WinInfo#winInfo.button, flash),
- handle_event({gs, Id, click, Data, ["Ok"]}, WinInfo);
-handle_event({gs, _Id, click, _Data, ["Ok"|_]}, WinInfo) ->
+ handle_event({gs, Id, click, Data, ["OK"]}, WinInfo);
+handle_event({gs, _Id, click, _Data, ["OK"|_]}, WinInfo) ->
Ent = WinInfo#winInfo.entry,
Str = gs:read(Ent, text),
Type = WinInfo#winInfo.type,
diff --git a/lib/debugger/src/dbg_ui_filedialog_win.erl b/lib/debugger/src/dbg_ui_filedialog_win.erl
index 3203991c1f..52dc2012f3 100644
--- a/lib/debugger/src/dbg_ui_filedialog_win.erl
+++ b/lib/debugger/src/dbg_ui_filedialog_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,13 @@
%%
-module(dbg_ui_filedialog_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/6, create_win/7, get_window/1,
@@ -100,7 +107,7 @@ create_win(GS, Title, {X,Y}, Mode, Filter, Extra, FileName) ->
Opts = [{y, Y4}, {width, Wbtn}, {height, Hbtn}, {font, Font}],
case Mode of
normal ->
- gs:button(Win, [{label, {text,"Ok"}}, {x, Pad},
+ gs:button(Win, [{label, {text,"OK"}}, {x, Pad},
{data, select} | Opts]),
gs:button(Win, [{label, {text,"Filter"}}, {x, Wlb/2-Wbtn/2},
{data, filter} | Opts]),
diff --git a/lib/debugger/src/dbg_ui_interpret.erl b/lib/debugger/src/dbg_ui_interpret.erl
index 952e73b537..73392d40cb 100644
--- a/lib/debugger/src/dbg_ui_interpret.erl
+++ b/lib/debugger/src/dbg_ui_interpret.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
@@ -145,7 +145,7 @@ interpret_all(State, Dir, [File0|Files]) ->
Window = dbg_ui_filedialog_win:get_window(State#state.win),
Error = format_error(int:interpretable(File)),
Msg = ["Error when interpreting:", File, Error,
- "Ok to continue?"],
+ "OK to continue?"],
case tool_utils:confirm(Window, Msg) of
ok -> interpret_all(State, Dir, Files);
cancel -> true
diff --git a/lib/debugger/src/dbg_ui_mon_win.erl b/lib/debugger/src/dbg_ui_mon_win.erl
index 52e8f433ba..8655c7697a 100644
--- a/lib/debugger/src/dbg_ui_mon_win.erl
+++ b/lib/debugger/src/dbg_ui_mon_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,19 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_mon_win).
+-compile([{nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([init/0]).
diff --git a/lib/debugger/src/dbg_ui_settings.erl b/lib/debugger/src/dbg_ui_settings.erl
index 146aa7e239..fcfd67966f 100644
--- a/lib/debugger/src/dbg_ui_settings.erl
+++ b/lib/debugger/src/dbg_ui_settings.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
@@ -136,8 +136,8 @@ default_settings_dir(GS) ->
{ok, CWD} = file:get_cwd(),
Msg = ["Default directory", DefDir, "does not exist.",
- "Click Ok to create it or",
- "Cancel to use other directory!"],
+ "Click OK to create it or",
+ "Cancel to use other directory."],
case tool_utils:confirm(GS, Msg) of
ok ->
ToolsDir = filename:dirname(DefDir),
diff --git a/lib/debugger/src/dbg_ui_trace_win.erl b/lib/debugger/src/dbg_ui_trace_win.erl
index 82d4199630..1b439cbf18 100644
--- a/lib/debugger/src/dbg_ui_trace_win.erl
+++ b/lib/debugger/src/dbg_ui_trace_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,25 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_trace_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
%% External exports
-export([init/0]).
diff --git a/lib/debugger/src/dbg_ui_win.erl b/lib/debugger/src/dbg_ui_win.erl
index 9bed6a1ec5..1c7a80a1c4 100644
--- a/lib/debugger/src/dbg_ui_win.erl
+++ b/lib/debugger/src/dbg_ui_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,15 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_win).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% External exports
-export([init/0,
diff --git a/lib/debugger/src/dbg_ui_winman.erl b/lib/debugger/src/dbg_ui_winman.erl
index c7aac0df23..b5433a202b 100644
--- a/lib/debugger/src/dbg_ui_winman.erl
+++ b/lib/debugger/src/dbg_ui_winman.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,11 @@
%%
-module(dbg_ui_winman).
-behaviour(gen_server).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,3}}]).
%% External exports
-export([start/0]).
diff --git a/lib/debugger/src/dbg_wx_break_win.erl b/lib/debugger/src/dbg_wx_break_win.erl
index 7ac82c8fb4..062da3937a 100644
--- a/lib/debugger/src/dbg_wx_break_win.erl
+++ b/lib/debugger/src/dbg_wx_break_win.erl
@@ -82,8 +82,8 @@ create_win(Parent, Pos, function, Mod, _Line) ->
wxComboBox:connect(Text, command_text_updated),
wxListBox:connect(LB, command_listbox_selected),
wxListBox:connect(LB, command_listbox_doubleclicked),
- OkId = wxDialog:getAffirmativeId(Win),
- OKButt = wxWindow:findWindowById(OkId, [{parent, Win}]),
+ OKId = wxDialog:getAffirmativeId(Win),
+ OKButt = wxWindow:findWindowById(OKId, [{parent, Win}]),
wxWindow:disable(OKButt),
wxDialog:centreOnParent(Win),
wxDialog:show(Win),
@@ -141,8 +141,8 @@ create_win(Parent, Pos, Type, Mod, Line) ->
wxComboBox:setFocus(ModT),
wxDialog:connect(Win, command_button_clicked),
wxDialog:connect(Win, command_text_updated),
- OkId = wxDialog:getAffirmativeId(Win),
- OKButt = wxWindow:findWindowById(OkId),
+ OKId = wxDialog:getAffirmativeId(Win),
+ OKButt = wxWindow:findWindowById(OKId),
wxWindow:disable(OKButt),
wxDialog:centreOnParent(Win),
wxDialog:show(Win),
@@ -180,30 +180,30 @@ handle_event(#wx{id=?wxID_CANCEL}, #winInfo{win=Win}) ->
wxDialog:destroy(Win),
stopped;
handle_event(#wx{event=#wxCommand{type=command_text_updated}},
- #winInfo{type=function, text=Text, ok=Ok}) ->
+ #winInfo{type=function, text=Text, ok=OK}) ->
Module = wxComboBox:getValue(Text),
- wxWindow:disable(Ok),
+ wxWindow:disable(OK),
{module, list_to_atom(Module)};
handle_event(#wx{event=#wxCommand{type=command_text_updated}},
- #winInfo{text=Text, ok=Ok, entries=Es}) ->
+ #winInfo{text=Text, ok=OK, entries=Es}) ->
Module = wxComboBox:getValue(Text),
case check_input(Es) of
- error -> wxWindow:disable(Ok);
- _Data when Module =/= "" -> wxWindow:enable(Ok);
- _ -> wxWindow:disable(Ok)
+ error -> wxWindow:disable(OK);
+ _Data when Module =/= "" -> wxWindow:enable(OK);
+ _ -> wxWindow:disable(OK)
end,
ignore;
handle_event(#wx{event=#wxCommand{type=command_listbox_selected}},
- #winInfo{type=function, listbox=LB, ok=Ok}) ->
+ #winInfo{type=function, listbox=LB, ok=OK}) ->
case wxListBox:getSelections(LB) of
- {N,_} when N > 0 -> wxWindow:enable(Ok);
- _ -> wxWindow:disable(Ok)
+ {N,_} when N > 0 -> wxWindow:enable(OK);
+ _ -> wxWindow:disable(OK)
end,
ignore;
-handle_event(#wx{id=OKorListBox, event=#wxCommand{type=OkorDoubleClick}},
+handle_event(#wx{id=OKorListBox, event=#wxCommand{type=OKorDoubleClick}},
#winInfo{type=function,win=Win,listbox=LB,funcs=Funcs,text=Text})
when OKorListBox =:= ?wxID_OK;
- OkorDoubleClick =:= command_listbox_doubleclicked ->
+ OKorDoubleClick =:= command_listbox_doubleclicked ->
Mod = wxComboBox:getValue(Text),
{_, IndexL} = wxListBox:getSelections(LB),
Breaks = [[list_to_atom(Mod)|lists:nth(Index+1, Funcs)] || Index <- IndexL],
diff --git a/lib/debugger/src/dbg_wx_filedialog_win.erl b/lib/debugger/src/dbg_wx_filedialog_win.erl
index 9687efa981..f109652a70 100644
--- a/lib/debugger/src/dbg_wx_filedialog_win.erl
+++ b/lib/debugger/src/dbg_wx_filedialog_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
@@ -24,7 +24,7 @@
-export([new/3, getFilename/1, getFilenames/1, getDirectory/1, destroy/1]).
%% Internal
--export([init/1, handle_call/3, handle_event/2,
+-export([init/1, handle_call/3, handle_event/2, handle_cast/2,
handle_info/2, code_change/3, terminate/2]).
-include_lib("wx/include/wx.hrl").
@@ -151,7 +151,7 @@ init([Parent, Id, Options0]) ->
Bott = wxDialog:createButtonSizer(Dlg, ?wxCANCEL bor ?wxOK),
wxDialog:connect(Dlg, command_button_clicked),
- %% Ok done
+ %% OK done
Box = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Box, Top, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]),
wxSizer:add(Box, Dir, [{border, 2}, {flag,?wxALL bor ?wxEXPAND}]),
@@ -193,6 +193,9 @@ handle_call(getDirectory, _From, State = #state{path=Dir}) ->
handle_call(destroy, _From, State) ->
{stop, normal, ok, State}.
+handle_cast(_, State) ->
+ {noreply, State}.
+
%% events
handle_event(#wx{id=?wxID_UP}, State0) ->
State = update_window(change_dir(0, State0)),
diff --git a/lib/debugger/src/dbg_wx_settings.erl b/lib/debugger/src/dbg_wx_settings.erl
index 8f87815949..3be93c495c 100644
--- a/lib/debugger/src/dbg_wx_settings.erl
+++ b/lib/debugger/src/dbg_wx_settings.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
@@ -83,9 +83,9 @@ default_settings_dir(Win) ->
false ->
{ok, CWD} = file:get_cwd(),
- Msg = ["Default directory", DefDir, "does not exist.",
- "Click Ok to create it or",
- "Cancel to use other directory!"],
+ Msg = ["Default directory ", DefDir, " does not exist. ",
+ "Click OK to create it or ",
+ "Cancel to use other directory."],
case dbg_wx_win:confirm(Win, Msg) of
ok ->
ToolsDir = filename:dirname(DefDir),
diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl
index 720b913024..68e8e0b844 100755..100644
--- a/lib/debugger/src/dbg_wx_trace_win.erl
+++ b/lib/debugger/src/dbg_wx_trace_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,7 @@
%%
-module(dbg_wx_trace_win).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
%% External exports
-export([init/0, stop/1]).
diff --git a/lib/debugger/src/dbg_wx_winman.erl b/lib/debugger/src/dbg_wx_winman.erl
index 79dcc47f6f..79dcc47f6f 100755..100644
--- a/lib/debugger/src/dbg_wx_winman.erl
+++ b/lib/debugger/src/dbg_wx_winman.erl
diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src
index 5538f66260..807054c983 100644
--- a/lib/debugger/src/debugger.app.src
+++ b/lib/debugger/src/debugger.app.src
@@ -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
diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile
index 3dfbed31ff..bf948ce8b0 100644
--- a/lib/debugger/test/Makefile
+++ b/lib/debugger/test/Makefile
@@ -98,10 +98,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) debugger.spec debugger.cover $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) debugger.spec debugger.cover "$(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 187c9f53b0..e0bda7eac8 100644
--- a/lib/debugger/test/bs_construct_SUITE.erl
+++ b/lib/debugger/test/bs_construct_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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,7 +56,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
- Dog = test_server:timetrap(?t:minutes(1)),
+ Dog = test_server:timetrap(?t:minutes(15)),
[{watchdog,Dog}|Config].
end_per_testcase(_Case, Config) ->
@@ -477,7 +477,6 @@ 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) ->
@@ -490,13 +489,6 @@ big_bin(B1, B2) ->
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>>,
diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl
index 89fce263f5..6b66c45448 100644
--- a/lib/debugger/test/bs_match_misc_SUITE.erl
+++ b/lib/debugger/test/bs_match_misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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 @@ end_per_suite(Config) when is_list(Config) ->
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
- Dog = test_server:timetrap(?t:minutes(1)),
+ Dog = test_server:timetrap(?t:minutes(15)),
[{watchdog,Dog}|Config].
end_per_testcase(_Case, Config) ->
diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl
index 8103d9c692..a06cdc7165 100644
--- a/lib/debugger/test/fun_SUITE.erl
+++ b/lib/debugger/test/fun_SUITE.erl
@@ -24,8 +24,10 @@
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
good_call/1,bad_apply/1,bad_fun_call/1,badarity/1,
- ext_badarity/1,otp_6061/1]).
--export([nothing/0]).
+ ext_badarity/1,otp_6061/1,external/1]).
+
+%% Internal exports.
+-export([nothing/0,call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -46,7 +48,7 @@ end_per_group(_GroupName, Config) ->
cases() ->
[good_call, bad_apply, bad_fun_call, badarity,
- ext_badarity, otp_6061].
+ ext_badarity, otp_6061, external].
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -244,3 +246,47 @@ test_otp_6061(Starter) ->
fun() -> Starter ! working end,
fun() -> Starter ! not_working end],
lists:foreach(fun(P)->(lists:nth(P,PassesF))() end,Passes).
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/debugger/test/int_break_SUITE.erl b/lib/debugger/test/int_break_SUITE.erl
index 159678a1f9..7bb0fc2018 100644
--- a/lib/debugger/test/int_break_SUITE.erl
+++ b/lib/debugger/test/int_break_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,6 +76,9 @@ basic(Config) when list(Config) ->
?line S3 = [xxx,y] = ordsets1:add_element(y, S2),
?line ok = i:ib(ordsets1, union, 2),
?line [xxx,y,z] = ordsets1:union(S3, [z]),
+ All = [{{ordsets1,86}, _}, {{ordsets1,_},_}|_] = lists:sort(int:all_breaks()),
+ [] = lists:sort(int:all_breaks(foobar)),
+ All = lists:sort(int:all_breaks(ordsets1)),
ok.
cleanup(doc) -> "Make sure that the auto-attach flag is turned off.";
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 90f83e80e8..c9ac6931e2 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
@@ -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
diff --git a/lib/debugger/test/test_lib.erl b/lib/debugger/test/test_lib.erl
index 5e4ac7f164..29b26343e8 100644
--- a/lib/debugger/test/test_lib.erl
+++ b/lib/debugger/test/test_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
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index 0f70dafc19..5b572f5f20 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 3.2.6
+DEBUGGER_VSN = 3.2.8
diff --git a/lib/dialyzer/doc/src/Makefile b/lib/dialyzer/doc/src/Makefile
index 45b0ffa5ff..a827281cc5 100755..100644
--- a/lib/dialyzer/doc/src/Makefile
+++ b/lib/dialyzer/doc/src/Makefile
@@ -100,13 +100,13 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/dialyzer/doc/src/book.xml b/lib/dialyzer/doc/src/book.xml
index 0b4e1cb617..ec06427671 100755..100644
--- a/lib/dialyzer/doc/src/book.xml
+++ b/lib/dialyzer/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/dialyzer/doc/src/fascicules.xml b/lib/dialyzer/doc/src/fascicules.xml
index 0678195e07..0678195e07 100755..100644
--- a/lib/dialyzer/doc/src/fascicules.xml
+++ b/lib/dialyzer/doc/src/fascicules.xml
diff --git a/lib/dialyzer/doc/src/make.dep b/lib/dialyzer/doc/src/make.dep
deleted file mode 100755
index f8177cd419..0000000000
--- a/lib/dialyzer/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex dialyzer.tex dialyzer_chapter.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 17291b24f7..934cdba437 100755..100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -31,6 +31,109 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 2.5.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Handle <c>nowarn_unused_function</c> the same way as
+ the compiler does. </p>
+ <p>
+ Own Id: OTP-9833</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix false warning about closure application</p>
+ <p>
+ Whenever a variable that could hold one of two or more
+ possible closures was used in a particular application,
+ the application was assumed to fail if ONE of the
+ closures would fail in this application. This has been
+ corrected to infer failing application if ALL possible
+ closures would fail in the particular application.</p>
+ <p>
+ Change category of 'might also return' warnings</p>
+ <p>
+ Dialyzer emits warnings like the following "The
+ specification for _ states that the function might also
+ return _ but the inferred return is _", which are
+ actually underspecifications and not wrong type
+ specifications. This patch makes sure that they are filed
+ under the appropriate category.</p>
+ <p>
+ Own Id: OTP-9707</p>
+ </item>
+ <item>
+ <p>Wrap up behaviours patch for Dialyzer</p> <list>
+ <item><p>Enable warnings by default, add two options for
+ suppressing them</p></item> <item><p>Fix warning
+ formatting and update testsuites.</p></item>
+ <item><p>Detection of callback-spec
+ discrepancies</p></item> <item><p>Allow none() as return
+ value in callbacks</p></item> <item><p>Behaviour callback
+ discrepancy detection for Dialyzer</p></item>
+ <item><p>Add lookup function for callbacks</p></item>
+ <item><p>Store callbacks in codeserver and PLT</p></item>
+ <item><p>Collect callback definitions during
+ compilation</p></item> <item><p>Update inets
+ results</p></item> </list>
+ <p>
+ Own Id: OTP-9731</p>
+ </item>
+ <item>
+ <p>
+ <list> <item><p>No warnings for underspecs with remote
+ types</p></item> <item><p> Fix crash in Typer</p></item>
+ <item><p>Fix Dialyzer's warning for its own
+ code</p></item> <item><p>Fix Dialyzer's warnings in
+ HiPE</p></item> <item><p>Add file/line info in a
+ particular Dialyzer crash</p></item> <item><p>Update
+ inets test results</p></item> </list></p>
+ <p>
+ Own Id: OTP-9758</p>
+ </item>
+ <item>
+ <p>
+ <list> <item><p>Correct callback spec in application
+ module</p></item> <item><p>Refine warning about callback
+ specs with extra ranges</p></item> <item><p>Cleanup
+ autoimport compiler directives</p></item> <item><p>Fix
+ Dialyzer's warnings in typer</p></item> <item><p>Fix
+ Dialyzer's warning for its own code</p></item>
+ <item><p>Fix bug in Dialyzer's behaviours
+ analysis</p></item> <item><p>Fix crash in
+ Dialyzer</p></item> <item><p>Variable substitution was
+ not generalizing any unknown variables.</p></item>
+ </list></p>
+ <p>
+ Own Id: OTP-9776</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Optimize the joining of maps in
+ <c>dialyzer_dataflow</c>. </p>
+ <p>
+ Own Id: OTP-9761</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 2.4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/doc/src/part.xml b/lib/dialyzer/doc/src/part.xml
index 4410840660..564ef3a52f 100755..100644
--- a/lib/dialyzer/doc/src/part.xml
+++ b/lib/dialyzer/doc/src/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/dialyzer/doc/src/part_notes.xml b/lib/dialyzer/doc/src/part_notes.xml
index cb048d55dd..992ee73daa 100755..100644
--- a/lib/dialyzer/doc/src/part_notes.xml
+++ b/lib/dialyzer/doc/src/part_notes.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/dialyzer/doc/src/ref_man.xml b/lib/dialyzer/doc/src/ref_man.xml
index ca5410f6b8..7e5367b7c5 100755..100644
--- a/lib/dialyzer/doc/src/ref_man.xml
+++ b/lib/dialyzer/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/dialyzer/info b/lib/dialyzer/info
index 9fba4b54ad..9fba4b54ad 100755..100644
--- a/lib/dialyzer/info
+++ b/lib/dialyzer/info
diff --git a/lib/dialyzer/src/Makefile b/lib/dialyzer/src/Makefile
index 810f86dc21..63cc1c98f1 100644
--- a/lib/dialyzer/src/Makefile
+++ b/lib/dialyzer/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2010. All Rights Reserved.
+# Copyright Ericsson AB 2006-2012. All Rights Reserved.
#
# The 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,10 @@ MODULES = \
dialyzer_plt \
dialyzer_races \
dialyzer_succ_typings \
+ dialyzer_timing \
dialyzer_typesig \
+ dialyzer_coordinator \
+ dialyzer_worker \
dialyzer_utils
HRL_FILES= dialyzer.hrl dialyzer_gui_wx.hrl
@@ -86,7 +89,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
ifeq ($(NATIVE_LIBS_ENABLED),yes)
ERL_COMPILE_FLAGS += +native
endif
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_unused_import +warn_untyped_record +warn_missing_spec
+ERL_COMPILE_FLAGS += +warn_exported_vars +warn_unused_import +warn_untyped_record +warn_missing_spec +warnings_as_errors
# ----------------------------------------------------
# Targets
@@ -152,10 +155,10 @@ $(EBIN)/dialyzer_utils.beam: dialyzer.hrl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(EXTRA_FILES) \
- $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(INSTALL_FILES) $(RELSYSDIR)/ebin
+ "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(INSTALL_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index 5014a4244c..3e3c12405f 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -442,23 +442,29 @@ message_to_string({opaque_type_test, [Fun, Opaque]}) ->
message_to_string({race_condition, [M, F, Args, Reason]}) ->
io_lib:format("The call ~w:~w~s ~s\n", [M, F, Args, Reason]);
%%----- Warnings for behaviour errors --------------------
-message_to_string({callback_type_mismatch, [B, F, A, O]}) ->
- io_lib:format("The inferred return type of the ~w/~w callback includes the"
- " type ~s which is not a valid return for the ~w behaviour\n",
- [F, A, erl_types:t_to_string(O), B]);
-message_to_string({callback_arg_type_mismatch, [B, F, A, N, O]}) ->
- io_lib:format("The inferred type of the ~s argument of ~w/~w callback"
- " includes the type ~s which is not valid for the ~w behaviour"
- "\n", [ordinal(N), F, A, erl_types:t_to_string(O), B]);
+message_to_string({callback_type_mismatch, [B, F, A, ST, CT]}) ->
+ io_lib:format("The inferred return type of ~w/~w (~s) has nothing in common"
+ " with ~s, which is the expected return type for the callback of"
+ " ~w behaviour\n", [F, A, ST, CT, B]);
+message_to_string({callback_arg_type_mismatch, [B, F, A, N, ST, CT]}) ->
+ io_lib:format("The inferred type for the ~s argument of ~w/~w (~s) is"
+ " not a supertype of ~s, which is expected type for this"
+ " argument in the callback of the ~w behaviour\n",
+ [ordinal(N), F, A, ST, CT, B]);
+message_to_string({callback_spec_type_mismatch, [B, F, A, ST, CT]}) ->
+ io_lib:format("The return type ~s in the specification of ~w/~w is not a"
+ " subtype of ~s, which is the expected return type for the"
+ " callback of ~w behaviour\n", [ST, F, A, CT, B]);
+message_to_string({callback_spec_arg_type_mismatch, [B, F, A, N, ST, CT]}) ->
+ io_lib:format("The specified type for the ~s argument of ~w/~w (~s) is"
+ " not a supertype of ~s, which is expected type for this"
+ " argument in the callback of the ~w behaviour\n",
+ [ordinal(N), F, A, ST, CT, B]);
message_to_string({callback_missing, [B, F, A]}) ->
io_lib:format("Undefined callback function ~w/~w (behaviour '~w')\n",
[F, A, B]);
-message_to_string({invalid_spec, [B, F, A, R]}) ->
- io_lib:format("The spec for the ~w:~w/~w callback is not correct: ~s\n",
- [B, F, A, R]);
-message_to_string({spec_missing, [B, F, A]}) ->
- io_lib:format("Type info about ~w:~w/~w callback is not available\n",
- [B, F, A]).
+message_to_string({callback_info_missing, [B]}) ->
+ io_lib:format("Callback info about the ~w behaviour is not available\n", [B]).
%%-----------------------------------------------------------------------------
%% Auxiliary functions below
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl
index 9d2e554981..105a174e31 100644
--- a/lib/dialyzer/src/dialyzer.hrl
+++ b/lib/dialyzer/src/dialyzer.hrl
@@ -2,7 +2,7 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%%
%%% The 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 @@
-define(WARN_UNMATCHED_RETURN, warn_umatched_return).
-define(WARN_RACE_CONDITION, warn_race_condition).
-define(WARN_BEHAVIOUR, warn_behaviour).
+-define(WARN_UNDEFINED_CALLBACK, warn_undefined_callbacks).
%%
%% The following type has double role:
@@ -71,7 +72,8 @@
| ?WARN_CONTRACT_NOT_EQUAL | ?WARN_CONTRACT_SUBTYPE
| ?WARN_CONTRACT_SUPERTYPE | ?WARN_CALLGRAPH
| ?WARN_UNMATCHED_RETURN | ?WARN_RACE_CONDITION
- | ?WARN_BEHAVIOUR | ?WARN_CONTRACT_RANGE.
+ | ?WARN_BEHAVIOUR | ?WARN_CONTRACT_RANGE
+ | ?WARN_UNDEFINED_CALLBACK.
%%
%% This is the representation of each warning as they will be returned
@@ -108,6 +110,8 @@
-type label() :: non_neg_integer().
-type rep_mode() :: 'quiet' | 'normal' | 'verbose'.
-type start_from() :: 'byte_code' | 'src_code'.
+-type mfa_or_funlbl() :: label() | mfa().
+-type solver() :: 'v1' | 'v2'.
%%--------------------------------------------------------------------
%% Record declarations used by various files
@@ -124,11 +128,15 @@
use_contracts = true :: boolean(),
race_detection = false :: boolean(),
behaviours_chk = false :: boolean(),
- callgraph_file = "" :: file:filename()}).
+ timing = false :: boolean() | 'debug',
+ timing_server :: dialyzer_timing:timing_server(),
+ callgraph_file = "" :: file:filename(),
+ solvers :: [solver()]}).
-record(options, {files = [] :: [file:filename()],
files_rec = [] :: [file:filename()],
analysis_type = succ_typings :: anal_type1(),
+ timing = false :: boolean() | 'debug',
defines = [] :: [dial_define()],
from = byte_code :: start_from(),
get_warnings = maybe :: boolean() | 'maybe',
@@ -143,10 +151,20 @@
output_format = formatted :: format(),
filename_opt = basename :: fopt(),
callgraph_file = "" :: file:filename(),
- check_plt = true :: boolean()}).
+ check_plt = true :: boolean(),
+ solvers = [] :: [solver()]}).
-record(contract, {contracts = [] :: [contract_pair()],
args = [] :: [erl_types:erl_type()],
forms = [] :: [{_, _}]}).
%%--------------------------------------------------------------------
+
+-define(timing(Server, Msg, Var, Expr),
+ begin
+ dialyzer_timing:start_stamp(Server, Msg),
+ Var = Expr,
+ dialyzer_timing:end_stamp(Server),
+ Var
+ end).
+-define(timing(Server, Msg, Expr),?timing(Server, Msg, _T, Expr)).
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index abad1f3a75..c237d4e0e9 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -2,7 +2,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,15 @@
-export([start/3]).
+-export([compile_init_result/0,
+ add_to_result/4,
+ start_compilation/2,
+ continue_compilation/2]).
+
+-export_type([compile_init_data/0,
+ one_file_result/0,
+ compile_result/0]).
+
-include("dialyzer.hrl").
-record(analysis_state,
@@ -44,7 +53,8 @@
plt :: dialyzer_plt:plt(),
start_from = byte_code :: start_from(),
use_contracts = true :: boolean(),
- behaviours = {false,[]} :: {boolean(),[atom()]}
+ timing_server :: dialyzer_timing:timing_server(),
+ solvers :: [solver()]
}).
-record(server_state, {parent :: pid(), legal_warnings :: [dial_warn_tag()]}).
@@ -56,14 +66,15 @@
-spec start(pid(), [dial_warn_tag()], #analysis{}) -> 'ok'.
start(Parent, LegalWarnings, Analysis) ->
+ TimingServer = dialyzer_timing:init(Analysis#analysis.timing),
RacesOn = ordsets:is_element(?WARN_RACE_CONDITION, LegalWarnings),
- BehavOn = ordsets:is_element(?WARN_BEHAVIOUR, LegalWarnings),
- Analysis0 = Analysis#analysis{race_detection = RacesOn,
- behaviours_chk = BehavOn},
+ Analysis0 =
+ Analysis#analysis{race_detection = RacesOn, timing_server = TimingServer},
Analysis1 = expand_files(Analysis0),
Analysis2 = run_analysis(Analysis1),
State = #server_state{parent = Parent, legal_warnings = LegalWarnings},
- loop(State, Analysis2, none).
+ loop(State, Analysis2, none),
+ dialyzer_timing:stop(TimingServer).
run_analysis(Analysis) ->
Self = self(),
@@ -126,7 +137,8 @@ analysis_start(Parent, Analysis) ->
parent = Parent,
start_from = Analysis#analysis.start_from,
use_contracts = Analysis#analysis.use_contracts,
- behaviours = {Analysis#analysis.behaviours_chk, []}
+ timing_server = Analysis#analysis.timing_server,
+ solvers = Analysis#analysis.solvers
},
Files = ordsets:from_list(Analysis#analysis.files),
{Callgraph, NoWarn, TmpCServer0} = compile_and_store(Files, State),
@@ -150,7 +162,8 @@ analysis_start(Parent, Analysis) ->
dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes,
TmpCServer1),
TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2),
- dialyzer_contracts:process_contract_remote_types(TmpCServer3)
+ ?timing(State#analysis_state.timing_server, "remote",
+ dialyzer_contracts:process_contract_remote_types(TmpCServer3))
catch
throw:{error, _ErrorMsg} = Error -> exit(Error)
end,
@@ -171,83 +184,75 @@ analysis_start(Parent, Analysis) ->
false -> Callgraph
end,
State3 = analyze_callgraph(NewCallgraph, State2#analysis_state{plt = Plt1}),
+ dialyzer_callgraph:dispose_race_server(NewCallgraph),
rcv_and_send_ext_types(Parent),
NonExports = sets:subtract(sets:from_list(AllNodes), Exports),
NonExportsList = sets:to_list(NonExports),
- Plt3 = dialyzer_plt:delete_list(State3#analysis_state.plt, NonExportsList),
- Plt4 = dialyzer_plt:delete_contract_list(Plt3, NonExportsList),
+ Plt2 = dialyzer_plt:delete_list(State3#analysis_state.plt, NonExportsList),
send_codeserver_plt(Parent, CServer, State3#analysis_state.plt),
- send_analysis_done(Parent, Plt4, State3#analysis_state.doc_plt).
-
-analyze_callgraph(Callgraph, State) ->
- Plt = State#analysis_state.plt,
- Codeserver = State#analysis_state.codeserver,
- Parent = State#analysis_state.parent,
- case State#analysis_state.analysis_type of
- plt_build ->
- Callgraph1 = dialyzer_callgraph:finalize(Callgraph),
- NewPlt = dialyzer_succ_typings:analyze_callgraph(Callgraph1, Plt,
- Codeserver, Parent),
- dialyzer_callgraph:delete(Callgraph1),
- State#analysis_state{plt = NewPlt};
- succ_typings ->
- NoWarn = State#analysis_state.no_warn_unused,
- {BehavioursChk, _Known} = State#analysis_state.behaviours,
- DocPlt = State#analysis_state.doc_plt,
- Callgraph1 = dialyzer_callgraph:finalize(Callgraph),
- {Warnings, NewPlt, NewDocPlt} =
- dialyzer_succ_typings:get_warnings(Callgraph1, Plt, DocPlt,
- Codeserver, NoWarn, Parent,
- BehavioursChk),
- dialyzer_callgraph:delete(Callgraph1),
- send_warnings(State#analysis_state.parent, Warnings),
- State#analysis_state{plt = NewPlt, doc_plt = NewDocPlt}
- end.
+ send_analysis_done(Parent, Plt2, State3#analysis_state.doc_plt).
+
+analyze_callgraph(Callgraph, #analysis_state{codeserver = Codeserver,
+ doc_plt = DocPlt,
+ timing_server = TimingServer,
+ parent = Parent,
+ solvers = Solvers} = State) ->
+ Plt = dialyzer_plt:insert_callbacks(State#analysis_state.plt, Codeserver),
+ {NewPlt, NewDocPlt} =
+ case State#analysis_state.analysis_type of
+ plt_build ->
+ NewPlt0 =
+ dialyzer_succ_typings:analyze_callgraph(Callgraph, Plt, Codeserver,
+ TimingServer, Solvers, Parent),
+ {NewPlt0, DocPlt};
+ succ_typings ->
+ NoWarn = State#analysis_state.no_warn_unused,
+ {Warnings, NewPlt0, NewDocPlt0} =
+ dialyzer_succ_typings:get_warnings(Callgraph, Plt, DocPlt, Codeserver,
+ NoWarn, TimingServer, Solvers, Parent),
+ send_warnings(State#analysis_state.parent, Warnings),
+ {NewPlt0, NewDocPlt0}
+ end,
+ dialyzer_callgraph:delete(Callgraph),
+ State#analysis_state{plt = NewPlt, doc_plt = NewDocPlt}.
%%--------------------------------------------------------------------
%% Build the callgraph and fill the codeserver.
%%--------------------------------------------------------------------
+-record(compile_init,{
+ callgraph :: dialyzer_callgraph:callgraph(),
+ codeserver :: dialyzer_codeserver:codeserver(),
+ defines = [] :: [dial_define()],
+ include_dirs = [] :: [file:filename()],
+ start_from = byte_code :: start_from(),
+ use_contracts = true :: boolean()
+ }).
+
+make_compile_init(#analysis_state{codeserver = Codeserver,
+ defines = Defs,
+ include_dirs = Dirs,
+ use_contracts = UseContracts,
+ start_from = StartFrom}, Callgraph) ->
+ #compile_init{callgraph = Callgraph,
+ codeserver = Codeserver,
+ defines = [{d, Macro, Val} || {Macro, Val} <- Defs],
+ include_dirs = [{i, D} || D <- Dirs],
+ use_contracts = UseContracts,
+ start_from = StartFrom}.
+
compile_and_store(Files, #analysis_state{codeserver = CServer,
- defines = Defs,
- include_dirs = Dirs,
- parent = Parent,
- use_contracts = UseContracts,
- start_from = StartFrom,
- behaviours = {BehChk, _}
- } = State) ->
+ timing_server = Timing,
+ parent = Parent} = State) ->
send_log(Parent, "Reading files and computing callgraph... "),
{T1, _} = statistics(runtime),
- Includes = [{i, D} || D <- Dirs],
- Defines = [{d, Macro, Val} || {Macro, Val} <- Defs],
Callgraph = dialyzer_callgraph:new(),
- Fun = case StartFrom of
- src_code ->
- fun(File, {TmpCG, TmpCServer, TmpFailed, TmpNoWarn, TmpMods}) ->
- case compile_src(File, Includes, Defines, TmpCG,
- TmpCServer, UseContracts) of
- {error, Reason} ->
- {TmpCG, TmpCServer, [{File, Reason}|TmpFailed], TmpNoWarn,
- TmpMods};
- {ok, NewCG, NoWarn, NewCServer, Mod} ->
- {NewCG, NewCServer, TmpFailed, NoWarn++TmpNoWarn,
- [Mod|TmpMods]}
- end
- end;
- byte_code ->
- fun(File, {TmpCG, TmpCServer, TmpFailed, TmpNoWarn, TmpMods}) ->
- case compile_byte(File, TmpCG, TmpCServer, UseContracts) of
- {error, Reason} ->
- {TmpCG, TmpCServer, [{File, Reason}|TmpFailed], TmpNoWarn,
- TmpMods};
- {ok, NewCG, NoWarn, NewCServer, Mod} ->
- {NewCG, NewCServer, TmpFailed, NoWarn++TmpNoWarn,
- [Mod|TmpMods]}
- end
- end
- end,
- {NewCallgraph1, NewCServer, Failed, NoWarn, Modules} =
- lists:foldl(Fun, {Callgraph, CServer, [], [], []}, Files),
+ CompileInit = make_compile_init(State, Callgraph),
+ {{Failed, NoWarn, Modules}, NextLabel} =
+ ?timing(Timing, "compile", _C1,
+ dialyzer_coordinator:parallel_job(compile, Files,
+ CompileInit, Timing)),
+ CServer2 = dialyzer_codeserver:set_next_core_label(NextLabel, CServer),
case Failed =:= [] of
true ->
NewFiles = lists:zip(lists:reverse(Modules), Files),
@@ -263,47 +268,81 @@ compile_and_store(Files, #analysis_state{codeserver = CServer,
{T2, _} = statistics(runtime),
Msg1 = io_lib:format("done in ~.2f secs\nRemoving edges... ", [(T2-T1)/1000]),
send_log(Parent, Msg1),
- {KnownBehaviours, UnknownBehaviours} =
- dialyzer_behaviours:get_behaviours(Modules, NewCServer),
- if UnknownBehaviours =:= [] -> ok;
- true -> send_unknown_behaviours(Parent, UnknownBehaviours)
- end,
- State1 = State#analysis_state{behaviours = {BehChk, KnownBehaviours}},
- NewCallgraph2 = cleanup_callgraph(State1, NewCServer, NewCallgraph1, Modules),
+ Callgraph =
+ ?timing(Timing, "clean", _C2,
+ cleanup_callgraph(State, CServer2, Callgraph, Modules)),
{T3, _} = statistics(runtime),
Msg2 = io_lib:format("done in ~.2f secs\n", [(T3-T2)/1000]),
send_log(Parent, Msg2),
- {NewCallgraph2, sets:from_list(NoWarn), NewCServer}.
+ {Callgraph, sets:from_list(NoWarn), CServer2}.
+
+-type compile_init_data() :: #compile_init{}.
+-type error_reason() :: string().
+-type compile_result() :: {[{file:filename(), error_reason()}], [mfa()],
+ [module()]}. %%opaque
+-type one_file_result() :: {error, error_reason()} |
+ {ok, [dialyzer_callgraph:callgraph_edge()],
+ [mfa_or_funlbl()], [mfa()], module()}. %%opaque
+-type compile_mid_data() :: {module(), cerl:cerl(), [mfa()],
+ dialyzer_callgraph:callgraph(),
+ dialyzer_codeserver:codeserver()}.
+
+-spec compile_init_result() -> compile_result().
+
+compile_init_result() -> {[], [], []}.
+
+-spec add_to_result(file:filename(), one_file_result(), compile_result(),
+ compile_init_data()) -> compile_result().
+
+add_to_result(File, NewData, {Failed, NoWarn, Mods}, InitData) ->
+ case NewData of
+ {error, Reason} ->
+ {[{File, Reason}|Failed], NoWarn, Mods};
+ {ok, V, E, NewNoWarn, Mod} ->
+ Callgraph = InitData#compile_init.callgraph,
+ dialyzer_callgraph:add_edges(E, V, Callgraph),
+ {Failed, NewNoWarn ++ NoWarn, [Mod|Mods]}
+ end.
+
+-spec start_compilation(file:filename(), compile_init_data()) ->
+ {error, error_reason()} |{ok, integer(), compile_mid_data()}.
+
+start_compilation(File,
+ #compile_init{callgraph = Callgraph, codeserver = Codeserver,
+ defines = Defines, include_dirs = IncludeD,
+ use_contracts = UseContracts,
+ start_from = StartFrom}) ->
+ case StartFrom of
+ src_code ->
+ compile_src(File, IncludeD, Defines, Callgraph, Codeserver, UseContracts);
+ byte_code ->
+ compile_byte(File, Callgraph, Codeserver, UseContracts)
+ end.
cleanup_callgraph(#analysis_state{plt = InitPlt, parent = Parent,
- codeserver = CodeServer,
- behaviours = {BehChk, KnownBehaviours}
+ codeserver = CodeServer
},
CServer, Callgraph, Modules) ->
ModuleDeps = dialyzer_callgraph:module_deps(Callgraph),
send_mod_deps(Parent, ModuleDeps),
{Callgraph1, ExtCalls} = dialyzer_callgraph:remove_external(Callgraph),
- if BehChk ->
- RelevantAPICalls =
- dialyzer_behaviours:get_behaviour_apis(KnownBehaviours),
- BehaviourAPICalls = [Call || {_From, To} = Call <- ExtCalls,
- lists:member(To, RelevantAPICalls)],
- Callgraph2 =
- dialyzer_callgraph:put_behaviour_api_calls(BehaviourAPICalls,
- Callgraph1);
- true ->
- Callgraph2 = Callgraph1
- end,
+ RelevantAPICalls =
+ dialyzer_behaviours:get_behaviour_apis([gen_server]),
+ BehaviourAPICalls = [Call || {_From, To} = Call <- ExtCalls,
+ lists:member(To, RelevantAPICalls)],
+ Callgraph2 =
+ dialyzer_callgraph:put_behaviour_api_calls(BehaviourAPICalls,
+ Callgraph1),
ExtCalls1 = [Call || Call = {_From, To} <- ExtCalls,
not dialyzer_plt:contains_mfa(InitPlt, To)],
{BadCalls1, RealExtCalls} =
if ExtCalls1 =:= [] -> {[], []};
true ->
ModuleSet = sets:from_list(Modules),
- lists:partition(fun({_From, {M, _F, _A}}) ->
- sets:is_element(M, ModuleSet) orelse
- dialyzer_plt:contains_module(InitPlt, M)
- end, ExtCalls1)
+ PltModuleSet = dialyzer_plt:all_modules(InitPlt),
+ AllModules = sets:union(ModuleSet, PltModuleSet),
+ Pred = fun({_From, {M, _F, _A}}) -> sets:is_element(M, AllModules) end,
+ lists:partition(Pred, ExtCalls1)
end,
NonLocalCalls = dialyzer_callgraph:non_local_calls(Callgraph1),
BadCalls2 = [Call || Call = {_From, To} <- NonLocalCalls,
@@ -325,81 +364,75 @@ compile_src(File, Includes, Defines, Callgraph, CServer, UseContracts) ->
case dialyzer_utils:get_abstract_code_from_src(File, CompOpts) of
{error, _Msg} = Error -> Error;
{ok, AbstrCode} ->
- case dialyzer_utils:get_core_from_abstract_code(AbstrCode, CompOpts) of
- error -> {error, " Could not find abstract code for: " ++ File};
- {ok, Core} ->
- Mod = cerl:concrete(cerl:module_name(Core)),
- NoWarn = abs_get_nowarn(AbstrCode, Mod),
- case dialyzer_utils:get_record_and_type_info(AbstrCode) of
- {error, _} = Error -> Error;
- {ok, RecInfo} ->
- CServer2 =
- dialyzer_codeserver:store_temp_records(Mod, RecInfo, CServer),
- case UseContracts of
- true ->
- case dialyzer_utils:get_spec_info(Mod, AbstrCode, RecInfo) of
- {error, _} = Error -> Error;
- {ok, SpecInfo} ->
- CServer3 =
- dialyzer_codeserver:store_temp_contracts(Mod,
- SpecInfo,
- CServer2),
- store_core(Mod, Core, NoWarn, Callgraph, CServer3)
- end;
- false ->
- store_core(Mod, Core, NoWarn, Callgraph, CServer2)
- end
- end
- end
+ compile_common(File, AbstrCode, CompOpts, Callgraph, CServer, UseContracts)
end.
compile_byte(File, Callgraph, CServer, UseContracts) ->
case dialyzer_utils:get_abstract_code_from_beam(File) of
error ->
{error, " Could not get abstract code for: " ++ File ++ "\n" ++
- " Recompile with +debug_info or analyze starting from source code"};
+ " Recompile with +debug_info or analyze starting from source code"};
{ok, AbstrCode} ->
- case dialyzer_utils:get_core_from_abstract_code(AbstrCode) of
- error -> {error, " Could not get core for: "++File};
- {ok, Core} ->
- Mod = cerl:concrete(cerl:module_name(Core)),
- NoWarn = abs_get_nowarn(AbstrCode, Mod),
- case dialyzer_utils:get_record_and_type_info(AbstrCode) of
- {error, _} = Error -> Error;
- {ok, RecInfo} ->
- CServer1 =
- dialyzer_codeserver:store_temp_records(Mod, RecInfo, CServer),
- case UseContracts of
- true ->
- case dialyzer_utils:get_spec_info(Mod, AbstrCode, RecInfo) of
- {error, _} = Error -> Error;
- {ok, SpecInfo} ->
- CServer2 =
- dialyzer_codeserver:store_temp_contracts(Mod, SpecInfo,
- CServer1),
- store_core(Mod, Core, NoWarn, Callgraph, CServer2)
- end;
- false ->
- store_core(Mod, Core, NoWarn, Callgraph, CServer1)
- end
+ compile_common(File, AbstrCode, [], Callgraph, CServer, UseContracts)
+ end.
+
+compile_common(File, AbstrCode, CompOpts, Callgraph, CServer, UseContracts) ->
+ case dialyzer_utils:get_core_from_abstract_code(AbstrCode, CompOpts) of
+ error -> {error, " Could not get core Erlang code for: " ++ File};
+ {ok, Core} ->
+ Mod = cerl:concrete(cerl:module_name(Core)),
+ NoWarn = abs_get_nowarn(AbstrCode, Mod),
+ case dialyzer_utils:get_record_and_type_info(AbstrCode) of
+ {error, _} = Error -> Error;
+ {ok, RecInfo} ->
+ CServer1 =
+ dialyzer_codeserver:store_temp_records(Mod, RecInfo, CServer),
+ case UseContracts of
+ true ->
+ case dialyzer_utils:get_spec_info(Mod, AbstrCode, RecInfo) of
+ {error, _} = Error -> Error;
+ {ok, SpecInfo, CallbackInfo} ->
+ CServer2 =
+ dialyzer_codeserver:store_temp_contracts(Mod, SpecInfo,
+ CallbackInfo,
+ CServer1),
+ store_core(Mod, Core, NoWarn, Callgraph, CServer2)
+ end;
+ false ->
+ store_core(Mod, Core, NoWarn, Callgraph, CServer1)
end
end
end.
store_core(Mod, Core, NoWarn, Callgraph, CServer) ->
Exp = get_exports_from_core(Core),
- OldExpTypes = dialyzer_codeserver:get_temp_exported_types(CServer),
- NewExpTypes = get_exported_types_from_core(Core),
- MergedExpTypes = sets:union(NewExpTypes, OldExpTypes),
- CServer1 = dialyzer_codeserver:insert_exports(Exp, CServer),
- CServer2 = dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes,
- CServer1),
- {LabeledCore, CServer3} = label_core(Core, CServer2),
- store_code_and_build_callgraph(Mod, LabeledCore, Callgraph, CServer3, NoWarn).
+ ExpTypes = get_exported_types_from_core(Core),
+ CServer = dialyzer_codeserver:insert_exports(Exp, CServer),
+ CServer = dialyzer_codeserver:insert_temp_exported_types(ExpTypes, CServer),
+ CoreTree = cerl:from_records(Core),
+ {ok, cerl_trees:size(CoreTree), {Mod, CoreTree, NoWarn, Callgraph, CServer}}.
+
+-spec continue_compilation(integer(), compile_mid_data()) -> one_file_result().
+
+continue_compilation(NextLabel, {Mod, CoreTree, NoWarn, Callgraph, CServer}) ->
+ {LabeledTree, _NewNextLabel} = cerl_trees:label(CoreTree, NextLabel),
+ LabeledCore = cerl:to_records(LabeledTree),
+ store_code_and_build_callgraph(Mod, LabeledCore, Callgraph, NoWarn, CServer).
abs_get_nowarn(Abs, M) ->
- [{M, F, A}
- || {attribute, _, compile, {nowarn_unused_function, {F, A}}} <- Abs].
+ Opts = lists:flatten([C || {attribute, _, compile, C} <- Abs]),
+ Warn = erl_lint:bool_option(warn_unused_function, nowarn_unused_function,
+ true, Opts),
+ case Warn of
+ false ->
+ [{M, F, A} || {function, _, F, A, _} <- Abs]; % all functions
+ true ->
+ OnLoad =
+ lists:flatten([{M, F, A} || {attribute, _, on_load, {F, A}} <- Abs]),
+ OnLoad ++ [{M, F, A} ||
+ {nowarn_unused_function, FAs} <- Opts,
+ {F, A} <- lists:flatten([FAs])]
+ end.
get_exported_types_from_core(Core) ->
Attrs = cerl:module_attrs(Core),
@@ -417,18 +450,11 @@ get_exports_from_core(Core) ->
M = cerl:atom_val(cerl:module_name(Tree)),
[{M, F, A} || {F, A} <- Exports2].
-label_core(Core, CServer) ->
- NextLabel = dialyzer_codeserver:get_next_core_label(CServer),
- CoreTree = cerl:from_records(Core),
- {LabeledTree, NewNextLabel} = cerl_trees:label(CoreTree, NextLabel),
- {cerl:to_records(LabeledTree),
- dialyzer_codeserver:set_next_core_label(NewNextLabel, CServer)}.
-
-store_code_and_build_callgraph(Mod, Core, Callgraph, CServer, NoWarn) ->
+store_code_and_build_callgraph(Mod, Core, Callgraph, NoWarn, CServer) ->
CoreTree = cerl:from_records(Core),
- NewCallgraph = dialyzer_callgraph:scan_core_tree(CoreTree, Callgraph),
- CServer2 = dialyzer_codeserver:insert(Mod, CoreTree, CServer),
- {ok, NewCallgraph, NoWarn, CServer2, Mod}.
+ {Vertices, Edges} = dialyzer_callgraph:scan_core_tree(CoreTree, Callgraph),
+ CServer = dialyzer_codeserver:insert(Mod, CoreTree, CServer),
+ {ok, Vertices, Edges, NoWarn, Mod}.
%%--------------------------------------------------------------------
%% Utilities
@@ -492,9 +518,12 @@ default_includes(Dir) ->
rcv_and_send_ext_types(Parent) ->
Self = self(),
Self ! {Self, done},
- ExtTypes = rcv_ext_types(Self, []),
- Parent ! {Self, ext_types, ExtTypes},
- ok.
+ case rcv_ext_types(Self, []) of
+ [] -> ok;
+ ExtTypes ->
+ Parent ! {Self, ext_types, ExtTypes},
+ ok
+ end.
rcv_ext_types(Self, ExtTypes) ->
receive
diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl
index 47ce9ba6eb..b84071b95c 100644
--- a/lib/dialyzer/src/dialyzer_behaviours.erl
+++ b/lib/dialyzer/src/dialyzer_behaviours.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The 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 @@
-module(dialyzer_behaviours).
--export([check_callbacks/4, get_behaviours/2, get_behaviour_apis/1,
+-export([check_callbacks/5, get_behaviour_apis/1,
translate_behaviour_api_call/5, translatable_behaviours/1,
translate_callgraph/3]).
@@ -47,21 +47,16 @@
-record(state, {plt :: dialyzer_plt:plt(),
codeserver :: dialyzer_codeserver:codeserver(),
filename :: file:filename(),
- behlines :: [{behaviour(), non_neg_integer()}]}).
+ behlines :: [{behaviour(), non_neg_integer()}],
+ records :: dict()}).
%%--------------------------------------------------------------------
--spec get_behaviours([module()], dialyzer_codeserver:codeserver()) ->
- {[behaviour()], [behaviour()]}.
-
-get_behaviours(Modules, Codeserver) ->
- get_behaviours(Modules, Codeserver, [], []).
-
--spec check_callbacks(module(), [{cerl:cerl(), cerl:cerl()}],
+-spec check_callbacks(module(), [{cerl:cerl(), cerl:cerl()}], dict(),
dialyzer_plt:plt(),
dialyzer_codeserver:codeserver()) -> [dial_warning()].
-check_callbacks(Module, Attrs, Plt, Codeserver) ->
+check_callbacks(Module, Attrs, Records, Plt, Codeserver) ->
{Behaviours, BehLines} = get_behaviours(Attrs),
case Behaviours of
[] -> [];
@@ -69,12 +64,169 @@ check_callbacks(Module, Attrs, Plt, Codeserver) ->
MFA = {Module,module_info,0},
{_Var,Code} = dialyzer_codeserver:lookup_mfa_code(MFA, Codeserver),
File = get_file(cerl:get_ann(Code)),
- State = #state{plt = Plt, codeserver = Codeserver, filename = File,
- behlines = BehLines},
+ State = #state{plt = Plt, filename = File, behlines = BehLines,
+ codeserver = Codeserver, records = Records},
Warnings = get_warnings(Module, Behaviours, State),
[add_tag_file_line(Module, W, State) || W <- Warnings]
end.
+%%--------------------------------------------------------------------
+
+get_behaviours(Attrs) ->
+ BehaviourListsAndLine =
+ [{cerl:concrete(L2), hd(cerl:get_ann(L2))} ||
+ {L1, L2} <- Attrs, cerl:is_literal(L1),
+ cerl:is_literal(L2), cerl:concrete(L1) =:= 'behaviour' orelse
+ cerl:concrete(L1) =:= 'behavior'],
+ Behaviours = lists:append([Behs || {Behs,_} <- BehaviourListsAndLine]),
+ BehLines = [{B,L} || {L1,L} <- BehaviourListsAndLine, B <- L1],
+ {Behaviours, BehLines}.
+
+get_warnings(Module, Behaviours, State) ->
+ get_warnings(Module, Behaviours, State, []).
+
+get_warnings(_, [], _, Acc) ->
+ Acc;
+get_warnings(Module, [Behaviour|Rest], State, Acc) ->
+ NewAcc = check_behaviour(Module, Behaviour, State, Acc),
+ get_warnings(Module, Rest, State, NewAcc).
+
+check_behaviour(Module, Behaviour, #state{plt = Plt} = State, Acc) ->
+ case dialyzer_plt:lookup_callbacks(Plt, Behaviour) of
+ none -> [{callback_info_missing, [Behaviour]}|Acc];
+ {value, Callbacks} ->
+ check_all_callbacks(Module, Behaviour, Callbacks, State, Acc)
+ end.
+
+check_all_callbacks(_Module, _Behaviour, [], _State, Acc) ->
+ Acc;
+check_all_callbacks(Module, Behaviour, [Cb|Rest],
+ #state{plt = Plt, codeserver = Codeserver,
+ records = Records} = State, Acc) ->
+ {{Behaviour, Function, Arity},
+ {{_BehFile, _BehLine}, Callback}} = Cb,
+ CbMFA = {Module, Function, Arity},
+ CbReturnType = dialyzer_contracts:get_contract_return(Callback),
+ CbArgTypes = dialyzer_contracts:get_contract_args(Callback),
+ Acc0 = Acc,
+ Acc1 =
+ case dialyzer_plt:lookup(Plt, CbMFA) of
+ 'none' -> [{callback_missing, [Behaviour, Function, Arity]}|Acc0];
+ {'value', RetArgTypes} ->
+ Acc00 = Acc0,
+ {ReturnType, ArgTypes} = RetArgTypes,
+ Acc01 =
+ case erl_types:t_is_subtype(ReturnType, CbReturnType) of
+ true -> Acc00;
+ false ->
+ case erl_types:t_is_none(
+ erl_types:t_inf(ReturnType, CbReturnType)) of
+ false -> Acc00;
+ true ->
+ [{callback_type_mismatch,
+ [Behaviour, Function, Arity,
+ erl_types:t_to_string(ReturnType, Records),
+ erl_types:t_to_string(CbReturnType, Records)]}|Acc00]
+ end
+ end,
+ Acc02 =
+ case erl_types:any_none(
+ erl_types:t_inf_lists(ArgTypes, CbArgTypes)) of
+ false -> Acc01;
+ true ->
+ find_mismatching_args(type, ArgTypes, CbArgTypes, Behaviour,
+ Function, Arity, Records, 1, Acc01)
+ end,
+ Acc02
+ end,
+ Acc2 =
+ case dialyzer_codeserver:lookup_mfa_contract(CbMFA, Codeserver) of
+ 'error' -> Acc1;
+ {ok, {{File, Line}, Contract}} ->
+ Acc10 = Acc1,
+ SpecReturnType0 = dialyzer_contracts:get_contract_return(Contract),
+ SpecArgTypes0 = dialyzer_contracts:get_contract_args(Contract),
+ SpecReturnType = erl_types:subst_all_vars_to_any(SpecReturnType0),
+ SpecArgTypes =
+ [erl_types:subst_all_vars_to_any(ArgT0) || ArgT0 <- SpecArgTypes0],
+ Acc11 =
+ case erl_types:t_is_subtype(SpecReturnType, CbReturnType) of
+ true -> Acc10;
+ false ->
+ ExtraType = erl_types:t_subtract(SpecReturnType, CbReturnType),
+ [{callback_spec_type_mismatch,
+ [File, Line, Behaviour, Function, Arity,
+ erl_types:t_to_string(ExtraType, Records),
+ erl_types:t_to_string(CbReturnType, Records)]}|Acc10]
+ end,
+ Acc12 =
+ case erl_types:any_none(
+ erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of
+ false -> Acc11;
+ true ->
+ find_mismatching_args({spec, File, Line}, SpecArgTypes,
+ CbArgTypes, Behaviour, Function,
+ Arity, Records, 1, Acc11)
+ end,
+ Acc12
+ end,
+ NewAcc = Acc2,
+ check_all_callbacks(Module, Behaviour, Rest, State, NewAcc).
+
+find_mismatching_args(_, [], [], _Beh, _Function, _Arity, _Records, _N, Acc) ->
+ Acc;
+find_mismatching_args(Kind, [Type|Rest], [CbType|CbRest], Behaviour,
+ Function, Arity, Records, N, Acc) ->
+ case erl_types:t_is_none(erl_types:t_inf(Type, CbType)) of
+ false ->
+ find_mismatching_args(Kind, Rest, CbRest, Behaviour, Function,
+ Arity, Records, N+1, Acc);
+ true ->
+ Info =
+ [Behaviour, Function, Arity, N,
+ erl_types:t_to_string(Type, Records),
+ erl_types:t_to_string(CbType, Records)],
+ NewAcc =
+ [case Kind of
+ type -> {callback_arg_type_mismatch, Info};
+ {spec, File, Line} ->
+ {callback_spec_arg_type_mismatch, [File, Line | Info]}
+ end | Acc],
+ find_mismatching_args(Kind, Rest, CbRest, Behaviour, Function,
+ Arity, Records, N+1, NewAcc)
+ end.
+
+add_tag_file_line(_Module, {Tag, [B|_R]} = Warn, State)
+ when Tag =:= callback_missing;
+ Tag =:= callback_info_missing ->
+ {B, Line} = lists:keyfind(B, 1, State#state.behlines),
+ Category =
+ case Tag of
+ callback_missing -> ?WARN_BEHAVIOUR;
+ callback_info_missing -> ?WARN_UNDEFINED_CALLBACK
+ end,
+ {Category, {State#state.filename, Line}, Warn};
+add_tag_file_line(_Module, {Tag, [File, Line|R]}, _State)
+ when Tag =:= callback_spec_type_mismatch;
+ Tag =:= callback_spec_arg_type_mismatch ->
+ {?WARN_BEHAVIOUR, {File, Line}, {Tag, R}};
+add_tag_file_line(Module, {_Tag, [_B, Fun, Arity|_R]} = Warn, State) ->
+ {_A, FunCode} =
+ dialyzer_codeserver:lookup_mfa_code({Module, Fun, Arity},
+ State#state.codeserver),
+ Anns = cerl:get_ann(FunCode),
+ FileLine = {get_file(Anns), get_line(Anns)},
+ {?WARN_BEHAVIOUR, FileLine, Warn}.
+
+get_line([Line|_]) when is_integer(Line) -> Line;
+get_line([_|Tail]) -> get_line(Tail);
+get_line([]) -> -1.
+
+get_file([{file, File}|_]) -> File;
+get_file([_|Tail]) -> get_file(Tail).
+
+%%-----------------------------------------------------------------------------
+
-spec translatable_behaviours(cerl:c_module()) -> behaviour_api_dict().
translatable_behaviours(Tree) ->
@@ -87,12 +239,12 @@ translatable_behaviours(Tree) ->
get_behaviour_apis(Behaviours) ->
get_behaviour_apis(Behaviours, []).
--spec translate_behaviour_api_call(dialyzer_races:mfa_or_funlbl(),
+-spec translate_behaviour_api_call(dialyzer_callgraph:mfa_or_funlbl(),
[erl_types:erl_type()],
[dialyzer_races:core_vars()],
module(),
behaviour_api_dict()) ->
- {dialyzer_races:mfa_or_funlbl(),
+ {dialyzer_callgraph:mfa_or_funlbl(),
[erl_types:erl_type()],
[dialyzer_races:core_vars()]}
| 'plain_call'.
@@ -128,187 +280,11 @@ translate_callgraph([{Behaviour,_}|Behaviours], Module, Callgraph) ->
DirectCalls = [{From, {Module, Fun, Arity}} ||
{From, To} <- UsedCalls,{API, {Fun, Arity, _Ord}} <- Calls,
To =:= API],
- NewCallgraph = dialyzer_callgraph:add_edges(DirectCalls, Callgraph),
- translate_callgraph(Behaviours, Module, NewCallgraph);
+ dialyzer_callgraph:add_edges(DirectCalls, Callgraph),
+ translate_callgraph(Behaviours, Module, Callgraph);
translate_callgraph([], _Module, Callgraph) ->
Callgraph.
-%%--------------------------------------------------------------------
-
-get_behaviours(Attrs) ->
- BehaviourListsAndLine = [{cerl:concrete(L2), hd(cerl:get_ann(L2))} ||
- {L1, L2} <- Attrs, cerl:is_literal(L1),
- cerl:is_literal(L2), cerl:concrete(L1) =:= 'behaviour'],
- Behaviours = lists:append([Behs || {Behs,_} <- BehaviourListsAndLine]),
- BehLines = [{B,L} || {L1,L} <- BehaviourListsAndLine, B <- L1],
- {Behaviours, BehLines}.
-
-get_warnings(Module, Behaviours, State) ->
- get_warnings(Module, Behaviours, State, []).
-
-get_warnings(_, [], _, Acc) ->
- Acc;
-get_warnings(Module, [Behaviour|Rest], State, Acc) ->
- Warnings = check_behaviour(Module, Behaviour, State),
- get_warnings(Module, Rest, State, Warnings ++ Acc).
-
-check_behaviour(Module, Behaviour, State) ->
- try
- Callbacks = Behaviour:behaviour_info(callbacks),
- Fun = fun({_,_,_}) -> true;
- (_) -> false
- end,
- case lists:any(Fun, Callbacks) of
- true -> check_all_callbacks(Module, Behaviour, Callbacks, State);
- false -> []
- end
- catch
- _:_ -> []
- end.
-
-check_all_callbacks(Module, Behaviour, Callbacks, State) ->
- check_all_callbacks(Module, Behaviour, Callbacks, State, []).
-
-check_all_callbacks(_Module, _Behaviour, [], _State, Acc) ->
- Acc;
-check_all_callbacks(Module, Behaviour, [{Fun, Arity, Spec}|Rest],
- #state{codeserver = CServer} = State, Acc) ->
- Records = dialyzer_codeserver:get_records(CServer),
- ExpTypes = dialyzer_codeserver:get_exported_types(CServer),
- case parse_spec(Spec, ExpTypes, Records) of
- {ok, Fun, Type} ->
- RetType = erl_types:t_fun_range(Type),
- ArgTypes = erl_types:t_fun_args(Type),
- Warns = check_callback(Module, Behaviour, Fun, Arity, RetType,
- ArgTypes, State#state.plt);
- Else ->
- Warns = [{invalid_spec, [Behaviour, Fun, Arity, reason_spec_error(Else)]}]
- end,
- check_all_callbacks(Module, Behaviour, Rest, State, Warns ++ Acc);
-check_all_callbacks(Module, Behaviour, [{Fun, Arity}|Rest], State, Acc) ->
- Warns = {spec_missing, [Behaviour, Fun, Arity]},
- check_all_callbacks(Module, Behaviour, Rest, State, [Warns|Acc]).
-
-parse_spec(String, ExpTypes, Records) ->
- case erl_scan:string(String) of
- {ok, Tokens, _} ->
- case erl_parse:parse(Tokens) of
- {ok, Form} ->
- case Form of
- {attribute, _, 'spec', {{Fun, _}, [TypeForm|_Constraint]}} ->
- MaybeRemoteType = erl_types:t_from_form(TypeForm),
- try
- Type = erl_types:t_solve_remote(MaybeRemoteType, ExpTypes,
- Records),
- {ok, Fun, Type}
- catch
- throw:{error,Msg} -> {spec_remote_error, Msg}
- end;
- _Other -> not_a_spec
- end;
- {error, {Line, _, Msg}} -> {spec_parser_error, Line, Msg}
- end;
- _Other ->
- lexer_error
- end.
-
-reason_spec_error({spec_remote_error, Msg}) ->
- io_lib:format("Remote type solver error: ~s. Make sure the behaviour source is included in the analysis or the plt",[Msg]);
-reason_spec_error(not_a_spec) ->
- "This is not a spec";
-reason_spec_error({spec_parser_error, Line, Msg}) ->
- io_lib:format("~s line of the spec: ~s", [ordinal(Line),Msg]);
-reason_spec_error(lexer_error) ->
- "Lexical error".
-
-ordinal(1) -> "1st";
-ordinal(2) -> "2nd";
-ordinal(3) -> "3rd";
-ordinal(N) when is_integer(N) -> io_lib:format("~wth",[N]).
-
-check_callback(Module, Behaviour, Fun, Arity, XRetType, XArgTypes, Plt) ->
- LookupType = dialyzer_plt:lookup(Plt, {Module, Fun, Arity}),
- case LookupType of
- {value, {Type,Args}} ->
- Warn1 = case unifiable(Type, XRetType) of
- [] -> [];
- Offenders ->
- [{callback_type_mismatch,
- [Behaviour, Fun, Arity, erl_types:t_sup(Offenders)]}]
- end,
- ZipArgs = lists:zip3(lists:seq(1, Arity), Args, XArgTypes),
- Warn2 = [{callback_arg_type_mismatch,
- [Behaviour, Fun, Arity, N,
- erl_types:t_sup(Offenders)]} ||
- {Offenders, N} <- [check_callback_1(V) || V <- ZipArgs],
- Offenders =/= []],
- Warn1 ++ Warn2;
- _ -> [{callback_missing, [Behaviour, Fun, Arity]}]
- end.
-
-check_callback_1({N, T1, T2}) ->
- {unifiable(T1, T2), N}.
-
-unifiable(Type1, Type2) ->
- List1 = erl_types:t_elements(Type1),
- List2 = erl_types:t_elements(Type2),
- [T || T <- List1,
- lists:all(fun(T1) ->
- erl_types:t_is_none(erl_types:t_inf(T, T1, opaque))
- end, List2)].
-
-add_tag_file_line(_Module, {Tag, [B|_R]} = Warn, State)
- when Tag =:= spec_missing;
- Tag =:= invalid_spec;
- Tag =:= callback_missing ->
- {B, Line} = lists:keyfind(B, 1, State#state.behlines),
- {?WARN_BEHAVIOUR, {State#state.filename, Line}, Warn};
-add_tag_file_line(Module, {_Tag, [_B, Fun, Arity|_R]} = Warn, State) ->
- {_A, FunCode} =
- dialyzer_codeserver:lookup_mfa_code({Module, Fun, Arity},
- State#state.codeserver),
- Anns = cerl:get_ann(FunCode),
- FileLine = {get_file(Anns), get_line(Anns)},
- {?WARN_BEHAVIOUR, FileLine, Warn}.
-
-get_line([Line|_]) when is_integer(Line) -> Line;
-get_line([_|Tail]) -> get_line(Tail);
-get_line([]) -> -1.
-
-get_file([{file, File}|_]) -> File;
-get_file([_|Tail]) -> get_file(Tail).
-
-%%-----------------------------------------------------------------------------
-
-get_behaviours([], _Codeserver, KnownAcc, UnknownAcc) ->
- {KnownAcc, UnknownAcc};
-get_behaviours([M|Rest], Codeserver, KnownAcc, UnknownAcc) ->
- Tree = dialyzer_codeserver:lookup_mod_code(M, Codeserver),
- Attrs = cerl:module_attrs(Tree),
- {Behaviours, _BehLines} = get_behaviours(Attrs),
- {Known, Unknown} = call_behaviours(Behaviours),
- get_behaviours(Rest, Codeserver, Known ++ KnownAcc, Unknown ++ UnknownAcc).
-
-call_behaviours(Behaviours) ->
- call_behaviours(Behaviours, [], []).
-call_behaviours([], KnownAcc, UnknownAcc) ->
- {lists:reverse(KnownAcc), lists:reverse(UnknownAcc)};
-call_behaviours([Behaviour|Rest], KnownAcc, UnknownAcc) ->
- try
- Callbacks = Behaviour:behaviour_info(callbacks),
- Fun = fun({_,_,_}) -> true;
- (_) -> false
- end,
- case lists:any(Fun, Callbacks) of
- false -> call_behaviours(Rest, KnownAcc, [Behaviour | UnknownAcc]);
- true -> call_behaviours(Rest, [Behaviour | KnownAcc], UnknownAcc)
- end
- catch
- _:_ -> call_behaviours(Rest, KnownAcc, [Behaviour | UnknownAcc])
- end.
-
-%------------------------------------------------------------------------------
-
get_behaviour_apis([], Acc) ->
Acc;
get_behaviour_apis([Behaviour | Rest], Acc) ->
diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl
index d3de5aaf45..64e0ee88af 100644
--- a/lib/dialyzer/src/dialyzer_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_callgraph.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,7 @@
-module(dialyzer_callgraph).
-export([add_edges/2,
+ add_edges/3,
all_nodes/1,
delete/1,
finalize/1,
@@ -43,12 +44,15 @@
%% module_postorder/1,
module_postorder_from_funs/2,
new/0,
+ get_depends_on/2,
+ get_required_by/2,
in_neighbours/2,
renew_race_info/4,
+ renew_race_code/2,
+ renew_race_public_tables/2,
reset_from_funs/2,
scan_core_tree/2,
strip_module_deps/2,
- take_scc/1,
remove_external/1,
to_dot/2,
to_ps/3]).
@@ -57,15 +61,14 @@
get_race_code/1, get_race_detection/1, race_code_new/1,
put_digraph/2, put_race_code/2, put_race_detection/2,
put_named_tables/2, put_public_tables/2, put_behaviour_api_calls/2,
- get_behaviour_api_calls/1]).
+ get_behaviour_api_calls/1, dispose_race_server/1, duplicate/1]).
--export_type([callgraph/0]).
+-export_type([callgraph/0, mfa_or_funlbl/0, callgraph_edge/0]).
-include("dialyzer.hrl").
%%----------------------------------------------------------------------
--type mfa_or_funlbl() :: label() | mfa().
-type scc() :: [mfa_or_funlbl()].
-type mfa_calls() :: [{mfa_or_funlbl(), mfa_or_funlbl()}].
@@ -78,9 +81,6 @@
%% digraph - A digraph representing the callgraph.
%% Nodes are represented as MFAs or labels.
%% esc - A set of all escaping functions as reported by dialyzer_dep.
-%% postorder - A list of strongly connected components of the callgraph
-%% sorted in a topological bottom-up order.
-%% This is produced by calling finalize/1.
%% name_map - A mapping from label to MFA.
%% rev_name_map - A reverse mapping of the name_map.
%% rec_var_map - A dict mapping from letrec bound labels to function names.
@@ -91,29 +91,42 @@
%%-----------------------------------------------------------------------------
-record(callgraph, {digraph = digraph:new() :: digraph(),
- esc = sets:new() :: set(),
- name_map = dict:new() :: dict(),
- rev_name_map = dict:new() :: dict(),
- postorder = [] :: [scc()],
- rec_var_map = dict:new() :: dict(),
- self_rec = sets:new() :: set(),
- calls = dict:new() :: dict(),
- race_code = dict:new() :: dict(),
- public_tables = [] :: [label()],
- named_tables = [] :: [string()],
+ active_digraph :: active_digraph(),
+ esc :: ets:tid(),
+ name_map :: ets:tid(),
+ rev_name_map :: ets:tid(),
+ rec_var_map :: ets:tid(),
+ self_rec :: ets:tid(),
+ calls :: ets:tid(),
race_detection = false :: boolean(),
- beh_api_calls = [] :: [{mfa(), mfa()}]}).
+ race_data_server = new_race_data_server() :: pid()}).
+
+-record(race_data_state, {race_code = dict:new() :: dict(),
+ public_tables = [] :: [label()],
+ named_tables = [] :: [string()],
+ beh_api_calls = [] :: [{mfa(), mfa()}]}).
%% Exported Types
-type callgraph() :: #callgraph{}.
+-type active_digraph() :: {'d', digraph()} | {'e', ets:tid(), ets:tid()}.
+
%%----------------------------------------------------------------------
-spec new() -> callgraph().
new() ->
- #callgraph{}.
+ [ETSEsc, ETSNameMap, ETSRevNameMap, ETSRecVarMap, ETSSelfRec, ETSCalls] =
+ [ets:new(N,[public, {read_concurrency, true}]) ||
+ N <- [callgraph_esc, callgraph_name_map, callgraph_rev_name_map,
+ callgraph_rec_var_map, callgraph_self_rec, callgraph_calls]],
+ #callgraph{esc = ETSEsc,
+ name_map = ETSNameMap,
+ rev_name_map = ETSRevNameMap,
+ rec_var_map = ETSRecVarMap,
+ self_rec = ETSSelfRec,
+ calls = ETSCalls}.
-spec delete(callgraph()) -> 'true'.
@@ -129,32 +142,32 @@ all_nodes(#callgraph{digraph = DG}) ->
lookup_rec_var(Label, #callgraph{rec_var_map = RecVarMap})
when is_integer(Label) ->
- dict:find(Label, RecVarMap).
+ ets_lookup_dict(Label, RecVarMap).
-spec lookup_call_site(label(), callgraph()) -> 'error' | {'ok', [_]}. % XXX: refine
lookup_call_site(Label, #callgraph{calls = Calls})
when is_integer(Label) ->
- dict:find(Label, Calls).
+ ets_lookup_dict(Label, Calls).
-spec lookup_name(label(), callgraph()) -> 'error' | {'ok', mfa()}.
lookup_name(Label, #callgraph{name_map = NameMap})
when is_integer(Label) ->
- dict:find(Label, NameMap).
+ ets_lookup_dict(Label, NameMap).
-spec lookup_label(mfa_or_funlbl(), callgraph()) -> 'error' | {'ok', integer()}.
lookup_label({_,_,_} = MFA, #callgraph{rev_name_map = RevNameMap}) ->
- dict:find(MFA, RevNameMap);
+ ets_lookup_dict(MFA, RevNameMap);
lookup_label(Label, #callgraph{}) when is_integer(Label) ->
{ok, Label}.
-spec in_neighbours(mfa_or_funlbl(), callgraph()) -> 'none' | [mfa_or_funlbl(),...].
-in_neighbours(Label, #callgraph{digraph = Digraph, name_map = NameMap})
+in_neighbours(Label, #callgraph{digraph = Digraph} = CG)
when is_integer(Label) ->
- Name = case dict:find(Label, NameMap) of
+ Name = case lookup_name(Label, CG) of
{ok, Val} -> Val;
error -> Label
end,
@@ -165,39 +178,32 @@ in_neighbours({_, _, _} = MFA, #callgraph{digraph = Digraph}) ->
-spec is_self_rec(mfa_or_funlbl(), callgraph()) -> boolean().
is_self_rec(MfaOrLabel, #callgraph{self_rec = SelfRecs}) ->
- sets:is_element(MfaOrLabel, SelfRecs).
+ ets_lookup_set(MfaOrLabel, SelfRecs).
-spec is_escaping(label(), callgraph()) -> boolean().
is_escaping(Label, #callgraph{esc = Esc}) when is_integer(Label) ->
- sets:is_element(Label, Esc).
+ ets_lookup_set(Label, Esc).
-type callgraph_edge() :: {mfa_or_funlbl(),mfa_or_funlbl()}.
--spec add_edges([callgraph_edge()], callgraph()) -> callgraph().
+-spec add_edges([callgraph_edge()], callgraph()) -> ok.
-add_edges([], CG) ->
- CG;
-add_edges(Edges, #callgraph{digraph = Callgraph} = CG) ->
- CG#callgraph{digraph = digraph_add_edges(Edges, Callgraph)}.
+add_edges([], _CG) ->
+ ok;
+add_edges(Edges, #callgraph{digraph = Digraph}) ->
+ digraph_add_edges(Edges, Digraph).
--spec add_edges([callgraph_edge()], [mfa_or_funlbl()], callgraph()) -> callgraph().
+-spec add_edges([callgraph_edge()], [mfa_or_funlbl()], callgraph()) -> ok.
add_edges(Edges, MFAs, #callgraph{digraph = DG} = CG) ->
- DG1 = digraph_confirm_vertices(MFAs, DG),
- add_edges(Edges, CG#callgraph{digraph = DG1}).
-
--spec take_scc(callgraph()) -> 'none' | {'ok', scc(), callgraph()}.
-
-take_scc(#callgraph{postorder = [SCC|SCCs]} = CG) ->
- {ok, SCC, CG#callgraph{postorder = SCCs}};
-take_scc(#callgraph{postorder = []}) ->
- none.
+ digraph_confirm_vertices(MFAs, DG),
+ add_edges(Edges, CG).
-spec remove_external(callgraph()) -> {callgraph(), [tuple()]}.
remove_external(#callgraph{digraph = DG} = CG) ->
- {NewDG, External} = digraph_remove_external(DG),
- {CG#callgraph{digraph = NewDG}, External}.
+ {DG, External} = digraph_remove_external(DG),
+ {CG, External}.
-spec non_local_calls(callgraph()) -> mfa_calls().
@@ -221,13 +227,25 @@ find_non_local_calls([{Label1, Label2}|Left], Set) when is_integer(Label1),
find_non_local_calls([], Set) ->
sets:to_list(Set).
--spec renew_race_info(callgraph(), dict(), [label()], [string()]) ->
- callgraph().
+-spec get_depends_on(scc() | module(), callgraph()) -> [scc()].
+
+get_depends_on(SCC, #callgraph{active_digraph = {'e', Out, _In}}) ->
+ case ets_lookup_dict(SCC, Out) of
+ {ok, Value} -> Value;
+ error -> []
+ end;
+get_depends_on(SCC, #callgraph{active_digraph = {'d', DG}}) ->
+ digraph:out_neighbours(DG, SCC).
+
+-spec get_required_by(scc() | module(), callgraph()) -> [scc()].
-renew_race_info(CG, RaceCode, PublicTables, NamedTables) ->
- CG#callgraph{race_code = RaceCode,
- public_tables = PublicTables,
- named_tables = NamedTables}.
+get_required_by(SCC, #callgraph{active_digraph = {'e', _Out, In}}) ->
+ case ets_lookup_dict(SCC, In) of
+ {ok, Value} -> Value;
+ error -> []
+ end;
+get_required_by(SCC, #callgraph{active_digraph = {'d', DG}}) ->
+ digraph:in_neighbours(DG, SCC).
%%----------------------------------------------------------------------
%% Handling of modules & SCCs
@@ -238,33 +256,38 @@ renew_race_info(CG, RaceCode, PublicTables, NamedTables) ->
modules(#callgraph{digraph = DG}) ->
ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]).
--spec module_postorder(callgraph()) -> [[module()]].
+-spec module_postorder(callgraph()) -> {[module()], {'d', digraph()}}.
module_postorder(#callgraph{digraph = DG}) ->
- Edges = digraph_edges(DG),
- Nodes = ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
- MDG = digraph:new(),
- MDG1 = digraph_confirm_vertices(Nodes, MDG),
- MDG2 = create_module_digraph(Edges, MDG1),
- MDG3 = digraph_utils:condensation(MDG2),
- PostOrder = digraph_utils:postorder(MDG3),
- PostOrder1 = sort_sccs_internally(PostOrder, MDG2),
- digraph:delete(MDG2),
- digraph_delete(MDG3),
- PostOrder1.
+ Edges = lists:foldl(fun edge_fold/2, sets:new(), digraph_edges(DG)),
+ Nodes = sets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
+ MDG = digraph:new([acyclic]),
+ digraph_confirm_vertices(sets:to_list(Nodes), MDG),
+ Foreach = fun({M1,M2}) -> digraph:add_edge(MDG, M1, M2) end,
+ lists:foreach(Foreach, sets:to_list(Edges)),
+ {digraph_utils:topsort(MDG), {'d', MDG}}.
+
+edge_fold({{M1,_,_},{M2,_,_}}, Set) ->
+ case M1 =/= M2 of
+ true -> sets:add_element({M1,M2},Set);
+ false -> Set
+ end;
+edge_fold(_, Set) -> Set.
+
%% The module deps of a module are modules that depend on the module
-spec module_deps(callgraph()) -> dict().
module_deps(#callgraph{digraph = DG}) ->
- Edges = digraph_edges(DG),
- Nodes = ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
+ Edges = lists:foldl(fun edge_fold/2, sets:new(), digraph_edges(DG)),
+ Nodes = sets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
MDG = digraph:new(),
- MDG1 = digraph_confirm_vertices(Nodes, MDG),
- MDG2 = create_module_digraph(Edges, MDG1),
- Deps = [{N, ordsets:from_list(digraph:in_neighbours(MDG2, N))}
- || N <- Nodes],
- digraph_delete(MDG2),
+ digraph_confirm_vertices(sets:to_list(Nodes), MDG),
+ Foreach = fun({M1,M2}) -> digraph:add_edge(MDG, M1, M2) end,
+ lists:foreach(Foreach, sets:to_list(Edges)),
+ Deps = [{N, ordsets:from_list(digraph:in_neighbours(MDG, N))}
+ || N <- sets:to_list(Nodes)],
+ digraph_delete(MDG),
dict:from_list(Deps).
-spec strip_module_deps(dict(), set()) -> dict().
@@ -276,52 +299,42 @@ strip_module_deps(ModDeps, StripSet) ->
FilterFun2 = fun(_Key, ValSet) -> ValSet =/= [] end,
dict:filter(FilterFun2, ModDeps1).
-sort_sccs_internally(PO, MDG) ->
- sort_sccs_internally(PO, MDG, []).
-
-sort_sccs_internally([SCC|SCCs], MDG, Acc) ->
- case SCC of
- [_, _, _ | _] -> % length(SCC) >= 3
- TmpDG = digraph_utils:subgraph(MDG, SCC),
- NewSCC = digraph_utils:postorder(TmpDG),
- digraph_delete(TmpDG),
- sort_sccs_internally(SCCs, MDG, [NewSCC|Acc]);
- _ ->
- sort_sccs_internally(SCCs, MDG, [SCC|Acc])
- end;
-sort_sccs_internally([], _MDG, Acc) ->
- lists:reverse(Acc).
-
-create_module_digraph([{{M, _, _}, {M, _, _}}|Left], MDG) ->
- create_module_digraph(Left, MDG);
-create_module_digraph([{{M1, _, _}, {M2, _, _}}|Left], MDG) ->
- create_module_digraph(Left, digraph_add_edge(M1, M2, MDG));
-create_module_digraph([{_, _}|Left], MDG) ->
- create_module_digraph(Left, MDG);
-create_module_digraph([], MDG) ->
- MDG.
-
--spec finalize(callgraph()) -> callgraph().
+-spec finalize(callgraph()) -> {[scc()], callgraph()}.
finalize(#callgraph{digraph = DG} = CG) ->
- CG#callgraph{postorder = digraph_finalize(DG)}.
+ {ActiveDG, Postorder} = condensation(DG),
+ {Postorder, CG#callgraph{active_digraph = ActiveDG}}.
--spec reset_from_funs([mfa_or_funlbl()], callgraph()) -> callgraph().
+-spec reset_from_funs([mfa_or_funlbl()], callgraph()) -> {[scc()], callgraph()}.
-reset_from_funs(Funs, #callgraph{digraph = DG} = CG) ->
+reset_from_funs(Funs, #callgraph{digraph = DG, active_digraph = ADG} = CG) ->
+ active_digraph_delete(ADG),
SubGraph = digraph_reaching_subgraph(Funs, DG),
- Postorder = digraph_finalize(SubGraph),
+ {NewActiveDG, Postorder} = condensation(SubGraph),
digraph_delete(SubGraph),
- CG#callgraph{postorder = Postorder}.
+ {Postorder, CG#callgraph{active_digraph = NewActiveDG}}.
--spec module_postorder_from_funs([mfa_or_funlbl()], callgraph()) -> [[module()]].
+-spec module_postorder_from_funs([mfa_or_funlbl()], callgraph()) ->
+ {[module()], callgraph()}.
-module_postorder_from_funs(Funs, #callgraph{digraph = DG} = CG) ->
+module_postorder_from_funs(Funs, #callgraph{digraph = DG,
+ active_digraph = ADG} = CG) ->
+ active_digraph_delete(ADG),
SubGraph = digraph_reaching_subgraph(Funs, DG),
- PO = module_postorder(CG#callgraph{digraph = SubGraph}),
+ {PO, Active} = module_postorder(CG#callgraph{digraph = SubGraph}),
digraph_delete(SubGraph),
- PO.
-
+ {PO, CG#callgraph{active_digraph = Active}}.
+
+ets_lookup_dict(Key, Table) ->
+ try ets:lookup_element(Table, Key, 2) of
+ Val -> {ok, Val}
+ catch
+ _:_ -> error
+ end.
+
+ets_lookup_set(Key, Table) ->
+ ets:lookup(Table, Key) =/= [].
+
%%----------------------------------------------------------------------
%% Core code
%%----------------------------------------------------------------------
@@ -330,36 +343,37 @@ module_postorder_from_funs(Funs, #callgraph{digraph = DG} = CG) ->
%% The set of labels in the tree must be disjoint from the set of
%% labels already occuring in the callgraph.
--spec scan_core_tree(cerl:c_module(), callgraph()) -> callgraph().
+-spec scan_core_tree(cerl:c_module(), callgraph()) ->
+ {[mfa_or_funlbl()], [callgraph_edge()]}.
-scan_core_tree(Tree, #callgraph{calls = OldCalls,
- esc = OldEsc,
- name_map = OldNameMap,
- rec_var_map = OldRecVarMap,
- rev_name_map = OldRevNameMap,
- self_rec = OldSelfRec} = CG) ->
+scan_core_tree(Tree, #callgraph{calls = ETSCalls,
+ esc = ETSEsc,
+ name_map = ETSNameMap,
+ rec_var_map = ETSRecVarMap,
+ rev_name_map = ETSRevNameMap,
+ self_rec = ETSSelfRec}) ->
%% Build name map and recursion variable maps.
- {NewNameMap, NewRevNameMap, NewRecVarMap} =
- build_maps(Tree, OldRecVarMap, OldNameMap, OldRevNameMap),
-
+ build_maps(Tree, ETSRecVarMap, ETSNameMap, ETSRevNameMap),
+
%% First find the module-local dependencies.
{Deps0, EscapingFuns, Calls} = dialyzer_dep:analyze(Tree),
- NewCalls = dict:merge(fun(_Key, Val, Val) -> Val end, OldCalls, Calls),
- NewEsc = sets:union(sets:from_list(EscapingFuns), OldEsc),
+ true = ets:insert(ETSCalls, dict:to_list(Calls)),
+ true = ets:insert(ETSEsc, [{E} || E <- EscapingFuns]),
+
LabelEdges = get_edges_from_deps(Deps0),
%% Find the self recursive functions. Named functions get both the
%% key and their name for convenience.
SelfRecs0 = lists:foldl(fun({Key, Key}, Acc) ->
- case dict:find(Key, NewNameMap) of
+ case ets_lookup_dict(Key, ETSNameMap) of
error -> [Key|Acc];
{ok, Name} -> [Key, Name|Acc]
end;
(_, Acc) -> Acc
end, [], LabelEdges),
- SelfRecs = sets:union(sets:from_list(SelfRecs0), OldSelfRec),
+ true = ets:insert(ETSSelfRec, [{S} || S <- SelfRecs0]),
- NamedEdges1 = name_edges(LabelEdges, NewNameMap),
+ NamedEdges1 = name_edges(LabelEdges, ETSNameMap),
%% We need to scan for inter-module calls since these are not tracked
%% by dialyzer_dep. Note that the caller is always recorded as the
@@ -378,27 +392,25 @@ scan_core_tree(Tree, #callgraph{calls = OldCalls,
NewNamedEdges1 =
[E || {From, To} = E <- NamedEdges1, From =/= top, To =/= top],
NamedEdges3 = NewNamedEdges1 ++ NewNamedEdges2,
- CG1 = add_edges(NamedEdges3, Names3, CG),
- CG1#callgraph{calls = NewCalls,
- esc = NewEsc,
- name_map = NewNameMap,
- rec_var_map = NewRecVarMap,
- rev_name_map = NewRevNameMap,
- self_rec = SelfRecs}.
-
-build_maps(Tree, RecVarMap, NameMap, RevNameMap) ->
+ {Names3, NamedEdges3}.
+
+build_maps(Tree, ETSRecVarMap, ETSNameMap, ETSRevNameMap) ->
%% We only care about the named (top level) functions. The anonymous
%% functions will be analysed together with their parents.
Defs = cerl:module_defs(Tree),
Mod = cerl:atom_val(cerl:module_name(Tree)),
- lists:foldl(fun({Var, Function}, {AccNameMap, AccRevNameMap, AccRecVarMap}) ->
- FunName = cerl:fname_id(Var),
- Arity = cerl:fname_arity(Var),
- MFA = {Mod, FunName, Arity},
- {dict:store(get_label(Function), MFA, AccNameMap),
- dict:store(MFA, get_label(Function), AccRevNameMap),
- dict:store(get_label(Var), MFA, AccRecVarMap)}
- end, {NameMap, RevNameMap, RecVarMap}, Defs).
+ Fun =
+ fun({Var, Function}) ->
+ FunName = cerl:fname_id(Var),
+ Arity = cerl:fname_arity(Var),
+ MFA = {Mod, FunName, Arity},
+ FunLabel = get_label(Function),
+ VarLabel = get_label(Var),
+ true = ets:insert(ETSNameMap, {FunLabel, MFA}),
+ true = ets:insert(ETSRevNameMap, {MFA, FunLabel}),
+ true = ets:insert(ETSRecVarMap, {VarLabel, MFA})
+ end,
+ lists:foreach(Fun, Defs).
get_edges_from_deps(Deps) ->
%% Convert the dependencies as produced by dialyzer_dep to a list of
@@ -411,22 +423,22 @@ get_edges_from_deps(Deps) ->
end, [], Deps),
lists:flatten(Edges).
-name_edges(Edges, NameMap) ->
+name_edges(Edges, ETSNameMap) ->
%% If a label is present in the name map it is renamed. Otherwise
%% keep the label as the identity.
MapFun = fun(X) ->
- case dict:find(X, NameMap) of
+ case ets_lookup_dict(X, ETSNameMap) of
error -> X;
{ok, MFA} -> MFA
end
end,
- name_edges(Edges, MapFun, NameMap, []).
+ name_edges(Edges, MapFun, []).
-name_edges([{From, To}|Left], MapFun, NameMap, Acc) ->
+name_edges([{From, To}|Left], MapFun, Acc) ->
NewFrom = MapFun(From),
NewTo = MapFun(To),
- name_edges(Left, MapFun, NameMap, [{NewFrom, NewTo}|Acc]);
-name_edges([], _MapFun, _NameMap, Acc) ->
+ name_edges(Left, MapFun, [{NewFrom, NewTo}|Acc]);
+name_edges([], _MapFun, Acc) ->
Acc.
scan_core_funs(Tree) ->
@@ -478,9 +490,10 @@ get_label(T) ->
%%----------------------------------------------------------------------
digraph_add_edges([{From, To}|Left], DG) ->
- digraph_add_edges(Left, digraph_add_edge(From, To, DG));
-digraph_add_edges([], DG) ->
- DG.
+ digraph_add_edge(From, To, DG),
+ digraph_add_edges(Left, DG);
+digraph_add_edges([], _DG) ->
+ ok.
digraph_add_edge(From, To, DG) ->
case digraph:vertex(DG, From) of
@@ -492,13 +505,13 @@ digraph_add_edge(From, To, DG) ->
{To, _} -> ok
end,
digraph:add_edge(DG, {From, To}, From, To, []),
- DG.
+ ok.
digraph_confirm_vertices([MFA|Left], DG) ->
digraph:add_vertex(DG, MFA, confirmed),
digraph_confirm_vertices(Left, DG);
-digraph_confirm_vertices([], DG) ->
- DG.
+digraph_confirm_vertices([], _DG) ->
+ ok.
digraph_remove_external(DG) ->
Vertices = digraph:vertices(DG),
@@ -522,6 +535,12 @@ remove_unconfirmed([], DG, Unconfirmed) ->
digraph_delete(DG) ->
digraph:delete(DG).
+active_digraph_delete({'d', DG}) ->
+ digraph:delete(DG);
+active_digraph_delete({'e', Out, In}) ->
+ ets:delete(Out),
+ ets:delete(In).
+
digraph_edges(DG) ->
digraph:edges(DG).
@@ -534,75 +553,6 @@ digraph_in_neighbours(V, DG) ->
List -> List
end.
-%% Pick all the independent nodes (leaves) from one module. Then try
-%% to stay within the module until no more independent nodes can be
-%% chosen. Then pick a new module and so on.
-%%
-%% Note that an SCC that ranges over more than one module is
-%% considered to belong to all modules to make sure that we do not
-%% lose any nodes.
-
-digraph_postorder(Digraph) ->
- %% Remove all self-edges for SCCs.
- Edges = [digraph:edge(Digraph, E) || E <- digraph:edges(Digraph)],
- SelfEdges = [E || {E, V, V, _} <- Edges],
- true = digraph:del_edges(Digraph, SelfEdges),
- %% Determine the first module outside of the loop.
- Leaves = digraph_leaves(Digraph),
- case Leaves =:= [] of
- true -> [];
- false ->
- {Module, Taken} = take_sccs_from_fresh_module(Leaves),
- true = digraph:del_vertices(Digraph, Taken),
- digraph_postorder(Digraph, Module, [Taken])
- end.
-
-digraph_postorder(Digraph, LastModule, Acc) ->
- Leaves = digraph_leaves(Digraph),
- case Leaves =:= [] of
- true -> lists:append(lists:reverse(Acc));
- false ->
- case [SCC || SCC <- Leaves, scc_belongs_to_module(SCC, LastModule)] of
- [] ->
- {NewModule, NewTaken} = take_sccs_from_fresh_module(Leaves),
- true = digraph:del_vertices(Digraph, NewTaken),
- digraph_postorder(Digraph, NewModule, [NewTaken|Acc]);
- NewTaken ->
- true = digraph:del_vertices(Digraph, NewTaken),
- digraph_postorder(Digraph, LastModule, [NewTaken|Acc])
- end
- end.
-
-digraph_leaves(Digraph) ->
- [V || V <- digraph:vertices(Digraph), digraph:out_degree(Digraph, V) =:= 0].
-
-take_sccs_from_fresh_module(Leaves) ->
- NewModule = find_module(hd(Leaves)),
- {NewModule,
- [SCC || SCC <- Leaves, scc_belongs_to_module(SCC, NewModule)]}.
-
--spec scc_belongs_to_module(scc(), module()) -> boolean().
-
-scc_belongs_to_module([Label|Left], Module) when is_integer(Label) ->
- scc_belongs_to_module(Left, Module);
-scc_belongs_to_module([{M, _, _}|Left], Module) ->
- if M =:= Module -> true;
- true -> scc_belongs_to_module(Left, Module)
- end;
-scc_belongs_to_module([], _Module) ->
- false.
-
--spec find_module(scc()) -> module().
-
-find_module([{M, _, _}|_]) -> M;
-find_module([Label|Left]) when is_integer(Label) -> find_module(Left).
-
-digraph_finalize(DG) ->
- DG1 = digraph_utils:condensation(DG),
- Postorder = digraph_postorder(DG1),
- digraph:delete(DG1),
- Postorder.
-
digraph_reaching_subgraph(Funs, DG) ->
Vertices = digraph_utils:reaching(Funs, DG),
digraph_utils:subgraph(DG, Vertices).
@@ -611,20 +561,71 @@ digraph_reaching_subgraph(Funs, DG) ->
%% Races
%%----------------------------------------------------------------------
+-spec renew_race_info(callgraph(), dict(), [label()], [string()]) ->
+ callgraph().
+
+renew_race_info(#callgraph{race_data_server = RaceDataServer} = CG,
+ RaceCode, PublicTables, NamedTables) ->
+ ok = race_data_server_cast(
+ {renew_race_info, {RaceCode, PublicTables, NamedTables}},
+ RaceDataServer),
+ CG.
+
+renew_race_info({RaceCode, PublicTables, NamedTables},
+ #race_data_state{} = State) ->
+ State#race_data_state{race_code = RaceCode,
+ public_tables = PublicTables,
+ named_tables = NamedTables}.
+
+-spec renew_race_code(dialyzer_races:races(), callgraph()) -> callgraph().
+
+renew_race_code(Races, #callgraph{race_data_server = RaceDataServer} = CG) ->
+ Fun = dialyzer_races:get_curr_fun(Races),
+ FunArgs = dialyzer_races:get_curr_fun_args(Races),
+ Code = lists:reverse(dialyzer_races:get_race_list(Races)),
+ ok = race_data_server_cast(
+ {renew_race_code, {Fun, FunArgs, Code}},
+ RaceDataServer),
+ CG.
+
+renew_race_code_handler({Fun, FunArgs, Code},
+ #race_data_state{race_code = RaceCode} = State) ->
+ State#race_data_state{race_code = dict:store(Fun, [FunArgs, Code], RaceCode)}.
+
+-spec renew_race_public_tables(label(), callgraph()) -> callgraph().
+
+renew_race_public_tables(VarLabel,
+ #callgraph{race_data_server = RaceDataServer} = CG) ->
+ ok =
+ race_data_server_cast({renew_race_public_tables, VarLabel}, RaceDataServer),
+ CG.
+
+renew_race_public_tables_handler(VarLabel,
+ #race_data_state{public_tables = PT}
+ = State) ->
+ State#race_data_state{public_tables = ordsets:add_element(VarLabel, PT)}.
+
-spec cleanup(callgraph()) -> callgraph().
-cleanup(#callgraph{digraph = Digraph,
- name_map = NameMap,
- rev_name_map = RevNameMap,
- public_tables = PublicTables,
- named_tables = NamedTables,
- race_code = RaceCode}) ->
+cleanup(#callgraph{digraph = Digraph,
+ name_map = NameMap,
+ rev_name_map = RevNameMap,
+ race_data_server = RaceDataServer}) ->
#callgraph{digraph = Digraph,
- name_map = NameMap,
- rev_name_map = RevNameMap,
- public_tables = PublicTables,
- named_tables = NamedTables,
- race_code = RaceCode}.
+ name_map = NameMap,
+ rev_name_map = RevNameMap,
+ race_data_server = race_data_server_call(dup, RaceDataServer)}.
+
+-spec duplicate(callgraph()) -> callgraph().
+
+duplicate(#callgraph{race_data_server = RaceDataServer} = Callgraph) ->
+ Callgraph#callgraph{
+ race_data_server = race_data_server_call(dup, RaceDataServer)}.
+
+-spec dispose_race_server(callgraph()) -> ok.
+
+dispose_race_server(#callgraph{race_data_server = RaceDataServer}) ->
+ race_data_server_cast(stop, RaceDataServer).
-spec get_digraph(callgraph()) -> digraph().
@@ -633,28 +634,34 @@ get_digraph(#callgraph{digraph = Digraph}) ->
-spec get_named_tables(callgraph()) -> [string()].
-get_named_tables(#callgraph{named_tables = NamedTables}) ->
- NamedTables.
+get_named_tables(#callgraph{race_data_server = RaceDataServer}) ->
+ race_data_server_call(get_named_tables, RaceDataServer).
-spec get_public_tables(callgraph()) -> [label()].
-get_public_tables(#callgraph{public_tables = PT}) ->
- PT.
+get_public_tables(#callgraph{race_data_server = RaceDataServer}) ->
+ race_data_server_call(get_public_tables, RaceDataServer).
-spec get_race_code(callgraph()) -> dict().
-get_race_code(#callgraph{race_code = RaceCode}) ->
- RaceCode.
+get_race_code(#callgraph{race_data_server = RaceDataServer}) ->
+ race_data_server_call(get_race_code, RaceDataServer).
-spec get_race_detection(callgraph()) -> boolean().
get_race_detection(#callgraph{race_detection = RD}) ->
RD.
+-spec get_behaviour_api_calls(callgraph()) -> [{mfa(), mfa()}].
+
+get_behaviour_api_calls(#callgraph{race_data_server = RaceDataServer}) ->
+ race_data_server_call(get_behaviour_api_calls, RaceDataServer).
+
-spec race_code_new(callgraph()) -> callgraph().
-race_code_new(Callgraph) ->
- Callgraph#callgraph{race_code = dict:new()}.
+race_code_new(#callgraph{race_data_server = RaceDataServer} = CG) ->
+ ok = race_data_server_cast(race_code_new, RaceDataServer),
+ CG.
-spec put_digraph(digraph(), callgraph()) -> callgraph().
@@ -663,8 +670,9 @@ put_digraph(Digraph, Callgraph) ->
-spec put_race_code(dict(), callgraph()) -> callgraph().
-put_race_code(RaceCode, Callgraph) ->
- Callgraph#callgraph{race_code = RaceCode}.
+put_race_code(RaceCode, #callgraph{race_data_server = RaceDataServer} = CG) ->
+ ok = race_data_server_cast({put_race_code, RaceCode}, RaceDataServer),
+ CG.
-spec put_race_detection(boolean(), callgraph()) -> callgraph().
@@ -673,13 +681,79 @@ put_race_detection(RaceDetection, Callgraph) ->
-spec put_named_tables([string()], callgraph()) -> callgraph().
-put_named_tables(NamedTables, Callgraph) ->
- Callgraph#callgraph{named_tables = NamedTables}.
+put_named_tables(NamedTables,
+ #callgraph{race_data_server = RaceDataServer} = CG) ->
+ ok = race_data_server_cast({put_named_tables, NamedTables}, RaceDataServer),
+ CG.
-spec put_public_tables([label()], callgraph()) -> callgraph().
-put_public_tables(PublicTables, Callgraph) ->
- Callgraph#callgraph{public_tables = PublicTables}.
+put_public_tables(PublicTables,
+ #callgraph{race_data_server = RaceDataServer} = CG) ->
+ ok = race_data_server_cast({put_public_tables, PublicTables}, RaceDataServer),
+ CG.
+
+-spec put_behaviour_api_calls([{mfa(), mfa()}], callgraph()) -> callgraph().
+
+put_behaviour_api_calls(Calls,
+ #callgraph{race_data_server = RaceDataServer} = CG) ->
+ ok = race_data_server_cast({put_behaviour_api_calls, Calls}, RaceDataServer),
+ CG.
+
+
+new_race_data_server() ->
+ spawn_link(fun() -> race_data_server_loop(#race_data_state{}) end).
+
+race_data_server_loop(State) ->
+ receive
+ {call, From, Ref, Query} ->
+ Reply = race_data_server_handle_call(Query, State),
+ From ! {Ref, Reply},
+ race_data_server_loop(State);
+ {cast, stop} ->
+ ok;
+ {cast, Message} ->
+ NewState = race_data_server_handle_cast(Message, State),
+ race_data_server_loop(NewState)
+ end.
+
+race_data_server_call(Query, Server) ->
+ Ref = make_ref(),
+ Server ! {call, self(), Ref, Query},
+ receive
+ {Ref, Reply} -> Reply
+ end.
+
+race_data_server_cast(Message, Server) ->
+ Server ! {cast, Message},
+ ok.
+
+race_data_server_handle_cast(race_code_new, State) ->
+ State#race_data_state{race_code = dict:new()};
+race_data_server_handle_cast({Tag, Data}, State) ->
+ case Tag of
+ renew_race_info -> renew_race_info(Data, State);
+ renew_race_code -> renew_race_code_handler(Data, State);
+ renew_race_public_tables -> renew_race_public_tables_handler(Data, State);
+ put_race_code -> State#race_data_state{race_code = Data};
+ put_public_tables -> State#race_data_state{public_tables = Data};
+ put_named_tables -> State#race_data_state{named_tables = Data};
+ put_behaviour_api_calls -> State#race_data_state{beh_api_calls = Data}
+ end.
+
+race_data_server_handle_call(Query,
+ #race_data_state{race_code = RaceCode,
+ public_tables = PublicTables,
+ named_tables = NamedTables,
+ beh_api_calls = BehApiCalls}
+ = State) ->
+ case Query of
+ dup -> spawn_link(fun() -> race_data_server_loop(State) end);
+ get_race_code -> RaceCode;
+ get_public_tables -> PublicTables;
+ get_named_tables -> NamedTables;
+ get_behaviour_api_calls -> BehApiCalls
+ end.
%%=============================================================================
%% Utilities for 'dot'
@@ -695,7 +769,7 @@ to_dot(#callgraph{digraph = DG, esc = Esc} = CG, File) ->
end
end,
Escaping = [{Fun(L), {color, red}}
- || L <- sets:to_list(Esc), L =/= external],
+ || L <- [E || {E} <- ets:tab2list(Esc)], L =/= external],
Vertices = digraph_edges(DG),
hipe_dot:translate_list(Vertices, File, "CG", Escaping).
@@ -708,14 +782,41 @@ to_ps(#callgraph{} = CG, File, Args) ->
_ = os:cmd(Command),
ok.
-%-------------------------------------------------------------------------------
-
--spec put_behaviour_api_calls([{mfa(), mfa()}], callgraph()) -> callgraph().
-
-put_behaviour_api_calls(Calls, Callgraph) ->
- Callgraph#callgraph{beh_api_calls = Calls}.
-
--spec get_behaviour_api_calls(callgraph()) -> [{mfa(), mfa()}].
-
-get_behaviour_api_calls(Callgraph) ->
- Callgraph#callgraph.beh_api_calls.
+condensation(G) ->
+ SCs = digraph_utils:strong_components(G),
+ V2I = ets:new(condensation_v2i, []),
+ I2C = ets:new(condensation_i2c, []),
+ I2I = ets:new(condensation_i2i, [bag]),
+ CFun =
+ fun(SC, N) ->
+ lists:foreach(fun(V) -> true = ets:insert(V2I, {V,N}) end, SC),
+ true = ets:insert(I2C, {N, SC}),
+ N + 1
+ end,
+ lists:foldl(CFun, 1, SCs),
+ Fun1 =
+ fun({V1, V2}) ->
+ I1 = ets:lookup_element(V2I, V1, 2),
+ I2 = ets:lookup_element(V2I, V2, 2),
+ case I1 =:= I2 of
+ true -> true;
+ false -> ets:insert(I2I, {I1, I2})
+ end
+ end,
+ lists:foreach(Fun1, digraph:edges(G)),
+ Fun3 =
+ fun({I1, I2}, {Out, In}) ->
+ SC1 = ets:lookup_element(I2C, I1, 2),
+ SC2 = ets:lookup_element(I2C, I2, 2),
+ {dict:append(SC1, SC2, Out), dict:append(SC2, SC1, In)}
+ end,
+ {OutDict, InDict} = ets:foldl(Fun3, {dict:new(), dict:new()}, I2I),
+ [OutETS, InETS] =
+ [ets:new(Name,[{read_concurrency, true}]) ||
+ Name <- [callgraph_deps_out, callgraph_deps_in]],
+ ets:insert(OutETS, dict:to_list(OutDict)),
+ ets:insert(InETS, dict:to_list(InDict)),
+ ets:delete(V2I),
+ ets:delete(I2C),
+ ets:delete(I2I),
+ {{'e', OutETS, InETS}, SCs}.
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 8d61216b7a..6732d96b98 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -2,7 +2,7 @@
%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(dialyzer_cl).
-%% Avoid warning for local function error/1 clashing with autoimported BIF.
--compile({no_auto_import,[error/1]}).
-%% Avoid warning for local function error/2 clashing with autoimported BIF.
--compile({no_auto_import,[error/2]}).
-export([start/1]).
-include("dialyzer.hrl").
@@ -88,7 +84,7 @@ init_opts_for_build(Opts) ->
Plts ->
Msg = io_lib:format("Could not build multiple PLT files: ~s\n",
[format_plts(Plts)]),
- error(Msg)
+ cl_error(Msg)
end;
false -> Opts#options{init_plts = []}
end.
@@ -110,7 +106,7 @@ init_opts_for_add(Opts) ->
Plts ->
Msg = io_lib:format("Could not add to multiple PLT files: ~s\n",
[format_plts(Plts)]),
- error(Msg)
+ cl_error(Msg)
end;
false ->
case Opts#options.init_plts =:= [] of
@@ -134,11 +130,12 @@ check_plt_aux([_] = Plt, Opts) ->
report_check(Opts2),
plt_common(Opts2, [], []);
check_plt_aux([Plt|Plts], Opts) ->
- Opts1 = Opts#options{init_plts = [Plt]},
- Opts2 = init_opts_for_check(Opts1),
- report_check(Opts2),
- plt_common(Opts2, [], []),
- check_plt_aux(Plts, Opts).
+ case check_plt_aux([Plt], Opts) of
+ {?RET_NOTHING_SUSPICIOUS, []} -> check_plt_aux(Plts, Opts);
+ {?RET_DISCREPANCIES, Warns} ->
+ {_RET, MoreWarns} = check_plt_aux(Plts, Opts),
+ {?RET_DISCREPANCIES, Warns ++ MoreWarns}
+ end.
init_opts_for_check(Opts) ->
InitPlt =
@@ -175,7 +172,7 @@ init_opts_for_remove(Opts) ->
Plts ->
Msg = io_lib:format("Could not remove from multiple PLT files: ~s\n",
[format_plts(Plts)]),
- error(Msg)
+ cl_error(Msg)
end;
false ->
case Opts#options.init_plts =:= [] of
@@ -191,9 +188,10 @@ plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
ok ->
case Opts#options.output_plt of
none -> ok;
+ InitPlt -> ok;
OutPlt ->
{ok, Binary} = file:read_file(InitPlt),
- file:write_file(OutPlt, Binary)
+ ok = file:write_file(OutPlt, Binary)
end,
case Opts#options.report_mode of
quiet -> ok;
@@ -221,19 +219,19 @@ plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
{error, no_such_file} ->
Msg = io_lib:format("Could not find the PLT: ~s\n~s",
[InitPlt, default_plt_error_msg()]),
- error(Msg);
+ cl_error(Msg);
{error, not_valid} ->
Msg = io_lib:format("The file: ~s is not a valid PLT file\n~s",
[InitPlt, default_plt_error_msg()]),
- error(Msg);
+ cl_error(Msg);
{error, read_error} ->
Msg = io_lib:format("Could not read the PLT: ~s\n~s",
[InitPlt, default_plt_error_msg()]),
- error(Msg);
+ cl_error(Msg);
{error, {no_file_to_remove, F}} ->
Msg = io_lib:format("Could not remove the file ~s from the PLT: ~s\n",
[F, InitPlt]),
- error(Msg)
+ cl_error(Msg)
end.
default_plt_error_msg() ->
@@ -396,10 +394,12 @@ do_analysis(Files, Options, Plt, PltInfo) ->
defines = Options#options.defines,
include_dirs = Options#options.include_dirs,
files = Files,
- start_from = Options#options.from,
+ start_from = Options#options.from,
+ timing = Options#options.timing,
plt = Plt,
use_contracts = Options#options.use_contracts,
- callgraph_file = Options#options.callgraph_file},
+ callgraph_file = Options#options.callgraph_file,
+ solvers = Options#options.solvers},
State3 = start_analysis(State2, InitAnalysis),
{T1, _} = statistics(wall_clock),
Return = cl_loop(State3),
@@ -426,7 +426,7 @@ assert_writable(PltFile) ->
true -> ok;
false ->
Msg = io_lib:format(" The PLT file ~s is not writable", [PltFile]),
- error(Msg)
+ cl_error(Msg)
end.
check_if_writable(PltFile) ->
@@ -525,10 +525,7 @@ native_compile(Mods) ->
end.
hc(Mod) ->
- case code:ensure_loaded(Mod) of
- {module, Mod} -> ok;
- {error, sticky_directory} -> ok
- end,
+ {module, Mod} = code:ensure_loaded(Mod),
case code:is_module_native(Mod) of
true -> ok;
false ->
@@ -553,7 +550,7 @@ init_output(State0, #options{output_file = OutFile,
{error, Reason} ->
Msg = io_lib:format("Could not open output file ~p, Reason: ~p\n",
[OutFile, Reason]),
- error(State, lists:flatten(Msg))
+ cl_error(State, lists:flatten(Msg))
end
end.
@@ -599,10 +596,10 @@ cl_loop(State, LogCache) ->
cl_loop(NewState, LogCache);
{'EXIT', BackendPid, {error, Reason}} ->
Msg = failed_anal_msg(Reason, LogCache),
- error(State, Msg);
+ cl_error(State, Msg);
{'EXIT', BackendPid, Reason} when Reason =/= 'normal' ->
Msg = failed_anal_msg(io_lib:format("~P", [Reason, 12]), LogCache),
- error(State, Msg);
+ cl_error(State, Msg);
_Other ->
%% io:format("Received ~p\n", [_Other]),
cl_loop(State, LogCache)
@@ -611,7 +608,7 @@ cl_loop(State, LogCache) ->
-spec failed_anal_msg(string(), [_]) -> nonempty_string().
failed_anal_msg(Reason, LogCache) ->
- Msg = "Analysis failed with error: " ++ Reason ++ "\n",
+ Msg = "Analysis failed with error:\n" ++ Reason ++ "\n",
case LogCache =:= [] of
true -> Msg;
false ->
@@ -635,14 +632,14 @@ store_warnings(#cl_state{stored_warnings = StoredWarnings} = St, Warnings) ->
store_unknown_behaviours(#cl_state{unknown_behaviours = Behs} = St, Beh) ->
St#cl_state{unknown_behaviours = Beh ++ Behs}.
--spec error(string()) -> no_return().
+-spec cl_error(string()) -> no_return().
-error(Msg) ->
+cl_error(Msg) ->
throw({dialyzer_error, Msg}).
--spec error(#cl_state{}, string()) -> no_return().
+-spec cl_error(#cl_state{}, string()) -> no_return().
-error(State, Msg) ->
+cl_error(State, Msg) ->
case State#cl_state.output of
standard_io -> ok;
Outfile -> io:format(Outfile, "\n~s\n", [Msg])
@@ -754,15 +751,13 @@ print_unknown_behaviours(#cl_state{output = Output,
true -> io:nl(Output); %% Need to do a newline first
false -> ok
end,
- case Format of
- formatted ->
- io:put_chars(Output, "Unknown behaviours (behaviour_info(callbacks)"
- " does not return any specs):\n"),
- do_print_unknown_behaviours(Output, Behaviours, " ");
- raw ->
- io:put_chars(Output, "%% Unknown behaviours:\n"),
- do_print_unknown_behaviours(Output, Behaviours, "%% ")
- end
+ {Prompt, Prefix} =
+ case Format of
+ formatted -> {"Unknown behaviours:\n"," "};
+ raw -> {"%% Unknown behaviours:\n","%% "}
+ end,
+ io:put_chars(Output, Prompt),
+ do_print_unknown_behaviours(Output, Behaviours, Prefix)
end.
do_print_unknown_behaviours(Output, [B|T], Before) ->
diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl
index f80eb81ac6..2ea3d3af5a 100644
--- a/lib/dialyzer/src/dialyzer_cl_parse.erl
+++ b/lib/dialyzer/src/dialyzer_cl_parse.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -164,6 +164,13 @@ cl(["--src"|T]) ->
cl(["--no_spec"|T]) ->
put(dialyzer_options_use_contracts, false),
cl(T);
+cl(["--statistics"|T]) ->
+ put(dialyzer_timing, true),
+ cl(T);
+cl(["--resources"|T]) ->
+ put(dialyzer_options_report_mode, quiet),
+ put(dialyzer_timing, debug),
+ cl(T);
cl(["-v"|_]) ->
io:format("Dialyzer version "++?VSN++"\n"),
erlang:halt(?RET_NOTHING_SUSPICIOUS);
@@ -191,6 +198,9 @@ cl(["--gui"|T]) ->
cl(["--wx"|T]) ->
put(dialyzer_options_mode, {gui, wx}),
cl(T);
+cl(["--solver",Solver|T]) -> % not documented
+ append_var(dialyzer_solvers, [list_to_atom(Solver)]),
+ cl(T);
cl([H|_] = L) ->
case filelib:is_file(H) orelse filelib:is_dir(H) of
true ->
@@ -250,6 +260,8 @@ init() ->
put(dialyzer_output_format, formatted),
put(dialyzer_filename_opt, basename),
put(dialyzer_options_check_plt, DefaultOpts#options.check_plt),
+ put(dialyzer_timing, DefaultOpts#options.timing),
+ put(dialyzer_solvers, DefaultOpts#options.solvers),
ok.
append_defines([Def, Val]) ->
@@ -290,6 +302,7 @@ cl_options() ->
{filename_opt, get(dialyzer_filename_opt)},
{analysis_type, get(dialyzer_options_analysis_type)},
{get_warnings, get(dialyzer_options_get_warnings)},
+ {timing, get(dialyzer_timing)},
{callgraph_file, get(dialyzer_callgraph_file)}
|common_options()].
@@ -302,7 +315,8 @@ common_options() ->
{report_mode, get(dialyzer_options_report_mode)},
{use_spec, get(dialyzer_options_use_contracts)},
{warnings, get(dialyzer_warnings)},
- {check_plt, get(dialyzer_options_check_plt)}].
+ {check_plt, get(dialyzer_options_check_plt)},
+ {solvers, get(dialyzer_solvers)}].
%%-----------------------------------------------------------------------
@@ -351,7 +365,7 @@ help_message() ->
[--apps applications] [-o outfile]
[--build_plt] [--add_to_plt] [--remove_from_plt]
[--check_plt] [--no_check_plt] [--plt_info] [--get_warnings]
- [--no_native] [--fullpath]
+ [--no_native] [--fullpath] [--statistics]
Options:
files_or_dirs (for backwards compatibility also as: -c files_or_dirs)
Use Dialyzer from the command line to detect defects in the
@@ -418,6 +432,9 @@ Options:
Make Dialyzer a bit more quiet.
--verbose
Make Dialyzer a bit more verbose.
+ --statistics
+ Prints information about the progress of execution (analysis phases,
+ time spent in each and size of the relative input).
--build_plt
The analysis starts from an empty plt and creates a new one from the
files specified with -c and -r. Only works for beam files.
@@ -491,6 +508,12 @@ warning_options_msg() ->
Suppress warnings for patterns that are unused or cannot match.
-Wno_opaque
Suppress warnings for violations of opaqueness of data types.
+ -Wno_behaviours
+ Suppress warnings about behaviour callbacks which drift from the published
+ recommended interfaces.
+ -Wno_undefined_callbacks
+ Suppress warnings about behaviours that have no -callback attributes for
+ their callbacks.
-Wunmatched_returns ***
Include warnings for function calls which ignore a structured return
value or do not match against one of many possible return value(s).
@@ -498,9 +521,6 @@ warning_options_msg() ->
Include warnings for functions that only return by means of an exception.
-Wrace_conditions ***
Include warnings for possible race conditions.
- -Wbehaviours ***
- Include warnings about behaviour callbacks which drift from the published
- recommended interfaces.
-Wunderspecs ***
Warn about underspecified functions
(those whose -spec is strictly more allowing than the success typing).
diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl
index b2097f7e53..9989118671 100644
--- a/lib/dialyzer/src/dialyzer_codeserver.erl
+++ b/lib/dialyzer/src/dialyzer_codeserver.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
@@ -28,10 +28,11 @@
-module(dialyzer_codeserver).
-export([delete/1,
- finalize_contracts/2,
+ finalize_contracts/3,
finalize_exported_types/2,
finalize_records/2,
get_contracts/1,
+ get_callbacks/1,
get_exported_types/1,
get_exports/1,
get_records/1,
@@ -51,10 +52,8 @@
new/0,
set_next_core_label/2,
set_temp_records/2,
- store_records/3,
store_temp_records/3,
- store_contracts/3,
- store_temp_contracts/3]).
+ store_temp_contracts/4]).
-export_type([codeserver/0]).
@@ -62,82 +61,159 @@
%%--------------------------------------------------------------------
--record(codeserver, {table_pid :: pid(),
- exported_types = sets:new() :: set(), % set(mfa())
- temp_exported_types = sets:new() :: set(), % set(mfa())
- exports = sets:new() :: set(), % set(mfa())
- next_core_label = 0 :: label(),
- records = dict:new() :: dict(),
- temp_records = dict:new() :: dict(),
- contracts = dict:new() :: dict(),
- temp_contracts = dict:new() :: dict()}).
+-type dict_ets() :: ets:tid().
+-type set_ets() :: ets:tid().
+
+-record(codeserver, {next_core_label = 0 :: label(),
+ code :: dict_ets(),
+ exported_types :: set_ets(), % set(mfa())
+ records :: dict_ets(),
+ contracts :: dict_ets(),
+ callbacks :: dict_ets(),
+ exports :: 'clean' | set_ets(), % set(mfa())
+ temp_exported_types :: 'clean' | set_ets(), % set(mfa())
+ temp_records :: 'clean' | dict_ets(),
+ temp_contracts :: 'clean' | dict_ets(),
+ temp_callbacks :: 'clean' | dict_ets()
+ }).
-opaque codeserver() :: #codeserver{}.
%%--------------------------------------------------------------------
+ets_dict_find(Key, Table) ->
+ try ets:lookup_element(Table, Key, 2) of
+ Val -> {ok, Val}
+ catch
+ _:_ -> error
+ end.
+
+ets_dict_store(Key, Element, Table) ->
+ true = ets:insert(Table, {Key, Element}),
+ Table.
+
+ets_dict_store_dict(Dict, Table) ->
+ true = ets:insert(Table, dict:to_list(Dict)).
+
+ets_dict_to_dict(Table) ->
+ Fold = fun({Key,Value}, Dict) -> dict:store(Key, Value, Dict) end,
+ ets:foldl(Fold, dict:new(), Table).
+
+ets_set_is_element(Key, Table) ->
+ case ets:lookup(Table, Key) of
+ [] -> false;
+ _ -> true
+ end.
+
+ets_set_insert_set(Set, Table) ->
+ ets_set_insert_list(sets:to_list(Set), Table).
+
+ets_set_insert_list(List, Table) ->
+ true = ets:insert(Table, [{E} || E <- List]).
+
+ets_set_to_set(Table) ->
+ Fold = fun({E}, Set) -> sets:add_element(E, Set) end,
+ ets:foldl(Fold, sets:new(), Table).
+
+ets_read_concurrent_table(Name) ->
+ ets:new(Name,[{read_concurrency, true}]).
+
+%%--------------------------------------------------------------------
+
-spec new() -> codeserver().
new() ->
- #codeserver{table_pid = table__new()}.
+ CodeOptions = [compressed, public, {read_concurrency, true}],
+ Code = ets:new(dialyzer_codeserver_code, CodeOptions),
+ TempOptions = [public, {write_concurrency, true}],
+ [Exports, TempExportedTypes, TempRecords, TempContracts, TempCallbacks] =
+ [ets:new(Name, TempOptions) ||
+ Name <-
+ [dialyzer_codeserver_exports, dialyzer_codeserver_temp_exported_types,
+ dialyzer_codeserver_temp_records, dialyzer_codeserver_temp_contracts,
+ dialyzer_codeserver_temp_callbacks]],
+ #codeserver{code = Code,
+ exports = Exports,
+ temp_exported_types = TempExportedTypes,
+ temp_records = TempRecords,
+ temp_contracts = TempContracts,
+ temp_callbacks = TempCallbacks}.
-spec delete(codeserver()) -> 'ok'.
-delete(#codeserver{table_pid = TablePid}) ->
- table__delete(TablePid).
+delete(#codeserver{code = Code, exported_types = ExportedTypes,
+ records = Records, contracts = Contracts,
+ callbacks = Callbacks}) ->
+ lists:foreach(fun ets:delete/1,
+ [Code, ExportedTypes, Records, Contracts, Callbacks]).
-spec insert(atom(), cerl:c_module(), codeserver()) -> codeserver().
insert(Mod, ModCode, CS) ->
- NewTablePid = table__insert(CS#codeserver.table_pid, Mod, ModCode),
- CS#codeserver{table_pid = NewTablePid}.
+ Name = cerl:module_name(ModCode),
+ Exports = cerl:module_exports(ModCode),
+ Attrs = cerl:module_attrs(ModCode),
+ Defs = cerl:module_defs(ModCode),
+ As = cerl:get_ann(ModCode),
+ Funs =
+ [{{Mod, cerl:fname_id(Var), cerl:fname_arity(Var)},
+ Val} || Val = {Var, _Fun} <- Defs],
+ Keys = [Key || {Key, _Value} <- Funs],
+ ModEntry = {Mod, {Name, Exports, Attrs, Keys, As}},
+ true = ets:insert(CS#codeserver.code, [ModEntry|Funs]),
+ CS.
+
+-spec get_temp_exported_types(codeserver()) -> set().
+
+get_temp_exported_types(#codeserver{temp_exported_types = TempExpTypes}) ->
+ ets_set_to_set(TempExpTypes).
-spec insert_temp_exported_types(set(), codeserver()) -> codeserver().
insert_temp_exported_types(Set, CS) ->
- CS#codeserver{temp_exported_types = Set}.
+ TempExportedTypes = CS#codeserver.temp_exported_types,
+ true = ets_set_insert_set(Set, TempExportedTypes),
+ CS.
-spec insert_exports([mfa()], codeserver()) -> codeserver().
insert_exports(List, #codeserver{exports = Exports} = CS) ->
- Set = sets:from_list(List),
- NewExports = sets:union(Exports, Set),
- CS#codeserver{exports = NewExports}.
+ true = ets_set_insert_list(List, Exports),
+ CS.
-spec is_exported(mfa(), codeserver()) -> boolean().
is_exported(MFA, #codeserver{exports = Exports}) ->
- sets:is_element(MFA, Exports).
+ ets_set_is_element(MFA, Exports).
-spec get_exported_types(codeserver()) -> set(). % set(mfa())
get_exported_types(#codeserver{exported_types = ExpTypes}) ->
- ExpTypes.
-
--spec get_temp_exported_types(codeserver()) -> set().
-
-get_temp_exported_types(#codeserver{temp_exported_types = TempExpTypes}) ->
- TempExpTypes.
+ ets_set_to_set(ExpTypes).
-spec get_exports(codeserver()) -> set(). % set(mfa())
get_exports(#codeserver{exports = Exports}) ->
- Exports.
+ ets_set_to_set(Exports).
-spec finalize_exported_types(set(), codeserver()) -> codeserver().
finalize_exported_types(Set, CS) ->
- CS#codeserver{exported_types = Set, temp_exported_types = sets:new()}.
+ ExportedTypes = ets_read_concurrent_table(dialyzer_codeserver_exported_types),
+ true = ets_set_insert_set(Set, ExportedTypes),
+ TempExpTypes = CS#codeserver.temp_exported_types,
+ true = ets:delete(TempExpTypes),
+ CS#codeserver{exported_types = ExportedTypes, temp_exported_types = clean}.
-spec lookup_mod_code(atom(), codeserver()) -> cerl:c_module().
lookup_mod_code(Mod, CS) when is_atom(Mod) ->
- table__lookup(CS#codeserver.table_pid, Mod).
+ table__lookup(CS#codeserver.code, Mod).
-spec lookup_mfa_code(mfa(), codeserver()) -> {cerl:c_var(), cerl:c_fun()}.
lookup_mfa_code({_M, _F, _A} = MFA, CS) ->
- table__lookup(CS#codeserver.table_pid, MFA).
+ table__lookup(CS#codeserver.code, MFA).
-spec get_next_core_label(codeserver()) -> label().
@@ -149,20 +225,10 @@ get_next_core_label(#codeserver{next_core_label = NCL}) ->
set_next_core_label(NCL, CS) ->
CS#codeserver{next_core_label = NCL}.
--spec store_records(atom(), dict(), codeserver()) -> codeserver().
-
-store_records(Mod, Dict, #codeserver{records = RecDict} = CS)
- when is_atom(Mod) ->
- case dict:size(Dict) =:= 0 of
- true -> CS;
- false -> CS#codeserver{records = dict:store(Mod, Dict, RecDict)}
- end.
-
-spec lookup_mod_records(atom(), codeserver()) -> dict().
-lookup_mod_records(Mod, #codeserver{records = RecDict})
- when is_atom(Mod) ->
- case dict:find(Mod, RecDict) of
+lookup_mod_records(Mod, #codeserver{records = RecDict}) when is_atom(Mod) ->
+ case ets_dict_find(Mod, RecDict) of
error -> dict:new();
{ok, Dict} -> Dict
end.
@@ -170,7 +236,7 @@ lookup_mod_records(Mod, #codeserver{records = RecDict})
-spec get_records(codeserver()) -> dict().
get_records(#codeserver{records = RecDict}) ->
- RecDict.
+ ets_dict_to_dict(RecDict).
-spec store_temp_records(atom(), dict(), codeserver()) -> codeserver().
@@ -178,132 +244,107 @@ store_temp_records(Mod, Dict, #codeserver{temp_records = TempRecDict} = CS)
when is_atom(Mod) ->
case dict:size(Dict) =:= 0 of
true -> CS;
- false -> CS#codeserver{temp_records = dict:store(Mod, Dict, TempRecDict)}
+ false -> CS#codeserver{temp_records = ets_dict_store(Mod, Dict, TempRecDict)}
end.
-spec get_temp_records(codeserver()) -> dict().
get_temp_records(#codeserver{temp_records = TempRecDict}) ->
- TempRecDict.
+ ets_dict_to_dict(TempRecDict).
-spec set_temp_records(dict(), codeserver()) -> codeserver().
set_temp_records(Dict, CS) ->
- CS#codeserver{temp_records = Dict}.
+ true = ets:delete(CS#codeserver.temp_records),
+ TempRecords = ets:new(dialyzer_codeserver_temp_records,[]),
+ true = ets_dict_store_dict(Dict, TempRecords),
+ CS#codeserver{temp_records = TempRecords}.
-spec finalize_records(dict(), codeserver()) -> codeserver().
finalize_records(Dict, CS) ->
- CS#codeserver{records = Dict, temp_records = dict:new()}.
-
--spec store_contracts(atom(), dict(), codeserver()) -> codeserver().
-
-store_contracts(Mod, Dict, #codeserver{contracts = C} = CS) when is_atom(Mod) ->
- case dict:size(Dict) =:= 0 of
- true -> CS;
- false -> CS#codeserver{contracts = dict:store(Mod, Dict, C)}
- end.
+ true = ets:delete(CS#codeserver.temp_records),
+ Records = ets_read_concurrent_table(dialyzer_codeserver_records),
+ true = ets_dict_store_dict(Dict, Records),
+ CS#codeserver{records = Records, temp_records = clean}.
-spec lookup_mod_contracts(atom(), codeserver()) -> dict().
lookup_mod_contracts(Mod, #codeserver{contracts = ContDict})
when is_atom(Mod) ->
- case dict:find(Mod, ContDict) of
+ case ets_dict_find(Mod, ContDict) of
error -> dict:new();
- {ok, Dict} -> Dict
+ {ok, Keys} ->
+ dict:from_list([get_contract_pair(Key, ContDict)|| Key <- Keys])
end.
+get_contract_pair(Key, ContDict) ->
+ {Key, ets:lookup_element(ContDict, Key, 2)}.
+
-spec lookup_mfa_contract(mfa(), codeserver()) ->
'error' | {'ok', dialyzer_contracts:file_contract()}.
-lookup_mfa_contract({M,_F,_A} = MFA, #codeserver{contracts = ContDict}) ->
- case dict:find(M, ContDict) of
- error -> error;
- {ok, Dict} -> dict:find(MFA, Dict)
- end.
+lookup_mfa_contract(MFA, #codeserver{contracts = ContDict}) ->
+ ets_dict_find(MFA, ContDict).
-spec get_contracts(codeserver()) -> dict().
get_contracts(#codeserver{contracts = ContDict}) ->
- ContDict.
+ ets_dict_to_dict(ContDict).
--spec store_temp_contracts(atom(), dict(), codeserver()) -> codeserver().
+-spec get_callbacks(codeserver()) -> list().
-store_temp_contracts(Mod, Dict, #codeserver{temp_contracts = C} = CS)
- when is_atom(Mod) ->
- case dict:size(Dict) =:= 0 of
- true -> CS;
- false -> CS#codeserver{temp_contracts = dict:store(Mod, Dict, C)}
- end.
-
--spec get_temp_contracts(codeserver()) -> dict().
-
-get_temp_contracts(#codeserver{temp_contracts = TempContDict}) ->
- TempContDict.
-
--spec finalize_contracts(dict(), codeserver()) -> codeserver().
-
-finalize_contracts(Dict, CS) ->
- CS#codeserver{contracts = Dict, temp_contracts = dict:new()}.
+get_callbacks(#codeserver{callbacks = CallbDict}) ->
+ ets:tab2list(CallbDict).
-table__new() ->
- spawn_link(fun() -> table__loop(none, dict:new()) end).
+-spec store_temp_contracts(atom(), dict(), dict(), codeserver()) ->
+ codeserver().
-table__delete(TablePid) ->
- TablePid ! stop,
- ok.
-
-table__lookup(TablePid, Key) ->
- TablePid ! {self(), lookup, Key},
- receive
- {TablePid, Key, Ans} -> Ans
- end.
-
-table__insert(TablePid, Key, Val) ->
- TablePid ! {insert, [{Key, term_to_binary(Val, [compressed])}]},
- TablePid.
-
-table__loop(Cached, Map) ->
- receive
- stop -> ok;
- {Pid, lookup, {M, F, A} = MFA} ->
- {NewCached, Ans} =
- case Cached of
- {M, Tree} ->
- [Val] = [VarFun || {Var, _Fun} = VarFun <- cerl:module_defs(Tree),
- cerl:fname_id(Var) =:= F,
- cerl:fname_arity(Var) =:= A],
- {Cached, Val};
- _ ->
- Tree = fetch_and_expand(M, Map),
- [Val] = [VarFun || {Var, _Fun} = VarFun <- cerl:module_defs(Tree),
- cerl:fname_id(Var) =:= F,
- cerl:fname_arity(Var) =:= A],
- {{M, Tree}, Val}
- end,
- Pid ! {self(), MFA, Ans},
- table__loop(NewCached, Map);
- {Pid, lookup, Mod} when is_atom(Mod) ->
- Ans = case Cached of
- {Mod, Tree} -> Tree;
- _ -> fetch_and_expand(Mod, Map)
- end,
- Pid ! {self(), Mod, Ans},
- table__loop({Mod, Ans}, Map);
- {insert, List} ->
- NewMap = lists:foldl(fun({Key, Val}, AccMap) ->
- dict:store(Key, Val, AccMap)
- end, Map, List),
- table__loop(Cached, NewMap)
+store_temp_contracts(Mod, SpecDict, CallbackDict,
+ #codeserver{temp_contracts = Cn,
+ temp_callbacks = Cb} = CS)
+ when is_atom(Mod) ->
+ CS1 =
+ case dict:size(SpecDict) =:= 0 of
+ true -> CS;
+ false ->
+ CS#codeserver{temp_contracts = ets_dict_store(Mod, SpecDict, Cn)}
+ end,
+ case dict:size(CallbackDict) =:= 0 of
+ true -> CS1;
+ false ->
+ CS1#codeserver{temp_callbacks = ets_dict_store(Mod, CallbackDict, Cb)}
end.
-fetch_and_expand(Mod, Map) ->
- try
- Bin = dict:fetch(Mod, Map),
- binary_to_term(Bin)
- catch
- _:_ ->
- S = atom_to_list(Mod),
- Msg = "found no module named '" ++ S ++ "' in the analyzed files",
- exit({error, Msg})
- end.
+-spec get_temp_contracts(codeserver()) -> {dict(), dict()}.
+
+get_temp_contracts(#codeserver{temp_contracts = TempContDict,
+ temp_callbacks = TempCallDict}) ->
+ {ets_dict_to_dict(TempContDict), ets_dict_to_dict(TempCallDict)}.
+
+-spec finalize_contracts(dict(), dict(), codeserver()) -> codeserver().
+
+finalize_contracts(SpecDict, CallbackDict, CS) ->
+ Contracts = ets_read_concurrent_table(dialyzer_codeserver_contracts),
+ Callbacks = ets_read_concurrent_table(dialyzer_codeserver_callbacks),
+ Contracts = dict:fold(fun decompose_spec_dict/3, Contracts, SpecDict),
+ Callbacks = dict:fold(fun decompose_cb_dict/3, Callbacks, CallbackDict),
+ CS#codeserver{contracts = Contracts, callbacks = Callbacks,
+ temp_contracts = clean, temp_callbacks = clean}.
+
+decompose_spec_dict(Mod, Dict, Table) ->
+ Keys = dict:fetch_keys(Dict),
+ true = ets:insert(Table, dict:to_list(Dict)),
+ true = ets:insert(Table, {Mod, Keys}),
+ Table.
+
+decompose_cb_dict(_Mod, Dict, Table) ->
+ true = ets:insert(Table, dict:to_list(Dict)),
+ Table.
+
+table__lookup(TablePid, M) when is_atom(M) ->
+ {Name, Exports, Attrs, Keys, As} = ets:lookup_element(TablePid, M, 2),
+ Defs = [table__lookup(TablePid, Key) || Key <- Keys],
+ cerl:ann_c_module(As, Name, Exports, Attrs, Defs);
+table__lookup(TablePid, MFA) ->
+ ets:lookup_element(TablePid, MFA, 2).
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index bcdcf2685d..76f23d00b9 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -2,7 +2,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
@@ -141,7 +141,8 @@ sequence([H|T], Delimiter) -> H ++ Delimiter ++ sequence(T, Delimiter).
dialyzer_codeserver:codeserver().
process_contract_remote_types(CodeServer) ->
- TmpContractDict = dialyzer_codeserver:get_temp_contracts(CodeServer),
+ {TmpContractDict, TmpCallbackDict} =
+ dialyzer_codeserver:get_temp_contracts(CodeServer),
ExpTypes = dialyzer_codeserver:get_exported_types(CodeServer),
RecordDict = dialyzer_codeserver:get_records(CodeServer),
ContractFun =
@@ -155,7 +156,9 @@ process_contract_remote_types(CodeServer) ->
dict:map(ContractFun, ContractDict)
end,
NewContractDict = dict:map(ModuleFun, TmpContractDict),
- dialyzer_codeserver:finalize_contracts(NewContractDict, CodeServer).
+ NewCallbackDict = dict:map(ModuleFun, TmpCallbackDict),
+ dialyzer_codeserver:finalize_contracts(NewContractDict, NewCallbackDict,
+ CodeServer).
-spec check_contracts([{mfa(), file_contract()}],
dialyzer_callgraph:callgraph(), dict()) -> plt_contracts().
@@ -253,7 +256,7 @@ check_extraneous([C|Cs], SuccType) ->
check_extraneous_1(Contract, SuccType) ->
CRngs = erl_types:t_elements(erl_types:t_fun_range(Contract)),
STRng = erl_types:t_fun_range(SuccType),
- %% io:format("CR = ~p\nSR = ~p\n", [CRngs, STRng]),
+ ?debug("CR = ~p\nSR = ~p\n", [CRngs, STRng]),
case [CR || CR <- CRngs, erl_types:t_is_none(erl_types:t_inf(CR, STRng, opaque))] of
[] -> ok;
CRs -> {error, {extra_range, erl_types:t_sup(CRs), STRng}}
@@ -341,7 +344,7 @@ insert_constraints([{subtype, Type1, Type2}|Left], Dict) ->
false ->
%% A lot of things should change to add supertypes
throw({error, io_lib:format("First argument of is_subtype constraint "
- "must be a type variable\n", [])})
+ "must be a type variable: ~p\n", [Type1])})
end;
insert_constraints([], Dict) -> Dict.
@@ -349,55 +352,111 @@ insert_constraints([], Dict) -> Dict.
store_tmp_contract(MFA, FileLine, TypeSpec, SpecDict, RecordsDict) ->
%% io:format("contract from form: ~p\n", [TypeSpec]),
- TmpContract = contract_from_form(TypeSpec, RecordsDict),
+ TmpContract = contract_from_form(TypeSpec, RecordsDict, FileLine),
%% io:format("contract: ~p\n", [Contract]),
dict:store(MFA, {FileLine, TmpContract}, SpecDict).
-contract_from_form(Forms, RecDict) ->
- {CFuns, Forms1} = contract_from_form(Forms, RecDict, [], []),
+contract_from_form(Forms, RecDict, FileLine) ->
+ {CFuns, Forms1} = contract_from_form(Forms, RecDict, FileLine, [], []),
#tmp_contract{contract_funs = CFuns, forms = Forms1}.
contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], RecDict,
- TypeAcc, FormAcc) ->
+ FileLine, TypeAcc, FormAcc) ->
TypeFun =
fun(ExpTypes, AllRecords) ->
- Type = erl_types:t_from_form(Form, RecDict),
+ Type =
+ try
+ erl_types:t_from_form(Form, RecDict)
+ catch
+ throw:{error, Msg} ->
+ {File, Line} = FileLine,
+ NewMsg = io_lib:format("~s:~p: ~s", [filename:basename(File),
+ Line, Msg]),
+ throw({error, NewMsg})
+ end,
NewType = erl_types:t_solve_remote(Type, ExpTypes, AllRecords),
{NewType, []}
end,
NewTypeAcc = [TypeFun | TypeAcc],
NewFormAcc = [{Form, []} | FormAcc],
- contract_from_form(Left, RecDict, NewTypeAcc, NewFormAcc);
+ contract_from_form(Left, RecDict, FileLine, NewTypeAcc, NewFormAcc);
contract_from_form([{type, _L1, bounded_fun,
[{type, _L2, 'fun', [_, _]} = Form, Constr]}| Left],
- RecDict, TypeAcc, FormAcc) ->
+ RecDict, FileLine, TypeAcc, FormAcc) ->
TypeFun =
fun(ExpTypes, AllRecords) ->
- Constr1 = [constraint_from_form(C, RecDict, ExpTypes, AllRecords)
- || C <- Constr],
- VarDict = insert_constraints(Constr1, dict:new()),
+ {Constr1, VarDict} =
+ process_constraints(Constr, RecDict, ExpTypes, AllRecords),
Type = erl_types:t_from_form(Form, RecDict, VarDict),
NewType = erl_types:t_solve_remote(Type, ExpTypes, AllRecords),
{NewType, Constr1}
end,
NewTypeAcc = [TypeFun | TypeAcc],
NewFormAcc = [{Form, Constr} | FormAcc],
- contract_from_form(Left, RecDict, NewTypeAcc, NewFormAcc);
-contract_from_form([], _RecDict, TypeAcc, FormAcc) ->
+ contract_from_form(Left, RecDict, FileLine, NewTypeAcc, NewFormAcc);
+contract_from_form([], _RecDict, _FileLine, TypeAcc, FormAcc) ->
{lists:reverse(TypeAcc), lists:reverse(FormAcc)}.
-constraint_from_form({type, _, constraint, [{atom, _, is_subtype},
- [Type1, Type2]]}, RecDict,
- ExpTypes, AllRecords) ->
- T1 = erl_types:t_from_form(Type1, RecDict),
- T2 = erl_types:t_from_form(Type2, RecDict),
- T3 = erl_types:t_solve_remote(T1, ExpTypes, AllRecords),
- T4 = erl_types:t_solve_remote(T2, ExpTypes, AllRecords),
- {subtype, T3, T4};
-constraint_from_form({type, _, constraint, [{atom,_,Name}, List]}, _RecDict,
- _ExpTypes, _AllRecords) ->
- N = length(List),
- throw({error, io_lib:format("Unsupported type guard ~w/~w\n", [Name, N])}).
+process_constraints(Constrs, RecDict, ExpTypes, AllRecords) ->
+ Init = initialize_constraints(Constrs, RecDict, ExpTypes, AllRecords),
+ constraints_fixpoint(Init, RecDict, ExpTypes, AllRecords).
+
+initialize_constraints(Constrs, RecDict, ExpTypes, AllRecords) ->
+ initialize_constraints(Constrs, RecDict, ExpTypes, AllRecords, []).
+
+initialize_constraints([], _RecDict, _ExpTypes, _AllRecords, Acc) ->
+ Acc;
+initialize_constraints([Constr|Rest], RecDict, ExpTypes, AllRecords, Acc) ->
+ case Constr of
+ {type, _, constraint, [{atom, _, is_subtype}, [Type1, Type2]]} ->
+ T1 = final_form(Type1, RecDict, ExpTypes, AllRecords, dict:new()),
+ Entry = {T1, Type2},
+ initialize_constraints(Rest, RecDict, ExpTypes, AllRecords, [Entry|Acc]);
+ {type, _, constraint, [{atom,_,Name}, List]} ->
+ N = length(List),
+ throw({error,
+ io_lib:format("Unsupported type guard ~w/~w\n", [Name, N])})
+ end.
+
+constraints_fixpoint(Constrs, RecDict, ExpTypes, AllRecords) ->
+ VarDict =
+ constraints_to_dict(Constrs, RecDict, ExpTypes, AllRecords, dict:new()),
+ constraints_fixpoint(VarDict, Constrs, RecDict, ExpTypes, AllRecords).
+
+constraints_fixpoint(OldVarDict, Constrs, RecDict, ExpTypes, AllRecords) ->
+ NewVarDict =
+ constraints_to_dict(Constrs, RecDict, ExpTypes, AllRecords, OldVarDict),
+ case NewVarDict of
+ OldVarDict ->
+ DictFold =
+ fun(Key, Value, Acc) ->
+ [{subtype, erl_types:t_var(Key), Value}|Acc]
+ end,
+ FinalConstrs = dict:fold(DictFold, [], NewVarDict),
+ {FinalConstrs, NewVarDict};
+ _Other ->
+ constraints_fixpoint(NewVarDict, Constrs, RecDict, ExpTypes, AllRecords)
+ end.
+
+-define(TYPE_LIMIT, 4).
+
+final_form(Form, RecDict, ExpTypes, AllRecords, VarDict) ->
+ T1 = erl_types:t_from_form(Form, RecDict, VarDict),
+ T2 = erl_types:t_solve_remote(T1, ExpTypes, AllRecords),
+ erl_types:t_limit(T2, ?TYPE_LIMIT).
+
+constraints_to_dict(Constrs, RecDict, ExpTypes, AllRecords, VarDict) ->
+ Subtypes =
+ constraints_to_subs(Constrs, RecDict, ExpTypes, AllRecords, VarDict, []),
+ insert_constraints(Subtypes, dict:new()).
+
+constraints_to_subs([], _RecDict, _ExpTypes, _AllRecords, _VarDict, Acc) ->
+ Acc;
+constraints_to_subs([C|Rest], RecDict, ExpTypes, AllRecords, VarDict, Acc) ->
+ {T1, Form2} = C,
+ T2 = final_form(Form2, RecDict, ExpTypes, AllRecords, VarDict),
+ NewAcc = [{subtype, T1, T2}|Acc],
+ constraints_to_subs(Rest, RecDict, ExpTypes, AllRecords, VarDict, NewAcc).
%% Gets the most general domain of a list of domains of all
%% the overloaded contracts
@@ -441,7 +500,21 @@ get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract}}|Left],
{error, invalid_contract} ->
[invalid_contract_warning(MFA, FileLine, Sig, RecDict)|Acc];
{error, {extra_range, ExtraRanges, STRange}} ->
- [extra_range_warning(MFA, FileLine, ExtraRanges, STRange)|Acc];
+ Warn =
+ case t_from_forms_without_remote(Contract#contract.forms,
+ RecDict) of
+ {ok, NoRemoteType} ->
+ CRet = erl_types:t_fun_range(NoRemoteType),
+ erl_types:t_is_subtype(ExtraRanges, CRet);
+ unsupported ->
+ true
+ end,
+ case Warn of
+ true ->
+ [extra_range_warning(MFA, FileLine, ExtraRanges, STRange)|Acc];
+ false ->
+ Acc
+ end;
{error, Msg} ->
[{?WARN_CONTRACT_SYNTAX, FileLine, Msg}|Acc];
ok ->
@@ -480,7 +553,7 @@ invalid_contract_warning({M, F, A}, FileLine, SuccType, RecDict) ->
extra_range_warning({M, F, A}, FileLine, ExtraRanges, STRange) ->
ERangesStr = erl_types:t_to_string(ExtraRanges),
STRangeStr = erl_types:t_to_string(STRange),
- {?WARN_CONTRACT_TYPES, FileLine,
+ {?WARN_CONTRACT_SUPERTYPE, FileLine,
{extra_range, [M, F, A, ERangesStr, STRangeStr]}}.
picky_contract_check(CSig0, Sig0, MFA, FileLine, Contract, RecDict, Acc) ->
@@ -504,26 +577,92 @@ picky_contract_check(CSig0, Sig0, MFA, FileLine, Contract, RecDict, Acc) ->
extra_contract_warning({M, F, A}, FileLine, Contract, CSig, Sig, RecDict) ->
SigString = lists:flatten(dialyzer_utils:format_sig(Sig, RecDict)),
ContractString0 = lists:flatten(dialyzer_utils:format_sig(CSig, RecDict)),
- case SigString =:= ContractString0 of
+ %% The only difference is in record fields containing 'undefined' or not.
+ IsUndefRecordFieldsRelated = SigString =:= ContractString0,
+ {IsRemoteTypesRelated, SubtypeRelation} =
+ is_remote_types_related(Contract, CSig, Sig, RecDict),
+ case IsUndefRecordFieldsRelated orelse IsRemoteTypesRelated of
true ->
- %% The only difference is in record fields containing 'undefined' or not.
no_warning;
false ->
ContractString = contract_to_string(Contract),
{Tag, Msg} =
- case erl_types:t_is_subtype(CSig, Sig) of
- true ->
+ case SubtypeRelation of
+ contract_is_subtype ->
{?WARN_CONTRACT_SUBTYPE,
{contract_subtype, [M, F, A, ContractString, SigString]}};
- false ->
- case erl_types:t_is_subtype(Sig, CSig) of
- true ->
- {?WARN_CONTRACT_SUPERTYPE,
- {contract_supertype, [M, F, A, ContractString, SigString]}};
- false ->
- {?WARN_CONTRACT_NOT_EQUAL,
- {contract_diff, [M, F, A, ContractString, SigString]}}
- end
+ contract_is_supertype ->
+ {?WARN_CONTRACT_SUPERTYPE,
+ {contract_supertype, [M, F, A, ContractString, SigString]}};
+ neither ->
+ {?WARN_CONTRACT_NOT_EQUAL,
+ {contract_diff, [M, F, A, ContractString, SigString]}}
end,
{warning, {Tag, FileLine, Msg}}
end.
+
+is_remote_types_related(Contract, CSig, Sig, RecDict) ->
+ case erl_types:t_is_subtype(CSig, Sig) of
+ true ->
+ {false, contract_is_subtype};
+ false ->
+ case erl_types:t_is_subtype(Sig, CSig) of
+ true ->
+ case t_from_forms_without_remote(Contract#contract.forms, RecDict) of
+ {ok, NoRemoteTypeSig} ->
+ case blame_remote(CSig, NoRemoteTypeSig, Sig) of
+ true ->
+ {true, neither};
+ false ->
+ {false, contract_is_supertype}
+ end;
+ unsupported ->
+ {false, contract_is_supertype}
+ end;
+ false ->
+ {false, neither}
+ end
+ end.
+
+t_from_forms_without_remote([{FType, []}], RecDict) ->
+ Type0 = erl_types:t_from_form(FType, RecDict),
+ Map =
+ fun(Type) ->
+ case erl_types:t_is_remote(Type) of
+ true -> erl_types:t_none();
+ false -> Type
+ end
+ end,
+ {ok, erl_types:t_map(Map, Type0)};
+t_from_forms_without_remote([{_FType, _Constrs}], _RecDict) ->
+ %% 'When' constraints
+ unsupported;
+t_from_forms_without_remote(_Forms, _RecDict) ->
+ %% Lots of forms
+ unsupported.
+
+blame_remote(ContractSig, NoRemoteContractSig, Sig) ->
+ CArgs = erl_types:t_fun_args(ContractSig),
+ CRange = erl_types:t_fun_range(ContractSig),
+ NRArgs = erl_types:t_fun_args(NoRemoteContractSig),
+ NRRange = erl_types:t_fun_range(NoRemoteContractSig),
+ SArgs = erl_types:t_fun_args(Sig),
+ SRange = erl_types:t_fun_range(Sig),
+ blame_remote_list([CRange|CArgs], [NRRange|NRArgs], [SRange|SArgs]).
+
+blame_remote_list([], [], []) ->
+ true;
+blame_remote_list([CArg|CArgs], [NRArg|NRArgs], [SArg|SArgs]) ->
+ case erl_types:t_is_equal(CArg, NRArg) of
+ true ->
+ case not erl_types:t_is_equal(CArg, SArg) of
+ true -> false;
+ false -> blame_remote_list(CArgs, NRArgs, SArgs)
+ end;
+ false ->
+ case erl_types:t_is_subtype(SArg, NRArg)
+ andalso not erl_types:t_is_subtype(NRArg, SArg) of
+ true -> false;
+ false -> blame_remote_list(CArgs, NRArgs, SArgs)
+ end
+ end.
diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl
new file mode 100644
index 0000000000..28dcf098af
--- /dev/null
+++ b/lib/dialyzer/src/dialyzer_coordinator.erl
@@ -0,0 +1,251 @@
+%% -*- erlang-indent-level: 2 -*-
+%%-----------------------------------------------------------------------
+%% %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 : dialyzer_coordinator.erl
+%%% Authors : Stavros Aronis <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(dialyzer_coordinator).
+
+%%% Export for dialyzer main process
+-export([parallel_job/4]).
+
+%%% Exports for all possible workers
+-export([wait_activation/0, job_done/3]).
+
+%%% Exports for the typesig and dataflow analysis workers
+-export([sccs_to_pids/2, request_activation/1]).
+
+%%% Exports for the compilation workers
+-export([get_next_label/2]).
+
+-export_type([coordinator/0, mode/0, init_data/0, result/0]).
+
+%%--------------------------------------------------------------------
+
+-type collector() :: pid().
+-type regulator() :: pid().
+-type scc_to_pid() :: ets:tid() | 'unused'.
+
+-type coordinator() :: {collector(), regulator(), scc_to_pid()}. %%opaque
+-type timing() :: dialyzer_timing:timing_server().
+
+-type scc() :: [mfa_or_funlbl()].
+-type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'.
+
+-type compile_jobs() :: [file:filename()].
+-type typesig_jobs() :: [scc()].
+-type dataflow_jobs() :: [module()].
+-type warnings_jobs() :: [module()].
+
+-type compile_init_data() :: dialyzer_analysis_callgraph:compile_init_data().
+-type typesig_init_data() :: dialyzer_succ_typings:typesig_init_data().
+-type dataflow_init_data() :: dialyzer_succ_typings:dataflow_init_data().
+-type warnings_init_data() :: dialyzer_succ_typings:warnings_init_data().
+
+-type compile_result() :: dialyzer_analysis_callgraph:compile_result().
+-type typesig_result() :: [mfa_or_funlbl()].
+-type dataflow_result() :: [mfa_or_funlbl()].
+-type warnings_result() :: [dial_warning()].
+
+-type init_data() :: compile_init_data() | typesig_init_data() |
+ dataflow_init_data() | warnings_init_data().
+
+-type result() :: compile_result() | typesig_result() |
+ dataflow_result() | warnings_result().
+
+-type job() :: scc() | module() | file:filename().
+-type job_result() :: dialyzer_analysis_callgraph:one_file_result() |
+ typesig_result() | dataflow_result() | warnings_result().
+
+-record(state, {mode :: mode(),
+ active = 0 :: integer(),
+ result :: result(),
+ next_label = 0 :: integer(),
+ init_data :: init_data(),
+ regulator :: regulator(),
+ scc_to_pid :: scc_to_pid()
+ }).
+
+-include("dialyzer.hrl").
+
+%%--------------------------------------------------------------------
+
+-spec parallel_job('compile', compile_jobs(), compile_init_data(), timing()) ->
+ {compile_result(), integer()};
+ ('typesig', typesig_jobs(), typesig_init_data(), timing()) ->
+ typesig_result();
+ ('dataflow', dataflow_jobs(), dataflow_init_data(),
+ timing()) -> dataflow_result();
+ ('warnings', warnings_jobs(), warnings_init_data(),
+ timing()) -> warnings_result().
+
+parallel_job(Mode, Jobs, InitData, Timing) ->
+ State = spawn_jobs(Mode, Jobs, InitData, Timing),
+ collect_result(State).
+
+spawn_jobs(Mode, Jobs, InitData, Timing) ->
+ Collector = self(),
+ Regulator = spawn_regulator(),
+ TypesigOrDataflow = (Mode =:= 'typesig') orelse (Mode =:= 'dataflow'),
+ SCCtoPID =
+ case TypesigOrDataflow of
+ true -> ets:new(scc_to_pid, [{read_concurrency, true}]);
+ false -> unused
+ end,
+ Coordinator = {Collector, Regulator, SCCtoPID},
+ Fold =
+ fun(Job, Count) ->
+ Pid = dialyzer_worker:launch(Mode, Job, InitData, Coordinator),
+ case TypesigOrDataflow of
+ true -> true = ets:insert(SCCtoPID, {Job, Pid}), ok;
+ false -> request_activation(Regulator, Pid)
+ end,
+ Count + 1
+ end,
+ JobCount = lists:foldl(Fold, 0, Jobs),
+ Unit =
+ case Mode of
+ 'typesig' -> "SCCs";
+ _ -> "modules"
+ end,
+ dialyzer_timing:send_size_info(Timing, JobCount, Unit),
+ InitResult =
+ case Mode of
+ 'compile' -> dialyzer_analysis_callgraph:compile_init_result();
+ _ -> []
+ end,
+ #state{mode = Mode, active = JobCount, result = InitResult, next_label = 0,
+ init_data = InitData, regulator = Regulator, scc_to_pid = SCCtoPID}.
+
+collect_result(#state{mode = Mode, active = Active, result = Result,
+ next_label = NextLabel, init_data = InitData,
+ regulator = Regulator, scc_to_pid = SCCtoPID} = State) ->
+ receive
+ {next_label_request, Estimation, Pid} ->
+ Pid ! {next_label_reply, NextLabel},
+ collect_result(State#state{next_label = NextLabel + Estimation});
+ {done, Job, Data} ->
+ NewResult = update_result(Mode, InitData, Job, Data, Result),
+ case Active of
+ 1 ->
+ kill_regulator(Regulator),
+ case Mode of
+ 'compile' ->
+ {NewResult, NextLabel};
+ X when X =:= 'typesig'; X =:= 'dataflow' ->
+ ets:delete(SCCtoPID),
+ NewResult;
+ 'warnings' ->
+ NewResult
+ end;
+ N ->
+ collect_result(State#state{result = NewResult, active = N - 1})
+ end
+ end.
+
+update_result(Mode, InitData, Job, Data, Result) ->
+ case Mode of
+ 'compile' ->
+ dialyzer_analysis_callgraph:add_to_result(Job, Data, Result,
+ InitData);
+ X when X =:= 'typesig'; X =:= 'dataflow' ->
+ dialyzer_succ_typings:lookup_names(Data, InitData) ++ Result;
+ 'warnings' ->
+ Data ++ Result
+ end.
+
+-spec sccs_to_pids([scc() | module()], coordinator()) ->
+ {[dialyzer_worker:worker()], [scc() | module()]}.
+
+sccs_to_pids(SCCs, {_Collector, _Regulator, SCCtoPID}) ->
+ Fold =
+ fun(SCC, {Pids, Unknown}) ->
+ try ets:lookup_element(SCCtoPID, SCC, 2) of
+ Result -> {[Result|Pids], Unknown}
+ catch
+ _:_ -> {Pids, [SCC|Unknown]}
+ end
+ end,
+ lists:foldl(Fold, {[], []}, SCCs).
+
+-spec job_done(job(), job_result(), coordinator()) -> ok.
+
+job_done(Job, Result, {Collector, Regulator, _SCCtoPID}) ->
+ Regulator ! done,
+ Collector ! {done, Job, Result},
+ ok.
+
+-spec get_next_label(integer(), coordinator()) -> integer().
+
+get_next_label(EstimatedSize, {Collector, _Regulator, _SCCtoPID}) ->
+ Collector ! {next_label_request, EstimatedSize, self()},
+ receive
+ {next_label_reply, NextLabel} -> NextLabel
+ end.
+
+-spec wait_activation() -> ok.
+
+wait_activation() ->
+ receive activate -> ok end.
+
+activate_pid(Pid) ->
+ Pid ! activate.
+
+-spec request_activation(coordinator()) -> ok.
+
+request_activation({_Collector, Regulator, _SCCtoPID}) ->
+ Regulator ! {req, self()},
+ wait_activation().
+
+request_activation(Regulator, Pid) ->
+ Regulator ! {req, Pid},
+ ok.
+
+spawn_regulator() ->
+ InitTickets = dialyzer_utils:parallelism(),
+ spawn_link(fun() -> regulator_loop(InitTickets, queue:new()) end).
+
+regulator_loop(Tickets, Queue) ->
+ receive
+ {req, Pid} ->
+ case Tickets of
+ 0 ->
+ regulator_loop(0, queue:in(Pid, Queue));
+ N ->
+ activate_pid(Pid),
+ regulator_loop(N-1, Queue)
+ end;
+ done ->
+ {Waiting, NewQueue} = queue:out(Queue),
+ NewTickets =
+ case Waiting of
+ empty -> Tickets + 1;
+ {value, Pid} ->
+ activate_pid(Pid),
+ Tickets
+ end,
+ regulator_loop(NewTickets, NewQueue);
+ stop -> ok
+ end.
+
+kill_regulator(Regulator) ->
+ Regulator ! stop.
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index d74c04385b..7131633da1 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -2,7 +2,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,13 +32,11 @@
%% Data structure interfaces.
-export([state__add_warning/2, state__cleanup/1,
+ state__duplicate/1, dispose_state/1,
state__get_callgraph/1, state__get_races/1,
state__get_records/1, state__put_callgraph/2,
state__put_races/2, state__records_only/1]).
-%% Debug and test interfaces.
--export([get_top_level_signatures/2, pp/1]).
-
-export_type([state/0]).
-include("dialyzer.hrl").
@@ -68,7 +66,6 @@
%%-define(DEBUG, true).
%%-define(DEBUG_PP, true).
%%-define(DEBUG_TIME, true).
-%%-define(DOT, true).
-ifdef(DEBUG).
-import(erl_types, [t_to_string/1]).
@@ -77,9 +74,6 @@
-define(debug(S_, L_), ok).
-endif.
-%%-define(debug1(S_, L_), io:format(S_, L_)).
-%%-define(debug1(S_, L_), ok).
-
%%--------------------------------------------------------------------
-define(no_arg, no_arg).
@@ -101,6 +95,12 @@
behaviour_api_dict = [] ::
dialyzer_behaviours:behaviour_api_dict()}).
+-record(map, {dict = dict:new() :: dict(),
+ subst = dict:new() :: dict(),
+ modified = [] :: [Key :: term()],
+ modified_stack = [] :: [{[Key :: term()],reference()}],
+ ref = undefined :: reference() | undefined}).
+
%% Exported Types
-opaque state() :: #state{}.
@@ -109,7 +109,7 @@
-spec get_warnings(cerl:c_module(), dialyzer_plt:plt(),
dialyzer_callgraph:callgraph(), dict(), set()) ->
- {[dial_warning()], dict(), dict(), [label()], [string()]}.
+ {[dial_warning()], dict()}.
get_warnings(Tree, Plt, Callgraph, Records, NoWarnUnused) ->
State1 = analyze_module(Tree, Plt, Callgraph, Records, true),
@@ -117,145 +117,14 @@ get_warnings(Tree, Plt, Callgraph, Records, NoWarnUnused) ->
State3 =
state__renew_warnings(state__get_warnings(State2, NoWarnUnused), State2),
State4 = state__get_race_warnings(State3),
- Callgraph1 = State2#state.callgraph,
- {State4#state.warnings, state__all_fun_types(State4),
- dialyzer_callgraph:get_race_code(Callgraph1),
- dialyzer_callgraph:get_public_tables(Callgraph1),
- dialyzer_callgraph:get_named_tables(Callgraph1)}.
+ {State4#state.warnings, state__all_fun_types(State4)}.
-spec get_fun_types(cerl:c_module(), dialyzer_plt:plt(),
- dialyzer_callgraph:callgraph(), dict()) ->
- {dict(), dict(), [label()], [string()]}.
+ dialyzer_callgraph:callgraph(), dict()) -> dict().
get_fun_types(Tree, Plt, Callgraph, Records) ->
State = analyze_module(Tree, Plt, Callgraph, Records, false),
- Callgraph1 = State#state.callgraph,
- {state__all_fun_types(State),
- dialyzer_callgraph:get_race_code(Callgraph1),
- dialyzer_callgraph:get_public_tables(Callgraph1),
- dialyzer_callgraph:get_named_tables(Callgraph1)}.
-
-%%--------------------------------------------------------------------
-
--spec pp(file:filename()) -> 'ok'.
-
-pp(File) ->
- {ok, Code} = dialyzer_utils:get_core_from_src(File, [no_copt]),
- Plt = get_def_plt(),
- AnnTree = annotate_module(Code, Plt),
- io:put_chars(cerl_prettypr:format(AnnTree, [{hook, cerl_typean:pp_hook()}])),
- io:nl().
-
-%%--------------------------------------------------------------------
-%% This is used in the testsuite.
-
--spec get_top_level_signatures(cerl:c_module(), dict()) ->
- [{{atom(), arity()}, erl_types:erl_type()}].
-
-get_top_level_signatures(Code, Records) ->
- {Tree, _} = cerl_trees:label(cerl:from_records(Code)),
- Callgraph0 = dialyzer_callgraph:new(),
- Callgraph1 = dialyzer_callgraph:scan_core_tree(Tree, Callgraph0),
- {Callgraph2, _} = dialyzer_callgraph:remove_external(Callgraph1),
- Callgraph = dialyzer_callgraph:finalize(Callgraph2),
- to_dot(Callgraph),
- Plt = get_def_plt(),
- FunTypes = get_fun_types(Tree, Plt, Callgraph, Records),
- FunTypes1 = lists:foldl(fun({V, F}, Acc) ->
- Label = get_label(F),
- case dict:find(Label, Acc) of
- error ->
- Arity = cerl:fname_arity(V),
- Type = t_fun(lists:duplicate(Arity,
- t_none()),
- t_none()),
- dict:store(Label, Type, Acc);
- {ok, _} -> Acc
- end
- end, FunTypes, cerl:module_defs(Tree)),
- dialyzer_callgraph:delete(Callgraph),
- Sigs = [{{cerl:fname_id(V), cerl:fname_arity(V)},
- dict:fetch(get_label(F), FunTypes1)}
- || {V, F} <- cerl:module_defs(Tree)],
- ordsets:from_list(Sigs).
-
-get_def_plt() ->
- try
- dialyzer_plt:from_file(dialyzer_plt:get_default_plt())
- catch
- throw:{dialyzer_error, _} -> dialyzer_plt:new()
- end.
-
-%%% ===========================================================================
-%%%
-%%% Annotate all top level funs.
-%%%
-%%% ===========================================================================
-
-annotate_module(Code, Plt) ->
- {Tree, _} = cerl_trees:label(cerl:from_records(Code)),
- Callgraph0 = dialyzer_callgraph:new(),
- Callgraph1 = dialyzer_callgraph:scan_core_tree(Tree, Callgraph0),
- {Callgraph2, _} = dialyzer_callgraph:remove_external(Callgraph1),
- Callgraph = dialyzer_callgraph:finalize(Callgraph2),
- State = analyze_module(Tree, Plt, Callgraph),
- Res = annotate(Tree, State),
- dialyzer_callgraph:delete(Callgraph),
- Res.
-
-annotate(Tree, State) ->
- case cerl:subtrees(Tree) of
- [] -> set_type(Tree, State);
- List ->
- NewSubTrees = [[annotate(Subtree, State) || Subtree <- Group]
- || Group <- List],
- NewTree = cerl:update_tree(Tree, NewSubTrees),
- set_type(NewTree, State)
- end.
-
-set_type(Tree, State) ->
- case cerl:type(Tree) of
- 'fun' ->
- Type = state__fun_type(Tree, State),
- case t_is_any(Type) of
- true ->
- cerl:set_ann(Tree, delete_ann(typesig, cerl:get_ann(Tree)));
- false ->
- cerl:set_ann(Tree, append_ann(typesig, Type, cerl:get_ann(Tree)))
- end;
- apply ->
- case state__find_apply_return(Tree, State) of
- unknown -> Tree;
- ReturnType ->
- case t_is_any(ReturnType) of
- true ->
- cerl:set_ann(Tree, delete_ann(type, cerl:get_ann(Tree)));
- false ->
- cerl:set_ann(Tree, append_ann(type, ReturnType,
- cerl:get_ann(Tree)))
- end
- end;
- _ ->
- Tree
- end.
-
-append_ann(Tag, Val, [X | Xs]) ->
- if tuple_size(X) >= 1, element(1, X) =:= Tag ->
- append_ann(Tag, Val, Xs);
- true ->
- [X | append_ann(Tag, Val, Xs)]
- end;
-append_ann(Tag, Val, []) ->
- [{Tag, Val}].
-
-delete_ann(Tag, [X | Xs]) ->
- if tuple_size(X) >= 1, element(1, X) =:= Tag ->
- delete_ann(Tag, Xs);
- true ->
- [X | delete_ann(Tag, Xs)]
- end;
-delete_ann(_, []) ->
- [].
+ state__all_fun_types(State).
%%% ===========================================================================
%%%
@@ -263,9 +132,6 @@ delete_ann(_, []) ->
%%%
%%% ===========================================================================
-analyze_module(Tree, Plt, Callgraph) ->
- analyze_module(Tree, Plt, Callgraph, dict:new(), false).
-
analyze_module(Tree, Plt, Callgraph, Records, GetWarnings) ->
debug_pp(Tree, false),
Module = cerl:atom_val(cerl:module_name(Tree)),
@@ -276,73 +142,64 @@ analyze_module(Tree, Plt, Callgraph, Records, GetWarnings) ->
false -> []
end,
TopFun = cerl:ann_c_fun([{label, top}], [], Tree),
- State = state__new(dialyzer_callgraph:race_code_new(Callgraph),
- TopFun, Plt, Module, Records, BehaviourTranslations),
+ State =
+ state__new(Callgraph, TopFun, Plt, Module, Records, BehaviourTranslations),
State1 = state__race_analysis(not GetWarnings, State),
State2 = analyze_loop(State1),
- RaceCode = dialyzer_callgraph:get_race_code(Callgraph),
- Callgraph1 = State2#state.callgraph,
- RaceCode1 = dialyzer_callgraph:get_race_code(Callgraph1),
case GetWarnings of
true ->
State3 = state__set_warning_mode(State2),
State4 = analyze_loop(State3),
- State5 = state__restore_race_code(RaceCode, State4),
%% EXPERIMENTAL: Turn all behaviour API calls into calls to the
%% respective callback module's functions.
case BehaviourTranslations of
- [] -> dialyzer_races:race(State5);
+ [] -> dialyzer_races:race(State4);
Behaviours ->
- Callgraph2 = State5#state.callgraph,
- Digraph = dialyzer_callgraph:get_digraph(Callgraph2),
+ Digraph = dialyzer_callgraph:get_digraph(State4#state.callgraph),
TranslatedCallgraph =
dialyzer_behaviours:translate_callgraph(Behaviours, Module,
- Callgraph2),
+ Callgraph),
St =
- dialyzer_races:race(State5#state{callgraph = TranslatedCallgraph}),
- Callgraph3 = dialyzer_callgraph:put_digraph(Digraph,
- St#state.callgraph),
- St#state{callgraph = Callgraph3}
+ dialyzer_races:race(State4#state{callgraph = TranslatedCallgraph}),
+ FinalCallgraph = dialyzer_callgraph:put_digraph(Digraph,
+ St#state.callgraph),
+ St#state{callgraph = FinalCallgraph}
end;
false ->
- state__restore_race_code(
- dict:merge(fun (_K, V1, _V2) -> V1 end,
- RaceCode, RaceCode1), State2)
+ State2
end.
-analyze_loop(#state{callgraph = Callgraph, races = Races} = State) ->
+analyze_loop(State) ->
case state__get_work(State) of
- none -> state__clean_not_called(State);
- {Fun, NewState} ->
- ArgTypes = state__get_args(Fun, NewState),
- case any_none(ArgTypes) of
+ none -> State;
+ {Fun, NewState1} ->
+ {ArgTypes, IsCalled} = state__get_args_and_status(Fun, NewState1),
+ case not IsCalled of
true ->
- ?debug("Not handling1 ~w: ~s\n",
+ ?debug("Not handling (not called) ~w: ~s\n",
[state__lookup_name(get_label(Fun), State),
t_to_string(t_product(ArgTypes))]),
- analyze_loop(NewState);
+ analyze_loop(NewState1);
false ->
- case state__fun_env(Fun, NewState) of
+ case state__fun_env(Fun, NewState1) of
none ->
- ?debug("Not handling2 ~w: ~s\n",
+ ?debug("Not handling (no env) ~w: ~s\n",
[state__lookup_name(get_label(Fun), State),
t_to_string(t_product(ArgTypes))]),
- analyze_loop(NewState);
+ analyze_loop(NewState1);
Map ->
?debug("Handling fun ~p: ~s\n",
[state__lookup_name(get_label(Fun), State),
- t_to_string(state__fun_type(Fun, NewState))]),
- NewState1 = state__mark_fun_as_handled(NewState, Fun),
+ t_to_string(state__fun_type(Fun, NewState1))]),
Vars = cerl:fun_vars(Fun),
Map1 = enter_type_lists(Vars, ArgTypes, Map),
Body = cerl:fun_body(Fun),
FunLabel = get_label(Fun),
- RaceDetection = dialyzer_callgraph:get_race_detection(Callgraph),
- RaceAnalysis = dialyzer_races:get_race_analysis(Races),
+ IsRaceAnalysisEnabled = is_race_analysis_enabled(State),
NewState3 =
- case RaceDetection andalso RaceAnalysis of
+ case IsRaceAnalysisEnabled of
true ->
NewState2 = state__renew_curr_fun(
state__lookup_name(FunLabel, NewState1), FunLabel,
@@ -356,17 +213,8 @@ analyze_loop(#state{callgraph = Callgraph, races = Races} = State) ->
[state__lookup_name(get_label(Fun), State),
t_to_string(t_fun(ArgTypes, BodyType))]),
NewState5 =
- case RaceDetection andalso RaceAnalysis of
- true ->
- Races1 = NewState4#state.races,
- Code = lists:reverse(dialyzer_races:get_race_list(Races1)),
- Callgraph1 =
- renew_code(dialyzer_races:get_curr_fun(Races1),
- dialyzer_races:get_curr_fun_args(Races1),
- Code,
- state__warning_mode(NewState4),
- NewState4#state.callgraph),
- NewState4#state{callgraph = Callgraph1};
+ case IsRaceAnalysisEnabled of
+ true -> renew_race_code(NewState4);
false -> NewState4
end,
NewState6 =
@@ -581,9 +429,7 @@ handle_apply_or_call([{local, external}|Left], Args, ArgTypes, Map, Tree, State,
ArgTypes, t_any());
handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
Args, ArgTypes, Map, Tree,
- #state{callgraph = Callgraph, races = Races,
- opaques = Opaques} = State,
- AccArgTypes, AccRet) ->
+ #state{opaques = Opaques} = State, AccArgTypes, AccRet) ->
Any = t_any(),
AnyArgs = [Any || _ <- Args],
GenSig = {AnyArgs, fun(_) -> t_any() end},
@@ -679,8 +525,7 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
?debug("ContrRet: ~s\n", [erl_types:t_to_string(CRange(TmpArgTypes))]),
?debug("SigRet: ~s\n", [erl_types:t_to_string(SigRange)]),
State1 =
- case dialyzer_callgraph:get_race_detection(Callgraph) andalso
- dialyzer_races:get_race_analysis(Races) of
+ case is_race_analysis_enabled(State) of
true ->
Ann = cerl:get_ann(Tree),
File = get_file(Ann),
@@ -760,7 +605,13 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
true -> AccArgTypes;
false -> [t_sup(X, Y) || {X, Y} <- lists:zip(NewArgTypes, AccArgTypes)]
end,
- NewAccRet = t_sup(AccRet, t_inf(RetWithoutLocal, LocalRet, opaque)),
+ TotalRet =
+ case t_is_none(LocalRet) andalso t_is_unit(RetWithoutLocal) of
+ true -> RetWithoutLocal;
+ false -> t_inf(RetWithoutLocal, LocalRet, opaque)
+ end,
+ NewAccRet = t_sup(AccRet, TotalRet),
+ ?debug("NewAccRet: ~s\n", [t_to_string(NewAccRet)]),
handle_apply_or_call(Left, Args, ArgTypes, Map, Tree,
State3, NewAccArgTypes, NewAccRet);
handle_apply_or_call([], Args, _ArgTypes, Map, _Tree, State,
@@ -1040,30 +891,28 @@ handle_call(Tree, Map, State) ->
%%----------------------------------------
-handle_case(Tree, Map, #state{callgraph = Callgraph} = State) ->
+handle_case(Tree, Map, State) ->
Arg = cerl:case_arg(Tree),
Clauses = filter_match_fail(cerl:case_clauses(Tree)),
{State1, Map1, ArgType} = SMA = traverse(Arg, Map, State),
case t_is_none_or_unit(ArgType) of
true -> SMA;
false ->
- Races = State1#state.races,
State2 =
- case dialyzer_callgraph:get_race_detection(Callgraph) andalso
- dialyzer_races:get_race_analysis(Races) of
+ case is_race_analysis_enabled(State) of
true ->
- RaceList = dialyzer_races:get_race_list(Races),
- RaceListSize = dialyzer_races:get_race_list_size(Races),
+ {RaceList, RaceListSize} = get_race_list_and_size(State1),
state__renew_race_list([beg_case|RaceList],
RaceListSize + 1, State1);
false -> State1
end,
+ Map2 = join_maps_begin(Map1),
{MapList, State3, Type} =
handle_clauses(Clauses, Arg, ArgType, ArgType, State2,
- [], Map1, [], []),
- Map2 = join_maps(MapList, Map1),
+ [], Map2, [], []),
+ Map3 = join_maps_end(MapList, Map2),
debug_pp_map(Map2),
- {State3, Map2, Type}
+ {State3, Map3, Type}
end.
%%----------------------------------------
@@ -1086,9 +935,8 @@ handle_cons(Tree, Map, State) ->
%%----------------------------------------
-handle_let(Tree, Map, #state{callgraph = Callgraph, races = Races} = State) ->
- RaceAnalysis = dialyzer_races:get_race_analysis(Races),
- RaceDetection = dialyzer_callgraph:get_race_detection(Callgraph),
+handle_let(Tree, Map, State) ->
+ IsRaceAnalysisEnabled = is_race_analysis_enabled(State),
Arg = cerl:let_arg(Tree),
Vars = cerl:let_vars(Tree),
{Map0, State0} =
@@ -1096,10 +944,9 @@ handle_let(Tree, Map, #state{callgraph = Callgraph, races = Races} = State) ->
true ->
[Var] = Vars,
{enter_subst(Var, Arg, Map),
- case RaceDetection andalso RaceAnalysis of
+ case IsRaceAnalysisEnabled of
true ->
- RaceList = dialyzer_races:get_race_list(Races),
- RaceListSize = dialyzer_races:get_race_list_size(Races),
+ {RaceList, RaceListSize} = get_race_list_and_size(State),
state__renew_race_list(
[dialyzer_races:let_tag_new(Var, Arg)|RaceList],
RaceListSize + 1, State);
@@ -1109,9 +956,8 @@ handle_let(Tree, Map, #state{callgraph = Callgraph, races = Races} = State) ->
end,
Body = cerl:let_body(Tree),
{State1, Map1, ArgTypes} = SMA = traverse(Arg, Map0, State0),
- Callgraph1 = State1#state.callgraph,
- Callgraph2 =
- case RaceDetection andalso RaceAnalysis andalso cerl:is_c_call(Arg) of
+ State2 =
+ case IsRaceAnalysisEnabled andalso cerl:is_c_call(Arg) of
true ->
Mod = cerl:call_module(Arg),
Name = cerl:call_name(Arg),
@@ -1119,16 +965,11 @@ handle_let(Tree, Map, #state{callgraph = Callgraph, races = Races} = State) ->
cerl:concrete(Mod) =:= ets andalso
cerl:is_literal(Name) andalso
cerl:concrete(Name) =:= new of
- true ->
- NewTable = dialyzer_races:get_new_table(State1#state.races),
- renew_public_tables(Vars, NewTable,
- state__warning_mode(State1),
- Callgraph1);
- false -> Callgraph1
+ true -> renew_race_public_tables(Vars, State1);
+ false -> State1
end;
- false -> Callgraph1
+ false -> State1
end,
- State2 = State1#state{callgraph = Callgraph2},
case t_is_none_or_unit(ArgTypes) of
true -> SMA;
false ->
@@ -1159,16 +1000,13 @@ handle_module(Tree, Map, State) ->
%%----------------------------------------
-handle_receive(Tree, Map,
- #state{callgraph = Callgraph, races = Races} = State) ->
+handle_receive(Tree, Map, State) ->
Clauses = filter_match_fail(cerl:receive_clauses(Tree)),
Timeout = cerl:receive_timeout(Tree),
State1 =
- case dialyzer_callgraph:get_race_detection(Callgraph) andalso
- dialyzer_races:get_race_analysis(Races) of
+ case is_race_analysis_enabled(State) of
true ->
- RaceList = dialyzer_races:get_race_list(Races),
- RaceListSize = dialyzer_races:get_race_list_size(Races),
+ {RaceList, RaceListSize} = get_race_list_and_size(State),
state__renew_race_list([beg_case|RaceList],
RaceListSize + 1, State);
false -> State
@@ -1291,16 +1129,13 @@ handle_tuple(Tree, Map, State) ->
%%----------------------------------------
%% Clauses
%%
-handle_clauses([C|Left], Arg, ArgType, OrigArgType,
- #state{callgraph = Callgraph, races = Races} = State,
- CaseTypes, MapIn, Acc, ClauseAcc) ->
- RaceDetection = dialyzer_callgraph:get_race_detection(Callgraph),
- RaceAnalysis = dialyzer_races:get_race_analysis(Races),
+handle_clauses([C|Left], Arg, ArgType, OrigArgType, State, CaseTypes, MapIn,
+ Acc, ClauseAcc) ->
+ IsRaceAnalysisEnabled = is_race_analysis_enabled(State),
State1 =
- case RaceDetection andalso RaceAnalysis of
+ case IsRaceAnalysisEnabled of
true ->
- RaceList = dialyzer_races:get_race_list(Races),
- RaceListSize = dialyzer_races:get_race_list_size(Races),
+ {RaceList, RaceListSize} = get_race_list_and_size(State),
state__renew_race_list(
[dialyzer_races:beg_clause_new(Arg, cerl:clause_pats(C),
cerl:clause_guard(C))|
@@ -1311,11 +1146,9 @@ handle_clauses([C|Left], Arg, ArgType, OrigArgType,
{State2, ClauseMap, BodyType, NewArgType} =
do_clause(C, Arg, ArgType, OrigArgType, MapIn, State1),
{NewClauseAcc, State3} =
- case RaceDetection andalso RaceAnalysis of
+ case IsRaceAnalysisEnabled of
true ->
- Races1 = State2#state.races,
- RaceList1 = dialyzer_races:get_race_list(Races1),
- RaceListSize1 = dialyzer_races:get_race_list_size(Races1),
+ {RaceList1, RaceListSize1} = get_race_list_and_size(State2),
EndClause = dialyzer_races:end_clause_new(Arg, cerl:clause_pats(C),
cerl:clause_guard(C)),
{[EndClause|ClauseAcc],
@@ -1330,30 +1163,25 @@ handle_clauses([C|Left], Arg, ArgType, OrigArgType,
end,
handle_clauses(Left, Arg, NewArgType, OrigArgType, State3,
NewCaseTypes, MapIn, NewAcc, NewClauseAcc);
-handle_clauses([], _Arg, _ArgType, _OrigArgType,
- #state{callgraph = Callgraph, races = Races} = State,
- CaseTypes, _MapIn, Acc, ClauseAcc) ->
+handle_clauses([], _Arg, _ArgType, _OrigArgType, State, CaseTypes, _MapIn, Acc,
+ ClauseAcc) ->
State1 =
- case dialyzer_callgraph:get_race_detection(Callgraph) andalso
- dialyzer_races:get_race_analysis(Races) of
+ case is_race_analysis_enabled(State) of
true ->
+ {RaceList, RaceListSize} = get_race_list_and_size(State),
state__renew_race_list(
- [dialyzer_races:end_case_new(ClauseAcc)|
- dialyzer_races:get_race_list(Races)],
- dialyzer_races:get_race_list_size(Races) + 1, State);
+ [dialyzer_races:end_case_new(ClauseAcc)|RaceList],
+ RaceListSize + 1, State);
false -> State
end,
{lists:reverse(Acc), State1, t_sup(CaseTypes)}.
-do_clause(C, Arg, ArgType0, OrigArgType, Map,
- #state{callgraph = Callgraph, races = Races} = State) ->
+do_clause(C, Arg, ArgType0, OrigArgType, Map, State) ->
Pats = cerl:clause_pats(C),
Guard = cerl:clause_guard(C),
Body = cerl:clause_body(C),
- RaceDetection = dialyzer_callgraph:get_race_detection(Callgraph),
- RaceAnalysis = dialyzer_races:get_race_analysis(Races),
State1 =
- case RaceDetection andalso RaceAnalysis of
+ case is_race_analysis_enabled(State) of
true ->
state__renew_fun_args(Pats, State);
false -> State
@@ -1640,14 +1468,15 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
false ->
SubTuples = t_tuple_subtypes(Tuple),
%% Need to call the top function to get the try-catch wrapper
+ MapJ = join_maps_begin(Map),
Results =
case Rev of
true ->
[bind_pat_vars_reverse(Es, t_tuple_args(SubTuple), [],
- Map, State)
+ MapJ, State)
|| SubTuple <- SubTuples];
false ->
- [bind_pat_vars(Es, t_tuple_args(SubTuple), [], Map, State)
+ [bind_pat_vars(Es, t_tuple_args(SubTuple), [], MapJ, State)
|| SubTuple <- SubTuples]
end,
case lists:keyfind(opaque, 2, Results) of
@@ -1661,7 +1490,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
false -> bind_error([Pat], Tuple, t_none(), bind)
end;
Maps ->
- Map1 = join_maps(Maps, Map),
+ Map1 = join_maps_end(Maps, MapJ),
TupleType = t_sup([t_tuple(EsTypes)
|| {M, EsTypes} <- Results, M =/= error]),
{Map1, TupleType}
@@ -2308,27 +2137,29 @@ handle_guard_and(Guard, Map, Env, Eval, State) ->
end
end;
neg ->
+ MapJ = join_maps_begin(Map),
{Map1, Type1} =
- try bind_guard(Arg1, Map, Env, neg, State)
- catch throw:{fail, _} -> bind_guard(Arg2, Map, Env, pos, State)
+ try bind_guard(Arg1, MapJ, Env, neg, State)
+ catch throw:{fail, _} -> bind_guard(Arg2, MapJ, Env, pos, State)
end,
{Map2, Type2} =
- try bind_guard(Arg2, Map, Env, neg, State)
- catch throw:{fail, _} -> bind_guard(Arg1, Map, Env, pos, State)
+ try bind_guard(Arg2, MapJ, Env, neg, State)
+ catch throw:{fail, _} -> bind_guard(Arg1, MapJ, Env, pos, State)
end,
case t_is_atom(false, Type1) orelse t_is_atom(false, Type2) of
- true -> {join_maps([Map1, Map2], Map), t_atom(false)};
+ true -> {join_maps_end([Map1, Map2], MapJ), t_atom(false)};
false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State)
end;
dont_know ->
- {Map1, Type1} = bind_guard(Arg1, Map, Env, dont_know, State),
- {Map2, Type2} = bind_guard(Arg2, Map, Env, dont_know, State),
+ MapJ = join_maps_begin(Map),
+ {Map1, Type1} = bind_guard(Arg1, MapJ, Env, dont_know, State),
+ {Map2, Type2} = bind_guard(Arg2, MapJ, Env, dont_know, State),
Bool1 = t_inf(Type1, t_boolean()),
Bool2 = t_inf(Type2, t_boolean()),
case t_is_none(Bool1) orelse t_is_none(Bool2) of
true -> throw({fatal_fail, none});
false ->
- NewMap = join_maps([Map1, Map2], Map),
+ NewMap = join_maps_end([Map1, Map2], MapJ),
NewType =
case {t_atom_vals(Bool1), t_atom_vals(Bool2)} of
{['true'] , ['true'] } -> t_atom(true);
@@ -2344,20 +2175,21 @@ handle_guard_or(Guard, Map, Env, Eval, State) ->
[Arg1, Arg2] = cerl:call_args(Guard),
case Eval of
pos ->
+ MapJ = join_maps_begin(Map),
{Map1, Bool1} =
- try bind_guard(Arg1, Map, Env, pos, State)
+ try bind_guard(Arg1, MapJ, Env, pos, State)
catch
- throw:{fail,_} -> bind_guard(Arg1, Map, Env, dont_know, State)
+ throw:{fail,_} -> bind_guard(Arg1, MapJ, Env, dont_know, State)
end,
{Map2, Bool2} =
- try bind_guard(Arg2, Map, Env, pos, State)
+ try bind_guard(Arg2, MapJ, Env, pos, State)
catch
- throw:{fail,_} -> bind_guard(Arg2, Map, Env, dont_know, State)
+ throw:{fail,_} -> bind_guard(Arg2, MapJ, Env, dont_know, State)
end,
case ((t_is_atom(true, Bool1) andalso t_is_boolean(Bool2))
orelse
(t_is_atom(true, Bool2) andalso t_is_boolean(Bool1))) of
- true -> {join_maps([Map1, Map2], Map), t_atom(true)};
+ true -> {join_maps_end([Map1, Map2], MapJ), t_atom(true)};
false -> signal_guard_fail(Eval, Guard, [Bool1, Bool2], State)
end;
neg ->
@@ -2372,14 +2204,15 @@ handle_guard_or(Guard, Map, Env, Eval, State) ->
end
end;
dont_know ->
- {Map1, Type1} = bind_guard(Arg1, Map, Env, dont_know, State),
- {Map2, Type2} = bind_guard(Arg2, Map, Env, dont_know, State),
+ MapJ = join_maps_begin(Map),
+ {Map1, Type1} = bind_guard(Arg1, MapJ, Env, dont_know, State),
+ {Map2, Type2} = bind_guard(Arg2, MapJ, Env, dont_know, State),
Bool1 = t_inf(Type1, t_boolean()),
Bool2 = t_inf(Type2, t_boolean()),
case t_is_none(Bool1) orelse t_is_none(Bool2) of
true -> throw({fatal_fail, none});
false ->
- NewMap = join_maps([Map1, Map2], Map),
+ NewMap = join_maps_end([Map1, Map2], MapJ),
NewType =
case {t_atom_vals(Bool1), t_atom_vals(Bool2)} of
{['false'], ['false']} -> t_atom(false);
@@ -2493,8 +2326,9 @@ mk_guard_msg(Eval, F, Args, ArgTypes, State) ->
end
end.
-bind_guard_case_clauses(Arg, Clauses, Map, Env, Eval, State) ->
+bind_guard_case_clauses(Arg, Clauses, Map0, Env, Eval, State) ->
Clauses1 = filter_fail_clauses(Clauses),
+ Map = join_maps_begin(Map0),
{GenMap, GenArgType} = bind_guard(Arg, Map, Env, dont_know, State),
bind_guard_case_clauses(GenArgType, GenMap, Arg, Clauses1, Map, Env, Eval,
t_none(), [], State).
@@ -2594,7 +2428,7 @@ bind_guard_case_clauses(_GenArgType, _GenMap, _ArgExpr, [], Map, _Env, _Eval,
AccType, AccMaps, _State) ->
case t_is_none(AccType) of
true -> throw({fail, none});
- false -> {join_maps(AccMaps, Map), AccType}
+ false -> {join_maps_end(AccMaps, Map), AccType}
end.
%%% ===========================================================================
@@ -2604,21 +2438,48 @@ bind_guard_case_clauses(_GenArgType, _GenMap, _ArgExpr, [], Map, _Env, _Eval,
%%% ===========================================================================
map__new() ->
- {dict:new(), dict:new()}.
+ #map{}.
+
+%% join_maps_begin pushes 'modified' to the stack; join_maps pops
+%% 'modified' from the stack.
+
+join_maps_begin(#map{modified = M, modified_stack = S, ref = Ref} = Map) ->
+ Map#map{ref = make_ref(), modified = [], modified_stack = [{M,Ref} | S]}.
+
+join_maps_end(Maps, MapOut) ->
+ #map{ref = Ref, modified_stack = [{M1,R1} | S]} = MapOut,
+ true = lists:all(fun(M) -> M#map.ref =:= Ref end, Maps), % sanity
+ Keys0 = lists:usort(lists:append([M#map.modified || M <- Maps])),
+ #map{dict = Dict, subst = Subst} = MapOut,
+ Keys = [Key ||
+ Key <- Keys0,
+ dict:is_key(Key, Dict) orelse dict:is_key(Key, Subst)],
+ Out = case Maps of
+ [] -> join_maps(Maps, MapOut);
+ _ -> join_maps(Keys, Maps, MapOut)
+ end,
+ debug_join_check(Maps, MapOut, Out),
+ Out#map{ref = R1,
+ modified = Out#map.modified ++ M1, % duplicates possible
+ modified_stack = S}.
join_maps(Maps, MapOut) ->
- {Map, Subst} = MapOut,
- Keys = ordsets:from_list(dict:fetch_keys(Map) ++ dict:fetch_keys(Subst)),
+ #map{dict = Dict, subst = Subst} = MapOut,
+ Keys = ordsets:from_list(dict:fetch_keys(Dict) ++ dict:fetch_keys(Subst)),
join_maps(Keys, Maps, MapOut).
-join_maps([Key|Left], Maps, MapOut) ->
+join_maps(Keys, Maps, MapOut) ->
+ KTs = join_maps_collect(Keys, Maps, MapOut),
+ lists:foldl(fun({K, T}, M) -> enter_type(K, T, M) end, MapOut, KTs).
+
+join_maps_collect([Key|Left], Maps, MapOut) ->
Type = join_maps_one_key(Maps, Key, t_none()),
case t_is_equal(lookup_type(Key, MapOut), Type) of
- true -> join_maps(Left, Maps, MapOut);
- false -> join_maps(Left, Maps, enter_type(Key, Type, MapOut))
+ true -> join_maps_collect(Left, Maps, MapOut);
+ false -> [{Key, Type} | join_maps_collect(Left, Maps, MapOut)]
end;
-join_maps([], _Maps, MapOut) ->
- MapOut.
+join_maps_collect([], _Maps, _MapOut) ->
+ [].
join_maps_one_key([Map|Left], Key, AccType) ->
case t_is_any(AccType) of
@@ -2631,6 +2492,17 @@ join_maps_one_key([Map|Left], Key, AccType) ->
join_maps_one_key([], _Key, AccType) ->
AccType.
+-ifdef(DEBUG).
+debug_join_check(Maps, MapOut, Out) ->
+ #map{dict = Dict, subst = Subst} = Out,
+ #map{dict = Dict2, subst = Subst2} = join_maps(Maps, MapOut),
+ F = fun(D) -> lists:keysort(1, dict:to_list(D)) end,
+ [throw({bug, join_maps}) ||
+ F(Dict) =/= F(Dict2) orelse F(Subst) =/= F(Subst2)].
+-else.
+debug_join_check(_Maps, _MapOut, _Out) -> ok.
+-endif.
+
enter_type_lists([Key|KeyTail], [Val|ValTail], Map) ->
Map1 = enter_type(Key, Val, Map),
enter_type_lists(KeyTail, ValTail, Map1);
@@ -2643,20 +2515,21 @@ enter_type_list([{Key, Val}|Left], Map) ->
enter_type_list([], Map) ->
Map.
-enter_type(Key, Val, {Map, Subst} = MS) ->
+enter_type(Key, Val, MS) ->
case cerl:is_literal(Key) of
true -> MS;
false ->
case cerl:is_c_values(Key) of
true ->
- Keys = cerl:values_es(Key),
+ Keys = cerl:values_es(Key),
case t_is_any(Val) orelse t_is_none(Val) of
true ->
enter_type_lists(Keys, [Val || _ <- Keys], MS);
false ->
- enter_type_lists(cerl:values_es(Key), t_to_tlist(Val), MS)
+ enter_type_lists(Keys, t_to_tlist(Val), MS)
end;
false ->
+ #map{dict = Dict, subst = Subst} = MS,
KeyLabel = get_label(Key),
case dict:find(KeyLabel, Subst) of
{ok, NewKey} ->
@@ -2664,21 +2537,25 @@ enter_type(Key, Val, {Map, Subst} = MS) ->
enter_type(NewKey, Val, MS);
error ->
?debug("Entering ~p :: ~s\n", [KeyLabel, t_to_string(Val)]),
- case dict:find(KeyLabel, Map) of
+ case dict:find(KeyLabel, Dict) of
{ok, Val} -> MS;
- {ok, _OldVal} -> {dict:store(KeyLabel, Val, Map), Subst};
- error -> {dict:store(KeyLabel, Val, Map), Subst}
+ {ok, _OldVal} -> store_map(KeyLabel, Val, MS);
+ error -> store_map(KeyLabel, Val, MS)
end
end
end
end.
-enter_subst(Key, Val, {Map, Subst} = MS) ->
+store_map(Key, Val, #map{dict = Dict, ref = undefined} = Map) ->
+ Map#map{dict = dict:store(Key, Val, Dict)};
+store_map(Key, Val, #map{dict = Dict, modified = Mod} = Map) ->
+ Map#map{dict = dict:store(Key, Val, Dict), modified = [Key | Mod]}.
+
+enter_subst(Key, Val, #map{subst = Subst} = MS) ->
KeyLabel = get_label(Key),
case cerl:is_literal(Val) of
true ->
- NewMap = dict:store(KeyLabel, literal_type(Val), Map),
- {NewMap, Subst};
+ store_map(KeyLabel, literal_type(Val), MS);
false ->
case cerl:is_c_var(Val) of
false -> MS;
@@ -2691,25 +2568,29 @@ enter_subst(Key, Val, {Map, Subst} = MS) ->
if KeyLabel =:= ValLabel -> MS;
true ->
?debug("Subst: storing ~p = ~p\n", [KeyLabel, ValLabel]),
- NewSubst = dict:store(KeyLabel, ValLabel, Subst),
- {Map, NewSubst}
+ store_subst(KeyLabel, ValLabel, MS)
end
end
end
end.
-lookup_type(Key, {Map, Subst}) ->
- lookup(Key, Map, Subst, t_none()).
+store_subst(Key, Val, #map{subst = S, ref = undefined} = Map) ->
+ Map#map{subst = dict:store(Key, Val, S)};
+store_subst(Key, Val, #map{subst = S, modified = Mod} = Map) ->
+ Map#map{subst = dict:store(Key, Val, S), modified = [Key | Mod]}.
+
+lookup_type(Key, #map{dict = Dict, subst = Subst}) ->
+ lookup(Key, Dict, Subst, t_none()).
-lookup(Key, Map, Subst, AnyNone) ->
+lookup(Key, Dict, Subst, AnyNone) ->
case cerl:is_literal(Key) of
true -> literal_type(Key);
false ->
Label = get_label(Key),
case dict:find(Label, Subst) of
- {ok, NewKey} -> lookup(NewKey, Map, Subst, AnyNone);
+ {ok, NewKey} -> lookup(NewKey, Dict, Subst, AnyNone);
error ->
- case dict:find(Label, Map) of
+ case dict:find(Label, Dict) of
{ok, Val} -> Val;
error -> AnyNone
end
@@ -2744,8 +2625,8 @@ mark_as_fresh([], Map) ->
Map.
-ifdef(DEBUG).
-debug_pp_map(Map = {Map0, _Subst}) ->
- Keys = dict:fetch_keys(Map0),
+debug_pp_map(#map{dict = Dict}=Map) ->
+ Keys = dict:fetch_keys(Dict),
io:format("Map:\n", []),
lists:foreach(fun (Key) ->
io:format("\t~w :: ~s\n",
@@ -2836,37 +2717,27 @@ state__new(Callgraph, Tree, Plt, Module, Records, BehaviourTranslations) ->
TreeMap = build_tree_map(Tree),
Funs = dict:fetch_keys(TreeMap),
FunTab = init_fun_tab(Funs, dict:new(), TreeMap, Callgraph, Plt, Opaques),
- Work = init_work([get_label(Tree)]),
- Env = dict:store(top, map__new(), dict:new()),
+ ExportedFuns =
+ [Fun || Fun <- Funs--[top], dialyzer_callgraph:is_escaping(Fun, Callgraph)],
+ Work = init_work(ExportedFuns),
+ Env = lists:foldl(fun(Fun, Env) -> dict:store(Fun, map__new(), Env) end,
+ dict:new(), Funs),
#state{callgraph = Callgraph, envs = Env, fun_tab = FunTab, opaques = Opaques,
plt = Plt, races = dialyzer_races:new(), records = Records,
warning_mode = false, warnings = [], work = Work, tree_map = TreeMap,
module = Module, behaviour_api_dict = BehaviourTranslations}.
-state__mark_fun_as_handled(#state{fun_tab = FunTab} = State, Fun0) ->
- Fun = get_label(Fun0),
- case dict:find(Fun, FunTab) of
- {ok, {not_handled, Entry}} ->
- State#state{fun_tab = dict:store(Fun, Entry, FunTab)};
- {ok, {_, _}} ->
- State
- end.
-
state__warning_mode(#state{warning_mode = WM}) ->
WM.
state__set_warning_mode(#state{tree_map = TreeMap, fun_tab = FunTab,
races = Races} = State) ->
- ?debug("Starting warning pass\n", []),
+ ?debug("==========\nStarting warning pass\n==========\n", []),
Funs = dict:fetch_keys(TreeMap),
State#state{work = init_work([top|Funs--[top]]),
fun_tab = FunTab, warning_mode = true,
races = dialyzer_races:put_race_analysis(true, Races)}.
-state__restore_race_code(RaceCode, #state{callgraph = Callgraph} = State) ->
- State#state{callgraph = dialyzer_callgraph:put_race_code(RaceCode,
- Callgraph)}.
-
state__race_analysis(Analysis, #state{races = Races} = State) ->
State#state{races = dialyzer_races:put_race_analysis(Analysis, Races)}.
@@ -2929,7 +2800,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
{NotCalled, Ret} =
case dict:fetch(get_label(Fun), FunTab) of
{not_handled, {_Args0, Ret0}} -> {true, Ret0};
- {Args0, Ret0} -> {any_none(Args0), Ret0}
+ {_Args0, Ret0} -> {false, Ret0}
end,
case NotCalled of
true ->
@@ -3023,11 +2894,11 @@ state__lookup_record(Tag, Arity, #state{records = Records}) ->
error
end.
-state__get_args(Tree, #state{fun_tab = FunTab}) ->
+state__get_args_and_status(Tree, #state{fun_tab = FunTab}) ->
Fun = get_label(Tree),
case dict:find(Fun, FunTab) of
- {ok, {not_handled, {ArgTypes, _}}} -> ArgTypes;
- {ok, {ArgTypes, _}} -> ArgTypes
+ {ok, {not_handled, {ArgTypes, _}}} -> {ArgTypes, false};
+ {ok, {ArgTypes, _}} -> {ArgTypes, true}
end.
build_tree_map(Tree) ->
@@ -3043,7 +2914,7 @@ build_tree_map(Tree) ->
cerl_trees:fold(Fun, dict:new(), Tree).
init_fun_tab([top|Left], Dict, TreeMap, Callgraph, Plt, Opaques) ->
- NewDict = dict:store(top, {not_handled, {[], t_none()}}, Dict),
+ NewDict = dict:store(top, {[], t_none()}, Dict),
init_fun_tab(Left, NewDict, TreeMap, Callgraph, Plt, Opaques);
init_fun_tab([Fun|Left], Dict, TreeMap, Callgraph, Plt, Opaques) ->
Arity = cerl:fun_arity(dict:fetch(Fun, TreeMap)),
@@ -3059,11 +2930,12 @@ init_fun_tab([Fun|Left], Dict, TreeMap, Callgraph, Plt, Opaques) ->
false -> {Args, t_unit()}
end
end;
- false -> {lists:duplicate(Arity, t_none()), t_unit()}
+ false -> {not_handled, {lists:duplicate(Arity, t_none()), t_unit()}}
end,
- NewDict = dict:store(Fun, {not_handled, FunEntry}, Dict),
+ NewDict = dict:store(Fun, FunEntry, Dict),
init_fun_tab(Left, NewDict, TreeMap, Callgraph, Plt, Opaques);
init_fun_tab([], Dict, _TreeMap, _Callgraph, _Plt, _Opaques) ->
+ ?debug("DICT:~p\n",[dict:to_list(Dict)]),
Dict.
state__update_fun_env(Tree, Map, #state{envs = Envs} = State) ->
@@ -3085,7 +2957,8 @@ state__clean_not_called(#state{fun_tab = FunTab} = State) ->
end, FunTab),
State#state{fun_tab = NewFunTab}.
-state__all_fun_types(#state{fun_tab = FunTab}) ->
+state__all_fun_types(State) ->
+ #state{fun_tab = FunTab} = state__clean_not_called(State),
Tab1 = dict:erase(top, FunTab),
dict:map(fun(_Fun, {Args, Ret}) -> t_fun(Args, Ret)end, Tab1).
@@ -3094,7 +2967,9 @@ state__fun_type(Fun, #state{fun_tab = FunTab}) ->
if is_integer(Fun) -> Fun;
true -> get_label(Fun)
end,
- case dict:find(Label, FunTab) of
+ Entry = dict:find(Label, FunTab),
+ ?debug("FunType ~p:~p\n",[Label, Entry]),
+ case Entry of
{ok, {not_handled, {A, R}}} ->
t_fun(A, R);
{ok, {A, R}} ->
@@ -3202,23 +3077,9 @@ state__fun_info(Fun, #state{callgraph = CG, fun_tab = FunTab, plt = PLT}) ->
{not_handled, {_Args, Ret}} -> Ret;
{_Args, Ret} -> Ret
end,
+ ?debug("LocalRet: ~s\n", [t_to_string(LocalRet)]),
{Fun, Sig, Contract, LocalRet}.
-state__find_apply_return(Tree, #state{callgraph = Callgraph} = State) ->
- Apply = get_label(Tree),
- case dialyzer_callgraph:lookup_call_site(Apply, Callgraph) of
- error ->
- unknown;
- {ok, List} ->
- case lists:member(external, List) of
- true -> t_any();
- false ->
- FunTypes = [state__fun_type(F, State) || F <- List],
- Returns = [t_fun_range(F) || F <- FunTypes],
- t_sup(Returns)
- end
- end.
-
forward_args(Fun, ArgTypes, #state{work = Work, fun_tab = FunTab} = State) ->
{OldArgTypes, OldOut, Fixpoint} =
case dict:find(Fun, FunTab) of
@@ -3249,6 +3110,16 @@ state__cleanup(#state{callgraph = Callgraph,
races = dialyzer_races:cleanup(Races),
records = Records}.
+-spec state__duplicate(state()) -> state().
+
+state__duplicate(#state{callgraph = Callgraph} = State) ->
+ State#state{callgraph = dialyzer_callgraph:duplicate(Callgraph)}.
+
+-spec dispose_state(state()) -> ok.
+
+dispose_state(#state{callgraph = Callgraph}) ->
+ dialyzer_callgraph:dispose_race_server(Callgraph).
+
-spec state__get_callgraph(state()) -> dialyzer_callgraph:callgraph().
state__get_callgraph(#state{callgraph = Callgraph}) ->
@@ -3286,26 +3157,36 @@ state__records_only(#state{records = Records}) ->
%%%
%%% ===========================================================================
-renew_code(Fun, FunArgs, Code, WarningMode, Callgraph) ->
+is_race_analysis_enabled(#state{races = Races, callgraph = Callgraph}) ->
+ RaceDetection = dialyzer_callgraph:get_race_detection(Callgraph),
+ RaceAnalysis = dialyzer_races:get_race_analysis(Races),
+ RaceDetection andalso RaceAnalysis.
+
+get_race_list_and_size(#state{races = Races}) ->
+ dialyzer_races:get_race_list_and_size(Races).
+
+renew_race_code(#state{races = Races, callgraph = Callgraph,
+ warning_mode = WarningMode} = State) ->
case WarningMode of
- true -> Callgraph;
+ true -> State;
false ->
- RaceCode = dialyzer_callgraph:get_race_code(Callgraph),
- dialyzer_callgraph:put_race_code(
- dict:store(Fun, [FunArgs, Code], RaceCode), Callgraph)
+ NewCallgraph = dialyzer_callgraph:renew_race_code(Races, Callgraph),
+ State#state{callgraph = NewCallgraph}
end.
-renew_public_tables([Var], Table, WarningMode, Callgraph) ->
+renew_race_public_tables([Var], #state{races = Races, callgraph = Callgraph,
+ warning_mode = WarningMode} = State) ->
case WarningMode of
- true -> Callgraph;
+ true -> State;
false ->
+ Table = dialyzer_races:get_new_table(Races),
case Table of
- no_t -> Callgraph;
- _Other ->
- VarLabel = get_label(Var),
- PTables = dialyzer_callgraph:get_public_tables(Callgraph),
- dialyzer_callgraph:put_public_tables(
- lists:usort([VarLabel|PTables]), Callgraph)
+ no_t -> State;
+ _Other ->
+ VarLabel = get_label(Var),
+ NewCallgraph =
+ dialyzer_callgraph:renew_race_public_tables(VarLabel, Callgraph),
+ State#state{callgraph = NewCallgraph}
end
end.
@@ -3632,17 +3513,3 @@ strip_annotations(Tree) ->
debug_pp(_Tree, _UseHook) ->
ok.
-endif.
-
-%%----------------------------------------------------------------------------
-
--spec to_dot(dialyzer_callgraph:callgraph()) -> 'ok'.
-
--ifdef(DOT).
-to_dot(CG) ->
- dialyzer_callgraph:to_dot(CG).
--else.
-to_dot(_CG) ->
- ok.
--endif.
-
-%%----------------------------------------------------------------------------
diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl
index ccd80a4835..ac9844c22c 100644
--- a/lib/dialyzer/src/dialyzer_gui.erl
+++ b/lib/dialyzer/src/dialyzer_gui.erl
@@ -2,7 +2,7 @@
%%------------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,23 @@
%%%-----------------------------------------------------------------------
-module(dialyzer_gui).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,stop,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/1]).
@@ -494,6 +511,16 @@ gui_loop(#gui_state{add_all = AddAll, add_file = AddFile, add_rec = AddRec,
[ExtCalls]),
free_editor(State, "Analysis done", Msg),
gui_loop(State);
+ {BackendPid, ext_types, ExtTypes} ->
+ Map = fun({M,F,A}) -> io_lib:format("~p:~p/~p",[M,F,A]) end,
+ ExtTypeString = string:join(lists:map(Map, ExtTypes), "\n"),
+ Msg = io_lib:format("The following remote types are being used "
+ "but information about them is not available.\n"
+ "The analysis might get more precise by including "
+ "the modules containing these types and making sure "
+ "that they are exported:\n~s\n", [ExtTypeString]),
+ free_editor(State, "Analysis done", Msg),
+ gui_loop(State);
{BackendPid, log, LogMsg} ->
update_editor(Log, LogMsg),
gui_loop(State);
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl
index e711c15ea7..c6f7c56227 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.erl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.erl
@@ -2,7 +2,7 @@
%%------------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,39 +40,38 @@
%%------------------------------------------------------------------------
--type wx_object() :: any(). %% XXX: should be imported from wx
-
--record(menu, {file :: wx_object(),
- warnings :: wx_object(),
- plt :: wx_object(),
- options :: wx_object(),
- help :: wx_object()}).
-
--record(gui_state, {add :: wx_object(),
- add_dir :: wx_object(),
- add_rec :: wx_object(),
- chosen_box :: wx_object(),
+-record(menu, {file :: wx:wx_object(),
+ warnings :: wx:wx_object(),
+ plt :: wx:wx_object(),
+ options :: wx:wx_object(),
+ help :: wx:wx_object()}).
+-type menu() :: #menu{}.
+
+-record(gui_state, {add :: wx:wx_object(),
+ add_dir :: wx:wx_object(),
+ add_rec :: wx:wx_object(),
+ chosen_box :: wx:wx_object(),
analysis_pid :: pid(),
- del_file :: wx_object(),
+ del_file :: wx:wx_object(),
doc_plt :: dialyzer_plt:plt(),
- clear_chosen :: wx_object(),
- clear_log :: wx_object(),
- explain_warn :: wx_object(),
- clear_warn :: wx_object(),
+ clear_chosen :: wx:wx_object(),
+ clear_log :: wx:wx_object(),
+ explain_warn :: wx:wx_object(),
+ clear_warn :: wx:wx_object(),
init_plt :: dialyzer_plt:plt(),
- dir_entry :: wx_object(),
- file_box :: wx_object(),
+ dir_entry :: wx:wx_object(),
+ file_box :: wx:wx_object(),
files_to_analyze :: ordset(string()),
- gui :: wx_object(),
- log :: wx_object(),
- menu :: #menu{},
- mode :: wx_object(),
+ gui :: wx:wx_object(),
+ log :: wx:wx_object(),
+ menu :: menu(),
+ mode :: wx:wx_object(),
options :: #options{},
- run :: wx_object(),
- stop :: wx_object(),
- frame :: wx_object(),
- warnings_box :: wx_object(),
- explanation_box :: wx_object(),
+ run :: wx:wx_object(),
+ stop :: wx:wx_object(),
+ frame :: wx:wx_object(),
+ warnings_box :: wx:wx_object(),
+ explanation_box :: wx:wx_object(),
wantedWarnings :: list(),
rawWarnings :: list(),
backend_pid :: pid(),
@@ -193,48 +192,50 @@ create_window(Wx, #options{init_plts = InitPltFiles} = DialyzerOptions) ->
RunButtons = wxBoxSizer:new(?wxHORIZONTAL),
Buttons = wxFlexGridSizer:new(3),
- wxSizer:add(ChooseButtons, DeleteButton, ?BorderOpt),
- wxSizer:add(ChooseButtons, DeleteAllButton, ?BorderOpt),
- wxSizer:add(ChooseItem, Lab1, Center),
- wxSizer:add(ChooseItem, ChosenBox, Opts),
- wxSizer:add(ChooseItem, ChooseButtons, ?BorderOpt),
- wxSizer:add(FileTypeItem, OptionsLabel),
- wxSizer:add(FileTypeItem, FileType, [{border, 5}, {flag, ?wxALL}]),
- wxSizer:add(LogItem, LogLabel, Center),
- wxSizer:add(LogItem, LogBox, Opts3),
- wxSizer:add(LogItem, ClearLogButton, ?BorderOpt),
- wxSizer:add(FileItem, FileLabel),
- wxSizer:add(FileItem, FilePicker),
- wxSizer:add(DirItem, DirLabel),
- wxSizer:add(DirItem, DirPicker),
- wxSizer:add(AddDirButtons, AddDirButton, ?BorderOpt),
- wxSizer:add(AddDirButtons, AddRecButton, ?BorderOpt),
- wxSizer:add(FileDirItem, FileItem),
- wxSizer:add(FileDirItem, AddButton, ?BorderOpt),
- wxSizer:add(FileDirItem, DirItem, ?BorderOpt),
- wxSizer:add(FileDirItem, AddDirButtons, ?BorderOpt),
- wxSizer:add(WarnButtons, ExplainWarnButton, ?BorderOpt),
- wxSizer:add(WarnButtons, ClearWarningsButton, ?BorderOpt),
- wxSizer:add(RunButtons, RunButton, ?BorderOpt),
- wxSizer:add(RunButtons, StopButton, ?BorderOpt),
- wxSizer:add(Buttons, WarnButtons),
- wxSizer:add(Buttons, wxStaticText:new(Frame, ?LABEL7, ""), [{flag, ?wxEXPAND}]),
- wxSizer:add(Buttons, RunButtons),
- wxFlexGridSizer:addGrowableCol(Buttons, 1),
- wxSizer:add(WarningsItem, WarningsLabel, Center),
- wxSizer:add(WarningsItem, WarningsBox, Opts3),
- wxSizer:add(WarningsItem, Buttons, [{flag, ?wxEXPAND bor ?wxALL},?Border]),
-
- wxSizer:add(Left, ChooseItem, Opts),
- wxSizer:add(Left, FileDirItem, [{proportion, 1}, {border, 60}, {flag, ?wxTOP}]),
- wxSizer:add(RightUp, FileTypeItem, ?BorderOpt),
- wxSizer:add(RightUp, LogItem, Opts3),
- wxSizer:add(Right, RightUp, Opts3),
- wxSizer:add(Right, WarningsItem, Opts3),
- wxSizer:add(Top, Left, Opts),
- wxSizer:add(Top, Right, Opts3),
-
- wxSizer:add(All, Top, Opts),
+ _ = wxSizer:add(ChooseButtons, DeleteButton, ?BorderOpt),
+ _ = wxSizer:add(ChooseButtons, DeleteAllButton, ?BorderOpt),
+ _ = wxSizer:add(ChooseItem, Lab1, Center),
+ _ = wxSizer:add(ChooseItem, ChosenBox, Opts),
+ _ = wxSizer:add(ChooseItem, ChooseButtons, ?BorderOpt),
+ _ = wxSizer:add(FileTypeItem, OptionsLabel),
+ _ = wxSizer:add(FileTypeItem, FileType, [{border, 5}, {flag, ?wxALL}]),
+ _ = wxSizer:add(LogItem, LogLabel, Center),
+ _ = wxSizer:add(LogItem, LogBox, Opts3),
+ _ = wxSizer:add(LogItem, ClearLogButton, ?BorderOpt),
+ _ = wxSizer:add(FileItem, FileLabel),
+ _ = wxSizer:add(FileItem, FilePicker),
+ _ = wxSizer:add(DirItem, DirLabel),
+ _ = wxSizer:add(DirItem, DirPicker),
+ _ = wxSizer:add(AddDirButtons, AddDirButton, ?BorderOpt),
+ _ = wxSizer:add(AddDirButtons, AddRecButton, ?BorderOpt),
+ _ = wxSizer:add(FileDirItem, FileItem),
+ _ = wxSizer:add(FileDirItem, AddButton, ?BorderOpt),
+ _ = wxSizer:add(FileDirItem, DirItem, ?BorderOpt),
+ _ = wxSizer:add(FileDirItem, AddDirButtons, ?BorderOpt),
+ _ = wxSizer:add(WarnButtons, ExplainWarnButton, ?BorderOpt),
+ _ = wxSizer:add(WarnButtons, ClearWarningsButton, ?BorderOpt),
+ _ = wxSizer:add(RunButtons, RunButton, ?BorderOpt),
+ _ = wxSizer:add(RunButtons, StopButton, ?BorderOpt),
+ _ = wxSizer:add(Buttons, WarnButtons),
+ _ = wxSizer:add(Buttons, wxStaticText:new(Frame, ?LABEL7, ""),
+ [{flag, ?wxEXPAND}]),
+ _ = wxSizer:add(Buttons, RunButtons),
+ _ = wxFlexGridSizer:addGrowableCol(Buttons, 1),
+ _ = wxSizer:add(WarningsItem, WarningsLabel, Center),
+ _ = wxSizer:add(WarningsItem, WarningsBox, Opts3),
+ _ = wxSizer:add(WarningsItem, Buttons,
+ [{flag, ?wxEXPAND bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Left, ChooseItem, Opts),
+ _ = wxSizer:add(Left, FileDirItem,
+ [{proportion, 1}, {border, 60}, {flag, ?wxTOP}]),
+ _ = wxSizer:add(RightUp, FileTypeItem, ?BorderOpt),
+ _ = wxSizer:add(RightUp, LogItem, Opts3),
+ _ = wxSizer:add(Right, RightUp, Opts3),
+ _ = wxSizer:add(Right, WarningsItem, Opts3),
+ _ = wxSizer:add(Top, Left, Opts),
+ _ = wxSizer:add(Top, Right, Opts3),
+
+ _ = wxSizer:add(All, Top, Opts),
wxWindow:setSizer(Frame, All),
wxWindow:setSizeHints(Frame, {1150,600}),
wxWindow:show(Frame),
@@ -295,91 +296,67 @@ create_window(Wx, #options{init_plts = InitPltFiles} = DialyzerOptions) ->
createFileMenu() ->
FileMenu = wxMenu:new(),
- wxMenu:append(FileMenu, wxMenuItem:new([{id, ?menuID_FILE_SAVE_WARNINGS},
- {text, "Save &Warnings"}])),
- wxMenu:append(FileMenu, wxMenuItem:new([{id, ?menuID_FILE_SAVE_LOG},
- {text, "Save &Log"}])),
- wxMenu:append(FileMenu, wxMenuItem:new([{id, ?menuID_FILE_QUIT},
- {text, "E&xit\tAlt-X"}])),
+ _ = wxMenu:append(FileMenu, wxMenuItem:new([{id, ?menuID_FILE_SAVE_WARNINGS},
+ {text, "Save &Warnings"}])),
+ _ = wxMenu:append(FileMenu, wxMenuItem:new([{id, ?menuID_FILE_SAVE_LOG},
+ {text, "Save &Log"}])),
+ _ = wxMenu:append(FileMenu, wxMenuItem:new([{id, ?menuID_FILE_QUIT},
+ {text, "E&xit\tAlt-X"}])),
FileMenu.
createWarningsMenu() ->
WarningsMenu = wxMenu:new(),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_MATCH_FAILURES,
- "Match failures"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_MATCH_FAILURES, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_FAIL_FUN_CALLS,
- "Failing function calls"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_FAIL_FUN_CALLS, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_BAD_FUN,
- "Bad fun applications"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_BAD_FUN, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_OPAQUE,
- "Opaqueness violations"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_OPAQUE, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_LIST_CONSTR,
- "Improper list constructions"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_LIST_CONSTR, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_UNUSED_FUN,
- "Unused functions"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_UNUSED_FUN, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_ERROR_HANDLING_FUN,
- "Error handling functions"),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_NO_RETURN_FUN,
- "Functions of no return"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_NO_RETURN_FUN, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_UNEXPORTED_FUN,
- "Call to unexported function"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_UNEXPORTED_FUN, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_RACE_CONDITIONS,
- "Possible race conditions"),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_WRONG_CONTRACTS,
- "Wrong contracts"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_WRONG_CONTRACTS, true),
- wxMenu:appendCheckItem(WarningsMenu,
- ?menuID_WARN_CONTRACT_SYNTAX,
- "Wrong contract syntax"),
- wxMenu:check(WarningsMenu, ?menuID_WARN_CONTRACT_SYNTAX, true),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_MATCH_FAILURES, "Match failures"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_FAIL_FUN_CALLS,
+ "Failing function calls"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_BAD_FUN, "Bad fun applications"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_OPAQUE, "Opaqueness violations"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_LIST_CONSTR,
+ "Improper list constructions"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_UNUSED_FUN, "Unused functions"),
+ _ = wxMenu:appendCheckItem(WarningsMenu, ?menuID_WARN_ERROR_HANDLING_FUN,
+ "Error handling functions"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_NO_RETURN_FUN,
+ "Functions of no return"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_UNEXPORTED_FUN,
+ "Call to unexported function"),
+ _ = wxMenu:appendCheckItem(WarningsMenu, ?menuID_WARN_RACE_CONDITIONS,
+ "Possible race conditions"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_WRONG_CONTRACTS, "Wrong contracts"),
+ addCheckedItem(WarningsMenu, ?menuID_WARN_CONTRACT_SYNTAX,
+ "Wrong contract syntax"),
WarningsMenu.
+addCheckedItem(Menu, ItemId, Str) ->
+ _ = wxMenu:appendCheckItem(Menu, ItemId, Str),
+ wxMenu:check(Menu, ItemId, true).
+
createPltMenu() ->
PltMenu = wxMenu:new(),
- wxMenu:appendCheckItem(PltMenu,
- ?menuID_PLT_INIT_EMPTY,
- "Init with empty PLT"),
- wxMenu:append(PltMenu, wxMenuItem:new([{id, ?menuID_PLT_SHOW_CONTENTS},
- {text, "Show contents"}])),
- wxMenu:append(PltMenu, wxMenuItem:new([{id, ?menuID_PLT_SEARCH_CONTENTS},
- {text, "Search contents"}])),
+ _ = wxMenu:appendCheckItem(PltMenu, ?menuID_PLT_INIT_EMPTY,
+ "Init with empty PLT"),
+ _ = wxMenu:append(PltMenu, wxMenuItem:new([{id, ?menuID_PLT_SHOW_CONTENTS},
+ {text, "Show contents"}])),
+ _ = wxMenu:append(PltMenu, wxMenuItem:new([{id, ?menuID_PLT_SEARCH_CONTENTS},
+ {text, "Search contents"}])),
PltMenu.
createOptionsMenu() ->
OptsMenu = wxMenu:new(),
- wxMenu:append(OptsMenu, wxMenuItem:new([{id, ?menuID_OPTIONS_MACRO},
- {text, "Manage Macro Definitions"}])),
- wxMenu:append(OptsMenu, wxMenuItem:new([{id, ?menuID_OPTIONS_INCLUDE_DIR},
- {text, "Manage Include Directories"}])),
+ _ = wxMenu:append(OptsMenu, wxMenuItem:new([{id, ?menuID_OPTIONS_MACRO},
+ {text, "Manage Macro Definitions"}])),
+ _ = wxMenu:append(OptsMenu, wxMenuItem:new([{id, ?menuID_OPTIONS_INCLUDE_DIR},
+ {text, "Manage Include Directories"}])),
OptsMenu.
createHelpMenu() ->
HelpMenu = wxMenu:new(),
- wxMenu:append(HelpMenu, wxMenuItem:new([{id, ?menuID_HELP_MANUAL},
- {text, "Manual"}])),
- wxMenu:append(HelpMenu, wxMenuItem:new([{id, ?menuID_HELP_WARNING_OPTIONS},
- {text, "Warning Options"}])),
- wxMenu:append(HelpMenu, wxMenuItem:new([{id, ?menuID_HELP_ABOUT},
- {text, "About"}])),
+ _ = wxMenu:append(HelpMenu, wxMenuItem:new([{id, ?menuID_HELP_MANUAL},
+ {text, "Manual"}])),
+ _ = wxMenu:append(HelpMenu, wxMenuItem:new([{id, ?menuID_HELP_WARNING_OPTIONS},
+ {text, "Warning Options"}])),
+ _ = wxMenu:append(HelpMenu, wxMenuItem:new([{id, ?menuID_HELP_ABOUT},
+ {text, "About"}])),
HelpMenu.
%% ----------------------------------------------------------------
@@ -503,6 +480,16 @@ gui_loop(#gui_state{backend_pid = BackendPid, doc_plt = DocPlt,
[ExtCalls]),
free_editor(State,"Analysis Done", Msg),
gui_loop(State);
+ {BackendPid, ext_types, ExtTypes} ->
+ Map = fun({M,F,A}) -> io_lib:format("~p:~p/~p",[M,F,A]) end,
+ ExtTypeString = string:join(lists:map(Map, ExtTypes), "\n"),
+ Msg = io_lib:format("The following remote types are being used "
+ "but information about them is not available.\n"
+ "The analysis might get more precise by including "
+ "the modules containing these types and making sure "
+ "that they are exported:\n~s\n", [ExtTypeString]),
+ free_editor(State, "Analysis done", Msg),
+ gui_loop(State);
{BackendPid, log, LogMsg} ->
update_editor(Log, LogMsg),
gui_loop(State);
@@ -574,20 +561,20 @@ search_doc_plt(#gui_state{gui = Wx} = State) ->
ArLayout = wxBoxSizer:new(?wxVERTICAL),
Buttons = wxBoxSizer:new(?wxHORIZONTAL),
- wxSizer:add(ModLayout, ModLabel, ?BorderOpt),
- wxSizer:add(ModLayout,ModText, ?BorderOpt),
- wxSizer:add(FunLayout, FunLabel, ?BorderOpt),
- wxSizer:add(FunLayout,FunText, ?BorderOpt),
- wxSizer:add(ArLayout, ArLabel, ?BorderOpt),
- wxSizer:add(ArLayout,ArText, ?BorderOpt),
- wxSizer:add(Buttons, SearchButton, ?BorderOpt),
- wxSizer:add(Buttons,Cancel, ?BorderOpt),
-
- wxSizer:add(Top, ModLayout),
- wxSizer:add(Top, FunLayout),
- wxSizer:add(Top, ArLayout),
- wxSizer:add(Layout, Top,[{flag, ?wxALIGN_CENTER}]),
- wxSizer:add(Layout, Buttons,[{flag, ?wxALIGN_CENTER bor ?wxBOTTOM}]),
+ _ = wxSizer:add(ModLayout, ModLabel, ?BorderOpt),
+ _ = wxSizer:add(ModLayout, ModText, ?BorderOpt),
+ _ = wxSizer:add(FunLayout, FunLabel, ?BorderOpt),
+ _ = wxSizer:add(FunLayout,FunText, ?BorderOpt),
+ _ = wxSizer:add(ArLayout, ArLabel, ?BorderOpt),
+ _ = wxSizer:add(ArLayout,ArText, ?BorderOpt),
+ _ = wxSizer:add(Buttons, SearchButton, ?BorderOpt),
+ _ = wxSizer:add(Buttons,Cancel, ?BorderOpt),
+
+ _ = wxSizer:add(Top, ModLayout),
+ _ = wxSizer:add(Top, FunLayout),
+ _ = wxSizer:add(Top, ArLayout),
+ _ = wxSizer:add(Layout, Top,[{flag, ?wxALIGN_CENTER}]),
+ _ = wxSizer:add(Layout, Buttons,[{flag, ?wxALIGN_CENTER bor ?wxBOTTOM}]),
wxFrame:connect(Dialog, close_window),
wxWindow:setSizer(Dialog, Layout),
wxFrame:show(Dialog),
@@ -645,14 +632,15 @@ error_sms(State, Message) ->
output_sms(State, ?DIALYZER_ERROR_TITLE, Message, error).
output_sms(#gui_state{frame = Frame}, Title, Message, Type) ->
- case Type of
- error ->
- MessageWin = wxMessageDialog:new(Frame,Message,[{caption, Title},{style, ?wxOK bor ?wxICON_ERROR}]);
- info ->
- MessageWin = wxMessageDialog:new(Frame,Message,[{caption, Title},{style, ?wxOK bor ?wxICON_INFORMATION}])
- end,
+ Style = case Type of
+ error -> ?wxOK bor ?wxICON_ERROR;
+ info -> ?wxOK bor ?wxICON_INFORMATION
+ end,
+ Options = [{caption, Title}, {style, Style}],
+ MessageWin = wxMessageDialog:new(Frame, Message, Options),
wxWindow:setSizeHints(MessageWin, {350,100}),
- wxDialog:showModal(MessageWin).
+ wxDialog:showModal(MessageWin),
+ ok.
free_editor(#gui_state{gui = Wx, frame = Frame}, Title, Contents0) ->
Contents = lists:flatten(Contents0),
@@ -676,8 +664,9 @@ free_editor(#gui_state{gui = Wx, frame = Frame}, Title, Contents0) ->
wxButton:connect(Ok, command_button_clicked),
Layout = wxBoxSizer:new(?wxVERTICAL),
- wxSizer:add(Layout, Editor, ?BorderOpt),
- wxSizer:add(Layout, Ok, [{flag, ?wxALIGN_CENTER bor ?wxBOTTOM bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Layout, Editor, ?BorderOpt),
+ Flag = ?wxALIGN_CENTER bor ?wxBOTTOM bor ?wxALL,
+ _ = wxSizer:add(Layout, Ok, [{flag, Flag}, ?Border]),
wxWindow:setSizer(Win, Layout),
wxWindow:show(Win),
show_info_loop(Frame, Win).
@@ -687,7 +676,7 @@ show_info_loop(Frame, Win) ->
#wx{id = ?Message_Ok, event = #wxCommand{type = command_button_clicked}} ->
wxWindow:destroy(Win);
#wx{id = ?Message, event = #wxClose{type = close_window}} ->
- wxWindow:destroy(Win);
+ wxWindow:destroy(Win);
#wx{event = #wxClose{type = close_window}} ->
wxWindow:destroy(Frame)
end.
@@ -814,7 +803,7 @@ build_analysis_record(#gui_state{mode = Mode, menu = Menu, options = Options,
1 -> src_code
end,
InitPlt =
- case wxMenu:isChecked(Menu#menu.plt,?menuID_PLT_INIT_EMPTY) of
+ case wxMenu:isChecked(Menu#menu.plt, ?menuID_PLT_INIT_EMPTY) of
true -> dialyzer_plt:new();
false -> InitPlt0
end,
@@ -912,13 +901,14 @@ save_file(#gui_state{frame = Frame, warnings_box = WBox, log = Log} = State, Typ
{message, Message},
{style,?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT}]),
case wxFileDialog:showModal(FileDialog) of
- ?wxID_OK -> Path = wxFileDialog:getPath(FileDialog),
- case wxTextCtrl:saveFile(Box,[{file,Path}]) of
- true -> ok;
- false -> error_sms(State,"Could not write to file:\n" ++ Path)
- end;
+ ?wxID_OK ->
+ Path = wxFileDialog:getPath(FileDialog),
+ case wxTextCtrl:saveFile(Box,[{file,Path}]) of
+ true -> ok;
+ false -> error_sms(State, "Could not write to file:\n" ++ Path)
+ end;
?wxID_CANCEL -> wxWindow:destroy(FileDialog);
- _ -> error_sms(State,"Could not write to file:\n")
+ _ -> error_sms(State, "Could not write to file:\n")
end
end.
@@ -952,16 +942,16 @@ include_dialog(#gui_state{gui = Wx, frame = Frame, options = Options}) ->
Buttons = wxBoxSizer:new(?wxHORIZONTAL),
Buttons1 = wxBoxSizer:new(?wxHORIZONTAL),
- wxSizer:add(Layout, DirLabel, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
- wxSizer:add(Layout, DirPicker, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
- wxSizer:add(Layout,AddButton, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
- wxSizer:add(Layout,Box, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
- wxSizer:add(Buttons, DeleteButton, ?BorderOpt),
- wxSizer:add(Buttons, DeleteAllButton, ?BorderOpt),
- wxSizer:add(Layout,Buttons, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
- wxSizer:add(Buttons1, Ok, ?BorderOpt),
- wxSizer:add(Buttons1,Cancel, ?BorderOpt),
- wxSizer:add(Layout,Buttons1,[{flag, ?wxALIGN_RIGHT bor ?wxBOTTOM}]),
+ _ = wxSizer:add(Layout, DirLabel, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+ _ = wxSizer:add(Layout, DirPicker, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+ _ = wxSizer:add(Layout,AddButton, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Layout,Box, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Buttons, DeleteButton, ?BorderOpt),
+ _ = wxSizer:add(Buttons, DeleteAllButton, ?BorderOpt),
+ _ = wxSizer:add(Layout,Buttons, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+ _ = wxSizer:add(Buttons1, Ok, ?BorderOpt),
+ _ = wxSizer:add(Buttons1,Cancel, ?BorderOpt),
+ _ = wxSizer:add(Layout,Buttons1,[{flag, ?wxALIGN_RIGHT bor ?wxBOTTOM}]),
wxFrame:connect(Dialog, close_window),
wxWindow:setSizer(Dialog, Layout),
@@ -1049,21 +1039,21 @@ macro_dialog(#gui_state{gui = Wx, frame = Frame, options = Options}) ->
Buttons = wxBoxSizer:new(?wxHORIZONTAL),
Buttons1 = wxBoxSizer:new(?wxHORIZONTAL),
- wxSizer:add(MacroItem, MacroLabel, ?BorderOpt),
- wxSizer:add(MacroItem, MacroText, ?BorderOpt),
- wxSizer:add(TermItem, TermLabel, ?BorderOpt),
- wxSizer:add(TermItem, TermText, ?BorderOpt),
- wxSizer:add(Item, MacroItem),
- wxSizer:add(Item, TermItem),
- wxSizer:add(Layout, Item, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
- wxSizer:add(Layout, AddButton, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
- wxSizer:add(Layout, Box, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
- wxSizer:add(Buttons, DeleteButton, ?BorderOpt),
- wxSizer:add(Buttons, DeleteAllButton, ?BorderOpt),
- wxSizer:add(Layout, Buttons, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
- wxSizer:add(Buttons1, Ok, ?BorderOpt),
- wxSizer:add(Buttons1, Cancel, ?BorderOpt),
- wxSizer:add(Layout, Buttons1, [{flag, ?wxALIGN_RIGHT bor ?wxBOTTOM}]),
+ _ = wxSizer:add(MacroItem, MacroLabel, ?BorderOpt),
+ _ = wxSizer:add(MacroItem, MacroText, ?BorderOpt),
+ _ = wxSizer:add(TermItem, TermLabel, ?BorderOpt),
+ _ = wxSizer:add(TermItem, TermText, ?BorderOpt),
+ _ = wxSizer:add(Item, MacroItem),
+ _ = wxSizer:add(Item, TermItem),
+ _ = wxSizer:add(Layout, Item, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+ _ = wxSizer:add(Layout, AddButton, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Layout, Box, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Buttons, DeleteButton, ?BorderOpt),
+ _ = wxSizer:add(Buttons, DeleteAllButton, ?BorderOpt),
+ _ = wxSizer:add(Layout, Buttons, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+ _ = wxSizer:add(Buttons1, Ok, ?BorderOpt),
+ _ = wxSizer:add(Buttons1, Cancel, ?BorderOpt),
+ _ = wxSizer:add(Layout, Buttons1, [{flag, ?wxALIGN_RIGHT bor ?wxBOTTOM}]),
wxFrame:connect(Dialog, close_window),
wxWindow:setSizer(Dialog, Layout),
@@ -1207,13 +1197,14 @@ show_explanation(#gui_state{gui = Wx} = State, Explanation) ->
wxButton:connect(Ok, command_button_clicked),
Layout = wxBoxSizer:new(?wxVERTICAL),
Buttons = wxBoxSizer:new(?wxHORIZONTAL),
- wxSizer:add(Buttons, ExplButton, ?BorderOpt),
- wxSizer:add(Buttons, Ok, ?BorderOpt),
- wxSizer:add(Layout, Editor,[{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
- wxSizer:add(Layout, Buttons,[{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+ _ = wxSizer:add(Buttons, ExplButton, ?BorderOpt),
+ _ = wxSizer:add(Buttons, Ok, ?BorderOpt),
+ _ = wxSizer:add(Layout, Editor, [{flag, ?wxALIGN_CENTER_HORIZONTAL bor ?wxALL}, ?Border]),
+ _ = wxSizer:add(Layout, Buttons,[{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
wxWindow:setSizer(Win, Layout),
wxWindow:show(Win),
- show_explanation_loop(State#gui_state{explanation_box = Editor}, Win, Explanation)
+ NewState = State#gui_state{explanation_box = Editor},
+ show_explanation_loop(NewState, Win, Explanation)
end.
show_explanation_loop(#gui_state{frame = Frame, expl_pid = ExplPid} = State, Win, Explanation) ->
diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl
index b2a67de8bd..06672e595f 100644
--- a/lib/dialyzer/src/dialyzer_options.erl
+++ b/lib/dialyzer/src/dialyzer_options.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -49,7 +49,9 @@ build(Opts) ->
?WARN_CALLGRAPH,
?WARN_CONTRACT_RANGE,
?WARN_CONTRACT_TYPES,
- ?WARN_CONTRACT_SYNTAX],
+ ?WARN_CONTRACT_SYNTAX,
+ ?WARN_BEHAVIOUR,
+ ?WARN_UNDEFINED_CALLBACK],
DefaultWarns1 = ordsets:from_list(DefaultWarns),
InitPlt = dialyzer_plt:get_default_plt(),
DefaultOpts = #options{},
@@ -192,6 +194,11 @@ build_options([{OptionName, Value} = Term|Rest], Options) ->
callgraph_file ->
assert_filename(Value),
build_options(Rest, Options#options{callgraph_file = Value});
+ timing ->
+ build_options(Rest, Options#options{timing = Value});
+ solvers ->
+ assert_solvers(Value),
+ build_options(Rest, Options#options{solvers = Value});
_ ->
bad_option("Unknown dialyzer command line option", Term)
end;
@@ -253,6 +260,15 @@ is_plt_mode(plt_remove) -> true;
is_plt_mode(plt_check) -> true;
is_plt_mode(succ_typings) -> false.
+assert_solvers([]) ->
+ ok;
+assert_solvers([v1|Terms]) ->
+ assert_solvers(Terms);
+assert_solvers([v2|Terms]) ->
+ assert_solvers(Terms);
+assert_solvers([Term|_]) ->
+ bad_option("Illegal value for solver", Term).
+
-spec build_warnings([atom()], [dial_warning()]) -> [dial_warning()].
build_warnings([Opt|Opts], Warnings) ->
@@ -275,14 +291,16 @@ build_warnings([Opt|Opts], Warnings) ->
no_contracts ->
Warnings1 = ordsets:del_element(?WARN_CONTRACT_SYNTAX, Warnings),
ordsets:del_element(?WARN_CONTRACT_TYPES, Warnings1);
+ no_behaviours ->
+ ordsets:del_element(?WARN_BEHAVIOUR, Warnings);
+ no_undefined_callbacks ->
+ ordsets:del_element(?WARN_UNDEFINED_CALLBACK, Warnings);
unmatched_returns ->
ordsets:add_element(?WARN_UNMATCHED_RETURN, Warnings);
error_handling ->
ordsets:add_element(?WARN_RETURN_ONLY_EXIT, Warnings);
race_conditions ->
ordsets:add_element(?WARN_RACE_CONDITION, Warnings);
- behaviours ->
- ordsets:add_element(?WARN_BEHAVIOUR, Warnings);
specdiffs ->
S = ordsets:from_list([?WARN_CONTRACT_SUBTYPE,
?WARN_CONTRACT_SUPERTYPE,
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 6033d7f17c..5f64099210 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -2,7 +2,7 @@
%%----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,8 +31,7 @@
-export([check_plt/3,
compute_md5_from_files/1,
contains_mfa/2,
- contains_module/2,
- delete_contract_list/2,
+ all_modules/1,
delete_list/2,
delete_module/2,
included_files/1,
@@ -43,10 +42,12 @@
%% insert/3,
insert_list/2,
insert_contract_list/2,
+ insert_callbacks/2,
insert_types/2,
insert_exported_types/2,
lookup/2,
lookup_contract/2,
+ lookup_callbacks/2,
lookup_module/2,
merge_plts/1,
merge_plts_or_report_conflicts/2,
@@ -54,7 +55,10 @@
plt_and_info_from_file/1,
get_specs/1,
get_specs/4,
- to_file/4]).
+ to_file/4,
+ get_mini_plt/1,
+ restore_full_plt/2
+ ]).
%% Debug utilities
-export([pp_non_returning/0, pp_mod/1]).
@@ -79,8 +83,15 @@
-record(plt, {info = table_new() :: dict(),
types = table_new() :: dict(),
contracts = table_new() :: dict(),
+ callbacks = table_new() :: dict(),
exported_types = sets:new() :: set()}).
--opaque plt() :: #plt{}.
+
+-record(mini_plt, {info :: ets:tid(),
+ contracts :: ets:tid(),
+ callbacks :: ets:tid()
+ }).
+
+-opaque plt() :: #plt{} | #mini_plt{}.
-include("dialyzer.hrl").
@@ -91,6 +102,7 @@
file_md5_list = [] :: [file_md5()],
info = dict:new() :: dict(),
contracts = dict:new() :: dict(),
+ callbacks = dict:new() :: dict(),
types = dict:new() :: dict(),
exported_types = sets:new() :: set(),
mod_deps :: mod_deps(),
@@ -105,57 +117,72 @@ new() ->
-spec delete_module(plt(), atom()) -> plt().
-delete_module(#plt{info = Info, types = Types, contracts = Contracts,
+delete_module(#plt{info = Info, types = Types,
+ contracts = Contracts,
+ callbacks = Callbacks,
exported_types = ExpTypes}, Mod) ->
#plt{info = table_delete_module(Info, Mod),
types = table_delete_module2(Types, Mod),
contracts = table_delete_module(Contracts, Mod),
+ callbacks = table_delete_module(Callbacks, Mod),
exported_types = table_delete_module1(ExpTypes, Mod)}.
-spec delete_list(plt(), [mfa() | integer()]) -> plt().
-delete_list(#plt{info = Info, types = Types, contracts = Contracts,
+delete_list(#plt{info = Info, types = Types,
+ contracts = Contracts,
+ callbacks = Callbacks,
exported_types = ExpTypes}, List) ->
#plt{info = table_delete_list(Info, List),
types = Types,
contracts = table_delete_list(Contracts, List),
+ callbacks = table_delete_list(Callbacks, List),
exported_types = ExpTypes}.
-spec insert_contract_list(plt(), dialyzer_contracts:plt_contracts()) -> plt().
-insert_contract_list(#plt{contracts = Contracts} = PLT, List) ->
- PLT#plt{contracts = table_insert_list(Contracts, List)}.
+insert_contract_list(#mini_plt{contracts = Contracts} = PLT, List) ->
+ true = ets:insert(Contracts, List),
+ PLT.
+
+-spec insert_callbacks(plt(), dialyzer_codeserver:codeserver()) -> plt().
+
+insert_callbacks(#plt{callbacks = Callbacks} = Plt, Codeserver) ->
+ List = dialyzer_codeserver:get_callbacks(Codeserver),
+ Plt#plt{callbacks = table_insert_list(Callbacks, List)}.
-spec lookup_contract(plt(), mfa_patt()) -> 'none' | {'value', #contract{}}.
-lookup_contract(#plt{contracts = Contracts},
+lookup_contract(#mini_plt{contracts = ETSContracts},
{M, F, _} = MFA) when is_atom(M), is_atom(F) ->
- table_lookup(Contracts, MFA).
-
--spec delete_contract_list(plt(), [mfa()]) -> plt().
+ ets_table_lookup(ETSContracts, MFA).
-delete_contract_list(#plt{contracts = Contracts} = PLT, List) ->
- PLT#plt{contracts = table_delete_list(Contracts, List)}.
+-spec lookup_callbacks(plt(), module()) ->
+ 'none' | {'value', [{mfa(), {{Filename::string(),
+ Line::pos_integer()},
+ #contract{}}}]}.
-%% -spec insert(plt(), mfa() | integer(), {_, _}) -> plt().
-%%
-%% insert(#plt{info = Info} = PLT, Id, Types) ->
-%% PLT#plt{info = table_insert(Info, Id, Types)}.
+lookup_callbacks(#mini_plt{callbacks = ETSCallbacks}, Mod) when is_atom(Mod) ->
+ ets_table_lookup(ETSCallbacks, Mod).
-type ret_args_types() :: {erl_types:erl_type(), [erl_types:erl_type()]}.
-spec insert_list(plt(), [{mfa() | integer(), ret_args_types()}]) -> plt().
-insert_list(#plt{info = Info} = PLT, List) ->
- PLT#plt{info = table_insert_list(Info, List)}.
+insert_list(#mini_plt{info = Info} = PLT, List) ->
+ true = ets:insert(Info, List),
+ PLT.
-spec lookup(plt(), integer() | mfa_patt()) ->
'none' | {'value', ret_args_types()}.
-lookup(#plt{info = Info}, {M, F, _} = MFA) when is_atom(M), is_atom(F) ->
- table_lookup(Info, MFA);
-lookup(#plt{info = Info}, Label) when is_integer(Label) ->
- table_lookup(Info, Label).
+lookup(Plt, {M, F, _} = MFA) when is_atom(M), is_atom(F) ->
+ lookup_1(Plt, MFA);
+lookup(Plt, Label) when is_integer(Label) ->
+ lookup_1(Plt, Label).
+
+lookup_1(#mini_plt{info = Info}, MFAorLabel) ->
+ ets_table_lookup(Info, MFAorLabel).
-spec insert_types(plt(), dict()) -> plt().
@@ -184,10 +211,10 @@ get_exported_types(#plt{exported_types = ExpTypes}) ->
lookup_module(#plt{info = Info}, M) when is_atom(M) ->
table_lookup_module(Info, M).
--spec contains_module(plt(), atom()) -> boolean().
+-spec all_modules(plt()) -> set().
-contains_module(#plt{info = Info, contracts = Cs}, M) when is_atom(M) ->
- table_contains_module(Info, M) orelse table_contains_module(Cs, M).
+all_modules(#plt{info = Info, contracts = Cs}) ->
+ sets:union(table_all_modules(Info), table_all_modules(Cs)).
-spec contains_mfa(plt(), mfa()) -> boolean().
@@ -230,6 +257,7 @@ from_file(FileName, ReturnInfo) ->
Plt = #plt{info = Rec#file_plt.info,
types = Rec#file_plt.types,
contracts = Rec#file_plt.contracts,
+ callbacks = Rec#file_plt.callbacks,
exported_types = Rec#file_plt.exported_types},
case ReturnInfo of
false -> Plt;
@@ -284,26 +312,34 @@ get_record_from_file(FileName) ->
-spec merge_plts([plt()]) -> plt().
merge_plts(List) ->
- InfoList = [Info || #plt{info = Info} <- List],
- TypesList = [Types || #plt{types = Types} <- List],
- ExpTypesList = [ExpTypes || #plt{exported_types = ExpTypes} <- List],
- ContractsList = [Contracts || #plt{contracts = Contracts} <- List],
+ {InfoList, TypesList, ExpTypesList, ContractsList, CallbacksList} =
+ group_fields(List),
#plt{info = table_merge(InfoList),
types = table_merge(TypesList),
exported_types = sets_merge(ExpTypesList),
- contracts = table_merge(ContractsList)}.
+ contracts = table_merge(ContractsList),
+ callbacks = table_merge(CallbacksList)
+ }.
-spec merge_disj_plts([plt()]) -> plt().
merge_disj_plts(List) ->
+ {InfoList, TypesList, ExpTypesList, ContractsList, CallbacksList} =
+ group_fields(List),
+ #plt{info = table_disj_merge(InfoList),
+ types = table_disj_merge(TypesList),
+ exported_types = sets_disj_merge(ExpTypesList),
+ contracts = table_disj_merge(ContractsList),
+ callbacks = table_disj_merge(CallbacksList)
+ }.
+
+group_fields(List) ->
InfoList = [Info || #plt{info = Info} <- List],
TypesList = [Types || #plt{types = Types} <- List],
ExpTypesList = [ExpTypes || #plt{exported_types = ExpTypes} <- List],
ContractsList = [Contracts || #plt{contracts = Contracts} <- List],
- #plt{info = table_disj_merge(InfoList),
- types = table_disj_merge(TypesList),
- exported_types = sets_disj_merge(ExpTypesList),
- contracts = table_disj_merge(ContractsList)}.
+ CallbacksList = [Callbacks || #plt{callbacks = Callbacks} <- List],
+ {InfoList, TypesList, ExpTypesList, ContractsList, CallbacksList}.
-spec merge_plts_or_report_conflicts([file:filename()], [plt()]) -> plt().
@@ -329,7 +365,7 @@ find_duplicates(List) ->
to_file(FileName,
#plt{info = Info, types = Types, contracts = Contracts,
- exported_types = ExpTypes},
+ callbacks = Callbacks, exported_types = ExpTypes},
ModDeps, {MD5, OldModDeps}) ->
NewModDeps = dict:merge(fun(_Key, OldVal, NewVal) ->
ordsets:union(OldVal, NewVal)
@@ -340,6 +376,7 @@ to_file(FileName,
file_md5_list = MD5,
info = Info,
contracts = Contracts,
+ callbacks = Callbacks,
types = Types,
exported_types = ExpTypes,
mod_deps = NewModDeps,
@@ -472,6 +509,34 @@ init_md5_list_1([], DiffList, Acc) ->
init_md5_list_1(Md5List, [], Acc) ->
{ok, lists:reverse(Acc, Md5List)}.
+-spec get_mini_plt(plt()) -> plt().
+
+get_mini_plt(#plt{info = Info, contracts = Contracts, callbacks = Callbacks}) ->
+ [ETSInfo, ETSContracts, ETSCallbacks] =
+ [ets:new(Name, [public]) || Name <- [plt_info, plt_contracts, plt_callbacks]],
+ CallbackList = dict:to_list(Callbacks),
+ CallbacksByModule =
+ [{M, [Cb || {{M1,_,_},_} = Cb <- CallbackList, M1 =:= M]} ||
+ M <- lists:usort([M || {{M,_,_},_} <- CallbackList])],
+ [true, true] =
+ [ets:insert(ETS, dict:to_list(Data)) ||
+ {ETS, Data} <- [{ETSInfo, Info}, {ETSContracts, Contracts}]],
+ true = ets:insert(ETSCallbacks, CallbacksByModule),
+ #mini_plt{info = ETSInfo, contracts = ETSContracts, callbacks = ETSCallbacks};
+get_mini_plt(undefined) ->
+ undefined.
+
+-spec restore_full_plt(plt(), plt()) -> plt().
+
+restore_full_plt(#mini_plt{info = ETSInfo, contracts = ETSContracts}, Plt) ->
+ Info = dict:from_list(ets:tab2list(ETSInfo)),
+ Contracts = dict:from_list(ets:tab2list(ETSContracts)),
+ ets:delete(ETSContracts),
+ ets:delete(ETSInfo),
+ Plt#plt{info = Info, contracts = Contracts};
+restore_full_plt(undefined, undefined) ->
+ undefined.
+
%%---------------------------------------------------------------------------
%% Edoc
@@ -564,6 +629,13 @@ table_lookup(Plt, Obj) ->
{ok, Val} -> {value, Val}
end.
+ets_table_lookup(Plt, Obj) ->
+ try ets:lookup_element(Plt, Obj, 2) of
+ Val -> {value, Val}
+ catch
+ _:_ -> none
+ end.
+
table_lookup_module(Plt, Mod) ->
List = dict:fold(fun(Key, Val, Acc) ->
case Key of
@@ -577,10 +649,12 @@ table_lookup_module(Plt, Mod) ->
false -> {value, List}
end.
-table_contains_module(Plt, Mod) ->
- dict:fold(fun({M, _F, _A}, _Val, _Acc) when M =:= Mod -> true;
- (_, _, Acc) -> Acc
- end, false, Plt).
+table_all_modules(Plt) ->
+ Fold =
+ fun({M, _F, _A}, _Val, Acc) -> sets:add_element(M, Acc);
+ (_, _, Acc) -> Acc
+ end,
+ dict:fold(Fold, sets:new(), Plt).
table_merge([H|T]) ->
table_merge(T, H).
diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl
index ee9d5e88a3..cdb9f25999 100644
--- a/lib/dialyzer/src/dialyzer_races.erl
+++ b/lib/dialyzer/src/dialyzer_races.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +36,11 @@
-export([beg_clause_new/3, cleanup/1, end_case_new/1, end_clause_new/3,
get_curr_fun/1, get_curr_fun_args/1, get_new_table/1,
get_race_analysis/1, get_race_list/1, get_race_list_size/1,
+ get_race_list_and_size/1,
let_tag_new/2, new/0, put_curr_fun/3, put_fun_args/2,
put_race_analysis/2, put_race_list/3]).
--export_type([races/0, mfa_or_funlbl/0, core_vars/0]).
+-export_type([races/0, core_vars/0]).
-include("dialyzer.hrl").
@@ -66,8 +67,6 @@
%%%
%%% ===========================================================================
--type mfa_or_funlbl() :: label() | mfa().
-
-type label_type() :: label() | [label()] | {label()} | ?no_label.
-type args() :: [label_type() | [string()]].
-type core_vars() :: cerl:cerl() | ?no_arg | ?bypassed.
@@ -94,7 +93,7 @@
guard :: cerl:cerl()}).
-record(end_case, {clauses :: [#end_clause{}]}).
-record(curr_fun, {status :: 'in' | 'out',
- mfa :: mfa_or_funlbl(),
+ mfa :: dialyzer_callgraph:mfa_or_funlbl(),
label :: label(),
def_vars :: [core_vars()],
arg_types :: [erl_types:erl_type()],
@@ -107,8 +106,8 @@
state :: _, %% XXX: recursive
file_line :: file_line(),
var_map :: dict()}).
--record(fun_call, {caller :: mfa_or_funlbl(),
- callee :: mfa_or_funlbl(),
+-record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(),
+ callee :: dialyzer_callgraph:mfa_or_funlbl(),
arg_types :: [erl_types:erl_type()],
vars :: [core_vars()]}).
-record(let_tag, {var :: var_to_map1(),
@@ -130,10 +129,10 @@
vars :: [core_vars()],
file_line :: file_line(),
index :: non_neg_integer(),
- fun_mfa :: mfa_or_funlbl(),
+ fun_mfa :: dialyzer_callgraph:mfa_or_funlbl(),
fun_label :: label()}).
--record(races, {curr_fun :: mfa_or_funlbl(),
+-record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl(),
curr_fun_label :: label(),
curr_fun_args = 'empty' :: core_args(),
new_table = 'no_t' :: table(),
@@ -158,7 +157,8 @@
%%%
%%% ===========================================================================
--spec store_race_call(mfa_or_funlbl(), [erl_types:erl_type()], [core_vars()],
+-spec store_race_call(dialyzer_callgraph:mfa_or_funlbl(),
+ [erl_types:erl_type()], [core_vars()],
file_line(), dialyzer_dataflow:state()) ->
dialyzer_dataflow:state().
@@ -347,6 +347,7 @@ fixup_race_list(RaceWarnTag, WarnVarArgs, State) ->
DepList2 =
fixup_race_list_helper(NewParents, Calls, CurrFun, WarnVarArgs,
RaceWarnTag, NewState),
+ dialyzer_dataflow:dispose_state(CleanState),
lists:usort(cleanup_dep_calls(DepList1 ++ DepList2)).
fixup_race_list_helper(Parents, Calls, CurrFun, WarnVarArgs, RaceWarnTag,
@@ -381,13 +382,15 @@ fixup_race_forward_pullout(CurrFun, CurrFunLabel, Calls, Code, RaceList,
InitFun, WarnVarArgs, RaceWarnTag, RaceVarMap,
FunDefVars, FunCallVars, FunArgTypes, NestingLevel,
State) ->
+ TState = dialyzer_dataflow:state__duplicate(State),
{DepList, NewCurrFun, NewCurrFunLabel, NewCalls,
NewCode, NewRaceList, NewRaceVarMap, NewFunDefVars,
NewFunCallVars, NewFunArgTypes, NewNestingLevel} =
fixup_race_forward(CurrFun, CurrFunLabel, Calls, Code, RaceList,
InitFun, WarnVarArgs, RaceWarnTag, RaceVarMap,
FunDefVars, FunCallVars, FunArgTypes, NestingLevel,
- cleanup_race_code(State)),
+ cleanup_race_code(TState)),
+ dialyzer_dataflow:dispose_state(TState),
case NewCode of
[] -> DepList;
[#fun_call{caller = NewCurrFun, callee = Call, arg_types = FunTypes,
@@ -2405,7 +2408,7 @@ end_case_new(Clauses) ->
end_clause_new(Arg, Pats, Guard) ->
#end_clause{arg = Arg, pats = Pats, guard = Guard}.
--spec get_curr_fun(races()) -> mfa_or_funlbl().
+-spec get_curr_fun(races()) -> dialyzer_callgraph:mfa_or_funlbl().
get_curr_fun(#races{curr_fun = CurrFun}) ->
CurrFun.
@@ -2435,6 +2438,12 @@ get_race_list(#races{race_list = RaceList}) ->
get_race_list_size(#races{race_list_size = RaceListSize}) ->
RaceListSize.
+-spec get_race_list_and_size(races()) -> {code(), non_neg_integer()}.
+
+get_race_list_and_size(#races{race_list = RaceList,
+ race_list_size = RaceListSize}) ->
+ {RaceList, RaceListSize}.
+
-spec let_tag_new(var_to_map1(), var_to_map1()) -> #let_tag{}.
let_tag_new(Var, Arg) ->
@@ -2444,7 +2453,7 @@ let_tag_new(Var, Arg) ->
new() -> #races{}.
--spec put_curr_fun(mfa_or_funlbl(), label(), races()) ->
+-spec put_curr_fun(dialyzer_callgraph:mfa_or_funlbl(), label(), races()) ->
races().
put_curr_fun(CurrFun, CurrFunLabel, Races) ->
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index dc5a3fed37..84379642bf 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,15 +28,22 @@
-module(dialyzer_succ_typings).
-export([analyze_callgraph/3,
- analyze_callgraph/4,
- get_warnings/7]).
+ analyze_callgraph/6,
+ get_warnings/8
+ ]).
-%% These are only intended as debug functions.
--export([doit/1,
- get_top_level_signatures/3]).
+-export([
+ find_succ_types_for_scc/2,
+ refine_one_module/2,
+ find_required_by/2,
+ find_depends_on/2,
+ collect_warnings/2,
+ lookup_names/2
+ ]).
+
+-export_type([typesig_init_data/0, dataflow_init_data/0, warnings_init_data/0]).
%%-define(DEBUG, true).
-%%-define(DEBUG_PP, true).
-ifdef(DEBUG).
-define(debug(X__, Y__), io:format(X__, Y__)).
@@ -54,11 +61,21 @@
%% State record -- local to this module
-type parent() :: 'none' | pid().
+-type typesig_init_data() :: term().
+-type dataflow_init_data() :: term().
+-type warnings_init_data() :: term().
+
+-type fixpoint_init_data() :: typesig_init_data() | dataflow_init_data().
+
+-type scc() :: [mfa_or_funlbl()] | [module()].
+
-record(st, {callgraph :: dialyzer_callgraph:callgraph(),
codeserver :: dialyzer_codeserver:codeserver(),
no_warn_unused :: set(),
parent = none :: parent(),
+ timing_server :: dialyzer_timing:timing_server(),
+ solvers :: [solver()],
plt :: dialyzer_plt:plt()}).
%%--------------------------------------------------------------------
@@ -68,62 +85,90 @@
dialyzer_plt:plt().
analyze_callgraph(Callgraph, Plt, Codeserver) ->
- analyze_callgraph(Callgraph, Plt, Codeserver, none).
+ analyze_callgraph(Callgraph, Plt, Codeserver, none, [], none).
-spec analyze_callgraph(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
- dialyzer_codeserver:codeserver(), parent()) ->
+ dialyzer_codeserver:codeserver(),
+ dialyzer_timing:timing_server(),
+ [solver()], parent()) ->
dialyzer_plt:plt().
-analyze_callgraph(Callgraph, Plt, Codeserver, Parent) ->
- State = #st{callgraph = Callgraph, plt = Plt,
- codeserver = Codeserver, parent = Parent},
- NewState = get_refined_success_typings(State),
- NewState#st.plt.
+analyze_callgraph(Callgraph, Plt, Codeserver, TimingServer, Solvers, Parent) ->
+ NewState =
+ init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Solvers, Parent),
+ dialyzer_plt:restore_full_plt(NewState#st.plt, Plt).
%%--------------------------------------------------------------------
-get_refined_success_typings(State) ->
- case find_succ_typings(State) of
+init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Solvers, Parent) ->
+ {SCCs, Callgraph1} =
+ ?timing(TimingServer, "order", dialyzer_callgraph:finalize(Callgraph)),
+ State = #st{callgraph = Callgraph1, plt = dialyzer_plt:get_mini_plt(Plt),
+ codeserver = Codeserver, parent = Parent,
+ timing_server = TimingServer, solvers = Solvers},
+ get_refined_success_typings(SCCs, State).
+
+get_refined_success_typings(SCCs, #st{callgraph = Callgraph,
+ timing_server = TimingServer} = State) ->
+ case find_succ_typings(SCCs, State) of
{fixpoint, State1} -> State1;
{not_fixpoint, NotFixpoint1, State1} ->
- Callgraph = State1#st.callgraph,
- NotFixpoint2 = [lookup_name(F, Callgraph) || F <- NotFixpoint1],
- ModulePostorder =
- dialyzer_callgraph:module_postorder_from_funs(NotFixpoint2, Callgraph),
- case refine_succ_typings(ModulePostorder, State1) of
+ {ModulePostorder, ModCallgraph} =
+ ?timing(
+ TimingServer, "order", _C1,
+ dialyzer_callgraph:module_postorder_from_funs(NotFixpoint1,
+ Callgraph)),
+ ModState = State1#st{callgraph = ModCallgraph},
+ case refine_succ_typings(ModulePostorder, ModState) of
{fixpoint, State2} ->
State2;
- {not_fixpoint, NotFixpoint3, State2} ->
- Callgraph1 = State2#st.callgraph,
+ {not_fixpoint, NotFixpoint2, State2} ->
%% Need to reset the callgraph.
- NotFixpoint4 = [lookup_name(F, Callgraph1) || F <- NotFixpoint3],
- Callgraph2 = dialyzer_callgraph:reset_from_funs(NotFixpoint4,
- Callgraph1),
- get_refined_success_typings(State2#st{callgraph = Callgraph2})
+ {NewSCCs, Callgraph2} =
+ ?timing(TimingServer, "order", _C2,
+ dialyzer_callgraph:reset_from_funs(NotFixpoint2,
+ ModCallgraph)),
+ NewState = State2#st{callgraph = Callgraph2},
+ get_refined_success_typings(NewSCCs, NewState)
end
end.
-type doc_plt() :: 'undefined' | dialyzer_plt:plt().
-spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
doc_plt(), dialyzer_codeserver:codeserver(), set(),
- pid(), boolean()) ->
+ dialyzer_timing:timing_server(), [solver()], pid()) ->
{[dial_warning()], dialyzer_plt:plt(), doc_plt()}.
get_warnings(Callgraph, Plt, DocPlt, Codeserver,
- NoWarnUnused, Parent, BehavioursChk) ->
- InitState = #st{callgraph = Callgraph, codeserver = Codeserver,
- no_warn_unused = NoWarnUnused, parent = Parent, plt = Plt},
- NewState = get_refined_success_typings(InitState),
+ NoWarnUnused, TimingServer, Solvers, Parent) ->
+ InitState =
+ init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Solvers, Parent),
+ NewState = InitState#st{no_warn_unused = NoWarnUnused},
Mods = dialyzer_callgraph:modules(NewState#st.callgraph),
- CWarns = dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver,
- NewState#st.plt),
- get_warnings_from_modules(Mods, NewState, DocPlt, BehavioursChk, CWarns).
-
-get_warnings_from_modules([M|Ms], State, DocPlt,
- BehavioursChk, Acc) when is_atom(M) ->
- send_log(State#st.parent, io_lib:format("Getting warnings for ~w\n", [M])),
+ MiniPlt = NewState#st.plt,
+ CWarns =
+ dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver, MiniPlt),
+ MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt),
+ ModWarns =
+ ?timing(TimingServer, "warning",
+ get_warnings_from_modules(Mods, NewState, MiniDocPlt)),
+ {postprocess_warnings(CWarns ++ ModWarns, Codeserver),
+ dialyzer_plt:restore_full_plt(MiniPlt, Plt),
+ dialyzer_plt:restore_full_plt(MiniDocPlt, DocPlt)}.
+
+get_warnings_from_modules(Mods, State, DocPlt) ->
#st{callgraph = Callgraph, codeserver = Codeserver,
- no_warn_unused = NoWarnUnused, plt = Plt} = State,
+ no_warn_unused = NoWarnUnused, plt = Plt,
+ timing_server = TimingServer} = State,
+ Init = {Codeserver, Callgraph, NoWarnUnused, Plt, DocPlt},
+ dialyzer_coordinator:parallel_job(warnings, Mods, Init, TimingServer).
+
+-spec collect_warnings(module(), warnings_init_data()) -> [dial_warning()].
+
+collect_warnings(M, {Codeserver, Callgraph, NoWarnUnused, Plt, DocPlt}) ->
ModCode = dialyzer_codeserver:lookup_mod_code(M, Codeserver),
Records = dialyzer_codeserver:lookup_mod_records(M, Codeserver),
Contracts = dialyzer_codeserver:lookup_mod_contracts(M, Codeserver),
@@ -131,32 +176,27 @@ get_warnings_from_modules([M|Ms], State, DocPlt,
%% Check if there are contracts for functions that do not exist
Warnings1 =
dialyzer_contracts:contracts_without_fun(Contracts, AllFuns, Callgraph),
- {RawWarnings2, FunTypes, RaceCode, PublicTables, NamedTables} =
- dialyzer_dataflow:get_warnings(ModCode, Plt, Callgraph, Records, NoWarnUnused),
- {NewAcc, Warnings2} = postprocess_dataflow_warns(RawWarnings2, State, Acc),
+ {Warnings2, FunTypes} =
+ dialyzer_dataflow:get_warnings(ModCode, Plt, Callgraph,
+ Records, NoWarnUnused),
Attrs = cerl:module_attrs(ModCode),
- Warnings3 = if BehavioursChk ->
- dialyzer_behaviours:check_callbacks(M, Attrs,
- Plt, Codeserver);
- true -> []
- end,
- NewDocPlt = insert_into_doc_plt(FunTypes, Callgraph, DocPlt),
- NewCallgraph =
- dialyzer_callgraph:renew_race_info(Callgraph, RaceCode, PublicTables,
- NamedTables),
- State1 = st__renew_state_calls(NewCallgraph, State),
- get_warnings_from_modules(Ms, State1, NewDocPlt, BehavioursChk,
- [Warnings1, Warnings2, Warnings3|NewAcc]);
-get_warnings_from_modules([], #st{plt = Plt}, DocPlt, _, Acc) ->
- {lists:flatten(Acc), Plt, DocPlt}.
-
-postprocess_dataflow_warns(RawWarnings, State, WarnAcc) ->
- postprocess_dataflow_warns(RawWarnings, State, WarnAcc, []).
-
-postprocess_dataflow_warns([], _State, WAcc, Acc) ->
- {WAcc, lists:reverse(Acc)};
+ Warnings3 =
+ dialyzer_behaviours:check_callbacks(M, Attrs, Records, Plt, Codeserver),
+ DocPlt = insert_into_doc_plt(FunTypes, Callgraph, DocPlt),
+ lists:flatten([Warnings1, Warnings2, Warnings3]).
+
+postprocess_warnings(RawWarnings, Codeserver) ->
+ Pred =
+ fun({?WARN_CONTRACT_RANGE, _, _}) -> true;
+ (_) -> false
+ end,
+ {CRWarns, NonCRWarns} = lists:partition(Pred, RawWarnings),
+ postprocess_dataflow_warns(CRWarns, Codeserver, NonCRWarns, []).
+
+postprocess_dataflow_warns([], _Callgraph, WAcc, Acc) ->
+ lists:reverse(Acc, WAcc);
postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
- #st{codeserver = Codeserver} = State, WAcc, Acc) ->
+ Codeserver, WAcc, Acc) ->
{contract_range, [Contract, M, F, A, ArgStrings, CRet]} = Msg,
case dialyzer_codeserver:lookup_mfa_contract({M,F,A}, Codeserver) of
{ok, {{ContrF, _ContrL} = FileLine, _C}} ->
@@ -169,87 +209,66 @@ postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
(_) -> true
end,
FilterWAcc = lists:filter(Filter, WAcc),
- postprocess_dataflow_warns(Rest, State, FilterWAcc, [W|Acc]);
+ postprocess_dataflow_warns(Rest, Codeserver, FilterWAcc, [W|Acc]);
false ->
- postprocess_dataflow_warns(Rest, State, WAcc, Acc)
+ postprocess_dataflow_warns(Rest, Codeserver, 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]).
+ postprocess_dataflow_warns(Rest, Codeserver, WAcc, [W|Acc])
+ end.
-refine_succ_typings(ModulePostorder, State) ->
- ?debug("Module postorder: ~p\n", [ModulePostorder]),
- refine_succ_typings(ModulePostorder, State, []).
-
-refine_succ_typings([SCC|SCCs], State, Fixpoint) ->
- Msg = io_lib:format("Dataflow of one SCC: ~w\n", [SCC]),
- send_log(State#st.parent, Msg),
- ?debug("~s\n", [Msg]),
- {NewState, FixpointFromScc} =
- case SCC of
- [M] -> refine_one_module(M, State);
- [_|_] -> refine_one_scc(SCC, State)
- end,
- NewFixpoint = ordsets:union(Fixpoint, FixpointFromScc),
- refine_succ_typings(SCCs, NewState, NewFixpoint);
-refine_succ_typings([], State, Fixpoint) ->
- case Fixpoint =:= [] of
+refine_succ_typings(Modules, #st{codeserver = Codeserver,
+ callgraph = Callgraph,
+ plt = Plt,
+ timing_server = Timing,
+ solvers = Solvers} = State) ->
+ ?debug("Module postorder: ~p\n", [Modules]),
+ Init = {Codeserver, Callgraph, Plt, Solvers},
+ NotFixpoint =
+ ?timing(Timing, "refine",
+ dialyzer_coordinator:parallel_job(dataflow, Modules, Init, Timing)),
+ ?debug("==================== Dataflow done ====================\n\n", []),
+ case NotFixpoint =:= [] of
true -> {fixpoint, State};
- false -> {not_fixpoint, Fixpoint, State}
+ false -> {not_fixpoint, NotFixpoint, State}
end.
--spec refine_one_module(module(), #st{}) -> {#st{}, [label()]}. % ordset
+-spec find_depends_on(scc() | module(), fixpoint_init_data()) -> [scc()].
-refine_one_module(M, State) ->
- #st{callgraph = Callgraph, codeserver = CodeServer, plt = PLT} = State,
+find_depends_on(SCC, {_Codeserver, Callgraph, _Plt, _Solvers}) ->
+ dialyzer_callgraph:get_depends_on(SCC, Callgraph).
+
+-spec find_required_by(scc() | module(), fixpoint_init_data()) -> [scc()].
+
+find_required_by(SCC, {_Codeserver, Callgraph, _Plt, _Solvers}) ->
+ dialyzer_callgraph:get_required_by(SCC, Callgraph).
+
+-spec lookup_names([label()], fixpoint_init_data()) -> [mfa_or_funlbl()].
+
+lookup_names(Labels, {_Codeserver, Callgraph, _Plt, _Solvers}) ->
+ [lookup_name(F, Callgraph) || F <- Labels].
+
+-spec refine_one_module(module(), dataflow_init_data()) -> [label()]. % ordset
+
+refine_one_module(M, {CodeServer, Callgraph, Plt, _Solvers}) ->
ModCode = dialyzer_codeserver:lookup_mod_code(M, CodeServer),
AllFuns = collect_fun_info([ModCode]),
- FunTypes = get_fun_types_from_plt(AllFuns, State),
Records = dialyzer_codeserver:lookup_mod_records(M, CodeServer),
- {NewFunTypes, RaceCode, PublicTables, NamedTables} =
- dialyzer_dataflow:get_fun_types(ModCode, PLT, Callgraph, Records),
- NewCallgraph =
- dialyzer_callgraph:renew_race_info(Callgraph, RaceCode, PublicTables,
- NamedTables),
+ FunTypes = get_fun_types_from_plt(AllFuns, Callgraph, Plt),
+ NewFunTypes =
+ dialyzer_dataflow:get_fun_types(ModCode, Plt, Callgraph, Records),
case reached_fixpoint(FunTypes, NewFunTypes) of
- true ->
- State1 = st__renew_state_calls(NewCallgraph, State),
- {State1, ordsets:new()};
+ true -> [];
{false, NotFixpoint} ->
?debug("Not fixpoint\n", []),
- NewState = insert_into_plt(dict:from_list(NotFixpoint), State),
- NewState1 = st__renew_state_calls(NewCallgraph, NewState),
- {NewState1, ordsets:from_list([FunLbl || {FunLbl,_Type} <- NotFixpoint])}
+ Plt = insert_into_plt(dict:from_list(NotFixpoint), Callgraph, Plt),
+ [FunLbl || {FunLbl,_Type} <- NotFixpoint]
end.
-st__renew_state_calls(Callgraph, State) ->
- State#st{callgraph = Callgraph}.
-
-refine_one_scc(SCC, State) ->
- refine_one_scc(SCC, State, []).
-
-refine_one_scc(SCC, State, AccFixpoint) ->
- {NewState, FixpointFromScc} = refine_mods_in_scc(SCC, State, []),
- case FixpointFromScc =:= [] of
- true -> {NewState, AccFixpoint};
- false ->
- NewAccFixpoint = ordsets:union(AccFixpoint, FixpointFromScc),
- refine_one_scc(SCC, NewState, NewAccFixpoint)
- end.
-
-refine_mods_in_scc([Mod|Mods], State, Fixpoint) ->
- {NewState, FixpointFromModule} = refine_one_module(Mod, State),
- NewFixpoint = ordsets:union(FixpointFromModule, Fixpoint),
- refine_mods_in_scc(Mods, NewState, NewFixpoint);
-refine_mods_in_scc([], State, Fixpoint) ->
- {State, Fixpoint}.
-
reached_fixpoint(OldTypes, NewTypes) ->
reached_fixpoint(OldTypes, NewTypes, false).
@@ -305,29 +324,22 @@ compare_types_1([], [], _Strict, NotFixpoint) ->
false -> {false, NotFixpoint}
end.
-find_succ_typings(State) ->
- find_succ_typings(State, []).
-
-find_succ_typings(#st{callgraph = Callgraph, parent = Parent} = State,
- NotFixpoint) ->
- case dialyzer_callgraph:take_scc(Callgraph) of
- {ok, SCC, NewCallgraph} ->
- Msg = io_lib:format("Typesig analysis for SCC: ~w\n", [format_scc(SCC)]),
- ?debug("~s", [Msg]),
- send_log(Parent, Msg),
- {NewState, NewNotFixpoint1} =
- analyze_scc(SCC, State#st{callgraph = NewCallgraph}),
- NewNotFixpoint2 = ordsets:union(NewNotFixpoint1, NotFixpoint),
- find_succ_typings(NewState, NewNotFixpoint2);
- none ->
- ?debug("==================== Typesig done ====================\n\n", []),
- case NotFixpoint =:= [] of
- true -> {fixpoint, State};
- false -> {not_fixpoint, NotFixpoint, State}
- end
+find_succ_typings(SCCs, #st{codeserver = Codeserver, callgraph = Callgraph,
+ plt = Plt, timing_server = Timing,
+ solvers = Solvers} = State) ->
+ Init = {Codeserver, Callgraph, Plt, Solvers},
+ NotFixpoint =
+ ?timing(Timing, "typesig",
+ dialyzer_coordinator:parallel_job(typesig, SCCs, Init, Timing)),
+ ?debug("==================== Typesig done ====================\n\n", []),
+ case NotFixpoint =:= [] of
+ true -> {fixpoint, State};
+ false -> {not_fixpoint, NotFixpoint, State}
end.
-analyze_scc(SCC, #st{codeserver = Codeserver} = State) ->
+-spec find_succ_types_for_scc(scc(), typesig_init_data()) -> [mfa_or_funlbl()].
+
+find_succ_types_for_scc(SCC, {Codeserver, Callgraph, Plt, Solvers}) ->
SCC_Info = [{MFA,
dialyzer_codeserver:lookup_mfa_code(MFA, Codeserver),
dialyzer_codeserver:lookup_mod_records(M, Codeserver)}
@@ -336,30 +348,18 @@ analyze_scc(SCC, #st{codeserver = Codeserver} = State) ->
|| {_, _, _} = MFA <- SCC],
Contracts2 = [{MFA, Contract} || {MFA, {ok, Contract}} <- Contracts1],
Contracts3 = orddict:from_list(Contracts2),
- {SuccTypes, PltContracts, NotFixpoint} =
- find_succ_types_for_scc(SCC_Info, Contracts3, State),
- State1 = insert_into_plt(SuccTypes, State),
- ContrPlt = dialyzer_plt:insert_contract_list(State1#st.plt, PltContracts),
- {State1#st{plt = ContrPlt}, NotFixpoint}.
-
-find_succ_types_for_scc(SCC_Info, Contracts,
- #st{codeserver = Codeserver,
- callgraph = Callgraph, plt = Plt} = State) ->
- %% Assume that the PLT contains the current propagated types
+ Label = dialyzer_codeserver:get_next_core_label(Codeserver),
AllFuns = collect_fun_info([Fun || {_MFA, {_Var, Fun}, _Rec} <- SCC_Info]),
- PropTypes = get_fun_types_from_plt(AllFuns, State),
- MFAs = [MFA || {MFA, {_Var, _Fun}, _Rec} <- SCC_Info],
- NextLabel = dialyzer_codeserver:get_next_core_label(Codeserver),
- Plt1 = dialyzer_plt:delete_contract_list(Plt, MFAs),
- FunTypes = dialyzer_typesig:analyze_scc(SCC_Info, NextLabel,
- Callgraph, Plt1, PropTypes),
+ PropTypes = get_fun_types_from_plt(AllFuns, Callgraph, Plt),
+ %% Assume that the PLT contains the current propagated types
+ FunTypes = dialyzer_typesig:analyze_scc(SCC_Info, Label, Callgraph,
+ Plt, PropTypes, Solvers),
AllFunSet = sets:from_list([X || {X, _} <- AllFuns]),
- FilteredFunTypes = dict:filter(fun(X, _) ->
- sets:is_element(X, AllFunSet)
- end, FunTypes),
+ FilteredFunTypes =
+ dict:filter(fun(X, _) -> sets:is_element(X, AllFunSet) end, FunTypes),
%% Check contracts
- PltContracts = dialyzer_contracts:check_contracts(Contracts, Callgraph,
- FilteredFunTypes),
+ PltContracts =
+ dialyzer_contracts:check_contracts(Contracts3, Callgraph, FilteredFunTypes),
ContractFixpoint =
lists:all(fun({MFA, _C}) ->
%% Check the non-deleted PLT
@@ -368,23 +368,23 @@ find_succ_types_for_scc(SCC_Info, Contracts,
{value, _} -> true
end
end, PltContracts),
+ Plt = insert_into_plt(FilteredFunTypes, Callgraph, Plt),
+ Plt = dialyzer_plt:insert_contract_list(Plt, PltContracts),
case (ContractFixpoint andalso
reached_fixpoint_strict(PropTypes, FilteredFunTypes)) of
- true ->
- {FilteredFunTypes, PltContracts, []};
+ true -> [];
false ->
?debug("Not fixpoint for: ~w\n", [AllFuns]),
- {FilteredFunTypes, PltContracts,
- ordsets:from_list([Fun || {Fun, _Arity} <- AllFuns])}
+ [Fun || {Fun, _Arity} <- AllFuns]
end.
-get_fun_types_from_plt(FunList, State) ->
- get_fun_types_from_plt(FunList, State, dict:new()).
+get_fun_types_from_plt(FunList, Callgraph, Plt) ->
+ get_fun_types_from_plt(FunList, Callgraph, Plt, dict:new()).
-get_fun_types_from_plt([{FunLabel, Arity}|Left], State, Map) ->
- Type = lookup_fun_type(FunLabel, Arity, State),
- get_fun_types_from_plt(Left, State, dict:store(FunLabel, Type, Map));
-get_fun_types_from_plt([], _State, Map) ->
+get_fun_types_from_plt([{FunLabel, Arity}|Left], Callgraph, Plt, Map) ->
+ Type = lookup_fun_type(FunLabel, Arity, Callgraph, Plt),
+ get_fun_types_from_plt(Left, Callgraph, Plt, dict:store(FunLabel, Type, Map));
+get_fun_types_from_plt([], _Callgraph, _Plt, Map) ->
Map.
collect_fun_info(Trees) ->
@@ -402,7 +402,7 @@ collect_fun_info([Tree|Trees], List) ->
collect_fun_info([], List) ->
List.
-lookup_fun_type(Label, Arity, #st{callgraph = Callgraph, plt = Plt}) ->
+lookup_fun_type(Label, Arity, Callgraph, Plt) ->
ID = lookup_name(Label, Callgraph),
case dialyzer_plt:lookup(Plt, ID) of
none -> erl_types:t_fun(Arity, erl_types:t_any());
@@ -415,10 +415,10 @@ insert_into_doc_plt(FunTypes, Callgraph, DocPlt) ->
SuccTypes = format_succ_types(FunTypes, Callgraph),
dialyzer_plt:insert_list(DocPlt, SuccTypes).
-insert_into_plt(SuccTypes0, #st{callgraph = Callgraph, plt = Plt} = State) ->
+insert_into_plt(SuccTypes0, Callgraph, Plt) ->
SuccTypes = format_succ_types(SuccTypes0, Callgraph),
debug_pp_succ_typings(SuccTypes),
- State#st{plt = dialyzer_plt:insert_list(Plt, SuccTypes)}.
+ dialyzer_plt:insert_list(Plt, SuccTypes).
format_succ_types(SuccTypes, Callgraph) ->
format_succ_types(dict:to_list(SuccTypes), Callgraph, []).
@@ -453,131 +453,3 @@ lookup_name(F, CG) ->
error -> F;
{ok, Name} -> Name
end.
-
-send_log(none, _Msg) ->
- ok;
-send_log(Parent, Msg) ->
- Parent ! {self(), log, lists:flatten(Msg)},
- ok.
-
-format_scc(SCC) ->
- [MFA || {_M, _F, _A} = MFA <- SCC].
-
-%% ============================================================================
-%%
-%% Debug interface.
-%%
-%% ============================================================================
-
--spec doit(atom() | file:filename()) -> 'ok'.
-
-doit(Module) ->
- {ok, AbstrCode} = dialyzer_utils:get_abstract_code_from_src(Module),
- {ok, Code} = dialyzer_utils:get_core_from_abstract_code(AbstrCode),
- {ok, Records} = dialyzer_utils:get_record_and_type_info(AbstrCode),
- %% contract typing info in dictionary format
- {ok, Contracts} =
- dialyzer_utils:get_spec_info(cerl:concrete(cerl:module_name(Code)),
- AbstrCode, Records),
- Sigs0 = get_top_level_signatures(Code, Records, Contracts),
- M = if is_atom(Module) ->
- list_to_atom(filename:basename(atom_to_list(Module)));
- is_list(Module) ->
- list_to_atom(filename:basename(Module))
- end,
- Sigs1 = [{{M, F, A}, Type} || {{F, A}, Type} <- Sigs0],
- Sigs = ordsets:from_list(Sigs1),
- io:format("==================== Final result ====================\n\n", []),
- pp_signatures(Sigs, Records),
- ok.
-
--spec get_top_level_signatures(cerl:c_module(), dict(), dict()) ->
- [{{atom(), arity()}, erl_types:erl_type()}].
-
-get_top_level_signatures(Code, Records, Contracts) ->
- Tree = cerl:from_records(Code),
- {LabeledTree, NextLabel} = cerl_trees:label(Tree),
- Plt = get_def_plt(),
- ModuleName = cerl:atom_val(cerl:module_name(LabeledTree)),
- Plt1 = dialyzer_plt:delete_module(Plt, ModuleName),
- Plt2 = analyze_module(LabeledTree, NextLabel, Plt1, Records, Contracts),
- M = cerl:concrete(cerl:module_name(Tree)),
- Functions = [{M, cerl:fname_id(V), cerl:fname_arity(V)}
- || {V, _F} <- cerl:module_defs(LabeledTree)],
- %% First contracts check
- AllContracts = dict:fetch_keys(Contracts),
- ErrorContracts = AllContracts -- Functions,
- lists:foreach(fun(C) ->
- io:format("Contract for non-existing function: ~w\n",[C])
- end, ErrorContracts),
- Types = [{MFA, dialyzer_plt:lookup(Plt2, MFA)} || MFA <- Functions],
- Sigs = [{{F, A}, erl_types:t_fun(ArgT, RetT)}
- || {{_M, F, A}, {value, {RetT, ArgT}}} <- Types],
- ordsets:from_list(Sigs).
-
-get_def_plt() ->
- try
- dialyzer_plt:from_file(dialyzer_plt:get_default_plt())
- catch
- error:no_such_file -> dialyzer_plt:new();
- throw:{dialyzer_error, _} -> dialyzer_plt:new()
- end.
-
-pp_signatures([{{_, module_info, 0}, _}|Left], Records) ->
- pp_signatures(Left, Records);
-pp_signatures([{{_, module_info, 1}, _}|Left], Records) ->
- pp_signatures(Left, Records);
-pp_signatures([{{M, F, _A}, Type}|Left], Records) ->
- TypeString =
- case cerl:is_literal(Type) of
-%% Commented out so that dialyzer does not complain
-%% false ->
-%% "fun(" ++ String = erl_types:t_to_string(Type, Records),
-%% string:substr(String, 1, length(String)-1);
- true ->
- io_lib:format("~w", [cerl:concrete(Type)])
- end,
- io:format("~w:~w~s\n", [M, F, TypeString]),
- pp_signatures(Left, Records);
-pp_signatures([], _Records) ->
- ok.
-
--ifdef(DEBUG_PP).
-debug_pp(Tree, _Map) ->
- Tree1 = strip_annotations(Tree),
- io:put_chars(cerl_prettypr:format(Tree1)),
- io:nl().
-
-strip_annotations(Tree) ->
- cerl_trees:map(fun(T) ->
- case cerl:is_literal(T) orelse cerl:is_c_values(T) of
- true -> cerl:set_ann(T, []);
- false ->
- Label = cerl_trees:get_label(T),
- cerl:set_ann(T, [{'label', Label}])
- end
- end, Tree).
--else.
-debug_pp(_Tree, _Map) ->
- ok.
--endif. % DEBUG_PP
-
-%%
-%% Analysis of a single module
-%%
-analyze_module(LabeledTree, NextLbl, Plt, Records, Contracts) ->
- debug_pp(LabeledTree, dict:new()),
- CallGraph1 = dialyzer_callgraph:new(),
- CallGraph2 = dialyzer_callgraph:scan_core_tree(LabeledTree, CallGraph1),
- {CallGraph3, _Ext} = dialyzer_callgraph:remove_external(CallGraph2),
- CallGraph4 = dialyzer_callgraph:finalize(CallGraph3),
- CodeServer1 = dialyzer_codeserver:new(),
- Mod = cerl:concrete(cerl:module_name(LabeledTree)),
- CodeServer2 = dialyzer_codeserver:insert(Mod, LabeledTree, CodeServer1),
- CodeServer3 = dialyzer_codeserver:set_next_core_label(NextLbl, CodeServer2),
- CodeServer4 = dialyzer_codeserver:store_records(Mod, Records, CodeServer3),
- CodeServer5 = dialyzer_codeserver:store_contracts(Mod, Contracts, CodeServer4),
- Res = analyze_callgraph(CallGraph4, Plt, CodeServer5),
- dialyzer_callgraph:delete(CallGraph4),
- dialyzer_codeserver:delete(CodeServer5),
- Res.
diff --git a/lib/dialyzer/src/dialyzer_timing.erl b/lib/dialyzer/src/dialyzer_timing.erl
new file mode 100644
index 0000000000..b1a4bdc07c
--- /dev/null
+++ b/lib/dialyzer/src/dialyzer_timing.erl
@@ -0,0 +1,133 @@
+%% -*- erlang-indent-level: 2 -*-
+%%-------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 : dialyzer_timing.erl
+%%% Authors : Stavros Aronis <[email protected]>
+%%% Description : Timing reports for Dialyzer
+%%%-------------------------------------------------------------------
+
+-module(dialyzer_timing).
+
+-export([init/1, start_stamp/2, send_size_info/3, end_stamp/1, stop/1]).
+
+-export_type([timing_server/0]).
+
+-type timing_server() :: pid() | 'none'.
+
+-spec init(boolean() | 'debug') -> timing_server().
+
+init(Active) ->
+ case Active of
+ true ->
+ io:format("\n"),
+ spawn_link(fun() -> loop(now(), 0, "") end);
+ debug ->
+ io:format("\n"),
+ spawn_link(fun() -> debug_loop("") end);
+ false -> none
+ end.
+
+loop(LastNow, Size, Unit) ->
+ receive
+ {stamp, Msg, Now} ->
+ io:format(" ~-10s (+~4.2fs):", [Msg, diff(Now, LastNow)]),
+ loop(Now, 0, "");
+ {stamp, Now} ->
+ SizeStr =
+ case Size of
+ 0 -> "";
+ _ ->
+ Data = io_lib:format("~p ~s",[Size, Unit]),
+ io_lib:format(" (~12s)",[Data])
+ end,
+ io:format("~7.2fs~s\n", [diff(Now, LastNow), SizeStr]),
+ loop(Now, 0, "");
+ {size, NewSize, NewUnit} ->
+ loop(LastNow, NewSize, NewUnit);
+ {Pid, stop, Now} ->
+ io:format(" ~-9s (+~5.2fs)\n", ["",diff(Now, LastNow)]),
+ Pid ! ok;
+ {Pid, stop} ->
+ Pid ! ok
+ end.
+
+debug_loop(Phase) ->
+ receive
+ Message ->
+ {Runtime,_} = statistics(wall_clock),
+ Procs = erlang:system_info(process_count),
+ ProcMem = erlang:memory(total),
+ Status = io_lib:format("~12w ~6w ~20w", [Runtime, Procs, ProcMem]),
+ case Message of
+ {stamp, Msg, _Now} ->
+ io:format("~s ~s_start\n", [Status, Msg]),
+ debug_loop(Msg);
+ {stamp, _Now} ->
+ io:format("~s ~s_stop\n", [Status, Phase]),
+ debug_loop("");
+ {Pid, stop, _Now} ->
+ Pid ! ok;
+ {Pid, stop} ->
+ Pid ! ok;
+ _ ->
+ debug_loop(Phase)
+ end
+ after
+ 50 ->
+ {Runtime,_} = statistics(wall_clock),
+ Procs = erlang:system_info(process_count),
+ ProcMem = erlang:memory(total),
+ Status = io_lib:format("~12w ~6w ~20w", [Runtime, Procs, ProcMem]),
+ io:format("~s\n", [Status]),
+ debug_loop(Phase)
+ end.
+
+
+-spec start_stamp(timing_server(), string()) -> ok.
+
+start_stamp(none, _) -> ok;
+start_stamp(Pid, Msg) ->
+ Pid ! {stamp, Msg, now()},
+ ok.
+
+-spec end_stamp(timing_server()) -> ok.
+
+end_stamp(none) -> ok;
+end_stamp(Pid) ->
+ Pid ! {stamp, now()},
+ ok.
+
+-spec send_size_info(timing_server(), integer(), string()) -> ok.
+
+send_size_info(none, _, _) -> ok;
+send_size_info(Pid, Size, Unit) ->
+ Pid ! {size, Size, Unit},
+ ok.
+
+-spec stop(timing_server()) -> ok.
+
+stop(none) -> ok;
+stop(Pid) ->
+ Pid ! {self(), stop, now()},
+ receive ok -> ok end.
+
+diff(T2, T1) ->
+ timer:now_diff(T2,T1) / 1000000.
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 30aec59d22..0df003a035 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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(dialyzer_typesig).
--export([analyze_scc/5]).
+-export([analyze_scc/6]).
-export([get_safe_underapprox/2]).
-import(erl_types,
@@ -78,6 +78,8 @@
-record(constraint_list, {type :: 'conj' | 'disj',
list :: [constr()],
deps :: [dep()],
+ masks :: [{dep(),[non_neg_integer()]}] |
+ {'d',dict()},
id :: {'list', dep()}}).
-type constraint_list() :: #constraint_list{}.
@@ -91,22 +93,27 @@
-type typesig_scc() :: [{mfa(), {cerl:c_var(), cerl:c_fun()}, dict()}].
-type typesig_funmap() :: [{type_var(), type_var()}]. %% Orddict
--record(state, {callgraph :: dialyzer_callgraph:callgraph(),
- cs = [] :: [constr()],
- cmap = dict:new() :: dict(),
- fun_map = [] :: typesig_funmap(),
- fun_arities = dict:new() :: dict(),
- in_match = false :: boolean(),
- in_guard = false :: boolean(),
- module :: module(),
- name_map = dict:new() :: dict(),
- next_label :: label(),
- non_self_recs = [] :: [label()],
- plt :: dialyzer_plt:plt(),
- prop_types = dict:new() :: dict(),
- records = dict:new() :: dict(),
- opaques = [] :: [erl_types:erl_type()],
- scc = [] :: [type_var()]}).
+-type dict_or_ets() :: {'d', dict()} | {'e', ets:tid()}.
+
+-record(state, {callgraph :: dialyzer_callgraph:callgraph(),
+ cs = [] :: [constr()],
+ cmap = {'d', dict:new()} :: dict_or_ets(),
+ fun_map = [] :: typesig_funmap(),
+ fun_arities = dict:new() :: dict(),
+ in_match = false :: boolean(),
+ in_guard = false :: boolean(),
+ module :: module(),
+ name_map = dict:new() :: dict(),
+ next_label = 0 :: label(),
+ self_rec :: erl_types:erl_type(),
+ plt :: dialyzer_plt:plt(),
+ prop_types = {'d', dict:new()} :: dict_or_ets(),
+ records = dict:new() :: dict(),
+ opaques = [] :: [erl_types:erl_type()],
+ scc = [] :: [type_var()],
+ mfas :: [tuple()],
+ solvers = [] :: [solver()]
+ }).
%%-----------------------------------------------------------------------------
@@ -117,8 +124,10 @@
%%-define(DEBUG_CONSTRAINTS, true).
-ifdef(DEBUG).
-define(DEBUG_NAME_MAP, true).
+-define(DEBUG_LOOP_DETECTION, true).
-endif.
%%-define(DEBUG_NAME_MAP, true).
+%%-define(DEBUG_LOOP_DETECTION, true).
-ifdef(DEBUG).
-define(debug(__String, __Args), io:format(__String, __Args)).
@@ -137,7 +146,7 @@
%%-----------------------------------------------------------------------------
%% Analysis of strongly connected components.
%%
-%% analyze_scc(SCC, NextLabel, CallGraph, PLT, PropTypes) -> FunTypes
+%% analyze_scc(SCC, NextLabel, CallGraph, PLT, PropTypes, Solvers) -> FunTypes
%%
%% SCC - [{MFA, Def, Records}]
%% where Def = {Var, Fun} as in the Core Erlang module definitions.
@@ -150,15 +159,17 @@
%% about functions that can be called by this SCC.
%% PropTypes - A dictionary.
%% FunTypes - A dictionary.
+%% Solvers - User specified solvers.
%%-----------------------------------------------------------------------------
-spec analyze_scc(typesig_scc(), label(),
dialyzer_callgraph:callgraph(),
- dialyzer_plt:plt(), dict()) -> dict().
+ dialyzer_plt:plt(), dict(), [solver()]) -> dict().
-analyze_scc(SCC, NextLabel, CallGraph, Plt, PropTypes) ->
+analyze_scc(SCC, NextLabel, CallGraph, Plt, PropTypes, Solvers0) ->
+ Solvers = solvers(Solvers0),
assert_format_of_scc(SCC),
- State1 = new_state(SCC, NextLabel, CallGraph, Plt, PropTypes),
+ State1 = new_state(SCC, NextLabel, CallGraph, Plt, PropTypes, Solvers),
DefSet = add_def_list([Var || {_MFA, {Var, _Fun}, _Rec} <- SCC], sets:new()),
State2 = traverse_scc(SCC, DefSet, State1),
State3 = state__finalize(State2),
@@ -172,6 +183,9 @@ assert_format_of_scc([{_MFA, {_Var, _Fun}, _Records}|Left]) ->
assert_format_of_scc([]) ->
ok.
+solvers([]) -> [v2];
+solvers(Solvers) -> Solvers.
+
%% ============================================================================
%%
%% Gets the constraints by traversing the code.
@@ -448,7 +462,8 @@ traverse(Tree, DefinedVars, State) ->
%% Check if a record is constructed.
_ ->
Arity = length(Fields),
- case state__lookup_record(State2, cerl:atom_val(Tag), Arity) of
+ Records = State2#state.records,
+ case lookup_record(Records, cerl:atom_val(Tag), Arity) of
error -> {State2, TupleType};
{ok, RecType} ->
State3 = state__store_conj(TupleType, sub, RecType, State2),
@@ -646,8 +661,14 @@ get_plt_constr(MFA, Dst, ArgVars, State) ->
PltRes = dialyzer_plt:lookup(Plt, MFA),
Opaques = State#state.opaques,
Module = State#state.module,
+ SCCMFAs = State#state.mfas,
{FunModule, _, _} = MFA,
- case dialyzer_plt:lookup_contract(Plt, MFA) of
+ Contract =
+ case lists:member(MFA, SCCMFAs) of
+ true -> none;
+ false -> dialyzer_plt:lookup_contract(Plt, MFA)
+ end,
+ case Contract of
none ->
case PltRes of
none -> State;
@@ -1246,6 +1267,8 @@ get_bif_constr({erlang, is_record, 2}, Dst, [Var, Tag] = Args, _State) ->
mk_constraint(Var, sub, ArgV)]);
get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
%% TODO: Revise this to make it precise for Tag and Arity.
+ Records = State#state.records,
+ AllOpaques = State#state.opaques,
ArgFun =
fun(Map) ->
case t_is_atom(true, lookup_type(Dst, Map)) of
@@ -1262,10 +1285,8 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
GenRecord = t_tuple([TagType|AnyElems]),
case t_atom_vals(TagType) of
[TagVal] ->
- case state__lookup_record(State, TagVal,
- ArityVal - 1) of
+ case lookup_record(Records, TagVal, ArityVal - 1) of
{ok, Type} ->
- AllOpaques = State#state.opaques,
case t_opaque_match_record(Type, AllOpaques) of
[Opaque] -> Opaque;
_ -> Type
@@ -1287,7 +1308,7 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
DstFun = fun(Map) ->
[TmpVar, TmpTag, TmpArity] = TmpArgTypes = lookup_type_list(Args, Map),
TmpArgTypes2 =
- case lists:member(TmpVar, State#state.opaques) of
+ case lists:member(TmpVar, AllOpaques) of
true ->
case t_is_integer(TmpArity) of
true ->
@@ -1297,7 +1318,8 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
true ->
case t_atom_vals(TmpTag) of
[TmpTagVal] ->
- case state__lookup_record(State, TmpTagVal, TmpArityVal - 1) of
+ case lookup_record(Records, TmpTagVal,
+ TmpArityVal - 1) of
{ok, TmpType} ->
case t_is_none(t_inf(TmpType, TmpVar, opaque)) of
true -> TmpArgTypes;
@@ -1526,9 +1548,10 @@ get_bif_constr({erlang, element, 2} = _BIF, Dst, Args,
case t_is_none(GenType) of
true -> ?debug("Bif: ~w failed\n", [_BIF]), throw(error);
false ->
+ Opaques = State#state.opaques,
Fun = fun(Map) ->
[I, T] = ATs = lookup_type_list(Args, Map),
- ATs2 = case lists:member(T, State#state.opaques) of
+ ATs2 = case lists:member(T, Opaques) of
true -> [I, erl_types:t_opaque_structure(T)];
false -> ATs
end,
@@ -1546,7 +1569,7 @@ get_bif_constr({erlang, element, 2} = _BIF, Dst, Args,
end;
get_bif_constr({M, F, A} = _BIF, Dst, Args, State) ->
GenType = erl_bif_types:type(M, F, A),
- Opaques = State#state.opaques,
+ Opaques = State#state.opaques,
case t_is_none(GenType) of
true -> ?debug("Bif: ~w failed\n", [_BIF]), throw(error);
false ->
@@ -1612,11 +1635,12 @@ get_bif_test_constr(Dst, Arg, Type, State) ->
end
end,
ArgV = ?mk_fun_var(ArgFun, [Dst]),
+ Opaques = State#state.opaques,
DstFun = fun(Map) ->
ArgType = lookup_type(Arg, Map),
case t_is_none(t_inf(ArgType, Type)) of
true ->
- case lists:member(ArgType, State#state.opaques) of
+ case lists:member(ArgType, Opaques) of
true ->
OpaqueStruct = erl_types:t_opaque_structure(ArgType),
case t_is_none(t_inf(OpaqueStruct, Type)) of
@@ -1649,18 +1673,23 @@ get_bif_test_constr(Dst, Arg, Type, State) ->
solve([Fun], State) ->
?debug("============ Analyzing Fun: ~w ===========\n",
[debug_lookup_name(Fun)]),
- solve_fun(Fun, dict:new(), State);
+ solve_fun(Fun, map_new(), State);
solve([_|_] = SCC, State) ->
?debug("============ Analyzing SCC: ~w ===========\n",
[[debug_lookup_name(F) || F <- SCC]]),
- solve_scc(SCC, dict:new(), State, false).
+ {Parallel, NewState} =
+ case parallel_split(SCC) of
+ false -> {false, State};
+ SplitSCC -> {SplitSCC, minimize_state(State)}
+ end,
+ solve_scc(SCC, Parallel, map_new(), NewState, false).
solve_fun(Fun, FunMap, State) ->
Cs = state__get_cs(Fun, State),
Deps = get_deps(Cs),
Ref = mk_constraint_ref(Fun, Deps),
%% Note that functions are always considered to succeed.
- {ok, _MapDict, NewMap} = solve_ref_or_list(Ref, FunMap, dict:new(), State),
+ NewMap = solve(Fun, Ref, FunMap, State),
NewType = lookup_type(Fun, NewMap),
NewFunMap1 = case state__get_rec_var(Fun, State) of
error -> FunMap;
@@ -1668,21 +1697,23 @@ solve_fun(Fun, FunMap, State) ->
end,
enter_type(Fun, NewType, NewFunMap1).
-solve_scc(SCC, Map, State, TryingUnit) ->
- State1 = state__mark_as_non_self_rec(SCC, State),
+solve_scc(SCC, Parallel, Map, State, TryingUnit) ->
Vars0 = [{Fun, state__get_rec_var(Fun, State)} || Fun <- SCC],
Vars = [Var || {_, {ok, Var}} <- Vars0],
Funs = [Fun || {Fun, {ok, _}} <- Vars0],
Types = unsafe_lookup_type_list(Funs, Map),
RecTypes = [t_limit(Type, ?TYPE_LIMIT) || Type <- Types],
CleanMap = lists:foldl(fun(Fun, AccFunMap) ->
- dict:erase(t_var_name(Fun), AccFunMap)
+ erase_type(t_var_name(Fun), AccFunMap)
end, Map, SCC),
Map1 = enter_type_lists(Vars, RecTypes, CleanMap),
?debug("Checking SCC: ~w\n", [[debug_lookup_name(F) || F <- SCC]]),
- SolveFun = fun(X, Y) -> scc_fold_fun(X, Y, State1) end,
- Map2 = lists:foldl(SolveFun, Map1, SCC),
FunSet = ordsets:from_list([t_var_name(F) || F <- SCC]),
+ Map2 =
+ case Parallel of
+ false -> solve_whole_scc(SCC, Map1, State);
+ SplitSCC -> solve_whole_scc_parallel(SplitSCC, Map1, State)
+ end,
case maps_are_equal(Map2, Map, FunSet) of
true ->
?debug("SCC ~w reached fixpoint\n", [SCC]),
@@ -1696,20 +1727,134 @@ solve_scc(SCC, Map, State, TryingUnit) ->
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);
+ solve_scc(SCC, Parallel, Map3, State, true);
false ->
+ case Parallel of
+ false -> true;
+ _ -> dispose_state(State)
+ end,
Map2
end;
false ->
?debug("SCC ~w did not reach fixpoint\n", [SCC]),
- solve_scc(SCC, Map2, State, TryingUnit)
+ solve_scc(SCC, Parallel, Map2, State, TryingUnit)
+ end.
+
+solve_whole_scc(SCC, Map, State) ->
+ SolveFun = fun(X, Y) -> scc_fold_fun(X, Y, State) end,
+ lists:foldl(SolveFun, Map, SCC).
+
+%%------------------------------------------------------------------------------
+
+-define(worth_it, 42).
+
+parallel_split(SCC) ->
+ Length = length(SCC),
+ case Length > 2*?worth_it of
+ false -> false;
+ true ->
+ case min(dialyzer_utils:parallelism(), 8) of
+ 1 -> false;
+ CPUs ->
+ FullShare = Length div CPUs + 1,
+ Unit = max(FullShare, ?worth_it),
+ split(SCC, Unit, [])
+ end
+ end.
+
+minimize_state(#state{
+ cmap = {d, CMap},
+ fun_map = FunMap,
+ fun_arities = FunArities,
+ self_rec = SelfRec,
+ prop_types = {d, PropTypes},
+ opaques = Opaques,
+ solvers = Solvers
+ }) ->
+ ETSCMap = ets:new(cmap,[{read_concurrency, true}]),
+ ETSPropTypes = ets:new(prop_types,[{read_concurrency, true}]),
+ true = ets:insert(ETSCMap, dict:to_list(CMap)),
+ true = ets:insert(ETSPropTypes, dict:to_list(PropTypes)),
+ #state
+ {cmap = {e, ETSCMap},
+ fun_map = FunMap,
+ fun_arities = FunArities,
+ self_rec = SelfRec,
+ prop_types = {e, ETSPropTypes},
+ opaques = Opaques,
+ solvers = Solvers
+ }.
+
+dispose_state(#state{cmap = {e, ETSCMap},
+ prop_types = {e, ETSPropTypes}}) ->
+ true = ets:delete(ETSCMap),
+ true = ets:delete(ETSPropTypes).
+
+solve_whole_scc_parallel(SplitSCC, Map, State) ->
+ Workers = spawn_workers(SplitSCC, Map, State),
+ wait_results(Workers, Map, fold_res_fun(State)).
+
+spawn_workers(SplitSCC, Map, State) ->
+ Spawner = solve_scc_spawner(self(), Map, State),
+ lists:foreach(Spawner, SplitSCC),
+ length(SplitSCC).
+
+wait_results(0, Map, _FoldResFun) ->
+ Map;
+wait_results(Pending, Map, FoldResFun) ->
+ Res = receive_scc_result(),
+ NewMap = lists:foldl(FoldResFun, Map, Res),
+ wait_results(Pending-1, NewMap, FoldResFun).
+
+solve_scc_spawner(Parent, Map, State) ->
+ fun(SCCPart) ->
+ spawn_link(fun() -> solve_scc_worker(Parent, SCCPart, Map, State) end)
+ end.
+
+split([], _Unit, Acc) ->
+ Acc;
+split(List, Unit, Acc) ->
+ {Taken, Rest} =
+ try
+ lists:split(Unit, List)
+ catch
+ _:_ -> {List, []}
+ end,
+ split(Rest, Unit, [Taken|Acc]).
+
+solve_scc_worker(Parent, SCCPart, Map, State) ->
+ SolveFun = fun(X, Y) -> scc_fold_fun(X, Y, State) end,
+ FinalMap = lists:foldl(SolveFun, Map, SCCPart),
+ Res =
+ [{F, t_limit(unsafe_lookup_type(F, FinalMap), ?TYPE_LIMIT)} ||
+ F <- SCCPart],
+ send_scc_result(Parent, Res).
+
+fold_res_fun(State) ->
+ fun({F, Type}, Map) ->
+ case state__get_rec_var(F, State) of
+ {ok, R} ->
+ enter_type(R, Type, enter_type(F, Type, Map));
+ error ->
+ enter_type(F, Type, Map)
+ end
end.
+receive_scc_result() ->
+ receive
+ {scc_fun, Res} -> Res
+ end.
+
+send_scc_result(Parent, Res) ->
+ Parent ! {scc_fun, Res}.
+
+%%------------------------------------------------------------------------------
+
scc_fold_fun(F, FunMap, State) ->
Deps = get_deps(state__get_cs(F, State)),
Cs = mk_constraint_ref(F, Deps),
%% Note that functions are always considered to succeed.
- {ok, _NewMapDict, Map} = solve_ref_or_list(Cs, FunMap, dict:new(), State),
+ Map = solve(F, Cs, FunMap, State),
NewType0 = unsafe_lookup_type(F, Map),
NewType = t_limit(NewType0, ?TYPE_LIMIT),
NewFunMap = case state__get_rec_var(F, State) of
@@ -1722,15 +1867,440 @@ scc_fold_fun(F, FunMap, State) ->
format_type(NewType)]),
NewFunMap.
+solve(Fun, Cs, FunMap, State) ->
+ Solvers = State#state.solvers,
+ R = [solver(S, solve_fun(S, Fun, Cs, FunMap, State)) || S <- Solvers],
+ check_solutions(R, Fun, no_solver, no_map).
+
+solver(Solver, SolveFun) ->
+ ?debug("Start solver ~w\n", [Solver]),
+ try timer:tc(SolveFun) of
+ {Time, {ok, Map}} ->
+ ?debug("End solver ~w (~w microsecs)\n", [Solver, Time]),
+ {Solver, Map, Time};
+ {_, _R} ->
+ ?debug("Solver ~w returned unexpected result:\n ~P\n",
+ [Solver, _R, 60]),
+ throw(error)
+ catch E:R ->
+ io:format("Solver ~w failed: ~w:~p\n ~p\n",
+ [Solver, E, R, erlang:get_stacktrace()]),
+ throw(error)
+ end.
+
+solve_fun(v1, _Fun, Cs, FunMap, State) ->
+ fun() ->
+ {ok, _MapDict, NewMap} = solve_ref_or_list(Cs, FunMap, dict:new(), State),
+ {ok, NewMap}
+ end;
+solve_fun(v2, Fun, _Cs, FunMap, State) ->
+ fun() -> v2_solve_ref(Fun, FunMap, State) end.
+
+check_solutions([], _Fun, _S, Map) ->
+ Map;
+check_solutions([{S1,Map1,_Time1}|Maps], Fun, S, Map) ->
+ ?debug("Solver ~w needed ~w microsecs\n", [S1, _Time1]),
+ case Map =:= no_map orelse sane_maps(Map, Map1, [Fun], S, S1) of
+ true ->
+ check_solutions(Maps, Fun, S1, Map1);
+ false ->
+ ?debug("Constraint solvers do not agree on ~w\n", [Fun]),
+ pp_map(atom_to_list(S), Map),
+ pp_map(atom_to_list(S1), Map1),
+ io:format("A bug was found. Please report it, and use the option "
+ "`--solver v1' until the bug has been fixed.\n"),
+ throw(error)
+ end.
+
+sane_maps(Map1, Map2, Keys, _S1, _S2) ->
+ lists:all(fun(Key) ->
+ V1 = unsafe_lookup_type(Key, Map1),
+ V2 = unsafe_lookup_type(Key, Map2),
+ case t_is_equal(V1, V2) of
+ true -> true;
+ false ->
+ ?debug("Constraint solvers do not agree on ~w\n", [Key]),
+ ?debug("~w: ~s\n",
+ [_S1, format_type(unsafe_lookup_type(Key, Map1))]),
+ ?debug("~w: ~s\n",
+ [_S2, format_type(unsafe_lookup_type(Key, Map2))]),
+ false
+ end
+ end, Keys).
+
+%% Solver v2
+
+-record(v2_state, {constr_data = dict:new() :: dict(),
+ state :: #state{}}).
+
+v2_solve_ref(Fun, Map, State) ->
+ V2State = #v2_state{state = State},
+ {ok, NewMap, _, _} = v2_solve_reference(Fun, Map, V2State),
+ {ok, NewMap}.
+
+v2_solve(#constraint{}=C, Map, V2State) ->
+ State = V2State#v2_state.state,
+ case solve_one_c(C, Map, State#state.opaques) of
+ error ->
+ report_failed_constraint(C, Map),
+ {error, V2State};
+ {ok, {NewMap, U}} ->
+ {ok, NewMap, V2State, U}
+ end;
+v2_solve(#constraint_list{type = disj}=C, Map, V2State) ->
+ v2_solve_disjunct(C, Map, V2State);
+v2_solve(#constraint_list{type = conj}=C, Map, V2State) ->
+ v2_solve_conjunct(C, Map, V2State);
+v2_solve(#constraint_ref{id = Id}, Map, V2State) ->
+ v2_solve_reference(Id, Map, V2State).
+
+v2_solve_reference(Id, Map, V2State0) ->
+ ?debug("Checking ref to fun: ~w\n", [debug_lookup_name(Id)]),
+ pp_map("Map", Map),
+ pp_constr_data("solve_ref", V2State0),
+ Map1 = restore_local_map(V2State0, Id, Map),
+ State = V2State0#v2_state.state,
+ Cs = state__get_cs(Id, State),
+ Res =
+ case state__is_self_rec(Id, State) of
+ true -> v2_solve_self_recursive(Cs, Map1, Id, t_none(), V2State0);
+ false -> v2_solve(Cs, Map1, V2State0)
+ end,
+ {FunType, V2State} =
+ case Res of
+ {error, V2State1} ->
+ ?debug("Error solving for function ~p\n", [debug_lookup_name(Id)]),
+ Arity = state__fun_arity(Id, State),
+ FunType0 =
+ case state__prop_domain(t_var_name(Id), State) of
+ error -> t_fun(Arity, t_none());
+ {ok, Dom} -> t_fun(Dom, t_none())
+ end,
+ {FunType0, V2State1};
+ {ok, NewMap, V2State1, U} ->
+ ?debug("Done solving fun: ~p\n", [debug_lookup_name(Id)]),
+ FunType0 = lookup_type(Id, NewMap),
+ V2State2 = save_local_map(V2State1, Id, U, NewMap),
+ {FunType0, V2State2}
+ end,
+ ?debug("ref Id=~w Assigned ~s\n", [Id, format_type(FunType)]),
+ {NewMap1, U1} = enter_var_type(Id, FunType, Map),
+ {NewMap2, U2} =
+ case state__get_rec_var(Id, State) of
+ {ok, Var} -> enter_var_type(Var, FunType, NewMap1);
+ error -> {NewMap1, []}
+ end,
+ {ok, NewMap2, V2State, lists:umerge(U1, U2)}.
+
+v2_solve_self_recursive(Cs, Map, Id, RecType0, V2State0) ->
+ ?debug("Solving self recursive ~w\n", [debug_lookup_name(Id)]),
+ State = V2State0#v2_state.state,
+ {ok, RecVar} = state__get_rec_var(Id, State),
+ ?debug("OldRecType ~s\n", [format_type(RecType0)]),
+ RecType = t_limit(RecType0, ?TYPE_LIMIT),
+ {Map1, U0} = enter_var_type(RecVar, RecType, Map),
+ V2State1 = save_updated_vars1(V2State0, Cs, U0), % Probably not necessary
+ case v2_solve(Cs, Map1, V2State1) of
+ {error, _V2State}=Error ->
+ case t_is_none(RecType0) of
+ true ->
+ %% Try again and assume that this is a non-terminating function.
+ Arity = state__fun_arity(Id, State),
+ NewRecType = t_fun(lists:duplicate(Arity, t_any()), t_unit()),
+ v2_solve_self_recursive(Cs, Map, Id, NewRecType, V2State0);
+ false ->
+ Error
+ end;
+ {ok, NewMap, V2State, U} ->
+ pp_map("recursive finished", NewMap),
+ NewRecType = unsafe_lookup_type(Id, NewMap),
+ case t_is_equal(NewRecType, RecType0) of
+ true ->
+ {NewMap2, U1} = enter_var_type(RecVar, NewRecType, NewMap),
+ {ok, NewMap2, V2State, lists:umerge(U, U1)};
+ false ->
+ v2_solve_self_recursive(Cs, Map, Id, NewRecType, V2State0)
+ end
+ end.
+
+enter_var_type(Var, Type, Map0) ->
+ {Map, Vs} = enter_type2(Var, Type, Map0),
+ {Map, [t_var_name(V) || V <- Vs]}.
+
+v2_solve_disjunct(Disj, Map, V2State0) ->
+ #constraint_list{type = disj, id = _Id, list = Cs, masks = Masks} = Disj,
+ ?debug("disjunct Id=~w~n", [_Id]),
+ pp_map("Map", Map),
+ pp_constr_data("disjunct", V2State0),
+ case get_flags(V2State0, Disj) of
+ {V2State1, failed_list} -> {error, V2State1}; % cannot happen
+ {V2State1, Flags} when Flags =/= [] ->
+ {ok, V2State, Eval, UL, MapL0, Uneval, Failed} =
+ v2_solve_disj(Flags, Cs, 1, Map, V2State1, [], [], [], [], false),
+ ?debug("disj ending _Id=~w Eval=~w, |Uneval|=~w |UL|=~w~n",
+ [_Id, Eval, length(Uneval), length(UL)]),
+ if Eval =:= [], Uneval =:= [] ->
+ {error, failed_list(Disj, V2State0)};
+ true ->
+ {Is0, UnIds} = lists:unzip(Uneval),
+ MapL = [restore_local_map(V2State, Id, Map) ||
+ Id <- UnIds] ++ MapL0,
+ %% If some branch has just failed every variable of the
+ %% non-failed branches need to be checked, not just the
+ %% updated ones.
+ U0 = case Failed of
+ false -> lists:umerge(UL);
+ true -> constrained_keys(MapL)
+ end,
+ if U0 =:= [] -> {ok, Map, V2State, []};
+ true ->
+ NotFailed = lists:umerge(Is0, Eval),
+ U1 = [V || V <- U0,
+ var_occurs_everywhere(V, Masks, NotFailed)],
+ NewMap = join_maps(U1, MapL, Map),
+ pp_map("NewMap", NewMap),
+ U = updated_vars_only(U1, Map, NewMap),
+ ?debug("disjunct finished _Id=~w\n", [_Id]),
+ {ok, NewMap, V2State, U}
+ end
+ end
+ end.
+
+var_occurs_everywhere(V, Masks, NotFailed) ->
+ ordsets:is_subset(NotFailed, get_mask(V, Masks)).
+
+v2_solve_disj([I|Is], [C|Cs], I, Map0, V2State0, UL, MapL, Eval, Uneval,
+ Failed0) ->
+ Id = C#constraint_list.id,
+ Map1 = restore_local_map(V2State0, Id, Map0),
+ case v2_solve(C, Map1, V2State0) of
+ {error, V2State} ->
+ ?debug("disj error I=~w~n", [I]),
+ Failed = Failed0 orelse not is_failed_list(C, V2State0),
+ v2_solve_disj(Is, Cs, I+1, Map0, V2State, UL, MapL, Eval, Uneval, Failed);
+ {ok, Map, V2State1, U} ->
+ ?debug("disj I=~w U=~w~n", [I, U]),
+ V2State = save_local_map(V2State1, Id, U, Map),
+ pp_map("DMap", Map),
+ v2_solve_disj(Is, Cs, I+1, Map0, V2State, [U|UL], [Map|MapL],
+ [I|Eval], Uneval, Failed0)
+ end;
+v2_solve_disj([], [], _I, _Map, V2State, UL, MapL, Eval, Uneval, Failed) ->
+ {ok, V2State, lists:reverse(Eval), UL, MapL, lists:reverse(Uneval), Failed};
+v2_solve_disj(Is, [C|Cs], I, Map, V2State, UL, MapL, Eval, Uneval0, Failed) ->
+ Uneval = [{I,C#constraint_list.id} ||
+ not is_failed_list(C, V2State)] ++ Uneval0,
+ v2_solve_disj(Is, Cs, I+1, Map, V2State, UL, MapL, Eval, Uneval, Failed).
+
+save_local_map(#v2_state{constr_data = ConData}=V2State, Id, U, Map) ->
+ Part0 = [{V,dict:fetch(V, Map)} || V <- U],
+ Part1 =
+ case dict:find(Id, ConData) of
+ error -> []; % cannot happen
+ {ok, {Part2,[]}} -> Part2
+ end,
+ ?debug("save local map Id=~w:\n", [Id]),
+ Part = lists:ukeymerge(1, lists:keysort(1, Part0), Part1),
+ pp_map("New Part", dict:from_list(Part0)),
+ pp_map("Old Part", dict:from_list(Part1)),
+ pp_map(" => Part", dict:from_list(Part)),
+ V2State#v2_state{constr_data = dict:store(Id, {Part,[]}, ConData)}.
+
+restore_local_map(#v2_state{constr_data = ConData}, Id, Map0) ->
+ case dict:find(Id, ConData) of
+ error -> Map0;
+ {ok, failed} -> Map0;
+ {ok, {[],_}} -> Map0;
+ {ok, {Part0,U}} ->
+ Part = [{K,V} || {K,V} <- Part0, not lists:member(K, U)],
+ ?debug("restore local map Id=~w U=~w\n", [Id, U]),
+ pp_map("Part", dict:from_list(Part)),
+ pp_map("Map0", Map0),
+ Map = lists:foldl(fun({K,V}, D) -> dict:store(K, V, D)end, Map0, Part),
+ pp_map("Map", Map),
+ Map
+ end.
+
+v2_solve_conjunct(Conj, Map, V2State0) ->
+ #constraint_list{type = conj, list = Cs} = Conj,
+ ?debug("conjunct Id=~w~n", [Conj#constraint_list.id]),
+ IsFlat = case Cs of [#constraint{}|_] -> true; _ -> false end,
+ case get_flags(V2State0, Conj) of
+ {V2State, failed_list} -> {error, V2State};
+ {V2State, Flags} ->
+ v2_solve_conj(Flags, Cs, 1, Map, Conj, IsFlat, V2State, [], [], [],
+ Map, Flags)
+ end.
+
+%% LastMap and LastFlags are used for loop detection.
+v2_solve_conj([I|Is], [Cs|Tail], I, Map0, Conj, IsFlat, V2State0,
+ UL, NewFs0, VarsUp, LastMap, LastFlags) ->
+ ?debug("conj Id=~w I=~w~n", [Conj#constraint_list.id, I]),
+ true = IsFlat =:= is_record(Cs, constraint),
+ pp_constr_data("conj", V2State0),
+ case v2_solve(Cs, Map0, V2State0) of
+ {error, V2State1} -> {error, failed_list(Conj, V2State1)};
+ {ok, Map, V2State1, []} ->
+ v2_solve_conj(Is, Tail, I+1, Map, Conj, IsFlat, V2State1,
+ UL, NewFs0, VarsUp, LastMap, LastFlags);
+ {ok, Map, V2State1, U} when IsFlat -> % optimization
+ %% It is ensured by enumerate_constraints() that every
+ %% #constraint{} has a conjunct as parent, and that such a
+ %% parent has nothing but #constraint{}:s as children, a fact
+ %% which is used here to simplify the flag calculation.
+ Mask = lists:umerge([get_mask(V, Conj#constraint_list.masks) || V <- U]),
+ {Is1, NewF} = add_mask_to_flags(Is, Mask, I, []),
+ NewFs = [NewF|NewFs0],
+ v2_solve_conj(Is1, Tail, I+1, Map, Conj, IsFlat, V2State1,
+ [U|UL], NewFs, VarsUp, LastMap, LastFlags);
+ {ok, Map, V2State1, U} ->
+ #constraint_list{masks = Masks, list = AllCs} = Conj,
+ M = lists:keydelete(I, 1, vars_per_child(U, Masks)),
+ {V2State2, NewF0} = save_updated_vars_list(AllCs, M, V2State1),
+ {NewF, F} = lists:splitwith(fun(J) -> J < I end, NewF0),
+ Is1 = lists:umerge(Is, F),
+ NewFs = [NewF|NewFs0],
+ v2_solve_conj(Is1, Tail, I+1, Map, Conj, IsFlat, V2State2,
+ [U|UL], NewFs, VarsUp, LastMap, LastFlags)
+ end;
+v2_solve_conj([], _Cs, _I, Map, Conj, IsFlat, V2State, UL, NewFs, VarsUp,
+ LastMap, LastFlags) ->
+ U = lists:umerge(UL),
+ case lists:umerge(NewFs) of
+ [] ->
+ ?debug("conjunct finished Id=~w\n", [Conj#constraint_list.id]),
+ {ok, Map, V2State, lists:umerge([U|VarsUp])};
+ NewFlags when NewFlags =:= LastFlags, Map =:= LastMap ->
+ %% A loop was detected! The cause is some bug, possibly in erl_types.
+ %% The evaluation continues, but the results can be wrong.
+ report_detected_loop(Conj),
+ {ok, Map, V2State, lists:umerge([U|VarsUp])};
+ NewFlags ->
+ #constraint_list{type = conj, list = Cs} = Conj,
+ v2_solve_conj(NewFlags, Cs, 1, Map, Conj, IsFlat, V2State,
+ [], [], [U|VarsUp], Map, NewFlags)
+ end;
+v2_solve_conj(Is, [_|Tail], I, Map, Conj, IsFlat, V2State, UL, NewFs, VarsUp,
+ LastMap, LastFlags) ->
+ v2_solve_conj(Is, Tail, I+1, Map, Conj, IsFlat, V2State, UL, NewFs, VarsUp,
+ LastMap, LastFlags).
+
+-ifdef(DEBUG_LOOP_DETECTION).
+report_detected_loop(Conj) ->
+ io:format("A loop was detected in ~w\n", [Conj#constraint_list.id]).
+-else.
+report_detected_loop(_) ->
+ ok.
+-endif.
+
+add_mask_to_flags(Flags, [Im|M], I, L) when I > Im ->
+ add_mask_to_flags(Flags, M, I, [Im|L]);
+add_mask_to_flags(Flags, [_|M], _I, L) ->
+ {lists:umerge(Flags, M), lists:reverse(L)}.
+
+get_mask(V, {d, Masks}) ->
+ case dict:find(V, Masks) of
+ error -> [];
+ {ok, M} -> M
+ end;
+get_mask(V, Masks) ->
+ case lists:keyfind(V, 1, Masks) of
+ false -> [];
+ {V, M} -> M
+ end.
+
+get_flags(#v2_state{constr_data = ConData}=V2State0, C) ->
+ #constraint_list{id = Id, list = Cs, masks = Masks} = C,
+ case dict:find(Id, ConData) of
+ error ->
+ ?debug("get_flags Id=~w Flags=all ~w\n", [Id, length(Cs)]),
+ V2State = V2State0#v2_state{constr_data = dict:store(Id, {[],[]}, ConData)},
+ {V2State, lists:seq(1, length(Cs))};
+ {ok, failed} ->
+ {V2State0, failed_list};
+ {ok, {Part,U}} when U =/= [] ->
+ ?debug("get_flags Id=~w U=~w\n", [Id, U]),
+ V2State = V2State0#v2_state{constr_data = dict:store(Id, {Part,[]}, ConData)},
+ save_updated_vars_list(Cs, vars_per_child(U, Masks), V2State)
+ end.
+
+vars_per_child(U, Masks) ->
+ family([{I, V} || V <- lists:usort(U), I <- get_mask(V, Masks)]).
+
+save_updated_vars_list(Cs, IU, V2State) ->
+ save_updated_vars_list1(Cs, IU, V2State, 1, []).
+
+save_updated_vars_list1([C|Cs], [{I,U}|IU], V2State0, I, Is) ->
+ V2State = save_updated_vars(C, U, V2State0),
+ save_updated_vars_list1(Cs, IU, V2State, I+1, [I|Is]);
+save_updated_vars_list1([], [], V2State, _I, Is) ->
+ {V2State, lists:reverse(Is)};
+save_updated_vars_list1([_|Cs], IU, V2State, I, Is) ->
+ save_updated_vars_list1(Cs, IU, V2State, I+1, Is).
+
+save_updated_vars(#constraint{}, _, V2State) ->
+ V2State;
+save_updated_vars(#constraint_list{}=C, U, V2State0) ->
+ save_updated_vars1(V2State0, C, U);
+save_updated_vars(#constraint_ref{id = Id}, U, V2State) ->
+ Cs = state__get_cs(Id, V2State#v2_state.state),
+ save_updated_vars(Cs, U, V2State).
+
+save_updated_vars1(V2State, C, U) ->
+ #v2_state{constr_data = ConData} = V2State,
+ #constraint_list{id = Id} = C,
+ case dict:find(Id, ConData) of
+ error -> V2State; % error means everything is flagged
+ {ok, failed} -> V2State;
+ {ok, {Part,U0}} ->
+ %% Duplicates are not so common; let masks/2 remove them.
+ U1 = U ++ U0,
+ V2State#v2_state{constr_data = dict:store(Id, {Part,U1}, ConData)}
+ end.
+
+-ifdef(DEBUG).
+pp_constr_data(_Tag, #v2_state{constr_data = D}) ->
+ io:format("Constr data at ~p\n", [_Tag]),
+ _ = [begin
+ case _PartU of
+ {_Part, _U} ->
+ io:format("Id: ~w Vars: ~w\n", [_Id, _U]),
+ [pp_map("Part", dict:from_list(_Part)) || _Part =/= []];
+ failed ->
+ io:format("Id: ~w failed list\n", [_Id])
+ end
+ end ||
+ {_Id, _PartU} <- lists:keysort(1, dict:to_list(D))],
+ ok.
+
+-else.
+pp_constr_data(_Tag, _V2State) ->
+ ok.
+-endif.
+
+failed_list(#constraint_list{id = Id}, #v2_state{constr_data = D}=V2State) ->
+ ?debug("error list ~w~n", [Id]),
+ V2State#v2_state{constr_data = dict:store(Id, failed, D)}.
+
+is_failed_list(#constraint_list{id = Id}, #v2_state{constr_data = D}) ->
+ dict:find(Id, D) =:= {ok, failed}.
+
+%% Solver v1
+
solve_ref_or_list(#constraint_ref{id = Id, deps = Deps},
Map, MapDict, State) ->
{OldLocalMap, Check} =
case dict:find(Id, MapDict) of
- error -> {dict:new(), false};
+ error -> {map_new(), false};
{ok, M} -> {M, true}
end,
?debug("Checking ref to fun: ~w\n", [debug_lookup_name(Id)]),
+ %% Note: mk_constraint_ref() has already removed Id from Deps. The
+ %% reason for doing it there is that it makes it easy for
+ %% calculate_masks() to make the corresponding adjustment for
+ %% version v2.
CheckDeps = ordsets:del_element(t_var_name(Id), Deps),
+ true = CheckDeps =:= Deps,
case Check andalso maps_are_equal(OldLocalMap, Map, CheckDeps) of
true ->
?debug("Equal\n", []),
@@ -1743,49 +2313,50 @@ solve_ref_or_list(#constraint_ref{id = Id, deps = Deps},
true -> solve_self_recursive(Cs, Map, MapDict, Id, t_none(), State);
false -> solve_ref_or_list(Cs, Map, MapDict, State)
end,
- case Res of
- {error, NewMapDict} ->
- ?debug("Error solving for function ~p\n", [debug_lookup_name(Id)]),
- Arity = state__fun_arity(Id, State),
- FunType =
- case state__prop_domain(t_var_name(Id), State) of
- error -> t_fun(Arity, t_none());
- {ok, Dom} -> t_fun(Dom, t_none())
- end,
- NewMap1 = enter_type(Id, FunType, Map),
- NewMap2 =
- case state__get_rec_var(Id, State) of
- {ok, Var} -> enter_type(Var, FunType, NewMap1);
- error -> NewMap1
- end,
- {ok, dict:store(Id, NewMap2, NewMapDict), NewMap2};
- {ok, NewMapDict, NewMap} ->
- ?debug("Done solving fun: ~p\n", [debug_lookup_name(Id)]),
- FunType = lookup_type(Id, NewMap),
- NewMap1 = enter_type(Id, FunType, Map),
- NewMap2 =
- case state__get_rec_var(Id, State) of
- {ok, Var} -> enter_type(Var, FunType, NewMap1);
- error -> NewMap1
- end,
- {ok, dict:store(Id, NewMap2, NewMapDict), NewMap2}
- end
+ {NewMapDict, FunType} =
+ case Res of
+ {error, NewMapDict0} ->
+ ?debug("Error solving for function ~p\n", [debug_lookup_name(Id)]),
+ Arity = state__fun_arity(Id, State),
+ FunType0 =
+ case state__prop_domain(t_var_name(Id), State) of
+ error -> t_fun(Arity, t_none());
+ {ok, Dom} -> t_fun(Dom, t_none())
+ end,
+ {NewMapDict0, FunType0};
+ {ok, NewMapDict0, NewMap} ->
+ ?debug("Done solving fun: ~p\n", [debug_lookup_name(Id)]),
+ FunType0 = lookup_type(Id, NewMap),
+ {NewMapDict0, FunType0}
+ end,
+ ?debug(" Id=~w Assigned ~s\n", [Id, format_type(FunType)]),
+ NewMap1 = enter_type(Id, FunType, Map),
+ NewMap2 =
+ case state__get_rec_var(Id, State) of
+ {ok, Var} -> enter_type(Var, FunType, NewMap1);
+ error -> NewMap1
+ end,
+ {ok, dict:store(Id, NewMap2, NewMapDict), NewMap2}
end;
solve_ref_or_list(#constraint_list{type=Type, list = Cs, deps = Deps, id = Id},
Map, MapDict, State) ->
{OldLocalMap, Check} =
case dict:find(Id, MapDict) of
- error -> {dict:new(), false};
+ error -> {map_new(), false};
{ok, M} -> {M, true}
end,
?debug("Checking ref to list: ~w\n", [Id]),
- case Check andalso maps_are_equal(OldLocalMap, Map, Deps) of
+ if
+ OldLocalMap =:= error -> {error, MapDict};
true ->
- ?debug("~w equal ~w\n", [Type, Id]),
- {ok, MapDict, Map};
- false ->
- ?debug("~w not equal: ~w. Solving\n", [Type, Id]),
- solve_clist(Cs, Type, Id, Deps, MapDict, Map, State)
+ case Check andalso maps_are_equal(OldLocalMap, Map, Deps) of
+ true ->
+ ?debug("~w equal ~w\n", [Type, Id]),
+ {ok, MapDict, Map};
+ false ->
+ ?debug("~w not equal: ~w. Solving\n", [Type, Id]),
+ solve_clist(Cs, Type, Id, Deps, MapDict, Map, State)
+ end
end.
solve_self_recursive(Cs, Map, MapDict, Id, RecType0, State) ->
@@ -1793,8 +2364,8 @@ solve_self_recursive(Cs, Map, MapDict, Id, RecType0, State) ->
{ok, RecVar} = state__get_rec_var(Id, State),
?debug("OldRecType ~s\n", [format_type(RecType0)]),
RecType = t_limit(RecType0, ?TYPE_LIMIT),
- Map1 = enter_type(RecVar, RecType, dict:erase(t_var_name(Id), Map)),
- ?debug("\tMap in: ~p\n",[[{X, format_type(Y)}||{X, Y}<-dict:to_list(Map1)]]),
+ Map1 = enter_type(RecVar, RecType, erase_type(t_var_name(Id), Map)),
+ pp_map("Map1", Map1),
case solve_ref_or_list(Cs, Map1, MapDict, State) of
{error, _} = Error ->
case t_is_none(RecType0) of
@@ -1807,8 +2378,7 @@ solve_self_recursive(Cs, Map, MapDict, Id, RecType0, State) ->
Error
end;
{ok, NewMapDict, NewMap} ->
- ?debug("\tMap: ~p\n",
- [[{X, format_type(Y)} || {X, Y} <- dict:to_list(NewMap)]]),
+ pp_map("NewMap", NewMap),
NewRecType = unsafe_lookup_type(Id, NewMap),
case t_is_equal(NewRecType, RecType0) of
true ->
@@ -1820,7 +2390,8 @@ solve_self_recursive(Cs, Map, MapDict, Id, RecType0, State) ->
solve_clist(Cs, conj, Id, Deps, MapDict, Map, State) ->
case solve_cs(Cs, Map, MapDict, State) of
- {error, _} = Error -> Error;
+ {error, NewMapDict} ->
+ {error, dict:store(Id, error, NewMapDict)};
{ok, NewMapDict, NewMap} = Ret ->
case Cs of
[_] ->
@@ -1842,7 +2413,7 @@ solve_clist(Cs, disj, Id, _Deps, MapDict, Map, State) ->
end,
{Maps, NewMapDict} = lists:mapfoldl(Fun, MapDict, Cs),
case [X || {ok, X} <- Maps] of
- [] -> {error, NewMapDict};
+ [] -> {error, dict:store(Id, error, NewMapDict)};
MapList ->
NewMap = join_maps(MapList),
{ok, dict:store(Id, NewMap, NewMapDict), NewMap}
@@ -1861,14 +2432,9 @@ solve_cs([#constraint_list{} = C|Tail], Map, MapDict, State) ->
solve_cs([#constraint{} = C|Tail], Map, MapDict, State) ->
case solve_one_c(C, Map, State#state.opaques) of
error ->
- ?debug("+++++++++++\nFailed: ~s :: ~s ~w ~s :: ~s\n+++++++++++\n",
- [format_type(C#constraint.lhs),
- format_type(lookup_type(C#constraint.lhs, Map)),
- C#constraint.op,
- format_type(C#constraint.rhs),
- format_type(lookup_type(C#constraint.rhs, Map))]),
+ report_failed_constraint(C, Map),
{error, MapDict};
- {ok, NewMap} ->
+ {ok, {NewMap, _U}} ->
solve_cs(Tail, NewMap, MapDict, State)
end;
solve_cs([], Map, MapDict, _State) ->
@@ -1889,7 +2455,11 @@ solve_one_c(#constraint{lhs = Lhs, rhs = Rhs, op = Op}, Map, Opaques) ->
eq ->
case solve_subtype(Lhs, Inf, Map, Opaques) of
error -> error;
- {ok, Map1} -> solve_subtype(Rhs, Inf, Map1, Opaques)
+ {ok, {Map1, U1}} ->
+ case solve_subtype(Rhs, Inf, Map1, Opaques) of
+ error -> error;
+ {ok, {Map2, U2}} -> {ok, {Map2, lists:umerge(U1, U2)}}
+ end
end
end
end.
@@ -1912,18 +2482,34 @@ solve_subtype(Type, Inf, Map, Opaques) ->
end.
%% end.
+report_failed_constraint(_C, _Map) ->
+ ?debug("+++++++++++\nFailed: ~s :: ~s ~w ~s :: ~s\n+++++++++++\n",
+ [format_type(_C#constraint.lhs),
+ format_type(lookup_type(_C#constraint.lhs, _Map)),
+ _C#constraint.op,
+ format_type(_C#constraint.rhs),
+ format_type(lookup_type(_C#constraint.rhs, _Map))]).
+
%% ============================================================================
%%
%% Maps and types.
%%
%% ============================================================================
+map_new() ->
+ dict:new().
+
+join_maps([Map]) ->
+ Map;
join_maps(Maps) ->
- Keys = lists:foldl(fun(TmpMap, AccKeys) ->
- [Key || Key <- AccKeys, dict:is_key(Key, TmpMap)]
- end,
- dict:fetch_keys(hd(Maps)), tl(Maps)),
- join_maps(Keys, Maps, dict:new()).
+ Keys = constrained_keys(Maps),
+ join_maps(Keys, Maps, map_new()).
+
+constrained_keys(Maps) ->
+ lists:foldl(fun(TmpMap, AccKeys) ->
+ [Key || Key <- AccKeys, dict:is_key(Key, TmpMap)]
+ end,
+ dict:fetch_keys(hd(Maps)), tl(Maps)).
join_maps([Key|Left], Maps = [Map|MapsLeft], AccMap) ->
NewType = join_one_key(Key, MapsLeft, lookup_type(Key, Map)),
@@ -1986,13 +2572,13 @@ enter_type(Key, Val, Map) when is_integer(Key) ->
?debug("Entering ~s :: ~s\n", [format_type(t_var(Key)), format_type(Val)]),
case t_is_any(Val) of
true ->
- dict:erase(Key, Map);
+ erase_type(Key, Map);
false ->
LimitedVal = t_limit(Val, ?INTERNAL_TYPE_LIMIT),
case dict:find(Key, Map) of
{ok, LimitedVal} -> Map;
- {ok, _} -> dict:store(Key, LimitedVal, Map);
- error -> dict:store(Key, LimitedVal, Map)
+ {ok, _} -> map_store(Key, LimitedVal, Map);
+ error -> map_store(Key, LimitedVal, Map)
end
end;
enter_type(Key, Val, Map) ->
@@ -2000,13 +2586,13 @@ enter_type(Key, Val, Map) ->
KeyName = t_var_name(Key),
case t_is_any(Val) of
true ->
- dict:erase(KeyName, Map);
+ erase_type(KeyName, Map);
false ->
LimitedVal = t_limit(Val, ?INTERNAL_TYPE_LIMIT),
case dict:find(KeyName, Map) of
{ok, LimitedVal} -> Map;
- {ok, _} -> dict:store(KeyName, LimitedVal, Map);
- error -> dict:store(KeyName, LimitedVal, Map)
+ {ok, _} -> map_store(KeyName, LimitedVal, Map);
+ error -> map_store(KeyName, LimitedVal, Map)
end
end.
@@ -2016,11 +2602,25 @@ enter_type_lists([Key|KeyTail], [Val|ValTail], Map) ->
enter_type_lists([], [], Map) ->
Map.
-enter_type_list([{Key, Val}|Tail], Map) ->
+enter_type_list(KeyVals, Map) ->
+ enter_type_list(KeyVals, Map, []).
+
+enter_type_list([{Key, Val}|Tail], Map, U0) ->
+ {Map1,U1} = enter_type2(Key, Val, Map),
+ enter_type_list(Tail, Map1, U1++U0);
+enter_type_list([], Map, U) ->
+ {Map, ordsets:from_list(U)}.
+
+enter_type2(Key, Val, Map) ->
Map1 = enter_type(Key, Val, Map),
- enter_type_list(Tail, Map1);
-enter_type_list([], Map) ->
- Map.
+ {Map1, [Key || not is_same(Key, Map, Map1)]}.
+
+map_store(Key, Val, Map) ->
+ ?debug("Storing ~w :: ~s\n", [Key, format_type(Val)]),
+ dict:store(Key, Val, Map).
+
+erase_type(Key, Map) ->
+ dict:erase(Key, Map).
lookup_type_list(List, Map) ->
[lookup_type(X, Map) || X <- List].
@@ -2046,8 +2646,7 @@ lookup_type(Key, Map) ->
%% case cerl:is_literal(Key) of
%% true -> t_from_term(cerl:concrete(Key));
%% false ->
- Subst = t_subst(Key, Map),
- t_sup(Subst, Subst).
+ t_subst(Key, Map).
%% end.
mk_var(Var) ->
@@ -2072,17 +2671,41 @@ mk_var_no_lit(Var) ->
mk_var_no_lit_list(List) ->
[mk_var_no_lit(X) || X <- List].
+updated_vars_only(U, OldMap, NewMap) ->
+ [V || V <- U, not is_same(V, OldMap, NewMap)].
+
+is_same(Key, Map1, Map2) ->
+ t_is_equal(lookup_type(Key, Map1), lookup_type(Key, Map2)).
+
+pp_map(_S, _Map) ->
+ ?debug("\t~s: ~p\n",
+ [_S, [{X, lists:flatten(format_type(Y))} ||
+ {X, Y} <- lists:keysort(1, dict:to_list(_Map))]]).
+
%% ============================================================================
%%
%% The State.
%%
%% ============================================================================
-new_state(SCC0, NextLabel, CallGraph, Plt, PropTypes) ->
- NameMap = dict:from_list([{MFA, Var} || {MFA, {Var, _Fun}, _Rec} <- SCC0]),
+new_state(SCC0, NextLabel, CallGraph, Plt, PropTypes, Solvers) ->
+ List = [{MFA, Var} || {MFA, {Var, _Fun}, _Rec} <- SCC0],
+ NameMap = dict:from_list(List),
+ MFAs = [MFA || {MFA, _Var} <- List],
SCC = [mk_var(Fun) || {_MFA, {_Var, Fun}, _Rec} <- SCC0],
+ SelfRec =
+ case SCC of
+ [OneF] ->
+ Label = t_var_name(OneF),
+ case dialyzer_callgraph:is_self_rec(Label, CallGraph) of
+ true -> OneF;
+ false -> false
+ end;
+ _Many -> false
+ end,
#state{callgraph = CallGraph, name_map = NameMap, next_label = NextLabel,
- prop_types = PropTypes, plt = Plt, scc = ordsets:from_list(SCC)}.
+ prop_types = {d, PropTypes}, plt = Plt, scc = ordsets:from_list(SCC),
+ mfas = MFAs, self_rec = SelfRec, solvers = Solvers}.
state__set_rec_dict(State, RecDict) ->
State#state{records = RecDict}.
@@ -2092,15 +2715,6 @@ state__set_opaques(#state{records = RecDict} = State, {M, _F, _A}) ->
erl_types:module_builtin_opaques(M) ++ t_opaque_from_records(RecDict),
State#state{opaques = Opaques, module = M}.
-state__lookup_record(#state{records = Records}, Tag, Arity) ->
- case erl_types:lookup_record(Tag, Arity, Records) of
- {ok, Fields} ->
- {ok, t_tuple([t_from_term(Tag)|
- [FieldType || {_FieldName, FieldType} <- Fields]])};
- error ->
- error
- end.
-
state__set_in_match(State, Bool) ->
State#state{in_match = Bool}.
@@ -2161,13 +2775,21 @@ get_apply_constr(FunLabels, Dst, ArgTypes, #state{callgraph = CG} = State) ->
case lists:member(error, MFAs) of
true -> error;
false ->
- Constrs = [begin
- State1 = state__new_constraint_context(State),
- State2 = get_plt_constr(MFA, Dst, ArgTypes, State1),
- state__cs(State2)
- end || {ok, MFA} <- MFAs],
- ApplyConstr = mk_disj_constraint_list(Constrs),
- {ok, state__store_conj(ApplyConstr, State)}
+ Constrs0 =
+ [begin
+ State1 = state__new_constraint_context(State),
+ try get_plt_constr(MFA, Dst, ArgTypes, State1) of
+ State2 -> state__cs(State2)
+ catch
+ throw:error -> error
+ end
+ end || {ok, MFA} <- MFAs],
+ case [C || C <- Constrs0, C =/= error] of
+ [] -> throw(error);
+ Constrs ->
+ ApplyConstr = mk_disj_constraint_list(Constrs),
+ {ok, state__store_conj(ApplyConstr, State)}
+ end
end.
state__scc(#state{scc = SCC}) ->
@@ -2182,14 +2804,21 @@ state__plt(#state{plt = PLT}) ->
state__new_constraint_context(State) ->
State#state{cs = []}.
-state__prop_domain(FunLabel, #state{prop_types = PropTypes}) ->
+state__prop_domain(FunLabel, #state{prop_types = {e, ETSPropTypes}}) ->
+ try ets:lookup_element(ETSPropTypes, FunLabel, 2) of
+ {_Range_Fun, Dom} -> {ok, Dom};
+ FunType -> {ok, t_fun_args(FunType)}
+ catch
+ _:_ -> error
+ end;
+state__prop_domain(FunLabel, #state{prop_types = {d, PropTypes}}) ->
case dict:find(FunLabel, PropTypes) of
error -> error;
{ok, {_Range_Fun, Dom}} -> {ok, Dom};
{ok, FunType} -> {ok, t_fun_args(FunType)}
end.
-state__add_prop_constrs(Tree, #state{prop_types = PropTypes} = State) ->
+state__add_prop_constrs(Tree, #state{prop_types = {d, PropTypes}} = State) ->
Label = cerl_trees:get_label(Tree),
case dict:find(Label, PropTypes) of
error -> State;
@@ -2252,23 +2881,17 @@ state__mk_vars(N, #state{next_label = NL} = State) ->
Vars = [t_var(X) || X <- lists:seq(NL, NewLabel-1)],
{State#state{next_label = NewLabel}, Vars}.
-state__store_constrs(Id, Cs, #state{cmap = Dict} = State) ->
+state__store_constrs(Id, Cs, #state{cmap = {d, Dict}} = State) ->
NewDict = dict:store(Id, Cs, Dict),
- State#state{cmap = NewDict}.
+ State#state{cmap = {d, NewDict}}.
-state__get_cs(Var, #state{cmap = Dict}) ->
+state__get_cs(Var, #state{cmap = {e, ETSDict}}) ->
+ ets:lookup_element(ETSDict, Var, 2);
+state__get_cs(Var, #state{cmap = {d, Dict}}) ->
dict:fetch(Var, Dict).
-%% The functions here will not be treated as self recursive.
-%% These functions will need to be handled as such manually.
-state__mark_as_non_self_rec(SCC, #state{non_self_recs = NS} = State) ->
- State#state{non_self_recs = ordsets:union(NS, ordsets:from_list(SCC))}.
-
-state__is_self_rec(Fun, #state{callgraph = CallGraph, non_self_recs = NS}) ->
- case ordsets:is_element(Fun, NS) of
- true -> false;
- false -> dialyzer_callgraph:is_self_rec(t_var_name(Fun), CallGraph)
- end.
+state__is_self_rec(Fun, #state{self_rec = SelfRec}) ->
+ Fun =:= SelfRec.
state__store_funs(Vars0, Funs0, #state{fun_map = Map} = State) ->
debug_make_name_map(Vars0, Funs0),
@@ -2305,7 +2928,7 @@ mk_constraint(Lhs, Op, Rhs) ->
case Deps =:= [] of
true ->
%% This constraint is constant. Solve it immediately.
- case solve_one_c(C, dict:new(), []) of
+ case solve_one_c(C, map_new(), []) of
error -> throw(error);
_ ->
%% This is always true, keep it anyway for logistic reasons
@@ -2328,8 +2951,9 @@ 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{}.
+-spec mk_fun_var(integer(),
+ fun((_) -> erl_types:erl_type()),
+ [erl_types:erl_type()]) -> #fun_var{}.
mk_fun_var(Line, Fun, Types) ->
Deps = [t_var_name(Var) || Var <- t_collect_vars(t_product(Types))],
@@ -2377,7 +3001,9 @@ mk_constraints([], _Op, []) ->
[].
mk_constraint_ref(Id, Deps) ->
- #constraint_ref{id = Id, deps = Deps}.
+ %% See also solve_ref_or_list(), #constraint_ref{}.
+ Ds = ordsets:del_element(t_var_name(Id), Deps),
+ #constraint_ref{id = Id, deps = Ds}.
mk_constraint_list(Type, List) ->
List1 = ordsets:from_list(lift_lists(Type, List)),
@@ -2514,19 +3140,21 @@ enumerate_constraints([#constraint_ref{id = Id} = C|Tail], N, Acc, State) ->
enumerate_constraints([#constraint_list{type = conj, list = List} = C|Tail],
N, Acc, State) ->
%% Separate the flat constraints from the deep ones to make a
- %% separate fixpoint interation over the flat ones for speed.
- {Flat, Deep} = lists:splitwith(fun(#constraint{}) -> true;
+ %% separate fixpoint iteration over the flat ones for speed.
+ {Flat, Deep} = lists:partition(fun(#constraint{}) -> true;
(#constraint_list{}) -> false;
(#constraint_ref{}) -> false
end, List),
{NewFlat, N1, State1} = enumerate_constraints(Flat, N, [], State),
{NewDeep, N2, State2} = enumerate_constraints(Deep, N1, [], State1),
{NewList, N3} =
- case shorter_than_two(NewFlat) orelse (NewDeep =:= []) of
- true -> {NewFlat ++ NewDeep, N2};
- false ->
- {NewCLists, TmpN} = group_constraints_in_components(NewFlat, N2),
- {NewCLists ++ NewDeep, TmpN}
+ if
+ NewFlat =:= [] -> {NewDeep, N2};
+ NewDeep =:= [] -> {NewFlat, N2};
+ true ->
+ TmpCList = mk_conj_constraint_list(NewFlat),
+ {[TmpCList#constraint_list{id = {list, N2}}| NewDeep],
+ N2 + 1}
end,
NewAcc = [C#constraint_list{list = NewList, id = {list, N3}}|Acc],
enumerate_constraints(Tail, N3+1, NewAcc, State2);
@@ -2540,42 +3168,6 @@ enumerate_constraints([#constraint{} = C|Tail], N, Acc, State) ->
enumerate_constraints([], N, Acc, State) ->
{lists:reverse(Acc), N, State}.
-shorter_than_two([]) -> true;
-shorter_than_two([_]) -> true;
-shorter_than_two([_|_]) -> false.
-
-group_constraints_in_components(Cs, N) ->
- DepList = [Deps || #constraint{deps = Deps} <- Cs],
- case find_dep_components(DepList, []) of
- [_] -> {Cs, N};
- [_|_] = Components ->
- ConstrComp = [[C || #constraint{deps = D} = C <- Cs,
- ordsets:is_subset(D, Comp)]
- || Comp <- Components],
- lists:mapfoldl(fun(CComp, TmpN) ->
- TmpCList = mk_conj_constraint_list(CComp),
- {TmpCList#constraint_list{id = {list, TmpN}},
- TmpN + 1}
- end, N, ConstrComp)
- end.
-
-find_dep_components([Set|Left], AccComponents) ->
- {Component, Ungrouped} = find_dep_components(Left, Set, []),
- case Component =:= Set of
- true -> find_dep_components(Ungrouped, [Component|AccComponents]);
- false -> find_dep_components([Component|Ungrouped], AccComponents)
- end;
-find_dep_components([], AccComponents) ->
- AccComponents.
-
-find_dep_components([Set|Left], AccSet, Ungrouped) ->
- case ordsets:intersection(Set, AccSet) of
- [] -> find_dep_components(Left, AccSet, [Set|Ungrouped]);
- [_|_] -> find_dep_components(Left, ordsets:union(Set, AccSet), Ungrouped)
- end;
-find_dep_components([], AccSet, Ungrouped) ->
- {AccSet, Ungrouped}.
-
%% Put the fun ref constraints last in any conjunction since we need
%% to separate the environment from the interior of the function.
order_fun_constraints(State) ->
@@ -2606,7 +3198,9 @@ order_fun_constraints([#constraint_list{list = List, type = Type} = C|Tail],
end,
lists:mapfoldl(FoldFun, State, List)
end,
- NewAcc = [update_constraint_list(C, NewList)|Acc],
+ C1 = update_constraint_list(C, NewList),
+ Masks = calculate_masks(NewList, 1, []),
+ NewAcc = [update_masks(C1, Masks)|Acc],
order_fun_constraints(Tail, Funs, NewAcc, NewState);
order_fun_constraints([#constraint{} = C|Tail], Funs, Acc, State) ->
order_fun_constraints(Tail, Funs, [C|Acc], State);
@@ -2614,6 +3208,22 @@ order_fun_constraints([], Funs, Acc, State) ->
NewState = order_fun_constraints(Funs, State),
{lists:reverse(Acc)++Funs, NewState}.
+update_masks(C, Masks) ->
+ C#constraint_list{masks = Masks}.
+
+-define(VARS_LIMIT, 50).
+
+calculate_masks([C|Cs], I, L0) ->
+ calculate_masks(Cs, I+1, [{V, I} || V <- get_deps(C)] ++ L0);
+calculate_masks([], _I, L) ->
+ M = family(L),
+ case length(M) > ?VARS_LIMIT of
+ true ->
+ {d, dict:from_list(M)};
+ false ->
+ M
+ end.
+
%% ============================================================================
%%
%% Utilities.
@@ -2682,6 +3292,18 @@ find_constraint(Tuple, [#constraint_list{list = List}|Cs]) ->
find_constraint(Tuple, [_|Cs]) ->
find_constraint(Tuple, Cs).
+lookup_record(Records, Tag, Arity) ->
+ case erl_types:lookup_record(Tag, Arity, Records) of
+ {ok, Fields} ->
+ {ok, t_tuple([t_from_term(Tag)|
+ [FieldType || {_FieldName, FieldType} <- Fields]])};
+ error ->
+ error
+ end.
+
+family(L) ->
+ sofs:to_external(sofs:rel2fam(sofs:relation(L))).
+
%% ============================================================================
%%
%% Pretty printer and debug facilities.
@@ -2696,13 +3318,24 @@ find_constraint(Tuple, [_|Cs]) ->
-ifdef(DEBUG).
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])]);
+ L = [format_type(t_var(X)) || X <- Deps],
+ io_lib:format("Fun@L~p(~s)", [Origin, join_chars(L, ",")]);
format_type(Type) ->
case cerl:is_literal(Type) of
true -> io_lib:format("~w", [cerl:concrete(Type)]);
false -> erl_types:t_to_string(Type)
end.
+
+join_chars([], _Sep) ->
+ [];
+join_chars([H|T], Sep) ->
+ [H|[[Sep,X] || X <- T]].
+
+debug_lookup_name(Var) ->
+ case dict:find(t_var_name(Var), get(dialyzer_typesig_map)) of
+ error -> Var;
+ {ok, Name} -> Name
+ end.
-endif.
-ifdef(DEBUG_NAME_MAP).
@@ -2721,12 +3354,6 @@ debug_make_name_map([Var|VarLeft], [Fun|FunLeft], Map) ->
debug_make_name_map([], [], Map) ->
Map.
-debug_lookup_name(Var) ->
- case dict:find(t_var_name(Var), get(dialyzer_typesig_map)) of
- error -> Var;
- {ok, Name} -> Name
- end.
-
-else.
debug_make_name_map(_Vars, _Funs) ->
ok.
@@ -2737,51 +3364,55 @@ pp_constrs_scc(SCC, State) ->
[pp_constrs(Fun, state__get_cs(Fun, State), State) || Fun <- SCC].
pp_constrs(Fun, Cs, State) ->
- io:format("Constraints for fun: ~w\n", [debug_lookup_name(Fun)]),
+ io:format("Constraints for fun: ~w", [debug_lookup_name(Fun)]),
MaxDepth = pp_constraints(Cs, State),
io:format("Depth: ~w\n", [MaxDepth]).
pp_constraints(Cs, State) ->
- Res = pp_constraints([Cs], none, 0, 0, State),
+ Res = pp_constraints([Cs], 0, 0, State),
io:nl(),
Res.
-pp_constraints([List|Tail], Separator, Level, MaxDepth,
- State) when is_list(List) ->
- pp_constraints(List++Tail, Separator, Level, MaxDepth, State);
-pp_constraints([#constraint_ref{id = Id}|Left], Separator,
- Level, MaxDepth, State) ->
+pp_constraints([List|Tail], Level, MaxDepth, State) when is_list(List) ->
+ pp_constraints(List++Tail, Level, MaxDepth, State);
+pp_constraints([#constraint_ref{id = Id}|Left], Level, MaxDepth, State) ->
Cs = state__get_cs(Id, State),
+ pp_indent(Level),
io:format("%Ref ~w%", [t_var_name(Id)]),
- pp_constraints([Cs|Left], Separator, Level, MaxDepth, State);
-pp_constraints([#constraint{lhs = Lhs, op = Op, rhs = Rhs}], _Separator,
- Level, MaxDepth, _State) ->
- io:format("~s ~w ~s", [format_type(Lhs), Op, format_type(Rhs)]),
+ pp_constraints([Cs|Left], Level, MaxDepth, State);
+pp_constraints([#constraint{}=C], Level, MaxDepth, _State) ->
+ pp_op(C, Level),
erlang:max(Level, MaxDepth);
-pp_constraints([#constraint{lhs = Lhs, op = Op, rhs = Rhs}|Tail], Separator,
- Level, MaxDepth, State) ->
- io:format("~s ~w ~s ~s ", [format_type(Lhs), Op, format_type(Rhs),Separator]),
- pp_constraints(Tail, Separator, Level, MaxDepth, State);
+pp_constraints([#constraint{}=C|Tail], Level, MaxDepth, State) ->
+ pp_op(C, Level),
+ pp_constraints(Tail, Level, MaxDepth, State);
pp_constraints([#constraint_list{type = Type, list = List, id = Id}],
- _Separator, Level, MaxDepth, State) ->
- io:format("%List ~w(", [Id]),
- NewSeparator = case Type of
- conj -> "*";
- disj -> "+"
- end,
- NewMaxDepth = pp_constraints(List, NewSeparator, Level + 1, MaxDepth, State),
+ Level, MaxDepth, State) ->
+ pp_indent(Level),
+ case Type of
+ conj -> io:format("Conj ~w (", [Id]);
+ disj -> io:format("Disj ~w (", [Id])
+ end,
+ NewMaxDepth = pp_constraints(List, Level + 1, MaxDepth, State),
io:format(")", []),
NewMaxDepth;
pp_constraints([#constraint_list{type = Type, list = List, id = Id}|Tail],
- Separator, Level, MaxDepth, State) ->
- io:format("List ~w(", [Id]),
- NewSeparator = case Type of
- conj -> "*";
- disj -> "+"
- end,
- NewMaxDepth = pp_constraints(List, NewSeparator, Level+1, MaxDepth, State),
- io:format(") ~s\n~s ", [Separator, Separator]),
- pp_constraints(Tail, Separator, Level, NewMaxDepth, State).
+ Level, MaxDepth, State) ->
+ pp_indent(Level),
+ case Type of
+ conj -> io:format("Conj ~w (", [Id]);
+ disj -> io:format("Disj ~w (", [Id])
+ end,
+ NewMaxDepth = pp_constraints(List, Level+1, MaxDepth, State),
+ io:format(")", []),
+ pp_constraints(Tail, Level, NewMaxDepth, State).
+
+pp_op(#constraint{lhs = Lhs, op = Op, rhs = Rhs}, Level) ->
+ pp_indent(Level),
+ io:format("~s ~w ~s", [format_type(Lhs), Op, format_type(Rhs)]).
+
+pp_indent(Level) ->
+ io:format("\n~*s", [Level*2, ""]).
-else.
pp_constrs_scc(_SCC, _State) ->
ok.
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index 12f8dec67e..149e777e1f 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -43,7 +43,8 @@
pp_hook/0,
process_record_remote_types/1,
sets_filter/2,
- src_compiler_opts/0
+ src_compiler_opts/0,
+ parallelism/0
]).
-include("dialyzer.hrl").
@@ -311,11 +312,15 @@ merge_records(NewRecords, OldRecords) ->
%%
%% ============================================================================
+-type spec_dict() :: dict().
+-type callback_dict() :: dict().
+
-spec get_spec_info(atom(), abstract_code(), dict()) ->
- {'ok', dict()} | {'error', string()}.
+ {'ok', spec_dict(), callback_dict()} | {'error', string()}.
get_spec_info(ModName, AbstractCode, RecordsDict) ->
- get_spec_info(AbstractCode, dict:new(), RecordsDict, ModName, "nofile").
+ get_spec_info(AbstractCode, dict:new(), dict:new(),
+ RecordsDict, ModName, "nofile").
%% TypeSpec is a list of conditional contracts for a function.
%% Each contract is of the form {[Argument], Range, [Constraint]} where
@@ -323,21 +328,34 @@ get_spec_info(ModName, AbstractCode, RecordsDict) ->
%% - Constraint is of the form {subtype, T1, T2} where T1 and T2
%% are erl_types:erl_type()
-get_spec_info([{attribute, Ln, spec, {Id, TypeSpec}}|Left],
- SpecDict, RecordsDict, ModName, File) when is_list(TypeSpec) ->
+get_spec_info([{attribute, Ln, Contract, {Id, TypeSpec}}|Left],
+ SpecDict, CallbackDict, RecordsDict, ModName, File)
+ when ((Contract =:= 'spec') or (Contract =:= 'callback')),
+ is_list(TypeSpec) ->
MFA = case Id of
{_, _, _} = T -> T;
{F, A} -> {ModName, F, A}
end,
- try dict:find(MFA, SpecDict) of
+ ActiveDict =
+ case Contract of
+ spec -> SpecDict;
+ callback -> CallbackDict
+ end,
+ try dict:find(MFA, ActiveDict) of
error ->
- NewSpecDict =
+ NewActiveDict =
dialyzer_contracts:store_tmp_contract(MFA, {File, Ln}, TypeSpec,
- SpecDict, RecordsDict),
- get_spec_info(Left, NewSpecDict, RecordsDict, ModName, File);
+ ActiveDict, RecordsDict),
+ {NewSpecDict, NewCallbackDict} =
+ case Contract of
+ spec -> {NewActiveDict, CallbackDict};
+ callback -> {SpecDict, NewActiveDict}
+ end,
+ get_spec_info(Left, NewSpecDict, NewCallbackDict,
+ RecordsDict, ModName,File);
{ok, {{OtherFile, L},_C}} ->
{Mod, Fun, Arity} = MFA,
- Msg = flat_format(" Contract for function ~w:~w/~w "
+ Msg = flat_format(" Contract/callback for function ~w:~w/~w "
"already defined in ~s:~w\n",
[Mod, Fun, Arity, OtherFile, L]),
throw({error, Msg})
@@ -347,12 +365,14 @@ get_spec_info([{attribute, Ln, spec, {Id, TypeSpec}}|Left],
[Ln, Error])}
end;
get_spec_info([{attribute, _, file, {IncludeFile, _}}|Left],
- SpecDict, RecordsDict, ModName, _File) ->
- get_spec_info(Left, SpecDict, RecordsDict, ModName, IncludeFile);
-get_spec_info([_Other|Left], SpecDict, RecordsDict, ModName, File) ->
- get_spec_info(Left, SpecDict, RecordsDict, ModName, File);
-get_spec_info([], SpecDict, _RecordsDict, _ModName, _File) ->
- {ok, SpecDict}.
+ SpecDict, CallbackDict, RecordsDict, ModName, _File) ->
+ get_spec_info(Left, SpecDict, CallbackDict,
+ RecordsDict, ModName, IncludeFile);
+get_spec_info([_Other|Left], SpecDict, CallbackDict,
+ RecordsDict, ModName, File) ->
+ get_spec_info(Left, SpecDict, CallbackDict, RecordsDict, ModName, File);
+get_spec_info([], SpecDict, CallbackDict, _RecordsDict, _ModName, _File) ->
+ {ok, SpecDict, CallbackDict}.
%% ============================================================================
%%
@@ -517,3 +537,12 @@ pp_unit(Unit, Ctxt, Cont) ->
pp_atom(Atom) ->
String = atom_to_list(cerl:atom_val(Atom)),
prettypr:text(String).
+
+%%------------------------------------------------------------------------------
+
+-spec parallelism() -> integer().
+
+parallelism() ->
+ CPUs = erlang:system_info(logical_processors_available),
+ Schedulers = erlang:system_info(schedulers),
+ min(CPUs, Schedulers).
diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl
new file mode 100644
index 0000000000..50b2e31ed8
--- /dev/null
+++ b/lib/dialyzer/src/dialyzer_worker.erl
@@ -0,0 +1,189 @@
+%% -*- erlang-indent-level: 2 -*-
+%%-----------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(dialyzer_worker).
+
+-export([launch/4, sequential/4]).
+
+-export_type([worker/0]).
+
+-type worker() :: pid(). %%opaque
+
+-type mode() :: dialyzer_coordinator:mode().
+-type coordinator() :: dialyzer_coordinator:coordinator().
+-type init_data() :: dialyzer_coordinator:init_data().
+-type result() :: dialyzer_coordinator:result().
+
+-record(state, {
+ mode :: mode(),
+ job :: mfa_or_funlbl() | file:filename(),
+ coordinator :: coordinator(),
+ init_data :: init_data(),
+ depends_on = [] :: list()
+ }).
+
+-include("dialyzer.hrl").
+
+%% -define(DEBUG, true).
+
+-ifdef(DEBUG).
+-define(debug(X__, Y__), io:format(X__, Y__)).
+-else.
+-define(debug(X__, Y__), ok).
+-endif.
+
+%%--------------------------------------------------------------------
+
+-spec launch(mode(), [mfa_or_funlbl()], init_data(), coordinator()) -> worker().
+
+launch(Mode, Job, InitData, Coordinator) ->
+ State = #state{mode = Mode,
+ job = Job,
+ init_data = InitData,
+ coordinator = Coordinator},
+ InitState =
+ case Mode of
+ X when X =:= 'typesig'; X =:= 'dataflow' -> initializing;
+ X when X =:= 'compile'; X =:= 'warnings' -> running
+ end,
+ spawn_link(fun() -> loop(InitState, State) end).
+
+%%--------------------------------------------------------------------
+
+loop(updating, State) ->
+ ?debug("Update: ~p\n",[State#state.job]),
+ NextStatus =
+ case waits_more_success_typings(State) of
+ true -> waiting;
+ false -> running
+ end,
+ loop(NextStatus, State);
+loop(initializing, #state{job = SCC, init_data = InitData} = State) ->
+ DependsOn = dialyzer_succ_typings:find_depends_on(SCC, InitData),
+ ?debug("Deps ~p: ~p\n",[State#state.job, DependsOn]),
+ loop(updating, State#state{depends_on = DependsOn});
+loop(waiting, State) ->
+ ?debug("Wait: ~p\n",[State#state.job]),
+ NewState = wait_for_success_typings(State),
+ loop(updating, NewState);
+loop(running, #state{mode = 'compile'} = State) ->
+ dialyzer_coordinator:wait_activation(),
+ ?debug("Compile: ~s\n",[State#state.job]),
+ Result =
+ case start_compilation(State) of
+ {ok, EstimatedSize, Data} ->
+ Label = ask_coordinator_for_label(EstimatedSize, State),
+ continue_compilation(Label, Data);
+ {error, _Reason} = Error ->
+ Error
+ end,
+ report_to_coordinator(Result, State);
+loop(running, #state{mode = 'warnings'} = State) ->
+ dialyzer_coordinator:wait_activation(),
+ ?debug("Warning: ~s\n",[State#state.job]),
+ Result = collect_warnings(State),
+ report_to_coordinator(Result, State);
+loop(running, #state{mode = Mode} = State) when
+ Mode =:= 'typesig'; Mode =:= 'dataflow' ->
+ request_activation(State),
+ ?debug("Run: ~p\n",[State#state.job]),
+ NotFixpoint = do_work(State),
+ ok = broadcast_done(State),
+ report_to_coordinator(NotFixpoint, State).
+
+waits_more_success_typings(#state{depends_on = Depends}) ->
+ Depends =/= [].
+
+broadcast_done(#state{job = SCC, init_data = InitData,
+ coordinator = Coordinator}) ->
+ RequiredBy = dialyzer_succ_typings:find_required_by(SCC, InitData),
+ {Callers, Unknown} =
+ dialyzer_coordinator:sccs_to_pids(RequiredBy, Coordinator),
+ send_done(Callers, SCC),
+ continue_broadcast_done(Unknown, SCC, Coordinator).
+
+send_done(Callers, SCC) ->
+ ?debug("Sending ~p: ~p\n",[SCC, Callers]),
+ SendSTFun = fun(PID) -> PID ! {done, SCC} end,
+ lists:foreach(SendSTFun, Callers).
+
+continue_broadcast_done([], _SCC, _Coordinator) -> ok;
+continue_broadcast_done(Rest, SCC, Coordinator) ->
+ %% This time limit should be greater than the time required
+ %% by the coordinator to spawn all processes.
+ timer:sleep(500),
+ {Callers, Unknown} = dialyzer_coordinator:sccs_to_pids(Rest, Coordinator),
+ send_done(Callers, SCC),
+ continue_broadcast_done(Unknown, SCC, Coordinator).
+
+wait_for_success_typings(#state{depends_on = DependsOn} = State) ->
+ receive
+ {done, SCC} ->
+ ?debug("GOT ~p: ~p\n",[State#state.job, SCC]),
+ State#state{depends_on = DependsOn -- [SCC]}
+ after
+ 5000 ->
+ ?debug("Still Waiting ~p: ~p\n",[State#state.job, DependsOn]),
+ State
+ end.
+
+request_activation(#state{coordinator = Coordinator}) ->
+ dialyzer_coordinator:request_activation(Coordinator).
+
+do_work(#state{mode = Mode, job = Job, init_data = InitData}) ->
+ case Mode of
+ typesig -> dialyzer_succ_typings:find_succ_types_for_scc(Job, InitData);
+ dataflow -> dialyzer_succ_typings:refine_one_module(Job, InitData)
+ end.
+
+report_to_coordinator(Result, #state{job = Job, coordinator = Coordinator}) ->
+ ?debug("Done: ~p\n",[Job]),
+ dialyzer_coordinator:job_done(Job, Result, Coordinator).
+
+start_compilation(#state{job = Job, init_data = InitData}) ->
+ dialyzer_analysis_callgraph:start_compilation(Job, InitData).
+
+ask_coordinator_for_label(EstimatedSize, #state{coordinator = Coordinator}) ->
+ dialyzer_coordinator:get_next_label(EstimatedSize, Coordinator).
+
+continue_compilation(Label, Data) ->
+ dialyzer_analysis_callgraph:continue_compilation(Label, Data).
+
+collect_warnings(#state{job = Job, init_data = InitData}) ->
+ dialyzer_succ_typings:collect_warnings(Job, InitData).
+
+%%------------------------------------------------------------------------------
+
+-type extra() :: label() | 'unused'.
+
+-spec sequential(mode(), [mfa_or_funlbl()], init_data(), extra()) -> result().
+
+sequential('compile', Job, InitData, Extra) ->
+ case dialyzer_analysis_callgraph:start_compilation(Job, InitData) of
+ {ok, EstimatedSize, Data} ->
+ {EstimatedSize, continue_compilation(Extra, Data)};
+ {error, _Reason} = Error -> {0, Error}
+ end;
+sequential('typesig', Job, InitData, _Extra) ->
+ dialyzer_succ_typings:find_succ_types_for_scc(Job, InitData);
+sequential('dataflow', Job, InitData, _Extra) ->
+ dialyzer_succ_typings:refine_one_module(Job, InitData);
+sequential('warnings', Job, InitData, _Extra) ->
+ dialyzer_succ_typings:collect_warnings(Job, InitData).
diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile
index 47deb17f1d..9f8a3f1194 100644
--- a/lib/dialyzer/test/Makefile
+++ b/lib/dialyzer/test/Makefile
@@ -25,10 +25,10 @@ RELSYSDIR = $(RELEASE_PATH)/dialyzer_test
include $(ERL_TOP)/make/otp_release_targets.mk
release_tests_spec:
- $(INSTALL_DIR) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- $(INSTALL_DATA) $(AUXILIARY_FILES) $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
- cd $(RELSYSDIR);\
- erl -make;\
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(AUXILIARY_FILES) "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ cd "$(RELSYSDIR)";\
+ erlc dialyzer_common.erl file_utils.erl;\
erl -noshell -run dialyzer_common create_all_suites -s erlang halt
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options b/lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..50991c9bc5
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/dialyzer_options
@@ -0,0 +1 @@
+{dialyzer_options, []}.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs
new file mode 100644
index 0000000000..33d135048e
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs
@@ -0,0 +1,5 @@
+
+my_callbacks_wrong.erl:26: The return type #state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour
+my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::'undefined' | pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour
+my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour
+my_callbacks_wrong.erl:39: The specified type for the 2nd argument of callback_call/3 (atom()) is not a supertype of pid(), which is expected type for this argument in the callback of the my_behaviour behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return
new file mode 100644
index 0000000000..e646eea383
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_event_incorrect_return
@@ -0,0 +1,2 @@
+
+gen_event_incorrect_return.erl:16: The inferred return type of init/1 ('error') has nothing in common with {'error',_} | {'ok',_} | {'ok',_,'hibernate'}, which is the expected return type for the callback of gen_event behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
new file mode 100644
index 0000000000..3e98da785f
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
@@ -0,0 +1,8 @@
+
+gen_server_incorrect_args.erl:3: Undefined callback function code_change/3 (behaviour 'gen_server')
+gen_server_incorrect_args.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server')
+gen_server_incorrect_args.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server')
+gen_server_incorrect_args.erl:3: Undefined callback function init/1 (behaviour 'gen_server')
+gen_server_incorrect_args.erl:3: Undefined callback function terminate/2 (behaviour 'gen_server')
+gen_server_incorrect_args.erl:7: The inferred return type of handle_call/3 ({'no'} | {'ok'}) has nothing in common with {'noreply',_} | {'noreply',_,'hibernate' | 'infinity' | non_neg_integer()} | {'reply',_,_} | {'stop',_,_} | {'reply',_,_,'hibernate' | 'infinity' | non_neg_integer()} | {'stop',_,_,_}, which is the expected return type for the callback of gen_server behaviour
+gen_server_incorrect_args.erl:7: The inferred type for the 2nd argument of handle_call/3 ('boo' | 'foo') is not a supertype of {pid(),_}, which is expected type for this argument in the callback of the gen_server behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks
new file mode 100644
index 0000000000..5e0ed5fd27
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks
@@ -0,0 +1,3 @@
+
+gen_server_missing_callbacks.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server')
+gen_server_missing_callbacks.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server')
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour
new file mode 100644
index 0000000000..8cecabccaa
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour
@@ -0,0 +1,9 @@
+
+sample_callback_wrong.erl:16: The inferred return type of sample_callback_2/0 (42) has nothing in common with atom(), which is the expected return type for the callback of sample_behaviour behaviour
+sample_callback_wrong.erl:17: The inferred return type of sample_callback_3/0 ('fair') has nothing in common with 'fail' | {'ok',1..255}, which is the expected return type for the callback of sample_behaviour behaviour
+sample_callback_wrong.erl:18: The inferred return type of sample_callback_4/1 ('fail') has nothing in common with 'ok', which is the expected return type for the callback of sample_behaviour behaviour
+sample_callback_wrong.erl:20: The inferred return type of sample_callback_5/1 (string()) has nothing in common with 'fail' | 'ok', which is the expected return type for the callback of sample_behaviour behaviour
+sample_callback_wrong.erl:20: The inferred type for the 1st argument of sample_callback_5/1 (atom()) is not a supertype of 1..255, which is expected type for this argument in the callback of the sample_behaviour behaviour
+sample_callback_wrong.erl:22: The inferred return type of sample_callback_6/3 ({'okk',number()}) has nothing in common with 'fail' | {'ok',1..255}, which is the expected return type for the callback of sample_behaviour behaviour
+sample_callback_wrong.erl:22: The inferred type for the 3rd argument of sample_callback_6/3 (atom()) is not a supertype of string(), which is expected type for this argument in the callback of the sample_behaviour behaviour
+sample_callback_wrong.erl:4: Undefined callback function sample_callback_1/0 (behaviour 'sample_behaviour')
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old
new file mode 100644
index 0000000000..f0181bb59c
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour_old
@@ -0,0 +1,4 @@
+
+incorrect_args_callback.erl:12: The inferred type for the 2nd argument of bar/2 ('yes') is not a supertype of [any()], which is expected type for this argument in the callback of the correct_behaviour behaviour
+incorrect_return_callback.erl:9: The inferred return type of foo/0 ('error') has nothing in common with 'no' | 'yes', which is the expected return type for the callback of correct_behaviour behaviour
+missing_callback.erl:5: Undefined callback function foo/0 (behaviour 'correct_behaviour')
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return b/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return
new file mode 100644
index 0000000000..e89caf3cf7
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return
@@ -0,0 +1,2 @@
+
+supervisor_incorrect_return.erl:14: The inferred return type of init/1 ({'ok',{{'one_against_one',0,1},[{_,_,_,_,_,_},...]}}) has nothing in common with 'ignore' | {'ok',{{'one_for_all',non_neg_integer(),non_neg_integer()} | {'one_for_one',non_neg_integer(),non_neg_integer()} | {'rest_for_one',non_neg_integer(),non_neg_integer()} | {'simple_one_for_one',non_neg_integer(),non_neg_integer()},[{_,{atom() | tuple(),atom(),'undefined' | [any()]},'permanent' | 'temporary' | 'transient','brutal_kill' | 'infinity' | non_neg_integer(),'supervisor' | 'worker','dynamic' | [atom() | tuple()]}]}}, which is the expected return type for the callback of supervisor behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks b/lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks
new file mode 100644
index 0000000000..7147ffc750
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/undefined_callbacks
@@ -0,0 +1,2 @@
+
+undefined_beh_callback.erl:5: Callback info about the undefined_behaviour behaviour is not available
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec b/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec
new file mode 100644
index 0000000000..5284e412f0
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec
@@ -0,0 +1,6 @@
+
+vars_in_beh_spec.erl:3: Undefined callback function handle_call/3 (behaviour 'gen_server')
+vars_in_beh_spec.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server')
+vars_in_beh_spec.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server')
+vars_in_beh_spec.erl:3: Undefined callback function init/1 (behaviour 'gen_server')
+vars_in_beh_spec.erl:3: Undefined callback function terminate/2 (behaviour 'gen_server')
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_behaviour.erl
new file mode 100644
index 0000000000..c4e5203448
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_behaviour.erl
@@ -0,0 +1,11 @@
+-module(my_behaviour).
+
+-callback callback_init(Parent :: pid()) -> {'ok', State::term()}.
+
+-callback callback_cast(State::term(), From::pid(), Msg::term()) ->
+ {'noreply', NewState::term()}.
+
+-callback callback_call(State::term(), From::pid(), Msg::term()) ->
+ {'reply', NewState::term(), Reply::term()}.
+
+-callback callback_exit(State::term()) -> 'ok'.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_correct.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_correct.erl
new file mode 100644
index 0000000000..041b4ac56c
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_correct.erl
@@ -0,0 +1,59 @@
+-module(my_callbacks_correct).
+
+-export([
+ callback_init/1
+ , callback_call/3
+ , callback_cast/3
+ , callback_exit/1
+ ]).
+
+-record(state, {
+ parent :: pid(),
+ status = init :: 'init' | 'open' | 'closed',
+ subscribe = [] :: list({pid(), integer()}),
+ counter = 1 :: integer()
+ }).
+
+-type state() :: #state{}.
+
+-type cast_message() :: 'open' | 'closed'.
+
+-type call_message() :: 'subscribe' | 'unsubscribe'.
+-type call_reply() :: 'accepted' | 'rejected'.
+
+-spec callback_init(Parent::pid()) -> {'ok', state()}.
+
+callback_init(Parent) ->
+ {ok, #state{parent = Parent}}.
+
+-spec callback_cast(state(), pid(), cast_message()) -> {'noreply', state()}.
+
+callback_cast(#state{parent = Pid} = State, Pid, Message)
+ when Message =:= 'open'; Message =:= 'close' ->
+ {noreply, State#state{status = Message}};
+callback_cast(State, _Pid, _Message) ->
+ {noreply, State}.
+
+-spec callback_call(state(), pid(), call_message()) ->
+ {'reply', state(), call_reply()}.
+
+callback_call(#state{status = open, subscribe = Subscribers} = State,
+ Pid, Message)
+ when Message =:= 'subscribe';
+ Message =:= 'unsubscribe' ->
+ NewState =
+ case Message of
+ subscribe ->
+ N = State#state.counter,
+ State#state{subscribe = [{Pid, N}|Subscribers], counter = N+1};
+ unsubscribe ->
+ State#state{subscribe = lists:keydelete(Pid, 1, Subscribers)}
+ end,
+ {reply, NewState, accepted};
+callback_call(State, _Pid, _Message) ->
+ {reply, State, rejected}.
+
+-spec callback_exit(state()) -> 'ok'.
+
+callback_exit(_State) ->
+ ok.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_wrong.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_wrong.erl
new file mode 100644
index 0000000000..0459622dc1
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/callbacks_and_specs/my_callbacks_wrong.erl
@@ -0,0 +1,61 @@
+-module(my_callbacks_wrong).
+
+-export([
+ callback_init/1
+ , callback_call/3
+ , callback_cast/3
+ , callback_exit/1
+ ]).
+
+-behaviour(my_behaviour).
+
+-record(state, {
+ parent :: pid(),
+ status = init :: 'init' | 'open' | 'closed',
+ subscribe = [] :: list({pid(), integer()}),
+ counter = 1 :: integer()
+ }).
+
+-type state() :: #state{}.
+
+-type cast_message() :: 'open' | 'closed'.
+
+-type call_message() :: 'subscribe' | 'unsubscribe'.
+-type call_reply() :: 'accepted' | 'rejected'.
+
+-spec callback_init(Parent::pid()) -> state(). %% Wrong return spec
+
+callback_init(Parent) -> #state{parent = Parent}. %% Wrong return
+
+-spec callback_cast(state(), pid() | atom(), cast_message()) ->
+ {'noreply' | 'reply', state()}. %% More generic spec
+
+callback_cast(#state{parent = Pid} = State, Pid, Message)
+ when Message =:= 'open'; Message =:= 'close' ->
+ {noreply, State#state{status = Message}};
+callback_cast(State, _Pid, _Message) ->
+ {noreply, State}.
+
+-spec callback_call(state(), atom(), call_message()) -> %% Wrong arg spec
+ {'reply', state(), call_reply()}.
+
+callback_call(#state{status = open, subscribe = Subscribers} = State,
+ Pid, Message)
+ when Message =:= 'subscribe';
+ Message =:= 'unsubscribe' ->
+ NewState =
+ case Message of
+ subscribe ->
+ N = State#state.counter,
+ State#state{subscribe = [{Pid, N}|Subscribers], counter = N+1};
+ unsubscribe ->
+ State#state{subscribe = lists:keydelete(Pid, 1, Subscribers)}
+ end,
+ {reply, NewState, accepted};
+callback_call(State, _Pid, _Message) ->
+ {reply, State, rejected}.
+
+-spec callback_exit(state()) -> ok.
+
+callback_exit(_State) ->
+ ok.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl
new file mode 100644
index 0000000000..8ec84d798f
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl
@@ -0,0 +1,37 @@
+%%% Dialyzer was giving a warning with this input because of a bug in the
+%%% substitution of remote types in specs. Remote types in the first element of
+%%% a tuple would not update the tuple's tag set and we could end up with a
+%%% non-normalized representation.
+%%%
+%%% Reported by Damian Dobroczyński on 29/02/2012
+
+-module(custom_sup).
+
+-behavior(supervisor).
+
+-export([init/1]).
+
+-spec init(atom()) ->
+ {ok, {{supervisor:strategy(), non_neg_integer(), non_neg_integer()},
+ [supervisor:child_spec()]}} | ignore.
+
+init(StorageName) ->
+ Strategy = {one_for_all, 100, 1},
+ %% get application-wide storage parameters
+ case application:get_env(storage) of
+ undefined ->
+ ignore;
+ {ok, Storage} ->
+ BackendId = proplists:get_value(backend, Storage),
+ BackendArgs = proplists:get_value(args, Storage),
+ if
+ (BackendId =:= undefined) orelse (BackendArgs =:= undefined) ->
+ ignore;
+ true ->
+ {ok, {Strategy,
+ [{id1, {a_module, start_link, []},
+ permanent, 5000, worker, [a_module]},
+ {id2, {another_module, start_link, []},
+ permanent, 5000, worker, [another_module]}]}}
+ end
+ end.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl
new file mode 100644
index 0000000000..f5ccf7f8c4
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_event_incorrect_return.erl
@@ -0,0 +1,33 @@
+-module(gen_event_incorrect_return).
+
+-behaviour(gen_event).
+
+-export([start_link/0, add_handler/0]).
+
+-export([init/1, handle_event/2, handle_call/2,
+ handle_info/2, terminate/2, code_change/3]).
+
+start_link() ->
+ gen_event:start_link({local, myserver}).
+
+add_handler() ->
+ gen_event:add_handler(myserver, ?MODULE, []).
+
+init([]) ->
+ error.
+
+handle_event(_Event, State) ->
+ {ok, State}.
+
+handle_call(_Request, State) ->
+ Reply = ok,
+ {ok, Reply, State}.
+
+handle_info(_Info, State) ->
+ {ok, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl
new file mode 100644
index 0000000000..df04dff80d
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_incorrect_args.erl
@@ -0,0 +1,11 @@
+-module(gen_server_incorrect_args).
+
+-behaviour(gen_server).
+
+-export([handle_call/3]).
+
+handle_call(_Request, From, _State) ->
+ case From of
+ 'boo' -> {'ok'};
+ 'foo' -> {'no'}
+ end.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl
new file mode 100644
index 0000000000..760466fdac
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_missing_callbacks.erl
@@ -0,0 +1,23 @@
+-module(gen_server_missing_callbacks).
+
+-behaviour(gen_server).
+
+-export([start_link/0]).
+
+-export([init/1, handle_call/3, terminate/2, code_change/3]).
+
+start_link() ->
+ gen_server:start_link({local, myserver}, ?MODULE, [], []).
+
+init([]) ->
+ ignore.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl
new file mode 100644
index 0000000000..116980986b
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_behaviour.erl
@@ -0,0 +1,13 @@
+-module(sample_behaviour).
+
+-type custom() :: 1..42.
+
+-callback sample_callback_1() -> term().
+-callback sample_callback_2() -> atom().
+-callback sample_callback_3() -> {'ok', custom()} | 'fail'.
+
+-callback sample_callback_4(term()) -> 'ok'.
+-callback sample_callback_5(custom()) -> 'ok' | 'fail'.
+
+-callback sample_callback_6(custom(), custom(), string()) ->
+ {'ok', custom()} | 'fail'.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl
new file mode 100644
index 0000000000..ab0378e6f0
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct.erl
@@ -0,0 +1,32 @@
+-module(sample_callback_correct).
+
+-behaviour(sample_behaviour).
+
+-export([
+ sample_callback_1/0,
+ sample_callback_2/0,
+ sample_callback_3/0,
+ sample_callback_4/1,
+ sample_callback_5/1,
+ sample_callback_6/3
+ ]).
+
+sample_callback_1() -> 42. % This is a valid return.
+sample_callback_2() -> foo. % This is a valid return.
+sample_callback_3() -> {ok, 17}. % This is a valid return.
+sample_callback_4(Input) ->
+ put(mine, Input+1), % This is valid handling of the input
+ ok. % This is a valid return.
+sample_callback_5(Input) ->
+ case Input - 1 < 22 of % This is valid handling of the input
+ true -> ok; % This is a valid return.
+ false -> fail % This is a valid return.
+ end.
+sample_callback_6(OldNr, NewNr, Reason) ->
+ Diff = NewNr - OldNr, % This is valid handling of the input
+ Msg = string:join(["Reason: ", Reason], ","), % This is valid handling of the input
+ case Diff > 0 of
+ true -> put(mine, {NewNr, Msg}),
+ {ok, NewNr}; % This is a valid return.
+ false -> fail % This is a valid return.
+ end.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl
new file mode 100644
index 0000000000..c218174e58
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_correct_2.erl
@@ -0,0 +1,38 @@
+-module(sample_callback_correct_2).
+
+-behaviour(sample_behaviour).
+
+-export([
+ sample_callback_1/0,
+ sample_callback_2/0,
+ sample_callback_3/0,
+ sample_callback_4/1,
+ sample_callback_5/1,
+ sample_callback_6/3,
+ common_infrastructure/1
+ ]).
+
+sample_callback_1() -> 42. % This is a valid return.
+sample_callback_2() -> halt(). % Crashes are also allowed.
+sample_callback_3() -> {ok, 17}. % This is a valid return.
+sample_callback_4(Input) ->
+ case Input of
+ 1 -> common_infrastructure(Input); % This is 'correct' input for
+ _ -> ok % common_infrastructure.
+ end.
+sample_callback_5(Input) ->
+ case get(Input) of % This is valid handling of a more generic input
+ true -> ok; % This is a valid return.
+ false -> fail % This is a valid return.
+ end.
+sample_callback_6(OldNr, NewNr, Reason) ->
+ Diff = NewNr - OldNr, % This is valid handling of the input
+ Msg = string:join(["Reason: ", Reason], ","), % This is valid handling of the input
+ case Diff > 0 of
+ true -> put(mine, {NewNr, Msg}),
+ {ok, NewNr}; % This is a valid return.
+ false -> fail % This is a valid return.
+ end.
+
+common_infrastructure( 1) -> 'ok';
+common_infrastructure(42) -> 'fail'.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl
new file mode 100644
index 0000000000..430494c48c
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl
@@ -0,0 +1,26 @@
+-module(sample_callback_wrong).
+
+%% This attribute uses the american spelling of 'behaviour'.
+-behavior(sample_behaviour).
+
+-export([
+% sample_callback_1/0,
+ sample_callback_2/0,
+ sample_callback_3/0,
+ sample_callback_4/1,
+ sample_callback_5/1,
+ sample_callback_6/3
+ ]).
+
+% sample_callback_1() -> 41. % We can't really break this contract so: missing!
+sample_callback_2() -> 42. % This is not an atom().
+sample_callback_3() -> fair. % This is probably a typo.
+sample_callback_4(_) -> % We cannot break the input.
+ fail. % We can definitely return a wrong value however. :)
+sample_callback_5(Input) -> % Input is treated as an atom, result is a list.
+ atom_to_list(Input). % Both violate the contract.
+sample_callback_6(OldNr, NewNr, Reason) ->
+ Diff = NewNr - OldNr, % This is valid handling of the input
+ %% Reason should have been treated as a string.
+ Msg = string:join(["Reason: ", atom_to_list(Reason)], ","),
+ {okk, NewNr}. %% This, too, is a typo.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl
new file mode 100644
index 0000000000..90ce590997
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_behaviour.erl
@@ -0,0 +1,6 @@
+%%% This is a behaviour with info about its calllbacks.
+
+-module(correct_behaviour).
+
+-callback foo() -> yes | no.
+-callback bar({atom(),_},[_]) -> term().
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl
new file mode 100644
index 0000000000..8f254520ab
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/correct_callback.erl
@@ -0,0 +1,15 @@
+%%% This is a correct callback module for the correct_behaviour.
+
+-module(correct_callback).
+
+-behaviour(correct_behaviour).
+
+-export([foo/0, bar/2]).
+
+foo() ->
+ yes.
+
+bar({'query', 'boo'}, _Any) ->
+ no;
+bar({'reply', [_R]}, [1,2,3]) ->
+ yes.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl
new file mode 100644
index 0000000000..68fc60d418
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_args_callback.erl
@@ -0,0 +1,13 @@
+%%% This is a correct callback module for the correct_behaviour.
+
+-module(incorrect_args_callback).
+
+-behaviour(correct_behaviour).
+
+-export([foo/0, bar/2]).
+
+foo() ->
+ yes.
+
+bar({'reply', _Any}, yes) -> %% Should be a tuple and a list.
+ yes.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl
new file mode 100644
index 0000000000..9ff920cdd0
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/incorrect_return_callback.erl
@@ -0,0 +1,15 @@
+%%% This is a correct callback module for the correct_behaviour.
+
+-module(incorrect_return_callback).
+
+-behaviour(correct_behaviour).
+
+-export([foo/0, bar/2]).
+
+foo() ->
+ error. %% Should be 'yes' or 'no'.
+
+bar({'query', 'boo'}, _Any) ->
+ no;
+bar({'reply', [_R]}, [1,2,3]) ->
+ yes.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl
new file mode 100644
index 0000000000..e6c5306839
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour_old/missing_callback.erl
@@ -0,0 +1,10 @@
+%%% This is a correct callback module for the correct_behaviour.
+
+-module(missing_callback).
+
+-behaviour(correct_behaviour).
+
+-export([bar/2]).
+
+bar({'reply', _Any}, []) ->
+ yes.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl
new file mode 100644
index 0000000000..616a9073ae
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/supervisor_incorrect_return.erl
@@ -0,0 +1,17 @@
+-module(supervisor_incorrect_return).
+
+-behaviour(supervisor).
+
+-export([start_link/0]).
+
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+start_link() ->
+ supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+init([]) ->
+ AChild = {'AName',{'AModule',start_link,[]},
+ permanent,2000,worker,['AModule']},
+ {ok,{{one_against_one,0,1}, [AChild]}}.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl
new file mode 100644
index 0000000000..8223225b4b
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_beh_callback.erl
@@ -0,0 +1,13 @@
+%%% This is a correct callback module for the correct_behaviour.
+
+-module(undefined_beh_callback).
+
+-behaviour(undefined_behaviour).
+
+-export([foo/0, bar/2]).
+
+foo() ->
+ yes.
+
+bar({'reply', _Any}, yes) ->
+ yes.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl
new file mode 100644
index 0000000000..fb3d4c5e03
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/undefined_callbacks/undefined_behaviour.erl
@@ -0,0 +1,10 @@
+%%% This is a behaviour with undefined info about its calllbacks.
+
+-module(undefined_behaviour).
+
+-export([behaviour_info/1]).
+
+behaviour_info(callbacks) ->
+ [{foo, 0}, {bar, 2}];
+behaviour_info(_Other) ->
+ undefined.
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/vars_in_beh_spec.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/vars_in_beh_spec.erl
new file mode 100644
index 0000000000..dc75b30d0e
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/vars_in_beh_spec.erl
@@ -0,0 +1,10 @@
+-module(vars_in_beh_spec).
+
+-behaviour(gen_server).
+
+-export([code_change/3]).
+
+-spec code_change(_, State, _) -> {ok, State}.
+
+code_change(_, State, _) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/dialyzer_common.erl b/lib/dialyzer/test/dialyzer_common.erl
index 51766a4604..d2b1026c06 100644
--- a/lib/dialyzer/test/dialyzer_common.erl
+++ b/lib/dialyzer/test/dialyzer_common.erl
@@ -216,10 +216,13 @@ get_suites(Dir) ->
end.
suffix(String, Suffix) ->
- Index = string:rstr(String, Suffix),
- case string:substr(String, Index) =:= Suffix of
- true -> {yes, string:sub_string(String,1,Index-1)};
- false -> no
+ case string:rstr(String, Suffix) of
+ 0 -> no;
+ Index ->
+ case string:substr(String, Index) =:= Suffix of
+ true -> {yes, string:sub_string(String,1,Index-1)};
+ false -> no
+ end
end.
-spec create_suite(string()) -> 'ok'.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash
index 6bdd934169..1ddae5149f 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/crash
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash
@@ -1,5 +1,4 @@
-crash_1.erl:42: The specification for crash_1:empty/0 states that the function might also return crash_1:targetlist() but the inferred return is none()
crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::'undefined' | crash_1:target()
crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::'undefined' | crash_1:target()) contains an opaque term as 2nd argument when terms of different types are expected in these positions
crash_1.erl:50: The pattern <_Branch, []> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()>
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques b/lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques
new file mode 100644
index 0000000000..18ece8820c
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques
@@ -0,0 +1,2 @@
+
+multiple_wrong_opaques.erl:5: Invalid type specification for function multiple_wrong_opaques:weird/1. The success typing is ('gazonk') -> 42
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/queue b/lib/dialyzer/test/opaque_SUITE_data/results/queue
index 59ce33f098..c3f04ea64d 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/queue
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/queue
@@ -5,6 +5,7 @@ queue_use.erl:27: The attempt to match a term of type queue() against the patter
queue_use.erl:33: Attempt to test for equality between a term of type {[42,...],[]} and a term of opaque type queue()
queue_use.erl:36: The attempt to match a term of type queue() against the pattern {F, _R} breaks the opaqueness of the term
queue_use.erl:40: The call queue:out({[42,...],[]}) does not have an opaque term of type queue() as 1st argument
+queue_use.erl:48: The call queue_use:add_unique(42,#db{p::[],q::queue()}) contains an opaque term as 2nd argument when terms of different types are expected in these positions
queue_use.erl:51: The call queue_use:is_in_queue(E::42,DB::#db{p::[],q::queue()}) contains an opaque term as 2nd argument when terms of different types are expected in these positions
queue_use.erl:56: The attempt to match a term of type #db{p::[],q::queue()} against the pattern {'db', _, {L1, L2}} breaks the opaqueness of queue()
queue_use.erl:62: The call queue_use:tuple_queue({42,'gazonk'}) does not have a term of type {_,queue()} (with opaque subterms) as 1st argument
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl b/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl
new file mode 100644
index 0000000000..9e695cec1d
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl
@@ -0,0 +1,8 @@
+-module(multiple_wrong_opaques).
+
+-export([weird/1]).
+
+-spec weird(dict() | gb_tree()) -> 42.
+
+weird(gazonk) -> 42.
+
diff --git a/lib/dialyzer/test/options1_SUITE_data/results/compiler b/lib/dialyzer/test/options1_SUITE_data/results/compiler
index e82087ae86..6399e3e36b 100644
--- a/lib/dialyzer/test/options1_SUITE_data/results/compiler
+++ b/lib/dialyzer/test/options1_SUITE_data/results/compiler
@@ -20,6 +20,7 @@ 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:244: Function counter_stats/0 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()]>
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets
index 0177dcc88c..773525eb7f 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/inets
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets
@@ -3,21 +3,16 @@ ftp.erl:1243: The pattern {'ok', {N, Bytes}} can never match the type 'eof' | {'
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: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:660: Function exit_session_ok/2 has no local return
+httpc_handler.erl:676: Function format_time/0 will never be called
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
@@ -26,14 +21,10 @@ httpd_manager.erl:885: The pattern {'EXIT', Reason} can never match since previo
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_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:649: Guard test [{_,_}] =:= Trailers::nonempty_string() can never succeed
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',_,_}
@@ -48,10 +39,10 @@ mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[
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: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() | [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
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
index 2be71ac7d7..b397d37523 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
@@ -2,6 +2,7 @@
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_backup.erl:49: Callback info about the mnesia_backup behaviour is not available
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
@@ -12,9 +13,12 @@ mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can neve
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:26: Callback info about the mnesia_access behaviour is not available
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_frag_hash.erl:24: Callback info about the mnesia_frag_hash behaviour is not available
+mnesia_frag_old_hash.erl:23: Callback info about the mnesia_frag_hash behaviour is not available
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()}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify b/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify
index 87bf6f309f..06dc0d63ee 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify
+++ b/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify
@@ -1,4 +1,4 @@
cerl_hipeify.erl:370: Function will never be called
-cerl_hipeify.erl:370: Guard test fun((none()) -> none()) =:= F::{_,_,_} | {_,_,_,_} | {_,_,_,_,_} | {_,_,_,_,_,_} | {_,_,_,_,_,_,_} can never succeed
+cerl_hipeify.erl:370: Guard test fun((none()) -> no_return()) =:= F::{_,_,_} | {_,_,_,_} | {_,_,_,_,_} | {_,_,_,_,_,_} | {_,_,_,_,_,_,_} can never succeed
cerl_hipeify.erl:641: Function env__new_function_name/2 will never be called
diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
new file mode 100644
index 0000000000..8dc0361b0d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
@@ -0,0 +1,31 @@
+
+contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
+contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
+contracts_with_subtypes.erl:108: The call contracts_with_subtypes:rec_arg({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
+contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
+contracts_with_subtypes.erl:110: The call contracts_with_subtypes:rec_arg({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
+contracts_with_subtypes.erl:111: The call contracts_with_subtypes:rec_arg({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
+contracts_with_subtypes.erl:142: The pattern 1 can never match the type binary() | string()
+contracts_with_subtypes.erl:145: The pattern 'alpha' can never match the type {'ok',X} | {'ok',X,binary() | string()}
+contracts_with_subtypes.erl:147: The pattern 42 can never match the type {'ok',_} | {'ok',_,binary() | string()}
+contracts_with_subtypes.erl:163: The pattern 'alpha' can never match the type {'ok',X}
+contracts_with_subtypes.erl:165: The pattern 42 can never match the type {'ok',X}
+contracts_with_subtypes.erl:183: The pattern 'alpha' can never match the type {'ok',X}
+contracts_with_subtypes.erl:185: The pattern 42 can never match the type {'ok',X}
+contracts_with_subtypes.erl:202: The pattern 1 can never match the type binary() | string()
+contracts_with_subtypes.erl:205: The pattern {'ok', _} can never match the type {'ok',X,binary() | string()}
+contracts_with_subtypes.erl:206: The pattern 'alpha' can never match the type {'ok',X,binary() | string()}
+contracts_with_subtypes.erl:207: The pattern {'ok', 42} can never match the type {'ok',X,binary() | string()}
+contracts_with_subtypes.erl:208: The pattern 42 can never match the type {'ok',X,binary() | string()}
+contracts_with_subtypes.erl:234: Function flat_ets_new_t/0 has no local return
+contracts_with_subtypes.erl:235: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed')
+contracts_with_subtypes.erl:23: Invalid type specification for function contracts_with_subtypes:extract2/0. The success typing is () -> 'something'
+contracts_with_subtypes.erl:261: Function factored_ets_new_t/0 has no local return
+contracts_with_subtypes.erl:262: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks), is_subtype(Type,type()), is_subtype(Access,access()), is_subtype(Tweaks,{'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed'), is_subtype(Pos,pos_integer()), is_subtype(HeirData,term())
+contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,atom()), is_subtype(Res,atom())
+contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,Arg2), is_subtype(Arg2,atom()), is_subtype(Res,atom())
+contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when is_subtype(Arg2,atom()), is_subtype(Arg1,Arg2), is_subtype(Res,atom())
+contracts_with_subtypes.erl:7: Invalid type specification for function contracts_with_subtypes:extract/0. The success typing is () -> 'something'
+contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when is_subtype(Type,atom())
+contracts_with_subtypes.erl:81: The call contracts_with_subtypes:foo5(5) breaks the contract (Type::atom()) -> Type::atom()
+contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when is_subtype(Type,atom())
diff --git a/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
new file mode 100644
index 0000000000..7ce440a60d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
@@ -0,0 +1,4 @@
+
+higher_order_discrepancy.erl:11: The call higher_order_discrepancy:g('foo') will never return since it differs in the 1st argument from the success typing arguments: ('bar')
+higher_order_discrepancy.erl:14: Function g/1 has no local return
+higher_order_discrepancy.erl:14: The pattern 'bar' can never match the type 'foo'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_2 b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_2
new file mode 100644
index 0000000000..c1c7dbbfcc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy_2
@@ -0,0 +1,8 @@
+
+higher_order_discrepancy_2.erl:11: The call higher_order_discrepancy_2:f('foo') will never return since it differs in the 1st argument from the success typing arguments: ('bar')
+higher_order_discrepancy_2.erl:11: The call higher_order_discrepancy_2:g('foo') will never return since it differs in the 1st argument from the success typing arguments: ('baz')
+higher_order_discrepancy_2.erl:13: Function f/1 has no local return
+higher_order_discrepancy_2.erl:13: The pattern 'bar' can never match the type 'foo'
+higher_order_discrepancy_2.erl:14: Function g/1 has no local return
+higher_order_discrepancy_2.erl:14: The pattern 'baz' can never match the type 'foo'
+higher_order_discrepancy_2.erl:5: Function test/1 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/inf_loop2 b/lib/dialyzer/test/small_SUITE_data/results/inf_loop2
index 7e9972ad98..142e4b2c37 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/inf_loop2
+++ b/lib/dialyzer/test/small_SUITE_data/results/inf_loop2
@@ -1,4 +1,4 @@
inf_loop2.erl:18: Function test/0 has no local return
inf_loop2.erl:19: The call lists:reverse('gazonk') will never return since it differs in the 1st argument from the success typing arguments: ([any()])
-inf_loop2.erl:22: Function loop/0 has no local return
+inf_loop2.erl:22: Function loop/0 will never be called
diff --git a/lib/dialyzer/test/small_SUITE_data/results/no_local_return b/lib/dialyzer/test/small_SUITE_data/results/no_local_return
new file mode 100644
index 0000000000..6ca1ed51d8
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/no_local_return
@@ -0,0 +1,3 @@
+
+no_local_return.erl:11: Function bar/1 will never be called
+no_local_return.erl:8: Function foo/0 will never be called
diff --git a/lib/dialyzer/test/small_SUITE_data/results/port_info_test b/lib/dialyzer/test/small_SUITE_data/results/port_info_test
index 9ee863f9eb..863a3d61df 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/port_info_test
+++ b/lib/dialyzer/test/small_SUITE_data/results/port_info_test
@@ -3,4 +3,5 @@ port_info_test.erl:10: The pattern {'connected', 42} can never match the type 'u
port_info_test.erl:14: The pattern {'registered_name', "42"} can never match the type 'undefined' | {'registered_name',atom()}
port_info_test.erl:19: The pattern {'output', 42} can never match the type 'undefined' | {'connected',pid()}
port_info_test.erl:24: Guard test 'links' =:= Atom::'connected' can never succeed
-port_info_test.erl:28: The pattern {'gazonk', _} can never match the type 'undefined' | {'connected' | 'id' | 'input' | 'links' | 'name' | 'output' | 'registered_name',atom() | pid() | [pid() | char()] | integer()}
+port_info_test.erl:28: The pattern {'gazonk', _} can never match the type 'undefined' | {'connected' | 'id' | 'input' | 'links' | 'name' | 'os_pid' | 'output' | 'registered_name',atom() | pid() | [pid() | char()] | integer()}
+port_info_test.erl:32: The pattern {'os_pid', "42"} can never match the type 'undefined' | {'os_pid','undefined' | non_neg_integer()}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
index 191d3d4173..8c9df56a4b 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
+++ b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
@@ -12,4 +12,3 @@ tuple_set_crash.erl:179: The pattern <<AudioVolume:16/integer-little-unit:1,Rest
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_SUITE_data/src/collapse_lists/a.erl b/lib/dialyzer/test/small_SUITE_data/src/collapse_lists/a.erl
new file mode 100644
index 0000000000..7efe870b0d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/collapse_lists/a.erl
@@ -0,0 +1,9 @@
+-module(a).
+-export([g/1]).
+
+-export_type([a/0, t/0]).
+-type a() :: integer().
+-type t() :: a() | maybe_improper_list(t(), t()).
+
+-spec g(t()) -> t().
+g(X) -> X.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/collapse_lists/b.erl b/lib/dialyzer/test/small_SUITE_data/src/collapse_lists/b.erl
new file mode 100644
index 0000000000..b08bc5e66c
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/collapse_lists/b.erl
@@ -0,0 +1,5 @@
+-module(b).
+-export([f/1]).
+
+-spec f(a:t()) -> a:t().
+f(X) -> a:g(X).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl b/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl
new file mode 100644
index 0000000000..d72138d509
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl
@@ -0,0 +1,267 @@
+-module(contracts_with_subtypes).
+
+-compile(export_all).
+
+%===============================================================================
+
+-spec extract() -> 'ok'.
+
+extract() ->
+ case dz_extract() of
+ {ok, Val} -> Val;
+ error -> exit(boom)
+ end.
+
+-spec dz_extract() -> RetValue when
+ FileList :: something,
+ RetValue :: {ok, FileList} | error.
+
+dz_extract() -> get(foo).
+
+%-------------------------------------------------------------------------------
+
+-spec extract2() -> 'ok'.
+
+extract2() ->
+ case dz_extract2() of
+ {ok, Val} -> Val;
+ error -> exit(boom)
+ end.
+
+-spec dz_extract2() -> RetValue when
+ RetValue :: {ok, FileList} | error,
+ FileList :: something.
+
+dz_extract2() -> get(foo).
+
+%===============================================================================
+
+-spec foo1(Arg1) -> Res when
+ Arg1 :: atom(),
+ Res :: atom().
+
+foo1(X) -> X.
+
+-spec foo2(Arg1) -> Res when
+ Arg1 :: Arg2,
+ Arg2 :: atom(),
+ Res :: atom().
+
+foo2(X) -> X.
+
+-spec foo3(Arg1) -> Res when
+ Arg2 :: atom(),
+ Arg1 :: Arg2,
+ Res :: atom().
+
+foo3(X) -> X.
+
+-spec foo4(Type) -> Type when is_subtype(Type, atom()).
+
+foo4(X) -> X.
+
+-spec foo5(Type :: atom()) -> Type :: atom().
+
+foo5(X) -> X.
+
+-spec foo6(Type) -> Type when Type :: atom().
+
+foo6(X) -> X.
+
+-spec foo7(Type) -> Type.
+
+foo7(X) -> X.
+
+%-------------------------------------------------------------------------------
+
+bar(1) -> foo1(5);
+bar(2) -> foo2(5);
+bar(3) -> foo3(5);
+bar(4) -> foo4(5);
+bar(5) -> foo5(5);
+bar(6) -> foo6(5);
+bar(7) -> foo7(5).
+
+wrong_foo6() ->
+ b = foo6(a).
+
+%===============================================================================
+
+-spec rec_arg(Arg) -> ok when
+ Arg :: {a, A} | {b, B},
+ A :: a | {b, B},
+ B :: b | {a, A}.
+
+rec_arg(X) -> get(X).
+
+c(aa) -> rec_arg({a, a});
+c(bb) -> rec_arg({b, b});
+c(abb) -> rec_arg({a, {b, b}});
+c(baa) -> rec_arg({b, {a, a}});
+c(abaa) -> rec_arg({a, {b, {a, a}}});
+c(babb) -> rec_arg({b, {a, {b, b}}});
+c(ababb) -> rec_arg({a, {b, {a, {b, b}}}});
+c(babaa) -> rec_arg({b, {a, {b, {a, a}}}}).
+
+w(ab) -> rec_arg({a, b});
+w(ba) -> rec_arg({b, a});
+w(aba) -> rec_arg({a, {b, a}});
+w(bab) -> rec_arg({b, {a, b}});
+w(abab) -> rec_arg({a, {b, {a, b}}});
+w(baba) -> rec_arg({b, {a, {b, a}}});
+w(ababa) -> rec_arg({a, {b, {a, {b, a}}}});
+w(babab) -> rec_arg({b, {a, {b, {a, b}}}}).
+
+%===============================================================================
+
+-type dublo(X) :: {X, X}.
+
+-type weird(X,Y) :: {X, Y, X, X}.
+
+-spec forfun(dublo(Var)) -> ok when Var :: atom().
+
+forfun(_) -> ok.
+
+-spec forfun2(weird(Var, Var)) -> ok when Var :: atom().
+
+forfun2(_) -> ok.
+
+%===============================================================================
+
+-spec shallow(X) -> {ok, X} | {ok, X, file:filename()} | err1 | err2.
+
+shallow(X) -> get(X).
+
+st(X) when is_atom(X) ->
+ case shallow(X) of
+ err1 -> ok;
+ err2 -> ok;
+ {ok, X} -> ok;
+ {ok, X, Res} ->
+ case Res of
+ 1 -> bad;
+ _Other -> ok
+ end;
+ alpha -> bad;
+ {ok, 42} -> bad;
+ 42 -> bad
+ end.
+
+%-------------------------------------------------------------------------------
+
+-spec deep(X) -> Ret when
+ Ret :: {ok, X} | Err,
+ Err :: err1 | err2.
+
+deep(X) -> get(X).
+
+dt(X) when is_atom(X) ->
+ case deep(X) of
+ err1 -> ok;
+ err2 -> ok;
+ {ok, X} -> ok;
+ alpha -> bad;
+ {ok, 42} -> bad;
+ 42 -> bad
+ end.
+
+%-------------------------------------------------------------------------------
+
+-type local_errors() :: err1 | err2.
+
+-spec deep2(X) -> Ret when
+ Ret :: {ok, X} | Err,
+ Err :: local_errors().
+
+deep2(X) -> get(X).
+
+dt2(X) when is_atom(X) ->
+ case deep2(X) of
+ err1 -> ok;
+ err2 -> ok;
+ {ok, X} -> ok;
+ alpha -> bad;
+ {ok, 42} -> bad;
+ 42 -> bad
+ end.
+
+%-------------------------------------------------------------------------------
+
+-spec deep3(X) -> Ret when
+ Ret :: {ok, X, file:filename()} | Err,
+ Err :: local_errors().
+
+deep3(X) -> get(X).
+
+dt3(X) when is_atom(X) ->
+ case deep3(X) of
+ err1 -> ok;
+ err2 -> ok;
+ {ok, X, Res} ->
+ case Res of
+ 1 -> bad;
+ _Other -> ok
+ end;
+ {ok, X} -> bad;
+ alpha -> bad;
+ {ok, 42} -> bad;
+ 42 -> bad
+ end.
+
+%===============================================================================
+
+-spec flat_ets_new(Name, Options) -> atom() when
+ Name :: atom(),
+ Options :: [Option],
+ Option :: set
+ | ordered_set
+ | bag
+ | duplicate_bag
+ | public
+ | protected
+ | private
+ | named_table
+ | {keypos, integer()}
+ | {heir, pid(), term()}
+ | {heir, none}
+ | {write_concurrency, boolean()}
+ | {read_concurrency, boolean()}
+ | compressed.
+
+flat_ets_new(Name, Options) ->
+ get({Name, Options}).
+
+flat_ets_new_t() ->
+ flat_ets_new(12,[]),
+ flat_ets_new({a,b},[]),
+ flat_ets_new(name,[foo]),
+ flat_ets_new(name,{bag}),
+ flat_ets_new(name,bag),
+ ok.
+
+-type access() :: public | protected | private.
+-type type() :: set | ordered_set | bag | duplicate_bag.
+
+-spec factored_ets_new(Name, Options) -> atom() when
+ Name :: atom(),
+ Options :: [Option],
+ Option :: Type | Access | named_table | {keypos,Pos}
+ | {heir, Pid :: pid(), HeirData} | {heir, none} | Tweaks,
+ Type :: type(),
+ Access :: access(),
+ Tweaks :: {write_concurrency, boolean()}
+ | {read_concurrency, boolean()}
+ | compressed,
+ Pos :: pos_integer(),
+ HeirData :: term().
+
+factored_ets_new(Name, Options) ->
+ get({Name, Options}).
+
+factored_ets_new_t() ->
+ factored_ets_new(12,[]),
+ factored_ets_new({a,b},[]),
+ factored_ets_new(name,[foo]),
+ factored_ets_new(name,{bag}),
+ factored_ets_new(name,bag),
+ ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/deep_lc.erl b/lib/dialyzer/test/small_SUITE_data/src/deep_lc.erl
new file mode 100644
index 0000000000..d9ca0817d9
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/deep_lc.erl
@@ -0,0 +1,14 @@
+-module(deep_lc).
+
+-export([t/0]).
+
+%% This is compile/test/lc_SUITE:deeply_nested/1
+%%
+%% Used to be _very_ slow. Unknown how slow, but more than 15 hours.
+
+t() ->
+ [[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]].
diff --git a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl
new file mode 100644
index 0000000000..ff5ee6bac4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl
@@ -0,0 +1,14 @@
+-module(higher_order_discrepancy).
+
+-export([test/1]).
+
+test(X) ->
+ F =
+ case X of
+ 1 -> fun f/1;
+ 2 -> fun g/1
+ end,
+ F(foo).
+
+f(foo) -> ok.
+g(bar) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl
new file mode 100644
index 0000000000..4b0d4f6b45
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl
@@ -0,0 +1,14 @@
+-module(higher_order_discrepancy_2).
+
+-export([test/1]).
+
+test(X) ->
+ F =
+ case X of
+ 1 -> fun f/1;
+ 2 -> fun g/1
+ end,
+ F(foo).
+
+f(bar) -> ok.
+g(baz) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl b/lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl
new file mode 100644
index 0000000000..1743d81493
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl
@@ -0,0 +1,7 @@
+-module(maybe_improper).
+
+-export([s/1]).
+
+-spec s(maybe_improper_list(X,Y)) -> {[X], maybe_improper_list(X,Y)}.
+s(A) ->
+ lists:split(2,A).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/maybe_servers.erl b/lib/dialyzer/test/small_SUITE_data/src/maybe_servers.erl
new file mode 100644
index 0000000000..237f43b1a6
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/maybe_servers.erl
@@ -0,0 +1,31 @@
+-module(maybe_servers).
+
+-export([maybe_server/2, mirror_maybe_server/2]).
+
+maybe_server(O, I) ->
+ case O of
+ no ->
+ maybe_loop(fun(_) -> fin end, I);
+ yes ->
+ maybe_loop(fun(X) -> {ok, X} end, I)
+ end.
+
+maybe_loop(F, X)->
+ case F(X) of
+ {ok, Y} -> maybe_loop(F, Y);
+ fin -> exit(n)
+ end.
+
+mirror_maybe_loop(F, X)->
+ case F(X) of
+ {ok, Y} -> mirror_maybe_loop(F, Y);
+ fin -> exit(n)
+ end.
+
+mirror_maybe_server(O, I) ->
+ case O of
+ no ->
+ mirror_maybe_loop(fun(_) -> fin end, I);
+ yes ->
+ mirror_maybe_loop(fun(X) -> {ok, X} end, I)
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl b/lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl
new file mode 100644
index 0000000000..4e1a0b015a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl
@@ -0,0 +1,12 @@
+-module(no_local_return).
+
+%% NOTE: No function is exported. Dialyzer produced a bogus
+%% 'Function foo/0 has no local return' warning
+%% when in fact typer was finding correct return values for both
+%% these functions.
+
+foo() ->
+ bar(42).
+
+bar(X) ->
+ lists:duplicate(X, gazonk).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/on_load.erl b/lib/dialyzer/test/small_SUITE_data/src/on_load.erl
new file mode 100644
index 0000000000..16533a9caa
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/on_load.erl
@@ -0,0 +1,11 @@
+%%% This is to ensure that "on_load" functions are never reported as unused.
+
+-module(on_load).
+
+-export([foo/0]).
+
+-on_load(bar/0).
+
+foo() -> ok.
+
+bar() -> ok.
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
index 2ee9a3a6e2..07f22256c9 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl
@@ -3,7 +3,7 @@
%% 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]).
+-export([t1/1, t2/1, t3/1, t4/1, t5/2, t6/1, buggy/1]).
%% The following errors are correctly caught, but the messages are a bit weird
t1(X) when is_port(X) ->
@@ -28,6 +28,10 @@ t5(X, Atom) when is_port(X) ->
{gazonk, _} = erlang:port_info(X, Atom);
t5(_, _) -> ok.
+t6(X) when is_port(X) ->
+ {os_pid, "42"} = erlang:port_info(X, os_pid);
+t6(_) -> 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/underspecs_SUITE_data/dialyzer_options b/lib/dialyzer/test/underspecs_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..f7197ac30f
--- /dev/null
+++ b/lib/dialyzer/test/underspecs_SUITE_data/dialyzer_options
@@ -0,0 +1 @@
+{dialyzer_options, [{warnings, [underspecs]}]}.
diff --git a/lib/dialyzer/test/underspecs_SUITE_data/results/remote b/lib/dialyzer/test/underspecs_SUITE_data/results/remote
new file mode 100644
index 0000000000..1e0cda3bde
--- /dev/null
+++ b/lib/dialyzer/test/underspecs_SUITE_data/results/remote
@@ -0,0 +1,9 @@
+
+remotes1.erl:17: The specification for remotes1:foo5/1 states that the function might also return 'ko' but the inferred return is 'ok'
+remotes1.erl:20: Type specification remotes1:foo6('ok' | 'ko') -> 'ok' is a supertype of the success typing: remotes1:foo6('ok') -> 'ok'
+remotes1.erl:25: The specification for remotes1:foo7/1 states that the function might also return 'ko' but the inferred return is 'ok'
+remotes1.erl:28: Type specification remotes1:foo8(local_type_42()) -> 'ok' is a supertype of the success typing: remotes1:foo8('ok') -> 'ok'
+remotes1.erl:33: The specification for remotes1:foo9/1 states that the function might also return 'ko' but the inferred return is 'ok'
+remotes1.erl:36: Type specification remotes1:foo10(local_and_known_remote_type_42()) -> 'ok' is a supertype of the success typing: remotes1:foo10('ok') -> 'ok'
+remotes1.erl:49: Type specification remotes1:foo13('ok') -> local_and_unknown_remote_type_42() is a supertype of the success typing: remotes1:foo13('ok') -> 'ok'
+remotes1.erl:52: Type specification remotes1:foo14(local_and_unknown_remote_type_42()) -> 'ok' is a supertype of the success typing: remotes1:foo14('ok') -> 'ok'
diff --git a/lib/dialyzer/test/underspecs_SUITE_data/src/remote/remotes1.erl b/lib/dialyzer/test/underspecs_SUITE_data/src/remote/remotes1.erl
new file mode 100644
index 0000000000..b722495095
--- /dev/null
+++ b/lib/dialyzer/test/underspecs_SUITE_data/src/remote/remotes1.erl
@@ -0,0 +1,61 @@
+-module(remotes1).
+
+-compile(export_all).
+
+-spec foo1(some_unknown_remote:type42()) -> ok.
+foo1(ok) -> ok.
+
+-spec foo2(ok) -> some_unknown_remote:type42().
+foo2(ok) -> ok.
+
+-spec foo3(some_known_remote:type42()) -> ok.
+foo3(ok) -> ok.
+
+-spec foo4(ok) -> some_known_remote:type42().
+foo4(ok) -> ok.
+
+-spec foo5(ok|ko) -> ok|ko.
+foo5(ok) -> ok.
+
+-spec foo6(ok|ko) -> ok.
+foo6(ok) -> ok.
+
+-type local_type_42() :: ok | ko.
+
+-spec foo7(ok) -> local_type_42().
+foo7(ok) -> ok.
+
+-spec foo8(local_type_42()) -> ok.
+foo8(ok) -> ok.
+
+-type local_and_known_remote_type_42() :: some_known_remote:type42() | ok | ko.
+
+-spec foo9(ok) -> local_and_known_remote_type_42().
+foo9(ok) -> ok.
+
+-spec foo10(local_and_known_remote_type_42()) -> ok.
+foo10(ok) -> ok.
+
+-type local_and_ok_known_remote_type_42() :: some_known_remote:type42() | ok.
+
+-spec foo11(ok) -> local_and_ok_known_remote_type_42().
+foo11(ok) -> ok.
+
+-spec foo12(local_and_ok_known_remote_type_42()) -> ok.
+foo12(ok) -> ok.
+
+-type local_and_unknown_remote_type_42() :: some_unknown_remote:type42() | ok | ko.
+
+-spec foo13(ok) -> local_and_unknown_remote_type_42().
+foo13(ok) -> ok.
+
+-spec foo14(local_and_unknown_remote_type_42()) -> ok.
+foo14(ok) -> ok.
+
+-type local_and_ok_unknown_remote_type_42() :: some_unknown_remote:type42() | ok.
+
+-spec foo15(ok) -> local_and_ok_unknown_remote_type_42().
+foo15(ok) -> ok.
+
+-spec foo16(local_and_ok_unknown_remote_type_42()) -> ok.
+foo16(ok) -> ok.
diff --git a/lib/dialyzer/test/underspecs_SUITE_data/src/remote/some_known_remote.erl b/lib/dialyzer/test/underspecs_SUITE_data/src/remote/some_known_remote.erl
new file mode 100644
index 0000000000..437f1e7826
--- /dev/null
+++ b/lib/dialyzer/test/underspecs_SUITE_data/src/remote/some_known_remote.erl
@@ -0,0 +1,5 @@
+-module(some_known_remote).
+
+-export_type([type42/0]).
+
+-type type42() :: ok | ko.
diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1
new file mode 100644
index 0000000000..de416455e2
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1
@@ -0,0 +1,2 @@
+
+nowarn_unused_function_1.erl:17: Function f3/1 will never be called
diff --git a/lib/docbuilder/doc/html/.gitignore b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2
index e69de29bb2..e69de29bb2 100644
--- a/lib/docbuilder/doc/html/.gitignore
+++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2
diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3
new file mode 100644
index 0000000000..8ae78673d5
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3
@@ -0,0 +1,3 @@
+
+nowarn_unused_function_3.erl:12: Function f2/1 will never be called
+nowarn_unused_function_3.erl:9: Function f1/1 will never be called
diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl
new file mode 100644
index 0000000000..fcce532f73
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl
@@ -0,0 +1,18 @@
+%% Test that option 'nowarn_unused_funcion' works similarly in
+%% Dialyzer as in the compiler.
+
+-module(nowarn_unused_function_1).
+
+-compile(warn_unused_function).
+
+-compile({nowarn_unused_function,f1/1}).
+f1(_) ->
+ a.
+
+-compile({nowarn_unused_function,[{f2,1}]}).
+f2(_) ->
+ a.
+
+-compile({warn_unused_function,[{f3,1}]}).
+f3(_) ->
+ a.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl
new file mode 100644
index 0000000000..9bc3ab14ea
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl
@@ -0,0 +1,18 @@
+%% Test that option 'nowarn_unused_funcion' works similarly in
+%% Dialyzer as in the compiler.
+
+-module(nowarn_unused_function_2).
+
+-compile(nowarn_unused_function).
+
+-compile({warn_unused_function,f1/1}).
+f1(_) ->
+ a.
+
+-compile({warn_unused_function,[{f2,1}]}).
+f2(_) ->
+ a.
+
+-compile({nowarn_unused_function,[{f3,1}]}).
+f3(_) ->
+ a.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl
new file mode 100644
index 0000000000..604c5e436b
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl
@@ -0,0 +1,16 @@
+%% Test that option 'nowarn_unused_funcion' works similarly in
+%% Dialyzer as in the compiler.
+
+-module(nowarn_unused_function_3).
+
+-compile({warn_unused_function,[{f1,1},{f2,1}]}).
+-compile({nowarn_unused_function,[{f3,1}]}).
+
+f1(_) ->
+ a.
+
+f2(_) ->
+ a.
+
+f3(_) ->
+ a.
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index a7e82b54ce..edafcc4afb 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 2.4.4
+DIALYZER_VSN = 2.5.1
diff --git a/lib/diameter/autoconf/vxworks/sed.general b/lib/diameter/autoconf/vxworks/sed.general
index 77b306aa0a..9199983e16 100644
--- a/lib/diameter/autoconf/vxworks/sed.general
+++ b/lib/diameter/autoconf/vxworks/sed.general
@@ -66,7 +66,6 @@ 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@||
diff --git a/lib/diameter/bin/diameterc b/lib/diameter/bin/diameterc
index f5cf3ebc10..a72ba2d75c 100755
--- a/lib/diameter/bin/diameterc
+++ b/lib/diameter/bin/diameterc
@@ -33,19 +33,24 @@
usage() ->
io:format(
- "~w [options] file~n"
+ "~w [options] dict~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",
+ "~n"
+ " --name name = set @name~n"
+ " --prefix prefix = set @prefix~n"
+ " --inherits dict|- = set/clear @inherits~n"
+ "~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) ->
@@ -68,24 +73,30 @@ gen(Args) ->
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
+ try diameter_dict_util:parse({path, File}, Opts) of
+ {ok, Spec} ->
+ 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;
+ {error, Reason} ->
+ error_msg(diameter_dict_util:format_error(Reason), []),
+ 1
catch
error: Reason ->
- error_msg({"ERROR: ~p~n ~p", [Reason, erlang:get_stacktrace()]}),
+ 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).
+ andalso diameter_codegen:from_dict(File, Spec, Opts, Mode).
error_msg({Fmt, Args}) ->
- io:format(standard_error, Fmt ++ "~n", Args).
+ error_msg(Fmt, Args).
+
+error_msg(Fmt, Args) ->
+ io:format(standard_error, "** " ++ Fmt ++ "~n", Args).
norm({_,_} = T) ->
T;
@@ -109,9 +120,17 @@ arg(["-o", Dir | Args], #argv{options = Opts} = A) ->
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(["--name", Name | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = [{name, Name} | Opts]});
+
+arg(["--prefix", Name | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = [{prefix, Name} | Opts]});
+
+arg(["--inherits", Dict | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = Opts ++ [{inherits, Dict}]});
+
arg(["-E" | Args], #argv{output = Output} = A) ->
arg(Args, A#argv{output = lists:delete(erl, Output)});
@@ -120,10 +139,10 @@ arg(["-H" | Args], #argv{output = Output} = A) ->
arg(["-d" | Args], #argv{options = Opts, output = Output} = A) ->
arg(Args, A#argv{options = [debug | Opts],
- output = [spec | Output]});
+ output = [spec | Output]});
arg([[$- = M, C, H | T] | Args], A) %% clustered options
- when C /= $i, C /= $o ->
+ when C /= $i, C /= $o, C /= $- ->
arg([[M,C], [M,H|T] | Args], A);
arg([File], A) ->
diff --git a/lib/diameter/configure.in b/lib/diameter/configure.in
index 9aca3859c5..8acfb28fed 100644
--- a/lib/diameter/configure.in
+++ b/lib/diameter/configure.in
@@ -132,7 +132,6 @@ 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/src/Makefile b/lib/diameter/doc/src/Makefile
index 1453138cb6..cdf63e7fb6 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -126,8 +126,6 @@ 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)"
@@ -141,10 +139,6 @@ info:
@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)"
@@ -168,18 +162,18 @@ 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
+ $(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:
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 43c497f50a..93e2603c10 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -107,7 +107,9 @@ belonging to the application.</p>
<marker id="application_module"/>
</item>
-<tag><c>application_module() = Mod | [Mod | ExtraArgs]</c></tag>
+<tag><c>application_module() = Mod
+ | [Mod | ExtraArgs]
+ | #diameter_callback{}</c></tag>
<item>
<code>
Mod = atom()
@@ -125,6 +127,14 @@ 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>
+<p>
+Specifying a <c>#diameter_callback{}</c> record allows individual
+functions to be configured in place of the usual <seealso
+marker="diameter_app">diameter_app(3)</seealso> callbacks, with
+default implementations provided by module <c>diameter_callback</c>
+unless otherwise specified.
+See that module for details.</p>
+
<marker id="application_opt"/>
</item>
@@ -431,7 +441,7 @@ eval(F) ->
</code>
<p>
-Evaluating an evaluable() <c>E</c> on an argument list <c>A</c>
+Applying an evaluable() <c>E</c> to an argument list <c>A</c>
is meant in the sense of <c>eval([E|A])</c>.</p>
<p>
@@ -565,7 +575,7 @@ Pkt = #diameter_packet{}
</code>
<p>
-Reports that the RFC 3539 watchdog state machine has
+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
@@ -576,9 +586,9 @@ 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.
+as many <seealso marker="diameter_app#peer_up">peer_up/peer_down</seealso>
+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>
@@ -597,12 +607,96 @@ transport connection with a peer following <c>reconnect_timer</c> or
<c>watchdog_timer</c> expiry.</p>
</item>
+<tag><c>{closed, Ref, Reason, Config}</c></tag>
+<item>
+<code>
+Ref = transport_ref()
+Config = {connect|listen, [transport_opt()]}
+</code>
+
+<p>
+Capabilities exchange has failed. <c>Reason</c> can be one of
+the following.</p>
+
+<taglist>
+
+<tag><c>{'CER', Result, Caps, Pkt}</c></tag>
+<item>
+<code>
+Result = ResultCode | {capabilities_cb, CB, ResultCode|discard}
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+ResultCode = integer()
+CB = evaluable()
+</code>
+
+<p>
+An incoming CER has been answered with the indicated result code or
+discarded.
+The capabilities record contains pairs of values for the the local
+node and remote peer.
+The packet record contains the CER in question.
+In the case of rejection by a capabilities callback, the tuple
+indicates the rejecting callback.</p>
+</item>
+
+<tag><c>{'CER', Caps, {ResultCode, Pkt}}</c></tag>
+<item>
+<code>
+ResultCode = integer()
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+</code>
+
+<p>
+An incoming CER contained errors and has been answered with the
+indicated result code.
+The capabilities record contains only values for the the local
+node.
+The packet record contains the CER in question.</p>
+</item>
+
+<tag><c>{'CEA', Result, Caps, Pkt}</c></tag>
+<item>
+<code>
+Result = integer() | atom() | {capabilities_cb, CB, ResultCode|discard}
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+ResultCode = integer()
+</code>
+
+<p>
+An incoming CEA has been rejected for the indicated reason.
+An integer-valued <c>Result</c> indicates the result code sent
+by the peer.
+The capabilities record contains pairs of values for the the local
+node and remote peer.
+The packet record contains the CEA in question.
+In the case of rejection by a capabilities callback, the tuple
+indicates the rejecting callback.</p>
+</item>
+
+<tag><c>{'CEA', Caps, Pkt}</c></tag>
+<item>
+<code>
+Caps = #diameter_caps{}
+Pkt = #diameter_packet{}
+</code>
+
+<p>
+An incoming CER contained errors and has been rejected.
+The capabilities record contains only values for the the local node.
+The packet record contains the CEA in question.</p>
+</item>
+
+</taglist>
+</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>
+info fields of forms other than the above.</p>
<marker id="service_name"/>
</item>
@@ -706,6 +800,31 @@ not over SCTP as implemented by
<seealso marker="diameter_sctp">diameter_sctp(3)</seealso>.</p>
</item>
+<tag><c>{capabilities_cb, evaluable()}</c></tag>
+<item>
+<p>
+A callback invoked upon reception of CER/CEA during capabilities
+exchange in order to ask whether or not the connection should
+be accepted.
+Applied to the transport reference (as returned by <seealso
+marker="#add_transport">add_transport/2</seealso>) and
+<c>diameter_caps</c> record of the connection.
+Returning <c>ok</c> accepts the connection.
+Returning <c>integer()</c> causes an incoming
+CER to be answered with the specified Result-Code.
+Returning <c>discard</c> causes an incoming CER to
+be discarded.
+Returning <c>unknown</c> is equivalent to returning <c>3010</c>,
+DIAMETER_UNKNOWN_PEER.
+Returning anything but <c>ok</c> or a 2xxx series result
+code causes the transport connection to be broken.</p>
+
+<p>
+Multiple <c>capabilities_cb</c> options can be specified, in which
+case the corresponding callbacks are applied until either all return
+<c>ok</c> or one does not.</p>
+</item>
+
<tag><c>{watchdog_timer, TwInit}</c></tag>
<item>
<code>
diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml
index 72bac30709..60e08d41da 100644
--- a/lib/diameter/doc/src/diameter_compile.xml
+++ b/lib/diameter/doc/src/diameter_compile.xml
@@ -64,9 +64,10 @@ Defaults to the current working directory.</p>
<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>
+Use to point at beam files corresponding to dictionaries
+inherited by the one being compiled using <c>@inherits</c> or
+<c>--inherits</c>.
+Inheritance is a beam dependency, not an erl/hrl dependency.</p>
<p>
Multiple <c>-i</c> options can be specified.</p>
@@ -84,6 +85,31 @@ Supresses erl generation.</p>
Supresses hrl generation.</p>
</item>
+<tag><![CDATA[--name <name>]]></tag>
+<item>
+<p>
+Set <c>@name</c> in the dictionary file.
+Overrides any setting in the file itself.</p>
+</item>
+
+<tag><![CDATA[--prefix <prefix>]]></tag>
+<item>
+<p>
+Set <c>@prefix</c> in the dictionary file.
+Overrides any setting in the file itself.</p>
+</item>
+
+<tag><![CDATA[--inherits <dict>]]></tag>
+<item>
+<p>
+Append an <c>@inherits</c> to the dictionary file.
+Specifying <c>'-'</c> as the dictionary has the effect of clearing
+any previous inherits, effectively ignoring previous inherits.</p>
+
+<p>
+Multiple <c>--inherits</c> options can be specified.</p>
+</item>
+
</taglist>
</item>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
index e7c530f1b8..cc638dbc18 100644
--- a/lib/diameter/doc/src/diameter_dict.xml
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -36,7 +36,7 @@ under the License.
<!-- ===================================================================== -->
<file>diameter_dict</file>
-<filesummary>Dictionary inteface of the diameter application.</filesummary>
+<filesummary>Dictionary interface of the diameter application.</filesummary>
<description>
<p>
@@ -44,9 +44,9 @@ 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.
+to encode and decode its messages and AVPs.
The dictionary module is in turn generated from a file that defines
-these messages and AVP's.
+these messages and AVPs.
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
@@ -56,7 +56,7 @@ 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
+for the messages and grouped AVPs 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>.)
@@ -74,14 +74,14 @@ corresponding to applications defined in section 2.4 of RFC 3588:
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
+<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
+encode/decode since the messages and AVPs it handles are not specifically
defined.</p>
<marker id="FILE_FORMAT"/>
@@ -94,18 +94,16 @@ defined.</p>
<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.
+Each section starts with a tag followed by zero or more arguments
+and 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>
+Whitespace separates individual tokens but is otherwise 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.
+Each section can occur multiple times unless otherwise specified.
The order in which sections are specified is unimportant.</p>
<taglist>
@@ -115,7 +113,8 @@ The order in which sections are specified is unimportant.</p>
<p>
Defines the integer Number as the Diameter Application Id of the
application in question.
-Required if the dictionary defines <c>@messages</c>.
+Can occur at most once and is required if the dictionary defines
+<c>@messages</c>.
The section has empty content.</p>
<p>
@@ -136,16 +135,13 @@ Example:</p>
<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>
+Can occur at most once and defaults to the name of the dictionary file
+minus any extension if unspecified.
+The section has empty content.</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>
+Note that a dictionary module should have a unique name so as not collide
+with existing modules in the system.</p>
<p>
Example:</p>
@@ -159,22 +155,22 @@ Example:</p>
<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>
+Defines Name as the prefix to be added to record and constant names
+(followed by a <c>'_'</c> character) in the generated dictionary
+module and hrl.
+Can occur at most once.
+The section has empty content.</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>
+A prefix is optional but can be be used to disambiguate between record
+and constant names resulting from similarly named messages and AVPs in
+different Diameter applications.</p>
<p>
Example:</p>
<code>
-@prefix etsi_e2_
+@prefix etsi_e2
</code>
</item>
@@ -182,10 +178,12 @@ Example:</p>
<tag><c>@vendor Number Name</c></tag>
<item>
<p>
-Defines the integer Number as the the default Vendor-ID of AVP's for
+Defines the integer Number as the the default Vendor-Id of AVPs for
which the V flag is set.
Name documents the owner of the application
but is otherwise unused.
+Can occur at most once and is required if an AVP sets the V flag and
+is not otherwise assigned a Vendor-Id.
The section has empty content.</p>
<p>
@@ -200,10 +198,9 @@ Example:</p>
<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
+Defines the integer Number as the Vendor-Id of the AVPs 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>
+The section content consists of AVP names.</p>
<p>
Example:</p>
@@ -221,13 +218,27 @@ Region-Set
<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>
+Defines the name of a dictionary module containing AVP
+definitions that should be imported into the current dictionary.
+The section content consists of the names of those AVPs whose
+definitions should be imported from the dictionary, an empty list
+causing all to be imported.
+Any listed AVPs must not be defined in the current dictionary and
+it is an error to inherit the same AVP from more than one
+dictionary.</p>
<p>
-Can occur 0 or more times (with different values of Mod) but all
-dictionaries should typically inherit RFC3588 AVPs from
+Note that an inherited AVP that sets the V flag takes its Vendor-Id
+from either <c>@avp_vendor_id</c> in the inheriting dictionary or
+<c>@vendor</c> in the inherited dictionary.
+In particular, <c>@avp_vendor_id</c> in the inherited dictionary is
+ignored.
+Inheriting from a dictionary that specifies the required <c>@vendor</c>
+is equivalent to using <c>@avp_vendor_id</c> with a copy of the
+dictionary's definitions but the former makes for easier reuse.</p>
+
+<p>
+All dictionaries should typically inherit RFC3588 AVPs from
<c>diameter_gen_base_rfc3588</c>.</p>
<p>
@@ -248,13 +259,11 @@ 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>
+where Code is the integer AVP code, Type identifies an AVP Data Format
+as defined in <seealso marker="#DATA_TYPES">DATA TYPES</seealso> below,
+and Flags is a string of V, M and P characters indicating the flags to be
+set on an outgoing AVP or a single <c>'-'</c> (minus) character if
+none are to be set.</p>
<p>
Example:</p>
@@ -262,8 +271,8 @@ Example:</p>
<code>
@avp_types
-Location-Information 350 Grouped VM
-Requested-Information 353 Enumerated V
+Location-Information 350 Grouped MV
+Requested-Information 353 Enumerated V
</code>
<p>
@@ -276,21 +285,36 @@ to 0 as mandated by the current draft standard.</p>
<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>
+Specifies AVPs for which module Mod provides encode/decode functions.
+The section contents consists of AVP names.
+For each such name, <c>Mod:Name(encode|decode, Type, Data)</c> is
+expected to provide encode/decode for values of the AVP, where Name is
+the name of the AVP, Type is it's type as declared in the
+<c>@avp_types</c> section of the dictionary and Data is the value to
+encode/decode.</p>
+
+<p>
+Example:</p>
+
+<code>
+@custom_types rfc4005_avps
+
+Framed-IP-Address
+</code>
+</item>
+<tag><c>@codecs Mod</c></tag>
+<item>
<p>
-Can occur 0 or more times (with different values of Mod).</p>
+Like <c>@custom_types</c> but requires the specified module to export
+<c>Mod:Type(encode|decode, Name, Data)</c> rather than
+<c>Mod:Name(encode|decode, Type, Data)</c>.</p>
<p>
Example:</p>
<code>
-@custom_types rfc4005_types
+@codecs rfc4005_avps
Framed-IP-Address
</code>
@@ -360,6 +384,10 @@ SIP-Deregistration-Reason ::= &lt; AVP Header: 383 >
[ SIP-Reason-Info ]
* [ AVP ]
</code>
+
+<p>
+Specifying a Vendor-Id in the definition of a grouped AVP is
+equivalent to specifying it with <c>@avp_vendor_id</c>.</p>
</item>
<tag><c>@enum Name</c></tag>
@@ -371,11 +399,9 @@ 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>
+Note that the AVP in question can be defined in an inherited
+dictionary in order to introduce additional values to an enumeration
+otherwise defined in another dictionary.</p>
<p>
Example:</p>
@@ -390,11 +416,18 @@ REMOVE_SIP_SERVER 3
</code>
</item>
+<tag><c>@end</c></tag>
+<item>
+<p>
+Causes parsing of the dictionary to terminate:
+any remaining content is ignored.</p>
+</item>
+
</taglist>
<p>
Comments can be included in a dictionary file using semicolon:
-text from a semicolon to end of line is ignored.</p>
+characters from a semicolon to end of line are ignored.</p>
<marker id="MESSAGE_RECORDS"/>
</section>
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index e2723f3e99..6e364a3200 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -36,6 +36,120 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>Diameter 1.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix faulty cleanup after diameter:remove_transport/2.</p>
+ <p>
+ Removing a transport removed the configuration but did
+ not prevent the transport process from being restarted.</p>
+ <p>
+ Own Id: OTP-9756</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add support for TLS over TCP.</p>
+ <p>
+ RFC 3588 requires that a Diameter server support TLS. In
+ practice 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.</p>
+ <p>
+ TLS handshaking can take place either following a CER/CEA
+ that negotiates TLS using the Inband-Security-Id AVP (the
+ method documented in RFC 3588) or immediately following
+ connection establishment (the method added to the current
+ draft).</p>
+ <p>
+ Own Id: OTP-9605</p>
+ </item>
+ <item>
+ <p>
+ Improvements to the dictionary parser.</p>
+ <p>
+ The dictionary parser now emits useful error messages in
+ case of faults in the input file, also identifying the
+ line number at which the fault was detected. There are
+ semantic checks that were missing in the previous parser,
+ a fault in the interpretation of vendor id's in
+ combination with @inherits has been fixed and @end can be
+ used to terminate parsing explicitly instead of always
+ parsing to end of file.</p>
+ <p>
+ Own Id: OTP-9639</p>
+ </item>
+ <item>
+ <p>
+ Improve dictionary reusability.</p>
+ <p>
+ Reusing a dictionary just to get a different generated
+ module name or prefix previously required taking a copy
+ of the source, which may consist of several files if
+ inheritance is used, just to edit a couple of lines which
+ don't affect the semantics of the Diameter application
+ being defined. Options --name, --prefix and --inherits
+ have been added to diameterc to allow corresponding
+ values to be set at compile time.</p>
+ <p>
+ Own Id: OTP-9641</p>
+ </item>
+ <item>
+ <p>
+ Add capabilities_cb transport option.</p>
+ <p>
+ Its value is a function that's applied to the transport
+ reference and capabilities record after capabilities
+ exchange. If a callback returns anything but 'ok' then
+ the connection is closed. In the case of an incoming CER,
+ the callback can return a result code with which to
+ answer. Multiple callbacks can be specified and are
+ applied until either all return 'ok' or one doesn't.</p>
+ <p>
+ This provides a way to reject a peer connection.</p>
+ <p>
+ Own Id: OTP-9654</p>
+ </item>
+ <item>
+ <p>
+ Add @codecs to dictionary format.</p>
+ <p>
+ The semantics are similar to @custom_types but results in
+ codec functions of the form TypeName(encode|decode,
+ AvpName, Data) rather than AvpName(encode|decode,
+ TypeName, Data). That is, the role of the AVP name and
+ Diameter type name are reversed. This eliminates the need
+ for exporting one function for each AVP sharing a common
+ specialized encode/decode.</p>
+ <p>
+ Own Id: OTP-9708 Aux Id: OTP-9639 </p>
+ </item>
+ <item>
+ <p>
+ Add #diameter_callback{} for more flexible callback
+ configuration.</p>
+ <p>
+ The record allows individual functions to be configured
+ for each of the diameter_app(3) callbacks, as well as a
+ default callback.</p>
+ <p>
+ Own Id: OTP-9777</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Diameter 0.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/examples/GNUmakefile b/lib/diameter/examples/GNUmakefile
deleted file mode 100644
index 4c3f87939b..0000000000
--- a/lib/diameter/examples/GNUmakefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# %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
deleted file mode 100644
index 36a77dd524..0000000000
--- a/lib/diameter/examples/client.erl
+++ /dev/null
@@ -1,125 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 524a8f94a1..0000000000
--- a/lib/diameter/examples/client_cb.erl
+++ /dev/null
@@ -1,103 +0,0 @@
-%%
-%% %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/code/GNUmakefile b/lib/diameter/examples/code/GNUmakefile
new file mode 100644
index 0000000000..98e36a99e3
--- /dev/null
+++ b/lib/diameter/examples/code/GNUmakefile
@@ -0,0 +1,35 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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/code/client.erl b/lib/diameter/examples/code/client.erl
new file mode 100644
index 0000000000..bfe71b0e56
--- /dev/null
+++ b/lib/diameter/examples/code/client.erl
@@ -0,0 +1,125 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/client_cb.erl b/lib/diameter/examples/code/client_cb.erl
new file mode 100644
index 0000000000..ee3dcb2fec
--- /dev/null
+++ b/lib/diameter/examples/code/client_cb.erl
@@ -0,0 +1,103 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/peer.erl b/lib/diameter/examples/code/peer.erl
new file mode 100644
index 0000000000..b07cd32b98
--- /dev/null
+++ b/lib/diameter/examples/code/peer.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/redirect.erl b/lib/diameter/examples/code/redirect.erl
new file mode 100644
index 0000000000..d4d94ab23a
--- /dev/null
+++ b/lib/diameter/examples/code/redirect.erl
@@ -0,0 +1,70 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/redirect_cb.erl b/lib/diameter/examples/code/redirect_cb.erl
new file mode 100644
index 0000000000..da31add70d
--- /dev/null
+++ b/lib/diameter/examples/code/redirect_cb.erl
@@ -0,0 +1,63 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/code/relay.erl b/lib/diameter/examples/code/relay.erl
new file mode 100644
index 0000000000..d3438f83f3
--- /dev/null
+++ b/lib/diameter/examples/code/relay.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/relay_cb.erl b/lib/diameter/examples/code/relay_cb.erl
new file mode 100644
index 0000000000..9f9cd8d5ae
--- /dev/null
+++ b/lib/diameter/examples/code/relay_cb.erl
@@ -0,0 +1,69 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/sctp.erl b/lib/diameter/examples/code/sctp.erl
new file mode 100644
index 0000000000..08de023571
--- /dev/null
+++ b/lib/diameter/examples/code/sctp.erl
@@ -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%
+%%
+
+-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/code/server.erl b/lib/diameter/examples/code/server.erl
new file mode 100644
index 0000000000..3959461cec
--- /dev/null
+++ b/lib/diameter/examples/code/server.erl
@@ -0,0 +1,88 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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/code/server_cb.erl b/lib/diameter/examples/code/server_cb.erl
new file mode 100644
index 0000000000..0f6eb32ed6
--- /dev/null
+++ b/lib/diameter/examples/code/server_cb.erl
@@ -0,0 +1,115 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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/include/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}, _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/examples/dict/rfc4004_mip.dia b/lib/diameter/examples/dict/rfc4004_mip.dia
new file mode 100644
index 0000000000..575ad4394a
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4004_mip.dia
@@ -0,0 +1,280 @@
+;;
+;; %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%
+;;
+
+;;
+;; RFC 4004, Diameter Mobile IPv4 Application
+;;
+;; Edits:
+;;
+;; - MIP-nonce -> MIP-Nonce
+;; - Session-ID -> Session-Id
+;; - Omit MIP-HA-to-MN-SPI, MIP-MN-FA-SPI and MIP-MN-HA-SPI, none of
+;; which are defined.
+;;
+
+@id 2
+
+@inherits rfc3588_base
+
+;; ===========================================================================
+
+@avp_types
+
+ MIP-Reg-Request 320 OctetString M
+ MIP-Reg-Reply 321 OctetString M
+ MIP-MN-AAA-Auth 322 Grouped M
+ MIP-Mobile-Node-Address 333 Address M
+ MIP-Home-Agent-Address 334 Address M
+ MIP-Candidate-Home-Agent-Host 336 DiamIdent M
+ MIP-Feature-Vector 337 Unsigned32 M
+ MIP-Auth-Input-Data-Length 338 Unsigned32 M
+ MIP-Authenticator-Length 339 Unsigned32 M
+ MIP-Authenticator-Offset 340 Unsigned32 M
+ MIP-MN-AAA-SPI 341 Unsigned32 M
+ MIP-Filter-Rule 342 IPFilterRule M
+ MIP-FA-Challenge 344 OctetString M
+ MIP-Originating-Foreign-AAA 347 Grouped M
+ MIP-Home-Agent-Host 348 Grouped M
+
+ MIP-FA-to-HA-SPI 318 Unsigned32 M
+ MIP-FA-to-MN-SPI 319 Unsigned32 M
+ MIP-HA-to-FA-SPI 323 Unsigned32 M
+ MIP-MN-to-FA-MSA 325 Grouped M
+ MIP-FA-to-MN-MSA 326 Grouped M
+ MIP-FA-to-HA-MSA 328 Grouped M
+ MIP-HA-to-FA-MSA 329 Grouped M
+ MIP-MN-to-HA-MSA 331 Grouped M
+ MIP-HA-to-MN-MSA 332 Grouped M
+ MIP-Nonce 335 OctetString M
+ MIP-Session-Key 343 OctetString M
+ MIP-Algorithm-Type 345 Enumerated M
+ MIP-Replay-Mode 346 Enumerated M
+ MIP-MSA-Lifetime 367 Unsigned32 M
+
+;; ===========================================================================
+
+@messages
+
+ ;; 5.1. AA-Mobile-Node-Request
+
+ AMR ::= < Diameter Header: 260, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { User-Name }
+ { Destination-Realm }
+ { Origin-Host }
+ { Origin-Realm }
+ { MIP-Reg-Request }
+ { MIP-MN-AAA-Auth }
+ [ Acct-Multi-Session-Id ]
+ [ Destination-Host ]
+ [ Origin-State-Id ]
+ [ MIP-Mobile-Node-Address ]
+ [ MIP-Home-Agent-Address ]
+ [ MIP-Feature-Vector ]
+ [ MIP-Originating-Foreign-AAA ]
+ [ Authorization-Lifetime ]
+ [ Auth-Session-State ]
+ [ MIP-FA-Challenge ]
+ [ MIP-Candidate-Home-Agent-Host ]
+ [ MIP-Home-Agent-Host ]
+ [ MIP-HA-to-FA-SPI ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 5.2. AA-Mobile-Node-Answer
+
+ AMA ::= < Diameter Header: 260, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Acct-Multi-Session-Id ]
+ [ User-Name ]
+ [ Authorization-Lifetime ]
+ [ Auth-Session-State ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Re-Auth-Request-Type ]
+ [ MIP-Feature-Vector ]
+ [ MIP-Reg-Reply ]
+ [ MIP-MN-to-FA-MSA ]
+ [ MIP-MN-to-HA-MSA ]
+ [ MIP-FA-to-MN-MSA ]
+ [ MIP-FA-to-HA-MSA ]
+ [ MIP-HA-to-MN-MSA ]
+ [ MIP-MSA-Lifetime ]
+ [ MIP-Home-Agent-Address ]
+ [ MIP-Mobile-Node-Address ]
+ * [ MIP-Filter-Rule ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ;; 5.3. Home-Agent-MIP-Request
+
+ HAR ::= < Diameter Header: 262, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Authorization-Lifetime }
+ { Auth-Session-State }
+ { MIP-Reg-Request }
+ { Origin-Host }
+ { Origin-Realm }
+ { User-Name }
+ { Destination-Realm }
+ { MIP-Feature-Vector }
+ [ Destination-Host ]
+ [ MIP-MN-to-HA-MSA ]
+ [ MIP-MN-to-FA-MSA ]
+ [ MIP-HA-to-MN-MSA ]
+ [ MIP-HA-to-FA-MSA ]
+ [ MIP-MSA-Lifetime ]
+ [ MIP-Originating-Foreign-AAA ]
+ [ MIP-Mobile-Node-Address ]
+ [ MIP-Home-Agent-Address ]
+ * [ MIP-Filter-Rule ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 5.4. Home-Agent-MIP-Answer
+
+ HAA ::= < Diameter Header: 262, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Acct-Multi-Session-Id ]
+ [ User-Name ]
+ [ Error-Reporting-Host ]
+ [ Error-Message ]
+ [ MIP-Reg-Reply ]
+ [ MIP-Home-Agent-Address ]
+ [ MIP-Mobile-Node-Address ]
+ [ MIP-FA-to-HA-SPI ]
+ [ MIP-FA-to-MN-SPI ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+;; ===========================================================================
+
+@grouped
+
+ MIP-MN-AAA-Auth ::= < AVP Header: 322 >
+
+ { MIP-MN-AAA-SPI }
+ { MIP-Auth-Input-Data-Length }
+ { MIP-Authenticator-Length }
+ { MIP-Authenticator-Offset }
+ * [ AVP ]
+
+
+ MIP-Originating-Foreign-AAA ::= < AVP Header: 347 >
+
+ { Origin-Realm }
+ { Origin-Host }
+ * [ AVP ]
+
+ MIP-Home-Agent-Host ::= < AVP Header: 348 >
+
+ { Destination-Realm }
+ { Destination-Host }
+ * [ AVP ]
+
+ MIP-FA-to-MN-MSA ::= < AVP Header: 326 >
+
+ { MIP-FA-to-MN-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-FA-to-HA-MSA ::= < AVP Header: 328 >
+
+ { MIP-FA-to-HA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-HA-to-FA-MSA ::= < AVP Header: 329 >
+
+ { MIP-HA-to-FA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-HA-to-MN-MSA ::= < AVP Header: 332 >
+
+ ; { MIP-HA-to-MN-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Replay-Mode }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-MN-to-FA-MSA ::= < AVP Header: 325 >
+
+ ; { MIP-MN-FA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Nonce }
+ * [ AVP ]
+
+ MIP-MN-to-HA-MSA ::= < AVP Header: 331 >
+
+ ; { MIP-MN-HA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Replay-Mode }
+ { MIP-Nonce }
+ * [ AVP ]
+
+;; ===========================================================================
+
+@enum MIP-Algorithm-Type
+
+ HMAC-SHA-1 2
+
+@enum MIP-Replay-Mode
+
+ NONE 1
+ TIMESTAMPS 2
+ NONCES 3
+
+;; ===========================================================================
+
+@define Result-Code
+
+ ;; 6.1. Transient Failures
+
+ MIP_REPLY_FAILURE 4005
+ HA_NOT_AVAILABLE 4006
+ BAD_KEY 4007
+ MIP_FILTER_NOT_SUPPORTED 4008
+
+ ;; 6.2. Permanent Failures
+
+ NO_FOREIGN_HA_SERVICE 5024
+ END_TO_END_MIP_KEY_ENCRYPTION 5025
diff --git a/lib/diameter/examples/dict/rfc4005_nas.dia b/lib/diameter/examples/dict/rfc4005_nas.dia
new file mode 100644
index 0000000000..a4b44e38bb
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4005_nas.dia
@@ -0,0 +1,740 @@
+;;
+;; %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%
+;;
+
+;;
+;; RFC 4005, Diameter Network Access Server Application
+;;
+;; Edits:
+;;
+;; - Acounting-Auth-Method -> Accounting-Auth-Method
+;; - Connection-Info -> ConnectInfo
+;; - Framed-Appletalk-Link -> Framed-AppleTalk-Link
+;; - Framed-Appletalk-Network -> Framed-AppleTalk-Network
+;; - Framed-Appletalk-Zone -> Framed-AppleTalk-Zone
+;; - Qos-Filter-Rule -> QoS-Filter-Rule
+;; - Redirect-Host-Usase -> Redirect-Host-Usage
+;; - Redirected-Host -> Redirect-Host
+;; - Redirected-Host-Usage -> Redirect-Host-Usage
+;; - Redirected-Host-Cache-Time -> Redirect-Max-Cache-Time
+;; - Redirected-Max-Cache-Time -> Redirect-Max-Cache-Time
+;;
+
+@id 1
+
+@inherits rfc3588_base
+
+;; ===========================================================================
+
+@avp_types
+
+ ;; 4. NAS Session AVPs
+
+ NAS-Port 5 Unsigned32 M
+ NAS-Port-Id 87 UTF8String M
+ NAS-Port-Type 61 Enumerated M
+ Called-Station-Id 30 UTF8String M
+ Calling-Station-Id 31 UTF8String M
+ Connect-Info 77 UTF8String M
+ Originating-Line-Info 94 OctetString -
+ Reply-Message 18 UTF8String M
+
+ ;; 5. NAS Authentication AVPs
+
+ User-Password 2 OctetString M
+ Password-Retry 75 Unsigned32 M
+ Prompt 76 Enumerated M
+ CHAP-Auth 402 Grouped M
+ CHAP-Algorithm 403 Enumerated M
+ CHAP-Ident 404 OctetString M
+ CHAP-Response 405 OctetString M
+ CHAP-Challenge 60 OctetString M
+ ARAP-Password 70 OctetString M
+ ARAP-Challenge-Response 84 OctetString M
+ ARAP-Security 73 Unsigned32 M
+ ARAP-Security-Data 74 OctetString M
+
+ ;; 6. NAS Authorization AVPs
+
+ Service-Type 6 Enumerated M
+ Callback-Number 19 UTF8String M
+ Callback-Id 20 UTF8String M
+ Idle-Timeout 28 Unsigned32 M
+ Port-Limit 62 Unsigned32 M
+ NAS-Filter-Rule 400 IPFilterRule M
+ Filter-Id 11 UTF8String M
+ Configuration-Token 78 OctetString M
+ QoS-Filter-Rule 407 QoSFilterRule -
+ Framed-Protocol 7 Enumerated M
+ Framed-Routing 10 Enumerated M
+ Framed-MTU 12 Unsigned32 M
+ Framed-Compression 13 Enumerated M
+ Framed-IP-Address 8 OctetString M
+ Framed-IP-Netmask 9 OctetString M
+ Framed-Route 22 UTF8String M
+ Framed-Pool 88 OctetString M
+ Framed-Interface-Id 96 Unsigned64 M
+ Framed-IPv6-Prefix 97 OctetString M
+ Framed-IPv6-Route 99 UTF8String M
+ Framed-IPv6-Pool 100 OctetString M
+ Framed-IPX-Network 23 UTF8String M
+ Framed-AppleTalk-Link 37 Unsigned32 M
+ Framed-AppleTalk-Network 38 Unsigned32 M
+ Framed-AppleTalk-Zone 39 OctetString M
+ ARAP-Features 71 OctetString M
+ ARAP-Zone-Access 72 Enumerated M
+ Login-IP-Host 14 OctetString M
+ Login-IPv6-Host 98 OctetString M
+ Login-Service 15 Enumerated M
+ Login-TCP-Port 16 Unsigned32 M
+ Login-LAT-Service 34 OctetString M
+ Login-LAT-Node 35 OctetString M
+ Login-LAT-Group 36 OctetString M
+ Login-LAT-Port 63 OctetString M
+
+ ;; 7. NAS Tunneling
+
+ Tunneling 401 Grouped M
+ Tunnel-Type 64 Enumerated M
+ Tunnel-Medium-Type 65 Enumerated M
+ Tunnel-Client-Endpoint 66 UTF8String M
+ Tunnel-Server-Endpoint 67 UTF8String M
+ Tunnel-Password 69 OctetString M
+ Tunnel-Private-Group-Id 81 OctetString M
+ Tunnel-Assignment-Id 82 OctetString M
+ Tunnel-Preference 83 Unsigned32 M
+ Tunnel-Client-Auth-Id 90 UTF8String M
+ Tunnel-Server-Auth-Id 91 UTF8String M
+
+ ;; 8. NAS Accounting
+
+ Accounting-Input-Octets 363 Unsigned64 M
+ Accounting-Output-Octets 364 Unsigned64 M
+ Accounting-Input-Packets 365 Unsigned64 M
+ Accounting-Output-Packets 366 Unsigned64 M
+ Acct-Session-Time 46 Unsigned32 M
+ Acct-Authentic 45 Enumerated M
+ Accounting-Auth-Method 406 Enumerated M
+ Acct-Delay-Time 41 Unsigned32 M
+ Acct-Link-Count 51 Unsigned32 M
+ Acct-Tunnel-Connection 68 OctetString M
+ Acct-Tunnel-Packets-Lost 86 Unsigned32 M
+
+ ;; 9.3. AVPs Used Only for Compatibility
+
+ NAS-Identifier 32 UTF8String M
+ NAS-IP-Address 4 OctetString M
+ NAS-IPv6-Address 95 OctetString M
+ State 24 OctetString M
+ ;;Termination-Cause 295 Enumerated M
+ Origin-AAA-Protocol 408 Enumerated M
+
+;; ===========================================================================
+
+@messages
+
+ AAR ::= < 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 ]
+ * [ 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 ]
+
+ AAA ::= < 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 ]
+ [ 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 ]
+ [ Login-TCP-Port ]
+ * [ NAS-Filter-Rule ]
+ * [ QoS-Filter-Rule ]
+ * [ Tunneling ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ 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-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 ]
+
+ RAA ::= < 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 ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-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 ]
+
+ 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-AAA-Protocol ]
+ [ 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-AAA-Protocol ]
+ [ 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-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 ]
+
+ ASA ::= < 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 ]
+ * [ 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 ]
+ [ 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 ]
+ * [ Connect-Info ]
+ [ Originating-Line-Info ]
+ [ Authorization-Lifetime ]
+ [ Session-Timeout ]
+ [ Idle-Timeout ]
+ [ 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 ]
+
+ 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 ]
+ [ 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 ]
+
+;; ===========================================================================
+
+@grouped
+
+ CHAP-Auth ::= < AVP Header: 402 >
+
+ { CHAP-Algorithm }
+ { CHAP-Ident }
+ [ CHAP-Response ]
+ * [ AVP ]
+
+ 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 ]
+
+;; ===========================================================================
+
+@enum NAS-Port-Type
+
+ ASYNC 0
+ SYNC 1
+ ISDN_SYNC 2
+ ISDN_ASYNC_V120 3
+ ISDN_ASYNC_V110 4
+ VIRTUAL 5
+ PIAFS 6
+ HDLC_CLEAR_CHANNEL 7
+ X25 8
+ X75 9
+ G3FAX 10
+ SDSL 11
+ ADSL-CAP 12
+ ADSL-DMT 13
+ IDSL 14
+ ETHERNET 15
+ XDSL 16
+ CABLE 17
+ WIRELESS_OTHER 18
+ 'WIRELESS_802.11' 19
+ TOKEN-RING 20
+ FDDI 21
+ WIRELESS_CDMA2000 22
+ WIRELESS_UMTS 23
+ WIRELESS_1X-EV 24
+ IAPP 25
+
+@enum Prompt
+
+ NO_ECHO 0
+ ECHO 1
+
+@enum CHAP-Algorithm
+
+ WITH_MD5 5
+
+@enum Service-Type
+
+ LOGIN 1
+ FRAMED 2
+ CALLBACK_LOGIN 3
+ CALLBACK_FRAMED 4
+ OUTBOUND 5
+ ADMINISTRATIVE 6
+ NAS_PROMPT 7
+ AUTHENTICATE_ONLY 8
+ CALLBACK_NAS_PROMPT 9
+ CALL_CHECK 10
+ CALLBACK_ADMINISTRATIVE 11
+ VOICE 12
+ FAX 13
+ MODEM_RELAY 14
+ IAPP-REGISTER 15
+ IAPP-AP-CHECK 16
+ AUTHORIZE_ONLY 17
+
+@enum Framed-Protocol
+
+ PPP 1
+ SLIP 2
+ ARAP 3
+ GANDALF 4
+ XYLOGICS 5
+ X75 6
+
+@enum Framed-Routing
+
+ NONE 0
+ SEND 1
+ LISTEN 2
+ SEND_AND_LISTEN 3
+
+@enum Framed-Compression
+
+ NONE 0
+ VJ 1
+ IPX 2
+ STAC-LZS 3
+
+@enum ARAP-Zone-Access
+
+ DEFAULT 1
+ FILTER_INCLUSIVELY 2
+ FILTER_EXCLUSIVELY 4
+
+@enum Login-Service
+
+ TELNET 0
+ RLOGIN 1
+ TCP_CLEAR 2
+ PORTMASTER 3
+ LAT 4
+ X25-PAD 5
+ X25-T3POS 6
+ TCP_CLEAR_QUIET 8
+
+@enum Tunnel-Type
+
+ PPTP 1
+ L2F 2
+ L2TP 3
+ ATMP 4
+ VTP 5
+ AH 6
+ IP-IP 7
+ MIN-IP-IP 8
+ ESP 9
+ GRE 10
+ DVS 11
+ IP-IN-IP 12
+ VLAN 13
+
+@enum Tunnel-Medium-Type
+
+ IPV4 1
+ IPV6 2
+ NSAP 3
+ HDLC 4
+ BBN_1822 5
+ '802' 6
+ E163 7
+ E164 8
+ F69 9
+ X121 10
+ IPX 11
+ APPLETALK 12
+ DECNET_IV 13
+ BANYAN_VINES 14
+ E164_NSAP 15
+
+
+@enum Acct-Authentic
+
+ RADIUS 1
+ LOCAL 2
+ REMOTE 3
+ DIAMETER 4
+
+@enum Accounting-Auth-Method
+
+ PAP 1
+ CHAP 2
+ MS-CHAP-1 3
+ MS-CHAP-2 4
+ EAP 5
+ NONE 7
+
+@enum Termination-Cause
+
+ USER_REQUEST 11
+ LOST_CARRIER 12
+ LOST_SERVICE 13
+ IDLE_TIMEOUT 14
+ SESSION_TIMEOUT 15
+ ADMIN_RESET 16
+ ADMIN_REBOOT 17
+ PORT_ERROR 18
+ NAS_ERROR 19
+ NAS_REQUEST 20
+ NAS_REBOOT 21
+ PORT_UNNEEDED 22
+ PORT_PREEMPTED 23
+ PORT_SUSPENDED 24
+ SERVICE_UNAVAILABLE 25
+ CALLBACK 26
+ USER_ERROR 27
+ HOST_REQUEST 28
+ SUPPLICANT_RESTART 29
+ REAUTHORIZATION_FAILURE 30
+ PORT_REINIT 31
+ PORT_DISABLED 32
diff --git a/lib/diameter/examples/dict/rfc4006_cc.dia b/lib/diameter/examples/dict/rfc4006_cc.dia
new file mode 100644
index 0000000000..b723e4ddbb
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4006_cc.dia
@@ -0,0 +1,349 @@
+;;
+;; %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%
+;;
+
+;;
+;; RFC 4006, Diameter Credit-Control Application
+;;
+
+@id 4
+
+@inherits rfc3588_base
+@inherits rfc4005_nas Filter-Id
+
+;; ===========================================================================
+
+@avp_types
+
+ CC-Correlation-Id 411 OctetString -
+ CC-Input-Octets 412 Unsigned64 M
+ CC-Money 413 Grouped M
+ CC-Output-Octets 414 Unsigned64 M
+ CC-Request-Number 415 Unsigned32 M
+ CC-Request-Type 416 Enumerated M
+ CC-Service-Specific-Units 417 Unsigned64 M
+ CC-Session-Failover 418 Enumerated M
+ CC-Sub-Session-Id 419 Unsigned64 M
+ CC-Time 420 Unsigned32 M
+ CC-Total-Octets 421 Unsigned64 M
+ CC-Unit-Type 454 Enumerated M
+ Check-Balance-Result 422 Enumerated M
+ Cost-Information 423 Grouped M
+ Cost-Unit 424 UTF8String M
+ Credit-Control 426 Enumerated M
+ Credit-Control-Failure-Handling 427 Enumerated M
+ Currency-Code 425 Unsigned32 M
+ Direct-Debiting-Failure-Handling 428 Enumerated M
+ Exponent 429 Integer32 M
+ Final-Unit-Action 449 Enumerated M
+ Final-Unit-Indication 430 Grouped M
+ Granted-Service-Unit 431 Grouped M
+ G-S-U-Pool-Identifier 453 Unsigned32 M
+ G-S-U-Pool-Reference 457 Grouped M
+ Multiple-Services-Credit-Control 456 Grouped M
+ Multiple-Services-Indicator 455 Enumerated M
+ Rating-Group 432 Unsigned32 M
+ Redirect-Address-Type 433 Enumerated M
+ Redirect-Server 434 Grouped M
+ Redirect-Server-Address 435 UTF8String M
+ Requested-Action 436 Enumerated M
+ Requested-Service-Unit 437 Grouped M
+ Restriction-Filter-Rule 438 IPFilterRule M
+ Service-Context-Id 461 UTF8String M
+ Service-Identifier 439 Unsigned32 M
+ Service-Parameter-Info 440 Grouped -
+ Service-Parameter-Type 441 Unsigned32 -
+ Service-Parameter-Value 442 OctetString -
+ Subscription-Id 443 Grouped M
+ Subscription-Id-Data 444 UTF8String M
+ Subscription-Id-Type 450 Enumerated M
+ Tariff-Change-Usage 452 Enumerated M
+ Tariff-Time-Change 451 Time M
+ Unit-Value 445 Grouped M
+ Used-Service-Unit 446 Grouped M
+ User-Equipment-Info 458 Grouped -
+ User-Equipment-Info-Type 459 Enumerated -
+ User-Equipment-Info-Value 460 OctetString -
+ Value-Digits 447 Integer64 M
+ Validity-Time 448 Unsigned32 M
+
+;; ===========================================================================
+
+@messages
+
+ CCR ::= < 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 ]
+
+ CCA ::= < 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 ]
+
+;; ===========================================================================
+
+@grouped
+
+ Cost-Information ::= < AVP Header: 423 >
+
+ { Unit-Value }
+ { Currency-Code }
+ [ Cost-Unit ]
+
+ Unit-Value ::= < AVP Header: 445 >
+
+ { Value-Digits }
+ [ Exponent ]
+
+ 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 ]
+
+ 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 ]
+
+ Requested-Service-Unit ::= < AVP Header: 437 >
+
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ * [ AVP ]
+
+ 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 ]
+
+ CC-Money ::= < AVP Header: 413 >
+
+ { Unit-Value }
+ [ Currency-Code ]
+
+ G-S-U-Pool-Reference ::= < AVP Header: 457 >
+
+ { G-S-U-Pool-Identifier }
+ { CC-Unit-Type }
+ { Unit-Value }
+
+ Final-Unit-Indication ::= < AVP Header: 430 >
+
+ { Final-Unit-Action }
+ * [ Restriction-Filter-Rule ]
+ * [ Filter-Id ]
+ [ Redirect-Server ]
+
+ Redirect-Server ::= < AVP Header: 434 >
+
+ { Redirect-Address-Type }
+ { Redirect-Server-Address }
+
+ Service-Parameter-Info ::= < AVP Header: 440 >
+
+ { Service-Parameter-Type }
+ { Service-Parameter-Value }
+
+ Subscription-Id ::= < AVP Header: 443 >
+
+ { Subscription-Id-Type }
+ { Subscription-Id-Data }
+
+ User-Equipment-Info ::= < AVP Header: 458 >
+
+ { User-Equipment-Info-Type }
+ { User-Equipment-Info-Value }
+
+;; ===========================================================================
+
+@enum CC-Request-Type
+
+ INITIAL_REQUEST 1
+ UPDATE_REQUEST 2
+ TERMINATION_REQUEST 3
+ EVENT_REQUEST 4
+
+@enum CC-Session-Failover
+
+ NOT_SUPPORTED 0
+ SUPPORTED 1
+
+@enum Check-Balance-Result
+
+ ENOUGH_CREDIT 0
+ NO_CREDIT 1
+
+@enum Credit-Control
+
+ AUTHORIZATION 0
+ RE_AUTHORIZATION 1
+
+@enum Credit-Control-Failure-Handling
+
+ TERMINATE 0
+ CONTINUE 1
+ RETRY_AND_TERMINATE 2
+
+@enum Direct-Debiting-Failure-Handling
+
+ TERMINATE_OR_BUFFER 0
+ CONTINUE 1
+
+@enum Tariff-Change-Usage
+
+ UNIT_BEFORE_TARIFF_CHANGE 0
+ UNIT_AFTER_TARIFF_CHANGE 1
+ UNIT_INDETERMINATE 2
+
+@enum CC-Unit-Type
+
+ TIME 0
+ MONEY 1
+ TOTAL-OCTETS 2
+ INPUT-OCTETS 3
+ OUTPUT-OCTETS 4
+ SERVICE-SPECIFIC-UNITS 5
+
+@enum Final-Unit-Action
+
+ TERMINATE 0
+ REDIRECT 1
+ RESTRICT_ACCESS 2
+
+@enum Redirect-Address-Type
+
+ IPV4 0
+ IPV6 1
+ URL 2
+ SIP_URI 3
+
+@enum Multiple-Services-Indicator
+
+ NOT_SUPPORTED 0
+ SUPPORTED 1
+
+@enum Requested-Action
+
+ DIRECT_DEBITING 0
+ REFUND_ACCOUNT 1
+ CHECK_BALANCE 2
+ PRICE_ENQUIRY 3
+
+@enum Subscription-Id-Type
+
+ END_USER_E164 0
+ END_USER_IMSI 1
+ END_USER_SIP_URI 2
+ END_USER_NAI 3
+ END_USER_PRIVATE 4
+
+@enum User-Equipment-Info-Type
+
+ IMEISV 0
+ MAC 1
+ EUI64 2
+ MODIFIED_EUI64 3
+
+;; ===========================================================================
+
+@define Result-Code
+
+ END_USER_SERVICE_DENIED 4010
+ CREDIT_CONTROL_NOT_APPLICABLE 4011
+ CREDIT_LIMIT_REACHED 4012
+
+ USER_UNKNOWN 5030
+ RATING_FAILED 5031
diff --git a/lib/diameter/examples/dict/rfc4072_eap.dia b/lib/diameter/examples/dict/rfc4072_eap.dia
new file mode 100644
index 0000000000..111516b347
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4072_eap.dia
@@ -0,0 +1,150 @@
+;;
+;; %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%
+;;
+
+;;
+;; RFC 4072, Diameter Extensible Authentication Protocol (EAP) Application
+;;
+;; Edits:
+;;
+;; - Move EAP-Payload to not break fixed/required/optional order
+;; - Framed-Appletalk-Link -> Framed-AppleTalk-Link
+;; - Framed-Appletalk-Network -> Framed-AppleTalk-Network
+;; - Framed-Appletalk-Zone -> Framed-AppleTalk-Zone
+;;
+
+@id 5
+
+@inherits rfc3588_base
+@inherits rfc4005_nas
+
+;; ===========================================================================
+
+@avp_types
+
+ EAP-Master-Session-Key 464 OctetString -
+ EAP-Key-Name 102 OctetString -
+ EAP-Payload 462 OctetString -
+ EAP-Reissued-Payload 463 OctetString -
+ Accounting-EAP-Auth-Method 465 Unsigned64 -
+
+;; ===========================================================================
+
+@messages
+
+ DER ::= < Diameter Header: 268, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Request-Type }
+ { EAP-Payload }
+ [ Destination-Host ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Origin-State-Id ]
+ [ Port-Limit ]
+ [ User-Name ]
+ [ 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 ]
+
+ DEA ::= < 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 ]
+ [ 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 ]
diff --git a/lib/diameter/examples/dict/rfc4590_digest.dia b/lib/diameter/examples/dict/rfc4590_digest.dia
new file mode 100644
index 0000000000..a4ebe0c456
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4590_digest.dia
@@ -0,0 +1,45 @@
+;;
+;; %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%
+;;
+
+;;
+;; RFC 4590, RADIUS Extension for Digest Authentication
+;;
+
+@avp_types
+
+ Digest-Response 103 OctetString -
+ Digest-Realm 104 OctetString -
+ Digest-Nonce 105 OctetString -
+ Digest-Response-Auth 106 OctetString -
+ Digest-Nextnonce 107 OctetString -
+ Digest-Method 108 OctetString -
+ Digest-URI 109 OctetString -
+ Digest-Qop 110 OctetString -
+ Digest-Algorithm 111 OctetString -
+ Digest-Entity-Body-Hash 112 OctetString -
+ Digest-CNonce 113 OctetString -
+ Digest-Nonce-Count 114 OctetString -
+ Digest-Username 115 OctetString -
+ Digest-Opaque 116 OctetString -
+ Digest-Auth-Param 117 OctetString -
+ Digest-AKA-Auts 118 OctetString -
+ Digest-Domain 119 OctetString -
+ Digest-Stale 120 OctetString -
+ Digest-HA1 121 OctetString -
+ SIP-AOR 122 OctetString -
diff --git a/lib/diameter/examples/dict/rfc4740_sip.dia b/lib/diameter/examples/dict/rfc4740_sip.dia
new file mode 100644
index 0000000000..8c21882649
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4740_sip.dia
@@ -0,0 +1,446 @@
+;;
+;; %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%
+;;
+
+;;
+;; RFC 4740, Diameter Session Initiation Protocol (SIP) Application
+;;
+
+@id 6
+
+@inherits rfc3588_base
+@inherits rfc4590_digest
+
+;; ===========================================================================
+
+@avp_types
+
+ SIP-Accounting-Information 368 Grouped M
+ SIP-Accounting-Server-URI 369 DiameterURI M
+ SIP-Credit-Control-Server-URI 370 DiameterURI M
+ SIP-Server-URI 371 UTF8String M
+ SIP-Server-Capabilities 372 Grouped M
+ SIP-Mandatory-Capability 373 Unsigned32 M
+ SIP-Optional-Capability 374 Unsigned32 M
+ SIP-Server-Assignment-Type 375 Enumerated M
+ SIP-Auth-Data-Item 376 Grouped M
+ SIP-Authentication-Scheme 377 Enumerated M
+ SIP-Item-Number 378 Unsigned32 M
+ SIP-Authenticate 379 Grouped M
+ SIP-Authorization 380 Grouped M
+ SIP-Authentication-Info 381 Grouped M
+ SIP-Number-Auth-Items 382 Unsigned32 M
+ SIP-Deregistration-Reason 383 Grouped M
+ SIP-Reason-Code 384 Enumerated M
+ SIP-Reason-Info 385 UTF8String M
+ SIP-Visited-Network-Id 386 UTF8String M
+ SIP-User-Authorization-Type 387 Enumerated M
+ SIP-Supported-User-Data-Type 388 UTF8String M
+ SIP-User-Data 389 Grouped M
+ SIP-User-Data-Type 390 UTF8String M
+ SIP-User-Data-Contents 391 OctetString M
+ SIP-User-Data-Already-Available 392 Enumerated M
+ SIP-Method 393 UTF8String M
+
+;; ===========================================================================
+
+@messages
+
+ ;; 8.1. User-Authorization-Request
+
+ 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 ::= < Diameter Header: 283, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+ [ 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 ::= < 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 ]
+
+ ;; 8.4. Server-Assignment-Answer
+
+ 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 ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.5. Location-Info-Request
+
+ 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 ::= < Diameter Header: 285, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { 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 ::= < 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 ::= < 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 ]
+
+ ;; 8.9. Registration-Termination-Request
+
+ 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 ::= < 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 ::= < 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 ::= < 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 ]
+
+;; ===========================================================================
+
+@grouped
+
+ SIP-Accounting-Information ::= < AVP Header: 368 >
+
+ * [ SIP-Accounting-Server-URI ]
+ * [ SIP-Credit-Control-Server-URI ]
+ * [ AVP]
+
+ SIP-Server-Capabilities ::= < AVP Header: 372 >
+
+ * [ SIP-Mandatory-Capability ]
+ * [ SIP-Optional-Capability ]
+ * [ SIP-Server-URI ]
+ * [ AVP ]
+
+ SIP-Auth-Data-Item ::= < AVP Header: 376 >
+
+ { SIP-Authentication-Scheme }
+ [ SIP-Item-Number ]
+ [ SIP-Authenticate ]
+ [ SIP-Authorization ]
+ [ SIP-Authentication-Info ]
+ * [ AVP ]
+
+ 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 ]
+
+ 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 ]
+
+ SIP-Authentication-Info ::= < AVP Header: 381 >
+
+ [ Digest-Nextnonce ]
+ [ Digest-Qop ]
+ [ Digest-Response-Auth ]
+ [ Digest-CNonce ]
+ [ Digest-Nonce-Count ]
+ * [ AVP ]
+
+ SIP-Deregistration-Reason ::= < AVP Header: 383 >
+
+ { SIP-Reason-Code }
+ [ SIP-Reason-Info ]
+ * [ AVP ]
+
+ SIP-User-Data ::= < AVP Header: 389 >
+
+ { SIP-User-Data-Type }
+ { SIP-User-Data-Contents }
+ * [ AVP ]
+
+;; ===========================================================================
+
+@enum SIP-Server-Assignment-Type
+
+ NO_ASSIGNMENT 0
+ REGISTRATION 1
+ RE_REGISTRATION 2
+ UNREGISTERED_USER 3
+ TIMEOUT_DEREGISTRATION 4
+ USER_DEREGISTRATION 5
+ TIMEOUT_DEREGISTRATION_STORE 6
+ USER_DEREGISTRATION_STORE 7
+ ADMINISTRATIVE_DEREGISTRATION 8
+ AUTHENTICATION_FAILURE 9
+ AUTHENTICATION_TIMEOUT 10
+ DEREGISTRATION_TOO_MUCH_DATA 11
+
+@enum SIP-Authentication-Scheme
+
+ DIGEST 0
+
+@enum SIP-Reason-Code
+
+ PERMANENT_TERMINATION 0
+ NEW_SIP_SERVER_ASSIGNED 1
+ SIP_SERVER_CHANGE 2
+ REMOVE_SIP_SERVER 3
+
+@enum SIP-User-Authorization-Type
+
+ REGISTRATION 0
+ DEREGISTRATION 1
+ REGISTRATION_AND_CAPABILITIES 2
+
+@enum SIP-User-Data-Already-Available
+
+ USER_DATA_NOT_AVAILABLE 0
+ USER_DATA_ALREADY_AVAILABLE 1
+
+;; ===========================================================================
+
+@define Result-Code
+
+ ;; Success
+
+ FIRST_REGISTRATION 2003
+ SUBSEQUENT_REGISTRATION 2004
+ UNREGISTERED_SERVICE 2005
+ SUCCESS_SERVER_NAME_NOT_STORED 2006
+ SERVER_SELECTION 2007
+ SUCCESS_AUTH_SENT_SERVER_NOT_STORED 2008
+
+ ;; Transient Failures
+
+ USER_NAME_REQUIRED 4013
+
+ ;; Permanent Failures
+
+ USER_UNKNOWN 5032
+ IDENTITIES_DONT_MATCH 5033
+ IDENTITY_NOT_REGISTERED 5034
+ ROAMING_NOT_ALLOWED 5035
+ IDENTITY_ALREADY_REGISTERED 5036
+ AUTH_SCHEME_NOT_SUPPORTED 5037
+ IN_ASSIGNMENT_TYPE 5038
+ TOO_MUCH_DATA 5039
+ NOT_SUPPORTED_USER_DATA 5040
diff --git a/lib/diameter/examples/peer.erl b/lib/diameter/examples/peer.erl
deleted file mode 100644
index 89203e15c3..0000000000
--- a/lib/diameter/examples/peer.erl
+++ /dev/null
@@ -1,139 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index b54701243f..0000000000
--- a/lib/diameter/examples/redirect.erl
+++ /dev/null
@@ -1,70 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index ea7ad38749..0000000000
--- a/lib/diameter/examples/redirect_cb.erl
+++ /dev/null
@@ -1,63 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index deecb1cfc0..0000000000
--- a/lib/diameter/examples/relay.erl
+++ /dev/null
@@ -1,92 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 9ed6517d5c..0000000000
--- a/lib/diameter/examples/relay_cb.erl
+++ /dev/null
@@ -1,69 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 2e0e9d8b0b..0000000000
--- a/lib/diameter/examples/sctp.erl
+++ /dev/null
@@ -1,113 +0,0 @@
-
--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
deleted file mode 100644
index ebb408e501..0000000000
--- a/lib/diameter/examples/server.erl
+++ /dev/null
@@ -1,88 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 43b8e24b5c..0000000000
--- a/lib/diameter/examples/server_cb.erl
+++ /dev/null
@@ -1,115 +0,0 @@
-%%
-%% %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
index 0fa7fd406f..4273262015 100644
--- a/lib/diameter/include/diameter.hrl
+++ b/lib/diameter/include/diameter.hrl
@@ -107,6 +107,21 @@
transport = sctp, %% | tcp,
protocol = diameter}). %% | radius | 'tacacs+'
+%% A diameter_callback record can be specified as an application
+%% module in order to selectively receive callbacks or alter their
+%% form.
+-record(diameter_callback,
+ {peer_up,
+ peer_down,
+ pick_peer,
+ prepare_request,
+ prepare_retransmit,
+ handle_request,
+ handle_answer,
+ handle_error,
+ default,
+ extra = []}).
+
%% 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
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
index d037e1044a..13a6c462af 100644
--- a/lib/diameter/include/diameter_gen.hrl
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -40,14 +40,14 @@ encode_avps(Name, Rec) ->
list_to_binary(encode(Name, Rec))
catch
throw: {?MODULE, Reason} ->
- diameter_dbg:log({encode, error},
+ diameter_lib: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},
+ diameter_lib:log({encode, failure},
?MODULE,
?LINE,
{Reason, Name, Rec, Stack}),
@@ -159,7 +159,7 @@ d_rc(Name, {Avps, {Rec, [] = Failed}}) ->
{Rec, Avps, Failed}
catch
throw: {?MODULE, {AvpName, Reason}} ->
- diameter_dbg:log({decode, error},
+ diameter_lib:log({decode, error},
?MODULE,
?LINE,
{AvpName, Reason, Rec}),
@@ -260,7 +260,7 @@ d(Name, Avp, {Avps, Acc}) ->
%% 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},
+ diameter_lib:log({decode, failure},
?MODULE,
?LINE,
{Reason, Avp, erlang:get_stacktrace()}),
diff --git a/lib/diameter/make/rules.mk.in b/lib/diameter/make/rules.mk.in
index 6318f2bc9c..cd3c297d75 100644
--- a/lib/diameter/make/rules.mk.in
+++ b/lib/diameter/make/rules.mk.in
@@ -112,8 +112,6 @@ $(EBIN)/%.beam: $(ESRC)/%.erl
# ----------------------------------------------------
# export VSN
-# DOCSUPPORT = 1
-
# TOPDOCDIR=../../../../doc
DOCDIR = ..
diff --git a/lib/diameter/src/.gitignore b/lib/diameter/src/.gitignore
new file mode 100644
index 0000000000..feeb378fd8
--- /dev/null
+++ b/lib/diameter/src/.gitignore
@@ -0,0 +1,2 @@
+
+/depend.mk
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index 6935eb053e..de2eca0279 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -16,28 +16,251 @@
#
# %CopyrightEnd%
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-else
+ifeq ($(ERL_TOP),)
include $(DIAMETER_TOP)/make/target.mk
include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+else
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
endif
# ----------------------------------------------------
-# Common Macros
+# Application version
+# ----------------------------------------------------
+
+include ../vsn.mk
+
+VSN = $(DIAMETER_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
# ----------------------------------------------------
-include subdirs.mk
+RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
+
+# Where to put/find things.
+EBIN = ../ebin
+INCDIR = ../include
-SPECIAL_TARGETS =
+# Dumbed down to make 3.80. In 3.81 and later it's just $(realpath $(EBIN)).
+ABS_EBIN := $(shell cd $(EBIN) && pwd)
+
+# Where make should look for dependencies.
+VPATH = .:base:compiler:transport:gen
# ----------------------------------------------------
-# Default Subdir Targets
+# Target specs
# ----------------------------------------------------
-ifneq ($(ERL_TOP),)
-include $(ERL_TOP)/make/otp_subdir.mk
+
+include modules.mk
+
+# Modules generated from dictionary specifications.
+DICT_MODULES = $(DICTS:%=gen/diameter_gen_%)
+DICT_ERLS = $(DICT_MODULES:%=%.erl)
+DICT_HRLS = $(DICT_MODULES:%=%.hrl)
+
+# Modules to build before compiling dictionaries.
+COMPILER_MODULES = $(notdir $(filter compiler/%, $(CT_MODULES))) \
+ $(DICT_YRL)
+
+# All handwritten modules from which a depend.mk is generated.
+MODULES = \
+ $(RT_MODULES) \
+ $(CT_MODULES)
+
+# Modules whose names are inserted into the app file.
+APP_MODULES = \
+ $(RT_MODULES) \
+ $(DICT_MODULES)
+
+# Modules for which to build beams.
+TARGET_MODULES = \
+ $(APP_MODULES) \
+ $(CT_MODULES) \
+ $(DICT_YRL:%=gen/%)
+
+# What to build for the 'opt' target.
+TARGET_FILES = \
+ $(patsubst %, $(EBIN)/%.$(EMULATOR), $(notdir $(TARGET_MODULES))) \
+ $(APP_TARGET) \
+ $(APPUP_TARGET)
+
+# Subdirectories of src to release modules into.
+TARGET_DIRS = $(sort $(dir $(TARGET_MODULES)))
+
+# Ditto for examples.
+EXAMPLE_DIRS = $(sort $(dir $(EXAMPLES)))
+
+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
+
+ERL_COMPILE_FLAGS += \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,app_vsn,$(APP_VSN)}' \
+ +warn_export_vars \
+ +warn_unused_vars \
+ -pa $(ABS_EBIN) \
+ -I $(INCDIR) \
+ -I gen
+# -pa is to be able to include_lib from the include directory: the
+# path must contain the application name.
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+# erl/hrl from dictionary file.
+gen/diameter_gen_%.erl gen/diameter_gen_%.hrl: dict/%.dia
+ ../bin/diameterc -o gen -i $(EBIN) $<
+
+opt: $(TARGET_FILES)
+
+debug:
+ @$(MAKE) TYPE=debug opt
+
+# The dictionary parser.
+gen/$(DICT_YRL).erl: compiler/$(DICT_YRL).yrl
+ $(ERLC) -Werror -o $(@D) $<
+
+# Generate the app file.
+$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk
+ M=`echo $(notdir $(APP_MODULES)) | tr ' ' ,`; \
+ sed -e 's;%VSN%;$(VSN);' \
+ -e "s;%MODULES%;$$M;" \
+ $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+app: $(APP_TARGET) $(APPUP_TARGET)
+dict: $(DICT_ERLS)
+
+docs:
+
+list = echo $(1):; echo $($(1)) | tr ' ' '\n' | sort | sed 's@^@ @'
+
+info:
+ @echo ========================================
+ @$(call list,DICTS)
+ @echo
+ @$(call list,DICT_YRL)
+ @echo
+ @$(call list,RT_MODULES)
+ @echo
+ @$(call list,CT_MODULES)
+ @echo
+ @$(call list,TARGET_MODULES)
+ @echo
+ @$(call list,TARGET_DIRS)
+ @echo
+ @$(call list,EXTERNAL_HRLS)
+ @echo
+ @$(call list,INTERNAL_HRLS)
+ @echo
+ @$(call list,EXAMPLES)
+ @echo
+ @$(call list,EXAMPLE_DIRS)
+ @echo
+ @$(call list,BINS)
+ @echo ========================================
+
+clean:
+ rm -f $(TARGET_FILES) gen/*
+ rm -f depend.mk
+
+# ----------------------------------------------------
+# Release targets
+# ----------------------------------------------------
+
+ifeq ($(ERL_TOP),)
+include $(DIAMETER_TOP)/make/release_targets.mk
else
-include $(DIAMETER_TOP)/make/subdir.mk
+include $(ERL_TOP)/make/otp_release_targets.mk
endif
-#include ../make/subdir.mk
+
+# Can't $(INSTALL_DIR) more than one directory at a time on Solaris.
+
+release_spec: opt
+ for d in bin ebin include src/dict; do \
+ $(INSTALL_DIR) "$(RELSYSDIR)/$$d"; \
+ done
+ $(INSTALL_SCRIPT) $(BINS:%=../bin/%) "$(RELSYSDIR)/bin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(EXTERNAL_HRLS:%=../include/%) $(DICT_HRLS) \
+ "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(DICTS:%=dict/%.dia) "$(RELSYSDIR)/src/dict"
+ $(MAKE) $(TARGET_DIRS:%/=release_src_%)
+ $(MAKE) $(EXAMPLE_DIRS:%/=release_examples_%)
+
+$(TARGET_DIRS:%/=release_src_%): release_src_%:
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/$*"
+ $(INSTALL_DATA) $(filter $*/%, $(TARGET_MODULES:%=%.erl) \
+ $(INTERNAL_HRLS)) \
+ $(filter $*/%, compiler/$(DICT_YRL).yrl) \
+ "$(RELSYSDIR)/src/$*"
+
+$(EXAMPLE_DIRS:%/=release_examples_%): release_examples_%:
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/$*"
+ $(INSTALL_DATA) $(patsubst %, ../examples/%, $(filter $*/%, $(EXAMPLES))) \
+ "$(RELSYSDIR)/examples/$*"
+
+release_docs_spec:
+
+# ----------------------------------------------------
+# Dependencies
+# ----------------------------------------------------
+
+gen/diameter_gen_base_accounting.erl gen/diameter_gen_relay.erl \
+gen/diameter_gen_base_accounting.hrl gen/diameter_gen_relay.hrl: \
+ $(EBIN)/diameter_gen_base_rfc3588.$(EMULATOR)
+
+gen/diameter_gen_base_rfc3588.erl gen/diameter_gen_base_rfc3588.hrl: \
+ $(COMPILER_MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+$(DICT_MODULES:gen/%=$(EBIN)/%.$(EMULATOR)): \
+ $(INCDIR)/diameter.hrl \
+ $(INCDIR)/diameter_gen.hrl
+
+depend: depend.mk
+
+# Generate dependencies makefile.
+depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
+ (for f in $(MODULES); do \
+ (echo $$f; cat $$f.erl) | sed -f $<; \
+ done) \
+ > $@
+
+-include depend.mk
+
+.PHONY: app clean depend dict info release_subdir
+.PHONY: debug opt release_docs_spec release_spec
+.PHONY: $(TARGET_DIRS:%/=%) $(TARGET_DIRS:%/=release_src_%)
+.PHONY: $(EXAMPLE_DIRS:%/=release_examples_%)
+
+# Keep intermediate files.
+.SECONDARY: $(DICT_ERLS) $(DICT_HRLS) gen/$(DICT_YRL:%=%.erl)
+
+# ----------------------------------------------------
+# Targets using secondary expansion (make >= 3.81)
+# ----------------------------------------------------
+
+.SECONDEXPANSION:
+
+# Make beams from a subdirectory.
+$(TARGET_DIRS:%/=%): \
+ $$(patsubst $$@/%, \
+ $(EBIN)/%.$(EMULATOR), \
+ $$(filter $$@/%, $(TARGET_MODULES) compiler/$(DICT_YRL)))
diff --git a/lib/diameter/src/app/.gitignore b/lib/diameter/src/app/.gitignore
deleted file mode 100644
index d388e61877..0000000000
--- a/lib/diameter/src/app/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-
-/diameter_gen_*.erl
-/diameter_gen_*.hrl
-/depend.mk
-/diameter.mk
-
diff --git a/lib/diameter/src/app/Makefile b/lib/diameter/src/app/Makefile
deleted file mode 100644
index 96b7736a90..0000000000
--- a/lib/diameter/src/app/Makefile
+++ /dev/null
@@ -1,218 +0,0 @@
-#
-# %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
deleted file mode 100644
index 9df0133960..0000000000
--- a/lib/diameter/src/app/depend.sed
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# %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
deleted file mode 100644
index a806b5c78a..0000000000
--- a/lib/diameter/src/app/diameter.app.src
+++ /dev/null
@@ -1,28 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 6d8ceadb92..0000000000
--- a/lib/diameter/src/app/diameter.appup.src
+++ /dev/null
@@ -1,47 +0,0 @@
-%% 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
deleted file mode 100644
index 2f721421d8..0000000000
--- a/lib/diameter/src/app/diameter.erl
+++ /dev/null
@@ -1,190 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index c161064303..0000000000
--- a/lib/diameter/src/app/diameter.mk.in
+++ /dev/null
@@ -1,47 +0,0 @@
-#-*-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_callback.erl b/lib/diameter/src/app/diameter_callback.erl
deleted file mode 100644
index 6d5c8cdca1..0000000000
--- a/lib/diameter/src/app/diameter_callback.erl
+++ /dev/null
@@ -1,91 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 138e76411e..0000000000
--- a/lib/diameter/src/app/diameter_capx.erl
+++ /dev/null
@@ -1,405 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index d88f42fb7c..0000000000
--- a/lib/diameter/src/app/diameter_codec.erl
+++ /dev/null
@@ -1,561 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index a6b48fe65b..0000000000
--- a/lib/diameter/src/app/diameter_config.erl
+++ /dev/null
@@ -1,676 +0,0 @@
-%%
-%% %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_exprecs.erl b/lib/diameter/src/app/diameter_exprecs.erl
deleted file mode 100644
index 5e120d6f44..0000000000
--- a/lib/diameter/src/app/diameter_exprecs.erl
+++ /dev/null
@@ -1,301 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 64e95dddb5..0000000000
--- a/lib/diameter/src/app/diameter_gen_base_accounting.dia
+++ /dev/null
@@ -1,68 +0,0 @@
-;;
-;; %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
deleted file mode 100644
index 4a12e21acd..0000000000
--- a/lib/diameter/src/app/diameter_gen_base_rfc3588.dia
+++ /dev/null
@@ -1,413 +0,0 @@
-;;
-;; %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
deleted file mode 100644
index d86446e368..0000000000
--- a/lib/diameter/src/app/diameter_gen_relay.dia
+++ /dev/null
@@ -1,24 +0,0 @@
-;;
-;; %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_peer_fsm.erl b/lib/diameter/src/app/diameter_peer_fsm.erl
deleted file mode 100644
index 282fa2742f..0000000000
--- a/lib/diameter/src/app/diameter_peer_fsm.erl
+++ /dev/null
@@ -1,777 +0,0 @@
-%%
-%% %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_service.erl b/lib/diameter/src/app/diameter_service.erl
deleted file mode 100644
index 421e36ccf5..0000000000
--- a/lib/diameter/src/app/diameter_service.erl
+++ /dev/null
@@ -1,2903 +0,0 @@
-%%
-%% %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_session.erl b/lib/diameter/src/app/diameter_session.erl
deleted file mode 100644
index bb91e97f39..0000000000
--- a/lib/diameter/src/app/diameter_session.erl
+++ /dev/null
@@ -1,172 +0,0 @@
-%%
-%% %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_types.erl b/lib/diameter/src/app/diameter_types.erl
deleted file mode 100644
index 6b1b1b8d39..0000000000
--- a/lib/diameter/src/app/diameter_types.erl
+++ /dev/null
@@ -1,537 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index 02bf8a74dd..0000000000
--- a/lib/diameter/src/app/diameter_types.hrl
+++ /dev/null
@@ -1,139 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index b7c1491f4b..0000000000
--- a/lib/diameter/src/app/diameter_watchdog.erl
+++ /dev/null
@@ -1,571 +0,0 @@
-%%
-%% %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/modules.mk b/lib/diameter/src/app/modules.mk
deleted file mode 100644
index c133e6f64e..0000000000
--- a/lib/diameter/src/app/modules.mk
+++ /dev/null
@@ -1,70 +0,0 @@
-#-*-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/base/diameter.app.src b/lib/diameter/src/base/diameter.app.src
new file mode 100644
index 0000000000..c092fdb022
--- /dev/null
+++ b/lib/diameter/src/base/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, [%MODULES%]},
+ {registered, []},
+ {applications, [stdlib, kernel]},
+ {env, []},
+ {mod, {diameter_app, []}}
+ ]}.
diff --git a/lib/diameter/src/base/diameter.appup.src b/lib/diameter/src/base/diameter.appup.src
new file mode 100644
index 0000000000..2ebdad598f
--- /dev/null
+++ b/lib/diameter/src/base/diameter.appup.src
@@ -0,0 +1,34 @@
+%% 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", [{restart_application, diameter}]},
+ {"0.10", [{restart_application, diameter}]},
+ {"1.0", [{update, diameter_service},
+ {update, diameter_watchdog}]}
+ ],
+ [
+ {"0.9", [{restart_application, diameter}]},
+ {"0.10", [{restart_application, diameter}]},
+ {"1.0", [{update, diameter_watchdog},
+ {update, diameter_service}]}
+ ]
+}.
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
new file mode 100644
index 0000000000..336f0c1f2d
--- /dev/null
+++ b/lib/diameter/src/base/diameter.erl
@@ -0,0 +1,339 @@
+%%
+%% %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 a release file rather than by calling
+%% start/stop explicitly.
+-export([start/0,
+ stop/0]).
+
+-export_type([evaluable/0,
+ app_alias/0,
+ service_name/0,
+ capability/0,
+ peer_filter/0,
+ service_opt/0,
+ application_opt/0,
+ app_module/0,
+ transport_ref/0,
+ transport_opt/0,
+ transport_pred/0,
+ call_opt/0]).
+
+-export_type(['OctetString'/0,
+ 'Integer32'/0,
+ 'Integer64'/0,
+ 'Unsigned32'/0,
+ 'Unsigned64'/0,
+ 'Float32'/0,
+ 'Float64'/0,
+ 'Grouped'/0,
+ 'Address'/0,
+ 'Time'/0,
+ 'UTF8String'/0,
+ 'DiameterIdentity'/0,
+ 'DiameterURI'/0,
+ 'Enumerated'/0,
+ 'IPFilterRule'/0,
+ 'QoSFilterRule'/0]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.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/1
+%% ---------------------------------------------------------------------------
+
+-spec subscribe(service_name())
+ -> true.
+
+subscribe(SvcName) ->
+ diameter_service:subscribe(SvcName).
+
+%% ---------------------------------------------------------------------------
+%% unsubscribe/1
+%% ---------------------------------------------------------------------------
+
+-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/3,4
+%% ---------------------------------------------------------------------------
+
+-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, []).
+
+%% ===========================================================================
+
+%% 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'().
+
+%% The handle to a service.
+
+-type service_name()
+ :: any().
+
+%% 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()]}.
+
+-type evaluable()
+ :: {module(), atom(), list()}
+ | fun()
+ | maybe_improper_list(evaluable(), list()).
+
+%% 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_alias()
+ :: any().
+
+-type app_module()
+ :: module()
+ | maybe_improper_list(module(), list())
+ | #diameter_callback{}.
+
+%% 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()]}
+ | {capabilities_cb, evaluable()}
+ | {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_app.erl b/lib/diameter/src/base/diameter_app.erl
index 600f7ff04d..600f7ff04d 100644
--- a/lib/diameter/src/app/diameter_app.erl
+++ b/lib/diameter/src/base/diameter_app.erl
diff --git a/lib/diameter/src/base/diameter_callback.erl b/lib/diameter/src/base/diameter_callback.erl
new file mode 100644
index 0000000000..90431099b0
--- /dev/null
+++ b/lib/diameter/src/base/diameter_callback.erl
@@ -0,0 +1,234 @@
+%%
+%% %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 diameter callback module that can redirect selected callbacks,
+%% providing reasonable default implementations otherwise.
+%%
+%% To order alternate callbacks, configure a #diameter_callback record
+%% as the Diameter application callback in question. The record has
+%% one field for each callback function as well as 'default' and
+%% 'extra' fields. A function-specific field can be set to a
+%% diameter:evaluable() in order to redirect the callback
+%% corresponding to that field, or to 'false' to request the default
+%% callback implemented in this module. If neither of these fields are
+%% set then the 'default' field determines the form of the callback: a
+%% module name results in the usual callback as if the module had been
+%% configured directly as the callback module, a diameter_evaluable()
+%% in a callback applied to the atom-valued callback name and argument
+%% list. For all callbacks not to this module, the 'extra' field is a
+%% list of additional arguments, following arguments supplied by
+%% diameter but preceeding those of the diameter:evaluable() being
+%% applied.
+%%
+%% For example, the following config to diameter:start_service/2, in
+%% an 'application' tuple, would result in only a mymod:peer_down/3
+%% callback, this module implementing the remaining callbacks.
+%%
+%% {module, #diameter_callback{peer_down = {mymod, down, []}}}
+%%
+%% Equivalently, this can also be specified with a [Mod | Args]
+%% field/value list as follows.
+%%
+%% {module, [diameter_callback, {peer_down, {mymod, down, []}}]}
+%%
+%% The following would result in this module suppying peer_up and
+%% peer_down callback, others taking place in module mymod.
+%%
+%% {module, #diameter_callback{peer_up = false,
+%% peer_down = false,
+%% default = mymod}}
+%%
+%% The following would result in all callbacks taking place as
+%% calls to mymod:diameter/2.
+%%
+%% {module, #diameter_callback{default = {mymod, diameter, []}}}
+%%
+%% The following are equivalent and result in all callbacks being
+%% provided by this module.
+%%
+%% {module, #diameter_callback{}}
+%% {module, diameter_callback}
+%%
+
+-module(diameter_callback).
+
+%% Default callbacks when no aleternate is specified.
+-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]).
+
+%% Callbacks taking a #diameter_callback record.
+-export([peer_up/4,
+ peer_down/4,
+ pick_peer/5,
+ prepare_request/4,
+ prepare_retransmit/4,
+ handle_request/4,
+ handle_answer/5,
+ handle_error/5]).
+
+-include_lib("diameter/include/diameter.hrl").
+
+%%% ----------------------------------------------------------
+%%% # peer_up/3
+%%% ----------------------------------------------------------
+
+peer_up(_Svc, _Peer, State) ->
+ State.
+
+peer_up(Svc, Peer, State, D) ->
+ cb(peer_up,
+ [Svc, Peer, State],
+ D#diameter_callback.peer_up,
+ D).
+
+%%% ----------------------------------------------------------
+%%% # peer_down/3
+%%% ----------------------------------------------------------
+
+peer_down(_Svc, _Peer, State) ->
+ State.
+
+peer_down(Svc, Peer, State, D) ->
+ cb(peer_down,
+ [Svc, Peer, State],
+ D#diameter_callback.peer_down,
+ D).
+
+%%% ----------------------------------------------------------
+%%% # pick_peer/4
+%%% ----------------------------------------------------------
+
+pick_peer([Peer|_], _, _Svc, _State) ->
+ {ok, Peer};
+pick_peer([], _, _Svc, _State) ->
+ false.
+
+pick_peer(PeersL, PeersR, Svc, State, D) ->
+ cb(pick_peer,
+ [PeersL, PeersR, Svc, State],
+ D#diameter_callback.pick_peer,
+ D).
+
+%%% ----------------------------------------------------------
+%%% # prepare_request/3
+%%% ----------------------------------------------------------
+
+prepare_request(Pkt, _Svc, _Peer) ->
+ {send, Pkt}.
+
+prepare_request(Pkt, Svc, Peer, D) ->
+ cb(prepare_request,
+ [Pkt, Svc, Peer],
+ D#diameter_callback.prepare_request,
+ D).
+
+%%% ----------------------------------------------------------
+%%% # prepare_retransmit/3
+%%% ----------------------------------------------------------
+
+prepare_retransmit(Pkt, _Svc, _Peer) ->
+ {send, Pkt}.
+
+prepare_retransmit(Pkt, Svc, Peer, D) ->
+ cb(prepare_retransmit,
+ [Pkt, Svc, Peer],
+ D#diameter_callback.prepare_retransmit,
+ D).
+
+%%% ----------------------------------------------------------
+%%% # handle_request/3
+%%% ----------------------------------------------------------
+
+handle_request(_Pkt, _Svc, _Peer) ->
+ {protocol_error, 3001}. %% DIAMETER_COMMAND_UNSUPPORTED
+
+handle_request(Pkt, Svc, Peer, D) ->
+ cb(handle_request,
+ [Pkt, Svc, Peer],
+ D#diameter_callback.handle_request,
+ D).
+
+%%% ----------------------------------------------------------
+%%% # handle_answer/4
+%%% ----------------------------------------------------------
+
+handle_answer(#diameter_packet{msg = Ans, errors = []}, _Req, _Svc, _Peer) ->
+ Ans;
+handle_answer(#diameter_packet{msg = Ans, errors = Es}, _Req, _Svc, _Peer) ->
+ [Ans | Es].
+
+handle_answer(Pkt, Req, Svc, Peer, D) ->
+ cb(handle_answer,
+ [Pkt, Req, Svc, Peer],
+ D#diameter_callback.handle_answer,
+ D).
+
+%%% ---------------------------------------------------------------------------
+%%% # handle_error/4
+%%% ---------------------------------------------------------------------------
+
+handle_error(Reason, _Req, _Svc, _Peer) ->
+ {error, Reason}.
+
+handle_error(Reason, Req, Svc, Peer, D) ->
+ cb(handle_error,
+ [Reason, Req, Svc, Peer],
+ D#diameter_callback.handle_error,
+ D).
+
+%% ===========================================================================
+
+%% cb/4
+
+%% Unspecified callback: use default field to determine something
+%% appropriate.
+cb(CB, Args, undefined, D) ->
+ cb(CB, Args, D);
+
+%% Explicitly requested default.
+cb(CB, Args, false, _) ->
+ apply(?MODULE, CB, Args);
+
+%% A specified callback.
+cb(_, Args, F, #diameter_callback{extra = X}) ->
+ diameter_lib:eval([[F|X] | Args]).
+
+%% cb/3
+
+%% No user-supplied default: call ours.
+cb(CB, Args, #diameter_callback{default = undefined}) ->
+ apply(?MODULE, CB, Args);
+
+%% Default is a module name: make the usual callback.
+cb(CB, Args, #diameter_callback{default = M,
+ extra = X})
+ when is_atom(M) ->
+ apply(M, CB, Args ++ X);
+
+%% Default is something else: apply if to callback name and arguments.
+cb(CB, Args, #diameter_callback{default = F,
+ extra = X}) ->
+ diameter_lib:eval([F, CB, Args | X]).
diff --git a/lib/diameter/src/base/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl
new file mode 100644
index 0000000000..6c4d60ee9b
--- /dev/null
+++ b/lib/diameter/src/base/diameter_capx.erl
@@ -0,0 +1,391 @@
+%%
+%% %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_gen_base_rfc3588.hrl").
+
+-define(SUCCESS, 2001). %% DIAMETER_SUCCESS
+-define(NOAPP, 5010). %% DIAMETER_NO_COMMON_APPLICATION
+-define(NOSECURITY, 5017). %% 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({[diameter:'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({[diameter:'Unsigned32'()],
+ [diameter:'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}
+ 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})}.
+
+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(CEA, #diameter_service{capabilities = LCaps} = Svc) ->
+ RCaps = capx_to_caps(CEA),
+ SApps = common_applications(LCaps, RCaps, Svc),
+ IS = common_security(LCaps, RCaps),
+
+ {SApps, IS, RCaps}.
+
+%% 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/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
new file mode 100644
index 0000000000..fe1212b7e0
--- /dev/null
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -0,0 +1,543 @@
+%%
+%% %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, 'answer-message' = MsgName, Header) ->
+ ?BASE = Mod,
+ #diameter_header{cmd_code = Code} = Header,
+ {_, Flags, ApplId} = ?BASE:msg_header(MsgName),
+ {Code, Flags, ApplId};
+
+msg_header(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>>.
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
new file mode 100644
index 0000000000..9253af0de2
--- /dev/null
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -0,0 +1,691 @@
+%%
+%% %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(#diameter_callback{} = R) ->
+ init_mod([diameter_callback, R]);
+init_mod([diameter_callback, #diameter_callback{}] = L) ->
+ L;
+init_mod([diameter_callback = M | L])
+ when is_list(L) ->
+ [M, init_cb(L)];
+init_mod(M)
+ when is_atom(M) ->
+ [M];
+init_mod([M|_] = L)
+ when is_atom(M) ->
+ L;
+init_mod(M) ->
+ ?THROW({module, M}).
+
+init_cb(List) ->
+ Fields = record_info(fields, diameter_callback),
+ Defaults = lists:zip(Fields, tl(tuple_to_list(#diameter_callback{}))),
+ Values = [V || F <- Fields,
+ D <- [proplists:get_value(F, Defaults)],
+ V <- [proplists:get_value(F, List, D)]],
+ #diameter_callback{} = list_to_tuple([diameter_callback | Values]).
+
+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/base/diameter_dbg.erl
index 5b0ac3a3b6..5b0ac3a3b6 100644
--- a/lib/diameter/src/app/diameter_dbg.erl
+++ b/lib/diameter/src/base/diameter_dbg.erl
diff --git a/lib/diameter/src/app/diameter_dict.erl b/lib/diameter/src/base/diameter_dict.erl
index 3b9ba00a3f..3b9ba00a3f 100644
--- a/lib/diameter/src/app/diameter_dict.erl
+++ b/lib/diameter/src/base/diameter_dict.erl
diff --git a/lib/diameter/src/app/diameter_info.erl b/lib/diameter/src/base/diameter_info.erl
index 39d32d07cd..39d32d07cd 100644
--- a/lib/diameter/src/app/diameter_info.erl
+++ b/lib/diameter/src/base/diameter_info.erl
diff --git a/lib/diameter/src/app/diameter_internal.hrl b/lib/diameter/src/base/diameter_internal.hrl
index 63b35550a8..63b35550a8 100644
--- a/lib/diameter/src/app/diameter_internal.hrl
+++ b/lib/diameter/src/base/diameter_internal.hrl
diff --git a/lib/diameter/src/app/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl
index 362d593b24..362d593b24 100644
--- a/lib/diameter/src/app/diameter_lib.erl
+++ b/lib/diameter/src/base/diameter_lib.erl
diff --git a/lib/diameter/src/app/diameter_misc_sup.erl b/lib/diameter/src/base/diameter_misc_sup.erl
index 4e40476f14..4e40476f14 100644
--- a/lib/diameter/src/app/diameter_misc_sup.erl
+++ b/lib/diameter/src/base/diameter_misc_sup.erl
diff --git a/lib/diameter/src/app/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl
index 3e78c4caef..3e78c4caef 100644
--- a/lib/diameter/src/app/diameter_peer.erl
+++ b/lib/diameter/src/base/diameter_peer.erl
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
new file mode 100644
index 0000000000..99644814d2
--- /dev/null
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -0,0 +1,881 @@
+%%
+%% %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_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).
+
+%% A 2xxx series Result-Code. Not necessarily 2001.
+-define(IS_SUCCESS(N), 2 == (N) div 1000).
+
+%% 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 | {diameter:'Unsigned32'(),
+ diameter:'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, T, Opts, #diameter_service{capabilities = Caps} = Svc0}) ->
+ putr(dwa, dwa(Caps)),
+ {M, Ref} = T,
+ {[Ts], Rest} = proplists:split(Opts, [capabilities_cb]),
+ putr(capabilities_cb, {Ref, [F || {_,F} <- Ts]}),
+ {ok, TPid, Svc} = start_transport(T, Rest, 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
+ {?MODULE, Tag, Reason} ->
+ ?LOG(Tag, {Reason, T}),
+ {stop, {shutdown, Reason}, State}
+ end.
+%% The form of the exception caught here is historical. It's
+%% significant that it's not a 2-tuple, as in ?FAILURE(Reason),
+%% since these are caught elsewhere.
+
+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}).
+
+eraser(Key) ->
+ erase({?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) ->
+ OH = Caps#diameter_caps.origin_host,
+ req_send_CER(OH, Remote)
+ orelse
+ close({already_connected, Remote, Caps}, 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 = H,
+ transport_data = TD}
+ = ReqPkt,
+
+ {Msg, PostF} = build_answer(Type, ReqPkt, S),
+
+ %% An answer message clears the R and T flags and retains the P
+ %% flag. The E flag is set at encode.
+ Pkt = #diameter_packet{header
+ = H#diameter_header{version = ?DIAMETER_VERSION,
+ is_request = false,
+ is_error = undefined,
+ is_retransmitted = false},
+ msg = Msg,
+ 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/3
+
+build_answer('CER',
+ #diameter_packet{msg = CER,
+ header = #diameter_header{version
+ = ?DIAMETER_VERSION,
+ is_error = false},
+ errors = []}
+ = Pkt,
+ S) ->
+ {SupportedApps, RCaps, #diameter_base_CEA{'Result-Code' = RC,
+ 'Inband-Security-Id' = IS}
+ = CEA}
+ = recv_CER(CER, S),
+
+ #diameter_caps{origin_host = {OH, DH}}
+ = Caps
+ = capz(caps(S), RCaps),
+
+ try
+ 2001 == RC %% DIAMETER_SUCCESS
+ orelse ?THROW(RC),
+ register_everywhere({?MODULE, connection, OH, DH})
+ orelse ?THROW(4003), %% DIAMETER_ELECTION_LOST
+ caps_cb(Caps)
+ of
+ N -> {cea(CEA, N), [fun open/5, Pkt,
+ SupportedApps,
+ Caps,
+ {accept, hd([_] = IS)}]}
+ catch
+ ?FAILURE(Reason) ->
+ rejected(Reason, {'CER', Reason, Caps, Pkt}, S)
+ end;
+
+%% The error checks below are similar to those in diameter_service for
+%% other messages. Should factor out the commonality.
+
+build_answer(Type,
+ #diameter_packet{header = H,
+ errors = Es}
+ = Pkt,
+ S) ->
+ RC = rc(H, Es),
+ {answer(Type, RC, Es, S), post(Type, RC, Pkt, S)}.
+
+cea(CEA, ok) ->
+ CEA;
+cea(CEA, 2001) ->
+ CEA;
+cea(CEA, RC) ->
+ CEA#diameter_base_CEA{'Result-Code' = RC}.
+
+post('CER' = T, RC, Pkt, S) ->
+ [fun close/2, {T, caps(S), {RC, Pkt}}];
+post(_, _, _, _) ->
+ ok.
+
+rejected({capabilities_cb, _F, Reason}, T, S) ->
+ rejected(Reason, T, S);
+
+rejected(discard, T, S) ->
+ close(T, S);
+rejected({N, Es}, T, S) ->
+ {answer('CER', N, Es, S), [fun close/2, T]};
+rejected(N, T, S) ->
+ rejected({N, []}, T, S).
+
+answer(Type, RC, Es, S) ->
+ set(answer(Type, RC, S), failed_avp([A || {_,A} <- Es])).
+
+answer(Type, RC, S) ->
+ answer_message(answer(Type, S), RC).
+
+%% answer_message/2
+
+answer_message([_ | Avps], RC)
+ when 3000 =< RC, RC < 4000 ->
+ ['answer-message', {'Result-Code', RC}
+ | lists:filter(fun is_origin/1, Avps)];
+
+answer_message(Msg, RC) ->
+ Msg ++ [{'Result-Code', RC}].
+
+is_origin({N, _}) ->
+ N == 'Origin-Host'
+ orelse N == 'Origin-Realm'
+ orelse N == 'Origin-State-Id'.
+
+%% failed_avp/1
+
+failed_avp([] = No) ->
+ No;
+failed_avp(Avps) ->
+ [{'Failed-AVP', [[{'AVP', Avps}]]}].
+
+%% set/2
+
+set(Ans, []) ->
+ Ans;
+set(['answer-message' | _] = Ans, FailedAvp) ->
+ Ans ++ [{'AVP', [FailedAvp]}];
+set([_|_] = Ans, FailedAvp) ->
+ Ans ++ FailedAvp.
+
+%% rc/2
+
+rc(#diameter_header{is_error = true}, _) ->
+ 3008; %% DIAMETER_INVALID_HDR_BITS
+
+rc(_, [Bs|_])
+ when is_bitstring(Bs) ->
+ 3009; %% DIAMETER_INVALID_HDR_BITS
+
+rc(#diameter_header{version = ?DIAMETER_VERSION}, Es) ->
+ rc(Es);
+
+rc(_, _) ->
+ 5011. %% DIAMETER_UNSUPPORTED_VERSION
+
+%% rc/1
+
+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,
+ origin_state_id = OSI}) ->
+ ['CEA', {'Origin-Host', Host},
+ {'Origin-Realm', Realm},
+ {'Host-IP-Address', Addrs},
+ {'Vendor-Id', Vid},
+ {'Product-Name', Name},
+ {'Origin-State-Id', OSI}];
+
+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{bin = Bin}
+ = Pkt,
+ #state{service = #diameter_service{capabilities = LCaps}}
+ = S)
+ when is_binary(Bin) ->
+ ?LOG(recv, 'CEA'),
+
+ #diameter_packet{msg = CEA}
+ = DPkt
+ = diameter_codec:decode(?BASE, Pkt),
+
+ {SApps, IS, RCaps} = recv_CEA(DPkt, S),
+
+ #diameter_caps{origin_host = {OH, DH}}
+ = Caps
+ = capz(LCaps, RCaps),
+
+ #diameter_base_CEA{'Result-Code' = RC}
+ = CEA,
+
+ %% 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.
+
+ try
+ ?IS_SUCCESS(RC)
+ orelse ?THROW(RC),
+ [] == SApps
+ andalso ?THROW(no_common_application),
+ [] == IS
+ andalso ?THROW(no_common_security),
+ register_everywhere({?MODULE, connection, OH, DH})
+ orelse ?THROW(election_lost),
+ caps_cb(Caps)
+ of
+ _ -> open(DPkt, SApps, Caps, {connect, hd([_] = IS)}, S)
+ catch
+ ?FAILURE(Reason) -> close({'CEA', Reason, Caps, DPkt}, S)
+ end.
+%% Check more than the result code since the peer could send success
+%% regardless. If not 2001 then a peer_up callback could do anything
+%% required. It's not unimaginable that a peer agreeing to TLS after
+%% capabilities exchange could send DIAMETER_LIMITED_SUCCESS = 2002,
+%% even if this isn't required by RFC 3588.
+
+%% recv_CEA/2
+
+recv_CEA(#diameter_packet{header = #diameter_header{version
+ = ?DIAMETER_VERSION,
+ is_error = false},
+ msg = CEA,
+ errors = []},
+ #state{service = Svc}) ->
+ {ok, T} = diameter_capx:recv_CEA(CEA, Svc),
+ T;
+
+recv_CEA(Pkt, S) ->
+ close({'CEA', caps(S), Pkt}, S).
+
+caps(#diameter_service{capabilities = Caps}) ->
+ Caps;
+caps(#state{service = Svc}) ->
+ caps(Svc).
+
+%% caps_cb/1
+
+caps_cb(Caps) ->
+ {Ref, Ts} = eraser(capabilities_cb),
+ ccb(Ts, [Ref, Caps]).
+
+ccb([], _) ->
+ ok;
+ccb([F | Rest], T) ->
+ case diameter_lib:eval([F|T]) of
+ ok ->
+ ccb(Rest, T);
+ N when ?IS_SUCCESS(N) -> %% 2xxx result code: accept immediately
+ N;
+ Res ->
+ ?THROW({capabilities_cb, F, rejected(Res)})
+ end.
+%% Note that returning 2xxx causes the capabilities exchange to be
+%% accepted directly, without further callbacks.
+
+rejected(discard = T) ->
+ T;
+rejected(unknown) ->
+ 3010; %% DIAMETER_UNKNOWN_PEER
+rejected(N)
+ when is_integer(N) ->
+ N.
+
+%% open/5
+
+open(Pkt, SupportedApps, Caps, {Type, IS}, #state{parent = Pid} = S) ->
+ #diameter_caps{origin_host = {_,_} = H,
+ inband_security_id = {LS,_}}
+ = Caps,
+
+ tls_ack(lists:member(?TLS, LS), Caps, Type, IS, S),
+ Pid ! {open, self(), H, {Caps, 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, Caps, Type, IS, #state{transport = TPid} = S) ->
+ Ref = make_ref(),
+ TPid ! {diameter, {tls, Ref, Type, IS == ?TLS}},
+ receive
+ {diameter, {tls, Ref}} ->
+ ok;
+ {'DOWN', _, process, TPid, Reason} ->
+ close({tls_ack, Reason, Caps}, 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/base/diameter_peer_fsm_sup.erl
index 995eaf74d0..995eaf74d0 100644
--- a/lib/diameter/src/app/diameter_peer_fsm_sup.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm_sup.erl
diff --git a/lib/diameter/src/app/diameter_reg.erl b/lib/diameter/src/base/diameter_reg.erl
index 882b9da238..882b9da238 100644
--- a/lib/diameter/src/app/diameter_reg.erl
+++ b/lib/diameter/src/base/diameter_reg.erl
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
new file mode 100644
index 0000000000..3dfdcee2b2
--- /dev/null
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -0,0 +1,2897 @@
+%%
+%% %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").
+
+-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([diameter:transport_opt()]),%% from 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, diameter: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(diameter:app_alias()), %% #diameter_app.alias
+ dictionary :: match(module()), %% #diameter_app.dictionary
+ module :: match([module() | list()]),
+ %% #diameter_app.module
+ filter :: match(diameter:peer_filter()),
+ packet :: match(#diameter_packet{})}).
+
+%% Record call/4 options are parsed into.
+-record(options,
+ {filter = none :: diameter: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.
+
+%% 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).
+
+%%% ---------------------------------------------------------------------------
+%%% # 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 = 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) ->
+ case diameter_watchdog:start({Type, Ref}, T) of
+ {_MRef, Pid} ->
+ Pid;
+ Pid when is_pid(Pid) -> %% from old code
+ erlang:monitor(process, Pid),
+ Pid
+ end.
+
+%% 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{op_state = ?STATE_UP, %% assert
+ 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{op_state = ?STATE_DOWN}, _, S) ->
+ S;
+
+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),
+ closed(Reason, P, S),
+ restart(P,S),
+ peer_down(P,S).
+
+%% Send an event at connection establishment failure.
+closed({shutdown, {close, _TPid, Reason}},
+ #peer{op_state = ?STATE_DOWN,
+ ref = Ref,
+ type = Type,
+ options = Opts},
+ #state{service_name = SvcName}) ->
+ send_event(SvcName, {closed, Ref, Reason, {type(Type), Opts}});
+closed(_, _, _) ->
+ ok.
+
+%% The peer has never come up ...
+peer_down(#peer{conn = B}, S)
+ when is_boolean(B) ->
+ S;
+
+%% ... or it has.
+peer_down(#peer{conn = TPid} = P, #state{connT = ConnT} = S) ->
+ #conn{} = C = fetch(ConnT, TPid),
+ ets:delete_object(ConnT, C),
+ 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(diameter_config: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, diameter_config: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_request_packet(Msg),
+
+ case cb(ModX, prepare_request, [Pkt, SvcName, {TPid, Caps}]) of
+ {send, P} ->
+ send_request(make_request_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_request_packet/1
+%%
+%% Turn an outgoing request as passed to call/4 into a diameter_packet
+%% record in preparation for a prepare_request callback.
+
+make_request_packet(Bin)
+ when is_binary(Bin) ->
+ #diameter_packet{header = diameter_codec:decode_header(Bin),
+ bin = Bin};
+
+make_request_packet(#diameter_packet{msg = [#diameter_header{} = Hdr | Avps]}
+ = Pkt) ->
+ Pkt#diameter_packet{msg = [make_request_header(Hdr) | Avps]};
+
+make_request_packet(#diameter_packet{header = Hdr} = Pkt) ->
+ Pkt#diameter_packet{header = make_request_header(Hdr)};
+
+make_request_packet(Msg) ->
+ make_request_packet(#diameter_packet{msg = Msg}).
+
+%% make_request_header/1
+
+make_request_header(undefined) ->
+ Seq = diameter_session:sequence(),
+ make_request_header(#diameter_header{end_to_end_id = Seq,
+ hop_by_hop_id = Seq});
+
+make_request_header(#diameter_header{version = undefined} = Hdr) ->
+ make_request_header(Hdr#diameter_header{version = ?DIAMETER_VERSION});
+
+make_request_header(#diameter_header{end_to_end_id = undefined} = H) ->
+ Seq = diameter_session:sequence(),
+ make_request_header(H#diameter_header{end_to_end_id = Seq});
+
+make_request_header(#diameter_header{hop_by_hop_id = undefined} = H) ->
+ Seq = diameter_session:sequence(),
+ make_request_header(H#diameter_header{hop_by_hop_id = Seq});
+
+make_request_header(#diameter_header{} = Hdr) ->
+ Hdr;
+
+make_request_header(T) ->
+ ?ERROR({invalid_header, T}).
+
+%% make_request_packet/2
+%%
+%% Reconstruct a diameter_packet from the return value of
+%% prepare_request or prepare_retransmit callback.
+
+make_request_packet(Bin, _)
+ when is_binary(Bin) ->
+ make_request_packet(Bin);
+
+make_request_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_request_packet(#diameter_packet{header = Hdr} = Pkt,
+ #diameter_packet{header = Hdr0}) ->
+ Pkt#diameter_packet{header = fold_record(Hdr0, Hdr)};
+
+make_request_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_request_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_answer_packet(Msg, ReqPkt)),
+ incr(send, Pkt, 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_answer_packet/2
+
+%% Binaries and header/avp lists are sent as-is.
+make_answer_packet(Bin, _)
+ when is_binary(Bin) ->
+ #diameter_packet{bin = Bin};
+make_answer_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. 6.2 of 3588 requires the
+%% same P flag on an answer as on the request.
+make_answer_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,
+ caps = Caps,
+ packet = P}
+ = Req) ->
+ try
+ incr(in, Pkt, 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, TPid)
+ when is_pid(TPid) ->
+ #diameter_packet{header = #diameter_header{is_error = E}
+ = Hdr,
+ msg = Rec}
+ = Pkt,
+
+ RC = int(get_avp_value(?BASE, '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(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(Rec, _) ->
+ rcc(get_avp_value(?BASE, '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}} = Req, S) ->
+ find_transport(get_destination(Msg), 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} = App, Msg, Opts, S) ->
+ #options{filter = Filter,
+ extra = Xtra}
+ = Opts,
+ pick_peer(App#diameter_app{module = Mod ++ Xtra},
+ get_destination(Msg),
+ 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/1
+
+get_destination(Msg) ->
+ [str(get_avp_value(?BASE, 'Destination-Realm', Msg)),
+ str(get_avp_value(?BASE, '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/base/diameter_service_sup.erl
index 153fff902f..153fff902f 100644
--- a/lib/diameter/src/app/diameter_service_sup.erl
+++ b/lib/diameter/src/base/diameter_service_sup.erl
diff --git a/lib/diameter/src/base/diameter_session.erl b/lib/diameter/src/base/diameter_session.erl
new file mode 100644
index 0000000000..4c468f207c
--- /dev/null
+++ b/lib/diameter/src/base/diameter_session.erl
@@ -0,0 +1,170 @@
+%%
+%% %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]).
+
+-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()
+ -> diameter:'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()
+ -> diameter:'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(diameter:'DiameterIdentity'())
+ -> diameter:'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/base/diameter_stats.erl
index 71479afa95..71479afa95 100644
--- a/lib/diameter/src/app/diameter_stats.erl
+++ b/lib/diameter/src/base/diameter_stats.erl
diff --git a/lib/diameter/src/app/diameter_sup.erl b/lib/diameter/src/base/diameter_sup.erl
index e5afd23dcd..e5afd23dcd 100644
--- a/lib/diameter/src/app/diameter_sup.erl
+++ b/lib/diameter/src/base/diameter_sup.erl
diff --git a/lib/diameter/src/app/diameter_sync.erl b/lib/diameter/src/base/diameter_sync.erl
index ce2db4b3a2..ce2db4b3a2 100644
--- a/lib/diameter/src/app/diameter_sync.erl
+++ b/lib/diameter/src/base/diameter_sync.erl
diff --git a/lib/diameter/src/base/diameter_types.erl b/lib/diameter/src/base/diameter_types.erl
new file mode 100644
index 0000000000..9ae289034c
--- /dev/null
+++ b/lib/diameter/src/base/diameter_types.erl
@@ -0,0 +1,596 @@
+%%
+%% %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]).
+
+%% Functions taking the AVP name in question as second parameter.
+-export(['OctetString'/3,
+ 'Integer32'/3,
+ 'Integer64'/3,
+ 'Unsigned32'/3,
+ 'Unsigned64'/3,
+ 'Float32'/3,
+ 'Float64'/3,
+ 'Address'/3,
+ 'Time'/3,
+ 'UTF8String'/3,
+ 'DiameterIdentity'/3,
+ 'DiameterURI'/3,
+ 'IPFilterRule'/3,
+ 'QoSFilterRule'/3]).
+
+-include_lib("diameter/include/diameter.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>>.
+
+%% -------------------------------------------------------------------------
+
+'OctetString'(M, _, Data) ->
+ 'OctetString'(M, Data).
+
+'Integer32'(M, _, Data) ->
+ 'Integer32'(M, Data).
+
+'Integer64'(M, _, Data) ->
+ 'Integer64'(M, Data).
+
+'Unsigned32'(M, _, Data) ->
+ 'Unsigned32'(M, Data).
+
+'Unsigned64'(M, _, Data) ->
+ 'Unsigned64'(M, Data).
+
+'Float32'(M, _, Data) ->
+ 'Float32'(M, Data).
+
+'Float64'(M, _, Data) ->
+ 'Float64'(M, Data).
+
+'Address'(M, _, Data) ->
+ 'Address'(M, Data).
+
+'Time'(M, _, Data) ->
+ 'Time'(M, Data).
+
+'UTF8String'(M, _, Data) ->
+ 'UTF8String'(M, Data).
+
+'DiameterIdentity'(M, _, Data) ->
+ 'DiameterIdentity'(M, Data).
+
+'DiameterURI'(M, _, Data) ->
+ 'DiameterURI'(M, Data).
+
+'IPFilterRule'(M, _, Data) ->
+ 'IPFilterRule'(M, Data).
+
+'QoSFilterRule'(M, _, Data) ->
+ 'QoSFilterRule'(M, Data).
+
+%% ===========================================================================
+%% ===========================================================================
+
+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/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
new file mode 100644
index 0000000000..fb22fd8275
--- /dev/null
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -0,0 +1,595 @@
+%%
+%% %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 a monitor before the watchdog is allowed to proceed to ensure
+%% that a failed capabilities exchange produces the desired exit
+%% reason.
+
+start({_,_} = Type, T) ->
+ Ref = make_ref(),
+ {ok, Pid} = diameter_watchdog_sup:start_child({Ref, {Type, self(), T}}),
+ try
+ {erlang:monitor(process, Pid), Pid}
+ after
+ Pid ! Ref
+ end.
+
+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({Ref, {_, Pid, _} = T}) ->
+ MRef = erlang:monitor(process, Pid),
+ receive
+ Ref ->
+ make_state(T);
+ {'DOWN', MRef, process, _, _} = D ->
+ exit({shutdown, D})
+ end;
+
+i({_, Pid, _} = T) -> %% from old code
+ erlang:monitor(process, Pid),
+ make_state(T).
+
+make_state({T, Pid, {ConnT,
+ Opts,
+ SvcName,
+ #diameter_service{applications = Apps,
+ capabilities = Caps}
+ = Svc}}) ->
+ random:seed(now()),
+ putr(restart, {T, Opts, Svc}), %% save seeing it in trace
+ putr(dwr, dwr(Caps)), %%
+ #watchdog{parent = 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 accepting then we may be resuming a connection that went
+%% down in another watchdog process, in which case this is the
+%% transition below, from down to 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/base/diameter_watchdog_sup.erl
index fc837fe4ef..fc837fe4ef 100644
--- a/lib/diameter/src/app/diameter_watchdog_sup.erl
+++ b/lib/diameter/src/base/diameter_watchdog_sup.erl
diff --git a/lib/diameter/src/compiler/.gitignore b/lib/diameter/src/compiler/.gitignore
deleted file mode 100644
index d9f072e262..0000000000
--- a/lib/diameter/src/compiler/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-
-/depend.mk
-
diff --git a/lib/diameter/src/compiler/Makefile b/lib/diameter/src/compiler/Makefile
deleted file mode 100644
index 779013bfbc..0000000000
--- a/lib/diameter/src/compiler/Makefile
+++ /dev/null
@@ -1,131 +0,0 @@
-#
-# %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
index a33b07a3d3..1e31c40afe 100644
--- a/lib/diameter/src/compiler/diameter_codegen.erl
+++ b/lib/diameter/src/compiler/diameter_codegen.erl
@@ -20,17 +20,18 @@
-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.)
+%% This module generates erl/hrl files for encode/decode modules
+%% from the orddict parsed from a dictionary file (.dia) by
+%% diameter_dict_util. The generated code is simple (one-liners),
+%% the generated functions being called by code included iin the
+%% generated modules from diameter_gen.hrl. The orddict itself is
+%% returned by dict/0 in the generated module and diameter_dict_util
+%% calls this function when importing dictionaries as a consequence
+%% of @inherits sections. That is, @inherits introduces a dependency
+%% on the beam file of another dictionary.
%%
--export([from_spec/4]).
+-export([from_dict/4]).
%% Internal exports (for test).
-export([file/1,
@@ -38,17 +39,23 @@
file/3]).
-include("diameter_forms.hrl").
+-include("diameter_vsn.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)})])]}).
+-define(S, atom_to_list).
+-define(A, list_to_atom).
+-define(Atom(T), ?ATOM(?A(T))).
-from_spec(File, Spec, Opts, Mode) ->
+%% ===========================================================================
+
+-spec from_dict(File, Spec, Opts, Mode)
+ -> ok
+ when File :: string(),
+ Spec :: orddict:orddict(),
+ Opts :: list(),
+ Mode :: spec | erl | hrl.
+
+from_dict(File, Spec, Opts, Mode) ->
Outdir = proplists:get_value(outdir, Opts, "."),
putr(verbose, lists:member(verbose, Opts)),
putr(debug, lists:member(debug, Opts)),
@@ -73,7 +80,7 @@ getr(Key) ->
%% ===========================================================================
%% ===========================================================================
-%% Generate from parsed spec in a file.
+%% Generate from parsed dictionary in a file.
file(F) ->
file(F, spec).
@@ -83,55 +90,46 @@ file(F, Mode) ->
file(F, Outdir, Mode) ->
{ok, [Spec]} = file:consult(F),
- from_spec(F, Spec, Outdir, Mode).
+ from_dict(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.").
+write(Path, Str) ->
+ w(Path, Str, "~s").
-w(Path, Spec, Fmt) ->
+write_term(Path, T) ->
+ w(Path, T, "~p.").
+
+w(Path, T, Fmt) ->
{ok, Fd} = file:open(Path, [write]),
- io:fwrite(Fd, Fmt ++ "~n", [Spec]),
+ io:fwrite(Fd, Fmt ++ "~n", [T]),
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),
+ gen(Mode, Spec, ?A(Mod), Path),
ok.
mod(File, error) ->
filename:rootname(filename:basename(File));
mod(_, {ok, Mod}) ->
- atom_to_list(Mod).
+ Mod.
gen(spec, Spec, _Mod, Path) ->
- write(Path ++ ".spec", Spec);
+ write_term(Path ++ ".spec", [?VERSION | 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, compile, [{parse_transform, diameter_nowarn}]},
{?attribute, export, [{name, 0},
{id, 0},
{vendor_id, 0},
@@ -175,7 +173,7 @@ gen(erl, Spec, Mod, Path) ->
gen_erl(Path, insert_hrl_forms(Spec, Forms)).
gen_erl(Path, Forms) ->
- getr(debug) andalso write(Path ++ ".forms", Forms),
+ getr(debug) andalso write_term(Path ++ ".forms", Forms),
write(Path ++ ".erl",
header() ++ erl_prettypr:format(erl_syntax:form_list(Forms))).
@@ -224,16 +222,16 @@ 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)),
+ Name = list_to_atom(Prefix ++ 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)};
+ {?record_field, ?Atom(Name)};
true ->
- {?record_field, ?ATOM(Name), ?NIL}
+ {?record_field, ?Atom(Name), ?NIL}
end.
%%% ------------------------------------------------------------------------
@@ -256,25 +254,33 @@ c_id({ok, Id}) ->
{?clause, [], [], [?INTEGER(Id)]};
c_id(error) ->
- ?UNEXPECTED(0).
+ ?BADARG(0).
%%% ------------------------------------------------------------------------
%%% # vendor_id/0
%%% ------------------------------------------------------------------------
f_vendor_id(Spec) ->
- {Id, _} = orddict:fetch(vendor, Spec),
{?function, vendor_id, 0,
- [{?clause, [], [], [?INTEGER(Id)]}]}.
+ [{?clause, [], [], [b_vendor_id(orddict:find(vendor, Spec))]}]}.
+
+b_vendor_id({ok, {Id, _}}) ->
+ ?INTEGER(Id);
+b_vendor_id(error) ->
+ ?APPLY(erlang, error, [?TERM(undefined)]).
%%% ------------------------------------------------------------------------
%%% # vendor_name/0
%%% ------------------------------------------------------------------------
f_vendor_name(Spec) ->
- {_, Name} = orddict:fetch(vendor, Spec),
{?function, vendor_name, 0,
- [{?clause, [], [], [?ATOM(Name)]}]}.
+ [{?clause, [], [], [b_vendor_name(orddict:find(vendor, Spec))]}]}.
+
+b_vendor_name({ok, {_, Name}}) ->
+ ?Atom(Name);
+b_vendor_name(error) ->
+ ?APPLY(erlang, error, [?TERM(undefined)]).
%%% ------------------------------------------------------------------------
%%% # msg_name/1
@@ -287,22 +293,18 @@ f_msg_name(Spec) ->
%% DIAMETER_COMMAND_UNSUPPORTED should be replied.
msg_name(Spec) ->
- lists:flatmap(fun c_msg_name/1,
- proplists:get_value(command_codes, 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))]},
+ [?Atom(Req)]},
{?clause, [?INTEGER(Code), ?ATOM(false)],
[],
- [?ATOM(mname(Ans))]}].
-
-mname({N, _Abbr}) ->
- N;
-mname(N) ->
- N.
+ [?Atom(Ans)]}].
%%% ------------------------------------------------------------------------
%%% # msg2rec/1
@@ -313,30 +315,11 @@ f_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.
+ lists:map(fun(T) -> c_msg2rec(T, Pre) end, get_value(messages, Spec))
+ ++ [?BADARG(1)].
-c_msg2rec({N,A}, Pre) ->
- [c_name2rec(N, N, Pre), c_name2rec(A, N, Pre)];
-c_msg2rec(N, Pre) ->
- [c_name2rec(N, N, Pre)].
+c_msg2rec({N,_,_,_,_}, Pre) ->
+ c_name2rec(N, Pre).
%%% ------------------------------------------------------------------------
%%% # rec2msg/1
@@ -348,10 +331,10 @@ f_rec2msg(Spec) ->
rec2msg(Spec) ->
Pre = prefix(Spec),
lists:map(fun(T) -> c_rec2msg(T, Pre) end, get_value(messages, Spec))
- ++ [?UNEXPECTED(1)].
+ ++ [?BADARG(1)].
c_rec2msg({N,_,_,_,_}, Pre) ->
- {?clause, [?ATOM(rec_name(N, Pre))], [], [?ATOM(N)]}.
+ {?clause, [?Atom(rec_name(N, Pre))], [], [?Atom(N)]}.
%%% ------------------------------------------------------------------------
%%% # name2rec/1
@@ -364,11 +347,11 @@ 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)
+ lists:map(fun({N,_,_,_}) -> c_name2rec(N, Pre) end, Groups)
++ [{?clause, [?VAR('T')], [], [?CALL(msg2rec, [?VAR('T')])]}].
-c_name2rec(Name, Rname, Pre) ->
- {?clause, [?ATOM(Name)], [], [?ATOM(rec_name(Rname, Pre))]}.
+c_name2rec(Name, Pre) ->
+ {?clause, [?Atom(Name)], [], [?Atom(rec_name(Name, Pre))]}.
avps({_Mod, Avps}) ->
Avps.
@@ -390,32 +373,47 @@ f_avp_name(Spec) ->
%% 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)),
+ Avps = get_value(avp_types, Spec),
+ Imported = get_value(import_avps, Spec),
+ Vid = orddict:find(vendor, Spec),
+ Vs = vendor_id_map(Spec),
- lists:map(fun(T) -> c_avp_name(T, Vid, Vs) end, Avps)
+ lists:map(fun(T) -> c_avp_name(T, Vs, Vid) end, Avps)
+ ++ lists:flatmap(fun(T) -> c_imported_avp_name(T, Vs) end, Imported)
++ [{?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({Name, Code, Type, Flags}, Vs, Vid) ->
+ c_avp_name_(?TERM({?A(Name), ?A(Type)}),
+ ?INTEGER(Code),
+ vid(Name, Flags, Vs, Vid)).
-c_avp_name(T, Code, false, _, undefined = U) ->
- {?clause, [?INTEGER(Code), ?ATOM(U)],
+%% Note that an imported AVP's vendor id is determined by
+%% avp_vendor_id in the inheriting module and vendor in the inherited
+%% module. In particular, avp_vendor_id in the inherited module is
+%% ignored so can't just call Mod:avp_header/1 to retrieve the vendor
+%% id. A vendor id specified in @grouped is equivalent to one
+%% specified as avp_vendor_id.
+
+c_imported_avp_name({Mod, Avps}, Vs) ->
+ lists:map(fun(A) -> c_avp_name(A, Vs, {module, Mod}) end, Avps).
+
+c_avp_name_(T, Code, undefined = U) ->
+ {?clause, [Code, ?ATOM(U)],
[],
- [?TERM(T)]};
+ [T]};
-c_avp_name(T, Code, true, Vid, V)
- when is_integer(Vid) ->
- {?clause, [?INTEGER(Code), ?INTEGER(choose(V == undefined, Vid, V))],
+c_avp_name_(T, Code, Vid) ->
+ {?clause, [Code, ?INTEGER(Vid)],
[],
- [?TERM(T)]}.
+ [T]}.
+
+vendor_id_map(Spec) ->
+ lists:flatmap(fun({V,Ns}) -> [{N,V} || N <- Ns] end,
+ get_value(avp_vendor_id, Spec))
+ ++ lists:flatmap(fun({_,_,[],_}) -> [];
+ ({N,_,[V],_}) -> [{N,V}]
+ end,
+ get_value(grouped, Spec)).
%%% ------------------------------------------------------------------------
%%% # avp_arity/2
@@ -445,60 +443,75 @@ c_avp_arity(Name, Avps) ->
c_arity(Name, Avp) ->
{AvpName, Arity} = avp_info(Avp),
- {?clause, [?ATOM(Name), ?ATOM(AvpName)], [], [?TERM(Arity)]}.
+ {?clause, [?Atom(Name), ?Atom(AvpName)], [], [?TERM(Arity)]}.
%%% ------------------------------------------------------------------------
%%% # avp/3
%%% ------------------------------------------------------------------------
f_avp(Spec) ->
- {?function, avp, 3, avp(Spec) ++ [?UNEXPECTED(3)]}.
+ {?function, avp, 3, avp(Spec) ++ [?BADARG(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).
+ Native = get_value(avp_types, Spec),
+ CustomMods = get_value(custom_types, Spec),
+ TypeMods = get_value(codecs, Spec),
+ Imported = get_value(import_avps, Spec),
+ Enums = get_value(enum, Spec),
-avp(Native, Imported, Custom, Enums) ->
- Dict = orddict:from_list(Native),
+ Custom = lists:map(fun({M,As}) -> {M, custom_types, As} end,
+ CustomMods)
+ ++ lists:map(fun({M,As}) -> {M, codecs, As} end,
+ TypeMods),
+ avp(types(Native), Imported, Custom, Enums).
+
+types(Avps) ->
+ lists:map(fun({N,_,T,_}) -> {N,T} end, Avps).
- report(native, Dict),
+avp(Native, Imported, Custom, Enums) ->
+ report(native, Native),
report(imported, Imported),
report(custom, Custom),
- CustomNames = lists:flatmap(fun({_,Ns}) -> Ns end, Custom),
+ TypeDict = lists:foldl(fun({N,_,T,_}, D) -> orddict:store(N,T,D) end,
+ orddict:from_list(Native),
+ lists:flatmap(fun avps/1, Imported)),
+
+ 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,
+ lists:filter(fun({N,_}) -> not_in(CustomNames, N) end,
Native))
- ++ lists:flatmap(fun(I) -> cs_imported_avp(I, Enums) end, Imported)
- ++ lists:flatmap(fun(C) -> cs_custom_avp(C, Dict) end, Custom).
+ ++ lists:flatmap(fun(I) -> cs_imported_avp(I, Enums, CustomNames) end,
+ Imported)
+ ++ lists:flatmap(fun(C) -> cs_custom_avp(C, TypeDict) end, Custom).
+
+not_in(List, X) ->
+ not lists:member(X, List).
c_base_avp({AvpName, T}) ->
- {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
+ {?clause, [?VAR('T'), ?VAR('Data'), ?Atom(AvpName)],
[],
- [base_avp(AvpName, T)]}.
+ [b_base_avp(AvpName, T)]}.
-base_avp(AvpName, 'Enumerated') ->
- ?CALL(enumerated_avp, [?VAR('T'), ?ATOM(AvpName), ?VAR('Data')]);
+b_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')]);
+b_base_avp(AvpName, "Grouped") ->
+ ?CALL(grouped_avp, [?VAR('T'), ?Atom(AvpName), ?VAR('Data')]);
-base_avp(_, Type) ->
- ?APPLY(diameter_types, Type, [?VAR('T'), ?VAR('Data')]).
+b_base_avp(_, Type) ->
+ ?APPLY(diameter_types, ?A(Type), [?VAR('T'), ?VAR('Data')]).
-cs_imported_avp({Mod, Avps}, Enums) ->
- lists:map(fun(A) -> imported_avp(Mod, A, Enums) end, Avps).
+cs_imported_avp({Mod, Avps}, Enums, CustomNames) ->
+ lists:map(fun(A) -> imported_avp(Mod, A, Enums) end,
+ lists:filter(fun({N,_,_,_}) -> not_in(CustomNames, N) end,
+ Avps)).
-imported_avp(_Mod, {AvpName, _, 'Grouped' = T, _, _}, _) ->
+imported_avp(_Mod, {AvpName, _, "Grouped" = T, _}, _) ->
c_base_avp({AvpName, T});
-imported_avp(Mod, {AvpName, _, 'Enumerated' = T, _, _}, Enums) ->
+imported_avp(Mod, {AvpName, _, "Enumerated" = T, _}, Enums) ->
case lists:keymember(AvpName, 1, Enums) of
true ->
c_base_avp({AvpName, T});
@@ -506,34 +519,40 @@ imported_avp(Mod, {AvpName, _, 'Enumerated' = T, _, _}, Enums) ->
c_imported_avp(Mod, AvpName)
end;
-imported_avp(Mod, {AvpName, _, _, _, _}, _) ->
+imported_avp(Mod, {AvpName, _, _, _}, _) ->
c_imported_avp(Mod, AvpName).
c_imported_avp(Mod, AvpName) ->
- {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
+ {?clause, [?VAR('T'), ?VAR('Data'), ?Atom(AvpName)],
[],
[?APPLY(Mod, avp, [?VAR('T'),
?VAR('Data'),
- ?ATOM(AvpName)])]}.
+ ?Atom(AvpName)])]}.
-cs_custom_avp({Mod, Avps}, Dict) ->
- lists:map(fun(N) -> c_custom_avp(Mod, N, orddict:fetch(N, Dict)) end,
+cs_custom_avp({Mod, Key, Avps}, Dict) ->
+ lists:map(fun(N) -> c_custom_avp(Mod, Key, N, orddict:fetch(N, Dict)) end,
Avps).
-c_custom_avp(Mod, AvpName, Type) ->
- {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
+c_custom_avp(Mod, Key, AvpName, Type) ->
+ {F,A} = custom(Key, AvpName, Type),
+ {?clause, [?VAR('T'), ?VAR('Data'), ?Atom(AvpName)],
[],
- [?APPLY(Mod, AvpName, [?VAR('T'), ?ATOM(Type), ?VAR('Data')])]}.
+ [?APPLY(?A(Mod), ?A(F), [?VAR('T'), ?Atom(A), ?VAR('Data')])]}.
+
+custom(custom_types, AvpName, Type) ->
+ {AvpName, Type};
+custom(codecs, AvpName, Type) ->
+ {Type, AvpName}.
%%% ------------------------------------------------------------------------
%%% # enumerated_avp/3
%%% ------------------------------------------------------------------------
f_enumerated_avp(Spec) ->
- {?function, enumerated_avp, 3, enumerated_avp(Spec) ++ [?UNEXPECTED(3)]}.
+ {?function, enumerated_avp, 3, enumerated_avp(Spec) ++ [?BADARG(3)]}.
enumerated_avp(Spec) ->
- Enums = get_value(enums, Spec),
+ Enums = get_value(enum, 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)).
@@ -554,11 +573,11 @@ 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>>)],
+c_enumerated_avp(AvpName, {_,I}) ->
+ [{?clause, [?ATOM(decode), ?Atom(AvpName), ?TERM(<<I:32/integer>>)],
[],
[?TERM(I)]},
- {?clause, [?ATOM(encode), ?ATOM(AvpName), ?INTEGER(I)],
+ {?clause, [?ATOM(encode), ?Atom(AvpName), ?INTEGER(I)],
[],
[?TERM(<<I:32/integer>>)]}].
@@ -567,7 +586,7 @@ c_enumerated_avp(AvpName, {I,_}) ->
%%% ------------------------------------------------------------------------
f_msg_header(Spec) ->
- {?function, msg_header, 1, msg_header(Spec) ++ [?UNEXPECTED(1)]}.
+ {?function, msg_header, 1, msg_header(Spec) ++ [?BADARG(1)]}.
msg_header(Spec) ->
msg_header(get_value(messages, Spec), Spec).
@@ -582,7 +601,7 @@ msg_header(Msgs, Spec) ->
%% Note that any application id in the message header spec is ignored.
c_msg_header(Name, Code, Flags, ApplId) ->
- {?clause, [?ATOM(Name)],
+ {?clause, [?Atom(Name)],
[],
[?TERM({Code, encode_msg_flags(Flags), ApplId})]}.
@@ -598,50 +617,61 @@ emf('ERR', N) -> N bor 2#00100000.
%%% ------------------------------------------------------------------------
f_avp_header(Spec) ->
- {?function, avp_header, 1, avp_header(Spec) ++ [?UNEXPECTED(1)]}.
+ {?function, avp_header, 1, avp_header(Spec) ++ [?BADARG(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)),
+ Vid = orddict:find(vendor, Spec),
+ Vs = vendor_id_map(Spec),
- lists:flatmap(fun(A) -> c_avp_header({Vid, Vs}, A) end,
+ lists:flatmap(fun(A) -> c_avp_header(A, Vs, Vid) end,
Native ++ Imported).
-c_avp_header({Vid, Vs}, {Name, Code, _Type, Flags, _Encr}) ->
- [{?clause, [?ATOM(Name)],
+c_avp_header({Name, Code, _Type, Flags}, Vs, Vid) ->
+ [{?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({Mod, Avps}, Vs, _Vid) ->
+ lists:map(fun(A) -> c_imported_avp_header(A, Mod, Vs) end, Avps).
-c_avp_header(Vs, Mod, {Name, _, _, Flags, _}) ->
- Apply = ?APPLY(Mod, avp_header, [?ATOM(Name)]),
- {?clause, [?ATOM(Name)],
+%% Note that avp_vendor_id in the inherited dictionary is ignored. The
+%% value must be changed in the inheriting dictionary. This is
+%% consistent with the semantics of avp_name/2.
+
+c_imported_avp_header({Name, _Code, _Type, _Flags}, Mod, Vs) ->
+ 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.
+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(lists:member($V, Flags), Name, Vs, Vid).
+
+v(true = T, Name, Vs, {module, Mod}) ->
+ v(T, Name, Vs, {ok, {Mod:vendor_id(), Mod:vendor_name()}});
v(true, Name, Vs, Vid) ->
- proplists:get_value(Name, Vs, Vid);
+ case proplists:get_value(Name, Vs) of
+ undefined ->
+ {ok, {Id, _}} = Vid,
+ Id;
+ Id ->
+ Id
+ end;
v(false, _, _, _) ->
undefined.
@@ -656,19 +686,19 @@ 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),
+ Enums = [T || {N,_} = T <- get_value(enum, 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)],
+ {?clause, [?Atom(Name)],
[],
- [?CALL(empty_group, [?ATOM(Name)])]};
+ [?CALL(empty_group, [?Atom(Name)])]};
c_empty_value({Name, _}) ->
- {?clause, [?ATOM(Name)],
+ {?clause, [?Atom(Name)],
[],
[?TERM(<<0:32/integer>>)]}.
@@ -678,7 +708,7 @@ c_empty_value({Name, _}) ->
f_dict(Spec) ->
{?function, dict, 0,
- [{?clause, [], [], [?TERM(Spec)]}]}.
+ [{?clause, [], [], [?TERM([?VERSION | Spec])]}]}.
%%% ------------------------------------------------------------------------
%%% # gen_hrl/3
@@ -706,10 +736,10 @@ gen_hrl(Path, Mod, Spec) ->
write("ENUM Macros",
Fd,
- m_enums(PREFIX, false, get_value(enums, Spec))),
- write("RESULT CODE Macros",
+ m_enums(PREFIX, false, get_value(enum, Spec))),
+ write("DEFINE Macros",
Fd,
- m_enums(PREFIX, false, get_value(result_codes, Spec))),
+ m_enums(PREFIX, false, get_value(define, Spec))),
lists:foreach(fun({M,Es}) ->
write("ENUM Macros from " ++ atom_to_list(M),
@@ -751,8 +781,8 @@ m_enums(Prefix, Wrap, 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))), "'"],
+ lists:map(fun({A,I}) ->
+ N = ["'", P, to_upper(z(A)), "'"],
wrap(B,
N,
["-define(", N, ", ", integer_to_list(I), ").\n"])
@@ -794,34 +824,34 @@ header() ->
"%%\n\n").
hrl_header(Name) ->
- header() ++ "-hrl_name('" ++ Name ++ ".hrl').\n".
+ header() ++ "-hrl_name('" ++ ?S(Name) ++ ".hrl').\n".
%% avp_info/1
avp_info(Entry) -> %% {Name, Arity}
case Entry of
- {'<',A,'>'} -> {A, 1};
- {A} -> {A, 1};
- [A] -> {A, {0,1}};
+ {{A}} -> {A, 1};
+ {A} -> {A, 1};
+ [A] -> {A, {0,1}};
{Q,T} ->
{A,_} = avp_info(T),
- {A, arity(Q)}
+ {A, arity(T,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.
+arity({{_}}, '*' = Inf) -> {0, Inf};
+arity([_], '*' = Inf) -> {0, Inf};
+arity({_}, '*' = Inf) -> {1, Inf};
+arity(_, {_,_} = Q) -> Q.
prefix(Spec) ->
case orddict:find(prefix, Spec) of
{ok, P} ->
- atom_to_list(P) ++ "_";
+ P ++ "_";
error ->
""
end.
rec_name(Name, Prefix) ->
- list_to_atom(Prefix ++ atom_to_list(Name)).
+ Prefix ++ Name.
diff --git a/lib/diameter/src/compiler/diameter_dict_parser.yrl b/lib/diameter/src/compiler/diameter_dict_parser.yrl
new file mode 100644
index 0000000000..6fd4cedd23
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_dict_parser.yrl
@@ -0,0 +1,324 @@
+%% -*- 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%
+%%
+
+%%
+%% A grammar for dictionary specification.
+%%
+
+Nonterminals
+ application_id avp avp_code avp_def avp_defs avp_flags avp_header
+ avp_header_tok avp_name avp_names avp_ref avp_spec avp_type
+ avp_vendor avps bit bits command_def command_id diameter_name
+ dictionary enum_def enum_defs group_def group_defs header header_tok
+ ident idents message_defs module qual section sections.
+
+Terminals
+ avp_types avp_vendor_id codecs custom_types define enum grouped
+ id inherits messages name prefix vendor
+ number word
+ '{' '}' '<' '>' '[' ']' '*' '::=' ':' ',' '-'
+ code
+ 'answer-message'
+ 'AVP' 'AVP-Header'
+ 'Diameter' 'Diameter-Header' 'Header'
+ 'REQ' 'PXY' 'ERR'.
+
+Rootsymbol dictionary.
+
+Endsymbol '$end'.
+
+%% ===========================================================================
+
+dictionary -> sections : '$1'.
+
+sections -> '$empty' : [].
+sections -> section sections : ['$1' | '$2'].
+
+section -> name ident : ['$1', '$2'].
+section -> prefix ident : ['$1', '$2'].
+section -> id number : ['$1', '$2'].
+section -> vendor number ident : ['$1', '$2', '$3'].
+section -> inherits module avp_names : ['$1', '$2' | '$3'].
+section -> avp_types avp_defs : ['$1' | '$2'].
+section -> avp_vendor_id number avp_names : ['$1', '$2' | '$3'].
+section -> custom_types module avp_names : ['$1', '$2' | '$3'].
+section -> codecs module avp_names : ['$1', '$2' | '$3'].
+section -> messages message_defs : ['$1' | '$2'].
+section -> grouped group_defs : ['$1' | '$2'].
+section -> enum ident enum_defs : ['$1', '$2' | '$3'].
+section -> define ident enum_defs : ['$1', '$2' | '$3'].
+
+%% =====================================
+
+module -> ident : '$1'.
+
+avp_names -> idents : '$1'. %% Note: not 'AVP'
+
+avp_defs -> '$empty' : [].
+avp_defs -> avp_def avp_defs : ['$1' | '$2'].
+
+avp_def -> ident number avp_type avp_flags : ['$1', '$2', '$3', '$4'].
+
+avp_type -> ident : '$1'.
+
+idents -> '$empty' : [].
+idents -> ident idents : ['$1' | '$2'].
+
+avp_flags -> '-' :
+ {_, Lineno} = '$1',
+ {word, Lineno, ""}.
+avp_flags -> ident :
+ '$1'.
+%% 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.
+
+ident -> word : '$1'.
+
+%% Don't bother mapping reserved words to make these usable in this
+%% context. That an AVP can't be named Diameter-Header is probably no
+%% great loss, and that it can't be named AVP may even save someone
+%% from themselves. (Temporarily at least.)
+
+group_defs -> '$empty' : [].
+group_defs -> group_def group_defs : ['$1' | '$2'].
+
+message_defs -> '$empty' : [].
+message_defs -> command_def message_defs : ['$1' | '$2'].
+
+enum_defs -> '$empty' : [].
+enum_defs -> enum_def enum_defs : ['$1' | '$2'].
+
+enum_def -> ident number : ['$1', '$2'].
+
+%% =====================================
+%% 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
+%%
+%% diameter-name = ALPHA *(ALPHA / DIGIT / "-")
+%%
+%% diameter-message = header [ *fixed] [ *required] [ *optional]
+
+%% answer-message is a special case.
+command_def -> 'answer-message' '::=' '<' header_tok ':' code
+ ',' 'ERR' '[' 'PXY' ']' '>'
+ avps
+ : ['$1', false | '$13'].
+
+command_def -> diameter_name '::=' header avps
+ : ['$1', '$3' | '$4'].
+%% Ensure the order fixed/required/optional by semantic checks rather
+%% than grammatically since the latter requires more lookahead: don't
+%% know until after a leading qual which of the three it is that's
+%% being parsed.
+
+diameter_name -> ident : '$1'.
+
+%% header = "<" "Diameter Header:" command-id
+%% [r-bit] [p-bit] [e-bit] [application-id] ">"
+%%
+%% 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.
+%%
+%% application-id = 1*DIGIT
+
+header -> '<' header_tok ':' command_id bits application_id '>'
+ : ['$4', '$5', '$6'].
+
+command_id -> number : '$1'.
+
+%% Accept both the form of the base definition and the typo (fixed in
+%% 3588bis) of the grammar.
+header_tok -> 'Diameter' 'Header'.
+header_tok -> 'Diameter-Header'.
+
+bits -> '$empty' : [].
+bits -> ',' bit bits : ['$2' | '$3'].
+
+%% ERR only makes sense for answer-message so don't allow it here
+%% (despite 3588).
+bit -> 'REQ' : '$1'.
+bit -> 'PXY' : '$1'.
+
+application_id -> '$empty' : false.
+application_id -> number : '$1'.
+
+%% 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'.
+
+avps -> '$empty' : [].
+avps -> avp avps : ['$1' | '$2'].
+
+avp -> avp_ref : [false | '$1'].
+avp -> qual avp_ref : ['$1' | '$2'].
+
+avp_ref -> '<' avp_spec '>' : [$<, '$2'].
+avp_ref -> '{' avp_name '}' : [${, '$2'].
+avp_ref -> '[' avp_name ']' : [$[, '$2'].
+%% Note that required can be an avp_name, not just avp_spec. 'AVP'
+%% is specified as required by Failed-AVP for example.
+
+%% 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.
+
+qual -> number '*' number : {'$1', '$3'}.
+qual -> number '*' : {'$1', true}.
+qual -> '*' number : {true, '$2'}.
+qual -> '*' : true.
+
+%% avp-spec = diameter-name
+%% ; The avp-spec has to be an AVP Name, defined
+%% ; in the base or extended Diameter
+%% ; specifications.
+
+avp_spec -> diameter_name : '$1'.
+
+%% 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.
+
+avp_name -> 'AVP' : '$1'.
+avp_name -> avp_spec : '$1'.
+
+%% The following is a definition of a fictitious command code:
+%%
+%% Example-Request ::= < Diameter Header: 9999999, REQ, PXY >
+%% { User-Name }
+%% * { Origin-Host }
+%% * [ AVP ]
+
+%% =====================================
+%% 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.
+
+%% 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]
+
+group_def -> ident '::=' avp_header avps : ['$1', '$3' | '$4'].
+
+%% 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.
+
+avp_header -> '<' avp_header_tok ':' avp_code avp_vendor '>'
+ : ['$4', '$5'].
+
+avp_header_tok -> 'AVP-Header'.
+avp_header_tok -> 'AVP' 'Header'.
+
+avp_code -> number : '$1'.
+
+avp_vendor -> '$empty' : false.
+avp_vendor -> number : '$1'.
diff --git a/lib/diameter/src/compiler/diameter_dict_scanner.erl b/lib/diameter/src/compiler/diameter_dict_scanner.erl
new file mode 100644
index 0000000000..45189376fb
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_dict_scanner.erl
@@ -0,0 +1,276 @@
+%%
+%% %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_dict_scanner).
+
+%%
+%% A scanner for dictionary files of the form expected by yecc.
+%%
+
+-export([scan/1,
+ format_error/1]).
+
+-export([is_name/1]).
+
+%% -----------------------------------------------------------
+%% # scan/1
+%% -----------------------------------------------------------
+
+-spec scan(string() | binary())
+ -> {ok, [Token]}
+ | {error, {string(), string(), Lineno}}
+ when Token :: {word, Lineno, string()}
+ | {number, Lineno, non_neg_integer()}
+ | {Symbol, Lineno},
+ Lineno :: pos_integer(),
+ Symbol :: '{' | '}' | '<' | '>' | '[' | ']'
+ | '*' | '::=' | ':' | ',' | '-'
+ | avp_types
+ | avp_vendor_id
+ | codecs
+ | custom_types
+ | define
+ | grouped
+ | id
+ | inherits
+ | messages
+ | name
+ | prefix
+ | vendor
+ | '$end'
+ | code
+ | 'answer-message'
+ | 'AVP'
+ | 'AVP-Header'
+ | 'Diameter'
+ | 'Diameter-Header'
+ | 'Header'
+ | 'REQ'
+ | 'PXY'
+ | 'ERR'.
+
+scan(B)
+ when is_binary(B) ->
+ scan(binary_to_list(B));
+scan(S) ->
+ scan(S, {1, []}).
+
+scan(S, {Lineno, Acc}) ->
+ case split(S) of
+ '$end' = E ->
+ {ok, lists:reverse([{E, Lineno} | Acc])};
+ {Tok, Rest} ->
+ scan(Rest, acc(Tok, Lineno, Acc));
+ Reason when is_list(Reason) ->
+ {error, {Reason, S, Lineno}}
+ end.
+
+%% format_error/1
+
+format_error({Reason, Input, Lineno}) ->
+ io_lib:format("~s at line ~p: ~s",
+ [Reason, Lineno, head(Input, [], 20, true)]).
+
+%% is_name/1
+
+is_name([H|T]) ->
+ is_alphanum(H) andalso lists:all(fun is_name_ch/1, T).
+
+%% ===========================================================================
+
+head(Str, Acc, N, _)
+ when [] == Str;
+ 0 == N;
+ $\r == hd(Str);
+ $\n == hd(Str) ->
+ lists:reverse(Acc);
+head([C|Rest], Acc, N, true = T) %% skip leading whitespace
+ when C == $\s;
+ C == $\t;
+ C == $\f;
+ C == $\v ->
+ head(Rest, Acc, N, T);
+head([C|Rest], Acc, N, _) ->
+ head(Rest, [C|Acc], N-1, false).
+
+acc(endline, Lineno, Acc) ->
+ {Lineno + 1, Acc};
+acc(T, Lineno, Acc) ->
+ {Lineno, [tok(T, Lineno) | Acc]}.
+
+tok({Cat, Sym}, Lineno) ->
+ {Cat, Lineno, Sym};
+tok(Sym, Lineno) ->
+ {Sym, Lineno}.
+
+%% # split/1
+%%
+%% Output: {Token, Rest} | atom()
+
+%% Finito.
+split("") ->
+ '$end';
+
+%% Skip comments. This precludes using semicolon for any other purpose.
+split([$;|T]) ->
+ split(lists:dropwhile(fun(C) -> not is_eol_ch(C) end, T));
+
+%% Beginning of a section.
+split([$@|T]) ->
+ {Name, Rest} = lists:splitwith(fun is_name_ch/1, T),
+ case section(Name) of
+ false ->
+ "Unknown section";
+ 'end' ->
+ '$end';
+ A ->
+ {A, Rest}
+ end;
+
+split("::=" ++ T) ->
+ {'::=', T};
+
+split([H|T])
+ when H == ${; H == $};
+ H == $<; H == $>;
+ H == $[; H == $];
+ H == $*; H == $:; H == $,; H == $- ->
+ {list_to_atom([H]), T};
+
+%% RFC 3588 requires various names to begin with a letter but 3GPP (for
+%% one) abuses this. (eg 3GPP-Charging-Id in TS32.299.)
+split([H|_] = L) when $0 =< H, H =< $9 ->
+ {P, Rest} = splitwith(fun is_name_ch/1, L),
+ Tok = try
+ {number, read_int(P)}
+ catch
+ error:_ ->
+ word(P)
+ end,
+ {Tok, Rest};
+
+split([H|_] = L) when $a =< H, H =< $z;
+ $A =< H, H =< $Z ->
+ {P, Rest} = splitwith(fun is_name_ch/1, L),
+ {word(P), Rest};
+
+split([$'|T]) ->
+ case lists:splitwith(fun(C) -> not lists:member(C, "'\r\n") end, T) of
+ {[_|_] = A, [$'|Rest]} ->
+ {{word, A}, Rest};
+ {[], [$'|_]} ->
+ "Empty string";
+ _ -> %% not terminated on same line
+ "Unterminated string"
+ end;
+
+%% Line ending of various forms.
+split([$\r,$\n|T]) ->
+ {endline, T};
+split([C|T])
+ when C == $\r;
+ C == $\n ->
+ {endline, T};
+
+%% Ignore whitespace.
+split([C|T])
+ when C == $\s;
+ C == $\t;
+ C == $\f;
+ C == $\v ->
+ split(T);
+
+split(_) ->
+ "Unexpected character".
+
+%% word/1
+
+%% Reserved words significant in parsing ...
+word(S)
+ when S == "answer-message";
+ S == "code";
+ S == "AVP";
+ S == "AVP-Header";
+ S == "Diameter";
+ S == "Diameter-Header";
+ S == "Header";
+ S == "REQ";
+ S == "PXY";
+ S == "ERR" ->
+ list_to_atom(S);
+
+%% ... or not.
+word(S) ->
+ {word, S}.
+
+%% section/1
+
+section(N)
+ when N == "avp_types";
+ N == "avp_vendor_id";
+ N == "codecs";
+ N == "custom_types";
+ N == "define";
+ N == "end";
+ N == "enum";
+ N == "grouped";
+ N == "id";
+ N == "inherits";
+ N == "messages";
+ N == "name";
+ N == "prefix";
+ N == "vendor" ->
+ list_to_atom(N);
+section(_) ->
+ false.
+
+%% 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, [H|T]) ->
+ {SH, ST} = lists:splitwith(Fun, T),
+ {[H|SH], ST}.
+
+is_eol_ch(C) ->
+ C == $\n orelse C == $\r.
+
+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_dict_util.erl b/lib/diameter/src/compiler/diameter_dict_util.erl
new file mode 100644
index 0000000000..36a6efa294
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_dict_util.erl
@@ -0,0 +1,1358 @@
+%%
+%% %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 dictionary 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_dict_util).
+
+-export([parse/2,
+ format_error/1,
+ format/1]).
+
+-include("diameter_vsn.hrl").
+
+-define(RETURN(T), throw({T, ?MODULE, ?LINE})).
+-define(RETURN(T, Args), ?RETURN({T, Args})).
+
+-define(A, list_to_atom).
+-define(L, atom_to_list).
+-define(I, integer_to_list).
+-define(F, io_lib:format).
+
+%% ===========================================================================
+%% parse/2
+%% ===========================================================================
+
+-spec parse(File, Opts)
+ -> {ok, orddict:orddict()}
+ | {error, term()}
+ when File :: {path, string()}
+ | iolist()
+ | binary(),
+ Opts :: list().
+
+parse(File, Opts) ->
+ putr(verbose, lists:member(verbose, Opts)),
+ try
+ {ok, do_parse(File, Opts)}
+ catch
+ {Reason, ?MODULE, _Line} ->
+ {error, Reason}
+ after
+ eraser(verbose)
+ end.
+
+%% ===========================================================================
+%% format_error/1
+%% ===========================================================================
+
+format_error({read, Reason}) ->
+ file:format_error(Reason);
+format_error({scan, Reason}) ->
+ diameter_dict_scanner:format_error(Reason);
+format_error({parse, {Line, _Mod, Reason}}) ->
+ lists:flatten(["Line ", ?I(Line), ", ", Reason]);
+
+format_error(T) ->
+ {Fmt, As} = fmt(T),
+ lists:flatten(io_lib:format(Fmt, As)).
+
+fmt({avp_code_already_defined = E, [Code, false, Name, Line, L]}) ->
+ {fmt(E), [Code, "", Name, Line, L]};
+fmt({avp_code_already_defined = E, [Code, Vid, Name, Line, L]}) ->
+ {fmt(E), [Code, ?F("/~p", [Vid]), Name, Line, L]};
+
+fmt({uint32_out_of_range = E, [id | T]}) ->
+ {fmt(E), ["@id", "application identifier" | T]};
+fmt({uint32_out_of_range = E, [K | T]})
+ when K == vendor;
+ K == avp_vendor_id ->
+ {fmt(E), [?F("@~p", [K]), "vendor id" | T]};
+fmt({uint32_out_of_range = E, [K, Name | T]})
+ when K == enum;
+ K == define ->
+ {fmt(E), [?F("@~p ~s", [K, Name]), "value" | T]};
+fmt({uint32_out_of_range = E, [avp_types, Name | T]}) ->
+ {fmt(E), ["AVP " ++ Name, "AVP code" | T]};
+fmt({uint32_out_of_range = E, [grouped, Name | T]}) ->
+ {fmt(E), ["Grouped AVP " ++ Name | T]};
+fmt({uint32_out_of_range = E, [messages, Name | T]}) ->
+ {fmt(E), ["Message " ++ Name, "command code" | T]};
+
+fmt({Reason, As}) ->
+ {fmt(Reason), As};
+
+fmt(avp_code_already_defined) ->
+ "AVP ~p~s (~s) at line ~p already defined at line ~p";
+
+fmt(uint32_out_of_range) ->
+ "~s specifies ~s ~p at line ~p that is out of range for a value of "
+ "Diameter type Unsigned32";
+
+fmt(imported_avp_already_defined) ->
+ "AVP ~s imported by @inherits ~p at line ~p defined at line ~p";
+fmt(duplicate_import) ->
+ "AVP ~s is imported by more than one @inherits, both at line ~p "
+ "and at line ~p";
+
+fmt(duplicate_section) ->
+ "Section @~s at line ~p already declared at line ~p";
+
+fmt(already_declared) ->
+ "Section @~p ~s at line ~p already declared at line ~p";
+
+fmt(inherited_avp_already_defined) ->
+ "AVP ~s inherited at line ~p defined in @avp_types at line ~p";
+fmt(avp_already_defined) ->
+ "AVP ~s at line ~p already in @~p at line ~p";
+fmt(key_already_defined) ->
+ "Value for ~s:~s in @~p at line ~p already provided at line ~p";
+
+fmt(messages_without_id) ->
+ "@messages at line ~p but @id not declared";
+
+fmt(avp_name_already_defined) ->
+ "AVP ~s at line ~p already defined at line ~p";
+fmt(avp_has_unknown_type) ->
+ "AVP ~s at line ~p defined with unknown type ~s";
+fmt(avp_has_invalid_flag) ->
+ "AVP ~s at line ~p specifies invalid flag ~c";
+fmt(avp_has_duplicate_flag) ->
+ "AVP ~s at line ~p specifies duplicate flag ~c";
+fmt(avp_has_vendor_id) ->
+ "AVP ~s at line ~p does not specify V flag "
+ "but is assigned vendor id ~p at line ~p";
+fmt(avp_has_no_vendor) ->
+ "AVP ~s at line ~p specifies V flag "
+ "but neither @vendor_avp_id nor @vendor supplies a value";
+
+fmt(group_already_defined) ->
+ "Group ~s at line ~p already defined at line ~p";
+fmt(grouped_avp_code_mismatch) ->
+ "AVP ~s at line ~p has with code ~p "
+ "but @avp_types specifies ~p at line ~p";
+fmt(grouped_avp_has_wrong_type) ->
+ "Grouped AVP ~s at line ~p defined with type ~s at line ~p";
+fmt(grouped_avp_not_defined) ->
+ "Grouped AVP ~s on line ~p not defined in @avp_types";
+fmt(grouped_vendor_id_without_flag) ->
+ "Grouped AVP ~s at line ~p has vendor id "
+ "but definition at line ~p does not specify V flag";
+fmt(grouped_vendor_id_mismatch) ->
+ "Grouped AVP ~s at line ~p has vendor id ~p "
+ "but ~p specified at line ~p";
+
+fmt(message_name_already_defined) ->
+ "Message ~s at line ~p already defined at line ~p";
+fmt(message_code_already_defined) ->
+ "~s message with code ~p at line ~p already defined at line ~p";
+fmt(message_has_duplicate_flag) ->
+ "Message ~s has duplicate flag ~s at line ~p";
+fmt(message_application_id_mismatch) ->
+ "Message ~s has application id ~p at line ~p "
+ "but @id specifies ~p at line ~p";
+
+fmt(invalid_avp_order) ->
+ "AVP reference ~c~s~c at line ~p breaks fixed/required/optional order";
+fmt(required_avp_has_zero_max_arity) ->
+ "Required AVP has maximum arity 0 at line ~p";
+fmt(required_avp_has_zero_min_arity) ->
+ "Required AVP has minimum arity 0 at line ~p";
+fmt(optional_avp_has_nonzero_min_arity) ->
+ "Optional AVP has non-zero minimum arity at line ~p";
+fmt(qualifier_has_min_greater_than_max) ->
+ "Qualifier ~p*~p at line ~p has Min > Max";
+fmt(avp_already_referenced) ->
+ "AVP ~s at line ~p already referenced at line ~p";
+
+fmt(message_missing) ->
+ "~s message at line ~p but no ~s message is defined";
+
+fmt(requested_avp_not_found) ->
+ "@inherit ~s at line ~p requests AVP ~s at line ~p "
+ "but module does not define that AVP";
+
+fmt(enumerated_avp_has_wrong_local_type) ->
+ "Enumerated AVP ~s in @enum at line ~p defined with type ~s at line ~p";
+fmt(enumerated_avp_has_wrong_inherited_type) ->
+ "Enumerated AVP ~s in @enum at line ~p "
+ "inherited with type ~s from module ~s at line ~p";
+fmt(enumerated_avp_not_defined) ->
+ "Enumerated AVP ~s in @enum at line ~p neither defined nor inherited";
+
+fmt(avp_not_defined) ->
+ "AVP ~s referenced at line ~p neither defined nor inherited";
+
+fmt(recompile) ->
+ "Module ~p appears to have been compiler with an incompatible "
+ "version of the dictionary compiler and must be recompiled";
+fmt(not_loaded) ->
+ "Module ~p is not on the code path or could not be loaded";
+fmt(no_dict) ->
+ "Module ~p does not appear to be a diameter dictionary".
+
+%% ===========================================================================
+%% format/1
+%%
+%% Turn dict/0 output back into a dictionary file (with line ending = $\n).
+
+-spec format(Dict)
+ -> iolist()
+ when Dict :: orddict:orddict().
+
+-define(KEYS, [id, name, prefix, vendor,
+ inherits, codecs, custom_types,
+ avp_types,
+ messages,
+ grouped,
+ enum, define]).
+
+format(Dict) ->
+ Io = orddict:fold(fun io/3, [], Dict),
+ [S || {_,S} <- lists:sort(fun keysort/2, Io)].
+
+keysort({A,_}, {B,_}) ->
+ [HA, HB] = [H || K <- [A,B],
+ H <- [lists:takewhile(fun(X) -> X /= K end, ?KEYS)]],
+ HA < HB.
+
+%% ===========================================================================
+
+-define(INDENT, " ").
+-define(SP, " ").
+-define(NL, $\n).
+
+%% io/3
+
+io(K, _, Acc)
+ when K == command_codes;
+ K == import_avps;
+ K == import_groups;
+ K == import_enums ->
+ Acc;
+
+io(Key, Body, Acc) ->
+ [{Key, io(Key, Body)} | Acc].
+
+%% io/2
+
+io(K, Id)
+ when K == id;
+ K == name;
+ K == prefix ->
+ [?NL, section(K), ?SP, tok(Id)];
+
+io(vendor = K, {Id, Name}) ->
+ [?NL, section(K) | [[?SP, tok(X)] || X <- [Id, Name]]];
+
+io(avp_types = K, Body) ->
+ [?NL, ?NL, section(K), ?NL, [body(K,A) || A <- Body]];
+
+io(K, Body)
+ when K == messages;
+ K == grouped ->
+ [?NL, ?NL, section(K), [body(K,A) || A <- Body]];
+
+io(K, Body)
+ when K == avp_vendor_id;
+ K == inherits;
+ K == custom_types;
+ K == codecs;
+ K == enum;
+ K == define ->
+ [[?NL, pairs(K, T)] || T <- Body].
+
+pairs(K, {Id, Avps}) ->
+ [?NL, section(K), ?SP, tok(Id), ?NL, [[?NL, body(K, A)] || A <- Avps]].
+
+body(K, AvpName)
+ when K == avp_vendor_id;
+ K == inherits;
+ K == custom_types;
+ K == codecs ->
+ [?INDENT, word(AvpName)];
+
+body(K, {Name, N})
+ when K == enum;
+ K == define ->
+ [?INDENT, word(Name), ?SP, ?I(N)];
+
+body(avp_types = K, {Name, Code, Type, ""}) ->
+ body(K, {Name, Code, Type, "-"});
+body(avp_types, {Name, Code, Type, Flags}) ->
+ [?NL, ?INDENT, word(Name),
+ [[?SP, ?SP, S] || S <- [?I(Code), Type, Flags]]];
+
+body(messages, {"answer-message", _, _, [], Avps}) ->
+ [?NL, ?NL, ?INDENT,
+ "answer-message ::= < Diameter Header: code, ERR [PXY] >",
+ f_avps(Avps)];
+body(messages, {Name, Code, Flags, ApplId, Avps}) ->
+ [?NL, ?NL, ?INDENT, word(Name), " ::= ", header(Code, Flags, ApplId),
+ f_avps(Avps)];
+
+body(grouped, {Name, Code, Vid, Avps}) ->
+ [?NL, ?NL, ?INDENT, word(Name), " ::= ", avp_header(Code, Vid),
+ f_avps(Avps)].
+
+header(Code, Flags, ApplId) ->
+ ["< Diameter Header: ",
+ ?I(Code),
+ [[", ", ?L(F)] || F <- Flags],
+ [[" ", ?I(N)] || N <- ApplId],
+ " >"].
+
+avp_header(Code, Vid) ->
+ ["< AVP Header: ",
+ ?I(Code),
+ [[" ", ?I(V)] || V <- Vid],
+ " >"].
+
+f_avps(L) ->
+ [[?NL, ?INDENT, ?INDENT, f_avp(A)] || A <- L].
+
+f_avp({Q, A}) ->
+ [D | _] = Avp = f_delim(A),
+ f_avp(f_qual(D, Q), Avp);
+f_avp(A) ->
+ f_avp("", f_delim(A)).
+
+f_delim({{A}}) ->
+ [$<, word(A), $>];
+f_delim({A}) ->
+ [${, word(A), $}];
+f_delim([A]) ->
+ [$[, word(A), $]].
+
+f_avp(Q, [L, Avp, R]) ->
+ Len = length(lists:flatten([Q])),
+ [io_lib:format("~*s", [-1*max(Len+1, 6) , Q]), L, " ", Avp, " ", R].
+
+f_qual(${, '*') ->
+ "1*"; %% Equivalent to "*" but the more common/obvious rendition
+f_qual(_, '*') ->
+ "*";
+f_qual(_, {'*', N}) ->
+ [$*, ?I(N)];
+f_qual(_, {N, '*'}) ->
+ [?I(N), $*];
+f_qual(_, {M,N}) ->
+ [?I(M), $*, ?I(N)].
+
+section(Key) ->
+ ["@", ?L(Key)].
+
+tok(N)
+ when is_integer(N) ->
+ ?I(N);
+tok(N) ->
+ word(N).
+
+word(Str) ->
+ word(diameter_dict_scanner:is_name(Str), Str).
+
+word(true, Str) ->
+ Str;
+word(false, Str) ->
+ [$', Str, $'].
+
+%% ===========================================================================
+
+do_parse(File, Opts) ->
+ Bin = do([fun read/1, File], read),
+ Toks = do([fun diameter_dict_scanner:scan/1, Bin], scan),
+ Tree = do([fun diameter_dict_parser:parse/1, Toks], parse),
+ make_dict(Tree, Opts).
+
+do([F|A], E) ->
+ case apply(F,A) of
+ {ok, T} ->
+ T;
+ {error, Reason} ->
+ ?RETURN({E, Reason})
+ end.
+
+read({path, Path}) ->
+ file:read_file(Path);
+read(File) ->
+ {ok, iolist_to_binary([File])}.
+
+make_dict(Parse, Opts) ->
+ make_orddict(pass4(pass3(pass2(pass1(reset(make_dict(Parse),
+ Opts))),
+ Opts))).
+
+%% make_orddict/1
+
+make_orddict(Dict) ->
+ dict:fold(fun mo/3,
+ orddict:from_list([{K,[]} || K <- [avp_types,
+ messages,
+ grouped,
+ inherits,
+ custom_types,
+ codecs,
+ avp_vendor_id,
+ enum,
+ define]]),
+ Dict).
+
+mo(K, Sects, Dict)
+ when is_atom(K) ->
+ orddict:store(K, make(K, Sects), Dict);
+
+mo(_, _, Dict) ->
+ Dict.
+
+make(K, [[_Line, {_, _, X}]])
+ when K == id;
+ K == name;
+ K == prefix ->
+ X;
+
+make(vendor, [[_Line, {_, _, Id}, {_, _, Name}]]) ->
+ {Id, Name};
+
+make(K, T)
+ when K == command_codes;
+ K == import_avps;
+ K == import_groups;
+ K == import_enums ->
+ T;
+
+make(K, Sects) ->
+ post(K, foldl(fun([_L|B], A) -> make(K,B,A) end,
+ [],
+ Sects)).
+
+post(avp_types, L) ->
+ lists:sort(L);
+
+post(K, L)
+ when K == grouped;
+ K == messages;
+ K == enum;
+ K == define ->
+ lists:reverse(L);
+
+post(_, L) ->
+ L.
+
+make(K, [{_,_,Name} | Body], Acc)
+ when K == enum;
+ K == define;
+ K == avp_vendor_id;
+ K == custom_types;
+ K == inherits;
+ K == codecs ->
+ [{Name, mk(K, Body)} | Acc];
+
+make(K, Body, Acc) ->
+ foldl(fun(T,A) -> [mk(K, T) | A] end, Acc, Body).
+
+mk(avp_types, [{_,_,Name}, {_,_,Code}, {_,_,Type}, {_,_,Flags}]) ->
+ {Name, Code, type(Type), Flags};
+
+mk(messages, [{'answer-message' = A, _}, false | Avps]) ->
+ {?L(A), -1, ['ERR', 'PXY'], [], make_body(Avps)};
+
+mk(messages, [{_,_,Name}, [{_,_,Code}, Flags, ApplId] | Avps]) ->
+ {Name,
+ Code,
+ lists:map(fun({F,_}) -> F end, Flags),
+ opt(ApplId),
+ make_body(Avps)};
+
+mk(grouped, [{_,_,Name}, [{_,_,Code}, Vid] | Avps]) ->
+ {Name, Code, opt(Vid), make_body(Avps)};
+
+mk(K, Body)
+ when K == enum;
+ K == define ->
+ lists:map(fun([{_,_,Name}, {_,_,Value}]) -> {Name, Value} end, Body);
+
+mk(K, Avps)
+ when K == avp_vendor_id;
+ K == custom_types;
+ K == inherits;
+ K == codecs ->
+ lists:map(fun({_,_,N}) -> N end, Avps).
+
+opt(false) ->
+ [];
+opt({_,_,X}) ->
+ [X].
+
+make_body(Avps) ->
+ lists:map(fun avp/1, Avps).
+
+avp([false, D, Avp]) ->
+ avp(D, Avp);
+avp([Q, D, Avp]) ->
+ case {qual(D, Q), avp(D, Avp)} of
+ {{0,1}, A} when D == $[ ->
+ A;
+ {{1,1}, A} ->
+ A;
+ T ->
+ T
+ end.
+%% Could just store the qualifier as a pair in all cases but the more
+%% compact form is easier to parse visually so live with a bit of
+%% mapping. Ditto the use of '*'.
+
+avp(D, {'AVP', _}) ->
+ delim(D, "AVP");
+avp(D, {_, _, Name}) ->
+ delim(D, Name).
+
+delim($<, N) ->
+ {{N}};
+delim(${, N) ->
+ {N};
+delim($[, N) ->
+ [N].
+
+%% There's a difference between max = 0 and not specifying an AVP:
+%% reception of an AVP with max = 0 will always be an error, otherwise
+%% it depends on the existence of 'AVP' and the M flag.
+
+qual(${, {{_,L,0}, _}) ->
+ ?RETURN(required_avp_has_zero_min_arity, [L]);
+qual(${, {_, {_,L,0}}) ->
+ ?RETURN(required_avp_has_zero_max_arity, [L]);
+
+qual($[, {{_,L,N}, _})
+ when 0 < N ->
+ ?RETURN(optional_avp_has_nonzero_min_arity, [L]);
+
+qual(_, {{_,L,Min}, {_,_,Max}})
+ when Min > Max ->
+ ?RETURN(qualifier_has_min_greater_than_max, [Min, Max, L]);
+
+qual(_, true) ->
+ '*';
+
+qual(${, {true, {_,_,N}}) ->
+ {1, N};
+qual(_, {true, {_,_,N}}) ->
+ {0, N};
+
+qual(D, {{_,_,N}, true})
+ when D == ${, N == 1;
+ D /= ${, N == 0 ->
+ '*';
+qual(_, {{_,_,N}, true}) ->
+ {N, '*'};
+
+qual(_, {{_,_,Min}, {_,_,Max}}) ->
+ {Min, Max}.
+
+%% Optional reports when running verbosely.
+report(What, [F | A])
+ when is_function(F) ->
+ report(What, apply(F, A));
+report(What, Data) ->
+ report(getr(verbose), What, Data).
+
+report(true, Tag, Data) ->
+ io:format("##~n## ~p ~p~n", [Tag, Data]);
+report(false, _, _) ->
+ ok.
+
+%% ------------------------------------------------------------------------
+%% make_dict/1
+%%
+%% Turn a parsed dictionary into an dict.
+
+make_dict(Parse) ->
+ foldl(fun(T,A) ->
+ report(section, T),
+ section(T,A)
+ end,
+ dict:new(),
+ Parse).
+
+section([{T, L} | Rest], Dict)
+ when T == name;
+ T == prefix;
+ T == id;
+ T == vendor ->
+ case find(T, Dict) of
+ [] ->
+ dict:store(T, [[L | Rest]], Dict);
+ [[Line | _]] ->
+ ?RETURN(duplicate_section, [T, L, Line])
+ end;
+
+section([{T, L} | Rest], Dict)
+ when T == avp_types;
+ T == messages;
+ T == grouped;
+ T == inherits;
+ T == custom_types;
+ T == codecs;
+ T == avp_vendor_id;
+ T == enum;
+ T == define ->
+ dict:append(T, [L | Rest], Dict).
+
+%% ===========================================================================
+%% reset/2
+%%
+%% Reset sections from options.
+
+reset(Dict, Opts) ->
+ foldl([fun reset/3, Opts], Dict, [name, prefix, inherits]).
+
+reset(K, Dict, Opts) ->
+ foldl(fun opt/2, Dict, [T || {A,_} = T <- Opts, A == K]).
+
+opt({inherits = Key, "-"}, Dict) ->
+ dict:erase(Key, Dict);
+
+opt({inherits = Key, Mod}, Dict) ->
+ case lists:splitwith(fun(C) -> C /= $/ end, Mod) of
+ {Mod, ""} ->
+ dict:append(Key, [0, {word, 0, Mod}], Dict);
+ {From, [$/|To]} ->
+ dict:store(Key,
+ [reinherit(From, To, M) || M <- find(Key, Dict)],
+ Dict)
+ end;
+
+opt({Key, Val}, Dict) ->
+ dict:store(Key, [[0, {word, 0, Val}]], Dict);
+
+opt(_, Dict) ->
+ Dict.
+
+reinherit(From, To, [L, {word, _, From} = T | Avps]) ->
+ [L, setelement(3, T, To) | Avps];
+reinherit(_, _, T) ->
+ T.
+
+%% ===========================================================================
+%% pass1/1
+%%
+%% Explode sections into additional dictionary entries plus semantic
+%% checks.
+
+pass1(Dict) ->
+ true = no_messages_without_id(Dict),
+
+ foldl(fun(K,D) -> foldl([fun p1/3, K], D, find(K,D)) end,
+ Dict,
+ [id,
+ vendor,
+ avp_types, %% must precede inherits, grouped, enum
+ avp_vendor_id,
+ custom_types,
+ codecs,
+ inherits,
+ grouped,
+ messages,
+ enum,
+ define]).
+
+%% Multiple sections are allowed as long as their bodies don't
+%% overlap. (Except enum/define.)
+
+p1([_Line, N], Dict, id = K) ->
+ true = is_uint32(N, [K]),
+ Dict;
+
+p1([_Line, Id, _Name], Dict, vendor = K) ->
+ true = is_uint32(Id, [K]),
+ Dict;
+
+p1([_Line, X | Body], Dict, K)
+ when K == avp_vendor_id;
+ K == custom_types;
+ K == codecs;
+ K == inherits ->
+ foldl([fun explode/4, X, K], Dict, Body);
+
+p1([_Line, X | Body], Dict, K)
+ when K == define;
+ K == enum ->
+ {_, L, Name} = X,
+ foldl([fun explode2/4, X, K],
+ store_new({K, Name},
+ [L, Body],
+ Dict,
+ [K, Name, L],
+ already_declared),
+ Body);
+
+p1([_Line | Body], Dict, K)
+ when K == avp_types;
+ K == grouped;
+ K == messages ->
+ foldl([fun explode/3, K], Dict, Body).
+
+no_messages_without_id(Dict) ->
+ case find(messages, Dict) of
+ [] ->
+ true;
+ [[Line | _] | _] ->
+ [] /= find(id, Dict) orelse ?RETURN(messages_without_id, [Line])
+ end.
+
+%% Note that the AVP's in avp_vendor_id, custom_types, codecs and
+%% enum can all be inherited, as can the AVP content of messages and
+%% grouped AVP's. Check that the referenced AVP's exist after
+%% importing definitions.
+
+%% explode/4
+%%
+%% {avp_vendor_id, AvpName} -> [Lineno, Id::integer()]
+%% {custom_types|codecs|inherits, AvpName} -> [Lineno, Mod::string()]
+
+explode({_, Line, AvpName}, Dict, {_, _, X} = T, K) ->
+ true = K /= avp_vendor_id orelse is_uint32(T, [K]),
+ true = K /= inherits orelse avp_not_local(AvpName, Line, Dict),
+
+ store_new({key(K), AvpName},
+ [Line, X],
+ Dict,
+ [AvpName, Line, K],
+ avp_already_defined).
+
+%% explode2/4
+
+%% {define, {Name, Key}} -> [Lineno, Value::integer(), enum|define]
+
+explode2([{_, Line, Key}, {_, _, Value} = T], Dict, {_, _, Name}, K) ->
+ true = is_uint32(T, [K, Name]),
+
+ store_new({key(K), {Name, Key}},
+ [Line, Value, K],
+ Dict,
+ [Name, Key, K, Line],
+ key_already_defined).
+
+%% key/1
+%%
+%% Conflate keys that are equivalent as far as uniqueness of
+%% definition goes.
+
+key(K)
+ when K == enum;
+ K == define ->
+ define;
+key(K)
+ when K == custom_types;
+ K == codecs ->
+ custom;
+key(K) ->
+ K.
+
+%% explode/3
+
+%% {avp_types, AvpName} -> [Line | Toks]
+%% {avp_types, {Code, IsReq}} -> [Line, AvpName]
+%%
+%% where AvpName = string()
+%% Code = integer()
+%% IsReq = boolean()
+
+explode([{_, Line, Name} | Toks], Dict0, avp_types = K) ->
+ %% Each AVP can be defined only once.
+ Dict = store_new({K, Name},
+ [Line | Toks],
+ Dict0,
+ [Name, Line],
+ avp_name_already_defined),
+
+ [{number, _, _Code} = C, {word, _, Type}, {word, _, _Flags}] = Toks,
+
+ true = avp_type_known(Type, Name, Line),
+ true = is_uint32(C, [K, Name]),
+
+ Dict;
+
+%% {grouped, Name} -> [Line, HeaderTok | AvpToks]
+%% {grouped, {Name, AvpName}} -> [Line, Qual, Delim]
+%%
+%% where Name = string()
+%% AvpName = string()
+%% Qual = {Q, Q} | boolean()
+%% Q = true | NumberTok
+%% Delim = $< | ${ | $[
+
+explode([{_, Line, Name}, Header | Avps], Dict0, grouped = K) ->
+ Dict = store_new({K, Name},
+ [Line, Header | Avps],
+ Dict0,
+ [Name, Line],
+ group_already_defined),
+
+ [{_,_, Code} = C, Vid] = Header,
+ {DefLine, {_, _, Flags}} = grouped_flags(Name, Code, Dict0, Line),
+ V = lists:member($V, Flags),
+
+ true = is_uint32(C, [K, Name, "AVP code"]),
+ true = is_uint32(Vid, [K, Name, "vendor id"]),
+ false = vendor_id_mismatch(Vid, V, Name, Dict0, Line, DefLine),
+
+ explode_avps(Avps, Dict, K, Name);
+
+%% {messages, Name} -> [Line, HeaderTok | AvpToks]
+%% {messages, {Code, IsReq}} -> [Line, NameTok]
+%% {messages, Code} -> [[Line, NameTok, IsReq]]
+%% {messages, {Name, Flag}} -> [Line]
+%% {messages, {Name, AvpName}} -> [Line, Qual, Delim]
+%%
+%% where Name = string()
+%% Code = integer()
+%% IsReq = boolean()
+%% Flag = 'REQ' | 'PXY'
+%% AvpName = string()
+%% Qual = true | {Q,Q}
+%% Q = true | NumberTok
+%% Delim = $< | ${ | ${
+
+explode([{'answer-message' = A, Line}, false = H | Avps],
+ Dict0,
+ messages = K) ->
+ Name = ?L(A),
+ Dict1 = store_new({K, Name},
+ [Line, H, Avps],
+ Dict0,
+ [Name, Line],
+ message_name_already_defined),
+
+ explode_avps(Avps, Dict1, K, Name);
+
+explode([{_, Line, MsgName} = M, Header | Avps],
+ Dict0,
+ messages = K) ->
+ %% There can be at most one message with a given name.
+ Dict1 = store_new({K, MsgName},
+ [Line, Header | Avps],
+ Dict0,
+ [MsgName, Line],
+ message_name_already_defined),
+
+ [{_, _, Code} = C, Bits, ApplId] = Header,
+
+ %% Don't check any application id since it's required to be
+ %% the same as @id.
+ true = is_uint32(C, [K, MsgName]),
+
+ %% An application id specified as part of the message definition
+ %% has to agree with @id. The former is parsed just because RFC
+ %% 3588 specifies it.
+ false = application_id_mismatch(ApplId, Dict1, MsgName),
+
+ IsReq = lists:keymember('REQ', 1, Bits),
+
+ %% For each command code, there can be at most one request and
+ %% one answer.
+ Dict2 = store_new({K, {Code, IsReq}},
+ [Line, M],
+ Dict1,
+ [choose(IsReq, "Request", "Answer"), Code, Line],
+ message_code_already_defined),
+
+ %% For each message, each flag can occur at most once.
+ Dict3 = foldl(fun({F,L},D) ->
+ store_new({K, {MsgName, F}},
+ [L],
+ D,
+ [MsgName, ?L(F)],
+ message_has_duplicate_flag)
+ end,
+ Dict2,
+ Bits),
+
+ dict:append({K, Code},
+ [Line, M, IsReq],
+ explode_avps(Avps, Dict3, K, MsgName)).
+
+%% explode_avps/4
+%%
+%% Ensure required AVP order and sane qualifiers. Can't check for AVP
+%% names until after they've been imported.
+%%
+%% RFC 3588 allows a trailing fixed while 3588bis doesn't. Parse the
+%% former.
+
+explode_avps(Avps, Dict, Key, Name) ->
+ xa("<{[<", Avps, Dict, Key, Name).
+
+xa(_, [], Dict, _, _) ->
+ Dict;
+
+xa(Ds, [[Qual, D, {'AVP', Line}] | Avps], Dict, Key, Name) ->
+ xa(Ds, [[Qual, D, {word, Line, "AVP"}] | Avps], Dict, Key, Name);
+
+xa([], [[_Qual, D, {_, Line, Name}] | _], _, _, _) ->
+ ?RETURN(invalid_avp_order, [D, Name, close(D), Line]);
+
+xa([D|_] = Ds, [[Qual, D, {_, Line, AvpName}] | Avps], Dict, Key, Name) ->
+ xa(Ds,
+ Avps,
+ store_new({Key, {Name, AvpName}},
+ [Line, Qual, D],
+ Dict,
+ [Name, Line],
+ avp_already_referenced),
+ Key,
+ Name);
+
+xa([_|Ds], Avps, Dict, Key, Name) ->
+ xa(Ds, Avps, Dict, Key, Name).
+
+close($<) -> $>;
+close(${) -> $};
+close($[) -> $].
+
+%% is_uint32/2
+
+is_uint32(false, _) ->
+ true;
+is_uint32({Line, _, N}, Args) ->
+ N < 1 bsl 32 orelse ?RETURN(uint32_out_of_range, Args ++ [N, Line]).
+%% Can't call diameter_types here since it may not exist yet.
+
+%% application_id_mismatch/3
+
+application_id_mismatch({number, Line, Id}, Dict, MsgName) ->
+ [[_, {_, L, I}]] = dict:fetch(id, Dict),
+
+ I /= Id andalso ?RETURN(message_application_id_mismatch,
+ [MsgName, Id, Line, I, L]);
+
+application_id_mismatch(false = No, _, _) ->
+ No.
+
+%% avp_not_local/3
+
+avp_not_local(Name, Line, Dict) ->
+ A = find({avp_types, Name}, Dict),
+
+ [] == A orelse ?RETURN(inherited_avp_already_defined,
+ [Name, Line, hd(A)]).
+
+%% avp_type_known/3
+
+avp_type_known(Type, Name, Line) ->
+ false /= type(Type)
+ orelse ?RETURN(avp_has_unknown_type, [Name, Line, Type]).
+
+%% vendor_id_mismatch/6
+%%
+%% Require a vendor id specified on a group to match any specified
+%% in @avp_vendor_id. Note that both locations for the value are
+%% equivalent, both in the value being attributed to a locally
+%% defined AVP and ignored when imported from another dictionary.
+
+vendor_id_mismatch({_,_,_}, false, Name, _, Line, DefLine) ->
+ ?RETURN(grouped_vendor_id_without_flag, [Name, Line, DefLine]);
+
+vendor_id_mismatch({_, _, I}, true, Name, Dict, Line, _) ->
+ case vendor_id(Name, Dict) of
+ {avp_vendor_id, L, N} ->
+ I /= N andalso
+ ?RETURN(grouped_vendor_id_mismatch, [Name, Line, I, N, L]);
+ _ ->
+ false
+ end;
+
+vendor_id_mismatch(_, _, _, _, _, _) ->
+ false.
+
+%% grouped_flags/4
+
+grouped_flags(Name, Code, Dict, Line) ->
+ case find({avp_types, Name}, Dict) of
+ [L, {_, _, Code}, {_, _, "Grouped"}, Flags] ->
+ {L, Flags};
+ [_, {_, L, C}, {_, _, "Grouped"}, _Flags] ->
+ ?RETURN(grouped_avp_code_mismatch, [Name, Line, Code, C, L]);
+ [_, _Code, {_, L, T}, _] ->
+ ?RETURN(grouped_avp_has_wrong_type, [Name, Line, T, L]);
+ [] ->
+ ?RETURN(grouped_avp_not_defined, [Name, Line])
+ end.
+
+%% vendor_id/2
+
+%% Look for a vendor id in @avp_vendor_id, then @vendor.
+vendor_id(Name, Dict) ->
+ case find({avp_vendor_id, Name}, Dict) of
+ [Line, Id] when is_integer(Id) ->
+ {avp_vendor_id, Line, Id};
+ [] ->
+ vendor(Dict)
+ end.
+
+vendor(Dict) ->
+ case find(vendor, Dict) of
+ [[_Line, {_, _, Id}, {_, _, _}]] ->
+ {vendor, Id};
+ [] ->
+ false
+ end.
+
+%% find/2
+
+find(Key, Dict) ->
+ case dict:find(Key, Dict) of
+ {ok, L} when is_list(L) ->
+ L;
+ error ->
+ []
+ end.
+
+%% store_new/5
+
+store_new(Key, Value, Dict, Args, Err) ->
+ case dict:find(Key, Dict) of
+ {ok, [L | _]} ->
+ ?RETURN(Err, Args ++ [L]);
+ error ->
+ dict:store(Key, Value, Dict)
+ end.
+
+%% type/1
+
+type("DiamIdent") ->
+ "DiameterIdentity";
+type("DiamURI") ->
+ "DiameterURI";
+type(T)
+ when T == "OctetString";
+ T == "Integer32";
+ T == "Integer64";
+ T == "Unsigned32";
+ T == "Unsigned64";
+ T == "Float32";
+ T == "Float64";
+ T == "Grouped";
+ T == "Enumerated";
+ T == "Address";
+ T == "Time";
+ T == "UTF8String";
+ T == "DiameterIdentity";
+ T == "DiameterURI";
+ T == "IPFilterRule";
+ T == "QoSFilterRule" ->
+ T;
+type(_) ->
+ false.
+
+%% ===========================================================================
+%% pass2/1
+%%
+%% More explosion, but that requires the previous pass to write its
+%% entries.
+
+pass2(Dict) ->
+ foldl(fun(K,D) -> foldl([fun p2/3, K], D, find(K,D)) end,
+ Dict,
+ [avp_types]).
+
+p2([_Line | Body], Dict, avp_types) ->
+ foldl(fun explode_avps/2, Dict, Body);
+
+p2([], Dict, _) ->
+ Dict.
+
+explode_avps([{_, Line, Name} | Toks], Dict) ->
+ [{number, _, Code}, {word, _, _Type}, {word, _, Flags}] = Toks,
+
+ true = avp_flags_valid(Flags, Name, Line),
+
+ Vid = avp_vendor_id(Flags, Name, Line, Dict),
+
+ %% An AVP is uniquely defined by its AVP code and vendor id (if any).
+ %% Ensure there are no duplicate.
+ store_new({avp_types, {Code, Vid}},
+ [Line, Name],
+ Dict,
+ [Code, Vid, Name, Line],
+ avp_code_already_defined).
+
+%% avp_flags_valid/3
+
+avp_flags_valid(Flags, Name, Line) ->
+ Bad = lists:filter(fun(C) -> not lists:member(C, "MVP") end, Flags),
+ [] == Bad
+ orelse ?RETURN(avp_has_invalid_flag, [Name, Line, hd(Bad)]),
+
+ Dup = Flags -- "MVP",
+ [] == Dup
+ orelse ?RETURN(avp_has_duplicate_flag, [Name, Line, hd(Dup)]).
+
+%% avp_vendor_id/4
+
+avp_vendor_id(Flags, Name, Line, Dict) ->
+ V = lists:member($V, Flags),
+
+ case vendor_id(Name, Dict) of
+ {avp_vendor_id, _, I} when V ->
+ I;
+ {avp_vendor_id, L, I} ->
+ ?RETURN(avp_has_vendor_id, [Name, Line, I, L]);
+ {vendor, I} when V ->
+ I;
+ false when V ->
+ ?RETURN(avp_has_no_vendor, [Name, Line]);
+ _ ->
+ false
+ end.
+
+%% ===========================================================================
+%% pass3/2
+%%
+%% Import AVPs.
+
+pass3(Dict, Opts) ->
+ import_enums(import_groups(import_avps(insert_codes(Dict), Opts))).
+
+%% insert_codes/1
+%%
+%% command_codes -> [{Code, ReqNameTok, AnsNameTok}]
+
+insert_codes(Dict) ->
+ dict:store(command_codes,
+ dict:fold(fun make_code/3, [], Dict),
+ Dict).
+
+make_code({messages, Code}, Names, Acc)
+ when is_integer(Code) ->
+ [mk_code(Code, Names) | Acc];
+make_code(_, _, Acc) ->
+ Acc.
+
+mk_code(Code, [[_, _, false] = Ans, [_, _, true] = Req]) ->
+ mk_code(Code, [Req, Ans]);
+
+mk_code(Code, [[_, {_,_,Req}, true], [_, {_,_,Ans}, false]]) ->
+ {Code, Req, Ans};
+
+mk_code(_Code, [[Line, _Name, IsReq]]) ->
+ ?RETURN(message_missing, [choose(IsReq, "Request", "Answer"),
+ Line,
+ choose(IsReq, "answer", "request")]).
+
+%% import_avps/2
+
+import_avps(Dict, Opts) ->
+ Import = inherit(Dict, Opts),
+ report(imported, Import),
+
+ %% pass4/1 tests that all referenced AVP's are either defined
+ %% or imported.
+
+ dict:store(import_avps,
+ lists:map(fun({M, _, As}) -> {M, [A || {_,A} <- As]} end,
+ lists:reverse(Import)),
+ foldl(fun explode_imports/2, Dict, Import)).
+
+explode_imports({Mod, Line, Avps}, Dict) ->
+ foldl([fun xi/4, Mod, Line], Dict, Avps).
+
+xi({L, {Name, _Code, _Type, _Flags} = A}, Dict, Mod, Line) ->
+ store_new({avp_types, Name},
+ [0, Mod, Line, L, A],
+ store_new({import, Name},
+ [Line],
+ Dict,
+ [Name, Line],
+ duplicate_import),
+ [Name, Mod, Line],
+ imported_avp_already_defined).
+
+%% 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(Dict) ->
+ dict:store(import_groups, import(grouped, Dict), Dict).
+
+import_enums(Dict) ->
+ dict:store(import_enums, import(enum, Dict), Dict).
+
+import(Key, Dict) ->
+ flatmap([fun import_key/2, Key], dict:fetch(import_avps, Dict)).
+
+import_key({Mod, Avps}, Key) ->
+ As = lists:flatmap(fun(T) ->
+ N = element(1,T),
+ choose(lists:keymember(N, 1, Avps), [T], [])
+ end,
+ orddict:fetch(Key, dict(Mod))),
+ if As == [] ->
+ [];
+ true ->
+ [{Mod, As}]
+ end.
+
+%% ------------------------------------------------------------------------
+%% inherit/2
+%%
+%% Return a {Mod, Line, [{Lineno, Avp}]} list, where Mod is a module
+%% name, Line points to the corresponding @inherit and each Avp is
+%% from Mod:dict(). Lineno is 0 if the import is implicit.
+
+inherit(Dict, Opts) ->
+ code:add_pathsa([D || {include, D} <- Opts]),
+ foldl(fun inherit_avps/2, [], find(inherits, Dict)).
+%% Note that the module order of the returned lists is reversed
+%% relative to @inherits.
+
+inherit_avps([Line, {_,_,M} | Names], Acc) ->
+ Mod = ?A(M),
+ report(inherit_from, Mod),
+ case find_avps(Names, avps_from_module(Mod)) of
+ {_, [{_, L, N} | _]} ->
+ ?RETURN(requested_avp_not_found, [Mod, Line, N, L]);
+ {Found, []} ->
+ [{Mod, Line, lists:sort(Found)} | Acc]
+ end.
+
+%% Import everything not defined locally ...
+find_avps([], Avps) ->
+ {[{0, A} || A <- Avps], []};
+
+%% ... or specified AVPs.
+find_avps(Names, Avps) ->
+ foldl(fun acc_avp/2, {[], Names}, Avps).
+
+acc_avp({Name, _Code, _Type, _Flags} = A, {Found, Not} = Acc) ->
+ case lists:keyfind(Name, 3, Not) of
+ {_, Line, Name} ->
+ {[{Line, A} | Found], lists:keydelete(Name, 3, Not)};
+ false ->
+ Acc
+ end.
+
+%% avps_from_module/2
+
+avps_from_module(Mod) ->
+ orddict:fetch(avp_types, dict(Mod)).
+
+dict(Mod) ->
+ try Mod:dict() of
+ [?VERSION | Dict] ->
+ Dict;
+ _ ->
+ ?RETURN(recompile, [Mod])
+ catch
+ error: _ ->
+ ?RETURN(choose(false == code:is_loaded(Mod),
+ not_loaded,
+ no_dict),
+ [Mod])
+ end.
+
+%% ===========================================================================
+%% pass4/1
+%%
+%% Sanity checks.
+
+pass4(Dict) ->
+ dict:fold(fun(K, V, _) -> p4(K, V, Dict) end, ok, Dict),
+ Dict.
+
+%% Ensure enum AVP's have type Enumerated.
+p4({enum, Name}, [Line | _], Dict)
+ when is_list(Name) ->
+ true = is_enumerated_avp(Name, Dict, Line);
+
+%% Ensure all referenced AVP's are either defined locally or imported.
+p4({K, {Name, AvpName}}, [Line | _], Dict)
+ when (K == grouped orelse K == messages),
+ is_list(Name),
+ is_list(AvpName),
+ AvpName /= "AVP" ->
+ true = avp_is_defined(AvpName, Dict, Line);
+
+%% Ditto.
+p4({K, AvpName}, [Line | _], Dict)
+ when K == avp_vendor_id;
+ K == custom_types;
+ K == codecs ->
+ true = avp_is_defined(AvpName, Dict, Line);
+
+p4(_, _, _) ->
+ ok.
+
+%% has_enumerated_type/3
+
+is_enumerated_avp(Name, Dict, Line) ->
+ case find({avp_types, Name}, Dict) of
+ [_Line, _Code, {_, _, "Enumerated"}, _Flags] -> %% local
+ true;
+ [_Line, _Code, {_, L, T}, _] ->
+ ?RETURN(enumerated_avp_has_wrong_local_type,
+ [Name, Line, T, L]);
+ [0, _, _, _, {_Name, _Code, "Enumerated", _Flags}] -> %% inherited
+ true;
+ [0, Mod, LM, LA, {_Name, _Code, Type, _Flags}] ->
+ ?RETURN(enumerated_avp_has_wrong_inherited_type,
+ [Name, Line, Type, Mod, choose(0 == LA, LM, LA)]);
+ [] ->
+ ?RETURN(enumerated_avp_not_defined, [Name, Line])
+ end.
+
+avp_is_defined(Name, Dict, Line) ->
+ case find({avp_types, Name}, Dict) of
+ [_Line, _Code, _Type, _Flags] -> %% local
+ true;
+ [0, _, _, _, {Name, _Code, _Type, _Flags}] -> %% inherited
+ true;
+ [] ->
+ ?RETURN(avp_not_defined, [Name, Line])
+ end.
+
+%% ===========================================================================
+
+putr(Key, Value) ->
+ put({?MODULE, Key}, Value).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+eraser(Key) ->
+ erase({?MODULE, Key}).
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
+
+foldl(F, Acc, List) ->
+ lists:foldl(fun(T,A) -> eval([F,T,A]) end, Acc, List).
+
+flatmap(F, List) ->
+ lists:flatmap(fun(T) -> eval([F,T]) end, List).
+
+eval([[F|X] | A]) ->
+ eval([F | A ++ X]);
+eval([F|A]) ->
+ apply(F,A).
diff --git a/lib/diameter/src/compiler/diameter_exprecs.erl b/lib/diameter/src/compiler/diameter_exprecs.erl
new file mode 100644
index 0000000000..191f53f29d
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_exprecs.erl
@@ -0,0 +1,275 @@
+%%
+%% %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]).
+
+-include("diameter_forms.hrl").
+
+%% parse_transform/2
+
+parse_transform(Forms, _Options) ->
+ Rs = [R || {attribute, _, record, R} <- Forms],
+ Es = lists:append([E || {attribute, _, export_records, E} <- Forms]),
+ {H,T} = lists:splitwith(fun is_head/1, Forms),
+ H ++ [a_export(Es) | f_accessors(Es, Rs)] ++ T.
+
+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) ++ [?BADARG(2)]}.
+
+'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) ++ [?BADARG(1)]}.
+
+'new-'(R) ->
+ {?clause, [?ATOM(R)],
+ [],
+ [{?record, R, []}]}.
+
+'#new-/2'(Exports) ->
+ {?function, fname(new), 2,
+ lists:map(fun 'new--'/1, Exports) ++ [?BADARG(2)]}.
+
+'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) ++ [?BADARG(2)]}.
+
+'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) ++ [?BADARG(2)]}.
+
+'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/compiler/diameter_forms.hrl b/lib/diameter/src/compiler/diameter_forms.hrl
index d93131df34..4cd86c32aa 100644
--- a/lib/diameter/src/compiler/diameter_forms.hrl
+++ b/lib/diameter/src/compiler/diameter_forms.hrl
@@ -21,6 +21,13 @@
%% Macros used when building abstract code.
%%
+%% Generated functions that could have no generated clauses will have
+%% a trailing ?BADARG clause that should never execute as called
+%% by diameter.
+-define(BADARG(N), {?clause, [?VAR('_') || _ <- lists:seq(1,N)],
+ [],
+ [?APPLY(erlang, error, [?ATOM(badarg)])]}).
+
%% Form tag with line number.
-define(F(T), T, ?LINE).
%% Yes, that's right. The replacement is to the first unmatched ')'.
diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl
index 4431b88c4d..16e30c1ffb 100644
--- a/lib/diameter/src/compiler/diameter_make.erl
+++ b/lib/diameter/src/compiler/diameter_make.erl
@@ -18,103 +18,115 @@
%%
%%
-%% Driver for the encoder generator utility.
+%% Module alternative to diameterc for dictionary compilation.
+%%
+%% Eg. 1> diameter_make:codec("mydict.dia").
+%%
+%% $ erl -noinput \
+%% -boot start_clean \
+%% -eval 'ok = diameter_make:codec("mydict.dia")' \
+%% -s init stop
%%
-module(diameter_make).
--export([spec/0,
- hrl/0,
- erl/0]).
+-export([codec/1,
+ codec/2,
+ dict/1,
+ dict/2,
+ format/1,
+ reformat/1]).
--spec spec() -> no_return().
--spec hrl() -> no_return().
--spec erl() -> no_return().
+-export_type([opt/0]).
-spec() ->
- make(spec).
+-type opt() :: {include|outdir|name|prefix|inherits, string()}
+ | verbose
+ | debug.
-hrl() ->
- make(hrl).
+%% ===========================================================================
-erl() ->
- make(erl).
+%% codec/1-2
+%%
+%% Parse a dictionary file and generate a codec module.
+
+-spec codec(Path, [opt()])
+ -> ok
+ | {error, Reason}
+ when Path :: string(),
+ Reason :: string().
+
+codec(File, Opts) ->
+ case dict(File, Opts) of
+ {ok, Dict} ->
+ make(File,
+ Opts,
+ Dict,
+ [spec || _ <- [1], lists:member(debug, Opts)] ++ [erl, hrl]);
+ {error, _} = E ->
+ E
+ end.
-%% make/1
+codec(File) ->
+ codec(File, []).
-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).
+%% dict/2
+%%
+%% Parse a dictionary file and return the orddict that a codec module
+%% returns from dict/0.
+
+-spec dict(string(), [opt()])
+ -> {ok, orddict:orddict()}
+ | {error, string()}.
+
+dict(Path, Opts) ->
+ case diameter_dict_util:parse({path, Path}, Opts) of
+ {ok, _} = Ok ->
+ Ok;
+ {error = E, Reason} ->
+ {E, diameter_dict_util:format_error(Reason)}
+ end.
-%% from_file/3
+dict(File) ->
+ dict(File, []).
-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.
+%% format/1
+%%
+%% Turn an orddict returned by dict/1-2 back into a dictionary file
+%% in the form of an iolist().
-%% to_spec/2
+-spec format(orddict:orddict())
+ -> iolist().
-%% 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.
+format(Dict) ->
+ diameter_dict_util:format(Dict).
-%% from_spec/4
+%% reformat/1
+%%
+%% Parse a dictionary file and return its formatted equivalent.
+
+-spec reformat(File)
+ -> {ok, iolist()}
+ | {error, Reason}
+ when File :: string(),
+ Reason :: string().
+
+reformat(File) ->
+ case dict(File) of
+ {ok, Dict} ->
+ {ok, format(Dict)};
+ {error, _} = No ->
+ No
+ end.
-from_spec(File, Spec, Mode, Opts) ->
+%% ===========================================================================
+
+make(_, _, _, []) ->
+ ok;
+make(File, Opts, Dict, [Mode | Rest]) ->
try
- diameter_codegen:from_spec(File, Spec, Opts, Mode)
+ ok = diameter_codegen:from_dict(File, Dict, Opts, Mode),
+ make(File, Opts, Dict, Rest)
catch
error: Reason ->
- io:format("==> ~p codegen failure:~n~p~n~p~n",
- [Mode, File, {Reason, erlang:get_stacktrace()}]),
- halt(1)
+ erlang:error({Reason, Mode, erlang:get_stacktrace()})
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_nowarn.erl b/lib/diameter/src/compiler/diameter_nowarn.erl
new file mode 100644
index 0000000000..6c17af6563
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_nowarn.erl
@@ -0,0 +1,41 @@
+%%
+%% %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 parse transform to work around dialyzer currently not
+%% understanding nowarn_unused_function except on individual
+%% functions. The include of diameter_gen.hrl by generated dictionary
+%% modules contains code that may not be called depending on the
+%% dictionary. (The relay dictionary for example.)
+%%
+%% Even called functions may contain cases that aren't used for a
+%% particular dictionary. This also causes dialyzer to complain but
+%% there's no way to silence it in this case.
+%%
+
+-module(diameter_nowarn).
+
+-export([parse_transform/2]).
+
+parse_transform(Forms, _Options) ->
+ [{attribute, ?LINE, compile, {nowarn_unused_function, {F,A}}}
+ || {function, _, F, A, _} <- Forms]
+ ++ Forms.
+%% Note that dialyzer also doesn't understand {nowarn_unused_function, FAs}
+%% with FAs a list of tuples.
diff --git a/lib/diameter/src/compiler/diameter_spec_scan.erl b/lib/diameter/src/compiler/diameter_spec_scan.erl
deleted file mode 100644
index bc0448882a..0000000000
--- a/lib/diameter/src/compiler/diameter_spec_scan.erl
+++ /dev/null
@@ -1,157 +0,0 @@
-%%
-%% %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
deleted file mode 100644
index b60886b678..0000000000
--- a/lib/diameter/src/compiler/diameter_spec_util.erl
+++ /dev/null
@@ -1,1068 +0,0 @@
-%%
-%% %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/diameter_vsn.hrl b/lib/diameter/src/compiler/diameter_vsn.hrl
new file mode 100644
index 0000000000..024d047adc
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_vsn.hrl
@@ -0,0 +1,22 @@
+%%
+%% %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 version of the format of the return value of dict/0 in
+%% generated dictionary modules.
+-define(VERSION, 1).
diff --git a/lib/diameter/src/compiler/modules.mk b/lib/diameter/src/compiler/modules.mk
deleted file mode 100644
index 17a311dacf..0000000000
--- a/lib/diameter/src/compiler/modules.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#-*-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/depend.sed b/lib/diameter/src/depend.sed
new file mode 100644
index 0000000000..8f999f646f
--- /dev/null
+++ b/lib/diameter/src/depend.sed
@@ -0,0 +1,51 @@
+#
+# %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. First line of input
+# is the path to the module in question (minus the .erl extension),
+# the rest is the contents of the module.
+#
+
+1{
+ s@^[^/]*/@@
+ h
+ d
+}
+
+# Only interested in includes of diameter hrls.
+/^-include/!d
+/"diameter/!d
+
+# Extract the name of the included files in one of two forms:
+#
+# $(INCDIR)/diameter.hrl
+# diameter_internal.hrl
+
+s@^-include_lib(".*/@$(INCDIR)/@
+s@^-include("@@
+s@".*@@
+
+# Retrieve the path to our module from the hold space, morph it
+# into a beam path and turn it into a dependency like this:
+#
+# $(EBIN)/diameter_service.$(EMULATOR): $(INCDIR)/diameter.hrl
+
+G
+s@^\(.*\)\n\(.*\)@$(EBIN)/\2.$(EMULATOR): \1@
diff --git a/lib/diameter/src/dict/base_accounting.dia b/lib/diameter/src/dict/base_accounting.dia
new file mode 100644
index 0000000000..ced324078c
--- /dev/null
+++ b/lib/diameter/src/dict/base_accounting.dia
@@ -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%
+;;
+
+@id 3
+@name diameter_gen_base_accounting
+@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/dict/base_rfc3588.dia b/lib/diameter/src/dict/base_rfc3588.dia
new file mode 100644
index 0000000000..acd7fffd00
--- /dev/null
+++ b/lib/diameter/src/dict/base_rfc3588.dia
@@ -0,0 +1,461 @@
+;;
+;; %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
+@name diameter_gen_base_rfc3588
+@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
+
+ LOGOUT 1
+ SERVICE_NOT_PROVIDED 2
+ BAD_ANSWER 3
+ ADMINISTRATIVE 4
+ LINK_BROKEN 5
+ AUTH_EXPIRED 6
+ USER_MOVED 7
+ 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
+
+@define Result-Code
+
+ ;; 7.1.1. Informational
+ MULTI_ROUND_AUTH 1001
+
+ ;; 7.1.2. Success
+ SUCCESS 2001
+ LIMITED_SUCCESS 2002
+
+ ;; 7.1.3. Protocol Errors
+ COMMAND_UNSUPPORTED 3001
+ UNABLE_TO_DELIVER 3002
+ REALM_NOT_SERVED 3003
+ TOO_BUSY 3004
+ LOOP_DETECTED 3005
+ REDIRECT_INDICATION 3006
+ APPLICATION_UNSUPPORTED 3007
+ INVALID_HDR_BITS 3008
+ INVALID_AVP_BITS 3009
+ UNKNOWN_PEER 3010
+
+ ;; 7.1.4. Transient Failures
+ AUTHENTICATION_REJECTED 4001
+ OUT_OF_SPACE 4002
+ ELECTION_LOST 4003
+
+ ;; 7.1.5. Permanent Failures
+ AVP_UNSUPPORTED 5001
+ UNKNOWN_SESSION_ID 5002
+ AUTHORIZATION_REJECTED 5003
+ INVALID_AVP_VALUE 5004
+ MISSING_AVP 5005
+ RESOURCES_EXCEEDED 5006
+ CONTRADICTING_AVPS 5007
+ AVP_NOT_ALLOWED 5008
+ AVP_OCCURS_TOO_MANY_TIMES 5009
+ NO_COMMON_APPLICATION 5010
+ UNSUPPORTED_VERSION 5011
+ UNABLE_TO_COMPLY 5012
+ INVALID_BIT_IN_HEADER 5013
+ INVALID_AVP_LENGTH 5014
+ INVALID_MESSAGE_LENGTH 5015
+ INVALID_AVP_BIT_COMBO 5016
+ NO_COMMON_SECURITY 5017
+
+ ;; With a prefix for backwards compatibility.
+ DIAMETER_MULTI_ROUND_AUTH 1001
+ DIAMETER_SUCCESS 2001
+ DIAMETER_LIMITED_SUCCESS 2002
+ 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
+ DIAMETER_AUTHENTICATION_REJECTED 4001
+ DIAMETER_OUT_OF_SPACE 4002
+ DIAMETER_ELECTION_LOST 4003
+ 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 }
+
+;; Backwards compatibility.
+@define 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
diff --git a/lib/diameter/src/dict/relay.dia b/lib/diameter/src/dict/relay.dia
new file mode 100644
index 0000000000..294014b093
--- /dev/null
+++ b/lib/diameter/src/dict/relay.dia
@@ -0,0 +1,23 @@
+;;
+;; %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
+@name diameter_gen_relay
+@prefix diameter_relay
+@vendor 0 IETF
diff --git a/lib/diameter/src/gen/.gitignore b/lib/diameter/src/gen/.gitignore
new file mode 100644
index 0000000000..3f32313f56
--- /dev/null
+++ b/lib/diameter/src/gen/.gitignore
@@ -0,0 +1,2 @@
+/diameter_dict_parser.erl
+/diameter_gen*rl
diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk
new file mode 100644
index 0000000000..7a700a6d53
--- /dev/null
+++ b/lib/diameter/src/modules.mk
@@ -0,0 +1,104 @@
+#-*-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%
+
+# Runtime dictionary files in ./dict. Modules will be generated from
+# these are included in the app file.
+DICTS = \
+ base_rfc3588 \
+ base_accounting \
+ relay
+
+# The yecc grammar for the dictionary parser.
+DICT_YRL = \
+ diameter_dict_parser
+
+# Handwritten (runtime) modules included in the app file.
+RT_MODULES = \
+ base/diameter \
+ base/diameter_app \
+ base/diameter_callback \
+ base/diameter_capx \
+ base/diameter_config \
+ base/diameter_codec \
+ base/diameter_dict \
+ base/diameter_lib \
+ base/diameter_misc_sup \
+ base/diameter_peer \
+ base/diameter_peer_fsm \
+ base/diameter_peer_fsm_sup \
+ base/diameter_reg \
+ base/diameter_service \
+ base/diameter_service_sup \
+ base/diameter_session \
+ base/diameter_stats \
+ base/diameter_sup \
+ base/diameter_sync \
+ base/diameter_types \
+ base/diameter_watchdog \
+ base/diameter_watchdog_sup \
+ transport/diameter_etcp \
+ transport/diameter_etcp_sup \
+ transport/diameter_tcp \
+ transport/diameter_tcp_sup \
+ transport/diameter_sctp \
+ transport/diameter_sctp_sup \
+ transport/diameter_transport_sup
+
+# Handwritten (compile time) modules not included in the app file.
+CT_MODULES = \
+ base/diameter_dbg \
+ base/diameter_info \
+ compiler/diameter_codegen \
+ compiler/diameter_exprecs \
+ compiler/diameter_nowarn \
+ compiler/diameter_dict_scanner \
+ compiler/diameter_dict_util \
+ compiler/diameter_make
+
+# Released hrl files in ../include intended for public consumption.
+EXTERNAL_HRLS = \
+ diameter.hrl \
+ diameter_gen.hrl
+
+# Released hrl files intended for private use.
+INTERNAL_HRLS = \
+ base/diameter_internal.hrl \
+ compiler/diameter_forms.hrl \
+ compiler/diameter_vsn.hrl
+
+# Released files relative to ../bin.
+BINS = \
+ diameterc
+
+# Released files relative to ../examples.
+EXAMPLES = \
+ code/GNUmakefile \
+ code/peer.erl \
+ code/client.erl \
+ code/client_cb.erl \
+ code/server.erl \
+ code/server_cb.erl \
+ code/relay.erl \
+ code/relay_cb.erl \
+ dict/rfc4004_mip.dia \
+ dict/rfc4005_nas.dia \
+ dict/rfc4006_cc.dia \
+ dict/rfc4072_eap.dia \
+ dict/rfc4590_digest.dia \
+ dict/rfc4740_sip.dia
diff --git a/lib/diameter/src/subdirs.mk b/lib/diameter/src/subdirs.mk
deleted file mode 100644
index 3e12d935bc..0000000000
--- a/lib/diameter/src/subdirs.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#-*-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
deleted file mode 100644
index d9f072e262..0000000000
--- a/lib/diameter/src/transport/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-
-/depend.mk
-
diff --git a/lib/diameter/src/transport/Makefile b/lib/diameter/src/transport/Makefile
deleted file mode 100644
index 4b53100fd2..0000000000
--- a/lib/diameter/src/transport/Makefile
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# %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_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 209f8c01c1..68b0342cd5 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -546,10 +546,10 @@ send(Sock, AssocId, Stream, Bin) ->
%% recv/2
%% Association established ...
-recv({[], #sctp_assoc_change{state = comm_up,
- outbound_streams = OS,
- inbound_streams = IS,
- assoc_id = Id}},
+recv({_, #sctp_assoc_change{state = comm_up,
+ outbound_streams = OS,
+ inbound_streams = IS,
+ assoc_id = Id}},
#transport{assoc_id = undefined,
mode = {T, _},
socket = Sock}
@@ -562,7 +562,7 @@ recv({[], #sctp_assoc_change{state = comm_up,
streams = {IS, OS}});
%% ... or not: try the next address.
-recv({[], #sctp_assoc_change{} = E},
+recv({_, #sctp_assoc_change{} = E},
#transport{assoc_id = undefined,
socket = Sock,
mode = {connect = C, {[RA|RAs], RP, Es}}}
@@ -570,7 +570,7 @@ recv({[], #sctp_assoc_change{} = E},
S#transport{mode = {C, connect(Sock, RAs, RP, [{RA,E} | Es])}};
%% Lost association after establishment.
-recv({[], #sctp_assoc_change{}}, _) ->
+recv({_, #sctp_assoc_change{}}, _) ->
stop;
%% Inbound Diameter message.
@@ -580,7 +580,7 @@ recv({[#sctp_sndrcvinfo{stream = Id}], Bin}, #transport{parent = Pid})
bin = Bin}),
ok;
-recv({[], #sctp_shutdown_event{assoc_id = Id}},
+recv({_, #sctp_shutdown_event{assoc_id = Id}},
#transport{assoc_id = Id}) ->
stop;
@@ -593,10 +593,10 @@ recv({[], #sctp_shutdown_event{assoc_id = Id}},
%% 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{}}, _) ->
+recv({_, #sctp_paddr_change{}}, _) ->
ok;
-recv({[], #sctp_pdapi_event{}}, _) ->
+recv({_, #sctp_pdapi_event{}}, _) ->
ok.
%% up/1
diff --git a/lib/diameter/src/transport/modules.mk b/lib/diameter/src/transport/modules.mk
deleted file mode 100644
index a0dc3cf2c0..0000000000
--- a/lib/diameter/src/transport/modules.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#-*-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/test/Makefile b/lib/diameter/test/Makefile
index 04e686c969..1659330a91 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -17,15 +17,13 @@
# %CopyrightEnd%
ifeq ($(ERL_TOP),)
-TOP = $(DIAMETER_TOP)
+include $(DIAMETER_TOP)/make/target.mk
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
else
-TOP = $(ERL_TOP)
-DIAMETER_TOP = $(TOP)/lib/diameter
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
endif
-include $(TOP)/make/target.mk
-include $(TOP)/make/$(TARGET)/otp.mk
-
# ----------------------------------------------------
# Application version
# ----------------------------------------------------
@@ -46,38 +44,34 @@ RELSYSDIR = $(RELEASE_PATH)/diameter_test
include modules.mk
-EBIN = .
-
-HRL_FILES = $(INTERNAL_HRL_FILES)
-ERL_FILES = $(MODULES:%=%.erl)
-
-SOURCE = $(HRL_FILES) $(ERL_FILES)
+ERL_FILES = $(MODULES:%=%.erl)
TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
SUITE_MODULES = $(filter diameter_%_SUITE, $(MODULES))
-SUITES = $(SUITE_MODULES:diameter_%_SUITE=%)
+SUITES = $(SUITE_MODULES:diameter_%_SUITE=%)
-RELTEST_FILES = $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) $(SOURCE)
+DATA_DIRS = $(sort $(dir $(DATA)))
# ----------------------------------------------------
# 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
+ERL_COMPILE_FLAGS += +warn_export_vars \
+ +warn_unused_vars \
+ -I ../include \
+ -I ../src/gen
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-all: $(SUITES)
+all: opt
+
+run: $(SUITES)
-beam tests debug opt: $(TARGET_FILES)
+debug opt: $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
@@ -85,66 +79,56 @@ clean:
realclean: clean
rm -rf log
- rm -f errs core *~
-
-.PHONY: all tests debug opt clean realclean
docs:
+list = echo $(1):; echo $($(1)) | tr ' ' '\n' | sort | sed 's@^@ @'
+
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 ========================================
+ @$(call list,MODULES)
@echo
- @echo "SUITE_MODULES = $(SUITE_MODULES)"
- @echo "SUITES = $(SUITES)"
+ @$(call list,HRL_FILES)
@echo
+ @$(call list,SUITES)
+ @echo ========================================
help:
+ @echo ========================================
+ @echo "Useful targets:"
@echo
- @echo "Targets:"
+ @echo " all:"
+ @echo " Compile all test suites."
@echo
- @echo " all"
- @echo " Run all test suites."
+ @echo " run:"
+ @echo " Compile and run all test suites."
@echo
- @echo " $(SUITES)"
- @echo " Run a specific test suite."
+ @echo " $(SUITES):"
+ @echo " Compile and run a specific test suite."
@echo
- @echo " tests"
- @echo " Compile all test-code."
- @echo
- @echo " clean | realclean"
+ @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
+ @echo " info:"
+ @echo " Echo some relevant variables."
+ @echo ========================================
-.PHONY: docs info help
+.PHONY: all run clean debug docs help info opt realclean
# ----------------------------------------------------
# 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}'
+# diameter_ct:run/1 itself can't tell (it seems). The absolute -pa is
+# because ct will change directories.
+$(SUITES): log opt
+ $(ERL) -noinput \
+ -pa $(realpath ../ebin) \
+ -sname diameter_test_$@ \
+ -s diameter_ct run diameter_$@_SUITE \
+ -s init stop \
+ | awk '{print} / FAILED /{rc=1} END{exit rc}' rc=0
# Shorter in sed but requires a GNU extension (ie. Q).
log:
@@ -156,17 +140,38 @@ log:
# Release Targets
# ----------------------------------------------------
-include $(TOP)/make/otp_release_targets.mk
+/%: % force
+ sed -f release.sed $< > "$(RELSYSDIR)$@"
-release_spec:
+ifeq ($(ERL_TOP),)
+include $(DIAMETER_TOP)/make/release_targets.mk
+else
+include $(ERL_TOP)/make/otp_release_targets.mk
+endif
-release_docs_spec:
+release_spec release_docs_spec:
release_tests_spec:
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(RELTEST_FILES) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(TEST_SPEC_FILE) \
+ $(COVER_SPEC_FILE) \
+ $(HRL_FILES) \
+ "$(RELSYSDIR)"
+ $(MAKE) $(DATA_DIRS:%/=release_data_%)
+ $(MAKE) $(ERL_FILES:%=/%)
+
+$(DATA_DIRS:%/=release_data_%): release_data_%:
+ $(INSTALL_DIR) "$(RELSYSDIR)/$*"
+ $(INSTALL_DATA) $(filter $*/%, $(DATA)) "$(RELSYSDIR)/$*"
+
+force:
.PHONY: release_spec release_docs_spec release_test_specs
+.PHONY: force
+.PHONY: $(DATA_DIRS:%/=release_data_%)
+
+# Can't just make $(ERL_FILES:%=/%) phony since then implicit rule
+# searching is skipped.
# ----------------------------------------------------
@@ -175,7 +180,7 @@ 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@"; \
+ (echo $$f; cat $$f.erl) | sed -f $<; \
done) \
> $@
diff --git a/lib/diameter/test/depend.sed b/lib/diameter/test/depend.sed
index a399eb45f0..95dca44984 100644
--- a/lib/diameter/test/depend.sed
+++ b/lib/diameter/test/depend.sed
@@ -18,14 +18,24 @@
#
#
-# Extract local include dependencies from .erl files. The output is massaged
-# further in Makefile.
+# Extract local include dependencies from an .erl file. The first
+# input line is the module name.
#
-/^-include/!d
+# Store the module name in the hold space.
+1{
+ h
+ d
+}
+
+# Throw away everything but local includes.
/^-include_lib/d
+/^-include/!d
/diameter_gen/d
+/diameter\./d
+# Output a dependency of the beam on the included file.
s@^-include("@@
s@".*@@
-s@^@$(EBIN)/.$(EMULATOR): @
+G
+s@^\(.*\)\n\(.*\)@$(EBIN)/\2.$(EMULATOR): \1@
diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl
index 15a98d4441..53332af626 100644
--- a/lib/diameter/test/diameter_app_SUITE.erl
+++ b/lib/diameter/test/diameter_app_SUITE.erl
@@ -41,6 +41,19 @@
-define(A, list_to_atom).
+%% Modules not in the app and that should not have dependencies on it
+%% for build reasons.
+-define(COMPILER_MODULES, [diameter_codegen,
+ diameter_dict_scanner,
+ diameter_dict_parser,
+ diameter_dict_util,
+ diameter_exprecs,
+ diameter_nowarn,
+ diameter_make]).
+
+-define(HELP_MODULES, [diameter_dbg,
+ diameter_info]).
+
%% ===========================================================================
suite() ->
@@ -93,13 +106,8 @@ vsn(Config) ->
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 = lists:sort(?HELP_MODULES ++ ?COMPILER_MODULES),
+
{[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}.
code_mods() ->
@@ -133,13 +141,16 @@ release(Config) ->
Rel = {release,
{"diameter test release", fetch(vsn, App)},
{erts, erlang:system_info(version)},
- [{A, appvsn(A)} || A <- fetch(applications, App)]},
+ [{A, appvsn(A)} || A <- [sasl | 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]).
+%% sasl need to be included to avoid a missing_sasl warning, error
+%% in the case of relup/1.
+
appvsn(Name) ->
[{application, Name, App}] = diameter_util:consult(Name, app),
fetch(vsn, App).
@@ -163,14 +174,12 @@ xref(Config) ->
%% 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.
+ %% applications.
ok = lists:foreach(fun(A) -> add_application(XRef, A) end,
[?APP, erts | fetch(applications, App)]),
{ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
+ {ok, Called} = xref:analyze(XRef, {module_call, ?COMPILER_MODULES}),
xref:stop(XRef),
@@ -179,7 +188,21 @@ xref(Config) ->
lists:member(F, Mods)
andalso {F,T} /= {diameter_tcp, ssl}
end,
- Undefs).
+ Undefs),
+ %% diameter_tcp does call ssl despite the latter 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.
+
+ [] = lists:filter(fun is_bad_dependency/1, Called).
+
+%% It's not strictly necessary that diameter compiler modules not
+%% depend on other diameter modules but it's a simple source of build
+%% errors if not encoded in the makefile (hence the test) so guard
+%% against it.
+is_bad_dependency(Mod) ->
+ lists:prefix("diameter", atom_to_list(Mod))
+ andalso not lists:member(Mod, ?COMPILER_MODULES).
add_application(XRef, App) ->
add_application(XRef, App, code:lib_dir(App)).
@@ -207,7 +230,7 @@ relup(Config) ->
App = fetch(app, Config),
Rel = [{erts, erlang:system_info(version)}
- | [{A, appvsn(A)} || A <- fetch(applications, App)]],
+ | [{A, appvsn(A)} || A <- [sasl | fetch(applications, App)]]],
Dir = fetch(priv_dir, Config),
@@ -215,12 +238,15 @@ relup(Config) ->
UpFrom = acc_rel(Dir, Rel, Up),
DownTo = acc_rel(Dir, Rel, Down),
- {[Name], [Name], UpFrom, DownTo} %% no intersections
+ {[Name], [Name], [], []} %% no current in up/down and go both ways
= {[Name] -- UpFrom,
[Name] -- DownTo,
UpFrom -- DownTo,
DownTo -- UpFrom},
+ [[], []] = [S -- sets:to_list(sets:from_list(S))
+ || S <- [UpFrom, DownTo]],
+
{ok, _, _, []} = systools:make_relup(Name, UpFrom, DownTo, [{path, [Dir]},
{outdir, Dir},
silent]).
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
new file mode 100644
index 0000000000..54a161d606
--- /dev/null
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -0,0 +1,420 @@
+%%
+%% %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 capabilities exchange between Diameter nodes. In
+%% particular, of error and event handling.
+%%
+
+-module(diameter_capx_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ add_listeners/1,
+ s_no_common_application/1,
+ c_no_common_application/1,
+ s_no_common_security/1,
+ c_no_common_security/1,
+ s_unknown_peer/1,
+ c_unknown_peer/1,
+ s_unable/1,
+ c_unable/1,
+ s_client_reject/1,
+ c_client_reject/1,
+ remove_listeners/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/4,
+ peer_down/4]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(CLIENT, client).
+-define(SERVER, server).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(REALM, "erlang.org").
+-define(HOST(Name), Name ++ "." ++ ?REALM).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Name),
+ [{'Origin-Realm', ?REALM},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]}
+ | [{application, [{alias, A},
+ {dictionary, D},
+ {module, [?MODULE, A]}]}
+ || {A,D} <- [{common, ?DIAMETER_DICT_COMMON},
+ {accounting, ?DIAMETER_DICT_ACCOUNTING}]]]).
+
+-define(A, list_to_atom).
+-define(L, atom_to_list).
+
+-define(event, #diameter_event).
+-define(caps, #diameter_caps).
+-define(packet, #diameter_packet).
+
+-define(cea, #diameter_base_CEA).
+-define(answer_message, #'diameter_base_answer-message').
+
+-define(fail(T), erlang:error({T, process_info(self(), messages)})).
+
+-define(TIMEOUT, 2000).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() -> [start,
+ start_services,
+ add_listeners,
+ {group, all},
+ {group, all, [parallel]},
+ remove_listeners,
+ stop_services,
+ stop].
+
+groups() ->
+ [{all, [], lists:flatmap(fun tc/1, tc())}].
+
+%% Generate a unique hostname for each testcase so that watchdogs
+%% don't prevent a connection from being brought up immediately.
+init_per_testcase(Name, Config) ->
+ Uniq = ["." ++ integer_to_list(N) || N <- tuple_to_list(now())],
+ [{host, lists:flatten([?L(Name) | Uniq])} | Config].
+
+end_per_testcase(N, _)
+ when N == start;
+ N == start_services;
+ N == add_listeners;
+ N == remove_listeners;
+ N == stop_services;
+ N == stop ->
+ ok;
+end_per_testcase(Name, Config) ->
+ CRef = ?util:read_priv(Config, Name),
+ ok = diameter:remove_transport(?CLIENT, CRef).
+
+%% Testcases all come in two flavours, client and server.
+tc(Name) ->
+ [?A([C,$_|?L(Name)]) || C <- "cs"].
+
+tc() ->
+ [no_common_application,
+ no_common_security,
+ unknown_peer,
+ unable,
+ client_reject].
+
+%% ===========================================================================
+%% 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)).
+
+%% One server that responds only to base accounting, one that responds
+%% to both this and the common application. Share a common service just
+%% to simplify config, and because we can.
+add_listeners(Config) ->
+ Acct = listen(?SERVER,
+ [{capabilities, [{'Origin-Host', ?HOST("acct-srv")},
+ {'Auth-Application-Id', []}]},
+ {applications, [accounting]},
+ {capabilities_cb, [fun server_capx/3, acct]}]),
+ Base = listen(?SERVER,
+ [{capabilities, [{'Origin-Host', ?HOST("base-srv")}]},
+ {capabilities_cb, [fun server_capx/3, base]}]),
+ ?util:write_priv(Config, ?MODULE, {Base, Acct}). %% lref/2 reads
+
+remove_listeners(_Config) ->
+ ok = diameter:remove_transport(?SERVER, true).
+
+stop_services(_Config) ->
+ ok = diameter:stop_service(?CLIENT),
+ ok = diameter:stop_service(?SERVER).
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+%% All the testcases come in pairs, one for receiving an event on the
+%% client side, one on the server side. Note that testcases will
+%% receive events resulting from other testcases when running in
+%% parallel since the events are per service. The unique client
+%% Origin-Host for each testcase plus transport references are used to
+%% ensure that only the relevant event is extracted from the mailbox.
+%% Don't bother extracting events that aren't relevant.
+
+%% ====================
+%% Ask the accounting server to speak the common application and expect
+%% DIAMETER_NO_COMMON_APPLICATION = 5010.
+
+s_no_common_application(Config) ->
+ server_closed(Config, fun no_common_application/1, 5010).
+
+c_no_common_application(Config) ->
+ client_closed(Config, "acct-srv", fun no_common_application/1, 5010).
+
+no_common_application(Config) ->
+ connect(Config, acct, [{capabilities, [{'Acct-Application-Id', []}]},
+ {applications, [common]}]).
+
+%% ====================
+%% Ask the base server to speak accounting with an unknown security
+%% method and expect DIAMETER_NO_COMMON_SECURITY = 5017.
+
+s_no_common_security(Config) ->
+ server_closed(Config, fun no_common_security/1, 5017).
+
+c_no_common_security(Config) ->
+ client_closed(Config, "base-srv", fun no_common_security/1, 5017).
+
+no_common_security(Config) ->
+ connect(Config, base, [{capabilities, [{'Acct-Application-Id', []},
+ {'Inband-Security-Id', [17, 18]}]},
+ {applications, [common]}]).
+
+%% ====================
+%% Have the base server reject a decent CER with the protocol error
+%% DIAMETER_UNKNOWN_PEER = 3010.
+
+s_unknown_peer(Config) ->
+ server_reject(Config, fun base/1, 3010).
+
+c_unknown_peer(Config) ->
+ true = diameter:subscribe(?CLIENT),
+ OH = ?HOST("base-srv"),
+
+ {CRef, _} = base(Config),
+
+ {'CEA', ?caps{},
+ ?packet{msg = ?answer_message{'Origin-Host' = OH,
+ 'Result-Code' = 3010}}}
+ = client_recv(CRef).
+
+base(Config) ->
+ connect(Config, base, []).
+
+%% ====================
+%% Have the base server reject a decent CER with the non-protocol
+%% error DIAMETER_UNABLE_TO_COMPLY = 5012.
+
+s_unable(Config) ->
+ server_reject(Config, fun base/1, 5012).
+
+c_unable(Config) ->
+ client_closed(Config, "base-srv", fun base/1, 5012).
+
+%% ====================
+%% Have the client reject a decent CEA.
+
+s_client_reject(Config) ->
+ true = diameter:subscribe(?SERVER),
+ OH = host(Config),
+
+ {_, LRef} = client_reject(Config),
+
+ receive
+ ?event{service = ?SERVER,
+ info = {up, LRef,
+ {_, ?caps{origin_host = {_, OH}}},
+ {listen, _},
+ ?packet{}}}
+ = Info ->
+ Info
+ after ?TIMEOUT ->
+ ?fail({LRef, OH})
+ end.
+
+c_client_reject(Config) ->
+ true = diameter:subscribe(?CLIENT),
+ OH = ?HOST("acct-srv"),
+
+ {CRef, _} = client_reject(Config),
+
+ {'CEA', {capabilities_cb, _, discard},
+ ?caps{origin_host = {_, OH}},
+ ?packet{msg = ?cea{'Result-Code' = 2001}}}
+ = client_recv(CRef).
+
+client_reject(Config) ->
+ connect(Config, acct, [{capabilities_cb, fun client_capx/2}]).
+
+%% ===========================================================================
+
+%% server_closed/3
+
+server_closed(Config, F, RC) ->
+ true = diameter:subscribe(?SERVER),
+ OH = host(Config),
+
+ {_, LRef} = F(Config),
+
+ receive
+ ?event{service = ?SERVER,
+ info = {closed, LRef,
+ {'CER', RC,
+ ?caps{origin_host = {_, OH}},
+ ?packet{}}
+ = Reason,
+ {listen, _}}} ->
+ Reason
+ after ?TIMEOUT ->
+ ?fail({LRef, OH})
+ end.
+
+%% server_reject/3
+
+server_reject(Config, F, RC) ->
+ true = diameter:subscribe(?SERVER),
+ OH = host(Config),
+
+ {_, LRef} = F(Config),
+
+ receive
+ ?event{service = ?SERVER,
+ info = {closed, LRef,
+ {'CER', {capabilities_cb, _, RC},
+ ?caps{origin_host = {_, OH}},
+ ?packet{}}
+ = Reason,
+ {listen, _}}} ->
+ Reason
+ after ?TIMEOUT ->
+ ?fail({LRef, OH})
+ end.
+
+%% cliient_closed/4
+
+client_closed(Config, Host, F, RC) ->
+ true = diameter:subscribe(?CLIENT),
+ OH = ?HOST(Host),
+
+ {CRef, _} = F(Config),
+
+ {'CEA', RC, ?caps{origin_host = {_, OH}}, ?packet{}}
+ = client_recv(CRef).
+
+%% client_recv/1
+
+client_recv(CRef) ->
+ receive
+ ?event{service = ?CLIENT,
+ info = {closed, CRef, Reason, {connect, _}}} ->
+ Reason
+ after ?TIMEOUT ->
+ ?fail(CRef)
+ end.
+
+%% server_capx/3
+
+server_capx(_, ?caps{origin_host = {_, [_,$_|"unknown_peer." ++ _]}}, _) ->
+ unknown;
+
+server_capx(_, ?caps{origin_host = {_, [_,$_|"unable." ++ _]}}, _) ->
+ 5012; %% DIAMETER_UNABLE_TO_COMPLY
+
+server_capx(_, ?caps{origin_host = {OH,DH}}, _) ->
+ io:format("connection: ~p -> ~p~n", [DH,OH]),
+ ok.
+
+%% client_capx/2
+
+client_capx(_, ?caps{origin_host = {[_,$_|"client_reject." ++ _], _}}) ->
+ discard.
+
+%% ===========================================================================
+
+host(Config) ->
+ {_, H} = lists:keyfind(host, 1, Config),
+ ?HOST(H).
+
+listen(Name, Opts) ->
+ ?util:listen(Name, tcp, Opts).
+
+connect(Config, T, Opts) ->
+ {_, H} = lists:keyfind(host, 1, Config),
+ LRef = lref(Config, T),
+ CRef = connect(LRef, [{capabilities, [{'Origin-Host', ?HOST(H)}]}
+ | Opts]),
+ Name = lists:takewhile(fun(C) -> C /= $. end, H),
+ ?util:write_priv(Config, Name, CRef), %% end_per_testcase reads
+ {CRef, LRef}.
+
+connect(LRef, Opts) ->
+ [PortNr] = ?util:lport(tcp, LRef, 20),
+ {ok, CRef} = diameter:add_transport(?CLIENT,
+ {connect, opts(PortNr, Opts)}),
+ CRef.
+
+opts(PortNr, Opts) ->
+ [{transport_module, diameter_tcp},
+ {transport_config, [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}]}
+ | Opts].
+
+lref(Config, T) ->
+ case ?util:read_priv(Config, ?MODULE) of
+ {LRef, _} when T == base ->
+ LRef;
+ {_, LRef} when T == acct ->
+ LRef
+ end.
+
+%% ===========================================================================
+%% diameter callbacks
+
+peer_up(?SERVER,
+ {_, ?caps{origin_host = {"acct-srv." ++ _,
+ [_,$_|"client_reject." ++ _]}}},
+ State,
+ _) ->
+ State.
+
+peer_down(?SERVER,
+ {_, ?caps{origin_host = {"acct-srv." ++ _,
+ [_,$_|"client_reject." ++ _]}}},
+ State,
+ _) ->
+ State.
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 30c60be8e9..2e219bbb10 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -35,7 +35,8 @@
%% testcases
-export([base/1,
gen/1,
- lib/1]).
+ lib/1,
+ unknown/1]).
-include("diameter_ct.hrl").
@@ -47,7 +48,7 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [base, gen, lib].
+ [base, gen, lib, unknown].
init_per_testcase(gen, Config) ->
[{application, ?APP, App}] = diameter_util:consult(?APP, app),
@@ -74,3 +75,26 @@ gen([{dicts, Ms} | _]) ->
lib(_Config) ->
diameter_codec_test:lib().
+
+%% Have a separate AVP dictionary just to exercise more code.
+unknown(Config) ->
+ Priv = proplists:get_value(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ ok = make(Data, "recv.dia"),
+ ok = make(Data, "avps.dia"),
+ {ok, _, _} = compile("diameter_test_avps.erl"),
+ ok = make(Data, "send.dia"),
+ {ok, _, _} = compile("diameter_test_send.erl"),
+ {ok, _, _} = compile("diameter_test_recv.erl"),
+ {ok, _, _} = compile(filename:join([Data, "diameter_test_unknown.erl"]),
+ [{i, Priv}]),
+ diameter_test_unknown:run().
+
+make(Dir, File) ->
+ diameter_make:codec(filename:join([Dir, File])).
+
+compile(File) ->
+ compile(File, []).
+
+compile(File, Opts) ->
+ compile:file(File, [return | Opts]).
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/avps.dia b/lib/diameter/test/diameter_codec_SUITE_data/avps.dia
new file mode 100644
index 0000000000..c9d80a37a9
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/avps.dia
@@ -0,0 +1,25 @@
+;;
+;; %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%
+;;
+
+@name diameter_test_avps
+
+@avp_types
+
+ XXX 111 Unsigned32 M
+ YYY 222 Unsigned32 -
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
new file mode 100644
index 0000000000..bce3d78a37
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.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%
+%%
+
+-module(diameter_test_unknown).
+
+-compile(export_all).
+
+%%
+%% Test reception of unknown AVP's.
+%%
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_test_send.hrl").
+-include("diameter_test_recv.hrl").
+
+-define(HOST, "test.erlang.org").
+-define(REALM, "erlang.org").
+
+%% Patterns to match decoded AVP's.
+-define(MANDATORY_XXX, #diameter_avp{code = 111}).
+-define(NOT_MANDATORY_YYY, #diameter_avp{code = 222}).
+
+%% Ensure that an unknown AVP with an M flag is regarded as an error
+%% while one without an M flag is returned as 'AVP'.
+
+run() ->
+ H = #diameter_header{version = 1,
+ end_to_end_id = 1,
+ hop_by_hop_id = 1},
+ Vs = [{'Origin-Host', ?HOST},
+ {'Origin-Realm', ?REALM},
+ {'XXX', [0]},
+ {'YYY', [1]}],
+ Pkt = #diameter_packet{header = H,
+ msg = Vs},
+
+ [] = diameter_util:run([{?MODULE, [run, M, enc(M, Pkt)]}
+ || M <- ['AR','BR']]).
+
+enc(M, #diameter_packet{msg = Vs} = P) ->
+ diameter_codec:encode(diameter_test_send,
+ P#diameter_packet{msg = [M|Vs]}).
+
+run(M, Pkt) ->
+ dec(M, diameter_codec:decode(diameter_test_recv, Pkt)).
+%% Note that the recv dictionary defines neither XXX nor YYY.
+
+dec('AR', #diameter_packet
+ {msg = #recv_AR{'Origin-Host' = ?HOST,
+ 'Origin-Realm' = ?REALM,
+ 'AVP' = [?NOT_MANDATORY_YYY]},
+ errors = [{5001, ?MANDATORY_XXX}]}) ->
+ ok;
+
+dec('BR', #diameter_packet
+ {msg = #recv_BR{'Origin-Host' = ?HOST,
+ 'Origin-Realm' = ?REALM},
+ errors = [{5008, ?NOT_MANDATORY_YYY},
+ {5001, ?MANDATORY_XXX}]}) ->
+ ok.
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/recv.dia b/lib/diameter/test/diameter_codec_SUITE_data/recv.dia
new file mode 100644
index 0000000000..15fec5a5dd
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/recv.dia
@@ -0,0 +1,51 @@
+;;
+;; %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 17
+@name diameter_test_recv
+@prefix recv
+
+@inherits diameter_gen_base_rfc3588
+
+ Origin-Host
+ Origin-Realm
+ Result-Code
+
+@messages
+
+ AR ::= < Diameter Header: 123, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
+
+ AA ::= < Diameter Header: 123 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
+
+ BR ::= < Diameter Header: 124, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+
+ BA ::= < Diameter Header: 124 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/send.dia b/lib/diameter/test/diameter_codec_SUITE_data/send.dia
new file mode 100644
index 0000000000..1472f146ae
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/send.dia
@@ -0,0 +1,56 @@
+;;
+;; %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 17
+@name diameter_test_send
+@prefix send
+
+@inherits diameter_gen_base_rfc3588
+
+ Origin-Host
+ Origin-Realm
+ Result-Code
+
+@inherits diameter_test_avps
+
+@messages
+
+ AR ::= < Diameter Header: 123, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ XXX ]
+ [ YYY ]
+
+ AA ::= < Diameter Header: 123 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
+
+ BR ::= < Diameter Header: 124, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ XXX ]
+ [ YYY ]
+
+ BA ::= < Diameter Header: 124 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index aab7ab35cc..fbd38067a8 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -25,11 +25,14 @@
%% Test encode/decode of dictionary-related modules.
%%
--include_lib("diameter/include/diameter.hrl").
+-include("diameter.hrl").
-define(BASE, diameter_gen_base_rfc3588).
-define(BOOL, [true, false]).
+-define(A, list_to_atom).
+-define(S, atom_to_list).
+
%% ===========================================================================
%% Interface.
@@ -42,7 +45,7 @@ gen(Mod) ->
command_codes,
avp_types,
grouped,
- enums,
+ enum,
import_avps,
import_groups,
import_enums]]).
@@ -133,7 +136,7 @@ types() ->
gen(M, T) ->
[] = run(lists:map(fun(X) -> {?MODULE, [gen, M, T, X]} end,
- fetch(T, M:dict()))).
+ fetch(T, dict(M)))).
fetch(T, Spec) ->
case orddict:find(T, Spec) of
@@ -143,6 +146,10 @@ fetch(T, Spec) ->
[]
end.
+gen(M, messages = T, {Name, Code, Flags, ApplId, Avps})
+ when is_list(Name) ->
+ gen(M, T, {?A(Name), Code, Flags, ApplId, Avps});
+
gen(M, messages, {Name, Code, Flags, _, _}) ->
Rname = M:msg2rec(Name),
Name = M:rec2msg(Rname),
@@ -156,22 +163,16 @@ gen(M, messages, {Name, Code, Flags, _, _}) ->
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()),
+ Msgs = orddict:fetch(messages, dict(M)),
{_, Code, _, _, _} = lists:keyfind(Req, 1, Msgs),
{_, Code, _, _, _} = lists:keyfind(Ans, 1, Msgs);
-gen(M, avp_types, {Name, Code, Type, _Flags, _Encr}) ->
+gen(M, avp_types = T, {Name, Code, Type, Flags})
+ when is_list(Name) ->
+ gen(M, T, {?A(Name), Code, ?A(Type), Flags});
+
+gen(M, avp_types, {Name, Code, Type, _Flags}) ->
{Code, Flags, VendorId} = M:avp_header(Name),
0 = Flags band 2#00011111,
V = undefined /= VendorId,
@@ -181,11 +182,19 @@ gen(M, avp_types, {Name, Code, Type, _Flags, _Encr}) ->
B = z(B),
[] = avp_decode(M, Type, Name);
+gen(M, grouped = T, {Name, Code, Vid, Avps})
+ when is_list(Name) ->
+ gen(M, T, {?A(Name), Code, Vid, Avps});
+
gen(M, grouped, {Name, _, _, _}) ->
Rname = M:name2rec(Name),
[] = arity(M, Name, Rname);
-gen(M, enums, {Name, ED}) ->
+gen(M, enum = T, {Name, ED})
+ when is_list(Name) ->
+ gen(M, T, {?A(Name), lists:map(fun({E,D}) -> {?A(E), D} end, ED)});
+
+gen(M, enum, {Name, ED}) ->
[] = run([{?MODULE, [enum, M, Name, T]} || T <- ED]);
gen(M, Tag, {_Mod, L}) ->
@@ -253,17 +262,17 @@ arity(M, Name, AvpName, Rec) ->
%% enum/3
-enum(M, Name, {E,_}) ->
+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(import_enums) -> enum;
retag(avp_types) -> import_avps;
-retag(enums) -> import_enums.
+retag(enum) -> import_enums.
%% ===========================================================================
@@ -370,8 +379,8 @@ values('Time') ->
%% 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);
+ {_Name, Vals} = lists:keyfind(?S(Name), 1, types(enum, Mod)),
+ lists:map(fun({_,N}) -> N end, Vals);
values('Grouped', Name, Mod) ->
Rname = Mod:name2rec(Name),
@@ -400,8 +409,8 @@ values('AVP', _) ->
values(Name, Mod) ->
Avps = types(avp_types, Mod),
- {Name, _Code, Type, _Flags, _Encr} = lists:keyfind(Name, 1, Avps),
- b(values(Type, Name, Mod)).
+ {_Name, _Code, Type, _Flags} = lists:keyfind(?S(Name), 1, Avps),
+ b(values(?A(Type), Name, Mod)).
%% group/5
%%
@@ -467,7 +476,7 @@ types(T, Mod) ->
types(T, retag(T), Mod).
types(T, IT, Mod) ->
- Dict = Mod:dict(),
+ Dict = dict(Mod),
fetch(T, Dict) ++ lists:flatmap(fun({_,As}) -> As end, fetch(IT, Dict)).
%% random/[12]
@@ -498,3 +507,8 @@ flatten({_, {{badmatch, [{_, {{badmatch, _}, _}} | _] = L}, _}}) ->
L;
flatten(T) ->
[T].
+
+%% dict/1
+
+dict(Mod) ->
+ tl(Mod:dict()).
diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl
new file mode 100644
index 0000000000..3b4c9706e0
--- /dev/null
+++ b/lib/diameter/test/diameter_compiler_SUITE.erl
@@ -0,0 +1,489 @@
+%%
+%% %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 dictionary file compiler.
+%%
+
+-module(diameter_compiler_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([format/1, format/2,
+ replace/1, replace/2,
+ generate/1, generate/4, generate/0,
+ examples/1, examples/0]).
+
+-export([dict/0]). %% fake dictionary module
+
+-define(base, "base_rfc3588.dia").
+-define(util, diameter_util).
+-define(S, atom_to_list).
+-define(L, integer_to_list).
+
+%% ===========================================================================
+
+%% RE/Replacement (in the sense of re:replace/4) pairs for morphing
+%% base_rfc3588.dia. The key is 'ok' or the the expected error as
+%% returned in the first element of the error tuple returned by
+%% diameter_dict_util:parse/2.
+-define(REPLACE,
+ [{ok,
+ "",
+ ""},
+ {scan,
+ "@id 0",
+ "@id \\&"},
+ {scan,
+ "@name ",
+ "&'"},
+ {parse,
+ "@id 0",
+ "@id @id"},
+ {avp_code_already_defined,
+ "480",
+ "485"},
+ {uint32_out_of_range,
+ "@id 0",
+ "@id 4294967296"},
+ {uint32_out_of_range,
+ "@vendor 0",
+ "@vendor 4294967296"},
+ {uint32_out_of_range,
+ [{"^ *Failed-AVP .*$", "&V"},
+ {"@avp_types", "@avp_vendor_id 4294967296 Failed-AVP\n&"}]},
+ {imported_avp_already_defined,
+ "@avp_types",
+ "@inherits diameter_gen_base_rfc3588 &"},
+ {duplicate_import,
+ [{"@avp_types", "@inherits diameter_gen_base_rfc3588 Class\n&"},
+ {"@avp_types", "@inherits diameter_gen_base_rfc3588\n&"},
+ {"^@avp_types[^@]*", ""},
+ {"^@enum[^&]*", ""}]},
+ {duplicate_section,
+ "@prefix",
+ "@name"},
+ {already_declared,
+ "@enum Termination-Cause",
+ "& XXX 0\n &"},
+ {already_declared,
+ "@define Result-Code",
+ "& XXX 1000 &"},
+ {inherited_avp_already_defined,
+ "@id",
+ "@inherits nomod Origin-Host &"},
+ {avp_already_defined,
+ "@avp_types",
+ "@inherits m XXX\nXXX\n&"},
+ {avp_already_defined,
+ "@avp_types",
+ "@inherits mod1 XXX\n@inherits mod2 XXX\n&"},
+ {key_already_defined,
+ "DIAMETER_SUCCESS",
+ "& 2001\n&"},
+ {messages_without_id,
+ "@id 0",
+ ""},
+ {avp_name_already_defined,
+ "Class",
+ "& 666 Time M\n&"},
+ {avp_has_unknown_type,
+ "Enumerated",
+ "Enum"},
+ {avp_has_invalid_flag,
+ " -",
+ " X"},
+ {avp_has_duplicate_flag,
+ " -",
+ " MM"},
+ {avp_has_vendor_id,
+ "@avp_types",
+ "@avp_vendor_id 667 Class\n&"},
+ {avp_has_no_vendor,
+ [{"^ *Class .*$", "&V"},
+ {"@vendor .*", ""}]},
+ {group_already_defined,
+ "@grouped",
+ "& Failed-AVP ::= < AVP Header: 279 > " "{AVP}\n&"},
+ {grouped_avp_code_mismatch,
+ "(Failed-AVP ::= [^0-9]*27)9",
+ "&8"},
+ {grouped_avp_has_wrong_type,
+ "(Failed-AVP *279 *)Grouped",
+ "\\1Time"},
+ {grouped_avp_not_defined,
+ "Failed-AVP *.*",
+ ""},
+ {grouped_vendor_id_without_flag,
+ "(Failed-AVP .*)>",
+ "\\1 668>"},
+ {grouped_vendor_id_mismatch,
+ [{"(Failed-AVP .*)>", "\\1 17>"},
+ {"^ *Failed-AVP .*$", "&V"},
+ {"@avp_types", "@avp_vendor_id 18 Failed-AVP\n&"}]},
+ {ok,
+ [{"(Failed-AVP .*)>", "\\1 17>"},
+ {"^ *Failed-AVP .*$", "&V"}]},
+ {message_name_already_defined,
+ "CEA ::= .*:",
+ "& 257 > {Result-Code}\n&"},
+ {message_code_already_defined,
+ "CEA( ::= .*)",
+ "XXX\\1 {Result-Code}\n&"},
+ {message_has_duplicate_flag,
+ "(CER ::=.*)>",
+ "\\1, REQ>"},
+ {message_application_id_mismatch,
+ "(CER ::=.*)>",
+ "\\1 1>"},
+ {invalid_avp_order,
+ "CEA ::=",
+ "{Result-Code} &"},
+ {ok,
+ "{ Product-Name",
+ "* &"},
+ {required_avp_has_zero_max_arity,
+ "{ Product-Name",
+ "*0 &"},
+ {required_avp_has_zero_min_arity,
+ "{ Product-Name",
+ "0* &"},
+ {required_avp_has_zero_min_arity,
+ "{ Product-Name",
+ "0*0 &"},
+ {ok,
+ "{ Product-Name",
+ "*1 &"},
+ {ok,
+ "{ Product-Name",
+ "1* &"},
+ {ok,
+ "{ Product-Name",
+ "1*1 &"},
+ {ok,
+ "{ Product-Name",
+ "2* &"},
+ {ok,
+ "{ Product-Name",
+ "*2 &"},
+ {ok,
+ "{ Product-Name",
+ "2*2 &"},
+ {ok,
+ "{ Product-Name",
+ "2*3 &"},
+ {qualifier_has_min_greater_than_max,
+ "{ Product-Name",
+ "3*2 &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "* &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "0* &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "*0 &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "0*0 &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "0*1 &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "0*2 &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "*1 &"},
+ {optional_avp_has_nonzero_min_arity,
+ "\\[ Origin-State-Id",
+ "1* &"},
+ {optional_avp_has_nonzero_min_arity,
+ "\\[ Origin-State-Id",
+ "1*1 &"},
+ {ok,
+ "\\[ Origin-State-Id",
+ "*2 &"},
+ {optional_avp_has_nonzero_min_arity,
+ "\\[ Origin-State-Id",
+ "2* &"},
+ {optional_avp_has_nonzero_min_arity,
+ "\\[ Origin-State-Id",
+ "2*2 &"},
+ {optional_avp_has_nonzero_min_arity,
+ "\\[ Origin-State-Id",
+ "2*3 &"},
+ {optional_avp_has_nonzero_min_arity,
+ "\\[ Origin-State-Id",
+ "3*2 &"},
+ {ok,
+ "^ *< Session-Id",
+ "* &"},
+ {ok,
+ "^ *< Session-Id",
+ "*0 &"},
+ {ok,
+ "^ *< Session-Id",
+ "0* &"},
+ {ok,
+ "^ *< Session-Id",
+ "0*0 &"},
+ {ok,
+ "^ *< Session-Id",
+ "0*1 &"},
+ {ok,
+ "^ *< Session-Id",
+ "0*2 &"},
+ {ok,
+ "^ *< Session-Id",
+ "*1 &"},
+ {ok,
+ "^ *< Session-Id",
+ "1* &"},
+ {ok,
+ "^ *< Session-Id",
+ "1*1 &"},
+ {ok,
+ "^ *< Session-Id",
+ "*2 &"},
+ {ok,
+ "^ *< Session-Id",
+ "2* &"},
+ {ok,
+ "^ *< Session-Id",
+ "2*2 &"},
+ {ok,
+ "^ *< Session-Id",
+ "2*3 &"},
+ {qualifier_has_min_greater_than_max,
+ "^ *< Session-Id",
+ "3*2 &"},
+ {avp_already_referenced,
+ "CER ::=.*",
+ "& {Origin-Host}"},
+ {message_missing,
+ "CER ::=",
+ "XXR ::= < Diameter-Header: 666, REQ > {Origin-Host} &"},
+ {requested_avp_not_found,
+ [{"@id", "@inherits diameter_gen_base_rfc3588 XXX &"},
+ {"CEA ::=", "<XXX> &"}]},
+ {requested_avp_not_found,
+ [{"@id", "@inherits diameter_gen_base_rfc3588 'X X X' &"},
+ {"CEA ::=", "<'X X X'> &"}]},
+ {enumerated_avp_has_wrong_local_type,
+ "Enumerated",
+ "Time"},
+ {enumerated_avp_not_defined,
+ [{"{ Disconnect-Cause }", ""},
+ {"^ *Disconnect-Cause .*", ""}]},
+ {avp_not_defined,
+ "CEA ::=",
+ "<XXX> &"},
+ {not_loaded,
+ [{"@avp_types", "@inherits nomod XXX &"},
+ {"CEA ::=", "<XXX> &"}]},
+ {recompile,
+ [{"@avp_types", "@inherits " ++ ?S(?MODULE) ++ " XXX &"},
+ {"CEA ::=", "<XXX> &"}]},
+ {no_dict,
+ [{"@avp_types", "@inherits diameter XXX &"},
+ {"CEA ::=", "<XXX> &"}]},
+ {ok,
+ "@avp_types",
+ "@end & bad syntax"},
+ {parse,
+ "@avp_types",
+ "& bad syntax"},
+ {ok,
+ [{"@avp_types", "& 3XXX 666 Time M 'X X X' 667 Time -"},
+ {"^ *Class .*", "@avp_types"},
+ {"^ *Failed-AVP ", "@avp_types &"},
+ {"@grouped", "&&"},
+ {"^ *Failed-AVP ::=", "@grouped &"},
+ {"CEA ::=", "<'Class'> &"},
+ {"@avp_types", "@inherits diameter_gen_base_rfc3588 Class\n&"},
+ {"@avp_types", "@custom_types mymod "
+ "Product-Name Firmware-Revision\n"
+ "@codecs mymod "
+ "Origin-Host Origin-Realm\n&"}]}]).
+
+%% Standard dictionaries in examples/dict.
+-define(EXAMPLES, [rfc4004_mip,
+ rfc4005_nas,
+ rfc4006_cc,
+ rfc4072_eap,
+ rfc4590_digest,
+ rfc4740_sip]).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 5}}].
+
+all() ->
+ [format,
+ replace,
+ generate,
+ examples].
+
+%% Error handling testcases will make an erroneous dictionary out of
+%% the base dictionary and check that the expected error results.
+%% ?REPLACE encodes the modifications and expected error.
+init_per_suite(Config) ->
+ Path = filename:join([code:lib_dir(diameter, src), "dict", ?base]),
+ {ok, Bin} = file:read_file(Path),
+ [{base, Bin} | Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+%% format/1
+%%
+%% Ensure that parse o format is the identity map.
+
+format(Config) ->
+ Bin = proplists:get_value(base, Config),
+ [] = ?util:run([{?MODULE, [format, M, Bin]}
+ || E <- ?REPLACE,
+ {ok, M} <- [norm(E)]]).
+
+format(Mods, Bin) ->
+ B = modify(Bin, Mods),
+ {ok, Dict} = diameter_dict_util:parse(B, []),
+ {ok, D} = diameter_dict_util:parse(diameter_dict_util:format(Dict), []),
+ {Dict, Dict} = {Dict, D}.
+
+%% ===========================================================================
+%% replace/1
+%%
+%% Ensure the expected success/error when parsing a morphed common
+%% dictionary.
+
+replace(Config) ->
+ Bin = proplists:get_value(base, Config),
+ [] = ?util:run([{?MODULE, [replace, N, Bin]}
+ || E <- ?REPLACE,
+ N <- [norm(E)]]).
+
+replace({E, Mods}, Bin) ->
+ B = modify(Bin, Mods),
+ case {E, diameter_dict_util:parse(B, [{include, here()}]), Mods} of
+ {ok, {ok, Dict}, _} ->
+ Dict;
+ {_, {error, {E,_} = T}, _} ->
+ S = diameter_dict_util:format_error(T),
+ true = nochar($", S, E),
+ true = nochar($', S, E),
+ S
+ end.
+
+re({RE, Repl}, Bin) ->
+ re:replace(Bin, RE, Repl, [multiline]).
+
+%% ===========================================================================
+%% generate/1
+%%
+%% Ensure success when generating code and compiling.
+
+generate() ->
+ [{timetrap, {seconds, 2*length(?REPLACE)}}].
+
+generate(Config) ->
+ Bin = proplists:get_value(base, Config),
+ Rs = lists:zip(?REPLACE, lists:seq(1, length(?REPLACE))),
+ [] = ?util:run([{?MODULE, [generate, M, Bin, N, T]}
+ || {E,N} <- Rs,
+ {ok, M} <- [norm(E)],
+ T <- [erl, hrl, spec]]).
+
+generate(Mods, Bin, N, Mode) ->
+ B = modify(Bin, Mods ++ [{"@name .*", "@name dict" ++ ?L(N)}]),
+ {ok, Dict} = diameter_dict_util:parse(B, []),
+ File = "dict" ++ integer_to_list(N),
+ {_, ok} = {Dict, diameter_codegen:from_dict("dict",
+ Dict,
+ [{name, File},
+ {prefix, "base"},
+ debug],
+ Mode)},
+ Mode == erl
+ andalso ({ok, _} = compile:file(File ++ ".erl", [return_errors])).
+
+%% ===========================================================================
+%% examples/1
+%%
+%% Compile dictionaries extracted from various standards.
+
+examples() ->
+ [{timetrap, {seconds, 3*length(?EXAMPLES)}}].
+
+examples(_Config) ->
+ Dir = filename:join([code:lib_dir(diameter, examples), "dict"]),
+ [D || D <- ?EXAMPLES, _ <- [examples(?S(D), Dir)]].
+
+examples(Dict, Dir) ->
+ {Name, Pre} = make_name(Dict),
+ ok = diameter_make:codec(filename:join([Dir, Dict ++ ".dia"]),
+ [{name, Name},
+ {prefix, Pre},
+ inherits("rfc3588_base")
+ | opts(Dict)]),
+ {ok, _, _} = compile:file(Name ++ ".erl", [return]).
+
+opts(M)
+ when M == "rfc4006_cc";
+ M == "rfc4072_eap" ->
+ [inherits("rfc4005_nas")];
+opts("rfc4740_sip") ->
+ [inherits("rfc4590_digest")];
+opts(_) ->
+ [].
+
+inherits(File) ->
+ {Name, _} = make_name(File),
+ {inherits, File ++ "/" ++ Name}.
+
+make_name(File) ->
+ {R, [$_|N]} = lists:splitwith(fun(C) -> C /= $_ end, File),
+ {string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}.
+
+%% ===========================================================================
+
+modify(Bin, Mods) ->
+ lists:foldl(fun re/2, Bin, Mods).
+
+norm({E, RE, Repl}) ->
+ {E, [{RE, Repl}]};
+norm({_,_} = T) ->
+ T.
+
+nochar(Char, Str, Err) ->
+ Err == parse orelse not lists:member(Char, Str) orelse Str.
+
+here() ->
+ filename:dirname(code:which(?MODULE)).
+
+dict() ->
+ [0 | orddict:new()].
diff --git a/lib/diameter/test/diameter_dict_SUITE.erl b/lib/diameter/test/diameter_dict_SUITE.erl
index 87bb9727fe..5cf8506d3f 100644
--- a/lib/diameter/test/diameter_dict_SUITE.erl
+++ b/lib/diameter/test/diameter_dict_SUITE.erl
@@ -25,9 +25,7 @@
-export([suite/0,
all/0,
- groups/0,
- init_per_group/2,
- end_per_group/2]).
+ groups/0]).
%% testcases
-export([append/1,
@@ -53,10 +51,11 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[append,
@@ -71,12 +70,6 @@ tc() ->
update,
update_counter].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
%% ===========================================================================
-define(KV100, [{N,[N]} || N <- lists:seq(1,100)]).
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
index c25e9682f0..53398dd93e 100644
--- a/lib/diameter/test/diameter_failover_SUITE.erl
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -48,23 +48,13 @@
stop/1]).
%% diameter callbacks
--export([peer_up/3,
- peer_down/3,
- pick_peer/4,
+-export([pick_peer/4,
prepare_request/3,
- prepare_retransmit/3,
handle_answer/4,
- handle_error/4,
handle_request/3]).
--ifdef(DIAMETER_CT).
+-include("diameter.hrl").
-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").
%% ===========================================================================
@@ -96,7 +86,12 @@
{'Acct-Application-Id', [Dict:id()]},
{application, [{alias, ?APP_ALIAS},
{dictionary, Dict},
- {module, ?MODULE},
+ {module, #diameter_callback
+ {peer_up = false,
+ peer_down = false,
+ handle_error = false,
+ prepare_retransmit = false,
+ default = ?MODULE}},
{answer_errors, callback}]}]).
-define(SUCCESS, 2001).
@@ -179,23 +174,13 @@ realm(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.
@@ -224,22 +209,12 @@ prepare(#diameter_packet{msg = Req}, Caps) ->
{'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.
diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
new file mode 100644
index 0000000000..7f435a6b7a
--- /dev/null
+++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
@@ -0,0 +1,354 @@
+%%
+%% %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%
+%%
+
+%%
+%% Some gen_sctp-specific tests demonstrating problems that were
+%% encountered during diameter development but have nothing
+%% specifically to do with diameter. At least one of them can cause
+%% diameter_transport_SUITE testcases to fail.
+%%
+
+-module(diameter_gen_sctp_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([send_not_from_controlling_process/1,
+ send_from_multiple_clients/1,
+ receive_what_was_sent/1]).
+
+-include_lib("kernel/include/inet_sctp.hrl").
+
+%% Message from gen_sctp are of this form.
+-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}).
+
+%% Open sockets on the loopback address.
+-define(ADDR, {127,0,0,1}).
+
+%% Snooze, nap, siesta.
+-define(SLEEP(T), receive after T -> ok end).
+
+%% An indescribably long number of milliseconds after which everthing
+%% that should have happened has.
+-define(FOREVER, 2000).
+
+%% The first byte in each message we send as a simple guard against
+%% not receiving what was sent.
+-define(MAGIC, 42).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {minutes, 2}}].
+
+all() ->
+ [send_not_from_controlling_process,
+ send_from_multiple_clients,
+ receive_what_was_sent].
+
+init_per_suite(Config) ->
+ case gen_sctp:open() of
+ {ok, Sock} ->
+ gen_sctp:close(Sock),
+ Config;
+ {error, E} when E == eprotonosupport;
+ E == esocktnosupport ->
+ {skip, no_sctp}
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+
+%% send_not_from_controlling_process/1
+%%
+%% This testcase failing shows gen_sctp:send/4 hanging when called
+%% outside the controlling process of the socket in question.
+
+send_not_from_controlling_process(_) ->
+ Pids = send_not_from_controlling_process(),
+ ?SLEEP(?FOREVER),
+ try
+ [] = [{P,I} || P <- Pids, I <- [process_info(P)], I /= undefined]
+ after
+ lists:foreach(fun(P) -> exit(P, kill) end, Pids)
+ end.
+
+%% send_not_from_controlling_process/0
+%%
+%% Returns the pids of three spawned processes: a listening process, a
+%% connecting process and a sending process.
+%%
+%% The expected behaviour is that all three processes exit:
+%%
+%% - The listening process exits upon receiving an SCTP message
+%% sent by the sending process.
+%% - The connecting process exits upon listening process exit.
+%% - The sending process exits upon gen_sctp:send/4 return.
+%%
+%% The observed behaviour is that all three processes remain alive
+%% indefinitely:
+%%
+%% - The listening process never receives the SCTP message sent
+%% by the sending process.
+%% - The connecting process has an inet_reply message in its mailbox
+%% as a consequence of the call to gen_sctp:send/4 call from the
+%% sending process.
+%% - The call to gen_sctp:send/4 in the sending process doesn't return,
+%% hanging in prim_inet:getopts/2.
+
+send_not_from_controlling_process() ->
+ FPid = self(),
+ {L, MRef} = spawn_monitor(fun() -> listen(FPid) end),%% listening process
+ receive
+ {?MODULE, C, S} ->
+ erlang:demonitor(MRef, [flush]),
+ [L,C,S];
+ {'DOWN', MRef, process, _, _} = T ->
+ error(T)
+ end.
+
+%% listen/1
+
+listen(FPid) ->
+ {ok, Sock} = open(),
+ ok = gen_sctp:listen(Sock, true),
+ {ok, PortNr} = inet:port(Sock),
+ LPid = self(),
+ spawn(fun() -> connect1(PortNr, FPid, LPid) end), %% connecting process
+ Id = assoc(Sock),
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], _Bin})
+ = recv(). %% Waits with this as current_function.
+
+%% recv/0
+
+recv() ->
+ receive T -> T end.
+
+%% connect1/3
+
+connect1(PortNr, FPid, LPid) ->
+ {ok, Sock} = open(),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
+ Id = assoc(Sock),
+ FPid ! {?MODULE,
+ self(),
+ spawn(fun() -> send(Sock, Id) end)}, %% sending process
+ MRef = erlang:monitor(process, LPid),
+ down(MRef). %% Waits with this as current_function.
+
+%% down/1
+
+down(MRef) ->
+ receive {'DOWN', MRef, process, _, Reason} -> Reason end.
+
+%% send/2
+
+send(Sock, Id) ->
+ ok = gen_sctp:send(Sock, Id, 0, <<0:32>>).
+
+%% ===========================================================================
+
+%% send_from_multiple_clients/0
+%%
+%% Demonstrates sluggish delivery of messages.
+
+send_from_multiple_clients(_) ->
+ {S, Rs} = T = send_from_multiple_clients(8, 1024),
+ {false, [], _} = {?FOREVER < S,
+ Rs -- [OI || {O,_} = OI <- Rs, is_integer(O)],
+ T}.
+
+%% send_from_multiple_clients/2
+%%
+%% Opens a listening socket and then spawns a specified number of
+%% processes, each of which connects to the listening socket. Each
+%% connecting process then sends a message, whose size in bytes is
+%% passed as an argument, the listening process sends a reply
+%% containing the time at which the message was received, and the
+%% connecting process then exits upon reception of this reply.
+%%
+%% Returns the elapsed time for all connecting process to exit
+%% together with a list of exit reasons for the connecting processes.
+%% In the successful case a connecting process exits with the
+%% outbound/inbound transit times for the sent/received message as
+%% reason.
+%%
+%% The observed behaviour is that some outbound messages (that is,
+%% from a connecting process to the listening process) can take an
+%% unexpectedly long time to complete their journey. The more
+%% connecting processes, the longer the possible delay it seems.
+%%
+%% eg. (With F = fun send_from_multiple_clients/2.)
+%%
+%% 5> F(2, 1024).
+%% {875,[{128,116},{113,139}]}
+%% 6> F(4, 1024).
+%% {2995290,[{2994022,250},{2994071,80},{200,130},{211,113}]}
+%% 7> F(8, 1024).
+%% {8997461,[{8996161,116},
+%% {2996471,86},
+%% {2996278,116},
+%% {2996360,95},
+%% {246,112},
+%% {213,159},
+%% {373,173},
+%% {376,118}]}
+%% 8> F(8, 1024).
+%% {21001891,[{20999968,128},
+%% {8997891,172},
+%% {8997927,91},
+%% {2995716,164},
+%% {2995860,87},
+%% {134,100},
+%% {117,98},
+%% {149,125}]}
+
+send_from_multiple_clients(N, Sz)
+ when is_integer(N), 0 < N, is_integer(Sz), 0 < Sz ->
+ timer:tc(fun listen/2, [N, <<?MAGIC, 0:Sz/unit:8>>]).
+
+%% listen/2
+
+listen(N, Bin) ->
+ {ok, Sock} = open(),
+ ok = gen_sctp:listen(Sock, true),
+ {ok, PortNr} = inet:port(Sock),
+
+ %% Spawn a middleman that in turn spawns N connecting processes,
+ %% collects a list of exit reasons and then exits with the list as
+ %% reason. loop/3 returns when we receive this list from the
+ %% middleman's 'DOWN'.
+
+ Self = self(),
+ Fun = fun() -> exit(connect2(Self, PortNr, Bin)) end,
+ {_, MRef} = spawn_monitor(fun() -> exit(fold(N, Fun)) end),
+ loop(Sock, MRef, Bin).
+
+%% fold/2
+%%
+%% Spawn N processes and collect their exit reasons in a list.
+
+fold(N, Fun) ->
+ start(N, Fun),
+ acc(N, []).
+
+start(0, _) ->
+ ok;
+start(N, Fun) ->
+ spawn_monitor(Fun),
+ start(N-1, Fun).
+
+acc(0, Acc) ->
+ Acc;
+acc(N, Acc) ->
+ receive
+ {'DOWN', _MRef, process, _, RC} ->
+ acc(N-1, [RC | Acc])
+ end.
+
+%% loop/3
+
+loop(Sock, MRef, Bin) ->
+ receive
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], B}) ->
+ Sz = size(Bin),
+ {Sz, Bin} = {size(B), B}, %% assert
+ ok = send(Sock, Id, mark(Bin)),
+ loop(Sock, MRef, Bin);
+ ?SCTP(Sock, _) ->
+ loop(Sock, MRef, Bin);
+ {'DOWN', MRef, process, _, Reason} ->
+ Reason
+ end.
+
+%% connect2/3
+
+connect2(Pid, PortNr, Bin) ->
+ erlang:monitor(process, Pid),
+
+ {ok, Sock} = open(),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
+ Id = assoc(Sock),
+
+ %% T1 = time before send
+ %% T2 = time after listening process received our message
+ %% T3 = time after reply is received
+
+ T1 = now(),
+ ok = send(Sock, Id, Bin),
+ T2 = unmark(recv(Sock, Id)),
+ T3 = now(),
+ {timer:now_diff(T2, T1), timer:now_diff(T3, T2)}. %% {Outbound, Inbound}
+
+%% recv/2
+
+recv(Sock, Id) ->
+ receive
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin}) ->
+ Bin;
+ T -> %% eg. 'DOWN'
+ exit(T)
+ end.
+
+%% send/3
+
+send(Sock, Id, Bin) ->
+ gen_sctp:send(Sock, Id, 0, Bin).
+
+%% mark/1
+
+mark(Bin) ->
+ Info = term_to_binary(now()),
+ <<Info/binary, Bin/binary>>.
+
+%% unmark/1
+
+unmark(Bin) ->
+ {_,_,_} = binary_to_term(Bin).
+
+%% ===========================================================================
+
+%% receive_what_was_sent/1
+%%
+%% Demonstrates reception of a message that differs from that sent.
+
+receive_what_was_sent(_Config) ->
+ send_from_multiple_clients(1, 1024*32). %% fails
+
+%% ===========================================================================
+
+%% open/0
+
+open() ->
+ gen_sctp:open([{ip, ?ADDR}, {port, 0}, {active, true}, binary]).
+
+%% assoc/1
+
+assoc(Sock) ->
+ receive
+ ?SCTP(Sock, {[], #sctp_assoc_change{state = S,
+ assoc_id = Id}}) ->
+ comm_up = S, %% assert
+ Id
+ end.
diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl
index ade824c9dd..ec6a0ca731 100644
--- a/lib/diameter/test/diameter_reg_SUITE.erl
+++ b/lib/diameter/test/diameter_reg_SUITE.erl
@@ -26,8 +26,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -48,10 +46,11 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[add,
@@ -61,12 +60,6 @@ tc() ->
terms,
pids].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
ok = diameter:start(),
Config.
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
index 03f1115496..70e1866791 100644
--- a/lib/diameter/test/diameter_relay_SUITE.erl
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -35,9 +35,7 @@
-export([suite/0,
all/0,
- groups/0,
- init_per_group/2,
- end_per_group/2]).
+ groups/0]).
%% testcases
-export([start/1,
@@ -55,23 +53,14 @@
stop/1]).
%% diameter callbacks
--export([peer_up/3,
- peer_down/3,
- pick_peer/4,
+-export([pick_peer/4,
prepare_request/3,
prepare_retransmit/3,
handle_answer/4,
- handle_error/4,
handle_request/3]).
--ifdef(DIAMETER_CT).
+-include("diameter.hrl").
-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").
%% ===========================================================================
@@ -107,7 +96,10 @@
{'Acct-Application-Id', [Dict:id()]},
{application, [{alias, ?APP_ALIAS},
{dictionary, Dict},
- {module, ?MODULE},
+ {module, #diameter_callback{peer_up = false,
+ peer_down = false,
+ handle_error = false,
+ default = ?MODULE}},
{answer_errors, callback}]}]).
-define(SUCCESS, 2001).
@@ -123,21 +115,17 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, start_services, connect]
- ++ tc()
- ++ [{group, all},
- disconnect,
- stop_services,
- stop].
+ [start,
+ start_services,
+ connect,
+ {group, all},
+ {group, all, [parallel]},
+ disconnect,
+ stop_services,
+ stop].
groups() ->
- [{all, [parallel], tc()}].
-
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
+ [{all, [], tc()}].
%% Traffic cases run when services are started and connections
%% established.
@@ -254,23 +242,13 @@ call(Server) ->
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)
@@ -314,11 +292,6 @@ 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})
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
index e50a0050a6..e7807fd360 100644
--- a/lib/diameter/test/diameter_stats_SUITE.erl
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -26,8 +26,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -44,21 +42,16 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[an,
twa].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
ok = diameter:start(),
Config.
diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl
index 84f77b6066..ab629fb1c1 100644
--- a/lib/diameter/test/diameter_sync_SUITE.erl
+++ b/lib/diameter/test/diameter_sync_SUITE.erl
@@ -26,8 +26,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -48,10 +46,11 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[call,
@@ -59,12 +58,6 @@ tc() ->
timeout,
flush].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
ok = diameter:start(),
Config.
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
index 99f92ca0e0..85b953dc1a 100644
--- a/lib/diameter/test/diameter_tls_SUITE.erl
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -36,8 +36,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -58,23 +56,13 @@
stop_ssl/1]).
%% diameter callbacks
--export([peer_up/3,
- peer_down/3,
- pick_peer/4,
- prepare_request/3,
+-export([prepare_request/3,
prepare_retransmit/3,
handle_answer/4,
- handle_error/4,
handle_request/3]).
--ifdef(DIAMETER_CT).
+-include("diameter.hrl").
-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").
%% ===========================================================================
@@ -110,7 +98,11 @@
{'Auth-Application-Id', [Dict:id()]},
{application, [{alias, ?APP_ALIAS},
{dictionary, Dict},
- {module, ?MODULE},
+ {module, #diameter_callback{peer_up = false,
+ peer_down = false,
+ pick_peer = false,
+ handle_error = false,
+ default = ?MODULE}},
{answer_errors, callback}]}]).
%% Config for diameter:add_transport/2. In the listening case, listen
@@ -142,31 +134,33 @@ all() ->
start_diameter,
make_certs,
start_services,
- add_transports]
- ++ [{group, N} || {N, _, _} <- groups()]
- ++ [remove_transports, stop_services, stop_diameter, stop_ssl].
+ add_transports,
+ {group, all},
+ {group, all, [parallel]},
+ 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.
+ [{all, [], tc()}].
+%% Shouldn't really have to know about crypto here but 'ok' from
+%% ssl:start() isn't enough to guarantee that TLS is available.
init_per_suite(Config) ->
- case os:find_executable("openssl") of
- false ->
- {skip, no_openssl};
- _ ->
- Config
+ try
+ false /= os:find_executable("openssl")
+ orelse throw({?MODULE, no_openssl}),
+ ok == (catch crypto:start())
+ orelse throw({?MODULE, no_crypto}),
+ Config
+ catch
+ {?MODULE, E} ->
+ {skip, E}
end.
end_per_suite(_Config) ->
- ok.
+ crypto:stop().
%% Testcases to run when services are started and connections
%% established.
@@ -251,21 +245,6 @@ send5(_Config) ->
%% ===========================================================================
%% 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},
@@ -290,11 +269,6 @@ 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}},
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 6704f24532..6eed8d3b5d 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -87,14 +87,8 @@
handle_error/5,
handle_request/3]).
--ifdef(DIAMETER_CT).
+-include("diameter.hrl").
-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").
%% ===========================================================================
@@ -168,27 +162,16 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, start_services, add_transports, result_codes
- | [{group, N} || {N, _, _} <- groups()]]
+ [start, start_services, add_transports, result_codes]
+ ++ [{group, E, P} || E <- ?ENCODINGS, P <- [[], [parallel]]]
++ [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).
+ [{E, [], Ts} || E <- ?ENCODINGS].
init_per_group(Name, Config) ->
- E = case ?L(Name) of
- "p_" ++ Rest ->
- ?A(Rest);
- _ ->
- Name
- end,
- [{encode, E} | Config].
+ [{encode, Name} | Config].
end_per_group(_, _) ->
ok.
@@ -251,7 +234,7 @@ start_services(_Config) ->
ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)).
add_transports(Config) ->
- LRef = ?util:listen(?SERVER, tcp),
+ LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx/2}]),
CRef = ?util:connect(?CLIENT, tcp, LRef),
?util:write_priv(Config, "transport", {LRef, CRef}).
@@ -266,6 +249,10 @@ stop_services(_Config) ->
stop(_Config) ->
ok = diameter:stop().
+capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
+ io:format("connection: ~p -> ~p~n", [DH,OH]),
+ ok.
+
%% ===========================================================================
%% Ensure that result codes have the expected values.
@@ -518,10 +505,10 @@ send_multiple_filters(Config, 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) ->
+send_anything(Config) ->
#diameter_base_STA{'Result-Code' = ?SUCCESS}
= call(Config, anything).
-
+
%% ===========================================================================
call(Config, Req) ->
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index a9520ef5bd..893b7ba2f9 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -27,8 +27,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -45,8 +43,7 @@
init/2]).
-include_lib("kernel/include/inet_sctp.hrl").
--include_lib("diameter/include/diameter.hrl").
--include("diameter_ct.hrl").
+-include("diameter.hrl").
-define(util, diameter_util).
@@ -93,10 +90,13 @@ suite() ->
[{timetrap, {minutes, 2}}].
all() ->
- [start | tc()] ++ [{group, all}, stop].
+ [start,
+ {group, all},
+ {group, all, [parallel]},
+ stop].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[tcp_accept,
@@ -104,12 +104,6 @@ tc() ->
sctp_accept,
sctp_connect].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
[{sctp, have_sctp()} | Config].
@@ -176,14 +170,12 @@ connect(Prot) ->
%% have_sctp/0
have_sctp() ->
- try gen_sctp:open() of
+ case gen_sctp:open() of
{ok, Sock} ->
gen_sctp:close(Sock),
true;
- {error, eprotonosupport} -> %% fail on any other reason
- false
- catch
- error: badarg ->
+ {error, E} when E == eprotonosupport;
+ E == esocktnosupport -> %% fail on any other reason
false
end.
@@ -220,7 +212,7 @@ init(gen_connect, {Prot, Ref}) ->
[PortNr] = ?util:lport(Prot, Ref, 20),
%% Connect, send a message and receive it back.
- {ok, Sock} = gen_connect(Prot, PortNr, Ref),
+ {ok, Sock} = gen_connect(Prot, PortNr),
Bin = make_msg(),
ok = gen_send(Prot, Sock, Bin),
Bin = gen_recv(Prot, Sock);
@@ -359,20 +351,7 @@ tmod(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/2
gen_connect(sctp = P, PortNr) ->
{ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index 3fe8ea5363..0c42f955ad 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -33,8 +33,8 @@
%% diameter-specific
-export([lport/2,
lport/3,
- listen/2,
- connect/3,
+ listen/2, listen/3,
+ connect/3, connect/4,
disconnect/4]).
%% common_test-specific
@@ -212,7 +212,7 @@ read_priv(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.
@@ -254,22 +254,28 @@ lp(M, Ref, T) ->
end.
%% ---------------------------------------------------------------------------
-%% listen/2
+%% listen/2-3
%%
%% Add a listening transport on the loopback address and a free port.
listen(SvcName, Prot) ->
- add_transport(SvcName, {listen, opts(Prot, listen)}).
+ listen(SvcName, Prot, []).
+
+listen(SvcName, Prot, Opts) ->
+ add_transport(SvcName, {listen, opts(Prot, listen) ++ Opts}).
%% ---------------------------------------------------------------------------
-%% connect/3
+%% connect/2-3
%%
%% Add a connecting transport on and connect to a listening transport
%% with the specified reference.
connect(Client, Prot, LRef) ->
+ connect(Client, Prot, LRef, []).
+
+connect(Client, Prot, LRef, Opts) ->
[PortNr] = lport(Prot, LRef, 20),
- Ref = add_transport(Client, {connect, opts(Prot, PortNr)}),
+ Ref = add_transport(Client, {connect, opts(Prot, PortNr) ++ Opts}),
true = diameter:subscribe(Client),
ok = receive
{diameter_event, Client, {up, Ref, _, _, _}} -> ok
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
index dec307529a..ff40326947 100644
--- a/lib/diameter/test/diameter_watchdog_SUITE.erl
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -36,7 +36,7 @@
id/1, %% jitter callback
run/1]).
--include_lib("diameter/include/diameter.hrl").
+-include("diameter.hrl").
-include("diameter_ct.hrl").
%% ===========================================================================
@@ -306,11 +306,8 @@ 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),
+ {_MRef, Pid} = diameter_watchdog:start({Type, Ref},
+ {false, Opts, false, ?SERVICE}),
Pid.
%% ===========================================================================
@@ -350,6 +347,10 @@ init(_, _, TPid, _) ->
monitor(TPid),
3.
+monitor(Pid) ->
+ erlang:monitor(process, Pid),
+ Pid.
+
%% Generate a unique hostname for the faked peer.
hostname() ->
lists:flatten(io_lib:format("~p-~p-~p", tuple_to_list(now()))).
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index 531aca2799..7f163536fb 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -24,6 +24,7 @@ MODULES = \
diameter_ct \
diameter_util \
diameter_enum \
+ diameter_compiler_SUITE \
diameter_codec_SUITE \
diameter_codec_test \
diameter_app_SUITE \
@@ -32,11 +33,19 @@ MODULES = \
diameter_sync_SUITE \
diameter_stats_SUITE \
diameter_watchdog_SUITE \
+ diameter_gen_sctp_SUITE \
diameter_transport_SUITE \
+ diameter_capx_SUITE \
diameter_traffic_SUITE \
diameter_relay_SUITE \
diameter_tls_SUITE \
diameter_failover_SUITE
-INTERNAL_HRL_FILES = \
+HRL_FILES = \
diameter_ct.hrl
+
+DATA = \
+ diameter_codec_SUITE_data/avps.dia \
+ diameter_codec_SUITE_data/send.dia \
+ diameter_codec_SUITE_data/recv.dia \
+ diameter_codec_SUITE_data/diameter_test_unknown.erl
diff --git a/lib/diameter/test/release.sed b/lib/diameter/test/release.sed
new file mode 100644
index 0000000000..2720b778f2
--- /dev/null
+++ b/lib/diameter/test/release.sed
@@ -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%
+#
+
+#
+# This bit of gymnastics is to replace the include of diameter's
+# public hrls by include_lib when releasing testsuites, so that they
+# compile both in the development filesystem (where generated hrls
+# aren't in diameter/include) and with common_test's autocompilation
+# on an installed release. Solving the problem by installing generated
+# hrls to ../include is anathema: that directory is for handwritten
+# source.)
+#
+
+/^-include("/!b
+/"diameter_gen_/b s
+/"diameter\./!b
+
+:s
+s@("@_lib&diameter/include/@
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index c783450c9f..f6dc786417 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 0.10
+DIAMETER_VSN = 1.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)"
diff --git a/lib/docbuilder/AUTHORS b/lib/docbuilder/AUTHORS
deleted file mode 100644
index 4f2a8e9361..0000000000
--- a/lib/docbuilder/AUTHORS
+++ /dev/null
@@ -1,10 +0,0 @@
-Docbuilder is a rewrite of the Old docbuilder
-and takes XML as input instead of SGML.
-Docbuilder makes use of xmerl for parsing XML
-and produces HTML. Everything is written in Erlang
-and there are no dependencies to external tools.
-
-Original Authors:
-Gunilla Arendt
-
-Contributors:
diff --git a/lib/docbuilder/Makefile b/lib/docbuilder/Makefile
deleted file mode 100644
index 21f42421d6..0000000000
--- a/lib/docbuilder/Makefile
+++ /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$
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-#
-# Macros
-#
-
-SUB_DIRECTORIES = src dtd etc doc/src
-
-include vsn.mk
-VSN = $(DOCB_VSN)
-
-SPECIAL_TARGETS =
-
-#
-# Default Subdir Targets
-#
-include $(ERL_TOP)/make/otp_subdir.mk
-
-
diff --git a/lib/docbuilder/doc/src/Makefile b/lib/docbuilder/doc/src/Makefile
deleted file mode 100644
index ae34266844..0000000000
--- a/lib/docbuilder/doc/src/Makefile
+++ /dev/null
@@ -1,132 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(DOCB_VSN)
-APPLICATION=docbuilder
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- docb_gen.xml \
- docb_transform.xml \
- docb_xml_check.xml
-XML_REF6_FILES = \
- docbuilder_app.xml
-
-XML_PART_FILES = part.xml part_notes.xml
-XML_CHAPTER_FILES = \
- overview.xml \
- user_guide_dtds.xml \
- refman_dtds.xml \
- fasc_dtds.xml \
- header_tags.xml \
- block_tags.xml \
- inline_tags.xml \
- character_entities.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-GIF_FILES = \
- man.gif
-
-
-XML_FILES = \
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
- $(XML_APPLICATION_FILES)
-
-# ----------------------------------------------------
-
-HTML_FILES = \
- $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-man: $(MAN3_FILES) $(MAN6_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-debug opt:
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(MAN6DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
-
-release_spec:
diff --git a/lib/docbuilder/doc/src/block_tags.xml b/lib/docbuilder/doc/src/block_tags.xml
deleted file mode 100644
index f5ba083f38..0000000000
--- a/lib/docbuilder/doc/src/block_tags.xml
+++ /dev/null
@@ -1,431 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2009</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>Block Tags</title>
- <prepared/>
- <docno/>
- <date/>
- <rev/>
- <file>block_tags.xml</file>
- </header>
-
- <p>Block tags typically define a separate block of information, such
- as a paragraph or a list.</p>
-
- <p>The following subset of block tags are common for all DTDs in
- the DocBuilder DTD suite:
- <marker id="block_subset"></marker>
- <seealso marker="#pTAG">&lt;p&gt;</seealso>,
- <seealso marker="#preTAG">&lt;pre&gt;</seealso>,
- <seealso marker="#codeTAG">&lt;code&gt;</seealso>,
- <seealso marker="#listTAG">&lt;list&gt;</seealso>,
- <seealso marker="#taglistTAG">&lt;taglist&gt;</seealso>,
- <seealso marker="#codeincludeTAG">&lt;codeinclude&gt;</seealso> and
- <seealso marker="#erlevalTAG">&lt;erleval&gt;</seealso>.
- </p>
-
- <section>
- <marker id="brTAG"></marker>
- <title>&lt;br&gt; - Line Break</title>
-
- <p>Forces a newline. Example:</p>
- <pre>
-Eat yourself&lt;br/&gt;senseless!
- </pre>
- <p>results in:</p>
- <p>Eat yourself<br/>senseless!</p>
-
- <p>The <c><![CDATA[<br>]]></c> tag is both a block- and an inline
- tag.</p>
- </section>
-
- <section>
- <marker id="codeTAG"></marker>
- <title>&lt;code&gt; - Code Example</title>
-
- <p>Highlight code examples. Example:</p>
- <pre>
-&lt;code>
-sum([H|T]) ->
- H + sum(T);
-sum([]) ->
- 0.
-&lt;/code>
- </pre>
- <p>results in:</p>
- <code>
-sum([H|T]) ->
- H + sum(T);
-sum([]) ->
- 0.
- </code>
-
- <p>There is an attribute <c>type = "erl" | "c" | "none"</c>, but
- currently this attribute is ignored by DocBuilder. Default value
- is <c>"none"</c></p>
-
- <note>
- <p>No tags are allowed within the tag and no
- <seealso marker="character_entities">character
- entities</seealso> are expanded.</p>
- </note>
- </section>
-
- <section>
- <marker id="codeincludeTAG"></marker>
- <title>&lt;codeinclude&gt; - Code Inclusion</title>
-
- <p>Include external code snippets. The attribute <c>file</c>
- gives the file name and <c>tag</c> defines a string which
- delimits the code snippet. Example:</p>
- <pre>
-&lt;codeinclude file="gazonk" tag="%% Erlang example"/&gt;
- </pre>
- <p>results in:</p>
- <codeinclude file="gazonk" tag="%% Erlang example"/>
-
- <p>provided there is a file named <c>gazonk</c> looking like this:
- </p>
- <code>
-...
-
-%% Erlang example
--module(gazonk).
-
-start() ->
- {error,"Pid required!"}.
-start(Pid) ->
- spawn(fun() -> init(Pid) end).
-%% Erlang example
-
-...
- </code>
-
- <p>If the <c>tag</c> attribute is omitted, the whole file is
- included.</p>
-
- <p>There is also an attribute <c>type = "erl" | "c" | "none"</c>, but
- currently this attribute is ignored by DocBuilder. Default value
- is <c>"none"</c></p>
- </section>
-
- <section>
- <marker id="erlevalTAG"></marker>
- <title>&lt;erleval&gt; - Erlang Evaluation</title>
-
- <p>Include the result from evaluating an Erlang expression. Example:
- </p>
- <code><![CDATA[
-<erleval expr="{A,b,C}={a,b,c}. "/>
- ]]></code>
- <p>results in:</p>
- <erleval expr="{A,b,C}={a,b,c}. "></erleval>
-
- <p>Note the '.' and space after the expression.</p>
- </section>
-
- <section>
- <marker id="listTAG"></marker>
- <title>&lt;list&gt; - List</title>
-
- <p>The attribute <c>type = "ordered"|"bulleted"</c> decides if
- the list is numbered or bulleted. Default is <c>"bulleted"</c>.
- </p>
-
- <p>Lists contains list items, tag <c><![CDATA[<item>]]></c>, which
- can contain plain text,
- the <seealso marker="#block_subset">common subset of block
- tags</seealso> and <seealso marker="inline_tags">inline
- tags</seealso>. Example:</p>
- <pre>
-&lt;list type="ordered"&gt;
- &lt;item&gt;Askosal:
- &lt;list&gt;
- &lt;item&gt;Nullalisis&lt;/item>
- &lt;item&gt;Facilisis&lt;/item>
- &lt;/list&gt;
- &lt;/item>
- &lt;item&gt;Ankara&lt;/item>
-&lt;/list&gt;
- </pre>
- <p>results in:</p>
- <list type="ordered">
- <item>
- <p>Askosal:</p>
- <list type="bulleted">
- <item>Nullalisis</item>
- <item>Facilisis</item>
- </list>
- </item>
- <item>Ankara</item>
- </list>
- </section>
-
- <section>
- <marker id="markerTAG"></marker>
- <title>&lt;marker&gt; - Marker</title>
-
- <p>Used as an anchor for hypertext references. The
- <c><![CDATA[<marker>]]></c> tag is both a block- and an inline
- tag and is described in
- the <seealso marker="inline_tags#markerTAG">Inline Tags</seealso>
- section.</p>
- </section>
-
- <section>
- <marker id="pTAG"></marker>
- <title>&lt;p&gt; - Paragraph</title>
-
- <p>Paragraphs contain plain text and
- <seealso marker="inline_tags">inline tags</seealso>. Example:</p>
- <pre>
-&lt;p&gt;I call specific attention to
- the authority given by the &lt;em&gt;21st Amendment&lt;/em&gt;
- to the Constitution to prohibit transportation
- or importation of intoxicating liquors into
- any State in violation of the laws of such
- State.&lt;/p&gt;
- </pre>
- <p>results in:</p>
- <p>I call specific attention to
- the authority given by the <em>21st Amendment</em>
- to the Constitution to prohibit transportation
- or importation of intoxicating liquors into
- any State in violation of the laws of such
- State.</p>
- </section>
-
- <section>
- <marker id="noteTAG"></marker>
- <title>&lt;note&gt; - Note</title>
-
- <p>Highlights a note. Can contain block tags except
- <c><![CDATA[<note>]]></c>, <c><![CDATA[<warning>]]></c>,
- <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.
- Example:</p>
-<pre>
-&lt;note>
- &lt;p>This function is mainly intended for debugging.&lt;/p>
-&lt;/note>
- </pre>
- <p>results in:</p>
- <note>
- <p>This function is mainly intended for debugging.</p>
- </note>
- </section>
-
- <section>
- <marker id="preTAG"></marker>
- <title>&lt;pre&gt; - Pre-formatted Text</title>
-
- <p>Used for documentation of system interaction. Can contain text,
- <seealso marker="inline_tags#seealsoTAG">seealso</seealso>,
- <seealso marker="inline_tags#urlTAG">url</seealso> and
- <c><![CDATA[<input>]]></c> tags.</p>
-
- <p>The <c><![CDATA[<input>]]></c> tag is used to highlight user
- input. Example:</p>
- <pre>
-&lt;pre&gt;
-$ &lt;input&gt;erl&lt;/input&gt;
-Erlang (BEAM) emulator version 5.5.3 [async-threads:0] [hipe] [kernel-poll:false]
-
-Eshell V5.5.3 (abort with ^G)
-1&gt; &lt;input&gt;pwd().&lt;/input&gt;
-/home/user
-2&gt; &lt;input&gt;halt().&lt;/input&gt;
-&lt;/pre&gt;
- </pre>
- <p> results in:</p>
- <pre>
-$ <input>erl</input>
-Erlang (BEAM) emulator version 5.5.3 [async-threads:0] [hipe] [kernel-poll:false]
-
-Eshell V5.5.3 (abort with ^G)
-1> <input>pwd().</input>
-/home/user
-2> <input>halt().</input>
- </pre>
-
- <p>All <seealso marker="character_entities">character
- entities</seealso> are expanded.</p>
- </section>
-
- <section>
- <marker id="quoteTAG"></marker>
- <title>&lt;quote&gt; - Quotation</title>
-
- <p>Highlight quotations from other works, or dialog spoken by
- characters in a narrative. Contains one or more
- <seealso marker="#pTAG">&lt;p&gt;</seealso> tags. Example:</p>
- <pre>
-&lt;p&gt;Whereas Section 217(a) of the Act of Congress entitled
-"An Act ..." approved June 16, 1933, provides as follows:&lt;/p&gt;
-&lt;quote&gt;
- &lt;p&gt;Section 217(a) The President shall proclaim the law.&lt;/p>
-&lt;/quote&gt;
- </pre>
- <p>results in:</p>
- <p>Whereas Section 217(a) of the Act of Congress entitled
- "An Act ..." approved June 16, 1933, provides as follows:</p>
- <quote>
- <p>Section 217(a) The President shall proclaim the law.</p>
- </quote>
- </section>
-
- <section>
- <marker id="taglistTAG"></marker>
- <marker id="tagTAG"></marker>
- <title>&lt;taglist&gt; - Definition List</title>
-
- <p>Definition lists contains pairs of tags,
- <c><![CDATA[<tag>]]></c>, and list items,
- <c><![CDATA[<item>]]></c>.</p>
-
- <p><c><![CDATA[<tag>]]></c> can contain plain text,
- <seealso marker="inline_tags#cTAG">&lt;c&gt;</seealso>,
- <seealso marker="inline_tags#emTAG">&lt;em&gt;</seealso>,
- <seealso marker="inline_tags#seealsoTAG">&lt;seealso&gt;</seealso>
- and <seealso marker="inline_tags#urlTAG">&lt;url&gt;</seealso>
- tags.</p>
-
- <p><c><![CDATA[<item>]]></c> can contain plain text,
- the <seealso marker="#block_subset">common subset of block
- tags</seealso> and <seealso marker="inline_tags">inline
- tags</seealso>. Example:</p>
- <pre>
-&lt;taglist>
- &lt;tag>&lt;c>eacces&lt;/c>&lt;/tag>
- &lt;item>Permission denied.&lt;/item>
- &lt;tag>&lt;c>enoent&lt;/c>&lt;/tag>
- &lt;item>No such file or directory.&lt;/item>
-&lt;/taglist>
- </pre>
- <p>results in:</p>
- <taglist>
- <tag><c>eacces</c></tag>
- <item>Permission denied.</item>
- <tag><c>enoent</c></tag>
- <item>No such file or directory.</item>
- </taglist>
- </section>
-
- <section>
- <marker id="warningTAG"></marker>
- <title>&lt;warning&gt; - Warning</title>
-
- <p>Highlights a warning. Can contain block tags except
- <c><![CDATA[<note>]]></c>, <c><![CDATA[<warning>]]></c>,
- <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.
- Example:</p>
-<pre>
-&lt;warning>
- &lt;p>This function might be removed in a future version without
- prior warning.&lt;/p>
-&lt;/warning>
- </pre>
- <p>results in:</p>
- <warning>
- <p>This function might be removed in a future version without
- prior warning.</p>
- </warning>
- </section>
-
- <section>
- <marker id="imageTAG"></marker>
- <marker id="icaptionTAG"></marker>
- <title>&lt;image&gt; - Image</title>
-
- <p>Graphics is imported using the <c><![CDATA[<image>]]></c> tag.
- An image caption <c><![CDATA[<icaption>]]></c>, containing plain
- text, must be supplied. Example:</p>
- <pre>
-&lt;image file="man"&gt;
- &lt;icaption&gt;A Silly Man&lt;/icaption&gt;
-&lt;/image&gt;
- </pre>
- <p>results in:</p>
- <image file="man.gif">
- <icaption>A Silly Man</icaption>
- </image>
-
- <p>This assumes that <c>man.gif</c> exists in the current directory.
- </p>
- </section>
-
- <section>
- <marker id="tableTAG"></marker>
- <marker id="rowTAG"></marker>
- <marker id="cellTAG"></marker>
- <marker id="tcaptionTAG"></marker>
- <title>&lt;table&gt; - Table</title>
-
- <p>The table format is similar to how tables are described in HTML
- 3.2. A table contains one or more rows, <c><![CDATA[<row>]]></c>,
- and a table caption <c><![CDATA[<tcaption>]]></c>, containing
- plain text.</p>
-
- <p>Each row contains one or more cells, <c><![CDATA[<cell>]]></c>.
- The attributes <c>align = "left"|"center"|"right"</c> and
- <c>valign = "top"|"middle"|"bottom"</c> decides how text is
- aligned in the cell horizontally and vertically. Default is
- "<c>left</c>" and "<c>middle</c>".</p>
-
- <p>Each cell contains plain text and
- <seealso marker="inline_tags">inline tags</seealso>. Example:</p>
- <pre><![CDATA[
- <table>
- <row>
- <cell align="left" valign="top"><em>Boys</em></cell>
- <cell align="center" valign="middle"><em>Girls</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">Juda</cell>
- <cell align="right" valign="bottom">Susy</cell>
- </row>
- <row>
- <cell align="left" valign="middle">Anders</cell>
- <cell align="left" valign="middle">Victoria</cell>
- </row>
- <tcaption>A table caption</tcaption>
- </table>
- ]]></pre>
- <p>results in:</p>
- <table>
- <row>
- <cell align="left" valign="top"><em>Boys</em></cell>
- <cell align="center" valign="middle"><em>Girls</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">Juda</cell>
- <cell align="right" valign="bottom">Susy</cell>
- </row>
- <row>
- <cell align="left" valign="middle">Anders</cell>
- <cell align="left" valign="middle">Victoria</cell>
- </row>
- <tcaption>A table caption</tcaption>
- </table>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/book.xml b/lib/docbuilder/doc/src/book.xml
deleted file mode 100644
index a13d56dd8a..0000000000
--- a/lib/docbuilder/doc/src/book.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?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>1997</year><year>2009</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>DocBuilder</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>Docbuilder</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listoffigures></listoffigures>
- <listoftables></listoftables>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/docbuilder/doc/src/character_entities.xml b/lib/docbuilder/doc/src/character_entities.xml
deleted file mode 100644
index 0a4ae17fb5..0000000000
--- a/lib/docbuilder/doc/src/character_entities.xml
+++ /dev/null
@@ -1,546 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</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>Character Entities</title>
- <prepared/>
- <docno/>
- <date/>
- <rev/>
- <file>character_entities.xml</file>
- </header>
-
- <section>
- <title>Added Latin 1</title>
-
- <p>The DocBuilder DTD suite uses the same character entities as
- defined in HTML 3.2
- (<c>ISO 8879-1986//ENTITIES Added Latin 1//EN//HTML</c>). That is:
- for an &amp; (ampersand), use the entity: <c>&amp;amp;</c>, for
- &ouml; use the entity <c>&amp;ouml;</c> and so on.</p>
-
- <table>
- <row>
- <cell align="left" valign="middle"><em>Character</em></cell>
- <cell align="left" valign="middle"><em>Entity</em></cell>
- <cell align="left" valign="middle"><em>Description</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">&amp;</cell>
- <cell align="left" valign="middle">&amp;amp;</cell>
- <cell align="left" valign="middle">ampersand</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&gt;</cell>
- <cell align="left" valign="middle">&amp;gt;</cell>
- <cell align="left" valign="middle">greater than</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&lt;</cell>
- <cell align="left" valign="middle">&amp;lt;</cell>
- <cell align="left" valign="middle">less than</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&nbsp;</cell>
- <cell align="left" valign="middle">&amp;nbsp;</cell>
- <cell align="left" valign="middle">no-break space</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&iexcl;</cell>
- <cell align="left" valign="middle">&amp;iexcl;</cell>
- <cell align="left" valign="middle">inverted exclamation mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&cent;</cell>
- <cell align="left" valign="middle">&amp;cent;</cell>
- <cell align="left" valign="middle">cent sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&pound;</cell>
- <cell align="left" valign="middle">&amp;pound;</cell>
- <cell align="left" valign="middle">pound sterling sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&curren;</cell>
- <cell align="left" valign="middle">&amp;curren;</cell>
- <cell align="left" valign="middle">general currency sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&yen;</cell>
- <cell align="left" valign="middle">&amp;yen;</cell>
- <cell align="left" valign="middle">yen sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&brvbar;</cell>
- <cell align="left" valign="middle">&amp;brvbar;</cell>
- <cell align="left" valign="middle">broken (vertical) bar</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&sect;</cell>
- <cell align="left" valign="middle">&amp;sect;</cell>
- <cell align="left" valign="middle">section sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&uml;</cell>
- <cell align="left" valign="middle">&amp;uml;</cell>
- <cell align="left" valign="middle">umlaut (dieresis)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&copy;</cell>
- <cell align="left" valign="middle">&amp;copy;</cell>
- <cell align="left" valign="middle">copyright sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ordf;</cell>
- <cell align="left" valign="middle">&amp;ordf;</cell>
- <cell align="left" valign="middle">ordinal indicator, feminine</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&laquo;</cell>
- <cell align="left" valign="middle">&amp;laquo;</cell>
- <cell align="left" valign="middle">angle quotation mark, left</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&not;</cell>
- <cell align="left" valign="middle">&amp;not;</cell>
- <cell align="left" valign="middle">not sign</cell>
- </row>
- <row>
- <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>
- <row>
- <cell align="left" valign="middle">&reg;</cell>
- <cell align="left" valign="middle">&amp;reg;</cell>
- <cell align="left" valign="middle">registered sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&macr;</cell>
- <cell align="left" valign="middle">&amp;macr;</cell>
- <cell align="left" valign="middle">macron</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&deg;</cell>
- <cell align="left" valign="middle">&amp;deg;</cell>
- <cell align="left" valign="middle">degree sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&plusmn;</cell>
- <cell align="left" valign="middle">&amp;plusmn;</cell>
- <cell align="left" valign="middle">plus-or-minus</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&sup2;</cell>
- <cell align="left" valign="middle">&amp;sup2;</cell>
- <cell align="left" valign="middle">superscript two</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&sup3;</cell>
- <cell align="left" valign="middle">&amp;sup3;</cell>
- <cell align="left" valign="middle">superscript three</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&acute;</cell>
- <cell align="left" valign="middle">&amp;acute;</cell>
- <cell align="left" valign="middle">acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&micro;</cell>
- <cell align="left" valign="middle">&amp;micro;</cell>
- <cell align="left" valign="middle">micro sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&para;</cell>
- <cell align="left" valign="middle">&amp;para;</cell>
- <cell align="left" valign="middle">pilcrow (paragraph sign)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&middot;</cell>
- <cell align="left" valign="middle">&amp;middot;</cell>
- <cell align="left" valign="middle">middle dot</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&cedil;</cell>
- <cell align="left" valign="middle">&amp;cedil;</cell>
- <cell align="left" valign="middle">cedilla</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&sup1;</cell>
- <cell align="left" valign="middle">&amp;sup1;</cell>
- <cell align="left" valign="middle">superscript one</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ordm;</cell>
- <cell align="left" valign="middle">&amp;ordm;</cell>
- <cell align="left" valign="middle">ordinal indicator, masculine</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&raquo;</cell>
- <cell align="left" valign="middle">&amp;raquo;</cell>
- <cell align="left" valign="middle">angle quotation mark, right</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&frac14;</cell>
- <cell align="left" valign="middle">&amp;frac14;</cell>
- <cell align="left" valign="middle">fraction one-quarter</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&frac12;</cell>
- <cell align="left" valign="middle">&amp;frac12;</cell>
- <cell align="left" valign="middle">fraction one-half</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&frac34;</cell>
- <cell align="left" valign="middle">&amp;frac34;</cell>
- <cell align="left" valign="middle">fraction three-quarters</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&iquest;</cell>
- <cell align="left" valign="middle">&amp;iquest;</cell>
- <cell align="left" valign="middle">inverted question mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Agrave;</cell>
- <cell align="left" valign="middle">&amp;Agrave;</cell>
- <cell align="left" valign="middle">capital A, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Aacute;</cell>
- <cell align="left" valign="middle">&amp;Aacute;</cell>
- <cell align="left" valign="middle">capital A, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Acirc;</cell>
- <cell align="left" valign="middle">&amp;Acirc;</cell>
- <cell align="left" valign="middle">capital A, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Atilde;</cell>
- <cell align="left" valign="middle">&amp;Atilde;</cell>
- <cell align="left" valign="middle">capital A, tilde</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Auml;</cell>
- <cell align="left" valign="middle">&amp;Auml;</cell>
- <cell align="left" valign="middle">capital A, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Aring;</cell>
- <cell align="left" valign="middle">&amp;Aring;</cell>
- <cell align="left" valign="middle">capital A, ring</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&AElig;</cell>
- <cell align="left" valign="middle">&amp;AElig;</cell>
- <cell align="left" valign="middle">capital AE diphthong (ligature)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ccedil;</cell>
- <cell align="left" valign="middle">&amp;Ccedil;</cell>
- <cell align="left" valign="middle">capital C, cedilla</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Egrave;</cell>
- <cell align="left" valign="middle">&amp;Egrave;</cell>
- <cell align="left" valign="middle">capital E, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Eacute;</cell>
- <cell align="left" valign="middle">&amp;Eacute;</cell>
- <cell align="left" valign="middle">capital E, acute accen</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ecirc;</cell>
- <cell align="left" valign="middle">&amp;Ecirc;</cell>
- <cell align="left" valign="middle">capital E, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Euml;</cell>
- <cell align="left" valign="middle">&amp;Euml;</cell>
- <cell align="left" valign="middle">capital E, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Igrave;</cell>
- <cell align="left" valign="middle">&amp;Igrave;</cell>
- <cell align="left" valign="middle">capital I, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Iacute;</cell>
- <cell align="left" valign="middle">&amp;Iacute;</cell>
- <cell align="left" valign="middle">capital I, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Icirc;</cell>
- <cell align="left" valign="middle">&amp;Icirc;</cell>
- <cell align="left" valign="middle">capital I, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Iuml;</cell>
- <cell align="left" valign="middle">&amp;Iuml;</cell>
- <cell align="left" valign="middle">capital I, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ETH;</cell>
- <cell align="left" valign="middle">&amp;ETH;</cell>
- <cell align="left" valign="middle">capital Eth, Icelandic</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ntilde;</cell>
- <cell align="left" valign="middle">&amp;Ntilde;</cell>
- <cell align="left" valign="middle">capital N, tilde</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ograve;</cell>
- <cell align="left" valign="middle">&amp;Ograve;</cell>
- <cell align="left" valign="middle">capital O, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Oacute;</cell>
- <cell align="left" valign="middle">&amp;Oacute;</cell>
- <cell align="left" valign="middle">capital O, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ocirc;</cell>
- <cell align="left" valign="middle">&amp;Ocirc;</cell>
- <cell align="left" valign="middle">capital O, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Otilde;</cell>
- <cell align="left" valign="middle">&amp;Otilde;</cell>
- <cell align="left" valign="middle">capital O, tilde</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ouml;</cell>
- <cell align="left" valign="middle">&amp;Ouml;</cell>
- <cell align="left" valign="middle">capital O, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&times;</cell>
- <cell align="left" valign="middle">&amp;times;</cell>
- <cell align="left" valign="middle">multiply sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Oslash;</cell>
- <cell align="left" valign="middle">&amp;Oslash;</cell>
- <cell align="left" valign="middle">capital O, slash</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ugrave;</cell>
- <cell align="left" valign="middle">&amp;Ugrave;</cell>
- <cell align="left" valign="middle">capital U, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Uacute;</cell>
- <cell align="left" valign="middle">&amp;Uacute;</cell>
- <cell align="left" valign="middle">capital U, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Ucirc;</cell>
- <cell align="left" valign="middle">&amp;Ucirc;</cell>
- <cell align="left" valign="middle">capital U, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Uuml;</cell>
- <cell align="left" valign="middle">&amp;Uuml;</cell>
- <cell align="left" valign="middle">capital U, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&Yacute;</cell>
- <cell align="left" valign="middle">&amp;Yacute;</cell>
- <cell align="left" valign="middle">capital Y, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&THORN;</cell>
- <cell align="left" valign="middle">&amp;THORN;</cell>
- <cell align="left" valign="middle">capital THORN, Icelandic</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&szlig;</cell>
- <cell align="left" valign="middle">&amp;szlig;</cell>
- <cell align="left" valign="middle">small sharp s, German (sz ligature)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&agrave;</cell>
- <cell align="left" valign="middle">&amp;agrave;</cell>
- <cell align="left" valign="middle">small a, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&aacute;</cell>
- <cell align="left" valign="middle">&amp;aacute;</cell>
- <cell align="left" valign="middle">small a, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&acirc;</cell>
- <cell align="left" valign="middle">&amp;acirc;</cell>
- <cell align="left" valign="middle">small a, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&atilde;</cell>
- <cell align="left" valign="middle">&amp;atilde;</cell>
- <cell align="left" valign="middle">small a, tilde</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&auml;</cell>
- <cell align="left" valign="middle">&amp;auml;</cell>
- <cell align="left" valign="middle">small a, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&aring;</cell>
- <cell align="left" valign="middle">&amp;aring;</cell>
- <cell align="left" valign="middle">small a, ring</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&aelig;</cell>
- <cell align="left" valign="middle">&amp;aelig;</cell>
- <cell align="left" valign="middle">small ae diphthong (ligature)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ccedil;</cell>
- <cell align="left" valign="middle">&amp;ccedil;</cell>
- <cell align="left" valign="middle">small c, cedilla</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&egrave;</cell>
- <cell align="left" valign="middle">&amp;egrave;</cell>
- <cell align="left" valign="middle">small e, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&eacute;</cell>
- <cell align="left" valign="middle">&amp;eacute;</cell>
- <cell align="left" valign="middle">small e, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ecirc;</cell>
- <cell align="left" valign="middle">&amp;ecirc;</cell>
- <cell align="left" valign="middle">small e, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&euml;</cell>
- <cell align="left" valign="middle">&amp;euml;</cell>
- <cell align="left" valign="middle">small e, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&igrave;</cell>
- <cell align="left" valign="middle">&amp;igrave;</cell>
- <cell align="left" valign="middle">small i, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&iacute;</cell>
- <cell align="left" valign="middle">&amp;iacute;</cell>
- <cell align="left" valign="middle">small i, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&icirc;</cell>
- <cell align="left" valign="middle">&amp;icirc;</cell>
- <cell align="left" valign="middle">small i, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&iuml;</cell>
- <cell align="left" valign="middle">&amp;iuml;</cell>
- <cell align="left" valign="middle">small i, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&eth;</cell>
- <cell align="left" valign="middle">&amp;eth;</cell>
- <cell align="left" valign="middle">small eth, Icelandic</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ntilde;</cell>
- <cell align="left" valign="middle">&amp;ntilde;</cell>
- <cell align="left" valign="middle">small n, tilde</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ograve;</cell>
- <cell align="left" valign="middle">&amp;ograve;</cell>
- <cell align="left" valign="middle">small o, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&oacute;</cell>
- <cell align="left" valign="middle">&amp;oacute;</cell>
- <cell align="left" valign="middle">small o, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ocirc;</cell>
- <cell align="left" valign="middle">&amp;ocirc;</cell>
- <cell align="left" valign="middle">small o, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&otilde;</cell>
- <cell align="left" valign="middle">&amp;otilde;</cell>
- <cell align="left" valign="middle">small o, tilde</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ouml;</cell>
- <cell align="left" valign="middle">&amp;ouml;</cell>
- <cell align="left" valign="middle">small o, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&divide;</cell>
- <cell align="left" valign="middle">&amp;divide;</cell>
- <cell align="left" valign="middle">divide sign</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&oslash;</cell>
- <cell align="left" valign="middle">&amp;oslash;</cell>
- <cell align="left" valign="middle">small o, slash</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ugrave;</cell>
- <cell align="left" valign="middle">&amp;ugrave;</cell>
- <cell align="left" valign="middle">small u, grave accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&uacute;</cell>
- <cell align="left" valign="middle">&amp;uacute;</cell>
- <cell align="left" valign="middle">small u, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&ucirc;</cell>
- <cell align="left" valign="middle">&amp;ucirc;</cell>
- <cell align="left" valign="middle">small u, circumflex accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&uuml;</cell>
- <cell align="left" valign="middle">&amp;uuml;</cell>
- <cell align="left" valign="middle">small u, dieresis or umlaut mark</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&yacute;</cell>
- <cell align="left" valign="middle">&amp;yacute;</cell>
- <cell align="left" valign="middle">small y, acute accent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&thorn;</cell>
- <cell align="left" valign="middle">&amp;thorn;</cell>
- <cell align="left" valign="middle">small thorn, Icelandic</cell>
- </row>
- <row>
- <cell align="left" valign="middle">&yuml;</cell>
- <cell align="left" valign="middle">&amp;yuml;</cell>
- <cell align="left" valign="middle">small y, dieresis or umlaut mark</cell>
- </row>
- <tcaption>Accented Latin-1 alphabetic characters.</tcaption>
- </table>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/docb_gen.xml b/lib/docbuilder/doc/src/docb_gen.xml
deleted file mode 100644
index d4ebfd0f84..0000000000
--- a/lib/docbuilder/doc/src/docb_gen.xml
+++ /dev/null
@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
- <title>docb_gen</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>docb_gen</module>
- <modulesummary>Generate XML from EDoc comments in Erlang source code.
- </modulesummary>
-
- <description>
- <p><c>docb_gen</c> contains functions for generating XML
- documentation source code according to the <c>erlref</c> or
- <c>chapter</c> DTD from
- <seealso marker="edoc:chapter">EDoc</seealso> comments in Erlang
- source code or an <c>overview.edoc</c> file, using EDoc.</p>
- </description>
-
- <funcs>
- <func>
- <name>module(File) -> ok | {error, Reason}</name>
- <name>module(File, Options) -> ok | {error, Reason}</name>
- <fsummary>Generate XML from EDoc comments in Erlang source code.
- </fsummary>
- <type>
- <v>File = string()</v>
- <v>Options = [Opt]</v>
- <v>Opt = {def,Defs} | {includes,Dirs} | {preprocess,Bool}
- | {sort_functions,Bool}</v>
- <v>Defs = [{atom(),string()}]</v>
- <v>Dirs = [string()]</v>
- <v>Bool = bool()</v>
- <v>Reason = badfile | {badopt,term()} | term()</v>
- </type>
- <desc>
- <p>Generates XML documentation source code according to
- the <c>erlref</c> DTD from EDoc comments <c>File</c>, using
- the EDoc application.</p>
-
- <p><c>File</c> is an Erlang source file, given with or without
- the <c>.erl</c> extension as <c>Name.erl</c> or <c>Name</c>.
- The resulting XML file is created in the current working
- directory and named <c>Name.xml</c>.</p>
-
- <p><c>Options</c> is a list of options, see below.</p>
-
- <p>Returns <c>ok</c> if successful, and an error tuple
- otherwise.</p>
- </desc>
- </func>
-
- <func>
- <name>users_guide(File) -> ok | {error, Reason}</name>
- <name>users_guide(File, Options) -> ok | {error, Reason}</name>
- <fsummary>Generate XML from EDoc comments in Erlang source code
- </fsummary>
- <type>
- <v>File -- see module/1,2</v>
- <v>Options -- see module/1,2</v>
- <v>Reason -- see module/1,2</v>
- </type>
- <desc>
- <p>Like <c>module/1,2</c> but generates XML source code
- according to the <c>chapter</c> DTD from an
- <c>overview.edoc</c> or similar file.</p>
-
- <p>The resulting file is named <c>chapter.xml</c>.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Options</title>
- <taglist>
- <tag><c>{def, [{Name,Text}]}</c></tag>
- <item>Specifies EDoc macro definitions. See
- <seealso marker="edoc:edoc">edoc:get_doc/2</seealso>.</item>
-
- <tag><c>{includes, [Dir]}</c></tag>
- <item>Specifies directories where EDoc should search for include
- files. See
- <seealso marker="edoc:edoc">edoc:read_source/2</seealso>.</item>
-
- <tag><c>{preprocess, true|false}</c></tag>
- <item>Specifies if EDoc should read the source file via the Erlang
- preprocessor. Default is <c>false</c>. See
- <seealso marker="edoc:edoc">edoc:read_source/2</seealso>.</item>
-
- <tag><c>{sort_functions, true|false}</c></tag>
- <item>Specifies if the functions in the resulting XML file should
- be sorted alphabetically. Default is <c>true</c>.</item>
- </taglist>
- </section>
-
- <section>
- <title>Limitations</title>
- <p>The mapping from the EDoc XHTML output to valid Erlang/OTP XML
- is not complete. An attempt has been made to cover the most
- commonly used XHTML constructs, but there will still be cases
- where XML generation fails or where the resulting XML is
- inadequate. This is especially true for <c>users_guide/1,2</c>.
- </p>
-
- <p>Known limitations for some XHTML tags:</p>
- <taglist>
- <tag><c><![CDATA[<a>]]></c></tag>
- <item>
- <p>All attributes except the first <c>href</c> or <c>name</c>
- attribute are ignored.</p>
- <p>A <c>href</c> attribute means the <c><![CDATA[<a>]]></c> tag
- will be transformed to a <c><![CDATA[<seealso>]]></c> or
- <c><![CDATA[<url>]]></c> tag and an attempt is made to
- resolve the reference if necessary.</p>
-
- <p>A <c>name</c> attribute means the <c><![CDATA[<a>]]></c> tag
- will be transformed to a <c><![CDATA[<marker>]]></c> tag.</p>
- </item>
-
- <tag><c><![CDATA[<b>, <em>, <pre>]]></c></tag>
- <item>Cannot contain other tags in Erlang/OTP XML, content is
- converted to plain text.
- </item>
-
- <tag><c><![CDATA[<center>]]></c></tag>
- <item>No corresponding Erlang/OTP XML tag, converted to plain
- text.
- </item>
-
- <tag><c><![CDATA[<font>]]></c></tag>
- <item>No corresponding Erlang/OTP XML tag, converted to plain
- text.
- </item>
-
- <tag><c><![CDATA[<h1>, <h2>, ...]]></c></tag>
- <item>There is no tag corresponding to a header in Erlang/OTP XML,
- so these are converted to plain text instead, with
- the exception of <c><![CDATA[<h3>]]></c> and
- <c><![CDATA[<h4>]]></c> tags within <c>overview.edoc</c>, see
- part about "<c>chapter</c> DTD" below.
- </item>
-
- <tag><c><![CDATA[<sup>]]></c></tag>
- <item>There is no tag corresponding to superscript in Erlang/OTP
- XML, so this is converted to plain text within brackets "(..)".
- </item>
-
- <tag>References</tag>
- <item>The markers automatically inserted by EDoc at each heading
- and function will override the markers automatically inserted
- by DocBuilder, with the unfortunate result that the links in
- the left-hand frame of the User's Guide will not work, and
- also that cross referencing a function in a module the usual
- Erlang/OTP way
- "<c><![CDATA[<seealso marker="edoc:edoc#run/3...>]]></c>" does
- not work. (But
- "<c><![CDATA[<seealso marker="edoc:edoc#run-3...>]]></c>" does.)
- </item>
- </taglist>
-
- <p><em>erlref DTD</em></p>
- <taglist>
- <tag>Tables</tag>
- <item>Tables are not allowed. The contents of a table is
- converted to text instead, each row corresponding to one line
- of text.
- </item>
- </taglist>
-
- <p><em>chapter DTD</em></p>
- <taglist>
- <tag>Sections</tag>
- <item>Only two levels of sections. <c><![CDATA[<h3>]]></c>
- (equivalent to EDoc headings "<c>== Heading ==</c>") is
- interpreted as start of top-level section, or if there is no
- <c><![CDATA[<h3>]]></c> tag, the entire document is made into
- one top-level section. <c><![CDATA[<h4>]]></c> (equivalent to
- EDoc sub-headings ("<c><![CDATA[=== Sub-heading ===]]></c>") is
- interpreted as start of second-level section.
- </item>
-
- <tag>Tables</tag>
- <item>Tables without borders are converted to text in the same
- manner as for the <c>erlref</c> DTD.
- </item>
- </taglist>
- </section>
-
-</erlref>
-
diff --git a/lib/docbuilder/doc/src/docb_transform.xml b/lib/docbuilder/doc/src/docb_transform.xml
deleted file mode 100644
index 06a04c8c02..0000000000
--- a/lib/docbuilder/doc/src/docb_transform.xml
+++ /dev/null
@@ -1,224 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>docb_transform</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>docb_transform</module>
- <modulesummary>Transform XML to HTML</modulesummary>
- <description>
- <p><c>docb_transform</c> contains functions for transforming XML
- documentation source code to HTML.</p>
- </description>
-
- <funcs>
- <func>
- <name>file(File) -> ok | {error, Reason}</name>
- <name>file(File, Options) -> ok | {error, Reason}</name>
- <fsummary>Transform XML to HTML</fsummary>
- <type>
- <v>File = string()</v>
- <v>Options = [Opt]</v>
- <v>Opt -- see below</v>
- </type>
- <desc>
- <p>Transforms XML documentation source code to HTML.</p>
-
- <p><c>File</c> is a documentation source file, given with or
- without the <c>.xml</c> extension as <c>Name.xml</c> or
- <c>Name</c>.</p>
-
- <p>If <c>File</c> contains XML code according to a basic DTD
- (<c>chapter</c>, <c>erlref</c>, ...), the resulting HTML
- file is named <c>Name.html</c>.</p>
-
- <p>If <c>File</c> contains XML code according to a compound DTD
- (<c>application</c> or <c>part</c>), several files are
- created:</p>
- <list>
- <item>A cover page for the application with two frames,
- <c>Name_frame.html</c>.</item>
- <item>The contents of the left frame and a front page,
- <c>Name.html</c> and <c>Name_first.html</c>.</item>
- <item>A bibliography and a glossary, <c>Name_cite.html</c>
- and <c>Name_term.html</c>.</item>
- <item>In the case of an <c>application</c> DTD an index
- is created, <c>Name.kwc</c> and <c>Name_index.html</c>.
- </item>
- <item>One HTML file for each file included from <c>File</c>.
- </item>
- <item>Also, if there exists a <c>fascicules.xml</c> file where
- the value of the <c>entry</c> attribute for <c>File</c> is
- <c>"yes"</c>, the cover page is copied to <c>index.html</c>.
- </item>
- </list>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Options</title>
- <taglist>
- <tag><c>{html_mod, Module}, Module=atom()</c></tag>
- <item>
- <p>A callback module can be used for specifying HTML snippets
- that should be included in the generated HTML files, see
- below.</p>
- </item>
-
- <tag><c>{outdir, Dir}, Dir=string()</c></tag>
- <item>
- <p>Destination for generated files. Default is current working
- directory.</p>
- </item>
-
- <tag><c>{number, Number}, Number=int()</c></tag>
- <item>
- <p>First chapter number when transforming a <c>chapter</c>
- file. Default is 1.</p>
- </item>
-
- <tag><c>{ptype, unix|windows}</c></tag>
- <item>
- <p>For <c>path</c> elements, the specified file path should be
- presented.</p>
- </item>
-
- <tag><c>silent</c></tag>
- <item>
- <p>Silent - no warnings, only error information is printed.</p>
- </item>
-
- <tag><c>{top, Index}, Index=string()</c></tag>
- <item>
- <p>Specifies the value of "Top" in the left frame of a front
- page, which normally should be some kind of top index file
- for the documentation.</p>
- </item>
-
- <tag><c>{vsn, Vsn}, Vsn=string()</c></tag>
- <item>
- <p>Application version number. Overrides a version number
- defined in the XML document. Visible in the left frame and
- on the front page.</p>
- </item>
-
- <tag><c>{term_defs, File}, File=string()</c></tag>
- <item>
- <p>Use the global glossary definitions in <c>File</c>, which
- should contain a list of tuples <c>{Id, Name, Definition,
- Owner}</c>. See the section
- <seealso marker="inline_tags#termTAG">&lt;term&gt;,
- &lt;termdef&gt; - Glossary</seealso> in the User's Guide.
- </p>
- </item>
-
- <tag><c>{cite_defs, File}, File=string()</c></tag>
- <item>
- <p>Use the global bibliography definitions in <c>File</c>, which
- should contain a list of tuples <c>{Id, Title, Info,
- Owner}</c>. See the section
- <seealso marker="inline_tags#citeTAG">&lt;cite&gt;,
- &lt;citedef&gt; - Bibliography</seealso> in the User's
- Guide.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Callback Module</title>
-
- <p>A <c>html_mod</c> callback module can include the functions
- specified below. Note that there is no check that the resulting
- HTML code is valid. All functions are optional.</p>
- </section>
-
- <funcs>
- <func>
- <name>Module:head() -> string()</name>
- <fsummary>Snippet to be included in head of a document.</fsummary>
- <desc>
- <p>Defines a HTML snippet to be included in the head of
- a document, after the <c>&lt;HEAD></c> start tag and
- <c>&lt;TITLE></c> tag:</p>
- <pre>
-&lt;HTML>
-&lt;HEAD>
- &lt;TITLE>...&lt;/TITLE>
- - snippet is included here -
- ...
-&lt;/HEAD>
-...
-&lt;/HTML>
- </pre>
- </desc>
- </func>
-
- <func>
- <name>Module:top() -> string()</name>
- <fsummary>Snippet to be included at the top of a document.
- </fsummary>
- <desc>
- <p>Defines a HTML snippet to be included at the top of a
- document, after the <c>&lt;BODY></c> start tag.</p>
- </desc>
- </func>
-
- <func>
- <name>Module:bottom() -> string()</name>
- <fsummary>Snippet to be included at the bottom of a document.
- </fsummary>
- <desc>
- <p>Defines a HTML snippet to be included at the bottom of a
- document, before the <c>&lt;/BODY></c> end tag.</p>
- </desc>
- </func>
-
- <func>
- <name>Module:seealso(SeeAlso) -> Href</name>
- <fsummary></fsummary>
- <type>
- <v>SeeAlso = Href = string()</v>
- </type>
- <desc>
- <p>When referring to another part of the document, or another
- document, the XML tag <c>&lt;seealso&gt;</c> is used:
- <c><![CDATA[<seealso marker="File#Marker">...text...</seealso>]]></c>.
- By default, this is translated to
- <c><![CDATA[<A HREF="File.html#Marker>...text...</A>]]></c>.</p>
-
- <p>This function makes it possible to specify an alternative
- translation <c>Href</c> of the <c>marker</c> attribute value
- <c>SeeAlso</c>. For example, in OTP this is used to resolve
- cross references between applications.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/docbuilder/doc/src/docb_xml_check.xml b/lib/docbuilder/doc/src/docb_xml_check.xml
deleted file mode 100644
index eff4fc4342..0000000000
--- a/lib/docbuilder/doc/src/docb_xml_check.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2007</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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>docb_xml_check</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>docb_xml_check</module>
- <modulesummary>Validate XML documentation source code</modulesummary>
- <description>
- <p><c>docb_xml_check</c> contains functions for validating XML
- documentation source code.</p>
- </description>
-
- <funcs>
- <func>
- <name>validate(File) -> ok | error | {error, badfile}</name>
- <fsummary>Validate XML source code.</fsummary>
- <type>
- <v>File = string()</v>
- </type>
- <desc>
- <p>Validates the XML documentation source code in <c>File</c>.
- The <c>.xml</c> extension can be omitted.</p>
-
- <p>Returns <c>ok</c> if successful, otherwise error information
- is printed and the function returns <c>error</c>.
- If <c>File</c> does not exist, <c>{error, badfile}</c> is
- returned.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/docbuilder/doc/src/docbuilder_app.xml b/lib/docbuilder/doc/src/docbuilder_app.xml
deleted file mode 100644
index 58b8daf598..0000000000
--- a/lib/docbuilder/doc/src/docbuilder_app.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE appref SYSTEM "appref.dtd">
-
-<appref>
- <header>
- <copyright>
- <year>2007</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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>docbuilder</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <app>docbuilder</app>
- <appsummary>The DocBuilder Application</appsummary>
- <description>
- <p>DocBuilder provides functionality for generating HTML
- documentation for Erlang modules and Erlang/OTP applications
- from XML source code and/or EDoc comments in Erlang source code.
- </p>
- </description>
-
- <section>
- <title>Limitations</title>
- <p>DocBuilder is primarily intended for generating documentation
- for Erlang/OTP itself. That is, no attempt has been made to create
- a tool suitable for generating documentation in general.</p>
- </section>
-
- <section>
- <title>See Also</title>
- <p>DocBuilder User's Guide,
- <seealso marker="docb_gen">docb_gen(3)</seealso>,
- <seealso marker="docb_transform">docb_transform(3)</seealso>
- <seealso marker="docb_xml_check"></seealso></p>
- </section>
-
-</appref>
-
diff --git a/lib/docbuilder/doc/src/fasc_dtds.xml b/lib/docbuilder/doc/src/fasc_dtds.xml
deleted file mode 100644
index dec8189b55..0000000000
--- a/lib/docbuilder/doc/src/fasc_dtds.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2007</year><year>2009</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>Fascicules DTDs</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>fasc_dtds.xml</file>
- </header>
-
- <section>
- <title>The fascicules DTD</title>
-
- <p>The <c>fascicules</c> DTD is a special kind of DTD which can be
- used to specify the different parts of the documentation, and
- which one of those should be shown as default.</p>
-
- <p>Example:</p>
-
- <pre><![CDATA[
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
-</fascicules>
- ]]></pre>
-
- <p>In the example, it is specified that the documentation for this
- application consists of three parts: User's Guide, where
- the "cover page" (with the two frames) is located in
- <c>part_frame.html</c>, Reference Manual with the cover page
- <c>ref_man_frame.html</c> and Release Notes with the cover page
- <c>part_notes_frame.html</c>.</p>
-
- <p>As a result, at the top of the left frame in the generated HTML
- documentation, there will be corresponding links to User's Guide,
- Reference Manual and Release Notes.</p>
-
- <p>The attribute <c>entry="yes"</c> specifies that it is
- the Reference Manual which should be shown as default. This means
- that when generating the HTML files, <c>application_frame.html</c>
- will be copied to <c>index.html</c>.</p>
-
- <note>
- <p>DocBuilder assumes that the XML file written according to
- the <c>fascicules</c> DTD is called <c>fascicules.xml</c>.</p>
- </note>
-
- <p>This file is optional. If it does not exist, there are no links
- to other parts of the documentation (as they are not known) in
- the left frame, and no <c>index.html</c> is created.</p>
- </section>
-
- <section>
- <marker id="fasciculesTAG"></marker>
- <title>&lt;fascicules&gt;</title>
-
- <p>Top level tag for the <c>fascicules</c> DTD.</p>
-
- <p>Contains one or more
- <seealso marker="#fasciculeTAG">&lt;fascicule&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="fasciculeTAG"></marker>
- <title>&lt;fascicule&gt;</title>
-
- <p>Specifies properties for one "part" of the documentation for an
- application.</p>
-
- <p>Contains plain text, the name of this part.</p>
-
- <p>The <c>file</c> attribute should specify the file name for
- the corresponding <c>part</c> or <c>application</c>, without
- the <c>.xml</c> extension.</p>
-
- <p>The <c>href</c> attribute should specify the file name for
- the corresponding HTML cover page file, without the <c>.html</c>
- extension.</p>
-
- <p>The optional <c>entry="yes"|"no"</c> attribute specifies if
- the HTML cover page should be copied to <c>index.html</c> or
- not. Default is <c>"no"</c>.</p>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/gazonk b/lib/docbuilder/doc/src/gazonk
deleted file mode 100644
index 1cf0b8f7bc..0000000000
--- a/lib/docbuilder/doc/src/gazonk
+++ /dev/null
@@ -1,17 +0,0 @@
-This example code is used in block_tags.xml.
-
-%% Erlang example
--module(gazonk).
-
-start() ->
- {error,"Pid required!"}.
-
-start(Pid) ->
- spawn(smalltalk,main,[]).
-%% Erlang example
-
-// A little C example
-int main() {
- for(;;);
-}
-// A little C example
diff --git a/lib/docbuilder/doc/src/header_tags.xml b/lib/docbuilder/doc/src/header_tags.xml
deleted file mode 100644
index b1456d679a..0000000000
--- a/lib/docbuilder/doc/src/header_tags.xml
+++ /dev/null
@@ -1,183 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2009</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>Header Tags</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>header_tags.xml</file>
- </header>
-
- <p>Each document begins with a header part, which looks the same for
- all DTDs. Here the title of the document is specified, as well as
- administrative data like who is responsible for the document, which
- version is it, when was it last changed and such.</p>
-
- <p>An full header looks like:</p>
- <pre>
-&lt;header>
- &lt;copyright>...&lt;/copyright>
- &lt;legalnotice>...&lt;/legalnotice>
- &lt;title>...&lt;/title>
- &lt;prepared>...&lt;/prepared>
- &lt;responsible>...&lt;/responsible>
- &lt;docno>...&lt;/docno>
- &lt;approved>...&lt;/approved>
- &lt;checked>...&lt;/checked>
- &lt;date>...&lt;/date>
- &lt;rev>...&lt;/rev>
- &lt;file>...&lt;/file>
-&lt;/header>
- </pre>
-
- <section>
- <marker id="headerTAG"></marker>
- <title>&lt;header&gt;</title>
-
- <p>Top level tag for the header part.</p>
- </section>
-
- <section>
- <marker id="copyrightTAG"></marker>
- <title>&lt;copyright&gt;</title>
-
- <p>The <c>copyright</c> element holds information about date(s) and holder(s) of
- a document copyright. The <c>copyright</c> element is optional.
- The <c>copyright</c> element has an inner structure containing one or
- more
- <c>year</c> elements followed by zero of more <c>holder</c> elements.<br/>
- See example below:
- </p>
- <code><![CDATA[
- <copyright>
- <year>1997</year>
- <year>2007</year>
- <holder>Ericsson AB</holder>
- </copyright>
- ]]></code>
- </section>
-
- <section>
- <marker id="legalnoticeTAG"></marker>
- <title>&lt;legalnotice&gt;</title>
-
- <p>The <c>legalnotice</c> element is used to express copyright, trademark,
- license, and other legal formalities of a document. The element contains
- only PCDATA in the same manner as <c>code</c> and <c>pre</c>.
- </p>
- </section>
-
- <section>
- <marker id="titleTAG"></marker>
- <title>&lt;title&gt;</title>
-
- <p>For <c>part</c> and <c>application</c> documents, this will be
- the title of the document, visible in the left frame and on
- the front page.</p>
-
- <p>For <c>chapter</c> documents, this will be the chapter name.</p>
-
- <p>For reference manual documents, this tag is ignored.</p>
- </section>
-
- <section>
- <title>&lt;shorttitle&gt;</title>
-
- <p>This optional tag is ignored by DocBuilder. It will likely be
- removed in the future.</p>
- </section>
-
- <section>
- <marker id="preparedTAG"></marker>
- <title>&lt;prepared&gt;</title>
-
- <p>This tag is intended for administrative use and is ignored by
- DocBuilder.</p>
- </section>
-
- <section>
- <marker id="responsibleTAG"></marker>
- <title>&lt;responsible&gt;</title>
-
- <p>This optional tag is intended for administrative use and is
- ignored by DocBuilder.</p>
- </section>
-
- <section>
- <marker id="docnoTAG"></marker>
- <title>&lt;docno&gt;</title>
-
- <p>Document number.</p>
-
- <p>For <c>part</c> and <c>application</c> documents, the document
- number is visible in the left frame and on the front page.</p>
-
- <p>For other types of documents, this tag is ignored.</p>
- </section>
-
- <section>
- <marker id="approvedTAG"></marker>
- <title>&lt;approved&gt;</title>
-
- <p>This optional tag is intended for administrative use and is
- ignored by DocBuilder.</p>
- </section>
-
- <section>
- <marker id="checkedTAG"></marker>
- <title>&lt;checked&gt;</title>
-
- <p>This optional tag is intended for administrative use and is
- ignored by DocBuilder.</p>
- </section>
-
- <section>
- <marker id="dateTAG"></marker>
- <title>&lt;date&gt;</title>
-
- <p>This tag is intended for administrative use and is ignored by
- DocBuilder.</p>
- </section>
-
- <section>
- <marker id="revTAG"></marker>
- <title>&lt;rev&gt;</title>
-
- <p>Document version.</p>
-
- <p>For <c>part</c> and <c>application</c> documents, the document
- version is visible in the left frame and on the front page.</p>
-
- <p>For other types of documents, this tag is ignored.</p>
- </section>
-
- <section>
- <marker id="fileTAG"></marker>
- <title>&lt;file&gt;</title>
-
- <p>This optional tag is intended for administrative use and is
- ignored by DocBuilder.</p>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/inline_tags.xml b/lib/docbuilder/doc/src/inline_tags.xml
deleted file mode 100644
index 5bcca54c05..0000000000
--- a/lib/docbuilder/doc/src/inline_tags.xml
+++ /dev/null
@@ -1,257 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</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>Inline Tags</title>
- <prepared/>
- <docno/>
- <date/>
- <rev/>
- <file>inline_tags.xml</file>
- </header>
-
- <p>Inline tags are typically used within block tags, for example to
- highlight a word within a paragraph.</p>
-
- <section>
- <marker id="brTAG"></marker>
- <title>&lt;br&gt; - Line Break</title>
-
- <p>Forces a newline. The <c><![CDATA[<br>]]></c> tag is both a
- block- and an inline tag and is described in
- the <seealso marker="block_tags#brTAG">Block Tags</seealso>
- section.</p>
- </section>
-
- <section>
- <marker id="cTAG"></marker>
- <title>&lt;c&gt; - Code</title>
-
- <p>Highlights things like variables and file names in a text flow.
- Can contain plain text only. Newlines and tabs are ignored as
- opposed to the <seealso marker="block_tags#codeTAG">code</seealso>
- tag. All <seealso marker="character_entities">character
- entities</seealso> are expanded. Example:</p>
- <pre>
-&lt;p>Returns &lt;c>true&lt;/c> if &lt;c>Term&lt;/c> is an integer.&lt;/p>
- </pre>
- <p>results in:</p>
- <p>Returns <c>true</c> if <c>Term</c> is an integer.</p>
- </section>
-
- <section>
- <marker id="emTAG"></marker>
- <title>&lt;em&gt; - Emphasis</title>
-
- <p>Highlights words which are important within a text flow. Example:
- </p>
- <pre>
-&lt;p>The application &lt;em>must&lt;/em> be up and running.&lt;/p>
- </pre>
- <p>results in:</p>
- <p>The application <em>must</em> be up and running.</p>
-
- <p>Contains plain text or a
- <seealso marker="#cTAG">&lt;c&gt;</seealso> tag.</p>
- </section>
-
- <section>
- <marker id="markerTAG"/>
- <title>&lt;marker&gt; - Marker</title>
-
- <p>Used as an anchor for hypertext references. The <c>id</c>
- attribute defines the name of the marker. Example:</p>
- <marker id="marker_example"/>
- <pre>
-&lt;marker id="marker_example"/&gt;
- </pre>
-
- <p>The <seealso marker="#seealsoTAG">&lt;seealso&gt;</seealso> tag
- is used to refer to the marker.</p>
-
- <p>The <c><![CDATA[<marker>]]></c> tag is both a block- and an
- inline tag.</p>
- </section>
-
- <section>
- <marker id="pathTAG"></marker>
- <title>&lt;path&gt; - Path</title>
-
- <p>Highlights file paths. The attributes <c>unix</c> and
- <c>windows</c> makes it possible to specify different paths for
- different file path notations. Default for both are "".
- Example:</p>
- <pre>
-&lt;p>Look at the &lt;path unix=".profile" windows="win.ini"&gt;start-up file&lt;/path&gt;
- if you intend to alter the initial behavior.&lt;/p>
- </pre>
- <p>If no <c>ptype</c> option is specified when calling
- <seealso marker="docb_transform#file/1">docb_transform:file/1,2</seealso>,
- this simply results in:</p>
- <p>"Look at the <path>start-up file</path>
- if you intend to alter the initial behavior."</p>
-
- <p>If both the options <c>{ptype,unix}</c> and
- <c>{ptype,windows}</c> are specified, the example instead results
- in:</p>
- <p>"Look at the <path unix=".profile" windows="win.ini">start-up file</path>
- if you intend to alter the initial behavior."</p>
- </section>
-
- <section>
- <marker id="seealsoTAG"></marker>
- <title>&lt;seealso&gt; - Local Cross Reference</title>
-
- <p>A cross reference (hypertext link) to a marker in the same file,
- a marker in another file, or (the top of) another file, given by
- the <c>marker</c> attribute. Must contain plain text. Examples:
- </p>
-
- <pre><![CDATA[
- <seealso marker="#marker_example">marker example</seealso>
- ]]></pre>
- <p>results in:
- <seealso marker="#marker_example">marker example</seealso>
- (a hypertext link to the marker example above).</p>
-
- <pre><![CDATA[
- <seealso marker="block_tags#markerTAG">marker tag</seealso>
- ]]></pre>
- <p>results in:
- <seealso marker="block_tags#markerTAG">marker tag</seealso>
- (a hypertext link to the marker section in the Block Tags
- chapter).</p>
-
- <pre><![CDATA[
- <seealso marker="overview">Overview</seealso>
- ]]></pre>
- <p>results in:
- <seealso marker="overview">Overview</seealso>
- (a hypertext link to the Overview chapter).</p>
-
- <p>Note the use of "#" before the name of the marker. Note also
- that the filename extension <c>.html</c> is omitted. This is
- because the default behavior of DocBuilder is to translate
- <c><![CDATA[<seealso marker="File#Marker">text</seealso>]]></c>
- to <c><![CDATA[<A HREF="File.html#Marker">text</A>]]></c>.</p>
-
- <p>The default behaviour can be modified by using the callback
- module option to <c>docb_transform:file/1,2</c> and defining a
- callback function
- <seealso marker="docb_transform#Module:seealso-1">Module:seealso/1</seealso>.
- This possibility is for example used in OTP to resolve cross
- references between applications.</p>
- </section>
-
- <section>
- <marker id="urlTAG"></marker>
- <title>&lt;url&gt; - Non-Local Cross Reference</title>
-
- <p>A reference to a file outside the documentation, a web address or
- similar, given by the <c>href</c> attribute. Must contain plain
- text. Example:</p>
- <pre><![CDATA[
-<url href="http://www.erlang.org">erlang.org</url>
- ]]></pre>
- <p>results in: <url href="http://www.erlang.org">erlang.org</url>
- </p>
- </section>
-
- <section>
- <marker id="termTAG"></marker>
- <marker id="termdefTAG"></marker>
- <title>&lt;term&gt;, &lt;termdef&gt; - Glossary</title>
-
- <p>Used to highlight a term with a local (for this document only) or
- global definition. The identity of the term is given by
- the <c>id</c> attribute.</p>
-
- <p>For a locally defined term, the tag contains a
- <c>&lt;termdef&gt;</c>, which in turn contains an explanation of
- the term as plain text. Example:</p>
- <pre><![CDATA[
-<term id="HTML"><termdef>Hyper-Text Markup Language</termdef></term>
- ]]></pre>
-
- <p>For a globally defined term, the tag is empty. Example:</p>
- <pre><![CDATA[
-<term id="HTML"/>
- ]]></pre>
-
- <p>Global definitions are given to DocBuilder in a file, using the
- <seealso marker="docb_transform#file/1">docb_transform:file/1,2</seealso>
- option <c>term_defs</c>. The file should contain a list of tuples,
- one for each term definition, on the format
- <c>{Id,Name,Definition,Owner}</c>. The <c>Owner</c> part is just
- for administration, if there are several people contributing to a
- term definition file. Example:</p>
- <pre>
-[...,
- {"HTML", "HTML", "Hyper-Text Markup Language", "Gunilla"},
- ...].
- </pre>
-
- <p>DocBuilder will collect both local and global definitions in a
- glossary, which can be reached from a link in the left frame of
- the HTML documentation.</p>
-
- <p>In the generated HTML, it is the term name which will be visible.
- For locally defined terms, the id and the name are the same.
- The name has a hypertext link to the definition in the glossary.
- Example:</p>
- <pre><![CDATA[
-<term id="HTML"><termdef>Hyper-Text Markup Language</termdef></term>
- ]]></pre>
- <p>results in: <term id="HTML"><termdef>Hyper-Text Markup Language</termdef></term>
- </p>
-
- <p>If a term is defined both locally and globally, the global
- definition takes precedence.</p>
- </section>
-
- <section>
- <marker id="citeTAG"></marker>
- <marker id="citedefTAG"></marker>
- <title>&lt;cite&gt;, &lt;citedef&gt; - Bibliography</title>
-
- <p>Works the same way as <c>&lt;term&gt;</c> and
- <c>&lt;termdef&gt;</c>, but for a bibliography list rather than
- a glossary.</p>
-
- <p>A global bibliography list is given to DocBuilder in a file,
- using the <seealso marker="docb_transform#file/1">docb_transform:file/1,2</seealso>
- option <c>cite_defs</c>. The file should contain a list of tuples,
- one for each cite, on the format
- <c>{Id,Title,Info,Owner}</c>. The <c>Owner</c> part is just
- for administration, if there are several people contributing to a
- 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"},
- ...].
- </pre>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/make.dep b/lib/docbuilder/doc/src/make.dep
deleted file mode 100644
index d9b075e114..0000000000
--- a/lib/docbuilder/doc/src/make.dep
+++ /dev/null
@@ -1,33 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: block_tags.tex book.tex character_entities.tex \
- docb_gen.tex docb_transform.tex docb_xml_check.tex \
- docbuilder_app.tex fasc_dtds.tex header_tags.tex \
- inline_tags.tex overview.tex part.tex ref_man.tex \
- refman_dtds.tex user_guide_dtds.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-block_tags.tex: gazonk
-
-book.tex: ref_man.xml
-
-inline_tags.tex: ../../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: man.ps
-
diff --git a/lib/docbuilder/doc/src/man.ps b/lib/docbuilder/doc/src/man.ps
deleted file mode 100644
index b4d7ef7636..0000000000
--- a/lib/docbuilder/doc/src/man.ps
+++ /dev/null
@@ -1,750 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0
-%%Title: /clearcase/otp/internal_tools/sgml/test/man.ps
-%%Creator: XV Version 3.10a Rev: 12/29/94 - by John Bradley
-%%BoundingBox: 243 308 369 484
-%%Pages: 1
-%%DocumentFonts:
-%%EndComments
-%%EndProlog
-
-%%Page: 1 1
-
-% remember original state
-/origstate save def
-
-% build a temporary dictionary
-20 dict begin
-
-% define string to hold a scanline's worth of data
-/pix 126 string def
-
-% define space for color conversions
-/grays 126 string def % space for gray scale line
-/npixls 0 def
-/rgbindx 0 def
-
-% lower left corner
-243 308 translate
-
-% size of image (on paper, in 1/72inch coords)
-126.00000 175.96800 scale
-
-126 176 8 % dimensions of data
-[126 0 0 -176 0 176] % mapping matrix
-{currentfile pix readhexstring pop}
-image
-
-110000110011111111111100111111110011110011111111111100111111112222222222
-33445544446655665555665566666655666666888888778899888899aabbaabbbbbbaabb
-bbaaaaaaaabbbbbbaabbccddbbaaaaccccccddddccddddccbbccccccbbccccaabbaaaaaa
-9999aaaa8899887777554455666655555544
-000000110011110000001100112222111111001111111100001111111111112222112233
-55334444446666775544555555775577777766888888889988889999aaccbbaabb99aaaa
-bbbbaaaaaaaabbbbccccccccccccbbccccccccddccddddccbbaaccddccbbaaccbbbbaaaa
-999999889977667755554455666655444444
-110011000011000000111111111100111100112211111111110011111111112222222233
-3344444455446677665555667777667788888888667788aa88999999aabbaabbaa889999
-aabbbbbbaaaaaabbddccccccbbccccccbbaaccccccccccccbbccccccccbbbbbbbbaaaa99
-9999aa888877666655555555555544333344
-110000110011110000001111111111000011001122110011111111002211222211224433
-3333444444556677666655667777667777888877666688998899aa99aabbaaaaaaaabbaa
-99aabbaabbbbbbbbbbccbbddaabbccbbaa99ccddccccccbbccccccddccbbbbaaccaa9988
-889988887766665566665544443344554444
-000000000000110011000000110000110000001111000000111100221111111133222222
-33444433444455667777555555776666778888667777778888aa998888bbaa99aaaaaabb
-bbbbbbaabbccbbbbbbccbbbbbbccccaabbbbbbccccccbbbbbbbbccbbbbbbbbbbbbaa7788
-aa9988889966666655666655553355556644
-110011111111111100111100110011000000001100002211111122221122111122222222
-33443333334455776666776666667766778855668866777788448899889988889999bbaa
-aaaabbaaaabbbbaabbbbbbbbbbbbaa99bbaabbccddccccccbbccbbbbaabbbbaaaa777788
-aa9999aa9988776677777755555544556655
-110000001111111122111111000000001111110011111111110022111111111133222233
-223322445555445544667777667777667777887788887799883377999999998899aaaaaa
-99aabbbbccbbbbbbbbbbaaaaaabb99aaaabbbbbbccccccbbccccbbbbaabbaaccaa886688
-9999aaaa9988888866667744555544445544
-110000111122111111221100111111110011111111111100111111222222221122333333
-22222244556655445555667788778888aaaa88aa889999aabbaaaa998888998899aa99aa
-bbaabbccbbbbaaaabbbbbbbbbbbbaabbaaaaccccccbbccddccbbaabbaabbaabb99888888
-99aa99aa9988888866446655554444444444
-110000001111111111110011110000111100221111001111000011222222222222333344
-223322444466664455667766777788777755556666333344557788aa9999888888aa88aa
-aabbbbaabbaaccbbaaaaaaccbbccaa99bbccccccccbbccccccbbbbbbbbaabbaaaa99aa88
-999988999988887766664455445555555544
-110011111100001111111111110000000011111111110011111122111111112233222222
-443333555544444455777788775522000000000000000000000000447799aaaa99888899
-aaaabbaaaaccbbaaaabbbbbbbbaa7788bbddccccbbbbbbbbccbbbbaabbaaaaaaaaaa9999
-aa999988aa99887766666655444455445544
-000000110011110000110000110011001100001111110000111122112211112211222222
-5544444455443333446677772200000000000000000000000000000000337799999999aa
-9999aabbbbbbaaaa88aaaabbbb889988ccccccbbccbbbbaaaa9999bb8855889999999988
-998888998888886655667755554455554433
-110011001111001100001100111111000000001100111100111111222211113333222211
-44555544444433445555550000000000000000000000000011000000000000003377aa99
-888899aa99aa9999aaaabbaabb99aabbaabbbbccaabbaaaabb88aaaa995588aaaaaa8888
-8888aa998888887755777766554444332222
-111111110011111111001111001111110000000011000011001111111122332222223322
-334466554444444455441100000000000000000000000000000000001155220000113366
-998888aa99998899bbbbaabbbbaaaaaabbbbbbbbbbaabbaaaa99aaaa8888aa9999889988
-7799aa888888665566666655554433334422
-221111110011000011111111110000000000110011110000111111001111333311223333
-443344443344554488440011553300000000000000000000000000227788883300000011
-4444559999887799aaaaaaccbbaaaa9988ccccbbaabbbbaaaa99aa9988aa999988888888
-776688888877667766554455444444444433
-221111110011111100110011000011000000000000110000110011001111112222221122
-2222333333111111448899ccffddbb77442222221111000000000044bbddccaa33000000
-00000000558888998899bbaabbaabbaa99bbaabbaaaabbaa99aa99999988778888777777
-663355778877776666665544444433333322
-221100222211001111112200111111000011000000000011001100111111112211112211
-332244220011000055ddffeeeeeeeeeeddddddeeddcc88330000000044ddddcc55000000
-000000000077aaaa999999aaaabbbbbbaa99aabbbbaaaabbaaaaaa999999888888557755
-664466666677666655667755443333223322
-221111222211221111111100000011110000110000001100111111110011111122112222
-3322000000000044ddffffeeffeeeeeeeeeeeeeeffeeffdd885511000033aaddaa330011
-2211000000339988889999aaaaaabbaabbbbbbbbbbaaaaaabb99aa8899aa999988665577
-665577777766555544443366443344333322
-221111111122221111001111111100000000000000001111111111111111111111223344
-22000000000077ddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffeebb440000005588661100
-11000000001188888888aa9999aabbbbbbaaaabbaabbbbbbaa8899888899888888776666
-556666776666443366555555445533333333
-112211111122221111221100111100110000000000001111001100000000111122112211
-000000000088eeeeeeeeeeeeffeeeeffffeeeeeeffeeeeeeeeeeffee8811000000118866
-0000000000118899888899aaaabbbbbbbbbbbb99aabbaaaaaa9988888877888877555566
-555555666655446655556655444444443344
-221111111100111111110011111111110011001100110000111100110011111111000000
-0000000088ffeeddeeeeeeeeeeeeeeeeeeeeffeeeeffffeeeeeeeeffffbb775566aaeeee
-aa332233000088aa88888899bbaaaa99aabbaaaabbaabbbbaaaa88888877888877555555
-445577666655554455555566665544665533
-110000111111110011111111111111110000000000001100111111000011111111110000
-00000088ddddddddddffeeffeeeeeeeeeeeeffeeeeeeeeffeeeeeeeeeeffffffffffeedd
-eecc441111002288997788aa99aaaa99aa99aabbbbaabbaaaa9977778888777777776655
-555577776666666666666677775555555555
-001111110011001100111111112211111100110000000011110011111111001111000000
-000022aaddccddddeeeeeeeeeeeeeeeeeeeeeeeeeeffeeffeeeeeeffeeffeeeeeeeeeeee
-eeffdd3311110044998899999999aaaaaaaaaabbaabbbbaaaa8888778877888866776677
-665566667755556644665555554444666666
-110011110011111111001100002211111100110011111100111100111111111100000000
-000022bbcccccccceeeeeeeeeeeeeeeeeeeeffeeffeeffffffeeeeffeeffeeffeeeeeeee
-eeddeebb6644000088998899bbbbbbaabbbbbbaabbbbbbcc999988888877888877667777
-557777777766665544555555555555665566
-110011221111111111111111111111221100001100110011111111221100221100000000
-00001199aabbccccddeeeeeeeeeeeeeeeeeeeeeeffffeeffeeffeeeeffeeffeeeeeeeeee
-eeddeeeebb88110066aa99aabbccbbaabbbbbbaabbbbbbbbbb99aaaa9988777766667777
-666677777777665544665566555566664455
-221111222222111111111111221111111111111111001111111100221122221100000000
-000022aabbbbaaccddeeeeeeeeddeeeeeeffeeeeeeeeffeeffeeffeeffffeeeeeeeeeeee
-eeeeeeeeeecc220066aaaaaaaabbbbbbccaabbaaaabbccbbaaaaaa998888886677887777
-777777888866776655667755665566666655
-222211222222111122111122111111000000001111111111111122111122220000000000
-00002299bbaaaabbddeeeeeeddeeffeeeeeeeeeeffeeeeeeeeffeeeeffffffeeeeeeeeee
-eeeeeeeeeecc330044aaaabbaabbbbbbaaaabb99aabbbbbbbbaaaa889988888877888888
-887777778888776644777777666677667766
-222222332233222211221111221111110000111111222222222211222222221100000000
-00001188cc99aabbddddddeeeeeeeeeeeeeeffeeeeeeeeeeffeeeeffeeffeeeeeeeeeeee
-eeeeeeeeeeee440044bbaabbbbaabbbb9999aaaabbaabbbbbb9999998888887788888899
-887777778888887755776677667755667755
-221122442222222222332211222222111111001111222222221133112222220000000000
-00001177bbaaaaaaeeddeeddeeeeddeeeeeeeeeeeeeeeeeeffeeffffeeeeeeffeeeeeedd
-eeeeffeeddffaa0022aabbbbbbbbbbaaaa99bbbbaabbaabbaa9988888888998888887777
-888866777788888888888877666655445566
-331133442233333333332222332211111111111111112222222233221122220000000000
-0000115599aabbccddddeeddeeeeeeeeeeeeeeeeffeeeeffeeffeeffffffeeffeeffddee
-eeeeeeeeeeffdd110088bbbbbbccbbaa99bbaabbaaaabbbbbbbb99888888888888666677
-777777778888666677888877775544444455
-332222332222334422222233222233110011222222112233223322222211221100000000
-000000228899aabbddddeeddeeeeeeeeeeeeeeeeffeeeeeeffeeffeeeeffeeffeeeeeedd
-eeffeeeeeeeecc220066bbaabbbbbbaaaa999999aaaaaaaa9999aaaa9988888877776688
-888877778888776677887777666666665544
-333311332233333333222222222233331111113322222222223322332222220000000000
-000000225577aabbccddddddeeeeeeeeeeeeeeeeeeeeeeffffffffeeffffeeeeeeeeeeee
-eeeeeeeeeeeedd110044bbaaaabbaabb99999999aabbaa999999aa999999998888777788
-888855888888886677777788777777555555
-222211222222224444111122222211222233221133443344332233333322551100000000
-00000022557788aaccddeeddddeeddeeeeeeeeeeffffeeffeeeeffeeeeeeeeffeeffeedd
-eeeeeeeeeeeedd33003399aaaabbbbaaaa88999999aaaaaa99aaaabbaaaaaa9999778888
-887766888888885577776666777766556644
-222211222222222233334422222222112233222233554444332222222222440000000000
-0000001144779988bbccddddddffddeeeeeeffeeeeeeeeffffffeeeeeeffeeffffeeeedd
-eeeeeeeeeeeedd2200228899aaaaaa88888899999999bbaa99aabbbbbbaa999988888888
-887777778877665566886666666677775566
-443322111133331111222233332222332222332233223333333333332233331100000000
-000000115555668899ddddddddeeeeeeeeffeeffffffeeffeeeeffeeeeeeeeeeeeeeeedd
-eeeeeeeeeeeedd2200339999aabbaa889999aaaa99aabbaaaa99bbbbaaaa998899998888
-888888997777775577777777777777666666
-332211223322222222221122223333221122112233333333332244333333330000000000
-0000000033444466aaccccddddeeeeeeeeeeeeffeeeeeeffeeeeeeeeeeffeeeeffffeedd
-eeeeeeeeeeeecc2200228899aaaa9988aaaaaaaa99aa99bbaabbaaaa99999988aa999988
-888888887777776677666666776666556644
-332222222233222233332222333333331133332233224433333344554444331100000000
-000000110044777788aaeeeeddeeeeddddddeeeeeeeeeeffeeffeeeeeeeeeeeeeeeedddd
-ddeeddeeeeeedd220011aa9999aa999999bbbbbb99bbbbbbbbbbbbaaaaaa999999888899
-998888888888666677556677666655555555
-332222222222333333443333333322443333443344334433444455553333330000000000
-000000002233557788ccccccccaa775555446688ccddcceeeeeeeeeeddeeeeeeeeeedddd
-eeddeeeeeeeedd44003399aa88aaaa99aaaaaaaa99bbbbbbbbbbbbbbbbbbaa999999aa88
-888866887788775577667755556655555544
-331122332222444433333333223333333344444444554433445555664444441100000000
-00000000332244889999777788330000000000116688aaddccddddccddddaa88aa99aadd
-ddddeeeeeeddee660022aa99999999bb99bbbbaaaabbbbbbbbccbbbbbbbbaa99aaaa8888
-888877776677667755777755445555556655
-331122333333335544554433333322443344555555554433334433556655441100000000
-000000000000225544221100110000000000001111557799ccbb88778877110011003388
-bbddeeeeeeddee55002299aa999999aaaabbaabbaabbbbbbaaaaaabbaaaabbaa99998888
-887777667788666666666666555555554444
-333333333322444444555555444444444455556666555544334455336666551100000000
-000000001111001100000000000000000000000011224455889966111111000000000011
-66aaddeeeeeeee550033aa99aa999999bb99bbccaabbbbaaaaaaaabbaaaabbaabb888888
-667777777777775577554455553344444444
-223344332233555544556666665533335544556655555533446655555555661100000000
-00001100111100000000000011000000000000000011449999bb77000000000000004433
-225588cceeeeff660044aaaa888899aa9999aaaa99aabbaaaaaa99bbbb9999aaaa998888
-886677777777667766555555443355554455
-443344332233556655666655666633555544555555555555555566555555662200000000
-0000001111110000000000001100000000000000000066ddeeee990000000000000066bb
-bb88bbcceeeeee880066aaaa9999bb9999aa99998899aa999999aaaabbaaaaaa99889988
-778888776677666655444455665555554433
-443333442233445577665566666655444444666655667766666666666644443300000000
-0000001133220000000000000000000000000000000055eeeeeebb110000000000000022
-bbffddddeeeeff88007799999999aabbaa9999999988aa99999999bbaaaa888877888888
-887777777766666655664455554455443344
-444422335566557766776666555544444455556666555555556666668899aa5500000000
-0000002233220000000000000044110011110000000055ffeeffcc110000000000000000
-0077ddddddddeebb118899999999aaaaaa8888aa88aaaaaa9999aabbaaaa997755889988
-887766777766775555665555444444443344
-555544333344556666556666445566556666555555665566665555335566999922000000
-0000002244332200000000001177663366330000000088eeeeffdd110000001100112200
-000066cceeeeeebb66ccbbaa9999aaaa998899aaaabbbbaa9988aaaabb99998888888877
-777755776666666655555555554444444444
-445555554444555555557766445544666677665566666666776611000000002233000000
-00000022445544112233442255442211110000000033bbeeeeeeee880000002255999966
-330033ddeeeeeeddddeeeeffccaa99998899aaaabbbbaaaa999999999999999988888877
-777766665566666655665544444444553333
-444444556666445555776666555566667777775566666655665500000000000000000000
-00000000334433337799999988775533112244225599ccddeeeeffee885533111166bbcc
-bb6666ddffeeeeeeeeeeaa66aa99aa889999bbbbbbbb99aa999999999999998888888877
-667766555555555555444433444444333322
-334444445577665555556666665566665577666644444466664400000000000000000000
-000000002255667788bbbbbbaabb998866556688aabbddeeeeeeeeeedd8888bbaaccddee
-eeeeddeeeeeeddeebb22000066aa88aabbaaccbbaa99aa99889988999999889999888877
-777766666666665544334455443333333333
-333355444466557766776655555555556666664455446666665500000000000000000000
-0000000011335577aaccddddddccbb998899ccddddccddeeffeeeeeeeedd8899ddeeeeee
-eeddffeeeeeedddd3322220066aaaaaabb99bbbb99aaaa88888899888888888877887777
-556688553355665533444433334433333344
-444444225555445566888866666666777777776666556666664400000000000000000000
-0000000011224477aaddddeeddddddddddddddddddddeeeeeeffeeeeeeeecc88aaddeeee
-eeeeeeeeeeeeeecc66dd8800779988bbbbaabbbbaaaa9988888888999977776677776666
-557766553355556644443333333344221133
-77bbccbb9988774455667777667788888877886666667777666611000000000000000000
-0000001111335577bbccddddeeeeeeddeeeeddddccddeeeeffeeeeeeeeeeffddddddeeee
-eeeeffeeeeeeddccddeedd22999988aa99aaaa8899aa9988888888888888776677777766
-776666665555555544444444332222112211
-bbeeffffffeeeedd88444455668899998866776666666677775533000000000000000000
-0011114433446688bbccccccddddeeeeddddbbddeeddeeeeffffeeffeeffeeffffffeeee
-ffeeeeffeeeeeebb77eeee88cc889999aaaa99aa99998888778888888888668888997777
-777777667766665533334433332222222222
-77ddeeffeeffeeeeee995555557788888888776677775577776655221100000000001100
-1122225555665588aabbbbccddddddeeccaabbeeddccddeeeeeeffeeffeeeeeeffeeeeee
-eeffeeffeeeeffcc33bbeeeebbaaaaaa99aaaa9999888877889999999988777788887777
-888866556677665533334433112211222222
-4499bbbbeeeeeeeeeeee6633667799889988778877667788777777332200110000001100
-444477888866667799aabbccccddddddbb8888aa7755779999bbddeeffffeeeeeeffeeee
-eeddeeeeffeeeedd44bbeeeebbaaaa99aaaaaa99889999888888aa99aa88776677888877
-887777666666554433554422222222222211
-003322446677cceeeeeeaa66777788888888888877667788887788662211113300002222
-66887777665566667799aabbccccccaa88443322000011223344446677ccffeeeeeeeeff
-eebbeeeeeecceeeeaacceeeebbbbaaaaaabbaabbaa999988778899998888888888778888
-777766776677665555442222222233222222
-00220000000066ccffeeffaa776677887777887777777788888877773311005566115533
-7788996666445566667799bbccbbaaaa9933000000000000000000000066ffeeeeffeeee
-eeddeeffeeffeeffeeddeeddbbaaaa99aaaaaabbccaaaa88889988999988888877888877
-888877667766666644332244442222223322
-1111000000000044aaeeffdd777755777788778877777788888888776611221122888844
-88aa77776655445555778899aa7788aaaa44000000000000000000000077ffeeeeddeeee
-eeeeeeeeeeeeeeeeeeeeffccaaaaaa9999aaaaaabbaaaa9999888899bb99888866778888
-777777665555554444333322222222221122
-22000000001111001177dddd999999886666888877887788778888888844115544aa8888
-9988888866555555446666666666bbcc99330000000000000000000055eeffeeeeccddee
-eeeeeeeeffeeffeeeeeeeeccaaaabbbbaaaabbbbaaaaaa88889999aa8899886688777766
-778888775566554433332233333322331111
-4400000000443300000033bbffeeffeebb666677888888888888777766663333bbbb88bb
-aa998888885555554444221144aaccbb330000000000000000000033ccffeeeeffddcccc
-cceeeeeeeeffeeeeeeffeebbbbbbbbbbbbaaaaaaaabbaa8899aa99889999888877888877
-667777668888998844332244442244332222
-770000000077ccbb996677eeeeeeeeeeeebb5566777788889988777777777755ccbbaacc
-bbaa9988775577664400000055bb6633110000000000000000000077bbddeeeeeeffddaa
-bbddddddddddffeeffeeeebbbbccccbbbbbbaaaaaaaa8888888888998899888888888888
-776677aaddeeeedd77223344443344333311
-dd77000011aa99aaddeecccceeeeeeeeeeeebbaa6677888899887788778888cceeccbbbb
-ccaa998888888855110000337733000000000000000000000000005599ddccddeeeeeedd
-aa99ccddaacceeffeeeeeeeebbaaccbbbbaa99aa99998888887799998899998877888888
-8888cceeeeeeeeddbb553344333333333322
-eeee88000077220033998866aaeeeeeeeeeeeeeeaa777788aa8899997788aaddccbbcccc
-ccbbaaaabb9977440000335522000000000000000000000000000000227788aaeeeeeeee
-bb8899ccddaaaaeeeeeeeeffcc99aaaa99999999aaaa8888888888777777888877777788
-88cceeeeeeeeddeeeeaa3344444433443333
-eeeedd55004488000011110077ffeeeeeeeeeeeeffbb8877889988999999ddddddddddcc
-ddccccbb8866332200113300000000000000000000000000000000000000334488cceeee
-ddccaa88bbbb6655bbffeeeeeeccaa9999aaaa99998899997777889999aa998888888866
-3388ddddddddcc88ccdd9944334433443322
-eeeeee88110066110000000088eeeeeeeeeeffeeeeeecc9977889999aacceeddeeeedddd
-ddddaa88663300000000000000000000000000000000000000000011000000000022aadd
-eeddccbb99aa88111188eeffeeffddaa99aaaaaa88998888888888aaeeeeeebbbbddddaa
-1155ccaa55443311aaeedd88222222332211
-ddccdd88440000000000000077ddeeeeeeeeeeffeeeeffeebb99aaaaccddeeeeeeeeeeee
-ddbb777777442200000000000000000000000000001188ccbb9999bb8833000000002222
-77ddddddccbb8844000044ddffffffeeaa88aa9999998888888888cceeddeeddeeeeeedd
-2288bb991100000066bbddcc551122222222
-cc666622221100000000000055ddeeeeeeeeeeeeeeeeeeeeee9999ccddeeeeffeeeeeeee
-eeddccaa884422331100000000000000000000001177eeeeeeeedddddd99550000001133
-1155ddeeddddcc8855000033aaeeeeffdd9999aa9999aa88995555cceeeeddeeeeeeeebb
-00559999440000000055bbddbb3322223322
-ffdd4400001100000000000044ddeeeeeeeeeeeeeeeeeeeeeeccbbeeffeeeeeeeeffeeee
-eeddeeccbb8866772200000000000000000000001144668899aabbddddccbb66110044bb
-bbbbcccceeeeddddcc8877332277cceeeeeebb88999999aadd7799eeeeeeeeeeeeddddaa
-4444775577220000000044bbee7711222211
-eeeecc33000000000000000033cceeeeeeeeeeeeeeeeeeffeeffeeffeeeeffeeffeeffff
-eeffeeddeeccbb884411000000000000000011000000000000000088ccddddaa6644bbee
-ddffeeddeeeeeeeeeeffffeeddbbddeeffeeeeddaa88aaccddbbeeddeeddddeeeeee8844
-7711221100000000001177ccddbb44112211
-eeeeffaa000000000000000066eeeeeeddddeeeeffeeeeeeffeeeeeeffeeeeffeeeeffff
-eeeeeeeeeeeeeecc66110000000000000022666655334433446688bbeeddeeddbbccddee
-eeeeeeeeeeddeeeeffffeeeeffffffeeeeeeeeffdd99cceeddbbddeeddddeeddeecc2200
-22000000000000003399ccccdddd88111122
-eeeeeeee550000000000000088eeddddddccddddeeeeddeeeeeeeeeeffeeffeeeeffffee
-ffffeeeeffeeeeee99220000000011336688bbddddddddeeeeffeeeeeeeeeeeeeeeeeeee
-ffeeffeeeeeeeeffeeeeeeffeeffeeeeffeeeeeeffddddeedd99ccddddddeeeedd660000
-00000000000000001166ccddddeeaa222222
-eeeeeeee880000000000000099eecc888888ddccccaa88ccddeeeeeeeeeeffeeffeeffee
-ffeeeeffeeeeeeddbb3300001122336688aaddeeeeddeeeeeeeeeeffffeeeeffeeeeeeee
-eeffeeffeeeeeeeeeeffeeeeffeeeeeeeeeeeeeeeeccccddcc5588aacceeddeecc220000
-0000000000000000004499bbccddcc331111
-eeeeeeee990000000000000088ddccdd6622bbddbb4455ddbbaaeeeeffeeffeeeeeeffff
-eeffeeeeeeeeddcc996633335522335588aaccddeeeeeeeeeeeeeeeeeeffeeffffeeeeff
-ffeeeeffffeeeeeeeeffeeeeeeffeeeeeeeeeeeeff99779988003377ccddeeee99000000
-000000000000000000000055bbddcc441122
-ffeeeeeedd3300000000000077cceeee880044aabb55ccffddccddffeeeeffeeeeeeeeff
-eeffeeeeeeddccbb776644442211223377aaccddeeeeeeeeeeeeffffffeeffeeeeeeffee
-ffeeeeeeeeeeeeffffeeeeffeeeeffffeeffeeffff8811333300001199ddeeee66000000
-0000000000000000001155ccddccdd551111
-eeeeeeeedd991100000000000077ccdd555577111133ddffeeddddffffffeeffffffeeee
-ffffeeeeffddccbb7733110000000011336688bbcccceeeeeeeeeeffeeeeffffffeeeeee
-ffeeffeeffeeffeeeeffeeffeeffffeeffeeffeeff99000000000066ddddeecc22000000
-00000000000000004499ccdddddddd771122
-eeeeeeeeeedd6600000000000000226677ddee66000088bbcc8866777799ccbbaabbbbcc
-ddeeffffffeeeeeebb6644110000000000113355668899bbbbddddddeeeeeeddeeeeeeff
-eeeeeeeeeeeeeeffffeeffffeeeeddddccddddddee990000000000aaffeeeeaa00000000
-00000000000000005588bbccccdddd880011
-eeeeffeeeeeebb99220000000000000055bbaa3300000011220000003399aa9988886666
-66888888bbddeeeeeeddcc9933000000000000000011224466778888aabbddddeeeeeeee
-ffffeeffffeeeeeeccbbbbaaaa777777774411222211000000000055aaaaaa6622000000
-00000000000000004499bbccddddee991111
-eeeeeeffeeddddcc4422220000000000001133000000000000000000669999aaaa99aa99
-999911000011445588aacccc88110000000000000000222222223322336699bbddeeffee
-ffeeeeddccccccaaaaaaaabbbbaabbbbbb66000000220000000000001111110000000000
-000000000000001155aabbddccddddbb2211
-ffeeffeeeeeecccc99aa55000000000000000000000000000000001188888899aaaaaaaa
-99770000000000000000113333000000000000000000000011000000002277cceeeeddaa
-8888ccccccccccccbbbbccddbbbbbbbbcc88000000000000000000000000000000000000
-00000000000000116699ccddddddeecc2211
-eeeeeeeeeeeeddccddccbb661100000000000000000000000000227788778877889999aa
-660000000000000000000000000000000000000000111100000000000011445544331100
-0088ccccccccccccccbbbbccccbbbbbbaa99110000000000000000000000000000000000
-000000000000002266aaccddddddddcc3300
-eeeeeeeeeeeeddddbbccccccaa88887788aa440000000000004488778888887788779977
-110000000000000000000000000000000000001111111111001111000000000000000000
-55ccccbbccccbbccccbbbbbbbbbbbb999999772200000000000000000000000000000000
-000000000000002277aaddddccccdddd5511
-eeeeeeffffddddddddddeeddddeeddeeddcc773311000000337766777777667766776611
-000000000000000000000000000000000000000000000000000000000000000000000055
-ccbbbbccbbccccbbbbbbbbbbbbaaaaaaaa99997711000000000000000000000000000000
-000000000000001166aabbccccdddddd7711
-eeeeffeeeeeeeeeeeeddeeddeeddddddccbb996611001144777777776677776666771100
-0000110000000000000000000000000000000000000000000000000000000000000022dd
-8844ccbbbbaabbaabbbbaabbaaaaaa99aa99aa7766110000000000000000000011557777
-66330000000000003388aaccdddddddd9911
-ddeeddeeeeeeeeeeddeeddddeeddddccbbaa883300004466667777666655666688440000
-0000001111000000000000000000000000000000000000000000000000000000000099ff
-aa0077bb99aabbbbbbbb99aaaa99999999aa887766440000000000000000003388bbccbb
-cc773300110000002277bbbbccccddddaa22
-ddeeddeeeeeeddeeeeddddddddddddbb9988330000336655886688776655556688220000
-00000011222211000000000000000000000000000000000000000000000000000077eeff
-bb001199ccbbaaaaaaaaaa889988999999997777777733000000000000001166aaccccdd
-ccbb770066550000336699ccddccdddddd55
-99aabbddddeeddeeddddddcceeddcc887755110011556666667777776677775522000000
-000011224455441100000000000000000000000000000000000000000000000066eeeeee
-cc0000338899bb999999999988888888aa998888777755000000000000002277bbccccdd
-ddcc991177882200336699bbddccddddddaa
-22333366ccddddddddccddbbaa9977333311001144666655666688889966330000000000
-0000115555777777551100000000000000000000000000000000000000000044ddeeeeee
-ee220000002277aabbaaaaaa99888899aa99aa88777766220000000000000055aaccddcc
-ddcc991133885522113388ccccddddccccdd
-0000000088aa888888887733221100000000115566776677777799994411000000000000
-00001155777788998877773300000000000000110000000000000000000077cceeeeeeee
-ee2200000000003377aabbbbaaaa9988aaaaaa999977665500000000000000117799aabb
-ccbb883311443311112266bbccccdddddddd
-000000002233001122111100000000002244667766668866888899220000000000000000
-000000777799aaaa99aaaa99550000000000000000000000000000003388ddeeeeeeffee
-ee33000000001100003388ccbbaa99999999999988775566330000000000000011558899
-aa9977220011000011335588ccddddeeddee
-00000000000000000000000000001144667766667788aa99aa8811000000000000000000
-0000003377aabb99bbbbccaa77663300000000000000000000000055cceeeeeeeeeeeeff
-ee3300000000001100000055aaccaaaa9988778888887755553300000000000000115566
-776622000000000000113377bbddccdddddd
-00000000000000000000000000336677777788777788aa99661100000000000000000000
-000000117799aaccccccccbbbbaa99440000000000000000002288ddeeeeeeeeffeeeeee
-dd22000000000000110000002288aaaaaa99778888778877776644000000000000002222
-22110000000000000000003388aaccddddee
-000000000000000000000022667777887788777799884411000000000000000000000000
-0000000077aabbccddddccccddccddbb88442200000000000088ffeeeeeeeeffeeeeeeff
-dd1100000000000000110000000044aabbaa999999888888665566440000000000000000
-0000000000000000000000001155bbccdddd
-000000000000000022556688776688888877887733000000000000000000000000000000
-0000000055bbccddccddddddddeeeedddddd8800000011110000bbffeeeeeeeeffeeeeff
-dd1100000000000000001100000000224444667777778888887766555500000000000000
-00000000000000000000000000003388ccdd
-000000001133558899998888887788998899660000000000000000000000000000000000
-0000000022aaccddddddeeeeeeeeeeeeeedd330000117766447733ddeeeeffeeeeeeeeff
-aa0000000000000000000000000000000000000000113344667788887766110000000000
-000000000000000000000000000000117799
-0000446688aabb88aa999988998888999977000000000000000000000000000000000000
-0000000000aaccddeeeeeeeeeeeeeeeeffaa00000044dd7788ee77aaeeffeeeeffeeffff
-880000000000000000000000000000000000000000000000001122222233441100000000
-000000000000000000000000000000000033
-777788aa9988888888888899aa8899886600000000000000000000000000000000000000
-000000000088ddeeeeeeeeeeeeeeeeffeeaa550066bbdd99cceeccaaffeeeeeeeeffeeff
-550000000000000000000000000000000000000000000000000000000000113322000000
-000000000000000000000000000000000000
-884422331100000000000022331100000000000000000000000000000000000000000000
-000000000077ddeeeeeeffeeffffffffbbaa6611aaddeecceeeeeebbeeffeeffffeeffee
-440000000000000000000000000000000000000000000000000000000000000022110000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000077ddeeeeeeeeffeeeeffcc1111113399bbee88cceeee99aaffffeeffeeeeee
-330000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000044ddeeeeeeeeffeeeeff66002266001166ee66aaeeee6666ffeeeeeeeeffdd
-110000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000022ddeeeeeeeeeeffffcc11001155003388eeddddeebb2211ddffeeffeeffcc
-110000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000aaffeeeeffeeeeff8800000088221155cceebbbb55000088ffeeeeeeffcc
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000077eeeeeeeeeeeeee3300000088660055ccdd554411000044ffffffeeffbb
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000022ddffeeffffff990055330055990077dddd221111330011ccffeeffff88
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000bbffeeeeeeee442299770022aa0077dddd442266bb9944aaffeeffff88
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-0000000000000066ffeeeeff882288ddaa000077331188993399eeeeffcc99eeeeeeff77
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-0000000000000011ddffeeffaa99ddeecc11001111001199bbeeeeeeeeeebbddffeecc11
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000066ffeeeeffeeeeeeee2200000066bbddeeeeeeeeeeffddcceebb5500
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000055ddeeeeeeeeffee550055aaaacceeccddffffeeeeeeeeeeffcc00
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000aaffeeffeeeeee66337788bbeeeeeeeeffeeffeeeeeeeeffcc00
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000033cceeeeeeeeeeee440066ddeeeeeeeeeeeeeeeeffeeffeeffbb00
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000055eeeeffeeffeeee88aacceeddeeeeeeeeeeeeffeeeeffeeff8800
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000011ddeeeeeeeeeeeeddddddeeeeeeeeffeeeeffeeffffeeffff6600
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000088ffeeffeeeeeeeeeeddeeeeeeffeeeeeeeeffeeeeffeeff4400
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000033eeeeeeffeeeeeeeeeeffeeeeeeeeeeddeeeeeeeeffeeee3300
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000011bbffeeeeffeeddeeddddbbaaaaddddcceeffeeffeeffee2200
-000000000000000000000000000000000000000000000000000000002200220000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000088ffeeeeeeddddcc9999aaaaddeeeeeeffeeffeeeeffcc0000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000044eeffeeffccddddccddeeeeeeeeeeeeeeeeeeffffffaa0000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000099ffcc5544cceeddddeeddccddeeddddeeeeeeeeff990000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000044ff9911004499aabbccccccccddbbaabbccddffff660000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000011ccbb996655bbbbaaccbbbbddddaaaaccddcceeee550000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000006688000066ddcccceeeeeeeeffeeddccaabbeeff330000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000001144000066eeeeeeddccbbbbbb7722220022bbee110000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000022665599aaccbbaabb775588778899cc000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000002211001177bbddbbaabbaa99ddeedd8844000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000110077bbddddeeffeeeeffeeffaa00000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000088aaeeffeeddccbbcc776655996600000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000778877555533445588113355882200000000
-441100000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000007799ccccddbbddeeee3300000000
-331100000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000001155bbeeeeeeeeffeeeeeeff5500000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000004488ddeeeeeeeeeeeeeeeedd2200000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000033bbddeeeeeeffeeeeffaa0000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000088ccddeeeeeeeeeeff880000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000044aaeeeeffeeeeeeff550000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000001188ddccccddbb9988000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000022222233774422000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000116699aaccddbb44000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000002288888888992200000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000002255661100000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000011000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000113355882200000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000011778899771100000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000002244110000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000110000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000001100
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000001100
-000000000000000000000000000000000000000000000000000000000033110000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000022440000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000011220000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000001100000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000001100000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000001100000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000110000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000001100000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000
-001100110011001100110011001100110000000000000000000000000000000000000000
-000000000000000000000000000000000000000000221100000000000000000000001111
-110000001100001100110000110000000000000000000000000000000000000000001100
-001100000000000000000000110000001100
-
-showpage
-
-% stop using temporary dictionary
-end
-
-% restore original state
-origstate restore
-
-%%Trailer
diff --git a/lib/docbuilder/doc/src/notes.xml b/lib/docbuilder/doc/src/notes.xml
deleted file mode 100644
index 95f24ea9ca..0000000000
--- a/lib/docbuilder/doc/src/notes.xml
+++ /dev/null
@@ -1,256 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2007</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>DocBuilder Release Notes</title>
- <prepared>otp_appnotes</prepared>
- <docno>nil</docno>
- <date>nil</date>
- <rev>nil</rev>
- <file>notes.xml</file>
- </header>
- <p>This document describes the changes made to the 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>
- <list>
- <item>
- <p> Fix compatibility issues with docbuilder for R11
- documentation patches. </p>
- <p>
- Own Id: OTP-8946</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Docbuilder 0.9.8.8</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> Fixed problem with a centered table that was
- transformed into an xml document which then produced
- mis-formatted html. </p>
- <p>
- Own Id: OTP-8784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Docbuilder 0.9.8.7</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>The documentation is now possible to build in an open
- source environment after a number of bugs are fixed and
- some features are added in the documentation build
- process. </p>
- <p>- The arity calculation is updated.</p>
- <p>- The module prefix used in the function names for
- bif's are removed in the generated links so the links
- will look like
- "http://www.erlang.org/doc/man/erlang.html#append_element-2"
- instead of
- "http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2".</p>
- <p>- Enhanced the menu positioning in the html
- documentation when a new page is loaded.</p>
- <p>- A number of corrections in the generation of man
- pages (thanks to Sergei Golovan)</p>
- <p>- The legal notice is taken from the xml book file so
- OTP's build process can be used for non OTP
- applications.</p>
- <p>
- Own Id: OTP-8343</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Docbuilder 0.9.8.6</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The documentation is now built with open source tools
- (xsltproc and fop) that exists on most platforms. One
- visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Docbuilder 0.9.8.5</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>The copyright notices have been updated.</p>
- <p>
- Own Id: OTP-7851</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Docbuilder 0.9.8.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The element "code" with multiple CDATA or CDATA plus
- other data now works as expected, previously it caused a
- crash.</p>
- <p>
- Own Id: OTP-7236</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Docbuilder 0.9.8</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The generated html should now be valid xhtml (with a few
- exceptions to be fixed in next version).</p>
- <p>
- Own Id: OTP-7027</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section><title>Docbuilder 0.9.7</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- New fonts and new CSS style included in generated html documents.
- </p>
- </item>
- <item>
- <p>
- Updated DTD's with new header elements copyright and legalnotice.
- Element authors changed to optional instead of mandatory.
-
- </p>
- </item>
- </list>
- </section>
- </section>
-
- <section><title>Docbuilder 0.9.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Line breaks within <c>pre</c> are now always preserved.</p>
- <p>
- The definition of <c>name</c> in the cref DTD is now
- correctly handled.</p>
- <p>
- <c>docb_transform</c>: The HTML snippet returned by the
- <c>Module:head()</c> callback function is now placed
- below the title in the HTML file (as specified in the
- documentation), not on the same line.</p>
- <p>
- <c>docb_gen</c>: Added option <c>sort_functions</c>.</p>
- <p>
- Fixed bugs in cites and terms DTD, and also in book,
- bookinsidecover and report DTDs which are not officially
- supported (yet).</p>
- <p>
- License info added to all DTD files.</p>
- <p>
- Corrections and clarifications made to the User's Guide.</p>
- <p>
- Own Id: OTP-6775</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>DocBuilder 0.9</title>
- <p>First version of DocBuilder released as part of Erlang/OTP.
- Previously it has been used as an internal tool only.</p>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/overview.xml b/lib/docbuilder/doc/src/overview.xml
deleted file mode 100644
index ca13c5d436..0000000000
--- a/lib/docbuilder/doc/src/overview.xml
+++ /dev/null
@@ -1,185 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2009</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>Overview</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>overview.xml</file>
- </header>
-
- <section>
- <title>Background</title>
-
- <p>DocBuilder has been used within the OTP project to generate
- documentation for Erlang/OTP itself for more than ten years.
- It has now been released as a regular Erlang/OTP application.</p>
-
- <p>The intention with DocBuilder is that it should be as easy to
- use and maintain as possible and generate adequate documentation
- for OTP's needs. It uses frames, which can probably be regarded as
- old-fashioned today. Hopefully, this should be improved in
- the future.</p>
-
- <p>Originally, DocBuilder input was SGML files and external tools
- was used for parsing. The internal version used in the OTP
- project can generate not only HTML code but also LaTeX (for PDF
- and PostScript) and nroff (for UNIX man pages). (Again, using
- external tools). Because of this, the parsed source code is
- transformed into a tree structure before being transformed again
- into the desired format.</p>
- </section>
-
- <section>
- <title>DTD Suite</title>
-
- <p>Input is written as XML according to one of the DTDs and output
- is corresponding HTML. Documentation for an Erlang/OTP application
- is usually organized as follows:</p>
- <taglist>
- <tag><em>User's Guide</em></tag>
- <item>
- <p>(DTD:
- <seealso marker="user_guide_dtds#partDTD">part</seealso>)
- A collection of chapters
- (<seealso marker="user_guide_dtds#chapterDTD">chapter</seealso>).
- </p>
- </item>
-
- <tag><em>Reference Manual</em></tag>
- <item>
- <p>(DTD:
- <seealso marker="refman_dtds#applicationDTD">application</seealso>
- A collection of manual pages for modules
- (<seealso marker="refman_dtds#erlrefDTD">erlref</seealso>),
- applications
- (<seealso marker="refman_dtds#apprefDTD">appref</seealso>),
- commands
- (<seealso marker="refman_dtds#comrefDTD">comref</seealso>),
- C libraries
- (<seealso marker="refman_dtds#crefDTD">cref</seealso>) and
- files
- (<seealso marker="refman_dtds#filerefDTD">fileref</seealso>).
- </p>
- </item>
-
- <tag><em>Release Notes</em></tag>
- <item>
- <p>Same structure as the User's Guide.</p>
- </item>
- </taglist>
-
- <p>In some cases, one or more of the User's Guide, Reference Manual
- and Release Notes are omitted. Also, it is possible to use either
- the <c>application</c> or <c>part</c> DTD to write other types
- of documentation for the application.</p>
-
- <p>A special kind of DTD,
- <seealso marker="fasc_dtds">fascicules</seealso>, can be used to
- specify the different parts of the documentation, and which one
- of those should be shown as default.</p>
- </section>
-
- <section>
- <title>Structure of Generated HTML</title>
-
- <p>The generated HTML corresponding to a <c>part</c> or
- <c>application</c> document is split into a left frame and a right
- frame. The left frame contains information about the document
- and links to the included files, that is chapters or manual pages.
- The right frame is used to display either the front page for
- the document, or the selected chapter/manual page.</p>
-
- <p>The left frame also contains links to a bibliography and a
- glossary, which are automatically generated.</p>
-
- <p>In the case of an <c>application</c> document, the left frame
- also contains a link to an automatically generated index.</p>
- </section>
-
- <section>
- <title>Basic Tags</title>
-
- <p>All DTDs in the DocBuilder DTD suite share a basic set of tags.
- An author can easily switch from one DTD to another and still use
- the same basic tags. It is furthermore easy to copy pieces of
- information from one document to another, even though they do not
- use the same DTD.</p>
-
- <p>The basic set of tags are divided into two categories:
- <seealso marker="block_tags">block tags</seealso> and
- <seealso marker="inline_tags">inline tags</seealso>. Block tags
- typically define a separate block of information, like a
- paragraph or a list. Inline tags are typically used within block
- tags, for example a highlighted word within a paragraph.</p>
- </section>
-
- <section>
- <title>About This Document</title>
-
- <p>In this User's Guide, the structure of the different documents
- and the meaning of the tags are explained. There are numerous
- examples of documentation source code.</p>
-
- <p>For readability and simplicity, the examples have been kept as
- short as possible. For an example of what the generated HTML
- will look like, it is recommended to look at the DocBuilder
- documentation itself:</p>
- <list>
- <item>This User's Guide is written using the <c>part</c> and
- <c>chapter</c> DTDs.</item>
-
- <item>The Reference Manual is written using
- the <c>application</c>, <c>appref</c> and <c>erlref</c> DTDs.
- </item>
- </list>
- </section>
-
- <section>
- <title>Usage</title>
-
- <list type="ordered">
- <item>
- <p>Create the relevant XML files.</p>
-
- <p>If there are EDoc comments in a module, the function
- <seealso marker="docb_gen#module/1">docb_gen:module/1,2</seealso>
- can be used to generate an XML file according to
- the <c>erlref</c> DTD for this module.</p>
- </item>
-
- <item>
- <p>The XML files can be validated using
- <seealso marker="docb_xml_check#validate/1">docb_xml_check:validate/1</seealso>.
- </p>
- </item>
-
- <item>
- <p>Generate HTML files by using
- <seealso marker="docb_transform#file/1">docb_transform:file/1,2</seealso>.
- </p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/part.xml b/lib/docbuilder/doc/src/part.xml
deleted file mode 100644
index 546c6c612e..0000000000
--- a/lib/docbuilder/doc/src/part.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2007</year><year>2009</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>DocBuilder User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Docbuilder</em> provides functionality for generating HTML
- documentation for Erlang modules and Erlang/OTP applications
- from XML source code and/or EDoc comments in Erlang source code.</p>
- </description>
- <xi:include href="overview.xml"/>
- <xi:include href="user_guide_dtds.xml"/>
- <xi:include href="refman_dtds.xml"/>
- <xi:include href="fasc_dtds.xml"/>
- <xi:include href="header_tags.xml"/>
- <xi:include href="block_tags.xml"/>
- <xi:include href="inline_tags.xml"/>
- <xi:include href="character_entities.xml"/>
-</part>
-
diff --git a/lib/docbuilder/doc/src/part_notes.xml b/lib/docbuilder/doc/src/part_notes.xml
deleted file mode 100644
index 2f824630fb..0000000000
--- a/lib/docbuilder/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2007</year><year>2009</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>DocBuilder Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Docbuilder</em> provides functionality for generating HTML
- documentation for Erlang modules and Erlang/OTP applications
- from XML source code and/or EDoc comments in Erlang source code.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/docbuilder/doc/src/ref_man.xml b/lib/docbuilder/doc/src/ref_man.xml
deleted file mode 100644
index 7be8ace32f..0000000000
--- a/lib/docbuilder/doc/src/ref_man.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2007</year><year>2009</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>DocBuilder Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>DocBuilder</em> provides functionality for generating HTML
- documentation for Erlang modules and Erlang/OTP applications
- from XML source code and/or EDoc comments in Erlang source code.</p>
- </description>
- <xi:include href="docbuilder_app.xml"/>
- <xi:include href="docb_gen.xml"/>
- <xi:include href="docb_transform.xml"/>
- <xi:include href="docb_xml_check.xml"/>
-</application>
-
diff --git a/lib/docbuilder/doc/src/refman_dtds.xml b/lib/docbuilder/doc/src/refman_dtds.xml
deleted file mode 100644
index a7beaed708..0000000000
--- a/lib/docbuilder/doc/src/refman_dtds.xml
+++ /dev/null
@@ -1,667 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2009</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>Reference Manual DTDs</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>refman_dtds.xml</file>
- </header>
-
- <p>There are five DTDs for writing manual pages about applications,
- shell commands, C libraries, Erlang modules and files, all with a
- similar structure:</p>
-
- <list type="bulleted">
- <item>A header.</item>
- <item>Name of the application/command/library/module/file.</item>
- <item>Short summary (one line).</item>
- <item>A longer description.</item>
- <item>"Formal" definitions of functions or commands.</item>
- <item>Optional sections of free text.</item>
- <item>Optional section with the name(s) and email(s) of the author(s).</item>
- </list>
-
- <p>The differences between the DTDs are the tags for the name,
- the short summary and some tags inside the "formal" definitions.</p>
-
- <section>
- <marker id="applicationDTD"></marker>
- <title>The application DTD</title>
-
- <p>The <c>application</c> DTD is intended for a Reference Manual and
- groups a set of manual pages into one unit. The structure is
- similar to the part DTD: first an introduction and then the manual
- pages, written in separate files with the
- <seealso marker="#apprefDTD">appref</seealso>,
- <seealso marker="#comrefDTD">comref</seealso>,
- <seealso marker="#crefDTD">cref</seealso>,
- <seealso marker="#erlrefDTD">erlref</seealso>, or
- <seealso marker="#filerefDTD">fileref</seealso> DTD.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE application SYSTEM "application.dtd">
-&lt;application>
- &lt;header>
- &lt;title>Application name&lt;/title>
- &lt;prepared/>
- &lt;docno/>
- &lt;date/>
- &lt;rev/>
- &lt;/header>
-
- &lt;description>
- &lt;p>Application description...&lt;/p>
- &lt;/description>
-
- &lt;include file="module1">
- &lt;include file="module2">
-&lt;/application>
- </pre>
- </section>
-
- <section>
- <marker id="applicationTAG"></marker>
- <title>&lt;application&gt;</title>
-
- <p>The top level tag of an <c>application</c> DTD.</p>
-
- <p>Contains a
- <seealso marker="header_tags">&lt;header&gt;</seealso>,
- an optional
- <seealso marker="user_guide_dtds#descriptionTAG">&lt;description&gt;</seealso>,
- followed by one or more
- <seealso marker="user_guide_dtds#includeTAG">&lt;include&gt;</seealso>.
- </p>
- </section>
-
- <section>
- <marker id="apprefDTD"></marker>
- <title>The appref DTD</title>
-
- <p>This is the DTD for writing an application manual page.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE appref SYSTEM "appref.dtd">
-&lt;appref>
- &lt;header>
- &lt;title>Application name&lt;/title>
- &lt;prepared/>
- &lt;docno/>
- &lt;date/>
- &lt;rev/>
- &lt;/header>
-
- &lt;app>Application name&lt;/app>
-
- &lt;appsummary>A short application summary.&lt;/appsummary>
-
- &lt;description>
- &lt;p>A longer description of the application.&lt;/p>
- &lt;/description>
-
- &lt;section>
- &lt;title>Configuration&lt;/title>
-
- &lt;p>...&lt;/p>
- &lt;/section>
-
- ...
-
- &lt;authors>
- &lt;aname>Name of author&lt;/aname>
- &lt;email>Email of author&lt;/email>
- &lt;/authors>
-&lt;/appref>
- </pre>
-
- <section>
- <marker id="apprefTAG"></marker>
- <title>&lt;appref&gt;</title>
-
- <p>The top level tag of an <c>appref</c> DTD.</p>
-
- <p>Contains
- <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
- <seealso marker="#appTAG">&lt;app&gt;</seealso>,
- <seealso marker="#appsummaryTAG">&lt;appsummary&gt;</seealso>,
- <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
- zero or more
- <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
- <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
- followed by zero or more
- <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="appTAG"></marker>
- <title>&lt;app&gt;</title>
-
- <p>The application name. Contains plain text.</p>
- </section>
-
- <section>
- <marker id="appsummaryTAG"></marker>
- <title>&lt;appsummary&gt;</title>
-
- <p>Short summary. Contains plain text.</p>
- </section>
- </section>
-
- <section>
- <marker id="comrefDTD"></marker>
- <title>The comref DTD</title>
-
- <p>This is the DTD for writing a command manual page.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE comref SYSTEM "comref.dtd">
-&lt;comref>
- &lt;header>
- &lt;title>Command name&lt;/title>
- &lt;prepared/>
- &lt;docno/>
- &lt;date/>
- &lt;rev/>
- &lt;/header>
-
- &lt;com>Command name&lt;/com>
-
- &lt;comsummary>A short command summary.&lt;/comsummary>
-
- &lt;description>
- &lt;p>A long description of the command.&lt;/p>
- &lt;/description>
-
- &lt;funcs>
- &lt;func>
- &lt;name>command&lt;/name>
- &lt;name>command -flag &lt;arg>&lt;/name>
- &lt;fsummary>A short command summary (max 40 characters).&lt;/fsummary>
- &lt;desc>
- &lt;p>An extended command description.
- &lt;/desc>
- &lt;/func>
- &lt;/funcs>
-
- &lt;section>
- &lt;title>Options&lt;/title>
-
- &lt;p>...&lt;/p>
- &lt;/section>
-
- &lt;authors>
- &lt;aname>Name of author&lt;/aname>
- &lt;email>Email of author&lt;/email>
- &lt;/authors>
-&lt;/comref>
- </pre>
-
- <section>
- <marker id="comrefTAG"></marker>
- <title>&lt;comref&gt;</title>
-
- <p>The top level tag for a <c>comref</c> DTD.</p>
-
- <p>Contains
- <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
- <seealso marker="#comTAG">&lt;com&gt;</seealso>,
- <seealso marker="#comsummaryTAG">&lt;comsummary&gt;</seealso>,
- <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
- zero or more
- <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
- <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
- followed by zero or more
- <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="comTAG"></marker>
- <title>&lt;com&gt;</title>
-
- <p>The command name. Contains plain text.</p>
- </section>
-
- <section>
- <marker id="comsummaryTAG"></marker>
-
- <title>&lt;comsummary&gt;</title>
-
- <p>Short summary. Contains plain text.</p>
- </section>
- </section>
-
- <section>
- <marker id="crefDTD"></marker>
- <title>The cref DTD</title>
-
- <p>This is the DTD for writing a C library manual page.</p>
-
- <p>Example:</p>
- <pre><![CDATA[
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE cref SYSTEM "cref.dtd">
-<cref>
- <header>
- <title>C library name</title>
- <prepared/>
- <docno/>
- <date/>
- <rev/>
- </header>
-
- <lib>C library name</lib>
-
- <libsummary>A short C library summary.</libsummary>
-
- <description>
- <p>A longer description of the C library.</p>
- </description>
-
- <funcs>
- <func>
- <name><ret>void</ret><nametext>start(bar)</nametext></name>
- <name><ret>void</ret><nametext>start(foo)</nametext></name>
- <fsummary>A short function summary (max 40 characters).</fsummary>
- <type>
- <v>char bar</v>
- <v>int foo</v>
- </type>
- <desc>
- <p>An extended function description.</p>
- </desc>
- </func>
-
- ...
- </funcs>
-
- <section>
- <title>A title</title>
-
- <p>Some text...</p>
- </section>
-
-
-</cref>
- ]]></pre>
-
- <section>
- <marker id="crefTAG"></marker>
- <title>&lt;cref&gt;</title>
-
- <p>The top level tag for a <c>cref</c> DTD.</p>
-
- <p>Contains
- <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
- <seealso marker="#libTAG">&lt;lib&gt;</seealso>,
- <seealso marker="#libsummaryTAG">&lt;libsummary&gt;</seealso>,
- <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
- zero or more
- <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
- <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>, followed by
- zero or more
- <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="libTAG"></marker>
- <title>&lt;lib&gt;</title>
-
- <p>The C library name or acronym. Contains plain text.</p>
- </section>
-
- <section>
- <marker id="libsummaryTAG"></marker>
- <title>&lt;libsummary&gt;</title>
-
- <p>Short summary. Contains plain text.</p>
- </section>
- </section>
-
- <section>
- <marker id="erlrefDTD"></marker>
- <title>The erlref DTD</title>
-
- <p>This is the DTD for writing Erlang module manual pages.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE erlref SYSTEM "erlref.dtd">
-&lt;erlref>
- &lt;header>
- &lt;title>Module name&lt;/title>
- &lt;prepared/>
- &lt;docno/>
- &lt;date/>
- &lt;rev/>
- &lt;/header>
-
- &lt;module>Module name&lt;/module>
-
- &lt;modulesummary>A short module summary.&lt;/modulesummary>
-
- &lt;description>
- &lt;p>A longer description of the module.&lt;/p>
- &lt;/description>
-
- &lt;funcs>
- &lt;func>
- &lt;name>start() -> Result&lt;/name>
- &lt;name>start(N) -> Result&lt;/name>
- &lt;fsummary>A short function summary (max 40 characters).&lt;/fsummary>
- &lt;type>
- &lt;v>Pid = pid()&lt;/v>
- &lt;v>N = int()&lt;/v>
- &lt;v>Result = {ok, Pid} | {error, Reason}&lt;/v>
- &lt;v>Reason = term()&lt;/v>
- &lt;d>A parameter description.&lt;/d>
- &lt;/type>
- &lt;desc>
- &lt;p>An extended function description.&lt;/p>
- &lt;/desc>
- &lt;/func>
-
- ...
- &lt;/funcs>
-
- &lt;section>
- &lt;title>Some Title&lt;/title>
- &lt;p>Some text...&lt;/p>
- &lt;/section>
-
- &lt;authors>
- &lt;aname>Name of author&lt;/aname>
- &lt;email>Email of author&lt;/email>
- &lt;/authors>
-&lt;/erlref>
- </pre>
-
- <section>
- <marker id="erlrefTAG"></marker>
- <title>&lt;erlref&gt;</title>
-
- <p>The top level tag for an <c>erlref</c> DTD.</p>
-
- <p>Contains
- <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
- <seealso marker="#moduleTAG">&lt;module&gt;</seealso>,
- <seealso marker="#modulesummaryTAG">&lt;modulesummary&gt;</seealso>,
- <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
- zero or more
- <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
- <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
- followed by zero or more
- <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="moduleTAG"></marker>
- <title>&lt;module&gt;</title>
-
- <p>The module name. Contains plain text.</p>
- </section>
-
- <section>
- <marker id="modulesummaryTAG"></marker>
- <title>&lt;modulesummary&gt;</title>
-
- <p>Short summary. Contains plain text.</p>
- </section>
- </section>
-
- <section>
- <marker id="filerefDTD"></marker>
- <title>The fileref DTD</title>
-
- <p>This is the DTD for writing file manual pages. In OTP, this DTD
- is used for defining the format of for example <c>.rel</c> and
- <c>.app</c> files.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE fileref SYSTEM "fileref.dtd">
-&lt;fileref>
- &lt;header>
- &lt;title>File name&lt;/title>
- &lt;prepared/>
- &lt;docno/>
- &lt;date/>
- &lt;rev/>
- &lt;/header>
-
- &lt;file>fileref&lt;/file>
-
- &lt;filesummary>A short file summary.&lt;/filesummary>
-
- &lt;description>
- &lt;p>A longer description of the file.&lt;/p>
- &lt;/description>
-
- &lt;section>
- &lt;title>File format&lt;/title>
-
- &lt;p>...&lt;/p>
- &lt;/section>
-
- &lt;authors>
- &lt;aname>Name of author&lt;/aname>
- &lt;email>Email of author&lt;/email>
- &lt;/authors>
-&lt;/fileref>
- </pre>
-
- <p>The file reference manual can also contain function definitions,
- similar to the <c>erlref</c> DTD.</p>
-
- <section>
- <marker id="filerefTAG"></marker>
- <title>&lt;fileref&gt;</title>
-
- <p>The top level tag for a <c>fileref</c> DTD.</p>
-
- <p>Contains
- <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
- <seealso marker="#fileTAG">&lt;file&gt;</seealso>,
- <seealso marker="#filesummaryTAG">&lt;filesummary&gt;</seealso>,
- <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
- zero or more
- <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
- <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
- followed by zero or more
- <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="fileTAG"></marker>
- <title>&lt;file&gt;</title>
-
- <p>The name of the file or file type. Contains plain text.</p>
- </section>
-
- <section>
- <marker id="filesummaryTAG"></marker>
- <title>&lt;filesummary&gt;</title>
-
- <p>Short summary. Contains plain text.</p>
- </section>
- </section>
-
- <section>
- <marker id="descriptionTAG"></marker>
- <title>&lt;description&gt;</title>
-
- <p>The introduction after the title and before sections and
- "formal" definitions.</p>
-
- <p>Contains any combination and any number of
- <seealso marker="block_tags">block tags</seealso> except
- <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.</p>
- </section>
-
- <section>
- <marker id="sectionTAG"></marker>
- <title>&lt;section&gt;</title>
-
- <p>Subdivisions of the document. Contains an optional
- <seealso marker="inline_tags#markerTAG">&lt;marker&gt;</seealso>,
- a <seealso marker="user_guide_dtds#titleTAG">&lt;title&gt;</seealso>,
-
- followed by any combination and any number of
- <seealso marker="block_tags">block tags</seealso> except
- <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.</p>
- </section>
-
- <section>
- <marker id="funcsTAG"></marker>
- <title>&lt;funcs&gt;</title>
-
- <p>A group of "formal" function definitions.</p>
-
- <p>Contains one or more
- <seealso marker="#funcTAG">&lt;func&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="funcTAG"></marker>
- <title>&lt;func&gt;</title>
-
- <p>A "formal" function definition.</p>
-
- <p>Contains one or more
- <seealso marker="#nameTAG">&lt;name&gt;</seealso>, followed by
- <seealso marker="#fsummaryTAG">&lt;fsummary&gt;</seealso>,
- <seealso marker="#typeTAG">&lt;type&gt;</seealso> (optional) and
- <seealso marker="#descTAG">&lt;desc&gt;</seealso> (optional).</p>
- </section>
-
- <section>
- <marker id="nameTAG"></marker>
- <title>&lt;name&gt;</title>
-
- <p>Function/command signature with name, arguments and return value.
- Contains plain text, except for the <c>cref</c> DTD where it
- contains a <c><![CDATA[<ret>]]></c> (return type, plain text) and
- a <c><![CDATA[<nametext>]]></c> (function name and arguments,
- plain text).</p>
-
- <p>In the case of an <c>erlref</c> DTD, DocBuilder will
- automatically try to add a
- <seealso marker="inline_tags#markerTAG">marker</seealso>,
- <c><![CDATA[<marker id="Name/Arity">]]></c> or
- <c><![CDATA[<marker id="Name">]]></c>, based on the contents of
- this tag before the function definition.</p>
-
- <p>Example: Consider the following name definition</p>
- <pre><![CDATA[
-<name>foo(Arg1, Arg2) -> ok | {error, Reason}</name>
- ]]></pre>
-
- <p>DocBuilder will create a marker
- <c><![CDATA[<marker id="foo/2">]]></c> before the function
- definition in the generated HTML. That is, referring to
- the function using
- <c><![CDATA[<seealso marker="#foo/2">foo/2</seealso>]]></c> will
- automatically work.</p>
- </section>
-
- <section>
- <marker id="fsummaryTAG"></marker>
- <title>&lt;fsummary&gt;</title>
-
- <p>Function/command summary. Contains plain text,
- <seealso marker="inline_tags#cTAG">&lt;c&gt;</seealso> and
- <seealso marker="inline_tags#emTAG">&lt;em&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="typeTAG"></marker>
- <title>&lt;type&gt;</title>
-
- <p>Type declarations for the function/command.</p>
-
- <p>Contains one or more pairs of
- <seealso marker="#vTAG">&lt;v&gt;</seealso> and
- <seealso marker="#dTAG">&lt;d&gt;</seealso> (optional).</p>
- </section>
-
- <section>
- <marker id="vTAG"></marker>
- <title>&lt;v&gt;</title>
-
- <p>Type declaration for an argument or return value. Contains plain
- text.</p>
- </section>
-
- <section>
- <marker id="dTAG"></marker>
- <title>&lt;d&gt;</title>
-
- <p>Description for an argument or return value. Contains plain text,
- <seealso marker="inline_tags#cTAG">&lt;c&gt;</seealso> and
- <seealso marker="inline_tags#emTAG">&lt;em&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="descTAG"></marker>
- <title>&lt;desc&gt;</title>
-
- <p>Function/command description. Contains
- <seealso marker="block_tags">block tags</seealso> except
- <c>&lt;image&gt;</c> and <c>&lt;table&gt;</c>.</p>
- </section>
-
- <section>
- <marker id="authorsTAG"></marker>
- <title>&lt;authors&gt;</title>
-
- <p>Authors of the manual page. The <c>authors</c> element is optional.</p>
-
- <p>Contains one or more pairs of
- <seealso marker="#anameTAG">&lt;aname&gt;</seealso> and
- <seealso marker="#emailTAG">&lt;email&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="anameTAG"></marker>
- <title>&lt;aname&gt;</title>
-
- <p>Author name. Contains plain text.</p>
- </section>
-
- <section>
- <marker id="emailTAG"></marker>
- <title>&lt;email&gt;</title>
-
- <p>Author email address. Contains plain text.</p>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/doc/src/user_guide_dtds.xml b/lib/docbuilder/doc/src/user_guide_dtds.xml
deleted file mode 100644
index a2db44f830..0000000000
--- a/lib/docbuilder/doc/src/user_guide_dtds.xml
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2009</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>User's Guide DTDs</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>user_guide_dtds.xml</file>
- </header>
-
- <section>
- <marker id="partDTD"></marker>
- <title>The part DTD</title>
-
- <p>The <c>part</c> DTD is intended for a "normal" document, like
- the User's Guide or Release Notes. First are some paragraphs
- introducing the main contents. After that follows chapters,
- written in separate files with
- the <seealso marker="#chapterDTD">chapter</seealso> DTD.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE part SYSTEM "part.dtd"&gt;
-&lt;part&gt;
- &lt;header&gt;
- &lt;title&gt;The chapter title&lt;/title&gt;
- &lt;prepared&gt;The author&lt;/prepared&gt;
- &lt;docno/&gt;
- &lt;date/&gt;
- &lt;rev/&gt;
- &lt;/header&gt;
-
- &lt;description&gt;
- &lt;p&gt;Some text..&lt;/p&gt;
- &lt;/description&gt;
-
- &lt;include file="file1"&gt;&lt;/include&gt;
- &lt;include file="file2"&gt;&lt;/include&gt;
-&lt;/part&gt;
- </pre>
- </section>
-
- <section>
- <marker id="partTAG"></marker>
- <title>&lt;part></title>
-
- <p>The top level tag of a <c>part</c> DTD.</p>
-
- <p>Contains a
- <seealso marker="header_tags">&lt;header&gt;</seealso>,
- an optional
- <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
- followed by one or more
- <seealso marker="#includeTAG">&lt;include&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="descriptionTAG"/>
- <title>&lt;description&gt;</title>
-
- <p>The introduction after the title and before the bulk of
- included chapters/manual pages.</p>
-
- <p>Contains any combination and any number
- of <seealso marker="block_tags">block tags</seealso> except
- <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.</p>
- </section>
-
- <section>
- <marker id="includeTAG"></marker>
- <title>&lt;include&gt;</title>
-
- <p>An empty tag. The attribute <c>file</c> specifies a file to
- include. The <c>.xml</c> file extension should be omitted.</p>
-
- <p>Example:</p>
- <pre>
-&lt;include file="notes">&lt;/include>
- </pre>
- </section>
-
- <section>
- <marker id="chapterDTD"></marker>
- <title>The chapter DTD</title>
-
- <p>The <c>chapter</c> DTD is intended for a chapter in a User's
- Guide or similar with text divided into sections, which can be
- nested.</p>
-
- <p>Example:</p>
- <pre>
-&lt;?xml version="1.0" encoding="latin1" ?>
-&lt;!DOCTYPE chapter SYSTEM "chapter.dtd">
-&lt;chapter>
- &lt;header>
- &lt;title>Title on first level&lt;/title>
- &lt;prepared/>
- &lt;docno/>
- &lt;date/>
- &lt;rev/>
- &lt;/header>
-
- &lt;p>Introduction...&lt;/p>
-
- &lt;section>
- &lt;title>Title on second level&lt;/title>
-
- &lt;p>First paragraph.&lt;/p>
-
- &lt;p>Second paragraph etc.&lt;/p>
-
- &lt;section>
- &lt;title>Title on third level&lt;/title>
-
- &lt;p>...&lt;/p>
- &lt;/section>
- &lt;/section>
-
- ...
-&lt;/chapter>
- </pre>
- </section>
-
- <section>
- <marker id="chapterTAG"></marker>
- <title>&lt;chapter&gt;</title>
-
- <p>The top level tag of a <c>chapter</c> DTD.</p>
-
- <p>Contains a
- <seealso marker="header_tags">&lt;header&gt;</seealso>,
- an optional introduction consisting of any combination of
- <seealso marker="block_tags">block tags</seealso>,
- followed by one or more
- <seealso marker="#sectionTAG">&lt;section&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="sectionTAG"></marker>
- <title>&lt;section&gt;</title>
-
- <p>Subdivision of a chapter.</p>
-
- <p>Contains an optional
- <seealso marker="inline_tags#markerTAG">&lt;marker&gt;</seealso>,
- a <seealso marker="#titleTAG">&lt;title&gt;</seealso>,
- followed by any combination and any number of
- <seealso marker="block_tags">block tags</seealso> and
- <c><![CDATA[<section>]]></c>.</p>
- </section>
-
- <section>
- <marker id="titleTAG"></marker>
- <title>&lt;title&gt;</title>
-
- <p>Section title, contains plain text.</p>
- </section>
-</chapter>
-
diff --git a/lib/docbuilder/dtd/Makefile b/lib/docbuilder/dtd/Makefile
deleted file mode 100644
index 05c656f3fc..0000000000
--- a/lib/docbuilder/dtd/Makefile
+++ /dev/null
@@ -1,91 +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 expressed or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999-2000, Ericsson
-# Utvecklings AB. All Rights Reserved.''
-#
-# $Id$
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(DOCB_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/docbuilder-$(VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-DTD_FILES = \
- application.dtd \
- appref.dtd \
- book.dtd \
- bookinsidecover.dtd \
- chapter.dtd \
- cites.dtd \
- common.dtd \
- common.entities.dtd \
- common.header.dtd \
- common.image.dtd \
- common.refs.dtd \
- common.table.dtd \
- comref.dtd \
- cref.dtd \
- erlref.dtd \
- fascicules.dtd \
- fileref.dtd \
- part.dtd \
- report.dtd \
- terms.dtd \
- xhtml-lat1.ent \
- xhtml-special.ent \
- xhtml-symbol.ent \
- xhtml1-frameset.dtd \
- xhtml1-strict.dtd \
- xhtml1-transitional.dtd
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt:
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/dtd
- $(INSTALL_DATA) $(DTD_FILES) $(RELSYSDIR)/dtd
-
-release_docs_spec:
-
-
-
-
-
-
-
diff --git a/lib/docbuilder/dtd/common.dtd b/lib/docbuilder/dtd/common.dtd
deleted file mode 100644
index 2c4ad51ab1..0000000000
--- a/lib/docbuilder/dtd/common.dtd
+++ /dev/null
@@ -1,87 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!-- This file contains common stuff for all dtds. -->
-
-<!ENTITY % common.entities SYSTEM "common.entities.dtd" >
-%common.entities;
-
-<!ENTITY % block "p|pre|code|list|taglist|codeinclude|
- erleval" >
-<!ENTITY % inline "#PCDATA|c|em|term|cite|br|path|seealso|
- url|marker" >
-<!-- XXX -->
-<!ELEMENT p (%inline;)* >
-<!ELEMENT pre (#PCDATA|seealso|url|input)* >
-<!ELEMENT input (#PCDATA|seealso|url)* >
-<!ELEMENT code (#PCDATA) >
-<!ATTLIST code type (erl|c|none) "none" >
-<!ELEMENT quote (p)* >
-<!ELEMENT warning (%block;|quote|br|marker)* >
-<!ELEMENT note (%block;|quote|br|marker)* >
-<!ELEMENT c (#PCDATA) >
-<!ELEMENT em (#PCDATA|c)* >
-
-<!-- XXX -->
-<!ELEMENT term (termdef?) >
-<!ATTLIST term id CDATA #REQUIRED >
-<!ELEMENT termdef (#PCDATA) >
-<!ELEMENT cite (citedef?) >
-<!ATTLIST cite id CDATA #REQUIRED >
-<!ELEMENT citedef (ctitle,cauthor,chowpublished) >
-<!ELEMENT ctitle (#PCDATA) >
-<!ELEMENT cauthor (#PCDATA) >
-<!ELEMENT chowpublished (#PCDATA) >
-
-<!-- XXX -->
-<!ELEMENT br EMPTY >
-
-<!-- Path -->
-
-<!ELEMENT path (#PCDATA) >
-<!ATTLIST path unix CDATA ""
- windows CDATA "" >
-
-<!-- List -->
-
-<!ELEMENT list (item+) >
-<!ATTLIST list type (ordered|bulleted) "bulleted" >
-<!ELEMENT taglist (tag,item)+ >
-<!ELEMENT tag (#PCDATA|c|em|seealso|url)* >
-<!ELEMENT item (%inline;|%block;)* >
-
-<!-- References -->
-
-<!ELEMENT seealso (#PCDATA) >
-<!ATTLIST seealso marker CDATA #REQUIRED >
-<!ELEMENT url (#PCDATA) >
-<!ATTLIST url href CDATA #REQUIRED >
-<!ELEMENT marker EMPTY >
-<!ATTLIST marker id CDATA #REQUIRED >
-
-<!-- CodeInclude -->
-
-<!ELEMENT codeinclude EMPTY >
-<!ATTLIST codeinclude file CDATA #REQUIRED
- tag CDATA ""
- type (erl|c|none) "none" >
-
-<!-- ErlEval -->
-
-<!ELEMENT erleval EMPTY >
-<!ATTLIST erleval expr CDATA #REQUIRED >
diff --git a/lib/docbuilder/dtd/common.refs.dtd b/lib/docbuilder/dtd/common.refs.dtd
deleted file mode 100644
index 7b9974fbda..0000000000
--- a/lib/docbuilder/dtd/common.refs.dtd
+++ /dev/null
@@ -1,40 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!-- This file contains common stuff for the *ref.dtd files.
- Note that `name' is defined in each *ref.dtd. -->
-
-<!ENTITY % common SYSTEM "common.dtd" >
-%common;
-<!ENTITY % common.header SYSTEM "common.header.dtd" >
-%common.header;
-
-<!ELEMENT description (%block;|quote|br|marker|warning|note)* >
-<!ELEMENT funcs (func)+ >
-<!ELEMENT func (name+,fsummary,type?,desc?) >
-<!-- ELEMENT name is defined in each ref dtd -->
-<!ELEMENT fsummary (#PCDATA|c|em)* >
-<!ELEMENT type (v,d?)+ >
-<!ELEMENT v (#PCDATA) >
-<!ELEMENT d (#PCDATA|c|em)* >
-<!ELEMENT desc (%block;|quote|br|marker|warning|note)* >
-<!ELEMENT authors (aname,email)+ >
-<!ELEMENT aname (#PCDATA) >
-<!ELEMENT email (#PCDATA) >
-<!ELEMENT section (marker*,title,(%block;|quote|br|marker|
- warning|note)*) >
diff --git a/lib/docbuilder/dtd/erlref.dtd b/lib/docbuilder/dtd/erlref.dtd
deleted file mode 100644
index 21656a1446..0000000000
--- a/lib/docbuilder/dtd/erlref.dtd
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common.refs SYSTEM "common.refs.dtd" >
-%common.refs;
-
-<!ELEMENT erlref (header,module,modulesummary,description,
- (section|funcs)*,authors?) >
-<!ELEMENT module (#PCDATA) >
-<!ELEMENT modulesummary (#PCDATA) >
-
-<!-- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd -->
-<!ELEMENT name (#PCDATA) >
diff --git a/lib/docbuilder/dtd/xhtml-lat1.ent b/lib/docbuilder/dtd/xhtml-lat1.ent
deleted file mode 100644
index aaae738cfc..0000000000
--- a/lib/docbuilder/dtd/xhtml-lat1.ent
+++ /dev/null
@@ -1,196 +0,0 @@
-<!-- Portions (C) International Organization for Standardization 1986
- Permission to copy in any form is granted for use with
- conforming SGML systems and applications as defined in
- ISO 8879, provided this notice is included in all copies.
--->
-<!-- Character entity set. Typical invocation:
- <!ENTITY % HTMLlat1 PUBLIC
- "-//W3C//ENTITIES Latin 1 for XHTML//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
- %HTMLlat1;
--->
-
-<!ENTITY nbsp "&#160;"> <!-- no-break space = non-breaking space,
- U+00A0 ISOnum -->
-<!ENTITY iexcl "&#161;"> <!-- inverted exclamation mark, U+00A1 ISOnum -->
-<!ENTITY cent "&#162;"> <!-- cent sign, U+00A2 ISOnum -->
-<!ENTITY pound "&#163;"> <!-- pound sign, U+00A3 ISOnum -->
-<!ENTITY curren "&#164;"> <!-- currency sign, U+00A4 ISOnum -->
-<!ENTITY yen "&#165;"> <!-- yen sign = yuan sign, U+00A5 ISOnum -->
-<!ENTITY brvbar "&#166;"> <!-- broken bar = broken vertical bar,
- U+00A6 ISOnum -->
-<!ENTITY sect "&#167;"> <!-- section sign, U+00A7 ISOnum -->
-<!ENTITY uml "&#168;"> <!-- diaeresis = spacing diaeresis,
- U+00A8 ISOdia -->
-<!ENTITY copy "&#169;"> <!-- copyright sign, U+00A9 ISOnum -->
-<!ENTITY ordf "&#170;"> <!-- feminine ordinal indicator, U+00AA ISOnum -->
-<!ENTITY laquo "&#171;"> <!-- left-pointing double angle quotation mark
- = left pointing guillemet, U+00AB ISOnum -->
-<!ENTITY not "&#172;"> <!-- not sign = discretionary hyphen,
- U+00AC ISOnum -->
-<!ENTITY shy "&#173;"> <!-- soft hyphen = discretionary hyphen,
- U+00AD ISOnum -->
-<!ENTITY reg "&#174;"> <!-- registered sign = registered trade mark sign,
- U+00AE ISOnum -->
-<!ENTITY macr "&#175;"> <!-- macron = spacing macron = overline
- = APL overbar, U+00AF ISOdia -->
-<!ENTITY deg "&#176;"> <!-- degree sign, U+00B0 ISOnum -->
-<!ENTITY plusmn "&#177;"> <!-- plus-minus sign = plus-or-minus sign,
- U+00B1 ISOnum -->
-<!ENTITY sup2 "&#178;"> <!-- superscript two = superscript digit two
- = squared, U+00B2 ISOnum -->
-<!ENTITY sup3 "&#179;"> <!-- superscript three = superscript digit three
- = cubed, U+00B3 ISOnum -->
-<!ENTITY acute "&#180;"> <!-- acute accent = spacing acute,
- U+00B4 ISOdia -->
-<!ENTITY micro "&#181;"> <!-- micro sign, U+00B5 ISOnum -->
-<!ENTITY para "&#182;"> <!-- pilcrow sign = paragraph sign,
- U+00B6 ISOnum -->
-<!ENTITY middot "&#183;"> <!-- middle dot = Georgian comma
- = Greek middle dot, U+00B7 ISOnum -->
-<!ENTITY cedil "&#184;"> <!-- cedilla = spacing cedilla, U+00B8 ISOdia -->
-<!ENTITY sup1 "&#185;"> <!-- superscript one = superscript digit one,
- U+00B9 ISOnum -->
-<!ENTITY ordm "&#186;"> <!-- masculine ordinal indicator,
- U+00BA ISOnum -->
-<!ENTITY raquo "&#187;"> <!-- right-pointing double angle quotation mark
- = right pointing guillemet, U+00BB ISOnum -->
-<!ENTITY frac14 "&#188;"> <!-- vulgar fraction one quarter
- = fraction one quarter, U+00BC ISOnum -->
-<!ENTITY frac12 "&#189;"> <!-- vulgar fraction one half
- = fraction one half, U+00BD ISOnum -->
-<!ENTITY frac34 "&#190;"> <!-- vulgar fraction three quarters
- = fraction three quarters, U+00BE ISOnum -->
-<!ENTITY iquest "&#191;"> <!-- inverted question mark
- = turned question mark, U+00BF ISOnum -->
-<!ENTITY Agrave "&#192;"> <!-- latin capital letter A with grave
- = latin capital letter A grave,
- U+00C0 ISOlat1 -->
-<!ENTITY Aacute "&#193;"> <!-- latin capital letter A with acute,
- U+00C1 ISOlat1 -->
-<!ENTITY Acirc "&#194;"> <!-- latin capital letter A with circumflex,
- U+00C2 ISOlat1 -->
-<!ENTITY Atilde "&#195;"> <!-- latin capital letter A with tilde,
- U+00C3 ISOlat1 -->
-<!ENTITY Auml "&#196;"> <!-- latin capital letter A with diaeresis,
- U+00C4 ISOlat1 -->
-<!ENTITY Aring "&#197;"> <!-- latin capital letter A with ring above
- = latin capital letter A ring,
- U+00C5 ISOlat1 -->
-<!ENTITY AElig "&#198;"> <!-- latin capital letter AE
- = latin capital ligature AE,
- U+00C6 ISOlat1 -->
-<!ENTITY Ccedil "&#199;"> <!-- latin capital letter C with cedilla,
- U+00C7 ISOlat1 -->
-<!ENTITY Egrave "&#200;"> <!-- latin capital letter E with grave,
- U+00C8 ISOlat1 -->
-<!ENTITY Eacute "&#201;"> <!-- latin capital letter E with acute,
- U+00C9 ISOlat1 -->
-<!ENTITY Ecirc "&#202;"> <!-- latin capital letter E with circumflex,
- U+00CA ISOlat1 -->
-<!ENTITY Euml "&#203;"> <!-- latin capital letter E with diaeresis,
- U+00CB ISOlat1 -->
-<!ENTITY Igrave "&#204;"> <!-- latin capital letter I with grave,
- U+00CC ISOlat1 -->
-<!ENTITY Iacute "&#205;"> <!-- latin capital letter I with acute,
- U+00CD ISOlat1 -->
-<!ENTITY Icirc "&#206;"> <!-- latin capital letter I with circumflex,
- U+00CE ISOlat1 -->
-<!ENTITY Iuml "&#207;"> <!-- latin capital letter I with diaeresis,
- U+00CF ISOlat1 -->
-<!ENTITY ETH "&#208;"> <!-- latin capital letter ETH, U+00D0 ISOlat1 -->
-<!ENTITY Ntilde "&#209;"> <!-- latin capital letter N with tilde,
- U+00D1 ISOlat1 -->
-<!ENTITY Ograve "&#210;"> <!-- latin capital letter O with grave,
- U+00D2 ISOlat1 -->
-<!ENTITY Oacute "&#211;"> <!-- latin capital letter O with acute,
- U+00D3 ISOlat1 -->
-<!ENTITY Ocirc "&#212;"> <!-- latin capital letter O with circumflex,
- U+00D4 ISOlat1 -->
-<!ENTITY Otilde "&#213;"> <!-- latin capital letter O with tilde,
- U+00D5 ISOlat1 -->
-<!ENTITY Ouml "&#214;"> <!-- latin capital letter O with diaeresis,
- U+00D6 ISOlat1 -->
-<!ENTITY times "&#215;"> <!-- multiplication sign, U+00D7 ISOnum -->
-<!ENTITY Oslash "&#216;"> <!-- latin capital letter O with stroke
- = latin capital letter O slash,
- U+00D8 ISOlat1 -->
-<!ENTITY Ugrave "&#217;"> <!-- latin capital letter U with grave,
- U+00D9 ISOlat1 -->
-<!ENTITY Uacute "&#218;"> <!-- latin capital letter U with acute,
- U+00DA ISOlat1 -->
-<!ENTITY Ucirc "&#219;"> <!-- latin capital letter U with circumflex,
- U+00DB ISOlat1 -->
-<!ENTITY Uuml "&#220;"> <!-- latin capital letter U with diaeresis,
- U+00DC ISOlat1 -->
-<!ENTITY Yacute "&#221;"> <!-- latin capital letter Y with acute,
- U+00DD ISOlat1 -->
-<!ENTITY THORN "&#222;"> <!-- latin capital letter THORN,
- U+00DE ISOlat1 -->
-<!ENTITY szlig "&#223;"> <!-- latin small letter sharp s = ess-zed,
- U+00DF ISOlat1 -->
-<!ENTITY agrave "&#224;"> <!-- latin small letter a with grave
- = latin small letter a grave,
- U+00E0 ISOlat1 -->
-<!ENTITY aacute "&#225;"> <!-- latin small letter a with acute,
- U+00E1 ISOlat1 -->
-<!ENTITY acirc "&#226;"> <!-- latin small letter a with circumflex,
- U+00E2 ISOlat1 -->
-<!ENTITY atilde "&#227;"> <!-- latin small letter a with tilde,
- U+00E3 ISOlat1 -->
-<!ENTITY auml "&#228;"> <!-- latin small letter a with diaeresis,
- U+00E4 ISOlat1 -->
-<!ENTITY aring "&#229;"> <!-- latin small letter a with ring above
- = latin small letter a ring,
- U+00E5 ISOlat1 -->
-<!ENTITY aelig "&#230;"> <!-- latin small letter ae
- = latin small ligature ae, U+00E6 ISOlat1 -->
-<!ENTITY ccedil "&#231;"> <!-- latin small letter c with cedilla,
- U+00E7 ISOlat1 -->
-<!ENTITY egrave "&#232;"> <!-- latin small letter e with grave,
- U+00E8 ISOlat1 -->
-<!ENTITY eacute "&#233;"> <!-- latin small letter e with acute,
- U+00E9 ISOlat1 -->
-<!ENTITY ecirc "&#234;"> <!-- latin small letter e with circumflex,
- U+00EA ISOlat1 -->
-<!ENTITY euml "&#235;"> <!-- latin small letter e with diaeresis,
- U+00EB ISOlat1 -->
-<!ENTITY igrave "&#236;"> <!-- latin small letter i with grave,
- U+00EC ISOlat1 -->
-<!ENTITY iacute "&#237;"> <!-- latin small letter i with acute,
- U+00ED ISOlat1 -->
-<!ENTITY icirc "&#238;"> <!-- latin small letter i with circumflex,
- U+00EE ISOlat1 -->
-<!ENTITY iuml "&#239;"> <!-- latin small letter i with diaeresis,
- U+00EF ISOlat1 -->
-<!ENTITY eth "&#240;"> <!-- latin small letter eth, U+00F0 ISOlat1 -->
-<!ENTITY ntilde "&#241;"> <!-- latin small letter n with tilde,
- U+00F1 ISOlat1 -->
-<!ENTITY ograve "&#242;"> <!-- latin small letter o with grave,
- U+00F2 ISOlat1 -->
-<!ENTITY oacute "&#243;"> <!-- latin small letter o with acute,
- U+00F3 ISOlat1 -->
-<!ENTITY ocirc "&#244;"> <!-- latin small letter o with circumflex,
- U+00F4 ISOlat1 -->
-<!ENTITY otilde "&#245;"> <!-- latin small letter o with tilde,
- U+00F5 ISOlat1 -->
-<!ENTITY ouml "&#246;"> <!-- latin small letter o with diaeresis,
- U+00F6 ISOlat1 -->
-<!ENTITY divide "&#247;"> <!-- division sign, U+00F7 ISOnum -->
-<!ENTITY oslash "&#248;"> <!-- latin small letter o with stroke,
- = latin small letter o slash,
- U+00F8 ISOlat1 -->
-<!ENTITY ugrave "&#249;"> <!-- latin small letter u with grave,
- U+00F9 ISOlat1 -->
-<!ENTITY uacute "&#250;"> <!-- latin small letter u with acute,
- U+00FA ISOlat1 -->
-<!ENTITY ucirc "&#251;"> <!-- latin small letter u with circumflex,
- U+00FB ISOlat1 -->
-<!ENTITY uuml "&#252;"> <!-- latin small letter u with diaeresis,
- U+00FC ISOlat1 -->
-<!ENTITY yacute "&#253;"> <!-- latin small letter y with acute,
- U+00FD ISOlat1 -->
-<!ENTITY thorn "&#254;"> <!-- latin small letter thorn with,
- U+00FE ISOlat1 -->
-<!ENTITY yuml "&#255;"> <!-- latin small letter y with diaeresis,
- U+00FF ISOlat1 -->
diff --git a/lib/docbuilder/etc/Makefile b/lib/docbuilder/etc/Makefile
deleted file mode 100644
index a2f669d749..0000000000
--- a/lib/docbuilder/etc/Makefile
+++ /dev/null
@@ -1,67 +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 expressed or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999-2000, Ericsson
-# Utvecklings AB. All Rights Reserved.''
-#
-# $Id$
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(DOCB_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/docbuilder-$(VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-VAR_FILES = \
- note.gif \
- warning.gif
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt:
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/etc
- $(INSTALL_DATA) $(VAR_FILES) $(RELSYSDIR)/etc
-
-release_docs_spec:
-
-
-
-
-
-
-
diff --git a/lib/docbuilder/info b/lib/docbuilder/info
deleted file mode 100644
index 60daa212c8..0000000000
--- a/lib/docbuilder/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: doc
-short: Tool for generating HTML documentation for applications.
diff --git a/lib/docbuilder/src/Makefile b/lib/docbuilder/src/Makefile
deleted file mode 100644
index e8a07a54e8..0000000000
--- a/lib/docbuilder/src/Makefile
+++ /dev/null
@@ -1,121 +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 expressed or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999-2000, Ericsson
-# Utvecklings AB. All Rights Reserved.''
-#
-# $Id$
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(DOCB_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/docbuilder-$(VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-MODULES= \
- docb_edoc_xml_cb \
- docb_gen \
- docb_html \
- docb_html_layout \
- docb_html_ref \
- docb_html_util \
- docb_html_util_iso \
- docb_main \
- docb_pretty_format \
- docb_tr_application2html \
- docb_tr_appref2html \
- docb_tr_chapter2html \
- docb_tr_cite2html \
- docb_tr_comref2html \
- docb_tr_cref2html \
- docb_tr_erlref2html \
- docb_tr_fileref2html \
- docb_tr_first2html \
- docb_tr_index2html \
- docb_tr_part2html \
- docb_tr_refs2kwic \
- docb_tr_report2html \
- docb_tr_term2html \
- docb_transform \
- docb_util \
- docb_xmerl_tree_cb \
- docb_xmerl_xml_cb \
- docb_xml_check
-
-HRL_FILES= \
- docb_util.hrl
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-APP_FILE= docbuilder.app
-APPUP_FILE= docbuilder.appup
-APP_SRC= $(APP_FILE).src
-APPUP_SRC= $(APPUP_FILE).src
-APP_TARGET= $(EBIN)/$(APP_FILE)
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_FLAGS +=
-XMERL = ../../xmerl
-ERL_COMPILE_FLAGS += -I$(XMERL)/include
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-clean:
- rm -f $(TARGET_FILES) $(APP_TARGET)
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
-
-release_docs_spec:
-
-
-
-
-
diff --git a/lib/docbuilder/src/docb_edoc_xml_cb.erl b/lib/docbuilder/src/docb_edoc_xml_cb.erl
deleted file mode 100644
index 90491bc007..0000000000
--- a/lib/docbuilder/src/docb_edoc_xml_cb.erl
+++ /dev/null
@@ -1,1154 +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 expressed or implied. See
-%% the Licence for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson AB.
-%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
-%% All Rights Reserved.��
-%%
-%% $Id$
-%%
--module(docb_edoc_xml_cb).
-
-%% This is the EDoc callback module for creating DocBuilder erlref
-%% documents (man pages) in XML format, and also a DocBuilder chapter
-%% document based on "overview.edoc".
-%%
-%% Usage examples:
-%% docb_gen File
-%% docb_gen -chapter overview.edoc
-%% or (from an Erlang shell)
-%% edoc:file(File, [{layout,docb_edoc_xml_cb},{file_suffix,".xml"},
-%% {preprocess,true}]).
-%%
-%% The origin of this file is the edoc module otpsgml_layout.erl
-%% written by Richard Carlsson.
-
--export([module/2, overview/2]).
-
--include("xmerl.hrl").
-
--define(NL, "\n").
-
-%%-User interface-------------------------------------------------------
-
-%% ERLREF
-module(Element, Opts) ->
- SortP = proplists:get_value(sort_functions, Opts, true),
- XML = layout_module(Element, SortP),
- xmerl:export_simple([XML], docb_xmerl_xml_cb, []).
-
-%% CHAPTER
-overview(Element, _Opts) ->
- XML = layout_chapter(Element),
- xmerl:export_simple([XML], docb_xmerl_xml_cb, []).
-
-%%--Internal functions--------------------------------------------------
-
-layout_module(#xmlElement{name = module, content = Es}=E, SortP) ->
- Name = get_attrval(name, E),
- Desc = get_content(description, Es),
- ShortDesc = text_only(get_content(briefDescription, Desc)),
- FullDesc = otp_xmlify(get_content(fullDescription, Desc)),
- Types0 = get_content(typedecls, Es),
- Types1 = lists:sort([{type_name(Et), Et} || Et <- Types0]),
- Functions =
- case SortP of
- true ->
- lists:sort([{function_name(Ef), Ef} ||
- Ef <- get_content(functions, Es)]);
- false ->
- [{function_name(Ef), Ef} ||
- Ef <- get_content(functions, Es)]
- end,
- Header = {header, [
- ?NL,{title, [Name]},
- ?NL,{prepared, [""]},
- ?NL,{responsible, [""]},
- ?NL,{docno, ["1"]},
- ?NL,{approved, [""]},
- ?NL,{checked, [""]},
- ?NL,{date, [""]},
- ?NL,{rev, ["A"]},
- ?NL,{file, [Name++".xml"]}
- ]},
- Module = {module, [Name]},
- ModuleSummary = {modulesummary, ShortDesc},
- Description = {description, [?NL|FullDesc]},
- Types = case Types1 of
- [] -> [];
- _ ->
- [?NL, {section,[{title,["DATA TYPES"]},
- {marker,[{id,"types"}],[]},
- ?NL|types(Types1)]}]
- end,
- Funcs = functions(Functions),
- See = seealso_module(Es),
- Authors = {authors, authors(Es)},
- {erlref,
- [?NL,Header,
- ?NL,Module,
- ?NL,ModuleSummary,
- ?NL,Description]
- ++ Types ++
- [?NL,Funcs,
- ?NL,See,
- ?NL,Authors]
- }.
-
-layout_chapter(#xmlElement{name=overview, content=Es}) ->
- Title = get_text(title, Es),
- Header = {header, [
- ?NL,{title,[Title]},
- ?NL,{prepared,[""]},
- ?NL,{docno,[""]},
- ?NL,{date,[""]},
- ?NL,{rev,[""]},
- ?NL,{file, ["chapter.xml"]}
- ]},
- DescEs = get_content(description, Es),
- FullDescEs = get_content(fullDescription, DescEs),
- Sections = chapter_ify(FullDescEs, first),
- {chapter, [?NL, Header, ?NL | Sections]}.
-
-chapter_ify([], _) ->
- [];
-chapter_ify(Es, first) ->
- %% Everything up to the first section should be made into
- %% plain paragraphs -- or if no first section is found, everything
- %% should be made into one
- case find_next(h3, Es) of
- {Es, []} ->
- SubSections = subchapter_ify(Es, first),
- [{section, [?NL,{title,["Overview"]},
- ?NL | SubSections]}];
- {FirstEs, RestEs} ->
- otp_xmlify(FirstEs) ++ chapter_ify(RestEs, next)
- end;
-chapter_ify([#xmlElement{name=h3} = E | Es], next) ->
- {SectionEs, RestEs} = find_next(h3, Es),
- SubSections = subchapter_ify(SectionEs, first),
- {Marker, Title} = chapter_title(E),
- [{section, [?NL,{marker,[{id,Marker}],[]},
- ?NL,{title,[Title]},
- ?NL | SubSections]} | chapter_ify(RestEs, next)].
-
-subchapter_ify([], _) ->
- [];
-subchapter_ify(Es, first) ->
- %% Everything up to the (possible) first subsection should be
- %% made into plain paragraphs
- {FirstEs, RestEs} = find_next(h4, Es),
- otp_xmlify(FirstEs) ++ subchapter_ify(RestEs, next);
-subchapter_ify([#xmlElement{name=h4} = E | Es], next) ->
- {SectionEs, RestEs} = find_next(h4, Es),
- Elements = otp_xmlify(SectionEs),
- {Marker, Title} = chapter_title(E),
- [{section, [?NL,{marker,[{id,Marker}],[]},
- ?NL,{title,[Title]},
- ?NL | Elements]} | subchapter_ify(RestEs, next)].
-
-chapter_title(#xmlElement{content=Es}) -> % name = h3 | h4
- case Es of
- [#xmlElement{name=a} = E] ->
- {get_attrval(name, E), get_text(E)}
- end.
-
-%%--XHTML->XML transformation-------------------------------------------
-
-%% otp_xmlify(Es1) -> Es2
-%% Es1 = Es2 = [#xmlElement{} | #xmlText{}]
-%% Fix things that are allowed in XHTML but not in chapter/erlref DTDs.
-%% 1) lists (<ul>, <ol>, <dl>) and code snippets (<pre>) can not occur
-%% within a <p>, such a <p> must be splitted into a sequence of <p>,
-%% <ul>, <ol>, <dl> and <pre>.
-%% 2) <a> must only have either a href attribute (corresponds to a
-%% <seealso> or <url> in the XML code) in which case its content
-%% must be plain text; or a name attribute (<marker>).
-%% 3a) <b> content must be plain text.
-%% b) <em> content must be plain text (or actually a <code> element
-%% as well, but a simplification is used here).
-%% c) <pre> content must be plain text (or could actually contain
-%% <input> as well, but a simplification is used here).
-%% 4) <code> content must be plain text, or the element must be split
-%% into a list of elements.
-%% 5a) <h1>, <h2> etc is not allowed - replaced by its content within
-%% a <b> tag.
-%% b) <center> is not allowed - replaced by its content.
-%% c) <font> -"-
-%% 6) <table> is not allowed in erlref, translated to text instead.
-%% Also a <table> in chapter without a border is translated to text.
-%% A <table> in chapter with a border must contain a <tcaption>.
-%% 7) <sup> is not allowed - is replaced with its text content
-%% within parenthesis.
-%% 8) <blockquote> contents may need to be made into paragraphs
-%% 9) <th> (table header) is not allowed - is replaced by
-%% <td><em>...</em></td>.
-otp_xmlify([]) ->
- [];
-otp_xmlify(Es0) ->
- Es = case is_paragraph(hd(Es0)) of
-
- %% If the first element is a <p> xmlElement, then
- %% the entire element list is ready to be otp_xmlified.
- true ->
- Es0;
-
- %% If the first element is not a <p> xmlElement, then all
- %% elements up to the first <p> (or end of list) must be
- %% made into a paragraph (using the {p, Es} construction)
- %% before the list is otp_xmlified.
- false ->
- case find_next(p, Es0, []) of
- {[#xmlText{value=Str}] = First, Rest} ->
- %% Special case: Making a paragraph out of a
- %% blank line isn't a great idea.
- case is_empty(Str) of
- true ->
- Rest;
- false ->
- [{p,First}|Rest]
- end;
- {First, Rest} ->
- [{p,First}|Rest]
- end
- end,
-
- %% Fix paragraph breaks not needed in XHTML but in XML
- EsFixed = otp_xmlify_fix(Es),
-
- otp_xmlify_es(EsFixed).
-
-%% EDoc does not always translate empty lines (with leading "%%")
-%% as paragraph break, this is the fix
-otp_xmlify_fix(Es) ->
- otp_xmlify_fix(Es, []).
-otp_xmlify_fix([#xmlText{value="\n \n"++_} = E1, E2 | Es], Res) ->
- %% This is how it looks when generating an erlref from a .erl file
- case is_paragraph(E2) of
- false ->
- {P, After} = find_p_ending(Es, []),
- otp_xmlify_fix(After, [{p, [E2|P]}, E1 | Res]);
- true ->
- otp_xmlify_fix([E2|Es], [E1|Res])
- end;
-otp_xmlify_fix([#xmlText{value="\n\n"} = E1, E2 | Es], Res) ->
- %% This is how it looks when generating a chapter from overview.edoc
- case is_paragraph(E2) of
- false ->
- {P, After} = find_p_ending(Es, []),
- otp_xmlify_fix(After, [{p, [E2|P]}, E1 | Res]);
- true ->
- otp_xmlify_fix([E2|Es], [E1|Res])
- end;
-otp_xmlify_fix([E|Es], Res) ->
- otp_xmlify_fix(Es, [E|Res]);
-otp_xmlify_fix([], Res) ->
- lists:reverse(Res).
-
-otp_xmlify_es([E | Es]) ->
- case is_paragraph(E) of
- true ->
- case otp_xmlify_psplit(E) of
-
- %% paragraph contained inline tags and text only
- nosplit ->
- otp_xmlify_e(E) ++ otp_xmlify_es(Es);
-
- %% paragraph contained dl, ul and/or pre and has been
- %% splitted
- SubEs ->
- lists:flatmap(fun otp_xmlify_e/1, SubEs) ++
- otp_xmlify_es(Es)
- end;
- false ->
- otp_xmlify_e(E) ++ otp_xmlify_es(Es)
- end;
-otp_xmlify_es([]) ->
- [].
-
-%% otp_xmlify_psplit(P) -> nosplit | [E]
-%% Handles case 1) above.
-%% Uses the {p, Es} construct, thus replaces an p xmlElement with one
-%% or more {p, Es} tuples if splitting the paraghrap is necessary.
-otp_xmlify_psplit(P) ->
- otp_xmlify_psplit(p_content(P), [], []).
-otp_xmlify_psplit([#xmlElement{name=Name}=E | Es], Content, Res) ->
- if
- Name==blockquote; Name==ul; Name==ol; Name==dl; Name==pre;
- Name==table ->
- case Content of
- [] ->
- otp_xmlify_psplit(Es, [], [E|Res]);
- [#xmlText{value=Str}] ->
- %% Special case: Making a paragraph out of a blank
- %% line isn't a great idea. Instead, this can be
- %% viewed as the case above, where there is no
- %% content to make a paragraph out of
- case is_empty(Str) of
- true ->
- otp_xmlify_psplit(Es, [], [E|Res]);
- false ->
- Pnew = {p, lists:reverse(Content)},
- otp_xmlify_psplit(Es, [], [E,Pnew|Res])
- end;
- _ ->
- Pnew = {p, lists:reverse(Content)},
- otp_xmlify_psplit(Es, [], [E,Pnew|Res])
- end;
-
- true ->
- otp_xmlify_psplit(Es, [E|Content], Res)
- end;
-otp_xmlify_psplit([E | Es], Content, Res) ->
- otp_xmlify_psplit(Es, [E|Content], Res);
-otp_xmlify_psplit([], _Content, []) ->
- nosplit;
-otp_xmlify_psplit([], [], Res) ->
- lists:reverse(Res);
-otp_xmlify_psplit([], [#xmlText{value="\n\n"}], Res) ->
- lists:reverse(Res);
-otp_xmlify_psplit([], Content, Res) ->
- Pnew = {p, lists:reverse(Content)},
- lists:reverse([Pnew|Res]).
-
-%% otp_xmlify_e(E) -> [E]
-%% This is the function which does the actual transformation of
-%% single elements, normally by making sure the content corresponds
-%% to what is allowed by the OTP DTDs.
-%% Returns a list of elements as the xmlification in some cases
-%% returns no element or more than one element (although in most cases
-%% exactly one element).
-otp_xmlify_e(#xmlElement{name=a} = E) -> % 2) above
- otp_xmlify_a(E);
-otp_xmlify_e(#xmlElement{name=Tag} = E) % 3a-c)
- when Tag==b; Tag==em; Tag==pre ->
- Content = text_only(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=code} = E) -> % 4)
- case catch text_only(E#xmlElement.content) of
- {'EXIT', _Error} ->
- otp_xmlify_code(E);
- Content ->
- [E#xmlElement{content=Content}]
- end;
-otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a
- when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 ->
- Content = text_only(E#xmlElement.content),
- [E#xmlElement{name=b, content=Content}];
-otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c)
- when Tag==center;
- Tag==font ->
- otp_xmlify_e(E#xmlElement.content);
-otp_xmlify_e(#xmlElement{name=table} = E) -> % 6)
- case parent(E) of
- module ->
- otp_xmlify_table(E#xmlElement.content);
- overview ->
- Content0 = otp_xmlify_e(E#xmlElement.content),
- Summary = #xmlText{value=get_attrval(summary, E)},
- TCaption = E#xmlElement{name=tcaption,
- attributes=[],
- content=[Summary]},
- Content = Content0 ++ [TCaption],
- [E#xmlElement{attributes=[], content=Content}]
- end;
-otp_xmlify_e(#xmlElement{name=tbody} = E) ->
- otp_xmlify_e(E#xmlElement.content);
-otp_xmlify_e(#xmlElement{name=sup} = E) -> % 7)
- Text = get_text(E),
- [#xmlText{parents = E#xmlElement.parents,
- pos = E#xmlElement.pos,
- language = E#xmlElement.language,
- value = "(" ++ Text ++ ")"}];
-otp_xmlify_e(#xmlElement{name=blockquote} = E) -> % 8)
- Content = otp_xmlify_blockquote(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=th} = E) -> % 9)
- Content = otp_xmlify_e(E#xmlElement.content),
- EmE = E#xmlElement{name=em, content=Content},
- [E#xmlElement{name=td, content=[EmE]}];
-otp_xmlify_e(#xmlElement{name=p} = E) -> % recurse
- Content = otp_xmlify_e(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e({p, Content1}) ->
- Content2 = otp_xmlify_e(Content1),
- [{p, Content2}];
-otp_xmlify_e(#xmlElement{name=ul} = E) ->
- Content = otp_xmlify_e(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=li} = E) ->
- %% Content may need to be made into <p>s etc.
- Content = otp_xmlify(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=dl} = E) ->
- Content0 = otp_xmlify_e(E#xmlElement.content),
- Content = otp_xmlify_dl(Content0),
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=dt} = E) ->
- %% Special fix: Markers in <taglist> <tag>s are not allowed,
- %% save it using 'put' and place the marker first in the <item>
- %% instead
- Content = case E#xmlElement.content of
- [#xmlElement{name=a} = A] ->
- put(dt_marker, otp_xmlify_e(A)),
- otp_xmlify_e(A#xmlElement.content);
- _ ->
- otp_xmlify_e(E#xmlElement.content)
- end,
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=dd} = E) ->
- %% Content may need to be made into <p>s etc.
- Content0 = otp_xmlify(E#xmlElement.content),
- Content = case get(dt_marker) of
- undefined -> Content0;
- [Marker] ->
- put(dt_marker, undefined),
- [Marker#xmlElement{content=[]}|Content0]
- end,
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=tr} = E) ->
- Content = otp_xmlify_e(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e(#xmlElement{name=td} = E) ->
- Content = otp_xmlify_e(E#xmlElement.content),
- [E#xmlElement{content=Content}];
-otp_xmlify_e([E | Es]) ->
- otp_xmlify_e(E) ++ otp_xmlify_e(Es);
-otp_xmlify_e([]) ->
- [];
-otp_xmlify_e(E) ->
- [E].
-
-%%--Tags with special handling------------------------------------------
-
-%% otp_xmlify_a(A1) -> [A2]
-%% Takes an <a> element and filters the attributes to decide wheather
-%% its a seealso/url or a marker.
-%% In the case of a seealso/url, the href part is checked, making
-%% sure a .xml/.html file extension is removed (as DocBuilder inserts
-%% .html extension when resolving cross references).
-%% Also, references to other applications //App has a href attribute
-%% value "OTPROOT/..." (due to app_default being set to "OTPROOT" in
-%% docb_gen.erl), in this case both href attribute and content must be
-%% formatted correctly according to DocBuilder requirements.
-otp_xmlify_a(A) ->
- [Attr0] = filter_a_attrs(A#xmlElement.attributes),
- case Attr0 of
- #xmlAttribute{name=href, value=Href0} -> % seealso | url
- Content0 = text_only(A#xmlElement.content),
- {Href, Content} = otp_xmlify_a_href(Href0, Content0),
- [A#xmlElement{attributes=[Attr0#xmlAttribute{value=Href}],
- content=Content}];
- #xmlAttribute{name=name} -> % marker
- Content = otp_xmlify_e(A#xmlElement.content),
- [A#xmlElement{attributes=[Attr0], content=Content}]
- end.
-
-%% filter_a_attrs(Attrs) -> [Attr]
-%% Removes all attributes from a <a> element except the href or
-%% name attribute.
-filter_a_attrs([#xmlAttribute{name=href} = Attr | _Attrs]) ->
- [Attr];
-filter_a_attrs([#xmlAttribute{name=name} = Attr | _Attrs]) ->
- [Attr];
-filter_a_attrs([_Attr|Attrs]) ->
- filter_a_attrs(Attrs);
-filter_a_attrs([]) ->
- [].
-
-%% otp_xmlify_a_href(Href0, Es0) -> {Href1, Es1}
-%% Href = string()
-otp_xmlify_a_href("#"++_ = Marker, Es0) -> % <seealso marker="#what">
- {Marker, Es0};
-otp_xmlify_a_href("http:"++_ = URL, Es0) -> % external URL
- {URL, Es0};
-otp_xmlify_a_href("OTPROOT"++AppRef, Es0) -> % <.. marker="App:FileRef
- [AppS, "doc", FileRef1] = split(AppRef, "/"),
- FileRef = AppS++":"++otp_xmlify_a_fileref(FileRef1, AppS),
- [#xmlText{value=Str0} = T] = Es0,
- Str = case split(Str0, "/") of
- %% //Application
- [AppS2] ->
- %% AppS2 can differ from AppS
- %% Example: xmerl/XMerL
- AppS2;
- [_AppS,ModRef] ->
- case split(ModRef, ":") of
- %% //Application/Module
- [Module] ->
- Module++"(3)";
- %% //Application/Module:Type()
- [_Module,_Type] ->
- ModRef
- end;
- %% //Application/Module:Function/Arity
- [_AppS,ModFunc,Arity] ->
- ModFunc++"/"++Arity
- end,
- {FileRef, [T#xmlText{value=Str}]};
-otp_xmlify_a_href("../"++File, Es0) ->
- %% Special case: This kind of relative path is used on some
- %% places within i.e. EDoc and refers to a file within the same
- %% application tree.
- %% Correct the path according to the OTP directory structure
- {"../../"++File, Es0};
-otp_xmlify_a_href(FileRef1, Es0) -> % File within the same application
- FileRef2 = otp_xmlify_a_fileref(FileRef1, this),
- {FileRef2, Es0}.
-
-%% otp_xmlify_a_fileref(FileRef1, AppS|this) -> FileRef2
-%% AppS = FileRef = string()
-otp_xmlify_a_fileref(FileRef1, AppS) ->
- case split(FileRef1, ".#") of
-
- %% EDoc default name is "overview-summary.html,
- %% name of OTP User's Guide chapter is "chapter.xml"
- ["overview-summary", _Ext] ->
- "chapter";
- ["overview-summary", _Ext, Marker] ->
- "chapter#"++Marker;
-
- [File, Ext] when Ext=="xml";
- Ext=="html", AppS/=this ->
- File;
- [File, Ext, Marker0] ->
- %% Here is an awkward solution to an awkward problem
- %% The marker automatically inserted by DocBuilder at
- %% each function does not seem to work for EDoc generated
- %% ERLREFs.
- %% So if the referenced marker is in an ERLREF generated
- %% by EDoc, keep it "as is", ie "function-arity".
- %% If the referenced marker is NOT in an ERLREF generated
- %% by EDoc, the marker should be on the format
- %% "function/arity".
- %% The awkward part of the solution is to decide wheather
- %% the ERLREF is generated by EDoc or not: Here we make
- %% the decision based on which application the module
- %% belongs to -- which is ok when the module was written
- %% but probably not in the future...
- EDocApps = ["edoc","hipe","syntax_tools","xmerl"],
- IsEDocGenerated = lists:member(AppS, EDocApps),
- Marker = if
- %% The marker is in a file in *this*
- %% application (which documentation obviously
- %% is generated by EDoc), or it is in a file
- %% in an application which documentation
- %% is assumed to be generated by EDoc
- AppS==this; IsEDocGenerated ->
- Marker0;
-
- %% The marker is in a file in an application
- %% which documentation is assumed NOT to be
- %% generated by EDoc
- true ->
- case split(Marker0, "-") of
- [Func,Arity] ->
- Func++"/"++Arity;
- _ ->
- Marker0
- end
- end,
- if
- %% Ignore file extension in file reference if it either
- %% is ".xml" or if it is ".html" but AppS/=this, that
- %% is, we're resolving an OTPROOT file reference
- Ext=="xml";
- Ext=="html", AppS/=this ->
- File++"#"++Marker;
- true ->
- File++"."++Ext++"#"++Marker
- end;
-
- %% References to other files than XML files are kept as-is
- _ ->
- FileRef1
- end.
-
-%% otp_xmlify_blockquote(Es1) -> Es2
-%% Ensures that the content of a <blockquote> is divided into
-%% <p>s using the {p, Es} construct.
-otp_xmlify_blockquote([#xmlElement{name=p} = E|Es]) ->
- [E | otp_xmlify_blockquote(Es)];
-otp_xmlify_blockquote([#xmlText{} = E|Es]) ->
- {P, After} = find_p_ending(Es, []),
- [{p, [E|P]} | otp_xmlify_blockquote(After)];
-otp_xmlify_blockquote([]) ->
- [].
-
-%% otp_xmlify_code(E) -> Es
-%% Takes a <code> xmlElement and split it into a list of <code> and
-%% other xmlElements. Necessary when it contains more than a single
-%% xmlText element.
-%% Example:
-%% #xmlElement{name=code,
-%% content=[#xmlText{}, #xmlElement{name=br}, #xmlText{}]}
-%% =>
-%% [#xmlElement{name=code, content=[#xmlText{}]},
-%% #xmlElement{name=br},
-%% #xmlElement{name=code, content=[#xmlText{}]}]
-otp_xmlify_code(E) ->
- otp_xmlify_code(E, E#xmlElement.content, []).
-otp_xmlify_code(Code, [#xmlText{} = E|Es], Acc) ->
- otp_xmlify_code(Code, Es, [Code#xmlElement{content=[E]}|Acc]);
-otp_xmlify_code(Code, [#xmlElement{} = E|Es], Acc) ->
- otp_xmlify_code(Code, Es, [E|Acc]);
-otp_xmlify_code(_Code, [], Acc) ->
- lists:reverse(Acc).
-
-%% otp_xmlify_dl(Es1) -> Es2
-%% Insert empty <dd> elements if necessary.
-%% OTP DTDs does not allow <taglist>s with <tag>s but no <item>s.
-otp_xmlify_dl([#xmlElement{name=dt} = E|Es]) ->
- [E|otp_xmlify_dl(Es, E)];
-otp_xmlify_dl([E|Es]) ->
- [E|otp_xmlify_dl(Es)];
-otp_xmlify_dl([]) ->
- [].
-
-otp_xmlify_dl([#xmlElement{name=dd} = E|Es], _DT) ->
- [E|otp_xmlify_dl(Es)];
-otp_xmlify_dl([#xmlElement{name=dt} = E|Es], DT) ->
- DD = DT#xmlElement{name=dd, attributes=[], content=[]},
- [DD,E|otp_xmlify_dl(Es, E)];
-otp_xmlify_dl([E|Es], DT) ->
- [E|otp_xmlify_dl(Es, DT)];
-otp_xmlify_dl([], DT) ->
- DD = DT#xmlElement{name=dd, attributes=[], content=[]},
- [DD].
-
-%% otp_xmlify_table(Es1) -> Es2
-%% Transform <table> contents into "text", that is, inline elements.
-otp_xmlify_table([#xmlText{} = E|Es]) ->
- [E | otp_xmlify_table(Es)];
-otp_xmlify_table([#xmlElement{name=tbody} = E|Es]) ->
- otp_xmlify_table(E#xmlElement.content)++otp_xmlify_table(Es);
-otp_xmlify_table([#xmlElement{name=tr, content=Content}|Es]) ->
- %% Insert newlines between table rows
- otp_xmlify_table(Content)++[{br,[]}]++otp_xmlify_table(Es);
-otp_xmlify_table([#xmlElement{name=th, content=Content}|Es]) ->
- [{em, Content} | otp_xmlify_table(Es)];
-otp_xmlify_table([#xmlElement{name=td, content=Content}|Es]) ->
- otp_xmlify_e(Content) ++ otp_xmlify_table(Es);
-otp_xmlify_table([]) ->
- [].
-
-%%--Misc help functions used by otp_xmlify/1 et al---------------------
-
-%% find_next(Tag, Es) -> {Es1, Es2}
-%% Returns {Es1, Es2} where Es1 is the list of all elements up to (but
-%% not including) the first element with tag Tag in Es, and Es2
-%% is the remaining elements of Es.
-find_next(Tag, Es) ->
- find_next(Tag, Es, []).
-find_next(Tag, [#xmlElement{name=Tag} = E | Es], AccEs) ->
- {lists:reverse(AccEs), [E|Es]};
-find_next(Tag, [E|Es], AccEs) ->
- find_next(Tag, Es, [E|AccEs]);
-find_next(_Tag, [], AccEs) ->
- {lists:reverse(AccEs), []}.
-
-%% find_p_ending(Es, []) -> {Es1, Es2}
-%% Returns {Es1, Es2} where Es1 is the list of all elements up to (but
-%% not including) the first paragraph break in Es, and Es2 is
-%% the remaining elements of Es2.
-%% Paragraph break = <p> tag or empty line
-%% the next blank line, <p> or end-of-list as P, and the remaining
-%% elements of Es as After.
-find_p_ending([#xmlText{value="\n \n"++_} = E|Es], P) ->
- {lists:reverse(P), [E|Es]};
-find_p_ending([#xmlElement{name=p} = E|Es], P) ->
- {lists:reverse(P), [E|Es]};
-find_p_ending([E|Es], P) ->
- find_p_ending(Es, [E|P]);
-find_p_ending([], P) ->
- {lists:reverse(P), []}.
-
-%% is_paragraph(E | P) -> bool()
-%% P = {p, Es}
-is_paragraph(#xmlElement{name=p}) -> true;
-is_paragraph({p, _Es}) -> true;
-is_paragraph(_E) -> false.
-
-%% p_content(E | P) -> Es
-p_content(#xmlElement{content=Content}) -> Content;
-p_content({p, Content}) -> Content.
-
-%% is_empty(Str) -> bool()
-%% Str = string()
-%% Returns true if Str is empty in the sense that it contains nothing
-%% but spaces, tabs or newlines.
-is_empty("\n"++Str) ->
- is_empty(Str);
-is_empty(" "++Str) ->
- is_empty(Str);
-is_empty("\t"++Str) ->
- is_empty(Str);
-is_empty("") ->
- true;
-is_empty(_) ->
- false.
-
-%% split(Str, Seps) -> [Str]
-split(Str, Seps) ->
- split(Str, Seps, []).
-
-split([Ch|Str], Seps, Acc) ->
- case lists:member(Ch, Seps) of
- true -> split(Str, Seps, Acc);
- false -> split(Str, Seps, Acc, [Ch])
- end;
-split([], _Seps, Acc) ->
- lists:reverse(Acc).
-
-split([Ch|Str], Seps, Acc, Chs) ->
- case lists:member(Ch, Seps) of
- true -> split(Str, Seps, [lists:reverse(Chs)|Acc]);
- false -> split(Str, Seps, Acc, [Ch|Chs])
- end;
-split([], _Seps, Acc, Chs) ->
- lists:reverse([lists:reverse(Chs)|Acc]).
-
-%%--Functions for creating an erlref document---------------------------
-
-%% function_name(F) -> string()
-%% F = #xmlElement{name=function}
-%% Returns the name of a function as "name/arity".
-function_name(E) ->
- get_attrval(name, E) ++ "/" ++ get_attrval(arity, E).
-
-%% functions(Fs) -> Es
-%% Fs = [{Name, F}]
-%% Name = string() "name/arity"
-%% F = #xmlElement{name=function}
-functions(Fs) ->
- Es = lists:flatmap(fun ({Name, E}) -> function(Name, E) end, Fs),
- if
- Es==[] ->
- [];
- true ->
- {funcs, Es}
- end.
-
-function(_Name, E=#xmlElement{content = Es}) ->
- TypeSpec = get_content(typespec, Es),
- [?NL,{func, [ ?NL,
- {name,
- case funcheader(TypeSpec) of
- [] ->
- signature(get_content(args, Es),
- get_attrval(name, E));
- Spec -> Spec
- end
- },
- ?NL,{fsummary, fsummary(Es)},
- ?NL,local_types(TypeSpec),
- ?NL,{desc,
- label_anchor(E)++
- deprecated(Es)++
- fulldesc(Es)++
- seealso_function(Es)}
- ]}].
-
-fsummary([]) -> ["\s"];
-fsummary(Es) ->
- Desc = get_content(description, Es),
- case get_content(briefDescription, Desc) of
- [] ->
- fsummary_equiv(Es); % no description at all if no equiv
- ShortDesc ->
- text_only(ShortDesc)
- end.
-
-fsummary_equiv(Es) ->
- case get_content(equiv, Es) of
- [] -> ["\s"];
- Es1 ->
- case get_content(expr, Es1) of
- [] -> ["\s"];
- [Expr] ->
- ["Equivalent to ", Expr, ".",?NL]
- end
- end.
-
-label_anchor(E) ->
- case get_attrval(label, E) of
- "" -> [];
- Ref -> [{marker, [{id, Ref}],[]},?NL]
- end.
-
-label_anchor(Content, E) ->
- case get_attrval(label, E) of
- "" -> Content;
- Ref -> {p,[{marker, [{id, Ref}],[]},
- {em, Content}]}
- end.
-
-signature(Es, Name) ->
- [Name, "("] ++ seq(fun arg/1, Es) ++ [") -> term()", ?NL].
-
-arg(#xmlElement{content = Es}) ->
- [get_text(argName, Es)].
-
-funcheader([]) -> [];
-funcheader(Es) ->
- [t_name(get_elem(erlangName, Es))] ++ t_utype(get_elem(type, Es)).
-
-local_types([]) -> [];
-local_types(Es) ->
- local_defs2(get_elem(localdef, Es)).
-
-local_defs2([]) -> [];
-local_defs2(Es) ->
- {type,[?NL | [{v, localdef2(E)} || E <- Es]]}.
-
-%% Like localdef/1, but does not use label_anchor/2 -- we don't want any
-%% markers or em tags in <v> tag, plain text only!
-localdef2(#xmlElement{content = Es}) ->
- case get_elem(typevar, Es) of
- [] ->
- t_utype(get_elem(type, Es));
- [V] ->
- t_var(V) ++ [" = "] ++ t_utype(get_elem(type, Es))
- end.
-
-type_name(#xmlElement{content = Es}) ->
- t_name(get_elem(erlangName, get_content(typedef, Es))).
-
-types(Ts) ->
- Es = lists:flatmap(fun ({Name, E}) -> typedecl(Name, E) end, Ts),
- [?NL, {taglist,[?NL|Es]}].
-
-typedecl(Name, #xmlElement{content = Es}) ->
- TypedefEs = get_content(typedef, Es),
- Id = "type-"++Name,
- [{tag, typedef(TypedefEs)},
- ?NL,
- {item, [{marker,[{id,Id}],[]} |
- local_defs(get_elem(localdef, TypedefEs)) ++ fulldesc(Es)]},
- ?NL].
-
-typedef(Es) ->
- Name = ([t_name(get_elem(erlangName, Es)), "("]
- ++ seq(fun t_utype_elem/1, get_content(argtypes, Es), [")"])),
- case get_elem(type, Es) of
- [] ->
- [{tt, Name}];
- Type ->
- [{tt, Name ++ [" = "] ++ t_utype(Type)}]
- end.
-
-local_defs([]) -> [];
-local_defs(Es) ->
- [?NL, {ul, [{li, [{tt, localdef(E)}]} || E <- Es]}].
-
-localdef(E = #xmlElement{content = Es}) ->
- Var = case get_elem(typevar, Es) of
- [] ->
- [label_anchor(t_abstype(get_content(abstype, Es)), E)];
- [V] ->
- t_var(V)
- end,
- Var ++ [" = "] ++ t_utype(get_elem(type, Es)).
-
-deprecated(Es) ->
- case get_content(deprecated, Es) of
- [] -> [];
- DeprEs ->
- Es2 = get_content(fullDescription,
- get_content(description, DeprEs)),
- Es3 = otp_xmlify_e(Es2),
- [{p, [{em, ["This function is deprecated: "]} |Es3]}, ?NL]
- end.
-
-fulldesc(Es) ->
- case get_content(fullDescription, get_content(description, Es)) of
- [] ->
- index_desc(Es);
- Desc ->
- [?NL|otp_xmlify(Desc)] ++ [?NL]
- end.
-
-index_desc(Es) ->
- Desc = get_content(description, Es),
- case get_content(briefDescription, Desc) of
- [] ->
- equiv(Es); % no description at all if no equiv
- ShortDesc ->
- ShortDesc
- end.
-
-seealso_module(Es) ->
- case get_elem(see, Es) of
- [] -> [];
- Es1 ->
- {section,[{title,["See also"]},{p,seq(fun see/1, Es1, [])}]}
- end.
-seealso_function(Es) ->
- case get_elem(see, Es) of
- [] -> [];
- Es1 ->
- [{p, [{em, ["See also:"]}, " "] ++ seq(fun see/1, Es1, ["."])},
- ?NL]
- end.
-
-%% ELEMENT see PCDATA
-%% ATTLIST name PCDATA
-%% href PCDATA
-see(#xmlElement{content=Es0} = E) ->
- Href0 = get_attrval(href, E),
- {Href, Es} = otp_xmlify_a_href(Href0, Es0),
- [{seealso, [{marker, Href}], Es}].
-
-equiv(Es) ->
- case get_content(equiv, Es) of
- [] -> ["\s"];
- Es1 ->
- case get_content(expr, Es1) of
- [] -> [];
- [Expr] ->
- Expr1 = [Expr],
- Expr2 = case get_elem(see, Es1) of
- [] ->
- {c,Expr1};
- [E=#xmlElement{}] ->
- case get_attrval(href, E) of
- "" ->
- {c,Expr1};
- Ref ->
- {seealso, [{marker, Ref}], Expr1}
- end
- end,
- [{p, ["Equivalent to ", Expr2, "."]}, ?NL]
- end
- end.
-
-authors(Es) ->
- case get_elem(author, Es) of
- [] ->
- [?NL,{aname,["\s"]},?NL,{email,["\s"]}];
- Es1 ->
- [?NL|seq(fun author/1, Es1, "", [])]
- end.
-
-author(E=#xmlElement{}) ->
- Name = case get_attrval(name, E) of
- [] -> "\s";
- N -> N
- end,
- Mail = case get_attrval(email, E) of
- [] -> "\s";
- M -> M
- end,
- [?NL,{aname,[Name]},?NL,{email,[Mail]}].
-
-t_name([E]) ->
- N = get_attrval(name, E),
- case get_attrval(module, E) of
- "" -> N;
- M ->
- S = M ++ ":" ++ N,
- case get_attrval(app, E) of
- "" -> S;
- A -> "//" ++ A ++ "/" ++ S
- end
- end.
-
-t_utype([E]) ->
- t_utype_elem(E).
-
-t_utype_elem(E=#xmlElement{content = Es}) ->
- case get_attrval(name, E) of
- "" -> t_type(Es);
- Name ->
- T = t_type(Es),
- case T of
- [Name] -> T; % avoid generating "Foo::Foo"
- T -> [Name] ++ ["::"] ++ T
- end
- end.
-
-t_type([E=#xmlElement{name = typevar}]) ->
- t_var(E);
-t_type([E=#xmlElement{name = atom}]) ->
- t_atom(E);
-t_type([E=#xmlElement{name = integer}]) ->
- t_integer(E);
-t_type([E=#xmlElement{name = float}]) ->
- t_float(E);
-t_type([#xmlElement{name = nil}]) ->
- t_nil();
-t_type([#xmlElement{name = list, content = Es}]) ->
- t_list(Es);
-t_type([#xmlElement{name = tuple, content = Es}]) ->
- t_tuple(Es);
-t_type([#xmlElement{name = 'fun', content = Es}]) ->
- t_fun(Es);
-t_type([#xmlElement{name = abstype, content = Es}]) ->
- t_abstype(Es);
-t_type([#xmlElement{name = union, content = Es}]) ->
- t_union(Es);
-t_type([#xmlElement{name = record, content = Es}]) ->
- t_record(Es).
-
-t_var(E) ->
- [get_attrval(name, E)].
-
-t_atom(E) ->
- [get_attrval(value, E)].
-
-t_integer(E) ->
- [get_attrval(value, E)].
-
-t_float(E) ->
- [get_attrval(value, E)].
-
-t_nil() ->
- ["[]"].
-
-t_list(Es) ->
- ["["] ++ t_utype(get_elem(type, Es)) ++ ["]"].
-
-t_tuple(Es) ->
- ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]).
-
-t_fun(Es) ->
- ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
- [") -> "] ++ t_utype(get_elem(type, Es))).
-
-t_record([E|Es]) ->
- ["#", get_attrval(value, E), "{"++ seq(fun t_field/1, Es) ++"}"].
-t_field(#xmlElement{name=field, content=[Atom,Type]}) ->
- [get_attrval(value, Atom), "="] ++ t_utype_elem(Type).
-
-t_abstype(Es) ->
- case split_at_colon(t_name(get_elem(erlangName, Es)),[]) of
- {Mod,Type} ->
- [Type, "("] ++
- seq(fun t_utype_elem/1, get_elem(type, Es), [")"]) ++
- [" (see module ", Mod, ")"];
- Type ->
- [Type, "("] ++
- seq(fun t_utype_elem/1, get_elem(type, Es), [")"])
- end.
-
-%% Split at one colon, but not at two (or more)
-split_at_colon([$:,$:|_]=Rest,Acc) ->
- lists:reverse(Acc)++Rest;
-split_at_colon([$:|Type],Acc) ->
- {lists:reverse(Acc),Type};
-split_at_colon([Char|Rest],Acc) ->
- split_at_colon(Rest,[Char|Acc]);
-split_at_colon([],Acc) ->
- lists:reverse(Acc).
-
-t_union(Es) ->
- seq(fun t_utype_elem/1, Es, " | ", []).
-
-%% seq(Fun, Es)
-%% seq(Fun, Es, Tail)
-%% seq(Fun, Es, Sep, Tail) -> [string()]
-%% Fun = function(E) -> [string()]
-%% Sep = string()
-%% Tail = [string()]
-%% Applies Fun to each element E in Es and return the appended list of
-%% strings, separated by Sep which defaults to ", " and ended by Tail
-%% which defaults to [].
-seq(Fun, Es) ->
- seq(Fun, Es, []).
-seq(Fun, Es, Tail) ->
- seq(Fun, Es, ", ", Tail).
-seq(Fun, [E], _Sep, Tail) ->
- Fun(E) ++ Tail;
-seq(Fun, [E | Es], Sep, Tail) ->
- Fun(E) ++ [Sep] ++ seq(Fun, Es, Sep, Tail);
-seq(_Fun, [], _Sep, Tail) ->
- Tail.
-
-%%--Misc functions for accessing fields etc-----------------------------
-
-%% Type definitions used below:
-%% E = #xmlElement{} | #xmlText{}
-%% Es = [E]
-%% Tag = atom(), XHTML tag
-%% Name = atom(), XHTML attribute name
-%% Attrs = [#xmlAttribute{}]
-%% Ts = [#xmlText{}]
-
-%% parent(E) -> module | overview
-parent(E) ->
- Parents = E#xmlElement.parents,
- {Parent,_} = lists:last(Parents),
- Parent.
-
-%% get_elem(Tag, Es1) -> Es2
-%% Returns a list of all elements in Es which have the name Tag.
-get_elem(Name, [#xmlElement{name = Name} = E | Es]) ->
- [E | get_elem(Name, Es)];
-get_elem(Name, [_ | Es]) ->
- get_elem(Name, Es);
-get_elem(_, []) ->
- [].
-
-%% get_attr(Name, Attrs1) -> Attrs2
-%% Returns a list of all attributes in Attrs1 which have the name Name.
-get_attr(Name, [#xmlAttribute{name = Name} = A | As]) ->
- [A | get_attr(Name, As)];
-get_attr(Name, [_ | As]) ->
- get_attr(Name, As);
-get_attr(_, []) ->
- [].
-
-%% get_attrval(Name, E) -> string()
-%% If E has one attribute with name Name, return its value, otherwise ""
-get_attrval(Name, #xmlElement{attributes = As}) ->
- case get_attr(Name, As) of
- [#xmlAttribute{value = V}] ->
- V;
- [] -> ""
- end.
-
-%% get_content(Tag, Es1) -> Es2
-%% If there is one element in Es1 with name Tag, returns its contents,
-%% otherwise []
-get_content(Name, Es) ->
- case get_elem(Name, Es) of
- [#xmlElement{content = Es1}] ->
- Es1;
- [] -> []
- end.
-
-%% get_text(Tag, Es) -> string()
-%% If there is one element in Es with name Tag, and its content is
-%% a single xmlText, return the value of this xmlText.
-%% Otherwise return "".
-get_text(Name, Es) ->
- case get_content(Name, Es) of
- [#xmlText{value = Text}] ->
- Text;
- [] -> ""
- end.
-
-%% get_text(E) -> string()
-%% Return the value of an single xmlText which is the content of E,
-%% possibly recursively.
-get_text(#xmlElement{content=[#xmlText{value=Text}]}) ->
- Text;
-get_text(#xmlElement{content=[E]}) ->
- get_text(E).
-
-%% text_only(Es) -> Ts
-%% Takes a list of xmlElement and xmlText and return a lists of xmlText.
-text_only([#xmlElement{content = Content}|Es]) ->
- text_only(Content) ++ text_only(Es);
-text_only([#xmlText{} = E |Es]) ->
- [E | text_only(Es)];
-text_only([]) ->
- [].
diff --git a/lib/docbuilder/src/docb_gen.erl b/lib/docbuilder/src/docb_gen.erl
deleted file mode 100644
index 75494314f1..0000000000
--- a/lib/docbuilder/src/docb_gen.erl
+++ /dev/null
@@ -1,142 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--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,
- def=[],
- includes=[],
- preprocess=false,
- sort_functions=true}).
-
-%% module(File) -> ok | {error, Reason}
-%% module(File, Opts) -> ok | {error, Reason}
-%% File = string(), file name with or without ".erl" extension
-%% Opts -- see code
-%% Reason = badfile | {badopt, Term}
-module(File0) ->
- module(File0, []).
-module(File0, RawOpts) ->
- File = case filename:extension(File0) of
- ".erl" -> File0;
- _ -> File0++".erl"
- end,
- case filelib:is_regular(File) of
- true ->
- case parse(RawOpts, #args{}) of
- {ok, Args} ->
- Opts = [{def, Args#args.def},
- {includes, Args#args.includes},
- {preprocess, Args#args.preprocess},
- {sort_functions, Args#args.sort_functions},
-
- {app_default, "OTPROOT"},
- {file_suffix, Args#args.suffix},
- {dir, "."},
- {layout, Args#args.layout}],
- edoc:file(File, Opts);
- Error ->
- Error
- end;
- false ->
- {error, badfile}
- end.
-
-%% users_guide(File) -> ok | {error, Reason}
-%% users_guide(File, Opts) -> ok | {error, Reason}
-%% File = string()
-%% Opts -- see code
-%% Reason = badfile | {badopt, Opt}
-users_guide(File) ->
- users_guide(File, []).
-users_guide(File, RawOpts) ->
- case filelib:is_regular(File) of
- true ->
- case parse(RawOpts, #args{}) of
- {ok, Args} ->
- Opts = [{def, Args#args.def},
- {app_default, "OTPROOT"},
- {file_suffix, Args#args.suffix},
- {layout, Args#args.layout}],
-
- Env = edoc_lib:get_doc_env(Opts),
-
- {ok, Tags} =
- edoc_extract:file(File, overview, Env, Opts),
- Data =
- edoc_data:overview("Overview", Tags, Env, Opts),
- F = fun(M) -> M:overview(Data, Opts) end,
- Text = edoc_lib:run_layout(F, Opts),
-
- OutFile = "chapter" ++ Args#args.suffix,
- edoc_lib:write_file(Text, ".", OutFile);
- Error ->
- Error
- end;
- false ->
- {error, badfile}
- end.
-
-parse([{output,xml} | RawOpts], Args) ->
- parse(RawOpts, Args); % default, no update of record necessary
-parse([{output,sgml} | RawOpts], Args) ->
- parse(RawOpts, Args#args{suffix=".sgml", layout=docb_edoc_sgml_cb});
-parse([{def,Defs} | RawOpts], Args) ->
- case parse_defs(Defs) of
- true ->
- Args2 = Args#args{def=Args#args.def++Defs},
- parse(RawOpts, Args2);
- false ->
- {error, {badopt, {def,Defs}}}
- end;
-parse([{includes,Dirs} | RawOpts], Args) ->
- case parse_includes(Dirs) of
- true ->
- Args2 = Args#args{includes=Args#args.includes++Dirs},
- parse(RawOpts, Args2);
- false ->
- {error, {badopt, {includes,Dirs}}}
- end;
-parse([{preprocess,Bool} | RawOpts], Args) when Bool==true;
- Bool==false ->
- parse(RawOpts, Args#args{preprocess=Bool});
-parse([{sort_functions,Bool} | RawOpts], Args) when Bool==true;
- Bool==false ->
- parse(RawOpts, Args#args{sort_functions=Bool});
-parse([], Args) ->
- {ok, Args};
-parse([Opt | _RawOpts], _Args) ->
- {error, {badopt, Opt}}.
-
-parse_defs(Defs) ->
- lists:all(fun({Key,Val}) when is_atom(Key), is_list(Val) -> true;
- (_) -> false
- end,
- Defs).
-
-parse_includes(Dirs) ->
- lists:all(fun(Dir) when is_list(Dir) -> true;
- (_) -> false
- end,
- Dirs).
diff --git a/lib/docbuilder/src/docb_html.erl b/lib/docbuilder/src/docb_html.erl
deleted file mode 100644
index bdfc5ea876..0000000000
--- a/lib/docbuilder/src/docb_html.erl
+++ /dev/null
@@ -1,393 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_html).
-
--export([rule/2, rule/3]).
-
-rule([p, item, list|_], {_, _, _}) ->
- {"", "<br />\n"};
-rule([p, item, taglist|_], {_, _, _}) ->
- {"", "<br />\n"};
-rule([p|_], _) ->
- {"\n<p>", "\n</p>"};
-
-rule([pre|_], _) ->
- {"\n<div class=\"example\"><pre>\n", "\n</pre></div>\n"};
-
-rule([input|_], _) ->
- {"<strong>", "</strong>"};
-
-rule([quote|_], _) ->
- {"\n<blockquote>\n", "\n</blockquote>\n"};
-
-rule([i|_], _) ->
- {"<em>", "</em>"};
-
-rule([b|_], _) ->
- {"<strong>", "</strong>"};
-
-rule([c|_], _) ->
- {"<span class=\"code\">", "</span>"};
-
-rule([em|_], _) ->
- {"<strong>", "</strong>"};
-
-rule([sub|_], _) ->
- {"<sub>", "</sub>"};
-
-rule([sup|_], _) ->
- {"<sup>", "</sup>"};
-
-rule([termdef|_], _) ->
- {drop, ""};
-
-rule([citedef|_], _) ->
- {drop, ""};
-
-rule([br|_], _) ->
- {"<br />\n", ""};
-
-rule([digression|_], _) ->
- {"<table>\n"
- " <tr>\n"
- " <td width=\"23\"></td>\n"
- " <td>\n"
- " <font size=\"-1\">\n",
- " </font>\n"
- " </td>\n"
- " </tr>\n"
- "</table>\n"};
-
-rule([list, item, list|_], {_, ["ORDERED"], _}) ->
- {"\n<ol>\n", "\n</ol>\n"};
-rule([list, item, taglist|_], {_, ["ORDERED"], _}) ->
- {"\n<ol>\n", "\n</ol>\n"};
-rule([list|_], {_, ["ORDERED"], _}) ->
- {"\n<ol>\n", "\n</ol>\n"};
-rule([list, item, list|_], {_, ["BULLETED"], _}) ->
- {"\n<ul>\n", "\n</ul>\n"};
-rule([list, item, taglist|_], {_, ["BULLETED"], _}) ->
- {"\n<ul>\n", "\n</ul>\n"};
-rule([list|_], {_, ["BULLETED"], _}) ->
- {"\n<ul>\n", "\n</ul>\n"};
-
-rule([taglist, item, taglist|_], _) ->
- {"\n<dl>\n", "\n</dl>\n"};
-rule([taglist, item, list|_], _) ->
- {"\n<dl>\n", "\n</dl>\n"};
-rule([taglist|_], _) ->
- {"\n<dl>\n", "\n</dl>\n"};
-
-rule([tag|_], _) ->
- {"\n<dt>\n", "\n</dt>\n"};
-
-rule([item, list|_], _) ->
- {"\n<li>\n", "\n</li>\n\n"};
-rule([item, taglist|_], _) ->
- {"\n<dd>\n", "\n</dd>\n"};
-
-rule([image|_], {_, [File], _}) ->
- File2 =
- case filename:extension(File) of
- [] -> File ++ ".gif";
- _ -> File
- end,
- {["\n<center>\n", "<img alt=\"", File2, "\" src=\"", File2,
- "\"/><br/>\n"],
- "\n</center>\n"};
-
-rule([icaption|_], _) ->
- {"<em>", "</em>\n"};
-
-rule([url|_], {_, [HREF], _}) ->
- URI = docb_html_util:make_uri(HREF),
- {io_lib:format("<a target=\"_top\" href=\"~s\">", [URI]), "</a>"};
-
-rule([marker|_], {_, [ID], _}) ->
- %% remove all chars before first # including the #
- {ok, NewID, _} = regexp:sub(ID, "^[^#]*#", ""),
- %% replace "/" with "-" because "/" xhtml does not
- %% allow "/" in the name attribute of element <a>
- %% so we have to do the same as for marker i.e
- %% Function/Arity is translated to an anchor in xhtml
- %% like this : <a name="Function-Arity"/>
- NewID2 = [case X of $/ -> $-;_->X end||X <- NewID],
- {drop, ["<a name=\"", NewID2, "\"><!-- Empty --></a>"]};
-
-rule([table|_], {_, ["", ""], Ts}) ->
- {newargs,
- "\n<center>\n"
- "<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n",
- reorder_table(Ts),
- "\n</table>\n"
- "</center>\n"};
-rule([table|_], {_, [Width, ""], Ts}) ->
- {newargs,
- ["\n<center>\n"
- "<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\" ",
- "width=\"", Width, "%\">\n"],
- reorder_table(Ts),
- "\n</table>\n"
- "</center>\n"};
-
-%% The clauses above are for the report DTD. This one is for the other
-%% DTDs.
-rule([table|_], {_, ["LEFT"], Ts}) ->
- {newargs,
- "\n"
- "<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n",
- reorder_table(Ts),
- "\n</table>\n"};
-
-rule([table|_], {_, _, Ts}) ->
- {newargs,
- "\n<center>\n"
- "<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n",
- reorder_table(Ts),
- "\n</table>\n"
- "</center>\n"};
-
-rule([row|_], _) ->
- {" <tr>\n", "\n </tr>\n"};
-
-rule([cell|_], {_, ["", ""], _}) ->
- {" <td>\n", "\n </td>\n"};
-rule([cell|_], {_, [Align, ""], _}) ->
- {[" <td align=\"", string:to_lower(Align), "\">\n"], "\n </td>\n"};
-rule([cell|_], {_, ["", VAlign], _}) ->
- {[" <td valign=\"", string:to_lower(VAlign), "\">\n"], "\n </td>\n"};
-rule([cell|_], {_, [Align, VAlign], _}) ->
- {[" <td align=\"", string:to_lower(Align), "\" valign=\"", string:to_lower(VAlign), "\">\n"],
- "\n </td>\n"};
-
-rule([tcaption|_], _) ->
- {" <caption align=\"bottom\"><em>", "</em></caption>\n"};
-
-rule([codeinclude|_], {_, [File, Tag, _Type], _}) ->
-%% Type can be "ERL", "C" or "NONE"
- {ok,Data} = docb_html_util:code_include(File, Tag),
- {drop, ["\n<div class=\"example\"><pre>\n", Data,
- "\n</pre></div>\n"]};
-
-rule([erleval|_], {_, [Expr], _}) ->
- docb_html_util:erl_eval(Expr);
-
-rule([pcdata, pre|_], {_, _, Data}) ->
- %% Do not remove leading spaces.
- {drop, docb_html_util:pcdata_to_html(Data, false)};
-
-rule([pcdata|_], {_, _, Data}) ->
- {drop, docb_html_util:pcdata_to_html(Data)}.
-
-rule([seealso|_], {_, [Marker], _}, Opts) ->
- Href =
- case docb_util:html_snippet(seealso, Marker, Opts) of
- "" ->
- %% DocBuilder default behavior:
- %% Marker is of format "Path#Fragment", both optional.
- %% Translated to <A HREF="Path.html#Fragment">
- case string:chr(Marker, $#) of
- 0 -> % No Fragment
- Marker++".html";
- 1 -> % No Path
- %% replace "/" with "-" because "/" xhtml does not
- %% allow "/" in the name attribute of element <a>
- %% so we have to do the same as for marker i.e
- %% Function/Arity is translated to an anchor in xhtml
- %% like this : <a name="Function-Arity"/>
- [case X of $/ -> $-;_->X end||X <- Marker];
- _ ->
- Marker1 = [case X of $/ -> $-;_->X end||X <- Marker],
- case string:tokens(Marker1, "#") of
- [Path] -> % # at end, remove it
- Path++".html";
- [Path | Frag0] ->
- Path++".html#"++
- docb_util:join(Frag0, "#")
- end
- end;
- Href0 ->
- %% User defined behavior, use result as-is
- Href0
- end,
- {{["<a href=\"", Href, "\">"], "</a>"}, Opts};
-
-rule([warning|_], _, Opts) ->
- docb_html_util:copy_pics("warning.gif", "warning.gif", Opts),
- {{"\n<div class=\"warning\">\n"
- "<div class=\"label\">Warning</div>\n"
- "<div class=\"content\">\n",
- "\n</div>"
- "\n</div>\n"}, Opts};
-
-rule([note|_], _, Opts) ->
- docb_html_util:copy_pics("note.gif", "note.gif", Opts),
- {{"\n<div class=\"note\">\n"
- "<div class=\"label\">Note</div>\n"
- "<div class=\"content\">",
- "\n</div>"
- "\n</div>\n"}, Opts};
-
-rule([path|_], {_, [UNIX, Windows], [{pcdata, _, Text}]}, Opts) ->
- UnixPart =
- docb_util:an_option({ptype,"unix"}, Opts) and (UNIX/=""),
- WinPart =
- docb_util:an_option({ptype,"windows"}, Opts) and (Windows/=""),
- if
- UnixPart, WinPart ->
- {{drop, [docb_html_util:pcdata_to_html(Text),
- " <font size=\"-2\">(<code>UNIX: ",
- docb_html_util:attribute_cdata_to_html(UNIX),
- ", ",
- "Windows: ",
- docb_html_util:attribute_cdata_to_html(Windows),
- "</code>)</font>"]},
- Opts};
- UnixPart ->
- {{drop, [docb_html_util:pcdata_to_html(Text),
- " <font size=\"-1\">(<code>UNIX: ",
- docb_html_util:attribute_cdata_to_html(UNIX),
- "</code>)</font>"]},
- Opts};
- WinPart ->
- {{drop, [docb_html_util:pcdata_to_html(Text),
- " <font size=\"-1\">(<code>Windows: ",
- docb_html_util:attribute_cdata_to_html(Windows),
- "</code>)</font>"]},
- Opts};
- true ->
- {{drop, docb_html_util:pcdata_to_html(Text)}, Opts}
- end;
-
-rule([term|_], {_, [ID], _}, Opts) ->
- case docb_util:an_option(dict, Opts) of
- false ->
- case docb_util:lookup_option({defs, term}, Opts) of
- false ->
- {{drop, ["<em><strong>",
- ID,
- "</strong></em> "]}, Opts};
- TermList ->
- case lists:keyfind(ID, 1, TermList) of
- false ->
- {{drop, ["<em><strong>", ID,
- "</strong></em> "]},
- Opts};
- {ID, Name, _Description, _Resp} ->
- {{drop, ["<em><strong>", Name,
- "</strong></em> "]},
- Opts};
- {ID, Name, _Description} ->
- {{drop, [ "<em><strong>", Name,
- "</strong></em> "]},
- Opts}
- end
- end;
- true ->
- case docb_util:lookup_option({defs, term}, Opts) of
- false ->
- {{drop, ["<em><strong>", ID,
- "</strong></em> "]}, Opts};
- TermList ->
- PartApplication =
- docb_util:lookup_option(part_application, Opts),
- case lists:keyfind(ID, 1, TermList) of
- false ->
- {{drop, ["<a href=\"", PartApplication,
- "_term.html#", ID, "\">", ID,
- "</a> "]}, Opts};
- {ID, Name, _Description, _Resp} ->
- {{drop, ["<a href=\"", PartApplication,
- "_term.html#", ID, "\">", Name,
- "</a> "]}, Opts};
- {ID, Name, _Description} ->
- {{drop, ["<a href=\"", PartApplication,
- "_term.html#", ID, "\">", Name,
- "</a> "]}, Opts}
- end
- end
- end;
-
-rule([cite|_], {_, [ID], _}, Opts) ->
- case docb_util:an_option(dict, Opts) of
- false ->
- case docb_util:lookup_option({defs, cite}, Opts) of
- false ->
- {{drop, ["<em><strong>", ID, "</strong></em> "]},
- Opts};
- CiteList ->
- case lists:keyfind(ID, 1, CiteList) of
- false ->
- {{drop,
- ["<em><strong>", ID, "</strong></em> "]},
- Opts};
- {ID, Name, _Description, _Resp} ->
- {{drop, ["<em><strong>", Name,
- "</strong></em> "]},
- Opts};
- {ID, Name, _Description} ->
- {{drop, ["<em><strong>", Name,
- "</strong></em> "]},
- Opts}
- end
- end;
- true ->
- case docb_util:lookup_option({defs, cite}, Opts) of
- false ->
- {{drop, ["<em><strong>", ID, "</strong></em> "]},
- Opts};
- CiteList ->
- PartApp =
- docb_util:lookup_option(part_application, Opts),
- case lists:keyfind(ID, 1, CiteList) of
- false ->
- {{drop, ["<a href=\"", PartApp,
- "_cite.html#", ID, "\">", ID,
- "</a> "]},
- Opts};
- {ID, Name, _Description, _Resp} ->
- {{drop, ["<a href=\"", PartApp,
- "_cite.html#", ID, "\">", Name,
- "</a> "]},
- Opts};
- {ID, Name, _Description} ->
- {{drop, ["<a href=\"", PartApp,
- "_cite.html#", ID, "\">", Name,
- "</a> "]},
- Opts}
- end
- end
- end;
-
-rule([code|_], {_, [Type], [{pcdata, _, Code}]}, Opts) ->
- case lists:member(Type, ["ERL","C","NONE"]) of
- true ->
- {{drop, ["\n<div class=\"example\"><pre>\n", docb_html_util:element_cdata_to_html(Code),
- "\n</pre></div>\n"]}, Opts};
- false ->
- exit({error,"unknown type of <code>"})
- end.
-
-reorder_table(TableContent) ->
- reorder_table(TableContent, [], []).
-reorder_table([], Caption, NewTableContent) ->
- Caption ++ lists:reverse(NewTableContent);
-reorder_table([{tcaption,_,_} = Caption | TableContent], _, NewTableContent) ->
- reorder_table(TableContent, [Caption], NewTableContent);
-reorder_table([Row | TableContent], Caption, NewTableContent) ->
- reorder_table(TableContent, Caption, [Row | NewTableContent]).
diff --git a/lib/docbuilder/src/docb_html_layout.erl b/lib/docbuilder/src/docb_html_layout.erl
deleted file mode 100644
index dca80ac58e..0000000000
--- a/lib/docbuilder/src/docb_html_layout.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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_html_layout).
-
--export([report_top/2, report_bot/1,
- first_top/2, first_bot/1,
- ref_top/2, ref_bot/1,
- chapter_top/2, chapter_bot/1,
- application_toc_top/3, application_toc_top/4,
- part_toc_top/3, part_toc_top/4, part_toc_bot/0,
- index_top/1, index_bot/0]).
-
-%% Report
-
-report_top(Data, Opts) ->
- [Title, Prepared, _Responsible, DocNo, _Approved, _Checked, _Date,
- Vsn0, _File] = Data,
- html_header(Title, Opts) ++
- docb_util:html_snippet(top, Opts) ++
-"<center>
-<h1>" ++ Title ++ "</h1>
-<big>
- " ++ DocNo ++ version(Opts, Vsn0) ++ "<br />
- " ++ Prepared ++ "<br />
-</big>
-</center>
-".
-
-report_bot(Opts) ->
- docb_util:html_snippet(bottom, Opts) ++
-"</body>
-</html>
-".
-
-%% First
-
-first_top(Data, Opts) ->
- [Title, _Prepared, _Responsible, DocNo, _Approved, _Checked, _Date,
- Vsn0, _File] = Data,
- html_header(Title, Opts) ++
- docb_util:html_snippet(top, Opts) ++
-"<center>
-<h1>" ++ Title ++ "</h1>
-<big>" ++ DocNo ++ version(Opts, Vsn0) ++ "<br />
-</big>
-</center>
-".
-
-first_bot(Opts) ->
- report_bot(Opts).
-
-%% Reference
-
-ref_top(Data, Opts) ->
- [Title, _Prepared, _Responsible, _DocNo, _Approved, _Checked,
- _Date, _Rev, _File] = Data,
- ref_html_header(Title, Opts) ++
-"<!-- refpage -->\n" ++
- docb_util:html_snippet(top, Opts) ++
-"<center>
-<h1>" ++ Title ++ "</h1>
-</center>".
-
-ref_bot(Opts) ->
- docb_util:html_snippet(bottom, Opts) ++
-"</body>
-</html>
-".
-
-%% Chapter
-
-chapter_top(Data, Opts) ->
- [Title, _Prepared, _Responsible, _DocNo, _Approved, _Checked,
- _Date, _Rev, _File] = Data,
- html_header(Title, Opts) ++
- docb_util:html_snippet(top, Opts).
-
-chapter_bot(Opts) ->
- report_bot(Opts).
-
-%% Application ToC
-
-application_toc_top(Data, DocName, Opts) ->
- [Title, _Prepared, _Responsible, DocNo, _Approved, _Checked,
- _Date, Vsn0, _File] = Data,
- html_header(Title, []) ++
-"<center>
-<strong>" ++ Title ++ "</strong>
-<p>
-<small>
- " ++ DocNo ++ version(Opts, Vsn0) ++ "
-</small>
-</p>
-<p>
-<small>
- <a target=\"document\" href=\"" ++ DocName ++ "_cite.html\">Bibliography</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_term.html\">Glossary</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_index.html\">Index</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_first.html\">Cover</a>" ++ top_index(Opts) ++
-"</small>
-</p>
-</center>
-<p>
-<small>
-<strong>Table of Contents</strong>
-</small>
-</p>
-".
-
-application_toc_top(Data, DocName, Opts, HRefTexts) ->
- [Title, _Prepared, _Responsible, DocNo, _Approved, _Checked,
- _Date, Vsn0, _File] = Data,
- html_header(Title, []) ++
-"<center>
-<small>
-" ++
- docb_util:join(
- lists:map(
- fun({HRef, Text}) ->
- "<a target=\"_top\" href=\"" ++ HRef ++ "\">" ++
- Text ++ "</a>"
- end,
- HRefTexts), " | ") ++ top_index(Opts) ++
-"</small>
-<p>
-<strong>" ++ Title ++ "</strong>
-</p>
-<p>
-<small>" ++ DocNo ++ version(Opts, Vsn0) ++ "<br />
-</small>
-</p>
-<p>
-<small>
- <a target=\"document\" href=\"" ++ DocName ++ "_cite.html\">Bibliography</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_term.html\">Glossary</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_index.html\">Index</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_first.html\">Cover</a>
-</small>
-</p>
-</center>
-<p>
-<small>
-<strong>Table of Contents</strong>
-</small>
-</p>
-".
-
-%% Part ToC
-
-part_toc_top(Data, DocName, Opts) ->
- [Title, _Prepared, _Responsible, DocNo, _Approved, _Checked,
- _Date, Vsn0, _File] = Data,
- html_header(Title, []) ++
-"<center>
-<p>
-<strong>" ++ Title ++ "</strong>
-</p>
-<p>
-<small>" ++ DocNo ++ version(Opts, Vsn0) ++ "<br />
-</small>
-</p>
-<p>
-<small>
- <a target=\"document\" href=\"" ++ DocName ++ "_cite.html\">Bibliography</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_term.html\">Glossary</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_first.html\">Cover</a>" ++
- top_index(Opts) ++
-"</small>
-</p>
-</center>
-<p>
-<small>
-<strong>Table of Contents</strong>
-</small>
-</p>
-".
-
-part_toc_top(Data, DocName, Opts, HRefTexts) ->
- [Title, _Prepared, _Responsible, DocNo, _Approved, _Checked,
- _Date, Vsn0, _File] = Data,
- html_header(Title, []) ++
-"<center>
-<p>
-<small>
-" ++
- docb_util:join(
- lists:map(
- fun({HRef, Text}) ->
- "<a target=\"_top\" href=\"" ++ HRef ++ "\">" ++
- Text ++ "</a>"
- end,
- HRefTexts), " | ") ++ top_index(Opts) ++
-"</small>
-</p>
-<p>
-<strong>" ++ Title ++ "</strong>
-</p>
-<p>
-<small>
- " ++ DocNo ++ version(Opts, Vsn0) ++ "<br />
-</small>
-</p>
-<p>
-<small>
- <a target=\"document\" href=\"" ++ DocName ++ "_cite.html\">Bibliography</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_term.html\">Glossary</a> |
- <a target=\"document\" href=\"" ++ DocName ++ "_first.html\">Cover</a>
-</small>
-</p>
-</center>
-<p>
-<small>
-<strong>Table of Contents</strong>
-</small>
-</p>
-".
-
-part_toc_bot() ->
-"</body >
-</html>
-".
-
-%% Index
-
-index_top(_Data) ->
- ref_html_header("INDEX", []) ++
-"<h1>INDEX</h1>
-<p><em>Emphasized</em> index entries refer to <em>modules</em>
-and <code>Courier</code> ditos to <code>functions</code>.\n</p>\n".
-
-index_bot() ->
- part_toc_bot().
-
-%% Internal functions
-
-html_header(Title, Opts) ->
- Vsn = docb_util:version(),
-%%"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
-"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
- \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
-<!-- This document was generated using DocBuilder-" ++ Vsn ++ " -->
-<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
-<head>
- <title>" ++ Title ++ "</title>
- <meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>
- " ++ docb_util:html_snippet(head, Opts) ++ "
- <style type=\"text/css\">
-<!--
- body { font-family: Verdana, Arial, Helvetica, sans-serif }
- span.bold_code { font-family: courier;font-weight: bold}
- span.code { font-family: courier;font-weight: normal}
-
-.note, .warning {
- border: solid black 1px;
- margin: 1em 3em;
-}
-
-.note .label {
- background: #30d42a;
- color: white;
- font-weight: bold;
- padding: 5px 10px;
-}
-.note .content {
- background: #eafeea;
- color: black;
- line-height: 120%;
- font-size: 90%;
- padding: 5px 10px;
-}
-.warning .label {
- background: #C00;
- color: white;
- font-weight: bold;
- padding: 5px 10px;
-}
-.warning .content {
- background: #FFF0F0;
- color: black;
- line-height: 120%;
- font-size: 90%;
- padding: 5px 10px;
-}
-
- .example { background-color:#eeeeff }
- pre { font-family: courier; font-weight: normal }
- .REFBODY { margin-left: 13mm }
- .REFTYPES { margin-left: 8mm }
--->
- </style>
-</head>
-<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" vlink=\"#FF00FF\" alink=\"#FF0000\">
-".
-
-ref_html_header(Title, Opts) ->
- Vsn = docb_util:version(),
-%%"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
-"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
- \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
-<!-- This document was generated using DocBuilder-" ++ Vsn ++ " -->
-<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
-<head>
- <title>" ++ Title ++ "</title>
- <meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>
- " ++ docb_util:html_snippet(head, Opts) ++ "
- <style type=\"text/css\">
-<!--
- body { font-family: Verdana, Arial, Helvetica, sans-serif }
- span.bold_code { font-family: courier;font-weight: bold}
- span.code { font-family: courier;font-weight: normal}
-
-.note, .warning {
- border: solid black 1px;
- margin: 1em 3em;
-}
-
-.note .label {
- background: #30d42a;
- color: white;
- font-weight: bold;
- padding: 5px 10px;
-}
-.note .content {
- background: #eafeea;
- color: black;
- line-height: 120%;
- font-size: 90%;
- padding: 5px 10px;
-}
-.warning .label {
- background: #C00;
- color: white;
- font-weight: bold;
- padding: 5px 10px;
-}
-.warning .content {
- background: #FFF0F0;
- color: black;
- line-height: 120%;
- font-size: 90%;
- padding: 5px 10px;
-}
-
- .example { background-color:#eeeeff }
- pre { font-family: courier; font-weight: normal }
- .REFBODY { margin-left: 13mm }
- .REFTYPES { margin-left: 8mm }
--->
- </style>
-</head>
-<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" vlink=\"#FF00FF\" alink=\"#FF0000\">
-".
-
-version(Opts, Vsn0) ->
- case docb_util:lookup_option(vsn, Opts, Vsn0) of
- "" -> "";
- Vsn -> " Version " ++ Vsn
- end.
-
-top_index(Opts) ->
- case docb_util:lookup_option(top, Opts) of
- false -> "";
- TIFile ->
- " | <a target=\"_top\" href=\"" ++ TIFile ++ "\">Top</a>"
- end.
diff --git a/lib/docbuilder/src/docb_html_ref.erl b/lib/docbuilder/src/docb_html_ref.erl
deleted file mode 100644
index c5c166f1ae..0000000000
--- a/lib/docbuilder/src/docb_html_ref.erl
+++ /dev/null
@@ -1,79 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_html_ref).
-
--export([rule/2, rule/3]).
-
-rule([description|_],_) ->
- {"\n<h3>DESCRIPTION</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([funcs|_],_) ->
- {"\n<h3>EXPORTS</h3>\n",""};
-
-rule([func|_],_) ->
- {"\n<p>",""};
-
-rule([name, func, funcs, RefType|_], {_,_,[{pcdata,[],Name0}]}) ->
- Name1 = docb_html_util:make_anchor_name_short(Name0, RefType),
- {"<a name=\"" ++ Name1 ++ "\"><span class=\"bold_code\">",
- "</span></a><br/>\n"};
-
-rule([fsummary|_],_) ->
- {drop, "\n</p>\n"};
-
-rule([type|_], _) ->
- {"\n<div class=\"REFBODY\"><p>Types:</p>\n <div class=\"REFTYPES\">\n<p>\n",
- "\n </p> </div>\n</div>\n"};
-
-rule([v|_], _) ->
- {"<span class=\"bold_code\">","</span><br/>\n"};
-
-rule([d|_], _) ->
- {"\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([desc|_], _) ->
- {"\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([authors|_], _) ->
- {"\n<h3>AUTHORS</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([aname|_], _) ->
- {"", " - "};
-
-rule([section|_], {1,_,_}) ->
- {"", ""};
-rule([section|_], {_N,_,_}) ->
- {"", "\n</div>\n"};
-
-rule([title|_], _) ->
- {"\n<h3>", "</h3>\n<div class=\"REFBODY\">\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html:rule(TagHistory, TagBody).
-
-rule([email|_], _, Opts) ->
- case docb_util:html_snippet(email, Opts) of
- "" ->
- {{"","<br/>\n"}, Opts};
- Email ->
- {{drop, Email++"<br/>\n"}, Opts}
- end;
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html:rule(TagHistory, TagBody, Opts).
-
diff --git a/lib/docbuilder/src/docb_html_util.erl b/lib/docbuilder/src/docb_html_util.erl
deleted file mode 100644
index 02ce8b52a7..0000000000
--- a/lib/docbuilder/src/docb_html_util.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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_html_util).
-
--export([attribute_cdata_to_html/1,
- element_cdata_to_html/1,
- pcdata_to_html/1, pcdata_to_html/2]).
--export([copy_pics/3]).
--export([extract_header_data/2, all_header_data/1]).
--export([make_uri/1,
- make_anchor_href/1, make_anchor_href_short/3,
- make_anchor_name_short/2,
- make_funcdef_short/2]).
--export([erl_include/2, code_include/2, erl_eval/1]).
--export([number/3, count_sections/1]).
--export([format_toc/1]).
--export([html_latin1_sort_order/1]).
-
-%%--Handle CDATA and PCDATA---------------------------------------------
-
-%% NB: Functions for transforming sgmls/XMerL data output to html.
-%% Do not use these for included text files (cf code_include and
-%% erl_include).
-
-attribute_cdata_to_html(Data) ->
- data2html(Data, false).
-
-element_cdata_to_html(Data) ->
- data2html(Data, false).
-
-pcdata_to_html(Data) ->
- data2html(Data, true).
-
-pcdata_to_html(Data, RmSp) ->
- data2html(Data, RmSp).
-
-%% PCDATA, CDATA: Replace entities, and optionally delete
-%% leading and multiple spaces. CDATA never contains entities to
-%% replace.
-
-%% data2html(Cs, RmSpace)
-data2html([246| Cs], RmSp) ->
- [$&, $#, $2, $4, $6, $;| data2html(Cs, RmSp)];
-data2html([$>| Cs], RmSp) ->
- [$&, $#, $6, $2, $;| data2html(Cs, RmSp)];
-data2html([$<| Cs], RmSp) ->
- [$&, $#, $6, $0, $;| data2html(Cs, RmSp)];
-data2html([$&| Cs], RmSp) ->
- [$&, $#, $3, $8, $;| data2html(Cs, RmSp)];
-data2html([$\"| Cs], RmSp) ->
- [$&, $#, $3, $4, $;| data2html(Cs, RmSp)];
-data2html([$\n| Cs], RmSp) ->
- data2html(Cs, RmSp);
-data2html([$\\, $n| Cs], false) ->
- [$\n| data2html(Cs, false)];
-data2html([$\\, $n| Cs], true) ->
- [$\n| data2html(delete_leading_space(Cs), true)];
-data2html([$ , $ | Cs], true) -> % delete multiple space
- [$ | data2html(delete_leading_space(Cs), true)];
-data2html([$\\, $|| Cs0], RmSp) ->
- {Ent, Cs1} = collect_entity(Cs0),
- [entity_to_html(Ent)| data2html(Cs1, RmSp)];
-data2html([$\\, $0, $1, $2| Cs], RmSp) ->
- data2html(Cs, RmSp);
-data2html([$\\, $\\, $n| Cs], RmSp) ->
- [$\\, $n| data2html(Cs, RmSp)];
-data2html([$\\, O1, O2, O3| Cs], RmSp)
- when O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
- case octal2dec(O1, O2, O3) of
- 173 -> % soft hyphen
- data2html(Cs, RmSp);
- C when C > 31, C < 256 ->
- Ent = io_lib:format("&#~w;", [C]),
- [Ent| data2html(Cs, RmSp)];
- C ->
- [C| data2html(Cs, RmSp)]
- end;
-data2html([$\\, $\\| Cs], RmSp) ->
- [$\\| data2html(Cs, RmSp)];
-data2html([C| Cs], RmSp) ->
- [C| data2html(Cs, RmSp)];
-data2html([], _) ->
- [].
-
-delete_leading_space([$ | Cs]) ->
- delete_leading_space(Cs);
-delete_leading_space(Cs) ->
- Cs.
-
-collect_entity(Data) ->
- collect_entity(Data, []).
-
-collect_entity([$\\, $|| Cs], Rs) ->
- {lists:reverse(Rs), Cs};
-collect_entity([C| Cs], Rs) ->
- collect_entity(Cs, [C| Rs]);
-collect_entity([], Rs) ->
- {[], lists:reverse(Rs)}.
-
-entity_to_html("&") -> "&#38;";
-entity_to_html("\"") -> "&#34;";
-entity_to_html("<") -> "&#60;";
-entity_to_html(">") -> "&#62;";
-entity_to_html([$\\, O1, O2, O3])
- when O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
- case octal2dec(O1, O2, O3) of
- 173 -> % soft hyphen
- "";
- Value ->
- io_lib:format("&#~w;", [Value])
- end;
-entity_to_html(Other) ->
- docb_html_util_iso:entity_to_html(Other).
-
-octal2dec(O1, O2, O3) ->
- (O1*8+O2)*8+O3-73*$0.
-
-%%--Copy images---------------------------------------------------------
-
-copy_pics(Src, Dest, Opts) ->
- Dir = code:lib_dir(docbuilder),
- InFile = filename:join([Dir, "etc", Src]),
- OutFile = docb_util:outfile(Dest, "", Opts),
- case filelib:last_modified(OutFile) of
- 0 -> % File doesn't exist
- file:copy(InFile, OutFile);
-
- OutMod2 ->
- InMod1s = calendar:datetime_to_gregorian_seconds(
- filelib:last_modified(InFile)),
- OutMod2s = calendar:datetime_to_gregorian_seconds(OutMod2),
- if
- InMod1s > OutMod2s -> % InFile is newer than OutFile
- file:copy(InFile, OutFile);
- true ->
- ok
- end
- end.
-
-%%--Resolve header data-------------------------------------------------
-
-extract_header_data(Key, {header, [], List}) ->
- case lists:keyfind(Key, 1, List) of
- {Key, [], []} ->
- "";
- {Key, [], [{pcdata, [], Value}]} ->
- pcdata_to_html(Value);
- false ->
- ""
- end.
-
-all_header_data(Header) ->
- all_header_data(Header,
- [title, prepared, responsible, docno, approved,
- checked, date, rev, file]).
-
-all_header_data(_Header, []) ->
- [];
-all_header_data(Header, [Key| Rest]) ->
- [extract_header_data(Key, Header) | all_header_data(Header, Rest)].
-
-%%--Resolve hypertext references----------------------------------------
-
-%% URI regular expression (RFC 2396):
-%% "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"
-%% We split it in five parts:
-%% scheme: "^(([^:/?#]+):)?" (includes trailing `:')
-%% authority: "^(//([^/?#]*))?" (includes leading `//')
-%% path: "^([^?#]*)"
-%% query: "^(\\?([^#]*))?" (includes leading `?')
-%% fragment: "^(#(.*))?" (includes leading `#')
-
-make_uri(Cs) ->
- lists:flatmap(
- fun({path, S}) ->
- case regexp:match(S, "\.xml?\$") of
- {match, _, _} ->
- {ok, NS, _} = regexp:sub(S, "\.xml?\$", ".html"),
- NS;
- _ ->
- S
- end;
- ({_, S}) ->
- S
- end,
- split_uri(Cs)).
-
-split_uri(URI) ->
- split_uri(URI, [{scheme, "^(([^:/?#]+):)?"},
- {authority, "^(//([^/?#]*))?"},
- {path, "^([^?#]*)"},
- {'query', "^(\\?([^#]*))?"},
- {fragment, "^(#(.*))?"}]).
-
-split_uri("", [{Tag, _R}| T]) ->
- [{Tag, ""}| split_uri("", T)];
-split_uri(Cs0, [{Tag, R}| T]) ->
- {match, 1, N} = regexp:match(Cs0, R),
- Cs1 = string:substr(Cs0, 1, N),
- Cs2 = strip_and_escape_uri_component(Tag, Cs1),
- [{Tag, Cs2}| split_uri(string:substr(Cs0, N+1), T)];
-split_uri(_, []) ->
- [].
-
-strip_and_escape_uri_component(authority, "//" ++ Cs) ->
- "//" ++ escape_uri(string:strip(Cs));
-strip_and_escape_uri_component(path, Cs) ->
- escape_uri(string:strip(Cs));
-strip_and_escape_uri_component('query', "?" ++ Cs) ->
- "?" ++ escape_uri(string:strip(Cs));
-strip_and_escape_uri_component(fragment, "#" ++ Cs) ->
- "#" ++ escape_uri(string:strip(Cs));
-strip_and_escape_uri_component(_, "") ->
- "";
-strip_and_escape_uri_component(_, Cs) ->
- escape_uri(string:strip(Cs)).
-
-escape_uri([C|Cs]) when C =< 32;
- C == $<; C == $<; C == $#; C == $%; C == $";
- C == $?;
- C == ${; C == $}; C ==$|; C == $\\; C == $^;
- C == $[; C == $]; C ==$';
- C >= 127 ->
- [$%, mk_hex(C div 16), mk_hex(C rem 16)| escape_uri(Cs)];
-escape_uri([C|Cs]) ->
- [C|escape_uri(Cs)];
-escape_uri([]) ->
- [].
-
-mk_hex(C) when C<10 ->
- C + $0;
-mk_hex(C) ->
- C - 10 + $a.
-
-make_anchor_href(HRef) ->
- case regexp:split(HRef, "#") of
- {ok, [HRef]} ->
- %% No `#' in HRef, i.e. only path
- make_anchor_href(HRef, "");
- {ok, [Path, Fragment]} ->
- make_anchor_href(Path, Fragment)
- end.
-
-make_anchor_href(Path0, Frag0) ->
- Frag1 = string:strip(Frag0),
- Path1 = case Path0 of
- "" ->
- "";
- _ ->
- case regexp:match(Path0, "\.xml?\$") of
- nomatch ->
- Path0 ++ ".html";
- _ ->
- {ok, NewPath, _} = regexp:sub(Path0,
- "\.xml?\$",
- ".html"),
- NewPath
- end
- end,
- case Frag1 of
- "" ->
- attribute_cdata_to_html(Path1);
- _ ->
- attribute_cdata_to_html(Path1) ++
- "#" ++
- attribute_cdata_to_html([case Ch of $/ -> $-; _ -> Ch end||
- Ch <-Frag1])
- end.
-
-make_anchor_href_short(Path, Frag, RefType) ->
- ShortFrag = make_funcdef_short(Frag, RefType,"-"),
- make_anchor_href(Path, ShortFrag).
-
-make_anchor_name_short(FuncName0, RefType) ->
- FuncName1 = make_funcdef_short(FuncName0, RefType,"-"),
- attribute_cdata_to_html(FuncName1).
-
-make_funcdef_short(FuncDef0, RefType) ->
- make_funcdef_short(FuncDef0, RefType, "/").
-
-make_funcdef_short(FuncDef0, RefType,Delimiter) ->
- FuncDef1 = docb_util:trim(FuncDef0),
- Any0 = case lists:member(RefType, [cref, erlref]) of
- true ->
- case catch docb_util:fknidx(FuncDef1, Delimiter) of
- {'EXIT', _} ->
- false;
- Any1 ->
- Any1
- end;
- false ->
- false
- end,
- case Any0 of
- false ->
- case string:tokens(FuncDef1, " ") of
- [Any2| _] ->
- Any2;
- _ ->
- FuncDef1
- end;
- _ ->
- Any0
- end.
-
-%%--Include tags--------------------------------------------------------
-
-%% Only used in report DTD
-erl_include(File, Tag) ->
- case docb_main:include_file(File, Tag) of
- {ok, Cs} ->
- {drop, "\n<pre>\n" ++ text_to_html(Cs) ++ "\n</pre>\n"};
- error ->
- {drop, ""}
- end.
-
-code_include(File, Tag) ->
- case docb_main:include(File, Tag, Tag) of
- {ok, Cs} ->
- {ok,text_to_html(Cs)};
- error ->
- {error, {codeinclude,File}}
- end.
-
-erl_eval(Expr) ->
- Cs = docb_main:eval_str(Expr),
- {drop, "\n<pre>\n" ++ text_to_html(Cs) ++ "\n</pre>\n"}.
-
-%% Only replaces certain characters. Spaces and new lines etc are kept.
-%% Used for plain text (e.g. inclusions of code).
-text_to_html([$>| Cs]) ->
- [$&, $#, $6, $2, $;| text_to_html(Cs)];
-text_to_html([$<| Cs]) ->
- [$&, $#, $6, $0, $;| text_to_html(Cs)];
-text_to_html([$&| Cs]) ->
- [$&, $#, $3, $8, $;| text_to_html(Cs)];
-text_to_html([$\"| Cs]) ->
- [$&, $#, $3, $4, $;| text_to_html(Cs)];
-text_to_html([C| Cs]) ->
- [C| text_to_html(Cs)];
-text_to_html([]) ->
- [].
-
-%%--Number sections-----------------------------------------------------
-
-number({Tag, Attrs, More}, none, File) ->
- {Tag, Attrs, do_number(More, [1], File)};
-number({Tag, Attrs, More}, Prefix, File) ->
- {Tag, Attrs, do_number(More, [list_to_integer(Prefix)], File)}.
-
-do_number([], _, _) ->
- [];
-do_number([{header, Attrs, More}| Rest], NN, File) ->
- [{header, Attrs, More}| do_number(Rest, NN, File)];
-do_number([{section, Attrs, More}| Rest], [N| NN], File) ->
- [{section, Attrs, do_number(More, [1, N| NN], File)}|
- do_number(Rest, [N+1| NN], File)];
-do_number([{title, _, [{pcdata, _, Title}]}| More], [N| NN], File) ->
- Format = make_format(length(NN)),
- Number = lists:flatten(io_lib:format(Format, lists:reverse(NN))),
- [{marker, [{"ID", "CDATA", Number}], []},
- {title, [{"NUMBER", "CDATA", Number},
- {"FILE", "CDATA", File}],
- [{pcdata, [], Title}]}| do_number(More, [N| NN], File)];
-do_number([{pcdata, Attrs, More}| Rest], NN, File) ->
- [{pcdata, Attrs, More}| do_number(Rest, NN, File)];
-do_number([{Tag, Attrs, More}| Rest], NN, File) ->
- [{Tag, Attrs, do_number(More, NN, File)}|do_number(Rest, NN, File)].
-
-make_format(1) ->
- "~w";
-make_format(N) ->
- "~w." ++ make_format(N-1).
-
-count_sections([section| Rest]) ->
- 1 + count_sections(Rest);
-count_sections([_| Rest]) ->
- count_sections(Rest);
-count_sections([]) ->
- 0.
-
-%%--Make a ToC----------------------------------------------------------
-
-format_toc(Toc) ->
- [format_toc1(T) || T <- Toc].
-
-format_toc1({Number, Title}) ->
- [Number, " <a href = \"#", Number, "\">", Title, "</a><br/>\n"].
-
-%%--Convert HTML ISO Latin 1 characters to ordinary characters----------
-
-%% To be used for sorting. Cs must be flat.
-html_latin1_sort_order(Cs) ->
- hlso(Cs).
-
-hlso([]) ->
- [];
-hlso([$&, $#, C2, C1, C0, $;| Cs])
- when $0 =< C2, C2 =< $9, $0 =< C1, C1 =< $9, $0 =< C0, C0 =< $9 ->
- C = ((C2-$0)*10 + (C1-$0))*10 + C0-$0,
- hlso0(C, Cs);
-hlso([$&, $#, C1, C0, $;| Cs])
- when $0 =< C1, C1 =< $9, $0 =< C0, C0 =< $9 ->
- C = (C1-$0)*10 + C0-$0,
- hlso0(C, Cs);
-hlso([C| Cs]) ->
- [C| hlso(Cs)].
-
-hlso0(C, Cs) when 0 =< C, C =< 159 ->
- [C| hlso(Cs)];
-hlso0(160, Cs) -> %% no-break space
- hlso(Cs); % Remove it.
-hlso0(161, Cs) -> %% inverted exclamation mark
- [$? |hlso(Cs)];
-hlso0(162, Cs) -> %% cent sign
- [$$|hlso(Cs)];
-hlso0(163, Cs) -> %% pound sterling sign
- [$$|hlso(Cs)];
-hlso0(164, Cs) -> %% general currency sign
- [$$|hlso(Cs)];
-hlso0(165, Cs) -> %% yen sign
- [$$|hlso(Cs)];
-hlso0(166, Cs) -> %% broken (vertical) bar
- [$| |hlso(Cs)];
-hlso0(167, Cs) -> %% section sign
- [$$|hlso(Cs)];
-hlso0(168, Cs) -> %% umlaut (dieresis)
- [$: |hlso(Cs)];
-hlso0(169, Cs) -> %% copyright sign
- [$c |hlso(Cs)];
-hlso0(170, Cs) -> %% ordinal indicator, feminine
- [$f |hlso(Cs)];
-hlso0(171, Cs) -> %% angle quotation mark, left
- [$" |hlso(Cs)];
-hlso0(172, Cs) -> %% not sign
- [$- |hlso(Cs)];
-hlso0(173, Cs) -> %% soft hyphen
- [$- |hlso(Cs)];
-hlso0(174, Cs) -> %% registered sign
- [$r |hlso(Cs)];
-hlso0(175, Cs) -> %% macron
- [$- |hlso(Cs)];
-hlso0(176, Cs) -> %% degree sign
- [$d |hlso(Cs)];
-hlso0(177, Cs) -> %% plus-or-minus sign
- [$+ |hlso(Cs)];
-hlso0(178, Cs) -> %% superscript two
- [$2 |hlso(Cs)];
-hlso0(179, Cs) -> %% superscript three
- [$3 |hlso(Cs)];
-hlso0(180, Cs) -> %% acute accent
- [$' |hlso(Cs)];
-hlso0(181, Cs) -> %% micro sign
- [$' |hlso(Cs)];
-hlso0(182, Cs) -> %% pilcrow (paragraph sign)
- [$$|hlso(Cs)];
-hlso0(183, Cs) -> %% middle dot
- [$. |hlso(Cs)];
-hlso0(184, Cs) -> %% cedilla
- [$c |hlso(Cs)];
-hlso0(185, Cs) -> %% superscript one
- [$1 |hlso(Cs)];
-hlso0(186, Cs) -> %% ordinal indicator, masculine
- [$m |hlso(Cs)];
-hlso0(187, Cs) -> %% angle quotation mark, right
- [$" |hlso(Cs)];
-hlso0(188, Cs) -> %% fraction one-quarter
- [$4 |hlso(Cs)];
-hlso0(189, Cs) -> %% fraction one-half
- [$2 |hlso(Cs)];
-hlso0(190, Cs) -> %% fraction three-quarters
- [$3 |hlso(Cs)];
-hlso0(191, Cs) -> %% inverted question mark
- [$? |hlso(Cs)];
-
-hlso0(C, Cs) when 192 =< C, C =< 198 -> %% capital A
- [$A |hlso(Cs)];
-hlso0(199, Cs) -> %% capital C, cedilla
- [$C |hlso(Cs)];
-hlso0(C, Cs) when 200 =< C, C =< 203 -> %% capital E
- [$E |hlso(Cs)];
-hlso0(C, Cs) when 204 =< C, C =< 207 -> %% capital I
- [$I |hlso(Cs)];
-hlso0(208, Cs) -> %% capital Eth, Icelandic
- [$D |hlso(Cs)];
-hlso0(209, Cs) -> %% capital N, tilde
- [$N |hlso(Cs)];
-hlso0(C, Cs) when 210 =< C, C =< 214 -> %% capital O
- [$O |hlso(Cs)];
-hlso0(215, Cs) -> %% multiply sign
- [$x |hlso(Cs)];
-hlso0(216, Cs) -> %% capital O, slash
- [$O |hlso(Cs)];
-hlso0(C, Cs) when 217 =< C, C =< 220 -> %% capital U
- [$U |hlso(Cs)];
-hlso0(221, Cs) -> %% capital Y, acute accent
- [$Y |hlso(Cs)];
-hlso0(222, Cs) -> %% capital THORN, Icelandic
- [$T |hlso(Cs)];
-hlso0(223, Cs) -> %% small sharp s, German (sz
- [$s |hlso(Cs)];
-hlso0(C, Cs) when 224 =< C, C =< 230-> %% small a
- [$a |hlso(Cs)];
-hlso0(231, Cs) -> %% small c, cedilla
- [$c |hlso(Cs)];
-hlso0(C, Cs) when 232 =< C, C =< 235 -> %% small e
- [$e |hlso(Cs)];
-hlso0(C, Cs) when 236 =< C, C =< 239 -> %% small i
- [$i |hlso(Cs)];
-hlso0(240, Cs) -> %% small eth, Icelandic
- [$d |hlso(Cs)];
-hlso0(241, Cs) -> %% small n, tilde
- [$n |hlso(Cs)];
-hlso0(C, Cs) when 242 =< C, C =< 246 -> %% small o
- [$o |hlso(Cs)];
-hlso0(247, Cs) -> %% divide sign
- [$/ |hlso(Cs)];
-hlso0(248, Cs) -> %% small o, slash
- [$o |hlso(Cs)];
-hlso0(C, Cs) when 249 =< C, C =< 252 -> %% small u
- [$u |hlso(Cs)];
-hlso0(253, Cs) -> %% small y, acute accent
- [$y |hlso(Cs)];
-hlso0(254, Cs) -> %% small thorn, Icelandic
- [$t |hlso(Cs)];
-hlso0(255, Cs) -> %% small y, dieresis or umlaut
- [$y |hlso(Cs)].
diff --git a/lib/docbuilder/src/docb_html_util_iso.erl b/lib/docbuilder/src/docb_html_util_iso.erl
deleted file mode 100644
index c836805cd2..0000000000
--- a/lib/docbuilder/src/docb_html_util_iso.erl
+++ /dev/null
@@ -1,204 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_html_util_iso).
--export([entity_to_html/1]).
-
-%% Encodes ISOtech, ISOnum and ISOgrk3.
-%%
-%% All entities are of the form "[abcdef]".
-%%
-entity_to_html(Entity) when is_list(Entity), hd(Entity) =/= $[ ->
- Entity;
-entity_to_html(Entity) ->
- case (catch enc(Entity)) of
- {'EXIT', _} ->
- Entity;
- Enc ->
- "<font face=symbol>" ++ Enc ++ "</font>"
- end.
-
-enc("[Delta ]") -> "&#68;";
-%% enc("[Dot ]") -> "&#0;";
-%% enc("[DotDot]") -> "&#0;";
-enc("[Gamma ]") -> "&#71;";
-enc("[Lambda]") -> "&#76;";
-enc("[Omega ]") -> "&#87;";
-enc("[Phi ]") -> "&#70;";
-enc("[Pi ]") -> "&#80;";
-enc("[Prime ]") -> "&#178;";
-enc("[Psi ]") -> "&#89;";
-enc("[Sigma ]") -> "&#83;";
-enc("[Theta ]") -> "&#81;";
-enc("[Upsi ]") -> "&#161;";
-%% enc("[Verbar]") -> "&#0;";
-enc("[Xi ]") -> "&#88;";
-
-enc("[aleph ]") -> "&#192;";
-enc("[alpha ]") -> "&#97;";
-enc("[amp ]") -> "&#38;";
-enc("[and ]") -> "&#217;";
-enc("[ang ]") -> "&#208;";
-%% enc("[ang90 ]") -> "&#0;";
-%% enc("[angsph]") -> "&#0;";
-%% enc("[angst ]") -> "&#0;";
-enc("[ap ]") -> "&#187;";
-
-%% enc("[becaus]") -> "&#0;";
-%% enc("[bernou]") -> "&#0;";
-enc("[bepsi ]") -> "&#39;";
-enc("[beta ]") -> "&#98;";
-enc("[bottom]") -> "&#94;";
-enc("[bull ]") -> "&#183;";
-
-enc("[cap ]") -> "&#199;";
-enc("[chi ]") -> "&#99;";
-enc("[clubs ]") -> "&#167;";
-%% enc("[compfn]") -> "&#0;";
-enc("[cong ]") -> "&#64;";
-enc("[copy ]") -> "&#211;";
-%% enc("[conint]") -> "&#0;";
-enc("[cup ]") -> "&#200;";
-
-enc("[dArr ]") -> "&#223;";
-enc("[darr ]") -> "&#175;";
-enc("[deg ]") -> "&#176;";
-enc("[delta ]") -> "&#100;";
-enc("[diam ]") -> "&#224;";
-enc("[diams ]") -> "&#168;";
-enc("[divide]") -> "&#184;";
-
-enc("[empty ]") -> "&#198;";
-%% enc("[epsi ]") -> "&#0;";
-%% enc("[epsis ]") -> "&#0;";
-enc("[epsiv ]") -> "&#101;";
-enc("[equiv ]") -> "&#186;";
-enc("[eta ]") -> "&#104;";
-enc("[exist ]") -> "&#36;";
-
-enc("[fnof ]") -> "&#166;";
-enc("[forall]") -> "&#34;";
-
-enc("[gamma ]") -> "&#103;";
-%% enc("[gammad]") -> "&#0;";
-enc("[ge ]") -> "&#179;";
-enc("[gt ]") -> "&#62;";
-
-%% enc("[hamilt]") -> "&#0;";
-enc("[hArr ]") -> "&#219;";
-enc("[harr ]") -> "&#171;";
-enc("[hearts]") -> "&#169;";
-enc("[horbar]") -> "&#190;";
-
-enc("[iff ]") -> "&#219;";
-enc("[image ]") -> "&#193;";
-enc("[infin ]") -> "&#165;";
-enc("[int ]") -> "&#242;";
-enc("[iota ]") -> "&#105;";
-enc("[isin ]") -> "&#206;";
-
-enc("[kappa ]") -> "&#107;";
-%%enc("[kappav]") -> "&#0;";
-
-enc("[lArr ]") -> "&#220;";
-%% enc("[lagran]") -> "&#0;";
-enc("[lambda]") -> "&#108;";
-enc("[lang ]") -> "&#225;";
-enc("[larr ]") -> "&#172;";
-enc("[le ]") -> "&#163;";
-%% enc("[lowast]") -> "&#0;";
-enc("[lowbar]") -> "&#95;";
-enc("[lt ]") -> "&#60;";
-
-enc("[middot]") -> "&#215;";
-enc("[minus ]") -> "&#45;";
-%% enc("[mnplus]") -> "&#0;";
-enc("[mu ]") -> "&#109;";
-
-enc("[nabla ]") -> "&#209;";
-enc("[ne ]") -> "&#185;";
-enc("[ni ]") -> "&#39;";
-enc("[nsub ]") -> "&#203;";
-enc("[not ]") -> "&#216;";
-enc("[notin ]") -> "&#207;";
-enc("[nu ]") -> "&#110;";
-
-enc("[omega ]") -> "&#119;";
-enc("[or ]") -> "&#218;";
-%% enc("[order ]") -> "&#0;";
-enc("[oplus ]") -> "&#197;";
-enc("[otimes]") -> "&#196;";
-
-%% enc("[par ]") -> "&#0;";
-enc("[part ]") -> "&#182;";
-%% enc("[permil]") -> "&#0;";
-enc("[perp ]") -> "&#94;"; % bottom
-enc("[phis ]") -> "&#102;";
-enc("[phiv ]") -> "&#106;";
-%% enc("[phmmat]") -> "&#0;";
-enc("[pi ]") -> "&#112;";
-enc("[piv ]") -> "&#118;";
-enc("[plus ]") -> "&#43;";
-enc("[plusmn]") -> "&#177;";
-enc("[prime ]") -> "&#162;";
-enc("[prod ]") -> "&#213;";
-enc("[prop ]") -> "&#181;";
-enc("[psi ]") -> "&#121;";
-
-enc("[radic ]") -> "&#214;";
-enc("[rang ]") -> "&#241;";
-enc("[rArr ]") -> "&#222;";
-enc("[rarr ]") -> "&#174;";
-enc("[real ]") -> "&#194;";
-enc("[reg ]") -> "&#210;";
-enc("[rho ]") -> "&#114;";
-%% enc("[rhov ]") -> "&#0;";
-
-enc("[sigma ]") -> "&#115;";
-enc("[sigmav]") -> "&#86;";
-enc("[sim ]") -> "&#126;";
-%% enc("[sime ]") -> "&#0;";
-%% enc("[square]") -> "&#0;";
-enc("[sol ]") -> "&#164;";
-enc("[spades]") -> "&#170;";
-enc("[sub ]") -> "&#204;";
-enc("[sube ]") -> "&#205;";
-enc("[sup ]") -> "&#201;";
-enc("[supe ]") -> "&#202;";
-enc("[sum ]") -> "&#229;";
-
-enc("[tau ]") -> "&#116;";
-enc("[tdot ]") -> "&#188;";
-enc("[there4]") -> "&#92;";
-enc("[thetas]") -> "&#113;";
-enc("[thetav]") -> "&#74;";
-enc("[times ]") -> "&#180;";
-%% enc("[tprime]") -> "&#0;";
-enc("[trade ]") -> "&#212;";
-
-enc("[uArr ]") -> "&#221;";
-enc("[uarr ]") -> "&#173;";
-enc("[upsi ]") -> "&#117;";
-
-enc("[verbar]") -> "&#189;";
-
-%% enc("[wedgeq]") -> "&#0;";
-enc("[weierp]") -> "&#195;";
-
-enc("[xi ]") -> "&#120;";
-
-enc("[zeta ]") -> "&#122;".
diff --git a/lib/docbuilder/src/docb_main.erl b/lib/docbuilder/src/docb_main.erl
deleted file mode 100644
index c20cfc8e67..0000000000
--- a/lib/docbuilder/src/docb_main.erl
+++ /dev/null
@@ -1,657 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_main).
-
--export([process/2,
- parse/2, parse1/2,
- pp/2,
- insert_after/3,
- transform/5, pp/5,
- include_file/2, include/3,
- eval_str/1,
- validate_html/1
- ]).
--export([do_parse_sgmls/1]).
-
-%%----------------------------------------------------------------------
-
-%% process(File, Opts) -> errors | ok
-%% Parses the source file File and transforms the result to html,
-%% latex and/or man page format.
-process(File, Opts) ->
-
- SrcType = docb_util:lookup_option(src_type, Opts),
-
- File1 =
- case SrcType of
- ".xml" ->
- FileTmp = File ++ ".tmpconv",
- os:cmd("sed -e 's/xi:include[ \t]*href/include file/g' -e 's/xmlns:xi=\"http:\\/\\/www.w3.org\\/2001\\/XInclude\"//g' < " ++
- File ++ ".xml > " ++ FileTmp ++ ".xml"),
- FileTmp;
- ".sgml" ->
- File
- end,
-
- case parse1(File1, Opts) of
- errors ->
- delete_tmp_file(SrcType, File1),
- errors;
- {ok, Tree} ->
- From = element(1, Tree),
- Tos0 =
- lists:foldl(
- fun(latex, Acc) -> [latex|Acc];
- (html, Acc) -> [html|Acc];
- ({man, _Section}, Acc) -> [man|Acc];
- (_, Acc) -> Acc
- end, [], Opts),
-
- %% If no target format is specified, assume HTML:
- Tos = if
- Tos0 =:= [] -> [html];
- true -> Tos0
- end,
-
- Result = [transform(From, To, Opts, File, Tree)||To <- Tos],
- case lists:member(transformation_error,Result) of
- true ->
- delete_tmp_file(SrcType, File1),
- errors;
- _ ->
- delete_tmp_file(SrcType, File1),
- ok
- end
-
- end.
-
-
-delete_tmp_file(".xml", File) ->
- file:delete(File ++ ".xml");
-delete_tmp_file(_, _) ->
- ok.
-
-%%----------------------------------------------------------------------
-
-%% parse(File, Opts) -> {ok, Tree} | errors
-%% Parses the source file File, resulting in a tree structure.
-parse(File, Opts) ->
- case docb_util:lookup_option(src_type, Opts) of
- ".xml" ->
- parse_xml(File++".xml", Opts);
- ".sgml" ->
- parse_sgml(File, Opts)
- end.
-
-%% parse1(File, Opts) -> {ok, Tree} | errors
-%% Like parse/2, but in the SGML case also prints the parse errors
-%% (in File.html.sgmls_errs) information to stdout.
-parse1(File, Opts) ->
- parse(File, [{print_parse_errs, true}|Opts]).
-
-
-validate_html(InFile) ->
- ScanOpts = [{validation,true}, {fetch_fun, fun fetch_dtd/2}],
- case xmerl_scan:file(InFile, ScanOpts) of
- {_XMLTuple,[]} -> % ok
- {InFile,ok};
- {'EXIT',Reason} ->
- {InFile,Reason}
- end.
-
-fetch_dtd({public,_,"http://www.w3.org/TR/xhtml1/DTD/"++ Rest},GlobalState) ->
- Filename = filename:join(docb_util:dtd_dir(),Rest),
- {ok,{file,Filename},GlobalState};
-fetch_dtd({public,_,Str},GlobalState) ->
- {ok,{file,filename:join(docb_util:dtd_dir(),Str)},GlobalState}.
-
-
-
-parse_xml(InFile, Opts) ->
- DtdDir = docb_util:dtd_dir(),
- ScanOpts = [{validation,true}, {fetch_path, [DtdDir]}],
- PrintP = docb_util:lookup_option(print_parse_errs, Opts),
- case catch xmerl_scan:file(InFile, ScanOpts) of
- {'EXIT', Error} when PrintP ->
- docb_util:message(error,
- "XML validation error:~n~p", [Error]),
- errors;
- {'EXIT', _Error} ->
- errors;
- {error, Reason} -> % probably file error
- docb_util:message(error, "XML scan error: ~p", [Reason]),
- errors;
- {Doc, []} ->
- case catch xmerl:export([Doc], docb_xmerl_tree_cb) of
- [Tree] ->
- verify(Tree),
- {ok, Tree};
- {'EXIT', Error} ->
- docb_util:message(error,
- "XML export error:~n~p", [Error]),
- errors
- end
- end.
-
-parse_sgml(InFile, Opts) ->
-
- Pfx = tmp_file_prefix(InFile, Opts),
- OutFile = Pfx ++ "sgmls_output",
- ErrFile = Pfx ++ "sgmls_errs",
-
- EntVals = lists:usort(docb_util:lookup_options(ent, Opts)),
- Ents = lists:flatten([" -ent " ++ Val || Val <- EntVals]),
- Cmd = docb_util:old_docb_dir() ++ "/bin/docb_sgmls_run " ++
- Ents ++ " " ++ InFile ++ ".sgml " ++ OutFile ++ " " ++ ErrFile,
-
- case os:cmd(Cmd) of
- [] ->
- PrintP = docb_util:lookup_option(print_parse_errs, Opts),
- case filelib:file_size(ErrFile) of
- 0 -> % implies no errors
- parse_sgmls(InFile, OutFile);
- _ when PrintP ->
- cat(ErrFile),
- errors;
- _ ->
- errors
- end;
- Msg ->
- docb_util:message(error, "~p", [Msg]),
- errors
- end.
-
-tmp_file_prefix(File, Opts) ->
- lists:concat(
- [File, "." | lists:foldl(
- fun(latex, Acc) -> ["latex."|Acc];
- (html, Acc) -> ["html."|Acc];
- ({man, Section}, Acc) -> ["man", Section, "."|Acc];
- (_, Acc) -> Acc
- end, [], Opts)]).
-
-parse_sgmls(InFile, SgmlsFile) ->
- case file:open(SgmlsFile, [read]) of
- {ok, Fd} ->
- Res = case (catch do_parse_sgmls(Fd)) of
- {ok, Tree} ->
- {ok, Tree};
- {'EXIT', Reason} ->
- docb_util:message(
- error,
- "Cannot parse sgmls output file "
- "~s, obtained from parsing ~s, "
- "reason: ~w",
- [SgmlsFile, InFile, Reason]),
- errors;
- {error, Reason} ->
- docb_util:message(
- error,
- "Cannot parse sgmls output file "
- "~s, obtained from parsing ~s, "
- "reason: ~w",
- [SgmlsFile, InFile, Reason]),
- errors
- end,
- file:close(Fd),
- case Res of
- {ok, Tree0} ->
- verify(Tree0),
- {ok, Tree0};
- _Other ->
- errors
- end;
- {error, Reason} ->
- docb_util:message(error,
- "Cannot open sgmls output file ~s, "
- "obtained from parsing ~s, reason: ~w",
- [SgmlsFile, InFile, Reason]),
- errors
- end.
-
-do_parse_sgmls(Fd) ->
- do_parse_sgmls(Fd, []).
-
-do_parse_sgmls(Fd, Attrs) ->
- case get_line(Fd) of
- {attrs, A} ->
- do_parse_sgmls(Fd, [A|Attrs]);
- {startTag, Tag} ->
- {ok, {Tag, Attrs, get_args(Fd)}};
- Other ->
- {error, Other}
- end.
-
-get_args(Fd) ->
- case get_line(Fd) of
- {startTag, Tag} ->
- H = {Tag, [], get_args(Fd)},
- [H|get_args(Fd)];
- {dataTag, Str} ->
- [{pcdata, [], Str}|get_args(Fd)];
- {attrs, A} ->
- get_args_attr(Fd, [A]);
- close ->
- [];
- ok ->
- []
- end.
-
-get_args_attr(Fd, Attrs) ->
- case get_line(Fd) of
- {startTag, Tag} ->
- H = {Tag, lists:reverse(Attrs), get_args(Fd)},
- [H|get_args(Fd)];
- {dataTag, Str} ->
- [{pcdata, lists:reverse(Attrs), Str}|get_args(Fd)];
- {attrs, A} ->
- get_args_attr(Fd, [A|Attrs]);
- close ->
- [];
- ok ->
- []
- end.
-
-get_line(Fd) ->
- Str = io:get_line(Fd, ''),
- case Str of
- [$(|T] ->
- {startTag, tag_name(T)};
- [$-|T] ->
- {dataTag, T};
- [$)|_T] ->
- close;
- [$A|T] ->
- {attrs, attrs(remove_nl(T))};
- [$?|_T] ->
- get_line(Fd);
- [$C|_] ->
- ok
- end.
-
-remove_nl([$\n|_]) -> [];
-remove_nl([H|T]) -> [H|remove_nl(T)];
-remove_nl([]) -> [].
-
-%% attrs
-%% splits a string like
-%% AAAAA BBBBB ......
-%% into {"AAA", "BBB", Rest}
-
-attrs(T) ->
- {X, T1} = get_item(T),
- {Y, T2} = get_item(T1),
- T3 = skip_blanks(T2),
- {X, Y, T3}.
-
-get_item(T) -> get_item(skip_blanks(T), []).
-
-get_item([$ |T], L) -> {lists:reverse(L), [$ |T]};
-get_item([H|T], L) -> get_item(T, [H|L]);
-get_item([], L) -> {lists:reverse(L), []}.
-
-skip_blanks([$ |T]) -> skip_blanks(T);
-skip_blanks(T) -> T.
-
-tag_name(Str) -> tag_name(Str, []).
-
-tag_name([H|T], L) when $A =< H, H =< $Z ->
- tag_name(T, [H-$A+$a|L]);
-tag_name([$\n], L) ->
- list_to_atom(lists:reverse(L));
-tag_name([H|T], L) ->
- tag_name(T, [H|L]).
-
-cat(File) ->
- case file:open(File, [read]) of
- {ok, Fd} ->
- cat1(Fd),
- file:close(Fd);
- Other ->
- Other
- end.
-
-cat1(Fd) ->
- case io:get_line(Fd, '') of
- eof ->
- eof;
- Str ->
- io:format("~s", [Str]),
- cat1(Fd)
- end.
-
-%%----------------------------------------------------------------------
-
-verify(Tree) -> verify(Tree, [], 1).
-
-verify({pcdata, Optional, _}, Path, Level) ->
- verify_optional(Optional, Path, Level);
-verify({Tag, Optional, Args}, Path, Level) when is_list(Args) ->
- verify_optional(Optional, Path, Level)
- andalso verify_list(Args, [Tag|Path], Level);
-verify(Other, Path, Level) ->
- verify_error(Other, Path, Level).
-
-verify_error(X, Path, Level) ->
- docb_util:message(error, "Invalid object found at: ~p level:~w~n~s",
- [Path, Level, docb_pretty_format:term(X)]),
- false.
-
-verify_list([H|T], Path, Level) ->
- verify(H, Path, Level) andalso verify_list(T, Path, Level + 1);
-verify_list([], _, _) ->
- true.
-
-verify_optional([{_, _, _}|T], Path, Level) ->
- verify_optional(T, Path, Level);
-verify_optional([], _Path, _Level) ->
- true;
-verify_optional(X, Path, Level) ->
- verify_error(X, Path, Level).
-
-%%----------------------------------------------------------------------
-
-%% pp(File, Opts) -> {ok, OutFile} | errors
-%% Parses the source file and, if successful, prints the resulting tree
-%% structure to a file with the extension ".pp".
-pp(File, Opts) ->
- case parse(File, Opts) of
- {ok, Tree} ->
- OutFile = File ++ ".pp",
- dump(OutFile, Tree),
- {ok, OutFile};
- errors ->
- errors
- end.
-
-dump(File, Struct) ->
- {ok, Stream} = file:open(File, [write]),
- io:format("Info: Dump on ~p ...", [File]),
- io:format(Stream, "~n~s~n", [docb_pretty_format:term(Struct)]),
- io:format(" done.\n"),
- file:close(Stream).
-
-%%----------------------------------------------------------------------
-
-%% insert_after(Tag, Tree, Obj) -> Tree | {'EXIT', Reason}
-%% Insert an element in a tree structure
-insert_after(Tag, Tree, Obj) ->
- edit(Tag, Tree, {insert_after, Obj}).
-
-%% edit Op = delete, insert_before, insert_after
-edit(Tag, Tree, Op) ->
- case catch edit1(Tag, Tree, Op) of
- error ->
- docb_util:message(error, "Cannot do ~p to ~w", [Op, Tag]),
- Tree;
- Other ->
- Other
- end.
-
-edit1(Tag, {Tag, _O, _A}, _Op) ->
- throw(error);
-edit1(Tag, {Tag1, O, A}, Op) ->
- {Tag1, O, edit1_list(Tag, A, Op)};
-edit1(_, _, _) ->
- throw(error).
-
-edit1_list(Tag, [{pcdata, Str}|T], Op) ->
- [{pcdata, Str}|edit1_list(Tag, T, Op)];
-edit1_list(Tag, [{Tag, O, A}|T], {insert_after, Obj}) ->
- [{Tag, O, A}, Obj|T];
-edit1_list(Tag, [H|T], Op) ->
- [H|edit1_list(Tag, T, Op)];
-edit1_list(_Tag, [], _Op) ->
- [].
-
-%%______________________________________________________________________
-
-%% transform(From, To, Opts, File, Tree) -> void()
-%% Actual transformation of tree structure to desired format.
-transform(From, To, Opts, File, Tree) ->
- Filter = if
- To =:= html; To =:= kwic ->
- list_to_atom("docb_tr_" ++ atom_to_list(From) ++
- [$2|atom_to_list(To)]);
- true ->
- list_to_atom("sgml_tr_" ++ atom_to_list(From) ++
- [$2|atom_to_list(To)])
- end,
-
- case catch Filter:transform(File, Tree, Opts) of
-
- %% R5C
- {'EXIT', {undef, [{Filter, transform, [File, Tree, Opts],_}|_]}}->
- %% No transformation defined
- finish_transform(Tree, File, Opts, Filter);
-
- {'EXIT', {undef, {Filter, transform, [File, Tree, Opts],_}}} ->
- %% No transformation defined
- finish_transform(Tree, File, Opts, Filter);
-
- {'EXIT', What} ->
- docb_util:message(error,
- "Transformation trouble in ~P", [What, 9]),
- transformation_error;
-
- {error, Reason} ->
- docb_util:message(error, Reason),
- transformation_error;
-
- {Tree1, Opts1} ->
- %% transformation returning both new parse and new options
- finish_transform(Tree1, File, Opts1, Filter);
-
- Tree1 ->
- %% transformation returning only new parse
- finish_transform(Tree1, File, Opts, Filter)
- end.
-
-finish_transform(Tree, File, Opts, Filter) ->
- {Str, NewOpts} = pp(Tree, [], 1, Filter, Opts),
- Extension =
- case catch Filter:extension(NewOpts) of
- {'EXIT', _} ->
- Filter:extension();
- Others ->
- Others
- end,
- {ok, Out} =
- file:open(docb_util:outfile(File, Extension, NewOpts), [write]),
- put_chars(Out, Str),
- file:close(Out).
-
-put_chars(Out, Str) -> put_chars(Out, Str, 0).
-
-put_chars(Out, [$\n|Cs], _Pos) ->
- io:put_chars(Out, [$\n]),
- put_chars(Out, Cs, 0);
-
-put_chars(Out, [$\011|Cs], Pos) -> % tab
- TabbedPos = 8*((Pos div 8)+1),
- Nblanks = TabbedPos - Pos,
- io:put_chars(Out, lists:duplicate(Nblanks, $ )),
- put_chars(Out, Cs, Pos+Nblanks);
-
-put_chars(Out, [C|Cs], Pos) when is_integer(C) ->
- io:put_chars(Out, [C]),
- put_chars(Out, Cs, Pos+1);
-
-put_chars(Out, [L|Cs], Pos) when is_list(L) ->
- put_chars(Out, Cs, put_chars(Out, L, Pos));
-
-put_chars(_Out, [], Pos) ->
- Pos.
-
-pp({Tag, Optional, Args}, TagPath, Level, Filter, Opts) ->
- TagPath1 = [Tag|TagPath],
- Optional1 = reduce_optional(Optional),
-
- %% First try Filter:rule/3. It returns {Return, NewOpts}
- %% where Return is as from rule/2:
- Rule_3_result =
- case catch Filter:rule(TagPath1, {Level,Optional1,Args},Opts) of
- %% R5C
- {'EXIT', {undef, [{_, rule, _, _}|_]}} -> % No rule/3 defined
- failed;
-
- {'EXIT', {undef, {_, rule, _, _}}} -> % No rule/3 defined
- failed;
- %% R5C
- {'EXIT', {function_clause, [{_, rule, _, _}|_]}} -> % No MATCHING rule/3
- failed;
-
- {'EXIT', {function_clause, {_, rule, _, _}}} -> % No MATCHING rule/3
- failed;
-
- {'EXIT', What} ->
- docb_util:message(error,
- "Serious Error: ~P", [What, 9]);
- Others ->
- Others
- end,
- handle_rule_call_result({r3, Rule_3_result}, Filter, TagPath1, Tag,
- Level, Optional1, Args, Opts).
-
-handle_rule_call_result({r3, failed}, Filter, TagPath1, Tag, Level, Optional1,
- Args, Opts) ->
- %% Hmmm, try Filter:rule/2
- Rule_2_result = (catch Filter:rule(TagPath1, {Level, Optional1, Args})),
- handle_rule_call_result({r2, Rule_2_result}, Filter, TagPath1, Tag,
- Level, Optional1, Args, Opts);
-handle_rule_call_result({r3, {Result, NewOpts}}, Filter, TagPath1, Tag, Level,
- Optional1, Args, _Opts) ->
- handle_rule_call_result({r2, Result}, Filter, TagPath1, Tag, Level,
- Optional1, Args, NewOpts);
-handle_rule_call_result({_, {func, F}}, _Filter, _TagPath1, _Tag, _Level,
- _Optional1, Args, Opts) ->
- {F(Args), Opts};
-handle_rule_call_result({_, {'EXIT', Why}}, _Filter, TagPath1, _Tag, Level,
- Optional1, Args, Opts) ->
- report_error(TagPath1, Why, {Level, Optional1, Args}),
- {[], Opts};
-handle_rule_call_result({_, {drop, Str}}, _Filter, _TagPath1, _Tag, _Level,
- _Optional1, _Args, Opts) ->
- {[Str], Opts};
-handle_rule_call_result({_, {newargs, NewArgs}}, Filter, TagPath1, _Tag, _Level,
- _Optional1, _Args, Opts) ->
- {List, NewOpts} = pp_list(NewArgs, TagPath1, 1, Filter, Opts),
- {[List], NewOpts};
-handle_rule_call_result({_, {newargs, Before, NewArgs, After}}, Filter, TagPath1, _Tag, _Level,
- _Optional1, _Args, Opts) ->
- {List, NewOpts} = pp_list(NewArgs, TagPath1, 1, Filter, Opts),
- {[Before, List, After], NewOpts};
-handle_rule_call_result({_, {Before, After}}, Filter, TagPath1, _Tag, _Level,
- _Optional1, Args, Opts) when is_list(Before) ->
- {List, NewOpts} = pp_list(Args, TagPath1, 1, Filter, Opts),
- {[Before, List, After], NewOpts}.
-
-pp_list([H|T], TagPath, Level, Rules, Opts) ->
- {Hpp, Hopts} = pp(H, TagPath, Level, Rules, Opts),
- {Tpp, Tops} = pp_list(T, TagPath, Level + 1, Rules, Hopts),
- {[Hpp|Tpp], Tops};
-pp_list([], _, _, _, Opts) ->
- {[], Opts}.
-
-reduce_optional([{_, _, H}|T]) -> [H|reduce_optional(T)];
-reduce_optional([]) -> [].
-
-report_error(Arg1, Cause, Arg2) ->
- [Tag|_] = Arg1,
- docb_util:message(error,
- "Formatting trouble in ~p: ~p", [Tag, Cause]),
- docb_util:message(error, "Failure in rule(~p, ~p)", [Arg1, Arg2]).
-
-%%----------------------------------------------------------------------
-
-%% include_file(File, Tag) -> {ok, String} | error
-include_file(File, Tag) ->
- include(File, "%S" ++ Tag, "%E" ++ Tag).
-
-%% include(File, StartTag, StopTag) -> {ok, String} | error
-include(File, "", "") ->
- case file:open(File, [read]) of
- {ok, Fd} ->
- String = include_all(Fd),
- file:close(Fd),
- {ok, String};
- _ ->
- docb_util:message(error,
- "Include file ~s not found", [File]),
- error
- end;
-include(File, StartTag, StopTag) ->
- case file:open(File, [read]) of
- {ok, Fd} ->
- String = extract(File, Fd, StartTag, StopTag, searching),
- file:close(Fd),
- {ok, lists:flatten(String)};
- _ ->
- docb_util:message(error,
- "Include file ~s not found", [File]),
- error
- end.
-
-include_all(Fd) ->
- case io:get_line(Fd, '') of
- eof ->
- [];
- ListOfChars ->
- ListOfChars ++ include_all(Fd)
- end.
-
-extract(File, Fd, StartTag, StopTag, State) ->
- Line=io:get_line(Fd, ''),
- extract(File, Fd, StartTag, StopTag, State, Line).
-
-extract(File, _, _, _, _, eof) ->
- docb_util:message(error,
- "Premature end of file in include file ~p",
- [File]),
- [];
-extract(File, Fd, StartTag, StopTag, searching, Line) ->
- case regexp:match(Line, "^" ++ StartTag) of
- {match, _Start, _Length} ->
- extract(File, Fd, StartTag, StopTag, copying);
- nomatch ->
- extract(File, Fd, StartTag, StopTag, searching);
- {error, _Error} ->
- docb_util:message(error, "Bad syntax in ~s", [File]),
- []
- end;
-extract(File, Fd, StartTag, StopTag, copying, Line) ->
- case regexp:match(Line, "^" ++ StopTag) of
- {match, _Start, _Length} ->
- [];
- nomatch ->
- [Line|extract(File, Fd, StartTag, StopTag, copying)];
- {error, _Error} ->
- docb_util:message(error, "Bad syntax in ~s", [File]),
- []
- end.
-
-%%----------------------------------------------------------------------
-
-eval_str(Str) ->
- case lib:eval_str(Str) of
- {error, Report} ->
- docb_util:message(error,
- "ErlEval failed: ~s (~s)", [Str, Report]);
- {ok, S} ->
- io_lib:format("~p~n", [S])
- end.
diff --git a/lib/docbuilder/src/docb_pretty_format.erl b/lib/docbuilder/src/docb_pretty_format.erl
deleted file mode 100644
index 25dcd8987b..0000000000
--- a/lib/docbuilder/src/docb_pretty_format.erl
+++ /dev/null
@@ -1,177 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_pretty_format).
-
--export([term/1]).
-
-%% 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.
-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, io_lib: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, io_lib: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_list(H) ->
- case is_string(H) of
- true ->
- complex_list(T);
- false ->
- true
- end;
-complex_list([H|_]) when is_tuple(H) -> true;
-complex_list(_) -> false.
-
-%% 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(_I) ->
- [$ ].
-
-indent(I) when I >= 8 ->
- [$\t|indent(I-8)];
-indent(I) when I > 0 ->
- [$ |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/docbuilder/src/docb_tr_application2html.erl b/lib/docbuilder/src/docb_tr_application2html.erl
deleted file mode 100644
index d8cb214d0a..0000000000
--- a/lib/docbuilder/src/docb_tr_application2html.erl
+++ /dev/null
@@ -1,286 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_application2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(File, {application, _Attrs, [Header|Rest]}, Opts0) ->
-
- %% Extract header data
- Title = docb_html_util:extract_header_data(title, Header),
-
- case docb_util:an_option(kwicindex_only, Opts0) of
- false ->
-
- %% Create the framing HTML document
- OutFile = docb_util:outfile(File++"_frame", ".html", Opts0),
- case file:open(OutFile, [write]) of
- {ok, Fd} ->
- io:format(Fd,
-"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\"
-\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">
-<!-- This document was generated using DocBuilder-" ++ docb_util:version() ++ " -->
-<html>
-<head>
- <title>~s</title>
- " ++ docb_util:html_snippet(head, Opts0) ++ "
-</head>
-<frameset cols=\"150, *\">
- <frame src=\"~s\" name=\"toc\">
- <frame src=\"~s\" name=\"document\">
- <noframes>
- <body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\"
- vlink=\"#FF00FF\" alink=\"#FF0000\">
- <p>This documentation requires a browser that can handle frames</p>
- </body>
- </noframes>
-</frameset>
-</html>
-",
- [Title,
- File++".html", File++"_first.html"]),
- file:close(Fd)
- end,
-
- %% Create the front HTML document
- docb_main:transform(first, html, Opts0, File ++ "_first",
- {first, [], [Header|Rest]});
-
- true ->
- ok
- end,
-
- %% Extract files to include
- Files = case Rest of
- [{description, _, _}|NewRest] ->
- lists:map(fun({include, [{_, _, F}], _}) ->filename:rootname(F) end,
- NewRest);
- [{include, _, _}|_NewRest] ->
- lists:map(fun({include, [{_, _, F}], _}) -> filename:rootname(F) end,
- Rest)
- end,
-
- %% Concat all reference manuals into a *big* parse tree
- ConcatTree = concat_files(Files, Opts0),
-
- %% Create the kwic index src file to be put in outdir
- docb_main:transform(refs, kwic, Opts0, File, {refs,[],ConcatTree}),
-
- case docb_util:an_option(kwicindex_only, Opts0) of
- false ->
-
- %% Create an index
- docb_main:transform(index, html, Opts0, File ++ "_index",
- {index, [], [Header|ConcatTree]}),
- %% Create a cite dictionary
- docb_main:transform(cite, html, Opts0, File ++ "_cite",
- {cite, [], [Header|ConcatTree]}),
-
- %% Create a term dictionary
- docb_main:transform(term, html, Opts0, File ++ "_term",
- {term, [], [Header|ConcatTree]}),
-
- %% Transform each reference page
- case docb_util:an_option(framework_only, Opts0) of
- true ->
- ok;
- false ->
- transform_refs(Files,
- [dict,{part_application,File}|Opts0])
- end;
- true ->
- ok
- end,
-
- %% Find all fascicules to be put in the top menu of the table of
- %% contents
- Ext = docb_util:lookup_option(src_type, Opts0),
- Opts2 =
- case filelib:is_regular("fascicules"++Ext) of
- true ->
- case docb_main:parse1("fascicules", Opts0) of
- {ok, Parse} ->
- FascData = get_fasc_data(Parse),
- case lists:keyfind(File, 1, FascData) of
- {_, _, "YES", _} ->
- OrigFile =
- docb_util:outfile(File++"_frame",
- ".html", Opts0),
- EntryFile =
- docb_util:outfile("index",
- ".html",Opts0),
- docb_util:message(info,
- "Copying ~s to ~s",
- [OrigFile,EntryFile]),
- file:copy(OrigFile, EntryFile);
- _ ->
- ok
- end,
- [{fascdata, FascData}| Opts0];
- errors ->
- %% Do not bother
- docb_util:message(
- warning,
- "fascicules~s could not be parsed,"
- " no index.html created",
- [Ext]),
- Opts0
- end;
- false ->
- %% do not bother
- docb_util:message(warning,
- "fascicules~s not found, "
- "no index.html created",
- [Ext]),
- Opts0
- end,
-
- %% Create ToC parse tree
- {{toc, [{"FILE", "CDATA", File}], [Header|make_toc(ConcatTree)]},
- Opts2}.
-
-concat_files(Files, Opts) ->
- concat_files(Files, [], Opts).
-
-concat_files([File|Rest], Body, Opts) ->
- case docb_main:parse1(File, Opts) of
- {ok, Parse} ->
- NewParse=expand([Parse], File),
- %% Remove the reference manual header
- [{Ref, [], [_Hdr| NewBody]}] = NewParse,
- RefParse = [{Ref, [], NewBody}],
- Body ++ concat_files(Rest, RefParse, Opts);
- errors ->
- errors
- end;
-concat_files([], Body, _Opts) ->
- Body.
-
-expand([], _) ->
- [];
-expand([{pcdata, Attrs, More}|Rest], File) ->
- [{pcdata, Attrs, More}|expand(Rest, File)];
-expand([{name, Attrs, More}|Rest], File) ->
- [{name, [{"FILE", "CDATA", File}|Attrs], More}|expand(Rest, File)];
-expand([{module, Attrs, More}|Rest], File) ->
- [{module, [{"FILE", "CDATA", File}|Attrs], More}|expand(Rest,File)];
-expand([{file, Attrs, More}|Rest], File) ->
- [{file, [{"FILE", "CDATA", File}|Attrs], More}|expand(Rest, File)];
-expand([{app, Attrs, More}|Rest], File) ->
- [{app, [{"FILE", "CDATA", File}|Attrs], More}|expand(Rest, File)];
-expand([{lib, Attrs, More}|Rest], File) ->
- [{lib, [{"FILE", "CDATA", File}|Attrs], More}|expand(Rest, File)];
-expand([{com, Attrs, More}|Rest], File) ->
- [{com, [{"FILE", "CDATA", File}|Attrs], More}|expand(Rest, File)];
-expand([{Tag, Attrs, More}|Rest], File) ->
- [{Tag, Attrs, expand(More, File)}|expand(Rest, File)].
-
-transform_refs([], _) ->
- ok;
-transform_refs([File|Rest], Opts) ->
- Ext = docb_util:lookup_option(src_type, Opts),
- docb_util:message(info, "Processing \"~s~s\"", [File, Ext]),
- docb_main:process(File, Opts),
- transform_refs(Rest, Opts).
-
-make_toc([]) ->
- [];
-make_toc([{pcdata, _Attrs, _More}|Rest]) ->
- make_toc(Rest);
-make_toc([{module, Attrs, More}|Rest]) ->
- [{module, Attrs, More}|make_toc(Rest)];
-make_toc([{file, Attrs, More}|Rest]) ->
- [{file, Attrs, More}|make_toc(Rest)];
-make_toc([{app, Attrs, More}|Rest]) ->
- [{app, Attrs, More}|make_toc(Rest)];
-make_toc([{lib, Attrs, More}|Rest]) ->
- [{lib, Attrs, More}|make_toc(Rest)];
-make_toc([{com, Attrs, More}|Rest]) ->
- [{com, Attrs, More}|make_toc(Rest)];
-make_toc([{_Tag, _Attrs, More}|Rest]) ->
- make_toc(More) ++ make_toc(Rest).
-
-rule([module|_], {_, [File], _}) ->
- {"<small><a target=\"document\" href=\"" ++
- docb_html_util:make_anchor_href(File) ++ "\">",
- "</a></small><br/>\n"};
-
-rule([file|_], {_, [File], _}) ->
- {"<small><a target=\"document\" href=\"" ++
- docb_html_util:make_anchor_href(File) ++ "\">",
- "</a></small><br/>\n"};
-
-rule([app|_], {_, [File], _}) ->
- {"<small><a target=\"document\" href=\"" ++
- docb_html_util:make_anchor_href(File) ++ "\">",
- "</a></small><br/>\n"};
-
-rule([lib|_], {_, [File], _}) ->
- {"<small><a target=\"document\" href=\"" ++
- docb_html_util:make_anchor_href(File) ++ "\">",
- "</a></small><br/>\n"};
-
-rule([com|_], {_, [File], _}) ->
- {"<small><a target=\"document\" href=\"" ++
- docb_html_util:make_anchor_href(File) ++ "\">",
- "</a></small><br/>\n"};
-
-rule([pcdata|_], {_, _, Data}) ->
- {drop, docb_html_util:pcdata_to_html(Data)};
-
-rule(_, _) ->
- {drop, ""}.
-
-rule([toc|_], {_Depth, [File], [Header|_]}, Opts) ->
- case docb_util:lookup_option(fascdata, Opts) of
- false ->
- {{docb_html_layout:application_toc_top(
- docb_html_util:all_header_data(Header),
- File, Opts),
- docb_html_layout:part_toc_bot()}, Opts};
- FascData ->
- HRefTexts =
- lists:map(
- fun({_File, HRef, _Entry, PCText}) ->
- {HRef, docb_html_util:pcdata_to_html(PCText)}
- end,
- FascData),
- {{docb_html_layout:application_toc_top(
- docb_html_util:all_header_data(Header),
- File, Opts, HRefTexts) ++ "\n",
- docb_html_layout:part_toc_bot()}, Opts}
- end.
-
-%% Returns: [{File, HRef, Entry, Text}].
-get_fasc_data({fascicules, _, Fascs}) ->
- lists:map(
- fun({fascicule, Atts, Trees}) ->
- AVals = get_avals(Atts),
- PCText = get_pc_text(Trees),
- list_to_tuple(lists:append([AVals, [PCText]]))
- end,
- Fascs).
-
-get_avals(Atts) ->
- [element(3, Tuple) || Tuple <- Atts].
-
-get_pc_text([{pcdata, _, Text}]) ->
- Text.
diff --git a/lib/docbuilder/src/docb_tr_appref2html.erl b/lib/docbuilder/src/docb_tr_appref2html.erl
deleted file mode 100644
index 6b4cc0f815..0000000000
--- a/lib/docbuilder/src/docb_tr_appref2html.erl
+++ /dev/null
@@ -1,48 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_appref2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-%% Transform the parse tree. Header data is stored in an extra
-%% argument to make life easier later on.
-transform(_File, {appref,_,[Header|Rest]}, _Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- {appref, Data, [{header,[],[]}|Rest]}.
-
-rule([header|_],_) ->
- {drop, ""};
-
-rule([app|_],_) ->
- {"\n<h3>APPLICATION</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([appsummary|_],_) ->
- {"\n<h3>APPLICATION SUMMARY</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html_ref:rule(TagHistory,TagBody).
-
-rule([appref|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:ref_top(Data, Opts),
- docb_html_layout:ref_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html_ref:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_chapter2html.erl b/lib/docbuilder/src/docb_tr_chapter2html.erl
deleted file mode 100644
index 185cdc7cc3..0000000000
--- a/lib/docbuilder/src/docb_tr_chapter2html.erl
+++ /dev/null
@@ -1,59 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_chapter2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(File, {chapter,_,[Header|Rest]}, Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- Tree = {chapter, Data, [{header,[],[]}|Rest]},
- ChapterLevel =
- case docb_util:lookup_option(number, Opts) of
- false -> none;
- Value -> Value
- end,
- docb_html_util:number(Tree, ChapterLevel, File).
-
-rule([header|_], _) ->
- {drop, ""};
-
-rule([toc|_], {_,_,ToC}) ->
- {drop,
- "\n<h3>Table of Contents</h3>\n" ++
- docb_html_util:format_toc(ToC) ++ "\n"};
-
-rule([section|_], _) ->
- {"", ""};
-
-rule([title|Rest], {_,[Number,_File], [{pcdata,_,Title}]}) ->
- N = integer_to_list(docb_html_util:count_sections(Rest)+1),
- {drop,"\n<h" ++ N ++ ">" ++ Number ++ " " ++
- docb_html_util:pcdata_to_html(Title) ++ "</h" ++ N ++ ">\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html:rule(TagHistory, TagBody).
-
-rule([chapter|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:chapter_top(Data, Opts),
- docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_cite2html.erl b/lib/docbuilder/src/docb_tr_cite2html.erl
deleted file mode 100644
index 77f1c4e636..0000000000
--- a/lib/docbuilder/src/docb_tr_cite2html.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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_cite2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, Tree, Opts) ->
- purge(Tree, Opts).
-
-purge({Tag, Attrs, [Header|Body]}, Opts) ->
- CiteList = case docb_util:lookup_option({defs,cite}, Opts) of
- false -> [];
- Value -> Value
- end,
- B1 = purge_body(Body, CiteList),
- B2 = lists:ukeysort(2, B1),
- {Tag, Attrs, [Header|B2]}.
-
-purge_body([], _) ->
- [];
-purge_body([{pcdata,_Attrs,_More}|Rest], CiteList) ->
- purge_body(Rest, CiteList);
-purge_body([{cite,[{"ID","CDATA",ID}],More}|Rest], CiteList) ->
- case lists:keyfind(ID, 1, CiteList) of
- false ->
- [{cite, [{"NAME","CDATA",ID}, {"ID","CDATA",ID}], More}|
- purge_body(Rest, CiteList)];
- {ID, Name, _Description, _Responsible} ->
- [{cite, [{"NAME","CDATA",Name}, {"ID","CDATA",ID}], More}|
- purge_body(Rest, CiteList)];
- {ID, Name, _Description} ->
- [{cite, [{"NAME","CDATA",Name}, {"ID","CDATA",ID}], More}|
- purge_body(Rest, CiteList)]
- end;
-purge_body([{_Tag,_Attrs,More}|Rest], CiteList) ->
- purge_body(More, CiteList) ++ purge_body(Rest, CiteList).
-
-rule([header|_], _) ->
- {drop, ""};
-rule(_, _) ->
- {drop, ""}.
-
-rule([cite|_], {_,[],[Header]}, Opts) ->
- HeaderData = docb_html_util:all_header_data(Header),
- {{docb_html_layout:chapter_top(HeaderData, Opts) ++
- "\n<center><h1>Bibliography</h1></center>\n",
- docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule([cite|_], {_,[],[Header|_]}, Opts) ->
- HeaderData = docb_html_util:all_header_data(Header),
- {{docb_html_layout:chapter_top(HeaderData, Opts) ++
- "\n<center><h1>Bibliography</h1></center>\n<dl>\n",
- "\n</dl>\n" ++ docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule([cite|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:chapter_top(Data, Opts) ++
- "\n<center><h1>Bibliography</h1></center>\n<dl>\n",
- "\n</dl>\n" ++ docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule([cite|T], {A, B, [{citedef,C,
- [{ctitle, [], [{pcdata,[],CTitle}]},
- {cauthor, [], [{pcdata,[],CAuthor}]},
- {chowpublished, [],
- [{pcdata,[],Chowpublished}]}]}]}, Opts) ->
- CiteDef = CTitle ++ " " ++ CAuthor ++ " " ++ Chowpublished,
- rule([cite|T], {A,B,[{citedef,C,[{pcdata,[],CiteDef}]}]}, Opts);
-
-rule([cite|_], {_,[Name,ID], [{citedef,[],[{pcdata,[],Def}]}]}, Opts) ->
- CiteList =
- case docb_util:lookup_option({defs,cite}, Opts) of
- false -> [];
- Value -> Value
- end,
- case lists:keyfind(ID, 1, CiteList) of
- false ->
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ ID ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Def) ++ "\n</dd>\n"}, Opts};
- {ID, Name, Description, _Responsible} ->
- docb_util:message(warning,
- "Global cite ~s overriding local", [ID]),
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"},
- Opts};
- {ID, Name, Description} ->
- docb_util:message(warning,
- "Global cite ~s overriding local", [ID]),
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"}, Opts}
- end;
-
-rule([cite|_], {_,[Name,ID],_}, Opts) ->
- CiteList =
- case docb_util:lookup_option({defs,cite}, Opts) of
- false -> [];
- Value -> Value
- end,
- case lists:keyfind(ID, 1, CiteList) of
- false ->
- docb_util:message(error,
- "The cite ~s has no definition", [ID]),
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ ID ++ "</strong></a></dt>\n<dd>" ++
- "??" ++ "\n</dd>\n"}, Opts};
- {ID, Name, Description, _Responsible} ->
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"},
- Opts};
- {ID, Name, Description} ->
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"}, Opts}
- end.
diff --git a/lib/docbuilder/src/docb_tr_comref2html.erl b/lib/docbuilder/src/docb_tr_comref2html.erl
deleted file mode 100644
index 25207dccb4..0000000000
--- a/lib/docbuilder/src/docb_tr_comref2html.erl
+++ /dev/null
@@ -1,46 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_comref2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, {comref,_,[Header|Rest]}, _Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- {comref, Data, [{header,[],[]}|Rest]}.
-
-rule([header|_],_) ->
- {drop,""};
-
-rule([com|_],_) ->
- {"\n<h3>COMMAND</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([comsummary|_],_) ->
- {"\n<h3>COMMAND SUMMARY</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html_ref:rule(TagHistory, TagBody).
-
-rule([comref|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:ref_top(Data, Opts),
- docb_html_layout:ref_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html_ref:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_cref2html.erl b/lib/docbuilder/src/docb_tr_cref2html.erl
deleted file mode 100644
index 06748b8c57..0000000000
--- a/lib/docbuilder/src/docb_tr_cref2html.erl
+++ /dev/null
@@ -1,61 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_cref2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, {cref,_,[Header|Rest]}, _Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- {cref, Data, [{header,[],[]}|Rest]}.
-
-rule([header|_],_) ->
- {drop, ""};
-
-rule([ret|_],_) ->
- {"",""};
-
-rule([nametext|_],_) ->
- {" ",""};
-
-rule([name|_], {_,_,[_Ret,{nametext,[],[{pcdata,[],Name}]}]}) ->
- FName = lists:flatten(docb_html_util:pcdata_to_html(Name)),
- TName = docb_util:trim(FName),
- CAnchor = docb_util:fknidx(TName, "/"),
- {"<A NAME=\"" ++ CAnchor ++ "\"><STRONG><CODE>",
- "</CODE></STRONG></A><BR>\n"};
-rule([name|T], {I,As,[Ret,{pcdata,[],Name}]}) -> % For SGML DTD
- rule([name|T], {I,As,[Ret,{nametext,[],[{pcdata,[],Name}]}]});
-
-rule([lib|_],_) ->
- {"\n<H3>C LIBRARY</H3>\n<DIV CLASS=REFBODY>\n","\n</DIV>\n"};
-
-rule([libsummary|_],_) ->
- {"\n<H3>C LIBRARY SUMMARY</H3>\n<DIV CLASS=REFBODY>\n","\n</DIV>\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html_ref:rule(TagHistory, TagBody).
-
-rule([cref|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:ref_top(Data, Opts),
- docb_html_layout:ref_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html_ref:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_erlref2html.erl b/lib/docbuilder/src/docb_tr_erlref2html.erl
deleted file mode 100644
index b264c46bce..0000000000
--- a/lib/docbuilder/src/docb_tr_erlref2html.erl
+++ /dev/null
@@ -1,46 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_erlref2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, {erlref,_,[Header|Rest]}, _Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- {erlref, Data, [{header,[],[]}|Rest]}.
-
-rule([header|_],_) ->
- {drop, ""};
-
-rule([module|_],_) ->
- {"\n<h3>MODULE</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([modulesummary|_],_) ->
- {"\n<h3>MODULE SUMMARY</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html_ref:rule(TagHistory, TagBody).
-
-rule([erlref|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:ref_top(Data, Opts),
- docb_html_layout:ref_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html_ref:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_fileref2html.erl b/lib/docbuilder/src/docb_tr_fileref2html.erl
deleted file mode 100644
index 60280543a8..0000000000
--- a/lib/docbuilder/src/docb_tr_fileref2html.erl
+++ /dev/null
@@ -1,46 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_fileref2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, {fileref,_,[Header|Rest]}, _Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- {fileref, Data, [{header,[],[]}|Rest]}.
-
-rule([header|_],_) ->
- {drop, ""};
-
-rule([file|_],_) ->
- {"\n<h3>FILE</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule([filesummary|_],_) ->
- {"\n<h3>FILE SUMMARY</h3>\n<div class=\"REFBODY\">\n","\n</div>\n"};
-
-rule(TagHistory, TagBody) ->
- docb_html_ref:rule(TagHistory, TagBody).
-
-rule([fileref|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:ref_top(Data, Opts),
- docb_html_layout:ref_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html_ref:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_first2html.erl b/lib/docbuilder/src/docb_tr_first2html.erl
deleted file mode 100644
index e9ecbe73cb..0000000000
--- a/lib/docbuilder/src/docb_tr_first2html.erl
+++ /dev/null
@@ -1,46 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_first2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, Tree, _Opts) ->
- Tree.
-
-rule([header|_], _) ->
- {drop, ""};
-
-rule([description|_], _) ->
- {"", ""};
-
-rule([include|_], _) ->
- {drop, ""};
-
-rule(TagHistory, TagBody) ->
- docb_html:rule(TagHistory, TagBody).
-
-rule([first|_], {_,[],[Header|_]}, Opts) ->
- HeaderData = docb_html_util:all_header_data(Header),
- {{docb_html_layout:first_top(HeaderData, Opts),
- docb_html_layout:first_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_index2html.erl b/lib/docbuilder/src/docb_tr_index2html.erl
deleted file mode 100644
index 312342add2..0000000000
--- a/lib/docbuilder/src/docb_tr_index2html.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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_index2html).
-
--export([extension/0, transform/3, rule/2]).
-
-extension() ->
- ".html".
-
-transform(_File0, {index, Attrs, [Header| Trees0]}, _Opts) ->
- Trees1 = prune_flat(Trees0, false),
- %%
- %% Now each element of Trees1 is a tree with tag `name' and
- %% attribute `File', and with one `pcdata' subtree containing the
- %% name `Func' of the function. We extract `File' and `Func', and
- %% create new trees.
- %%
- %% `File' is attribute CDATA (from an <include file=...>), and
- %% `Func' is PCDATA.
- %%
- FileFuncs =
- [{File, RefType, Func} ||
- {name, [{_, _, File}, {_, _, RefType}|_],
- [{pcdata, [], Func}]}
- <- Trees1],
- Trees2 = new_trees(FileFuncs),
- {index, Attrs, [Header| Trees2]}.
-
-%% Remove all elements except those with tag equal to `name'.
-%% Within `name' remove all elements except those equal to `pcdata'.
-%% Add attribute `filetype' to `name'.
-%%
-%% Refs: appref, comref, cref, erlref, fileref
-prune_flat([{appref, _Attrs, More}| Rest], _) ->
- RefType = appref,
- lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType));
-prune_flat([{comref, _Attrs, More}| Rest], _) ->
- RefType = comref,
- lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType));
-prune_flat([{cref, _Attrs, More}| Rest], _) ->
- RefType = cref,
- lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType));
-prune_flat([{erlref, _Attrs, More}| Rest], _) ->
- RefType = erlref,
- lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType));
-prune_flat([{fileref, _Attrs, More}| Rest], _) ->
- RefType = fileref,
- lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType));
-prune_flat([{name, [Attr0|Attrs0], More}| Rest], RefType) ->
- Attrs = [Attr0, {"FILETYPE", "CDATA", RefType} |
- Attrs0],
- [{name, Attrs, keep_pcdata(More)}| prune_flat(Rest, RefType)];
-prune_flat([{pcdata, _, _}| Rest], RefType) -> % special case
- prune_flat(Rest, RefType);
-prune_flat([{_Tag, _Attrs, More}| Rest], RefType) ->
- lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType));
-prune_flat([], _) ->
- [].
-
-keep_pcdata(Trees) ->
- [T || T = {pcdata, _, _} <- Trees].
-
-new_trees(FileFuncs) ->
- Files0 = [{File, RefType} || {File, RefType, _} <- FileFuncs],
- Files1 = lists:usort(Files0),
- FileEntries = [{reffile, File, RefType,
- [Fu || {Fi, _, Fu} <- FileFuncs, Fi == File]}
- || {File, RefType} <- Files1],
- FuncEntries = [{func, Func, RefType, [File]}
- || {File, RefType, Func} <- FileFuncs],
- Entries = FileEntries ++ FuncEntries,
- SortedEntries = sort_entries(Entries),
- %%
- %% We create a tree according to the following "dtd":
- %%
- %% element index (reffile | funcdef)*
- %% element reffile (funcdef2)*
- %% attribute reffile filename CDATA
- %% attribute reffile filetype CDATA
- %% element funcdef2 PCDATA
- %% attribute funcdef2 filename CDATA
- %% attribute funcdef2 filetype CDATA
- %% element funcdef PCDATA
- %% attribute funcdef filename CDATA
- %% attribute funcdef filetype CDATA
- %%
- %% For example:
- %% <index>
- %% <reffile filename="mymod" filetype="erlref">
- %% <funcdef2 filename="mymod" filetype="erlref">myfunca(A)</>
- %% <funcdef2 filename="mymod" filetype="erlref">myfuncb(A, B)</>
- %% </>
- %% <funcdef filename="mymod" filetype="erlref">myfunca(A)</>
- %% <funcdef filename="mymod" filetype="erlref">myfuncb(A, B)</>
- %% </>
- lists:flatmap(
- fun({reffile, File, RefType, Funcs}) ->
- %% A reffile tree
- [{reffile, [{"FILENAME", "CDATA", File},
- {"FILETYPE", "CDATA", RefType}],
- [{funcdef2, [{"FILENAME", "CDATA", File},
- {"FILETYPE", "CDATA", RefType}],
- [{pcdata, [], Func}]} || Func <- Funcs]}];
- ({func, Func, RefType, [File]}) ->
- %% A func tree
- [{funcdef, [{"FILENAME", "CDATA", File},
- {"FILETYPE", "CDATA", RefType}],
- [{pcdata, [], Func}]}]
- end, SortedEntries).
-
-%% Sorting of entries
-%%
-%% The sorting is based on how names of files and functions are
-%% presented (in a browser).
-%% Requires conversion to "function/2" etc.
-%%
-sort_entries(Entries) ->
- ExpEntries =
- lists:map(
- fun({reffile, File, RefType, Funcs}) ->
- HFile = filename_sort_order(File),
- HFuncs = [{funcdef_sort_order(Fu, RefType), Fu} || Fu <- Funcs],
- {reffile, HFile, File, RefType, lists:sort(HFuncs)};
- ({func, Func, RefType, [File]}) ->
- HFunc = funcdef_sort_order(Func, RefType),
- HFile = filename_sort_order(File),
- {func, HFunc, Func, RefType, [{HFile, File}]}
- end, Entries),
- SortedExpEntries = lists:keysort(2, ExpEntries),
- lists:map(
- fun({Tag, _HName, Name, RefType, Vals}) ->
- NVals = lists:map(fun({_HVal, Val}) -> Val end, Vals),
- {Tag, Name, RefType, NVals}
- end, SortedExpEntries).
-
-rule([index| _], _) ->
- {docb_html_layout:index_top("") ++
- "<dl>\n",
- "</dl>\n" ++ docb_html_layout:index_bot()};
-
-rule([header| _], _) ->
- {drop, ""};
-
-rule([reffile| _], {_, [File, _RefType|_], _}) ->
- CFile = docb_html_util:attribute_cdata_to_html(File),
- {"<dt><em>" ++ CFile ++ "</em></dt>\n", ""};
-
-rule([funcdef2| _], {_, [File, RefType|_], [{pcdata, [], FuncDef}]}) ->
- FFuncDef = lists:flatten(docb_html_util:pcdata_to_html(FuncDef)),
- TFuncDef = docb_util:trim(FFuncDef),
- ShortFuncDef = docb_html_util:make_funcdef_short(TFuncDef, RefType),
- HRef =
- docb_html_util:make_anchor_href_short(File, TFuncDef, RefType),
- {drop,
- "<dd><a href=\"" ++ HRef ++ "\"><code>" ++
- ShortFuncDef ++ "</code></a></dd>\n"};
-
-rule([funcdef| _], {_, [File, RefType|_], [{pcdata, [], FuncDef}]}) ->
- FFuncDef = lists:flatten(docb_html_util:pcdata_to_html(FuncDef)),
- TFuncDef = docb_util:trim(FFuncDef),
- ShortFuncDef = docb_html_util:make_funcdef_short(TFuncDef, RefType),
- HRef =
- docb_html_util:make_anchor_href_short(File, TFuncDef, RefType),
- CFile = docb_html_util:attribute_cdata_to_html(File),
- {drop,
- "<dt><code>" ++ ShortFuncDef ++ "</code></dt>\n"
- "<dd><a href=\"" ++ HRef ++ "\"><em>" ++
- CFile ++ "</em></a></dd>\n"};
-
-rule(_, _) ->
- {drop, ""}.
-
-filename_sort_order(File) ->
- docb_html_util:html_latin1_sort_order(
- lists:flatten(
- docb_html_util:attribute_cdata_to_html(string:strip(File)))).
-
-funcdef_sort_order(FuncDef, RefType) ->
- docb_html_util:html_latin1_sort_order(
- docb_html_util:make_anchor_name_short(FuncDef, RefType)).
diff --git a/lib/docbuilder/src/docb_tr_part2html.erl b/lib/docbuilder/src/docb_tr_part2html.erl
deleted file mode 100644
index 30befe8432..0000000000
--- a/lib/docbuilder/src/docb_tr_part2html.erl
+++ /dev/null
@@ -1,237 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_part2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(File, {part, _Attrs, [Header| Rest]}, Opts0) ->
-
- %% Extract header data
- Title = docb_html_util:extract_header_data(title, Header),
-
- %% Create the framing HTML document
- OutFile = docb_util:outfile(File ++ "_frame", ".html", Opts0),
- case file:open(OutFile, [write]) of
- {ok, Frame} ->
- io:format(Frame,
-"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\"
- \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">
-<!-- This document was generated using DocBuilder-" ++ docb_util:version() ++ " -->
-<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
-<head>
- <title>~s</title>
- " ++ docb_util:html_snippet(head, Opts0) ++ "
-</head>
-<frameset cols=\"200, *\">
- <frame src=\"~s\" name=\"toc\"/>
- <frame src=\"~s\" name=\"document\"/>
- <noframes>
- <body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\"
- vlink=\"#FF00FF\" alink=\"#FF0000\">
- <p>This documentation requires a browser that can handle frames</p>
- </body>
- </noframes>
-</frameset>
-</html>
-",
- [Title, File ++ ".html", File ++ "_first.html"]),
- file:close(Frame)
- end,
-
- %% Create the front HTML document
- docb_main:transform(first, html, Opts0, File ++ "_first",
- {first, [], [Header| Rest]}),
-
- %% Extract files to include
- Files =
- case Rest of
- [{description, _, _}| NewRest] ->
- lists:map(fun({include, [{_, _, F}], _}) -> filename:rootname(F) end,
- NewRest);
- [{include, _, _}| _NewRest] ->
- lists:map(fun({include, [{_, _, F}], _}) -> filename:rootname(F) end, Rest)
- end,
-
- %% Concat all chapters into a *big* parse tree
- %% Also transform them to HTML
- TransformP = not docb_util:an_option(framework_only, Opts0),
- TOpts = [dict, {part_application,File}],
- ConcatTree = concat_files(Files, Opts0, TransformP, TOpts),
-
- %% Create a cites dictionary
- docb_main:transform(cite, html, Opts0, File ++ "_cite",
- {cite, [], [Header| ConcatTree]}),
-
- %% Create a terms dictionary
- docb_main:transform(term, html, Opts0, File ++ "_term",
- {term, [], [Header| ConcatTree]}),
-
- %% Find all fascicules to be put in the top menu of the table of
- %% contents
- Ext = docb_util:lookup_option(src_type, Opts0),
- Opts2 =
- case filelib:is_regular("fascicules"++Ext) of
- true ->
- case docb_main:parse1("fascicules", Opts0) of
- {ok, Parse} ->
- FascData = get_fasc_data(Parse),
- case lists:keyfind(File, 1, FascData) of
- {_, _, "YES", _} ->
- OrigFile =
- docb_util:outfile(File++"_frame",
- ".html", Opts0),
- EntryFile =
- docb_util:outfile("index",
- ".html", Opts0),
- docb_util:message(info,
- "Copying ~s to ~s",
- [OrigFile,EntryFile]),
- file:copy(OrigFile, EntryFile);
- _ ->
- ok
- end,
- [{fascdata, FascData}| Opts0];
- errors ->
- %% do not bother
- docb_util:message(
- warning,
- "fascicules~s could not be parsed,"
- " no index.html created~n", [Ext]),
- Opts0
- end;
- _ ->
- %% do not bother
- docb_util:message(warning,
- "fascicules~s not found, "
- "no index.html created~n",
- [Ext]),
- Opts0
- end,
-
- %% Create ToC parse tree
- {{toc, [{"FILE", "CDATA", File}], [Header| ConcatTree]}, Opts2}.
-
-concat_files(Files, Opts, TransformP, TOpts) ->
- Ext = docb_util:lookup_option(src_type, Opts),
- concat_files(Files, [], 1, Opts, TransformP, TOpts, Ext).
-
-concat_files([File | Rest], Body, ChLevel, Opts, TP, TOpts, Ext) ->
- case docb_main:parse1(File, Opts) of
- {ok, Parse} ->
- {TopTag, Attrs, [Header = {header, _, HeaderContents} | More]} = Parse,
- {title,_,Title} = lists:keyfind(title,1,HeaderContents),
- NewMore = [{section, [], [{title, [], Title}| More]}],
- NewParse = {TopTag, Attrs, [Header| NewMore]},
- if
- TP ->
- docb_util:message(info,
- "Processing \"~s~s\"",
- [File, Ext]),
- Opts2 =
- [html, {number,integer_to_list(ChLevel)}] ++
- TOpts ++ Opts,
- docb_main:transform(TopTag, html, Opts2, File,
- NewParse);
- true -> ignore
- end,
- NumberTree =
- docb_html_util:number(NewParse,
- integer_to_list(ChLevel), File),
- {_, [], [_| NewBody]} = NumberTree,
- Body ++ concat_files(Rest, NewBody, ChLevel+1, Opts,
- TP, TOpts, Ext);
- errors ->
- throw({error,"Parse error when building chapter "++File})
- end;
-concat_files([], Body, _ChLevel, _Opts, _TP, _TOpts, _Ext) ->
- Body.
-
-rule([section| _], _) ->
- {"", ""};
-
-rule(_, _) ->
- {drop, ""}.
-
-rule([toc| _], {_Depth, [File], [Header| _]}, Opts) ->
- case docb_util:lookup_option(fascdata, Opts) of
- false ->
- {{docb_html_layout:part_toc_top(
- docb_html_util:all_header_data(Header), File, Opts),
- docb_html_layout:part_toc_bot()}, Opts};
- FascData ->
- HRefTexts =
- lists:map(
- fun({_File, HRef, _Entry, PCText}) ->
- {HRef, docb_html_util:pcdata_to_html(PCText)}
- end,
- FascData),
- {{docb_html_layout:part_toc_top(
- docb_html_util:all_header_data(Header),
- File, Opts, HRefTexts),
- docb_html_layout:part_toc_bot()}, Opts}
- end;
-
-rule([title| Rest], {_, [Number, File], [{pcdata, _, Title}]}, Opts) ->
- N = docb_html_util:count_sections(Rest),
- OutFile = docb_html_util:make_anchor_href(File),
- if
- N == 1 ->
- {{drop,
- "<hr/>\n<small>" ++
- Number ++
- " <a target=\"document\" href=\"" ++ OutFile ++ "#" ++
- Number ++ "\">" ++
- docb_html_util:pcdata_to_html(Title) ++
- "</a></small><br/>\n"},
- Opts};
- N < 3 ->
- {{drop,
- "<small>" ++
- Number ++
- " <a target=\"document\" href=\"" ++ OutFile ++ "#" ++
- Number ++ "\">" ++
- docb_html_util:pcdata_to_html(Title) ++
- "</a></small><br/>\n"},
- Opts};
- true ->
- {{drop, ""}, Opts}
- end.
-
-%% Parsed fascicules:
-%% {fascicules,[],
-%% [{fascicule, [{"FILE","CDATA","refman"},
-%% {"HREF","CDATA","refman_frame.html"},
-%% {"ENTRY","TOKEN","YES"}],
-%% [{pcdata, [], "" Reference Manual\\n \n"}]},
-%% Returns: [{File, HRef, Entry, Text}].
-get_fasc_data({fascicules, _, Fascs}) ->
- lists:map(
- fun({fascicule, Atts, Trees}) ->
- AVals = get_avals(Atts),
- PCText = get_pc_text(Trees),
- list_to_tuple(lists:append([AVals, [PCText]])) end,
- Fascs).
-
-get_avals(Atts) ->
- [element(3, Tuple) || Tuple <- Atts].
-
-get_pc_text([{pcdata, _, Text}]) ->
- Text.
diff --git a/lib/docbuilder/src/docb_tr_refs2kwic.erl b/lib/docbuilder/src/docb_tr_refs2kwic.erl
deleted file mode 100644
index dc60c329fc..0000000000
--- a/lib/docbuilder/src/docb_tr_refs2kwic.erl
+++ /dev/null
@@ -1,156 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_refs2kwic).
-
--export([extension/0, transform/3, rule/2]).
-
-%% Output parts of a parsetree that contains a series of reference
-%% manual pages. The tags considered are: module, file, app, com and lib
-%% (and their corresponding *summary tags), and name, fsummary, c, em,
-%% ret and pcdata.
-
-extension() ->
- ".kwc".
-
-transform(File, Tree, Opts) ->
- {refs, [], Trees} = Tree,
- FileTree = {srcfile, [], [{pcdata, [], File}]},
- AppName = docb_util:lookup_option(name, Opts, "unknown"),
- AppTree = {appname, [], [{pcdata, [], AppName}]},
- Vsn = docb_util:lookup_option(vsn, Opts, "unknown"),
- VsnTree = {appvsn, [], [{pcdata, [], Vsn}]},
- NewTree = {refs, [], [FileTree, AppTree, VsnTree| Trees]},
- {NewTree, Opts}.
-
-rule([refs|_],_) ->
- {"%% Automatically generated. Do not edit.\n", ""};
-
-rule([srcfile| _], _) ->
- {"{srcfile, \"", "\"}.\n"};
-
-rule([appname| _], _) ->
- {"{appname, \"", "\"}.\n"};
-
-rule([appvsn| _], _) ->
- {"{appvsn, \"", "\"}.\n"};
-
-rule([erlref|_ ], _) ->
- {"", ""};
-
-rule([fileref|_ ], _) ->
- {"", ""};
-
-rule([appref|_ ], _) ->
- {"", ""};
-
-rule([comref|_ ], _) ->
- {"", ""};
-
-rule([cref|_ ], _) ->
- {"", ""};
-
-rule([module| _], {_, [File], _}) ->
- {drop, "{module, \"" ++ File ++ "\"}.\n"};
-
-rule([file|_], {_, [File], _}) ->
- {drop, "{file, \"" ++ File ++ "\"}.\n"};
-
-rule([app|_], {_, [File], _}) ->
- {drop, "{app, \"" ++ File ++ "\"}.\n"};
-
-rule([com|_], {_, [File], _}) ->
- {drop, "{com, \"" ++ File ++ "\"}.\n"};
-
-rule([lib|_], {_, [File], _}) ->
- {drop, "{lib, \"" ++ File ++ "\"}.\n"};
-
-rule([modulesummary|_], _) ->
- {"{modulesummary, \"", "\"}.\n"};
-
-rule([filesummary|_], _) ->
- {"{filesummary, \"", "\"}.\n"};
-
-rule([appsummary|_], _) ->
- {"{appsummary, \"", "\"}.\n"};
-
-rule([comsummary|_], _) ->
- {"{comsummary, \"", "\"}.\n"};
-
-rule([libsummary|_], _) ->
- {"{libsummary, \"", "\"}.\n"};
-
-rule([funcs|_ ], _) ->
- {"", ""};
-
-rule([func|_ ], _) ->
- {"", ""};
-
-rule([name,func,funcs,cref|_], {_,[_File], [_Ret,{pcdata,[],Name}]}) ->
- FName = lists:flatten(docb_html_util:pcdata_to_html(Name)),
- TName = docb_util:trim(FName),
- case catch docb_util:fknidx(TName, "/") of
- {'EXIT',_} ->
- {drop, ["{name, \"", escq(TName), "\"}.\n"]};
- FuncName ->
- {drop, ["{name, \"", escq(FuncName), "\"}.\n"]}
- end;
-
-rule([name,func,funcs,erlref|_], {_,[_File], [{pcdata,[],Name}]}) ->
- FName = lists:flatten(docb_html_util:pcdata_to_html(Name)),
- TName = docb_util:trim(FName),
- case catch docb_util:fknidx(TName, "/") of
- {'EXIT',_} ->
- {drop, ["{name, \"", escq(TName), "\"}.\n"]};
- FuncName ->
- {drop, ["{name, \"", escq(FuncName), "\"}.\n"]}
- end;
-
-rule([name, func| _], {_, [_File], [{pcdata, [], Name}]}) ->
- FName = lists:flatten(docb_html_util:pcdata_to_html(Name)),
- TName = docb_util:trim(FName),
- Cmd = case string:tokens(TName, " ") of
- [Cmd0| _] ->
- Cmd0;
- _ ->
- TName
- end,
- {drop, ["{name, \"", escq(Cmd), "\"}.\n"]};
-
-rule([fsummary| _], _) ->
- {"{fsummary, \"", "\"}.\n"};
-
-rule([c, fsummary|_], _) ->
- {"", ""};
-
-rule([em, fsummary|_], _) ->
- {"", ""};
-
-rule([pcdata| _], {_, _, Data}) ->
- FData = lists:flatten(docb_html_util:pcdata_to_html(Data)),
- Out = lists:map(fun($\n) -> $ ; (C) -> C end, FData),
- {drop, escq(Out)};
-
-rule(_, _) ->
- {drop, ""}.
-
-escq(Cs) ->
- lists:flatmap(fun($") ->
- "\\\"";
- (C) -> [C]
- end,
- Cs).
diff --git a/lib/docbuilder/src/docb_tr_report2html.erl b/lib/docbuilder/src/docb_tr_report2html.erl
deleted file mode 100644
index 3386ed972a..0000000000
--- a/lib/docbuilder/src/docb_tr_report2html.erl
+++ /dev/null
@@ -1,70 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_report2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-%%
-%% File extension
-%%
-
-extension() ->
- ".html".
-
-transform(File, {report,_,[Header|Rest]}, Opts) ->
- Data = [{[], [], docb_html_util:all_header_data(Header)}],
- Tree = {report, Data, [{header,[],[]}|Rest]},
- ChapterLevel = case docb_util:lookup_option(number, Opts) of
- false -> none;
- Value -> Value
- end,
- NumberTree = docb_html_util:number(Tree, ChapterLevel, File),
- options(NumberTree, Opts).
-
-options(Tree, []) ->
- Tree;
-options(Tree, [_|Rest]) ->
- options(Tree, Rest).
-
-rule([header|_], _) ->
- {drop, ""};
-
-rule([toc|_], {_,_,ToC}) ->
- {drop, "\n<h3>Table of Contents</h3>\n" ++
- docb_html_util:format_toc(ToC) ++ "\n"};
-
-rule([section|_], _) ->
- {"", ""};
-
-rule([title|Rest], {_,[Number,_File], [{pcdata,_,Title}]}) ->
- N = integer_to_list(docb_html_util:count_sections(Rest)+1),
- {drop, "\n<h" ++ N ++ ">" ++ Number ++ " " ++
- docb_html_util:pcdata_to_html(Title) ++ "</h" ++ N ++ ">\n"};
-
-rule([erlinclude|_], {_,[File,Tag],_}) ->
- docb_html_util:erl_include(File, Tag);
-
-rule(TagHistory, TagBody) ->
- docb_html:rule(TagHistory, TagBody).
-
-rule([report|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:report_top(Data, Opts),
- docb_html_layout:report_bot(Opts)}, Opts};
-
-rule(TagHistory, TagBody, Opts) ->
- docb_html:rule(TagHistory, TagBody, Opts).
diff --git a/lib/docbuilder/src/docb_tr_term2html.erl b/lib/docbuilder/src/docb_tr_term2html.erl
deleted file mode 100644
index a3c4a5312a..0000000000
--- a/lib/docbuilder/src/docb_tr_term2html.erl
+++ /dev/null
@@ -1,124 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_tr_term2html).
-
--export([extension/0, transform/3, rule/2, rule/3]).
-
-extension() ->
- ".html".
-
-transform(_File, Tree, Opts) ->
- purge(Tree, Opts).
-
-purge({Tag, Attrs, [Header|Body]}, Opts) ->
- TermList = case docb_util:lookup_option({defs,term}, Opts) of
- false -> [];
- Value -> Value
- end,
- B1 = purge_body(Body, TermList),
- B2 = lists:ukeysort(2, B1),
- {Tag, Attrs, [Header|B2]}.
-
-purge_body([], _) ->
- [];
-purge_body([{pcdata,_Attrs,_More}|Rest], TermList) ->
- purge_body(Rest, TermList);
-purge_body([{term,[{"ID","CDATA",ID}],More}|Rest], TermList) ->
- case lists:keyfind(ID, 1, TermList) of
- false ->
- [{term,[{"NAME","CDATA",ID},{"ID","CDATA",ID}],More}|
- purge_body(Rest, TermList)];
- {ID, Name, _Description, _Responsible} ->
- [{term,[{"NAME","CDATA",Name},{"ID","CDATA",ID}],More}|
- purge_body(Rest, TermList)];
- {ID, Name, _Description} ->
- [{term,[{"NAME","CDATA",Name},{"ID","CDATA",ID}],More}|
- purge_body(Rest, TermList)]
- end;
-purge_body([{_Tag,_Attrs,More}|Rest], TermList) ->
- purge_body(More, TermList) ++ purge_body(Rest, TermList).
-
-rule([header|_], _) ->
- {drop, ""};
-rule(_, _) ->
- {drop, ""}.
-
-rule([term|_], {_,[],[Header]}, Opts) ->
- {{docb_html_layout:chapter_top(
- docb_html_util:all_header_data(Header), Opts) ++
- "\n<center><h1>Glossary</h1></center>\n",
- docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule([term|_], {_,[],[Header|_]},Opts) ->
- {{docb_html_layout:chapter_top(
- docb_html_util:all_header_data(Header), Opts) ++
- "\n<center><h1>Glossary</h1></center>\n<dl>\n",
- "\n</dl>\n" ++ docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule([term|_], {_,[Data],_}, Opts) ->
- {{docb_html_layout:chapter_top(Data, Opts) ++
- "\n<center><h1>Bibliography</h1></center>\n<dl>\n",
- "\n</dl>\n" ++ docb_html_layout:chapter_bot(Opts)}, Opts};
-
-rule([term|_], {_,[Name,ID],[{termdef,[],[{pcdata,[],Def}]}]}, Opts) ->
- TermList = case docb_util:lookup_option({defs,term}, Opts) of
- false -> [];
- Value -> Value
- end,
- case lists:keyfind(ID, 1, TermList) of
- false ->
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ ID ++ "</strong></a>\n</dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Def) ++ "\n</dd>\n"}, Opts};
- {ID, Name, Description, _Responsible} ->
- docb_util:message(warning,
- "Global term ~s overriding local", [ID]),
- {{drop,"\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"},
- Opts};
- {ID, Name, Description} ->
- docb_util:message(warning,
- "Global term ~s overriding local", [ID]),
- {{drop, "\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"}, Opts}
- end;
-
-rule([term|_], {_,[Name,ID],_}, Opts) ->
- TermList = case docb_util:lookup_option({defs,term}, Opts) of
- false -> [];
- Value -> Value
- end,
- case lists:keyfind(ID, 1, TermList) of
- false ->
- docb_util:message(error,
- "The term ~s has no definition", [ID]),
- {{drop, "\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ ID ++ "</strong></a></dt>\n<dd>" ++
- "??" ++ "\n</dd>\n"}, Opts};
- {ID, Name, Description, _Responsible} ->
- {{drop, "\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"},
- Opts};
- {ID, Name, Description} ->
- {{drop, "\n<dt><a name=\"" ++ ID ++ "\">" ++
- "<strong>" ++ Name ++ "</strong></a></dt>\n<dd>" ++
- docb_html_util:pcdata_to_html(Description) ++ "\n</dd>\n"}, Opts}
- end.
diff --git a/lib/docbuilder/src/docb_transform.erl b/lib/docbuilder/src/docb_transform.erl
deleted file mode 100644
index 736ac92274..0000000000
--- a/lib/docbuilder/src/docb_transform.erl
+++ /dev/null
@@ -1,163 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--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}
-%% File = string(), file name with or without ".xml" extension
-%% Opts = [Opt]
-%% Reason = badfile | {badopt, Term}
-file(File0) ->
- file(File0, []).
-file(File0, RawOpts) ->
- File = filename:rootname(File0), % without extension
- Ext = case filename:extension(File0) of
- ".xml" -> ".xml";
- ".sgml" -> ".sgml";
- "" ->
- %% If the file is given without extension, we try to
- %% infer if the source file is XML or SGML.
- %% SGML is supported *internally within OTP* for
- %% backwards compatibility reasons.
- case filelib:is_regular(File++".xml") of
- true -> ".xml";
- false -> ".sgml"
- end;
- _Ext0 -> % this is probably an error...
- ".xml"
- end,
- case filelib:is_regular(File++Ext) of
- true ->
- case parse(RawOpts) of
- {ok, Opts0} ->
- {ok, Cwd} = file:get_cwd(),
- Opts = [{src_type,Ext},
- {src_dir,Cwd},
- {src_file,File},
- {{local_defs,term},[]},
- {{local_defs,cite},[]} | Opts0],
- case docb_main:process(File, Opts) of
- errors -> error;
- ok -> ok
- end;
- Error -> % {error, {badopt,Term}}
- Error
- end;
- false ->
- {error, badfile}
- end.
-
-parse(RawOpts) ->
- parse(RawOpts, []).
-
-%% Officially supported options
-
-parse([{html_mod,Module} | RawOpts], Opts) when is_atom(Module) ->
- parse(RawOpts, [{html_mod,Module} | Opts]);
-parse([{outdir,Dir} | RawOpts], Opts) when is_list(Dir) ->
- parse(RawOpts, [{outdir,Dir} | Opts]);
-parse([{number,N} | RawOpts], Opts) when is_integer(N) ->
- parse(RawOpts, [{number,integer_to_list(N)} | Opts]);
-parse([{number,Nstr} | RawOpts], Opts) -> % list when called from script
- parse(RawOpts, [{number,Nstr} | Opts]);
-parse([{ptype,Type} | RawOpts], Opts) when Type==unix;
- Type==windows ->
- parse(RawOpts, [{ptype,atom_to_list(Type)} | Opts]);
-parse([{ptype,Type} | RawOpts], Opts) -> % list when called from script
- parse(RawOpts, [{ptype,Type} | Opts]);
-parse([silent | RawOpts], Opts) ->
- put(option_silent, true),
- parse(RawOpts, [silent | Opts]);
-parse([{top,Index} | RawOpts], Opts) when is_list(Index) ->
- parse(RawOpts, [{top,Index} | Opts]);
-parse([{vsn,Vsn} | RawOpts], Opts) when is_list(Vsn) ->
- parse(RawOpts, [{vsn,Vsn} | Opts]);
-
-parse([{term_defs,File} | RawOpts], Opts) when is_list(File) ->
- Opts2 = get_defs(term, File, Opts),
- parse(RawOpts, Opts2);
-parse([{cite_defs,File} | RawOpts], Opts) when is_list(File) ->
- Opts2 = get_defs(cite, File, Opts),
- parse(RawOpts, Opts2);
-
-%% OTP internal options (SGML and PDF support etc.)
-
-parse([html | RawOpts], Opts) ->
- parse(RawOpts, [html | Opts]);
-parse([latex | RawOpts], Opts) ->
- parse(RawOpts, [latex | Opts]);
-parse([{man,Level} | RawOpts], Opts) -> % Level = 1..9
- parse(RawOpts, [{man,Level} | Opts]);
-
-parse([{booksty,StyFile} | RawOpts], Opts) -> % "otpA4" | "otpBOOK"
- parse(RawOpts, [{booksty,StyFile} | Opts]);
-parse([{includepath,Dir} | RawOpts], Opts) ->
- parse(RawOpts, [{includepath,Dir} | Opts]);
-parse([showpaths | RawOpts], Opts) ->
- parse(RawOpts, [showpaths | Opts]);
-parse([straight | RawOpts], Opts) ->
- parse(RawOpts, [straight | Opts]);
-parse([{ent,Ent} | RawOpts], Opts) ->
- parse(RawOpts, [{ent,Ent} | Opts]);
-
-%% Undocumented options
-
-parse([{name, Name} | RawOpts], Opts) ->
- parse(RawOpts, [{name, Name} | Opts]);
-parse([framework_only | RawOpts], Opts) ->
- parse(RawOpts, [framework_only | Opts]);
-parse([kwicindex_only | RawOpts], Opts) ->
- parse(RawOpts, [kwicindex_only | Opts]);
-
-parse([], Opts) ->
- {ok, Opts};
-parse([Opt | _RawOpts], _Opts) ->
- {error, {badopt, Opt}}.
-
-%% Type = term | cite
-get_defs(Type, File, Opts) ->
- Key = {defs,Type},
- {PrevDefs, Opts2} =
- case lists:keyfind(Key, 1, Opts) of
- {_, Defs0} ->
- {Defs0, lists:keydelete(Key, 1, Opts)};
- false ->
- {[], Opts}
- end,
- NewDefs = case file:consult(File) of
- {ok, [DefL]} when is_list(DefL) ->
- DefL;
- {ok, _Terms} ->
- docb_util:message(error,
- "Skipping defs file ~s, does "
- "not contain one list", [File]),
- [];
- {error, Error} ->
- Expl = lists:flatten(file:format_error(Error)),
- docb_util:message(error,
- "Skipping defs file ~s, ~s",
- [File, Expl]),
- []
- end,
- [{Key,PrevDefs++NewDefs} | Opts2].
-
-
diff --git a/lib/docbuilder/src/docb_util.erl b/lib/docbuilder/src/docb_util.erl
deleted file mode 100644
index 9b2eec7733..0000000000
--- a/lib/docbuilder/src/docb_util.erl
+++ /dev/null
@@ -1,237 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--module(docb_util).
-
--export([version/0, old_docb_dir/0, dtd_dir/0]).
--export([html_snippet/2, html_snippet/3]).
--export([lookup_option/2, lookup_option/3, lookup_options/2,
- an_option/2]).
--export([outfile/3, full_file_name/4]).
--export([message/2, message/3]).
--export([ltrim/1, rtrim/1, trim/1]).
--export([join/2]).
--export([fknidx/2]).
-
--include("docb_util.hrl").
-
-%%--DocBuilder info-----------------------------------------------------
-
-%% version() -> string()
-%% Returns the DocBuilder application version.
-version() ->
- DocbDir = code:lib_dir(docbuilder),
- case string:tokens(filename:basename(DocbDir), "-") of
- [_, Vsn] -> Vsn;
- _ -> "unknown"
- end.
-
-%% old_docb_dir() -> string()
-%% Returns the root directory of Old_DocBuilder (OTP internal).
-old_docb_dir() ->
- "/home/otp/sgml/docb".
-
-%% dtd_dir() -> string()
-%% Returns the directory where the XML DTDs are located.
-dtd_dir() ->
- DocbDir = code:lib_dir(docbuilder),
- filename:join(DocbDir, "dtd").
-
-%%--User defined HTML snippets------------------------------------------
-
-%% html_snippet(What, Opts) -> HTML
-%% html_snippet(What, Arg, Opts) -> HTML
-%% What = head | seealso
-%% HTML = string()
-html_snippet(What, Opts) ->
- case lookup_option(html_mod, Opts) of
- false -> "";
- Module ->
- case catch Module:What() of
- HTML when is_list(HTML) ->
- HTML;
- {'EXIT', {undef, _}} ->
- "";
- {'EXIT', Reason} ->
- message(warning,
- "Callback function ~p:~p() => ~p",
- [Module, What, Reason]),
- "";
- Other ->
- message(warning,
- "Callback function ~p:~p() => ~p",
- [Module, What, Other]),
- ""
- end
- end.
-html_snippet(What, Arg, Opts) ->
- case lookup_option(html_mod, Opts) of
- false -> "";
- Module ->
- case catch Module:What(Arg) of
- HTML when is_list(HTML) ->
- HTML;
- {'EXIT', {undef, _}} ->
- "";
- {'EXIT', Reason} ->
- message(warning,
- "Callback function ~p:~p(~p) => ~p",
- [Module, What, Arg, Reason]),
- "";
- Other ->
- message(warning,
- "Callback function ~p:~p(~p) => ~p",
- [Module, What, Arg, Other]),
- ""
- end
- end.
-
-%%--Option utilities----------------------------------------------------
-
-%% Opts = [{Opt,Value} | Opt]
-
-%% lookup_option(Opt, Opts) -> Value | false
-lookup_option(Opt, Opts) ->
- case lists:keyfind(Opt, 1, Opts) of
- {Opt,Value} -> Value;
- false -> false
- end.
-
-%% lookup_option(Opt, Opts, DefaultValue) -> Value | DefaultValue
-lookup_option(Opt, Opts, DefaultValue) ->
- case lookup_option(Opt,Opts) of
- false -> DefaultValue;
- Value -> Value
- end.
-
-%% lookup_options(Opt, Opts) -> [Value]
-%% Used when the same option can be defined several times and returns
-%% the (possibly empty) list of values.
-lookup_options(Opt, Opts) ->
- [V || {O, V} <- Opts, O == Opt].
-
-%% an_option(Opt, Opts) -> bool()
-an_option(Opt, Opts) ->
- lists:member(Opt, Opts).
-
-%%--File handling-------------------------------------------------------
-
-%% outfile(File0, Extension, Opts) -> File
-%% Build the full filename for where to place a resulting file.
-outfile(File0, Extension, Opts) ->
- File =
- case regexp:match(File0, "[^/]*\$") of
- {match,Start,Length} ->
- string:substr(File0, Start, Length);
- _ ->
- File0
- end,
- full_file_name(File, Extension, outdir, Opts).
-
-%% full_file_name(File, Extension, What, Opts) -> File'
-%% File = string()
-%% What = outdir | includepath
-%% Prepend the full path name.
-full_file_name(File, Extension, What, Opts) ->
- Path = lookup_option(What, Opts, ""),
- full_file_name(File, Extension, Path).
-
-full_file_name(File0, Extension, Path) ->
- File = case filename:extension(File0) of
- Extension -> File0;
- _ -> File0++Extension
- end,
-
- case File of
- [$/|_] -> File;
- [$~|_] -> File;
- _ when Path=/="" -> filename:join(Path, File);
- _ -> File
- end.
-
-%%--Messages to the user------------------------------------------------
-
-%% message(Class, Format)
-%% message(Class, Format, Values) -> ok
-%% Class = info | warning | error
-%% Format, Values -- as in io:format/2
-%% Prints a warning or error message.
-%% Call as util:message(warning, "~w is undefined", [foo]).
-message(Class, Format) ->
- message(Class, Format, []).
-message(Class, Format, Values) ->
- Prefix = case Class of
- info -> "";
- warning -> "*** Warning: ";
- error -> "*** Error: "
- end,
- case get(option_silent) of
- true when Class==warning ->
- ok;
- _ ->
- io:format(Prefix, []),
- io:format(Format, Values),
- io:nl()
- end.
-
-%%--String handling-----------------------------------------------------
-
-%% ltrim(Str) -> Str'
-%% rtrim(Str) -> Str'
-%% trim(Str) -> Str'
-%% Strips whitespace from left, right or both.
-ltrim(Str) ->
- lists:dropwhile(fun white_space/1, Str).
-rtrim(Str) ->
- lists:reverse(ltrim(lists:reverse(Str))).
-trim(Str) ->
- rtrim(ltrim(Str)).
-
-white_space($ ) -> true;
-white_space(C) when C<$ -> true;
-white_space($\n) -> true;
-white_space($\t) -> true;
-white_space(_) -> false.
-
-%% join(Strings, With) -> string()
-join([H1, H2| T], S) ->
- H1 ++ S ++ join([H2| T], S);
-join([H], _) ->
- H;
-join([], _) ->
- [].
-
-%%--Other---------------------------------------------------------------
-
-%% fknidx(FNdef0, Fn_arity_sep) -> string()
-%% Get me the function name and arity.
-fknidx(FNdef0, Fn_arity_sep) ->
- FNdef = string:strip(FNdef0),
- case string:tokens(FNdef,"(") of
- [FNdef] ->
- %% No parentheses, assume variable: remove nl:s at end,
- %% and strip blanks.
- string:strip(string:strip(FNdef, right, $\n));
- [Name0|Args0] ->
- [Args1|_] = string:tokens(string:strip(hd(Args0)), "-"),
- Arity = case Args1 of
- [$)|_] -> 0;
- _ ->
- length(string:tokens(Args1, ","))
- end,
- string:strip(Name0)++Fn_arity_sep++integer_to_list(Arity)
- end.
diff --git a/lib/docbuilder/src/docb_util.hrl b/lib/docbuilder/src/docb_util.hrl
deleted file mode 100644
index 01ef3f7fca..0000000000
--- a/lib/docbuilder/src/docb_util.hrl
+++ /dev/null
@@ -1,34 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
-
-%%% For character conversion
-
--record(in_opts, {expand_entities=false,
- encode_filter = fun(X) -> X end}).
--record(out_opts, {escape_chars=false,
- remove_nl=false,
- delete_trailing_whitespace=false,
- delete_trailing_nl=false,
- compress_white_space=false,
- escape_filter = fun(X) -> X end}).
-
-
--define(pcdata_IN, #in_opts{expand_entities=true}).
--define(rcdata_IN, #in_opts{expand_entities=true}).
--define(cdata_IN, #in_opts{}).
-
diff --git a/lib/docbuilder/src/docb_xmerl_tree_cb.erl b/lib/docbuilder/src/docb_xmerl_tree_cb.erl
deleted file mode 100644
index bc62069230..0000000000
--- a/lib/docbuilder/src/docb_xmerl_tree_cb.erl
+++ /dev/null
@@ -1,343 +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 expressed or implied. See
-%% the Licence for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson AB.
-%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
-%% All Rights Reserved.��
-%%
-%% $Id$
-%%
--module(docb_xmerl_tree_cb).
-
-%% This is the XMerL callback module for exporting XML to the internal
-%% tree format used by DocBuilder.
-%% {Doc, _Misc} = xmerl_scan:file("file.xml", [{validation,true}])
-%% Tree = xmerl:export([Doc], docb_xmerl_tree_cb)
-
--export(['#xml-inheritance#'/0]).
-
--export(['#root#'/4,
- '#text#'/1,
- '#element#'/5]).
--include("xmerl.hrl").
-
-%%--Functions used by xmerl---------------------------------------------
-
-'#xml-inheritance#'() ->
- [].
-
-'#root#'(Data, _Attrs, [], _E) ->
- Data.
-
-'#text#'(Text) ->
- Text2 = strip_leading_blanks(Text),
-%% before
-%% case Text2 of
-%% [$\n|T] ->
-%% case is_empty(T) of
-%% true -> [];
-%% false -> {pcdata, [], nl(Text2)}
-%% end;
-%%
-%% _ ->
-%% {pcdata, [], nl(Text2)}
-%% end.
-%% after
- {pcdata, [], nl(Text2)}.
-
-'#element#'(Tag, Data, Attrs, Parents, _E) when Tag==pre; Tag==code ->
- [H|T] = reinsert_nl(Data),
- NewData = [strip_nl(H)|T],
- NewData2 = case Tag of
- code ->
- fix_single_pcdata(NewData);
- pre ->
- NewData
- end,
- {Tag, attrs(get_dtd(Parents), Tag, Attrs), NewData2};
-'#element#'(Tag, Data, Attrs, Parents, _E) ->
- NewData = case tag_content(Tag) of
- no_pcdata -> % remove all pcdata
- [Dat||
- Dat <- Data,
- begin
- Fun = fun({pcdata,_,_}) -> false;
- (_) -> true end,
- Fun(Dat)
- end];
- single_pcdata when length(Data)>1 ->
- %% merge several pcdata's into one single pcdata
- fix_single_pcdata(Data);
- _ ->
- lists:flatten(Data)
- end,
- {Tag, attrs(get_dtd(Parents), Tag, Attrs), NewData}.
-
-%%--Internal functions--------------------------------------------------
-
-%% is_empty(Str) -> bool()
-%% Returns true if the string Str only contains blanks, tabs and
-%% newlines, false otherwise.
-%% is_empty("\n" ++ Text) ->
-%% is_empty(Text);
-%% is_empty("\t" ++ Text) ->
-%% is_empty(Text);
-%% is_empty(" " ++ Text) ->
-%% is_empty(Text);
-%% is_empty("") ->
-%% true;
-%% is_empty(_) ->
-%% false.
-
-%% reinsert_nl(L1) -> L2
-%% Workaround for <pre>: Normally empty lines are ignored. However,
-%% Xmerl splits lines whenever it encounters an entity. In the case of
-%% <pre>, this may lead to that we ignores what we think is an empty
-%% line but is actually a line break that should be kept, for example
-%% in this case:
-%% <pre>
-%% <input>some command</input> <-- this line break is lost!
-%% &lt;some result&gt;
-%% </pre>
-%% This function reinserts line breaks where necessary.
-reinsert_nl([[]|T]) ->
- [{pcdata,[],"\\n"} | reinsert_nl(T)];
-reinsert_nl([H|T]) ->
- [H | reinsert_nl(T)];
-reinsert_nl([]) ->
- [].
-
-%% sgmls treats line breaks in a way that DocBuilder relies on and
-%% which must be imitated here. Replace all "\n" with "\\n" and add
-%% "\n" to the end of each text element.
-nl("") ->
- "\n";
-nl("\n"++Text) ->
- "\\n"++nl(Text);
-nl([Ch|Text]) ->
- [Ch|nl(Text)].
-
-
-%% strip_leading_blanks(Str) -> Str
-%% Leading spaces and tabs before a newline are always redundant
-%% and are therefore stripped of here
-%% If no newline is found the original string is returned unchanged
-
-strip_leading_blanks(Str) ->
- strip_leading_blanks(Str,Str).
-
-strip_leading_blanks([],Str) ->
- Str;
-strip_leading_blanks([$\s|T],Str) ->
- strip_leading_blanks(T,Str);
-strip_leading_blanks([$\t|T],Str) ->
- strip_leading_blanks(T,Str);
-strip_leading_blanks(Rest=[$\n|_],_) ->
- Rest;
-strip_leading_blanks(_,Str) ->
- Str.
-
-%% strip_nl(Str) -> Str
-%% The XMerL scan will often result in the contents of <pre> or <code>
-%% starting with a newline, as the format is normally:
-%% <pre>
-%% ..contents..
-%% </pre>
-%% However, this newline must be removed, or the resulting HTML will be
-%% <pre>
-%%
-%% ..content..
-%% </pre>
-strip_nl({pcdata,[],"\\n"++Str}) -> {pcdata,[],Str};
-strip_nl(E) -> E.
-
-get_dtd([]) ->
- none;
-get_dtd(Parents) ->
- {DTD, _} = lists:last(Parents),
- DTD.
-
-%% attrs(DTD, Tag, GivenAttrs) -> AllAttrs
-%% DTD = Tag = atom() DTD and tag name
-%% GivenAttrs = [#xmlAttribute{}]
-%% AllAttrs = [{Name, Type, Val}]
-%% Name = string() (uppercase) Example: "VALIGN"
-%% Type = "CDATA" | "TOKEN"
-%% Val = string() (uppercase if type is "TOKEN", as-is otherwise)
-%% The XMerL scanning of <file>.xml renders only the given attributes.
-%% However, DocBuilder needs also the optional attributes (which not
-%% necessarily have been given), so we add them here, using the default
-%% values according to the DTDs.
-%% NOTE: Uses the information from the DTDs. That is, if some change is
-%% done to the DTDs, also this file must be updated. Ideally, the DTDs
-%% should be parsed automatically in some way.
-%% It can also be noted that this check is superfluous in the case where
-%% all attributes are required (except that the attributes are sorted
-%% in the same order as in the DTD) and where an optional attribute has
-%% type "CDATA" as no sensible default value can be specified in this
-%% case.
-attrs(DTD, Tag, GivenAttrs) ->
- merge_attrs(Tag, default_attrs(DTD, Tag), GivenAttrs).
-
-merge_attrs(Tag, [{NameA, Type, DefVal}|Default], GivenAttrs) ->
- Val = case lists:keyfind(NameA, #xmlAttribute.name, GivenAttrs) of
- #xmlAttribute{value=Val0} -> Val0;
- false -> DefVal
- end,
- Attr = {attr_name(NameA), Type, attr_val(Type, Val)},
- [Attr | merge_attrs(Tag, Default, GivenAttrs)];
-merge_attrs(_Tag, [], _GivenAttrs) ->
- [].
-
-attr_name(Atom) ->
- string:to_upper(atom_to_list(Atom)).
-
-attr_val("CDATA", Val) -> Val;
-attr_val("TOKEN", Val) -> string:to_upper(Val).
-
-%% Given the DTD and element tag, return a list [{Name, Value}] where
-%% Name (atom) is the name of each possible attribute and
-%% Value (lowercase string) its default value.
-default_attrs(_, cell) ->
- [{align, "TOKEN", "left"},
- {valign, "TOKEN", "middle"}];
-default_attrs(_, cite) ->
- [{id, "CDATA", ""}]; % required
-default_attrs(_, code) ->
- [{type, "TOKEN", "none"}];
-default_attrs(_, codeinclude) ->
- [{file, "CDATA", ""}, % required
- {tag, "CDATA", ""},
- {type, "TOKEN", "none"}];
-default_attrs(book, contents) ->
- [{level, "TOKEN", "2"}];
-default_attrs(_, erleval) ->
- [{expr, "CDATA", ""}]; % required
-default_attrs(report, erlinclude) ->
- [{file, "CDATA", ""}, % required
- {tag, "CDATA", ""}]; % required
-default_attrs(_, fascicule) ->
- [{file, "CDATA", ""}, % required
- {href, "CDATA", ""}, % required
- {entry, "TOKEN", "no"}];
-default_attrs(book, header) ->
- [{titlestyle, "TOKEN", "normal"}];
-default_attrs(_, image) ->
- [{file, "CDATA", ""}]; % required
-default_attrs(_, include) ->
- [{file, "CDATA", ""}]; % required
-default_attrs(report, index) ->
- [{txt, "CDATA", ""}]; % required
-default_attrs(_, list) ->
- [{type, "TOKEN", "bulleted"}];
-default_attrs(_, marker) ->
- [{id, "CDATA", ""}]; % required
-default_attrs(book, onepart) ->
- [{lift, "TOKEN", "no"}];
-default_attrs(book, parts) ->
- [{lift, "TOKEN", "no"}];
-default_attrs(_, path) ->
- [{unix, "CDATA", ""},
- {windows, "CDATA", ""}];
-default_attrs(_, seealso) ->
- [{marker, "CDATA", ""}]; % required
-default_attrs(report, table) ->
- [{width, "CDATA", "0"},
- {colspec, "CDATA", ""}];
-default_attrs(_, table) ->
- [{align, "TOKEN", "center"}];
-default_attrs(_, term) ->
- [{id, "CDATA", ""}]; % required
-default_attrs(book, theheader) ->
- [{tag, "TOKEN", "none"}];
-default_attrs(bookinsidecover, theheader) ->
- [{tag, "TOKEN", "none"}];
-default_attrs(_, url) ->
- [{href, "CDATA", ""}]; % required
-default_attrs(_, _) -> [].
-
-%%--Single PCDATA broken into several fix-------------------------------
-
-%% When text contains an entity, then XMERL splits it into two
-%% PCDATA elements, the second starting with the entity.
-%%
-%% Example:
-%% Magnus Fr�berg => [{pcdata,[],"Magnus Fr\n"},{pcdata,[],"�berg\n"}]
-%%
-%% This is not handled by DocBuilder which expects many tags, for
-%% example title and aname, to contain a single PCDATA element. (That
-%% is also what nsgmls returned.)
-
-fix_single_pcdata([{pcdata,[],Str1}, {pcdata,[],Str2}|T]) ->
- fix_single_pcdata([{pcdata,[],Str1++Str2}|T]);
-fix_single_pcdata(FixedData) ->
- FixedData.
-
-tag_content(aname) -> single_pcdata;
-tag_content(app) -> single_pcdata;
-tag_content(approved) -> single_pcdata;
-tag_content(appsummary) -> single_pcdata;
-tag_content(b) -> single_pcdata;
-tag_content(c) -> single_pcdata;
-tag_content(cauthor) -> single_pcdata;
-tag_content(cell) -> mixed_content;
-tag_content(checked) -> single_pcdata;
-tag_content(chowpublished) -> single_pcdata;
-tag_content(code) -> single_pcdata; % mixed?
-tag_content(com) -> single_pcdata;
-tag_content(comsummary) -> single_pcdata;
-tag_content(copyright) -> mixed_content;
-tag_content(ctitle) -> single_pcdata;
-tag_content(d) -> mixed_content;
-tag_content(date) -> single_pcdata;
-tag_content(docno) -> single_pcdata;
-tag_content(em) -> mixed_content;
-tag_content(email) -> single_pcdata;
-tag_content(fascicule) -> single_pcdata;
-tag_content(file) -> single_pcdata;
-tag_content(filesummary) -> single_pcdata;
-tag_content(fsummary) -> mixed_content;
-tag_content(headline) -> single_pcdata;
-tag_content(holder) -> single_pcdata;
-tag_content(i) -> single_pcdata;
-tag_content(icaption) -> single_pcdata;
-tag_content(id) -> single_pcdata;
-tag_content(input) -> mixed_content;
-tag_content(item) -> mixed_content;
-tag_content(legalnotice) -> single_pcdata;
-tag_content(lib) -> single_pcdata;
-tag_content(libsummary) -> single_pcdata;
-tag_content(module) -> single_pcdata;
-tag_content(modulesummary) -> single_pcdata;
-tag_content(name) -> single_pcdata;
-tag_content(nametext) -> single_pcdata;
-tag_content(p) -> mixed_content;
-tag_content(pagetext) -> single_pcdata;
-tag_content(path) -> single_pcdata; % mixed?
-tag_content(pre) -> mixed_content;
-tag_content(prepared) -> single_pcdata;
-tag_content(resp) -> single_pcdata;
-tag_content(responsible) -> single_pcdata;
-tag_content(ret) -> single_pcdata;
-tag_content(rev) -> single_pcdata;
-tag_content(seealso) -> single_pcdata; % mixed?
-tag_content(shortdef) -> single_pcdata;
-tag_content(shorttitle) -> single_pcdata;
-tag_content(tag) -> mixed_content;
-tag_content(tcaption) -> single_pcdata;
-tag_content(termdef) -> single_pcdata;
-tag_content(title) -> single_pcdata;
-tag_content(url) -> single_pcdata; % mixed
-tag_content(v) -> single_pcdata;
-tag_content(year) -> single_pcdata;
-tag_content(_) -> no_pcdata.
-
-
diff --git a/lib/docbuilder/src/docb_xmerl_xml_cb.erl b/lib/docbuilder/src/docb_xmerl_xml_cb.erl
deleted file mode 100644
index 089b8f0c7d..0000000000
--- a/lib/docbuilder/src/docb_xmerl_xml_cb.erl
+++ /dev/null
@@ -1,88 +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 expressed or implied. See
-%% the Licence for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson AB.
-%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
-%% All Rights Reserved.��
-%%
-%% $Id$
-%%
--module(docb_xmerl_xml_cb).
-
-%% This is the callback module for exporting XHTML to a DocBuilder
-%% erlref or chapter document in XML format.
-%% See docb_edoc_xml_cb.erl for further information.
-%%
-%% The origin of this file is the xmerl module xmerl_otpsgml.erl
-%% written by Ulf Wiger and Richard Carlsson.
-
--export(['#xml-inheritance#'/0]).
-
--export(['#root#'/4,
- '#element#'/5,
- '#text#'/1]).
-
--include("xmerl.hrl").
-
-'#xml-inheritance#'() ->
- [xmerl_xml].
-
-'#root#'(Data, _Attrs, [], _E) ->
- ["<",DTD,">"] = hd(hd(Data)),
- ["<?xml version=\"1.0\" encoding=\"latin1\" ?>\n",
- "<!DOCTYPE "++DTD++" SYSTEM \""++DTD++".dtd\">\n",
- Data].
-
-'#element#'(Tag, Data, Attrs, _Parents, _E) ->
- {NewTag, NewAttrs} = convert_tag(Tag, Attrs),
- xmerl_lib:markup(NewTag, NewAttrs, Data).
-
-'#text#'(Text) ->
- xmerl_lib:export_text(Text).
-
-%% Utility functions
-
-convert_tag(a, [Attr]) ->
- case Attr#xmlAttribute.name of
- href ->
- Val = Attr#xmlAttribute.value,
- case is_url(Val) of
- true ->
- {url, [Attr]};
- false ->
- {seealso, [Attr#xmlAttribute{name=marker}]}
- end;
- name ->
- {marker, [Attr#xmlAttribute{name=id}]}
- end;
-convert_tag(b, Attrs) -> {em, Attrs};
-convert_tag(blockquote, Attrs) -> {quote, Attrs};
-convert_tag(code, Attrs) -> {c, Attrs};
-convert_tag(dd, Attrs) -> {item, Attrs};
-convert_tag(dl, Attrs) -> {taglist, Attrs};
-convert_tag(dt, Attrs) -> {tag, Attrs};
-convert_tag(li, Attrs) -> {item, Attrs};
-convert_tag(ol, Attrs) -> {list, Attrs};
-convert_tag(strong, Attrs) -> {em, Attrs};
-convert_tag(td, Attrs) -> {cell, Attrs};
-convert_tag(tr, Attrs) -> {row, Attrs};
-convert_tag(tt, Attrs) -> {c, Attrs};
-convert_tag(ul, Attrs) -> {list, Attrs};
-convert_tag(underline, Attrs) -> {em, Attrs};
-convert_tag(Tag, Attrs) -> {Tag, Attrs}.
-
-is_url("http:"++_) -> true;
-is_url("../"++_) -> true;
-is_url(FileRef) ->
- case filename:extension(FileRef) of
- "" -> false; % no extension = xml file, DocBuilder resolves
- _Ext -> true % extension, DocBuilder must not resolve
- end.
diff --git a/lib/docbuilder/src/docb_xml_check.erl b/lib/docbuilder/src/docb_xml_check.erl
deleted file mode 100644
index 5912e22e7b..0000000000
--- a/lib/docbuilder/src/docb_xml_check.erl
+++ /dev/null
@@ -1,45 +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 expressed or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
-%% Utvecklings AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
--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
-%% If XML validation fails for a file, the error information from
-%% Xmerl is printed to terminal and the function returns error.
-validate(File0) ->
- File = case filename:extension(File0) of
- ".xml" -> File0;
- _ -> File0++".xml"
- end,
- case filelib:is_regular(File) of
- true ->
- DtdDir = docb_util:dtd_dir(),
- case catch xmerl_scan:file(File, [{validation,true},
- {fetch_path,[DtdDir]}]) of
- {'EXIT', Error} ->
- io:format("~p~n", [Error]),
- error;
- {_Doc, _Misc} ->
- ok
- end;
- false ->
- {error, badfile}
- end.
diff --git a/lib/docbuilder/src/docbuilder.app.src b/lib/docbuilder/src/docbuilder.app.src
deleted file mode 100644
index 64c4770964..0000000000
--- a/lib/docbuilder/src/docbuilder.app.src
+++ /dev/null
@@ -1,37 +0,0 @@
-{application, docbuilder,
- [{description, "Tool for building HTML documentation"},
- {vsn, "%VSN%"},
- {modules, [docb_edoc_xml_cb,
- docb_gen,
- docb_html,
- docb_html_layout,
- docb_html_ref,
- docb_html_util,
- docb_html_util_iso,
- docb_main,
- docb_pretty_format,
- docb_tr_application2html,
- docb_tr_appref2html,
- docb_tr_chapter2html,
- docb_tr_cite2html,
- docb_tr_comref2html,
- docb_tr_cref2html,
- docb_tr_erlref2html,
- docb_tr_fileref2html,
- docb_tr_first2html,
- docb_tr_index2html,
- docb_tr_part2html,
- docb_tr_refs2kwic,
- docb_tr_report2html,
- docb_tr_term2html,
- docb_transform,
- docb_util,
- docb_xmerl_tree_cb,
- docb_xmerl_xml_cb,
- docb_xml_check
- ]},
- {registered, []},
- {applications, [kernel, stdlib]},
- {env, []}]}.
-
-
diff --git a/lib/docbuilder/src/docbuilder.appup.src b/lib/docbuilder/src/docbuilder.appup.src
deleted file mode 100644
index 54a63833e6..0000000000
--- a/lib/docbuilder/src/docbuilder.appup.src
+++ /dev/null
@@ -1 +0,0 @@
-{"%VSN%",[],[]}.
diff --git a/lib/docbuilder/test/Makefile b/lib/docbuilder/test/Makefile
deleted file mode 100644
index 53dff193dc..0000000000
--- a/lib/docbuilder/test/Makefile
+++ /dev/null
@@ -1,80 +0,0 @@
-# ``The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved via the world wide web at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-MODULES = \
- docb_SUITE
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-INSTALL_PROGS= $(TARGET_FILES)
-
-EMAKEFILE=Emakefile
-
-SPEC_FILES=
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/docb_test
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
-
-EBIN = .
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-.PHONY: make_emakefile
-
-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) $(SPEC_FILES) docb.cover $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
-
-release_docs_spec:
-
-
diff --git a/lib/docbuilder/test/docb.cover b/lib/docbuilder/test/docb.cover
deleted file mode 100644
index 80bab6eba7..0000000000
--- a/lib/docbuilder/test/docb.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,docbuilder,details}
-
diff --git a/lib/docbuilder/test/docb_SUITE.erl b/lib/docbuilder/test/docb_SUITE.erl
deleted file mode 100644
index d286824539..0000000000
--- a/lib/docbuilder/test/docb_SUITE.erl
+++ /dev/null
@@ -1,50 +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$
-%%
--module(docb_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2,html/1]).
-
--include_lib("common_test/include/ct.hrl").
-
--include_lib("kernel/include/file.hrl").
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
-[html].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-html(suite) -> [];
-html(Config) when is_list(Config) ->
- ok.
-
diff --git a/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml b/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml
deleted file mode 100755
index b7f6f5376e..0000000000
--- a/lib/docbuilder/test/docb_SUITE_data/cdata_problem.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-<chapter>
- <header>
- <title>�Docbook&ouml; bug</title>
- <prepared>Matthias Lang</prepared>
-<docno></docno>
-<date>2008-03-31</date>
- <rev>1.0</rev>
- </header>
-
-<section><title>This is a title</title>
- <code><![CDATA[
- This works
- ]]></code>
-
- <code><![CDATA[
- This does not
- ]]> </code>
-</section>
-</chapter>
-
diff --git a/lib/docbuilder/vsn.mk b/lib/docbuilder/vsn.mk
deleted file mode 100644
index 6df438a537..0000000000
--- a/lib/docbuilder/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-DOCB_VSN = 0.9.8.11
diff --git a/lib/docbuilder/xsd/application.xsd b/lib/docbuilder/xsd/application.xsd
deleted file mode 100755
index eb666cb6c7..0000000000
--- a/lib/docbuilder/xsd/application.xsd
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.xsd"/>
- <xs:include schemaLocation="common.header.xsd"/>
- <xs:element name="application">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element minOccurs="0" ref="description"/>
- <xs:element maxOccurs="unbounded" ref="include"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="description">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="include">
- <xs:complexType>
- <xs:attribute name="file" use="required"/>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/appref.xsd b/lib/docbuilder/xsd/appref.xsd
deleted file mode 100755
index b63839e494..0000000000
--- a/lib/docbuilder/xsd/appref.xsd
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.refs.xsd"/>
- <!-- Structure -->
- <xs:element name="appref">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element ref="app"/>
- <xs:element ref="appsummary"/>
- <xs:element ref="description"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="section"/>
- <xs:element ref="funcs"/>
- </xs:choice>
- <xs:element ref="authors"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="app" type="xs:string"/>
- <xs:element name="appsummary" type="xs:string"/>
- <!--
- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd
- -->
- <xs:element name="name" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/book.xsd b/lib/docbuilder/xsd/book.xsd
deleted file mode 100755
index b47962263a..0000000000
--- a/lib/docbuilder/xsd/book.xsd
+++ /dev/null
@@ -1,292 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.xsd"/>
- <xs:include schemaLocation="common.table.xsd"/>
- <xs:element name="book">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element minOccurs="0" ref="insidecover"/>
- <xs:element ref="pagetext"/>
- <xs:element ref="preamble"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="applications"/>
- <xs:element ref="parts"/>
- <xs:element ref="headline"/>
- <xs:element ref="pagetext"/>
- </xs:choice>
- <xs:sequence>
- <xs:element minOccurs="0" ref="listoffigures"/>
- <xs:element minOccurs="0" ref="listoftables"/>
- <xs:element minOccurs="0" ref="listofterms"/>
- <xs:element minOccurs="0" ref="bibliography"/>
- <xs:element minOccurs="0" ref="index"/>
- </xs:sequence>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="header">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="title"/>
- <xs:element ref="prepared"/>
- <xs:element minOccurs="0" ref="responsible"/>
- <xs:element ref="docno"/>
- <xs:element minOccurs="0" ref="approved"/>
- <xs:element minOccurs="0" ref="checked"/>
- <xs:element ref="date"/>
- <xs:element ref="rev"/>
- <xs:element minOccurs="0" ref="file"/>
- <xs:element minOccurs="0" ref="abbreviation"/>
- </xs:sequence>
- <xs:attribute name="titlestyle" default="normal">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="special"/>
- <xs:enumeration value="normal"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="title">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="prepared">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="responsible">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="docno">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="approved">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="checked">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="date">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="rev">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="file">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="abbreviation">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="br"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="pagetext" type="xs:string"/>
- <xs:element name="preamble">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="preface"/>
- <xs:element minOccurs="0" ref="contents"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="preface">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="title"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- <xs:element ref="table"/>
- </xs:choice>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="insidecover">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="br"/>
- <xs:element ref="theheader"/>
- <xs:element ref="vfill"/>
- <xs:element ref="tt"/>
- <xs:element ref="bold"/>
- <xs:element ref="include"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="tt">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="br"/>
- <xs:element ref="theheader"/>
- <xs:element ref="vfill"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="bold">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="br"/>
- <xs:element ref="theheader"/>
- <xs:element ref="vfill"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="vfill">
- <xs:complexType/>
- </xs:element>
- <xs:element name="theheader">
- <xs:complexType>
- <xs:attribute name="tag" default="none">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="title"/>
- <xs:enumeration value="prepared"/>
- <xs:enumeration value="responsible"/>
- <xs:enumeration value="docno"/>
- <xs:enumeration value="approved"/>
- <xs:enumeration value="checked"/>
- <xs:enumeration value="date"/>
- <xs:enumeration value="rev"/>
- <xs:enumeration value="file"/>
- <xs:enumeration value="abbreviation"/>
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="applications">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="include"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="parts">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="title"/>
- <xs:element minOccurs="0" ref="description"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="include"/>
- <xs:element ref="onepart"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="lift" default="no">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="yes"/>
- <xs:enumeration value="no"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="headline" type="xs:string"/>
- <xs:element name="index">
- <xs:complexType/>
- </xs:element>
- <xs:element name="listoffigures">
- <xs:complexType/>
- </xs:element>
- <xs:element name="listoftables">
- <xs:complexType/>
- </xs:element>
- <xs:element name="listofterms">
- <xs:complexType/>
- </xs:element>
- <xs:element name="bibliography">
- <xs:complexType/>
- </xs:element>
- <xs:element name="contents">
- <xs:complexType>
- <xs:attribute name="level" default="2">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- <xs:enumeration value="2"/>
- <xs:enumeration value="3"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="onepart">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="title"/>
- <xs:element minOccurs="0" ref="description"/>
- <xs:element maxOccurs="unbounded" ref="include"/>
- </xs:sequence>
- <xs:attribute name="lift" default="no">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="yes"/>
- <xs:enumeration value="no"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="description">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="include">
- <xs:complexType>
- <xs:attribute name="file" use="required"/>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/chapter.xsd b/lib/docbuilder/xsd/chapter.xsd
deleted file mode 100755
index 4d89baa988..0000000000
--- a/lib/docbuilder/xsd/chapter.xsd
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.xsd"/>
- <xs:include schemaLocation="common.header.xsd"/>
- <xs:include schemaLocation="common.table.xsd"/>
- <xs:include schemaLocation="common.image.xsd"/>
- <!-- Structure -->
- <xs:element name="chapter">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- <xs:element ref="br"/>
- <xs:element ref="image"/>
- <xs:element ref="marker"/>
- <xs:element ref="table"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="section"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="section">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="marker"/>
- <xs:element ref="title"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- <xs:element ref="br"/>
- <xs:element ref="image"/>
- <xs:element ref="marker"/>
- <xs:element ref="table"/>
- <xs:element ref="section"/>
- </xs:choice>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/common.entities.xsd b/lib/docbuilder/xsd/common.entities.xsd
deleted file mode 100755
index 52a5d35179..0000000000
--- a/lib/docbuilder/xsd/common.entities.xsd
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"/>
diff --git a/lib/docbuilder/xsd/common.header.xsd b/lib/docbuilder/xsd/common.header.xsd
deleted file mode 100755
index bfee4b8bb4..0000000000
--- a/lib/docbuilder/xsd/common.header.xsd
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:element name="header">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="title"/>
- <xs:element minOccurs="0" ref="shorttitle"/>
- <xs:element ref="prepared"/>
- <xs:element minOccurs="0" ref="responsible"/>
- <xs:element ref="docno"/>
- <xs:element minOccurs="0" ref="approved"/>
- <xs:element minOccurs="0" ref="checked"/>
- <xs:element ref="date"/>
- <xs:element ref="rev"/>
- <xs:element minOccurs="0" ref="file"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="title" type="xs:string"/>
- <xs:element name="shorttitle" type="xs:string"/>
- <xs:element name="prepared" type="xs:string"/>
- <xs:element name="responsible" type="xs:string"/>
- <xs:element name="docno" type="xs:string"/>
- <xs:element name="approved" type="xs:string"/>
- <xs:element name="checked" type="xs:string"/>
- <xs:element name="date" type="xs:string"/>
- <xs:element name="rev" type="xs:string"/>
- <xs:element name="file" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/common.image.xsd b/lib/docbuilder/xsd/common.image.xsd
deleted file mode 100755
index 17054eb23c..0000000000
--- a/lib/docbuilder/xsd/common.image.xsd
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:element name="image">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="icaption">
- <xs:attribute name="file" use="required"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:complexType name="icaption">
- <xs:sequence>
- <xs:element ref="icaption"/>
- </xs:sequence>
- </xs:complexType>
- <xs:element name="icaption" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/common.refs.xsd b/lib/docbuilder/xsd/common.refs.xsd
deleted file mode 100755
index 58b450669d..0000000000
--- a/lib/docbuilder/xsd/common.refs.xsd
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- This file contains common stuff for the *ref.dtd files.
- Note that `name' is defined in each *ref.dtd.
--->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.xsd"/>
- <xs:include schemaLocation="common.header.xsd"/>
- <xs:element name="description">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="funcs">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="func"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="func">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="name"/>
- <xs:element ref="fsummary"/>
- <xs:element minOccurs="0" ref="type"/>
- <xs:element minOccurs="0" ref="desc"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <!-- ELEMENT name is defined in each ref dtd -->
- <xs:element name="fsummary">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="c"/>
- <xs:element ref="em"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="type">
- <xs:complexType>
- <xs:sequence maxOccurs="unbounded">
- <xs:element ref="v"/>
- <xs:element minOccurs="0" ref="d"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="v" type="xs:string"/>
- <xs:element name="d">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="c"/>
- <xs:element ref="em"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="desc">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="authors">
- <xs:complexType>
- <xs:sequence maxOccurs="unbounded">
- <xs:element ref="aname"/>
- <xs:element ref="email"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="aname" type="xs:string"/>
- <xs:element name="email" type="xs:string"/>
- <xs:element name="section">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="marker"/>
- <xs:element ref="title"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- </xs:choice>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/common.table.xsd b/lib/docbuilder/xsd/common.table.xsd
deleted file mode 100755
index cf63df4317..0000000000
--- a/lib/docbuilder/xsd/common.table.xsd
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:element name="table">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="row"/>
- <xs:element ref="tcaption"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="row">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="cell"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="cell">
- <xs:complexType mixed="true">
- <xs:group minOccurs="0" maxOccurs="unbounded" ref="inline"/>
- <xs:attribute name="align" default="left">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="valign" default="middle">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="top"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="bottom"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="tcaption" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/common.xsd b/lib/docbuilder/xsd/common.xsd
deleted file mode 100755
index 3d43390bd8..0000000000
--- a/lib/docbuilder/xsd/common.xsd
+++ /dev/null
@@ -1,212 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- This file contains common stuff for all dtds. -->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:element name="block" abstract="true"/>
- <xs:group name="inline">
- <xs:sequence>
- <xs:choice minOccurs="0">
- <xs:element ref="c"/>
- <xs:element ref="em"/>
- <xs:element ref="term"/>
- <xs:element ref="cite"/>
- <xs:element ref="br"/>
- <xs:element ref="path"/>
- <xs:element ref="seealso"/>
- <xs:element ref="url"/>
- <xs:element ref="marker"/>
- </xs:choice>
- </xs:sequence>
- </xs:group>
- <!-- XXX -->
- <xs:element name="p" substitutionGroup="block">
- <xs:complexType mixed="true">
- <xs:group minOccurs="0" maxOccurs="unbounded" ref="inline"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="pre" substitutionGroup="block">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="seealso"/>
- <xs:element ref="url"/>
- <xs:element ref="input"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="input">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="seealso"/>
- <xs:element ref="url"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="code" substitutionGroup="block">
- <xs:complexType mixed="true">
- <xs:attribute name="type" default="none">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="erl"/>
- <xs:enumeration value="c"/>
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="quote">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="p"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="warning">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="note">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="c" type="xs:string"/>
- <xs:element name="em">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="c"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <!-- XXX -->
- <xs:element name="term">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="termdef"/>
- </xs:sequence>
- <xs:attribute name="id" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="termdef" type="xs:string"/>
- <xs:element name="cite">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="citedef"/>
- </xs:sequence>
- <xs:attribute name="id" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="citedef">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="ctitle"/>
- <xs:element ref="cauthor"/>
- <xs:element ref="chowpublished"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="ctitle" type="xs:string"/>
- <xs:element name="cauthor" type="xs:string"/>
- <xs:element name="chowpublished" type="xs:string"/>
- <!-- XXX -->
- <xs:element name="br">
- <xs:complexType/>
- </xs:element>
- <!-- Path -->
- <xs:element name="path">
- <xs:complexType mixed="true">
- <xs:attribute name="unix" default=""/>
- <xs:attribute name="windows" default=""/>
- </xs:complexType>
- </xs:element>
- <!-- List -->
- <xs:element name="list" substitutionGroup="block">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="item"/>
- </xs:sequence>
- <xs:attribute name="type" default="bulleted">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ordered"/>
- <xs:enumeration value="bulleted"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="taglist" substitutionGroup="block">
- <xs:complexType>
- <xs:sequence maxOccurs="unbounded">
- <xs:element ref="tag"/>
- <xs:element ref="item"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="tag">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="c"/>
- <xs:element ref="em"/>
- <xs:element ref="seealso"/>
- <xs:element ref="url"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="item">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:group ref="inline"/>
- <xs:element ref="block"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <!-- References -->
- <xs:element name="seealso">
- <xs:complexType mixed="true">
- <xs:attribute name="marker" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="url">
- <xs:complexType mixed="true">
- <xs:attribute name="href" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="marker">
- <xs:complexType>
- <xs:attribute name="id" use="required"/>
- </xs:complexType>
- </xs:element>
- <!-- CodeInclude -->
- <xs:element name="codeinclude" substitutionGroup="block">
- <xs:complexType>
- <xs:attribute name="file" use="required"/>
- <xs:attribute name="tag" default=""/>
- <xs:attribute name="type" default="none">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="erl"/>
- <xs:enumeration value="c"/>
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <!-- ErlEval -->
- <xs:element name="erleval" substitutionGroup="block">
- <xs:complexType>
- <xs:attribute name="expr" use="required"/>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/comref.xsd b/lib/docbuilder/xsd/comref.xsd
deleted file mode 100755
index 61df4dd848..0000000000
--- a/lib/docbuilder/xsd/comref.xsd
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.refs.xsd"/>
- <xs:element name="comref">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element ref="com"/>
- <xs:element ref="comsummary"/>
- <xs:element ref="description"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="section"/>
- <xs:element ref="funcs"/>
- </xs:choice>
- <xs:element ref="authors"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="com" type="xs:string"/>
- <xs:element name="comsummary" type="xs:string"/>
- <!--
- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd
- -->
- <xs:element name="name" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/cref.xsd b/lib/docbuilder/xsd/cref.xsd
deleted file mode 100755
index f1cbeddfff..0000000000
--- a/lib/docbuilder/xsd/cref.xsd
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.refs.xsd"/>
- <xs:element name="cref">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element ref="lib"/>
- <xs:element ref="libsummary"/>
- <xs:element ref="description"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="section"/>
- <xs:element ref="funcs"/>
- </xs:choice>
- <xs:element ref="authors"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="lib" type="xs:string"/>
- <xs:element name="libsummary" type="xs:string"/>
- <!--
- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd
- -->
- <xs:element name="name">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="ret"/>
- <xs:element ref="nametext"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="ret" type="xs:string"/>
- <xs:element name="nametext" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/erlref.xsd b/lib/docbuilder/xsd/erlref.xsd
deleted file mode 100755
index f6011b7bea..0000000000
--- a/lib/docbuilder/xsd/erlref.xsd
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.refs.xsd"/>
- <xs:element name="erlref">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element ref="module"/>
- <xs:element ref="modulesummary"/>
- <xs:element ref="description"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="section"/>
- <xs:element ref="funcs"/>
- </xs:choice>
- <xs:element ref="authors"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="module" type="xs:string"/>
- <xs:element name="modulesummary" type="xs:string"/>
- <!--
- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd
- -->
- <xs:element name="name" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/fascicules.xsd b/lib/docbuilder/xsd/fascicules.xsd
deleted file mode 100755
index bfdb5bd604..0000000000
--- a/lib/docbuilder/xsd/fascicules.xsd
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Structure -->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:element name="fascicules">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="fascicule"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="fascicule">
- <xs:complexType mixed="true">
- <xs:attribute name="file" use="required"/>
- <xs:attribute name="href" use="required"/>
- <xs:attribute name="entry" default="no">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="yes"/>
- <xs:enumeration value="no"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/fileref.xsd b/lib/docbuilder/xsd/fileref.xsd
deleted file mode 100755
index 8038f2115f..0000000000
--- a/lib/docbuilder/xsd/fileref.xsd
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.refs.xsd"/>
- <xs:element name="fileref">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element ref="file"/>
- <xs:element ref="filesummary"/>
- <xs:element ref="description"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="section"/>
- <xs:element ref="funcs"/>
- </xs:choice>
- <xs:element ref="authors"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <!-- Note: ELEMENT file is already defined -->
- <xs:element name="filesummary" type="xs:string"/>
- <!--
- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd
- -->
- <xs:element name="name" type="xs:string"/>
-</xs:schema>
diff --git a/lib/docbuilder/xsd/part.xsd b/lib/docbuilder/xsd/part.xsd
deleted file mode 100755
index 30d6ec0120..0000000000
--- a/lib/docbuilder/xsd/part.xsd
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
- <xs:include schemaLocation="common.xsd"/>
- <xs:include schemaLocation="common.header.xsd"/>
- <xs:element name="part">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="header"/>
- <xs:element minOccurs="0" ref="description"/>
- <xs:element maxOccurs="unbounded" ref="include"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="description">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="block"/>
- <xs:element ref="quote"/>
- <xs:element ref="br"/>
- <xs:element ref="marker"/>
- <xs:element ref="warning"/>
- <xs:element ref="note"/>
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <xs:element name="include">
- <xs:complexType>
- <xs:attribute name="file" use="required"/>
- </xs:complexType>
- </xs:element>
-</xs:schema>
diff --git a/lib/edoc/doc/Makefile b/lib/edoc/doc/Makefile
index c5f68b25d0..7a59809d9b 100644
--- a/lib/edoc/doc/Makefile
+++ b/lib/edoc/doc/Makefile
@@ -78,12 +78,3 @@ release_docs_spec: docs
release_spec:
-
-
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-#-include make.dep
-
-
diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile
index b933094464..1f92d36f12 100644
--- a/lib/edoc/doc/src/Makefile
+++ b/lib/edoc/doc/src/Makefile
@@ -124,13 +124,13 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/edoc/doc/src/make.dep b/lib/edoc/doc/src/make.dep
deleted file mode 100644
index b46e36314f..0000000000
--- a/lib/edoc/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex edoc.tex edoc_doclet.tex \
- edoc_extract.tex edoc_layout.tex edoc_lib.tex \
- edoc_run.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index b220067bbe..a74a19bc05 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -31,6 +31,21 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.7.9.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Miscellaneous documentation build updates</p>
+ <p>
+ Own Id: OTP-9813</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.7.9</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/edoc/include/Makefile b/lib/edoc/include/Makefile
index 5b2ad38c9d..cf2e051632 100644
--- a/lib/edoc/include/Makefile
+++ b/lib/edoc/include/Makefile
@@ -49,8 +49,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(INCLUDE_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(INCLUDE_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/edoc/priv/Makefile b/lib/edoc/priv/Makefile
index 13225e6d1a..73c42c05eb 100644
--- a/lib/edoc/priv/Makefile
+++ b/lib/edoc/priv/Makefile
@@ -45,9 +45,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(PRIV_FILES) $(RELSYSDIR)/priv
- $(INSTALL_SCRIPT) $(GEN_SCRIPT) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(PRIV_FILES) "$(RELSYSDIR)/priv"
+ $(INSTALL_SCRIPT) $(GEN_SCRIPT) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/edoc/src/Makefile b/lib/edoc/src/Makefile
index fcb0b61292..72354ac711 100644
--- a/lib/edoc/src/Makefile
+++ b/lib/edoc/src/Makefile
@@ -85,10 +85,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(OBJECTS) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(SOURCES) $(HRL_FILES) $(YRL_FILE) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(OBJECTS) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(SOURCES) $(HRL_FILES) $(YRL_FILE) "$(RELSYSDIR)/src"
release_docs_spec:
diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl
index aad0b14371..624f9177a2 100644
--- a/lib/edoc/src/edoc_data.erl
+++ b/lib/edoc/src/edoc_data.erl
@@ -167,7 +167,10 @@ callbacks(Es, Module, Env, Opts) ->
case lists:any(fun (#entry{name = {behaviour_info, 1}}) -> true;
(_) -> false
end,
- Es) of
+ Es)
+ orelse
+ lists:keymember(callback, 1, Module#module.attributes)
+ of
true ->
try (Module#module.name):behaviour_info(callbacks) of
Fs ->
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index 7fd8358add..90fb8a679c 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -469,6 +469,10 @@ uri_get("ftp:" ++ Path) ->
uri_get("//" ++ Path) ->
Msg = io_lib:format("cannot access network-path: '//~s'.", [Path]),
{error, Msg};
+uri_get([C, $:, $/ | _]=Path) when C >= $A, C =< $Z; C >= $a, C =< $z ->
+ uri_get_file(Path); % special case for Windows
+uri_get([C, $:, $\ | _]=Path) when C >= $A, C =< $Z; C >= $a, C =< $z ->
+ uri_get_file(Path); % special case for Windows
uri_get(URI) ->
case is_relative_uri(URI) of
true ->
diff --git a/lib/edoc/test/Makefile b/lib/edoc/test/Makefile
index 2dbdb77eff..2033e003b3 100644
--- a/lib/edoc/test/Makefile
+++ b/lib/edoc/test/Makefile
@@ -57,10 +57,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) edoc.spec edoc.cover $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) edoc.spec edoc.cover "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 22f225dd9b..2f403212c8 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.7.9
+EDOC_VSN = 0.7.10
diff --git a/lib/eldap/.gitignore b/lib/eldap/.gitignore
new file mode 100644
index 0000000000..d3dd8228d5
--- /dev/null
+++ b/lib/eldap/.gitignore
@@ -0,0 +1,4 @@
+*.beam
+*.asn1db
+ebin/ELDAPv3.hrl
+ebin/ELDAPv3.erl
diff --git a/lib/eldap/AUTHORS b/lib/eldap/AUTHORS
new file mode 100644
index 0000000000..8f1e399306
--- /dev/null
+++ b/lib/eldap/AUTHORS
@@ -0,0 +1,7 @@
+Original author:
+ Torbjorn Tornkvist
+
+With patches from:
+ Simon MacMullen
+ Manuel Durán Aguete
+ voluntas \ No newline at end of file
diff --git a/lib/eldap/LICENSE b/lib/eldap/LICENSE
new file mode 100644
index 0000000000..1f6200918f
--- /dev/null
+++ b/lib/eldap/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) 2010, Torbjorn Tornkvist
+
+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
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/lib/eldap/Makefile b/lib/eldap/Makefile
new file mode 100644
index 0000000000..3635ec759d
--- /dev/null
+++ b/lib/eldap/Makefile
@@ -0,0 +1,39 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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
+
+# ----------------------------------------------------
+# Macros
+# ----------------------------------------------------
+
+SUB_DIRECTORIES = src doc/src
+
+include vsn.mk
+VSN = $(ELDAP_VSN)
+
+SPECIAL_TARGETS =
+
+# ----------------------------------------------------
+# Default Subdir Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_subdir.mk
+
diff --git a/lib/eldap/README b/lib/eldap/README
new file mode 100644
index 0000000000..e1bde9d658
--- /dev/null
+++ b/lib/eldap/README
@@ -0,0 +1,33 @@
+Hi,
+
+This is 'eldap', the Erlang LDAP library.
+
+It exports an API that can do all possible operations
+you may want to do against an LDAP server. The code has
+been tested to work at some point, but only the bind
+and search operations are running daily in our products,
+so there may be bugs lurking in some parts of the code.
+
+To just use eldap for doing authentication, do like in:
+
+ {ok,X} = eldap:open(["ldap.mycorp.com"], []).
+ eldap:simple_bind(X, "uid=tobbe,ou=People,dc=mycorp,dc=com", "passwd").
+
+In the doc/README.example you'll find a trace from a
+Erlang shell session as an example on how to setup a
+connection, authenticate (bind) and perform a search.
+Note that by using the option {ssl, true}, you should
+be able to setup an SSL tunnel (LDAPS) if your Erlang
+system has been configured with SSL.
+
+In the test directory there are some hints and examples
+on how to test the code and how to setup and populate
+an OpenLDAP server. The 'eldap' code has been tested
+agains OpenLDAP, IPlanet and ActiveDirectory servers.
+
+If you plan to incorporate this code into your system
+I suggest that you build a server/supervisor harnesk
+that uses 'eldap' (as we have done in our products).
+
+Good luck !
+/Tobbe
diff --git a/lib/eldap/asn1/ELDAPv3.asn1 b/lib/eldap/asn1/ELDAPv3.asn1
new file mode 100644
index 0000000000..72b87d7221
--- /dev/null
+++ b/lib/eldap/asn1/ELDAPv3.asn1
@@ -0,0 +1,278 @@
+-- Lightweight-Directory-Access-Protocol-V3 {1 3 6 1 1 18}
+-- Copyright (C) The Internet Society (2006). This version of
+-- this ASN.1 module is part of RFC 4511; see the RFC itself
+-- for full legal notices.
+ELDAPv3 DEFINITIONS
+IMPLICIT TAGS
+EXTENSIBILITY IMPLIED ::=
+
+BEGIN
+
+LDAPMessage ::= SEQUENCE {
+ messageID MessageID,
+ protocolOp CHOICE {
+ bindRequest BindRequest,
+ bindResponse BindResponse,
+ unbindRequest UnbindRequest,
+ searchRequest SearchRequest,
+ searchResEntry SearchResultEntry,
+ searchResDone SearchResultDone,
+ searchResRef SearchResultReference,
+ modifyRequest ModifyRequest,
+ modifyResponse ModifyResponse,
+ addRequest AddRequest,
+ addResponse AddResponse,
+ delRequest DelRequest,
+ delResponse DelResponse,
+ modDNRequest ModifyDNRequest,
+ modDNResponse ModifyDNResponse,
+ compareRequest CompareRequest,
+ compareResponse CompareResponse,
+ abandonRequest AbandonRequest,
+ extendedReq ExtendedRequest,
+ extendedResp ExtendedResponse,
+ ...,
+ intermediateResponse IntermediateResponse },
+ controls [0] Controls OPTIONAL }
+
+MessageID ::= INTEGER (0 .. maxInt)
+
+maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
+
+LDAPString ::= OCTET STRING -- UTF-8 encoded,
+ -- [ISO10646] characters
+
+LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+ -- [RFC4512]
+
+LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
+ -- [RFC4514]
+
+RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
+ -- [RFC4514]
+
+AttributeDescription ::= LDAPString
+ -- Constrained to <attributedescription>
+ -- [RFC4512]
+
+AttributeValue ::= OCTET STRING
+
+AttributeValueAssertion ::= SEQUENCE {
+ attributeDesc AttributeDescription,
+ assertionValue AssertionValue }
+
+AssertionValue ::= OCTET STRING
+
+PartialAttribute ::= SEQUENCE {
+ type AttributeDescription,
+ vals SET OF value AttributeValue }
+
+Attribute ::= PartialAttribute(WITH COMPONENTS {
+ ...,
+ vals (SIZE(1..MAX))})
+
+MatchingRuleId ::= LDAPString
+
+LDAPResult ::= SEQUENCE {
+ resultCode ENUMERATED {
+ success (0),
+ operationsError (1),
+ protocolError (2),
+ timeLimitExceeded (3),
+ sizeLimitExceeded (4),
+ compareFalse (5),
+ compareTrue (6),
+ authMethodNotSupported (7),
+ strongerAuthRequired (8),
+ -- 9 reserved --
+ referral (10),
+ adminLimitExceeded (11),
+ unavailableCriticalExtension (12),
+ confidentialityRequired (13),
+ saslBindInProgress (14),
+
+ noSuchAttribute (16),
+ undefinedAttributeType (17),
+ inappropriateMatching (18),
+ constraintViolation (19),
+ attributeOrValueExists (20),
+ invalidAttributeSyntax (21),
+ -- 22-31 unused --
+ noSuchObject (32),
+ aliasProblem (33),
+ invalidDNSyntax (34),
+ -- 35 reserved for undefined isLeaf --
+ aliasDereferencingProblem (36),
+ -- 37-47 unused --
+ inappropriateAuthentication (48),
+ invalidCredentials (49),
+ insufficientAccessRights (50),
+ busy (51),
+ unavailable (52),
+ unwillingToPerform (53),
+ loopDetect (54),
+ -- 55-63 unused --
+ namingViolation (64),
+ objectClassViolation (65),
+ notAllowedOnNonLeaf (66),
+ notAllowedOnRDN (67),
+ entryAlreadyExists (68),
+ objectClassModsProhibited (69),
+ -- 70 reserved for CLDAP --
+ affectsMultipleDSAs (71),
+ -- 72-79 unused --
+ other (80),
+ ... },
+ matchedDN LDAPDN,
+ diagnosticMessage LDAPString,
+ referral [3] Referral OPTIONAL }
+
+Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+
+URI ::= LDAPString -- limited to characters permitted in
+ -- URIs
+
+Controls ::= SEQUENCE OF control Control
+
+Control ::= SEQUENCE {
+ controlType LDAPOID,
+ criticality BOOLEAN DEFAULT FALSE,
+ controlValue OCTET STRING OPTIONAL }
+
+BindRequest ::= [APPLICATION 0] SEQUENCE {
+ version INTEGER (1 .. 127),
+ name LDAPDN,
+ authentication AuthenticationChoice }
+
+AuthenticationChoice ::= CHOICE {
+ simple [0] OCTET STRING,
+ -- 1 and 2 reserved
+ sasl [3] SaslCredentials,
+ ... }
+
+SaslCredentials ::= SEQUENCE {
+ mechanism LDAPString,
+ credentials OCTET STRING OPTIONAL }
+
+BindResponse ::= [APPLICATION 1] SEQUENCE {
+ COMPONENTS OF LDAPResult,
+ serverSaslCreds [7] OCTET STRING OPTIONAL }
+
+UnbindRequest ::= [APPLICATION 2] NULL
+
+SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ baseObject LDAPDN,
+ scope ENUMERATED {
+ baseObject (0),
+ singleLevel (1),
+ wholeSubtree (2),
+ ... },
+ derefAliases ENUMERATED {
+ neverDerefAliases (0),
+ derefInSearching (1),
+ derefFindingBaseObj (2),
+ derefAlways (3) },
+ sizeLimit INTEGER (0 .. maxInt),
+ timeLimit INTEGER (0 .. maxInt),
+ typesOnly BOOLEAN,
+ filter Filter,
+ attributes AttributeSelection }
+
+AttributeSelection ::= SEQUENCE OF selector LDAPString
+ -- The LDAPString is constrained to
+ -- <attributeSelector> in Section 4.5.1.8
+
+Filter ::= CHOICE {
+ and [0] SET SIZE (1..MAX) OF filter Filter,
+ or [1] SET SIZE (1..MAX) OF filter Filter,
+ not [2] Filter,
+ equalityMatch [3] AttributeValueAssertion,
+ substrings [4] SubstringFilter,
+ greaterOrEqual [5] AttributeValueAssertion,
+ lessOrEqual [6] AttributeValueAssertion,
+ present [7] AttributeDescription,
+ approxMatch [8] AttributeValueAssertion,
+ extensibleMatch [9] MatchingRuleAssertion,
+ ... }
+
+SubstringFilter ::= SEQUENCE {
+ type AttributeDescription,
+ substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+ initial [0] AssertionValue, -- can occur at most once
+ any [1] AssertionValue,
+ final [2] AssertionValue } -- can occur at most once
+ }
+
+MatchingRuleAssertion ::= SEQUENCE {
+ matchingRule [1] MatchingRuleId OPTIONAL,
+ type [2] AttributeDescription OPTIONAL,
+ matchValue [3] AssertionValue,
+ dnAttributes [4] BOOLEAN DEFAULT FALSE }
+
+SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+ objectName LDAPDN,
+ attributes PartialAttributeList }
+
+PartialAttributeList ::= SEQUENCE OF
+ partialAttribute PartialAttribute
+
+SearchResultReference ::= [APPLICATION 19] SEQUENCE
+ SIZE (1..MAX) OF uri URI
+
+SearchResultDone ::= [APPLICATION 5] LDAPResult
+
+ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+ object LDAPDN,
+ changes SEQUENCE OF change SEQUENCE {
+ operation ENUMERATED {
+ add (0),
+ delete (1),
+ replace (2),
+ ... },
+ modification PartialAttribute } }
+
+ModifyResponse ::= [APPLICATION 7] LDAPResult
+
+AddRequest ::= [APPLICATION 8] SEQUENCE {
+ entry LDAPDN,
+ attributes AttributeList }
+
+AttributeList ::= SEQUENCE OF attribute Attribute
+
+AddResponse ::= [APPLICATION 9] LDAPResult
+
+DelRequest ::= [APPLICATION 10] LDAPDN
+
+DelResponse ::= [APPLICATION 11] LDAPResult
+
+ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+ entry LDAPDN,
+ newrdn RelativeLDAPDN,
+ deleteoldrdn BOOLEAN,
+ newSuperior [0] LDAPDN OPTIONAL }
+
+ModifyDNResponse ::= [APPLICATION 13] LDAPResult
+
+CompareRequest ::= [APPLICATION 14] SEQUENCE {
+ entry LDAPDN,
+ ava AttributeValueAssertion }
+
+CompareResponse ::= [APPLICATION 15] LDAPResult
+
+AbandonRequest ::= [APPLICATION 16] MessageID
+
+ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+ requestName [0] LDAPOID,
+ requestValue [1] OCTET STRING OPTIONAL }
+
+ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+ COMPONENTS OF LDAPResult,
+ responseName [10] LDAPOID OPTIONAL,
+ responseValue [11] OCTET STRING OPTIONAL }
+
+IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
+ responseName [0] LDAPOID OPTIONAL,
+ responseValue [1] OCTET STRING OPTIONAL }
+
+END
+
diff --git a/lib/docbuilder/doc/man3/.gitignore b/lib/eldap/doc/html/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/docbuilder/doc/man3/.gitignore
+++ b/lib/eldap/doc/html/.gitignore
diff --git a/lib/docbuilder/doc/man6/.gitignore b/lib/eldap/doc/man3/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/docbuilder/doc/man6/.gitignore
+++ b/lib/eldap/doc/man3/.gitignore
diff --git a/lib/docbuilder/doc/pdf/.gitignore b/lib/eldap/doc/pdf/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/docbuilder/doc/pdf/.gitignore
+++ b/lib/eldap/doc/pdf/.gitignore
diff --git a/lib/eldap/doc/src/Makefile b/lib/eldap/doc/src/Makefile
new file mode 100644
index 0000000000..a4827793f4
--- /dev/null
+++ b/lib/eldap/doc/src/Makefile
@@ -0,0 +1,115 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved via the world wide web at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+# AB. All Rights Reserved.''
+#
+# $Id$
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(ELDAP_VSN)
+APPLICATION=eldap
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+XML_APPLICATION_FILES = ref_man.xml
+XML_REF3_FILES = eldap.xml
+
+XML_PART_FILES = release_notes.xml usersguide.xml
+XML_CHAPTER_FILES = notes.xml
+
+BOOK_FILES = book.xml
+
+XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+
+GIF_FILES =
+
+# ----------------------------------------------------
+
+HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+INFO_FILE = ../../info
+
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+XML_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+
+docs: pdf html man
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: gifs $(HTML_REF_MAN_FILE)
+
+man: $(MAN3_FILES) $(MAN6_FILES)
+
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+debug opt valgrind:
+
+clean clean_docs clean_tex:
+ rm -rf $(HTMLDIR)/*
+ rm -f $(MAN3DIR)/*
+ rm -f $(MAN6DIR)/*
+ rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f errs core *~
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_docs_spec: docs
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(HTMLDIR)/* \
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+# $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+# $(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
+
+
+release_spec:
+
diff --git a/lib/eldap/doc/src/book.xml b/lib/eldap/doc/src/book.xml
new file mode 100644
index 0000000000..74f1c37cdc
--- /dev/null
+++ b/lib/eldap/doc/src/book.xml
@@ -0,0 +1,47 @@
+<?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>2012</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>eldap</title>
+ <prepared>OTP team</prepared>
+ <docno></docno>
+ <date>1999-01-21</date>
+ <rev>A</rev>
+ <file>book.xml</file>
+ </header>
+ <pagetext>eldap</pagetext>
+ <preamble>
+ <contents level="2"></contents>
+ </preamble>
+ <parts lift="no">
+ <xi:include href="usersguide.xml"/>
+ </parts>
+ <applications>
+ <xi:include href="ref_man.xml"/>
+ </applications>
+ <releasenotes>
+ <xi:include href="notes.xml"/>
+ </releasenotes>
+ <listofterms></listofterms>
+ <index></index>
+</book>
+
diff --git a/lib/eldap/doc/src/eldap.xml b/lib/eldap/doc/src/eldap.xml
new file mode 100644
index 0000000000..04dad2eee7
--- /dev/null
+++ b/lib/eldap/doc/src/eldap.xml
@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2012</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>eldap</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>2000-06-20</date>
+ <rev>B</rev>
+ </header>
+ <module>eldap</module>
+ <modulesummary>Eldap Functions</modulesummary>
+ <description>
+ <p>This module provides a client api to the Lightweight Directory Access Protocol (LDAP).
+ </p>
+ <p>References:</p>
+ <list type="bulleted">
+ <item> <p>RFC 4510 - RFC 4519</p> </item>
+ </list>
+ <p>The above publications can be found at <url href="http://www.ietf.org">IETF</url>.
+ </p>
+ <p><em>Types</em></p>
+ <pre>
+handle() Connection handle
+attribute() {Type = string(), Values=[string()]}
+modify_op() See mod_add/2, mod_delete/2, mod_replace/2
+scope() See baseObject/0, singleLevel/0, wholeSubtree/0
+dereference() See neverDerefAliases/0, derefInSearching/0, derefFindingBaseObj/0, derefAlways/0
+filter() See present/1, substrings/2,
+ equalityMatch/2, greaterOrEqual/2, lessOrEqual/2,
+ approxMatch/2,
+ 'and'/1, 'or'/1, 'not'/1.
+ </pre>
+ <p></p>
+ </description>
+ <funcs>
+ <func>
+ <name>open([Host]) -> {ok, Handle} | {error, Reason}</name>
+ <fsummary>Open a connection to an LDAP server.</fsummary>
+ <type>
+ <v>Handle = handle()</v>
+ </type>
+ <desc>
+ <p>Setup a connection to an LDAP server, the <c>HOST</c>'s are tried in order. </p>
+ </desc>
+ </func>
+ <func>
+ <name>open([Host], [Option]) -> {ok, Handle} | {error, Reason}</name>
+ <fsummary>Open a connection to an LDAP server.</fsummary>
+ <type>
+ <v>Handle = handle()</v>
+ <v>Option = {port, integer()} | {log, function()} | {timeout, integer()} | {ssl, boolean()}</v>
+ </type>
+ <desc>
+ <p>Setup a connection to an LDAP server, the <c>HOST</c>'s are tried in order.</p>
+ <p>The log function takes three arguments, <c>fun(Level, FormatString, [FormatArg]) end</c>.</p>
+ <p>Timeout set the maximum time in milliseconds that each server request may take.</p>
+ </desc>
+ </func>
+ <func>
+ <name>close(Handle) -> ok</name>
+ <fsummary>Shutdown the connection.</fsummary>
+ <type>
+ <v>Handle = handle()</v>
+ </type>
+ <desc>
+ <p>Shutdown the connection.</p>
+ </desc>
+ </func>
+ <func>
+ <name>simple_bind(Handle, Dn, Password) -> ok | {error, Reason}</name>
+ <fsummary>Authenticate the connection.</fsummary>
+ <type>
+ <v>Handle = handle()</v>
+ <v>Dn = string()</v>
+ <v>Password = string()</v>
+ </type>
+ <desc>
+ <p>Authenticate the connection using simple authentication.</p>
+ </desc>
+ </func>
+ <func>
+ <name>add(Handle, Dn, [Attribute]) -> ok | {error, Reason}</name>
+ <fsummary>Add an entry.</fsummary>
+ <type>
+ <v>Handle = handle()</v>
+ <v>Dn = string()</v>
+ <v>Attribute = attribute()</v>
+ </type>
+ <desc>
+ <p> Add an entry. The entry must not exist.</p>
+ <pre>
+ add(Handle,
+ "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
+ [{"objectclass", ["person"]},
+ {"cn", ["Bill Valentine"]},
+ {"sn", ["Valentine"]},
+ {"telephoneNumber", ["545 555 00"]}]
+ )
+ </pre>
+ </desc>
+ </func>
+ <func>
+ <name>delete(Handle, Dn) -> ok | {error, Reason}</name>
+ <fsummary>Delete an entry.</fsummary>
+ <type>
+ <v>Dn = string()</v>
+ </type>
+ <desc>
+ <p> Delete an entry.</p>
+ <pre>
+ delete(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com")
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name>mod_add(Type, [Value]) -> modify_op()</name>
+ <fsummary>Create a modification operation.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p> Create an add modification operation.</p> </desc>
+ </func>
+ <func>
+ <name>mod_delete(Type, [Value]) -> modify_op()</name>
+ <fsummary>Create a modification operation.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p> Create a delete modification operation.</p> </desc>
+ </func>
+ <func>
+ <name>mod_replace(Type, [Value]) -> modify_op()</name>
+ <fsummary>Create a modification operation.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p> Create a replace modification operation.</p> </desc>
+ </func>
+
+ <func>
+ <name>modify(Handle, Dn, [ModifyOp]) -> ok | {error, Reason}</name>
+ <fsummary>Modify an entry.</fsummary>
+ <type>
+ <v>Dn = string()</v>
+ <v>ModifyOp = modify_op()</v>
+ </type>
+ <desc>
+ <p> Modify an entry.</p>
+ <pre>
+ modify(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
+ [eldap:mod_replace("telephoneNumber", ["555 555 00"]),
+ eldap:mod_add("description", ["LDAP Hacker"]) ])
+ </pre>
+ </desc>
+ </func>
+ <func>
+ <name>modify_dn(Handle, Dn, NewRDN, DeleteOldRDN, NewSupDN) -> ok | {error, Reason}</name>
+ <fsummary>Modify the DN of an entry.</fsummary>
+ <type>
+ <v>Dn = string()</v>
+ <v>NewRDN = string()</v>
+ <v>DeleteOldRDN = boolean()</v>
+ <v>NewSupDN = string()</v>
+ </type>
+ <desc>
+ <p> Modify the DN of an entry. <c>DeleteOldRDN</c> indicates
+ whether the current RDN should be removed after operation.
+ <c>NewSupDN</c> should be "" if the RDN should not be moved or the new parent which
+ the RDN will be moved to.</p>
+ <pre>
+ modify_dn(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com ",
+ "cn=Bill Jr Valentine", true, "")
+ </pre>
+ </desc>
+ </func>
+ <func>
+ <name>search(Handle, SearchOptions) -> {ok, #eldap_search_result{}} | {error, Reason}</name>
+ <fsummary>Search the Directory</fsummary>
+ <type>
+ <v>SearchOptions = #eldap_search{} | [SearchOption]</v>
+ <v>SearchOption = {base, string()} | {filter, filter()} | {scope, scope()}
+ | {attributes, [string()]} | {deref, dereference()} |
+ | {types_only, boolean()} | {timeout, integer()}
+ </v>
+ </type>
+ <desc>
+ <p>Search the directory with the supplied the SearchOptions.
+ The base and filter options must be supplied.
+ Default values: scope is <c>wholeSubtree()</c>, deref is <c>derefAlways()</c>,
+ types_only is <c>false</c> and timeout is <c>0</c> (meaning infinity).
+ </p>
+ <pre>
+ Filter = eldap:substrings("cn", [{any,"V"}]),
+ search(Handle, [{base, "dc=example, dc=com"}, {filter, Filter}, {attributes, ["cn"]}]),
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name>baseObject() -> scope()</name>
+ <fsummary>Create search scope.</fsummary>
+ <desc> <p> Search baseobject only.</p> </desc>
+ </func>
+ <func>
+ <name>singleLevel() -> scope()</name>
+ <fsummary>Create search scope.</fsummary>
+ <desc> <p> Search the specified level only, i.e. do not recurse.</p> </desc>
+ </func>
+ <func>
+ <name>wholeSubtree() -> scope()</name>
+ <fsummary>Create search scope.</fsummary>
+ <desc> <p> Search the entire subtree.</p> </desc>
+ </func>
+
+ <func>
+ <name>neverDerefAliases() -> dereference()</name>
+ <fsummary>Create search option.</fsummary>
+ <desc> <p>Never derefrence aliases, treat aliases as entries.</p> </desc>
+ </func>
+ <func>
+ <name>derefAlways() -> dereference()</name>
+ <fsummary>Create search option.</fsummary>
+ <desc> <p>Always derefrence aliases.</p> </desc>
+ </func>
+ <func>
+ <name>derefInSearching() -> dereference()</name>
+ <fsummary>Create search option.</fsummary>
+ <desc> <p>Derefrence aliases only when searching.</p> </desc>
+ </func>
+ <func>
+ <name>derefFindingBaseObj() -> dereference()</name>
+ <fsummary>Create search option.</fsummary>
+ <desc> <p>Derefrence aliases only in finding the base.</p> </desc>
+ </func>
+
+ <func>
+ <name>present(Type) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ </type>
+ <desc> <p>Create a filter which filters on attribute type presence.</p> </desc>
+ </func>
+ <func>
+ <name>substrings(Type, [SubString]) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>SubString = {StringPart, string()}</v>
+ <v>StringPart = initial | any | final</v>
+ </type>
+ <desc> <p>Create a filter which filters on substrings.</p> </desc>
+ </func>
+ <func>
+ <name>equalityMatch(Type, Value) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p>Create a equality filter.</p> </desc>
+ </func>
+ <func>
+ <name>greaterOrEqual(Type, Value) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p>Create a greater or equal filter.</p> </desc>
+ </func>
+ <func>
+ <name>lessOrEqual(Type, Value) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p>Create a less or equal filter.</p> </desc>
+ </func>
+ <func>
+ <name>approxMatch(Type, Value) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Type = string()</v>
+ <v>Value = string()</v>
+ </type>
+ <desc> <p>Create a approximation match filter.</p> </desc>
+ </func>
+ <func>
+ <name>'and'([Filter]) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Filter = filter()</v>
+ </type>
+ <desc> <p>Creates a filter where all <c>Filter</c> must be true.</p> </desc>
+ </func>
+ <func>
+ <name>'or'([Filter]) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Filter = filter()</v>
+ </type>
+ <desc> <p>Create a filter where at least one of the <c>Filter</c> must be true.</p> </desc>
+ </func>
+ <func>
+ <name>'not'(Filter) -> filter()</name>
+ <fsummary>Create search filter option.</fsummary>
+ <type>
+ <v>Filter = filter()</v>
+ </type>
+ <desc> <p>Negate a filter.</p> </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
+
diff --git a/lib/eldap/doc/src/fascicules.xml b/lib/eldap/doc/src/fascicules.xml
new file mode 100644
index 0000000000..8fc250bc75
--- /dev/null
+++ b/lib/eldap/doc/src/fascicules.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
+
+<fascicules>
+ <fascicule file="usersguide" href="usersguide_frame.html" entry="no">
+ User's Guide
+ </fascicule>
+ <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
+ Reference Manual
+ </fascicule>
+ <fascicule file="release_notes" href="release_notes_frame.html" entry="no">
+ Release Notes
+ </fascicule>
+ <fascicule file="" href="../../../../doc/print.html" entry="no">
+ Off-Print
+ </fascicule>
+</fascicules>
+
diff --git a/lib/docbuilder/etc/note.gif b/lib/eldap/doc/src/note.gif
index 6fffe30419..6fffe30419 100644
--- a/lib/docbuilder/etc/note.gif
+++ b/lib/eldap/doc/src/note.gif
Binary files differ
diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml
new file mode 100644
index 0000000000..d9b11875de
--- /dev/null
+++ b/lib/eldap/doc/src/notes.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2012</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>Eldap Release Notes</title>
+ <prepared>OTP team</prepared>
+ <docno></docno>
+ <date>2003-06-06</date>
+ <rev>B</rev>
+ <file>notes.xml</file>
+ </header>
+ <p>This document describes the changes made to the Eldap application.</p>
+
+ <section>
+ <title>Eldap 1.0</title>
+ <p>New application. </p>
+ </section>
+</chapter>
+
diff --git a/lib/eldap/doc/src/ref_man.xml b/lib/eldap/doc/src/ref_man.xml
new file mode 100644
index 0000000000..70c4cee16d
--- /dev/null
+++ b/lib/eldap/doc/src/ref_man.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE application SYSTEM "application.dtd">
+
+<application xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2012</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>Eldap Reference Manual</title>
+ <prepared>OTP team</prepared>
+ <docno></docno>
+ <date>2003-06-01</date>
+ <rev>B</rev>
+ <file>refman.sgml</file>
+ </header>
+ <description>
+ <p>The <em>Eldap</em> application provides an api for accessing an LDAP server.</p>
+ <p>The original code was developed by Torbj&ouml;rn T&ouml;rnkvist.</p>
+ </description>
+ <xi:include href="eldap.xml"/>
+</application>
+
diff --git a/lib/eldap/doc/src/release_notes.xml b/lib/eldap/doc/src/release_notes.xml
new file mode 100644
index 0000000000..778a49b894
--- /dev/null
+++ b/lib/eldap/doc/src/release_notes.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part>
+ <header>
+ <copyright>
+ <year>2012</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>Eldap Release Notes</title>
+ <prepared>OTP team</prepared>
+ <docno></docno>
+ <date>2003-06-01</date>
+ <rev>B</rev>
+ <file>release_notes.xml</file>
+ </header>
+ <description>
+ <p></p>
+ </description>
+ <include file="notes"></include>
+</part>
+
diff --git a/lib/eldap/doc/src/usersguide.xml b/lib/eldap/doc/src/usersguide.xml
new file mode 100644
index 0000000000..828588e88e
--- /dev/null
+++ b/lib/eldap/doc/src/usersguide.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2012</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>Eldap User's Guide</title>
+ <prepared>OTP Team</prepared>
+ <docno></docno>
+ <date>2003-06-01</date>
+ <rev>C</rev>
+ <file>usersguide.xml</file>
+ </header>
+ <description>
+ <p>The <em>Eldap</em> application provides an api for accessing an LDAP server.</p>
+ <p>The original code was developed by Torbj&ouml;rn T&ouml;rnkvist.</p>
+ </description>
+
+
+</part>
+
diff --git a/lib/docbuilder/etc/warning.gif b/lib/eldap/doc/src/warning.gif
index 96af52360e..96af52360e 100644
--- a/lib/docbuilder/etc/warning.gif
+++ b/lib/eldap/doc/src/warning.gif
Binary files differ
diff --git a/lib/docbuilder/ebin/.gitignore b/lib/eldap/ebin/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/docbuilder/ebin/.gitignore
+++ b/lib/eldap/ebin/.gitignore
diff --git a/lib/eldap/include/eldap.hrl b/lib/eldap/include/eldap.hrl
new file mode 100644
index 0000000000..7c12cd4f2b
--- /dev/null
+++ b/lib/eldap/include/eldap.hrl
@@ -0,0 +1,33 @@
+-ifndef( _ELDAP_HRL ).
+-define( _ELDAP_HRL , 1 ).
+
+%%%
+%%% Search input parameters
+%%%
+-record(eldap_search, {
+ base = [], % Baseobject
+ filter = [], % Search conditions
+ scope=wholeSubtree, % Search scope
+ deref=derefAlways, % Dereference
+ attributes = [], % Attributes to be returned
+ types_only = false, % Return types+values or types
+ timeout = 0 % Timelimit for search
+ }).
+
+%%%
+%%% Returned search result
+%%%
+-record(eldap_search_result, {
+ entries = [], % List of #eldap_entry{} records
+ referrals = [] % List of referrals
+ }).
+
+%%%
+%%% LDAP entry
+%%%
+-record(eldap_entry, {
+ object_name = "", % The DN for the entry
+ attributes = [] % List of {Attribute, Value} pairs
+ }).
+
+-endif.
diff --git a/lib/eldap/info b/lib/eldap/info
new file mode 100644
index 0000000000..463f9af6ea
--- /dev/null
+++ b/lib/eldap/info
@@ -0,0 +1,2 @@
+group: comm
+short: eldap - Erlang LDAP library
diff --git a/lib/eldap/src/Makefile b/lib/eldap/src/Makefile
new file mode 100644
index 0000000000..39a41d08e2
--- /dev/null
+++ b/lib/eldap/src/Makefile
@@ -0,0 +1,110 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/eldap-$(ELDAP_VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= eldap
+
+ASN1_FILES = ELDAPv3.asn1
+ASN1_HRL = $(EBIN)/$(ASN1_FILES:%.asn1=%.hrl)
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(ASN1_FILES:%.asn1=$(EBIN)/%.$(EMULATOR))
+
+EXTERNAL_HRL_FILES = ../include/eldap.hrl
+
+HRL_FILES = $(EXTERNAL_HRL_FILES) $(ASN1_HRL)
+
+APPUP_FILE = eldap.appup
+APPUP_SRC = $(APPUP_FILE).src
+APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+
+APP_FILE = eldap.app
+APP_SRC = $(APP_FILE).src
+APP_TARGET = $(EBIN)/$(APP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += -I../include -I../ebin
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+
+debug:
+ @${MAKE} TYPE=debug opt
+
+clean:
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(ASN1_FILES:%.asn1=$(EBIN)/%.*)
+ rm -f errs core *~
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(ELDAP_VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(ELDAP_VSN);' $< > $@
+
+docs:
+
+$(TARGET_FILES): $(HRL_FILES)
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+$(ASN1_HRL): ../asn1/$(ASN1_FILES)
+ $(ERLC) -o $(EBIN) -bber_bin +optimize +nif $(ERL_COMPILE_FLAGS) ../asn1/ELDAPv3.asn1
+
+# ----------------------------------------------------
+# 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) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/asn1"
+ $(INSTALL_DATA) ../asn1/$(ASN1_FILES) "$(RELSYSDIR)/asn1"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) "$(RELSYSDIR)/include"
+
+release_docs_spec:
+
+
diff --git a/lib/eldap/src/eldap.app.src b/lib/eldap/src/eldap.app.src
new file mode 100644
index 0000000000..8215328910
--- /dev/null
+++ b/lib/eldap/src/eldap.app.src
@@ -0,0 +1,8 @@
+{application, eldap,
+ [{description, "Ldap api"},
+ {vsn, "%VSN%"},
+ {modules, [eldap, 'ELDAPv3']},
+ {registered, []},
+ {applications, [kernel, stdlib]},
+ {env, []}
+]}.
diff --git a/lib/eldap/src/eldap.appup.src b/lib/eldap/src/eldap.appup.src
new file mode 100644
index 0000000000..8d33482f11
--- /dev/null
+++ b/lib/eldap/src/eldap.appup.src
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{"%VSN%",
+ [
+ ],
+ [
+ ]}.
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
new file mode 100644
index 0000000000..699dfc8791
--- /dev/null
+++ b/lib/eldap/src/eldap.erl
@@ -0,0 +1,1114 @@
+-module(eldap).
+%%% --------------------------------------------------------------------
+%%% Created: 12 Oct 2000 by Tobbe <[email protected]>
+%%% Function: Erlang client LDAP implementation according RFC 2251,2253
+%%% and 2255. The interface is based on RFC 1823, and
+%%% draft-ietf-asid-ldap-c-api-00.txt
+%%%
+%%% Copyright (c) 2010 Torbjorn Tornkvist
+%%% See MIT-LICENSE at the top dir for licensing information.
+%%% --------------------------------------------------------------------
+-vc('$Id$ ').
+-export([open/1,open/2,simple_bind/3,controlling_process/2,
+ baseObject/0,singleLevel/0,wholeSubtree/0,close/1,
+ equalityMatch/2,greaterOrEqual/2,lessOrEqual/2,
+ approxMatch/2,search/2,substrings/2,present/1,
+ 'and'/1,'or'/1,'not'/1,modify/3, mod_add/2, mod_delete/2,
+ mod_replace/2, add/3, delete/2, modify_dn/5,parse_dn/1,
+ parse_ldap_url/1]).
+
+-export([neverDerefAliases/0, derefInSearching/0,
+ derefFindingBaseObj/0, derefAlways/0]).
+
+%% for upgrades
+-export([loop/2]).
+
+-import(lists,[concat/1]).
+
+-include("ELDAPv3.hrl").
+-include("eldap.hrl").
+
+-define(LDAP_VERSION, 3).
+-define(LDAP_PORT, 389).
+-define(LDAPS_PORT, 636).
+
+-record(eldap, {version = ?LDAP_VERSION,
+ host, % Host running LDAP server
+ port = ?LDAP_PORT, % The LDAP server port
+ fd, % Socket filedescriptor.
+ binddn = "", % Name of the entry to bind as
+ passwd, % Password for (above) entry
+ id = 0, % LDAP Request ID
+ log, % User provided log function
+ timeout = infinity, % Request timeout
+ anon_auth = false, % Allow anonymous authentication
+ use_tls = false % LDAP/LDAPS
+ }).
+
+%%% For debug purposes
+%%-define(PRINT(S, A), io:fwrite("~w(~w): " ++ S, [?MODULE,?LINE|A])).
+-define(PRINT(S, A), true).
+
+-define(elog(S, A), error_logger:info_msg("~w(~w): "++S,[?MODULE,?LINE|A])).
+
+%%% ====================================================================
+%%% Exported interface
+%%% ====================================================================
+
+%%% --------------------------------------------------------------------
+%%% open(Hosts [,Opts] )
+%%% --------------------
+%%% Setup a connection to on of the Hosts in the argument
+%%% list. Stop at the first successful connection attempt.
+%%% Valid Opts are: Where:
+%%%
+%%% {port, Port} - Port is the port number
+%%% {log, F} - F(LogLevel, FormatString, ListOfArgs)
+%%% {timeout, milliSec} - Server request timeout
+%%%
+%%% --------------------------------------------------------------------
+open(Hosts) ->
+ open(Hosts, []).
+
+open(Hosts, Opts) when is_list(Hosts), is_list(Opts) ->
+ Self = self(),
+ Pid = spawn_link(fun() -> init(Hosts, Opts, Self) end),
+ recv(Pid).
+
+%%% --------------------------------------------------------------------
+%%% Shutdown connection (and process) asynchronous.
+%%% --------------------------------------------------------------------
+
+close(Handle) when is_pid(Handle) ->
+ send(Handle, close).
+
+%%% --------------------------------------------------------------------
+%%% Set who we should link ourselves to
+%%% --------------------------------------------------------------------
+
+controlling_process(Handle, Pid) when is_pid(Handle), is_pid(Pid) ->
+ link(Pid),
+ send(Handle, {cnt_proc, Pid}),
+ recv(Handle).
+
+%%% --------------------------------------------------------------------
+%%% Authenticate ourselves to the Directory
+%%% using simple authentication.
+%%%
+%%% Dn - The name of the entry to bind as
+%%% Passwd - The password to be used
+%%%
+%%% Returns: ok | {error, Error}
+%%% --------------------------------------------------------------------
+simple_bind(Handle, Dn, Passwd) when is_pid(Handle) ->
+ send(Handle, {simple_bind, Dn, Passwd}),
+ recv(Handle).
+
+%%% --------------------------------------------------------------------
+%%% Add an entry. The entry field MUST NOT exist for the AddRequest
+%%% to succeed. The parent of the entry MUST exist.
+%%% Example:
+%%%
+%%% add(Handle,
+%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com",
+%%% [{"objectclass", ["person"]},
+%%% {"cn", ["Bill Valentine"]},
+%%% {"sn", ["Valentine"]},
+%%% {"telephoneNumber", ["545 555 00"]}]
+%%% )
+%%% --------------------------------------------------------------------
+add(Handle, Entry, Attributes) when is_pid(Handle),is_list(Entry),is_list(Attributes) ->
+ send(Handle, {add, Entry, add_attrs(Attributes)}),
+ recv(Handle).
+
+%%% Do sanity check !
+add_attrs(Attrs) ->
+ F = fun({Type,Vals}) when is_list(Type),is_list(Vals) ->
+ %% Confused ? Me too... :-/
+ {'AddRequest_attributes',Type, Vals}
+ end,
+ case catch lists:map(F, Attrs) of
+ {'EXIT', _} -> throw({error, attribute_values});
+ Else -> Else
+ end.
+
+%%% --------------------------------------------------------------------
+%%% Delete an entry. The entry consists of the DN of
+%%% the entry to be deleted.
+%%% Example:
+%%%
+%%% delete(Handle,
+%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com"
+%%% )
+%%% --------------------------------------------------------------------
+delete(Handle, Entry) when is_pid(Handle), is_list(Entry) ->
+ send(Handle, {delete, Entry}),
+ recv(Handle).
+
+%%% --------------------------------------------------------------------
+%%% Modify an entry. Given an entry a number of modification
+%%% operations can be performed as one atomic operation.
+%%% Example:
+%%%
+%%% modify(Handle,
+%%% "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com",
+%%% [mod_replace("telephoneNumber", ["555 555 00"]),
+%%% mod_add("description", ["LDAP hacker"])]
+%%% )
+%%% --------------------------------------------------------------------
+modify(Handle, Object, Mods) when is_pid(Handle), is_list(Object), is_list(Mods) ->
+ send(Handle, {modify, Object, Mods}),
+ recv(Handle).
+
+%%%
+%%% Modification operations.
+%%% Example:
+%%% mod_replace("telephoneNumber", ["555 555 00"])
+%%%
+mod_add(Type, Values) when is_list(Type), is_list(Values) -> m(add, Type, Values).
+mod_delete(Type, Values) when is_list(Type), is_list(Values) -> m(delete, Type, Values).
+mod_replace(Type, Values) when is_list(Type), is_list(Values) -> m(replace, Type, Values).
+
+m(Operation, Type, Values) ->
+ #'ModifyRequest_changes_SEQOF'{
+ operation = Operation,
+ modification = #'PartialAttribute'{
+ type = Type,
+ vals = Values}}.
+
+%%% --------------------------------------------------------------------
+%%% Modify an entry. Given an entry a number of modification
+%%% operations can be performed as one atomic operation.
+%%% Example:
+%%%
+%%% modify_dn(Handle,
+%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com",
+%%% "cn=Ben Emerson",
+%%% true,
+%%% ""
+%%% )
+%%% --------------------------------------------------------------------
+modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup)
+ when is_pid(Handle),is_list(Entry),is_list(NewRDN),is_atom(DelOldRDN),is_list(NewSup) ->
+ send(Handle, {modify_dn, Entry, NewRDN,
+ bool_p(DelOldRDN), optional(NewSup)}),
+ recv(Handle).
+
+%%% Sanity checks !
+
+bool_p(Bool) when Bool==true;Bool==false -> Bool.
+
+optional([]) -> asn1_NOVALUE;
+optional(Value) -> Value.
+
+%%% --------------------------------------------------------------------
+%%% Synchronous search of the Directory returning a
+%%% requested set of attributes.
+%%%
+%%% Example:
+%%%
+%%% Filter = eldap:substrings("cn", [{any,"o"}]),
+%%% eldap:search(S, [{base, "dc=bluetail, dc=com"},
+%%% {filter, Filter},
+%%% {attributes,["cn"]}])),
+%%%
+%%% Returned result: {ok, #eldap_search_result{}}
+%%%
+%%% Example:
+%%%
+%%% {ok,{eldap_search_result,
+%%% [{eldap_entry,
+%%% "cn=Magnus Froberg, dc=bluetail, dc=com",
+%%% [{"cn",["Magnus Froberg"]}]},
+%%% {eldap_entry,
+%%% "cn=Torbjorn Tornkvist, dc=bluetail, dc=com",
+%%% [{"cn",["Torbjorn Tornkvist"]}]}],
+%%% []}}
+%%%
+%%% --------------------------------------------------------------------
+search(Handle, A) when is_pid(Handle), is_record(A, eldap_search) ->
+ call_search(Handle, A);
+search(Handle, L) when is_pid(Handle), is_list(L) ->
+ case catch parse_search_args(L) of
+ {error, Emsg} -> {error, Emsg};
+ A when is_record(A, eldap_search) -> call_search(Handle, A)
+ end.
+
+call_search(Handle, A) ->
+ send(Handle, {search, A}),
+ recv(Handle).
+
+parse_search_args(Args) ->
+ parse_search_args(Args,
+ #eldap_search{scope = wholeSubtree,
+ deref = derefAlways}).
+
+parse_search_args([{base, Base}|T],A) ->
+ parse_search_args(T,A#eldap_search{base = Base});
+parse_search_args([{filter, Filter}|T],A) ->
+ parse_search_args(T,A#eldap_search{filter = Filter});
+parse_search_args([{scope, Scope}|T],A) ->
+ parse_search_args(T,A#eldap_search{scope = Scope});
+parse_search_args([{deref, Deref}|T],A) ->
+ parse_search_args(T,A#eldap_search{deref = Deref});
+parse_search_args([{attributes, Attrs}|T],A) ->
+ parse_search_args(T,A#eldap_search{attributes = Attrs});
+parse_search_args([{types_only, TypesOnly}|T],A) ->
+ parse_search_args(T,A#eldap_search{types_only = TypesOnly});
+parse_search_args([{timeout, Timeout}|T],A) when is_integer(Timeout) ->
+ parse_search_args(T,A#eldap_search{timeout = Timeout});
+parse_search_args([H|_],_) ->
+ throw({error,{unknown_arg, H}});
+parse_search_args([],A) ->
+ A.
+
+%%%
+%%% The Scope parameter
+%%%
+baseObject() -> baseObject.
+singleLevel() -> singleLevel.
+wholeSubtree() -> wholeSubtree.
+
+%%
+%% The derefAliases parameter
+%%
+neverDerefAliases() -> neverDerefAliases.
+derefInSearching() -> derefInSearching.
+derefFindingBaseObj() -> derefFindingBaseObj.
+derefAlways() -> derefAlways.
+
+%%%
+%%% Boolean filter operations
+%%%
+'and'(ListOfFilters) when is_list(ListOfFilters) -> {'and',ListOfFilters}.
+'or'(ListOfFilters) when is_list(ListOfFilters) -> {'or', ListOfFilters}.
+'not'(Filter) when is_tuple(Filter) -> {'not',Filter}.
+
+%%%
+%%% The following Filter parameters consist of an attribute
+%%% and an attribute value. Example: F("uid","tobbe")
+%%%
+equalityMatch(Desc, Value) -> {equalityMatch, av_assert(Desc, Value)}.
+greaterOrEqual(Desc, Value) -> {greaterOrEqual, av_assert(Desc, Value)}.
+lessOrEqual(Desc, Value) -> {lessOrEqual, av_assert(Desc, Value)}.
+approxMatch(Desc, Value) -> {approxMatch, av_assert(Desc, Value)}.
+
+av_assert(Desc, Value) ->
+ #'AttributeValueAssertion'{attributeDesc = Desc,
+ assertionValue = Value}.
+
+%%%
+%%% Filter to check for the presence of an attribute
+%%%
+present(Attribute) when is_list(Attribute) ->
+ {present, Attribute}.
+
+
+%%%
+%%% A substring filter seem to be based on a pattern:
+%%%
+%%% InitValue*AnyValue*FinalValue
+%%%
+%%% where all three parts seem to be optional (at least when
+%%% talking with an OpenLDAP server). Thus, the arguments
+%%% to substrings/2 looks like this:
+%%%
+%%% Type ::= string( <attribute> )
+%%% SubStr ::= listof( {initial,Value} | {any,Value}, {final,Value})
+%%%
+%%% Example: substrings("sn",[{initial,"To"},{any,"kv"},{final,"st"}])
+%%% will match entries containing: 'sn: Tornkvist'
+%%%
+substrings(Type, SubStr) when is_list(Type), is_list(SubStr) ->
+ Ss = {'SubstringFilter_substrings',v_substr(SubStr)},
+ {substrings,#'SubstringFilter'{type = Type,
+ substrings = Ss}}.
+
+%%% --------------------------------------------------------------------
+%%% Worker process. We keep track of a controlling process to
+%%% be able to terminate together with it.
+%%% --------------------------------------------------------------------
+
+init(Hosts, Opts, Cpid) ->
+ Data = parse_args(Opts, Cpid, #eldap{}),
+ case try_connect(Hosts, Data) of
+ {ok,Data2} ->
+ send(Cpid, {ok,self()}),
+ ?MODULE:loop(Cpid, Data2);
+ Else ->
+ send(Cpid, Else),
+ unlink(Cpid),
+ exit(Else)
+ end.
+
+parse_args([{port, Port}|T], Cpid, Data) when is_integer(Port) ->
+ parse_args(T, Cpid, Data#eldap{port = Port});
+parse_args([{timeout, Timeout}|T], Cpid, Data) when is_integer(Timeout),Timeout>0 ->
+ parse_args(T, Cpid, Data#eldap{timeout = Timeout});
+parse_args([{anon_auth, true}|T], Cpid, Data) ->
+ parse_args(T, Cpid, Data#eldap{anon_auth = false});
+parse_args([{anon_auth, _}|T], Cpid, Data) ->
+ parse_args(T, Cpid, Data);
+parse_args([{ssl, true}|T], Cpid, Data) ->
+ parse_args(T, Cpid, Data#eldap{use_tls = true});
+parse_args([{ssl, _}|T], Cpid, Data) ->
+ parse_args(T, Cpid, Data);
+parse_args([{log, F}|T], Cpid, Data) when is_function(F) ->
+ parse_args(T, Cpid, Data#eldap{log = F});
+parse_args([{log, _}|T], Cpid, Data) ->
+ parse_args(T, Cpid, Data);
+parse_args([H|_], Cpid, _) ->
+ send(Cpid, {error,{wrong_option,H}}),
+ exit(wrong_option);
+parse_args([], _, Data) ->
+ Data.
+
+%%% Try to connect to the hosts in the listed order,
+%%% and stop with the first one to which a successful
+%%% connection is made.
+
+try_connect([Host|Hosts], Data) ->
+ TcpOpts = [{packet, asn1}, {active,false}],
+ try do_connect(Host, Data, TcpOpts) of
+ {ok,Fd} -> {ok,Data#eldap{host = Host, fd = Fd}};
+ Err ->
+ log2(Data, "Connect: ~p failed ~p~n",[Host, Err]),
+ try_connect(Hosts, Data)
+ catch _:Err ->
+ log2(Data, "Connect: ~p failed ~p~n",[Host, Err]),
+ try_connect(Hosts, Data)
+ end;
+try_connect([],_) ->
+ {error,"connect failed"}.
+
+do_connect(Host, Data, Opts) when Data#eldap.use_tls == false ->
+ gen_tcp:connect(Host, Data#eldap.port, Opts, Data#eldap.timeout);
+do_connect(Host, Data, Opts) when Data#eldap.use_tls == true ->
+ ssl:connect(Host, Data#eldap.port, [{verify,0}|Opts]).
+
+
+loop(Cpid, Data) ->
+ receive
+
+ {From, {search, A}} ->
+ {Res,NewData} = do_search(Data, A),
+ send(From,Res),
+ ?MODULE:loop(Cpid, NewData);
+
+ {From, {modify, Obj, Mod}} ->
+ {Res,NewData} = do_modify(Data, Obj, Mod),
+ send(From,Res),
+ ?MODULE:loop(Cpid, NewData);
+
+ {From, {modify_dn, Obj, NewRDN, DelOldRDN, NewSup}} ->
+ {Res,NewData} = do_modify_dn(Data, Obj, NewRDN, DelOldRDN, NewSup),
+ send(From,Res),
+ ?MODULE:loop(Cpid, NewData);
+
+ {From, {add, Entry, Attrs}} ->
+ {Res,NewData} = do_add(Data, Entry, Attrs),
+ send(From,Res),
+ ?MODULE:loop(Cpid, NewData);
+
+ {From, {delete, Entry}} ->
+ {Res,NewData} = do_delete(Data, Entry),
+ send(From,Res),
+ ?MODULE:loop(Cpid, NewData);
+
+ {From, {simple_bind, Dn, Passwd}} ->
+ {Res,NewData} = do_simple_bind(Data, Dn, Passwd),
+ send(From,Res),
+ ?MODULE:loop(Cpid, NewData);
+
+ {From, {cnt_proc, NewCpid}} ->
+ unlink(Cpid),
+ send(From,ok),
+ ?PRINT("New Cpid is: ~p~n",[NewCpid]),
+ ?MODULE:loop(NewCpid, Data);
+
+ {_From, close} ->
+ unlink(Cpid),
+ exit(closed);
+
+ {Cpid, 'EXIT', Reason} ->
+ ?PRINT("Got EXIT from Cpid, reason=~p~n",[Reason]),
+ exit(Reason);
+
+ _XX ->
+ ?PRINT("loop got: ~p~n",[_XX]),
+ ?MODULE:loop(Cpid, Data)
+
+ end.
+
+%%% --------------------------------------------------------------------
+%%% bindRequest
+%%% --------------------------------------------------------------------
+
+%%% Authenticate ourselves to the directory using
+%%% simple authentication.
+
+do_simple_bind(Data, anon, anon) -> %% For testing
+ do_the_simple_bind(Data, "", "");
+do_simple_bind(Data, Dn, _Passwd) when Dn=="",Data#eldap.anon_auth==false ->
+ {{error,anonymous_auth},Data};
+do_simple_bind(Data, _Dn, Passwd) when Passwd=="",Data#eldap.anon_auth==false ->
+ {{error,anonymous_auth},Data};
+do_simple_bind(Data, Dn, Passwd) ->
+ do_the_simple_bind(Data, Dn, Passwd).
+
+do_the_simple_bind(Data, Dn, Passwd) ->
+ case catch exec_simple_bind(Data#eldap{binddn = Dn,
+ passwd = Passwd,
+ id = bump_id(Data)}) of
+ {ok,NewData} -> {ok,NewData};
+ {error,Emsg} -> {{error,Emsg},Data};
+ Else -> {{error,Else},Data}
+ end.
+
+exec_simple_bind(Data) ->
+ Req = #'BindRequest'{version = Data#eldap.version,
+ name = Data#eldap.binddn,
+ authentication = {simple, Data#eldap.passwd}},
+ log2(Data, "bind request = ~p~n", [Req]),
+ Reply = request(Data#eldap.fd, Data, Data#eldap.id, {bindRequest, Req}),
+ log2(Data, "bind reply = ~p~n", [Reply]),
+ exec_simple_bind_reply(Data, Reply).
+
+exec_simple_bind_reply(Data, {ok,Msg}) when
+ Msg#'LDAPMessage'.messageID == Data#eldap.id ->
+ case Msg#'LDAPMessage'.protocolOp of
+ {bindResponse, Result} ->
+ case Result#'BindResponse'.resultCode of
+ success -> {ok,Data};
+ Error -> {error, Error}
+ end;
+ Other -> {error, Other}
+ end;
+exec_simple_bind_reply(_, Error) ->
+ {error, Error}.
+
+
+%%% --------------------------------------------------------------------
+%%% searchRequest
+%%% --------------------------------------------------------------------
+
+do_search(Data, A) ->
+ case catch do_search_0(Data, A) of
+ {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data};
+ {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data};
+ {ok,Res,Ref,NewData} -> {{ok,polish(Res, Ref)},NewData};
+ {{error,Reason},NewData} -> {{error,Reason},NewData};
+ Else -> {ldap_closed_p(Data, Else),Data}
+ end.
+
+%%%
+%%% Polish the returned search result
+%%%
+
+polish(Res, Ref) ->
+ R = polish_result(Res),
+ %%% No special treatment of referrals at the moment.
+ #eldap_search_result{entries = R,
+ referrals = Ref}.
+
+polish_result([H|T]) when is_record(H, 'SearchResultEntry') ->
+ ObjectName = H#'SearchResultEntry'.objectName,
+ F = fun({_,A,V}) -> {A,V} end,
+ Attrs = lists:map(F, H#'SearchResultEntry'.attributes),
+ [#eldap_entry{object_name = ObjectName,
+ attributes = Attrs}|
+ polish_result(T)];
+polish_result([]) ->
+ [].
+
+do_search_0(Data, A) ->
+ Req = #'SearchRequest'{baseObject = A#eldap_search.base,
+ scope = v_scope(A#eldap_search.scope),
+ derefAliases = v_deref(A#eldap_search.deref),
+ sizeLimit = 0, % no size limit
+ timeLimit = v_timeout(A#eldap_search.timeout),
+ typesOnly = v_bool(A#eldap_search.types_only),
+ filter = v_filter(A#eldap_search.filter),
+ attributes = v_attributes(A#eldap_search.attributes)
+ },
+ Id = bump_id(Data),
+ collect_search_responses(Data#eldap{id=Id}, Req, Id).
+
+%%% The returned answers cames in one packet per entry
+%%% mixed with possible referals
+
+collect_search_responses(Data, Req, ID) ->
+ S = Data#eldap.fd,
+ log2(Data, "search request = ~p~n", [Req]),
+ send_request(S, Data, ID, {searchRequest, Req}),
+ Resp = recv_response(S, Data),
+ log2(Data, "search reply = ~p~n", [Resp]),
+ collect_search_responses(Data, S, ID, Resp, [], []).
+
+collect_search_responses(Data, S, ID, {ok,Msg}, Acc, Ref)
+ when is_record(Msg,'LDAPMessage') ->
+ case Msg#'LDAPMessage'.protocolOp of
+ {'searchResDone',R} ->
+ case R#'LDAPResult'.resultCode of
+ success ->
+ log2(Data, "search reply = searchResDone ~n", []),
+ {ok,Acc,Ref,Data};
+ Reason ->
+ {{error,Reason},Data}
+ end;
+ {'searchResEntry',R} when is_record(R,'SearchResultEntry') ->
+ Resp = recv_response(S, Data),
+ log2(Data, "search reply = ~p~n", [Resp]),
+ collect_search_responses(Data, S, ID, Resp, [R|Acc], Ref);
+ {'searchResRef',R} ->
+ %% At the moment we don't do anyting sensible here since
+ %% I haven't been able to trigger the server to generate
+ %% a response like this.
+ Resp = recv_response(S, Data),
+ log2(Data, "search reply = ~p~n", [Resp]),
+ collect_search_responses(Data, S, ID, Resp, Acc, [R|Ref]);
+ Else ->
+ throw({error,Else})
+ end;
+collect_search_responses(_, _, _, Else, _, _) ->
+ throw({error,Else}).
+
+%%% --------------------------------------------------------------------
+%%% addRequest
+%%% --------------------------------------------------------------------
+
+do_add(Data, Entry, Attrs) ->
+ case catch do_add_0(Data, Entry, Attrs) of
+ {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data};
+ {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data};
+ {ok,NewData} -> {ok,NewData};
+ Else -> {ldap_closed_p(Data, Else),Data}
+ end.
+
+do_add_0(Data, Entry, Attrs) ->
+ Req = #'AddRequest'{entry = Entry,
+ attributes = Attrs},
+ S = Data#eldap.fd,
+ Id = bump_id(Data),
+ log2(Data, "add request = ~p~n", [Req]),
+ Resp = request(S, Data, Id, {addRequest, Req}),
+ log2(Data, "add reply = ~p~n", [Resp]),
+ check_reply(Data#eldap{id = Id}, Resp, addResponse).
+
+
+%%% --------------------------------------------------------------------
+%%% deleteRequest
+%%% --------------------------------------------------------------------
+
+do_delete(Data, Entry) ->
+ case catch do_delete_0(Data, Entry) of
+ {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data};
+ {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data};
+ {ok,NewData} -> {ok,NewData};
+ Else -> {ldap_closed_p(Data, Else),Data}
+ end.
+
+do_delete_0(Data, Entry) ->
+ S = Data#eldap.fd,
+ Id = bump_id(Data),
+ log2(Data, "del request = ~p~n", [Entry]),
+ Resp = request(S, Data, Id, {delRequest, Entry}),
+ log2(Data, "del reply = ~p~n", [Resp]),
+ check_reply(Data#eldap{id = Id}, Resp, delResponse).
+
+
+%%% --------------------------------------------------------------------
+%%% modifyRequest
+%%% --------------------------------------------------------------------
+
+do_modify(Data, Obj, Mod) ->
+ case catch do_modify_0(Data, Obj, Mod) of
+ {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data};
+ {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data};
+ {ok,NewData} -> {ok,NewData};
+ Else -> {ldap_closed_p(Data, Else),Data}
+ end.
+
+do_modify_0(Data, Obj, Mod) ->
+ v_modifications(Mod),
+ Req = #'ModifyRequest'{object = Obj,
+ changes = Mod},
+ S = Data#eldap.fd,
+ Id = bump_id(Data),
+ log2(Data, "modify request = ~p~n", [Req]),
+ Resp = request(S, Data, Id, {modifyRequest, Req}),
+ log2(Data, "modify reply = ~p~n", [Resp]),
+ check_reply(Data#eldap{id = Id}, Resp, modifyResponse).
+
+%%% --------------------------------------------------------------------
+%%% modifyDNRequest
+%%% --------------------------------------------------------------------
+
+do_modify_dn(Data, Entry, NewRDN, DelOldRDN, NewSup) ->
+ case catch do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup) of
+ {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data};
+ {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data};
+ {ok,NewData} -> {ok,NewData};
+ Else -> {ldap_closed_p(Data, Else),Data}
+ end.
+
+do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup) ->
+ Req = #'ModifyDNRequest'{entry = Entry,
+ newrdn = NewRDN,
+ deleteoldrdn = DelOldRDN,
+ newSuperior = NewSup},
+ S = Data#eldap.fd,
+ Id = bump_id(Data),
+ log2(Data, "modify DN request = ~p~n", [Req]),
+ Resp = request(S, Data, Id, {modDNRequest, Req}),
+ log2(Data, "modify DN reply = ~p~n", [Resp]),
+ check_reply(Data#eldap{id = Id}, Resp, modDNResponse).
+
+%%% --------------------------------------------------------------------
+%%% Send an LDAP request and receive the answer
+%%% --------------------------------------------------------------------
+
+request(S, Data, ID, Request) ->
+ send_request(S, Data, ID, Request),
+ recv_response(S, Data).
+
+send_request(S, Data, ID, Request) ->
+ Message = #'LDAPMessage'{messageID = ID,
+ protocolOp = Request},
+ {ok,Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message),
+ case do_send(S, Data, Bytes) of
+ {error,Reason} -> throw({gen_tcp_error,Reason});
+ Else -> Else
+ end.
+
+do_send(S, Data, Bytes) when Data#eldap.use_tls == false ->
+ gen_tcp:send(S, Bytes);
+do_send(S, Data, Bytes) when Data#eldap.use_tls == true ->
+ ssl:send(S, Bytes).
+
+do_recv(S, #eldap{use_tls=false, timeout=Timeout}, Len) ->
+ gen_tcp:recv(S, Len, Timeout);
+do_recv(S, #eldap{use_tls=true, timeout=Timeout}, Len) ->
+ ssl:recv(S, Len, Timeout).
+
+recv_response(S, Data) ->
+ case do_recv(S, Data, 0) of
+ {ok, Packet} ->
+ check_tag(Packet),
+ case asn1rt:decode('ELDAPv3', 'LDAPMessage', Packet) of
+ {ok,Resp} -> {ok,Resp};
+ Error -> throw(Error)
+ end;
+ {error,Reason} ->
+ throw({gen_tcp_error, Reason});
+ Error ->
+ throw(Error)
+ end.
+
+%%% Sanity check of received packet
+check_tag(Data) ->
+ case asn1rt_ber_bin:decode_tag(l2b(Data)) of
+ {_Tag, Data1, _Rb} ->
+ case asn1rt_ber_bin:decode_length(l2b(Data1)) of
+ {{_Len, _Data2}, _Rb2} -> ok;
+ _ -> throw({error,decoded_tag_length})
+ end;
+ _ -> throw({error,decoded_tag})
+ end.
+
+%%% Check for expected kind of reply
+check_reply(Data, {ok,Msg}, Op) when
+ Msg#'LDAPMessage'.messageID == Data#eldap.id ->
+ case Msg#'LDAPMessage'.protocolOp of
+ {Op, Result} ->
+ case Result#'LDAPResult'.resultCode of
+ success -> {ok,Data};
+ Error -> {error, Error}
+ end;
+ Other -> {error, Other}
+ end;
+check_reply(_, Error, _) ->
+ {error, Error}.
+
+
+%%% --------------------------------------------------------------------
+%%% Verify the input data
+%%% --------------------------------------------------------------------
+
+v_filter({'and',L}) -> {'and',L};
+v_filter({'or', L}) -> {'or',L};
+v_filter({'not',L}) -> {'not',L};
+v_filter({equalityMatch,AV}) -> {equalityMatch,AV};
+v_filter({greaterOrEqual,AV}) -> {greaterOrEqual,AV};
+v_filter({lessOrEqual,AV}) -> {lessOrEqual,AV};
+v_filter({approxMatch,AV}) -> {approxMatch,AV};
+v_filter({present,A}) -> {present,A};
+v_filter({substrings,S}) when is_record(S,'SubstringFilter') -> {substrings,S};
+v_filter(_Filter) -> throw({error,concat(["unknown filter: ",_Filter])}).
+
+v_modifications(Mods) ->
+ F = fun({_,Op,_}) ->
+ case lists:member(Op,[add,delete,replace]) of
+ true -> true;
+ _ -> throw({error,{mod_operation,Op}})
+ end
+ end,
+ lists:foreach(F, Mods).
+
+v_substr([{Key,Str}|T]) when is_list(Str),Key==initial;Key==any;Key==final ->
+ [{Key,Str}|v_substr(T)];
+v_substr([H|_]) ->
+ throw({error,{substring_arg,H}});
+v_substr([]) ->
+ [].
+v_scope(baseObject) -> baseObject;
+v_scope(singleLevel) -> singleLevel;
+v_scope(wholeSubtree) -> wholeSubtree;
+v_scope(_Scope) -> throw({error,concat(["unknown scope: ",_Scope])}).
+
+v_deref(DR = neverDerefAliases) -> DR;
+v_deref(DR = derefInSearching) -> DR;
+v_deref(DR = derefFindingBaseObj) -> DR;
+v_deref(DR = derefAlways ) -> DR.
+
+v_bool(true) -> true;
+v_bool(false) -> false;
+v_bool(_Bool) -> throw({error,concat(["not Boolean: ",_Bool])}).
+
+v_timeout(I) when is_integer(I), I>=0 -> I;
+v_timeout(_I) -> throw({error,concat(["timeout not positive integer: ",_I])}).
+
+v_attributes(Attrs) ->
+ F = fun(A) when is_list(A) -> A;
+ (A) -> throw({error,concat(["attribute not String: ",A])})
+ end,
+ lists:map(F,Attrs).
+
+
+%%% --------------------------------------------------------------------
+%%% Log routines. Call a user provided log routine F.
+%%% --------------------------------------------------------------------
+
+%log1(Data, Str, Args) -> log(Data, Str, Args, 1).
+log2(Data, Str, Args) -> log(Data, Str, Args, 2).
+
+log(Data, Str, Args, Level) when is_function(Data#eldap.log) ->
+ catch (Data#eldap.log)(Level, Str, Args);
+log(_, _, _, _) ->
+ ok.
+
+
+%%% --------------------------------------------------------------------
+%%% Misc. routines
+%%% --------------------------------------------------------------------
+
+send(To,Msg) -> To ! {self(),Msg}.
+recv(From) ->
+ receive
+ {From,Msg} -> Msg;
+ {'EXIT', From, Reason} ->
+ {error, {internal_error, Reason}}
+ end.
+
+ldap_closed_p(Data, Emsg) when Data#eldap.use_tls == true ->
+ %% Check if the SSL socket seems to be alive or not
+ case catch ssl:sockname(Data#eldap.fd) of
+ {error, _} ->
+ ssl:close(Data#eldap.fd),
+ {error, ldap_closed};
+ {ok, _} ->
+ {error, Emsg};
+ _ ->
+ %% sockname crashes if the socket pid is not alive
+ {error, ldap_closed}
+ end;
+ldap_closed_p(Data, Emsg) ->
+ %% non-SSL socket
+ case inet:port(Data#eldap.fd) of
+ {error,_} -> {error, ldap_closed};
+ _ -> {error,Emsg}
+ end.
+
+bump_id(Data) -> Data#eldap.id + 1.
+
+
+%%% --------------------------------------------------------------------
+%%% parse_dn/1 - Implementation of RFC 2253:
+%%%
+%%% "UTF-8 String Representation of Distinguished Names"
+%%%
+%%% Test cases:
+%%%
+%%% The simplest case:
+%%%
+%%% 1> eldap:parse_dn("CN=Steve Kille,O=Isode Limited,C=GB").
+%%% {ok,[[{attribute_type_and_value,"CN","Steve Kille"}],
+%%% [{attribute_type_and_value,"O","Isode Limited"}],
+%%% [{attribute_type_and_value,"C","GB"}]]}
+%%%
+%%% The first RDN is multi-valued:
+%%%
+%%% 2> eldap:parse_dn("OU=Sales+CN=J. Smith,O=Widget Inc.,C=US").
+%%% {ok,[[{attribute_type_and_value,"OU","Sales"},
+%%% {attribute_type_and_value,"CN","J. Smith"}],
+%%% [{attribute_type_and_value,"O","Widget Inc."}],
+%%% [{attribute_type_and_value,"C","US"}]]}
+%%%
+%%% Quoting a comma:
+%%%
+%%% 3> eldap:parse_dn("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB").
+%%% {ok,[[{attribute_type_and_value,"CN","L. Eagle"}],
+%%% [{attribute_type_and_value,"O","Sue\\, Grabbit and Runn"}],
+%%% [{attribute_type_and_value,"C","GB"}]]}
+%%%
+%%% A value contains a carriage return:
+%%%
+%%% 4> eldap:parse_dn("CN=Before
+%%% 4> After,O=Test,C=GB").
+%%% {ok,[[{attribute_type_and_value,"CN","Before\nAfter"}],
+%%% [{attribute_type_and_value,"O","Test"}],
+%%% [{attribute_type_and_value,"C","GB"}]]}
+%%%
+%%% 5> eldap:parse_dn("CN=Before\\0DAfter,O=Test,C=GB").
+%%% {ok,[[{attribute_type_and_value,"CN","Before\\0DAfter"}],
+%%% [{attribute_type_and_value,"O","Test"}],
+%%% [{attribute_type_and_value,"C","GB"}]]}
+%%%
+%%% An RDN in OID form:
+%%%
+%%% 6> eldap:parse_dn("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB").
+%%% {ok,[[{attribute_type_and_value,"1.3.6.1.4.1.1466.0","#04024869"}],
+%%% [{attribute_type_and_value,"O","Test"}],
+%%% [{attribute_type_and_value,"C","GB"}]]}
+%%%
+%%%
+%%% --------------------------------------------------------------------
+
+parse_dn("") -> % empty DN string
+ {ok,[]};
+parse_dn([H|_] = Str) when H=/=$, -> % 1:st name-component !
+ case catch parse_name(Str,[]) of
+ {'EXIT',Reason} -> {parse_error,internal_error,Reason};
+ Else -> Else
+ end.
+
+parse_name("",Acc) ->
+ {ok,lists:reverse(Acc)};
+parse_name([$,|T],Acc) -> % N:th name-component !
+ parse_name(T,Acc);
+parse_name(Str,Acc) ->
+ {Rest,NameComponent} = parse_name_component(Str),
+ parse_name(Rest,[NameComponent|Acc]).
+
+parse_name_component(Str) ->
+ parse_name_component(Str,[]).
+
+parse_name_component(Str,Acc) ->
+ case parse_attribute_type_and_value(Str) of
+ {[$+|Rest], ATV} ->
+ parse_name_component(Rest,[ATV|Acc]);
+ {Rest,ATV} ->
+ {Rest,lists:reverse([ATV|Acc])}
+ end.
+
+parse_attribute_type_and_value(Str) ->
+ case parse_attribute_type(Str) of
+ {_Rest,[]} ->
+ parse_error(expecting_attribute_type,Str);
+ {Rest,Type} ->
+ Rest2 = parse_equal_sign(Rest),
+ {Rest3,Value} = parse_attribute_value(Rest2),
+ {Rest3,{attribute_type_and_value,Type,Value}}
+ end.
+
+-define(IS_ALPHA(X) , X>=$a,X=<$z;X>=$A,X=<$Z ).
+-define(IS_DIGIT(X) , X>=$0,X=<$9 ).
+-define(IS_SPECIAL(X) , X==$,;X==$=;X==$+;X==$<;X==$>;X==$#;X==$; ).
+-define(IS_QUOTECHAR(X) , X=/=$\\,X=/=$" ).
+-define(IS_STRINGCHAR(X) ,
+ X=/=$,,X=/=$=,X=/=$+,X=/=$<,X=/=$>,X=/=$#,X=/=$;,?IS_QUOTECHAR(X) ).
+-define(IS_HEXCHAR(X) , ?IS_DIGIT(X);X>=$a,X=<$f;X>=$A,X=<$F ).
+
+parse_attribute_type([H|T]) when ?IS_ALPHA(H) ->
+ %% NB: It must be an error in the RFC in the definition
+ %% of 'attributeType', should be: (ALPHA *keychar)
+ {Rest,KeyChars} = parse_keychars(T),
+ {Rest,[H|KeyChars]};
+parse_attribute_type([H|_] = Str) when ?IS_DIGIT(H) ->
+ parse_oid(Str);
+parse_attribute_type(Str) ->
+ parse_error(invalid_attribute_type,Str).
+
+
+
+%%% Is a hexstring !
+parse_attribute_value([$#,X,Y|T]) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) ->
+ {Rest,HexString} = parse_hexstring(T),
+ {Rest,[$#,X,Y|HexString]};
+%%% Is a "quotation-sequence" !
+parse_attribute_value([$"|T]) ->
+ {Rest,Quotation} = parse_quotation(T),
+ {Rest,[$"|Quotation]};
+%%% Is a stringchar , pair or Empty !
+parse_attribute_value(Str) ->
+ parse_string(Str).
+
+parse_hexstring(Str) ->
+ parse_hexstring(Str,[]).
+
+parse_hexstring([X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) ->
+ parse_hexstring(T,[Y,X|Acc]);
+parse_hexstring(T,Acc) ->
+ {T,lists:reverse(Acc)}.
+
+parse_quotation([$"|T]) -> % an empty: "" is ok !
+ {T,[$"]};
+parse_quotation(Str) ->
+ parse_quotation(Str,[]).
+
+%%% Parse to end of quotation
+parse_quotation([$"|T],Acc) ->
+ {T,lists:reverse([$"|Acc])};
+parse_quotation([X|T],Acc) when ?IS_QUOTECHAR(X) ->
+ parse_quotation(T,[X|Acc]);
+parse_quotation([$\\,X|T],Acc) when ?IS_SPECIAL(X) ->
+ parse_quotation(T,[X,$\\|Acc]);
+parse_quotation([$\\,$\\|T],Acc) ->
+ parse_quotation(T,[$\\,$\\|Acc]);
+parse_quotation([$\\,$"|T],Acc) ->
+ parse_quotation(T,[$",$\\|Acc]);
+parse_quotation([$\\,X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) ->
+ parse_quotation(T,[Y,X,$\\|Acc]);
+parse_quotation(T,_) ->
+ parse_error(expecting_double_quote_mark,T).
+
+parse_string(Str) ->
+ parse_string(Str,[]).
+
+parse_string("",Acc) ->
+ {"",lists:reverse(Acc)};
+parse_string([H|T],Acc) when ?IS_STRINGCHAR(H) ->
+ parse_string(T,[H|Acc]);
+parse_string([$\\,X|T],Acc) when ?IS_SPECIAL(X) -> % is a pair !
+ parse_string(T,[X,$\\|Acc]);
+parse_string([$\\,$\\|T],Acc) -> % is a pair !
+ parse_string(T,[$\\,$\\|Acc]);
+parse_string([$\\,$" |T],Acc) -> % is a pair !
+ parse_string(T,[$" ,$\\|Acc]);
+parse_string([$\\,X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> % is a pair!
+ parse_string(T,[Y,X,$\\|Acc]);
+parse_string(T,Acc) ->
+ {T,lists:reverse(Acc)}.
+
+parse_equal_sign([$=|T]) -> T;
+parse_equal_sign(T) -> parse_error(expecting_equal_sign,T).
+
+parse_keychars(Str) -> parse_keychars(Str,[]).
+
+parse_keychars([H|T],Acc) when ?IS_ALPHA(H) -> parse_keychars(T,[H|Acc]);
+parse_keychars([H|T],Acc) when ?IS_DIGIT(H) -> parse_keychars(T,[H|Acc]);
+parse_keychars([$-|T],Acc) -> parse_keychars(T,[$-|Acc]);
+parse_keychars(T,Acc) -> {T,lists:reverse(Acc)}.
+
+parse_oid(Str) -> parse_oid(Str,[]).
+
+parse_oid([H,$.|T], Acc) when ?IS_DIGIT(H) ->
+ parse_oid(T,[$.,H|Acc]);
+parse_oid([H|T], Acc) when ?IS_DIGIT(H) ->
+ parse_oid(T,[H|Acc]);
+parse_oid(T, Acc) ->
+ {T,lists:reverse(Acc)}.
+
+parse_error(Emsg,Rest) ->
+ throw({parse_error,Emsg,Rest}).
+
+
+%%% --------------------------------------------------------------------
+%%% Parse LDAP url according to RFC 2255
+%%%
+%%% Test case:
+%%%
+%%% 2> eldap:parse_ldap_url("ldap://10.42.126.33:389/cn=Administrative%20CA,o=Post%20Danmark,c=DK?certificateRevokationList;binary").
+%%% {ok,{{10,42,126,33},389},
+%%% [[{attribute_type_and_value,"cn","Administrative%20CA"}],
+%%% [{attribute_type_and_value,"o","Post%20Danmark"}],
+%%% [{attribute_type_and_value,"c","DK"}]],
+%%% {attributes,["certificateRevokationList;binary"]}}
+%%%
+%%% --------------------------------------------------------------------
+
+parse_ldap_url("ldap://" ++ Rest1 = Str) ->
+ {Rest2,HostPort} = parse_hostport(Rest1),
+ %% Split the string into DN and Attributes+etc
+ {Sdn,Rest3} = split_string(rm_leading_slash(Rest2),$?),
+ case parse_dn(Sdn) of
+ {parse_error,internal_error,_Reason} ->
+ {parse_error,internal_error,{Str,[]}};
+ {parse_error,Emsg,Tail} ->
+ Head = get_head(Str,Tail),
+ {parse_error,Emsg,{Head,Tail}};
+ {ok,DN} ->
+ %% We stop parsing here for now and leave
+ %% 'scope', 'filter' and 'extensions' to
+ %% be implemented later if needed.
+ {_Rest4,Attributes} = parse_attributes(Rest3),
+ {ok,HostPort,DN,Attributes}
+ end.
+
+rm_leading_slash([$/|Tail]) -> Tail;
+rm_leading_slash(Tail) -> Tail.
+
+parse_attributes([$?|Tail]) ->
+ case split_string(Tail,$?) of
+ {[],Attributes} ->
+ {[],{attributes,string:tokens(Attributes,",")}};
+ {Attributes,Rest} ->
+ {Rest,{attributes,string:tokens(Attributes,",")}}
+ end.
+
+parse_hostport(Str) ->
+ {HostPort,Rest} = split_string(Str,$/),
+ case split_string(HostPort,$:) of
+ {Shost,[]} ->
+ {Rest,{parse_host(Rest,Shost),?LDAP_PORT}};
+ {Shost,[$:|Sport]} ->
+ {Rest,{parse_host(Rest,Shost),
+ parse_port(Rest,Sport)}}
+ end.
+
+parse_port(Rest,Sport) ->
+ try list_to_integer(Sport)
+ catch _:_ -> parse_error(parsing_port,Rest)
+ end.
+
+parse_host(Rest,Shost) ->
+ case catch validate_host(Shost) of
+ {parse_error,Emsg,_} -> parse_error(Emsg,Rest);
+ Host -> Host
+ end.
+
+validate_host(Shost) ->
+ case inet_parse:address(Shost) of
+ {ok,Host} -> Host;
+ _ ->
+ case inet_parse:domain(Shost) of
+ true -> Shost;
+ _ -> parse_error(parsing_host,Shost)
+ end
+ end.
+
+
+split_string(Str,Key) ->
+ Pred = fun(X) when X==Key -> false; (_) -> true end,
+ lists:splitwith(Pred, Str).
+
+get_head(Str,Tail) ->
+ get_head(Str,Tail,[]).
+
+%%% Should always succeed !
+get_head([H|Tail],Tail,Rhead) -> lists:reverse([H|Rhead]);
+get_head([H|Rest],Tail,Rhead) -> get_head(Rest,Tail,[H|Rhead]).
+
+l2b(B) when is_binary(B) -> B;
+l2b(L) when is_list(L) -> list_to_binary(L).
+
diff --git a/lib/eldap/test/Makefile b/lib/eldap/test/Makefile
new file mode 100644
index 0000000000..3c5810eece
--- /dev/null
+++ b/lib/eldap/test/Makefile
@@ -0,0 +1,83 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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
+
+
+INCLUDES= -I. -I ../include
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ eldap_basic_SUITE
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+HRL_FILES=
+
+TARGET_FILES= \
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+SPEC_FILES = eldap.spec
+
+# COVER_FILE = eldap.cover
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/eldap_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += $(INCLUDES) -pa $(ERL_TOP)/lib/eldap/ebin
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+tests debug opt: $(TARGET_FILES)
+
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SPEC_FILES) $(ERL_FILES) $(COVER_FILE) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+# @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+release_docs_spec:
diff --git a/lib/eldap/test/eldap.spec b/lib/eldap/test/eldap.spec
new file mode 100644
index 0000000000..b14e9a655a
--- /dev/null
+++ b/lib/eldap/test/eldap.spec
@@ -0,0 +1 @@
+{suites,"../eldap_test",all}.
diff --git a/lib/eldap/test/eldap_basic_SUITE.erl b/lib/eldap/test/eldap_basic_SUITE.erl
new file mode 100644
index 0000000000..c7e3052b29
--- /dev/null
+++ b/lib/eldap/test/eldap_basic_SUITE.erl
@@ -0,0 +1,222 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(eldap_basic_SUITE).
+
+-compile(export_all).
+
+%%-include_lib("common_test/include/ct.hrl").
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("eldap/include/eldap.hrl").
+
+-define(TIMEOUT, 120000). % 2 min
+
+init_per_suite(Config0) ->
+ {{EldapHost,Port}, Config1} =
+ case catch ct:get_config(eldap_server, undefined) of
+ undefined -> %% Dev test only
+ Server = {"localhost", 9876},
+ {Server, [{eldap_server, {"localhost", 9876}}|Config0]};
+ {'EXIT', _} -> %% Dev test only
+ Server = {"localhost", 9876},
+ {Server, [{eldap_server, {"localhost", 9876}}|Config0]};
+ Server ->
+ {Server, [{eldap_server, Server}|Config0]}
+ end,
+ %% Add path for this test run
+ try
+ {ok, Handle} = eldap:open([EldapHost], [{port, Port}]),
+ ok = eldap:simple_bind(Handle, "cn=Manager,dc=ericsson,dc=se", "hejsan"),
+ {ok, MyHost} = inet:gethostname(),
+ Path = "dc="++MyHost++",dc=ericsson,dc=se",
+ Config = [{eldap_path,Path}|Config1],
+ eldap:add(Handle,"dc=ericsson,dc=se",
+ [{"objectclass", ["dcObject", "organization"]},
+ {"dc", ["ericsson"]}, {"o", ["Testing"]}]),
+ eldap:add(Handle,Path,
+ [{"objectclass", ["dcObject", "organization"]},
+ {"dc", [MyHost]}, {"o", ["Test machine"]}]),
+ Config
+ catch error:{badmatch,Error} ->
+ io:format("Eldap init error ~p~n ~p~n",[Error, erlang:get_stacktrace()]),
+ {skip, lists:flatten(io_lib:format("Ldap init failed with host ~p", [EldapHost]))}
+ end.
+end_per_suite(Config) ->
+ %% Cleanup everything
+ {EHost, Port} = proplists:get_value(eldap_server, Config),
+ Path = proplists:get_value(eldap_path, Config),
+ {ok, H} = eldap:open([EHost], [{port, Port}]),
+ ok = eldap:simple_bind(H, "cn=Manager,dc=ericsson,dc=se", "hejsan"),
+ case eldap:search(H, [{base, Path},
+ {filter, eldap:present("objectclass")},
+ {scope, eldap:wholeSubtree()}])
+ of
+ {ok, {eldap_search_result, Entries, _}} ->
+ [ok = eldap:delete(H, Entry) || {eldap_entry, Entry, _} <- Entries];
+ _ -> ignore
+ end,
+ ok.
+
+init_per_testcase(_TestCase, Config) -> Config.
+end_per_testcase(_TestCase, _Config) -> ok.
+
+%% suite() ->
+
+all() ->
+ [app,
+ api].
+
+app(doc) -> "Test that the eldap app file is ok";
+app(suite) -> [];
+app(Config) when is_list(Config) ->
+ ok = test_server:app_test(public_key).
+
+api(doc) -> "Basic test that all api functions works as expected";
+api(suite) -> [];
+api(Config) ->
+ {Host,Port} = proplists:get_value(eldap_server, Config),
+ {ok, H} = eldap:open([Host], [{port,Port}]),
+ %% {ok, H} = eldap:open([Host], [{port,Port+1}, {ssl, true}]),
+ BasePath = proplists:get_value(eldap_path, Config),
+ All = fun(Where) ->
+ eldap:search(H, #eldap_search{base=Where,
+ filter=eldap:present("objectclass"),
+ scope= eldap:wholeSubtree()})
+ end,
+ Search = fun(Filter) ->
+ eldap:search(H, #eldap_search{base=BasePath,
+ filter=Filter,
+ scope=eldap:singleLevel()})
+ end,
+ {ok, #eldap_search_result{entries=[_]}} = All(BasePath),
+ {error, noSuchObject} = All("cn=Bar,"++BasePath),
+
+ {error, _} = eldap:add(H, "cn=Jonas Jonsson," ++ BasePath,
+ [{"objectclass", ["person"]},
+ {"cn", ["Jonas Jonsson"]}, {"sn", ["Jonsson"]}]),
+ eldap:simple_bind(H, "cn=Manager,dc=ericsson,dc=se", "hejsan"),
+
+ %% Add
+ ok = eldap:add(H, "cn=Jonas Jonsson," ++ BasePath,
+ [{"objectclass", ["person"]},
+ {"cn", ["Jonas Jonsson"]}, {"sn", ["Jonsson"]}]),
+ ok = eldap:add(H, "cn=Foo Bar," ++ BasePath,
+ [{"objectclass", ["person"]},
+ {"cn", ["Foo Bar"]}, {"sn", ["Bar"]}, {"telephoneNumber", ["555-1232", "555-5432"]}]),
+ ok = eldap:add(H, "ou=Team," ++ BasePath,
+ [{"objectclass", ["organizationalUnit"]},
+ {"ou", ["Team"]}]),
+
+ %% Search
+ JJSR = {ok, #eldap_search_result{entries=[#eldap_entry{}]}} = Search(eldap:equalityMatch("sn", "Jonsson")),
+ JJSR = Search(eldap:substrings("sn", [{any, "ss"}])),
+ FBSR = {ok, #eldap_search_result{entries=[#eldap_entry{object_name=FB}]}} =
+ Search(eldap:substrings("sn", [{any, "a"}])),
+ FBSR = Search(eldap:substrings("sn", [{initial, "B"}])),
+ FBSR = Search(eldap:substrings("sn", [{final, "r"}])),
+
+ F_AND = eldap:'and'([eldap:present("objectclass"), eldap:present("ou")]),
+ {ok, #eldap_search_result{entries=[#eldap_entry{}]}} = Search(F_AND),
+ F_NOT = eldap:'and'([eldap:present("objectclass"), eldap:'not'(eldap:present("ou"))]),
+ {ok, #eldap_search_result{entries=[#eldap_entry{}, #eldap_entry{}]}} = Search(F_NOT),
+
+ %% MODIFY
+ Mod = [eldap:mod_replace("telephoneNumber", ["555-12345"]),
+ eldap:mod_add("description", ["Nice guy"])],
+ %% io:format("MOD ~p ~p ~n",[FB, Mod]),
+ ok = eldap:modify(H, FB, Mod),
+ %% DELETE ATTR
+ ok = eldap:modify(H, FB, [eldap:mod_delete("telephoneNumber", [])]),
+
+ %% DELETE
+ {error, entryAlreadyExists} = eldap:add(H, "cn=Jonas Jonsson," ++ BasePath,
+ [{"objectclass", ["person"]},
+ {"cn", ["Jonas Jonsson"]}, {"sn", ["Jonsson"]}]),
+ ok = eldap:delete(H, "cn=Jonas Jonsson," ++ BasePath),
+ {error, noSuchObject} = eldap:delete(H, "cn=Jonas Jonsson," ++ BasePath),
+
+ %% MODIFY_DN
+ ok = eldap:modify_dn(H, FB, "cn=Niclas Andre", true, ""),
+ %%io:format("Res ~p~n ~p~n",[R, All(BasePath)]),
+
+ eldap:close(H),
+ ok.
+
+add(H, Attr, Value, Path0, Attrs, Class) ->
+ Path = case Path0 of
+ [] -> Attr ++ "=" ++ Value;
+ _ -> Attr ++ "=" ++ Value ++ "," ++ Path0
+ end,
+ case eldap:add(H, Path, [{"objectclass", Class}, {Attr, [Value]}] ++ Attrs)
+ of
+ ok -> {ok, Path};
+ {error, E = entryAlreadyExists} -> {E, Path};
+ R = {error, Reason} ->
+ io:format("~p:~p: ~s,~s =>~n ~p~n",
+ [?MODULE,?LINE, Attr, Value, R]),
+ exit({ldap, add, Reason})
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Develop
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+test() ->
+ run().
+
+run() ->
+ Cases = all(),
+ run(Cases).
+
+run(Case) when is_atom(Case) ->
+ run([Case]);
+run(Cases) when is_list(Cases) ->
+ Run = fun(Test, Config0) ->
+ Config = init_per_testcase(Test, Config0),
+ try
+ io:format("~nTest ~p ... ",[Test]),
+ ?MODULE:Test(Config),
+ end_per_testcase(Test, Config),
+ io:format("ok~n",[])
+ catch _:Reason ->
+ io:format("~n FAIL (~p): ~p~n ~p~n",
+ [Test, Reason, erlang:get_stacktrace()])
+ end
+ end,
+ process_flag(trap_exit, true),
+ Pid = spawn_link(fun() ->
+ case init_per_suite([]) of
+ {skip, Reason} -> io:format("Skip ~s~n",[Reason]);
+ Config ->
+ try
+ [Run(Test, Config) || Test <- Cases]
+ catch _:Err ->
+ io:format("Error ~p in ~p~n",[Err, erlang:get_stacktrace()])
+ end,
+ end_per_suite(Config)
+ end
+ end),
+ receive
+ {'EXIT', Pid, normal} -> ok;
+ Msg -> io:format("Received ~p (~p)~n",[Msg, Pid])
+ after 100 -> ok end,
+ process_flag(trap_exit, false),
+ ok.
diff --git a/lib/eldap/test/ldap_server/slapd.conf b/lib/eldap/test/ldap_server/slapd.conf
new file mode 100644
index 0000000000..87be676d9f
--- /dev/null
+++ b/lib/eldap/test/ldap_server/slapd.conf
@@ -0,0 +1,14 @@
+include /etc/ldap/schema/core.schema
+pidfile /tmp/openldap-data/slapd.pid
+argsfile /tmp/openldap-data/slapd.args
+
+database bdb
+suffix "dc=ericsson,dc=se"
+rootdn "cn=Manager,dc=ericsson,dc=se"
+rootpw hejsan
+# The database must exist before running slapd
+directory /tmp/openldap-data
+# Indices to maintain
+index objectClass eq
+# URI "ldap://0.0.0.0:9876 ldaps://0.0.0.0:9870"
+# servers/slapd/slapd -d 255 -h "ldap://0.0.0.0:9876 ldaps://0.0.0.0:9870" -f /ldisk/dgud/src/otp/lib/eldap/test/ldap_server/slapd.conf \ No newline at end of file
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
new file mode 100644
index 0000000000..c9d6e4e324
--- /dev/null
+++ b/lib/eldap/vsn.mk
@@ -0,0 +1 @@
+ELDAP_VSN = 1.0
diff --git a/lib/erl_docgen/Makefile b/lib/erl_docgen/Makefile
index 93a6353cac..19b129fd5d 100644
--- a/lib/erl_docgen/Makefile
+++ b/lib/erl_docgen/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
@@ -23,8 +23,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = src priv
-#doc/src
+SUB_DIRECTORIES = src priv doc/src
include vsn.mk
VSN = $(ERL_DOCGEN_VSN)
diff --git a/lib/erl_docgen/doc/html/.gitignore b/lib/erl_docgen/doc/html/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/erl_docgen/doc/html/.gitignore
diff --git a/lib/erl_docgen/doc/man6/.gitignore b/lib/erl_docgen/doc/man6/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/erl_docgen/doc/man6/.gitignore
diff --git a/lib/erl_docgen/doc/pdf/.gitignore b/lib/erl_docgen/doc/pdf/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/erl_docgen/doc/pdf/.gitignore
diff --git a/lib/erl_docgen/doc/src/Makefile b/lib/erl_docgen/doc/src/Makefile
new file mode 100644
index 0000000000..a254c4fb6d
--- /dev/null
+++ b/lib/erl_docgen/doc/src/Makefile
@@ -0,0 +1,136 @@
+#
+# %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%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(ERL_DOCGEN_VSN)
+APPLICATION=erl_docgen
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+XML_APPLICATION_FILES = ref_man.xml
+XML_REF6_FILES = \
+ erl_docgen_app.xml
+
+XML_PART_FILES = \
+ part.xml
+
+XML_CHAPTER_FILES = \
+ overview.xml \
+ doc-build.xml \
+ user_guide_dtds.xml \
+ refman_dtds.xml \
+ notes.xml \
+ inline_tags.xml \
+ header_tags.xml \
+ character_entities.xml \
+ block_tags.xml
+
+BOOK_FILES = book.xml
+
+XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF6_FILES) \
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+
+TECHNICAL_DESCR_FILES =
+
+EXAMPLE_FILES = \
+ example.txt
+
+GIF_FILES = \
+ man.gif
+
+# ----------------------------------------------------
+
+HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+INFO_FILE = ../../info
+
+MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+XML_FLAGS +=
+DVIPS_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+docs: pdf html man
+
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+$(HTMLDIR)/example.txt: example.txt
+ $(INSTALL_DATA) $< $@
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: gifs examples $(HTML_REF_MAN_FILE)
+
+clean clean_docs:
+ rm -rf $(HTMLDIR)/*
+ rm -f $(MAN6DIR)/*
+ rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f errs core *~
+ rm -f $(JD_HTML) $(JD_PACK)
+
+man: $(MAN6_FILES)
+
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+examples: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+debug opt:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_docs_spec: docs
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(HTMLDIR)/* \
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
+
+release_spec:
diff --git a/lib/erl_docgen/doc/src/block_tags.xml b/lib/erl_docgen/doc/src/block_tags.xml
new file mode 100644
index 0000000000..0900d7f008
--- /dev/null
+++ b/lib/erl_docgen/doc/src/block_tags.xml
@@ -0,0 +1,431 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>Block Tags</title>
+ <prepared/>
+ <docno/>
+ <date/>
+ <rev/>
+ <file>block_tags.xml</file>
+ </header>
+
+ <p>Block tags typically define a separate block of information, such
+ as a paragraph or a list.</p>
+
+ <p>The following subset of block tags are common for all DTDs in
+ the OTP DTD suite:
+ <marker id="block_subset"></marker>
+ <seealso marker="#pTAG">&lt;p&gt;</seealso>,
+ <seealso marker="#preTAG">&lt;pre&gt;</seealso>,
+ <seealso marker="#codeTAG">&lt;code&gt;</seealso>,
+ <seealso marker="#listTAG">&lt;list&gt;</seealso>,
+ <seealso marker="#taglistTAG">&lt;taglist&gt;</seealso>,
+ <seealso marker="#codeincludeTAG">&lt;codeinclude&gt;</seealso> and
+ <seealso marker="#erlevalTAG">&lt;erleval&gt;</seealso>.
+ </p>
+
+ <section>
+ <marker id="brTAG"></marker>
+ <title>&lt;br&gt; - Line Break</title>
+
+ <p>Forces a newline. Example:</p>
+ <pre>
+Eat yourself&lt;br/&gt;senseless!
+ </pre>
+ <p>results in:</p>
+ <p>Eat yourself<br/>senseless!</p>
+
+ <p>The <c><![CDATA[<br>]]></c> tag is both a block- and an inline
+ tag.</p>
+ </section>
+
+ <section>
+ <marker id="codeTAG"></marker>
+ <title>&lt;code&gt; - Code Example</title>
+
+ <p>Highlight code examples. Example:</p>
+ <pre>
+&lt;code>
+sum([H|T]) ->
+ H + sum(T);
+sum([]) ->
+ 0.
+&lt;/code>
+ </pre>
+ <p>results in:</p>
+ <code>
+sum([H|T]) ->
+ H + sum(T);
+sum([]) ->
+ 0.
+ </code>
+
+ <p>There is an attribute <c>type = "erl" | "c" | "none"</c>, but
+ currently this attribute is ignored. Default value
+ is <c>"none"</c></p>
+
+ <note>
+ <p>No tags are allowed within the tag and no
+ <seealso marker="character_entities">character
+ entities</seealso> are expanded.</p>
+ </note>
+ </section>
+
+ <section>
+ <marker id="codeincludeTAG"></marker>
+ <title>&lt;codeinclude&gt; - Code Inclusion</title>
+
+ <p>Include external code snippets. The attribute <c>file</c>
+ gives the file name and <c>tag</c> defines a string which
+ delimits the code snippet. Example:</p>
+ <pre>
+&lt;codeinclude file="example.txt" tag="%% Erlang example"/&gt;
+ </pre>
+ <p>results in:</p>
+ <codeinclude file="example.txt" tag="%% Erlang example"/>
+
+ <p>provided there is a file named <c>examples.txt</c> looking like this:
+ </p>
+ <code>
+...
+
+%% Erlang example
+-module(example).
+
+start() ->
+ {error,"Pid required!"}.
+start(Pid) ->
+ spawn(fun() -> init(Pid) end).
+%% Erlang example
+
+...
+ </code>
+
+ <p>If the <c>tag</c> attribute is omitted, the whole file is
+ included.</p>
+
+ <p>There is also an attribute <c>type = "erl" | "c" | "none"</c>, but
+ currently this attribute is ignored. Default value
+ is <c>"none"</c></p>
+ </section>
+
+ <section>
+ <marker id="erlevalTAG"></marker>
+ <title>&lt;erleval&gt; - Erlang Evaluation</title>
+
+ <p>Include the result from evaluating an Erlang expression. Example:
+ </p>
+ <code><![CDATA[
+<erleval expr="{A,b,C}={a,b,c}. "/>
+ ]]></code>
+ <p>results in:</p>
+ <erleval expr="{A,b,C}={a,b,c}. "></erleval>
+
+ <p>Note the '.' and space after the expression.</p>
+ </section>
+
+ <section>
+ <marker id="listTAG"></marker>
+ <title>&lt;list&gt; - List</title>
+
+ <p>The attribute <c>type = "ordered"|"bulleted"</c> decides if
+ the list is numbered or bulleted. Default is <c>"bulleted"</c>.
+ </p>
+
+ <p>Lists contains list items, tag <c><![CDATA[<item>]]></c>, which
+ can contain plain text,
+ the <seealso marker="#block_subset">common subset of block
+ tags</seealso> and <seealso marker="inline_tags">inline
+ tags</seealso>. Example:</p>
+ <pre>
+&lt;list type="ordered"&gt;
+ &lt;item&gt;Askosal:
+ &lt;list&gt;
+ &lt;item&gt;Nullalisis&lt;/item>
+ &lt;item&gt;Facilisis&lt;/item>
+ &lt;/list&gt;
+ &lt;/item>
+ &lt;item&gt;Ankara&lt;/item>
+&lt;/list&gt;
+ </pre>
+ <p>results in:</p>
+ <list type="ordered">
+ <item>
+ <p>Askosal:</p>
+ <list type="bulleted">
+ <item>Nullalisis</item>
+ <item>Facilisis</item>
+ </list>
+ </item>
+ <item>Ankara</item>
+ </list>
+ </section>
+
+ <section>
+ <marker id="markerTAG"></marker>
+ <title>&lt;marker&gt; - Marker</title>
+
+ <p>Used as an anchor for hypertext references. The
+ <c><![CDATA[<marker>]]></c> tag is both a block- and an inline
+ tag and is described in
+ the <seealso marker="inline_tags#markerTAG">Inline Tags</seealso>
+ section.</p>
+ </section>
+
+ <section>
+ <marker id="pTAG"></marker>
+ <title>&lt;p&gt; - Paragraph</title>
+
+ <p>Paragraphs contain plain text and
+ <seealso marker="inline_tags">inline tags</seealso>. Example:</p>
+ <pre>
+&lt;p&gt;I call specific attention to
+ the authority given by the &lt;em&gt;21st Amendment&lt;/em&gt;
+ to the Constitution to prohibit transportation
+ or importation of intoxicating liquors into
+ any State in violation of the laws of such
+ State.&lt;/p&gt;
+ </pre>
+ <p>results in:</p>
+ <p>I call specific attention to
+ the authority given by the <em>21st Amendment</em>
+ to the Constitution to prohibit transportation
+ or importation of intoxicating liquors into
+ any State in violation of the laws of such
+ State.</p>
+ </section>
+
+ <section>
+ <marker id="noteTAG"></marker>
+ <title>&lt;note&gt; - Note</title>
+
+ <p>Highlights a note. Can contain block tags except
+ <c><![CDATA[<note>]]></c>, <c><![CDATA[<warning>]]></c>,
+ <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.
+ Example:</p>
+<pre>
+&lt;note>
+ &lt;p>This function is mainly intended for debugging.&lt;/p>
+&lt;/note>
+ </pre>
+ <p>results in:</p>
+ <note>
+ <p>This function is mainly intended for debugging.</p>
+ </note>
+ </section>
+
+ <section>
+ <marker id="preTAG"></marker>
+ <title>&lt;pre&gt; - Pre-formatted Text</title>
+
+ <p>Used for documentation of system interaction. Can contain text,
+ <seealso marker="inline_tags#seealsoTAG">seealso</seealso>,
+ <seealso marker="inline_tags#urlTAG">url</seealso> and
+ <c><![CDATA[<input>]]></c> tags.</p>
+
+ <p>The <c><![CDATA[<input>]]></c> tag is used to highlight user
+ input. Example:</p>
+ <pre>
+&lt;pre&gt;
+$ &lt;input&gt;erl&lt;/input&gt;
+Erlang (BEAM) emulator version 5.5.3 [async-threads:0] [hipe] [kernel-poll:false]
+
+Eshell V5.5.3 (abort with ^G)
+1&gt; &lt;input&gt;pwd().&lt;/input&gt;
+/home/user
+2&gt; &lt;input&gt;halt().&lt;/input&gt;
+&lt;/pre&gt;
+ </pre>
+ <p> results in:</p>
+ <pre>
+$ <input>erl</input>
+Erlang (BEAM) emulator version 5.5.3 [async-threads:0] [hipe] [kernel-poll:false]
+
+Eshell V5.5.3 (abort with ^G)
+1> <input>pwd().</input>
+/home/user
+2> <input>halt().</input>
+ </pre>
+
+ <p>All <seealso marker="character_entities">character
+ entities</seealso> are expanded.</p>
+ </section>
+
+ <section>
+ <marker id="quoteTAG"></marker>
+ <title>&lt;quote&gt; - Quotation</title>
+
+ <p>Highlight quotations from other works, or dialog spoken by
+ characters in a narrative. Contains one or more
+ <seealso marker="#pTAG">&lt;p&gt;</seealso> tags. Example:</p>
+ <pre>
+&lt;p&gt;Whereas Section 217(a) of the Act of Congress entitled
+"An Act ..." approved June 16, 1933, provides as follows:&lt;/p&gt;
+&lt;quote&gt;
+ &lt;p&gt;Section 217(a) The President shall proclaim the law.&lt;/p>
+&lt;/quote&gt;
+ </pre>
+ <p>results in:</p>
+ <p>Whereas Section 217(a) of the Act of Congress entitled
+ "An Act ..." approved June 16, 1933, provides as follows:</p>
+ <quote>
+ <p>Section 217(a) The President shall proclaim the law.</p>
+ </quote>
+ </section>
+
+ <section>
+ <marker id="taglistTAG"></marker>
+ <marker id="tagTAG"></marker>
+ <title>&lt;taglist&gt; - Definition List</title>
+
+ <p>Definition lists contains pairs of tags,
+ <c><![CDATA[<tag>]]></c>, and list items,
+ <c><![CDATA[<item>]]></c>.</p>
+
+ <p><c><![CDATA[<tag>]]></c> can contain plain text,
+ <seealso marker="inline_tags#cTAG">&lt;c&gt;</seealso>,
+ <seealso marker="inline_tags#emTAG">&lt;em&gt;</seealso>,
+ <seealso marker="inline_tags#seealsoTAG">&lt;seealso&gt;</seealso>
+ and <seealso marker="inline_tags#urlTAG">&lt;url&gt;</seealso>
+ tags.</p>
+
+ <p><c><![CDATA[<item>]]></c> can contain plain text,
+ the <seealso marker="#block_subset">common subset of block
+ tags</seealso> and <seealso marker="inline_tags">inline
+ tags</seealso>. Example:</p>
+ <pre>
+&lt;taglist>
+ &lt;tag>&lt;c>eacces&lt;/c>&lt;/tag>
+ &lt;item>Permission denied.&lt;/item>
+ &lt;tag>&lt;c>enoent&lt;/c>&lt;/tag>
+ &lt;item>No such file or directory.&lt;/item>
+&lt;/taglist>
+ </pre>
+ <p>results in:</p>
+ <taglist>
+ <tag><c>eacces</c></tag>
+ <item>Permission denied.</item>
+ <tag><c>enoent</c></tag>
+ <item>No such file or directory.</item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="warningTAG"></marker>
+ <title>&lt;warning&gt; - Warning</title>
+
+ <p>Highlights a warning. Can contain block tags except
+ <c><![CDATA[<note>]]></c>, <c><![CDATA[<warning>]]></c>,
+ <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.
+ Example:</p>
+<pre>
+&lt;warning>
+ &lt;p>This function might be removed in a future version without
+ prior warning.&lt;/p>
+&lt;/warning>
+ </pre>
+ <p>results in:</p>
+ <warning>
+ <p>This function might be removed in a future version without
+ prior warning.</p>
+ </warning>
+ </section>
+
+ <section>
+ <marker id="imageTAG"></marker>
+ <marker id="icaptionTAG"></marker>
+ <title>&lt;image&gt; - Image</title>
+
+ <p>Graphics is imported using the <c><![CDATA[<image>]]></c> tag.
+ An image caption <c><![CDATA[<icaption>]]></c>, containing plain
+ text, must be supplied. Example:</p>
+ <pre>
+&lt;image file="man"&gt;
+ &lt;icaption&gt;A Silly Man&lt;/icaption&gt;
+&lt;/image&gt;
+ </pre>
+ <p>results in:</p>
+ <image file="man.gif">
+ <icaption>A Silly Man</icaption>
+ </image>
+
+ <p>This assumes that <c>man.gif</c> exists in the current directory.
+ </p>
+ </section>
+
+ <section>
+ <marker id="tableTAG"></marker>
+ <marker id="rowTAG"></marker>
+ <marker id="cellTAG"></marker>
+ <marker id="tcaptionTAG"></marker>
+ <title>&lt;table&gt; - Table</title>
+
+ <p>The table format is similar to how tables are described in HTML
+ 3.2. A table contains one or more rows, <c><![CDATA[<row>]]></c>,
+ and a table caption <c><![CDATA[<tcaption>]]></c>, containing
+ plain text.</p>
+
+ <p>Each row contains one or more cells, <c><![CDATA[<cell>]]></c>.
+ The attributes <c>align = "left"|"center"|"right"</c> and
+ <c>valign = "top"|"middle"|"bottom"</c> decides how text is
+ aligned in the cell horizontally and vertically. Default is
+ "<c>left</c>" and "<c>middle</c>".</p>
+
+ <p>Each cell contains plain text and
+ <seealso marker="inline_tags">inline tags</seealso>. Example:</p>
+ <pre><![CDATA[
+ <table>
+ <row>
+ <cell align="left" valign="top"><em>Boys</em></cell>
+ <cell align="center" valign="middle"><em>Girls</em></cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">Juda</cell>
+ <cell align="right" valign="bottom">Susy</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">Anders</cell>
+ <cell align="left" valign="middle">Victoria</cell>
+ </row>
+ <tcaption>A table caption</tcaption>
+ </table>
+ ]]></pre>
+ <p>results in:</p>
+ <table>
+ <row>
+ <cell align="left" valign="top"><em>Boys</em></cell>
+ <cell align="center" valign="middle"><em>Girls</em></cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">Juda</cell>
+ <cell align="right" valign="bottom">Susy</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">Anders</cell>
+ <cell align="left" valign="middle">Victoria</cell>
+ </row>
+ <tcaption>A table caption</tcaption>
+ </table>
+ </section>
+</chapter>
+
diff --git a/lib/erl_docgen/doc/src/book.xml b/lib/erl_docgen/doc/src/book.xml
index 9df5c39271..73bfb7916d 100644
--- a/lib/erl_docgen/doc/src/book.xml
+++ b/lib/erl_docgen/doc/src/book.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE book SYSTEM "book.dtd">
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,27 +21,26 @@
</legalnotice>
- <title>erl_docgen</title>
+ <title>Erl_Docgen</title>
<prepared>Lars Thorsen</prepared>
<docno></docno>
- <date>2009-11-10</date>
- <rev>0.1</rev>
+ <date>2011-11-10</date>
+ <rev>0.3</rev>
<file>book.xml</file>
</header>
- <insidecover>
- </insidecover>
<pagetext>erl_docgen</pagetext>
<preamble>
<contents level="2"></contents>
</preamble>
<parts lift="no">
+ <xi:include href="part.xml"/>
</parts>
<applications>
+ <xi:include href="ref_man.xml"/>
</applications>
<releasenotes>
<xi:include href="notes.xml"/>
</releasenotes>
- <listofterms></listofterms>
<index></index>
</book>
diff --git a/lib/erl_docgen/doc/src/character_entities.xml b/lib/erl_docgen/doc/src/character_entities.xml
new file mode 100644
index 0000000000..9f55b68d18
--- /dev/null
+++ b/lib/erl_docgen/doc/src/character_entities.xml
@@ -0,0 +1,546 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>Character Entities</title>
+ <prepared/>
+ <docno/>
+ <date/>
+ <rev/>
+ <file>character_entities.xml</file>
+ </header>
+
+ <section>
+ <title>Added Latin 1</title>
+
+ <p>The OTP DTD suite uses the same character entities as
+ defined in HTML 3.2
+ (<c>ISO 8879-1986//ENTITIES Added Latin 1//EN//HTML</c>). That is:
+ for an &amp; (ampersand), use the entity: <c>&amp;amp;</c>, for
+ &ouml; use the entity <c>&amp;ouml;</c> and so on.</p>
+
+ <table>
+ <row>
+ <cell align="left" valign="middle"><em>Character</em></cell>
+ <cell align="left" valign="middle"><em>Entity</em></cell>
+ <cell align="left" valign="middle"><em>Description</em></cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&amp;</cell>
+ <cell align="left" valign="middle">&amp;amp;</cell>
+ <cell align="left" valign="middle">ampersand</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&gt;</cell>
+ <cell align="left" valign="middle">&amp;gt;</cell>
+ <cell align="left" valign="middle">greater than</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&lt;</cell>
+ <cell align="left" valign="middle">&amp;lt;</cell>
+ <cell align="left" valign="middle">less than</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&nbsp;</cell>
+ <cell align="left" valign="middle">&amp;nbsp;</cell>
+ <cell align="left" valign="middle">no-break space</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&iexcl;</cell>
+ <cell align="left" valign="middle">&amp;iexcl;</cell>
+ <cell align="left" valign="middle">inverted exclamation mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&cent;</cell>
+ <cell align="left" valign="middle">&amp;cent;</cell>
+ <cell align="left" valign="middle">cent sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&pound;</cell>
+ <cell align="left" valign="middle">&amp;pound;</cell>
+ <cell align="left" valign="middle">pound sterling sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&curren;</cell>
+ <cell align="left" valign="middle">&amp;curren;</cell>
+ <cell align="left" valign="middle">general currency sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&yen;</cell>
+ <cell align="left" valign="middle">&amp;yen;</cell>
+ <cell align="left" valign="middle">yen sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&brvbar;</cell>
+ <cell align="left" valign="middle">&amp;brvbar;</cell>
+ <cell align="left" valign="middle">broken (vertical) bar</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&sect;</cell>
+ <cell align="left" valign="middle">&amp;sect;</cell>
+ <cell align="left" valign="middle">section sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&uml;</cell>
+ <cell align="left" valign="middle">&amp;uml;</cell>
+ <cell align="left" valign="middle">umlaut (dieresis)</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&copy;</cell>
+ <cell align="left" valign="middle">&amp;copy;</cell>
+ <cell align="left" valign="middle">copyright sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ordf;</cell>
+ <cell align="left" valign="middle">&amp;ordf;</cell>
+ <cell align="left" valign="middle">ordinal indicator, feminine</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&laquo;</cell>
+ <cell align="left" valign="middle">&amp;laquo;</cell>
+ <cell align="left" valign="middle">angle quotation mark, left</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&not;</cell>
+ <cell align="left" valign="middle">&amp;not;</cell>
+ <cell align="left" valign="middle">not sign</cell>
+ </row>
+ <row>
+ <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>
+ <row>
+ <cell align="left" valign="middle">&reg;</cell>
+ <cell align="left" valign="middle">&amp;reg;</cell>
+ <cell align="left" valign="middle">registered sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&macr;</cell>
+ <cell align="left" valign="middle">&amp;macr;</cell>
+ <cell align="left" valign="middle">macron</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&deg;</cell>
+ <cell align="left" valign="middle">&amp;deg;</cell>
+ <cell align="left" valign="middle">degree sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&plusmn;</cell>
+ <cell align="left" valign="middle">&amp;plusmn;</cell>
+ <cell align="left" valign="middle">plus-or-minus</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&sup2;</cell>
+ <cell align="left" valign="middle">&amp;sup2;</cell>
+ <cell align="left" valign="middle">superscript two</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&sup3;</cell>
+ <cell align="left" valign="middle">&amp;sup3;</cell>
+ <cell align="left" valign="middle">superscript three</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&acute;</cell>
+ <cell align="left" valign="middle">&amp;acute;</cell>
+ <cell align="left" valign="middle">acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&micro;</cell>
+ <cell align="left" valign="middle">&amp;micro;</cell>
+ <cell align="left" valign="middle">micro sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&para;</cell>
+ <cell align="left" valign="middle">&amp;para;</cell>
+ <cell align="left" valign="middle">pilcrow (paragraph sign)</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&middot;</cell>
+ <cell align="left" valign="middle">&amp;middot;</cell>
+ <cell align="left" valign="middle">middle dot</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&cedil;</cell>
+ <cell align="left" valign="middle">&amp;cedil;</cell>
+ <cell align="left" valign="middle">cedilla</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&sup1;</cell>
+ <cell align="left" valign="middle">&amp;sup1;</cell>
+ <cell align="left" valign="middle">superscript one</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ordm;</cell>
+ <cell align="left" valign="middle">&amp;ordm;</cell>
+ <cell align="left" valign="middle">ordinal indicator, masculine</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&raquo;</cell>
+ <cell align="left" valign="middle">&amp;raquo;</cell>
+ <cell align="left" valign="middle">angle quotation mark, right</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&frac14;</cell>
+ <cell align="left" valign="middle">&amp;frac14;</cell>
+ <cell align="left" valign="middle">fraction one-quarter</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&frac12;</cell>
+ <cell align="left" valign="middle">&amp;frac12;</cell>
+ <cell align="left" valign="middle">fraction one-half</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&frac34;</cell>
+ <cell align="left" valign="middle">&amp;frac34;</cell>
+ <cell align="left" valign="middle">fraction three-quarters</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&iquest;</cell>
+ <cell align="left" valign="middle">&amp;iquest;</cell>
+ <cell align="left" valign="middle">inverted question mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Agrave;</cell>
+ <cell align="left" valign="middle">&amp;Agrave;</cell>
+ <cell align="left" valign="middle">capital A, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Aacute;</cell>
+ <cell align="left" valign="middle">&amp;Aacute;</cell>
+ <cell align="left" valign="middle">capital A, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Acirc;</cell>
+ <cell align="left" valign="middle">&amp;Acirc;</cell>
+ <cell align="left" valign="middle">capital A, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Atilde;</cell>
+ <cell align="left" valign="middle">&amp;Atilde;</cell>
+ <cell align="left" valign="middle">capital A, tilde</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Auml;</cell>
+ <cell align="left" valign="middle">&amp;Auml;</cell>
+ <cell align="left" valign="middle">capital A, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Aring;</cell>
+ <cell align="left" valign="middle">&amp;Aring;</cell>
+ <cell align="left" valign="middle">capital A, ring</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&AElig;</cell>
+ <cell align="left" valign="middle">&amp;AElig;</cell>
+ <cell align="left" valign="middle">capital AE diphthong (ligature)</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ccedil;</cell>
+ <cell align="left" valign="middle">&amp;Ccedil;</cell>
+ <cell align="left" valign="middle">capital C, cedilla</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Egrave;</cell>
+ <cell align="left" valign="middle">&amp;Egrave;</cell>
+ <cell align="left" valign="middle">capital E, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Eacute;</cell>
+ <cell align="left" valign="middle">&amp;Eacute;</cell>
+ <cell align="left" valign="middle">capital E, acute accen</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ecirc;</cell>
+ <cell align="left" valign="middle">&amp;Ecirc;</cell>
+ <cell align="left" valign="middle">capital E, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Euml;</cell>
+ <cell align="left" valign="middle">&amp;Euml;</cell>
+ <cell align="left" valign="middle">capital E, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Igrave;</cell>
+ <cell align="left" valign="middle">&amp;Igrave;</cell>
+ <cell align="left" valign="middle">capital I, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Iacute;</cell>
+ <cell align="left" valign="middle">&amp;Iacute;</cell>
+ <cell align="left" valign="middle">capital I, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Icirc;</cell>
+ <cell align="left" valign="middle">&amp;Icirc;</cell>
+ <cell align="left" valign="middle">capital I, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Iuml;</cell>
+ <cell align="left" valign="middle">&amp;Iuml;</cell>
+ <cell align="left" valign="middle">capital I, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ETH;</cell>
+ <cell align="left" valign="middle">&amp;ETH;</cell>
+ <cell align="left" valign="middle">capital Eth, Icelandic</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ntilde;</cell>
+ <cell align="left" valign="middle">&amp;Ntilde;</cell>
+ <cell align="left" valign="middle">capital N, tilde</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ograve;</cell>
+ <cell align="left" valign="middle">&amp;Ograve;</cell>
+ <cell align="left" valign="middle">capital O, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Oacute;</cell>
+ <cell align="left" valign="middle">&amp;Oacute;</cell>
+ <cell align="left" valign="middle">capital O, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ocirc;</cell>
+ <cell align="left" valign="middle">&amp;Ocirc;</cell>
+ <cell align="left" valign="middle">capital O, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Otilde;</cell>
+ <cell align="left" valign="middle">&amp;Otilde;</cell>
+ <cell align="left" valign="middle">capital O, tilde</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ouml;</cell>
+ <cell align="left" valign="middle">&amp;Ouml;</cell>
+ <cell align="left" valign="middle">capital O, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&times;</cell>
+ <cell align="left" valign="middle">&amp;times;</cell>
+ <cell align="left" valign="middle">multiply sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Oslash;</cell>
+ <cell align="left" valign="middle">&amp;Oslash;</cell>
+ <cell align="left" valign="middle">capital O, slash</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ugrave;</cell>
+ <cell align="left" valign="middle">&amp;Ugrave;</cell>
+ <cell align="left" valign="middle">capital U, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Uacute;</cell>
+ <cell align="left" valign="middle">&amp;Uacute;</cell>
+ <cell align="left" valign="middle">capital U, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Ucirc;</cell>
+ <cell align="left" valign="middle">&amp;Ucirc;</cell>
+ <cell align="left" valign="middle">capital U, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Uuml;</cell>
+ <cell align="left" valign="middle">&amp;Uuml;</cell>
+ <cell align="left" valign="middle">capital U, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&Yacute;</cell>
+ <cell align="left" valign="middle">&amp;Yacute;</cell>
+ <cell align="left" valign="middle">capital Y, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&THORN;</cell>
+ <cell align="left" valign="middle">&amp;THORN;</cell>
+ <cell align="left" valign="middle">capital THORN, Icelandic</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&szlig;</cell>
+ <cell align="left" valign="middle">&amp;szlig;</cell>
+ <cell align="left" valign="middle">small sharp s, German (sz ligature)</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&agrave;</cell>
+ <cell align="left" valign="middle">&amp;agrave;</cell>
+ <cell align="left" valign="middle">small a, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&aacute;</cell>
+ <cell align="left" valign="middle">&amp;aacute;</cell>
+ <cell align="left" valign="middle">small a, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&acirc;</cell>
+ <cell align="left" valign="middle">&amp;acirc;</cell>
+ <cell align="left" valign="middle">small a, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&atilde;</cell>
+ <cell align="left" valign="middle">&amp;atilde;</cell>
+ <cell align="left" valign="middle">small a, tilde</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&auml;</cell>
+ <cell align="left" valign="middle">&amp;auml;</cell>
+ <cell align="left" valign="middle">small a, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&aring;</cell>
+ <cell align="left" valign="middle">&amp;aring;</cell>
+ <cell align="left" valign="middle">small a, ring</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&aelig;</cell>
+ <cell align="left" valign="middle">&amp;aelig;</cell>
+ <cell align="left" valign="middle">small ae diphthong (ligature)</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ccedil;</cell>
+ <cell align="left" valign="middle">&amp;ccedil;</cell>
+ <cell align="left" valign="middle">small c, cedilla</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&egrave;</cell>
+ <cell align="left" valign="middle">&amp;egrave;</cell>
+ <cell align="left" valign="middle">small e, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&eacute;</cell>
+ <cell align="left" valign="middle">&amp;eacute;</cell>
+ <cell align="left" valign="middle">small e, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ecirc;</cell>
+ <cell align="left" valign="middle">&amp;ecirc;</cell>
+ <cell align="left" valign="middle">small e, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&euml;</cell>
+ <cell align="left" valign="middle">&amp;euml;</cell>
+ <cell align="left" valign="middle">small e, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&igrave;</cell>
+ <cell align="left" valign="middle">&amp;igrave;</cell>
+ <cell align="left" valign="middle">small i, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&iacute;</cell>
+ <cell align="left" valign="middle">&amp;iacute;</cell>
+ <cell align="left" valign="middle">small i, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&icirc;</cell>
+ <cell align="left" valign="middle">&amp;icirc;</cell>
+ <cell align="left" valign="middle">small i, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&iuml;</cell>
+ <cell align="left" valign="middle">&amp;iuml;</cell>
+ <cell align="left" valign="middle">small i, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&eth;</cell>
+ <cell align="left" valign="middle">&amp;eth;</cell>
+ <cell align="left" valign="middle">small eth, Icelandic</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ntilde;</cell>
+ <cell align="left" valign="middle">&amp;ntilde;</cell>
+ <cell align="left" valign="middle">small n, tilde</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ograve;</cell>
+ <cell align="left" valign="middle">&amp;ograve;</cell>
+ <cell align="left" valign="middle">small o, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&oacute;</cell>
+ <cell align="left" valign="middle">&amp;oacute;</cell>
+ <cell align="left" valign="middle">small o, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ocirc;</cell>
+ <cell align="left" valign="middle">&amp;ocirc;</cell>
+ <cell align="left" valign="middle">small o, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&otilde;</cell>
+ <cell align="left" valign="middle">&amp;otilde;</cell>
+ <cell align="left" valign="middle">small o, tilde</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ouml;</cell>
+ <cell align="left" valign="middle">&amp;ouml;</cell>
+ <cell align="left" valign="middle">small o, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&divide;</cell>
+ <cell align="left" valign="middle">&amp;divide;</cell>
+ <cell align="left" valign="middle">divide sign</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&oslash;</cell>
+ <cell align="left" valign="middle">&amp;oslash;</cell>
+ <cell align="left" valign="middle">small o, slash</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ugrave;</cell>
+ <cell align="left" valign="middle">&amp;ugrave;</cell>
+ <cell align="left" valign="middle">small u, grave accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&uacute;</cell>
+ <cell align="left" valign="middle">&amp;uacute;</cell>
+ <cell align="left" valign="middle">small u, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&ucirc;</cell>
+ <cell align="left" valign="middle">&amp;ucirc;</cell>
+ <cell align="left" valign="middle">small u, circumflex accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&uuml;</cell>
+ <cell align="left" valign="middle">&amp;uuml;</cell>
+ <cell align="left" valign="middle">small u, dieresis or umlaut mark</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&yacute;</cell>
+ <cell align="left" valign="middle">&amp;yacute;</cell>
+ <cell align="left" valign="middle">small y, acute accent</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&thorn;</cell>
+ <cell align="left" valign="middle">&amp;thorn;</cell>
+ <cell align="left" valign="middle">small thorn, Icelandic</cell>
+ </row>
+ <row>
+ <cell align="left" valign="middle">&yuml;</cell>
+ <cell align="left" valign="middle">&amp;yuml;</cell>
+ <cell align="left" valign="middle">small y, dieresis or umlaut mark</cell>
+ </row>
+ <tcaption>Accented Latin-1 alphabetic characters.</tcaption>
+ </table>
+ </section>
+</chapter>
+
diff --git a/lib/erl_docgen/doc/src/convert.howto b/lib/erl_docgen/doc/src/convert.howto
deleted file mode 100644
index 2c72de8c4c..0000000000
--- a/lib/erl_docgen/doc/src/convert.howto
+++ /dev/null
@@ -1,13 +0,0 @@
-
-- add xmlns:xi="http://www.w3.org/2001/XInclude" on top tag
- in files whith include directives
-
-- change <include file="notes"></include> <xi:include href="notes.xml"/>
-
-- change <image file="a"/> to <image file="a.gif"/>
-
-- remove chapers directly in the book and put them in the part instead
-
--change title to just the application name
-
-- fix codeinclude : xml --> xmlsrc \ No newline at end of file
diff --git a/lib/erl_docgen/doc/src/doc-build.xml b/lib/erl_docgen/doc/src/doc-build.xml
new file mode 100644
index 0000000000..08410a1539
--- /dev/null
+++ b/lib/erl_docgen/doc/src/doc-build.xml
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>How to Build OTP like documentation</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>doc-build.xml</file>
+ </header>
+
+ <section>
+ <title>Utilities to prepare XML files</title>
+ <section>
+ <title>Create XML files from code</title>
+ <p>
+ If there are EDoc comments in a module, the escript <c>xml_from_edoc.escript</c>
+ can be used to generate an XML file according to the <c>erlref</c> DTD
+ for this module.
+ </p>
+ <p>
+ Example:
+ </p>
+ <code>
+
+ 1> escript $(ERL_TOP)/lib/erl_docgen/priv/bin/xml_from_edoc.escript ex1.erl
+ </code>
+ </section>
+ <section>
+ <title>Include code in XML</title>
+ <p>If there are OTP DTD <i>codeinclude</i> tags in the source XML file, the escript
+ <c>codeline_preprocessing.escript</c> can be used to include the code and produce
+ an XML file according to the OTP DTDs.
+ </p>
+ <p>
+ Example:
+ </p>
+ <code>
+
+ 1> escript $(ERL_TOP)/lib/erl_docgen/priv/bin/codeline_preprocessing.escript ex1.xmlsrc ex1.xml
+ </code>
+ </section>
+ </section>
+
+ <section>
+ <title>Use xsltproc to generate different output formats</title>
+
+ <section>
+ <title>Parameters used in all the the XSL transformations</title>
+ <p>
+ These parameters to <c>xsltproc</c> are used for all the supported output formats.
+ </p>
+ <taglist>
+ <tag><c>docgen</c></tag>
+ <item>
+ Path to erl_docgen's top directory.
+ </item>
+ <tag><c>gendate</c></tag>
+ <item>
+ The date string that will be used in the documentation.
+ </item>
+ <tag><c>appname</c></tag>
+ <item>
+ The name of the application.>
+ </item>
+ <tag><c>appver</c></tag>
+ <item>
+ The version of the application.
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <title>Generate HTML output</title>
+ <p>
+ When generating HTML one also needs these three pramaters to <c>xsltproc</c>.
+ </p>
+ <taglist>
+ <tag><c>outdir</c></tag>
+ <item>
+ Output directory for the produced html files.
+ </item>
+ <tag><c>topdocdir</c></tag>
+ <item>
+ If one builds a standalone documentation for an application this should be set to ".".
+ </item>
+ <tag><c>pdfdir</c></tag>
+ <item>
+ Relative path from the html directory to where the pdf file are placed.
+ </item>
+ </taglist>
+ <p>
+ Example:
+ </p>
+ <code>
+
+ 1> xsltproc --noout --stringparam outdir /tmp/myhtmldoc \
+ --stringparam docgen $(ERL_TOP)/lib/erl_docgen \
+ --stringparam topdocdir . \
+ --stringparam pdfdir "$(PDFDIR)" \
+ --xinclude \
+ --stringparam gendate "December 5 2011" \
+ --stringparam appname MyApp \
+ --stringparam appver 0.1 \
+ -path $ERL_TOP/lib/erl_docgen/priv/dtd \
+ -path $ERL_TOP/lib/erl_docgen/priv/dtd_html_entities \
+ $ERL_TOP/lib/erl_docgen/priv/xsl/db_html.xsl mybook.xml
+ </code>
+ </section>
+
+ <section>
+ <title>Generate PDF</title>
+ <p>
+ The generation of the PDF file is done in two steps. First is <c>xsltproc</c> used to generate a <c>.fo</c> file
+ which is used as input to the <c>fop</c> command to produce th PDF file.
+ </p>
+ <p>
+ Example:
+ </p>
+ <code>
+
+ 1> xsltproc --output MyApp.fo \
+ --stringparam docgen $ERL_TOP/lib/erl_docgen \
+ --stringparam gendate "December 5 2011" \
+ --stringparam appname MyApp \
+ --stringparam appver 0.1 \
+ --xinclude \
+ -path $ERL_TOP/lib/erl_docgen/priv/dtd \
+ -path $ERL_TOP/lib/erl_docgen/priv/dtd_html_entities \
+ $ERL_TOP/lib/erl_docgen/priv/xsl/db_pdf.xsl mybook.xml
+
+
+ 2> fop -fo MyApp.fo -pdf MyApp.pdf
+ </code>
+ </section>
+
+ <section>
+ <title>Generate man pages</title>
+ <p>
+ Unix man pages can be generated with <c>xsltproc</c> from XML files written according to
+ the different OTP ref type DTDs.
+ </p>
+ <p>
+ Example:
+ </p>
+ <code>
+
+ 1> xsltproc --output my_module.3\
+ --stringparam docgen $ERL_TOP/lib/erl_docgen \
+ --stringparam gendate "December 5 2011" \
+ --stringparam appname MyApp \
+ --stringparam appver 0.1 \
+ --xinclude -path $ERL_TOP/lib/erl_docgen/priv/dtd \
+ -path $ERL_TOP/lib/erl_docgen/priv/dtd_man_entities \
+ $ERL_TOP/lib/erl_docgen/priv/xsl/db_man.xsl my_refpage.xml
+ </code>
+ </section>
+
+ <section>
+ <title>Upcomming changes</title>
+ <p>
+ The output from the <c>erl_docgen</c> documentation build process is now just the OTP style.
+ But in a near future we will for example add the possibility to change logo, color in the PDF and
+ style sheet for the HTML.
+ </p>
+ </section>
+
+ </section>
+</chapter>
diff --git a/lib/erl_docgen/doc/src/docgen_xml_check.xml b/lib/erl_docgen/doc/src/docgen_xml_check.xml
new file mode 100644
index 0000000000..58cf069d81
--- /dev/null
+++ b/lib/erl_docgen/doc/src/docgen_xml_check.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2007</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.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>docgen_xml_check</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>docgen_xml_check</module>
+ <modulesummary>Validate XML documentation source code</modulesummary>
+ <description>
+ <p><c>docgen_xml_check</c> contains functions for validating XML
+ documentation source code.</p>
+ </description>
+
+ <funcs>
+ <func>
+ <name>validate(File) -> ok | error | {error, badfile}</name>
+ <fsummary>Validate XML source code.</fsummary>
+ <type>
+ <v>File = string()</v>
+ </type>
+ <desc>
+ <p>Validates the XML documentation source code in <c>File</c>.
+ The <c>.xml</c> extension can be omitted.</p>
+
+ <p>Returns <c>ok</c> if successful, otherwise error information
+ is printed and the function returns <c>error</c>.
+ If <c>File</c> does not exist, <c>{error, badfile}</c> is
+ returned.</p>
+ </desc>
+ </func>
+ </funcs>
+
+</erlref>
+
diff --git a/lib/erl_docgen/doc/src/erl_docgen.txt b/lib/erl_docgen/doc/src/erl_docgen.txt
deleted file mode 100644
index 14a4dc8e10..0000000000
--- a/lib/erl_docgen/doc/src/erl_docgen.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-/home/otptest/bin/otp_wrap_ssh boddington /home/otptest/bin/otp_build_doc -rel r13b02 -view otptest_r13_daily_doc2 -csfile /usr/local/otp/config-specs/r13_dev.cs -insdir /ldisk/daily_build
-_
- \ No newline at end of file
diff --git a/lib/erl_docgen/doc/src/erl_docgen_app.xml b/lib/erl_docgen/doc/src/erl_docgen_app.xml
new file mode 100644
index 0000000000..25c473bb7e
--- /dev/null
+++ b/lib/erl_docgen/doc/src/erl_docgen_app.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE appref SYSTEM "appref.dtd">
+
+<appref>
+ <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>erl_docgen</title>
+ <file>erl_docgen_app.xml</file>
+ </header>
+ <app>erl_docgen</app>
+ <appsummary>
+ The erl_docgen application is used to produce the OTP documentation.
+ </appsummary>
+
+ <description>
+ <p>
+ The application consists of the following parts
+ <taglist>
+ <tag>XSL</tag>
+ <item>
+ <p>
+ A number of XSL files that is used to transform the xml files to html, pdf or man pages.
+ </p>
+ </item>
+ <tag>DTDs</tag>
+ <item>
+ <p>
+ The DTDs used for the OTP documentation.
+ </p>
+ </item>
+ <tag>escripts</tag>
+ <item>
+ <p>
+ Some scripts that is used to produce xml files according to OTP DTDs from some different input.
+ </p>
+ </item>
+ <tag>misc</tag>
+ <item>
+ <p>
+ Erlang logo, javascripts and css stylesheets used in the documentation.
+ </p>
+ </item>
+ </taglist>
+ </p>
+ </description>
+
+</appref>
diff --git a/lib/erl_docgen/doc/src/example.txt b/lib/erl_docgen/doc/src/example.txt
new file mode 100644
index 0000000000..ad86165391
--- /dev/null
+++ b/lib/erl_docgen/doc/src/example.txt
@@ -0,0 +1,17 @@
+This example code is used in block_tags.xml.
+
+%% Erlang example
+-module(example).
+
+start() ->
+ {error,"Pid required!"}.
+
+start(Pid) ->
+ spawn(smalltalk,main,[]).
+%% Erlang example
+
+// A little C example
+int main() {
+ for(;;);
+}
+// A little C example
diff --git a/lib/erl_docgen/doc/src/fasc_dtds.xml b/lib/erl_docgen/doc/src/fasc_dtds.xml
new file mode 100644
index 0000000000..86eeb958f6
--- /dev/null
+++ b/lib/erl_docgen/doc/src/fasc_dtds.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2007</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>Fascicules DTDs</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>fasc_dtds.xml</file>
+ </header>
+
+ <section>
+ <title>The fascicules DTD</title>
+
+ <p>The <c>fascicules</c> DTD is a special kind of DTD which can be
+ used to specify the different parts of the documentation, and
+ which one of those should be shown as default.</p>
+
+ <p>Example:</p>
+
+ <pre><![CDATA[
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
+<fascicules>
+ <fascicule file="part" href="part_frame.html" entry="no">
+ User's Guide
+ </fascicule>
+ <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
+ Reference Manual
+ </fascicule>
+ <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
+ Release Notes
+ </fascicule>
+</fascicules>
+ ]]></pre>
+
+ <p>In the example, it is specified that the documentation for this
+ application consists of three parts: User's Guide, where
+ the "cover page" (with the two frames) is located in
+ <c>part_frame.html</c>, Reference Manual with the cover page
+ <c>ref_man_frame.html</c> and Release Notes with the cover page
+ <c>part_notes_frame.html</c>.</p>
+
+ <p>As a result, at the top of the left frame in the generated HTML
+ documentation, there will be corresponding links to User's Guide,
+ Reference Manual and Release Notes.</p>
+
+ <p>The attribute <c>entry="yes"</c> specifies that it is
+ the Reference Manual which should be shown as default. This means
+ that when generating the HTML files, <c>application_frame.html</c>
+ will be copied to <c>index.html</c>.</p>
+
+ <note>
+ <p>DocBuilder assumes that the XML file written according to
+ the <c>fascicules</c> DTD is called <c>fascicules.xml</c>.</p>
+ </note>
+
+ <p>This file is optional. If it does not exist, there are no links
+ to other parts of the documentation (as they are not known) in
+ the left frame, and no <c>index.html</c> is created.</p>
+ </section>
+
+ <section>
+ <marker id="fasciculesTAG"></marker>
+ <title>&lt;fascicules&gt;</title>
+
+ <p>Top level tag for the <c>fascicules</c> DTD.</p>
+
+ <p>Contains one or more
+ <seealso marker="#fasciculeTAG">&lt;fascicule&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="fasciculeTAG"></marker>
+ <title>&lt;fascicule&gt;</title>
+
+ <p>Specifies properties for one "part" of the documentation for an
+ application.</p>
+
+ <p>Contains plain text, the name of this part.</p>
+
+ <p>The <c>file</c> attribute should specify the file name for
+ the corresponding <c>part</c> or <c>application</c>, without
+ the <c>.xml</c> extension.</p>
+
+ <p>The <c>href</c> attribute should specify the file name for
+ the corresponding HTML cover page file, without the <c>.html</c>
+ extension.</p>
+
+ <p>The optional <c>entry="yes"|"no"</c> attribute specifies if
+ the HTML cover page should be copied to <c>index.html</c> or
+ not. Default is <c>"no"</c>.</p>
+ </section>
+</chapter>
+
diff --git a/lib/docbuilder/doc/src/fascicules.xml b/lib/erl_docgen/doc/src/fascicules.xml
index 1b9d6bc94d..1b9d6bc94d 100644
--- a/lib/docbuilder/doc/src/fascicules.xml
+++ b/lib/erl_docgen/doc/src/fascicules.xml
diff --git a/lib/erl_docgen/doc/src/header_tags.xml b/lib/erl_docgen/doc/src/header_tags.xml
new file mode 100644
index 0000000000..dfae15107f
--- /dev/null
+++ b/lib/erl_docgen/doc/src/header_tags.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>Header Tags</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>header_tags.xml</file>
+ </header>
+
+ <p>Each document begins with a header part, which looks the same for
+ all DTDs. Here the title of the document is specified, as well as
+ administrative data like who is responsible for the document, which
+ version is it, when was it last changed and such.</p>
+
+ <p>An full header looks like:</p>
+ <pre>
+&lt;header>
+ &lt;copyright>...&lt;/copyright>
+ &lt;legalnotice>...&lt;/legalnotice>
+ &lt;title>...&lt;/title>
+ &lt;prepared>...&lt;/prepared>
+ &lt;responsible>...&lt;/responsible>
+ &lt;docno>...&lt;/docno>
+ &lt;approved>...&lt;/approved>
+ &lt;checked>...&lt;/checked>
+ &lt;date>...&lt;/date>
+ &lt;rev>...&lt;/rev>
+ &lt;file>...&lt;/file>
+&lt;/header>
+ </pre>
+
+ <section>
+ <marker id="headerTAG"></marker>
+ <title>&lt;header&gt;</title>
+
+ <p>Top level tag for the header part.</p>
+ </section>
+
+ <section>
+ <marker id="copyrightTAG"></marker>
+ <title>&lt;copyright&gt;</title>
+
+ <p>The <c>copyright</c> element holds information about date(s) and holder(s) of
+ a document copyright. The <c>copyright</c> element is optional.
+ The <c>copyright</c> element has an inner structure containing one or
+ more
+ <c>year</c> elements followed by zero of more <c>holder</c> elements.<br/>
+ See example below:
+ </p>
+ <code><![CDATA[
+ <copyright>
+ <year>1997</year>
+ <year>2007</year>
+ <holder>Ericsson AB</holder>
+ </copyright>
+ ]]></code>
+ </section>
+
+ <section>
+ <marker id="legalnoticeTAG"></marker>
+ <title>&lt;legalnotice&gt;</title>
+
+ <p>The <c>legalnotice</c> element is used to express copyright, trademark,
+ license, and other legal formalities of a document. The element contains
+ only PCDATA in the same manner as <c>code</c> and <c>pre</c>.
+ </p>
+ </section>
+
+ <section>
+ <marker id="titleTAG"></marker>
+ <title>&lt;title&gt;</title>
+
+ <p>For <c>part</c> and <c>application</c> documents, this will be
+ the title of the document, visible in the left frame and on
+ the front page.</p>
+
+ <p>For <c>chapter</c> documents, this will be the chapter name.</p>
+
+ <p>For reference manual documents, this tag is ignored.</p>
+ </section>
+
+ <section>
+ <title>&lt;shorttitle&gt;</title>
+
+ <p>This optional tag is ignored. It will likely be
+ removed in the future.</p>
+ </section>
+
+ <section>
+ <marker id="preparedTAG"></marker>
+ <title>&lt;prepared&gt;</title>
+
+ <p>This tag is intended for administrative use and is ignored.</p>
+ </section>
+
+ <section>
+ <marker id="responsibleTAG"></marker>
+ <title>&lt;responsible&gt;</title>
+
+ <p>This optional tag is intended for administrative use and is
+ ignored.</p>
+ </section>
+
+ <section>
+ <marker id="docnoTAG"></marker>
+ <title>&lt;docno&gt;</title>
+
+ <p>Document number.</p>
+
+ <p>For <c>part</c> and <c>application</c> documents, the document
+ number is visible in the left frame and on the front page.</p>
+
+ <p>For other types of documents, this tag is ignored.</p>
+ </section>
+
+ <section>
+ <marker id="approvedTAG"></marker>
+ <title>&lt;approved&gt;</title>
+
+ <p>This optional tag is intended for administrative use and is
+ ignored.</p>
+ </section>
+
+ <section>
+ <marker id="checkedTAG"></marker>
+ <title>&lt;checked&gt;</title>
+
+ <p>This optional tag is intended for administrative use and is
+ ignored.</p>
+ </section>
+
+ <section>
+ <marker id="dateTAG"></marker>
+ <title>&lt;date&gt;</title>
+
+ <p>This tag is intended for administrative use and is ignored.</p>
+ </section>
+
+ <section>
+ <marker id="revTAG"></marker>
+ <title>&lt;rev&gt;</title>
+
+ <p>Document version.</p>
+
+ <p>For <c>part</c> and <c>application</c> documents, the document
+ version is visible in the left frame and on the front page.</p>
+
+ <p>For other types of documents, this tag is ignored.</p>
+ </section>
+
+ <section>
+ <marker id="fileTAG"></marker>
+ <title>&lt;file&gt;</title>
+
+ <p>This optional tag is intended for administrative use and is
+ ignored.</p>
+ </section>
+</chapter>
+
diff --git a/lib/erl_docgen/doc/src/inline_tags.xml b/lib/erl_docgen/doc/src/inline_tags.xml
new file mode 100644
index 0000000000..9b27da659b
--- /dev/null
+++ b/lib/erl_docgen/doc/src/inline_tags.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>Inline Tags</title>
+ <prepared/>
+ <docno/>
+ <date/>
+ <rev/>
+ <file>inline_tags.xml</file>
+ </header>
+
+ <p>Inline tags are typically used within block tags, for example to
+ highlight a word within a paragraph.</p>
+
+ <section>
+ <marker id="brTAG"></marker>
+ <title>&lt;br&gt; - Line Break</title>
+
+ <p>Forces a newline. The <c><![CDATA[<br>]]></c> tag is both a
+ block- and an inline tag and is described in
+ the <seealso marker="block_tags#brTAG">Block Tags</seealso>
+ section.</p>
+ </section>
+
+ <section>
+ <marker id="cTAG"></marker>
+ <title>&lt;c&gt; - Code</title>
+
+ <p>Highlights things like variables and file names in a text flow.
+ Can contain plain text only. Newlines and tabs are ignored as
+ opposed to the <seealso marker="block_tags#codeTAG">code</seealso>
+ tag. All <seealso marker="character_entities">character
+ entities</seealso> are expanded. Example:</p>
+ <pre>
+&lt;p>Returns &lt;c>true&lt;/c> if &lt;c>Term&lt;/c> is an integer.&lt;/p>
+ </pre>
+ <p>results in:</p>
+ <p>Returns <c>true</c> if <c>Term</c> is an integer.</p>
+ </section>
+
+ <section>
+ <marker id="emTAG"></marker>
+ <title>&lt;em&gt; - Emphasis</title>
+
+ <p>Highlights words which are important within a text flow. Example:
+ </p>
+ <pre>
+&lt;p>The application &lt;em>must&lt;/em> be up and running.&lt;/p>
+ </pre>
+ <p>results in:</p>
+ <p>The application <em>must</em> be up and running.</p>
+
+ <p>Contains plain text or a
+ <seealso marker="#cTAG">&lt;c&gt;</seealso> tag.</p>
+ </section>
+
+ <section>
+ <marker id="markerTAG"/>
+ <title>&lt;marker&gt; - Marker</title>
+
+ <p>Used as an anchor for hypertext references. The <c>id</c>
+ attribute defines the name of the marker. Example:</p>
+ <marker id="marker_example"/>
+ <pre>
+&lt;marker id="marker_example"/&gt;
+ </pre>
+
+ <p>The <seealso marker="#seealsoTAG">&lt;seealso&gt;</seealso> tag
+ is used to refer to the marker.</p>
+
+ <p>The <c><![CDATA[<marker>]]></c> tag is both a block- and an
+ inline tag.</p>
+ </section>
+
+ <!-- section>
+ <marker id="pathTAG"></marker>
+ <title>&lt;path&gt; - Path</title>
+
+ <p>Highlights file paths. The attributes <c>unix</c> and
+ <c>windows</c> makes it possible to specify different paths for
+ different file path notations. Default for both are "".
+ Example:</p>
+ <pre>
+&lt;p>Look at the &lt;path unix=".profile" windows="win.ini"&gt;start-up file&lt;/path&gt;
+ if you intend to alter the initial behavior.&lt;/p>
+ </pre>
+ <p>If no <c>ptype</c> option is specified when calling
+ <seealso marker="docb_transform#file/1">docb_transform:file/1,2</seealso>,
+ this simply results in:</p>
+ <p>"Look at the <path>start-up file</path>
+ if you intend to alter the initial behavior."</p>
+
+ <p>If both the options <c>{ptype,unix}</c> and
+ <c>{ptype,windows}</c> are specified, the example instead results
+ in:</p>
+ <p>"Look at the <path unix=".profile" windows="win.ini">start-up file</path>
+ if you intend to alter the initial behavior."</p>
+ </section -->
+
+ <section>
+ <marker id="seealsoTAG"></marker>
+ <title>&lt;seealso&gt; - Local Cross Reference</title>
+
+ <p>A cross reference (hypertext link) to a marker in the same file,
+ a marker in another file, or (the top of) another file, given by
+ the <c>marker</c> attribute. Must contain plain text. Examples:
+ </p>
+
+ <pre><![CDATA[
+ <seealso marker="#marker_example">marker example</seealso>
+ ]]></pre>
+ <p>results in:
+ <seealso marker="#marker_example">marker example</seealso>
+ (a hypertext link to the marker example above).</p>
+
+ <pre><![CDATA[
+ <seealso marker="block_tags#markerTAG">marker tag</seealso>
+ ]]></pre>
+ <p>results in:
+ <seealso marker="block_tags#markerTAG">marker tag</seealso>
+ (a hypertext link to the marker section in the Block Tags
+ chapter).</p>
+
+ <pre><![CDATA[
+ <seealso marker="overview">Overview</seealso>
+ ]]></pre>
+ <p>results in:
+ <seealso marker="overview">Overview</seealso>
+ (a hypertext link to the Overview chapter).</p>
+
+ <p>Note the use of "#" before the name of the marker. Note also
+ that the filename extension <c>.html</c> is omitted. This is
+ because the default behavior is to translate
+ <c><![CDATA[<seealso marker="File#Marker">text</seealso>]]></c>
+ to <c><![CDATA[<A HREF="File.html#Marker">text</A>]]></c>.</p>
+
+ </section>
+
+ <section>
+ <marker id="urlTAG"></marker>
+ <title>&lt;url&gt; - Non-Local Cross Reference</title>
+
+ <p>A reference to a file outside the documentation, a web address or
+ similar, given by the <c>href</c> attribute. Must contain plain
+ text. Example:</p>
+ <pre><![CDATA[
+<url href="http://www.erlang.org">erlang.org</url>
+ ]]></pre>
+ <p>results in: <url href="http://www.erlang.org">erlang.org</url>
+ </p>
+ </section>
+
+ <section>
+ <marker id="termTAG"></marker>
+ <marker id="termdefTAG"></marker>
+ <title>&lt;term&gt;, &lt;termdef&gt; - Glossary</title>
+
+ <p>Used to highlight a term with a local (for this document only) or
+ global definition. The identity of the term is given by
+ the <c>id</c> attribute.</p>
+
+ <p>For a locally defined term, the tag contains a
+ <c>&lt;termdef&gt;</c>, which in turn contains an explanation of
+ the term as plain text. Example:</p>
+ <pre><![CDATA[
+<term id="HTML"><termdef>Hyper-Text Markup Language</termdef></term>
+ ]]></pre>
+
+ <p>In the generated HTML, it is the term name which will be visible.
+ For locally defined terms, the id and the name are the same.
+ The name has a hypertext link to the definition in the glossary.
+ Example:</p>
+ <pre><![CDATA[
+<term id="HTML"><termdef>Hyper-Text Markup Language</termdef></term>
+ ]]></pre>
+ <p>results in: <term id="HTML"><termdef>Hyper-Text Markup Language</termdef></term>
+ </p>
+
+ <p>If a term is defined both locally and globally, the global
+ definition takes precedence.</p>
+ </section>
+
+ <section>
+ <marker id="citeTAG"></marker>
+ <marker id="citedefTAG"></marker>
+ <title>&lt;cite&gt;, &lt;citedef&gt; - Bibliography</title>
+
+ <p>Works the same way as <c>&lt;term&gt;</c> and
+ <c>&lt;termdef&gt;</c>, but for a bibliography list rather than
+ a glossary.</p>
+
+ </section>
+</chapter>
+
diff --git a/lib/docbuilder/doc/src/man.gif b/lib/erl_docgen/doc/src/man.gif
index 8656c7443d..8656c7443d 100644
--- a/lib/docbuilder/doc/src/man.gif
+++ b/lib/erl_docgen/doc/src/man.gif
Binary files differ
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 6a0eece56d..8ca11b1cf5 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/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>
@@ -21,16 +21,112 @@
</legalnotice>
- <title>erl_docgen Release Notes</title>
+ <title>Erl_Docgen Release Notes</title>
<prepared>otp_appnotes</prepared>
<docno>nil</docno>
<date>nil</date>
<rev>nil</rev>
<file>notes.xml</file>
</header>
- <p>This document describes the changes made to the erl_docgen application.</p>
+ <p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 0.2.6</title>
+ <section><title>Erl_Docgen 0.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Some links in C libraries were not generated
+ correctly. This bug has been fixed. </p>
+ <p>
+ Own Id: OTP-9832</p>
+ </item>
+ <item>
+ <p>
+ Set `font-family: Courier, monospace' in OTP doc CSS</p>
+ <p>
+ left Courier as the primary original font and also added
+ monospace as secondary for people which in Linux does not
+ have it installed.</p>
+ <p>
+ Also adds minor cosmetic changes to the CSS. (Thanks to
+ Ricardo Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9918</p>
+ </item>
+ <item>
+ <p>
+ When generating from edoc it is now possible to use
+ ranges in specs and &lt;img&gt; tags in the description.</p>
+ <p>
+ Own Id: OTP-9970</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Optimize and improve handling of multiple func:s.
+ </p>
+ <p>
+ Own Id: OTP-9877</p>
+ </item>
+ <item>
+ <p> The generation of the libraries' HTML documentation
+ has been optimized. </p>
+ <p>
+ Own Id: OTP-9893</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Bug fixes concerning the generation of manpages. </p>
+ <p>
+ Own Id: OTP-9614</p>
+ </item>
+ <item>
+ <p> Fix syntax bug in eix files. </p>
+ <p>
+ Own Id: OTP-9617</p>
+ </item>
+ <item>
+ <p> Bug fix concerning the generation of manpages. </p>
+ <p>
+ Own Id: OTP-9759</p>
+ </item>
+ <item>
+ <p> Fixed an arity calculation bug for erlang functions
+ in the documentation index for html and pdf. </p>
+ <p>
+ Own Id: OTP-9772</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The docbuilder application is removed in R15 and
+ parts still used in the OTP documentation build process
+ and the DTD documentation is moved to erl_docgen. </p>
+ <p>
+ Own Id: OTP-9721</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.2.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/erl_docgen/doc/src/overview.xml b/lib/erl_docgen/doc/src/overview.xml
new file mode 100644
index 0000000000..2a420c53d9
--- /dev/null
+++ b/lib/erl_docgen/doc/src/overview.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>Overview OTP DTDs</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>overview.xml</file>
+ </header>
+
+ <section>
+ <title>DTD Suite</title>
+
+ <p>Input is written as XML according to one of the DTDs and output
+ is corresponding HTML. Documentation for an Erlang/OTP application
+ is usually organized as follows:</p>
+ <taglist>
+ <tag><em>User's Guide</em></tag>
+ <item>
+ <p>(DTD:
+ <seealso marker="user_guide_dtds#partDTD">part</seealso>)
+ A collection of chapters
+ (<seealso marker="user_guide_dtds#chapterDTD">chapter</seealso>).
+ </p>
+ </item>
+
+ <tag><em>Reference Manual</em></tag>
+ <item>
+ <p>(DTD:
+ <seealso marker="refman_dtds#applicationDTD">application</seealso>
+ A collection of manual pages for modules
+ (<seealso marker="refman_dtds#erlrefDTD">erlref</seealso>),
+ applications
+ (<seealso marker="refman_dtds#apprefDTD">appref</seealso>),
+ commands
+ (<seealso marker="refman_dtds#comrefDTD">comref</seealso>),
+ C libraries
+ (<seealso marker="refman_dtds#crefDTD">cref</seealso>) and
+ files
+ (<seealso marker="refman_dtds#filerefDTD">fileref</seealso>).
+ </p>
+ </item>
+
+ <tag><em>Release Notes</em></tag>
+ <item>
+ <p>Same structure as the User's Guide.</p>
+ </item>
+ </taglist>
+
+ <p>In some cases, one or more of the User's Guide, Reference Manual
+ and Release Notes are omitted. Also, it is possible to use either
+ the <c>application</c> or <c>part</c> DTD to write other types
+ of documentation for the application.</p>
+
+
+ <p>The structure of the different documents and the meaning of the
+ tags are explained. There are numerous examples of documentation
+ source code.</p>
+
+ <p>For readability and simplicity, the examples have been kept as
+ short as possible. For an example of what the generated HTML
+ will look like, it is recommended to look at the documentation of
+ an OTP application.</p>
+
+ </section>
+
+ <section>
+ <title>Basic Tags</title>
+
+ <p>All DTDs in the OTP DTD suite share a basic set of tags.
+ An author can easily switch from one DTD to another and still use
+ the same basic tags. It is furthermore easy to copy pieces of
+ information from one document to another, even though they do not
+ use the same DTD.</p>
+
+ <p>The basic set of tags are divided into two categories:
+ <seealso marker="block_tags">block tags</seealso> and
+ <seealso marker="inline_tags">inline tags</seealso>. Block tags
+ typically define a separate block of information, like a
+ paragraph or a list. Inline tags are typically used within block
+ tags, for example a highlighted word within a paragraph.</p>
+ </section>
+
+</chapter>
+
diff --git a/lib/erl_docgen/doc/src/part.xml b/lib/erl_docgen/doc/src/part.xml
new file mode 100644
index 0000000000..26d660df08
--- /dev/null
+++ b/lib/erl_docgen/doc/src/part.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <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>Erl_Docgen User's Guide</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <description>
+ <p><em>Erl_Docgen</em> provides functionality for generating HTML/PDF/man
+ documentation for Erlang modules and Erlang/OTP applications
+ from XML source code and/or EDoc comments in Erlang source code.</p>
+ </description>
+ <xi:include href="doc-build.xml"/>
+ <xi:include href="overview.xml"/>
+ <xi:include href="user_guide_dtds.xml"/>
+ <xi:include href="refman_dtds.xml"/>
+ <xi:include href="header_tags.xml"/>
+ <xi:include href="block_tags.xml"/>
+ <xi:include href="inline_tags.xml"/>
+ <xi:include href="character_entities.xml"/>
+</part>
+
diff --git a/lib/erl_docgen/doc/src/ref_man.xml b/lib/erl_docgen/doc/src/ref_man.xml
new file mode 100644
index 0000000000..a2bc1a10a0
--- /dev/null
+++ b/lib/erl_docgen/doc/src/ref_man.xml
@@ -0,0 +1,36 @@
+<?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><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>Erl_Docgen Reference Manual</title>
+ <prepared>OTP Team</prepared>
+ <docno></docno>
+ <date>2011-11-10</date>
+ <rev>0.3</rev>
+ <file>ref_man.xml</file>
+ </header>
+ <description>
+ <p>The <em>erl_docgen</em> supports the OTP documentation build.</p>
+ </description>
+ <xi:include href="erl_docgen_app.xml"/>
+</application>
+
diff --git a/lib/erl_docgen/doc/src/refman_dtds.xml b/lib/erl_docgen/doc/src/refman_dtds.xml
new file mode 100644
index 0000000000..4f0e388a8a
--- /dev/null
+++ b/lib/erl_docgen/doc/src/refman_dtds.xml
@@ -0,0 +1,667 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>Reference Manual DTDs</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>refman_dtds.xml</file>
+ </header>
+
+ <p>There are five DTDs for writing manual pages about applications,
+ shell commands, C libraries, Erlang modules and files, all with a
+ similar structure:</p>
+
+ <list type="bulleted">
+ <item>A header.</item>
+ <item>Name of the application/command/library/module/file.</item>
+ <item>Short summary (one line).</item>
+ <item>A longer description.</item>
+ <item>"Formal" definitions of functions or commands.</item>
+ <item>Optional sections of free text.</item>
+ <item>Optional section with the name(s) and email(s) of the author(s).</item>
+ </list>
+
+ <p>The differences between the DTDs are the tags for the name,
+ the short summary and some tags inside the "formal" definitions.</p>
+
+ <section>
+ <marker id="applicationDTD"></marker>
+ <title>The application DTD</title>
+
+ <p>The <c>application</c> DTD is intended for a Reference Manual and
+ groups a set of manual pages into one unit. The structure is
+ similar to the part DTD: first an introduction and then the manual
+ pages, written in separate files with the
+ <seealso marker="#apprefDTD">appref</seealso>,
+ <seealso marker="#comrefDTD">comref</seealso>,
+ <seealso marker="#crefDTD">cref</seealso>,
+ <seealso marker="#erlrefDTD">erlref</seealso>, or
+ <seealso marker="#filerefDTD">fileref</seealso> DTD.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE application SYSTEM "application.dtd">
+&lt;application>
+ &lt;header>
+ &lt;title>Application name&lt;/title>
+ &lt;prepared/>
+ &lt;docno/>
+ &lt;date/>
+ &lt;rev/>
+ &lt;/header>
+
+ &lt;description>
+ &lt;p>Application description...&lt;/p>
+ &lt;/description>
+
+ &lt;include file="module1">
+ &lt;include file="module2">
+&lt;/application>
+ </pre>
+ </section>
+
+ <section>
+ <marker id="applicationTAG"></marker>
+ <title>&lt;application&gt;</title>
+
+ <p>The top level tag of an <c>application</c> DTD.</p>
+
+ <p>Contains a
+ <seealso marker="header_tags">&lt;header&gt;</seealso>,
+ an optional
+ <seealso marker="user_guide_dtds#descriptionTAG">&lt;description&gt;</seealso>,
+ followed by one or more
+ <seealso marker="user_guide_dtds#includeTAG">&lt;include&gt;</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <marker id="apprefDTD"></marker>
+ <title>The appref DTD</title>
+
+ <p>This is the DTD for writing an application manual page.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE appref SYSTEM "appref.dtd">
+&lt;appref>
+ &lt;header>
+ &lt;title>Application name&lt;/title>
+ &lt;prepared/>
+ &lt;docno/>
+ &lt;date/>
+ &lt;rev/>
+ &lt;/header>
+
+ &lt;app>Application name&lt;/app>
+
+ &lt;appsummary>A short application summary.&lt;/appsummary>
+
+ &lt;description>
+ &lt;p>A longer description of the application.&lt;/p>
+ &lt;/description>
+
+ &lt;section>
+ &lt;title>Configuration&lt;/title>
+
+ &lt;p>...&lt;/p>
+ &lt;/section>
+
+ ...
+
+ &lt;authors>
+ &lt;aname>Name of author&lt;/aname>
+ &lt;email>Email of author&lt;/email>
+ &lt;/authors>
+&lt;/appref>
+ </pre>
+
+ <section>
+ <marker id="apprefTAG"></marker>
+ <title>&lt;appref&gt;</title>
+
+ <p>The top level tag of an <c>appref</c> DTD.</p>
+
+ <p>Contains
+ <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
+ <seealso marker="#appTAG">&lt;app&gt;</seealso>,
+ <seealso marker="#appsummaryTAG">&lt;appsummary&gt;</seealso>,
+ <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
+ zero or more
+ <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
+ <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
+ followed by zero or more
+ <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="appTAG"></marker>
+ <title>&lt;app&gt;</title>
+
+ <p>The application name. Contains plain text.</p>
+ </section>
+
+ <section>
+ <marker id="appsummaryTAG"></marker>
+ <title>&lt;appsummary&gt;</title>
+
+ <p>Short summary. Contains plain text.</p>
+ </section>
+ </section>
+
+ <section>
+ <marker id="comrefDTD"></marker>
+ <title>The comref DTD</title>
+
+ <p>This is the DTD for writing a command manual page.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE comref SYSTEM "comref.dtd">
+&lt;comref>
+ &lt;header>
+ &lt;title>Command name&lt;/title>
+ &lt;prepared/>
+ &lt;docno/>
+ &lt;date/>
+ &lt;rev/>
+ &lt;/header>
+
+ &lt;com>Command name&lt;/com>
+
+ &lt;comsummary>A short command summary.&lt;/comsummary>
+
+ &lt;description>
+ &lt;p>A long description of the command.&lt;/p>
+ &lt;/description>
+
+ &lt;funcs>
+ &lt;func>
+ &lt;name>command&lt;/name>
+ &lt;name>command -flag &lt;arg>&lt;/name>
+ &lt;fsummary>A short command summary (max 40 characters).&lt;/fsummary>
+ &lt;desc>
+ &lt;p>An extended command description.
+ &lt;/desc>
+ &lt;/func>
+ &lt;/funcs>
+
+ &lt;section>
+ &lt;title>Options&lt;/title>
+
+ &lt;p>...&lt;/p>
+ &lt;/section>
+
+ &lt;authors>
+ &lt;aname>Name of author&lt;/aname>
+ &lt;email>Email of author&lt;/email>
+ &lt;/authors>
+&lt;/comref>
+ </pre>
+
+ <section>
+ <marker id="comrefTAG"></marker>
+ <title>&lt;comref&gt;</title>
+
+ <p>The top level tag for a <c>comref</c> DTD.</p>
+
+ <p>Contains
+ <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
+ <seealso marker="#comTAG">&lt;com&gt;</seealso>,
+ <seealso marker="#comsummaryTAG">&lt;comsummary&gt;</seealso>,
+ <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
+ zero or more
+ <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
+ <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
+ followed by zero or more
+ <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="comTAG"></marker>
+ <title>&lt;com&gt;</title>
+
+ <p>The command name. Contains plain text.</p>
+ </section>
+
+ <section>
+ <marker id="comsummaryTAG"></marker>
+
+ <title>&lt;comsummary&gt;</title>
+
+ <p>Short summary. Contains plain text.</p>
+ </section>
+ </section>
+
+ <section>
+ <marker id="crefDTD"></marker>
+ <title>The cref DTD</title>
+
+ <p>This is the DTD for writing a C library manual page.</p>
+
+ <p>Example:</p>
+ <pre><![CDATA[
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE cref SYSTEM "cref.dtd">
+<cref>
+ <header>
+ <title>C library name</title>
+ <prepared/>
+ <docno/>
+ <date/>
+ <rev/>
+ </header>
+
+ <lib>C library name</lib>
+
+ <libsummary>A short C library summary.</libsummary>
+
+ <description>
+ <p>A longer description of the C library.</p>
+ </description>
+
+ <funcs>
+ <func>
+ <name><ret>void</ret><nametext>start(bar)</nametext></name>
+ <name><ret>void</ret><nametext>start(foo)</nametext></name>
+ <fsummary>A short function summary (max 40 characters).</fsummary>
+ <type>
+ <v>char bar</v>
+ <v>int foo</v>
+ </type>
+ <desc>
+ <p>An extended function description.</p>
+ </desc>
+ </func>
+
+ ...
+ </funcs>
+
+ <section>
+ <title>A title</title>
+
+ <p>Some text...</p>
+ </section>
+
+
+</cref>
+ ]]></pre>
+
+ <section>
+ <marker id="crefTAG"></marker>
+ <title>&lt;cref&gt;</title>
+
+ <p>The top level tag for a <c>cref</c> DTD.</p>
+
+ <p>Contains
+ <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
+ <seealso marker="#libTAG">&lt;lib&gt;</seealso>,
+ <seealso marker="#libsummaryTAG">&lt;libsummary&gt;</seealso>,
+ <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
+ zero or more
+ <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
+ <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>, followed by
+ zero or more
+ <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="libTAG"></marker>
+ <title>&lt;lib&gt;</title>
+
+ <p>The C library name or acronym. Contains plain text.</p>
+ </section>
+
+ <section>
+ <marker id="libsummaryTAG"></marker>
+ <title>&lt;libsummary&gt;</title>
+
+ <p>Short summary. Contains plain text.</p>
+ </section>
+ </section>
+
+ <section>
+ <marker id="erlrefDTD"></marker>
+ <title>The erlref DTD</title>
+
+ <p>This is the DTD for writing Erlang module manual pages.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE erlref SYSTEM "erlref.dtd">
+&lt;erlref>
+ &lt;header>
+ &lt;title>Module name&lt;/title>
+ &lt;prepared/>
+ &lt;docno/>
+ &lt;date/>
+ &lt;rev/>
+ &lt;/header>
+
+ &lt;module>Module name&lt;/module>
+
+ &lt;modulesummary>A short module summary.&lt;/modulesummary>
+
+ &lt;description>
+ &lt;p>A longer description of the module.&lt;/p>
+ &lt;/description>
+
+ &lt;funcs>
+ &lt;func>
+ &lt;name>start() -> Result&lt;/name>
+ &lt;name>start(N) -> Result&lt;/name>
+ &lt;fsummary>A short function summary (max 40 characters).&lt;/fsummary>
+ &lt;type>
+ &lt;v>Pid = pid()&lt;/v>
+ &lt;v>N = int()&lt;/v>
+ &lt;v>Result = {ok, Pid} | {error, Reason}&lt;/v>
+ &lt;v>Reason = term()&lt;/v>
+ &lt;d>A parameter description.&lt;/d>
+ &lt;/type>
+ &lt;desc>
+ &lt;p>An extended function description.&lt;/p>
+ &lt;/desc>
+ &lt;/func>
+
+ ...
+ &lt;/funcs>
+
+ &lt;section>
+ &lt;title>Some Title&lt;/title>
+ &lt;p>Some text...&lt;/p>
+ &lt;/section>
+
+ &lt;authors>
+ &lt;aname>Name of author&lt;/aname>
+ &lt;email>Email of author&lt;/email>
+ &lt;/authors>
+&lt;/erlref>
+ </pre>
+
+ <section>
+ <marker id="erlrefTAG"></marker>
+ <title>&lt;erlref&gt;</title>
+
+ <p>The top level tag for an <c>erlref</c> DTD.</p>
+
+ <p>Contains
+ <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
+ <seealso marker="#moduleTAG">&lt;module&gt;</seealso>,
+ <seealso marker="#modulesummaryTAG">&lt;modulesummary&gt;</seealso>,
+ <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
+ zero or more
+ <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
+ <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
+ followed by zero or more
+ <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="moduleTAG"></marker>
+ <title>&lt;module&gt;</title>
+
+ <p>The module name. Contains plain text.</p>
+ </section>
+
+ <section>
+ <marker id="modulesummaryTAG"></marker>
+ <title>&lt;modulesummary&gt;</title>
+
+ <p>Short summary. Contains plain text.</p>
+ </section>
+ </section>
+
+ <section>
+ <marker id="filerefDTD"></marker>
+ <title>The fileref DTD</title>
+
+ <p>This is the DTD for writing file manual pages. In OTP, this DTD
+ is used for defining the format of for example <c>.rel</c> and
+ <c>.app</c> files.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE fileref SYSTEM "fileref.dtd">
+&lt;fileref>
+ &lt;header>
+ &lt;title>File name&lt;/title>
+ &lt;prepared/>
+ &lt;docno/>
+ &lt;date/>
+ &lt;rev/>
+ &lt;/header>
+
+ &lt;file>fileref&lt;/file>
+
+ &lt;filesummary>A short file summary.&lt;/filesummary>
+
+ &lt;description>
+ &lt;p>A longer description of the file.&lt;/p>
+ &lt;/description>
+
+ &lt;section>
+ &lt;title>File format&lt;/title>
+
+ &lt;p>...&lt;/p>
+ &lt;/section>
+
+ &lt;authors>
+ &lt;aname>Name of author&lt;/aname>
+ &lt;email>Email of author&lt;/email>
+ &lt;/authors>
+&lt;/fileref>
+ </pre>
+
+ <p>The file reference manual can also contain function definitions,
+ similar to the <c>erlref</c> DTD.</p>
+
+ <section>
+ <marker id="filerefTAG"></marker>
+ <title>&lt;fileref&gt;</title>
+
+ <p>The top level tag for a <c>fileref</c> DTD.</p>
+
+ <p>Contains
+ <seealso marker="header_tags#headerTAG">&lt;header&gt;</seealso>,
+ <seealso marker="#fileTAG">&lt;file&gt;</seealso>,
+ <seealso marker="#filesummaryTAG">&lt;filesummary&gt;</seealso>,
+ <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
+ zero or more
+ <seealso marker="#sectionTAG">&lt;section&gt;</seealso> and
+ <seealso marker="#funcsTAG">&lt;funcs&gt;</seealso>,
+ followed by zero or more
+ <seealso marker="#authorsTAG">&lt;authors&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="fileTAG"></marker>
+ <title>&lt;file&gt;</title>
+
+ <p>The name of the file or file type. Contains plain text.</p>
+ </section>
+
+ <section>
+ <marker id="filesummaryTAG"></marker>
+ <title>&lt;filesummary&gt;</title>
+
+ <p>Short summary. Contains plain text.</p>
+ </section>
+ </section>
+
+ <section>
+ <marker id="descriptionTAG"></marker>
+ <title>&lt;description&gt;</title>
+
+ <p>The introduction after the title and before sections and
+ "formal" definitions.</p>
+
+ <p>Contains any combination and any number of
+ <seealso marker="block_tags">block tags</seealso> except
+ <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.</p>
+ </section>
+
+ <section>
+ <marker id="sectionTAG"></marker>
+ <title>&lt;section&gt;</title>
+
+ <p>Subdivisions of the document. Contains an optional
+ <seealso marker="inline_tags#markerTAG">&lt;marker&gt;</seealso>,
+ a <seealso marker="user_guide_dtds#titleTAG">&lt;title&gt;</seealso>,
+
+ followed by any combination and any number of
+ <seealso marker="block_tags">block tags</seealso> except
+ <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.</p>
+ </section>
+
+ <section>
+ <marker id="funcsTAG"></marker>
+ <title>&lt;funcs&gt;</title>
+
+ <p>A group of "formal" function definitions.</p>
+
+ <p>Contains one or more
+ <seealso marker="#funcTAG">&lt;func&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="funcTAG"></marker>
+ <title>&lt;func&gt;</title>
+
+ <p>A "formal" function definition.</p>
+
+ <p>Contains one or more
+ <seealso marker="#nameTAG">&lt;name&gt;</seealso>, followed by
+ <seealso marker="#fsummaryTAG">&lt;fsummary&gt;</seealso>,
+ <seealso marker="#typeTAG">&lt;type&gt;</seealso> (optional) and
+ <seealso marker="#descTAG">&lt;desc&gt;</seealso> (optional).</p>
+ </section>
+
+ <section>
+ <marker id="nameTAG"></marker>
+ <title>&lt;name&gt;</title>
+
+ <p>Function/command signature with name, arguments and return value.
+ Contains plain text, except for the <c>cref</c> DTD where it
+ contains a <c><![CDATA[<ret>]]></c> (return type, plain text) and
+ a <c><![CDATA[<nametext>]]></c> (function name and arguments,
+ plain text).</p>
+
+ <p>In the case of an <c>erlref</c> DTD, it will
+ automatically be added a
+ <seealso marker="inline_tags#markerTAG">marker</seealso>,
+ <c><![CDATA[<marker id="Name/Arity">]]></c> or
+ <c><![CDATA[<marker id="Name">]]></c>, based on the contents of
+ this tag before the function definition.</p>
+
+ <p>Example: Consider the following name definition</p>
+ <pre><![CDATA[
+<name>foo(Arg1, Arg2) -> ok | {error, Reason}</name>
+ ]]></pre>
+
+ <p>Then a marker like this will be added
+ <c><![CDATA[<marker id="foo/2">]]></c> before the function
+ definition in the generated HTML. That is, referring to
+ the function using
+ <c><![CDATA[<seealso marker="#foo/2">foo/2</seealso>]]></c> will
+ automatically work.</p>
+ </section>
+
+ <section>
+ <marker id="fsummaryTAG"></marker>
+ <title>&lt;fsummary&gt;</title>
+
+ <p>Function/command summary. Contains plain text,
+ <seealso marker="inline_tags#cTAG">&lt;c&gt;</seealso> and
+ <seealso marker="inline_tags#emTAG">&lt;em&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="typeTAG"></marker>
+ <title>&lt;type&gt;</title>
+
+ <p>Type declarations for the function/command.</p>
+
+ <p>Contains one or more pairs of
+ <seealso marker="#vTAG">&lt;v&gt;</seealso> and
+ <seealso marker="#dTAG">&lt;d&gt;</seealso> (optional).</p>
+ </section>
+
+ <section>
+ <marker id="vTAG"></marker>
+ <title>&lt;v&gt;</title>
+
+ <p>Type declaration for an argument or return value. Contains plain
+ text.</p>
+ </section>
+
+ <section>
+ <marker id="dTAG"></marker>
+ <title>&lt;d&gt;</title>
+
+ <p>Description for an argument or return value. Contains plain text,
+ <seealso marker="inline_tags#cTAG">&lt;c&gt;</seealso> and
+ <seealso marker="inline_tags#emTAG">&lt;em&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="descTAG"></marker>
+ <title>&lt;desc&gt;</title>
+
+ <p>Function/command description. Contains
+ <seealso marker="block_tags">block tags</seealso> except
+ <c>&lt;image&gt;</c> and <c>&lt;table&gt;</c>.</p>
+ </section>
+
+ <section>
+ <marker id="authorsTAG"></marker>
+ <title>&lt;authors&gt;</title>
+
+ <p>Authors of the manual page. The <c>authors</c> element is optional.</p>
+
+ <p>Contains one or more pairs of
+ <seealso marker="#anameTAG">&lt;aname&gt;</seealso> and
+ <seealso marker="#emailTAG">&lt;email&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="anameTAG"></marker>
+ <title>&lt;aname&gt;</title>
+
+ <p>Author name. Contains plain text.</p>
+ </section>
+
+ <section>
+ <marker id="emailTAG"></marker>
+ <title>&lt;email&gt;</title>
+
+ <p>Author email address. Contains plain text.</p>
+ </section>
+</chapter>
+
diff --git a/lib/erl_docgen/doc/src/user_guide_dtds.xml b/lib/erl_docgen/doc/src/user_guide_dtds.xml
new file mode 100644
index 0000000000..79a7701ce8
--- /dev/null
+++ b/lib/erl_docgen/doc/src/user_guide_dtds.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</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>User's Guide DTDs</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>user_guide_dtds.xml</file>
+ </header>
+
+ <section>
+ <marker id="partDTD"></marker>
+ <title>The part DTD</title>
+
+ <p>The <c>part</c> DTD is intended for a "normal" document, like
+ the User's Guide or Release Notes. First are some paragraphs
+ introducing the main contents. After that follows chapters,
+ written in separate files with
+ the <seealso marker="#chapterDTD">chapter</seealso> DTD.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE part SYSTEM "part.dtd"&gt;
+&lt;part&gt;
+ &lt;header&gt;
+ &lt;title&gt;The chapter title&lt;/title&gt;
+ &lt;prepared&gt;The author&lt;/prepared&gt;
+ &lt;docno/&gt;
+ &lt;date/&gt;
+ &lt;rev/&gt;
+ &lt;/header&gt;
+
+ &lt;description&gt;
+ &lt;p&gt;Some text..&lt;/p&gt;
+ &lt;/description&gt;
+
+ &lt;include file="file1"&gt;&lt;/include&gt;
+ &lt;include file="file2"&gt;&lt;/include&gt;
+&lt;/part&gt;
+ </pre>
+ </section>
+
+ <section>
+ <marker id="partTAG"></marker>
+ <title>&lt;part></title>
+
+ <p>The top level tag of a <c>part</c> DTD.</p>
+
+ <p>Contains a
+ <seealso marker="header_tags">&lt;header&gt;</seealso>,
+ an optional
+ <seealso marker="#descriptionTAG">&lt;description&gt;</seealso>,
+ followed by one or more
+ <seealso marker="#includeTAG">&lt;include&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="descriptionTAG"/>
+ <title>&lt;description&gt;</title>
+
+ <p>The introduction after the title and before the bulk of
+ included chapters/manual pages.</p>
+
+ <p>Contains any combination and any number
+ of <seealso marker="block_tags">block tags</seealso> except
+ <c><![CDATA[<image>]]></c> and <c><![CDATA[<table>]]></c>.</p>
+ </section>
+
+ <section>
+ <marker id="includeTAG"></marker>
+ <title>&lt;include&gt;</title>
+
+ <p>An empty tag. The attribute <c>file</c> specifies a file to
+ include. The <c>.xml</c> file extension should be omitted.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;include file="notes">&lt;/include>
+ </pre>
+ </section>
+
+ <section>
+ <marker id="chapterDTD"></marker>
+ <title>The chapter DTD</title>
+
+ <p>The <c>chapter</c> DTD is intended for a chapter in a User's
+ Guide or similar with text divided into sections, which can be
+ nested.</p>
+
+ <p>Example:</p>
+ <pre>
+&lt;?xml version="1.0" encoding="latin1" ?>
+&lt;!DOCTYPE chapter SYSTEM "chapter.dtd">
+&lt;chapter>
+ &lt;header>
+ &lt;title>Title on first level&lt;/title>
+ &lt;prepared/>
+ &lt;docno/>
+ &lt;date/>
+ &lt;rev/>
+ &lt;/header>
+
+ &lt;p>Introduction...&lt;/p>
+
+ &lt;section>
+ &lt;title>Title on second level&lt;/title>
+
+ &lt;p>First paragraph.&lt;/p>
+
+ &lt;p>Second paragraph etc.&lt;/p>
+
+ &lt;section>
+ &lt;title>Title on third level&lt;/title>
+
+ &lt;p>...&lt;/p>
+ &lt;/section>
+ &lt;/section>
+
+ ...
+&lt;/chapter>
+ </pre>
+ </section>
+
+ <section>
+ <marker id="chapterTAG"></marker>
+ <title>&lt;chapter&gt;</title>
+
+ <p>The top level tag of a <c>chapter</c> DTD.</p>
+
+ <p>Contains a
+ <seealso marker="header_tags">&lt;header&gt;</seealso>,
+ an optional introduction consisting of any combination of
+ <seealso marker="block_tags">block tags</seealso>,
+ followed by one or more
+ <seealso marker="#sectionTAG">&lt;section&gt;</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="sectionTAG"></marker>
+ <title>&lt;section&gt;</title>
+
+ <p>Subdivision of a chapter.</p>
+
+ <p>Contains an optional
+ <seealso marker="inline_tags#markerTAG">&lt;marker&gt;</seealso>,
+ a <seealso marker="#titleTAG">&lt;title&gt;</seealso>,
+ followed by any combination and any number of
+ <seealso marker="block_tags">block tags</seealso> and
+ <c><![CDATA[<section>]]></c>.</p>
+ </section>
+
+ <section>
+ <marker id="titleTAG"></marker>
+ <title>&lt;title&gt;</title>
+
+ <p>Section title, contains plain text.</p>
+ </section>
+</chapter>
+
diff --git a/lib/erl_docgen/info b/lib/erl_docgen/info
new file mode 100644
index 0000000000..31c7eb911a
--- /dev/null
+++ b/lib/erl_docgen/info
@@ -0,0 +1,2 @@
+group: doc Documentation Applications
+short: A utility used to produce the OTP documentation.
diff --git a/lib/erl_docgen/priv/Makefile b/lib/erl_docgen/priv/Makefile
index f50350bef2..18cf7b90dd 100644
--- a/lib/erl_docgen/priv/Makefile
+++ b/lib/erl_docgen/priv/Makefile
@@ -22,7 +22,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = bin css docbuilder_dtd dtd_html_entities dtd_man_entities images js/flipmenu xsl
+SUB_DIRECTORIES = bin css dtd dtd_html_entities dtd_man_entities images js/flipmenu xsl
SPECIAL_TARGETS =
diff --git a/lib/erl_docgen/priv/bin/Makefile b/lib/erl_docgen/priv/bin/Makefile
index 95ad36216a..449cc6691c 100644
--- a/lib/erl_docgen/priv/bin/Makefile
+++ b/lib/erl_docgen/priv/bin/Makefile
@@ -64,8 +64,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_SCRIPT) $(ESCRIPT_FILES) $(RELSYSDIR)/priv/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_SCRIPT) $(ESCRIPT_FILES) "$(RELSYSDIR)/priv/bin"
release_docs_spec:
diff --git a/lib/erl_docgen/priv/bin/specs_gen.escript b/lib/erl_docgen/priv/bin/specs_gen.escript
index 982afece7f..156311565c 100644
--- a/lib/erl_docgen/priv/bin/specs_gen.escript
+++ b/lib/erl_docgen/priv/bin/specs_gen.escript
@@ -19,7 +19,7 @@
%%% <script> [-I<dir>]... [-o<dir>] [-module Module] [File]
%%%
-%%% Use EDoc and the layout module 'otp_specs' to create an XML file
+%%% Use EDoc and the layout module 'docgen_otp_specs' to create an XML file
%%% containing Dialyzer types and specifications (-type, -spec).
%%%
%%% Options:
@@ -69,7 +69,7 @@ usage() ->
call_edoc(FileSpec, InclFs, Dir) ->
ReadOpts = [{includes, InclFs}, {preprocess, true}],
ExtractOpts = [{report_missing_type, false}],
- LayoutOpts = [{pretty_printer, erl_pp}, {layout, otp_specs}],
+ LayoutOpts = [{pretty_printer, erl_pp}, {layout, docgen_otp_specs}],
File = case FileSpec of
{file, File0} -> File0;
{module, Module0} -> Module0
diff --git a/lib/erl_docgen/priv/bin/xml_from_edoc.escript b/lib/erl_docgen/priv/bin/xml_from_edoc.escript
index ee79e82c3a..2cb81be1be 100755
--- a/lib/erl_docgen/priv/bin/xml_from_edoc.escript
+++ b/lib/erl_docgen/priv/bin/xml_from_edoc.escript
@@ -2,7 +2,7 @@
%% -*- erlang -*-
%% %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
@@ -27,7 +27,7 @@
%% Records
%%======================================================================
-record(args, {suffix=".xml",
- layout=docb_edoc_xml_cb,
+ layout=docgen_edoc_xml_cb,
def=[],
includes=[],
preprocess=false,
@@ -126,7 +126,7 @@ users_guide(File, Args) ->
parse(["-xml" |RawOpts], Type, Args) ->
parse(RawOpts, Type, Args); % default, no update of record necessary
parse(["-sgml" |RawOpts], Type, Args) ->
- parse(RawOpts, Type, Args#args{suffix=".sgml", layout=docb_edoc_sgml_cb});
+ parse(RawOpts, Type, Args#args{suffix=".sgml", layout=docgen_edoc_sgml_cb});
parse(["-chapter" |RawOpts], _Type, Args) ->
parse(RawOpts, chapter, Args);
parse(["-def", Key, Val |RawOpts], Type, Args) ->
diff --git a/lib/erl_docgen/priv/css/Makefile b/lib/erl_docgen/priv/css/Makefile
index 81124fb111..0faca019f3 100644
--- a/lib/erl_docgen/priv/css/Makefile
+++ b/lib/erl_docgen/priv/css/Makefile
@@ -64,13 +64,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/css
- $(INSTALL_DATA) $(CSS_FILES) $(RELSYSDIR)/priv/css
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/css"
+ $(INSTALL_DATA) $(CSS_FILES) "$(RELSYSDIR)/priv/css"
release_docs_spec:
- $(INSTALL_DIR) $(RELEASE_PATH)/doc
- $(INSTALL_DATA) $(CSS_FILES) ../nyi.html $(RELEASE_PATH)/doc
+ $(INSTALL_DIR) "$(RELEASE_PATH)/doc"
+ $(INSTALL_DATA) $(CSS_FILES) ../nyi.html "$(RELEASE_PATH)/doc"
release_tests_spec:
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 97d8c2df74..c56de378f4 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -1,6 +1,5 @@
-
-
-body {
+/* standard OTP style sheet */
+body {
background: white;
font-family: Verdana, Arial, Helvetica, sans-serif;
margin: 0;
@@ -11,7 +10,6 @@ body {
max-height: 100%;
}
-
th { font-family: Verdana, Arial, Helvetica, sans-serif }
td { font-family: Verdana, Arial, Helvetica, sans-serif }
p { font-family: Verdana, Arial, Helvetica, sans-serif }
@@ -33,8 +31,7 @@ a:visited { color: blue; text-decoration: none }
background-color: #fff;
}
-
-#leftnav {
+#leftnav {
position: fixed;
float: left;
top: 0;
@@ -47,8 +44,7 @@ a:visited { color: blue; text-decoration: none }
border-right: 1px solid red;
}
-
-#content {
+#content {
margin-left: 240px; /* set left value to WidthOfFrameDiv */
}
@@ -57,7 +53,6 @@ a:visited { color: blue; text-decoration: none }
padding-top: 50px; /* Magins for inner DIV inside each DIV (to provide padding) */
}
-
.innertube
{
margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */
@@ -66,16 +61,15 @@ a:visited { color: blue; text-decoration: none }
.footer
{
margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */
-
}
-span.bold_code { font-family: courier;font-weight: bold}
-span.code { font-family: courier;font-weight: normal}
+
+span.bold_code { font-family: Courier, monospace; font-weight: bold }
+span.code { font-family: Courier, monospace; font-weight: normal }
.note, .warning {
border: solid black 1px;
margin: 1em 3em;
}
-
.note .label {
background: #30d42a;
color: white;
@@ -102,16 +96,15 @@ span.code { font-family: courier;font-weight: normal}
font-size: 90%;
padding: 5px 10px;
}
-
-.example {
+.example {
background-color:#eeeeff;
padding: 0px 10px;
-}
+}
-pre { font-family: courier; font-weight: normal }
+pre { font-family: Courier, monospace; font-weight: normal }
.REFBODY { margin-left: 13mm }
.REFTYPES { margin-left: 8mm }
-footer { }
+footer { }
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/Makefile b/lib/erl_docgen/priv/docbuilder_dtd/Makefile
deleted file mode 100644
index e2214107cb..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/Makefile
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(ERL_DOCGEN_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/erl_docgen-$(VSN)
-
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-
-DTD_FILES = \
- application.dtd \
- chapter.dtd \
- common.header.dtd \
- comref.dtd \
- fileref.dtd \
- xhtml1-frameset.dtd \
- appref.dtd \
- cites.dtd \
- common.image.dtd \
- cref.dtd \
- part.dtd \
- xhtml1-strict.dtd \
- book.dtd \
- common.dtd \
- common.refs.dtd \
- erlref.dtd \
- report.dtd \
- xhtml1-transitional.dtd \
- bookinsidecover.dtd \
- common.entities.dtd \
- common.table.dtd \
- fascicules.dtd \
- terms.dtd
-
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug opt:
-
-docs:
-
-clean:
- $(RM) $(TARGET_FILES)
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/docbuilder_dtd
- $(INSTALL_DATA) $(DTD_FILES) $(RELSYSDIR)/priv/docbuilder_dtd
-
-
-release_docs_spec:
-
-
-release_tests_spec:
-
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/application.dtd b/lib/erl_docgen/priv/docbuilder_dtd/application.dtd
deleted file mode 100644
index 8a1e8832ec..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/application.dtd
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common SYSTEM "common.dtd" >
-%common;
-<!ENTITY % common.header SYSTEM "common.header.dtd" >
-%common.header;
-
-<!ELEMENT application (header,description?,include+) >
-<!ELEMENT description (%block;|quote|br|marker|warning|note)* >
-<!ELEMENT include EMPTY >
-<!ATTLIST include file CDATA #REQUIRED>
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/appref.dtd b/lib/erl_docgen/priv/docbuilder_dtd/appref.dtd
deleted file mode 100644
index 70a5ff37af..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/appref.dtd
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common.refs SYSTEM "common.refs.dtd" >
-%common.refs;
-
-<!-- Structure -->
-
-<!ELEMENT appref (header,app,appsummary,description,
- (section|funcs)*,authors?) >
-<!ELEMENT app (#PCDATA) >
-<!ELEMENT appsummary (#PCDATA) >
-
-<!-- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd -->
-<!ELEMENT name (#PCDATA) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/book.dtd b/lib/erl_docgen/priv/docbuilder_dtd/book.dtd
deleted file mode 100644
index bb89a6d255..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/book.dtd
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common SYSTEM "common.dtd" >
-%common;
-<!ENTITY % common.header SYSTEM "common.header.dtd" >
-%common.header;
-<!ENTITY % common.table SYSTEM "common.table.dtd" >
-%common.table;
-
-<!ELEMENT book (header,
- insidecover?,
- pagetext,
- preamble,
- (applications|parts|headline|pagetext)+,
- (listoffigures?,
- listoftables?,
- listofterms?,
- bibliography?,
- index?)) >
-
-<!ELEMENT pagetext (#PCDATA) >
-<!ELEMENT preamble (contents?,preface?) >
-<!ELEMENT preface (title?,(%block;|quote|br|marker|warning|note|table)*) >
-
-<!ELEMENT insidecover (#PCDATA|br|theheader|vfill|vspace|tt|bold|
- include)* >
-<!ELEMENT tt (#PCDATA|br|theheader|vfill)* >
-<!ELEMENT bold (#PCDATA|br|theheader|vfill)* >
-<!ELEMENT vfill EMPTY >
-<!ELEMENT theheader EMPTY >
-<!ATTLIST theheader tag (title|prepared|responsible|docno|
- approved|checked|date|rev|file|
- abbreviation|
- none) "none" >
-
-
-<!ELEMENT applications (include)* >
-<!ELEMENT parts (title?,description?,(include|onepart)*) >
-<!ATTLIST parts lift (yes|no) "no" >
-<!ELEMENT headline (#PCDATA) >
-<!ELEMENT index EMPTY >
-<!ELEMENT listoffigures EMPTY >
-<!ELEMENT listoftables EMPTY >
-<!ELEMENT listofterms EMPTY >
-<!ELEMENT bibliography EMPTY >
-<!ELEMENT contents EMPTY >
-<!ATTLIST contents level (0|1|2|3) "2">
-
-<!ELEMENT onepart (title?,description?,include+) >
-<!ATTLIST onepart lift (yes|no) "no" >
-
-<!ELEMENT description (%block;|quote|br|marker|warning|note)* >
-
-<!ELEMENT include EMPTY >
-<!ATTLIST include file CDATA #REQUIRED>
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/bookinsidecover.dtd b/lib/erl_docgen/priv/docbuilder_dtd/bookinsidecover.dtd
deleted file mode 100644
index d6efbef6a4..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/bookinsidecover.dtd
+++ /dev/null
@@ -1,36 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ENTITY % ISOlat1 SYSTEM "xhtml-lat1.ent" >
-%ISOlat1;
-
-<!ENTITY amp "&#x0026;" >
-<!ENTITY gt "&#x003E;" >
-<!ENTITY lt "&#x003C;" >
-
-<!ELEMENT bookinsidecover (#PCDATA|br|theheader|vfill|tt|bold)* >
-
-<!ELEMENT tt (#PCDATA|br|theheader|vfill)* >
-<!ELEMENT bold (#PCDATA|br|theheader|vfill)* >
-<!ELEMENT vfill EMPTY >
-<!ELEMENT theheader EMPTY >
-<!ATTLIST theheader tag (title|prepared|responsible|docno|
- approved|checked|date|rev|file|
- none) "none" >
-
-<!ELEMENT br EMPTY >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/chapter.dtd b/lib/erl_docgen/priv/docbuilder_dtd/chapter.dtd
deleted file mode 100644
index eb2c96b04f..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/chapter.dtd
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common SYSTEM "common.dtd" >
-%common;
-<!ENTITY % common.header SYSTEM "common.header.dtd" >
-%common.header;
-<!ENTITY % common.table SYSTEM "common.table.dtd" >
-%common.table;
-<!ENTITY % common.image SYSTEM "common.image.dtd" >
-%common.image;
-
-<!-- Structure -->
-
-<!ELEMENT chapter (header,(%block;|quote|warning|note|br|
- image|marker|table)*,section+) >
-<!ELEMENT section (marker*,title,
- (%block;|quote|warning|note|br|image|marker|
- table|section)*) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/cites.dtd b/lib/erl_docgen/priv/docbuilder_dtd/cites.dtd
deleted file mode 100644
index 334574bff9..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/cites.dtd
+++ /dev/null
@@ -1,35 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ENTITY % ISOlat1 SYSTEM "xhtml-lat1.ent" >
-%ISOlat1;
-
-<!ENTITY amp "&#x0026;" >
-<!ENTITY gt "&#x003E;" >
-<!ENTITY lt "&#x003C;" >
-
-<!-- Structure -->
-
-<!ELEMENT cites (cite)* >
-<!ELEMENT cite (id, shortdef, def, resp?) >
-<!ELEMENT id (#PCDATA) >
-<!ELEMENT shortdef (#PCDATA) >
-<!ELEMENT def (#PCDATA|c|em)* >
-<!ELEMENT resp (#PCDATA) >
-<!ELEMENT c (#PCDATA) >
-<!ELEMENT em (#PCDATA|c)* >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/common.entities.dtd b/lib/erl_docgen/priv/docbuilder_dtd/common.entities.dtd
deleted file mode 100644
index f893ecd070..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/common.entities.dtd
+++ /dev/null
@@ -1,24 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ENTITY % ISOlat1 SYSTEM "xhtml-lat1.ent" >
-%ISOlat1;
-
-<!ENTITY amp "&#x0026;" >
-<!ENTITY gt "&#x003E;" >
-<!ENTITY lt "&#x003C;" >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/common.header.dtd b/lib/erl_docgen/priv/docbuilder_dtd/common.header.dtd
deleted file mode 100644
index d422a89693..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/common.header.dtd
+++ /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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ELEMENT header (copyright?,legalnotice?,title,shorttitle?,
- prepared,responsible?,docno,approved?,
- checked?,date,rev,file?) >
-
-<!--
-The titlestyle attribute is only defined to make all the book.xml files
-go through the validation. The attribute is not used for anything
--->
-<!ATTLIST header titlestyle (special|normal) "normal">
-
-<!ELEMENT title (#PCDATA) >
-<!ELEMENT shorttitle (#PCDATA) >
-<!ELEMENT prepared (#PCDATA) >
-<!ELEMENT responsible (#PCDATA) >
-<!ELEMENT docno (#PCDATA) >
-<!ELEMENT approved (#PCDATA) >
-<!ELEMENT checked (#PCDATA) >
-<!ELEMENT copyright (year+,holder*) >
-<!ELEMENT legalnotice (#PCDATA) >
-<!ELEMENT date (#PCDATA) >
-<!ELEMENT rev (#PCDATA) >
-<!ELEMENT file (#PCDATA) >
-<!ELEMENT year (#PCDATA) >
-<!ELEMENT holder (#PCDATA) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/common.image.dtd b/lib/erl_docgen/priv/docbuilder_dtd/common.image.dtd
deleted file mode 100644
index fc95a669dd..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/common.image.dtd
+++ /dev/null
@@ -1,21 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ELEMENT image (icaption) >
-<!ATTLIST image file CDATA #REQUIRED >
-<!ELEMENT icaption (#PCDATA) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/common.table.dtd b/lib/erl_docgen/priv/docbuilder_dtd/common.table.dtd
deleted file mode 100644
index 7741da1018..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/common.table.dtd
+++ /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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ELEMENT table (row+,tcaption) >
-<!ATTLIST table align (left|center|right) "center" >
-<!ELEMENT row (cell+) >
-<!ELEMENT cell (%inline;)* >
-<!ATTLIST cell align (left|center|right) "left"
- valign (top|middle|bottom) "middle" >
-<!ELEMENT tcaption (#PCDATA) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/comref.dtd b/lib/erl_docgen/priv/docbuilder_dtd/comref.dtd
deleted file mode 100644
index fcdea625d5..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/comref.dtd
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common.refs SYSTEM "common.refs.dtd" >
-%common.refs;
-
-<!ELEMENT comref (header,com,comsummary,description,
- (section|funcs)*,authors?) >
-<!ELEMENT com (#PCDATA) >
-<!ELEMENT comsummary (#PCDATA) >
-
-<!-- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd -->
-<!ELEMENT name (#PCDATA) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/cref.dtd b/lib/erl_docgen/priv/docbuilder_dtd/cref.dtd
deleted file mode 100644
index e43bb2bf51..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/cref.dtd
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common.refs SYSTEM "common.refs.dtd" >
-%common.refs;
-
-<!ELEMENT cref (header,lib,libsummary,description,
- (section|funcs)*,authors?) >
-<!ELEMENT lib (#PCDATA) >
-<!ELEMENT libsummary (#PCDATA) >
-
-<!-- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd -->
-<!ELEMENT name (ret,nametext) >
-<!ELEMENT ret (#PCDATA) >
-<!ELEMENT nametext (#PCDATA) >
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/fascicules.dtd b/lib/erl_docgen/priv/docbuilder_dtd/fascicules.dtd
deleted file mode 100644
index b14276a2c0..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/fascicules.dtd
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % ISOlat1 SYSTEM "xhtml-lat1.ent" >
-%ISOlat1;
-
-<!ENTITY amp "&#x0026;" >
-<!ENTITY gt "&#x003E;" >
-<!ENTITY lt "&#x003C;" >
-
-<!-- Structure -->
-
-<!ELEMENT fascicules (fascicule)+ >
-<!ELEMENT fascicule (#PCDATA) >
-<!ATTLIST fascicule file CDATA #REQUIRED
- href CDATA #REQUIRED
- entry (yes|no) "no" >
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/fileref.dtd b/lib/erl_docgen/priv/docbuilder_dtd/fileref.dtd
deleted file mode 100644
index 5a1cc54afe..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/fileref.dtd
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common.refs SYSTEM "common.refs.dtd" >
-%common.refs;
-
-<!ELEMENT fileref (header,file,filesummary,description,
- (section|funcs)*,authors?) >
-<!-- Note: ELEMENT file is already defined -->
-<!ELEMENT filesummary (#PCDATA) >
-
-<!-- `name' is used in common.refs.dtd and must therefore
- be defined in each *ref. dtd -->
-<!ELEMENT name (#PCDATA) >
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/part.dtd b/lib/erl_docgen/priv/docbuilder_dtd/part.dtd
deleted file mode 100644
index 3f97199042..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/part.dtd
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % common SYSTEM "common.dtd" >
-%common;
-<!ENTITY % common.header SYSTEM "common.header.dtd" >
-%common.header;
-
-<!ELEMENT part (header,description?,include+) >
-<!ELEMENT description (%block;|quote|br|marker|warning|note)* >
-<!ELEMENT include EMPTY >
-<!ATTLIST include file CDATA #REQUIRED>
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/report.dtd b/lib/erl_docgen/priv/docbuilder_dtd/report.dtd
deleted file mode 100644
index 3d07e6e5a7..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/report.dtd
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved via the world wide web at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-
-<!ENTITY % ISOlat1 SYSTEM "xhtml-lat1.ent" >
-%ISOlat1;
-
-<!ENTITY amp "&#x0026;" >
-<!ENTITY gt "&#x003E;" >
-<!ENTITY lt "&#x003C;" >
-
-<!ENTITY % header "title,prepared,responsible,docno,approved,
- checked,date,rev,file" >
-<!ENTITY % block "p|pre|code|list|taglist|erlinclude|
- codeinclude|erleval" >
-<!ENTITY % inline "#PCDATA|i|b|c|em|term|cite|br|path|seealso|
- url|marker" >
-
-<!-- Structure -->
-
-<!ELEMENT report (header,section+) >
-<!ELEMENT header (title,prepared,responsible?,docno,approved?,
- checked?,date,rev,file?) >
-<!ELEMENT title (#PCDATA) >
-<!ELEMENT prepared (#PCDATA) >
-<!ELEMENT responsible (#PCDATA) >
-<!ELEMENT docno (#PCDATA) >
-<!ELEMENT approved (#PCDATA) >
-<!ELEMENT checked (#PCDATA) >
-<!ELEMENT date (#PCDATA) >
-<!ELEMENT rev (#PCDATA) >
-<!ELEMENT file (#PCDATA) >
-
-<!ELEMENT section (marker*,title,
- (%block;|quote|warning|note|br|image|marker|
- table|section)*) >
-<!ELEMENT p (%inline;|index)* >
-<!ELEMENT pre (#PCDATA|seealso|url|input)* >
-<!ELEMENT input (#PCDATA|seealso|url)* >
-<!ELEMENT code (#PCDATA) >
-<!ATTLIST code type (erl|c|none) "none" >
-<!ELEMENT quote (p)* >
-<!ELEMENT warning (%block;|quote|br|image|marker|table)* >
-<!ELEMENT note (%block;|quote|br|image|marker|table)* >
-<!ELEMENT i (#PCDATA|b|c|em)* >
-<!ELEMENT b (#PCDATA|i|c|em)* >
-<!ELEMENT c (#PCDATA) >
-<!ELEMENT em (#PCDATA|i|b|c)* >
-<!ELEMENT term (termdef?) >
-<!ATTLIST term id CDATA #REQUIRED >
-<!ELEMENT termdef (#PCDATA) >
-<!ELEMENT cite (citedef?) >
-<!ATTLIST cite id CDATA #REQUIRED >
-<!ELEMENT citedef (ctitle,cauthor,chowpublished) >
-<!ELEMENT ctitle (#PCDATA) >
-<!ELEMENT cauthor (#PCDATA) >
-<!ELEMENT chowpublished (#PCDATA) >
-<!ELEMENT br EMPTY >
-
-<!-- Path -->
-
-<!ELEMENT path (#PCDATA) >
-<!ATTLIST path unix CDATA ""
- windows CDATA "" >
-
-<!-- List -->
-
-<!ELEMENT list (item+) >
-<!ATTLIST list type (ordered|bulleted) "bulleted" >
-<!ELEMENT taglist (tag,item)+ >
-<!ELEMENT tag (#PCDATA|i|b|c|em|seealso|url)* >
-<!ELEMENT item (%inline;|%block;)* >
-
-<!-- Image -->
-
-<!ELEMENT image (icaption?) >
-<!ATTLIST image file CDATA #REQUIRED >
-<!ELEMENT icaption (#PCDATA) >
-
-<!-- References -->
-
-<!ELEMENT seealso (#PCDATA) >
-<!ATTLIST seealso marker CDATA #REQUIRED >
-<!ELEMENT url (#PCDATA) >
-<!ATTLIST url href CDATA #REQUIRED >
-<!ELEMENT marker EMPTY >
-<!ATTLIST marker id CDATA #REQUIRED >
-
-<!-- Table -->
-
-<!ELEMENT table (row+,tcaption?) >
-<!ATTLIST table width CDATA "0"
- colspec CDATA "" >
-<!ELEMENT row (cell+) >
-<!ELEMENT cell (%inline;)* >
-<!ATTLIST cell align (left|center|right) "left"
- valign (top|middle|bottom) "middle" >
-<!ELEMENT tcaption (#PCDATA) >
-
-<!-- ErlInclude -->
-
-<!ELEMENT erlinclude EMPTY >
-<!ATTLIST erlinclude file CDATA #REQUIRED
- tag CDATA #REQUIRED >
-
-<!-- CodeInclude -->
-
-<!ELEMENT codeinclude EMPTY >
-<!ATTLIST codeinclude file CDATA #REQUIRED
- tag CDATA ""
- type (erl|c|none) "none" >
-
-<!-- ErlEval -->
-
-<!ELEMENT erleval EMPTY >
-<!ATTLIST erleval expr CDATA #REQUIRED >
-
-<!-- Index FOR COMPATIBILITY -->
-
-<!ELEMENT index EMPTY >
-<!ATTLIST index txt CDATA #REQUIRED >
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/terms.dtd b/lib/erl_docgen/priv/docbuilder_dtd/terms.dtd
deleted file mode 100644
index 6105ec593e..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/terms.dtd
+++ /dev/null
@@ -1,36 +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 expressed or 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.
- Portions created by Ericsson are Copyright 1999-2007, Ericsson AB.
- All Rights Reserved.''
-
- $Id$
--->
-<!ENTITY % ISOlat1 SYSTEM "xhtml-lat1.ent" >
-%ISOlat1;
-
-<!ENTITY amp "&#x0026;" >
-<!ENTITY gt "&#x003E;" >
-<!ENTITY lt "&#x003C;" >
-
-<!-- Structure -->
-
-<!ELEMENT terms (term)* >
-<!ELEMENT term (id, shortdef, def, resp?) >
-<!ELEMENT id (#PCDATA) >
-<!ELEMENT shortdef (#PCDATA) >
-<!ELEMENT def (#PCDATA|c|em)* >
-<!ELEMENT resp (#PCDATA) >
-<!ELEMENT c (#PCDATA) >
-<!ELEMENT em (#PCDATA|c)* >
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-frameset.dtd b/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-frameset.dtd
deleted file mode 100644
index d128f2eb7c..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-frameset.dtd
+++ /dev/null
@@ -1,1235 +0,0 @@
-<!--
- Extensible HTML version 1.0 Frameset DTD
-
- This is the same as HTML 4 Frameset except for
- changes due to the differences between XML and SGML.
-
- Namespace = http://www.w3.org/1999/xhtml
-
- For further information, see: http://www.w3.org/TR/xhtml1
-
- Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
- All Rights Reserved.
-
- This DTD module is identified by the PUBLIC and SYSTEM identifiers:
-
- PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
- SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
-
- $Revision: 1.2 $
- $Date: 2002/08/01 18:37:55 $
-
--->
-
-<!--================ Character mnemonic entities =========================-->
-
-<!ENTITY % HTMLlat1 PUBLIC
- "-//W3C//ENTITIES Latin 1 for XHTML//EN"
- "xhtml-lat1.ent">
-%HTMLlat1;
-
-<!ENTITY % HTMLsymbol PUBLIC
- "-//W3C//ENTITIES Symbols for XHTML//EN"
- "xhtml-symbol.ent">
-%HTMLsymbol;
-
-<!ENTITY % HTMLspecial PUBLIC
- "-//W3C//ENTITIES Special for XHTML//EN"
- "xhtml-special.ent">
-%HTMLspecial;
-
-<!--================== Imported Names ====================================-->
-
-<!ENTITY % ContentType "CDATA">
- <!-- media type, as per [RFC2045] -->
-
-<!ENTITY % ContentTypes "CDATA">
- <!-- comma-separated list of media types, as per [RFC2045] -->
-
-<!ENTITY % Charset "CDATA">
- <!-- a character encoding, as per [RFC2045] -->
-
-<!ENTITY % Charsets "CDATA">
- <!-- a space separated list of character encodings, as per [RFC2045] -->
-
-<!ENTITY % LanguageCode "NMTOKEN">
- <!-- a language code, as per [RFC3066] -->
-
-<!ENTITY % Character "CDATA">
- <!-- a single character, as per section 2.2 of [XML] -->
-
-<!ENTITY % Number "CDATA">
- <!-- one or more digits -->
-
-<!ENTITY % LinkTypes "CDATA">
- <!-- space-separated list of link types -->
-
-<!ENTITY % MediaDesc "CDATA">
- <!-- single or comma-separated list of media descriptors -->
-
-<!ENTITY % URI "CDATA">
- <!-- a Uniform Resource Identifier, see [RFC2396] -->
-
-<!ENTITY % UriList "CDATA">
- <!-- a space separated list of Uniform Resource Identifiers -->
-
-<!ENTITY % Datetime "CDATA">
- <!-- date and time information. ISO date format -->
-
-<!ENTITY % Script "CDATA">
- <!-- script expression -->
-
-<!ENTITY % StyleSheet "CDATA">
- <!-- style sheet data -->
-
-<!ENTITY % Text "CDATA">
- <!-- used for titles etc. -->
-
-<!ENTITY % FrameTarget "NMTOKEN">
- <!-- render in this frame -->
-
-<!ENTITY % Length "CDATA">
- <!-- nn for pixels or nn% for percentage length -->
-
-<!ENTITY % MultiLength "CDATA">
- <!-- pixel, percentage, or relative -->
-
-<!ENTITY % MultiLengths "CDATA">
- <!-- comma-separated list of MultiLength -->
-
-<!ENTITY % Pixels "CDATA">
- <!-- integer representing length in pixels -->
-
-<!-- these are used for image maps -->
-
-<!ENTITY % Shape "(rect|circle|poly|default)">
-
-<!ENTITY % Coords "CDATA">
- <!-- comma separated list of lengths -->
-
-<!-- used for object, applet, img, input and iframe -->
-<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
-
-<!-- a color using sRGB: #RRGGBB as Hex values -->
-<!ENTITY % Color "CDATA">
-
-<!-- There are also 16 widely known color names with their sRGB values:
-
- Black = #000000 Green = #008000
- Silver = #C0C0C0 Lime = #00FF00
- Gray = #808080 Olive = #808000
- White = #FFFFFF Yellow = #FFFF00
- Maroon = #800000 Navy = #000080
- Red = #FF0000 Blue = #0000FF
- Purple = #800080 Teal = #008080
- Fuchsia= #FF00FF Aqua = #00FFFF
--->
-
-<!--=================== Generic Attributes ===============================-->
-
-<!-- core attributes common to most elements
- id document-wide unique id
- class space separated list of classes
- style associated style info
- title advisory title/amplification
--->
-<!ENTITY % coreattrs
- "id ID #IMPLIED
- class CDATA #IMPLIED
- style %StyleSheet; #IMPLIED
- title %Text; #IMPLIED"
- >
-
-<!-- internationalization attributes
- lang language code (backwards compatible)
- xml:lang language code (as per XML 1.0 spec)
- dir direction for weak/neutral text
--->
-<!ENTITY % i18n
- "lang %LanguageCode; #IMPLIED
- xml:lang %LanguageCode; #IMPLIED
- dir (ltr|rtl) #IMPLIED"
- >
-
-<!-- attributes for common UI events
- onclick a pointer button was clicked
- ondblclick a pointer button was double clicked
- onmousedown a pointer button was pressed down
- onmouseup a pointer button was released
- onmousemove a pointer was moved onto the element
- onmouseout a pointer was moved away from the element
- onkeypress a key was pressed and released
- onkeydown a key was pressed down
- onkeyup a key was released
--->
-<!ENTITY % events
- "onclick %Script; #IMPLIED
- ondblclick %Script; #IMPLIED
- onmousedown %Script; #IMPLIED
- onmouseup %Script; #IMPLIED
- onmouseover %Script; #IMPLIED
- onmousemove %Script; #IMPLIED
- onmouseout %Script; #IMPLIED
- onkeypress %Script; #IMPLIED
- onkeydown %Script; #IMPLIED
- onkeyup %Script; #IMPLIED"
- >
-
-<!-- attributes for elements that can get the focus
- accesskey accessibility key character
- tabindex position in tabbing order
- onfocus the element got the focus
- onblur the element lost the focus
--->
-<!ENTITY % focus
- "accesskey %Character; #IMPLIED
- tabindex %Number; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED"
- >
-
-<!ENTITY % attrs "%coreattrs; %i18n; %events;">
-
-<!-- text alignment for p, div, h1-h6. The default is
- align="left" for ltr headings, "right" for rtl -->
-
-<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
-
-<!--=================== Text Elements ====================================-->
-
-<!ENTITY % special.extra
- "object | applet | img | map | iframe">
-
-<!ENTITY % special.basic
- "br | span | bdo">
-
-<!ENTITY % special
- "%special.basic; | %special.extra;">
-
-<!ENTITY % fontstyle.extra "big | small | font | basefont">
-
-<!ENTITY % fontstyle.basic "tt | i | b | u
- | s | strike ">
-
-<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
-
-<!ENTITY % phrase.extra "sub | sup">
-<!ENTITY % phrase.basic "em | strong | dfn | code | q |
- samp | kbd | var | cite | abbr | acronym">
-
-<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
-
-<!ENTITY % inline.forms "input | select | textarea | label | button">
-
-<!-- these can occur at block or inline level -->
-<!ENTITY % misc.inline "ins | del | script">
-
-<!-- these can only occur at block level -->
-<!ENTITY % misc "noscript | %misc.inline;">
-
-
-<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
-
-<!-- %Inline; covers inline or "text-level" elements -->
-<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
-
-<!--================== Block level elements ==============================-->
-
-<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
-<!ENTITY % lists "ul | ol | dl | menu | dir">
-<!ENTITY % blocktext "pre | hr | blockquote | address | center">
-
-<!ENTITY % block
- "p | %heading; | div | %lists; | %blocktext; | isindex | fieldset | table">
-
-<!-- %Flow; mixes block and inline and is used for list items etc. -->
-<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
-
-<!--================== Content models for exclusions =====================-->
-
-<!-- a elements use %Inline; excluding a -->
-
-<!ENTITY % a.content
- "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
-
-<!-- pre uses %Inline excluding img, object, applet, big, small,
- sub, sup, font, or basefont -->
-
-<!ENTITY % pre.content
- "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
- %inline.forms; | %misc.inline;)*">
-
-
-<!-- form uses %Flow; excluding form -->
-
-<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
-
-<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
-
-<!ENTITY % button.content
- "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
- table | br | span | bdo | object | applet | img | map |
- %fontstyle; | %phrase; | %misc;)*">
-
-<!--================ Document Structure ==================================-->
-
-<!-- the namespace URI designates the document profile -->
-
-<!ELEMENT html (head, frameset)>
-<!ATTLIST html
- %i18n;
- id ID #IMPLIED
- xmlns %URI; #FIXED 'http://www.w3.org/1999/xhtml'
- >
-
-<!--================ Document Head =======================================-->
-
-<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
-
-<!-- content model is %head.misc; combined with a single
- title and an optional base element in any order -->
-
-<!ELEMENT head (%head.misc;,
- ((title, %head.misc;, (base, %head.misc;)?) |
- (base, %head.misc;, (title, %head.misc;))))>
-
-<!ATTLIST head
- %i18n;
- id ID #IMPLIED
- profile %URI; #IMPLIED
- >
-
-<!-- The title element is not considered part of the flow of text.
- It should be displayed, for example as the page header or
- window title. Exactly one title is required per document.
- -->
-<!ELEMENT title (#PCDATA)>
-<!ATTLIST title
- %i18n;
- id ID #IMPLIED
- >
-
-<!-- document base URI -->
-
-<!ELEMENT base EMPTY>
-<!ATTLIST base
- id ID #IMPLIED
- href %URI; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!-- generic metainformation -->
-<!ELEMENT meta EMPTY>
-<!ATTLIST meta
- %i18n;
- id ID #IMPLIED
- http-equiv CDATA #IMPLIED
- name CDATA #IMPLIED
- content CDATA #REQUIRED
- scheme CDATA #IMPLIED
- >
-
-<!--
- Relationship values can be used in principle:
-
- a) for document specific toolbars/menus when used
- with the link element in document head e.g.
- start, contents, previous, next, index, end, help
- b) to link to a separate style sheet (rel="stylesheet")
- c) to make a link to a script (rel="script")
- d) by stylesheets to control how collections of
- html nodes are rendered into printed documents
- e) to make a link to a printable version of this document
- e.g. a PostScript or PDF version (rel="alternate" media="print")
--->
-
-<!ELEMENT link EMPTY>
-<!ATTLIST link
- %attrs;
- charset %Charset; #IMPLIED
- href %URI; #IMPLIED
- hreflang %LanguageCode; #IMPLIED
- type %ContentType; #IMPLIED
- rel %LinkTypes; #IMPLIED
- rev %LinkTypes; #IMPLIED
- media %MediaDesc; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!-- style info, which may include CDATA sections -->
-<!ELEMENT style (#PCDATA)>
-<!ATTLIST style
- %i18n;
- id ID #IMPLIED
- type %ContentType; #REQUIRED
- media %MediaDesc; #IMPLIED
- title %Text; #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!-- script statements, which may include CDATA sections -->
-<!ELEMENT script (#PCDATA)>
-<!ATTLIST script
- id ID #IMPLIED
- charset %Charset; #IMPLIED
- type %ContentType; #REQUIRED
- language CDATA #IMPLIED
- src %URI; #IMPLIED
- defer (defer) #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!-- alternate content container for non script-based rendering -->
-
-<!ELEMENT noscript %Flow;>
-<!ATTLIST noscript
- %attrs;
- >
-
-<!--======================= Frames =======================================-->
-
-<!-- only one noframes element permitted per document -->
-
-<!ELEMENT frameset (frameset|frame|noframes)*>
-<!ATTLIST frameset
- %coreattrs;
- rows %MultiLengths; #IMPLIED
- cols %MultiLengths; #IMPLIED
- onload %Script; #IMPLIED
- onunload %Script; #IMPLIED
- >
-
-<!-- reserved frame names start with "_" otherwise starts with letter -->
-
-<!-- tiled window within frameset -->
-
-<!ELEMENT frame EMPTY>
-<!ATTLIST frame
- %coreattrs;
- longdesc %URI; #IMPLIED
- name NMTOKEN #IMPLIED
- src %URI; #IMPLIED
- frameborder (1|0) "1"
- marginwidth %Pixels; #IMPLIED
- marginheight %Pixels; #IMPLIED
- noresize (noresize) #IMPLIED
- scrolling (yes|no|auto) "auto"
- >
-
-<!-- inline subwindow -->
-
-<!ELEMENT iframe %Flow;>
-<!ATTLIST iframe
- %coreattrs;
- longdesc %URI; #IMPLIED
- name NMTOKEN #IMPLIED
- src %URI; #IMPLIED
- frameborder (1|0) "1"
- marginwidth %Pixels; #IMPLIED
- marginheight %Pixels; #IMPLIED
- scrolling (yes|no|auto) "auto"
- align %ImgAlign; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- >
-
-<!-- alternate content container for non frame-based rendering -->
-
-<!ELEMENT noframes (body)>
-<!ATTLIST noframes
- %attrs;
- >
-
-<!--=================== Document Body ====================================-->
-
-<!ELEMENT body %Flow;>
-<!ATTLIST body
- %attrs;
- onload %Script; #IMPLIED
- onunload %Script; #IMPLIED
- background %URI; #IMPLIED
- bgcolor %Color; #IMPLIED
- text %Color; #IMPLIED
- link %Color; #IMPLIED
- vlink %Color; #IMPLIED
- alink %Color; #IMPLIED
- >
-
-<!ELEMENT div %Flow;> <!-- generic language/style container -->
-<!ATTLIST div
- %attrs;
- %TextAlign;
- >
-
-<!--=================== Paragraphs =======================================-->
-
-<!ELEMENT p %Inline;>
-<!ATTLIST p
- %attrs;
- %TextAlign;
- >
-
-<!--=================== Headings =========================================-->
-
-<!--
- There are six levels of headings from h1 (the most important)
- to h6 (the least important).
--->
-
-<!ELEMENT h1 %Inline;>
-<!ATTLIST h1
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h2 %Inline;>
-<!ATTLIST h2
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h3 %Inline;>
-<!ATTLIST h3
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h4 %Inline;>
-<!ATTLIST h4
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h5 %Inline;>
-<!ATTLIST h5
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h6 %Inline;>
-<!ATTLIST h6
- %attrs;
- %TextAlign;
- >
-
-<!--=================== Lists ============================================-->
-
-<!-- Unordered list bullet styles -->
-
-<!ENTITY % ULStyle "(disc|square|circle)">
-
-<!-- Unordered list -->
-
-<!ELEMENT ul (li)+>
-<!ATTLIST ul
- %attrs;
- type %ULStyle; #IMPLIED
- compact (compact) #IMPLIED
- >
-
-<!-- Ordered list numbering style
-
- 1 arabic numbers 1, 2, 3, ...
- a lower alpha a, b, c, ...
- A upper alpha A, B, C, ...
- i lower roman i, ii, iii, ...
- I upper roman I, II, III, ...
-
- The style is applied to the sequence number which by default
- is reset to 1 for the first list item in an ordered list.
--->
-<!ENTITY % OLStyle "CDATA">
-
-<!-- Ordered (numbered) list -->
-
-<!ELEMENT ol (li)+>
-<!ATTLIST ol
- %attrs;
- type %OLStyle; #IMPLIED
- compact (compact) #IMPLIED
- start %Number; #IMPLIED
- >
-
-<!-- single column list (DEPRECATED) -->
-<!ELEMENT menu (li)+>
-<!ATTLIST menu
- %attrs;
- compact (compact) #IMPLIED
- >
-
-<!-- multiple column list (DEPRECATED) -->
-<!ELEMENT dir (li)+>
-<!ATTLIST dir
- %attrs;
- compact (compact) #IMPLIED
- >
-
-<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
-<!ENTITY % LIStyle "CDATA">
-
-<!-- list item -->
-
-<!ELEMENT li %Flow;>
-<!ATTLIST li
- %attrs;
- type %LIStyle; #IMPLIED
- value %Number; #IMPLIED
- >
-
-<!-- definition lists - dt for term, dd for its definition -->
-
-<!ELEMENT dl (dt|dd)+>
-<!ATTLIST dl
- %attrs;
- compact (compact) #IMPLIED
- >
-
-<!ELEMENT dt %Inline;>
-<!ATTLIST dt
- %attrs;
- >
-
-<!ELEMENT dd %Flow;>
-<!ATTLIST dd
- %attrs;
- >
-
-<!--=================== Address ==========================================-->
-
-<!-- information on author -->
-
-<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
-<!ATTLIST address
- %attrs;
- >
-
-<!--=================== Horizontal Rule ==================================-->
-
-<!ELEMENT hr EMPTY>
-<!ATTLIST hr
- %attrs;
- align (left|center|right) #IMPLIED
- noshade (noshade) #IMPLIED
- size %Pixels; #IMPLIED
- width %Length; #IMPLIED
- >
-
-<!--=================== Preformatted Text ================================-->
-
-<!-- content is %Inline; excluding
- "img|object|applet|big|small|sub|sup|font|basefont" -->
-
-<!ELEMENT pre %pre.content;>
-<!ATTLIST pre
- %attrs;
- width %Number; #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!--=================== Block-like Quotes ================================-->
-
-<!ELEMENT blockquote %Flow;>
-<!ATTLIST blockquote
- %attrs;
- cite %URI; #IMPLIED
- >
-
-<!--=================== Text alignment ===================================-->
-
-<!-- center content -->
-<!ELEMENT center %Flow;>
-<!ATTLIST center
- %attrs;
- >
-
-<!--=================== Inserted/Deleted Text ============================-->
-
-
-<!--
- ins/del are allowed in block and inline content, but its
- inappropriate to include block content within an ins element
- occurring in inline content.
--->
-<!ELEMENT ins %Flow;>
-<!ATTLIST ins
- %attrs;
- cite %URI; #IMPLIED
- datetime %Datetime; #IMPLIED
- >
-
-<!ELEMENT del %Flow;>
-<!ATTLIST del
- %attrs;
- cite %URI; #IMPLIED
- datetime %Datetime; #IMPLIED
- >
-
-<!--================== The Anchor Element ================================-->
-
-<!-- content is %Inline; except that anchors shouldn't be nested -->
-
-<!ELEMENT a %a.content;>
-<!ATTLIST a
- %attrs;
- %focus;
- charset %Charset; #IMPLIED
- type %ContentType; #IMPLIED
- name NMTOKEN #IMPLIED
- href %URI; #IMPLIED
- hreflang %LanguageCode; #IMPLIED
- rel %LinkTypes; #IMPLIED
- rev %LinkTypes; #IMPLIED
- shape %Shape; "rect"
- coords %Coords; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!--===================== Inline Elements ================================-->
-
-<!ELEMENT span %Inline;> <!-- generic language/style container -->
-<!ATTLIST span
- %attrs;
- >
-
-<!ELEMENT bdo %Inline;> <!-- I18N BiDi over-ride -->
-<!ATTLIST bdo
- %coreattrs;
- %events;
- lang %LanguageCode; #IMPLIED
- xml:lang %LanguageCode; #IMPLIED
- dir (ltr|rtl) #REQUIRED
- >
-
-<!ELEMENT br EMPTY> <!-- forced line break -->
-<!ATTLIST br
- %coreattrs;
- clear (left|all|right|none) "none"
- >
-
-<!ELEMENT em %Inline;> <!-- emphasis -->
-<!ATTLIST em %attrs;>
-
-<!ELEMENT strong %Inline;> <!-- strong emphasis -->
-<!ATTLIST strong %attrs;>
-
-<!ELEMENT dfn %Inline;> <!-- definitional -->
-<!ATTLIST dfn %attrs;>
-
-<!ELEMENT code %Inline;> <!-- program code -->
-<!ATTLIST code %attrs;>
-
-<!ELEMENT samp %Inline;> <!-- sample -->
-<!ATTLIST samp %attrs;>
-
-<!ELEMENT kbd %Inline;> <!-- something user would type -->
-<!ATTLIST kbd %attrs;>
-
-<!ELEMENT var %Inline;> <!-- variable -->
-<!ATTLIST var %attrs;>
-
-<!ELEMENT cite %Inline;> <!-- citation -->
-<!ATTLIST cite %attrs;>
-
-<!ELEMENT abbr %Inline;> <!-- abbreviation -->
-<!ATTLIST abbr %attrs;>
-
-<!ELEMENT acronym %Inline;> <!-- acronym -->
-<!ATTLIST acronym %attrs;>
-
-<!ELEMENT q %Inline;> <!-- inlined quote -->
-<!ATTLIST q
- %attrs;
- cite %URI; #IMPLIED
- >
-
-<!ELEMENT sub %Inline;> <!-- subscript -->
-<!ATTLIST sub %attrs;>
-
-<!ELEMENT sup %Inline;> <!-- superscript -->
-<!ATTLIST sup %attrs;>
-
-<!ELEMENT tt %Inline;> <!-- fixed pitch font -->
-<!ATTLIST tt %attrs;>
-
-<!ELEMENT i %Inline;> <!-- italic font -->
-<!ATTLIST i %attrs;>
-
-<!ELEMENT b %Inline;> <!-- bold font -->
-<!ATTLIST b %attrs;>
-
-<!ELEMENT big %Inline;> <!-- bigger font -->
-<!ATTLIST big %attrs;>
-
-<!ELEMENT small %Inline;> <!-- smaller font -->
-<!ATTLIST small %attrs;>
-
-<!ELEMENT u %Inline;> <!-- underline -->
-<!ATTLIST u %attrs;>
-
-<!ELEMENT s %Inline;> <!-- strike-through -->
-<!ATTLIST s %attrs;>
-
-<!ELEMENT strike %Inline;> <!-- strike-through -->
-<!ATTLIST strike %attrs;>
-
-<!ELEMENT basefont EMPTY> <!-- base font size -->
-<!ATTLIST basefont
- id ID #IMPLIED
- size CDATA #REQUIRED
- color %Color; #IMPLIED
- face CDATA #IMPLIED
- >
-
-<!ELEMENT font %Inline;> <!-- local change to font -->
-<!ATTLIST font
- %coreattrs;
- %i18n;
- size CDATA #IMPLIED
- color %Color; #IMPLIED
- face CDATA #IMPLIED
- >
-
-<!--==================== Object ======================================-->
-<!--
- object is used to embed objects as part of HTML pages.
- param elements should precede other content. Parameters
- can also be expressed as attribute/value pairs on the
- object element itself when brevity is desired.
--->
-
-<!ELEMENT object (#PCDATA | param | %block; | form |%inline; | %misc;)*>
-<!ATTLIST object
- %attrs;
- declare (declare) #IMPLIED
- classid %URI; #IMPLIED
- codebase %URI; #IMPLIED
- data %URI; #IMPLIED
- type %ContentType; #IMPLIED
- codetype %ContentType; #IMPLIED
- archive %UriList; #IMPLIED
- standby %Text; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- usemap %URI; #IMPLIED
- name NMTOKEN #IMPLIED
- tabindex %Number; #IMPLIED
- align %ImgAlign; #IMPLIED
- border %Pixels; #IMPLIED
- hspace %Pixels; #IMPLIED
- vspace %Pixels; #IMPLIED
- >
-
-<!--
- param is used to supply a named property value.
- In XML it would seem natural to follow RDF and support an
- abbreviated syntax where the param elements are replaced
- by attribute value pairs on the object start tag.
--->
-<!ELEMENT param EMPTY>
-<!ATTLIST param
- id ID #IMPLIED
- name CDATA #REQUIRED
- value CDATA #IMPLIED
- valuetype (data|ref|object) "data"
- type %ContentType; #IMPLIED
- >
-
-<!--=================== Java applet ==================================-->
-<!--
- One of code or object attributes must be present.
- Place param elements before other content.
--->
-<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
-<!ATTLIST applet
- %coreattrs;
- codebase %URI; #IMPLIED
- archive CDATA #IMPLIED
- code CDATA #IMPLIED
- object CDATA #IMPLIED
- alt %Text; #IMPLIED
- name NMTOKEN #IMPLIED
- width %Length; #REQUIRED
- height %Length; #REQUIRED
- align %ImgAlign; #IMPLIED
- hspace %Pixels; #IMPLIED
- vspace %Pixels; #IMPLIED
- >
-
-<!--=================== Images ===========================================-->
-
-<!--
- To avoid accessibility problems for people who aren't
- able to see the image, you should provide a text
- description using the alt and longdesc attributes.
- In addition, avoid the use of server-side image maps.
--->
-
-<!ELEMENT img EMPTY>
-<!ATTLIST img
- %attrs;
- src %URI; #REQUIRED
- alt %Text; #REQUIRED
- name NMTOKEN #IMPLIED
- longdesc %URI; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- usemap %URI; #IMPLIED
- ismap (ismap) #IMPLIED
- align %ImgAlign; #IMPLIED
- border %Pixels; #IMPLIED
- hspace %Pixels; #IMPLIED
- vspace %Pixels; #IMPLIED
- >
-
-<!-- usemap points to a map element which may be in this document
- or an external document, although the latter is not widely supported -->
-
-<!--================== Client-side image maps ============================-->
-
-<!-- These can be placed in the same document or grouped in a
- separate document although this isn't yet widely supported -->
-
-<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
-<!ATTLIST map
- %i18n;
- %events;
- id ID #REQUIRED
- class CDATA #IMPLIED
- style %StyleSheet; #IMPLIED
- title %Text; #IMPLIED
- name NMTOKEN #IMPLIED
- >
-
-<!ELEMENT area EMPTY>
-<!ATTLIST area
- %attrs;
- %focus;
- shape %Shape; "rect"
- coords %Coords; #IMPLIED
- href %URI; #IMPLIED
- nohref (nohref) #IMPLIED
- alt %Text; #REQUIRED
- target %FrameTarget; #IMPLIED
- >
-
-<!--================ Forms ===============================================-->
-
-<!ELEMENT form %form.content;> <!-- forms shouldn't be nested -->
-
-<!ATTLIST form
- %attrs;
- action %URI; #REQUIRED
- method (get|post) "get"
- name NMTOKEN #IMPLIED
- enctype %ContentType; "application/x-www-form-urlencoded"
- onsubmit %Script; #IMPLIED
- onreset %Script; #IMPLIED
- accept %ContentTypes; #IMPLIED
- accept-charset %Charsets; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!--
- Each label must not contain more than ONE field
- Label elements shouldn't be nested.
--->
-<!ELEMENT label %Inline;>
-<!ATTLIST label
- %attrs;
- for IDREF #IMPLIED
- accesskey %Character; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED
- >
-
-<!ENTITY % InputType
- "(text | password | checkbox |
- radio | submit | reset |
- file | hidden | image | button)"
- >
-
-<!-- the name attribute is required for all but submit & reset -->
-
-<!ELEMENT input EMPTY> <!-- form control -->
-<!ATTLIST input
- %attrs;
- %focus;
- type %InputType; "text"
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- checked (checked) #IMPLIED
- disabled (disabled) #IMPLIED
- readonly (readonly) #IMPLIED
- size CDATA #IMPLIED
- maxlength %Number; #IMPLIED
- src %URI; #IMPLIED
- alt CDATA #IMPLIED
- usemap %URI; #IMPLIED
- onselect %Script; #IMPLIED
- onchange %Script; #IMPLIED
- accept %ContentTypes; #IMPLIED
- align %ImgAlign; #IMPLIED
- >
-
-<!ELEMENT select (optgroup|option)+> <!-- option selector -->
-<!ATTLIST select
- %attrs;
- name CDATA #IMPLIED
- size %Number; #IMPLIED
- multiple (multiple) #IMPLIED
- disabled (disabled) #IMPLIED
- tabindex %Number; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED
- onchange %Script; #IMPLIED
- >
-
-<!ELEMENT optgroup (option)+> <!-- option group -->
-<!ATTLIST optgroup
- %attrs;
- disabled (disabled) #IMPLIED
- label %Text; #REQUIRED
- >
-
-<!ELEMENT option (#PCDATA)> <!-- selectable choice -->
-<!ATTLIST option
- %attrs;
- selected (selected) #IMPLIED
- disabled (disabled) #IMPLIED
- label %Text; #IMPLIED
- value CDATA #IMPLIED
- >
-
-<!ELEMENT textarea (#PCDATA)> <!-- multi-line text field -->
-<!ATTLIST textarea
- %attrs;
- %focus;
- name CDATA #IMPLIED
- rows %Number; #REQUIRED
- cols %Number; #REQUIRED
- disabled (disabled) #IMPLIED
- readonly (readonly) #IMPLIED
- onselect %Script; #IMPLIED
- onchange %Script; #IMPLIED
- >
-
-<!--
- The fieldset element is used to group form fields.
- Only one legend element should occur in the content
- and if present should only be preceded by whitespace.
--->
-<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
-<!ATTLIST fieldset
- %attrs;
- >
-
-<!ENTITY % LAlign "(top|bottom|left|right)">
-
-<!ELEMENT legend %Inline;> <!-- fieldset label -->
-<!ATTLIST legend
- %attrs;
- accesskey %Character; #IMPLIED
- align %LAlign; #IMPLIED
- >
-
-<!--
- Content is %Flow; excluding a, form, form controls, iframe
--->
-<!ELEMENT button %button.content;> <!-- push button -->
-<!ATTLIST button
- %attrs;
- %focus;
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- type (button|submit|reset) "submit"
- disabled (disabled) #IMPLIED
- >
-
-<!-- single-line text input control (DEPRECATED) -->
-<!ELEMENT isindex EMPTY>
-<!ATTLIST isindex
- %coreattrs;
- %i18n;
- prompt %Text; #IMPLIED
- >
-
-<!--======================= Tables =======================================-->
-
-<!-- Derived from IETF HTML table standard, see [RFC1942] -->
-
-<!--
- The border attribute sets the thickness of the frame around the
- table. The default units are screen pixels.
-
- The frame attribute specifies which parts of the frame around
- the table should be rendered. The values are not the same as
- CALS to avoid a name clash with the valign attribute.
--->
-<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
-
-<!--
- The rules attribute defines which rules to draw between cells:
-
- If rules is absent then assume:
- "none" if border is absent or border="0" otherwise "all"
--->
-
-<!ENTITY % TRules "(none | groups | rows | cols | all)">
-
-<!-- horizontal placement of table relative to document -->
-<!ENTITY % TAlign "(left|center|right)">
-
-<!-- horizontal alignment attributes for cell contents
-
- char alignment char, e.g. char=":"
- charoff offset for alignment char
--->
-<!ENTITY % cellhalign
- "align (left|center|right|justify|char) #IMPLIED
- char %Character; #IMPLIED
- charoff %Length; #IMPLIED"
- >
-
-<!-- vertical alignment attributes for cell contents -->
-<!ENTITY % cellvalign
- "valign (top|middle|bottom|baseline) #IMPLIED"
- >
-
-<!ELEMENT table
- (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
-<!ELEMENT caption %Inline;>
-<!ELEMENT thead (tr)+>
-<!ELEMENT tfoot (tr)+>
-<!ELEMENT tbody (tr)+>
-<!ELEMENT colgroup (col)*>
-<!ELEMENT col EMPTY>
-<!ELEMENT tr (th|td)+>
-<!ELEMENT th %Flow;>
-<!ELEMENT td %Flow;>
-
-<!ATTLIST table
- %attrs;
- summary %Text; #IMPLIED
- width %Length; #IMPLIED
- border %Pixels; #IMPLIED
- frame %TFrame; #IMPLIED
- rules %TRules; #IMPLIED
- cellspacing %Length; #IMPLIED
- cellpadding %Length; #IMPLIED
- align %TAlign; #IMPLIED
- bgcolor %Color; #IMPLIED
- >
-
-<!ENTITY % CAlign "(top|bottom|left|right)">
-
-<!ATTLIST caption
- %attrs;
- align %CAlign; #IMPLIED
- >
-
-<!--
-colgroup groups a set of col elements. It allows you to group
-several semantically related columns together.
--->
-<!ATTLIST colgroup
- %attrs;
- span %Number; "1"
- width %MultiLength; #IMPLIED
- %cellhalign;
- %cellvalign;
- >
-
-<!--
- col elements define the alignment properties for cells in
- one or more columns.
-
- The width attribute specifies the width of the columns, e.g.
-
- width=64 width in screen pixels
- width=0.5* relative width of 0.5
-
- The span attribute causes the attributes of one
- col element to apply to more than one column.
--->
-<!ATTLIST col
- %attrs;
- span %Number; "1"
- width %MultiLength; #IMPLIED
- %cellhalign;
- %cellvalign;
- >
-
-<!--
- Use thead to duplicate headers when breaking table
- across page boundaries, or for static headers when
- tbody sections are rendered in scrolling panel.
-
- Use tfoot to duplicate footers when breaking table
- across page boundaries, or for static footers when
- tbody sections are rendered in scrolling panel.
-
- Use multiple tbody sections when rules are needed
- between groups of table rows.
--->
-<!ATTLIST thead
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tfoot
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tbody
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tr
- %attrs;
- %cellhalign;
- %cellvalign;
- bgcolor %Color; #IMPLIED
- >
-
-<!-- Scope is simpler than headers attribute for common tables -->
-<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
-
-<!-- th is for headers, td for data and for cells acting as both -->
-
-<!ATTLIST th
- %attrs;
- abbr %Text; #IMPLIED
- axis CDATA #IMPLIED
- headers IDREFS #IMPLIED
- scope %Scope; #IMPLIED
- rowspan %Number; "1"
- colspan %Number; "1"
- %cellhalign;
- %cellvalign;
- nowrap (nowrap) #IMPLIED
- bgcolor %Color; #IMPLIED
- width %Pixels; #IMPLIED
- height %Pixels; #IMPLIED
- >
-
-<!ATTLIST td
- %attrs;
- abbr %Text; #IMPLIED
- axis CDATA #IMPLIED
- headers IDREFS #IMPLIED
- scope %Scope; #IMPLIED
- rowspan %Number; "1"
- colspan %Number; "1"
- %cellhalign;
- %cellvalign;
- nowrap (nowrap) #IMPLIED
- bgcolor %Color; #IMPLIED
- width %Pixels; #IMPLIED
- height %Pixels; #IMPLIED
- >
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-strict.dtd b/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-strict.dtd
deleted file mode 100644
index 2927b9ece7..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-strict.dtd
+++ /dev/null
@@ -1,978 +0,0 @@
-<!--
- Extensible HTML version 1.0 Strict DTD
-
- This is the same as HTML 4 Strict except for
- changes due to the differences between XML and SGML.
-
- Namespace = http://www.w3.org/1999/xhtml
-
- For further information, see: http://www.w3.org/TR/xhtml1
-
- Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
- All Rights Reserved.
-
- This DTD module is identified by the PUBLIC and SYSTEM identifiers:
-
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
-
- $Revision: 1.1 $
- $Date: 2002/08/01 13:56:03 $
-
--->
-
-<!--================ Character mnemonic entities =========================-->
-
-<!ENTITY % HTMLlat1 PUBLIC
- "-//W3C//ENTITIES Latin 1 for XHTML//EN"
- "xhtml-lat1.ent">
-%HTMLlat1;
-
-<!ENTITY % HTMLsymbol PUBLIC
- "-//W3C//ENTITIES Symbols for XHTML//EN"
- "xhtml-symbol.ent">
-%HTMLsymbol;
-
-<!ENTITY % HTMLspecial PUBLIC
- "-//W3C//ENTITIES Special for XHTML//EN"
- "xhtml-special.ent">
-%HTMLspecial;
-
-<!--================== Imported Names ====================================-->
-
-<!ENTITY % ContentType "CDATA">
- <!-- media type, as per [RFC2045] -->
-
-<!ENTITY % ContentTypes "CDATA">
- <!-- comma-separated list of media types, as per [RFC2045] -->
-
-<!ENTITY % Charset "CDATA">
- <!-- a character encoding, as per [RFC2045] -->
-
-<!ENTITY % Charsets "CDATA">
- <!-- a space separated list of character encodings, as per [RFC2045] -->
-
-<!ENTITY % LanguageCode "NMTOKEN">
- <!-- a language code, as per [RFC3066] -->
-
-<!ENTITY % Character "CDATA">
- <!-- a single character, as per section 2.2 of [XML] -->
-
-<!ENTITY % Number "CDATA">
- <!-- one or more digits -->
-
-<!ENTITY % LinkTypes "CDATA">
- <!-- space-separated list of link types -->
-
-<!ENTITY % MediaDesc "CDATA">
- <!-- single or comma-separated list of media descriptors -->
-
-<!ENTITY % URI "CDATA">
- <!-- a Uniform Resource Identifier, see [RFC2396] -->
-
-<!ENTITY % UriList "CDATA">
- <!-- a space separated list of Uniform Resource Identifiers -->
-
-<!ENTITY % Datetime "CDATA">
- <!-- date and time information. ISO date format -->
-
-<!ENTITY % Script "CDATA">
- <!-- script expression -->
-
-<!ENTITY % StyleSheet "CDATA">
- <!-- style sheet data -->
-
-<!ENTITY % Text "CDATA">
- <!-- used for titles etc. -->
-
-<!ENTITY % Length "CDATA">
- <!-- nn for pixels or nn% for percentage length -->
-
-<!ENTITY % MultiLength "CDATA">
- <!-- pixel, percentage, or relative -->
-
-<!ENTITY % Pixels "CDATA">
- <!-- integer representing length in pixels -->
-
-<!-- these are used for image maps -->
-
-<!ENTITY % Shape "(rect|circle|poly|default)">
-
-<!ENTITY % Coords "CDATA">
- <!-- comma separated list of lengths -->
-
-<!--=================== Generic Attributes ===============================-->
-
-<!-- core attributes common to most elements
- id document-wide unique id
- class space separated list of classes
- style associated style info
- title advisory title/amplification
--->
-<!ENTITY % coreattrs
- "id ID #IMPLIED
- class CDATA #IMPLIED
- style %StyleSheet; #IMPLIED
- title %Text; #IMPLIED"
- >
-
-<!-- internationalization attributes
- lang language code (backwards compatible)
- xml:lang language code (as per XML 1.0 spec)
- dir direction for weak/neutral text
--->
-<!ENTITY % i18n
- "lang %LanguageCode; #IMPLIED
- xml:lang %LanguageCode; #IMPLIED
- dir (ltr|rtl) #IMPLIED"
- >
-
-<!-- attributes for common UI events
- onclick a pointer button was clicked
- ondblclick a pointer button was double clicked
- onmousedown a pointer button was pressed down
- onmouseup a pointer button was released
- onmousemove a pointer was moved onto the element
- onmouseout a pointer was moved away from the element
- onkeypress a key was pressed and released
- onkeydown a key was pressed down
- onkeyup a key was released
--->
-<!ENTITY % events
- "onclick %Script; #IMPLIED
- ondblclick %Script; #IMPLIED
- onmousedown %Script; #IMPLIED
- onmouseup %Script; #IMPLIED
- onmouseover %Script; #IMPLIED
- onmousemove %Script; #IMPLIED
- onmouseout %Script; #IMPLIED
- onkeypress %Script; #IMPLIED
- onkeydown %Script; #IMPLIED
- onkeyup %Script; #IMPLIED"
- >
-
-<!-- attributes for elements that can get the focus
- accesskey accessibility key character
- tabindex position in tabbing order
- onfocus the element got the focus
- onblur the element lost the focus
--->
-<!ENTITY % focus
- "accesskey %Character; #IMPLIED
- tabindex %Number; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED"
- >
-
-<!ENTITY % attrs "%coreattrs; %i18n; %events;">
-
-<!--=================== Text Elements ====================================-->
-
-<!ENTITY % special.pre
- "br | span | bdo | map">
-
-
-<!ENTITY % special
- "%special.pre; | object | img ">
-
-<!ENTITY % fontstyle "tt | i | b | big | small ">
-
-<!ENTITY % phrase "em | strong | dfn | code | q |
- samp | kbd | var | cite | abbr | acronym | sub | sup ">
-
-<!ENTITY % inline.forms "input | select | textarea | label | button">
-
-<!-- these can occur at block or inline level -->
-<!ENTITY % misc.inline "ins | del | script">
-
-<!-- these can only occur at block level -->
-<!ENTITY % misc "noscript | %misc.inline;">
-
-<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
-
-<!-- %Inline; covers inline or "text-level" elements -->
-<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
-
-<!--================== Block level elements ==============================-->
-
-<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
-<!ENTITY % lists "ul | ol | dl">
-<!ENTITY % blocktext "pre | hr | blockquote | address">
-
-<!ENTITY % block
- "p | %heading; | div | %lists; | %blocktext; | fieldset | table">
-
-<!ENTITY % Block "(%block; | form | %misc;)*">
-
-<!-- %Flow; mixes block and inline and is used for list items etc. -->
-<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
-
-<!--================== Content models for exclusions =====================-->
-
-<!-- a elements use %Inline; excluding a -->
-
-<!ENTITY % a.content
- "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
-
-<!-- pre uses %Inline excluding big, small, sup or sup -->
-
-<!ENTITY % pre.content
- "(#PCDATA | a | %fontstyle; | %phrase; | %special.pre; | %misc.inline;
- | %inline.forms;)*">
-
-<!-- form uses %Block; excluding form -->
-
-<!ENTITY % form.content "(%block; | %misc;)*">
-
-<!-- button uses %Flow; but excludes a, form and form controls -->
-
-<!ENTITY % button.content
- "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
- table | %special; | %fontstyle; | %phrase; | %misc;)*">
-
-<!--================ Document Structure ==================================-->
-
-<!-- the namespace URI designates the document profile -->
-
-<!ELEMENT html (head, body)>
-<!ATTLIST html
- %i18n;
- id ID #IMPLIED
- xmlns %URI; #FIXED 'http://www.w3.org/1999/xhtml'
- >
-
-<!--================ Document Head =======================================-->
-
-<!ENTITY % head.misc "(script|style|meta|link|object)*">
-
-<!-- content model is %head.misc; combined with a single
- title and an optional base element in any order -->
-
-<!ELEMENT head (%head.misc;,
- ((title, %head.misc;, (base, %head.misc;)?) |
- (base, %head.misc;, (title, %head.misc;))))>
-
-<!ATTLIST head
- %i18n;
- id ID #IMPLIED
- profile %URI; #IMPLIED
- >
-
-<!-- The title element is not considered part of the flow of text.
- It should be displayed, for example as the page header or
- window title. Exactly one title is required per document.
- -->
-<!ELEMENT title (#PCDATA)>
-<!ATTLIST title
- %i18n;
- id ID #IMPLIED
- >
-
-<!-- document base URI -->
-
-<!ELEMENT base EMPTY>
-<!ATTLIST base
- href %URI; #REQUIRED
- id ID #IMPLIED
- >
-
-<!-- generic metainformation -->
-<!ELEMENT meta EMPTY>
-<!ATTLIST meta
- %i18n;
- id ID #IMPLIED
- http-equiv CDATA #IMPLIED
- name CDATA #IMPLIED
- content CDATA #REQUIRED
- scheme CDATA #IMPLIED
- >
-
-<!--
- Relationship values can be used in principle:
-
- a) for document specific toolbars/menus when used
- with the link element in document head e.g.
- start, contents, previous, next, index, end, help
- b) to link to a separate style sheet (rel="stylesheet")
- c) to make a link to a script (rel="script")
- d) by stylesheets to control how collections of
- html nodes are rendered into printed documents
- e) to make a link to a printable version of this document
- e.g. a PostScript or PDF version (rel="alternate" media="print")
--->
-
-<!ELEMENT link EMPTY>
-<!ATTLIST link
- %attrs;
- charset %Charset; #IMPLIED
- href %URI; #IMPLIED
- hreflang %LanguageCode; #IMPLIED
- type %ContentType; #IMPLIED
- rel %LinkTypes; #IMPLIED
- rev %LinkTypes; #IMPLIED
- media %MediaDesc; #IMPLIED
- >
-
-<!-- style info, which may include CDATA sections -->
-<!ELEMENT style (#PCDATA)>
-<!ATTLIST style
- %i18n;
- id ID #IMPLIED
- type %ContentType; #REQUIRED
- media %MediaDesc; #IMPLIED
- title %Text; #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!-- script statements, which may include CDATA sections -->
-<!ELEMENT script (#PCDATA)>
-<!ATTLIST script
- id ID #IMPLIED
- charset %Charset; #IMPLIED
- type %ContentType; #REQUIRED
- src %URI; #IMPLIED
- defer (defer) #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!-- alternate content container for non script-based rendering -->
-
-<!ELEMENT noscript %Block;>
-<!ATTLIST noscript
- %attrs;
- >
-
-<!--=================== Document Body ====================================-->
-
-<!ELEMENT body %Block;>
-<!ATTLIST body
- %attrs;
- onload %Script; #IMPLIED
- onunload %Script; #IMPLIED
- >
-
-<!ELEMENT div %Flow;> <!-- generic language/style container -->
-<!ATTLIST div
- %attrs;
- >
-
-<!--=================== Paragraphs =======================================-->
-
-<!ELEMENT p %Inline;>
-<!ATTLIST p
- %attrs;
- >
-
-<!--=================== Headings =========================================-->
-
-<!--
- There are six levels of headings from h1 (the most important)
- to h6 (the least important).
--->
-
-<!ELEMENT h1 %Inline;>
-<!ATTLIST h1
- %attrs;
- >
-
-<!ELEMENT h2 %Inline;>
-<!ATTLIST h2
- %attrs;
- >
-
-<!ELEMENT h3 %Inline;>
-<!ATTLIST h3
- %attrs;
- >
-
-<!ELEMENT h4 %Inline;>
-<!ATTLIST h4
- %attrs;
- >
-
-<!ELEMENT h5 %Inline;>
-<!ATTLIST h5
- %attrs;
- >
-
-<!ELEMENT h6 %Inline;>
-<!ATTLIST h6
- %attrs;
- >
-
-<!--=================== Lists ============================================-->
-
-<!-- Unordered list -->
-
-<!ELEMENT ul (li)+>
-<!ATTLIST ul
- %attrs;
- >
-
-<!-- Ordered (numbered) list -->
-
-<!ELEMENT ol (li)+>
-<!ATTLIST ol
- %attrs;
- >
-
-<!-- list item -->
-
-<!ELEMENT li %Flow;>
-<!ATTLIST li
- %attrs;
- >
-
-<!-- definition lists - dt for term, dd for its definition -->
-
-<!ELEMENT dl (dt|dd)+>
-<!ATTLIST dl
- %attrs;
- >
-
-<!ELEMENT dt %Inline;>
-<!ATTLIST dt
- %attrs;
- >
-
-<!ELEMENT dd %Flow;>
-<!ATTLIST dd
- %attrs;
- >
-
-<!--=================== Address ==========================================-->
-
-<!-- information on author -->
-
-<!ELEMENT address %Inline;>
-<!ATTLIST address
- %attrs;
- >
-
-<!--=================== Horizontal Rule ==================================-->
-
-<!ELEMENT hr EMPTY>
-<!ATTLIST hr
- %attrs;
- >
-
-<!--=================== Preformatted Text ================================-->
-
-<!-- content is %Inline; excluding "img|object|big|small|sub|sup" -->
-
-<!ELEMENT pre %pre.content;>
-<!ATTLIST pre
- %attrs;
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!--=================== Block-like Quotes ================================-->
-
-<!ELEMENT blockquote %Block;>
-<!ATTLIST blockquote
- %attrs;
- cite %URI; #IMPLIED
- >
-
-<!--=================== Inserted/Deleted Text ============================-->
-
-<!--
- ins/del are allowed in block and inline content, but its
- inappropriate to include block content within an ins element
- occurring in inline content.
--->
-<!ELEMENT ins %Flow;>
-<!ATTLIST ins
- %attrs;
- cite %URI; #IMPLIED
- datetime %Datetime; #IMPLIED
- >
-
-<!ELEMENT del %Flow;>
-<!ATTLIST del
- %attrs;
- cite %URI; #IMPLIED
- datetime %Datetime; #IMPLIED
- >
-
-<!--================== The Anchor Element ================================-->
-
-<!-- content is %Inline; except that anchors shouldn't be nested -->
-
-<!ELEMENT a %a.content;>
-<!ATTLIST a
- %attrs;
- %focus;
- charset %Charset; #IMPLIED
- type %ContentType; #IMPLIED
- name NMTOKEN #IMPLIED
- href %URI; #IMPLIED
- hreflang %LanguageCode; #IMPLIED
- rel %LinkTypes; #IMPLIED
- rev %LinkTypes; #IMPLIED
- shape %Shape; "rect"
- coords %Coords; #IMPLIED
- >
-
-<!--===================== Inline Elements ================================-->
-
-<!ELEMENT span %Inline;> <!-- generic language/style container -->
-<!ATTLIST span
- %attrs;
- >
-
-<!ELEMENT bdo %Inline;> <!-- I18N BiDi over-ride -->
-<!ATTLIST bdo
- %coreattrs;
- %events;
- lang %LanguageCode; #IMPLIED
- xml:lang %LanguageCode; #IMPLIED
- dir (ltr|rtl) #REQUIRED
- >
-
-<!ELEMENT br EMPTY> <!-- forced line break -->
-<!ATTLIST br
- %coreattrs;
- >
-
-<!ELEMENT em %Inline;> <!-- emphasis -->
-<!ATTLIST em %attrs;>
-
-<!ELEMENT strong %Inline;> <!-- strong emphasis -->
-<!ATTLIST strong %attrs;>
-
-<!ELEMENT dfn %Inline;> <!-- definitional -->
-<!ATTLIST dfn %attrs;>
-
-<!ELEMENT code %Inline;> <!-- program code -->
-<!ATTLIST code %attrs;>
-
-<!ELEMENT samp %Inline;> <!-- sample -->
-<!ATTLIST samp %attrs;>
-
-<!ELEMENT kbd %Inline;> <!-- something user would type -->
-<!ATTLIST kbd %attrs;>
-
-<!ELEMENT var %Inline;> <!-- variable -->
-<!ATTLIST var %attrs;>
-
-<!ELEMENT cite %Inline;> <!-- citation -->
-<!ATTLIST cite %attrs;>
-
-<!ELEMENT abbr %Inline;> <!-- abbreviation -->
-<!ATTLIST abbr %attrs;>
-
-<!ELEMENT acronym %Inline;> <!-- acronym -->
-<!ATTLIST acronym %attrs;>
-
-<!ELEMENT q %Inline;> <!-- inlined quote -->
-<!ATTLIST q
- %attrs;
- cite %URI; #IMPLIED
- >
-
-<!ELEMENT sub %Inline;> <!-- subscript -->
-<!ATTLIST sub %attrs;>
-
-<!ELEMENT sup %Inline;> <!-- superscript -->
-<!ATTLIST sup %attrs;>
-
-<!ELEMENT tt %Inline;> <!-- fixed pitch font -->
-<!ATTLIST tt %attrs;>
-
-<!ELEMENT i %Inline;> <!-- italic font -->
-<!ATTLIST i %attrs;>
-
-<!ELEMENT b %Inline;> <!-- bold font -->
-<!ATTLIST b %attrs;>
-
-<!ELEMENT big %Inline;> <!-- bigger font -->
-<!ATTLIST big %attrs;>
-
-<!ELEMENT small %Inline;> <!-- smaller font -->
-<!ATTLIST small %attrs;>
-
-<!--==================== Object ======================================-->
-<!--
- object is used to embed objects as part of HTML pages.
- param elements should precede other content. Parameters
- can also be expressed as attribute/value pairs on the
- object element itself when brevity is desired.
--->
-
-<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
-<!ATTLIST object
- %attrs;
- declare (declare) #IMPLIED
- classid %URI; #IMPLIED
- codebase %URI; #IMPLIED
- data %URI; #IMPLIED
- type %ContentType; #IMPLIED
- codetype %ContentType; #IMPLIED
- archive %UriList; #IMPLIED
- standby %Text; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- usemap %URI; #IMPLIED
- name NMTOKEN #IMPLIED
- tabindex %Number; #IMPLIED
- >
-
-<!--
- param is used to supply a named property value.
- In XML it would seem natural to follow RDF and support an
- abbreviated syntax where the param elements are replaced
- by attribute value pairs on the object start tag.
--->
-<!ELEMENT param EMPTY>
-<!ATTLIST param
- id ID #IMPLIED
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- valuetype (data|ref|object) "data"
- type %ContentType; #IMPLIED
- >
-
-<!--=================== Images ===========================================-->
-
-<!--
- To avoid accessibility problems for people who aren't
- able to see the image, you should provide a text
- description using the alt and longdesc attributes.
- In addition, avoid the use of server-side image maps.
- Note that in this DTD there is no name attribute. That
- is only available in the transitional and frameset DTD.
--->
-
-<!ELEMENT img EMPTY>
-<!ATTLIST img
- %attrs;
- src %URI; #REQUIRED
- alt %Text; #REQUIRED
- longdesc %URI; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- usemap %URI; #IMPLIED
- ismap (ismap) #IMPLIED
- >
-
-<!-- usemap points to a map element which may be in this document
- or an external document, although the latter is not widely supported -->
-
-<!--================== Client-side image maps ============================-->
-
-<!-- These can be placed in the same document or grouped in a
- separate document although this isn't yet widely supported -->
-
-<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
-<!ATTLIST map
- %i18n;
- %events;
- id ID #REQUIRED
- class CDATA #IMPLIED
- style %StyleSheet; #IMPLIED
- title %Text; #IMPLIED
- name NMTOKEN #IMPLIED
- >
-
-<!ELEMENT area EMPTY>
-<!ATTLIST area
- %attrs;
- %focus;
- shape %Shape; "rect"
- coords %Coords; #IMPLIED
- href %URI; #IMPLIED
- nohref (nohref) #IMPLIED
- alt %Text; #REQUIRED
- >
-
-<!--================ Forms ===============================================-->
-<!ELEMENT form %form.content;> <!-- forms shouldn't be nested -->
-
-<!ATTLIST form
- %attrs;
- action %URI; #REQUIRED
- method (get|post) "get"
- enctype %ContentType; "application/x-www-form-urlencoded"
- onsubmit %Script; #IMPLIED
- onreset %Script; #IMPLIED
- accept %ContentTypes; #IMPLIED
- accept-charset %Charsets; #IMPLIED
- >
-
-<!--
- Each label must not contain more than ONE field
- Label elements shouldn't be nested.
--->
-<!ELEMENT label %Inline;>
-<!ATTLIST label
- %attrs;
- for IDREF #IMPLIED
- accesskey %Character; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED
- >
-
-<!ENTITY % InputType
- "(text | password | checkbox |
- radio | submit | reset |
- file | hidden | image | button)"
- >
-
-<!-- the name attribute is required for all but submit & reset -->
-
-<!ELEMENT input EMPTY> <!-- form control -->
-<!ATTLIST input
- %attrs;
- %focus;
- type %InputType; "text"
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- checked (checked) #IMPLIED
- disabled (disabled) #IMPLIED
- readonly (readonly) #IMPLIED
- size CDATA #IMPLIED
- maxlength %Number; #IMPLIED
- src %URI; #IMPLIED
- alt CDATA #IMPLIED
- usemap %URI; #IMPLIED
- onselect %Script; #IMPLIED
- onchange %Script; #IMPLIED
- accept %ContentTypes; #IMPLIED
- >
-
-<!ELEMENT select (optgroup|option)+> <!-- option selector -->
-<!ATTLIST select
- %attrs;
- name CDATA #IMPLIED
- size %Number; #IMPLIED
- multiple (multiple) #IMPLIED
- disabled (disabled) #IMPLIED
- tabindex %Number; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED
- onchange %Script; #IMPLIED
- >
-
-<!ELEMENT optgroup (option)+> <!-- option group -->
-<!ATTLIST optgroup
- %attrs;
- disabled (disabled) #IMPLIED
- label %Text; #REQUIRED
- >
-
-<!ELEMENT option (#PCDATA)> <!-- selectable choice -->
-<!ATTLIST option
- %attrs;
- selected (selected) #IMPLIED
- disabled (disabled) #IMPLIED
- label %Text; #IMPLIED
- value CDATA #IMPLIED
- >
-
-<!ELEMENT textarea (#PCDATA)> <!-- multi-line text field -->
-<!ATTLIST textarea
- %attrs;
- %focus;
- name CDATA #IMPLIED
- rows %Number; #REQUIRED
- cols %Number; #REQUIRED
- disabled (disabled) #IMPLIED
- readonly (readonly) #IMPLIED
- onselect %Script; #IMPLIED
- onchange %Script; #IMPLIED
- >
-
-<!--
- The fieldset element is used to group form fields.
- Only one legend element should occur in the content
- and if present should only be preceded by whitespace.
--->
-<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
-<!ATTLIST fieldset
- %attrs;
- >
-
-<!ELEMENT legend %Inline;> <!-- fieldset label -->
-<!ATTLIST legend
- %attrs;
- accesskey %Character; #IMPLIED
- >
-
-<!--
- Content is %Flow; excluding a, form and form controls
--->
-<!ELEMENT button %button.content;> <!-- push button -->
-<!ATTLIST button
- %attrs;
- %focus;
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- type (button|submit|reset) "submit"
- disabled (disabled) #IMPLIED
- >
-
-<!--======================= Tables =======================================-->
-
-<!-- Derived from IETF HTML table standard, see [RFC1942] -->
-
-<!--
- The border attribute sets the thickness of the frame around the
- table. The default units are screen pixels.
-
- The frame attribute specifies which parts of the frame around
- the table should be rendered. The values are not the same as
- CALS to avoid a name clash with the valign attribute.
--->
-<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
-
-<!--
- The rules attribute defines which rules to draw between cells:
-
- If rules is absent then assume:
- "none" if border is absent or border="0" otherwise "all"
--->
-
-<!ENTITY % TRules "(none | groups | rows | cols | all)">
-
-<!-- horizontal alignment attributes for cell contents
-
- char alignment char, e.g. char=':'
- charoff offset for alignment char
--->
-<!ENTITY % cellhalign
- "align (left|center|right|justify|char) #IMPLIED
- char %Character; #IMPLIED
- charoff %Length; #IMPLIED"
- >
-
-<!-- vertical alignment attributes for cell contents -->
-<!ENTITY % cellvalign
- "valign (top|middle|bottom|baseline) #IMPLIED"
- >
-
-<!ELEMENT table
- (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
-<!ELEMENT caption %Inline;>
-<!ELEMENT thead (tr)+>
-<!ELEMENT tfoot (tr)+>
-<!ELEMENT tbody (tr)+>
-<!ELEMENT colgroup (col)*>
-<!ELEMENT col EMPTY>
-<!ELEMENT tr (th|td)+>
-<!ELEMENT th %Flow;>
-<!ELEMENT td %Flow;>
-
-<!ATTLIST table
- %attrs;
- summary %Text; #IMPLIED
- width %Length; #IMPLIED
- border %Pixels; #IMPLIED
- frame %TFrame; #IMPLIED
- rules %TRules; #IMPLIED
- cellspacing %Length; #IMPLIED
- cellpadding %Length; #IMPLIED
- >
-
-<!ATTLIST caption
- %attrs;
- >
-
-<!--
-colgroup groups a set of col elements. It allows you to group
-several semantically related columns together.
--->
-<!ATTLIST colgroup
- %attrs;
- span %Number; "1"
- width %MultiLength; #IMPLIED
- %cellhalign;
- %cellvalign;
- >
-
-<!--
- col elements define the alignment properties for cells in
- one or more columns.
-
- The width attribute specifies the width of the columns, e.g.
-
- width=64 width in screen pixels
- width=0.5* relative width of 0.5
-
- The span attribute causes the attributes of one
- col element to apply to more than one column.
--->
-<!ATTLIST col
- %attrs;
- span %Number; "1"
- width %MultiLength; #IMPLIED
- %cellhalign;
- %cellvalign;
- >
-
-<!--
- Use thead to duplicate headers when breaking table
- across page boundaries, or for static headers when
- tbody sections are rendered in scrolling panel.
-
- Use tfoot to duplicate footers when breaking table
- across page boundaries, or for static footers when
- tbody sections are rendered in scrolling panel.
-
- Use multiple tbody sections when rules are needed
- between groups of table rows.
--->
-<!ATTLIST thead
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tfoot
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tbody
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tr
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-
-<!-- Scope is simpler than headers attribute for common tables -->
-<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
-
-<!-- th is for headers, td for data and for cells acting as both -->
-
-<!ATTLIST th
- %attrs;
- abbr %Text; #IMPLIED
- axis CDATA #IMPLIED
- headers IDREFS #IMPLIED
- scope %Scope; #IMPLIED
- rowspan %Number; "1"
- colspan %Number; "1"
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST td
- %attrs;
- abbr %Text; #IMPLIED
- axis CDATA #IMPLIED
- headers IDREFS #IMPLIED
- scope %Scope; #IMPLIED
- rowspan %Number; "1"
- colspan %Number; "1"
- %cellhalign;
- %cellvalign;
- >
-
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-transitional.dtd b/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-transitional.dtd
deleted file mode 100644
index 628f27ac50..0000000000
--- a/lib/erl_docgen/priv/docbuilder_dtd/xhtml1-transitional.dtd
+++ /dev/null
@@ -1,1201 +0,0 @@
-<!--
- Extensible HTML version 1.0 Transitional DTD
-
- This is the same as HTML 4 Transitional except for
- changes due to the differences between XML and SGML.
-
- Namespace = http://www.w3.org/1999/xhtml
-
- For further information, see: http://www.w3.org/TR/xhtml1
-
- Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
- All Rights Reserved.
-
- This DTD module is identified by the PUBLIC and SYSTEM identifiers:
-
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
-
- $Revision: 1.2 $
- $Date: 2002/08/01 18:37:55 $
-
--->
-
-<!--================ Character mnemonic entities =========================-->
-
-<!ENTITY % HTMLlat1 PUBLIC
- "-//W3C//ENTITIES Latin 1 for XHTML//EN"
- "xhtml-lat1.ent">
-%HTMLlat1;
-
-<!ENTITY % HTMLsymbol PUBLIC
- "-//W3C//ENTITIES Symbols for XHTML//EN"
- "xhtml-symbol.ent">
-%HTMLsymbol;
-
-<!ENTITY % HTMLspecial PUBLIC
- "-//W3C//ENTITIES Special for XHTML//EN"
- "xhtml-special.ent">
-%HTMLspecial;
-
-<!--================== Imported Names ====================================-->
-
-<!ENTITY % ContentType "CDATA">
- <!-- media type, as per [RFC2045] -->
-
-<!ENTITY % ContentTypes "CDATA">
- <!-- comma-separated list of media types, as per [RFC2045] -->
-
-<!ENTITY % Charset "CDATA">
- <!-- a character encoding, as per [RFC2045] -->
-
-<!ENTITY % Charsets "CDATA">
- <!-- a space separated list of character encodings, as per [RFC2045] -->
-
-<!ENTITY % LanguageCode "NMTOKEN">
- <!-- a language code, as per [RFC3066] -->
-
-<!ENTITY % Character "CDATA">
- <!-- a single character, as per section 2.2 of [XML] -->
-
-<!ENTITY % Number "CDATA">
- <!-- one or more digits -->
-
-<!ENTITY % LinkTypes "CDATA">
- <!-- space-separated list of link types -->
-
-<!ENTITY % MediaDesc "CDATA">
- <!-- single or comma-separated list of media descriptors -->
-
-<!ENTITY % URI "CDATA">
- <!-- a Uniform Resource Identifier, see [RFC2396] -->
-
-<!ENTITY % UriList "CDATA">
- <!-- a space separated list of Uniform Resource Identifiers -->
-
-<!ENTITY % Datetime "CDATA">
- <!-- date and time information. ISO date format -->
-
-<!ENTITY % Script "CDATA">
- <!-- script expression -->
-
-<!ENTITY % StyleSheet "CDATA">
- <!-- style sheet data -->
-
-<!ENTITY % Text "CDATA">
- <!-- used for titles etc. -->
-
-<!ENTITY % FrameTarget "NMTOKEN">
- <!-- render in this frame -->
-
-<!ENTITY % Length "CDATA">
- <!-- nn for pixels or nn% for percentage length -->
-
-<!ENTITY % MultiLength "CDATA">
- <!-- pixel, percentage, or relative -->
-
-<!ENTITY % Pixels "CDATA">
- <!-- integer representing length in pixels -->
-
-<!-- these are used for image maps -->
-
-<!ENTITY % Shape "(rect|circle|poly|default)">
-
-<!ENTITY % Coords "CDATA">
- <!-- comma separated list of lengths -->
-
-<!-- used for object, applet, img, input and iframe -->
-<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
-
-<!-- a color using sRGB: #RRGGBB as Hex values -->
-<!ENTITY % Color "CDATA">
-
-<!-- There are also 16 widely known color names with their sRGB values:
-
- Black = #000000 Green = #008000
- Silver = #C0C0C0 Lime = #00FF00
- Gray = #808080 Olive = #808000
- White = #FFFFFF Yellow = #FFFF00
- Maroon = #800000 Navy = #000080
- Red = #FF0000 Blue = #0000FF
- Purple = #800080 Teal = #008080
- Fuchsia= #FF00FF Aqua = #00FFFF
--->
-
-<!--=================== Generic Attributes ===============================-->
-
-<!-- core attributes common to most elements
- id document-wide unique id
- class space separated list of classes
- style associated style info
- title advisory title/amplification
--->
-<!ENTITY % coreattrs
- "id ID #IMPLIED
- class CDATA #IMPLIED
- style %StyleSheet; #IMPLIED
- title %Text; #IMPLIED"
- >
-
-<!-- internationalization attributes
- lang language code (backwards compatible)
- xml:lang language code (as per XML 1.0 spec)
- dir direction for weak/neutral text
--->
-<!ENTITY % i18n
- "lang %LanguageCode; #IMPLIED
- xml:lang %LanguageCode; #IMPLIED
- dir (ltr|rtl) #IMPLIED"
- >
-
-<!-- attributes for common UI events
- onclick a pointer button was clicked
- ondblclick a pointer button was double clicked
- onmousedown a pointer button was pressed down
- onmouseup a pointer button was released
- onmousemove a pointer was moved onto the element
- onmouseout a pointer was moved away from the element
- onkeypress a key was pressed and released
- onkeydown a key was pressed down
- onkeyup a key was released
--->
-<!ENTITY % events
- "onclick %Script; #IMPLIED
- ondblclick %Script; #IMPLIED
- onmousedown %Script; #IMPLIED
- onmouseup %Script; #IMPLIED
- onmouseover %Script; #IMPLIED
- onmousemove %Script; #IMPLIED
- onmouseout %Script; #IMPLIED
- onkeypress %Script; #IMPLIED
- onkeydown %Script; #IMPLIED
- onkeyup %Script; #IMPLIED"
- >
-
-<!-- attributes for elements that can get the focus
- accesskey accessibility key character
- tabindex position in tabbing order
- onfocus the element got the focus
- onblur the element lost the focus
--->
-<!ENTITY % focus
- "accesskey %Character; #IMPLIED
- tabindex %Number; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED"
- >
-
-<!ENTITY % attrs "%coreattrs; %i18n; %events;">
-
-<!-- text alignment for p, div, h1-h6. The default is
- align="left" for ltr headings, "right" for rtl -->
-
-<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
-
-<!--=================== Text Elements ====================================-->
-
-<!ENTITY % special.extra
- "object | applet | img | map | iframe">
-
-<!ENTITY % special.basic
- "br | span | bdo">
-
-<!ENTITY % special
- "%special.basic; | %special.extra;">
-
-<!ENTITY % fontstyle.extra "big | small | font | basefont">
-
-<!ENTITY % fontstyle.basic "tt | i | b | u
- | s | strike ">
-
-<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
-
-<!ENTITY % phrase.extra "sub | sup">
-<!ENTITY % phrase.basic "em | strong | dfn | code | q |
- samp | kbd | var | cite | abbr | acronym">
-
-<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
-
-<!ENTITY % inline.forms "input | select | textarea | label | button">
-
-<!-- these can occur at block or inline level -->
-<!ENTITY % misc.inline "ins | del | script">
-
-<!-- these can only occur at block level -->
-<!ENTITY % misc "noscript | %misc.inline;">
-
-<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
-
-<!-- %Inline; covers inline or "text-level" elements -->
-<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
-
-<!--================== Block level elements ==============================-->
-
-<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
-<!ENTITY % lists "ul | ol | dl | menu | dir">
-<!ENTITY % blocktext "pre | hr | blockquote | address | center | noframes">
-
-<!ENTITY % block
- "p | %heading; | div | %lists; | %blocktext; | isindex |fieldset | table">
-
-<!-- %Flow; mixes block and inline and is used for list items etc. -->
-<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
-
-<!--================== Content models for exclusions =====================-->
-
-<!-- a elements use %Inline; excluding a -->
-
-<!ENTITY % a.content
- "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
-
-<!-- pre uses %Inline excluding img, object, applet, big, small,
- font, or basefont -->
-
-<!ENTITY % pre.content
- "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
- %inline.forms; | %misc.inline;)*">
-
-<!-- form uses %Flow; excluding form -->
-
-<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
-
-<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
-
-<!ENTITY % button.content
- "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
- table | br | span | bdo | object | applet | img | map |
- %fontstyle; | %phrase; | %misc;)*">
-
-<!--================ Document Structure ==================================-->
-
-<!-- the namespace URI designates the document profile -->
-
-<!ELEMENT html (head, body)>
-<!ATTLIST html
- %i18n;
- id ID #IMPLIED
- xmlns %URI; #FIXED 'http://www.w3.org/1999/xhtml'
- >
-
-<!--================ Document Head =======================================-->
-
-<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
-
-<!-- content model is %head.misc; combined with a single
- title and an optional base element in any order -->
-
-<!ELEMENT head (%head.misc;,
- ((title, %head.misc;, (base, %head.misc;)?) |
- (base, %head.misc;, (title, %head.misc;))))>
-
-<!ATTLIST head
- %i18n;
- id ID #IMPLIED
- profile %URI; #IMPLIED
- >
-
-<!-- The title element is not considered part of the flow of text.
- It should be displayed, for example as the page header or
- window title. Exactly one title is required per document.
- -->
-<!ELEMENT title (#PCDATA)>
-<!ATTLIST title
- %i18n;
- id ID #IMPLIED
- >
-
-<!-- document base URI -->
-
-<!ELEMENT base EMPTY>
-<!ATTLIST base
- id ID #IMPLIED
- href %URI; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!-- generic metainformation -->
-<!ELEMENT meta EMPTY>
-<!ATTLIST meta
- %i18n;
- id ID #IMPLIED
- http-equiv CDATA #IMPLIED
- name CDATA #IMPLIED
- content CDATA #REQUIRED
- scheme CDATA #IMPLIED
- >
-
-<!--
- Relationship values can be used in principle:
-
- a) for document specific toolbars/menus when used
- with the link element in document head e.g.
- start, contents, previous, next, index, end, help
- b) to link to a separate style sheet (rel="stylesheet")
- c) to make a link to a script (rel="script")
- d) by stylesheets to control how collections of
- html nodes are rendered into printed documents
- e) to make a link to a printable version of this document
- e.g. a PostScript or PDF version (rel="alternate" media="print")
--->
-
-<!ELEMENT link EMPTY>
-<!ATTLIST link
- %attrs;
- charset %Charset; #IMPLIED
- href %URI; #IMPLIED
- hreflang %LanguageCode; #IMPLIED
- type %ContentType; #IMPLIED
- rel %LinkTypes; #IMPLIED
- rev %LinkTypes; #IMPLIED
- media %MediaDesc; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!-- style info, which may include CDATA sections -->
-<!ELEMENT style (#PCDATA)>
-<!ATTLIST style
- %i18n;
- id ID #IMPLIED
- type %ContentType; #REQUIRED
- media %MediaDesc; #IMPLIED
- title %Text; #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!-- script statements, which may include CDATA sections -->
-<!ELEMENT script (#PCDATA)>
-<!ATTLIST script
- id ID #IMPLIED
- charset %Charset; #IMPLIED
- type %ContentType; #REQUIRED
- language CDATA #IMPLIED
- src %URI; #IMPLIED
- defer (defer) #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!-- alternate content container for non script-based rendering -->
-
-<!ELEMENT noscript %Flow;>
-<!ATTLIST noscript
- %attrs;
- >
-
-<!--======================= Frames =======================================-->
-
-<!-- inline subwindow -->
-
-<!ELEMENT iframe %Flow;>
-<!ATTLIST iframe
- %coreattrs;
- longdesc %URI; #IMPLIED
- name NMTOKEN #IMPLIED
- src %URI; #IMPLIED
- frameborder (1|0) "1"
- marginwidth %Pixels; #IMPLIED
- marginheight %Pixels; #IMPLIED
- scrolling (yes|no|auto) "auto"
- align %ImgAlign; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- >
-
-<!-- alternate content container for non frame-based rendering -->
-
-<!ELEMENT noframes %Flow;>
-<!ATTLIST noframes
- %attrs;
- >
-
-<!--=================== Document Body ====================================-->
-
-<!ELEMENT body %Flow;>
-<!ATTLIST body
- %attrs;
- onload %Script; #IMPLIED
- onunload %Script; #IMPLIED
- background %URI; #IMPLIED
- bgcolor %Color; #IMPLIED
- text %Color; #IMPLIED
- link %Color; #IMPLIED
- vlink %Color; #IMPLIED
- alink %Color; #IMPLIED
- >
-
-<!ELEMENT div %Flow;> <!-- generic language/style container -->
-<!ATTLIST div
- %attrs;
- %TextAlign;
- >
-
-<!--=================== Paragraphs =======================================-->
-
-<!ELEMENT p %Inline;>
-<!ATTLIST p
- %attrs;
- %TextAlign;
- >
-
-<!--=================== Headings =========================================-->
-
-<!--
- There are six levels of headings from h1 (the most important)
- to h6 (the least important).
--->
-
-<!ELEMENT h1 %Inline;>
-<!ATTLIST h1
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h2 %Inline;>
-<!ATTLIST h2
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h3 %Inline;>
-<!ATTLIST h3
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h4 %Inline;>
-<!ATTLIST h4
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h5 %Inline;>
-<!ATTLIST h5
- %attrs;
- %TextAlign;
- >
-
-<!ELEMENT h6 %Inline;>
-<!ATTLIST h6
- %attrs;
- %TextAlign;
- >
-
-<!--=================== Lists ============================================-->
-
-<!-- Unordered list bullet styles -->
-
-<!ENTITY % ULStyle "(disc|square|circle)">
-
-<!-- Unordered list -->
-
-<!ELEMENT ul (li)+>
-<!ATTLIST ul
- %attrs;
- type %ULStyle; #IMPLIED
- compact (compact) #IMPLIED
- >
-
-<!-- Ordered list numbering style
-
- 1 arabic numbers 1, 2, 3, ...
- a lower alpha a, b, c, ...
- A upper alpha A, B, C, ...
- i lower roman i, ii, iii, ...
- I upper roman I, II, III, ...
-
- The style is applied to the sequence number which by default
- is reset to 1 for the first list item in an ordered list.
--->
-<!ENTITY % OLStyle "CDATA">
-
-<!-- Ordered (numbered) list -->
-
-<!ELEMENT ol (li)+>
-<!ATTLIST ol
- %attrs;
- type %OLStyle; #IMPLIED
- compact (compact) #IMPLIED
- start %Number; #IMPLIED
- >
-
-<!-- single column list (DEPRECATED) -->
-<!ELEMENT menu (li)+>
-<!ATTLIST menu
- %attrs;
- compact (compact) #IMPLIED
- >
-
-<!-- multiple column list (DEPRECATED) -->
-<!ELEMENT dir (li)+>
-<!ATTLIST dir
- %attrs;
- compact (compact) #IMPLIED
- >
-
-<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
-<!ENTITY % LIStyle "CDATA">
-
-<!-- list item -->
-
-<!ELEMENT li %Flow;>
-<!ATTLIST li
- %attrs;
- type %LIStyle; #IMPLIED
- value %Number; #IMPLIED
- >
-
-<!-- definition lists - dt for term, dd for its definition -->
-
-<!ELEMENT dl (dt|dd)+>
-<!ATTLIST dl
- %attrs;
- compact (compact) #IMPLIED
- >
-
-<!ELEMENT dt %Inline;>
-<!ATTLIST dt
- %attrs;
- >
-
-<!ELEMENT dd %Flow;>
-<!ATTLIST dd
- %attrs;
- >
-
-<!--=================== Address ==========================================-->
-
-<!-- information on author -->
-
-<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
-<!ATTLIST address
- %attrs;
- >
-
-<!--=================== Horizontal Rule ==================================-->
-
-<!ELEMENT hr EMPTY>
-<!ATTLIST hr
- %attrs;
- align (left|center|right) #IMPLIED
- noshade (noshade) #IMPLIED
- size %Pixels; #IMPLIED
- width %Length; #IMPLIED
- >
-
-<!--=================== Preformatted Text ================================-->
-
-<!-- content is %Inline; excluding
- "img|object|applet|big|small|sub|sup|font|basefont" -->
-
-<!ELEMENT pre %pre.content;>
-<!ATTLIST pre
- %attrs;
- width %Number; #IMPLIED
- xml:space (preserve) #FIXED 'preserve'
- >
-
-<!--=================== Block-like Quotes ================================-->
-
-<!ELEMENT blockquote %Flow;>
-<!ATTLIST blockquote
- %attrs;
- cite %URI; #IMPLIED
- >
-
-<!--=================== Text alignment ===================================-->
-
-<!-- center content -->
-<!ELEMENT center %Flow;>
-<!ATTLIST center
- %attrs;
- >
-
-<!--=================== Inserted/Deleted Text ============================-->
-
-<!--
- ins/del are allowed in block and inline content, but its
- inappropriate to include block content within an ins element
- occurring in inline content.
--->
-<!ELEMENT ins %Flow;>
-<!ATTLIST ins
- %attrs;
- cite %URI; #IMPLIED
- datetime %Datetime; #IMPLIED
- >
-
-<!ELEMENT del %Flow;>
-<!ATTLIST del
- %attrs;
- cite %URI; #IMPLIED
- datetime %Datetime; #IMPLIED
- >
-
-<!--================== The Anchor Element ================================-->
-
-<!-- content is %Inline; except that anchors shouldn't be nested -->
-
-<!ELEMENT a %a.content;>
-<!ATTLIST a
- %attrs;
- %focus;
- charset %Charset; #IMPLIED
- type %ContentType; #IMPLIED
- name NMTOKEN #IMPLIED
- href %URI; #IMPLIED
- hreflang %LanguageCode; #IMPLIED
- rel %LinkTypes; #IMPLIED
- rev %LinkTypes; #IMPLIED
- shape %Shape; "rect"
- coords %Coords; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!--===================== Inline Elements ================================-->
-
-<!ELEMENT span %Inline;> <!-- generic language/style container -->
-<!ATTLIST span
- %attrs;
- >
-
-<!ELEMENT bdo %Inline;> <!-- I18N BiDi over-ride -->
-<!ATTLIST bdo
- %coreattrs;
- %events;
- lang %LanguageCode; #IMPLIED
- xml:lang %LanguageCode; #IMPLIED
- dir (ltr|rtl) #REQUIRED
- >
-
-<!ELEMENT br EMPTY> <!-- forced line break -->
-<!ATTLIST br
- %coreattrs;
- clear (left|all|right|none) "none"
- >
-
-<!ELEMENT em %Inline;> <!-- emphasis -->
-<!ATTLIST em %attrs;>
-
-<!ELEMENT strong %Inline;> <!-- strong emphasis -->
-<!ATTLIST strong %attrs;>
-
-<!ELEMENT dfn %Inline;> <!-- definitional -->
-<!ATTLIST dfn %attrs;>
-
-<!ELEMENT code %Inline;> <!-- program code -->
-<!ATTLIST code %attrs;>
-
-<!ELEMENT samp %Inline;> <!-- sample -->
-<!ATTLIST samp %attrs;>
-
-<!ELEMENT kbd %Inline;> <!-- something user would type -->
-<!ATTLIST kbd %attrs;>
-
-<!ELEMENT var %Inline;> <!-- variable -->
-<!ATTLIST var %attrs;>
-
-<!ELEMENT cite %Inline;> <!-- citation -->
-<!ATTLIST cite %attrs;>
-
-<!ELEMENT abbr %Inline;> <!-- abbreviation -->
-<!ATTLIST abbr %attrs;>
-
-<!ELEMENT acronym %Inline;> <!-- acronym -->
-<!ATTLIST acronym %attrs;>
-
-<!ELEMENT q %Inline;> <!-- inlined quote -->
-<!ATTLIST q
- %attrs;
- cite %URI; #IMPLIED
- >
-
-<!ELEMENT sub %Inline;> <!-- subscript -->
-<!ATTLIST sub %attrs;>
-
-<!ELEMENT sup %Inline;> <!-- superscript -->
-<!ATTLIST sup %attrs;>
-
-<!ELEMENT tt %Inline;> <!-- fixed pitch font -->
-<!ATTLIST tt %attrs;>
-
-<!ELEMENT i %Inline;> <!-- italic font -->
-<!ATTLIST i %attrs;>
-
-<!ELEMENT b %Inline;> <!-- bold font -->
-<!ATTLIST b %attrs;>
-
-<!ELEMENT big %Inline;> <!-- bigger font -->
-<!ATTLIST big %attrs;>
-
-<!ELEMENT small %Inline;> <!-- smaller font -->
-<!ATTLIST small %attrs;>
-
-<!ELEMENT u %Inline;> <!-- underline -->
-<!ATTLIST u %attrs;>
-
-<!ELEMENT s %Inline;> <!-- strike-through -->
-<!ATTLIST s %attrs;>
-
-<!ELEMENT strike %Inline;> <!-- strike-through -->
-<!ATTLIST strike %attrs;>
-
-<!ELEMENT basefont EMPTY> <!-- base font size -->
-<!ATTLIST basefont
- id ID #IMPLIED
- size CDATA #REQUIRED
- color %Color; #IMPLIED
- face CDATA #IMPLIED
- >
-
-<!ELEMENT font %Inline;> <!-- local change to font -->
-<!ATTLIST font
- %coreattrs;
- %i18n;
- size CDATA #IMPLIED
- color %Color; #IMPLIED
- face CDATA #IMPLIED
- >
-
-<!--==================== Object ======================================-->
-<!--
- object is used to embed objects as part of HTML pages.
- param elements should precede other content. Parameters
- can also be expressed as attribute/value pairs on the
- object element itself when brevity is desired.
--->
-
-<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
-<!ATTLIST object
- %attrs;
- declare (declare) #IMPLIED
- classid %URI; #IMPLIED
- codebase %URI; #IMPLIED
- data %URI; #IMPLIED
- type %ContentType; #IMPLIED
- codetype %ContentType; #IMPLIED
- archive %UriList; #IMPLIED
- standby %Text; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- usemap %URI; #IMPLIED
- name NMTOKEN #IMPLIED
- tabindex %Number; #IMPLIED
- align %ImgAlign; #IMPLIED
- border %Pixels; #IMPLIED
- hspace %Pixels; #IMPLIED
- vspace %Pixels; #IMPLIED
- >
-
-<!--
- param is used to supply a named property value.
- In XML it would seem natural to follow RDF and support an
- abbreviated syntax where the param elements are replaced
- by attribute value pairs on the object start tag.
--->
-<!ELEMENT param EMPTY>
-<!ATTLIST param
- id ID #IMPLIED
- name CDATA #REQUIRED
- value CDATA #IMPLIED
- valuetype (data|ref|object) "data"
- type %ContentType; #IMPLIED
- >
-
-<!--=================== Java applet ==================================-->
-<!--
- One of code or object attributes must be present.
- Place param elements before other content.
--->
-<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
-<!ATTLIST applet
- %coreattrs;
- codebase %URI; #IMPLIED
- archive CDATA #IMPLIED
- code CDATA #IMPLIED
- object CDATA #IMPLIED
- alt %Text; #IMPLIED
- name NMTOKEN #IMPLIED
- width %Length; #REQUIRED
- height %Length; #REQUIRED
- align %ImgAlign; #IMPLIED
- hspace %Pixels; #IMPLIED
- vspace %Pixels; #IMPLIED
- >
-
-<!--=================== Images ===========================================-->
-
-<!--
- To avoid accessibility problems for people who aren't
- able to see the image, you should provide a text
- description using the alt and longdesc attributes.
- In addition, avoid the use of server-side image maps.
--->
-
-<!ELEMENT img EMPTY>
-<!ATTLIST img
- %attrs;
- src %URI; #REQUIRED
- alt %Text; #REQUIRED
- name NMTOKEN #IMPLIED
- longdesc %URI; #IMPLIED
- height %Length; #IMPLIED
- width %Length; #IMPLIED
- usemap %URI; #IMPLIED
- ismap (ismap) #IMPLIED
- align %ImgAlign; #IMPLIED
- border %Length; #IMPLIED
- hspace %Pixels; #IMPLIED
- vspace %Pixels; #IMPLIED
- >
-
-<!-- usemap points to a map element which may be in this document
- or an external document, although the latter is not widely supported -->
-
-<!--================== Client-side image maps ============================-->
-
-<!-- These can be placed in the same document or grouped in a
- separate document although this isn't yet widely supported -->
-
-<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
-<!ATTLIST map
- %i18n;
- %events;
- id ID #REQUIRED
- class CDATA #IMPLIED
- style %StyleSheet; #IMPLIED
- title %Text; #IMPLIED
- name CDATA #IMPLIED
- >
-
-<!ELEMENT area EMPTY>
-<!ATTLIST area
- %attrs;
- %focus;
- shape %Shape; "rect"
- coords %Coords; #IMPLIED
- href %URI; #IMPLIED
- nohref (nohref) #IMPLIED
- alt %Text; #REQUIRED
- target %FrameTarget; #IMPLIED
- >
-
-<!--================ Forms ===============================================-->
-
-<!ELEMENT form %form.content;> <!-- forms shouldn't be nested -->
-
-<!ATTLIST form
- %attrs;
- action %URI; #REQUIRED
- method (get|post) "get"
- name NMTOKEN #IMPLIED
- enctype %ContentType; "application/x-www-form-urlencoded"
- onsubmit %Script; #IMPLIED
- onreset %Script; #IMPLIED
- accept %ContentTypes; #IMPLIED
- accept-charset %Charsets; #IMPLIED
- target %FrameTarget; #IMPLIED
- >
-
-<!--
- Each label must not contain more than ONE field
- Label elements shouldn't be nested.
--->
-<!ELEMENT label %Inline;>
-<!ATTLIST label
- %attrs;
- for IDREF #IMPLIED
- accesskey %Character; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED
- >
-
-<!ENTITY % InputType
- "(text | password | checkbox |
- radio | submit | reset |
- file | hidden | image | button)"
- >
-
-<!-- the name attribute is required for all but submit & reset -->
-
-<!ELEMENT input EMPTY> <!-- form control -->
-<!ATTLIST input
- %attrs;
- %focus;
- type %InputType; "text"
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- checked (checked) #IMPLIED
- disabled (disabled) #IMPLIED
- readonly (readonly) #IMPLIED
- size CDATA #IMPLIED
- maxlength %Number; #IMPLIED
- src %URI; #IMPLIED
- alt CDATA #IMPLIED
- usemap %URI; #IMPLIED
- onselect %Script; #IMPLIED
- onchange %Script; #IMPLIED
- accept %ContentTypes; #IMPLIED
- align %ImgAlign; #IMPLIED
- >
-
-<!ELEMENT select (optgroup|option)+> <!-- option selector -->
-<!ATTLIST select
- %attrs;
- name CDATA #IMPLIED
- size %Number; #IMPLIED
- multiple (multiple) #IMPLIED
- disabled (disabled) #IMPLIED
- tabindex %Number; #IMPLIED
- onfocus %Script; #IMPLIED
- onblur %Script; #IMPLIED
- onchange %Script; #IMPLIED
- >
-
-<!ELEMENT optgroup (option)+> <!-- option group -->
-<!ATTLIST optgroup
- %attrs;
- disabled (disabled) #IMPLIED
- label %Text; #REQUIRED
- >
-
-<!ELEMENT option (#PCDATA)> <!-- selectable choice -->
-<!ATTLIST option
- %attrs;
- selected (selected) #IMPLIED
- disabled (disabled) #IMPLIED
- label %Text; #IMPLIED
- value CDATA #IMPLIED
- >
-
-<!ELEMENT textarea (#PCDATA)> <!-- multi-line text field -->
-<!ATTLIST textarea
- %attrs;
- %focus;
- name CDATA #IMPLIED
- rows %Number; #REQUIRED
- cols %Number; #REQUIRED
- disabled (disabled) #IMPLIED
- readonly (readonly) #IMPLIED
- onselect %Script; #IMPLIED
- onchange %Script; #IMPLIED
- >
-
-<!--
- The fieldset element is used to group form fields.
- Only one legend element should occur in the content
- and if present should only be preceded by whitespace.
--->
-<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
-<!ATTLIST fieldset
- %attrs;
- >
-
-<!ENTITY % LAlign "(top|bottom|left|right)">
-
-<!ELEMENT legend %Inline;> <!-- fieldset label -->
-<!ATTLIST legend
- %attrs;
- accesskey %Character; #IMPLIED
- align %LAlign; #IMPLIED
- >
-
-<!--
- Content is %Flow; excluding a, form, form controls, iframe
--->
-<!ELEMENT button %button.content;> <!-- push button -->
-<!ATTLIST button
- %attrs;
- %focus;
- name CDATA #IMPLIED
- value CDATA #IMPLIED
- type (button|submit|reset) "submit"
- disabled (disabled) #IMPLIED
- >
-
-<!-- single-line text input control (DEPRECATED) -->
-<!ELEMENT isindex EMPTY>
-<!ATTLIST isindex
- %coreattrs;
- %i18n;
- prompt %Text; #IMPLIED
- >
-
-<!--======================= Tables =======================================-->
-
-<!-- Derived from IETF HTML table standard, see [RFC1942] -->
-
-<!--
- The border attribute sets the thickness of the frame around the
- table. The default units are screen pixels.
-
- The frame attribute specifies which parts of the frame around
- the table should be rendered. The values are not the same as
- CALS to avoid a name clash with the valign attribute.
--->
-<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
-
-<!--
- The rules attribute defines which rules to draw between cells:
-
- If rules is absent then assume:
- "none" if border is absent or border="0" otherwise "all"
--->
-
-<!ENTITY % TRules "(none | groups | rows | cols | all)">
-
-<!-- horizontal placement of table relative to document -->
-<!ENTITY % TAlign "(left|center|right)">
-
-<!-- horizontal alignment attributes for cell contents
-
- char alignment char, e.g. char=':'
- charoff offset for alignment char
--->
-<!ENTITY % cellhalign
- "align (left|center|right|justify|char) #IMPLIED
- char %Character; #IMPLIED
- charoff %Length; #IMPLIED"
- >
-
-<!-- vertical alignment attributes for cell contents -->
-<!ENTITY % cellvalign
- "valign (top|middle|bottom|baseline) #IMPLIED"
- >
-
-<!ELEMENT table
- (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
-<!ELEMENT caption %Inline;>
-<!ELEMENT thead (tr)+>
-<!ELEMENT tfoot (tr)+>
-<!ELEMENT tbody (tr)+>
-<!ELEMENT colgroup (col)*>
-<!ELEMENT col EMPTY>
-<!ELEMENT tr (th|td)+>
-<!ELEMENT th %Flow;>
-<!ELEMENT td %Flow;>
-
-<!ATTLIST table
- %attrs;
- summary %Text; #IMPLIED
- width %Length; #IMPLIED
- border %Pixels; #IMPLIED
- frame %TFrame; #IMPLIED
- rules %TRules; #IMPLIED
- cellspacing %Length; #IMPLIED
- cellpadding %Length; #IMPLIED
- align %TAlign; #IMPLIED
- bgcolor %Color; #IMPLIED
- >
-
-<!ENTITY % CAlign "(top|bottom|left|right)">
-
-<!ATTLIST caption
- %attrs;
- align %CAlign; #IMPLIED
- >
-
-<!--
-colgroup groups a set of col elements. It allows you to group
-several semantically related columns together.
--->
-<!ATTLIST colgroup
- %attrs;
- span %Number; "1"
- width %MultiLength; #IMPLIED
- %cellhalign;
- %cellvalign;
- >
-
-<!--
- col elements define the alignment properties for cells in
- one or more columns.
-
- The width attribute specifies the width of the columns, e.g.
-
- width=64 width in screen pixels
- width=0.5* relative width of 0.5
-
- The span attribute causes the attributes of one
- col element to apply to more than one column.
--->
-<!ATTLIST col
- %attrs;
- span %Number; "1"
- width %MultiLength; #IMPLIED
- %cellhalign;
- %cellvalign;
- >
-
-<!--
- Use thead to duplicate headers when breaking table
- across page boundaries, or for static headers when
- tbody sections are rendered in scrolling panel.
-
- Use tfoot to duplicate footers when breaking table
- across page boundaries, or for static footers when
- tbody sections are rendered in scrolling panel.
-
- Use multiple tbody sections when rules are needed
- between groups of table rows.
--->
-<!ATTLIST thead
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tfoot
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tbody
- %attrs;
- %cellhalign;
- %cellvalign;
- >
-
-<!ATTLIST tr
- %attrs;
- %cellhalign;
- %cellvalign;
- bgcolor %Color; #IMPLIED
- >
-
-<!-- Scope is simpler than headers attribute for common tables -->
-<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
-
-<!-- th is for headers, td for data and for cells acting as both -->
-
-<!ATTLIST th
- %attrs;
- abbr %Text; #IMPLIED
- axis CDATA #IMPLIED
- headers IDREFS #IMPLIED
- scope %Scope; #IMPLIED
- rowspan %Number; "1"
- colspan %Number; "1"
- %cellhalign;
- %cellvalign;
- nowrap (nowrap) #IMPLIED
- bgcolor %Color; #IMPLIED
- width %Length; #IMPLIED
- height %Length; #IMPLIED
- >
-
-<!ATTLIST td
- %attrs;
- abbr %Text; #IMPLIED
- axis CDATA #IMPLIED
- headers IDREFS #IMPLIED
- scope %Scope; #IMPLIED
- rowspan %Number; "1"
- colspan %Number; "1"
- %cellhalign;
- %cellvalign;
- nowrap (nowrap) #IMPLIED
- bgcolor %Color; #IMPLIED
- width %Length; #IMPLIED
- height %Length; #IMPLIED
- >
-
diff --git a/lib/erl_docgen/priv/dtd/Makefile b/lib/erl_docgen/priv/dtd/Makefile
new file mode 100644
index 0000000000..314374d34b
--- /dev/null
+++ b/lib/erl_docgen/priv/dtd/Makefile
@@ -0,0 +1,101 @@
+#
+# %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%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(ERL_DOCGEN_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/erl_docgen-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+
+DTD_FILES = \
+ application.dtd \
+ chapter.dtd \
+ common.header.dtd \
+ comref.dtd \
+ fileref.dtd \
+ xhtml1-frameset.dtd \
+ appref.dtd \
+ cites.dtd \
+ common.image.dtd \
+ cref.dtd \
+ part.dtd \
+ xhtml1-strict.dtd \
+ book.dtd \
+ common.dtd \
+ common.refs.dtd \
+ erlref.dtd \
+ report.dtd \
+ xhtml1-transitional.dtd \
+ bookinsidecover.dtd \
+ common.entities.dtd \
+ common.table.dtd \
+ fascicules.dtd \
+ terms.dtd
+
+ENT_FILES = \
+ xhtml-special.ent \
+ xhtml-symbol.ent
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+debug opt:
+
+docs:
+
+clean:
+ $(RM) $(TARGET_FILES)
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+
+release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/dtd"
+ $(INSTALL_DATA) $(DTD_FILES) $(ENT_FILES) "$(RELSYSDIR)/priv/dtd"
+
+
+release_docs_spec:
+
+
+release_tests_spec:
+
+
diff --git a/lib/docbuilder/dtd/application.dtd b/lib/erl_docgen/priv/dtd/application.dtd
index 8a1e8832ec..8a1e8832ec 100644
--- a/lib/docbuilder/dtd/application.dtd
+++ b/lib/erl_docgen/priv/dtd/application.dtd
diff --git a/lib/docbuilder/dtd/appref.dtd b/lib/erl_docgen/priv/dtd/appref.dtd
index 70a5ff37af..70a5ff37af 100644
--- a/lib/docbuilder/dtd/appref.dtd
+++ b/lib/erl_docgen/priv/dtd/appref.dtd
diff --git a/lib/docbuilder/dtd/book.dtd b/lib/erl_docgen/priv/dtd/book.dtd
index bb89a6d255..bb89a6d255 100644
--- a/lib/docbuilder/dtd/book.dtd
+++ b/lib/erl_docgen/priv/dtd/book.dtd
diff --git a/lib/docbuilder/dtd/bookinsidecover.dtd b/lib/erl_docgen/priv/dtd/bookinsidecover.dtd
index d6efbef6a4..d6efbef6a4 100644
--- a/lib/docbuilder/dtd/bookinsidecover.dtd
+++ b/lib/erl_docgen/priv/dtd/bookinsidecover.dtd
diff --git a/lib/docbuilder/dtd/chapter.dtd b/lib/erl_docgen/priv/dtd/chapter.dtd
index eb2c96b04f..eb2c96b04f 100644
--- a/lib/docbuilder/dtd/chapter.dtd
+++ b/lib/erl_docgen/priv/dtd/chapter.dtd
diff --git a/lib/docbuilder/dtd/cites.dtd b/lib/erl_docgen/priv/dtd/cites.dtd
index 334574bff9..334574bff9 100644
--- a/lib/docbuilder/dtd/cites.dtd
+++ b/lib/erl_docgen/priv/dtd/cites.dtd
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd
index fdc02c55a1..fdc02c55a1 100644
--- a/lib/erl_docgen/priv/docbuilder_dtd/common.dtd
+++ b/lib/erl_docgen/priv/dtd/common.dtd
diff --git a/lib/docbuilder/dtd/common.entities.dtd b/lib/erl_docgen/priv/dtd/common.entities.dtd
index f893ecd070..f893ecd070 100644
--- a/lib/docbuilder/dtd/common.entities.dtd
+++ b/lib/erl_docgen/priv/dtd/common.entities.dtd
diff --git a/lib/docbuilder/dtd/common.header.dtd b/lib/erl_docgen/priv/dtd/common.header.dtd
index d422a89693..d422a89693 100644
--- a/lib/docbuilder/dtd/common.header.dtd
+++ b/lib/erl_docgen/priv/dtd/common.header.dtd
diff --git a/lib/docbuilder/dtd/common.image.dtd b/lib/erl_docgen/priv/dtd/common.image.dtd
index fc95a669dd..fc95a669dd 100644
--- a/lib/docbuilder/dtd/common.image.dtd
+++ b/lib/erl_docgen/priv/dtd/common.image.dtd
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd
index c1237766e1..c1237766e1 100644
--- a/lib/erl_docgen/priv/docbuilder_dtd/common.refs.dtd
+++ b/lib/erl_docgen/priv/dtd/common.refs.dtd
diff --git a/lib/docbuilder/dtd/common.table.dtd b/lib/erl_docgen/priv/dtd/common.table.dtd
index 7741da1018..7741da1018 100644
--- a/lib/docbuilder/dtd/common.table.dtd
+++ b/lib/erl_docgen/priv/dtd/common.table.dtd
diff --git a/lib/docbuilder/dtd/comref.dtd b/lib/erl_docgen/priv/dtd/comref.dtd
index fcdea625d5..fcdea625d5 100644
--- a/lib/docbuilder/dtd/comref.dtd
+++ b/lib/erl_docgen/priv/dtd/comref.dtd
diff --git a/lib/docbuilder/dtd/cref.dtd b/lib/erl_docgen/priv/dtd/cref.dtd
index e43bb2bf51..e43bb2bf51 100644
--- a/lib/docbuilder/dtd/cref.dtd
+++ b/lib/erl_docgen/priv/dtd/cref.dtd
diff --git a/lib/erl_docgen/priv/docbuilder_dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd
index 9905086ff4..9905086ff4 100644
--- a/lib/erl_docgen/priv/docbuilder_dtd/erlref.dtd
+++ b/lib/erl_docgen/priv/dtd/erlref.dtd
diff --git a/lib/docbuilder/dtd/fascicules.dtd b/lib/erl_docgen/priv/dtd/fascicules.dtd
index b14276a2c0..b14276a2c0 100644
--- a/lib/docbuilder/dtd/fascicules.dtd
+++ b/lib/erl_docgen/priv/dtd/fascicules.dtd
diff --git a/lib/docbuilder/dtd/fileref.dtd b/lib/erl_docgen/priv/dtd/fileref.dtd
index 5a1cc54afe..5a1cc54afe 100644
--- a/lib/docbuilder/dtd/fileref.dtd
+++ b/lib/erl_docgen/priv/dtd/fileref.dtd
diff --git a/lib/docbuilder/dtd/part.dtd b/lib/erl_docgen/priv/dtd/part.dtd
index 3f97199042..3f97199042 100644
--- a/lib/docbuilder/dtd/part.dtd
+++ b/lib/erl_docgen/priv/dtd/part.dtd
diff --git a/lib/docbuilder/dtd/report.dtd b/lib/erl_docgen/priv/dtd/report.dtd
index 3d07e6e5a7..3d07e6e5a7 100644
--- a/lib/docbuilder/dtd/report.dtd
+++ b/lib/erl_docgen/priv/dtd/report.dtd
diff --git a/lib/docbuilder/dtd/terms.dtd b/lib/erl_docgen/priv/dtd/terms.dtd
index 6105ec593e..6105ec593e 100644
--- a/lib/docbuilder/dtd/terms.dtd
+++ b/lib/erl_docgen/priv/dtd/terms.dtd
diff --git a/lib/docbuilder/dtd/xhtml-special.ent b/lib/erl_docgen/priv/dtd/xhtml-special.ent
index ca358b2fec..ca358b2fec 100644
--- a/lib/docbuilder/dtd/xhtml-special.ent
+++ b/lib/erl_docgen/priv/dtd/xhtml-special.ent
diff --git a/lib/docbuilder/dtd/xhtml-symbol.ent b/lib/erl_docgen/priv/dtd/xhtml-symbol.ent
index 63c2abfa6f..63c2abfa6f 100644
--- a/lib/docbuilder/dtd/xhtml-symbol.ent
+++ b/lib/erl_docgen/priv/dtd/xhtml-symbol.ent
diff --git a/lib/docbuilder/dtd/xhtml1-frameset.dtd b/lib/erl_docgen/priv/dtd/xhtml1-frameset.dtd
index d128f2eb7c..d128f2eb7c 100644
--- a/lib/docbuilder/dtd/xhtml1-frameset.dtd
+++ b/lib/erl_docgen/priv/dtd/xhtml1-frameset.dtd
diff --git a/lib/docbuilder/dtd/xhtml1-strict.dtd b/lib/erl_docgen/priv/dtd/xhtml1-strict.dtd
index 2927b9ece7..2927b9ece7 100644
--- a/lib/docbuilder/dtd/xhtml1-strict.dtd
+++ b/lib/erl_docgen/priv/dtd/xhtml1-strict.dtd
diff --git a/lib/docbuilder/dtd/xhtml1-transitional.dtd b/lib/erl_docgen/priv/dtd/xhtml1-transitional.dtd
index 628f27ac50..628f27ac50 100644
--- a/lib/docbuilder/dtd/xhtml1-transitional.dtd
+++ b/lib/erl_docgen/priv/dtd/xhtml1-transitional.dtd
diff --git a/lib/erl_docgen/priv/dtd_html_entities/Makefile b/lib/erl_docgen/priv/dtd_html_entities/Makefile
index d57302bd1b..9cd3f38c4b 100644
--- a/lib/erl_docgen/priv/dtd_html_entities/Makefile
+++ b/lib/erl_docgen/priv/dtd_html_entities/Makefile
@@ -63,8 +63,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/dtd_html_entities
- $(INSTALL_DATA) $(ENTITY_FILES) $(RELSYSDIR)/priv/dtd_html_entities
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/dtd_html_entities"
+ $(INSTALL_DATA) $(ENTITY_FILES) "$(RELSYSDIR)/priv/dtd_html_entities"
release_docs_spec:
diff --git a/lib/erl_docgen/priv/dtd_man_entities/Makefile b/lib/erl_docgen/priv/dtd_man_entities/Makefile
index 5651d8bc29..b6f29af6b4 100644
--- a/lib/erl_docgen/priv/dtd_man_entities/Makefile
+++ b/lib/erl_docgen/priv/dtd_man_entities/Makefile
@@ -63,8 +63,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/dtd_man_entities
- $(INSTALL_DATA) $(ENTITY_FILES) $(RELSYSDIR)/priv/dtd_man_entities
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/dtd_man_entities"
+ $(INSTALL_DATA) $(ENTITY_FILES) "$(RELSYSDIR)/priv/dtd_man_entities"
release_docs_spec:
diff --git a/lib/erl_docgen/priv/images/Makefile b/lib/erl_docgen/priv/images/Makefile
index 8b858fefb3..389f9f98ae 100644
--- a/lib/erl_docgen/priv/images/Makefile
+++ b/lib/erl_docgen/priv/images/Makefile
@@ -66,13 +66,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/images
- $(INSTALL_DATA) $(GIF_FILES) $(PNG_FILES) $(RELSYSDIR)/priv/images
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/images"
+ $(INSTALL_DATA) $(GIF_FILES) $(PNG_FILES) "$(RELSYSDIR)/priv/images"
release_docs_spec:
- $(INSTALL_DIR) $(RELEASE_PATH)/doc
- $(INSTALL_DATA) $(PNG_FILES) $(RELEASE_PATH)/doc
+ $(INSTALL_DIR) "$(RELEASE_PATH)/doc"
+ $(INSTALL_DATA) $(PNG_FILES) "$(RELEASE_PATH)/doc"
release_tests_spec:
diff --git a/lib/erl_docgen/priv/js/flipmenu/Makefile b/lib/erl_docgen/priv/js/flipmenu/Makefile
index 65c5c91f35..682d186608 100644
--- a/lib/erl_docgen/priv/js/flipmenu/Makefile
+++ b/lib/erl_docgen/priv/js/flipmenu/Makefile
@@ -68,13 +68,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/js/flipmenu
- $(INSTALL_DATA) $(JS_FILES) $(GIF_FILES) $(RELSYSDIR)/priv/js/flipmenu
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/js/flipmenu"
+ $(INSTALL_DATA) $(JS_FILES) $(GIF_FILES) "$(RELSYSDIR)/priv/js/flipmenu"
release_docs_spec:
- $(INSTALL_DIR) $(RELEASE_PATH)/doc/js/flipmenu
- $(INSTALL_DATA) $(JS_FILES) $(GIF_FILES) $(RELEASE_PATH)/doc/js/flipmenu
+ $(INSTALL_DIR) "$(RELEASE_PATH)/doc/js/flipmenu"
+ $(INSTALL_DATA) $(JS_FILES) $(GIF_FILES) "$(RELEASE_PATH)/doc/js/flipmenu"
release_tests_spec:
diff --git a/lib/erl_docgen/priv/xsl/Makefile b/lib/erl_docgen/priv/xsl/Makefile
index 92a53b8c0b..ca7a4e8157 100644
--- a/lib/erl_docgen/priv/xsl/Makefile
+++ b/lib/erl_docgen/priv/xsl/Makefile
@@ -68,8 +68,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/xsl
- $(INSTALL_DATA) $(XSL_FILES) $(RELSYSDIR)/priv/xsl
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/xsl"
+ $(INSTALL_DATA) $(XSL_FILES) "$(RELSYSDIR)/priv/xsl"
release_docs_spec:
diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl
index 7a648ddfd7..249e6950f7 100644
--- a/lib/erl_docgen/priv/xsl/db_eix.xsl
+++ b/lib/erl_docgen/priv/xsl/db_eix.xsl
@@ -106,10 +106,14 @@
<xsl:choose>
<!-- @arity is mandatory when referring to a specification -->
<xsl:when test="string-length(@arity) > 0">
- <xsl:call-template name="spec_name"/>
+ <xsl:call-template name="spec_name">
+ <xsl:with-param name="lastfuncsblock" select="$lastfuncsblock"/>
+ </xsl:call-template>
</xsl:when>
<xsl:otherwise>
- <xsl:call-template name="name"/>
+ <xsl:call-template name="name">
+ <xsl:with-param name="lastfuncsblock" select="$lastfuncsblock"/>
+ </xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
@@ -324,7 +328,7 @@
<xsl:choose>
<xsl:when test="string-length($tmp1) > 0 or starts-with($string, $start)">
<xsl:variable name="tmp2">
- <xsl:value-of select="substring-after($string, $end)"/>
+ <xsl:value-of select="substring-after(substring-after($string, $start), $end)"/>
</xsl:variable>
<xsl:variable name="retstring">
<xsl:call-template name="remove-paren">
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index a9052f29e5..4bc5abb364 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The 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,6 +40,11 @@
<xsl:variable name="m2a" select="document($mod2app_file)"></xsl:variable>
<xsl:key name="mod2app" match="module" use="@name"/>
+ <xsl:key
+ name="mfa"
+ match="func/name[string-length(@arity) > 0 and ancestor::erlref]"
+ use="concat(ancestor::erlref/module,':',@name, '/', @arity)"/>
+
<xsl:template name="err">
<xsl:param name="f"/>
<xsl:param name="m"/>
@@ -101,10 +106,14 @@
</xsl:message>
</xsl:when>
<xsl:when test="ancestor::erlref">
+ <!-- Do not to use preceding since it is very slow! -->
+ <xsl:variable name="curModule" select="ancestor::erlref/module"/>
+ <xsl:variable name="mfas"
+ select="key('mfa',
+ concat($curModule,':',$name,'/',$arity))"/>
<xsl:choose>
- <xsl:when test="preceding-sibling::name[position() = 1
- and @name = $name and @arity = $arity]">
- <!-- Avoid duplicated anchors.-->
+ <xsl:when test="generate-id($mfas[1]) != generate-id(.)">
+ <!-- Avoid duplicated anchors. See also menu.funcs. -->
</xsl:when>
<xsl:otherwise>
<a name="{$name}-{$arity}"></a>
@@ -546,6 +555,23 @@
<!-- End of Dialyzer type/spec tags -->
+ <!-- Cache for each module all the elements used for navigation. -->
+ <xsl:variable name="erlref.nav" select="exsl:node-set($erlref.nav_rtf)"/>
+
+ <xsl:variable name="erlref.nav_rtf">
+ <xsl:for-each select="//erlref">
+ <xsl:variable name="cval" select="module"/>
+ <xsl:variable name="link_cval"><xsl:value-of select="translate($cval, '&#173;', '')"/></xsl:variable>
+ <module name="{$cval}">
+ <xsl:call-template name="menu.funcs">
+ <xsl:with-param name="entries" select="funcs/func/name"/>
+ <xsl:with-param name="cval" select="$cval"/>
+ <xsl:with-param name="basename" select="$link_cval"/>
+ </xsl:call-template>
+ </module>
+ </xsl:for-each>
+ </xsl:variable>
+
<!-- Page layout -->
<xsl:template name="pagelayout">
<xsl:param name="chapnum"/>
@@ -1315,11 +1341,25 @@
Top of manual page
</a>
</li>
- <xsl:call-template name="menu.funcs">
- <xsl:with-param name="entries"
- select="funcs/func/name"/>
- <xsl:with-param name="basename"><xsl:value-of select="$link_cval"/></xsl:with-param>
- </xsl:call-template>
+ <xsl:call-template name="nl"/>
+ <xsl:choose>
+ <xsl:when test="local-name() = 'erlref'">
+ <!-- Use the cached value in order to save time.
+ value-of a string node is _much_ faster than
+ copy-of a rtf -->
+ <xsl:value-of
+ disable-output-escaping="yes"
+ select="$erlref.nav/module[@name = $cval]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="menu.funcs">
+ <xsl:with-param name="entries"
+ select="funcs/func/name"/>
+ <xsl:with-param name="basename"><xsl:value-of select="$link_cval"/></xsl:with-param>
+ <xsl:with-param name="cval" select="$cval"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
</ul>
</li>
</xsl:when>
@@ -1349,6 +1389,7 @@
<xsl:template name="menu.funcs">
<xsl:param name="entries"/>
<xsl:param name="basename"/>
+ <xsl:param name="cval"/>
<xsl:for-each select="$entries">
@@ -1434,17 +1475,41 @@
</xsl:choose>
</xsl:variable>
+ <!-- Avoid duplicated entries. See also template "spec_name" -->
+ <!-- Do not to use preceding since it is very slow! -->
+ <xsl:variable name="mfas"
+ select="key('mfa',
+ concat($cval,':',$fname,'/',$arity))"/>
<xsl:choose>
- <xsl:when test="preceding-sibling::name[position() = 1
- and @name = $fname and @arity = $arity]">
+ <xsl:when test="string-length(@name) > 0 and
+ generate-id($mfas[1]) != generate-id(.)">
<!-- 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>
+-->
+ <!-- Generate a text node -->
+ <xsl:text>&lt;li title="</xsl:text>
+ <xsl:value-of select="$fname"/>
+ <xsl:text>-</xsl:text>
+ <xsl:value-of select="$arity"/>
+ <xsl:text>">&lt;a href="</xsl:text>
+ <xsl:value-of select="$basename"/>
+ <xsl:text>.html#</xsl:text>
+ <xsl:value-of select="$fname"/>
+ <xsl:text>-</xsl:text>
+ <xsl:value-of select="$arity"/>
+ <xsl:text>"></xsl:text>
+ <xsl:value-of select="$fname"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="$arity"/>
+ <xsl:text>&lt;/a>&lt;/li></xsl:text>
+ <xsl:call-template name="nl"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
@@ -1752,7 +1817,14 @@
<xsl:choose>
<xsl:when test="ancestor::cref">
- <a name="{substring-before(nametext, '(')}"><span class="bold_code"><xsl:value-of select="ret"/><xsl:text> </xsl:text><xsl:value-of select="nametext"/></span></a><br/>
+ <a name="{substring-before(nametext, '(')}">
+ <span class="bold_code">
+ <xsl:value-of select="ret"/>
+ <xsl:call-template name="maybe-space-after-ret">
+ <xsl:with-param name="s" select="ret"/>
+ </xsl:call-template>
+ <xsl:value-of select="nametext"/>
+ </span></a><br/>
</xsl:when>
<xsl:when test="ancestor::erlref">
<xsl:variable name="fname">
@@ -1780,6 +1852,18 @@
</xsl:template>
+ <xsl:template name="maybe-space-after-ret">
+ <xsl:param name="s"/>
+ <xsl:variable name="last_char"
+ select="substring($s, string-length($s), 1)"/>
+ <xsl:choose>
+ <xsl:when test="$last_char != '*'">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+
<!-- Type -->
<xsl:template match="type">
<xsl:param name="partnum"/>
@@ -1854,18 +1938,24 @@
<xsl:choose>
<xsl:when test="string-length($filepart) > 0">
- <xsl:variable name="modulepart"><xsl:value-of select="substring-before($filepart, ':')"/></xsl:variable>
+ <!-- "Filepart#Linkpart" (or "Filepart#") -->
+ <xsl:variable name="app_part"><xsl:value-of select="substring-before($filepart, ':')"/></xsl:variable>
<xsl:choose>
- <xsl:when test="string-length($modulepart) > 0">
- <xsl:variable name="filepart1"><xsl:value-of select="substring-after($filepart, ':')"/></xsl:variable>
- <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$modulepart}','{$filepart1}.html#{$linkpart}');"><xsl:apply-templates/></a></span>
+ <xsl:when test="string-length($app_part) > 0">
+ <!-- "AppPart:ModPart#Linkpart" -->
+ <xsl:variable name="mod_part"><xsl:value-of select="substring-after($filepart, ':')"/></xsl:variable>
+ <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app_part}','{$mod_part}.html#{$linkpart}');"><xsl:apply-templates/></a></span>
</xsl:when>
<xsl:otherwise>
+ <!-- "Filepart#Linkpart (there is no ':' in Filepart) -->
+ <xsl:variable name="minus_prefix"
+ select="substring-before($linkpart, '-')"/>
<xsl:choose>
- <!-- Dialyzer seealso (the application is unknown) -->
- <xsl:when test="string-length($specs_file) > 0
+ <xsl:when test="$minus_prefix = 'type'
+ and string-length($specs_file) > 0
and count($i/specs/module[@name=$filepart]) = 0">
- <!-- Deemed to slow; use key() instead
+ <!-- Dialyzer seealso (the application is unknown) -->
+ <!-- Following code deemed too slow; use key() instead
<xsl:variable name="app"
select="$m2a/mod2app/module[@name=$filepart]"/>
-->
@@ -1877,41 +1967,45 @@
<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="$this"/>
+ <!-- Unknown application -->
+ <xsl:message terminate="yes">
+ Error <xsl:value-of select="$filepart"/>: cannot find module exporting type
+ </xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:when test="string-length($linkpart) > 0">
+ <!-- Still Filepart#Linkpart (there is no ':' in Filepart -->
<span class="bold_code"><a href="{$filepart}.html#{$linkpart}"><xsl:apply-templates/></a></span>
</xsl:when>
<xsl:otherwise>
+ <!-- "Filepart#" (there is no ':' in Filepart -->
<span class="bold_code"><a href="{$filepart}.html"><xsl:apply-templates/></a></span>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
+ </xsl:when> <!-- string-length($filepart) > 0 -->
+ <xsl:when test="string-length($linkpart) > 0">
+ <!-- "#Linkpart" -->
+ <span class="bold_code"><a href="#{$linkpart}"><xsl:apply-templates/></a></span>
</xsl:when>
<xsl:otherwise>
- <xsl:choose>
- <xsl:when test="string-length($linkpart) > 0">
- <span class="bold_code"><a href="#{$linkpart}"><xsl:apply-templates/></a></span>
- </xsl:when>
- <xsl:otherwise>
- <xsl:variable name="modulepart"><xsl:value-of select="substring-before(@marker, ':')"/></xsl:variable>
+ <!-- "AppPart:Mod" or "Mod" (there is no '#') -->
+ <xsl:variable name="app_part"><xsl:value-of select="substring-before(@marker, ':')"/></xsl:variable>
- <xsl:choose>
- <xsl:when test="string-length($modulepart) > 0">
- <xsl:variable name="filepart1"><xsl:value-of select="substring-after(@marker, ':')"/></xsl:variable>
- <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$modulepart}','{$filepart1}.html');"><xsl:apply-templates/></a></span>
- </xsl:when>
- <xsl:otherwise>
- <span class="bold_code"><a href="{@marker}.html"><xsl:apply-templates/></a></span>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="string-length($app_part) > 0">
+ <!-- "App:Mod" -->
+ <xsl:variable name="mod_part"><xsl:value-of select="substring-after(@marker, ':')"/></xsl:variable>
+ <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app_part}','{$mod_part}.html');"><xsl:apply-templates/></a></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- "Mod" -->
+ <span class="bold_code"><a href="{@marker}.html"><xsl:apply-templates/></a></span>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:otherwise>
</xsl:choose>
@@ -2184,7 +2278,7 @@
<xsl:choose>
<xsl:when test="string-length($tmp1) > 0 or starts-with($string, $start)">
<xsl:variable name="tmp2">
- <xsl:value-of select="substring-after($string, $end)"/>
+ <xsl:value-of select="substring-after(substring-after($string, $start), $end)"/>
</xsl:variable>
<xsl:variable name="retstring">
<xsl:call-template name="remove-paren">
@@ -2200,4 +2294,9 @@
</xsl:template>
+ <xsl:template name="nl">
+ <xsl:text>
+</xsl:text>
+ </xsl:template>
+
</xsl:stylesheet>
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl
index 0aca74bc97..33808859c7 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-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -586,7 +586,15 @@
</xsl:template>
<xsl:template match="seealso">
- <xsl:text>\fB</xsl:text><xsl:apply-templates/><xsl:text>\fR\&amp;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="ancestor::head">
+ <!-- The header of Dialyzer specs -->
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>\fB</xsl:text><xsl:apply-templates/><xsl:text>\fR\&amp;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
<!-- Code -->
@@ -750,10 +758,32 @@
<xsl:template name="name">
<xsl:text>&#10;.B&#10;</xsl:text>
- <xsl:apply-templates/>
+ <xsl:choose>
+ <xsl:when test="ancestor::cref">
+ <xsl:value-of select="ret"/>
+ <xsl:call-template name="maybe-space-after-ret">
+ <xsl:with-param name="s" select="ret"/>
+ </xsl:call-template>
+ <xsl:value-of select="nametext"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
<xsl:text>&#10;.br</xsl:text>
</xsl:template>
+ <xsl:template name="maybe-space-after-ret">
+ <xsl:param name="s"/>
+ <xsl:variable name="last_char"
+ select="substring($s, string-length($s), 1)"/>
+ <xsl:choose>
+ <xsl:when test="$last_char != '*'">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
<!-- Type -->
<xsl:template match="type">
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index 48a7a026c1..da96052462 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -1424,7 +1424,13 @@
<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:call-template name="maybe-space-after-ret">
+ <xsl:with-param name="s" select="ret"/>
+ </xsl:call-template>
+ <xsl:value-of select="nametext"/>
+ </fo:block>
</xsl:when>
<xsl:otherwise>
<fo:block id="{generate-id(.)}"><xsl:value-of select="."/></fo:block>
@@ -1432,6 +1438,16 @@
</xsl:choose>
</xsl:template>
+ <xsl:template name="maybe-space-after-ret">
+ <xsl:param name="s"/>
+ <xsl:variable name="last_char"
+ select="substring($s, string-length($s), 1)"/>
+ <xsl:choose>
+ <xsl:when test="$last_char != '*'">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
<!-- Type -->
<xsl:template match="type">
@@ -1564,7 +1580,7 @@
</xsl:variable>
<fo:block xsl:use-attribute-sets="image">
- <fo:external-graphic content-width="60%" src="{@file}"/>
+ <fo:external-graphic content-width="scale-down-to-fit" inline-progression-dimension.maximum="100%" src="{@file}"/>
<xsl:apply-templates>
<xsl:with-param name="chapnum" select="$chapnum"/>
@@ -1680,7 +1696,7 @@
<xsl:choose>
<xsl:when test="string-length($tmp1) > 0 or starts-with($string, $start)">
<xsl:variable name="tmp2">
- <xsl:value-of select="substring-after($string, $end)"/>
+ <xsl:value-of select="substring-after(substring-after($string, $start), $end)"/>
</xsl:variable>
<xsl:variable name="retstring">
<xsl:call-template name="remove-paren">
diff --git a/lib/erl_docgen/src/Makefile b/lib/erl_docgen/src/Makefile
index 8e81bccd59..4d8f43bfed 100644
--- a/lib/erl_docgen/src/Makefile
+++ b/lib/erl_docgen/src/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
@@ -35,7 +35,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/erl_docgen-$(VSN)
# Target Specs
# ----------------------------------------------------
MODULES = \
- otp_specs
+ docgen_otp_specs \
+ docgen_edoc_xml_cb \
+ docgen_xmerl_xml_cb
HRL_FILES =
@@ -87,10 +89,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
new file mode 100644
index 0000000000..20daae8215
--- /dev/null
+++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
@@ -0,0 +1,1171 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See
+%% the Licence for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson AB.
+%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
+%% All Rights Reserved.��
+%%
+%% $Id$
+%%
+-module(docgen_edoc_xml_cb).
+
+%% This is the EDoc callback module for creating erlref
+%% documents (man pages) in XML format, and also a chapter
+%% document based on "overview.edoc".
+%%
+%% edoc:file(File, [{layout,docgen_edoc_xml_cb},{file_suffix,".xml"},
+%% {preprocess,true}]).
+%%
+%% The origin of this file is the edoc module otpsgml_layout.erl
+%% written by Richard Carlsson.
+
+-export([module/2, overview/2]).
+
+-include("xmerl.hrl").
+
+-define(NL, "\n").
+
+%%-User interface-------------------------------------------------------
+
+%% ERLREF
+module(Element, Opts) ->
+ SortP = proplists:get_value(sort_functions, Opts, true),
+ XML = layout_module(Element, SortP),
+ xmerl:export_simple([XML], docgen_xmerl_xml_cb, []).
+
+%% CHAPTER
+overview(Element, _Opts) ->
+ XML = layout_chapter(Element),
+ xmerl:export_simple([XML], docgen_xmerl_xml_cb, []).
+
+%%--Internal functions--------------------------------------------------
+
+layout_module(#xmlElement{name = module, content = Es}=E, SortP) ->
+ Name = get_attrval(name, E),
+ Desc = get_content(description, Es),
+ ShortDesc = text_only(get_content(briefDescription, Desc)),
+ FullDesc = otp_xmlify(get_content(fullDescription, Desc)),
+ Types0 = get_content(typedecls, Es),
+ Types1 = lists:sort([{type_name(Et), Et} || Et <- Types0]),
+ Functions =
+ case SortP of
+ true ->
+ lists:sort([{function_name(Ef), Ef} ||
+ Ef <- get_content(functions, Es)]);
+ false ->
+ [{function_name(Ef), Ef} ||
+ Ef <- get_content(functions, Es)]
+ end,
+ Header = {header, [
+ ?NL,{title, [Name]},
+ ?NL,{prepared, [""]},
+ ?NL,{responsible, [""]},
+ ?NL,{docno, ["1"]},
+ ?NL,{approved, [""]},
+ ?NL,{checked, [""]},
+ ?NL,{date, [""]},
+ ?NL,{rev, ["A"]},
+ ?NL,{file, [Name++".xml"]}
+ ]},
+ Module = {module, [Name]},
+ ModuleSummary = {modulesummary, ShortDesc},
+ Description = {description, [?NL|FullDesc]},
+ Types = case Types1 of
+ [] -> [];
+ _ ->
+ [?NL, {section,[{title,["DATA TYPES"]},
+ {marker,[{id,"types"}],[]},
+ ?NL|types(Types1)]}]
+ end,
+ Funcs = functions(Functions),
+ See = seealso_module(Es),
+ Authors = {authors, authors(Es)},
+ {erlref,
+ [?NL,Header,
+ ?NL,Module,
+ ?NL,ModuleSummary,
+ ?NL,Description]
+ ++ Types ++
+ [?NL,Funcs,
+ ?NL,See,
+ ?NL,Authors]
+ }.
+
+layout_chapter(#xmlElement{name=overview, content=Es}) ->
+ Title = get_text(title, Es),
+ Header = {header, [
+ ?NL,{title,[Title]},
+ ?NL,{prepared,[""]},
+ ?NL,{docno,[""]},
+ ?NL,{date,[""]},
+ ?NL,{rev,[""]},
+ ?NL,{file, ["chapter.xml"]}
+ ]},
+ DescEs = get_content(description, Es),
+ FullDescEs = get_content(fullDescription, DescEs),
+ Sections = chapter_ify(FullDescEs, first),
+ {chapter, [?NL, Header, ?NL | Sections]}.
+
+chapter_ify([], _) ->
+ [];
+chapter_ify(Es, first) ->
+ %% Everything up to the first section should be made into
+ %% plain paragraphs -- or if no first section is found, everything
+ %% should be made into one
+ case find_next(h3, Es) of
+ {Es, []} ->
+ SubSections = subchapter_ify(Es, first),
+ [{section, [?NL,{title,["Overview"]},
+ ?NL | SubSections]}];
+ {FirstEs, RestEs} ->
+ otp_xmlify(FirstEs) ++ chapter_ify(RestEs, next)
+ end;
+chapter_ify([#xmlElement{name=h3} = E | Es], next) ->
+ {SectionEs, RestEs} = find_next(h3, Es),
+ SubSections = subchapter_ify(SectionEs, first),
+ {Marker, Title} = chapter_title(E),
+ [{section, [?NL,{marker,[{id,Marker}],[]},
+ ?NL,{title,[Title]},
+ ?NL | SubSections]} | chapter_ify(RestEs, next)].
+
+subchapter_ify([], _) ->
+ [];
+subchapter_ify(Es, first) ->
+ %% Everything up to the (possible) first subsection should be
+ %% made into plain paragraphs
+ {FirstEs, RestEs} = find_next(h4, Es),
+ otp_xmlify(FirstEs) ++ subchapter_ify(RestEs, next);
+subchapter_ify([#xmlElement{name=h4} = E | Es], next) ->
+ {SectionEs, RestEs} = find_next(h4, Es),
+ Elements = otp_xmlify(SectionEs),
+ {Marker, Title} = chapter_title(E),
+ [{section, [?NL,{marker,[{id,Marker}],[]},
+ ?NL,{title,[Title]},
+ ?NL | Elements]} | subchapter_ify(RestEs, next)].
+
+chapter_title(#xmlElement{content=Es}) -> % name = h3 | h4
+ case Es of
+ [#xmlElement{name=a} = E] ->
+ {get_attrval(name, E), get_text(E)}
+ end.
+
+%%--XHTML->XML transformation-------------------------------------------
+
+%% otp_xmlify(Es1) -> Es2
+%% Es1 = Es2 = [#xmlElement{} | #xmlText{}]
+%% Fix things that are allowed in XHTML but not in chapter/erlref DTDs.
+%% 1) lists (<ul>, <ol>, <dl>) and code snippets (<pre>) can not occur
+%% within a <p>, such a <p> must be splitted into a sequence of <p>,
+%% <ul>, <ol>, <dl> and <pre>.
+%% 2) <a> must only have either a href attribute (corresponds to a
+%% <seealso> or <url> in the XML code) in which case its content
+%% must be plain text; or a name attribute (<marker>).
+%% 3a) <b> content must be plain text.
+%% b) <em> content must be plain text (or actually a <code> element
+%% as well, but a simplification is used here).
+%% c) <pre> content must be plain text (or could actually contain
+%% <input> as well, but a simplification is used here).
+%% 4) <code> content must be plain text, or the element must be split
+%% into a list of elements.
+%% 5a) <h1>, <h2> etc is not allowed - replaced by its content within
+%% a <b> tag.
+%% b) <center> is not allowed - replaced by its content.
+%% c) <font> -"-
+%% 6) <table> is not allowed in erlref, translated to text instead.
+%% Also a <table> in chapter without a border is translated to text.
+%% A <table> in chapter with a border must contain a <tcaption>.
+%% 7) <sup> is not allowed - is replaced with its text content
+%% within parenthesis.
+%% 8) <blockquote> contents may need to be made into paragraphs
+%% 9) <th> (table header) is not allowed - is replaced by
+%% <td><em>...</em></td>.
+%% 10) <img src=""> is not allowed, replace with <image file="">
+otp_xmlify([]) ->
+ [];
+otp_xmlify(Es0) ->
+ Es = case is_paragraph(hd(Es0)) of
+
+ %% If the first element is a <p> xmlElement, then
+ %% the entire element list is ready to be otp_xmlified.
+ true ->
+ Es0;
+
+ %% If the first element is not a <p> xmlElement, then all
+ %% elements up to the first <p> (or end of list) must be
+ %% made into a paragraph (using the {p, Es} construction)
+ %% before the list is otp_xmlified.
+ false ->
+ case find_next(p, Es0, []) of
+ {[#xmlText{value=Str}] = First, Rest} ->
+ %% Special case: Making a paragraph out of a
+ %% blank line isn't a great idea.
+ case is_empty(Str) of
+ true ->
+ Rest;
+ false ->
+ [{p,First}|Rest]
+ end;
+ {First, Rest} ->
+ [{p,First}|Rest]
+ end
+ end,
+
+ %% Fix paragraph breaks not needed in XHTML but in XML
+ EsFixed = otp_xmlify_fix(Es),
+
+ otp_xmlify_es(EsFixed).
+
+%% EDoc does not always translate empty lines (with leading "%%")
+%% as paragraph break, this is the fix
+otp_xmlify_fix(Es) ->
+ otp_xmlify_fix(Es, []).
+otp_xmlify_fix([#xmlText{value="\n \n"++_} = E1, E2 | Es], Res) ->
+ %% This is how it looks when generating an erlref from a .erl file
+ case is_paragraph(E2) of
+ false ->
+ {P, After} = find_p_ending(Es, []),
+ otp_xmlify_fix(After, [{p, [E2|P]}, E1 | Res]);
+ true ->
+ otp_xmlify_fix([E2|Es], [E1|Res])
+ end;
+otp_xmlify_fix([#xmlText{value="\n\n"} = E1, E2 | Es], Res) ->
+ %% This is how it looks when generating a chapter from overview.edoc
+ case is_paragraph(E2) of
+ false ->
+ {P, After} = find_p_ending(Es, []),
+ otp_xmlify_fix(After, [{p, [E2|P]}, E1 | Res]);
+ true ->
+ otp_xmlify_fix([E2|Es], [E1|Res])
+ end;
+otp_xmlify_fix([E|Es], Res) ->
+ otp_xmlify_fix(Es, [E|Res]);
+otp_xmlify_fix([], Res) ->
+ lists:reverse(Res).
+
+otp_xmlify_es([E | Es]) ->
+ case is_paragraph(E) of
+ true ->
+ case otp_xmlify_psplit(E) of
+
+ %% paragraph contained inline tags and text only
+ nosplit ->
+ otp_xmlify_e(E) ++ otp_xmlify_es(Es);
+
+ %% paragraph contained dl, ul and/or pre and has been
+ %% splitted
+ SubEs ->
+ lists:flatmap(fun otp_xmlify_e/1, SubEs) ++
+ otp_xmlify_es(Es)
+ end;
+ false ->
+ otp_xmlify_e(E) ++ otp_xmlify_es(Es)
+ end;
+otp_xmlify_es([]) ->
+ [].
+
+%% otp_xmlify_psplit(P) -> nosplit | [E]
+%% Handles case 1) above.
+%% Uses the {p, Es} construct, thus replaces an p xmlElement with one
+%% or more {p, Es} tuples if splitting the paraghrap is necessary.
+otp_xmlify_psplit(P) ->
+ otp_xmlify_psplit(p_content(P), [], []).
+otp_xmlify_psplit([#xmlElement{name=Name}=E | Es], Content, Res) ->
+ if
+ Name==blockquote; Name==ul; Name==ol; Name==dl; Name==pre;
+ Name==table ->
+ case Content of
+ [] ->
+ otp_xmlify_psplit(Es, [], [E|Res]);
+ [#xmlText{value=Str}] ->
+ %% Special case: Making a paragraph out of a blank
+ %% line isn't a great idea. Instead, this can be
+ %% viewed as the case above, where there is no
+ %% content to make a paragraph out of
+ case is_empty(Str) of
+ true ->
+ otp_xmlify_psplit(Es, [], [E|Res]);
+ false ->
+ Pnew = {p, lists:reverse(Content)},
+ otp_xmlify_psplit(Es, [], [E,Pnew|Res])
+ end;
+ _ ->
+ Pnew = {p, lists:reverse(Content)},
+ otp_xmlify_psplit(Es, [], [E,Pnew|Res])
+ end;
+
+ true ->
+ otp_xmlify_psplit(Es, [E|Content], Res)
+ end;
+otp_xmlify_psplit([E | Es], Content, Res) ->
+ otp_xmlify_psplit(Es, [E|Content], Res);
+otp_xmlify_psplit([], _Content, []) ->
+ nosplit;
+otp_xmlify_psplit([], [], Res) ->
+ lists:reverse(Res);
+otp_xmlify_psplit([], [#xmlText{value="\n\n"}], Res) ->
+ lists:reverse(Res);
+otp_xmlify_psplit([], Content, Res) ->
+ Pnew = {p, lists:reverse(Content)},
+ lists:reverse([Pnew|Res]).
+
+%% otp_xmlify_e(E) -> [E]
+%% This is the function which does the actual transformation of
+%% single elements, normally by making sure the content corresponds
+%% to what is allowed by the OTP DTDs.
+%% Returns a list of elements as the xmlification in some cases
+%% returns no element or more than one element (although in most cases
+%% exactly one element).
+otp_xmlify_e(#xmlElement{name=a} = E) -> % 2) above
+ otp_xmlify_a(E);
+otp_xmlify_e(#xmlElement{name=Tag} = E) % 3a-c)
+ when Tag==b; Tag==em; Tag==pre ->
+ Content = text_only(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=code} = E) -> % 4)
+ case catch text_only(E#xmlElement.content) of
+ {'EXIT', _Error} ->
+ otp_xmlify_code(E);
+ Content ->
+ [E#xmlElement{content=Content}]
+ end;
+otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a
+ when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 ->
+ Content = text_only(E#xmlElement.content),
+ [E#xmlElement{name=b, content=Content}];
+otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c)
+ when Tag==center;
+ Tag==font ->
+ otp_xmlify_e(E#xmlElement.content);
+otp_xmlify_e(#xmlElement{name=table} = E) -> % 6)
+ case parent(E) of
+ module ->
+ otp_xmlify_table(E#xmlElement.content);
+ overview ->
+ Content0 = otp_xmlify_e(E#xmlElement.content),
+ Summary = #xmlText{value=get_attrval(summary, E)},
+ TCaption = E#xmlElement{name=tcaption,
+ attributes=[],
+ content=[Summary]},
+ Content = Content0 ++ [TCaption],
+ [E#xmlElement{attributes=[], content=Content}]
+ end;
+otp_xmlify_e(#xmlElement{name=tbody} = E) ->
+ otp_xmlify_e(E#xmlElement.content);
+otp_xmlify_e(#xmlElement{name=sup} = E) -> % 7)
+ Text = get_text(E),
+ [#xmlText{parents = E#xmlElement.parents,
+ pos = E#xmlElement.pos,
+ language = E#xmlElement.language,
+ value = "(" ++ Text ++ ")"}];
+otp_xmlify_e(#xmlElement{name=blockquote} = E) -> % 8)
+ Content = otp_xmlify_blockquote(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=th} = E) -> % 9)
+ Content = otp_xmlify_e(E#xmlElement.content),
+ EmE = E#xmlElement{name=em, content=Content},
+ [E#xmlElement{name=td, content=[EmE]}];
+otp_xmlify_e(#xmlElement{name=p} = E) -> % recurse
+ Content = otp_xmlify_e(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e({p, Content1}) ->
+ Content2 = otp_xmlify_e(Content1),
+ [{p, Content2}];
+otp_xmlify_e(#xmlElement{name=ul} = E) ->
+ Content = otp_xmlify_e(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=li} = E) ->
+ %% Content may need to be made into <p>s etc.
+ Content = otp_xmlify(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=dl} = E) ->
+ Content0 = otp_xmlify_e(E#xmlElement.content),
+ Content = otp_xmlify_dl(Content0),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=dt} = E) ->
+ %% Special fix: Markers in <taglist> <tag>s are not allowed,
+ %% save it using 'put' and place the marker first in the <item>
+ %% instead
+ Content = case E#xmlElement.content of
+ [#xmlElement{name=a} = A] ->
+ put(dt_marker, otp_xmlify_e(A)),
+ otp_xmlify_e(A#xmlElement.content);
+ _ ->
+ otp_xmlify_e(E#xmlElement.content)
+ end,
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=dd} = E) ->
+ %% Content may need to be made into <p>s etc.
+ Content0 = otp_xmlify(E#xmlElement.content),
+ Content = case get(dt_marker) of
+ undefined -> Content0;
+ [Marker] ->
+ put(dt_marker, undefined),
+ [Marker#xmlElement{content=[]}|Content0]
+ end,
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=tr} = E) ->
+ Content = otp_xmlify_e(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=td} = E) ->
+ Content = otp_xmlify_e(E#xmlElement.content),
+ [E#xmlElement{content=Content}];
+otp_xmlify_e(#xmlElement{name=img} = E) -> % 10)
+ Content = otp_xmlify_e(E#xmlElement.content),
+ [otp_xmlify_img(E#xmlElement{ content = Content })];
+otp_xmlify_e([E | Es]) ->
+ otp_xmlify_e(E) ++ otp_xmlify_e(Es);
+otp_xmlify_e([]) ->
+ [];
+otp_xmlify_e(E) ->
+ [E].
+
+%%--Tags with special handling------------------------------------------
+
+%% otp_xmlify_a(A1) -> [A2]
+%% Takes an <a> element and filters the attributes to decide wheather
+%% its a seealso/url or a marker.
+%% In the case of a seealso/url, the href part is checked, making
+%% sure a .xml/.html file extension is removed.
+%% Also, references to other applications //App has a href attribute
+%% value "OTPROOT/..." (due to app_default being set to "OTPROOT")
+%% , in this case both href attribute and content must be
+%% formatted correctly according to requirements.
+otp_xmlify_a(A) ->
+ [Attr0] = filter_a_attrs(A#xmlElement.attributes),
+ case Attr0 of
+ #xmlAttribute{name=href, value=Href0} -> % seealso | url
+ Content0 = text_only(A#xmlElement.content),
+ {Href, Content} = otp_xmlify_a_href(Href0, Content0),
+ [A#xmlElement{attributes=[Attr0#xmlAttribute{value=Href}],
+ content=Content}];
+ #xmlAttribute{name=name} -> % marker
+ Content = otp_xmlify_e(A#xmlElement.content),
+ [A#xmlElement{attributes=[Attr0], content=Content}]
+ end.
+
+%% filter_a_attrs(Attrs) -> [Attr]
+%% Removes all attributes from a <a> element except the href or
+%% name attribute.
+filter_a_attrs([#xmlAttribute{name=href} = Attr | _Attrs]) ->
+ [Attr];
+filter_a_attrs([#xmlAttribute{name=name} = Attr | _Attrs]) ->
+ [Attr];
+filter_a_attrs([_Attr|Attrs]) ->
+ filter_a_attrs(Attrs);
+filter_a_attrs([]) ->
+ [].
+
+%% otp_xmlify_a_href(Href0, Es0) -> {Href1, Es1}
+%% Href = string()
+otp_xmlify_a_href("#"++_ = Marker, Es0) -> % <seealso marker="#what">
+ {Marker, Es0};
+otp_xmlify_a_href("http:"++_ = URL, Es0) -> % external URL
+ {URL, Es0};
+otp_xmlify_a_href("OTPROOT"++AppRef, Es0) -> % <.. marker="App:FileRef
+ [AppS, "doc", FileRef1] = split(AppRef, "/"),
+ FileRef = AppS++":"++otp_xmlify_a_fileref(FileRef1, AppS),
+ [#xmlText{value=Str0} = T] = Es0,
+ Str = case split(Str0, "/") of
+ %% //Application
+ [AppS2] ->
+ %% AppS2 can differ from AppS
+ %% Example: xmerl/XMerL
+ AppS2;
+ [_AppS,ModRef] ->
+ case split(ModRef, ":") of
+ %% //Application/Module
+ [Module] ->
+ Module++"(3)";
+ %% //Application/Module:Type()
+ [_Module,_Type] ->
+ ModRef
+ end;
+ %% //Application/Module:Function/Arity
+ [_AppS,ModFunc,Arity] ->
+ ModFunc++"/"++Arity
+ end,
+ {FileRef, [T#xmlText{value=Str}]};
+otp_xmlify_a_href("../"++File, Es0) ->
+ %% Special case: This kind of relative path is used on some
+ %% places within i.e. EDoc and refers to a file within the same
+ %% application tree.
+ %% Correct the path according to the OTP directory structure
+ {"../../"++File, Es0};
+otp_xmlify_a_href(FileRef1, Es0) -> % File within the same application
+ FileRef2 = otp_xmlify_a_fileref(FileRef1, this),
+ {FileRef2, Es0}.
+
+%% otp_xmlify_a_fileref(FileRef1, AppS|this) -> FileRef2
+%% AppS = FileRef = string()
+otp_xmlify_a_fileref(FileRef1, AppS) ->
+ case split(FileRef1, ".#") of
+
+ %% EDoc default name is "overview-summary.html,
+ %% name of OTP User's Guide chapter is "chapter.xml"
+ ["overview-summary", _Ext] ->
+ "chapter";
+ ["overview-summary", _Ext, Marker] ->
+ "chapter#"++Marker;
+
+ [File, Ext] when Ext=="xml";
+ Ext=="html", AppS/=this ->
+ File;
+ [File, Ext, Marker0] ->
+ %% Here is an awkward solution to an awkward problem
+ %% The marker automatically inserted at each function
+ %% does not seem to work for EDoc generated ERLREFs.
+ %% So if the referenced marker is in an ERLREF generated
+ %% by EDoc, keep it "as is", ie "function-arity".
+ %% If the referenced marker is NOT in an ERLREF generated
+ %% by EDoc, the marker should be on the format
+ %% "function/arity".
+ %% The awkward part of the solution is to decide wheather
+ %% the ERLREF is generated by EDoc or not: Here we make
+ %% the decision based on which application the module
+ %% belongs to -- which is ok when the module was written
+ %% but probably not in the future...
+ EDocApps = ["edoc","hipe","syntax_tools","xmerl"],
+ IsEDocGenerated = lists:member(AppS, EDocApps),
+ Marker = if
+ %% The marker is in a file in *this*
+ %% application (which documentation obviously
+ %% is generated by EDoc), or it is in a file
+ %% in an application which documentation
+ %% is assumed to be generated by EDoc
+ AppS==this; IsEDocGenerated ->
+ Marker0;
+
+ %% The marker is in a file in an application
+ %% which documentation is assumed NOT to be
+ %% generated by EDoc
+ true ->
+ case split(Marker0, "-") of
+ [Func,Arity] ->
+ Func++"/"++Arity;
+ _ ->
+ Marker0
+ end
+ end,
+ if
+ %% Ignore file extension in file reference if it either
+ %% is ".xml" or if it is ".html" but AppS/=this, that
+ %% is, we're resolving an OTPROOT file reference
+ Ext=="xml";
+ Ext=="html", AppS/=this ->
+ File++"#"++Marker;
+ true ->
+ File++"."++Ext++"#"++Marker
+ end;
+
+ %% References to other files than XML files are kept as-is
+ _ ->
+ FileRef1
+ end.
+
+%% otp_xmlify_blockquote(Es1) -> Es2
+%% Ensures that the content of a <blockquote> is divided into
+%% <p>s using the {p, Es} construct.
+otp_xmlify_blockquote([#xmlElement{name=p} = E|Es]) ->
+ [E | otp_xmlify_blockquote(Es)];
+otp_xmlify_blockquote([#xmlText{} = E|Es]) ->
+ {P, After} = find_p_ending(Es, []),
+ [{p, [E|P]} | otp_xmlify_blockquote(After)];
+otp_xmlify_blockquote([]) ->
+ [].
+
+%% otp_xmlify_code(E) -> Es
+%% Takes a <code> xmlElement and split it into a list of <code> and
+%% other xmlElements. Necessary when it contains more than a single
+%% xmlText element.
+%% Example:
+%% #xmlElement{name=code,
+%% content=[#xmlText{}, #xmlElement{name=br}, #xmlText{}]}
+%% =>
+%% [#xmlElement{name=code, content=[#xmlText{}]},
+%% #xmlElement{name=br},
+%% #xmlElement{name=code, content=[#xmlText{}]}]
+otp_xmlify_code(E) ->
+ otp_xmlify_code(E, E#xmlElement.content, []).
+otp_xmlify_code(Code, [#xmlText{} = E|Es], Acc) ->
+ otp_xmlify_code(Code, Es, [Code#xmlElement{content=[E]}|Acc]);
+otp_xmlify_code(Code, [#xmlElement{} = E|Es], Acc) ->
+ otp_xmlify_code(Code, Es, [E|Acc]);
+otp_xmlify_code(_Code, [], Acc) ->
+ lists:reverse(Acc).
+
+%% otp_xmlify_dl(Es1) -> Es2
+%% Insert empty <dd> elements if necessary.
+%% OTP DTDs does not allow <taglist>s with <tag>s but no <item>s.
+otp_xmlify_dl([#xmlElement{name=dt} = E|Es]) ->
+ [E|otp_xmlify_dl(Es, E)];
+otp_xmlify_dl([E|Es]) ->
+ [E|otp_xmlify_dl(Es)];
+otp_xmlify_dl([]) ->
+ [].
+
+otp_xmlify_dl([#xmlElement{name=dd} = E|Es], _DT) ->
+ [E|otp_xmlify_dl(Es)];
+otp_xmlify_dl([#xmlElement{name=dt} = E|Es], DT) ->
+ DD = DT#xmlElement{name=dd, attributes=[], content=[]},
+ [DD,E|otp_xmlify_dl(Es, E)];
+otp_xmlify_dl([E|Es], DT) ->
+ [E|otp_xmlify_dl(Es, DT)];
+otp_xmlify_dl([], DT) ->
+ DD = DT#xmlElement{name=dd, attributes=[], content=[]},
+ [DD].
+
+%% otp_xmlify_table(Es1) -> Es2
+%% Transform <table> contents into "text", that is, inline elements.
+otp_xmlify_table([#xmlText{} = E|Es]) ->
+ [E | otp_xmlify_table(Es)];
+otp_xmlify_table([#xmlElement{name=tbody} = E|Es]) ->
+ otp_xmlify_table(E#xmlElement.content)++otp_xmlify_table(Es);
+otp_xmlify_table([#xmlElement{name=tr, content=Content}|Es]) ->
+ %% Insert newlines between table rows
+ otp_xmlify_table(Content)++[{br,[]}]++otp_xmlify_table(Es);
+otp_xmlify_table([#xmlElement{name=th, content=Content}|Es]) ->
+ [{em, Content} | otp_xmlify_table(Es)];
+otp_xmlify_table([#xmlElement{name=td, content=Content}|Es]) ->
+ otp_xmlify_e(Content) ++ otp_xmlify_table(Es);
+otp_xmlify_table([]) ->
+ [].
+
+%% otp_xmlify_img(E) -> Es.
+%% Transforms a <img src=""> into <image file="">
+otp_xmlify_img(E0) ->
+ Attrs = lists:map(
+ fun(#xmlAttribute{ name = src, value = Path} = A) ->
+ V = otp_xmlify_a_fileref(Path,this),
+ A#xmlAttribute{ name = file,
+ value = V };
+ (A) ->
+ A
+ end,E0#xmlElement.attributes),
+ E0#xmlElement{name = image, expanded_name = image,
+ attributes = Attrs}.
+
+%%--Misc help functions used by otp_xmlify/1 et al---------------------
+
+%% find_next(Tag, Es) -> {Es1, Es2}
+%% Returns {Es1, Es2} where Es1 is the list of all elements up to (but
+%% not including) the first element with tag Tag in Es, and Es2
+%% is the remaining elements of Es.
+find_next(Tag, Es) ->
+ find_next(Tag, Es, []).
+find_next(Tag, [#xmlElement{name=Tag} = E | Es], AccEs) ->
+ {lists:reverse(AccEs), [E|Es]};
+find_next(Tag, [E|Es], AccEs) ->
+ find_next(Tag, Es, [E|AccEs]);
+find_next(_Tag, [], AccEs) ->
+ {lists:reverse(AccEs), []}.
+
+%% find_p_ending(Es, []) -> {Es1, Es2}
+%% Returns {Es1, Es2} where Es1 is the list of all elements up to (but
+%% not including) the first paragraph break in Es, and Es2 is
+%% the remaining elements of Es2.
+%% Paragraph break = <p> tag or empty line
+%% the next blank line, <p> or end-of-list as P, and the remaining
+%% elements of Es as After.
+find_p_ending([#xmlText{value="\n \n"++_} = E|Es], P) ->
+ {lists:reverse(P), [E|Es]};
+find_p_ending([#xmlElement{name=p} = E|Es], P) ->
+ {lists:reverse(P), [E|Es]};
+find_p_ending([E|Es], P) ->
+ find_p_ending(Es, [E|P]);
+find_p_ending([], P) ->
+ {lists:reverse(P), []}.
+
+%% is_paragraph(E | P) -> bool()
+%% P = {p, Es}
+is_paragraph(#xmlElement{name=p}) -> true;
+is_paragraph({p, _Es}) -> true;
+is_paragraph(_E) -> false.
+
+%% p_content(E | P) -> Es
+p_content(#xmlElement{content=Content}) -> Content;
+p_content({p, Content}) -> Content.
+
+%% is_empty(Str) -> bool()
+%% Str = string()
+%% Returns true if Str is empty in the sense that it contains nothing
+%% but spaces, tabs or newlines.
+is_empty("\n"++Str) ->
+ is_empty(Str);
+is_empty(" "++Str) ->
+ is_empty(Str);
+is_empty("\t"++Str) ->
+ is_empty(Str);
+is_empty("") ->
+ true;
+is_empty(_) ->
+ false.
+
+%% split(Str, Seps) -> [Str]
+split(Str, Seps) ->
+ split(Str, Seps, []).
+
+split([Ch|Str], Seps, Acc) ->
+ case lists:member(Ch, Seps) of
+ true -> split(Str, Seps, Acc);
+ false -> split(Str, Seps, Acc, [Ch])
+ end;
+split([], _Seps, Acc) ->
+ lists:reverse(Acc).
+
+split([Ch|Str], Seps, Acc, Chs) ->
+ case lists:member(Ch, Seps) of
+ true -> split(Str, Seps, [lists:reverse(Chs)|Acc]);
+ false -> split(Str, Seps, Acc, [Ch|Chs])
+ end;
+split([], _Seps, Acc, Chs) ->
+ lists:reverse([lists:reverse(Chs)|Acc]).
+
+%%--Functions for creating an erlref document---------------------------
+
+%% function_name(F) -> string()
+%% F = #xmlElement{name=function}
+%% Returns the name of a function as "name/arity".
+function_name(E) ->
+ get_attrval(name, E) ++ "/" ++ get_attrval(arity, E).
+
+%% functions(Fs) -> Es
+%% Fs = [{Name, F}]
+%% Name = string() "name/arity"
+%% F = #xmlElement{name=function}
+functions(Fs) ->
+ Es = lists:flatmap(fun ({Name, E}) -> function(Name, E) end, Fs),
+ if
+ Es==[] ->
+ [];
+ true ->
+ {funcs, Es}
+ end.
+
+function(_Name, E=#xmlElement{content = Es}) ->
+ TypeSpec = get_content(typespec, Es),
+ [?NL,{func, [ ?NL,
+ {name,
+ case funcheader(TypeSpec) of
+ [] ->
+ signature(get_content(args, Es),
+ get_attrval(name, E));
+ Spec -> Spec
+ end
+ },
+ ?NL,{fsummary, fsummary(Es)},
+ ?NL,local_types(TypeSpec),
+ ?NL,{desc,
+ label_anchor(E)++
+ deprecated(Es)++
+ fulldesc(Es)++
+ seealso_function(Es)}
+ ]}].
+
+fsummary([]) -> ["\s"];
+fsummary(Es) ->
+ Desc = get_content(description, Es),
+ case get_content(briefDescription, Desc) of
+ [] ->
+ fsummary_equiv(Es); % no description at all if no equiv
+ ShortDesc ->
+ text_only(ShortDesc)
+ end.
+
+fsummary_equiv(Es) ->
+ case get_content(equiv, Es) of
+ [] -> ["\s"];
+ Es1 ->
+ case get_content(expr, Es1) of
+ [] -> ["\s"];
+ [Expr] ->
+ ["Equivalent to ", Expr, ".",?NL]
+ end
+ end.
+
+label_anchor(E) ->
+ case get_attrval(label, E) of
+ "" -> [];
+ Ref -> [{marker, [{id, Ref}],[]},?NL]
+ end.
+
+label_anchor(Content, E) ->
+ case get_attrval(label, E) of
+ "" -> Content;
+ Ref -> {p,[{marker, [{id, Ref}],[]},
+ {em, Content}]}
+ end.
+
+signature(Es, Name) ->
+ [Name, "("] ++ seq(fun arg/1, Es) ++ [") -> term()", ?NL].
+
+arg(#xmlElement{content = Es}) ->
+ [get_text(argName, Es)].
+
+funcheader([]) -> [];
+funcheader(Es) ->
+ [t_name(get_elem(erlangName, Es))] ++ t_utype(get_elem(type, Es)).
+
+local_types([]) -> [];
+local_types(Es) ->
+ local_defs2(get_elem(localdef, Es)).
+
+local_defs2([]) -> [];
+local_defs2(Es) ->
+ {type,[?NL | [{v, localdef2(E)} || E <- Es]]}.
+
+%% Like localdef/1, but does not use label_anchor/2 -- we don't want any
+%% markers or em tags in <v> tag, plain text only!
+localdef2(#xmlElement{content = Es}) ->
+ case get_elem(typevar, Es) of
+ [] ->
+ t_utype(get_elem(type, Es));
+ [V] ->
+ t_var(V) ++ [" = "] ++ t_utype(get_elem(type, Es))
+ end.
+
+type_name(#xmlElement{content = Es}) ->
+ t_name(get_elem(erlangName, get_content(typedef, Es))).
+
+types(Ts) ->
+ Es = lists:flatmap(fun ({Name, E}) -> typedecl(Name, E) end, Ts),
+ [?NL, {taglist,[?NL|Es]}].
+
+typedecl(Name, #xmlElement{content = Es}) ->
+ TypedefEs = get_content(typedef, Es),
+ Id = "type-"++Name,
+ [{tag, typedef(TypedefEs)},
+ ?NL,
+ {item, [{marker,[{id,Id}],[]} |
+ local_defs(get_elem(localdef, TypedefEs)) ++ fulldesc(Es)]},
+ ?NL].
+
+typedef(Es) ->
+ Name = ([t_name(get_elem(erlangName, Es)), "("]
+ ++ seq(fun t_utype_elem/1, get_content(argtypes, Es), [")"])),
+ case get_elem(type, Es) of
+ [] ->
+ [{tt, Name}];
+ Type ->
+ [{tt, Name ++ [" = "] ++ t_utype(Type)}]
+ end.
+
+local_defs([]) -> [];
+local_defs(Es) ->
+ [?NL, {ul, [{li, [{tt, localdef(E)}]} || E <- Es]}].
+
+localdef(E = #xmlElement{content = Es}) ->
+ Var = case get_elem(typevar, Es) of
+ [] ->
+ [label_anchor(t_abstype(get_content(abstype, Es)), E)];
+ [V] ->
+ t_var(V)
+ end,
+ Var ++ [" = "] ++ t_utype(get_elem(type, Es)).
+
+deprecated(Es) ->
+ case get_content(deprecated, Es) of
+ [] -> [];
+ DeprEs ->
+ Es2 = get_content(fullDescription,
+ get_content(description, DeprEs)),
+ Es3 = otp_xmlify_e(Es2),
+ [{p, [{em, ["This function is deprecated: "]} |Es3]}, ?NL]
+ end.
+
+fulldesc(Es) ->
+ case get_content(fullDescription, get_content(description, Es)) of
+ [] ->
+ index_desc(Es);
+ Desc ->
+ [?NL|otp_xmlify(Desc)] ++ [?NL]
+ end.
+
+index_desc(Es) ->
+ Desc = get_content(description, Es),
+ case get_content(briefDescription, Desc) of
+ [] ->
+ equiv(Es); % no description at all if no equiv
+ ShortDesc ->
+ ShortDesc
+ end.
+
+seealso_module(Es) ->
+ case get_elem(see, Es) of
+ [] -> [];
+ Es1 ->
+ {section,[{title,["See also"]},{p,seq(fun see/1, Es1, [])}]}
+ end.
+seealso_function(Es) ->
+ case get_elem(see, Es) of
+ [] -> [];
+ Es1 ->
+ [{p, [{em, ["See also:"]}, " "] ++ seq(fun see/1, Es1, ["."])},
+ ?NL]
+ end.
+
+%% ELEMENT see PCDATA
+%% ATTLIST name PCDATA
+%% href PCDATA
+see(#xmlElement{content=Es0} = E) ->
+ Href0 = get_attrval(href, E),
+ {Href, Es} = otp_xmlify_a_href(Href0, Es0),
+ [{seealso, [{marker, Href}], Es}].
+
+equiv(Es) ->
+ case get_content(equiv, Es) of
+ [] -> ["\s"];
+ Es1 ->
+ case get_content(expr, Es1) of
+ [] -> [];
+ [Expr] ->
+ Expr1 = [Expr],
+ Expr2 = case get_elem(see, Es1) of
+ [] ->
+ {c,Expr1};
+ [E=#xmlElement{}] ->
+ case get_attrval(href, E) of
+ "" ->
+ {c,Expr1};
+ Ref ->
+ {seealso, [{marker, Ref}], Expr1}
+ end
+ end,
+ [{p, ["Equivalent to ", Expr2, "."]}, ?NL]
+ end
+ end.
+
+authors(Es) ->
+ case get_elem(author, Es) of
+ [] ->
+ [?NL,{aname,["\s"]},?NL,{email,["\s"]}];
+ Es1 ->
+ [?NL|seq(fun author/1, Es1, "", [])]
+ end.
+
+author(E=#xmlElement{}) ->
+ Name = case get_attrval(name, E) of
+ [] -> "\s";
+ N -> N
+ end,
+ Mail = case get_attrval(email, E) of
+ [] -> "\s";
+ M -> M
+ end,
+ [?NL,{aname,[Name]},?NL,{email,[Mail]}].
+
+t_name([E]) ->
+ N = get_attrval(name, E),
+ case get_attrval(module, E) of
+ "" -> N;
+ M ->
+ S = M ++ ":" ++ N,
+ case get_attrval(app, E) of
+ "" -> S;
+ A -> "//" ++ A ++ "/" ++ S
+ end
+ end.
+
+t_utype([E]) ->
+ t_utype_elem(E).
+
+t_utype_elem(E=#xmlElement{content = Es}) ->
+ case get_attrval(name, E) of
+ "" -> t_type(Es);
+ Name ->
+ T = t_type(Es),
+ case T of
+ [Name] -> T; % avoid generating "Foo::Foo"
+ T -> [Name] ++ ["::"] ++ T
+ end
+ end.
+
+t_type([E=#xmlElement{name = typevar}]) ->
+ t_var(E);
+t_type([E=#xmlElement{name = atom}]) ->
+ t_atom(E);
+t_type([E=#xmlElement{name = integer}]) ->
+ t_integer(E);
+t_type([E=#xmlElement{name = range}]) ->
+ t_range(E);
+t_type([E=#xmlElement{name = float}]) ->
+ t_float(E);
+t_type([#xmlElement{name = nil}]) ->
+ t_nil();
+t_type([#xmlElement{name = list, content = Es}]) ->
+ t_list(Es);
+t_type([#xmlElement{name = tuple, content = Es}]) ->
+ t_tuple(Es);
+t_type([#xmlElement{name = 'fun', content = Es}]) ->
+ t_fun(Es);
+t_type([#xmlElement{name = abstype, content = Es}]) ->
+ t_abstype(Es);
+t_type([#xmlElement{name = union, content = Es}]) ->
+ t_union(Es);
+t_type([#xmlElement{name = record, content = Es}]) ->
+ t_record(Es).
+
+t_var(E) ->
+ [get_attrval(name, E)].
+
+t_atom(E) ->
+ [get_attrval(value, E)].
+
+t_integer(E) ->
+ [get_attrval(value, E)].
+
+t_range(E) ->
+ [get_attrval(value, E)].
+
+t_float(E) ->
+ [get_attrval(value, E)].
+
+t_nil() ->
+ ["[]"].
+
+t_list(Es) ->
+ ["["] ++ t_utype(get_elem(type, Es)) ++ ["]"].
+
+t_tuple(Es) ->
+ ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]).
+
+t_fun(Es) ->
+ ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
+ [") -> "] ++ t_utype(get_elem(type, Es))).
+
+t_record([E|Es]) ->
+ ["#", get_attrval(value, E), "{"++ seq(fun t_field/1, Es) ++"}"].
+t_field(#xmlElement{name=field, content=[Atom,Type]}) ->
+ [get_attrval(value, Atom), "="] ++ t_utype_elem(Type).
+
+t_abstype(Es) ->
+ case split_at_colon(t_name(get_elem(erlangName, Es)),[]) of
+ {Mod,Type} ->
+ [Type, "("] ++
+ seq(fun t_utype_elem/1, get_elem(type, Es), [")"]) ++
+ [" (see module ", Mod, ")"];
+ Type ->
+ [Type, "("] ++
+ seq(fun t_utype_elem/1, get_elem(type, Es), [")"])
+ end.
+
+%% Split at one colon, but not at two (or more)
+split_at_colon([$:,$:|_]=Rest,Acc) ->
+ lists:reverse(Acc)++Rest;
+split_at_colon([$:|Type],Acc) ->
+ {lists:reverse(Acc),Type};
+split_at_colon([Char|Rest],Acc) ->
+ split_at_colon(Rest,[Char|Acc]);
+split_at_colon([],Acc) ->
+ lists:reverse(Acc).
+
+t_union(Es) ->
+ seq(fun t_utype_elem/1, Es, " | ", []).
+
+%% seq(Fun, Es)
+%% seq(Fun, Es, Tail)
+%% seq(Fun, Es, Sep, Tail) -> [string()]
+%% Fun = function(E) -> [string()]
+%% Sep = string()
+%% Tail = [string()]
+%% Applies Fun to each element E in Es and return the appended list of
+%% strings, separated by Sep which defaults to ", " and ended by Tail
+%% which defaults to [].
+seq(Fun, Es) ->
+ seq(Fun, Es, []).
+seq(Fun, Es, Tail) ->
+ seq(Fun, Es, ", ", Tail).
+seq(Fun, [E], _Sep, Tail) ->
+ Fun(E) ++ Tail;
+seq(Fun, [E | Es], Sep, Tail) ->
+ Fun(E) ++ [Sep] ++ seq(Fun, Es, Sep, Tail);
+seq(_Fun, [], _Sep, Tail) ->
+ Tail.
+
+%%--Misc functions for accessing fields etc-----------------------------
+
+%% Type definitions used below:
+%% E = #xmlElement{} | #xmlText{}
+%% Es = [E]
+%% Tag = atom(), XHTML tag
+%% Name = atom(), XHTML attribute name
+%% Attrs = [#xmlAttribute{}]
+%% Ts = [#xmlText{}]
+
+%% parent(E) -> module | overview
+parent(E) ->
+ Parents = E#xmlElement.parents,
+ {Parent,_} = lists:last(Parents),
+ Parent.
+
+%% get_elem(Tag, Es1) -> Es2
+%% Returns a list of all elements in Es which have the name Tag.
+get_elem(Name, [#xmlElement{name = Name} = E | Es]) ->
+ [E | get_elem(Name, Es)];
+get_elem(Name, [_ | Es]) ->
+ get_elem(Name, Es);
+get_elem(_, []) ->
+ [].
+
+%% get_attr(Name, Attrs1) -> Attrs2
+%% Returns a list of all attributes in Attrs1 which have the name Name.
+get_attr(Name, [#xmlAttribute{name = Name} = A | As]) ->
+ [A | get_attr(Name, As)];
+get_attr(Name, [_ | As]) ->
+ get_attr(Name, As);
+get_attr(_, []) ->
+ [].
+
+%% get_attrval(Name, E) -> string()
+%% If E has one attribute with name Name, return its value, otherwise ""
+get_attrval(Name, #xmlElement{attributes = As}) ->
+ case get_attr(Name, As) of
+ [#xmlAttribute{value = V}] ->
+ V;
+ [] -> ""
+ end.
+
+%% get_content(Tag, Es1) -> Es2
+%% If there is one element in Es1 with name Tag, returns its contents,
+%% otherwise []
+get_content(Name, Es) ->
+ case get_elem(Name, Es) of
+ [#xmlElement{content = Es1}] ->
+ Es1;
+ [] -> []
+ end.
+
+%% get_text(Tag, Es) -> string()
+%% If there is one element in Es with name Tag, and its content is
+%% a single xmlText, return the value of this xmlText.
+%% Otherwise return "".
+get_text(Name, Es) ->
+ case get_content(Name, Es) of
+ [#xmlText{value = Text}] ->
+ Text;
+ [] -> ""
+ end.
+
+%% get_text(E) -> string()
+%% Return the value of an single xmlText which is the content of E,
+%% possibly recursively.
+get_text(#xmlElement{content=[#xmlText{value=Text}]}) ->
+ Text;
+get_text(#xmlElement{content=[E]}) ->
+ get_text(E).
+
+%% text_only(Es) -> Ts
+%% Takes a list of xmlElement and xmlText and return a lists of xmlText.
+text_only([#xmlElement{content = Content}|Es]) ->
+ text_only(Content) ++ text_only(Es);
+text_only([#xmlText{} = E |Es]) ->
+ [E | text_only(Es)];
+text_only([]) ->
+ [].
diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl
new file mode 100644
index 0000000000..3929e66515
--- /dev/null
+++ b/lib/erl_docgen/src/docgen_otp_specs.erl
@@ -0,0 +1,713 @@
+%%
+%% %CopyrightBegin%
+%%
+%% 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
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(docgen_otp_specs).
+
+-export([module/2, package/2, overview/2, type/1]).
+
+-include("xmerl.hrl").
+
+-define(XML_EXPORT, xmerl_xml).
+-define(DEFAULT_XML_EXPORT, ?XML_EXPORT).
+-define(DEFAULT_PP, erl_pp).
+-define(IND(N), #xmlText{value="\n" ++ lists:duplicate(N, $\s)}).
+-define(NL, "\n").
+
+module(Element, Options) ->
+ XML = layout_module(Element, init_opts(Options)),
+ Export = proplists:get_value(xml_export, Options,
+ ?DEFAULT_XML_EXPORT),
+ xmerl:export_simple(XML, Export, [#xmlAttribute{name=prolog,
+ value=""}]).
+
+-record(opts, {pretty_print, file_suffix}).
+
+init_opts(Options) ->
+ #opts{pretty_print = proplists:get_value(pretty_print,
+ Options, ?DEFAULT_PP),
+ %% It *is* depending on edoc.hrl!
+ file_suffix = proplists:get_value(file_suffix, Options, ".html")}.
+
+layout_module(#xmlElement{name = module, content = Es}=E, Opts) ->
+ Name = get_attrval(name, E),
+ Functions = [{function_name(Elem), Elem} ||
+ Elem <- get_content(functions, Es)],
+ Types = [{type_name(Elem), Elem} || Elem <- get_content(typedecls, Es)],
+ Body = [{module,
+ [{name,[Name]}],
+ ([?NL] ++ types(lists:sort(Types), Opts)
+ ++ functions(lists:sort(Functions), Opts)
+ ++ timestamp())}],
+ Body.
+
+timestamp() ->
+ [{timestamp, [io_lib:fwrite("Generated by EDoc, ~s, ~s.",
+ [edoc_lib:datestr(date()),
+ edoc_lib:timestr(time())])]},?NL].
+
+functions(Fs, Opts) ->
+ lists:flatmap(fun ({Name, E}) -> function(Name, E, Opts) end, Fs).
+
+function(Name, #xmlElement{content = Es}, Opts) ->
+ TS = get_content(typespec, Es),
+ Spec = typespec(TS, Opts),
+ [{spec,(Name
+ ++ [?IND(2),{contract,Spec}]
+ ++ typespec_annos(TS))},
+ ?NL].
+
+function_name(E) ->
+ [] = get_attrval(module, E),
+ [?IND(2),{name,[atom(get_attrval(name, E))]},
+ ?IND(2),{arity,[get_attrval(arity, E)]}].
+
+label_anchor(Content, E) ->
+ case get_attrval(label, E) of
+ "" -> Content;
+ Ref -> [{marker, [{id, Ref}], Content}]
+ end.
+
+typespec([], _Opts) -> [];
+typespec(Es, Opts) ->
+ {Head, LDefs} = collect_clause(Es, Opts),
+ clause(Head, LDefs) ++ [?IND(2)].
+
+collect_clause(Es, Opts) ->
+ Name = t_name(get_elem(erlangName, Es)),
+ Defs = get_elem(localdef, Es),
+ [Type] = get_elem(type, Es),
+ {format_spec(Name, Type, Opts), collect_local_defs(Defs, Opts)}.
+
+clause(Head, LDefs) ->
+ FC = [?IND(6),{head,Head}] ++ local_clause_defs(LDefs),
+ [?IND(4),{clause,FC}].
+
+local_clause_defs([]) -> [];
+local_clause_defs(LDefs) ->
+ LocalDefs = [{subtype,T} || T <- coalesce_local_defs(LDefs, [])],
+ [?IND(6),{guard,margin(8, LocalDefs)}].
+
+types(Ts, Opts) ->
+ lists:flatmap(fun ({Name, E}) -> typedecl(Name, E, Opts) end, Ts).
+
+typedecl(Name, E=#xmlElement{content = Es}, Opts) ->
+ TD = get_content(typedef, Es),
+ TypeDef = typedef(E, TD, Opts),
+ [{type,(Name
+ ++ [?IND(2),{typedecl, TypeDef}]
+ ++ typedef_annos(TD))},
+ ?NL].
+
+type_name(#xmlElement{content = Es}) ->
+ Typedef = get_content(typedef, Es),
+ [E] = get_elem(erlangName, Typedef),
+ Args = get_content(argtypes, Typedef),
+ [] = get_attrval(module, E),
+ [?IND(2),{name,[atom(get_attrval(name, E))]},
+ ?IND(2),{n_vars,[integer_to_list(length(Args))]}].
+
+typedef(E, Es, Opts) ->
+ Ns = get_elem(erlangName, Es),
+ Name =
+ ([t_name(Ns), "("]
+ ++ seq(fun t_utype_elem/1, get_content(argtypes, Es), [")"])),
+ LDefs = collect_local_defs(get_elem(localdef, Es), Opts),
+ TypeHead = case get_elem(type, Es) of
+ [] -> label_anchor(Name, E);
+ Type -> (label_anchor(Name, E)
+ ++ format_type(Name, Type, Opts))
+ end,
+ ([?IND(6),{typehead,TypeHead}]
+ ++ local_type_defs(LDefs, [])).
+
+local_type_defs([], _) -> [];
+local_type_defs(LDefs, Last) ->
+ LocalDefs = [{local_def,T} || T <- coalesce_local_defs(LDefs, Last)],
+ [?IND(6),{local_defs,margin(8, LocalDefs)}].
+
+collect_local_defs(Es, Opts) ->
+ [collect_localdef(E, Opts) || E <- Es].
+
+collect_localdef(E = #xmlElement{content = Es}, Opts) ->
+ Name = case get_elem(typevar, Es) of
+ [] ->
+ label_anchor(N0 = t_abstype(get_content(abstype, Es)), E);
+ [V] ->
+ N0 = t_var(V)
+ end,
+ {Name,N0,format_type(N0, get_elem(type, Es), Opts)}.
+
+%% "A = t(), B = t()" is coalesced into "A = B = t()".
+%% Names as B above are kept, but the formated string is empty.
+coalesce_local_defs([], _Last) ->
+ [];
+coalesce_local_defs([{Name,N0,TypeS} | L], Last) when Name =:= N0 ->
+ cld(L, [{Name,N0}], TypeS, Last);
+coalesce_local_defs([{Name,N0,TypeS} | L], Last) ->
+ [local_def(N0, Name, TypeS, Last, L) | coalesce_local_defs(L, Last)].
+
+cld([{Name,N0,TypeS} | L], Names, TypeS, Last) when Name =:= N0 ->
+ cld(L, [{Name,N0} | Names], TypeS, Last);
+cld(L, Names0, TypeS, Last) ->
+ Names = [{_,Name0} | Names1] = lists:reverse(Names0),
+ NS = join([N || {N,_} <- Names], [" = "]),
+ ([local_def(Name0, NS, TypeS, Last, L) |
+ [local_def(N0, "", "", [], L) || {_,N0} <- Names1]]
+ ++ coalesce_local_defs(L, Last)).
+
+local_def(Name, NS, TypeS, Last, L) ->
+ [{typename,Name},{string,NS ++ TypeS ++ [Last || L =:= []]}].
+
+%% join([], Sep) when is_list(Sep) ->
+%% [];
+join([H|T], Sep) ->
+ H ++ lists:append([Sep ++ X || X <- T]).
+
+%% Use the default formatting of EDoc, which creates references, and
+%% then insert newlines and indentation according to erl_pp (the
+%% (fast) Erlang pretty printer).
+format_spec(Name, Type, #opts{pretty_print = erl_pp}=Opts) ->
+ try
+ L = t_clause(Name, Type),
+ O = pp_clause(Name, Type),
+ {R, ".\n"} = diaf(L, O, Opts),
+ R
+ catch _:_ ->
+ %% Example: "@spec ... -> record(a)"
+ format_spec(Name, Type, Opts#opts{pretty_print=default})
+ end;
+format_spec(Sep, Type, _Opts) ->
+ t_clause(Sep, Type).
+
+t_clause(Name, Type) ->
+ #xmlElement{content = [#xmlElement{name = 'fun', content = C}]} = Type,
+ [Name] ++ t_fun(C).
+
+pp_clause(Pre, Type) ->
+ Types = ot_utype([Type]),
+ Atom = lists:duplicate(iolist_size(Pre), $a),
+ L1 = erl_pp:attribute({attribute,0,spec,{{list_to_atom(Atom),0},[Types]}}),
+ "-spec " ++ L2 = lists:flatten(L1),
+ L3 = Pre ++ lists:nthtail(length(Atom), L2),
+ re:replace(L3, "\n ", "\n", [{return,list},global]).
+
+format_type(Name, Type, #opts{pretty_print = erl_pp}=Opts) ->
+ try
+ L = t_utype(Type),
+ O = pp_type(Name, Type),
+ {R, ".\n"} = diaf(L, O, Opts),
+ [" = "] ++ R
+ catch _:_ ->
+ %% Example: "t() = record(a)."
+ format_type(Name, Type, Opts#opts{pretty_print=default})
+ end;
+format_type(_Name, Type, _Opts) ->
+ [" = "] ++ t_utype(Type).
+
+pp_type(Prefix, Type) ->
+ Atom = list_to_atom(lists:duplicate(iolist_size(Prefix), $a)),
+ L1 = erl_pp:attribute({attribute,0,type,{Atom,ot_utype(Type),[]}}),
+ {L2,N} = case lists:dropwhile(fun(C) -> C =/= $: end, lists:flatten(L1)) of
+ ":: " ++ L3 -> {L3,9}; % compensation for extra "()" and ":"
+ "::\n" ++ L3 -> {"\n"++L3,6}
+ end,
+ Ss = lists:duplicate(N, $\s),
+ re:replace(L2, "\n"++Ss, "\n", [{return,list},global]).
+
+diaf(L, O0, Opts) ->
+ {R0, O} = diaf(L, [], O0, [], Opts),
+ R1 = rewrite_some_predefs(lists:reverse(R0)),
+ R = indentation(lists:flatten(R1)),
+ {R, O}.
+
+diaf([C | L], St, [C | O], R, Opts) ->
+ diaf(L, St, O, [[C] | R], Opts);
+diaf(" "++L, St, O, R, Opts) ->
+ diaf(L, St, O, R, Opts);
+diaf("", [Cs | St], O, R, Opts) ->
+ diaf(Cs, St, O, R, Opts);
+diaf("", [], O, R, _Opts) ->
+ {R, O};
+diaf(L, St, " "++O, R, Opts) ->
+ diaf(L, St, O, [" " | R], Opts);
+diaf(L, St, "\n"++O, R, Opts) ->
+ Ss = lists:takewhile(fun(C) -> C =:= $\s end, O),
+ diaf(L, St, lists:nthtail(length(Ss), O), ["\n"++Ss | R], Opts);
+diaf([{seealso, HRef0, S0} | L], St, O0, R, Opts) ->
+ {S, O} = diaf(S0, app_fix(O0), Opts),
+ HRef = fix_mod_ref(HRef0, Opts),
+ diaf(L, St, O, [{seealso, HRef, S} | R], Opts);
+diaf("="++L, St, "::"++O, R, Opts) ->
+ %% EDoc uses "=" for record field types; Dialyzer uses "::". Maybe
+ %% there should be an option for this, possibly affecting other
+ %% similar discrepancies.
+ diaf(L, St, O, ["=" | R], Opts);
+diaf([Cs | L], St, O, R, Opts) ->
+ diaf(Cs, [L | St], O, R, Opts).
+
+rewrite_some_predefs(S) ->
+ xpredef(lists:flatten(S)).
+
+xpredef([]) ->
+ [];
+xpredef("neg_integer()"++L) ->
+ ["integer() =< -1"] ++ xpredef(L);
+xpredef("non_neg_integer()"++L) ->
+ ["integer() >= 0"] ++ xpredef(L);
+xpredef("pos_integer()"++L) ->
+ ["integer() >= 1"] ++ xpredef(L);
+xpredef([T | Es]) when is_tuple(T) ->
+ [T | xpredef(Es)];
+xpredef([E | Es]) ->
+ [[E] | xpredef(Es)].
+
+indentation([]) ->
+ [];
+indentation([$\n|L]) ->
+ [{br,[]}|indent(L)];
+indentation([T | Es]) when is_tuple(T) ->
+ [T | indentation(Es)];
+indentation([E|L]) ->
+ [[E]|indentation(L)].
+
+indent([$\s|L]) ->
+ [{nbsp,[]}|indent(L)];
+indent(L) ->
+ indentation(L).
+
+app_fix(L) ->
+ try
+ {"//" ++ R1,L2} = app_fix(L, 1),
+ [App, Mod] = string:tokens(R1, "/"),
+ "//" ++ atom(App) ++ "/" ++ atom(Mod) ++ L2
+ catch _:_ -> L
+ end.
+
+app_fix(L, I) -> % a bit slow
+ {L1, L2} = lists:split(I, L),
+ case erl_scan:tokens([], L1 ++ ". ", 1) of
+ {done, {ok,[{atom,_,Atom}|_],_}, _} -> {atom_to_list(Atom), L2};
+ _ -> app_fix(L, I+1)
+ end.
+
+%% Remove the file suffix from module references.
+fix_mod_ref(HRef, #opts{file_suffix = ""}) ->
+ HRef;
+fix_mod_ref([{marker, S}]=HRef0, #opts{file_suffix = FS}) ->
+ {A, B} = lists:splitwith(fun(C) -> C =/= $# end, S),
+ case lists:member($:, A) of
+ true ->
+ HRef0; % should "save" most application references "http:"
+ false ->
+ case {lists:suffix(FS, A), B} of
+ {true, "#"++_} ->
+ [{marker, lists:sublist(A, length(A)-length(FS)) ++ B}];
+ _ ->
+ HRef0
+ end
+ end.
+
+see(E, Es) ->
+ case href(E) of
+ [] -> Es;
+ Ref ->
+ [{seealso, Ref, Es}]
+ end.
+
+href(E) ->
+ case get_attrval(href, E) of
+ "" -> [];
+ URI ->
+ [{marker, URI}]
+ end.
+
+atom(String) ->
+ io_lib:write_atom(list_to_atom(String)).
+
+t_name([E]) ->
+ N = get_attrval(name, E),
+ case get_attrval(module, E) of
+ "" -> atom(N);
+ M ->
+ S = atom(M) ++ ":" ++ atom(N),
+ case get_attrval(app, E) of
+ "" -> S;
+ A -> "//" ++ atom(A) ++ "/" ++ S
+ end
+ end.
+
+t_utype([E]) ->
+ t_utype_elem(E).
+
+t_utype_elem(E=#xmlElement{content = Es}) ->
+ case get_attrval(name, E) of
+ "" -> t_type(Es);
+ Name ->
+ T = t_type(Es),
+ case T of
+ [Name] -> T; % avoid generating "Foo::Foo"
+ T -> [Name] ++ ["::"] ++ T
+ end
+ end.
+
+t_type([E=#xmlElement{name = typevar}]) ->
+ t_var(E);
+t_type([E=#xmlElement{name = atom}]) ->
+ t_atom(E);
+t_type([E=#xmlElement{name = integer}]) ->
+ t_integer(E);
+t_type([E=#xmlElement{name = range}]) ->
+ t_range(E);
+t_type([E=#xmlElement{name = binary}]) ->
+ t_binary(E);
+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}]) ->
+ t_nonempty_list(Es);
+t_type([#xmlElement{name = tuple, content = Es}]) ->
+ t_tuple(Es);
+t_type([#xmlElement{name = 'fun', content = Es}]) ->
+ ["fun("] ++ t_fun(Es) ++ [")"];
+t_type([E = #xmlElement{name = record, content = Es}]) ->
+ t_record(E, Es);
+t_type([E = #xmlElement{name = abstype, content = Es}]) ->
+ t_abstype(E, Es);
+t_type([#xmlElement{name = union, content = Es}]) ->
+ t_union(Es).
+
+t_var(E) ->
+ [get_attrval(name, E)].
+
+t_atom(E) ->
+ [get_attrval(value, E)].
+
+t_integer(E) ->
+ [get_attrval(value, E)].
+
+t_range(E) ->
+ [get_attrval(value, E)].
+
+t_binary(E) ->
+ [get_attrval(value, E)].
+
+t_float(E) ->
+ [get_attrval(value, E)].
+
+t_nil() ->
+ ["[]"].
+
+t_paren(Es) ->
+ ["("] ++ t_utype(get_elem(type, Es)) ++ [")"].
+
+t_list(Es) ->
+ ["["] ++ t_utype(get_elem(type, Es)) ++ ["]"].
+
+t_nonempty_list(Es) ->
+ ["["] ++ t_utype(get_elem(type, Es)) ++ [", ...]"].
+
+t_tuple(Es) ->
+ ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]).
+
+t_fun(Es) ->
+ ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
+ [") -> "] ++ t_utype(get_elem(type, Es))).
+
+t_record(E, Es) ->
+ Name = ["#"] ++ t_type(get_elem(atom, Es)),
+ case get_elem(field, Es) of
+ [] ->
+ see(E, [Name, "{}"]);
+ Fs ->
+ see(E, Name) ++ ["{"] ++ seq(fun t_field/1, Fs, ["}"])
+ end.
+
+t_field(#xmlElement{content = Es}) ->
+ t_type(get_elem(atom, Es)) ++ [" = "] ++ t_utype(get_elem(type, Es)).
+
+t_abstype(E, Es) ->
+ Name = t_name(get_elem(erlangName, Es)),
+ case get_elem(type, Es) of
+ [] ->
+ see(E, [Name, "()"]);
+ Ts ->
+ see(E, [Name]) ++ ["("] ++ seq(fun t_utype_elem/1, Ts, [")"])
+ end.
+
+t_abstype(Es) ->
+ ([t_name(get_elem(erlangName, Es)), "("]
+ ++ seq(fun t_utype_elem/1, get_elem(type, Es), [")"])).
+
+t_union(Es) ->
+ seq(fun t_utype_elem/1, Es, " | ", []).
+
+seq(F, Es, Tail) ->
+ seq(F, Es, ", ", Tail).
+
+seq(F, [E], _Sep, Tail) ->
+ F(E) ++ Tail;
+seq(F, [E | Es], Sep, Tail) ->
+ F(E) ++ [Sep] ++ seq(F, Es, Sep, Tail);
+seq(_F, [], _Sep, Tail) ->
+ Tail.
+
+get_elem(Name, [#xmlElement{name = Name} = E | Es]) ->
+ [E | get_elem(Name, Es)];
+get_elem(Name, [_ | Es]) ->
+ get_elem(Name, Es);
+get_elem(_, []) ->
+ [].
+
+get_attr(Name, [#xmlAttribute{name = Name} = A | As]) ->
+ [A | get_attr(Name, As)];
+get_attr(Name, [_ | As]) ->
+ get_attr(Name, As);
+get_attr(_, []) ->
+ [].
+
+get_attrval(Name, #xmlElement{attributes = As}) ->
+ case get_attr(Name, As) of
+ [#xmlAttribute{value = V}] ->
+ V;
+ [] -> ""
+ end.
+
+get_content(Name, Es) ->
+ case get_elem(Name, Es) of
+ [#xmlElement{content = Es1}] ->
+ Es1;
+ [] -> []
+ end.
+
+overview(_, _Options) -> [].
+
+package(_, _Options) -> [].
+
+type(_) -> [].
+
+%% ---------------------------------------------------------------------
+
+ot_utype([E]) ->
+ ot_utype_elem(E).
+
+ot_utype_elem(E=#xmlElement{content = Es}) ->
+ case get_attrval(name, E) of
+ "" -> ot_type(Es);
+ N ->
+ Name = {var,0,list_to_atom(N)},
+ T = ot_type(Es),
+ case T of
+ Name -> T;
+ T -> {ann_type,0,[Name, T]}
+ end
+ end.
+
+ot_type([E=#xmlElement{name = typevar}]) ->
+ ot_var(E);
+ot_type([E=#xmlElement{name = atom}]) ->
+ ot_atom(E);
+ot_type([E=#xmlElement{name = integer}]) ->
+ ot_integer(E);
+ot_type([E=#xmlElement{name = range}]) ->
+ ot_range(E);
+ot_type([E=#xmlElement{name = binary}]) ->
+ ot_binary(E);
+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}]) ->
+ ot_nonempty_list(Es);
+ot_type([#xmlElement{name = tuple, content = Es}]) ->
+ ot_tuple(Es);
+ot_type([#xmlElement{name = 'fun', content = Es}]) ->
+ ot_fun(Es);
+ot_type([#xmlElement{name = record, content = Es}]) ->
+ ot_record(Es);
+ot_type([#xmlElement{name = abstype, content = Es}]) ->
+ ot_abstype(Es);
+ot_type([#xmlElement{name = union, content = Es}]) ->
+ ot_union(Es).
+
+ot_var(E) ->
+ {var,0,list_to_atom(get_attrval(name, E))}.
+
+ot_atom(E) ->
+ {ok, [Atom], _} = erl_scan:string(get_attrval(value, E), 0),
+ Atom.
+
+ot_integer(E) ->
+ {integer,0,list_to_integer(get_attrval(value, E))}.
+
+ot_range(E) ->
+ [I1, I2] = string:tokens(get_attrval(value, E), "."),
+ {type,0,range,[{integer,0,list_to_integer(I1)},
+ {integer,0,list_to_integer(I2)}]}.
+
+ot_binary(E) ->
+ {Base, Unit} =
+ case string:tokens(get_attrval(value, E), ",:*><") of
+ [] ->
+ {0, 0};
+ ["_",B] ->
+ {list_to_integer(B), 0};
+ ["_","_",U] ->
+ {0, list_to_integer(U)};
+ ["_",B,_,"_",U] ->
+ {list_to_integer(B), list_to_integer(U)}
+ end,
+ {type,0,binary,[{integer,0,Base},{integer,0,Unit}]}.
+
+ot_float(E) ->
+ {float,0,list_to_float(get_attrval(value, 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))]}.
+
+ot_nonempty_list(Es) ->
+ {type,0,nonempty_list,[ot_utype(get_elem(type, Es))]}.
+
+ot_tuple(Es) ->
+ {type,0,tuple,[ot_utype_elem(E) || E <- Es]}.
+
+ot_fun(Es) ->
+ Range = ot_utype(get_elem(type, Es)),
+ Args = [ot_utype_elem(A) || A <- get_content(argtypes, Es)],
+ {type,0,'fun',[{type,0,product,Args},Range]}.
+
+ot_record(Es) ->
+ {type,0,record,[ot_type(get_elem(atom, Es)) |
+ [ot_field(F) || F <- get_elem(field, Es)]]}.
+
+ot_field(#xmlElement{content = Es}) ->
+ {type,0,field_type,
+ [ot_type(get_elem(atom, Es)), ot_utype(get_elem(type, Es))]}.
+
+ot_abstype(Es) ->
+ ot_name(get_elem(erlangName, Es),
+ [ot_utype_elem(Elem) || Elem <- get_elem(type, Es)]).
+
+ot_union(Es) ->
+ {type,0,union,[ot_utype_elem(E) || E <- Es]}.
+
+ot_name(Es, T) ->
+ case ot_name(Es) of
+ [Mod, ":", Atom] ->
+ {remote_type,0,[{atom,0,list_to_atom(Mod)},
+ {atom,0,list_to_atom(Atom)},T]};
+ "tuple" when T =:= [] ->
+ {type,0,tuple,any};
+ Atom ->
+ {type,0,list_to_atom(Atom),T}
+ end.
+
+ot_name([E]) ->
+ Atom = get_attrval(name, E),
+ case get_attrval(module, E) of
+ "" -> Atom;
+ M ->
+ case get_attrval(app, E) of
+ "" ->
+ [M, ":", Atom];
+ A ->
+ ["//"++A++"/" ++ M, ":", Atom] % EDoc only!
+ end
+ end.
+
+%% Returns exactly those annotations that can be referred to. Note
+%% that a Dialyzer type/spec (currently) can have more annotations
+%% than can be represented by EDoc types. Note also that edoc_dia
+%% has annotated all type variables with themselves.
+typespec_annos([]) -> [?NL];
+typespec_annos([_|Es]) ->
+ annotations(clause_annos(Es)).
+
+clause_annos(Es) ->
+ [annos(get_elem(type, Es)), local_defs_annos(get_elem(localdef, Es))].
+
+typedef_annos(Es) ->
+ annotations([(case get_elem(type, Es) of
+ [] -> [];
+ T -> annos(T)
+ end
+ ++ lists:flatmap(fun annos_elem/1,
+ get_content(argtypes, Es))),
+ local_defs_annos(get_elem(localdef, Es))]).
+
+local_defs_annos(Es) ->
+ lists:flatmap(fun localdef_annos/1, Es).
+
+localdef_annos(#xmlElement{content = Es}) ->
+ annos(get_elem(type, Es)).
+
+annotations(AnnoL) ->
+ Annos = lists:usort(lists:flatten(AnnoL)),
+ margin(2, Annos).
+
+margin(N, L) ->
+ lists:append([[?IND(N),E] || E <- L]) ++ [?IND(N-2)].
+
+annos([E]) ->
+ annos_elem(E).
+
+annos_elem(E=#xmlElement{content = Es}) ->
+ case get_attrval(name, E) of
+ "" -> annos_type(Es);
+ "..." -> annos_type(Es); % compensate for a kludge in edoc_dia.erl
+ N ->
+ [{anno,[N]} | annos_type(Es)]
+ end.
+
+annos_type([#xmlElement{name = list, content = Es}]) ->
+ annos(get_elem(type, Es));
+annos_type([#xmlElement{name = nonempty_list, content = Es}]) ->
+ annos(get_elem(type, Es));
+annos_type([#xmlElement{name = tuple, content = Es}]) ->
+ lists:flatmap(fun annos_elem/1, Es);
+annos_type([#xmlElement{name = 'fun', content = Es}]) ->
+ (annos(get_elem(type, Es))
+ ++ lists:flatmap(fun annos_elem/1, get_content(argtypes, Es)));
+annos_type([#xmlElement{name = record, content = Es}]) ->
+ lists:append([annos(get_elem(type, Es1)) ||
+ #xmlElement{content = Es1} <- get_elem(field, Es)]);
+annos_type([#xmlElement{name = abstype, content = Es}]) ->
+ lists:flatmap(fun annos_elem/1, get_elem(type, Es));
+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/src/docgen_xmerl_xml_cb.erl b/lib/erl_docgen/src/docgen_xmerl_xml_cb.erl
new file mode 100644
index 0000000000..884932ed12
--- /dev/null
+++ b/lib/erl_docgen/src/docgen_xmerl_xml_cb.erl
@@ -0,0 +1,88 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See
+%% the Licence for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson AB.
+%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
+%% All Rights Reserved.��
+%%
+%% $Id$
+%%
+-module(docgen_xmerl_xml_cb).
+
+%% This is the callback module for exporting XHTML to an
+%% erlref or chapter document in XML format.
+%% See docgen_edoc_xml_cb.erl for further information.
+%%
+%% The origin of this file is the xmerl module xmerl_otpsgml.erl
+%% written by Ulf Wiger and Richard Carlsson.
+
+-export(['#xml-inheritance#'/0]).
+
+-export(['#root#'/4,
+ '#element#'/5,
+ '#text#'/1]).
+
+-include("xmerl.hrl").
+
+'#xml-inheritance#'() ->
+ [xmerl_xml].
+
+'#root#'(Data, _Attrs, [], _E) ->
+ ["<",DTD,">"] = hd(hd(Data)),
+ ["<?xml version=\"1.0\" encoding=\"latin1\" ?>\n",
+ "<!DOCTYPE "++DTD++" SYSTEM \""++DTD++".dtd\">\n",
+ Data].
+
+'#element#'(Tag, Data, Attrs, _Parents, _E) ->
+ {NewTag, NewAttrs} = convert_tag(Tag, Attrs),
+ xmerl_lib:markup(NewTag, NewAttrs, Data).
+
+'#text#'(Text) ->
+ xmerl_lib:export_text(Text).
+
+%% Utility functions
+
+convert_tag(a, [Attr]) ->
+ case Attr#xmlAttribute.name of
+ href ->
+ Val = Attr#xmlAttribute.value,
+ case is_url(Val) of
+ true ->
+ {url, [Attr]};
+ false ->
+ {seealso, [Attr#xmlAttribute{name=marker}]}
+ end;
+ name ->
+ {marker, [Attr#xmlAttribute{name=id}]}
+ end;
+convert_tag(b, Attrs) -> {em, Attrs};
+convert_tag(blockquote, Attrs) -> {quote, Attrs};
+convert_tag(code, Attrs) -> {c, Attrs};
+convert_tag(dd, Attrs) -> {item, Attrs};
+convert_tag(dl, Attrs) -> {taglist, Attrs};
+convert_tag(dt, Attrs) -> {tag, Attrs};
+convert_tag(li, Attrs) -> {item, Attrs};
+convert_tag(ol, Attrs) -> {list, Attrs};
+convert_tag(strong, Attrs) -> {em, Attrs};
+convert_tag(td, Attrs) -> {cell, Attrs};
+convert_tag(tr, Attrs) -> {row, Attrs};
+convert_tag(tt, Attrs) -> {c, Attrs};
+convert_tag(ul, Attrs) -> {list, Attrs};
+convert_tag(underline, Attrs) -> {em, Attrs};
+convert_tag(Tag, Attrs) -> {Tag, Attrs}.
+
+is_url("http:"++_) -> true;
+is_url("../"++_) -> true;
+is_url(FileRef) ->
+ case filename:extension(FileRef) of
+ "" -> false; % no extension = xml file
+ _Ext -> true % extension
+ end.
diff --git a/lib/erl_docgen/src/docgen_xml_check.erl b/lib/erl_docgen/src/docgen_xml_check.erl
new file mode 100644
index 0000000000..892a880269
--- /dev/null
+++ b/lib/erl_docgen/src/docgen_xml_check.erl
@@ -0,0 +1,45 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999-2000, Ericsson
+%% Utvecklings AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(docgen_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
+%% If XML validation fails for a file, the error information from
+%% Xmerl is printed to terminal and the function returns error.
+validate(File0) ->
+ File = case filename:extension(File0) of
+ ".xml" -> File0;
+ _ -> File0++".xml"
+ end,
+ case filelib:is_regular(File) of
+ true ->
+ DtdDir = filename:join(code:priv_dir(erl_docgen), "dtd"),
+ case catch xmerl_scan:file(File, [{validation,true},
+ {fetch_path,[DtdDir]}]) of
+ {'EXIT', Error} ->
+ io:format("~p~n", [Error]),
+ error;
+ {_Doc, _Misc} ->
+ ok
+ end;
+ false ->
+ {error, badfile}
+ end.
diff --git a/lib/erl_docgen/src/erl_docgen.app.src b/lib/erl_docgen/src/erl_docgen.app.src
index 1720464b6d..daad172106 100644
--- a/lib/erl_docgen/src/erl_docgen.app.src
+++ b/lib/erl_docgen/src/erl_docgen.app.src
@@ -1,7 +1,9 @@
{application, erl_docgen,
[{description, "Misc tools for building documentation"},
{vsn, "%VSN%"},
- {modules, [otp_specs
+ {modules, [docgen_otp_specs,
+ docgen_edoc_xml_cb,
+ docgen_xmerl_xml_cb
]
},
{registered,[]},
diff --git a/lib/erl_docgen/src/otp_specs.erl b/lib/erl_docgen/src/otp_specs.erl
deleted file mode 100644
index edb437a942..0000000000
--- a/lib/erl_docgen/src/otp_specs.erl
+++ /dev/null
@@ -1,713 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(otp_specs).
-
--export([module/2, package/2, overview/2, type/1]).
-
--include("xmerl.hrl").
-
--define(XML_EXPORT, xmerl_xml).
--define(DEFAULT_XML_EXPORT, ?XML_EXPORT).
--define(DEFAULT_PP, erl_pp).
--define(IND(N), #xmlText{value="\n" ++ lists:duplicate(N, $\s)}).
--define(NL, "\n").
-
-module(Element, Options) ->
- XML = layout_module(Element, init_opts(Options)),
- Export = proplists:get_value(xml_export, Options,
- ?DEFAULT_XML_EXPORT),
- xmerl:export_simple(XML, Export, [#xmlAttribute{name=prolog,
- value=""}]).
-
--record(opts, {pretty_print, file_suffix}).
-
-init_opts(Options) ->
- #opts{pretty_print = proplists:get_value(pretty_print,
- Options, ?DEFAULT_PP),
- %% It *is* depending on edoc.hrl!
- file_suffix = proplists:get_value(file_suffix, Options, ".html")}.
-
-layout_module(#xmlElement{name = module, content = Es}=E, Opts) ->
- Name = get_attrval(name, E),
- Functions = [{function_name(Elem), Elem} ||
- Elem <- get_content(functions, Es)],
- Types = [{type_name(Elem), Elem} || Elem <- get_content(typedecls, Es)],
- Body = [{module,
- [{name,[Name]}],
- ([?NL] ++ types(lists:sort(Types), Opts)
- ++ functions(lists:sort(Functions), Opts)
- ++ timestamp())}],
- Body.
-
-timestamp() ->
- [{timestamp, [io_lib:fwrite("Generated by EDoc, ~s, ~s.",
- [edoc_lib:datestr(date()),
- edoc_lib:timestr(time())])]},?NL].
-
-functions(Fs, Opts) ->
- lists:flatmap(fun ({Name, E}) -> function(Name, E, Opts) end, Fs).
-
-function(Name, #xmlElement{content = Es}, Opts) ->
- TS = get_content(typespec, Es),
- Spec = typespec(TS, Opts),
- [{spec,(Name
- ++ [?IND(2),{contract,Spec}]
- ++ typespec_annos(TS))},
- ?NL].
-
-function_name(E) ->
- [] = get_attrval(module, E),
- [?IND(2),{name,[atom(get_attrval(name, E))]},
- ?IND(2),{arity,[get_attrval(arity, E)]}].
-
-label_anchor(Content, E) ->
- case get_attrval(label, E) of
- "" -> Content;
- Ref -> [{marker, [{id, Ref}], Content}]
- end.
-
-typespec([], _Opts) -> [];
-typespec(Es, Opts) ->
- {Head, LDefs} = collect_clause(Es, Opts),
- clause(Head, LDefs) ++ [?IND(2)].
-
-collect_clause(Es, Opts) ->
- Name = t_name(get_elem(erlangName, Es)),
- Defs = get_elem(localdef, Es),
- [Type] = get_elem(type, Es),
- {format_spec(Name, Type, Opts), collect_local_defs(Defs, Opts)}.
-
-clause(Head, LDefs) ->
- FC = [?IND(6),{head,Head}] ++ local_clause_defs(LDefs),
- [?IND(4),{clause,FC}].
-
-local_clause_defs([]) -> [];
-local_clause_defs(LDefs) ->
- LocalDefs = [{subtype,T} || T <- coalesce_local_defs(LDefs, [])],
- [?IND(6),{guard,margin(8, LocalDefs)}].
-
-types(Ts, Opts) ->
- lists:flatmap(fun ({Name, E}) -> typedecl(Name, E, Opts) end, Ts).
-
-typedecl(Name, E=#xmlElement{content = Es}, Opts) ->
- TD = get_content(typedef, Es),
- TypeDef = typedef(E, TD, Opts),
- [{type,(Name
- ++ [?IND(2),{typedecl, TypeDef}]
- ++ typedef_annos(TD))},
- ?NL].
-
-type_name(#xmlElement{content = Es}) ->
- Typedef = get_content(typedef, Es),
- [E] = get_elem(erlangName, Typedef),
- Args = get_content(argtypes, Typedef),
- [] = get_attrval(module, E),
- [?IND(2),{name,[atom(get_attrval(name, E))]},
- ?IND(2),{n_vars,[integer_to_list(length(Args))]}].
-
-typedef(E, Es, Opts) ->
- Ns = get_elem(erlangName, Es),
- Name =
- ([t_name(Ns), "("]
- ++ seq(fun t_utype_elem/1, get_content(argtypes, Es), [")"])),
- LDefs = collect_local_defs(get_elem(localdef, Es), Opts),
- TypeHead = case get_elem(type, Es) of
- [] -> label_anchor(Name, E);
- Type -> (label_anchor(Name, E)
- ++ format_type(Name, Type, Opts))
- end,
- ([?IND(6),{typehead,TypeHead}]
- ++ local_type_defs(LDefs, [])).
-
-local_type_defs([], _) -> [];
-local_type_defs(LDefs, Last) ->
- LocalDefs = [{local_def,T} || T <- coalesce_local_defs(LDefs, Last)],
- [?IND(6),{local_defs,margin(8, LocalDefs)}].
-
-collect_local_defs(Es, Opts) ->
- [collect_localdef(E, Opts) || E <- Es].
-
-collect_localdef(E = #xmlElement{content = Es}, Opts) ->
- Name = case get_elem(typevar, Es) of
- [] ->
- label_anchor(N0 = t_abstype(get_content(abstype, Es)), E);
- [V] ->
- N0 = t_var(V)
- end,
- {Name,N0,format_type(N0, get_elem(type, Es), Opts)}.
-
-%% "A = t(), B = t()" is coalesced into "A = B = t()".
-%% Names as B above are kept, but the formated string is empty.
-coalesce_local_defs([], _Last) ->
- [];
-coalesce_local_defs([{Name,N0,TypeS} | L], Last) when Name =:= N0 ->
- cld(L, [{Name,N0}], TypeS, Last);
-coalesce_local_defs([{Name,N0,TypeS} | L], Last) ->
- [local_def(N0, Name, TypeS, Last, L) | coalesce_local_defs(L, Last)].
-
-cld([{Name,N0,TypeS} | L], Names, TypeS, Last) when Name =:= N0 ->
- cld(L, [{Name,N0} | Names], TypeS, Last);
-cld(L, Names0, TypeS, Last) ->
- Names = [{_,Name0} | Names1] = lists:reverse(Names0),
- NS = join([N || {N,_} <- Names], [" = "]),
- ([local_def(Name0, NS, TypeS, Last, L) |
- [local_def(N0, "", "", [], L) || {_,N0} <- Names1]]
- ++ coalesce_local_defs(L, Last)).
-
-local_def(Name, NS, TypeS, Last, L) ->
- [{typename,Name},{string,NS ++ TypeS ++ [Last || L =:= []]}].
-
-%% join([], Sep) when is_list(Sep) ->
-%% [];
-join([H|T], Sep) ->
- H ++ lists:append([Sep ++ X || X <- T]).
-
-%% Use the default formatting of EDoc, which creates references, and
-%% then insert newlines and indentation according to erl_pp (the
-%% (fast) Erlang pretty printer).
-format_spec(Name, Type, #opts{pretty_print = erl_pp}=Opts) ->
- try
- L = t_clause(Name, Type),
- O = pp_clause(Name, Type),
- {R, ".\n"} = diaf(L, O, Opts),
- R
- catch _:_ ->
- %% Example: "@spec ... -> record(a)"
- format_spec(Name, Type, Opts#opts{pretty_print=default})
- end;
-format_spec(Sep, Type, _Opts) ->
- t_clause(Sep, Type).
-
-t_clause(Name, Type) ->
- #xmlElement{content = [#xmlElement{name = 'fun', content = C}]} = Type,
- [Name] ++ t_fun(C).
-
-pp_clause(Pre, Type) ->
- Types = ot_utype([Type]),
- Atom = lists:duplicate(iolist_size(Pre), $a),
- L1 = erl_pp:attribute({attribute,0,spec,{{list_to_atom(Atom),0},[Types]}}),
- "-spec " ++ L2 = lists:flatten(L1),
- L3 = Pre ++ lists:nthtail(length(Atom), L2),
- re:replace(L3, "\n ", "\n", [{return,list},global]).
-
-format_type(Name, Type, #opts{pretty_print = erl_pp}=Opts) ->
- try
- L = t_utype(Type),
- O = pp_type(Name, Type),
- {R, ".\n"} = diaf(L, O, Opts),
- [" = "] ++ R
- catch _:_ ->
- %% Example: "t() = record(a)."
- format_type(Name, Type, Opts#opts{pretty_print=default})
- end;
-format_type(_Name, Type, _Opts) ->
- [" = "] ++ t_utype(Type).
-
-pp_type(Prefix, Type) ->
- Atom = list_to_atom(lists:duplicate(iolist_size(Prefix), $a)),
- L1 = erl_pp:attribute({attribute,0,type,{Atom,ot_utype(Type),[]}}),
- {L2,N} = case lists:dropwhile(fun(C) -> C =/= $: end, lists:flatten(L1)) of
- ":: " ++ L3 -> {L3,9}; % compensation for extra "()" and ":"
- "::\n" ++ L3 -> {"\n"++L3,6}
- end,
- Ss = lists:duplicate(N, $\s),
- re:replace(L2, "\n"++Ss, "\n", [{return,list},global]).
-
-diaf(L, O0, Opts) ->
- {R0, O} = diaf(L, [], O0, [], Opts),
- R1 = rewrite_some_predefs(lists:reverse(R0)),
- R = indentation(lists:flatten(R1)),
- {R, O}.
-
-diaf([C | L], St, [C | O], R, Opts) ->
- diaf(L, St, O, [[C] | R], Opts);
-diaf(" "++L, St, O, R, Opts) ->
- diaf(L, St, O, R, Opts);
-diaf("", [Cs | St], O, R, Opts) ->
- diaf(Cs, St, O, R, Opts);
-diaf("", [], O, R, _Opts) ->
- {R, O};
-diaf(L, St, " "++O, R, Opts) ->
- diaf(L, St, O, [" " | R], Opts);
-diaf(L, St, "\n"++O, R, Opts) ->
- Ss = lists:takewhile(fun(C) -> C =:= $\s end, O),
- diaf(L, St, lists:nthtail(length(Ss), O), ["\n"++Ss | R], Opts);
-diaf([{seealso, HRef0, S0} | L], St, O0, R, Opts) ->
- {S, O} = diaf(S0, app_fix(O0), Opts),
- HRef = fix_mod_ref(HRef0, Opts),
- diaf(L, St, O, [{seealso, HRef, S} | R], Opts);
-diaf("="++L, St, "::"++O, R, Opts) ->
- %% EDoc uses "=" for record field types; Dialyzer uses "::". Maybe
- %% there should be an option for this, possibly affecting other
- %% similar discrepancies.
- diaf(L, St, O, ["=" | R], Opts);
-diaf([Cs | L], St, O, R, Opts) ->
- diaf(Cs, [L | St], O, R, Opts).
-
-rewrite_some_predefs(S) ->
- xpredef(lists:flatten(S)).
-
-xpredef([]) ->
- [];
-xpredef("neg_integer()"++L) ->
- ["integer() =< -1"] ++ xpredef(L);
-xpredef("non_neg_integer()"++L) ->
- ["integer() >= 0"] ++ xpredef(L);
-xpredef("pos_integer()"++L) ->
- ["integer() >= 1"] ++ xpredef(L);
-xpredef([T | Es]) when is_tuple(T) ->
- [T | xpredef(Es)];
-xpredef([E | Es]) ->
- [[E] | xpredef(Es)].
-
-indentation([]) ->
- [];
-indentation([$\n|L]) ->
- [{br,[]}|indent(L)];
-indentation([T | Es]) when is_tuple(T) ->
- [T | indentation(Es)];
-indentation([E|L]) ->
- [[E]|indentation(L)].
-
-indent([$\s|L]) ->
- [{nbsp,[]}|indent(L)];
-indent(L) ->
- indentation(L).
-
-app_fix(L) ->
- try
- {"//" ++ R1,L2} = app_fix(L, 1),
- [App, Mod] = string:tokens(R1, "/"),
- "//" ++ atom(App) ++ "/" ++ atom(Mod) ++ L2
- catch _:_ -> L
- end.
-
-app_fix(L, I) -> % a bit slow
- {L1, L2} = lists:split(I, L),
- case erl_scan:tokens([], L1 ++ ". ", 1) of
- {done, {ok,[{atom,_,Atom}|_],_}, _} -> {atom_to_list(Atom), L2};
- _ -> app_fix(L, I+1)
- end.
-
-%% Remove the file suffix from module references.
-fix_mod_ref(HRef, #opts{file_suffix = ""}) ->
- HRef;
-fix_mod_ref([{marker, S}]=HRef0, #opts{file_suffix = FS}) ->
- {A, B} = lists:splitwith(fun(C) -> C =/= $# end, S),
- case lists:member($:, A) of
- true ->
- HRef0; % should "save" most application references "http:"
- false ->
- case {lists:suffix(FS, A), B} of
- {true, "#"++_} ->
- [{marker, lists:sublist(A, length(A)-length(FS)) ++ B}];
- _ ->
- HRef0
- end
- end.
-
-see(E, Es) ->
- case href(E) of
- [] -> Es;
- Ref ->
- [{seealso, Ref, Es}]
- end.
-
-href(E) ->
- case get_attrval(href, E) of
- "" -> [];
- URI ->
- [{marker, URI}]
- end.
-
-atom(String) ->
- io_lib:write_atom(list_to_atom(String)).
-
-t_name([E]) ->
- N = get_attrval(name, E),
- case get_attrval(module, E) of
- "" -> atom(N);
- M ->
- S = atom(M) ++ ":" ++ atom(N),
- case get_attrval(app, E) of
- "" -> S;
- A -> "//" ++ atom(A) ++ "/" ++ S
- end
- end.
-
-t_utype([E]) ->
- t_utype_elem(E).
-
-t_utype_elem(E=#xmlElement{content = Es}) ->
- case get_attrval(name, E) of
- "" -> t_type(Es);
- Name ->
- T = t_type(Es),
- case T of
- [Name] -> T; % avoid generating "Foo::Foo"
- T -> [Name] ++ ["::"] ++ T
- end
- end.
-
-t_type([E=#xmlElement{name = typevar}]) ->
- t_var(E);
-t_type([E=#xmlElement{name = atom}]) ->
- t_atom(E);
-t_type([E=#xmlElement{name = integer}]) ->
- t_integer(E);
-t_type([E=#xmlElement{name = range}]) ->
- t_range(E);
-t_type([E=#xmlElement{name = binary}]) ->
- t_binary(E);
-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}]) ->
- t_nonempty_list(Es);
-t_type([#xmlElement{name = tuple, content = Es}]) ->
- t_tuple(Es);
-t_type([#xmlElement{name = 'fun', content = Es}]) ->
- ["fun("] ++ t_fun(Es) ++ [")"];
-t_type([E = #xmlElement{name = record, content = Es}]) ->
- t_record(E, Es);
-t_type([E = #xmlElement{name = abstype, content = Es}]) ->
- t_abstype(E, Es);
-t_type([#xmlElement{name = union, content = Es}]) ->
- t_union(Es).
-
-t_var(E) ->
- [get_attrval(name, E)].
-
-t_atom(E) ->
- [get_attrval(value, E)].
-
-t_integer(E) ->
- [get_attrval(value, E)].
-
-t_range(E) ->
- [get_attrval(value, E)].
-
-t_binary(E) ->
- [get_attrval(value, E)].
-
-t_float(E) ->
- [get_attrval(value, E)].
-
-t_nil() ->
- ["[]"].
-
-t_paren(Es) ->
- ["("] ++ t_utype(get_elem(type, Es)) ++ [")"].
-
-t_list(Es) ->
- ["["] ++ t_utype(get_elem(type, Es)) ++ ["]"].
-
-t_nonempty_list(Es) ->
- ["["] ++ t_utype(get_elem(type, Es)) ++ [", ...]"].
-
-t_tuple(Es) ->
- ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]).
-
-t_fun(Es) ->
- ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
- [") -> "] ++ t_utype(get_elem(type, Es))).
-
-t_record(E, Es) ->
- Name = ["#"] ++ t_type(get_elem(atom, Es)),
- case get_elem(field, Es) of
- [] ->
- see(E, [Name, "{}"]);
- Fs ->
- see(E, Name) ++ ["{"] ++ seq(fun t_field/1, Fs, ["}"])
- end.
-
-t_field(#xmlElement{content = Es}) ->
- t_type(get_elem(atom, Es)) ++ [" = "] ++ t_utype(get_elem(type, Es)).
-
-t_abstype(E, Es) ->
- Name = t_name(get_elem(erlangName, Es)),
- case get_elem(type, Es) of
- [] ->
- see(E, [Name, "()"]);
- Ts ->
- see(E, [Name]) ++ ["("] ++ seq(fun t_utype_elem/1, Ts, [")"])
- end.
-
-t_abstype(Es) ->
- ([t_name(get_elem(erlangName, Es)), "("]
- ++ seq(fun t_utype_elem/1, get_elem(type, Es), [")"])).
-
-t_union(Es) ->
- seq(fun t_utype_elem/1, Es, " | ", []).
-
-seq(F, Es, Tail) ->
- seq(F, Es, ", ", Tail).
-
-seq(F, [E], _Sep, Tail) ->
- F(E) ++ Tail;
-seq(F, [E | Es], Sep, Tail) ->
- F(E) ++ [Sep] ++ seq(F, Es, Sep, Tail);
-seq(_F, [], _Sep, Tail) ->
- Tail.
-
-get_elem(Name, [#xmlElement{name = Name} = E | Es]) ->
- [E | get_elem(Name, Es)];
-get_elem(Name, [_ | Es]) ->
- get_elem(Name, Es);
-get_elem(_, []) ->
- [].
-
-get_attr(Name, [#xmlAttribute{name = Name} = A | As]) ->
- [A | get_attr(Name, As)];
-get_attr(Name, [_ | As]) ->
- get_attr(Name, As);
-get_attr(_, []) ->
- [].
-
-get_attrval(Name, #xmlElement{attributes = As}) ->
- case get_attr(Name, As) of
- [#xmlAttribute{value = V}] ->
- V;
- [] -> ""
- end.
-
-get_content(Name, Es) ->
- case get_elem(Name, Es) of
- [#xmlElement{content = Es1}] ->
- Es1;
- [] -> []
- end.
-
-overview(_, _Options) -> [].
-
-package(_, _Options) -> [].
-
-type(_) -> [].
-
-%% ---------------------------------------------------------------------
-
-ot_utype([E]) ->
- ot_utype_elem(E).
-
-ot_utype_elem(E=#xmlElement{content = Es}) ->
- case get_attrval(name, E) of
- "" -> ot_type(Es);
- N ->
- Name = {var,0,list_to_atom(N)},
- T = ot_type(Es),
- case T of
- Name -> T;
- T -> {ann_type,0,[Name, T]}
- end
- end.
-
-ot_type([E=#xmlElement{name = typevar}]) ->
- ot_var(E);
-ot_type([E=#xmlElement{name = atom}]) ->
- ot_atom(E);
-ot_type([E=#xmlElement{name = integer}]) ->
- ot_integer(E);
-ot_type([E=#xmlElement{name = range}]) ->
- ot_range(E);
-ot_type([E=#xmlElement{name = binary}]) ->
- ot_binary(E);
-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}]) ->
- ot_nonempty_list(Es);
-ot_type([#xmlElement{name = tuple, content = Es}]) ->
- ot_tuple(Es);
-ot_type([#xmlElement{name = 'fun', content = Es}]) ->
- ot_fun(Es);
-ot_type([#xmlElement{name = record, content = Es}]) ->
- ot_record(Es);
-ot_type([#xmlElement{name = abstype, content = Es}]) ->
- ot_abstype(Es);
-ot_type([#xmlElement{name = union, content = Es}]) ->
- ot_union(Es).
-
-ot_var(E) ->
- {var,0,list_to_atom(get_attrval(name, E))}.
-
-ot_atom(E) ->
- {ok, [Atom], _} = erl_scan:string(get_attrval(value, E), 0),
- Atom.
-
-ot_integer(E) ->
- {integer,0,list_to_integer(get_attrval(value, E))}.
-
-ot_range(E) ->
- [I1, I2] = string:tokens(get_attrval(value, E), "."),
- {type,0,range,[{integer,0,list_to_integer(I1)},
- {integer,0,list_to_integer(I2)}]}.
-
-ot_binary(E) ->
- {Base, Unit} =
- case string:tokens(get_attrval(value, E), ",:*><") of
- [] ->
- {0, 0};
- ["_",B] ->
- {list_to_integer(B), 0};
- ["_","_",U] ->
- {0, list_to_integer(U)};
- ["_",B,_,"_",U] ->
- {list_to_integer(B), list_to_integer(U)}
- end,
- {type,0,binary,[{integer,0,Base},{integer,0,Unit}]}.
-
-ot_float(E) ->
- {float,0,list_to_float(get_attrval(value, 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))]}.
-
-ot_nonempty_list(Es) ->
- {type,0,nonempty_list,[ot_utype(get_elem(type, Es))]}.
-
-ot_tuple(Es) ->
- {type,0,tuple,[ot_utype_elem(E) || E <- Es]}.
-
-ot_fun(Es) ->
- Range = ot_utype(get_elem(type, Es)),
- Args = [ot_utype_elem(A) || A <- get_content(argtypes, Es)],
- {type,0,'fun',[{type,0,product,Args},Range]}.
-
-ot_record(Es) ->
- {type,0,record,[ot_type(get_elem(atom, Es)) |
- [ot_field(F) || F <- get_elem(field, Es)]]}.
-
-ot_field(#xmlElement{content = Es}) ->
- {type,0,field_type,
- [ot_type(get_elem(atom, Es)), ot_utype(get_elem(type, Es))]}.
-
-ot_abstype(Es) ->
- ot_name(get_elem(erlangName, Es),
- [ot_utype_elem(Elem) || Elem <- get_elem(type, Es)]).
-
-ot_union(Es) ->
- {type,0,union,[ot_utype_elem(E) || E <- Es]}.
-
-ot_name(Es, T) ->
- case ot_name(Es) of
- [Mod, ":", Atom] ->
- {remote_type,0,[{atom,0,list_to_atom(Mod)},
- {atom,0,list_to_atom(Atom)},T]};
- "tuple" when T =:= [] ->
- {type,0,tuple,any};
- Atom ->
- {type,0,list_to_atom(Atom),T}
- end.
-
-ot_name([E]) ->
- Atom = get_attrval(name, E),
- case get_attrval(module, E) of
- "" -> Atom;
- M ->
- case get_attrval(app, E) of
- "" ->
- [M, ":", Atom];
- A ->
- ["//"++A++"/" ++ M, ":", Atom] % EDoc only!
- end
- end.
-
-%% Returns exactly those annotations that can be referred to. Note
-%% that a Dialyzer type/spec (currently) can have more annotations
-%% than can be represented by EDoc types. Note also that edoc_dia
-%% has annotated all type variables with themselves.
-typespec_annos([]) -> [?NL];
-typespec_annos([_|Es]) ->
- annotations(clause_annos(Es)).
-
-clause_annos(Es) ->
- [annos(get_elem(type, Es)), local_defs_annos(get_elem(localdef, Es))].
-
-typedef_annos(Es) ->
- annotations([(case get_elem(type, Es) of
- [] -> [];
- T -> annos(T)
- end
- ++ lists:flatmap(fun annos_elem/1,
- get_content(argtypes, Es))),
- local_defs_annos(get_elem(localdef, Es))]).
-
-local_defs_annos(Es) ->
- lists:flatmap(fun localdef_annos/1, Es).
-
-localdef_annos(#xmlElement{content = Es}) ->
- annos(get_elem(type, Es)).
-
-annotations(AnnoL) ->
- Annos = lists:usort(lists:flatten(AnnoL)),
- margin(2, Annos).
-
-margin(N, L) ->
- lists:append([[?IND(N),E] || E <- L]) ++ [?IND(N-2)].
-
-annos([E]) ->
- annos_elem(E).
-
-annos_elem(E=#xmlElement{content = Es}) ->
- case get_attrval(name, E) of
- "" -> annos_type(Es);
- "..." -> annos_type(Es); % compensate for a kludge in edoc_dia.erl
- N ->
- [{anno,[N]} | annos_type(Es)]
- end.
-
-annos_type([#xmlElement{name = list, content = Es}]) ->
- annos(get_elem(type, Es));
-annos_type([#xmlElement{name = nonempty_list, content = Es}]) ->
- annos(get_elem(type, Es));
-annos_type([#xmlElement{name = tuple, content = Es}]) ->
- lists:flatmap(fun annos_elem/1, Es);
-annos_type([#xmlElement{name = 'fun', content = Es}]) ->
- (annos(get_elem(type, Es))
- ++ lists:flatmap(fun annos_elem/1, get_content(argtypes, Es)));
-annos_type([#xmlElement{name = record, content = Es}]) ->
- lists:append([annos(get_elem(type, Es1)) ||
- #xmlElement{content = Es1} <- get_elem(field, Es)]);
-annos_type([#xmlElement{name = abstype, content = Es}]) ->
- lists:flatmap(fun annos_elem/1, get_elem(type, Es));
-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 79c8c570bf..bf10591f34 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1,2 +1,2 @@
-ERL_DOCGEN_VSN = 0.2.6
+ERL_DOCGEN_VSN = 0.3.1
diff --git a/lib/erl_interface/aclocal.m4 b/lib/erl_interface/aclocal.m4
index 151fd5ea5a..a76594d86f 120000..100644
--- a/lib/erl_interface/aclocal.m4
+++ b/lib/erl_interface/aclocal.m4
@@ -1 +1,1872 @@
-../../erts/aclocal.m4 \ No newline at end of file
+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
+
+AC_DEFUN(LM_PRECIOUS_VARS,
+[
+
+dnl ERL_TOP
+AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory])
+
+dnl Tools
+AC_ARG_VAR(CC, [C compiler])
+AC_ARG_VAR(CFLAGS, [C compiler flags])
+AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags])
+AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler])
+AC_ARG_VAR(CPP, [C/C++ preprocessor])
+AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags])
+AC_ARG_VAR(CXX, [C++ compiler])
+AC_ARG_VAR(CXXFLAGS, [C++ compiler flags])
+AC_ARG_VAR(LD, [linker (is often overridden by configure)])
+AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overriden by configure)])
+AC_ARG_VAR(LIBS, [libraries])
+AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)])
+AC_ARG_VAR(RANLIB, [ranlib])
+AC_ARG_VAR(AR, [ar])
+AC_ARG_VAR(GETCONF, [getconf])
+
+dnl Cross system root
+AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)])
+
+dnl Cross compilation variables
+AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for retrieving process CPU time: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+
+])
+
+AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
+[
+erl_xcomp_without_sysroot=no
+if test "$cross_compiling" = "yes"; then
+ test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes
+ test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot"
+else
+ erl_xcomp_sysroot=
+ erl_xcomp_isysroot=
+fi
+])
+
+AC_DEFUN(LM_CHECK_GETCONF,
+[
+if test "$cross_compiling" != "yes"; then
+ AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false])
+else
+ dnl First check if we got a `<HOST>-getconf' in $PATH
+ host_getconf="$host_alias-getconf"
+ AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false])
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ dnl We should perhaps give up if we have'nt found it by now, but at
+ dnl least in one Tilera MDE `getconf' under sysroot is a bourne
+ dnl shell script which we can use. We try to find `<HOST>-getconf'
+ dnl or `getconf' under sysconf, but only under sysconf since
+ dnl `getconf' in $PATH is almost guaranteed to be for the build
+ dnl machine.
+ GETCONF=
+ prfx="$erl_xcomp_sysroot"
+ AC_PATH_TOOL([GETCONF], [getconf], [false],
+ ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
+ fi
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_WINDOWS_ENVIRONMENT
+dnl
+dnl
+dnl Tries to determine thw windows build environment, i.e.
+dnl MIXED_CYGWIN_VC or MIXED_MSYS_VC
+dnl
+
+AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
+[
+MIXED_CYGWIN=no
+MIXED_MSYS=no
+
+AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment)
+if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_CYGWIN_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
+ elif test -x /usr/bin/msysinfo; then
+ CFLAGS="-O2"
+ MIXED_MSYS=yes
+ AC_MSG_RESULT([MSYS and VC])
+ MIXED_MSYS_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_VC=no
+ MIXED_MSYS_VC=no
+fi
+AC_SUBST(MIXED_CYGWIN_VC)
+AC_SUBST(MIXED_MSYS_VC)
+
+MIXED_VC=no
+if test "x$MIXED_MSYS_VC" = "xyes" -o "x$MIXED_CYGWIN_VC" = "xyes" ; then
+ MIXED_VC=yes
+fi
+
+AC_SUBST(MIXED_VC)
+
+if test "x$MIXED_MSYS" != "xyes"; then
+ AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
+ if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([yes])
+ MIXED_CYGWIN_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_MINGW=no
+ fi
+else
+ MIXED_CYGWIN_MINGW=no
+fi
+AC_SUBST(MIXED_CYGWIN_MINGW)
+
+AC_MSG_CHECKING(if we mix cygwin with any native compiler)
+if test "X$MIXED_CYGWIN" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_CYGWIN)
+
+AC_MSG_CHECKING(if we mix msys with another native compiler)
+if test "X$MIXED_MSYS" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_MSYS)
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_FIND_EMU_CC
+dnl
+dnl
+dnl Tries fairly hard to find a C compiler that can handle jump tables.
+dnl Defines the @EMU_CC@ variable for the makefiles and
+dnl inserts NO_JUMP_TABLE in the header if one cannot be found...
+dnl
+
+AC_DEFUN(LM_FIND_EMU_CC,
+ [AC_CACHE_CHECK(for a compiler that handles jumptables,
+ ac_cv_prog_emu_cc,
+ [
+AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+lbl1:
+ return 1;
+lbl2:
+ return 2;
+],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+
+if test $ac_cv_prog_emu_cc = no; then
+ for ac_progname in emu_cc.sh gcc-4.2 gcc; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_progname; then
+ ac_cv_prog_emu_cc=$ac_dir/$ac_progname
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ if test $ac_cv_prog_emu_cc != no; then
+ break
+ fi
+ done
+fi
+
+if test $ac_cv_prog_emu_cc != no; then
+ save_CC=$CC
+ save_CFLAGS=$CFLAGS
+ save_CPPFLAGS=$CPPFLAGS
+ CC=$ac_cv_prog_emu_cc
+ CFLAGS=""
+ CPPFLAGS=""
+ AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+ lbl1:
+ return 1;
+ lbl2:
+ return 2;
+ ],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+ CC=$save_CC
+ CFLAGS=$save_CFLAGS
+ CPPFLAGS=$save_CPPFLAGS
+fi
+])
+if test $ac_cv_prog_emu_cc = no; then
+ AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables])
+ EMU_CC=$CC
+else
+ EMU_CC=$ac_cv_prog_emu_cc
+fi
+AC_SUBST(EMU_CC)
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_INSTALL_DIR
+dnl
+dnl This macro may be used by any OTP application.
+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
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_PERL5
+dnl
+dnl Try to find perl version 5. If found set PERL to the absolute path
+dnl of the program, if not found set PERL to false.
+dnl
+dnl On some systems /usr/bin/perl is perl 4 and e.g.
+dnl /usr/local/bin/perl is perl 5. We try to handle this case by
+dnl putting a couple of
+dnl Tries to handle the case that there are two programs called perl
+dnl in the path and one of them is perl 5 and the other isn't.
+dnl
+AC_DEFUN(LM_PROG_PERL5,
+[AC_PATH_PROGS(PERL, perl5 perl, false,
+ /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH})
+changequote(, )dnl
+dnl[ That bracket is needed to balance the right bracket below
+if test "$PERL" = "false" || $PERL -e 'exit ($] >= 5)'; then
+changequote([, ])dnl
+ ac_cv_path_PERL=false
+ PERL=false
+dnl AC_MSG_WARN(perl version 5 not found)
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SO_BSDCOMPAT
+dnl
+dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux)
+dnl
+AC_DEFUN(LM_DECL_SO_BSDCOMPAT,
+[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat,
+AC_TRY_COMPILE([#include <sys/socket.h>], [int i = SO_BSDCOMPAT;],
+ ac_cv_decl_so_bsdcompat=yes,
+ ac_cv_decl_so_bsdcompat=no))
+
+case "${ac_cv_decl_so_bsdcompat}" in
+ "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[],
+ [Define if you have SO_BSDCOMPAT flag on sockets]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_INADDR_LOOPBACK
+dnl
+dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default
+dnl
+
+AC_DEFUN(LM_DECL_INADDR_LOOPBACK,
+[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h],
+ ac_cv_decl_inaddr_loopback,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>], [int i = INADDR_LOOPBACK;],
+ac_cv_decl_inaddr_loopback=yes, ac_cv_decl_inaddr_loopback=no)
+])
+
+if test ${ac_cv_decl_inaddr_loopback} = no; then
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h],
+ ac_cv_decl_inaddr_loopback_rpc,
+ AC_TRY_COMPILE([#include <rpc/types.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_rpc=yes,
+ ac_cv_decl_inaddr_loopback_rpc=no))
+
+ case "${ac_cv_decl_inaddr_loopback_rpc}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
+ [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h],
+ ac_cv_decl_inaddr_loopback_winsock2,
+ AC_TRY_COMPILE([#define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_winsock2=yes,
+ ac_cv_decl_inaddr_loopback_winsock2=no))
+ case "${ac_cv_decl_inaddr_loopback_winsock2}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[],
+ [Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ # couldn't find it anywhere
+ AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[],
+ [Define if you don't have a definition of INADDR_LOOPBACK]) ;;
+ esac;;
+ esac
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_SOCKADDR_SA_LEN
+dnl
+dnl Check if the sockaddr structure has the field sa_len
+dnl
+
+AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN,
+[AC_CACHE_CHECK([whether struct sockaddr has sa_len field],
+ ac_cv_struct_sockaddr_sa_len,
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>], [struct sockaddr s; s.sa_len = 10;],
+ ac_cv_struct_sockaddr_sa_len=yes, ac_cv_struct_sockaddr_sa_len=no))
+
+dnl FIXME convbreak
+case ${ac_cv_struct_sockaddr_sa_len} in
+ "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;;
+ *) ;;
+esac
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_EXCEPTION
+dnl
+dnl Check to see whether the system supports the matherr function
+dnl and its associated type "struct exception".
+dnl
+
+AC_DEFUN(LM_STRUCT_EXCEPTION,
+[AC_CACHE_CHECK([for struct exception (and matherr function)],
+ ac_cv_struct_exception,
+AC_TRY_COMPILE([#include <math.h>],
+ [struct exception x; x.type = DOMAIN; x.type = SING;],
+ ac_cv_struct_exception=yes, ac_cv_struct_exception=no))
+
+case "${ac_cv_struct_exception}" in
+ "yes" ) AC_DEFINE(USE_MATHERR,[1],[Define if you have matherr() function and struct exception type]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_IPV6
+dnl
+dnl Check for ipv6 support and what the in6_addr structure is called.
+dnl (early linux used in_addr6 insted of in6_addr)
+dnl
+
+AC_DEFUN(LM_SYS_IPV6,
+[AC_MSG_CHECKING(for IP version 6 support)
+AC_CACHE_VAL(ac_cv_sys_ipv6_support,
+[ok_so_far=yes
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no)
+
+if test $ok_so_far = yes; then
+ ac_cv_sys_ipv6_support=yes
+else
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in_addr6 a6; struct sockaddr_in6 s6;],
+ ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no)
+fi
+])dnl
+
+dnl
+dnl Have to use old style AC_DEFINE due to BC with old autoconf.
+dnl
+
+case ${ac_cv_sys_ipv6_support} in
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ ;;
+ in_addr6)
+ AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)])
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this])
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_MULTICAST
+dnl
+dnl Check for multicast support. Only checks for multicast options in
+dnl setsockopt(), no check is performed that multicasting actually works.
+dnl If options are found defines HAVE_MULTICAST_SUPPORT
+dnl
+
+AC_DEFUN(LM_SYS_MULTICAST,
+[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
+[AC_EGREP_CPP(yes,
+[#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP)
+yes
+#endif
+], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)])
+if test $ac_cv_sys_multicast_support = yes; then
+ AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1],
+ [Define if setsockopt() accepts multicast options])
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SYS_ERRLIST
+dnl
+dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared
+dnl in a system header file, stdio.h or errno.h.
+dnl
+
+AC_DEFUN(LM_DECL_SYS_ERRLIST,
+[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h],
+ ac_cv_decl_sys_errlist,
+[AC_TRY_COMPILE([#include <stdio.h>
+#include <errno.h>], [char *msg = *(sys_errlist + 1);],
+ ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)])
+if test $ac_cv_decl_sys_errlist = yes; then
+ AC_DEFINE(SYS_ERRLIST_DECLARED,[],
+ [define if the variable sys_errlist is declared in a system header file])
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes
+dnl [, action-if-found [, action-if-not-found]]] )
+dnl
+dnl Checks if the declaration "declaration" of "funname" conflicts
+dnl with the header files idea of how the function should be
+dnl declared. It is useful on systems which lack prototypes and you
+dnl need to provide your own (e.g. when you want to take the address
+dnl of a function). The 4'th argument is expanded if conflicting,
+dnl the 5'th argument otherwise
+dnl
+dnl
+
+AC_DEFUN(LM_CHECK_FUNC_DECL,
+[AC_MSG_CHECKING([for conflicting declaration of $1])
+AC_CACHE_VAL(ac_cv_func_decl_$1,
+[AC_TRY_COMPILE([#include <stdio.h>
+$3],[$2
+char *c = (char *)$1;
+], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")])
+if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$4], , :, [$4])
+else
+ AC_MSG_RESULT(no)
+ifelse([$5], , , [$5
+])dnl
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl AC_DOUBLE_MIDDLE_ENDIAN
+dnl
+dnl Checks whether doubles are represented in "middle-endian" format.
+dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
+dnl as well as DOUBLE_MIDDLE_ENDIAN.
+dnl
+dnl
+
+AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
+[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
+[# It does not; compile a test program.
+AC_RUN_IFELSE(
+[AC_LANG_SOURCE([[#include <stdlib.h>
+
+int
+main(void)
+{
+ int i = 0;
+ int zero = 0;
+ int bigendian;
+ int zero_index = 0;
+
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+
+ /* we'll use the one with 32-bit words */
+ union
+ {
+ double d;
+ unsigned int c[2];
+ } vint;
+
+ union
+ {
+ double d;
+ unsigned long c[2];
+ } vlong;
+
+ union
+ {
+ double d;
+ unsigned short c[2];
+ } vshort;
+
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ u.l = 1;
+ bigendian = (u.c[sizeof (long int) - 1] == 1);
+
+ zero_index = bigendian ? 1 : 0;
+
+ vint.d = 1.0;
+ vlong.d = 1.0;
+ vshort.d = 1.0;
+
+ if (sizeof(unsigned int) == 4)
+ {
+ if (vint.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned long) == 4)
+ {
+ if (vlong.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned short) == 4)
+ {
+ if (vshort.c[zero_index] != 0)
+ zero = 1;
+ }
+
+ exit (zero);
+}
+]])],
+ [ac_cv_c_double_middle_endian=no],
+ [ac_cv_c_double_middle_endian=yes],
+ [ac_cv_c_double_middle=unknown])])
+case $ac_cv_c_double_middle_endian in
+ yes)
+ m4_default([$1],
+ [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
+ [Define to 1 if your processor stores the words in a double in
+ middle-endian format (like some ARMs).])]) ;;
+ no)
+ $2 ;;
+ *)
+ m4_default([$3],
+ [AC_MSG_WARN([unknown double endianness
+presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
+esac
+])# AC_C_DOUBLE_MIDDLE_ENDIAN
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_THR_LIB
+dnl
+dnl This macro may be used by any OTP application.
+dnl
+dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also
+dnl checks for some pthread headers which will appear in DEFS or config.h.
+dnl
+
+AC_DEFUN(LM_CHECK_THR_LIB,
+[
+
+NEED_NPTL_PTHREAD_H=no
+
+dnl win32?
+AC_MSG_CHECKING([for native win32 threads])
+if test "X$host_os" = "Xwin32"; then
+ AC_MSG_RESULT(yes)
+ THR_DEFS="-DWIN32_THREADS"
+ THR_LIBS=
+ THR_LIB_NAME=win32_threads
+ THR_LIB_TYPE=win32_threads
+else
+ AC_MSG_RESULT(no)
+ THR_DEFS=
+ THR_LIBS=
+ THR_LIB_NAME=
+ THR_LIB_TYPE=posix_unknown
+
+dnl Try to find POSIX threads
+
+dnl The usual pthread lib...
+ AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
+
+dnl FreeBSD has pthreads in special c library, c_r...
+ if test "x$THR_LIBS" = "x"; then
+ AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r")
+ fi
+
+dnl On ofs1 the '-pthread' switch should be used
+ if test "x$THR_LIBS" = "x"; then
+ AC_MSG_CHECKING([if the '-pthread' switch can be used])
+ saved_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -pthread"
+ AC_TRY_LINK([#include <pthread.h>],
+ pthread_create((void*)0,(void*)0,(void*)0,(void*)0);,
+ [THR_DEFS="-pthread"
+ THR_LIBS="-pthread"])
+ CFLAGS=$saved_cflags
+ if test "x$THR_LIBS" != "x"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ if test "x$THR_LIBS" != "x"; then
+ THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
+ THR_LIB_NAME=pthread
+ case $host_os in
+ solaris*)
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
+ linux*)
+ THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
+
+ LM_CHECK_GETCONF
+ AC_MSG_CHECKING(for Native POSIX Thread Library)
+ libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
+ if test $? -eq 0; then
+ case "$libpthr_vsn" in
+ *nptl*|*NPTL*) nptl=yes;;
+ *) nptl=no;;
+ esac
+ elif test "$cross_compiling" = "yes"; then
+ case "$erl_xcomp_linux_nptl" in
+ "") nptl=cross;;
+ yes|no) nptl=$erl_xcomp_linux_nptl;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);;
+ esac
+ else
+ nptl=no
+ fi
+ AC_MSG_RESULT($nptl)
+ if test $nptl = cross; then
+ nptl=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $nptl = yes; then
+ THR_LIB_TYPE=posix_nptl
+ need_nptl_incldir=no
+ AC_CHECK_HEADER(nptl/pthread.h,
+ [need_nptl_incldir=yes
+ NEED_NPTL_PTHREAD_H=yes])
+ if test $need_nptl_incldir = yes; then
+ # Ahh...
+ nptl_path="$C_INCLUDE_PATH:$CPATH"
+ if test X$cross_compiling != Xyes; then
+ nptl_path="$nptl_path:/usr/local/include:/usr/include"
+ else
+ IROOT="$erl_xcomp_isysroot"
+ test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot"
+ test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot])
+ nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include"
+ fi
+ nptl_ws_path=
+ save_ifs="$IFS"; IFS=":"
+ for dir in $nptl_path; do
+ if test "x$dir" != "x"; then
+ nptl_ws_path="$nptl_ws_path $dir"
+ fi
+ done
+ IFS=$save_ifs
+ nptl_incldir=
+ for dir in $nptl_ws_path; do
+ AC_CHECK_HEADER($dir/nptl/pthread.h,
+ nptl_incldir=$dir/nptl)
+ if test "x$nptl_incldir" != "x"; then
+ THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
+ break
+ fi
+ done
+ if test "x$nptl_incldir" = "x"; then
+ AC_MSG_ERROR(Failed to locate nptl system include directory)
+ fi
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need THR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $THR_DEFS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h,
+ AC_DEFINE(HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ fi
+fi
+
+])
+
+AC_DEFUN(ERL_INTERNAL_LIBS,
+[
+
+ERTS_INTERNAL_X_LIBS=
+
+AC_CHECK_LIB(kstat, kstat_open,
+[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat])
+ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"])
+
+AC_SUBST(ERTS_INTERNAL_X_LIBS)
+
+])
+
+AC_DEFUN(ETHR_CHK_SYNC_OP,
+[
+ AC_MSG_CHECKING([for $3-bit $1()])
+ case "$2" in
+ "1") sync_call="$1(&var);";;
+ "2") sync_call="$1(&var, ($4) 0);";;
+ "3") sync_call="$1(&var, ($4) 0, ($4) 0);";;
+ esac
+ have_sync_op=no
+ AC_TRY_LINK([],
+ [
+ $4 res;
+ volatile $4 var;
+ res = $sync_call
+ ],
+ [have_sync_op=yes])
+ test $have_sync_op = yes && $5
+ AC_MSG_RESULT([$have_sync_op])
+])
+
+AC_DEFUN(ETHR_CHK_INTERLOCKED,
+[
+ ilckd="$1"
+ AC_MSG_CHECKING([for ${ilckd}()])
+ case "$2" in
+ "1") ilckd_call="${ilckd}(var);";;
+ "2") ilckd_call="${ilckd}(var, ($3) 0);";;
+ "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
+ "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
+ esac
+ have_interlocked_op=no
+ AC_TRY_LINK(
+ [
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <intrin.h>
+ ],
+ [
+ volatile $3 *var;
+ volatile $3 arr[2];
+
+ $ilckd_call
+ return 0;
+ ],
+ [have_interlocked_op=yes])
+ test $have_interlocked_op = yes && $4
+ AC_MSG_RESULT([$have_interlocked_op])
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_FIND_ETHR_LIB
+dnl
+dnl NOTE! This macro may be changed at any time! Should *only* be used by
+dnl ERTS!
+dnl
+dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link
+dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS
+dnl except that the ethread lib itself is not included), ETHR_DEFS to
+dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the
+dnl thread library which the ethread library is based on, and ETHR_LIB_NAME
+dnl to the name of the library where the ethread implementation is located.
+dnl ERL_FIND_ETHR_LIB currently searches for 'pthreads', and
+dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS,
+dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the
+dnl empty string.
+dnl
+
+AC_DEFUN(ERL_FIND_ETHR_LIB,
+[
+
+LM_CHECK_THR_LIB
+ERL_INTERNAL_LIBS
+
+ethr_have_native_atomics=no
+ethr_have_native_spinlock=no
+ETHR_THR_LIB_BASE="$THR_LIB_NAME"
+ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
+ETHR_DEFS="$THR_DEFS"
+ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS"
+ETHR_LIBS=
+ETHR_LIB_NAME=
+
+ethr_modified_default_stack_size=
+
+dnl Name of lib where ethread implementation is located
+ethr_lib_name=ethread
+
+case "$THR_LIB_NAME" in
+
+ win32_threads)
+ ETHR_THR_LIB_BASE_DIR=win
+ # * _WIN32_WINNT >= 0x0400 is needed for
+ # TryEnterCriticalSection
+ # * _WIN32_WINNT >= 0x0403 is needed for
+ # InitializeCriticalSectionAndSpinCount
+ # The ethread lib will refuse to build if _WIN32_WINNT < 0x0403.
+ #
+ # -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it
+ # and save it in ETHR_DEFS.
+ found_win32_winnt=no
+ for cppflag in $CPPFLAGS; do
+ case $cppflag in
+ -DWINVER*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ ;;
+ -D_WIN32_WINNT*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ found_win32_winnt=yes
+ ;;
+ *)
+ ;;
+ esac
+ done
+ if test $found_win32_winnt = no; then
+ AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS])
+ fi
+
+ AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
+
+ test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes
+ ;;
+
+ pthread)
+ ETHR_THR_LIB_BASE_DIR=pthread
+ AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
+ case $host_os in
+ openbsd*)
+ # The default stack size is insufficient for our needs
+ # on OpenBSD. We increase it to 256 kilo words.
+ ethr_modified_default_stack_size=256;;
+ linux*)
+ ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE"
+
+ if test X$cross_compiling = Xyes; then
+ case X$erl_xcomp_linux_usable_sigusrx in
+ X) usable_sigusrx=cross;;
+ Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);;
+ esac
+ case X$erl_xcomp_linux_usable_sigaltstack in
+ X) usable_sigaltstack=cross;;
+ Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);;
+ esac
+ else
+ # FIXME: Test for actual problems instead of kernel versions
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-1]]|2.[[0-1]].*)
+ usable_sigusrx=no
+ usable_sigaltstack=no;;
+ 2.[[2-3]]|2.[[2-3]].*)
+ usable_sigusrx=yes
+ usable_sigaltstack=no;;
+ *)
+ usable_sigusrx=yes
+ usable_sigaltstack=yes;;
+ esac
+ fi
+
+ AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used)
+ AC_MSG_RESULT($usable_sigusrx)
+ if test $usable_sigusrx = cross; then
+ usable_sigusrx=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigusrx = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
+ fi
+
+ AC_MSG_CHECKING(if sigaltstack can be used)
+ AC_MSG_RESULT($usable_sigaltstack)
+ if test $usable_sigaltstack = cross; then
+ usable_sigaltstack=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigaltstack = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need ETHR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $ETHR_DEFS"
+
+ dnl We need the thread library in order to find some functions
+ saved_libs="$LIBS"
+ LIBS="$LIBS $ETHR_X_LIBS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ if test $NEED_NPTL_PTHREAD_H = yes; then
+ AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \
+[Define if you need the <nptl/pthread.h> header file.])
+ fi
+
+ AC_CHECK_HEADER(sched.h, \
+ AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \
+[Define if you have the <sched.h> header file.]))
+
+ AC_CHECK_HEADER(sys/time.h, \
+ AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \
+[Define if you have the <sys/time.h> header file.]))
+
+ AC_TRY_COMPILE([#include <time.h>
+ #include <sys/time.h>],
+ [struct timeval *tv; return 0;],
+ AC_DEFINE(ETHR_TIME_WITH_SYS_TIME, 1, \
+[Define if you can safely include both <sys/time.h> and <time.h>.]))
+
+
+ dnl
+ dnl Check for functions
+ dnl
+
+ AC_CHECK_FUNC(pthread_spin_lock, \
+ [ethr_have_native_spinlock=yes \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
+[Define if you have the pthread_spin_lock function.])])
+
+ have_sched_yield=no
+ have_librt_sched_yield=no
+ AC_CHECK_FUNC(sched_yield, [have_sched_yield=yes])
+ if test $have_sched_yield = no; then
+ AC_CHECK_LIB(rt, sched_yield,
+ [have_librt_sched_yield=yes
+ ETHR_X_LIBS="$ETHR_X_LIBS -lrt"])
+ fi
+ if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.])
+ AC_MSG_CHECKING([whether sched_yield() returns an int])
+ sched_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #ifdef ETHR_HAVE_SCHED_H
+ #include <sched.h>
+ #endif
+ ],
+ [int sched_yield();],
+ [sched_yield_ret_int=yes])
+ AC_MSG_RESULT([$sched_yield_ret_int])
+ if test $sched_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_yield=no
+ AC_CHECK_FUNC(pthread_yield, [have_pthread_yield=yes])
+ if test $have_pthread_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.])
+ AC_MSG_CHECKING([whether pthread_yield() returns an int])
+ pthread_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [int pthread_yield();],
+ [pthread_yield_ret_int=yes])
+ AC_MSG_RESULT([$pthread_yield_ret_int])
+ if test $pthread_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_rwlock_init=no
+ AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes])
+ if test $have_pthread_rwlock_init = yes; then
+
+ ethr_have_pthread_rwlockattr_setkind_np=no
+ AC_CHECK_FUNC(pthread_rwlockattr_setkind_np,
+ [ethr_have_pthread_rwlockattr_setkind_np=yes])
+
+ if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \
+[Define if you have the pthread_rwlockattr_setkind_np() function.])
+
+ AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP])
+ ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
+ AC_TRY_LINK([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [
+ pthread_rwlockattr_t *attr;
+ return pthread_rwlockattr_setkind_np(attr,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+ ],
+ [ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes])
+ AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np])
+ if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \
+[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.])
+ fi
+ fi
+ fi
+
+ if test "$force_pthread_rwlocks" = "yes"; then
+
+ AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \
+[Define if you want to force usage of pthread rwlocks])
+
+ if test $have_pthread_rwlock_init = yes; then
+ AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.])
+ else
+ AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found])
+ fi
+ fi
+
+ AC_CHECK_FUNC(pthread_attr_setguardsize, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
+[Define if you have the pthread_attr_setguardsize function.]))
+
+ linux_futex=no
+ AC_MSG_CHECKING([for Linux futexes])
+ AC_TRY_LINK([
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <linux/futex.h>
+ #include <sys/time.h>
+ ],
+ [
+ int i = 1;
+ syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
+ (void*)0,(void*)0, 0);
+ syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
+ (void*)0,(void*)0, 0);
+ return 0;
+ ],
+ linux_futex=yes)
+ AC_MSG_RESULT([$linux_futex])
+ test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
+
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(long long)
+ AC_CHECK_SIZEOF(__int128_t)
+
+ if test "$ac_cv_sizeof_int" = "4"; then
+ int32="int"
+ elif test "$ac_cv_sizeof_long" = "4"; then
+ int32="long"
+ elif test "$ac_cv_sizeof_long_long" = "4"; then
+ int32="long long"
+ else
+ AC_MSG_ERROR([No 32-bit type found])
+ fi
+
+ if test "$ac_cv_sizeof_int" = "8"; then
+ int64="int"
+ elif test "$ac_cv_sizeof_long" = "8"; then
+ int64="long"
+ elif test "$ac_cv_sizeof_long_long" = "8"; then
+ int64="long long"
+ else
+ AC_MSG_ERROR([No 64-bit type found])
+ fi
+
+ int128=no
+ if test "$ac_cv_sizeof___int128_t" = "16"; then
+ int128="__int128_t"
+ fi
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32, 1, [Define if you have __sync_val_compare_and_swap() for 32-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH32, 1, [Define if you have __sync_add_and_fetch() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND32, 1, [Define if you have __sync_fetch_and_and() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR32, 1, [Define if you have __sync_fetch_and_or() for 32-bit integers]))
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64, 1, [Define if you have __sync_val_compare_and_swap() for 64-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH64, 1, [Define if you have __sync_add_and_fetch() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND64, 1, [Define if you have __sync_fetch_and_and() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR64, 1, [Define if you have __sync_fetch_and_or() for 64-bit integers]))
+
+ if test $int128 != no; then
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [128], [$int128], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128, 1, [Define if you have __sync_val_compare_and_swap() for 128-bit integers]))
+ fi
+
+ AC_MSG_CHECKING([for a usable libatomic_ops implementation])
+ case "x$with_libatomic_ops" in
+ xno | xyes | x)
+ libatomic_ops_include=
+ ;;
+ *)
+ if test -d "${with_libatomic_ops}/include"; then
+ libatomic_ops_include="-I$with_libatomic_ops/include"
+ CPPFLAGS="$CPPFLAGS $libatomic_ops_include"
+ else
+ AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found])
+ fi;;
+ esac
+ ethr_have_libatomic_ops=no
+ AC_TRY_LINK([#include "atomic_ops.h"],
+ [
+ volatile AO_t x;
+ AO_t y;
+ int z;
+
+ AO_nop_full();
+ AO_store(&x, (AO_t) 0);
+ z = AO_load(&x);
+ z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1);
+ ],
+ [ethr_have_native_atomics=yes
+ ethr_have_libatomic_ops=yes])
+ AC_MSG_RESULT([$ethr_have_libatomic_ops])
+ if test $ethr_have_libatomic_ops = yes; then
+ AC_CHECK_SIZEOF(AO_t, ,
+ [
+ #include <stdio.h>
+ #include "atomic_ops.h"
+ ])
+ AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used])
+
+ AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations])
+ if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations])
+ fi
+ ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
+ elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_MSG_ERROR([No usable libatomic_ops implementation found])
+ fi
+
+ case "$host_cpu" in
+ sparc | sun4u | sparc64 | sun4v)
+ case "$with_sparc_memory_order" in
+ "TSO")
+ AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
+ "PSO")
+ AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
+ "RMO"|"")
+ AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
+ *)
+ AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
+ esac
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
+ if test "$enable_x86_out_of_order" = "yes"; then
+ AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
+ fi
+ ethr_have_native_atomics=yes;;
+ macppc | ppc | "Power Macintosh")
+ ethr_have_native_atomics=yes;;
+ tile)
+ ethr_have_native_atomics=yes;;
+ *)
+ ;;
+ esac
+
+ test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
+
+ dnl Restore LIBS
+ LIBS=$saved_libs
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ ;;
+ *)
+ ;;
+esac
+
+AC_MSG_CHECKING([whether default stack size should be modified])
+if test "x$ethr_modified_default_stack_size" != "x"; then
+ AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size])
+ AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words])
+else
+ AC_MSG_RESULT([no])
+fi
+
+if test "x$ETHR_THR_LIB_BASE" != "x"; then
+ ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS"
+ ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS"
+ ETHR_LIB_NAME=$ethr_lib_name
+fi
+
+AC_CHECK_SIZEOF(void *)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers])
+
+AC_CHECK_SIZEOF(int)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int])
+AC_CHECK_SIZEOF(long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long])
+AC_CHECK_SIZEOF(long long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
+AC_CHECK_SIZEOF(__int64)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
+AC_CHECK_SIZEOF(__int128_t)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
+
+
+case X$erl_xcomp_bigendian in
+ X) ;;
+ Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);;
+esac
+
+AC_C_BIGENDIAN
+
+if test "$ac_cv_c_bigendian" = "yes"; then
+ AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
+fi
+
+case X$erl_xcomp_double_middle_endian in
+ X) ;;
+ Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
+esac
+
+AC_C_DOUBLE_MIDDLE_ENDIAN
+
+AC_ARG_ENABLE(native-ethr-impls,
+ AS_HELP_STRING([--disable-native-ethr-impls],
+ [disable native ethread implementations]),
+[ case "$enableval" in
+ no) disable_native_ethr_impls=yes ;;
+ *) disable_native_ethr_impls=no ;;
+ esac ], disable_native_ethr_impls=no)
+
+AC_ARG_ENABLE(x86-out-of-order,
+ AS_HELP_STRING([--enable-x86-out-of-order],
+ [enable x86/x84_64 out of order support (default disabled)]))
+
+test "X$disable_native_ethr_impls" = "Xyes" &&
+ AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
+
+AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
+ AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
+ [prefer gcc native ethread implementations]),
+[ case "$enableval" in
+ yes) enable_prefer_gcc_native_ethr_impls=yes ;;
+ *) enable_prefer_gcc_native_ethr_impls=no ;;
+ esac ], enable_prefer_gcc_native_ethr_impls=no)
+
+test $enable_prefer_gcc_native_ethr_impls = yes &&
+ AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
+
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
+AC_ARG_WITH(with_sparc_memory_order,
+ AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
+ [specify sparc memory order (defaults to RMO)]))
+
+ETHR_X86_SSE2_ASM=no
+case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in
+ yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64)
+ AC_MSG_CHECKING([for gcc sse2 asm support])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -msse2"
+ gcc_sse2_asm=no
+ AC_TRY_COMPILE([],
+ [
+ long long x, *y;
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
+ ],
+ [gcc_sse2_asm=yes])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$gcc_sse2_asm])
+ if test "$gcc_sse2_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
+ ETHR_X86_SSE2_ASM=yes
+ fi
+ ;;
+ *)
+ ;;
+esac
+
+case "$GCC-$host_cpu" in
+ yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
+ gcc_dw_cmpxchg_asm=no
+ AC_MSG_CHECKING([for gcc double word cmpxchg asm support])
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "pushl %%ebx\n\t"
+ "movl %8, %%ebx\n\t"
+#endif
+#if ETHR_SIZEOF_PTR == 4
+ "lock; cmpxchg8b %0\n\t"
+#else
+ "lock; cmpxchg16b %0\n\t"
+#endif
+ "setz %3\n\t"
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "popl %%ebx\n\t"
+#endif
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new[1]),
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "r"(new[0])
+#else
+ "b"(new[0])
+#endif
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test $gcc_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+#if !defined(__PIC__) || !__PIC__
+# error nope
+#endif
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new)
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
+ fi
+ fi
+ AC_MSG_RESULT([$gcc_dw_cmpxchg_asm])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
+ fi;;
+ *)
+ ;;
+esac
+
+AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
+[Define if you have all ethread defines])
+
+AC_SUBST(ETHR_X_LIBS)
+AC_SUBST(ETHR_LIBS)
+AC_SUBST(ETHR_LIB_NAME)
+AC_SUBST(ETHR_DEFS)
+AC_SUBST(ETHR_THR_LIB_BASE)
+AC_SUBST(ETHR_THR_LIB_BASE_DIR)
+AC_SUBST(ETHR_X86_SSE2_ASM)
+
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_TIME_CORRECTION
+dnl
+dnl In the presence of a high resolution realtime timer Erlang can adapt
+dnl its view of time relative to this timer. On solaris such a timer is
+dnl available with the syscall gethrtime(). On other OS's a fallback
+dnl solution using times() is implemented. (However on e.g. FreeBSD times()
+dnl is implemented using gettimeofday so it doesn't make much sense to
+dnl use it there...) On second thought, it seems to be safer to do it the
+dnl other way around. I.e. only use times() on OS's where we know it will
+dnl work...
+dnl
+
+AC_DEFUN(ERL_TIME_CORRECTION,
+[if test x$ac_cv_func_gethrtime = x; then
+ AC_CHECK_FUNC(gethrtime)
+fi
+if test x$clock_gettime_correction = xunknown; then
+ AC_TRY_COMPILE([#include <time.h>],
+ [struct timespec ts;
+ long long result;
+ clock_gettime(CLOCK_MONOTONIC,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);],
+ clock_gettime_compiles=yes,
+ clock_gettime_compiles=no)
+else
+ clock_gettime_compiles=no
+fi
+
+
+AC_CACHE_CHECK([how to correct for time adjustments], erl_cv_time_correction,
+[
+case $clock_gettime_correction in
+ yes)
+ erl_cv_time_correction=clock_gettime;;
+ no|unknown)
+ case $ac_cv_func_gethrtime in
+ yes)
+ erl_cv_time_correction=hrtime ;;
+ no)
+ case $host_os in
+ linux*)
+ case $clock_gettime_correction in
+ unknown)
+ if test x$clock_gettime_compiles = xyes; then
+ if test X$cross_compiling != Xyes; then
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-5]]|2.[[0-5]].*)
+ erl_cv_time_correction=times ;;
+ *)
+ erl_cv_time_correction=clock_gettime;;
+ esac
+ else
+ case X$erl_xcomp_linux_clock_gettime_correction in
+ X)
+ erl_cv_time_correction=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_linux_clock_gettime_correction = yes; then
+ erl_cv_time_correction=clock_gettime
+ else
+ erl_cv_time_correction=times
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_linux_clock_gettime_correction value: $erl_xcomp_linux_clock_gettime_correction]);;
+ esac
+ fi
+ else
+ erl_cv_time_correction=times
+ fi
+ ;;
+ *)
+ erl_cv_time_correction=times ;;
+ esac
+ ;;
+ *)
+ erl_cv_time_correction=none ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+])
+
+xrtlib=""
+case $erl_cv_time_correction in
+ times)
+ AC_DEFINE(CORRECT_USING_TIMES,[],
+ [Define if you do not have a high-res. timer & want to use times() instead])
+ ;;
+ clock_gettime|cross)
+ if test $erl_cv_time_correction = cross; then
+ erl_cv_time_correction=clock_gettime
+ AC_MSG_WARN([result clock_gettime guessed because of cross compilation])
+ fi
+ xrtlib="-lrt"
+ AC_DEFINE(GETHRTIME_WITH_CLOCK_GETTIME,[1],
+ [Define if you want to use clock_gettime to simulate gethrtime])
+ ;;
+esac
+dnl
+dnl Check if gethrvtime is working, and if to use procfs ioctl
+dnl or (yet to be written) write to the procfs ctl file.
+dnl
+
+AC_MSG_CHECKING([if gethrvtime works and how to use it])
+AC_TRY_RUN([
+/* gethrvtime procfs ioctl test */
+/* These need to be undef:ed to not break activation of
+ * micro level process accounting on /proc/self
+ */
+#ifdef _LARGEFILE_SOURCE
+# undef _LARGEFILE_SOURCE
+#endif
+#ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+
+int main() {
+ long msacct = PR_MSACCT;
+ int fd;
+ long long start, stop;
+ int i;
+ pid_t pid = getpid();
+ char proc_self[30] = "/proc/";
+
+ sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid);
+ if ( (fd = open(proc_self, O_WRONLY)) == -1)
+ exit(1);
+ if (ioctl(fd, PIOCSET, &msacct) < 0)
+ exit(2);
+ if (close(fd) < 0)
+ exit(3);
+ start = gethrvtime();
+ for (i = 0; i < 100; i++)
+ stop = gethrvtime();
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+}
+],
+erl_gethrvtime=procfs_ioctl,
+erl_gethrvtime=false,
+[
+case X$erl_xcomp_gethrvtime_procfs_ioctl in
+ X)
+ erl_gethrvtime=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then
+ erl_gethrvtime=procfs_ioctl
+ else
+ erl_gethrvtime=false
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);;
+esac
+])
+
+case $erl_gethrvtime in
+ procfs_ioctl)
+ AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1],
+ [define if gethrvtime() works and uses ioctl() to /proc/self])
+ AC_MSG_RESULT(uses ioctl to procfs)
+ ;;
+ *)
+ if test $erl_gethrvtime = cross; then
+ erl_gethrvtime=false
+ AC_MSG_RESULT(cross)
+ AC_MSG_WARN([result 'not working' guessed because of cross compilation])
+ else
+ AC_MSG_RESULT(not working)
+ fi
+
+ dnl
+ dnl Check if clock_gettime (linux) is working
+ dnl
+
+ AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time])
+ save_libs=$LIBS
+ LIBS="-lrt"
+ AC_TRY_RUN([
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <time.h>
+ int main() {
+ long long start, stop;
+ int i;
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0)
+ exit(1);
+ start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ for (i = 0; i < 100; i++)
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
+ stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+ }
+ ],
+ erl_clock_gettime=yes,
+ erl_clock_gettime=no,
+ [
+ case X$erl_xcomp_clock_gettime_cpu_time in
+ X) erl_clock_gettime=cross;;
+ Xyes|Xno) erl_clock_gettime=$erl_xcomp_clock_gettime_cpu_time;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);;
+ esac
+ ])
+ LIBS=$save_libs
+ case $host_os in
+ linux*)
+ AC_MSG_RESULT([no; not stable])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ AC_MSG_RESULT($erl_clock_gettime)
+ case $erl_clock_gettime in
+ yes)
+ AC_DEFINE(HAVE_CLOCK_GETTIME,[],
+ [define if clock_gettime() works for getting process time])
+ LIBRT=-lrt
+ ;;
+ cross)
+ erl_clock_gettime=no
+ AC_MSG_WARN([result no guessed because of cross compilation])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ LIBRT=$xrtlib
+ ;;
+ esac
+ ;;
+ esac
+ AC_SUBST(LIBRT)
+ ;;
+esac
+])dnl
+
+dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY
+dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
+dnl AC_LANG_JAVA instead...)
+AC_DEFUN(ERL_TRY_LINK_JAVA,
+[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
+changequote(, )dnl
+cat > conftest.java <<EOF
+$1
+class conftest { public static void main(String[] args) {
+ $2
+ ; return; }}
+EOF
+changequote([, ])dnl
+if AC_TRY_EVAL(java_link) && test -s conftest.class; then
+ ifelse([$3], , :, [rm -rf conftest*
+ $3])
+else
+ echo "configure: failed program was:" 1>&AC_FD_CC
+ cat conftest.java 1>&AC_FD_CC
+ echo "configure: PATH was $PATH" 1>&AC_FD_CC
+ifelse([$4], , , [ rm -rf conftest*
+ $4
+])dnl
+fi
+rm -f conftest*])
+#define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
+
+
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index 72ac8c7bbf..c958f80065 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# %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
@@ -89,7 +89,7 @@ AC_PROG_CC
AC_PROG_CPP
dnl AC_PROG_LIBTOOL
AC_PROG_RANLIB
-AC_CHECK_PROG(LD, ld.sh)
+AC_CHECK_PROGS(LD, ld.sh)
AC_CHECK_TOOL(LD, ld, '$(CC)')
AC_SUBST(LD)
@@ -224,50 +224,8 @@ elif test "x$with_gmp" != "xno" -a -n "$with_gmp" ;then
# FIXME return ERROR if no lib
fi
-MIXED_CYGWIN=no
-
-AC_MSG_CHECKING(for mixed cygwin and native VC++ environment)
-if test "X$CC" = "Xcc.sh" -a "X$host" = "Xwin32" -a "x$GCC" != x"yes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_VC=yes
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_VC=no
-fi
-AC_SUBST(MIXED_CYGWIN_VC)
-
-AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
-if test "X$CC" = "Xcc.sh" -a "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_MINGW=yes
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_MINGW=no
-fi
-AC_SUBST(MIXED_CYGWIN_MINGW)
-
-AC_MSG_CHECKING(if we mix cygwin with any native compiler)
-if test "X$MIXED_CYGWIN" = "Xyes" ; then
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(MIXED_CYGWIN)
+LM_WINDOWS_ENVIRONMENT
+
dnl
dnl Threads
@@ -338,12 +296,6 @@ AC_SUBST(LIB_CFLAGS)
if test "X$host" = "Xwin32"; then
LIB_CFLAGS="$CFLAGS"
else
- case $host_os in
- darwin*)
- CFLAGS="$CFLAGS -no-cpp-precomp"
- ;;
- esac
-
if test "x$GCC" = xyes; then
LIB_CFLAGS="$CFLAGS -fPIC"
else
diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile
index e05b647cb2..2bad8976b5 100644
--- a/lib/erl_interface/doc/src/Makefile
+++ b/lib/erl_interface/doc/src/Makefile
@@ -113,16 +113,16 @@ clean clean_docs clean_tex:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/erl_interface/doc/src/make.dep b/lib/erl_interface/doc/src/make.dep
deleted file mode 100644
index 3f43cf64fe..0000000000
--- a/lib/erl_interface/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin//docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex ei.tex ei_connect.tex ei_users_guide.tex \
- erl_call.tex erl_connect.tex erl_error.tex \
- erl_eterm.tex erl_format.tex erl_global.tex \
- erl_malloc.tex erl_marshal.tex part_ei.tex \
- ref_man.tex ref_man_ei.tex ref_man_erl_interface.tex \
- registry.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml ref_man_ei.xml ref_man_erl_interface.xml
-
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 9a42ebfddf..48ac0be22d 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -30,6 +30,59 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.7.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Minor suppressions and fixes of compilation
+ warnings</p>
+ <p>
+ Own Id: OTP-10016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.7.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An error when getting global names on OS X Lion has been
+ fixed. The error caused truncated strings to be returned
+ from the function.</p>
+ <p>
+ Own Id: OTP-9799</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.7.5</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 0d841cfa48..661dbb68ac 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -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
@@ -39,7 +39,9 @@ include ../vsn.mk
include $(TARGET)/eidefs.mk
USING_MINGW=@MIXED_CYGWIN_MINGW@
-USING_VC=@MIXED_CYGWIN_VC@
+USING_MSYS_VC==@MIXED_MSYS_VC@
+USING_CYGWIN_VC==@MIXED_MSYS_VC@
+USING_VC=@MIXED_VC@
ifdef TESTROOT
RELEASE_PATH=$(TESTROOT)
@@ -841,32 +843,32 @@ EXTRA = \
$(TARGET)/eidefs.mk
release: opt
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/lib
- $(INSTALL_DIR) $(RELSYSDIR)/bin
- $(INSTALL_DIR) $(RELSYSDIR)/src/auxdir
- $(INSTALL_DIR) $(RELSYSDIR)/src/connect
- $(INSTALL_DIR) $(RELSYSDIR)/src/decode
- $(INSTALL_DIR) $(RELSYSDIR)/src/encode
- $(INSTALL_DIR) $(RELSYSDIR)/src/epmd
- $(INSTALL_DIR) $(RELSYSDIR)/src/legacy
- $(INSTALL_DIR) $(RELSYSDIR)/src/misc
- $(INSTALL_DIR) $(RELSYSDIR)/src/prog
- $(INSTALL_DIR) $(RELSYSDIR)/src/registry
- $(INSTALL_DATA) $(HEADERS) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(OBJ_TARGETS) $(RELSYSDIR)/lib
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/lib"
+ $(INSTALL_DIR) "$(RELSYSDIR)/bin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/auxdir"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/connect"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/decode"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/encode"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/epmd"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/legacy"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/misc"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/prog"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/registry"
+ $(INSTALL_DATA) $(HEADERS) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(OBJ_TARGETS) "$(RELSYSDIR)/lib"
ifneq ($(EXE_TARGETS),)
- $(INSTALL_PROGRAM) $(EXE_TARGETS) $(RELSYSDIR)/bin
-endif
- $(INSTALL_DATA) $(EXTRA) $(RELSYSDIR)/src
- $(INSTALL_DATA) connect/*.[ch] $(RELSYSDIR)/src/connect
- $(INSTALL_DATA) decode/*.[ch] $(RELSYSDIR)/src/decode
- $(INSTALL_DATA) encode/*.[ch] $(RELSYSDIR)/src/encode
- $(INSTALL_DATA) epmd/*.[ch] $(RELSYSDIR)/src/epmd
- $(INSTALL_DATA) misc/*.[ch] $(RELSYSDIR)/src/misc
- $(INSTALL_DATA) registry/*.[ch] $(RELSYSDIR)/src/registry
- $(INSTALL_DATA) legacy/*.[ch] $(RELSYSDIR)/src/legacy
- $(INSTALL_DATA) prog/*.[ch] $(RELSYSDIR)/src/prog
+ $(INSTALL_PROGRAM) $(EXE_TARGETS) "$(RELSYSDIR)/bin"
+endif
+ $(INSTALL_DATA) $(EXTRA) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) connect/*.[ch] "$(RELSYSDIR)/src/connect"
+ $(INSTALL_DATA) decode/*.[ch] "$(RELSYSDIR)/src/decode"
+ $(INSTALL_DATA) encode/*.[ch] "$(RELSYSDIR)/src/encode"
+ $(INSTALL_DATA) epmd/*.[ch] "$(RELSYSDIR)/src/epmd"
+ $(INSTALL_DATA) misc/*.[ch] "$(RELSYSDIR)/src/misc"
+ $(INSTALL_DATA) registry/*.[ch] "$(RELSYSDIR)/src/registry"
+ $(INSTALL_DATA) legacy/*.[ch] "$(RELSYSDIR)/src/legacy"
+ $(INSTALL_DATA) prog/*.[ch] "$(RELSYSDIR)/src/prog"
release_docs:
diff --git a/lib/erl_interface/src/auxdir/config.guess b/lib/erl_interface/src/auxdir/config.guess
index fefabd7dd0..38a833903b 120000..100755
--- a/lib/erl_interface/src/auxdir/config.guess
+++ b/lib/erl_interface/src/auxdir/config.guess
@@ -1 +1,1519 @@
-../../../../erts/autoconf/config.guess \ No newline at end of file
+#! /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/erl_interface/src/auxdir/config.sub b/lib/erl_interface/src/auxdir/config.sub
index 90979e8924..f43233b104 120000..100755
--- a/lib/erl_interface/src/auxdir/config.sub
+++ b/lib/erl_interface/src/auxdir/config.sub
@@ -1 +1,1630 @@
-../../../../erts/autoconf/config.sub \ No newline at end of file
+#! /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/erl_interface/src/auxdir/install-sh b/lib/erl_interface/src/auxdir/install-sh
index 9422c370df..a5897de6ea 120000..100755
--- a/lib/erl_interface/src/auxdir/install-sh
+++ b/lib/erl_interface/src/auxdir/install-sh
@@ -1 +1,519 @@
-../../../../erts/autoconf/install-sh \ No newline at end of file
+#!/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/erl_interface/src/legacy/global_names.c b/lib/erl_interface/src/legacy/global_names.c
index 7333d94931..3a437df3a3 100644
--- a/lib/erl_interface/src/legacy/global_names.c
+++ b/lib/erl_interface/src/legacy/global_names.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
@@ -94,7 +94,7 @@ char **erl_global_names(int fd, int *count)
if (!(names = malloc((arity * sizeof(char**)) + (size-index)))) return NULL;
/* arity pointers first, followed by s */
- s = (char *)(names+arity+1);
+ s = (char *)(names+arity);
if (count) *count = 0;
for (i=0; i<arity; i++) {
diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c
index cf50f12451..281a192535 100644
--- a/lib/erl_interface/src/misc/ei_format.c
+++ b/lib/erl_interface/src/misc/ei_format.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -149,7 +149,7 @@ static int pdigit(const char** fmt, ei_x_buff* x)
{
const char* start = *fmt;
char c;
- int len, dotp=0;
+ int dotp=0;
double d;
long l;
@@ -166,7 +166,6 @@ static int pdigit(const char** fmt, ei_x_buff* x)
break;
}
--(*fmt);
- len = *fmt - start;
if (dotp) {
sscanf(start, "%lf", &d);
return ei_x_encode_double(x, d);
diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile
index 4faf89c0d6..d11a138844 100644
--- a/lib/erl_interface/test/Makefile
+++ b/lib/erl_interface/test/Makefile
@@ -71,9 +71,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(ERL_FILES) "$(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 42d4c6f27f..39085def2d 100644
--- a/lib/erl_interface/test/all_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/all_SUITE_data/Makefile.src
@@ -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
@@ -32,7 +32,7 @@ all: $(ALL_OBJS)
$(EI_COMMON_OBJS): gccifier@exe@
-@IFEQ@ (@erl_interface_cross_compile@, true)
+@IFEQ@ (@cross@, yes)
gccifier@exe@:
$(CP) gccifier.sh gccifier@exe@
$(CHMOD) a+x gccifier@exe@
diff --git a/lib/erl_interface/test/all_SUITE_data/gccifier.c b/lib/erl_interface/test/all_SUITE_data/gccifier.c
index 9f556fc4ed..a1019f9a72 100644
--- a/lib/erl_interface/test/all_SUITE_data/gccifier.c
+++ b/lib/erl_interface/test/all_SUITE_data/gccifier.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -16,7 +16,6 @@
*
* %CopyrightEnd%
*
-
*/
/*
@@ -74,17 +73,23 @@ save_arg(args_t *args, char *arg1, ...)
args->vec = (char **) (args->no
? realloc((void *) args->vec,
(sizeof(char *)
- *(args->no + ARGS_INCR + 1)))
+ *(args->no + ARGS_INCR + 2)))
: malloc((sizeof(char *)
- *(args->no + ARGS_INCR + 1))));
+ *(args->no + ARGS_INCR + 2))));
if (!args->vec)
enomem();
args->no += ARGS_INCR;
}
+ if (carg == arg1) {
+ args->vec[args->ix++] = "\"";
+ args->chars++;
+ }
args->vec[args->ix++] = carg;
args->chars += strlen(carg);
carg = va_arg(argp, char *);
}
+ args->vec[args->ix++] = "\"";
+ args->chars++;
args->vec[args->ix++] = " ";
args->chars++;
va_end(argp);
@@ -232,6 +237,9 @@ main(int argc, char *argv[])
CHECK_FIRST_LINK_ARG;
save_arg(&link_args, "-libpath:", arg, NULL);
}
+ else if (strcmp("-link",arg) == 0) {
+ CHECK_FIRST_LINK_ARG;
+ }
#endif /* #ifdef __WIN32__ */
else if (is_prefix("-l", &arg)) {
CHECK_FIRST_LINK_ARG;
diff --git a/lib/erl_interface/test/all_SUITE_data/init_tc.erl b/lib/erl_interface/test/all_SUITE_data/init_tc.erl
index 8157d590fc..60c965eda3 100644
--- a/lib/erl_interface/test/all_SUITE_data/init_tc.erl
+++ b/lib/erl_interface/test/all_SUITE_data/init_tc.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
@@ -40,28 +40,15 @@ run([]) ->
run1(Name) ->
CFile = Name ++ ".c",
{ok, Bin} = file:read_file(CFile),
- String = binary_to_list(Bin),
-
- %% This ConstPart stuff is because you can't retrieve part of a match.
- %% Long live Perl!
-
- ConstPart = "\nTESTCASE\\(",
- ConstPartLen = 10,
- {match, Matches} = regexp:matches(String, ConstPart++"[_a-zA-Z]*"),
- Cases = get_names(Matches, ConstPartLen, Bin, []),
+ RE = "\nTESTCASE\\(([_a-zA-Z]*)\\)",
+ {match, Cases0} = re:run(Bin, RE, [{capture,all_but_first,list},global]),
+ Cases = lists:concat(Cases0),
generate(Name, Cases).
-get_names([{Start, Length}|Rest], Skip, Bin, Result) ->
- Name = binary_to_list(Bin, Start+Skip, Start+Length-1),
- get_names(Rest, Skip, Bin, [Name|Result]);
-get_names([], _Skip, _Bin, Result) ->
- lists:reverse(Result).
-
generate(TcName, Cases) ->
Hrl = TcName ++ "_cases.hrl",
{ok, HrlFile} = file:open(Hrl, write),
- {ok, Dir} = file:get_cwd(),
- generate_hrl(Cases, HrlFile, {filename:join(Dir, TcName), 0}),
+ generate_hrl(Cases, HrlFile, {TcName, 0}),
file:close(HrlFile),
C = TcName ++ "_decl.c",
{ok, CFile} = file:open(C, write),
@@ -69,7 +56,7 @@ generate(TcName, Cases) ->
file:close(CFile).
generate_hrl([Case|Rest], File, {Name, Number}) ->
- io:format(File, "-define(~s, {\"~s\", ~w}).~n", [Case, Name, Number]),
+ io:format(File, "-define(~s, {filename:join(proplists:get_value(data_dir,Config),\"~s\"), ~w}).~n", [Case, Name, Number]),
generate_hrl(Rest, File, {Name, Number+1});
generate_hrl([], _, _) ->
ok.
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 7ff8c08280..cc22cb7440 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -88,12 +88,12 @@ ei_recv_tmo(doc) ->
ei_recv_tmo(suite) ->
[];
ei_recv_tmo(Config) when is_list(Config) ->
- ?line do_one_recv(c_node_recv_tmo_1),
- ?line do_one_recv_failure(c_node_recv_tmo_2),
+ ?line do_one_recv(Config,c_node_recv_tmo_1),
+ ?line do_one_recv_failure(Config,c_node_recv_tmo_2),
ok.
-do_one_recv(CNode) ->
+do_one_recv(Config,CNode) ->
?line {_,Host} = split(node()),
?line P1 = runner:start(?recv_tmo),
?line runner:send_term(P1,{CNode,
@@ -107,7 +107,7 @@ do_one_recv(CNode) ->
?line {term, Term1} = runner:get_term(P1, 10000),
?line runner:recv_eot(P1).
-do_one_recv_failure(CNode) ->
+do_one_recv_failure(Config,CNode) ->
?line P1 = runner:start(?recv_tmo),
?line runner:send_term(P1,{CNode,
erlang:get_cookie(),
@@ -128,14 +128,14 @@ ei_send_tmo(Config) when is_list(Config) ->
%dbg:p(self()),
VxSim = ?config(vxsim, Config),
?line register(ei_send_tmo_1,self()),
- ?line do_one_send(self(),c_node_send_tmo_1),
- ?line do_one_send(ei_send_tmo_1,c_node_send_tmo_2),
- ?line do_one_send_failure(self(),cccc1,c_nod_send_tmo_3,VxSim),
- ?line do_one_send_failure(ei_send_tmo_1,cccc2,c_nod_send_tmo_4,VxSim),
+ ?line do_one_send(Config,self(),c_node_send_tmo_1),
+ ?line do_one_send(Config,ei_send_tmo_1,c_node_send_tmo_2),
+ ?line do_one_send_failure(Config,self(),cccc1,c_nod_send_tmo_3,VxSim),
+ ?line do_one_send_failure(Config,ei_send_tmo_1,cccc2,c_nod_send_tmo_4,VxSim),
ok.
-do_one_send(From,CNode) ->
+do_one_send(Config,From,CNode) ->
?line {_,Host} = split(node()),
?line P1 = runner:start(?send_tmo),
?line runner:send_term(P1,{CNode,
@@ -155,7 +155,7 @@ do_one_send(From,CNode) ->
?line {term, 0} = runner:get_term(P1, 10000),
?line runner:recv_eot(P1).
-do_one_send_failure(From,FakeName,CName,VxSim) ->
+do_one_send_failure(Config,From,FakeName,CName,VxSim) ->
?line {_,Host} = split(node()),
?line OurName = join(FakeName,Host),
?line Node = join(CName,Host),
diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl
index e019fecca8..edbb17a8c1 100644
--- a/lib/erl_interface/test/erl_match_SUITE.erl
+++ b/lib/erl_interface/test/erl_match_SUITE.erl
@@ -29,7 +29,7 @@
bind/1, integers/1, floats/1, binaries/1, strings/1]).
%% For interactive running of matcher.
--export([start_matcher/0, erl_match/3]).
+-export([start_matcher/1, erl_match/3]).
%% This test suite tests the erl_match() function.
@@ -57,7 +57,7 @@ end_per_group(_GroupName, Config) ->
atoms(suite) -> [];
atoms(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line eq(P, '', ''),
?line eq(P, a, a),
@@ -74,7 +74,7 @@ atoms(Config) when is_list(Config) ->
lists(suite) -> [];
lists(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line eq(P, [], []),
?line ne(P, [], [a]),
@@ -101,7 +101,7 @@ lists(Config) when is_list(Config) ->
tuples(suite) -> [];
tuples(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line ne(P, {}, {a, b}),
?line ne(P, {a, b}, {}),
@@ -129,7 +129,7 @@ tuples(Config) when is_list(Config) ->
references(suite) -> [];
references(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line Ref1 = make_ref(),
?line Ref2 = make_ref(),
@@ -144,7 +144,7 @@ references(Config) when is_list(Config) ->
pids(suite) -> [];
pids(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line Pid1 = c:pid(0,1,2),
?line Pid2 = c:pid(0,1,3),
@@ -163,8 +163,8 @@ ports(Config) when is_list(Config) ->
vxworks ->
{skipped,"not on vxworks, pucko"};
_ ->
- ?line P = start_matcher(),
- ?line P2 = start_matcher(),
+ ?line P = start_matcher(Config),
+ ?line P2 = start_matcher(Config),
?line eq(P, P, P),
?line ne(P, P, P2),
@@ -176,7 +176,7 @@ ports(Config) when is_list(Config) ->
integers(suite) -> [];
integers(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line I1 = 123,
?line I2 = 12345,
?line I3 = -123,
@@ -195,7 +195,7 @@ integers(Config) when is_list(Config) ->
floats(suite) -> [];
floats(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line F1 = 3.1414,
?line F2 = 3.1415,
?line F3 = 3.1416,
@@ -218,7 +218,7 @@ floats(Config) when is_list(Config) ->
binaries(suite) -> [];
binaries(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line Bin1 = term_to_binary({kalle, 146015, {kungsgatan, 23}}),
?line Bin2 = term_to_binary(sune),
?line Bin3 = list_to_binary("sune"),
@@ -237,7 +237,7 @@ binaries(Config) when is_list(Config) ->
strings(suite) -> [];
strings(Config) when is_list(Config) ->
- ?line P = start_matcher(),
+ ?line P = start_matcher(Config),
?line S1 = "string",
?line S2 = "streng",
@@ -254,7 +254,7 @@ strings(Config) when is_list(Config) ->
bind(suite) -> [];
bind(Config) when is_list(Config) ->
- ?line P = start_bind(),
+ ?line P = start_bind(Config),
?line S = "[X,Y,Z]",
?line L1 = [301,302,302],
?line L2 = [65,66,67],
@@ -265,7 +265,7 @@ bind(Config) when is_list(Config) ->
?line runner:finish(P),
ok.
-start_bind() ->
+start_bind(Config) ->
runner:start(?erl_match_bind).
bind_ok(Port, Bind, Term) ->
@@ -287,7 +287,7 @@ erl_bind(Port, Pattern, Term) ->
-start_matcher() ->
+start_matcher(Config) ->
runner:start(?erl_match_server).
eq(Port, Pattern, Term) ->
diff --git a/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c b/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c
index 80811fb973..abc76085de 100644
--- a/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c
+++ b/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c
@@ -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
@@ -18,14 +18,17 @@
*/
#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
#include "erl_interface.h"
#include "erl_driver.h"
static ErlDrvPort my_erlang_port;
static ErlDrvData echo_start(ErlDrvPort, char *);
-static void from_erlang(ErlDrvData, char*, int);
-static int do_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags);
+static void from_erlang(ErlDrvData, char*, ErlDrvSizeT);
+static ErlDrvSSizeT do_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len, char **rbuf,
+ ErlDrvSizeT rlen, unsigned *ret_flags);
static ErlDrvEntry echo_driver_entry = {
NULL, /* Init */
echo_start,
@@ -41,7 +44,15 @@ static ErlDrvEntry echo_driver_entry = {
NULL,
NULL,
NULL,
- do_call
+ do_call,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
DRIVER_INIT(echo_drv)
@@ -56,14 +67,14 @@ echo_start(ErlDrvPort port, char *buf)
}
static void
-from_erlang(ErlDrvData data, char *buf, int count)
+from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count)
{
driver_output((ErlDrvPort) data, buf, count);
}
-static int
+static ErlDrvSSizeT
do_call(ErlDrvData drv_data, unsigned int command, char *buf,
- int len, char **rbuf, int rlen, unsigned *ret_flags)
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags)
{
int nlen;
ei_x_buff x;
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 601958579c..0e249d2483 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1 +1 @@
-EI_VSN = 3.7.5
+EI_VSN = 3.7.7
diff --git a/lib/et/doc/src/Makefile b/lib/et/doc/src/Makefile
index 6bb8164e91..facd335449 100644
--- a/lib/et/doc/src/Makefile
+++ b/lib/et/doc/src/Makefile
@@ -97,14 +97,14 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/et/doc/src/et_intro.xml b/lib/et/doc/src/et_intro.xml
index 0c5fb14d55..60da289721 100644
--- a/lib/et/doc/src/et_intro.xml
+++ b/lib/et/doc/src/et_intro.xml
@@ -40,8 +40,8 @@
ports or files.</p>
<section>
- <title>Scope and Purpose</title>'
-
+ <title>Scope and Purpose</title>
+
<p>This manual describes the <c>Event Tracer (ET)</c> application,
as a component of the Erlang/Open Telecom Platform development
environment. It is assumed that the reader is familiar with the
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index acc6120fcd..42790e0cdf 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -36,6 +36,26 @@
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.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The GS applications is now deprecated and will be
+ removed in the R16 release. The following GS-based
+ applications have been superseded by the Observer
+ application and will removed in R16: Appmon, Pman,
+ Tv.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9907</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/et/examples/Makefile b/lib/et/examples/Makefile
index 67a6536fdf..190d5e2d6a 100644
--- a/lib/et/examples/Makefile
+++ b/lib/et/examples/Makefile
@@ -73,8 +73,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/et/src/Makefile b/lib/et/src/Makefile
index bb6632ee91..7693571c5c 100644
--- a/lib/et/src/Makefile
+++ b/lib/et/src/Makefile
@@ -104,14 +104,14 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/et/src/et_gs_contents_viewer.erl b/lib/et/src/et_gs_contents_viewer.erl
index f6a87bd608..2d414f10b4 100644
--- a/lib/et/src/et_gs_contents_viewer.erl
+++ b/lib/et/src/et_gs_contents_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,17 @@
%%----------------------------------------------------------------------
-module(et_gs_contents_viewer).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-behaviour(gen_server).
diff --git a/lib/et/src/et_gs_viewer.erl b/lib/et/src/et_gs_viewer.erl
index 0af7814d15..ce8634d09f 100644
--- a/lib/et/src/et_gs_viewer.erl
+++ b/lib/et/src/et_gs_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,23 @@
%%----------------------------------------------------------------------
-module(et_gs_viewer).
+-compile([{nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-behaviour(gen_server).
diff --git a/lib/et/src/et_wx_contents_viewer.erl b/lib/et/src/et_wx_contents_viewer.erl
index 86f46f25d0..b559da8807 100644
--- a/lib/et/src/et_wx_contents_viewer.erl
+++ b/lib/et/src/et_wx_contents_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -245,12 +245,7 @@ handle_event(#wx{id = Id,
Data when is_record(Data, filter) ->
F = Data,
ChildState= S#state{active_filter = F#filter.name},
- case wx_object:start_link(?MODULE, [ChildState], []) of
- {ok, Pid} when S#state.parent_pid =/= self() ->
- unlink(Pid);
- _ ->
- ignore
- end;
+ wx_object:start_link(?MODULE, [ChildState], []);
{hide, Actors} ->
send_viewer_event(S, {delete_actors, Actors});
{show, Actors} ->
@@ -356,12 +351,7 @@ handle_event(#wx{event = #wxKey{rawCode = KeyCode}}, S) ->
case lists:keysearch(?DEFAULT_FILTER_NAME, #filter.name, S#state.filters) of
{value, F} when is_record(F, filter) ->
ChildState= S#state{active_filter = F#filter.name},
- case wx_object:start_link(?MODULE, [ChildState], []) of
- {ok, Pid} when S#state.parent_pid =/= self() ->
- unlink(Pid);
- _ ->
- ignore
- end;
+ wx_object:start_link(?MODULE, [ChildState], []);
false ->
ignore
end,
@@ -370,12 +360,7 @@ handle_event(#wx{event = #wxKey{rawCode = KeyCode}}, S) ->
case catch lists:nth(Int-$0, S#state.filters) of
F when is_record(F, filter) ->
ChildState= S#state{active_filter = F#filter.name},
- case wx_object:start_link(?MODULE, [ChildState], []) of
- {ok, Pid} when S#state.parent_pid =/= self() ->
- unlink(Pid);
- _ ->
- ignore
- end;
+ wx_object:start_link(?MODULE, [ChildState], []);
{'EXIT', _} ->
ignore
end,
diff --git a/lib/et/test/Makefile b/lib/et/test/Makefile
index e10a2a1587..7b4db7b0c3 100644
--- a/lib/et/test/Makefile
+++ b/lib/et/test/Makefile
@@ -70,12 +70,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) et.spec et.cover $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_SCRIPT) ett $(RELSYSDIR)
- $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
-# chmod -R u+w $(RELSYSDIR)
-# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) et.spec et.cover $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_SCRIPT) ett "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(INSTALL_PROGS) "$(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 239a72ad73..090d43d52f 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.4.4
+ET_VSN = 1.4.4.1
diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc
index ad449cb6fc..b4af31ae6a 100644
--- a/lib/eunit/doc/overview.edoc
+++ b/lib/eunit/doc/overview.edoc
@@ -723,8 +723,12 @@ A <em>simple test object</em> is one of the following:
```fun some_function/0'''
```fun some_module:some_function/0'''
</li>
- <li>A pair of atoms `{ModuleName, FunctionName}', referring to the
- function `ModuleName:FunctionName/0'</li>
+ <li>A tuple `{test, ModuleName, FunctionName}', where `ModuleName' and
+ `FunctionName' are atoms, referring to the function
+ `ModuleName:FunctionName/0'</li>
+ <li>(Obsolete) A pair of atoms `{ModuleName, FunctionName}', equivalent to
+ `{test, ModuleName, FunctionName}' if nothing else matches first. This
+ might be removed in a future version.</li>
<li>A pair `{LineNumber, SimpleTest}', where `LineNumber' is a
nonnegative integer and `SimpleTest' is another simple test
object. `LineNumber' should indicate the source line of the test.
diff --git a/lib/eunit/doc/src/Makefile b/lib/eunit/doc/src/Makefile
index 2cdc579275..cbcd4c1507 100644
--- a/lib/eunit/doc/src/Makefile
+++ b/lib/eunit/doc/src/Makefile
@@ -157,14 +157,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/eunit/doc/src/make.dep b/lib/eunit/doc/src/make.dep
deleted file mode 100644
index d68f888403..0000000000
--- a/lib/eunit/doc/src/make.dep
+++ /dev/null
@@ -1,19 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex eunit.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index e68330482c..34e8a47e3d 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -32,6 +32,24 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.2.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eunit/examples/Makefile b/lib/eunit/examples/Makefile
index 48ec2ebf2b..cfa0a7a645 100644
--- a/lib/eunit/examples/Makefile
+++ b/lib/eunit/examples/Makefile
@@ -49,8 +49,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(EXAMPLE_FILES) "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index db68d8ae60..fba840c3bd 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -25,11 +25,12 @@
%% will become undefined. NODEBUG also implies NOASSERT, unless testing
%% is enabled.
%%
-%% If including this file causes TEST to be defined, then NOASSERT will
-%% be undefined, even if it was previously defined and even if NODEBUG
-%% is defined. If both ASSERT and NOASSERT are defined before the file
-%% is included, then ASSERT takes precedence, and NOASSERT will become
-%% undefined regardless of TEST.
+%% Defining NOASSERT disables asserts. NODEBUG implies NOASSERT unless
+%% testing is enabled. If including this file causes TEST to be defined,
+%% then NOASSERT will be undefined, even if it was previously defined and
+%% even if NODEBUG is defined. If both ASSERT and NOASSERT are defined
+%% before the file is included, then ASSERT takes precedence, and NOASSERT
+%% will become undefined regardless of TEST.
%%
%% After including this file, EUNIT will be defined if and only if TEST
%% is defined.
@@ -127,9 +128,9 @@
current_function)))).
-endif.
--ifdef(NOASSERT).
%% The plain assert macro should be defined to do nothing if this file
%% is included when debugging/testing is turned off.
+-ifdef(NOASSERT).
-ifndef(assert).
-define(assert(BoolExpr),ok).
-endif.
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile
index bec2fdbe0b..0a2e71cf7b 100644
--- a/lib/eunit/src/Makefile
+++ b/lib/eunit/src/Makefile
@@ -28,6 +28,9 @@ ERL_COMPILE_FLAGS += -pa $(EBIN) -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_v
PARSE_TRANSFORM = eunit_autoexport.erl
+BEHAVIOUR_SOURCES= \
+ eunit_listener.erl
+
SOURCES= \
eunit_striptests.erl \
eunit.erl \
@@ -40,13 +43,16 @@ SOURCES= \
eunit_data.erl \
eunit_tty.erl \
eunit_surefire.erl \
- eunit_listener.erl
INCLUDE_FILES = eunit.hrl
PARSE_TRANSFORM_BIN = $(PARSE_TRANSFORM:%.erl=$(EBIN)/%.$(EMULATOR))
-OBJECTS=$(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+TARGET_FILES= $(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR))
+
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_SOURCES:%.erl=$(EBIN)/%.$(EMULATOR))
+
+OBJECTS= $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
INCLUDE_DELIVERABLES = $(INCLUDE_FILES:%=$(INCLUDE)/%)
@@ -62,6 +68,8 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# Targets
# ----------------------------------------------------
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
+
debug opt: $(PARSE_TRANSFORM_BIN) $(OBJECTS)
docs:
@@ -107,12 +115,12 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(PARSE_TRANSFORM_BIN) $(OBJECTS) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(PARSE_TRANSFORM) $(SOURCES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(INCLUDE_DELIVERABLES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(PARSE_TRANSFORM_BIN) $(OBJECTS) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(PARSE_TRANSFORM) $(SOURCES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(INCLUDE_DELIVERABLES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src
index 5e16dfa2ce..431abac98b 100644
--- a/lib/eunit/src/eunit.app.src
+++ b/lib/eunit/src/eunit.app.src
@@ -14,7 +14,6 @@
eunit_striptests,
eunit_surefire,
eunit_test,
- eunit_tests,
eunit_tty]},
{registered,[]},
{applications, [kernel,stdlib]},
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index 95857e83c8..51846d73b3 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -139,7 +139,7 @@ test(Tests, Options) ->
%% @private
%% @doc See {@link test/2}.
test(Server, Tests, Options) ->
- Listeners = [eunit_tty:start(Options) | listeners(Options)],
+ Listeners = listeners(Options),
Serial = eunit_serial:start(Listeners),
case eunit_server:start_test(Server, Serial, Tests, Options) of
{ok, Reference} -> test_run(Reference, Listeners);
@@ -194,7 +194,10 @@ submit(Server, T, Options) ->
eunit_server:start_test(Server, Dummy, T, Options).
listeners(Options) ->
- Ps = start_listeners(proplists:get_all_values(report, Options)),
+ %% note that eunit_tty must always run, because it sends the final
+ %% {result,...} message that the test_run() function is waiting for
+ Ls = [{eunit_tty, Options} | proplists:get_all_values(report, Options)],
+ Ps = start_listeners(Ls),
%% the event_log option is for debugging, to view the raw events
case proplists:get_value(event_log, Options) of
undefined ->
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index 392d378a0e..0350f9bf6e 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -83,6 +83,7 @@
%% SimpleTest = TestFunction | {Line::integer(), SimpleTest}
%%
%% TestFunction = () -> any()
+%% | {test, M::moduleName(), F::functionName()}
%% | {M::moduleName(), F::functionName()}.
%%
%% AbstractTestFunction = (X::any()) -> any()
@@ -95,7 +96,6 @@
%%
%% @type moduleName() = atom()
%% @type functionName() = atom()
-%% @type arity() = integer()
%% @type appName() = atom()
%% @type fileName() = string()
@@ -156,8 +156,9 @@ iter_prev(#iter{prev = [T | Ts]} = I) ->
%% @spec (tests()) -> none | {testItem(), tests()}
%% @type testItem() = #test{} | #group{}
%% @throws {bad_test, term()}
-%% | {generator_failed, exception()}
-%% | {no_such_function, eunit_lib:mfa()}
+%% | {generator_failed, {{M::atom(),F::atom(),A::integer()},
+%% exception()}}
+%% | {no_such_function, mfa()}
%% | {module_not_found, moduleName()}
%% | {application_not_found, appName()}
%% | {file_read_error, {Reason::atom(), Message::string(),
@@ -221,17 +222,27 @@ parse({foreachx, P, S1, C1, Ps} = T)
[] ->
{data, []}
end;
-parse({generator, F} = T) when is_function(F) ->
+parse({generator, F}) when is_function(F) ->
+ {module, M} = erlang:fun_info(F, module),
+ {name, N} = erlang:fun_info(F, name),
+ {arity, A} = erlang:fun_info(F, arity),
+ parse({generator, F, {M,N,A}});
+parse({generator, F, {M,N,A}} = T)
+ when is_function(F), is_atom(M), is_atom(N), is_integer(A) ->
check_arity(F, 0, T),
%% use run_testfun/1 to handle wrapper exceptions
case eunit_test:run_testfun(F) of
{ok, T1} ->
+ case eunit_lib:is_not_test(T1) of
+ true -> throw({bad_generator, {{M,N,A}, T1}});
+ false -> ok
+ end,
{data, T1};
{error, {Class, Reason, Trace}} ->
- throw({generator_failed, {Class, Reason, Trace}})
+ throw({generator_failed, {{M,N,A}, {Class, Reason, Trace}}})
end;
parse({generator, M, F}) when is_atom(M), is_atom(F) ->
- parse({generator, eunit_test:function_wrapper(M, F)});
+ parse({generator, eunit_test:mf_wrapper(M, F), {M,F,0}});
parse({inorder, T}) ->
group(#group{tests = T, order = inorder});
parse({inparallel, T}) ->
@@ -421,8 +432,11 @@ parse_simple(F) ->
parse_function(F) when is_function(F) ->
check_arity(F, 0, F),
#test{f = F, location = eunit_lib:fun_parent(F)};
-parse_function({M,F}) when is_atom(M), is_atom(F) ->
- #test{f = eunit_test:function_wrapper(M, F), location = {M, F, 0}};
+parse_function({test, M, F}) when is_atom(M), is_atom(F) ->
+ #test{f = eunit_test:mf_wrapper(M, F), location = {M, F, 0}};
+parse_function({M, F}) when is_atom(M), is_atom(F) ->
+ %% {M,F} is now considered obsolete; use {test,M,F} instead
+ parse_function({test, M, F});
parse_function(F) ->
bad_test(F).
@@ -580,7 +594,7 @@ testfuns(Es, M, TestSuffix, GeneratorSuffix) ->
N = atom_to_list(F),
case lists:suffix(TestSuffix, N) of
true ->
- [{M,F} | Fs];
+ [{test, M, F} | Fs];
false ->
case lists:suffix(GeneratorSuffix, N) of
true ->
@@ -723,6 +737,7 @@ data_test_() ->
Tests = [T,T,T],
[?_assertMatch(ok, eunit:test(T)),
?_assertMatch(error, eunit:test(Fail)),
+ ?_assertMatch(ok, eunit:test({test, ?MODULE, trivial_test})),
?_assertMatch(ok, eunit:test({generator, fun () -> Tests end})),
?_assertMatch(ok, eunit:test({generator, fun generator/0})),
?_assertMatch(ok, eunit:test({generator, ?MODULE, generator_exported_})),
@@ -740,6 +755,12 @@ data_test_() ->
%%?_test({foreach, Setup, [T, T, T]})
].
+trivial_test() ->
+ ok.
+
+trivial_generator_test_() ->
+ [?_test(ok)].
+
lazy_test_() ->
{spawn, [?_test(undefined = put(count, 0)),
lazy_gen(7),
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index 1c41e229c5..ea9e944d7e 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -30,7 +30,8 @@
-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_exception/2, format_error/1]).
+ format_exception/1, format_exception/2, format_error/1,
+ is_not_test/1]).
%% Type definitions for describing exceptions
@@ -39,13 +40,10 @@
%%
%% @type exceptionClass() = error | exit | throw
%%
-%% @type stackTrace() = [{moduleName(), functionName(),
-%% arity() | argList()}]
+%% @type stackTrace() = [{moduleName(), functionName(), arity() | argList()}]
%%
%% @type moduleName() = atom()
%% @type functionName() = atom()
-%% @type arity() = integer()
-%% @type mfa() = {moduleName(), functionName(), arity()}
%% @type argList() = [term()]
%% @type fileName() = string()
@@ -59,8 +57,9 @@ 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, Depth, format_stacktrace(Trace)]);
+ io_lib:format("~s**~w:~s",
+ [format_stacktrace(Trace), Class,
+ format_term(Term, Depth)]);
false ->
format_term(Term, Depth)
end;
@@ -86,6 +85,12 @@ analyze_exit_term(Term) ->
is_stacktrace([]) ->
true;
+is_stacktrace([{M,F,A,L}|Fs])
+ when is_atom(M), is_atom(F), is_integer(A), is_list(L) ->
+ is_stacktrace(Fs);
+is_stacktrace([{M,F,As,L}|Fs])
+ when is_atom(M), is_atom(F), is_list(As), is_list(L) ->
+ is_stacktrace(Fs);
is_stacktrace([{M,F,A}|Fs]) when is_atom(M), is_atom(F), is_integer(A) ->
is_stacktrace(Fs);
is_stacktrace([{M,F,As}|Fs]) when is_atom(M), is_atom(F), is_list(As) ->
@@ -96,10 +101,11 @@ is_stacktrace(_) ->
format_stacktrace(Trace) ->
format_stacktrace(Trace, "in function", "in call from").
-format_stacktrace([{M,F,A}|Fs], Pre, Pre1) when is_integer(A) ->
- [io_lib:fwrite(" ~s ~w:~w/~w\n", [Pre, M, F, A])
+format_stacktrace([{M,F,A,L}|Fs], Pre, Pre1) when is_integer(A) ->
+ [io_lib:fwrite("~s ~w:~w/~w~s\n",
+ [Pre, M, F, A, format_stacktrace_location(L)])
| format_stacktrace(Fs, Pre1, Pre1)];
-format_stacktrace([{M,F,As}|Fs], Pre, Pre1) when is_list(As) ->
+format_stacktrace([{M,F,As,L}|Fs], Pre, Pre1) when is_list(As) ->
A = length(As),
C = case is_op(M,F,A) of
true when A =:= 1 ->
@@ -112,12 +118,23 @@ format_stacktrace([{M,F,As}|Fs], Pre, Pre1) when is_list(As) ->
false ->
io_lib:fwrite("~w(~s)", [F,format_arglist(As)])
end,
- [io_lib:fwrite(" ~s ~w:~w/~w\n called as ~s\n",
- [Pre,M,F,A,C])
+ [io_lib:fwrite("~s ~w:~w/~w~s\n called as ~s\n",
+ [Pre,M,F,A,format_stacktrace_location(L),C])
| format_stacktrace(Fs,Pre1,Pre1)];
+format_stacktrace([{M,F,As}|Fs], Pre, Pre1) ->
+ format_stacktrace([{M,F,As,[]}|Fs], Pre, Pre1);
format_stacktrace([],_Pre,_Pre1) ->
"".
+format_stacktrace_location(Location) ->
+ File = proplists:get_value(file, Location),
+ Line = proplists:get_value(line, Location),
+ if File =/= undefined, Line =/= undefined ->
+ io_lib:format(" (~s, line ~w)", [File, Line]);
+ true ->
+ ""
+ end.
+
format_arg(A) ->
io_lib:format("~P",[A,15]).
@@ -139,9 +156,13 @@ is_op(_M, _F, _A) ->
format_error({bad_test, Term}) ->
error_msg("bad test descriptor", "~P", [Term, 15]);
-format_error({generator_failed, Exception}) ->
- error_msg("test generator failed", "~s",
- [format_exception(Exception)]);
+format_error({bad_generator, {{M,F,A}, Term}}) ->
+ error_msg(io_lib:format("result from generator ~w:~w/~w is not a test",
+ [M,F,A]),
+ "~P", [Term, 15]);
+format_error({generator_failed, {{M,F,A}, Exception}}) ->
+ error_msg(io_lib:format("test generator ~w:~w/~w failed",[M,F,A]),
+ "~s", [format_exception(Exception)]);
format_error({no_such_function, {M,F,A}})
when is_atom(M), is_atom(F), is_integer(A) ->
error_msg(io_lib:format("no such function: ~w:~w/~w", [M,F,A]),
@@ -158,14 +179,55 @@ format_error({setup_failed, Exception}) ->
format_error({cleanup_failed, Exception}) ->
error_msg("context cleanup failed", "~s",
[format_exception(Exception)]);
+format_error({{bad_instantiator, {{M,F,A}, Term}}, _DummyException}) ->
+ error_msg(io_lib:format("result from instantiator ~w:~w/~w is not a test",
+ [M,F,A]),
+ "~P", [Term, 15]);
format_error({instantiation_failed, Exception}) ->
error_msg("instantiation of subtests failed", "~s",
[format_exception(Exception)]).
error_msg(Title, Fmt, Args) ->
- Msg = io_lib:format("::"++Fmt, Args), % gets indentation right
+ Msg = io_lib:format("**"++Fmt, Args), % gets indentation right
io_lib:fwrite("*** ~s ***\n~s\n\n", [Title, Msg]).
+-ifdef(TEST).
+format_exception_test_() ->
+ [?_assertMatch(
+ "\nymmud:rorre"++_,
+ lists:reverse(lists:flatten(
+ format_exception(try erlang:error(dummy)
+ catch C:R -> {C, R, erlang:get_stacktrace()}
+ end)))),
+ ?_assertMatch(
+ "\nymmud:rorre"++_,
+ lists:reverse(lists:flatten(
+ format_exception(try erlang:error(dummy, [a])
+ catch C:R -> {C, R, erlang:get_stacktrace()}
+ end))))].
+-endif.
+
+%% ---------------------------------------------------------------------
+%% detect common return values that are definitely not tests
+
+is_not_test(T) ->
+ case T of
+ ok -> true;
+ error -> true;
+ true -> true;
+ false -> true;
+ undefined -> true;
+ {ok, _} -> true;
+ {error, _} -> true;
+ {'EXIT', _} -> true;
+ N when is_number(N) -> true;
+ [N|_] when is_number(N) -> true;
+ X when is_binary(X) -> true;
+ X when is_pid(X) -> true;
+ X when is_port(X) -> true;
+ X when is_reference(X) -> true;
+ _ -> false
+ end.
%% ---------------------------------------------------------------------
%% Deep list iterator; accepts improper lists/sublists, and also accepts
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index 2a6cbca14d..46b8c8b503 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -156,9 +156,33 @@ handle_end(test, Data, St) ->
St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
%% Cancel group does not give information on the individual cancelled test case
-%% We ignore this event
-handle_cancel(group, _Data, St) ->
- St;
+%% We ignore this event...
+handle_cancel(group, Data, St) ->
+ %% ...except when it tells us that a fixture setup or cleanup failed.
+ case proplists:get_value(reason, Data) of
+ {abort, {SomethingFailed, Exception}}
+ when SomethingFailed =:= setup_failed;
+ SomethingFailed =:= cleanup_failed ->
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
+
+ %% We don't have any proper name. Let's give all the
+ %% clues that we have.
+ Name = case SomethingFailed of
+ setup_failed -> "fixture setup ";
+ cleanup_failed -> "fixture cleanup "
+ end
+ ++ io_lib:format("~p", [proplists:get_value(id, Data)]),
+ Desc = format_desc(proplists:get_value(desc, Data)),
+ TestCase = #testcase{
+ name = Name, description = Desc,
+ time = 0, output = <<>>},
+ NewTestSuite = add_testcase_to_testsuite({error, Exception}, TestCase, TestSuite),
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)};
+ _ ->
+ St
+ end;
handle_cancel(test, Data, St) ->
%% Retrieve existing test suite:
[GroupId|_] = proplists:get_value(id, Data),
@@ -232,7 +256,7 @@ write_reports(TestSuites, XmlDir) ->
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
+ case file:open(Filename, [write,{encoding,utf8}]) of
{ok, FileDescriptor} ->
try
write_report_to(TestSuite, FileDescriptor)
diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl
index bca49ae626..9cf40a738d 100644
--- a/lib/eunit/src/eunit_test.erl
+++ b/lib/eunit/src/eunit_test.erl
@@ -21,8 +21,7 @@
-module(eunit_test).
--export([run_testfun/1, function_wrapper/2, enter_context/4,
- multi_setup/1]).
+-export([run_testfun/1, mf_wrapper/2, enter_context/4, multi_setup/1]).
-include("eunit.hrl").
@@ -43,8 +42,12 @@ get_stacktrace(Ts) ->
prune_trace([{eunit_data, _, _} | Rest], Tail) ->
prune_trace(Rest, Tail);
+prune_trace([{eunit_data, _, _, _} | Rest], Tail) ->
+ prune_trace(Rest, Tail);
prune_trace([{?MODULE, _, _} | _Rest], Tail) ->
Tail;
+prune_trace([{?MODULE, _, _, _} | _Rest], Tail) ->
+ Tail;
prune_trace([T | Ts], Tail) ->
[T | prune_trace(Ts, Tail)];
prune_trace([], Tail) ->
@@ -258,7 +261,7 @@ macro_test_() ->
%% @type wrapperError() = {no_such_function, mfa()}
%% | {module_not_found, moduleName()}
-function_wrapper(M, F) ->
+mf_wrapper(M, F) ->
fun () ->
try M:F()
catch
@@ -289,12 +292,12 @@ fail(Term) ->
wrapper_test_() ->
{"error handling in function wrapper",
[?_assertException(throw, {module_not_found, eunit_nonexisting},
- run_testfun(function_wrapper(eunit_nonexisting,test))),
+ run_testfun(mf_wrapper(eunit_nonexisting,test))),
?_assertException(throw,
{no_such_function, {?MODULE,nonexisting_test,0}},
- run_testfun(function_wrapper(?MODULE,nonexisting_test))),
+ run_testfun(mf_wrapper(?MODULE,nonexisting_test))),
?_test({error, {error, undef, _T}}
- = run_testfun(function_wrapper(?MODULE,wrapper_test_exported_)))
+ = run_testfun(mf_wrapper(?MODULE,wrapper_test_exported_)))
]}.
%% this must be exported (done automatically by the autoexport transform)
@@ -319,6 +322,17 @@ enter_context(Setup, Cleanup, Instantiate, Callback) ->
R ->
try Instantiate(R) of
T ->
+ case eunit_lib:is_not_test(T) of
+ true ->
+ catch throw(error), % generate a stack trace
+ {module,M} = erlang:fun_info(Instantiate, module),
+ {name,N} = erlang:fun_info(Instantiate, name),
+ {arity,A} = erlang:fun_info(Instantiate, arity),
+ context_error({bad_instantiator, {{M,N,A},T}},
+ error, badarg);
+ false ->
+ ok
+ end,
try Callback(T) %% call back to client code
after
%% Always run cleanup; client may be an idiot
diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl
index e3e7b710b2..f21b2da3d3 100644
--- a/lib/eunit/src/eunit_tty.erl
+++ b/lib/eunit/src/eunit_tty.erl
@@ -44,6 +44,7 @@ start(Options) ->
init(Options) ->
St = #state{verbose = proplists:get_bool(verbose, Options)},
+ put(no_tty, proplists:get_bool(no_tty, Options)),
receive
{start, _Reference} ->
if St#state.verbose -> print_header();
@@ -59,30 +60,30 @@ terminate({ok, Data}, St) ->
Cancel = proplists:get_value(cancel, Data, 0),
if Fail =:= 0, Skip =:= 0, Cancel =:= 0 ->
if Pass =:= 0 ->
- io:fwrite(" There were no tests to run.\n");
+ fwrite(" There were no tests to run.\n");
true ->
if St#state.verbose -> print_bar();
true -> ok
end,
if Pass =:= 1 ->
- io:fwrite(" Test passed.\n");
+ fwrite(" Test passed.\n");
true ->
- io:fwrite(" All ~w tests passed.\n", [Pass])
+ fwrite(" All ~w tests passed.\n", [Pass])
end
end,
sync_end(ok);
true ->
print_bar(),
- io:fwrite(" Failed: ~w. Skipped: ~w. Passed: ~w.\n",
- [Fail, Skip, Pass]),
+ fwrite(" Failed: ~w. Skipped: ~w. Passed: ~w.\n",
+ [Fail, Skip, Pass]),
if Cancel =/= 0 ->
- io:fwrite("One or more tests were cancelled.\n");
+ fwrite("One or more tests were cancelled.\n");
true -> ok
end,
sync_end(error)
end;
terminate({error, Reason}, _St) ->
- io:fwrite("Internal error: ~P.\n", [Reason, 25]),
+ fwrite("Internal error: ~P.\n", [Reason, 25]),
sync_end(error).
sync_end(Result) ->
@@ -93,10 +94,10 @@ sync_end(Result) ->
end.
print_header() ->
- io:fwrite("======================== EUnit ========================\n").
+ fwrite("======================== EUnit ========================\n").
print_bar() ->
- io:fwrite("=======================================================\n").
+ fwrite("=======================================================\n").
handle_begin(group, Data, St) ->
@@ -170,18 +171,18 @@ handle_cancel(test, Data, St) ->
indent(N) when is_integer(N), N >= 1 ->
- io:put_chars(lists:duplicate(N * 2, $\s));
+ fwrite(lists:duplicate(N * 2, $\s));
indent(_N) ->
ok.
print_group_start(I, Desc) ->
indent(I),
- io:fwrite("~s\n", [Desc]).
+ fwrite("~s\n", [Desc]).
print_group_end(I, Time) ->
if Time > 0 ->
indent(I),
- io:fwrite("[done in ~.3f s]\n", [Time/1000]);
+ fwrite("[done in ~.3f s]\n", [Time/1000]);
true ->
ok
end.
@@ -198,9 +199,9 @@ print_test_begin(I, Data) ->
end,
case proplists:get_value(source, Data) of
{Module, Name, _Arity} ->
- io:fwrite("~s:~s ~s~s...", [Module, L, Name, D]);
+ fwrite("~s:~s ~s~s...", [Module, L, Name, D]);
_ ->
- io:fwrite("~s~s...", [L, D])
+ fwrite("~s~s...", [L, D])
end.
print_test_end(Data) ->
@@ -208,36 +209,35 @@ print_test_end(Data) ->
T = if Time > 0 -> io_lib:fwrite("[~.3f s] ", [Time/1000]);
true -> ""
end,
- io:fwrite("~sok\n", [T]).
+ fwrite("~sok\n", [T]).
print_test_error({error, Exception}, Data) ->
Output = proplists:get_value(output, Data),
- io:fwrite("*failed*\n::~s",
- [eunit_lib:format_exception(Exception)]),
+ fwrite("*failed*\n~s", [eunit_lib:format_exception(Exception)]),
case Output of
<<>> ->
- io:put_chars("\n\n");
+ fwrite("\n\n");
<<Text:800/binary, _:1/binary, _/binary>> ->
- io:fwrite(" output:<<\"~s\">>...\n\n", [Text]);
+ fwrite(" output:<<\"~s\">>...\n\n", [Text]);
_ ->
- io:fwrite(" output:<<\"~s\">>\n\n", [Output])
+ fwrite(" output:<<\"~s\">>\n\n", [Output])
end;
print_test_error({skipped, Reason}, _) ->
- io:fwrite("*did not run*\n::~s\n", [format_skipped(Reason)]).
+ fwrite("*did not run*\n::~s\n", [format_skipped(Reason)]).
format_skipped({module_not_found, M}) ->
- io_lib:format("missing module: ~w", [M]);
+ io_lib:fwrite("missing module: ~w", [M]);
format_skipped({no_such_function, {M,F,A}}) ->
- io_lib:format("no such function: ~w:~w/~w", [M,F,A]).
+ io_lib:fwrite("no such function: ~w:~w/~w", [M,F,A]).
print_test_cancel(Reason) ->
- io:fwrite(format_cancel(Reason)).
+ fwrite(format_cancel(Reason)).
print_group_cancel(_I, {blame, _}) ->
ok;
print_group_cancel(I, Reason) ->
indent(I),
- io:fwrite(format_cancel(Reason)).
+ fwrite(format_cancel(Reason)).
format_cancel(undefined) ->
"*skipped*\n";
@@ -253,3 +253,12 @@ format_cancel({exit, Reason}) ->
[Reason, 15]);
format_cancel({abort, Reason}) ->
eunit_lib:format_error(Reason).
+
+fwrite(String) ->
+ fwrite(String, []).
+
+fwrite(String, Args) ->
+ case get(no_tty) of
+ false -> io:fwrite(String, Args);
+ true -> ok
+ end.
diff --git a/lib/eunit/test/Makefile b/lib/eunit/test/Makefile
index a2d276f619..1586dd8857 100644
--- a/lib/eunit/test/Makefile
+++ b/lib/eunit/test/Makefile
@@ -74,9 +74,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) eunit.spec $(EMAKEFILE) \
$(COVERFILE) $(ERL_FILES) \
- $(RELSYSDIR)
+ "$(RELSYSDIR)"
release_docs_spec:
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index b0a77a225b..174d197117 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.2.1
+EUNIT_VSN = 2.2.3
diff --git a/lib/gs/contribs/bonk/Makefile b/lib/gs/contribs/bonk/Makefile
index be096824dd..dc92149784 100644
--- a/lib/gs/contribs/bonk/Makefile
+++ b/lib/gs/contribs/bonk/Makefile
@@ -94,14 +94,14 @@ $(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/bonk/bitmaps
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) $(RELSYSDIR)/bonk/bitmaps
- $(INSTALL_DIR) $(RELSYSDIR)/bonk/sounds
- $(INSTALL_DATA) $(SOUNDS) $(RELSYSDIR)/bonk/sounds
- $(INSTALL_DIR) $(RELSYSDIR)/bonk
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) $(RELSYSDIR)/bonk
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/bonk/bitmaps"
+ $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/bonk/bitmaps"
+ $(INSTALL_DIR) "$(RELSYSDIR)/bonk/sounds"
+ $(INSTALL_DATA) $(SOUNDS) "$(RELSYSDIR)/bonk/sounds"
+ $(INSTALL_DIR) "$(RELSYSDIR)/bonk"
+ $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/bonk"
release_docs_spec:
diff --git a/lib/gs/contribs/bonk/bonk.erl b/lib/gs/contribs/bonk/bonk.erl
index 79f01bf659..3d1e8ce34b 100644
--- a/lib/gs/contribs/bonk/bonk.erl
+++ b/lib/gs/contribs/bonk/bonk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,12 @@
%%
-module(bonk).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-export([run/0, run/1,bonk_dir/0,start/0]).
-record(colors, {miss, x, bomb, face}).
diff --git a/lib/gs/contribs/cols/Makefile b/lib/gs/contribs/cols/Makefile
index 75ca75ffc0..4ce4204c92 100644
--- a/lib/gs/contribs/cols/Makefile
+++ b/lib/gs/contribs/cols/Makefile
@@ -91,12 +91,12 @@ $(EBIN)/help.gif: help.gif
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/cols/bitmaps
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) $(RELSYSDIR)/cols/bitmaps
- $(INSTALL_DIR) $(RELSYSDIR)/cols
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) $(RELSYSDIR)/cols
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/cols/bitmaps"
+ $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/cols/bitmaps"
+ $(INSTALL_DIR) "$(RELSYSDIR)/cols"
+ $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/cols"
release_docs_spec:
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
index 111c9a58f1..d1a1b791c3 100644
--- a/lib/gs/contribs/cols/cols.erl
+++ b/lib/gs/contribs/cols/cols.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,12 @@
%%
-module(cols).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0, init/0]).
diff --git a/lib/gs/contribs/cols/highscore.erl b/lib/gs/contribs/cols/highscore.erl
index 9ffbea50a7..7f80debb07 100644
--- a/lib/gs/contribs/cols/highscore.erl
+++ b/lib/gs/contribs/cols/highscore.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,13 @@
%%
-module(highscore).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([run/2]).
diff --git a/lib/gs/contribs/mandel/Makefile b/lib/gs/contribs/mandel/Makefile
index 61a7a612e0..451ece2c8f 100644
--- a/lib/gs/contribs/mandel/Makefile
+++ b/lib/gs/contribs/mandel/Makefile
@@ -90,11 +90,11 @@ $(EBIN)/help.gif: help.gif
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/mandel/bitmaps
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) $(RELSYSDIR)/mandel/bitmaps
- $(INSTALL_DIR) $(RELSYSDIR)/mandel
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) $(RELSYSDIR)/mandel
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/mandel/bitmaps"
+ $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/mandel/bitmaps"
+ $(INSTALL_DIR) "$(RELSYSDIR)/mandel"
+ $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/mandel"
release_docs_spec:
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
index 0f1df5c665..8ecd649532 100644
--- a/lib/gs/contribs/mandel/mandel.erl
+++ b/lib/gs/contribs/mandel/mandel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,11 @@
%%
-module(mandel).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,image,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-author('(mbj,eklas)@erlang.ericsson.se').
%% User's interface
diff --git a/lib/gs/contribs/othello/Makefile b/lib/gs/contribs/othello/Makefile
index b81b35fb55..5f09f2ed13 100644
--- a/lib/gs/contribs/othello/Makefile
+++ b/lib/gs/contribs/othello/Makefile
@@ -89,12 +89,12 @@ $(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/othello
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) $(RELSYSDIR)/othello
- $(INSTALL_DIR) $(RELSYSDIR)/othello/priv
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) $(RELSYSDIR)/othello/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/othello"
+ $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/othello"
+ $(INSTALL_DIR) "$(RELSYSDIR)/othello/priv"
+ $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/othello/priv"
release_docs_spec:
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
index 212ba9bfe1..aaa4062ba8 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,12 @@
%%
-module(othello_board).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-export([start/0,stop/0,init/0]).
diff --git a/lib/gs/doc/src/Makefile b/lib/gs/doc/src/Makefile
index 192dd67a52..14204c52fc 100644
--- a/lib/gs/doc/src/Makefile
+++ b/lib/gs/doc/src/Makefile
@@ -144,13 +144,13 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- (/bin/cp -rf $(HTMLDIR) $(RELSYSDIR)/doc)
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ (/bin/cp -rf $(HTMLDIR) "$(RELSYSDIR)/doc")
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/gs/doc/src/gs.xml b/lib/gs/doc/src/gs.xml
index f2182fc673..417163e963 100644
--- a/lib/gs/doc/src/gs.xml
+++ b/lib/gs/doc/src/gs.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2000</year>
- <year>2010</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -39,9 +39,7 @@
graphical user interface.
</p>
<p>
- GS is not maintained and we plan to deprecate and remove it from
- the distribution as soon as possible, maybe already in the next
- major release (R15).
+ GS is deprecated and will be removed in the R16 release.
</p>
</warning>
<p>The Graphics System, GS, is easy to learn and
diff --git a/lib/gs/doc/src/make.dep b/lib/gs/doc/src/make.dep
deleted file mode 100644
index b33ed3b2de..0000000000
--- a/lib/gs/doc/src/make.dep
+++ /dev/null
@@ -1,58 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex gs.tex gs_chapter1.tex gs_chapter2.tex \
- gs_chapter3.tex gs_chapter4.tex gs_chapter5.tex \
- gs_chapter6.tex gs_chapter7.tex gs_chapter8.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-gs_chapter2.tex: examples/ex1.erl examples/ex2.erl
-
-gs_chapter4.tex: examples/ex3.erl examples/ex4.erl examples/ex5.erl \
- examples/ex6.erl
-
-gs_chapter5.tex: examples/ex15.erl
-
-gs_chapter6.tex: examples/ex16.erl
-
-gs_chapter7.tex: examples/ex17.erl
-
-gs_chapter8.tex: examples/ex10.erl examples/ex11.erl examples/ex12.erl \
- examples/ex13.erl examples/ex14.erl examples/ex7.erl \
- examples/ex8.erl examples/ex9.erl
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: pics/gs1-1-image-1.ps pics/gs1-1-image-2.ps \
- pics/gs1-1-image-3.ps
-
-book.dvi: pics/ex1.ps pics/gs1-1-image-4.ps
-
-book.dvi: pics/ex15.ps
-
-book.dvi: pics/ex16.ps
-
-book.dvi: pics/packer1.ps pics/packer2.ps
-
-book.dvi: pics/arc.ps pics/buttons.ps pics/ex10.ps pics/ex11.ps \
- pics/ex12.ps pics/ex13.ps pics/ex14.ps pics/ex8.ps \
- pics/ex9.ps pics/image.ps pics/line.ps pics/oval.ps \
- pics/polygon.ps pics/rectangle.ps pics/text.ps \
- pics/window.ps
-
diff --git a/lib/gs/doc/src/notes.xml b/lib/gs/doc/src/notes.xml
index c32db495a1..d1b74ecfb1 100644
--- a/lib/gs/doc/src/notes.xml
+++ b/lib/gs/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,7 +30,51 @@
</header>
<p>This document describes the changes made to the GS application.</p>
- <section><title>GS 1.5.14</title>
+ <section><title>GS 1.5.15.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The GS applications is now deprecated and will be
+ removed in the R16 release. The following GS-based
+ applications have been superseded by the Observer
+ application and will removed in R16: Appmon, Pman,
+ Tv.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9907</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>GS 1.5.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>GS 1.5.14</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/gs/examples/Makefile b/lib/gs/examples/Makefile
index 10b166b207..d214cd2256 100644
--- a/lib/gs/examples/Makefile
+++ b/lib/gs/examples/Makefile
@@ -87,9 +87,9 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
release_docs_spec:
diff --git a/lib/gs/examples/ball.erl b/lib/gs/examples/ball.erl
index 3f91a7b379..42e3522fc7 100644
--- a/lib/gs/examples/ball.erl
+++ b/lib/gs/examples/ball.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(ball).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,oval,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/browser.erl b/lib/gs/examples/browser.erl
index 1dba5a915b..dd01e0299b 100644
--- a/lib/gs/examples/browser.erl
+++ b/lib/gs/examples/browser.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,14 @@
%% ------------------------------------------------------------
-module(browser).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,start/2,init/3]).
diff --git a/lib/gs/examples/calc.erl b/lib/gs/examples/calc.erl
index 992b8adb4e..9ed8ed4dbd 100644
--- a/lib/gs/examples/calc.erl
+++ b/lib/gs/examples/calc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% ------------------------------------------------------------
-module(calc).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,calc/0]).
diff --git a/lib/gs/examples/calc2.erl b/lib/gs/examples/calc2.erl
index 0e841397f6..51f9c31d28 100644
--- a/lib/gs/examples/calc2.erl
+++ b/lib/gs/examples/calc2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(calc2).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
+
-export([start/0,calc/0]).
start() ->
diff --git a/lib/gs/examples/color_demo.erl b/lib/gs/examples/color_demo.erl
index 650f853061..5ebfe36d75 100644
--- a/lib/gs/examples/color_demo.erl
+++ b/lib/gs/examples/color_demo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,11 @@
%% ------------------------------------------------------------
-module(color_demo).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/color_demo2.erl b/lib/gs/examples/color_demo2.erl
index 817cc9ed7d..1c8db7a851 100644
--- a/lib/gs/examples/color_demo2.erl
+++ b/lib/gs/examples/color_demo2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,10 @@
%% ------------------------------------------------------------
-module(color_demo2).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/distrib_draw.erl b/lib/gs/examples/distrib_draw.erl
index ecb1386c25..fc821c6df4 100644
--- a/lib/gs/examples/distrib_draw.erl
+++ b/lib/gs/examples/distrib_draw.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%%
-module(distrib_draw).
+-compile([{nowarn_deprecated_function,{gs,canvas,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/2,init/0]).
diff --git a/lib/gs/examples/entry_demo.erl b/lib/gs/examples/entry_demo.erl
index a5ecfbc4d3..4cdbe7e279 100644
--- a/lib/gs/examples/entry_demo.erl
+++ b/lib/gs/examples/entry_demo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,12 @@
%% ------------------------------------------------------------
-module(entry_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/1]).
diff --git a/lib/gs/examples/event_test.erl b/lib/gs/examples/event_test.erl
index f6fcc9b4b9..3231df00e1 100644
--- a/lib/gs/examples/event_test.erl
+++ b/lib/gs/examples/event_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,9 @@
%% Demo for testing some events
-module(event_test).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/file_dialog.erl b/lib/gs/examples/file_dialog.erl
index ff20321374..37b19a322c 100644
--- a/lib/gs/examples/file_dialog.erl
+++ b/lib/gs/examples/file_dialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% ------------------------------------------------------------
-module(file_dialog).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0,start/1,start/2,fs_init/3]).
diff --git a/lib/gs/examples/focus_demo.erl b/lib/gs/examples/focus_demo.erl
index b9d86866e6..990140d9bc 100644
--- a/lib/gs/examples/focus_demo.erl
+++ b/lib/gs/examples/focus_demo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% ------------------------------------------------------------
-module(focus_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/frac.erl b/lib/gs/examples/frac.erl
index 139a4be310..be77c8f5d4 100644
--- a/lib/gs/examples/frac.erl
+++ b/lib/gs/examples/frac.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,9 @@
%% Purpose : Fractal trees
-module(frac).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0, go/0, test/0, grow/2, expand/3, subst/2]).
diff --git a/lib/gs/examples/line_demo.erl b/lib/gs/examples/line_demo.erl
index c8a6a69e2e..32c2920878 100644
--- a/lib/gs/examples/line_demo.erl
+++ b/lib/gs/examples/line_demo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(line_demo).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0,line/3]).
diff --git a/lib/gs/examples/man.erl b/lib/gs/examples/man.erl
index a0ffd3364e..093ce854f8 100644
--- a/lib/gs/examples/man.erl
+++ b/lib/gs/examples/man.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,15 @@
%% ------------------------------------------------------------
-module(man).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/0,init/0]).
-export([man_list/0]).
diff --git a/lib/gs/examples/menu_demo.erl b/lib/gs/examples/menu_demo.erl
index c95fc33152..60e335c40b 100644
--- a/lib/gs/examples/menu_demo.erl
+++ b/lib/gs/examples/menu_demo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,12 @@
%%
-module(menu_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-compile(export_all).
diff --git a/lib/gs/examples/rubber.erl b/lib/gs/examples/rubber.erl
index ba263f07ac..a9fe403b12 100644
--- a/lib/gs/examples/rubber.erl
+++ b/lib/gs/examples/rubber.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,14 @@
%% ------------------------------------------------------------
-module(rubber).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0, init/0]).
diff --git a/lib/gs/src/Makefile b/lib/gs/src/Makefile
index 964966ba00..a9904161a4 100644
--- a/lib/gs/src/Makefile
+++ b/lib/gs/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
@@ -107,13 +107,13 @@ $(GSTK_GENERIC_TARGET): gstk_generic.hrl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
$(INSTALL_DATA) $(APP_SRC) $(ERL_FILES) $(HRL_FILES) $(GEN_HRL_FILES) \
- $(GSTK_GENERIC) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bitmap
- $(INSTALL_DATA) $(IMAGES) $(RELSYSDIR)/priv/bitmap
+ $(GSTK_GENERIC) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bitmap"
+ $(INSTALL_DATA) $(IMAGES) "$(RELSYSDIR)/priv/bitmap"
release_docs_spec:
diff --git a/lib/gs/src/gs.erl b/lib/gs/src/gs.erl
index 3e9a1c4b8b..c25c75766e 100644
--- a/lib/gs/src/gs.erl
+++ b/lib/gs/src/gs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,13 @@
%%
-module(gs).
-
+-deprecated(module).
+-compile([{nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,create_tree,2}},
+ {nowarn_deprecated_function,{gs,foreach,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% ----- Exports -----
-export([start/0, stop/0, start/1]).
diff --git a/lib/gs/src/gs_frontend.erl b/lib/gs/src/gs_frontend.erl
index 009b264e69..37f91cf37c 100644
--- a/lib/gs/src/gs_frontend.erl
+++ b/lib/gs/src/gs_frontend.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,8 @@
%%
-module(gs_frontend).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,error,2}}]).
-export([create/2,
config/2,
diff --git a/lib/gs/src/gs_make.erl b/lib/gs/src/gs_make.erl
index e41183f9bf..9acffcd62e 100644
--- a/lib/gs/src/gs_make.erl
+++ b/lib/gs/src/gs_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,7 @@
%%
-module(gs_make).
+-compile([{nowarn_deprecated_function,{gs,assq,2}}]).
-export([start/0]).
diff --git a/lib/gs/src/gse.erl b/lib/gs/src/gse.erl
index b3ea2af4d4..b63841bc20 100644
--- a/lib/gs/src/gse.erl
+++ b/lib/gs/src/gse.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,68 @@
%%%----------------------------------------------------------------------
-module(gse).
+-compile([{nowarn_deprecated_function,{gs,arc,2}},
+ {nowarn_deprecated_function,{gs,arc,3}},
+ {nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,canvas,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,create_tree,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,gridline,3}},
+ {nowarn_deprecated_function,{gs,image,2}},
+ {nowarn_deprecated_function,{gs,image,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,line,3}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,message,2}},
+ {nowarn_deprecated_function,{gs,message,3}},
+ {nowarn_deprecated_function,{gs,oval,2}},
+ {nowarn_deprecated_function,{gs,oval,3}},
+ {nowarn_deprecated_function,{gs,polygon,2}},
+ {nowarn_deprecated_function,{gs,polygon,3}},
+ {nowarn_deprecated_function,{gs,prompter,2}},
+ {nowarn_deprecated_function,{gs,prompter,3}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,rectangle,2}},
+ {nowarn_deprecated_function,{gs,rectangle,3}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,scale,3}},
+ {nowarn_deprecated_function,{gs,scrollbar,2}},
+ {nowarn_deprecated_function,{gs,scrollbar,3}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,start,1}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,text,3}},
+ {nowarn_deprecated_function,{gs,window,2}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
%%-compile(export_all).
-export([
diff --git a/lib/gs/src/gstk.erl b/lib/gs/src/gstk.erl
index 6f83cf8be4..04ca9b4722 100644
--- a/lib/gs/src/gstk.erl
+++ b/lib/gs/src/gstk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,6 +20,8 @@
%%
-module(gstk).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,creation_error,2}}]).
-export([start_link/4,
stop/1,
diff --git a/lib/gs/src/gstk_arc.erl b/lib/gs/src/gstk_arc.erl
index 8e80ef92b5..1441bb0b32 100644
--- a/lib/gs/src/gstk_arc.erl
+++ b/lib/gs/src/gstk_arc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% ------------------------------------------------------------
-module(gstk_arc).
+-compile([{nowarn_deprecated_function,{gs,creation_error,2}}]).
%%-----------------------------------------------------------------------------
%% ARC OPTIONS
diff --git a/lib/gs/src/gstk_canvas.erl b/lib/gs/src/gstk_canvas.erl
index 868b3020fe..34e4be0667 100644
--- a/lib/gs/src/gstk_canvas.erl
+++ b/lib/gs/src/gstk_canvas.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,6 +23,8 @@
%% ------------------------------------------------------------
-module(gstk_canvas).
+-compile([{nowarn_deprecated_function,{gs,pair,2}},
+ {nowarn_deprecated_function,{gs,val,2}}]).
%%-----------------------------------------------------------------------------
%% CANVAS OPTIONS
diff --git a/lib/gs/src/gstk_editor.erl b/lib/gs/src/gstk_editor.erl
index 3e0c8240e4..e918d93147 100644
--- a/lib/gs/src/gstk_editor.erl
+++ b/lib/gs/src/gstk_editor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,9 @@
%% ------------------------------------------------------------
-module(gstk_editor).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,error,2}},
+ {nowarn_deprecated_function,{gs,val,2}}]).
%%------------------------------------------------------------------------------
%% CANVAS OPTIONS
@@ -243,14 +246,14 @@ option(Option, Gstkid, _MainW, DB, Editor) ->
Editor, " ins ",AI," ", gstk:to_ascii(Text)]};
clear -> {c, [Editor, " delete 1.0 end"]};
{load, File} ->
- {ok, F2,_} = regexp:gsub(File, [92,92], "/"),
+ F2 = re:replace(File, [92,92], "/", [global,{return,list}]),
case gstk:call(["ed_load ", Editor, " ", gstk:to_ascii(F2)]) of
{result, _} -> none;
{bad_result,Re} ->
{error,{no_such_file,editor,load,F2,Re}}
end;
{save, File} ->
- {ok, F2,_} = regexp:gsub(File, [92,92], "/"),
+ F2 = re:replace(File, [92,92], "/", [global,{return,list}]),
case gstk:call(["ed_save ",Editor," ",gstk:to_ascii(F2)]) of
{result, _} -> none;
{bad_result,Re} ->
diff --git a/lib/gs/src/gstk_entry.erl b/lib/gs/src/gstk_entry.erl
index 14f7831151..b10b6460f2 100644
--- a/lib/gs/src/gstk_entry.erl
+++ b/lib/gs/src/gstk_entry.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% ------------------------------------------------------------
-module(gstk_entry).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%------------------------------------------------------------------------------
%% ENTRY OPTIONS
diff --git a/lib/gs/src/gstk_generic.erl b/lib/gs/src/gstk_generic.erl
index 3ddb69efc5..9b0efd07c1 100644
--- a/lib/gs/src/gstk_generic.erl
+++ b/lib/gs/src/gstk_generic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,7 @@
%%
-module(gstk_generic).
+-compile([{nowarn_deprecated_function,{gs,assq,2}}]).
-export([out_opts/8,
read_option/5,
@@ -322,7 +323,7 @@ handle_external_opt_call([Opt|Options],Gstkid,TkW,DB,ExtraArg,ExtRes,S,P,C) ->
end.
handle_external_read(Res) ->
- case Res of
+ _ = case Res of
{bad_result,{Objtype,Reason,Option}} ->
{error,{Objtype,Reason,Option}};
_ -> ok
@@ -414,7 +415,7 @@ gen_font(_Opt,Gstkid,_TkW,DB,_ExtraArg) ->
gen_label({text,Text},Opts,Gstkid,TkW,DB,ExtraArg,S,P,C) ->
out_opts(Opts,Gstkid,TkW,DB,ExtraArg,[" -text ", gstk:to_ascii(Text), " -bi {}"|S],P,C);
gen_label({image,Img},Opts,Gstkid,TkW,DB,ExtraArg,S,P,C) ->
- {ok, I2,_} = regexp:gsub(Img, [92,92], "/"),
+ I2 = re:replace(Img, [92,92], "/", [global,{return,list}]),
out_opts(Opts,Gstkid,TkW,DB,ExtraArg,[" -bi \"@", I2, "\" -text {}"|S],P,C).
gen_label(_Opt,_Gstkid,TkW,_DB,_ExtraArg) ->
case gstk:call([TkW, " cg -bit"]) of
diff --git a/lib/gs/src/gstk_grid.erl b/lib/gs/src/gstk_grid.erl
index 4189246822..5f4f4a24f0 100644
--- a/lib/gs/src/gstk_grid.erl
+++ b/lib/gs/src/gstk_grid.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,7 @@
%%
-module(gstk_grid).
+-compile([{nowarn_deprecated_function,{gs,val,2}}]).
-export([event/5,create/3,config/3,option/5,read/3,delete/2,destroy/2,
mk_create_opts_for_child/4,read_option/5]).
diff --git a/lib/gs/src/gstk_gridline.erl b/lib/gs/src/gstk_gridline.erl
index c1dd5a1443..914a7f1c6d 100644
--- a/lib/gs/src/gstk_gridline.erl
+++ b/lib/gs/src/gstk_gridline.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
%%
-module(gstk_gridline).
+-compile([{nowarn_deprecated_function,{gs,val,2}},
+ {nowarn_deprecated_function,{gs,val,3}}]).
-export([event/5,create/3,config/3,option/5,read/3,delete/2,destroy/3,
read_option/5]).
diff --git a/lib/gs/src/gstk_image.erl b/lib/gs/src/gstk_image.erl
index 5ad37cf6de..7dbcce3cf9 100644
--- a/lib/gs/src/gstk_image.erl
+++ b/lib/gs/src/gstk_image.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% ------------------------------------------------------------
-module(gstk_image).
+-compile([{nowarn_deprecated_function,{gs,pair,2}}]).
%%-----------------------------------------------------------------------------
%% BITMAP OPTIONS
@@ -227,10 +228,10 @@ event(DB, Gstkid, Etype, Edata, Args) ->
option(Option, Gstkid, _Canvas, _DB, _AItem) ->
case Option of
{bitmap, Bitmap} ->
- {ok, BF,_} = regexp:gsub(Bitmap, [92,92], "/"),
+ BF = re:replace(Bitmap, [92,92], "/", [global,{return,list}]),
{s, [" -bi @", BF]};
{load_gif, File} ->
- {ok, F2,_} = regexp:gsub(File, [92,92], "/"),
+ F2 = re:replace(File, [92,92], "/", [global,{return,list}]),
{Photo_item, _item} = Gstkid#gstkid.widget_data,
{c,[Photo_item, " configure -file ", gstk:to_ascii(F2)]};
{pix_val, {Coords,Color}} ->
diff --git a/lib/gs/src/gstk_menu.erl b/lib/gs/src/gstk_menu.erl
index 3957951a35..09f3208299 100644
--- a/lib/gs/src/gstk_menu.erl
+++ b/lib/gs/src/gstk_menu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%%------------------------------------------------------------------------------
-module(gstk_menu).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%------------------------------------------------------------------------------
%% MENU OPTIONS
diff --git a/lib/gs/src/gstk_menuitem.erl b/lib/gs/src/gstk_menuitem.erl
index 36a9253598..03aca75b80 100644
--- a/lib/gs/src/gstk_menuitem.erl
+++ b/lib/gs/src/gstk_menuitem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% ------------------------------------------------------------
-module(gstk_menuitem).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%-----------------------------------------------------------------------------
%% MENUITEM OPTIONS
diff --git a/lib/gs/src/gstk_port_handler.erl b/lib/gs/src/gstk_port_handler.erl
index 93f3e58dc2..3ecc6ac5d6 100644
--- a/lib/gs/src/gstk_port_handler.erl
+++ b/lib/gs/src/gstk_port_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,7 @@
%% ------------------------------------------------------------
-module(gstk_port_handler).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
-include("gstk.hrl").
diff --git a/lib/gs/src/gstk_rectangle.erl b/lib/gs/src/gstk_rectangle.erl
index 1e02977c9a..e26db2ed15 100644
--- a/lib/gs/src/gstk_rectangle.erl
+++ b/lib/gs/src/gstk_rectangle.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% ------------------------------------------------------------
-module(gstk_rectangle).
+-compile([{nowarn_deprecated_function,{gs,pair,2}}]).
%%-----------------------------------------------------------------------------
%% RECTANGLE OPTIONS
diff --git a/lib/gs/src/gstk_window.erl b/lib/gs/src/gstk_window.erl
index acac452ed1..d9ab16df37 100644
--- a/lib/gs/src/gstk_window.erl
+++ b/lib/gs/src/gstk_window.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% ------------------------------------------------------------
-module(gstk_window).
+-compile([{nowarn_deprecated_function,{gs,destroy,1}}]).
%%------------------------------------------------------------------------------
%% WINDOW OPTIONS
diff --git a/lib/gs/src/tcl2erl.erl b/lib/gs/src/tcl2erl.erl
index 8845cf0b9a..d93f589656 100644
--- a/lib/gs/src/tcl2erl.erl
+++ b/lib/gs/src/tcl2erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,7 @@
%% ------------------------------------------------------------
-module(tcl2erl).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
-export([parse_event/1,
ret_int/1,
diff --git a/lib/gs/src/tool_file_dialog.erl b/lib/gs/src/tool_file_dialog.erl
index 6b2c2e8c81..f47b4b9e3f 100644
--- a/lib/gs/src/tool_file_dialog.erl
+++ b/lib/gs/src/tool_file_dialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,16 @@
%%
-module(tool_file_dialog).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
+
-export([start/1]).
-record(opts, {type, % open | save | multiselect
diff --git a/lib/gs/src/tool_utils.erl b/lib/gs/src/tool_utils.erl
index b07e92c4f0..c6b75466be 100644
--- a/lib/gs/src/tool_utils.erl
+++ b/lib/gs/src/tool_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,11 @@
%%
-module(tool_utils).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
+
-include_lib("kernel/include/file.hrl").
%%%---------------------------------------------------------------------
@@ -98,7 +103,8 @@ open_help_default(Parent, File) ->
_Else -> "netscape -remote \"openURL(file:" ++ File ++ ")\""
end;
{win32,_AnyType} ->
- "netscape.exe -h " ++ regexp:gsub(File,"\\\\","/");
+ "netscape.exe -h " ++
+ re:replace(File,"\\\\","/",[global,{return,list}]);
_Other ->
unknown
end;
diff --git a/lib/gs/tcl/Makefile.in b/lib/gs/tcl/Makefile.in
index dce34a4baa..0bccb60c7b 100644
--- a/lib/gs/tcl/Makefile.in
+++ b/lib/gs/tcl/Makefile.in
@@ -74,10 +74,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(TCL_FILES) $(EXTRA_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(TCL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/priv"
ifneq ($(TCL_TAR),)
- gzip -dc $(TCL_TAR) | (cd $(RELSYSDIR)/priv && tar -xf -)
+ gzip -dc $(TCL_TAR) | (cd "$(RELSYSDIR)/priv" && tar -xf -)
endif
release_docs_spec:
diff --git a/lib/gs/vsn.mk b/lib/gs/vsn.mk
index 4894c6c13a..48249cb3d0 100644
--- a/lib/gs/vsn.mk
+++ b/lib/gs/vsn.mk
@@ -1,2 +1,2 @@
-GS_VSN = 1.5.14
+GS_VSN = 1.5.15.1
diff --git a/lib/hipe/Makefile b/lib/hipe/Makefile
index 6682c9aac0..2294f98158 100644
--- a/lib/hipe/Makefile
+++ b/lib/hipe/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The 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,8 +37,13 @@ else
SUB_DIRECTORIES = $(ALWAYS_SUBDIRS)
endif
+
include native.mk
+ifndef EBIN
+EBIN = ../ebin
+endif
+
#
# Default Subdir Targets
#
@@ -52,12 +57,20 @@ edocs:
fi
all-subdirs:
- -for dir in $(SUB_DIRECTORIES); do \
- (cd $$dir; $(MAKE) $(MAKETARGET) EBIN=../ebin; cd ..); \
+ for dir in $(SUB_DIRECTORIES); do \
+ (cd $$dir; $(MAKE) $(MAKETARGET) EBIN=$(EBIN); cd ..); \
+ done
+
+# distclean and realclean should clean the bootstrap files
+all-subdirs-x:
+ for dir in $(SUB_DIRECTORIES); do \
+ (cd $$dir; $(MAKE) $(MAKETARGET) EBIN=../boot_ebin; cd ..); \
done
+clean:
+ $(MAKE) MAKETARGET="clean" all-subdirs all-subdirs-x
distclean:
- $(MAKE) MAKETARGET="distclean" all-subdirs
+ $(MAKE) MAKETARGET="distclean" all-subdirs all-subdirs-x
realclean:
- $(MAKE) MAKETARGET="realclean" all-subdirs
+ $(MAKE) MAKETARGET="realclean" all-subdirs all-subdirs-x
diff --git a/lib/hipe/amd64/Makefile b/lib/hipe/amd64/Makefile
index 58377e5349..50cd024d72 100644
--- a/lib/hipe/amd64/Makefile
+++ b/lib/hipe/amd64/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -89,6 +89,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -102,8 +105,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/arm/Makefile b/lib/hipe/arm/Makefile
index 3f60cd77cc..651b82f1ed 100644
--- a/lib/hipe/arm/Makefile
+++ b/lib/hipe/arm/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2010. All Rights Reserved.
+# Copyright Ericsson AB 2005-2012. All Rights Reserved.
#
# The 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,6 +90,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -103,8 +106,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/boot_ebin/.gitignore b/lib/hipe/boot_ebin/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/hipe/boot_ebin/.gitignore
diff --git a/lib/hipe/cerl/Makefile b/lib/hipe/cerl/Makefile
index 7fcc44d27d..506e993ff4 100644
--- a/lib/hipe/cerl/Makefile
+++ b/lib/hipe/cerl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2010. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The 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 @@ RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN)
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-MODULES = cerl_cconv cerl_closurean cerl_hipeify cerl_hybrid_transform \
+MODULES = cerl_cconv cerl_closurean cerl_hipeify \
cerl_lib cerl_messagean cerl_pmatch cerl_prettypr cerl_to_icode \
cerl_typean erl_bif_types erl_types
@@ -82,6 +82,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -97,10 +100,10 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/cerl
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/cerl
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/cerl"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/cerl"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/cerl/cerl_hipe_primops.hrl b/lib/hipe/cerl/cerl_hipe_primops.hrl
index 36b1b62901..a777cd0108 100644
--- a/lib/hipe/cerl/cerl_hipe_primops.hrl
+++ b/lib/hipe/cerl/cerl_hipe_primops.hrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,6 @@
-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
diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl
index 8f6c3561c9..3351be77f2 100644
--- a/lib/hipe/cerl/cerl_hipeify.erl
+++ b/lib/hipe/cerl/cerl_hipeify.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -392,7 +392,6 @@ 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};
diff --git a/lib/hipe/cerl/cerl_hybrid_transform.erl b/lib/hipe/cerl/cerl_hybrid_transform.erl
deleted file mode 100644
index b248b0ccd0..0000000000
--- a/lib/hipe/cerl/cerl_hybrid_transform.erl
+++ /dev/null
@@ -1,153 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(cerl_hybrid_transform).
-
-%% Use compile option `{core_transform, cerl_hybrid_transform}' to
-%% insert this as a compilation pass.
-
--export([transform/2, core_transform/2]).
-
--spec core_transform(cerl:cerl(), [term()]) -> cerl:cerl().
-
-core_transform(Code, Opts) ->
- cerl:to_records(transform(cerl:from_records(Code), Opts)).
-
--spec transform(cerl:cerl(), [term()]) -> cerl:cerl().
-
-transform(Code, _Opts) ->
- Code0 = cerl_trees:map(fun unfold_literal/1, Code),
- {Code1, _} = cerl_trees:label(Code0),
- io:fwrite("Running hybrid heap analysis..."),
- {T1,_} = statistics(runtime),
- {Code2, _, Vars} = cerl_messagean:annotate(Code1),
- {T2,_} = statistics(runtime),
- io:fwrite("(~w ms), transform...", [T2 - T1]),
- Code3 = rewrite(Code2, Vars),
- io:fwrite("done.\n"),
- cerl_trees:map(fun fold_literal/1, Code3).
-
-unfold_literal(T) ->
- cerl:unfold_literal(T).
-
-fold_literal(T) ->
- cerl:fold_literal(T).
-
-%% If escape-annotated:
-%% {...} => hybrid:tuple([...])
-%% [H | T] => hybrid:cons(H, T)
-%%
-%% Wrapper for args to hybrid:cons/hybrid:tuple that may need copying:
-%% hybrid:copy(A)
-
-rewrite(Node, Vars) ->
- case cerl:type(Node) of
- tuple ->
- Es = rewrite_list(cerl:tuple_es(Node), Vars),
- case is_escaping(Node) of
- false ->
- cerl:update_c_tuple(Node, Es);
- true ->
- Es1 = wrap(Es, Node, Vars),
- cerl:update_c_call(Node,
- cerl:abstract(hybrid),
- cerl:abstract(tuple),
- [cerl:make_list(Es1)])
-%%% cerl:update_c_call(Node, cerl:abstract(hybrid),
-%%% cerl:abstract(tuple), Es1)
- end;
- cons ->
- H = rewrite(cerl:cons_hd(Node), Vars),
- T = rewrite(cerl:cons_tl(Node), Vars),
- case is_escaping(Node) of
- false ->
- cerl:update_c_cons(Node, H, T);
- true ->
- Es = wrap([H, T], Node, Vars),
- cerl:update_c_call(Node,
- cerl:abstract(hybrid),
- cerl:abstract(cons),
- Es)
- end;
-%%% call ->
-%%% M = rewrite(cerl:call_module(Node)),
-%%% F = rewrite(cerl:call_name(Node)),
-%%% As = rewrite_list(cerl:call_args(Node)),
-%%% case cerl:is_c_atom(M) andalso cerl:is_c_atom(F) of
-%%% true ->
-%%% case {cerl:atom_val(M), cerl:atom_val(F), length(As)} of
-%%% {erlang, '!', 2} ->
-%%% cerl:update_c_call(Node,
-%%% cerl:abstract(hipe_bifs),
-%%% cerl:abstract(send),
-%%% [cerl:make_list(As)]);
-%%% _ ->
-%%% cerl:update_c_call(Node, M, F, As)
-%%% end;
-%%% false ->
-%%% cerl:update_c_call(Node, M, F, As)
-%%% end;
- clause ->
- B = rewrite(cerl:clause_body(Node), Vars),
- cerl:update_c_clause(Node, cerl:clause_pats(Node),
- cerl:clause_guard(Node), B);
- primop ->
- case cerl:atom_val(cerl:primop_name(Node)) of
- match_fail ->
- Node;
- _ ->
- As = rewrite_list(cerl:primop_args(Node), Vars),
- cerl:update_c_primop(Node, cerl:primop_name(Node), As)
- end;
- _T ->
- case cerl:subtrees(Node) of
- [] ->
- Node;
- Gs ->
- cerl:update_tree(Node, [rewrite_list(Ns, Vars)
- || Ns <- Gs])
- end
- end.
-
-rewrite_list([N | Ns], Vars) ->
- [rewrite(N, Vars) | rewrite_list(Ns, Vars)];
-rewrite_list([], _) ->
- [].
-
-is_escaping(T) ->
- lists:member(escapes, cerl:get_ann(T)).
-
-wrap(Es, Node, Vars) ->
- L = cerl_trees:get_label(Node),
- Xs = dict:fetch(L, Vars),
- wrap(Es, Xs).
-
-wrap([E | Es], [{S, _} | Xs]) ->
- case ordsets:is_element(unsafe, S) of
-%% case cerl:type(E) =/= literal of
- true ->
- [cerl:c_call(cerl:abstract(hybrid),
- cerl:abstract(copy),
- [E])
- | wrap(Es, Xs)];
- false ->
- [E | wrap(Es, Xs)]
- end;
-wrap([], _) ->
- [].
diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl
index 6dd93adaa3..ca812a0f0d 100644
--- a/lib/hipe/cerl/cerl_messagean.erl
+++ b/lib/hipe/cerl/cerl_messagean.erl
@@ -1,7 +1,7 @@
%% =====================================================================
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1083,7 +1083,6 @@ is_imm_op(erlang, is_alive, 0) -> true;
is_imm_op(erlang, is_atom, 1) -> true;
is_imm_op(erlang, is_binary, 1) -> true;
is_imm_op(erlang, is_builtin, 3) -> true;
-is_imm_op(erlang, is_constant, 1) -> true;
is_imm_op(erlang, is_float, 1) -> true;
is_imm_op(erlang, is_function, 1) -> true;
is_imm_op(erlang, is_integer, 1) -> true;
diff --git a/lib/hipe/cerl/cerl_to_icode.erl b/lib/hipe/cerl/cerl_to_icode.erl
index 362c427cbe..1c1c10d9b0 100644
--- a/lib/hipe/cerl/cerl_to_icode.erl
+++ b/lib/hipe/cerl/cerl_to_icode.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -88,7 +88,6 @@
-define(TYPE_IS_ATOM, atom).
-define(TYPE_IS_BIGNUM, bignum).
-define(TYPE_IS_BINARY, binary).
--define(TYPE_IS_CONSTANT, constant).
-define(TYPE_IS_FIXNUM, fixnum).
-define(TYPE_IS_FLOAT, float).
-define(TYPE_IS_FUNCTION, function).
@@ -2051,7 +2050,6 @@ is_record_test(T, A, N, True, False, Ctxt, Env, S) ->
type_test(?PRIMOP_IS_ATOM) -> ?TYPE_IS_ATOM;
type_test(?PRIMOP_IS_BIGNUM) -> ?TYPE_IS_BIGNUM;
type_test(?PRIMOP_IS_BINARY) -> ?TYPE_IS_BINARY;
-type_test(?PRIMOP_IS_CONSTANT) -> ?TYPE_IS_CONSTANT;
type_test(?PRIMOP_IS_FIXNUM) -> ?TYPE_IS_FIXNUM;
type_test(?PRIMOP_IS_FLOAT) -> ?TYPE_IS_FLOAT;
type_test(?PRIMOP_IS_FUNCTION) -> ?TYPE_IS_FUNCTION;
@@ -2082,7 +2080,6 @@ is_bool_op(Op, A) when is_atom(Op), is_integer(A) -> false.
is_type_test(?PRIMOP_IS_ATOM, 1) -> true;
is_type_test(?PRIMOP_IS_BIGNUM, 1) -> true;
is_type_test(?PRIMOP_IS_BINARY, 1) -> true;
-is_type_test(?PRIMOP_IS_CONSTANT, 1) -> true;
is_type_test(?PRIMOP_IS_FIXNUM, 1) -> true;
is_type_test(?PRIMOP_IS_FLOAT, 1) -> true;
is_type_test(?PRIMOP_IS_FUNCTION, 1) -> true;
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 1483b2aee1..1ef73da1be 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,6 @@
t_cons/2,
t_cons_hd/1,
t_cons_tl/1,
- t_constant/0,
t_fixnum/0,
t_non_neg_fixnum/0,
t_pos_fixnum/0,
@@ -81,7 +80,6 @@
t_is_bitstr/1,
t_is_boolean/1,
t_is_cons/1,
- t_is_constant/1,
t_is_float/1,
t_is_float/1,
t_is_fun/1,
@@ -243,6 +241,7 @@ type(erl_ddll, try_unload, 2, Xs) ->
%%-- erlang -------------------------------------------------------------------
type(erlang, halt, 0, _) -> t_none();
type(erlang, halt, 1, _) -> t_none();
+type(erlang, halt, 2, _) -> t_none();
type(erlang, exit, 1, _) -> t_none();
%% Note that exit/2 sends an exit signal to another process.
type(erlang, exit, 2, _) -> t_atom('true');
@@ -711,6 +710,27 @@ type(erlang, display_nl, 0, _) ->
t_atom('true');
type(erlang, dist_exit, 3, Xs) ->
strict(arg_types(erlang, dist_exit, 3), Xs, fun (_) -> t_atom('true') end);
+type(erlang, dt_append_vm_tag_data, 1, Xs) ->
+ strict(arg_types(erlang, dt_append_vm_tag_data, 1),
+ Xs,
+ fun(_) -> t_iodata() end);
+type(erlang, dt_get_tag, 0, _) ->
+ t_sup(t_binary(), t_atom('undefined'));
+type(erlang, dt_get_tag_data, 0, _) ->
+ t_sup(t_binary(), t_atom('undefined'));
+type(erlang, dt_prepend_vm_tag_data, 1, Xs) ->
+ strict(arg_types(erlang, dt_prepend_vm_tag_data, 1),
+ Xs,
+ fun(_) -> t_iodata() end);
+type(erlang, dt_put_tag, 1, Xs) ->
+ strict(arg_types(erlang, dt_put_tag, 1), Xs,
+ fun(_) -> t_sup(t_binary(), t_atom('undefined')) end);
+type(erlang, dt_restore_tag, 1, Xs) ->
+ strict(arg_types(erlang, dt_restore_tag, 1), Xs, fun(_) -> t_atom('true') end);
+type(erlang, dt_spread_tag, 1, Xs) ->
+ strict(arg_types(erlang, dt_spread_tag, 1), Xs,
+ fun(_) -> t_sup(t_tuple([t_non_neg_integer(), t_sup(t_binary(), t_nil())]),
+ t_atom('true')) end);
type(erlang, element, 2, Xs) ->
strict(arg_types(erlang, element, 2), Xs,
fun ([X1, X2]) ->
@@ -845,11 +865,6 @@ type(erlang, is_boolean, 1, Xs) ->
strict(arg_types(erlang, is_boolean, 1), Xs, Fun);
type(erlang, is_builtin, 3, Xs) ->
strict(arg_types(erlang, is_builtin, 3), Xs, fun (_) -> t_boolean() end);
-type(erlang, is_constant, 1, Xs) ->
- Fun = fun (X) ->
- check_guard(X, fun (Y) -> t_is_constant(Y) end, t_constant())
- end,
- strict(arg_types(erlang, is_constant, 1), Xs, Fun);
type(erlang, is_float, 1, Xs) ->
Fun = fun (X) ->
check_guard(X, fun (Y) -> t_is_float(Y) end, t_float())
@@ -1171,6 +1186,7 @@ type(erlang, port_info, 2, Xs) ->
['links'] -> t_tuple([Item, t_list(t_pid())]);
['name'] -> t_tuple([Item, t_string()]);
['output'] -> t_tuple([Item, t_integer()]);
+ ['os_pid'] -> t_tuple([Item, t_sup(t_non_neg_integer(),t_atom('undefined'))]);
['registered_name'] -> t_tuple([Item, t_atom()]);
List when is_list(List) ->
t_tuple([t_sup([t_atom(A) || A <- List]),
@@ -1202,11 +1218,13 @@ type(erlang, process_flag, 2, Xs) ->
case t_atom_vals(Flag) of
['error_handler'] -> t_atom();
['min_heap_size'] -> t_non_neg_integer();
+ ['min_bin_vheap_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();
['trap_exit'] -> t_boolean();
+ ['sensitive'] -> t_boolean();
List when is_list(List) ->
T_process_flag_returns;
unknown ->
@@ -1251,7 +1269,6 @@ type(erlang, process_info, 2, Xs) ->
['links'] -> t_tuple([InfoItem, t_list(t_pid())]);
['memory'] ->
t_tuple([InfoItem, t_non_neg_integer()]);
- ['message_binary'] -> t_tuple([InfoItem, t_list()]);
['message_queue_len'] ->
t_tuple([InfoItem, t_non_neg_integer()]);
['messages'] -> t_tuple([InfoItem, t_list()]);
@@ -1321,6 +1338,9 @@ type(erlang, resume_process, 1, Xs) ->
fun (_) -> t_any() end); %% TODO: overapproximation -- fix this
type(erlang, round, 1, Xs) ->
strict(arg_types(erlang, round, 1), Xs, fun (_) -> t_integer() end);
+type(erlang, posixtime_to_universaltime, 1, Xs) ->
+ strict(arg_types(erlang, posixtime_to_universaltime, 1), Xs,
+ fun(_) -> t_tuple([t_date(), t_time()]) end);
type(erlang, self, 0, _) -> t_pid();
type(erlang, send, 2, Xs) -> type(erlang, '!', 2, Xs); % alias
type(erlang, send, 3, Xs) ->
@@ -1500,6 +1520,8 @@ type(erlang, system_flag, 2, Xs) ->
t_non_neg_fixnum();
['min_heap_size'] ->
t_non_neg_fixnum();
+ ['min_bin_vheap_size'] ->
+ t_non_neg_fixnum();
['multi_scheduling'] ->
t_system_multi_scheduling();
['schedulers_online'] ->
@@ -1543,8 +1565,12 @@ type(erlang, system_info, 1, Xs) ->
t_list(t_tuple([t_atom(),
t_list(t_tuple([t_atom(),
t_any()]))]))]);
+ ['build_type'] ->
+ t_system_build_type_return();
['break_ignored'] ->
t_boolean();
+ ['c_compiler_used'] ->
+ t_tuple([t_atom(), t_any()]);
['cpu_topology'] ->
t_system_cpu_topology();
['compat_rel'] ->
@@ -1557,6 +1583,8 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['dist_ctrl'] ->
t_list(t_tuple([t_atom(), t_sup([t_pid(), t_port])]));
+ ['driver_version'] ->
+ t_string();
%% elib_malloc is intentionally not included,
%% because it scheduled for removal in R15.
['endian'] ->
@@ -1565,12 +1593,10 @@ type(erlang, system_info, 1, Xs) ->
t_tuple([t_atom('fullsweep_after'), t_non_neg_integer()]);
['garbage_collection'] ->
t_list();
- ['global_heaps_size'] ->
- t_non_neg_integer();
['heap_sizes'] ->
t_list(t_integer());
['heap_type'] ->
- t_sup([t_atom('private'), t_atom('hybrid')]);
+ t_atom('private');
['hipe_architecture'] ->
t_atoms(['amd64', 'arm', 'powerpc', 'ppc64',
'undefined', 'ultrasparc', 'x86']);
@@ -1578,12 +1604,20 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['internal_cpu_topology'] -> %% Undocumented internal feature
t_internal_cpu_topology();
+ ['kernel_poll'] ->
+ t_boolean();
['loaded'] ->
t_binary();
['logical_processors'] ->
t_non_neg_fixnum();
['machine'] ->
t_string();
+ ['min_heap_size'] ->
+ t_tuple([t_atom('min_heap_size'),
+ t_non_neg_integer()]);
+ ['min_bin_vheap_size'] ->
+ t_tuple([t_atom('min_bin_vheap_size'),
+ t_non_neg_integer()]);
['multi_scheduling'] ->
t_system_multi_scheduling();
['multi_scheduling_blockers'] ->
@@ -1598,6 +1632,8 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_fixnum(),
t_non_neg_fixnum()]),
t_string());
+ ['otp_release'] ->
+ t_string();
['process_count'] ->
t_non_neg_fixnum();
['process_limit'] ->
@@ -1627,6 +1663,8 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_fixnum();
['trace_control_word'] ->
t_integer();
+ ['update_cpu_info'] ->
+ t_sup([t_atom('changed'), t_atom('unchanged')]);
['version'] ->
t_string();
['wordsize'] ->
@@ -1717,6 +1755,9 @@ type(erlang, universaltime, 0, _) ->
type(erlang, universaltime_to_localtime, 1, Xs) ->
strict(arg_types(erlang, universaltime_to_localtime, 1), Xs,
fun ([T]) -> T end);
+type(erlang, universaltime_to_posixtime, 1, Xs) ->
+ strict(arg_types(erlang, universaltime_to_posixtime,1), Xs,
+ fun(_) -> t_integer() end);
type(erlang, unlink, 1, Xs) ->
strict(arg_types(erlang, unlink, 1), Xs, fun (_) -> t_atom('true') end);
type(erlang, unregister, 1, Xs) ->
@@ -3471,6 +3512,20 @@ arg_types(erlang, display_string, 1) ->
[t_string()];
arg_types(erlang, dist_exit, 3) ->
[t_pid(), t_dist_exit(), t_sup(t_pid(), t_port())];
+arg_types(erlang, dt_append_vm_tag_data, 1) ->
+ [t_iodata()];
+arg_types(erlang, dt_get_tag, 0) ->
+ [];
+arg_types(erlang, dt_get_tag_data, 0) ->
+ [];
+arg_types(erlang, dt_prepend_vm_tag_data, 1) ->
+ [t_iodata()];
+arg_types(erlang, dt_put_tag, 1) ->
+ [t_sup(t_binary(), t_atom('undefined'))];
+arg_types(erlang, dt_restore_tag, 1) ->
+ [t_sup(t_tuple([t_non_neg_integer(), t_sup(t_binary(), t_nil())]), t_atom('true'))];
+arg_types(erlang, dt_spread_tag, 1) ->
+ [t_boolean()];
arg_types(erlang, element, 2) ->
[t_pos_fixnum(), t_tuple()];
arg_types(erlang, erase, 0) ->
@@ -3530,7 +3585,10 @@ arg_types(erlang, group_leader, 2) ->
arg_types(erlang, halt, 0) ->
[];
arg_types(erlang, halt, 1) ->
- [t_sup(t_non_neg_fixnum(), t_string())];
+ [t_sup([t_non_neg_fixnum(), t_atom('abort'), t_string()])];
+arg_types(erlang, halt, 2) ->
+ [t_sup([t_non_neg_fixnum(), t_atom('abort'), t_string()]),
+ t_list(t_tuple([t_atom('flush'), t_boolean()]))];
arg_types(erlang, hash, 2) ->
[t_any(), t_integer()];
arg_types(erlang, hd, 1) ->
@@ -3561,8 +3619,6 @@ arg_types(erlang, is_boolean, 1) ->
[t_any()];
arg_types(erlang, is_builtin, 3) ->
[t_atom(), t_atom(), t_arity()];
-arg_types(erlang, is_constant, 1) ->
- [t_any()];
arg_types(erlang, is_float, 1) ->
[t_any()];
arg_types(erlang, is_function, 1) ->
@@ -3729,7 +3785,7 @@ arg_types(erlang, port_info, 1) ->
arg_types(erlang, port_info, 2) ->
[t_sup(t_port(), t_atom()),
t_atoms(['registered_name', 'id', 'connected',
- 'links', 'name', 'input', 'output'])];
+ 'links', 'name', 'input', 'output', 'os_pid'])];
arg_types(erlang, port_to_list, 1) ->
[t_port()];
arg_types(erlang, ports, 0) ->
@@ -3741,8 +3797,13 @@ arg_types(erlang, pre_loaded, 0) ->
arg_types(erlang, process_display, 2) ->
[t_pid(), t_atom('backtrace')];
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_sup([t_atom('trap_exit'),
+ t_atom('error_handler'),
+ t_atom('min_heap_size'),
+ t_atom('min_bin_vheap_size'),
+ t_atom('priority'),
+ t_atom('save_calls'),
+ t_atom('sensitive'),
t_atom('scheduler'), % undocumented
t_atom('monitor_nodes'), % undocumented
t_tuple([t_atom('monitor_nodes'), t_list()])]), % undocumented
@@ -3776,6 +3837,8 @@ arg_types(erlang, resume_process, 1) ->
[t_pid()]; % intended for debugging only
arg_types(erlang, round, 1) ->
[t_number()];
+arg_types(erlang, posixtime_to_universaltime, 1) ->
+ [t_integer()];
arg_types(erlang, self, 0) ->
[];
arg_types(erlang, send, 2) ->
@@ -3853,6 +3916,7 @@ arg_types(erlang, system_flag, 2) ->
t_atom('display_items'), % undocumented
t_atom('fullsweep_after'),
t_atom('min_heap_size'),
+ t_atom('min_bin_vheap_size'),
t_atom('multi_scheduling'),
t_atom('schedulers_online'),
t_atom('scheduler_bind_type'),
@@ -3881,7 +3945,8 @@ arg_types(erlang, system_flag, 2) ->
arg_types(erlang, system_info, 1) ->
[t_sup([t_atom(), % documented
t_tuple([t_atom(), t_any()]), % documented
- t_tuple([t_atom(), t_atom(), t_any()])])];
+ t_tuple([t_atom(), t_atom(), t_any()]),
+ t_tuple([t_atom(allocator_sizes), t_reference(), t_any()])])];
arg_types(erlang, system_monitor, 0) ->
[];
arg_types(erlang, system_monitor, 1) ->
@@ -3941,6 +4006,8 @@ arg_types(erlang, universaltime, 0) ->
[];
arg_types(erlang, universaltime_to_localtime, 1) ->
[t_tuple([t_date(), t_time()])];
+arg_types(erlang, universaltime_to_posixtime, 1) ->
+ [t_tuple([t_date(), t_time()])];
arg_types(erlang, unlink, 1) ->
[t_sup(t_pid(), t_port())];
arg_types(erlang, unregister, 1) ->
@@ -4671,7 +4738,6 @@ t_pinfo_item() ->
t_atom('last_calls'),
t_atom('links'),
t_atom('memory'),
- t_atom('message_binary'), % for hybrid heap only
t_atom('message_queue_len'),
t_atom('messages'),
t_atom('monitored_by'),
@@ -4722,6 +4788,7 @@ t_spawn_options() ->
t_atom('monitor'),
t_tuple([t_atom('priority'), t_process_priority_level()]),
t_tuple([t_atom('min_heap_size'), t_fixnum()]),
+ t_tuple([t_atom('min_bin_vheap_size'), t_fixnum()]),
t_tuple([t_atom('fullsweep_after'), t_fixnum()])]).
t_spawn_opt_return(List) ->
@@ -4810,6 +4877,17 @@ t_system_profile_return() ->
t_sup(t_atom('undefined'),
t_tuple([t_sup(t_pid(), t_port()), t_system_profile_options()])).
+t_system_build_type_return() ->
+ t_sup([t_atom('opt'),
+ t_atom('debug'),
+ t_atom('purify'),
+ t_atom('quantify'),
+ t_atom('purecov'),
+ t_atom('gcov'),
+ t_atom('valgrind'),
+ t_atom('gprof'),
+ t_atom('lcnt')]).
+
%% =====================================================================
%% These are used for the built-in functions of 'ets'
%% =====================================================================
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 0ff827ac37..1579735773 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -275,8 +275,8 @@
-type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag
| ?list_tag | ?matchstate_tag | ?nil_tag | ?number_tag
- | ?opaque_tag | ?product_tag | ?tuple_tag | ?tuple_set_tag
- | ?union_tag | ?var_tag.
+ | ?opaque_tag | ?product_tag | ?remote_tag
+ | ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag.
-define(float_qual, float).
-define(integer_qual, integer).
@@ -424,12 +424,7 @@ t_has_opaque_subtype(T) ->
-spec t_opaque_structure(erl_type()) -> erl_type().
t_opaque_structure(?opaque(Elements)) ->
- case ordsets:size(Elements) of
- 1 ->
- [#opaque{struct = Struct}] = ordsets:to_list(Elements),
- Struct;
- _ -> throw({error, "Unexpected multiple opaque types"})
- end.
+ t_sup([Struct || #opaque{struct = Struct} <- ordsets:to_list(Elements)]).
-spec t_opaque_module(erl_type()) -> module().
@@ -688,9 +683,9 @@ t_solve_remote(?opaque(Set), ET, R, C) ->
{NewList, RR} = opaques_solve_remote(List, ET, R, C),
{?opaque(ordsets:from_list(NewList)), RR};
t_solve_remote(?tuple(?any, _, _) = T, _ET, _R, _C) -> {T, []};
-t_solve_remote(?tuple(Types, Arity, Tag), ET, R, C) ->
+t_solve_remote(?tuple(Types, _Arity, _Tag), ET, R, C) ->
{RL, RR} = list_solve_remote(Types, ET, R, C),
- {?tuple(RL, Arity, Tag), RR};
+ {t_tuple(RL), RR};
t_solve_remote(?tuple_set(Set), ET, R, C) ->
{NewSet, RR} = tuples_solve_remote(Set, ET, R, C),
{?tuple_set(NewSet), RR};
@@ -2323,10 +2318,14 @@ t_inf(?product(_), _, _Mode) ->
?none;
t_inf(_, ?product(_), _Mode) ->
?none;
-t_inf(?tuple(?any, ?any, ?any), ?tuple(_, _, _) = T, _Mode) -> T;
-t_inf(?tuple(_, _, _) = T, ?tuple(?any, ?any, ?any), _Mode) -> T;
-t_inf(?tuple(?any, ?any, ?any), ?tuple_set(_) = T, _Mode) -> T;
-t_inf(?tuple_set(_) = T, ?tuple(?any, ?any, ?any), _Mode) -> T;
+t_inf(?tuple(?any, ?any, ?any), ?tuple(_, _, _) = T, _Mode) ->
+ subst_all_vars_to_any(T);
+t_inf(?tuple(_, _, _) = T, ?tuple(?any, ?any, ?any), _Mode) ->
+ subst_all_vars_to_any(T);
+t_inf(?tuple(?any, ?any, ?any), ?tuple_set(_) = T, _Mode) ->
+ subst_all_vars_to_any(T);
+t_inf(?tuple_set(_) = T, ?tuple(?any, ?any, ?any), _Mode) ->
+ subst_all_vars_to_any(T);
t_inf(?tuple(Elements1, Arity, _Tag1), ?tuple(Elements2, Arity, _Tag2), Mode) ->
case t_inf_lists_strict(Elements1, Elements2, Mode) of
bottom -> ?none;
@@ -2528,52 +2527,95 @@ findfirst(N1, N2, U1, B1, U2, B2) ->
%%-----------------------------------------------------------------------------
%% Substitution of variables
%%
+%% Dialyzer versions prior to R15B used a dict data structure to map variables
+%% to types. Hans Bolinder suggested the use of lists of Key-Value pairs for
+%% this data structure and measurements showed a non-trivial speedup when using
+%% them for operations within this module (e.g. in t_unify/2). However, there
+%% is code outside erl_types that still passes a dict() in the 2nd argument.
+%% So, for the time being, this module provides a t_subst/2 function for these
+%% external calls and a clone of it (t_subst_kv/2) which is used from all calls
+%% from within this module. This code duplication needs to be eliminated at
+%% some point.
-spec t_subst(erl_type(), dict()) -> erl_type().
t_subst(T, Dict) ->
case t_has_var(T) of
- true -> t_subst(T, Dict, fun(X) -> X end);
+ true -> t_subst_dict(T, Dict);
false -> T
end.
+t_subst_dict(?var(Id), Dict) ->
+ case dict:find(Id, Dict) of
+ error -> ?any;
+ {ok, Type} -> Type
+ end;
+t_subst_dict(?list(Contents, Termination, Size), Dict) ->
+ case t_subst_dict(Contents, Dict) of
+ ?none -> ?none;
+ NewContents ->
+ %% Be careful here to make the termination collapse if necessary.
+ case t_subst_dict(Termination, Dict) of
+ ?nil -> ?list(NewContents, ?nil, Size);
+ ?any -> ?list(NewContents, ?any, Size);
+ Other ->
+ ?list(NewContents2, NewTermination, _) = t_cons(NewContents, Other),
+ ?list(NewContents2, NewTermination, Size)
+ end
+ end;
+t_subst_dict(?function(Domain, Range), Dict) ->
+ ?function(t_subst_dict(Domain, Dict), t_subst_dict(Range, Dict));
+t_subst_dict(?product(Types), Dict) ->
+ ?product([t_subst_dict(T, Dict) || T <- Types]);
+t_subst_dict(?tuple(?any, ?any, ?any) = T, _Dict) ->
+ T;
+t_subst_dict(?tuple(Elements, _Arity, _Tag), Dict) ->
+ t_tuple([t_subst_dict(E, Dict) || E <- Elements]);
+t_subst_dict(?tuple_set(_) = TS, Dict) ->
+ t_sup([t_subst_dict(T, Dict) || T <- t_tuple_subtypes(TS)]);
+t_subst_dict(T, _Dict) ->
+ T.
+
-spec subst_all_vars_to_any(erl_type()) -> erl_type().
subst_all_vars_to_any(T) ->
+ t_subst_kv(T, []).
+
+t_subst_kv(T, KVMap) ->
case t_has_var(T) of
- true -> t_subst(T, dict:new(), fun(_) -> ?any end);
+ true -> t_subst_aux(T, KVMap);
false -> T
end.
-t_subst(?var(Id) = V, Dict, Fun) ->
- case dict:find(Id, Dict) of
- error -> Fun(V);
- {ok, Type} -> Type
+t_subst_aux(?var(Id), VarMap) ->
+ case lists:keyfind(Id, 1, VarMap) of
+ false -> ?any;
+ {Id, Type} -> Type
end;
-t_subst(?list(Contents, Termination, Size), Dict, Fun) ->
- case t_subst(Contents, Dict, Fun) of
+t_subst_aux(?list(Contents, Termination, Size), VarMap) ->
+ case t_subst_aux(Contents, VarMap) of
?none -> ?none;
NewContents ->
%% Be careful here to make the termination collapse if necessary.
- case t_subst(Termination, Dict, Fun) of
+ case t_subst_aux(Termination, VarMap) of
?nil -> ?list(NewContents, ?nil, Size);
?any -> ?list(NewContents, ?any, Size);
Other ->
- ?list(NewContents, NewTermination, _) = t_cons(NewContents, Other),
- ?list(NewContents, NewTermination, Size)
+ ?list(NewContents2, NewTermination, _) = t_cons(NewContents, Other),
+ ?list(NewContents2, NewTermination, Size)
end
end;
-t_subst(?function(Domain, Range), Dict, Fun) ->
- ?function(t_subst(Domain, Dict, Fun), t_subst(Range, Dict, Fun));
-t_subst(?product(Types), Dict, Fun) ->
- ?product([t_subst(T, Dict, Fun) || T <- Types]);
-t_subst(?tuple(?any, ?any, ?any) = T, _Dict, _Fun) ->
+t_subst_aux(?function(Domain, Range), VarMap) ->
+ ?function(t_subst_aux(Domain, VarMap), t_subst_aux(Range, VarMap));
+t_subst_aux(?product(Types), VarMap) ->
+ ?product([t_subst_aux(T, VarMap) || T <- Types]);
+t_subst_aux(?tuple(?any, ?any, ?any) = T, _VarMap) ->
T;
-t_subst(?tuple(Elements, _Arity, _Tag), Dict, Fun) ->
- t_tuple([t_subst(E, Dict, Fun) || E <- Elements]);
-t_subst(?tuple_set(_) = TS, Dict, Fun) ->
- t_sup([t_subst(T, Dict, Fun) || T <- t_tuple_subtypes(TS)]);
-t_subst(T, _Dict, _Fun) ->
+t_subst_aux(?tuple(Elements, _Arity, _Tag), VarMap) ->
+ t_tuple([t_subst_aux(E, VarMap) || E <- Elements]);
+t_subst_aux(?tuple_set(_) = TS, VarMap) ->
+ t_sup([t_subst_aux(T, VarMap) || T <- t_tuple_subtypes(TS)]);
+t_subst_aux(T, _VarMap) ->
T.
%%-----------------------------------------------------------------------------
@@ -2590,87 +2632,87 @@ t_unify(T1, T2) ->
-spec t_unify(erl_type(), erl_type(), [erl_type()]) -> t_unify_ret().
t_unify(T1, T2, Opaques) ->
- {T, Dict} = t_unify(T1, T2, dict:new(), Opaques),
- {t_subst(T, Dict), lists:keysort(1, dict:to_list(Dict))}.
-
-t_unify(?var(Id) = T, ?var(Id), Dict, _Opaques) ->
- {T, Dict};
-t_unify(?var(Id1) = T, ?var(Id2), Dict, Opaques) ->
- case dict:find(Id1, Dict) of
- error ->
- case dict:find(Id2, Dict) of
- error -> {T, dict:store(Id2, T, Dict)};
- {ok, Type} -> t_unify(T, Type, Dict, Opaques)
+ {T, VarMap} = t_unify(T1, T2, [], Opaques),
+ {t_subst_kv(T, VarMap), lists:keysort(1, VarMap)}.
+
+t_unify(?var(Id) = T, ?var(Id), VarMap, _Opaques) ->
+ {T, VarMap};
+t_unify(?var(Id1) = T, ?var(Id2), VarMap, Opaques) ->
+ case lists:keyfind(Id1, 1, VarMap) of
+ false ->
+ case lists:keyfind(Id2, 1, VarMap) of
+ false -> {T, [{Id2, T} | VarMap]};
+ {Id2, Type} -> t_unify(T, Type, VarMap, Opaques)
end;
- {ok, Type1} ->
- case dict:find(Id2, Dict) of
- error -> {Type1, dict:store(Id2, T, Dict)};
- {ok, Type2} -> t_unify(Type1, Type2, Dict, Opaques)
+ {Id1, Type1} ->
+ case lists:keyfind(Id2, 1, VarMap) of
+ false -> {Type1, [{Id2, T} | VarMap]};
+ {Id2, Type2} -> t_unify(Type1, Type2, VarMap, Opaques)
end
end;
-t_unify(?var(Id), Type, Dict, Opaques) ->
- case dict:find(Id, Dict) of
- error -> {Type, dict:store(Id, Type, Dict)};
- {ok, VarType} -> t_unify(VarType, Type, Dict, Opaques)
+t_unify(?var(Id), Type, VarMap, Opaques) ->
+ case lists:keyfind(Id, 1, VarMap) of
+ false -> {Type, [{Id, Type} | VarMap]};
+ {Id, VarType} -> t_unify(VarType, Type, VarMap, Opaques)
end;
-t_unify(Type, ?var(Id), Dict, Opaques) ->
- case dict:find(Id, Dict) of
- error -> {Type, dict:store(Id, Type, Dict)};
- {ok, VarType} -> t_unify(VarType, Type, Dict, Opaques)
+t_unify(Type, ?var(Id), VarMap, Opaques) ->
+ case lists:keyfind(Id, 1, VarMap) of
+ false -> {Type, [{Id, Type} | VarMap]};
+ {Id, VarType} -> t_unify(VarType, Type, VarMap, Opaques)
end;
-t_unify(?function(Domain1, Range1), ?function(Domain2, Range2), Dict, Opaques) ->
- {Domain, Dict1} = t_unify(Domain1, Domain2, Dict, Opaques),
- {Range, Dict2} = t_unify(Range1, Range2, Dict1, Opaques),
- {?function(Domain, Range), Dict2};
+t_unify(?function(Domain1, Range1), ?function(Domain2, Range2), VarMap, Opaques) ->
+ {Domain, VarMap1} = t_unify(Domain1, Domain2, VarMap, Opaques),
+ {Range, VarMap2} = t_unify(Range1, Range2, VarMap1, Opaques),
+ {?function(Domain, Range), VarMap2};
t_unify(?list(Contents1, Termination1, Size),
- ?list(Contents2, Termination2, Size), Dict, Opaques) ->
- {Contents, Dict1} = t_unify(Contents1, Contents2, Dict, Opaques),
- {Termination, Dict2} = t_unify(Termination1, Termination2, Dict1, Opaques),
- {?list(Contents, Termination, Size), Dict2};
-t_unify(?product(Types1), ?product(Types2), Dict, Opaques) ->
- {Types, Dict1} = unify_lists(Types1, Types2, Dict, Opaques),
- {?product(Types), Dict1};
-t_unify(?tuple(?any, ?any, ?any) = T, ?tuple(?any, ?any, ?any), Dict, _Opaques) ->
- {T, Dict};
+ ?list(Contents2, Termination2, Size), VarMap, Opaques) ->
+ {Contents, VarMap1} = t_unify(Contents1, Contents2, VarMap, Opaques),
+ {Termination, VarMap2} = t_unify(Termination1, Termination2, VarMap1, Opaques),
+ {?list(Contents, Termination, Size), VarMap2};
+t_unify(?product(Types1), ?product(Types2), VarMap, Opaques) ->
+ {Types, VarMap1} = unify_lists(Types1, Types2, VarMap, Opaques),
+ {?product(Types), VarMap1};
+t_unify(?tuple(?any, ?any, ?any) = T, ?tuple(?any, ?any, ?any), VarMap, _Opaques) ->
+ {T, VarMap};
t_unify(?tuple(Elements1, Arity, _),
- ?tuple(Elements2, Arity, _), Dict, Opaques) when Arity =/= ?any ->
- {NewElements, Dict1} = unify_lists(Elements1, Elements2, Dict, Opaques),
- {t_tuple(NewElements), Dict1};
+ ?tuple(Elements2, Arity, _), VarMap, Opaques) when Arity =/= ?any ->
+ {NewElements, VarMap1} = unify_lists(Elements1, Elements2, VarMap, Opaques),
+ {t_tuple(NewElements), VarMap1};
t_unify(?tuple_set([{Arity, _}]) = T1,
- ?tuple(_, Arity, _) = T2, Dict, Opaques) when Arity =/= ?any ->
- unify_tuple_set_and_tuple(T1, T2, Dict, Opaques);
+ ?tuple(_, Arity, _) = T2, VarMap, Opaques) when Arity =/= ?any ->
+ unify_tuple_set_and_tuple(T1, T2, VarMap, Opaques);
t_unify(?tuple(_, Arity, _) = T1,
- ?tuple_set([{Arity, _}]) = T2, Dict, Opaques) when Arity =/= ?any ->
- unify_tuple_set_and_tuple(T2, T1, Dict, Opaques);
-t_unify(?tuple_set(List1), ?tuple_set(List2), Dict, Opaques) ->
- {Tuples, NewDict} =
+ ?tuple_set([{Arity, _}]) = T2, VarMap, Opaques) when Arity =/= ?any ->
+ unify_tuple_set_and_tuple(T2, T1, VarMap, Opaques);
+t_unify(?tuple_set(List1), ?tuple_set(List2), VarMap, Opaques) ->
+ {Tuples, NewVarMap} =
unify_lists(lists:append([T || {_Arity, T} <- List1]),
- lists:append([T || {_Arity, T} <- List2]), Dict, Opaques),
- {t_sup(Tuples), NewDict};
-t_unify(?opaque(Elements) = T, ?opaque(Elements), Dict, _Opaques) ->
- {T, Dict};
-t_unify(?opaque(_) = T1, ?opaque(_) = T2, _Dict, _Opaques) ->
+ lists:append([T || {_Arity, T} <- List2]), VarMap, Opaques),
+ {t_sup(Tuples), NewVarMap};
+t_unify(?opaque(Elements) = T, ?opaque(Elements), VarMap, _Opaques) ->
+ {T, VarMap};
+t_unify(?opaque(_) = T1, ?opaque(_) = T2, _VarMap, _Opaques) ->
throw({mismatch, T1, T2});
-t_unify(Type, ?opaque(_) = OpType, Dict, Opaques) ->
- t_unify_with_opaque(Type, OpType, Dict, Opaques);
-t_unify(?opaque(_) = OpType, Type, Dict, Opaques) ->
- t_unify_with_opaque(Type, OpType, Dict, Opaques);
-t_unify(T, T, Dict, _Opaques) ->
- {T, Dict};
+t_unify(Type, ?opaque(_) = OpType, VarMap, Opaques) ->
+ t_unify_with_opaque(Type, OpType, VarMap, Opaques);
+t_unify(?opaque(_) = OpType, Type, VarMap, Opaques) ->
+ t_unify_with_opaque(Type, OpType, VarMap, Opaques);
+t_unify(T, T, VarMap, _Opaques) ->
+ {T, VarMap};
t_unify(T1, T2, _, _) ->
throw({mismatch, T1, T2}).
-t_unify_with_opaque(Type, OpType, Dict, Opaques) ->
+t_unify_with_opaque(Type, OpType, VarMap, Opaques) ->
case lists:member(OpType, Opaques) of
true ->
Struct = t_opaque_structure(OpType),
- try t_unify(Type, Struct, Dict, Opaques) of
- {_T, Dict1} -> {OpType, Dict1}
+ try t_unify(Type, Struct, VarMap, Opaques) of
+ {_T, VarMap1} -> {OpType, VarMap1}
catch
throw:{mismatch, _T1, _T2} ->
case t_inf(OpType, Type, opaque) of
?none -> throw({mismatch, Type, OpType});
- _ -> {OpType, Dict}
+ _ -> {OpType, VarMap}
end
end;
false ->
@@ -2678,20 +2720,20 @@ t_unify_with_opaque(Type, OpType, Dict, Opaques) ->
end.
unify_tuple_set_and_tuple(?tuple_set([{Arity, List}]),
- ?tuple(Elements2, Arity, _), Dict, Opaques) ->
+ ?tuple(Elements2, Arity, _), VarMap, Opaques) ->
%% Can only work if the single tuple has variables at correct places.
%% Collapse the tuple set.
- {NewElements, Dict1} = unify_lists(sup_tuple_elements(List), Elements2, Dict, Opaques),
- {t_tuple(NewElements), Dict1}.
+ {NewElements, VarMap1} = unify_lists(sup_tuple_elements(List), Elements2, VarMap, Opaques),
+ {t_tuple(NewElements), VarMap1}.
-unify_lists(L1, L2, Dict, Opaques) ->
- unify_lists(L1, L2, Dict, [], Opaques).
+unify_lists(L1, L2, VarMap, Opaques) ->
+ unify_lists(L1, L2, VarMap, [], Opaques).
-unify_lists([T1|Left1], [T2|Left2], Dict, Acc, Opaques) ->
- {NewT, NewDict} = t_unify(T1, T2, Dict, Opaques),
- unify_lists(Left1, Left2, NewDict, [NewT|Acc], Opaques);
-unify_lists([], [], Dict, Acc, _Opaques) ->
- {lists:reverse(Acc), Dict}.
+unify_lists([T1|Left1], [T2|Left2], VarMap, Acc, Opaques) ->
+ {NewT, NewVarMap} = t_unify(T1, T2, VarMap, Opaques),
+ unify_lists(Left1, Left2, NewVarMap, [NewT|Acc], Opaques);
+unify_lists([], [], VarMap, Acc, _Opaques) ->
+ {lists:reverse(Acc), VarMap}.
%%t_assign_variables_to_subtype(T1, T2) ->
%% try
@@ -3148,8 +3190,8 @@ t_abstract_records(?list(Contents, Termination, Size), RecDict) ->
?nil -> ?list(NewContents, ?nil, Size);
?any -> ?list(NewContents, ?any, Size);
Other ->
- ?list(NewContents, NewTermination, _) = t_cons(NewContents, Other),
- ?list(NewContents, NewTermination, Size)
+ ?list(NewContents2, NewTermination, _) = t_cons(NewContents, Other),
+ ?list(NewContents2, NewTermination, Size)
end
end;
t_abstract_records(?function(Domain, Range), RecDict) ->
diff --git a/lib/hipe/doc/Makefile b/lib/hipe/doc/Makefile
index cdf9c9c798..4ea0137202 100644
--- a/lib/hipe/doc/Makefile
+++ b/lib/hipe/doc/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2010. All Rights Reserved.
+# Copyright Ericsson AB 2006-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,9 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
clean:
-rm -f *.html edoc-info stylesheet.css erlang.png
+distclean: clean
+realclean: clean
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile
index d440178e4c..fbfd4ca327 100644
--- a/lib/hipe/doc/src/Makefile
+++ b/lib/hipe/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2010. All Rights Reserved.
+# Copyright Ericsson AB 2006-2012. All Rights Reserved.
#
# The 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,18 +97,21 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
+distclean: clean
+realclean: clean
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
release_spec:
diff --git a/lib/hipe/doc/src/make.dep b/lib/hipe/doc/src/make.dep
deleted file mode 100644
index d5f5844c21..0000000000
--- a/lib/hipe/doc/src/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex
-
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 6b601e3039..ed8cf0b8d3 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -30,6 +30,129 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ References to <c>is_constant/1</c> (which was removed in
+ the R12 release) has been removed from documentation and
+ code.</p>
+ <p>
+ Own Id: OTP-6454 Aux Id: seq10407 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a discrepancy in compile_info</p>
+ <p>
+ The BEAM disassembler used the atom 'none' to signify the
+ absence of a compile_info chunk in a .beam file. This
+ clashed with the type declaration of the compile_info
+ field of a #beam_file{} record as containing a list. Now
+ [] signifies the absence of this chunk. This simplifies
+ the code and avoids a dialyzer warning.</p>
+ <p>
+ Own Id: OTP-9917</p>
+ </item>
+ <item>
+ <p>
+ Make dialyzer recognize the process_flag option sensitive
+ add missing specs to documentation (Thanks to Tobias
+ Schlager)</p>
+ <p>
+ Own Id: OTP-9923</p>
+ </item>
+ <item>
+ <p>
+ Remove hipe_ceach from hipe.app.src to fix
+ reltool-generated release startup. (Thanks to Tim
+ Stewart)</p>
+ <p>
+ Own Id: OTP-9939</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <list> <item><p>No warnings for underspecs with remote
+ types</p></item> <item><p> Fix crash in Typer</p></item>
+ <item><p>Fix Dialyzer's warning for its own
+ code</p></item> <item><p>Fix Dialyzer's warnings in
+ HiPE</p></item> <item><p>Add file/line info in a
+ particular Dialyzer crash</p></item> <item><p>Update
+ inets test results</p></item> </list></p>
+ <p>
+ Own Id: OTP-9758</p>
+ </item>
+ <item>
+ <p>
+ <list> <item><p>Correct callback spec in application
+ module</p></item> <item><p>Refine warning about callback
+ specs with extra ranges</p></item> <item><p>Cleanup
+ autoimport compiler directives</p></item> <item><p>Fix
+ Dialyzer's warnings in typer</p></item> <item><p>Fix
+ Dialyzer's warning for its own code</p></item>
+ <item><p>Fix bug in Dialyzer's behaviours
+ analysis</p></item> <item><p>Fix crash in
+ Dialyzer</p></item> <item><p>Variable substitution was
+ not generalizing any unknown variables.</p></item>
+ </list></p>
+ <p>
+ Own Id: OTP-9776</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Possible to run HiPE without floating point exceptions
+ (FPE). Useful on platforms that lack reliable FPE. Slower
+ float operations compared to HiPE with FPE.</p>
+ <p>
+ Own Id: OTP-9724</p>
+ </item>
+ <item>
+ <p>
+ HiPE compiler: The possibility to compile and load
+ selected functions from a module has been removed.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9751</p>
+ </item>
+ <item>
+ <p>
+ <c>filename:find_src/1,2</c> will now work on stripped
+ BEAM files (reported by Per Hedeland). The HiPE compiler
+ will also work on stripped BEAM files. The BEAM compiler
+ will no longer include compilation options given in the
+ source code itself in <c>M:module_info(compile)</c>
+ (because those options will be applied anyway if the
+ module is re-compiled).</p>
+ <p>
+ Own Id: OTP-9752</p>
+ </item>
+ <item>
+ <p> Optimize <c>erl_types:t_unify()</c>. </p>
+ <p>
+ Own Id: OTP-9768</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.8.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/hipe/flow/Makefile b/lib/hipe/flow/Makefile
index 02f610587b..75e156b542 100644
--- a/lib/hipe/flow/Makefile
+++ b/lib/hipe/flow/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -65,7 +65,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
@@ -82,6 +82,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -97,10 +100,10 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/flow
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(INC_FILES) $(RELSYSDIR)/flow
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/flow"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(INC_FILES) "$(RELSYSDIR)/flow"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl
index 62f47a707a..95bf5f7194 100644
--- a/lib/hipe/flow/cfg.hrl
+++ b/lib/hipe/flow/cfg.hrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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/hipe/icode/Makefile b/lib/hipe/icode/Makefile
index eced90b0ec..0f2d6db39b 100644
--- a/lib/hipe/icode/Makefile
+++ b/lib/hipe/icode/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The 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 @@ DOC_FILES= $(DOC_MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_unused_import +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_unused_import +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
@@ -100,6 +100,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -115,10 +118,10 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/icode
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/icode
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/icode"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/icode"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 45b390acbd..ecf1c77abc 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,7 +31,7 @@
-module(hipe_beam_to_icode).
--export([module/2, mfa/3]).
+-export([module/2]).
%%-----------------------------------------------------------------------
@@ -72,12 +72,11 @@
end).
%%-----------------------------------------------------------------------
-%% Exported types
+%% Types
%%-----------------------------------------------------------------------
-type hipe_beam_to_icode_ret() :: [{mfa(),#icode{}}].
-
%%-----------------------------------------------------------------------
%% Internal data structures
%%-----------------------------------------------------------------------
@@ -111,55 +110,6 @@ trans_beam_function_chunk(FunBeamCode, ClosureInfo) ->
{MFA,Icode}.
%%-----------------------------------------------------------------------
-%% @doc
-%% Translates the BEAM code of a single function into Icode.
-%% Returns a tuple whose first argument is list of {{M,F,A}, ICode}
-%% pairs, where the first entry is that of the given MFA, and the
-%% following (in undefined order) are those of the funs that are
-%% defined in the function, and recursively, in the funs. The
-%% second argument of the tuple is the HiPE compiler options
-%% contained in the file.
-%% @end
-%%-----------------------------------------------------------------------
-
--spec mfa(list(), mfa(), comp_options()) -> hipe_beam_to_icode_ret().
-
-mfa(BeamFuns, {M,F,A} = MFA, Options)
- when is_atom(M), is_atom(F), is_integer(A) ->
- BeamCode0 = [beam_disasm:function__code(Fn) || Fn <- BeamFuns],
- {ModCode, ClosureInfo} = preprocess_code(BeamCode0),
- mfa_loop([MFA], [], sets:new(), ModCode, ClosureInfo, Options).
-
-mfa_loop([{M,F,A} = MFA | MFAs], Acc, Seen, ModCode, ClosureInfo,
- Options) when is_atom(M), is_atom(F), is_integer(A) ->
- case sets:is_element(MFA, Seen) of
- true ->
- mfa_loop(MFAs, Acc, Seen, ModCode, ClosureInfo, Options);
- false ->
- {Icode, FunMFAs} = mfa_get(M, F, A, ModCode, ClosureInfo, Options),
- mfa_loop(FunMFAs ++ MFAs, [{MFA, Icode} | Acc],
- sets:add_element(MFA, Seen),
- ModCode, ClosureInfo, Options)
- end;
-mfa_loop([], Acc, _, _, _, _) ->
- lists:reverse(Acc).
-
-mfa_get(M, F, A, ModCode, ClosureInfo, Options) ->
- BeamCode = get_fun(ModCode, M,F,A),
- pp_beam([BeamCode], Options), % cheat by using a list
- Icode = trans_mfa_code(M,F,A, BeamCode, ClosureInfo),
- FunMFAs = get_fun_mfas(BeamCode),
- {Icode, FunMFAs}.
-
-get_fun_mfas([{patched_make_fun,{M,F,A} = MFA,_,_,_}|BeamCode])
- when is_atom(M), is_atom(F), is_integer(A) ->
- [MFA|get_fun_mfas(BeamCode)];
-get_fun_mfas([_|BeamCode]) ->
- get_fun_mfas(BeamCode);
-get_fun_mfas([]) ->
- [].
-
-%%-----------------------------------------------------------------------
%% The main translation function.
%%-----------------------------------------------------------------------
@@ -364,19 +314,19 @@ trans_fun([{call_ext_last,_N,{extfunc,M,F,A},_}|Instructions], Env) ->
%%--- bif0 ---
trans_fun([{bif,BifName,nofail,[],Reg}|Instructions], Env) ->
BifInst = trans_bif0(BifName,Reg),
- [hipe_icode:mk_comment({bif0,BifName}),BifInst|trans_fun(Instructions,Env)];
+ [BifInst|trans_fun(Instructions,Env)];
%%--- bif1 ---
trans_fun([{bif,BifName,{f,Lbl},[_] = Args,Reg}|Instructions], Env) ->
{BifInsts,Env1} = trans_bif(1,BifName,Lbl,Args,Reg,Env),
- [hipe_icode:mk_comment({bif1,BifName})|BifInsts] ++ trans_fun(Instructions,Env1);
+ BifInsts ++ trans_fun(Instructions,Env1);
%%--- bif2 ---
trans_fun([{bif,BifName,{f,Lbl},[_,_] = Args,Reg}|Instructions], Env) ->
{BifInsts,Env1} = trans_bif(2,BifName,Lbl,Args,Reg,Env),
- [hipe_icode:mk_comment({bif2,BifName})|BifInsts] ++ trans_fun(Instructions,Env1);
+ BifInsts ++ trans_fun(Instructions,Env1);
%%--- bif3 ---
trans_fun([{bif,BifName,{f,Lbl},[_,_,_] = Args,Reg}|Instructions], Env) ->
{BifInsts,Env1} = trans_bif(3,BifName,Lbl,Args,Reg,Env),
- [hipe_icode:mk_comment({bif3,BifName})|BifInsts] ++ trans_fun(Instructions,Env1);
+ BifInsts ++ trans_fun(Instructions,Env1);
%%--- allocate
trans_fun([{allocate,StackSlots,_}|Instructions], Env) ->
trans_allocate(StackSlots) ++ trans_fun(Instructions,Env);
@@ -514,10 +464,6 @@ trans_fun([{test,is_nil,{f,Lbl},[Arg]}|Instructions], Env) ->
trans_fun([{test,is_binary,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(binary,Lbl,Arg,Env),
[Code | trans_fun(Instructions,Env1)];
-%%--- is_constant ---
-trans_fun([{test,is_constant,{f,Lbl},[Arg]}|Instructions], Env) ->
- {Code,Env1} = trans_type_test(constant,Lbl,Arg,Env),
- [Code | trans_fun(Instructions,Env1)];
%%--- is_list ---
trans_fun([{test,is_list,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(list,Lbl,Arg,Env),
@@ -869,7 +815,7 @@ trans_fun([{test,bs_test_tail2,{f,Lbl},[Ms,Numbits]}| Instructions], Env) ->
trans_op_call({hipe_bs_primop,{bs_test_tail,Numbits}},
Lbl, [MsVar], [], Env, Instructions);
%%--------------------------------------------------------------------
-%% New bit syntax instructions added in February 2004 (R10B).
+%% bit syntax instructions added in February 2004 (R10B).
%%--------------------------------------------------------------------
trans_fun([{bs_init2,{f,Lbl},Size,_Words,_LiveRegs,{field_flags,Flags0},X}|
Instructions], Env) ->
@@ -1084,7 +1030,7 @@ trans_fun([{arithfbif,fnegate,Lab,[SrcR],DestR}|Instructions], Env) ->
trans_fun([{arithbif,'-',Lab,[{float,0.0},SrcR],DestR}|Instructions], Env)
end;
%%--------------------------------------------------------------------
-%% New apply instructions added in April 2004 (R10B).
+%% apply instructions added in April 2004 (R10B).
%%--------------------------------------------------------------------
trans_fun([{apply,Arity}|Instructions], Env) ->
BeamArgs = extract_fun_args(Arity+2), %% +2 is for M and F
@@ -1100,21 +1046,21 @@ trans_fun([{apply_last,Arity,_N}|Instructions], Env) -> % N is StackAdjustment?
hipe_icode:mk_enter_primop(#apply_N{arity=Arity}, [M,F|Args])
| trans_fun(Instructions,Env)];
%%--------------------------------------------------------------------
-%% New test instruction added in April 2004 (R10B).
+%% test for boolean added in April 2004 (R10B).
%%--------------------------------------------------------------------
%%--- is_boolean ---
trans_fun([{test,is_boolean,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(boolean,Lbl,Arg,Env),
[Code | trans_fun(Instructions,Env1)];
%%--------------------------------------------------------------------
-%% New test instruction added in June 2005 for R11
+%% test for function with specific arity added in June 2005 (R11).
%%--------------------------------------------------------------------
%%--- is_function2 ---
trans_fun([{test,is_function2,{f,Lbl},[Arg,Arity]}|Instructions], Env) ->
{Code,Env1} = trans_type_test2(function2,Lbl,Arg,Arity,Env),
[Code | trans_fun(Instructions,Env1)];
%%--------------------------------------------------------------------
-%% New garbage-collecting BIFs added in January 2006 for R11B.
+%% garbage collecting BIFs added in January 2006 (R11B).
%%--------------------------------------------------------------------
trans_fun([{gc_bif,'-',Fail,_Live,[SrcR],DstR}|Instructions], Env) ->
%% Unary minus. Change this to binary minus.
@@ -1132,21 +1078,21 @@ trans_fun([{gc_bif,Name,Fail,_Live,SrcRs,DstR}|Instructions], Env) ->
trans_fun([{bif,Name,Fail,SrcRs,DstR}|Instructions], Env)
end;
%%--------------------------------------------------------------------
-%% New test instruction added in July 2007 for R12.
+%% test for bitstream added in July 2007 (R12).
%%--------------------------------------------------------------------
%%--- is_bitstr ---
trans_fun([{test,is_bitstr,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(bitstr, Lbl, Arg, Env),
[Code | trans_fun(Instructions, Env1)];
%%--------------------------------------------------------------------
-%% New stack triming instruction added in October 2007 for R12.
+%% stack triming instruction added in October 2007 (R12).
%%--------------------------------------------------------------------
trans_fun([{trim,N,NY}|Instructions], Env) ->
%% trim away N registers leaving NY registers
Moves = trans_trim(N, NY),
Moves ++ trans_fun(Instructions, Env);
%%--------------------------------------------------------------------
-%% New line/1 instruction in R15.
+%% line instruction added in Fall 2012 (R15).
%%--------------------------------------------------------------------
trans_fun([{line,_}|Instructions], Env) ->
trans_fun(Instructions,Env);
@@ -1350,7 +1296,7 @@ trans_bin([{bs_put_integer,{f,Lbl},Size,Unit,{field_flags,Flags0},Source}|
SrcInstrs ++ trans_bin_call({hipe_bs_primop, Name},
Lbl, [Src|Args], [Offset], Base, Offset, Env2, Instructions);
%%----------------------------------------------------------------
-%% New binary construction instructions added in R12B-5 (Fall 2008).
+%% binary construction instructions added in Fall 2008 (R12B-5).
%%----------------------------------------------------------------
trans_bin([{bs_put_utf8,{f,Lbl},_FF,A3}|Instructions], Base, Offset, Env) ->
Src = trans_arg(A3),
@@ -1401,7 +1347,7 @@ trans_bs_get_or_skip_utf32(Lbl, Ms, Flags0, X, Instructions, Env) ->
Lbl, [Dst,MsVar], [MsVar], Env1, Instructions).
%%-----------------------------------------------------------------------
-%% trans_arith(Op, SrcVars, Des, Lab, Env) -> { Icode, NewEnv }
+%% trans_arith(Op, SrcVars, Des, Lab, Env) -> {Icode, NewEnv}
%% A failure label of type {f,0} means in a body.
%% A failure label of type {f,L} where L>0 means in a guard.
%% Within a guard a failure should branch to the next guard and
@@ -1507,7 +1453,7 @@ clone_dst(Dest) ->
%%-----------------------------------------------------------------------
-%% trans_type_test(Test, Lbl, Arg, Env) -> { Icode, NewEnv }
+%% trans_type_test(Test, Lbl, Arg, Env) -> {Icode, NewEnv}
%% Handles all unary type tests like is_integer etc.
%%-----------------------------------------------------------------------
@@ -1519,7 +1465,7 @@ trans_type_test(Test, Lbl, Arg, Env) ->
{[Move,I,True],Env1}.
%%
-%% This handles binary type tests. Currently, the only such is the new
+%% This handles binary type tests. Currently, the only such is the
%% is_function/2 BIF.
%%
trans_type_test2(function2, Lbl, Arg, Arity, Env) ->
@@ -1532,7 +1478,7 @@ trans_type_test2(function2, Lbl, Arg, Arity, Env) ->
%%-----------------------------------------------------------------------
%% trans_puts(Code, Environment) ->
-%% { Movs, Code, Vars, NewEnv }
+%% {Movs, Code, Vars, NewEnv}
%%-----------------------------------------------------------------------
trans_puts(Code, Env) ->
@@ -1884,16 +1830,6 @@ 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}.
-%%-----------------------------------------------------------------------
-
-%% Localize a particular function in a module
-get_fun([[L, {func_info,{atom,M},{atom,F},A} | Is] | _], M,F,A) ->
- [L, {func_info,{atom,M},{atom,F},A} | Is];
-get_fun([[_L1,_L2, {func_info,{atom,M},{atom,F},A} = MFA| _Is] | _], M,F,A) ->
- ?WARNING_MSG("Consecutive labels found; please re-create the .beam file~n", []),
- [_L1,_L2, MFA | _Is];
-get_fun([_|Rest], M,F,A) ->
- get_fun(Rest, M,F,A).
%%-----------------------------------------------------------------------
%% Takes a list of arguments and returns the constants of them into
diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl
index 65deaf6d7c..3b21276209 100644
--- a/lib/hipe/icode/hipe_icode.hrl
+++ b/lib/hipe/icode/hipe_icode.hrl
@@ -64,9 +64,9 @@
-type icode_if_op() :: '>' | '<' | '>=' | '=<' | '=:=' | '=/=' | '==' | '/='
| 'fixnum_eq' | 'fixnum_neq' | 'fixnum_lt'
| 'fixnum_le' | 'fixnum_ge' | 'fixnum_gt'
- | 'suspend_msg_timeout'.
+ | 'op_exact_eqeq_2' | 'suspend_msg_timeout'.
--type icode_type_test() :: 'atom' | 'bignum' | 'binary' | 'bitrst' | 'boolean'
+-type icode_type_test() :: 'atom' | 'bignum' | 'binary' | 'bitstr' | 'boolean'
| 'cons' | 'constant' | 'fixnum' | 'float'
| 'function' | 'function2' | 'integer' | 'list' | 'nil'
| 'number' | 'pid' | 'port' | 'reference' | 'tuple'
@@ -88,7 +88,7 @@
-type icode_call_type() :: 'local' | 'primop' | 'remote'.
-type icode_exit_class() :: 'error' | 'exit' | 'rethrow' | 'throw'.
--type icode_comment_text() :: atom() | string() | {atom(), term()}.
+-type icode_comment_text() :: atom() | string().
-type icode_info() :: [{'arg_types', [erl_types:erl_type()]}].
diff --git a/lib/hipe/icode/hipe_icode_coordinator.erl b/lib/hipe/icode/hipe_icode_coordinator.erl
index a71e143192..d8c82cf01c 100644
--- a/lib/hipe/icode/hipe_icode_coordinator.erl
+++ b/lib/hipe/icode/hipe_icode_coordinator.erl
@@ -2,7 +2,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
@@ -49,6 +49,12 @@ coordinate(CG, Escaping, NonEscaping, Mod) ->
fun (PM) -> last_action(PM, ServerPid, Mod, All) end,
coordinate({Clean,All}, CG, gb_trees:empty(), Restart, LastAction, ServerPid).
+-type mfalists() :: {[mfa()], [mfa()]}.
+
+-spec coordinate(mfalists(), hipe_digraph:hdg(), gb_tree(),
+ fun((mfalists(), gb_tree()) -> mfalists()),
+ fun((gb_tree()) -> 'ok'), pid()) -> no_return().
+
coordinate(MFALists, CG, PM, Restart, LastAction, ServerPid) ->
case MFALists of
{[], []} ->
@@ -106,8 +112,7 @@ last_action(PM, ServerPid, Mod, All) ->
receive
{done_rewrite, MFA} -> ok
end
- end, All),
- ok.
+ end, All).
restart_funs({Queue, Busy} = QB, PM, All, ServerPid) ->
case ?MAX_CONCURRENT - length(Busy) of
diff --git a/lib/hipe/icode/hipe_icode_inline_bifs.erl b/lib/hipe/icode/hipe_icode_inline_bifs.erl
index 27296dcad5..6ef15b9a18 100644
--- a/lib/hipe/icode/hipe_icode_inline_bifs.erl
+++ b/lib/hipe/icode/hipe_icode_inline_bifs.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
%% Currently inlined BIFs:
%% and, or, xor, not, <, >, >=, =<, ==, /=, =/=, =:=
-%% is_atom, is_boolean, is_binary, is_constant, is_float, is_function,
+%% is_atom, is_boolean, is_binary, is_float, is_function,
%% is_integer, is_list, is_pid, is_port, is_reference, is_tuple
-module(hipe_icode_inline_bifs).
@@ -131,7 +131,6 @@ is_type_test(Name) ->
is_boolean -> {true, boolean};
is_function -> {true, function};
is_reference -> {true, reference};
- is_constant -> {true, constant};
is_port -> {true, port};
_ -> false
end.
diff --git a/lib/hipe/icode/hipe_icode_mulret.erl b/lib/hipe/icode/hipe_icode_mulret.erl
index a6529c8519..a3cae621ab 100644
--- a/lib/hipe/icode/hipe_icode_mulret.erl
+++ b/lib/hipe/icode/hipe_icode_mulret.erl
@@ -2,7 +2,7 @@
%%
%% %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
@@ -595,9 +595,9 @@ optimizeDefine([I|Code], Dsts, DstLst, Res) ->
[Ds] = Dsts,
case isCallPrimop(I, mktuple) andalso DstLst =:= [] of
true ->
- case (hipe_icode:call_dstlist(I) =:= Dsts) of
+ case hipe_icode:call_dstlist(I) =:= Dsts of
true ->
- case (hipe_icode:call_args(I) > 1) of
+ case length(hipe_icode:call_args(I)) > 1 of
true ->
optimizeDefine(Code, Dsts, hipe_icode:call_args(I), Res);
false ->
diff --git a/lib/hipe/icode/hipe_icode_pp.erl b/lib/hipe/icode/hipe_icode_pp.erl
index 575bbfe43d..de29b6f779 100755..100644
--- a/lib/hipe/icode/hipe_icode_pp.erl
+++ b/lib/hipe/icode/hipe_icode_pp.erl
@@ -2,7 +2,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
diff --git a/lib/hipe/icode/hipe_icode_ssa.erl b/lib/hipe/icode/hipe_icode_ssa.erl
index 719d5d8f45..4607a96dda 100755..100644
--- a/lib/hipe/icode/hipe_icode_ssa.erl
+++ b/lib/hipe/icode/hipe_icode_ssa.erl
@@ -2,7 +2,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
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index 3f9488d7c3..046949d2f2 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,13 +79,13 @@
-import(erl_types, [number_min/1, number_max/1,
t_any/0, t_atom/1, t_atom/0, t_atom_vals/1,
t_binary/0, t_bitstr/0, t_bitstr_base/1, t_bitstr_unit/1,
- t_boolean/0, t_cons/0, t_constant/0,
+ t_boolean/0, t_cons/0,
t_float/0, t_from_term/1, t_from_range/2,
t_fun/0, t_fun/1, t_fun/2, t_fun_args/1, t_fun_arity/1,
t_inf/2, t_inf_lists/2, t_integer/0,
t_integer/1, t_is_atom/1, t_is_any/1,
t_is_binary/1, t_is_bitstr/1, t_is_bitwidth/1, t_is_boolean/1,
- t_is_fixnum/1, t_is_cons/1, t_is_constant/1,
+ t_is_fixnum/1, t_is_cons/1,
t_is_maybe_improper_list/1, t_is_equal/2, t_is_float/1,
t_is_fun/1, t_is_integer/1, t_is_non_neg_integer/1,
t_is_number/1, t_is_matchstate/1,
@@ -587,7 +587,6 @@ do_type(I, Info, Var) ->
TrueLab = hipe_icode:type_true_label(I),
FalseLab = hipe_icode:type_false_label(I),
None = t_none(),
-
case lookup(Var, Info) of
None ->
[{TrueLab, Info}, {FalseLab, Info}];
@@ -899,9 +898,7 @@ test_type0(list, T) ->
test_type0(cons, T) ->
t_is_cons(T);
test_type0(nil, T) ->
- t_is_nil(T);
-test_type0(constant, T) ->
- t_is_constant(T).
+ t_is_nil(T).
true_branch_info(integer) ->
@@ -940,8 +937,6 @@ true_branch_info(nil) ->
t_nil();
true_branch_info(boolean) ->
t_boolean();
-true_branch_info(constant) ->
- t_constant();
true_branch_info(T) ->
exit({?MODULE,unknown_typetest,T}).
@@ -1703,7 +1698,6 @@ lookup_list0([H|T], Info, Acc) ->
lookup_list0([], _, Acc) ->
lists:reverse(Acc).
-
%% safe_lookup treats anything that is neither in the map nor a
%% constant as t_any(). Use this during transformations.
diff --git a/lib/hipe/main/Makefile b/lib/hipe/main/Makefile
index a14c9c3ca4..673431a175 100644
--- a/lib/hipe/main/Makefile
+++ b/lib/hipe/main/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -93,6 +93,9 @@ clean:
rm -f $(TARGET_FILES) $(DOC_FILES) $(HRL_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -112,10 +115,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DATA) ../vsn.mk $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/main
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/main
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) ../vsn.mk "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/main"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/main"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src
index e5d6d1e540..7db4db8a57 100644
--- a/lib/hipe/main/hipe.app.src
+++ b/lib/hipe/main/hipe.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,6 @@
{modules, [cerl_cconv,
cerl_closurean,
cerl_hipeify,
- cerl_hybrid_transform,
cerl_lib,
cerl_messagean,
cerl_pmatch,
@@ -74,7 +73,6 @@
hipe_arm_specific,
hipe_bb,
hipe_beam_to_icode,
- hipe_ceach,
hipe_coalescing_regalloc,
hipe_consttab,
hipe_data_pp,
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 570e4d9d17..b2789978a4 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,9 +47,8 @@
%%
%% <h3>Using the direct interface - for advanced users only</h3>
%%
-%% To compile a module or a specific function to native code and
-%% automatically load the code into memory, call <a
-%% href="#c-1"><code>hipe:c(Module)</code></a> or <a
+%% To compile a module to native code and automatically load the code
+%% into memory, call <a href="#c-1"><code>hipe:c(Module)</code></a> or <a
%% href="#c-2"><code>hipe:c(Module, Options)</code></a>. Note that all
%% options are specific to the HiPE compiler. See the <a
%% href="#index">function index</a> for other compiler functions.
@@ -221,11 +220,10 @@
%%-------------------------------------------------------------------
-type mod() :: atom().
--type c_unit() :: mod() | mfa().
-type f_unit() :: mod() | binary().
-type ret_rtl() :: [_].
--type c_ret() :: {'ok', c_unit()} | {'error', term()} |
- {'ok', c_unit(), ret_rtl()}. %% The last for debugging only
+-type c_ret() :: {'ok', mod()} | {'error', term()} |
+ {'ok', mod(), ret_rtl()}. %% The last for debugging only
-type compile_file() :: atom() | string() | binary().
-type compile_ret() :: {hipe_architecture(), binary()} | list().
@@ -278,47 +276,44 @@ load(Mod, BeamFileName) when is_list(BeamFileName) ->
end.
%% @spec c(Name) -> {ok, Name} | {error, Reason}
-%% Name = mod() | mfa()
+%% Name = mod()
%% Reason = term()
%%
%% @equiv c(Name, [])
--spec c(c_unit()) -> c_ret().
+-spec c(mod()) -> c_ret().
c(Name) ->
c(Name, []).
%% @spec c(Name, options()) -> {ok, Name} | {error, Reason}
-%% Name = mod() | mfa()
+%% Name = mod()
%% options() = [option()]
%% option() = term()
%% Reason = term()
%%
-%% @type mfa() = {M::mod(),F::fun(),A::arity()}.
-%% A fully qualified function name.
-%%
%% @type fun() = atom(). A function identifier.
%%
%% @type arity() = integer(). A function arity; always nonnegative.
%%
%% @doc User-friendly native code compiler interface. Reads BEAM code
-%% from the corresponding "Module<code>.beam</code>" file in the system
-%% path, and compiles either a single function or the whole module to
-%% native code. By default, the compiled code is loaded directly. See
-%% above for documentation of options.
+%% from the corresponding "Module<code>.beam</code>" file in the
+%% system path, and compiles the whole module to native code. By
+%% default, the compiled code is loaded directly. See above for
+%% documentation of options.
%%
%% @see c/1
%% @see c/3
%% @see f/2
%% @see compile/2
--spec c(c_unit(), comp_options()) -> c_ret().
+-spec c(mod(), comp_options()) -> c_ret().
c(Name, Options) ->
c(Name, beam_file(Name), Options).
%% @spec c(Name, File, options()) -> {ok, Name} | {error, Reason}
-%% Name = mod() | mfa()
+%% Name = mod()
%% File = filename() | binary()
%% Reason = term()
%%
@@ -329,7 +324,6 @@ c(Name, Options) ->
%% @see f/2
c(Name, File, Opts) ->
- %% No server if only one function is compiled
Opts1 = user_compile_opts(Opts),
case compile(Name, File, Opts1) of
{ok, Res} ->
@@ -359,8 +353,7 @@ f(File) ->
%% Reason = term()
%%
%% @doc Like <code>c/3</code>, but takes the module name from the
-%% specified <code>File</code>. This always compiles the whole module;
-%% there is no possibility to compile just a single function.
+%% specified <code>File</code>.
%%
%% @see c/3
@@ -381,26 +374,26 @@ user_compile_opts(Opts) ->
%% @spec compile(Name) -> {ok, {Target,Binary}} | {error, Reason}
-%% Name = mod() | mfa()
+%% Name = mod()
%% Binary = binary()
%% Reason = term()
%%
%% @equiv compile(Name, [])
--spec compile(c_unit()) -> {'ok', compile_ret()} | {'error', term()}.
+-spec compile(mod()) -> {'ok', compile_ret()} | {'error', term()}.
compile(Name) ->
compile(Name, []).
%% @spec compile(Name, options()) -> {ok, {Target,Binary}} | {error, Reason}
-%% Name = mod() | mfa()
+%% Name = mod()
%% Binary = binary()
%% Reason = term()
%%
-%% @doc Direct compiler interface, for advanced use. This just compiles
-%% the named function or module, reading BEAM code from the
-%% corresponding "Module<code>.beam</code>" file in the system path.
-%% Returns <code>{ok, Binary}</code> if successful, or <code>{error,
+%% @doc Direct compiler interface, for advanced use. This just
+%% compiles the module, reading BEAM code from the corresponding
+%% "Module<code>.beam</code>" file in the system path. Returns
+%% <code>{ok, Binary}</code> if successful, or <code>{error,
%% Reason}</code> otherwise. By default, it does <em>not</em> load the
%% binary to memory (the <code>load</code> option can be used to
%% activate automatic loading). <code>File</code> can be either a file
@@ -412,15 +405,13 @@ compile(Name) ->
%% @see file/2
%% @see load/2
--spec compile(c_unit(), comp_options()) -> {'ok', compile_ret()} | {'error', _}.
+-spec compile(mod(), comp_options()) -> {'ok', compile_ret()} | {'error', _}.
compile(Name, Options) ->
compile(Name, beam_file(Name), Options).
--spec beam_file(mod() | mfa()) -> string().
+-spec beam_file(mod()) -> string().
-beam_file({M,F,A}) when is_atom(M), is_atom(F), is_integer(A), A >= 0 ->
- beam_file(M);
beam_file(Module) when is_atom(Module) ->
case code:which(Module) of
non_existing ->
@@ -432,7 +423,7 @@ beam_file(Module) when is_atom(Module) ->
%% @spec compile(Name, File, options()) ->
%% {ok, {Target, Binary}} | {error, Reason}
-%% Name = mod() | mfa()
+%% Name = mod()
%% File = filename() | binary()
%% Binary = binary()
%% Reason = term()
@@ -442,18 +433,11 @@ beam_file(Module) when is_atom(Module) ->
%%
%% @see compile/2
--spec compile(c_unit(), compile_file(), comp_options()) ->
+-spec compile(mod(), compile_file(), comp_options()) ->
{'ok', compile_ret()} | {'error', term()}.
-compile(Name, File, Opts0) ->
- Opts1 = expand_kt2(Opts0),
- Opts =
- case Name of
- {_Mod, _Fun, _Arity} ->
- [no_concurrent_comp|Opts1];
- _ ->
- Opts1
- end,
+compile(Name, File, Opts0) when is_atom(Name) ->
+ Opts = expand_kt2(Opts0),
case proplists:get_value(core, Opts) of
true when is_binary(File) ->
?error_msg("Cannot get Core Erlang code from BEAM binary.",[]),
@@ -486,23 +470,11 @@ compile(Name, File, Opts0) ->
?EXIT({cant_compile_source_code, Error})
end;
Other when Other =:= false; Other =:= undefined ->
- NewOpts =
- case proplists:get_value(use_callgraph, Opts) of
- No when No =:= false; No =:= undefined -> Opts;
- _ ->
- case Name of
- {_M,_F,_A} ->
- %% There is no point in using the callgraph or concurrent_comp
- %% when analyzing just one function.
- [no_use_callgraph, no_concurrent_comp|Opts];
- _ -> Opts
- end
- end,
DisasmFun = fun (_) -> disasm(File) end,
IcodeFun = fun (Code, Opts_) ->
get_beam_icode(Name, Code, File, Opts_)
end,
- run_compiler(Name, DisasmFun, IcodeFun, NewOpts)
+ run_compiler(Name, DisasmFun, IcodeFun, Opts)
end.
-spec compile_core(mod(), cerl:c_module(), compile_file(), comp_options()) ->
@@ -510,12 +482,7 @@ compile(Name, File, Opts0) ->
compile_core(Name, Core0, File, Opts) ->
Core = cerl:from_records(Core0),
- Core1 = case (erlang:system_info(heap_type) =:= hybrid)
- andalso proplists:get_bool(hybrid, Opts) of
- true -> cerl_hybrid_transform:transform(Core, Opts);
- false -> Core
- end,
- compile(Name, Core1, File, Opts).
+ compile(Name, Core, File, Opts).
%% @spec compile(Name, Core, File, options()) ->
%% {ok, {Target, Binary}} | {error, Reason}
@@ -604,7 +571,7 @@ disasm(File) ->
#beam_file{labeled_exports = LabeledExports,
compile_info = CompInfo,
code = BeamCode} ->
- {options, CompOpts} = lists:keyfind(options, 1, CompInfo),
+ CompOpts = proplists:get_value(options, CompInfo, []),
HCompOpts = case lists:keyfind(hipe, 1, CompOpts) of
{hipe, L} when is_list(L) -> L;
{hipe, X} -> [X];
@@ -625,11 +592,6 @@ fix_beam_exports([{F,A,_}|BeamExports], Exports) ->
fix_beam_exports([], Exports) ->
Exports.
-get_beam_icode({M,_F,_A} = MFA, {BeamCode, Exports}, _File, Options) ->
- ?option_time({ok, Icode} =
- (catch {ok, hipe_beam_to_icode:mfa(BeamCode, MFA, Options)}),
- "BEAM-to-Icode", Options),
- {{M, Exports, Icode}, false};
get_beam_icode(Mod, {BeamCode, Exports}, File, Options) ->
?option_time({ok, Icode} =
(catch {ok, hipe_beam_to_icode:module(BeamCode, Options)}),
@@ -899,7 +861,8 @@ maybe_load(Mod, Bin, WholeModule, Opts) ->
do_load(Mod, Bin, WholeModule)
end.
-do_load(Mod, Bin, WholeModule) ->
+do_load(Mod, Bin, BeamBinOrPath) when is_binary(BeamBinOrPath);
+ is_list(BeamBinOrPath) ->
HostArch = get(hipe_host_arch),
TargetArch = get(hipe_target_arch),
%% Make sure we can do the load.
@@ -907,29 +870,22 @@ do_load(Mod, Bin, WholeModule) ->
?EXIT({host_and_target_arch_differ, HostArch, TargetArch});
true -> ok
end,
- case WholeModule of
+ case code:is_sticky(Mod) of
+ true ->
+ %% We unpack and repack the Beam binary as a workaround to
+ %% ensure that it is not compressed.
+ {ok, _, Chunks} = beam_lib:all_chunks(BeamBinOrPath),
+ {ok, Beam} = beam_lib:build_module(Chunks),
+ %% Don't purge or register sticky mods; just load native.
+ code:load_native_sticky(Mod, Bin, Beam);
false ->
- %% In this case, the emulated code for the module must be loaded.
- {module, Mod} = code:ensure_loaded(Mod),
- code:load_native_partial(Mod, Bin);
- BeamBinOrPath when is_binary(BeamBinOrPath) orelse is_list(BeamBinOrPath) ->
- case code:is_sticky(Mod) of
- true ->
- %% We unpack and repack the Beam binary as a workaround to
- %% ensure that it is not compressed.
- {ok, _, Chunks} = beam_lib:all_chunks(WholeModule),
- {ok, Beam} = beam_lib:build_module(Chunks),
- %% Don't purge or register sticky mods; just load native.
- code:load_native_sticky(Mod, Bin, Beam);
- false ->
- %% Normal loading of a whole module
- Architecture = erlang:system_info(hipe_architecture),
- ChunkName = hipe_unified_loader:chunk_name(Architecture),
- {ok, _, Chunks0} = beam_lib:all_chunks(WholeModule),
- Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)],
- {ok, BeamPlusNative} = beam_lib:build_module(Chunks),
- code:load_binary(Mod, code:which(Mod), BeamPlusNative)
- end
+ %% Normal loading of a whole module
+ Architecture = erlang:system_info(hipe_architecture),
+ ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ {ok, _, Chunks0} = beam_lib:all_chunks(BeamBinOrPath),
+ Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)],
+ {ok, BeamPlusNative} = beam_lib:build_module(Chunks),
+ code:load_binary(Mod, code:which(Mod), BeamPlusNative)
end.
assemble(CompiledCode, Closures, Exports, Options) ->
diff --git a/lib/hipe/misc/Makefile b/lib/hipe/misc/Makefile
index 98a69d62c7..1204ab7c0b 100644
--- a/lib/hipe/misc/Makefile
+++ b/lib/hipe/misc/Makefile
@@ -100,10 +100,10 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/misc
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/misc
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/misc"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/misc"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/native.mk b/lib/hipe/native.mk
index 6f4602477b..738e78e556 100644
--- a/lib/hipe/native.mk
+++ b/lib/hipe/native.mk
@@ -1,5 +1,7 @@
-ifndef SECONDARY_BOOTSTRAP
ifeq ($(NATIVE_LIBS_ENABLED),yes)
+ifndef SECONDARY_BOOTSTRAP
ERL_COMPILE_FLAGS += +native
+else
+EBIN = ../boot_ebin
endif
endif
diff --git a/lib/hipe/opt/Makefile b/lib/hipe/opt/Makefile
index 74fde26c0b..a21c543574 100644
--- a/lib/hipe/opt/Makefile
+++ b/lib/hipe/opt/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The 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,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
@@ -80,6 +80,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -94,8 +97,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/opt/hipe_schedule.erl b/lib/hipe/opt/hipe_schedule.erl
index 4925b2927b..4f153e17ad 100644
--- a/lib/hipe/opt/hipe_schedule.erl
+++ b/lib/hipe/opt/hipe_schedule.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
@@ -797,7 +797,7 @@ dep_arc(N, Lat, M, {Dag,Preds}) ->
%% Returns : A dependence graph sorted by To.
%% Description : A new arc that is added is sorted in the right place, and if
%% there is already an arc between nodes A and B, the one with
-%% the greatest latency is choosen.
+%% the greatest latency is chosen.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
add_arc(Lat,To, []) -> {[{Lat, To}], added};
add_arc(Lat1, To, [{Lat2, To} | Arcs]) ->
diff --git a/lib/hipe/ppc/Makefile b/lib/hipe/ppc/Makefile
index f24139e34b..8bd2a8226c 100644
--- a/lib/hipe/ppc/Makefile
+++ b/lib/hipe/ppc/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The 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,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -105,8 +108,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/regalloc/Makefile b/lib/hipe/regalloc/Makefile
index 386f3589c6..d4be79ea85 100644
--- a/lib/hipe/regalloc/Makefile
+++ b/lib/hipe/regalloc/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -94,6 +94,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -109,8 +112,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index 55d20af8af..426d1bd3ee 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -89,6 +89,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core erl_crash.dump
+distclean: clean
+realclean: clean
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
@@ -100,18 +103,38 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/rtl
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/rtl
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/rtl"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/rtl"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
-HIPE_MKLITERALS=$(ERL_TOP)/bin/$(TARGET)/hipe_mkliterals
+ifeq ($(TYPE),debug)
+TYPE_STR=.debug
+else
+TYPE_STR=
+endif
+
+ifeq ($(FLAVOR),smp)
+FLAVOR_STR=.smp
+else
+FLAVOR_STR=
+endif
+
+ifeq ($(XCOMP),yes)
+MKLIT_FLAGS= -x
+else
+MKLIT_FLAGS=
+endif
+
+
+HIPE_MKLITERALS=$(ERL_TOP)/bin/$(TARGET)/hipe_mkliterals$(TYPE_STR)$(FLAVOR_STR)
+
hipe_literals.hrl: $(HIPE_MKLITERALS)
- $(HIPE_MKLITERALS) -e > hipe_literals.hrl
+ $(HIPE_MKLITERALS) $(MKLIT_FLAGS) -e > hipe_literals.hrl
# Need to generate hipe.hrl from one and only one target in one and only
# one makefile; otherwise, clearmake will force rebuilds of hipe over and
@@ -119,27 +142,35 @@ hipe_literals.hrl: $(HIPE_MKLITERALS)
../main/hipe.hrl: ../vsn.mk ../main/hipe.hrl.src
(cd ../main && $(MAKE) hipe.hrl)
-$(EBIN)/hipe_rtl.beam: hipe_rtl.hrl ../main/hipe.hrl
-$(EBIN)/hipe_rtl_arch.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_binary.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_bin_util.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_cfg.beam: hipe_rtl.hrl ../flow/cfg.hrl ../flow/cfg.inc ../main/hipe.hrl
-$(EBIN)/hipe_rtl_cleanup_const.beam: hipe_rtl.hrl
-$(EBIN)/hipe_rtl_liveness.beam: hipe_rtl.hrl ../flow/cfg.hrl ../flow/liveness.inc
-$(EBIN)/hipe_icode2rtl.beam: hipe_literals.hrl ../main/hipe.hrl ../icode/hipe_icode.hrl
-$(EBIN)/hipe_tagscheme.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_primops.beam: hipe_rtl.hrl ../icode/hipe_icode_primops.hrl hipe_literals.hrl ../main/hipe.hrl
+# 2012-02-24. Please keep these dependencies up to date. They tend to rot.
+# grep ^-include *.erl says a lot, but you need to dig further, e.g:
+# grep ^-include ../flow/*.{hrl,inc}
+$(EBIN)/hipe_icode2rtl.beam: \
+ ../main/hipe.hrl ../icode/hipe_icode.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_arch.beam: hipe_literals.hrl
$(EBIN)/hipe_rtl_arith_32.beam: ../main/hipe.hrl hipe_rtl_arith.inc
$(EBIN)/hipe_rtl_arith_64.beam: ../main/hipe.hrl hipe_rtl_arith.inc
-$(EBIN)/hipe_rtl_bs_ops.beam: hipe_literals.hrl ../main/hipe.hrl
-$(EBIN)/hipe_rtl_cerl_bs_ops.beam: ../main/hipe.hrl hipe_literals.hrl hipe_rtl.hrl
-$(EBIN)/hipe_rtl_exceptions.beam: hipe_literals.hrl ../main/hipe.hrl
-$(EBIN)/hipe_rtl_inline_bs_ops.beam: hipe_rtl.hrl hipe_literals.hrl ../main/hipe.hrl
+$(EBIN)/hipe_rtl_binary_construct.beam: \
+ ../main/hipe.hrl hipe_rtl.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_binary_match.beam: hipe_literals.hrl
+$(EBIN)/hipe_rtl_cfg.beam: \
+ ../main/hipe.hrl hipe_rtl.hrl ../flow/cfg.hrl ../flow/cfg.inc
+$(EBIN)/hipe_rtl_cleanup_const.beam: hipe_rtl.hrl
+$(EBIN)/hipe_rtl.beam: ../main/hipe.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_exceptions.beam: ../main/hipe.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_lcm.beam: ../main/hipe.hrl hipe_rtl.hrl ../flow/cfg.hrl
+$(EBIN)/hipe_rtl_liveness.beam: hipe_rtl.hrl ../flow/cfg.hrl ../flow/liveness.inc
$(EBIN)/hipe_rtl_mk_switch.beam: ../main/hipe.hrl
-$(EBIN)/hipe_rtl_lcm.beam: ../flow/cfg.hrl hipe_rtl.hrl
-$(EBIN)/hipe_rtl_symbolic.beam: hipe_rtl.hrl hipe_literals.hrl ../flow/cfg.hrl ../icode/hipe_icode_primops.hrl
-$(EBIN)/hipe_rtl_varmap.beam: ../main/hipe.hrl ../icode/hipe_icode.hrl
-
-$(EBIN)/hipe_rtl_ssa.beam: ../ssa/hipe_ssa.inc ../main/hipe.hrl ../ssa/hipe_ssa_liveness.inc hipe_rtl.hrl
-$(EBIN)/hipe_rtl_ssa_const_prop.beam: hipe_rtl.hrl ../main/hipe.hrl ../flow/cfg.hrl ../ssa/hipe_ssa_const_prop.inc
-$(EBIN)/hipe_rtl_ssapre.beam: ../main/hipe.hrl ../flow/cfg.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_primops.beam: ../main/hipe.hrl \
+ ../icode/hipe_icode_primops.hrl hipe_rtl.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_ssa_avail_expr.beam: ../main/hipe.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_ssa_const_prop.beam: ../main/hipe.hrl hipe_rtl.hrl \
+ ../flow/cfg.hrl ../ssa/hipe_ssa_const_prop.inc
+$(EBIN)/hipe_rtl_ssa.beam: hipe_rtl.hrl \
+ ../main/hipe.hrl ../ssa/hipe_ssa_liveness.inc ../ssa/hipe_ssa.inc
+$(EBIN)/hipe_rtl_ssapre.beam: ../main/hipe.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_symbolic.beam: hipe_rtl.hrl hipe_literals.hrl \
+ ../icode/hipe_icode_primops.hrl
+$(EBIN)/hipe_rtl_varmap.beam: ../main/hipe.hrl \
+ ../misc/hipe_consttab.hrl ../icode/hipe_icode.hrl
+$(EBIN)/hipe_tagscheme.beam: hipe_rtl.hrl hipe_literals.hrl
diff --git a/lib/hipe/rtl/hipe_rtl.erl b/lib/hipe/rtl/hipe_rtl.erl
index 29e9c8c8fe..4bf4eb6bd7 100644
--- a/lib/hipe/rtl/hipe_rtl.erl
+++ b/lib/hipe/rtl/hipe_rtl.erl
@@ -781,8 +781,11 @@ fstore_src_update(F, NewSrc) -> F#fstore{src=NewSrc}.
%% fp
%%
+
mk_fp(Dst, Src1, Op, Src2) ->
- #fp{dst=Dst, src1=Src1, op=Op, src2=Src2}.
+ [#fp{dst=Dst, src1=Src1, op=Op, src2=Src2}
+ | hipe_rtl_arch:mk_fp_check_result(Dst)].
+
fp_dst(#fp{dst=Dst}) -> Dst.
fp_dst_update(Fp, NewDst) -> Fp#fp{dst=NewDst}.
fp_src1(#fp{src1=Src1}) -> Src1.
diff --git a/lib/hipe/rtl/hipe_rtl_arch.erl b/lib/hipe/rtl/hipe_rtl_arch.erl
index 22cda57a3a..99eb80f3d1 100644
--- a/lib/hipe/rtl/hipe_rtl_arch.erl
+++ b/lib/hipe/rtl/hipe_rtl_arch.erl
@@ -65,7 +65,8 @@
%% alignment/0,
nr_of_return_regs/0,
log2_word_size/0,
- word_size/0
+ word_size/0,
+ mk_fp_check_result/1
]).
-include("hipe_literals.hrl").
@@ -558,6 +559,12 @@ eval_cond_bits(Cond, N, Z, V, C) ->
%%----------------------------------------------------------------------
fwait() ->
+ case ?ERTS_NO_FPE_SIGNALS of
+ 1 -> [];
+ 0 -> fwait_real()
+ end.
+
+fwait_real() ->
case get(hipe_target_arch) of
x86 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)];
amd64 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)];
@@ -573,6 +580,12 @@ fwait() ->
%% Returns RTL code to restore the FPU after a floating-point exception.
%% @end
handle_fp_exception() ->
+ case ?ERTS_NO_FPE_SIGNALS of
+ 1 -> [];
+ 0 -> handle_real_fp_exception()
+ end.
+
+handle_real_fp_exception() ->
case get(hipe_target_arch) of
x86 ->
ContLbl = hipe_rtl:mk_new_label(),
@@ -655,3 +668,15 @@ nr_of_return_regs() ->
1
%% hipe_amd64_registers:nr_rets();
end.
+
+
+mk_fp_check_result(Result) ->
+ case ?ERTS_NO_FPE_SIGNALS of
+ 0 ->
+ [];
+ 1 ->
+ [hipe_rtl:mk_fstore(proc_pointer(),
+ hipe_rtl:mk_imm(?P_FLOAT_RESULT),
+ Result),
+ hipe_rtl:mk_call([], emulate_fpe, [], [], [], not_remote)]
+ end.
diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl
index 9224623c8b..262aedb409 100644
--- a/lib/hipe/rtl/hipe_rtl_lcm.erl
+++ b/lib/hipe/rtl/hipe_rtl_lcm.erl
@@ -486,7 +486,7 @@ lcm_precalc(CFG, Options) ->
?option_time(NodeInfo2 = calc_down_exp(CFG, ExprMap, NodeInfo1, Labels),
"RTL LCM calc_down_exp", Options),
?option_time(NodeInfo3 = calc_killed_expr(CFG, NodeInfo2, UseMap, AllExpr,
- Labels),
+ IdMap, Labels),
"RTL LCM calc_killed_exp", Options),
?option_time(NodeInfo4 = calc_avail(CFG, NodeInfo3),
"RTL LCM calc_avail", Options),
@@ -815,19 +815,19 @@ exp_kill_expr(Instr, [CheckedExpr|Exprs]) ->
%%=============================================================================
%% Calculates the killed expression sets for all given labels.
-calc_killed_expr(_, NodeInfo, _, _, []) ->
+calc_killed_expr(_, NodeInfo, _, _, _, []) ->
NodeInfo;
-calc_killed_expr(CFG, NodeInfo, UseMap, AllExpr, [Label|Labels]) ->
+calc_killed_expr(CFG, NodeInfo, UseMap, AllExpr, IdMap, [Label|Labels]) ->
Code = hipe_bb:code(hipe_rtl_cfg:bb(CFG, Label)),
- KilledExprs = calc_killed_expr_bb(Code, UseMap, AllExpr, ?SETS:new()),
+ KilledExprs = calc_killed_expr_bb(Code, UseMap, AllExpr, IdMap, ?SETS:new()),
NewNodeInfo = set_killed_expr(NodeInfo, Label, KilledExprs),
- calc_killed_expr(CFG, NewNodeInfo, UseMap, AllExpr, Labels).
+ calc_killed_expr(CFG, NewNodeInfo, UseMap, AllExpr, IdMap, Labels).
%%=============================================================================
%% Calculates the killed expressions set for one basic block.
-calc_killed_expr_bb([], _UseMap, _AllExpr, KilledExprs) ->
+calc_killed_expr_bb([], _UseMap, _AllExpr, _IdMap, KilledExprs) ->
KilledExprs;
-calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) ->
+calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, IdMap, KilledExprs) ->
%% Calls, gctests and stores potentially clobber everything
case Instr of
#call{} -> AllExpr;
@@ -837,7 +837,8 @@ calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) ->
%% Kill all float expressions
%% FIXME: Make separate function is_fp_expr
?SETS:from_list
- (lists:foldl(fun(Expr, Fexprs) ->
+ (lists:foldl(fun(ExprId, Fexprs) ->
+ Expr = expr_id_map_get_expr(IdMap, ExprId),
[Define|_] = hipe_rtl:defines(Expr),
case hipe_rtl:is_fpreg(Define) of
true ->
@@ -849,10 +850,10 @@ calc_killed_expr_bb([Instr|Instrs], UseMap, AllExpr, KilledExprs) ->
_ ->
case hipe_rtl:defines(Instr) of
[] ->
- calc_killed_expr_bb(Instrs, UseMap, AllExpr, KilledExprs);
+ calc_killed_expr_bb(Instrs, UseMap, AllExpr, IdMap, KilledExprs);
[Define|_] ->
NewKilledExprs = use_map_get_expr_uses(UseMap, Define),
- calc_killed_expr_bb(Instrs, UseMap, AllExpr,
+ calc_killed_expr_bb(Instrs, UseMap, AllExpr, IdMap,
?SETS:union(NewKilledExprs, KilledExprs))
end
end.
diff --git a/lib/hipe/sparc/Makefile b/lib/hipe/sparc/Makefile
index f25212a89b..eb40117691 100644
--- a/lib/hipe/sparc/Makefile
+++ b/lib/hipe/sparc/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The 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,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -105,8 +108,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/sparc/hipe_rtl_to_sparc.erl b/lib/hipe/sparc/hipe_rtl_to_sparc.erl
index df5e2b0077..c93f603826 100644
--- a/lib/hipe/sparc/hipe_rtl_to_sparc.erl
+++ b/lib/hipe/sparc/hipe_rtl_to_sparc.erl
@@ -19,6 +19,7 @@
%%
-module(hipe_rtl_to_sparc).
+
-export([translate/1]).
-include("../rtl/hipe_rtl.hrl").
@@ -142,8 +143,7 @@ mk_fload_rr(Base1, Base2, Dst) ->
mk_fload_ii(Base1, Base2, Dst) ->
io:format("~w: RTL fload with two immediates\n", [?MODULE]),
Tmp = new_untagged_temp(),
- mk_set(Base1, Tmp,
- mk_fload_ri(Tmp, Base2, Dst)).
+ mk_set(Base1, Tmp, mk_fload_ri(Tmp, Base2, Dst)).
mk_fload_ri(Base, Disp, Dst) ->
hipe_sparc:mk_fload(Base, Disp, Dst, 'new').
@@ -239,8 +239,7 @@ mk_alu_ii(XAluOp, Src1, Src2, Dst) ->
io:format("~w: ALU with two immediates (~w ~w ~w ~w)\n",
[?MODULE, XAluOp, Src1, Src2, Dst]),
Tmp = new_untagged_temp(),
- mk_set(Src1, Tmp,
- mk_alu_ri(XAluOp, Tmp, Src2, Dst)).
+ mk_set(Src1, Tmp, mk_alu_ri(XAluOp, Tmp, Src2, Dst)).
mk_alu_ir(XAluOp, Src1, Src2, Dst) ->
case xaluop_commutes(XAluOp) of
@@ -249,8 +248,7 @@ mk_alu_ir(XAluOp, Src1, Src2, Dst) ->
true};
_ ->
Tmp = new_untagged_temp(),
- {mk_set(Src1, Tmp,
- mk_alu_rs(XAluOp, Tmp, Src2, Dst)),
+ {mk_set(Src1, Tmp, mk_alu_rs(XAluOp, Tmp, Src2, Dst)),
false}
end.
@@ -274,8 +272,7 @@ mk_arith_ri(XAluOp, Src1, Src2, Dst) when is_integer(Src2) ->
mk_alu_rs(XAluOp, Src1, hipe_sparc:mk_simm13(Src2), Dst);
true ->
Tmp = new_untagged_temp(),
- mk_set(Src2, Tmp,
- mk_alu_rs(XAluOp, Src1, Tmp, Dst))
+ mk_set(Src2, Tmp, mk_alu_rs(XAluOp, Src1, Tmp, Dst))
end.
mk_alu_rs(XAluOp, Src1, Src2, Dst) ->
@@ -623,8 +620,7 @@ mk_move(Src, Dst, Tail) ->
conv_return(I, Map, Data) ->
%% TODO: multiple-value returns
{[Arg], Map0} = conv_src_list(hipe_rtl:return_varlist(I), Map),
- I2 = mk_move(Arg, hipe_sparc:mk_rv(),
- [hipe_sparc:mk_pseudo_ret()]),
+ I2 = mk_move(Arg, hipe_sparc:mk_rv(), [hipe_sparc:mk_pseudo_ret()]),
{I2, Map0, Data}.
conv_store(I, Map, Data) ->
@@ -648,8 +644,7 @@ mk_store(StOp, Src, Base1, Base2) ->
mk_store2(StOp, Src, Base1, Base2);
_ ->
Tmp = new_untagged_temp(),
- mk_set(Src, Tmp,
- mk_store2(StOp, Tmp, Base1, Base2))
+ mk_set(Src, Tmp, mk_store2(StOp, Tmp, Base1, Base2))
end.
mk_store2(StOp, Src, Base1, Base2) ->
@@ -674,8 +669,7 @@ conv_switch(I, Map, Data) ->
[] ->
hipe_consttab:insert_block(Data, word, LMap);
SortOrder ->
- hipe_consttab:insert_sorted_block(
- Data, word, LMap, SortOrder)
+ hipe_consttab:insert_sorted_block(Data, word, LMap, SortOrder)
end,
%% no immediates allowed here
{IndexR, Map1} = conv_dst(hipe_rtl:switch_src(I), Map),
@@ -722,7 +716,7 @@ conv_aluop(RtlAluOp) ->
xaluop_commutes(XAluOp) ->
case XAluOp of
- 'cmp' -> true;
+ %% 'cmp' -> true;
'cmpcc' -> true;
'add' -> true;
'addcc' -> true;
@@ -739,16 +733,16 @@ xaluop_commutes(XAluOp) ->
'sll' -> false;
'srl' -> false;
'sra' -> false;
- 'sllx' -> false;
- 'srlx' -> false;
- 'srax' -> false;
+ %% 'sllx' -> false;
+ %% 'srlx' -> false;
+ %% 'srax' -> false;
'ldsb' -> true;
'ldsh' -> true;
- 'ldsw' -> true;
+ %% 'ldsw' -> true;
'ldub' -> true;
'lduh' -> true;
- 'lduw' -> true;
- 'ldx' -> true
+ 'lduw' -> true
+ %% 'ldx' -> true
end.
%%% Check if an extended SPARC AluOp is a shift.
diff --git a/lib/hipe/tools/Makefile b/lib/hipe/tools/Makefile
index 0eaa3a7b05..6761f11b01 100644
--- a/lib/hipe/tools/Makefile
+++ b/lib/hipe/tools/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
@@ -42,7 +42,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN)
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-MODULES = hipe_tool hipe_profile hipe_ceach hipe_jit
+MODULES = hipe_tool hipe_profile hipe_jit
# hipe_timer
HRL_FILES=
@@ -96,8 +96,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/tools/hipe_ceach.erl b/lib/hipe/tools/hipe_ceach.erl
deleted file mode 100644
index b29615e169..0000000000
--- a/lib/hipe/tools/hipe_ceach.erl
+++ /dev/null
@@ -1,74 +0,0 @@
-%% -*- erlang-indent-level: 2 -*-
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved
-%% ====================================================================
-%% Module : hipe_ceach
-%% Purpose : Compile each function in a module, possibly applying a
-%% fun between each compilation. Useful for bug hunting by
-%% pinpointing a function that when compiled causes a bug.
-%% Notes :
-%% History : * 2001-12-11 Erik Johansson ([email protected]): Created.
-%% ====================================================================
-%% Exports :
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--module(hipe_ceach).
-
--export([c/1, c/2, c/3]).
-
--include("../main/hipe.hrl").
-
-%%---------------------------------------------------------------------
-
--spec c(atom()) -> 'ok'.
-
-c(M) ->
- lists:foreach(fun({F,A}) -> comp(M, F, A) end,
- M:module_info(functions)).
-
--spec c(atom(), comp_options()) -> 'ok'.
-
-c(M, Opts) ->
- lists:foreach(fun({F,A}) -> comp(M, F, A, Opts) end,
- M:module_info(functions)).
-
--spec c(atom(), comp_options(), fun(() -> any())) -> 'ok'.
-
-c(M, Opts, Fn) ->
- lists:foreach(fun({F,A}) -> comp(M, F, A, Opts), Fn() end,
- M:module_info(functions)).
-
--spec comp(atom(), atom(), arity()) -> 'ok'.
-
-comp(M, F, A) ->
- io:format("~w:~w/~w... ", [M, F, A]),
- MFA = {M, F, A},
- {ok, MFA} = hipe:c(MFA),
- io:format("OK\n").
-
--spec comp(atom(), atom(), arity(), comp_options()) -> 'ok'.
-
-comp(M, F, A, Opts) ->
- io:format("~w:~w/~w... ", [M, F, A]),
- MFA = {M, F, A},
- {ok, MFA} = hipe:c(MFA, Opts),
- io:format("OK\n").
diff --git a/lib/hipe/tools/hipe_profile.erl b/lib/hipe/tools/hipe_profile.erl
index 7566acb8f4..ea6b1fb42c 100644
--- a/lib/hipe/tools/hipe_profile.erl
+++ b/lib/hipe/tools/hipe_profile.erl
@@ -2,7 +2,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
@@ -89,7 +89,7 @@ calls() ->
%% F(),
%% %% Get result.
%% R = res(),
-%% %% Turn of profiling.
+%% %% Turn off profiling.
%% prof_off(),
%% R.
diff --git a/lib/hipe/tools/hipe_tool.erl b/lib/hipe/tools/hipe_tool.erl
index 990805ceca..efcf073efa 100644
--- a/lib/hipe/tools/hipe_tool.erl
+++ b/lib/hipe/tools/hipe_tool.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,18 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_tool).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/0]).
diff --git a/lib/hipe/util/Makefile b/lib/hipe/util/Makefile
index 85719ec3d6..a5ee232057 100644
--- a/lib/hipe/util/Makefile
+++ b/lib/hipe/util/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The 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,6 +85,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -100,10 +103,10 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/util
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/util
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/util"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/util"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl
index d6ef801c88..e4a47ae0c4 100755..100644
--- a/lib/hipe/util/hipe_dot.erl
+++ b/lib/hipe/util/hipe_dot.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
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 65e04ff7fa..e296997466 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.8.1
+HIPE_VSN = 3.9.1
diff --git a/lib/hipe/x86/Makefile b/lib/hipe/x86/Makefile
index d7d0c7bf5a..3602949944 100644
--- a/lib/hipe/x86/Makefile
+++ b/lib/hipe/x86/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2010. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -100,6 +100,9 @@ clean:
rm -f $(TARGET_FILES)
rm -f core
+distclean: clean
+realclean: clean
+
$(DOCS)/%.html:%.erl
erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
@@ -113,8 +116,8 @@ $(DOCS)/%.html:%.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/ic/c_src/Makefile.in b/lib/ic/c_src/Makefile.in
index 28040ca42d..d8b8c85a8e 100644
--- a/lib/ic/c_src/Makefile.in
+++ b/lib/ic/c_src/Makefile.in
@@ -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
@@ -140,12 +140,12 @@ $(OBJDIR)/%.o: %.c
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/c_src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_DATA) ic.c ic_tmo.c $(RELSYSDIR)/c_src
- $(INSTALL_DATA) $(IDL_FILES) $(H_FILES) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(LIBRARY) $(RELSYSDIR)/priv/lib
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_DATA) ic.c ic_tmo.c "$(RELSYSDIR)/c_src"
+ $(INSTALL_DATA) $(IDL_FILES) $(H_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(LIBRARY) "$(RELSYSDIR)/priv/lib"
release_docs_spec:
diff --git a/lib/ic/doc/src/Makefile b/lib/ic/doc/src/Makefile
index acb6848fee..0ee242b234 100644
--- a/lib/ic/doc/src/Makefile
+++ b/lib/ic/doc/src/Makefile
@@ -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,13 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(IC_VSN)
APPLICATION=ic
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
# ----------------------------------------------------
# Java specific
@@ -96,32 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
JAVA_SOURCE_FILES = \
Holder.java \
BooleanHolder.java \
@@ -206,13 +177,9 @@ JAVADOCFLAGS = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-_create_dirs := $(shell mkdir -p $(JAVA_OUT_DIR))
-
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
ifneq (,$(JAVA))
docs: pdf html man $(JAVADOC_GENERATED_FILES)
else
@@ -231,35 +198,11 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html $(JAVADOC_GENERATED_FILES) gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
+$(JAVADOC_GENERATED_FILES): JAVADOC-GENERATED
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
- rm -rf $(JAVA_OUT_DIR)
-
-endif
-
-$(JAVADOC_GENERATED_FILES):
+JAVADOC-GENERATED: $(JAVA_SOURCE_FILES:%=$(JAVA_SOURCE_DIR)/%)
@(cd ../../java_src; $(JAVADOC) $(JAVADOCFLAGS) com.ericsson.otp.ic)
+ >JAVADOC-GENERATED
man: $(MAN3_FILES)
@@ -276,57 +219,13 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- (/bin/cp -rf $(HTMLDIR) $(RELSYSDIR)/doc)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
-ifneq (,$(JAVA))
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/resources
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com/ericsson
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com/ericsson/otp
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/com/ericsson/otp/ic
- $(INSTALL_DATA) $(JAVADOC_INDEX_HTML_FILES) \
- $(RELSYSDIR)/doc/html/java
- $(INSTALL_DATA) $(JD_GIF_FILES) \
- $(RELSYSDIR)/doc/html/java/resources
- $(INSTALL_DATA) $(JAVADOC_PACK_HTML_FILES) \
- $(RELSYSDIR)/doc/html/java/com/ericsson/otp/ic
-endif
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
-
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ (/bin/cp -rf $(HTMLDIR) "$(RELSYSDIR)/doc")
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
release_spec:
-
-
diff --git a/lib/ic/doc/src/ic_clib.xml b/lib/ic/doc/src/ic_clib.xml
index b557c4b5f6..ebeaabae91 100644
--- a/lib/ic/doc/src/ic_clib.xml
+++ b/lib/ic/doc/src/ic_clib.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -41,7 +41,7 @@
</section>
<funcs>
<func>
- <name><ret>CORBA_Environment*</ret><nametext>CORBA_Environment_alloc(int inbufsz, int outbufsz)</nametext></name>
+ <name><ret>CORBA_Environment *</ret><nametext>CORBA_Environment_alloc(int inbufsz, int outbufsz)</nametext></name>
<fsummary>Allocate environment data.</fsummary>
<desc>
<p>This function is used to allocate and initiate the
@@ -79,14 +79,14 @@
</desc>
</func>
<func>
- <name><ret>CORBA_char*</ret><nametext>CORBA_string_alloc(CORBA_unsigned_long len)</nametext></name>
+ <name><ret>CORBA_char *</ret><nametext>CORBA_string_alloc(CORBA_unsigned_long len)</nametext></name>
<fsummary>Allocate a string.</fsummary>
<desc>
<p>Allocates a (simple) CORBA character string of length <c>len + 1</c>.</p>
</desc>
</func>
<func>
- <name><ret>CORBA_wchar*</ret><nametext>CORBA_wstring_alloc(CORBA_unsigned_long len)</nametext></name>
+ <name><ret>CORBA_wchar *</ret><nametext>CORBA_wstring_alloc(CORBA_unsigned_long len)</nametext></name>
<fsummary>Allocate a wide string.</fsummary>
<desc>
<p>Allocates a CORBA wide string of length <c>len + 1</c>.</p>
@@ -101,7 +101,7 @@
</section>
<funcs>
<func>
- <name><ret>CORBA_char*</ret><nametext>CORBA_exception_id(CORBA_Environment *env)</nametext></name>
+ <name><ret>CORBA_char *</ret><nametext>CORBA_exception_id(CORBA_Environment *env)</nametext></name>
<fsummary>Get exception identity.</fsummary>
<desc>
<p>Returns the exception identity if an exception is set, otherwise
@@ -109,7 +109,7 @@
</desc>
</func>
<func>
- <name><ret>void*</ret><nametext>CORBA_exception_value(CORBA_Environment *env)</nametext></name>
+ <name><ret>void *</ret><nametext>CORBA_exception_value(CORBA_Environment *env)</nametext></name>
<fsummary>Get exception value.</fsummary>
<desc>
<p>Returns the exception value, if an exception is set, otherwise
@@ -160,7 +160,7 @@
</desc>
</func>
<func>
- <name><ret>oe_map_t*</ret><nametext>oe_merge_maps(oe_map_t *maps, int size)</nametext></name>
+ <name><ret>oe_map_t *</ret><nametext>oe_merge_maps(oe_map_t *maps, int size)</nametext></name>
<fsummary>Merge an array of server maps to one single map.</fsummary>
<desc>
<p>Merge an array of server maps to one single map.</p>
diff --git a/lib/ic/doc/src/make.dep b/lib/ic/doc/src/make.dep
deleted file mode 100644
index 64694ee85a..0000000000
--- a/lib/ic/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex c-part.tex ch_basic_idl.tex ch_c_client.tex \
- ch_c_corba_env.tex ch_c_mapping.tex ch_c_server.tex \
- ch_erl_genserv.tex ch_erl_plain.tex ch_ic_protocol.tex \
- ch_introduction.tex ch_java.tex erl-part.tex \
- ic.tex ic_c_protocol.tex ic_clib.tex java-part.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml
index de519d5f84..eac932fc06 100644
--- a/lib/ic/doc/src/notes.xml
+++ b/lib/ic/doc/src/notes.xml
@@ -30,6 +30,56 @@
<file>notes.xml</file>
</header>
+ <section><title>IC 4.2.30</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add generation of Erlang callback functions to generated
+ Erlang source code to avoid compiler warnings.</p>
+ <p>
+ Own Id: OTP-9998</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>IC 4.2.29</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
+ <title>IC 4.2.28</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Incorrect use of ets:match changed to ets:match_object.</p>
+ <p>
+ Own Id: OTP-9630 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
<section>
<title>IC 4.2.27</title>
diff --git a/lib/ic/examples/pre_post_condition/Makefile b/lib/ic/examples/pre_post_condition/Makefile
index 85cbbdb9ff..8ae37394ed 100644
--- a/lib/ic/examples/pre_post_condition/Makefile
+++ b/lib/ic/examples/pre_post_condition/Makefile
@@ -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
@@ -100,7 +100,7 @@ YRL_FLAGS =
debug opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES)
+ rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) IDL-GENERATED
rm -f errs core *~
docs:
@@ -124,8 +124,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/pre_post_condition
- $(INSTALL_DATA) $(ERL_FILES) $(IDL_FILES) $(TXT_FILES) $(RELSYSDIR)/examples/pre_post_condition
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/pre_post_condition"
+ $(INSTALL_DATA) $(ERL_FILES) $(IDL_FILES) $(TXT_FILES) "$(RELSYSDIR)/examples/pre_post_condition"
release_docs_spec:
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Makefile b/lib/ic/java_src/com/ericsson/otp/ic/Makefile
index f730749ccb..1b14d4430f 100644
--- a/lib/ic/java_src/com/ericsson/otp/ic/Makefile
+++ b/lib/ic/java_src/com/ericsson/otp/ic/Makefile
@@ -109,10 +109,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/java_src/com/ericsson/otp/ic
- $(INSTALL_DATA) $(JAVA_FILES) $(RELSYSDIR)/java_src/com/ericsson/otp/ic
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/java_src/com/ericsson/otp/ic"
+ $(INSTALL_DATA) $(JAVA_FILES) "$(RELSYSDIR)/java_src/com/ericsson/otp/ic"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/ic/src/Makefile b/lib/ic/src/Makefile
index 5dac304e32..c830ebec95 100644
--- a/lib/ic/src/Makefile
+++ b/lib/ic/src/Makefile
@@ -196,23 +196,23 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DIR) $(RELSYSDIR)/examples/c-client
- $(INSTALL_DATA) $(CCL_EX_FILES) $(RELSYSDIR)/examples/c-client
- $(INSTALL_DIR) $(RELSYSDIR)/examples/c-server
- $(INSTALL_DATA) $(CSRV_EX_FILES) $(RELSYSDIR)/examples/c-server
- $(INSTALL_DIR) $(RELSYSDIR)/examples/erl-plain
- $(INSTALL_DATA) $(EPL_EX_FILES) $(RELSYSDIR)/examples/erl-plain
- $(INSTALL_DIR) $(RELSYSDIR)/examples/erl-genserv
- $(INSTALL_DATA) $(ESRV_EX_FILES) $(RELSYSDIR)/examples/erl-genserv
- $(INSTALL_DIR) $(RELSYSDIR)/examples/java-client-server
- $(INSTALL_DATA) $(JAVA_EX_FILES) $(RELSYSDIR)/examples/java-client-server
- $(INSTALL_DIR) $(RELSYSDIR)/examples/all-against-all
- $(INSTALL_DATA) $(MIXED_EX_FILES) $(RELSYSDIR)/examples/all-against-all
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/c-client"
+ $(INSTALL_DATA) $(CCL_EX_FILES) "$(RELSYSDIR)/examples/c-client"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/c-server"
+ $(INSTALL_DATA) $(CSRV_EX_FILES) "$(RELSYSDIR)/examples/c-server"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/erl-plain"
+ $(INSTALL_DATA) $(EPL_EX_FILES) "$(RELSYSDIR)/examples/erl-plain"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/erl-genserv"
+ $(INSTALL_DATA) $(ESRV_EX_FILES) "$(RELSYSDIR)/examples/erl-genserv"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/java-client-server"
+ $(INSTALL_DATA) $(JAVA_EX_FILES) "$(RELSYSDIR)/examples/java-client-server"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/all-against-all"
+ $(INSTALL_DATA) $(MIXED_EX_FILES) "$(RELSYSDIR)/examples/all-against-all"
release_docs_spec:
diff --git a/lib/ic/src/ic.erl b/lib/ic/src/ic.erl
index 50fad921c4..bc7ec8ba91 100644
--- a/lib/ic/src/ic.erl
+++ b/lib/ic/src/ic.erl
@@ -250,7 +250,7 @@ make_erl_options(Opts) ->
Optimize = Opts#options.optimize,
PreProc =
lists:flatten(
- lists:map(fun(D) -> io_lib:format("-I~s ", [ic_util:to_list(D)]) end,
+ lists:map(fun(D) -> io_lib:format("-I\"~s\" ", [ic_util:to_list(D)]) end,
Includes1)++
lists:map(
fun ({Name, Value}) ->
diff --git a/lib/ic/src/ic_noc.erl b/lib/ic/src/ic_noc.erl
index d43d550a52..fcb413ba2e 100644
--- a/lib/ic/src/ic_noc.erl
+++ b/lib/ic/src/ic_noc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -289,6 +289,9 @@ emit_serv_std(G, N, X) ->
emit(Fd, "terminate(Reason, State) ->\n"),
emit(Fd, " ~p:~p(Reason, State).\n",
[Impl, terminate]),
+ nl(Fd),
+ emit(Fd, "code_change(_OldVsn, State, _Extra) ->\n"),
+ emit(Fd, " {ok, State}.\n"),
nl(Fd), nl(Fd)
end,
Fd.
@@ -304,13 +307,13 @@ gen_end_of_call(G, _N, _X) ->
Fd = ic_genobj:stubfiled(G),
nl(Fd), nl(Fd),
ic_codegen:mcomment_light(Fd, ["Standard gen_server call handle"]),
- emit(Fd, "handle_call(stop, From, State) ->\n"),
+ emit(Fd, "handle_call(stop, _From, State) ->\n"),
emit(Fd, " {stop, normal, ok, State}"),
case get_opt(G, serv_last_call) of
exception ->
emit(Fd, ";\n"),
nl(Fd),
- emit(Fd, "handle_call(Req, From, State) ->\n"),
+ emit(Fd, "handle_call(_Req, _From, State) ->\n"),
emit(Fd, " {reply, ~p, State}.\n",[getCallErr()]);
exit ->
emit(Fd, ".\n"),
@@ -335,7 +338,7 @@ gen_end_of_cast(G, _N, _X) ->
exception ->
emit(Fd, ";\n"),
nl(Fd),
- emit(Fd, "handle_cast(Req, State) ->\n"),
+ emit(Fd, "handle_cast(_Req, State) ->\n"),
emit(Fd, " {reply, ~p, State}.\n",[getCastErr()]);
exit ->
emit(Fd, ".\n"),
@@ -353,12 +356,13 @@ emit_skel_footer(G, N, X) ->
Fd = ic_genobj:stubfiled(G),
nl(Fd), nl(Fd),
ic_codegen:mcomment_light(Fd, ["Standard gen_server handles"]),
- emit(Fd, "handle_info(X, State) ->\n"),
case use_impl_handle_info(G, N, X) of
true ->
+ emit(Fd, "handle_info(X, State) ->\n"),
emit(Fd, " ~p:handle_info(X, State).\n\n",
[list_to_atom(ic_genobj:impl(G))]);
false ->
+ emit(Fd, "handle_info(_X, State) ->\n"),
emit(Fd, " {reply, ~p, State}.\n\n",[getInfoErr()])
end
end,
@@ -402,9 +406,8 @@ get_if_gen(G, N, X) ->
[io_lib:format("Standard Operation: ~p",
[Name])]),
- emit(Fd, "handle_call({~s, ~p, []}, From, State) ->~n",
+ emit(Fd, "handle_call({_~s, ~p, []}, _From, State) ->~n",
[mk_name(G, "Ref"), Name]),
-
emit(Fd, " {reply, ~p, State};~n", [IFC_TKS]),
nl(Fd),
ok;
@@ -479,8 +482,8 @@ gen_head_special(G, N, X) when is_record(X, interface) ->
nl(Fd),
ic_codegen:comment(Fd, "gen server export stuff"),
emit(Fd, "-behaviour(gen_server).\n"),
- ic_codegen:export(Fd, [{init, 1}, {terminate, 2}, {handle_call, 3},
- {handle_cast, 2}, {handle_info, 2}]),
+ ic_codegen:export(Fd, [{init, 1}, {terminate, 2}, {code_change, 3},
+ {handle_call, 3}, {handle_cast, 2}, {handle_info, 2}]),
nl(Fd), nl(Fd),
ic_codegen:mcomment(Fd, ["Object interface functions."]),
nl(Fd), nl(Fd), nl(Fd)
diff --git a/lib/ic/src/ic_pp.erl b/lib/ic/src/ic_pp.erl
index 8b53473caa..50eeeab48c 100644
--- a/lib/ic/src/ic_pp.erl
+++ b/lib/ic/src/ic_pp.erl
@@ -1894,23 +1894,37 @@ include_dir(Flags) when is_list(Flags)->
include_dir(_Flags) ->
[].
-include_dir(Flags,IncDir) ->
+include_dir(Flags,IncDirs) ->
case string:str(Flags,"-I") of
0 ->
- lists:reverse(IncDir);
+ lists:reverse(IncDirs);
X ->
- Rem2 = string:sub_string(Flags, X+2),
- Rem = string:strip(Rem2, left),
- Y = string:str(Rem," "),
- case string:str(Rem," ") of
- 0 ->
- lists:reverse([string:sub_string(Rem, Y+1)|IncDir]);
- Y ->
- include_dir(string:sub_string(Rem, Y+1),
- [string:sub_string(Rem,1,Y-1)|IncDir])
- end
+ {NewDir, RemainingFlags} =
+ gobble_inc_dir(string:sub_string(Flags, X+2),nq,[]),
+ include_dir(RemainingFlags, [NewDir|IncDirs])
end.
+% nq = not-quoted, q = quoted.
+% Possible strange scenarios:
+% /usr/test\ ing/
+% "/usr/test ing/"
+% /usr/test\"ing/
+% "/usr/test\"ing/"
+gobble_inc_dir([],nq,Acc) ->
+ % Only accept nq here, if we end up here in q mode the user has missed a "
+ {lists:reverse(Acc),[]};
+gobble_inc_dir([$\\,$"|R],Q,Acc) ->
+ gobble_inc_dir(R,Q,[$"|Acc]);
+gobble_inc_dir([$"|R],nq,Acc) ->
+ gobble_inc_dir(R,q,Acc);
+gobble_inc_dir([$"|R],q,Acc) ->
+ gobble_inc_dir(R,nq,Acc);
+gobble_inc_dir([$\\,$ |R],nq,Acc) ->
+ gobble_inc_dir(R,nq,[$ |Acc]);
+gobble_inc_dir([$ |R],nq,Acc) ->
+ {lists:reverse(Acc),R};
+gobble_inc_dir([C|R],Q,Acc) ->
+ gobble_inc_dir(R,Q,[C|Acc]).
%%===============================================================
@@ -1954,7 +1968,6 @@ find_inc_file2(FileName, [D|Rem]) ->
_ ->
D++"/"
end,
-
case catch file:read_file_info(Dir++FileName) of
{ok, _} ->
{ok, Dir++FileName};
diff --git a/lib/ic/src/ic_pragma.erl b/lib/ic/src/ic_pragma.erl
index 7f2216b9dc..beaa2852ab 100644
--- a/lib/ic/src/ic_pragma.erl
+++ b/lib/ic/src/ic_pragma.erl
@@ -1601,7 +1601,7 @@ remove_inheriters(S,RS,InheriterList) ->
ReducedInhList;
_Other ->
CleanList =
- ets:match(S, {inherits,'_','_'}),
+ ets:match_object(S, {inherits,'_','_'}),
% CodeOptList =
% [X || X <- EtsList, element(1,X) == codeopt],
NoInheriters =remove_inheriters2(S,ReducedInhList,CleanList),
@@ -1648,7 +1648,7 @@ remove_inh([X],[Y],List,EtsList) ->
%%%----------------------------------------------
remove_inherited(S,InheriterList) ->
CleanList =
- ets:match(S, {inherits, '_', '_'}),
+ ets:match_object(S, {inherits, '_', '_'}),
remove_inherited(S,InheriterList,CleanList).
@@ -1766,7 +1766,7 @@ inherits2(_X,Y,Z,EtsList) ->
%% false otherwise
%%
is_inherited_by(Interface1,Interface2,PragmaTab) ->
- InheritsList = ets:match(PragmaTab, {inherits, '_', '_'}),
+ InheritsList = ets:match_object(PragmaTab, {inherits, '_', '_'}),
inherits(Interface2,Interface1,InheritsList).
diff --git a/lib/ic/test/Makefile b/lib/ic/test/Makefile
index 1d90a1bc17..65003d703b 100644
--- a/lib/ic/test/Makefile
+++ b/lib/ic/test/Makefile
@@ -239,39 +239,39 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/ic_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/ic_register_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/ic_pragma_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/ic_pp_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/ic_be_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_proto_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/erl_client_c_server_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/erl_client_c_server_proto_SUITE_data
- $(INSTALL_DIR) $(RELSYSDIR)/java_client_erl_server_SUITE_data
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ic_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ic_register_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ic_pragma_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ic_pp_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ic_be_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_client_erl_server_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_client_erl_server_proto_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/erl_client_c_server_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/erl_client_c_server_proto_SUITE_data"
+ $(INSTALL_DIR) "$(RELSYSDIR)/java_client_erl_server_SUITE_data"
$(INSTALL_DATA) $(IDL_FILES) ic.cover $(TEST_SPEC_FILE) $(ERL_FILES) \
- $(RELSYSDIR)
- $(INSTALL_DATA) $(COMPILER_TEST_FILES) $(RELSYSDIR)/ic_SUITE_data
+ "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(COMPILER_TEST_FILES) "$(RELSYSDIR)/ic_SUITE_data"
$(INSTALL_DATA) $(COMPILER_TEST_FILES2) \
- $(RELSYSDIR)/ic_register_SUITE_data
+ "$(RELSYSDIR)/ic_register_SUITE_data"
$(INSTALL_DATA) $(COMPILER_TEST_FILES3) \
- $(RELSYSDIR)/ic_pragma_SUITE_data
+ "$(RELSYSDIR)/ic_pragma_SUITE_data"
$(INSTALL_DATA) $(COMPILER_TEST_FILES4) \
- $(RELSYSDIR)/ic_be_SUITE_data
+ "$(RELSYSDIR)/ic_be_SUITE_data"
$(INSTALL_DATA) $(PREPROCESSOR_TEST_FILES) \
- $(RELSYSDIR)/ic_pp_SUITE_data
+ "$(RELSYSDIR)/ic_pp_SUITE_data"
$(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_TEST_FILES) \
- $(RELSYSDIR)/c_client_erl_server_SUITE_data
+ "$(RELSYSDIR)/c_client_erl_server_SUITE_data"
$(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TEST_FILES) \
- $(RELSYSDIR)/c_client_erl_server_proto_SUITE_data
+ "$(RELSYSDIR)/c_client_erl_server_proto_SUITE_data"
$(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES) \
- $(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data
+ "$(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data"
$(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_TEST_FILES) \
- $(RELSYSDIR)/erl_client_c_server_SUITE_data
+ "$(RELSYSDIR)/erl_client_c_server_SUITE_data"
$(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_PROTO_TEST_FILES) \
- $(RELSYSDIR)/erl_client_c_server_proto_SUITE_data
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
+ "$(RELSYSDIR)/erl_client_c_server_proto_SUITE_data"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) $(JAVA_CLIENT_ERL_SERVER_TEST_FILES) \
- $(RELSYSDIR)/java_client_erl_server_SUITE_data
+ "$(RELSYSDIR)/java_client_erl_server_SUITE_data"
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
index d5277eb256..f3e6fdb67e 100644
--- a/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
+++ b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2011. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -122,24 +122,33 @@ EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
all: $(PGMS) $(EBINS)
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
+$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
+$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
clean:
-rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
-del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
$(PGMS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl
+c_erl_test.built_c: c_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" c_erl_test.idl
+ echo done > c_erl_test.built_c
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl
+c_erl_test.built_erl: c_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
+ echo done > c_erl_test.built_erl
-.c@obj@:
+.c@obj@:
$(CC) -c -o $*@obj@ $(CFLAGS) $<
-.erl.@EMULATOR@:
+.erl.@EMULATOR@:
$(ERLC) -I $(IC_INCLUDE_PATH) $<
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
index 8bc1a907a7..0818be01a6 100644
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
+++ b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2011. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -122,25 +122,34 @@ EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
all: $(PGMS) $(EBINS)
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
+$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
+$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
clean:
-rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
-del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
$(PGMS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl
+c_erl_test.built_c: c_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \
"+{user_protocol,my}" c_erl_test.idl
+ echo done > c_erl_test.built_c
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl
+c_erl_test.built_erl: c_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
+ echo done > c_erl_test.built_erl
-.c@obj@:
+.c@obj@:
$(CC) -c -o $*@obj@ $(CFLAGS) $<
-.erl.@EMULATOR@:
+.erl.@EMULATOR@:
$(ERLC) -I $(IC_INCLUDE_PATH) $<
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
index 2585341791..07b353bc0a 100644
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
+++ b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -122,25 +122,33 @@ EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
all: $(PGMS) $(EBINS)
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
+$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
+$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
clean:
-rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
-del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
$(PGMS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \
- "+{user_protocol,my}" "+{c_timeout,{5000,5000}}" c_erl_test.idl
+c_erl_test.built_c: c_erl_test.idl
+ $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" c_erl_test.idl
+ echo done > c_erl_test.built_c
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.idl
+c_erl_test.built_erl: c_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
+ echo done > c_erl_test.built_erl
-.c@obj@:
+.c@obj@:
$(CC) -c -o $*@obj@ $(CFLAGS) $<
-.erl.@EMULATOR@:
+.erl.@EMULATOR@:
$(ERLC) -I $(IC_INCLUDE_PATH) $<
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
index 50cf9d4445..e190295d70 100644
--- a/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
+++ b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2011. All Rights Reserved.
+# Copyright Ericsson AB 2002-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -122,25 +122,34 @@ EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
all: $(PGMS) $(EBINS)
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
+$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
+$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
clean:
-rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
-del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
$(PGMS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(GEN_C_FILES) $(GEN_H_FILES): erl_c_test.idl
+c_erl_test.built_c: erl_c_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \
"+{scoped_op_calls,true}" erl_c_test.idl
+ echo done > c_erl_test.built_c
# If we have scoped operation calls for C, we must have that for
# Erlang as well, if we use the m_i.erl file for calling the server.
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): erl_c_test.idl
+c_erl_test.built_erl: erl_c_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \
"+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl
+ echo done > c_erl_test.built_erl
.c@obj@:
$(CC) -c -o $*@obj@ $(CFLAGS) $<
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
index 6c7701ca50..86917950c9 100644
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
+++ b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -122,25 +122,34 @@ EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
all: $(PGMS) $(EBINS)
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
+$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
+$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
+$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
clean:
-rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
-del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+ $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
+ c_erl_test.built_erl c_erl_test.built_c
$(PGMS): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(GEN_C_FILES) $(GEN_H_FILES): erl_c_test.idl
+c_erl_test.built_c: erl_c_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \
"+{scoped_op_calls,true}" erl_c_test.idl
+ echo done > c_erl_test.built_c
# If we have scoped operation calls for C, we must have that for
# Erlang as well, if we use the m_i.erl file for calling the server.
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): erl_c_test.idl
+c_erl_test.built_erl: erl_c_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \
"+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl
+ echo done > c_erl_test.built_erl
.c@obj@:
$(CC) -c -o $*@obj@ $(CFLAGS) $<
diff --git a/lib/ic/test/java_client_erl_server_SUITE.erl b/lib/ic/test/java_client_erl_server_SUITE.erl
index 407c3d2d44..d4523dc2ad 100644
--- a/lib/ic/test/java_client_erl_server_SUITE.erl
+++ b/lib/ic/test/java_client_erl_server_SUITE.erl
@@ -249,7 +249,7 @@ marshal_any_2(Config) when is_list(Config) ->
java(Java, Dir, ClassAndArgs) ->
- cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs).
+ cmd(Java++" -classpath \""++classpath(Dir)++"\" "++ClassAndArgs).
java(Java, Dir, Class, Args) ->
java(Java, Dir, Class++" "++to_string(Args)).
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
index 5e190fe1a5..c106261efd 100644
--- a/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
+++ b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2011. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The 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,20 +69,29 @@ EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
all: $(CLASS_FILES) $(EBINS)
+$(GEN_ERL_FILES) $(GEN_HRL_FILES): java_erl_test.built_erl
+$(GEN_JAVA_FILES): java_erl_test.built_java
+$(CLASS_FILES): $(GEN_JAVA_FILES)
+$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
+
clean:
-rm -f $(GEN_JAVA_FILES) $(CLASS_FILES) \
- $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS)
+ $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS) \
+ java_erl_test.built_erl java_erl_test.built_java
-del /F /Q $(GEN_JAVA_FILES) $(CLASS_FILES) \
- $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS)
+ $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS) \
+ java_erl_test.built_erl java_erl_test.built_java
-$(GEN_JAVA_FILES) : java_erl_test.idl
+java_erl_test.built_java: java_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,java}" java_erl_test.idl
+ echo done > java_erl_test.built_java
$(CLASS_FILES) : $(JAVA_FILES)
$(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): java_erl_test.idl
+java_erl_test.built_erl: java_erl_test.idl
$(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" java_erl_test.idl
+ echo done > java_erl_test.built_erl
.erl.@EMULATOR@:
$(ERLC) -I $(IC_INCLUDE_PATH) $<
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
index 6561ccd2a7..fc1475974e 100644
--- a/lib/ic/vsn.mk
+++ b/lib/ic/vsn.mk
@@ -1 +1 @@
-IC_VSN = 4.2.27
+IC_VSN = 4.2.30
diff --git a/lib/inets/Makefile b/lib/inets/Makefile
index 4765a2ca3c..d837a3396a 100644
--- a/lib/inets/Makefile
+++ b/lib/inets/Makefile
@@ -31,12 +31,16 @@ VSN = $(INETS_VSN)
SPECIAL_TARGETS =
+DIA_PLT = ./priv/plt/$(APPLICATION).plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+
+
# ----------------------------------------------------
# Default Subdir Targets
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_subdir.mk
-.PHONY: info gclean
+.PHONY: info gclean dialyzer dialyzer_plt dclean
info:
@echo "OS: $(OS)"
@@ -45,6 +49,29 @@ info:
@echo "INETS_VSN: $(INETS_VSN)"
@echo "APP_VSN: $(APP_VSN)"
@echo ""
+ @echo "DIA_PLT: $(DIA_PLT)"
+ @echo "DIA_ANALYSIS: $(DIA_ANALYSIS)"
+ @echo ""
gclean:
git clean -fXd
+
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT):
+ @echo "Building $(APPLICATION) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ -r ../$(APPLICATION)/ebin \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on $(APPLICATION)"
+ @dialyzer --plt $< \
+ ../$(APPLICATION)/ebin \
+ --verbose
diff --git a/lib/inets/doc/archive/rfc3986.txt b/lib/inets/doc/archive/rfc3986.txt
new file mode 100644
index 0000000000..c56ed4eb70
--- /dev/null
+++ b/lib/inets/doc/archive/rfc3986.txt
@@ -0,0 +1,3419 @@
+
+
+
+
+
+
+Network Working Group T. Berners-Lee
+Request for Comments: 3986 W3C/MIT
+STD: 66 R. Fielding
+Updates: 1738 Day Software
+Obsoletes: 2732, 2396, 1808 L. Masinter
+Category: Standards Track Adobe Systems
+ January 2005
+
+
+ Uniform Resource Identifier (URI): Generic Syntax
+
+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
+
+ A Uniform Resource Identifier (URI) is a compact sequence of
+ characters that identifies an abstract or physical resource. This
+ specification defines the generic URI syntax and a process for
+ resolving URI references that might be in relative form, along with
+ guidelines and security considerations for the use of URIs on the
+ Internet. The URI syntax defines a grammar that is a superset of all
+ valid URIs, allowing an implementation to parse the common components
+ of a URI reference without knowing the scheme-specific requirements
+ of every possible identifier. This specification does not define a
+ generative grammar for URIs; that task is performed by the individual
+ specifications of each URI scheme.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 1]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. Overview of URIs . . . . . . . . . . . . . . . . . . . . 4
+ 1.1.1. Generic Syntax . . . . . . . . . . . . . . . . . 6
+ 1.1.2. Examples . . . . . . . . . . . . . . . . . . . . 7
+ 1.1.3. URI, URL, and URN . . . . . . . . . . . . . . . 7
+ 1.2. Design Considerations . . . . . . . . . . . . . . . . . 8
+ 1.2.1. Transcription . . . . . . . . . . . . . . . . . 8
+ 1.2.2. Separating Identification from Interaction . . . 9
+ 1.2.3. Hierarchical Identifiers . . . . . . . . . . . . 10
+ 1.3. Syntax Notation . . . . . . . . . . . . . . . . . . . . 11
+ 2. Characters . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 2.1. Percent-Encoding . . . . . . . . . . . . . . . . . . . . 12
+ 2.2. Reserved Characters . . . . . . . . . . . . . . . . . . 12
+ 2.3. Unreserved Characters . . . . . . . . . . . . . . . . . 13
+ 2.4. When to Encode or Decode . . . . . . . . . . . . . . . . 14
+ 2.5. Identifying Data . . . . . . . . . . . . . . . . . . . . 14
+ 3. Syntax Components . . . . . . . . . . . . . . . . . . . . . . 16
+ 3.1. Scheme . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 3.2. Authority . . . . . . . . . . . . . . . . . . . . . . . 17
+ 3.2.1. User Information . . . . . . . . . . . . . . . . 18
+ 3.2.2. Host . . . . . . . . . . . . . . . . . . . . . . 18
+ 3.2.3. Port . . . . . . . . . . . . . . . . . . . . . . 22
+ 3.3. Path . . . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 3.4. Query . . . . . . . . . . . . . . . . . . . . . . . . . 23
+ 3.5. Fragment . . . . . . . . . . . . . . . . . . . . . . . . 24
+ 4. Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
+ 4.1. URI Reference . . . . . . . . . . . . . . . . . . . . . 25
+ 4.2. Relative Reference . . . . . . . . . . . . . . . . . . . 26
+ 4.3. Absolute URI . . . . . . . . . . . . . . . . . . . . . . 27
+ 4.4. Same-Document Reference . . . . . . . . . . . . . . . . 27
+ 4.5. Suffix Reference . . . . . . . . . . . . . . . . . . . . 27
+ 5. Reference Resolution . . . . . . . . . . . . . . . . . . . . . 28
+ 5.1. Establishing a Base URI . . . . . . . . . . . . . . . . 28
+ 5.1.1. Base URI Embedded in Content . . . . . . . . . . 29
+ 5.1.2. Base URI from the Encapsulating Entity . . . . . 29
+ 5.1.3. Base URI from the Retrieval URI . . . . . . . . 30
+ 5.1.4. Default Base URI . . . . . . . . . . . . . . . . 30
+ 5.2. Relative Resolution . . . . . . . . . . . . . . . . . . 30
+ 5.2.1. Pre-parse the Base URI . . . . . . . . . . . . . 31
+ 5.2.2. Transform References . . . . . . . . . . . . . . 31
+ 5.2.3. Merge Paths . . . . . . . . . . . . . . . . . . 32
+ 5.2.4. Remove Dot Segments . . . . . . . . . . . . . . 33
+ 5.3. Component Recomposition . . . . . . . . . . . . . . . . 35
+ 5.4. Reference Resolution Examples . . . . . . . . . . . . . 35
+ 5.4.1. Normal Examples . . . . . . . . . . . . . . . . 36
+ 5.4.2. Abnormal Examples . . . . . . . . . . . . . . . 36
+
+
+
+Berners-Lee, et al. Standards Track [Page 2]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ 6. Normalization and Comparison . . . . . . . . . . . . . . . . . 38
+ 6.1. Equivalence . . . . . . . . . . . . . . . . . . . . . . 38
+ 6.2. Comparison Ladder . . . . . . . . . . . . . . . . . . . 39
+ 6.2.1. Simple String Comparison . . . . . . . . . . . . 39
+ 6.2.2. Syntax-Based Normalization . . . . . . . . . . . 40
+ 6.2.3. Scheme-Based Normalization . . . . . . . . . . . 41
+ 6.2.4. Protocol-Based Normalization . . . . . . . . . . 42
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 43
+ 7.1. Reliability and Consistency . . . . . . . . . . . . . . 43
+ 7.2. Malicious Construction . . . . . . . . . . . . . . . . . 43
+ 7.3. Back-End Transcoding . . . . . . . . . . . . . . . . . . 44
+ 7.4. Rare IP Address Formats . . . . . . . . . . . . . . . . 45
+ 7.5. Sensitive Information . . . . . . . . . . . . . . . . . 45
+ 7.6. Semantic Attacks . . . . . . . . . . . . . . . . . . . . 45
+ 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 46
+ 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 46
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 46
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 46
+ 10.2. Informative References . . . . . . . . . . . . . . . . . 47
+ A. Collected ABNF for URI . . . . . . . . . . . . . . . . . . . . 49
+ B. Parsing a URI Reference with a Regular Expression . . . . . . 50
+ C. Delimiting a URI in Context . . . . . . . . . . . . . . . . . 51
+ D. Changes from RFC 2396 . . . . . . . . . . . . . . . . . . . . 53
+ D.1. Additions . . . . . . . . . . . . . . . . . . . . . . . 53
+ D.2. Modifications . . . . . . . . . . . . . . . . . . . . . 53
+ Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 60
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 61
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 3]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1. Introduction
+
+ A Uniform Resource Identifier (URI) provides a simple and extensible
+ means for identifying a resource. This specification of URI syntax
+ and semantics is derived from concepts introduced by the World Wide
+ Web global information initiative, whose use of these identifiers
+ dates from 1990 and is described in "Universal Resource Identifiers
+ in WWW" [RFC1630]. The syntax is designed to meet the
+ recommendations laid out in "Functional Recommendations for Internet
+ Resource Locators" [RFC1736] and "Functional Requirements for Uniform
+ Resource Names" [RFC1737].
+
+ This document obsoletes [RFC2396], which merged "Uniform Resource
+ Locators" [RFC1738] and "Relative Uniform Resource Locators"
+ [RFC1808] in order to define a single, generic syntax for all URIs.
+ It obsoletes [RFC2732], which introduced syntax for an IPv6 address.
+ It excludes portions of RFC 1738 that defined the specific syntax of
+ individual URI schemes; those portions will be updated as separate
+ documents. The process for registration of new URI schemes is
+ defined separately by [BCP35]. Advice for designers of new URI
+ schemes can be found in [RFC2718]. All significant changes from RFC
+ 2396 are noted in Appendix D.
+
+ This specification uses the terms "character" and "coded character
+ set" in accordance with the definitions provided in [BCP19], and
+ "character encoding" in place of what [BCP19] refers to as a
+ "charset".
+
+1.1. Overview of URIs
+
+ URIs are characterized as follows:
+
+ Uniform
+
+ Uniformity provides several benefits. It allows different types
+ of resource identifiers to be used in the same context, even when
+ the mechanisms used to access those resources may differ. It
+ allows uniform semantic interpretation of common syntactic
+ conventions across different types of resource identifiers. It
+ allows introduction of new types of resource identifiers without
+ interfering with the way that existing identifiers are used. It
+ allows the identifiers to be reused in many different contexts,
+ thus permitting new applications or protocols to leverage a pre-
+ existing, large, and widely used set of resource identifiers.
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 4]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Resource
+
+ This specification does not limit the scope of what might be a
+ resource; rather, the term "resource" is used in a general sense
+ for whatever might be identified by a URI. Familiar examples
+ include an electronic document, an image, a source of information
+ with a consistent purpose (e.g., "today's weather report for Los
+ Angeles"), a service (e.g., an HTTP-to-SMS gateway), and a
+ collection of other resources. A resource is not necessarily
+ accessible via the Internet; e.g., human beings, corporations, and
+ bound books in a library can also be resources. Likewise,
+ abstract concepts can be resources, such as the operators and
+ operands of a mathematical equation, the types of a relationship
+ (e.g., "parent" or "employee"), or numeric values (e.g., zero,
+ one, and infinity).
+
+ Identifier
+
+ An identifier embodies the information required to distinguish
+ what is being identified from all other things within its scope of
+ identification. Our use of the terms "identify" and "identifying"
+ refer to this purpose of distinguishing one resource from all
+ other resources, regardless of how that purpose is accomplished
+ (e.g., by name, address, or context). These terms should not be
+ mistaken as an assumption that an identifier defines or embodies
+ the identity of what is referenced, though that may be the case
+ for some identifiers. Nor should it be assumed that a system
+ using URIs will access the resource identified: in many cases,
+ URIs are used to denote resources without any intention that they
+ be accessed. Likewise, the "one" resource identified might not be
+ singular in nature (e.g., a resource might be a named set or a
+ mapping that varies over time).
+
+ A URI is an identifier consisting of a sequence of characters
+ matching the syntax rule named <URI> in Section 3. It enables
+ uniform identification of resources via a separately defined
+ extensible set of naming schemes (Section 3.1). How that
+ identification is accomplished, assigned, or enabled is delegated to
+ each scheme specification.
+
+ This specification does not place any limits on the nature of a
+ resource, the reasons why an application might seek to refer to a
+ resource, or the kinds of systems that might use URIs for the sake of
+ identifying resources. This specification does not require that a
+ URI persists in identifying the same resource over time, though that
+ is a common goal of all URI schemes. Nevertheless, nothing in this
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 5]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ specification prevents an application from limiting itself to
+ particular types of resources, or to a subset of URIs that maintains
+ characteristics desired by that application.
+
+ URIs have a global scope and are interpreted consistently regardless
+ of context, though the result of that interpretation may be in
+ relation to the end-user's context. For example, "http://localhost/"
+ has the same interpretation for every user of that reference, even
+ though the network interface corresponding to "localhost" may be
+ different for each end-user: interpretation is independent of access.
+ However, an action made on the basis of that reference will take
+ place in relation to the end-user's context, which implies that an
+ action intended to refer to a globally unique thing must use a URI
+ that distinguishes that resource from all other things. URIs that
+ identify in relation to the end-user's local context should only be
+ used when the context itself is a defining aspect of the resource,
+ such as when an on-line help manual refers to a file on the end-
+ user's file system (e.g., "file:///etc/hosts").
+
+1.1.1. Generic Syntax
+
+ Each URI begins with a scheme name, as defined in Section 3.1, that
+ refers to a specification for assigning identifiers within that
+ scheme. As such, the URI syntax is a federated and extensible naming
+ system wherein each scheme's specification may further restrict the
+ syntax and semantics of identifiers using that scheme.
+
+ This specification defines those elements of the URI syntax that are
+ required of all URI schemes or are common to many URI schemes. It
+ thus defines the syntax and semantics needed to implement a scheme-
+ independent parsing mechanism for URI references, by which the
+ scheme-dependent handling of a URI can be postponed until the
+ scheme-dependent semantics are needed. Likewise, protocols and data
+ formats that make use of URI references can refer to this
+ specification as a definition for the range of syntax allowed for all
+ URIs, including those schemes that have yet to be defined. This
+ decouples the evolution of identification schemes from the evolution
+ of protocols, data formats, and implementations that make use of
+ URIs.
+
+ A parser of the generic URI syntax can parse any URI reference into
+ its major components. Once the scheme is determined, further
+ scheme-specific parsing can be performed on the components. In other
+ words, the URI generic syntax is a superset of the syntax of all URI
+ schemes.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 6]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1.1.2. Examples
+
+ The following example URIs illustrate several URI schemes and
+ variations in their common syntax components:
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+
+ http://www.ietf.org/rfc/rfc2396.txt
+
+ ldap://[2001:db8::7]/c=GB?objectClass?one
+
+
+ news:comp.infosystems.www.servers.unix
+
+ tel:+1-816-555-1212
+
+ telnet://192.0.2.16:80/
+
+ urn:oasis:names:specification:docbook:dtd:xml:4.1.2
+
+
+1.1.3. URI, URL, and URN
+
+ A URI can be further classified as a locator, a name, or both. The
+ term "Uniform Resource Locator" (URL) refers to the subset of URIs
+ that, in addition to identifying a resource, provide a means of
+ locating the resource by describing its primary access mechanism
+ (e.g., its network "location"). The term "Uniform Resource Name"
+ (URN) has been used historically to refer to both URIs under the
+ "urn" scheme [RFC2141], which are required to remain globally unique
+ and persistent even when the resource ceases to exist or becomes
+ unavailable, and to any other URI with the properties of a name.
+
+ An individual scheme does not have to be classified as being just one
+ of "name" or "locator". Instances of URIs from any given scheme may
+ have the characteristics of names or locators or both, often
+ depending on the persistence and care in the assignment of
+ identifiers by the naming authority, rather than on any quality of
+ the scheme. Future specifications and related documentation should
+ use the general term "URI" rather than the more restrictive terms
+ "URL" and "URN" [RFC3305].
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 7]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1.2. Design Considerations
+
+1.2.1. Transcription
+
+ The URI syntax has been designed with global transcription as one of
+ its main considerations. A URI is a sequence of characters from a
+ very limited set: the letters of the basic Latin alphabet, digits,
+ and a few special characters. A URI may be represented in a variety
+ of ways; e.g., ink on paper, pixels on a screen, or a sequence of
+ character encoding octets. The interpretation of a URI depends only
+ on the characters used and not on how those characters are
+ represented in a network protocol.
+
+ The goal of transcription can be described by a simple scenario.
+ Imagine two colleagues, Sam and Kim, sitting in a pub at an
+ international conference and exchanging research ideas. Sam asks Kim
+ for a location to get more information, so Kim writes the URI for the
+ research site on a napkin. Upon returning home, Sam takes out the
+ napkin and types the URI into a computer, which then retrieves the
+ information to which Kim referred.
+
+ There are several design considerations revealed by the scenario:
+
+ o A URI is a sequence of characters that is not always represented
+ as a sequence of octets.
+
+ o A URI might be transcribed from a non-network source and thus
+ should consist of characters that are most likely able to be
+ entered into a computer, within the constraints imposed by
+ keyboards (and related input devices) across languages and
+ locales.
+
+ o A URI often has to be remembered by people, and it is easier for
+ people to remember a URI when it consists of meaningful or
+ familiar components.
+
+ These design considerations are not always in alignment. For
+ example, it is often the case that the most meaningful name for a URI
+ component would require characters that cannot be typed into some
+ systems. The ability to transcribe a resource identifier from one
+ medium to another has been considered more important than having a
+ URI consist of the most meaningful of components.
+
+ In local or regional contexts and with improving technology, users
+ might benefit from being able to use a wider range of characters;
+ such use is not defined by this specification. Percent-encoded
+ octets (Section 2.1) may be used within a URI to represent characters
+ outside the range of the US-ASCII coded character set if this
+
+
+
+Berners-Lee, et al. Standards Track [Page 8]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ representation is allowed by the scheme or by the protocol element in
+ which the URI is referenced. Such a definition should specify the
+ character encoding used to map those characters to octets prior to
+ being percent-encoded for the URI.
+
+1.2.2. Separating Identification from Interaction
+
+ A common misunderstanding of URIs is that they are only used to refer
+ to accessible resources. The URI itself only provides
+ identification; access to the resource is neither guaranteed nor
+ implied by the presence of a URI. Instead, any operation associated
+ with a URI reference is defined by the protocol element, data format
+ attribute, or natural language text in which it appears.
+
+ Given a URI, a system may attempt to perform a variety of operations
+ on the resource, as might be characterized by words such as "access",
+ "update", "replace", or "find attributes". Such operations are
+ defined by the protocols that make use of URIs, not by this
+ specification. However, we do use a few general terms for describing
+ common operations on URIs. URI "resolution" is the process of
+ determining an access mechanism and the appropriate parameters
+ necessary to dereference a URI; this resolution may require several
+ iterations. To use that access mechanism to perform an action on the
+ URI's resource is to "dereference" the URI.
+
+ When URIs are used within information retrieval systems to identify
+ sources of information, the most common form of URI dereference is
+ "retrieval": making use of a URI in order to retrieve a
+ representation of its associated resource. A "representation" is a
+ sequence of octets, along with representation metadata describing
+ those octets, that constitutes a record of the state of the resource
+ at the time when the representation is generated. Retrieval is
+ achieved by a process that might include using the URI as a cache key
+ to check for a locally cached representation, resolution of the URI
+ to determine an appropriate access mechanism (if any), and
+ dereference of the URI for the sake of applying a retrieval
+ operation. Depending on the protocols used to perform the retrieval,
+ additional information might be supplied about the resource (resource
+ metadata) and its relation to other resources.
+
+ URI references in information retrieval systems are designed to be
+ late-binding: the result of an access is generally determined when it
+ is accessed and may vary over time or due to other aspects of the
+ interaction. These references are created in order to be used in the
+ future: what is being identified is not some specific result that was
+ obtained in the past, but rather some characteristic that is expected
+ to be true for future results. In such cases, the resource referred
+ to by the URI is actually a sameness of characteristics as observed
+
+
+
+Berners-Lee, et al. Standards Track [Page 9]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ over time, perhaps elucidated by additional comments or assertions
+ made by the resource provider.
+
+ Although many URI schemes are named after protocols, this does not
+ imply that use of these URIs will result in access to the resource
+ via the named protocol. URIs are often used simply for the sake of
+ identification. Even when a URI is used to retrieve a representation
+ of a resource, that access might be through gateways, proxies,
+ caches, and name resolution services that are independent of the
+ protocol associated with the scheme name. The resolution of some
+ URIs may require the use of more than one protocol (e.g., both DNS
+ and HTTP are typically used to access an "http" URI's origin server
+ when a representation isn't found in a local cache).
+
+1.2.3. Hierarchical Identifiers
+
+ The URI syntax is organized hierarchically, with components listed in
+ order of decreasing significance from left to right. For some URI
+ schemes, the visible hierarchy is limited to the scheme itself:
+ everything after the scheme component delimiter (":") is considered
+ opaque to URI processing. Other URI schemes make the hierarchy
+ explicit and visible to generic parsing algorithms.
+
+ The generic syntax uses the slash ("/"), question mark ("?"), and
+ number sign ("#") characters to delimit components that are
+ significant to the generic parser's hierarchical interpretation of an
+ identifier. In addition to aiding the readability of such
+ identifiers through the consistent use of familiar syntax, this
+ uniform representation of hierarchy across naming schemes allows
+ scheme-independent references to be made relative to that hierarchy.
+
+ It is often the case that a group or "tree" of documents has been
+ constructed to serve a common purpose, wherein the vast majority of
+ URI references in these documents point to resources within the tree
+ rather than outside it. Similarly, documents located at a particular
+ site are much more likely to refer to other resources at that site
+ than to resources at remote sites. Relative referencing of URIs
+ allows document trees to be partially independent of their location
+ and access scheme. For instance, it is possible for a single set of
+ hypertext documents to be simultaneously accessible and traversable
+ via each of the "file", "http", and "ftp" schemes if the documents
+ refer to each other with relative references. Furthermore, such
+ document trees can be moved, as a whole, without changing any of the
+ relative references.
+
+ A relative reference (Section 4.2) refers to a resource by describing
+ the difference within a hierarchical name space between the reference
+ context and the target URI. The reference resolution algorithm,
+
+
+
+Berners-Lee, et al. Standards Track [Page 10]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ presented in Section 5, defines how such a reference is transformed
+ to the target URI. As relative references can only be used within
+ the context of a hierarchical URI, designers of new URI schemes
+ should use a syntax consistent with the generic syntax's hierarchical
+ components unless there are compelling reasons to forbid relative
+ referencing within that scheme.
+
+ NOTE: Previous specifications used the terms "partial URI" and
+ "relative URI" to denote a relative reference to a URI. As some
+ readers misunderstood those terms to mean that relative URIs are a
+ subset of URIs rather than a method of referencing URIs, this
+ specification simply refers to them as relative references.
+
+ All URI references are parsed by generic syntax parsers when used.
+ However, because hierarchical processing has no effect on an absolute
+ URI used in a reference unless it contains one or more dot-segments
+ (complete path segments of "." or "..", as described in Section 3.3),
+ URI scheme specifications can define opaque identifiers by
+ disallowing use of slash characters, question mark characters, and
+ the URIs "scheme:." and "scheme:..".
+
+1.3. Syntax Notation
+
+ This specification uses the Augmented Backus-Naur Form (ABNF)
+ notation of [RFC2234], including the following core ABNF syntax rules
+ defined by that specification: ALPHA (letters), CR (carriage return),
+ DIGIT (decimal digits), DQUOTE (double quote), HEXDIG (hexadecimal
+ digits), LF (line feed), and SP (space). The complete URI syntax is
+ collected in Appendix A.
+
+2. Characters
+
+ The URI syntax provides a method of encoding data, presumably for the
+ sake of identifying a resource, as a sequence of characters. The URI
+ characters are, in turn, frequently encoded as octets for transport
+ or presentation. This specification does not mandate any particular
+ character encoding for mapping between URI characters and the octets
+ used to store or transmit those characters. When a URI appears in a
+ protocol element, the character encoding is defined by that protocol;
+ without such a definition, a URI is assumed to be in the same
+ character encoding as the surrounding text.
+
+ The ABNF notation defines its terminal values to be non-negative
+ integers (codepoints) based on the US-ASCII coded character set
+ [ASCII]. Because a URI is a sequence of characters, we must invert
+ that relation in order to understand the URI syntax. Therefore, the
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 11]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ integer values used by the ABNF must be mapped back to their
+ corresponding characters via US-ASCII in order to complete the syntax
+ rules.
+
+ A URI is composed from a limited set of characters consisting of
+ digits, letters, and a few graphic symbols. A reserved subset of
+ those characters may be used to delimit syntax components within a
+ URI while the remaining characters, including both the unreserved set
+ and those reserved characters not acting as delimiters, define each
+ component's identifying data.
+
+2.1. Percent-Encoding
+
+ A percent-encoding mechanism is used to represent a data octet in a
+ component when that octet's corresponding character is outside the
+ allowed set or is being used as a delimiter of, or within, the
+ component. A percent-encoded octet is encoded as a character
+ triplet, consisting of the percent character "%" followed by the two
+ hexadecimal digits representing that octet's numeric value. For
+ example, "%20" is the percent-encoding for the binary octet
+ "00100000" (ABNF: %x20), which in US-ASCII corresponds to the space
+ character (SP). Section 2.4 describes when percent-encoding and
+ decoding is applied.
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ The uppercase hexadecimal digits 'A' through 'F' are equivalent to
+ the lowercase digits 'a' through 'f', respectively. If two URIs
+ differ only in the case of hexadecimal digits used in percent-encoded
+ octets, they are equivalent. For consistency, URI producers and
+ normalizers should use uppercase hexadecimal digits for all percent-
+ encodings.
+
+2.2. Reserved Characters
+
+ URIs include components and subcomponents that are delimited by
+ characters in the "reserved" set. These characters are called
+ "reserved" because they may (or may not) be defined as delimiters by
+ the generic syntax, by each scheme-specific syntax, or by the
+ implementation-specific syntax of a URI's dereferencing algorithm.
+ If data for a URI component would conflict with a reserved
+ character's purpose as a delimiter, then the conflicting data must be
+ percent-encoded before the URI is formed.
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 12]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ reserved = gen-delims / sub-delims
+
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+ The purpose of reserved characters is to provide a set of delimiting
+ characters that are distinguishable from other data within a URI.
+ URIs that differ in the replacement of a reserved character with its
+ corresponding percent-encoded octet are not equivalent. Percent-
+ encoding a reserved character, or decoding a percent-encoded octet
+ that corresponds to a reserved character, will change how the URI is
+ interpreted by most applications. Thus, characters in the reserved
+ set are protected from normalization and are therefore safe to be
+ used by scheme-specific and producer-specific algorithms for
+ delimiting data subcomponents within a URI.
+
+ A subset of the reserved characters (gen-delims) is used as
+ delimiters of the generic URI components described in Section 3. A
+ component's ABNF syntax rule will not use the reserved or gen-delims
+ rule names directly; instead, each syntax rule lists the characters
+ allowed within that component (i.e., not delimiting it), and any of
+ those characters that are also in the reserved set are "reserved" for
+ use as subcomponent delimiters within the component. Only the most
+ common subcomponents are defined by this specification; other
+ subcomponents may be defined by a URI scheme's specification, or by
+ the implementation-specific syntax of a URI's dereferencing
+ algorithm, provided that such subcomponents are delimited by
+ characters in the reserved set allowed within that component.
+
+ URI producing applications should percent-encode data octets that
+ correspond to characters in the reserved set unless these characters
+ are specifically allowed by the URI scheme to represent data in that
+ component. If a reserved character is found in a URI component and
+ no delimiting role is known for that character, then it must be
+ interpreted as representing the data octet corresponding to that
+ character's encoding in US-ASCII.
+
+2.3. Unreserved Characters
+
+ Characters that are allowed in a URI but do not have a reserved
+ purpose are called unreserved. These include uppercase and lowercase
+ letters, decimal digits, hyphen, period, underscore, and tilde.
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 13]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ URIs that differ in the replacement of an unreserved character with
+ its corresponding percent-encoded US-ASCII octet are equivalent: they
+ identify the same resource. However, URI comparison implementations
+ do not always perform normalization prior to comparison (see Section
+ 6). For consistency, percent-encoded octets in the ranges of ALPHA
+ (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E),
+ underscore (%5F), or tilde (%7E) should not be created by URI
+ producers and, when found in a URI, should be decoded to their
+ corresponding unreserved characters by URI normalizers.
+
+2.4. When to Encode or Decode
+
+ Under normal circumstances, the only time when octets within a URI
+ are percent-encoded is during the process of producing the URI from
+ its component parts. This is when an implementation determines which
+ of the reserved characters are to be used as subcomponent delimiters
+ and which can be safely used as data. Once produced, a URI is always
+ in its percent-encoded form.
+
+ When a URI is dereferenced, the components and subcomponents
+ significant to the scheme-specific dereferencing process (if any)
+ must be parsed and separated before the percent-encoded octets within
+ those components can be safely decoded, as otherwise the data may be
+ mistaken for component delimiters. The only exception is for
+ percent-encoded octets corresponding to characters in the unreserved
+ set, which can be decoded at any time. For example, the octet
+ corresponding to the tilde ("~") character is often encoded as "%7E"
+ by older URI processing implementations; the "%7E" can be replaced by
+ "~" without changing its interpretation.
+
+ Because the percent ("%") character serves as the indicator for
+ percent-encoded octets, it must be percent-encoded as "%25" for that
+ octet to be used as data within a URI. Implementations must not
+ percent-encode or decode the same string more than once, as decoding
+ an already decoded string might lead to misinterpreting a percent
+ data octet as the beginning of a percent-encoding, or vice versa in
+ the case of percent-encoding an already percent-encoded string.
+
+2.5. Identifying Data
+
+ URI characters provide identifying data for each of the URI
+ components, serving as an external interface for identification
+ between systems. Although the presence and nature of the URI
+ production interface is hidden from clients that use its URIs (and is
+ thus beyond the scope of the interoperability requirements defined by
+ this specification), it is a frequent source of confusion and errors
+ in the interpretation of URI character issues. Implementers have to
+ be aware that there are multiple character encodings involved in the
+
+
+
+Berners-Lee, et al. Standards Track [Page 14]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ production and transmission of URIs: local name and data encoding,
+ public interface encoding, URI character encoding, data format
+ encoding, and protocol encoding.
+
+ Local names, such as file system names, are stored with a local
+ character encoding. URI producing applications (e.g., origin
+ servers) will typically use the local encoding as the basis for
+ producing meaningful names. The URI producer will transform the
+ local encoding to one that is suitable for a public interface and
+ then transform the public interface encoding into the restricted set
+ of URI characters (reserved, unreserved, and percent-encodings).
+ Those characters are, in turn, encoded as octets to be used as a
+ reference within a data format (e.g., a document charset), and such
+ data formats are often subsequently encoded for transmission over
+ Internet protocols.
+
+ For most systems, an unreserved character appearing within a URI
+ component is interpreted as representing the data octet corresponding
+ to that character's encoding in US-ASCII. Consumers of URIs assume
+ that the letter "X" corresponds to the octet "01011000", and even
+ when that assumption is incorrect, there is no harm in making it. A
+ system that internally provides identifiers in the form of a
+ different character encoding, such as EBCDIC, will generally perform
+ character translation of textual identifiers to UTF-8 [STD63] (or
+ some other superset of the US-ASCII character encoding) at an
+ internal interface, thereby providing more meaningful identifiers
+ than those resulting from simply percent-encoding the original
+ octets.
+
+ For example, consider an information service that provides data,
+ stored locally using an EBCDIC-based file system, to clients on the
+ Internet through an HTTP server. When an author creates a file with
+ the name "Laguna Beach" on that file system, the "http" URI
+ corresponding to that resource is expected to contain the meaningful
+ string "Laguna%20Beach". If, however, that server produces URIs by
+ using an overly simplistic raw octet mapping, then the result would
+ be a URI containing "%D3%81%87%A4%95%81@%C2%85%81%83%88". An
+ internal transcoding interface fixes this problem by transcoding the
+ local name to a superset of US-ASCII prior to producing the URI.
+ Naturally, proper interpretation of an incoming URI on such an
+ interface requires that percent-encoded octets be decoded (e.g.,
+ "%20" to SP) before the reverse transcoding is applied to obtain the
+ local name.
+
+ In some cases, the internal interface between a URI component and the
+ identifying data that it has been crafted to represent is much less
+ direct than a character encoding translation. For example, portions
+ of a URI might reflect a query on non-ASCII data, or numeric
+
+
+
+Berners-Lee, et al. Standards Track [Page 15]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ coordinates on a map. Likewise, a URI scheme may define components
+ with additional encoding requirements that are applied prior to
+ forming the component and producing the URI.
+
+ When a new URI scheme defines a component that represents textual
+ data consisting of characters from the Universal Character Set [UCS],
+ the data should first be encoded as octets according to the UTF-8
+ character encoding [STD63]; then only those octets that do not
+ correspond to characters in the unreserved set should be percent-
+ encoded. For example, the character A would be represented as "A",
+ the character LATIN CAPITAL LETTER A WITH GRAVE would be represented
+ as "%C3%80", and the character KATAKANA LETTER A would be represented
+ as "%E3%82%A2".
+
+3. Syntax Components
+
+ The generic URI syntax consists of a hierarchical sequence of
+ components referred to as the scheme, authority, path, query, and
+ fragment.
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ The scheme and path components are required, though the path may be
+ empty (no characters). When authority is present, the path must
+ either be empty or begin with a slash ("/") character. When
+ authority is not present, the path cannot begin with two slash
+ characters ("//"). These restrictions result in five different ABNF
+ rules for a path (Section 3.3), only one of which will match any
+ given URI reference.
+
+ The following are two example URIs and their component parts:
+
+ foo://example.com:8042/over/there?name=ferret#nose
+ \_/ \______________/\_________/ \_________/ \__/
+ | | | | |
+ scheme authority path query fragment
+ | _____________________|__
+ / \ / \
+ urn:example:animal:ferret:nose
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 16]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+3.1. Scheme
+
+ Each URI begins with a scheme name that refers to a specification for
+ assigning identifiers within that scheme. As such, the URI syntax is
+ a federated and extensible naming system wherein each scheme's
+ specification may further restrict the syntax and semantics of
+ identifiers using that scheme.
+
+ Scheme names consist of a sequence of characters beginning with a
+ letter and followed by any combination of letters, digits, plus
+ ("+"), period ("."), or hyphen ("-"). Although schemes are case-
+ insensitive, the canonical form is lowercase and documents that
+ specify schemes must do so with lowercase letters. An implementation
+ should accept uppercase letters as equivalent to lowercase in scheme
+ names (e.g., allow "HTTP" as well as "http") for the sake of
+ robustness but should only produce lowercase scheme names for
+ consistency.
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ Individual schemes are not specified by this document. The process
+ for registration of new URI schemes is defined separately by [BCP35].
+ The scheme registry maintains the mapping between scheme names and
+ their specifications. Advice for designers of new URI schemes can be
+ found in [RFC2718]. URI scheme specifications must define their own
+ syntax so that all strings matching their scheme-specific syntax will
+ also match the <absolute-URI> grammar, as described in Section 4.3.
+
+ When presented with a URI that violates one or more scheme-specific
+ restrictions, the scheme-specific resolution process should flag the
+ reference as an error rather than ignore the unused parts; doing so
+ reduces the number of equivalent URIs and helps detect abuses of the
+ generic syntax, which might indicate that the URI has been
+ constructed to mislead the user (Section 7.6).
+
+3.2. Authority
+
+ Many URI schemes include a hierarchical element for a naming
+ authority so that governance of the name space defined by the
+ remainder of the URI is delegated to that authority (which may, in
+ turn, delegate it further). The generic syntax provides a common
+ means for distinguishing an authority based on a registered name or
+ server address, along with optional port and user information.
+
+ The authority component is preceded by a double slash ("//") and is
+ terminated by the next slash ("/"), question mark ("?"), or number
+ sign ("#") character, or by the end of the URI.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 17]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+
+ URI producers and normalizers should omit the ":" delimiter that
+ separates host from port if the port component is empty. Some
+ schemes do not allow the userinfo and/or port subcomponents.
+
+ If a URI contains an authority component, then the path component
+ must either be empty or begin with a slash ("/") character. Non-
+ validating parsers (those that merely separate a URI reference into
+ its major components) will often ignore the subcomponent structure of
+ authority, treating it as an opaque string from the double-slash to
+ the first terminating delimiter, until such time as the URI is
+ dereferenced.
+
+3.2.1. User Information
+
+ The userinfo subcomponent may consist of a user name and, optionally,
+ scheme-specific information about how to gain authorization to access
+ the resource. The user information, if present, is followed by a
+ commercial at-sign ("@") that delimits it from the host.
+
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+
+ Use of the format "user:password" in the userinfo field is
+ deprecated. Applications should not render as clear text any data
+ after the first colon (":") character found within a userinfo
+ subcomponent unless the data after the colon is the empty string
+ (indicating no password). Applications may choose to ignore or
+ reject such data when it is received as part of a reference and
+ should reject the storage of such data in unencrypted form. The
+ passing of authentication information in clear text has proven to be
+ a security risk in almost every case where it has been used.
+
+ Applications that render a URI for the sake of user feedback, such as
+ in graphical hypertext browsing, should render userinfo in a way that
+ is distinguished from the rest of a URI, when feasible. Such
+ rendering will assist the user in cases where the userinfo has been
+ misleadingly crafted to look like a trusted domain name
+ (Section 7.6).
+
+3.2.2. Host
+
+ The host subcomponent of authority is identified by an IP literal
+ encapsulated within square brackets, an IPv4 address in dotted-
+ decimal form, or a registered name. The host subcomponent is case-
+ insensitive. The presence of a host subcomponent within a URI does
+ not imply that the scheme requires access to the given host on the
+ Internet. In many cases, the host syntax is used only for the sake
+
+
+
+Berners-Lee, et al. Standards Track [Page 18]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ of reusing the existing registration process created and deployed for
+ DNS, thus obtaining a globally unique name without the cost of
+ deploying another registry. However, such use comes with its own
+ costs: domain name ownership may change over time for reasons not
+ anticipated by the URI producer. In other cases, the data within the
+ host component identifies a registered name that has nothing to do
+ with an Internet host. We use the name "host" for the ABNF rule
+ because that is its most common purpose, not its only purpose.
+
+ host = IP-literal / IPv4address / reg-name
+
+ The syntax rule for host is ambiguous because it does not completely
+ distinguish between an IPv4address and a reg-name. In order to
+ disambiguate the syntax, we apply the "first-match-wins" algorithm:
+ If host matches the rule for IPv4address, then it should be
+ considered an IPv4 address literal and not a reg-name. Although host
+ is case-insensitive, producers and normalizers should use lowercase
+ for registered names and hexadecimal addresses for the sake of
+ uniformity, while only using uppercase letters for percent-encodings.
+
+ A host identified by an Internet Protocol literal address, version 6
+ [RFC3513] or later, is distinguished by enclosing the IP literal
+ within square brackets ("[" and "]"). This is the only place where
+ square bracket characters are allowed in the URI syntax. In
+ anticipation of future, as-yet-undefined IP literal address formats,
+ an implementation may use an optional version flag to indicate such a
+ format explicitly rather than rely on heuristic determination.
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ The version flag does not indicate the IP version; rather, it
+ indicates future versions of the literal format. As such,
+ implementations must not provide the version flag for the existing
+ IPv4 and IPv6 literal address forms described below. If a URI
+ containing an IP-literal that starts with "v" (case-insensitive),
+ indicating that the version flag is present, is dereferenced by an
+ application that does not know the meaning of that version flag, then
+ the application should return an appropriate error for "address
+ mechanism not supported".
+
+ A host identified by an IPv6 literal address is represented inside
+ the square brackets without a preceding version flag. The ABNF
+ provided here is a translation of the text definition of an IPv6
+ literal address provided in [RFC3513]. This syntax does not support
+ IPv6 scoped addressing zone identifiers.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 19]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A 128-bit IPv6 address is divided into eight 16-bit pieces. Each
+ piece is represented numerically in case-insensitive hexadecimal,
+ using one to four hexadecimal digits (leading zeroes are permitted).
+ The eight encoded pieces are given most-significant first, separated
+ by colon characters. Optionally, the least-significant two pieces
+ may instead be represented in IPv4 address textual format. A
+ sequence of one or more consecutive zero-valued 16-bit pieces within
+ the address may be elided, omitting all their digits and leaving
+ exactly two consecutive colons in their place to mark the elision.
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ ; least-significant 32 bits of address
+
+ h16 = 1*4HEXDIG
+ ; 16 bits of address represented in hexadecimal
+
+ A host identified by an IPv4 literal address is represented in
+ dotted-decimal notation (a sequence of four decimal numbers in the
+ range 0 to 255, separated by "."), as described in [RFC1123] by
+ reference to [RFC0952]. Note that other forms of dotted notation may
+ be interpreted on some platforms, as described in Section 7.4, but
+ only the dotted-decimal form of four octets is allowed by this
+ grammar.
+
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ A host identified by a registered name is a sequence of characters
+ usually intended for lookup within a locally defined host or service
+ name registry, though the URI's scheme-specific semantics may require
+ that a specific registry (or fixed name table) be used instead. The
+ most common name registry mechanism is the Domain Name System (DNS).
+ A registered name intended for lookup in the DNS uses the syntax
+
+
+
+Berners-Lee, et al. Standards Track [Page 20]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ defined in Section 3.5 of [RFC1034] and Section 2.1 of [RFC1123].
+ Such a name consists of a sequence of domain labels separated by ".",
+ each domain label starting and ending with an alphanumeric character
+ and possibly also containing "-" characters. The rightmost domain
+ label of a fully qualified domain name in DNS may be followed by a
+ single "." and should be if it is necessary to distinguish between
+ the complete domain name and some local domain.
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ If the URI scheme defines a default for host, then that default
+ applies when the host subcomponent is undefined or when the
+ registered name is empty (zero length). For example, the "file" URI
+ scheme is defined so that no authority, an empty host, and
+ "localhost" all mean the end-user's machine, whereas the "http"
+ scheme considers a missing authority or empty host invalid.
+
+ This specification does not mandate a particular registered name
+ lookup technology and therefore does not restrict the syntax of reg-
+ name beyond what is necessary for interoperability. Instead, it
+ delegates the issue of registered name syntax conformance to the
+ operating system of each application performing URI resolution, and
+ that operating system decides what it will allow for the purpose of
+ host identification. A URI resolution implementation might use DNS,
+ host tables, yellow pages, NetInfo, WINS, or any other system for
+ lookup of registered names. However, a globally scoped naming
+ system, such as DNS fully qualified domain names, is necessary for
+ URIs intended to have global scope. URI producers should use names
+ that conform to the DNS syntax, even when use of DNS is not
+ immediately apparent, and should limit these names to no more than
+ 255 characters in length.
+
+ The reg-name syntax allows percent-encoded octets in order to
+ represent non-ASCII registered names in a uniform way that is
+ independent of the underlying name resolution technology. Non-ASCII
+ characters must first be encoded according to UTF-8 [STD63], and then
+ each octet of the corresponding UTF-8 sequence must be percent-
+ encoded to be represented as URI characters. URI producing
+ applications must not use percent-encoding in host unless it is used
+ to represent a UTF-8 character sequence. When a non-ASCII registered
+ name represents an internationalized domain name intended for
+ resolution via the DNS, the name must be transformed to the IDNA
+ encoding [RFC3490] prior to name lookup. URI producers should
+ provide these registered names in the IDNA encoding, rather than a
+ percent-encoding, if they wish to maximize interoperability with
+ legacy URI resolvers.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 21]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+3.2.3. Port
+
+ The port subcomponent of authority is designated by an optional port
+ number in decimal following the host and delimited from it by a
+ single colon (":") character.
+
+ port = *DIGIT
+
+ A scheme may define a default port. For example, the "http" scheme
+ defines a default port of "80", corresponding to its reserved TCP
+ port number. The type of port designated by the port number (e.g.,
+ TCP, UDP, SCTP) is defined by the URI scheme. URI producers and
+ normalizers should omit the port component and its ":" delimiter if
+ port is empty or if its value would be the same as that of the
+ scheme's default.
+
+3.3. Path
+
+ The path component contains data, usually organized in hierarchical
+ form, that, along with data in the non-hierarchical query component
+ (Section 3.4), serves to identify a resource within the scope of the
+ URI's scheme and naming authority (if any). The path is terminated
+ by the first question mark ("?") or number sign ("#") character, or
+ by the end of the URI.
+
+ If a URI contains an authority component, then the path component
+ must either be empty or begin with a slash ("/") character. If a URI
+ does not contain an authority component, then the path cannot begin
+ with two slash characters ("//"). In addition, a URI reference
+ (Section 4.1) may be a relative-path reference, in which case the
+ first path segment cannot contain a colon (":") character. The ABNF
+ requires five separate rules to disambiguate these cases, only one of
+ which will match the path substring within a given URI reference. We
+ use the generic term "path component" to describe the URI substring
+ matched by the parser to one of these rules.
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 22]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ A path consists of a sequence of path segments separated by a slash
+ ("/") character. A path is always defined for a URI, though the
+ defined path may be empty (zero length). Use of the slash character
+ to indicate hierarchy is only required when a URI will be used as the
+ context for relative references. For example, the URI
+ <mailto:[email protected]> has a path of "[email protected]", whereas
+ the URI <foo://info.example.com?fred> has an empty path.
+
+ The path segments "." and "..", also known as dot-segments, are
+ defined for relative reference within the path name hierarchy. They
+ are intended for use at the beginning of a relative-path reference
+ (Section 4.2) to indicate relative position within the hierarchical
+ tree of names. This is similar to their role within some operating
+ systems' file directory structures to indicate the current directory
+ and parent directory, respectively. However, unlike in a file
+ system, these dot-segments are only interpreted within the URI path
+ hierarchy and are removed as part of the resolution process (Section
+ 5.2).
+
+ Aside from dot-segments in hierarchical paths, a path segment is
+ considered opaque by the generic syntax. URI producing applications
+ often use the reserved characters allowed in a segment to delimit
+ scheme-specific or dereference-handler-specific subcomponents. For
+ example, the semicolon (";") and equals ("=") reserved characters are
+ often used to delimit parameters and parameter values applicable to
+ that segment. The comma (",") reserved character is often used for
+ similar purposes. For example, one URI producer might use a segment
+ such as "name;v=1.1" to indicate a reference to version 1.1 of
+ "name", whereas another might use a segment such as "name,1.1" to
+ indicate the same. Parameter types may be defined by scheme-specific
+ semantics, but in most cases the syntax of a parameter is specific to
+ the implementation of the URI's dereferencing algorithm.
+
+3.4. Query
+
+ The query component contains non-hierarchical data that, along with
+ data in the path component (Section 3.3), serves to identify a
+ resource within the scope of the URI's scheme and naming authority
+ (if any). The query component is indicated by the first question
+ mark ("?") character and terminated by a number sign ("#") character
+ or by the end of the URI.
+
+
+
+Berners-Lee, et al. Standards Track [Page 23]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ query = *( pchar / "/" / "?" )
+
+ The characters slash ("/") and question mark ("?") may represent data
+ within the query component. Beware that some older, erroneous
+ implementations may not handle such data correctly when it is used as
+ the base URI for relative references (Section 5.1), apparently
+ because they fail to distinguish query data from path data when
+ looking for hierarchical separators. However, as query components
+ are often used to carry identifying information in the form of
+ "key=value" pairs and one frequently used value is a reference to
+ another URI, it is sometimes better for usability to avoid percent-
+ encoding those characters.
+
+3.5. Fragment
+
+ The fragment identifier component of a URI allows indirect
+ identification of a secondary resource by reference to a primary
+ resource and additional identifying information. The identified
+ secondary resource may be some portion or subset of the primary
+ resource, some view on representations of the primary resource, or
+ some other resource defined or described by those representations. A
+ fragment identifier component is indicated by the presence of a
+ number sign ("#") character and terminated by the end of the URI.
+
+ fragment = *( pchar / "/" / "?" )
+
+ The semantics of a fragment identifier are defined by the set of
+ representations that might result from a retrieval action on the
+ primary resource. The fragment's format and resolution is therefore
+ dependent on the media type [RFC2046] of a potentially retrieved
+ representation, even though such a retrieval is only performed if the
+ URI is dereferenced. If no such representation exists, then the
+ semantics of the fragment are considered unknown and are effectively
+ unconstrained. Fragment identifier semantics are independent of the
+ URI scheme and thus cannot be redefined by scheme specifications.
+
+ Individual media types may define their own restrictions on or
+ structures within the fragment identifier syntax for specifying
+ different types of subsets, views, or external references that are
+ identifiable as secondary resources by that media type. If the
+ primary resource has multiple representations, as is often the case
+ for resources whose representation is selected based on attributes of
+ the retrieval request (a.k.a., content negotiation), then whatever is
+ identified by the fragment should be consistent across all of those
+ representations. Each representation should either define the
+ fragment so that it corresponds to the same secondary resource,
+ regardless of how it is represented, or should leave the fragment
+ undefined (i.e., not found).
+
+
+
+Berners-Lee, et al. Standards Track [Page 24]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ As with any URI, use of a fragment identifier component does not
+ imply that a retrieval action will take place. A URI with a fragment
+ identifier may be used to refer to the secondary resource without any
+ implication that the primary resource is accessible or will ever be
+ accessed.
+
+ Fragment identifiers have a special role in information retrieval
+ systems as the primary form of client-side indirect referencing,
+ allowing an author to specifically identify aspects of an existing
+ resource that are only indirectly provided by the resource owner. As
+ such, the fragment identifier is not used in the scheme-specific
+ processing of a URI; instead, the fragment identifier is separated
+ from the rest of the URI prior to a dereference, and thus the
+ identifying information within the fragment itself is dereferenced
+ solely by the user agent, regardless of the URI scheme. Although
+ this separate handling is often perceived to be a loss of
+ information, particularly for accurate redirection of references as
+ resources move over time, it also serves to prevent information
+ providers from denying reference authors the right to refer to
+ information within a resource selectively. Indirect referencing also
+ provides additional flexibility and extensibility to systems that use
+ URIs, as new media types are easier to define and deploy than new
+ schemes of identification.
+
+ The characters slash ("/") and question mark ("?") are allowed to
+ represent data within the fragment identifier. Beware that some
+ older, erroneous implementations may not handle this data correctly
+ when it is used as the base URI for relative references (Section
+ 5.1).
+
+4. Usage
+
+ When applications make reference to a URI, they do not always use the
+ full form of reference defined by the "URI" syntax rule. To save
+ space and take advantage of hierarchical locality, many Internet
+ protocol elements and media type formats allow an abbreviation of a
+ URI, whereas others restrict the syntax to a particular form of URI.
+ We define the most common forms of reference syntax in this
+ specification because they impact and depend upon the design of the
+ generic syntax, requiring a uniform parsing algorithm in order to be
+ interpreted consistently.
+
+4.1. URI Reference
+
+ URI-reference is used to denote the most common usage of a resource
+ identifier.
+
+ URI-reference = URI / relative-ref
+
+
+
+Berners-Lee, et al. Standards Track [Page 25]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A URI-reference is either a URI or a relative reference. If the
+ URI-reference's prefix does not match the syntax of a scheme followed
+ by its colon separator, then the URI-reference is a relative
+ reference.
+
+ A URI-reference is typically parsed first into the five URI
+ components, in order to determine what components are present and
+ whether the reference is relative. Then, each component is parsed
+ for its subparts and their validation. The ABNF of URI-reference,
+ along with the "first-match-wins" disambiguation rule, is sufficient
+ to define a validating parser for the generic syntax. Readers
+ familiar with regular expressions should see Appendix B for an
+ example of a non-validating URI-reference parser that will take any
+ given string and extract the URI components.
+
+4.2. Relative Reference
+
+ A relative reference takes advantage of the hierarchical syntax
+ (Section 1.2.3) to express a URI reference relative to the name space
+ of another hierarchical URI.
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ The URI referred to by a relative reference, also known as the target
+ URI, is obtained by applying the reference resolution algorithm of
+ Section 5.
+
+ A relative reference that begins with two slash characters is termed
+ a network-path reference; such references are rarely used. A
+ relative reference that begins with a single slash character is
+ termed an absolute-path reference. A relative reference that does
+ not begin with a slash character is termed a relative-path reference.
+
+ A path segment that contains a colon character (e.g., "this:that")
+ cannot be used as the first segment of a relative-path reference, as
+ it would be mistaken for a scheme name. Such a segment must be
+ preceded by a dot-segment (e.g., "./this:that") to make a relative-
+ path reference.
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 26]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+4.3. Absolute URI
+
+ Some protocol elements allow only the absolute form of a URI without
+ a fragment identifier. For example, defining a base URI for later
+ use by relative references calls for an absolute-URI syntax rule that
+ does not allow a fragment.
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ URI scheme specifications must define their own syntax so that all
+ strings matching their scheme-specific syntax will also match the
+ <absolute-URI> grammar. Scheme specifications will not define
+ fragment identifier syntax or usage, regardless of its applicability
+ to resources identifiable via that scheme, as fragment identification
+ is orthogonal to scheme definition. However, scheme specifications
+ are encouraged to include a wide range of examples, including
+ examples that show use of the scheme's URIs with fragment identifiers
+ when such usage is appropriate.
+
+4.4. Same-Document Reference
+
+ When a URI reference refers to a URI that is, aside from its fragment
+ component (if any), identical to the base URI (Section 5.1), that
+ reference is called a "same-document" reference. The most frequent
+ examples of same-document references are relative references that are
+ empty or include only the number sign ("#") separator followed by a
+ fragment identifier.
+
+ When a same-document reference is dereferenced for a retrieval
+ action, the target of that reference is defined to be within the same
+ entity (representation, document, or message) as the reference;
+ therefore, a dereference should not result in a new retrieval action.
+
+ Normalization of the base and target URIs prior to their comparison,
+ as described in Sections 6.2.2 and 6.2.3, is allowed but rarely
+ performed in practice. Normalization may increase the set of same-
+ document references, which may be of benefit to some caching
+ applications. As such, reference authors should not assume that a
+ slightly different, though equivalent, reference URI will (or will
+ not) be interpreted as a same-document reference by any given
+ application.
+
+4.5. Suffix Reference
+
+ The URI syntax is designed for unambiguous reference to resources and
+ extensibility via the URI scheme. However, as URI identification and
+ usage have become commonplace, traditional media (television, radio,
+ newspapers, billboards, etc.) have increasingly used a suffix of the
+
+
+
+Berners-Lee, et al. Standards Track [Page 27]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ URI as a reference, consisting of only the authority and path
+ portions of the URI, such as
+
+ www.w3.org/Addressing/
+
+ or simply a DNS registered name on its own. Such references are
+ primarily intended for human interpretation rather than for machines,
+ with the assumption that context-based heuristics are sufficient to
+ complete the URI (e.g., most registered names beginning with "www"
+ are likely to have a URI prefix of "http://"). Although there is no
+ standard set of heuristics for disambiguating a URI suffix, many
+ client implementations allow them to be entered by the user and
+ heuristically resolved.
+
+ Although this practice of using suffix references is common, it
+ should be avoided whenever possible and should never be used in
+ situations where long-term references are expected. The heuristics
+ noted above will change over time, particularly when a new URI scheme
+ becomes popular, and are often incorrect when used out of context.
+ Furthermore, they can lead to security issues along the lines of
+ those described in [RFC1535].
+
+ As a URI suffix has the same syntax as a relative-path reference, a
+ suffix reference cannot be used in contexts where a relative
+ reference is expected. As a result, suffix references are limited to
+ places where there is no defined base URI, such as dialog boxes and
+ off-line advertisements.
+
+5. Reference Resolution
+
+ This section defines the process of resolving a URI reference within
+ a context that allows relative references so that the result is a
+ string matching the <URI> syntax rule of Section 3.
+
+5.1. Establishing a Base URI
+
+ The term "relative" implies that a "base URI" exists against which
+ the relative reference is applied. Aside from fragment-only
+ references (Section 4.4), relative references are only usable when a
+ base URI is known. A base URI must be established by the parser
+ prior to parsing URI references that might be relative. A base URI
+ must conform to the <absolute-URI> syntax rule (Section 4.3). If the
+ base URI is obtained from a URI reference, then that reference must
+ be converted to absolute form and stripped of any fragment component
+ prior to its use as a base URI.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 28]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ The base URI of a reference can be established in one of four ways,
+ discussed below in order of precedence. The order of precedence can
+ be thought of in terms of layers, where the innermost defined base
+ URI has the highest precedence. This can be visualized graphically
+ as follows:
+
+ .----------------------------------------------------------.
+ | .----------------------------------------------------. |
+ | | .----------------------------------------------. | |
+ | | | .----------------------------------------. | | |
+ | | | | .----------------------------------. | | | |
+ | | | | | <relative-reference> | | | | |
+ | | | | `----------------------------------' | | | |
+ | | | | (5.1.1) Base URI embedded in content | | | |
+ | | | `----------------------------------------' | | |
+ | | | (5.1.2) Base URI of the encapsulating entity | | |
+ | | | (message, representation, or none) | | |
+ | | `----------------------------------------------' | |
+ | | (5.1.3) URI used to retrieve the entity | |
+ | `----------------------------------------------------' |
+ | (5.1.4) Default Base URI (application-dependent) |
+ `----------------------------------------------------------'
+
+5.1.1. Base URI Embedded in Content
+
+ Within certain media types, a base URI for relative references can be
+ embedded within the content itself so that it can be readily obtained
+ by a parser. This can be useful for descriptive documents, such as
+ tables of contents, which may be transmitted to others through
+ protocols other than their usual retrieval context (e.g., email or
+ USENET news).
+
+ It is beyond the scope of this specification to specify how, for each
+ media type, a base URI can be embedded. The appropriate syntax, when
+ available, is described by the data format specification associated
+ with each media type.
+
+5.1.2. Base URI from the Encapsulating Entity
+
+ If no base URI is embedded, the base URI is defined by the
+ representation's retrieval context. For a document that is enclosed
+ within another entity, such as a message or archive, the retrieval
+ context is that entity. Thus, the default base URI of a
+ representation is the base URI of the entity in which the
+ representation is encapsulated.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 29]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A mechanism for embedding a base URI within MIME container types
+ (e.g., the message and multipart types) is defined by MHTML
+ [RFC2557]. Protocols that do not use the MIME message header syntax,
+ but that do allow some form of tagged metadata to be included within
+ messages, may define their own syntax for defining a base URI as part
+ of a message.
+
+5.1.3. Base URI from the Retrieval URI
+
+ If no base URI is embedded and the representation is not encapsulated
+ within some other entity, then, if a URI was used to retrieve the
+ representation, that URI shall be considered the base URI. Note that
+ if the retrieval was the result of a redirected request, the last URI
+ used (i.e., the URI that resulted in the actual retrieval of the
+ representation) is the base URI.
+
+5.1.4. Default Base URI
+
+ If none of the conditions described above apply, then the base URI is
+ defined by the context of the application. As this definition is
+ necessarily application-dependent, failing to define a base URI by
+ using one of the other methods may result in the same content being
+ interpreted differently by different types of applications.
+
+ A sender of a representation containing relative references is
+ responsible for ensuring that a base URI for those references can be
+ established. Aside from fragment-only references, relative
+ references can only be used reliably in situations where the base URI
+ is well defined.
+
+5.2. Relative Resolution
+
+ This section describes an algorithm for converting a URI reference
+ that might be relative to a given base URI into the parsed components
+ of the reference's target. The components can then be recomposed, as
+ described in Section 5.3, to form the target URI. This algorithm
+ provides definitive results that can be used to test the output of
+ other implementations. Applications may implement relative reference
+ resolution by using some other algorithm, provided that the results
+ match what would be given by this one.
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 30]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.2.1. Pre-parse the Base URI
+
+ The base URI (Base) is established according to the procedure of
+ Section 5.1 and parsed into the five main components described in
+ Section 3. Note that only the scheme component is required to be
+ present in a base URI; the other components may be empty or
+ undefined. A component is undefined if its associated delimiter does
+ not appear in the URI reference; the path component is never
+ undefined, though it may be empty.
+
+ Normalization of the base URI, as described in Sections 6.2.2 and
+ 6.2.3, is optional. A URI reference must be transformed to its
+ target URI before it can be normalized.
+
+5.2.2. Transform References
+
+ For each URI reference (R), the following pseudocode describes an
+ algorithm for transforming R into its target URI (T):
+
+ -- The URI reference is parsed into the five URI components
+ --
+ (R.scheme, R.authority, R.path, R.query, R.fragment) = parse(R);
+
+ -- A non-strict parser may ignore a scheme in the reference
+ -- if it is identical to the base URI's scheme.
+ --
+ if ((not strict) and (R.scheme == Base.scheme)) then
+ undefine(R.scheme);
+ endif;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 31]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ if defined(R.scheme) then
+ T.scheme = R.scheme;
+ T.authority = R.authority;
+ T.path = remove_dot_segments(R.path);
+ T.query = R.query;
+ else
+ if defined(R.authority) then
+ T.authority = R.authority;
+ T.path = remove_dot_segments(R.path);
+ T.query = R.query;
+ else
+ if (R.path == "") then
+ T.path = Base.path;
+ if defined(R.query) then
+ T.query = R.query;
+ else
+ T.query = Base.query;
+ endif;
+ else
+ if (R.path starts-with "/") then
+ T.path = remove_dot_segments(R.path);
+ else
+ T.path = merge(Base.path, R.path);
+ T.path = remove_dot_segments(T.path);
+ endif;
+ T.query = R.query;
+ endif;
+ T.authority = Base.authority;
+ endif;
+ T.scheme = Base.scheme;
+ endif;
+
+ T.fragment = R.fragment;
+
+5.2.3. Merge Paths
+
+ The pseudocode above refers to a "merge" routine for merging a
+ relative-path reference with the path of the base URI. This is
+ accomplished as follows:
+
+ o If the base URI has a defined authority component and an empty
+ path, then return a string consisting of "/" concatenated with the
+ reference's path; otherwise,
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 32]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ o return a string consisting of the reference's path component
+ appended to all but the last segment of the base URI's path (i.e.,
+ excluding any characters after the right-most "/" in the base URI
+ path, or excluding the entire base URI path if it does not contain
+ any "/" characters).
+
+5.2.4. Remove Dot Segments
+
+ The pseudocode also refers to a "remove_dot_segments" routine for
+ interpreting and removing the special "." and ".." complete path
+ segments from a referenced path. This is done after the path is
+ extracted from a reference, whether or not the path was relative, in
+ order to remove any invalid or extraneous dot-segments prior to
+ forming the target URI. Although there are many ways to accomplish
+ this removal process, we describe a simple method using two string
+ buffers.
+
+ 1. The input buffer is initialized with the now-appended path
+ components and the output buffer is initialized to the empty
+ string.
+
+ 2. While the input buffer is not empty, loop as follows:
+
+ A. If the input buffer begins with a prefix of "../" or "./",
+ then remove that prefix from the input buffer; otherwise,
+
+ B. if the input buffer begins with a prefix of "/./" or "/.",
+ where "." is a complete path segment, then replace that
+ prefix with "/" in the input buffer; otherwise,
+
+ C. if the input buffer begins with a prefix of "/../" or "/..",
+ where ".." is a complete path segment, then replace that
+ prefix with "/" in the input buffer and remove the last
+ segment and its preceding "/" (if any) from the output
+ buffer; otherwise,
+
+ D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise,
+
+ E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if
+ any) and any subsequent characters up to, but not including,
+ the next "/" character or the end of the input buffer.
+
+ 3. Finally, the output buffer is returned as the result of
+ remove_dot_segments.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 33]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Note that dot-segments are intended for use in URI references to
+ express an identifier relative to the hierarchy of names in the base
+ URI. The remove_dot_segments algorithm respects that hierarchy by
+ removing extra dot-segments rather than treat them as an error or
+ leaving them to be misinterpreted by dereference implementations.
+
+ The following illustrates how the above steps are applied for two
+ examples of merged paths, showing the state of the two buffers after
+ each step.
+
+ STEP OUTPUT BUFFER INPUT BUFFER
+
+ 1 : /a/b/c/./../../g
+ 2E: /a /b/c/./../../g
+ 2E: /a/b /c/./../../g
+ 2E: /a/b/c /./../../g
+ 2B: /a/b/c /../../g
+ 2C: /a/b /../g
+ 2C: /a /g
+ 2E: /a/g
+
+ STEP OUTPUT BUFFER INPUT BUFFER
+
+ 1 : mid/content=5/../6
+ 2E: mid /content=5/../6
+ 2E: mid/content=5 /../6
+ 2C: mid /6
+ 2E: mid/6
+
+ Some applications may find it more efficient to implement the
+ remove_dot_segments algorithm by using two segment stacks rather than
+ strings.
+
+ Note: Beware that some older, erroneous implementations will fail
+ to separate a reference's query component from its path component
+ prior to merging the base and reference paths, resulting in an
+ interoperability failure if the query component contains the
+ strings "/../" or "/./".
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 34]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.3. Component Recomposition
+
+ Parsed URI components can be recomposed to obtain the corresponding
+ URI reference string. Using pseudocode, this would be:
+
+ result = ""
+
+ if defined(scheme) then
+ append scheme to result;
+ append ":" to result;
+ endif;
+
+ if defined(authority) then
+ append "//" to result;
+ append authority to result;
+ endif;
+
+ append path to result;
+
+ if defined(query) then
+ append "?" to result;
+ append query to result;
+ endif;
+
+ if defined(fragment) then
+ append "#" to result;
+ append fragment to result;
+ endif;
+
+ return result;
+
+ Note that we are careful to preserve the distinction between a
+ component that is undefined, meaning that its separator was not
+ present in the reference, and a component that is empty, meaning that
+ the separator was present and was immediately followed by the next
+ component separator or the end of the reference.
+
+5.4. Reference Resolution Examples
+
+ Within a representation with a well defined base URI of
+
+ http://a/b/c/d;p?q
+
+ a relative reference is transformed to its target URI as follows.
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 35]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.4.1. Normal Examples
+
+ "g:h" = "g:h"
+ "g" = "http://a/b/c/g"
+ "./g" = "http://a/b/c/g"
+ "g/" = "http://a/b/c/g/"
+ "/g" = "http://a/g"
+ "//g" = "http://g"
+ "?y" = "http://a/b/c/d;p?y"
+ "g?y" = "http://a/b/c/g?y"
+ "#s" = "http://a/b/c/d;p?q#s"
+ "g#s" = "http://a/b/c/g#s"
+ "g?y#s" = "http://a/b/c/g?y#s"
+ ";x" = "http://a/b/c/;x"
+ "g;x" = "http://a/b/c/g;x"
+ "g;x?y#s" = "http://a/b/c/g;x?y#s"
+ "" = "http://a/b/c/d;p?q"
+ "." = "http://a/b/c/"
+ "./" = "http://a/b/c/"
+ ".." = "http://a/b/"
+ "../" = "http://a/b/"
+ "../g" = "http://a/b/g"
+ "../.." = "http://a/"
+ "../../" = "http://a/"
+ "../../g" = "http://a/g"
+
+5.4.2. Abnormal Examples
+
+ Although the following abnormal examples are unlikely to occur in
+ normal practice, all URI parsers should be capable of resolving them
+ consistently. Each example uses the same base as that above.
+
+ Parsers must be careful in handling cases where there are more ".."
+ segments in a relative-path reference than there are hierarchical
+ levels in the base URI's path. Note that the ".." syntax cannot be
+ used to change the authority component of a URI.
+
+ "../../../g" = "http://a/g"
+ "../../../../g" = "http://a/g"
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 36]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Similarly, parsers must remove the dot-segments "." and ".." when
+ they are complete components of a path, but not when they are only
+ part of a segment.
+
+ "/./g" = "http://a/g"
+ "/../g" = "http://a/g"
+ "g." = "http://a/b/c/g."
+ ".g" = "http://a/b/c/.g"
+ "g.." = "http://a/b/c/g.."
+ "..g" = "http://a/b/c/..g"
+
+ Less likely are cases where the relative reference uses unnecessary
+ or nonsensical forms of the "." and ".." complete path segments.
+
+ "./../g" = "http://a/b/g"
+ "./g/." = "http://a/b/c/g/"
+ "g/./h" = "http://a/b/c/g/h"
+ "g/../h" = "http://a/b/c/h"
+ "g;x=1/./y" = "http://a/b/c/g;x=1/y"
+ "g;x=1/../y" = "http://a/b/c/y"
+
+ Some applications fail to separate the reference's query and/or
+ fragment components from the path component before merging it with
+ the base path and removing dot-segments. This error is rarely
+ noticed, as typical usage of a fragment never includes the hierarchy
+ ("/") character and the query component is not normally used within
+ relative references.
+
+ "g?y/./x" = "http://a/b/c/g?y/./x"
+ "g?y/../x" = "http://a/b/c/g?y/../x"
+ "g#s/./x" = "http://a/b/c/g#s/./x"
+ "g#s/../x" = "http://a/b/c/g#s/../x"
+
+ Some parsers allow the scheme name to be present in a relative
+ reference if it is the same as the base URI scheme. This is
+ considered to be a loophole in prior specifications of partial URI
+ [RFC1630]. Its use should be avoided but is allowed for backward
+ compatibility.
+
+ "http:g" = "http:g" ; for strict parsers
+ / "http://a/b/c/g" ; for backward compatibility
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 37]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6. Normalization and Comparison
+
+ One of the most common operations on URIs is simple comparison:
+ determining whether two URIs are equivalent without using the URIs to
+ access their respective resource(s). A comparison is performed every
+ time a response cache is accessed, a browser checks its history to
+ color a link, or an XML parser processes tags within a namespace.
+ Extensive normalization prior to comparison of URIs is often used by
+ spiders and indexing engines to prune a search space or to reduce
+ duplication of request actions and response storage.
+
+ URI comparison is performed for some particular purpose. Protocols
+ or implementations that compare URIs for different purposes will
+ often be subject to differing design trade-offs in regards to how
+ much effort should be spent in reducing aliased identifiers. This
+ section describes various methods that may be used to compare URIs,
+ the trade-offs between them, and the types of applications that might
+ use them.
+
+6.1. Equivalence
+
+ Because URIs exist to identify resources, presumably they should be
+ considered equivalent when they identify the same resource. However,
+ this definition of equivalence is not of much practical use, as there
+ is no way for an implementation to compare two resources unless it
+ has full knowledge or control of them. For this reason,
+ determination of equivalence or difference of URIs is based on string
+ comparison, perhaps augmented by reference to additional rules
+ provided by URI scheme definitions. We use the terms "different" and
+ "equivalent" to describe the possible outcomes of such comparisons,
+ but there are many application-dependent versions of equivalence.
+
+ Even though it is possible to determine that two URIs are equivalent,
+ URI comparison is not sufficient to determine whether two URIs
+ identify different resources. For example, an owner of two different
+ domain names could decide to serve the same resource from both,
+ resulting in two different URIs. Therefore, comparison methods are
+ designed to minimize false negatives while strictly avoiding false
+ positives.
+
+ In testing for equivalence, applications should not directly compare
+ relative references; the references should be converted to their
+ respective target URIs before comparison. When URIs are compared to
+ select (or avoid) a network action, such as retrieval of a
+ representation, fragment components (if any) should be excluded from
+ the comparison.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 38]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6.2. Comparison Ladder
+
+ A variety of methods are used in practice to test URI equivalence.
+ These methods fall into a range, distinguished by the amount of
+ processing required and the degree to which the probability of false
+ negatives is reduced. As noted above, false negatives cannot be
+ eliminated. In practice, their probability can be reduced, but this
+ reduction requires more processing and is not cost-effective for all
+ applications.
+
+ If this range of comparison practices is considered as a ladder, the
+ following discussion will climb the ladder, starting with practices
+ that are cheap but have a relatively higher chance of producing false
+ negatives, and proceeding to those that have higher computational
+ cost and lower risk of false negatives.
+
+6.2.1. Simple String Comparison
+
+ If two URIs, when considered as character strings, are identical,
+ then it is safe to conclude that they are equivalent. This type of
+ equivalence test has very low computational cost and is in wide use
+ in a variety of applications, particularly in the domain of parsing.
+
+ Testing strings for equivalence requires some basic precautions.
+ This procedure is often referred to as "bit-for-bit" or
+ "byte-for-byte" comparison, which is potentially misleading. Testing
+ strings for equality is normally based on pair comparison of the
+ characters that make up the strings, starting from the first and
+ proceeding until both strings are exhausted and all characters are
+ found to be equal, until a pair of characters compares unequal, or
+ until one of the strings is exhausted before the other.
+
+ This character comparison requires that each pair of characters be
+ put in comparable form. For example, should one URI be stored in a
+ byte array in EBCDIC encoding and the second in a Java String object
+ (UTF-16), bit-for-bit comparisons applied naively will produce
+ errors. It is better to speak of equality on a character-for-
+ character basis rather than on a byte-for-byte or bit-for-bit basis.
+ In practical terms, character-by-character comparisons should be done
+ codepoint-by-codepoint after conversion to a common character
+ encoding.
+
+ False negatives are caused by the production and use of URI aliases.
+ Unnecessary aliases can be reduced, regardless of the comparison
+ method, by consistently providing URI references in an already-
+ normalized form (i.e., a form identical to what would be produced
+ after normalization is applied, as described below).
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 39]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Protocols and data formats often limit some URI comparisons to simple
+ string comparison, based on the theory that people and
+ implementations will, in their own best interest, be consistent in
+ providing URI references, or at least consistent enough to negate any
+ efficiency that might be obtained from further normalization.
+
+6.2.2. Syntax-Based Normalization
+
+ Implementations may use logic based on the definitions provided by
+ this specification to reduce the probability of false negatives.
+ This processing is moderately higher in cost than character-for-
+ character string comparison. For example, an application using this
+ approach could reasonably consider the following two URIs equivalent:
+
+ example://a/b/c/%7Bfoo%7D
+ eXAMPLE://a/./b/../b/%63/%7bfoo%7d
+
+ Web user agents, such as browsers, typically apply this type of URI
+ normalization when determining whether a cached response is
+ available. Syntax-based normalization includes such techniques as
+ case normalization, percent-encoding normalization, and removal of
+ dot-segments.
+
+6.2.2.1. Case Normalization
+
+ For all URIs, the hexadecimal digits within a percent-encoding
+ triplet (e.g., "%3a" versus "%3A") are case-insensitive and therefore
+ should be normalized to use uppercase letters for the digits A-F.
+
+ When a URI uses components of the generic syntax, the component
+ syntax equivalence rules always apply; namely, that the scheme and
+ host are case-insensitive and therefore should be normalized to
+ lowercase. For example, the URI <HTTP://www.EXAMPLE.com/> is
+ equivalent to <http://www.example.com/>. The other generic syntax
+ components are assumed to be case-sensitive unless specifically
+ defined otherwise by the scheme (see Section 6.2.3).
+
+6.2.2.2. Percent-Encoding Normalization
+
+ The percent-encoding mechanism (Section 2.1) is a frequent source of
+ variance among otherwise identical URIs. In addition to the case
+ normalization issue noted above, some URI producers percent-encode
+ octets that do not require percent-encoding, resulting in URIs that
+ are equivalent to their non-encoded counterparts. These URIs should
+ be normalized by decoding any percent-encoded octet that corresponds
+ to an unreserved character, as described in Section 2.3.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 40]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6.2.2.3. Path Segment Normalization
+
+ The complete path segments "." and ".." are intended only for use
+ within relative references (Section 4.1) and are removed as part of
+ the reference resolution process (Section 5.2). However, some
+ deployed implementations incorrectly assume that reference resolution
+ is not necessary when the reference is already a URI and thus fail to
+ remove dot-segments when they occur in non-relative paths. URI
+ normalizers should remove dot-segments by applying the
+ remove_dot_segments algorithm to the path, as described in
+ Section 5.2.4.
+
+6.2.3. Scheme-Based Normalization
+
+ The syntax and semantics of URIs vary from scheme to scheme, as
+ described by the defining specification for each scheme.
+ Implementations may use scheme-specific rules, at further processing
+ cost, to reduce the probability of false negatives. For example,
+ because the "http" scheme makes use of an authority component, has a
+ default port of "80", and defines an empty path to be equivalent to
+ "/", the following four URIs are equivalent:
+
+ http://example.com
+ http://example.com/
+ http://example.com:/
+ http://example.com:80/
+
+ In general, a URI that uses the generic syntax for authority with an
+ empty path should be normalized to a path of "/". Likewise, an
+ explicit ":port", for which the port is empty or the default for the
+ scheme, is equivalent to one where the port and its ":" delimiter are
+ elided and thus should be removed by scheme-based normalization. For
+ example, the second URI above is the normal form for the "http"
+ scheme.
+
+ Another case where normalization varies by scheme is in the handling
+ of an empty authority component or empty host subcomponent. For many
+ scheme specifications, an empty authority or host is considered an
+ error; for others, it is considered equivalent to "localhost" or the
+ end-user's host. When a scheme defines a default for authority and a
+ URI reference to that default is desired, the reference should be
+ normalized to an empty authority for the sake of uniformity, brevity,
+ and internationalization. If, however, either the userinfo or port
+ subcomponents are non-empty, then the host should be given explicitly
+ even if it matches the default.
+
+ Normalization should not remove delimiters when their associated
+ component is empty unless licensed to do so by the scheme
+
+
+
+Berners-Lee, et al. Standards Track [Page 41]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ specification. For example, the URI "http://example.com/?" cannot be
+ assumed to be equivalent to any of the examples above. Likewise, the
+ presence or absence of delimiters within a userinfo subcomponent is
+ usually significant to its interpretation. The fragment component is
+ not subject to any scheme-based normalization; thus, two URIs that
+ differ only by the suffix "#" are considered different regardless of
+ the scheme.
+
+ Some schemes define additional subcomponents that consist of case-
+ insensitive data, giving an implicit license to normalizers to
+ convert this data to a common case (e.g., all lowercase). For
+ example, URI schemes that define a subcomponent of path to contain an
+ Internet hostname, such as the "mailto" URI scheme, cause that
+ subcomponent to be case-insensitive and thus subject to case
+ normalization (e.g., "mailto:[email protected]" is equivalent to
+ "mailto:[email protected]", even though the generic syntax considers
+ the path component to be case-sensitive).
+
+ Other scheme-specific normalizations are possible.
+
+6.2.4. Protocol-Based Normalization
+
+ Substantial effort to reduce the incidence of false negatives is
+ often cost-effective for web spiders. Therefore, they implement even
+ more aggressive techniques in URI comparison. For example, if they
+ observe that a URI such as
+
+ http://example.com/data
+
+ redirects to a URI differing only in the trailing slash
+
+ http://example.com/data/
+
+ they will likely regard the two as equivalent in the future. This
+ kind of technique is only appropriate when equivalence is clearly
+ indicated by both the result of accessing the resources and the
+ common conventions of their scheme's dereference algorithm (in this
+ case, use of redirection by HTTP origin servers to avoid problems
+ with relative references).
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 42]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+7. Security Considerations
+
+ A URI does not in itself pose a security threat. However, as URIs
+ are often used to provide a compact set of instructions for access to
+ network resources, care must be taken to properly interpret the data
+ within a URI, to prevent that data from causing unintended access,
+ and to avoid including data that should not be revealed in plain
+ text.
+
+7.1. Reliability and Consistency
+
+ There is no guarantee that once a URI has been used to retrieve
+ information, the same information will be retrievable by that URI in
+ the future. Nor is there any guarantee that the information
+ retrievable via that URI in the future will be observably similar to
+ that retrieved in the past. The URI syntax does not constrain how a
+ given scheme or authority apportions its namespace or maintains it
+ over time. Such guarantees can only be obtained from the person(s)
+ controlling that namespace and the resource in question. A specific
+ URI scheme may define additional semantics, such as name persistence,
+ if those semantics are required of all naming authorities for that
+ scheme.
+
+7.2. Malicious Construction
+
+ It is sometimes possible to construct a URI so that an attempt to
+ perform a seemingly harmless, idempotent operation, such as the
+ retrieval of a representation, will in fact cause a possibly damaging
+ remote operation. The unsafe URI is typically constructed by
+ specifying a port number other than that reserved for the network
+ protocol in question. The client unwittingly contacts a site running
+ a different protocol service, and data within the URI contains
+ instructions that, when interpreted according to this other protocol,
+ cause an unexpected operation. A frequent example of such abuse has
+ been the use of a protocol-based scheme with a port component of
+ "25", thereby fooling user agent software into sending an unintended
+ or impersonating message via an SMTP server.
+
+ Applications should prevent dereference of a URI that specifies a TCP
+ port number within the "well-known port" range (0 - 1023) unless the
+ protocol being used to dereference that URI is compatible with the
+ protocol expected on that well-known port. Although IANA maintains a
+ registry of well-known ports, applications should make such
+ restrictions user-configurable to avoid preventing the deployment of
+ new services.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 43]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ When a URI contains percent-encoded octets that match the delimiters
+ for a given resolution or dereference protocol (for example, CR and
+ LF characters for the TELNET protocol), these percent-encodings must
+ not be decoded before transmission across that protocol. Transfer of
+ the percent-encoding, which might violate the protocol, is less
+ harmful than allowing decoded octets to be interpreted as additional
+ operations or parameters, perhaps triggering an unexpected and
+ possibly harmful remote operation.
+
+7.3. Back-End Transcoding
+
+ When a URI is dereferenced, the data within it is often parsed by
+ both the user agent and one or more servers. In HTTP, for example, a
+ typical user agent will parse a URI into its five major components,
+ access the authority's server, and send it the data within the
+ authority, path, and query components. A typical server will take
+ that information, parse the path into segments and the query into
+ key/value pairs, and then invoke implementation-specific handlers to
+ respond to the request. As a result, a common security concern for
+ server implementations that handle a URI, either as a whole or split
+ into separate components, is proper interpretation of the octet data
+ represented by the characters and percent-encodings within that URI.
+
+ Percent-encoded octets must be decoded at some point during the
+ dereference process. Applications must split the URI into its
+ components and subcomponents prior to decoding the octets, as
+ otherwise the decoded octets might be mistaken for delimiters.
+ Security checks of the data within a URI should be applied after
+ decoding the octets. Note, however, that the "%00" percent-encoding
+ (NUL) may require special handling and should be rejected if the
+ application is not expecting to receive raw data within a component.
+
+ Special care should be taken when the URI path interpretation process
+ involves the use of a back-end file system or related system
+ functions. File systems typically assign an operational meaning to
+ special characters, such as the "/", "\", ":", "[", and "]"
+ characters, and to special device names like ".", "..", "...", "aux",
+ "lpt", etc. In some cases, merely testing for the existence of such
+ a name will cause the operating system to pause or invoke unrelated
+ system calls, leading to significant security concerns regarding
+ denial of service and unintended data transfer. It would be
+ impossible for this specification to list all such significant
+ characters and device names. Implementers should research the
+ reserved names and characters for the types of storage device that
+ may be attached to their applications and restrict the use of data
+ obtained from URI components accordingly.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 44]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+7.4. Rare IP Address Formats
+
+ Although the URI syntax for IPv4address only allows the common
+ dotted-decimal form of IPv4 address literal, many implementations
+ that process URIs make use of platform-dependent system routines,
+ such as gethostbyname() and inet_aton(), to translate the string
+ literal to an actual IP address. Unfortunately, such system routines
+ often allow and process a much larger set of formats than those
+ described in Section 3.2.2.
+
+ For example, many implementations allow dotted forms of three
+ numbers, wherein the last part is interpreted as a 16-bit quantity
+ and placed in the right-most two bytes of the network address (e.g.,
+ a Class B network). Likewise, a dotted form of two numbers means
+ that the last part is interpreted as a 24-bit quantity and placed in
+ the right-most three bytes of the network address (Class A), and a
+ single number (without dots) is interpreted as a 32-bit quantity and
+ stored directly in the network address. Adding further to the
+ confusion, some implementations allow each dotted part to be
+ interpreted as decimal, octal, or hexadecimal, as specified in the C
+ language (i.e., a leading 0x or 0X implies hexadecimal; a leading 0
+ implies octal; otherwise, the number is interpreted as decimal).
+
+ These additional IP address formats are not allowed in the URI syntax
+ due to differences between platform implementations. However, they
+ can become a security concern if an application attempts to filter
+ access to resources based on the IP address in string literal format.
+ If this filtering is performed, literals should be converted to
+ numeric form and filtered based on the numeric value, and not on a
+ prefix or suffix of the string form.
+
+7.5. Sensitive Information
+
+ URI producers should not provide a URI that contains a username or
+ password that is intended to be secret. URIs are frequently
+ displayed by browsers, stored in clear text bookmarks, and logged by
+ user agent history and intermediary applications (proxies). A
+ password appearing within the userinfo component is deprecated and
+ should be considered an error (or simply ignored) except in those
+ rare cases where the 'password' parameter is intended to be public.
+
+7.6. Semantic Attacks
+
+ Because the userinfo subcomponent is rarely used and appears before
+ the host in the authority component, it can be used to construct a
+ URI intended to mislead a human user by appearing to identify one
+ (trusted) naming authority while actually identifying a different
+ authority hidden behind the noise. For example
+
+
+
+Berners-Lee, et al. Standards Track [Page 45]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ ftp://cnn.example.com&[email protected]/top_story.htm
+
+ might lead a human user to assume that the host is 'cnn.example.com',
+ whereas it is actually '10.0.0.1'. Note that a misleading userinfo
+ subcomponent could be much longer than the example above.
+
+ A misleading URI, such as that above, is an attack on the user's
+ preconceived notions about the meaning of a URI rather than an attack
+ on the software itself. User agents may be able to reduce the impact
+ of such attacks by distinguishing the various components of the URI
+ when they are rendered, such as by using a different color or tone to
+ render userinfo if any is present, though there is no panacea. More
+ information on URI-based semantic attacks can be found in [Siedzik].
+
+8. IANA Considerations
+
+ URI scheme names, as defined by <scheme> in Section 3.1, form a
+ registered namespace that is managed by IANA according to the
+ procedures defined in [BCP35]. No IANA actions are required by this
+ document.
+
+9. Acknowledgements
+
+ This specification is derived from RFC 2396 [RFC2396], RFC 1808
+ [RFC1808], and RFC 1738 [RFC1738]; the acknowledgements in those
+ documents still apply. It also incorporates the update (with
+ corrections) for IPv6 literals in the host syntax, as defined by
+ Robert M. Hinden, Brian E. Carpenter, and Larry Masinter in
+ [RFC2732]. In addition, contributions by Gisle Aas, Reese Anschultz,
+ Daniel Barclay, Tim Bray, Mike Brown, Rob Cameron, Jeremy Carroll,
+ Dan Connolly, Adam M. Costello, John Cowan, Jason Diamond, Martin
+ Duerst, Stefan Eissing, Clive D.W. Feather, Al Gilman, Tony Hammond,
+ Elliotte Harold, Pat Hayes, Henry Holtzman, Ian B. Jacobs, Michael
+ Kay, John C. Klensin, Graham Klyne, Dan Kohn, Bruce Lilly, Andrew
+ Main, Dave McAlpin, Ira McDonald, Michael Mealling, Ray Merkert,
+ Stephen Pollei, Julian Reschke, Tomas Rokicki, Miles Sabin, Kai
+ Schaetzl, Mark Thomson, Ronald Tschalaer, Norm Walsh, Marc Warne,
+ Stuart Williams, and Henry Zongaro are gratefully acknowledged.
+
+10. References
+
+10.1. Normative References
+
+ [ASCII] American National Standards Institute, "Coded Character
+ Set -- 7-bit American Standard Code for Information
+ Interchange", ANSI X3.4, 1986.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 46]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ [RFC2234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [STD63] Yergeau, F., "UTF-8, a transformation format of
+ ISO 10646", STD 63, RFC 3629, November 2003.
+
+ [UCS] International Organization for Standardization,
+ "Information Technology - Universal Multiple-Octet Coded
+ Character Set (UCS)", ISO/IEC 10646:2003, December 2003.
+
+10.2. Informative References
+
+ [BCP19] Freed, N. and J. Postel, "IANA Charset Registration
+ Procedures", BCP 19, RFC 2978, October 2000.
+
+ [BCP35] Petke, R. and I. King, "Registration Procedures for URL
+ Scheme Names", BCP 35, RFC 2717, November 1999.
+
+ [RFC0952] Harrenstien, K., Stahl, M., and E. Feinler, "DoD Internet
+ host table specification", RFC 952, October 1985.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC1535] Gavron, E., "A Security Problem and Proposed Correction
+ With Widely Deployed DNS Software", RFC 1535,
+ October 1993.
+
+ [RFC1630] Berners-Lee, T., "Universal Resource Identifiers in WWW: A
+ Unifying Syntax for the Expression of Names and Addresses
+ of Objects on the Network as used in the World-Wide Web",
+ RFC 1630, June 1994.
+
+ [RFC1736] Kunze, J., "Functional Recommendations for Internet
+ Resource Locators", RFC 1736, February 1995.
+
+ [RFC1737] Sollins, K. and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", RFC 1737, December 1994.
+
+ [RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RFC1808] Fielding, R., "Relative Uniform Resource Locators",
+ RFC 1808, June 1995.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 47]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+ [RFC2141] Moats, R., "URN Syntax", RFC 2141, May 1997.
+
+ [RFC2396] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2518] Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D.
+ Jensen, "HTTP Extensions for Distributed Authoring --
+ WEBDAV", RFC 2518, February 1999.
+
+ [RFC2557] Palme, J., Hopmann, A., and N. Shelness, "MIME
+ Encapsulation of Aggregate Documents, such as HTML
+ (MHTML)", RFC 2557, March 1999.
+
+ [RFC2718] Masinter, L., Alvestrand, H., Zigmond, D., and R. Petke,
+ "Guidelines for new URL Schemes", RFC 2718, November 1999.
+
+ [RFC2732] Hinden, R., Carpenter, B., and L. Masinter, "Format for
+ Literal IPv6 Addresses in URL's", RFC 2732, December 1999.
+
+ [RFC3305] Mealling, M. and R. Denenberg, "Report from the Joint
+ W3C/IETF URI Planning Interest Group: Uniform Resource
+ Identifiers (URIs), URLs, and Uniform Resource Names
+ (URNs): Clarifications and Recommendations", RFC 3305,
+ August 2002.
+
+ [RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications (IDNA)",
+ RFC 3490, March 2003.
+
+ [RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [Siedzik] Siedzik, R., "Semantic Attacks: What's in a URL?",
+ April 2001, <http://www.giac.org/practical/gsec/
+ Richard_Siedzik_GSEC.pdf>.
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 48]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Appendix A. Collected ABNF for URI
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ URI-reference = URI / relative-ref
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ host = IP-literal / IPv4address / reg-name
+ port = *DIGIT
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ h16 = 1*4HEXDIG
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 49]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ query = *( pchar / "/" / "?" )
+
+ fragment = *( pchar / "/" / "?" )
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ reserved = gen-delims / sub-delims
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+Appendix B. Parsing a URI Reference with a Regular Expression
+
+ As the "first-match-wins" algorithm is identical to the "greedy"
+ disambiguation method used by POSIX regular expressions, it is
+ natural and commonplace to use a regular expression for parsing the
+ potential five components of a URI reference.
+
+ The following line is the regular expression for breaking-down a
+ well-formed URI reference into its components.
+
+
+
+Berners-Lee, et al. Standards Track [Page 50]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+ 12 3 4 5 6 7 8 9
+
+ The numbers in the second line above are only to assist readability;
+ they indicate the reference points for each subexpression (i.e., each
+ paired parenthesis). We refer to the value matched for subexpression
+ <n> as $<n>. For example, matching the above expression to
+
+ http://www.ics.uci.edu/pub/ietf/uri/#Related
+
+ results in the following subexpression matches:
+
+ $1 = http:
+ $2 = http
+ $3 = //www.ics.uci.edu
+ $4 = www.ics.uci.edu
+ $5 = /pub/ietf/uri/
+ $6 = <undefined>
+ $7 = <undefined>
+ $8 = #Related
+ $9 = Related
+
+ where <undefined> indicates that the component is not present, as is
+ the case for the query component in the above example. Therefore, we
+ can determine the value of the five components as
+
+ scheme = $2
+ authority = $4
+ path = $5
+ query = $7
+ fragment = $9
+
+ Going in the opposite direction, we can recreate a URI reference from
+ its components by using the algorithm of Section 5.3.
+
+Appendix C. Delimiting a URI in Context
+
+ URIs are often transmitted through formats that do not provide a
+ clear context for their interpretation. For example, there are many
+ occasions when a URI is included in plain text; examples include text
+ sent in email, USENET news, and on printed paper. In such cases, it
+ is important to be able to delimit the URI from the rest of the text,
+ and in particular from punctuation marks that might be mistaken for
+ part of the URI.
+
+ In practice, URIs are delimited in a variety of ways, but usually
+ within double-quotes "http://example.com/", angle brackets
+ <http://example.com/>, or just by using whitespace:
+
+
+
+Berners-Lee, et al. Standards Track [Page 51]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ http://example.com/
+
+ These wrappers do not form part of the URI.
+
+ In some cases, extra whitespace (spaces, line-breaks, tabs, etc.) may
+ have to be added to break a long URI across lines. The whitespace
+ should be ignored when the URI is extracted.
+
+ No whitespace should be introduced after a hyphen ("-") character.
+ Because some typesetters and printers may (erroneously) introduce a
+ hyphen at the end of line when breaking it, the interpreter of a URI
+ containing a line break immediately after a hyphen should ignore all
+ whitespace around the line break and should be aware that the hyphen
+ may or may not actually be part of the URI.
+
+ Using <> angle brackets around each URI is especially recommended as
+ a delimiting style for a reference that contains embedded whitespace.
+
+ The prefix "URL:" (with or without a trailing space) was formerly
+ recommended as a way to help distinguish a URI from other bracketed
+ designators, though it is not commonly used in practice and is no
+ longer recommended.
+
+ For robustness, software that accepts user-typed URI should attempt
+ to recognize and strip both delimiters and embedded whitespace.
+
+ For example, the text
+
+ Yes, Jim, I found it under "http://www.w3.org/Addressing/",
+ but you can probably pick it up from <ftp://foo.example.
+ com/rfc/>. Note the warning in <http://www.ics.uci.edu/pub/
+ ietf/uri/historical.html#WARNING>.
+
+ contains the URI references
+
+ http://www.w3.org/Addressing/
+ ftp://foo.example.com/rfc/
+ http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 52]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Appendix D. Changes from RFC 2396
+
+D.1. Additions
+
+ An ABNF rule for URI has been introduced to correspond to one common
+ usage of the term: an absolute URI with optional fragment.
+
+ IPv6 (and later) literals have been added to the list of possible
+ identifiers for the host portion of an authority component, as
+ described by [RFC2732], with the addition of "[" and "]" to the
+ reserved set and a version flag to anticipate future versions of IP
+ literals. Square brackets are now specified as reserved within the
+ authority component and are not allowed outside their use as
+ delimiters for an IP literal within host. In order to make this
+ change without changing the technical definition of the path, query,
+ and fragment components, those rules were redefined to directly
+ specify the characters allowed.
+
+ As [RFC2732] defers to [RFC3513] for definition of an IPv6 literal
+ address, which, unfortunately, lacks an ABNF description of
+ IPv6address, we created a new ABNF rule for IPv6address that matches
+ the text representations defined by Section 2.2 of [RFC3513].
+ Likewise, the definition of IPv4address has been improved in order to
+ limit each decimal octet to the range 0-255.
+
+ Section 6, on URI normalization and comparison, has been completely
+ rewritten and extended by using input from Tim Bray and discussion
+ within the W3C Technical Architecture Group.
+
+D.2. Modifications
+
+ The ad-hoc BNF syntax of RFC 2396 has been replaced with the ABNF of
+ [RFC2234]. This change required all rule names that formerly
+ included underscore characters to be renamed with a dash instead. In
+ addition, a number of syntax rules have been eliminated or simplified
+ to make the overall grammar more comprehensible. Specifications that
+ refer to the obsolete grammar rules may be understood by replacing
+ those rules according to the following table:
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 53]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ +----------------+--------------------------------------------------+
+ | obsolete rule | translation |
+ +----------------+--------------------------------------------------+
+ | absoluteURI | absolute-URI |
+ | relativeURI | relative-part [ "?" query ] |
+ | hier_part | ( "//" authority path-abempty / |
+ | | path-absolute ) [ "?" query ] |
+ | | |
+ | opaque_part | path-rootless [ "?" query ] |
+ | net_path | "//" authority path-abempty |
+ | abs_path | path-absolute |
+ | rel_path | path-rootless |
+ | rel_segment | segment-nz-nc |
+ | reg_name | reg-name |
+ | server | authority |
+ | hostport | host [ ":" port ] |
+ | hostname | reg-name |
+ | path_segments | path-abempty |
+ | param | *<pchar excluding ";"> |
+ | | |
+ | uric | unreserved / pct-encoded / ";" / "?" / ":" |
+ | | / "@" / "&" / "=" / "+" / "$" / "," / "/" |
+ | | |
+ | uric_no_slash | unreserved / pct-encoded / ";" / "?" / ":" |
+ | | / "@" / "&" / "=" / "+" / "$" / "," |
+ | | |
+ | mark | "-" / "_" / "." / "!" / "~" / "*" / "'" |
+ | | / "(" / ")" |
+ | | |
+ | escaped | pct-encoded |
+ | hex | HEXDIG |
+ | alphanum | ALPHA / DIGIT |
+ +----------------+--------------------------------------------------+
+
+ Use of the above obsolete rules for the definition of scheme-specific
+ syntax is deprecated.
+
+ Section 2, on characters, has been rewritten to explain what
+ characters are reserved, when they are reserved, and why they are
+ reserved, even when they are not used as delimiters by the generic
+ syntax. The mark characters that are typically unsafe to decode,
+ including the exclamation mark ("!"), asterisk ("*"), single-quote
+ ("'"), and open and close parentheses ("(" and ")"), have been moved
+ to the reserved set in order to clarify the distinction between
+ reserved and unreserved and, hopefully, to answer the most common
+ question of scheme designers. Likewise, the section on
+ percent-encoded characters has been rewritten, and URI normalizers
+ are now given license to decode any percent-encoded octets
+
+
+
+Berners-Lee, et al. Standards Track [Page 54]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ corresponding to unreserved characters. In general, the terms
+ "escaped" and "unescaped" have been replaced with "percent-encoded"
+ and "decoded", respectively, to reduce confusion with other forms of
+ escape mechanisms.
+
+ The ABNF for URI and URI-reference has been redesigned to make them
+ more friendly to LALR parsers and to reduce complexity. As a result,
+ the layout form of syntax description has been removed, along with
+ the uric, uric_no_slash, opaque_part, net_path, abs_path, rel_path,
+ path_segments, rel_segment, and mark rules. All references to
+ "opaque" URIs have been replaced with a better description of how the
+ path component may be opaque to hierarchy. The relativeURI rule has
+ been replaced with relative-ref to avoid unnecessary confusion over
+ whether they are a subset of URI. The ambiguity regarding the
+ parsing of URI-reference as a URI or a relative-ref with a colon in
+ the first segment has been eliminated through the use of five
+ separate path matching rules.
+
+ The fragment identifier has been moved back into the section on
+ generic syntax components and within the URI and relative-ref rules,
+ though it remains excluded from absolute-URI. The number sign ("#")
+ character has been moved back to the reserved set as a result of
+ reintegrating the fragment syntax.
+
+ The ABNF has been corrected to allow the path component to be empty.
+ This also allows an absolute-URI to consist of nothing after the
+ "scheme:", as is present in practice with the "dav:" namespace
+ [RFC2518] and with the "about:" scheme used internally by many WWW
+ browser implementations. The ambiguity regarding the boundary
+ between authority and path has been eliminated through the use of
+ five separate path matching rules.
+
+ Registry-based naming authorities that use the generic syntax are now
+ defined within the host rule. This change allows current
+ implementations, where whatever name provided is simply fed to the
+ local name resolution mechanism, to be consistent with the
+ specification. It also removes the need to re-specify DNS name
+ formats here. Furthermore, it allows the host component to contain
+ percent-encoded octets, which is necessary to enable
+ internationalized domain names to be provided in URIs, processed in
+ their native character encodings at the application layers above URI
+ processing, and passed to an IDNA library as a registered name in the
+ UTF-8 character encoding. The server, hostport, hostname,
+ domainlabel, toplabel, and alphanum rules have been removed.
+
+ The resolving relative references algorithm of [RFC2396] has been
+ rewritten with pseudocode for this revision to improve clarity and
+ fix the following issues:
+
+
+
+Berners-Lee, et al. Standards Track [Page 55]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ o [RFC2396] section 5.2, step 6a, failed to account for a base URI
+ with no path.
+
+ o Restored the behavior of [RFC1808] where, if the reference
+ contains an empty path and a defined query component, the target
+ URI inherits the base URI's path component.
+
+ o The determination of whether a URI reference is a same-document
+ reference has been decoupled from the URI parser, simplifying the
+ URI processing interface within applications in a way consistent
+ with the internal architecture of deployed URI processing
+ implementations. The determination is now based on comparison to
+ the base URI after transforming a reference to absolute form,
+ rather than on the format of the reference itself. This change
+ may result in more references being considered "same-document"
+ under this specification than there would be under the rules given
+ in RFC 2396, especially when normalization is used to reduce
+ aliases. However, it does not change the status of existing
+ same-document references.
+
+ o Separated the path merge routine into two routines: merge, for
+ describing combination of the base URI path with a relative-path
+ reference, and remove_dot_segments, for describing how to remove
+ the special "." and ".." segments from a composed path. The
+ remove_dot_segments algorithm is now applied to all URI reference
+ paths in order to match common implementations and to improve the
+ normalization of URIs in practice. This change only impacts the
+ parsing of abnormal references and same-scheme references wherein
+ the base URI has a non-hierarchical path.
+
+Index
+
+ A
+ ABNF 11
+ absolute 27
+ absolute-path 26
+ absolute-URI 27
+ access 9
+ authority 17, 18
+
+ B
+ base URI 28
+
+ C
+ character encoding 4
+ character 4
+ characters 8, 11
+ coded character set 4
+
+
+
+Berners-Lee, et al. Standards Track [Page 56]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ D
+ dec-octet 20
+ dereference 9
+ dot-segments 23
+
+ F
+ fragment 16, 24
+
+ G
+ gen-delims 13
+ generic syntax 6
+
+ H
+ h16 20
+ hier-part 16
+ hierarchical 10
+ host 18
+
+ I
+ identifier 5
+ IP-literal 19
+ IPv4 20
+ IPv4address 19, 20
+ IPv6 19
+ IPv6address 19, 20
+ IPvFuture 19
+
+ L
+ locator 7
+ ls32 20
+
+ M
+ merge 32
+
+ N
+ name 7
+ network-path 26
+
+ P
+ path 16, 22, 26
+ path-abempty 22
+ path-absolute 22
+ path-empty 22
+ path-noscheme 22
+ path-rootless 22
+ path-abempty 16, 22, 26
+ path-absolute 16, 22, 26
+ path-empty 16, 22, 26
+
+
+
+Berners-Lee, et al. Standards Track [Page 57]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ path-rootless 16, 22
+ pchar 23
+ pct-encoded 12
+ percent-encoding 12
+ port 22
+
+ Q
+ query 16, 23
+
+ R
+ reg-name 21
+ registered name 20
+ relative 10, 28
+ relative-path 26
+ relative-ref 26
+ remove_dot_segments 33
+ representation 9
+ reserved 12
+ resolution 9, 28
+ resource 5
+ retrieval 9
+
+ S
+ same-document 27
+ sameness 9
+ scheme 16, 17
+ segment 22, 23
+ segment-nz 23
+ segment-nz-nc 23
+ sub-delims 13
+ suffix 27
+
+ T
+ transcription 8
+
+ U
+ uniform 4
+ unreserved 13
+ URI grammar
+ absolute-URI 27
+ ALPHA 11
+ authority 18
+ CR 11
+ dec-octet 20
+ DIGIT 11
+ DQUOTE 11
+ fragment 24
+ gen-delims 13
+
+
+
+Berners-Lee, et al. Standards Track [Page 58]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ h16 20
+ HEXDIG 11
+ hier-part 16
+ host 19
+ IP-literal 19
+ IPv4address 20
+ IPv6address 20
+ IPvFuture 19
+ LF 11
+ ls32 20
+ OCTET 11
+ path 22
+ path-abempty 22
+ path-absolute 22
+ path-empty 22
+ path-noscheme 22
+ path-rootless 22
+ pchar 23
+ pct-encoded 12
+ port 22
+ query 24
+ reg-name 21
+ relative-ref 26
+ reserved 13
+ scheme 17
+ segment 23
+ segment-nz 23
+ segment-nz-nc 23
+ SP 11
+ sub-delims 13
+ unreserved 13
+ URI 16
+ URI-reference 25
+ userinfo 18
+ URI 16
+ URI-reference 25
+ URL 7
+ URN 7
+ userinfo 18
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 59]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Authors' Addresses
+
+ Tim Berners-Lee
+ World Wide Web Consortium
+ Massachusetts Institute of Technology
+ 77 Massachusetts Avenue
+ Cambridge, MA 02139
+ USA
+
+ Phone: +1-617-253-5702
+ Fax: +1-617-258-5999
+ URI: http://www.w3.org/People/Berners-Lee/
+
+
+ Roy T. Fielding
+ Day Software
+ 5251 California Ave., Suite 110
+ Irvine, CA 92617
+ USA
+
+ Phone: +1-949-679-2960
+ Fax: +1-949-679-2972
+ URI: http://roy.gbiv.com/
+
+
+ Larry Masinter
+ Adobe Systems Incorporated
+ 345 Park Ave
+ San Jose, CA 95110
+ USA
+
+ Phone: +1-408-536-3024
+ URI: http://larry.masinter.net/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 60]
+
+RFC 3986 URI Generic Syntax January 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 IETF's procedures with respect to rights in IETF 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.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 61]
+
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index e4cb0c4e48..1a8e1c7ca8 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The 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,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
VSN=$(INETS_VSN)
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -58,6 +48,7 @@ XML_REF3_FILES = \
inets.xml \
ftp.xml \
tftp.xml \
+ http_uri.xml\
httpc.xml\
httpd.xml \
httpd_conf.xml \
@@ -98,37 +89,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = \
- $(XML_PART_FILES:%.xml=%.tex) \
- $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_REF6_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-TOP_HTML_FILES =
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -141,8 +105,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
ldocs: local_docs
@@ -156,33 +118,6 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(TOP_HTML_FILES) gifs
-
-clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
-
-clean: clean_tex clean_html clean_man
- rm -f *.xmls_output *.xmls_errs
- rm -f $(TOP_PDF_FILE)
- rm -f errs core *~
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -204,44 +139,14 @@ clean_man:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
-release_docs_spec: docs
- @echo "release_docs_spec(docs) when DOCSUPPORT=$DOCSUPPORT"
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(HTMLDIR)/* $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- @echo "release_docs_spec(pdf)"
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- @echo "release_docs_spec(ps)"
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
release_docs_spec: docs
- @echo "release_docs_spec(docs)"
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(HTMLDIR)/* "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/inets/doc/src/book.xml b/lib/inets/doc/src/book.xml
index 7da0abd98f..51cbb2d963 100644
--- a/lib/inets/doc/src/book.xml
+++ b/lib/inets/doc/src/book.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE book SYSTEM "book.dtd">
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/fascicules.xml b/lib/inets/doc/src/fascicules.xml
index 101e745722..ea3b988882 100644
--- a/lib/inets/doc/src/fascicules.xml
+++ b/lib/inets/doc/src/fascicules.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
<fascicules>
diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml
index ca902d8d9d..f8f11ec705 100644
--- a/lib/inets/doc/src/ftp.xml
+++ b/lib/inets/doc/src/ftp.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>
@@ -141,11 +141,21 @@
<tag>{timeout, Timeout}</tag>
<item>
<marker id="timeout"></marker>
- <p>Timeout = <c>integer() >= 0</c> </p>
+ <p>Timeout = <c>non_neg_integer()</c> </p>
<p>Connection timeout. </p>
<p>Default is 60000 (milliseconds). </p>
</item>
+ <tag>{dtimeout, DTimeout}</tag>
+ <item>
+ <marker id="dtimeout"></marker>
+ <p>DTimeout = <c>non_neg_integer() | infinity</c> </p>
+ <p>Data Connect timeout.
+ The time the client will wait for the server to connect to the
+ data socket. </p>
+ <p>Default is infinity. </p>
+ </item>
+
<tag>{progress, Progress}</tag>
<item>
<marker id="progress"></marker>
@@ -542,11 +552,12 @@
<v>verbose() = boolean() (defaults to false)</v>
<v>debug() = disable | debug | trace (defaults to disable)</v>
<!-- <v>open_options() = [open_option()]</v> -->
- <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {timeout, timeout()} | {progress, progress()}</v>
+ <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()}</v>
<v>ipfamily() = inet | inet6 | inet6fb4 (defaults to inet)</v>
<v>port() = integer() > 0 (defaults to 21)</v>
<v>mode() = active | passive (defaults to passive)</v>
- <v>timeout() = integer() >= 0 (defaults to 60000 milliseconds)</v>
+ <v>timeout() = integer() > 0 (defaults to 60000 milliseconds)</v>
+ <v>dtimeout() = integer() > 0 | infinity (defaults to infinity)</v>
<v>pogress() = ignore | {module(), function(), initial_data()} (defaults to ignore)</v>
<v>module() = atom()</v>
<v>function() = atom()</v>
diff --git a/lib/inets/doc/src/ftp_client.xml b/lib/inets/doc/src/ftp_client.xml
index 7f62a453a6..b44674d997 100644
--- a/lib/inets/doc/src/ftp_client.xml
+++ b/lib/inets/doc/src/ftp_client.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>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
new file mode 100644
index 0000000000..bd31ae42d2
--- /dev/null
+++ b/lib/inets/doc/src/http_uri.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2012</year><year>2012</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>http_uri</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+
+ <module>http_uri</module>
+ <modulesummary>URI utility module</modulesummary>
+
+ <description>
+ <p>This module provides utility functions for working with URIs,
+ according to RFC 3986. </p>
+
+ </description>
+
+ <section>
+ <title>COMMON DATA TYPES </title>
+ <p>Type definitions that are used more than once in
+ this module:</p>
+ <code type="none"><![CDATA[
+boolean() = true | false
+string() = list of ASCII characters
+ ]]></code>
+
+ </section>
+
+ <section>
+ <title>URI DATA TYPES </title>
+ <p>Type definitions that are related to URI:</p>
+ <p>For more information about URI, see RFC 3986. </p>
+
+ <code type="none"><![CDATA[
+uri() = string() - Syntax according to the URI definition in rfc 3986, ex: "http://www.erlang.org/"
+user_info() = string()
+scheme() = atom() - Example: http, https
+host() = string()
+port() = pos_integer()
+path() = string() - Representing a file path or directory path
+query() = string()
+ ]]></code>
+
+ <marker id="scheme_defaults"></marker>
+ </section>
+
+ <funcs>
+ <func>
+ <name>scheme_defaults() -> SchemeDefaults</name>
+ <fsummary>A list of scheme and their default ports</fsummary>
+ <type>
+ <v>SchemeDefaults = [{scheme(), default_scheme_port_number()}] </v>
+ <v>default_scheme_port_number() = pos_integer()</v>
+ </type>
+ <desc>
+ <p>This function provides a list of the scheme and their default
+ port numbers currently supported (by default) by this utility. </p>
+
+ <marker id="parse"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>parse(URI) -> {ok, Result} | {error, Reason}</name>
+ <name>parse(URI, Options) -> {ok, Result} | {error, Reason}</name>
+ <fsummary>Parse an URI</fsummary>
+ <type>
+ <v>URI = uri() </v>
+ <v>Options = [Option] </v>
+ <v>Option = {ipv6_host_with_brackets, boolean()} |
+ {scheme_defaults, scheme_defaults()}]</v>
+ <v>Result = {Scheme, UserInfo, Host, Port, Path, Query}</v>
+ <v>UserInfo = user_info()</v>
+ <v>Host = host()</v>
+ <v>Port = pos_integer()</v>
+ <v>Path = path()</v>
+ <v>Query = query()</v>
+ <v>Reason = term() </v>
+ </type>
+ <desc>
+ <p>This function is used to parse an URI. If no scheme defaults
+ are provided, the value of
+ <seealso marker="#scheme_defaults">scheme_defaults</seealso>
+ function will be used. </p>
+
+ <p>Note that when parsing an URI with an unknown scheme (that is,
+ a scheme not found in the scheme defaults) a port number must be
+ provided or else the parsing will fail. </p>
+
+ <marker id="encode"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>encode(URI) -> HexEncodedURI</name>
+
+ <fsummary>Hex encode an URI</fsummary>
+ <type>
+ <v>URI = uri()</v>
+ <v>HexEncodedURI = string() - Hex encoded uri</v>
+ </type>
+
+ <desc>
+ <p>Hex encode an URI. </p>
+
+ <marker id="decode"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>decode(HexEncodedURI) -> URI</name>
+
+ <fsummary>Decode a hex encoded URI</fsummary>
+ <type>
+ <v>HexEncodedURI = string() - A possibly hex encoded uri</v>
+ <v>URI = uri()</v>
+ </type>
+
+ <desc>
+ <p>Decode a possibly hex encoded URI. </p>
+
+ </desc>
+ </func>
+
+ </funcs>
+
+<!--
+ <section>
+ <title>SEE ALSO</title>
+ <p>RFC 2616, <seealso marker="inets">inets(3)</seealso>,
+ <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>,
+ <seealso marker="ssl:ssl">ssl(3)</seealso>
+ </p>
+ </section>
+-->
+
+</erlref>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index b1f964ae69..14ce3cbe7f 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2011</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -178,13 +178,14 @@ filename() = string()
<v>timeout() = integer() >= 0 | infinity</v>
<v>Options = options()</v>
<v>options() = [option()]</v>
- <v>option() = {sync, boolean()} |
- {stream, stream_to()} |
- {body_format, body_format()} |
- {full_result, boolean()} |
- {headers_as_is, boolean() |
- {socket_opts, socket_opts()} |
- {receiver, receiver()}}</v>
+ <v>option() = {sync, boolean()} |
+ {stream, stream_to()} |
+ {body_format, body_format()} |
+ {full_result, boolean()} |
+ {headers_as_is, boolean() |
+ {socket_opts, socket_opts()} |
+ {receiver, receiver()},
+ {ipv6_host_with_brackets, boolean()}}</v>
<v>stream_to() = none | self | {self, once} | filename() </v>
<v>socket_opts() = [socket_opt()]</v>
<v>receiver() = pid() | function()/1 | {Module, Function, Args} </v>
@@ -407,7 +408,18 @@ apply(Module, Function, [ReplyInfo | Args])
<p>Defaults to the <c>pid()</c> of the process calling the request
function (<c>self()</c>). </p>
+
+ <marker id="ipv6_host_with_brackets"></marker>
+ </item>
+
+ <tag><c><![CDATA[ipv6_host_with_brackets]]></c></tag>
+ <item>
+ <p>When parsing the Host-Port part of an URI with a IPv6 address
+ with brackets, shall we retain those brackets (<c>true</c>) or
+ strip them (<c>false</c>). </p>
+ <p>Defaults to <c>false</c>. </p>
</item>
+
</taglist>
<marker id="cancel_request"></marker>
@@ -468,66 +480,98 @@ apply(Module, Function, [ReplyInfo | Args])
<d>ex: "134.138" or "[FEDC:BA98" (all IP-addresses starting with 134.138 or FEDC:BA98), "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP-address).</d>
<v>MaxSessions = integer() </v>
<d>Default is <c>2</c>.
- Maximum number of persistent connections to a host.</d>
+ Maximum number of persistent connections to a host.</d>
<v>MaxKeepAlive = integer() </v>
- <d>Default is <c>5</c>.
- Maximum number of outstanding requests on the same connection to
- a host.</d>
- <v>KeepAliveTimeout = integer() </v>
- <d>Default is <c>120000</c> (= 2 min).
- If a persistent connection is idle longer than the
- <c>keep_alive_timeout</c> the client will close the connection.
- The server may also have such a time out but you should
- not count on it!</d>
+ <d>Default is <c>5</c>.
+ Maximum number of outstanding requests on the same connection to
+ a host.</d>
+ <v>KeepAliveTimeout = integer() </v>
+ <d>Default is <c>120000</c> (= 2 min).
+ If a persistent connection is idle longer than the
+ <c>keep_alive_timeout</c> in milliseconds,
+ the client will close the connection.
+ The server may also have such a time out but you should
+ not count on it!</d>
<v>MaxPipeline = integer() </v>
- <d>Default is <c>2</c>.
- Maximum number of outstanding requests on a pipelined connection to a host.</d>
- <v>PipelineTimeout = integer() </v>
- <d>Default is <c>0</c>,
- which will result in pipelining not being used.
- If a persistent connection is idle longer than the
- <c>pipeline_timeout</c> the client will close the connection. </d>
+ <d>Default is <c>2</c>.
+ Maximum number of outstanding requests on a pipelined connection
+ to a host.</d>
+ <v>PipelineTimeout = integer() </v>
+ <d>Default is <c>0</c>,
+ which will result in pipelining not being used.
+ If a persistent connection is idle longer than the
+ <c>pipeline_timeout</c> in milliseconds,
+ the client will close the connection. </d>
<v>CookieMode = enabled | disabled | verify </v>
<d>Default is <c>disabled</c>.
- If Cookies are enabled all valid cookies will automatically be
- saved in the client manager's cookie database.
- If the option <c>verify</c> is used the function <c>store_cookies/2</c>
- has to be called for the cookies to be saved.</d>
- <v>IpFamily = inet | inet6 | inet6fb4 </v>
- <d>By default <c>inet</c>.
- When it is set to <c>inet6fb4</c> you can use both ipv4 and ipv6.
- It first tries <c>inet6</c> and if that does not works falls back to <c>inet</c>.
- The option is here to provide a workaround for buggy ipv6 stacks to ensure that
- ipv4 will always work.</d>
+ If Cookies are enabled all valid cookies will automatically be
+ saved in the client manager's cookie database.
+ If the option <c>verify</c> is used the function <c>store_cookies/2</c>
+ has to be called for the cookies to be saved.</d>
+ <v>IpFamily = inet | inet6 | inet6fb4 </v>
+ <d>By default <c>inet</c>.
+ When it is set to <c>inet6fb4</c> you can use both ipv4 and ipv6.
+ It first tries <c>inet6</c> and if that does not works falls back to <c>inet</c>.
+ The option is here to provide a workaround for buggy ipv6 stacks to ensure that
+ ipv4 will always work.</d>
<v>IpAddress = ip_address() </v>
- <d>If the host has several network interfaces, this option specifies which one to use.
- See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d>
+ <d>If the host has several network interfaces, this option specifies which one to use.
+ See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d>
<v>Port = integer() </v>
- <d>Specify which local port number to use.
- See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d>
- <v>VerboseMode = false | verbose | debug | trace </v>
- <d>Default is <c>false</c>.
- This option is used to switch on (or off)
- different levels of erlang trace on the client.
- It is a debug feature.</d>
+ <d>Specify which local port number to use.
+ See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d>
+ <v>VerboseMode = false | verbose | debug | trace </v>
+ <d>Default is <c>false</c>.
+ This option is used to switch on (or off)
+ different levels of erlang trace on the client.
+ It is a debug feature.</d>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
+ </type>
+ <desc>
+ <p>Sets options to be used for subsequent requests.</p>
+ <note>
+ <p>If possible the client will keep its connections
+ alive and use persistent connections
+ with or without pipeline depending on configuration
+ and current circumstances. The HTTP/1.1 specification does not
+ provide a guideline for how many requests would be
+ ideal to be sent on a persistent connection,
+ this very much depends on the
+ application. Note that a very long queue of requests may cause a
+ user perceived delay as earlier requests may take a long time
+ to complete. The HTTP/1.1 specification does suggest a
+ limit of 2 persistent connections per server, which is the
+ default value of the <c>max_sessions</c> option. </p>
+ </note>
+
+ <marker id="get_options"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>get_options(OptionItems) -> {ok, Values} | {error, Reason}</name>
+ <name>get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}</name>
+ <fsummary>Gets the currently used options.</fsummary>
+ <type>
+ <v>OptionItems = all | [option_item()]</v>
+ <v>option_item() = proxy |
+ max_sessions |
+ keep_alive_timeout |
+ max_keep_alive_length |
+ pipeline_timeout |
+ max_pipeline_length |
+ cookies |
+ ipfamily |
+ ip |
+ port |
+ socket_opts |
+ verbose</v>
<v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
+ <v>Values = [{option_item(), term()}]</v>
+ <v>Reason = term() </v>
</type>
<desc>
- <p>Sets options to be used for subsequent requests.</p>
- <note>
- <p>If possible the client will keep its connections
- alive and use persistent connections
- with or without pipeline depending on configuration
- and current circumstances. The HTTP/1.1 specification does not
- provide a guideline for how many requests would be
- ideal to be sent on a persistent connection,
- this very much depends on the
- application. Note that a very long queue of requests may cause a
- user perceived delay as earlier requests may take a long time
- to complete. The HTTP/1.1 specification does suggest a
- limit of 2 persistent connections per server, which is the
- default value of the <c>max_sessions</c> option. </p>
- </note>
+ <p>Retrieves the options currently used by the client.</p>
<marker id="stream_next"></marker>
</desc>
@@ -572,17 +616,24 @@ apply(Module, Function, [ReplyInfo | Args])
<func>
<name>cookie_header(Url) -> </name>
- <name>cookie_header(Url, Profile) -> header() | {error, Reason}</name>
+ <name>cookie_header(Url, Profile | Opts) -> header() | {error, Reason}</name>
+ <name>cookie_header(Url, Opts, Profile) -> header() | {error, Reason}</name>
<fsummary>Returns the cookie header that would be sent when
making a request to Url using the profile <c>Profile</c>.</fsummary>
<type>
<v>Url = url()</v>
+ <v>Opts = [cookie_header_opt()]</v>
<v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
+ <v>cookie_header_opt() = {ipv6_host_with_brackets, boolean()}</v>
</type>
<desc>
<p>Returns the cookie header that would be sent
when making a request to <c>Url</c> using the profile <c>Profile</c>.
If no profile is specified the default profile will be used. </p>
+ <p>The option <c>ipv6_host_with_bracket</c> deals with how to
+ parse IPv6 addresses.
+ See the <c>Options</c> argument of the
+ <seealso marker="#request2">request/4,5</seealso> for more info. </p>
<marker id="reset_cookies"></marker>
</desc>
@@ -600,6 +651,8 @@ apply(Module, Function, [ReplyInfo | Args])
<p>Resets (clears) the cookie database for the specified
<c>Profile</c>. If no profile is specified the default profile
will be used. </p>
+
+ <marker id="which_cookies"></marker>
</desc>
</func>
@@ -619,6 +672,42 @@ apply(Module, Function, [ReplyInfo | Args])
<p>This function produces a list of the entire cookie database.
It is intended for debugging/testing purposes.
If no profile is specified the default profile will be used. </p>
+
+ <marker id="which_sessions"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>which_sessions() -> session_info()</name>
+ <name>which_sessions(Profile) -> session_info()</name>
+ <fsummary>Produces a slightly processed dump of the sessions database.</fsummary>
+ <type>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
+ <v>session_info() = {GoodSessions, BadSessions, NonSessions}</v>
+ <v>GoodSessions = session()</v>
+ <v>BadSessions = tuple()</v>
+ <v>NonSessions = term()</v>
+ </type>
+ <desc>
+ <p>This function produces a slightly processed dump of the session
+ database. It is intended for debugging.
+ If no profile is specified the default profile will be used. </p>
+
+ <marker id="info"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>info() -> list()</name>
+ <name>info(Profile) -> list()</name>
+ <fsummary>Produces a list of miscelleneous info</fsummary>
+ <type>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
+ </type>
+ <desc>
+ <p>This function produces a list of miscelleneous info.
+ It is intended for debugging.
+ If no profile is specified the default profile will be used. </p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index f88099a82e..7e21229fcf 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -55,14 +55,14 @@
<section>
<title>ERLANG HTTP SERVER SERVICE START/STOP </title>
<p>A web server can be configured to start when starting the inets
- application or started dynamically in runtime by calling the
- Inets application API <c>inets:start(httpd, ServiceConfig)</c>, or
- <c>inets:start(httpd, ServiceConfig, How)</c>,
- see <seealso marker="inets">inets(3)</seealso> Below follows a
- description of the available configuration options, also called
- properties.</p>
-
- <marker id="file_prop"></marker>
+ application or started dynamically in runtime by calling the
+ Inets application API <c>inets:start(httpd, ServiceConfig)</c>, or
+ <c>inets:start(httpd, ServiceConfig, How)</c>,
+ see <seealso marker="inets">inets(3)</seealso> Below follows a
+ description of the available configuration options, also called
+ properties.</p>
+
+ <marker id="props_file"></marker>
<p><em>File properties</em></p>
<p>When the web server is started
@@ -76,21 +76,25 @@
list.</p>
<taglist>
+ <marker id="prop_proplist_file"></marker>
<tag>{proplist_file, path()}</tag>
<item>
- If this property is defined inets will expect to find
- all other properties defined in this file. Note that the
- file must include all properties listed under mandatory
- properties. </item>
- <tag>{file, path()}</tag>
+ <p>If this property is defined inets will expect to find
+ all other properties defined in this file. Note that the
+ file must include all properties listed under mandatory
+ properties. </p>
+ </item>
- <item> If this property is defined
- inets will expect to find all other properties defined in this
- file, that uses Apache like syntax. Note that the file must
- include all properties listed under mandatory properties. The
- Apache like syntax is the property, written as one word where
- each new word begins with a capital, followed by a white-space
- followed by the value followed by a new line. Ex:
+ <marker id="prop_file"></marker>
+ <tag>{file, path()}</tag>
+ <item>
+ <p>If this property is defined inets will expect to find all
+ other properties defined in this file, that uses Apache like
+ syntax. Note that the file must include all properties listed
+ under mandatory properties. The Apache like syntax is the property,
+ written as one word where each new word begins with a capital,
+ followed by a white-space followed by the value followed by a
+ new line. Ex: </p>
<code>
{server_root, "/urs/local/www"} -> ServerRoot /usr/local/www
@@ -114,40 +118,51 @@
<p>The properties proplist_file and file are mutually exclusive.</p>
</note>
- <marker id="mand_prop"></marker>
+ <marker id="props_mand"></marker>
<p><em>Mandatory properties</em></p>
<taglist>
+ <marker id="prop_port"></marker>
<tag>{port, integer()} </tag>
<item>
- The port that the HTTP server shall listen on.
- If zero is specified as port, an arbitrary available port
- will be picked and you can use the httpd:info/2 function to find
- out which port was picked. </item>
+ <p>The port that the HTTP server shall listen on.
+ If zero is specified as port, an arbitrary available port
+ will be picked and you can use the httpd:info/2 function to find
+ out which port was picked. </p>
+ </item>
+
+ <marker id="prop_server_name"></marker>
<tag>{server_name, string()} </tag>
<item>
- The name of your server, normally a fully qualified domain
- name.
+ <p>The name of your server, normally a fully qualified domain name. </p>
</item>
+
+ <marker id="prop_server_root"></marker>
<tag>{server_root, path()} </tag>
<item>
- Defines the servers home directory where log files etc can
+ <p>Defines the servers home directory where log files etc can
be stored. Relative paths specified in other properties refer
- to this directory.</item>
+ to this directory. </p>
+ </item>
+
+ <marker id="prop_doc_root"></marker>
<tag>{document_root, path()}</tag>
<item>
Defines the top directory for the documents that
- are available on the HTTP server.</item>
+ are available on the HTTP server.
+ </item>
</taglist>
- <marker id="comm_prop"></marker>
+ <marker id="props_comm"></marker>
<p><em>Communication properties</em> </p>
<taglist>
+ <marker id="prop_bind_address"></marker>
<tag>{bind_address, ip_address() | hostname() | any} </tag>
<item>
- Defaults to <c>any</c>. Note that <c>any</c> is denoted <em>*</em>
- in the apache like configuration file.
+ <p>Defaults to <c>any</c>. Note that <c>any</c> is denoted <em>*</em>
+ in the apache like configuration file. </p>
</item>
+ <marker id="prop_socket_type"></marker>
<tag>{socket_type, ip_comm | ssl | essl}</tag>
<item>
<p>When using ssl, there are currently only one alternative.
@@ -156,6 +171,7 @@
<p>Defaults to <c>ip_comm</c>. </p>
</item>
+ <marker id="prop_ipfamily"></marker>
<tag>{ipfamily, inet | inet6 | inet6fb4}</tag>
<item>
<p>Defaults to <c>inet6fb4. </c> </p>
@@ -165,74 +181,93 @@
</taglist>
+ <marker id="props_api_modules"></marker>
<p><em>Erlang Web server API modules</em> </p>
<taglist>
+ <marker id="prop_modules"></marker>
<tag>{modules, [atom()]} </tag>
<item>
- Defines which modules the HTTP server will use to handle
+ <p>Defines which modules the HTTP server will use to handle
requests. Defaults to: <c>[mod_alias, mod_auth, mod_esi,
mod_actions, mod_cgi, mod_dir, mod_get, mod_head, mod_log,
mod_disk_log] </c>
Note that some mod-modules are dependent on
others, so the order can not be entirely arbitrary. See the
<seealso marker="http_server"> Inets Web server Modules in the
- Users guide</seealso> for more information.
+ Users guide</seealso> for more information. </p>
</item>
- </taglist>
+ </taglist>
- <marker id="limit_prop"></marker>
+ <marker id="props_limit"></marker>
<p><em>Limit properties</em> </p>
<taglist>
+ <marker id="prop_disable_chunked_encoding"></marker>
<tag>{disable_chunked_transfer_encoding_send, boolean()}</tag>
<item>
- This property allows you to disable chunked
+ <p>This property allows you to disable chunked
transfer-encoding when sending a response to a HTTP/1.1
- client, by default this is false.</item>
+ client, by default this is false. </p>
+ </item>
+ <marker id="prop_keep_alive"></marker>
<tag>{keep_alive, boolean()}</tag>
<item>
- Instructs the server whether or not to use persistent
+ <p>Instructs the server whether or not to use persistent
connections when the client claims to be HTTP/1.1
- compliant, default is true.</item>
+ compliant, default is true. </p>
+ </item>
+ <marker id="prop_keep_alive_timeout"></marker>
<tag>{keep_alive_timeout, integer()}</tag>
<item>
- The number of seconds the server will wait for a
+ <p>The number of seconds the server will wait for a
subsequent request from the client before closing the
- connection. Default is 150.</item>
+ connection. Default is 150. </p>
+ </item>
+ <marker id="prop_max_body_size"></marker>
<tag>{max_body_size, integer()}</tag>
<item>
- Limits the size of the message body of HTTP request.
- By the default there is no limit.</item>
+ <p>Limits the size of the message body of HTTP request.
+ By the default there is no limit. </p>
+ </item>
+ <marker id="prop_max_clients"></marker>
<tag>{max_clients, integer()}</tag>
<item>
- Limits the number of simultaneous requests that can be
- supported. Defaults to 150. </item>
+ <p>Limits the number of simultaneous requests that can be
+ supported. Defaults to 150. </p>
+ </item>
+ <marker id="prop_max_header_size"></marker>
<tag>{max_header_size, integer()}</tag>
<item>
- Limits the size of the message header of HTTP request.
- Defaults to 10240.
+ <p>Limits the size of the message header of HTTP request.
+ Defaults to 10240. </p>
</item>
+ <marker id="prop_max_uri"></marker>
<tag>{max_uri, integer()}</tag>
<item>
- Limits the size of the HTTP request URI. By
- default there is no limit.</item>
+ <p>Limits the size of the HTTP request URI. By
+ default there is no limit. </p>
+ </item>
+ <marker id="prop_max_keep_alive_req"></marker>
<tag>{max_keep_alive_requests, integer()}</tag>
- <item> The number of request that a client can do on one
+ <item>
+ <p>The number of request that a client can do on one
connection. When the server has responded to the number of
requests defined by max_keep_alive_requests the server close the
connection. The server will close it even if there are queued
- request. Defaults to no limit.</item>
+ request. Defaults to no limit. </p>
+ </item>
</taglist>
- <marker id="admin_prop"></marker>
+ <marker id="props_admin"></marker>
<p><em>Administrative properties</em></p>
<taglist>
+ <marker id="prop_mime_types"></marker>
<tag>{mime_types, [{MimeType, Extension}] | path()}</tag>
<item>
<p>Where MimeType = string() and Extension = string().
@@ -250,19 +285,43 @@ text/plain asc txt
<p>Defaults to [{"html","text/html"},{"htm","text/html"}]</p>
</item>
+ <marker id="prop_mime_type"></marker>
<tag>{mime_type, string()}</tag>
-
<item>
- When the server is asked to provide a document type which
+ <p>When the server is asked to provide a document type which
cannot be determined by the MIME Type Settings, the server will
- use this default type. </item>
+ use this default type. </p>
+ </item>
+ <marker id="prop_server_admin"></marker>
<tag>{server_admin, string()}</tag>
<item>
- ServerAdmin defines the email-address of the server
+ <p>ServerAdmin defines the email-address of the server
administrator, to be included in any error messages returned by
- the server.</item>
+ the server. </p>
+ </item>
+ <marker id="prop_server_tokens"></marker>
+ <tag>{server_tokens, prod|major|minor|minimal|os|full|{private, string()}}</tag>
+ <item>
+ <p>ServerTokens defines how the value of the server header
+ should look. </p>
+ <p>Example: Assuming the version of inets is 5.8.1,
+ here is what the server header string could look like for
+ the different values of server-tokens: </p>
+ <pre>
+prod "inets"
+major "inets/5"
+minor "inets/5.8"
+minimal "inets/5.8.1"
+os "inets/5.8.1 (unix)"
+full "inets/5.8.1 (unix/linux) OTP/R15B"
+{private, "foo/bar"} "foo/bar"
+ </pre>
+ <p>By default, the value is as before, which is <c>minimal</c>. </p>
+ </item>
+
+ <marker id="prop_log_format"></marker>
<tag>{log_format, common | combined}</tag>
<item>
<p>Defines if access logs should be written according to the common
@@ -307,8 +366,9 @@ bytes
<p>This affects the access logs written by mod_log and mod_disk_log.
</p>
- </item>
-
+ </item>
+
+ <marker id="prop_elog_format"></marker>
<tag>{error_log_format, pretty | compact}</tag>
<item>
<p>Defaults to pretty. If the error log is meant to be read
@@ -330,63 +390,77 @@ bytes
</taglist>
- <marker id="ssl_prop"></marker>
+ <marker id="props_ssl"></marker>
<p><em>ssl properties</em></p>
<taglist>
+ <marker id="prop_ssl_ca_cert_file"></marker>
<tag>{ssl_ca_certificate_file, path()}</tag>
<item>
- Used as cacertfile option in ssl:listen/2 see
- <seealso marker="ssl:ssl">ssl(3)</seealso> </item>
+ <p>Used as cacertfile option in ssl:listen/2 see
+ <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
+ </item>
+ <marker id="prop_ssl_cert_file"></marker>
<tag>{ssl_certificate_file, path()}</tag>
<item>
- Used as certfile option in ssl:listen/2 see
- <seealso marker="ssl:ssl">ssl(3)</seealso>
+ <p>Used as certfile option in ssl:listen/2 see
+ <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
</item>
+ <marker id="prop_ssl_ciphers"></marker>
<tag>{ssl_ciphers, list()}</tag>
<item>
- Used as ciphers option in ssl:listen/2 see
- <seealso marker="ssl:ssl">ssl(3)</seealso>
+ <p>Used as ciphers option in ssl:listen/2 see
+ <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
</item>
+ <marker id="prop_ssl_verify_client"></marker>
<tag>{ssl_verify_client, integer()}</tag>
<item>
- Used as verify option in ssl:listen/2 see
- <seealso marker="ssl:ssl">ssl(3)</seealso> </item>
+ <p>Used as verify option in ssl:listen/2 see
+ <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
+ </item>
+ <marker id="prop_ssl_verify_depth"></marker>
<tag>{ssl_verify_depth, integer()}</tag>
<item>
- Used as depth option in ssl:listen/2 see
- <seealso marker="ssl:ssl">ssl(3)</seealso> </item>
+ <p>Used as depth option in ssl:listen/2 see
+ <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
+ </item>
+ <marker id="prop_ssl_passwd_callback_funct"></marker>
<tag>{ssl_password_callback_function, atom()}</tag>
<item>
- Used together with ssl_password_callback_module
+ <p>Used together with ssl_password_callback_module
to retrieve a value to use as password option to ssl:listen/2
- see <seealso marker="ssl:ssl">ssl(3)</seealso>
+ see <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
</item>
+ <marker id="prop_ssl_passwd_callback_args"></marker>
<tag>{ssl_password_callback_arguments, list()}</tag>
<item>
- Used together with ssl_password_callback_function to supply a
+ <p>Used together with ssl_password_callback_function to supply a
list of arguments to the callback function. If not specified
- the callback function will be assumed to have arity 0. </item>
+ the callback function will be assumed to have arity 0. </p>
+ </item>
+ <marker id="prop_ssl_passwd_callback_mod"></marker>
<tag>{ssl_password_callback_module, atom()}</tag>
<item>
- Used together with ssl_password_callback_function
+ <p>Used together with ssl_password_callback_function
to retrieve a value to use as password option to ssl:listen/2
- see <seealso marker="ssl:ssl">ssl(3)</seealso></item>
+ see <seealso marker="ssl:ssl">ssl(3)</seealso>. </p>
+ </item>
</taglist>
- <marker id="alias_prop"></marker>
+ <marker id="props_alias"></marker>
<p><em>URL aliasing properties - requires mod_alias</em></p>
<taglist>
+ <marker id="prop_alias"></marker>
<tag>{alias, {Alias, RealName}}</tag>
-
- <item> Where Alias = string() and RealName = string().
+ <item>
+ <p>Where Alias = string() and RealName = string().
The Alias property allows documents to be stored in the local file
system instead of the document_root location. URLs with a path that
begins with url-path is mapped to local files that begins with
@@ -395,11 +469,13 @@ bytes
<code>{alias, {"/image", "/ftp/pub/image"}</code>
and an access to http://your.server.org/image/foo.gif would refer to
- the file /ftp/pub/image/foo.gif.</item>
+ the file /ftp/pub/image/foo.gif. </p>
+ </item>
- <tag>{re_write, {Re, Replacement}}</tag>
-
- <item> Where Re = string() and Replacement = string().
+ <marker id="prop_re_write"></marker>
+ <tag>{re_write, {Re, Replacement}}</tag>
+ <item>
+ <p>Where Re = string() and Replacement = string().
The ReWrite property allows documents to be stored in the local file
system instead of the document_root location. URLs are rewritten
by re:replace/3 to produce a path in the local filesystem.
@@ -419,13 +495,13 @@ bytes
Beware of trailing space in Replacement that will be used.
If you must have a space in Re use e.g the character encoding
- <code>\040</code> see <seealso marker="stdlib:re">re(3)</seealso>.
+ <code>\040</code> see <seealso marker="stdlib:re">re(3)</seealso>. </p>
</item>
- <tag>{directory_index, [string()]}</tag>
-
+ <marker id="prop_dir_idx"></marker>
+ <tag>{directory_index, [string()]}</tag>
<item>
- DirectoryIndex specifies a list of resources to look for
+ <p>DirectoryIndex specifies a list of resources to look for
if a client requests a directory using a / at the end of the
directory name. file depicts the name of a file in the
directory. Several files may be given, in which case the server
@@ -436,70 +512,79 @@ bytes
and access to http://your.server.org/docs/ would return
http://your.server.org/docs/index.html or
http://your.server.org/docs/welcome.html if index.html do not
- exist.
+ exist. </p>
</item>
</taglist>
- <marker id="cgi_prop"></marker>
+ <marker id="props_cgi"></marker>
<p><em>CGI properties - requires mod_cgi</em></p>
<taglist>
+ <marker id="prop_script_alias"></marker>
<tag>{script_alias, {Alias, RealName}}</tag>
- <item> Where Alias = string() and RealName = string().
+ <item>
+ <p>Where Alias = string() and RealName = string().
Has the same behavior as the Alias property, except that
it also marks the target directory as containing CGI
scripts. URLs with a path beginning with url-path are mapped to
scripts beginning with directory-filename, for example:
- <code> {script_alias, {"/cgi-bin/", "/web/cgi-bin/"}</code>
+ <code>{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}</code>
and an access to http://your.server.org/cgi-bin/foo would cause
- the server to run the script /web/cgi-bin/foo.
+ the server to run the script /web/cgi-bin/foo. </p>
</item>
+ <marker id="prop_script_re_write"></marker>
<tag>{script_re_write, {Re, Replacement}}</tag>
- <item> Where Re = string() and Replacement = string().
+ <item>
+ <p>Where Re = string() and Replacement = string().
Has the same behavior as the ReWrite property, except that
it also marks the target directory as containing CGI
scripts. URLs with a path beginning with url-path are mapped to
scripts beginning with directory-filename, for example:
- <code> {script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}</code>
+ <code>{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}</code>
and an access to http://your.server.org/cgi-bin/17/foo would cause
- the server to run the script /web/17/cgi-bin/foo.
+ the server to run the script /web/17/cgi-bin/foo. </p>
</item>
+ <marker id="prop_script_nocache"></marker>
<tag>{script_nocache, boolean()}</tag>
-
<item>
- If ScriptNoCache is set to true the HTTP server will by
+ <p>If ScriptNoCache is set to true the HTTP server will by
default add the header fields necessary to prevent proxies from
caching the page. Generally this is something you want. Defaults
- to false.</item>
+ to false. </p>
+ </item>
+ <marker id="prop_script_timeout"></marker>
<tag>{script_timeout, integer()}</tag>
-
<item>
- The time in seconds the web server will wait between each
+ <p>The time in seconds the web server will wait between each
chunk of data from the script. If the CGI-script not delivers
any data before the timeout the connection to the client will be
- closed. Defaults to 15. </item>
+ closed. Defaults to 15. </p>
+ </item>
+ <marker id="prop_action"></marker>
<tag>{action, {MimeType, CgiScript}} - requires mod_action</tag>
-
- <item>Where MimeType = string() and CgiScript = string().
+ <item>
+ <p>Where MimeType = string() and CgiScript = string().
Action adds an action, which will activate a cgi-script
whenever a file of a certain mime-type is requested. It
propagates the URL and file path of the requested document using
the standard CGI PATH_INFO and PATH_TRANSLATED environment
variables.
- <code> {action, {"text/plain", "/cgi-bin/log_and_deliver_text"}
- </code>
+
+ <code>{action, {"text/plain", "/cgi-bin/log_and_deliver_text"}</code>
+ </p>
</item>
+ <marker id="prop_script"></marker>
<tag>{script, {Method, CgiScript}} - requires mod_action</tag>
-
- <item>Where Method = string() and CgiScript = string().
+ <item>
+ <p>Where Method = string() and CgiScript = string().
Script adds an action, which will activate a cgi-script
whenever a file is requested using a certain HTTP method. The
method is either GET or POST as defined in RFC 1945. It
@@ -507,18 +592,19 @@ bytes
the standard CGI PATH_INFO and PATH_TRANSLATED environment
variables.
- <code> {script, {"PUT", "/cgi-bin/put"}
- </code>
+ <code>{script, {"PUT", "/cgi-bin/put"}</code>
+ </p>
</item>
</taglist>
- <marker id="esi_prop"></marker>
+ <marker id="props_esi"></marker>
<p><em>ESI properties - requires mod_esi</em></p>
<taglist>
- <tag>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
-
- <item>Where URLPath = string() and AllowedModule = atom().
+ <marker id="prop_esi_alias"></marker>
+ <tag>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
+ <item>
+ <p>Where URLPath = string() and AllowedModule = atom().
erl_script_alias marks all URLs matching url-path as erl
scheme scripts. A matching URL is mapped into a specific module
and function. For example:
@@ -531,140 +617,151 @@ bytes
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.
+ not be allowed to execute. </p>
</item>
+ <marker id="prop_esi_nocache"></marker>
<tag>{erl_script_nocache, boolean()}</tag>
-
<item>
- If erl_script_nocache is set to true the server will add
+ <p>If erl_script_nocache is set to true the server will add
http header fields that prevents proxies from caching the
page. This is generally a good idea for dynamic content, since
- the content often vary between each request. Defaults to false.
+ the content often vary between each request.
+ Defaults to false. </p>
</item>
+ <marker id="prop_esi_timeout"></marker>
<tag>{erl_script_timeout, integer()}</tag>
-
<item>
- If erl_script_timeout sets the time in seconds the server will
+ <p>If erl_script_timeout sets the time in seconds the server will
wait between each chunk of data to be delivered through
mod_esi:deliver/2. Defaults to 15. This is only relevant
- for scripts that uses the erl scheme.
+ for scripts that uses the erl scheme. </p>
</item>
+ <marker id="prop_esi_timeout"></marker>
<tag>{eval_script_alias, {URLPath, [AllowedModule]}}</tag>
-
- <item>Where URLPath = string() and AllowedModule = atom().
+ <item>
+ <p>Where URLPath = string() and AllowedModule = atom().
Same as erl_script_alias but for scripts
- using the eval scheme. Note that this is only supported
- for backwards compatibility. The eval scheme is deprecated.</item>
+ using the eval scheme. Note that this is only supported
+ for backwards compatibility. The eval scheme is deprecated. </p>
+ </item>
</taglist>
- <marker id="log_prop"></marker>
+ <marker id="props_log"></marker>
<p><em>Log properties - requires mod_log</em></p>
<taglist>
+ <marker id="prop_elog"></marker>
<tag>{error_log, path()}</tag>
-
<item>
- Defines the filename of the error log file to be used to log
+ <p>Defines the filename of the error log file to be used to log
server errors. If the filename does not begin with a slash (/)
- it is assumed to be relative to the server_root</item>
+ it is assumed to be relative to the server_root. </p>
+ </item>
+ <marker id="prop_slog"></marker>
<tag>{security_log, path()}</tag>
-
<item>
- Defines the filename of the access log file to be used to
- log security events. If the filename does not begin with a slash
- (/) it is assumed to be relative to the server_root.
+ <p>Defines the filename of the access log file to be used to
+ log security events. If the filename does not begin with a slash
+ (/) it is assumed to be relative to the server_root. </p>
</item>
+ <marker id="prop_tlog"></marker>
<tag>{transfer_log, path()}</tag>
-
<item>
- Defines the filename of the access log file to be used to
+ <p>Defines the filename of the access log file to be used to
log incoming requests. If the filename does not begin with a
- slash (/) it is assumed to be relative to the server_root.
+ slash (/) it is assumed to be relative to the server_root. </p>
</item>
</taglist>
- <marker id="dlog_prop"></marker>
+ <marker id="props_dlog"></marker>
<p><em>Disk Log properties - requires mod_disk_log</em></p>
<taglist>
+ <marker id="prop_dlog_format"></marker>
<tag>{disk_log_format, internal | external}</tag>
-
<item>
- Defines the file-format of the log files see disk_log for
+ <p>Defines the file-format of the log files see disk_log for
more information. If the internal file-format is used, the
logfile will be repaired after a crash. When a log file is
repaired data might get lost. When the external file-format is
used httpd will not start if the log file is broken. Defaults to
- external.
+ external. </p>
</item>
+ <marker id="prop_edlog"></marker>
<tag>{error_disk_log, internal | external}</tag>
-
<item>
- Defines the filename of the (disk_log(3)) error log file
+ <p>Defines the filename of the (disk_log(3)) error log file
to be used to log server errors. If the filename does not begin
- with a slash (/) it is assumed to be relative to the server_root.
+ with a slash (/) it is assumed to be relative to the server_root. </p>
</item>
+ <marker id="prop_edlog_size"></marker>
<tag>{error_disk_log_size, {MaxBytes, MaxFiles}}</tag>
-
- <item>Where MaxBytes = integer() and MaxFiles = integer().
+ <item>
+ <p>Where MaxBytes = integer() and MaxFiles = integer().
Defines the properties of the (disk_log(3)) error log
file. The disk_log(3) error log file is of type wrap log and
max-bytes will be written to each file and max-files will be
- used before the first file is truncated and reused. </item>
+ used before the first file is truncated and reused. </p>
+ </item>
+ <marker id="prop_sdlog"></marker>
<tag>{security_disk_log, path()}</tag>
-
<item>
- Defines the filename of the (disk_log(3)) access log file
+ <p>Defines the filename of the (disk_log(3)) access log file
which logs incoming security events i.e authenticated
requests. If the filename does not begin with a slash (/) it
- is assumed to be relative to the server_root.
+ is assumed to be relative to the server_root. </p>
</item>
+ <marker id="prop_sdlog_size"></marker>
<tag>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag>
-
- <item>Where MaxBytes = integer() and MaxFiles = integer().
+ <item>
+ <p>Where MaxBytes = integer() and MaxFiles = integer().
Defines the properties of the disk_log(3) access log
file. The disk_log(3) access log file is of type wrap log and
max-bytes will be written to each file and max-files will be
- used before the first file is truncated and reused.</item>
+ used before the first file is truncated and reused. </p>
+ </item>
- <tag>{transfer_disk_log, path()}</tag>
-
+ <marker id="prop_tdlog"></marker>
+ <tag>{transfer_disk_log, path()}</tag>
<item>
- Defines the filename of the (disk_log(3)) access log file
+ <p>Defines the filename of the (disk_log(3)) access log file
which logs incoming requests. If the filename does not begin
with a slash (/) it is assumed to be relative to the
- server_root.
+ server_root. </p>
</item>
+ <marker id="prop_tdlog_size"></marker>
<tag>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag>
-
- <item>Where MaxBytes = integer() and MaxFiles = integer().
+ <item>
+ <p>Where MaxBytes = integer() and MaxFiles = integer().
Defines the properties of the disk_log(3) access log
file. The disk_log(3) access log file is of type wrap log and
max-bytes will be written to each file and max-files will be
- used before the first file is truncated and reused.</item>
+ used before the first file is truncated and reused. </p>
+ </item>
</taglist>
- <marker id="auth_prop"></marker>
+ <marker id="props_auth"></marker>
<p><em>Authentication properties - requires mod_auth</em></p>
+ <marker id="prop_dri"></marker>
<p><em>{directory, {path(), [{property(), term()}]}}</em></p>
- <marker id="dir_prop"></marker>
+ <marker id="props_dir"></marker>
<p>Here follows the valid properties for directories </p>
<taglist>
+ <marker id="prop_allow_from"></marker>
<tag>{allow_from, all | [RegxpHostString]}</tag>
-
<item>
- Defines a set of hosts which should be granted access to a
+ <p>Defines a set of hosts which should be granted access to a
given directory.
For example:
@@ -672,34 +769,36 @@ bytes
<code>{allow_from, ["123.34.56.11", "150.100.23"] </code>
The host 123.34.56.11 and all machines on the 150.100.23
- subnet are allowed access.</item>
+ subnet are allowed access. </p>
+ </item>
+ <marker id="prop_deny_from"></marker>
<tag>{deny_from, all | [RegxpHostString]}</tag>
-
<item>
- Defines a set of hosts
+ <p>Defines a set of hosts
which should be denied access to a given directory.
For example:
<code>{deny_from, ["123.34.56.11", "150.100.23"] </code>
The host 123.34.56.11 and all machines on the 150.100.23
- subnet are not allowed access.</item>
+ subnet are not allowed access. </p>
+ </item>
+ <marker id="prop_auth_type"></marker>
<tag>{auth_type, plain | dets | mnesia}</tag>
-
<item>
- Sets the type of authentication database that is used for the
+ <p>Sets the type of authentication database that is used for the
directory.The key difference between the different methods is
that dynamic data can be saved when Mnesia and Dets is used.
This property is called AuthDbType in the Apache like
- configuration files.
+ configuration files. </p>
</item>
+ <marker id="prop_auth_user_file"></marker>
<tag>{auth_user_file, path()}</tag>
-
<item>
- Sets the name of a file which contains the list of users and
+ <p>Sets the name of a file which contains the list of users and
passwords for user authentication. filename can be either
absolute or relative to the <c>server_root</c>. If using the
plain storage method, this file is a plain text file, where
@@ -717,12 +816,13 @@ bytes
storage method. For security reasons, make sure that the
<c>auth_user_file</c> is stored outside the document tree of the Web
server. If it is placed in the directory which it protects,
- clients will be able to download it.
+ clients will be able to download it. </p>
</item>
+ <marker id="prop_auth_group_file"></marker>
<tag>{auth_group_file, path()}</tag>
-
- <item> Sets the name of a file which contains the list of user
+ <item>
+ <p>Sets the name of a file which contains the list of user
groups for user authentication. Filename can be either
absolute or relative to the <c>server_root</c>. If you use the plain
storage method, the group file is a plain text file, where
@@ -738,93 +838,109 @@ bytes
For security reasons, make sure that the <c>auth_group_file</c> is
stored outside the document tree of the Web server. If it is
placed in the directory which it protects, clients will be
- able to download it.</item>
+ able to download it. </p>
+ </item>
+ <marker id="prop_auth_name"></marker>
<tag>{auth_name, string()}</tag>
-
<item>
- Sets the name of the authorization realm (auth-domain) for
+ <p>Sets the name of the authorization realm (auth-domain) for
a directory. This string informs the client about which user
- name and password to use. </item>
+ name and password to use. </p>
+ </item>
+ <marker id="prop_auth_access_passwd"></marker>
<tag>{auth_access_password, string()}</tag>
-
- <item> If set to other than "NoPassword" the password is required
+ <item>
+ <p>If set to other than "NoPassword" the password is required
for all API calls. If the password is set to "DummyPassword" the
password must be changed before any other API calls. To secure
the authenticating data the password must be changed after the
web server is started since it otherwise is written in clear
- text in the configuration file.</item>
+ text in the configuration file. </p>
+ </item>
+ <marker id="prop_req_user"></marker>
<tag>{require_user, [string()]}</tag>
<item>
- Defines users which should be granted access to a given
- directory using a secret password.
+ <p>Defines users which should be granted access to a given
+ directory using a secret password. </p>
</item>
+ <marker id="prop_req_grp"></marker>
<tag>{require_group, [string()]}</tag>
<item>
- Defines users which should be granted access to a given
- directory using a secret password.
+ <p>Defines users which should be granted access to a given
+ directory using a secret password. </p>
</item>
</taglist>
- <marker id="htaccess_prop"></marker>
+ <marker id="props_htaccess"></marker>
<p><em>Htaccess authentication properties - requires mod_htaccess</em></p>
<taglist>
+ <marker id="prop_access_files"></marker>
<tag>{access_files, [path()]}</tag>
-
- <item> Specify which filenames that are used for
+ <item>
+ <p>Specify which filenames that are used for
access-files. When a request comes every directory in the path
to the requested asset will be searched after files with the
names specified by this parameter. If such a file is found the
file will be parsed and the restrictions specified in it will
- be applied to the request.
+ be applied to the request. </p>
</item>
</taglist>
- <marker id="sec_prop"></marker>
+ <marker id="props_sec"></marker>
<p><em>Security properties - requires mod_security </em></p>
+ <marker id="prop_sec_dir"></marker>
<p><em>{security_directory, {path(), [{property(), term()}]}</em></p>
- <marker id="sdir_prop"></marker>
- <p> Here follows the valid properties for security directories</p>
+ <marker id="props_sdir"></marker>
+ <p>Here follows the valid properties for security directories</p>
<taglist>
- <tag>{data_file, path()}</tag>
-
+ <marker id="prop_data_file"></marker>
+ <tag>{data_file, path()}</tag>
<item>
- Name of the security data file. The filename can either
+ <p>Name of the security data file. The filename can either
absolute or relative to the server_root. This file is used to
- store persistent data for the mod_security module. </item>
-
- <tag>{max_retries, integer()}</tag>
+ store persistent data for the mod_security module. </p>
+ </item>
- <item> Specifies the maximum number of tries to authenticate a
+ <marker id="prop_max_retries"></marker>
+ <tag>{max_retries, integer()}</tag>
+ <item>
+ <p>Specifies the maximum number of tries to authenticate a
user has before the user is blocked out. If a user
successfully authenticates when the user has been blocked, the
user will receive a 403 (Forbidden) response from the
server. If the user makes a failed attempt while blocked the
server will return 401 (Unauthorized), for security
- reasons. Defaults to 3 may also be set to infinity.</item>
+ reasons.
+ Defaults to 3 may also be set to infinity. </p>
+ </item>
+ <marker id="prop_block_time"></marker>
<tag>{block_time, integer()}</tag>
-
- <item> Specifies the number of minutes a user is blocked. After
+ <item>
+ <p>Specifies the number of minutes a user is blocked. After
this amount of time, he automatically regains access.
- Defaults to 60</item>
+ Defaults to 60. </p>
+ </item>
+ <marker id="prop_fail_exp_time"></marker>
<tag>{fail_expire_time, integer()}</tag>
-
<item>
- Specifies the number of minutes a failed user authentication
+ <p>Specifies the number of minutes a failed user authentication
is remembered. If a user authenticates after this amount of
time, his previous failed authentications are
- forgotten. Defaults to 30</item>
+ forgotten.
+ Defaults to 30. </p>
+ </item>
+ <marker id="prop_auth_timeout"></marker>
<tag>{auth_timeout, integer()}</tag>
-
<item>
Specifies the number of seconds a successful user
authentication is remembered. After this time has passed, the
@@ -835,6 +951,7 @@ bytes
<funcs>
<func>
+ <marker id="info1"></marker>
<name>info(Pid) -></name>
<name>info(Pid, Properties) -> [{Option, Value}]</name>
<fsummary>Fetches information about the HTTP server</fsummary>
@@ -858,6 +975,7 @@ bytes
</func>
<func>
+ <marker id="info2"></marker>
<name>info(Address, Port) -> </name>
<name>info(Address, Port, Properties) -> [{Option, Value}] </name>
<fsummary>Fetches information about the HTTP server</fsummary>
@@ -883,6 +1001,7 @@ bytes
</func>
<func>
+ <marker id="reload_config"></marker>
<name>reload_config(Config, Mode) -> ok | {error, Reason}</name>
<fsummary>Reloads the HTTP server configuration without
restarting the server.</fsummary>
@@ -1003,6 +1122,7 @@ bytes
</section>
<funcs>
<func>
+ <marker id="module_do"></marker>
<name>Module:do(ModData)-> {proceed, OldData} | {proceed, NewData} | {break, NewData} | done</name>
<fsummary>Called for each request to the Web server.</fsummary>
<type>
@@ -1046,7 +1166,9 @@ bytes
closing the connection.</p>
</desc>
</func>
+
<func>
+ <marker id="module_load"></marker>
<name>Module:load(Line, AccIn)-> eof | ok | {ok, AccOut} | {ok, AccOut, {Option, Value}} | {ok, AccOut, [{Option, Value}]} | {error, Reason} </name>
<fsummary>Load is used to convert a line in a Apache like config
file to a <c>{Option, Value}</c> tuple.</fsummary>
@@ -1068,7 +1190,9 @@ bytes
</p>
</desc>
</func>
+
<func>
+ <marker id="module_store"></marker>
<name>Module:store({Option, Value}, Config)-> {ok, {Option, NewValue}} | {error, Reason} </name>
<fsummary></fsummary>
<type>
@@ -1092,6 +1216,7 @@ bytes
</func>
<func>
+ <marker id="module_remove"></marker>
<name>Module:remove(ConfigDB) -> ok | {error, Reason} </name>
<fsummary>Callback function that is called when the Web server is closed.</fsummary>
<type>
@@ -1112,6 +1237,7 @@ bytes
</section>
<funcs>
<func>
+ <marker id="parse_query"></marker>
<name>parse_query(QueryString) -> [{Key,Value}]</name>
<fsummary>Parse incoming data to <c>erl </c>and <c>eval </c>scripts.</fsummary>
<type>
@@ -1120,7 +1246,6 @@ bytes
<v>Value = string()</v>
</type>
<desc>
- <marker id="parse_query"></marker>
<p><c>parse_query/1</c> parses incoming data to <c>erl</c> and
<c>eval</c> scripts (See <seealso marker="mod_esi">mod_esi(3)</seealso>) as defined in the standard
URL format, that is '+' becomes 'space' and decoding of
diff --git a/lib/inets/doc/src/httpd_conf.xml b/lib/inets/doc/src/httpd_conf.xml
index a1ad76a8ae..fc34f14ec3 100644
--- a/lib/inets/doc/src/httpd_conf.xml
+++ b/lib/inets/doc/src/httpd_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>1997</year><year>2009</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,11 +33,14 @@
Web server API programmer.</modulesummary>
<description>
<p>This module provides the Erlang Webserver API programmer with
- utility functions for adding run-time configuration directives.</p>
+ utility functions for adding run-time configuration directives.</p>
+
+ <marker id="check_enum"></marker>
</description>
+
<funcs>
<func>
- <name>check_enum(EnumString,ValidEnumStrings) -> Result</name>
+ <name>check_enum(EnumString, ValidEnumStrings) -> Result</name>
<fsummary>Check if string is a valid enumeration.</fsummary>
<type>
<v>EnumString = string()</v>
@@ -47,10 +50,13 @@
<desc>
<marker id="check_enum"></marker>
<p><c>check_enum/2</c> checks if <c>EnumString</c> is a valid
- enumeration of <c>ValidEnumStrings</c> in which case it is
- returned as an atom.</p>
+ enumeration of <c>ValidEnumStrings</c> in which case it is
+ returned as an atom.</p>
+
+ <marker id="clean"></marker>
</desc>
</func>
+
<func>
<name>clean(String) -> Stripped</name>
<fsummary>Remove leading and/or trailing white spaces.</fsummary>
@@ -60,9 +66,12 @@
<desc>
<marker id="clean"></marker>
<p><c>clean/1</c> removes leading and/or trailing white spaces
- from <c>String</c>.</p>
+ from <c>String</c>.</p>
+
+ <marker id="custom_clean"></marker>
</desc>
</func>
+
<func>
<name>custom_clean(String,Before,After) -> Stripped</name>
<fsummary>Remove leading and/or trailing white spaces and custom characters.</fsummary>
@@ -73,11 +82,14 @@
<desc>
<marker id="custom_clean"></marker>
<p><c>custom_clean/3</c> removes leading and/or trailing white
- spaces and custom characters from <c>String</c>. <c>Before</c>
- and <c>After</c> are regular expressions, as defined in
- <c>regexp(3)</c>, describing the custom characters.</p>
+ spaces and custom characters from <c>String</c>. <c>Before</c>
+ and <c>After</c> are regular expressions, as defined in
+ <c>regexp(3)</c>, describing the custom characters.</p>
+
+ <marker id="is_directory"></marker>
</desc>
</func>
+
<func>
<name>is_directory(FilePath) -> Result</name>
<fsummary>Check if a file path is a directory.</fsummary>
@@ -91,13 +103,16 @@
<desc>
<marker id="is_directory"></marker>
<p><c>is_directory/1</c> checks if <c>FilePath</c> is a
- directory in which case it is returned. Please read
- <c>file(3)</c> for a description of <c>enoent</c>,
- <c>eaccess</c> and <c>enotdir</c>. The definition of
- the file info record can be found by including <c>file.hrl</c>
- from the kernel application, see file(3).</p>
+ directory in which case it is returned. Please read
+ <c>file(3)</c> for a description of <c>enoent</c>,
+ <c>eaccess</c> and <c>enotdir</c>. The definition of
+ the file info record can be found by including <c>file.hrl</c>
+ from the kernel application, see file(3).</p>
+
+ <marker id="is_file"></marker>
</desc>
</func>
+
<func>
<name>is_file(FilePath) -> Result</name>
<fsummary>Check if a file path is a regular file.</fsummary>
@@ -111,13 +126,16 @@
<desc>
<marker id="is_file"></marker>
<p><c>is_file/1</c> checks if <c>FilePath</c> is a regular
- file in which case it is returned. Read <c>file(3)</c> for a
- description of <c>enoent</c>, <c>eaccess</c> and
- <c>enotdir</c>. The definition of the file info record can be
- found by including <c>file.hrl</c> from the kernel application,
- see file(3).</p>
+ file in which case it is returned. Read <c>file(3)</c> for a
+ description of <c>enoent</c>, <c>eaccess</c> and
+ <c>enotdir</c>. The definition of the file info record can be
+ found by including <c>file.hrl</c> from the kernel application,
+ see file(3).</p>
+
+ <marker id="make_integer"></marker>
</desc>
</func>
+
<func>
<name>make_integer(String) -> Result</name>
<fsummary>Return an integer representation of a string.</fsummary>
diff --git a/lib/inets/doc/src/httpd_socket.xml b/lib/inets/doc/src/httpd_socket.xml
index fba1a58d3a..58cd2ec575 100644
--- a/lib/inets/doc/src/httpd_socket.xml
+++ b/lib/inets/doc/src/httpd_socket.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>2009</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,10 +33,13 @@
Web server API programmer.</modulesummary>
<description>
<p>This module provides the Erlang Web server API module programmer
- with utility functions for generic sockets communication. The
- appropriate communication mechanism is transparently used, that
- is <c>ip_comm</c> or <c>ssl</c>.</p>
+ with utility functions for generic sockets communication. The
+ appropriate communication mechanism is transparently used, that
+ is <c>ip_comm</c> or <c>ssl</c>.</p>
+
+ <marker id="deliver"></marker>
</description>
+
<funcs>
<func>
<name>deliver(SocketType, Socket, Data) -> Result</name>
@@ -50,11 +53,14 @@
<desc>
<marker id="deliver"></marker>
<p><c>deliver/3</c> sends the <c>Binary</c> over the
- <c>Socket</c> using the specified <c>SocketType</c>. Socket
- and SocketType should be the socket and the socket_type form
- the mod record as defined in httpd.hrl</p>
+ <c>Socket</c> using the specified <c>SocketType</c>. Socket
+ and SocketType should be the socket and the socket_type form
+ the mod record as defined in httpd.hrl</p>
+
+ <marker id="peername"></marker>
</desc>
</func>
+
<func>
<name>peername(SocketType,Socket) -> {Port,IPAddress}</name>
<fsummary>Return the port and IP-address of the remote socket.</fsummary>
@@ -67,9 +73,12 @@
<desc>
<marker id="peername"></marker>
<p><c>peername/3</c> returns the <c>Port</c> and
- <c>IPAddress</c> of the remote <c>Socket</c>. </p>
+ <c>IPAddress</c> of the remote <c>Socket</c>. </p>
+
+ <marker id="resolve"></marker>
</desc>
</func>
+
<func>
<name>resolve() -> HostName</name>
<fsummary>Return the official name of the current host.</fsummary>
@@ -79,7 +88,7 @@
<desc>
<marker id="resolve"></marker>
<p><c>resolve/0</c> returns the official <c>HostName</c> of
- the current host. </p>
+ the current host. </p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/httpd_util.xml b/lib/inets/doc/src/httpd_util.xml
index 6ac2b13c72..9f290084d2 100644
--- a/lib/inets/doc/src/httpd_util.xml
+++ b/lib/inets/doc/src/httpd_util.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>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/inets_services.xml b/lib/inets/doc/src/inets_services.xml
index c274d67f19..e282050b12 100644
--- a/lib/inets/doc/src/inets_services.xml
+++ b/lib/inets/doc/src/inets_services.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>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/make.dep b/lib/inets/doc/src/make.dep
deleted file mode 100644
index 8deb7e7a5a..0000000000
--- a/lib/inets/doc/src/make.dep
+++ /dev/null
@@ -1,47 +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%
-#
-#
-
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex ftp.tex ftp_client.tex httpc.tex http_client.tex \
- http_server.tex httpd.tex httpd_conf.tex httpd_socket.tex \
- httpd_util.tex inets.tex inets_services.tex \
- mod_alias.tex mod_auth.tex mod_esi.tex mod_security.tex \
- part.tex ref_man.tex tftp.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ftp.tex: ../../../../system/doc/definitions/term.defs
-
-inets_services.tex: ../../../../system/doc/definitions/term.defs
-
diff --git a/lib/inets/doc/src/mod_alias.xml b/lib/inets/doc/src/mod_alias.xml
index c783b99b23..265a1b8e76 100644
--- a/lib/inets/doc/src/mod_alias.xml
+++ b/lib/inets/doc/src/mod_alias.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>2009</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,8 +32,11 @@
<modulesummary>URL aliasing.</modulesummary>
<description>
<p>Erlang Webserver Server internal API for handling of things
- such as interaction data exported by the mod_alias module.</p>
+ such as interaction data exported by the mod_alias module.</p>
+
+ <marker id="default_index"></marker>
</description>
+
<funcs>
<func>
<name>default_index(ConfigDB, Path) -> NewPath</name>
@@ -45,17 +48,20 @@
<desc>
<marker id="default_index"></marker>
<p>If <c>Path</c> is a directory, <c>default_index/2</c>, it starts
- searching for resources or files that are specified in the config
- directive DirectoryIndex.
- If an appropriate resource or file is found, it is appended to
- the end of <c>Path</c> and then returned. <c>Path</c> is
- returned unaltered, if no appropriate
- file is found, or if <c>Path</c> is not a directory.
- <c>config_db()</c> is the server config file in ETS table format
- as described in
- <seealso marker="http_server">Inets Users Guide.</seealso>.</p>
+ searching for resources or files that are specified in the config
+ directive DirectoryIndex.
+ If an appropriate resource or file is found, it is appended to
+ the end of <c>Path</c> and then returned. <c>Path</c> is
+ returned unaltered, if no appropriate
+ file is found, or if <c>Path</c> is not a directory.
+ <c>config_db()</c> is the server config file in ETS table format
+ as described in
+ <seealso marker="http_server">Inets Users Guide.</seealso>.</p>
+
+ <marker id="path"></marker>
</desc>
</func>
+
<func>
<name>path(PathData, ConfigDB, RequestURI) -> Path</name>
<fsummary>Return the actual file path to a URL.</fsummary>
@@ -67,15 +73,19 @@
<desc>
<marker id="path"></marker>
<p><c>path/3</c> returns the actual file <c>Path</c> in the
- <c>RequestURI</c> (See RFC 1945). If the interaction data
- <c>{real_name,{Path,AfterPath}}</c> has been exported by
- mod_alias;
- <c>Path</c> is returned. If no interaction data has been
- exported, ServerRoot is used to
- generate a file <c>Path</c>. <c>config_db()</c> and
- <c>interaction_data()</c> are as defined in <seealso marker="http_server">Inets Users Guide</seealso>.</p>
+ <c>RequestURI</c> (See RFC 1945). If the interaction data
+ <c>{real_name,{Path,AfterPath}}</c> has been exported by
+ mod_alias;
+ <c>Path</c> is returned. If no interaction data has been
+ exported, ServerRoot is used to
+ generate a file <c>Path</c>. <c>config_db()</c> and
+ <c>interaction_data()</c> are as defined in
+ <seealso marker="http_server">Inets Users Guide</seealso>.</p>
+
+ <marker id="real_name"></marker>
</desc>
</func>
+
<func>
<name>real_name(ConfigDB, RequestURI, Aliases) -> Ret</name>
<fsummary>Expand a request uri using Alias config directives.</fsummary>
@@ -89,18 +99,24 @@
<desc>
<marker id="real_name"></marker>
<p><c>real_name/3</c> traverses <c>Aliases</c>, typically
- extracted from <c>ConfigDB</c>, and matches each
- <c>FakeName</c> with <c>RequestURI</c>. If a match is found
- <c>FakeName</c> is replaced with <c>RealName</c> in the
- match. The resulting path is split into two parts, that
- is <c>ShortPath</c> and <c>AfterPath</c> as defined in <seealso marker="httpd_util#split_path">httpd_util:split_path/1</seealso>.
- <c>Path</c> is generated from <c>ShortPath</c>, that is
- the result from <seealso marker="#default_index">default_index/2</seealso> with
- <c>ShortPath</c> as an argument.
- <c>config_db()</c> is the server config file in ETS table
- format as described in <seealso marker="http_server">Inets User Guide.</seealso>. </p>
+ extracted from <c>ConfigDB</c>, and matches each
+ <c>FakeName</c> with <c>RequestURI</c>. If a match is found
+ <c>FakeName</c> is replaced with <c>RealName</c> in the
+ match. The resulting path is split into two parts, that
+ is <c>ShortPath</c> and <c>AfterPath</c> as defined in
+ <seealso marker="httpd_util#split_path">httpd_util:split_path/1</seealso>.
+ <c>Path</c> is generated from <c>ShortPath</c>, that is
+ the result from
+ <seealso marker="#default_index">default_index/2</seealso> with
+ <c>ShortPath</c> as an argument.
+ <c>config_db()</c> is the server config file in ETS table
+ format as described in
+ <seealso marker="http_server">Inets User Guide.</seealso>. </p>
+
+ <marker id="real_script_name"></marker>
</desc>
</func>
+
<func>
<name>real_script_name(ConfigDB,RequestURI,ScriptAliases) -> Ret</name>
<fsummary>Expand a request uri using ScriptAlias config directives.</fsummary>
@@ -114,15 +130,15 @@
<desc>
<marker id="real_script_name"></marker>
<p><c>real_name/3</c> traverses <c>ScriptAliases</c>,
- typically extracted from <c>ConfigDB</c>, and matches each
- <c>FakeName</c> with <c>RequestURI</c>. If a match is found
- <c>FakeName</c> is replaced with <c>RealName</c> in the
- match. If the resulting match is not an executable script
- <c>not_a_script</c> is returned. If it is a script the
- resulting script path is in two parts, that is
- <c>ShortPath</c> and <c>AfterPath</c> as defined in <seealso marker="httpd_util#split_script_path">httpd_util:split_script_path/1</seealso>.
- <c>config_db()</c> is the server config file in ETS table
- format as described in <seealso marker="http_server">Inets Users Guide.</seealso>.</p>
+ typically extracted from <c>ConfigDB</c>, and matches each
+ <c>FakeName</c> with <c>RequestURI</c>. If a match is found
+ <c>FakeName</c> is replaced with <c>RealName</c> in the
+ match. If the resulting match is not an executable script
+ <c>not_a_script</c> is returned. If it is a script the
+ resulting script path is in two parts, that is
+ <c>ShortPath</c> and <c>AfterPath</c> as defined in <seealso marker="httpd_util#split_script_path">httpd_util:split_script_path/1</seealso>.
+ <c>config_db()</c> is the server config file in ETS table
+ format as described in <seealso marker="http_server">Inets Users Guide.</seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml
index 2134ebeeae..a176242a72 100644
--- a/lib/inets/doc/src/mod_auth.xml
+++ b/lib/inets/doc/src/mod_auth.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>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,8 +32,11 @@
<modulesummary>User authentication using text files, dets or mnesia database.</modulesummary>
<description>
<p>This module provides for basic user authentication using
- textual files, dets databases as well as mnesia databases. </p>
+ textual files, dets databases as well as mnesia databases. </p>
+
+ <marker id="add_user"></marker>
</description>
+
<funcs>
<func>
<name>add_user(UserName, Options) -> true| {error, Reason}</name>
@@ -55,12 +58,17 @@
<desc>
<marker id="user_api"></marker>
<marker id="add_user"></marker>
- <p><c>add_user/2, add_user/5</c> and <c>add_user/6</c> adds a user to the user
- database. If the operation is successful, this function returns
- <c>true</c>. If an error occurs, <c>{error,Reason}</c> is returned. When <c>add_user/2</c>
- is called the Password, UserData Port and Dir options is mandatory.</p>
+ <p><c>add_user/2, add_user/5</c> and <c>add_user/6</c> adds a
+ user to the user
+ database. If the operation is successful, this function returns
+ <c>true</c>. If an error occurs, <c>{error,Reason}</c> is returned.
+ When <c>add_user/2</c> is called the Password,
+ UserData Port and Dir options is mandatory.</p>
+
+ <marker id="delete_user"></marker>
</desc>
</func>
+
<func>
<name>delete_user(UserName,Options) -> true | {error, Reason}</name>
<name>delete_user(UserName, Port, Dir) -> true | {error, Reason}</name>
@@ -79,13 +87,16 @@
<desc>
<marker id="delete_user"></marker>
<p><c>delete_user/2, delete_user/3</c> and <c>delete_user/4</c>
- deletes a user
- from the user database. If the operation is successful, this
- function returns <c>true</c>. If an error occurs,
- <c>{error,Reason}</c> is returned. When <c>delete_user/2</c> is
- called the Port and Dir options are mandatory.</p>
+ deletes a user from the user database.
+ If the operation is successful, this function returns <c>true</c>.
+ If an error occurs, <c>{error,Reason}</c> is returned.
+ When <c>delete_user/2</c> is called the Port and Dir options
+ are mandatory.</p>
+
+ <marker id="get_user"></marker>
</desc>
</func>
+
<func>
<name>get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason}</name>
<name>get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name>
@@ -104,12 +115,15 @@
<desc>
<marker id="get_user"></marker>
<p><c>get_user/2, get_user/3</c> and <c>get_user/4</c> returns a
- <c>httpd_user</c> record containing the userdata for a
- specific user. If the user cannot be found, <c>{error, Reason}</c>
- is returned. When <c>get_user/2</c> is called the Port and Dir
- options are mandatory.</p>
+ <c>httpd_user</c> record containing the userdata for a
+ specific user. If the user cannot be found, <c>{error, Reason}</c>
+ is returned. When <c>get_user/2</c> is called the Port and Dir
+ options are mandatory.</p>
+
+ <marker id="list_users"></marker>
</desc>
</func>
+
<func>
<name>list_users(Options) -> {ok, Users} | {error, Reason}</name>
<name>list_users(Port, Dir) -> {ok, Users} | {error, Reason}</name>
@@ -127,12 +141,16 @@
</type>
<desc>
<marker id="list_users"></marker>
- <p><c>list_users/1, list_users/2</c> and <c>list_users/3</c> returns a list
- of users in the user database for a specific <c>Port/Dir</c>.
- When <c>list_users/1</c> is called the Port and Dir
- options are mandatory.</p>
+ <p><c>list_users/1, list_users/2</c> and <c>list_users/3</c>
+ returns a list
+ of users in the user database for a specific <c>Port/Dir</c>.
+ When <c>list_users/1</c> is called the Port and Dir
+ options are mandatory.</p>
+
+ <marker id="add_group_member"></marker>
</desc>
</func>
+
<func>
<name>add_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name>
<name>add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name>
@@ -151,13 +169,18 @@
</type>
<desc>
<marker id="add_group_member"></marker>
- <p><c>add_group_member/3, add_group_member/4</c> and <c>add_group_member/5</c>
- adds a user to a group. If the group does not exist, it
- is created and the user is added to the group. Upon successful
- operation, this function returns <c>true</c>. When <c>add_group_members/3</c>
- is called the Port and Dir options are mandatory.</p>
+ <p><c>add_group_member/3, add_group_member/4</c> and
+ <c>add_group_member/5</c>
+ adds a user to a group. If the group does not exist, it
+ is created and the user is added to the group. Upon successful
+ operation, this function returns <c>true</c>.
+ When <c>add_group_members/3</c>
+ is called the Port and Dir options are mandatory.</p>
+
+ <marker id="delete_group_member"></marker>
</desc>
</func>
+
<func>
<name>delete_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name>
<name>delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name>
@@ -176,13 +199,17 @@
</type>
<desc>
<marker id="delete_group_member"></marker>
- <p><c>delete_group_member/3, delete_group_member/4</c> and <c>delete_group_member/5</c> deletes a user from a group.
- If the group or the user does not exist,
- this function returns an error, otherwise it returns <c>true</c>.
- When <c>delete_group_member/3</c> is called the Port and Dir options
- are mandatory.</p>
+ <p><c>delete_group_member/3, delete_group_member/4</c> and
+ <c>delete_group_member/5</c> deletes a user from a group.
+ If the group or the user does not exist,
+ this function returns an error, otherwise it returns <c>true</c>.
+ When <c>delete_group_member/3</c> is called the Port and Dir options
+ are mandatory.</p>
+
+ <marker id="list_group_members"></marker>
</desc>
</func>
+
<func>
<name>list_group_members(GroupName, Options) -> {ok, Users} | {error, Reason}</name>
<name>list_group_members(GroupName, Port, Dir) -> {ok, Users} | {error, Reason}</name>
@@ -201,13 +228,17 @@
</type>
<desc>
<marker id="list_group_members"></marker>
- <p><c>list_group_members/2, list_group_members/3</c> and <c>list_group_members/4</c>
- lists the members of a specified group. If the group does not
- exist or there is an error, <c>{error, Reason}</c> is returned.
- When <c>list_group_members/2</c> is called the Port and Dir options
- are mandatory.</p>
+ <p><c>list_group_members/2, list_group_members/3</c> and
+ <c>list_group_members/4</c>
+ lists the members of a specified group. If the group does not
+ exist or there is an error, <c>{error, Reason}</c> is returned.
+ When <c>list_group_members/2</c> is called the Port and Dir options
+ are mandatory.</p>
+
+ <marker id="list_groups"></marker>
</desc>
</func>
+
<func>
<name>list_groups(Options) -> {ok, Groups} | {error, Reason}</name>
<name>list_groups(Port, Dir) -> {ok, Groups} | {error, Reason}</name>
@@ -225,12 +256,16 @@
</type>
<desc>
<marker id="list_groups"></marker>
- <p><c>list_groups/1, list_groups/2</c> and <c>list_groups/3</c> lists all
- the groups available. If there is an error, <c>{error, Reason}</c>
- is returned. When <c>list_groups/1</c> is called the Port and Dir options
- are mandatory.</p>
+ <p><c>list_groups/1, list_groups/2</c> and <c>list_groups/3</c>
+ lists all the groups available.
+ If there is an error, <c>{error, Reason}</c> is returned.
+ When <c>list_groups/1</c> is called the Port and Dir options
+ are mandatory.</p>
+
+ <marker id="delete_group"></marker>
</desc>
</func>
+
<func>
<name>delete_group(GroupName, Options) -> true | {error,Reason} &lt;name>delete_group(GroupName, Port, Dir) -> true | {error, Reason}</name>
<name>delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason}</name>
@@ -247,12 +282,16 @@
</type>
<desc>
<marker id="delete_group"></marker>
- <p><c>delete_group/2, delete_group/3</c> and <c>delete_group/4</c> deletes the
- group specified and returns <c>true</c>. If there is an error,
- <c>{error, Reason}</c> is returned. When <c>delete_group/2</c> is called the
- Port and Dir options are mandatory.</p>
+ <p><c>delete_group/2, delete_group/3</c> and <c>delete_group/4</c>
+ deletes the group specified and returns <c>true</c>.
+ If there is an error, <c>{error, Reason}</c> is returned.
+ When <c>delete_group/2</c> is called the
+ Port and Dir options are mandatory.</p>
+
+ <marker id="update_password"></marker>
</desc>
</func>
+
<func>
<name>update_password(Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name>
<name>update_password(Address,Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name>
@@ -268,10 +307,12 @@
</type>
<desc>
<marker id="update_password"></marker>
- <p><c>update_password/5</c> and <c>update_password/6</c> Updates the AuthAccessPassword
- for the specified directory. If NewPassword is equal to "NoPassword" no password is requires to
- change authorisation data. If NewPassword is equal to "DummyPassword" no changes can be done
- without changing the password first.</p>
+ <p><c>update_password/5</c> and <c>update_password/6</c>
+ Updates the AuthAccessPassword for the specified directory.
+ If NewPassword is equal to "NoPassword" no password is requires to
+ change authorisation data.
+ If NewPassword is equal to "DummyPassword" no changes can be done
+ without changing the password first.</p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 87a8c173a5..3aae1ff70a 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2011</year>
+ <year>2002</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>Inets Release Notes</title>
@@ -32,8 +32,175 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 5.8</title>
+
+ <section>
+ <title>Inets 5.9.1</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list>
+ <item>
+ <p>Better handling of errorI(s) during update of the session
+ database. </p>
+ <p>Also added and updated some debugging functions
+ <seealso marker="httpc#which_sessions">which_sessions/10,1</seealso>
+ and
+ <seealso marker="httpc#info">info/0</seealso>. </p>
+ <p>Own Id: OTP-10093</p>
+ <p>Aux Id: Seq 12062</p>
+ </item>
+
+ <item>
+ <p>Removed R14B compatible version of (inets-service and
+ tftp) behaviour definition. </p>
+ <p>Own Id: OTP-10095</p>
+ </item>
+
+ <item>
+ <p>[httpc] Documentation of KeepAlive and Pipeline timeout
+ options have been improved. </p>
+ <p>Own Id: OTP-10114</p>
+ </item>
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list>
+ <item>
+ <p>[httpc] Cancel request does not work due to incorrect
+ handler table creation (wrong keypos). </p>
+ <p>Vyacheslav Vorobyov</p>
+ <p>Own Id: OTP-10092</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+
+ <!--
+ <list>
+ <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.9.1 -->
+
+
+ <section>
+ <title>Inets 5.9</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list>
+ <item>
+ <p>[httpd] Make the server header configurable with new config
+ option
+ <seealso marker="httpd#prop_server_tokens">server_tokens</seealso>.
+ The value of the server header, which was previously hard-coded
+ (at compile time), is now possible to manipulate through the means
+ of the
+ <seealso marker="httpd#prop_server_tokens">server_tokens</seealso>
+ config option. </p>
+ <p>Own Id: OTP-9805</p>
+ </item>
+
+ <item>
+ <p>Improve inets support for inets as an included application. </p>
+ <p><c>inets_app</c> calls <c>supervisor:start_link/3</c> directly
+ rather than calling the root supervisor function
+ <c>inets_sup:start_link/0</c>.
+ This precludes using included_applications to start inets without
+ having a wrapper function. </p>
+ <p>Jay Nelson</p>
+ <p>Own Id: OTP-9960</p>
+ </item>
+
+ <item>
+ <p>[httpc] Add function for retrieving current options,
+ <seealso marker="httpc#get_options">get_options/1,2</seealso>. </p>
+ <p>Own Id: OTP-9979</p>
+ </item>
+ <item>
+ <p>Utility module
+ <seealso marker="http_uri">http_uri</seealso>
+ now officially supported. </p>
+ <p>Also, the
+ <seealso marker="http_uri#parse">parse</seealso>
+ function has been extended with more
+ scheme support and a way to provide your own scheme info. </p>
+ <p>Own Id: OTP-9983</p>
+ <p>Aux Id: Seq 12022</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpd] Fix logging of content length in mod_log. </p>
+ <p>Garrett Smith</p>
+ <p>Own Id: OTP-9715</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+<!--
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+
+ <list>
+ <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.9 -->
+
+
+ <section><title>Inets 5.8.1</title>
<section><title>Improvements and New Features</title>
<p>-</p>
@@ -41,7 +208,7 @@
<list>
<item>
<p>[httpc|httpd] Added support for IPv6 with ssl. </p>
- <p>Own Id: OTP-5566</p>
+ <p>Own Id: OTP-5566</p>
</item>
</list>
@@ -50,20 +217,105 @@
</section>
<section><title>Fixed Bugs and Malfunctions</title>
+<!--
<p>-</p>
+-->
+ <list>
+ <item>
+ <p>[ftp] Fails to open IPv6 connection due to badly formatted
+ IPv6 address in EPRT command. The address part of the command
+ incorrectly contained decimal elements instead of hexadecimal. </p>
+ <p>Own Id: OTP-9827</p>
+ <p>Aux Id: Seq 11970 </p>
+ </item>
+
+ <item>
+ <p>[httpc] Bad Keep Alive Mode. When selecting a session,
+ the "state" of the session (specifically if the server has
+ responded) was not taken into account. </p>
+ <p>Own Id: OTP-9847</p>
+ </item>
+
+ <item>
+ <p>[httpc] The client incorrectly streams 404 responses.
+ The documentation specifies that only 200 and 206 responses
+ shall be streamed. </p>
+ <p>Shane Evens</p>
+ <p>Own Id: OTP-9860</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 5.8.1 -->
+
+
+ <section><title>Inets 5.8</title>
+
+ <section><title>Improvements and New Features</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>
+ <p>[ftpc] Add a config option to specify a
+ <seealso marker="ftp#dtimeout">data connect timeout</seealso>.
+ That is how long the ftp client will wait for the server to connect
+ to the data socket. If this timeout occurs, an error will be
+ returned to the caller and the ftp client process will be
+ terminated. </p>
+ <p>Own Id: OTP-9545</p>
+ </item>
+
+ <item>
+ <p>[httpc] Wrong Host header in IPv6 HTTP requests.
+ When a URI with a IPv6 host is parsed, the brackets that encapsulates
+ the address part is removed. This value is then supplied as the host
+ header. This can cause problems with some servers.
+ A workaround for this is to use headers_as_is and provide the host
+ header with the requst call.
+ To solve this a new option has been added,
+ <seealso marker="httpc#ipv6_host_with_brackets">ipv6_host_with_brackets</seealso>.
+ This option specifies if the host value of the host header shall
+ include the brackets or not. By default, it does not (as before).
+ </p>
+ <p>Own Id: OTP-9628</p>
</item>
</list>
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
-->
+ <list>
+ <item>
+ <p>[httpd] Fix logging of content length in mod_log. </p>
+ <p>Garrett Smith</p>
+ <p>Own Id: OTP-9715</p>
+ </item>
+
+ <item>
+ <p>[httpd] Sometimes entries in the transfer log was written
+ with the message size as list of numbers. This list was actually
+ the size as a string, e.g. "123", written with the control
+ sequence ~w. This has now been corrected so that any string is
+ converted to an integer (if possible). </p>
+ <p>Own Id: OTP-9733</p>
+ </item>
+
+ <item>
+ <p>Fixed various problems detected by Dialyzer. </p>
+ <p>Own Id: OTP-9736</p>
+ </item>
+
+ </list>
+
</section>
<section>
@@ -94,6 +346,65 @@
</section> <!-- 5.8 -->
+ <section><title>Inets 5.7.2</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>[httpd] XSS prevention did not work for hex-encoded URL's. </p>
+ <p>Own Id: OTP-9655</p>
+ </item>
+
+ <item>
+ <p>[httpd] GET request with malformed header date caused
+ server crash (non-fatal) with no reply to client. Will
+ now result in a reply with status code 400. </p>
+ <p>Own Id: OTP-9674</p>
+ <p>Aux Id: seq11936</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>
+
+ </list>
+
+ </section>
+-->
+
+ </section> <!-- 5.7.2 -->
+
+
<section><title>Inets 5.7.1</title>
<section><title>Improvements and New Features</title>
@@ -266,7 +577,7 @@
<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>
+ <seealso marker="httpd#props_comm">socket_type</seealso>
communication property or the httpc
<seealso marker="httpc#request2">request/4,5</seealso> function
for more info. </p>
@@ -285,7 +596,7 @@
<list>
<item>
<p>[httpd] Wrong
- <seealso marker="httpd#sec_prop">security property</seealso>
+ <seealso marker="httpd#props_sec">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>
@@ -469,7 +780,7 @@
the <c>essl</c> tag instead. </p>
<p>See the <c>http_option</c> option in the
<seealso marker="httpc#request2">request/4,5</seealso> or
- the <seealso marker="httpd#comm_prop">socket-type</seealso>
+ the <seealso marker="httpd#props_comm">socket-type</seealso>
section of the Communication properties chapter for more info, </p>
<p>Own Id: OTP-7907</p>
</item>
@@ -486,9 +797,9 @@
<p>[httpd] - Improved mod_alias.
Now able to do better URL rewrites. </p>
<p>See
- <seealso marker="httpd#alias_prop">URL aliasing properties</seealso>
+ <seealso marker="httpd#props_alias">URL aliasing properties</seealso>
and the
- <seealso marker="httpd#cgi_prop">CGI properties</seealso>
+ <seealso marker="httpd#props_cgi">CGI properties</seealso>
section(s) for more info, </p>
<p>Own Id: OTP-8573</p>
</item>
@@ -1074,7 +1385,7 @@
<p>Default is <c>inet6fb4</c> which emulates the
behaviour of the previous version. </p>
<p>See the
- <seealso marker="httpd#comm_prop">Communication properties</seealso>
+ <seealso marker="httpd#props_comm">Communication properties</seealso>
section for more info. </p>
<p>Own Id: OTP-8069</p>
<p>Aux Id: seq11086</p>
diff --git a/lib/inets/doc/src/notes_history.xml b/lib/inets/doc/src/notes_history.xml
index 151bec375e..bd59c1ba47 100644
--- a/lib/inets/doc/src/notes_history.xml
+++ b/lib/inets/doc/src/notes_history.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>2004</year><year>2011</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/part.xml b/lib/inets/doc/src/part.xml
index 36955df6b3..3b6734a9b8 100644
--- a/lib/inets/doc/src/part.xml
+++ b/lib/inets/doc/src/part.xml
@@ -1,10 +1,10 @@
-<?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">
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/part_notes.xml b/lib/inets/doc/src/part_notes.xml
index 21f464318b..81b0dedbfa 100644
--- a/lib/inets/doc/src/part_notes.xml
+++ b/lib/inets/doc/src/part_notes.xml
@@ -1,10 +1,10 @@
-<?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">
<header>
<copyright>
- <year>2002</year><year>2009</year>
+ <year>2002</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/part_notes_history.xml b/lib/inets/doc/src/part_notes_history.xml
index 3c1e6f5232..f714a6d2e3 100644
--- a/lib/inets/doc/src/part_notes_history.xml
+++ b/lib/inets/doc/src/part_notes_history.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE part SYSTEM "part.dtd">
<part>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/ref_man.xml b/lib/inets/doc/src/ref_man.xml
index 45d5dfcd0e..e44829827c 100644
--- a/lib/inets/doc/src/ref_man.xml
+++ b/lib/inets/doc/src/ref_man.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>1997</year><year>2010</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,8 +30,8 @@
</header>
<description>
<p>Inets is a container for Internet clients and
- servers. Currently a FTP client, a HTTP client and server, and
- a tftp client and server has been incorporated in Inets.</p>
+ servers. Currently a FTP client, a HTTP client and server, and
+ a tftp client and server has been incorporated in Inets.</p>
</description>
<xi:include href="inets.xml"/>
<xi:include href="ftp.xml"/>
@@ -45,6 +45,7 @@
<xi:include href="mod_auth.xml"/>
<xi:include href="mod_esi.xml"/>
<xi:include href="mod_security.xml"/>
+ <xi:include href="http_uri.xml"/>
</application>
diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml
index 96d6ae0dd5..0b3e93a153 100644
--- a/lib/inets/doc/src/tftp.xml
+++ b/lib/inets/doc/src/tftp.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>2009</year>
+ <year>2006</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -218,6 +218,8 @@
<c>5</c> times when the timeout expires.</p>
</item>
</taglist>
+
+ <marker id="start1"></marker>
</section>
<funcs>
@@ -231,11 +233,14 @@
</type>
<desc>
<p>Starts a daemon process which listens for udp packets on a
- port. When it receives a request for read or write it spawns
- a temporary server process which handles the actual transfer
- of the (virtual) file.</p>
+ port. When it receives a request for read or write it spawns
+ a temporary server process which handles the actual transfer
+ of the (virtual) file.</p>
+
+ <marker id="read_file"></marker>
</desc>
</func>
+
<func>
<name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
<fsummary>Read a (virtual) file from a TFTP server</fsummary>
@@ -248,23 +253,26 @@
</type>
<desc>
<p>Reads a (virtual) file <c>RemoteFilename</c> from a TFTP
- server.</p>
- <p>If <c>LocalFilename</c> is the atom <c>binary</c>,
- <c>tftp_binary</c> is used as callback module. It concatenates
- all transferred blocks and returns them as one single binary
- in <c>LastCallbackState</c>.</p>
- <p>If <c>LocalFilename</c> is a string and there are no
- registered callback modules, <c>tftp_file</c> is used as
- callback module. It writes each transferred block to the file
- named <c>LocalFilename</c> and returns the number of
- transferred bytes in <c>LastCallbackState</c>.</p>
- <p>If <c>LocalFilename</c> is a string and there are registered
- callback modules, <c>LocalFilename</c> is tested against
- the regexps of these and the callback module corresponding to
- the first match is used, or an error tuple is returned if no
- matching regexp is found.</p>
+ server.</p>
+ <p>If <c>LocalFilename</c> is the atom <c>binary</c>,
+ <c>tftp_binary</c> is used as callback module. It concatenates
+ all transferred blocks and returns them as one single binary
+ in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are no
+ registered callback modules, <c>tftp_file</c> is used as
+ callback module. It writes each transferred block to the file
+ named <c>LocalFilename</c> and returns the number of
+ transferred bytes in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are registered
+ callback modules, <c>LocalFilename</c> is tested against
+ the regexps of these and the callback module corresponding to
+ the first match is used, or an error tuple is returned if no
+ matching regexp is found.</p>
</desc>
+
+ <marker id="write_file"></marker>
</func>
+
<func>
<name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
<fsummary>Write a (virtual) file to a TFTP server</fsummary>
@@ -288,10 +296,12 @@
block by block and returns the number of transferred bytes
in <c>LastCallbackState</c>.</p>
<p>If <c>LocalFilename</c> is a string and there are registered
- callback modules, <c>LocalFilename</c> is tested against
- the regexps of these and the callback module corresponding to
- the first match is used, or an error tuple is returned if no
- matching regexp is found.</p>
+ callback modules, <c>LocalFilename</c> is tested against
+ the regexps of these and the callback module corresponding to
+ the first match is used, or an error tuple is returned if no
+ matching regexp is found.</p>
+
+ <marker id="info_daemons"></marker>
</desc>
</func>
@@ -304,8 +314,9 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Returns info about all TFTP daemon processes.
- </p>
+ <p>Returns info about all TFTP daemon processes. </p>
+
+ <marker id="info_servers"></marker>
</desc>
</func>
@@ -318,8 +329,9 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Returns info about all TFTP server processes.
- </p>
+ <p>Returns info about all TFTP server processes. </p>
+
+ <marker id="info_pid"></marker>
</desc>
</func>
@@ -332,6 +344,8 @@
</type>
<desc>
<p>Returns info about a TFTP daemon, server or client process.</p>
+
+ <marker id="change_config_daemons"></marker>
</desc>
</func>
@@ -346,8 +360,9 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Changes config for all TFTP daemon processes
- </p>
+ <p>Changes config for all TFTP daemon processes. </p>
+
+ <marker id="change_config_servers"></marker>
</desc>
</func>
@@ -362,8 +377,9 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Changes config for all TFTP server processes
- </p>
+ <p>Changes config for all TFTP server processes. </p>
+
+ <marker id="change_config_pid"></marker>
</desc>
</func>
@@ -378,8 +394,11 @@
</type>
<desc>
<p>Changes config for a TFTP daemon, server or client process</p>
+
+ <marker id="start2"></marker>
</desc>
</func>
+
<func>
<name>start() -> ok | {error, Reason}</name>
<fsummary>Start the Inets application</fsummary>
@@ -442,8 +461,9 @@
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>
+ consumer lesser resources. </p>
+
+ <marker id="prepare"></marker>
</section>
<funcs>
@@ -468,17 +488,20 @@
<v>Text = string()</v>
</type>
<desc>
- <p>Prepares to open a file on the client side.</p>
- <p>No new options may be added, but the ones that are present in
- <c>SuggestedOptions</c> may be omitted or replaced with new
- values in <c>AcceptedOptions</c>.</p>
- <p>Will be followed by a call to <c>open/4</c> before any
- read/write access is performed. <c>AcceptedOptions</c> is
- sent to the server which replies with those options that it
- accepts. These will be forwarded to <c>open/4</c> as
- <c>SuggestedOptions</c>.</p>
+ <p>Prepares to open a file on the client side.</p>
+ <p>No new options may be added, but the ones that are present in
+ <c>SuggestedOptions</c> may be omitted or replaced with new
+ values in <c>AcceptedOptions</c>.</p>
+ <p>Will be followed by a call to <c>open/4</c> before any
+ read/write access is performed. <c>AcceptedOptions</c> is
+ sent to the server which replies with those options that it
+ accepts. These will be forwarded to <c>open/4</c> as
+ <c>SuggestedOptions</c>.</p>
+
+ <marker id="open"></marker>
</desc>
</func>
+
<func>
<name>open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
<fsummary>Open a file for read or write access</fsummary>
@@ -503,14 +526,17 @@
<desc>
<p>Opens a file for read or write access.</p>
<p>On the client side where the <c>open/5</c> call has been
- preceded by a call to <c>prepare/5</c>, all options must be
- accepted or rejected.</p>
- <p>On the server side, where there is no preceding
- <c>prepare/5</c> call, no new options may be added, but
- the ones that are present in <c>SuggestedOptions</c> may be
- omitted or replaced with new values in <c>AcceptedOptions</c>.</p>
+ preceded by a call to <c>prepare/5</c>, all options must be
+ accepted or rejected.</p>
+ <p>On the server side, where there is no preceding
+ <c>prepare/5</c> call, no new options may be added, but
+ the ones that are present in <c>SuggestedOptions</c> may be
+ omitted or replaced with new values in <c>AcceptedOptions</c>.</p>
+
+ <marker id="read"></marker>
</desc>
</func>
+
<func>
<name>read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name>
<fsummary>Read a chunk from the file</fsummary>
@@ -526,15 +552,18 @@
<desc>
<p>Read a chunk from the file.</p>
<p>The callback function is expected to close
- the file when the last file chunk is
- encountered. When an error is encountered
- the callback function is expected to clean
- up after the aborted file transfer, such as
- closing open file descriptors etc. In both
- cases there will be no more calls to any of
- the callback functions.</p>
+ the file when the last file chunk is
+ encountered. When an error is encountered
+ the callback function is expected to clean
+ up after the aborted file transfer, such as
+ closing open file descriptors etc. In both
+ cases there will be no more calls to any of
+ the callback functions.</p>
+
+ <marker id="write"></marker>
</desc>
</func>
+
<func>
<name>write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name>
<fsummary>Write a chunk to the file</fsummary>
@@ -550,15 +579,18 @@
<desc>
<p>Write a chunk to the file.</p>
<p>The callback function is expected to close
- the file when the last file chunk is
- encountered. When an error is encountered
- the callback function is expected to clean
- up after the aborted file transfer, such as
- closing open file descriptors etc. In both
- cases there will be no more calls to any of
- the callback functions.</p>
+ the file when the last file chunk is
+ encountered. When an error is encountered
+ the callback function is expected to clean
+ up after the aborted file transfer, such as
+ closing open file descriptors etc. In both
+ cases there will be no more calls to any of
+ the callback functions.</p>
+
+ <marker id="abort"></marker>
</desc>
</func>
+
<func>
<name>abort(Code, Text, State) -> ok</name>
<fsummary>Abort the file transfer</fsummary>
@@ -572,14 +604,14 @@
<desc>
<p>Invoked when the file transfer is aborted.</p>
<p>The callback function is expected to clean
- up its used resources after the aborted file
- transfer, such as closing open file
- descriptors etc. The function will not be
- invoked if any of the other callback
- functions returns an error, as it is
- expected that they already have cleaned up
- the necessary resources. It will however be
- invoked if the functions fails (crashes).</p>
+ up its used resources after the aborted file
+ transfer, such as closing open file
+ descriptors etc. The function will not be
+ invoked if any of the other callback
+ functions returns an error, as it is
+ expected that they already have cleaned up
+ the necessary resources. It will however be
+ invoked if the functions fails (crashes).</p>
</desc>
</func>
</funcs>
@@ -589,7 +621,9 @@
<title>LOGGER FUNCTIONS</title>
<p>A <c>tftp_logger</c> callback module should be implemented as a
- <c>tftp_logger</c> behavior and export the functions listed below.</p>
+ <c>tftp_logger</c> behavior and export the functions listed below.</p>
+
+ <marker id="error_msg"></marker>
</section>
<funcs>
@@ -602,7 +636,10 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Log an error message. See <c>error_logger:error_msg/2 for details.</c> </p>
+ <p>Log an error message.
+ See <c>error_logger:error_msg/2 for details.</c> </p>
+
+ <marker id="warning_msg"></marker>
</desc>
</func>
@@ -615,7 +652,10 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Log a warning message. See <c>error_logger:warning_msg/2 for details.</c> </p>
+ <p>Log a warning message.
+ See <c>error_logger:warning_msg/2 for details.</c> </p>
+
+ <marker id="info_msg"></marker>
</desc>
</func>
@@ -628,7 +668,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Log an info message. See <c>error_logger:info_msg/2 for details.</c> </p>
+ <p>Log an info message.
+ See <c>error_logger:info_msg/2 for details.</c> </p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/examples/httpd_load_test/Makefile b/lib/inets/examples/httpd_load_test/Makefile
index 1cc61ad8ae..de1b2a289f 100644
--- a/lib/inets/examples/httpd_load_test/Makefile
+++ b/lib/inets/examples/httpd_load_test/Makefile
@@ -34,7 +34,7 @@ VSN=$(INETS_VSN)
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
-EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
+EXAMPLE_RELSYSDIR = "$(RELSYSDIR)/examples"
HDLT_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/httpd_load_test
diff --git a/lib/inets/examples/server_root/Makefile b/lib/inets/examples/server_root/Makefile
index d7a3231068..2230a7eafc 100644
--- a/lib/inets/examples/server_root/Makefile
+++ b/lib/inets/examples/server_root/Makefile
@@ -174,36 +174,36 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/auth
- $(INSTALL_DATA) $(AUTH_FILES) $(RELSYSDIR)/examples/server_root/auth
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/cgi-bin
- $(INSTALL_SCRIPT) $(CGI_FILES) $(RELSYSDIR)/examples/server_root/cgi-bin
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/conf
- $(INSTALL_DATA) $(CONF_FILES) $(RELSYSDIR)/examples/server_root/conf
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/open
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/auth"
+ $(INSTALL_DATA) $(AUTH_FILES) "$(RELSYSDIR)/examples/server_root/auth"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/cgi-bin"
+ $(INSTALL_SCRIPT) $(CGI_FILES) "$(RELSYSDIR)/examples/server_root/cgi-bin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/conf"
+ $(INSTALL_DATA) $(CONF_FILES) "$(RELSYSDIR)/examples/server_root/conf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/htdocs/open"
$(INSTALL_DATA) $(OPEN_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/open
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/mnesia_open
+ "$(RELSYSDIR)/examples/server_root/htdocs/open"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/htdocs/mnesia_open"
$(INSTALL_DATA) $(MNESIA_OPEN_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_open
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/misc
+ "$(RELSYSDIR)/examples/server_root/htdocs/mnesia_open"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/htdocs/misc"
$(INSTALL_DATA) $(MISC_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/misc
+ "$(RELSYSDIR)/examples/server_root/htdocs/misc"
$(INSTALL_DIR) \
- $(RELSYSDIR)/examples/server_root/htdocs/secret/top_secret
+ "$(RELSYSDIR)/examples/server_root/htdocs/secret/top_secret"
$(INSTALL_DIR) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret/top_secret
+ "$(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret/top_secret"
$(INSTALL_DATA) $(SECRET_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/secret
+ "$(RELSYSDIR)/examples/server_root/htdocs/secret"
$(INSTALL_DATA) $(MNESIA_SECRET_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs
- $(INSTALL_DATA) $(HTDOCS_FILES) $(RELSYSDIR)/examples/server_root/htdocs
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/icons
- $(INSTALL_DATA) $(ICON_FILES) $(RELSYSDIR)/examples/server_root/icons
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/ssl
- $(INSTALL_DATA) $(SSL_FILES) $(RELSYSDIR)/examples/server_root/ssl
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/logs
+ "$(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/htdocs"
+ $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/examples/server_root/htdocs"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/icons"
+ $(INSTALL_DATA) $(ICON_FILES) "$(RELSYSDIR)/examples/server_root/icons"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/ssl"
+ $(INSTALL_DATA) $(SSL_FILES) "$(RELSYSDIR)/examples/server_root/ssl"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/server_root/logs"
release_docs_spec:
diff --git a/lib/inets/priv/Makefile b/lib/inets/priv/Makefile
index 85da409e55..4dc521f618 100644
--- a/lib/inets/priv/Makefile
+++ b/lib/inets/priv/Makefile
@@ -57,8 +57,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_SCRIPT) $(EXECUTABLES) $(RELSYSDIR)/priv/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_SCRIPT) $(EXECUTABLES) "$(RELSYSDIR)/priv/bin"
release_docs_spec:
diff --git a/lib/inets/priv/plt/.gitignore b/lib/inets/priv/plt/.gitignore
new file mode 100644
index 0000000000..2051b52d48
--- /dev/null
+++ b/lib/inets/priv/plt/.gitignore
@@ -0,0 +1,2 @@
+/*.plt
+/*.dialyzer_analysis
diff --git a/lib/inets/src/ftp/Makefile b/lib/inets/src/ftp/Makefile
index 19b93870df..426286f254 100644
--- a/lib/inets/src/ftp/Makefile
+++ b/lib/inets/src/ftp/Makefile
@@ -88,11 +88,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/ftp
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/ftp
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/ftp"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/ftp"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index ac72963347..fe25c23316 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,9 +55,10 @@
-include("ftp_internal.hrl").
%% Constante used in internal state definition
--define(CONNECTION_TIMEOUT, 60*1000).
--define(DEFAULT_MODE, passive).
--define(PROGRESS_DEFAULT, ignore).
+-define(CONNECTION_TIMEOUT, 60*1000).
+-define(DATA_ACCEPT_TIMEOUT, infinity).
+-define(DEFAULT_MODE, passive).
+-define(PROGRESS_DEFAULT, ignore).
%% Internal Constants
-define(FTP_PORT, 21).
@@ -88,7 +89,8 @@
%% data needed further on.
caller = undefined, % term()
ipfamily, % inet | inet6 | inet6fb4
- progress = ignore % ignore | pid()
+ progress = ignore, % ignore | pid()
+ dtimeout = ?DATA_ACCEPT_TIMEOUT % non_neg_integer() | infinity
}).
@@ -847,6 +849,7 @@ start_options(Options) ->
%% host
%% port
%% timeout
+%% dtimeout
%% progress
open_options(Options) ->
?fcrt("open_options", [{options, Options}]),
@@ -875,7 +878,12 @@ open_options(Options) ->
(_) -> false
end,
ValidateTimeout =
- fun(Timeout) when is_integer(Timeout) andalso (Timeout > 0) -> true;
+ fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true;
+ (_) -> false
+ end,
+ ValidateDTimeout =
+ fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true;
+ (infinity) -> true;
(_) -> false
end,
ValidateProgress =
@@ -893,6 +901,7 @@ open_options(Options) ->
{port, ValidatePort, false, ?FTP_PORT},
{ipfamily, ValidateIpFamily, false, inet},
{timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT},
+ {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT},
{progress, ValidateProgress, false, ?PROGRESS_DEFAULT}],
validate_options(Options, ValidOptions, []).
@@ -1037,13 +1046,15 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
Mode = key_search(mode, Opts, ?DEFAULT_MODE),
Port = key_search(port, Opts, ?FTP_PORT),
Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
+ DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
Progress = key_search(progress, Opts, ignore),
IpFamily = key_search(ipfamily, Opts, inet),
-
+
State2 = State#state{client = From,
mode = Mode,
progress = progress(Progress),
- ipfamily = IpFamily},
+ ipfamily = IpFamily,
+ dtimeout = DTimeout},
?fcrd("handle_call(open) -> setup ctrl connection with",
[{host, Host}, {port, Port}, {timeout, Timeout}]),
@@ -1064,11 +1075,13 @@ handle_call({_, {open, ip_comm, Host, Opts}}, From, State) ->
Mode = key_search(mode, Opts, ?DEFAULT_MODE),
Port = key_search(port, Opts, ?FTP_PORT),
Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
+ DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
Progress = key_search(progress, Opts, ignore),
State2 = State#state{client = From,
mode = Mode,
- progress = progress(Progress)},
+ progress = progress(Progress),
+ dtimeout = DTimeout},
case setup_ctrl_connection(Host, Port, Timeout, State2) of
{ok, State3, WaitTimeout} ->
@@ -1657,9 +1670,19 @@ handle_ctrl_result({pos_compl, Lines},
%%--------------------------------------------------------------------------
%% Directory listing
handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State) ->
- NewState = accept_data_connection(State),
- activate_data_connection(NewState),
- {noreply, NewState#state{caller = {handle_dir_result, Dir}}};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ activate_data_connection(NewState),
+ {noreply, NewState#state{caller = {handle_dir_result, Dir}}};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
Data}, client = From}
@@ -1756,9 +1779,19 @@ handle_ctrl_result({Status, _},
%%--------------------------------------------------------------------------
%% File handling - recv_bin
handle_ctrl_result({pos_prel, _}, #state{caller = recv_bin} = State) ->
- NewState = accept_data_connection(State),
- activate_data_connection(NewState),
- {noreply, NewState};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ activate_data_connection(NewState),
+ {noreply, NewState};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({pos_compl, _}, #state{caller = {recv_bin, Data},
client = From} = State) ->
@@ -1780,16 +1813,37 @@ handle_ctrl_result({Status, _}, #state{caller = {recv_bin, _}} = State) ->
handle_ctrl_result({pos_prel, _}, #state{client = From,
caller = start_chunk_transfer}
= State) ->
- NewState = accept_data_connection(State),
- gen_server:reply(From, ok),
- {noreply, NewState#state{chunk = true, client = undefined,
- caller = undefined}};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ gen_server:reply(From, ok),
+ {noreply, NewState#state{chunk = true, client = undefined,
+ caller = undefined}};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
+
%%--------------------------------------------------------------------------
%% File handling - recv_file
handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State) ->
- NewState = accept_data_connection(State),
- activate_data_connection(NewState),
- {noreply, NewState};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ activate_data_connection(NewState),
+ {noreply, NewState};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
file_close(Fd),
@@ -1800,17 +1854,38 @@ handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
%% File handling - transfer_*
handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}}
= State) ->
- NewState = accept_data_connection(State),
- send_file(Fd, NewState);
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ send_file(Fd, NewState);
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
= State) ->
- NewState = accept_data_connection(State),
- send_data_message(NewState, Bin),
- close_data_connection(NewState),
- activate_ctrl_connection(NewState),
- {noreply, NewState#state{caller = transfer_data_second_phase,
- dsock = undefined}};
+ case accept_data_connection(State) of
+ {ok, NewState} ->
+ send_data_message(NewState, Bin),
+ close_data_connection(NewState),
+ activate_ctrl_connection(NewState),
+ {noreply, NewState#state{caller = transfer_data_second_phase,
+ dsock = undefined}};
+ {error, _Reason} = ERROR ->
+ case State#state.client of
+ undefined ->
+ {stop, ERROR, State};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State#state{client = undefined}}
+ end
+ end;
+
%%--------------------------------------------------------------------------
%% Default
handle_ctrl_result({Status, Lines}, #state{client = From} = State)
@@ -1912,17 +1987,14 @@ setup_ctrl_connection(Host, Port, Timeout, State) ->
setup_data_connection(#state{mode = active,
caller = Caller,
csock = CSock} = State) ->
- IntToString = fun(Element) -> integer_to_list(Element) end,
-
case (catch inet:sockname(CSock)) of
{ok, {{_, _, _, _, _, _, _, _} = IP, _}} ->
{ok, LSock} =
gen_tcp:listen(0, [{ip, IP}, {active, false},
inet6, binary, {packet, 0}]),
{ok, Port} = inet:port(LSock),
- Cmd = mk_cmd("EPRT |2|~s:~s:~s:~s:~s:~s:~s:~s|~s|",
- lists:map(IntToString,
- tuple_to_list(IP) ++ [Port])),
+ IpAddress = inet_parse:ntoa(IP),
+ Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
send_ctrl_message(State, Cmd),
activate_ctrl_connection(State),
{noreply, State#state{caller = {setup_data_connection,
@@ -2009,16 +2081,20 @@ connect2(Host, Port, IpFam, Timeout) ->
Error
end.
-
-accept_data_connection(#state{mode = active,
- dsock = {lsock, LSock}} = State) ->
- {ok, Socket} = gen_tcp:accept(LSock),
- gen_tcp:close(LSock),
- State#state{dsock = Socket};
+accept_data_connection(#state{mode = active,
+ dtimeout = DTimeout,
+ dsock = {lsock, LSock}} = State) ->
+ case gen_tcp:accept(LSock, DTimeout) of
+ {ok, Socket} ->
+ gen_tcp:close(LSock),
+ {ok, State#state{dsock = Socket}};
+ {error, Reason} ->
+ {error, {data_connect_failed, Reason}}
+ end;
accept_data_connection(#state{mode = passive} = State) ->
- State.
+ {ok, State}.
send_ctrl_message(#state{csock = Socket, verbose = Verbose}, Message) ->
%% io:format("send control message: ~n~p~n", [lists:flatten(Message)]),
diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile
index 3960c36d00..850c790bd1 100644
--- a/lib/inets/src/http_client/Makefile
+++ b/lib/inets/src/http_client/Makefile
@@ -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
@@ -89,11 +89,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/http_client
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/http_client
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/http_client"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/http_client"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index 75c26c63cc..b6e7708353 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,12 +31,15 @@
-export([
request/1, request/2, request/4, request/5,
cancel_request/1, cancel_request/2,
- set_option/2, set_option/3,
+ set_option/2, set_option/3,
set_options/1, set_options/2,
+ get_option/1, get_option/2,
+ get_options/1, get_options/2,
store_cookies/2, store_cookies/3,
- cookie_header/1, cookie_header/2,
+ cookie_header/1, cookie_header/2, cookie_header/3,
which_cookies/0, which_cookies/1,
reset_cookies/0, reset_cookies/1,
+ which_sessions/0, which_sessions/1,
stream_next/1,
default_profile/0,
profile_name/1, profile_name/2,
@@ -141,7 +144,9 @@ request(Url, Profile) ->
request(Method, Request, HttpOptions, Options) ->
request(Method, Request, HttpOptions, Options, default_profile()).
-request(Method, {Url, Headers}, HTTPOptions, Options, Profile)
+request(Method,
+ {Url, Headers},
+ HTTPOptions, Options, Profile)
when (Method =:= options) orelse
(Method =:= get) orelse
(Method =:= head) orelse
@@ -154,15 +159,17 @@ request(Method, {Url, Headers}, HTTPOptions, Options, Profile)
{http_options, HTTPOptions},
{options, Options},
{profile, Profile}]),
- case http_uri:parse(Url) of
+ case uri_parse(Url, Options) of
{error, Reason} ->
{error, Reason};
- ParsedUrl ->
+ {ok, ParsedUrl} ->
handle_request(Method, Url, ParsedUrl, Headers, [], [],
HTTPOptions, Options, Profile)
end;
-request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options, Profile)
+request(Method,
+ {Url, Headers, ContentType, Body},
+ HTTPOptions, Options, Profile)
when ((Method =:= post) orelse (Method =:= put)) andalso
(is_atom(Profile) orelse is_pid(Profile)) ->
?hcrt("request", [{method, Method},
@@ -173,10 +180,10 @@ request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options, Profile)
{http_options, HTTPOptions},
{options, Options},
{profile, Profile}]),
- case http_uri:parse(Url) of
+ case uri_parse(Url, Options) of
{error, Reason} ->
{error, Reason};
- ParsedUrl ->
+ {ok, ParsedUrl} ->
handle_request(Method, Url,
ParsedUrl, Headers, ContentType, Body,
HTTPOptions, Options, Profile)
@@ -226,7 +233,7 @@ cancel_request(RequestId, Profile)
set_options(Options) ->
set_options(Options, default_profile()).
set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) ->
- ?hcrt("set cookies", [{options, Options}, {profile, Profile}]),
+ ?hcrt("set options", [{options, Options}, {profile, Profile}]),
case validate_options(Options) of
{ok, Opts} ->
try
@@ -249,6 +256,59 @@ set_option(Key, Value, Profile) ->
%%--------------------------------------------------------------------------
+%% get_options(OptionItems) -> {ok, Values} | {error, Reason}
+%% get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}
+%% OptionItems - all | [option_item()]
+%% option_item() - proxy | pipeline_timeout | max_pipeline_length |
+%% keep_alive_timeout | max_keep_alive_length |
+%% max_sessions | verbose |
+%% cookies | ipfamily | ip | port | socket_opts
+%% Profile - atom()
+%% Values - [{option_item(), term()}]
+%% Reason - term()
+%% Description: Retrieves the current options.
+%%-------------------------------------------------------------------------
+
+get_options() ->
+ record_info(fields, options).
+
+get_options(Options) ->
+ get_options(Options, default_profile()).
+
+get_options(all = _Options, Profile) ->
+ get_options(get_options(), Profile);
+get_options(Options, Profile)
+ when (is_list(Options) andalso
+ (is_atom(Profile) orelse is_pid(Profile))) ->
+ ?hcrt("get options", [{options, Options}, {profile, Profile}]),
+ case Options -- get_options() of
+ [] ->
+ try
+ begin
+ {ok, httpc_manager:get_options(Options,
+ profile_name(Profile))}
+ end
+ catch
+ exit:{noproc, _} ->
+ {error, inets_not_started}
+ end;
+ InvalidGetOptions ->
+ {error, {invalid_options, InvalidGetOptions}}
+ end.
+
+get_option(Key) ->
+ get_option(Key, default_profile()).
+
+get_option(Key, Profile) ->
+ case get_options([Key], Profile) of
+ {ok, [{Key, Value}]} ->
+ {ok, Value};
+ Error ->
+ Error
+ end.
+
+
+%%--------------------------------------------------------------------------
%% store_cookies(SetCookieHeaders, Url [, Profile]) -> ok | {error, reason}
%%
%%
@@ -267,7 +327,10 @@ store_cookies(SetCookieHeaders, Url, Profile)
{profile, Profile}]),
try
begin
- {_, _, Host, Port, Path, _} = http_uri:parse(Url),
+ %% Since the Address part is not actually used
+ %% by the manager when storing cookies, we dont
+ %% care about ipv6-host-with-brackets.
+ {ok, {_, _, Host, Port, Path, _}} = uri_parse(Url),
Address = {Host, Port},
ProfileName = profile_name(Profile),
Cookies = httpc_cookie:cookies(SetCookieHeaders, Path, Host),
@@ -283,26 +346,35 @@ store_cookies(SetCookieHeaders, Url, Profile)
%%--------------------------------------------------------------------------
-%% cookie_header(Url [, Profile]) -> Header | {error, Reason}
-%%
+%% cookie_header(Url) -> Header | {error, Reason}
+%% cookie_header(Url, Profile) -> Header | {error, Reason}
+%% cookie_header(Url, Opts, Profile) -> Header | {error, Reason}
+%%
%% Description: Returns the cookie header that would be sent when making
%% a request to <Url>.
%%-------------------------------------------------------------------------
cookie_header(Url) ->
cookie_header(Url, default_profile()).
-cookie_header(Url, Profile) ->
+cookie_header(Url, Profile) when is_atom(Profile) orelse is_pid(Profile) ->
+ cookie_header(Url, [], Profile);
+cookie_header(Url, Opts) when is_list(Opts) ->
+ cookie_header(Url, Opts, default_profile()).
+
+cookie_header(Url, Opts, Profile)
+ when (is_list(Opts) andalso (is_atom(Profile) orelse is_pid(Profile))) ->
?hcrt("cookie header", [{url, Url},
+ {opts, Opts},
{profile, Profile}]),
try
begin
- httpc_manager:which_cookies(Url, profile_name(Profile))
+ httpc_manager:which_cookies(Url, Opts, profile_name(Profile))
end
catch
exit:{noproc, _} ->
{error, {not_started, Profile}}
end.
-
+
%%--------------------------------------------------------------------------
%% which_cookies() -> [cookie()]
@@ -326,10 +398,32 @@ which_cookies(Profile) ->
%%--------------------------------------------------------------------------
+%% which_sessions() -> {GoodSession, BadSessions, NonSessions}
+%% which_sessions(Profile) -> {GoodSession, BadSessions, NonSessions}
+%%
+%% Description: Debug function, dumping the sessions database, sorted
+%% into three groups (Good-, Bad- and Non-sessions).
+%%-------------------------------------------------------------------------
+which_sessions() ->
+ which_sessions(default_profile()).
+
+which_sessions(Profile) ->
+ ?hcrt("which sessions", [{profile, Profile}]),
+ try
+ begin
+ httpc_manager:which_sessions(profile_name(Profile))
+ end
+ catch
+ exit:{noproc, _} ->
+ {[], [], []}
+ end.
+
+
+%%--------------------------------------------------------------------------
%% info() -> list()
%% info(Profile) -> list()
%%
-%% Description: Debug function, retreive info about the profile
+%% Description: Debug function, retrieve info about the profile
%%-------------------------------------------------------------------------
info() ->
info(default_profile()).
@@ -464,6 +558,8 @@ handle_request(Method, Url,
HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
Receiver = proplists:get_value(receiver, Options),
SocketOpts = proplists:get_value(socket_opts, Options),
+ BracketedHost = proplists:get_value(ipv6_host_with_brackets,
+ Options),
MaybeEscPath = maybe_encode_uri(HTTPOptions, Path),
MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query),
AbsUri = maybe_encode_uri(HTTPOptions, Url),
@@ -482,7 +578,8 @@ handle_request(Method, Url,
stream = Stream,
headers_as_is = headers_as_is(Headers0, Options),
socket_opts = SocketOpts,
- started = Started},
+ started = Started,
+ ipv6_host_with_brackets = BracketedHost},
case httpc_manager:request(Request, profile_name(Profile)) of
{ok, RequestId} ->
@@ -739,14 +836,17 @@ request_options_defaults() ->
error
end,
+ VerifyBrackets = VerifyBoolean,
+
[
- {sync, true, VerifySync},
- {stream, none, VerifyStream},
- {body_format, string, VerifyBodyFormat},
- {full_result, true, VerifyFullResult},
- {headers_as_is, false, VerifyHeaderAsIs},
- {receiver, self(), VerifyReceiver},
- {socket_opts, undefined, VerifySocketOpts}
+ {sync, true, VerifySync},
+ {stream, none, VerifyStream},
+ {body_format, string, VerifyBodyFormat},
+ {full_result, true, VerifyFullResult},
+ {headers_as_is, false, VerifyHeaderAsIs},
+ {receiver, self(), VerifyReceiver},
+ {socket_opts, undefined, VerifySocketOpts},
+ {ipv6_host_with_brackets, false, VerifyBrackets}
].
request_options(Options) ->
@@ -1120,6 +1220,22 @@ validate_headers(RequestHeaders, _, _) ->
RequestHeaders.
+%%--------------------------------------------------------------------------
+%% These functions is just simple wrappers to parse specifically HTTP URIs
+%%--------------------------------------------------------------------------
+
+scheme_defaults() ->
+ [{http, 80}, {https, 443}].
+
+uri_parse(URI) ->
+ http_uri:parse(URI, [{scheme_defaults, scheme_defaults()}]).
+
+uri_parse(URI, Opts) ->
+ http_uri:parse(URI, [{scheme_defaults, scheme_defaults()} | Opts]).
+
+
+%%--------------------------------------------------------------------------
+
child_name2info(undefined) ->
{error, no_such_service};
child_name2info(httpc_manager) ->
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 587e24cc8d..6fe05dec80 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -157,12 +157,12 @@ info(Pid) ->
%% memory in vain.)
%%--------------------------------------------------------------------
%% Request should not be streamed
-stream(BodyPart, Request = #request{stream = none}, _) ->
+stream(BodyPart, #request{stream = none} = Request, _) ->
?hcrt("stream - none", []),
{BodyPart, Request};
%% Stream to caller
-stream(BodyPart, Request = #request{stream = Self}, Code)
+stream(BodyPart, #request{stream = Self} = Request, Code)
when ((Code =:= 200) orelse (Code =:= 206)) andalso
((Self =:= self) orelse (Self =:= {self, once})) ->
?hcrt("stream - self", [{stream, Self}, {code, Code}]),
@@ -170,17 +170,10 @@ stream(BodyPart, Request = #request{stream = Self}, Code)
{Request#request.id, stream, BodyPart}),
{<<>>, Request};
-stream(BodyPart, Request = #request{stream = Self}, 404)
- when (Self =:= self) orelse (Self =:= {self, once}) ->
- ?hcrt("stream - self with 404", [{stream, Self}]),
- httpc_response:send(Request#request.from,
- {Request#request.id, stream, BodyPart}),
- {<<>>, Request};
-
%% Stream to file
%% This has been moved to start_stream/3
%% We keep this for backward compatibillity...
-stream(BodyPart, Request = #request{stream = Filename}, Code)
+stream(BodyPart, #request{stream = Filename} = Request, Code)
when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) ->
?hcrt("stream - filename", [{stream, Filename}, {code, Code}]),
case file:open(Filename, [write, raw, append, delayed_write]) of
@@ -192,7 +185,7 @@ stream(BodyPart, Request = #request{stream = Filename}, Code)
end;
%% Stream to file
-stream(BodyPart, Request = #request{stream = Fd}, Code)
+stream(BodyPart, #request{stream = Fd} = Request, Code)
when ((Code =:= 200) orelse (Code =:= 206)) ->
?hcrt("stream to file", [{stream, Fd}, {code, Code}]),
case file:write(Fd, BodyPart) of
@@ -295,7 +288,7 @@ handle_call(#request{address = Addr} = Request, _,
%% Queue + current
queue:len(NewPipeline) + 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{pipeline = NewPipeline,
session = NewSession,
@@ -363,7 +356,7 @@ handle_call(#request{address = Addr} = Request, _,
%% Queue + current
queue:len(NewKeepAlive) + 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{keep_alive = NewKeepAlive,
session = NewSession,
@@ -377,7 +370,7 @@ handle_call(#request{address = Addr} = Request, _,
NewSession =
Session#session{queue_length = 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
Relaxed =
(Request#request.settings)#http_options.relaxed,
MFA = {httpc_response, parse,
@@ -766,23 +759,52 @@ deliver_answer(Request) ->
%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
%% Purpose: Convert process state when code is changed
%%--------------------------------------------------------------------
-%% code_change(_, #state{request = Request, pipeline = Queue} = State,
-%% [{from, '5.0.1'}, {to, '5.0.2'}]) ->
-%% Settings = new_http_options(Request#request.settings),
-%% NewRequest = Request#request{settings = Settings},
-%% NewQueue = new_queue(Queue, fun new_http_options/1),
-%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
-
-%% code_change(_, #state{request = Request, pipeline = Queue} = State,
-%% [{from, '5.0.2'}, {to, '5.0.1'}]) ->
-%% Settings = old_http_options(Request#request.settings),
-%% NewRequest = Request#request{settings = Settings},
-%% NewQueue = new_queue(Queue, fun old_http_options/1),
-%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
+
+code_change(_,
+ #state{session = OldSession,
+ profile_name = ProfileName} = State,
+ upgrade_from_pre_5_8_1) ->
+ case OldSession of
+ {session,
+ Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type} ->
+ NewSession = #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type},
+ insert_session(NewSession, ProfileName),
+ {ok, State#state{session = NewSession}};
+ _ ->
+ {ok, State}
+ end;
+
+code_change(_,
+ #state{session = OldSession,
+ profile_name = ProfileName} = State,
+ downgrade_to_pre_5_8_1) ->
+ case OldSession of
+ #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type} ->
+ NewSession = {session,
+ Id, ClientClose, Scheme, Socket, SocketType,
+ QueueLen, Type},
+ insert_session(NewSession, ProfileName),
+ {ok, State#state{session = NewSession}};
+ _ ->
+ {ok, State}
+ end;
code_change(_, State, _) ->
{ok, State}.
+
%% new_http_options({http_options, TimeOut, AutoRedirect, SslOpts,
%% Auth, Relaxed}) ->
%% {http_options, "HTTP/1.1", TimeOut, AutoRedirect, SslOpts,
@@ -829,14 +851,17 @@ connect(SocketType, ToAddress,
case IpFamily of
inet6fb4 ->
Opts3 = [inet6 | Opts2],
- case http_transport:connect(SocketType, ToAddress, Opts3, Timeout) of
- {error, _Reason} = Error ->
+ case http_transport:connect(SocketType,
+ ToAddress, Opts3, Timeout) of
+ {error, Reason6} ->
Opts4 = [inet | Opts2],
case http_transport:connect(SocketType,
ToAddress, Opts4, Timeout) of
- {error, _} ->
- %% Reply with the "original" error
- Error;
+ {error, Reason4} ->
+ {error, {failed_connect,
+ [{to_address, ToAddress},
+ {inet6, Opts3, Reason6},
+ {inet, Opts4, Reason4}]}};
OK ->
OK
end;
@@ -845,7 +870,13 @@ connect(SocketType, ToAddress,
end;
_ ->
Opts3 = [IpFamily | Opts2],
- http_transport:connect(SocketType, ToAddress, Opts3, Timeout)
+ case http_transport:connect(SocketType, ToAddress, Opts3, Timeout) of
+ {error, Reason} ->
+ {error, {failed_connect, [{to_address, ToAddress},
+ {IpFamily, Opts3, Reason}]}};
+ Else ->
+ Else
+ end
end.
connect_and_send_first_request(Address, Request, #state{options = Options} = State) ->
@@ -1181,7 +1212,7 @@ handle_pipeline(#state{status = pipeline,
case queue:out(State#state.pipeline) of
{empty, _} ->
- ?hcrd("epmty pipeline queue", []),
+ ?hcrd("pipeline queue empty", []),
%% The server may choose too teminate an idle pipeline
%% in this case we want to receive the close message
@@ -1191,9 +1222,8 @@ handle_pipeline(#state{status = pipeline,
%% If a pipeline that has been idle for some time is not
%% closed by the server, the client may want to close it.
- NewState = activate_queue_timeout(TimeOut, State),
- NewSession = Session#session{queue_length = 0},
- httpc_manager:insert_session(NewSession, ProfileName),
+ NewState = activate_queue_timeout(TimeOut, State),
+ update_session(ProfileName, Session, #session.queue_length, 0),
%% Note mfa will be initilized when a new request
%% arrives.
{noreply,
@@ -1203,6 +1233,7 @@ handle_pipeline(#state{status = pipeline,
headers = undefined,
body = undefined}};
{{value, NextRequest}, Pipeline} ->
+ ?hcrd("pipeline queue non-empty", []),
case lists:member(NextRequest#request.id,
State#state.canceled) of
true ->
@@ -1218,7 +1249,7 @@ handle_pipeline(#state{status = pipeline,
Session#session{queue_length =
%% Queue + current
queue:len(Pipeline) + 1},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
Relaxed =
(NextRequest#request.settings)#http_options.relaxed,
MFA = {httpc_response,
@@ -1257,7 +1288,7 @@ handle_keep_alive_queue(
case queue:out(State#state.keep_alive) of
{empty, _} ->
- ?hcrd("empty keep_alive queue", []),
+ ?hcrd("keep_alive queue empty", []),
%% The server may choose too terminate an idle keep_alive session
%% in this case we want to receive the close message
%% at once and not when trying to send the next
@@ -1266,8 +1297,7 @@ handle_keep_alive_queue(
%% If a keep_alive session has been idle for some time is not
%% closed by the server, the client may want to close it.
NewState = activate_queue_timeout(TimeOut, State),
- NewSession = Session#session{queue_length = 0},
- httpc_manager:insert_session(NewSession, ProfileName),
+ update_session(ProfileName, Session, #session.queue_length, 0),
%% Note mfa will be initilized when a new request
%% arrives.
{noreply,
@@ -1279,6 +1309,7 @@ handle_keep_alive_queue(
}
};
{{value, NextRequest}, KeepAlive} ->
+ ?hcrd("keep_alive queue non-empty", []),
case lists:member(NextRequest#request.id,
State#state.canceled) of
true ->
@@ -1388,10 +1419,10 @@ try_to_enable_pipeline_or_keep_alive(
case (is_pipeline_enabled_client(Session) andalso
httpc_request:is_idempotent(Method)) of
true ->
- httpc_manager:insert_session(Session, ProfileName),
+ insert_session(Session, ProfileName),
State#state{status = pipeline};
false ->
- httpc_manager:insert_session(Session, ProfileName),
+ insert_session(Session, ProfileName),
%% Make sure type is keep_alive in session
%% as it in this case might be pipeline
NewSession = Session#session{type = keep_alive},
@@ -1403,7 +1434,9 @@ try_to_enable_pipeline_or_keep_alive(
end.
answer_request(#request{id = RequestId, from = From} = Request, Msg,
- #state{timers = Timers, profile_name = ProfileName} = State) ->
+ #state{session = Session,
+ timers = Timers,
+ profile_name = ProfileName} = State) ->
?hcrt("answer request", [{request, Request}, {msg, Msg}]),
httpc_response:send(From, Msg),
RequestTimers = Timers#timers.request_timers,
@@ -1412,12 +1445,20 @@ 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),
-
+ NewSession = maybe_make_session_available(ProfileName, Session),
+ Timers2 = Timers#timers{request_timers = lists:delete(Timer,
+ RequestTimers)},
State#state{request = Request#request{from = answer_sent},
- timers =
- Timers#timers{request_timers =
- lists:delete(Timer, RequestTimers)}}.
-
+ session = NewSession,
+ timers = Timers2}.
+
+maybe_make_session_available(ProfileName,
+ #session{available = false} = Session) ->
+ update_session(ProfileName, Session, #session.available, true),
+ Session#session{available = true};
+maybe_make_session_available(_ProfileName, Session) ->
+ Session.
+
cancel_timers(#timers{request_timers = ReqTmrs, queue_timer = QTmr}) ->
cancel_timer(QTmr, timeout_queue),
CancelTimer = fun({_, Timer}) -> cancel_timer(Timer, timeout) end,
@@ -1656,6 +1697,53 @@ send_raw(SocketType, Socket, ProcessBody, Acc) ->
end.
+%% ---------------------------------------------------------------------
+%% Session wrappers
+%% ---------------------------------------------------------------------
+
+insert_session(Session, ProfileName) ->
+ httpc_manager:insert_session(Session, ProfileName).
+
+
+update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
+ try
+ begin
+ httpc_manager:update_session(ProfileName, SessionId, Pos, Value)
+ end
+ catch
+ error:undef -> % This could happen during code upgrade
+ Session2 = erlang:setelement(Pos, Session, Value),
+ insert_session(Session2, ProfileName);
+ T:E ->
+ error_logger:error_msg("Failed updating session: "
+ "~n ProfileName: ~p"
+ "~n SessionId: ~p"
+ "~n Pos: ~p"
+ "~n Value: ~p"
+ "~nwhen"
+ "~n Session (db) info: ~p"
+ "~n Session (db): ~p"
+ "~n Session (record): ~p"
+ "~n T: ~p"
+ "~n E: ~p",
+ [ProfileName, SessionId, Pos, Value,
+ (catch httpc_manager:which_session_info(ProfileName)),
+ Session,
+ (catch httpc_manager:lookup_session(ProfileName, SessionId)),
+ T, E]),
+ exit({failed_updating_session,
+ [{profile, ProfileName},
+ {session_id, SessionId},
+ {pos, Pos},
+ {value, Value},
+ {etype, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()}]})
+ end.
+
+
+%% ---------------------------------------------------------------------
+
call(Msg, Pid) ->
Timeout = infinity,
call(Msg, Pid, Timeout).
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index 1d8a5b6a92..8af752546c 100644
--- a/lib/inets/src/http_client/httpc_internal.hrl
+++ b/lib/inets/src/http_client/httpc_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,39 +90,62 @@
%%% All data associated to a specific HTTP request
-record(request,
{
- id, % ref() - Request Id
- from, % pid() - Caller
- redircount = 0,% Number of redirects made for this request
- scheme, % http | https
- address, % ({Host,Port}) Destination Host and Port
- path, % string() - Path of parsed URL
- pquery, % string() - Rest of parsed URL
- method, % atom() - HTTP request Method
- headers, % #http_request_h{}
- content, % {ContentType, Body} - Current HTTP request
- settings, % #http_options{} - User defined settings
- abs_uri, % string() ex: "http://www.erlang.org"
- userinfo, % string() - optinal "<userinfo>@<host>:<port>"
- stream, % Boolean() - stream async reply?
- headers_as_is, % Boolean() - workaround for servers that does
- % not honor the http standard, can also be used for testing purposes.
- started, % integer() > 0 - When we started processing the request
- timer, % undefined | ref()
- socket_opts % undefined | [socket_option()]
+ id, % ref() - Request Id
+ from, % pid() - Caller
+ redircount = 0,% Number of redirects made for this request
+ scheme, % http | https
+ address, % ({Host,Port}) Destination Host and Port
+ path, % string() - Path of parsed URL
+ pquery, % string() - Rest of parsed URL
+ method, % atom() - HTTP request Method
+ headers, % #http_request_h{}
+ content, % {ContentType, Body} - Current HTTP request
+ settings, % #http_options{} - User defined settings
+ abs_uri, % string() ex: "http://www.erlang.org"
+ userinfo, % string() - optinal "<userinfo>@<host>:<port>"
+ stream, % boolean() - stream async reply?
+ headers_as_is, % boolean() - workaround for servers that does
+ % not honor the http standard, can also be used
+ % for testing purposes.
+ started, % integer() > 0 - When we started processing the
+ % request
+ timer, % undefined | ref()
+ socket_opts, % undefined | [socket_option()]
+ ipv6_host_with_brackets % boolean()
}
).
+
-record(session,
{
- id, % {{Host, Port}, HandlerPid}
- client_close, % true | false
- scheme, % http (HTTP/TCP) | https (HTTP/SSL/TCP)
- socket, % Open socket, used by connection
- socket_type, % socket-type, used by connection
- queue_length = 1, % Current length of pipeline or keep-alive queue
- type % pipeline | keep_alive (wait for response before sending new request)
+ %% {{Host, Port}, HandlerPid}
+ id,
+
+ %% true | false
+ client_close,
+
+ %% http (HTTP/TCP) | https (HTTP/SSL/TCP)
+ scheme,
+
+ %% Open socket, used by connection
+ socket,
+
+ %% socket-type, used by connection
+ socket_type,
+
+ %% Current length of pipeline or keep-alive queue
+ queue_length = 1,
+
+ %% pipeline | keep_alive (wait for response before sending new request)
+ type,
+
+ %% true | false
+ %% This will be true, when a response has been received for
+ %% the first request. See type above.
+ available = false
}).
+
-record(http_cookie,
{
domain,
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 9015bf1ce2..3612b331e7 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,15 @@
retry_request/2,
redirect_request/2,
insert_session/2,
+ lookup_session/2,
+ update_session/4,
delete_session/2,
+ which_sessions/1,
+ which_session_info/1,
set_options/2,
+ get_options/2,
store_cookies/3,
- which_cookies/1, which_cookies/2,
+ which_cookies/1, which_cookies/2, which_cookies/3,
reset_cookies/1,
session_type/1,
info/1
@@ -57,17 +62,9 @@
options = #options{}
}).
--record(handler_info,
- {
- id, % Id of the request: request_id()
- starter, % Pid of the handler starter process (temp): pid()
- handler, % Pid of the handler process: pid()
- from, % From for the request: from()
- state % State of the handler: initiating | started | operational | canceled
- }).
-
-define(DELAY, 500).
+
%%====================================================================
%% Internal Application API
%%====================================================================
@@ -193,12 +190,48 @@ insert_session(Session, ProfileName) ->
%%--------------------------------------------------------------------
-%% Function: delete_session(SessionId, ProfileName) -> _
+%% Function: lookup_session(SessionId, ProfileName) -> _
+%% SessionId - term()
+%% ProfileName - atom()
+%%
+%% Description: Looks up a session record in the httpc manager
+%% table <ProfileName>__session_db.
+%%--------------------------------------------------------------------
+
+lookup_session(SessionId, ProfileName) ->
+ SessionDbName = session_db_name(ProfileName),
+ ?hcrt("lookup session", [{session_id, SessionId}, {profile, ProfileName}]),
+ ets:lookup(SessionDbName, SessionId).
+
+
+%%--------------------------------------------------------------------
+%% Function: update_session(ProfileName, SessionId, Pos, Value) -> _
+%% Session - #session{}
+%% ProfileName - atom()
+%%
+%% Description: Update, only one field (Pos) of the session record
+%% identified by the SessionId, the session information
+%% of the httpc manager table <ProfileName>__session_db.
+%% Intended to be called by the httpc request handler process.
+%%--------------------------------------------------------------------
+
+update_session(ProfileName, SessionId, Pos, Value) ->
+ SessionDbName = session_db_name(ProfileName),
+ ?hcrt("update session",
+ [{id, SessionId},
+ {pos, Pos},
+ {value, Value},
+ {profile, ProfileName}]),
+ ets:update_element(SessionDbName, SessionId, {Pos, Value}).
+
+
+%%--------------------------------------------------------------------
+%% Function: delete_session(SessionId, ProfileName) -> void()
%% SessionId - {{Host, Port}, HandlerPid}
%% ProfileName - atom()
%%
%% Description: Deletes session information from the httpc manager
-%% table httpc_manager_session_db_<Profile>. Intended to be called by
+%% table <ProfileName>__session_db. Intended to be called by
%% the httpc request handler process.
%%--------------------------------------------------------------------
@@ -209,6 +242,57 @@ delete_session(SessionId, ProfileName) ->
%%--------------------------------------------------------------------
+%% Function: which sessions(ProfileName) -> SessionsInfo
+%% ProfileName - atom()
+%% SessionsInfo - {GoodSessions, BadSessions, NonSessions}
+%% GoodSessions - [#session{}]
+%% BadSessions - [tuple()]
+%% NonSessions - [term()]
+%%
+%% Description: Produces a list of all sessions in the session db.
+%% Used for debugging and since that is the intent, there is some
+%% checking and transforming done, which produces the results.
+%%--------------------------------------------------------------------
+
+which_sessions(ProfileName) ->
+ ?hcrt("which_sessions", [{profile, ProfileName}]),
+ SessionDbName = session_db_name(ProfileName),
+ which_sessions2(SessionDbName).
+
+which_sessions2(SessionDbName) ->
+ Sessions = which_sessions_order(ets:tab2list(SessionDbName)),
+ GoodSessions = [GoodSession || {good_session, GoodSession} <- Sessions],
+ BadSessions = [BadSession || {bad_session, BadSession} <- Sessions],
+ NonSessions = [NonSession || {non_session, NonSession} <- Sessions],
+ {lists:keysort(#session.id, GoodSessions),
+ lists:keysort(#session.id, BadSessions),
+ lists:sort(NonSessions)}.
+
+which_sessions_order([]) ->
+ [];
+which_sessions_order([Session|Sessions]) when is_record(Session, session) ->
+ [{good_session, Session} | which_sessions_order(Sessions)];
+which_sessions_order([BadSession|Sessions])
+ when is_tuple(BadSession) andalso
+ (element(1, BadSession) =:= session) ->
+ [{bad_session, BadSession} | which_sessions_order(Sessions)];
+which_sessions_order([NonSession|Sessions]) ->
+ [{non_session, NonSession} | which_sessions_order(Sessions)].
+
+
+%%--------------------------------------------------------------------
+%% Function: which session_info(ProfileName) -> list()
+%%
+%% Description: Produces a ets table info list of the sessions table
+%%--------------------------------------------------------------------
+
+which_session_info(ProfileName) ->
+ SessionDbName = session_db_name(ProfileName),
+ ?hcrt("which_session_info", [{profile, ProfileName}]),
+ ets:info(SessionDbName).
+
+
+%%--------------------------------------------------------------------
%% Function: set_options(Options, ProfileName) -> ok
%%
%% Options = [Option]
@@ -228,6 +312,21 @@ set_options(Options, ProfileName) ->
%%--------------------------------------------------------------------
+%% Function: get_options(OptionItems, ProfileName) -> Values
+%%
+%% OptionItems = [OptionItem]
+%% OptionItem = Any or all fields of the current #options{} record
+%% Values = [{OptionItem, Value}]
+%% Value = term()
+%%
+%% Description: Gets the specified options used by the client.
+%%--------------------------------------------------------------------
+
+get_options(Options, ProfileName) ->
+ call(ProfileName, {get_options, Options}).
+
+
+%%--------------------------------------------------------------------
%% Function: store_cookies(Cookies, Address, ProfileName) -> ok
%%
%% Cookies = [Cookie]
@@ -256,19 +355,29 @@ reset_cookies(ProfileName) ->
%%--------------------------------------------------------------------
-%% Function: which_cookies(Url, ProfileName) -> [cookie()]
+%% Function: which_cookies(ProfileName) -> [cookie()]
+%% which_cookies(Url, ProfileName) -> [cookie()]
+%% which_cookies(Url, Options, ProfileName) -> [cookie()]
%%
%% Url = string()
+%% Options = [option()]
%% ProfileName = atom()
+%% option() = {ipv6_host_with_brackets, boolean()}
%%
%% Description: Retrieves the cookies that would be sent when
%% requesting <Url>.
%%--------------------------------------------------------------------
-which_cookies(ProfileName) ->
+which_cookies(ProfileName) when is_atom(ProfileName) ->
call(ProfileName, which_cookies).
-which_cookies(Url, ProfileName) ->
- call(ProfileName, {which_cookies, Url}).
+
+which_cookies(Url, ProfileName)
+ when is_list(Url) andalso is_atom(ProfileName) ->
+ which_cookies(Url, [], ProfileName).
+
+which_cookies(Url, Options, ProfileName)
+ when is_list(Url) andalso is_list(Options) andalso is_atom(ProfileName) ->
+ call(ProfileName, {which_cookies, Url, Options}).
%%--------------------------------------------------------------------
@@ -331,8 +440,7 @@ do_init(ProfileName, CookiesDir) ->
%% Create handler db
?hcrt("create handler/request db", []),
HandlerDbName = handler_db_name(ProfileName),
- ets:new(HandlerDbName,
- [protected, set, named_table, {keypos, #handler_info.id}]),
+ ets:new(HandlerDbName, [protected, set, named_table, {keypos, 1}]),
%% Cookie DB
?hcrt("create cookie db", []),
@@ -366,9 +474,10 @@ handle_call({request, Request}, _, State) ->
{stop, Error, httpc_response:error(Request, Error), State}
end;
-handle_call({cancel_request, RequestId}, From, State) ->
+handle_call({cancel_request, RequestId}, From,
+ #state{handler_db = HandlerDb} = State) ->
?hcri("cancel_request", [{request_id, RequestId}]),
- case ets:lookup(State#state.handler_db, RequestId) of
+ case ets:lookup(HandlerDb, RequestId) of
[] ->
%% The request has allready compleated make sure
%% it is deliverd to the client process queue so
@@ -380,9 +489,9 @@ handle_call({cancel_request, RequestId}, From, State) ->
{noreply, State};
[{_, Pid, _}] ->
httpc_handler:cancel(RequestId, Pid, From),
- {noreply, State#state{cancel =
- [{RequestId, Pid, From} |
- State#state.cancel]}}
+ {noreply,
+ State#state{cancel =
+ [{RequestId, Pid, From} | State#state.cancel]}}
end;
handle_call(reset_cookies, _, #state{cookie_db = CookieDb} = State) ->
@@ -395,17 +504,24 @@ handle_call(which_cookies, _, #state{cookie_db = CookieDb} = State) ->
CookieHeaders = httpc_cookie:which_cookies(CookieDb),
{reply, CookieHeaders, State};
-handle_call({which_cookies, Url}, _, #state{cookie_db = CookieDb} = State) ->
- ?hcrv("which cookies", [{url, Url}]),
- case http_uri:parse(Url) of
- {Scheme, _, Host, Port, Path, _} ->
+handle_call({which_cookies, Url, Options}, _,
+ #state{cookie_db = CookieDb} = State) ->
+ ?hcrv("which cookies", [{url, Url}, {options, Options}]),
+ case uri_parse(Url, Options) of
+ {ok, {Scheme, _, Host, Port, Path, _}} ->
CookieHeaders =
httpc_cookie:header(CookieDb, Scheme, {Host, Port}, Path),
{reply, CookieHeaders, State};
- Msg ->
- {reply, Msg, State}
+ {error, _} = ERROR ->
+ {reply, ERROR, State}
end;
+handle_call({get_options, OptionItems}, _, #state{options = Options} = State) ->
+ ?hcrv("get options", [{option_items, OptionItems}]),
+ Reply = [{OptionItem, get_option(OptionItem, Options)} ||
+ OptionItem <- OptionItems],
+ {reply, Reply, State};
+
handle_call(info, _, State) ->
?hcrv("info", []),
Info = get_manager_info(State),
@@ -548,49 +664,126 @@ terminate(_, State) ->
%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
%% Purpose: Convert process state when code is changed
%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
+code_change(_,
+ #state{session_db = SessionDB} = State,
+ upgrade_from_pre_5_8_1) ->
+ Upgrade =
+ fun({session,
+ Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type}) ->
+ {ok, #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type}};
+ (_) -> % Already upgraded (by handler)
+ ignore
+ end,
+ (catch update_session_table(SessionDB, Upgrade)),
+ {ok, State};
+
+code_change(_,
+ #state{session_db = SessionDB} = State,
+ downgrade_to_pre_5_8_1) ->
+ Downgrade =
+ fun(#session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type}) ->
+ {ok, {session,
+ Id, ClientClose, Scheme, Socket, SocketType,
+ QueueLen, Type}};
+ (_) -> % Already downgraded (by handler)
+ ignore
+ end,
+ (catch update_session_table(SessionDB, Downgrade)),
+ {ok, State};
+
+code_change(_, State, _) ->
{ok, State}.
+%% This function is used to catch everything that falls through the cracks...
+update_session_table(SessionDB, Transform) ->
+ ets:safe_fixtable(SessionDB, true),
+ update_session_table(SessionDB, ets:first(SessionDB), Transform),
+ ets:safe_fixtable(SessionDB, false).
+
+update_session_table(_SessionDB, '$end_of_table', _Transform) ->
+ ok;
+update_session_table(SessionDB, Key, Transform) ->
+ case ets:lookup(SessionDB, Key) of
+ [OldSession] ->
+ case Transform(OldSession) of
+ {ok, NewSession} ->
+ ets:insert(SessionDB, NewSession);
+ ignore ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ update_session_table(SessionDB, ets:next(SessionDB, Key), Transform).
+
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
get_manager_info(#state{handler_db = HDB,
- cookie_db = CDB} = _State) ->
+ session_db = SDB,
+ cookie_db = CDB,
+ options = Options} = _State) ->
HandlerInfo = get_handler_info(HDB),
+ SessionInfo = which_sessions2(SDB),
+ OptionsInfo =
+ [{Item, get_option(Item, Options)} ||
+ Item <- record_info(fields, options)],
CookieInfo = httpc_cookie:which_cookies(CDB),
- [{handlers, HandlerInfo}, {cookies, CookieInfo}].
+ [{handlers, HandlerInfo},
+ {sessions, SessionInfo},
+ {options, OptionsInfo},
+ {cookies, CookieInfo}].
+
+sort_handlers(Unsorted) ->
+ sort_handlers2(lists:keysort(1, Unsorted)).
+
+sort_handlers2([]) ->
+ [];
+sort_handlers2([{HandlerPid, RequestId}|L]) ->
+ {Handler, Rest} = sort_handlers2(HandlerPid, [RequestId], L),
+ [Handler | sort_handlers2(Rest)].
+
+sort_handlers2(HandlerPid, Reqs, []) ->
+ {{HandlerPid, lists:sort(Reqs)}, []};
+sort_handlers2(HandlerPid, Reqs, [{HandlerPid, ReqId}|Rest]) ->
+ sort_handlers2(HandlerPid, [ReqId|Reqs], Rest);
+sort_handlers2(HandlerPid1, Reqs, [{HandlerPid2, _}|_] = Rest)
+ when HandlerPid1 =/= HandlerPid2 ->
+ {{HandlerPid1, lists:sort(Reqs)}, Rest}.
get_handler_info(Tab) ->
- Pattern = #handler_info{handler = '$1',
- state = '$2',
- _ = '_'},
- Handlers1 = [{Pid, State} || [Pid, State] <- ets:match(Tab, Pattern)],
- F = fun({Pid, State} = Elem, Acc) when State =/= canceled ->
- case lists:keymember(Pid, 1, Acc) of
- true ->
- Acc;
- false ->
- [Elem | Acc]
- end;
- (_, Acc) ->
- Acc
- end,
- Handlers2 = lists:foldl(F, [], Handlers1),
- Handlers3 = [{Pid, State,
- case (catch httpc_handler:info(Pid)) of
- {'EXIT', _} ->
+ Pattern = {'$2', '$1', '_'},
+ Handlers1 = [{Pid, Id} || [Pid, Id] <- ets:match(Tab, Pattern)],
+ Handlers2 = sort_handlers(Handlers1),
+ Handlers3 = [{Pid, Reqs,
+ try
+ begin
+ httpc_handler:info(Pid)
+ end
+ catch
+ _:_ ->
%% Why would this crash?
%% Only if the process has died, but we don't
%% know about it?
- [];
- Else ->
- Else
- end} ||
- {Pid, State} <- Handlers2],
+ []
+ end} || {Pid, Reqs} <- Handlers2],
Handlers3.
+
handle_request(#request{settings =
#http_options{version = "HTTP/0.9"}} = Request,
State) ->
@@ -642,19 +835,21 @@ handle_request(Request, State = #state{options = Options}) ->
{reply, {ok, NewRequest#request.id}, State}.
-start_handler(Request, State) ->
+start_handler(#request{id = Id,
+ from = From} = Request,
+ #state{profile_name = ProfileName,
+ handler_db = HandlerDb,
+ options = Options}) ->
{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]);
+ Request, Options, ProfileName]);
false ->
- httpc_handler:start_link(self(), Request, State#state.options,
- State#state.profile_name)
+ httpc_handler:start_link(self(), Request, Options, ProfileName)
end,
- ets:insert(State#state.handler_db, {Request#request.id,
- Pid, Request#request.from}),
+ HandlerInfo = {Id, Pid, From},
+ ets:insert(HandlerDb, HandlerInfo),
erlang:monitor(process, Pid).
@@ -679,6 +874,7 @@ select_session(Method, HostPort, Scheme, SessionType,
scheme = Scheme,
queue_length = '$2',
type = SessionType,
+ available = true,
_ = '_'},
%% {'_', {HostPort, '$1'}, false, Scheme, '_', '$2', SessionTyp},
Candidates = ets:match(SessionDb, Pattern),
@@ -710,13 +906,15 @@ select_session(Candidates, Max) ->
{ok, HandlerPid}
end.
-pipeline_or_keep_alive(Request, HandlerPid, State) ->
+pipeline_or_keep_alive(#request{id = Id,
+ from = From} = Request,
+ HandlerPid,
+ #state{handler_db = HandlerDb} = State) ->
case (catch httpc_handler:send(Request, HandlerPid)) of
ok ->
- ets:insert(State#state.handler_db, {Request#request.id,
- HandlerPid,
- Request#request.from});
- _ -> %timeout pipelining failed
+ HandlerInfo = {Id, HandlerPid, From},
+ ets:insert(HandlerDb, HandlerInfo);
+ _ -> % timeout pipelining failed
start_handler(Request, State)
end.
@@ -777,6 +975,19 @@ make_db_name(ProfileName, Post) ->
list_to_atom(atom_to_list(ProfileName) ++ Post).
+%%--------------------------------------------------------------------------
+%% These functions is just simple wrappers to parse specifically HTTP URIs
+%%--------------------------------------------------------------------------
+
+scheme_defaults() ->
+ [{http, 80}, {https, 443}].
+
+uri_parse(URI, Opts) ->
+ http_uri:parse(URI, [{scheme_defaults, scheme_defaults()} | Opts]).
+
+
+%%--------------------------------------------------------------------------
+
call(ProfileName, Msg) ->
Timeout = infinity,
@@ -788,6 +999,31 @@ cast(ProfileName, Msg) ->
gen_server:cast(ProfileName, Msg).
+get_option(proxy, #options{proxy = Proxy}) ->
+ Proxy;
+get_option(pipeline_timeout, #options{pipeline_timeout = Timeout}) ->
+ Timeout;
+get_option(max_pipeline_length, #options{max_pipeline_length = Length}) ->
+ Length;
+get_option(keep_alive_timeout, #options{keep_alive_timeout = Timeout}) ->
+ Timeout;
+get_option(max_keep_alive_length, #options{max_keep_alive_length = Length}) ->
+ Length;
+get_option(max_sessions, #options{max_sessions = MaxSessions}) ->
+ MaxSessions;
+get_option(cookies, #options{cookies = Cookies}) ->
+ Cookies;
+get_option(verbose, #options{verbose = Verbose}) ->
+ Verbose;
+get_option(ipfamily, #options{ipfamily = IpFamily}) ->
+ IpFamily;
+get_option(ip, #options{ip = IP}) ->
+ IP;
+get_option(port, #options{port = Port}) ->
+ Port;
+get_option(socket_opts, #options{socket_opts = SocketOpts}) ->
+ SocketOpts.
+
get_proxy(Opts, #options{proxy = Default}) ->
proplists:get_value(proxy, Opts, Default).
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 207b96271c..04976447cc 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -340,7 +340,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) ->
undefined ->
transparent(Response, Request);
RedirUrl ->
- case http_uri:parse(RedirUrl) of
+ UrlParseOpts = [{ipv6_host_with_brackets,
+ Request#request.ipv6_host_with_brackets}],
+ case uri_parse(RedirUrl, UrlParseOpts) of
{error, no_scheme} when
(Request#request.settings)#http_options.relaxed ->
NewLocation = fix_relative_uri(Request, RedirUrl),
@@ -350,10 +352,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) ->
{error, Reason} ->
{ok, error(Request, Reason), Data};
%% Automatic redirection
- {Scheme, _, Host, Port, Path, Query} ->
+ {ok, {Scheme, _, Host, Port, Path, Query}} ->
NewHeaders =
- (Request#request.headers)#http_request_h{host =
- Host},
+ (Request#request.headers)#http_request_h{host = Host},
NewRequest =
Request#request{redircount =
Request#request.redircount+1,
@@ -436,3 +437,17 @@ format_response({StatusLine, Headers, Body}) ->
end,
{{StatusLine, http_response:header_list(Headers), NewBody}, Data}.
+%%--------------------------------------------------------------------------
+%% These functions is just simple wrappers to parse specifically HTTP URIs
+%%--------------------------------------------------------------------------
+
+scheme_defaults() ->
+ [{http, 80}, {https, 443}].
+
+uri_parse(URI, Opts) ->
+ http_uri:parse(URI, [{scheme_defaults, scheme_defaults()} | Opts]).
+
+
+%%--------------------------------------------------------------------------
+
+
diff --git a/lib/inets/src/http_lib/Makefile b/lib/inets/src/http_lib/Makefile
index aaf3cfb995..3ec6ce7436 100644
--- a/lib/inets/src/http_lib/Makefile
+++ b/lib/inets/src/http_lib/Makefile
@@ -87,11 +87,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/http_lib
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/http_lib
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/http_lib"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/http_lib"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index 44b9face0b..5962001c3a 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,61 +16,138 @@
%%
%% %CopyrightEnd%
%%
-%%
+%%
+%% This is from chapter 3, Syntax Components, of RFC 3986:
+%%
+%% The generic URI syntax consists of a hierarchical sequence of
+%% components referred to as the scheme, authority, path, query, and
+%% fragment.
+%%
+%% URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+%%
+%% hier-part = "//" authority path-abempty
+%% / path-absolute
+%% / path-rootless
+%% / path-empty
+%%
+%% The scheme and path components are required, though the path may be
+%% empty (no characters). When authority is present, the path must
+%% either be empty or begin with a slash ("/") character. When
+%% authority is not present, the path cannot begin with two slash
+%% characters ("//"). These restrictions result in five different ABNF
+%% rules for a path (Section 3.3), only one of which will match any
+%% given URI reference.
+%%
+%% The following are two example URIs and their component parts:
+%%
+%% foo://example.com:8042/over/there?name=ferret#nose
+%% \_/ \______________/\_________/ \_________/ \__/
+%% | | | | |
+%% scheme authority path query fragment
+%% | _____________________|__
+%% / \ / \
+%% urn:example:animal:ferret:nose
+%%
+%% scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+%% authority = [ userinfo "@" ] host [ ":" port ]
+%% userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+%%
+%%
-module(http_uri).
--export([parse/1, encode/1, decode/1]).
+-export([parse/1, parse/2,
+ scheme_defaults/0,
+ encode/1, decode/1]).
+
+-export_type([scheme/0, default_scheme_port_number/0]).
+
%%%=========================================================================
%%% API
%%%=========================================================================
+
+-type scheme() :: atom().
+-type default_scheme_port_number() :: pos_integer().
+
+-spec scheme_defaults() ->
+ [{scheme(), default_scheme_port_number()}].
+
+scheme_defaults() ->
+ [{http, 80},
+ {https, 443},
+ {ftp, 21},
+ {ssh, 22},
+ {sftp, 22},
+ {tftp, 69}].
+
parse(AbsURI) ->
- case parse_scheme(AbsURI) of
+ parse(AbsURI, []).
+
+parse(AbsURI, Opts) ->
+ case parse_scheme(AbsURI, Opts) of
{error, Reason} ->
{error, Reason};
- {Scheme, Rest} ->
- case (catch parse_uri_rest(Scheme, Rest)) of
- {UserInfo, Host, Port, Path, Query} ->
- {Scheme, UserInfo, Host, Port, Path, Query};
+ {Scheme, DefaultPort, Rest} ->
+ case (catch parse_uri_rest(Scheme, DefaultPort, Rest, Opts)) of
+ {ok, {UserInfo, Host, Port, Path, Query}} ->
+ {ok, {Scheme, UserInfo, Host, Port, Path, Query}};
+ {error, Reason} ->
+ {error, {Reason, Scheme, AbsURI}};
_ ->
- {error, {malformed_url, AbsURI}}
+ {error, {malformed_url, Scheme, AbsURI}}
end
end.
+reserved() ->
+ sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?,
+ $#, $[, $], $<, $>, $\", ${, $}, $|,
+ $\\, $', $^, $%, $ ]).
+
encode(URI) ->
- Reserved = sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?,
- $#, $[, $], $<, $>, $\", ${, $}, $|,
- $\\, $', $^, $%, $ ]),
- lists:append(lists:map(fun(Char) ->
- uri_encode(Char, Reserved)
- end, URI)).
-
-decode([$%,Hex1,Hex2|Rest]) ->
- [hex2dec(Hex1)*16+hex2dec(Hex2)|decode(Rest)];
-decode([First|Rest]) ->
- [First|decode(Rest)];
-decode([]) ->
+ Reserved = reserved(),
+ lists:append([uri_encode(Char, Reserved) || Char <- URI]).
+
+decode(String) ->
+ do_decode(String).
+
+do_decode([$%,Hex1,Hex2|Rest]) ->
+ [hex2dec(Hex1)*16+hex2dec(Hex2)|do_decode(Rest)];
+do_decode([First|Rest]) ->
+ [First|do_decode(Rest)];
+do_decode([]) ->
[].
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
-parse_scheme(AbsURI) ->
+
+which_scheme_defaults(Opts) ->
+ Key = scheme_defaults,
+ case lists:keysearch(Key, 1, Opts) of
+ {value, {Key, SchemeDefaults}} ->
+ SchemeDefaults;
+ false ->
+ scheme_defaults()
+ end.
+
+parse_scheme(AbsURI, Opts) ->
case split_uri(AbsURI, ":", {error, no_scheme}, 1, 1) of
{error, no_scheme} ->
{error, no_scheme};
- {StrScheme, Rest} ->
- case list_to_atom(http_util:to_lower(StrScheme)) of
- Scheme when Scheme == http; Scheme == https ->
- {Scheme, Rest};
- Scheme ->
- {error, {not_supported_scheme, Scheme}}
+ {SchemeStr, Rest} ->
+ Scheme = list_to_atom(http_util:to_lower(SchemeStr)),
+ SchemeDefaults = which_scheme_defaults(Opts),
+ case lists:keysearch(Scheme, 1, SchemeDefaults) of
+ {value, {Scheme, DefaultPort}} ->
+ {Scheme, DefaultPort, Rest};
+ false ->
+ {Scheme, no_default_port, Rest}
end
end.
-parse_uri_rest(Scheme, "//" ++ URIPart) ->
-
+parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) ->
{Authority, PathQuery} =
case split_uri(URIPart, "/", URIPart, 1, 0) of
Split = {_, _} ->
@@ -83,25 +160,25 @@ parse_uri_rest(Scheme, "//" ++ URIPart) ->
{URIPart,""}
end
end,
-
{UserInfo, HostPort} = split_uri(Authority, "@", {"", Authority}, 1, 1),
- {Host, Port} = parse_host_port(Scheme, HostPort),
- {Path, Query} = parse_path_query(PathQuery),
- {UserInfo, Host, Port, Path, Query}.
+ {Host, Port} = parse_host_port(Scheme, DefaultPort, HostPort, Opts),
+ {Path, Query} = parse_path_query(PathQuery),
+ {ok, {UserInfo, Host, Port, Path, Query}}.
parse_path_query(PathQuery) ->
{Path, Query} = split_uri(PathQuery, "\\?", {PathQuery, ""}, 1, 0),
{path(Path), Query}.
-parse_host_port(Scheme,"[" ++ HostPort) -> %ipv6
- DefaultPort = default_port(Scheme),
+%% In this version of the function, we no longer need
+%% the Scheme argument, but just in case...
+parse_host_port(_Scheme, DefaultPort, "[" ++ HostPort, Opts) -> %ipv6
{Host, ColonPort} = split_uri(HostPort, "\\]", {HostPort, ""}, 1, 1),
+ Host2 = maybe_ipv6_host_with_brackets(Host, Opts),
{_, Port} = split_uri(ColonPort, ":", {"", DefaultPort}, 0, 1),
- {Host, int_port(Port)};
+ {Host2, int_port(Port)};
-parse_host_port(Scheme, HostPort) ->
- DefaultPort = default_port(Scheme),
+parse_host_port(_Scheme, DefaultPort, HostPort, _Opts) ->
{Host, Port} = split_uri(HostPort, ":", {HostPort, DefaultPort}, 1, 1),
{Host, int_port(Port)}.
@@ -114,15 +191,22 @@ split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
NoMatchResult
end.
-default_port(http) ->
- 80;
-default_port(https) ->
- 443.
+maybe_ipv6_host_with_brackets(Host, Opts) ->
+ case lists:keysearch(ipv6_host_with_brackets, 1, Opts) of
+ {value, {ipv6_host_with_brackets, true}} ->
+ "[" ++ Host ++ "]";
+ _ ->
+ Host
+ end.
+
int_port(Port) when is_integer(Port) ->
Port;
int_port(Port) when is_list(Port) ->
- list_to_integer(Port).
+ list_to_integer(Port);
+%% This is the case where no port was found and there was no default port
+int_port(no_default_port) ->
+ throw({error, no_default_port}).
path("") ->
"/";
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index 973600d7be..5b21170b78 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -206,9 +206,7 @@ timeout(Timeout, Started) ->
html_encode(Chars) ->
Reserved = sets:from_list([$&, $<, $>, $\", $', $/]),
- lists:append(lists:map(fun(Char) ->
- char_to_html_entity(Char, Reserved)
- end, Chars)).
+ lists:append([char_to_html_entity(Char, Reserved) || Char <- Chars]).
%%%========================================================================
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index 55cc68dede..67555d5f1c 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2010. All Rights Reserved.
+# Copyright Ericsson AB 2005-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -88,6 +88,8 @@ ERL_FILES = $(MODULES:%=%.erl)
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
+
# ----------------------------------------------------
# FLAGS
@@ -121,11 +123,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/http_server
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/http_server
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/http_server"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/http_server"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl
index bcebb6a9e3..08ee9ee0d0 100644
--- a/lib/inets/src/http_server/httpd_acceptor.erl
+++ b/lib/inets/src/http_server/httpd_acceptor.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
@@ -139,11 +139,11 @@ acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout) ->
handle_error(Reason, ConfigDb),
?MODULE:acceptor_loop(Manager, SocketType, ListenSocket,
ConfigDb, AcceptTimeout);
- {'EXIT', _Reason} = EXIT ->
- ?hdri("accept exited", [{reason, _Reason}]),
- handle_error(EXIT, ConfigDb),
- ?MODULE:acceptor_loop(Manager, SocketType, ListenSocket,
- ConfigDb, AcceptTimeout)
+ {'EXIT', Reason} ->
+ ?hdri("accept exited", [{reason, Reason}]),
+ ReasonString =
+ lists:flatten(io_lib:format("Accept exit: ~p", [Reason])),
+ accept_failed(ConfigDb, ReasonString)
end.
@@ -189,15 +189,13 @@ handle_error(esslaccept, _) ->
%% not write an error message.
ok;
-handle_error({'EXIT', Reason}, ConfigDb) ->
- String = lists:flatten(io_lib:format("Accept exit: ~p", [Reason])),
- accept_failed(ConfigDb, String);
-
handle_error(Reason, ConfigDb) ->
String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])),
accept_failed(ConfigDb, String).
--spec accept_failed(_, string()) -> no_return().
+
+-spec accept_failed(ConfigDB :: term(),
+ ReasonString :: string()) -> no_return().
accept_failed(ConfigDb, String) ->
error_logger:error_report(String),
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index 7646300409..b575d7331b 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -210,12 +210,32 @@ load("MaxBodySize " ++ MaxBodySize, []) ->
{ok, Integer} ->
{ok, [], {max_body_size,Integer}};
{error, _} ->
- {error, ?NICE(clean(MaxBodySize)++
+ {error, ?NICE(clean(MaxBodySize) ++
" is an invalid number of MaxBodySize")}
end;
load("ServerName " ++ ServerName, []) ->
- {ok,[],{server_name,clean(ServerName)}};
+ {ok,[], {server_name, clean(ServerName)}};
+
+load("ServerTokens " ++ ServerTokens, []) ->
+ %% These are the valid *plain* server tokens:
+ %% sprod, major, minor, minimum, os, full
+ %% It can also be a "private" server token: private:<any string>
+ case string:tokens(ServerTokens, [$:]) of
+ ["private", Private] ->
+ {ok,[], {server_tokens, clean(Private)}};
+ [TokStr] ->
+ Tok = list_to_atom(clean(TokStr)),
+ case lists:member(Tok, [prod, major, minor, minimum, os, full]) of
+ true ->
+ {ok,[], {server_tokens, Tok}};
+ false ->
+ {error, ?NICE(clean(ServerTokens) ++
+ " is an invalid ServerTokens")}
+ end;
+ _ ->
+ {error, ?NICE(clean(ServerTokens) ++ " is an invalid ServerTokens")}
+ end;
load("SocketType " ++ SocketType, []) ->
%% ssl is the same as HTTP_DEFAULT_SSL_KIND
@@ -475,7 +495,7 @@ validate_properties(Properties) ->
validate_properties2(Properties) ->
case proplists:get_value(bind_address, Properties) of
undefined ->
- case proplists:get_value(sock_type, Properties, ip_comm) of
+ case proplists:get_value(sock_type, Properties, ip_comm) of
ip_comm ->
case proplists:get_value(ipfamily, Properties) of
undefined ->
@@ -537,6 +557,20 @@ validate_config_params([{server_name, Value} | Rest])
validate_config_params([{server_name, Value} | _]) ->
throw({server_name, Value});
+validate_config_params([{server_tokens, Value} | Rest])
+ when is_atom(Value) ->
+ case lists:member(Value, plain_server_tokens()) of
+ true ->
+ validate_config_params(Rest);
+ false ->
+ throw({server_tokens, Value})
+ end;
+validate_config_params([{server_tokens, {private, Value}} | Rest])
+ when is_list(Value) ->
+ validate_config_params(Rest);
+validate_config_params([{server_tokens, Value} | _]) ->
+ throw({server_tokens, Value});
+
validate_config_params([{socket_type, Value} | Rest])
when (Value =:= ip_comm) orelse
(Value =:= ssl) orelse
@@ -737,9 +771,73 @@ store({log_format, LogFormat}, _ConfigList)
store({log_format, LogFormat}, _ConfigList)
when (LogFormat =:= compact) orelse (LogFormat =:= pretty) ->
{ok, {log_format, LogFormat}};
+store({server_tokens, ServerTokens} = Entry, _ConfigList) ->
+ Server = server(ServerTokens),
+ {ok, [Entry, {server, Server}]};
store(ConfigListEntry, _ConfigList) ->
{ok, ConfigListEntry}.
+
+%% The SERVER_SOFTWARE macro has the following structure:
+%% <product>/<version>
+%% Example: "inets/1.2.3"
+%% So, with this example (on a linux machine, with OTP R15B),
+%% this will result in:
+%% prod: "inets"
+%% major: "inets/1"
+%% minor: "inets/1.2"
+%% minimal: "inets/1.2.3"
+%% os: "inets/1.2.3 (unix)
+%% full: "inets/1.2.3 (unix/linux) OTP/R15B"
+%% Note that the format of SERVER_SOFTWARE is that of 'minimal'.
+%% Also, there will always be atleast two digits in a version:
+%% Not just 1 but 1.0
+%%
+%% We have already checked that the value is valid,
+%% so there is no need to check enything here.
+%%
+server(prod = _ServerTokens) ->
+ [Prod|_Version] = string:tokens(?SERVER_SOFTWARE, [$/]),
+ Prod;
+server(major = _ServerTokens) ->
+ [Prod|Version] = string:tokens(?SERVER_SOFTWARE, [$/]),
+ [Major|_] = string:tokens(Version, [$.]),
+ Prod ++ "/" ++ Major;
+server(minor = _ServerTokens) ->
+ [Prod|Version] = string:tokens(?SERVER_SOFTWARE, [$/]),
+ [Major,Minor|_] = string:tokens(Version, [$.]),
+ Prod ++ "/" ++ Major ++ "." ++ Minor;
+server(minimal = _ServerTokens) ->
+ %% This is the default
+ ?SERVER_SOFTWARE;
+server(os = _ServerTokens) ->
+ OS = os_info(partial),
+ lists:flatten(io_lib:format("~s ~s", [?SERVER_SOFTWARE, OS]));
+server(full = _ServerTokens) ->
+ OTPRelease = otp_release(),
+ OS = os_info(full),
+ lists:flatten(
+ io_lib:format("~s ~s OTP/~s", [?SERVER_SOFTWARE, OS, OTPRelease]));
+server({private, Server} = _ServerTokens) when is_list(Server) ->
+ %% The user provide its own
+ Server;
+server(_) ->
+ ?SERVER_SOFTWARE.
+
+os_info(Info) ->
+ case os:type() of
+ {OsFamily, _OsName} when Info =:= partial ->
+ lists:flatten(io_lib:format("(~w)", [OsFamily]));
+ {OsFamily, OsName} ->
+ lists:flatten(io_lib:format("(~w/~w)", [OsFamily, OsName]));
+ OsFamily ->
+ lists:flatten(io_lib:format("(~w)", [OsFamily]))
+ end.
+
+otp_release() ->
+ erlang:system_info(otp_release).
+
+
%% Phase 3: Remove
remove_all(ConfigDB) ->
Modules = httpd_util:lookup(ConfigDB,modules,[]),
@@ -1159,6 +1257,10 @@ ssl_ca_certificate_file(ConfigDB) ->
[{cacertfile, File}]
end.
+plain_server_tokens() ->
+ [prod, major, minor, minimum, os, full].
+
error_report(Where,M,F,Error) ->
error_logger:error_report([{?MODULE, Where},
{apply, {M, F, []}}, Error]).
+
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index e8a8ab6411..f2ba33099e 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -36,9 +36,9 @@ handle_error(emfile, Op, _ModData, Path) ->
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(_Reason, Op, _ModData, Path) ->
+ handle_error(500, Op, none, Path, "").
+
handle_error(StatusCode, Op, none, Path, Reason) ->
{StatusCode, none, ?NICE("Can't " ++ Op ++ " " ++ Path ++ Reason)};
handle_error(StatusCode, Op, ModData, Path, Reason) ->
diff --git a/lib/inets/src/http_server/httpd_log.erl b/lib/inets/src/http_server/httpd_log.erl
index db1e2c627a..60ab326a20 100644
--- a/lib/inets/src/http_server/httpd_log.erl
+++ b/lib/inets/src/http_server/httpd_log.erl
@@ -24,68 +24,110 @@
-export([access_entry/8, error_entry/5, error_report_entry/5,
security_entry/5]).
+
%%%=========================================================================
%%% Internal Application API
%%%=========================================================================
-access_entry(Log, NoLog, Info, RFC931, AuthUser, Date, StatusCode, Bytes) ->
- ConfigDB = Info#mod.config_db,
- case httpd_util:lookup(ConfigDB, Log) of
- undefined ->
- NoLog;
- LogRef ->
- {_, RemoteHost}
- = (Info#mod.init_data)#init_data.peername,
- RequestLine = Info#mod.request_line,
- Headers = Info#mod.parsed_header,
- Entry = do_access_entry(ConfigDB, Headers, RequestLine,
- RemoteHost, RFC931, AuthUser,
- Date, StatusCode, Bytes),
- {LogRef, Entry}
- end.
-error_entry(Log, NoLog, Info, Date, Reason) ->
- ConfigDB = Info#mod.config_db,
- case httpd_util:lookup(ConfigDB, Log) of
- undefined ->
- NoLog;
- LogRef ->
- {_, RemoteHost} =
- (Info#mod.init_data)#init_data.peername,
- URI = Info#mod.request_uri,
- Entry = do_error_entry(ConfigDB, RemoteHost, URI, Date, Reason),
- {LogRef, Entry}
- end.
+-spec access_entry(Log :: term(), % Id of the log
+ NoLog :: term(), % What to return when no log is found
+ Info :: #mod{},
+ RFC931 :: string(),
+ AuthUser :: string(),
+ Date :: string(),
+ StatusCode :: pos_integer(),
+ Size :: pos_integer() | string()) ->
+ {Log :: atom() | pid(), Entry :: string()}.
+
+access_entry(Log, NoLog, Info, RFC931, AuthUser, Date, StatusCode, SizeStr)
+ when is_list(SizeStr) ->
+ Size =
+ case (catch list_to_integer(SizeStr)) of
+ I when is_integer(I) ->
+ I;
+ _ ->
+ SizeStr % This is better then nothing
+ end,
+ access_entry(Log, NoLog, Info, RFC931, AuthUser, Date, StatusCode, Size);
+access_entry(Log, NoLog,
+ #mod{config_db = ConfigDB,
+ init_data = #init_data{peername = {_, RemoteHost}},
+ request_line = RequestLine,
+ parsed_header = Headers},
+ RFC931, AuthUser, Date, StatusCode, Size) ->
+ MakeEntry =
+ fun() ->
+ do_access_entry(ConfigDB, Headers, RequestLine,
+ RemoteHost, RFC931, AuthUser,
+ Date, StatusCode, Size)
+ end,
+ log_entry(Log, NoLog, ConfigDB, MakeEntry).
+
+
+-spec error_entry(Log :: term(), % Id of the log
+ NoLog :: term(), % What to return when no log is found
+ Info :: #mod{},
+ Date :: string(),
+ Reason :: term()) ->
+ {Log :: atom() | pid(), Entry :: string()}.
+
+error_entry(Log, NoLog,
+ #mod{config_db = ConfigDB,
+ init_data = #init_data{peername = {_, RemoteHost}},
+ request_uri = URI}, Date, Reason) ->
+ MakeEntry =
+ fun() ->
+ do_error_entry(ConfigDB, RemoteHost, URI, Date, Reason)
+ end,
+ log_entry(Log, NoLog, ConfigDB, MakeEntry).
+
+
+-spec error_report_entry(Log :: term(),
+ NoLog :: term(),
+ ConfigDB :: term(),
+ Date :: string(),
+ ErrroStr :: string()) ->
+ {Log :: atom() | pid(), Entry :: string()}.
error_report_entry(Log, NoLog, ConfigDb, Date, ErrorStr) ->
- case httpd_util:lookup(ConfigDb, Log) of
- undefined ->
- NoLog;
- LogRef ->
- Entry = io_lib:format("[~s], ~s~n", [Date, ErrorStr]),
- {LogRef, Entry}
- end.
+ MakeEntry = fun() -> io_lib:format("[~s], ~s~n", [Date, ErrorStr]) end,
+ log_entry(Log, NoLog, ConfigDb, MakeEntry).
+
-security_entry(Log, NoLog, #mod{config_db = ConfigDb}, Date, Reason) ->
+-spec security_entry(Log :: term(),
+ NoLog :: term(),
+ ConfigDB :: term(),
+ Date :: string(),
+ Reason :: term()) ->
+ {Log :: atom() | pid(), Entry :: string()}.
+
+security_entry(Log, NoLog, #mod{config_db = ConfigDB}, Date, Reason) ->
+ MakeEntry = fun() -> io_lib:format("[~s] ~s~n", [Date, Reason]) end,
+ log_entry(Log, NoLog, ConfigDB, MakeEntry).
+
+
+log_entry(Log, NoLog, ConfigDb, MakeEntry) when is_function(MakeEntry) ->
case httpd_util:lookup(ConfigDb, Log) of
undefined ->
NoLog;
LogRef ->
- Entry = io_lib:format("[~s] ~s~n", [Date, Reason]),
- {LogRef, Entry}
+ {LogRef, MakeEntry()}
end.
-
+
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
+
do_access_entry(ConfigDB, Headers, RequestLine,
- RemoteHost, RFC931, AuthUser, Date, StatusCode,
- Bytes) ->
+ RemoteHost, RFC931, AuthUser, Date, StatusCode,
+ Size) ->
case httpd_util:lookup(ConfigDB, log_format, common) of
common ->
lists:flatten(io_lib:format("~s ~s ~s [~s] \"~s\" ~w ~w~n",
[RemoteHost, RFC931, AuthUser, Date,
RequestLine,
- StatusCode, Bytes]));
+ StatusCode, Size]));
combined ->
Referer =
proplists:get_value("referer", Headers, "-"),
@@ -94,7 +136,7 @@ do_access_entry(ConfigDB, Headers, RequestLine,
Headers, "-"),
io_lib:format("~s ~s ~s [~s] \"~s\" ~w ~w ~s ~s~n",
[RemoteHost, RFC931, AuthUser, Date,
- RequestLine, StatusCode, Bytes,
+ RequestLine, StatusCode, Size,
Referer, UserAgent])
end.
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index a04bcc2778..5ba79b2706 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -309,12 +309,12 @@ validate_uri(RequestURI) ->
(catch http_uri:decode(string:left(RequestURI, Ndx)))
end,
case UriNoQueryNoHex of
- {'EXIT',_Reason} ->
+ {'EXIT', _Reason} ->
{error, {bad_request, {malformed_syntax, RequestURI}}};
_ ->
Path = format_request_uri(UriNoQueryNoHex),
- Path2 = [X||X<-string:tokens(Path, "/\\"),X=/="."],
- validate_path( Path2,0, RequestURI)
+ Path2 = [X||X<-string:tokens(Path, "/"),X=/="."], %% OTP-5938
+ validate_path(Path2, 0, RequestURI)
end.
validate_path([], _, _) ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index c3b47ce390..b62c10bbc7 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -1,8 +1,8 @@
%%
%% %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
@@ -162,7 +162,14 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call(Request, From, State) ->
+handle_call(Request, From, #state{mod = ModData} = State) ->
+ Error =
+ lists:flatten(
+ io_lib:format("Unexpected request: "
+ "~n~p"
+ "~nto request handler (~p) from ~p"
+ "~n", [Request, self(), From])),
+ error_log(Error, ModData),
{stop, {call_api_violation, Request, From}, State}.
%%--------------------------------------------------------------------
@@ -171,8 +178,15 @@ handle_call(Request, From, State) ->
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast(Msg, State) ->
- {reply, {cast_api_violation, Msg}, State}.
+handle_cast(Msg, #state{mod = ModData} = State) ->
+ Error =
+ lists:flatten(
+ io_lib:format("Unexpected message: "
+ "~n~p"
+ "~nto request handler (~p)"
+ "~n", [Msg, self()])),
+ error_log(Error, ModData),
+ {noreply, State}.
%%--------------------------------------------------------------------
%% handle_info(Info, State) -> {noreply, State} |
@@ -253,7 +267,10 @@ handle_info(timeout, #state{mod = ModData} = State) ->
%% Default case
handle_info(Info, #state{mod = ModData} = State) ->
Error = lists:flatten(
- io_lib:format("Unexpected message received: ~n~p~n", [Info])),
+ io_lib:format("Unexpected info: "
+ "~n~p"
+ "~nto request handler (~p)"
+ "~n", [Info, self()])),
error_log(Error, ModData),
{noreply, State}.
@@ -355,7 +372,7 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
Reason = io_lib:format("Forbidden URI: ~p~n", [URI]),
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
- {error,{bad_request, {malformed_syntax, URI}}} ->
+ {error, {bad_request, {malformed_syntax, URI}}} ->
?hdrd("validation failed: bad request - malformed syntax",
[{uri, URI}]),
httpd_response:send_status(ModData#mod{http_version = Version},
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index ea9cfbf4f2..2dedb088e4 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.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
@@ -78,6 +78,7 @@ traverse_modules(ModData,[Module|Rest]) ->
[Module, Reason])),
report_error(mod_log, ModData#mod.config_db, String),
report_error(mod_disk_log, ModData#mod.config_db, String),
+ send_status(ModData, 500, none),
done;
done ->
?hdrt("traverse modules - done", []),
@@ -100,12 +101,19 @@ send_status(#mod{socket_type = SocketType,
socket = Socket,
config_db = ConfigDB} = ModData, StatusCode, PhraseArgs) ->
+ ?hdrd("send status", [{status_code, StatusCode},
+ {phrase_args, PhraseArgs}]),
+
ReasonPhrase = httpd_util:reason_phrase(StatusCode),
Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
Body = get_body(ReasonPhrase, Message),
- send_header(ModData, StatusCode, [{content_type, "text/html"},
- {content_length, integer_to_list(length(Body))}]),
+ ?hdrt("send status - header", [{reason_phrase, ReasonPhrase},
+ {message, Message}]),
+ send_header(ModData, StatusCode,
+ [{content_type, "text/html"},
+ {content_length, integer_to_list(length(Body))}]),
+
httpd_socket:deliver(SocketType, Socket, Body).
@@ -136,10 +144,14 @@ send_response(ModData, Header, Body) ->
end
end.
-send_header(#mod{socket_type = Type, socket = Sock,
- http_version = Ver, connection = Conn} = _ModData,
+send_header(#mod{socket_type = Type,
+ socket = Sock,
+ http_version = Ver,
+ connection = Conn,
+ config_db = ConfigDb} = _ModData,
StatusCode, KeyValueTupleHeaders) ->
- Headers = create_header(lists:map(fun transform/1, KeyValueTupleHeaders)),
+ Headers = create_header(ConfigDb,
+ lists:map(fun transform/1, KeyValueTupleHeaders)),
NewVer = case {Ver, StatusCode} of
{[], _} ->
%% May be implicit!
@@ -267,13 +279,20 @@ cache_headers(#mod{config_db = Db}) ->
[]
end.
-create_header(KeyValueTupleHeaders) ->
- NewHeaders = add_default_headers([{"date", httpd_util:rfc1123_date()},
- {"content-type", "text/html"},
- {"server", ?SERVER_SOFTWARE}],
- KeyValueTupleHeaders),
+create_header(ConfigDb, KeyValueTupleHeaders) ->
+ Date = httpd_util:rfc1123_date(),
+ ContentType = "text/html",
+ Server = server(ConfigDb),
+ NewHeaders = add_default_headers([{"date", Date},
+ {"content-type", ContentType},
+ {"server", Server}],
+ KeyValueTupleHeaders),
lists:map(fun fix_header/1, NewHeaders).
+
+server(ConfigDb) ->
+ httpd_util:lookup(ConfigDb, server, ?SERVER_SOFTWARE).
+
fix_header({Key0, Value}) ->
%% make sure first letter is capital
Words1 = string:tokens(Key0, "-"),
@@ -345,8 +364,9 @@ transform({Field, Value}) when is_list(Field) ->
%% Leave this method and go on to the newer form of response
%% OTP-4408
%%----------------------------------------------------------------------
-send_response_old(#mod{method = "HEAD"} = ModData,
+send_response_old(#mod{method = "HEAD"} = ModData,
StatusCode, Response) ->
+
NewResponse = lists:flatten(Response),
case httpd_util:split(NewResponse, [?CR, ?LF, ?CR, ?LF],2) of
diff --git a/lib/inets/src/http_server/httpd_script_env.erl b/lib/inets/src/http_server/httpd_script_env.erl
index d3115150b0..ac79a8cc63 100644
--- a/lib/inets/src/http_server/httpd_script_env.erl
+++ b/lib/inets/src/http_server/httpd_script_env.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,29 +50,44 @@ create_env(ScriptType, ModData, ScriptElements) ->
%%%========================================================================
%%% Internal functions
%%%========================================================================
+
+which_server(#mod{config_db = ConfigDb}) ->
+ httpd_util:lookup(ConfigDb, server, ?SERVER_SOFTWARE).
+
+which_port(#mod{config_db = ConfigDb}) ->
+ httpd_util:lookup(ConfigDb, port, 80).
+
+which_peername(#mod{init_data = #init_data{peername = {_, RemoteAddr}}}) ->
+ RemoteAddr.
+
+which_resolve(#mod{init_data = #init_data{resolve = Resolve}}) ->
+ Resolve.
+
+which_method(#mod{method = Method}) ->
+ Method.
+
+which_request_uri(#mod{request_uri = RUri}) ->
+ RUri.
+
create_basic_elements(esi, ModData) ->
- {_, RemoteAddr} = (ModData#mod.init_data)#init_data.peername,
- [{server_software, ?SERVER_SOFTWARE},
- {server_name, (ModData#mod.init_data)#init_data.resolve},
- {gateway_interface,?GATEWAY_INTERFACE},
- {server_protocol, ?SERVER_PROTOCOL},
- {server_port, httpd_util:lookup(ModData#mod.config_db,port,80)},
- {request_method, ModData#mod.method},
- {remote_addr, RemoteAddr},
- {script_name, ModData#mod.request_uri}];
+ [{server_software, which_server(ModData)},
+ {server_name, which_resolve(ModData)},
+ {gateway_interface, ?GATEWAY_INTERFACE},
+ {server_protocol, ?SERVER_PROTOCOL},
+ {server_port, which_port(ModData)},
+ {request_method, which_method(ModData)},
+ {remote_addr, which_peername(ModData)},
+ {script_name, which_request_uri(ModData)}];
create_basic_elements(cgi, ModData) ->
- {_, RemoteAddr} = (ModData#mod.init_data)#init_data.peername,
- [{"SERVER_SOFTWARE",?SERVER_SOFTWARE},
- {"SERVER_NAME", (ModData#mod.init_data)#init_data.resolve},
- {"GATEWAY_INTERFACE",?GATEWAY_INTERFACE},
- {"SERVER_PROTOCOL",?SERVER_PROTOCOL},
- {"SERVER_PORT",
- integer_to_list(httpd_util:lookup(
- ModData#mod.config_db, port, 80))},
- {"REQUEST_METHOD", ModData#mod.method},
- {"REMOTE_ADDR", RemoteAddr},
- {"SCRIPT_NAME", ModData#mod.request_uri}].
+ [{"SERVER_SOFTWARE", which_server(ModData)},
+ {"SERVER_NAME", which_resolve(ModData)},
+ {"GATEWAY_INTERFACE", ?GATEWAY_INTERFACE},
+ {"SERVER_PROTOCOL", ?SERVER_PROTOCOL},
+ {"SERVER_PORT", integer_to_list(which_port(ModData))},
+ {"REQUEST_METHOD", which_method(ModData)},
+ {"REMOTE_ADDR", which_peername(ModData)},
+ {"SCRIPT_NAME", which_request_uri(ModData)}].
create_http_header_elements(ScriptType, Headers) ->
create_http_header_elements(ScriptType, Headers, []).
@@ -80,7 +95,7 @@ create_http_header_elements(ScriptType, Headers) ->
create_http_header_elements(_, [], Acc) ->
Acc;
create_http_header_elements(ScriptType, [{Name, [Value | _] = Values } |
- Headers], Acc)
+ Headers], Acc)
when is_list(Value) ->
NewName = lists:map(fun(X) -> if X == $- -> $_; true -> X end end, Name),
Element = http_env_element(ScriptType, NewName, multi_value(Values)),
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index 264dc9f006..8f3e8f9500 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -162,17 +162,30 @@ httpd_config([Value| _] = Config) when is_tuple(Value) ->
httpd_child_spec([Value| _] = Config, AcceptTimeout, Debug)
when is_tuple(Value) ->
+ ?hdrt("httpd_child_spec - entry", [{accept_timeout, AcceptTimeout},
+ {debug, Debug}]),
Address = proplists:get_value(bind_address, Config, any),
Port = proplists:get_value(port, Config, 80),
httpd_child_spec(Config, AcceptTimeout, Debug, Address, Port);
-httpd_child_spec(ConfigFile, AcceptTimeout, Debug) ->
+%% In this case the AcceptTimeout and Debug will only have default values...
+httpd_child_spec(ConfigFile, AcceptTimeoutDef, DebugDef) ->
+ ?hdrt("httpd_child_spec - entry", [{config_file, ConfigFile},
+ {accept_timeout_def, AcceptTimeoutDef},
+ {debug_def, DebugDef}]),
case httpd_conf:load(ConfigFile) of
{ok, ConfigList} ->
+ ?hdrt("httpd_child_spec - loaded", [{config_list, ConfigList}]),
case (catch httpd_conf:validate_properties(ConfigList)) of
{ok, Config} ->
+ ?hdrt("httpd_child_spec - validated", [{config, Config}]),
Address = proplists:get_value(bind_address, Config, any),
Port = proplists:get_value(port, Config, 80),
+ AcceptTimeout =
+ proplists:get_value(accept_timeout, Config,
+ AcceptTimeoutDef),
+ Debug =
+ proplists:get_value(debug, Config, DebugDef),
httpd_child_spec([{file, ConfigFile} | Config],
AcceptTimeout, Debug, Address, Port);
Error ->
@@ -183,7 +196,7 @@ httpd_child_spec(ConfigFile, AcceptTimeout, Debug) ->
end.
httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port) ->
- case Port == 0 orelse proplists:is_defined(fd, Config) of
+ case (Port =:= 0) orelse proplists:is_defined(fd, Config) of
true ->
httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port);
false ->
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index c051422529..b0b18b9c3d 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -178,11 +178,12 @@ message(301,URL,_) ->
"The document has moved <A HREF=\""++ maybe_encode(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(400,Msg,_) ->
- "Your browser sent a query that this server could not understand. "++ http_util:html_encode(Msg);
-message(401,none,_) ->
+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. " ++
+ html_encode(Msg);
+message(401, none, _) ->
"This server could not verify that you
are authorized to access the document you
requested. Either you supplied the wrong
@@ -190,40 +191,49 @@ 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 "++ http_util:html_encode(RequestURI) ++" on this server.";
+ "You don't have permission to access " ++
+ html_encode(RequestURI) ++
+ " on this server.";
message(404,RequestURI,_) ->
- "The requested URL " ++ http_util:html_encode(RequestURI) ++ " was not found on this server.";
+ "The requested URL " ++
+ html_encode(RequestURI) ++
+ " was not found on this server.";
message(408, Timeout, _) ->
Timeout;
message(412,none,_) ->
"The requested preconditions were false";
message(413, Reason,_) ->
- "Entity: " ++ http_util:html_encode(Reason);
+ "Entity: " ++ html_encode(Reason);
message(414,ReasonPhrase,_) ->
- "Message "++ http_util:html_encode(ReasonPhrase) ++".";
+ "Message " ++ html_encode(ReasonPhrase) ++ ".";
message(416,ReasonPhrase,_) ->
- http_util:html_encode(ReasonPhrase);
+ 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 "
- ++ http_util:html_encode(ServerAdmin) ++ ", and inform them of the time the error occurred "
+ ++ 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) ->
- http_util:html_encode(atom_to_list(Method))++
- " to "++ http_util:html_encode(RequestURI)++" ("++ http_util:html_encode(HTTPVersion)++") not supported.";
+ atom_to_list(Method) ++
+ " to " ++
+ html_encode(RequestURI) ++
+ " (" ++ HTTPVersion ++ ") not supported.";
is_list(Method) ->
- http_util:html_encode(Method)++
- " to "++ http_util:html_encode(RequestURI)++" ("++ http_util:html_encode(HTTPVersion)++") not supported."
+ Method ++
+ " to " ++
+ html_encode(RequestURI) ++
+ " (" ++ HTTPVersion ++ ") not supported."
end;
message(503, String, _ConfigDB) ->
- "This service in unavailable due to: "++ http_util:html_encode(String).
+ "This service in unavailable due to: " ++ html_encode(String).
maybe_encode(URI) ->
Decoded = try http_uri:decode(URI) of
@@ -233,6 +243,15 @@ maybe_encode(URI) ->
end,
http_uri:encode(Decoded).
+html_encode(String) ->
+ try http_uri:decode(String) of
+ Decoded when is_list(Decoded) ->
+ http_util:html_encode(Decoded)
+ catch
+ _:_ ->
+ http_util:html_encode(String)
+ end.
+
%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}
convert_request_date([D,A,Y,DateType| Rest])->
@@ -245,7 +264,7 @@ convert_request_date([D,A,Y,DateType| Rest])->
fun convert_rfc850_date/1
end,
case catch Func([D,A,Y,DateType| Rest]) of
- {ok,Date} ->
+ {ok, Date} ->
Date;
_Error->
bad_date
diff --git a/lib/inets/src/http_server/mod_get.erl b/lib/inets/src/http_server/mod_get.erl
index 5cb30e3d97..758985f330 100644
--- a/lib/inets/src/http_server/mod_get.erl
+++ b/lib/inets/src/http_server/mod_get.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,9 +18,16 @@
%%
%%
-module(mod_get).
+
-export([do/1]).
+
-include("httpd.hrl").
-include("httpd_internal.hrl").
+-include("inets_internal.hrl").
+
+-define(VMODULE,"GET").
+
+
%% do
do(Info) ->
@@ -84,15 +91,16 @@ send_response(_Socket, _SocketType, Path, Info)->
file:close(FileDescriptor),
{proceed,[{response,{already_sent,200,
FileInfo#file_info.size}},
- {mime_type,MimeType}|Info#mod.data]};
+ {mime_type,MimeType} | Info#mod.data]};
{error, Reason} ->
+ ?hdrt("send_response -> failed open file",
+ [{path, Path}, {reason, Reason}]),
Status = httpd_file:handle_error(Reason, "open", Info, Path),
- {proceed,
- [{status, Status}| Info#mod.data]}
+ {proceed, [{status, Status} | Info#mod.data]}
end.
%% send
-
+
send(#mod{socket = Socket, socket_type = SocketType} = Info,
StatusCode, Headers, FileDescriptor) ->
?DEBUG("send -> send header",[]),
diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl
index c8a2ec0dc4..a912f5616c 100644
--- a/lib/inets/src/http_server/mod_log.erl
+++ b/lib/inets/src/http_server/mod_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
@@ -100,7 +100,7 @@ do(Info) ->
transfer_log(Info,"-",AuthUser,Date,StatusCode,Size),
{proceed,Info#mod.data};
{response, Head, _Body} ->
- Size = proplists:get_value(content_length,Head,unknown),
+ Size = content_length(Head),
Code = proplists:get_value(code,Head,unknown),
transfer_log(Info, "-", AuthUser, Date, Code, Size),
{proceed, Info#mod.data};
@@ -254,4 +254,10 @@ auth_user(Data) ->
RemoteUser
end.
-
+content_length(Head) ->
+ case proplists:get_value(content_length, Head) of
+ undefined ->
+ unknown;
+ Size ->
+ list_to_integer(Size)
+ end.
diff --git a/lib/inets/src/http_server/mod_responsecontrol.erl b/lib/inets/src/http_server/mod_responsecontrol.erl
index 5d5b60cdbd..6af5f6211e 100644
--- a/lib/inets/src/http_server/mod_responsecontrol.erl
+++ b/lib/inets/src/http_server/mod_responsecontrol.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
@@ -209,14 +209,14 @@ compare_etags(Tag,Etags) ->
nomatch
end.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%%Control if the file is modificated %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Control if the file is modified %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%----------------------------------------------------------------------
-%%Control the If-Modified-Since and If-Not-Modified-Since header fields
+%% Control the If-Modified-Since and If-Not-Modified-Since header fields
%%----------------------------------------------------------------------
control_modification(Path,Info,FileInfo)->
?DEBUG("control_modification() -> entry",[]),
@@ -227,6 +227,8 @@ control_modification(Path,Info,FileInfo)->
continue;
unmodified->
{304, Info, Path};
+ {bad_date, _} = BadDate->
+ {400, Info, BadDate};
undefined ->
case control_modification_data(Info,
FileInfo#file_info.mtime,
@@ -253,21 +255,27 @@ control_modification_data(Info, ModificationTime, HeaderField)->
undefined->
undefined;
LastModified0 ->
- LastModified = calendar:universal_time_to_local_time(
- httpd_util:convert_request_date(LastModified0)),
- ?DEBUG("control_modification_data() -> "
- "~n Request-Field: ~s"
- "~n FileLastModified: ~p"
- "~n FieldValue: ~p",
- [HeaderField, ModificationTime, LastModified]),
- 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
+ case httpd_util:convert_request_date(LastModified0) of
+ bad_date ->
+ {bad_date, LastModified0};
+ ConvertedReqDate ->
+ LastModified =
+ calendar:universal_time_to_local_time(ConvertedReqDate),
+ ?DEBUG("control_modification_data() -> "
+ "~n Request-Field: ~s"
+ "~n FileLastModified: ~p"
+ "~n FieldValue: ~p",
+ [HeaderField, ModificationTime, LastModified]),
+ 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.
@@ -285,6 +293,9 @@ strip_date([C | Rest]) ->
send_return_value({412,_,_}, _FileInfo)->
{status,{412,none,"Precondition Failed"}};
+send_return_value({400,_, {bad_date, BadDate}}, _FileInfo)->
+ {status, {400, none, "Bad date: " ++ BadDate}};
+
send_return_value({304,Info,Path}, FileInfo)->
Suffix = httpd_util:suffix(Path),
MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index 20e22917e2..b8d923edd8 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -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
@@ -30,6 +30,7 @@ include ../../vsn.mk
VSN = $(INETS_VSN)
+
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -41,11 +42,12 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# ----------------------------------------------------
MODULES = \
- inets_service \
inets \
+ inets_service \
inets_app \
inets_sup \
- inets_regexp
+ inets_regexp \
+ inets_trace
INTERNAL_HRL_FILES = inets_internal.hrl
EXTERNAL_HRL_FILES = ../../include/httpd.hrl \
@@ -109,13 +111,13 @@ $(APPUP_TARGET): $(APPUP_SRC) ../../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/inets_app
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/inets_app
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/inets_app"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/inets_app"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 4d0defb329..4aea2ef3d7 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -1,7 +1,7 @@
%% This is an -*- erlang -*- file.
%% %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
@@ -18,14 +18,15 @@
%%
{application,inets,
- [{description,"INETS CXC 138 49"},
- {vsn,"%VSN%"},
+ [{description, "INETS CXC 138 49"},
+ {vsn, "%VSN%"},
{modules,[
inets,
inets_sup,
inets_app,
inets_service,
inets_regexp,
+ inets_trace,
%% FTP
ftp,
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index e6d315819c..2adb2a0fc8 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -1,7 +1,7 @@
%% This is an -*- erlang -*- file.
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,34 +18,92 @@
{"%VSN%",
[
- {"5.7.1",
+ {"5.9",
[
- {restart_application, inets}
+ {load_module, tftp, soft_purge, soft_purge, [inets_service]},
+ {load_module, inets_service, soft_purge, soft_purge, []},
+ {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
+ {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]},
+ {update, httpc_manager, soft, soft_purge, soft_purge, []}
+ ]
+ },
+ {"5.8.1",
+ [
+ {load_module, tftp, soft_purge, soft_purge, [inets_service]},
+ {load_module, inets_service, soft_purge, soft_purge, []},
+
+ {load_module, http_uri, soft_purge, soft_purge, []},
+ {load_module, httpc_response, soft_purge, soft_purge, [http_uri]},
+
+ {load_module, httpc, soft_purge, soft_purge,
+ [http_uri, httpc_manager]},
+
+ {load_module, inets_app, soft_purge, soft_purge, [inets_sup]},
+ {update, inets_sup, soft, soft_purge, soft_purge, []},
+
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge, []},
+ {load_module, httpd_script_env, soft_purge, soft_purge, []},
+
+ {load_module, inets, soft_purge, soft_purge, [inets_trace]},
+ {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]},
+ {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]},
+ {update, httpd_sup, soft, soft_purge, soft_purge, []},
+ {add_module, inets_trace}
]
},
- {"5.7",
+ {"5.8",
[
{restart_application, inets}
]
},
- {"5.6",
+ {"5.7.2",
[
{restart_application, inets}
]
- }
+ }
],
[
- {"5.7.1",
+ {"5.9",
[
- {restart_application, inets}
+ {load_module, tftp, soft_purge, soft_purge, [inets_service]},
+ {load_module, inets_service, soft_purge, soft_purge, []},
+ {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
+ {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]},
+ {update, httpc_manager, soft, soft_purge, soft_purge, []}
+ ]
+ },
+ {"5.8.1",
+ [
+ {load_module, tftp, soft_purge, soft_purge, [inets_service]},
+ {load_module, inets_service, soft_purge, soft_purge, []},
+
+ {load_module, http_uri, soft_purge, soft_purge, []},
+ {load_module, httpc_response, soft_purge, soft_purge, [http_uri]},
+
+ {load_module, httpc, soft_purge, soft_purge,
+ [http_uri, httpc_manager]},
+
+ {load_module, inets_app, soft_purge, soft_purge, [inets_sup]},
+ {update, inets_sup, soft, soft_purge, soft_purge, []},
+
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge, []},
+ {load_module, httpd_script_env, soft_purge, soft_purge, []},
+
+ {load_module, inets, soft_purge, soft_purge, []},
+ {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]},
+ {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]},
+ {update, httpd_sup, soft, soft_purge, soft_purge, []},
+ {remove, {inets_trace, soft_purge, brutal_purge}}
]
},
- {"5.7",
+ {"5.8",
[
{restart_application, inets}
]
},
- {"5.6",
+ {"5.7.2",
[
{restart_application, inets}
]
diff --git a/lib/inets/src/inets_app/inets.erl b/lib/inets/src/inets_app/inets.erl
index 054468e445..f33e0abe27 100644
--- a/lib/inets/src/inets_app/inets.erl
+++ b/lib/inets/src/inets_app/inets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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 @@
stop/0, stop/2,
services/0, services_info/0,
service_names/0]).
--export([enable_trace/2, enable_trace/3, disable_trace/0, set_trace/1,
+-export([enable_trace/2, enable_trace/3, disable_trace/0, set_trace/1,
report_event/4]).
-export([versions/0,
print_version_info/0, print_version_info/1]).
@@ -409,47 +409,8 @@ service_names() ->
%% Severity withing Limit) will be written to stdout using io:format.
%%
%%-----------------------------------------------------------------
-enable_trace(Level, Dest) ->
- enable_trace(Level, Dest, all).
-
-enable_trace(Level, Dest, Service) ->
- case valid_trace_service(Service) of
- true ->
- enable_trace2(Level, Dest, Service);
- false ->
- {error, {invalid_service, Service}}
- end.
-
-enable_trace2(Level, File, Service)
- when is_list(File) ->
- case file:open(File, [write]) of
- {ok, Fd} ->
- HandleSpec = {fun handle_trace/2, {Service, Fd}},
- do_enable_trace(Level, process, HandleSpec);
- Err ->
- Err
- end;
-enable_trace2(Level, Port, _) when is_integer(Port) ->
- do_enable_trace(Level, port, dbg:trace_port(ip, Port));
-enable_trace2(Level, io, Service) ->
- HandleSpec = {fun handle_trace/2, {Service, standard_io}},
- do_enable_trace(Level, process, HandleSpec);
-enable_trace2(Level, {Fun, _Data} = HandleSpec, _) when is_function(Fun) ->
- do_enable_trace(Level, process, HandleSpec).
-
-do_enable_trace(Level, Type, HandleSpec) ->
- case dbg:tracer(Type, HandleSpec) of
- {ok, _} ->
- set_trace(Level),
- ok;
- Error ->
- Error
- end.
-
-valid_trace_service(all) ->
- true;
-valid_trace_service(Service) ->
- lists:member(Service, [httpc, httpd, ftpc, tftp]).
+enable_trace(Level, Dest) -> inets_trace:enable(Level, Dest).
+enable_trace(Level, Dest, Service) -> inets_trace:enable(Level, Dest, Service).
%%-----------------------------------------------------------------
@@ -458,12 +419,7 @@ valid_trace_service(Service) ->
%% Description:
%% This function is used to stop tracing.
%%-----------------------------------------------------------------
-disable_trace() ->
- %% This is to make handle_trace/2 close the output file (if the
- %% event gets there before dbg closes)
- inets:report_event(100, "stop trace", stop_trace, [stop_trace]),
- dbg:stop().
-
+disable_trace() -> inets_trace:disable().
%%-----------------------------------------------------------------
@@ -476,60 +432,7 @@ disable_trace() ->
%% This function is used to change the trace level when tracing has
%% already been started.
%%-----------------------------------------------------------------
-set_trace(Level) ->
- set_trace(Level, all).
-
-set_trace(Level, Service) ->
- Pat = make_pattern(?MODULE, Service, Level),
- change_pattern(Pat).
-
-make_pattern(Mod, Service, Level)
- when is_atom(Mod) andalso is_atom(Service) ->
- case Level of
- min ->
- {Mod, Service, []};
- max ->
- Head = ['$1', '_', '_', '_'],
- Body = [],
- Cond = [],
- {Mod, Service, [{Head, Cond, Body}]};
- DetailLevel when is_integer(DetailLevel) ->
- Head = ['$1', '_', '_', '_'],
- Body = [],
- Cond = [{ '=<', '$1', DetailLevel}],
- {Mod, Service, [{Head, Cond, Body}]};
- _ ->
- exit({bad_level, Level})
- end.
-
-change_pattern({Mod, Service, Pattern})
- when is_atom(Mod) andalso is_atom(Service) ->
- MFA = {Mod, report_event, 4},
- case Pattern of
- [] ->
- try
- error_to_exit(ctp, dbg:ctp(MFA)),
- error_to_exit(p, dbg:p(all, clear))
- catch
- exit:{Where, Reason} ->
- {error, {Where, Reason}}
- end;
- List when is_list(List) ->
- try
- error_to_exit(ctp, dbg:ctp(MFA)),
- error_to_exit(tp, dbg:tp(MFA, Pattern)),
- error_to_exit(p, dbg:p(all, [call, timestamp]))
- catch
- exit:{Where, Reason} ->
- {error, {Where, Reason}}
- end
- end,
- ok.
-
-error_to_exit(_Where, {ok, _} = OK) ->
- OK;
-error_to_exit(Where, {error, Reason}) ->
- exit({Where, Reason}).
+set_trace(Level) -> inets_trace:set_level(Level).
%%-----------------------------------------------------------------
@@ -546,164 +449,8 @@ error_to_exit(Where, {error, Reason}) ->
%% put trace on this function.
%%-----------------------------------------------------------------
-report_event(Severity, Label, Service, Content)
- when (is_integer(Severity) andalso
- (Severity >= 0) andalso (100 >= Severity)) andalso
- is_list(Label) andalso
- is_atom(Service) andalso
- is_list(Content) ->
- hopefully_traced.
-
-
-%% ----------------------------------------------------------------------
-%% handle_trace(Event, Fd) -> Verbosity
-%%
-%% Parameters:
-%% Event -> The trace event (only megaco 'trace_ts' events are printed)
-%% Fd -> standard_io | file_descriptor() | trace_port()
-%%
-%% Description:
-%% This function is used to "receive" and print the trace events.
-%% Events are printed if:
-%% - Verbosity is max
-%% - Severity is =< Verbosity (e.g. Severity = 30, and Verbosity = 40)
-%% Events are not printed if:
-%% - Verbosity is min
-%% - Severity is > Verbosity
-%%-----------------------------------------------------------------
-
-handle_trace(_, closed_file = Fd) ->
- Fd;
-handle_trace({trace_ts, _Who, call,
- {?MODULE, report_event,
- [_Sev, "stop trace", stop_trace, [stop_trace]]},
- Timestamp},
- {_, standard_io} = Fd) ->
- (catch io:format(standard_io, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
- Fd;
-handle_trace({trace_ts, _Who, call,
- {?MODULE, report_event,
- [_Sev, "stop trace", stop_trace, [stop_trace]]},
- Timestamp},
- standard_io = Fd) ->
- (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
- Fd;
-handle_trace({trace_ts, _Who, call,
- {?MODULE, report_event,
- [_Sev, "stop trace", stop_trace, [stop_trace]]},
- Timestamp},
- {_Service, Fd}) ->
- (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
- (catch file:close(Fd)),
- closed_file;
-handle_trace({trace_ts, _Who, call,
- {?MODULE, report_event,
- [_Sev, "stop trace", stop_trace, [stop_trace]]},
- Timestamp},
- Fd) ->
- (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
- (catch file:close(Fd)),
- closed_file;
-handle_trace({trace_ts, Who, call,
- {?MODULE, report_event,
- [Sev, Label, Service, Content]}, Timestamp},
- Fd) ->
- (catch print_inets_trace(Fd, Sev, Timestamp, Who,
- Label, Service, Content)),
- Fd;
-handle_trace(Event, Fd) ->
- (catch print_trace(Fd, Event)),
- Fd.
-
-
-print_inets_trace({Service, Fd},
- Sev, Timestamp, Who, Label, Service, Content) ->
- do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content);
-print_inets_trace({ServiceA, Fd},
- Sev, Timestamp, Who, Label, ServiceB, Content)
- when (ServiceA =:= all) ->
- do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, ServiceB, Content);
-print_inets_trace({ServiceA, _Fd},
- _Sev, _Timestamp, _Who, _Label, ServiceB, _Content)
- when ServiceA =/= ServiceB ->
- ok;
-print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content) ->
- do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content).
-
-do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content) ->
- Ts = format_timestamp(Timestamp),
- io:format(Fd, "[inets ~w trace ~w ~w ~s] ~s "
- "~n Content: ~p"
- "~n",
- [Service, Sev, Who, Ts, Label, Content]).
-
-print_trace({_, Fd}, Event) ->
- do_print_trace(Fd, Event);
-print_trace(Fd, Event) ->
- do_print_trace(Fd, Event).
-
-do_print_trace(Fd, {trace, Who, What, Where}) ->
- io:format(Fd, "[trace]"
- "~n Who: ~p"
- "~n What: ~p"
- "~n Where: ~p"
- "~n", [Who, What, Where]);
-
-do_print_trace(Fd, {trace, Who, What, Where, Extra}) ->
- io:format(Fd, "[trace]"
- "~n Who: ~p"
- "~n What: ~p"
- "~n Where: ~p"
- "~n Extra: ~p"
- "~n", [Who, What, Where, Extra]);
-
-do_print_trace(Fd, {trace_ts, Who, What, Where, When}) ->
- Ts = format_timestamp(When),
- io:format(Fd, "[trace ~s]"
- "~n Who: ~p"
- "~n What: ~p"
- "~n Where: ~p"
- "~n", [Ts, Who, What, Where]);
-
-do_print_trace(Fd, {trace_ts, Who, What, Where, Extra, When}) ->
- Ts = format_timestamp(When),
- io:format(Fd, "[trace ~s]"
- "~n Who: ~p"
- "~n What: ~p"
- "~n Where: ~p"
- "~n Extra: ~p"
- "~n", [Ts, Who, What, Where, Extra]);
-
-do_print_trace(Fd, {seq_trace, What, Where}) ->
- io:format(Fd, "[seq trace]"
- "~n What: ~p"
- "~n Where: ~p"
- "~n", [What, Where]);
-
-do_print_trace(Fd, {seq_trace, What, Where, When}) ->
- Ts = format_timestamp(When),
- io:format(Fd, "[seq trace ~s]"
- "~n What: ~p"
- "~n Where: ~p"
- "~n", [Ts, What, Where]);
-
-do_print_trace(Fd, {drop, Num}) ->
- io:format(Fd, "[drop trace] ~p~n", [Num]);
-
-do_print_trace(Fd, Trace) ->
- io:format(Fd, "[trace] "
- "~n ~p"
- "~n", [Trace]).
-
-
-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).
+report_event(Severity, Label, Service, Content) ->
+ inets_trace:report_event(Severity, Label, Service, Content).
%%--------------------------------------------------------------------
diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk
index b6e9fe1d96..adef32dc19 100644
--- a/lib/inets/src/inets_app/inets.mk
+++ b/lib/inets/src/inets_app/inets.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010. All Rights Reserved.
+# Copyright Ericsson AB 2010-2012. All Rights Reserved.
#
# The 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,8 +37,6 @@ INETS_APP_VSN_COMPILE_FLAGS = \
+'{parse_transform,sys_pre_attributes}' \
+'{attribute,insert,app_vsn,$(APP_VSN)}'
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
-
INETS_ERL_COMPILE_FLAGS += \
-pa $(ERL_TOP)/lib/inets/ebin \
$(INETS_APP_VSN_COMPILE_FLAGS)
diff --git a/lib/inets/src/inets_app/inets_app.erl b/lib/inets/src/inets_app/inets_app.erl
index cae79a6767..ee3359c4c3 100644
--- a/lib/inets/src/inets_app/inets_app.erl
+++ b/lib/inets/src/inets_app/inets_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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([start/2, stop/1]).
start(_Type, _State) ->
- supervisor:start_link({local, inets_sup}, inets_sup, []).
+ inets_sup:start_link().
stop(_State) ->
ok.
diff --git a/lib/inets/src/inets_app/inets_internal.hrl b/lib/inets/src/inets_app/inets_internal.hrl
index 55c3669e4a..e56af3b59d 100644
--- a/lib/inets/src/inets_app/inets_internal.hrl
+++ b/lib/inets/src/inets_app/inets_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %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
@@ -24,8 +24,8 @@
%% Various trace macros
-define(report(Severity, Label, Service, Content),
- inets:report_event(Severity, Label, Service,
- [{module, ?MODULE}, {line, ?LINE} | Content])).
+ inets_trace:report_event(Severity, Label, Service,
+ [{module, ?MODULE}, {line, ?LINE} | Content])).
-define(report_important(Label, Service, Content),
?report(20, Label, Service, Content)).
-define(report_verbose(Label, Service, Content),
diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl
index f89dac195c..d17fdfe13e 100644
--- a/lib/inets/src/inets_app/inets_service.erl
+++ b/lib/inets/src/inets_app/inets_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,7 @@
-module(inets_service).
+
%% Starts service stand-alone
%% start_standalone(Config) -> % {ok, Pid} | {error, Reason}
%% <service>:start_link(Config).
@@ -67,3 +68,4 @@
-callback service_info(Service :: term()) ->
{ok, [{Property :: term(), Value :: term()}]} | {error, Reason :: term()}.
+
diff --git a/lib/inets/src/inets_app/inets_sup.erl b/lib/inets/src/inets_app/inets_sup.erl
index 20d5ef343e..66a0cdf785 100644
--- a/lib/inets/src/inets_app/inets_sup.erl
+++ b/lib/inets/src/inets_app/inets_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,19 @@
-behaviour(supervisor).
+%% External API
+-export([start_link/0]).
+
+%% Supervisor callbacks
-export([init/1]).
%%%=========================================================================
+%%% External functions
+%%%=========================================================================
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
init([]) ->
diff --git a/lib/inets/src/inets_app/inets_trace.erl b/lib/inets/src/inets_app/inets_trace.erl
new file mode 100644
index 0000000000..8911f65897
--- /dev/null
+++ b/lib/inets/src/inets_app/inets_trace.erl
@@ -0,0 +1,357 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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: Module for debug trace functions of the inets application
+%%----------------------------------------------------------------------
+
+-module(inets_trace).
+
+%% API
+-export([enable/2, enable/3,
+ disable/0,
+ set_level/1, set_level/2,
+ report_event/4]).
+
+
+%%====================================================================
+%% API
+%%====================================================================
+
+%%-----------------------------------------------------------------
+%% enable(Level, Destination) -> void()
+%% enable(Level, Destination, Service) -> void()
+%%
+%% Parameters:
+%% Level -> max | min | integer()
+%% Destination -> File | Port | io | HandlerSpec
+%% Service -> httpc | httpd | ftpc | tftp | all
+%% File -> string()
+%% Port -> integer()
+%% Verbosity -> true | false
+%% HandlerSpec = {function(), Data}
+%% Data = term()
+%%
+%% Description:
+%% This function is used to start tracing at level Level and send
+%% the result either to the file File, the port Port or to a
+%% trace handler.
+%% Note that it starts a tracer server.
+%% When Destination is the atom io (or the tuple {io, Verbosity}),
+%% all (printable) inets trace events (trace_ts events which has
+%% Severity withing Limit) will be written to stdout using io:format.
+%%
+%%-----------------------------------------------------------------
+enable(Level, Dest) ->
+ enable(Level, Dest, all).
+
+enable(Level, Dest, Service) ->
+ case valid_trace_service(Service) of
+ true ->
+ enable2(Level, Dest, Service);
+ false ->
+ {error, {invalid_service, Service}}
+ end.
+
+enable2(Level, File, Service)
+ when is_list(File) ->
+ case file:open(File, [write]) of
+ {ok, Fd} ->
+ HandleSpec = {fun handle_trace/2, {Service, Fd}},
+ do_enable(Level, process, HandleSpec);
+ Err ->
+ Err
+ end;
+enable2(Level, Port, _) when is_integer(Port) ->
+ do_enable(Level, port, dbg:trace_port(ip, Port));
+enable2(Level, io, Service) ->
+ HandleSpec = {fun handle_trace/2, {Service, standard_io}},
+ do_enable(Level, process, HandleSpec);
+enable2(Level, {Fun, _Data} = HandleSpec, _) when is_function(Fun) ->
+ do_enable(Level, process, HandleSpec).
+
+do_enable(Level, Type, HandleSpec) ->
+ case dbg:tracer(Type, HandleSpec) of
+ {ok, _} ->
+ set_level(Level),
+ ok;
+ Error ->
+ Error
+ end.
+
+valid_trace_service(all) ->
+ true;
+valid_trace_service(Service) ->
+ lists:member(Service, [httpc, httpd, ftpc, tftp]).
+
+
+%%-----------------------------------------------------------------
+%% disable() -> void()
+%%
+%% Description:
+%% This function is used to stop tracing.
+%%-----------------------------------------------------------------
+
+disable() ->
+ %% This is to make handle_trace/2 close the output file (if the
+ %% event gets there before dbg closes)
+ inets_trace:report_event(100, "stop trace", stop_trace, [stop_trace]),
+ dbg:stop().
+
+
+
+%%-----------------------------------------------------------------
+%% set_level(Level) -> void()
+%%
+%% Parameters:
+%% Level -> max | min | integer()
+%%
+%% Description:
+%% This function is used to change the trace level when tracing has
+%% already been started.
+%%-----------------------------------------------------------------
+set_level(Level) ->
+ set_level(Level, all).
+
+set_level(Level, Service) ->
+ Pat = make_pattern(?MODULE, Service, Level),
+ change_pattern(Pat).
+
+make_pattern(Mod, Service, Level)
+ when is_atom(Mod) andalso is_atom(Service) ->
+ case Level of
+ min ->
+ {Mod, Service, []};
+ max ->
+ Head = ['$1', '_', '_', '_'],
+ Body = [],
+ Cond = [],
+ {Mod, Service, [{Head, Cond, Body}]};
+ DetailLevel when is_integer(DetailLevel) ->
+ Head = ['$1', '_', '_', '_'],
+ Body = [],
+ Cond = [{ '=<', '$1', DetailLevel}],
+ {Mod, Service, [{Head, Cond, Body}]};
+ _ ->
+ exit({bad_level, Level})
+ end.
+
+change_pattern({Mod, Service, Pattern})
+ when is_atom(Mod) andalso is_atom(Service) ->
+ MFA = {Mod, report_event, 4},
+ case Pattern of
+ [] ->
+ try
+ error_to_exit(ctp, dbg:ctp(MFA)),
+ error_to_exit(p, dbg:p(all, clear))
+ catch
+ exit:{Where, Reason} ->
+ {error, {Where, Reason}}
+ end;
+ List when is_list(List) ->
+ try
+ error_to_exit(ctp, dbg:ctp(MFA)),
+ error_to_exit(tp, dbg:tp(MFA, Pattern)),
+ error_to_exit(p, dbg:p(all, [call, timestamp]))
+ catch
+ exit:{Where, Reason} ->
+ {error, {Where, Reason}}
+ end
+ end.
+
+error_to_exit(_Where, {ok, _} = OK) ->
+ OK;
+error_to_exit(Where, {error, Reason}) ->
+ exit({Where, Reason}).
+
+
+%%-----------------------------------------------------------------
+%% report_event(Severity, Label, Service, Content)
+%%
+%% Parameters:
+%% Severity -> 0 =< integer() =< 100
+%% Label -> string()
+%% Service -> httpd | httpc | ftp | tftp
+%% Content -> [{tag, term()}]
+%%
+%% Description:
+%% This function is used to generate trace events, that is,
+%% put trace on this function.
+%%-----------------------------------------------------------------
+
+report_event(Severity, Label, Service, Content)
+ when (is_integer(Severity) andalso
+ (Severity >= 0) andalso (100 >= Severity)) andalso
+ is_list(Label) andalso
+ is_atom(Service) andalso
+ is_list(Content) ->
+ hopefully_traced.
+
+
+%% ----------------------------------------------------------------------
+%% handle_trace(Event, Fd) -> Verbosity
+%%
+%% Parameters:
+%% Event -> The trace event
+%% Fd -> standard_io | file_descriptor() | trace_port()
+%%
+%% Description:
+%% This function is used to "receive" and pretty print the trace events.
+%% Events are printed if:
+%% - Verbosity is max
+%% - Severity is =< Verbosity (e.g. Severity = 30, and Verbosity = 40)
+%% Events are not printed if:
+%% - Verbosity is min
+%% - Severity is > Verbosity
+%%-----------------------------------------------------------------
+
+handle_trace(_, closed_file = Fd) ->
+ Fd;
+handle_trace({trace_ts, _Who, call,
+ {?MODULE, report_event,
+ [_Sev, "stop trace", stop_trace, [stop_trace]]},
+ Timestamp},
+ {_, standard_io} = Fd) ->
+ (catch io:format(standard_io, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ Fd;
+handle_trace({trace_ts, _Who, call,
+ {?MODULE, report_event,
+ [_Sev, "stop trace", stop_trace, [stop_trace]]},
+ Timestamp},
+ standard_io = Fd) ->
+ (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ Fd;
+handle_trace({trace_ts, _Who, call,
+ {?MODULE, report_event,
+ [_Sev, "stop trace", stop_trace, [stop_trace]]},
+ Timestamp},
+ {_Service, Fd}) ->
+ (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ (catch file:close(Fd)),
+ closed_file;
+handle_trace({trace_ts, _Who, call,
+ {?MODULE, report_event,
+ [_Sev, "stop trace", stop_trace, [stop_trace]]},
+ Timestamp},
+ Fd) ->
+ (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ (catch file:close(Fd)),
+ closed_file;
+handle_trace({trace_ts, Who, call,
+ {?MODULE, report_event,
+ [Sev, Label, Service, Content]}, Timestamp},
+ Fd) ->
+ (catch print_inets_trace(Fd, Sev, Timestamp, Who,
+ Label, Service, Content)),
+ Fd;
+handle_trace(Event, Fd) ->
+ (catch print_trace(Fd, Event)),
+ Fd.
+
+
+print_inets_trace({Service, Fd},
+ Sev, Timestamp, Who, Label, Service, Content) ->
+ do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content);
+print_inets_trace({ServiceA, Fd},
+ Sev, Timestamp, Who, Label, ServiceB, Content)
+ when (ServiceA =:= all) ->
+ do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, ServiceB, Content);
+print_inets_trace({ServiceA, _Fd},
+ _Sev, _Timestamp, _Who, _Label, ServiceB, _Content)
+ when ServiceA =/= ServiceB ->
+ ok;
+print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content) ->
+ do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content).
+
+do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content) ->
+ Ts = format_timestamp(Timestamp),
+ io:format(Fd, "[inets ~w trace ~w ~w ~s] ~s "
+ "~n Content: ~p"
+ "~n",
+ [Service, Sev, Who, Ts, Label, Content]).
+
+print_trace({_, Fd}, Event) ->
+ do_print_trace(Fd, Event);
+print_trace(Fd, Event) ->
+ do_print_trace(Fd, Event).
+
+do_print_trace(Fd, {trace, Who, What, Where}) ->
+ io:format(Fd, "[trace]"
+ "~n Who: ~p"
+ "~n What: ~p"
+ "~n Where: ~p"
+ "~n", [Who, What, Where]);
+
+do_print_trace(Fd, {trace, Who, What, Where, Extra}) ->
+ io:format(Fd, "[trace]"
+ "~n Who: ~p"
+ "~n What: ~p"
+ "~n Where: ~p"
+ "~n Extra: ~p"
+ "~n", [Who, What, Where, Extra]);
+
+do_print_trace(Fd, {trace_ts, Who, What, Where, When}) ->
+ Ts = format_timestamp(When),
+ io:format(Fd, "[trace ~s]"
+ "~n Who: ~p"
+ "~n What: ~p"
+ "~n Where: ~p"
+ "~n", [Ts, Who, What, Where]);
+
+do_print_trace(Fd, {trace_ts, Who, What, Where, Extra, When}) ->
+ Ts = format_timestamp(When),
+ io:format(Fd, "[trace ~s]"
+ "~n Who: ~p"
+ "~n What: ~p"
+ "~n Where: ~p"
+ "~n Extra: ~p"
+ "~n", [Ts, Who, What, Where, Extra]);
+
+do_print_trace(Fd, {seq_trace, What, Where}) ->
+ io:format(Fd, "[seq trace]"
+ "~n What: ~p"
+ "~n Where: ~p"
+ "~n", [What, Where]);
+
+do_print_trace(Fd, {seq_trace, What, Where, When}) ->
+ Ts = format_timestamp(When),
+ io:format(Fd, "[seq trace ~s]"
+ "~n What: ~p"
+ "~n Where: ~p"
+ "~n", [Ts, What, Where]);
+
+do_print_trace(Fd, {drop, Num}) ->
+ io:format(Fd, "[drop trace] ~p~n", [Num]);
+
+do_print_trace(Fd, Trace) ->
+ io:format(Fd, "[trace] "
+ "~n ~p"
+ "~n", [Trace]).
+
+
+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/src/tftp/Makefile b/lib/inets/src/tftp/Makefile
index 759b70c8e4..a9df8d0319 100644
--- a/lib/inets/src/tftp/Makefile
+++ b/lib/inets/src/tftp/Makefile
@@ -39,8 +39,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
+BEHAVIOUR_MODULES= \
+ tftp
+
MODULES = \
- tftp \
tftp_binary \
tftp_engine \
tftp_file \
@@ -50,10 +52,13 @@ MODULES = \
HRL_FILES = tftp.hrl
-ERL_FILES = $(MODULES:%=%.erl)
+ERL_FILES= \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
# FLAGS
@@ -72,10 +77,12 @@ ERL_COMPILE_FLAGS += \
# Targets
# ----------------------------------------------------
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
+
debug opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES)
+ rm -f $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES)
rm -f core
docs:
@@ -86,11 +93,11 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/tftp
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/tftp
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/tftp"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/tftp"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl
index b33c0a98f4..1621add246 100644
--- a/lib/inets/src/tftp/tftp.erl
+++ b/lib/inets/src/tftp/tftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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/inets/test/Makefile b/lib/inets/test/Makefile
index 87ca60e4b3..7befa82272 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -234,7 +234,7 @@ endif
# Release directory specification
# ----------------------------------------------------
-RELTESTSYSDIR = $(RELEASE_PATH)/inets_test
+RELTESTSYSDIR = "$(RELEASE_PATH)/inets_test"
RELTESTSYSALLDATADIR = $(RELTESTSYSDIR)/all_SUITE_data
RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
@@ -284,9 +284,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/test
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/test
- $(INSTALL_DATA) $(INETS_FILES) $(RELSYSDIR)/test
+ $(INSTALL_DIR) "$(RELSYSDIR)/test"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/test"
+ $(INSTALL_DATA) $(INETS_FILES) "$(RELSYSDIR)/test"
@for d in $(DATADIRS); do \
echo "installing data dir $$d"; \
if test -f $$d/TAR.exclude; then \
@@ -299,9 +299,9 @@ release_spec: opt
find $$d -name 'erl_crash.dump' >> $$d/TAR.exclude2; \
find $$d -name 'core' >> $$d/TAR.exclude2; \
find $$d -name '.cmake.state' >> $$d/TAR.exclude2; \
- tar cfX - $$d/TAR.exclude2 $$d | (cd $(RELSYSDIR)/test; tar xf -); \
+ tar cfX - $$d/TAR.exclude2 $$d | (cd "$(RELSYSDIR)/test"; tar xf -); \
else \
- tar cf - $$d | (cd $(RELSYSDIR)/test; tar xf -); \
+ tar cf - $$d | (cd "$(RELSYSDIR)/test"; tar xf -); \
fi; \
done
@@ -330,8 +330,8 @@ info:
@echo "INETS_SPECS = $(INETS_SPECS)"
@echo "INETS_FILES = $(INETS_FILES)"
@echo ""
- @echo "RELEASE_PATH = $(RELEASE_PATH)"
- @echo "RELSYSDIR = $(RELSYSDIR)"
+ @echo "RELEASE_PATH = "$(RELEASE_PATH)""
+ @echo "RELSYSDIR = "$(RELSYSDIR)""
@echo "RELTESTSYSDIR = $(RELTESTSYSDIR)"
@echo "RELTESTSYSALLDATADIR = $(RELTESTSYSALLDATADIR)"
@echo "RELTESTSYSBINDIR = $(RELTESTSYSBINDIR)"
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index 3ebd02229e..ffb58c91b6 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -196,7 +196,9 @@ test_filenames() ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_testcase(Case, Config)
- when (Case =:= open) orelse (Case =:= open_port) ->
+ when (Case =:= open) orelse
+ (Case =:= open_port) ->
+ put(ftp_testcase, Case),
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
inets:start(),
NewConfig = data_dir(Config),
@@ -266,7 +268,7 @@ do_init_per_testcase(Case, Config) ->
end,
Opts2 =
case string:tokens(atom_to_list(Case), [$_]) of
- [_, "active" | _] ->
+ ["active" | _] ->
[{mode, active} | Opts1];
_ ->
[{mode, passive} | Opts1]
@@ -367,8 +369,11 @@ open(Config) when is_list(Config) ->
tc_open(Host) ->
+ p("tc_open -> entry with"
+ "~n Host: ~p", [Host]),
{ok, Pid} = ?ftp_open(Host, []),
ok = ftp:close(Pid),
+ p("tc_open -> try (ok) open 1"),
{ok, Pid1} =
ftp:open({option_list, [{host,Host},
{port, ?FTP_PORT},
@@ -376,11 +381,13 @@ tc_open(Host) ->
{timeout, 30000}]}),
ok = ftp:close(Pid1),
+ p("tc_open -> try (fail) open 2"),
{error, ehost} =
ftp:open({option_list, [{port, ?FTP_PORT}, {flags, [verbose]}]}),
{ok, Pid2} = ftp:open(Host),
ok = ftp:close(Pid2),
+ p("tc_open -> try (ok) open 3"),
{ok, NewHost} = inet:getaddr(Host, inet),
{ok, Pid3} = ftp:open(NewHost),
ftp:user(Pid3, ?FTP_USER, ?FTP_PASS),
@@ -392,33 +399,68 @@ tc_open(Host) ->
%% Bad input that has default values are ignored and the defult
%% is used.
+ p("tc_open -> try (ok) open 4"),
{ok, Pid4} =
- ftp:open({option_list, [{host, Host}, {port, badarg},
- {flags, [verbose]},
+ ftp:open({option_list, [{host, Host},
+ {port, badarg},
+ {flags, [verbose]},
{timeout, 30000}]}),
test_server:sleep(100),
ok = ftp:close(Pid4),
+
+ p("tc_open -> try (ok) open 5"),
{ok, Pid5} =
- ftp:open({option_list, [{host, Host}, {port, ?FTP_PORT},
- {flags, [verbose]},
+ ftp:open({option_list, [{host, Host},
+ {port, ?FTP_PORT},
+ {flags, [verbose]},
{timeout, -42}]}),
test_server:sleep(100),
ok = ftp:close(Pid5),
+
+ p("tc_open -> try (ok) open 6"),
{ok, Pid6} =
- ftp:open({option_list, [{host, Host}, {port, ?FTP_PORT},
+ ftp:open({option_list, [{host, Host},
+ {port, ?FTP_PORT},
{flags, [verbose]},
- {mode, cool}]}),
+ {mode, cool}]}),
test_server:sleep(100),
ok = ftp:close(Pid6),
+ p("tc_open -> try (ok) open 7"),
{ok, Pid7} =
ftp:open(Host, [{port, ?FTP_PORT}, {verbose, true}, {timeout, 30000}]),
ok = ftp:close(Pid7),
+ p("tc_open -> try (ok) open 8"),
{ok, Pid8} =
ftp:open(Host, ?FTP_PORT),
ok = ftp:close(Pid8),
+ p("tc_open -> try (ok) open 9"),
+ {ok, Pid9} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
+ {dtimeout, -99}]),
+ ok = ftp:close(Pid9),
+
+ p("tc_open -> try (ok) open 10"),
+ {ok, Pid10} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
+ {dtimeout, "foobar"}]),
+ ok = ftp:close(Pid10),
+
+ p("tc_open -> try (ok) open 11"),
+ {ok, Pid11} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
+ {dtimeout, 1}]),
+ ok = ftp:close(Pid11),
+
+ p("tc_open -> done"),
ok.
@@ -445,7 +487,7 @@ passive_user(suite) ->
[];
passive_user(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
- io:format("Pid: ~p~n",[Pid]),
+ p("Pid: ~p",[Pid]),
do_user(Pid).
@@ -967,13 +1009,13 @@ api_missuse(doc)->
["Test that behaviour of the ftp process if the api is abused"];
api_missuse(suite) -> [];
api_missuse(Config) when is_list(Config) ->
- io:format("api_missuse -> entry~n", []),
+ p("api_missuse -> entry"),
Flag = process_flag(trap_exit, true),
Pid = ?config(ftp, Config),
Host = ftp_host(Config),
%% Serious programming fault, connetion will be shut down
- io:format("api_missuse -> verify bad call termination (~p)~n", [Pid]),
+ p("api_missuse -> verify bad call termination (~p)", [Pid]),
case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
{error, {connection_terminated, 'API_violation'}} ->
ok;
@@ -983,23 +1025,23 @@ api_missuse(Config) when is_list(Config) ->
test_server:sleep(500),
undefined = process_info(Pid, status),
- io:format("api_missuse -> start new client~n", []),
+ p("api_missuse -> start new client"),
{ok, Pid2} = ?ftp_open(Host, []),
%% Serious programming fault, connetion will be shut down
- io:format("api_missuse -> verify bad cast termination~n", []),
+ p("api_missuse -> verify bad cast termination"),
gen_server:cast(Pid2, {self(), foobar, 10}),
test_server:sleep(500),
undefined = process_info(Pid2, status),
- io:format("api_missuse -> start new client~n", []),
+ p("api_missuse -> start new client"),
{ok, Pid3} = ?ftp_open(Host, []),
%% Could be an innocent misstake the connection lives.
- io:format("api_missuse -> verify bad bang~n", []),
+ p("api_missuse -> verify bad bang"),
Pid3 ! foobar,
test_server:sleep(500),
{status, _} = process_info(Pid3, status),
process_flag(trap_exit, Flag),
- io:format("api_missuse -> done~n", []),
+ p("api_missuse -> done"),
ok.
@@ -1567,9 +1609,9 @@ split([], I, Is) ->
lists:reverse([lists:reverse(I)| Is]).
do_ftp_open(Host, Opts) ->
- io:format("do_ftp_open -> entry with"
- "~n Host: ~p"
- "~n Opts: ~p", [Host, Opts]),
+ p("do_ftp_open -> entry with"
+ "~n Host: ~p"
+ "~n Opts: ~p", [Host, Opts]),
case ftp:open(Host, Opts) of
{ok, _} = OK ->
OK;
@@ -1595,7 +1637,7 @@ passwd() ->
ftpd_hosts(Config) ->
DataDir = ?config(data_dir, Config),
FileName = filename:join([DataDir, "../ftp_SUITE_data/", ftpd_hosts]),
- io:format("FileName: ~p~n", [FileName]),
+ p("FileName: ~p", [FileName]),
case file:consult(FileName) of
{ok, [Hosts]} when is_list(Hosts) ->
Hosts;
diff --git a/lib/inets/test/ftp_windows_2003_server_test.erl b/lib/inets/test/ftp_windows_2003_server_test.erl
index 57f1ae8358..32f25713f8 100644
--- a/lib/inets/test/ftp_windows_2003_server_test.erl
+++ b/lib/inets/test/ftp_windows_2003_server_test.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
@@ -87,14 +87,22 @@ end_per_testcase(Case, Config) ->
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
+ [
+ open,
+ open_port,
+ {group, passive},
+ {group, active},
+ api_missuse,
+ not_owner,
+ {group, progress_report}
+ ].
groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
+ [
+ {passive, [], ftp_suite_lib:passive(suite)},
+ {active, [], ftp_suite_lib:active(suite)},
+ {progress_report, [], ftp_suite_lib:progress_report(suite)}
+ ].
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index f95fb93669..1cdd96f0b0 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,6 +90,7 @@ all() ->
parse_url,
options,
headers_as_is,
+ selecting_session,
{group, proxy},
{group, ssl},
{group, stream},
@@ -145,7 +146,13 @@ groups() ->
].
-
+init_per_group(ipv6 = _GroupName, Config) ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
+ Config;
+ _ ->
+ {skip, "Host does not support IPv6"}
+ end;
init_per_group(_GroupName, Config) ->
Config.
@@ -163,6 +170,9 @@ end_per_group(_GroupName, Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+
+ ?PRINT_SYSTEM_INFO([]),
+
PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config),
ServerRoot = filename:join(PrivDir, "server_root"),
@@ -186,10 +196,11 @@ init_per_suite(Config) ->
{ok, FileInfo} = file:read_file_info(Cgi),
ok = file:write_file_info(Cgi, FileInfo#file_info{mode = 8#00755}),
- [{server_root, ServerRoot},
- {doc_root, DocRoot},
- {local_port, ?IP_PORT},
- {local_ssl_port, ?SSL_PORT} | Config].
+ [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
+ {server_root, ServerRoot},
+ {doc_root, DocRoot},
+ {local_port, ?IP_PORT},
+ {local_ssl_port, ?SSL_PORT} | Config].
%%--------------------------------------------------------------------
@@ -205,6 +216,7 @@ end_per_suite(Config) ->
application:stop(ssl),
ok.
+
%%--------------------------------------------------------------------
%% Function: init_per_testcase(Case, Config) -> Config
%% Case - atom()
@@ -226,9 +238,7 @@ init_per_testcase(initial_server_connect = Case, Config) ->
%% this test case does not work unless it does
try
begin
- ensure_started(crypto),
- ensure_started(public_key),
- ensure_started(ssl),
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
inets:start(),
Config
end
@@ -238,22 +248,23 @@ init_per_testcase(initial_server_connect = Case, Config) ->
"~n ~p", [Case, App, ActualError]),
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
+ skip(SkipString);
_:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
init_per_testcase(Case, Config) ->
init_per_testcase(Case, 2, Config).
init_per_testcase(Case, Timeout, Config) ->
- 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"),
+ io:format(user,
+ "~n~n*** INIT ~w:~w[~w] ***"
+ "~n~n", [?MODULE, Case, Timeout]),
+
+ PrivDir = ?config(priv_dir, Config),
application:stop(inets),
Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
TmpConfig = lists:keydelete(watchdog, 1, Config),
@@ -262,15 +273,17 @@ init_per_testcase(Case, Timeout, Config) ->
%% inets:enable_trace(max, io, httpd),
%% inets:enable_trace(max, io, httpc),
- inets:enable_trace(max, io, all),
+ %% inets:enable_trace(max, io, all),
NewConfig =
case atom_to_list(Case) of
[$s, $s, $l | _] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
[{watchdog, Dog} | TmpConfig]);
[$e, $s, $s, $l | _] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
init_per_testcase_ssl(essl, PrivDir, SslConfFile,
[{watchdog, Dog} | TmpConfig]);
@@ -282,19 +295,19 @@ init_per_testcase(Case, Timeout, Config) ->
inets:start(),
tsp("init_per_testcase -> "
"[proxy case] start crypto, public_key and ssl"),
- try ensure_started([crypto, public_key, ssl]) of
+ try ?ENSURE_STARTED([crypto, public_key, ssl]) of
ok ->
[{watchdog, Dog} | TmpConfig]
catch
throw:{error, {failed_starting, App, _}} ->
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
- _:X ->
+ skip(SkipString);
+ _:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
_ ->
@@ -323,20 +336,20 @@ init_per_testcase(Case, Timeout, Config) ->
],
case lists:member(Rest, BadCases) of
true ->
- [{skip, "TC and server not compatible"}|
+ [skip("TC and server not compatible") |
TmpConfig];
false ->
inets:start(),
[{watchdog, Dog} | TmpConfig]
end;
false ->
- [{skip, "proxy not responding"} | 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
+ %% Ensure needed apps (crypto, public_key and ssl) are started
+ try ?ENSURE_STARTED([crypto, public_key, ssl]) of
ok ->
Profile = ipv6,
%% A stand-alone profile is represented by a pid()
@@ -344,7 +357,8 @@ init_per_testcase(Case, Timeout, Config) ->
inets:start(httpc,
[{profile, Profile},
{data_dir, PrivDir}], stand_alone),
- httpc:set_options([{ipfamily, inet6}], ProfilePid),
+ ok = httpc:set_options([{ipfamily, inet6}],
+ ProfilePid),
tsp("httpc profile pid: ~p", [ProfilePid]),
[{watchdog, Dog}, {profile, ProfilePid}| TmpConfig]
catch
@@ -353,28 +367,67 @@ init_per_testcase(Case, Timeout, Config) ->
"~n ~p", [Case, App, ActualError]),
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
+ skip(SkipString);
_:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
+
_ ->
+ %% Try inet6fb4 on windows...
+ %% No need? Since it is set above?
+
+ %% tsp("init_per_testcase -> allways try IPv6 on windows"),
+ %% ?RUN_ON_WINDOWS(
+ %% fun() ->
+ %% tsp("init_per_testcase:set_options_fun -> "
+ %% "set-option ipfamily to inet6fb4"),
+ %% Res = httpc:set_options([{ipfamily, inet6fb4}]),
+ %% tsp("init_per_testcase:set_options_fun -> "
+ %% "~n Res: ~p", [Res]),
+ %% Res
+ %% end),
+
TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
- Server =
- %% Will start inets
- inets_test_lib:start_http_server(
- filename:join(PrivDir, IpConfFile)),
+ %% Will start inets
+ tsp("init_per_testcase -> try start server"),
+ Server = start_http_server(PrivDir, IpConfFile),
[{watchdog, Dog}, {local_server, Server} | TmpConfig2]
end,
- %% This will fail for the ipv6_ - cases (but that is ok)
- httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT},
- ["localhost", ?IPV6_LOCAL_HOST]}},
- {ipfamily, inet6fb4}]),
+ %% <IPv6>
+ %% Set default ipfamily to the same as the main server has by default
+ %% This makes the client try w/ ipv6 before falling back to ipv4,
+ %% as that is what the server is configured to do.
+ %% Note that this is required for the tests to run on *BSD w/ ipv6 enabled
+ %% as well as on Windows. The Linux behaviour of allowing ipv4 connects
+ %% to ipv6 sockets is not required or even encouraged.
+
+ tsp("init_per_testcase -> Options before ipfamily set: ~n~p",
+ [httpc:get_options(all)]),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("init_per_testcase -> Options after ipfamily set: ~n~p",
+ [httpc:get_options(all)]),
+
+ %% Note that the IPv6 test case(s) *must* use inet6,
+ %% so this value will be overwritten (see "ipv6_" below).
+ %% </IPv6>
+ %% This will fail for the ipv6_ - cases (but that is ok)
+ ProxyExceptions = ["localhost", ?IPV6_LOCAL_HOST],
+ tsp("init_per_testcase -> Options before proxy set: ~n~p",
+ [httpc:get_options(all)]),
+ ok = httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT}, ProxyExceptions}}]),
+ tsp("init_per_testcase -> Options after proxy set: ~n~p",
+ [httpc:get_options(all)]),
+ inets:enable_trace(max, io, httpc),
+ %% inets:enable_trace(max, io, all),
%% snmp:set_trace([gen_tcp]),
+ tsp("init_per_testcase(~w) -> done when"
+ "~n NewConfig: ~p"
+ "~n~n", [Case, NewConfig]),
NewConfig.
@@ -390,7 +443,10 @@ init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
[{local_ssl_server, Server} | Config2].
-
+start_http_server(ConfDir, ConfFile) ->
+ inets_test_lib:start_http_server( filename:join(ConfDir, ConfFile) ).
+
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -410,6 +466,7 @@ end_per_testcase(http_save_to_file = Case, Config) ->
end_per_testcase(Case, Config) ->
io:format(user, "~n~n*** END ~w:~w ***~n~n",
[?MODULE, Case]),
+ dbg:stop(), % ?
case atom_to_list(Case) of
"ipv6_" ++ _Rest ->
tsp("end_per_testcase(~w) -> stop ssl", [Case]),
@@ -454,29 +511,39 @@ http_options(doc) ->
http_options(suite) ->
[];
http_options(Config) when is_list(Config) ->
- {skip, "Not supported by httpd"}.
+ skip("Not supported by httpd").
http_head(doc) ->
["Test http head request against local server."];
http_head(suite) ->
[];
http_head(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- case httpc:request(head, {URL, []}, [], []) of
- {ok, {{_,200,_}, [_ | _], []}} ->
- ok;
- {ok, WrongReply} ->
- tsf({wrong_reply, WrongReply});
- Error ->
- tsf({failed, Error})
- end;
- _ ->
- {skip, "Failed to start local http-server"}
- end.
+ tsp("http_head -> entry with"
+ "~n Config: ~p", [Config]),
+ Method = head,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HttpOpts = [],
+ Opts = [],
+ VerifyResult =
+ fun({ok, {{_,200,_}, [_ | _], []}}) ->
+ ok;
+ ({ok, UnexpectedReply}) ->
+ tsp("http_head:verify_fun -> Unexpected Reply: "
+ "~n ~p", [UnexpectedReply]),
+ tsf({unexpected_reply, UnexpectedReply});
+ ({error, Reason} = Error) ->
+ tsp("http_head:verify_fun -> Error reply: "
+ "~n Reason: ~p", [Reason]),
+ tsf({bad_reply, Error})
+ end,
+ simple_request_and_verify(Config,
+ Method, Request, HttpOpts, Opts, VerifyResult).
+
+
%%-------------------------------------------------------------------------
+
http_get(doc) ->
["Test http get request against local server"];
http_get(suite) ->
@@ -493,7 +560,8 @@ http_get(Config) when is_list(Config) ->
Request = {URL, []},
Timeout = timer:seconds(1),
ConnTimeout = Timeout + timer:seconds(1),
- HttpOptions1 = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
+ HttpOptions1 = [{timeout, Timeout},
+ {connect_timeout, ConnTimeout}],
Options1 = [],
Body =
case httpc:request(Method, Request, HttpOptions1, Options1) of
@@ -521,14 +589,15 @@ http_get(Config) when is_list(Config) ->
tsf({bad_reply, Error2})
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
+
http_post(doc) ->
- ["Test http post request against local server. We do in this case"
- " only care about the client side of the the post. The server"
- " script will not actually use the post data."];
+ ["Test http post request against local server. We do in this case "
+ "only care about the client side of the the post. The server "
+ "script will not actually use the post data."];
http_post(suite) ->
[];
http_post(Config) when is_list(Config) ->
@@ -556,7 +625,7 @@ http_post(Config) when is_list(Config) ->
httpc:request(post, {URL, [{"expect","100-continue"}],
"text/plain", "foobar"}, [], []);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -602,7 +671,7 @@ http_post_streaming(Config) when is_list(Config) ->
"text/plain", {BodyFun, 10}}, [], []);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -626,7 +695,7 @@ http_emulate_lower_versions(Config) when is_list(Config) ->
httpc:request(get, {URL, []}, [{version, "HTTP/1.1"}], []),
inets_test_lib:check_body(Body2);
_->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -687,121 +756,163 @@ http_inets_pipe(Config) when is_list(Config) ->
URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
test_pipeline(URL);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
test_pipeline(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} =
+ p("test_pipeline -> entry with"
+ "~n URL: ~p", [URL]),
+
+ httpc:set_options([{pipeline_timeout, 50000}]),
+
+ p("test_pipeline -> issue (async) request 1"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdA1} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- 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),
-
- p("test_pipeline -> issue (async) request 2"),
- {ok, RequestId2} =
+ tsp("RequestIdA1: ~p", [RequestIdA1]),
+ p("test_pipeline -> RequestIdA1: ~p"
+ "~n when profile info: ~p", [RequestIdA1, httpc:info()]),
+
+ %% Make sure pipeline is initiated
+ p("test_pipeline -> sleep some", []),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request A2, A3 and A4"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdA2} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId2: ~p", [RequestId2]),
- p("test_pipeline -> RequestId2: ~p", [RequestId2]),
-
- p("test_pipeline -> issue (sync) request 3"),
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ {ok, RequestIdA3} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdA4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p",
+ [RequestIdA2, RequestIdA3, RequestIdA4]),
+ p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p"
+ "~n when profile info: ~p",
+ [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]),
+
+ 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
- {http, {RequestId1, {{_, 200, _}, _, _}}} ->
- p("test_pipeline -> received reply for (async) request 1 - now wait for 2"),
- receive
- {http, {RequestId2, {{_, 200, _}, _, _}}} ->
- p("test_pipeline -> received reply for (async) request 2"),
- ok;
- {http, Msg1} ->
- test_server:fail(Msg1)
- end;
- {http, {RequestId2, {{_, 200, _}, _, _}}} ->
- io:format("test_pipeline -> received reply for (async) request 2 - now wait for 1"),
- receive
- {http, {RequestId1, {{_, 200, _}, _, _}}} ->
- io:format("test_pipeline -> received reply for (async) request 1"),
- ok;
- {http, Msg2} ->
- test_server:fail(Msg2)
- 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
- end,
-
- p("test_pipeline -> sleep some"),
- test_server:sleep(4000),
-
- p("test_pipeline -> issue (async) request 4"),
- {ok, RequestId3} =
+
+ p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4"
+ "~n when profile info: ~p", [httpc:info()]),
+ pipeline_await_async_reply([{RequestIdA1, a1, 200},
+ {RequestIdA2, a2, 200},
+ {RequestIdA3, a3, 200},
+ {RequestIdA4, a4, 200}], ?MINS(1)),
+
+ p("test_pipeline -> sleep some"
+ "~n when profile info: ~p", [httpc:info()]),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request B1, B2, B3 and B4"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdB1} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId3: ~p", [RequestId3]),
- p("test_pipeline -> RequestId3: ~p", [RequestId3]),
-
- p("test_pipeline -> issue (async) request 5"),
- {ok, RequestId4} =
+ {ok, RequestIdB2} =
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;
- {http, Msg4} ->
- test_server:fail(Msg4)
- after 60000 ->
- receive Any2 ->
- tsp("received crap after timeout: ~n ~p", [Any2]),
- test_server:fail({error, {timeout, Any2}})
- end
- end,
-
- p("test_pipeline -> check reply for (async) request 5"),
+ {ok, RequestIdB3} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdB4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p",
+ [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]),
+ p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p"
+ "~n when profile info: ~p",
+ [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]),
+
+ p("test_pipeline -> cancel (async) request B2"
+ "~n when profile info: ~p", [httpc:info()]),
+ ok = httpc:cancel_request(RequestIdB2),
+
+ p("test_pipeline -> "
+ "expect *no* reply for cancelled (async) request B2 (for 3 secs)"
+ "~n when profile info: ~p", [httpc:info()]),
+ receive
+ {http, {RequestIdB2, _}} ->
+ tsf(http_cancel_request_failed)
+ after 3000 ->
+ ok
+ end,
+
+ p("test_pipeline -> expect reply for (async) request B1, B3 and B4"
+ "~n when profile info: ~p", [httpc:info()]),
+ Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200},
+ {RequestIdB3, b3, 200},
+ {RequestIdB4, b4, 200}], ?MINS(1)),
+ [{b1, Body}|_] = Bodies,
+
+ p("test_pipeline -> check reply for (async) request B1"
+ "~n when profile info: ~p", [httpc:info()]),
inets_test_lib:check_body(binary_to_list(Body)),
-
- p("test_pipeline -> ensure no unexpected incomming"),
+
+ p("test_pipeline -> ensure no unexpected incomming"
+ "~n when profile info: ~p", [httpc:info()]),
receive
{http, Any} ->
- test_server:fail({unexpected_message, Any})
+ tsf({unexpected_message, Any})
after 500 ->
ok
end,
-
- p("test_pipeline -> done"),
+
+ p("test_pipeline -> done"
+ "~n when profile info: ~p", [httpc:info()]),
ok.
+pipeline_await_async_reply(ReqIds, Timeout) ->
+ pipeline_await_async_reply(ReqIds, Timeout, []).
+
+pipeline_await_async_reply([], _, Acc) ->
+ lists:keysort(1, Acc);
+pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 ->
+ T1 = inets_test_lib:timestamp(),
+ p("pipeline_await_async_reply -> await replies"
+ "~n ReqIds: ~p"
+ "~n Timeout: ~p", [ReqIds, Timeout]),
+ receive
+ {http, {RequestId, {{_, Status, _}, _, Body}}} ->
+ p("pipeline_await_async_reply -> received reply for"
+ "~n RequestId: ~p"
+ "~n Status: ~p", [RequestId, Status]),
+ case lists:keysearch(RequestId, 1, ReqIds) of
+ {value, {RequestId, N, Status}} ->
+ p("pipeline_await_async_reply -> "
+ "found expected request ~w", [N]),
+ ReqIds2 = lists:keydelete(RequestId, 1, ReqIds),
+ NewTimeout = Timeout - (inets_test_lib:timestamp()-T1),
+ pipeline_await_async_reply(ReqIds2, NewTimeout,
+ [{N, Body} | Acc]);
+ {value, {RequestId, N, WrongStatus}} ->
+ p("pipeline_await_async_reply -> "
+ "found request ~w with wrong status", [N]),
+ tsf({reply_with_unexpected_status,
+ {RequestId, N, WrongStatus}});
+ false ->
+ tsf({unexpected_reply, {RequestId, Status}})
+ end;
+ {http, Msg} ->
+ tsf({unexpected_reply, Msg})
+ after Timeout ->
+ receive
+ Any ->
+ tsp("pipeline_await_async_reply -> "
+ "received unknown data after timeout: "
+ "~n ~p", [Any]),
+ tsf({timeout, {unknown, Any}})
+ end
+ end;
+pipeline_await_async_reply(ReqIds, _, Acc) ->
+ tsp("pipeline_await_async_reply -> "
+ "timeout: "
+ "~n ~p"
+ "~nwhen"
+ "~n ~p", [ReqIds, Acc]),
+ tsf({timeout, ReqIds, Acc}).
+
+
+
%%-------------------------------------------------------------------------
http_trace(doc) ->
["Perform a TRACE request that goes through a proxy."];
@@ -816,14 +927,14 @@ http_trace(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], "TRACE /dummy.html" ++ _}} ->
ok;
{ok, {{_,200,_}, [_ | _], WrongBody}} ->
- test_server:fail({wrong_body, WrongBody});
+ tsf({wrong_body, WrongBody});
{ok, WrongReply} ->
- test_server:fail({wrong_reply, WrongReply});
+ tsf({wrong_reply, WrongReply});
Error ->
- test_server:fail({failed, Error})
+ tsf({failed, Error})
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
http_async(doc) ->
@@ -843,7 +954,7 @@ http_async(Config) when is_list(Config) ->
{http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
BinBody;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
inets_test_lib:check_body(binary_to_list(Body)),
@@ -853,12 +964,12 @@ http_async(Config) when is_list(Config) ->
ok = httpc:cancel_request(NewRequestId),
receive
{http, {NewRequestId, _NewResult}} ->
- test_server:fail(http_cancel_request_failed)
+ tsf(http_cancel_request_failed)
after 3000 ->
ok
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -879,7 +990,7 @@ http_save_to_file(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
Bin == Body;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -902,14 +1013,14 @@ http_save_to_file_async(Config) when is_list(Config) ->
{http, {RequestId, saved_to_file}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
{ok, Bin} = file:read_file(FilePath),
{ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
Bin == Body;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
http_headers(doc) ->
@@ -966,7 +1077,7 @@ http_headers(Config) when is_list(Config) ->
]}, [], []),
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -1101,9 +1212,9 @@ ssl_head(SslTag, Config) ->
{ok, {{_,200, _}, [_ | _], []}} =
httpc:request(head, {URL, []}, [{ssl, SSLConfig}], []);
{ok, _} ->
- {skip, "local http-server not started"};
+ skip("local http-server not started");
_ ->
- {skip, "SSL not started"}
+ skip("SSL not started")
end.
@@ -1141,13 +1252,24 @@ ssl_get(SslTag, Config) when is_list(Config) ->
"~n URL: ~p"
"~n SslTag: ~p"
"~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} =
- httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []),
- inets_test_lib:check_body(Body);
+ case httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []) of
+ {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} ->
+ inets_test_lib:check_body(Body),
+ ok;
+ {ok, {StatusLine, Headers, _Body}} ->
+ tsp("ssl_get -> unexpected result: "
+ "~n StatusLine: ~p"
+ "~n Headers: ~p", [StatusLine, Headers]),
+ tsf({unexpected_response, StatusLine, Headers});
+ {error, Reason} ->
+ tsp("ssl_get -> request failed: "
+ "~n Reason: ~p", [Reason]),
+ tsf({request_failed, Reason})
+ end;
{ok, _} ->
- {skip, "local http-server not started"};
+ skip("local http-server not started");
_ ->
- {skip, "SSL not started"}
+ skip("SSL not started")
end.
@@ -1196,9 +1318,9 @@ ssl_trace(SslTag, Config) when is_list(Config) ->
tsf({failed, Error})
end;
{ok, _} ->
- {skip, "local http-server not started"};
+ skip("local http-server not started");
_ ->
- {skip, "SSL not started"}
+ skip("SSL not started")
end.
@@ -1213,8 +1335,8 @@ http_redirect(Config) when is_list(Config) ->
"~n Config: ~p", [Config]),
case ?config(local_server, Config) of
ok ->
- tsp("http_redirect -> set ipfamily option to inet"),
- ok = httpc:set_options([{ipfamily, inet}]),
+ %% tsp("http_redirect -> set ipfamily option to inet"),
+ %% ok = httpc:set_options([{ipfamily, inet}]),
tsp("http_redirect -> start dummy server inet"),
{DummyServerPid, Port} = dummy_server(ipv4),
@@ -1317,7 +1439,7 @@ http_redirect(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -1448,13 +1570,13 @@ proxy_options(Config) when is_list(Config) ->
{value, {"allow", _}} ->
ok;
_ ->
- test_server:fail(http_options_request_failed)
+ tsf(http_options_request_failed)
end;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1472,10 +1594,10 @@ proxy_head(Config) when is_list(Config) ->
{ok, {{_,200, _}, [_ | _], []}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1491,10 +1613,10 @@ proxy_get(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], Body = [_ | _]}} ->
inets_test_lib:check_body(Body);
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
%%-------------------------------------------------------------------------
@@ -1535,12 +1657,13 @@ proxy_emulate_lower_versions(Config) when is_list(Config) ->
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
pelv_get(Version) ->
httpc:request(get, {?PROXY_URL, []}, [{version, Version}], []).
+
%%-------------------------------------------------------------------------
proxy_trace(doc) ->
["Perform a TRACE request that goes through a proxy."];
@@ -1549,8 +1672,8 @@ proxy_trace(suite) ->
proxy_trace(Config) when is_list(Config) ->
%%{ok, {{_,200,_}, [_ | _], "TRACE " ++ _}} =
%% httpc:request(trace, {?PROXY_URL, []}, [], []),
- {skip, "HTTP TRACE is no longer allowed on the ?PROXY_URL server due "
- "to security reasons"}.
+ skip("HTTP TRACE is no longer allowed on the ?PROXY_URL server due "
+ "to security reasons").
%%-------------------------------------------------------------------------
@@ -1570,10 +1693,10 @@ proxy_post(Config) when is_list(Config) ->
{ok, {{_,405,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1595,10 +1718,10 @@ proxy_put(Config) when is_list(Config) ->
{ok, {{_,405,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1620,10 +1743,10 @@ proxy_delete(Config) when is_list(Config) ->
{ok, {{_,404,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1657,9 +1780,10 @@ proxy_headers(Config) when is_list(Config) ->
]}, [], []),
ok;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
+
%%-------------------------------------------------------------------------
proxy_auth(doc) ->
["Test the code for sending of proxy authorization."];
@@ -1676,10 +1800,10 @@ proxy_auth(Config) when is_list(Config) ->
{ok, {{_,200, _}, [_ | _], [_|_]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1723,7 +1847,7 @@ proxy_page_does_not_exist(Config) when is_list(Config) ->
httpc:request(get, {URL, []}, [], []),
ok;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1742,6 +1866,7 @@ proxy_https_not_supported(Config) when is_list(Config) ->
tsf({unexpected_reason, Result})
end.
+
%%-------------------------------------------------------------------------
http_stream(doc) ->
@@ -1762,7 +1887,7 @@ http_stream(Config) when is_list(Config) ->
{http, {RequestId, stream_start, _Headers}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
StreamedBody = receive_streamed_body(RequestId, <<>>),
@@ -1771,6 +1896,7 @@ http_stream(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+
http_stream_once(doc) ->
["Test the option stream for asynchrony requests"];
http_stream_once(suite) ->
@@ -1778,12 +1904,12 @@ http_stream_once(suite) ->
http_stream_once(Config) when is_list(Config) ->
p("http_stream_once -> entry with"
"~n Config: ~p", [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(ipv4),
-
+
PortStr = integer_to_list(Port),
p("http_stream_once -> once", []),
once(?URL_START ++ PortStr ++ "/once.html"),
@@ -1791,14 +1917,14 @@ http_stream_once(Config) when is_list(Config) ->
once(?URL_START ++ PortStr ++ "/once_chunked.html"),
p("http_stream_once -> dummy", []),
once(?URL_START ++ PortStr ++ "/dummy.html"),
-
+
p("http_stream_once -> stop dummy server", []),
DummyServerPid ! stop,
p("http_stream_once -> set ipfamily to inet6fb4", []),
ok = httpc:set_options([{ipfamily, inet6fb4}]),
p("http_stream_once -> done", []),
ok.
-
+
once(URL) ->
p("once -> issue sync request for ~p", [URL]),
{ok, {{_,200,_}, [_ | _], Body}} =
@@ -1817,7 +1943,7 @@ once(URL) ->
[RequestId, Pid]),
Pid;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
tsp("once -> request handler: ~p", [NewPid]),
@@ -1860,14 +1986,14 @@ proxy_stream(Config) when is_list(Config) ->
{http, {RequestId, stream_start, _Headers}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
StreamedBody = receive_streamed_body(RequestId, <<>>),
Body == binary_to_list(StreamedBody);
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1878,42 +2004,53 @@ parse_url(suite) ->
[];
parse_url(Config) when is_list(Config) ->
%% ipv6
- {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}
- = http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, true}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, false}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{foo, false}]),
{error,
- {malformed_url,"http://2010:836B:4179::836B:4179/foobar.html"}} =
+ {malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
%% ipv4
- {http,[],"127.0.0.1",80,"/foobar.html",[]} =
+ {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
http_uri:parse("http://127.0.0.1/foobar.html"),
%% host
- {http,[],"localhost",8888,"/foobar.html",[]} =
+ {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
http_uri:parse("http://localhost:8888/foobar.html"),
%% Userinfo
- {http,"nisse:foobar","localhost",8888,"/foobar.html",[]} =
+ {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
%% Scheme error
- {error,no_scheme} = http_uri:parse("localhost/foobar.html"),
- {error,{not_supported_scheme,localhost}} =
+ {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
+ {error, {malformed_url, _, _}} =
http_uri:parse("localhost:8888/foobar.html"),
%% Query
- {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"} =
+ {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
%% Esc chars
- {http,[],"www.somedomain.com",80,"/%2Eabc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
http_uri:parse("http://www.somedomain.com/%2Eabc"),
- {http,[],"www.somedomain.com",80,"/%252Eabc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
http_uri:parse("http://www.somedomain.com/%252Eabc"),
- {http,[],"www.somedomain.com",80,"/%25abc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
http_uri:parse("http://www.somedomain.com/%25abc"),
- {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"} =
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
+
+
ok.
@@ -1959,7 +2096,7 @@ ipv6_essl(Config) when is_list(Config) ->
ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
%% Check if we are a IPv6 host
- tsp("ipv6 -> verify ipv6 support", []),
+ tsp("ipv6 -> verify ipv6 support"),
case inets_test_lib:has_ipv6_support(Config) of
{ok, Addr} ->
tsp("ipv6 -> ipv6 supported: ~p", [Addr]),
@@ -1990,12 +2127,13 @@ ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
end,
ok;
_ ->
- tsp("ipv6 -> ipv6 not supported", []),
- {skip, "Host does not support IPv6"}
+ tsp("ipv6 -> ipv6 not supported"),
+ skip("Host does not support IPv6")
end.
%%-------------------------------------------------------------------------
+
headers_as_is(doc) ->
["Test the option headers_as_is"];
headers_as_is(suite) ->
@@ -2013,6 +2151,321 @@ headers_as_is(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+
+selecting_session(doc) ->
+ ["Test selection of sessions - OTP-9847"];
+selecting_session(suite) ->
+ [];
+selecting_session(Config) when is_list(Config) ->
+ tsp("selecting_session -> entry with"
+ "~n Config: ~p", [Config]),
+
+ tsp("selecting_session -> set ipfamily to inet"),
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ tsp("selecting_session -> start server"),
+ {ServerPid, Port} = otp_9847_server(),
+
+ PortStr = integer_to_list(Port),
+ URL = ?URL_START ++ PortStr ++ "/index.html",
+
+ tsp("selecting_session -> issue the first batch (three) requests"),
+ lists:foreach(fun(P) ->
+ tsp("selecting_session:fun1 -> "
+ "send stop request to ~p", [P]),
+ P ! stop
+ end,
+ reqs(URL, ServerPid, 3, 3, false)),
+ tsp("selecting_session -> sleep some (1) to make sure nothing lingers"),
+ ?SLEEP(5000),
+ tsp("selecting_session -> "
+ "instruct the server to reply to the first request"),
+ ServerPid ! {answer, true},
+ receive
+ {answer, true} ->
+ tsp("selecting_session -> "
+ "received ack from server to reply to the first request"),
+ ok
+ end,
+ tsp("selecting_session -> issue the second batch (four) requests"),
+ lists:foreach(fun(P) ->
+ tsp("selecting_session:fun2 -> "
+ "send stop request to ~p", [P]),
+ P ! stop
+ end,
+ reqs(URL, ServerPid, 4, 1, true)),
+ tsp("selecting_session -> sleep some (2) to make sure nothing lingers"),
+ ?SLEEP(5000),
+
+ tsp("selecting_session -> stop server"),
+ ServerPid ! stop,
+ tsp("selecting_session -> set ipfamily (back) to inet6fb4"),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("selecting_session -> done"),
+ ok.
+
+reqs(URL, ServerPid, NumReqs, NumHandlers, InitialSync) ->
+ tsp("reqs -> entry with"
+ "~n URL: ~p"
+ "~n ServerPid: ~w"
+ "~n NumReqs: ~w"
+ "~n NumHandlers: ~w"
+ "~n InitialSync: ~w",
+ [URL, ServerPid, NumReqs, NumHandlers, InitialSync]),
+ Handlers = reqs2(URL, NumReqs, [], InitialSync),
+ tsp("reqs -> "
+ "~n Handlers: ~w", [Handlers]),
+ case length(Handlers) of
+ NumHandlers ->
+ tsp("reqs -> "
+ "~n NumHandlers: ~w", [NumHandlers]),
+ ServerPid ! num_handlers,
+ receive
+ {num_handlers, NumHandlers} ->
+ tsp("reqs -> received num_handlers with"
+ "~n NumHandlers: ~w", [NumHandlers]),
+ Handlers;
+ {num_handlers, WrongNumHandlers} ->
+ tsp("reqs -> received num_handlers with"
+ "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
+ exit({wrong_num_handlers1, WrongNumHandlers, NumHandlers})
+ end;
+ WrongNumHandlers ->
+ tsp("reqs -> "
+ "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
+ exit({wrong_num_handlers2, WrongNumHandlers, NumHandlers})
+ end.
+
+
+reqs2(_URL, 0, Acc, _Sync) ->
+ lists:reverse(Acc);
+reqs2(URL, Num, Acc, Sync) ->
+ tsp("reqs2 -> entry with"
+ "~n Num: ~w"
+ "~n Sync: ~w", [Num, Sync]),
+ case httpc:request(get, {URL, []}, [], [{sync, Sync}]) of
+ {ok, _Reply} ->
+ tsp("reqs2 -> successful request: ~p", [_Reply]),
+ receive
+ {handler, Handler, _Manager} ->
+ %% This is when a new handler is created
+ tsp("reqs2 -> received handler: ~p", [Handler]),
+ case lists:member(Handler, Acc) of
+ true ->
+ tsp("reqs2 -> duplicate handler"),
+ exit({duplicate_handler, Handler, Num, Acc});
+ false ->
+ tsp("reqs2 -> wait for data ack"),
+ receive
+ {data_received, Handler} ->
+ tsp("reqs2 -> "
+ "received data ack from ~p", [Handler]),
+ case Sync of
+ true ->
+ reqs2(URL, Num-1, [Handler|Acc],
+ false);
+ false ->
+ reqs2(URL, Num-1, [Handler|Acc],
+ Sync)
+ end
+ end
+ end;
+
+ {data_received, Handler} ->
+ tsp("reqs2 -> "
+ "received data ack from ~p", [Handler]),
+ reqs2(URL, Num-1, Acc, false)
+
+ end;
+
+ {error, Reason} ->
+ tsp("reqs2 -> request ~w failed: ~p", [Num, Reason]),
+ exit({request_failed, Reason, Num, Acc})
+ end.
+
+otp_9847_server() ->
+ TC = self(),
+ Pid = spawn_link(fun() -> otp_9847_server_init(TC) end),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+otp_9847_server_init(TC) ->
+ tsp("otp_9847_server_init -> entry with"
+ "~n TC: ~p", [TC]),
+ {ok, ListenSocket} =
+ gen_tcp:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}]),
+ tsp("otp_9847_server_init -> listen socket created: "
+ "~n ListenSocket: ~p", [ListenSocket]),
+ {ok, Port} = inet:port(ListenSocket),
+ tsp("otp_9847_server_init -> Port: ~p", [Port]),
+ TC ! {port, Port},
+ otp_9847_server_main(TC, ListenSocket, false, []).
+
+otp_9847_server_main(TC, ListenSocket, Answer, Handlers) ->
+ tsp("otp_9847_server_main -> entry with"
+ "~n TC: ~p"
+ "~n ListenSocket: ~p"
+ "~n Answer: ~p"
+ "~n Handlers: ~p", [TC, ListenSocket, Answer, Handlers]),
+ case gen_tcp:accept(ListenSocket, 1000) of
+ {ok, Sock} ->
+ tsp("otp_9847_server_main -> accepted"
+ "~n Sock: ~p", [Sock]),
+ {Handler, Mon, Port} = otp_9847_handler(TC, Sock, Answer),
+ tsp("otp_9847_server_main -> handler ~p created for ~w",
+ [Handler, Port]),
+ gen_tcp:controlling_process(Sock, Handler),
+ tsp("otp_9847_server_main -> control transfer"),
+ Handler ! owner,
+ tsp("otp_9847_server_main -> "
+ "handler ~p informed of owner transfer", [Handler]),
+ TC ! {handler, Handler, self()},
+ tsp("otp_9847_server_main -> "
+ "TC ~p informed of handler ~p", [TC, Handler]),
+ otp_9847_server_main(TC, ListenSocket, Answer,
+ [{Handler, Mon, Sock, Port}|Handlers]);
+
+ {error, timeout} ->
+ tsp("otp_9847_server_main -> timeout"),
+ receive
+ {answer, true} ->
+ tsp("otp_9847_server_main -> received answer request"),
+ TC ! {answer, true},
+ otp_9847_server_main(TC, ListenSocket, true, Handlers);
+
+ {'DOWN', _Mon, process, Pid, _Reason} ->
+ %% Could be one of the handlers
+ tsp("otp_9847_server_main -> received DOWN for ~p", [Pid]),
+ otp_9847_server_main(TC, ListenSocket, Answer,
+ lists:keydelete(Pid, 1, Handlers));
+
+ num_handlers ->
+ tsp("otp_9847_server_main -> "
+ "received request for number of handlers (~w)",
+ [length(Handlers)]),
+ TC ! {num_handlers, length(Handlers)},
+ otp_9847_server_main(TC, ListenSocket, Answer, Handlers);
+
+ stop ->
+ tsp("otp_9847_server_main -> received stop request"),
+ %% Stop all handlers (just in case)
+ Pids = [Handler || {Handler, _, _} <- Handlers],
+ lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
+ exit(normal);
+
+ Any ->
+ tsp("otp_9847_server_main -> received"
+ "~n Any: ~p", [Any]),
+ exit({crap, Any})
+
+ after 0 ->
+ tsp("otp_9847_server_main -> nothing in queue"),
+ otp_9847_server_main(TC, ListenSocket, Answer, Handlers)
+ end;
+
+ Error ->
+ exit(Error)
+ end.
+
+
+otp_9847_handler(TC, Sock, Answer) ->
+ tsp("otp_9847_handler -> entry with"
+ "~n TC: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p", [TC, Sock, Answer]),
+ Self = self(),
+ {Pid, Mon} =
+ spawn_opt(fun() ->
+ otp_9847_handler_init(TC, Self, Sock, Answer)
+ end,
+ [monitor]),
+ receive
+ {port, Port} ->
+ tsp("otp_9847_handler -> received port message (from ~p)"
+ "~n Port: ~p", [Pid, Port]),
+ {Pid, Mon, Port}
+ end.
+
+
+otp_9847_handler_init(TC, Server, Sock, Answer) ->
+ tsp("otp_9847_handler_init -> entry with"
+ "~n TC: ~p"
+ "~n Server: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p", [TC, Server, Sock, Answer]),
+ {ok, Port} = inet:port(Sock),
+ Server ! {port, Port},
+ receive
+ owner ->
+ tsp("otp_9847_handler_init -> "
+ "received owner message - activate socket"),
+ inet:setopts(Sock, [{active, true}]),
+ otp_9847_handler_main(TC, Server, Sock, Answer, [?HTTP_MAX_HEADER_SIZE])
+ end.
+
+otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs) ->
+ tsp("otp_9847_handler_main -> entry with"
+ "~n TC: ~p"
+ "~n Server: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p"
+ "~n ParseArgs: ~p", [TC, Server, Sock, Answer, ParseArgs]),
+ receive
+ stop ->
+ tsp("otp_9847_handler_main -> received stop request"),
+ exit(normal);
+
+ {tcp, Sock, _Data} when Answer =:= false ->
+ tsp("otp_9847_handler_main -> received tcp data - no answer"),
+ TC ! {data_received, self()},
+ inet:setopts(Sock, [{active, true}]),
+ %% Ignore all data
+ otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs);
+
+ {tcp, Sock, Data} when Answer =:= true ->
+ tsp("otp_9847_handler_main -> received tcp data - answer"),
+ TC ! {data_received, self()},
+ inet:setopts(Sock, [{active, true}]),
+ NewParseArgs = otp_9847_handler_request(Sock, [Data|ParseArgs]),
+ otp_9847_handler_main(TC, Server, Sock, Answer, NewParseArgs);
+
+ {tcp_closed, Sock} ->
+ tsp("otp_9847_handler_main -> received tcp socket closed"),
+ exit(normal);
+
+ {tcp_error, Sock, Reason} ->
+ tsp("otp_9847_handler_main -> socket error: ~p", [Reason]),
+ (catch gen_tcp:close(Sock)),
+ exit(normal)
+
+ %% after 30000 ->
+ %% gen_tcp:close(Sock),
+ %% exit(normal)
+ end.
+
+otp_9847_handler_request(Sock, Args) ->
+ Msg =
+ case httpd_request:parse(Args) of
+ {ok, {_, "/index.html" = _RelUrl, _, _, _}} ->
+ B =
+ "<HTML><BODY>" ++
+ "...some body part..." ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
+ end,
+ gen_tcp:send(Sock, Msg),
+ [?HTTP_MAX_HEADER_SIZE].
+
+
+
+%%-------------------------------------------------------------------------
+
options(doc) ->
["Test the option parameters."];
options(suite) ->
@@ -2032,11 +2485,12 @@ options(Config) when is_list(Config) ->
= httpc:request(get, {URL, []}, [{timeout, infinity}],
[{full_result, false}]);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
+
http_invalid_http(doc) ->
["Test parse error"];
http_invalid_http(suite) ->
@@ -2058,12 +2512,14 @@ http_invalid_http(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+-define(GOOGLE, "www.google.com").
+
hexed_query_otp_6191(doc) ->
[];
hexed_query_otp_6191(suite) ->
[];
hexed_query_otp_6191(Config) when is_list(Config) ->
- Google = "www.google.com",
+ Google = ?GOOGLE,
GoogleSearch = "http://" ++ Google ++ "/search",
Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
URI1 = GoogleSearch ++ Search1,
@@ -2072,11 +2528,32 @@ hexed_query_otp_6191(Config) when is_list(Config) ->
Search3 = "?hl=en&q=%foo",
URI3 = GoogleSearch ++ Search3,
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI1),
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI2),
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI3),
+ Verify1 =
+ fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
+ (_) -> error
+ end,
+ Verify2 = Verify1,
+ Verify3 = Verify1,
+ verify_uri(URI1, Verify1),
+ verify_uri(URI2, Verify2),
+ verify_uri(URI3, Verify3),
ok.
+verify_uri(URI, Verify) ->
+ case http_uri:parse(URI) of
+ {ok, ParsedURI} ->
+ case Verify(ParsedURI) of
+ ok ->
+ ok;
+ error ->
+ Reason = {unexpected_parse_result, URI, ParsedURI},
+ ERROR = {error, Reason},
+ throw(ERROR)
+ end;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
%%-------------------------------------------------------------------------
@@ -2121,7 +2598,7 @@ proxy_not_modified_otp_6821(Config) when is_list(Config) ->
undefined ->
provocate_not_modified_bug(?PROXY_URL);
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -2523,7 +3000,7 @@ otp_8106_pid(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2543,7 +3020,7 @@ otp_8106_fun(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2563,7 +3040,7 @@ otp_8106_mfa(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2712,7 +3189,7 @@ otp_8352(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2827,6 +3304,7 @@ otp_8739_dummy_server_main(_Parent, ListenSocket) ->
exit(Error)
end.
+
%%-------------------------------------------------------------------------
initial_server_connect(doc) ->
@@ -2906,7 +3384,11 @@ create_config(FileName, ComType, Port, PrivDir, ServerRoot, DocRoot,
" mod_include mod_dir mod_get mod_head"
" mod_log mod_disk_log mod_trace",
+ %% BindAddress = "*|inet", % Force the use of IPv4
+ BindAddress = "*", % This corresponds to using IpFamily inet6fb4
+
HttpConfig = [
+ cline(["BindAddress ", BindAddress]),
cline(["Port ", integer_to_list(Port)]),
cline(["ServerName ", "httpc_test"]),
cline(["SocketType ", atom_to_list(ComType)]),
@@ -2945,7 +3427,7 @@ receive_streamed_body(RequestId, Body) ->
{http, {RequestId, stream_end, _Headers}} ->
Body;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end.
receive_streamed_body(RequestId, Body, Pid) ->
@@ -2959,7 +3441,7 @@ receive_streamed_body(RequestId, Body, Pid) ->
{http, {RequestId, stream_end, _Headers}} ->
Body;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end.
%% Perform a synchronous stop
@@ -3417,7 +3899,7 @@ handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
end.
check_cookie([]) ->
- test_server:fail(no_cookie_header);
+ tsf(no_cookie_header);
check_cookie(["cookie:" ++ _Value | _]) ->
ok;
check_cookie([_Head | Tail]) ->
@@ -3465,6 +3947,34 @@ pick_header(Headers, Name) ->
Val
end.
+
+%% -------------------------------------------------------------------------
+
+simple_request_and_verify(Config,
+ Method, Request, HttpOpts, Opts, VerifyResult)
+ when (is_list(Config) andalso
+ is_atom(Method) andalso
+ is_list(HttpOpts) andalso
+ is_list(Opts) andalso
+ is_function(VerifyResult, 1)) ->
+ tsp("request_and_verify -> entry with"
+ "~n Method: ~p"
+ "~n Request: ~p"
+ "~n HttpOpts: ~p"
+ "~n Opts: ~p", [Method, Request, HttpOpts, Opts]),
+ case ?config(local_server, Config) of
+ ok ->
+ tsp("request_and_verify -> local-server running"),
+ Result = (catch httpc:request(Method, Request, HttpOpts, Opts)),
+ VerifyResult(Result);
+ _ ->
+ tsp("request_and_verify -> local-server *not* running - skip"),
+ hard_skip("Local http-server not running")
+ end.
+
+
+
+
not_implemented_yet() ->
exit(not_implemented_yet).
@@ -3475,9 +3985,9 @@ p(F, A) ->
io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
tsp(F) ->
- tsp(F, []).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
tsf(Reason) ->
test_server:fail(Reason).
@@ -3516,19 +4026,8 @@ dummy_ssl_server_hang_loop(_) ->
ok
end.
+hard_skip(Reason) ->
+ throw(skip(Reason)).
-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.
-
+skip(Reason) ->
+ {skip, Reason}.
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index 2a6110e3ea..07d94ea97a 100644
--- a/lib/inets/test/httpd_1_1.erl
+++ b/lib/inets/test/httpd_1_1.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_1_1).
--author('[email protected]').
-include("test_server.hrl").
-include("test_server_line.hrl").
@@ -159,70 +158,79 @@ if_test(Type, Port, Host, Node, DocRoot)->
calendar:datetime_to_gregorian_seconds(FileInfo#file_info.mtime),
Mod = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec-1)),
-
+ CreatedSec-1)),
+
%% Test that we get the data when the file is modified
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:" ++ Host ++
- "\r\nIf-Modified-Since:" ++
- Mod ++ "\r\n\r\n",
- [{statuscode, 200}]),
- Mod1 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec+100)),
- ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++"\r\nIf-Modified-Since:"
- ++ Mod1 ++"\r\n\r\n",
- [{statuscode, 304}]),
+ "GET / HTTP/1.1\r\nHost:" ++ Host ++
+ "\r\nIf-Modified-Since:" ++
+ Mod ++ "\r\n\r\n",
+ [{statuscode, 200}]),
+ Mod1 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
+ CreatedSec+100)),
+ ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++"\r\nIf-Modified-Since:"
+ ++ Mod1 ++"\r\n\r\n",
+ [{statuscode, 304}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET / HTTP/1.1\r\nHost:" ++ Host ++
+ "\r\nIf-Modified-Since:" ++
+ "AAA[...]AAAA" ++ "\r\n\r\n",
+ [{statuscode, 400}]),
+
+
Mod2 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec+1)),
+ CreatedSec+1)),
%% Control that the If-Unmodified-Header lmits the response
ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++
- "\r\nIf-Unmodified-Since:" ++ Mod2
- ++ "\r\n\r\n",
- [{statuscode, 200}]),
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++
+ "\r\nIf-Unmodified-Since:" ++ Mod2
+ ++ "\r\n\r\n",
+ [{statuscode, 200}]),
Mod3 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime(
- CreatedSec-1)),
+ CreatedSec-1)),
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++
- "\r\nIf-Unmodified-Since:"++ Mod3
- ++"\r\n\r\n",
- [{statuscode, 412}]),
-
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++
+ "\r\nIf-Unmodified-Since:"++ Mod3
+ ++"\r\n\r\n",
+ [{statuscode, 412}]),
+
%% Control that we get the body when the etag match
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:" ++ Host
- ++"\r\n"++
- "If-Match:"++
- httpd_util:create_etag(FileInfo)++
- "\r\n\r\n",
- [{statuscode, 200}]),
+ "GET / HTTP/1.1\r\nHost:" ++ Host
+ ++"\r\n"++
+ "If-Match:"++
+ httpd_util:create_etag(FileInfo)++
+ "\r\n\r\n",
+ [{statuscode, 200}]),
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:" ++
- Host ++ "\r\n"++
- "If-Match:NotEtag\r\n\r\n",
- [{statuscode, 412}]),
+ "GET / HTTP/1.1\r\nHost:" ++
+ Host ++ "\r\n"++
+ "If-Match:NotEtag\r\n\r\n",
+ [{statuscode, 412}]),
%% Control the response when the if-none-match header is there
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++"\r\n"++
- "If-None-Match:NoTaag," ++
- httpd_util:create_etag(FileInfo) ++
- "\r\n\r\n",
- [{statuscode, 304}]),
-
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++"\r\n"++
+ "If-None-Match:NoTaag," ++
+ httpd_util:create_etag(FileInfo) ++
+ "\r\n\r\n",
+ [{statuscode, 304}]),
+
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.1\r\nHost:"
- ++ Host ++ "\r\n"++
- "If-None-Match:NotEtag,"
- "NeihterEtag\r\n\r\n",
- [{statuscode,200}]).
+ "GET / HTTP/1.1\r\nHost:"
+ ++ Host ++ "\r\n"++
+ "If-None-Match:NotEtag,"
+ "NeihterEtag\r\n\r\n",
+ [{statuscode,200}]),
+ ok.
http_trace(Type, Port, Host, Node)->
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index faeed3b5f9..41e4188e5f 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -224,7 +224,8 @@ all() ->
].
groups() ->
- [{ip, [],
+ [
+ {ip, [],
[ip_mod_alias, ip_mod_actions, ip_mod_security,
ip_mod_auth, ip_mod_auth_api, ip_mod_auth_mnesia_api,
ip_mod_htaccess, ip_mod_cgi, ip_mod_esi, ip_mod_get,
@@ -293,6 +294,14 @@ groups() ->
[ticket_5775, ticket_5865, ticket_5913, ticket_6003,
ticket_7304]}].
+
+init_per_group(ipv6 = _GroupName, Config) ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
+ Config;
+ _ ->
+ {skip, "Host does not support IPv6"}
+ end;
init_per_group(_GroupName, Config) ->
Config.
@@ -314,6 +323,8 @@ init_per_suite(Config) ->
"~n Config: ~p"
"~n", [Config]),
+ ?PRINT_SYSTEM_INFO([]),
+
PrivDir = ?config(priv_dir, Config),
SuiteTopDir = filename:join(PrivDir, ?MODULE),
case file:make_dir(SuiteTopDir) of
@@ -325,10 +336,11 @@ init_per_suite(Config) ->
throw({error, {failed_creating_suite_top_dir, Error}})
end,
- [{suite_top_dir, SuiteTopDir},
- {node, node()},
- {host, inets_test_lib:hostname()},
- {address, getaddr()} | Config].
+ [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
+ {suite_top_dir, SuiteTopDir},
+ {node, node()},
+ {host, inets_test_lib:hostname()},
+ {address, getaddr()} | Config].
%%--------------------------------------------------------------------
@@ -363,10 +375,9 @@ init_per_testcase(Case, Config) ->
init_per_testcase2(Case, Config) ->
- io:format(user, "~w:init_per_testcase2(~w) -> entry with"
- "~n Config: ~p"
- "~n", [?MODULE, Case, Config]),
-
+ tsp("init_per_testcase2 -> entry with"
+ "~n Config: ~p", [Config]),
+
IpNormal = integer_to_list(?IP_PORT) ++ ".conf",
IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf",
SslNormal = integer_to_list(?SSL_PORT) ++ ".conf",
@@ -375,39 +386,33 @@ init_per_testcase2(Case, Config) ->
DataDir = ?config(data_dir, Config),
SuiteTopDir = ?config(suite_top_dir, Config),
- io:format(user, "~w:init_per_testcase2(~w) -> "
- "~n SuiteDir: ~p"
- "~n DataDir: ~p"
- "~n", [?MODULE, Case, SuiteTopDir, DataDir]),
+ tsp("init_per_testcase2 -> "
+ "~n SuiteDir: ~p"
+ "~n DataDir: ~p", [SuiteTopDir, DataDir]),
TcTopDir = filename:join(SuiteTopDir, Case),
?line ok = file:make_dir(TcTopDir),
- io:format(user, "~w:init_per_testcase2(~w) -> "
- "~n TcTopDir: ~p"
- "~n", [?MODULE, Case, TcTopDir]),
+ tsp("init_per_testcase2 -> "
+ "~n TcTopDir: ~p", [TcTopDir]),
DataSrc = filename:join([DataDir, "server_root"]),
ServerRoot = filename:join([TcTopDir, "server_root"]),
- io:format(user, "~w:init_per_testcase2(~w) -> "
- "~n DataSrc: ~p"
- "~n ServerRoot: ~p"
- "~n", [?MODULE, Case, DataSrc, ServerRoot]),
+ tsp("init_per_testcase2 -> "
+ "~n DataSrc: ~p"
+ "~n ServerRoot: ~p", [DataSrc, ServerRoot]),
ok = file:make_dir(ServerRoot),
ok = file:make_dir(filename:join([TcTopDir, "logs"])),
NewConfig = [{tc_top_dir, TcTopDir}, {server_root, ServerRoot} | Config],
- io:format(user, "~w:init_per_testcase2(~w) -> "
- "copy DataSrc to ServerRoot~n",
- [?MODULE, Case]),
+ tsp("init_per_testcase2 -> copy DataSrc to ServerRoot"),
inets_test_lib:copy_dirs(DataSrc, ServerRoot),
- io:format(user, "~w:init_per_testcase2(~w) -> fix cgi~n",
- [?MODULE, Case]),
+ tsp("init_per_testcase2 -> fix cgi"),
EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]),
{ok, FileInfo} = file:read_file_info(EnvCGI),
ok = file:write_file_info(EnvCGI,
@@ -427,16 +432,14 @@ init_per_testcase2(Case, Config) ->
FileInfo1#file_info{mode = 8#00755}),
%% To be used by IP test cases
- io:format(user, "~w:init_per_testcase2(~w) -> ip testcase setups~n",
- [?MODULE, Case]),
+ tsp("init_per_testcase2 -> ip testcase setups"),
create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
normal_access, IpNormal),
create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
mod_htaccess, IpHtaccess),
%% To be used by SSL test cases
- io:format(user, "~w:init_per_testcase2(~w) -> ssl testcase setups~n",
- [?MODULE, Case]),
+ tsp("init_per_testcase2 -> ssl testcase setups"),
SocketType =
case atom_to_list(Case) of
[X, $s, $s, $l | _] ->
@@ -460,8 +463,7 @@ init_per_testcase2(Case, Config) ->
%% when you run the whole test suite due to shortcomings
%% of the test server.
- io:format(user, "~w:init_per_testcase2(~w) -> "
- "maybe generate IPv6 config file(s)", [?MODULE, Case]),
+ tsp("init_per_testcase2 -> maybe generate IPv6 config file(s)"),
NewConfig2 =
case atom_to_list(Case) of
"ipv6_" ++ _ ->
@@ -497,19 +499,20 @@ init_per_testcase2(Case, Config) ->
_ ->
NewConfig
end;
+
_ ->
NewConfig
end,
- io:format(user, "~w:init_per_testcase2(~w) -> done~n",
- [?MODULE, Case]),
+ tsp("init_per_testcase2 -> done when"
+ "~n NewConfig2: ~p", [NewConfig2]),
NewConfig2.
init_per_testcase3(Case, Config) ->
- io:format(user, "~w:init_per_testcase3(~w) -> entry with"
- "~n Config: ~p", [?MODULE, Case, Config]),
+ tsp("init_per_testcase3(~w) -> entry with"
+ "~n Config: ~p", [Case, Config]),
%% %% Create a new fresh node to be used by the server in this test-case
@@ -528,15 +531,13 @@ init_per_testcase3(Case, Config) ->
application:stop(ssl),
cleanup_mnesia(),
- %% Set trace
+ %% Set trace level
case lists:reverse(atom_to_list(Case)) of
"tset_emit" ++ _Rest -> % test-cases ending with time_test
- io:format(user, "~w:init_per_testcase3(~w) -> disabling trace",
- [?MODULE, Case]),
+ tsp("init_per_testcase3(~w) -> disabling trace", [Case]),
inets:disable_trace();
_ ->
- io:format(user, "~w:init_per_testcase3(~w) -> enabling trace",
- [?MODULE, Case]),
+ tsp("init_per_testcase3(~w) -> enabling trace", [Case]),
%% TraceLevel = 70,
TraceLevel = max,
TraceDest = io,
@@ -544,8 +545,7 @@ init_per_testcase3(Case, Config) ->
end,
%% Start initialization
- io:format(user, "~w:init_per_testcase3(~w) -> start init",
- [?MODULE, Case]),
+ tsp("init_per_testcase3(~w) -> start init", [Case]),
Dog = test_server:timetrap(inets_test_lib:minutes(10)),
@@ -581,9 +581,10 @@ init_per_testcase3(Case, Config) ->
Rest;
[X, $s, $s, $l, $_, $m, $o, $d, $_, $h, $t, $a, $c, $c, $e, $s, $s] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
SslTag =
case X of
- $p -> ssl; % plain
+ $p -> ssl; % Plain
$e -> essl % Erlang based ssl
end,
case inets_test_lib:start_http_server_ssl(
@@ -597,6 +598,7 @@ init_per_testcase3(Case, Config) ->
{skip, "SSL does not seem to be supported"}
end;
[X, $s, $s, $l, $_ | Rest] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
SslTag =
case X of
$p -> ssl;
@@ -624,26 +626,32 @@ init_per_testcase3(Case, Config) ->
end
end,
- case CaseRest of
- {skip, _} = Skip ->
- Skip;
- "mod_auth_" ++ _ ->
- start_mnesia(?config(node, Config)),
- [{watchdog, Dog} | NewConfig];
- "mod_htaccess" ->
- ServerRoot = ?config(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- catch remove_htaccess(Path),
- create_htaccess_data(Path, ?config(address, Config)),
- [{watchdog, Dog} | NewConfig];
- "range" ->
- ServerRoot = ?config(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- create_range_data(Path),
- [{watchdog, Dog} | NewConfig];
- _ ->
- [{watchdog, Dog} | NewConfig]
- end.
+ InitRes =
+ case CaseRest of
+ {skip, _} = Skip ->
+ Skip;
+ "mod_auth_" ++ _ ->
+ start_mnesia(?config(node, Config)),
+ [{watchdog, Dog} | NewConfig];
+ "mod_htaccess" ->
+ ServerRoot = ?config(server_root, Config),
+ Path = filename:join([ServerRoot, "htdocs"]),
+ catch remove_htaccess(Path),
+ create_htaccess_data(Path, ?config(address, Config)),
+ [{watchdog, Dog} | NewConfig];
+ "range" ->
+ ServerRoot = ?config(server_root, Config),
+ Path = filename:join([ServerRoot, "htdocs"]),
+ create_range_data(Path),
+ [{watchdog, Dog} | NewConfig];
+ _ ->
+ [{watchdog, Dog} | NewConfig]
+ end,
+
+ tsp("init_per_testcase3(~w) -> done when"
+ "~n InitRes: ~p", [Case, InitRes]),
+
+ InitRes.
%%--------------------------------------------------------------------
@@ -661,16 +669,14 @@ end_per_testcase(Case, Config) ->
ok.
end_per_testcase2(Case, Config) ->
- io:format(user, "~w:end_per_testcase2(~w) -> entry with"
- "~n Config: ~p~n",
- [?MODULE, Case, Config]),
+ tsp("end_per_testcase2(~w) -> entry with"
+ "~n Config: ~p", [Case, Config]),
application:unset_env(inets, services),
application:stop(inets),
application:stop(ssl),
application:stop(crypto), % used by the new ssl (essl test cases)
cleanup_mnesia(),
- io:format(user, "~w:end_per_testcase2(~w) -> done~n",
- [?MODULE, Case]),
+ tsp("end_per_testcase2(~w) -> done", [Case]),
ok.
@@ -679,23 +685,6 @@ end_per_testcase2(Case, Config) ->
%%-------------------------------------------------------------------------
%%-------------------------------------------------------------------------
-
-
-
-
-
-
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
ip_mod_alias(doc) ->
["Module test: mod_alias"];
ip_mod_alias(suite) ->
@@ -704,6 +693,7 @@ ip_mod_alias(Config) when is_list(Config) ->
httpd_mod:alias(ip_comm, ?IP_PORT,
?config(host, Config), ?config(node, Config)),
ok.
+
%%-------------------------------------------------------------------------
ip_mod_actions(doc) ->
["Module test: mod_actions"];
@@ -713,6 +703,7 @@ ip_mod_actions(Config) when is_list(Config) ->
httpd_mod:actions(ip_comm, ?IP_PORT,
?config(host, Config), ?config(node, Config)),
ok.
+
%%-------------------------------------------------------------------------
ip_mod_security(doc) ->
["Module test: mod_security"];
@@ -2239,6 +2230,7 @@ ticket_5865(doc) ->
ticket_5865(suite) ->
[];
ticket_5865(Config) ->
+ ?SKIP(as_of_r15_behaviour_of_calendar_has_changed),
Host = ?config(host,Config),
ServerRoot = ?config(server_root, Config),
DocRoot = filename:join([ServerRoot, "htdocs"]),
@@ -2276,24 +2268,24 @@ ticket_5913(doc) ->
["Tests that a header without last-modified is handled"];
ticket_5913(suite) -> [];
ticket_5913(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
"GET /cgi-bin/erl/httpd_example:get_bin "
"HTTP/1.0\r\n\r\n",
[{statuscode, 200},
- {version, "HTTP/1.0"}]),
+ {version, "HTTP/1.0"}]),
ok.
ticket_6003(doc) ->
["Tests that a URI with a bad hexadecimal code is handled"];
ticket_6003(suite) -> [];
ticket_6003(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
- "GET http://www.erlang.org/%skalle "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 400},
- {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
+ "GET http://www.erlang.org/%skalle "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 400},
+ {version, "HTTP/1.0"}]),
ok.
ticket_7304(doc) ->
@@ -2365,32 +2357,33 @@ create_config(Config, Access, FileName) ->
true ->
[]
end,
- ModOrder = case Access of
- mod_htaccess ->
- "Modules mod_alias mod_htaccess mod_auth "
- "mod_security "
- "mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_include mod_dir "
- "mod_range mod_get "
- "mod_head mod_log mod_disk_log";
- _ ->
- "Modules mod_alias mod_auth mod_security "
- "mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_include mod_dir "
+ ModOrder =
+ case Access of
+ mod_htaccess ->
+ "Modules mod_alias mod_htaccess mod_auth "
+ "mod_security "
+ "mod_responsecontrol mod_trace mod_esi "
+ "mod_actions mod_cgi mod_include mod_dir "
+ "mod_range mod_get "
+ "mod_head mod_log mod_disk_log";
+ _ ->
+ "Modules mod_alias mod_auth mod_security "
+ "mod_responsecontrol mod_trace mod_esi "
+ "mod_actions mod_cgi mod_include mod_dir "
"mod_range mod_get "
- "mod_head mod_log mod_disk_log"
- end,
+ "mod_head mod_log mod_disk_log"
+ end,
-%% The test suite currently does not handle an explicit BindAddress.
-%% They assume any has been used, that is Addr is always set to undefined!
+ %% The test suite currently does not handle an explicit BindAddress.
+ %% They assume any has been used, that is Addr is always set to undefined!
-%% {ok, Hostname} = inet:gethostname(),
-%% {ok, Addr} = inet:getaddr(Hostname, inet6),
-%% AddrStr = make_ipv6(Addr),
-%% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])),
+ %% {ok, Hostname} = inet:gethostname(),
+ %% {ok, Addr} = inet:getaddr(Hostname, inet6),
+ %% AddrStr = make_ipv6(Addr),
+ %% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])),
- %% BindAddress = "*|inet",
- BindAddress = "*",
+ BindAddress = "*|inet",
+ %% BindAddress = "*",
HttpConfig = [
cline(["Port ", integer_to_list(Port)]),
@@ -2781,10 +2774,10 @@ create_ipv6_config(Config, FileName, Ipv6Address) ->
ok = file:close(Fd).
-%% tsp(F) ->
-%% inets_test_lib:tsp(F).
+tsp(F) ->
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
tsp(F, A) ->
- inets_test_lib:tsp(F, A).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
tsf(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 f23d0b4765..7a476ea14a 100644
--- a/lib/inets/test/httpd_basic_SUITE.erl
+++ b/lib/inets/test/httpd_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,6 +20,8 @@
-module(httpd_basic_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include("inets_test_lib.hrl").
+
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -59,9 +61,28 @@ init_per_suite(Config) ->
"~n Config: ~p", [Config]),
ok = inets:start(),
PrivDir = ?config(priv_dir, Config),
- HttpdConf = [{port, 0}, {ipfamily, inet},
- {server_name, "httpd_test"}, {server_root, PrivDir},
- {document_root, PrivDir}, {bind_address, "localhost"}],
+
+ Dummy =
+"<HTML>
+<HEAD>
+<TITLE>/index.html</TITLE>
+</HEAD>
+<BODY>
+DUMMY
+</BODY>
+</HTML>",
+
+ DummyFile = filename:join([PrivDir,"dummy.html"]),
+ {ok, Fd} = file:open(DummyFile, [write]),
+ ok = file:write(Fd, Dummy),
+ ok = file:close(Fd),
+ HttpdConf = [{port, 0},
+ {ipfamily, inet},
+ {server_name, "httpd_test"},
+ {server_root, PrivDir},
+ {document_root, PrivDir},
+ {bind_address, "localhost"}],
+
[{httpd_conf, HttpdConf} | Config].
%%--------------------------------------------------------------------
@@ -133,6 +154,10 @@ uri_too_long_414(Config) when is_list(Config) ->
{version, "HTTP/0.9"}]),
inets:stop(httpd, Pid).
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
header_too_long_413(doc) ->
["Test that too long headers's get 413 HTTP code"];
header_too_long_413(suite) ->
@@ -152,34 +177,106 @@ header_too_long_413(Config) when is_list(Config) ->
{version, "HTTP/1.1"}]),
inets:stop(httpd, Pid).
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
escaped_url_in_error_body(doc) ->
["Test Url-encoding see OTP-8940"];
escaped_url_in_error_body(suite) ->
[];
escaped_url_in_error_body(Config) when is_list(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>",
- URL = ?URL_START ++ integer_to_list(Port) ++ Path,
- EscapedPath = http_uri:encode(Path),
- {ok, {404, Body1}} = httpc:request(get, {URL, []},
- [{url_encode, true},
- {version, "HTTP/1.0"}],
- [{full_result, false}]),
- EscapedPath = find_URL_path(string:tokens(Body1, " ")),
- {ok, {404, Body2}} = httpc:request(get, {URL, []},
- [{url_encode, false},
- {version, "HTTP/1.0"}],
- [{full_result, false}]),
+ %% <CONDITIONAL-SKIP>
+ %% This skip is due to a problem on windows with long path's
+ %% If a path is too long file:open fails with, for example, eio.
+ %% Until that problem is fixed, we skip this case...
+ Skippable = [win32],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ tsp("escaped_url_in_error_body -> entry"),
+ 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),
+
+ %% Request 1
+ tss(1000),
+ tsp("escaped_url_in_error_body -> request 1"),
+ URL1 = ?URL_START ++ integer_to_list(Port),
+ %% Make sure the server is ok, by making a request for a valid page
+ case httpc:request(get, {URL1 ++ "/dummy.html", []},
+ [{url_encode, false},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {200, _}} ->
+ %% Don't care about the the body, just that we get a ok response
+ ok;
+ {ok, {StatusCode1, Body1}} ->
+ tsf({unexpected_ok_1, StatusCode1, Body1})
+ end,
+
+ %% Request 2
+ tss(1000),
+ tsp("escaped_url_in_error_body -> request 2"),
+ %% Make sure the server is ok, by making a request for a valid page
+ case httpc:request(get, {URL1 ++ "/dummy.html", []},
+ [{url_encode, true},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {200, _}} ->
+ %% Don't care about the the body, just that we get a ok response
+ ok;
+ {ok, {StatusCode2, Body2}} ->
+ tsf({unexpected_ok_2, StatusCode2, Body2})
+ end,
+
+ %% Request 3
+ tss(1000),
+ tsp("escaped_url_in_error_body -> request 3"),
+ %% Ask for a non-existing page(1)
+ Path = "/<b>this_is_bold<b>",
HTMLEncodedPath = http_util:html_encode(Path),
- HTMLEncodedPath = find_URL_path(string:tokens(Body2, " ")),
+ URL2 = URL1 ++ Path,
+ case httpc:request(get, {URL2, []},
+ [{url_encode, true},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {404, Body3}} ->
+ case find_URL_path(string:tokens(Body3, " ")) of
+ HTMLEncodedPath ->
+ ok;
+ BadPath3 ->
+ tsf({unexpected_path_3, HTMLEncodedPath, BadPath3})
+ end;
+ {ok, UnexpectedOK3} ->
+ tsf({unexpected_ok_3, UnexpectedOK3})
+ end,
+
+ %% Request 4
+ tss(1000),
+ tsp("escaped_url_in_error_body -> request 4"),
+ %% Ask for a non-existing page(2)
+ case httpc:request(get, {URL2, []},
+ [{url_encode, false},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {404, Body4}} ->
+ case find_URL_path(string:tokens(Body4, " ")) of
+ HTMLEncodedPath ->
+ ok;
+ BadPath4 ->
+ tsf({unexpected_path_4, HTMLEncodedPath, BadPath4})
+ end;
+ {ok, UnexpectedOK4} ->
+ tsf({unexpected_ok_4, UnexpectedOK4})
+ end,
+ tss(1000),
+ tsp("escaped_url_in_error_body -> stop inets"),
inets:stop(httpd, Pid),
- tsp("escaped_url_in_error_body -> done"),
+ tsp("escaped_url_in_error_body -> done"),
ok.
find_URL_path([]) ->
@@ -191,7 +288,19 @@ find_URL_path([_ | Rest]) ->
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).
+
+tss(Time) ->
+ inets_test_lib:tss(Time).
+
+
+
+
+skip(Reason) ->
+ {skip, Reason}.
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index 1754cec7bc..387263ce58 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -39,14 +39,10 @@
%% Test cases starts here.
%%-------------------------------------------------------------------------
alias(Type, Port, Host, Node) ->
-%% io:format(user, "~w:alias -> entry with"
-%% "~n Type: ~p"
-%% "~n Port: ~p"
-%% "~n Host: ~p"
-%% "~n Node: ~p"
-%% "~n", [?MODULE, Type, Port, Host, Node]),
-
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ %% This is very crude, but...
+ tsp("alias -> Has IPv6 support: ~p", [inets_test_lib:has_ipv6_support()]),
+ Opts = [],
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
"GET /pics/icon.sheet.gif "
"HTTP/1.0\r\n\r\n",
[{statuscode, 200},
@@ -55,7 +51,7 @@ alias(Type, Port, Host, Node) ->
{header, "Date"},
{version, "HTTP/1.0"}]),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
"GET / HTTP/1.0\r\n\r\n",
[{statuscode, 200},
{header, "Content-Type","text/html"},
@@ -63,7 +59,7 @@ alias(Type, Port, Host, Node) ->
{header, "Date"},
{version, "HTTP/1.0"}]),
- ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
"GET /misc/ HTTP/1.0\r\n\r\n",
[{statuscode, 200},
{header, "Content-Type","text/html"},
@@ -71,8 +67,8 @@ alias(Type, Port, Host, Node) ->
{header, "Date"},
{version, "HTTP/1.0"}]),
- %% Check redirection if trailing slash is missing.
- ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
+ %% Check redirection if trailing slash is missing.
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
"GET /misc HTTP/1.0\r\n\r\n",
[{statuscode, 301},
{header, "Location"},
@@ -86,19 +82,23 @@ actions(Type, Port, Host, Node) ->
[{statuscode, 200},
{version, "HTTP/1.0"}]).
+
%%-------------------------------------------------------------------------
security(ServerRoot, Type, Port, Host, Node) ->
-%% io:format(user, "~w:security -> entry with"
-%% "~n ServerRoot: ~p"
-%% "~n Type: ~p"
-%% "~n Port: ~p"
-%% "~n Host: ~p"
-%% "~n Node: ~p"
-%% "~n", [?MODULE, ServerRoot, Type, Port, Host, Node]),
-
-%% io:format(user, "~w:security -> register~n", [?MODULE]),
+ tsp("security -> "
+ "entry with"
+ "~n ServerRoot: ~p"
+ "~n Type: ~p"
+ "~n Port: ~p"
+ "~n Host: ~p"
+ "~n Node: ~p", [ServerRoot, Type, Port, Host, Node]),
+
+ tsp("security -> "
+ "register - receive security events"),
global:register_name(mod_security_test, self()), % Receive events
+ tsp("security -> "
+ "sleep"),
test_server:sleep(5000),
OpenDir = filename:join([ServerRoot, "htdocs", "open"]),
@@ -106,133 +106,240 @@ security(ServerRoot, Type, Port, Host, Node) ->
%% Test blocking / unblocking of users.
%% /open, require user one Aladdin
-%% io:format(user, "~w:security -> remove user~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "remove all existing users"),
remove_users(Node, ServerRoot, Host, Port, "open"),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request for nonex user 'one' - expect 401"),
auth_request(Type, Host, Port, Node, "/open/", "one", "onePassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "one"}, {password, "onePassword"}]},
Node, Port),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request for nonex user 'two' - expect 401"),
auth_request(Type,Host,Port,Node,"/open/", "two", "twoPassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "two"}, {password, "twoPassword"}]},
Node, Port),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request for nonex user 'Alladin' - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "Aladdin",
"AladdinPassword", [{statuscode, 401}]),
-%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "Aladdin"},
{password, "AladdinPassword"}]},
Node, Port),
-%% io:format(user, "~w:security -> add users~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "add user 'one'"),
add_user(Node, ServerRoot, Port, "open", "one", "onePassword", []),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "add user 'two'"),
add_user(Node, ServerRoot, Port, "open", "two", "twoPassword", []),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request 1 for user 'one' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "one"}, {password, "WrongPassword"}]},
Node, Port),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request 2 for user 'one' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "one"}, {password, "WrongPassword"}]},
Node, Port),
-%% io:format(user, "~w:security -> await block security event~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "await block security event (two failed attempts)"),
receive_security_event({event, user_block, Port, OpenDir,
[{user, "one"}]}, Node, Port),
-%% io:format(user, "~w:security -> unregister~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "unregister - no more security events"),
global:unregister_name(mod_security_test), % No more events.
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request for user 'one' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request for user 'one' with correct password - expect 403"),
auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword",
[{statuscode, 403}]),
%% User "one" should be blocked now..
- %% [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "list blocked users - 'one' should be the only one"),
case list_blocked_users(Node, Port) of
[{"one",_, Port, OpenDir,_}] ->
ok;
Blocked ->
- io:format(user, "~w:security -> Blocked: ~p"
- "~n", [?MODULE, Blocked]),
+ tsp(" *** unexpected blocked users ***"
+ "~n Blocked: ~p", [Blocked]),
exit({unexpected_blocked, Blocked})
end,
-
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
- [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port,OpenDir),
-%% io:format(user, "~w:security -> unblock user~n", [?MODULE]),
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "list users blocked for dir '~p' - "
+ "user 'one' should be the only one", [OpenDir]),
+ [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir),
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "unblock user 'one' for dir '~p'", [OpenDir]),
true = unblock_user(Node, "one", Port, OpenDir),
- %% User "one" should not be blocked any more..
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+ %% User "one" should not be blocked any more.
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "ensure user 'one' is no longer blocked"),
[] = list_blocked_users(Node, Port),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
- [] = list_blocked_users(Node, Port, OpenDir),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+
+
+ tsp("security -> "
+ "blocking and unblocking of users - "
+ "auth request for user 'one' with correct password - expect 200"),
auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword",
[{statuscode, 200}]),
+
+
%% Test list_auth_users & auth_timeout
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users - expect user 'one'"),
["one"] = list_auth_users(Node, Port),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
- ["one"] = list_auth_users(Node, Port, OpenDir),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "auth request for user 'two' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "two", "onePassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users - expect user 'one'"),
["one"] = list_auth_users(Node, Port),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users for dir '~p' - expect user 'one'", [OpenDir]),
["one"] = list_auth_users(Node, Port, OpenDir),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "auth request for user 'two' with correct password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword",
[{statuscode, 401}]),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users - expect user 'one'"),
["one"] = list_auth_users(Node, Port),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users for dir '~p' - expect user 'one'", [OpenDir]),
["one"] = list_auth_users(Node, Port, OpenDir),
+
%% Wait for successful auth to timeout.
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "wait for successful auth to timeout"),
test_server:sleep(?AUTH_TIMEOUT*1001),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users - expect none"),
[] = list_auth_users(Node, Port),
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "list auth users for dir '~p'~n - expect none", [OpenDir]),
[] = list_auth_users(Node, Port, OpenDir),
+
%% "two" is blocked.
-%% io:format(user, "~w:security -> unblock user~n", [?MODULE]),
+
+ tsp("security -> "
+ "list-auth-users and auth-timeout - "
+ "unblock user 'two' for dir '~p'", [OpenDir]),
true = unblock_user(Node, "two", Port, OpenDir),
+
+
%% Test explicit blocking. Block user 'two'.
-%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]),
+
+ tsp("security -> "
+ "explicit blocking - list blocked users - should be none"),
[] = list_blocked_users(Node,Port,OpenDir),
-%% io:format(user, "~w:security -> block user~n", [?MODULE]),
+
+ tsp("security -> "
+ "explicit blocking - "
+ "block user 'two' for dir '~p'", [OpenDir]),
true = block_user(Node, "two", Port, OpenDir, 10),
-%% io:format(user, "~w:security -> auth request~n", [?MODULE]),
+
+ tsp("security -> "
+ "explicit blocking - "
+ "auth request for user 'two' with correct password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword",
- [{statuscode, 401}]).
+ [{statuscode, 401}]),
+ tsp("security -> "
+ "done").
+
%%-------------------------------------------------------------------------
auth(Type, Port, Host, Node) ->
+ tsp("auth -> "
+ "entry with"
+ "~n Type: ~p"
+ "~n Port: ~p"
+ "~n Host: ~p"
+ "~n Node: ~p", [Type, Port, Host, Node]),
+
%% Authentication required!
ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
"GET /open/ HTTP/1.0\r\n\r\n",
@@ -917,13 +1024,11 @@ list_users(Node, Root, _Host, Port, Dir) ->
receive_security_event(Event, Node, Port) ->
-%% io:format(user, "~w:receive_security_event -> entry with"
-%% "~n Event: ~p"
-%% "~n Node: ~p"
-%% "~n Port: ~p"
-%% "~n", [?MODULE, Event, Node, Port]),
+ tsp("receive_security_event -> await ~w event", [element(2, Event)]),
receive
Event ->
+ tsp("receive_security_event -> "
+ "received expected ~w event", [element(2, Event)]),
ok;
{'EXIT', _, _} ->
receive_security_event(Event, Node, Port)
@@ -1031,10 +1136,17 @@ check_lists_members1(L1,L2) ->
{error,{lists_not_equal,L1,L2}}.
-%% tsp(F) ->
-%% tsp(F, []).
-%% tsp(F, A) ->
-%% test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+%% p(F) ->
+%% p(F, []).
+
+%% p(F, A) ->
+%% io:format(user, "~w:" ++ F ++ "~n", [?MODULE|A]).
+
+tsp(F) ->
+ inets_test_lib:tsp(F).
+tsp(F, A) ->
+ inets_test_lib:tsp(F, A).
+
tsf(Reason) ->
test_server:fail(Reason).
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 581461fe03..4b33350cf2 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -79,14 +79,18 @@
%%--------------------------------------------------------------------
%% API
%%------------------------------------------------------------------
+
verify_request(SocketType, Host, Port, Node, RequestStr, Options) ->
verify_request(SocketType, Host, Port, Node, RequestStr, Options, 30000).
+
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"
@@ -97,7 +101,7 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
"~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
+ try 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),
@@ -113,25 +117,37 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
case request(State#state{request = RequestStr,
socket = Socket}, TimeOut) of
{error, Reason} ->
- tsp("request failed: "
+ tsp("verify_request -> request failed: "
"~n Reason: ~p", [Reason]),
{error, Reason};
NewState ->
- tsp("validate reply: "
+ tsp("verify_request -> validate reply: "
"~n NewState: ~p", [NewState]),
ValidateResult =
validate(RequestStr, NewState, Options, Node, Port),
- tsp("validation result: "
+ tsp("verify_request -> validation result: "
"~n ~p", [ValidateResult]),
inets_test_lib:close(SocketType, Socket),
ValidateResult
end;
ConnectError ->
- tsp("verify_request -> connect failed: "
+ tsp("verify_request -> connect error: "
"~n ~p"
"~n", [ConnectError]),
- tsf({connect_failure, ConnectError})
+ tsf({connect_error, ConnectError,
+ [SocketType, Host, Port, TranspOpts]})
+ catch
+ T:E ->
+ tsp("verify_request -> connect failed: "
+ "~n E: ~p"
+ "~n T: ~p"
+ "~n", [E, T]),
+ tsf({connect_failure,
+ [{type, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()},
+ {args, [SocketType, Host, Port, TranspOpts]}]})
end.
request(#state{mfa = {Module, Function, Args},
@@ -140,6 +156,9 @@ request(#state{mfa = {Module, Function, Args},
HeadRequest = lists:sublist(RequestStr, 1, 4),
receive
{tcp, Socket, Data} ->
+ io:format("~p ~w[~w]request -> received (tcp) data"
+ "~n Data: ~p"
+ "~n", [self(), ?MODULE, ?LINE, Data]),
print(tcp, Data, State),
case Module:Function([Data | Args]) of
{ok, Parsed} ->
@@ -150,11 +169,19 @@ request(#state{mfa = {Module, Function, Args},
request(State#state{mfa = NewMFA}, TimeOut)
end;
{tcp_closed, Socket} when Function =:= whole_body ->
+ io:format("~p ~w[~w]request -> "
+ "received (tcp) closed when whole_body"
+ "~n", [self(), ?MODULE, ?LINE]),
print(tcp, "closed", State),
State#state{body = hd(Args)};
{tcp_closed, Socket} ->
+ io:format("~p ~w[~w]request -> received (tcp) closed"
+ "~n", [self(), ?MODULE, ?LINE]),
test_server:fail(connection_closed);
{tcp_error, Socket, Reason} ->
+ io:format("~p ~w[~w]request -> received (tcp) error"
+ "~n Reason: ~p"
+ "~n", [self(), ?MODULE, ?LINE, Reason]),
test_server:fail({tcp_error, Reason});
{ssl, Socket, Data} ->
print(ssl, Data, State),
@@ -174,11 +201,21 @@ request(#state{mfa = {Module, Function, Args},
{ssl_error, Socket, Reason} ->
test_server:fail({ssl_error, Reason})
after TimeOut ->
+ io:format("~p ~w[~w]request -> timeout"
+ "~n", [self(), ?MODULE, ?LINE]),
test_server:fail(connection_timed_out)
end.
handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
State = #state{request = RequestStr}) ->
+ io:format("~p ~w[~w]handle_http_msg -> entry with"
+ "~n Version: ~p"
+ "~n StatusCode: ~p"
+ "~n ReasonPharse: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p"
+ "~n", [self(), ?MODULE, ?LINE,
+ Version, StatusCode, ReasonPharse, Headers, Body]),
case is_expect(RequestStr) of
true ->
State#state{status_line = {Version,
@@ -235,13 +272,14 @@ handle_http_body(Body, State = #state{headers = Headers,
end.
validate(RequestStr, #state{status_line = {Version, StatusCode, _},
- headers = Headers,
- body = Body}, Options, N, P) ->
+ headers = Headers,
+ body = Body}, Options, N, P) ->
- %% tsp("validate -> entry with"
- %% "~n StatusCode: ~p"
- %% "~n Headers: ~p"
- %% "~n Body: ~p", [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, _} ->
@@ -255,6 +293,7 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _},
list_to_integer(Headers#http_response_h.'content-length'),
Body).
+
%%--------------------------------------------------------------------
%% Internal functions
%%------------------------------------------------------------------
@@ -263,21 +302,20 @@ check_version(Version, Options) ->
{value, {version, Version}} ->
ok;
{value, {version, Ver}} ->
- test_server:fail({wrong_version, [{got, Version},
- {expected, Ver}]});
+ tsf({wrong_version, [{got, Version},
+ {expected, Ver}]});
_ ->
case Version of
"HTTP/1.1" ->
ok;
_ ->
- test_server:fail({wrong_version, [{got, Version},
- {expected, "HTTP/1.1"}]})
+ tsf({wrong_version, [{got, Version},
+ {expected, "HTTP/1.1"}]})
end
end.
check_status_code(StatusCode, [], Options) ->
- test_server:fail({wrong_status_code, [{got, StatusCode},
- {expected, Options}]});
+ tsf({wrong_status_code, [{got, StatusCode}, {expected, Options}]});
check_status_code(StatusCode, Current = [_ | Rest], Options) ->
case lists:keysearch(statuscode, 1, Current) of
{value, {statuscode, StatusCode}} ->
@@ -285,8 +323,7 @@ check_status_code(StatusCode, Current = [_ | Rest], Options) ->
{value, {statuscode, _OtherStatus}} ->
check_status_code(StatusCode, Rest, Options);
false ->
- test_server:fail({wrong_status_code, [{got, StatusCode},
- {expected, Options}]})
+ tsf({wrong_status_code, [{got, StatusCode}, {expected, Options}]})
end.
do_validate(_, [], _, _) ->
@@ -299,9 +336,9 @@ do_validate(Header, [{header, HeaderField}|Rest], N, P) ->
{value, {LowerHeaderField, _Value}} ->
ok;
false ->
- test_server:fail({missing_header_field, LowerHeaderField, Header});
+ tsf({missing_header_field, LowerHeaderField, Header});
_ ->
- test_server:fail({missing_header_field, LowerHeaderField, Header})
+ tsf({missing_header_field, LowerHeaderField, Header})
end,
do_validate(Header, Rest, N, P);
do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) ->
@@ -310,19 +347,15 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) ->
{value, {LowerHeaderField, Value}} ->
ok;
false ->
- test_server:fail({wrong_header_field_value, LowerHeaderField,
- Header});
+ tsf({wrong_header_field_value, LowerHeaderField, Header});
_ ->
- test_server:fail({wrong_header_field_value, LowerHeaderField,
- Header})
+ tsf({wrong_header_field_value, LowerHeaderField, Header})
end,
do_validate(Header, Rest, N, P);
-do_validate(Header,[{no_last_modified,HeaderField}|Rest],N,P) ->
-% io:format("Header: ~p~nHeaderField: ~p~n",[Header,HeaderField]),
+do_validate(Header,[{no_last_modified, HeaderField}|Rest],N,P) ->
case lists:keysearch(HeaderField,1,Header) of
{value,_} ->
- test_server:fail({wrong_header_field_value, HeaderField,
- Header});
+ tsf({wrong_header_field_value, HeaderField, Header});
_ ->
ok
end,
@@ -331,7 +364,6 @@ do_validate(Header, [_Unknown | Rest], N, P) ->
do_validate(Header, Rest, N, P).
is_expect(RequestStr) ->
-
case inets_regexp:match(RequestStr, "xpect:100-continue") of
{match, _, _}->
true;
@@ -340,15 +372,15 @@ is_expect(RequestStr) ->
end.
%% OTP-5775, content-length
-check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.0\r\n\r\n", 200, "text/html", Length, _Body) when Length /= 274->
- test_server:fail(content_length_error);
+check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.0\r\n\r\n", 200, "text/html", Length, _Body) when (Length =/= 274) ->
+ tsf(content_length_error);
check_body("GET /cgi-bin/cgi_echo HTTP/1.0\r\n\r\n", 200, "text/plain",
_, Body) ->
case size(Body) of
100 ->
ok;
_ ->
- test_server:fail(content_length_error)
+ tsf(content_length_error)
end;
check_body(RequestStr, 200, "text/html", _, Body) ->
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index c54674be36..0bb457f9b9 100644
--- a/lib/inets/test/httpd_time_test.erl
+++ b/lib/inets/test/httpd_time_test.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
@@ -333,51 +333,82 @@ poll(Error, _SocketType, _URI, _ExpRes) ->
exit({failed_creating_socket, Error}).
await_poll_response(ok, SocketType, Socket, ExpStatusCode) ->
+ await_poll_response2(SocketType, Socket, ExpStatusCode, []);
+await_poll_response(Error, _SocketType, _Socket, _ExpStatusCode) ->
+ exit(Error).
+
+%% The reply *can* be split into two messages (this is a
+%% result of OTP-9757 for ssl), so we read them all until
+%% the sockets closes, then we analyze the response.
+await_poll_response2(SocketType, Socket, ExpStatusCode, Data) ->
receive
%% SSL receives
- {ssl, Socket, Data} ->
- validate(ExpStatusCode, SocketType, Socket, Data);
- {ssl_closed, Socket} ->
- exit(connection_closed);
+ {ssl, Socket, NewData} ->
+ d("await_poll_response2 -> "
+ "received part (~w bytes) of the response", [sz(NewData)]),
+ await_poll_response2(SocketType, Socket, ExpStatusCode,
+ [NewData | Data]);
+ {ssl_closed, Socket} ->
+ %% We are done or we failed
+ d("await_poll_response2 -> "
+ "we are done after receiving ~w bytes data", [sz(Data)]),
+ validate(ExpStatusCode, SocketType, Socket,
+ lists:flatten(lists:reverse(Data)));
{ssl_error, Socket, Error} ->
exit({connection_error, Error});
%% TCP receives
- {tcp, Socket, Response} ->
- validate(ExpStatusCode, SocketType, Socket, Response);
+ {tcp, Socket, NewData} ->
+ d("await_poll_response2 -> "
+ "received part (~w bytes) of the response", [sz(NewData)]),
+ await_poll_response2(SocketType, Socket, ExpStatusCode,
+ [NewData | Data]);
{tcp_closed, Socket} ->
- exit(connection_closed);
+ %% We are done or we failed
+ d("await_poll_response2 -> "
+ "we are done after receiving ~w bytes data", [sz(Data)]),
+ validate(ExpStatusCode, SocketType, Socket,
+ lists:flatten(lists:reverse(Data)));
{tcp_error, Socket, Error} ->
exit({connection_error, Error})
after 10000 ->
- exit(response_timed_out)
- end;
-await_poll_response(Error, _SocketType, _Socket, _ExpStatusCode) ->
- exit(Error).
-
+ d("we timed out while waiting for response, "
+ "validate whatever we got so far"),
+ validate(ExpStatusCode, SocketType, Socket,
+ lists:flatten(lists:reverse(Data)))
+ %% exit(response_timed_out)
+ end.
-validate(ExpStatusCode, SocketType, Socket, Response) ->
- Sz = sz(Response),
- trash_the_rest(Socket, Sz),
- inets_test_lib:close(SocketType, Socket),
+validate(ExpStatusCode, _SocketType, _Socket, Response) ->
+ %% Sz = sz(Response),
+ %% trash_the_rest(Socket, Sz),
+ %% inets_test_lib:close(SocketType, Socket),
case inets_regexp:split(Response," ") of
- {ok,["HTTP/1.0", ExpStatusCode|_]} ->
+ {ok, ["HTTP/1.0", ExpStatusCode|_]} ->
ok;
- {ok,["HTTP/1.0", StatusCode|_]} ->
+ {ok, ["HTTP/1.0", StatusCode|_]} ->
error_msg("Unexpected status code: ~p (~s). "
"Expected status code: ~p (~s)",
[StatusCode, status_to_message(StatusCode),
ExpStatusCode, status_to_message(ExpStatusCode)]),
exit({unexpected_response_code, StatusCode, ExpStatusCode});
- {ok,["HTTP/1.1", ExpStatusCode|_]} ->
+ {ok, ["HTTP/1.1", ExpStatusCode|_]} ->
ok;
- {ok,["HTTP/1.1", StatusCode|_]} ->
+ {ok, ["HTTP/1.1", StatusCode|_]} ->
error_msg("Unexpected status code: ~p (~s). "
"Expected status code: ~p (~s)",
[StatusCode, status_to_message(StatusCode),
ExpStatusCode, status_to_message(ExpStatusCode)]),
- exit({unexpected_response_code, StatusCode, ExpStatusCode})
+ exit({unexpected_response_code, StatusCode, ExpStatusCode});
+ {ok, Unexpected} ->
+ error_msg("Unexpected response split: ~p (~s)",
+ [Unexpected, Response]),
+ exit({unexpected_response, Unexpected, Response});
+ {error, Reason} ->
+ error_msg("Failed processing response: ~p (~s)",
+ [Reason, Response]),
+ exit({failed_response_processing, Reason, Response})
end.
diff --git a/lib/inets/test/inets_app_test.erl b/lib/inets/test/inets_app_test.erl
index 9d7202e087..db2218f3b6 100644
--- a/lib/inets/test/inets_app_test.erl
+++ b/lib/inets/test/inets_app_test.erl
@@ -45,8 +45,7 @@ end_per_testcase(_Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [fields, modules, exportall, app_depend,
- undef_funcs].
+ [fields, modules, exportall, app_depend, undef_funcs].
groups() ->
[].
@@ -243,18 +242,11 @@ 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
+ %% causes ssl 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,
+ ?ENSURE_STARTED(crypto),
App = inets,
AppFile = key1search(app_file, Config),
Mods = key1search(modules, AppFile),
@@ -266,7 +258,7 @@ undef_funcs(Config) when is_list(Config) ->
ok = xref:set_default(XRef,
[{verbose,false},{warnings,false}]),
XRefName = undef_funcs_make_name(App, xref_name),
- {ok, XRefName} = xref:add_release(XRef, Root, {name,XRefName}),
+ {ok, XRefName} = xref:add_release(XRef, Root, {name, XRefName}),
{ok, App} = xref:replace_application(XRef, App, EbinDir),
{ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
xref:stop(XRef),
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index ddb1a49394..0f8671b682 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,41 +31,49 @@
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([timestamp/0, formated_timestamp/0]).
+-export([tsp/1, tsp/2, tsf/1, tss/1]).
-export([check_body/1]).
-export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]).
--export([oscmd/1, has_ipv6_support/1]).
+-export([oscmd/1, has_ipv6_support/0, has_ipv6_support/1, print_system_info/1]).
+-export([run_on_os/2, run_on_windows/1]).
+-export([ensure_started/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() ->
+ 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.
+
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;
+ has_ipv6_support();
+
{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]),
@@ -87,6 +95,49 @@ has_ipv6_support(Config) ->
oscmd(Cmd) ->
string:strip(os:cmd(Cmd), right, $\n).
+
+print_system_info([]) ->
+ do_print_system_info("System Info");
+print_system_info(Prefix) when is_list(Prefix) ->
+ NewPrefix = lists:flatten(io_lib:format("~s: System Info", [Prefix])),
+ do_print_system_info(NewPrefix).
+
+do_print_system_info(Prefix) ->
+ tsp("~s => "
+ "~n"
+ "~n OS Type: ~p"
+ "~n OS version: ~p"
+ "~n Sys Arch: ~p"
+ "~n CPU Topology: ~p"
+ "~n Num logical procs: ~p"
+ "~n SMP support: ~p"
+ "~n Num schedulers: ~p"
+ "~n Scheduler bindings: ~p"
+ "~n Wordsize: ~p"
+ "~n~n", [Prefix,
+ os:type(), os:version(),
+ erlang:system_info(system_architecture),
+ erlang:system_info(cpu_topology),
+ erlang:system_info(logical_processors),
+ erlang:system_info(smp_support),
+ erlang:system_info(schedulers),
+ erlang:system_info(scheduler_bindings),
+ erlang:system_info(wordsize)]),
+ ok.
+
+
+run_on_windows(Fun) ->
+ run_on_os(windows, Fun).
+
+run_on_os(windows, Fun) ->
+ case os:type() of
+ {win32, _} ->
+ Fun();
+ _ ->
+ ok
+ end.
+
+
%% -- Misc node operation wrapper functions --
start_node(Name) ->
@@ -126,6 +177,48 @@ await_stopped(Node, N) ->
%% ----------------------------------------------------------------
+%% Ensure apps are started
+%% This to ensure we dont attempt to run teatcases on platforms
+%% where there is no working ssl app.
+
+ensure_started([]) ->
+ ok;
+ensure_started([App|Apps]) ->
+ ensure_started(App),
+ ensure_started(Apps);
+ensure_started(crypto = App) ->
+ %% We have to treat crypto in this special way because
+ %% only this function ensures that the NIF lib is actually
+ %% loaded. And only by loading that lib can we know if it
+ %% is even possible to run crypto.
+ do_ensure_started(App, fun() -> crypto:start() end);
+ensure_started(App) when is_atom(App) ->
+ do_ensure_started(App, fun() -> application:start(App) end).
+
+do_ensure_started(App, Start) when is_function(Start) ->
+ case (catch Start()) of
+ ok ->
+ ok;
+ {error, {already_started, _}} ->
+ ok;
+ Error ->
+ throw({error, {failed_starting, App, Error}})
+ end.
+
+
+ensure_loaded(App) ->
+ case application:load(App) of
+ ok ->
+ ok;
+ {error, {already_loaded,inets}} ->
+ ok;
+ Error ->
+ Error
+ end.
+
+
+
+%% ----------------------------------------------------------------
%% HTTPD starter functions
%%
@@ -133,8 +226,9 @@ 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"),
+ tsp("start_http_server(essl) -> try start crypto"),
application:start(crypto),
+ tsp("start_http_server(essl) -> try start public_key"),
application:start(public_key),
do_start_http_server(Conf);
start_http_server(Conf, SslTag) ->
@@ -145,23 +239,32 @@ do_start_http_server(Conf) ->
tsp("do_start_http_server -> entry with"
"~n Conf: ~p"
"~n", [Conf]),
- application:load(inets),
- case application:set_env(inets, services, [{httpd, Conf}]) of
+ tsp("do_start_http_server -> load inets"),
+ case ensure_loaded(inets) of
ok ->
- tsp("start_http_server -> httpd conf stored in inets app env"),
- case application:start(inets) of
+ tsp("do_start_http_server -> inets loaded - now set_env for httpd"),
+ case application:set_env(inets, services, [{httpd, Conf}]) of
ok ->
- tsp("start_http_server -> inets started"),
- ok;
- Error1 ->
- tsp("<ERROR> Failed starting application: "
- "~n Error1: ~p", [Error1]),
- Error1
+ tsp("do_start_http_server -> "
+ "httpd conf stored in inets app env"),
+ case (catch application:start(inets)) of
+ ok ->
+ tsp("do_start_http_server -> inets started"),
+ ok;
+ Error1 ->
+ tsp("<ERROR> Failed starting application: "
+ "~n Error1: ~p", [Error1]),
+ tsf({failed_starting_inets, Error1})
+ end;
+ Error2 ->
+ tsp("<ERROR> Failed set application env: "
+ "~n Error: ~p", [Error2]),
+ tsf({failed_set_env, Error2})
end;
- Error2 ->
- tsp("<ERROR> Failed set application env: "
- "~n Error: ~p", [Error2]),
- Error2
+ {error, Reason} ->
+ tsp("do_start_http_server -> failed loading inets"
+ "~n Reason: ~p", [Reason]),
+ tsf({failed_loading_inets, Reason})
end.
start_http_server_ssl(FileName) ->
@@ -181,6 +284,7 @@ do_start_http_server_ssl(FileName) ->
catch do_start_http_server(FileName).
+
%% ----------------------------------------------------------------------
%% print functions
%%
@@ -225,20 +329,49 @@ copy_files(FromDir, ToDir) ->
copy_dirs(FromDirRoot, ToDirRoot) ->
- {ok, Files} = file:list_dir(FromDirRoot),
- lists:foreach(
- fun(FileOrDir) ->
- %% Check if it's a directory or a file
- case filelib:is_dir(filename:join(FromDirRoot, FileOrDir)) of
- true ->
- FromDir = filename:join([FromDirRoot, FileOrDir]),
- ToDir = filename:join([ToDirRoot, FileOrDir]),
- ok = file:make_dir(ToDir),
- copy_dirs(FromDir, ToDir);
- false ->
- copy_file(FileOrDir, FromDirRoot, ToDirRoot)
- end
- end, Files).
+ case file:list_dir(FromDirRoot) of
+ {ok, Files} ->
+ lists:foreach(
+ fun(FileOrDir) ->
+ %% Check if it's a directory or a file
+ case filelib:is_dir(filename:join(FromDirRoot,
+ FileOrDir)) of
+ true ->
+ FromDir = filename:join([FromDirRoot, FileOrDir]),
+ ToDir = filename:join([ToDirRoot, FileOrDir]),
+ case file:make_dir(ToDir) of
+ ok ->
+ copy_dirs(FromDir, ToDir);
+ {error, Reason} ->
+ tsp("<ERROR> Failed creating directory: "
+ "~n ToDir: ~p"
+ "~n Reason: ~p"
+ "~nwhen"
+ "~n ToDirRoot: ~p"
+ "~n ToDirRoot file info: ~p",
+ [ToDir,
+ Reason,
+ ToDirRoot,
+ file:read_file_info(ToDirRoot)]),
+ tsf({failed_copy_dir, ToDir, Reason})
+ end;
+ false ->
+ copy_file(FileOrDir, FromDirRoot, ToDirRoot)
+ end
+ end, Files);
+ {error, Reason} ->
+ tsp("<ERROR> Failed get directory file list: "
+ "~n FromDirRoot: ~p"
+ "~n Reason: ~p"
+ "~nwhen"
+ "~n FromDirRoot file info: ~p",
+ [FromDirRoot,
+ Reason,
+ file:read_file_info(FromDirRoot)]),
+ tsf({failed_list_dir, FromDirRoot, Reason})
+ end.
+
+
del_dirs(Dir) ->
case file:list_dir(Dir) of
@@ -362,56 +495,73 @@ connect_byte(ip_comm, Host, Port, Opts0) ->
connect(ip_comm, Host, Port, Opts).
-connect(ssl, Host, Port, Opts) ->
+%% This always falls back on IPV4, but tries IPV6 first.
+connect(Proto, Host, Port, Opts0) ->
+ Opts = Opts0 -- [inet, inet6],
+ connect(Proto, Host, Port, Opts ++ [inet6], inet6).
+
+connect(ssl, Host, Port, Opts, Type) ->
tsp("connect(ssl) -> entry with"
"~n Host: ~p"
"~n Port: ~p"
- "~n Opts: ~p", [Host, Port, Opts]),
+ "~n Opts: ~p"
+ "~n Type: ~p", [Host, Port, Opts, Type]),
ssl:start(),
- %% Does not support ipv6 in old ssl
+ %% We ignore this option for ssl...
+ %% ...maybe we should really treat this in the same way as ip_comm...
case ssl:connect(Host, Port, Opts) of
{ok, Socket} ->
{ok, Socket};
+ {error, Reason} when Type =:= inet6 ->
+ tsp("connect(ssl) -> failed connecting with inet6: "
+ "~n Reason: ~p"
+ "~n trying inet", [Reason]),
+ connect(ssl, Host, Port, Opts -- [inet6], inet);
{error, Reason} ->
- {error, Reason};
+ tsp("connect(ssl) -> failed connecting: "
+ "~n Reason: ~p", [Reason]),
+ {error, Reason};
Error ->
Error
end;
-connect(ip_comm, Host, Port, Opts) ->
+connect(ip_comm, Host, Port, Opts, Type) ->
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
+ "~n Opts: ~p"
+ "~n Type: ~p", [Host, Port, Opts, Type]),
+
+ case gen_tcp:connect(Host, Port, Opts, timer:seconds(10)) of
{ok, Socket} ->
tsp("connect success"),
{ok, Socket};
- {error, nxdomain} ->
- tsp("connect error nxdomain when opts: ~p", [Opts]),
- connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
- {error, eafnosupport} ->
- 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("connect error eafnosupport when opts: ~p", [Opts]),
- connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
- {error, {enfile,_}} ->
- tsp("connect error enfile when opts: ~p", [Opts]),
- {error, enfile};
+
+ {error, Reason} when ((Type =:= inet6) andalso
+ ((Reason =:= timeout) orelse
+ (Reason =:= nxdomain) orelse
+ (Reason =:= eafnosupport) orelse
+ (Reason =:= econnreset) orelse
+ (Reason =:= enetunreach) orelse
+ (Reason =:= econnrefused) orelse
+ (Reason =:= ehostunreach))) ->
+ tsp("connect(ip_comm) -> Connect error: "
+ "~n Reason: ~p"
+ "~n Type: ~p"
+ "~n Opts: ~p", [Reason, Type, Opts]),
+ connect(ip_comm, Host, Port, Opts -- [inet6], inet);
+
Error ->
- tsp("Unexpected error: "
+ tsp("connect(ip_comm) -> Fatal connect error: "
"~n Error: ~p"
"~nwhen"
"~n Host: ~p"
"~n Port: ~p"
"~n Opts: ~p"
- "~n", [Error, Host, Port, Opts]),
+ "~n Type: ~p"
+ "~n", [Error, Host, Port, Opts, Type]),
Error
end.
-
+
send(ssl, Socket, Data) ->
ssl:send(Socket, Data);
@@ -477,12 +627,18 @@ tsp(F) ->
tsp(F, []).
tsp(F, A) ->
Timestamp = formated_timestamp(),
- test_server:format("*** ~s ~p ~p ~w:" ++ F ++ "~n",
- [Timestamp, node(), self(), ?MODULE | A]).
+ test_server:format("*** ~s ~p ~p " ++ F ++ "~n",
+ [Timestamp, node(), self() | A]).
tsf(Reason) ->
test_server:fail(Reason).
+tss(Time) ->
+ test_server:sleep(Time).
+
+timestamp() ->
+ http_util:timestamp().
+
formated_timestamp() ->
format_timestamp( os:timestamp() ).
diff --git a/lib/inets/test/inets_test_lib.hrl b/lib/inets/test/inets_test_lib.hrl
index 4dd81093a2..6a86b1b764 100644
--- a/lib/inets/test/inets_test_lib.hrl
+++ b/lib/inets/test/inets_test_lib.hrl
@@ -50,6 +50,11 @@
-define(OSCMD(Cmd), inets_test_lib:oscmd(Cmd)).
+-define(PRINT_SYSTEM_INFO(P), inets_test_lib:print_system_info(P)).
+
+-define(RUN_ON_OS(OS, FUN), inets_test_lib:run_on_os(OS, FUN)).
+-define(RUN_ON_WINDOWS(FUN), inets_test_lib:run_on_windows(FUN)).
+
%% - Test case macros -
@@ -64,10 +69,11 @@
%% - Misc macros -
--define(UPDATE(K,V,C), inets_test_lib:update_config(K,V,C)).
--define(CONFIG(K,C), inets_test_lib:get_config(K,C)).
--define(HOSTNAME(), inets_test_lib:hostname()).
--define(SZ(X), inets_test_lib:sz(X)).
+-define(ENSURE_STARTED(A), inets_test_lib:ensure_started(A)).
+-define(UPDATE(K,V,C), inets_test_lib:update_config(K,V,C)).
+-define(CONFIG(K,C), inets_test_lib:get_config(K,C)).
+-define(HOSTNAME(), inets_test_lib:hostname()).
+-define(SZ(X), inets_test_lib:sz(X)).
%% - Test case macros -
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 1df4558e45..949eceea7f 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2011. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The 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,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 5.8
+INETS_VSN = 5.9.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/inviso/doc/src/Makefile b/lib/inviso/doc/src/Makefile
index 1b184ed78b..f00b10f29c 100644
--- a/lib/inviso/doc/src/Makefile
+++ b/lib/inviso/doc/src/Makefile
@@ -106,14 +106,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/inviso/doc/src/inviso.xml b/lib/inviso/doc/src/inviso.xml
index 44fe7a3a78..c0e2e8f0de 100644
--- a/lib/inviso/doc/src/inviso.xml
+++ b/lib/inviso/doc/src/inviso.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,10 @@
<module>inviso</module>
<modulesummary>Main API Module to the Inviso Tracer</modulesummary>
<description>
+ <warning>
+ <p>The <c>inviso</c> application is deprecated and will be
+ removed in the R16 release.</p>
+ </warning>
<p>With the <c>inviso</c> API runtime components can be started and tracing managed across a network of distributed Erlang nodes, using a control component also started with <c>inviso</c> API functions.</p>
<p>Inviso can be used both in a distributed environment and in a non-distributed. API functions not taking a list of nodes as argument works on all started runtime components. If it is the non-distributed case, that is the local runtime component. The API functions taking a list of nodes as argument, or as part of one of the arguments, can not be used in a non-distributed environment. Return values named <c>NodeResult</c> refers to return values from a single Erlang node, and will therefore be the return in the non-distributed environment.</p>
</description>
diff --git a/lib/inviso/doc/src/inviso_chapter.xml b/lib/inviso/doc/src/inviso_chapter.xml
index 4480099c67..b69fb97586 100644
--- a/lib/inviso/doc/src/inviso_chapter.xml
+++ b/lib/inviso/doc/src/inviso_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,8 +30,12 @@
</header>
<section>
- <title>Introduction</title>
<p><em>inviso</em>: (Latin) to go to see, visit, inspect, look at.</p>
+ <warning>
+ <p>The <c>inviso</c> application is deprecated and will be
+ removed in the R16 release.</p>
+ </warning>
+ <title>Introduction</title>
<p>The Inviso trace system consists of one or several runtime components supposed to run on each Erlang node doing tracing and one control component which can run on any node with available processor power. Inviso may also be part of a higher layer trace tool. See the inviso-tool as an example. The implementation is spread out over the Runtime_tools and the Inviso Erlang/OTP applications. Erlang modules necessary to run the runtime component are located in Runtime_tools and therefore assumed to be available on any node. Even though Inviso is introduced with Erlang/OTP R11B the runtime component implementation is done with backward compatibility in mind. Meaning that it is possible to compile and run it on older Erlang/OTP releases.</p>
<image file="inviso_users_guide_pic1.gif">
<icaption>Inviso Trace System Architecture Overview.</icaption>
diff --git a/lib/inviso/doc/src/make.dep b/lib/inviso/doc/src/make.dep
deleted file mode 100644
index 9459f74e6d..0000000000
--- a/lib/inviso/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex inviso.tex inviso_as_lib.tex inviso_chapter.tex \
- inviso_lfm.tex inviso_lfm_tpfreader.tex inviso_rt.tex \
- inviso_rt_meta.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: inviso_users_guide_pic1.ps
-
diff --git a/lib/inviso/doc/src/notes.xml b/lib/inviso/doc/src/notes.xml
index 7c2c3c3bde..661284e786 100644
--- a/lib/inviso/doc/src/notes.xml
+++ b/lib/inviso/doc/src/notes.xml
@@ -31,7 +31,28 @@
<p>This document describes the changes made to the Inviso application.</p>
- <section><title>Inviso 0.6.2</title>
+ <section><title>Inviso 0.6.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The <c>inviso</c> application has been deprecated and
+ will be removed in the R16 release.</p>
+ <p>
+ Own Id: OTP-9798</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inviso 0.6.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/inviso/src/Makefile b/lib/inviso/src/Makefile
index 1f2f8b1aff..292a2bec99 100644
--- a/lib/inviso/src/Makefile
+++ b/lib/inviso/src/Makefile
@@ -87,12 +87,12 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
-# $(INSTALL_DIR) $(RELSYSDIR)/include
-# $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+# $(INSTALL_DIR) "$(RELSYSDIR)/include"
+# $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inviso/src/inviso.erl b/lib/inviso/src/inviso.erl
index 0eda06a5c2..07bdf3e649 100644
--- a/lib/inviso/src/inviso.erl
+++ b/lib/inviso/src/inviso.erl
@@ -25,6 +25,7 @@
%% ------------------------------------------------------------------------------
-module(inviso).
+-deprecated(module).
%% ------------------------------------------------------------------------------
%% Exported API functions.
diff --git a/lib/inviso/src/inviso_tool_lib.erl b/lib/inviso/src/inviso_tool_lib.erl
index 7953acedd6..f221c4b6de 100644
--- a/lib/inviso/src/inviso_tool_lib.erl
+++ b/lib/inviso/src/inviso_tool_lib.erl
@@ -19,7 +19,7 @@
%% Support module to the inviso tool.
%%
%% Authors:
-%% Lennart �hman, [email protected]
+%% Lennart Öhman, [email protected]
%% -----------------------------------------------------------------------------
-module(inviso_tool_lib).
@@ -145,10 +145,10 @@ expand_module_names_2(Nodes,DirStr,ModStr,Opts) ->
%% Always returns a regexp or {error,Reason}.
expand_module_names_special_regexp(Str) ->
StrLen=length(Str),
- case regexp:first_match(Str,"[0-9a-zA-Z_/]*") of
- {match,1,StrLen} -> % Ok, it is the special case.
+ case re:run(Str,"[0-9a-zA-Z_/]*") of
+ {match,[{0,StrLen}]} -> % Ok, it is the special case.
{ok,".*"++Str++".*"}; % Convert it to a proper regexp.
- {match,_,_} ->
+ {match,_} ->
{ok,Str}; % Keep it and hope it is a regexp.
nomatch ->
{ok,Str}; % Keep it and hope it is a regexp.
diff --git a/lib/inviso/test/Makefile b/lib/inviso/test/Makefile
index c1df29d631..2650faa392 100644
--- a/lib/inviso/test/Makefile
+++ b/lib/inviso/test/Makefile
@@ -51,10 +51,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) inviso.spec inviso.cover $(ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) inviso.spec inviso.cover $(ERL_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/inviso/test/inviso_tool_SUITE.erl b/lib/inviso/test/inviso_tool_SUITE.erl
index 6b16e506eb..e14f32de44 100644
--- a/lib/inviso/test/inviso_tool_SUITE.erl
+++ b/lib/inviso/test/inviso_tool_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,7 +52,12 @@ end_per_group(_GroupName, Config) ->
%% -----------------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ case test_server:is_native(lists) of
+ true ->
+ {skip,"Native libs -- tracing doesn't work"};
+ false ->
+ Config
+ end.
%% -----------------------------------------------------------------------------
end_per_suite(_Config) ->
diff --git a/lib/inviso/vsn.mk b/lib/inviso/vsn.mk
index 79093597fe..c6b0398bde 100644
--- a/lib/inviso/vsn.mk
+++ b/lib/inviso/vsn.mk
@@ -1 +1 @@
-INVISO_VSN = 0.6.2
+INVISO_VSN = 0.6.3
diff --git a/lib/jinterface/doc/src/Makefile b/lib/jinterface/doc/src/Makefile
index acd5307dee..858c97f187 100644
--- a/lib/jinterface/doc/src/Makefile
+++ b/lib/jinterface/doc/src/Makefile
@@ -160,17 +160,17 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html/java/$(JAVA_PKG_PATH)
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- (/bin/cp -rf ../html $(RELSYSDIR)/doc)
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html/java/$(JAVA_PKG_PATH)"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ (/bin/cp -rf ../html "$(RELSYSDIR)/doc")
# $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
-# $(RELSYSDIR)/doc/html
-# $(INSTALL_DATA) $(JAVA_EXTRA_FILES) $(RELSYSDIR)/doc/html/java
-# $(INSTALL_DATA) $(TOP_HTML_FILES) $(RELSYSDIR)/doc
+# "$(RELSYSDIR)/doc/html"
+# $(INSTALL_DATA) $(JAVA_EXTRA_FILES) "$(RELSYSDIR)/doc/html/java"
+# $(INSTALL_DATA) $(TOP_HTML_FILES) "$(RELSYSDIR)/doc"
release_spec:
diff --git a/lib/jinterface/doc/src/make.dep b/lib/jinterface/doc/src/make.dep
deleted file mode 100644
index a1b3c322c6..0000000000
--- a/lib/jinterface/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex jinterface.tex jinterface_users_guide.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index 11fcc5f387..420e121389 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -30,6 +30,60 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.5.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct spelling of registered (Thanks to Richard
+ Carlsson)</p>
+ <p>
+ Own Id: OTP-9925</p>
+ </item>
+ <item>
+ <p>
+ Java 1.5 has a bug where detecting codepoint offsets in
+ strings that are created by String.substring() gives
+ wrong results. The new implementation uses a different
+ method, avoinding the issue. (Thanks to Vlad Dumitrescu)</p>
+ <p>
+ Own Id: OTP-9927</p>
+ </item>
+ <item>
+ <p>
+ Improve error message when creating a too long
+ OtpErlangAtom. Also print the value that we tried to use
+ for the atom. (Thanks to Vlad Dumitrescu)</p>
+ <p>
+ Own Id: OTP-9928</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Jinterface 1.5.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ JInterface: improve OtpOutputStream buffer allocation</p>
+ <p>
+ Previously, the buffer was increased linearly by 2048
+ bytes. I now propose to use an exponential increase
+ function (similar to Javas ArrayList, e.g. always at
+ least +50%). This significantly increases performance of
+ e.g. doRPC for large parameters. (Thanks to Nico Kruber)</p>
+ <p>
+ Own Id: OTP-9806</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.5.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
index e772a2b0a5..ec817aa39b 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
@@ -3,7 +3,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
@@ -66,7 +66,7 @@ JARFLAGS=-cvf
JAVA_OPTIONS =
ifeq ($(TESTROOT),)
-RELEASE_PATH=$(ERL_TOP)/release/$(TARGET)
+RELEASE_PATH="$(ERL_TOP)/release/$(TARGET)"
else
RELEASE_PATH=$(TESTROOT)
endif
@@ -96,13 +96,13 @@ docs:
# include $(ERL_TOP)/make/otp_release_targets.mk
release release_docs release_tests release_html:
- $(MAKE) $(MFLAGS) RELEASE_PATH=$(RELEASE_PATH) $(TARGET_MAKEFILE) $@_spec
+ $(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
+ $(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/OtpErlangAtom.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java
index 4d53447164..ced4dbb8c2 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -53,7 +53,7 @@ public class OtpErlangAtom extends OtpErlangObject implements Serializable,
if (atom.length() > maxAtomLength) {
throw new java.lang.IllegalArgumentException("Atom may not exceed "
- + maxAtomLength + " characters");
+ + maxAtomLength + " characters: " + atom);
}
this.atom = atom;
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
index 19ee92e0d0..6766b52ce5 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -154,19 +154,22 @@ public class OtpErlangString extends OtpErlangObject implements Serializable,
* Unicode code points
*/
- public static int[] stringToCodePoints(final String s) {
- final int m = s.codePointCount(0, s.length());
- final int [] codePoints = new int[m];
- for (int i = 0, j = 0; j < m; i = s.offsetByCodePoints(i, 1), j++) {
- codePoints[j] = s.codePointAt(i);
- }
- return codePoints;
+ public static int[] stringToCodePoints(final String s) {
+ final int m = s.codePointCount(0, s.length());
+ final int[] codePoints = new int[m];
+ int j = 0;
+ for (int offset = 0; offset < s.length();) {
+ final int codepoint = s.codePointAt(offset);
+ codePoints[j++] = codepoint;
+ offset += Character.charCount(codepoint);
+ }
+ return codePoints;
}
/**
* Validate a code point according to Erlang definition; Unicode 3.0.
* That is; valid in the range U+0..U+10FFFF, but not in the range
- * U+D800..U+DFFF (surrogat pairs), nor U+FFFE..U+FFFF (non-characters).
+ * U+D800..U+DFFF (surrogat pairs).
*
* @param cp
* the code point value to validate
@@ -179,8 +182,7 @@ public class OtpErlangString extends OtpErlangObject implements Serializable,
// Erlang definition of valid Unicode code points;
// Unicode 3.0, XML, et.al.
return (cp>>>16) <= 0x10 // in 0..10FFFF; Unicode range
- && (cp & ~0x7FF) != 0xD800 // not in D800..DFFF; surrogate range
- && (cp & ~1) != 0xFFFE; // not in FFFE..FFFF; non-characters
+ && (cp & ~0x7FF) != 0xD800; // not in D800..DFFF; surrogate range
}
/**
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
index 71a419497a..0fd93b09f4 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -31,7 +31,7 @@ package com.ericsson.otp.erlang;
* the recipient of the message. When sending messages to other mailboxes, the
* recipient can only respond if the sender includes the pid as part of the
* message contents. The sender can determine his own pid by calling
- * {@link #self self()}.
+ * {@link #self() self()}.
* </p>
*
* <p>
@@ -141,7 +141,7 @@ public class OtpMbox {
* Get the registered name of this mailbox.
*
* @return the registered name of this mailbox, or null if the mailbox had
- * no registerd name.
+ * no registered name.
*/
public String getName() {
return name;
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java
index d499fae3fb..7ead0b9c54 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -182,7 +182,7 @@ public class OtpNode extends OtpLocalNode {
* Create an unnamed {@link OtpMbox mailbox} that can be used to send and
* receive messages with other, similar mailboxes and with Erlang processes.
* Messages can be sent to this mailbox by using its associated
- * {@link OtpMbox#self pid}.
+ * {@link OtpMbox#self() pid}.
*
* @return a mailbox.
*/
@@ -248,7 +248,7 @@ public class OtpNode extends OtpLocalNode {
* Create an named mailbox that can be used to send and receive messages
* with other, similar mailboxes and with Erlang processes. Messages can be
* sent to this mailbox by using its registered name or the associated
- * {@link OtpMbox#self pid}.
+ * {@link OtpMbox#self() pid}.
*
* @param name
* a name to register for this mailbox. The name must be unique
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
index 181350100f..22ebb4688a 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
@@ -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
@@ -25,6 +25,7 @@ import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
+import java.util.Arrays;
/**
* Provides a stream for encoding Erlang terms to external format, for
@@ -39,7 +40,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
/** The default initial size of the stream. * */
public static final int defaultInitialSize = 2048;
- /** The default increment used when growing the stream. * */
+ /** The default increment used when growing the stream (increment at least this much). * */
public static final int defaultIncrement = 2048;
// static formats, used to encode floats and doubles
@@ -95,6 +96,41 @@ public class OtpOutputStream extends ByteArrayOutputStream {
}
/**
+ * Trims the capacity of this <tt>OtpOutputStream</tt> instance to be the
+ * buffer's current size. An application can use this operation to minimize
+ * the storage of an <tt>OtpOutputStream</tt> instance.
+ */
+ public void trimToSize() {
+ if (super.count < super.buf.length) {
+ final byte[] tmp = new byte[super.count];
+ System.arraycopy(super.buf, 0, tmp, 0, super.count);
+ super.buf = tmp;
+ }
+ }
+
+ /**
+ * Increases the capacity of this <tt>OtpOutputStream</tt> instance, if
+ * necessary, to ensure that it can hold at least the number of elements
+ * specified by the minimum capacity argument.
+ *
+ * @param minCapacity the desired minimum capacity
+ */
+ public void ensureCapacity(int minCapacity) {
+ int oldCapacity = super.buf.length;
+ if (minCapacity > oldCapacity) {
+ int newCapacity = (oldCapacity * 3)/2 + 1;
+ if (newCapacity < oldCapacity + defaultIncrement)
+ newCapacity = oldCapacity + defaultIncrement;
+ if (newCapacity < minCapacity)
+ newCapacity = minCapacity;
+ // minCapacity is usually close to size, so this is a win:
+ final byte[] tmp = new byte[newCapacity];
+ System.arraycopy(super.buf, 0, tmp, 0, super.count);
+ super.buf = tmp;
+ }
+ }
+
+ /**
* Write one byte to the stream.
*
* @param b
@@ -102,13 +138,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
*
*/
public void write(final byte b) {
- if (super.count >= super.buf.length) {
- // System.err.println("Expanding buffer from " + this.buf.length
- // + " to " + (this.buf.length+defaultIncrement));
- final byte[] tmp = new byte[super.buf.length + defaultIncrement];
- System.arraycopy(super.buf, 0, tmp, 0, super.count);
- super.buf = tmp;
- }
+ ensureCapacity(super.count + 1);
super.buf[super.count++] = b;
}
@@ -122,14 +152,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
@Override
public void write(final byte[] buf) {
- if (super.count + buf.length > super.buf.length) {
- // System.err.println("Expanding buffer from " + super.buf.length
- // + " to " + (buf.length + super.buf.lengt + defaultIncrement));
- final byte[] tmp = new byte[super.buf.length + buf.length
- + defaultIncrement];
- System.arraycopy(super.buf, 0, tmp, 0, super.count);
- super.buf = tmp;
- }
+ ensureCapacity(super.count + buf.length);
System.arraycopy(buf, 0, super.buf, super.count, buf.length);
super.count += buf.length;
}
diff --git a/lib/jinterface/test/Makefile b/lib/jinterface/test/Makefile
index a85d0e7411..b70521c08d 100644
--- a/lib/jinterface/test/Makefile
+++ b/lib/jinterface/test/Makefile
@@ -80,6 +80,6 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(TEST_SPEC_FILE) $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(TEST_SPEC_FILE) $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index da54f5bf51..9c88400c2a 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -296,7 +296,8 @@ lists_roundtrip_2(Config) when is_list(Config) ->
{[z,23|24],tail3},
{[z|25],tail3},
{"abc123",sub3atom},
- {"abc",sub3atom}
+ {"abc",sub3atom},
+ {"abcdefg",codepointBug}
],
Trans =
fun ([_|T], tail) ->
@@ -308,7 +309,9 @@ lists_roundtrip_2(Config) when is_list(Config) ->
(L, tail3) when is_list(L) ->
null;
([_,_,_|L], sub3atom) ->
- list_to_atom(L)
+ list_to_atom(L);
+ (L, codepointBug) ->
+ L
end,
OutTrans =
fun ({L,Twist}) ->
diff --git a/lib/jinterface/test/nc_SUITE_data/echo_server.java b/lib/jinterface/test/nc_SUITE_data/echo_server.java
index 0550e4beb1..2e18e908d4 100644
--- a/lib/jinterface/test/nc_SUITE_data/echo_server.java
+++ b/lib/jinterface/test/nc_SUITE_data/echo_server.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -202,6 +202,12 @@ public class echo_server {
final OtpErlangAtom o = new OtpErlangAtom(s.stringValue()
.substring(3));
return o;
+ } else if (atomValue.equals("codepointBug")
+ && i instanceof OtpErlangString) {
+ final OtpErlangString s = (OtpErlangString) i;
+ final String ss = s.stringValue().substring(3, 6);
+ final int[] cps = OtpErlangString.stringToCodePoints(ss);
+ return s;
} else if (atomValue.equals("utf8")) {
if (i instanceof OtpErlangString) {
final OtpErlangString s = (OtpErlangString) i;
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index 9d75a653e3..15423e5658 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1 +1 @@
-JINTERFACE_VSN = 1.5.4
+JINTERFACE_VSN = 1.5.6
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index 214e994889..78e5f7bc26 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -155,18 +155,18 @@ $(SPECDIR)/specs_zlib_stub.xml:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man4
- $(INSTALL_DATA) $(MAN4_FILES) $(RELEASE_PATH)/man/man4
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man4"
+ $(INSTALL_DATA) $(MAN4_FILES) "$(RELEASE_PATH)/man/man4"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml
index ff8a12fe97..1914844b37 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>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -75,7 +75,7 @@ MaxT int() infinity
Names [Name] []
Apps [App] []
Env [{Par,Val}] []
-Start {Module,StartArgs} undefined
+Start {Module,StartArgs} []
Phases [{Phase,PhaseArgs}] undefined
Module = Name = App = Par = Phase = atom()
Val = StartArgs = PhaseArgs = term()</code>
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 6b89711924..ee687511a3 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -229,10 +229,10 @@
<c>-code_path_choice Choice</c>. If the flag is set to <c>relaxed</c>,
the code server will instead choose a suitable directory
depending on the actual file structure. If there exists a regular
- application ebin directory,situation it will be choosen. But if it does
- not exist, the ebin directory in the archive is choosen if it
+ application ebin directory,situation it will be chosen. But if it does
+ not exist, the ebin directory in the archive is chosen if it
exists. If neither of them exists the original directory will be
- choosen.</p>
+ chosen.</p>
<p>The command line flag <c>-code_path_choice Choice</c> does also
affect how <c>init</c> interprets the <c>boot script</c>. The
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index 2d95f96ac7..ec3274965a 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>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -49,7 +49,7 @@
that events are logged to file instead, or not logged at all, see
<seealso marker="kernel_app">kernel(6)</seealso>.</p>
<p>Also the SASL application, if started, adds its own event
- handler, which by default writes supervisor-, crash- and progress
+ handler, which by default writes supervisor, crash and progress
reports to tty. See
<seealso marker="sasl:sasl_app">sasl(6)</seealso>.</p>
<p>It is recommended that user defined applications should report
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 7db20e6343..772eff13cc 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -149,6 +149,12 @@
<datatype>
<name name="mode"/>
</datatype>
+ <datatype>
+ <name name="file_info_option"/>
+ </datatype>
+ <datatype>
+ <name name="sendfile_option"/>
+ </datatype>
</datatypes>
<funcs>
@@ -409,7 +415,7 @@
<name>file_info(Filename) -> {ok, FileInfo} | {error, Reason}</name>
<fsummary>Get information about a file (deprecated)</fsummary>
<desc>
- <p>This function is obsolete. Use <c>read_file_info/1</c>
+ <p>This function is obsolete. Use <c>read_file_info/1,2</c>
instead.</p>
</desc>
</func>
@@ -536,7 +542,7 @@
<desc>
<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
+ platforms that support links (Unix and Windows). This function returns
<c>ok</c> if the link was successfully created, or
<c>{error, <anno>Reason</anno>}</c>. On platforms that do not support
links, <c>{error,enotsup}</c> is returned.</p>
@@ -563,11 +569,12 @@
<name name="make_symlink" arity="2"/>
<fsummary>Make a symbolic link to a file or directory</fsummary>
<desc>
- <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
+ <p>This function creates a symbolic link <c><anno>New</anno></c> to
+ the file or directory <c><anno>Existing</anno></c>, on platforms that
+ support symbolic links (most Unix systems and Windows beginning with
+ Vista).
+ <c><anno>Existing</anno></c> need not exist.
+ This function returns <c>ok</c> if the link was
successfully created, or <c>{error, <anno>Reason</anno>}</c>.
On platforms
that do not support symbolic links, <c>{error, enotsup}</c>
@@ -577,11 +584,11 @@
<tag><c>eacces</c></tag>
<item>
<p>Missing read or write permissions for the parent directories
- of <c><anno>Name1</anno></c> or <c><anno>Name2</anno></c>.</p>
+ of <c><anno>Existing</anno></c> or <c><anno>New</anno></c>.</p>
</item>
<tag><c>eexist</c></tag>
<item>
- <p><c><anno>Name2</anno></c> already exists.</p>
+ <p><c><anno>New</anno></c> already exists.</p>
</item>
<tag><c>enotsup</c></tag>
<item>
@@ -1185,6 +1192,7 @@
</func>
<func>
<name name="read_file_info" arity="1"/>
+ <name name="read_file_info" arity="2"/>
<fsummary>Get information about a file</fsummary>
<desc>
<p>Retrieves information about a file. Returns
@@ -1196,6 +1204,20 @@
from which the function is called:</p>
<code type="none">
-include_lib("kernel/include/file.hrl").</code>
+ <p>The time type returned in <c>atime</c>, <c>mtime</c> and <c>ctime</c>
+ is dependent on the time type set in <c>Opts :: {time, Type}</c>.
+ Type <c>local</c> will return local time, <c>universal</c> will
+ return universal time and <c>posix</c> will return seconds since
+ or before unix time epoch which is 1970-01-01 00:00 UTC.
+ Default is <c>{time, local}</c>.
+ </p>
+ <note>
+ <p>
+ Since file times is stored in posix time on most OS it is
+ faster to query file information with the <c>posix</c> option.
+ </p>
+ </note>
+
<p>The record <c>file_info</c> contains the following fields.</p>
<taglist>
<tag><c>size = integer()</c></tag>
@@ -1210,15 +1232,15 @@
<item>
<p>The current system access to the file.</p>
</item>
- <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer() </c></tag>
<item>
- <p>The last (local) time the file was read.</p>
+ <p>The last time the file was read.</p>
</item>
- <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer() </c></tag>
<item>
- <p>The last (local) time the file was written.</p>
+ <p>The last time the file was written.</p>
</item>
- <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer() </c></tag>
<item>
<p>The interpretation of this time field depends on
the operating system. On Unix, it is the last time
@@ -1374,9 +1396,11 @@
</func>
<func>
<name name="read_link_info" arity="1"/>
+ <name name="read_link_info" arity="2"/>
<fsummary>Get information about a link or file</fsummary>
<desc>
- <p>This function works like <c>read_file_info/1</c>, except that
+ <p>This function works like
+ <seealso marker="#read_file_info/2">read_file_info/1,2</seealso> except that
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
@@ -1574,6 +1598,48 @@
</desc>
</func>
<func>
+ <name name="sendfile" arity="2"/>
+ <fsummary>send a file to a socket</fsummary>
+ <desc>
+ <p>Sends the file <c>Filename</c> to <c>Socket</c>.
+ Returns <c>{ok, BytesSent}</c> if successful,
+ otherwise <c>{error, Reason}</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="sendfile" arity="5"/>
+ <fsummary>send a file to a socket</fsummary>
+ <desc>
+ <p>Sends <c>Bytes</c> from the file
+ referenced by <c>RawFile</c> beginning at <c>Offset</c> to
+ <c>Socket</c>.
+ Returns <c>{ok, BytesSent}</c> if successful,
+ otherwise <c>{error, Reason}</c>. If <c>Bytes</c> is set to
+ 0 all data after the given <c>Offset</c> is sent.</p>
+ <p>The file used must be opened using the raw flag, and the process
+ calling sendfile must be the controlling process of the socket.
+ See <seealso marker="gen_tcp#controlling_process-2">gen_tcp:controlling_process/2</seealso></p>
+ <p>If the OS used does not support sendfile, an Erlang fallback
+ using file:read and gen_tcp:send is used.</p>
+ <p>The option list can contain the following options:
+ <taglist>
+ <tag><c>chunk_size</c></tag>
+ <item>The chunk size used by the erlang fallback to send
+ data. If using the fallback, this should be set to a value
+ which comfortably fits in the systems memory. Default is 20 MB.</item>
+ </taglist>
+ </p>
+ <p>On operating systems with thread support, it is recommended to use
+ async threads. See the command line flag
+ <c>+A</c> in <seealso marker="erts:erl">erl(1)</seealso>. If it is not
+ possible to use async threads for sendfile, it is recommended to use
+ a relatively small value for the send buffer on the socket. Otherwise
+ the Erlang VM might loose some of its soft realtime guarantees.
+ Which size to use depends on the OS/hardware and the requirements
+ of the application.</p>
+ </desc>
+ </func>
+ <func>
<name name="write" arity="2"/>
<fsummary>Write to a file</fsummary>
<desc>
@@ -1645,6 +1711,7 @@
</func>
<func>
<name name="write_file_info" arity="2"/>
+ <name name="write_file_info" arity="3"/>
<fsummary>Change information about a file</fsummary>
<desc>
<p>Change file information. Returns <c>ok</c> if successful,
@@ -1655,18 +1722,25 @@
from which the function is called:</p>
<code type="none">
-include_lib("kernel/include/file.hrl").</code>
+ <p>The time type set in <c>atime</c>, <c>mtime</c> and <c>ctime</c>
+ is dependent on the time type set in <c>Opts :: {time, Type}</c>.
+ Type <c>local</c> will interpret the time set as local, <c>universal</c> will
+ interpret it as universal time and <c>posix</c> must be seconds since
+ or before unix time epoch which is 1970-01-01 00:00 UTC.
+ Default is <c>{time, local}</c>.
+ </p>
<p>The following fields are used from the record, if they are
given.</p>
<taglist>
- <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso> | integer()</c></tag>
<item>
- <p>The last (local) time the file was read.</p>
+ <p>The last time the file was read.</p>
</item>
- <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso> | integer()</c></tag>
<item>
- <p>The last (local) time the file was written.</p>
+ <p>The last time the file was written.</p>
</item>
- <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso> | integer()</c></tag>
<item>
<p>On Unix, any value give for this field will be ignored
(the "ctime" for the file will be set to the current
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 688cd0f78f..e327a4f907 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -45,7 +45,15 @@
SUSE Linux Enterprise Server 10 (x86_64) kernel 2.6.16.27-0.6-smp,
with lksctp-tools-1.0.6, briefly on Solaris 10, and later on
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>
+ kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7,
+ and later also on FreeBSD 8.2.
+ </p>
+ <p>
+ This module was written for one-to-many style sockets
+ (type <c>seqpacket</c>). With the addition of
+ <seealso marker="#peeloff/2">peeloff/2</seealso>, one-to-one style
+ sockets (type <c>stream</c>) were introduced.
+ </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>
<p>These record definitions use the "new" spelling 'adaptation',
@@ -115,7 +123,7 @@
<p>Completely closes the socket and all associations on it. The unsent
data is flushed as in <c>eof/2</c>. The <c>close/1</c> call
is blocking or otherwise depending of the value of
- the <seealso marker="#option-linger">linger</seealso> socket
+ the <seealso marker="inet#option-linger">linger</seealso> socket
<seealso marker="#options">option</seealso>.
If <c>close</c> does not linger or linger timeout expires,
the call returns and the data is flushed in the background.</p>
@@ -254,15 +262,19 @@
</desc>
</func>
<func>
- <name name="listen" arity="2"/>
+ <name name="listen" arity="2" clause_i="1"/>
+ <name name="listen" arity="2" clause_i="2"/>
<fsummary>Set up a socket to listen.</fsummary>
<desc>
<p>Sets up a socket to listen on the IP address and port number
- 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 <c><anno>IsServer</anno></c> is <c>true</c> the socket accepts new associations, i.e.
- it will become an SCTP server socket.</p>
+ it is bound to.</p>
+ <p>For type <c>seqpacket</c> sockets (the default)
+ <c><anno>IsServer</anno></c> must be <c>true</c> or <c>false</c>.
+ In contrast to TCP, in SCTP there is no listening queue length.
+ 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>
+ <p>For type <c>stream</c> sockets <anno>Backlog</anno> defines
+ the backlog queue length just like in TCP.</p>
</desc>
</func>
<func>
@@ -295,9 +307,37 @@
is used. In particular, the socket is opened in
<seealso marker="#option-binary">binary</seealso> and
<seealso marker="#option-active">passive</seealso> mode,
+ with <anno>SockType</anno> <c>seqpacket</c>,
and with reasonably large
- <seealso marker="#option-sndbuf">kernel</seealso> and driver
- <seealso marker="#option-buffer">buffers.</seealso></p>
+ <seealso marker="inet#option-sndbuf">kernel</seealso> and driver
+ <seealso marker="inet#option-buffer">buffers.</seealso></p>
+ </desc>
+ </func>
+ <func>
+ <name name="peeloff" arity="2"/>
+ <fsummary>
+ Peel off a type <c>stream</c> socket from a type <c>seqpacket</c> one
+ </fsummary>
+ <desc>
+ <p>
+ Branch off an existing association <anno>Assoc</anno>
+ in a socket <anno>Socket</anno> of type <c>seqpacket</c>
+ (one-to-may style) into
+ a new socket <anno>NewSocket</anno> of type <c>stream</c>
+ (one-to-one style).
+ </p>
+ <p>
+ The existing association argument <anno>Assoc</anno>
+ can be either a
+ <seealso marker="#record-sctp_assoc_change">
+ #sctp_assoc_change{}
+ </seealso>
+ record as returned from e.g
+ <seealso marker="#recv-2">recv/*</seealso>,
+ <seealso marker="#connect-5">connect/*</seealso> or
+ from a listening socket in active mode. Or it can be just
+ the field <c>assoc_id</c> integer from such a record.
+ </p>
</desc>
</func>
<func>
@@ -490,19 +530,8 @@
SCTP data interleaved with other inter-process messages.</p>
</item>
</list>
- <marker id="option-buffer"></marker>
- </item>
- <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>
- and <c>recbuf</c> options which correspond to
- the kernel socket buffers. It is recommended
- to have <c>val(buffer) &gt;= max(val(sndbuf),val(recbuf))</c>.
- 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, integer()}</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
@@ -527,19 +556,8 @@
<c>{IP,Port}</c> of the socket can be re-used immediately:
no waiting in the CLOSE_WAIT state is performed (may be
required for high-throughput servers).</p>
- <marker id="option-linger"></marker>
</item>
- <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
- tuple is <c>false</c>, the 2nd one is ignored, which means that
- <c>gen_sctp:close/1</c> returns immediately not waiting
- for data to be flushed. Otherwise, the 2nd component is
- the flushing time-out in seconds.</p>
- <marker id="option-sndbuf"></marker>
- </item>
- <tag><c>{sndbuf, integer()}</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
@@ -553,6 +571,15 @@
<c>val(sndbuf)</c>. Setting this option also adjusts
the size of the driver buffer (see <c>buffer</c> above).</p>
</item>
+
+ <tag><c>{sctp_module, module()}</c></tag>
+ <item> <p>
+ Override which callback module is used. Defaults to
+ <c>inet_sctp</c> for IPv4 and <c>inet6_sctp</c> for IPv6.
+ </p>
+ </item>
+
+
<tag><c>{sctp_rtoinfo, #sctp_rtoinfo{}}</c></tag>
<item>
<pre> #sctp_rtoinfo{
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index 8a5d40bb16..11a0843c10 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>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -96,37 +96,47 @@ do_recv(Sock, Bs) ->
can be either a hostname, or an IP address.</p>
<p>The available options are:</p>
<taglist>
- <tag><c>list</c></tag>
- <item>
- <p>Received <c>Packet</c> is delivered as a list.</p>
- </item>
- <tag><c>binary</c></tag>
- <item>
- <p>Received <c>Packet</c> is delivered as a binary.</p>
- </item>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, ip_address()}</c></tag>
<item>
<p>If the host has several network interfaces, this option
specifies which one to use.</p>
</item>
- <tag><c>{port, Port}</c></tag>
+
+ <tag><c>{ifaddr, ip_address()}</c></tag>
<item>
- <p>Specify which local port number to use.</p>
- </item>
+ <p>Same as <c>{ip, ip_address()}</c>. If the host has several network interfaces, this option
+ specifies which one to use.</p>
+ </item>
+
<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
descriptor for it.</p>
</item>
- <tag><c>inet6</c></tag>
+
+ <tag><c>inet</c></tag>
<item>
+ <p>Set up the socket for IPv4.</p>
+ </item>
+
+ <tag><c>inet6</c></tag>
+ <item>
<p>Set up the socket for IPv6.</p>
</item>
- <tag><c>inet</c></tag>
+
+ <tag><c>{port, Port}</c></tag>
<item>
- <p>Set up the socket for IPv4.</p>
+ <p>Specify which local port number to use.</p>
</item>
+
+ <tag><c>{tcp_module, module()}</c></tag>
+ <item> <p>
+ Override which callback module is used. Defaults to
+ <c>inet_tcp</c> for IPv4 and <c>inet6_tcp</c> for IPv6.
+ </p>
+ </item>
+
<tag><c>Opt</c></tag>
<item>
<p>See
@@ -197,6 +207,13 @@ do_recv(Sock, Bs) ->
<c>gen_tcp</c>, use this option to pass the file
descriptor for it.</p>
</item>
+
+ <tag><c>{ifaddr, ip_address()}</c></tag>
+ <item>
+ <p>Same as <c>{ip, ip_address()}</c>. If the host has several network interfaces, this option
+ specifies which one to use.</p>
+ </item>
+
<tag><c>inet6</c></tag>
<item>
<p>Set up the socket for IPv6.</p>
@@ -205,6 +222,14 @@ do_recv(Sock, Bs) ->
<item>
<p>Set up the socket for IPv4.</p>
</item>
+
+ <tag><c>{tcp_module, module()}</c></tag>
+ <item> <p>
+ Override which callback module is used. Defaults to
+ <c>inet_tcp</c> for IPv4 and <c>inet6_tcp</c> for IPv6.
+ </p>
+ </item>
+
<tag><c>Opt</c></tag>
<item>
<p>See
@@ -235,7 +260,9 @@ do_recv(Sock, Bs) ->
<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
+ within the specified time,
+ or <c>{error, system_limit}</c> if all available ports in the
+ Erlang emulator are in use. 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><anno>Socket</anno></c>
@@ -297,7 +324,7 @@ do_recv(Sock, Bs) ->
<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>
+ <c>{error, not_owner}</c> is returned.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index daa9b7d887..726dc30546 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -72,6 +72,14 @@
<p>If the host has several network interfaces, this option
specifies which one to use.</p>
</item>
+
+ <tag><c>{ifaddr, ip_address()}</c></tag>
+ <item>
+ <p>Same as <c>{ip, ip_address()}</c>. If the host has several network interfaces, this option
+ specifies which one to use.</p>
+ </item>
+
+
<tag><c>{fd, integer() >= 0}</c></tag>
<item>
<p>If a socket has somehow been opened without using
@@ -86,6 +94,51 @@
<item>
<p>Set up the socket for IPv4.</p>
</item>
+
+ <tag><c>{udp_module, module()}</c></tag>
+ <item> <p>
+ Override which callback module is used. Defaults to
+ <c>inet_udp</c> for IPv4 and <c>inet6_udp</c> for IPv6.
+ </p>
+ </item>
+
+ <tag><c>{multicast_if, Address}</c></tag>
+ <item>
+ <p>Set the local device for a multicast socket.</p>
+ </item>
+
+ <tag><c>{multicast_loop, true | false}</c></tag>
+ <item>
+ <p>
+ When <c>true</c> sent multicast packets will be looped back to the local
+ sockets.
+ </p>
+ </item>
+
+ <tag><c>{multicast_ttl, Integer}</c></tag>
+ <item>
+ <p>
+ The <c>multicast_ttl</c> option changes the time-to-live (TTL) for
+ outgoing multicast datagrams in order to control the scope of the
+ multicasts.
+ </p>
+ <p>
+ Datagrams with a TTL of 1 are not forwarded beyond the local
+ network.
+ <br />Default: 1
+ </p>
+ </item>
+
+ <tag><c>{add_membership, {MultiAddress, InterfaceAddress}}</c></tag>
+ <item>
+ <p>Join a multicast group. </p>
+ </item>
+
+ <tag><c>{drop_membership, {MultiAddress, InterfaceAddress}}</c></tag>
+ <item>
+ <p>Leave multicast group.</p>
+ </item>
+
<tag><c>Opt</c></tag>
<item>
<p>See
@@ -136,7 +189,9 @@
<desc>
<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>
+ receives messages from the socket. If called by any other
+ process than the current controlling process,
+ <c>{error, not_owner}</c> is returned.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index e2dbcbe63d..26d1e27822 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -42,7 +42,7 @@
system.</p>
<p>An Erlang runtime system to be monitored by a heart program,
should be started with the command line flag <c>-heart</c> (see
- also <seealso marker="erts:erl">erl(1)</seealso>. The <c>heart</c>
+ also <seealso marker="erts:erl">erl(1)</seealso>). The <c>heart</c>
process is then started automatically:</p>
<pre>
% <input>erl -heart ...</input></pre>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index fad5af85bb..b727960d96 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>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -149,7 +149,7 @@ fe80::204:acff:fe17:bf38
<fsummary>Return a descriptive string for an error reason</fsummary>
<desc>
<p>Returns a diagnostic error string. See the section below
- for possible <c><anno>Posix</anno></c> values and the corresponding
+ for possible Posix values and the corresponding
strings.</p>
</desc>
</func>
@@ -445,10 +445,34 @@ fe80::204:acff:fe17:bf38
flow control; the other side will not be able send
faster than the receiver can read.</p>
</item>
+
+ <tag><c>{bit8, clear | set | on | off}</c></tag>
+ <item>
+ <p>
+ Scans every byte in received data-packets and checks if the 8 bit
+ is set in any of them. Information is retrieved with
+ <c>inet:getopts/2</c>.
+ </p>
+ <p>Note that the <c>bit8</c> option is deprecated and will be removed in Erlang/OTP R16.</p>
+ </item>
+
<tag><c>{broadcast, Boolean}</c>(UDP sockets)</tag>
<item>
<p>Enable/disable permission to send broadcasts.</p>
+ <marker id="option-buffer"></marker>
</item>
+
+ <tag><c>{buffer, Size}</c></tag>
+ <item>
+ <p>Determines the size of the user-level software buffer used by
+ the driver. Not to be confused with <c>sndbuf</c>
+ and <c>recbuf</c> options which correspond to
+ the kernel socket buffers. It is recommended
+ to have <c>val(buffer) &gt;= max(val(sndbuf),val(recbuf))</c>.
+ 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>{delay_send, Boolean}</c></tag>
<item>
<p>Normally, when an Erlang process sends to a socket,
@@ -463,10 +487,19 @@ fe80::204:acff:fe17:bf38
real property of the socket. Needless to say it is an
implementation specific option. Default is <c>false</c>.</p>
</item>
+
+ <tag><c>{deliver, port | term}</c></tag>
+ <item> <p> When <c>{active, true}</c> delivers data on the forms
+ <c>port</c> : <c>{S, {data, [H1,..Hsz | Data]}}</c> or
+ <c>term</c> : <c>{tcp, S, [H1..Hsz | Data]}</c>.
+ </p>
+ </item>
+
<tag><c>{dontroute, Boolean}</c></tag>
<item>
<p>Enable/disable routing bypass for outgoing messages.</p>
</item>
+
<tag><c>{exit_on_close, Boolean}</c></tag>
<item>
<p>By default this option is set to <c>true</c>.</p>
@@ -476,6 +509,7 @@ fe80::204:acff:fe17:bf38
<seealso marker="gen_tcp#shutdown/2">gen_tcp:shutdown/2</seealso>
to shutdown the write side.</p>
</item>
+
<tag><c>{header, Size}</c></tag>
<item>
<p>This option is only meaningful if the <c>binary</c>
@@ -487,6 +521,15 @@ fe80::204:acff:fe17:bf38
example <c>Size == 2</c>, the data received will match
<c>[Byte1,Byte2|Binary]</c>.</p>
</item>
+
+ <tag><c>{high_watermark, Size}</c></tag>
+ <item> <p>
+ Sender is forced busy if sent and enqueued data
+ reaches the highwater mark.
+ <br /> Default: 8192 kB.
+ </p>
+ </item>
+
<tag><c>{keepalive, Boolean}</c>(TCP/IP sockets)</tag>
<item>
<p>Enables/disables periodic transmission on a connected
@@ -494,7 +537,43 @@ fe80::204:acff:fe17:bf38
the other end does not respond, the connection is
considered broken and an error message will be sent to
the controlling process. Default disabled.</p>
+ <marker id="option-linger"></marker>
</item>
+
+ <tag><c>{linger, {true|false, Seconds}}</c></tag>
+ <item>
+ <p>Determines the timeout in seconds for flushing unsent data in the
+ <c>close/1</c> socket call. If the 1st component of the value
+ tuple is <c>false</c>, the 2nd one is ignored, which means that
+ <c>close/1</c> returns immediately not waiting
+ for data to be flushed. Otherwise, the 2nd component is
+ the flushing time-out in seconds.</p>
+ </item>
+
+ <tag><c>{low_watermark, Size}</c></tag>
+ <item> <p>
+ If the port has reached its <c>high_watermark</c> it will
+ force busy onto senders. When the port data queue reaches the
+ <c>low_watermark</c> callers are no longer forced busy.
+ <br /> Default: 4096 kB.
+ </p>
+ </item>
+
+ <tag><c>{mode, Mode :: binary | list}</c></tag>
+ <item>
+ <p>Received <c>Packet</c> is delivered as defined by Mode.</p>
+ </item>
+
+ <tag><c>list</c></tag>
+ <item>
+ <p>Received <c>Packet</c> is delivered as a list.</p>
+ </item>
+
+ <tag><c>binary</c></tag>
+ <item>
+ <p>Received <c>Packet</c> is delivered as a binary.</p>
+ </item>
+
<tag><c>{nodelay, Boolean}</c>(TCP/IP sockets)</tag>
<item>
<p>If <c>Boolean == true</c>, the <c>TCP_NODELAY</c> option
@@ -573,7 +652,21 @@ fe80::204:acff:fe17:bf38
is longer than the max allowed length, the packet is
considered invalid. The same happens if the packet header
is too big for the socket receive buffer.</p>
+ <p>For line oriented protocols (<c>line</c>,<c>http*</c>),
+ option <c>packet_size</c> also guarantees that lines up to the
+ indicated length are accepted and not considered invalid due
+ to internal buffer limitations.</p>
</item>
+
+ <tag><c>{priority, Priority}</c></tag>
+ <item> <p>Set the protocol-defined priority for all packets to be sent
+ on this socket.</p>
+ </item>
+
+ <tag><c>{raw, Protocol, OptionNum, ValueBin}</c></tag>
+ <item> <p>See below.</p>
+ </item>
+
<tag><c>{read_packets, Integer}</c>(UDP sockets)</tag>
<item>
<p>Sets the max number of UDP packets to read without
@@ -585,7 +678,7 @@ fe80::204:acff:fe17:bf38
high the system can become unresponsive due to
UDP packet flooding.</p>
</item>
- <tag><c>{recbuf, Integer}</c></tag>
+ <tag><c>{recbuf, Size}</c></tag>
<item>
<p>Gives the size of the receive buffer to use for
the socket.</p>
@@ -614,9 +707,10 @@ fe80::204:acff:fe17:bf38
returns <c>{error,timeout}</c>. The recommended setting is
<c>true</c> which will automatically close the socket.
Default is <c>false</c> due to backward compatibility.</p>
+ <marker id="option-sndbuf"></marker>
</item>
- <tag><c>{sndbuf, Integer}</c></tag>
+ <tag><c>{sndbuf, Size}</c></tag>
<item>
<p>Gives the size of the send buffer to use for the socket.</p>
</item>
@@ -635,6 +729,7 @@ fe80::204:acff:fe17:bf38
not implemented. Use with caution.</p>
</item>
</taglist>
+
<p>In addition to the options mentioned above, <em>raw</em>
option specifications can be used. The raw options are
specified as a tuple of arity four, beginning with the tag
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index bf513b7815..faa8f86dbd 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -104,7 +104,7 @@
that node. <c>Value</c> is one of:</p>
<taglist>
<tag><c>never</c></tag>
- <item>Connections are never automatically connected, they
+ <item>Connections are never automatically established, they
must be explicitly connected. See <c>net_kernel(3)</c>.</item>
<tag><c>once</c></tag>
<item>Connections will be established automatically, but only
@@ -231,6 +231,15 @@ MaxT = TickTime + TickTime / 4</code>
<p><em>Note:</em> Normally, a terminating node is detected
immediately.</p>
</item>
+ <tag><c>shutdown_timeout = integer() | infinity</c></tag>
+ <item>
+ <p>Specifies the time <c>application_controller</c> will wait
+ for an application to terminate during node shutdown. If the
+ timer expires, <c>application_controller</c> will brutally
+ kill <c>application_master</c> of the hanging
+ application. If this parameter is undefined, it defaults
+ to <c>infinity</c>.</p>
+ </item>
<tag><c>sync_nodes_mandatory = [NodeName]</c></tag>
<item>
<p>Specifies which other nodes <em>must</em> be alive in order
diff --git a/lib/kernel/doc/src/make.dep b/lib/kernel/doc/src/make.dep
deleted file mode 100644
index f79d1c6367..0000000000
--- a/lib/kernel/doc/src/make.dep
+++ /dev/null
@@ -1,28 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: app.tex application.tex auth.tex book.tex \
- code.tex config.tex disk_log.tex erl_boot_server.tex \
- erl_ddll.tex erl_prim_loader_stub.tex erlang_stub.tex \
- error_handler.tex error_logger.tex file.tex \
- gen_sctp.tex gen_tcp.tex gen_udp.tex global.tex \
- global_group.tex heart.tex inet.tex inet_res.tex \
- init_stub.tex kernel_app.tex net_adm.tex net_kernel.tex \
- os.tex packages.tex pg2.tex ref_man.tex rpc.tex \
- seq_trace.tex user.tex wrap_log_reader.tex \
- zlib_stub.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 3b7a710664..e54a427ff0 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -210,6 +210,10 @@
<p><c>net_kernel</c> is currently changing
<c>net_ticktime</c> to <c><anno>NetTicktime</anno></c> seconds.</p>
</item>
+ <tag><c>ignored</c></tag>
+ <item>
+ <p>The local node is not alive.</p>
+ </item>
</taglist>
</desc>
</func>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index ec57b03bd9..94624bf512 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -30,6 +30,368 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 2.15.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Driver output has been corrected so output of large
+ binaries (> 4 GiB) now does not silently fail or crash
+ the emulator, but either outputs the binary or fails the
+ call. This means that writing a binary > 4 Gib to file
+ now works but on e.g 64-bit Windows (that has
+ scatter/gather I/O buffer segment lengths of 32 bits)
+ fails. The behaviour may change in the future to always
+ write the binary, in parts if necessary.</p>
+ <p>
+ Own Id: OTP-9820 Aux Id: OTP-9795 </p>
+ </item>
+ <item>
+ <p>
+ erts: minor fix for unnecessary condition erts: change
+ SENDFILE_CHUNK_SIZE from signed to unsigned (Thanks to
+ jovi zhang)</p>
+ <p>
+ Own Id: OTP-9872</p>
+ </item>
+ <item>
+ <p> Two contracts in <c>gen_sctp</c> have been corrected.
+ </p>
+ <p>
+ Own Id: OTP-9874</p>
+ </item>
+ <item>
+ <p>If a process calls a module with an running on_load
+ handler, the process is supposed to be suspended. But if
+ the module with the on_load handler was loading used
+ <c>code:load_binary/3</c>, the call would instead fail
+ with an <c>undef</c> exception.</p>
+ <p>
+ Own Id: OTP-9875</p>
+ </item>
+ <item>
+ <p>
+ File name and error reason is now returned if creation of
+ a cookie fails. (Thanks to Magnus Henoch)</p>
+ <p>
+ Own Id: OTP-9954</p>
+ </item>
+ <item>
+ <p>
+ Fix port leak in <c>zlib</c> when passing invalid data to
+ <c>compress,uncompress,zip,unzip,gzip,gunzip</c>.</p>
+ <p>
+ Own Id: OTP-9981</p>
+ </item>
+ <item>
+ <p>
+ Various typographical errors corrected in documentation
+ for the global, error_logger, etop, lists, ets and
+ supervisor modules and in the c_portdriver and kernel_app
+ documentation. (Thanks to Ricardo Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9987</p>
+ </item>
+ <item>
+ <p> Fix returned error from gen_tcp:accept/1,2 when
+ running out of ports
+ <p>
+ The {error, enfile} return value is badly misleading and
+ confusing for this case, since the Posix ENFILE errno
+ value has a well-defined meaning that has nothing to do
+ with Erlang ports. The fix changes the return value to
+ {error, system_limit}, which is consistent with e.g.
+ various file(3) functions. inet:format_error/1 has also
+ been updated to support system_limit in the same manner
+ as file:format_error/1. (Thanks to Per Hedeland)</p></p>
+ <p>
+ Own Id: OTP-9990</p>
+ </item>
+ <item>
+ <p><c>erts_debug:size/1</c> has been corrected to take
+ sharing in the environment of funs into account. For funs
+ it used to always give the same result as
+ <c>erts_debug:flat_size/1</c>.</p>
+ <p>
+ Own Id: OTP-9991</p>
+ </item>
+ <item>
+ <p>
+ In some cases when the process doing file:sendfile
+ crashes while sending the file the efile_drv code would
+ not clean up after itself correctly. This has now been
+ fixed.</p>
+ <p>
+ Own Id: OTP-9993</p>
+ </item>
+ <item>
+ <p>
+ On BSD based platforms file:sendfile would sometime go
+ into an infinite loop when sending big files. This has
+ now been fixed.</p>
+ <p>
+ Own Id: OTP-9994</p>
+ </item>
+ <item>
+ <p>While <c>disk_log</c> eagerly collects logged terms
+ for better performance, collecting too much data may
+ choke the system and cause huge binaries to be
+ written.</p>
+ <p>The problem was addressed in OTP-9764, but the
+ situation was not improved in all cases.</p>
+ <p>(Thanks to Richard Carlsson.)</p>
+ <p>
+ Own Id: OTP-9999 Aux Id: OTP-9764 </p>
+ </item>
+ <item>
+ <p>
+ The documentation of .app files incorrectly said that the
+ default value for the <c>mod</c> parameter is
+ <c>undefined</c>. This is now corrected to <c>[]</c>.</p>
+ <p>
+ Own Id: OTP-10002</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 2.15</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Calls to <c>global:whereis_name/1</c> have been
+ substituted for calls to
+ <c>global:safe_whereis_name/1</c> since the latter is not
+ safe at all.</p>
+ <p>The reason for not doing this earlier is that setting
+ a global lock masked out a bug concerning the restart of
+ supervised children. The bug has now been fixed by a
+ modification of <c>global:whereis_name/1</c>. (Thanks to
+ Ulf Wiger for code contribution.)</p>
+ <p>A minor race conditions in <c>gen_fsm:start*</c> has
+ been fixed: if one of these functions returned <c>{error,
+ Reason}</c> or ignore, the name could still be registered
+ (either locally or in <c>global</c>. (This is the same
+ modification as was done for gen_server in OTP-7669.)</p>
+ <p>The undocumented function
+ <c>global:safe_whereis_name/1</c> has been removed. </p>
+ <p>
+ Own Id: OTP-9212 Aux Id: seq7117, OTP-4174 </p>
+ </item>
+ <item>
+ <p>
+ Honor option <c>packet_size</c> for http packet parsing
+ by both TCP socket and <c>erlang:decode_packet</c>. This
+ gives the ability to accept HTTP headers larger than the
+ default setting, but also avoid DoS attacks by accepting
+ lines only up to whatever length you wish to allow. For
+ consistency, packet type <c>line</c> also honor option
+ <c>packet_size</c>. (Thanks to Steve Vinoski)</p>
+ <p>
+ Own Id: OTP-9389</p>
+ </item>
+ <item>
+ <p> <c>disk_log:reopen/2,3</c> and
+ <c>disk_log:breopen/3</c> could return the error reason
+ from <c>file:rename/2</c> rather than the reason
+ <c>{file_error, Filename, Reason}</c>. This bug has been
+ fixed. </p> <p> The message <c>{disk_log, Node, {error,
+ disk_log_stopped}}</c> which according the documentation
+ is sent upon failure to truncate or reopen a disk log was
+ sometimes turned into a reply. This bug has been fixed.
+ </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9508</p>
+ </item>
+ <item>
+ <p>
+ Environment variable 'shutdown_timeout' is added to
+ kernel application. Earlier, application_controller would
+ hang forever if an application top supervisor did not
+ terminate upon a shutdown request. If this new
+ environment variable is set to a positive integer T, then
+ application controller will now give up after T
+ milliseconds and instead brutally kill the application.
+ For backwards compatibility, the default value for
+ shutdown_timeout is 'infinity'.</p>
+ <p>
+ Own Id: OTP-9540</p>
+ </item>
+ <item>
+ <p>
+ Add '-callback' attributes in stdlib's behaviours</p>
+ <p>
+ Replace the behaviour_info(callbacks) export in stdlib's
+ behaviours with -callback' attributes for all the
+ callbacks. Update the documentation with information on
+ the callback attribute Automatically generate
+ 'behaviour_info' function from '-callback' attributes</p>
+ <p>
+ 'behaviour_info(callbacks)' is a special function that is
+ defined in a module which describes a behaviour and
+ returns a list of its callbacks.</p>
+ <p>
+ This function is now automatically generated using the
+ '-callback' specs. An error is returned by lint if user
+ defines both '-callback' attributes and the
+ behaviour_info/1 function. If no type info is needed for
+ a callback use a generic spec for it. Add '-callback'
+ attribute to language syntax</p>
+ <p>
+ Behaviours may define specs for their callbacks using the
+ familiar spec syntax, replacing the '-spec' keyword with
+ '-callback'. Simple lint checks are performed to ensure
+ that no callbacks are defined twice and all types
+ referred are declared.</p>
+ <p>
+ These attributes can be then used by tools to provide
+ documentation to the behaviour or find discrepancies in
+ the callback definitions in the callback module.</p>
+ <p>
+ Add callback specs into 'application' module in kernel
+ Add callback specs to tftp module following internet
+ documentation Add callback specs to inets_service module
+ following possibly deprecated comments</p>
+ <p>
+ Own Id: OTP-9621</p>
+ </item>
+ <item>
+ <p>
+ make tab completion work in remote shells (Thanks to Mats
+ Cronqvist)</p>
+ <p>
+ Own Id: OTP-9673</p>
+ </item>
+ <item>
+ <p>
+ Add missing parenthesis in heart doc.</p>
+ <p>
+ Add missing spaces in the Reference Manual distributed
+ section.</p>
+ <p>
+ In the HTML version of the doc those spaces are necessary
+ to separate those words.</p>
+ <p>
+ Own Id: OTP-9693</p>
+ </item>
+ <item>
+ <p>
+ Fixes net_kernel:get_net_ticktime() doc</p>
+ <p>
+ Adds missing description when `ignored' is returned.
+ (Thanks to Ricardo Catalinas Jim�nez )</p>
+ <p>
+ Own Id: OTP-9713</p>
+ </item>
+ <item>
+ <p> While <c>disk_log</c> eagerly collects logged terms
+ for better performance, collecting too much data may
+ choke the system and cause huge binaries to be written.
+ In order to remedy the situation a (small) limit on the
+ amount of data that is collected before writing to disk
+ has been introduced. </p>
+ <p>
+ Own Id: OTP-9764</p>
+ </item>
+ <item>
+ <p>
+ <list> <item><p>Correct callback spec in application
+ module</p></item> <item><p>Refine warning about callback
+ specs with extra ranges</p></item> <item><p>Cleanup
+ autoimport compiler directives</p></item> <item><p>Fix
+ Dialyzer's warnings in typer</p></item> <item><p>Fix
+ Dialyzer's warning for its own code</p></item>
+ <item><p>Fix bug in Dialyzer's behaviours
+ analysis</p></item> <item><p>Fix crash in
+ Dialyzer</p></item> <item><p>Variable substitution was
+ not generalizing any unknown variables.</p></item>
+ </list></p>
+ <p>
+ Own Id: OTP-9776</p>
+ </item>
+ <item>
+ <p>
+ Fix a crash when file:change_time/2,3 are called with
+ invalid dates</p>
+ <p>
+ Calling file:change_time/2,3 with an invalid date tuple
+ (e.g file:change_time("file.txt", {undefined,
+ undefined})) will cause file_server_2 to crash.
+ error_logger will shutdown and the whole VM will stop.
+ Change behavior to validate given dates on system
+ boundaries. (i.e before issuing a server call).(Thanks to
+ Ahmed Omar)</p>
+ <p>
+ Own Id: OTP-9785</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> An option list argument can now be passed to
+ <c>file:read_file_info/2, file:read_link_info/2</c> and
+ <c>file:write_file_info/3</c> and set time type
+ information in the call. Valid options are <c>{time,
+ local}, {time, universal}</c> and <c>{time, posix}</c>.
+ In the case of <c>posix</c> time no conversions are made
+ which makes the operation a bit faster. </p>
+ <p>
+ Own Id: OTP-7687</p>
+ </item>
+ <item>
+ <p><c>file:list_dir/1,2</c> will now fill an buffer
+ entire with filenames from the efile driver before
+ sending it to an erlang process. This will speed up this
+ file operation in most cases.</p>
+ <p>
+ Own Id: OTP-9023</p>
+ </item>
+ <item>
+ <p>gen_sctp:open/0-2 may now return
+ {error,eprotonosupport} if SCTP is not supported</p>
+ <p>gen_sctp:peeloff/1 has been implemented and creates a
+ one-to-one socket which also are supported now</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9239</p>
+ </item>
+ <item>
+ <p>
+ Sendfile has been added to the file module's API.
+ sendfile/2 is used to read data from a file and send it
+ to a tcp socket using a zero copying mechanism if
+ available on that OS.</p>
+ <p>
+ Thanks to Tuncer Ayaz and Steve Vinovski for original
+ implementation</p>
+ <p>
+ Own Id: OTP-9240</p>
+ </item>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 2.14.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index e94119845a..09c525b376 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -80,6 +80,10 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
Each environment variable is given as a single string on
the format <c>"VarName=Value"</c>, where <c>VarName</c> is
the name of the variable and <c>Value</c> its value.</p>
+ <p>If Unicode file name encoding is in effect (see the <seealso
+ marker="erts:erl#file_name_encoding">erl manual
+ page</seealso>), the strings may contain characters with
+ codepoints > 255.</p>
</desc>
</func>
<func>
@@ -93,6 +97,10 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
<p>Returns the <c>Value</c> of the environment variable
<c>VarName</c>, or <c>false</c> if the environment variable
is undefined.</p>
+ <p>If Unicode file name encoding is in effect (see the <seealso
+ marker="erts:erl#file_name_encoding">erl manual
+ page</seealso>), the strings (both <c>VarName</c> and
+ <c>Value</c>) may contain characters with codepoints > 255.</p>
</desc>
</func>
<func>
@@ -123,6 +131,13 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
<desc>
<p>Sets a new <c>Value</c> for the environment variable
<c>VarName</c>.</p>
+ <p>If Unicode filename encoding is in effect (see the <seealso
+ marker="erts:erl#file_name_encoding">erl manual
+ page</seealso>), the strings (both <c>VarName</c> and
+ <c>Value</c>) may contain characters with codepoints > 255.</p>
+ <p>On Unix platforms, the environment will be set using UTF-8 encoding
+ if Unicode file name translation is in effect. On Windows the
+ environment is set using wide character interfaces.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/packages.xml b/lib/kernel/doc/src/packages.xml
index 80de2e05fc..81b8693baa 100644
--- a/lib/kernel/doc/src/packages.xml
+++ b/lib/kernel/doc/src/packages.xml
@@ -204,11 +204,5 @@ ok
Explicitly
declaring each use of a module makes for safe code.</p>
</description>
- <funcs>
- <func>
- <name>no functions exported</name>
- <fsummary>x</fsummary>
- </func>
- </funcs>
</erlref>
diff --git a/lib/kernel/examples/Makefile b/lib/kernel/examples/Makefile
index fb27f8d438..21dfd0ec0e 100644
--- a/lib/kernel/examples/Makefile
+++ b/lib/kernel/examples/Makefile
@@ -47,8 +47,8 @@ RELSYSDIR = $(RELEASE_PATH)/lib/kernel-$(KERNEL_VSN)/examples
EXAMPLES = uds_dist
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
tar cf - $(EXAMPLES) | \
- (cd $(RELSYSDIR); tar xf - ; chmod -R ug+w $(EXAMPLES) )
+ (cd "$(RELSYSDIR)"; tar xf - ; chmod -R ug+w $(EXAMPLES) )
release_docs_spec:
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 9327ab19dc..9ad6b85a0f 100644
--- a/lib/kernel/examples/uds_dist/c_src/uds_drv.c
+++ b/lib/kernel/examples/uds_dist/c_src/uds_drv.c
@@ -967,7 +967,7 @@ static void *my_malloc(size_t size)
void *ptr;
if ((ptr = driver_alloc(size)) == NULL) {
- erl_exit(1,"Could not allocate %d bytes of memory",(int) size);
+ erl_exit(1,"Could not allocate %lu bytes of memory",(unsigned long) size);
}
return ptr;
}
@@ -977,7 +977,7 @@ static void *my_realloc(void *ptr, size_t size)
void erl_exit(int, char *, ...);
void *nptr;
if ((nptr = driver_realloc(ptr, size)) == NULL) {
- erl_exit(1,"Could not reallocate %d bytes of memory",(int) size);
+ erl_exit(1,"Could not reallocate %lu bytes of memory",(unsigned long) size);
}
return nptr;
}
diff --git a/lib/kernel/include/dist.hrl b/lib/kernel/include/dist.hrl
index aea1ab81ba..5b52f6f294 100644
--- a/lib/kernel/include/dist.hrl
+++ b/lib/kernel/include/dist.hrl
@@ -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
diff --git a/lib/kernel/include/dist_util.hrl b/lib/kernel/include/dist_util.hrl
index f2b0598532..c3a7f97418 100644
--- a/lib/kernel/include/dist_util.hrl
+++ b/lib/kernel/include/dist_util.hrl
@@ -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
diff --git a/lib/kernel/include/file.hrl b/lib/kernel/include/file.hrl
index 3889bce393..bf97173122 100644
--- a/lib/kernel/include/file.hrl
+++ b/lib/kernel/include/file.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
@@ -25,10 +25,11 @@
{size :: non_neg_integer(), % Size of file in bytes.
type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
access :: 'read' | 'write' | 'read_write' | 'none',
- atime :: file:date_time(), % The local time the file was last read:
- % {{Year, Mon, Day}, {Hour, Min, Sec}}.
- mtime :: file:date_time(), % The local time the file was last written.
- ctime :: file:date_time(), % The interpretation of this time field
+ atime :: file:date_time() | integer(), % The local time the file was last read:
+ % {{Year, Mon, Day}, {Hour, Min, Sec}}.
+ % atime, ctime, mtime may also be unix epochs()
+ mtime :: file:date_time() | integer(), % The local time the file was last written.
+ ctime :: file:date_time() | integer(), % The interpretation of this time field
% is dependent on operating system.
% On Unix it is the last time the file
% or the inode was changed. On Windows,
diff --git a/lib/kernel/include/net_address.hrl b/lib/kernel/include/net_address.hrl
index 5342076507..9b9ea42931 100644
--- a/lib/kernel/include/net_address.hrl
+++ b/lib/kernel/include/net_address.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
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 02be6b5036..a39864d6b7 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/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
@@ -198,13 +198,13 @@ $(EBIN)/erl_epmd.beam: $(ESRC)/erl_epmd.erl
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index caac4d926c..c299fb085c 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -59,7 +59,7 @@
-callback start(StartType :: normal | {takeover, node()} | {failover, node()},
StartArgs :: term()) ->
- {ok, pid()} | {ok, pid(), State :: term()} | {error, Reason :: term}.
+ {'ok', pid()} | {'ok', pid(), State :: term()} | {'error', Reason :: term()}.
-callback stop(State :: term()) ->
term().
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index 42f527f400..ebfe84463a 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_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
@@ -1180,10 +1180,27 @@ terminate(Reason, S) ->
_ ->
ok
end,
+ ShutdownTimeout =
+ case application:get_env(kernel, shutdown_timeout) of
+ undefined -> infinity;
+ {ok,T} -> T
+ end,
foreach(fun({_AppName, Id}) when is_pid(Id) ->
+ Ref = erlang:monitor(process, Id),
+ unlink(Id),
exit(Id, shutdown),
receive
+ %% Proc died before link
{'EXIT', Id, _} -> ok
+ after 0 ->
+ receive
+ {'DOWN', Ref, process, Id, _} -> ok
+ after ShutdownTimeout ->
+ exit(Id, kill),
+ receive
+ {'DOWN', Ref, process, Id, _} -> ok
+ end
+ end
end;
(_) -> ok
end,
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index c329a5652a..6ae786ebd9 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -381,13 +381,17 @@ create_cookie(Name) ->
case {R1, R2} of
{ok, ok} ->
ok;
- {{error,_Reason}, _} ->
- {error, "Failed to create cookie file"};
+ {{error,Reason}, _} ->
+ {error,
+ lists:flatten(
+ io_lib:format("Failed to write to cookie file '~s': ~p", [Name, Reason]))};
{ok, {error, Reason}} ->
{error, "Failed to change mode: " ++ atom_to_list(Reason)}
end;
- {error,_Reason} ->
- {error, "Failed to create cookie file"}
+ {error,Reason} ->
+ {error,
+ lists:flatten(
+ io_lib:format("Failed to create cookie file '~s': ~p", [Name, Reason]))}
end.
random_cookie(0, _, Result) ->
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 882e9625fe..363072951e 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -63,7 +63,7 @@
which/1,
where_is_file/1,
where_is_file/2,
- set_primary_archive/3,
+ set_primary_archive/4,
clash/0]).
-export_type([load_error_rsn/0, load_ret/0]).
@@ -107,7 +107,7 @@
%% unstick_mod(Module) -> true
%% is_sticky(Module) -> boolean()
%% which(Module) -> Filename | loaded_ret_atoms() | non_existing
-%% set_primary_archive((FileName, Bin, FileInfo) -> ok | {error, Reason}
+%% set_primary_archive((FileName, ArchiveBin, FileInfo, ParserFun) -> ok | {error, Reason}
%% clash() -> ok prints out number of clashes
%%----------------------------------------------------------------------------
@@ -324,15 +324,7 @@ start_link(Flags) ->
%%-----------------------------------------------------------------
do_start(Flags) ->
- %% The following module_info/1 calls are here to ensure
- %% that these modules are loaded prior to their use elsewhere in
- %% the code_server.
- %% Otherwise a deadlock may occur when the code_server is starting.
- code_server = code_server:module_info(module),
- packages = packages:module_info(module),
- catch hipe_unified_loader:load_hipe_modules(),
- Modules2 = [gb_sets, gb_trees, ets, os, binary, unicode, filename, lists],
- lists:foreach(fun (M) -> M = M:module_info(module) end, Modules2),
+ load_code_server_prerequisites(),
Mode = get_mode(Flags),
case init:get_argument(root) of
@@ -360,6 +352,25 @@ do_start(Flags) ->
{error, crash}
end.
+%% Make sure that all modules that the code_server process calls
+%% (directly or indirectly) are loaded. Otherwise the code_server
+%% process will deadlock.
+
+load_code_server_prerequisites() ->
+ %% Please keep the alphabetical order.
+ Needed = [binary,
+ ets,
+ filename,
+ gb_sets,
+ gb_trees,
+ hipe_unified_loader,
+ lists,
+ os,
+ packages,
+ unicode],
+ [M = M:module_info(module) || M <- Needed],
+ ok.
+
do_stick_dirs() ->
do_s(compiler),
do_s(stdlib),
@@ -470,13 +481,16 @@ where_is_file(Path, File) when is_list(Path), is_list(File) ->
-spec set_primary_archive(ArchiveFile :: file:filename(),
ArchiveBin :: binary(),
- FileInfo :: file:file_info())
+ FileInfo :: file:file_info(),
+ ParserFun :: fun())
-> 'ok' | {'error', atom()}.
-set_primary_archive(ArchiveFile0, ArchiveBin, #file_info{} = FileInfo)
+set_primary_archive(ArchiveFile0, ArchiveBin, #file_info{} = FileInfo,
+ ParserFun)
when is_list(ArchiveFile0), is_binary(ArchiveBin) ->
ArchiveFile = filename:absname(ArchiveFile0),
- case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo}) of
+ case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo,
+ ParserFun}) of
{ok, []} ->
ok;
{ok, _Mode, Ebins} ->
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index e3d22e7999..00ad923466 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,8 @@
-import(lists, [foreach/2]).
+-define(ANY_NATIVE_CODE_LOADED, any_native_code_loaded).
+
-record(state, {supervisor,
root,
path,
@@ -97,6 +99,8 @@ init(Ref, Parent, [Root,Mode0]) ->
State0
end,
+ put(?ANY_NATIVE_CODE_LOADED, false),
+
Parent ! {Ref,{ok,self()}},
loop(State#state{supervisor = Parent}).
@@ -390,8 +394,8 @@ handle_call(stop,{_From,_Tag}, S) ->
handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) ->
{reply, no, S};
-handle_call({set_primary_archive, File, ArchiveBin, FileInfo}, {_From,_Tag}, S=#state{mode=Mode}) ->
- case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo) of
+handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From,_Tag}, S=#state{mode=Mode}) ->
+ case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) of
{ok, Files} ->
{reply, {ok, Mode, Files}, S};
{error, _Reason} = Error ->
@@ -1278,35 +1282,56 @@ load_native_code(Mod, Bin) ->
%% Therefore we must test for that the loader modules are available
%% before trying to to load native code.
case erlang:module_loaded(hipe_unified_loader) of
- false -> no_native;
- true -> hipe_unified_loader:load_native_code(Mod, Bin)
+ false ->
+ no_native;
+ true ->
+ Result = hipe_unified_loader:load_native_code(Mod, Bin),
+ case Result of
+ {module,_} ->
+ put(?ANY_NATIVE_CODE_LOADED, true);
+ _ ->
+ ok
+ end,
+ Result
end.
hipe_result_to_status(Result) ->
case Result of
- {module,_} -> Result;
- _ -> {error,Result}
+ {module,_} ->
+ put(?ANY_NATIVE_CODE_LOADED, true),
+ Result;
+ _ ->
+ {error,Result}
end.
post_beam_load(Mod) ->
- case erlang:module_loaded(hipe_unified_loader) of
- false -> ok;
- true -> hipe_unified_loader:post_beam_load(Mod)
+ %% post_beam_load/1 can potentially be very expensive because it
+ %% blocks multi-scheduling; thus we want to avoid the call if we
+ %% know that it is not needed.
+ case get(?ANY_NATIVE_CODE_LOADED) of
+ true -> hipe_unified_loader:post_beam_load(Mod);
+ false -> ok
end.
int_list([H|T]) when is_integer(H) -> int_list(T);
int_list([_|_]) -> false;
int_list([]) -> true.
+load_file(Mod0, {From,_}=Caller, St0) ->
+ Mod = to_atom(Mod0),
+ case pending_on_load(Mod, From, St0) of
+ no -> load_file_1(Mod, Caller, St0);
+ {yes,St} -> {noreply,St}
+ end.
-load_file(Mod, Caller, #state{path=Path,cache=no_cache}=St) ->
+load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) ->
case mod_to_bin(Path, Mod) of
error ->
{reply,{error,nofile},St};
{Mod,Binary,File} ->
try_load_module(File, Mod, Binary, Caller, St)
end;
-load_file(Mod, Caller, #state{cache=Cache}=St0) ->
+load_file_1(Mod, Caller, #state{cache=Cache}=St0) ->
Key = {obj,Mod},
case ets:lookup(Cache, Key) of
[] ->
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index d6bc23be6d..5b1efcd395 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,7 +64,7 @@
%%-define(PROFILE(C), C).
-define(PROFILE(C), void).
--compile({inline,[{log_loop,4},{log_end_sync,2},{replies,2},{rflat,1}]}).
+-compile({inline,[{log_loop,5},{log_end_sync,2},{replies,2},{rflat,1}]}).
%%%----------------------------------------------------------------------
%%% Contract type specifications
@@ -282,7 +282,8 @@ change_notify(Log, Pid, NewNotify) ->
-spec change_header(Log, Header) -> 'ok' | {'error', Reason} when
Log :: log(),
- Header :: {head, dlog_head_opt()} | {head_func, mfa()},
+ Header :: {head, dlog_head_opt()}
+ | {head_func, MFA :: {atom(), atom(), list()}},
Reason :: no_such_log | nonode | {read_only_mode, Log}
| {blocked_log, Log} | {badarg, head}.
change_header(Log, NewHead) ->
@@ -336,7 +337,9 @@ format_error(Error) ->
ok | {blocked, QueueLogRecords :: boolean()}}
| {node, Node :: node()}
| {distributed, Dist :: local | [node()]}
- | {head, Head :: none | {head, term()} | mfa()}
+ | {head, Head :: none
+ | {head, term()}
+ | (MFA :: {atom(), atom(), list()})}
| {no_written_items, NoWrittenItems ::non_neg_integer()}
| {full, Full :: boolean}
| {no_current_bytes, non_neg_integer()}
@@ -685,7 +688,7 @@ handle({From, {log, B}}, S) ->
L when L#log.mode =:= read_only ->
reply(From, {error, {read_only_mode, L#log.name}}, S);
L when L#log.status =:= ok, L#log.format =:= internal ->
- log_loop(S, From, [B], []);
+ log_loop(S, From, [B], [], iolist_size(B));
L when L#log.status =:= ok, L#log.format =:= external ->
reply(From, {error, {format_external, L#log.name}}, S);
L when L#log.status =:= {blocked, false} ->
@@ -700,7 +703,7 @@ handle({From, {blog, B}}, S) ->
L when L#log.mode =:= read_only ->
reply(From, {error, {read_only_mode, L#log.name}}, S);
L when L#log.status =:= ok ->
- log_loop(S, From, [B], []);
+ log_loop(S, From, [B], [], iolist_size(B));
L when L#log.status =:= {blocked, false} ->
reply(From, {error, {blocked_log, L#log.name}}, S);
L when L#log.blocked_by =:= From ->
@@ -714,7 +717,7 @@ handle({alog, B}, S) ->
notify_owners({read_only,B}),
loop(S);
L when L#log.status =:= ok, L#log.format =:= internal ->
- log_loop(S, [], [B], []);
+ log_loop(S, [], [B], [], iolist_size(B));
L when L#log.status =:= ok ->
notify_owners({format_external, B}),
loop(S);
@@ -730,7 +733,7 @@ handle({balog, B}, S) ->
notify_owners({read_only,B}),
loop(S);
L when L#log.status =:= ok ->
- log_loop(S, [], [B], []);
+ log_loop(S, [], [B], [], iolist_size(B));
L when L#log.status =:= {blocked, false} ->
notify_owners({blocked_log, B}),
loop(S);
@@ -1029,38 +1032,40 @@ handle(_, S) ->
loop(S).
sync_loop(From, S) ->
- log_loop(S, [], [], From).
+ log_loop(S, [], [], From, 0).
+
+-define(MAX_LOOK_AHEAD, 64*1024).
%% Inlined.
-log_loop(S, Pids, _Bins, _Sync) when S#state.cache_error =/= ok ->
+log_loop(#state{cache_error = CE}=S, Pids, _Bins, _Sync, _Sz) when CE =/= ok ->
loop(cache_error(S, Pids));
-log_loop(S, Pids, Bins, Sync) when S#state.messages =:= [] ->
+log_loop(#state{}=S, Pids, Bins, Sync, Sz) when Sz > ?MAX_LOOK_AHEAD ->
+ loop(log_end(S, Pids, Bins, Sync));
+log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz) ->
receive
Message ->
- log_loop(Message, Pids, Bins, Sync, S, get(log))
+ log_loop(Message, Pids, Bins, Sync, Sz, S, get(log))
after 0 ->
loop(log_end(S, Pids, Bins, Sync))
end;
-log_loop(S, Pids, Bins, Sync) ->
- [M | Ms] = S#state.messages,
+log_loop(#state{messages = [M | Ms]}=S, Pids, Bins, Sync, Sz) ->
S1 = S#state{messages = Ms},
- log_loop(M, Pids, Bins, Sync, S1, get(log)).
+ log_loop(M, Pids, Bins, Sync, Sz, S1, get(log)).
%% Items logged after the last sync request found are sync:ed as well.
-log_loop({alog,B}, Pids, Bins, Sync, S, L) when L#log.format =:= internal ->
+log_loop({alog,B}, Pids, Bins, Sync, Sz, S, #log{format = internal}) ->
%% {alog, _} allowed for the internal format only.
- log_loop(S, Pids, [B | Bins], Sync);
-log_loop({balog, B}, Pids, Bins, Sync, S, _L) ->
- log_loop(S, Pids, [B | Bins], Sync);
-log_loop({From, {log, B}}, Pids, Bins, Sync, S, L)
- when L#log.format =:= internal ->
+ log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B));
+log_loop({balog, B}, Pids, Bins, Sync, Sz, S, _L) ->
+ log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B));
+log_loop({From, {log, B}}, Pids, Bins, Sync, Sz, S, #log{format = internal}) ->
%% {log, _} allowed for the internal format only.
- log_loop(S, [From | Pids], [B | Bins], Sync);
-log_loop({From, {blog, B}}, Pids, Bins, Sync, S, _L) ->
- log_loop(S, [From | Pids], [B | Bins], Sync);
-log_loop({From, sync}, Pids, Bins, Sync, S, _L) ->
- log_loop(S, Pids, Bins, [From | Sync]);
-log_loop(Message, Pids, Bins, Sync, S, _L) ->
+ log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B));
+log_loop({From, {blog, B}}, Pids, Bins, Sync, Sz, S, _L) ->
+ log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B));
+log_loop({From, sync}, Pids, Bins, Sync, Sz, S, _L) ->
+ log_loop(S, Pids, Bins, [From | Sync], Sz);
+log_loop(Message, Pids, Bins, Sync, _Sz, S, _L) ->
NS = log_end(S, Pids, Bins, Sync),
handle(Message, NS).
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 259967650f..242a25a7a6 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,7 +74,7 @@
| {distributed, Nodes :: [node()]}
| {notify, boolean()}
| {head, Head :: dlog_head_opt()}
- | {head_func, mfa()}
+ | {head_func, MFA :: {atom(), atom(), list()}}
| {mode, Mode :: dlog_mode()}.
-type dlog_options() :: [dlog_option()].
-type dlog_repair() :: 'truncate' | boolean().
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index 7d6a5ade94..b8871e0d45 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,6 +53,11 @@ size(Tuple, Seen0, Sum0) when is_tuple(Tuple) ->
Sum = Sum0 + 1 + tuple_size(Tuple),
tuple_size(1, tuple_size(Tuple), Tuple, Seen, Sum)
end;
+size(Fun, Seen0, Sum) when is_function(Fun) ->
+ case remember_term(Fun, Seen0) of
+ seen -> {Sum,Seen0};
+ Seen -> fun_size(Fun, Seen, Sum)
+ end;
size(Term, Seen0, Sum) ->
case erts_debug:flat_size(Term) of
0 -> {Sum,Seen0};
@@ -68,6 +73,21 @@ tuple_size(I, Sz, _, Seen, Sum) when I > Sz ->
tuple_size(I, Sz, Tuple, Seen0, Sum0) ->
{Sum,Seen} = size(element(I, Tuple), Seen0, Sum0),
tuple_size(I+1, Sz, Tuple, Seen, Sum).
+
+fun_size(Fun, Seen, Sum) ->
+ case erlang:fun_info(Fun, type) of
+ {type,external} ->
+ {Sum + erts_debug:flat_size(Fun),Seen};
+ {type,local} ->
+ Sz = erts_debug:flat_size(fun() -> ok end),
+ {env,Env} = erlang:fun_info(Fun, env),
+ fun_size_1(Env, Seen, Sum+Sz+length(Env))
+ end.
+
+fun_size_1([H|T], Seen0, Sum0) ->
+ {Sum,Seen} = size(H, Seen0, Sum0),
+ fun_size_1(T, Seen, Sum);
+fun_size_1([], Seen, Sum) -> {Sum,Seen}.
remember_term(Term, Seen) ->
case gb_trees:lookup(Term, Seen) of
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 706c60caaf..cdb984c333 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% File system and metadata.
-export([get_cwd/0, get_cwd/1, set_cwd/1, delete/1, rename/2,
make_dir/1, del_dir/1, list_dir/1,
- read_file_info/1, write_file_info/2,
+ read_file_info/1, read_file_info/2,
+ write_file_info/2, write_file_info/3,
altname/1,
- read_link_info/1, read_link/1,
+ read_link_info/1, read_link_info/2,
+ read_link/1,
make_link/2, make_symlink/2,
read_file/1, write_file/2, write_file/3]).
%% Specialized
@@ -51,6 +53,9 @@
-export([pid2name/1]).
+%% Sendfile functions
+-export([sendfile/2,sendfile/5]).
+
%%% Obsolete exported functions
-export([raw_read_file_info/1, raw_write_file_info/2]).
@@ -103,6 +108,10 @@
-type date_time() :: calendar:datetime().
-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
| 'no_reuse' | 'will_need' | 'dont_need'.
+-type sendfile_option() :: {chunk_size, non_neg_integer()}.
+-type file_info_option() :: {'time', 'local'} | {'time', 'universal'}
+ | {'time', 'posix'}.
+
%%%-----------------------------------------------------------------
%%% General functions
@@ -211,6 +220,15 @@ del_dir(Name) ->
read_file_info(Name) ->
check_and_call(read_file_info, [file_name(Name)]).
+-spec read_file_info(Filename, Opts) -> {ok, FileInfo} | {error, Reason} when
+ Filename :: name(),
+ Opts :: [file_info_option()],
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
+
+read_file_info(Name, Opts) when is_list(Opts) ->
+ check_and_call(read_file_info, [file_name(Name), Opts]).
+
-spec altname(Name :: name()) -> any().
altname(Name) ->
@@ -224,6 +242,16 @@ altname(Name) ->
read_link_info(Name) ->
check_and_call(read_link_info, [file_name(Name)]).
+-spec read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason} when
+ Name :: name(),
+ Opts :: [file_info_option()],
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
+
+read_link_info(Name, Opts) when is_list(Opts) ->
+ check_and_call(read_link_info, [file_name(Name),Opts]).
+
+
-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
Name :: name(),
Filename :: filename(),
@@ -240,6 +268,15 @@ read_link(Name) ->
write_file_info(Name, Info = #file_info{}) ->
check_and_call(write_file_info, [file_name(Name), Info]).
+-spec write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason} when
+ Filename :: name(),
+ Opts :: [file_info_option()],
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
+
+write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) ->
+ check_and_call(write_file_info, [file_name(Name), Info, Opts]).
+
-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
Dir :: name(),
Filenames :: [filename()],
@@ -264,9 +301,9 @@ read_file(Name) ->
make_link(Old, New) ->
check_and_call(make_link, [file_name(Old), file_name(New)]).
--spec make_symlink(Name1, Name2) -> ok | {error, Reason} when
- Name1 :: name(),
- Name2 :: name(),
+-spec make_symlink(Existing, New) -> ok | {error, Reason} when
+ Existing :: name(),
+ New :: name(),
Reason :: posix() | badarg.
make_symlink(Old, New) ->
@@ -1100,8 +1137,9 @@ change_group(Name, GroupId)
Mtime :: date_time(),
Reason :: posix() | badarg.
-change_time(Name, Time)
- when is_tuple(Time) ->
+change_time(Name, {{Y, M, D}, {H, Min, Sec}}=Time)
+ when is_integer(Y), is_integer(M), is_integer(D),
+ is_integer(H), is_integer(Min), is_integer(Sec)->
write_file_info(Name, #file_info{mtime=Time}).
-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason} when
@@ -1110,10 +1148,150 @@ change_time(Name, Time)
Mtime :: date_time(),
Reason :: posix() | badarg.
-change_time(Name, Atime, Mtime)
- when is_tuple(Atime), is_tuple(Mtime) ->
+change_time(Name, {{AY, AM, AD}, {AH, AMin, ASec}}=Atime,
+ {{MY, MM, MD}, {MH, MMin, MSec}}=Mtime)
+ when is_integer(AY), is_integer(AM), is_integer(AD),
+ is_integer(AH), is_integer(AMin), is_integer(ASec),
+ is_integer(MY), is_integer(MM), is_integer(MD),
+ is_integer(MH), is_integer(MMin), is_integer(MSec)->
write_file_info(Name, #file_info{atime=Atime, mtime=Mtime}).
+%%
+%% Send data using sendfile
+%%
+
+-define(MAX_CHUNK_SIZE, (1 bsl 20)*20). %% 20 MB, has to fit in primary memory
+
+-spec sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
+ {'ok', non_neg_integer()} | {'error', inet:posix() |
+ closed | badarg | not_owner} when
+ RawFile :: file:fd(),
+ Socket :: inet:socket(),
+ Offset :: non_neg_integer(),
+ Bytes :: non_neg_integer(),
+ Opts :: [sendfile_option()].
+sendfile(File, _Sock, _Offet, _Bytes, _Opts) when is_pid(File) ->
+ {error, badarg};
+sendfile(File, Sock, Offset, Bytes, []) ->
+ sendfile(File, Sock, Offset, Bytes, ?MAX_CHUNK_SIZE, [], [],
+ false, false, false);
+sendfile(File, Sock, Offset, Bytes, Opts) ->
+ ChunkSize0 = proplists:get_value(chunk_size, Opts, ?MAX_CHUNK_SIZE),
+ ChunkSize = if ChunkSize0 > ?MAX_CHUNK_SIZE ->
+ ?MAX_CHUNK_SIZE;
+ true -> ChunkSize0
+ end,
+ %% Support for headers, trailers and options has been removed because the
+ %% Darwin and BSD API for using it does not play nice with
+ %% non-blocking sockets. See unix_efile.c for more info.
+ sendfile(File, Sock, Offset, Bytes, ChunkSize, [], [],
+ false,false,false).
+
+%% sendfile/2
+-spec sendfile(Filename, Socket) ->
+ {'ok', non_neg_integer()} | {'error', inet:posix() |
+ closed | badarg | not_owner}
+ when Filename :: file:name(),
+ Socket :: inet:socket().
+sendfile(Filename, Sock) ->
+ case file:open(Filename, [read, raw, binary]) of
+ {error, Reason} ->
+ {error, Reason};
+ {ok, Fd} ->
+ Res = sendfile(Fd, Sock, 0, 0, []),
+ file:close(Fd),
+ Res
+ end.
+
+%% Internal sendfile functions
+sendfile(#file_descriptor{ module = Mod } = Fd, Sock, Offset, Bytes,
+ ChunkSize, Headers, Trailers, Nodiskio, MNowait, Sync)
+ when is_port(Sock) ->
+ case Mod:sendfile(Fd, Sock, Offset, Bytes, ChunkSize, Headers, Trailers,
+ Nodiskio, MNowait, Sync) of
+ {error, enotsup} ->
+ sendfile_fallback(Fd, Sock, Offset, Bytes, ChunkSize,
+ Headers, Trailers);
+ Else ->
+ Else
+ end;
+sendfile(_,_,_,_,_,_,_,_,_,_) ->
+ {error, badarg}.
+
+%%%
+%% Sendfile Fallback
+%%%
+sendfile_fallback(File, Sock, Offset, Bytes, ChunkSize,
+ Headers, Trailers)
+ when Headers == []; is_integer(Headers) ->
+ case sendfile_fallback(File, Sock, Offset, Bytes, ChunkSize) of
+ {ok, BytesSent} when is_list(Trailers),
+ Trailers =/= [],
+ is_integer(Headers) ->
+ sendfile_send(Sock, Trailers, BytesSent+Headers);
+ {ok, BytesSent} when is_list(Trailers), Trailers =/= [] ->
+ sendfile_send(Sock, Trailers, BytesSent);
+ {ok, BytesSent} when is_integer(Headers) ->
+ {ok, BytesSent + Headers};
+ Else ->
+ Else
+ end;
+sendfile_fallback(File, Sock, Offset, Bytes, ChunkSize, Headers, Trailers) ->
+ case sendfile_send(Sock, Headers, 0) of
+ {ok, BytesSent} ->
+ sendfile_fallback(File, Sock, Offset, Bytes, ChunkSize, BytesSent,
+ Trailers);
+ Else ->
+ Else
+ end.
+
+
+sendfile_fallback(File, Sock, Offset, Bytes, ChunkSize) ->
+ {ok, CurrPos} = file:position(File, {cur, 0}),
+ {ok, _NewPos} = file:position(File, {bof, Offset}),
+ Res = sendfile_fallback_int(File, Sock, Bytes, ChunkSize, 0),
+ file:position(File, {bof, CurrPos}),
+ Res.
+
+
+sendfile_fallback_int(File, Sock, Bytes, ChunkSize, BytesSent)
+ when Bytes > BytesSent; Bytes == 0 ->
+ Size = if Bytes == 0 ->
+ ChunkSize;
+ (Bytes - BytesSent) < ChunkSize ->
+ Bytes - BytesSent;
+ true ->
+ ChunkSize
+ end,
+ case file:read(File, Size) of
+ {ok, Data} ->
+ case sendfile_send(Sock, Data, BytesSent) of
+ {ok,NewBytesSent} ->
+ sendfile_fallback_int(
+ File, Sock, Bytes, ChunkSize,
+ NewBytesSent);
+ Error ->
+ Error
+ end;
+ eof ->
+ {ok, BytesSent};
+ Error ->
+ Error
+ end;
+sendfile_fallback_int(_File, _Sock, BytesSent, _ChunkSize, BytesSent) ->
+ {ok, BytesSent}.
+
+sendfile_send(Sock, Data, Old) ->
+ Len = iolist_size(Data),
+ case gen_tcp:send(Sock, Data) of
+ ok ->
+ {ok, Len+Old};
+ Else ->
+ Else
+ end.
+
+
+
%%%-----------------------------------------------------------------
%%% Helpers
@@ -1238,7 +1416,11 @@ mode_list(_) ->
%% Functions for communicating with the file server
call(Command, Args) when is_list(Args) ->
- gen_server:call(?FILE_SERVER, list_to_tuple([Command | Args]), infinity).
+ X = erlang:dt_spread_tag(true),
+ Y = gen_server:call(?FILE_SERVER, list_to_tuple([Command | Args]),
+ infinity),
+ erlang:dt_restore_tag(X),
+ Y.
check_and_call(Command, Args) when is_list(Args) ->
case check_args(Args) of
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 14da9c1a55..0bff56cf46 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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,9 +57,11 @@ start_link(Owner, FileName, ModeList)
do_start(Spawn, Owner, FileName, ModeList) ->
Self = self(),
Ref = make_ref(),
+ Utag = erlang:dt_spread_tag(true),
Pid =
erlang:Spawn(
fun() ->
+ erlang:dt_restore_tag(Utag),
%% process_flag(trap_exit, true),
case parse_options(ModeList) of
{ReadMode, UnicodeMode, Opts} ->
@@ -84,6 +86,7 @@ do_start(Spawn, Owner, FileName, ModeList) ->
exit(Reason1)
end
end),
+ erlang:dt_restore_tag(Utag),
Mref = erlang:monitor(process, Pid),
receive
{Ref, {error, _Reason} = Error} ->
diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl
index 64c61ba3ac..fc6cd823c9 100644
--- a/lib/kernel/src/file_server.erl
+++ b/lib/kernel/src/file_server.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
@@ -147,15 +147,24 @@ handle_call({get_cwd, Name}, _From, Handle) ->
handle_call({read_file_info, Name}, _From, Handle) ->
{reply, ?PRIM_FILE:read_file_info(Handle, Name), Handle};
+handle_call({read_file_info, Name, Opts}, _From, Handle) ->
+ {reply, ?PRIM_FILE:read_file_info(Handle, Name, Opts), Handle};
+
handle_call({altname, Name}, _From, Handle) ->
{reply, ?PRIM_FILE:altname(Handle, Name), Handle};
handle_call({write_file_info, Name, Info}, _From, Handle) ->
{reply, ?PRIM_FILE:write_file_info(Handle, Name, Info), Handle};
+handle_call({write_file_info, Name, Info, Opts}, _From, Handle) ->
+ {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info, Opts), Handle};
+
handle_call({read_link_info, Name}, _From, Handle) ->
{reply, ?PRIM_FILE:read_link_info(Handle, Name), Handle};
+handle_call({read_link_info, Name, Opts}, _From, Handle) ->
+ {reply, ?PRIM_FILE:read_link_info(Handle, Name, Opts), Handle};
+
handle_call({read_link, Name}, _From, Handle) ->
{reply, ?PRIM_FILE:read_link(Handle, Name), Handle};
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 6cebb7ab97..8fa963ec78 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,8 @@
-include("inet_sctp.hrl").
-export([open/0,open/1,open/2,close/1]).
--export([listen/2,connect/4,connect/5,connect_init/4,connect_init/5]).
+-export([listen/2,peeloff/2]).
+-export([connect/4,connect/5,connect_init/4,connect_init/5]).
-export([eof/2,abort/2]).
-export([send/3,send/4,recv/1,recv/2]).
-export([error_string/1]).
@@ -109,9 +110,11 @@ open() ->
| {ifaddr,IP}
| inet:address_family()
| {port,Port}
+ | {type,SockType}
| option(),
IP :: inet:ip_address() | any | loopback,
Port :: inet:port_number(),
+ SockType :: seqpacket | stream,
Socket :: sctp_socket().
open(Opts) when is_list(Opts) ->
@@ -134,9 +137,11 @@ open(X) ->
| {ifaddr,IP}
| inet:address_family()
| {port,Port}
+ | {type,SockType}
| option(),
IP :: inet:ip_address() | any | loopback,
Port :: inet:port_number(),
+ SockType :: seqpacket | stream,
Socket :: sctp_socket().
open(Port, Opts) when is_integer(Port), is_list(Opts) ->
@@ -161,17 +166,38 @@ close(S) ->
-spec listen(Socket, IsServer) -> ok | {error, Reason} when
Socket :: sctp_socket(),
IsServer :: boolean(),
+ Reason :: term();
+ (Socket, Backlog) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Backlog :: integer(),
Reason :: term().
-listen(S, Flag) when is_port(S), is_boolean(Flag) ->
+listen(S, Backlog)
+ when is_port(S), is_boolean(Backlog);
+ is_port(S), is_integer(Backlog) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
- Mod:listen(S, Flag);
+ Mod:listen(S, Backlog);
Error -> Error
end;
listen(S, Flag) ->
erlang:error(badarg, [S,Flag]).
+-spec peeloff(Socket, Assoc) -> {ok, NewSocket} | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{} | assoc_id(),
+ NewSocket :: sctp_socket(),
+ Reason :: term().
+
+peeloff(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
+ peeloff(S, AssocId);
+peeloff(S, AssocId) when is_port(S), is_integer(AssocId) ->
+ case inet_db:lookup_socket(S) of
+ {ok,Mod} ->
+ Mod:peeloff(S, AssocId);
+ Error -> Error
+ end.
+
-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, inet:posix()} when
Socket :: sctp_socket(),
Addr :: inet:ip_address() | inet:hostname(),
@@ -288,7 +314,7 @@ eof_or_abort(S, AssocId, Action) ->
-spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason} when
Socket :: sctp_socket(),
SndRcvInfo :: #sctp_sndrcvinfo{},
- Data :: binary | iolist(),
+ Data :: binary() | iolist(),
Reason :: term().
%% Full-featured send. Rarely needed.
@@ -305,7 +331,7 @@ send(S, SRI, Data) ->
Socket :: sctp_socket(),
Assoc :: #sctp_assoc_change{} | assoc_id(),
Stream :: integer(),
- Data :: binary | iolist(),
+ Data :: binary() | iolist(),
Reason :: term().
send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data)
@@ -399,9 +425,10 @@ error_string(X) ->
erlang:error(badarg, [X]).
--spec controlling_process(Socket, Pid) -> ok when
+-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when
Socket :: sctp_socket(),
- Pid :: pid().
+ Pid :: pid(),
+ Reason :: closed | not_owner | inet:posix().
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 8ab18c01b4..e6dfdadb03 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,10 +27,10 @@
-export([fdopen/2]).
-include("inet_int.hrl").
+-include("file.hrl").
-type option() ::
{active, true | false | once} |
- {bit8, clear | set | on | off} |
{buffer, non_neg_integer()} |
{delay_send, boolean()} |
{deliver, port | term} |
@@ -60,7 +60,6 @@
{tos, non_neg_integer()}.
-type option_name() ::
active |
- bit8 |
buffer |
delay_send |
deliver |
@@ -174,7 +173,7 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) ->
Port :: inet:port_number(),
Options :: [listen_option()],
ListenSocket :: socket(),
- Reason :: inet:posix().
+ Reason :: system_limit | inet:posix().
listen(Port, Opts) ->
Mod = mod(Opts, undefined),
@@ -193,7 +192,7 @@ listen(Port, Opts) ->
-spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when
ListenSocket :: socket(),
Socket :: socket(),
- Reason :: closed | timeout | inet:posix().
+ Reason :: closed | timeout | system_limit | inet:posix().
accept(S) ->
case inet_db:lookup_socket(S) of
@@ -207,7 +206,7 @@ accept(S) ->
ListenSocket :: socket(),
Timeout :: timeout(),
Socket :: socket(),
- Reason :: closed | timeout | inet:posix().
+ Reason :: closed | timeout | system_limit | inet:posix().
accept(S, Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
@@ -302,7 +301,7 @@ unrecv(S, Data) when is_port(S) ->
Mod:unrecv(S, Data);
Error ->
Error
- end.
+ end.
%%
%% Set controlling process
@@ -354,3 +353,4 @@ mod([_|Opts], Address) ->
mod(Opts, Address);
mod([], Address) ->
mod(Address).
+
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 8688799ae9..914854c65c 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -185,9 +185,10 @@ connect(S, Address, Port) when is_port(S) ->
Error
end.
--spec controlling_process(Socket, Pid) -> ok when
+-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when
Socket :: socket(),
- Pid :: pid().
+ Pid :: pid(),
+ Reason :: closed | not_owner | inet:posix().
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 7d15f8bf83..36cb713ee1 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
%% External exports
-export([start/0, start_link/0, stop/0, sync/0, sync/1,
- safe_whereis_name/1, whereis_name/1, register_name/2,
+ 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,
@@ -203,10 +203,6 @@ send(Name, Msg) ->
whereis_name(Name) ->
where(Name).
--spec safe_whereis_name(term()) -> pid() | 'undefined'.
-safe_whereis_name(Name) ->
- gen_server:call(global_name_server, {whereis, Name}, infinity).
-
node_disconnected(Node) ->
global_name_server ! {nodedown, Node}.
@@ -284,13 +280,13 @@ unregister_name(Name) ->
gen_server:call(global_name_server, {registrar, Fun}, infinity)
end.
--spec re_register_name(Name, Pid) -> _ when
+-spec re_register_name(Name, Pid) -> 'yes' 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(Name, Pid, Resolve) -> _ when
+-spec re_register_name(Name, Pid, Resolve) -> 'yes' when
Name :: term(),
Pid :: pid(),
Resolve :: method().
@@ -510,8 +506,7 @@ init([]) ->
%% delay can sometimes be quite substantial. Global guarantees that
%% the name will eventually be removed, but there is no
%% synchronization between nodes; the name can be removed from some
-%% node(s) long before it is removed from other nodes. Using
-%% safe_whereis_name is no cure.
+%% node(s) long before it is removed from other nodes.
%%
%% - Global cannot handle problems with the distribution very well.
%% Depending on the value of the kernel variable 'net_ticktime' long
@@ -589,10 +584,6 @@ init([]) ->
{'reply', term(), state()} |
{'stop', 'normal', 'stopped', state()}.
-handle_call({whereis, Name}, From, S) ->
- do_whereis(Name, From),
- {noreply, S};
-
handle_call({registrar, Fun}, From, S) ->
S#state.the_registrar ! {trans_all_known, Fun, From},
{noreply, S};
@@ -1235,7 +1226,15 @@ ins_name_ext(Name, Pid, Method, RegNode, FromPidOrNode, ExtraInfo, S0) ->
where(Name) ->
case ets:lookup(global_names, Name) of
- [{_Name, Pid, _Method, _RPid, _Ref}] -> Pid;
+ [{_Name, Pid, _Method, _RPid, _Ref}] ->
+ if node(Pid) == node() ->
+ case is_process_alive(Pid) of
+ true -> Pid;
+ false -> undefined
+ end;
+ true ->
+ Pid
+ end;
[] -> undefined
end.
@@ -1966,7 +1965,7 @@ resolve_it(Method, Name, Pid1, Pid2) ->
minmax(P1,P2) ->
if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end.
--spec random_exit_name(Name, Pid1, Pid2) -> 'none' when
+-spec random_exit_name(Name, Pid1, Pid2) -> pid() when
Name :: term(),
Pid1 :: pid(),
Pid2 :: pid().
@@ -1977,7 +1976,7 @@ random_exit_name(Name, Pid, Pid2) ->
exit(Max, kill),
Min.
--spec random_notify_name(Name, Pid1, Pid2) -> 'none' when
+-spec random_notify_name(Name, Pid1, Pid2) -> pid() when
Name :: term(),
Pid1 :: pid(),
Pid2 :: pid().
@@ -2176,7 +2175,7 @@ get_own_nodes() ->
start_the_registrar() ->
spawn_link(fun() -> loop_the_registrar() end).
-
+
loop_the_registrar() ->
receive
{trans_all_known, Fun, From} ->
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index 255ae4e51b..218be964a0 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -18,6 +18,10 @@
%%
-module(heart).
+-compile(no_native).
+% 'no_native' as part of a crude fix to make init:restart/0 work by clearing
+% all hipe inter-module information (hipe_mfa_info's in hipe_bif0.c).
+
%%%--------------------------------------------------------------------
%%% This is a rewrite of pre_heart from BS.3.
%%%
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index 1d3eb926ca..514c002d87 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -34,9 +34,15 @@
-module(hipe_unified_loader).
+-compile(no_native).
+% 'no_native' is a workaround to avoid "The code server called unloaded module"
+% caused by Mod:module_info(exports) in patch_to_emu_step1() called by post_beam_load.
+% Reproducable with hipelibs and asn1_SUITE.
+% I think the real solution would be to let BIF erlang:load_module/2 redirect all
+% hipe calls to the module and thereby remove post_beam_load.
+
-export([chunk_name/1,
%% Only the code and code_server modules may call the entries below!
- load_hipe_modules/0,
load_native_code/2,
post_beam_load/1,
load_module/3,
@@ -78,16 +84,6 @@ chunk_name(Architecture) ->
%%========================================================================
--spec load_hipe_modules() -> 'ok'.
-%% @doc
-%% Ensures HiPE's loader modules are loaded.
-%% Called from code.erl at start-up.
-
-load_hipe_modules() ->
- ok.
-
-%%========================================================================
-
-spec load_native_code(Mod, binary()) -> 'no_native' | {'module', Mod}
when is_subtype(Mod, atom()).
%% @doc
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 48a6f3db65..1a03424f88 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,10 +36,14 @@
-export([i/0, i/1, i/2]).
--export([getll/1, getfd/1, open/7, fdopen/5]).
+-export([getll/1, getfd/1, open/8, fdopen/6]).
-export([tcp_controlling_process/2, udp_controlling_process/2,
tcp_close/1, udp_close/1]).
+
+%% used by sendfile
+-export([lock_socket/2]).
+
%% used by socks5
-export([setsockname/2, setpeername/2]).
@@ -115,7 +119,8 @@
'mtu' | 'netmask' | 'flags' |'hwaddr'.
-type address_family() :: 'inet' | 'inet6'.
--type protocol_option() :: 'tcp' | 'udp' | 'sctp'.
+-type socket_protocol() :: 'tcp' | 'udp' | 'sctp'.
+-type socket_type() :: 'stream' | 'dgram' | 'seqpacket'.
-type stat_option() ::
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
@@ -748,6 +753,8 @@ sctp_opt([Opt|Opts], Mod, R, As) ->
sctp_opt(Opts, Mod, R#sctp_opts{port=P}, As);
Error -> Error
end;
+ {type,Type} when Type =:= seqpacket; Type =:= stream ->
+ sctp_opt(Opts, Mod, R#sctp_opts{type=Type}, As);
binary -> sctp_opt (Opts, Mod, R, As, mode, binary);
list -> sctp_opt (Opts, Mod, R, As, mode, list);
{sctp_module,_} -> sctp_opt (Opts, Mod, R, As); % Done with
@@ -756,8 +763,12 @@ sctp_opt([Opt|Opts], Mod, R, As) ->
{Name,Val} -> sctp_opt (Opts, Mod, R, As, Name, Val);
_ -> {error,badarg}
end;
-sctp_opt([], _Mod, R, _SockOpts) ->
- {ok, R}.
+sctp_opt([], _Mod, #sctp_opts{ifaddr=IfAddr}=R, _SockOpts) ->
+ if is_list(IfAddr) ->
+ {ok, R#sctp_opts{ifaddr=lists:reverse(IfAddr)}};
+ true ->
+ {ok, R}
+ end.
sctp_opt(Opts, Mod, R, As, Name, Val) ->
case add_opt(Name, Val, R#sctp_opts.opts, As) of
@@ -996,22 +1007,19 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
Addr :: ip_address(),
Port :: port_number(),
Opts :: [socket_setopt()],
- Protocol :: protocol_option(),
- Family :: 'inet' | 'inet6',
+ Protocol :: socket_protocol(),
+ Family :: address_family(),
+ Type :: socket_type(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
- case prim_inet:open(Protocol, Family) of
+open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 ->
+ case prim_inet:open(Protocol, Family, Type) of
{ok,S} ->
case prim_inet:setopts(S, Opts) of
ok ->
case if is_list(Addr) ->
- prim_inet:bind(S, add,
- [case A of
- {_,_} -> A;
- _ -> {A,Port}
- end || A <- Addr]);
+ bindx(S, Addr, Port);
true ->
prim_inet:bind(S, Addr, Port)
end of
@@ -1029,18 +1037,47 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
Error ->
Error
end;
-open(Fd, _Addr, _Port, Opts, Protocol, Family, Module) ->
- fdopen(Fd, Opts, Protocol, Family, Module).
+open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) ->
+ fdopen(Fd, Opts, Protocol, Family, Type, Module).
+
+bindx(S, [Addr], Port0) ->
+ {IP, Port} = set_bindx_port(Addr, Port0),
+ prim_inet:bind(S, IP, Port);
+bindx(S, Addrs, Port0) ->
+ [{IP, Port} | Rest] = [set_bindx_port(Addr, Port0) || Addr <- Addrs],
+ case prim_inet:bind(S, IP, Port) of
+ {ok, AssignedPort} when Port =:= 0 ->
+ %% On newer Linux kernels, Solaris and FreeBSD, calling
+ %% bindx with port 0 is ok, but on SuSE 10, it results in einval
+ Rest2 = [change_bindx_0_port(Addr, AssignedPort) || Addr <- Rest],
+ prim_inet:bind(S, add, Rest2);
+ {ok, _} ->
+ prim_inet:bind(S, add, Rest);
+ Error ->
+ Error
+ end.
+
+set_bindx_port({_IP, _Port}=Addr, _OtherPort) ->
+ Addr;
+set_bindx_port(IP, Port) ->
+ {IP, Port}.
+
+change_bindx_0_port({IP, 0}, AssignedPort) ->
+ {IP, AssignedPort};
+change_bindx_0_port({_IP, _Port}=Addr, _AssignedPort) ->
+ Addr.
+
-spec fdopen(Fd :: non_neg_integer(),
Opts :: [socket_setopt()],
- Protocol :: protocol_option(),
+ Protocol :: socket_protocol(),
Family :: address_family(),
+ Type :: socket_type(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-fdopen(Fd, Opts, Protocol, Family, Module) ->
- case prim_inet:fdopen(Protocol, Fd, Family) of
+fdopen(Fd, Opts, Protocol, Family, Type, Module) ->
+ case prim_inet:fdopen(Protocol, Family, Type, Fd) of
{ok, S} ->
case prim_inet:setopts(S, Opts) of
ok ->
@@ -1056,18 +1093,24 @@ fdopen(Fd, Opts, Protocol, Family, Module) ->
%% socket stat
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-i() -> i(tcp), i(udp).
+i() -> i(tcp), i(udp), i(sctp).
i(Proto) -> i(Proto, [port, module, recv, sent, owner,
- local_address, foreign_address, state]).
+ local_address, foreign_address, state, type]).
i(tcp, Fs) ->
ii(tcp_sockets(), Fs, tcp);
i(udp, Fs) ->
- ii(udp_sockets(), Fs, udp).
+ ii(udp_sockets(), Fs, udp);
+i(sctp, Fs) ->
+ ii(sctp_sockets(), Fs, sctp).
ii(Ss, Fs, Proto) ->
- LLs = [h_line(Fs) | info_lines(Ss, Fs, Proto)],
+ LLs =
+ case info_lines(Ss, Fs, Proto) of
+ [] -> [];
+ InfoLines -> [h_line(Fs) | InfoLines]
+ end,
Maxs = foldl(
fun(Line,Max0) -> smax(Max0,Line) end,
duplicate(length(Fs),0),LLs),
@@ -1135,6 +1178,7 @@ info(S, F, Proto) ->
case prim_inet:gettype(S) of
{ok,{_,stream}} -> "STREAM";
{ok,{_,dgram}} -> "DGRAM";
+ {ok,{_,seqpacket}} -> "SEQPACKET";
_ -> " "
end;
fd ->
@@ -1186,6 +1230,7 @@ fmt_port(N, Proto) ->
%% Return a list of all tcp sockets
tcp_sockets() -> port_list("tcp_inet").
udp_sockets() -> port_list("udp_inet").
+sctp_sockets() -> port_list("sctp_inet").
%% Return all ports having the name 'Name'
port_list(Name) ->
@@ -1201,11 +1246,13 @@ port_list(Name) ->
%% utils
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec format_error(Posix) -> string() when
- Posix :: posix().
+-spec format_error(Reason) -> string() when
+ Reason :: posix() | system_limit.
format_error(exbadport) -> "invalid port state";
format_error(exbadseq) -> "bad command sequence";
+format_error(system_limit) ->
+ "a system limit was hit, probably not enough ports";
format_error(Tag) ->
erl_posix_msg:message(Tag).
@@ -1227,6 +1274,8 @@ udp_close(S) when is_port(S) ->
%% Set controlling process for TCP socket.
tcp_controlling_process(S, NewOwner) when is_port(S), is_pid(NewOwner) ->
case erlang:port_info(S, connected) of
+ {connected, NewOwner} ->
+ ok;
{connected, Pid} when Pid =/= self() ->
{error, not_owner};
undefined ->
@@ -1278,6 +1327,8 @@ tcp_sync_input(S, Owner, Flag) ->
%% Set controlling process for UDP or SCTP socket.
udp_controlling_process(S, NewOwner) when is_port(S), is_pid(NewOwner) ->
case erlang:port_info(S, connected) of
+ {connected, NewOwner} ->
+ ok;
{connected, Pid} when Pid =/= self() ->
{error, not_owner};
_ ->
@@ -1340,3 +1391,14 @@ stop_timer(Timer) ->
end;
T -> T
end.
+
+
+lock_socket(S,Val) ->
+ case erlang:port_info(S, connected) of
+ {connected, Pid} when Pid =/= self() ->
+ {error, not_owner};
+ undefined ->
+ {error, einval};
+ _ ->
+ prim_inet:ignorefd(S,Val)
+ end.
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index 5bf3fca647..c47483bbdd 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_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
@@ -32,7 +32,8 @@
-define(FAMILY, inet6).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
+-export([open/1,close/1,listen/2,peeloff/2,connect/5]).
+-export([sendmsg/3,send/4,recv/2]).
@@ -54,8 +55,8 @@ translate_ip(IP) ->
open(Opts) ->
case inet:sctp_options(Opts, ?MODULE) of
- {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,opts=SOs}} ->
- inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, ?MODULE);
+ {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,type=Type,opts=SOs}} ->
+ inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, Type, ?MODULE);
Error -> Error
end.
@@ -65,6 +66,14 @@ close(S) ->
listen(S, Flag) ->
prim_inet:listen(S, Flag).
+peeloff(S, AssocId) ->
+ case prim_inet:peeloff(S, AssocId) of
+ {ok, NewS}=Result ->
+ inet_db:register_socket(NewS, ?MODULE),
+ Result;
+ Error -> Error
+ end.
+
connect(S, Addr, Port, Opts, Timer) ->
inet_sctp:connect(S, Addr, Port, Opts, Timer).
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index cc45f6c7f6..c714b2bee0 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.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
@@ -93,7 +93,7 @@ do_connect(Addr = {A,B,C,D,E,F,G,H}, Port, Opts, Time) when
port=BPort,
opts=SockOpts}}
when ?ip6(Ab,Bb,Cb,Db,Eb,Fb,Gb,Hb), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,stream,?MODULE) of
{ok, S} ->
case prim_inet:connect(S, Addr, Port, Time) of
ok -> {ok,S};
@@ -115,7 +115,7 @@ listen(Port, Opts) ->
port=BPort,
opts=SockOpts}=R}
when ?ip6(A,B,C,D,E,F,G,H), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,stream,?MODULE) of
{ok, S} ->
case prim_inet:listen(S, R#listen_opts.backlog) of
ok -> {ok, S};
@@ -149,5 +149,5 @@ accept(L,Timeout) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, tcp, inet6, ?MODULE).
+ inet:fdopen(Fd, Opts, tcp, inet6, stream, ?MODULE).
diff --git a/lib/kernel/src/inet6_udp.erl b/lib/kernel/src/inet6_udp.erl
index e81d417151..ca43c94211 100644
--- a/lib/kernel/src/inet6_udp.erl
+++ b/lib/kernel/src/inet6_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
@@ -45,7 +45,7 @@ open(Port, Opts) ->
port=BPort,
opts=SockOpts}}
when ?ip6(A,B,C,D,E,F,G,H), ?port(BPort) ->
- inet:open(Fd,BAddr,BPort,SockOpts,udp,inet6,?MODULE);
+ inet:open(Fd,BAddr,BPort,SockOpts,udp,inet6,dgram,?MODULE);
{ok, _} -> exit(badarg)
end.
@@ -84,4 +84,4 @@ controlling_process(Socket, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, udp, inet6, ?MODULE).
+ inet:fdopen(Fd, Opts, udp, inet6, dgram, ?MODULE).
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 6f1688c6a2..cf893c73eb 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.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
@@ -29,7 +29,7 @@
-define(INET_AF_ANY, 3). % Fake for ANY in any address family
-define(INET_AF_LOOPBACK, 4). % Fake for LOOPBACK in any address family
-%% type codes (gettype, INET_REQ_GETTYPE)
+%% type codes to open and gettype - INET_REQ_GETTYPE
-define(INET_TYPE_STREAM, 1).
-define(INET_TYPE_DGRAM, 2).
-define(INET_TYPE_SEQPACKET, 3).
@@ -83,16 +83,21 @@
-define(INET_REQ_IFSET, 23).
-define(INET_REQ_SUBSCRIBE, 24).
-define(INET_REQ_GETIFADDRS, 25).
+-define(INET_REQ_ACCEPT, 26).
+-define(INET_REQ_LISTEN, 27).
+-define(INET_REQ_IGNOREFD, 28).
+
%% TCP requests
--define(TCP_REQ_ACCEPT, 40).
--define(TCP_REQ_LISTEN, 41).
+%%-define(TCP_REQ_ACCEPT, 40). MOVED
+%%-define(TCP_REQ_LISTEN, 41). MERGED
-define(TCP_REQ_RECV, 42).
-define(TCP_REQ_UNRECV, 43).
-define(TCP_REQ_SHUTDOWN, 44).
%% UDP and SCTP requests
-define(PACKET_REQ_RECV, 60).
--define(SCTP_REQ_LISTEN, 61).
+%%-define(SCTP_REQ_LISTEN, 61). MERGED
-define(SCTP_REQ_BINDX, 62). %% Multi-home SCTP bind
+-define(SCTP_REQ_PEELOFF, 63).
%% subscribe codes, INET_REQ_SUBSCRIBE
-define(INET_SUBS_EMPTY_OUT_Q, 1).
@@ -100,7 +105,7 @@
%% reply codes for *_REQ_*
-define(INET_REP_ERROR, 0).
-define(INET_REP_OK, 1).
--define(INET_REP_SCTP, 2).
+-define(INET_REP, 2).
%% INET, TCP and UDP options:
-define(INET_OPT_REUSEADDR, 0).
@@ -399,6 +404,7 @@
ifaddr,
port = 0,
fd = -1,
+ type = seqpacket,
opts = [{mode, binary},
{buffer, ?SCTP_DEF_BUFSZ},
{sndbuf, ?SCTP_DEF_BUFSZ},
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index de74b573bd..2d799d79fa 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_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
@@ -31,7 +31,8 @@
-define(FAMILY, inet).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
+-export([open/1,close/1,listen/2,peeloff/2,connect/5]).
+-export([sendmsg/3,send/4,recv/2]).
@@ -53,8 +54,8 @@ translate_ip(IP) ->
open(Opts) ->
case inet:sctp_options(Opts, ?MODULE) of
- {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,opts=SOs}} ->
- inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, ?MODULE);
+ {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,type=Type,opts=SOs}} ->
+ inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, Type, ?MODULE);
Error -> Error
end.
@@ -64,6 +65,14 @@ close(S) ->
listen(S, Flag) ->
prim_inet:listen(S, Flag).
+peeloff(S, AssocId) ->
+ case prim_inet:peeloff(S, AssocId) of
+ {ok, NewS}=Result ->
+ inet_db:register_socket(NewS, ?MODULE),
+ Result;
+ Error -> Error
+ end.
+
%% A non-blocking connect is implemented when the initial call is to
%% gen_sctp:connect_init which passes the value nowait as the Timer
connect(S, Addr, Port, Opts, Timer) ->
@@ -102,7 +111,7 @@ connect(S, Addr, Port, Opts, Timer) ->
connect_get_assoc(S, Addr, Port, false, Timer) ->
case recv(S, inet:timeout(Timer)) of
- {ok, {Addr, Port, [], #sctp_assoc_change{state=St}=Ev}} ->
+ {ok, {Addr, Port, _, #sctp_assoc_change{state=St}=Ev}} ->
if St =:= comm_up ->
%% Yes, successfully connected, return the whole
%% sctp_assoc_change event (containing, in particular,
@@ -123,7 +132,7 @@ connect_get_assoc(S, Addr, Port, false, Timer) ->
connect_get_assoc(S, Addr, Port, Active, Timer) ->
Timeout = inet:timeout(Timer),
receive
- {sctp,S,Addr,Port,{[],#sctp_assoc_change{state=St}=Ev}} ->
+ {sctp,S,Addr,Port,{_,#sctp_assoc_change{state=St}=Ev}} ->
case Active of
once ->
prim_inet:setopt(S, active, once);
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index 6dadccd6a9..4c2db16ce3 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.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
@@ -95,7 +95,7 @@ do_connect({A,B,C,D}, Port, Opts, Time) when ?ip(A,B,C,D), ?port(Port) ->
port=BPort,
opts=SockOpts}}
when ?ip(Ab,Bb,Cb,Db), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,stream,?MODULE) of
{ok, S} ->
case prim_inet:connect(S, {A,B,C,D}, Port, Time) of
ok -> {ok,S};
@@ -117,7 +117,7 @@ listen(Port, Opts) ->
port=BPort,
opts=SockOpts}=R}
when ?ip(A,B,C,D), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,stream,?MODULE) of
{ok, S} ->
case prim_inet:listen(S, R#listen_opts.backlog) of
ok -> {ok, S};
@@ -150,4 +150,4 @@ accept(L,Timeout) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, tcp, inet, ?MODULE).
+ inet:fdopen(Fd, Opts, tcp, inet, stream, ?MODULE).
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index 60bd96f332..80d930fe10 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -52,7 +52,7 @@ open(Port, Opts) ->
ifaddr=BAddr={A,B,C,D},
port=BPort,
opts=SockOpts}} when ?ip(A,B,C,D), ?port(BPort) ->
- inet:open(Fd,BAddr,BPort,SockOpts,udp,inet,?MODULE);
+ inet:open(Fd,BAddr,BPort,SockOpts,udp,inet,dgram,?MODULE);
{ok, _} -> exit(badarg)
end.
@@ -93,7 +93,7 @@ controlling_process(Socket, NewOwner) ->
fdopen(Fd, Opts) ->
inet:fdopen(Fd,
optuniquify([{recbuf, ?RECBUF} | Opts]),
- udp, inet, ?MODULE).
+ udp, inet, dgram, ?MODULE).
%% Remove all duplicate options from an option list.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 54a63833e6..bded2408a7 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -1 +1,27 @@
-{"%VSN%",[],[]}.
+%% -*- erlang -*-
+%% %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%
+{"%VSN%",
+ %% Up from - max two major revisions back
+ [{<<"2\\.15(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"2\\.14(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14
+ {<<"2\\.13(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R13
+ %% Down to - max two major revisions back
+ [{<<"2\\.15(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"2\\.14(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14
+ {<<"2\\.13(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R13
+}.
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index e214ffa404..a3fc57a124 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -286,7 +286,7 @@ call(N,M,F,A) ->
Reason :: term(),
Timeout :: timeout().
-call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call
+call(N,M,F,A,infinity) when node() =:= N -> %% Optimize local call
local_call(M,F,A);
call(N,M,F,A,infinity) ->
do_call(N, {call,M,F,A,group_leader()}, infinity);
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index c34f2ddeb0..8f2ca28f56 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.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
@@ -117,8 +117,9 @@ server1(Iport, Oport, Shell) ->
{Curr,Shell1} =
case init:get_argument(remsh) of
{ok,[[Node]]} ->
- RShell = {list_to_atom(Node),shell,start,[]},
- RGr = group:start(self(), RShell),
+ ANode = list_to_atom(Node),
+ RShell = {ANode,shell,start,[]},
+ RGr = group:start(self(), RShell, rem_sh_opts(ANode)),
{RGr,RShell};
E when E =:= error ; E =:= {ok,[[]]} ->
{group:start(self(), Shell),Shell}
@@ -134,6 +135,9 @@ server1(Iport, Oport, Shell) ->
%% Enter the server loop.
server_loop(Iport, Oport, Curr, User, Gr).
+rem_sh_opts(Node) ->
+ [{expand_fun,fun(B)-> rpc:call(Node,edlin_expand,expand,[B]) end}].
+
%% start_user()
%% Start a group leader process and register it as 'user', unless,
%% of course, a 'user' already exists.
diff --git a/lib/kernel/src/user_sup.erl b/lib/kernel/src/user_sup.erl
index 35b7ff0cfe..cb50d9491d 100644
--- a/lib/kernel/src/user_sup.erl
+++ b/lib/kernel/src/user_sup.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
@@ -45,7 +45,7 @@ init([]) ->
Pid = start_slave(Master),
{ok, Pid, Pid};
{M, F, A} ->
- case start_user({M, F}, A) of
+ case start_user(M, F, A) of
{ok, Pid} ->
{ok, Pid, Pid};
Error ->
@@ -95,8 +95,8 @@ terminate(_Reason, UserPid) ->
%% is guaranteed that the user is started.
%%-----------------------------------------------------------------
-start_user(Func,A) ->
- apply(Func, A),
+start_user(Mod, Func, A) ->
+ apply(Mod, Func, A),
wait_for_user_p(100).
wait_for_user_p(0) ->
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 82bc3fc6d1..7bb3e3a365 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -74,7 +74,8 @@ MODULES= \
wrap_log_reader_SUITE \
cleanup \
zlib_SUITE \
- loose_node
+ loose_node \
+ sendfile_SUITE
APP_FILES = \
appinc.app \
@@ -139,12 +140,12 @@ 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) $(APP_FILES) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(APP_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) kernel.spec $(EMAKEFILE)\
- $(COVERFILE) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(COVERFILE) "$(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 2c5b8ccb66..f469a0af98 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -33,7 +33,7 @@
-export([config_change/1,
distr_changed_tc1/1, distr_changed_tc2/1,
- shutdown_func/1, do_shutdown/1]).
+ shutdown_func/1, do_shutdown/1, shutdown_timeout/1]).
-define(TESTCASE, testcase_name).
-define(testcase, ?config(?TESTCASE, Config)).
@@ -50,7 +50,7 @@ all() ->
load_use_cache, {group, reported_bugs}, start_phases,
script_start, nodedown_start, permit_false_start_local,
permit_false_start_dist, get_key,
- {group, distr_changed}, config_change, shutdown_func].
+ {group, distr_changed}, config_change, shutdown_func, shutdown_timeout].
groups() ->
[{reported_bugs, [],
@@ -1915,6 +1915,32 @@ do_shutdown(Reason) ->
+%%%-----------------------------------------------------------------
+%%% Tests the 'shutdown_timeout' kernel config parameter
+%%%-----------------------------------------------------------------
+shutdown_timeout(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_timeout"),
+ wait_for_ready_net(),
+ ok = rpc:call(Cp1, application, set_env, [kernel, shutdown_timeout, 1000]),
+ rpc:call(Cp1, code, add_path, [filename:join([DataDir,deadlock])]),
+ ok = rpc:call(Cp1, application, start, [sasl]),
+ ok = rpc:call(Cp1, application, start, [deadlock]),
+ rpc:call(Cp1, deadlock, restart_and_fail, []),
+
+ ok = net_kernel:monitor_nodes(true),
+ _ = rpc:call(Cp1, init, stop, []),
+ receive
+ {nodedown,Cp1} ->
+ ok
+ after 10000 ->
+ ct:fail("timeout 10 sec: node termination hangs")
+ end,
+ ok.
+
+
+
+
%%-----------------------------------------------------------------
%% Utility functions
%%-----------------------------------------------------------------
diff --git a/lib/kernel/test/application_SUITE_data/Makefile.src b/lib/kernel/test/application_SUITE_data/Makefile.src
index a237f6badb..abc3c82907 100644
--- a/lib/kernel/test/application_SUITE_data/Makefile.src
+++ b/lib/kernel/test/application_SUITE_data/Makefile.src
@@ -2,7 +2,8 @@ EFLAGS=+debug_info
all: app_start_error.@EMULATOR@ trans_abnormal_sup.@EMULATOR@ \
trans_normal_sup.@EMULATOR@ transient.@EMULATOR@ \
- group_leader_sup.@EMULATOR@ group_leader.@EMULATOR@
+ group_leader_sup.@EMULATOR@ group_leader.@EMULATOR@ \
+ deadlock/deadlock.@EMULATOR@
app_start_error.@EMULATOR@: app_start_error.erl
erlc $(EFLAGS) app_start_error.erl
@@ -22,3 +23,5 @@ group_leader.@EMULATOR@: group_leader.erl
group_leader_sup.@EMULATOR@: group_leader_sup.erl
erlc $(EFLAGS) group_leader_sup.erl
+deadlock/deadlock.@EMULATOR@: deadlock/deadlock.erl
+ erlc $(EFLAGS) -o deadlock deadlock/deadlock.erl \ No newline at end of file
diff --git a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
new file mode 100644
index 0000000000..0c1001bed6
--- /dev/null
+++ b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
@@ -0,0 +1,8 @@
+{application, deadlock, [
+ {vsn, "1"},
+ {registered, []},
+ {applications, [kernel, stdlib, sasl]},
+ {modules, [deadlock]},
+ {mod, {deadlock, []}},
+ {env, [{fail_start, false}]}
+]}.
diff --git a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
new file mode 100644
index 0000000000..5f68bf9078
--- /dev/null
+++ b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
@@ -0,0 +1,69 @@
+-module(deadlock).
+-behaviour(application).
+-compile(export_all).
+-define(SUP,deadlock_sup).
+-define(CHILD,deadlock_child).
+
+
+%%%-----------------------------------------------------------------
+%%% application callbacks
+start(_StartType, _StartArgs) ->
+ supervisor:start_link({local, ?SUP}, ?MODULE, [sup]).
+
+stop(_State) ->
+ ok.
+
+
+
+%%%-----------------------------------------------------------------
+%%% supervisor callbacks
+init([sup]) ->
+ {ok, {{one_for_one, 5, 10}, [
+ {
+ sasl_syslog_dm, {?MODULE, start_link, []},
+ permanent, brutal_kill, worker,
+ [deadlock]
+ }
+ ]}};
+
+
+%%%-----------------------------------------------------------------
+%%% gen_server callbacks
+init([child]) ->
+ case application:get_env(deadlock, fail_start) of
+ {ok, false} ->
+ %% we must not fail on the first init, otherwise supervisor
+ %% terminates immediately
+ {ok, []};
+ {ok, true} ->
+ timer:sleep(infinity), % init hangs!!!!
+ {ok, []}
+ end.
+
+handle_call(_Req, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast(restart, State) ->
+ {stop, error, State}.
+
+handle_info(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% Start child
+start_link() ->
+ gen_server:start_link({local, ?CHILD}, ?MODULE, [child], []).
+
+
+%%%-----------------------------------------------------------------
+%%% Provoke hanging
+restart_and_fail() ->
+ application:set_env(deadlock, fail_start, true), % next init will hang
+ gen_server:cast(?CHILD, restart).
diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl
index 6276270d20..a2826f34df 100644
--- a/lib/kernel/test/bif_SUITE.erl
+++ b/lib/kernel/test/bif_SUITE.erl
@@ -260,23 +260,15 @@ spawn_opt2(Config) when is_list(Config) ->
?line P1 = spawn_opt(fun() ->
Parent ! {self(), fetch_proc_vals(self())}
end,
- case heap_type() of
- separate ->
- [{fullsweep_after, 0},{min_heap_size, 1000}];
- shared ->
- []
- end
- ++ [link, {priority, max}]),
+ [{fullsweep_after, 0},{min_heap_size, 1000},
+ link, {priority, max}]),
?line receive
{P1, PV1} ->
?line Node = node(P1),
?line check_proc_vals(true, max, 0, 1000, PV1)
end,
?line P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end,
- case heap_type() of
- separate -> [{min_heap_size, 10}];
- shared -> []
- end),
+ [{min_heap_size, 10}]),
?line receive
{P2, PV2} ->
?line Node = node(P2),
@@ -295,13 +287,8 @@ spawn_opt3(Config) when is_list(Config) ->
fun() ->
Parent ! {self(), fetch_proc_vals(self())}
end,
- case heap_type() of
- separate ->
- [{fullsweep_after,0}, {min_heap_size,1000}];
- shared ->
- []
- end
- ++ [link, {priority, max}]),
+ [{fullsweep_after,0}, {min_heap_size,1000},
+ link, {priority, max}]),
?line receive
{P1, PV1} ->
?line Node = node(P1),
@@ -309,10 +296,7 @@ spawn_opt3(Config) when is_list(Config) ->
end,
?line P2 = spawn_opt(Node,
fun() -> Parent ! {self(), fetch_proc_vals(self())} end,
- case heap_type() of
- separate -> [{min_heap_size, 10}];
- shared -> []
- end),
+ [{min_heap_size, 10}]),
?line receive
{P2, PV2} ->
?line Node = node(P2),
@@ -333,13 +317,8 @@ spawn_opt4(Config) when is_list(Config) ->
[fun() ->
Parent ! {self(), fetch_proc_vals(self())}
end],
- case heap_type() of
- separate ->
- [{fullsweep_after,0}, {min_heap_size,1000}];
- shared ->
- []
- end
- ++ [link, {priority, max}]),
+ [{fullsweep_after,0}, {min_heap_size,1000},
+ link, {priority, max}]),
?line receive
{P1, PV1} ->
?line Node = node(P1),
@@ -350,10 +329,7 @@ spawn_opt4(Config) when is_list(Config) ->
[fun() ->
Parent ! {self(), fetch_proc_vals(self())}
end],
- case heap_type() of
- separate -> [{min_heap_size, 10}];
- shared -> []
- end),
+ [{min_heap_size, 10}]),
?line receive
{P2, PV2} ->
?line Node = node(P2),
@@ -374,13 +350,8 @@ spawn_opt5(Config) when is_list(Config) ->
[fun() ->
Parent ! {self(), fetch_proc_vals(self())}
end],
- case heap_type() of
- separate ->
- [{fullsweep_after,0}, {min_heap_size,1000}];
- shared ->
- []
- end
- ++ [link, {priority, max}]),
+ [{fullsweep_after,0}, {min_heap_size,1000},
+ link, {priority, max}]),
?line receive
{P1, PV1} ->
?line Node = node(P1),
@@ -392,10 +363,7 @@ spawn_opt5(Config) when is_list(Config) ->
[fun() ->
Parent ! {self(), fetch_proc_vals(self())}
end],
- case heap_type() of
- separate -> [{min_heap_size, 10}];
- shared -> []
- end),
+ [{min_heap_size, 10}]),
?line receive
{P2, PV2} ->
?line Node = node(P2),
@@ -532,34 +500,19 @@ spawn_failures(Config) when is_list(Config) ->
check_proc_vals(Link, Priority, FullsweepAfter, MinHeapSize, {Ls, P, FA, HS}) ->
?line Link = lists:member(self(), Ls),
?line Priority = P,
- ?line case heap_type() of
- separate ->
- ?line FullsweepAfter = FA,
- ?line true = (HS >= MinHeapSize);
- shared ->
- ?line ok
- end,
+ FullsweepAfter = FA,
+ true = (HS >= MinHeapSize),
?line ok.
fetch_proc_vals(Pid) ->
?line PI = process_info(Pid),
?line {value,{links, Ls}} = lists:keysearch(links, 1, PI),
?line {value,{priority,P}} = lists:keysearch(priority, 1, PI),
- ?line {FA, HS}
- = case heap_type() of
- separate ->
- ?line {value,
- {garbage_collection,
- Gs}} = lists:keysearch(garbage_collection, 1, PI),
- ?line {value,
- {fullsweep_after,
- Fa}} = lists:keysearch(fullsweep_after, 1, Gs),
- ?line {value,
- {heap_size,Hs}} = lists:keysearch(heap_size, 1, PI),
- ?line {Fa, Hs};
- shared ->
- {undefined, undefined}
- end,
+ {value,{garbage_collection,Gs}} =
+ lists:keysearch(garbage_collection, 1, PI),
+ {value,{fullsweep_after,FA}} =
+ lists:keysearch(fullsweep_after, 1, Gs),
+ {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI),
?line {Ls, P, FA, HS}.
% This testcase should probably be moved somewhere else
@@ -650,12 +603,3 @@ stop_node(Node) ->
run_fun(Fun) ->
Fun().
-
-heap_type() ->
- case catch erlang:system_info(heap_type) of
- shared -> shared;
- unified -> shared;
- _ -> separate
- end.
-
-
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 10ab3e4370..827208b048 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
load_cached/1, start_node_with_cache/1, add_and_rehash/1,
where_is_file_cached/1, where_is_file_no_cache/1,
purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1,
- code_archive/1, code_archive2/1, on_load/1,
- big_boot_embedded/1,
- on_load_embedded/1, on_load_errors/1, native_early_modules/1]).
+ code_archive/1, code_archive2/1, on_load/1, on_load_binary/1,
+ on_load_embedded/1, on_load_errors/1, big_boot_embedded/1,
+ native_early_modules/1]).
-export([init_per_testcase/2, end_per_testcase/2,
init_per_suite/1, end_per_suite/1,
@@ -55,8 +55,8 @@ all() ->
add_and_rehash, where_is_file_no_cache,
where_is_file_cached, purge_stacktrace, mult_lib_roots,
bad_erl_libs, code_archive, code_archive2, on_load,
- on_load_embedded, big_boot_embedded, on_load_errors,
- native_early_modules].
+ on_load_binary, on_load_embedded, on_load_errors,
+ big_boot_embedded, native_early_modules].
groups() ->
[].
@@ -501,7 +501,7 @@ sticky_dir(doc) -> ["Test that a module with the same name as a module in ",
"a sticky directory cannot be loaded."];
sticky_dir(Config) when is_list(Config) ->
MyDir=filename:dirname(code:which(?MODULE)),
- ?line {ok, Node}=?t:start_node(sticky_dir, slave,[{args, "-pa "++MyDir}]),
+ ?line {ok, Node}=?t:start_node(sticky_dir, slave,[{args, "-pa \""++MyDir++"\""}]),
File=filename:join([?config(data_dir, Config), "calendar"]),
?line Ret=rpc:call(Node, ?MODULE, sticky_compiler, [File]),
case Ret of
@@ -822,7 +822,7 @@ load_cached(Config) when is_list(Config) ->
?line WD = filename:dirname(code:which(?MODULE)),
?line {ok,Node} =
?t:start_node(code_cache_node, peer, [{args,
- "-pa " ++ WD},
+ "-pa \"" ++ WD ++ "\""},
{erl, [this]}]),
CCTabCreated = fun(Tab) ->
case ets:info(Tab, name) of
@@ -907,7 +907,7 @@ add_and_rehash(Config) when is_list(Config) ->
?line WD = filename:dirname(code:which(?MODULE)),
?line {ok,Node} =
?t:start_node(code_cache_node, peer, [{args,
- "-pa " ++ WD},
+ "-pa \"" ++ WD ++ "\""},
{erl, [this]}]),
CCTabCreated = fun(Tab) ->
case ets:info(Tab, name) of
@@ -1286,6 +1286,45 @@ on_load_wait_for_all([Ref|T]) ->
end;
on_load_wait_for_all([]) -> ok.
+on_load_binary(_) ->
+ Master = on_load_binary_test_case_process,
+ register(Master, self()),
+
+ %% Construct, compile and pretty-print.
+ Mod = on_load_binary,
+ File = atom_to_list(Mod) ++ ".erl",
+ Forms = [{attribute,1,file,{File,1}},
+ {attribute,1,module,Mod},
+ {attribute,2,export,[{ok,0}]},
+ {attribute,3,on_load,{init,0}},
+ {function,5,init,0,
+ [{clause,5,[],[],
+ [{op,6,'!',
+ {atom,6,Master},
+ {tuple,6,[{atom,6,Mod},{call,6,{atom,6,self},[]}]}},
+ {'receive',7,[{clause,8,[{atom,8,go}],[],[{atom,8,ok}]}]}]}]},
+ {function,11,ok,0,[{clause,11,[],[],[{atom,11,true}]}]}],
+ {ok,Mod,Bin} = compile:forms(Forms, [report]),
+ [io:put_chars(erl_pp:form(F)) || F <- Forms],
+
+ {Pid1,Ref1} = spawn_monitor(fun() ->
+ code:load_binary(Mod, File, Bin),
+ true = on_load_binary:ok()
+ end),
+ receive {Mod,OnLoadPid} -> ok end,
+ {Pid2,Ref2} = spawn_monitor(fun() ->
+ true = on_load_binary:ok()
+ end),
+ erlang:yield(),
+ OnLoadPid ! go,
+ receive {'DOWN',Ref1,process,Pid1,Exit1} -> ok end,
+ receive {'DOWN',Ref2,process,Pid2,Exit2} -> ok end,
+ normal = Exit1,
+ normal = Exit2,
+ true = code:delete(on_load_binary),
+ false = code:purge(on_load_binary),
+ ok.
+
on_load_embedded(Config) when is_list(Config) ->
try
on_load_embedded_1(Config)
@@ -1402,6 +1441,9 @@ filter_app("netconf",_) ->
% Safe has the same kind of error in the .app file as ic
filter_app("safe",_) ->
false;
+% Comte cannot be started in the "usual" way
+filter_app("comte",_) ->
+ false;
% OS_mon does not find it's port program when running cerl
filter_app("os_mon",true) ->
false;
@@ -1508,7 +1550,8 @@ native_early_modules_1(Architecture) ->
true ->
?line true = lists:all(fun code:is_module_native/1,
[ets,file,filename,gb_sets,gb_trees,
- hipe_unified_loader,lists,os,packages]),
+ %%hipe_unified_loader, no_native as workaround
+ lists,os,packages]),
ok
end.
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index ad987fe7a7..0c3f5c3514 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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 @@
evil/1,
- otp_6278/1]).
+ otp_6278/1, otp_10131/1]).
-export([head_fun/1, hf/0, lserv/1,
measure/0, init_m/1, xx/0, head_exit/0, slow_header/1]).
@@ -124,7 +124,7 @@
[halt_int, wrap_int, halt_ext, wrap_ext, read_mode, head,
notif, new_idx_vsn, reopen, block, unblock, open, close,
error, chunk, truncate, many_users, info, change_size,
- change_attribute, distribution, evil, otp_6278]).
+ change_attribute, distribution, evil, otp_6278, otp_10131]).
%% The following two lists should be mutually exclusive. To skip a case
%% on VxWorks altogether, use the kernel.spec.vxworks file instead.
@@ -153,7 +153,7 @@ all() ->
{group, open}, {group, close}, {group, error}, chunk,
truncate, many_users, {group, info},
{group, change_size}, change_attribute,
- {group, distribution}, evil, otp_6278].
+ {group, distribution}, evil, otp_6278, otp_10131].
groups() ->
[{halt_int, [], [halt_int_inf, {group, halt_int_sz}]},
@@ -4915,6 +4915,22 @@ otp_6278(Conf) when is_list(Conf) ->
end,
?line error_logger:delete_report_handler(?MODULE).
+otp_10131(suite) -> [];
+otp_10131(doc) -> ["OTP-10131. head_func type."];
+otp_10131(Conf) when is_list(Conf) ->
+ Dir = ?privdir(Conf),
+ Log = otp_10131,
+ File = filename:join(Dir, lists:concat([Log, ".LOG"])),
+ HeadFunc = {?MODULE, head_fun, [{ok,"head"}]},
+ {ok, Log} = disk_log:open([{name,Log},{file,File},
+ {head_func, HeadFunc}]),
+ HeadFunc = info(Log, head, undef),
+ HeadFunc2 = {?MODULE, head_fun, [{ok,"head2"}]},
+ ok = disk_log:change_header(Log, {head_func, HeadFunc2}),
+ HeadFunc2 = info(Log, head, undef),
+ ok = disk_log:close(Log),
+ ok.
+
mark(FileName, What) ->
{ok,Fd} = file:open(FileName, [raw, binary, read, write]),
{ok,_} = file:position(Fd, 4),
diff --git a/lib/kernel/test/erl_boot_server_SUITE.erl b/lib/kernel/test/erl_boot_server_SUITE.erl
index cea3715ce4..bb64c01058 100644
--- a/lib/kernel/test/erl_boot_server_SUITE.erl
+++ b/lib/kernel/test/erl_boot_server_SUITE.erl
@@ -346,7 +346,7 @@ good_hosts(_Config) ->
[GoodHost1, GoodHost2, GoodHost3].
open_udp() ->
- ?line {ok, S} = prim_inet:open(udp, inet),
+ ?line {ok, S} = prim_inet:open(udp, inet, dgram),
?line ok = prim_inet:setopts(S, [{mode,list},{active,true},
{deliver,term},{broadcast,true}]),
?line {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0),
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 7599a89779..72239641e9 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -175,10 +175,10 @@ wait_really_started(Node, N) ->
inet_disconnects(doc) -> ["Start a node using the 'inet' loading method, ",
"then lose the connection."];
inet_disconnects(Config) when is_list(Config) ->
- case os:type() of
- vxworks ->
- {comment, "VxWorks: tested separately"};
- _ ->
+ case test_server:is_native(erl_boot_server) of
+ true ->
+ {skip,"erl_boot_server is native"};
+ false ->
?line Name = erl_prim_test_inet_disconnects,
?line Host = host(),
?line Cookie = atom_to_list(erlang:get_cookie()),
@@ -426,7 +426,9 @@ primary_archive(Config) when is_list(Config) ->
ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"],
io:format("ExpectedEbins: ~p\n", [ExpectedEbins]),
?line {ok, FileInfo} = prim_file:read_file_info(Archive),
- ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, [Archive, ArchiveBin, FileInfo]),
+ ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive,
+ [Archive, ArchiveBin, FileInfo,
+ fun escript:parse_file/1]),
?line ExpectedEbins = lists:sort(Ebins), % assert
?line {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]),
@@ -435,7 +437,9 @@ primary_archive(Config) when is_list(Config) ->
?line ok = test_archive(Node, Archive, DictDir, BeamName),
%% Cleanup
- ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, [undefined, undefined, undefined]),
+ ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive,
+ [undefined, undefined, undefined,
+ fun escript:parse_file/1]),
?line stop_node(Node),
?line ok = file:delete(Archive),
ok.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 77fc7e73f9..2b6af7e1fb 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,7 +78,7 @@
-export([altname/1]).
--export([large_file/1]).
+-export([large_file/1, large_write/1]).
-export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]).
@@ -92,6 +92,8 @@
-export([bytes/2, iterate/3]).
+%% System probe functions that might be handy to check from the shell
+-export([disc_free/1, memsize/0]).
-include_lib("test_server/include/test_server.hrl").
-include_lib("kernel/include/file.hrl").
@@ -106,7 +108,7 @@ all() ->
{group, compression}, {group, links}, copy,
delayed_write, read_ahead, segment_read, segment_write,
ipread, pid2name, interleaved_read_write, otp_5814,
- large_file, read_line_1, read_line_2, read_line_3,
+ large_file, large_write, read_line_1, read_line_2, read_line_3,
read_line_4, standard_io].
groups() ->
@@ -143,6 +145,13 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) when is_list(Config) ->
+ SaslConfig = case application:start(sasl) of
+ {error, {already_started, sasl}} ->
+ [];
+ ok ->
+ [{sasl,started}]
+ end,
+ ok = application:start(os_mon),
case os:type() of
{win32, _} ->
Priv = ?config(priv_dir, Config),
@@ -154,9 +163,9 @@ init_per_suite(Config) when is_list(Config) ->
{ok, _} ->
[]
end,
- ?FILE_INIT(HasAccessTime++Config);
+ ?FILE_INIT(HasAccessTime++Config++SaslConfig);
_ ->
- ?FILE_INIT(Config)
+ ?FILE_INIT(Config++SaslConfig)
end.
end_per_suite(Config) when is_list(Config) ->
@@ -166,6 +175,13 @@ end_per_suite(Config) when is_list(Config) ->
_ ->
ok
end,
+ application:stop(os_mon),
+ case proplists:get_value(sasl, Config) of
+ started ->
+ application:stop(sasl);
+ _Else ->
+ ok
+ end,
?FILE_FINI(Config).
init_per_testcase(_Func, Config) ->
@@ -394,6 +410,7 @@ make_del_dir(Config) when is_list(Config) ->
%% Don't worry ;-) the parent directory should never be empty, right?
?line case ?FILE_MODULE:del_dir('..') of
{error, eexist} -> ok;
+ {error, eacces} -> ok; %OpenBSD
{error, einval} -> ok %FreeBSD
end,
?line {error, enoent} = ?FILE_MODULE:del_dir(""),
@@ -3144,12 +3161,12 @@ ipread_int(Dir, ModeList) ->
{fun (Bin) when is_binary(Bin) -> Bin;
(List) when is_list(List) -> list_to_binary(List)
end,
- {erlang, size}};
+ fun erlang:byte_size/1};
false ->
{fun (Bin) when is_binary(Bin) -> binary_to_list(Bin);
(List) when is_list(List) -> List
end,
- {erlang, length}}
+ fun erlang:length/1}
end,
?line Pos = 4711,
?line Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"),
@@ -3287,50 +3304,13 @@ large_file(suite) ->
large_file(doc) ->
["Tests positioning in large files (> 4G)"];
large_file(Config) when is_list(Config) ->
- case {os:type(),os:version()} of
- {{win32,nt},_} ->
- do_large_file(Config);
- {{unix,sunos},{A,B,C}}
- when A == 5, B == 5, C >= 1; A == 5, B >= 6; A >= 6 ->
- do_large_file(Config);
- {{unix,Unix},_} when Unix =/= sunos ->
- N = unix_free(Config),
- io:format("Free: ~w KByte~n", [N]),
- if N < 5 * (1 bsl 20) ->
- %% Less than 5 GByte free
- {skipped,"Less than 5 GByte free"};
- true ->
- do_large_file(Config)
- end;
- _ ->
- {skipped,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
- end.
+ run_large_file_test(Config,
+ fun(Name) -> do_large_file(Name) end,
+ "_large_file").
-unix_free(Config) ->
- Cmd = ["df -k '",?config(priv_dir, Config),"'"],
- DF0 = os:cmd(Cmd),
- io:format("$ ~s~n~s", [Cmd,DF0]),
- [$\n|DF1] = lists:dropwhile(fun ($\n) -> false; (_) -> true end, DF0),
- {ok,[N],_} = io_lib:fread(" ~*s ~d", DF1),
- N.
+do_large_file(Name) ->
+ ?line Watchdog = ?t:timetrap(?t:minutes(20)),
-do_large_file(Config) ->
- ?line Watchdog = ?t:timetrap(?t:minutes(5)),
- %%
- ?line Name = filename:join(?config(priv_dir, Config),
- ?MODULE_STRING ++ "_large_file"),
- ?line Tester = self(),
- Deleter =
- spawn(
- fun() ->
- Mref = erlang:monitor(process, Tester),
- receive
- {'DOWN',Mref,_,_,_} -> ok;
- {Tester,done} -> ok
- end,
- ?FILE_MODULE:delete(Name)
- end),
- %%
?line S = "1234567890",
L = length(S),
R = lists:reverse(S),
@@ -3366,15 +3346,36 @@ do_large_file(Config) ->
?line {ok,R} = ?FILE_MODULE:read(F1, L+1),
?line ok = ?FILE_MODULE:close(F1),
%%
- ?line Mref = erlang:monitor(process, Deleter),
- ?line Deleter ! {Tester,done},
- ?line receive {'DOWN',Mref,_,_,_} -> ok end,
- %%
?line ?t:timetrap_cancel(Watchdog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+large_write(Config) when is_list(Config) ->
+ run_large_file_test(Config,
+ fun(Name) -> do_large_write(Name) end,
+ "_large_write").
+
+do_large_write(Name) ->
+ Memsize = memsize(),
+ io:format("Memsize = ~w Bytes~n", [Memsize]),
+ case {erlang:system_info(wordsize),Memsize} of
+ {4,_} ->
+ {skip,"Needs a 64-bit emulator"};
+ {8,N} when N < 6 bsl 30 ->
+ {skip,
+ "This machine has < 6 GB memory: "
+ ++integer_to_list(N)};
+ {8,_} ->
+ Size = 4*1024*1024*1024+1,
+ Bin = <<0:Size/unit:8>>,
+ ok = file:write_file(Name, Bin),
+ {ok,#file_info{size=Size}} = file:read_file_info(Name),
+ ok
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
response_analysis(Module, Function, Arguments) ->
@@ -3950,3 +3951,67 @@ flush(Msgs) ->
after 0 ->
lists:reverse(Msgs)
end.
+
+%%%
+%%% Support for testing large files.
+%%%
+
+run_large_file_test(Config, Run, Name) ->
+ case {os:type(),os:version()} of
+ {{win32,nt},_} ->
+ do_run_large_file_test(Config, Run, Name);
+ {{unix,sunos},OsVersion} when OsVersion < {5,5,1} ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"};
+ {{unix,_},_} ->
+ N = disc_free(?config(priv_dir, Config)),
+ io:format("Free disk: ~w KByte~n", [N]),
+ if N < 5 * (1 bsl 20) ->
+ %% Less than 5 GByte free
+ {skip,"Less than 5 GByte free"};
+ true ->
+ do_run_large_file_test(Config, Run, Name)
+ end;
+ _ ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
+ end.
+
+
+do_run_large_file_test(Config, Run, Name0) ->
+ Name = filename:join(?config(priv_dir, Config),
+ ?MODULE_STRING ++ Name0),
+
+ %% Set up a process that will delete this file.
+ Tester = self(),
+ Deleter =
+ spawn(
+ fun() ->
+ Mref = erlang:monitor(process, Tester),
+ receive
+ {'DOWN',Mref,_,_,_} -> ok;
+ {Tester,done} -> ok
+ end,
+ ?FILE_MODULE:delete(Name)
+ end),
+
+ %% Run the test case.
+ Res = Run(Name),
+
+ %% Delete file and finish deleter process.
+ Mref = erlang:monitor(process, Deleter),
+ Deleter ! {Tester,done},
+ receive {'DOWN',Mref,_,_,_} -> ok end,
+
+ Res.
+
+disc_free(Path) ->
+ Data = disksup:get_disk_data(),
+ {_,Tot,Perc} = hd(lists:filter(
+ fun({P,_Size,_Full}) ->
+ lists:prefix(filename:nativename(P),
+ filename:nativename(Path))
+ end, lists:reverse(lists:sort(Data)))),
+ round(Tot * (1-(Perc/100))).
+
+memsize() ->
+ {Tot,_Used,_} = memsup:get_memory_data(),
+ Tot.
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 53bcb1162d..be33ec2c06 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -74,7 +74,7 @@
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([normal/1,icky/1,very_icky/1,normalize/1]).
+-export([normal/1,icky/1,very_icky/1,normalize/1,home_dir/1]).
init_per_testcase(_Func, Config) ->
@@ -88,7 +88,7 @@ end_per_testcase(_Func, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [normal, icky, very_icky, normalize].
+ [normal, icky, very_icky, normalize, home_dir].
groups() ->
[].
@@ -105,6 +105,54 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+home_dir(suite) ->
+ [];
+home_dir(doc) ->
+ ["Check that Erlang can be started with unicode named home directory"];
+home_dir(Config) when is_list(Config) ->
+ try
+ Name=[960,945,964,961,953,954],
+ Priv = ?config(priv_dir, Config),
+ UniMode = file:native_name_encoding() =/= latin1,
+ if
+ not UniMode ->
+ throw(need_unicode_mode);
+ true ->
+ ok
+ end,
+ NewHome=filename:join(Priv,Name),
+ file:make_dir(NewHome),
+ {SaveOldName,SaveOldValue} = case os:type() of
+ {win32,nt} ->
+ HomePath=re:replace(filename:nativename(NewHome),"^[a-zA-Z]:","",[{return,list},unicode]),
+ Save = os:getenv("HOMEPATH"),
+ os:putenv("HOMEPATH",HomePath),
+ {"HOMEPATH",Save};
+ {unix,_} ->
+ Save = os:getenv("HOME"),
+ os:putenv("HOME",NewHome),
+ {"HOME",Save};
+ _ ->
+ rm_rf(prim_file,NewHome),
+ throw(unsupported_os)
+ end,
+ try
+ {ok,Node} = test_server:start_node(test_unicode_homedir,slave,[{args,"-setcookie "++atom_to_list(erlang:get_cookie())}]),
+ test_server:stop_node(Node),
+ ok
+ after
+ os:putenv(SaveOldName,SaveOldValue),
+ rm_rf(prim_file,NewHome)
+ end
+ catch
+ throw:need_unicode_mode ->
+ io:format("Sorry, can only run in unicode mode.~n"),
+ {skipped,"VM needs to be started in Unicode filename mode"};
+ throw:unsupported_os ->
+ io:format("Sorry, can only run on Unix/Windows.~n"),
+ {skipped,"Runs only on Unix/Windows"}
+ end.
+
normalize(suite) ->
[];
normalize(doc) ->
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 1b534a5fc4..f4bf6e719e 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -30,33 +30,39 @@
-export(
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
- xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1]).
+ xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
+ basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1,
+ open_multihoming_ipv4_socket/1,
+ open_unihoming_ipv6_socket/1,
+ open_multihoming_ipv6_socket/1,
+ open_multihoming_ipv4_and_ipv6_socket/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
- api_opts, xfer_min, xfer_active, def_sndrcvinfo,
- implicit_inet6].
+ api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
+ basic_stream, xfer_stream_min, peeloff, buffers,
+ open_multihoming_ipv4_socket,
+ open_unihoming_ipv6_socket,
+ open_multihoming_ipv6_socket,
+ open_multihoming_ipv4_and_ipv6_socket].
groups() ->
[].
-init_per_suite(Config) ->
- try gen_sctp:open() of
+init_per_suite(_Config) ->
+ case gen_sctp:open() of
{ok,Socket} ->
gen_sctp:close(Socket),
[];
- _ ->
- []
- catch
- error:badarg ->
- {skip,"SCTP not supported on this machine"};
- _:_ ->
- Config
+ {error,Error}
+ when Error =:= eprotonosupport;
+ Error =:= esocktnosupport ->
+ {skip,"SCTP not supported on this machine"}
end.
-end_per_suite(_Conifig) ->
+end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
@@ -96,7 +102,7 @@ xfer_min(Config) when is_list(Config) ->
?line Stream = 0,
?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
?line Loopback = {127,0,0,1},
- ?line {ok,Sb} = gen_sctp:open(),
+ ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
?line {ok,Pb} = inet:port(Sb),
?line ok = gen_sctp:listen(Sb, true),
@@ -108,29 +114,44 @@ xfer_min(Config) when is_list(Config) ->
inbound_streams=SaInboundStreams,
assoc_id=SaAssocId}=SaAssocChange} =
gen_sctp:connect(Sa, Loopback, Pb, []),
- ?line {ok,{Loopback,
- Pa,[],
+ ?line {SbAssocId,SaOutboundStreams,SaInboundStreams} =
+ case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
+ {Loopback,Pa,
#sctp_assoc_change{state=comm_up,
error=0,
outbound_streams=SbOutboundStreams,
inbound_streams=SbInboundStreams,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line SaOutboundStreams = SbInboundStreams,
- ?line SbOutboundStreams = SaInboundStreams,
+ assoc_id=AssocId}} ->
+ {AssocId,SbInboundStreams,SbOutboundStreams};
+ {Loopback,Pa,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=AssocId}} ->
+ {Loopback,Pa,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=AssocId}} =
+ ?line recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ {AssocId,SbInboundStreams,SbOutboundStreams}
+ end,
+
?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
- ?line case gen_sctp:recv(Sb, infinity) of
- {ok,{Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok;
- {ok,{Loopback,
- Pa,[],
+ ?line case log_ok(gen_sctp:recv(Sb, infinity)) of
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} -> ok;
+ Event1 ->
+ {Loopback,Pa,
#sctp_paddr_change{addr = {Loopback,_},
state = addr_available,
error = 0,
- assoc_id = SbAssocId}}} ->
+ assoc_id = SbAssocId}} =
+ recv_event(Event1),
{ok,{Loopback,
Pa,
[#sctp_sndrcvinfo{stream=Stream,
@@ -138,30 +159,40 @@ xfer_min(Config) when is_list(Config) ->
Data}} = gen_sctp:recv(Sb, infinity)
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
- ?line {ok,{Loopback,
- Pb,
+ ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
- Data}} =
- gen_sctp:recv(Sa, infinity),
+ Data} ->
+ ok;
+ Event2 ->
+ {Loopback,Pb,
+ #sctp_paddr_change{addr={_,Pb},
+ state=addr_confirmed,
+ error=0,
+ assoc_id=SaAssocId}} =
+ ?line recv_event(Event2),
+ ?line {Loopback,
+ Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ log_ok(gen_sctp:recv(Sa, infinity))
+ end,
%%
?line ok = gen_sctp:eof(Sa, SaAssocChange),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_shutdown_event{assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line {ok,{Loopback,
- Pb,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SaAssocId}}} =
- gen_sctp:recv(Sa, infinity),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
+ ?line {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ ?line {Loopback,Pb,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
+ ?line {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
@@ -186,32 +217,52 @@ xfer_active(Config) when is_list(Config) ->
?line {ok,Sa} = gen_sctp:open([{active,true}]),
?line {ok,Pa} = inet:port(Sa),
- ?line {ok,#sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId}=SaAssocChange} =
- gen_sctp:connect(Sa, Loopback, Pb, []),
+ ?line ok = gen_sctp:connect_init(Sa, Loopback, Pb, []),
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId} = SaAssocChange =
+ recv_assoc_change(Sa, Loopback, Pb, Timeout),
?line io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, "
"SaOutboundStreams=~p, SaInboundStreams=~p~n",
[Sa,Pa,Sb,Pb,SaAssocId,
SaOutboundStreams,SaInboundStreams]),
- ?line SbAssocId =
- receive
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SbOutboundStreams,
- inbound_streams=SbInboundStreams,
- assoc_id=SBAI}}} ->
- ?line SaOutboundStreams = SbInboundStreams,
- ?line SaInboundStreams = SbOutboundStreams,
- SBAI
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
- end,
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=SbAssocId} =
+ recv_assoc_change(Sb, Loopback, Pa, Timeout),
+ ?line SbOutboundStreams = SaInboundStreams,
+ ?line SbInboundStreams = SaOutboundStreams,
?line io:format("SbAssocId=~p~n", [SbAssocId]),
+
+ ?line case recv_paddr_change(Sa, Loopback, Pb, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ timeout -> ok
+ end,
+ ?line case recv_paddr_change(Sb, Loopback, Pa, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=SbAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={Loopback,P},
+ error=0,
+ assoc_id=SbAssocId} ->
+ ?line match_unless_solaris(Pa, P);
+ timeout -> ok
+ end,
+ ?line [] = flush(),
+
?line ok =
do_from_other_process(
fun () -> gen_sctp:send(Sa, SaAssocId, 0, Data) end),
@@ -219,21 +270,9 @@ xfer_active(Config) when is_list(Config) ->
{sctp,Sb,Loopback,Pa,
{[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SbAssocId}],
- Data}} -> ok;
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_paddr_change{addr = {Loopback,_},
- state = addr_available,
- error = 0,
- assoc_id = SbAssocId}}} ->
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok
- end
+ Data}} -> ok
after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
?line receive
@@ -242,31 +281,28 @@ xfer_active(Config) when is_list(Config) ->
assoc_id=SaAssocId}],
Data}} -> ok
after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
%%
?line ok = gen_sctp:abort(Sa, SaAssocChange),
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SbAssocId}}} -> ok
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line case recv_assoc_change(Sb, Loopback, Pa, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SbAssocId} -> ok;
+ timeout ->
+ ?line test_server:fail({timeout,flush()})
end,
?line ok = gen_sctp:close(Sb),
+ ?line case recv_assoc_change(Sa, Loopback, Pb, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SaAssocId} -> ok;
+ timeout ->
+ ?line io:format("timeout waiting for comm_lost on Sa~n"),
+ ?line match_unless_solaris(ok, {timeout,flush()})
+ end,
?line receive
- {sctp,Sa,Loopback,Pb,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SaAssocId}}} -> ok
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
- end,
- ?line receive
- {sctp_error,Sa,enotconn} -> ok % Solaris
- after 17 -> ok %% Only happens on Solaris
- end,
+ {sctp_error,Sa,enotconn} -> ok % Solaris
+ after 17 -> ok
+ end,
?line ok = gen_sctp:close(Sa),
%%
?line receive
@@ -275,6 +311,30 @@ xfer_active(Config) when is_list(Config) ->
end,
ok.
+recv_assoc_change(S, Addr, Port, Timeout) ->
+ receive
+ {sctp,S,Addr,Port,{[], #sctp_assoc_change{}=AssocChange}} ->
+ AssocChange;
+ {sctp,S,Addr,Port,
+ {[#sctp_sndrcvinfo{assoc_id=AssocId}],
+ #sctp_assoc_change{assoc_id=AssocId}=AssocChange}} ->
+ AssocChange
+ after Timeout ->
+ timeout
+ end.
+
+recv_paddr_change(S, Addr, Port, Timeout) ->
+ receive
+ {sctp,S,Addr,Port,{[], #sctp_paddr_change{}=PaddrChange}} ->
+ PaddrChange;
+ {sctp,S,Addr,Port,
+ {[#sctp_sndrcvinfo{assoc_id=AssocId}],
+ #sctp_paddr_change{assoc_id=AssocId}=PaddrChange}} ->
+ PaddrChange
+ after Timeout ->
+ timeout
+ end.
+
def_sndrcvinfo(doc) ->
"Test that #sctp_sndrcvinfo{} parameters set on a socket "
"are used by gen_sctp:send/4";
@@ -285,11 +345,11 @@ def_sndrcvinfo(Config) when is_list(Config) ->
?line Data = <<"What goes up, must come down.">>,
%%
?line S1 =
- ok(gen_sctp:open(
+ log_ok(gen_sctp:open(
0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])),
?LOGVAR(S1),
?line P1 =
- ok(inet:port(S1)),
+ log_ok(inet:port(S1)),
?LOGVAR(P1),
?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
getopt(S1, sctp_default_send_param),
@@ -297,10 +357,10 @@ def_sndrcvinfo(Config) when is_list(Config) ->
gen_sctp:listen(S1, true),
%%
?line S2 =
- ok(gen_sctp:open()),
+ log_ok(gen_sctp:open()),
?LOGVAR(S2),
?line P2 =
- ok(inet:port(S2)),
+ log_ok(inet:port(S2)),
?LOGVAR(P2),
?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
getopt(S2, sctp_default_send_param),
@@ -309,32 +369,57 @@ def_sndrcvinfo(Config) when is_list(Config) ->
state=comm_up,
error=0,
assoc_id=S2AssocId} = S2AssocChange =
- ok(gen_sctp:connect(S2, Loopback, P1, [])),
+ log_ok(gen_sctp:connect(S2, Loopback, P1, [])),
?LOGVAR(S2AssocChange),
- ?line case ok(gen_sctp:recv(S1)) of
- {Loopback, P2,[],
+ ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
+ {Loopback,P2,
#sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId);
+ {Loopback,P2,
+ #sctp_paddr_change{
+ state=addr_confirmed,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId),
+ {Loopback,P2,
+ #sctp_assoc_change{
state=comm_up,
error=0,
- assoc_id=S1AssocId}} ->
- ?LOGVAR(S1AssocId)
+ assoc_id=S1AssocId}} =
+ recv_event(log_ok(gen_sctp:recv(S1)))
end,
+
?line #sctp_sndrcvinfo{
- ppid=17, context=0, timetolive=0, assoc_id=S1AssocId} =
+ ppid=17, context=0, timetolive=0} = %, assoc_id=S1AssocId} =
getopt(
S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
?line #sctp_sndrcvinfo{
- ppid=0, context=0, timetolive=0, assoc_id=S2AssocId} =
+ ppid=0, context=0, timetolive=0} = %, assoc_id=S2AssocId} =
getopt(
S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}),
%%
?line ok =
gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S2)) of
+ ?line case log_ok(gen_sctp:recv(S2)) of
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
- <<"1: ",Data/binary>>} -> ok
+ <<"1: ",Data/binary>>} -> ok;
+ Event1 ->
+ ?line {Loopback,P1,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,P1},
+ error=0,
+ assoc_id=S2AssocId}} =
+ recv_event(Event1),
+ ?line {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+ <<"1: ",Data/binary>>} =
+ log_ok(gen_sctp:recv(S2))
end,
%%
?line ok =
@@ -354,7 +439,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
%%
?line ok =
gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S2)) of
+ ?line case log_ok(gen_sctp:recv(S2)) of
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
@@ -362,16 +447,18 @@ def_sndrcvinfo(Config) when is_list(Config) ->
end,
?line ok =
gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S1)) of
+ ?line case log_ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
<<"3: ",Data/binary>>} -> ok;
- {Loopback,P2,[],
- #sctp_paddr_change{
- addr={Loopback,_}, state=addr_available,
- error=0, assoc_id=S1AssocId}} ->
- ?line case ok(gen_sctp:recv(S1)) of
+ Event2 ->
+ {Loopback,P2,
+ #sctp_paddr_change{
+ addr={Loopback,_}, state=addr_available,
+ error=0, assoc_id=S1AssocId}} =
+ recv_event(Event2),
+ ?line case log_ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0,
@@ -387,7 +474,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
#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
+ ?line case log_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}],
@@ -416,8 +503,12 @@ getopt(S, Opt, Param) ->
setopt(S, Opt, Val) ->
inet:setopts(S, [{Opt,Val}]).
-ok({ok,X}) ->
- io:format("OK: ~p~n", [X]),
+log_ok(X) -> log(ok(X)).
+
+ok({ok,X}) -> X.
+
+log(X) ->
+ io:format("LOG[~w]: ~p~n", [self(),X]),
X.
flush() ->
@@ -520,7 +611,10 @@ api_listen(Config) when is_list(Config) ->
#sctp_assoc_change{
state=comm_lost}}} =
gen_sctp:recv(Sa, infinity);
- {error,#sctp_assoc_change{state=cant_assoc}} -> ok
+ {error,#sctp_assoc_change{state=cant_assoc}} ->
+ ok%;
+ %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} ->
+ %% ok
end,
?line ok = gen_sctp:listen(Sb, true),
?line {ok,#sctp_assoc_change{state=comm_up,
@@ -552,29 +646,41 @@ api_connect_init(Config) when is_list(Config) ->
?line {ok,Sa} = gen_sctp:open(),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
{error,econnrefused} ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{state=comm_lost}}} =
- gen_sctp:recv(Sa, infinity);
+ ?line {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)));
ok ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{state=cant_assoc}}} =
- gen_sctp:recv(Sa, infinity)
+ ?line {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:listen(Sb, true),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
ok ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{
- state = comm_up}}} =
- gen_sctp:recv(Sa, infinity)
+ ?line {Localhost,Pb,#sctp_assoc_change{state=comm_up}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
ok.
+recv_event({Addr,Port,[],#sctp_assoc_change{}=AssocChange}) ->
+ {Addr,Port,AssocChange};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_assoc_change{assoc_id=Assoc}=AssocChange}) ->
+ {Addr,Port,AssocChange};
+recv_event({Addr,Port,[],#sctp_paddr_change{}=PaddrChange}) ->
+ {Addr,Port,PaddrChange};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_paddr_change{assoc_id=Assoc}=PaddrChange}) ->
+ {Addr,Port,PaddrChange};
+recv_event({Addr,Port,[],#sctp_shutdown_event{}=ShutdownEvent}) ->
+ {Addr,Port,ShutdownEvent};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_shutdown_event{assoc_id=Assoc}=ShutdownEvent}) ->
+ {Addr,Port,ShutdownEvent}.
+
api_opts(doc) ->
"Test socket options";
api_opts(suite) ->
@@ -600,7 +706,7 @@ api_opts(Config) when is_list(Config) ->
end.
implicit_inet6(Config) when is_list(Config) ->
- ?line Hostname = ok(inet:gethostname()),
+ ?line Hostname = log_ok(inet:gethostname()),
?line
case gen_sctp:open(0, [inet6]) of
{ok,S1} ->
@@ -613,16 +719,16 @@ implicit_inet6(Config) when is_list(Config) ->
?line ok = gen_sctp:close(S1),
%%
?line Localhost =
- ok(inet:getaddr("localhost", inet6)),
+ log_ok(inet:getaddr("localhost", inet6)),
?line io:format("~s ~p~n", ["localhost",Localhost]),
?line S2 =
- ok(gen_sctp:open(0, [{ip,Localhost}])),
+ log_ok(gen_sctp:open(0, [{ip,Localhost}])),
?line implicit_inet6(S2, Localhost),
?line ok = gen_sctp:close(S2),
%%
?line io:format("~s ~p~n", [Hostname,Host]),
?line S3 =
- ok(gen_sctp:open(0, [{ifaddr,Host}])),
+ log_ok(gen_sctp:open(0, [{ifaddr,Host}])),
?line implicit_inet6(S3, Host),
?line ok = gen_sctp:close(S1);
{error,eafnosupport} ->
@@ -635,25 +741,159 @@ implicit_inet6(Config) when is_list(Config) ->
implicit_inet6(S1, Addr) ->
?line ok = gen_sctp:listen(S1, true),
- ?line P1 = ok(inet:port(S1)),
- ?line S2 = ok(gen_sctp:open(0, [inet6])),
- ?line P2 = ok(inet:port(S2)),
+ ?line P1 = log_ok(inet:port(S1)),
+ ?line S2 = log_ok(gen_sctp:open(0, [inet6])),
+ ?line P2 = log_ok(inet:port(S2)),
?line #sctp_assoc_change{state=comm_up} =
- ok(gen_sctp:connect(S2, Addr, P1, [])),
- ?line case ok(gen_sctp:recv(S1)) of
- {Addr,P2,[],#sctp_assoc_change{state=comm_up}} ->
- ok
+ log_ok(gen_sctp:connect(S2, Addr, P1, [])),
+ ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} ->
+ ok;
+ {Addr,P2,#sctp_paddr_change{state=addr_confirmed,
+ addr={Addr,P2},
+ error=0}} ->
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} =
+ recv_event(log_ok(gen_sctp:recv(S1)))
end,
- ?line case ok(inet:sockname(S1)) of
+ ?line case log_ok(inet:sockname(S1)) of
{Addr,P1} -> ok;
{{0,0,0,0,0,0,0,0},P1} -> ok
end,
- ?line case ok(inet:sockname(S2)) of
+ ?line case log_ok(inet:sockname(S2)) of
{Addr,P2} -> ok;
{{0,0,0,0,0,0,0,0},P2} -> ok
end,
?line ok = gen_sctp:close(S2).
+basic_stream(doc) ->
+ "Hello world stream socket";
+basic_stream(suite) ->
+ [];
+basic_stream(Config) when is_list(Config) ->
+ ?line {ok,S} = gen_sctp:open([{type,stream}]),
+ ?line ok = gen_sctp:listen(S, true),
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:listen(S, 10) end),
+ ?line ok = gen_sctp:close(S),
+ ok.
+
+xfer_stream_min(doc) ->
+ "Minimal data transfer";
+xfer_stream_min(suite) ->
+ [];
+xfer_stream_min(Config) when is_list(Config) ->
+ ?line Stream = 0,
+ ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
+ ?line Loopback = {127,0,0,1},
+ ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
+ ?line ?LOGVAR(Sb),
+ ?line {ok,Pb} = inet:port(Sb),
+ ?line ?LOGVAR(Pb),
+ ?line ok = gen_sctp:listen(Sb, true),
+
+ ?line {ok,Sa} = gen_sctp:open([{type,stream}]),
+ ?line ?LOGVAR(Sa),
+ ?line {ok,Pa} = inet:port(Sa),
+ ?line ?LOGVAR(Pa),
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId_X} =
+ log_ok(gen_sctp:connect(Sa, Loopback, Pb, [])),
+ ?line ?LOGVAR(SaAssocId_X),
+ ?line [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] =
+ log_ok(inet:getopts(Sa, [{sctp_get_peer_addr_info,
+ #sctp_paddrinfo{address={Loopback,Pb}}}])),
+ ?line ?LOGVAR(SaAssocId),
+ ?line match_unless_solaris(SaAssocId_X, SaAssocId),
+
+ ?line {SbOutboundStreams,SbInboundStreams,SbAssocId} =
+ case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
+ {Loopback,Pa,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} ->
+ {OS,IS,AI};
+ {Loopback,Pa,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=AI}} ->
+ {Loopback,Pa,
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ {OS,IS,AI}
+ end,
+ ?line ?LOGVAR(SbAssocId),
+ ?line SaOutboundStreams = SbInboundStreams,
+ ?line ?LOGVAR(SaOutboundStreams),
+ ?line SbOutboundStreams = SaInboundStreams,
+ ?line ?LOGVAR(SbOutboundStreams),
+ ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+ ?line case gen_sctp:recv(Sb, infinity) of
+ {ok,{Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} -> ok;
+ {ok,{Loopback,
+ Pa,[],
+ #sctp_paddr_change{addr = {Loopback,_},
+ state = addr_available,
+ error = 0,
+ assoc_id = SbAssocId}}} ->
+ {ok,{Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} = gen_sctp:recv(Sb, infinity)
+ end,
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end),
+ ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} -> ok;
+ Event1 ->
+ ?line {Loopback,Pb,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(Event1),
+ ?line {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ log_ok(gen_sctp:recv(Sa, infinity))
+ end,
+ ?line ok = gen_sctp:close(Sa),
+ ?line {Loopback,Pa,
+ #sctp_shutdown_event{assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ ?line {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ ?line ok = gen_sctp:close(Sb),
+
+ ?line receive
+ Msg -> test_server:fail({received,Msg})
+ after 17 -> ok
+ end,
+ ok.
+
do_from_other_process(Fun) ->
@@ -681,3 +921,605 @@ do_from_other_process(Fun) ->
{'DOWN',Mref,_,_,Reason} ->
erlang:exit(Reason)
end.
+
+
+
+peeloff(doc) ->
+ "Peel off an SCTP stream socket";
+peeloff(suite) ->
+ [];
+peeloff(Config) when is_list(Config) ->
+ ?line Addr = {127,0,0,1},
+ ?line Stream = 0,
+ ?line Timeout = 333,
+ ?line S1 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line ?LOGVAR(S1),
+ ?line P1 = socket_call(S1, get_port),
+ ?line ?LOGVAR(P1),
+ ?line Socket1 = socket_call(S1, get_socket),
+ ?line ?LOGVAR(Socket1),
+ ?line socket_call(S1, {listen,true}),
+ ?line S2 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line ?LOGVAR(S2),
+ ?line P2 = socket_call(S2, get_port),
+ ?line ?LOGVAR(P2),
+ ?line Socket2 = socket_call(S2, get_socket),
+ ?line ?LOGVAR(Socket2),
+ %%
+ ?line socket_call(S2, {connect_init,Addr,P1,[]}),
+ ?line S2Ai =
+ receive
+ {S2,{Addr,P1,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line ?LOGVAR(S2Ai),
+ ?line S1Ai =
+ receive
+ {S1,{Addr,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line ?LOGVAR(S1Ai),
+ %%
+ ?line socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}),
+ ?line
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}),
+ ?line
+ receive
+ {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ %%
+ ?line S3 = socket_peeloff(Socket1, S1Ai, Timeout),
+ ?line ?LOGVAR(S3),
+ ?line P3_X = socket_call(S3, get_port),
+ ?line ?LOGVAR(P3_X),
+ ?line P3 = case P3_X of 0 -> P1; _ -> P3_X end,
+ ?line [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] =
+ socket_call(S3,
+ {getopts,[{sctp_get_peer_addr_info,
+ #sctp_paddrinfo{address={Addr,P2}}}]}),
+ %%?line S3Ai = S1Ai,
+ ?line ?LOGVAR(S3Ai),
+ %%
+ ?line socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}),
+ ?line
+ receive
+ {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
+ ?line socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}),
+ ?line
+ receive
+ {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
+ %%
+ ?line inet:i(sctp),
+ ?line socket_close_verbose(S1),
+ ?line socket_close_verbose(S2),
+ ?line
+ receive
+ {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} ->
+ ?line match_unless_solaris(S3Ai, S3Ai_X)
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ ?line
+ receive
+ {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S3Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ ?line socket_close_verbose(S3),
+ ?line [] = flush(),
+ ok.
+
+
+
+buffers(doc) ->
+ ["Check sndbuf and recbuf behaviour"];
+buffers(suite) ->
+ [];
+buffers(Config) when is_list(Config) ->
+ ?line Limit = 4096,
+ ?line Addr = {127,0,0,1},
+ ?line Stream = 1,
+ ?line Timeout = 3333,
+ ?line S1 = socket_open([{ip,Addr}], Timeout),
+ ?line ?LOGVAR(S1),
+ ?line P1 = socket_call(S1, get_port),
+ ?line ?LOGVAR(P1),
+ ?line ok = socket_call(S1, {listen,true}),
+ ?line S2 = socket_open([{ip,Addr}], Timeout),
+ ?line ?LOGVAR(S2),
+ ?line P2 = socket_call(S2, get_port),
+ ?line ?LOGVAR(P2),
+ %%
+ ?line socket_call(S2, {connect_init,Addr,P1,[]}),
+ ?line S2Ai =
+ receive
+ {S2,{Addr,P1,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line S1Ai =
+ receive
+ {S1,{Addr,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ %%
+ ?line socket_call(S1, {setopts,[{recbuf,Limit}]}),
+ ?line Recbuf =
+ case socket_call(S1, {getopts,[recbuf]}) of
+ [{recbuf,RB1}] when RB1 >= Limit -> RB1
+ end,
+ ?line Data = mk_data(Recbuf+Limit),
+ ?line socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}),
+ ?line socket_call(S2, {send,S2Ai,Stream,Data}),
+ ?line
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ %%
+ ?line socket_close_verbose(S1),
+ ?line
+ receive
+ {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ ?line
+ receive
+ {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ ?line socket_close_verbose(S2),
+ ?line [] = flush(),
+ ok.
+
+mk_data(Bytes) ->
+ mk_data(0, Bytes, <<>>).
+%%
+mk_data(N, Bytes, Bin) when N < Bytes ->
+ mk_data(N+4, Bytes, <<Bin/binary,N:32>>);
+mk_data(_, _, Bin) ->
+ Bin.
+
+
+
+open_multihoming_ipv4_socket(doc) ->
+ "Test opening a multihoming ipv4 socket";
+open_multihoming_ipv4_socket(suite) ->
+ [];
+open_multihoming_ipv4_socket(Config) when is_list(Config) ->
+ ?line case get_addrs_by_family(inet, 2) of
+ {ok, [Addr1, Addr2]} ->
+ ?line do_open_and_connect([Addr1, Addr2], Addr1);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+open_unihoming_ipv6_socket(doc) ->
+ %% This test is mostly aimed to indicate
+ %% whether host has a non-working ipv6 setup
+ "Test opening a unihoming (non-multihoming) ipv6 socket";
+open_unihoming_ipv6_socket(suite) ->
+ [];
+open_unihoming_ipv6_socket(Config) when is_list(Config) ->
+ ?line case get_addrs_by_family(inet6, 1) of
+ {ok, [Addr]} ->
+ ?line do_open_and_connect([Addr], Addr);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+
+open_multihoming_ipv6_socket(doc) ->
+ "Test opening a multihoming ipv6 socket";
+open_multihoming_ipv6_socket(suite) ->
+ [];
+open_multihoming_ipv6_socket(Config) when is_list(Config) ->
+ ?line case get_addrs_by_family(inet6, 2) of
+ {ok, [Addr1, Addr2]} ->
+ ?line do_open_and_connect([Addr1, Addr2], Addr1);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+open_multihoming_ipv4_and_ipv6_socket(doc) ->
+ "Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses";
+open_multihoming_ipv4_and_ipv6_socket(suite) ->
+ [];
+open_multihoming_ipv4_and_ipv6_socket(Config) when is_list(Config) ->
+ ?line case get_addrs_by_family(inet_and_inet6, 2) of
+ {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} ->
+ %% Connect to the first address to test bind
+ ?line do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2],
+ InetAddr1),
+ ?line do_open_and_connect([Inet6Addr1, InetAddr1],
+ Inet6Addr1),
+
+ %% Connect an address, not the first,
+ %% to test sctp_bindx
+ ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1],
+ Inet6Addr2),
+ ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1],
+ InetAddr1);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+
+get_addrs_by_family(Family, NumAddrs) ->
+ case os:type() of
+ {unix,linux} ->
+ get_addrs_by_family_aux(Family, NumAddrs);
+ {unix,freebsd} ->
+ get_addrs_by_family_aux(Family, NumAddrs);
+ {unix,sunos} ->
+ case get_addrs_by_family_aux(Family, NumAddrs) of
+ {ok, [InetAddrs, Inet6Addrs]} when Family =:= inet_and_inet6 ->
+ %% Man page for sctp_bindx on Solaris says: "If sock is an
+ %% Internet Protocol Version 6 (IPv6) socket, addrs should
+ %% be an array of sockaddr_in6 structures containing IPv6
+ %% or IPv4-mapped IPv6 addresses."
+ {ok, [ipv4_map_addrs(InetAddrs), Inet6Addrs]};
+ {ok, Addrs} ->
+ {ok, Addrs};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ Os ->
+ Reason = if Family =:= inet_and_inet6 ->
+ f("Mixing ipv4 and ipv6 addresses for multihoming "
+ " has not been verified on ~p", [Os]);
+ true ->
+ f("Multihoming for ~p has not been verified on ~p",
+ [Family, Os])
+ end,
+ {error, Reason}
+ end.
+
+get_addrs_by_family_aux(Family, NumAddrs) when Family =:= inet;
+ Family =:= inet6 ->
+ ?line
+ case inet:getaddr(localhost, Family) of
+ {error,eafnosupport} ->
+ {skip, f("No support for ~p", Family)};
+ {ok, _} ->
+ ?line IfAddrs = ok(inet:getifaddrs()),
+ ?line case filter_addrs_by_family(IfAddrs, Family) of
+ Addrs when length(Addrs) >= NumAddrs ->
+ {ok, lists:sublist(Addrs, NumAddrs)};
+ [] ->
+ {error, f("Need ~p ~p address(es) found none~n",
+ [NumAddrs, Family])};
+ Addrs ->
+ {error,
+ f("Need ~p ~p address(es) found only ~p: ~p~n",
+ [NumAddrs, Family, length(Addrs), Addrs])}
+ end
+ end;
+get_addrs_by_family_aux(inet_and_inet6, NumAddrs) ->
+ ?line catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of
+ {ok, Addrs} -> Addrs;
+ {error, Reason} -> throw({error, Reason})
+ end || Family <- [inet, inet6]]}.
+
+filter_addrs_by_family(IfAddrs, Family) ->
+ lists:flatten([[Addr || {addr, Addr} <- Info,
+ is_good_addr(Addr, Family)]
+ || {_IfName, Info} <- IfAddrs]).
+
+is_good_addr(Addr, inet) when tuple_size(Addr) =:= 4 ->
+ true;
+is_good_addr({0,0,0,0,0,16#ffff,_,_}, inet6) ->
+ false; %% ipv4 mapped
+is_good_addr({16#fe80,_,_,_,_,_,_,_}, inet6) ->
+ false; %% link-local
+is_good_addr(Addr, inet6) when tuple_size(Addr) =:= 8 ->
+ true;
+is_good_addr(_Addr, _Family) ->
+ false.
+
+ipv4_map_addrs(InetAddrs) ->
+ [begin
+ <<AB:16>> = <<A,B>>,
+ <<CD:16>> = <<C,D>>,
+ {0, 0, 0, 0, 0, 16#ffff, AB, CD}
+ end || {A,B,C,D} <- InetAddrs].
+
+f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
+
+do_open_and_connect(ServerAddresses, AddressToConnectTo) ->
+ ?line ServerFamily = get_family_by_addrs(ServerAddresses),
+ ?line io:format("Serving ~p addresses: ~p~n",
+ [ServerFamily, ServerAddresses]),
+ ?line S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++
+ [ServerFamily])),
+ ?line ok = gen_sctp:listen(S1, true),
+ ?line P1 = ok(inet:port(S1)),
+ ?line ClientFamily = get_family_by_addr(AddressToConnectTo),
+ ?line io:format("Connecting to ~p ~p~n",
+ [ClientFamily, AddressToConnectTo]),
+ ?line S2 = ok(gen_sctp:open(0, [ClientFamily])),
+ %% Verify client can connect
+ ?line #sctp_assoc_change{state=comm_up} =
+ ok(gen_sctp:connect(S2, AddressToConnectTo, P1, [])),
+ %% verify server side also receives comm_up from client
+ ?line recv_comm_up_eventually(S1),
+ ?line ok = gen_sctp:close(S2),
+ ?line ok = gen_sctp:close(S1).
+
+%% If at least one of the addresses is an ipv6 address, return inet6, else inet.
+get_family_by_addrs(Addresses) ->
+ ?line case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of
+ [inet, inet6] -> inet6;
+ [inet] -> inet;
+ [inet6] -> inet6
+ end.
+
+get_family_by_addr(Addr) when tuple_size(Addr) =:= 4 -> inet;
+get_family_by_addr(Addr) when tuple_size(Addr) =:= 8 -> inet6.
+
+recv_comm_up_eventually(S) ->
+ ?line case ok(gen_sctp:recv(S)) of
+ {_Addr, _Port, _Info, #sctp_assoc_change{state=comm_up}} ->
+ ok;
+ {_Addr, _Port, _Info, _OtherSctpMsg} ->
+ ?line recv_comm_up_eventually(S)
+ end.
+
+%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% socket gen_server ultra light
+
+socket_open(SocketOpts, Timeout) ->
+ Opts = [{type,seqpacket},{active,once},binary|SocketOpts],
+ Starter =
+ fun () ->
+ {ok,Socket} =
+ gen_sctp:open(Opts),
+ Socket
+ end,
+ s_start(Starter, Timeout).
+
+socket_peeloff(Socket, AssocId, Timeout) ->
+ Opts = [{active,once},binary],
+ Starter =
+ fun () ->
+ {ok,NewSocket} =
+ gen_sctp:peeloff(Socket, AssocId),
+ ok = inet:setopts(NewSocket, Opts),
+ NewSocket
+ end,
+ s_start(Starter, Timeout).
+
+socket_close_verbose(S) ->
+ History = socket_history(socket_close(S)),
+ io:format("socket_close ~p:~n ~p.~n", [S,History]),
+ History.
+
+socket_close(S) ->
+ s_req(S, close).
+
+socket_call(S, Request) ->
+ s_req(S, {Request}).
+
+%% socket_get(S, Key) ->
+%% s_req(S, {get,Key}).
+
+socket_bailout([S|Ss]) ->
+ History = socket_history(socket_close(S)),
+ io:format("bailout ~p:~n ~p.~n", [S,History]),
+ socket_bailout(Ss);
+socket_bailout([]) ->
+ io:format("flush: ~p.~n", [flush()]),
+ test_server:fail(socket_bailout).
+
+socket_history({State,Flush}) ->
+ {lists:keysort(
+ 2,
+ lists:flatten(
+ [[{Key,Val} || Val <- Vals]
+ || {Key,Vals} <- gb_trees:to_list(State)])),
+ Flush}.
+
+s_handler(Socket) ->
+ fun ({listen,Listen}) ->
+ ok = gen_sctp:listen(Socket, Listen);
+ (get_port) ->
+ ok(inet:port(Socket));
+ (get_socket) ->
+ Socket;
+ ({connect_init,ConAddr,ConPort,ConOpts}) ->
+ ok = gen_sctp:connect_init(Socket, ConAddr, ConPort, ConOpts);
+ ({send,AssocId,Stream,Data}) ->
+ ok = gen_sctp:send(Socket, AssocId, Stream, Data);
+ ({send,OtherSocket,AssocId,Stream,Data}) ->
+ ok = gen_sctp:send(OtherSocket, AssocId, Stream, Data);
+ ({setopts,Opts}) ->
+ ok = inet:setopts(Socket, Opts);
+ ({getopts,Optnames}) ->
+ ok(inet:getopts(Socket, Optnames))
+ end.
+
+s_req(S, Req) ->
+ Mref = erlang:monitor(process, S),
+ S ! {self(),Mref,Req},
+ receive
+ {'DOWN',Mref,_,_,Error} ->
+ exit(Error);
+ {S,Mref,Reply} ->
+ erlang:demonitor(Mref),
+ receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
+ Reply
+ end.
+
+s_start(Starter, Timeout) ->
+ Parent = self(),
+ Owner =
+ spawn_link(
+ fun () ->
+ s_start(Starter(), Timeout, Parent)
+ end),
+ Owner.
+
+s_start(Socket, Timeout, Parent) ->
+ Handler = s_handler(Socket),
+ try
+ s_loop(Socket, Timeout, Parent, Handler, gb_trees:empty())
+ catch
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ io:format(?MODULE_STRING":socket exception ~w:~w at~n"
+ "~p.~n", [Class,Reason,Stacktrace]),
+ erlang:raise(Class, Reason, Stacktrace)
+ end.
+
+s_loop(Socket, Timeout, Parent, Handler, State) ->
+ receive
+ {Parent,Ref,close} -> % socket_close()
+ erlang:send_after(Timeout, self(), {Parent,Ref,exit}),
+ s_loop(Socket, Timeout, Parent, Handler, State);
+ {Parent,Ref,exit} ->
+ ok = gen_sctp:close(Socket),
+ Key = exit,
+ Val = {now(),Socket},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),Ref,{NewState,flush()}};
+ {Parent,Ref,{Msg}} ->
+ Result = Handler(Msg),
+ Key = req,
+ Val = {now(),{Msg,Result}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),Ref,Result},
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ %% {Parent,Ref,{get,Key}} ->
+ %% Parent ! {self(),Ref,gb_get(Key, State)},
+ %% s_loop(Socket, Timeout, Parent, Handler, State);
+ {sctp,Socket,Addr,Port,
+ {[#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}=SRI],Data}}
+ when not is_tuple(Data) ->
+ case gb_get({assoc_change,AssocId}, State) of
+ [{_,{Addr,Port,
+ #sctp_assoc_change{
+ state=comm_up,
+ inbound_streams=Is}}}|_]
+ when 0 =< Stream, Stream < Is-> ok;
+ [] -> ok
+ end,
+ Key = {msg,AssocId,Stream},
+ Val = {now(),{Addr,Port,SRI,Data}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),{Addr,Port,AssocId,Stream,Data}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_assoc_change{assoc_id=AssocId,state=St}=SAC}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ Key = {assoc_change,AssocId},
+ Val = {now(),{Addr,Port,SAC}},
+ case {gb_get(Key, State),St} of
+ {[],_} -> ok;
+ {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_}
+ when St =:= comm_lost; St =:= shutdown_comp -> ok
+ end,
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),{Addr,Port,SAC}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_paddr_change{assoc_id=AssocId,
+ addr={_,P},
+ state=St}=SPC}} ->
+ match_unless_solaris(Port, P),
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ case {gb_get({assoc_change,AssocId}, State),St} of
+ {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],
+ addr_available} -> ok;
+ {[],addr_confirmed} -> ok
+ end,
+ Key = {paddr_change,AssocId},
+ Val = {now(),{Addr,Port,SPC}},
+ NewState = gb_push(Key, Val, State),
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_shutdown_event{assoc_id=AssocId}=SSE}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ case gb_get({assoc_change,AssocId}, State) of
+ [{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_] -> ok;
+ [] -> ok
+ end,
+ Key = {shutdown_event,AssocId},
+ Val = {now(),{Addr,Port}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(), {Addr,Port,SSE}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ Unexpected ->
+ erlang:error({unexpected,Unexpected})
+ end.
+
+again(Socket) ->
+ inet:setopts(Socket, [{active,once}]).
+
+gb_push(Key, Val, GBT) ->
+ case gb_trees:lookup(Key, GBT) of
+ none ->
+ gb_trees:insert(Key, [Val], GBT);
+ {value,V} ->
+ gb_trees:update(Key, [Val|V], GBT)
+ end.
+
+gb_get(Key, GBT) ->
+ case gb_trees:lookup(Key, GBT) of
+ none ->
+ [];
+ {value,V} ->
+ V
+ end.
+
+match_unless_solaris(A, B) ->
+ case os:type() of
+ {unix,sunos} -> B;
+ _ -> A = B
+ end.
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index cbaec2d6dd..a7af00c12a 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -22,7 +22,7 @@
%% are not tested here, because they are tested indirectly in this and
%% and other test suites.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -46,6 +46,8 @@ groups() ->
{t_connect, [], [t_connect_timeout, t_connect_bad]},
{t_recv, [], [t_recv_timeout, t_recv_eof]}].
+
+
init_per_suite(Config) ->
Config.
@@ -55,9 +57,8 @@ end_per_suite(_Config) ->
init_per_group(_GroupName, Config) ->
Config.
-end_per_group(_GroupName, Config) ->
- Config.
-
+end_per_group(_,_Config) ->
+ ok.
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(60)),
@@ -237,7 +238,6 @@ implicit_inet6(S, Addr) ->
?line ok = gen_tcp:close(S1).
-
%%% Utilities
%% Calls M:F/length(A), which should return a timeout error, and complete
diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl
index fffaaf4c45..5bbaeb02ad 100644
--- a/lib/kernel/test/gen_tcp_echo_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_echo_SUITE.erl
@@ -167,8 +167,12 @@ echo_test_1(SockOpts, EchoFun, Config0) ->
[{type, {cdr, little}}|Config]),
?line case lists:keymember(packet_size, 1, SockOpts) of
false ->
- ?line echo_packet([{packet, line}|SockOpts],
- EchoFun, Config);
+ % This is cheating, we should test that packet_size
+ % also works for line and http.
+ echo_packet([{packet, line}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, http}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config);
+
true -> ok
end,
?line echo_packet([{packet, tpkt}|SockOpts], EchoFun, Config),
@@ -183,9 +187,6 @@ echo_test_1(SockOpts, EchoFun, Config0) ->
[{type, {asn1, short, LongTag}}|Config]),
?line echo_packet([{packet, asn1}|SockOpts], EchoFun,
[{type, {asn1, long, LongTag}}|Config]),
-
- ?line echo_packet([{packet, http}|SockOpts], EchoFun, Config),
- ?line echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config),
ok.
echo_packet(SockOpts, EchoFun, Opts) ->
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index b1ef8826d5..1592399996 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,8 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- controlling_process/1, no_accept/1, close_with_pending_output/1,
+ controlling_process/1, controlling_process_self/1,
+ no_accept/1, close_with_pending_output/1,
data_before_close/1, iter_max_socks/1, get_status/1,
passive_sockets/1, accept_closed_by_other_process/1,
init_per_testcase/2, end_per_testcase/2,
@@ -39,8 +40,10 @@
accept_timeouts_in_order/1,accept_timeouts_in_order2/1,
accept_timeouts_in_order3/1,accept_timeouts_mixed/1,
killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1,
- several_accepts_in_one_go/1,active_once_closed/1, send_timeout/1, send_timeout_active/1,
- otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1]).
+ several_accepts_in_one_go/1, accept_system_limit/1,
+ active_once_closed/1, send_timeout/1, send_timeout_active/1,
+ otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
+ otp_9389/1]).
%% Internal exports.
-export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1,
@@ -56,7 +59,7 @@ end_per_testcase(_Func, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [controlling_process, no_accept,
+ [controlling_process, controlling_process_self, no_accept,
close_with_pending_output, data_before_close,
iter_max_socks, passive_sockets,
accept_closed_by_other_process, otp_3924, closed_socket,
@@ -70,9 +73,9 @@ all() ->
accept_timeouts_in_order, accept_timeouts_in_order2,
accept_timeouts_in_order3, accept_timeouts_mixed,
killing_acceptor, killing_multi_acceptors,
- killing_multi_acceptors2, several_accepts_in_one_go,
+ killing_multi_acceptors2, several_accepts_in_one_go, accept_system_limit,
active_once_closed, send_timeout, send_timeout_active, otp_7731,
- zombie_sockets, otp_7816, otp_8102].
+ zombie_sockets, otp_7816, otp_8102, otp_9389].
groups() ->
[].
@@ -305,6 +308,32 @@ not_owner(S) ->
ok
end.
+controlling_process_self(doc) ->
+ ["Open a listen port and assign the controlling process to "
+ "it self, then exit and make sure the port is closed properly."];
+controlling_process_self(Config) when is_list(Config) ->
+ S = self(),
+ process_flag(trap_exit,true),
+ spawn_link(fun() ->
+ {ok,Sock} = gen_tcp:listen(0,[]),
+ S ! {socket, Sock},
+ ok = gen_tcp:controlling_process(Sock,self()),
+ S ! done
+ end),
+ receive
+ done ->
+ receive
+ {socket,Sock} ->
+ process_flag(trap_exit,false),
+ %% Make sure the port is invalid after process crash
+ {error,einval} = inet:port(Sock)
+ end;
+ Msg when element(1,Msg) /= socket ->
+ process_flag(trap_exit,false),
+ exit({unknown_msg,Msg})
+ end.
+
+
no_accept(doc) ->
["Open a listen port and connect to it, then close the listen port ",
"without doing any accept. The connected socket should receive ",
@@ -1030,6 +1059,7 @@ busy_send_loop(Server, Client, N) ->
{Server,send} ->
?line busy_send_2(Server, Client, N+1)
after 10000 ->
+ %% If this happens, see busy_send_srv
?t:fail({timeout,{server,not_send,flush([])}})
end
end.
@@ -1049,7 +1079,9 @@ busy_send_2(Server, Client, _N) ->
busy_send_srv(L, Master, Msg) ->
%% Server
- %%
+ %% Sometimes this accept does not return, do not really know why
+ %% but is causes the timeout error in busy_send_loop to be
+ %% triggered. Only happens on OS X Leopard?!?
{ok,Socket} = gen_tcp:accept(L),
busy_send_srv_loop(Socket, Master, Msg).
@@ -1833,6 +1865,54 @@ wait_until_accepting(Proc,N) ->
end.
+accept_system_limit(suite) ->
+ [];
+accept_system_limit(doc) ->
+ ["Check that accept returns {error, system_limit} "
+ "(and not {error, enfile}) when running out of ports"];
+accept_system_limit(Config) when is_list(Config) ->
+ ?line {ok, LS} = gen_tcp:listen(0, []),
+ ?line {ok, TcpPort} = inet:port(LS),
+ ?line Connector = spawn_link(fun () -> connector(TcpPort) end),
+ ?line ok = acceptor(LS, false, []),
+ ?line Connector ! stop,
+ ok.
+
+acceptor(LS, GotSL, A) ->
+ case gen_tcp:accept(LS, 1000) of
+ {ok, S} ->
+ acceptor(LS, GotSL, [S|A]);
+ {error, system_limit} ->
+ acceptor(LS, true, A);
+ {error, timeout} when GotSL ->
+ ok;
+ {error, timeout} ->
+ error
+ end.
+
+connector(TcpPort) ->
+ ManyPorts = open_ports([]),
+ ConnF = fun (Port) ->
+ case catch gen_tcp:connect({127,0,0,1}, TcpPort, []) of
+ {ok, Sock} ->
+ Sock;
+ _Error ->
+ port_close(Port)
+ end
+ end,
+ R = [ConnF(Port) || Port <- lists:sublist(ManyPorts, 10)],
+ receive stop -> R end.
+
+open_ports(L) ->
+ case catch open_port({spawn_driver, "ram_file_drv"}, []) of
+ Port when is_port(Port) ->
+ open_ports([Port|L]);
+ {'EXIT', {system_limit, _}} ->
+ {L1, L2} = lists:split(5, L),
+ [port_close(Port) || Port <- L1],
+ L2
+ end.
+
active_once_closed(suite) ->
[];
@@ -1991,7 +2071,7 @@ send_timeout_active(Config) when is_list(Config) ->
?line {error,timeout} =
Loop(fun() ->
receive
- {tcp, Sock, _Data} ->
+ {tcp, _Sock, _Data} ->
inet:setopts(A, [{active, once}]),
Res = gen_tcp:send(A,lists:duplicate(1000, $a)),
%erlang:display(Res),
@@ -2479,4 +2559,63 @@ otp_8102_do(LSocket, PortNum, {Bin,PType}) ->
io:format("Got error msg, ok.\n",[]),
gen_tcp:close(SSocket),
gen_tcp:close(RSocket).
-
+
+otp_9389(doc) -> ["Verify packet_size handles long HTTP header lines"];
+otp_9389(suite) -> [];
+otp_9389(Config) when is_list(Config) ->
+ ?line {ok, LS} = gen_tcp:listen(0, [{active,false}]),
+ ?line {ok, {_, PortNum}} = inet:sockname(LS),
+ io:format("Listening on ~w with port number ~p\n", [LS, PortNum]),
+ OrigLinkHdr = "/" ++ string:chars($S, 8192),
+ _Server = spawn_link(
+ fun() ->
+ ?line {ok, S} = gen_tcp:accept(LS),
+ ?line ok = inet:setopts(S, [{packet_size, 16384}]),
+ ?line ok = otp_9389_loop(S, OrigLinkHdr),
+ ?line ok = gen_tcp:close(S)
+ end),
+ ?line {ok, S} = gen_tcp:connect("localhost", PortNum,
+ [binary, {active, false}]),
+ Req = "GET / HTTP/1.1\r\n"
+ ++ "Host: localhost\r\n"
+ ++ "Link: " ++ OrigLinkHdr ++ "\r\n\r\n",
+ ?line ok = gen_tcp:send(S, Req),
+ ?line ok = inet:setopts(S, [{packet, http}]),
+ ?line {ok, {http_response, {1,1}, 200, "OK"}} = gen_tcp:recv(S, 0),
+ ?line ok = inet:setopts(S, [{packet, httph}, {packet_size, 16384}]),
+ ?line {ok, {http_header, _, 'Content-Length', _, "0"}} = gen_tcp:recv(S, 0),
+ ?line {ok, {http_header, _, "Link", _, LinkHdr}} = gen_tcp:recv(S, 0),
+ ?line true = (LinkHdr == OrigLinkHdr),
+ ok = gen_tcp:close(S),
+ ok = gen_tcp:close(LS),
+ ok.
+
+otp_9389_loop(S, OrigLinkHdr) ->
+ ?line ok = inet:setopts(S, [{active,once},{packet,http}]),
+ receive
+ {http, S, {http_request, 'GET', _, _}} ->
+ ?line ok = otp_9389_loop(S, OrigLinkHdr, undefined)
+ after
+ 3000 ->
+ ?line error({timeout,request_line})
+ end.
+otp_9389_loop(S, OrigLinkHdr, ok) ->
+ ?line Resp = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n" ++
+ "Link: " ++ OrigLinkHdr ++ "\r\n\r\n",
+ ?line ok = gen_tcp:send(S, Resp);
+otp_9389_loop(S, OrigLinkHdr, State) ->
+ ?line ok = inet:setopts(S, [{active,once}, {packet,httph}]),
+ receive
+ {http, S, http_eoh} ->
+ ?line otp_9389_loop(S, OrigLinkHdr, ok);
+ {http, S, {http_header, _, "Link", _, LinkHdr}} ->
+ ?line LinkHdr = OrigLinkHdr,
+ ?line otp_9389_loop(S, OrigLinkHdr, State);
+ {http, S, {http_header, _, _Hdr, _, _Val}} ->
+ ?line otp_9389_loop(S, OrigLinkHdr, State);
+ {http, S, {http_error, Err}} ->
+ ?line error({error, Err})
+ after
+ 3000 ->
+ ?line error({timeout,header})
+ end.
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index 514deaf065..2354f8accd 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -99,9 +99,9 @@ buffer_size(Config) when is_list(Config) ->
?line Bin = list_to_binary(lists:seq(0, Len-1)),
?line M = 8192 div Len,
?line Spec0 =
- [{opt,M},{safe,M-1},{long,M+1},
- {opt,2*M},{safe,2*M-1},{long,2*M+1},
- {opt,4*M},{safe,4*M-1},{long,4*M+1}],
+ [{opt,M},{safe,M-3},{long,M+1},
+ {opt,2*M},{safe,2*M-3},{long,2*M+1},
+ {opt,4*M},{safe,4*M-3},{long,4*M+1}],
?line Spec =
[case Tag of
opt ->
@@ -145,16 +145,27 @@ buffer_size_client(_, _, _, _, _, []) ->
?line ok;
buffer_size_client(Server, IP, Port,
Socket, Cnt, [Opts|T]) when is_list(Opts) ->
+ ?line io:format("buffer_size_client Cnt=~w setopts ~p.~n", [Cnt,Opts]),
?line ok = inet:setopts(Socket, Opts),
?line Server ! {self(),setopts,Cnt},
?line receive {Server,setopts,Cnt} -> ok end,
?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T);
buffer_size_client(Server, IP, Port,
- Socket, Cnt, [{B,Replies}|T]) when is_binary(B) ->
- ?line ok = gen_udp:send(Socket, IP, Port, B),
+ Socket, Cnt, [{B,Replies}|T]=Opts) when is_binary(B) ->
+ ?line io:format(
+ "buffer_size_client Cnt=~w send size ~w expecting ~p.~n",
+ [Cnt,size(B),Replies]),
+ ?line ok = gen_udp:send(Socket, IP, Port, <<Cnt,B/binary>>),
?line receive
{Server,Cnt,Reply} ->
- ?line case lists:member(Reply, Replies) of
+ ?line Tag =
+ if
+ is_tuple(Reply) ->
+ element(1, Reply);
+ is_atom(Reply) ->
+ Reply
+ end,
+ ?line case lists:member(Tag, Replies) of
true -> ok;
false ->
?line
@@ -162,34 +173,62 @@ buffer_size_client(Server, IP, Port,
byte_size(B),
inet:getopts(Socket,
[sndbuf,recbuf])})
- end
- end,
- ?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T).
+ end,
+ ?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T)
+ after 1313 ->
+ ?line buffer_size_client(Server, IP, Port, Socket, Cnt, Opts)
+ end.
buffer_size_server(_, _, _, _, _, []) ->
ok;
buffer_size_server(Client, IP, Port,
Socket, Cnt, [Opts|T]) when is_list(Opts) ->
receive {Client,setopts,Cnt} -> ok end,
+ ?line io:format("buffer_size_server Cnt=~w setopts ~p.~n", [Cnt,Opts]),
ok = inet:setopts(Socket, Opts),
Client ! {self(),setopts,Cnt},
buffer_size_server(Client, IP, Port, Socket, Cnt+1, T);
buffer_size_server(Client, IP, Port,
Socket, Cnt, [{B,_}|T]) when is_binary(B) ->
+ ?line io:format(
+ "buffer_size_server Cnt=~w expecting size ~w.~n",
+ [Cnt,size(B)]),
Client !
{self(),Cnt,
- receive
- {udp,Socket,IP,Port,D} when is_binary(D) ->
+ case buffer_size_server_recv(Socket, IP, Port, Cnt) of
+ D when is_binary(D) ->
SizeD = byte_size(D),
+ ?line io:format(
+ "buffer_size_server Cnt=~w received size ~w.~n",
+ [Cnt,SizeD]),
case B of
- D -> correct;
- <<D:SizeD/binary,_/binary>> -> truncated
+ D ->
+ correct;
+ <<D:SizeD/binary,_/binary>> ->
+ truncated;
+ _ ->
+ {unexpected,D}
end;
- {udp_error,Socket,Error} -> Error
- after 5000 -> timeout
+ Error ->
+ ?line io:format(
+ "buffer_size_server Cnt=~w received error ~w.~n",
+ [Cnt,Error]),
+ Error
end},
buffer_size_server(Client, IP, Port, Socket, Cnt+1, T).
+buffer_size_server_recv(Socket, IP, Port, Cnt) ->
+ receive
+ {udp,Socket,IP,Port,<<Cnt,B/binary>>} ->
+ B;
+ {udp,Socket,IP,Port,<<_/binary>>} ->
+ buffer_size_server_recv(Socket, IP, Port, Cnt);
+ {udp_error,Socket,Error} ->
+ Error
+ after 5000 ->
+ {timeout,flush()}
+ end.
+
%%-------------------------------------------------------------
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 1e7bcf1766..60035b50a0 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -436,7 +436,7 @@ lock_global2(Id, Parent) ->
%cp1 - cp3 are started, and the name 'test' registered for a process on
%test_server. Then it is checked that the name is registered on all
-%nodes, using whereis_name and safe_whereis_name. Check that the same
+%nodes, using whereis_name. Check that the same
%name can't be registered with another value. Exit the registered
%process and check that the name disappears. Register a new process
%(Pid2) under the name 'test'. Let another new process (Pid3)
@@ -465,10 +465,6 @@ names(Config) when is_list(Config) ->
% test that it is registered at all nodes
?line
?UNTIL(begin
- (Pid =:= global:safe_whereis_name(test)) and
- (Pid =:= rpc:call(Cp1, global, safe_whereis_name, [test])) and
- (Pid =:= rpc:call(Cp2, global, safe_whereis_name, [test])) and
- (Pid =:= rpc:call(Cp3, global, safe_whereis_name, [test])) and
(Pid =:= global:whereis_name(test)) and
(Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and
@@ -566,10 +562,7 @@ names_hidden(Config) when is_list(Config) ->
% Check that it didn't get registered on visible nodes
?line
- ?UNTIL((undefined =:= global:safe_whereis_name(test)) and
- (undefined =:= rpc:call(Cp1, global, safe_whereis_name, [test])) and
- (undefined =:= rpc:call(Cp2, global, safe_whereis_name, [test])) and
- (undefined =:= global:whereis_name(test)) and
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test]))),
@@ -579,11 +572,7 @@ names_hidden(Config) when is_list(Config) ->
% test that it is registered at all nodes
?line
- ?UNTIL((Pid =:= global:safe_whereis_name(test)) and
- (Pid =:= rpc:call(Cp1, global, safe_whereis_name, [test])) and
- (Pid =:= rpc:call(Cp2, global, safe_whereis_name, [test])) and
- (HPid =:= rpc:call(Cp3, global, safe_whereis_name, [test])) and
- (Pid =:= global:whereis_name(test)) and
+ ?UNTIL((Pid =:= global:whereis_name(test)) and
(Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and
(HPid =:= rpc:call(Cp3, global, whereis_name, [test])) and
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index aaa20b7398..7241b093d0 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -97,8 +97,12 @@ t_gethostbyaddr() ->
required(v4).
t_gethostbyaddr(doc) -> "Test the inet:gethostbyaddr/1 function.";
t_gethostbyaddr(Config) when is_list(Config) ->
- ?line {Name,FullName,IPStr,IP,Aliases,_,_} =
+ ?line {Name,FullName,IPStr,{A,B,C,D}=IP,Aliases,_,_} =
ct:get_config(test_host_ipv4_only),
+ ?line Rname = integer_to_list(D) ++ "." ++
+ integer_to_list(C) ++ "." ++
+ integer_to_list(B) ++ "." ++
+ integer_to_list(A) ++ ".in-addr.arpa",
?line {ok,HEnt} = inet:gethostbyaddr(IPStr),
?line {ok,HEnt} = inet:gethostbyaddr(IP),
?line {error,Error} = inet:gethostbyaddr(Name),
@@ -116,7 +120,7 @@ t_gethostbyaddr(Config) when is_list(Config) ->
ok;
_ ->
?line check_elems([{HEnt#hostent.h_name,[Name,FullName]},
- {HEnt#hostent.h_aliases,[[],Aliases]}])
+ {HEnt#hostent.h_aliases,[[],Aliases,[Rname]]}])
end,
?line {_DName, _DFullName, DIPStr, DIP, _, _, _} =
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index 8a3d220e46..f3ba28e4f9 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -88,7 +88,7 @@ init_per_testcase(Func, Config) ->
inet_db:ins_alt_ns(IP, Port);
_ -> ok
end,
- Dog = test_server:timetrap(test_server:seconds(10)),
+ Dog = test_server:timetrap(test_server:seconds(20)),
[{nameserver,NsSpec},{res_lookup,Lookup},{watchdog,Dog}|Config]
catch
SkipReason ->
@@ -136,21 +136,22 @@ ns_init(ZoneDir, PrivDir, DataDir) ->
atom_to_list(ZoneDir)]},
stderr_to_stdout,
eof]),
- ns_start(ZoneDir, NS, P);
+ ns_start(ZoneDir, PrivDir, NS, P);
_ ->
throw("Only run on Unix")
end.
-ns_start(ZoneDir, NS, P) ->
+ns_start(ZoneDir, PrivDir, NS, P) ->
case ns_collect(P) of
eof ->
erlang:error(eof);
"Running: "++_ ->
{ZoneDir,NS,P};
"Error: "++Error ->
+ ns_printlog(filename:join([PrivDir,ZoneDir,"named.log"])),
throw(Error);
_ ->
- ns_start(ZoneDir, NS, P)
+ ns_start(ZoneDir, PrivDir, NS, P)
end.
ns_end(undefined, _PrivDir) -> undefined;
@@ -302,7 +303,7 @@ basic(Config) when is_list(Config) ->
{ok,Msg2} = inet_dns:decode(Bin2),
%%
%% lookup
- [IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]}]),
+ [IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose]),
%%
%% gethostbyname
{ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(Name),
@@ -409,7 +410,7 @@ edns0(Config) when is_list(Config) ->
false = inet_db:res_option(edns), % ASSERT
true = inet_db:res_option(udp_payload_size) >= 1280, % ASSERT
%% These will fall back to TCP
- MXs = lists:sort(inet_res:lookup(Domain, in, mx, [{nameservers,[NS]}])),
+ MXs = lists:sort(inet_res:lookup(Domain, in, mx, [{nameservers,[NS]},verbose])),
%%
{ok,#hostent{h_addr_list=As}} = inet_res:getbyname(Domain++".", mx),
MXs = lists:sort(As),
diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named
index 7caa3756ef..211d2c7af7 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-2011. All Rights Reserved.
+## Copyright Ericsson AB 2009-2012. All Rights Reserved.
##
## The contents of this file are subject to the Erlang Public License,
## Version 1.1, (the "License"); you may not use this file except in
@@ -71,10 +71,14 @@ test -d "$SRCDIR" || \
test -f "$SRCDIR/$INC_FILE" || \
error "Missing file: $SRCDIR/$INC_FILE !"
-# Locate named and check version
+# Locate named and check version.
+# The bind-named name is used for tricking Apparmor and such
+# by copying/hardlinking the real named to that name.
NAMED=named
-for n in /usr/sbin/named /usr/sbin/in.named; do
- test -x "$n" && NAMED="$n"
+for n in /usr/local/bin/bind-named /usr/local/bin/named \
+ /usr/sbin/bind-named /usr/sbin/named /usr/sbin/in.named
+do
+ test -x "$n" && NAMED="$n" && break
done
NAMED_VER="`"$NAMED" -v 2>&1`" || \
error "Name server not found!"
@@ -151,13 +155,21 @@ echo "Cwd: `pwd`"
echo "Nameserver: $NAMED_VER"
echo "Port: $2"
echo "ZoneDir: $3"
+echo "Command: $NAMED $NAMED_FG -c $CONF_FILE"
$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" \
+NAMED_PID=$!
+echo "Pid: $NAMED_PID"
+trap "kill $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \
0 1 2 3 15
-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
-done
-echo "Closing: Terminating nameserver..."
+
+sleep 5 # Give name server time to load its zone files
+
+if ps -p $NAMED_PID >/dev/null 2>&1 || ps p $NAMED_PID >/dev/null 2>&1; then
+ echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED_PID]..."
+ while read LINE; do
+ test :"$LINE" = :'quit' && break
+ done
+ echo "Closing: Terminating nameserver..."
+else
+ error "$NAMED failed to start"
+fi
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index b39fadd65f..e3fa4642b7 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -608,7 +608,7 @@ boot2(Config) when is_list(Config) ->
%% Absolute boot file name
Boot = filename:join([code:root_dir(), "bin", "start_sasl"]),
- Args = args() ++ " -boot " ++ Boot,
+ Args = args() ++ " -boot \"" ++ Boot++"\"",
?line {ok, Node} = start_node(init_test, Args),
?line stop_node(Node),
@@ -618,7 +618,7 @@ boot2(Config) when is_list(Config) ->
%% converted to backslashes.
Win_boot = lists:map(fun($/) -> $\\; (C) -> C end,
Boot),
- Args2 = args() ++ " -boot " ++ Win_boot,
+ Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"",
?line {ok, Node2} = start_node(init_test, Args2),
?line stop_node(Node2);
_ ->
diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl
index b2308dd321..96e45cc23f 100644
--- a/lib/kernel/test/interactive_shell_SUITE.erl
+++ b/lib/kernel/test/interactive_shell_SUITE.erl
@@ -251,7 +251,7 @@ rtnode(Commands,Nodename,ErlPrefix) ->
?line {skip, Reason2};
Tempdir ->
?line SPid =
- start_runerl_node(RunErl,ErlPrefix++Erl,
+ start_runerl_node(RunErl,ErlPrefix++"\\\""++Erl++"\\\"",
Tempdir,Nodename),
?line CPid = start_toerl_server(ToErl,Tempdir),
?line erase(getline_skipped),
@@ -487,7 +487,7 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename) ->
" -setcookie "++atom_to_list(erlang:get_cookie())
end,
spawn(fun() ->
- os:cmd(RunErl++" "++Tempdir++"/ "++Tempdir++" \""++
+ os:cmd("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++" \""++
Erl++XArg++"\"")
end).
@@ -518,7 +518,7 @@ try_to_erl(Command, N) ->
end.
toerl_server(Parent,ToErl,Tempdir) ->
- Port = try_to_erl(ToErl++" "++Tempdir++"/ 2>/dev/null",8),
+ Port = try_to_erl("\""++ToErl++"\" "++Tempdir++"/ 2>/dev/null",8),
case Port of
P when is_port(P) ->
Parent ! {self(),started};
diff --git a/lib/kernel/test/kernel_SUITE.erl b/lib/kernel/test/kernel_SUITE.erl
index 16b6c54939..0f29d895e5 100644
--- a/lib/kernel/test/kernel_SUITE.erl
+++ b/lib/kernel/test/kernel_SUITE.erl
@@ -32,7 +32,7 @@
-export([init_per_testcase/2, end_per_testcase/2]).
% Test cases must be exported.
--export([app_test/1]).
+-export([app_test/1, appup_test/1]).
%%
%% all/1
@@ -40,7 +40,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app_test].
+ [app_test, appup_test].
groups() ->
[].
@@ -76,3 +76,63 @@ app_test(suite) ->
app_test(Config) when is_list(Config) ->
?line ok=?t:app_test(kernel),
ok.
+
+
+%% Test that appup allows upgrade from/downgrade to a maximum of two
+%% major releases back.
+appup_test(_Config) ->
+ application:load(kernel),
+ {_,_,Vsn} = lists:keyfind(kernel,1,application:loaded_applications()),
+ AppupFile = filename:join([code:lib_dir(kernel),ebin,"kernel.appup"]),
+ {ok,[{Vsn,UpFrom,DownTo}=AppupScript]} = file:consult(AppupFile),
+ ct:log("~p~n",[AppupScript]),
+ {OkVsns,NokVsns} = create_test_vsns(Vsn),
+ check_appup(OkVsns,UpFrom,{ok,[restart_new_emulator]}),
+ check_appup(OkVsns,DownTo,{ok,[restart_new_emulator]}),
+ check_appup(NokVsns,UpFrom,error),
+ check_appup(NokVsns,DownTo,error),
+ ok.
+
+create_test_vsns(Current) ->
+ [XStr,YStr|Rest] = string:tokens(Current,"."),
+ X = list_to_integer(XStr),
+ Y = list_to_integer(YStr),
+ SecondMajor = vsn(X,Y-2),
+ SecondMinor = SecondMajor ++ ".1.3",
+ FirstMajor = vsn(X,Y-1),
+ FirstMinor = FirstMajor ++ ".57",
+ ThisMajor = vsn(X,Y),
+ This =
+ case Rest of
+ [] ->
+ [];
+ ["1"] ->
+ [ThisMajor];
+ _ ->
+ ThisMinor = ThisMajor ++ ".1",
+ [ThisMajor,ThisMinor]
+ end,
+ OkVsns = This ++ [FirstMajor, FirstMinor, SecondMajor, SecondMinor],
+
+ ThirdMajor = vsn(X,Y-3),
+ ThirdMinor = ThirdMajor ++ ".10.12",
+ Illegal = ThisMajor ++ ",1",
+ Newer1Major = vsn(X,Y+1),
+ Newer1Minor = Newer1Major ++ ".1",
+ Newer2Major = ThisMajor ++ "1",
+ NokVsns = [ThirdMajor,ThirdMinor,
+ Illegal,
+ Newer1Major,Newer1Minor,
+ Newer2Major],
+ {OkVsns,NokVsns}.
+
+vsn(X,Y) ->
+ integer_to_list(X) ++ "." ++ integer_to_list(Y).
+
+check_appup([Vsn|Vsns],Instrs,Expected) ->
+ case systools_relup:appup_search_for_version(Vsn, Instrs) of
+ Expected -> check_appup(Vsns,Instrs,Expected);
+ Other -> ct:fail({unexpected_result_for_vsn,Vsn,Other})
+ end;
+check_appup([],_,_) ->
+ ok.
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl
index b08b12c978..ae3410d13f 100644
--- a/lib/kernel/test/os_SUITE.erl
+++ b/lib/kernel/test/os_SUITE.erl
@@ -117,9 +117,21 @@ space_in_name(Config) when is_list(Config) ->
?line ok = file:change_mode(Echo, 8#777), % Make it executable on Unix.
%% Run the echo program.
-
- ?line comp("", os:cmd("\"" ++ Echo ++ "\"")),
- ?line comp("a::b::c", os:cmd("\"" ++ Echo ++ "\" a b c")),
+ %% Quoting on windows depends on if the full path of the executable
+ %% contains special characters. Paths when running common_tests always
+ %% include @, why Windows would always fail if we do not double the
+ %% quotes (this is the behaviour of cmd.exe, not Erlang's idea).
+ Quote = case os:type() of
+ {win32,_} ->
+ case (Echo -- "&<>()@^|") =:= Echo of
+ true -> "\"";
+ false -> "\"\""
+ end;
+ _ ->
+ "\""
+ end,
+ ?line comp("", os:cmd(Quote ++ Echo ++ Quote)),
+ ?line comp("a::b::c", os:cmd(Quote ++ Echo ++ Quote ++ " a b c")),
?t:sleep(5),
?line [] = receive_all(),
ok.
diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl
index 0ac34e735c..520b53b4e4 100644
--- a/lib/kernel/test/pg2_SUITE.erl
+++ b/lib/kernel/test/pg2_SUITE.erl
@@ -47,6 +47,7 @@ init_per_testcase(Case, Config) ->
[{?TESTCASE, Case}, {watchdog, Dog} | Config].
end_per_testcase(_Case, _Config) ->
+ test_server_ctrl:kill_slavenodes(),
Dog = ?config(watchdog, _Config),
test_server:timetrap_cancel(Dog),
ok.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 00eda6292f..3e2202922c 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -32,7 +32,10 @@
file_info_basic_directory_a/1, file_info_basic_directory_b/1,
file_info_bad_a/1, file_info_bad_b/1,
file_info_times_a/1, file_info_times_b/1,
- file_write_file_info_a/1, file_write_file_info_b/1]).
+ file_write_file_info_a/1, file_write_file_info_b/1,
+ file_read_file_info_opts/1, file_write_file_info_opts/1,
+ file_write_read_file_info_opts/1
+ ]).
-export([rename_a/1, rename_b/1,
access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1, exclusive/1]).
@@ -49,6 +52,10 @@
list_dir_limit/1]).
-export([advise/1]).
+-export([large_write/1]).
+
+%% System probe functions that might be handy to check from the shell
+-export([unix_free/1]).
-include_lib("test_server/include/test_server.hrl").
-include_lib("kernel/include/file.hrl").
@@ -80,7 +87,7 @@ groups() ->
cur_dir_1a, cur_dir_1b]},
{files, [],
[{group, open}, {group, pos}, {group, file_info},
- truncate, sync, datasync, advise]},
+ truncate, sync, datasync, advise, large_write]},
{open, [],
[open1, modes, close, access, read_write, pread_write,
append, exclusive]},
@@ -90,7 +97,10 @@ groups() ->
file_info_basic_directory_a,
file_info_basic_directory_b, file_info_bad_a,
file_info_bad_b, file_info_times_a, file_info_times_b,
- file_write_file_info_a, file_write_file_info_b]},
+ file_write_file_info_a, file_write_file_info_b,
+ file_read_file_info_opts, file_write_file_info_opts,
+ file_write_read_file_info_opts
+ ]},
{errors, [],
[e_delete, e_rename, e_make_dir, e_del_dir]},
{compression, [],
@@ -284,6 +294,7 @@ make_del_dir(Config, Handle, Suffix) ->
%% Don't worry ;-) the parent directory should never be empty, right?
?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
{error, eexist} -> ok;
+ {error, eacces} -> ok; %OpenBSD
{error, einval} -> ok %FreeBSD
end,
?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
@@ -1074,6 +1085,104 @@ file_write_file_info(Config, Handle, Suffix) ->
?line test_server:timetrap_cancel(Dog),
ok.
+%% Test the write_file_info/3 function.
+
+file_write_file_info_opts(suite) -> [];
+file_write_file_info_opts(doc) -> [];
+file_write_file_info_opts(Config) when is_list(Config) ->
+ {ok, Handle} = ?PRIM_FILE:start(),
+ Dog = test_server:timetrap(test_server:seconds(10)),
+ RootDir = get_good_directory(Config),
+ test_server:format("RootDir = ~p", [RootDir]),
+
+ Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_write_file_info_opts"),
+ ok = ?PRIM_FILE:write_file(Name, "hello_opts"),
+
+ lists:foreach(fun
+ ({FI, Opts}) ->
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
+ end, [
+ {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} ||
+ Opts <- [[{time, posix}]],
+ Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ]
+ ]),
+
+ % REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64
+ % Determine time_t on os:type()?
+ lists:foreach(fun
+ ({FI, Opts}) ->
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
+ end, [
+ {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} ||
+ Opts <- [[{time, universal}],[{time, local}]],
+ Time <- [
+ {{1970,1,1},{0,0,0}},
+ {{1970,1,1},{0,0,1}},
+ {{1969,12,31},{23,59,59}},
+ {{1908,2,3},{23,59,59}},
+ {{2012,2,3},{23,59,59}},
+ {{2037,2,3},{23,59,59}},
+ erlang:localtime()
+ ]]),
+ ok = ?PRIM_FILE:stop(Handle),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+file_read_file_info_opts(suite) -> [];
+file_read_file_info_opts(doc) -> [];
+file_read_file_info_opts(Config) when is_list(Config) ->
+ {ok, Handle} = ?PRIM_FILE:start(),
+ Dog = test_server:timetrap(test_server:seconds(10)),
+ RootDir = get_good_directory(Config),
+ test_server:format("RootDir = ~p", [RootDir]),
+
+ Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_file_info_opts"),
+ ok = ?PRIM_FILE:write_file(Name, "hello_opts"),
+
+ lists:foreach(fun
+ (Opts) ->
+ {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts])
+ end, [[{time, Type}] || Type <- [local, universal, posix]]),
+ ok = ?PRIM_FILE:stop(Handle),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+%% Test the write and read back *_file_info/3 functions.
+
+file_write_read_file_info_opts(suite) -> [];
+file_write_read_file_info_opts(doc) -> [];
+file_write_read_file_info_opts(Config) when is_list(Config) ->
+ {ok, Handle} = ?PRIM_FILE:start(),
+ Dog = test_server:timetrap(test_server:seconds(10)),
+ RootDir = get_good_directory(Config),
+ test_server:format("RootDir = ~p", [RootDir]),
+
+ Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_write_file_info_opts"),
+ ok = ?PRIM_FILE:write_file(Name, "hello_opts2"),
+
+ ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]),
+ ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]),
+ ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]),
+ ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]),
+ ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, posix}]),
+ ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]),
+ ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, posix}]),
+ ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, posix}]),
+ ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, posix}]),
+
+ ok = ?PRIM_FILE:stop(Handle),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+file_write_read_file_info_opts(Handle, Name, Mtime, Opts) ->
+ {ok, FI} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]),
+ FI2 = FI#file_info{ mtime = Mtime },
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI2, Opts]),
+ {ok, FI2} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]),
+ ok.
+
+
+
%% Returns a directory on a file system that has correct file times.
get_good_directory(Config) ->
@@ -1218,6 +1327,41 @@ advise(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+large_write(Config) when is_list(Config) ->
+ run_large_file_test(Config,
+ fun(Name) -> do_large_write(Name) end,
+ "_large_write").
+
+do_large_write(Name) ->
+ Dog = test_server:timetrap(test_server:minutes(60)),
+ ChunkSize = (256 bsl 20) + 1, % 256 M + 1
+ Chunks = 16, % times 16 -> 4 G + 16
+ Base = 100,
+ Interleave = lists:seq(Base+1, Base+Chunks),
+ Chunk = <<0:ChunkSize/unit:8>>,
+ Data = zip_data(lists:duplicate(Chunks, Chunk), Interleave),
+ Size = Chunks * ChunkSize + Chunks, % 4 G + 32
+ Wordsize = erlang:system_info(wordsize),
+ case prim_file:write_file(Name, Data) of
+ ok when Wordsize =:= 8 ->
+ {ok,#file_info{size=Size}} = file:read_file_info(Name),
+ {ok,Fd} = prim_file:open(Name, [read]),
+ check_large_write(Dog, Fd, ChunkSize, 0, Interleave);
+ {error,einval} when Wordsize =:= 4 ->
+ ok
+ end.
+
+check_large_write(Dog, Fd, ChunkSize, Pos, [X|Interleave]) ->
+ Pos1 = Pos + ChunkSize,
+ {ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}),
+ {ok,[X]} = prim_file:read(Fd, 1),
+ check_large_write(Dog, Fd, ChunkSize, Pos1+1, Interleave);
+check_large_write(Dog, Fd, _, _, []) ->
+ eof = prim_file:read(Fd, 1),
+ test_server:timetrap_cancel(Dog),
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1940,3 +2084,70 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) ->
?PRIM_FILE:delete(Handle, filename:join(Dir, Name)),
list_dir_limit_cleanup(Dir, Handle, N, Cnt+1).
+%%%
+%%% Support for testing large files.
+%%%
+
+run_large_file_test(Config, Run, Name) ->
+ case {os:type(),os:version()} of
+ {{win32,nt},_} ->
+ do_run_large_file_test(Config, Run, Name);
+ {{unix,sunos},OsVersion} when OsVersion < {5,5,1} ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"};
+ {{unix,_},_} ->
+ N = unix_free(?config(priv_dir, Config)),
+ io:format("Free disk: ~w KByte~n", [N]),
+ if N < 5 bsl 20 ->
+ %% Less than 5 GByte free
+ {skip,"Less than 5 GByte free disk"};
+ true ->
+ do_run_large_file_test(Config, Run, Name)
+ end;
+ _ ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
+ end.
+
+
+do_run_large_file_test(Config, Run, Name0) ->
+ Name = filename:join(?config(priv_dir, Config),
+ ?MODULE_STRING ++ Name0),
+
+ %% Set up a process that will delete this file.
+ Tester = self(),
+ Deleter =
+ spawn(
+ fun() ->
+ Mref = erlang:monitor(process, Tester),
+ receive
+ {'DOWN',Mref,_,_,_} -> ok;
+ {Tester,done} -> ok
+ end,
+ prim_file:delete(Name)
+ end),
+
+ %% Run the test case.
+ Res = Run(Name),
+
+ %% Delete file and finish deleter process.
+ Mref = erlang:monitor(process, Deleter),
+ Deleter ! {Tester,done},
+ receive {'DOWN',Mref,_,_,_} -> ok end,
+
+ Res.
+
+unix_free(Path) ->
+ Cmd = ["df -k '",Path,"'"],
+ DF0 = os:cmd(Cmd),
+ io:format("$ ~s~n~s", [Cmd,DF0]),
+ Lines = re:split(DF0, "\n", [trim,{return,list}]),
+ Last = lists:last(Lines),
+ RE = "^[^\\s]*\\s+\\d+\\s+\\d+\\s+(\\d+)",
+ {match,[Avail]} = re:run(Last, RE, [{capture,all_but_first,list}]),
+ list_to_integer(Avail).
+
+zip_data([A|As], [B|Bs]) ->
+ [[A,B]|zip_data(As, Bs)];
+zip_data([], Bs) ->
+ Bs;
+zip_data(As, []) ->
+ As.
diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl
new file mode 100644
index 0000000000..4cf4c6489d
--- /dev/null
+++ b/lib/kernel/test/sendfile_SUITE.erl
@@ -0,0 +1,407 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(sendfile_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-compile(export_all).
+
+all() ->
+ [t_sendfile_small
+ ,t_sendfile_big_all
+ ,t_sendfile_big_size
+ ,t_sendfile_many_small
+ ,t_sendfile_partial
+ ,t_sendfile_offset
+ ,t_sendfile_sendafter
+ ,t_sendfile_recvafter
+ ,t_sendfile_sendduring
+ ,t_sendfile_recvduring
+ ,t_sendfile_closeduring
+ ,t_sendfile_crashduring
+ ].
+
+init_per_suite(Config) ->
+ case {os:type(),os:version()} of
+ {{unix,sunos}, {5,8,_}} ->
+ {skip, "Solaris 8 not supported for now"};
+ _ ->
+ Priv = ?config(priv_dir, Config),
+ SFilename = filename:join(Priv, "sendfile_small.html"),
+ {ok, DS} = file:open(SFilename,[write,raw]),
+ file:write(DS,"yo baby yo"),
+ file:sync(DS),
+ file:close(DS),
+ BFilename = filename:join(Priv, "sendfile_big.html"),
+ {ok, DB} = file:open(BFilename,[write,raw]),
+ [file:write(DB,[<<0:(10*8*1024*1024)>>]) || _I <- lists:seq(1,51)],
+ file:sync(DB),
+ file:close(DB),
+ [{small_file, SFilename},
+ {file_opts,[raw,binary]},
+ {big_file, BFilename}|Config]
+ end.
+
+end_per_suite(Config) ->
+ file:delete(proplists:get_value(big_file, Config)).
+
+init_per_testcase(TC,Config) when TC == t_sendfile_recvduring;
+ TC == t_sendfile_sendduring ->
+ Filename = proplists:get_value(small_file, Config),
+
+ Send = fun(Sock) ->
+ {_Size, Data} = sendfile_file_info(Filename),
+ {ok,D} = file:open(Filename, [raw,binary,read]),
+ prim_file:sendfile(D, Sock, 0, 0, 0,
+ [],[],false,false,false),
+ Data
+ end,
+
+ %% Check if sendfile is supported on this platform
+ case catch sendfile_send(Send) of
+ ok ->
+ Config;
+ Error ->
+ ct:log("Error: ~p",[Error]),
+ {skip,"Not supported"}
+ end;
+init_per_testcase(_Tc,Config) ->
+ Config.
+
+
+t_sendfile_small(Config) when is_list(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+
+ Send = fun(Sock) ->
+ {Size, Data} = sendfile_file_info(Filename),
+ {ok, Size} = file:sendfile(Filename, Sock),
+ Data
+ end,
+
+ ok = sendfile_send(Send).
+
+t_sendfile_many_small(Config) when is_list(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+ FileOpts = proplists:get_value(file_opts, Config, []),
+
+ error_logger:add_report_handler(?MODULE,[self()]),
+
+ Send = fun(Sock) ->
+ {Size,_} = sendfile_file_info(Filename),
+ N = 10000,
+ {ok,D} = file:open(Filename,[read|FileOpts]),
+ [begin
+ {ok,Size} = file:sendfile(D,Sock,0,0,[])
+ end || _I <- lists:seq(1,N)],
+ file:close(D),
+ Size*N
+ end,
+
+ ok = sendfile_send({127,0,0,1}, Send, 0),
+
+ receive
+ {stolen,Reason} ->
+ exit(Reason)
+ after 200 ->
+ ok
+ end.
+
+
+t_sendfile_big_all(Config) when is_list(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+
+ Send = fun(Sock) ->
+ {ok, #file_info{size = Size}} =
+ file:read_file_info(Filename),
+ {ok, Size} = file:sendfile(Filename, Sock),
+ Size
+ end,
+
+ ok = sendfile_send({127,0,0,1}, Send, 0).
+
+t_sendfile_big_size(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+ FileOpts = proplists:get_value(file_opts, Config, []),
+
+ SendAll = fun(Sock) ->
+ {ok, #file_info{size = Size}} =
+ file:read_file_info(Filename),
+ {ok,D} = file:open(Filename,[read|FileOpts]),
+ {ok, Size} = file:sendfile(D, Sock,0,Size,[]),
+ Size
+ end,
+
+ ok = sendfile_send({127,0,0,1}, SendAll, 0).
+
+t_sendfile_partial(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+ FileOpts = proplists:get_value(file_opts, Config, []),
+
+ SendSingle = fun(Sock) ->
+ {_Size, <<Data:5/binary,_/binary>>} =
+ sendfile_file_info(Filename),
+ {ok,D} = file:open(Filename,[read|FileOpts]),
+ {ok,5} = file:sendfile(D,Sock,0,5,[]),
+ file:close(D),
+ Data
+ end,
+ ok = sendfile_send(SendSingle),
+
+ {_Size, <<FData:5/binary,SData:3/binary,_/binary>>} =
+ sendfile_file_info(Filename),
+ {ok,D} = file:open(Filename,[read|FileOpts]),
+ {ok, <<FData/binary>>} = file:read(D,5),
+ FSend = fun(Sock) ->
+ {ok,5} = file:sendfile(D,Sock,0,5,[]),
+ FData
+ end,
+
+ ok = sendfile_send(FSend),
+
+ SSend = fun(Sock) ->
+ {ok,3} = file:sendfile(D,Sock,5,3,[]),
+ SData
+ end,
+
+ ok = sendfile_send(SSend),
+
+ {ok, <<SData/binary>>} = file:read(D,3),
+
+ file:close(D).
+
+t_sendfile_offset(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+ FileOpts = proplists:get_value(file_opts, Config, []),
+
+ Send = fun(Sock) ->
+ {_Size, <<_:5/binary,Data:3/binary,_/binary>> = AllData} =
+ sendfile_file_info(Filename),
+ {ok,D} = file:open(Filename,[read|FileOpts]),
+ {ok,3} = file:sendfile(D,Sock,5,3,[]),
+ {ok, AllData} = file:read(D,100),
+ file:close(D),
+ Data
+ end,
+ ok = sendfile_send(Send).
+
+
+t_sendfile_sendafter(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+
+ Send = fun(Sock) ->
+ {Size, Data} = sendfile_file_info(Filename),
+ {ok, Size} = file:sendfile(Filename, Sock),
+ ok = gen_tcp:send(Sock, <<2>>),
+ <<Data/binary,2>>
+ end,
+
+ ok = sendfile_send(Send).
+
+t_sendfile_recvafter(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+
+ Send = fun(Sock) ->
+ {Size, Data} = sendfile_file_info(Filename),
+ {ok, Size} = file:sendfile(Filename, Sock),
+ ok = gen_tcp:send(Sock, <<1>>),
+ {ok,<<1>>} = gen_tcp:recv(Sock, 1),
+ <<Data/binary,1>>
+ end,
+
+ ok = sendfile_send(Send).
+
+t_sendfile_sendduring(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+
+ Send = fun(Sock) ->
+ {ok, #file_info{size = Size}} =
+ file:read_file_info(Filename),
+ spawn_link(fun() ->
+ timer:sleep(50),
+ ok = gen_tcp:send(Sock, <<2>>)
+ end),
+ {ok, Size} = file:sendfile(Filename, Sock),
+ Size+1
+ end,
+
+ ok = sendfile_send({127,0,0,1}, Send, 0).
+
+t_sendfile_recvduring(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+
+ Send = fun(Sock) ->
+ {ok, #file_info{size = Size}} =
+ file:read_file_info(Filename),
+ spawn_link(fun() ->
+ timer:sleep(50),
+ ok = gen_tcp:send(Sock, <<1>>),
+ {ok,<<1>>} = gen_tcp:recv(Sock, 1)
+ end),
+ {ok, Size} = file:sendfile(Filename, Sock),
+ timer:sleep(1000),
+ Size+1
+ end,
+
+ ok = sendfile_send({127,0,0,1}, Send, 0).
+
+t_sendfile_closeduring(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+
+ Send = fun(Sock,SFServPid) ->
+ spawn_link(fun() ->
+ timer:sleep(50),
+ SFServPid ! stop
+ end),
+ case erlang:system_info(thread_pool_size) of
+ 0 ->
+ {error, closed} = file:sendfile(Filename, Sock);
+ _Else ->
+ %% This can return how much has been sent or
+ %% {error,closed} depending on OS.
+ %% How much is sent impossible to know as
+ %% the socket was closed mid sendfile
+ case file:sendfile(Filename, Sock) of
+ {error, closed} ->
+ ok;
+ {ok, Size} when is_integer(Size) ->
+ ok
+ end
+ end,
+ -1
+ end,
+
+ ok = sendfile_send({127,0,0,1}, Send, 0).
+
+t_sendfile_crashduring(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+
+ error_logger:add_report_handler(?MODULE,[self()]),
+
+ Send = fun(Sock) ->
+ spawn_link(fun() ->
+ timer:sleep(50),
+ exit(die)
+ end),
+ {error, closed} = file:sendfile(Filename, Sock),
+ -1
+ end,
+ process_flag(trap_exit,true),
+ spawn_link(fun() ->
+ ok = sendfile_send({127,0,0,1}, Send, 0)
+ end),
+ receive
+ {stolen,Reason} ->
+ process_flag(trap_exit,false),
+ ct:fail(Reason)
+ after 200 ->
+ receive
+ {'EXIT',_,Reason} ->
+ process_flag(trap_exit,false),
+ die = Reason
+ end
+ end.
+
+%% Generic sendfile server code
+sendfile_send(Send) ->
+ sendfile_send({127,0,0,1},Send).
+sendfile_send(Host, Send) ->
+ sendfile_send(Host, Send, []).
+sendfile_send(Host, Send, Orig) ->
+ SFServer = spawn_link(?MODULE, sendfile_server, [self(), Orig]),
+ receive
+ {server, Port} ->
+ {ok, Sock} = gen_tcp:connect(Host, Port,
+ [binary,{packet,0},
+ {active,false}]),
+ Data = case proplists:get_value(arity,erlang:fun_info(Send)) of
+ 1 ->
+ Send(Sock);
+ 2 ->
+ Send(Sock, SFServer)
+ end,
+ ok = gen_tcp:close(Sock),
+ receive
+ {ok, Bin} ->
+ Data = Bin,
+ ok
+ end
+ end.
+
+sendfile_server(ClientPid, Orig) ->
+ {ok, LSock} = gen_tcp:listen(0, [binary, {packet, 0},
+ {active, true},
+ {reuseaddr, true}]),
+ {ok, Port} = inet:port(LSock),
+ ClientPid ! {server, Port},
+ {ok, Sock} = gen_tcp:accept(LSock),
+ {ok, Bin} = sendfile_do_recv(Sock, Orig),
+ ClientPid ! {ok, Bin},
+ gen_tcp:send(Sock, <<1>>).
+
+-define(SENDFILE_TIMEOUT, 10000).
+sendfile_do_recv(Sock, Bs) ->
+ TimeoutMul = case os:type() of
+ {win32, _} -> 6;
+ _ -> 1
+ end,
+ receive
+ stop when Bs /= 0,is_integer(Bs) ->
+ gen_tcp:close(Sock),
+ {ok, -1};
+ {tcp, Sock, B} ->
+ case binary:match(B,<<1>>) of
+ nomatch when is_list(Bs) ->
+ sendfile_do_recv(Sock, [B|Bs]);
+ nomatch when is_integer(Bs) ->
+ sendfile_do_recv(Sock, byte_size(B) + Bs);
+ _ when is_list(Bs) ->
+ ct:log("Stopped due to a 1"),
+ {ok, iolist_to_binary(lists:reverse([B|Bs]))};
+ _ when is_integer(Bs) ->
+ ct:log("Stopped due to a 1"),
+ {ok, byte_size(B) + Bs}
+ end;
+ {tcp_closed, Sock} when is_list(Bs) ->
+ ct:log("Stopped due to close"),
+ {ok, iolist_to_binary(lists:reverse(Bs))};
+ {tcp_closed, Sock} when is_integer(Bs) ->
+ ct:log("Stopped due to close"),
+ {ok, Bs}
+ after ?SENDFILE_TIMEOUT * TimeoutMul ->
+ ct:log("Sendfile timeout"),
+ timeout
+ end.
+
+sendfile_file_info(File) ->
+ {ok, #file_info{size = Size}} = file:read_file_info(File),
+ {ok, Data} = file:read_file(File),
+ {Size, Data}.
+
+
+%% Error handler
+
+init([Proc]) -> {ok,Proc}.
+
+handle_event({error,noproc,{emulator,Format,Args}}, Proc) ->
+ Proc ! {stolen,lists:flatten(io_lib:format(Format,Args))},
+ {ok,Proc};
+handle_event(_, Proc) ->
+ {ok,Proc}.
diff --git a/lib/kernel/test/seq_trace_SUITE_data/echo_drv.c b/lib/kernel/test/seq_trace_SUITE_data/echo_drv.c
index dcbb3348d8..aa182b0877 100644
--- a/lib/kernel/test/seq_trace_SUITE_data/echo_drv.c
+++ b/lib/kernel/test/seq_trace_SUITE_data/echo_drv.c
@@ -3,7 +3,7 @@
static ErlDrvPort erlang_port;
static ErlDrvData echo_start(ErlDrvPort, char *);
-static void echo_stop(ErlDrvData), echo_read(ErlDrvData, char*, int);
+static void echo_stop(ErlDrvData), echo_read(ErlDrvData, char*, ErlDrvSizeT);
static ErlDrvEntry echo_driver_entry = {
NULL,
@@ -13,7 +13,22 @@ static ErlDrvEntry echo_driver_entry = {
NULL,
NULL,
"echo_drv",
- NULL
+ NULL,
+ NULL, /* handle */
+ NULL, /* control */
+ NULL, /* timeout */
+ NULL, /* outputv */
+ NULL, /* ready_async */
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
DRIVER_INIT(echo_drv)
@@ -31,7 +46,7 @@ static ErlDrvData echo_start(ErlDrvPort port,char *buf)
return (ErlDrvData)port;
}
-static void echo_read(ErlDrvData data, char *buf, int count)
+static void echo_read(ErlDrvData data, char *buf, ErlDrvSizeT count)
{
driver_output(erlang_port, buf, count);
}
diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl
index ffc8def626..96dc3e6d33 100644
--- a/lib/kernel/test/wrap_log_reader_SUITE.erl
+++ b/lib/kernel/test/wrap_log_reader_SUITE.erl
@@ -561,4 +561,4 @@ rec(M, Where) ->
end.
pps() ->
- {erlang:ports(), lists:filter({erlang, is_process_alive}, processes())}.
+ {erlang:ports(), lists:filter(fun erlang:is_process_alive/1, processes())}.
diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl
index 74bafe8935..bd237cb513 100644
--- a/lib/kernel/test/zlib_SUITE.erl
+++ b/lib/kernel/test/zlib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[{group, api}, {group, examples}, {group, func}, smp,
+ otp_9981,
otp_7359].
groups() ->
@@ -964,6 +965,24 @@ otp_7359_def_inf(Data,{DefSize,InfSize}) ->
?line ok = zlib:close(ZInf),
ok.
+otp_9981(Config) when is_list(Config) ->
+ Ports = lists:sort(erlang:ports()),
+ Invalid = <<"My invalid data">>,
+ catch zlib:compress(invalid),
+ Ports = lists:sort(erlang:ports()),
+ catch zlib:uncompress(Invalid),
+ Ports = lists:sort(erlang:ports()),
+ catch zlib:zip(invalid),
+ Ports = lists:sort(erlang:ports()),
+ catch zlib:unzip(Invalid),
+ Ports = lists:sort(erlang:ports()),
+ catch zlib:gzip(invalid),
+ Ports = lists:sort(erlang:ports()),
+ catch zlib:gunzip(Invalid),
+ Ports = lists:sort(erlang:ports()),
+ ok.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Helps with testing directly %%%%%%%%%%%%%
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 76c62ece67..c494f8a864 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.15
+KERNEL_VSN = 2.15.2
diff --git a/lib/megaco/.gitignore b/lib/megaco/.gitignore
new file mode 100644
index 0000000000..1c5979cd62
--- /dev/null
+++ b/lib/megaco/.gitignore
@@ -0,0 +1,3 @@
+examples/meas/Makefile
+examples/meas/meas.sh.skel
+examples/meas/mstone1.sh.skel
diff --git a/lib/megaco/Makefile b/lib/megaco/Makefile
index 10efaf667f..fc8f408b0a 100644
--- a/lib/megaco/Makefile
+++ b/lib/megaco/Makefile
@@ -49,11 +49,14 @@ VSN=$(MEGACO_VSN)
DIR_NAME = megaco_src-$(VSN)$(PRE_VSN)
+nullstring :=
+space := $(nullstring) # a space at the end
+
ifndef APP_RELEASE_DIR
ifndef TESTROOT
APP_RELEASE_DIR = /tmp
else
- APP_RELEASE_DIR = $(TESTROOT)
+ APP_RELEASE_DIR = $(subst $(space),\ ,$(TESTROOT))
endif
endif
@@ -97,9 +100,8 @@ endif
CONFIGURE_OPTS = $(FLEX_SCANNER_LINENO_ENABLER) $(FLEX_SCANNER_REENTRANT_ENABLER)
-MEGACO_DIA_PLT = ./priv/megaco.plt
-MEGACO_DIA_PLT_LOG = $(basename $(MEGACO_DIA_PLT)).dialyzer_plt_log
-MEGACO_DIA_LOG = $(basename $(MEGACO_DIA_PLT)).dialyzer_log
+DIA_PLT = ./priv/plt/$(APPLICATION).plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
# ----------------------------------------------------
@@ -140,8 +142,8 @@ info:
@echo "OTP_INSTALL_DIR: $(OTP_INSTALL_DIR)"
@echo "APP_INSTALL_DIR: $(APP_INSTALL_DIR)"
@echo ""
- @echo "MEGACO_PLT = $(MEGACO_PLT)"
- @echo "MEGACO_DIA_LOG = $(MEGACO_DIA_LOG)"
+ @echo "DIA_PLT: $(DIA_PLT)"
+ @echo "DIA_ANALYSIS: $(DIA_ANALYSIS)"
@echo ""
version:
@@ -152,7 +154,7 @@ version:
# Application install (of a app built from source) targets
# ----------------------------------------------------
app_install:
- $(MAKE) TESTROOT=$(APP_INSTALL_DIR) release
+ $(MAKE) TESTROOT="$(APP_INSTALL_DIR)" release
# ----------------------------------------------------
@@ -186,33 +188,33 @@ TAR.exclude2: Makefile TAR.exclude
(cd ..; find megaco -name '.cmake.state' >> megaco/TAR.exclude2)
$(APP_DIR): tar_exclude
- mkdir -p $(APP_DIR); \
+ mkdir -p "$(subst $(space),\ ,$@)"; \
(cd ..; tar cfX - megaco/TAR.exclude2 megaco) | \
- (cd $(APP_DIR); tar xf -); \
- mv $(APP_DIR)/megaco/* $(APP_DIR)/; \
- mkdir $(APP_DIR)/autoconf; \
- cp autoconf/config.guess $(APP_DIR)/autoconf/; \
- cp autoconf/config.sub $(APP_DIR)/autoconf/; \
- cp autoconf/install-sh $(APP_DIR)/autoconf/; \
- rmdir $(APP_DIR)/megaco
+ (cd "$(subst $(space),\ ,$@)"; tar xf -); \
+ mv "$(subst $(space),\ ,$@)"/megaco/* "$(subst $(space),\ ,$@)"/; \
+ mkdir $(subst $(space),\ ,$@)/autoconf; \
+ cp autoconf/config.guess "$(subst $(space),\ ,$@)"/autoconf/; \
+ cp autoconf/config.sub "$(subst $(space),\ ,$@)"/autoconf/; \
+ cp autoconf/install-sh "$(subst $(space),\ ,$@)"/autoconf/; \
+ rmdir "$(subst $(space),\ ,$@)"/megaco
tar: $(APP_TAR_FILE)
$(APP_TAR_FILE): $(APP_DIR)
- (cd $(APP_RELEASE_DIR); gtar zcf $(APP_TAR_FILE) $(DIR_NAME))
+ (cd "$(APP_RELEASE_DIR)"; gtar zcf "$(subst $(space),\ ,$@)" $(DIR_NAME))
-dialyzer_plt: $(MEGACO_DIA_PLT)
+dialyzer_plt: $(DIA_PLT)
-$(MEGACO_DIA_PLT):
- @echo "Building megaco plt file"
+$(DIA_PLT):
+ @echo "Building $(APPLICATION) plt file"
@dialyzer --build_plt \
--output_plt $@ \
- -r ../megaco/ebin \
- -o $(MEGACO_DIA_PLT_LOG) \
+ -r ../$(APPLICATION)/ebin \
+ --output $(DIA_ANALYSIS) \
--verbose
-dialyzer: $(MEGACO_DIA_PLT)
- (dialyzer --plt $< \
- -o $(MEGACO_DIA_LOG) \
- ../megaco/ebin \
- && (shell cat $(MEGACO_DIA_LOG)))
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on $(APPLICATION)"
+ @dialyzer --plt $< \
+ ../$(APPLICATION)/ebin \
+ --verbose
diff --git a/lib/megaco/configure.in b/lib/megaco/configure.in
index 8f94a4efcf..42c50b8961 100644
--- a/lib/megaco/configure.in
+++ b/lib/megaco/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2001-2010. All Rights Reserved.
+dnl Copyright Ericsson AB 2001-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
@@ -208,7 +208,7 @@ if test "X$host" = "Xwin32"; then
else
case $host_os in
darwin*)
- CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
+ CFLAGS="$CFLAGS -fno-common"
;;
esac
@@ -273,5 +273,6 @@ if test "$PERL" = no_perl; then
AC_MSG_ERROR([Perl is required to build the flex scanner!])
fi
+AC_OUTPUT(examples/meas/Makefile:examples/meas/Makefile.in)
AC_OUTPUT(src/flex/$host/Makefile:src/flex/Makefile.in)
diff --git a/lib/megaco/doc/src/Makefile b/lib/megaco/doc/src/Makefile
index 4b3c117b20..493304523e 100644
--- a/lib/megaco/doc/src/Makefile
+++ b/lib/megaco/doc/src/Makefile
@@ -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
@@ -27,14 +27,6 @@ VSN=$(MEGACO_VSN)
APPLICATION=megaco
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -73,35 +65,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi $(APP_FILE)
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-
-TOP_HTML_FILES = $(INDEX_TARGET)
-
-endif
-
INDEX_FILE = index.html
INDEX_SRC = $(INDEX_FILE).src
INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
@@ -131,8 +98,6 @@ $(HTMLDIR)/%.jpg: %.jpg
$(HTMLDIR)/%.png: %.png
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
ldocs: local_docs $(INDEX_TARGET)
@@ -147,41 +112,6 @@ clean clean_docs: clean_html clean_man
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html imgs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: imgs $(HTML_FILES) $(TOP_HTML_FILES)
-
-mhtml: html $(HTML_REF3_FILES) $(HTML_CHAPTER_FILES)
-
-clean: clean_html clean_man clean_pdf
- rm -f core *~
- rm -f *.aux *.cites *.citeshd *.dvi *.idx *.ilg *.ind
- rm -f *.indhd *.lof *.lofhd *.lot *.lothd *.otpdef
- rm -f *.otpuse *.terms *.termshd *.toc *.makeindexlog *.dvipslog
- rm -f *.bib *.bbl *.blg *.bibhd
-
-clean_pdf:
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f $(TEX_FILES_USERS_GUIDE)
- rm -f $(TEX_FILES_REF_MAN)
- rm -f $(TEX_FILES_BOOK)
-
-endif
-
clean_man:
rm -f $(MAN3DIR)/*
@@ -193,18 +123,19 @@ imgs: $(IMG_FILES:%=$(HTMLDIR)/%)
man: $(MAN3_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\/megaco-$(VSN).pdf/' $< > $@
+ sed -e 's/%VSN%/$(VSN)/' $< > $@
+
+$(INDEX_TARGET): $(INDEX_SRC) $(APP_FILE)
+ sed -e 's/%VSN%/$(VSN)/' \
+ -e 's/%ERLANG_SITE%/www\.erlang\.se\//' \
+ -e 's/%UP_ONE_LEVEL%/..\/..\/..\/doc\/index.html/' \
+ -e 's/%OFF_PRINT%/pdf\/megaco-$(VSN).pdf/' $< > $@
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)"
@@ -216,10 +147,6 @@ info:
@echo ""
@echo "IMG_FILES = $(IMG_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 "MAN3_FILES = $(MAN3_FILES)"
@echo ""
@echo "HTML_FILES = $(HTML_FILES)"
@@ -236,46 +163,17 @@ info:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELSYSDIR)/doc/standard
- $(INSTALL_DATA) $(STANDARDS) $(RELSYSDIR)/doc/standard
-
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(IMG_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(TOP_HTML_FILES) $(RELSYSDIR)/doc
- $(INSTALL_DIR) $(RELSYSDIR)/doc/standard
- $(INSTALL_DATA) $(STANDARDS) $(RELSYSDIR)/doc/standard
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/standard"
+ $(INSTALL_DATA) $(STANDARDS) "$(RELSYSDIR)/doc/standard"
release_spec:
diff --git a/lib/megaco/doc/src/make.dep b/lib/megaco/doc/src/make.dep
deleted file mode 100644
index 0e2040ab50..0000000000
--- a/lib/megaco/doc/src/make.dep
+++ /dev/null
@@ -1,59 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex megaco.tex megaco_architecture.tex \
- megaco_codec_meas.tex \
- megaco_codec_mstone1.tex megaco_codec_mstone2.tex \
- megaco_codec_transform.tex \
- megaco_debug.tex megaco_edist_compress.tex \
- megaco_encode.tex megaco_encoder.tex megaco_examples.tex \
- megaco_flex_scanner.tex megaco_intro.tex megaco_mib.tex \
- megaco_performance.tex megaco_run.tex megaco_tcp.tex \
- megaco_transport.tex megaco_transport_mechanisms.tex \
- megaco_udp.tex megaco_user.tex part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: call_flow.ps call_flow_cont.ps distr_node_config.ps \
- megaco_sys_arch.ps single_node_config.ps
-
-book.dvi: mstone1.ps
-
-book.dvi: MG-startup_flow_noMID.ps MGC_startup_call_flow.ps \
- MG_startup_call_flow.ps
-
diff --git a/lib/megaco/doc/src/megaco_run.xml b/lib/megaco/doc/src/megaco_run.xml
index 9ed589b079..b723778890 100644
--- a/lib/megaco/doc/src/megaco_run.xml
+++ b/lib/megaco/doc/src/megaco_run.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>
@@ -317,7 +317,7 @@
"in storage" (indicated by the transaction id) it is assumed to
be a resend and everything stored is sent. This could happen if
the values of the <c><![CDATA[trans_timer]]></c> and the
- <c><![CDATA[request_timer]]></c> is not properly choosen.</p>
+ <c><![CDATA[request_timer]]></c> is not properly chosen.</p>
</section>
<section>
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 2aba8db71b..928e3bea82 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2011</year>
+ <year>2000</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,6 +36,226 @@
section is the version number of Megaco.</p>
+ <section><title>Megaco 3.16.0.2</title>
+
+ <p>Version 3.16.0.2 supports code replacement in runtime from/to
+ version 3.16.0.1, 3.16, 3.15.1.1, 3.15.1 and 3.15.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Allow whitespaces in installation path. </p>
+ <p>It is now possible to give configure and make an
+ installation/release path with whitespaces in it. </p>
+ <p>Own Id: OTP-10107</p>
+ </item>
+
+ <item>
+ <p>Fix parallel make for behaviours. </p>
+ </item>
+
+ <item>
+ <p>Removed use of deprecated system flag,
+ <c>global_haeps_size</c>, in the measurement tool
+ <c>mstone1</c>. </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>
+ <title>Incompatibilities</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>Due to the change in the flex driver API,
+ we may no longer be able to build and/or use
+ the flex driver without reentrant support. </p>
+ <p>Own Id: OTP-9795</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ </section> <!-- 3.16.0.2 -->
+
+
+ <section><title>Megaco 3.16.0.1</title>
+
+ <p>Version 3.16.0.1 supports code replacement in runtime from/to
+ version 3.16, 3.15.1.1, 3.15.1 and 3.15.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Fixed some faulty test cases. </p>
+<!--
+ <p>Own Id: OTP-9795</p>
+-->
+ </item>
+
+ <item>
+ <p>Removed use of deprecated system flag,
+ <c>scheduler_bind_type</c>, in the measurement tool
+ <c>mstone1</c>. </p>
+ <p>Own Id: OTP-9949</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>
+ <title>Incompatibilities</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>Due to the change in the flex driver API,
+ we may no longer be able to build and/or use
+ the flex driver without reentrant support. </p>
+ <p>Own Id: OTP-9795</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ </section> <!-- 3.16.0.1 -->
+
+
+ <section><title>Megaco 3.16</title>
+
+ <p>Version 3.16 supports code replacement in runtime from/to
+ version 3.15.1.1, 3.15.1 and 3.15.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Minor improvements to the measurement tool <c>mstone1</c>. </p>
+ <p>Own Id: OTP-9604</p>
+ </item>
+
+ <item>
+ <p>ASN.1 no longer makes use of a driver to accelerate encode/decode,
+ instead it uses NIFs. The encoding config option is <em>still</em>
+ the same, i.e. <c>driver</c>. </p>
+ <p>Own Id: OTP-9672</p>
+ </item>
+
+ <item>
+ <p>The profiling test tool has been rewritten. </p>
+ <p>H&aring;kan Mattsson</p>
+ <p>Own Id: OTP-9679</p>
+ </item>
+
+ <item>
+ <p>The flex driver has been updated to support the new driver format
+ (changed to enable 64-bit aware drivers). </p>
+ <p>Own Id: OTP-9795</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>
+ <title>Incompatibilities</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>Due to the change in the flex driver API,
+ we may no longer be able to build and/or use
+ the flex driver without reentrant support. </p>
+ <p>Own Id: OTP-9795</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ </section> <!-- 3.16 -->
+
+
<section><title>Megaco 3.15.1.1</title>
<p>Version 3.15.1.1 supports code replacement in runtime from/to
diff --git a/lib/megaco/examples/meas/Makefile b/lib/megaco/examples/meas/Makefile
deleted file mode 100644
index 0a6cbb44a6..0000000000
--- a/lib/megaco/examples/meas/Makefile
+++ /dev/null
@@ -1,132 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2002-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-EBIN = .
-MEGACO_INCLUDEDIR = ../../include
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(MEGACO_VSN)
-
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
-EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
-MEAS_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/meas
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-include modules.mk
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-TARGET_FILES = \
- $(ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR))
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ifeq ($(WARN_UNUSED_WARS),true)
-ERL_COMPILE_FLAGS += +warn_unused_vars
-endif
-
-ifeq ($(USE_MEGACO_HIPE),true)
-ERL_COMPILE_FLAGS += +native
-endif
-
-ifeq ($(USE_VERBOSE_STATS),true)
-ERL_COMPILE_FLAGS += -DVERBOSE_STATS=true
-endif
-
-ifneq ($(MSTONE_TIME),)
-ERL_COMPILE_FLAGS += -DMSTONE_TIME=$(MSTONE_TIME)
-endif
-
-ERL_COMPILE_FLAGS += \
- -pa $(ERL_TOP)/lib/megaco/ebin \
- -I../include
-
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
-
-opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) $(EXAMPLE_RELSYSDIR)
- $(INSTALL_DIR) $(MEAS_RELSYSDIR)
- $(INSTALL_DATA) $(MESSAGE_PACKAGES) $(MEAS_RELSYSDIR)
- $(INSTALL_DATA) $(SCRIPT_SKELETONS) $(MEAS_RELSYSDIR)
- $(INSTALL_DATA) $(TARGET_FILES) $(MEAS_RELSYSDIR)
- $(INSTALL_DATA) $(ERL_FILES) $(MEAS_RELSYSDIR)
-
-
-release_docs_spec:
-
-
-# ----------------------------------------------------
-# Include dependencies
-# ----------------------------------------------------
-
-megaco_codec_transform.$(EMULATOR): megaco_codec_transform.erl
-
-megaco_codec_meas.$(EMULATOR): megaco_codec_meas.erl
-
-megaco_codec_mstone1.$(EMULATOR): megaco_codec_mstone1.erl
-
-megaco_codec_mstone2.$(EMULATOR): megaco_codec_mstone2.erl
-
-megaco_codec_mstone_lib.$(EMULATOR): megaco_codec_mstone_lib.erl
-
diff --git a/lib/megaco/examples/meas/Makefile.in b/lib/megaco/examples/meas/Makefile.in
new file mode 100644
index 0000000000..607d81d440
--- /dev/null
+++ b/lib/megaco/examples/meas/Makefile.in
@@ -0,0 +1,166 @@
+#
+# %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 $(ERL_TOP)/make/target.mk
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug -W
+endif
+
+EBIN = .
+MEGACO_INCLUDEDIR = ../../include
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(MEGACO_VSN)
+
+
+# ----------------------------------------------------
+# Configured variables
+# ----------------------------------------------------
+PERL = @PERL@
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
+EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
+MEAS_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/meas
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+SCRIPT_SKELETONS = $(SCRIPT_SKELETON_SRC:%.src=%)
+
+ERL_TARGETS = \
+ $(ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR))
+
+TARGET_FILES = $(SCRIPT_SKELETONS) $(ERL_TARGETS)
+
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ifeq ($(WARN_UNUSED_WARS),true)
+ERL_COMPILE_FLAGS += +warn_unused_vars
+endif
+
+ifeq ($(USE_MEGACO_HIPE),true)
+ERL_COMPILE_FLAGS += +native
+endif
+
+ifeq ($(USE_VERBOSE_STATS),true)
+ERL_COMPILE_FLAGS += -DVERBOSE_STATS=true
+endif
+
+ifneq ($(MSTONE_TIME),)
+ERL_COMPILE_FLAGS += -DMSTONE_TIME=$(MSTONE_TIME)
+endif
+
+ERL_COMPILE_FLAGS += \
+ -pa $(ERL_TOP)/lib/megaco/ebin \
+ -I../include
+
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+debug:
+ @${MAKE} TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+script_skeletons: $(SCRIPT_SKELETONS)
+
+info:
+ @echo "MODULES = $(MODULES)"
+ @echo "ERL_FILED = $(ERL_FILES)"
+ @echo ""
+ @echo "SCRIPT_SKELETON_SRC = $(SCRIPT_SKELETON_SRC)"
+ @echo "SCRIPT_SKELETONS = $(SCRIPT_SKELETONS)"
+ @echo ""
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+conf:
+ cd ../..; $(MAKE) conf
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+
+release_spec: opt
+ $(INSTALL_DIR) "$(EXAMPLE_RELSYSDIR)"
+ $(INSTALL_DIR) "$(MEAS_RELSYSDIR)"
+ $(INSTALL_DATA) $(MESSAGE_PACKAGES) "$(MEAS_RELSYSDIR)"
+ $(INSTALL_DATA) $(SCRIPT_SKELETONS) "$(MEAS_RELSYSDIR)"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(MEAS_RELSYSDIR)"
+ $(INSTALL_DATA) $(ERL_FILES) "$(MEAS_RELSYSDIR)"
+
+
+release_docs_spec:
+
+
+# ----------------------------------------------------
+# Include dependencies
+# ----------------------------------------------------
+
+meas.sh.skel: meas.sh.skel.src
+ @echo "transforming $< to $@"
+ $(PERL) -p -e 's?%VSN%?$(VSN)? ' < $< > $@
+
+mstone1.sh.skel: mstone1.sh.skel.src
+ @echo "transforming $< to $@"
+ $(PERL) -p -e 's?%VSN%?$(VSN)? ' < $< > $@
+
+megaco_codec_transform.$(EMULATOR): megaco_codec_transform.erl
+
+megaco_codec_meas.$(EMULATOR): megaco_codec_meas.erl
+
+megaco_codec_mstone1.$(EMULATOR): megaco_codec_mstone1.erl
+
+megaco_codec_mstone2.$(EMULATOR): megaco_codec_mstone2.erl
+
+megaco_codec_mstone_lib.$(EMULATOR): megaco_codec_mstone_lib.erl
+
diff --git a/lib/megaco/examples/meas/meas.sh.skel b/lib/megaco/examples/meas/meas.sh.skel
deleted file mode 100644
index 76745ed8f4..0000000000
--- a/lib/megaco/examples/meas/meas.sh.skel
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-# %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%
-
-#
-# Skeleton for a script intended to run the meas test.
-#
-
-ERL_HOME=<path to otp top dir>
-MEGACO_HOME=$ERL_HOME/lib/erlang/lib/<megaco dir>
-MEAS_HOME=$MEGACO_HOME/examples/meas
-PATH=$ERL_HOME/bin:$PATH
-
-# MEAS_TIME_TEST="-s megaco_codec_meas start time_test"
-MEAS_DEFAULT="-s megaco_codec_meas start"
-STOP="-s init stop"
-
-ERL="erl \
- -noshell \
- -pa $MEAS_HOME \
- $MEAS_DEFAULT \
- $STOP"
-
-echo $ERL
-$ERL | tee meas.log
-
diff --git a/lib/megaco/examples/meas/meas.sh.skel.src b/lib/megaco/examples/meas/meas.sh.skel.src
new file mode 100644
index 0000000000..ecf463b9c6
--- /dev/null
+++ b/lib/megaco/examples/meas/meas.sh.skel.src
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2007-2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+#
+# Skeleton for a script intended to run the meas test.
+#
+
+ERL_HOME=<path to otp top dir>
+MEGACO_HOME=$ERL_HOME/lib/erlang/lib/megaco-%VSN%
+MEAS_HOME=$MEGACO_HOME/examples/meas
+PATH=$ERL_HOME/bin:$PATH
+
+# MEAS_TIME_TEST="-s megaco_codec_meas start time_test"
+MEAS_DEFAULT="-s megaco_codec_meas start"
+STOP="-s init stop"
+
+ERL="erl \
+ -noshell \
+ +sbt tnnps \
+ -pa $MEAS_HOME \
+ $MEAS_DEFAULT \
+ $STOP"
+
+echo $ERL
+$ERL | tee meas.log
+
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone1.erl b/lib/megaco/examples/meas/megaco_codec_mstone1.erl
index 9ab7822df8..2133cd633c 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone1.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,6 @@ mstone_init(MessagePackage, Factor, Codecs, DrvInclude) ->
do_mstone(MessagePackage, Factor, Codecs, DrvInclude) ->
io:format("~n", []),
- ?LIB:set_default_sched_bind(),
?LIB:display_os_info(),
?LIB:display_system_info(),
?LIB:display_app_info(),
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone2.erl b/lib/megaco/examples/meas/megaco_codec_mstone2.erl
index f3588f2e3d..54b889345f 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone2.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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 @@
%% When the finished timer expires, it will stop respawing
%% the worker processes, and instead just wait for them all
%% to finish.
-%% The test is finished by printing the statistics.
+%% The test is finishes by printing the statistics.
%% - A worker process for each codec combination.
%% This process is spawned by the loader process. It receives
%% at start a list of messages. It shall decode and then
@@ -162,7 +162,6 @@ parse_message_package(BadMessagePackage) ->
mstone_init(MessagePackage, DrvInclude) ->
io:format("~n", []),
- ?LIB:set_default_sched_bind(),
?LIB:display_os_info(),
?LIB:display_system_info(),
?LIB:display_app_info(),
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
index 040af9826b..9af88d9f50 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,6 @@
-compile({no_auto_import,[error/1]}).
-export([start_flex_scanner/0, stop_flex_scanner/1,
expanded_messages/2, expanded_messages/3,
- set_default_sched_bind/0,
display_os_info/0,
display_system_info/0,
display_alloc_info/0,
@@ -70,16 +69,6 @@ detect_version(Codec, Conf, Bin) ->
%%----------------------------------------------------------------------
%%
-%% S c h e d u l e r b i n d t y p e
-%%
-%%----------------------------------------------------------------------
-
-set_default_sched_bind() ->
- (catch erlang:system_flag(scheduler_bind_type, default_bind)).
-
-
-%%----------------------------------------------------------------------
-%%
%% D i s p l a y O s I n f o
%%
%%----------------------------------------------------------------------
@@ -111,7 +100,6 @@ display_system_info() ->
OtpRel = otp_release(),
SysVer = system_version(),
SysHT = heap_type(),
- SysGHSz = global_heaps_size(),
SysSMP = smp_support(),
SysNumSched = schedulers(),
SysProcLimit = process_limit(),
@@ -124,7 +112,6 @@ display_system_info() ->
io:format("OTP release: ~s~n", [OtpRel]),
io:format("System version: ~s~n", [SysVer]),
io:format("Heap type: ~s~n", [SysHT]),
- io:format("Global heap size: ~s~n", [SysGHSz]),
io:format("Thread support: ~s~n", [SysThreads]),
io:format("Thread pool size: ~s~n", [SysTPSz]),
io:format("Process limit: ~s~n", [SysProcLimit]),
@@ -148,9 +135,6 @@ system_version() ->
heap_type() ->
system_info(heap_type, any).
-global_heaps_size() ->
- system_info(global_heaps_size, any).
-
smp_support() ->
system_info(smp_support, any).
diff --git a/lib/megaco/examples/meas/modules.mk b/lib/megaco/examples/meas/modules.mk
index 8f1b45c8a6..26979933d7 100644
--- a/lib/megaco/examples/meas/modules.mk
+++ b/lib/megaco/examples/meas/modules.mk
@@ -2,7 +2,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
@@ -17,9 +17,9 @@
#
# %CopyrightEnd%
-SCRIPT_SKELETONS = \
- meas.sh.skel \
- mstone1.sh.skel
+SCRIPT_SKELETON_SRC = \
+ meas.sh.skel.src \
+ mstone1.sh.skel.src
MESSAGE_PACKAGES = \
time_test.msgs
diff --git a/lib/megaco/examples/meas/mstone1.sh.skel b/lib/megaco/examples/meas/mstone1.sh.skel
deleted file mode 100644
index b7c7e41007..0000000000
--- a/lib/megaco/examples/meas/mstone1.sh.skel
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/bin/sh
-
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2007-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-
-# Skeleton for a script intended to run the mstone1(N)
-# performance test.
-#
-
-# Get the name of the program
-program=`echo $0 | sed 's#.*/##g'`
-
-usage="\
-Usage: $program [options]
-
-This shell script is used to run the mstone 1 (factor) performance
-test. It is not intended to test the megaco stack but instead to
-give a \"performance value\" of the host on which it is run.
-
-Options:
- -help display this help and exit.
- -mp <message package> message package to use for test
- default is time_test
- -h <num> default process heap size
- -a <num> async thread pool size (default is 0)
- -f <factor> normally the test is run with 16 processes
- (factor 1), one for each codec config. The test
- can however be run with other factors, e.g.
- factor 10 means that 10 processes will be started
- for each megaco codec config.
- The options -s and -f cannot both be present.
- -s <num sched> normally the test is run with a fixed factor,
- but if this option is given, the number of
- schedulers is fixed (to the value set by this option)
- and the factor is the variable.
- The options -s and -f cannot both be present.
- -d <drv-mode> driver mode for the test:
- std - all codec config(s) will be used
- flex - only the text codec config(s) utilizing the
- flex scanner will be used
- nd - only codec config(s) without drivers will be used
- od - only codec config(s) with drivers will be used
- -- everything after this is just passed on to erl.
-"
-
-ERL_HOME=<path to otp top dir>
-MEGACO_HOME=$ERL_HOME/lib/erlang/lib/<megaco dir>
-MEAS_HOME=$MEGACO_HOME/examples/meas
-PATH=$ERL_HOME/bin:$PATH
-
-MODULE=megaco_codec_mstone1
-STARTF="start"
-FACTOR=""
-MSG_PACK=time_test
-
-while test $# != 0; do
- # echo "DBG: Value = $1"
- case $1 in
- -help)
- echo "$usage" ;
- exit 0;;
-
- -mp)
- MSG_PACK="$2";
- shift ; shift ;;
-
- -h)
- PHS="+h $2";
- shift ; shift ;;
-
- -a)
- ATP="+A $2";
- shift ; shift ;;
-
- -d)
- case $2 in
- std)
- STARTF="start";
- shift ; shift ;;
- flex)
- STARTF="start_flex";
- shift ; shift ;;
- nd)
- STARTF="start_no_drv";
- shift ; shift ;;
- od)
- STARTF="start_only_drv";
- shift ; shift ;;
- *)
- echo "unknown driver mode: $2";
- echo "$usage" ;
- exit 0
- esac;;
-
- -f)
- if [ "x$SCHED" != "x" ]; then
- echo "option(s) -s and -f cannot both be given" ;
- echo "$usage" ;
- exit 0
- fi
- FACTOR="$2";
- TYPE=factor;
- shift ; shift ;;
-
- -s)
- if [ "x$FACTOR" != "x" ]; then
- echo "option(s) -f and -s cannot both be given" ;
- echo "$usage" ;
- exit 0
- fi
- SCHED="$2";
- TYPE=sched;
- shift ; shift ;;
-
- --)
- shift ;
- break;;
-
- *)
- echo "unknown option: $1";
- echo "$usage" ;
- exit 0
- esac
-done
-
-if [ $TYPE = factor ]; then
-
- MSTONE="-s $MODULE $STARTF $MSG_PACK $FACTOR"
-
- # SCHEDS="no_smp 01 02 04"
- # SCHEDS="no_smp 01 02 04 08"
- # SCHEDS="no_smp 01 02 04 08 16"
- # SCHEDS="no_smp 01 02 04 08 16 32"
- # SCHEDS="no_smp 01 02 04 08 16 32 64"
- SCHEDS="no_smp 01 02 03 04 05 06 07 08"
-
- for i in `echo $SCHEDS`; do
- case $i in
- no_smp)
- SMP_INFO="No SMP"
- SMP_OPTS="-smp disable" # THIS IS THE R12B WAY TO DISABLE SMP
- LOG="mstone1-f$FACTOR-s00.log"
- ;;
-
- 01)
- SMP_INFO="SMP: 1 scheduler"
- SMP_OPTS="-smp +S $i"
- LOG="mstone1-f$FACTOR-s$i.log"
- ;;
-
- *)
- SMP_INFO="SMP: $i schedulers"
- SMP_OPTS="-smp +S $i"
- LOG="mstone1-f$FACTOR-s$i.log"
- ;;
- esac
-
- echo ""
- echo "---------------------------------------------"
- echo "$SMP_INFO"
- echo ""
-
- ERL="erl \
- -noshell \
- $PHS \
- $ATP \
- $SMP_OPTS \
- -pa $MEAS_HOME \
- $MSTONE \
- $* \
- -s init stop"
-
- echo $ERL
- $ERL | tee $LOG
- done
-
-elif [ $TYPE = sched ]; then
-
- MSTONE="-s $MODULE $STARTF $MSG_PACK"
-
- # FACTORS="01 02 03 04"
- # FACTORS="01 02 03 04 05 06 07 08 09 10"
- FACTORS="01 02 04 08 16 32"
- # FACTORS="001 010 100"
-
- case $SCHED in
- no_smp)
- SMP_OPTS="-smp disable" # THIS IS THE R12B WAY TO DISABLE SMP
- ;;
-
- *)
- SMP_OPTS="-smp +S $SCHED"
- ;;
- esac
-
- for i in `echo $FACTORS`; do
- LOG="mstone1-s$SCHED-f$i.log"
-
- echo ""
- echo "---------------------------------------------"
- echo "Factor $i"
- echo ""
-
- ERL="erl \
- -noshell \
- $PHS \
- $ATP \
- $SMP_OPTS \
- -pa $MEAS_HOME \
- $MSTONE $i \
- $* \
- -s init stop"
-
- echo $ERL
- $ERL | tee $LOG
- done
-
-
-else
- echo "Either option -f or -s must be specified"
- echo "$usage" ;
- exit 0
-
-fi
diff --git a/lib/megaco/examples/meas/mstone1.sh.skel.src b/lib/megaco/examples/meas/mstone1.sh.skel.src
new file mode 100644
index 0000000000..b1935acef6
--- /dev/null
+++ b/lib/megaco/examples/meas/mstone1.sh.skel.src
@@ -0,0 +1,262 @@
+#!/bin/sh
+
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2007-2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+# Skeleton for a script intended to run the mstone1(N)
+# performance test.
+#
+
+# Get the name of the program
+program=`echo $0 | sed 's#.*/##g'`
+
+usage="\
+Usage: $program [options]
+
+This shell script is used to run the mstone 1 (factor) performance
+test. It is not intended to test the megaco stack but instead to
+give a \"performance value\" of the host on which it is run.
+
+Options:
+ -help display this help and exit.
+ -mp <message package> message package to use for test
+ default is time_test
+ -h <num> default process heap size
+ -a <num> async thread pool size (default is 0)
+ -f <factor> normally the test is run with 16 processes
+ (factor 1), one for each codec config. The test
+ can however be run with other factors, e.g.
+ factor 10 means that 10 processes will be started
+ for each megaco codec config.
+ The options -s and -f cannot both be present.
+ -s <num sched> normally the test is run with a fixed factor,
+ but if this option is given, the number of
+ schedulers is fixed (to the value set by this option)
+ and the factor is the variable.
+ The options -s and -f cannot both be present.
+ -d <drv-mode> driver mode for the test:
+ std - all codec config(s) will be used
+ flex - only the text codec config(s) utilizing the
+ flex scanner will be used
+ nd - only codec config(s) without drivers will be used
+ od - only codec config(s) with drivers will be used
+ -sbt <bind-type> Set scheduler bind type. See erl man page for more info.
+ tnnps - Thread no node processor spread (default)
+ u - Unbound
+ ns - No spread
+ ts - Thread spread
+ ps - Processor spread
+ s - Spread
+ nnts - No node thread spread
+ nnps - No node processor spread
+ -- everything after this is just passed on to erl.
+"
+
+ERL_HOME=<path to otp top dir>
+MEGACO_HOME=$ERL_HOME/lib/erlang/lib/megaco-%VSN%
+MEAS_HOME=$MEGACO_HOME/examples/meas
+PATH=$ERL_HOME/bin:$PATH
+
+MODULE=megaco_codec_mstone1
+STARTF="start"
+FACTOR=""
+MSG_PACK=time_test
+SBT="+sbt tnnps"
+
+while test $# != 0; do
+ # echo "DBG: Value = $1"
+ case $1 in
+ -help)
+ echo "$usage" ;
+ exit 0;;
+
+ -mp)
+ MSG_PACK="$2";
+ shift ; shift ;;
+
+ -h)
+ PHS="+h $2";
+ shift ; shift ;;
+
+ -a)
+ ATP="+A $2";
+ shift ; shift ;;
+
+ -d)
+ case $2 in
+ std)
+ STARTF="start";
+ shift ; shift ;;
+ flex)
+ STARTF="start_flex";
+ shift ; shift ;;
+ nd)
+ STARTF="start_no_drv";
+ shift ; shift ;;
+ od)
+ STARTF="start_only_drv";
+ shift ; shift ;;
+ *)
+ echo "unknown driver mode: $2";
+ echo "$usage" ;
+ exit 0
+ esac;;
+
+ -sbt)
+ case $2 in
+ tnnps|u|ns|ts|ps|s|nnts|nnps)
+ SBT="+sbt $2";
+ shift ; shift ;;
+ *)
+ echo "unknown scheduler bind type: $2";
+ echo "$usage" ;
+ exit 0
+ esac;;
+
+ -f)
+ if [ "x$SCHED" != "x" ]; then
+ echo "option(s) -s and -f cannot both be given" ;
+ echo "$usage" ;
+ exit 0
+ fi
+ FACTOR="$2";
+ TYPE=factor;
+ shift ; shift ;;
+
+ -s)
+ if [ "x$FACTOR" != "x" ]; then
+ echo "option(s) -f and -s cannot both be given" ;
+ echo "$usage" ;
+ exit 0
+ fi
+ SCHED="$2";
+ TYPE=sched;
+ shift ; shift ;;
+
+ --)
+ shift ;
+ break;;
+
+ *)
+ echo "unknown option: $1";
+ echo "$usage" ;
+ exit 0
+ esac
+done
+
+if [ $TYPE = factor ]; then
+
+ MSTONE="-s $MODULE $STARTF $MSG_PACK $FACTOR"
+
+ # SCHEDS="no_smp 01 02 04"
+ # SCHEDS="no_smp 01 02 04 08"
+ # SCHEDS="no_smp 01 02 04 08 16"
+ # SCHEDS="no_smp 01 02 04 08 16 32"
+ # SCHEDS="no_smp 01 02 04 08 16 32 64"
+ SCHEDS="no_smp 01 02 03 04 05 06 07 08"
+
+ for i in `echo $SCHEDS`; do
+ case $i in
+ no_smp)
+ SMP_INFO="No SMP"
+ SMP_OPTS="-smp disable" # THIS IS THE R12B WAY TO DISABLE SMP
+ LOG="mstone1-f$FACTOR-s00.log"
+ ;;
+
+ 01)
+ SMP_INFO="SMP: 1 scheduler"
+ SMP_OPTS="-smp +S $i"
+ LOG="mstone1-f$FACTOR-s$i.log"
+ ;;
+
+ *)
+ SMP_INFO="SMP: $i schedulers"
+ SMP_OPTS="-smp +S $i"
+ LOG="mstone1-f$FACTOR-s$i.log"
+ ;;
+ esac
+
+ echo ""
+ echo "---------------------------------------------"
+ echo "$SMP_INFO"
+ echo ""
+
+ ERL="erl \
+ -noshell \
+ $SBT \
+ $PHS \
+ $ATP \
+ $SMP_OPTS \
+ -pa $MEAS_HOME \
+ $MSTONE \
+ $* \
+ -s init stop"
+
+ echo $ERL
+ $ERL | tee $LOG
+ done
+
+elif [ $TYPE = sched ]; then
+
+ MSTONE="-s $MODULE $STARTF $MSG_PACK"
+
+ # FACTORS="01 02 03 04"
+ # FACTORS="01 02 03 04 05 06 07 08 09 10"
+ FACTORS="01 02 04 08 16 32"
+ # FACTORS="001 010 100"
+
+ case $SCHED in
+ no_smp)
+ SMP_OPTS="-smp disable" # THIS IS THE R12B WAY TO DISABLE SMP
+ ;;
+
+ *)
+ SMP_OPTS="-smp +S $SCHED"
+ ;;
+ esac
+
+ for i in `echo $FACTORS`; do
+ LOG="mstone1-s$SCHED-f$i.log"
+
+ echo ""
+ echo "---------------------------------------------"
+ echo "Factor $i"
+ echo ""
+
+ ERL="erl \
+ -noshell \
+ $SBT \
+ $PHS \
+ $ATP \
+ $SMP_OPTS \
+ -pa $MEAS_HOME \
+ $MSTONE $i \
+ $* \
+ -s init stop"
+
+ echo $ERL
+ $ERL | tee $LOG
+ done
+
+
+else
+ echo "Either option -f or -s must be specified"
+ echo "$usage" ;
+ exit 0
+
+fi
diff --git a/lib/megaco/examples/simple/Makefile b/lib/megaco/examples/simple/Makefile
index f91d1d886f..261acbb479 100644
--- a/lib/megaco/examples/simple/Makefile
+++ b/lib/megaco/examples/simple/Makefile
@@ -139,9 +139,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DIR) $(RELSYSDIR)/examples/simple
- $(INSTALL_DATA) $(ERL_FILES) $(TARGET_FILES) $(RELSYSDIR)/examples/simple
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/simple"
+ $(INSTALL_DATA) $(ERL_FILES) $(TARGET_FILES) "$(RELSYSDIR)/examples/simple"
release_docs_spec:
diff --git a/lib/megaco/include/megaco_message_prev3a.hrl b/lib/megaco/include/megaco_message_prev3a.hrl
index 7b7a60fdae..3e73f94761 100644
--- a/lib/megaco/include/megaco_message_prev3a.hrl
+++ b/lib/megaco/include/megaco_message_prev3a.hrl
@@ -563,7 +563,7 @@
%% This is the actual ASN.1 type and it is as this it will
-%% be represented if the encoding config [native] is choosen.
+%% be represented if the encoding config [native] is chosen.
%% %% String of at least 1 character and at most 67 characters (ASN.1).
%% %% 64 characters for name, 1 for "/", 2 for version to match ABNF
%% -record('ServiceChangeProfile',
diff --git a/lib/megaco/include/megaco_message_prev3b.hrl b/lib/megaco/include/megaco_message_prev3b.hrl
index cfabb29941..b4bde2bb7e 100644
--- a/lib/megaco/include/megaco_message_prev3b.hrl
+++ b/lib/megaco/include/megaco_message_prev3b.hrl
@@ -563,7 +563,7 @@
%% This is the actual ASN.1 type and it is as this it will
-%% be represented if the encoding config [native] is choosen.
+%% be represented if the encoding config [native] is chosen.
%% %% String of at least 1 character and at most 67 characters (ASN.1).
%% %% 64 characters for name, 1 for "/", 2 for version to match ABNF
%% -record('ServiceChangeProfile',
diff --git a/lib/megaco/include/megaco_message_prev3c.hrl b/lib/megaco/include/megaco_message_prev3c.hrl
index 32024c9a02..90612f66c8 100644
--- a/lib/megaco/include/megaco_message_prev3c.hrl
+++ b/lib/megaco/include/megaco_message_prev3c.hrl
@@ -748,7 +748,7 @@
%% This is the actual ASN.1 type and it is as this it will
-%% be represented if the encoding config [native] is choosen.
+%% be represented if the encoding config [native] is chosen.
%% %% String of at least 1 character and at most 67 characters (ASN.1).
%% %% 64 characters for name, 1 for "/", 2 for version to match ABNF
%% -record('ServiceChangeProfile',
diff --git a/lib/megaco/include/megaco_message_v1.hrl b/lib/megaco/include/megaco_message_v1.hrl
index ba50b50c80..f196c26713 100644
--- a/lib/megaco/include/megaco_message_v1.hrl
+++ b/lib/megaco/include/megaco_message_v1.hrl
@@ -404,7 +404,7 @@
}). % with extension mark
%% This is the actual ASN.1 type and it is as this it will
-%% be represented if the encoding config [native] is choosen.
+%% be represented if the encoding config [native] is chosen.
% %% String of at least 1 character and at most 67 characters (ASN.1).
% %% 64 characters for name, 1 for "/", 2 for version to match ABNF
% -record('ServiceChangeProfile',
diff --git a/lib/megaco/include/megaco_message_v2.hrl b/lib/megaco/include/megaco_message_v2.hrl
index 6190ea7ac4..af79c4dc92 100644
--- a/lib/megaco/include/megaco_message_v2.hrl
+++ b/lib/megaco/include/megaco_message_v2.hrl
@@ -525,7 +525,7 @@
%% This is the actual ASN.1 type and it is as this it will
-%% be represented if the encoding config [native] is choosen.
+%% be represented if the encoding config [native] is chosen.
%% %% String of at least 1 character and at most 67 characters (ASN.1).
%% %% 64 characters for name, 1 for "/", 2 for version to match ABNF
%% -record('ServiceChangeProfile',
diff --git a/lib/megaco/include/megaco_message_v3.hrl b/lib/megaco/include/megaco_message_v3.hrl
index 7a1bc80571..466cfa6856 100644
--- a/lib/megaco/include/megaco_message_v3.hrl
+++ b/lib/megaco/include/megaco_message_v3.hrl
@@ -743,7 +743,7 @@
%% This is the actual ASN.1 type and it is as this it will
-%% be represented if the encoding config [native] is choosen.
+%% be represented if the encoding config [native] is chosen.
%% %% String of at least 1 character and at most 67 characters (ASN.1).
%% %% 64 characters for name, 1 for "/", 2 for version to match ABNF
%% -record('ServiceChangeProfile',
diff --git a/lib/megaco/priv/plt/.gitignore b/lib/megaco/priv/plt/.gitignore
new file mode 100644
index 0000000000..2051b52d48
--- /dev/null
+++ b/lib/megaco/priv/plt/.gitignore
@@ -0,0 +1,2 @@
+/*.plt
+/*.dialyzer_analysis
diff --git a/lib/megaco/src/app/Makefile b/lib/megaco/src/app/Makefile
index 01dfb9b860..a7b458845d 100644
--- a/lib/megaco/src/app/Makefile
+++ b/lib/megaco/src/app/Makefile
@@ -108,14 +108,14 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/app
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/app
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/app"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/app"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/megaco/src/app/megaco.appup.src b/lib/megaco/src/app/megaco.appup.src
index 7107178d1a..a7b38eb107 100644
--- a/lib/megaco/src/app/megaco.appup.src
+++ b/lib/megaco/src/app/megaco.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,39 +139,65 @@
%% |
%% v
%% 3.15.1.1
+%% |
+%% v
+%% 3.16
+%% |
+%% v
+%% 3.16.0.1
+%% |
+%% v
+%% 3.16.0.2
%%
%%
{"%VSN%",
[
+ {"3.16.0.1",
+ [
+ ]
+ },
+ {"3.16",
+ [
+ ]
+ },
+ {"3.15.1.1",
+ [
+ {restart_application, megaco}
+ ]
+ },
{"3.15.1",
[
+ {restart_application, megaco}
]
},
{"3.15",
[
- {load_module, megaco_flex_scanner, soft_purge, soft_purge, []},
- {load_module, megaco_sdp, soft_purge, soft_purge, []},
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {load_module, megaco_timer, soft_purge, soft_purge, [megaco_config_misc]},
- {update, megaco_config, soft, soft_purge, soft_purge,
- [megaco_timer, megaco_config_misc]},
- {add_module, megaco_config_misc}
+ {restart_application, megaco}
]
}
],
[
+ {"3.16.0.1",
+ [
+ ]
+ },
+ {"3.16",
+ [
+ ]
+ },
+ {"3.15.1.1",
+ [
+ {restart_application, megaco}
+ ]
+ },
{"3.15.1",
[
+ {restart_application, megaco}
]
},
{"3.15",
[
- {load_module, megaco_flex_scanner, soft_purge, soft_purge, []},
- {load_module, megaco_sdp, soft_purge, soft_purge, []},
- {load_module, megaco_filter, soft_purge, soft_purge, []},
- {load_module, megaco_timer, soft_purge, soft_purge, [megaco_config]},
- {update, megaco_config, soft, soft_purge, soft_purge, []},
- {remove, {megaco_config_misc, soft_purge, brutal_purge}}
+ {restart_application, megaco}
]
}
]
diff --git a/lib/megaco/src/binary/Makefile b/lib/megaco/src/binary/Makefile
index d594f34f43..77b06c81d3 100644
--- a/lib/megaco/src/binary/Makefile
+++ b/lib/megaco/src/binary/Makefile
@@ -194,11 +194,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/binary
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(ASN1_FILES) $(RELSYSDIR)/src/binary
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/binary"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(ASN1_FILES) "$(RELSYSDIR)/src/binary"
release_docs_spec:
diff --git a/lib/megaco/src/binary/depend.mk b/lib/megaco/src/binary/depend.mk
index d12bd8bad0..c9ca34bcf6 100644
--- a/lib/megaco/src/binary/depend.mk
+++ b/lib/megaco/src/binary/depend.mk
@@ -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
@@ -24,9 +24,9 @@
# but for per_bin it means that a stage in the encode
# is done in the asn1 driver.
#
-# +driver
+# +nif
# For ber_bin this means that part of the decode is done
-# in the asn1 driver.
+# in the asn1 nif.
#
# +asn1config
# This is only used by the ber_bin, and means that
@@ -45,22 +45,22 @@ endif
BER_V1_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_V2_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_PREV3A_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_PREV3A_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_PREV3B_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_PREV3B_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_PREV3C_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_PREV3C_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
BER_V3_FLAGS = $(ASN1_CT_OPTS)
BER_BIN_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize
-BER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +driver
+BER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config +optimize +nif
PER_V1_FLAGS = $(ASN1_CT_OPTS)
PER_BIN_V1_FLAGS = $(ASN1_CT_OPTS)
PER_BIN_DRV_V1_FLAGS = $(ASN1_CT_OPTS) +optimize
diff --git a/lib/megaco/src/engine/Makefile b/lib/megaco/src/engine/Makefile
index 3943f4b957..ae2fadb3fc 100644
--- a/lib/megaco/src/engine/Makefile
+++ b/lib/megaco/src/engine/Makefile
@@ -42,9 +42,14 @@ RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
include modules.mk
-ERL_FILES = $(MODULES:%=%.erl)
+ERL_FILES = \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
-TARGET_FILES = \
+BEHAVIOUR_TARGET_FILES= \
+ $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+TARGET_FILES = \
$(MODULES:%=$(EBIN)/%.$(EMULATOR))
@@ -65,19 +70,23 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
+
debug:
@${MAKE} TYPE=debug opt
opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
rm -f errs core *~
docs:
info:
@echo "MODULES = $(MODULES)"
+ @echo "BEHAVIOUR_MODULES = $(BEHAVIOUR_MODULES)"
@echo ""
@@ -88,12 +97,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/engine
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/engine
- $(INSTALL_DIR) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/engine"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/engine"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/megaco/src/engine/megaco_digit_map.erl b/lib/megaco/src/engine/megaco_digit_map.erl
index de28686d6d..bf798d7938 100644
--- a/lib/megaco/src/engine/megaco_digit_map.erl
+++ b/lib/megaco/src/engine/megaco_digit_map.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
@@ -362,7 +362,7 @@ collect(Event, State, Timers, STL, Letters) ->
"~n Timers2: ~p"
"~n Letters2: ~p", [State2, Timers2, Letters2]),
MaxWait = choose_timer(State2, Event, Timers2),
- ?d("collect -> Timer choosen: "
+ ?d("collect -> Timer chosen: "
"~n MaxWait: ~p", [MaxWait]),
receive
{?MODULE, _FromPid, Event2} ->
@@ -737,7 +737,7 @@ compute_cont([Next | Cont] = All, Mode, GlobalMode, State, STL) ->
"~n Mode: ~p"
"~n GlobalMode: ~p", [Next, Mode, GlobalMode]),
case Next of
- %% Retain long timer if that has already been choosen
+ %% Retain long timer if that has already been chosen
use_short_timer when GlobalMode =:= use_long_timer ->
compute_cont(Cont, Mode, GlobalMode, State, STL);
use_short_timer ->
diff --git a/lib/megaco/src/engine/modules.mk b/lib/megaco/src/engine/modules.mk
index 4bc57cd63e..6e2f9246f0 100644
--- a/lib/megaco/src/engine/modules.mk
+++ b/lib/megaco/src/engine/modules.mk
@@ -23,7 +23,6 @@ BEHAVIOUR_MODULES = \
megaco_transport
MODULES = \
- $(BEHAVIOUR_MODULES) \
megaco_config_misc \
megaco_config \
megaco_digit_map \
diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in
index 2c46a673e4..976ecaa4f7 100644
--- a/lib/megaco/src/flex/Makefile.in
+++ b/lib/megaco/src/flex/Makefile.in
@@ -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
@@ -271,16 +271,16 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/flex
- $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/flex
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/flex"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/flex"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
ifeq ($(ENABLE_MEGACO_FLEX_SCANNER),true)
- $(INSTALL_DATA) $(FLEX_FILES) $(C_TARGETS) $(RELSYSDIR)/src/flex
- $(INSTALL_PROGRAM) $(SOLIBS) $(RELSYSDIR)/priv/lib
+ $(INSTALL_DATA) $(FLEX_FILES) $(C_TARGETS) "$(RELSYSDIR)/src/flex"
+ $(INSTALL_PROGRAM) $(SOLIBS) "$(RELSYSDIR)/priv/lib"
endif
diff --git a/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src b/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src
index 9b4f717201..b8146c345d 100644
--- a/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src
+++ b/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src
@@ -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
@@ -60,18 +60,11 @@
#define NUL 0x0
#if defined(MEGACO_REENTRANT_FLEX_SCANNER)
- #define MEGACO_EXTENDED_MARKER ERL_DRV_EXTENDED_MARKER
- #define MEGACO_DRIVER_FLAGS ERL_DRV_FLAG_USE_PORT_LOCKING
- #define MEGACO_EXTENDED_MAJOR_VERSION ERL_DRV_EXTENDED_MAJOR_VERSION
- #define MEGACO_EXTENDED_MINOR_VERSION ERL_DRV_EXTENDED_MINOR_VERSION
-#else
- #define MEGACO_EXTENDED_MARKER 0
- #define MEGACO_DRIVER_FLAGS 0
- #define MEGACO_EXTENDED_MAJOR_VERSION 0
- #define MEGACO_EXTENDED_MINOR_VERSION 0
+# define MEGACO_DRIVER_FLAGS ERL_DRV_FLAG_USE_PORT_LOCKING
+#else
+# define MEGACO_DRIVER_FLAGS 0
#endif
-
#define FREE(bufP) driver_free(bufP)
#define ALLOC(sz) driver_alloc(sz)
#define REALLOC(bufP, sz) driver_realloc(bufP, sz)
@@ -320,11 +313,11 @@ static void mfs_load_map_token();
static ErlDrvData mfs_start(ErlDrvPort port, char *buf);
static void mfs_stop(ErlDrvData handle);
static void mfs_command(ErlDrvData handle,
- char *buf, int buf_len);
-static int mfs_control(ErlDrvData handle,
+ char *buf, ErlDrvSizeT buf_len);
+static ErlDrvSSizeT mfs_control(ErlDrvData handle,
unsigned int command,
- char *buf, int buf_len,
- char **res_buf, int res_buf_len);
+ char *buf, ErlDrvSizeT buf_len,
+ char **res_buf, ErlDrvSizeT res_buf_len);
static void mfs_finish(void);
/*
@@ -348,10 +341,10 @@ static ErlDrvEntry mfs_entry = {
NULL, /* flush, port is about to be closed */
NULL, /* call, a syncronous call into the driver */
NULL, /* event, event selected by driver_event() has occurred */
- MEGACO_EXTENDED_MARKER, /* extended_marker, which we use if reentrant */
- MEGACO_EXTENDED_MAJOR_VERSION, /* major_version, ... */
- MEGACO_EXTENDED_MINOR_VERSION, /* minor_version, ... */
- MEGACO_DRIVER_FLAGS, /* driver_flags, used for port lock indication */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ MEGACO_DRIVER_FLAGS, /* driver_flags, used for port lock indication */
NULL, /* handle2, emulator internal use */
NULL /* process_exit, Called when a process monitor fires */
};
@@ -1685,17 +1678,17 @@ static void mfs_stop(ErlDrvData handle)
}
static void mfs_command(ErlDrvData handle,
- char *buf, int buf_len)
+ char *buf, ErlDrvSizeT buf_len)
{
driver_failure_atom(((MfsErlDrvData*) handle)->port, "bad_usage");
return;
}
-static int mfs_control(ErlDrvData handle,
+static ErlDrvSSizeT mfs_control(ErlDrvData handle,
unsigned int command,
- char *buf, int buf_len,
- char **res_buf, int res_buf_len)
+ char *buf, ErlDrvSizeT buf_len,
+ char **res_buf, ErlDrvSizeT res_buf_len)
{
MfsErlDrvData* dataP = (MfsErlDrvData*) handle;
char* tmp;
diff --git a/lib/megaco/src/tcp/Makefile b/lib/megaco/src/tcp/Makefile
index 0bd4b7c4ee..efc76bb2c5 100644
--- a/lib/megaco/src/tcp/Makefile
+++ b/lib/megaco/src/tcp/Makefile
@@ -89,11 +89,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/tcp
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/tcp
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/tcp"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/tcp"
release_docs_spec:
diff --git a/lib/megaco/src/text/Makefile b/lib/megaco/src/text/Makefile
index b2e8e762dd..2c7703cd33 100644
--- a/lib/megaco/src/text/Makefile
+++ b/lib/megaco/src/text/Makefile
@@ -130,11 +130,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(BEAM_TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/text
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_YRL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/text
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(BEAM_TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/text"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_YRL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/text"
release_docs_spec:
diff --git a/lib/megaco/src/udp/Makefile b/lib/megaco/src/udp/Makefile
index 64b6478c2c..db9bb72d82 100644
--- a/lib/megaco/src/udp/Makefile
+++ b/lib/megaco/src/udp/Makefile
@@ -89,11 +89,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/udp
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/udp
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/udp"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/udp"
release_docs_spec:
diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile
index 88f6f06e73..b1bca10ca8 100644
--- a/lib/megaco/test/Makefile
+++ b/lib/megaco/test/Makefile
@@ -748,11 +748,11 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(RELTEST_FILES) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(RELTEST_FILES) "$(RELSYSDIR)"
# $(INSTALL_DATA) $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) \
# $(HRL_FILES) $(ERL_FILES) \
-# $(RELSYSDIR)
+# "$(RELSYSDIR)"
#
- chmod -R u+w $(RELSYSDIR)
+ chmod -R u+w "$(RELSYSDIR)"
diff --git a/lib/megaco/test/megaco_codec_v1_test.erl b/lib/megaco/test/megaco_codec_v1_test.erl
index 3a548c4d9e..e9c19605dd 100644
--- a/lib/megaco/test/megaco_codec_v1_test.erl
+++ b/lib/megaco/test/megaco_codec_v1_test.erl
@@ -371,9 +371,9 @@ profile_decode_text_messages(Slogan, Codec, Config, Msgs0) ->
decode_text_messages(Codec, Config, Bins, [])
end,
%% Make a dry run, just to make sure all modules are loaded:
- io:format("make a dry run..~n", []),
+ io:format("make a dry run...~n", []),
(catch Fun()),
- io:format("make the run..~n", []),
+ io:format("make the run...~n", []),
megaco_profile:profile(Slogan, Fun).
%% (catch megaco_codec_v1_test:profile_encode_compact_text_messages()).
diff --git a/lib/megaco/test/megaco_codec_v2_test.erl b/lib/megaco/test/megaco_codec_v2_test.erl
index c3a80febba..a44f74166c 100644
--- a/lib/megaco/test/megaco_codec_v2_test.erl
+++ b/lib/megaco/test/megaco_codec_v2_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
@@ -346,9 +346,9 @@ profile_decode_text_messages(Slogan, Codec, Config, Msgs0) ->
decode_text_messages(Codec, Config, Bins, [])
end,
%% Make a dry run, just to make sure all modules are loaded:
- io:format("make a dry run..~n", []),
+ io:format("make a dry run...~n", []),
(catch Fun()),
- io:format("make the run..~n", []),
+ io:format("make the run...~n", []),
megaco_profile:profile(Slogan, Fun).
%% (catch megaco_codec_v2_test:profile_encode_compact_text_messages()).
diff --git a/lib/megaco/test/megaco_mess_test.erl b/lib/megaco/test/megaco_mess_test.erl
index ded1506271..663ac8c329 100644
--- a/lib/megaco/test/megaco_mess_test.erl
+++ b/lib/megaco/test/megaco_mess_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,12 +34,12 @@
%% -compile(export_all).
-export([
- all/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
+ all/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,
connect/1,
-
request_and_reply_plain/1,
request_and_no_reply/1,
@@ -324,9 +324,6 @@
min(M) -> timer:minutes(M).
%% Test server callbacks
-% init_per_testcase(pending_ack = Case, Config) ->
-% put(dbg,true),
-% megaco_test_lib:init_per_testcase(Case, Config);
init_per_testcase(otp_7189 = Case, Config) ->
C = lists:keydelete(tc_timeout, 1, Config),
megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(2)} |C]);
@@ -337,9 +334,6 @@ init_per_testcase(Case, Config) ->
C = lists:keydelete(tc_timeout, 1, Config),
megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(1)} |C]).
-% end_per_testcase(pending_ack = Case, Config) ->
-% erase(dbg),
-% megaco_test_lib:end_per_testcase(Case, Config);
end_per_testcase(Case, Config) ->
megaco_test_lib:end_per_testcase(Case, Config).
@@ -347,39 +341,83 @@ end_per_testcase(Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [connect, {group, request_and_reply},
- {group, pending_ack}, dist, {group, tickets}].
+ [
+ connect,
+ {group, request_and_reply},
+ {group, pending_ack},
+ dist,
+ {group, tickets}
+ ].
groups() ->
- [{request_and_reply, [],
- [request_and_reply_plain, request_and_no_reply,
+ [
+ {request_and_reply, [],
+ [request_and_reply_plain,
+ request_and_no_reply,
request_and_reply_pending_ack_no_pending,
request_and_reply_pending_ack_one_pending,
single_trans_req_and_reply,
single_trans_req_and_reply_sendopts,
- request_and_reply_and_ack, request_and_reply_and_no_ack,
+ request_and_reply_and_ack,
+ request_and_reply_and_no_ack,
request_and_reply_and_late_ack,
trans_req_and_reply_and_req]},
{pending_ack, [],
[pending_ack_plain,
request_and_pending_and_late_reply]},
{tickets, [],
- [otp_4359, otp_4836, otp_5805, otp_5881, otp_5887,
- otp_6253, otp_6275, otp_6276, {group, otp_6442},
- {group, otp_6865}, otp_7189, otp_7259, otp_7713,
- {group, otp_8183}, otp_8212]},
+ [otp_4359,
+ otp_4836,
+ otp_5805,
+ otp_5881,
+ otp_5887,
+ otp_6253,
+ otp_6275,
+ otp_6276,
+ {group, otp_6442},
+ {group, otp_6865},
+ otp_7189,
+ otp_7259,
+ otp_7713,
+ {group, otp_8183},
+ otp_8212]},
{otp_6442, [],
- [otp_6442_resend_request1, otp_6442_resend_request2,
- otp_6442_resend_reply1, otp_6442_resend_reply2]},
+ [otp_6442_resend_request1,
+ otp_6442_resend_request2,
+ otp_6442_resend_reply1,
+ otp_6442_resend_reply2]},
{otp_6865, [],
[otp_6865_request_and_reply_plain_extra1,
otp_6865_request_and_reply_plain_extra2]},
- {otp_8183, [], [otp_8183_request1]}].
+ {otp_8183, [], [otp_8183_request1]}
+ ].
+
+
+init_per_suite(Config) ->
+ io:format("~w:init_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n", [?MODULE, Config]),
+ Config.
+
+end_per_suite(_Config) ->
+ io:format("~w:end_per_suite -> entry with"
+ "~n _Config: ~p"
+ "~n", [?MODULE, _Config]),
+ ok.
+
init_per_group(_GroupName, Config) ->
+ io:format("~w:init_per_group -> entry with"
+ "~n _GroupName: ~p"
+ "~n Config: ~p"
+ "~n", [?MODULE, _GroupName, Config]),
Config.
end_per_group(_GroupName, Config) ->
+ io:format("~w:end_per_group -> entry with"
+ "~n _GroupName: ~p"
+ "~n Config: ~p"
+ "~n", [?MODULE, _GroupName, Config]),
Config.
@@ -390,16 +428,21 @@ connect(suite) ->
connect(doc) ->
[];
connect(Config) when is_list(Config) ->
+ %% ?SKIP("Needs a re-write..."),
?ACQUIRE_NODES(1, Config),
PrelMid = preliminary_mid,
MgMid = ipv4_mid(4711),
+ d("connect -> start megaco app",[]),
?VERIFY(ok, application:start(megaco)),
+ d("connect -> start (MG) user ~p",[MgMid]),
?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, bad_send_mod},
{request_timer, infinity},
{reply_timer, infinity}])),
+ d("connect -> get receive info for ~p",[MgMid]),
MgRH = user_info(MgMid, receive_handle),
+ d("connect -> (MG) try connect to MGC",[]),
{ok, PrelCH} = ?VERIFY({ok, _}, megaco:connect(MgRH, PrelMid, sh, self())),
connections([PrelCH]),
@@ -408,9 +451,29 @@ connect(Config) when is_list(Config) ->
?VERIFY(bad_send_mod, megaco:user_info(MgMid, send_mod)),
?VERIFY(bad_send_mod, megaco:conn_info(PrelCH, send_mod)),
SC = service_change_request(),
- ?VERIFY({1, {error, {send_message_failed, {'EXIT',
- {undef, [{bad_send_mod, send_message, [sh, _]} | _]}}}}},
- megaco:call(PrelCH, [SC], [])),
+ case megaco:call(PrelCH, [SC], []) of
+ {_Version,
+ {error,
+ {send_message_failed,
+ {'EXIT', {undef, [{bad_send_mod, send_message, [sh, _]} | _]}}}}
+ } ->
+ %% R14B and previous
+ ?LOG("expected send failure (1)", []),
+ ok;
+
+ %% As of R15, we also get some extra info (e.g. line numbers)
+ {_Version,
+ {error,
+ {send_message_failed,
+ {'EXIT', {undef, [{bad_send_mod, send_message, [sh, _], _} | _]}}}}
+ } ->
+ %% R15B and later
+ ?LOG("expected send failure (2)", []),
+ ok;
+
+ Unexpected ->
+ ?ERROR(Unexpected)
+ end,
?VERIFY(ok, megaco:disconnect(PrelCH, shutdown)),
@@ -6776,16 +6839,12 @@ rapalr_mg_notify_request_ar(Rid, Tid, Cid) ->
-
-
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dist(suite) ->
[];
dist(Config) when is_list(Config) ->
+ ?SKIP("Needs a re-write..."),
[_Local, Dist] = ?ACQUIRE_NODES(2, Config),
d("dist -> start proxy",[]),
megaco_mess_user_test:start_proxy(),
@@ -6897,7 +6956,11 @@ dist(Config) when is_list(Config) ->
?VERIFY(ok, application:stop(megaco)),
?RECEIVE([]),
- d("dist -> done",[]),
+
+ d("dist -> stop proxy",[]),
+ megaco_mess_user_test:stop_proxy(),
+
+ d("dist -> done", []),
ok.
diff --git a/lib/megaco/test/megaco_profile.erl b/lib/megaco/test/megaco_profile.erl
index d0b62610e1..fd72604e92 100644
--- a/lib/megaco/test/megaco_profile.erl
+++ b/lib/megaco/test/megaco_profile.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
@@ -24,50 +24,102 @@
-module(megaco_profile).
--export([profile/2]).
-
+-export([profile/2, prepare/2, analyse/1,
+ fprof_to_calltree/1, fprof_to_calltree/2, fprof_to_calltree/3]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Execute Fun and profile it with fprof.
-profile(Slogan, Fun) when is_function(Fun) ->
+profile(Slogan, Fun) when is_function(Fun, 0) ->
Pids = [self()],
- profile(Slogan, Fun, Pids).
+ {ok, TraceFile} = prepare(Slogan, Pids),
+ Res = (catch Fun()),
+ {ok, _DestFile} = analyse(Slogan),
+ ok = file:delete(TraceFile),
+ {ok, _TreeFile} = fprof_to_calltree(Slogan),
+ Res.
-profile(Slogan, Fun, Pids) ->
+%% Prepare for tracing
+prepare(Slogan, Pids) ->
TraceFile = lists:concat(["profile_", Slogan, "-fprof.trace"]),
- DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
- TreeFile = lists:concat(["profile_", Slogan, ".calltree"]),
- erlang:garbage_collect(),
{ok, _Pid} = fprof:start(),
+ erlang:garbage_collect(),
TraceOpts = [start,
- {cpu_time, false},
- {procs, Pids},
- {file, TraceFile}
+ {cpu_time, false},
+ {procs, Pids},
+ {file, TraceFile}
],
- ok = fprof:trace(TraceOpts),
- Res = (catch Fun()),
- ok = fprof:trace(stop),
- ok = fprof:profile([{file, TraceFile}]),
- ok = fprof:analyse([{dest, DestFile}]),
- ok = fprof:stop(),
- ok = file:delete(TraceFile),
- reformat_total(DestFile, TreeFile),
- Res.
+ ok = fprof:trace(TraceOpts),
+ {ok, TraceFile}.
-reformat_total(FromFile, ToFile) ->
- {ok, ConsultedFromFile} = file:consult(FromFile),
- [_AnalysisOpts, [Totals] | Terms] = ConsultedFromFile,
- {totals, _, TotalAcc, _} = Totals,
+%% Stop tracing and analyse it
+analyse(Slogan) ->
+ fprof:trace(stop),
+ TraceFile = lists:concat(["profile_", Slogan, "-fprof.trace"]),
+ DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
+ try
+ case fprof:profile([{file, TraceFile}]) of
+ ok ->
+ ok = fprof:analyse([{dest, DestFile}, {totals, false}]),
+ {ok, DestFile};
+ {error, Reason} ->
+ {error, Reason}
+ end
+ after
+ fprof:stop()
+ end.
+
+fprof_to_calltree(Slogan) ->
+ fprof_to_calltree(Slogan, 0).
+
+fprof_to_calltree(Slogan, MinPercent) ->
+ DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
+ TreeFile = lists:concat(["profile_", Slogan, ".calltree"]),
+ fprof_to_calltree(DestFile, TreeFile, MinPercent).
+
+%% Create a calltree from an fprof file
+fprof_to_calltree(FromFile, ToFile, MinPercent) ->
+ ReplyTo = self(),
+ Ref = make_ref(),
+ spawn_link(fun() ->
+ ReplyTo ! {Ref, do_fprof_to_calltree(FromFile, ToFile, MinPercent)}
+ end),
+ wait_for_reply(Ref).
+
+wait_for_reply(Ref) ->
+ receive
+ {Ref, Res} ->
+ Res;
+ {'EXIT', normal} ->
+ wait_for_reply(Ref);
+ {'EXIT', Reason} ->
+ exit(Reason)
+ end.
+
+do_fprof_to_calltree(FromFile, ToFile, MinPercent) ->
{ok, Fd} = file:open(ToFile, [write, raw]),
- Indent = "",
- log(Fd, Indent, TotalAcc, Totals),
- Processes = split_processes(Terms, [], []),
- Reformat = fun(P) -> reformat_process(Fd, " " ++ Indent, TotalAcc, P) end,
- lists:foreach(Reformat, Processes),
- file:close(Fd).
+ {ok, ConsultedFromFile} = file:consult(FromFile),
+ [_AnalysisOpts, [_Totals] | Terms] = ConsultedFromFile,
+ Processes = split_processes(Terms, [], []),
+ Indent = "",
+ Summary = collapse_processes(Processes),
+ {_Label, _Cnt, Acc, _Own, _Roots, Details} = Summary,
+ %% log(Fd, Label, Indent, Acc, {Label, Cnt, Acc, Own}, [], 0),
+ gen_calltree(Fd, Indent, Acc, Summary, MinPercent),
+ Delim = io_lib:format("\n~80..=c\n\n", [$=]),
+ Write =
+ fun(P) ->
+ file:write(Fd, Delim),
+ gen_calltree(Fd, Indent, Acc, P, MinPercent)
+ end,
+ lists:foreach(Write, Processes),
+ file:write(Fd, Delim),
+ gen_details(Fd, Acc, Details),
+ file:close(Fd),
+ {ok, ToFile}.
+%% Split all fprof terms into a list of processes
split_processes([H | T], ProcAcc, TotalAcc) ->
if
is_tuple(H) ->
@@ -75,64 +127,185 @@ split_processes([H | T], ProcAcc, TotalAcc) ->
is_list(H), ProcAcc =:= [] ->
split_processes(T, [H], TotalAcc);
is_list(H) ->
- split_processes(T, [H], [lists:reverse(ProcAcc) | TotalAcc])
+ ProcAcc2 = rearrange_process(lists:reverse(ProcAcc)),
+ split_processes(T, [H], [ProcAcc2 | TotalAcc])
end;
split_processes([], [], TotalAcc) ->
- lists:reverse(TotalAcc);
+ lists:reverse(lists:keysort(3, TotalAcc));
split_processes([], ProcAcc, TotalAcc) ->
- lists:reverse([lists:reverse(ProcAcc) | TotalAcc]).
-
-reformat_process(Fd, Indent, TotalAcc, Terms) ->
- case Terms of
- [[{ProcLabel, _, _, _}] | All] -> ok;
- [[{ProcLabel,_,_,_} | _] | All] -> ok
- end,
- [{_, {TopKey, TopCnt, TopAcc, TopOwn}, _} | _] = All,
- Process = {ProcLabel, TopCnt, TopAcc, TopOwn},
- log(Fd, Indent, TotalAcc, Process),
- reformat_calls(Fd, " " ++ Indent, TotalAcc, TopKey, All, []).
-
-reformat_calls(Fd, Indent, TotalAcc, Key, Terms, Stack) ->
- {_CalledBy, Current, Calls} = find(Key, Terms),
- log(Fd, Indent, TotalAcc, Current),
- case lists:member(Key, Stack) of
- true ->
- ok;
- false ->
- case Key of
- {io_lib, _, _} ->
- ok;
- {disk_log, _, _} ->
- ok;
- {lists, flatten, _} ->
- ok;
- {lists, keysort, _} ->
- ok;
- _ ->
- Fun = fun({NextKey, _, _, _}) ->
- reformat_calls(Fd,
- " " ++ Indent,
- TotalAcc,
- NextKey,
- Terms,
- [Key | Stack])
- end,
- lists:foreach(Fun, Calls)
- end
+ ProcAcc2 = rearrange_process(lists:reverse(ProcAcc)),
+ lists:reverse(lists:keysort(3, [ProcAcc2 | TotalAcc])).
+
+%% Rearrange the raw process list into a more useful format
+rearrange_process([[{Label, _Cnt, _Acc, _Own} | _ ] | Details]) ->
+ do_rearrange_process(Details, Details, Label, [], []).
+
+do_rearrange_process([{CalledBy, Current, _Calls} | T], Orig, Label, Roots, Undefs) ->
+ case [{undefined, Cnt, safe_max(Acc, Own), Own} ||
+ {undefined, Cnt, Acc, Own} <- CalledBy] of
+ [] ->
+ do_rearrange_process(T, Orig, Label, Roots, Undefs);
+ NewUndefs ->
+ do_rearrange_process(T, Orig, Label, [Current | Roots], NewUndefs ++ Undefs)
+ end;
+do_rearrange_process([], Details, Label, Roots, Undefs) ->
+ [{undefined, Cnt, Acc, Own}] = collapse_calls(Undefs, []),
+ Details2 = sort_details(3, Details),
+ {Label, Cnt, Acc, Own, lists:reverse(lists:keysort(3, Roots)), Details2}.
+
+%% Compute a summary of the rearranged process info
+collapse_processes(Processes) ->
+ Headers = lists:map(fun({_L, C, A, O, _R, _D}) -> {"SUMMARY", C, A, O} end,
+ Processes),
+ [{Label, Cnt, Acc, Own}] = collapse_calls(Headers, []),
+ Details = lists:flatmap(fun({_L, _C, _A, _O, _R, D}) -> D end, Processes),
+ Details2 = do_collapse_processes(sort_details(1, Details), []),
+ Roots = lists:flatmap(fun({_L, _C, _A, _O, R, _D}) -> R end, Processes),
+ RootMFAs = lists:usort([MFA || {MFA, _, _, _} <- Roots]),
+ Roots2 = [R || RootMFA <- RootMFAs,
+ {_, {MFA, _, _, _} = R, _} <- Details2,
+ MFA =:= RootMFA],
+ Roots3 = collapse_calls(Roots2, []),
+ {Label, Cnt, Acc, Own, Roots3, Details2}.
+
+do_collapse_processes([{CalledBy1, {MFA, Cnt1, Acc1, Own1}, Calls1} | T1],
+ [{CalledBy2, {MFA, Cnt2, Acc2, Own2}, Calls2} | T2]) ->
+ Cnt = Cnt1 + Cnt2,
+ Acc = Acc1 + Acc2,
+ Own = Own1 + Own2,
+ Current = {MFA, Cnt, Acc, Own},
+ CalledBy0 = CalledBy1 ++ CalledBy2,
+ Calls0 = Calls1 ++ Calls2,
+ CalledBy = collapse_calls(lists:keysort(3, CalledBy0), []),
+ Calls = collapse_calls(lists:keysort(3, Calls0), []),
+ do_collapse_processes(T1, [{CalledBy, Current, Calls} | T2]);
+do_collapse_processes([{CalledBy, Current, Calls} | T1],
+ T2) ->
+ do_collapse_processes(T1, [{CalledBy, Current, Calls} | T2]);
+do_collapse_processes([],
+ T2) ->
+ sort_details(3, T2).
+
+%% Reverse sort on acc field
+sort_details(Pos, Details) ->
+ Pivot = fun({_CalledBy1, Current1, _Calls1},
+ {_CalledBy2, Current2, _Calls2}) ->
+ element(Pos, Current1) =< element(Pos, Current2)
+ end,
+ lists:reverse(lists:sort(Pivot, Details)).
+
+%% Compute a summary from a list of call tuples
+collapse_calls([{MFA, Cnt1, Acc1, Own1} | T1],
+ [{MFA, Cnt2, Acc2, Own2} | T2]) ->
+ Cnt = Cnt1 + Cnt2,
+ Acc = safe_sum(Acc1, Acc2),
+ Own = Own1 + Own2,
+ collapse_calls(T1, [{MFA, Cnt, Acc, Own} | T2]);
+collapse_calls([{MFA, Cnt, Acc, Own} | T1],
+ T2) ->
+ collapse_calls(T1, [{MFA, Cnt, Acc, Own} | T2]);
+collapse_calls([],
+ T2) ->
+ lists:reverse(lists:keysort(3, T2)).
+
+safe_sum(Int1, Int2) ->
+ if
+ Int1 =:= undefined -> Int2;
+ Int2 =:= undefined -> Int1;
+ true -> Int1 + Int2
+ end.
+
+safe_max(Int1, Int2) ->
+ if
+ Int1 =:= undefined ->
+ io:format("111\n", []),
+ Int2;
+ Int2 =:= undefined ->
+ io:format("222\n", []),
+ Int1;
+ Int2 > Int1 -> Int2;
+ true -> Int1
+ end.
+
+%% Compute a calltree and write it to file
+gen_calltree(Fd, Indent, TotalAcc, {Label, Cnt, Acc, Own, Roots, Details}, MinPercent) ->
+ Header = {Label, Cnt, Acc, Own},
+ MetaLabel = "Process",
+ Diff = length(Label) - length(MetaLabel),
+ IoList = io_lib:format("~s~s Lvl Pct Cnt Acc Own Calls => MFA\n",
+ [MetaLabel, lists:duplicate(Diff, $\ )]),
+ file:write(Fd, IoList),
+ log(Fd, Label, Indent, TotalAcc, Header, Roots, MinPercent),
+ NewIndent = " " ++ Indent,
+ Fun = fun({MFA, _C, _A, _O}) ->
+ [put_detail(Label, D) || D <- Details],
+ gen_calls(Fd, Label, NewIndent, TotalAcc, MFA, MinPercent)
+ end,
+ lists:foreach(Fun, Roots).
+
+gen_calls(Fd, Label, Indent, TotalAcc, MFA, MinPercent) ->
+ case get_detail(Label, MFA) of
+ {read, {_CalledBy, Current, _Calls}} ->
+ log(Fd, Label, Indent, TotalAcc, Current, -1, MinPercent);
+ {unread, {_CalledBy, Current, Calls}} ->
+ log(Fd, Label, Indent, TotalAcc, Current, Calls, MinPercent),
+ NewIndent = " " ++ Indent,
+ Fun = fun({NextMFA, _, _, _}) ->
+ gen_calls(Fd, Label, NewIndent, TotalAcc,
+ NextMFA, MinPercent)
+ end,
+ lists:foreach(Fun, Calls)
+ end.
+
+put_detail(Label, {_, {MFA, _, _, _}, _} = Detail) ->
+ put({Label, MFA}, {unread, Detail}).
+
+get_detail(Label, MFA) ->
+ Val = get({Label, MFA}),
+ case Val of
+ {unread, Detail} ->
+ put({Label, MFA}, {read, Detail}),
+ Val;
+ {read, _Detail} ->
+ Val
+ end.
+
+gen_details(Fd, Total, Details) ->
+ IoList = io_lib:format("Pct Cnt Acc Own MFA\n", []),
+ file:write(Fd, IoList),
+ do_gen_details(Fd, Total, Details).
+
+do_gen_details(Fd, Total, [{_CalledBy, {MFA, Cnt, Acc, Own}, _Calls} | Details]) ->
+ MFAStr = io_lib:format("~p", [MFA]),
+ {_, Percent} = calc_percent(Acc, Own, Total),
+ IoList = io_lib:format("~3.. B% ~10.3B ~10.3f ~10.3f => ~s\n",
+ [Percent, Cnt, Acc, Own, MFAStr]),
+ file:write(Fd, IoList),
+ do_gen_details(Fd, Total, Details);
+do_gen_details(_Fd, _Total, []) ->
+ ok.
+
+log(Fd, Label, Indent, Acc, Current, Calls, MinPercent) when is_list(Calls) ->
+ log(Fd, Label, Indent, Acc, Current, length(Calls), MinPercent);
+log(Fd, Label, Indent, Total, {MFA, Cnt, Acc, Own}, N, MinPercent) ->
+ {Max, Percent} = calc_percent(Acc, Own, Total),
+ if
+ Percent >= MinPercent ->
+ do_log(Fd, Label, Indent, Percent, MFA, Cnt, Max, Own, N);
+ true ->
+ ok
end.
-find(Key, [{_, {Key, _, _, _}, _} = H | _]) ->
- H;
-find(Key, [{_, {_, _, _, _}, _} | T]) ->
- find(Key, T).
-
-log(Fd, Indent, Total, {Label, Cnt, Acc, Own}) ->
- Percent = case Acc of
- undefined -> 100;
- _ -> trunc((lists:max([Acc, Own]) * 100) / Total)
- end,
- Label2 = io_lib:format("~p", [Label]),
- IoList = io_lib:format("~s~p% ~s \t~p \t~p \t~p\n",
- [Indent, Percent, Label2, Cnt, trunc(Acc), trunc(Own)]),
+do_log(Fd, Label, Indent, Percent, MFA, Cnt, Acc, Own, N) ->
+ MFAStr = io_lib:format("~p", [MFA]),
+ CallsStr = io_lib:format(" ~5.. s ", [lists:concat([N])]),
+ IoList = io_lib:format("~s ~3.. B "
+ "~s~3.. B% ~10.. B ~10.. B ~10.. B ~s => ~s\n",
+ [Label, length(Indent) div 2,
+ Indent, Percent, Cnt,
+ round(Acc), round(Own), CallsStr, MFAStr]),
file:write(Fd, IoList).
+calc_percent(Acc, Own, Total) ->
+ Max = safe_max(Acc, Own),
+ {Max, round((Max * 100) / Total)}.
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 41f6c2c4cb..282fd91b44 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -21,6 +21,7 @@
%%----------------------------------------------------------------------
%% Purpose: Lightweight test server
%%----------------------------------------------------------------------
+%%
-module(megaco_test_lib).
@@ -684,7 +685,7 @@ skip(Actual, File, Line) ->
fatal_skip(Actual, File, Line) ->
error(Actual, File, Line),
- exit(shutdown).
+ exit({skipped, {fatal, Actual, File, Line}}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -749,6 +750,7 @@ proxy_loop(OwnId, Controller) ->
proxy_loop(OwnId, Controller)
end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Test server callbacks
init_per_testcase(_Case, Config) ->
@@ -852,10 +854,10 @@ watchdog(Pid, Time) ->
prepare_test_case(Actions, N, Config, File, Line) ->
OrigNodes = lookup_config(nodes, Config),
TestNodes = lookup_config(nodenames, Config), %% For testserver
- This = node(),
+ This = node(),
SomeNodes = OrigNodes ++ (TestNodes -- OrigNodes),
- AllNodes = [This | (SomeNodes -- [This])],
- Nodes = pick_n_nodes(N, AllNodes, File, Line),
+ AllNodes = [This | (SomeNodes -- [This])],
+ Nodes = pick_n_nodes(N, AllNodes, File, Line),
start_nodes(Nodes, File, Line),
do_prepare_test_case(Actions, Nodes, Config, File, Line).
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index c1476488ca..5e72ade769 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.15.1.1
+MEGACO_VSN = 3.16.0.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/Makefile b/lib/mnesia/doc/src/Makefile
index f45b5137a3..173e43ac1f 100644
--- a/lib/mnesia/doc/src/Makefile
+++ b/lib/mnesia/doc/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
@@ -29,14 +29,6 @@ VSN=$(MNESIA_VSN)
APPLICATION=mnesia
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -105,31 +97,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -142,8 +113,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -158,33 +127,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -199,42 +141,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
-
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/mnesia/doc/src/company.erl b/lib/mnesia/doc/src/company.erl
index 28c32ed513..eef5535ed3 100644
--- a/lib/mnesia/doc/src/company.erl
+++ b/lib/mnesia/doc/src/company.erl
@@ -1,19 +1,20 @@
-%% ``The contents of this file are subject to the Erlang Public License,
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of 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%
%%
-module(company).
@@ -83,16 +84,24 @@ g() -> l.
%3
female_bosses() ->
- Q = qlc:q( [{E#employee.name, Boss#employee.name} ||
- E <- mnesia:table(employee),
- Boss <- mnesia:table(employee),
- Atdep <- mnesia:table(at_dep),
- Mgr <- mnesia:table(manager),
- E#employee.sex == female,
- Atdep#at_dep.emp == E#employee.emp_no,
- Mgr#manager.emp == Boss#employee.emp_no,
- Atdep#at_dep.dept_id == Mgr#manager.dept]
+ H1 = qlc:q( [{Atdep#at_dep.dept_id,E} ||
+ E <- mnesia:table(employee),
+ E#employee.sex == female,
+ Atdep <- mnesia:table(at_dep),
+ Atdep#at_dep.emp == E#employee.emp_no]
+ ),
+
+ H2 = qlc:q( [{Mgr#manager.emp,E} ||
+ {AtdepDeptId, E} <- H1,
+ Mgr <- mnesia:table(manager),
+ AtdepDeptId == Mgr#manager.dept]
),
+
+ Q = qlc:q( [{E#employee.name, Boss#employee.name} ||
+ {MgrEmp,E} <- H2,
+ Boss <- mnesia:table(employee),
+ MgrEmp == Boss#employee.emp_no]
+ ),
mnesia:transaction(fun() -> qlc:e(Q) end).
%3
diff --git a/lib/mnesia/doc/src/company_o.erl b/lib/mnesia/doc/src/company_o.erl
index 3c7ad0d5e5..dffe9840bb 100644
--- a/lib/mnesia/doc/src/company_o.erl
+++ b/lib/mnesia/doc/src/company_o.erl
@@ -1,20 +1,22 @@
-%% ``The contents of this file are subject to the Erlang Public License,
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of 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%
+%%
+
-module(company_o).
-compile(export_all).
diff --git a/lib/mnesia/doc/src/make.dep b/lib/mnesia/doc/src/make.dep
deleted file mode 100644
index 6e79484cb3..0000000000
--- a/lib/mnesia/doc/src/make.dep
+++ /dev/null
@@ -1,46 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: Mnesia_App_A.tex Mnesia_App_B.tex Mnesia_App_C.tex \
- Mnesia_App_D.tex Mnesia_chap1.tex Mnesia_chap2.tex \
- Mnesia_chap3.tex Mnesia_chap4.tex Mnesia_chap5.tex \
- Mnesia_chap7.tex Mnesia_chap8.tex book.tex \
- mnesia.tex mnesia_frag_hash.tex mnesia_registry.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-Mnesia_App_B.tex: ../../src/mnesia_backup.erl
-
-Mnesia_App_C.tex: ../../src/mnesia_frag.erl
-
-Mnesia_App_D.tex: ../../src/mnesia_frag_hash.erl
-
-Mnesia_chap2.tex: company.erl company.hrl
-
-Mnesia_chap3.tex: company.erl
-
-Mnesia_chap4.tex: company.erl
-
-Mnesia_chap5.tex: FRUITS company.erl company_o.erl company_o.hrl
-
-Mnesia_chap7.tex: bup.erl
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: company.ps
-
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index 19ec70118f..20133cb6cb 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -813,6 +813,21 @@ mnesia:change_table_copy_type(person, node(), disc_copies)
</p>
</item>
<item>
+ <p><c>{storage_properties, [{Backend, Properties}]</c>.
+ Forwards additional properties to the backend storage.
+ <c>Backend</c> can currently be <c>ets</c> or <c>dets</c> and
+ <c>Properties</c> is a list of options sent to the backend storage
+ during table creation. <c>Properties</c> may not contain properties
+ already used by mnesia such as <c>type</c> or <c>named_table</c>.
+ </p>
+ <p>For example:</p>
+ <code type="none">
+mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
+ {storage_properties,
+ [{ets, [compressed]}, {dets, [{auto_save, 5000}]} ]}])
+ </code>
+ </item>
+ <item>
<p><c>{type, Type}</c>, where <c>Type</c> must be
either of the atoms <c>set</c>, <c>ordered_set</c> or
<c>bag</c>. The default value is <c>set</c>. In a
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 8ef573a948..612ccb5ee8 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -38,7 +38,119 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.5</title>
+ <section><title>Mnesia 4.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Returns the same value for
+ mnesia_loader:disc_load_table/2 as
+ mnesia_loader:net_load_table/4 if a table copy can not be
+ found. (Thanks to Uwe Dauernheim)</p>
+ <p>
+ Own Id: OTP-10015</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improved table lock algorithm.</p>
+ <p>
+ Own Id: OTP-9890</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Reduce calls to phash in key_to_frag_number</p>
+ <p>
+ Original code calls phash 1..2 times, based on which
+ fragment the hashed key targets and how many fragments
+ exist. New code always calls phash only once.</p>
+ <p>
+ Add mnesia_frag_hash test (Thanks to Philip Robinson)</p>
+ <p>
+ Own Id: OTP-9722</p>
+ </item>
+ <item>
+ <p>
+ Fixed a sticky lock bug which caused mnesia:read(Tab,
+ Key, write) return undefined.</p>
+ <p>
+ Own Id: OTP-9786</p>
+ </item>
+ <item>
+ <p>
+ Use the synchronous log_terms instead of alog_terms in
+ mnesia_log:ets2dcd()</p>
+ <p>
+ This avoids the situation where mnesia could dump a very
+ large ets table in its entirety into the message queue of
+ the disk_log process, causing memory blowup and choking
+ the disk logger. (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9804</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Implemented a new option to mnesia:create_table/2 which
+ allows the user to assign 'ets' and 'dets' options not
+ available in mnesia.</p>
+ <p>
+ Own Id: OTP-8970</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix deadlock in mnesia:del_table_copy/2.</p>
+ <p>
+ Own Id: OTP-9689 Aux Id: seq11927 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Allow schema operations when using different mnesia
+ versions.</p>
+ <p>
+ Own Id: OTP-9657 Aux Id: seq11926 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/examples/Makefile b/lib/mnesia/examples/Makefile
index ff00ee76a5..5379761c64 100644
--- a/lib/mnesia/examples/Makefile
+++ b/lib/mnesia/examples/Makefile
@@ -78,9 +78,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) $(RELSYSDIR)/examples
- $(INSTALL_DIR) $(RELSYSDIR)/examples/bench
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) "$(RELSYSDIR)/examples"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/bench"
(cd bench; $(INSTALL_DATA) \
Makefile \
README \
@@ -96,8 +96,8 @@ release_spec: opt
bench.config5 \
bench.config6 \
bench.config7 \
- $(RELSYSDIR)/examples/bench)
- (cd bench; $(INSTALL_SCRIPT) bench.sh $(RELSYSDIR)/examples/bench)
+ "$(RELSYSDIR)/examples/bench")
+ (cd bench; $(INSTALL_SCRIPT) bench.sh "$(RELSYSDIR)/examples/bench")
release_docs_spec:
diff --git a/lib/mnesia/include/Makefile b/lib/mnesia/include/Makefile
index f9b7d72abe..20f62b5460 100644
--- a/lib/mnesia/include/Makefile
+++ b/lib/mnesia/include/Makefile
@@ -54,8 +54,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/include
-# $(INSTALL_DATA) $(INCLUDE_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+# $(INSTALL_DATA) $(INCLUDE_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/mnesia/src/Makefile b/lib/mnesia/src/Makefile
index 1c8ec54605..1432eabc37 100644
--- a/lib/mnesia/src/Makefile
+++ b/lib/mnesia/src/Makefile
@@ -132,10 +132,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
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
+ $(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/mnesia/src/mnesia.appup.src b/lib/mnesia/src/mnesia.appup.src
index fe4e5e2e7a..355aafb215 100644
--- a/lib/mnesia/src/mnesia.appup.src
+++ b/lib/mnesia/src/mnesia.appup.src
@@ -1,12 +1,22 @@
%% -*- erlang -*-
-{"%VSN%",
+{"%VSN%",
[
+ {"4.7.1", [{restart_application, mnesia}]},
+ {"4.7", [{restart_application, mnesia}]},
+ {"4.6", [{restart_application, mnesia}]},
+ {"4.5.1", [{restart_application, mnesia}]},
+ {"4.5", [{restart_application, mnesia}]},
{"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.7.1", [{restart_application, mnesia}]},
+ {"4.7", [{restart_application, mnesia}]},
+ {"4.6", [{restart_application, mnesia}]},
+ {"4.5.1", [{restart_application, mnesia}]},
+ {"4.5", [{restart_application, mnesia}]},
{"4.4.19", [{restart_application, mnesia}]},
{"4.4.18", [{restart_application, mnesia}]},
{"4.4.17", [{restart_application, mnesia}]},
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 980a9c6213..3d30debc53 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -27,7 +27,7 @@
%% 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,
+ ms/0,
change_config/2,
%% Activity mgt
@@ -40,14 +40,14 @@
%% Access within an activity - Lock acquisition
lock/2, lock/4,
lock_table/2,
- read_lock_table/1,
+ 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,
-
+ 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, read/2, wread/1, read/3, read/5,
match_object/1, match_object/3, match_object/5,
@@ -58,9 +58,9 @@
first/1, next/2, last/1, prev/2,
first/3, next/4, last/3, prev/4,
- %% Iterators within an activity
+ %% 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,
@@ -72,8 +72,8 @@
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,
+ 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,
@@ -102,7 +102,7 @@
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,
@@ -112,7 +112,7 @@
%% Textfile access
load_textfile/1, dump_to_textfile/1,
-
+
%% QLC functions
table/1, table/2,
@@ -137,20 +137,20 @@
-define(DEFAULT_ACCESS, ?MODULE).
-%% Select
+%% 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);
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
Value -> Value
end.
is_dollar_digits(Var) ->
case atom_to_list(Var) of
- [$$ | Digs] ->
+ [$$ | Digs] ->
is_digits(Digs);
_ ->
false
@@ -166,13 +166,13 @@ is_digits([Dig | Tail]) ->
is_digits([]) ->
true.
-has_var(X) when is_atom(X) ->
- if
- X == '_' ->
+has_var(X) when is_atom(X) ->
+ if
+ X == '_' ->
true;
- is_atom(X) ->
+ is_atom(X) ->
is_dollar_digits(X);
- true ->
+ true ->
false
end;
has_var(X) when is_tuple(X) ->
@@ -196,9 +196,9 @@ e_has_var(X, Pos) ->
start() ->
{Time , Res} = timer:tc(application, start, [?APPLICATION, temporary]),
-
+
Secs = Time div 1000000,
- case Res of
+ case Res of
ok ->
verbose("Mnesia started, ~p seconds~n",[ Secs]),
ok;
@@ -243,10 +243,10 @@ change_config(extra_db_nodes, Ns) when is_list(Ns) ->
mnesia_controller:connect_nodes(Ns);
change_config(dc_dump_limit, N) when is_number(N), N > 0 ->
case mnesia_lib:is_running() of
- yes ->
+ yes ->
mnesia_lib:set(dc_dump_limit, N),
{ok, N};
- _ ->
+ _ ->
{error, {not_started, ?APPLICATION}}
end;
change_config(BadKey, _BadVal) ->
@@ -255,7 +255,7 @@ change_config(BadKey, _BadVal) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Debugging
-set_debug_level(Level) ->
+set_debug_level(Level) ->
mnesia_subscr:set_debug_level(Level).
lkill() ->
@@ -274,9 +274,9 @@ ms() ->
mnesia_controller,
mnesia_dumper,
mnesia_loader,
- mnesia_frag,
- mnesia_frag_hash,
- mnesia_frag_old_hash,
+ mnesia_frag,
+ mnesia_frag_hash,
+ mnesia_frag_old_hash,
mnesia_index,
mnesia_kernel_sup,
mnesia_late_loader,
@@ -295,9 +295,9 @@ ms() ->
%% Keep these last in the list, so
%% mnesia_sup kills these last
- mnesia_monitor,
+ mnesia_monitor,
mnesia_event
- ].
+ ].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -305,7 +305,7 @@ ms() ->
-spec abort(_) -> no_return().
-abort(Reason) ->
+abort(Reason) ->
exit({aborted, Reason}).
is_transaction() ->
@@ -339,7 +339,7 @@ sync_transaction(Fun, Args, Retries) ->
transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, sync).
-transaction(State, Fun, Args, Retries, Mod, Kind)
+transaction(State, Fun, Args, Retries, Mod, Kind)
when is_function(Fun), is_list(Args), Retries == infinity, is_atom(Mod) ->
mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);
transaction(State, Fun, Args, Retries, Mod, Kind)
@@ -348,7 +348,7 @@ 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)
+non_transaction(State, Fun, Args, ActivityKind, Mod)
when is_function(Fun), is_list(Args), is_atom(Mod) ->
mnesia_tm:non_transaction(State, Fun, Args, ActivityKind, Mod);
non_transaction(_State, Fun, Args, _ActivityKind, _Mod) ->
@@ -394,7 +394,7 @@ wrap_trans(State, Fun, Args, Retries, Mod, Kind) ->
{atomic, GoodRes} -> GoodRes;
BadRes -> exit(BadRes)
end.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Access within an activity - lock acquisition
@@ -507,13 +507,13 @@ good_global_nodes(Nodes) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Access within an activity - updates
-write(Val) when is_tuple(Val), tuple_size(Val) > 2 ->
+write(Val) when is_tuple(Val), tuple_size(Val) > 2 ->
Tab = element(1, Val),
write(Tab, Val, write);
write(Val) ->
abort({bad_type, Val}).
-s_write(Val) when is_tuple(Val), tuple_size(Val) > 2 ->
+s_write(Val) when is_tuple(Val), tuple_size(Val) > 2 ->
Tab = element(1, Val),
write(Tab, Val, sticky_write).
@@ -561,7 +561,7 @@ write_to_store(Tab, Store, Oid, Val) ->
_ ->
?ets_delete(Store, Oid),
?ets_insert(Store, {Oid, Val, write})
- end,
+ end,
ok;
{'EXIT', _} ->
abort({no_exists, Tab});
@@ -611,7 +611,7 @@ delete(Tid, Ts, Tab, Key, LockKind)
ok;
Protocol ->
do_dirty_delete(Protocol, Tab, Key)
- end;
+ end;
delete(_Tid, _Ts, Tab, _Key, _LockKind) ->
abort({bad_type, Tab}).
@@ -640,7 +640,7 @@ delete_object(Tab, Val, LockKind) ->
delete_object(Tid, Ts, Tab, Val, LockKind)
when is_atom(Tab), Tab /= schema, is_tuple(Val), tuple_size(Val) > 2 ->
case has_var(Val) of
- false ->
+ false ->
do_delete_object(Tid, Ts, Tab, Val, LockKind);
true ->
abort({bad_type, Tab, Val})
@@ -665,7 +665,7 @@ do_delete_object(Tid, Ts, Tab, Val, LockKind) ->
abort({bad_type, Tab, LockKind})
end,
case val({Tab, setorbag}) of
- bag ->
+ bag ->
?ets_match_delete(Store, {Oid, Val, '_'}),
?ets_insert(Store, {Oid, Val, delete_object});
_ ->
@@ -731,7 +731,7 @@ read(Tid, Ts, Tab, Key, LockKind)
add_written(?ets_lookup(Store, Oid), Tab, Objs);
_Protocol ->
dirty_read(Tab, Key)
- end;
+ end;
read(_Tid, _Ts, Tab, _Key, _LockKind) ->
abort({bad_type, Tab}).
@@ -744,7 +744,7 @@ first(Tab) ->
_ ->
abort(no_transaction)
end.
-
+
first(Tid, Ts, Tab)
when is_atom(Tab), Tab /= schema ->
case element(1, Tid) of
@@ -845,9 +845,9 @@ prev(_Tid, _Ts,Tab,_) ->
stored_keys(Tab,'$end_of_table',Prev,Ts,Op,Type) ->
case ts_keys(Ts#tidstore.store,Tab,Op,Type,[]) of
[] -> '$end_of_table';
- Keys when Type == ordered_set->
+ Keys when Type == ordered_set->
get_ordered_tskey(Prev,Keys,Op);
- Keys ->
+ Keys ->
get_next_tskey(Prev,Keys,Tab)
end;
stored_keys(Tab,{'EXIT',{aborted,R={badarg,[Tab,Key]}}},
@@ -858,7 +858,7 @@ stored_keys(Tab,{'EXIT',{aborted,R={badarg,[Tab,Key]}}},
Ops ->
case lists:last(Ops) of
[delete] -> abort(R);
- _ ->
+ _ ->
case ts_keys(Store,Tab,Op,Type,[]) of
[] -> '$end_of_table';
Keys -> get_next_tskey(Key,Keys,Tab)
@@ -869,14 +869,14 @@ stored_keys(_,{'EXIT',{aborted,R}},_,_,_,_) ->
abort(R);
stored_keys(Tab,Key,Prev,#tidstore{store=Store},Op,ordered_set) ->
case ?ets_match(Store, {{Tab, Key}, '_', '$1'}) of
- [] ->
+ [] ->
Keys = ts_keys(Store,Tab,Op,ordered_set,[Key]),
get_ordered_tskey(Prev,Keys,Op);
Ops ->
case lists:last(Ops) of
[delete] ->
mnesia:Op(Tab,Key);
- _ ->
+ _ ->
Keys = ts_keys(Store,Tab,Op,ordered_set,[Key]),
get_ordered_tskey(Prev,Keys,Op)
end
@@ -898,7 +898,7 @@ get_ordered_tskey(Prev, [_|R],Op) -> get_ordered_tskey(Prev,R,Op);
get_ordered_tskey(_, [],_) -> '$end_of_table'.
get_next_tskey(Key,Keys,Tab) ->
- Next =
+ Next =
if Key == '$end_of_table' -> hd(Keys);
true ->
case lists:dropwhile(fun(A) -> A /= Key end, Keys) of
@@ -912,7 +912,7 @@ get_next_tskey(Key,Keys,Tab) ->
_ -> %% Really slow anybody got another solution??
case dirty_read(Tab, Next) of
[] -> Next;
- _ ->
+ _ ->
%% Updated value we already returned this key
get_next_tskey(Next,Keys,Tab)
end
@@ -921,7 +921,7 @@ get_next_tskey(Key,Keys,Tab) ->
ts_keys(Store, Tab, Op, Type, Def) ->
All = ?ets_match(Store, {{Tab,'$1'},'_','$2'}),
Keys = ts_keys_1(All, Def),
- if
+ if
Type == ordered_set, Op == prev ->
lists:reverse(lists:sort(Keys));
Type == ordered_set ->
@@ -947,7 +947,7 @@ ts_keys_1([], Acc) ->
%%%%%%%%%%%%%%%%%%%%%
-%% Iterators
+%% Iterators
foldl(Fun, Acc, Tab) ->
foldl(Fun, Acc, Tab, read).
@@ -968,7 +968,7 @@ foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
close_iteration(Res, Tab).
do_foldl(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
- lists:foldl(fun(Key, Acc) ->
+ 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 ->
@@ -983,7 +983,7 @@ 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)),
{_, Tid, Ts} = get(mnesia_activity_state),
do_foldl(Tid, Ts, 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
+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),
{_, Tid, Ts} = get(mnesia_activity_state),
@@ -1003,8 +1003,8 @@ foldr(Fun, Acc, Tab, LockKind) when is_function(Fun) ->
foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
{Type, TempPrev} = init_iteration(ActivityId, Opaque, Tab, LockKind),
- Prev =
- if
+ Prev =
+ if
Type == ordered_set ->
lists:reverse(TempPrev);
true -> %% Order doesn't matter for set and bag
@@ -1014,7 +1014,7 @@ foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
close_iteration(Res, Tab).
do_foldr(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
- lists:foldl(fun(Key, Acc) ->
+ 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 ->
@@ -1029,7 +1029,7 @@ 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)),
{_, Tid, Ts} = get(mnesia_activity_state),
do_foldr(Tid, Ts, 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
+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),
{_, Tid, Ts} = get(mnesia_activity_state),
@@ -1037,25 +1037,25 @@ do_foldr(A, O, Tab, Key, Fun, Acc, Type, Stored) -> %% Type is set or bag
init_iteration(ActivityId, Opaque, Tab, LockKind) ->
lock(ActivityId, Opaque, {table, Tab}, LockKind),
- Type = val({Tab, setorbag}),
+ Type = val({Tab, setorbag}),
Previous = add_previous(ActivityId, Opaque, Type, Tab),
St = val({Tab, storage_type}),
- if
- St == unknown ->
+ if
+ St == unknown ->
ignore;
true ->
mnesia_lib:db_fixtable(St, Tab, true)
- end,
+ end,
{Type, Previous}.
close_iteration(Res, Tab) ->
case val({Tab, storage_type}) of
- unknown ->
+ unknown ->
ignore;
- St ->
+ St ->
mnesia_lib:db_fixtable(St, Tab, false)
end,
- case Res of
+ case Res of
{'EXIT', {aborted, What}} ->
abort(What);
{'EXIT', What} ->
@@ -1074,7 +1074,7 @@ add_previous(_Tid, Ts, _Type, Tab) ->
%% it is correct with respect to what this particular transaction
%% has already written, deleted .... etc
-add_written([], _Tab, Objs) ->
+add_written([], _Tab, Objs) ->
Objs; % standard normal fast case
add_written(Written, Tab, Objs) ->
case val({Tab, setorbag}) of
@@ -1093,7 +1093,7 @@ add_written_to_set(Ws) ->
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) ->
+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
@@ -1118,7 +1118,7 @@ match_object(Tab, Pat, LockKind) ->
abort(no_transaction)
end.
-match_object(Tid, Ts, Tab, Pat, LockKind)
+match_object(Tid, Ts, Tab, Pat, LockKind)
when is_atom(Tab), Tab /= schema, is_tuple(Pat), tuple_size(Pat) > 2 ->
case element(1, Tid) of
ets ->
@@ -1142,11 +1142,11 @@ add_written_match(S, Pat, Tab, Objs) ->
add_match(Ops, Objs, val({Tab, setorbag})).
find_ops(S, Tab, Pat) ->
- GetWritten = [{{{Tab, '_'}, Pat, write}, [], ['$_']},
+ 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) ->
@@ -1162,13 +1162,13 @@ 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)
+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)
+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)
+add_ordered_match([{{_, Key}, _, _DelOP}|Rest], Objs =[Obj|_], Acc)
when Key < element(2, Obj) ->
add_ordered_match(Rest,Objs,Acc);
%% Greater than last object
@@ -1176,7 +1176,7 @@ 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
+%% 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) ->
@@ -1207,7 +1207,7 @@ add_sel_match([Op={Oid, _, delete}|R], Objs, Type, Acc) ->
end;
add_sel_match([Op = {_Oid, Val, delete_object}|R], Objs, Type, Acc) ->
case lists:delete(Val, Objs) of
- Objs ->
+ Objs ->
add_sel_match(R, Objs, Type, [Op|Acc]);
NewObjs when Type == set ->
add_sel_match(R, NewObjs, Type, Acc);
@@ -1224,26 +1224,26 @@ add_sel_match([Op={Oid={_,Key}, Val, write}|R], Objs, bag, Acc) ->
end;
add_sel_match([Op={Oid, Val, write}|R], Objs, set, Acc) ->
case deloid(Oid,Objs) of
- Objs ->
+ Objs ->
add_sel_match(R, Objs,set, [Op|Acc]);
NewObjs ->
add_sel_match(R, [Val | NewObjs],set, Acc)
end.
%% For ordered_set only !!
-add_sel_ordered_match(Written = [{{_, Key}, _, _}|_], [Obj|Objs],Acc)
+add_sel_ordered_match(Written = [{{_, Key}, _, _}|_], [Obj|Objs],Acc)
when Key > element(2, Obj) ->
add_sel_ordered_match(Written, Objs, [Obj|Acc]);
-add_sel_ordered_match([{{_, Key}, Val, write}|Rest], Objs =[Obj|_],Acc)
+add_sel_ordered_match([{{_, Key}, Val, write}|Rest], Objs =[Obj|_],Acc)
when Key < element(2, Obj) ->
add_sel_ordered_match(Rest,[Val|Objs],Acc);
-add_sel_ordered_match([{{_, Key}, _, _DelOP}|Rest], Objs =[Obj|_], Acc)
+add_sel_ordered_match([{{_, Key}, _, _DelOP}|Rest], Objs =[Obj|_], Acc)
when Key < element(2, Obj) ->
add_sel_ordered_match(Rest,Objs,Acc);
%% Greater than last object
add_sel_ordered_match(Ops1, [], Acc) ->
{lists:reverse(Acc), Ops1};
-%% Keys are equal from here
+%% Keys are equal from here
add_sel_ordered_match([{_, Val, write}|Rest], [_Obj|Objs], Acc) ->
add_sel_ordered_match(Rest, [Val|Objs], Acc);
add_sel_ordered_match([{_, _Val, delete}|Rest], [_Obj|Objs], Acc) ->
@@ -1264,11 +1264,11 @@ deloid(Oid, [H | T]) ->
[H | deloid(Oid, T)].
%%%%%%%%%%%%%%%%%%
-% select
+% select
select(Tab, Pat) ->
select(Tab, Pat, read).
-select(Tab, Pat, LockKind)
+select(Tab, Pat, LockKind)
when is_atom(Tab), Tab /= schema, is_list(Pat) ->
case get(mnesia_activity_state) of
{?DEFAULT_ACCESS, Tid, Ts} ->
@@ -1293,13 +1293,13 @@ fun_select(Tid, Ts, Tab, Spec, LockKind, TabPat, SelectFun) ->
select_lock(Tid,Ts,LockKind,Spec,Tab),
Store = Ts#tidstore.store,
Written = ?ets_match_object(Store, {{TabPat, '_'}, '_', '_'}),
- case Written of
- [] ->
+ 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
+ _ ->
+ %% 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),
@@ -1326,7 +1326,7 @@ select_lock(Tid,Ts,LockKind,Spec,Tab) ->
end.
%% Breakable Select
-select(Tab, Pat, NObjects, LockKind)
+select(Tab, Pat, NObjects, LockKind)
when is_atom(Tab), Tab /= schema, is_list(Pat), is_integer(NObjects) ->
case get(mnesia_activity_state) of
{?DEFAULT_ACCESS, Tid, Ts} ->
@@ -1356,26 +1356,26 @@ fun_select(Tid, Ts, Tab, Spec, LockKind, TabPat, Init, NObjects, Node, Storage)
select_lock(Tid,Ts,LockKind,Spec,Tab),
Store = Ts#tidstore.store,
do_fixtable(Tab, Store),
-
- Written0 = ?ets_match_object(Store, {{TabPat, '_'}, '_', '_'}),
- case Written0 of
- [] ->
+
+ Written0 = ?ets_match_object(Store, {{TabPat, '_'}, '_', '_'}),
+ case Written0 of
+ [] ->
%% Nothing changed in the table during this transaction,
%% Simple case get results from [d]ets
select_state(Init(Spec),Def);
- _ ->
- %% Hard (slow case) records added or deleted earlier
+ _ ->
+ %% Hard (slow case) records added or deleted earlier
%% in the transaction, have to cope with that.
Type = val({Tab, setorbag}),
- Written =
+ Written =
if Type == ordered_set -> %% Sort stable
lists:keysort(1,Written0);
- true ->
+ true ->
Written0
end,
FixedSpec = get_record_pattern(Spec),
CMS = ets:match_spec_compile(Spec),
- trans_select(Init(FixedSpec),
+ trans_select(Init(FixedSpec),
Def#mnesia_select{written=Written,spec=CMS,type=Type, orig=FixedSpec})
end;
_Protocol ->
@@ -1394,7 +1394,7 @@ select(Cont) ->
select_cont(_Tid,_Ts,'$end_of_table') ->
'$end_of_table';
-select_cont(Tid,_Ts,State=#mnesia_select{tid=Tid,cont=Cont, orig=Ms})
+select_cont(Tid,_Ts,State=#mnesia_select{tid=Tid,cont=Cont, orig=Ms})
when element(1,Tid) == ets ->
case Cont of
'$end_of_table' -> '$end_of_table';
@@ -1415,7 +1415,7 @@ trans_select('$end_of_table', #mnesia_select{written=Written0,spec=CMS,type=Type
trans_select({TabRecs,Cont}, State = #mnesia_select{written=Written0,spec=CMS,type=Type}) ->
{FixedRes,Written} = add_sel_match(Written0, TabRecs, Type),
select_state({ets:match_spec_run(FixedRes, CMS),Cont},
- State#mnesia_select{written=Written}).
+ State#mnesia_select{written=Written}).
select_state({Matches, Cont}, MS) ->
{Matches, MS#mnesia_select{cont=Cont}};
@@ -1433,9 +1433,9 @@ all_keys(Tab) ->
Mod:all_keys(Tid, Ts, Tab, read);
_ ->
abort(no_transaction)
- end.
+ end.
-all_keys(Tid, Ts, Tab, LockKind)
+all_keys(Tid, Ts, Tab, LockKind)
when is_atom(Tab), Tab /= schema ->
Pat0 = val({Tab, wild_pattern}),
Pat = setelement(2, Pat0, '$1'),
@@ -1446,7 +1446,7 @@ all_keys(Tid, Ts, Tab, LockKind)
_ ->
Keys
end;
-all_keys(_Tid, _Ts, Tab, _LockKind) ->
+all_keys(_Tid, _Ts, Tab, _LockKind) ->
abort({bad_type, Tab}).
index_match_object(Pat, Attr) when is_tuple(Pat), tuple_size(Pat) > 2 ->
@@ -1465,7 +1465,7 @@ index_match_object(Tab, Pat, Attr, LockKind) ->
abort(no_transaction)
end.
-index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind)
+index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind)
when is_atom(Tab), Tab /= schema, is_tuple(Pat), tuple_size(Pat) > 2 ->
case element(1, Tid) of
ets ->
@@ -1501,7 +1501,7 @@ index_read(Tab, Key, Attr) ->
abort(no_transaction)
end.
-index_read(Tid, Ts, Tab, Key, Attr, LockKind)
+index_read(Tid, Ts, Tab, Key, Attr, LockKind)
when is_atom(Tab), Tab /= schema ->
case element(1, Tid) of
ets ->
@@ -1536,7 +1536,7 @@ dirty_write(Val) when is_tuple(Val), tuple_size(Val) > 2 ->
dirty_write(Tab, Val);
dirty_write(Val) ->
abort({bad_type, Val}).
-
+
dirty_write(Tab, Val) ->
do_dirty_write(async_dirty, Tab, Val).
@@ -1562,7 +1562,7 @@ dirty_delete(Oid) ->
dirty_delete(Tab, Key) ->
do_dirty_delete(async_dirty, Tab, Key).
-
+
do_dirty_delete(SyncMode, Tab, Key) when is_atom(Tab), Tab /= schema ->
Oid = {Tab, Key},
mnesia_tm:dirty(SyncMode, {Oid, Oid, delete});
@@ -1582,7 +1582,7 @@ do_dirty_delete_object(SyncMode, Tab, Val)
when is_atom(Tab), Tab /= schema, is_tuple(Val), tuple_size(Val) > 2 ->
Oid = {Tab, element(2, Val)},
case has_var(Val) of
- false ->
+ false ->
mnesia_tm:dirty(SyncMode, {Oid, Val, delete_object});
true ->
abort({bad_type, Tab, Val})
@@ -1600,7 +1600,7 @@ dirty_update_counter(Counter, _Incr) ->
dirty_update_counter(Tab, Key, Incr) ->
do_dirty_update_counter(async_dirty, Tab, Key, Incr).
-
+
do_dirty_update_counter(SyncMode, Tab, Key, Incr)
when is_atom(Tab), Tab /= schema, is_integer(Incr) ->
case ?catch_val({Tab, record_validation}) of
@@ -1638,7 +1638,7 @@ dirty_match_object(Pat) when is_tuple(Pat), tuple_size(Pat) > 2 ->
dirty_match_object(Tab, Pat);
dirty_match_object(Pat) ->
abort({bad_type, Pat}).
-
+
dirty_match_object(Tab, Pat)
when is_atom(Tab), Tab /= schema, is_tuple(Pat), tuple_size(Pat) > 2 ->
dirty_rpc(Tab, ?MODULE, remote_dirty_match_object, [Tab, Pat]);
@@ -1697,8 +1697,8 @@ remote_dirty_select(Tab, [{HeadPat,_, _}] = Spec, [Pos | Tail])
%% 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 ->
+ case val({Tab, setorbag}) of
+ ordered_set ->
ets:match_spec_run(lists:sort(Recs), CMS);
_ ->
ets:match_spec_run(Recs, CMS)
@@ -1730,14 +1730,14 @@ dirty_all_keys(Tab) when is_atom(Tab), Tab /= schema ->
end;
dirty_all_keys(Tab) ->
abort({bad_type, Tab}).
-
+
dirty_index_match_object(Pat, Attr) when is_tuple(Pat), tuple_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)
+dirty_index_match_object(Tab, Pat, Attr)
when is_atom(Tab), Tab /= schema, is_tuple(Pat), tuple_size(Pat) > 2 ->
case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
Pos when Pos =< tuple_size(Pat) ->
@@ -1752,7 +1752,7 @@ dirty_index_match_object(Tab, Pat, Attr)
[Tab, Pat, Pos]);
true ->
abort({bad_type, Tab, Attr, Elem})
- end
+ end
end;
BadPos ->
abort({bad_type, Tab, BadPos})
@@ -1810,7 +1810,7 @@ do_dirty_rpc(Tab, Node, M, F, Args) ->
%% Sync with mnesia_monitor
try sys:get_status(mnesia_monitor) catch _:_ -> ok end,
case mnesia_controller:call({check_w2r, Node, Tab}) of % Sync
- NewNode when NewNode =:= Node ->
+ NewNode when NewNode =:= Node ->
ErrorTag = mnesia_lib:dirty_rpc_error_tag(Reason),
mnesia:abort({ErrorTag, Args});
NewNode ->
@@ -1821,9 +1821,9 @@ do_dirty_rpc(Tab, Node, M, F, Args) ->
%% to acquire the lock on the NewNode.
%% In this context we do neither know
%% the kind or granularity of the lock.
- %% --> Abort the transaction
+ %% --> Abort the transaction
mnesia:abort({node_not_running, Node});
- {error, {node_not_running, _}} ->
+ {error, {node_not_running, _}} ->
%% Mnesia is stopping
mnesia:abort({no_exists, Args});
_ ->
@@ -1858,21 +1858,21 @@ table_info(_Tid, _Ts, Tab, Item) ->
any_table_info(Tab, Item).
-any_table_info(Tab, Item) when is_atom(Tab) ->
+any_table_info(Tab, Item) when is_atom(Tab) ->
case Item of
master_nodes ->
mnesia_recover:get_master_nodes(Tab);
-% checkpoints ->
+% checkpoints ->
% case ?catch_val({Tab, commit_work}) of
% [{checkpoints, List} | _] -> List;
% No_chk when is_list(No_chk) -> [];
% Else -> info_reply(Else, Tab, Item)
% end;
- size ->
+ size ->
raw_table_info(Tab, Item);
memory ->
raw_table_info(Tab, Item);
- type ->
+ type ->
case ?catch_val({Tab, setorbag}) of
{'EXIT', _} ->
abort({no_exists, Tab, Item});
@@ -1885,8 +1885,8 @@ any_table_info(Tab, Item) when is_atom(Tab) ->
abort({no_exists, Tab, Item});
Props ->
lists:map(fun({setorbag, Type}) -> {type, Type};
- (Prop) -> Prop end,
- Props)
+ (Prop) -> Prop end,
+ Props)
end;
name ->
Tab;
@@ -1927,14 +1927,14 @@ bad_info_reply(_Tab, memory) -> 0;
bad_info_reply(Tab, Item) -> abort({no_exists, Tab, Item}).
%% Raw info about all tables
-schema() ->
+schema() ->
mnesia_schema:info().
%% Raw info about one tables
-schema(Tab) ->
+schema(Tab) ->
mnesia_schema:info(Tab).
-error_description(Err) ->
+error_description(Err) ->
mnesia_lib:error_desc(Err).
info() ->
@@ -1951,18 +1951,18 @@ info() ->
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",
+ "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",
+ "from ~w~n",
[Tid, Nodes])
end, Uncertain),
@@ -2023,15 +2023,15 @@ display_tab_info() ->
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
@@ -2041,7 +2041,7 @@ display_tab_info() ->
table_info(T, where_to_commit)
end,
case lists:keysearch(Rpat, 1, Acc) of
- {value, {_Rpat, Rtabs}} ->
+ {value, {_Rpat, Rtabs}} ->
lists:keyreplace(Rpat, 1, Acc, {Rpat, [T | Rtabs]});
false ->
[{Rpat, [T]} | Acc]
@@ -2161,20 +2161,20 @@ system_info2(fallback_activated) ->
system_info2(version) ->
case ?catch_val(version) of
- {'EXIT', _} ->
+ {'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()}
+ {mnesia_not_loaded, node(), now()}
end;
Version ->
Version
end;
-system_info2(access_module) -> mnesia_monitor:get_env(access_module);
+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);
@@ -2183,7 +2183,7 @@ 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) ->
+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);
@@ -2204,9 +2204,9 @@ 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(core_dir) -> mnesia_monitor:get_env(core_dir);
-system_info2(no_table_loaders) -> mnesia_monitor:get_env(no_table_loaders);
-system_info2(dc_dump_limit) -> mnesia_monitor:get_env(dc_dump_limit);
+system_info2(core_dir) -> mnesia_monitor:get_env(core_dir);
+system_info2(no_table_loaders) -> mnesia_monitor:get_env(no_table_loaders);
+system_info2(dc_dump_limit) -> mnesia_monitor:get_env(dc_dump_limit);
system_info2(send_compressed) -> mnesia_monitor:get_env(send_compressed);
system_info2(Item) -> exit({badarg, Item}).
@@ -2281,7 +2281,7 @@ system_info_items(no) ->
core_dir,
version
].
-
+
system_info() ->
IsRunning = mnesia_lib:is_running(),
case IsRunning of
@@ -2308,62 +2308,62 @@ load_mnesia_or_abort() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Database mgt
-create_schema(Ns) ->
+create_schema(Ns) ->
mnesia_bup:create_schema(Ns).
-delete_schema(Ns) ->
+delete_schema(Ns) ->
mnesia_schema:delete_schema(Ns).
-backup(Opaque) ->
+backup(Opaque) ->
mnesia_log:backup(Opaque).
-backup(Opaque, Mod) ->
+backup(Opaque, Mod) ->
mnesia_log:backup(Opaque, Mod).
-traverse_backup(S, T, Fun, Acc) ->
+traverse_backup(S, T, Fun, Acc) ->
mnesia_bup:traverse_backup(S, T, Fun, Acc).
-traverse_backup(S, SM, T, TM, F, A) ->
+traverse_backup(S, SM, T, TM, F, A) ->
mnesia_bup:traverse_backup(S, SM, T, TM, F, A).
-install_fallback(Opaque) ->
+install_fallback(Opaque) ->
mnesia_bup:install_fallback(Opaque).
-install_fallback(Opaque, Mod) ->
+install_fallback(Opaque, Mod) ->
mnesia_bup:install_fallback(Opaque, Mod).
-uninstall_fallback() ->
+uninstall_fallback() ->
mnesia_bup:uninstall_fallback().
-uninstall_fallback(Args) ->
+uninstall_fallback(Args) ->
mnesia_bup:uninstall_fallback(Args).
-activate_checkpoint(Args) ->
+activate_checkpoint(Args) ->
mnesia_checkpoint:activate(Args).
-deactivate_checkpoint(Name) ->
+deactivate_checkpoint(Name) ->
mnesia_checkpoint:deactivate(Name).
-backup_checkpoint(Name, Opaque) ->
+backup_checkpoint(Name, Opaque) ->
mnesia_log:backup_checkpoint(Name, Opaque).
-backup_checkpoint(Name, Opaque, Mod) ->
+backup_checkpoint(Name, Opaque, Mod) ->
mnesia_log:backup_checkpoint(Name, Opaque, Mod).
-restore(Opaque, Args) ->
+restore(Opaque, Args) ->
mnesia_schema:restore(Opaque, Args).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Table mgt
-create_table(Arg) ->
+create_table(Arg) ->
mnesia_schema:create_table(Arg).
-create_table(Name, Arg) when is_list(Arg) ->
+create_table(Name, Arg) when is_list(Arg) ->
mnesia_schema:create_table([{name, Name}| Arg]);
create_table(Name, Arg) ->
{aborted, badarg, Name, Arg}.
-delete_table(Tab) ->
+delete_table(Tab) ->
mnesia_schema:delete_table(Tab).
add_table_copy(Tab, N, S) ->
@@ -2371,38 +2371,38 @@ add_table_copy(Tab, N, S) ->
del_table_copy(Tab, N) ->
mnesia_schema:del_table_copy(Tab, N).
-move_table_copy(Tab, From, To) ->
+move_table_copy(Tab, From, To) ->
mnesia_schema:move_table(Tab, From, To).
-add_table_index(Tab, Ix) ->
+add_table_index(Tab, Ix) ->
mnesia_schema:add_table_index(Tab, Ix).
-del_table_index(Tab, Ix) ->
+del_table_index(Tab, Ix) ->
mnesia_schema:del_table_index(Tab, Ix).
-transform_table(Tab, Fun, NewA) ->
+transform_table(Tab, Fun, NewA) ->
case catch val({Tab, record_name}) of
- {'EXIT', Reason} ->
+ {'EXIT', Reason} ->
mnesia:abort(Reason);
- OldRN ->
+ OldRN ->
mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
end.
-transform_table(Tab, Fun, NewA, NewRN) ->
+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) ->
- case get(mnesia_activity_state) of
+ case get(mnesia_activity_state) of
State = {Mod, Tid, _Ts} when element(1, Tid) =/= tid ->
transaction(State, fun() -> do_clear_table(Tab) end, [], infinity, Mod, sync);
- undefined ->
+ undefined ->
transaction(undefined, fun() -> do_clear_table(Tab) end, [], infinity, ?DEFAULT_ACCESS, sync);
_ -> %% Not allowed for clear_table
mnesia:abort({aborted, nested_transaction})
end.
-
+
do_clear_table(Tab) ->
case get(mnesia_activity_state) of
{?DEFAULT_ACCESS, Tid, Ts} ->
@@ -2415,7 +2415,7 @@ do_clear_table(Tab) ->
clear_table(Tid, Ts, Tab, Obj) when element(1, Tid) =:= tid ->
Store = Ts#tidstore.store,
- mnesia_locker:wlock_table(Tid, Store, Tab),
+ mnesia_locker:wlock_table(Tid, Store, Tab),
Oid = {Tab, '_'},
?ets_insert(Store, {Oid, Obj, clear_table}),
ok.
@@ -2423,26 +2423,26 @@ clear_table(Tid, Ts, Tab, Obj) when element(1, Tid) =:= tid ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Table mgt - user properties
-read_table_property(Tab, PropKey) ->
+read_table_property(Tab, PropKey) ->
val({Tab, user_property, PropKey}).
-write_table_property(Tab, Prop) ->
+write_table_property(Tab, Prop) ->
mnesia_schema:write_table_property(Tab, Prop).
-delete_table_property(Tab, PropKey) ->
+delete_table_property(Tab, PropKey) ->
mnesia_schema:delete_table_property(Tab, PropKey).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Table mgt - user properties
-change_table_frag(Tab, FragProp) ->
+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) ->
+dump_tables(Tabs) ->
mnesia_schema:dump_tables(Tabs).
%% allow the user to wait for some tables to be loaded
@@ -2455,10 +2455,10 @@ force_load_table(Tab) ->
Other -> Other
end.
-change_table_access_mode(T, Access) ->
+change_table_access_mode(T, Access) ->
mnesia_schema:change_table_access_mode(T, Access).
-change_table_load_order(T, O) ->
+change_table_load_order(T, O) ->
mnesia_schema:change_table_load_order(T, O).
change_table_majority(T, M) ->
@@ -2471,13 +2471,13 @@ set_master_nodes(Nodes) when is_list(Nodes) ->
yes ->
CsPat = {{'_', cstruct}, '_'},
Cstructs0 = ?ets_match_object(mnesia_gvar, CsPat),
- Cstructs = [Cs || {_, Cs} <- Cstructs0],
+ Cstructs = [Cs || {_, Cs} <- Cstructs0],
log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning);
_NotRunning ->
case UseDir of
true ->
mnesia_lib:lock_table(schema),
- Res =
+ Res =
case mnesia_schema:read_cstructs_from_disc() of
{ok, Cstructs} ->
log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning);
@@ -2497,7 +2497,7 @@ 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}
+ {Cs#cstruct.name, Valid}
end,
Args = lists:map(Fun, Cstructs),
mnesia_recover:log_master_nodes(Args, UseDir, IsRunning).
@@ -2523,7 +2523,7 @@ set_master_nodes(Tab, Nodes) when is_list(Nodes) ->
case UseDir of
true ->
mnesia_lib:lock_table(schema),
- Res =
+ Res =
case mnesia_schema:read_cstructs_from_disc() of
{ok, Cstructs} ->
case lists:keysearch(Tab, 2, Cstructs) of
@@ -2553,7 +2553,7 @@ set_master_nodes(Tab, Nodes) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Misc admin
-dump_log() ->
+dump_log() ->
mnesia_controller:sync_dump_log(user).
subscribe(What) ->
@@ -2568,10 +2568,10 @@ report_event(Event) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Snmp
-snmp_open_table(Tab, Us) ->
+snmp_open_table(Tab, Us) ->
mnesia_schema:add_snmp(Tab, Us).
-snmp_close_table(Tab) ->
+snmp_close_table(Tab) ->
mnesia_schema:del_snmp(Tab).
snmp_get_row(Tab, RowIndex) when is_atom(Tab), Tab /= schema, is_list(RowIndex) ->
@@ -2583,26 +2583,26 @@ snmp_get_row(Tab, RowIndex) when is_atom(Tab), Tab /= schema, is_list(RowIndex)
SnmpType = val({Tab,snmp}),
Fix = fun({{_,Key},Row,Op}, Res) ->
case mnesia_snmp_hook:key_to_oid(Tab,Key,SnmpType) of
- RowIndex ->
+ RowIndex ->
case Op of
write -> {ok, Row};
_ ->
undefined
end;
- _ ->
+ _ ->
Res
end
end,
lists:foldl(Fix, undefined, Ops);
Key ->
case Mod:read(Tid, Ts, Tab, Key, read) of
- [Row] ->
+ [Row] ->
{ok, Row};
- _ ->
+ _ ->
undefined
end
end;
- _ ->
+ _ ->
dirty_rpc(Tab, mnesia_snmp_hook, get_row, [Tab, RowIndex])
end;
snmp_get_row(Tab, _RowIndex) ->
@@ -2613,7 +2613,7 @@ snmp_get_row(Tab, _RowIndex) ->
snmp_get_next_index(Tab, RowIndex) when is_atom(Tab), Tab /= schema, is_list(RowIndex) ->
{Next,OrigKey} = dirty_rpc(Tab, mnesia_snmp_hook, get_next_index, [Tab, RowIndex]),
case get(mnesia_activity_state) of
- {_Mod, Tid, #tidstore{store=Store}} when element(1, Tid) =:= tid ->
+ {_Mod, Tid, #tidstore{store=Store}} when element(1, Tid) =:= tid ->
case OrigKey of
undefined ->
snmp_order_keys(Store, Tab, RowIndex, []);
@@ -2639,7 +2639,7 @@ snmp_get_next_index(Tab, _RowIndex) ->
snmp_order_keys(Store,Tab,RowIndex,Def) ->
All = ?ets_match(Store, {{Tab,'$1'},'_','$2'}),
SnmpType = val({Tab,snmp}),
- Keys0 = [mnesia_snmp_hook:key_to_oid(Tab,Key,SnmpType) ||
+ Keys0 = [mnesia_snmp_hook:key_to_oid(Tab,Key,SnmpType) ||
Key <- ts_keys_1(All, Def)],
Keys = lists:sort(Keys0),
get_ordered_snmp_key(RowIndex,Keys).
@@ -2648,7 +2648,7 @@ get_ordered_snmp_key(Prev, [First|_]) when Prev < First -> {ok, First};
get_ordered_snmp_key(Prev, [_|R]) ->
get_ordered_snmp_key(Prev, R);
get_ordered_snmp_key(_, []) ->
- endOfTable.
+ endOfTable.
%%%%%%%%%%
@@ -2657,7 +2657,7 @@ snmp_get_mnesia_key(Tab, RowIndex) when is_atom(Tab), Tab /= schema, is_list(Row
{_Mod, Tid, Ts} when element(1, Tid) =:= tid ->
Res = dirty_rpc(Tab,mnesia_snmp_hook,get_mnesia_key,[Tab,RowIndex]),
snmp_filter_key(Res, RowIndex, Tab, Ts#tidstore.store);
- _ ->
+ _ ->
dirty_rpc(Tab, mnesia_snmp_hook, get_mnesia_key, [Tab, RowIndex])
end;
snmp_get_mnesia_key(Tab, _RowIndex) ->
@@ -2670,7 +2670,7 @@ snmp_oid_to_mnesia_key(RowIndex, Tab) ->
{ok, MnesiaKey} -> MnesiaKey;
undefined -> unknown
end;
- MnesiaKey ->
+ MnesiaKey ->
MnesiaKey
end.
@@ -2690,20 +2690,20 @@ snmp_filter_key(undefined, RowIndex, Tab, Store) ->
SnmpType = val({Tab,snmp}),
Fix = fun({{_,Key},_,Op}, Res) ->
case mnesia_snmp_hook:key_to_oid(Tab,Key,SnmpType) of
- RowIndex ->
+ RowIndex ->
case Op of
write -> {ok, Key};
_ ->
undefined
end;
- _ ->
+ _ ->
Res
end
end,
lists:foldl(Fix, undefined, Ops);
Key ->
case ?ets_lookup(Store, {Tab,Key}) of
- [] ->
+ [] ->
undefined;
Ops ->
case lists:last(Ops) of
@@ -2716,9 +2716,9 @@ snmp_filter_key(undefined, RowIndex, Tab, Store) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Textfile access
-load_textfile(F) ->
+load_textfile(F) ->
mnesia_text:load_textfile(F).
-dump_to_textfile(F) ->
+dump_to_textfile(F) ->
mnesia_text:dump_to_textfile(F).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2727,7 +2727,7 @@ dump_to_textfile(F) ->
table(Tab) ->
table(Tab, []).
table(Tab,Opts) ->
- {[Trav,Lock,NObjects],QlcOptions0} =
+ {[Trav,Lock,NObjects],QlcOptions0} =
qlc_opts(Opts,[{traverse,select},{lock,read},{n_objects,100}]),
TF = case Trav of
{select,Ms} ->
@@ -2740,10 +2740,10 @@ table(Tab,Opts) ->
Pre = fun(Arg) -> pre_qlc(Arg, Tab) end,
Post = fun() -> post_qlc(Tab) end,
Info = fun(Tag) -> qlc_info(Tab, Tag) end,
- ParentFun = fun() ->
- {mnesia_activity, mnesia:get_activity_id()}
+ ParentFun = fun() ->
+ {mnesia_activity, mnesia:get_activity_id()}
end,
- Lookup =
+ Lookup =
case Trav of
{select, _} -> [];
_ ->
@@ -2757,27 +2757,27 @@ table(Tab,Opts) ->
[{lookup_fun, LFun}]
end,
MFA = fun(Type) -> qlc_format(Type, Tab, NObjects, Lock, Opts) end,
- QlcOptions = [{pre_fun, Pre}, {post_fun, Post},
- {info_fun, Info}, {parent_fun, ParentFun},
+ QlcOptions = [{pre_fun, Pre}, {post_fun, Post},
+ {info_fun, Info}, {parent_fun, ParentFun},
{format_fun, MFA}|Lookup] ++ QlcOptions0,
qlc:table(TF, QlcOptions).
pre_qlc(Opts, Tab) ->
- {_,Tid,_} =
+ {_,Tid,_} =
case get(mnesia_activity_state) of
undefined ->
case lists:keysearch(parent_value, 1, Opts) of
{value, {parent_value,{mnesia_activity,undefined}}} ->
abort(no_transaction);
{value, {parent_value,{mnesia_activity,Aid}}} ->
- {value,{stop_fun,Stop}} =
+ {value,{stop_fun,Stop}} =
lists:keysearch(stop_fun,1,Opts),
put_activity_id(Aid,Stop),
Aid;
_ ->
abort(no_transaction)
end;
- Else ->
+ Else ->
Else
end,
case element(1,Tid) of
@@ -2785,9 +2785,9 @@ pre_qlc(Opts, Tab) ->
_ ->
case ?catch_val({Tab, setorbag}) of
ordered_set -> ok;
- _ ->
+ _ ->
dirty_rpc(Tab, mnesia_tm, fixtable, [Tab,true,self()]),
- ok
+ ok
end
end.
@@ -2806,7 +2806,7 @@ post_qlc(Tab) ->
qlc_select('$end_of_table') -> [];
qlc_select({[], Cont}) -> qlc_select(select(Cont));
-qlc_select({Objects, Cont}) ->
+qlc_select({Objects, Cont}) ->
Objects ++ fun() -> qlc_select(select(Cont)) end.
qlc_opts(Opts, Keys) when is_list(Opts) ->
@@ -2826,7 +2826,7 @@ qlc_opts(Opts,[],Acc) -> {lists:reverse(Acc),Opts}.
qlc_info(Tab, num_of_objects) ->
dirty_rpc(Tab, ?MODULE, raw_table_info, [Tab, size]);
-qlc_info(_, keypos) -> 2;
+qlc_info(_, keypos) -> 2;
qlc_info(_, is_unique_objects) -> true;
qlc_info(Tab, is_unique_keys) ->
case val({Tab, type}) of
@@ -2836,9 +2836,9 @@ qlc_info(Tab, is_unique_keys) ->
end;
qlc_info(Tab, is_sorted_objects) ->
case val({Tab, type}) of
- ordered_set ->
+ ordered_set ->
case ?catch_val({Tab, frag_hash}) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
ascending;
_ -> %% Fragmented tables are not ordered
no
@@ -2856,11 +2856,11 @@ qlc_format({match_spec, Ms}, Tab, NObjects, Lock, Opts) ->
{?MODULE, table, [Tab,[{traverse,{select,Ms}},{n_objects, NObjects}, {lock,Lock}|Opts]]};
qlc_format({lookup, 2, Keys}, Tab, _, Lock, _) ->
io_lib:format("lists:flatmap(fun(V) -> "
- "~w:read(~w, V, ~w) end, ~w)",
+ "~w:read(~w, V, ~w) end, ~w)",
[?MODULE, Tab, Lock, Keys]);
qlc_format({lookup, Index,Keys}, Tab, _, _, _) ->
io_lib:format("lists:flatmap(fun(V) -> "
- "~w:index_read(~w, V, ~w) end, ~w)",
+ "~w:index_read(~w, V, ~w) end, ~w)",
[?MODULE, Tab, Index, Keys]).
@@ -2874,7 +2874,7 @@ do_fixtable(Tab, Store) ->
ok;
_ ->
case ?ets_match_object(Store, {fixtable, {Tab, '_'}}) of
- [] ->
+ [] ->
Node = dirty_rpc(Tab, mnesia_tm, fixtable, [Tab,true,self()]),
?ets_insert(Store, {fixtable, {Tab, Node}});
_ ->
@@ -2886,10 +2886,10 @@ do_fixtable(Tab, Store) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Mnemosyne exclusive
-get_activity_id() ->
+get_activity_id() ->
get(mnesia_activity_state).
-put_activity_id(Activity) ->
+put_activity_id(Activity) ->
mnesia_tm:put_activity_id(Activity).
-put_activity_id(Activity,Fun) ->
+put_activity_id(Activity,Fun) ->
mnesia_tm:put_activity_id(Activity,Fun).
diff --git a/lib/mnesia/src/mnesia.hrl b/lib/mnesia/src/mnesia.hrl
index 2375b72d59..2855792646 100644
--- a/lib/mnesia/src/mnesia.hrl
+++ b/lib/mnesia/src/mnesia.hrl
@@ -70,6 +70,7 @@
attributes = [key, val], % [Atom]
user_properties = [], % [Record]
frag_properties = [], % [{Key, Val]
+ storage_properties = [], % [{Key, Val]
cookie = ?unique_cookie, % Term
version = {{2, 0}, []}}). % {{Integer, Integer}, [Node]}
diff --git a/lib/mnesia/src/mnesia_backup.erl b/lib/mnesia/src/mnesia_backup.erl
index f372ca0be5..736f2ed9bf 100644
--- a/lib/mnesia/src/mnesia_backup.erl
+++ b/lib/mnesia/src/mnesia_backup.erl
@@ -1,19 +1,19 @@
%%
%% %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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -56,14 +56,14 @@
-export([
%% Write access
- open_write/1,
- write/2,
- commit_write/1,
+ open_write/1,
+ write/2,
+ commit_write/1,
abort_write/1,
%% Read access
- open_read/1,
- read/1,
+ open_read/1,
+ read/1,
close_read/1
]).
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 47dcdad7ac..fd87be1759 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -62,7 +62,7 @@
fallback_tmp,
skip_tables = [],
keep_tables = [],
- default_op = keep_tables
+ default_op = keep_tables
}).
-type fallback_args() :: #fallback_args{}.
@@ -134,7 +134,7 @@ abort_restore(R, What, Args, Reason) ->
[Mod, What, Args, Reason]),
catch apply(Mod, close_read, [Opaque]),
throw({error, Reason}).
-
+
fallback_to_schema() ->
Fname = fallback_bup(),
fallback_to_schema(Fname).
@@ -146,14 +146,14 @@ fallback_to_schema(Fname) ->
{error, Reason};
Schema ->
case catch lookup_schema(schema, Schema) of
- {error, _} ->
+ {error, _} ->
{error, "No schema in fallback"};
List ->
{ok, fallback, List}
end
end.
-%% Opens Opaque reads schema and then close
+%% 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
@@ -163,7 +163,7 @@ read_schema(Mod, Opaque) ->
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}}
@@ -227,7 +227,7 @@ refresh_cookie(Schema, NewCookie) ->
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}})
@@ -273,7 +273,7 @@ convert_0_1([{schema, db_nodes, DbNodes} | Schema], Acc, Cs) ->
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 =
+ Head =
case lists:keysearch(index, 1, Def) of
{value, {index, PosList}} ->
%% Remove the snmp "index"
@@ -334,7 +334,7 @@ create_schema(Ns, ok) ->
case mnesia_lib:ensure_loaded(?APPLICATION) of
ok ->
case mnesia_monitor:get_env(schema_location) of
- ram ->
+ ram ->
{error, {has_no_disc, node()}};
_ ->
case mnesia_schema:opt_create_dir(true, mnesia_lib:dir()) of
@@ -358,7 +358,7 @@ create_schema(Ns, ok) ->
{error, Reason}
end
end
- end;
+ end;
{error, Reason} ->
{error, Reason}
end;
@@ -372,7 +372,9 @@ mk_str() ->
lists:concat([node()] ++ Now ++ ".TMP").
make_initial_backup(Ns, Opaque, Mod) ->
- Schema = [{schema, schema, mnesia_schema:get_initial_schema(disc_copies, Ns)}],
+ Orig = mnesia_schema:get_initial_schema(disc_copies, Ns),
+ Modded = proplists:delete(storage_properties, proplists:delete(majority, Orig)),
+ Schema = [{schema, schema, Modded}],
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),
@@ -432,7 +434,7 @@ check_fallback_args([Arg | Tail], FA) ->
check_fallback_args([], FA) ->
{ok, FA}.
-check_fallback_arg_type(Arg, FA) ->
+check_fallback_arg_type(Arg, FA) ->
case Arg of
{scope, global} ->
FA#fallback_args{scope = global};
@@ -460,10 +462,10 @@ atom_list([H | T]) when is_atom(H) ->
atom_list(T);
atom_list([]) ->
ok.
-
+
do_install_fallback(FA) ->
Pid = spawn_link(?MODULE, install_fallback_master, [self(), FA]),
- Res =
+ Res =
receive
{'EXIT', Pid, Reason} -> % if appl has trapped exit
{error, {'EXIT', Reason}};
@@ -504,7 +506,7 @@ restore_recs(Recs, Header, Schema, {start, 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),
+ global:del_lock({{mnesia_table_lock, schema}, self()}, Ns),
Res
end;
@@ -576,7 +578,7 @@ fallback_tmp_name() -> "FALLBACK.TMP".
-spec fallback_receiver(pid(), fallback_args()) -> no_return().
fallback_receiver(Master, FA) ->
process_flag(trap_exit, true),
-
+
case catch register(mnesia_fallback, self()) of
{'EXIT', _} ->
Reason = {already_exists, node()},
@@ -608,7 +610,7 @@ 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 ->
@@ -657,7 +659,7 @@ fallback_receiver_loop(Master, R, FA, State) ->
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]),
@@ -832,7 +834,7 @@ create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
ok = dets:delete(schema, {schema, Tab}),
create_dat_files(Tail, LocalTabs);
Storage =:= disc_only_copies ->
- Args = [{file, TmpFile}, {keypos, 2},
+ Args = [{file, TmpFile}, {keypos, 2},
{type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}],
Open = fun(T, LT) when T =:= LT#local_tab.name ->
case mnesia_lib:dets_sync_open(T, Args) of
@@ -859,9 +861,9 @@ create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
Swap = fun(T, LT) when T =:= LT#local_tab.name ->
Expunge(),
case LT#local_tab.opened of
- true ->
+ true ->
Close(T,LT);
- false ->
+ false ->
Open(T,LT),
Close(T,LT)
end,
@@ -885,8 +887,8 @@ create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
create_dat_files(Tail, LocalTabs);
Storage =:= ram_copies; Storage =:= disc_copies ->
Open = fun(T, LT) when T =:= LT#local_tab.name ->
- mnesia_log:open_log({?MODULE, T},
- mnesia_log:dcl_log_header(),
+ mnesia_log:open_log({?MODULE, T},
+ mnesia_log:dcl_log_header(),
TmpFile,
false,
false,
@@ -915,7 +917,7 @@ create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
true ->
Log = mnesia_log:open_log(fallback_tab,
mnesia_log:dcd_log_header(),
- DcdFile,
+ DcdFile,
false),
mnesia_log:close_log(Log),
case LT#local_tab.opened of
@@ -924,7 +926,7 @@ create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
false ->
Open(T,LT),
Close(T,LT)
- end,
+ end,
case file:rename(TmpFile, DclFile) of
ok ->
ok;
@@ -957,7 +959,7 @@ create_dat_files([], _LocalTabs) ->
ok.
uninstall_fallback() ->
- uninstall_fallback([{scope, global}]).
+ uninstall_fallback([{scope, global}]).
uninstall_fallback(Args) ->
case check_fallback_args(Args, #fallback_args{}) of
@@ -967,7 +969,7 @@ uninstall_fallback(Args) ->
{error, Reason}
end.
-do_uninstall_fallback(FA) ->
+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
@@ -1038,11 +1040,11 @@ do_uninstall(_ClientPid, [], GoodPids, 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}, []),
@@ -1050,7 +1052,7 @@ local_uninstall_fallback(Master, FA) ->
Tmp = FA2#fallback_args.fallback_tmp,
Bup = FA2#fallback_args.fallback_bup,
file:delete(Tmp),
- Res =
+ Res =
case fallback_exists(Bup) of
true -> file:delete(Bup);
false -> ok
@@ -1077,7 +1079,7 @@ rec_uninstall(ClientPid, [], Res) ->
ClientPid ! {self(), Res},
unlink(ClientPid),
exit(normal).
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Backup traversal
@@ -1128,7 +1130,7 @@ do_traverse_backup(ClientPid, Source, SourceMod, Target, TargetMod, Fun, Acc) ->
if
TargetMod =/= read_only ->
case catch do_apply(TargetMod, open_write, [Target], Target) of
- {error, Error} ->
+ {error, Error} ->
unlink(ClientPid),
ClientPid ! {iter_done, self(), {error, Error}},
exit(Error);
@@ -1138,15 +1140,15 @@ do_traverse_backup(ClientPid, Source, SourceMod, Target, TargetMod, Fun, Acc) ->
ignore
end,
A = {start, Fun, Acc, TargetMod, Iter},
- Res =
+ 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} ->
{error, Reason};
- _ ->
+ _ ->
{ok, Acc2}
- end;
+ end;
{ok, {iter, _, Acc2, _, _}} ->
{ok, Acc2};
{error, Reason} when TargetMod =/= read_only->
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 1d3bd55b48..d488a33d67 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -107,14 +107,14 @@
-include("mnesia.hrl").
--define(SERVER_NAME, ?MODULE).
+-define(SERVER_NAME, ?MODULE).
-record(state, {supervisor,
schema_is_merged = false,
early_msgs = [],
- loader_pid = [], %% Was Pid is now [{Pid,Work}|..]
+ loader_pid = [], %% Was Pid is now [{Pid,Work}|..]
loader_queue, %% Was list is now gb_tree
- sender_pid = [], %% Was a pid or undef is now [{Pid,Work}|..]
+ sender_pid = [], %% Was a pid or undef is now [{Pid,Work}|..]
sender_queue = [],
late_loader_queue, %% Was list is now gb_tree
dumper_pid, %% Dumper or schema commit pid
@@ -124,12 +124,12 @@
is_stopping = false
}).
%% Backwards Comp. Sender_pid is now a list of senders..
-get_senders(#state{sender_pid = Pids}) when is_list(Pids) -> Pids.
+get_senders(#state{sender_pid = Pids}) when is_list(Pids) -> Pids.
%% Backwards Comp. loader_pid is now a list of loaders..
-get_loaders(#state{loader_pid = Pids}) when is_list(Pids) -> Pids.
+get_loaders(#state{loader_pid = Pids}) when is_list(Pids) -> Pids.
max_loaders() ->
case ?catch_val(no_table_loaders) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
mnesia_lib:set(no_table_loaders,1),
1;
Val -> Val
@@ -153,7 +153,7 @@ max_loaders() ->
remote_storage
}).
--record(disc_load, {table,
+-record(disc_load, {table,
reason,
opt_reply_to
}).
@@ -184,7 +184,7 @@ max_loaders() ->
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.
@@ -199,7 +199,7 @@ 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
@@ -227,7 +227,7 @@ do_wait_for_tables(Tabs, Timeout) ->
exit(Pid, timeout),
reply_wait(Tabs)
end.
-
+
reply_wait(Tabs) ->
case catch mnesia_lib:active_tables() of
{'EXIT', _} ->
@@ -270,7 +270,7 @@ rec_tabs([Tab | Tabs], AllTabs, From, Init) ->
%% This will trigger an exit signal
%% to mnesia_init
exit(wait_for_tables_timeout);
-
+
{'EXIT', Init, _} ->
%% Oops, mnesia_init stopped,
exit(mnesia_stopped)
@@ -279,50 +279,14 @@ rec_tabs([], _, _, Init) ->
unlink(Init),
ok.
-%% 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).
+ get_cstructs(). %% Sigh not forward compatible always check version
%% 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)]).
-
+ {cstructs, mnesia_schema:normalize_cs(Cstructs, Node), Running}.
update(Fun) ->
call({update,Fun}).
@@ -352,7 +316,7 @@ get_network_copy(Tab, Cs) ->
% We can't let the controller queue this one
% because that may cause a deadlock between schema_operations
% and initial tableloadings which both takes schema locks.
-% But we have to get copier_done msgs when the other side
+% But we have to get copier_done msgs when the other side
% goes down.
call({add_other, self()}),
Reason = {dumper,add_table_copy},
@@ -374,14 +338,14 @@ get_network_copy(Tab, Cs) ->
ignore
end,
Res#loader_done.reply;
- #loader_done{} ->
+ #loader_done{} ->
Res#loader_done.reply;
Else ->
{not_loaded, Else}
end.
%% This functions is invoked from the dumper
-%%
+%%
%% There are two cases here:
%% startup ->
%% no need for sync, since mnesia_controller not started yet
@@ -413,11 +377,11 @@ force_load_table(Tab) when is_atom(Tab), Tab /= schema ->
end;
force_load_table(Tab) ->
{error, {bad_type, Tab}}.
-
+
do_force_load_table(Tab) ->
Loaded = ?catch_val({Tab, load_reason}),
case Loaded of
- unknown ->
+ unknown ->
set({Tab, load_by_force}, true),
mnesia_late_loader:async_late_disc_load(node(), [Tab], forced_by_user),
wait_for_tables([Tab], infinity);
@@ -427,7 +391,7 @@ do_force_load_table(Tab) ->
wait_for_tables([Tab], infinity);
_ ->
ok
- end.
+ end.
master_nodes_updated(schema, _Masters) ->
ignore;
master_nodes_updated(Tab, Masters) ->
@@ -471,15 +435,15 @@ connect_nodes(Ns) ->
connect_nodes(Ns, fun default_merge/1).
connect_nodes(Ns, UserFun) ->
- case mnesia:system_info(is_running) of
+ case mnesia:system_info(is_running) of
no ->
{error, {node_not_running, node()}};
- yes ->
+ yes ->
Pid = spawn_link(?MODULE,connect_nodes2,[self(),Ns, UserFun]),
- receive
- {?MODULE, Pid, Res, New} ->
+ receive
+ {?MODULE, Pid, Res, New} ->
case Res of
- ok ->
+ ok ->
mnesia_lib:add_list(extra_db_nodes, New),
{ok, New};
{aborted, {throw, Str}} when is_list(Str) ->
@@ -487,8 +451,8 @@ connect_nodes(Ns, UserFun) ->
{error, {merge_schema_failed, lists:flatten(Str)}};
Else ->
{error, Else}
- end;
- {'EXIT', Pid, Reason} ->
+ end;
+ {'EXIT', Pid, Reason} ->
{error, Reason}
end
end.
@@ -499,16 +463,16 @@ connect_nodes2(Father, Ns, UserFun) ->
{NewC, OldC} = mnesia_recover:connect_nodes(Ns),
Connected = NewC ++OldC,
New1 = mnesia_lib:intersect(Ns, Connected),
- New = New1 -- Current,
+ New = New1 -- Current,
process_flag(trap_exit, true),
Res = try_merge_schema(New, [], UserFun),
Msg = {schema_is_merged, [], late_merge, []},
multicall([node()|Ns], Msg),
- After = val({current, db_nodes}),
+ After = val({current, db_nodes}),
Father ! {?MODULE, self(), Res, mnesia_lib:intersect(Ns,After)},
unlink(Father),
ok.
-
+
%% 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.
@@ -516,7 +480,7 @@ connect_nodes2(Father, Ns, UserFun) ->
merge_schema() ->
AllNodes = mnesia_lib:all_nodes(),
case try_merge_schema(AllNodes, [node()], fun default_merge/1) of
- ok ->
+ ok ->
schema_is_merged();
{aborted, {throw, Str}} when is_list(Str) ->
fatal("Failed to merge schema: ~s~n", [Str]);
@@ -568,7 +532,7 @@ im_running(OldFriends, 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
@@ -578,7 +542,7 @@ schema_is_merged() ->
%% 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).
@@ -622,7 +586,7 @@ remote_call(Node, Func, Args) ->
Else ->
Else
end.
-
+
multicall(Nodes, Msg) ->
{Good, Bad} = gen_server:multi_call(Nodes, ?MODULE, Msg, infinity),
PatchedGood = [Reply || {_Node, Reply} <- Good],
@@ -654,9 +618,9 @@ init([Parent]) ->
Msg = {async_dump_log, time_threshold},
{ok, Ref} = timer:send_interval(Interval, Msg),
mnesia_dumper:start_regulator(),
-
+
Empty = gb_trees:empty(),
- {ok, #state{supervisor = Parent, dump_log_timer_ref = Ref,
+ {ok, #state{supervisor = Parent, dump_log_timer_ref = Ref,
loader_queue = Empty,
late_loader_queue = Empty}}.
@@ -689,17 +653,17 @@ handle_call(block_controller, From, State) ->
handle_call({update,Fun}, From, State) ->
Res = (catch Fun()),
- reply(From, Res),
+ reply(From, Res),
noreply(State);
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}),
+ reply(From, {cstructs, Cstructs, Running}),
noreply(State);
-handle_call({schema_is_merged, [], late_merge, []}, From,
+handle_call({schema_is_merged, [], late_merge, []}, From,
State = #state{schema_is_merged = Merged}) ->
case Merged of
{false, Node} when Node == node(From) ->
@@ -730,8 +694,8 @@ handle_call(disc_load_intents,From,State = #state{loader_queue=LQ,late_loader_qu
handle_call({update_where_to_write, [add, Tab, AddNode], _From}, _Dummy, State) ->
Current = val({current, db_nodes}),
- Res =
- case lists:member(AddNode, Current) and
+ Res =
+ case lists:member(AddNode, Current) and
(State#state.schema_is_merged == true) of
true ->
mnesia_lib:add_lsort({Tab, where_to_write}, AddNode),
@@ -765,7 +729,7 @@ handle_call({add_active_replica, [Tab, ToNode, RemoteS, AccessMode], From},
noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
end;
-handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
+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
@@ -785,16 +749,16 @@ handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
end;
handle_call({net_load, Tab, Cs}, From, State) ->
- State2 =
+ State2 =
case State#state.schema_is_merged of
- true ->
+ true ->
Worker = #net_load{table = Tab,
opt_reply_to = From,
reason = {dumper,add_table_copy},
cstruct = Cs
},
add_worker(Worker, State);
- false ->
+ false ->
reply(From, {not_loaded, schema_not_merged}),
State
end,
@@ -837,16 +801,16 @@ handle_call({add_other, Who}, _From, State = #state{others=Others0}) ->
handle_call({del_other, Who}, _From, State = #state{others=Others0}) ->
Others = lists:delete(Who, Others0),
{reply, ok, State#state{others=Others}};
-
+
handle_call(Msg, _From, State) ->
error("~p got unexpected call: ~p~n", [?SERVER_NAME, Msg]),
noreply(State).
-late_disc_load(TabsR, Reason, RemoteLoaders, From,
+late_disc_load(TabsR, Reason, RemoteLoaders, From,
State = #state{loader_queue = LQ, late_loader_queue = LLQ}) ->
verbose("Intend to load tables: ~p~n", [TabsR]),
?eval_debug_fun({?MODULE, late_disc_load},
- [{tabs, TabsR},
+ [{tabs, TabsR},
{reason, Reason},
{loaders, RemoteLoaders}]),
@@ -855,14 +819,14 @@ late_disc_load(TabsR, Reason, RemoteLoaders, From,
%% Remove deleted tabs and queued/loaded
LocalTabs = gb_sets:from_ordset(lists:sort(mnesia_lib:val({schema,local_tables}))),
- Filter = fun(TabInfo0, Acc) ->
- TabInfo = {Tab,_} =
- case TabInfo0 of
+ Filter = fun(TabInfo0, Acc) ->
+ TabInfo = {Tab,_} =
+ case TabInfo0 of
{_,_} -> TabInfo0;
TabN -> {TabN,Reason}
end,
case gb_sets:is_member(Tab, LocalTabs) of
- true ->
+ true ->
case ?catch_val({Tab, where_to_read}) == node() of
true -> Acc;
false ->
@@ -874,12 +838,12 @@ late_disc_load(TabsR, Reason, RemoteLoaders, From,
false -> Acc
end
end,
-
+
Tabs = lists:foldl(Filter, [], TabsR),
-
+
Nodes = val({current, db_nodes}),
LateQueue = late_loaders(Tabs, RemoteLoaders, Nodes, LLQ),
- State#state{late_loader_queue = LateQueue}.
+ State#state{late_loader_queue = LateQueue}.
late_loaders([{Tab, Reason} | Tabs], RemoteLoaders, Nodes, LLQ) ->
case gb_trees:is_defined(Tab, LLQ) of
@@ -892,7 +856,7 @@ late_loaders([{Tab, Reason} | Tabs], RemoteLoaders, Nodes, LLQ) ->
LateLoad = #late_load{table=Tab,loaders=LoadNodes,reason=Reason},
late_loaders(Tabs, RemoteLoaders, Nodes, gb_trees:insert(Tab,LateLoad,LLQ));
true ->
- late_loaders(Tabs, RemoteLoaders, Nodes, LLQ)
+ late_loaders(Tabs, RemoteLoaders, Nodes, LLQ)
end;
late_loaders([], _RemoteLoaders, _Nodes, LLQ) ->
LLQ.
@@ -932,7 +896,7 @@ late_load_filter([RL | RemoteLoaders], Tab, Nodes, Acc) ->
end;
late_load_filter([], _Tab, _Nodes, Acc) ->
Acc.
-
+
%%----------------------------------------------------------------------
%% Func: handle_cast/2
%% Returns: {noreply, State} |
@@ -944,7 +908,7 @@ handle_cast({release_schema_commit_lock, _Owner}, State) ->
if
State#state.is_stopping == true ->
{stop, shutdown, State};
- true ->
+ true ->
case State#state.dumper_queue of
[#schema_commit_lock{}|Rest] ->
[_Worker | Rest] = State#state.dumper_queue,
@@ -965,7 +929,7 @@ handle_cast(unblock_controller, State) ->
[_Worker | Rest] = State#state.dumper_queue,
State2 = State#state{dumper_pid = undefined,
dumper_queue = Rest},
- State3 = opt_start_worker(State2),
+ State3 = opt_start_worker(State2),
noreply(State3)
end;
@@ -981,31 +945,31 @@ handle_cast({mnesia_down, Node}, State) ->
%% Fix if we are late_merging against the node that went down
case State#state.schema_is_merged of
- {false, Node} ->
+ {false, Node} ->
spawn(?MODULE, call, [{schema_is_merged, [], late_merge, []}]);
_ ->
ignore
end,
-
+
%% Fix internal stuff
LateQ = remove_loaders(Alltabs, Node, State#state.late_loader_queue),
-
+
case get_senders(State) ++ get_loaders(State) of
[] -> ignore;
- Senders ->
+ Senders ->
lists:foreach(fun({Pid,_}) -> Pid ! {copier_done, Node} end,
Senders)
end,
- lists:foreach(fun(Pid) -> Pid ! {copier_done,Node} end,
+ lists:foreach(fun(Pid) -> Pid ! {copier_done,Node} end,
State#state.others),
-
+
Remove = fun(ST) ->
node(ST#send_table.receiver_pid) /= Node
end,
NewSenders = lists:filter(Remove, State#state.sender_queue),
Early = remove_early_messages(State#state.early_msgs, Node),
- noreply(State#state{sender_queue = NewSenders,
- early_msgs = Early,
+ noreply(State#state{sender_queue = NewSenders,
+ early_msgs = Early,
late_loader_queue = LateQ
});
@@ -1014,8 +978,8 @@ handle_cast({merging_schema, Node}, State) ->
false ->
%% This comes from dynamic connect_nodes which are made
%% after mnesia:start() and the schema_merge.
- ImANewKidInTheBlock =
- (val({schema, storage_type}) == ram_copies)
+ ImANewKidInTheBlock =
+ (val({schema, storage_type}) == ram_copies)
andalso (mnesia_lib:val({schema, local_tables}) == [schema]),
case ImANewKidInTheBlock of
true -> %% I'm newly started ram_node..
@@ -1033,7 +997,7 @@ handle_cast(Msg, State) when State#state.schema_is_merged /= true ->
noreply(State#state{early_msgs = [{cast, Msg} | Msgs]});
%% 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
+%% 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) ->
LocalTabs = mnesia_lib:local_active_tables() -- [schema],
@@ -1060,7 +1024,7 @@ handle_cast({sync_tabs, Tabs, From}, State) ->
handle_cast({i_have_tab, Tab, Node}, State) ->
case lists:member(Node, val({current, db_nodes})) of
- true ->
+ true ->
State2 = node_has_tabs([Tab], Node, State),
noreply(State2);
false ->
@@ -1076,10 +1040,10 @@ handle_cast({force_load_updated, Tab}, State) ->
State2 = node_has_tabs([Tab], SomeNode, State),
noreply(State2)
end;
-
+
handle_cast({master_nodes_updated, Tab, Masters}, State) ->
Active = val({Tab, active_replicas}),
- Valid =
+ Valid =
case val({Tab, load_by_force}) of
true ->
Active;
@@ -1099,10 +1063,10 @@ handle_cast({master_nodes_updated, Tab, Masters}, State) ->
State2 = node_has_tabs([Tab], SomeNode, State),
noreply(State2)
end;
-
+
handle_cast({adopt_orphans, Node, Tabs}, State) ->
State2 = node_has_tabs(Tabs, Node, State),
-
+
case ?catch_val({node_up,Node}) of
true -> ignore;
_ ->
@@ -1134,7 +1098,7 @@ handle_cast(Msg, State) ->
error("~p got unexpected cast: ~p~n", [?SERVER_NAME, Msg]),
noreply(State).
-handle_sync_tabs([Tab | Tabs], From) ->
+handle_sync_tabs([Tab | Tabs], From) ->
case val({Tab, where_to_read}) of
nowhere ->
case get({sync_tab, Tab}) of
@@ -1178,7 +1142,7 @@ handle_info(#dumper_done{worker_pid=Pid, worker_res=Res}, State) ->
{stop, fatal, State}
end;
-handle_info(Done = #loader_done{worker_pid=WPid, table_name=Tab}, State0) ->
+handle_info(Done = #loader_done{worker_pid=WPid, table_name=Tab}, State0) ->
LateQueue0 = State0#state.late_loader_queue,
State1 = State0#state{loader_pid = lists:keydelete(WPid,1,get_loaders(State0))},
@@ -1186,7 +1150,7 @@ handle_info(Done = #loader_done{worker_pid=WPid, table_name=Tab}, State0) ->
case Done#loader_done.is_loaded of
true ->
%% Optional table announcement
- if
+ if
Done#loader_done.needs_announce == true,
Done#loader_done.needs_reply == true ->
i_have_tab(Tab),
@@ -1220,7 +1184,7 @@ handle_info(Done = #loader_done{worker_pid=WPid, table_name=Tab}, State0) ->
State1#state{late_loader_queue=gb_trees:delete_any(Tab, LateQueue0)};
false ->
%% Either the node went down or table was not
- %% loaded remotly yet
+ %% loaded remotly yet
case Done#loader_done.needs_reply of
true ->
reply(Done#loader_done.reply_to,
@@ -1243,7 +1207,7 @@ handle_info(#sender_done{worker_pid=Pid, worker_res=Res}, State) ->
Senders = get_senders(State),
{value, {Pid,_Worker}} = lists:keysearch(Pid, 1, Senders),
if
- Res == ok ->
+ Res == ok ->
State2 = State#state{sender_pid = lists:keydelete(Pid, 1, Senders)},
State3 = opt_start_worker(State2),
noreply(State3);
@@ -1285,7 +1249,7 @@ handle_info(Msg = {'EXIT', Pid, R}, State) when R /= wait_for_tables_timeout ->
{stop, fatal, State};
false ->
case lists:keymember(Pid, 1, get_loaders(State)) of
- true ->
+ true ->
fatal("Loader crashed: ~p~n state: ~p~n", [R, State]),
{stop, fatal, State};
false ->
@@ -1371,7 +1335,7 @@ code_change(_OldVsn, State0, _Extra) ->
State1 = case State0#state.loader_pid of
Pids when is_list(Pids) -> State0;
undefined -> State0#state{loader_pid = [],loader_queue=gb_trees:empty()};
- Pid when is_pid(Pid) ->
+ Pid when is_pid(Pid) ->
[Loader|Rest] = State0#state.loader_queue,
LQ0 = [{element(2,Rec),Rec} || Rec <- Rest],
LQ1 = lists:sort(LQ0),
@@ -1379,7 +1343,7 @@ code_change(_OldVsn, State0, _Extra) ->
State0#state{loader_pid=[{Pid,Loader}], loader_queue=LQ}
end,
%% LateLoaderQueue
- State = if is_list(State1#state.late_loader_queue) ->
+ State = if is_list(State1#state.late_loader_queue) ->
LLQ0 = State1#state.late_loader_queue,
LLQ1 = lists:sort([{element(2,Rec),Rec} || Rec <- LLQ0]),
LLQ = gb_trees:from_orddict(LLQ1),
@@ -1388,7 +1352,7 @@ code_change(_OldVsn, State0, _Extra) ->
State1
end,
{ok, State}.
-
+
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
@@ -1398,20 +1362,20 @@ maybe_log_mnesia_down(N) ->
%% 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 ->
+ 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
+ if
HalfLoadedTabs == true ->
verbose("Logging mnesia_down ~w~n", [N]),
mnesia_recover:log_mnesia_down(N),
- ok;
+ ok;
true ->
%% Unfortunately we have not loaded some common
%% tables yet, so we cannot rely on the nodedown
@@ -1440,7 +1404,7 @@ orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
BeingCreated = (?catch_val({Tab, create_table}) == true),
Read = val({Tab, where_to_read}),
case lists:member(Node, DiscCopyHolders) of
- _ when BeingCreated == true ->
+ _ when BeingCreated == true ->
orphan_tables(Tabs, Node, Ns, Local, Remote);
_ when Read == node() -> %% Allready loaded
orphan_tables(Tabs, Node, Ns, Local, Remote);
@@ -1478,13 +1442,13 @@ orphan_tables([], _, _, LocalOrphans, RemoteMasters) ->
{LocalOrphans, RemoteMasters}.
node_has_tabs([Tab | Tabs], Node, State) when Node /= node() ->
- State2 =
+ State2 =
case catch update_whereabouts(Tab, Node, State) of
State1 = #state{} -> State1;
{'EXIT', R} -> %% Tab was just deleted?
case ?catch_val({Tab, cstruct}) of
{'EXIT', _} -> State; % yes
- _ -> erlang:error(R)
+ _ -> erlang:error(R)
end
end,
node_has_tabs(Tabs, Node, State2);
@@ -1510,14 +1474,14 @@ update_whereabouts(Tab, Node, State) ->
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;
- BeingCreated == true ->
+ BeingCreated == true ->
%% The table is currently being created
%% It will be handled elsewhere
State;
@@ -1534,8 +1498,8 @@ update_whereabouts(Tab, Node, State) ->
State
end;
Storage == unknown ->
- %% No own copy, continue to read remotely
- add_active_replica(Tab, Node),
+ %% 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
@@ -1575,16 +1539,16 @@ initial_safe_loads() ->
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),
@@ -1661,7 +1625,7 @@ 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)
+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);
@@ -1715,9 +1679,9 @@ is_tab_blocked(W2C) when is_list(W2C) ->
is_tab_blocked({blocked, W2C}) when is_list(W2C) ->
{true, W2C}.
-mark_blocked_tab(true, Value) ->
+mark_blocked_tab(true, Value) ->
{blocked, Value};
-mark_blocked_tab(false, Value) ->
+mark_blocked_tab(false, Value) ->
Value.
%%
@@ -1750,7 +1714,7 @@ del_active_replica(Tab, Node) ->
update_where_to_wlock(Tab).
change_table_access_mode(Cs) ->
- W = fun() ->
+ W = fun() ->
Tab = Cs#cstruct.name,
lists:foreach(fun(N) -> add_active_replica(Tab, N, Cs) end,
val({Tab, active_replicas}))
@@ -1779,7 +1743,7 @@ update_where_to_wlock(Tab) ->
unannounce_add_table_copy(Tab, To) ->
catch del_active_replica(Tab, To),
case catch val({Tab , where_to_read}) of
- To ->
+ To ->
mnesia_lib:set_remote_where_to_read(Tab);
_ ->
ignore
@@ -1792,7 +1756,7 @@ user_sync_tab(Tab) ->
_ ->
ignore
end,
-
+
case erase({sync_tab, Tab}) of
undefined ->
ok;
@@ -1811,11 +1775,11 @@ i_have_tab(Tab) ->
sync_and_block_table_whereabouts(Tab, ToNode, RemoteS, AccessMode) when Tab /= schema ->
Current = val({current, db_nodes}),
- Ns =
+ Ns =
case lists:member(ToNode, Current) of
true -> Current -- [ToNode];
false -> Current
- end,
+ end,
remote_call(ToNode, block_table, [Tab]),
[remote_call(Node, add_active_replica, [Tab, ToNode, RemoteS, AccessMode]) ||
Node <- [ToNode | Ns]],
@@ -1860,7 +1824,7 @@ get_workers(Timeout) ->
{timeout, Timeout}
end
end.
-
+
info() ->
Tabs = mnesia_lib:local_active_tables(),
io:format( "---> Active tables <--- ~n", []),
@@ -1869,12 +1833,12 @@ info() ->
info([Tab | Tail]) ->
case val({Tab, storage_type}) of
disc_only_copies ->
- info_format(Tab,
- dets:info(Tab, size),
+ info_format(Tab,
+ dets:info(Tab, size),
dets:info(Tab, file_size),
"bytes on disc");
_ ->
- info_format(Tab,
+ info_format(Tab,
?ets_info(Tab, size),
?ets_info(Tab, memory),
"words of mem")
@@ -1914,7 +1878,7 @@ handle_early_msg({cast, Msg}, State) ->
handle_cast(Msg, State);
handle_early_msg({info, Msg}, State) ->
handle_info(Msg, State).
-
+
noreply(State) ->
{noreply, State}.
@@ -1962,7 +1926,7 @@ add_worker(Worker = #send_table{}, State) ->
add_worker(Worker = #disc_load{}, State) ->
opt_start_worker(add_loader(Worker#disc_load.table,Worker,State));
% Block controller should be used for upgrading mnesia.
-add_worker(Worker = #block_controller{}, State) ->
+add_worker(Worker = #block_controller{}, State) ->
Queue = State#state.dumper_queue,
Queue2 = [Worker | Queue],
State2 = State#state{dumper_queue = Queue2},
@@ -1971,13 +1935,13 @@ add_worker(Worker = #block_controller{}, State) ->
add_loader(Tab,Worker,State = #state{loader_queue=LQ0}) ->
case gb_trees:is_defined(Tab, LQ0) of
true -> State;
- false ->
+ false ->
LQ=gb_trees:insert(Tab, Worker, LQ0),
State#state{loader_queue=LQ}
end.
%% 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.
@@ -1991,7 +1955,7 @@ opt_start_worker(State) ->
%% 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
is_record(Worker, schema_commit_lock) ->
@@ -1999,7 +1963,7 @@ opt_start_worker(State) ->
reply(ReplyTo, granted),
{Owner, _Tag} = ReplyTo,
opt_start_loader(State#state{dumper_pid = Owner});
-
+
is_record(Worker, dump_log) ->
Pid = spawn_link(?MODULE, dump_and_reply, [self(), Worker]),
State2 = State#state{dumper_pid = Pid},
@@ -2009,7 +1973,7 @@ opt_start_worker(State) ->
%% or sender
State3 = opt_start_sender(State2),
opt_start_loader(State3);
-
+
is_record(Worker, block_controller) ->
case {get_senders(State), get_loaders(State)} of
{[], []} ->
@@ -2022,7 +1986,7 @@ opt_start_worker(State) ->
end
end;
_ ->
- %% Bad luck, try with a loader or sender instead
+ %% Bad luck, try with a loader or sender instead
State2 = opt_start_sender(State),
opt_start_loader(State2)
end.
@@ -2030,8 +1994,8 @@ opt_start_worker(State) ->
opt_start_sender(State) ->
case State#state.sender_queue of
[]-> State; %% No need
- SenderQ ->
- {NewS,Kept} = opt_start_sender2(SenderQ, get_senders(State),
+ SenderQ ->
+ {NewS,Kept} = opt_start_sender2(SenderQ, get_senders(State),
[], get_loaders(State)),
State#state{sender_pid = NewS, sender_queue = Kept}
end.
@@ -2040,11 +2004,11 @@ opt_start_sender2([], Pids,Kept, _) -> {Pids,Kept};
opt_start_sender2([Sender|R], Pids, Kept, LoaderQ) ->
Tab = Sender#send_table.table,
Active = val({Tab, active_replicas}),
- IgotIt = lists:member(node(), Active),
- IsLoading = lists:any(fun({_Pid,Loader}) ->
+ IgotIt = lists:member(node(), Active),
+ IsLoading = lists:any(fun({_Pid,Loader}) ->
Tab == element(#net_load.table, Loader)
end, LoaderQ),
- if
+ if
IgotIt, IsLoading ->
%% I'm currently finishing loading the table let him wait
opt_start_sender2(R,Pids, [Sender|Kept], LoaderQ);
@@ -2062,11 +2026,11 @@ opt_start_loader(State = #state{loader_queue = LoaderQ}) ->
Current = get_loaders(State),
Max = max_loaders(),
case gb_trees:is_empty(LoaderQ) of
- true ->
+ true ->
State;
- _ when length(Current) >= Max ->
+ _ when length(Current) >= Max ->
State;
- false ->
+ false ->
SchemaQueue = State#state.dumper_queue,
case lists:keymember(schema_commit_lock, 1, SchemaQueue) of
false ->
@@ -2097,7 +2061,7 @@ already_loading(#disc_load{table=Tab},Loaders) ->
already_loading2(Tab, [{_,#net_load{table=Tab}}|_]) -> true;
already_loading2(Tab, [{_,#disc_load{table=Tab}}|_]) -> true;
-already_loading2(Tab, [_|Rest]) -> already_loading2(Tab,Rest);
+already_loading2(Tab, [_|Rest]) -> already_loading2(Tab,Rest);
already_loading2(_,[]) -> false.
start_remote_sender(Node, Tab, Receiver, Storage) ->
@@ -2126,8 +2090,8 @@ send_and_reply(ReplyTo, Worker) ->
load_and_reply(ReplyTo, Worker) ->
Load = load_table_fun(Worker),
- SendAndReply =
- fun() ->
+ SendAndReply =
+ fun() ->
process_flag(trap_exit, true),
Done = Load(),
ReplyTo ! Done#loader_done{worker_pid = self()},
@@ -2194,7 +2158,7 @@ load_table_fun(#disc_load{table=Tab, reason=Reason, opt_reply_to=ReplyTo}) ->
ReadNode == nowhere ->
%% Already loaded on other node, lets get it
Cs = val({Tab, cstruct}),
- fun() ->
+ fun() ->
case mnesia_loader:net_load_table(Tab, Reason, Active, Cs) of
{loaded, ok} ->
Done#loader_done{needs_sync = true};
@@ -2237,10 +2201,10 @@ filter_active(Tab) ->
Active = val({Tab, active_replicas}),
Masters = mnesia_recover:get_master_nodes(Tab),
Ns = do_filter_active(ByForce, Active, Masters),
- %% Reorder the so that we load from fastest first
+ %% Reorder the so that we load from fastest first
LS = ?catch_val({Tab, storage_type}),
DOC = val({Tab, disc_only_copies}),
- {Good,Worse} =
+ {Good,Worse} =
case LS of
disc_only_copies ->
G = mnesia_lib:intersect(Ns, DOC),
@@ -2251,7 +2215,7 @@ filter_active(Tab) ->
end,
%% Pick a random node of the fastest
Len = length(Good),
- if
+ if
Len > 0 ->
R = erlang:phash(node(), Len+1),
random(R-1,Good,Worse);
@@ -2270,5 +2234,5 @@ do_filter_active(false, Active, []) ->
Active;
do_filter_active(false, Active, Masters) ->
mnesia_lib:intersect(Active, Masters).
-
+
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index f8d7664156..e2a0aa3bda 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -43,7 +43,7 @@
%% Internal stuff
-export([regulator_init/1]).
-
+
-include("mnesia.hrl").
-include_lib("kernel/include/file.hrl").
@@ -70,14 +70,14 @@ incr_log_writes() ->
adjust_log_writes(DoCast) ->
Token = {mnesia_adjust_log_writes, self()},
- case global:set_lock(Token, [node()], 1) of
+ case global:set_lock(Token, [node()], 1) of
false ->
ignore; %% Somebody else is sending a dump request
- true ->
- case DoCast of
+ true ->
+ case DoCast of
false ->
ignore;
- true ->
+ true ->
mnesia_controller:async_dump_log(write_threshold)
end,
Max = mnesia_monitor:get_env(dump_log_write_threshold),
@@ -93,16 +93,16 @@ adjust_log_writes(DoCast) ->
opt_dump_log(InitBy) ->
Reg = case whereis(?REGULATOR_NAME) of
undefined ->
- nopid;
+ nopid;
Pid when is_pid(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);
@@ -112,8 +112,8 @@ 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),
+ [InitBy, LogState]),
+ adjust_log_writes(false),
case LogState of
already_dumped ->
mnesia_recover:allow_garb(),
@@ -142,7 +142,7 @@ perform_dump(InitBy, Regulator) ->
mnesia_lib:important(Desc, Reason),
%% Ignore rest of the log
mnesia_log:confirm_log_dump(Diff);
- false ->
+ false ->
fatal(Desc, Reason)
end
end;
@@ -189,9 +189,9 @@ do_perform_dump(Cont, InPlace, InitBy, Regulator, OldVersion) ->
insert_recs([Rec | Recs], InPlace, InitBy, Regulator, LogV) ->
regulate(Regulator),
case insert_rec(Rec, InPlace, InitBy, LogV) of
- LogH when is_record(LogH, log_header) ->
+ LogH when is_record(LogH, log_header) ->
insert_recs(Recs, InPlace, InitBy, Regulator, LogH#log_header.log_version);
- _ ->
+ _ ->
insert_recs(Recs, InPlace, InitBy, Regulator, LogV)
end;
@@ -199,7 +199,7 @@ insert_recs([], _InPlace, _InitBy, _Regulator, Version) ->
Version.
insert_rec(Rec, _InPlace, scan_decisions, _LogV) ->
- if
+ if
is_record(Rec, commit) ->
ignore;
is_record(Rec, log_header) ->
@@ -227,7 +227,7 @@ insert_rec(H, _InPlace, _InitBy, _LogV) when is_record(H, log_header) ->
H#log_header.log_kind /= trans_log ->
exit({"Bad kind of transaction log", H});
H#log_header.log_version == CurrentVersion ->
- ok;
+ ok;
H#log_header.log_version == "4.2" ->
ok;
H#log_header.log_version == "4.1" ->
@@ -247,8 +247,8 @@ do_insert_rec(Tid, Rec, InPlace, InitBy, LogV) ->
[] ->
ignore;
SchemaOps ->
- case val({schema, storage_type}) of
- ram_copies ->
+ 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),
@@ -264,13 +264,13 @@ do_insert_rec(Tid, Rec, 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),
+ Res = perform_update(Tid, SchemaOps, DumperMode, UseDir),
mnesia_controller:release_schema_commit_lock(),
Res.
@@ -279,23 +279,23 @@ perform_update(_Tid, _SchemaOps, mandatory, true) ->
%% dumper perform needed updates
InitBy = schema_update,
- ?eval_debug_fun({?MODULE, dump_schema_op}, [InitBy]),
+ ?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,
+ 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,
+ 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
@@ -318,7 +318,7 @@ insert_ops(Tid, Storage, [Op | Ops], InPlace, InitBy, Ver) when Ver < "4.3" ->
disc_insert(_Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
case open_files(Tab, Storage, InPlace, InitBy) of
true ->
- case Storage of
+ case Storage of
disc_copies when Tab /= schema ->
mnesia_log:append({?MODULE,Tab}, {{Tab, Key}, Val, Op}),
ok;
@@ -331,7 +331,7 @@ disc_insert(_Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
%% To fix update_counter so that it behaves better.
%% i.e. if nothing have changed in tab except update_counter
-%% trust that the value in the dets file is correct.
+%% trust that the value in the dets file is correct.
%% Otherwise we will get a double increment.
%% This is perfect but update_counter is a dirty op.
@@ -353,12 +353,12 @@ dets_insert(Op,Tab,Key,Val) ->
_ when Incr < 0 ->
Zero = {RecName, Key, 0},
ok = dets:insert(Tab, Zero);
- _ ->
+ _ ->
Init = {RecName, Key, Incr},
ok = dets:insert(Tab, Init)
end;
false -> ok
- end;
+ end;
delete_object ->
dets_updated(Tab,Key),
ok = dets:delete_object(Tab, Val);
@@ -366,17 +366,17 @@ dets_insert(Op,Tab,Key,Val) ->
dets_cleared(Tab),
ok = dets:delete_all_objects(Tab)
end.
-
-dets_updated(Tab,Key) ->
+
+dets_updated(Tab,Key) ->
case get(mnesia_dumper_dets) of
- undefined ->
+ undefined ->
Empty = gb_trees:empty(),
Tree = gb_trees:insert(Tab, gb_sets:singleton(Key), Empty),
put(mnesia_dumper_dets, Tree);
Tree ->
case gb_trees:lookup(Tab,Tree) of
{value, cleared} -> ignore;
- {value, Set} ->
+ {value, Set} ->
T = gb_trees:update(Tab, gb_sets:add(Key, Set), Tree),
put(mnesia_dumper_dets, T);
none ->
@@ -398,14 +398,14 @@ dets_incr_counter(Tab,Key) ->
dets_cleared(Tab) ->
case get(mnesia_dumper_dets) of
- undefined ->
+ undefined ->
Empty = gb_trees:empty(),
Tree = gb_trees:insert(Tab, cleared, Empty),
put(mnesia_dumper_dets, Tree);
Tree ->
case gb_trees:lookup(Tab,Tree) of
{value, cleared} -> ignore;
- _ ->
+ _ ->
T = gb_trees:enter(Tab, cleared, Tree),
put(mnesia_dumper_dets, T)
end
@@ -417,7 +417,7 @@ insert(Tid, Storage, Tab, Key, [Val | 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
@@ -447,18 +447,18 @@ insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
disc_delete_table(Tab, Storage) ->
case mnesia_monitor:use_dir() of
true ->
- if
- Storage == disc_only_copies; Tab == schema ->
+ if
+ Storage == disc_only_copies; Tab == schema ->
mnesia_monitor:unsafe_close_dets(Tab),
Dat = mnesia_lib:tab2dat(Tab),
- file:delete(Dat);
- true ->
+ 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),
@@ -490,7 +490,7 @@ insert_op(Tid, Storage, {{Tab, Key}, Val, Op}, InPlace, InitBy) ->
insert_op(_Tid, schema_ops, _OP, _InPlace, Initby)
when Initby /= startup,
Initby /= fast_schema_update,
- Initby /= schema_update ->
+ Initby /= schema_update ->
ignore;
insert_op(Tid, _, {op, rec, Storage, Item}, InPlace, InitBy) ->
@@ -507,7 +507,7 @@ insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace,
_ ->
ignore
end,
- if
+ if
N == node() ->
Dmp = mnesia_lib:tab2dmp(Tab),
Dat = mnesia_lib:tab2dat(Tab),
@@ -531,8 +531,8 @@ insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace,
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
+ %% 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,
@@ -540,17 +540,17 @@ insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace,
{disc_only_copies, ram_copies} ->
mnesia_monitor:unsafe_close_dets(Tab),
disc_delete_indecies(Tab, Cs, disc_only_copies),
- case InitBy of
- startup ->
+ 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),
+ mnesia_schema:ram_delete_table(Tab, FromS),
PosList = Cs#cstruct.index,
mnesia_index:init_indecies(Tab, disc_only_copies, PosList),
file:delete(Dcl),
@@ -558,8 +558,8 @@ insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace,
{disc_only_copies, disc_copies} ->
mnesia_monitor:unsafe_close_dets(Tab),
disc_delete_indecies(Tab, Cs, disc_only_copies),
- case InitBy of
- startup ->
+ case InitBy of
+ startup ->
ignore;
_ ->
mnesia_log:ets2dcd(Tab),
@@ -576,7 +576,7 @@ insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace,
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 ->
+ disc_copies ->
open_dcl(Cs#cstruct.name);
_ ->
ignore
@@ -604,28 +604,34 @@ insert_op(Tid, _, {op, restore_recreate, TabDef}, InPlace, InitBy) ->
mnesia_checkpoint:tm_del_copy(Tab, node())
end
end,
+ StorageProps = Cs#cstruct.storage_properties,
+
%% And create new ones..
if
(InitBy == startup) or (Storage == unknown) ->
ignore;
Storage == ram_copies ->
- Args = [{keypos, 2}, public, named_table, Type],
+ EtsProps = proplists:get_value(ets, StorageProps, []),
+ Args = [{keypos, 2}, public, named_table, Type | EtsProps],
mnesia_monitor:mktab(Tab, Args);
Storage == disc_copies ->
- Args = [{keypos, 2}, public, named_table, Type],
+ EtsProps = proplists:get_value(ets, StorageProps, []),
+ Args = [{keypos, 2}, public, named_table, Type | EtsProps],
mnesia_monitor:mktab(Tab, Args),
- File = mnesia_lib:tab2dcd(Tab),
- FArg = [{file, File}, {name, {mnesia,create}},
+ 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),
+ DetsProps = proplists:get_value(dets, StorageProps, []),
Args = [{file, mnesia_lib:tab2dat(Tab)},
{type, mnesia_lib:disk_type(Tab, Type)},
{keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
+ {repair, mnesia_monitor:get_env(auto_repair)}
+ | DetsProps ],
mnesia_monitor:open_dets(Tab, Args)
end,
insert_op(Tid, ignore, {op, create_table, TabDef}, InPlace, InitBy);
@@ -635,6 +641,7 @@ insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
insert_cstruct(Tid, Cs, false, InPlace, InitBy),
Tab = Cs#cstruct.name,
Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ StorageProps = Cs#cstruct.storage_properties,
case InitBy of
startup ->
case Storage of
@@ -644,22 +651,25 @@ insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
ignore;
disc_copies ->
Dcd = mnesia_lib:tab2dcd(Tab),
- case mnesia_lib:exists(Dcd) of
+ case mnesia_lib:exists(Dcd) of
true -> ignore;
false ->
- mnesia_log:open_log(temp,
+ mnesia_log:open_log(temp,
mnesia_log:dcd_log_header(),
- Dcd,
- false,
+ Dcd,
+ false,
false,
read_write),
mnesia_log:unsafe_close_log(temp)
end;
_ ->
+ DetsProps = proplists:get_value(dets, StorageProps, []),
+
Args = [{file, mnesia_lib:tab2dat(Tab)},
{type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)},
{keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
+ {repair, mnesia_monitor:get_env(auto_repair)}
+ | DetsProps ],
case mnesia_monitor:open_dets(Tab, Args) of
{ok, _} ->
mnesia_monitor:unsafe_close_dets(Tab);
@@ -671,7 +681,7 @@ insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
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 ->
mnesia_lib:unset({Tab, create_table}),
@@ -695,8 +705,8 @@ insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
%% Indecies are still created by loader
disc_delete_indecies(Tab, Cs, Storage)
%% disc_delete_table(Tab, Storage)
- end,
-
+ end,
+
%% Update whereabouts and create table
mnesia_controller:create_table(Tab),
mnesia_lib:unset({Tab, create_table})
@@ -754,7 +764,7 @@ insert_op(Tid, _, {op, clear_table, TabDef}, InPlace, InitBy) ->
true ->
ignore
end,
- %% Need to catch this, it crashes on ram_copies if
+ %% Need to catch this, it crashes on ram_copies if
%% the op comes before table is loaded at startup.
catch insert(Tid, Storage, Tab, '_', Oid, clear_table, InPlace, InitBy)
end;
@@ -766,16 +776,16 @@ insert_op(Tid, _, {op, merge_schema, TabDef}, InPlace, InitBy) ->
%% If we bootstrap an empty (diskless) mnesia from another node
%% we might have changed the storage_type of schema.
%% I think this is a good place to do it.
- Update = fun(NS = {Node,Storage}) ->
+ Update = fun(NS = {Node,Storage}) ->
case mnesia_lib:cs_to_storage_type(Node, Cs) of
Storage -> NS;
- disc_copies when Node == node() ->
- Dir = mnesia_lib:dir(),
+ disc_copies when Node == node() ->
+ Dir = mnesia_lib:dir(),
ok = mnesia_schema:opt_create_dir(true, Dir),
mnesia_schema:purge_dir(Dir, []),
mnesia_log:purge_all_logs(),
- mnesia_lib:set(use_dir, true),
+ mnesia_lib:set(use_dir, true),
mnesia_log:init(),
Ns = val({current, db_nodes}),
F = fun(U) -> mnesia_recover:log_mnesia_up(U) end,
@@ -783,11 +793,11 @@ insert_op(Tid, _, {op, merge_schema, TabDef}, InPlace, InitBy) ->
raw_named_dump_table(schema, dat),
temp_set_master_nodes(),
{Node,disc_copies};
- CSstorage ->
+ CSstorage ->
{Node,CSstorage}
end
end,
-
+
W2C0 = val({schema, where_to_commit}),
W2C = case W2C0 of
{blocked, List} ->
@@ -854,9 +864,9 @@ insert_op(Tid, _, {op, del_snmp, TabDef}, InPlace, InitBy) ->
InitBy /= startup,
Storage /= unknown ->
case ?catch_val({Tab, {index, snmp}}) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
ignore;
- Stab ->
+ Stab ->
mnesia_snmp_hook:delete_table(Tab, Stab),
mnesia_lib:unset({Tab, {index, snmp}})
end;
@@ -874,7 +884,7 @@ insert_op(Tid, _, {op, add_index, Pos, TabDef}, InPlace, InitBy) ->
true = open_files(Tab, Storage, InPlace, InitBy),
mnesia_index:init_indecies(Tab, Storage, [Pos]);
startup ->
- ignore;
+ ignore;
_ ->
case val({Tab,where_to_read}) of
nowhere -> ignore;
@@ -890,7 +900,7 @@ insert_op(Tid, _, {op, del_index, Pos, TabDef}, InPlace, InitBy) ->
case InitBy of
startup when Storage == disc_only_copies ->
mnesia_index:del_index_table(Tab, Storage, Pos);
- startup ->
+ startup ->
ignore;
_ ->
mnesia_index:del_index_table(Tab, Storage, Pos)
@@ -939,16 +949,19 @@ open_files(Tab, Storage, UpdateInPlace, InitBy)
{'EXIT', _} ->
false;
Type ->
- case Storage of
+ case Storage of
disc_copies when Tab /= schema ->
Bool = open_disc_copies(Tab, InitBy),
Bool;
_ ->
+ Props = val({Tab, storage_properties}),
+ DetsProps = proplists:get_value(dets, Props, []),
Fname = prepare_open(Tab, UpdateInPlace),
Args = [{file, Fname},
{keypos, 2},
{repair, mnesia_monitor:get_env(auto_repair)},
- {type, mnesia_lib:disk_type(Tab, Type)}],
+ {type, mnesia_lib:disk_type(Tab, Type)}
+ | DetsProps],
{ok, _} = mnesia_monitor:open_dets(Tab, Args),
put({?MODULE, Tab}, {opened_dumper, dat}),
true
@@ -964,7 +977,7 @@ open_files(_Tab, _Storage, _UpdateInPlace, _InitBy) ->
open_disc_copies(Tab, InitBy) ->
DclF = mnesia_lib:tab2dcl(Tab),
- DumpEts =
+ DumpEts =
case file:read_file_info(DclF) of
{error, enoent} ->
false;
@@ -975,7 +988,7 @@ open_disc_copies(Tab, InitBy) ->
mnesia_lib:dbg_out("File ~p info_error ~p ~n",
[DcdF, Reason]),
true;
- {ok, DcdInfo} ->
+ {ok, DcdInfo} ->
Mul = case ?catch_val(dc_dump_limit) of
{'EXIT', _} -> ?DumpToEtsMultiplier;
Val -> Val
@@ -983,12 +996,12 @@ open_disc_copies(Tab, InitBy) ->
DcdInfo#file_info.size =< (DclInfo#file_info.size * Mul)
end
end,
- if
- DumpEts == false; InitBy == startup ->
- mnesia_log:open_log({?MODULE,Tab},
- mnesia_log:dcl_log_header(),
- DclF,
- mnesia_lib:exists(DclF),
+ 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}),
@@ -997,9 +1010,9 @@ open_disc_copies(Tab, InitBy) ->
mnesia_log:ets2dcd(Tab),
put({?MODULE, Tab}, already_dumped),
false
- end.
+ end.
-%% Always opens the dcl file for writing overriding already_dumped
+%% Always opens the dcl file for writing overriding already_dumped
%% mechanismen, used for schema transactions.
open_dcl(Tab) ->
case get({?MODULE, Tab}) of
@@ -1007,10 +1020,10 @@ open_dcl(Tab) ->
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_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}),
@@ -1047,7 +1060,7 @@ close_files(InPlace, Outcome, InitBy, [{{?MODULE, Tab}, {opened_dumper, Type}} |
case val({Tab, storage_type}) of
disc_only_copies when InitBy /= startup ->
ignore;
- disc_copies when Tab /= schema ->
+ disc_copies when Tab /= schema ->
mnesia_log:close_log({?MODULE,Tab});
Storage ->
do_close(InPlace, Outcome, Tab, Type, Storage)
@@ -1082,7 +1095,7 @@ do_close(InPlace, Outcome, Tab, dat, Storage) ->
true ->
file:delete(mnesia_lib:tab2tmp(Tab))
end.
-
+
ensure_rename(From, To) ->
case mnesia_lib:exists(From) of
@@ -1096,7 +1109,7 @@ ensure_rename(From, To) ->
{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,
@@ -1114,15 +1127,15 @@ delete_cstruct(Tid, Cs, InPlace, InitBy) ->
temp_set_master_nodes() ->
Tabs = val({schema, local_tables}),
- Masters = [{Tab, (val({Tab, disc_copies}) ++
- val({Tab, ram_copies}) ++
- val({Tab, disc_only_copies})) -- [node()]}
+ Masters = [{Tab, (val({Tab, disc_copies}) ++
+ val({Tab, ram_copies}) ++
+ val({Tab, disc_only_copies})) -- [node()]}
|| Tab <- Tabs],
%% UseDir = false since we don't want to remember these
%% masternodes and we are running (really soon anyway) since we want this
%% to be known during table loading.
mnesia_recover:log_master_nodes(Masters, false, yes),
- ok.
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Raw dump of table. Dumper must have unique access to the ets table.
@@ -1152,7 +1165,7 @@ raw_named_dump_table(Tab, Ftype) ->
{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),
@@ -1179,11 +1192,11 @@ raw_dump_table(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 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.
@@ -1230,6 +1243,6 @@ regulate(RegulatorPid) ->
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.
diff --git a/lib/mnesia/src/mnesia_event.erl b/lib/mnesia/src/mnesia_event.erl
index ec6b99ecaa..8085155fd5 100644
--- a/lib/mnesia/src/mnesia_event.erl
+++ b/lib/mnesia/src/mnesia_event.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
@@ -121,7 +121,7 @@ handle_system_event({mnesia_up, Node}, State) ->
{ok, State#state{nodes = Nodes}};
handle_system_event({mnesia_down, Node}, State) ->
- case mnesia:system_info(fallback_activated) of
+ case mnesia:system_info(fallback_activated) andalso Node =/= node() of
true ->
case mnesia_monitor:get_env(fallback_error_function) of
{mnesia, lkill} ->
@@ -129,8 +129,8 @@ handle_system_event({mnesia_down, Node}, State) ->
"must be restarted. Forcing shutdown "
"after mnesia_down from ~p...~n",
report_fatal(Msg, [Node], nocore, State#state.dumped_core),
- mnesia:lkill(),
- exit(fatal);
+ catch exit(whereis(mnesia_monitor), fatal),
+ {ok, State};
{UserMod, UserFunc} ->
Msg = "Warning: A fallback is installed and Mnesia got mnesia_down "
"from ~p. ~n",
diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl
index 9e77fe0b9f..4a1616e054 100644
--- a/lib/mnesia/src/mnesia_frag.erl
+++ b/lib/mnesia/src/mnesia_frag.erl
@@ -758,7 +758,7 @@ make_activate(Tab, Props) ->
[] ->
Cs2 = Cs#cstruct{frag_properties = Props},
[Cs3] = expand_cstruct(Cs2, activate),
- TabDef = mnesia_schema:cs2list(Cs3),
+ TabDef = mnesia_schema:vsn_cs2list(Cs3),
Op = {op, change_table_frag, activate, TabDef},
[[Op]];
BadProps ->
@@ -783,7 +783,7 @@ make_deactivate(Tab) ->
mnesia:abort({combine_error, Tab, "Too many fragments"});
true ->
Cs2 = Cs#cstruct{frag_properties = []},
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
Op = {op, change_table_frag, deactivate, TabDef},
[[Op]]
end.
@@ -850,7 +850,7 @@ make_add_frag(Tab, SortedNs) ->
SplitOps = split(Tab, FH2, FromIndecies, FragNames, []),
Cs2 = replace_frag_hash(Cs, FH2),
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
BaseOp = {op, change_table_frag, {add_frag, SortedNs}, TabDef},
[BaseOp, NewOp | SplitOps].
@@ -962,7 +962,7 @@ make_del_frag(Tab) ->
LastFrag = element(N, FragNames),
[LastOp] = mnesia_schema:make_delete_table(LastFrag, single_frag),
Cs2 = replace_frag_hash(Cs, FH2),
- TabDef = mnesia_schema:cs2list(Cs2),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
BaseOp = {op, change_table_frag, del_frag, TabDef},
[BaseOp, LastOp | MergeOps];
_ ->
@@ -1075,7 +1075,7 @@ make_add_node(Tab, Node) when is_atom(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),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
Op = {op, change_table_frag, {add_node, Node}, TabDef},
[Op];
true ->
@@ -1104,7 +1104,7 @@ make_del_node(Tab, Node) when is_atom(Node) ->
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),
+ TabDef = mnesia_schema:vsn_cs2list(Cs2),
Op = {op, change_table_frag, {del_node, Node}, TabDef},
[Op];
false ->
diff --git a/lib/mnesia/src/mnesia_frag_hash.erl b/lib/mnesia/src/mnesia_frag_hash.erl
index 610ba2535c..3dfdb87f30 100644
--- a/lib/mnesia/src/mnesia_frag_hash.erl
+++ b/lib/mnesia/src/mnesia_frag_hash.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
@@ -101,21 +101,19 @@ del_frag(OldState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-key_to_frag_number(#hash_state{function = phash, next_n_to_split = SplitN, n_doubles = L}, Key) ->
- P = SplitN,
- A = erlang:phash(Key, power2(L)),
+key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
+ A = erlang:phash(Key, power2(L + 1)),
if
- A < P ->
- erlang:phash(Key, power2(L + 1));
+ A > N ->
+ A - power2(L);
true ->
A
end;
-key_to_frag_number(#hash_state{function = phash2, next_n_to_split = SplitN, n_doubles = L}, Key) ->
- P = SplitN,
- A = erlang:phash2(Key, power2(L)) + 1,
+key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
+ A = erlang:phash2(Key, power2(L + 1)) + 1,
if
- A < P ->
- erlang:phash2(Key, power2(L + 1)) + 1;
+ A > N ->
+ A - power2(L);
true ->
A
end;
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 61210d7e55..37989a1958 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -120,9 +120,9 @@ del_object_bag(Tab, Key, Obj, Pos, Ixt, undefined) ->
IxKey = element(Pos, Obj),
Old = [X || X <- mnesia_lib:db_get(Tab, Key), element(Pos, X) =:= IxKey],
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 ->
+%% If Tab type is bag we need remove index identifier if the object being
+%% deleted was the last one
+del_object_bag(_Tab, Key, Obj, Pos, Ixt, Old) when Old =:= [Obj] ->
del_ixes(Ixt, [Obj], Pos, Key);
del_object_bag(_Tab, _Key, _Obj, _Pos, _Ixt, _Old) -> ok.
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index c4b22814a8..4ba400fbbf 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -57,13 +57,15 @@ disc_load_table(Tab, Reason) ->
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}; %% ?
+ {not_loaded, storage_unknown};
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],
+ StorageProps = val({Tab, storage_properties}),
+ EtsOpts = proplists:get_value(ets, StorageProps, []),
+ Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources allready allocated
+ {dumper, _} -> %% Resources already allocated
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
@@ -82,7 +84,9 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
{loaded, ok};
do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
- Args = [{keypos, 2}, public, named_table, Type],
+ StorageProps = val({Tab, storage_properties}),
+ EtsOpts = proplists:get_value(ets, StorageProps, []),
+ Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
{dumper, _} -> %% Resources allready allocated
ignore;
@@ -115,10 +119,14 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
{loaded, ok};
do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies ->
+ StorageProps = val({Tab, storage_properties}),
+ DetsOpts = proplists:get_value(dets, StorageProps, []),
+
Args = [{file, mnesia_lib:tab2dat(Tab)},
{type, mnesia_lib:disk_type(Tab, Type)},
{keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
+ {repair, mnesia_monitor:get_env(auto_repair)}
+ | DetsOpts],
case Reason of
{dumper, _} ->
mnesia_index:init_index(Tab, Storage),
@@ -349,17 +357,21 @@ do_init_table(Tab,Storage,Cs,SenderPid,
end.
create_table(Tab, TabSize, Storage, Cs) ->
+ StorageProps = val({Tab, storage_properties}),
if
Storage == disc_only_copies ->
mnesia_lib:lock_table(Tab),
Tmp = mnesia_lib:tab2tmp(Tab),
Size = lists:max([TabSize, 256]),
+ DetsOpts = lists:keydelete(estimated_no_objects, 1,
+ proplists:get_value(dets, StorageProps, [])),
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)}],
+ {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}
+ | DetsOpts],
file:delete(Tmp),
case mnesia_lib:dets_sync_open(Tab, Args) of
{ok, _} ->
@@ -370,7 +382,8 @@ create_table(Tab, TabSize, Storage, Cs) ->
Else
end;
(Storage == ram_copies) or (Storage == disc_copies) ->
- Args = [{keypos, 2}, public, named_table, Cs#cstruct.type],
+ EtsOpts = proplists:get_value(ets, StorageProps, []),
+ Args = [{keypos, 2}, public, named_table, Cs#cstruct.type | EtsOpts],
case mnesia_monitor:unsafe_mktab(Tab, Args) of
Tab ->
{Storage, Tab};
@@ -516,10 +529,13 @@ handle_last({disc_only_copies, Tab}, Type, nobin) ->
Dat = mnesia_lib:tab2dat(Tab),
case file:rename(Tmp, Dat) of
ok ->
+ StorageProps = val({Tab, storage_properties}),
+ DetsOpts = proplists:get_value(dets, StorageProps, []),
+
Args = [{file, mnesia_lib:tab2dat(Tab)},
{type, mnesia_lib:disk_type(Tab, Type)},
{keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
+ {repair, mnesia_monitor:get_env(auto_repair)} | DetsOpts],
mnesia_monitor:open_dets(Tab, Args),
ok;
{error, Reason} ->
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index 0492d794f3..a22c95d454 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -66,14 +66,14 @@
-record(queue, {oid, tid, op, pid, lucky}).
-%% mnesia_held_locks: contain {Oid, Op, Tid} entries (bag)
+%% mnesia_held_locks: contain {Oid, MaxLock, [{Op, Tid}]} entries
-define(match_oid_held_locks(Oid), {Oid, '_', '_'}).
-%% mnesia_tid_locks: contain {Tid, Oid, Op} entries (bag)
+%% 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 (bag)
--define(match_oid_lock_queue(Oid), #queue{oid=Oid, tid='_', op = '_', pid = '_', lucky = '_'}).
+-define(match_oid_lock_queue(Oid), #queue{oid=Oid, tid='_', op = '_', pid = '_', lucky = '_'}).
%% mnesia_lock_counter: {{write, Tab}, Number} &&
%% {{read, Tab}, Number} entries (set)
@@ -83,11 +83,11 @@ start() ->
init(Parent) ->
register(?MODULE, self()),
process_flag(trap_exit, true),
- ?ets_new_table(mnesia_held_locks, [bag, private, named_table]),
+ ?ets_new_table(mnesia_held_locks, [ordered_set, private, named_table]),
?ets_new_table(mnesia_tid_locks, [bag, private, named_table]),
?ets_new_table(mnesia_sticky_locks, [set, private, named_table]),
?ets_new_table(mnesia_lock_queue, [bag, private, named_table, {keypos, 2}]),
-
+
proc_lib:init_ack(Parent, {ok, self()}),
case ?catch_val(pid_sort_order) of
r9b_plain -> put(pid_sort_order, r9b_plain);
@@ -98,8 +98,8 @@ init(Parent) ->
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.
reply(From, R) ->
@@ -111,10 +111,10 @@ l_request(Node, X, Store) ->
l_req_rec(Node, Store) ->
?ets_insert(Store, {nodes, Node}),
- receive
- {?MODULE, Node, Reply} ->
+ receive
+ {?MODULE, Node, Reply} ->
Reply;
- {mnesia_down, Node} ->
+ {mnesia_down, Node} ->
{not_granted, {node_not_running, Node}}
end.
@@ -128,10 +128,10 @@ 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
+ {?MODULE, Node, {tid_released, Tid}} ->
receive_release_tid_acc(Nodes, Tid);
- {mnesia_down, Node} ->
+ {mnesia_down, Node} ->
receive_release_tid_acc(Nodes, Tid)
end;
receive_release_tid_acc([], _Tid) ->
@@ -152,27 +152,27 @@ 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
+ %% Lock is stuck here, see now if we can just set
%% a regular write lock
try_lock(Tid, Lock, From, Oid),
loop(State);
@@ -188,7 +188,7 @@ loop(State) ->
?ets_insert(mnesia_sticky_locks, {Tab, N}),
loop(State);
- %% The caller which sends this message, must have first
+ %% 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),
@@ -205,14 +205,14 @@ loop(State) ->
[{_,N}] ->
Req = {From, {ix_read, Tid, Tab, IxKey, Pos}},
From ! {?MODULE, node(), {switch, N, Req}},
- loop(State)
+ loop(State)
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),
@@ -229,16 +229,23 @@ loop(State) ->
{get_table, From, LockTable} ->
From ! {LockTable, ?ets_match_object(LockTable, '_')},
loop(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}).
+set_lock(Tid, Oid, Op, []) ->
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, Op}),
+ ?ets_insert(mnesia_held_locks, {Oid, Op, [{Op, Tid}]});
+set_lock(Tid, Oid, read, [{Oid, Prev, Items}]) ->
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, read}),
+ ?ets_insert(mnesia_held_locks, {Oid, Prev, [{read, Tid}|Items]});
+set_lock(Tid, Oid, write, [{Oid, _Prev, Items}]) ->
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, write}),
+ ?ets_insert(mnesia_held_locks, {Oid, write, [{write, Tid}|Items]});
+set_lock(Tid, Oid, Op, undefined) ->
+ set_lock(Tid, Oid, Op, ?ets_lookup(mnesia_held_locks, Oid)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Acquire locks
@@ -261,32 +268,32 @@ try_lock(Tid, 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),
+ {yes, Default} ->
+ Reply = grant_lock(Tid, SimpleOp, Lock, Oid, Default),
reply(Pid, Reply);
- {no, Lucky} ->
+ {{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} ->
+ {{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,
+ ?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, Oid = {Tab, Key})
+grant_lock(Tid, read, Lock, Oid = {Tab, Key}, Default)
when Key /= ?ALL, Tab /= ?GLOBAL ->
case node(Tid#tid.pid) == node() of
true ->
- set_lock(Tid, Oid, Lock),
+ set_lock(Tid, Oid, Lock, Default),
{granted, lookup_in_client};
false ->
try
Val = mnesia_lib:db_get(Tab, Key), %% lookup as well
- set_lock(Tid, Oid, Lock),
+ set_lock(Tid, Oid, Lock, Default),
{granted, Val}
catch _:_Reason ->
%% Table has been deleted from this node,
@@ -296,87 +303,71 @@ grant_lock(Tid, read, Lock, Oid = {Tab, Key})
{not_granted, C}
end
end;
-grant_lock(Tid, {ix_read,IxKey,Pos}, Lock, Oid = {Tab, _}) ->
+grant_lock(Tid, {ix_read,IxKey,Pos}, Lock, Oid = {Tab, _}, Default) ->
try
Res = ix_read_res(Tab, IxKey,Pos),
- set_lock(Tid, Oid, Lock),
+ set_lock(Tid, Oid, Lock, Default),
{granted, Res, [?ALL]}
catch _:_ ->
{not_granted, {no_exists, Tab, {index, [Pos]}}}
end;
-grant_lock(Tid, read, Lock, Oid) ->
- set_lock(Tid, Oid, Lock),
+grant_lock(Tid, read, Lock, Oid, Default) ->
+ set_lock(Tid, Oid, Lock, Default),
{granted, ok};
-grant_lock(Tid, write, Lock, Oid) ->
- set_lock(Tid, Oid, Lock),
+grant_lock(Tid, write, Lock, Oid, Default) ->
+ set_lock(Tid, Oid, Lock, Default),
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
+%% 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 = {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
+ ObjLocks = ?ets_lookup(mnesia_held_locks, Oid),
+ TabLocks = ?ets_lookup(mnesia_held_locks, {Tab, ?ALL}),
+ {check_lock(Tid, Oid,
+ filter_write(ObjLocks),
+ filter_write(TabLocks),
+ yes, AlreadyQ, read),
+ ObjLocks};
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);
+ {check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, read), undefined};
-can_lock(Tid, write, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
- Oid = {Tab, Key},
+can_lock(Tid, write, Oid = {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
ObjLocks = ?ets_lookup(mnesia_held_locks, Oid),
TabLocks = ?ets_lookup(mnesia_held_locks, {Tab, ?ALL}),
- check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, write);
+ {check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, write), ObjLocks};
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_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, write), undefined}.
+
+filter_write([{_, read, _}]) -> [];
+filter_write(Res) -> Res.
%% 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 ->
- Queue = allowed_to_be_queued(WaitForTid,Tid),
- if Queue == true ->
- check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ, Type);
- Tid#tid.pid == WaitForTid#tid.pid ->
- dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
- [Oid, Lock, Tid, WaitForTid]),
- %% Test..
- {Tab, _Key} = Oid,
- HaveQ = (ets:lookup(mnesia_lock_queue, Oid) /= [])
- orelse (ets:lookup(mnesia_lock_queue,{Tab,?ALL}) /= []),
- if
- HaveQ ->
- {no, WaitForTid};
- true ->
- check_lock(Tid,Oid,Locks,TabLocks,{queue,WaitForTid},AlreadyQ,Type)
- end;
- %%{no, WaitForTid}; Safe solution
- true ->
- {no, WaitForTid}
- end
+check_lock(Tid, Oid, [{_, _, Lock} | Locks], TabLocks, _X, AlreadyQ, Type) ->
+ case can_queue(Lock, Tid, Oid, _X) of
+ {no, _} = Res ->
+ Res;
+ Res ->
+ check_lock(Tid, Oid, Locks, TabLocks, Res, AlreadyQ, Type)
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;
+ X;
-check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
- {Tab, Key} = Oid,
+check_lock(Tid, Oid = {Tab, Key}, [], [], X, AlreadyQ, Type) ->
if
Type == write ->
check_queue(Tid, Tab, X, AlreadyQ);
@@ -387,7 +378,7 @@ check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
%% If there is a queue on that object, read_lock shouldn't be granted
ObjLocks = ets:lookup(mnesia_lock_queue, Oid),
case max(ObjLocks) of
- empty ->
+ empty ->
check_queue(Tid, Tab, X, AlreadyQ);
ObjL ->
case allowed_to_be_queued(ObjL,Tid) of
@@ -403,16 +394,36 @@ check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
check_lock(Tid, Oid, [], TabLocks, X, AlreadyQ, Type) ->
check_lock(Tid, Oid, TabLocks, [], X, AlreadyQ, Type).
+can_queue([{_Op, Tid}|Locks], Tid, Oid, Res) ->
+ can_queue(Locks, Tid, Oid, Res);
+can_queue([{Op, WaitForTid}|Locks], Tid, Oid = {Tab, _}, _) ->
+ case allowed_to_be_queued(WaitForTid,Tid) of
+ true when Tid#tid.pid == WaitForTid#tid.pid ->
+ dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
+ [Oid, Op, Tid, WaitForTid]),
+ HaveQ = (ets:lookup(mnesia_lock_queue, Oid) /= [])
+ orelse (ets:lookup(mnesia_lock_queue,{Tab,?ALL}) /= []),
+ case HaveQ of
+ true -> {no, WaitForTid};
+ false -> can_queue(Locks, Tid, Oid, {queue, WaitForTid})
+ end;
+ true ->
+ can_queue(Locks, Tid, Oid, {queue, WaitForTid});
+ false ->
+ {no, WaitForTid}
+ end;
+can_queue([], _, _, Res) -> Res.
+
%% True if WaitForTid > Tid -> % Important order
allowed_to_be_queued(WaitForTid, Tid) ->
case get(pid_sort_order) of
undefined -> WaitForTid > Tid;
- r9b_plain ->
+ r9b_plain ->
cmp_tid(true, WaitForTid, Tid) =:= 1;
- standard ->
+ standard ->
cmp_tid(false, WaitForTid, Tid) =:= 1
- end.
-
+ end.
+
%% Check queue for conflicting locks
%% Assume that all queued locks belongs to other tid's
@@ -421,25 +432,25 @@ check_queue(Tid, Tab, X, AlreadyQ) ->
Greatest = max(TabLocks),
case Greatest of
empty -> X;
- Tid -> X;
- WaitForTid ->
+ Tid -> X;
+ WaitForTid ->
case allowed_to_be_queued(WaitForTid,Tid) of
true ->
{queue, WaitForTid};
- false when AlreadyQ =:= {no, bad_luck} ->
+ false when AlreadyQ =:= {no, bad_luck} ->
{no, WaitForTid}
end
end.
sort_queue(QL) ->
case get(pid_sort_order) of
- undefined ->
+ undefined ->
lists:reverse(lists:keysort(#queue.tid, QL));
- r9b_plain ->
- lists:sort(fun(#queue{tid=X},#queue{tid=Y}) ->
+ r9b_plain ->
+ lists:sort(fun(#queue{tid=X},#queue{tid=Y}) ->
cmp_tid(true, X, Y) == 1
end, QL);
- standard ->
+ standard ->
lists:sort(fun(#queue{tid=X},#queue{tid=Y}) ->
cmp_tid(false, X, Y) == 1
end, QL)
@@ -456,22 +467,22 @@ set_read_lock_on_all_keys(Tid, From, Tab, IxKey, Pos) ->
Op = {ix_read,IxKey, Pos},
Lock = read,
case can_lock(Tid, Lock, Oid, {no, bad_luck}) of
- yes ->
- Reply = grant_lock(Tid, Op, Lock, Oid),
+ {yes, Default} ->
+ Reply = grant_lock(Tid, Op, Lock, Oid, Default),
reply(From, Reply);
- {no, Lucky} ->
+ {{no, Lucky},_} ->
C = #cyclic{op = Op, lock = Lock, oid = Oid, lucky = Lucky},
?dbg("Rejected ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
reply(From, {not_granted, C});
- {queue, Lucky} ->
+ {{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,
+ ?ets_insert(mnesia_lock_queue,
+ #queue{oid = Oid, tid = Tid, op = Op,
pid = From, lucky = Lucky}),
?ets_insert(mnesia_tid_locks, {Tid, Oid, {queued, Op}})
end.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Release of locks
@@ -520,30 +531,40 @@ release_locks([]) ->
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:delete_object(mnesia_held_locks, {Oid, Op, Tid})
+release_lock({_Tid, Oid, write}) ->
+ ?ets_delete(mnesia_held_locks, Oid);
+release_lock({Tid, Oid, read}) ->
+ case ?ets_lookup(mnesia_held_locks, Oid) of
+ [{Oid, Prev, Locks0}] ->
+ case remove_tid(Locks0, Tid, []) of
+ [] -> ?ets_delete(mnesia_held_locks, Oid);
+ Locks -> ?ets_insert(mnesia_held_locks, {Oid, Prev, Locks})
+ end;
+ [] -> ok
end.
+remove_tid([{_Op, Tid}|Ls], Tid, Acc) ->
+ remove_tid(Ls,Tid, Acc);
+remove_tid([Keep|Ls], Tid, Acc) ->
+ remove_tid(Ls,Tid, [Keep|Acc]);
+remove_tid([], _, Acc) -> Acc.
+
rearrange_queue([{_Tid, {Tab, Key}, _} | Locks]) ->
if
- Key /= ?ALL->
- Queue =
- ets:lookup(mnesia_lock_queue, {Tab, ?ALL}) ++
+ Key /= ?ALL->
+ Queue =
+ ets:lookup(mnesia_lock_queue, {Tab, ?ALL}) ++
ets:lookup(mnesia_lock_queue, {Tab, Key}),
- case Queue of
- [] ->
+ case Queue of
+ [] ->
ok;
_ ->
Sorted = sort_queue(Queue),
try_waiters_obj(Sorted)
- end;
- true ->
+ end;
+ true ->
Pat = ?match_oid_lock_queue({Tab, '_'}),
- Queue = ?ets_match_object(mnesia_lock_queue, Pat),
+ Queue = ?ets_match_object(mnesia_lock_queue, Pat),
Sorted = sort_queue(Queue),
try_waiters_tab(Sorted)
end,
@@ -556,7 +577,7 @@ try_waiters_obj([W | Waiters]) ->
case try_waiter(W) of
queued ->
no;
- _ ->
+ _ ->
try_waiters_obj(Waiters)
end;
try_waiters_obj([]) ->
@@ -573,10 +594,10 @@ try_waiters_tab([W | Waiters]) ->
end;
Oid ->
case try_waiter(W) of
- queued ->
+ queued ->
Rest = key_delete_all(Oid, #queue.oid, Waiters),
try_waiters_tab(Rest);
- _ ->
+ _ ->
try_waiters_tab(Waiters)
end
end;
@@ -592,22 +613,22 @@ try_waiter({queue, Oid, Tid, Op, ReplyTo, _}) ->
try_waiter(Oid, Op, SimpleOp, Lock, ReplyTo, Tid) ->
case can_lock(Tid, Lock, Oid, {queue, bad_luck}) of
- yes ->
+ {yes, Default} ->
%% Delete from queue: Nice place for trace output
- ?ets_match_delete(mnesia_lock_queue,
+ ?ets_match_delete(mnesia_lock_queue,
#queue{oid=Oid, tid = Tid, op = Op,
pid = ReplyTo, lucky = '_'}),
- Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
+ Reply = grant_lock(Tid, SimpleOp, Lock, Oid, Default),
reply(ReplyTo,Reply),
locked;
- {queue, _Why} ->
+ {{queue, _Why}, _} ->
?dbg("Keep ~p ~p ~p ~p~n", [Tid, Oid, Lock, _Why]),
- queued; % Keep waiter in queue
- {no, Lucky} ->
+ 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,
+ ?ets_match_delete(mnesia_lock_queue,
#queue{oid=Oid, tid = Tid, op = Op,
pid = ReplyTo, lucky = '_'}),
Reply = {not_granted, C},
@@ -645,7 +666,7 @@ mnesia_down(N, Pending) ->
Pid ! {release_remote_non_pending, N, Pending}
end.
-%% Aquire a write lock, but do a read, used by
+%% Aquire a write lock, but do a read, used by
%% mnesia:wread/1
rwlock(Tid, Store, Oid) ->
@@ -657,9 +678,10 @@ rwlock(Tid, Store, Oid) ->
Lock = write,
case need_lock(Store, Tab, Key, Lock) of
yes ->
- {Ns, Majority} = w_nodes(Tab),
+ {Ns0, Majority} = w_nodes(Tab),
+ Ns = [Node|lists:delete(Node,Ns0)],
check_majority(Majority, Tab, Ns),
- Res = get_rwlocks_on_nodes(Ns, rwlock, Node, Store, Tid, Oid),
+ Res = get_rwlocks_on_nodes(Ns, make_ref(), Store, Tid, Oid),
?ets_insert(Store, {{locks, Tab, Key}, Lock}),
Res;
no ->
@@ -718,7 +740,7 @@ 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}),
+ N = val({Tab, where_to_read}),
if
node() == N ->
case need_lock(Store, Tab, Key, write) of
@@ -805,9 +827,9 @@ sticky_wlock_table(Tid, Store, Tab) ->
%% 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
+%% We also store an item {{locks, Tab, Key}, write} in the
%% local store when we have aquired the lock.
-%%
+%%
wlock(Tid, Store, Oid) ->
wlock(Tid, Store, Oid, _CheckMajority = true).
@@ -845,10 +867,10 @@ wlock_no_exist(Tid, Store, Tab, Ns) ->
need_lock(Store, Tab, Key, LockPattern) ->
TabL = ?ets_match_object(Store, {{locks, Tab, ?ALL}, LockPattern}),
- if
+ if
TabL == [] ->
KeyL = ?ets_match_object(Store, {{locks, Tab, Key}, LockPattern}),
- if
+ if
KeyL == [] ->
yes;
true ->
@@ -865,7 +887,7 @@ del_debug() ->
erase(mnesia_wlock_nodes).
%% We first send lock request to the local node if it is part of the lockers
-%% then the first sorted node then to the rest of the lockmanagers on all
+%% then the first sorted node then to the rest of the lockmanagers on all
%% nodes holding a copy of the table
get_wlocks_on_nodes([Node | Tail], Orig, Store, Request, Oid) ->
@@ -875,51 +897,31 @@ get_wlocks_on_nodes([Node | Tail], Orig, Store, Request, Oid) ->
case node() of
Node -> %% Local done try one more
get_wlocks_on_nodes(Tail, Orig, Store, Request, Oid);
- _ -> %% The first succeded cont with the rest
+ _ -> %% The first succeded cont with the rest
get_wlocks_on_nodes(Tail, Store, Request),
receive_wlocks(Tail, Orig, Store, Oid)
end;
-get_wlocks_on_nodes([], Orig, _Store, _Request, _Oid) ->
+get_wlocks_on_nodes([], Orig, _Store, _Request, _Oid) ->
Orig.
get_wlocks_on_nodes([Node | Tail], Store, Request) ->
{?MODULE, Node} ! Request,
?ets_insert(Store,{nodes, Node}),
get_wlocks_on_nodes(Tail, Store, Request);
-get_wlocks_on_nodes([], _, _) ->
+get_wlocks_on_nodes([], _, _) ->
ok.
-get_rwlocks_on_nodes([ReadNode|Tail], _Res, ReadNode, Store, Tid, Oid) ->
+get_rwlocks_on_nodes([ReadNode|Tail], Ref, Store, Tid, Oid) ->
Op = {self(), {read_write, Tid, Oid}},
{?MODULE, ReadNode} ! Op,
?ets_insert(Store, {nodes, ReadNode}),
- Res = receive_wlocks([ReadNode], undefined, Store, Oid),
- case node() of
- ReadNode ->
- get_rwlocks_on_nodes(Tail, Res, ReadNode, Store, Tid, Oid);
- _ ->
- get_wlocks_on_nodes(Tail, Store, {self(), {write, Tid, Oid}}),
- receive_wlocks(Tail, Res, Store, Oid)
+ case receive_wlocks([ReadNode], Ref, Store, Oid) of
+ Ref ->
+ get_rwlocks_on_nodes(Tail, Ref, Store, Tid, Oid);
+ Res ->
+ get_wlocks_on_nodes(Tail, Res, Store, {self(), {write, Tid, Oid}}, Oid)
end;
-get_rwlocks_on_nodes([Node | Tail], Res, ReadNode, Store, Tid, Oid) ->
- Op = {self(), {write, Tid, Oid}},
- {?MODULE, Node} ! Op,
- ?ets_insert(Store, {nodes, Node}),
- receive_wlocks([Node], undefined, Store, Oid),
- if node() == Node ->
- get_rwlocks_on_nodes(Tail, Res, ReadNode, Store, Tid, Oid);
- Res == rwlock -> %% Hmm
- Rest = lists:delete(ReadNode, Tail),
- Op2 = {self(), {read_write, Tid, Oid}},
- {?MODULE, ReadNode} ! Op2,
- ?ets_insert(Store, {nodes, ReadNode}),
- get_wlocks_on_nodes(Rest, Store, {self(), {write, Tid, Oid}}),
- receive_wlocks([ReadNode|Rest], undefined, Store, Oid);
- true ->
- get_wlocks_on_nodes(Tail, Store, {self(), {write, Tid, Oid}}),
- receive_wlocks(Tail, Res, Store, Oid)
- end;
-get_rwlocks_on_nodes([],Res,_,_,_,_) ->
+get_rwlocks_on_nodes([],Res,_,_,_) ->
Res.
receive_wlocks([], Res, _Store, _Oid) ->
@@ -944,8 +946,8 @@ receive_wlocks(Nodes = [This|Ns], Res, Store, Oid) ->
Tail = lists:delete(Node,Nodes),
Nonstuck = lists:delete(Sticky,Tail),
[?ets_insert(Store, {nodes, NSNode}) || NSNode <- Nonstuck],
- case lists:member(Sticky,Tail) of
- true ->
+ case lists:member(Sticky,Tail) of
+ true ->
sticky_flush(Nonstuck,Store),
receive_wlocks([Sticky], Res, Store, Oid);
false ->
@@ -957,7 +959,7 @@ receive_wlocks(Nodes = [This|Ns], Res, Store, Oid) ->
flush_remaining(Ns, This, Reason1)
end.
-sticky_flush([], _) ->
+sticky_flush([], _) ->
del_debug(),
ok;
sticky_flush(Ns=[Node | Tail], Store) ->
@@ -991,7 +993,7 @@ opt_lookup_in_client(lookup_in_client, Oid, Lock) ->
%% Table has been deleted from this node,
%% restart the transaction.
#cyclic{op = read, lock = Lock, oid = Oid, lucky = nowhere};
- Val ->
+ Val ->
Val
end;
opt_lookup_in_client(Val, _Oid, _Lock) ->
@@ -1000,8 +1002,8 @@ opt_lookup_in_client(Val, _Oid, _Lock) ->
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
+
+%% 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.
@@ -1059,9 +1061,9 @@ rlock_get_reply(Node, Store, Oid, {granted, V}) ->
?ets_insert(Store, {{locks, Tab, Key}, read}),
?ets_insert(Store, {nodes, Node}),
case opt_lookup_in_client(V, Oid, read) of
- C = #cyclic{} ->
+ C = #cyclic{} ->
mnesia:abort(C);
- Val ->
+ Val ->
Val
end;
rlock_get_reply(Node, Store, Oid, granted) ->
@@ -1079,7 +1081,7 @@ rlock_get_reply(Node, Store, Tab, {granted, V, RealKeys}) ->
rlock_get_reply(_Node, _Store, _Oid, {not_granted, Reason}) ->
exit({aborted, Reason});
-rlock_get_reply(_Node, Store, Oid, {switch, N2, Req}) ->
+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)).
@@ -1095,7 +1097,7 @@ ixrlock(Tid, Store, Tab, IxKey, Pos) ->
%%% Old code
%% R = l_request(Node, {ix_read, Tid, Tab, IxKey, Pos}, Store),
%% rlock_get_reply(Node, Store, Tab, R)
-
+
case need_lock(Store, Tab, ?ALL, read) of
no when Node =:= node() ->
ix_read_res(Tab,IxKey,Pos);
@@ -1135,11 +1137,23 @@ rec_requests([], _Oid, _Store) ->
get_held_locks() ->
?MODULE ! {get_table, self(), mnesia_held_locks},
- receive {mnesia_held_locks, Locks} -> Locks end.
+ Locks = receive {mnesia_held_locks, Ls} -> Ls after 5000 -> [] end,
+ rewrite_locks(Locks, []).
+
+rewrite_locks([{Oid, _, Ls}|Locks], Acc0) ->
+ Acc = rewrite_locks(Ls, Oid, Acc0),
+ rewrite_locks(Locks, Acc);
+rewrite_locks([], Acc) ->
+ lists:reverse(Acc).
+
+rewrite_locks([{Op, Tid}|Ls], Oid, Acc) ->
+ rewrite_locks(Ls, Oid, [{Oid, Op, Tid}|Acc]);
+rewrite_locks([], _, Acc) ->
+ Acc.
get_lock_queue() ->
?MODULE ! {get_table, self(), mnesia_lock_queue},
- Q = receive {mnesia_lock_queue, Locks} -> Locks end,
+ Q = receive {mnesia_lock_queue, Locks} -> Locks after 5000 -> [] end,
[{Oid, Op, Pid, Tid, WFT} || {queue, Oid, Tid, Op, Pid, WFT} <- Q].
do_stop() ->
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 94153473cb..18303869ed 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -180,8 +180,8 @@
view/1,
write_trans_log_header/0
]).
-
-
+
+
-compile({no_auto_import,[error/2]}).
-include("mnesia.hrl").
@@ -210,7 +210,7 @@ decision_tab_version() -> "1.0".
dcl_version() -> "1.0".
dcd_version() -> "1.0".
-
+
append(Log, Bin) when is_binary(Bin) ->
disk_log:balog(Log, Bin);
append(Log, Term) ->
@@ -218,9 +218,9 @@ append(Log, Term) ->
%% Synced append
sappend(Log, Bin) when is_binary(Bin) ->
- ok = disk_log:blog(Log, Bin);
+ ok = disk_log:blog(Log, Bin);
sappend(Log, Term) ->
- ok = disk_log:log(Log, Term).
+ ok = disk_log:log(Log, Term).
%% Write commit records to the latest_log
log(C) when C#commit.disc_copies == [],
@@ -283,7 +283,7 @@ 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".
@@ -297,10 +297,10 @@ init() ->
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 ->
@@ -346,20 +346,20 @@ open_log(Name, Header, Fname, Exists, Repair, Mode) ->
write_header(Log, Header),
Log;
{repaired, Log, _Recover, BadBytes} ->
- mnesia_lib:important("Data may be missing, log ~p repaired: Lost ~p bytes~n",
+ 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",
+ mnesia_lib:important("Data may be missing, Corrupt logfile deleted: ~p, ~p ~n",
[Fname, Reason]),
- %% Create a new
+ %% 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) ->
+write_header(Log, Header) ->
append(Log, Header).
write_trans_log_header() ->
@@ -376,12 +376,12 @@ stop() ->
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
+ case disk_log:sync(Log) of
ok -> ok;
- {error, {read_only_mode, Log}} ->
+ {error, {read_only_mode, Log}} ->
ok;
- {error, Reason} ->
- mnesia_lib:important("Failed syncing ~p to_disk reason ~p ~n",
+ {error, Reason} ->
+ mnesia_lib:important("Failed syncing ~p to_disk reason ~p ~n",
[Log, Reason])
end,
mnesia_monitor:close_log(Log).
@@ -392,7 +392,7 @@ unsafe_close_log(Log) ->
purge_some_logs() ->
- mnesia_monitor:unsafe_close_log(latest_log),
+ mnesia_monitor:unsafe_close_log(latest_log),
file:delete(latest_log_file()),
file:delete(decision_tab_file()).
@@ -466,10 +466,10 @@ chunk_log(Log, Cont) ->
[Log, Reason]);
{C2, Chunk, _BadBytes} ->
%% Read_only case, should we warn about the bad log file?
- %% BUGBUG Should we crash if Repair == false ??
+ %% 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};
+ {C2, Chunk};
Other ->
Other
end.
@@ -492,7 +492,7 @@ 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).
@@ -586,11 +586,11 @@ view_file(C, 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,
+ 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,
+ lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
Terms),
view_file(C2, Log)
end.
@@ -655,7 +655,7 @@ check_backup_args([Arg | Tail], B) ->
check_backup_args([], B) ->
{ok, B}.
-check_backup_arg_type(Arg, B) ->
+check_backup_arg_type(Arg, B) ->
case Arg of
{scope, global} ->
B#backup_args{scope = global};
@@ -714,7 +714,7 @@ select_tables(AllTabs, B) ->
safe_write(B, []) ->
B;
-safe_write(B, Recs) ->
+safe_write(B, Recs) ->
safe_apply(B, write, [B#backup_args.opaque, Recs]).
backup_schema(B, Tabs) ->
@@ -754,7 +754,7 @@ abort_write(B, What, Args, Reason) ->
[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
@@ -768,7 +768,7 @@ backup_tab(Tab, B) ->
{error, Reason} ->
abort_write(B, {?MODULE, backup_tab}, [Tab, B], {error, Reason})
end.
-
+
tab_copier(Pid, B, Tab) when is_record(B, backup_args) ->
%% Intentional crash at exit
Name = B#backup_args.name,
@@ -829,7 +829,7 @@ handle_last(Pid, _Acc) ->
exit(normal).
iterate(B, Name, Tab, Pid, Source, Age, Pass, Acc) ->
- Fun =
+ Fun =
if
Pid == self() ->
RecName = val({Tab, record_name}),
@@ -874,7 +874,7 @@ tab_receiver(Pid, B, Tab, RecName, Slot) ->
Recs2 = rec_filter(B, Tab, RecName, Recs),
B2 = safe_write(B, Recs2),
tab_receiver(Pid, B2, Tab, RecName, Next);
-
+
{Pid, {last, {ok,_}}} ->
B;
@@ -885,7 +885,7 @@ tab_receiver(Pid, B, Tab, RecName, Slot) ->
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}},
+ R = {error, {"Tab receiver got unexpected msg", Msg}},
abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], R)
end.
@@ -910,9 +910,9 @@ ets2dcd(Tab, Ftype) ->
case Ftype of
dcd -> mnesia_lib:tab2dcd(Tab);
dmp -> mnesia_lib:tab2dmp(Tab)
- end,
+ end,
TmpF = mnesia_lib:tab2tmp(Tab),
- file:delete(TmpF),
+ 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),
@@ -926,8 +926,8 @@ ets2dcd(Tab, Ftype) ->
ets2dcd('$end_of_table', _Tab, _Log) ->
ok;
-ets2dcd({Recs, Cont}, Tab, Log) ->
- ok = disk_log:alog_terms(Log, Recs),
+ets2dcd({Recs, Cont}, Tab, Log) ->
+ ok = disk_log:log_terms(Log, Recs),
ets2dcd(mnesia_lib:db_chunk(ram_copies, Cont), Tab, Log).
dcd2ets(Tab) ->
@@ -937,12 +937,12 @@ dcd2ets(Tab, Rep) ->
Dcd = mnesia_lib:tab2dcd(Tab),
case mnesia_lib:exists(Dcd) of
true ->
- Log = open_log({Tab, dcd2ets}, dcd_log_header(), Dcd,
+ 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);
+ 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}),
@@ -956,13 +956,13 @@ dcd2ets(Tab, Rep) ->
end
end.
-insert_dcdchunk({Cont, [LogH | Rest]}, Log, Tab)
- when is_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, [LogH | Rest]}, Log, Tab)
+ when is_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) ->
+insert_dcdchunk({Cont, Recs}, Log, Tab) ->
true = ets:insert(Tab, Recs),
insert_dcdchunk(chunk_log(Log, Cont), Log, Tab);
insert_dcdchunk(eof, _Log, _Tab) ->
@@ -971,13 +971,13 @@ insert_dcdchunk(eof, _Log, _Tab) ->
load_dcl(Tab, Rep) ->
FName = mnesia_lib:tab2dcl(Tab),
case mnesia_lib:exists(FName) of
- true ->
+ true ->
Name = {load_dcl,Tab},
- open_log(Name,
- dcl_log_header(),
- FName,
+ open_log(Name,
+ dcl_log_header(),
+ FName,
true,
- Rep,
+ Rep,
read_only),
FirstChunk = chunk_log(Name, start),
N = insert_logchunk(FirstChunk, Name, 0),
@@ -1015,10 +1015,10 @@ add_recs([{{Tab, Key}, Val, update_counter} | Rest], N) ->
true = ets:insert(Tab, Zero)
end,
add_recs(Rest, N+1);
-add_recs([LogH|Rest], N)
- when is_record(LogH, log_header),
- LogH#log_header.log_kind == dcl_log,
- LogH#log_header.log_version >= "1.0" ->
+add_recs([LogH|Rest], N)
+ when is_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) ->
Size = ets:info(Tab, size),
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index e110ad3241..c08bbc879f 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -80,9 +80,9 @@
going_down = [], tm_started = false, early_connects = [],
connecting, mq = []}).
--define(current_protocol_version, {8,0}).
+-define(current_protocol_version, {8,1}).
--define(previous_protocol_version, {7,6}).
+-define(previous_protocol_version, {8,0}).
start() ->
gen_server:start_link({local, ?MODULE}, ?MODULE,
@@ -188,7 +188,7 @@ protocol_version() ->
%% A sorted list of acceptable protocols the
%% preferred protocols are first in the list
acceptable_protocol_versions() ->
- [protocol_version(), ?previous_protocol_version].
+ [protocol_version(), ?previous_protocol_version, {7,6}].
needs_protocol_conversion(Node) ->
case {?catch_val({protocol, Node}), protocol_version()} of
@@ -417,6 +417,8 @@ handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
case hd(Protocols) of
?previous_protocol_version ->
accept_protocol(Mon, MyVersion, ?previous_protocol_version, From, State);
+ {7,6} ->
+ accept_protocol(Mon, MyVersion, {7,6}, From, State);
_ ->
verbose("Connection with ~p rejected. "
"version = ~p, protocols = ~p, "
@@ -536,7 +538,11 @@ handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
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),
+ %% This may hang supervisor if a shutdown happens at the same time as an fatal
+ %% is in progress
+ %% exit(State#state.supervisor, shutdown),
+ %% It is better to kill an innocent process
+ catch exit(whereis(mnesia_locker), kill),
{noreply, State};
handle_info(Msg = {'EXIT',Pid,_}, State) ->
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index 05be474aea..6e43052fb0 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -39,9 +39,10 @@
change_table_load_order/2,
change_table_majority/2,
change_table_frag/2,
- clear_table/1,
+%% clear_table/1, %% removed since it is not a schema op anymore
create_table/1,
cs2list/1,
+ vsn_cs2list/1,
del_snmp/1,
del_table_copy/2,
del_table_index/2,
@@ -65,6 +66,7 @@
merge_schema/0,
merge_schema/1,
move_table/3,
+ normalize_cs/2,
opt_create_dir/2,
prepare_commit/3,
purge_dir/2,
@@ -186,6 +188,7 @@ do_set_schema(Tab, Cs) ->
[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, storage_properties}, Cs#cstruct.storage_properties),
set({Tab, attributes}, Cs#cstruct.attributes),
Arity = length(Cs#cstruct.attributes) + 1,
set({Tab, arity}, Arity),
@@ -626,11 +629,30 @@ do_insert_schema_ops(Store, [Head | Tail]) ->
do_insert_schema_ops(_Store, []) ->
ok.
+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}).
+
+vsn_cs2list(Cs) ->
+ cs2list(need_old_cstructs(), Cs).
+
cs2list(Cs) when is_record(Cs, cstruct) ->
Tags = record_info(fields, cstruct),
rec2list(Tags, Tags, 2, Cs);
cs2list(CreateList) when is_list(CreateList) ->
CreateList;
+%% 4.6
+cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 19 ->
+ 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,storage_properties,
+ cookie,version],
+ rec2list(Tags, Tags, 2, Cs);
%% 4.4.19
cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 18 ->
Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
@@ -648,7 +670,7 @@ cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 17 ->
cs2list(false, Cs) ->
cs2list(Cs);
-cs2list(ver4_4_18, Cs) ->
+cs2list(ver4_4_18, Cs) -> %% Or earlier
Orig = record_info(fields, cstruct),
Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
load_order,access_mode,index,snmp,local_content,
@@ -661,8 +683,17 @@ cs2list(ver4_4_19, Cs) ->
load_order,access_mode,majority,index,snmp,local_content,
record_name,attributes,user_properties,frag_properties,
cookie,version],
+ rec2list(Tags, Orig, 2, Cs);
+cs2list(ver4_6, 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,storage_properties,
+ cookie,version],
rec2list(Tags, Orig, 2, Cs).
+
rec2list([Tag | Tags], [Tag | Orig], Pos, Rec) ->
Val = element(Pos, Rec),
[{Tag, Val} | rec2list(Tags, Orig, Pos + 1, Rec)];
@@ -671,13 +702,19 @@ 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}).
+normalize_cs(Cstructs, Node) ->
+ %% backward-compatibility hack; normalize before returning
+ case need_old_cstructs([Node]) of
+ false ->
+ Cstructs;
+ Version ->
+ %% some other format
+ [convert_cs(Version, Cs) || Cs <- Cstructs]
+ end.
+
+convert_cs(Version, Cs) ->
+ Fields = [Value || {_, Value} <- cs2list(Version, Cs)],
+ list_to_tuple([cstruct|Fields]).
list2cs(List) when is_list(List) ->
Name = pick(unknown, name, List, must),
@@ -709,6 +746,29 @@ 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}}),
+
+ BEProps = pick(Name, storage_properties, List, []),
+ verify({alt, [nil, list]}, mnesia_lib:etype(Ix),
+ {badarg, Name, {storage_properties, BEProps}}),
+ CheckProp = fun(Opt, Opts) when is_atom(Opt) ->
+ lists:member(Opt, Opts)
+ andalso mnesia:abort({badarg, Name, Opt});
+ (Tuple, Opts) when is_tuple(Tuple) ->
+ lists:member(element(1,Tuple), Opts)
+ andalso mnesia:abort({badarg, Name, Tuple});
+ (What,_) ->
+ mnesia:abort({badarg, Name, What})
+ end,
+ BadEtsOpts = [set, ordered_set, bag, duplicate_bag,
+ public, private, protected,
+ keypos, named_table],
+ EtsOpts = proplists:get_value(ets, BEProps, []),
+ is_list(EtsOpts) orelse mnesia:abort({badarg, Name, {ets, EtsOpts}}),
+ [CheckProp(Prop, BadEtsOpts) || Prop <- EtsOpts],
+ BadDetsOpts = [type, keypos, repair, access, file],
+ DetsOpts = proplists:get_value(dets, BEProps, []),
+ is_list(DetsOpts) orelse mnesia:abort({badarg, Name, {dets, DetsOpts}}),
+ [CheckProp(Prop, BadDetsOpts) || Prop <- DetsOpts],
#cstruct{name = Name,
ram_copies = Rc,
disc_copies = Dc,
@@ -724,6 +784,7 @@ list2cs(List) when is_list(List) ->
attributes = Attrs,
user_properties = lists:sort(UserProps),
frag_properties = lists:sort(Frag),
+ storage_properties = lists:sort(BEProps),
cookie = Cookie,
version = Version}.
@@ -1048,7 +1109,7 @@ unsafe_make_create_table(Cs) ->
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)}].
+ [{op, create_table, vsn_cs2list(Cs)}].
check_if_exists(Tab) ->
TidTs = get_tid_ts_and_lock(schema, write),
@@ -1133,7 +1194,7 @@ make_delete_table2(Tab) ->
Cs = val({Tab, cstruct}),
ensure_active(Cs),
ensure_writable(Tab),
- {op, delete_table, cs2list(Cs)}.
+ {op, delete_table, vsn_cs2list(Cs)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Change fragmentation of a table
@@ -1152,10 +1213,6 @@ do_change_table_frag(Tab, _Change) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Clear a table
-%% No need for a schema transaction
-clear_table(Tab) ->
- schema_transaction(fun() -> do_clear_table(Tab) end).
-
do_clear_table(schema) ->
mnesia:abort({bad_type, schema});
do_clear_table(Tab) ->
@@ -1166,7 +1223,7 @@ do_clear_table(Tab) ->
make_clear_table(Tab) ->
Cs = val({Tab, cstruct}),
ensure_writable(Tab),
- [{op, clear_table, cs2list(Cs)}].
+ [{op, clear_table, vsn_cs2list(Cs)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1206,7 +1263,7 @@ make_add_table_copy(Tab, Node, Storage) ->
IsRunning == false ->
mnesia:abort({not_active, schema, Node})
end,
- [{op, add_table_copy, Storage, Node, cs2list(Cs2)}].
+ [{op, add_table_copy, Storage, Node, vsn_cs2list(Cs2)}].
del_table_copy(Tab, Node) ->
schema_transaction(fun() -> do_del_table_copy(Tab, Node) end).
@@ -1235,11 +1292,11 @@ make_del_table_copy(Tab, Node) ->
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];
+ [{op, del_table_copy, ram_copies, Node, vsn_cs2list(Cs2)} | Ops];
_ ->
ensure_active(Cs),
verify_cstruct(Cs2),
- [{op, del_table_copy, Storage, Node, cs2list(Cs2)}]
+ [{op, del_table_copy, Storage, Node, vsn_cs2list(Cs2)}]
end.
remove_node_from_tabs([], _Node) ->
@@ -1253,7 +1310,7 @@ remove_node_from_tabs([Tab|Rest], Node) ->
unknown ->
case IsFragModified of
true ->
- [{op, change_table_frag, {del_node, Node}, cs2list(Cs)} |
+ [{op, change_table_frag, {del_node, Node}, vsn_cs2list(Cs)} |
remove_node_from_tabs(Rest, Node)];
false ->
remove_node_from_tabs(Rest, Node)
@@ -1262,11 +1319,11 @@ remove_node_from_tabs([Tab|Rest], Node) ->
Cs2 = new_cs(Cs, Node, Storage, del),
case mnesia_lib:cs_to_nodes(Cs2) of
[] ->
- [{op, delete_table, cs2list(Cs)} |
+ [{op, delete_table, vsn_cs2list(Cs)} |
remove_node_from_tabs(Rest, Node)];
_Ns ->
verify_cstruct(Cs2),
- [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)}|
+ [{op, del_table_copy, ram_copies, Node, vsn_cs2list(Cs2)}|
remove_node_from_tabs(Rest, Node)]
end
end.
@@ -1318,9 +1375,9 @@ make_move_table(Tab, FromNode, 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, add_table_copy, Storage, ToNode, vsn_cs2list(Cs2)},
{op, sync_trans},
- {op, del_table_copy, Storage, FromNode, cs2list(Cs3)}].
+ {op, del_table_copy, Storage, FromNode, vsn_cs2list(Cs3)}].
%% end of functions to add and delete nodes to tables
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1357,7 +1414,7 @@ make_change_table_copy_type(Tab, Node, ToS) ->
Cs3 = new_cs(Cs2, Node, ToS, add),
verify_cstruct(Cs3),
- [{op, change_table_copy_type, Node, FromS, ToS, cs2list(Cs3)}].
+ [{op, change_table_copy_type, Node, FromS, ToS, vsn_cs2list(Cs3)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% change index functions ....
@@ -1383,7 +1440,7 @@ make_add_table_index(Tab, Pos) ->
Ix2 = lists:sort([Pos | Ix]),
Cs2 = Cs#cstruct{index = Ix2},
verify_cstruct(Cs2),
- [{op, add_index, Pos, cs2list(Cs2)}].
+ [{op, add_index, Pos, vsn_cs2list(Cs2)}].
del_table_index(Tab, Pos) ->
schema_transaction(fun() -> do_del_table_index(Tab, Pos) end).
@@ -1404,7 +1461,7 @@ make_del_table_index(Tab, Pos) ->
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)}].
+ [{op, del_index, Pos, vsn_cs2list(Cs2)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1427,7 +1484,7 @@ make_add_snmp(Tab, Ustruct) ->
verify(true, mnesia_snmp_hook:check_ustruct(Ustruct), Error),
Cs2 = Cs#cstruct{snmp = Ustruct},
verify_cstruct(Cs2),
- [{op, add_snmp, Ustruct, cs2list(Cs2)}].
+ [{op, add_snmp, Ustruct, vsn_cs2list(Cs2)}].
del_snmp(Tab) ->
schema_transaction(fun() -> do_del_snmp(Tab) end).
@@ -1445,7 +1502,7 @@ make_del_snmp(Tab) ->
ensure_active(Cs),
Cs2 = Cs#cstruct{snmp = []},
verify_cstruct(Cs2),
- [{op, del_snmp, cs2list(Cs2)}].
+ [{op, del_snmp, vsn_cs2list(Cs2)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
@@ -1477,26 +1534,26 @@ make_transform(Tab, Fun, NewAttrs, NewRecName) ->
[] ->
Cs2 = Cs#cstruct{attributes = NewAttrs, record_name = NewRecName},
verify_cstruct(Cs2),
- [{op, transform, Fun, cs2list(Cs2)}];
+ [{op, transform, Fun, vsn_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 = {op, del_index, Pos, vsn_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 = {op, add_index, Pos, vsn_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])
+ lists:flatten([DelOps, {op, transform, Fun, vsn_cs2list(Cs2)}, AddOps])
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1520,7 +1577,7 @@ make_change_table_access_mode(Tab, 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}].
+ [{op, change_table_access_mode, vsn_cs2list(Cs2), OldMode, Mode}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1541,7 +1598,7 @@ make_change_table_load_order(Tab, LoadOrder) ->
OldLoadOrder = Cs#cstruct.load_order,
Cs2 = Cs#cstruct{load_order = LoadOrder},
verify_cstruct(Cs2),
- [{op, change_table_load_order, cs2list(Cs2), OldLoadOrder, LoadOrder}].
+ [{op, change_table_load_order, vsn_cs2list(Cs2), OldLoadOrder, LoadOrder}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1571,14 +1628,14 @@ make_change_table_majority(Tab, Majority) ->
ensure_active(CsT),
CsT2 = CsT#cstruct{majority = Majority},
verify_cstruct(CsT2),
- {op, change_table_majority, cs2list(CsT2),
+ {op, change_table_majority, vsn_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].
+ [{op, change_table_majority, vsn_cs2list(Cs2), OldMajority, Majority} | FragOps].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1619,7 +1676,7 @@ make_write_table_properties(Tab, [Prop | Props], Cs) ->
MergedProps = lists:merge(DelProps, [Prop]),
Cs2 = Cs#cstruct{user_properties = MergedProps},
verify_cstruct(Cs2),
- [{op, write_property, cs2list(Cs2), Prop} |
+ [{op, write_property, vsn_cs2list(Cs2), Prop} |
make_write_table_properties(Tab, Props, Cs2)];
make_write_table_properties(_Tab, [], _Cs) ->
[].
@@ -1740,7 +1797,7 @@ make_delete_table_properties(Tab, [PropKey | PropKeys], Cs) ->
Props = lists:keydelete(PropKey, 1, OldProps),
Cs2 = Cs#cstruct{user_properties = Props},
verify_cstruct(Cs2),
- [{op, delete_property, cs2list(Cs2), PropKey} |
+ [{op, delete_property, vsn_cs2list(Cs2), PropKey} |
make_delete_table_properties(Tab, PropKeys, Cs2)];
make_delete_table_properties(_Tab, [], _Cs) ->
[].
@@ -1866,18 +1923,18 @@ prepare_op(Tid, {op, create_table, TabDef}, _WaitFor) ->
mnesia:abort(UseDirReason);
ram_copies ->
mnesia_lib:set({Tab, create_table},true),
- create_ram_table(Tab, Cs#cstruct.type),
+ create_ram_table(Tab, Cs),
insert_cstruct(Tid, Cs, false),
{true, optional};
disc_copies ->
mnesia_lib:set({Tab, create_table},true),
- create_ram_table(Tab, Cs#cstruct.type),
+ create_ram_table(Tab, Cs),
create_disc_table(Tab),
insert_cstruct(Tid, Cs, false),
{true, optional};
disc_only_copies ->
mnesia_lib:set({Tab, create_table},true),
- create_disc_only_table(Tab,Cs#cstruct.type),
+ create_disc_only_table(Tab,Cs),
insert_cstruct(Tid, Cs, false),
{true, optional};
unknown -> %% No replica on this node
@@ -2029,7 +2086,7 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
mnesia_dumper:raw_named_dump_table(Tab, dmp);
FromS == disc_only_copies ->
Type = Cs#cstruct.type,
- create_ram_table(Tab, Type),
+ create_ram_table(Tab, Cs),
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
@@ -2117,8 +2174,9 @@ prepare_op(_Tid, {op, merge_schema, TabDef}, _WaitFor) ->
prepare_op(_Tid, _Op, _WaitFor) ->
{true, optional}.
-create_ram_table(Tab, Type) ->
- Args = [{keypos, 2}, public, named_table, Type],
+create_ram_table(Tab, #cstruct{type=Type, storage_properties=Props}) ->
+ EtsOpts = proplists:get_value(ets, Props, []),
+ Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case mnesia_monitor:unsafe_mktab(Tab, Args) of
Tab ->
ok;
@@ -2126,6 +2184,7 @@ create_ram_table(Tab, Type) ->
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),
@@ -2139,13 +2198,15 @@ create_disc_table(Tab) ->
Err = "Failed to create disc table",
mnesia:abort({system_limit, Tab, {Err,Reason}})
end.
-create_disc_only_table(Tab,Type) ->
+create_disc_only_table(Tab, #cstruct{type=Type, storage_properties=Props}) ->
File = mnesia_lib:tab2dat(Tab),
file:delete(File),
+ DetsOpts = proplists:get_value(dets, Props, []),
Args = [{file, mnesia_lib:tab2dat(Tab)},
{type, mnesia_lib:disk_type(Tab, Type)},
{keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
+ {repair, mnesia_monitor:get_env(auto_repair)}
+ | DetsOpts],
case mnesia_monitor:unsafe_open_dets(Tab, Args) of
{ok, _} ->
ok;
@@ -2166,12 +2227,17 @@ receive_sync(Nodes, Pids) ->
{abort, Else}
end.
-lock_del_table(Tab, Node, Cs, Father) ->
+lock_del_table(Tab, NewNode, Cs0, Father) ->
Ns = val({schema, active_replicas}),
process_flag(trap_exit,true),
Lock = fun() ->
mnesia:write_lock_table(Tab),
- {Res, []} = rpc:multicall(Ns, ?MODULE, set_where_to_read, [Tab, Node, Cs]),
+ %% Sigh using cs record
+ Set = fun(Node) ->
+ [Cs] = normalize_cs([Cs0], Node),
+ rpc:call(Node, ?MODULE, set_where_to_read, [Tab, NewNode, Cs])
+ end,
+ Res = [Set(Node) || Node <- Ns],
Filter = fun(ok) ->
false;
({badrpc, {'EXIT', {undef, _}}}) ->
@@ -2353,11 +2419,12 @@ undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
when Node == node() ->
+ WriteLocker = get(mnesia_lock),
+ WriteLocker =/= undefined andalso (WriteLocker ! die),
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),
@@ -2667,17 +2734,17 @@ restore_schema([{schema, Tab, List} | Schema], R) ->
R2 = R#r{tables = [{Tab, undefined, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
recreate_tables ->
- case ?catch_val({Tab, cstruct}) of
- {'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)),
- RunningNodes),
- mnesia_locker:wlock_no_exist(Tid, Ts#tidstore.store, Tab, Nodes),
- TidTs;
- _ ->
- TidTs = get_tid_ts_and_lock(Tab, write)
- end,
+ TidTs = case ?catch_val({Tab, cstruct}) of
+ {'EXIT', _} ->
+ TTs = {_Mod, Tid, Ts} = get(mnesia_activity_state),
+ RunningNodes = val({current, db_nodes}),
+ Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(list2cs(List)),
+ RunningNodes),
+ mnesia_locker:wlock_no_exist(Tid, Ts#tidstore.store, Tab, Nodes),
+ TTs;
+ _ ->
+ get_tid_ts_and_lock(Tab, write)
+ end,
NC = {cookie, ?unique_cookie},
List2 = lists:keyreplace(cookie, 1, List, NC),
Where = where_to_commit(Tab, List2),
@@ -2818,17 +2885,20 @@ do_merge_schema(LockTabs0) ->
end.
fetch_cstructs(Node) ->
- case mnesia_monitor:needs_protocol_conversion(Node) of
- true ->
+ case need_old_cstructs([Node]) of
+ false ->
+ rpc:call(Node, mnesia_controller, get_remote_cstructs, []);
+ _Ver ->
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
end.
+need_old_cstructs() ->
+ need_old_cstructs(val({schema, where_to_write})).
+
need_old_cstructs(Nodes) ->
Filter = fun(Node) -> not mnesia_monitor:needs_protocol_conversion(Node) end,
case lists:dropwhile(Filter, Nodes) of
@@ -2844,7 +2914,9 @@ need_old_cstructs(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
+ ver4_4_19; % With majority
+ Cs when element(1, Cs) == cstruct, tuple_size(Cs) == 19 ->
+ ver4_6 % With storage_properties
end
end.
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index f62f7cb7c8..0af7f55c06 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -36,7 +36,7 @@
prepare_checkpoint/2,
prepare_checkpoint/1, % Internal
prepare_snmp/3,
- do_snmp/2,
+ do_snmp/2,
put_activity_id/1,
put_activity_id/2,
block_tab/1,
@@ -68,7 +68,7 @@
majority = []
}).
--record(participant, {tid, pid, commit, disc_nodes = [],
+-record(participant, {tid, pid, commit, disc_nodes = [],
ram_nodes = [], protocol = sym_trans}).
start() ->
@@ -77,12 +77,12 @@ start() ->
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(),
@@ -101,11 +101,11 @@ init(Parent) ->
false ->
ignore
end,
-
+
mnesia_schema:purge_tmp_files(),
mnesia_recover:start_garb(),
-
- ?eval_debug_fun({?MODULE, init}, [{nodes, AllOthers}]),
+
+ ?eval_debug_fun({?MODULE, init}, [{nodes, AllOthers}]),
case val(debug) of
Debug when Debug /= debug, Debug /= trace ->
@@ -118,8 +118,8 @@ init(Parent) ->
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.
reply({From,Ref}, R) ->
@@ -136,7 +136,7 @@ req(R) ->
undefined ->
{error, {node_not_running, node()}};
Pid ->
- Ref = make_ref(),
+ Ref = make_ref(),
Pid ! {{self(), Ref}, R},
rec(Pid, Ref)
end.
@@ -161,7 +161,7 @@ rec(Pid, Ref) ->
Reply;
{'EXIT', Pid, _} ->
{error, {node_not_running, node()}}
- end.
+ end.
tmlink({From, Ref}) when is_reference(Ref) ->
link(From);
@@ -209,7 +209,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
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 ->
@@ -220,7 +220,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
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
@@ -236,16 +236,16 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
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},
+ ?eval_debug_fun({?MODULE, doit_ask_commit},
[{tid, Tid}, {prot, Protocol}]),
mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
- Pid =
+ 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);
+ spawn_link(?MODULE, commit_participant, Args);
_ when node(Tid#tid.pid) /= node() -> %% *_sym_trans
reply(From, {vote_yes, Tid}),
nopid
@@ -258,7 +258,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
protocol = Protocol},
State2 = State#state{participants = gb_trees:insert(Tid,P,Participants)},
doit_loop(State2);
-
+
{Tid, do_commit} ->
case gb_trees:lookup(Tid, Participants) of
none ->
@@ -272,14 +272,14 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
Member = lists:member(node(), P#participant.disc_nodes),
if Member == false ->
ignore;
- P#participant.protocol == sym_trans ->
+ P#participant.protocol == sym_trans ->
mnesia_log:log(Commit);
- P#participant.protocol == sync_sym_trans ->
+ P#participant.protocol == sync_sym_trans ->
mnesia_log:slog(Commit)
end,
mnesia_recover:note_decision(Tid, committed),
do_commit(Tid, Commit),
- if
+ if
P#participant.protocol == sync_sym_trans ->
Tid#tid.pid ! {?MODULE, node(), {committed, Tid}};
true ->
@@ -296,13 +296,13 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
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}]),
case gb_trees:lookup(Tid, Participants) of
@@ -317,7 +317,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
Commit = P#participant.commit,
mnesia_recover:note_decision(Tid, aborted),
do_abort(Tid, Commit),
- if
+ if
P#participant.protocol == sync_sym_trans ->
Tid#tid.pid ! {?MODULE, node(), {aborted, Tid}};
true ->
@@ -335,7 +335,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
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
@@ -355,14 +355,14 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
{'EXIT', Pid, Reason} ->
handle_exit(Pid, Reason, State);
-
+
{From, {restart, Tid, Store}} ->
A2 = restore_stores(Coordinators, Tid, Store),
clear_fixtable([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
@@ -377,7 +377,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
clear_fixtable(Etabs),
erase_ets_tabs(Etabs),
transaction_terminated(Tid),
- doit_loop(State#state{coordinators =
+ doit_loop(State#state{coordinators =
gb_trees:delete(Tid,Coordinators)})
end;
true ->
@@ -385,20 +385,20 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
State2 = State#state{participants=gb_trees:delete(Tid,Participants)},
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, gb_trees:values(Participants),
+ reply(From, {info, gb_trees:values(Participants),
gb_trees:to_list(Coordinators)}, State);
-
+
{mnesia_down, N} ->
verbose("Got mnesia_down from ~p, reconfiguring...~n", [N]),
reconfigure_coordinators(N, gb_trees:to_list(Coordinators)),
-
+
Tids = gb_trees:keys(Participants),
reconfigure_participants(N, gb_trees:values(Participants)),
NewState = clear_fixtable(N, State),
@@ -408,34 +408,34 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
{From, {unblock_me, Tab}} ->
case lists:member(Tab, State#state.blocked_tabs) of
false ->
- verbose("Wrong dirty Op blocked on ~p ~p ~p",
+ verbose("Wrong dirty Op blocked on ~p ~p ~p",
[node(), Tab, From]),
reply(From, unblocked),
doit_loop(State);
true ->
- Item = {Tab, unblock_me, From},
+ Item = {Tab, unblock_me, From},
State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
doit_loop(State2)
- end;
-
+ 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,
+ 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
@@ -448,18 +448,18 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
reply(From, Res, State);
{From, {fixtable, [Tab,Lock,Requester]}} ->
case ?catch_val({Tab, storage_type}) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
reply(From, error, State);
Storage ->
mnesia_lib:db_fixtable(Storage,Tab,Lock),
NewState = manage_fixtable(Tab,Lock,Requester,State),
reply(From, node(), NewState)
end;
-
+
{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)
@@ -508,7 +508,7 @@ prepare_pending_coordinators([{Tid, [Store | _Etabs]} | Coords], IgnoreNew) ->
ignore
end,
prepare_pending_coordinators(Coords, IgnoreNew);
- {'EXIT', _} ->
+ {'EXIT', _} ->
prepare_pending_coordinators(Coords, IgnoreNew)
end;
prepare_pending_coordinators([], _IgnoreNew) ->
@@ -538,7 +538,7 @@ handle_exit(Pid, _Reason, State) when Pid == State#state.supervisor ->
handle_exit(Pid, Reason, State) ->
%% Check if it is a coordinator
- case pid_search_delete(Pid, gb_trees:to_list(State#state.coordinators)) of
+ case pid_search_delete(Pid, gb_trees:to_list(State#state.coordinators)) of
{none, _} ->
%% Check if it is a participant
Ps = gb_trees:values(State#state.participants),
@@ -552,9 +552,9 @@ handle_exit(Pid, Reason, State) ->
NewPs = gb_trees:delete(P#participant.tid,State#state.participants),
doit_loop(State#state{participants = NewPs})
end;
-
+
{{Tid, Etabs}, RestC} ->
- %% A local coordinator has died and
+ %% 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
@@ -578,7 +578,7 @@ recover_coordinator(Tid, Etabs) ->
%% 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, [], []),
@@ -589,7 +589,7 @@ recover_coordinator(Tid, Etabs) ->
recover_coordinator(Tid, Protocol, Outcome, Local, DiscNs, RamNs),
?eval_debug_fun({?MODULE, recover_coordinator, post},
[{tid, Tid}, {outcome, Outcome}, {prot, Protocol}]);
- false -> %% When killed before store havn't been copied to
+ false -> %% When killed before store havn't been copied to
ok %% to the new nested trans store.
end
end,
@@ -610,12 +610,12 @@ recover_coordinator(Tid, sync_sym_trans, aborted, _Local, _, _) ->
recover_coordinator(Tid, asym_trans, committed, Local, DiscNs, RamNs) ->
D = #decision{tid = Tid, outcome = committed,
- disc_nodes = DiscNs, ram_nodes = RamNs},
+ 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},
+ disc_nodes = DiscNs, ram_nodes = RamNs},
mnesia_recover:log_decision(D),
do_abort(Tid, Local).
@@ -631,7 +631,7 @@ add_coord_store(Coords, Tid, Etab) ->
del_coord_store(Coords, Tid, Current, Obsolete) ->
Stores = gb_trees:get(Tid, Coords),
- Rest =
+ Rest =
case Stores of
[Obsolete, Current | Tail] -> Tail;
[Current, Obsolete | Tail] -> Tail
@@ -642,14 +642,14 @@ del_coord_store(Coords, Tid, Current, Obsolete) ->
erase_ets_tabs([H | T]) ->
?ets_delete_table(H),
erase_ets_tabs(T);
-erase_ets_tabs([]) ->
+erase_ets_tabs([]) ->
ok.
%% Clear one transactions all fixtables
clear_fixtable([Store|_]) ->
Fixed = get_elements(fixtable, Store),
lists:foreach(fun({Tab,Node}) ->
- rpc:cast(Node, ?MODULE, fixtable, [Tab,false,self()])
+ rpc:cast(Node, ?MODULE, fixtable, [Tab,false,self()])
end, Fixed).
%% Clear all fixtable Node have done
@@ -661,7 +661,7 @@ clear_fixtable(Node, State=#state{fixed_tabs = FT0}) ->
lists:foreach(
fun(Tab) ->
case ?catch_val({Tab, storage_type}) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
ignore;
Storage ->
mnesia_lib:db_fixtable(Storage,Tab,false)
@@ -680,9 +680,9 @@ manage_fixtable(Tab,true,Requester,State=#state{fixed_tabs = FT0}) ->
end;
manage_fixtable(Tab,false,Requester,State = #state{fixed_tabs = FT0}) ->
Node = node(Requester),
- case mnesia_lib:key_search_delete(Node, 1, FT0) of
+ case mnesia_lib:key_search_delete(Node, 1, FT0) of
{none,_FT} -> State; % Hmm? Safeguard
- {{Node, Tabs0},FT} ->
+ {{Node, Tabs0},FT} ->
case lists:delete(Tab, Tabs0) of
[] -> State#state{fixed_tabs=FT};
Tabs -> State#state{fixed_tabs=[{Node,Tabs}|FT]}
@@ -691,7 +691,7 @@ manage_fixtable(Tab,false,Requester,State = #state{fixed_tabs = FT0}) ->
%% Deletes a pid from a list of participants
%% or from a gb_trees of coordinators
-%% {none, All} or {Tr, Rest}
+%% {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 ->
@@ -701,7 +701,7 @@ pid_search_delete(Pid, [Tr | Trs], Val, Ack) ->
pid_search_delete(_Pid, [], Val, Ack) ->
{Val, gb_trees:from_orddict(lists:reverse(Ack))}.
-
+
transaction_terminated(Tid) ->
mnesia_checkpoint:tm_exit_pending(Tid),
Pid = Tid#tid.pid,
@@ -713,14 +713,14 @@ transaction_terminated(Tid) ->
end.
%% If there are an surrounding transaction, we inherit it's context
-non_transaction(OldState={_,_,Trans}, Fun, Args, ActivityKind, Mod)
+non_transaction(OldState={_,_,Trans}, Fun, Args, ActivityKind, Mod)
when Trans /= non_transaction ->
- Kind = case ActivityKind of
+ Kind = case ActivityKind of
sync_dirty -> sync;
_ -> async
end,
case transaction(OldState, Fun, Args, infinity, Mod, Kind) of
- {atomic, Res} ->
+ {atomic, Res} ->
Res;
{aborted,Res} ->
exit(Res)
@@ -766,7 +766,7 @@ transaction(OldTidTs, Fun, Args, Retries, Mod, Type) ->
execute_outer(Mod, Fun, Args, Factor, Retries, Type) ->
case req(start_outer) of
- {error, Reason} ->
+ {error, Reason} ->
{aborted, Reason};
{new_tid, Tid, Store} ->
Ts = #tidstore{store = Store},
@@ -792,7 +792,7 @@ execute_inner(Mod, Tid, OldMod, Ts, Fun, Args, Factor, Retries, Type) ->
copy_ets(From, To) ->
do_copy_ets(?ets_first(From), From, To).
-do_copy_ets('$end_of_table', _,_) ->
+do_copy_ets('$end_of_table', _,_) ->
ok;
do_copy_ets(K, From, To) ->
Objs = ?ets_lookup(From, K),
@@ -813,7 +813,7 @@ execute_transaction(Fun, Args, Factor, Retries, Type) ->
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 any un processed mnesia_down messages we might have
flush_downs(),
catch unlink(whereis(?MODULE)),
{atomic, Value};
@@ -846,7 +846,7 @@ check_exit(Fun, Args, Factor, Retries, Reason, Type) ->
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.
@@ -888,11 +888,11 @@ restart(Mod, Tid, Ts, Fun, Args, Factor0, Retries0, Type, Why) ->
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);
+ 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;
@@ -911,7 +911,7 @@ restart(Mod, Tid, Ts, Fun, Args, Factor0, Retries0, Type, Why) ->
mnesia_locker:receive_release_tid_acc(Nodes, Tid),
case get_restarted(Tid) of
{restarted, Tid} ->
- execute_transaction(Fun, Args, Factor0 + 1,
+ execute_transaction(Fun, Args, Factor0 + 1,
Retries, Type);
{error, Reason} ->
mnesia:abort(Reason)
@@ -934,7 +934,7 @@ decr(_X) -> 0.
return_abort(Fun, Args, Reason) ->
{_Mod, Tid, Ts} = get(mnesia_activity_state),
- dbg_out("Transaction ~p calling ~p with ~p failed: ~n ~p~n",
+ dbg_out("Transaction ~p calling ~p with ~p failed: ~n ~p~n",
[Tid, Fun, Args, Reason]),
OldStore = Ts#tidstore.store,
Nodes = get_elements(nodes, OldStore),
@@ -945,7 +945,7 @@ return_abort(Fun, Args, Reason) ->
Level == 1 ->
mnesia_locker:async_release_tid(Nodes, Tid),
?MODULE ! {delete_transaction, Tid},
- erase(mnesia_activity_state),
+ erase(mnesia_activity_state),
flush_downs(),
catch unlink(whereis(?MODULE)),
{aborted, mnesia_lib:fix_error(Reason)};
@@ -958,14 +958,14 @@ return_abort(Fun, Args, Reason) ->
level = Level - 1},
NewTidTs = {OldMod, Tid, Ts2},
put(mnesia_activity_state, NewTidTs),
- case Reason of
+ case Reason of
#cyclic{} ->
exit({aborted, Reason});
- {node_not_running, _N} ->
+ {node_not_running, _N} ->
exit({aborted, Reason});
- {bad_commit, _N}->
+ {bad_commit, _N}->
exit({aborted, Reason});
- _ ->
+ _ ->
{aborted, mnesia_lib:fix_error(Reason)}
end
end.
@@ -982,10 +982,10 @@ put_activity_id(MTT) ->
put_activity_id(MTT, undefined).
put_activity_id(undefined,_) ->
erase_activity_id();
-put_activity_id({Mod, Tid = #tid{}, Ts = #tidstore{}},Fun) ->
+put_activity_id({Mod, Tid = #tid{}, Ts = #tidstore{}},Fun) ->
flush_downs(),
Store = Ts#tidstore.store,
- if
+ if
is_function(Fun) ->
?ets_insert(Store, {friends, {stop,Fun}});
true ->
@@ -1000,14 +1000,14 @@ erase_activity_id() ->
flush_downs(),
erase(mnesia_activity_state).
-get_elements(Type,Store) ->
+get_elements(Type,Store) ->
case catch ?ets_lookup(Store, Type) of
[] -> [];
[{_,Val}] -> [Val];
{'EXIT', _} -> [];
Vals -> [Val|| {_,Val} <- Vals]
end.
-
+
opt_propagate_store(_Current, _Obsolete, false) ->
ok;
opt_propagate_store(Current, Obsolete, true) ->
@@ -1030,8 +1030,8 @@ intercept_best_friend([],_) -> ok;
intercept_best_friend([{stop,Fun} | R],Ignore) ->
catch Fun(),
intercept_best_friend(R,Ignore);
-intercept_best_friend([Pid | R],false) ->
- Pid ! {activity_ended, undefined, self()},
+intercept_best_friend([Pid | R],false) ->
+ Pid ! {activity_ended, undefined, self()},
wait_for_best_friend(Pid, 0),
intercept_best_friend(R,true);
intercept_best_friend([_|R],true) ->
@@ -1047,18 +1047,18 @@ wait_for_best_friend(Pid, Timeout) ->
false -> ok
end
end.
-
+
my_process_is_alive(Pid) ->
case catch erlang:is_process_alive(Pid) of % New BIF in R5
- true ->
+ true ->
true;
- false ->
+ false ->
false;
- {'EXIT', _} -> % Pre R5 backward compatibility
+ {'EXIT', _} -> % Pre R5 backward compatibility
case process_info(Pid, message_queue_len) of
undefined -> false;
_ -> true
- end
+ end
end.
dirty(Protocol, Item) ->
@@ -1070,12 +1070,12 @@ dirty(Protocol, Item) ->
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.
-
+ %% 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
@@ -1097,7 +1097,7 @@ t_commit(Type) ->
if
Ts#tidstore.level == 1 ->
intercept_friends(Tid, Ts),
- %% N is number of updates
+ %% N is number of updates
case arrange(Tid, Store, Type) of
{N, Prep} when N > 0 ->
multi_commit(Prep#prep.protocol,
@@ -1135,8 +1135,8 @@ arrange(Tid, Store, Type) ->
Recs = prep_recs(Nodes, []),
Key = ?ets_first(Store),
N = 0,
- Prep =
- case Type of
+ Prep =
+ case Type of
async -> #prep{protocol = sym_trans, records = Recs};
sync -> #prep{protocol = sync_sym_trans, records = Recs}
end,
@@ -1146,7 +1146,7 @@ arrange(Tid, Store, Type) ->
case Reason of
{aborted, R} ->
mnesia:abort(R);
- _ ->
+ _ ->
mnesia:abort(Reason)
end;
{New, Prepared} ->
@@ -1155,7 +1155,7 @@ arrange(Tid, Store, Type) ->
reverse([]) ->
[];
-reverse([H=#commit{ram_copies=Ram, disc_copies=DC,
+reverse([H=#commit{ram_copies=Ram, disc_copies=DC,
disc_only_copies=DOC,snmp = Snmp}
|R]) ->
[
@@ -1164,7 +1164,7 @@ reverse([H=#commit{ram_copies=Ram, disc_copies=DC,
disc_copies = lists:reverse(DC),
disc_only_copies = lists:reverse(DOC),
snmp = lists:reverse(Snmp)
- }
+ }
| reverse(R)].
prep_recs([N | Nodes], Recs) ->
@@ -1191,7 +1191,7 @@ do_arrange(Tid, Store, RestoreKey, Prep, N) when RestoreKey == restore_op ->
(BupRec, CommitRecs, RecName, Where, Snmp) ->
Tab = element(1, BupRec),
Key = element(2, BupRec),
- Item =
+ Item =
if
Tab == RecName ->
[{{Tab, Key}, BupRec, write}];
@@ -1200,7 +1200,7 @@ do_arrange(Tid, Store, RestoreKey, Prep, N) when RestoreKey == restore_op ->
[{{Tab, Key}, BupRec2, write}]
end,
do_prepare_items(Tid, Tab, Key, Where, Snmp, Item, CommitRecs)
- end,
+ 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);
@@ -1222,20 +1222,20 @@ prepare_items(Tid, Tab, Key, Items, Prep) when Prep#prep.prev_tab == Tab ->
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, _} ->
+ {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,
+ Recs2 = do_prepare_items(Tid, Tab, Key, Types,
Snmp, Items, Prep#prep.records),
- Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,
+ Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,
majority = Majority,
prev_types = Types, prev_snmp = Snmp},
check_prep(Prep2, Types)
@@ -1273,7 +1273,7 @@ have_majority([{Tab, AllNodes} | Rest], Nodes) ->
end.
prepare_snmp(Tab, Key, Items) ->
- case val({Tab, snmp}) of
+ case val({Tab, snmp}) of
[] ->
[];
Ustruct when Key /= '_' ->
@@ -1286,10 +1286,10 @@ prepare_snmp(Tab, Key, Items) ->
[{clear_table, Tab}]
end.
-prepare_snmp(_Tid, _Tab, _Key, _Types, [], _Items, Recs) ->
+prepare_snmp(_Tid, _Tab, _Key, _Types, [], _Items, Recs) ->
Recs;
-prepare_snmp(Tid, Tab, Key, Types, Us, Items, 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
@@ -1334,7 +1334,7 @@ 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 =
+ Rec2 =
case Storage of
ram_copies ->
Rec#commit{ram_copies = [Item | Rec#commit.ram_copies]};
@@ -1345,7 +1345,7 @@ prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind /= schema ->
[Item | Rec#commit.disc_only_copies]}
end,
prepare_node(Node, Storage, Items, Rec2, Kind);
-prepare_node(_Node, _Storage, Items, Rec, 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) ->
@@ -1354,7 +1354,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, _Maj = [], Tid, CR, _Store) ->
- %% This featherweight commit protocol is used when no
+ %% This featherweight commit protocol is used when no
%% updates has been performed in the transaction.
{DiscNs, RamNs} = commit_nodes(CR, [], []),
@@ -1381,11 +1381,11 @@ multi_commit(sym_trans, _Maj = [], Tid, CR, Store) ->
%% 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.
@@ -1394,15 +1394,15 @@ multi_commit(sym_trans, _Maj = [], Tid, CR, Store) ->
%% 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}]),
+ {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
@@ -1422,15 +1422,15 @@ 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.
-
+
{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}]),
+ {Outcome, []} = rec_all(WaitFor, Tid, do_commit, []),
+ ?eval_debug_fun({?MODULE, multi_commit_sym_sync},
+ [{tid, Tid}, {outcome, Outcome}]),
[?ets_insert(Store, {waiting_for_commit_ack, Node}) || Node <- WaitFor],
rpc:abcast(DiscNs -- [node()], ?MODULE, {Tid, Outcome}),
rpc:abcast(RamNs -- [node()], ?MODULE, {Tid, Outcome}),
@@ -1451,7 +1451,7 @@ multi_commit(sync_sym_trans, _Maj = [], Tid, CR, Store) ->
Outcome;
multi_commit(asym_trans, Majority, Tid, CR, Store) ->
- %% This more expensive commit protocol is used when
+ %% 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
@@ -1462,14 +1462,14 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
%% 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.
+ %% acc_pre_commit when they are done.
%%
%% 3a Somebody died
%% Tell the remaining participants to do_abort
@@ -1492,7 +1492,7 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
%% 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.
@@ -1506,7 +1506,7 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
%% 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,
@@ -1518,10 +1518,10 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
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},
+ 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 ->
@@ -1530,20 +1530,20 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
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),
+ 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,Local},
+ rec_acc_pre_commit(Pids, Tid, Store, {C,Local},
do_commit, DumperMode, [], []);
{'EXIT', Reason} ->
- %% The others have logged the commit
+ %% 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},
@@ -1564,7 +1564,7 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
end.
%% Returns do_commit or {do_abort, Reason}
-rec_acc_pre_commit([Pid | Tail], Tid, Store, Commit, Res, DumperMode,
+rec_acc_pre_commit([Pid | Tail], Tid, Store, Commit, Res, DumperMode,
GoodPids, SchemaAckPids) ->
receive
{?MODULE, _, {acc_pre_commit, Tid, Pid, true}} ->
@@ -1598,7 +1598,7 @@ rec_acc_pre_commit([], Tid, Store, {Commit,OrigC}, Res, DumperMode, GoodPids, Sc
%% everybody are uncertain.
prepare_sync_schema_commit(Store, SchemaAckPids),
tell_participants(GoodPids, {Tid, committed}),
- D2 = D#decision{outcome = committed},
+ D2 = D#decision{outcome = committed},
mnesia_recover:log_decision(D2),
?eval_debug_fun({?MODULE, rec_acc_pre_commit_log_commit},
[{tid, Tid}]),
@@ -1611,10 +1611,10 @@ rec_acc_pre_commit([], Tid, Store, {Commit,OrigC}, Res, DumperMode, GoodPids, Sc
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},
+ D2 = D#decision{outcome = aborted},
mnesia_recover:log_decision(D2),
?eval_debug_fun({?MODULE, rec_acc_pre_commit_log_abort},
[{tid, Tid}]),
@@ -1702,7 +1702,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
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},
@@ -1710,7 +1710,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
mnesia_schema:undo_prepare_commit(Tid, C0),
?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},
@@ -1718,7 +1718,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
mnesia_schema:undo_prepare_commit(Tid, C0),
?eval_debug_fun({?MODULE, commit_participant, exit_undo_prepare},
[{tid, Tid}]);
-
+
Msg ->
verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
[Tid, Msg])
@@ -1739,7 +1739,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
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}]),
@@ -1750,7 +1750,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?MODULE ! {delete_transaction, Tid},
unlink(whereis(?MODULE)),
exit(normal).
-
+
do_abort(Tid, Bin) when is_binary(Bin) ->
%% Possible optimization:
%% If we want we could pass arround a flag
@@ -1761,7 +1761,7 @@ do_abort(Tid, Bin) when is_binary(Bin) ->
%% mnesia_schema:undo_prepare_commit/1.
do_abort(Tid, binary_to_term(Bin));
do_abort(Tid, Commit) ->
- mnesia_schema:undo_prepare_commit(Tid, Commit),
+ mnesia_schema:undo_prepare_commit(Tid, Commit),
Commit.
do_dirty(Tid, Commit) when Commit#commit.schema_ops == [] ->
@@ -1799,7 +1799,7 @@ do_update(Tid, Storage, [Op | Ops], OldRes) ->
verbose("do_update in ~w failed: ~p -> {'EXIT', ~p}~n",
[Tid, Op, Reason]),
- do_update(Tid, Storage, Ops, OldRes);
+ do_update(Tid, Storage, Ops, OldRes);
NewRes ->
do_update(Tid, Storage, Ops, NewRes)
end;
@@ -1807,7 +1807,7 @@ do_update(_Tid, _Storage, [], Res) ->
Res.
do_update_op(Tid, Storage, {{Tab, K}, Obj, write}) ->
- commit_write(?catch_val({Tab, commit_work}), Tid,
+ commit_write(?catch_val({Tab, commit_work}), Tid,
Tab, K, Obj, undefined),
mnesia_lib:db_put(Storage, Tab, Obj);
@@ -1816,7 +1816,7 @@ do_update_op(Tid, Storage, {{Tab, K}, Val, delete}) ->
mnesia_lib:db_erase(Storage, Tab, K);
do_update_op(Tid, Storage, {{Tab, K}, {RecName, Incr}, update_counter}) ->
- {NewObj, OldObjs} =
+ {NewObj, OldObjs} =
case catch mnesia_lib:db_update_counter(Storage, Tab, K, Incr) of
NewVal when is_integer(NewVal), NewVal >= 0 ->
{{RecName, K, NewVal}, [{RecName, K, NewVal - Incr}]};
@@ -1824,17 +1824,17 @@ do_update_op(Tid, Storage, {{Tab, K}, {RecName, Incr}, update_counter}) ->
New = {RecName, K, Incr},
mnesia_lib:db_put(Storage, Tab, New),
{New, []};
- _ ->
+ _ ->
Zero = {RecName, K, 0},
mnesia_lib:db_put(Storage, Tab, Zero),
{Zero, []}
end,
- commit_update(?catch_val({Tab, commit_work}), Tid, Tab,
+ 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}),
+ commit_del_object(?catch_val({Tab, commit_work}),
Tid, Tab, Key, Obj, undefined),
mnesia_lib:db_match_erase(Storage, Tab, Obj);
@@ -1846,11 +1846,11 @@ 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)
+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)
+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).
@@ -1859,11 +1859,11 @@ 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)
+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)
+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).
@@ -1872,11 +1872,11 @@ 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)
+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)
+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).
@@ -1885,12 +1885,12 @@ 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 ->
+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 ->
+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).
@@ -1898,11 +1898,11 @@ 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)
+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)
+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).
@@ -1913,7 +1913,7 @@ do_snmp(Tid, [Head | Tail]) ->
{'EXIT', Reason} ->
%% This should only happen when we recently have
%% deleted our local replica or recently deattached
- %% the snmp table
+ %% the snmp table
verbose("do_snmp in ~w failed: ~p -> {'EXIT', ~p}~n",
[Tid, Head, Reason]);
@@ -1922,7 +1922,7 @@ do_snmp(Tid, [Head | Tail]) ->
end,
do_snmp(Tid, Tail).
-commit_nodes([C | Tail], AccD, AccR)
+commit_nodes([C | Tail], AccD, AccR)
when C#commit.disc_copies == [],
C#commit.disc_only_copies == [],
C#commit.schema_ops == [] ->
@@ -1934,7 +1934,7 @@ commit_nodes([], AccD, AccR) ->
commit_decision(D, [C | Tail], AccD, AccR) ->
N = C#commit.node,
- {D2, Tail2} =
+ {D2, Tail2} =
case C#commit.schema_ops of
[] when C#commit.disc_copies == [],
C#commit.disc_only_copies == [] ->
@@ -1954,8 +1954,8 @@ 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 ->
+ case lists:member({name, schema}, Cs) of
+ true ->
%% We always use disk if change type of the schema
false;
false ->
@@ -2025,12 +2025,12 @@ get_dirty_reply(Node, Res) ->
Reply;
{mnesia_down, Node} ->
case get(mnesia_activity_state) of
- {_, Tid, _Ts} when element(1,Tid) == tid ->
+ {_, Tid, _Ts} when element(1,Tid) == tid ->
%% Hmm dirty called inside a transaction, to avoid
%% hanging transaction we need to restart the transaction
mnesia:abort({node_not_running, Node});
_ ->
- %% It's ok to ignore mnesia_down's since we will make
+ %% It's ok to ignore mnesia_down's since we will make
%% the replicas consistent again when Node is started
Res
end
@@ -2068,10 +2068,10 @@ ask_commit(_Protocol, _Tid, [], _DiscNs, _RamNs, WaitFor, Local) ->
%% to be safe we let erts do the translation (many times maybe and thus
%% slower but it works.
% opt_term_to_binary(asym_trans, Head, Nodes) ->
-% opt_term_to_binary(Nodes, Head);
+% opt_term_to_binary(Nodes, Head);
opt_term_to_binary(_Protocol, Head, _Nodes) ->
Head.
-
+
rec_all([Node | Tail], Tid, Res, Pids) ->
receive
{?MODULE, Node, {vote_yes, Tid}} ->
@@ -2085,7 +2085,7 @@ rec_all([Node | Tail], Tid, Res, Pids) ->
{?MODULE, Node, {aborted, Tid}} ->
rec_all(Tail, Tid, Res, Pids);
- {mnesia_down, Node} ->
+ {mnesia_down, Node} ->
%% Make sure that mnesia_tm knows it has died
%% it may have been restarted
Abort = {do_abort, {bad_commit, Node}},
@@ -2095,7 +2095,7 @@ rec_all([Node | Tail], Tid, Res, Pids) ->
rec_all([], _Tid, Res, Pids) ->
{Res, Pids}.
-get_transactions() ->
+get_transactions() ->
{info, Participant, Coordinator} = req(info),
lists:map(fun({Tid, _Tabs}) ->
Status = tr_status(Tid,Participant),
@@ -2125,7 +2125,7 @@ get_info(Timeout) ->
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),
@@ -2134,7 +2134,7 @@ display_info(Stream, {info, Part, Coord}) ->
pr_participant(Stream, P) ->
Commit0 = P#participant.commit,
- Commit =
+ Commit =
if
is_binary(Commit0) -> binary_to_term(Commit0);
true -> Commit0
@@ -2161,11 +2161,11 @@ search_pr_coordinator(S, [{Tid, _Ts}|Tail]) ->
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, []) ->
+search_pr_participant(_S, []) ->
false;
search_pr_participant(S, [ P | Tail]) ->
Tid = P#participant.tid,
@@ -2176,15 +2176,15 @@ search_pr_participant(S, [ P | Tail]) ->
Pid = Tid#tid.pid,
display_pid_info(Pid),
io:format( "Tid wants to write objects \n",[]),
- Commit =
+ Commit =
if
is_binary(Commit0) -> binary_to_term(Commit0);
true -> Commit0
end,
-
+
io:format("~p~n", [Commit]),
search_pr_participant(S,Tail); %% !!!!!
- true ->
+ true ->
search_pr_participant(S, Tail)
end.
@@ -2200,7 +2200,7 @@ display_pid_info(Pid) ->
Other ->
Other
end,
- Reds = fetch(reductions, Info),
+ Reds = fetch(reductions, Info),
LM = length(fetch(messages, Info)),
pformat(io_lib:format("~p", [Pid]),
io_lib:format("~p", [Call]),
@@ -2254,7 +2254,7 @@ send_to_pids([_ | Pids], 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
@@ -2262,25 +2262,25 @@ reconfigure_participants(N, [P | Tail]) ->
%% 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
+ if
node(Tid#tid.pid) /= N ->
%% Another participant node died. Ignore.
reconfigure_participants(N, Tail);
true ->
- %% The coordinator node has died and
+ %% 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],
@@ -2332,8 +2332,8 @@ system_terminate(_Reason, _Parent, _Debug, State) ->
system_code_change(State=#state{coordinators=Cs0,participants=Ps0},_Module,_OldVsn,downgrade) ->
case is_tuple(Cs0) of
- true ->
- Cs = gb_trees:to_list(Cs0),
+ true ->
+ Cs = gb_trees:to_list(Cs0),
Ps = gb_trees:values(Ps0),
{ok, State#state{coordinators=Cs,participants=Ps}};
false ->
@@ -2342,7 +2342,7 @@ system_code_change(State=#state{coordinators=Cs0,participants=Ps0},_Module,_OldV
system_code_change(State=#state{coordinators=Cs0,participants=Ps0},_Module,_OldVsn,_Extra) ->
case is_list(Cs0) of
- true ->
+ true ->
Cs = gb_trees:from_orddict(lists:sort(Cs0)),
Ps1 = [{P#participant.tid,P}|| P <- Ps0],
Ps = gb_trees:from_orddict(lists:sort(Ps1)),
diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile
index ae4c9626c7..0451da697d 100644
--- a/lib/mnesia/test/Makefile
+++ b/lib/mnesia/test/Makefile
@@ -52,24 +52,29 @@ MODULES= \
mnesia_cost \
mnesia_dbn_meters
-MnesiaExamplesDir := ../examples
+DocExamplesDir := ../doc/src/
-ExampleModules = \
+DocExampleModules = \
company \
company_o \
- bup \
- mnesia_meter \
- mnesia_tpcb
-ExamplesHrl = \
+ bup
+
+DocExamplesHrl = \
company.hrl \
company_o.hrl
-ERL_FILES= $(MODULES:%=%.erl) $(ExampleModules:%=$(MnesiaExamplesDir)/%.erl)
+ExamplesDir := ../examples/
+
+ExampleModules = \
+ mnesia_meter \
+ mnesia_tpcb
-HRL_FILES= mnesia_test_lib.hrl $(ExamplesHrl:%=$(MnesiaExamplesDir)/%)
+ERL_FILES= $(MODULES:%=%.erl) $(DocExampleModules:%=$(DocExamplesDir)/%.erl) $(ExampleModules:%=$(ExamplesDir)/%.erl)
+
+HRL_FILES= mnesia_test_lib.hrl $(DocExamplesHrl:%=$(DocExamplesDir)/%)
TARGET_FILES= \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(ExampleModules:%=$(EBIN)/%.$(EMULATOR))
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(DocExampleModules:%=$(EBIN)/%.$(EMULATOR)) $(ExampleModules:%=$(EBIN)/%.$(EMULATOR))
INSTALL_PROGS= $(TARGET_FILES)
@@ -91,7 +96,10 @@ EBIN = .
tests debug opt: $(TARGET_FILES)
-$(EBIN)/%.beam: $(MnesiaExamplesDir)/%.erl
+$(EBIN)/%.beam: $(DocExamplesDir)/%.erl
+ $(ERLC) -bbeam $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
+
+$(EBIN)/%.beam: $(ExamplesDir)/%.erl
$(ERLC) -bbeam $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
clean:
@@ -108,11 +116,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
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 -R u+w $(RELSYSDIR)
-# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) mnesia.spec mnesia.cover $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_SCRIPT) mt $(INSTALL_PROGS) "$(RELSYSDIR)"
+# chmod -R u+w "$(RELSYSDIR)"
+# @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl
index cf878fc820..06c4d16d71 100644
--- a/lib/mnesia/test/mnesia_atomicity_test.erl
+++ b/lib/mnesia/test/mnesia_atomicity_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
@@ -31,13 +31,13 @@ end_per_testcase(Func, Conf) ->
mnesia_test_lib:end_per_testcase(Func, Conf).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-all() ->
+all() ->
[explicit_abort_in_middle_of_trans,
runtime_error_in_middle_of_trans,
kill_self_in_middle_of_trans, throw_in_middle_of_trans,
{group, mnesia_down_in_middle_of_trans}].
-groups() ->
+groups() ->
[{mnesia_down_in_middle_of_trans, [],
[mnesia_down_during_infinite_trans,
{group, lock_waiter}, {group, restart_check}]},
@@ -297,7 +297,7 @@ mnesia_down_during_infinite_trans(Config) when is_list(Config) ->
?match({atomic, ok},
mnesia:transaction(fun() -> mnesia:write({Tab, 1, test_ok}) end)),
mnesia_test_lib:start_sync_transactions([A2, A1]),
-
+
%% Obtain a write lock and wait forever
RecA = {Tab, 1, test_not_ok},
A1 ! fun() -> mnesia:write(RecA) end,
@@ -471,12 +471,12 @@ lock_waiter_w_wt(Config) when is_list(Config) ->
start_lock_waiter(BlockOpA, BlockOpB, Config) ->
[N1, N2] = Nodes = ?acquire_nodes(2, Config),
-
+
TabName = mk_tab_name(lock_waiter_),
?match({atomic, ok}, mnesia:create_table(TabName,
[{ram_copies, [N1, N2]}])),
-
- %% initialize the table with object {1, c} - when there
+
+ %% initialize the table with object {1, c} - when there
%% is a read transaction, the read will find that value
?match({atomic, ok}, mnesia:sync_transaction(fun() -> mnesia:write({TabName, 1, c}) end)),
rpc:call(N2, ?MODULE, sync_tid_release, []),
@@ -484,7 +484,7 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) ->
Tester = self(),
Fun_A =fun() ->
NewCounter = incr_restart_counter(),
- if
+ if
NewCounter == 1 ->
Tester ! go_ahead_test,
receive go_ahead -> ok end;
@@ -493,13 +493,13 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) ->
lock_waiter_fun(BlockOpA, TabName, a),
NewCounter
end,
-
+
%% it's not possible to just spawn the transaction, because
%% the result shall be evaluated
A = spawn_link(N1, ?MODULE, perform_restarted_transaction, [Fun_A]),
-
+
?match(ok, receive go_ahead_test -> ok after 10000 -> timeout end),
-
+
mnesia_test_lib:sync_trans_tid_serial([N1, N2]),
Fun_B = fun() ->
@@ -507,21 +507,21 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) ->
A ! go_ahead,
wait(infinity)
end,
-
+
B = spawn_link(N2, mnesia, transaction, [Fun_B, 100]),
-
+
io:format("waiting for A (~p on ~p) to be in the queue ~n", [A, [N1, N2]]),
wait_for_a(A, [N1, N2]),
-
- io:format("Queus ~p~n",
+
+ io:format("Queus ~p~n",
[[{N,rpc:call(N, mnesia, system_info, [lock_queue])} || N <- Nodes]]),
-
+
KillNode = node(B),
io:format("A was in the queue, time to kill Mnesia on B's node (~p on ~p)~n",
[B, KillNode]),
-
+
mnesia_test_lib:kill_mnesia([KillNode]), % kill mnesia of fun B
-
+
%% Read Ops does not need to be restarted
ExpectedCounter =
if
@@ -535,20 +535,22 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) ->
BlockOpA == rt, BlockOpB /= sw -> 1;
true -> 2
end,
- ?match_multi_receive([{'EXIT', A, {atomic, ExpectedCounter}},
- {'EXIT', B, killed}]),
-
+ receive {'EXIT', B, _} -> ok
+ after 3000 -> ?error("Timeout~n", []) end,
+ receive {'EXIT', A, Exp1} -> ?match({atomic, ExpectedCounter}, Exp1)
+ after 3000 -> ?error("Timeout~n", []) end,
+
%% the expected result depends on the transaction of
%% fun A - when that doesn't change the object in the
%% table (e.g. it is a read) then the predefined
%% value {Tabname, 1, c} is expected to be the result here
- ExpectedResult =
+ ExpectedResult =
case BlockOpA of
w -> {TabName, 1, a};
sw ->{TabName, 1, a};
_all_other -> {TabName, 1, c}
end,
-
+
?match({atomic, [ExpectedResult]},
mnesia:transaction(fun() -> mnesia:read({TabName, 1}) end, 100)),
?verify_mnesia([N1], [N2]).
@@ -567,7 +569,7 @@ lock_waiter_fun(Op, TabName, Val) ->
srw -> mnesia:read(TabName, 1, sticky_write);
sw -> mnesia:s_write({TabName, 1, Val})
end.
-
+
wait_for_a(Pid, Nodes) ->
wait_for_a(Pid, Nodes, 5).
@@ -589,12 +591,12 @@ check_q(Pid, [_ | Tail], N, Count) ->
check_q(Pid, [], N, Count) ->
timer:sleep(500),
wait_for_a(Pid, N, Count - 1).
-
+
perform_restarted_transaction (Fun_Trans) ->
%% the result of the transaction shall be:
%% - undefined (if the transaction was never executed)
%% - Times ( number of times that the transaction has been executed)
-
+
Result = mnesia:transaction(Fun_Trans, 100),
exit(Result).
@@ -666,10 +668,10 @@ restart_sw_two(Config) when is_list(Config) ->
start_restart_check(RestartOp, ReplicaNeed, Config) ->
[N1, N2, N3] = Nodes = ?acquire_nodes(3, Config),
-
+
{TabName, _TabNodes} = create_restart_table(ReplicaNeed, Nodes),
-
- %% initialize the table with object {1, c} - when there
+
+ %% initialize the table with object {1, c} - when there
%% is a read transaction, the read will find that value
?match({atomic, ok}, mnesia:sync_transaction(fun() -> mnesia:write({TabName, 1, c}) end)),
@@ -681,9 +683,9 @@ start_restart_check(RestartOp, ReplicaNeed, Config) ->
NewCounter = incr_restart_counter(),
case NewCounter of
1 ->
- mnesia:write({TabName, 1, d}),
+ mnesia:write({TabName, 1, d}),
%% send a message to the test proc
- Coord ! {self(),fun_a_is_blocked},
+ Coord ! {self(),fun_a_is_blocked},
receive go_ahead -> ok end;
_ ->
%% the fun will NOT be blocked here
@@ -691,19 +693,19 @@ start_restart_check(RestartOp, ReplicaNeed, Config) ->
end,
NewCounter
end,
-
+
A = spawn_link(N1, ?MODULE, perform_restarted_transaction, [Fun_A]),
- ?match_receive({A,fun_a_is_blocked}),
-
+ ?match_receive({A,fun_a_is_blocked}),
+
%% mnesia shall be killed at that node, where A is reading
%% the information from
kill_where_to_read(TabName, N1, [N2, N3]),
-
+
%% wait some time to let mnesia go down and spread those news around
%% fun A shall be able to finish its job before being restarted
- wait(500),
+ wait(500),
A ! go_ahead,
-
+
%% the sticky write doesnt work on remote nodes !!!
ExpectedMsg =
case RestartOp of
@@ -717,19 +719,19 @@ start_restart_check(RestartOp, ReplicaNeed, Config) ->
{'EXIT',A,{atomic, 2}}
end
end,
-
- ?match_receive(ExpectedMsg),
-
+
+ ?match_receive(ExpectedMsg),
+
%% now mnesia has to be started again on the node KillNode
%% because the next test suite will need it
?match([], mnesia_test_lib:start_mnesia(Nodes, [TabName])),
-
-
+
+
%% the expected result depends on the transaction of
%% fun A - when that doesnt change the object in the
%% table (e.g. it is a read) then the predefined
%% value {Tabname, 1, c} is expected to be the result here
-
+
ExpectedResult =
case ReplicaNeed of
one ->
@@ -746,7 +748,7 @@ start_restart_check(RestartOp, ReplicaNeed, Config) ->
?verify_mnesia(Nodes, []).
create_restart_table(ReplicaNeed, [_N1, N2, N3]) ->
- TabNodes =
+ TabNodes =
case ReplicaNeed of
one -> [N2];
two -> [N2, N3]
@@ -754,7 +756,7 @@ create_restart_table(ReplicaNeed, [_N1, N2, N3]) ->
TabName = mk_tab_name(restart_check_),
?match({atomic, ok}, mnesia:create_table(TabName, [{ram_copies, TabNodes}])),
{TabName, TabNodes}.
-
+
restart_fun_A(Op, TabName) ->
case Op of
rt -> mnesia:read_lock_table(TabName);
@@ -774,8 +776,8 @@ kill_where_to_read(TabName, N1, Nodes) ->
?error("Fault while killing Mnesia: ~p~n", [Read]),
mnesia_test_lib:kill_mnesia(Nodes)
end.
-
-sync_tid_release() ->
+
+sync_tid_release() ->
sys:get_status(whereis(mnesia_tm)),
sys:get_status(whereis(mnesia_locker)),
ok.
diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl
index f38e13f3a2..bb21723e27 100644
--- a/lib/mnesia/test/mnesia_consistency_test.erl
+++ b/lib/mnesia/test/mnesia_consistency_test.erl
@@ -100,7 +100,7 @@ groups() ->
{group, updates_during_checkpoint_iteration},
{group, load_table_with_activated_checkpoint},
{group,
- add_table_copy_to_table_with_activated_checkpoint}]},
+ add_table_copy_to_table_checkpoint}]},
{updates_during_checkpoint_activation, [],
[updates_during_checkpoint_activation_2_ram,
updates_during_checkpoint_activation_2_disc,
@@ -116,10 +116,10 @@ groups() ->
[load_table_with_activated_checkpoint_ram,
load_table_with_activated_checkpoint_disc,
load_table_with_activated_checkpoint_disc_only]},
- {add_table_copy_to_table_with_activated_checkpoint, [],
- [add_table_copy_to_table_with_activated_checkpoint_ram,
- add_table_copy_to_table_with_activated_checkpoint_disc,
- add_table_copy_to_table_with_activated_checkpoint_disc_only]},
+ {add_table_copy_to_table_checkpoint, [],
+ [add_table_copy_to_table_checkpoint_ram,
+ add_table_copy_to_table_checkpoint_disc,
+ add_table_copy_to_table_checkpoint_disc_only]},
{backup_consistency, [],
[{group, interupted_install_fallback},
{group, interupted_uninstall_fallback},
@@ -952,16 +952,16 @@ view(Source, Mod) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_table_copy_to_table_with_activated_checkpoint_ram(suite) -> [];
-add_table_copy_to_table_with_activated_checkpoint_ram(Config) when is_list(Config) ->
+add_table_copy_to_table_checkpoint_ram(suite) -> [];
+add_table_copy_to_table_checkpoint_ram(Config) when is_list(Config) ->
add_table_copy_to_table_with_activated_checkpoint(ram_copies, Config).
-add_table_copy_to_table_with_activated_checkpoint_disc(suite) -> [];
-add_table_copy_to_table_with_activated_checkpoint_disc(Config) when is_list(Config) ->
+add_table_copy_to_table_checkpoint_disc(suite) -> [];
+add_table_copy_to_table_checkpoint_disc(Config) when is_list(Config) ->
add_table_copy_to_table_with_activated_checkpoint(disc_copies, Config).
-add_table_copy_to_table_with_activated_checkpoint_disc_only(suite) -> [];
-add_table_copy_to_table_with_activated_checkpoint_disc_only(Config) when is_list(Config) ->
+add_table_copy_to_table_checkpoint_disc_only(suite) -> [];
+add_table_copy_to_table_checkpoint_disc_only(Config) when is_list(Config) ->
add_table_copy_to_table_with_activated_checkpoint(disc_only_copies, Config).
add_table_copy_to_table_with_activated_checkpoint(Type,Config) ->
diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl
index abbdab48c0..a57adefbac 100644
--- a/lib/mnesia/test/mnesia_dirty_access_test.erl
+++ b/lib/mnesia/test/mnesia_dirty_access_test.erl
@@ -527,6 +527,9 @@ dirty_index_update_bag(Config, Storage) ->
?match(ok, mnesia:dirty_write(Rec1)),
?match([Rec1], mnesia:dirty_index_read(Tab, 2, ValPos)),
+ ?match(ok, mnesia:dirty_delete_object(Rec5)),
+ ?match([Rec1], mnesia:dirty_index_read(Tab, 2, ValPos)),
+
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec2) end)),
R1 = mnesia:dirty_index_read(Tab, 2, ValPos),
?match([Rec1, Rec2], lists:sort(R1)),
diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl
index 63f4146d98..9e0a8db1ae 100644
--- a/lib/mnesia/test/mnesia_evil_backup.erl
+++ b/lib/mnesia/test/mnesia_evil_backup.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
@@ -244,9 +244,9 @@ restore(Config, Op) ->
[rpc:call(Node, ?MODULE, check_tab, [Res31, ?LINE]) || Node <- Nodes],
%% Restore all tables on it's nodes
- mnesia_schema:clear_table(Tab1),
- mnesia_schema:clear_table(Tab2),
- mnesia_schema:clear_table(Tab3),
+ mnesia:clear_table(Tab1),
+ mnesia:clear_table(Tab2),
+ mnesia:clear_table(Tab3),
[mnesia:dirty_write({Tab1, N, N+1}) || N <- lists:seq(1, 11)],
[mnesia:dirty_write({Tab2, N, N+1}) || N <- lists:seq(1, 11)],
[mnesia:dirty_write({Tab3, N, N+1}) || N <- lists:seq(1, 11)],
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 668eba176f..64b61288ef 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_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
@@ -37,7 +37,8 @@ end_per_testcase(Func, Conf) ->
all() ->
[system_info, table_info, error_description,
db_node_lifecycle, evil_delete_db_node, start_and_stop,
- checkpoint, table_lifecycle, add_copy_conflict,
+ checkpoint, table_lifecycle, storage_options,
+ add_copy_conflict,
add_copy_when_going_down, replica_management,
schema_availability, local_content,
{group, table_access_modifications}, replica_location,
@@ -244,7 +245,7 @@ db_node_lifecycle(Config) when is_list(Config) ->
?match([], mnesia_test_lib:start_mnesia(AllNodes)),
?match([SNs, SNs, SNs],
- lists:map({lists, sort},
+ lists:map(fun lists:sort/1,
element(1, rpc:multicall(AllNodes, mnesia, table_info,
[schema, disc_copies])))),
@@ -259,7 +260,7 @@ db_node_lifecycle(Config) when is_list(Config) ->
mnesia:change_table_copy_type(schema, Node2, disc_copies)),
?match([SNs, SNs, SNs],
- lists:map({lists, sort},
+ lists:map(fun lists:sort/1,
element(1, rpc:multicall(AllNodes, mnesia, table_info,
[schema, disc_copies])))),
@@ -462,7 +463,7 @@ table_lifecycle(Config) when is_list(Config) ->
?match({atomic, ok}, mnesia:create_table([{name, already_exists},
{ram_copies, [Node1]}])),
?match({aborted, Reason23 } when element(1, Reason23) ==already_exists,
- mnesia:create_table([{name, already_exists},
+ mnesia:create_table([{name, already_exists},
{ram_copies, [Node1]}])),
?match({aborted, Reason21 } when element(1, Reason21) == bad_type,
mnesia:create_table([{name, bad_node}, {ram_copies, ["foo"]}])),
@@ -520,12 +521,57 @@ table_lifecycle(Config) when is_list(Config) ->
?match({atomic, ok},
mnesia:create_table([{name, create_with_index}, {index, [3]},
{ram_copies, [Node1]}])),
- ets:new(ets_table, [named_table]),
+ ets:new(ets_table, [named_table]),
?match({aborted, _}, mnesia:create_table(ets_table, [{ram_copies, Nodes}])),
+ ?match({aborted, _}, mnesia:create_table(ets_table, [{ram_copies, [Node1]}])),
+ ets:delete(ets_table),
+ ?match({atomic, ok}, mnesia:create_table(ets_table, [{ram_copies, [Node1]}])),
+ ?match(Node1, rpc:call(Node1, mnesia_lib, val, [{ets_table,where_to_read}])),
+ ?match(Node1, rpc:call(Node2, mnesia_lib, val, [{ets_table,where_to_read}])),
+ ?match({atomic, ok}, mnesia:change_table_copy_type(ets_table, Node1, disc_only_copies)),
+ ?match(Node1, rpc:call(Node2, mnesia_lib, val, [{ets_table,where_to_read}])),
+
+ ?verify_mnesia(Nodes, []).
+
+
+storage_options(suite) -> [];
+storage_options(Config) when is_list(Config) ->
+ [N1,N2,N3] = Nodes = ?acquire_nodes(3, Config),
+
+ ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,foobar}]}])),
+ ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,[foobar]}]}])),
+ ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,[duplicate_bag]}]}])),
+ ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{dets,[{type,bag}]}]}])),
+
+ ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [N1]},
+ {disc_only_copies, [N2]},
+ {storage_properties,
+ [{ets,[compressed]},
+ {dets, [{auto_save, 5000}]} ]}])),
+ ?match(true, ets:info(a, compressed)),
+ ?match(5000, rpc:call(N2, dets, info, [a, auto_save])),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([{a,1,1}], mnesia:dirty_read({a,1})),
+ mnesia:dump_log(),
+ W2C1 = [{N2, disc_only_copies}, {N1, ram_copies}],
+ ?match(W2C1, lists:sort(rpc:call(N2, mnesia_lib, val, [{a, where_to_commit}]))),
+ ?match(W2C1, lists:sort(rpc:call(N3, mnesia_lib, val, [{a, where_to_commit}]))),
+ ?match({atomic,ok}, mnesia:change_table_copy_type(a, N1, disc_only_copies)),
+ W2C2 = [{N2, disc_only_copies}, {N1, disc_only_copies}],
+ ?match(W2C2, lists:sort(rpc:call(N2, mnesia_lib, val, [{a, where_to_commit}]))),
+ ?match(W2C2, lists:sort(rpc:call(N3, mnesia_lib, val, [{a, where_to_commit}]))),
+ ?match(undefined, ets:info(a, compressed)),
+ ?match(5000, dets:info(a, auto_save)),
+ ?match({atomic,ok}, mnesia:change_table_copy_type(a, N1, disc_copies)),
+ ?match(true, ets:info(a, compressed)),
?verify_mnesia(Nodes, []).
+
+
+
+
add_copy_conflict(suite) -> [];
add_copy_conflict(doc) ->
["Verify that OTP-5065 doesn't happen again, whitebox testing"];
@@ -1795,7 +1841,7 @@ subscribe_extended(Config) when is_list(Config) ->
?match({mnesia_table_event, {delete, schema, {schema, Tab1}, [{schema, Tab1, _}],_}}, recv_event()),
?match({mnesia_table_event, {write, schema, {schema, Tab1, _}, [], _}}, recv_event()),
- ?match({atomic, ok}, mnesia_schema:clear_table(Tab2)),
+ ?match({atomic, ok}, mnesia:clear_table(Tab2)),
?match({mnesia_table_event, {delete, schema, {schema, Tab2}, [{schema, Tab2, _}],_}},
recv_event()),
?match({mnesia_table_event, {write, schema, {schema, Tab2, _}, [], _}}, recv_event()),
diff --git a/lib/mnesia/test/mnesia_frag_hash_test.erl b/lib/mnesia/test/mnesia_frag_hash_test.erl
new file mode 100644
index 0000000000..095d25e74f
--- /dev/null
+++ b/lib/mnesia/test/mnesia_frag_hash_test.erl
@@ -0,0 +1,94 @@
+-module(mnesia_frag_hash_test).
+
+-export([test/0]).
+
+-define(NUM_FRAGS, 20).
+-define(NUM_KEYS, 10000).
+
+-record(hash_state,
+ {n_fragments,
+ next_n_to_split,
+ n_doubles,
+ function}).
+
+% OLD mnesia_frag_hash:key_to_frag_number/2.
+old_key_to_frag_number(#hash_state{function = phash, next_n_to_split = SplitN, n_doubles = L}, Key) ->
+ P = SplitN,
+ A = erlang:phash(Key, power2(L)),
+ if
+ A < P ->
+ erlang:phash(Key, power2(L + 1));
+ true ->
+ A
+ end;
+old_key_to_frag_number(#hash_state{function = phash2, next_n_to_split = SplitN, n_doubles = L}, Key) ->
+ P = SplitN,
+ A = erlang:phash2(Key, power2(L)) + 1,
+ if
+ A < P ->
+ erlang:phash2(Key, power2(L + 1)) + 1;
+ true ->
+ A
+ end;
+old_key_to_frag_number(OldState, Key) ->
+ State = convert_old_state(OldState),
+ old_key_to_frag_number(State, Key).
+
+
+% NEW mnesia_frag_hash:key_to_frag_number/2.
+new_key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
+ A = erlang:phash(Key, power2(L + 1)),
+ if
+ A > N ->
+ A - power2(L);
+ true ->
+ A
+ end;
+new_key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
+ A = erlang:phash2(Key, power2(L + 1)) + 1,
+ if
+ A > N ->
+ A - power2(L);
+ true ->
+ A
+ end;
+new_key_to_frag_number(OldState, Key) ->
+ State = convert_old_state(OldState),
+ new_key_to_frag_number(State, Key).
+
+
+% Helpers for key_to_frag_number functions.
+
+power2(Y) ->
+ 1 bsl Y. % trunc(math:pow(2, Y)).
+
+convert_old_state({hash_state, N, P, L}) ->
+ #hash_state{n_fragments = N,
+ next_n_to_split = P,
+ n_doubles = L,
+ function = phash}.
+
+
+test() ->
+ test2(mnesia_frag_hash:init_state(undefined, undefined)), % phash2
+ test2({hash_state, 1, 1, 0}). % phash
+
+test2(I) ->
+ test_keys(I),
+ lists:foldl(
+ fun(_, S) -> test_frag(S) end,
+ I, lists:seq(1, ?NUM_FRAGS)),
+ ok.
+
+test_frag(State) ->
+ {State2,_,_} = mnesia_frag_hash:add_frag(State),
+ test_keys(State2),
+ State2.
+
+test_keys(State) ->
+ [test_key(State, Key) || Key <- lists:seq(1, ?NUM_KEYS)].
+
+test_key(State, Key) ->
+ Old = old_key_to_frag_number(State, Key),
+ New = new_key_to_frag_number(State, Key),
+ Old = New.
diff --git a/lib/mnesia/test/mnesia_install_test.erl b/lib/mnesia/test/mnesia_install_test.erl
index 5d55fcac0e..06d53d3912 100644
--- a/lib/mnesia/test/mnesia_install_test.erl
+++ b/lib/mnesia/test/mnesia_install_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
@@ -205,7 +205,7 @@ silly_upgrade(Config) when is_list(Config) ->
?match(ok, mnesia:install_fallback(Bup2)),
file:delete(Bup2),
%% Will generate intentional crash, fatal error
- ?match([], mnesia_test_lib:stop_mnesia([Node2])),
+ ?match([], mnesia_test_lib:stop_mnesia([Node2])),
wait_till_dead([Node1, Node2]),
?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [Tab1, Tab2])),
?match(match, verify_state(Tab1, Tab2, CpState)),
@@ -213,22 +213,29 @@ silly_upgrade(Config) when is_list(Config) ->
?match(ok, mnesia:install_fallback(Bup)),
file:delete(Bup),
%% Will generate intentional crash, fatal error
- ?match([], mnesia_test_lib:stop_mnesia([Node1, Node2])),
+ ?match([], mnesia_test_lib:stop_mnesia([Node1, Node2])),
wait_till_dead([Node1, Node2]),
?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [Tab1, Tab2])),
CpState2 = [X || X <- CpState, element(1, X) /= Tab1],
?match(match, verify_state(Tab1, Tab2, CpState2)),
?verify_mnesia(Nodes, []).
-wait_till_dead([]) -> ok;
-wait_till_dead([N|Ns]) ->
+wait_till_dead([]) ->
+ ok; %% timer:sleep(5);
+wait_till_dead(Repeat = [N|Ns]) ->
Apps = rpc:call(N, application, which_applications, []),
case lists:keymember(mnesia, 1, Apps) of
- true ->
+ true ->
timer:sleep(10),
- wait_till_dead([N|Ns]);
- false ->
- wait_till_dead(Ns)
+ wait_till_dead(Repeat);
+ false ->
+ case rpc:call(N, erlang, whereis, [mnesia_monitor]) of
+ undefined ->
+ wait_till_dead(Ns);
+ _ ->
+ timer:sleep(10),
+ wait_till_dead(Repeat)
+ end
end.
add_some_records(Tab1, Tab2, Old) ->
diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl
index 9da45975d5..ba5bf84e24 100644
--- a/lib/mnesia/test/mnesia_test_lib.erl
+++ b/lib/mnesia/test/mnesia_test_lib.erl
@@ -99,7 +99,7 @@
slave_start_link/0,
slave_start_link/1,
slave_sup/0,
-
+
start_mnesia/1,
start_mnesia/2,
start_appls/2,
@@ -131,7 +131,7 @@
struct/1,
init_per_testcase/2,
end_per_testcase/2,
- kill_tc/2
+ kill_tc/2
]).
-include("mnesia_test_lib.hrl").
@@ -187,7 +187,7 @@ verbose(Format, Args, File, Line) ->
ok
end
end.
-
+
-record('REASON', {file, line, desc}).
error(Format, Args, File, Line) ->
@@ -196,9 +196,9 @@ error(Format, Args, File, Line) ->
line = Line,
desc = Args},
case global:whereis_name(mnesia_test_case_sup) of
- undefined ->
+ undefined ->
ignore;
- Pid ->
+ Pid ->
Pid ! Fail
%% global:send(mnesia_test_case_sup, Fail),
end,
@@ -217,7 +217,7 @@ storage_type(Default, Config) ->
default_config() ->
[{nodes, default_nodes()}].
-default_nodes() ->
+default_nodes() ->
mk_nodes(3, []).
mk_nodes(0, Nodes) ->
@@ -231,7 +231,7 @@ mk_nodes(N, Nodes) when N > 0 ->
mk_node(N, Name, Host) ->
list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])).
-
+
slave_start_link() ->
slave_start_link(node()).
@@ -247,11 +247,11 @@ slave_start_link(Host, Name) ->
slave_start_link(Host, Name, Retries) ->
Debug = atom_to_list(mnesia:system_info(debug)),
- Args = "-mnesia debug " ++ Debug ++
+ Args = "-mnesia debug " ++ Debug ++
+ " -pa " ++
+ filename:dirname(code:which(?MODULE)) ++
" -pa " ++
- filename:dirname(code:which(?MODULE)) ++
- " -pa " ++
- filename:dirname(code:which(mnesia)),
+ filename:dirname(code:which(mnesia)),
case starter(Host, Name, Args) of
{ok, NewNode} ->
?match(pong, net_adm:ping(NewNode)),
@@ -264,8 +264,8 @@ slave_start_link(Host, Name, Retries) ->
{ok, NewNode};
{error, Reason} when Retries == 0->
{error, Reason};
- {error, Reason} ->
- io:format("Could not start slavenode ~p ~p retrying~n",
+ {error, Reason} ->
+ io:format("Could not start slavenode ~p ~p retrying~n",
[{Host, Name, Args}, Reason]),
timer:sleep(500),
slave_start_link(Host, Name, Retries - 1)
@@ -284,7 +284,7 @@ starter(Host, Name, Args) ->
slave_sup() ->
process_flag(trap_exit, true),
receive
- {'EXIT', _, _} ->
+ {'EXIT', _, _} ->
case os:type() of
vxworks ->
erlang:halt();
@@ -292,7 +292,7 @@ slave_sup() ->
ignore
end
end.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Index the test case structure
@@ -305,7 +305,7 @@ doc(TestCases) when is_list(TestCases) ->
io:format(Fd, "<TITLE>Test specification for ~p</TITLE>.~n", [TestCases]),
io:format(Fd, "<H1>Test specification for ~p</H1>~n", [TestCases]),
io:format(Fd, "Test cases which not are implemented yet are written in <B>bold face</B>.~n~n", []),
-
+
io:format(Fd, "<BR><BR>~n", []),
io:format(Fd, "~n<DL>~n", []),
do_doc(Fd, TestCases, []),
@@ -349,7 +349,7 @@ do_doc(Fd, Module, TestCase, List) ->
print_doc(Fd, Mod, Fun, Head) ->
case catch (apply(Mod, Fun, [doc])) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
io:format(Fd, "<DT>~s</DT>~n", [Head]);
Doc when is_list(Doc) ->
io:format(Fd, "<DT><U>~s</U><BR><DD>~n", [Head]),
@@ -428,10 +428,10 @@ test_driver({Module, TestCase}, Config) ->
_ ->
log("Eval test case: ~w~n", [{Module, TestCase}]),
try timer:tc(?MODULE, eval_test_case, [Module, TestCase, Config]) of
- {T, Res} ->
+ {T, Res} ->
log("Tested ~w in ~w sec~n", [TestCase, T div Sec]),
{T div Sec, Res}
- catch error:function_clause ->
+ catch error:function_clause ->
log("<WARNING> Test case ~w NYI~n", [{Module, TestCase}]),
{0, {skip, {Module, TestCase}, "NYI"}}
end
@@ -472,13 +472,13 @@ get_suite(Module, TestCase, Config) ->
%% Returns a list (possibly empty) or the atom 'NYI'
get_suite(Mod, {group, Suite}) ->
- try
+ try
Groups = Mod:groups(),
{_, _, TCList} = lists:keyfind(Suite, 1, Groups),
TCList
catch
_:Reason ->
- io:format("Not implemented ~p ~p (~p ~p)~n",
+ io:format("Not implemented ~p ~p (~p ~p)~n",
[Mod,Suite,Reason, erlang:get_stacktrace()]),
'NYI'
end;
@@ -487,7 +487,7 @@ get_suite(Mod, all) ->
{'EXIT', _} -> 'NYI';
List when is_list(List) -> List
end;
-get_suite(_Mod, _Fun) ->
+get_suite(_Mod, _Fun) ->
[].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -511,7 +511,7 @@ wait_for_evaluator(Pid, Mod, Fun, Config) ->
receive
{'EXIT', Pid, {test_case_ok, _PidRes}} ->
Errors = flush(),
- Res =
+ Res =
case Errors of
[] -> ok;
Errors -> failed
@@ -531,7 +531,7 @@ wait_for_evaluator(Pid, Mod, Fun, Config) ->
test_case_evaluator(Mod, Fun, [Config]) ->
NewConfig = Mod:init_per_testcase(Fun, Config),
- try
+ try
R = apply(Mod, Fun, [NewConfig]),
Mod:end_per_testcase(Fun, NewConfig),
exit({test_case_ok, R})
@@ -588,7 +588,7 @@ mapl(_Fun, []) ->
diskless(Config) ->
case lists:keysearch(diskless, 1, Config) of
- {value, {diskless, true}} ->
+ {value, {diskless, true}} ->
true;
_Else ->
false
@@ -634,7 +634,7 @@ sync_trans_tid_serial(Nodes) ->
select_nodes(N, Config, File, Line) ->
prepare_test_case([], N, Config, File, Line).
-
+
prepare_test_case(Actions, N, Config, File, Line) ->
NodeList1 = lookup_config(nodes, Config),
NodeList2 = lookup_config(nodenames, Config), %% For testserver
@@ -666,10 +666,10 @@ do_prepare([delete_schema | Actions], Selected, All, Config, File, Line) ->
true ->
skip;
false ->
- Del = fun(Node) ->
+ Del = fun(Node) ->
case mnesia:delete_schema([Node]) of
ok -> ok;
- {error, {"All nodes not running",_}} ->
+ {error, {"All nodes not running",_}} ->
ok;
Else ->
?log("Delete schema error ~p ~n", [Else])
@@ -680,7 +680,7 @@ do_prepare([delete_schema | Actions], Selected, All, Config, File, Line) ->
do_prepare(Actions, Selected, All, Config, File, Line);
do_prepare([create_schema | Actions], Selected, All, Config, File, Line) ->
case diskless(Config) of
- true ->
+ true ->
skip;
_Else ->
case mnesia:create_schema(Selected) of
@@ -705,12 +705,12 @@ set_kill_timer(Config) ->
case init:get_argument(mnesia_test_timeout) of
{ok, _ } -> ok;
_ ->
- Time0 =
+ Time0 =
case lookup_config(tc_timeout, Config) of
[] -> timer:minutes(5);
ConfigTime when is_integer(ConfigTime) -> ConfigTime
end,
- Mul = try
+ Mul = try
test_server:timetrap_scale_factor()
catch _:_ -> 1 end,
(catch test_server:timetrap(Mul*Time0 + 1000)),
@@ -718,7 +718,7 @@ set_kill_timer(Config) ->
end.
kill_tc(Pid, Time) ->
- receive
+ receive
after Time ->
case process_info(Pid) of
undefined -> ok;
@@ -739,10 +739,10 @@ kill_tc(Pid, Time) ->
exit(Pid, kill)
end
end.
-
+
append_unique([], List) -> List;
-append_unique([H|R], List) ->
+append_unique([H|R], List) ->
case lists:member(H, List) of
true -> append_unique(R, List);
false -> [H | append_unique(R, List)]
@@ -751,13 +751,13 @@ append_unique([H|R], List) ->
pick_nodes(all, Nodes, File, Line) ->
pick_nodes(length(Nodes), Nodes, File, Line);
pick_nodes(N, [H | T], File, Line) when N > 0 ->
- [H | pick_nodes(N - 1, T, File, Line)];
+ [H | pick_nodes(N - 1, T, File, Line)];
pick_nodes(0, _Nodes, _File, _Line) ->
[];
pick_nodes(N, [], File, Line) ->
?skip("Test case (~p(~p)) ignored: ~p nodes missing~n",
[File, Line, N]).
-
+
init_nodes([Node | Nodes], File, Line) ->
case net_adm:ping(Node) of
pong ->
@@ -777,7 +777,7 @@ init_nodes([Node | Nodes], File, Line) ->
init_nodes([], _File, _Line) ->
[].
-%% Returns [Name, Host]
+%% Returns [Name, Host]
node_to_name_and_host(Node) ->
string:tokens(atom_to_list(Node), [$@]).
@@ -793,7 +793,7 @@ lookup_config(Key,Config) ->
start_appls(Appls, Nodes) ->
start_appls(Appls, Nodes, [], [schema]).
-
+
start_appls(Appls, Nodes, Config) ->
start_appls(Appls, Nodes, Config, [schema]).
@@ -815,9 +815,9 @@ start_appls([], _Nodes, _Config, _Tabs) ->
remote_start(mnesia, Config, Nodes) ->
case diskless(Config) of
- true ->
- application_controller:set_env(mnesia,
- extra_db_nodes,
+ true ->
+ application_controller:set_env(mnesia,
+ extra_db_nodes,
Nodes -- [node()]),
application_controller:set_env(mnesia,
schema_location,
@@ -830,7 +830,7 @@ remote_start(mnesia, Config, Nodes) ->
end,
{node(), mnesia:start()};
remote_start(Appl, _Config, _Nodes) ->
- Res =
+ Res =
case application:start(Appl) of
{error, {already_started, Appl}} ->
ok;
@@ -842,13 +842,13 @@ remote_start(Appl, _Config, _Nodes) ->
%% Start Mnesia on all given nodes and wait for specified
%% tables to be accessible on each node. The atom all means
%% that we should wait for all tables to be loaded
-%%
+%%
%% Returns a list of error tuples {BadNode, mnesia, Reason}
start_mnesia(Nodes) ->
start_appls([mnesia], Nodes).
start_mnesia(Nodes, Tabs) when is_list(Nodes) ->
start_appls([mnesia], Nodes, [], Tabs).
-
+
%% Wait for the tables to be accessible from all nodes in the list
%% and that all nodes are aware of that the other nodes also ...
sync_tables(Nodes, Tabs) ->
@@ -924,26 +924,26 @@ verify_nodes([Tab| Tabs], N) ->
mnesia:table_info(Tab, ram_copies),
Local = mnesia:table_info(Tab, local_content),
case Copies -- Nodes of
- [] ->
+ [] ->
verify_nodes(Tabs, 0);
_Else when Local == true, Nodes /= [] ->
verify_nodes(Tabs, 0);
Else ->
- N2 =
+ N2 =
if
- N > 20 ->
- log("<>WARNING<> ~w Waiting for table: ~p on ~p ~n",
+ N > 20 ->
+ log("<>WARNING<> ~w Waiting for table: ~p on ~p ~n",
[node(), Tab, Else]),
0;
true -> N+1
- end,
+ end,
timer:sleep(500),
verify_nodes([Tab| Tabs], N2)
end.
%% Nicely stop Mnesia on all given nodes
-%%
+%%
%% Returns a list of error tuples {BadNode, Reason}
stop_mnesia(Nodes) when is_list(Nodes) ->
stop_appls([mnesia], Nodes).
@@ -1047,7 +1047,7 @@ verify_replica_location(Tab, DiscOnly0, Ram0, Disc0, AliveNodes0) ->
Read = ignore_dead(DiscOnly ++ Ram ++ Disc, AliveNodes),
This = node(),
- timer:sleep(100),
+ timer:sleep(100),
S1 = ?match(AliveNodes, lists:sort(mnesia:system_info(running_db_nodes))),
S2 = ?match(DiscOnly, lists:sort(mnesia:table_info(Tab, disc_only_copies))),
@@ -1080,7 +1080,7 @@ do_remote_activate_debug_fun(From, I, F, C, File, Line) ->
timer:sleep(infinity). % Dies whenever the test process dies !!
-sort(L) when is_list(L) ->
+sort(L) when is_list(L) ->
lists:sort(L);
sort({atomic, L}) when is_list(L) ->
{atomic, lists:sort(L)};
diff --git a/lib/mnesia/test/mnesia_test_lib.hrl b/lib/mnesia/test/mnesia_test_lib.hrl
index fc377dbd2c..281634c239 100644
--- a/lib/mnesia/test/mnesia_test_lib.hrl
+++ b/lib/mnesia/test/mnesia_test_lib.hrl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -112,7 +112,7 @@
-define(remote_deactivate_debug_fun(N, I),
rpc:call(N, mnesia_lib, deactivate_debug_fun, [I, ?FILE, ?LINE])).
--define(is_debug_compiled,
+-define(is_debug_compiled,
case mnesia_lib:is_debug_compiled() of
false ->
?skip("Mnesia is not debug compiled, test case ignored.~n", []);
@@ -120,7 +120,7 @@
ok
end).
--define(needs_disc(Config),
+-define(needs_disc(Config),
case mnesia_test_lib:diskless(Config) of
false ->
ok;
@@ -128,5 +128,5 @@
?skip("Must have disc, test case ignored.~n", [])
end).
--define(verify_mnesia(Ups, Downs),
+-define(verify_mnesia(Ups, Downs),
mnesia_test_lib:verify_mnesia(Ups, Downs, ?FILE, ?LINE)).
diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl
index ca3f0fbf49..73c3fe0362 100644
--- a/lib/mnesia/test/mnesia_trans_access_test.erl
+++ b/lib/mnesia/test/mnesia_trans_access_test.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -31,22 +31,22 @@ end_per_testcase(Func, Conf) ->
-define(receive_messages(Msgs), mnesia_recovery_test:receive_messages(Msgs, ?FILE, ?LINE)).
-% First Some debug logging
+% First Some debug logging
-define(dgb, true).
-ifdef(dgb).
-define(dl(X, Y), ?verbose("**TRACING: " ++ X ++ "**~n", Y)).
--else.
+-else.
-define(dl(X, Y), ok).
-endif.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-all() ->
+all() ->
[write, read, wread, delete, delete_object,
match_object, select, select14, all_keys, transaction,
{group, nested_activities}, {group, index_tabs},
{group, index_lifecycle}].
-groups() ->
+groups() ->
[{nested_activities, [],
[basic_nested, {group, nested_transactions},
mix_of_nested_activities]},
@@ -80,128 +80,133 @@ end_per_group(_GroupName, Config) ->
write(suite) -> [];
write(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = write,
- Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
-
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:write([]) end)),
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:write({Tab, 2}) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:write({foo, 2}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:write({Tab, 1, 2})),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = write,
+ Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:write([]) end)),
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 2}) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:write({foo, 2}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:write({Tab, 1, 2})),
?verify_mnesia(Nodes, []).
%% Read records
read(suite) -> [];
read(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = read,
- Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
-
- OneRec = {Tab, 1, 2},
- TwoRec = {Tab, 1, 3},
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:read([]) end)),
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:read({Tab}) end)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = read,
+ Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+
+ OneRec = {Tab, 1, 2},
+ TwoRec = {Tab, 1, 3},
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:read([]) end)),
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:read({Tab}) end)),
?match({aborted, {bad_type, _}}
- , mnesia:transaction(fun() -> mnesia:read(OneRec) end)),
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, [OneRec]},
- mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
- ?match({atomic, [OneRec, TwoRec]},
- mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:read({Tab, 1})),
+ , mnesia:transaction(fun() -> mnesia:read(OneRec) end)),
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, [OneRec]},
+ mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
+ ?match({atomic, [OneRec, TwoRec]},
+ mnesia:transaction(fun() -> mnesia:read({Tab, 1}) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:read({Tab, 1})),
?verify_mnesia(Nodes, []).
%% Read records and set write lock
wread(suite) -> [];
wread(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = wread,
- Schema = [{name, Tab}, {type, set}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
-
- OneRec = {Tab, 1, 2},
- TwoRec = {Tab, 1, 3},
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:wread([]) end)),
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:wread({Tab}) end)),
+ [_N1,N2] = Nodes = ?acquire_nodes(2, Config),
+ Tab = wread,
+ Schema = [{name, Tab}, {type, set}, {attributes, [k, v]}, {ram_copies, Nodes}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+
+ OneRec = {Tab, 1, 2},
+ TwoRec = {Tab, 1, 3},
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:wread([]) end)),
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:wread({Tab}) end)),
?match({aborted, {bad_type, _}}
- , mnesia:transaction(fun() -> mnesia:wread(OneRec) end)),
-
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
-
- ?match({atomic, [OneRec]},
- mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
- ?match({atomic, [TwoRec]},
- mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:wread({Tab, 1})),
+ , mnesia:transaction(fun() -> mnesia:wread(OneRec) end)),
+
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+
+ ?match({atomic, [OneRec]},
+ mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
+ ?match({atomic, [TwoRec]},
+ mnesia:transaction(fun() -> mnesia:wread({Tab, 1}) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:wread({Tab, 1})),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Tab, {Tab, 42, a}, sticky_write) end)),
+ ?match({atomic, [{Tab,42, a}]},
+ rpc:call(N2, mnesia, transaction, [fun() -> mnesia:wread({Tab, 42}) end])),
?verify_mnesia(Nodes, []).
%% Delete record
delete(suite) -> [];
delete(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = delete,
- Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
-
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:delete([]) end)),
- ?match({aborted, {bad_type, _}},
- mnesia:transaction(fun() -> mnesia:delete({Tab}) end)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = delete,
+ Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:delete([]) end)),
+ ?match({aborted, {bad_type, _}},
+ mnesia:transaction(fun() -> mnesia:delete({Tab}) end)),
?match({aborted, {bad_type, _}}
- , mnesia:transaction(fun() -> mnesia:delete({Tab, 1, 2}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:delete({Tab, 1})),
+ , mnesia:transaction(fun() -> mnesia:delete({Tab, 1, 2}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 1, 2}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:delete({Tab, 1}) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:delete({Tab, 1})),
?verify_mnesia(Nodes, []).
%% Delete matching record
delete_object(suite) -> [];
delete_object(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = delete_object,
- Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = delete_object,
+ Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
- OneRec = {Tab, 1, 2},
+ OneRec = {Tab, 1, 2},
?match({aborted, {bad_type, _}},
mnesia:transaction(fun() -> mnesia:delete_object([]) end)),
?match({aborted, {bad_type, _}},
@@ -215,17 +220,17 @@ delete_object(Config) when is_list(Config) ->
?match({atomic, ok},
mnesia:transaction(fun() -> mnesia:delete_object(OneRec) end)),
?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, ok},
mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, ok},
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, ok},
mnesia:transaction(fun() -> mnesia:delete_object(OneRec) end)),
-
+
?match({'EXIT', {aborted, no_transaction}}, mnesia:delete_object(OneRec)),
- ?match({aborted, {bad_type, Tab, _}},
+ ?match({aborted, {bad_type, Tab, _}},
mnesia:transaction(fun() -> mnesia:delete_object({Tab, {['_']}, 21}) end)),
- ?match({aborted, {bad_type, Tab, _}},
+ ?match({aborted, {bad_type, Tab, _}},
mnesia:transaction(fun() -> mnesia:delete_object({Tab, {['$5']}, 21}) end)),
?verify_mnesia(Nodes, []).
@@ -234,108 +239,108 @@ delete_object(Config) when is_list(Config) ->
match_object(suite) -> [];
match_object(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = match,
- Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
-
- OneRec = {Tab, 1, 2},
- OnePat = {Tab, '$1', 2},
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, [OneRec]},
- mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)),
-
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:match_object({foo, '$1', 2}) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:match_object({[], '$1', 2}) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:match_object(OnePat)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = match,
+ Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+
+ OneRec = {Tab, 1, 2},
+ OnePat = {Tab, '$1', 2},
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, [OneRec]},
+ mnesia:transaction(fun() -> mnesia:match_object(OnePat) end)),
+
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:match_object({foo, '$1', 2}) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:match_object({[], '$1', 2}) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:match_object(OnePat)),
?verify_mnesia(Nodes, []).
%% select
select(suite) -> [];
select(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = match,
- Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = match,
+ Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
- OneRec = {Tab, 1, 2},
- TwoRec = {Tab, 2, 3},
+ OneRec = {Tab, 1, 2},
+ TwoRec = {Tab, 2, 3},
OnePat = [{{Tab, '$1', 2}, [], ['$_']}],
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
- ?match({atomic, [OneRec]},
- mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)),
-
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:select(Tab, {match, '$1', 2}) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:select(Tab, [{'_', [], '$1'}]) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat)),
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
+ ?match({atomic, [OneRec]},
+ mnesia:transaction(fun() -> mnesia:select(Tab, OnePat) end)),
+
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:select(Tab, {match, '$1', 2}) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:select(Tab, [{'_', [], '$1'}]) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat)),
?verify_mnesia(Nodes, []).
%% more select
select14(suite) -> [];
select14(Config) when is_list(Config) ->
- [Node1,Node2] = Nodes = ?acquire_nodes(2, Config),
- Tab1 = select14_ets,
- Tab2 = select14_dets,
- Tab3 = select14_remote,
- Tab4 = select14_remote_dets,
- Schemas = [[{name, Tab1}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- [{name, Tab2}, {attributes, [k, v]}, {disc_only_copies, [Node1]}],
+ [Node1,Node2] = Nodes = ?acquire_nodes(2, Config),
+ Tab1 = select14_ets,
+ Tab2 = select14_dets,
+ Tab3 = select14_remote,
+ Tab4 = select14_remote_dets,
+ Schemas = [[{name, Tab1}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ [{name, Tab2}, {attributes, [k, v]}, {disc_only_copies, [Node1]}],
[{name, Tab3}, {attributes, [k, v]}, {ram_copies, [Node2]}],
- [{name, Tab4}, {attributes, [k, v]}, {disc_only_copies, [Node2]}]],
+ [{name, Tab4}, {attributes, [k, v]}, {disc_only_copies, [Node2]}]],
[?match({atomic, ok}, mnesia:create_table(Schema)) || Schema <- Schemas],
%% Some Helpers
Trans = fun(Fun) -> mnesia:transaction(Fun) end,
LoopHelp = fun('$end_of_table',_) -> [];
- ({Recs,Cont},Fun) ->
+ ({Recs,Cont},Fun) ->
Sel = mnesia:select(Cont),
Recs ++ Fun(Sel, Fun)
end,
- Loop = fun(Table,Pattern) ->
+ Loop = fun(Table,Pattern) ->
Sel = mnesia:select(Table, Pattern, 1, read),
Res = LoopHelp(Sel,LoopHelp),
case mnesia:table_info(Table, type) of
ordered_set -> Res;
_ -> lists:sort(Res)
- end
+ end
end,
- Test =
+ Test =
fun(Tab) ->
- OneRec = {Tab, 1, 2},
- TwoRec = {Tab, 2, 3},
+ OneRec = {Tab, 1, 2},
+ TwoRec = {Tab, 2, 3},
OnePat = [{{Tab, '$1', 2}, [], ['$_']}],
All = [OneRec,TwoRec],
AllPat = [{'_', [], ['$_']}],
- ?match({atomic, []}, Trans(fun() -> Loop(Tab, OnePat) end)),
- ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
- ?match({atomic, [OneRec]}, Trans(fun() -> Loop(Tab, OnePat) end)),
- ?match({atomic, All}, Trans(fun() -> Loop(Tab, AllPat) end)),
-
+ ?match({atomic, []}, Trans(fun() -> Loop(Tab, OnePat) end)),
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(TwoRec) end)),
+ ?match({atomic, [OneRec]}, Trans(fun() -> Loop(Tab, OnePat) end)),
+ ?match({atomic, All}, Trans(fun() -> Loop(Tab, AllPat) end)),
+
{atomic,{_, Cont}} = Trans(fun() -> mnesia:select(Tab, OnePat, 1, read) end),
?match({aborted, wrong_transaction}, Trans(fun() -> mnesia:select(Cont) end)),
-
- ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, {match, '$1', 2},1,read) end)),
- ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, [{'_', [], '$1'}],1,read) end)),
- ?match({aborted, _}, Trans(fun() -> mnesia:select(sune) end)),
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat,1,read)),
- ?match({aborted, {badarg,sune}},
+
+ ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, {match, '$1', 2},1,read) end)),
+ ?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, [{'_', [], '$1'}],1,read) end)),
+ ?match({aborted, _}, Trans(fun() -> mnesia:select(sune) end)),
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:select(Tab, OnePat,1,read)),
+ ?match({aborted, {badarg,sune}},
Trans(fun() -> mnesia:select(sune) end))
end,
Test(Tab1),
@@ -349,28 +354,28 @@ select14(Config) when is_list(Config) ->
all_keys(suite) ->[];
all_keys(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = all_keys,
- Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
-
- Write = fun() -> mnesia:write({Tab, 14, 4}) end,
- AllKeys = fun() -> mnesia:all_keys(Tab) end,
-
- ?match({atomic, []}, mnesia:transaction(AllKeys)),
-
- ?match({atomic, ok}, mnesia:transaction(Write)),
- ?match({atomic, [14]}, mnesia:transaction(AllKeys)),
-
- ?match({atomic, ok}, mnesia:transaction(Write)),
- ?match({atomic, [14]}, mnesia:transaction(AllKeys)),
-
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:all_keys(foo) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:all_keys([]) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:all_keys(Tab)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = all_keys,
+ Schema = [{name, Tab}, {type, bag}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+
+ Write = fun() -> mnesia:write({Tab, 14, 4}) end,
+ AllKeys = fun() -> mnesia:all_keys(Tab) end,
+
+ ?match({atomic, []}, mnesia:transaction(AllKeys)),
+
+ ?match({atomic, ok}, mnesia:transaction(Write)),
+ ?match({atomic, [14]}, mnesia:transaction(AllKeys)),
+
+ ?match({atomic, ok}, mnesia:transaction(Write)),
+ ?match({atomic, [14]}, mnesia:transaction(AllKeys)),
+
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:all_keys(foo) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:all_keys([]) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:all_keys(Tab)),
?verify_mnesia(Nodes, []).
@@ -436,49 +441,49 @@ transaction(Config) when is_list(Config) ->
basic_nested(doc) -> ["Test the basic functionality of nested transactions"];
basic_nested(suite) -> [];
basic_nested(Config) when is_list(Config) ->
- Nodes = ?acquire_nodes(3, Config),
- Args = [{ram_copies, Nodes},
- {attributes, record_info(fields, ntab)}],
- ?match({atomic, ok}, mnesia:create_table(ntab, Args)),
- do_nested(top),
+ Nodes = ?acquire_nodes(3, Config),
+ Args = [{ram_copies, Nodes},
+ {attributes, record_info(fields, ntab)}],
+ ?match({atomic, ok}, mnesia:create_table(ntab, Args)),
+ do_nested(top),
case mnesia_test_lib:diskless(Config) of
false ->
lists:foreach(fun(N) ->
- ?match({atomic, ok},
+ ?match({atomic, ok},
mnesia:change_table_copy_type(ntab, N, disc_only_copies))
- end, Nodes),
+ end, Nodes),
do_nested(top);
- true ->
+ true ->
skip
end,
?verify_mnesia(Nodes, []).
do_nested(How) ->
F1 = fun() ->
- mnesia:write(#ntab{a= 1}),
+ mnesia:write(#ntab{a= 1}),
mnesia:write(#ntab{a= 2})
- end,
+ end,
F2 = fun() ->
mnesia:read({ntab, 1})
- end,
- ?match({atomic, ok}, mnesia:transaction(F1)),
- ?match({atomic, _}, mnesia:transaction(F2)),
+ end,
+ ?match({atomic, ok}, mnesia:transaction(F1)),
+ ?match({atomic, _}, mnesia:transaction(F2)),
- ?match({atomic, {aborted, _}},
- mnesia:transaction(fun() -> n_f1(),
+ ?match({atomic, {aborted, _}},
+ mnesia:transaction(fun() -> n_f1(),
mnesia:transaction(fun() -> n_f2() end)
- end)),
+ end)),
- ?match({atomic, {aborted, _}},
- mnesia:transaction(fun() -> n_f1(),
+ ?match({atomic, {aborted, _}},
+ mnesia:transaction(fun() -> n_f1(),
mnesia:transaction(fun() -> n_f3() end)
- end)),
- ?match({atomic, {atomic, [#ntab{a = 5}]}},
- mnesia:transaction(fun() -> mnesia:write(#ntab{a = 5}),
+ end)),
+ ?match({atomic, {atomic, [#ntab{a = 5}]}},
+ mnesia:transaction(fun() -> mnesia:write(#ntab{a = 5}),
mnesia:transaction(fun() -> n_f4() end)
- end)),
- Cyclic = fun() -> mnesia:abort({cyclic,a,a,a,a,a}) end, %% Ugly
- NodeNotR = fun() -> mnesia:abort({node_not_running, testNode}) end,
+ end)),
+ Cyclic = fun() -> mnesia:abort({cyclic,a,a,a,a,a}) end, %% Ugly
+ NodeNotR = fun() -> mnesia:abort({node_not_running, testNode}) end,
TestAbort = fun(Fun) ->
case get(restart_counter) of
@@ -490,46 +495,46 @@ do_nested(How) ->
ok
end
end,
-
- ?match({atomic,{atomic,ok}},
+
+ ?match({atomic,{atomic,ok}},
mnesia:transaction(fun()->mnesia:transaction(TestAbort,
[Cyclic])end)),
-
- ?match({atomic,{atomic,ok}},
+
+ ?match({atomic,{atomic,ok}},
mnesia:transaction(fun()->mnesia:transaction(TestAbort,
[NodeNotR])end)),
-
+
%% Now try the restart thingie
case How of
- top ->
- Pids = [spawn(?MODULE, do_nested, [{spawned, self()}]),
- spawn(?MODULE, do_nested, [{spawned, self()}]),
- spawn(?MODULE, do_nested, [{spawned, self()}]),
- spawn(?MODULE, do_nested, [{spawned, self()}])],
- ?match({info, _, _}, mnesia_tm:get_info(2000)),
+ top ->
+ Pids = [spawn(?MODULE, do_nested, [{spawned, self()}]),
+ spawn(?MODULE, do_nested, [{spawned, self()}]),
+ spawn(?MODULE, do_nested, [{spawned, self()}]),
+ spawn(?MODULE, do_nested, [{spawned, self()}])],
+ ?match({info, _, _}, mnesia_tm:get_info(2000)),
lists:foreach(fun(P) -> receive
{P, ok} -> ok
end
- end, Pids),
+ end, Pids),
?match([], [Tab || Tab <- ets:all(), mnesia_trans_store == ets:info(Tab, name)]);
-
+
{spawned, Pid} ->
- ?match({info, _, _}, mnesia_tm:get_info(2000)),
+ ?match({info, _, _}, mnesia_tm:get_info(2000)),
Pid ! {self(), ok},
exit(normal)
end.
n_f1() ->
- mnesia:read({ntab, 1}),
+ mnesia:read({ntab, 1}),
mnesia:write(#ntab{a = 3}).
n_f2() ->
- mnesia:write(#ntab{a = 4}),
+ mnesia:write(#ntab{a = 4}),
erlang:error(exit_here).
n_f3() ->
- mnesia:write(#ntab{a = 4}),
+ mnesia:write(#ntab{a = 4}),
throw(funky).
n_f4() ->
@@ -555,24 +560,24 @@ nested_trans_both_dies(Config) when is_list(Config) ->
nested_transactions(Config, abort, abort).
nested_transactions(Config, Child, Father) ->
- [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config),
+ [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config),
Tab = nested_trans,
- Def =
+ Def =
case mnesia_test_lib:diskless(Config) of
true ->
[{name, Tab}, {ram_copies, Nodes}];
false ->
- [{name, Tab}, {ram_copies, [Node1]},
+ [{name, Tab}, {ram_copies, [Node1]},
{disc_copies, [Node2]}, {disc_only_copies, [Node3]}]
end,
?match({atomic, ok}, mnesia:create_table(Def)),
?match(ok, mnesia:dirty_write({Tab, father, not_updated})),
- ?match(ok, mnesia:dirty_write({Tab, child, not_updated})),
+ ?match(ok, mnesia:dirty_write({Tab, child, not_updated})),
ChildOk = fun() -> mnesia:write({Tab, child, updated}) end,
- ChildAbort = fun() ->
+ ChildAbort = fun() ->
mnesia:write({Tab, child, updated}),
erlang:error(exit_here)
end,
@@ -616,7 +621,7 @@ nested_transactions(Config, Child, Father) ->
?verify_mnesia(Nodes, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-mix_of_nested_activities(doc) ->
+mix_of_nested_activities(doc) ->
["Verify that dirty operations in a transaction are handled like ",
"normal transactions"];
mix_of_nested_activities(suite) -> [];
@@ -624,27 +629,27 @@ mix_of_nested_activities(Config) when is_list(Config) ->
[Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config),
Tab = tab,
- Def =
+ Def =
case mnesia_test_lib:diskless(Config) of
true -> [{ram_copies, Nodes}];
- false ->
- [{ram_copies, [Node1]},
- {disc_copies, [Node2]},
+ false ->
+ [{ram_copies, [Node1]},
+ {disc_copies, [Node2]},
{disc_only_copies, [Node3]}]
end,
?match({atomic, ok}, mnesia:create_table(Tab, [{type,bag}|Def])),
- Activities = [transaction, sync_transaction,
+ Activities = [transaction, sync_transaction,
ets, async_dirty, sync_dirty],
%% Make a test for all 3000 combinations
- Tests = [[A,B,C,D,E] ||
+ Tests = [[A,B,C,D,E] ||
A <- Activities,
B <- Activities,
C <- Activities,
D <- Activities,
E <- Activities],
- Foreach =
- fun(Test,No) ->
+ Foreach =
+ fun(Test,No) ->
Result = lists:reverse(Test),
?match({No,Result},{No,catch apply_op({Tab,No},Test)}),
No+1
@@ -661,9 +666,9 @@ apply_op(Oid = {Tab,Key},[Type|Next]) ->
apply_op(Oid,Next)
end)).
-check_res(transaction, {atomic,Res}) ->
+check_res(transaction, {atomic,Res}) ->
Res;
-check_res(sync_transaction, {atomic,Res}) ->
+check_res(sync_transaction, {atomic,Res}) ->
Res;
check_res(async_dirty, Res) when is_list(Res) ->
Res;
@@ -673,11 +678,11 @@ check_res(ets, Res) when is_list(Res) ->
Res;
check_res(Type,Res) ->
?match(bug,{Type,Res}).
-
+
read_op(Oid) ->
case lists:reverse(mnesia:read(Oid)) of
[] -> [];
- [{_,_,Ops}|_] ->
+ [{_,_,Ops}|_] ->
Ops
end.
@@ -686,24 +691,24 @@ read_op(Oid) ->
index_match_object(suite) -> [];
index_match_object(Config) when is_list(Config) ->
- [Node1, Node2] = Nodes = ?acquire_nodes(2, Config),
- Tab = index_match_object,
- Schema = [{name, Tab}, {attributes, [k, v, e]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
- ValPos = 3,
- BadValPos = ValPos + 2,
- ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
-
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:index_match_object({Tab, '$1', 2}, ValPos) end)),
- OneRec = {Tab, {1, 1}, 2, {1, 1}},
- OnePat = {Tab, '$1', 2, '_'},
+ [Node1, Node2] = Nodes = ?acquire_nodes(2, Config),
+ Tab = index_match_object,
+ Schema = [{name, Tab}, {attributes, [k, v, e]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ BadValPos = ValPos + 2,
+ ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
+
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:index_match_object({Tab, '$1', 2}, ValPos) end)),
+ OneRec = {Tab, {1, 1}, 2, {1, 1}},
+ OnePat = {Tab, '$1', 2, '_'},
BadPat = {Tab, '$1', '$2', '_'}, %% See ref guide
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- Imatch = fun(Patt, Pos) ->
+ Imatch = fun(Patt, Pos) ->
mnesia:transaction(fun() -> lists:sort(mnesia:index_match_object(Patt, Pos)) end)
end,
?match({atomic, [OneRec]}, Imatch(OnePat, ValPos)),
@@ -711,13 +716,13 @@ index_match_object(Config) when is_list(Config) ->
?match({aborted, _}, Imatch({foo, '$1', 2, '_'}, ValPos)),
?match({aborted, _}, Imatch({[], '$1', 2, '_'}, ValPos)),
?match({aborted, _}, Imatch(BadPat, ValPos)),
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_match_object(OnePat, ValPos)),
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_match_object(OnePat, ValPos)),
Another = {Tab, {3,1}, 2, {4,4}},
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Another) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, {4, 4}, 3, {4, 4}}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Another) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, {4, 4}, 3, {4, 4}}) end)),
?match({atomic, [OneRec]}, Imatch({Tab, {1,1}, 2, {1,1}}, ValPos)),
?match({atomic, [OneRec]}, Imatch({Tab, {1,1}, 2, '$1'}, ValPos)),
@@ -727,110 +732,110 @@ index_match_object(Config) when is_list(Config) ->
?match({atomic, [OneRec]}, Imatch({Tab, {'$2', '$1'}, 2, {'_', '$1'}}, ValPos)),
?match({atomic, [OneRec, Another]}, Imatch({Tab, '_', 2, '_'}, ValPos)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, 4, 5, {7, 4}}) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write({Tab, 7, 5, {7, 5}}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 4, 5, {7, 4}}) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write({Tab, 7, 5, {7, 5}}) end)),
?match({atomic, [{Tab, 4, 5, {7, 4}}]}, Imatch({Tab, '$1', 5, {'_', '$1'}}, ValPos)),
?match({atomic, [OneRec]}, rpc:call(Node2, mnesia, transaction,
- [fun() ->
- lists:sort(mnesia:index_match_object({Tab, {1,1}, 2,
+ [fun() ->
+ lists:sort(mnesia:index_match_object({Tab, {1,1}, 2,
{1,1}}, ValPos))
- end])),
+ end])),
?verify_mnesia(Nodes, []).
%% Read records by using an index
index_read(suite) -> [];
index_read(Config) when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = index_read,
- Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
- ValPos = 3,
- BadValPos = ValPos + 1,
- ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
-
- OneRec = {Tab, 1, 2},
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
- ?match({atomic, [OneRec]},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, BadValPos) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:index_read(foo, 2, ValPos) end)),
- ?match({aborted, _},
- mnesia:transaction(fun() -> mnesia:index_read([], 2, ValPos) end)),
-
- ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_read(Tab, 2, ValPos)),
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = index_read,
+ Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ValPos = 3,
+ BadValPos = ValPos + 1,
+ ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
+
+ OneRec = {Tab, 1, 2},
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(OneRec) end)),
+ ?match({atomic, [OneRec]},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, BadValPos) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:index_read(foo, 2, ValPos) end)),
+ ?match({aborted, _},
+ mnesia:transaction(fun() -> mnesia:index_read([], 2, ValPos) end)),
+
+ ?match({'EXIT', {aborted, no_transaction}}, mnesia:index_read(Tab, 2, ValPos)),
?verify_mnesia(Nodes, []).
index_update_set(suite) -> [];
index_update_set(Config)when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = index_test,
- Schema = [{name, Tab}, {attributes, [k, v1, v2, v3]}, {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
- ValPos = v1,
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = index_test,
+ Schema = [{name, Tab}, {attributes, [k, v1, v2, v3]}, {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ValPos = v1,
ValPos2 = v3,
- ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
-
+ ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
+
Pat1 = {Tab, '$1', 2, '$2', '$3'},
- Pat2 = {Tab, '$1', '$2', '$3', '$4'},
-
- Rec1 = {Tab, 1, 2, 3, 4},
+ Pat2 = {Tab, '$1', '$2', '$3', '$4'},
+
+ Rec1 = {Tab, 1, 2, 3, 4},
Rec2 = {Tab, 2, 2, 13, 14},
- Rec3 = {Tab, 1, 12, 13, 14},
- Rec4 = {Tab, 4, 2, 13, 14},
-
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec1) end)),
- ?match({atomic, [Rec1]},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
-
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec2) end)),
- {atomic, R1} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
+ Rec3 = {Tab, 1, 12, 13, 14},
+ Rec4 = {Tab, 4, 2, 13, 14},
+
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec1) end)),
+ ?match({atomic, [Rec1]},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec2) end)),
+ {atomic, R1} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1, Rec2], lists:sort(R1)),
-
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec3) end)),
- {atomic, R2} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec3) end)),
+ {atomic, R2} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec2], lists:sort(R2)),
- ?match({atomic, [Rec2]},
- mnesia:transaction(fun() -> mnesia:index_match_object(Pat1, ValPos) end)),
-
- {atomic, R3} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end),
+ ?match({atomic, [Rec2]},
+ mnesia:transaction(fun() -> mnesia:index_match_object(Pat1, ValPos) end)),
+
+ {atomic, R3} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end),
?match([Rec3, Rec2], lists:sort(R3)),
-
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec4) end)),
- {atomic, R4} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec4) end)),
+ {atomic, R4} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec2, Rec4], lists:sort(R4)),
-
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)),
- ?match({atomic, [Rec2]},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
-
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)),
+ ?match({atomic, [Rec2]},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+
?match({atomic, ok}, mnesia:del_table_index(Tab, ValPos)),
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec4) end)),
?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos2)),
-
- {atomic, R5} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end),
+
+ {atomic, R5} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end),
?match([Rec3, Rec2, Rec4], lists:sort(R5)),
-
+
{atomic, R6} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec2, Rec4], lists:sort(R6)),
-
+
?match({atomic, []},
mnesia:transaction(fun() -> mnesia:index_read(Tab, 4, ValPos2) end)),
{atomic, R7} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 14, ValPos2) end),
@@ -857,62 +862,66 @@ index_update_set(Config)when is_list(Config) ->
?match([Rec1], lists:sort(R11)),
?match({atomic, [Rec1]},mnesia:transaction(fun() -> mnesia:index_read(Tab, 4, ValPos2) end)),
?match({atomic, []},mnesia:transaction(fun() -> mnesia:index_read(Tab, 14, ValPos2) end)),
-
+
?verify_mnesia(Nodes, []).
index_update_bag(suite) -> [];
index_update_bag(Config)when is_list(Config) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
- Tab = index_test,
+ [Node1] = Nodes = ?acquire_nodes(1, Config),
+ Tab = index_test,
Schema = [{name, Tab},
{type, bag},
- {attributes, [k, v1, v2, v3]},
- {ram_copies, [Node1]}],
- ?match({atomic, ok}, mnesia:create_table(Schema)),
- ValPos = v1,
+ {attributes, [k, v1, v2, v3]},
+ {ram_copies, [Node1]}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ValPos = v1,
ValPos2 = v3,
- ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
+ ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
Pat1 = {Tab, '$1', 2, '$2', '$3'},
- Pat2 = {Tab, '$1', '$2', '$3', '$4'},
+ Pat2 = {Tab, '$1', '$2', '$3', '$4'},
- Rec1 = {Tab, 1, 2, 3, 4},
- Rec2 = {Tab, 2, 2, 13, 14},
- Rec3 = {Tab, 1, 12, 13, 14},
- Rec4 = {Tab, 4, 2, 13, 4},
+ Rec1 = {Tab, 1, 2, 3, 4},
+ Rec2 = {Tab, 2, 2, 13, 14},
+ Rec3 = {Tab, 1, 12, 13, 14},
+ Rec4 = {Tab, 4, 2, 13, 4},
Rec5 = {Tab, 1, 2, 234, 14},
%% Simple Index
- ?match({atomic, []},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec1) end)),
- ?match({atomic, [Rec1]},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
-
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec2) end)),
+ ?match({atomic, []},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec1) end)),
+ ?match({atomic, [Rec1]},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec5) end)),
+ ?match({atomic, [Rec1]},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec2) end)),
{atomic, R1} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1, Rec2], lists:sort(R1)),
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec3) end)),
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec3) end)),
{atomic, R2} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1, Rec2], lists:sort(R2)),
{atomic, R3} = mnesia:transaction(fun() -> mnesia:index_match_object(Pat1, ValPos) end),
?match([Rec1, Rec2], lists:sort(R3)),
-
+
{atomic, R4} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end),
?match([Rec1, Rec3, Rec2], lists:sort(R4)),
-
- ?match({atomic, ok},
- mnesia:transaction(fun() -> mnesia:write(Rec4) end)),
- {atomic, R5} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(Rec4) end)),
+ {atomic, R5} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1, Rec2, Rec4], lists:sort(R5)),
- ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)),
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete({Tab, 4}) end)),
{atomic, R6} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1, Rec2], lists:sort(R6)),
@@ -922,20 +931,20 @@ index_update_bag(Config)when is_list(Config) ->
ITab = mnesia_lib:val({index_test,{index, IPos}}),
io:format("~n Index ~p @ ~p => ~p ~n~n",[IPos,ITab, ets:tab2list(ITab)]),
?match([{2,1},{2,2},{12,1}], ets:tab2list(ITab)),
-
+
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec5) end)),
{atomic, R60} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1,Rec5,Rec2], lists:sort(R60)),
?match([{2,1},{2,2},{12,1}], ets:tab2list(ITab)),
-
+
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec3) end)),
{atomic, R61} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1,Rec5,Rec2], lists:sort(R61)),
{atomic, R62} = mnesia:transaction(fun() -> mnesia:index_read(Tab,12, ValPos) end),
?match([], lists:sort(R62)),
?match([{2,1},{2,2}], ets:tab2list(ITab)),
-
+
%% reset for rest of testcase
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec3) end)),
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec5) end)),
@@ -943,19 +952,19 @@ index_update_bag(Config)when is_list(Config) ->
?match([Rec1, Rec2], lists:sort(R6)),
%% OTP-6587
- ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec1) end)),
- ?match({atomic, [Rec2]},
- mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:delete_object(Rec1) end)),
+ ?match({atomic, [Rec2]},
+ mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end)),
{atomic, R7} = mnesia:transaction(fun() -> mnesia:match_object(Pat2) end),
?match([Rec3, Rec2], lists:sort(R7)),
-
+
%% Two indexies
?match({atomic, ok}, mnesia:del_table_index(Tab, ValPos)),
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec1) end)),
?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write(Rec4) end)),
?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos2)),
-
+
{atomic, R8} = mnesia:transaction(fun() -> mnesia:index_read(Tab, 2, ValPos) end),
?match([Rec1, Rec2, Rec4], lists:sort(R8)),
@@ -1001,12 +1010,12 @@ index_update_bag(Config)when is_list(Config) ->
index_write(suite) -> [];
index_write(doc) -> ["See ticket OTP-8072"];
index_write(Config)when is_list(Config) ->
- Nodes = ?acquire_nodes(1, Config),
+ Nodes = ?acquire_nodes(1, Config),
mnesia:create_table(a, [{index, [val]}]),
mnesia:create_table(counter, []),
CreateIfNonExist =
- fun(Index) ->
+ fun(Index) ->
case mnesia:index_read(a, Index, 3) of
[] ->
Id = mnesia:dirty_update_counter(counter, id, 1),
@@ -1017,7 +1026,7 @@ index_write(Config)when is_list(Config) ->
Found
end
end,
-
+
Trans = fun(A) ->
mnesia:transaction(CreateIfNonExist, [A])
%% This works better most of the time
@@ -1030,9 +1039,9 @@ index_write(Config)when is_list(Config) ->
Res = lists:map(Trans, lists:seq(1,10)),
Self ! {self(), Res}
end,
-
+
Pids = [spawn(Update) || _ <- lists:seq(1,5)],
-
+
Gather = fun(Pid, Acc) -> receive {Pid, Res} -> [Res|Acc] end end,
Results = lists:foldl(Gather, [], Pids),
Expected = hd(Results),
@@ -1075,7 +1084,7 @@ add_table_index(Config, Storage) ->
mnesia:add_table_index(Tab, 1)),
?match({aborted, Reason44 } when element(1, Reason44) == bad_type,
mnesia:add_table_index(Tab, 0)),
- ?match({aborted, Reason45 } when element(1, Reason45) == bad_type,
+ ?match({aborted, Reason45 } when element(1, Reason45) == bad_type,
mnesia:add_table_index(Tab, -1)),
?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
?match({aborted, Reason46 } when element(1, Reason46) == already_exists,
@@ -1083,10 +1092,10 @@ add_table_index(Config, Storage) ->
NestedFun = fun() ->
?match({aborted, nested_transaction},
- mnesia:add_table_index(Tab, ValPos)),
+ mnesia:add_table_index(Tab, ValPos)),
ok
end,
- ?match({atomic, ok}, mnesia:transaction(NestedFun)),
+ ?match({atomic, ok}, mnesia:transaction(NestedFun)),
?verify_mnesia(Nodes, []).
create_live_table_index_ram(suite) -> [];
@@ -1110,7 +1119,7 @@ create_live_table_index(Config, Storage) ->
mnesia:dirty_write({Tab, 1, 2}),
Fun = fun() ->
- ?match(ok, mnesia:write({Tab, 2, 2})),
+ ?match(ok, mnesia:write({Tab, 2, 2})),
ok
end,
?match({atomic, ok}, mnesia:transaction(Fun)),
@@ -1133,17 +1142,17 @@ create_live_table_index(Config, Storage) ->
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}]},
+ ?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]},
rpc:call(N2, mnesia, transaction, [IRead])),
-
+
?verify_mnesia(Nodes, []).
%% Drop table index
@@ -1210,49 +1219,49 @@ idx_schema_changes(Config, Storage) ->
ram_copies ->
{disc_copies, disc_only_copies}
end,
-
+
Write = fun(N) ->
mnesia:write({Tab, N, N+50})
- end,
-
+ end,
+
[mnesia:sync_transaction(Write, [N]) || N <- lists:seq(1, 10)],
?match([{Tab, 1, 51}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 51, Idx])),
?match([{Tab, 1, 51}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 51, Idx])),
?match({atomic, ok}, mnesia:change_table_copy_type(Tab, N1, Storage1)),
-
+
?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [17]])),
?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [18]])),
-
+
?match([{Tab, 17, 67}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 67, Idx])),
?match([{Tab, 18, 68}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 68, Idx])),
-
+
?match({atomic, ok}, mnesia:del_table_copy(Tab, N1)),
?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [11]])),
?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [12]])),
-
+
?match([{Tab, 11, 61}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 61, Idx])),
?match([{Tab, 12, 62}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 62, Idx])),
?match({atomic, ok}, mnesia:move_table_copy(Tab, N2, N1)),
?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [19]])),
?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [20]])),
-
+
?match([{Tab, 19, 69}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 69, Idx])),
- ?match([{Tab, 20, 70}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 70, Idx])),
-
+ ?match([{Tab, 20, 70}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 70, Idx])),
+
?match({atomic, ok}, mnesia:add_table_copy(Tab, N2, Storage)),
?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [13]])),
?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [14]])),
-
+
?match([{Tab, 13, 63}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 63, Idx])),
?match([{Tab, 14, 64}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 64, Idx])),
-
+
?match({atomic, ok}, mnesia:change_table_copy_type(Tab, N2, Storage2)),
-
+
?match({atomic, ok}, rpc:call(N1, mnesia, sync_transaction, [Write, [15]])),
?match({atomic, ok}, rpc:call(N2, mnesia, sync_transaction, [Write, [16]])),
-
+
?match([{Tab, 15, 65}], rpc:call(N2, mnesia, dirty_index_read, [Tab, 65, Idx])),
?match([{Tab, 16, 66}], rpc:call(N1, mnesia, dirty_index_read, [Tab, 66, Idx])),
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index a21ab007ef..da292cbb43 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.5
+MNESIA_VSN = 4.7
diff --git a/lib/observer/doc/src/Makefile b/lib/observer/doc/src/Makefile
index f82a49abbe..0f564d3299 100644
--- a/lib/observer/doc/src/Makefile
+++ b/lib/observer/doc/src/Makefile
@@ -36,6 +36,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = \
crashdump.xml \
+ observer.xml \
etop.xml \
ttb.xml
XML_REF6_FILES = observer_app.xml
@@ -48,6 +49,7 @@ XML_PART_FILES = \
XML_CHAPTER_FILES = \
crashdump_ug.xml \
etop_ug.xml \
+ observer_ug.xml \
ttb_ug.xml \
notes.xml \
notes_history.xml
@@ -131,16 +133,16 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/observer/doc/src/etop.xml b/lib/observer/doc/src/etop.xml
index 78047caab3..af6bb2442b 100644
--- a/lib/observer/doc/src/etop.xml
+++ b/lib/observer/doc/src/etop.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2002</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -114,6 +114,37 @@ Default: <c>on</c></item>
</description>
<funcs>
<func>
+ <name>start() -> ok</name>
+ <fsummary>Start etop</fsummary>
+ <desc>
+ <p>This function starts <c>etop</c>.
+ Note that etop is preferably started with the etop and getop scripts</p>
+ </desc>
+ </func>
+ <func>
+ <name>start(Options) -> ok</name>
+ <fsummary>Start etop</fsummary>
+ <type>
+ <v>Options = [Option]</v>
+ <v>Option = {Key, Value}</v>
+ <v>Key = atom()</v>
+ <v>Value = term()</v>
+ </type>
+ <desc>
+ <p>This function starts <c>etop</c>. Use
+ <seealso marker="#help/0">help/0</seealso> to see a
+ description of the possible options.</p>
+ </desc>
+ </func>
+ <func>
+ <name>help() -> ok</name>
+ <fsummary>Print etop's help</fsummary>
+ <desc>
+ <p>This function prints the help of <c>etop</c> and
+ its options.</p>
+ </desc>
+ </func>
+ <func>
<name>config(Key,Value) -> Result</name>
<fsummary>Change tool's configuration</fsummary>
<type>
diff --git a/lib/observer/doc/src/make.dep b/lib/observer/doc/src/make.dep
deleted file mode 100644
index 3c1b3df771..0000000000
--- a/lib/observer/doc/src/make.dep
+++ /dev/null
@@ -1,29 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex crashdump.tex crashdump_ug.tex etop.tex \
- etop_ug.tex observer_app.tex part.tex ref_man.tex \
- ttb.tex ttb_ug.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: etop_5.ps etop_lines.ps etop_main.ps etop_opt.ps
-
-book.dvi: et_modsprocs.ps et_processes.ps
-
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index baa1354268..a9554a08f4 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -31,6 +31,125 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 1.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The following bugs in <c>ttb</c> have been corrected:</p>
+ <p>
+ <list> <item><c>ttb:tracer/2</c> would earlier crash when
+ trying to set up tracing for a diskless node to wrap
+ files, i.e. when option
+ <c>{file,{local,{wrap,Filename,Size,Count}}}</c> was
+ used.</item> <item><c>ttb:stop([fetch])</c> would
+ sometimes silently fail if multiple nodes with different
+ current working directories were traced.</item>
+ <item><c>ttb:stop([fetch])</c> would crash if the tracer
+ was started with option
+ <c>{file,{local,Filename}}</c></item> <item>A deadlock
+ would sometimes occur due to an information printout from
+ the <c>ttb_control</c> process when <c>ttb</c> was
+ stopped.</item> </list></p>
+ <p>
+ Own Id: OTP-9431</p>
+ </item>
+ <item>
+ <p>
+ The file trace port to which the IP trace client relays
+ all traces from diskless nodes was not flushed and closed
+ properly on ttb:stop. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9665</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new GUI for Observer. Integrating pman, etop, appmon
+ and tv into observer with tracing facilities.</p>
+ <p>
+ Own Id: OTP-4779</p>
+ </item>
+ <item>
+ <p>
+ The following new features are added to <c>ttb</c>:</p>
+ <p>
+ <list> <item>A one-command trace setup is added,
+ <c>ttb:start_trace/4</c>.</item> <item>The following new
+ options are added to <c>ttb:tracer/2</c>: <list>
+ <item><em><c>shell</c></em> - Show trace messages on the
+ console in real time</item> <item><em><c>timer</c></em> -
+ Time constrained tracing</item>
+ <item><em><c>overload</c></em> - Overload
+ protection</item> <item><em><c>flush</c></em> - Flush
+ file trace port buffers with given frequency</item>
+ <item><em><c>resume</c></em> - Automatically resume
+ tracing after node restart</item> </list> </item> <item>
+ A new shortcut is added for common tracer settings
+ similar to using the <c>dbg</c> module directly,
+ <c>ttb:tracer(shell | dbg)</c>. </item> <item> Some
+ shortcuts are added for commonly used match
+ specifications in <c>ttb:tp</c> and <c>ttb:tpl</c>.
+ </item> <item> The <c>Options</c> argument to functions
+ <c>ttb:tracer</c>, <c>ttb:write_config</c>,
+ <c>ttb:stop</c> and <c>ttb:format</c> may now be one
+ single option instead of a list. </item> <item> The
+ history buffer of the last trace is now always
+ automatically dumped to the file <c>ttb_last_config</c>
+ when <c>ttb:stop</c> is called. </item> <item> The
+ following new options are added to <c>ttb:stop/1</c>:
+ <list> <item><em><c>fetch_dir</c></em> - Specify where to
+ store fetched logs</item>
+ <item><em><c>{format,FormatOpts}</c></em> - Specify
+ options to use when formatting the fetched logs</item>
+ <item><em><c>return_fetch_dir</c></em> - Indicate that
+ the return value from <c>ttb:stop/1</c> should include
+ the name of the directory where the fetched logs are
+ stored</item> </list> </item> <item> The option
+ <c>disable_sort</c> is added to <c>ttb:format/2</c>. When
+ this option is used, trace messages from different logs
+ are not merged according to timestamps, but just appended
+ one log after the other. </item> </list></p>
+ <p>
+ Own Id: OTP-9403</p>
+ </item>
+ <item>
+ <p>
+ The following non backwards compatible changes are done
+ in <c>ttb</c>:</p>
+ <p>
+ <list> <item> When setting up trace with ttb, the
+ 'timestamp' trace flag will now always be set. </item>
+ <item> The 'fetch' option to ttb:stop/1 is removed since
+ it is now default behavior that trace logs are fetched
+ when stopping ttb. Fetching can be disabled with the
+ 'nofetch' option to ttb:stop/1. </item> <item> The name
+ of the upload directory is changed from
+ ttb_upload-Timestamp to ttb_upload_FileName-Timestamp.
+ </item> <item> To format the output using 'et', you now
+ need to provide the option {handler,ttb:get_et_handler()}
+ instead of {handler,et}. </item> <item> When formatting a
+ trace log, the handler state was earlier reset after each
+ trace file, this is now changed so the handler state is
+ passed not only from one trace message to the next in the
+ same file, but also from one file to the next. </item>
+ </list></p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9430</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 0.9.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/observer/doc/src/observer.xml b/lib/observer/doc/src/observer.xml
new file mode 100644
index 0000000000..03830f2b1c
--- /dev/null
+++ b/lib/observer/doc/src/observer.xml
@@ -0,0 +1,58 @@
+<?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.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>Observer</title>
+ <prepared>Dan Gudmundsson</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2011-12-08</date>
+ <rev>PA1</rev>
+ <file>observer.xml</file>
+ </header>
+ <module>observer</module>
+ <modulesummary>A GUI tool for observing an erlang system.</modulesummary>
+ <description>
+ <p>The observer is gui frontend containing various tools to
+ inspect a system. It displays system information, application
+ structures, process information, ets or mnesia tables and a frontend
+ for tracing with <seealso marker="ttb">ttb</seealso>.
+ </p>
+
+ <p>See the <seealso marker="observer_ug">user's guide</seealso>
+ for more information about how to get started.</p>
+ </description>
+ <funcs>
+ <func>
+ <name>start() -> ok</name>
+ <fsummary>Start the observer gui</fsummary>
+ <desc>
+ <p>This function starts the <c>observer</c> gui.
+ Close the window to stop the application.
+ </p>
+ </desc>
+ </func>
+ </funcs>
+</erlref>
diff --git a/lib/observer/doc/src/observer_ug.xml b/lib/observer/doc/src/observer_ug.xml
new file mode 100644
index 0000000000..569d72e71e
--- /dev/null
+++ b/lib/observer/doc/src/observer_ug.xml
@@ -0,0 +1,190 @@
+<?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>Observer</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>observer_ug.xml</file>
+ </header>
+
+ <section>
+ <title>Introduction</title>
+ <p>Observer, is a graphical tool for observing the characteristics of
+ erlang systems. Observer displays system information, application
+ supervisor trees, process information, ets or mnesia tables and contains
+ a frontend for erlang tracing.
+ </p>
+ </section>
+
+ <section>
+ <title>General</title>
+ <p>Normally observer should be run from a standalone node to minimize
+ the impact of the system being observed. Example:
+ </p>
+ <code>
+ > erl -sname observer -hidden -setcookie MyCookie -run observer
+ </code>
+ <p>
+ Choose which node to observe via <c>Nodes</c> menu. The <c>View/Refresh
+ Interval</c> controls how frequent the view should be updated.
+ The refresh interval is set per viewer so you can
+ have different settings for each viewer. To minimize the system
+ impact only the active viewer is updated and the other
+ views will be updated when activated.
+ </p>
+ <note>
+ <p>Only R15B nodes can be observed.</p>
+ </note>
+
+ <p> In general the mouse buttons behaves as expected, use left click
+ to select objects, right click to pop up a menu with most used
+ choices and double click to bring up information about the
+ selected object. In most viewers with several columns you can change
+ sort order by left clicking on column header.
+ </p>
+ </section>
+
+ <section>
+ <title>Applications</title>
+ <p>The <c>Applications</c> view lists application information.
+ Select an application in the left list to display its supervisor
+ tree.
+ </p>
+ <p><c>Trace process</c> will add the selected process identifier
+ to <c>Trace Overview</c> view and the node the process resides on
+ will be added as well.
+ </p>
+ <p><c>Trace named process</c> will add the
+ registered name of the process. This can be useful when tracing on
+ several nodes, then processes with that name will be traced on all traced
+ nodes.
+ </p>
+ <p><c>Trace process tree</c> and <c>Trace named process
+ tree</c> will add the selected process and all processes below,
+ right of, it to the <c>Trace Overview</c> view.
+ </p>
+ </section>
+
+ <section>
+ <title>Processes</title>
+ <p>The <c>Processes</c> view lists process information.
+ For each process the following information is presented:
+ </p>
+ <taglist>
+ <tag>Pid</tag>
+ <item>The process identifier.</item>
+ <tag>Reds</tag>
+ <item>This is the number of reductions that has been executed
+ on the process</item>
+ <tag>Memory</tag>
+ <item>This is the size of the process in bytes, obtained by a
+ call to <c>process_info(Pid,memory)</c>.</item>
+ <tag>MsgQ</tag>
+ <item>This is the length of the message queue for the process.</item>
+ </taglist>
+ <note>
+ <p><em>Reds</em> can be presented as accumulated values or as values since last update.</p>
+ </note>
+ <p><c>Trace Processes</c> will add the selected process identifiers to the <c>Trace Overview</c> view and the
+ node the processes reside on will be added as well.
+ <c>Trace Named Processes</c> will add the registered name of processes. This can be useful
+ when tracing is done on several nodes, then processes with that name will be traced on all traced nodes.
+ </p>
+ </section>
+
+ <section>
+ <title>Table Viewer</title>
+ <p>The <c>Table Viewer</c> view lists tables. By default ets tables
+ are visible and unreadable, private ets, tables and tables created by the OTP
+ applications are not visible. Use <c>View</c> menu to view "system"
+ ets tables, unreadable ets tables or mnesia tables.
+ </p>
+ <p>Double click to view the content of the table. Select table and activate <c>View/Table Information</c>
+ menu to view table information.
+ </p>
+ <p>In the table viewer you can regexp search for objects, edit and delete objects.
+ </p>
+ </section>
+
+ <section>
+ <title>Trace Overview</title>
+ <p>The <c>Trace Overview</c> view handles tracing. Tracing is done
+ by selecting which processes to be traced and how to trace
+ them. You can trace messages, function calls and events, where
+ events are process related events such as <c>spawn</c>,
+ <c>exit</c> and several others.
+ </p>
+
+ <p>When you want to trace function calls, you also need to setup
+ <c>trace patterns</c>. Trace patterns selects the function calls
+ that will be traced. The number of traced function calls can be
+ further reduced with <c>match specifications</c>. Match
+ specifications can also be used to trigger additional information
+ in the trace messages.
+ </p>
+ <note><p>Trace patterns only applies to the traced processes.</p></note>
+
+ <p>
+ Processes are added from the <c>Applications</c> or <c>Processes</c> views.
+ A special <c>new</c> identifier, meaning all processes spawned after trace start,
+ can be added with the <c>Add 'new' Process</c> button.
+ </p>
+ <p>
+ When adding processes, a window with trace options will pop up. The chosen options will
+ be set for the selected processes.
+ Process options can be changed by right clicking on a process.
+ </p>
+ <p>
+ Processes added by process identifiers will add the nodes these
+ processes resides on in the node list. Additional nodes can be added by the <c>Add
+ Nodes</c> button.
+ </p>
+ <p>
+ If function calls are traced, trace patterns must be added by <c>Add Trace Pattern</c> button.
+ Select a module, function(s) and a match specification.
+ If no functions are selected, all functions in the module will be traced.
+ A few basic match specifications are provided in the tool, and
+ you can provide your own match specifications. The syntax of match
+ specifications are described in the <seealso
+ marker="erts:match_spec">ERTS User's Guide</seealso>. To simplify
+ the writing of a match specification they can also be written as
+ <c>fun/1</c> see <seealso marker="stdlib:ms_transform">ms_transform manual page</seealso> for
+ further information.
+ </p>
+
+ <p>Use the <c>Start trace</c> button to start the trace.
+ By default trace output is written to a new window, tracing is stopped when the
+ window is closed, or with <c>Stop Trace</c> button.
+ Trace output can be changed via <c>Options/Output</c> menu.
+ The trace settings, including match specifications, can be saved to, or loaded from, a file.
+ </p>
+ <p>More information about tracing can be found in <seealso
+ marker="runtime_tools:dbg">dbg</seealso> and in the chapter "Match
+ specifications in Erlang" in <seealso marker="erts:match_spec">ERTS User's
+ Guide</seealso> and the
+ <seealso marker="stdlib:ms_transform">ms_transform manual page</seealso>.
+ </p>
+ </section>
+</chapter>
diff --git a/lib/observer/doc/src/part.xml b/lib/observer/doc/src/part.xml
index bd6c2b6c77..0d6aad09f2 100644
--- a/lib/observer/doc/src/part.xml
+++ b/lib/observer/doc/src/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2002</year><year>2009</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,7 @@
<p>The <em>Observer</em> application contains tools for tracing
and investigation of distributed systems.</p>
</description>
+ <xi:include href="observer_ug.xml"/>
<xi:include href="ttb_ug.xml"/>
<xi:include href="etop_ug.xml"/>
<xi:include href="crashdump_ug.xml"/>
diff --git a/lib/observer/doc/src/ref_man.xml b/lib/observer/doc/src/ref_man.xml
index 3d37570d2d..c33ce74141 100644
--- a/lib/observer/doc/src/ref_man.xml
+++ b/lib/observer/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2002</year><year>2009</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,6 +34,7 @@
<br></br>
</description>
<xi:include href="observer_app.xml"/>
+ <xi:include href="observer.xml"/>
<xi:include href="ttb.xml"/>
<xi:include href="etop.xml"/>
<xi:include href="crashdump.xml"/>
diff --git a/lib/observer/doc/src/ttb_ug.xml b/lib/observer/doc/src/ttb_ug.xml
index 4f2b55a22a..08093a9451 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>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/observer/priv/erlang_observer.png b/lib/observer/priv/erlang_observer.png
new file mode 100644
index 0000000000..01723d210b
--- /dev/null
+++ b/lib/observer/priv/erlang_observer.png
Binary files differ
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index 3875b62101..7135a6abd5 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2002-2011. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2002-2012. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, 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
@@ -41,11 +41,26 @@ MODULES= \
etop_gui \
etop_tr \
etop_txt \
+ observer \
+ observer_app_wx \
+ observer_lib \
+ observer_wx \
+ observer_perf_wx \
+ observer_pro_wx \
+ observer_procinfo \
+ observer_sys_wx \
+ observer_trace_wx \
+ observer_traceoptions_wx \
+ observer_tv_table \
+ observer_tv_wx \
ttb \
ttb_et
+
HRL_FILES= \
../include/etop.hrl
INTERNAL_HRL_FILES= \
+ observer_tv.hrl \
+ observer_defs.hrl \
crashdump_viewer.hrl \
etop_defs.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -54,7 +69,7 @@ EXAMPLE_FILES= multitrace.erl
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
PRIVDIR= ../priv
-WEBTOOLFILES= $(PRIVDIR)/crashdump_viewer.tool
+WEBTOOLFILES= $(PRIVDIR)/crashdump_viewer.tool $(PRIVDIR)/erlang_observer.png
BINDIR= $(PRIVDIR)/bin
ifeq ($(findstring win32,$(TARGET)),win32)
WIN32_EXECUTABLES= $(BINDIR)/etop.bat $(BINDIR)/getop.bat $(BINDIR)/cdv.bat
@@ -92,8 +107,7 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
+opt debug: $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
@@ -105,28 +119,30 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
+$(TARGET_FILES): $(INTERNAL_HRL_FILES)
+
docs:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_SCRIPT) $(EXECUTABLES) $(RELSYSDIR)/priv/bin
- $(INSTALL_DIR) $(RELSYSDIR)/priv/crashdump_viewer
- $(INSTALL_DATA) $(WEBTOOLFILES) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(GIF_FILES) $(RELSYSDIR)/priv/crashdump_viewer
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(EXAMPLE_FILES) "$(RELSYSDIR)/examples"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_SCRIPT) $(EXECUTABLES) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/crashdump_viewer"
+ $(INSTALL_DATA) $(WEBTOOLFILES) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(GIF_FILES) "$(RELSYSDIR)/priv/crashdump_viewer"
release_docs_spec:
diff --git a/lib/observer/src/crashdump_viewer_html.erl b/lib/observer/src/crashdump_viewer_html.erl
index 24a80b1916..3151b83bfb 100644
--- a/lib/observer/src/crashdump_viewer_html.erl
+++ b/lib/observer/src/crashdump_viewer_html.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1394,7 +1394,7 @@ timers_table(Timer) ->
td("ALIGN=right",Time)]).
loaded_mods_table(#loaded_mod{mod=Mod,current_size=CS,old_size=OS}) ->
- tr([td(href(["loaded_mod_details?mod=",Mod],Mod)),
+ tr([td(href(["loaded_mod_details?mod=",http_uri:encode(Mod)],Mod)),
td("ALIGN=right",CS),
td("ALIGN=right",OS)]).
diff --git a/lib/observer/src/etop.erl b/lib/observer/src/etop.erl
index 0bf1d68534..428757e5ce 100644
--- a/lib/observer/src/etop.erl
+++ b/lib/observer/src/etop.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,9 +31,9 @@
help() ->
io:format(
- "Usage of the erlang top program~n"
- "Options are set as command line parameters as in -node a@host -..~n"
- "or as parameter to etop:start([{node, a@host}, {...}])~n"
+ "Usage of the Erlang top program~n~n"
+ "Options are set as command line parameters as in -node my@host~n"
+ "or as parameters to etop:start([{node, my@host}, {...}]).~n~n"
"Options are:~n"
" node atom Required The erlang node to measure ~n"
" port integer The used port, NOTE: due to a bug this program~n"
diff --git a/lib/observer/src/etop_gui.erl b/lib/observer/src/etop_gui.erl
index ff1b8078ad..f5cc0deb38 100644
--- a/lib/observer/src/etop_gui.erl
+++ b/lib/observer/src/etop_gui.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,13 @@
%% %CopyrightEnd%
%%
-module(etop_gui).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-author('[email protected]').
-export([init/1,stop/1]).
diff --git a/lib/observer/src/observer.app.src b/lib/observer/src/observer.app.src
index 5c65ea5c8f..d3aaf351dd 100644
--- a/lib/observer/src/observer.app.src
+++ b/lib/observer/src/observer.app.src
@@ -25,6 +25,18 @@
etop_gui,
etop_tr,
etop_txt,
+ observer,
+ observer_app_wx,
+ observer_lib,
+ observer_perf_wx,
+ observer_pro_wx,
+ observer_procinfo,
+ observer_sys_wx,
+ observer_trace_wx,
+ observer_traceoptions_wx,
+ observer_tv_table,
+ observer_tv_wx,
+ observer_wx,
ttb,
ttb_et]},
{registered, []},
diff --git a/lib/observer/src/observer.erl b/lib/observer/src/observer.erl
new file mode 100644
index 0000000000..098100e8ee
--- /dev/null
+++ b/lib/observer/src/observer.erl
@@ -0,0 +1,25 @@
+%%
+%% %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(observer).
+
+-export([start/0]).
+
+
+start() ->
+ observer_wx:start().
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
new file mode 100644
index 0000000000..380532e90c
--- /dev/null
+++ b/lib/observer/src/observer_app_wx.erl
@@ -0,0 +1,571 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_app_wx).
+
+-export([start_link/2]).
+
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_sync_event/3, handle_cast/2]).
+
+-behaviour(wx_object).
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+%% Import drawing wrappers
+-import(observer_perf_wx, [haveGC/1,
+ setPen/2, setFont/3, setBrush/2,
+ strokeLine/5, strokeLines/2, drawRoundedRectangle/6,
+ drawText/4, getTextExtent/2]).
+
+-record(state,
+ {
+ parent,
+ panel,
+ apps_w,
+ app_w,
+ paint,
+ current,
+ app,
+ sel,
+ appmon,
+ usegc = false
+ }).
+
+-record(paint, {font, pen, brush, sel, links}).
+
+-record(app, {ptree, n2p, links, dim}).
+-record(box, {x,y, w,h, s1}).
+-record(str, {x,y,text,pid}).
+
+-define(BX_E, 10). %% Empty width between text and box
+-define(BX_HE, (?BX_E div 2)).
+-define(BY_E, 10). %% Empty height between text and box
+-define(BY_HE, (?BY_E div 2)).
+
+-define(BB_X, 16). %% Empty width between boxes
+-define(BB_Y, 12). %% Empty height between boxes
+
+-define(DRAWAREA, 5).
+-define(ID_PROC_INFO, 101).
+-define(ID_PROC_MSG, 102).
+-define(ID_PROC_KILL, 103).
+-define(ID_TRACE_PID, 104).
+-define(ID_TRACE_NAME, 105).
+-define(ID_TRACE_TREE_PIDS, 106).
+-define(ID_TRACE_TREE_NAMES, 107).
+
+-define(wxGC, wxGraphicsContext).
+
+start_link(Notebook, Parent) ->
+ wx_object:start_link(?MODULE, [Notebook, Parent], []).
+
+init([Notebook, Parent]) ->
+ Panel = wxPanel:new(Notebook, [{size, wxWindow:getClientSize(Notebook)},
+ {winid, 1}
+ ]),
+ Main = wxBoxSizer:new(?wxHORIZONTAL),
+ Splitter = wxSplitterWindow:new(Panel, [{size, wxWindow:getClientSize(Panel)},
+ {style, ?wxSP_LIVE_UPDATE},
+ {id, 2}
+ ]),
+ Apps = wxListBox:new(Splitter, 3, []),
+ %% Need extra panel and sizer to get correct size updates
+ %% in draw area for some reason
+ P2 = wxPanel:new(Splitter, [{winid, 4}]),
+ Extra = wxBoxSizer:new(?wxVERTICAL),
+ DrawingArea = wxScrolledWindow:new(P2, [{winid, ?DRAWAREA},
+ {style,?wxFULL_REPAINT_ON_RESIZE}]),
+ wxWindow:setBackgroundColour(DrawingArea, ?wxWHITE),
+ wxWindow:setVirtualSize(DrawingArea, 800, 800),
+ wxSplitterWindow:setMinimumPaneSize(Splitter,50),
+ wxSizer:add(Extra, DrawingArea, [{flag, ?wxEXPAND},{proportion, 1}]),
+ wxWindow:setSizer(P2, Extra),
+ wxSplitterWindow:splitVertically(Splitter, Apps, P2, [{sashPosition, 150}]),
+ wxWindow:setSizer(Panel, Main),
+
+ wxSizer:add(Main, Splitter, [{flag, ?wxEXPAND bor ?wxALL},
+ {proportion, 1}, {border, 5}]),
+ wxWindow:setSizer(Panel, Main),
+ wxListBox:connect(Apps, command_listbox_selected),
+ wxPanel:connect(DrawingArea, paint, [callback]),
+ wxPanel:connect(DrawingArea, size, [{skip, true}]),
+ wxPanel:connect(DrawingArea, left_up),
+ wxPanel:connect(DrawingArea, left_dclick),
+ wxPanel:connect(DrawingArea, right_down),
+ case os:type() of
+ {win32, _} -> %% Ignore erase on windows
+ wxPanel:connect(DrawingArea, erase_background, [{callback, fun(_,_) -> ok end}]);
+ _ -> ok
+ end,
+
+ UseGC = haveGC(DrawingArea),
+ Font = case os:type() of
+ {unix,_} when UseGC ->
+ wxFont:new(12,?wxFONTFAMILY_DECORATIVE,?wxFONTSTYLE_NORMAL,?wxFONTWEIGHT_NORMAL);
+ _ ->
+ wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT)
+ end,
+ SelCol = wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT),
+ GreyBrush = wxBrush:new({230,230,240}),
+ SelBrush = wxBrush:new(SelCol),
+ LinkPen = wxPen:new(SelCol, [{width, 2}]),
+ process_flag(trap_exit, true),
+ {Panel, #state{parent=Parent,
+ panel =Panel,
+ apps_w=Apps,
+ app_w =DrawingArea,
+ usegc = UseGC,
+ paint=#paint{font = Font,
+ pen = wxPen:new({80,80,80}, [{width, 2}]),
+ brush= GreyBrush,
+ sel = SelBrush,
+ links= LinkPen
+ }
+ }}.
+
+setup_scrollbar(AppWin, App) ->
+ setup_scrollbar(wxWindow:getClientSize(AppWin), AppWin, App).
+
+setup_scrollbar({CW, CH}, AppWin, #app{dim={W0,H0}}) ->
+ W = max(W0,CW),
+ H = max(H0,CH),
+ PPC = 20,
+ if W0 =< CW, H0 =< CH ->
+ wxScrolledWindow:setScrollbars(AppWin, W, H, 0, 0);
+ H0 =< CH ->
+ wxScrolledWindow:setScrollbars(AppWin, PPC, H, W div PPC+1, 0);
+ W0 =< CW ->
+ wxScrolledWindow:setScrollbars(AppWin, W, PPC, 0, H div PPC+1);
+ true ->
+ wxScrolledWindow:setScrollbars(AppWin, PPC, PPC, W div PPC+1, H div PPC+1)
+ end;
+setup_scrollbar(_, _, undefined) -> ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+handle_event(#wx{event=#wxCommand{type=command_listbox_selected, cmdString=AppStr}},
+ State = #state{appmon=AppMon, current=Prev}) ->
+ case AppStr of
+ [] ->
+ {noreply, State};
+ _ ->
+ App = list_to_atom(AppStr),
+ (Prev =/= undefined) andalso appmon_info:app(AppMon, Prev, false, []),
+ appmon_info:app(AppMon, App, true, []),
+ {noreply, State#state{current=App}}
+ end;
+
+handle_event(#wx{id=Id, event=_Sz=#wxSize{size=Size}},
+ State=#state{app=App, app_w=AppWin}) ->
+ Id =:= ?DRAWAREA andalso setup_scrollbar(Size,AppWin,App),
+ {noreply, State};
+
+handle_event(#wx{event=#wxMouse{type=Type, x=X0, y=Y0}},
+ S0=#state{app=#app{ptree=Tree}, app_w=AppWin}) ->
+ {X,Y} = wxScrolledWindow:calcUnscrolledPosition(AppWin, X0, Y0),
+ Hit = locate_node(X,Y, [Tree]),
+ State = handle_mouse_click(Hit, Type, S0),
+ {noreply, State};
+
+handle_event(#wx{event=#wxCommand{type=command_menu_selected}},
+ State = #state{sel=undefined}) ->
+ observer_lib:display_info_dialog("Select process first"),
+ {noreply, State};
+
+handle_event(#wx{id=?ID_PROC_INFO, event=#wxCommand{type=command_menu_selected}},
+ State = #state{panel=Panel, sel={#box{s1=#str{pid=Pid}},_}}) ->
+ observer_procinfo:start(Pid, Panel, self()),
+ {noreply, State};
+
+handle_event(#wx{id=?ID_PROC_MSG, event=#wxCommand{type=command_menu_selected}},
+ State = #state{panel=Panel, sel={#box{s1=#str{pid=Pid}},_}}) ->
+ case observer_lib:user_term(Panel, "Enter message", "") of
+ cancel -> ok;
+ {ok, Term} -> Pid ! Term;
+ {error, Error} -> observer_lib:display_info_dialog(Error)
+ end,
+ {noreply, State};
+
+handle_event(#wx{id=?ID_PROC_KILL, event=#wxCommand{type=command_menu_selected}},
+ State = #state{panel=Panel, sel={#box{s1=#str{pid=Pid}},_}}) ->
+ case observer_lib:user_term(Panel, "Enter Exit Reason", "kill") of
+ cancel -> ok;
+ {ok, Term} -> exit(Pid, Term);
+ {error, Error} -> observer_lib:display_info_dialog(Error)
+ end,
+ {noreply, State};
+
+%%% Trace api
+handle_event(#wx{id=?ID_TRACE_PID, event=#wxCommand{type=command_menu_selected}},
+ State = #state{sel={Box,_}}) ->
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), [box_to_pid(Box)]),
+ {noreply, State};
+handle_event(#wx{id=?ID_TRACE_NAME, event=#wxCommand{type=command_menu_selected}},
+ State = #state{sel={Box,_}}) ->
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), [box_to_reg(Box)]),
+ {noreply, State};
+handle_event(#wx{id=?ID_TRACE_TREE_PIDS, event=#wxCommand{type=command_menu_selected}},
+ State = #state{sel=Sel}) ->
+ Get = fun(Box) -> box_to_pid(Box) end,
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), tree_map(Sel, Get)),
+ {noreply, State};
+handle_event(#wx{id=?ID_TRACE_TREE_NAMES, event=#wxCommand{type=command_menu_selected}},
+ State = #state{sel=Sel}) ->
+ Get = fun(Box) -> box_to_reg(Box) end,
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), tree_map(Sel, Get)),
+ {noreply, State};
+
+handle_event(Event, _State) ->
+ error({unhandled_event, Event}).
+
+%%%%%%%%%%
+handle_sync_event(#wx{event = #wxPaint{}},_,
+ #state{app_w=DA, app=App, sel=Sel, paint=Paint, usegc=UseGC}) ->
+ %% PaintDC must be created in a callback to work on windows.
+ IsWindows = element(1, os:type()) =:= win32,
+ %% Avoid Windows flickering hack
+ DC = if IsWindows -> wx:typeCast(wxBufferedPaintDC:new(DA), wxPaintDC);
+ true -> wxPaintDC:new(DA)
+ end,
+ IsWindows andalso wxDC:clear(DC),
+ GC = case UseGC of
+ true ->
+ GC0 = ?wxGC:create(DC),
+ %% Argh must handle scrolling when using ?wxGC
+ {Sx,Sy} = wxScrolledWindow:calcScrolledPosition(DA, {0,0}),
+ ?wxGC:translate(GC0, Sx,Sy),
+ GC0;
+ false ->
+ wxScrolledWindow:doPrepareDC(DA,DC),
+ DC
+ end,
+ %% Nothing is drawn until wxPaintDC is destroyed.
+ draw({UseGC, GC}, App, Sel, Paint),
+ UseGC andalso ?wxGC:destroy(GC),
+ wxPaintDC:destroy(DC),
+ ok.
+%%%%%%%%%%
+handle_call(Event, From, _State) ->
+ error({unhandled_call, Event, From}).
+
+handle_cast(Event, _State) ->
+ error({unhandled_cast, Event}).
+%%%%%%%%%%
+handle_info({active, Node}, State = #state{parent=Parent, current=Curr, appmon=Appmon}) ->
+ create_menus(Parent, []),
+ Pid = try
+ Node = node(Appmon),
+ Appmon
+ catch _:_ ->
+ {ok, P} = appmon_info:start_link(Node, self(), []),
+ P
+ end,
+ appmon_info:app_ctrl(Pid, Node, true, []),
+ (Curr =/= undefined) andalso appmon_info:app(Pid, Curr, true, []),
+ {noreply, State#state{appmon=Pid}};
+handle_info(not_active, State = #state{appmon=AppMon}) ->
+ appmon_info:app_ctrl(AppMon, node(AppMon), false, []),
+ lists:member(node(AppMon), nodes()) andalso exit(AppMon, normal),
+ observer_wx:set_status(""),
+ {noreply, State#state{appmon=undefined}};
+handle_info({delivery, Pid, app_ctrl, _, Apps0},
+ State = #state{appmon=Pid, apps_w=LBox, current=Curr0}) ->
+ Apps = [atom_to_list(App) || {_, App, {_, _, _}} <- Apps0],
+ wxListBox:clear(LBox),
+ wxListBox:appendStrings(LBox, [App || App <- lists:sort(Apps)]),
+ case Apps of
+ [App|_] when Curr0 =:= undefined ->
+ Curr = list_to_atom(App),
+ appmon_info:app(Pid, Curr, true, []),
+ {noreply, State#state{current=Curr}};
+ _ ->
+ {noreply, State}
+ end;
+handle_info({delivery, _Pid, app, _Curr, {[], [], [], []}},
+ State = #state{panel=Panel}) ->
+ wxWindow:refresh(Panel),
+ {noreply, State#state{app=undefined, sel=undefined}};
+
+handle_info({delivery, Pid, app, Curr, AppData},
+ State = #state{panel=Panel, appmon=Pid, current=Curr, usegc=UseGC,
+ app_w=AppWin, paint=#paint{font=Font}}) ->
+ GC = if UseGC -> ?wxGC:create(AppWin);
+ true -> wxWindowDC:new(AppWin)
+ end,
+ FontW = {UseGC, GC},
+ setFont(FontW, Font, {0,0,0}),
+ App = build_tree(AppData, FontW),
+ if UseGC -> ?wxGC:destroy(GC);
+ true -> wxWindowDC:destroy(GC)
+ end,
+ setup_scrollbar(AppWin, App),
+ wxWindow:refresh(Panel),
+ wxWindow:layout(Panel),
+ {noreply, State#state{app=App, sel=undefined}};
+
+handle_info({'EXIT', _, noconnection}, State) ->
+ {noreply, State};
+handle_info({'EXIT', _, normal}, State) ->
+ {noreply, State};
+handle_info(_Event, State) ->
+ %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]),
+ {noreply, State}.
+
+%%%%%%%%%%
+terminate(_Event, _State) ->
+ ok.
+code_change(_, _, State) ->
+ State.
+
+handle_mouse_click(Node = {#box{s1=#str{pid=Pid}},_}, Type,
+ State=#state{app_w=AppWin,panel=Panel}) ->
+ case Type of
+ left_dclick -> observer_procinfo:start(Pid, Panel, self());
+ right_down -> popup_menu(Panel);
+ _ -> ok
+ end,
+ observer_wx:set_status(io_lib:format("Pid: ~p", [Pid])),
+ wxWindow:refresh(AppWin),
+ State#state{sel=Node};
+handle_mouse_click(_, _, State = #state{sel=undefined}) ->
+ State;
+handle_mouse_click(_, right_down, State=#state{panel=Panel}) ->
+ popup_menu(Panel),
+ State;
+handle_mouse_click(_, _, State=#state{app_w=AppWin}) ->
+ observer_wx:set_status(""),
+ wxWindow:refresh(AppWin),
+ State#state{sel=undefined}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_menus(Parent, _) ->
+ MenuEntries =
+ [{"File",
+ [#create_menu{id=?ID_PROC_INFO, text="Process info"},
+ #create_menu{id=?ID_PROC_MSG, text="Send Msg"},
+ #create_menu{id=?ID_PROC_KILL, text="Kill process"}
+ ]},
+ {"Trace",
+ [#create_menu{id=?ID_TRACE_PID, text="Trace process"},
+ #create_menu{id=?ID_TRACE_NAME, text="Trace named process"},
+ #create_menu{id=?ID_TRACE_TREE_PIDS, text="Trace process tree"},
+ #create_menu{id=?ID_TRACE_TREE_NAMES, text="Trace named process tree"}
+ ]}],
+ observer_wx:create_menus(Parent, MenuEntries).
+
+popup_menu(Panel) ->
+ Menu = wxMenu:new(),
+ wxMenu:append(Menu, ?ID_PROC_INFO, "Process info"),
+ wxMenu:append(Menu, ?ID_TRACE_PID, "Trace process"),
+ wxMenu:append(Menu, ?ID_TRACE_NAME, "Trace named process"),
+ wxMenu:append(Menu, ?ID_TRACE_TREE_PIDS, "Trace process tree"),
+ wxMenu:append(Menu, ?ID_TRACE_TREE_NAMES, "Trace named process tree"),
+ wxMenu:append(Menu, ?ID_PROC_MSG, "Send Msg"),
+ wxMenu:append(Menu, ?ID_PROC_KILL, "Kill process"),
+ wxWindow:popupMenu(Panel, Menu),
+ wxMenu:destroy(Menu).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+locate_node(X, _Y, [{Box=#box{x=BX}, _Chs}|_Rest])
+ when X < BX ->
+ {left, Box};
+locate_node(X,Y, [Node={Box=#box{x=BX,y=BY,w=BW,h=BH}, _Chs}|Rest])
+ when X =< (BX+BW)->
+ if
+ Y < BY -> {above, Box}; %% Above
+ Y =< (BY+BH) -> Node;
+ true -> locate_node(X,Y,Rest)
+ end;
+locate_node(X,Y, [{_, Chs}|Rest]) ->
+ case locate_node(X,Y,Chs) of
+ Node = {#box{},_} -> Node;
+ _Miss ->
+ locate_node(X,Y,Rest)
+ end;
+locate_node(_, _, []) -> false.
+
+locate_box(From, [{Box=#box{s1=#str{pid=From}},_}|_]) -> Box;
+locate_box(From, [{_,Chs}|Rest]) ->
+ case locate_box(From, Chs) of
+ Box = #box{} -> Box;
+ _ -> locate_box(From, Rest)
+ end;
+locate_box(From, []) -> {false, From}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+build_tree({Root, P2Name, Links, XLinks0}, FontW) ->
+ Fam = sofs:relation_to_family(sofs:relation(Links)),
+ Name2P = gb_trees:from_orddict(lists:sort([{Name,Pid} || {Pid,Name} <- P2Name])),
+ Lookup = gb_trees:from_orddict(sofs:to_external(Fam)),
+ {_, Tree0} = build_tree2(Root, Lookup, Name2P, FontW),
+ {Tree, Dim} = calc_tree_size(Tree0),
+ Fetch = fun({From, To}, Acc) ->
+ try {value, ToPid} = gb_trees:lookup(To, Name2P),
+ FromPid = gb_trees:get(From, Name2P),
+ [{locate_box(FromPid, [Tree]),locate_box(ToPid, [Tree])}|Acc]
+ catch _:_ ->
+ Acc
+ end
+ end,
+ XLinks = lists:foldl(Fetch, [], XLinks0),
+ #app{ptree=Tree, dim=Dim, links=XLinks}.
+
+build_tree2(Root, Tree0, N2P, FontW) ->
+ case gb_trees:lookup(Root, Tree0) of
+ none -> {Tree0, {box(Root, N2P, FontW), []}};
+ {value, Children} ->
+ Tree1 = gb_trees:delete(Root, Tree0),
+ {Tree, CHs} = lists:foldr(fun("port " ++_, Acc) ->
+ Acc; %% Skip ports
+ (Child,{T0, Acc}) ->
+ {T, C} = build_tree2(Child, T0, N2P, FontW),
+ {T, [C|Acc]}
+ end, {Tree1, []}, Children),
+ {Tree, {box(Root, N2P, FontW), CHs}}
+ end.
+
+calc_tree_size(Tree) ->
+ Cols = calc_col_start(Tree, [0]),
+ {Boxes,{W,Hs}} = calc_tree_size(Tree, Cols, ?BB_X, [?BB_Y]),
+ {Boxes, {W,lists:max(Hs)}}.
+
+calc_col_start({#box{w=W}, Chs}, [Max|Acc0]) ->
+ Acc = if Acc0 == [] -> [0]; true -> Acc0 end,
+ Depth = lists:foldl(fun(Child, MDepth) -> calc_col_start(Child, MDepth) end,
+ Acc, Chs),
+ [max(W,Max)|Depth].
+
+calc_tree_size({Box=#box{w=W,h=H}, []}, _, X, [Y|Ys]) ->
+ {{Box#box{x=X,y=Y}, []}, {X+W+?BB_X,[Y+H+?BB_Y|Ys]}};
+calc_tree_size({Box, Children}, [Col|Cols], X, [H0|Hs0]) ->
+ Hs1 = calc_row_start(Children, H0, Hs0),
+ StartX = X+Col+?BB_X,
+ {Boxes, {W,Hs}} = calc_tree_sizes(Children, Cols, StartX, StartX, Hs1, []),
+ Y = middle(Boxes, H0),
+ H = Y+Box#box.h+?BB_Y,
+ {{Box#box{x=X,y=Y}, Boxes}, {W,[H|Hs]}}.
+
+calc_tree_sizes([Child|Chs], Cols, X0, W0, Hs0, Acc) ->
+ {Tree, {W,Hs}} = calc_tree_size(Child, Cols, X0, Hs0),
+ calc_tree_sizes(Chs, Cols, X0, max(W,W0), Hs, [Tree|Acc]);
+calc_tree_sizes([], _, _, W,Hs, Acc) ->
+ {lists:reverse(Acc), {W,Hs}}.
+
+calc_row_start(Chs = [{#box{h=H},_}|_], Start, Hs0) ->
+ NChs = length(Chs),
+ Wanted = (H*NChs + ?BB_Y*(NChs-1)) div 2 - H div 2,
+ case Hs0 of
+ [] -> [max(?BB_Y, Start - Wanted)];
+ [Next|Hs] ->
+ [max(Next, Start - Wanted)|Hs]
+ end.
+
+middle([], Y) -> Y;
+middle([{#box{y=Y}, _}], _) -> Y;
+middle([{#box{y=Y0},_}|List], _) ->
+ {#box{y=Y1},_} = lists:last(List),
+ (Y0+Y1) div 2.
+
+box(Str0, N2P, FontW) ->
+ Pid = gb_trees:get(Str0, N2P),
+ Str = if hd(Str0) =:= $< -> lists:append(io_lib:format("~w", [Pid]));
+ true -> Str0
+ end,
+ {TW,TH} = getTextExtent(FontW, Str),
+ Data = #str{text=Str, x=?BX_HE, y=?BY_HE, pid=Pid},
+ %% Add pid
+ #box{w=round(TW)+?BX_E, h=round(TH)+?BY_E, s1=Data}.
+
+box_to_pid(#box{s1=#str{pid=Pid}}) -> Pid.
+box_to_reg(#box{s1=#str{text=[$<|_], pid=Pid}}) -> Pid;
+box_to_reg(#box{s1=#str{text=Name}}) -> list_to_atom(Name).
+
+tree_map({Box, Chs}, Fun) ->
+ tree_map(Chs, Fun, [Fun(Box)]).
+tree_map([{Box, Chs}|Rest], Fun, Acc0) ->
+ Acc = tree_map(Chs, Fun, [Fun(Box)|Acc0]),
+ tree_map(Rest, Fun, Acc);
+tree_map([], _ , Acc) -> Acc.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+draw(_DC, undefined, _, _) ->
+ ok;
+draw(DC, #app{dim={_W,_H}, ptree=Tree, links=Links}, Sel,
+ #paint{font=Font, pen=Pen, brush=Brush, links=LPen, sel=SelBrush}) ->
+ setPen(DC, LPen),
+ [draw_xlink(Link, DC) || Link <- Links],
+ setPen(DC, Pen),
+ %% ?wxGC:drawRectangle(DC, 2,2, _W-2,_H-2), %% DEBUG
+ setBrush(DC, Brush),
+ setFont(DC, Font, {0,0,0}),
+ draw_tree(Tree, root, DC),
+ case Sel of
+ undefined -> ok;
+ {#box{x=X,y=Y,w=W,h=H,s1=Str1}, _} ->
+ setBrush(DC, SelBrush),
+ drawRoundedRectangle(DC, X-1,Y-1, W+2,H+2, 8.0),
+ draw_str(DC, Str1, X, Y)
+ end.
+
+draw_tree({Box=#box{x=X,y=Y,w=W,h=H,s1=Str1}, Chs}, Parent, DC) ->
+ drawRoundedRectangle(DC, X,Y, W,H, 8.0),
+ draw_str(DC, Str1, X, Y),
+ Dot = case Chs of
+ [] -> ok;
+ [{#box{x=CX0},_}|_] ->
+ CY = Y+(H div 2),
+ CX = CX0-(?BB_X div 2),
+ strokeLine(DC, X+W, CY, CX, CY),
+ {CX, CY}
+ end,
+ draw_link(Parent, Box, DC),
+ [draw_tree(Child, Dot, DC) || Child <- Chs].
+
+draw_link({CX,CY}, #box{x=X,y=Y0,h=H}, DC) ->
+ Y = Y0+(H div 2),
+ case Y =:= CY of
+ true ->
+ strokeLine(DC, CX, CY, X, CY);
+ false ->
+ strokeLines(DC, [{CX, CY}, {CX, Y}, {X,Y}])
+ end;
+draw_link(_, _, _) -> ok.
+
+draw_xlink({#box{x=X0, y=Y0, h=BH}, #box{x=X1, y=Y1}}, DC)
+ when X0 =:= X1 ->
+ draw_xlink(X0,Y0,X1,Y1,BH,DC);
+draw_xlink({#box{x=X0, y=Y0, h=BH, w=BW}, #box{x=X1, y=Y1}}, DC)
+ when X0 < X1 ->
+ draw_xlink(X0+BW,Y0,X1,Y1,BH,DC);
+draw_xlink({#box{x=X0, y=Y0, h=BH}, #box{x=X1, w=BW, y=Y1}}, DC)
+ when X0 > X1 ->
+ draw_xlink(X1+BW,Y1,X0,Y0,BH,DC);
+draw_xlink({_From, _To}, _DC) ->
+ ignore.
+draw_xlink(X0, Y00, X1, Y11, BH, DC) ->
+ {Y0,Y1} = if Y00 < Y11 -> {Y00+BH-6, Y11+6};
+ true -> {Y00+6, Y11+BH-6}
+ end,
+ strokeLines(DC, [{X0,Y0}, {X0+5,Y0}, {X1-5,Y1}, {X1,Y1}]).
+
+draw_str(DC, #str{x=Sx,y=Sy, text=Text}, X, Y) ->
+ drawText(DC, Text, X+Sx,Y+Sy);
+draw_str(_, _, _, _) -> ok.
diff --git a/lib/observer/src/observer_defs.hrl b/lib/observer/src/observer_defs.hrl
new file mode 100644
index 0000000000..586e7bbff9
--- /dev/null
+++ b/lib/observer/src/observer_defs.hrl
@@ -0,0 +1,47 @@
+%%
+%% %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%
+
+-record(match_spec, {name = "",
+ term = [],
+ str = [],
+ func = ""}).
+
+-record(tpattern, {m, fa, ms}).
+
+-record(traced_func, {func_name, %atom
+ arity, %integer
+ match_spec = #match_spec{}}).
+
+-record(create_menu,
+ {id,
+ text,
+ help = [],
+ type = append,
+ check = false
+ }).
+
+-record(attrs, {even, odd, deleted, changed, searched}).
+-define(EVEN(Row), ((Row rem 2) =:= 0)).
+-define(BG_EVEN, {230,230,250}).
+-define(BG_ODD, {255,255,255}).
+-define(BG_DELETED, {100,100,100}).
+-define(FG_DELETED, {240,30,30}).
+-define(BG_SEARCHED,{235,215,90}).
+-define(BG_CHANGED, {230,230,250}).
+
+-define(LCTRL_WDECR, 4). %% Remove some pixels in column width to avoid creating unnecessary scrollbar
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
new file mode 100644
index 0000000000..4077f8371a
--- /dev/null
+++ b/lib/observer/src/observer_lib.erl
@@ -0,0 +1,429 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_lib).
+
+-export([get_wx_parent/1,
+ display_info_dialog/1, user_term/3, user_term_multiline/3,
+ interval_dialog/4, start_timer/1, stop_timer/1,
+ display_info/2, fill_info/2, update_info/2, to_str/1,
+ create_menus/3, create_menu_item/3,
+ create_attrs/0,
+ set_listctrl_col_size/2
+ ]).
+
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+get_wx_parent(Window) ->
+ Parent = wxWindow:getParent(Window),
+ case wx:is_null(Parent) of
+ true -> Window;
+ false -> get_wx_parent(Parent)
+ end.
+
+interval_dialog(Parent0, {Timer, Value}, Min, Max) ->
+ Parent = get_wx_parent(Parent0),
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Update Interval",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor
+ ?wxRESIZE_BORDER}]),
+ Panel = wxPanel:new(Dialog),
+ Check = wxCheckBox:new(Panel, ?wxID_ANY, "Periodical refresh"),
+ wxCheckBox:setValue(Check, Timer /= false),
+ Style = ?wxSL_HORIZONTAL bor ?wxSL_AUTOTICKS bor ?wxSL_LABELS,
+ Slider = wxSlider:new(Panel, ?wxID_ANY, Value, Min, Max,
+ [{style, Style}, {size, {200, -1}}]),
+ wxWindow:enable(Slider, [{enable, Timer /= false}]),
+ InnerSizer = wxBoxSizer:new(?wxVERTICAL),
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ Flags = [{flag, ?wxEXPAND bor ?wxALL}, {border, 2}],
+ wxSizer:add(InnerSizer, Check, Flags),
+ wxSizer:add(InnerSizer, Slider, Flags),
+ wxPanel:setSizer(Panel, InnerSizer),
+ TopSizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(TopSizer, Panel, [{flag, ?wxEXPAND bor ?wxALL}, {border, 5}]),
+ wxSizer:add(TopSizer, Buttons, [{flag, ?wxEXPAND}]),
+ wxWindow:setSizerAndFit(Dialog, TopSizer),
+ wxSizer:setSizeHints(TopSizer, Dialog),
+ wxCheckBox:connect(Check, command_checkbox_clicked,
+ [{callback, fun(#wx{event=#wxCommand{commandInt=Enable0}},_) ->
+ Enable = Enable0 > 0,
+ wxWindow:enable(Slider, [{enable, Enable}])
+ end}]),
+ Res = case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Enabled = wxCheckBox:isChecked(Check),
+ setup_timer(Enabled, {Timer, wxSlider:getValue(Slider)});
+ ?wxID_CANCEL ->
+ {Timer, Value}
+ end,
+ wxDialog:destroy(Dialog),
+ Res.
+
+stop_timer(Timer = {false, _}) -> Timer;
+stop_timer(Timer = {true, _}) -> Timer;
+stop_timer(Timer = {_, Intv}) ->
+ setup_timer(false, Timer),
+ {true, Intv}.
+start_timer(Intv) when is_integer(Intv) ->
+ setup_timer(true, {true, Intv});
+start_timer(Timer) ->
+ setup_timer(true, Timer).
+
+setup_timer(false, {Timer, Value})
+ when is_boolean(Timer) ->
+ {false, Value};
+setup_timer(true, {false, Value}) ->
+ {ok, Timer} = timer:send_interval(Value * 1000, refresh_interval),
+ {Timer, Value};
+setup_timer(Bool, {Timer, Old}) ->
+ timer:cancel(Timer),
+ setup_timer(Bool, {false, Old}).
+
+display_info_dialog(Str) ->
+ Dlg = wxMessageDialog:new(wx:null(), Str),
+ wxMessageDialog:showModal(Dlg),
+ wxMessageDialog:destroy(Dlg),
+ ok.
+
+%% display_info(Parent, [{Title, [{Label, Info}]}]) -> {Panel, Sizer, InfoFieldsToUpdate}
+display_info(Frame, Info) ->
+ Panel = wxPanel:new(Frame),
+ wxWindow:setBackgroundColour(Panel, {255,255,255}),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:addSpacer(Sizer, 5),
+ Add = fun(BoxInfo) ->
+ {Box, InfoFs} = create_box(Panel, BoxInfo),
+ wxSizer:add(Sizer, Box, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}]),
+ wxSizer:addSpacer(Sizer, 5),
+ InfoFs
+ end,
+ InfoFs = [Add(I) || I <- Info],
+ wxWindow:setSizerAndFit(Panel, Sizer),
+ {Panel, Sizer, InfoFs}.
+
+fill_info([{Str, Key}|Rest], Data) when is_atom(Key); is_function(Key) ->
+ [{Str, get_value(Key, Data)} | fill_info(Rest, Data)];
+fill_info([{Str, {Format, Key}}|Rest], Data)
+ when is_atom(Key); is_function(Key), is_atom(Format) ->
+ [{Str, {Format, get_value(Key,Data)}} | fill_info(Rest, Data)];
+fill_info([{Str,SubStructure}|Rest], Data) when is_list(SubStructure) ->
+ [{Str, fill_info(SubStructure, Data)}|fill_info(Rest,Data)];
+fill_info([{Str,Attrib,SubStructure}|Rest], Data) ->
+ [{Str, Attrib, fill_info(SubStructure, Data)}|fill_info(Rest,Data)];
+fill_info([], _) -> [].
+
+get_value(Key, Data) when is_atom(Key) ->
+ proplists:get_value(Key,Data);
+get_value(Fun, Data) when is_function(Fun) ->
+ Fun(Data).
+
+update_info([Fields|Fs], [{_Header, SubStructure}| Rest]) ->
+ update_info2(Fields, SubStructure),
+ update_info(Fs, Rest);
+update_info([Fields|Fs], [{_Header, _Attrib, SubStructure}| Rest]) ->
+ update_info2(Fields, SubStructure),
+ update_info(Fs, Rest);
+update_info([], []) ->
+ ok.
+
+update_info2([Field|Fs], [{_Str, Value}|Rest]) ->
+ wxStaticText:setLabel(Field, to_str(Value)),
+ update_info2(Fs, Rest);
+update_info2([], []) -> ok.
+
+
+to_str(Value) when is_atom(Value) ->
+ atom_to_list(Value);
+to_str({bytes, B}) ->
+ KB = B div 1024,
+ MB = KB div 1024,
+ GB = MB div 1024,
+ if
+ GB > 10 -> integer_to_list(GB) ++ " gB";
+ MB > 10 -> integer_to_list(MB) ++ " mB";
+ KB > 0 -> integer_to_list(KB) ++ " kB";
+ true -> integer_to_list(B) ++ " B "
+ end;
+to_str({time_ms, MS}) ->
+ S = MS div 1000,
+ Min = S div 60,
+ Hours = Min div 60,
+ Days = Hours div 24,
+ if
+ Days > 0 -> integer_to_list(Days) ++ " Days";
+ Hours > 0 -> integer_to_list(Hours) ++ " Hours";
+ Min > 0 -> integer_to_list(Min) ++ " Mins";
+ true -> integer_to_list(S) ++ " Secs"
+ end;
+
+to_str({func, {F,A}}) when is_atom(F), is_integer(A) ->
+ lists:concat([F, "/", A]);
+to_str({func, {F,'_'}}) when is_atom(F) ->
+ atom_to_list(F);
+to_str({A, B}) when is_atom(A), is_atom(B) ->
+ lists:concat([A, ":", B]);
+to_str({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->
+ lists:concat([M, ":", F, "/", A]);
+to_str(Value) when is_list(Value) ->
+ case lists:all(fun(X) -> is_integer(X) end, Value) of
+ true -> Value;
+ false ->
+ lists:foldl(fun(X, Acc) ->
+ to_str(X) ++ " " ++ Acc end,
+ "", Value)
+ end;
+to_str(Port) when is_port(Port) ->
+ erlang:port_to_list(Port);
+to_str(Pid) when is_pid(Pid) ->
+ pid_to_list(Pid);
+to_str(No) when is_integer(No) ->
+ integer_to_list(No);
+to_str(Term) ->
+ io_lib:format("~w", [Term]).
+
+create_menus([], _MenuBar, _Type) -> ok;
+create_menus(Menus, MenuBar, Type) ->
+ Add = fun({Tag, Ms}, Index) ->
+ create_menu(Tag, Ms, Index, MenuBar, Type)
+ end,
+ [{First, _}|_] = Menus,
+ OnMac = os:type() =:= {unix, darwin},
+ Index = if Type =:= default -> 0;
+ First =:= "File" -> 0;
+ OnMac -> 0;
+ true -> 1
+ end,
+ wx:foldl(Add, Index, Menus),
+ ok.
+
+create_menu("File", MenuItems, Index, MenuBar, Type) ->
+ OnMac = os:type() =:= {unix, darwin},
+ if OnMac, Type =:= default ->
+ Index;
+ not OnMac, Type =:= plugin ->
+ MenuId = wxMenuBar:findMenu(MenuBar, "File"),
+ Menu = wxMenuBar:getMenu(MenuBar, MenuId),
+ lists:foldl(fun(Record, N) ->
+ create_menu_item(Record, Menu, N)
+ end, 0, MenuItems),
+ Index + 1;
+ true ->
+ Menu = wxMenu:new(),
+ lists:foldl(fun(Record, N) ->
+ create_menu_item(Record, Menu, N)
+ end, 0, MenuItems),
+ wxMenuBar:insert(MenuBar, Index, Menu, "File"),
+ Index+1
+ end;
+create_menu(Name, MenuItems, Index, MenuBar, _Type) ->
+ Menu = wxMenu:new(),
+ lists:foldl(fun(Record, N) ->
+ create_menu_item(Record, Menu, N)
+ end, 0, MenuItems),
+ wxMenuBar:insert(MenuBar, Index, Menu, Name),
+ Index+1.
+
+create_menu_item(#create_menu{id = ?wxID_HELP=Id}, Menu, Index) ->
+ wxMenu:insert(Menu, Index, Id),
+ Index+1;
+create_menu_item(#create_menu{id=Id, text=Text, help=Help, type=Type, check=Check},
+ Menu, Index) ->
+ Opts = case Help of
+ [] -> [];
+ _ -> [{help, Help}]
+ end,
+ case Type of
+ append ->
+ wxMenu:insert(Menu, Index, Id,
+ [{text, Text}|Opts]);
+ check ->
+ wxMenu:insertCheckItem(Menu, Index, Id, Text, Opts),
+ wxMenu:check(Menu, Id, Check);
+ radio ->
+ wxMenu:insertRadioItem(Menu, Index, Id, Text, Opts),
+ wxMenu:check(Menu, Id, Check);
+ separator ->
+ wxMenu:insertSeparator(Menu, Index)
+ end,
+ Index+1;
+create_menu_item(separator, Menu, Index) ->
+ wxMenu:insertSeparator(Menu, Index),
+ Index+1.
+
+create_attrs() ->
+ Font = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
+ Text = case wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOXTEXT) of
+ {255,255,255,_} -> {10,10,10}; %% Is white on Mac for some reason
+ Color -> Color
+ end,
+ #attrs{even = wxListItemAttr:new(Text, ?BG_EVEN, Font),
+ odd = wxListItemAttr:new(Text, ?BG_ODD, Font),
+ deleted = wxListItemAttr:new(?FG_DELETED, ?BG_DELETED, Font),
+ changed = wxListItemAttr:new(Text, ?BG_CHANGED, Font),
+ searched = wxListItemAttr:new(Text, ?BG_SEARCHED, Font)
+ }.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_box_info({Title, List}) when is_list(List) -> {Title, ?wxALIGN_LEFT, List};
+get_box_info({Title, left, List}) -> {Title, ?wxALIGN_LEFT, List};
+get_box_info({Title, right, List}) -> {Title, ?wxALIGN_RIGHT, List}.
+
+create_box(Panel, Data) ->
+ {Title, Align, Info} = get_box_info(Data),
+ Box = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, [{label, Title}]),
+ Left = wxBoxSizer:new(?wxVERTICAL),
+ Right = wxBoxSizer:new(?wxVERTICAL),
+ Expand = [{flag, ?wxEXPAND}],
+ ExpAlign = [{flag, Align}],
+ AddRow = fun({Desc, Value}) ->
+ wxSizer:add(Left, wxStaticText:new(Panel, ?wxID_ANY, Desc ++ ":"), Expand),
+ Field = wxStaticText:new(Panel, ?wxID_ANY, to_str(Value)),
+ wxSizer:add(Right, Field, ExpAlign),
+ Field
+ end,
+ InfoFields = [AddRow(Entry) || Entry <- Info],
+ wxSizer:add(Box, Left),
+ wxSizer:addSpacer(Box, 10),
+ wxSizer:add(Box, Right),
+ wxSizer:addSpacer(Box, 30),
+ {Box, InfoFields}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+set_listctrl_col_size(LCtrl, Total) ->
+ wx:batch(fun() -> calc_last(LCtrl, Total) end).
+
+calc_last(LCtrl, _Total) ->
+ Cols = wxListCtrl:getColumnCount(LCtrl),
+ {Total, _} = wxWindow:getClientSize(LCtrl),
+ SBSize = scroll_size(LCtrl),
+ Last = lists:foldl(fun(I, Last) ->
+ Last - wxListCtrl:getColumnWidth(LCtrl, I)
+ end, Total-SBSize, lists:seq(0, Cols - 2)),
+ Size = max(150, Last),
+ wxListCtrl:setColumnWidth(LCtrl, Cols-1, Size).
+
+scroll_size(LCtrl) ->
+ case os:type() of
+ {win32, nt} -> 0;
+ {unix, darwin} ->
+ %% I can't figure out is there is a visible scrollbar
+ %% Always make room for it
+ wxSystemSettings:getMetric(?wxSYS_VSCROLL_X);
+ _ ->
+ case wxWindow:hasScrollbar(LCtrl, ?wxVERTICAL) of
+ true -> wxSystemSettings:getMetric(?wxSYS_VSCROLL_X);
+ false -> 0
+ end
+ end.
+
+
+user_term(Parent, Title, Default) ->
+ Dialog = wxTextEntryDialog:new(Parent, Title, [{value, Default}]),
+ case wxTextEntryDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Str = wxTextEntryDialog:getValue(Dialog),
+ wxTextEntryDialog:destroy(Dialog),
+ parse_string(ensure_last_is_dot(Str));
+ ?wxID_CANCEL ->
+ wxTextEntryDialog:destroy(Dialog),
+ cancel
+ end.
+
+user_term_multiline(Parent, Title, Default) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, Title,
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor
+ ?wxRESIZE_BORDER}]),
+ Panel = wxPanel:new(Dialog),
+
+ TextCtrl = wxTextCtrl:new(Panel, ?wxID_ANY,
+ [{value, Default},
+ {style, ?wxDEFAULT bor ?wxTE_MULTILINE}]),
+ Line = wxStaticLine:new(Panel, [{style, ?wxLI_HORIZONTAL}]),
+
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+
+ InnerSizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(InnerSizer, TextCtrl,
+ [{flag, ?wxEXPAND bor ?wxALL},{proportion, 1},{border, 5}]),
+ wxSizer:add(InnerSizer, Line,
+ [{flag, ?wxEXPAND},{proportion, 0},{border, 5}]),
+ wxPanel:setSizer(Panel, InnerSizer),
+
+ TopSizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(TopSizer, Panel,
+ [{flag, ?wxEXPAND bor ?wxALL},{proportion, 1},{border, 5}]),
+ wxSizer:add(TopSizer, Buttons,
+ [{flag, ?wxEXPAND bor ?wxBOTTOM bor ?wxRIGHT},{border, 10}]),
+
+ % calculate the size of TopSizer when the whole user_term
+ % fits in the TextCtrl
+ DC = wxClientDC:new(Panel),
+ W = wxDC:getCharWidth(DC),
+ H = wxDC:getCharHeight(DC),
+ {EW, EH} = wxDC:getMultiLineTextExtent(DC, Default),
+ wxSizer:setItemMinSize(InnerSizer, 0, EW+2*W, EH+H),
+ TopSize = wxSizer:getMinSize(TopSizer),
+ % reset min size of TextCtrl to 40 chararacters * 4 lines
+ wxSizer:setItemMinSize(InnerSizer, 0, 40*W, 4*H),
+
+ wxWindow:setSizerAndFit(Dialog, TopSizer),
+ wxSizer:setSizeHints(TopSizer, Dialog),
+
+ wxWindow:setClientSize(Dialog, TopSize),
+
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Str = wxTextCtrl:getValue(TextCtrl),
+ wxDialog:destroy(Dialog),
+ parse_string(ensure_last_is_dot(Str));
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ cancel
+ end.
+
+parse_string(Str) ->
+ try
+ Tokens = case erl_scan:string(Str) of
+ {ok, Ts, _} -> Ts;
+ {error, {_SLine, SMod, SError}, _} ->
+ throw(io_lib:format("~s", [SMod:format_error(SError)]))
+ end,
+ case erl_parse:parse_term(Tokens) of
+ {error, {_PLine, PMod, PError}} ->
+ throw(io_lib:format("~s", [PMod:format_error(PError)]));
+ Res -> Res
+ end
+ catch
+ throw:ErrStr ->
+ {error, ErrStr};
+ _:_Err ->
+ {error, ["Syntax error in: ", Str]}
+ end.
+
+ensure_last_is_dot([]) ->
+ ".";
+ensure_last_is_dot(String) ->
+ case lists:last(String) =:= $. of
+ true ->
+ String;
+ false ->
+ String ++ "."
+ end.
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
new file mode 100644
index 0000000000..abf90ac612
--- /dev/null
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -0,0 +1,575 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_perf_wx).
+
+-export([start_link/2]).
+
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_sync_event/3, handle_cast/2]).
+
+%% Drawing wrappers for DC and GC areas
+-export([haveGC/1,
+ setPen/2, setFont/3, setBrush/2,
+ strokeLine/5, strokeLines/2, drawRoundedRectangle/6,
+ drawText/4, getTextExtent/2]).
+
+-behaviour(wx_object).
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+-record(state,
+ {
+ offset = 0.0,
+ active = false,
+ parent,
+ windows,
+ data = {0, queue:new()},
+ panel,
+ paint,
+ appmon,
+ usegc = false
+ }).
+
+-define(wxGC, wxGraphicsContext).
+
+-record(paint, {font, small, pen, pen2, pens}).
+
+-define(RQ_W, 1).
+-define(MEM_W, 2).
+-define(IO_W, 3).
+
+start_link(Notebook, Parent) ->
+ wx_object:start_link(?MODULE, [Notebook, Parent], []).
+
+init([Notebook, Parent]) ->
+ try
+ Panel = wxPanel:new(Notebook),
+ Main = wxBoxSizer:new(?wxVERTICAL),
+ Style = ?wxFULL_REPAINT_ON_RESIZE bor ?wxCLIP_CHILDREN,
+ CPU = wxPanel:new(Panel, [{winid, ?RQ_W}, {style,Style}]),
+ wxWindow:setBackgroundColour(CPU, ?wxWHITE),
+ wxSizer:add(Main, CPU, [{flag, ?wxEXPAND bor ?wxALL},
+ {proportion, 1}, {border, 5}]),
+ MemIO = wxBoxSizer:new(?wxHORIZONTAL),
+ MEM = wxPanel:new(Panel, [{winid, ?MEM_W}, {style,Style}]),
+ wxWindow:setBackgroundColour(MEM, ?wxWHITE),
+ IO = wxPanel:new(Panel, [{winid, ?IO_W}, {style,Style}]),
+ wxWindow:setBackgroundColour(IO, ?wxWHITE),
+ wxSizer:add(MemIO, MEM, [{flag, ?wxEXPAND bor ?wxLEFT},
+ {proportion, 1}, {border, 5}]),
+ wxSizer:add(MemIO, IO, [{flag, ?wxEXPAND bor ?wxLEFT bor ?wxRIGHT},
+ {proportion, 1}, {border, 5}]),
+ wxSizer:add(Main, MemIO, [{flag, ?wxEXPAND bor ?wxDOWN},
+ {proportion, 1}, {border, 5}]),
+ wxWindow:setSizer(Panel, Main),
+
+ wxPanel:connect(CPU, paint, [callback]),
+ wxPanel:connect(IO, paint, [callback]),
+ wxPanel:connect(MEM, paint, [callback]),
+ case os:type() of
+ {win32, _} -> %% Ignore erase on windows
+ wxPanel:connect(CPU, erase_background, [{callback, fun(_,_) -> ok end}]),
+ wxPanel:connect(IO, erase_background, [{callback, fun(_,_) -> ok end}]),
+ wxPanel:connect(MEM, erase_background, [{callback, fun(_,_) -> ok end}]);
+ _ -> ok
+ end,
+
+ UseGC = haveGC(Panel),
+ {Font, SmallFont}
+ = case os:type() of
+ {unix, _} when UseGC ->
+ %% Def font is really small when using Graphics contexts for some reason
+ %% Hardcode it
+ F = wxFont:new(12,?wxFONTFAMILY_DECORATIVE,?wxFONTSTYLE_NORMAL,?wxFONTWEIGHT_BOLD),
+ SF = wxFont:new(10, ?wxFONTFAMILY_DECORATIVE, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
+ {F, SF};
+ _ ->
+ DefFont = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
+ DefSize = wxFont:getPointSize(DefFont),
+ DefFamily = wxFont:getFamily(DefFont),
+ F = wxFont:new(DefSize, DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_BOLD),
+ SF = wxFont:new(DefSize-1, DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
+ {F, SF}
+ end,
+ BlackPen = wxPen:new({0,0,0}, [{width, 2}]),
+ Pens = [wxPen:new(Col, [{width, 2}]) || Col <- tuple_to_list(colors())],
+ process_flag(trap_exit, true),
+ {Panel, #state{parent=Parent,
+ panel =Panel,
+ windows = {CPU, MEM, IO},
+ usegc=UseGC,
+ paint=#paint{font = Font,
+ small = SmallFont,
+ pen = ?wxGREY_PEN,
+ pen2 = BlackPen,
+ pens = list_to_tuple(Pens)
+ }
+ }}
+ catch _:Err ->
+ io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
+ {stop, Err}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+handle_event(#wx{event=#wxCommand{type=command_menu_selected}},
+ State = #state{}) ->
+ {noreply, State};
+
+handle_event(Event, _State) ->
+ error({unhandled_event, Event}).
+
+%%%%%%%%%%
+handle_sync_event(#wx{obj=Panel, event = #wxPaint{}},_,
+ #state{active=Active, offset=Offset, paint=Paint,
+ windows=Windows, data=Data, usegc=UseGC}) ->
+ %% PaintDC must be created in a callback to work on windows.
+ %% Sigh workaround bug on MacOSX (Id in paint event is always 0)
+ %% Panel = element(Id, Windows),
+ Id = if Panel =:= element(?RQ_W, Windows) -> ?RQ_W;
+ Panel =:= element(?MEM_W, Windows) -> ?MEM_W;
+ Panel =:= element(?IO_W, Windows) -> ?IO_W
+ end,
+ IsWindows = element(1, os:type()) =:= win32,
+
+ DC = if IsWindows ->
+ %% Ugly hack to aviod flickering on windows, works on windows only
+ %% But the other platforms are doublebuffered by default
+ wx:typeCast(wxBufferedPaintDC:new(Panel), wxPaintDC);
+ true ->
+ wxPaintDC:new(Panel)
+ end,
+ IsWindows andalso wxDC:clear(DC),
+ GC = if UseGC -> ?wxGC:create(DC);
+ true -> DC
+ end,
+ %% Nothing is drawn until wxPaintDC is destroyed.
+ try
+ draw(Offset, Id, {UseGC, GC}, Panel, Paint, Data, Active)
+ catch _:Err ->
+ io:format("Internal error ~p ~p~n",[Err, erlang:get_stacktrace()])
+ end,
+ UseGC andalso ?wxGC:destroy(GC),
+ wxPaintDC:destroy(DC),
+ ok.
+%%%%%%%%%%
+handle_call(Event, From, _State) ->
+ error({unhandled_call, Event, From}).
+
+handle_cast(Event, _State) ->
+ error({unhandled_cast, Event}).
+%%%%%%%%%%
+handle_info(Stats = {stats, 1, _, _, _},
+ State = #state{panel=Panel, data=Data, active=Active}) ->
+ if Active ->
+ wxWindow:refresh(Panel),
+ Freq = 6,
+ erlang:send_after(trunc(1000 / Freq), self(), {refresh, 1, Freq});
+ true -> ignore
+ end,
+ {noreply, State#state{offset=0.0, data = add_data(Stats, Data)}};
+
+handle_info({refresh, Seq, Freq}, State = #state{panel=Panel, offset=Prev}) ->
+ wxWindow:refresh(Panel),
+ Next = Seq+1,
+ if Seq > 1, Prev =:= 0.0 ->
+ %% We didn't have time to handle the refresh
+ {noreply, State};
+ Next < Freq ->
+ erlang:send_after(trunc(1000 / Freq), self(), {refresh, Next, Freq}),
+ {noreply, State#state{offset=Seq/Freq}};
+ true ->
+ {noreply, State#state{offset=Seq/Freq}}
+ end;
+
+handle_info({active, Node}, State = #state{parent=Parent, panel=Panel, appmon=Old}) ->
+ create_menus(Parent, []),
+ try
+ Node = node(Old),
+ wxWindow:refresh(Panel),
+ {noreply, State#state{active=true}}
+ catch _:_ ->
+ catch Old ! exit,
+ Me = self(),
+ Pid = spawn_link(Node, observer_backend, fetch_stats, [Me, 1000]),
+ wxWindow:refresh(Panel),
+ {noreply, State#state{active=true, appmon=Pid, data={0, queue:new()}}}
+ end;
+
+handle_info(not_active, State = #state{appmon=_Pid}) ->
+ %% Pid ! exit,
+ {noreply, State#state{active=false}};
+
+handle_info({'EXIT', Old, _}, State = #state{appmon=Old}) ->
+ {noreply, State#state{active=false, appmon=undefined}};
+
+handle_info(_Event, State) ->
+ %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]),
+ {noreply, State}.
+
+%%%%%%%%%%
+terminate(_Event, #state{appmon=Pid}) ->
+ catch Pid ! exit,
+ ok.
+code_change(_, _, State) ->
+ State.
+
+add_data(Stats, {N, Q}) when N > 60 ->
+ {N, queue:drop(queue:in(Stats, Q))};
+add_data(Stats, {N, Q}) ->
+ {N+1, queue:in(Stats, Q)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_menus(Parent, _) ->
+ MenuEntries =
+ [{"File",
+ [
+ ]}
+ ],
+ observer_wx:create_menus(Parent, MenuEntries).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+collect_data(?RQ_W, {N, Q}) ->
+ case queue:to_list(Q) of
+ [] -> {0, 0, []};
+ [_] -> {0, 0, []};
+ [{stats, _Ver, Init0, _IO, _Mem}|Data0] ->
+ Init = lists:sort(Init0),
+ [_|Data=[First|_]] = lists:foldl(fun({stats, _, T0, _, _}, [Prev|Acc]) ->
+ TN = lists:sort(T0),
+ Delta = calc_delta(TN, Prev),
+ [TN, list_to_tuple(Delta)|Acc]
+ end, [Init], Data0),
+ {N, lmax(Data), lists:reverse([First|Data])}
+ end;
+collect_data(?MEM_W, {N, Q}) ->
+ MemT = mem_types(),
+ Data = [list_to_tuple([Value || {Type,Value} <- MemInfo,
+ lists:member(Type, MemT)])
+ || {stats, _Ver, _RQ, _IO, MemInfo} <- queue:to_list(Q)],
+ {N, lmax(Data), Data};
+collect_data(?IO_W, {N, Q}) ->
+ case queue:to_list(Q) of
+ [] -> {0, 0, []};
+ [_] -> {0, 0, []};
+ [{stats, _Ver, _RQ, {{_,In0}, {_,Out0}}, _Mem}|Data0] ->
+ [_,_|Data=[First|_]] =
+ lists:foldl(fun({stats, _, _, {{_,In}, {_,Out}}, _}, [PIn,Pout|Acc]) ->
+ [In,Out,{In-PIn,Out-Pout}|Acc]
+ end, [In0,Out0], Data0),
+ {N, lmax(Data), lists:reverse([First|Data])}
+ end.
+
+mem_types() ->
+ [total, processes, atom, binary, code, ets].
+
+lmax([]) -> 0;
+lmax(List) ->
+ lists:max([lists:max(tuple_to_list(T)) || T <- List]).
+
+calc_delta([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) ->
+ [100*(WN-WP) div (TN-TP)|calc_delta(Ss, Ps)];
+calc_delta([], []) -> [].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+draw(Offset, Id, DC, Panel, Paint=#paint{pens=Pens, small=Small}, Data, Active) ->
+ %% This can be optimized a lot by collecting data once
+ %% and draw to memory and then blit memory and only draw new entries in new memory
+ %% area. Hmm now rewritten to use ?wxGC I don't now if it is feasable.
+ {Len, Max0, Hs} = collect_data(Id, Data),
+ Max = calc_max(Max0),
+ NoGraphs = try tuple_size(hd(Hs)) catch _:_ -> 0 end,
+ Size = wxWindow:getClientSize(Panel),
+ {X0,Y0,WS,HS} = draw_borders(Id, NoGraphs, DC, Size, Max, Paint),
+ Last = 60*WS+X0-1,
+ Start = max(61-Len, 0)*WS+X0 - Offset*WS,
+ case Hs of
+ [] -> ignore;
+ [_] -> ignore;
+ _ ->
+ Draw = fun(N) ->
+ Lines = make_lines(Hs, Start, N, {X0,Max*HS,Last}, Y0, WS, HS),
+ setPen(DC, element(1+ ((N-1) rem tuple_size(Pens)), Pens)),
+ strokeLines(DC, Lines),
+ N+1
+ end,
+ [Draw(I) || I <- lists:seq(NoGraphs, 1, -1)]
+ end,
+ case Active of
+ false ->
+ NotActive = "Service not available",
+ setFont(DC, Small, {0,0,0}),
+ drawText(DC, NotActive, X0 + 100, element(2,Size) div 2);
+ true ->
+ ignore
+ end,
+ ok.
+
+make_lines(Ds = [Data|_], PX, N, Clip, ZeroY, WS, HS) ->
+ Y = element(N,Data),
+ make_lines(Ds, PX, N, Clip, ZeroY, WS, HS, Y, []).
+
+make_lines([D1 | Ds = [D2|Rest]], PX, N, Clip={Cx,Cy, _}, ZeroY, WS, HS, Y0, Acc0) ->
+ Y1 = element(N,D1),
+ Y2 = element(N,D2),
+ Y3 = case Rest of
+ [D3|_] -> element(N,D3);
+ [] -> Y2
+ end,
+ This = {max(Cx, PX),ZeroY-min(Cy,Y1*HS)},
+ Acc = if (abs(Y1-Y2) * HS) < 3.0 -> [This|Acc0];
+ WS < 3.0 -> [This|Acc0];
+ PX < Cx ->
+ make_splines(Y0,Y1,Y2,Y3,PX,Clip,ZeroY,WS,HS,Acc0);
+ true ->
+ make_splines(Y0,Y1,Y2,Y3,PX,Clip,ZeroY,WS,HS,[This|Acc0])
+ end,
+ make_lines(Ds, PX+WS, N, Clip, ZeroY, WS, HS, Y1, Acc);
+make_lines([D1], _PX, N, {_,Cy,Last}, ZeroY, _WS, HS, _Y0, Acc) ->
+ Y1 = element(N,D1),
+ [{Last,ZeroY-min(Cy, Y1*HS)}|Acc].
+
+make_splines(Y00,Y10,Y20,Y30,PX,Clip,ZeroY,WS,HS,Acc) ->
+ Y1 = Y10*HS,
+ Y2 = Y20*HS,
+ Steps = min(abs(Y1-Y2), WS),
+ if Steps > 2 ->
+ Y0 = Y00*HS,
+ Y3 = Y30*HS,
+ Tan = spline_tan(Y0,Y1,Y2,Y3),
+ Delta = 1/Steps,
+ splines(Steps-1, 0.0, Delta, Tan, Y1,Y2, PX, Clip,ZeroY, Delta*WS, Acc);
+ true ->
+ Acc
+ end.
+
+splines(N, XD, XD0, Tan, Y1,Y2, PX0, Clip={Cx,Cy,_},ZeroY, WS, Acc) when N > 0 ->
+ PX = PX0+WS,
+ Delta = XD+XD0,
+ if PX < Cx ->
+ splines(N-1, Delta, XD0, Tan, Y1, Y2, PX, Clip,ZeroY, WS, Acc);
+ true ->
+ Y = min(Cy, max(0,spline(Delta, Tan, Y1,Y2))),
+ splines(N-1, Delta, XD0, Tan, Y1, Y2, PX, Clip,ZeroY, WS,
+ [{PX, ZeroY-Y}|Acc])
+ end;
+splines(_N, _XD, _XD0, _Tan, _Y1,_Y2, _PX, _Clip,_ZeroY, _WS, Acc) -> Acc.
+
+spline(T, {M1, M2}, Y1, Y2) ->
+ %% Hermite Basis Funcs
+ T2 = T*T, T3 = T*T*T,
+ H1 = 2*T3-3*T2+1,
+ H2 = -2*T3+3*T2,
+ H3 = T3-2*T2+T,
+ H4 = T3-T2,
+ %% Result
+ M1*H3 + Y1*H1 + Y2*H2 + M2*H4.
+
+spline_tan(Y0, Y1, Y2, Y3) ->
+ S = 1.0,
+ C = 0.5,
+ %% Calc tangent values
+ M1 = S*C*(Y2-Y0),
+ M2 = S*C*(Y3-Y1),
+ {M1,M2}.
+
+-define(BW, 5).
+-define(BH, 5).
+
+draw_borders(Type, NoGraphs, DC, {W,H}, Max,
+ #paint{pen=Pen, pen2=Pen2, font=Font, small=Small}) ->
+ {Unit, MaxUnit} = bytes(Type, Max),
+ Str1 = observer_lib:to_str(MaxUnit),
+ Str2 = observer_lib:to_str(MaxUnit div 2),
+ Str3 = observer_lib:to_str(0),
+
+ setFont(DC, Font, {0,0,0}),
+ {TW,TH} = getTextExtent(DC, Str1),
+ {SpaceW, _} = getTextExtent(DC, "W"),
+
+ GraphX0 = ?BW+TW+?BW,
+ GraphX1 = W-?BW*4,
+ TopTextX = ?BW+TW+?BW,
+ MaxTextY = ?BH+TH+?BH,
+ BottomTextY = H-?BH-TH,
+ SecondsY = BottomTextY - ?BH - TH,
+ GraphY0 = MaxTextY + (TH / 2),
+ GraphY1 = SecondsY - ?BH,
+ GraphW = GraphX1-GraphX0-1,
+ GraphH = GraphY1-GraphY0-1,
+ GraphY25 = GraphY0 + (GraphY1 - GraphY0) / 4,
+ GraphY50 = GraphY0 + (GraphY1 - GraphY0) / 2,
+ GraphY75 = GraphY0 + 3*(GraphY1 - GraphY0) / 4,
+ ScaleW = GraphW / 60,
+ ScaleH = GraphH / Max,
+
+ setFont(DC, Small, {0,0,0}),
+ Align = fun(Str, Y) ->
+ {StrW, _} = getTextExtent(DC, Str),
+ drawText(DC, Str, GraphX0 - StrW - ?BW, Y)
+ end,
+ Align(Str1, MaxTextY),
+ Align(Str2, GraphY50 - (TH / 2)),
+ Align(Str3, GraphY1 - (TH / 2) + 1),
+
+ setPen(DC, Pen),
+ DrawSecs = fun(Secs, Pos) ->
+ Str = [observer_lib:to_str(Secs)|" s"],
+ X = GraphX0+Pos,
+ drawText(DC, Str, X-SpaceW, SecondsY),
+ strokeLine(DC, X, GraphY0, X, GraphY1+5),
+ Pos + 10*ScaleW
+ end,
+ lists:foldl(DrawSecs, 0, lists:seq(60,0, -10)),
+
+ strokeLine(DC, GraphX0-3, GraphY25, GraphX1, GraphY25),
+ strokeLine(DC, GraphX0-3, GraphY50, GraphX1, GraphY50),
+ strokeLine(DC, GraphX0-3, GraphY75, GraphX1, GraphY75),
+
+ setPen(DC, Pen2),
+ strokeLines(DC, [{GraphX0, GraphY0-1}, {GraphX0, GraphY1+1},
+ {GraphX1, GraphY1+1}, {GraphX1, GraphY0-1},
+ {GraphX0, GraphY0-1}]),
+
+ setFont(DC, Font, {0,0,0}),
+ case Type of
+ ?RQ_W -> drawText(DC, "Scheduler Utilization (%) ", TopTextX,?BH);
+ ?MEM_W -> drawText(DC, "Memory Usage " ++ Unit, TopTextX,?BH);
+ ?IO_W -> drawText(DC, "IO Usage " ++ Unit, TopTextX,?BH)
+ end,
+
+ Text = fun(X,Y, Str, PenId) ->
+ if PenId == 0 ->
+ setFont(DC, Font, {0,0,0});
+ PenId > 0 ->
+ Id = 1 + ((PenId-1) rem tuple_size(colors())),
+ setFont(DC, Font, element(Id, colors()))
+ end,
+ drawText(DC, Str, X, Y),
+ {StrW, _} = getTextExtent(DC, Str),
+ StrW + X + SpaceW
+ end,
+ case Type of
+ ?RQ_W ->
+ TN0 = Text(?BW, BottomTextY, "Scheduler: ", 0),
+ lists:foldl(fun(Id, Pos0) ->
+ Text(Pos0, BottomTextY, integer_to_list(Id), Id)
+ end, TN0, lists:seq(1, NoGraphs));
+ ?MEM_W ->
+ lists:foldl(fun(MType, {PenId, Pos0}) ->
+ Str = uppercase(atom_to_list(MType)),
+ Pos = Text(Pos0, BottomTextY, Str, PenId),
+ {PenId+1, Pos}
+ end, {1, ?BW}, mem_types());
+ ?IO_W ->
+ TN0 = Text(?BW, BottomTextY, "Input", 1),
+ Text(TN0, BottomTextY, "Output", 2)
+ end,
+ {GraphX0+1, GraphY1, ScaleW, ScaleH}.
+
+uppercase([C|Rest]) ->
+ [C-$a+$A|Rest].
+
+calc_max(Max) when Max < 10 -> 10;
+calc_max(Max) -> calc_max1(Max).
+
+calc_max1(Max) ->
+ case Max div 10 of
+ X when X < 10 ->
+ case Max rem 10 of
+ 0 -> Max;
+ _ ->
+ (X+1)*10
+ end;
+ X ->
+ 10*calc_max1(X)
+ end.
+
+bytes(?RQ_W, Val) -> {"", Val};
+bytes(_, B) ->
+ KB = B div 1024,
+ MB = KB div 1024,
+ GB = MB div 1024,
+ if
+ GB > 10 -> {"(GB)", GB};
+ MB > 10 -> {"(MB)", MB};
+ KB > 0 -> {"(KB)", KB};
+ true -> {"(B)", B}
+ end.
+
+colors() ->
+ {{200, 50, 50}, {50, 200, 50}, {50, 50, 200},
+ {255, 110, 0}, {50, 200, 200}, {200, 50, 200},
+ {240, 200, 80}, {140, 2, 140},
+ {100, 200, 240}, {100, 240, 100}
+ }.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% wxDC and ?wxGC wrappers
+
+haveGC(Win) ->
+ try
+ GC = ?wxGC:create(Win),
+ ?wxGC:destroy(GC),
+ true
+ catch _:_ -> false
+ end.
+
+setPen({false, DC}, Pen) ->
+ wxDC:setPen(DC, Pen);
+setPen({true, GC}, Pen) ->
+ ?wxGC:setPen(GC, Pen).
+
+setFont({false, DC}, Font, Color) ->
+ wxDC:setTextForeground(DC, Color),
+ wxDC:setFont(DC, Font);
+setFont({true, GC}, Font, Color) ->
+ ?wxGC:setFont(GC, Font, Color).
+
+setBrush({false, DC}, Brush) ->
+ wxDC:setBrush(DC, Brush);
+setBrush({true, GC}, Brush) ->
+ ?wxGC:setBrush(GC, Brush).
+
+strokeLine({false, DC}, X0, Y0, X1, Y1) ->
+ wxDC:drawLine(DC, {round(X0), round(Y0)}, {round(X1), round(Y1)});
+strokeLine({true, GC}, X0, Y0, X1, Y1) ->
+ ?wxGC:strokeLine(GC, X0, Y0, X1, Y1).
+
+strokeLines({false, DC}, Lines) ->
+ wxDC:drawLines(DC, [{round(X), round(Y)} || {X,Y} <- Lines]);
+strokeLines({true, GC}, Lines) ->
+ ?wxGC:strokeLines(GC, Lines).
+
+drawRoundedRectangle({false, DC}, X0, Y0, X1, Y1, R) ->
+ wxDC:drawRoundedRectangle(DC, {round(X0), round(Y0)}, {round(X1), round(Y1)}, round(R));
+drawRoundedRectangle({true, GC}, X0, Y0, X1, Y1, R) ->
+ ?wxGC:drawRoundedRectangle(GC, X0, Y0, X1, Y1, R).
+
+drawText({false, DC}, Str, X, Y) ->
+ wxDC:drawText(DC, Str, {round(X),round(Y)});
+drawText({true, GC}, Str, X, Y) ->
+ ?wxGC:drawText(GC, Str, X, Y).
+
+getTextExtent({false, DC}, Str) ->
+ wxDC:getTextExtent(DC, Str);
+getTextExtent({true, GC}, Str) ->
+ {W,H,_,_} = ?wxGC:getTextExtent(GC, Str),
+ {W,H}.
diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl
new file mode 100644
index 0000000000..ee67664539
--- /dev/null
+++ b/lib/observer/src/observer_pro_wx.erl
@@ -0,0 +1,600 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_pro_wx).
+
+-behaviour(wx_object).
+
+-export([start_link/2]).
+
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_cast/2]).
+
+-include_lib("wx/include/wx.hrl").
+-include("../include/etop.hrl").
+-include("observer_defs.hrl").
+-include("etop_defs.hrl").
+
+%% Defines
+-define(COL_PID, 0).
+-define(COL_NAME, ?COL_PID+1).
+%%-define(COL_TIME, 2).
+-define(COL_REDS, ?COL_NAME+1).
+-define(COL_MEM, ?COL_REDS+1).
+-define(COL_MSG, ?COL_MEM+1).
+-define(COL_FUN, ?COL_MSG+1).
+
+-define(ID_KILL, 201).
+-define(ID_PROC, 202).
+-define(ID_REFRESH, 203).
+-define(ID_REFRESH_INTERVAL, 204).
+-define(ID_DUMP_TO_FILE, 205).
+-define(ID_TRACE_PIDS, 206).
+-define(ID_TRACE_NAMES, 207).
+-define(ID_TRACE_NEW, 208).
+-define(ID_TRACE_ALL, 209).
+-define(ID_ACCUMULATE, 210).
+
+-define(TRACE_PIDS_STR, "Trace selected process identifiers").
+-define(TRACE_NAMES_STR, "Trace selected processes, "
+ "if a process have a registered name "
+ "processes with same name will be traced on all nodes").
+
+
+%% Records
+
+-record(sort,
+ {
+ sort_key=?COL_REDS,
+ sort_incr=false
+ }).
+
+-record(holder, {parent,
+ info,
+ sort=#sort{},
+ accum=[],
+ attrs,
+ node,
+ backend_pid
+ }).
+
+-record(state, {parent,
+ grid,
+ panel,
+ popup_menu,
+ parent_notebook,
+ timer,
+ procinfo_menu_pids=[],
+ sel={[], []},
+ holder}).
+
+start_link(Notebook, Parent) ->
+ wx_object:start_link(?MODULE, [Notebook, Parent], []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init([Notebook, Parent]) ->
+ Attrs = observer_lib:create_attrs(),
+ Self = self(),
+ Holder = spawn_link(fun() -> init_table_holder(Self, Attrs) end),
+ {ProPanel, State} = setup(Notebook, Parent, Holder),
+ {ProPanel, State#state{holder=Holder}}.
+
+setup(Notebook, Parent, Holder) ->
+ ProPanel = wxPanel:new(Notebook, []),
+
+ Grid = create_list_box(ProPanel, Holder),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxALL},
+ {proportion, 1},
+ {border,4}]),
+
+ wxWindow:setSizer(ProPanel, Sizer),
+
+ State = #state{parent=Parent,
+ grid=Grid,
+ panel=ProPanel,
+ parent_notebook=Notebook,
+ holder=Holder,
+ timer={false, 10}
+ },
+ {ProPanel, State}.
+
+
+%% UI-creation
+
+create_pro_menu(Parent, Holder) ->
+ MenuEntries = [{"File",
+ [#create_menu{id=?ID_DUMP_TO_FILE, text="Dump to file"}]},
+ {"View",
+ [#create_menu{id=?ID_ACCUMULATE, text="Accumulate",
+ type=check,
+ check=call(Holder, {get_accum, self()})},
+ separator,
+ #create_menu{id=?ID_REFRESH, text="Refresh\tCtrl-R"},
+ #create_menu{id=?ID_REFRESH_INTERVAL, text="Refresh Interval"}]},
+ {"Trace",
+ [#create_menu{id=?ID_TRACE_PIDS, text="Trace processes"},
+ #create_menu{id=?ID_TRACE_NAMES, text="Trace named processes (all nodes)"},
+ #create_menu{id=?ID_TRACE_NEW, text="Trace new processes"}
+ %% , #create_menu{id=?ID_TRACE_ALL_MENU, text="Trace all processes"}
+ ]}
+ ],
+ observer_wx:create_menus(Parent, MenuEntries).
+
+create_list_box(Panel, Holder) ->
+ Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_HRULES,
+ ListCtrl = wxListCtrl:new(Panel, [{style, Style},
+ {onGetItemText,
+ fun(_, Row, Col) ->
+ call(Holder, {get_row, self(), Row, Col})
+ end},
+ {onGetItemAttr,
+ fun(_, Item) ->
+ call(Holder, {get_attr, self(), Item})
+ end}
+ ]),
+ Li = wxListItem:new(),
+ AddListEntry = fun({Name, Align, DefSize}, Col) ->
+ wxListItem:setText(Li, Name),
+ wxListItem:setAlign(Li, Align),
+ wxListCtrl:insertColumn(ListCtrl, Col, Li),
+ wxListCtrl:setColumnWidth(ListCtrl, Col, DefSize),
+ Col + 1
+ end,
+ ListItems = [{"Pid", ?wxLIST_FORMAT_CENTRE, 120},
+ {"Name or Initial Func", ?wxLIST_FORMAT_LEFT, 200},
+%% {"Time", ?wxLIST_FORMAT_CENTRE, 50},
+ {"Reds", ?wxLIST_FORMAT_RIGHT, 100},
+ {"Memory", ?wxLIST_FORMAT_RIGHT, 100},
+ {"MsgQ", ?wxLIST_FORMAT_RIGHT, 50},
+ {"Current Function", ?wxLIST_FORMAT_LEFT, 200}],
+ lists:foldl(AddListEntry, 0, ListItems),
+ wxListItem:destroy(Li),
+
+ wxListCtrl:setItemCount(ListCtrl, 1),
+ wxListCtrl:connect(ListCtrl, size, [{skip, true}]),
+ wxListCtrl:connect(ListCtrl, command_list_item_activated),
+ wxListCtrl:connect(ListCtrl, command_list_item_right_click),
+ wxListCtrl:connect(ListCtrl, command_list_col_click),
+ %% Use focused instead of selected, selected doesn't generate events
+ %% for all multiple selections on Linux
+ wxListCtrl:connect(ListCtrl, command_list_item_focused),
+ ListCtrl.
+
+dump_to_file(Parent, FileName, Holder) ->
+ case file:open(FileName, [write]) of
+ {ok, Fd} ->
+ %% Holder closes the file when it's done
+ Holder ! {dump, Fd};
+ {error, Reason} ->
+ FailMsg = file:format_error(Reason),
+ MD = wxMessageDialog:new(Parent, FailMsg),
+ wxDialog:showModal(MD),
+ wxDialog:destroy(MD)
+ end.
+
+start_procinfo(undefined, _Frame, Opened) ->
+ Opened;
+start_procinfo(Pid, Frame, Opened) ->
+ %% This code doesn't work until we collect which windows have been
+ %% closed maybe it should moved to observer_wx.erl
+ %% and add a global menu which remembers windows.
+ %% case lists:keyfind(Pid, 1, Opened) of
+ %% false ->
+ case observer_procinfo:start(Pid, Frame, self()) of
+ {error, _} -> Opened;
+ PI -> [{Pid, PI} | Opened]
+ end.
+ %%;
+ %% {_, PI} ->
+ %% wxFrame:raise(PI),
+ %% Opened
+ %% end.
+
+call(Holder, What) ->
+ Ref = erlang:monitor(process, Holder),
+ Holder ! What,
+ receive
+ {'DOWN', Ref, _, _, _} -> "";
+ {Holder, Res} ->
+ erlang:demonitor(Ref),
+ Res
+ after 2000 ->
+ io:format("Hanging call ~p~n",[What]),
+ ""
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+handle_info({holder_updated, Count}, State0=#state{grid=Grid}) ->
+ State = update_selection(State0),
+
+ wxListCtrl:setItemCount(Grid, Count),
+ wxListCtrl:refreshItems(Grid, 0, Count-1),
+
+ {noreply, State};
+
+handle_info(refresh_interval, #state{holder=Holder}=State) ->
+ Holder ! refresh,
+ {noreply, State};
+
+handle_info({procinfo_menu_closed, Pid},
+ #state{procinfo_menu_pids=Opened}=State) ->
+ NewPids = lists:delete(Pid, Opened),
+ {noreply, State#state{procinfo_menu_pids=NewPids}};
+
+handle_info({active, Node},
+ #state{holder=Holder, timer=Timer, parent=Parent}=State) ->
+ create_pro_menu(Parent, Holder),
+ Holder ! {change_node, Node},
+ {noreply, State#state{timer=observer_lib:start_timer(Timer)}};
+
+handle_info(not_active, #state{timer=Timer0}=State) ->
+ Timer = observer_lib:stop_timer(Timer0),
+ {noreply, State#state{timer=Timer}};
+
+handle_info(Info, State) ->
+ io:format("~p:~p, Unexpected info: ~p~n", [?MODULE, ?LINE, Info]),
+ {noreply, State}.
+
+terminate(_Reason, #state{holder=Holder}) ->
+ Holder ! stop,
+ etop:stop(),
+ ok.
+
+code_change(_, _, State) ->
+ {ok, State}.
+
+handle_call(Msg, _From, State) ->
+ io:format("~p:~p: Unhandled call ~p~n",[?MODULE, ?LINE, Msg]),
+ {reply, ok, State}.
+
+
+handle_cast(Msg, State) ->
+ io:format("~p:~p: Unhandled cast ~p~n", [?MODULE, ?LINE, Msg]),
+ {noreply, State}.
+
+%%%%%%%%%%%%%%%%%%%%LOOP%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+handle_event(#wx{id=?ID_DUMP_TO_FILE}, #state{panel=Panel, holder=Holder}=State) ->
+ FD = wxFileDialog:new(Panel,
+ [{style,?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT}]),
+ case wxFileDialog:showModal(FD) of
+ ?wxID_OK ->
+ Path = wxFileDialog:getPath(FD),
+ wxDialog:destroy(FD),
+ dump_to_file(Panel, Path, Holder);
+ _ ->
+ wxDialog:destroy(FD)
+ end,
+ {noreply, State};
+
+handle_event(#wx{id=?ID_ACCUMULATE,
+ event=#wxCommand{type=command_menu_selected, commandInt=CmdInt}},
+ #state{holder=Holder}=State) ->
+ Holder ! {accum, CmdInt =:= 1},
+ {noreply, State};
+
+handle_event(#wx{id=?ID_REFRESH, event=#wxCommand{type=command_menu_selected}},
+ #state{holder=Holder}=State) ->
+ Holder ! refresh,
+ {noreply, State};
+
+handle_event(#wx{id=?ID_REFRESH_INTERVAL},
+ #state{panel=Panel, timer=Timer0}=State) ->
+ Timer = observer_lib:interval_dialog(Panel, Timer0, 1, 5*60),
+ {noreply, State#state{timer=Timer}};
+
+handle_event(#wx{id=?ID_KILL}, #state{sel={[_|Ids], [ToKill|Pids]}}=State) ->
+ exit(ToKill, kill),
+ {noreply, State#state{sel={Ids,Pids}}};
+
+
+handle_event(#wx{id=?ID_PROC},
+ #state{panel=Panel, sel={_, [Pid|_]},procinfo_menu_pids=Opened}=State) ->
+ Opened2 = start_procinfo(Pid, Panel, Opened),
+ {noreply, State#state{procinfo_menu_pids=Opened2}};
+
+handle_event(#wx{id=?ID_TRACE_PIDS}, #state{sel={_, Pids}, panel=Panel}=State) ->
+ case Pids of
+ [] ->
+ observer_wx:create_txt_dialog(Panel, "No selected processes", "Tracer", ?wxICON_EXCLAMATION),
+ {noreply, State};
+ Pids ->
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), Pids),
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?ID_TRACE_NAMES}, #state{sel={SelIds,_Pids}, holder=Holder, panel=Panel}=State) ->
+ case SelIds of
+ [] ->
+ observer_wx:create_txt_dialog(Panel, "No selected processes", "Tracer", ?wxICON_EXCLAMATION),
+ {noreply, State};
+ _ ->
+ PidsOrReg = call(Holder, {get_name_or_pid, self(), SelIds}),
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), PidsOrReg),
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?ID_TRACE_NEW, event=#wxCommand{type=command_menu_selected}}, State) ->
+ observer_trace_wx:add_processes(observer_wx:get_tracer(), [new]),
+ {noreply, State};
+
+handle_event(#wx{event=#wxSize{size={W,_}}},
+ #state{grid=Grid}=State) ->
+ observer_lib:set_listctrl_col_size(Grid, W),
+ {noreply, State};
+
+handle_event(#wx{event=#wxList{type=command_list_item_right_click,
+ itemIndex=Row}},
+ #state{panel=Panel, holder=Holder}=State) ->
+
+ case call(Holder, {get_row, self(), Row, pid}) of
+ {error, undefined} ->
+ undefined;
+ {ok, _} ->
+ Menu = wxMenu:new(),
+ wxMenu:append(Menu, ?ID_PROC, "Process info"),
+ wxMenu:append(Menu, ?ID_TRACE_PIDS, "Trace processes", [{help, ?TRACE_PIDS_STR}]),
+ wxMenu:append(Menu, ?ID_TRACE_NAMES, "Trace named processes (all nodes)",
+ [{help, ?TRACE_NAMES_STR}]),
+ wxMenu:append(Menu, ?ID_KILL, "Kill Process"),
+ wxWindow:popupMenu(Panel, Menu),
+ wxMenu:destroy(Menu)
+ end,
+ {noreply, State};
+
+handle_event(#wx{event=#wxList{type=command_list_item_focused,
+ itemIndex=Row}},
+ #state{grid=Grid,holder=Holder} = State) ->
+ case Row >= 0 of
+ true ->
+ SelIds = [Row|lists:delete(Row, get_selected_items(Grid))],
+ Pids = call(Holder, {get_pids, self(), SelIds}),
+ {noreply, State#state{sel={SelIds, Pids}}};
+ false ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{event=#wxList{type=command_list_col_click, col=Col}},
+ #state{holder=Holder}=State) ->
+ Holder ! {change_sort, Col},
+ {noreply, State};
+
+handle_event(#wx{event=#wxList{type=command_list_item_activated}},
+ #state{panel=Panel, procinfo_menu_pids=Opened,
+ sel={_, [Pid|_]}}=State)
+ when Pid =/= undefined ->
+ Opened2 = start_procinfo(Pid, Panel, Opened),
+ {noreply, State#state{procinfo_menu_pids=Opened2}};
+
+handle_event(Event, State) ->
+ io:format("~p:~p: handle event ~p\n", [?MODULE, ?LINE, Event]),
+ {noreply, State}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+update_selection(State=#state{holder=Holder, grid=Grid,
+ sel={SelIds0, SelPids0}}) ->
+ Sel = {SelIds,_SelPids} = call(Holder, {get_rows_from_pids, self(), SelPids0}),
+ set_focus(SelIds0, SelIds, Grid),
+ case SelIds =:= SelIds0 of
+ true -> ok;
+ false ->
+ wx:batch(fun() ->
+ [wxListCtrl:setItemState(Grid, I, 0, ?wxLIST_STATE_SELECTED) ||
+ I <- SelIds0],
+ [wxListCtrl:setItemState(Grid, I, 16#FFFF, ?wxLIST_STATE_SELECTED) ||
+ I <- SelIds]
+ end)
+ end,
+ %%io:format("Update ~p -> ~p~n",[{SelIds0, SelPids0}, Sel]),
+ State#state{sel=Sel}.
+
+get_selected_items(Grid) ->
+ get_selected_items(Grid, -1, []).
+
+get_selected_items(Grid, Index, ItemAcc) ->
+ Item = wxListCtrl:getNextItem(Grid, Index, [{geometry, ?wxLIST_NEXT_ALL},
+ {state, ?wxLIST_STATE_SELECTED}]),
+ case Item of
+ -1 ->
+ lists:reverse(ItemAcc);
+ _ ->
+ get_selected_items(Grid, Item, [Item | ItemAcc])
+ end.
+
+set_focus([], [], _Grid) -> ok;
+set_focus([Same|_], [Same|_], _Grid) -> ok;
+set_focus([], [New|_], Grid) ->
+ wxListCtrl:setItemState(Grid, New, 16#FFFF, ?wxLIST_STATE_FOCUSED);
+set_focus([Old|_], [], Grid) ->
+ wxListCtrl:setItemState(Grid, Old, 0, ?wxLIST_STATE_FOCUSED);
+set_focus([Old|_], [New|_], Grid) ->
+ wxListCtrl:setItemState(Grid, Old, 0, ?wxLIST_STATE_FOCUSED),
+ wxListCtrl:setItemState(Grid, New, 16#FFFF, ?wxLIST_STATE_FOCUSED).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%TABLE HOLDER%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init_table_holder(Parent, Attrs) ->
+ Backend = spawn_link(node(), observer_backend,etop_collect,[self()]),
+ table_holder(#holder{parent=Parent,
+ info=#etop_info{procinfo=[]},
+ node=node(),
+ backend_pid=Backend,
+ attrs=Attrs
+ }).
+
+table_holder(#holder{info=#etop_info{procinfo=Info}, attrs=Attrs,
+ node=Node, backend_pid=Backend}=S0) ->
+ receive
+ {get_row, From, Row, Col} ->
+ get_row(From, Row, Col, Info),
+ table_holder(S0);
+ {get_attr, From, Row} ->
+ get_attr(From, Row, Attrs),
+ table_holder(S0);
+ {Backend, EtopInfo=#etop_info{}} ->
+ State = handle_update(EtopInfo, S0),
+ table_holder(State#holder{backend_pid=undefined});
+ refresh when is_pid(Backend)->
+ table_holder(S0); %% Already updating
+ refresh ->
+ Pid = spawn_link(Node,observer_backend,etop_collect,[self()]),
+ table_holder(S0#holder{backend_pid=Pid});
+ {change_sort, Col} ->
+ State = change_sort(Col, S0),
+ table_holder(State);
+ {get_pids, From, Indices} ->
+ get_pids(From, Indices, Info),
+ table_holder(S0);
+ {get_rows_from_pids, From, Pids} ->
+ get_rows_from_pids(From, Pids, Info),
+ table_holder(S0);
+ {get_name_or_pid, From, Indices} ->
+ get_name_or_pid(From, Indices, Info),
+ table_holder(S0);
+
+ {get_node, From} ->
+ From ! {self(), Node},
+ table_holder(S0);
+ {change_node, NewNode} ->
+ case Node == NewNode of
+ true ->
+ table_holder(S0);
+ false ->
+ self() ! refresh,
+ table_holder(S0#holder{node=NewNode})
+ end;
+ {accum, Bool} ->
+ table_holder(change_accum(Bool,S0));
+ {get_accum, From} ->
+ From ! {self(), S0#holder.accum == true},
+ table_holder(S0);
+ {dump, Fd} ->
+ etop_txt:do_update(Fd, S0#holder.info, #opts{node=Node}),
+ file:close(Fd),
+ table_holder(S0);
+ stop ->
+ ok;
+ What ->
+ io:format("Table holder got ~p~n",[What]),
+ table_holder(S0)
+ end.
+
+change_sort(Col, S0=#holder{parent=Parent, info=EI=#etop_info{procinfo=Data}, sort=Sort0}) ->
+ {Sort, ProcInfo}=sort(Col, Sort0, Data),
+ Parent ! {holder_updated, length(Data)},
+ S0#holder{info=EI#etop_info{procinfo=ProcInfo}, sort=Sort}.
+
+change_accum(true, S0) ->
+ S0#holder{accum=true};
+change_accum(false, S0=#holder{info=#etop_info{procinfo=Info}}) ->
+ self() ! refresh,
+ S0#holder{accum=lists:sort(Info)}.
+
+handle_update(EI=#etop_info{procinfo=ProcInfo0},
+ S0=#holder{parent=Parent, sort=Sort=#sort{sort_key=KeyField}}) ->
+ {ProcInfo1, S1} = accum(ProcInfo0, S0),
+ {_SO, ProcInfo} = sort(KeyField, Sort#sort{sort_key=undefined}, ProcInfo1),
+ Parent ! {holder_updated, length(ProcInfo)},
+ S1#holder{info=EI#etop_info{procinfo=ProcInfo}}.
+
+accum(ProcInfo, State=#holder{accum=true}) ->
+ {ProcInfo, State};
+accum(ProcInfo0, State=#holder{accum=Previous}) ->
+ ProcInfo = lists:sort(ProcInfo0),
+ {accum2(ProcInfo,Previous,[]), State#holder{accum=ProcInfo}}.
+
+accum2([PI=#etop_proc_info{pid=Pid, reds=Reds, runtime=RT}|PIs],
+ [#etop_proc_info{pid=Pid, reds=OldReds, runtime=OldRT}|Old], Acc) ->
+ accum2(PIs, Old, [PI#etop_proc_info{reds=Reds-OldReds, runtime=RT-OldRT}|Acc]);
+accum2(PIs=[#etop_proc_info{pid=Pid}|_], [#etop_proc_info{pid=OldPid}|Old], Acc)
+ when Pid > OldPid ->
+ accum2(PIs, Old, Acc);
+accum2([PI|PIs], Old, Acc) ->
+ accum2(PIs, Old, [PI|Acc]);
+accum2([], _, Acc) -> Acc.
+
+sort(Col, Opt=#sort{sort_key=Col, sort_incr=Bool}, Table) ->
+ {Opt#sort{sort_incr=not Bool}, lists:reverse(Table)};
+sort(Col, S=#sort{sort_incr=true}, Table) ->
+ {S#sort{sort_key=Col}, lists:keysort(col_to_element(Col), Table)};
+sort(Col, S=#sort{sort_incr=false}, Table) ->
+ {S#sort{sort_key=Col}, lists:reverse(lists:keysort(col_to_element(Col), Table))}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_procinfo_data(Col, Info) ->
+ element(col_to_element(Col), Info).
+col_to_element(?COL_PID) -> #etop_proc_info.pid;
+col_to_element(?COL_NAME) -> #etop_proc_info.name;
+col_to_element(?COL_MEM) -> #etop_proc_info.mem;
+%%col_to_element(?COL_TIME) -> #etop_proc_info.runtime;
+col_to_element(?COL_REDS) -> #etop_proc_info.reds;
+col_to_element(?COL_FUN) -> #etop_proc_info.cf;
+col_to_element(?COL_MSG) -> #etop_proc_info.mq.
+
+get_pids(From, Indices, ProcInfo) ->
+ Processes = [(lists:nth(I+1, ProcInfo))#etop_proc_info.pid || I <- Indices],
+ From ! {self(), Processes}.
+
+get_name_or_pid(From, Indices, ProcInfo) ->
+ Get = fun(#etop_proc_info{name=Name}) when is_atom(Name) -> Name;
+ (#etop_proc_info{pid=Pid}) -> Pid
+ end,
+ Processes = [Get(lists:nth(I+1, ProcInfo)) || I <- Indices],
+ From ! {self(), Processes}.
+
+
+get_row(From, Row, pid, Info) ->
+ Pid = case Row =:= -1 of
+ true -> {error, undefined};
+ false -> {ok, get_procinfo_data(?COL_PID, lists:nth(Row+1, Info))}
+ end,
+ From ! {self(), Pid};
+get_row(From, Row, Col, Info) ->
+ Data = case Row+1 > length(Info) of
+ true ->
+ "";
+ false ->
+ ProcInfo = lists:nth(Row+1, Info),
+ get_procinfo_data(Col, ProcInfo)
+ end,
+ From ! {self(), observer_lib:to_str(Data)}.
+
+get_rows_from_pids(From, Pids0, Info) ->
+ Res = lists:foldl(fun(Pid, Data = {Ids, Pids}) ->
+ case index(Pid, Info, 0) of
+ false -> Data;
+ Index -> {[Index|Ids], [Pid|Pids]}
+ end
+ end, {[],[]}, Pids0),
+ From ! {self(), Res}.
+
+get_attr(From, Row, Attrs) ->
+ Attribute = case Row rem 2 =:= 0 of
+ true -> Attrs#attrs.even;
+ false -> Attrs#attrs.odd
+ end,
+ From ! {self(), Attribute}.
+
+index(Pid, [#etop_proc_info{pid=Pid}|_], Index) -> Index;
+index(Pid, [_|PI], Index) -> index(Pid, PI, Index+1);
+index(_, _, _) -> false.
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
new file mode 100644
index 0000000000..45218c177b
--- /dev/null
+++ b/lib/observer/src/observer_procinfo.erl
@@ -0,0 +1,313 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_procinfo).
+
+-behaviour(wx_object).
+
+-export([start/3]).
+
+-export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3,
+ handle_call/3, handle_info/2]).
+
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+-define(REFRESH, 601).
+-define(SELECT_ALL, 603).
+-define(ID_NOTEBOOK, 604).
+
+-record(state, {parent,
+ frame,
+ pid,
+ pages=[]
+ }).
+
+-record(worker, {panel, callback}).
+
+start(Process, ParentFrame, Parent) ->
+ wx_object:start_link(?MODULE, [Process, ParentFrame, Parent], []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init([Pid, ParentFrame, Parent]) ->
+ try
+ Title=case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, registered_name]) of
+ [] -> io_lib:format("~p",[Pid]);
+ {registered_name, Registered} -> io_lib:format("~p (~p)",[Registered, Pid]);
+ undefined -> throw(process_undefined)
+ end,
+ Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [atom_to_list(node(Pid)), $:, Title],
+ [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]),
+ MenuBar = wxMenuBar:new(),
+ create_menus(MenuBar),
+ wxFrame:setMenuBar(Frame, MenuBar),
+
+ Notebook = wxNotebook:new(Frame, ?ID_NOTEBOOK, [{style, ?wxBK_DEFAULT}]),
+
+ ProcessPage = init_panel(Notebook, "Process Information", Pid, fun init_process_page/2),
+ MessagePage = init_panel(Notebook, "Messages", Pid, fun init_message_page/2),
+ DictPage = init_panel(Notebook, "Dictionary", Pid, fun init_dict_page/2),
+ StackPage = init_panel(Notebook, "Stack Trace", Pid, fun init_stack_page/2),
+
+ wxFrame:connect(Frame, close_window),
+ wxMenu:connect(Frame, command_menu_selected),
+ %% wxNotebook:connect(Notebook, command_notebook_page_changed, [{skip,true}]),
+ wxFrame:show(Frame),
+ {Frame, #state{parent=Parent,
+ pid=Pid,
+ frame=Frame,
+ pages=[ProcessPage,MessagePage,DictPage,StackPage]
+ }}
+ catch error:{badrpc, _} ->
+ observer_wx:return_to_localnode(ParentFrame, node(Pid)),
+ {stop, badrpc};
+ process_undefined ->
+ observer_lib:display_info_dialog("No such alive process"),
+ {stop, normal}
+ end.
+
+init_panel(Notebook, Str, Pid, Fun) ->
+ Panel = wxPanel:new(Notebook),
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ {Window,Callback} = Fun(Panel, Pid),
+ wxSizer:add(Sizer, Window, [{flag, ?wxEXPAND bor ?wxALL}, {proportion, 1}, {border, 5}]),
+ wxPanel:setSizer(Panel, Sizer),
+ true = wxNotebook:addPage(Notebook, Panel, Str),
+ #worker{panel=Panel, callback=Callback}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Callbacks%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+handle_event(#wx{event=#wxClose{type=close_window}}, State) ->
+ {stop, normal, State};
+
+handle_event(#wx{id=?wxID_CLOSE, event=#wxCommand{type=command_menu_selected}}, State) ->
+ {stop, normal, State};
+
+handle_event(#wx{id=?REFRESH}, #state{frame=Frame, pid=Pid, pages=Pages}=State) ->
+ try [(W#worker.callback)() || W <- Pages]
+ catch process_undefined ->
+ wxFrame:setTitle(Frame, io_lib:format("*DEAD* ~p",[Pid]))
+ end,
+ {noreply, State};
+
+handle_event(Event, _State) ->
+ error({unhandled_event, Event}).
+
+handle_info(_Info, State) ->
+ %% io:format("~p: ~p, Handle info: ~p~n", [?MODULE, ?LINE, Info]),
+ {noreply, State}.
+
+handle_call(Call, From, _State) ->
+ error({unhandled_call, Call, From}).
+
+handle_cast(Cast, _State) ->
+ error({unhandled_cast, Cast}).
+
+terminate(_Reason, #state{parent=Parent,pid=Pid,frame=Frame}) ->
+ Parent ! {procinfo_menu_closed, Pid},
+ case Frame of
+ undefined -> ok;
+ _ -> wxFrame:destroy(Frame)
+ end,
+ ok.
+
+code_change(_, _, State) ->
+ {ok, State}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init_process_page(Panel, Pid) ->
+ Fields0 = process_info_fields(Pid),
+ {FPanel, _, UpFields} = observer_lib:display_info(Panel, Fields0),
+ {FPanel, fun() ->
+ Fields = process_info_fields(Pid),
+ observer_lib:update_info(UpFields, Fields)
+ end}.
+
+init_text_page(Parent) ->
+ Style = ?wxTE_MULTILINE bor ?wxTE_RICH2 bor ?wxTE_READONLY,
+ Text = wxTextCtrl:new(Parent, ?wxID_ANY, [{style, Style}]),
+ Font = observer_wx:get_attrib({font, fixed}),
+ Attr = wxTextAttr:new(?wxBLACK, [{font, Font}]),
+ true = wxTextCtrl:setDefaultStyle(Text, Attr),
+ wxTextAttr:destroy(Attr),
+ Text.
+
+init_message_page(Parent, Pid) ->
+ Text = init_text_page(Parent),
+ Format = fun(Message, Number) ->
+ {io_lib:format("~-4.w ~p~n", [Number, Message]),
+ Number+1}
+ end,
+ Update = fun() ->
+ case observer_wx:try_rpc(node(Pid), erlang, process_info,
+ [Pid, messages])
+ of
+ {messages,RawMessages} ->
+ {Messages,_} = lists:mapfoldl(Format, 1, RawMessages),
+ Last = wxTextCtrl:getLastPosition(Text),
+ wxTextCtrl:remove(Text, 0, Last),
+ case Messages =:= [] of
+ true ->
+ wxTextCtrl:writeText(Text, "No messages");
+ false ->
+ wxTextCtrl:writeText(Text, Messages)
+ end;
+ _ ->
+ throw(process_undefined)
+ end
+ end,
+ Update(),
+ {Text, Update}.
+
+init_dict_page(Parent, Pid) ->
+ Text = init_text_page(Parent),
+ Update = fun() ->
+ case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, dictionary])
+ of
+ {dictionary,RawDict} ->
+ Dict = [io_lib:format("~-20.w ~p~n", [K, V]) || {K, V} <- RawDict],
+ Last = wxTextCtrl:getLastPosition(Text),
+ wxTextCtrl:remove(Text, 0, Last),
+ wxTextCtrl:writeText(Text, Dict);
+ _ ->
+ throw(process_undefined)
+ end
+ end,
+ Update(),
+ {Text, Update}.
+
+init_stack_page(Parent, Pid) ->
+ LCtrl = wxListCtrl:new(Parent, [{style, ?wxLC_REPORT bor ?wxLC_HRULES}]),
+ Li = wxListItem:new(),
+ wxListItem:setText(Li, "Module:Function/Arg"),
+ wxListCtrl:insertColumn(LCtrl, 0, Li),
+ wxListCtrl:setColumnWidth(LCtrl, 0, 300),
+ wxListItem:setText(Li, "File:LineNumber"),
+ wxListCtrl:insertColumn(LCtrl, 1, Li),
+ wxListCtrl:setColumnWidth(LCtrl, 1, 300),
+ wxListItem:destroy(Li),
+ Update = fun() ->
+ case observer_wx:try_rpc(node(Pid), erlang, process_info,
+ [Pid, current_stacktrace])
+ of
+ {current_stacktrace,RawBt} ->
+ observer_wx:try_rpc(node(Pid), erlang, process_info,
+ [Pid, current_stacktrace]),
+ wxListCtrl:deleteAllItems(LCtrl),
+ wx:foldl(fun({M, F, A, Info}, Row) ->
+ _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
+ ?EVEN(Row) andalso
+ wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({M,F,A})),
+ FileLine = case Info of
+ [{file,File},{line,Line}] ->
+ io_lib:format("~s:~w", [File,Line]);
+ _ ->
+ []
+ end,
+ wxListCtrl:setItem(LCtrl, Row, 1, FileLine),
+ Row+1
+ end, 0, RawBt);
+ _ ->
+ throw(process_undefined)
+ end
+ end,
+ Resize = fun(#wx{event=#wxSize{size={W,_}}},Ev) ->
+ wxEvent:skip(Ev),
+ observer_lib:set_listctrl_col_size(LCtrl, W)
+ end,
+ wxListCtrl:connect(LCtrl, size, [{callback, Resize}]),
+ Update(),
+ {LCtrl, Update}.
+
+create_menus(MenuBar) ->
+ Menus = [{"File", [#create_menu{id=?wxID_CLOSE, text="Close"}]},
+ {"View", [#create_menu{id=?REFRESH, text="Refresh\tCtrl-R"}]}],
+ observer_lib:create_menus(Menus, MenuBar, new_window).
+
+process_info_fields(Pid) ->
+ Struct = [{"Overview",
+ [{"Initial Call", initial_call},
+ {"Current Function", current_function},
+ {"Registered Name", registered_name},
+ {"Status", status},
+ {"Message Queue Len",message_queue_len},
+ {"Priority", priority},
+ {"Trap Exit", trap_exit},
+ {"Reductions", reductions},
+ {"Binary", binary},
+ {"Last Calls", last_calls},
+ {"Catch Level", catchlevel},
+ {"Trace", trace},
+ {"Suspending", suspending},
+ {"Sequential Trace Token", sequential_trace_token},
+ {"Error Handler", error_handler}]},
+ {"Connections",
+ [{"Group Leader", group_leader},
+ {"Links", links},
+ {"Monitors", monitors},
+ {"Monitored by", monitored_by}]},
+ {"Memory and Garbage Collection", right,
+ [{"Memory", {bytes, memory}},
+ {"Stack and Heaps", {bytes, total_heap_size}},
+ {"Heap Size", {bytes, heap_size}},
+ {"Stack Size", {bytes, stack_size}},
+ {"GC Min Heap Size", {bytes, get_gc_info(min_heap_size)}},
+ {"GC FullSweep After", get_gc_info(fullsweep_after)}
+ ]}],
+ case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, item_list()]) of
+ RawInfo when is_list(RawInfo) ->
+ observer_lib:fill_info(Struct, RawInfo);
+ _ ->
+ throw(process_undefined)
+ end.
+
+item_list() ->
+ [ %% backtrace,
+ binary,
+ catchlevel,
+ current_function,
+ %% dictionary,
+ error_handler,
+ garbage_collection,
+ group_leader,
+ heap_size,
+ initial_call,
+ last_calls,
+ links,
+ memory,
+ message_queue_len,
+ %% messages,
+ monitored_by,
+ monitors,
+ priority,
+ reductions,
+ registered_name,
+ sequential_trace_token,
+ stack_size,
+ status,
+ suspending,
+ total_heap_size,
+ trace,
+ trap_exit].
+
+get_gc_info(Arg) ->
+ fun(Data) ->
+ GC = proplists:get_value(garbage_collection, Data),
+ proplists:get_value(Arg, GC)
+ end.
diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl
new file mode 100644
index 0000000000..f00a666a35
--- /dev/null
+++ b/lib/observer/src/observer_sys_wx.erl
@@ -0,0 +1,177 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_sys_wx).
+
+-behaviour(wx_object).
+
+-export([start_link/2]).
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_cast/2]).
+
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+-define(ID_REFRESH, 101).
+-define(ID_REFRESH_INTERVAL, 102).
+
+%% Records
+-record(sys_wx_state,
+ {parent,
+ node,
+ parent_notebook,
+ panel, sizer,
+ menubar,
+ fields,
+ timer}).
+
+start_link(Notebook, Parent) ->
+ wx_object:start_link(?MODULE, [Notebook, Parent], []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init([Notebook, Parent]) ->
+ SysInfo = observer_backend:sys_info(),
+ {Info, Stat} = info_fields(),
+ Panel = wxPanel:new(Notebook),
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ {FPanel0, _FSizer0, Fields0} =
+ observer_lib:display_info(Panel, observer_lib:fill_info(Info, SysInfo)),
+ {FPanel1, _FSizer1, Fields1} =
+ observer_lib:display_info(Panel, observer_lib:fill_info(Stat, SysInfo)),
+ wxSizer:add(Sizer, FPanel0, [{flag, ?wxEXPAND bor ?wxTOP bor ?wxBOTTOM bor ?wxLEFT},
+ {proportion, 1}, {border, 5}]),
+ wxSizer:add(Sizer, FPanel1, [{flag, ?wxEXPAND bor ?wxTOP bor ?wxBOTTOM bor ?wxRIGHT},
+ {proportion, 1}, {border, 5}]),
+ wxPanel:setSizer(Panel, Sizer),
+ Timer = observer_lib:start_timer(10),
+ {Panel, #sys_wx_state{parent=Parent,
+ parent_notebook=Notebook,
+ panel=Panel, sizer=Sizer,
+ timer=Timer, fields=Fields0 ++ Fields1}}.
+
+create_sys_menu(Parent) ->
+ View = {"View", [#create_menu{id = ?ID_REFRESH, text = "Refresh\tCtrl-R"},
+ #create_menu{id = ?ID_REFRESH_INTERVAL, text = "Refresh interval"}]},
+ observer_wx:create_menus(Parent, [View]).
+
+update_syspage(#sys_wx_state{node = Node, fields=Fields, sizer=Sizer}) ->
+ SysInfo = observer_wx:try_rpc(Node, observer_backend, sys_info, []),
+ {Info, Stat} = info_fields(),
+ observer_lib:update_info(Fields, observer_lib:fill_info(Info, SysInfo) ++
+ observer_lib:fill_info(Stat, SysInfo)),
+ wxSizer:layout(Sizer).
+
+info_fields() ->
+ Info = [{"System and Architecture",
+ [{"System Version", otp_release},
+ {"Erts Version", version},
+ {"Compiled for", system_architecture},
+ {"Emulator Wordsize", wordsize_external},
+ {"Process Wordsize", wordsize_internal},
+ {"Smp Support", smp_support},
+ {"Thread Support", threads},
+ {"Async thread pool size", thread_pool_size}
+ ]},
+ {"CPU's and Threads",
+ [{"System Logical CPU's", logical_processors},
+ {"Erlang Logical CPU's", logical_processors_online},
+ {"Used Logical CPU's", logical_processors_available}
+ ]}
+ ],
+ Stat = [{"Memory Usage", right,
+ [{"Total", {bytes, total}},
+ {"Processes", {bytes, processes}},
+ {"Atoms", {bytes, atom}},
+ {"Binaries", {bytes, binary}},
+ {"Code", {bytes, code}},
+ {"Ets", {bytes, ets}}
+ ]},
+ {"Statistics", right,
+ [{"Up time", {time_ms, uptime}},
+ {"Max Processes", process_limit},
+ {"Processes", process_count},
+ {"Run Queue", run_queue},
+ {"IO Input", {bytes, io_input}},
+ {"IO Output", {bytes, io_output}}
+ ]}
+ ],
+ {Info, Stat}.
+
+%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+handle_info(refresh_interval, #sys_wx_state{panel = Panel,
+ node = Node} = State) ->
+ try
+ update_syspage(State)
+ catch error:{badrpc, _} ->
+ observer_wx:return_to_localnode(Panel, Node)
+ end,
+ {noreply, State};
+
+handle_info({active, Node}, #sys_wx_state{parent = Parent, panel = Panel,
+ timer = Timer} = State) ->
+ UpdState = State#sys_wx_state{node = Node},
+ create_sys_menu(Parent),
+ try
+ update_syspage(UpdState),
+ {noreply, UpdState#sys_wx_state{timer=observer_lib:start_timer(Timer)}}
+ catch error:{badrpc, _} ->
+ observer_wx:return_to_localnode(Panel, Node),
+ {noreply, State}
+ end;
+
+handle_info(not_active, #sys_wx_state{timer = Timer} = State) ->
+ {noreply, State#sys_wx_state{timer = observer_lib:stop_timer(Timer)}};
+
+handle_info(Info, State) ->
+ io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]),
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_, _, State) ->
+ {ok, State}.
+
+handle_call(Msg, _From, State) ->
+ io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
+ {reply, ok, State}.
+
+handle_cast(Msg, State) ->
+ io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]),
+ {noreply, State}.
+
+handle_event(#wx{id = ?ID_REFRESH, event = #wxCommand{type = command_menu_selected}},
+ #sys_wx_state{node = Node, panel = Panel} = State) ->
+ try
+ update_syspage(State)
+ catch error:{badrpc, _} ->
+ observer_wx:return_to_localnode(Panel, Node)
+ end,
+ {noreply, State};
+
+handle_event(#wx{id = ?ID_REFRESH_INTERVAL,
+ event = #wxCommand{type = command_menu_selected}},
+ #sys_wx_state{timer = Timer0, parent_notebook = Notebook} = State) ->
+ Timer = observer_lib:interval_dialog(Notebook, Timer0, 1, 5*60),
+ {noreply, State#sys_wx_state{timer=Timer}};
+
+handle_event(Event, State) ->
+ io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]),
+ {noreply, State}.
diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl
new file mode 100644
index 0000000000..f2a1084f85
--- /dev/null
+++ b/lib/observer/src/observer_trace_wx.erl
@@ -0,0 +1,866 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_trace_wx).
+
+-export([start_link/2, add_processes/2]).
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_cast/2]).
+
+-behaviour(wx_object).
+
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+-define(SAVE_TRACEOPTS, 305).
+-define(LOAD_TRACEOPTS, 306).
+-define(TOGGLE_TRACE, 307).
+-define(ADD_NEW, 308).
+-define(ADD_TP, 309).
+-define(TRACE_OUTPUT, 310).
+-define(TRACE_DEFMS, 311).
+-define(TRACE_DEFPS, 312).
+
+-define(NODES_WIN, 330).
+-define(ADD_NODES, 331).
+-define(REMOVE_NODES, 332).
+
+-define(PROC_WIN, 340).
+-define(EDIT_PROCS, 341).
+-define(REMOVE_PROCS, 342).
+
+-define(MODULES_WIN, 350).
+
+-define(FUNCS_WIN, 360).
+-define(EDIT_FUNCS_MS, 361).
+-define(REMOVE_FUNCS_MS, 362).
+
+-define(LOG_WIN, 370).
+-define(LOG_SAVE, 321).
+-define(LOG_CLEAR, 322).
+
+-record(state,
+ {parent,
+ panel,
+ n_view, p_view, m_view, f_view, %% The listCtrl's
+ logwin, %% The latest log window
+ nodes = [],
+ toggle_button,
+ tpids = [], %% #tpid
+ def_trace_opts = [],
+ output = [],
+ tpatterns = dict:new(), % Key =:= Module::atom, Value =:= {M, F, A, MatchSpec}
+ match_specs = []}). % [ #match_spec{} ]
+
+-record(tpid, {pid, opts}).
+
+start_link(Notebook, ParentPid) ->
+ wx_object:start_link(?MODULE, [Notebook, ParentPid], []).
+
+add_processes(Tracer, Pids) when is_list(Pids) ->
+ wx_object:cast(Tracer, {add_processes, Pids}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init([Notebook, ParentPid]) ->
+ wx:batch(fun() -> create_window(Notebook, ParentPid) end).
+
+create_window(Notebook, ParentPid) ->
+ %% Create the window
+ Panel = wxPanel:new(Notebook, [{size, wxWindow:getClientSize(Notebook)}]),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ Splitter = wxSplitterWindow:new(Panel, [{size, wxWindow:getClientSize(Panel)}]),
+ {NodeProcView, NodeView, ProcessView} = create_process_view(Splitter),
+ {MatchSpecView,ModView,FuncView} = create_matchspec_view(Splitter),
+ wxSplitterWindow:setSashGravity(Splitter, 0.5),
+ wxSplitterWindow:setMinimumPaneSize(Splitter,50),
+ wxSplitterWindow:splitHorizontally(Splitter, NodeProcView, MatchSpecView),
+ wxSizer:add(Sizer, Splitter, [{flag, ?wxEXPAND bor ?wxALL}, {border, 5}, {proportion, 1}]),
+ %% Buttons
+ Buttons = wxBoxSizer:new(?wxHORIZONTAL),
+ ToggleButton = wxToggleButton:new(Panel, ?TOGGLE_TRACE, "Start Trace", []),
+ wxSizer:add(Buttons, ToggleButton, [{flag, ?wxALIGN_CENTER_VERTICAL}]),
+ wxSizer:addSpacer(Buttons, 15),
+ wxSizer:add(Buttons, wxButton:new(Panel, ?ADD_NODES, [{label, "Add Nodes"}])),
+ wxSizer:add(Buttons, wxButton:new(Panel, ?ADD_NEW, [{label, "Add 'new' Process"}])),
+ wxSizer:add(Buttons, wxButton:new(Panel, ?ADD_TP, [{label, "Add Trace Pattern"}])),
+ wxMenu:connect(Panel, command_togglebutton_clicked, [{skip, true}]),
+ wxMenu:connect(Panel, command_button_clicked, [{skip, true}]),
+ wxSizer:add(Sizer, Buttons, [{flag, ?wxLEFT bor ?wxRIGHT bor ?wxDOWN},
+ {border, 5}, {proportion,0}]),
+ wxWindow:setSizer(Panel, Sizer),
+ {Panel, #state{parent=ParentPid, panel=Panel,
+ n_view=NodeView, p_view=ProcessView, m_view=ModView, f_view=FuncView,
+ toggle_button = ToggleButton,
+ match_specs=default_matchspecs()}}.
+
+default_matchspecs() ->
+ Ms = [{"Return Trace", [{'_', [], [{return_trace}]}], "fun(_) -> return_trace() end"},
+ {"Exception Trace", [{'_', [], [{exception_trace}]}], "fun(_) -> exception_trace() end"},
+ {"Message Caller", [{'_', [], [{message,{caller}}]}], "fun(_) -> message(caller()) end"},
+ {"Message Dump", [{'_', [], [{message,{process_dump}}]}], "fun(_) -> message(process_dump()) end"}],
+ [make_ms(Name,Term,FunStr) || {Name,Term,FunStr} <- Ms].
+
+create_process_view(Parent) ->
+ Panel = wxPanel:new(Parent),
+ MainSz = wxBoxSizer:new(?wxHORIZONTAL),
+ Style = ?wxLC_REPORT bor ?wxLC_HRULES,
+ Splitter = wxSplitterWindow:new(Panel, []),
+ Nodes = wxListCtrl:new(Splitter, [{winid, ?NODES_WIN}, {style, Style}]),
+ Procs = wxListCtrl:new(Splitter, [{winid, ?PROC_WIN}, {style, Style}]),
+ Li = wxListItem:new(),
+ wxListItem:setText(Li, "Nodes"),
+ wxListCtrl:insertColumn(Nodes, 0, Li),
+
+ AddProc = fun({Name, Align, DefSize}, Col) ->
+ wxListItem:setText(Li, Name),
+ wxListItem:setAlign(Li, Align),
+ wxListCtrl:insertColumn(Procs, Col, Li),
+ wxListCtrl:setColumnWidth(Procs, Col, DefSize),
+ Col + 1
+ end,
+ ListItems = [{"Process Id", ?wxLIST_FORMAT_CENTER, 120},
+ {"Trace Options", ?wxLIST_FORMAT_LEFT, 300}],
+ lists:foldl(AddProc, 0, ListItems),
+ wxListItem:destroy(Li),
+
+ wxSplitterWindow:setSashGravity(Splitter, 0.0),
+ wxSplitterWindow:setMinimumPaneSize(Splitter,50),
+ wxSplitterWindow:splitVertically(Splitter, Nodes, Procs, [{sashPosition, 155}]),
+ wxSizer:add(MainSz, Splitter, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ wxListCtrl:connect(Procs, command_list_item_right_click),
+ wxListCtrl:connect(Nodes, command_list_item_right_click),
+ wxListCtrl:connect(Procs, size, [{skip, true}]),
+ wxListCtrl:connect(Nodes, size, [{skip, true}]),
+
+ wxPanel:setSizer(Panel, MainSz),
+ wxWindow:setFocus(Procs),
+ {Panel, Nodes, Procs}.
+
+create_matchspec_view(Parent) ->
+ Panel = wxPanel:new(Parent),
+ MainSz = wxBoxSizer:new(?wxHORIZONTAL),
+ Style = ?wxLC_REPORT bor ?wxLC_HRULES,
+ Splitter = wxSplitterWindow:new(Panel, []),
+ Modules = wxListCtrl:new(Splitter, [{winid, ?MODULES_WIN}, {style, Style}]),
+ Funcs = wxListCtrl:new(Splitter, [{winid, ?FUNCS_WIN}, {style, Style}]),
+ Li = wxListItem:new(),
+
+ wxListItem:setText(Li, "Modules"),
+ wxListCtrl:insertColumn(Modules, 0, Li),
+ wxListItem:setText(Li, "Functions"),
+ wxListCtrl:insertColumn(Funcs, 0, Li),
+ wxListCtrl:setColumnWidth(Funcs, 0, 150),
+ wxListItem:setText(Li, "Match Spec"),
+ wxListCtrl:insertColumn(Funcs, 1, Li),
+ wxListCtrl:setColumnWidth(Funcs, 1, 300),
+ wxListItem:destroy(Li),
+
+ wxSplitterWindow:setSashGravity(Splitter, 0.0),
+ wxSplitterWindow:setMinimumPaneSize(Splitter,50),
+ wxSplitterWindow:splitVertically(Splitter, Modules, Funcs, [{sashPosition, 155}]),
+ wxSizer:add(MainSz, Splitter, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ wxListCtrl:connect(Modules, size, [{skip, true}]),
+ wxListCtrl:connect(Funcs, size, [{skip, true}]),
+ wxListCtrl:connect(Modules, command_list_item_selected),
+ wxListCtrl:connect(Funcs, command_list_item_right_click),
+ wxPanel:setSizer(Panel, MainSz),
+ {Panel, Modules, Funcs}.
+
+create_menues(Parent) ->
+ Menus = [{"File",
+ [#create_menu{id = ?LOAD_TRACEOPTS, text = "Load settings"},
+ #create_menu{id = ?SAVE_TRACEOPTS, text = "Save settings"}]},
+ {"Options",
+ [#create_menu{id = ?TRACE_OUTPUT, text = "Output"},
+ #create_menu{id = ?TRACE_DEFMS, text = "Match Specifications"},
+ #create_menu{id = ?TRACE_DEFPS, text = "Default Process Options"}]}
+ ],
+ observer_wx:create_menus(Parent, Menus).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%Main window
+handle_event(#wx{obj=Obj, event=#wxSize{size={W,_}}}, State) ->
+ case wx:getObjectType(Obj) =:= wxListCtrl of
+ true -> observer_lib:set_listctrl_col_size(Obj, W);
+ false -> ok
+ end,
+ {noreply, State};
+
+handle_event(#wx{id=?ADD_NEW}, State = #state{panel=Parent, def_trace_opts=TraceOpts}) ->
+ try
+ Opts = observer_traceoptions_wx:process_trace(Parent, TraceOpts),
+ Process = #tpid{pid=new, opts=Opts},
+ {noreply, do_add_processes([Process], State#state{def_trace_opts=Opts})}
+ catch cancel -> {noreply, State}
+ end;
+
+handle_event(#wx{id=?ADD_TP},
+ State = #state{panel=Parent, nodes=Nodes, match_specs=Ms}) ->
+ Node = case Nodes of
+ [N|_] -> N;
+ [] -> node()
+ end,
+ case observer_traceoptions_wx:trace_pattern(self(), Parent, Node, Ms) of
+ cancel ->
+ {noreply, State};
+ Patterns ->
+ {noreply, do_add_patterns(Patterns, State)}
+ end;
+
+handle_event(#wx{id=?MODULES_WIN, event=#wxList{type=command_list_item_selected, itemIndex=Row}},
+ State = #state{tpatterns=TPs, m_view=Mview, f_view=Fview}) ->
+ Module = list_to_atom(wxListCtrl:getItemText(Mview, Row)),
+ update_functions_view(dict:fetch(Module, TPs), Fview),
+ {noreply, State};
+
+handle_event(#wx{event = #wxCommand{type = command_togglebutton_clicked, commandInt = 1}},
+ #state{panel = Panel,
+ nodes = Nodes,
+ tpids = TProcs,
+ tpatterns = TPs0,
+ toggle_button = ToggleBtn,
+ output = Opts
+ } = State) ->
+ try
+ TPs = dict:to_list(TPs0),
+ (TProcs == []) andalso throw({error, "No processes traced"}),
+ (Nodes == []) andalso throw({error, "No nodes traced"}),
+ HaveCallTrace = fun(#tpid{opts=Os}) -> lists:member(functions,Os) end,
+ WStr = "Call trace actived but no trace patterns used",
+ (TPs == []) andalso lists:any(HaveCallTrace, TProcs) andalso
+ observer_wx:create_txt_dialog(Panel, WStr, "Warning", ?wxICON_WARNING),
+
+ {TTB, LogWin} = ttb_output_args(Panel, Opts),
+ {ok, _} = ttb:tracer(Nodes, TTB),
+ setup_ttb(TPs, TProcs),
+ wxToggleButton:setLabel(ToggleBtn, "Stop Trace"),
+ {noreply, State#state{logwin=LogWin}}
+ catch {error, Msg} ->
+ observer_wx:create_txt_dialog(Panel, Msg, "Error", ?wxICON_ERROR),
+ wxToggleButton:setValue(ToggleBtn, false),
+ {noreply, State}
+ end;
+
+handle_event(#wx{event = #wxCommand{type = command_togglebutton_clicked, commandInt = 0}},
+ #state{toggle_button = ToggleBtn} = State) ->
+ %%Stop tracing
+ ttb:stop(nofetch),
+ wxToggleButton:setLabel(ToggleBtn, "Start Trace"),
+ wxToggleButton:setValue(ToggleBtn, false),
+ {noreply, State#state{logwin=false}};
+
+handle_event(#wx{id=Id, obj=LogWin, event=Ev},
+ #state{toggle_button = ToggleBtn, logwin=Latest} = State)
+ when Id =:= ?LOG_WIN; is_record(Ev, wxClose) ->
+ case LogWin of
+ Latest ->
+ %%Stop tracing
+ ttb:stop(nofetch),
+ wxToggleButton:setLabel(ToggleBtn, "Start Trace"),
+ wxToggleButton:setValue(ToggleBtn, false),
+ {noreply, State#state{logwin=false}};
+ _ ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?LOG_CLEAR, userData=TCtrl}, State) ->
+ wxTextCtrl:clear(TCtrl),
+ {noreply, State};
+
+handle_event(#wx{id=?LOG_SAVE, userData=TCtrl}, #state{panel=Panel} = State) ->
+ Dialog = wxFileDialog:new(Panel, [{style, ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT}]),
+ case wxFileDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Path = wxFileDialog:getPath(Dialog),
+ wxDialog:destroy(Dialog),
+ wxTextCtrl:saveFile(TCtrl, [{file, Path}]);
+ _ ->
+ wxDialog:destroy(Dialog),
+ ok
+ end,
+ {noreply, State};
+
+handle_event(#wx{id = ?SAVE_TRACEOPTS},
+ #state{panel = Panel,
+ def_trace_opts = TraceOpts,
+ match_specs = MatchSpecs,
+ tpatterns = TracePatterns,
+ output = Output
+ } = State) ->
+ Dialog = wxFileDialog:new(Panel, [{style, ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT}]),
+ case wxFileDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Path = wxFileDialog:getPath(Dialog),
+ write_file(Panel, Path,
+ TraceOpts, MatchSpecs, Output,
+ dict:to_list(TracePatterns)
+ );
+ _ ->
+ ok
+ end,
+ wxDialog:destroy(Dialog),
+ {noreply, State};
+
+handle_event(#wx{id = ?LOAD_TRACEOPTS}, #state{panel = Panel} = State) ->
+ Dialog = wxFileDialog:new(Panel, [{style, ?wxFD_FILE_MUST_EXIST}]),
+ State2 = case wxFileDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Path = wxFileDialog:getPath(Dialog),
+ read_settings(Path, State);
+ _ ->
+ State
+ end,
+ wxDialog:destroy(Dialog),
+ {noreply, State2};
+
+handle_event(#wx{id=Type, event=#wxList{type=command_list_item_right_click}},
+ State = #state{panel=Panel}) ->
+ Menus = case Type of
+ ?PROC_WIN ->
+ [{?EDIT_PROCS, "Edit process options"},
+ {?REMOVE_PROCS, "Remove processes"}];
+ ?FUNCS_WIN ->
+ [{?EDIT_FUNCS_MS, "Edit matchspecs"},
+ {?REMOVE_FUNCS_MS, "Remove trace patterns"}];
+ ?NODES_WIN ->
+ [{?ADD_NODES, "Trace other nodes"},
+ {?REMOVE_NODES, "Remove nodes"}]
+ end,
+ Menu = wxMenu:new(),
+ [wxMenu:append(Menu,Id,Str) || {Id,Str} <- Menus],
+ wxWindow:popupMenu(Panel, Menu),
+ wxMenu:destroy(Menu),
+ {noreply, State};
+
+handle_event(#wx{id=?EDIT_PROCS}, #state{panel=Panel, tpids=Tpids, p_view=Ps} = State) ->
+ try
+ [#tpid{opts=DefOpts}|_] = Selected = get_selected_items(Ps, Tpids),
+ Opts = observer_traceoptions_wx:process_trace(Panel, DefOpts),
+ Changed = [Tpid#tpid{opts=Opts} || Tpid <- Selected],
+ {noreply, do_add_processes(Changed, State#state{def_trace_opts=Opts})}
+ catch _:_ ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?REMOVE_PROCS}, #state{tpids=Tpids, p_view=LCtrl} = State) ->
+ Selected = get_selected_items(LCtrl, Tpids),
+ Pids = Tpids -- Selected,
+ update_process_view(Pids, LCtrl),
+ {noreply, State#state{tpids=Pids}};
+
+handle_event(#wx{id=?TRACE_DEFPS}, #state{panel=Panel, def_trace_opts=PO} = State) ->
+ try
+ Opts = observer_traceoptions_wx:process_trace(Panel, PO),
+ {noreply, State#state{def_trace_opts=Opts}}
+ catch _:_ ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?TRACE_DEFMS}, #state{panel=Panel, match_specs=Ms} = State) ->
+ try %% Return selected MS and sends new MS's to us
+ observer_traceoptions_wx:select_matchspec(self(), Panel, Ms)
+ catch _:_ ->
+ cancel
+ end,
+ {noreply, State};
+
+handle_event(#wx{id=?EDIT_FUNCS_MS}, #state{panel=Panel, tpatterns=TPs,
+ f_view=LCtrl, m_view=Mview,
+ match_specs=Mss
+ } = State) ->
+ try
+ [Module] = get_selected_items(Mview, lists:sort(dict:fetch_keys(TPs))),
+ Selected = get_selected_items(LCtrl, dict:fetch(Module, TPs)),
+ Ms = observer_traceoptions_wx:select_matchspec(self(), Panel, Mss),
+ Changed = [TP#tpattern{ms=Ms} || TP <- Selected],
+ {noreply, do_add_patterns({Module, Changed}, State)}
+ catch _:_ ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?REMOVE_FUNCS_MS}, #state{tpatterns=TPs0, f_view=LCtrl, m_view=Mview} = State) ->
+ case get_selected_items(Mview, lists:sort(dict:fetch_keys(TPs0))) of
+ [] -> {noreply, State};
+ [Module] ->
+ FMs0 = dict:fetch(Module, TPs0),
+ Selected = get_selected_items(LCtrl, FMs0),
+ FMs = FMs0 -- Selected,
+ update_functions_view(FMs, LCtrl),
+ TPs = case FMs of
+ [] ->
+ New = dict:erase(Module, TPs0),
+ update_modules_view(lists:sort(dict:fetch_keys(New)), Module, Mview),
+ New;
+ _ ->
+ dict:store(Module, FMs, TPs0)
+ end,
+ {noreply, State#state{tpatterns=TPs}}
+ end;
+
+handle_event(#wx{id=?TRACE_OUTPUT}, #state{panel=Panel, output=Out0} = State) ->
+ try
+ Out = observer_traceoptions_wx:output(Panel, Out0),
+ {noreply, State#state{output=Out}}
+ catch _:_ ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?ADD_NODES}, #state{panel=Panel, n_view=Nview, nodes=Ns0} = State) ->
+ try
+ Possible = [node()|nodes()] -- Ns0,
+ case Possible of
+ [] ->
+ Msg = "Already selected all connected nodes\n"
+ "Use the Nodes menu to connect to new nodes first.",
+ observer_wx:create_txt_dialog(Panel, Msg, "No available nodes", ?wxICON_INFORMATION),
+ throw(cancel);
+ _ ->
+ Ns = lists:usort(Ns0 ++ observer_traceoptions_wx:select_nodes(Panel, Possible)),
+ update_nodes_view(Ns, Nview),
+ {noreply, State#state{nodes=Ns}}
+ end
+ catch cancel ->
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?REMOVE_NODES}, #state{n_view=Nview, nodes=Ns0} = State) ->
+ Sel = get_selected_items(Nview, Ns0),
+ Ns = Ns0 -- Sel,
+ update_nodes_view(Ns, Nview),
+ {noreply, State#state{nodes = Ns}};
+
+handle_event(#wx{id=ID, event = What}, State) ->
+ io:format("~p:~p: Unhandled event: ~p, ~p ~n", [?MODULE, ?LINE, ID, What]),
+ {noreply, State}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+handle_call(Msg, From, _State) ->
+ error({unhandled_call, Msg, From}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+handle_cast({add_processes, Pids}, State = #state{panel=Parent, def_trace_opts=TraceOpts}) ->
+ try
+ Opts = observer_traceoptions_wx:process_trace(Parent, TraceOpts),
+ POpts = [#tpid{pid=Pid, opts=Opts} || Pid <- Pids],
+ S = do_add_processes(POpts, State#state{def_trace_opts=Opts}),
+ {noreply, S}
+ catch cancel ->
+ {noreply, State}
+ end;
+handle_cast(Msg, _State) ->
+ error({unhandled_cast, Msg}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+handle_info({active, _Node}, State=#state{parent=Parent}) ->
+ create_menues(Parent),
+ {noreply, State};
+
+handle_info(not_active, State) ->
+ {noreply, State};
+
+handle_info({update_ms, NewMs}, State) ->
+ {noreply, State#state{match_specs=NewMs}};
+
+handle_info(Any, State) ->
+ io:format("~p~p: received unexpected message: ~p\n", [?MODULE, self(), Any]),
+ {noreply, State}.
+
+terminate(_Reason, #state{nodes=_Nodes}) ->
+ ttb:stop(nofetch),
+ ok.
+
+code_change(_, _, State) ->
+ {ok, State}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+do_add_patterns({Module, NewPs}, State=#state{tpatterns=TPs0, m_view=Mview, f_view=Fview}) ->
+ Old = case dict:find(Module, TPs0) of
+ {ok, Prev} -> Prev;
+ error -> []
+ end,
+ case merge_patterns(NewPs, Old) of
+ {Old, [], []} ->
+ State;
+ {MPatterns, _New, _Changed} ->
+ %% if dynamicly updates update New and Changed
+ TPs = dict:store(Module, MPatterns, TPs0),
+ update_modules_view(lists:sort(dict:fetch_keys(TPs)), Module, Mview),
+ update_functions_view(dict:fetch(Module, TPs), Fview),
+ State#state{tpatterns=TPs}
+ end.
+
+do_add_processes(POpts, S0=#state{n_view=Nview, p_view=LCtrl, tpids=OldPids, nodes=Ns0}) ->
+ case merge_pids(POpts, OldPids) of
+ {OldPids, [], []} ->
+ S0;
+ {Pids, New, _Changed} ->
+ update_process_view(Pids, LCtrl),
+ Ns1 = lists:usort([node(Pid) || #tpid{pid=Pid} <- New, is_pid(Pid)]),
+ Nodes = case ordsets:subtract(Ns1, Ns0) of
+ [] -> Ns0; %% No new Nodes
+ NewNs ->
+ %% if dynamicly updates add trace patterns for new nodes
+ All = ordsets:union(NewNs, Ns0),
+ update_nodes_view(All, Nview),
+ All
+ end,
+ S0#state{tpids=Pids, nodes=Nodes}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+update_process_view(Pids, LCtrl) ->
+ wxListCtrl:deleteAllItems(LCtrl),
+ wx:foldl(fun(#tpid{pid=Pid, opts=Opts}, Row) ->
+ _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
+ ?EVEN(Row) andalso
+ wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str(Pid)),
+ wxListCtrl:setItem(LCtrl, Row, 1, observer_lib:to_str(Opts)),
+ Row+1
+ end, 0, Pids).
+
+update_nodes_view(Nodes, LCtrl) ->
+ wxListCtrl:deleteAllItems(LCtrl),
+ wx:foldl(fun(Node, Row) ->
+ _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
+ ?EVEN(Row) andalso
+ wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str(Node)),
+ Row+1
+ end, 0, Nodes).
+
+update_modules_view(Mods, Module, LCtrl) ->
+ wxListCtrl:deleteAllItems(LCtrl),
+ wx:foldl(fun(Mod, Row) ->
+ _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
+ ?EVEN(Row) andalso
+ wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str(Mod)),
+ (Mod =:= Module) andalso
+ wxListCtrl:setItemState(LCtrl, Row, 16#FFFF, ?wxLIST_STATE_SELECTED),
+ Row+1
+ end, 0, Mods).
+
+update_functions_view(Funcs, LCtrl) ->
+ wxListCtrl:deleteAllItems(LCtrl),
+ wx:foldl(fun(#tpattern{fa=FA, ms=#match_spec{str=Ms}}, Row) ->
+ _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
+ ?EVEN(Row) andalso wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({func,FA})),
+ wxListCtrl:setItem(LCtrl, Row, 1, Ms),
+ Row+1
+ end, 0, Funcs).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+merge_pids([N1=#tpid{pid=new}|Ns], [N2=#tpid{pid=new}|Old]) ->
+ {Pids, New, Changed} = merge_pids_1(Ns,Old),
+ {[N1|Pids], New, [{N2,N2}|Changed]};
+merge_pids([N1=#tpid{pid=new}|Ns], Old) ->
+ {Pids, New, Changed} = merge_pids_1(Ns,Old),
+ {[N1|Pids], [N1|New], Changed};
+merge_pids(Ns, [N2=#tpid{pid=new}|Old]) ->
+ {Pids, New, Changed} = merge_pids_1(Ns,Old),
+ {[N2|Pids], New, Changed};
+merge_pids(New, Old) ->
+ merge_pids_1(New, Old).
+
+merge_pids_1(New, Old) ->
+ merge(lists:sort(New), Old, #tpid.pid, [], [], []).
+
+merge_patterns(New, Old) ->
+ merge(lists:sort(New), Old, #tpattern.fa, [], [], []).
+
+merge([N|Ns], [N|Os], El, New, Ch, All) ->
+ merge(Ns, Os, El, New, Ch, [N|All]);
+merge([N|Ns], [O|Os], El, New, Ch, All)
+ when element(El, N) == element(El, O) ->
+ merge(Ns, Os, El, New, [{O,N}|Ch], [N|All]);
+merge([N|Ns], Os=[O|_], El, New, Ch, All)
+ when element(El, N) < element(El, O) ->
+ merge(Ns, Os, El, [N|New], Ch, [N|All]);
+merge(Ns=[N|_], [O|Os], El, New, Ch, All)
+ when element(El, N) > element(El, O) ->
+ merge(Ns, Os, El, New, Ch, [O|All]);
+merge([], Os, _El, New, Ch, All) ->
+ {lists:reverse(All, Os), New, Ch};
+merge(Ns, [], _El, New, Ch, All) ->
+ {lists:reverse(All, Ns), Ns++New, Ch}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ttb_output_args(Parent, Opts) ->
+ ToWindow = proplists:get_value(window, Opts, true),
+ ToShell = proplists:get_value(shell, Opts, false),
+ ToFile = proplists:get_value(file, Opts, false),
+ ToWindow orelse ToShell orelse ToFile orelse
+ throw({error, "No output of trace"}),
+ {LogWin,Text} = create_logwindow(Parent, ToWindow),
+ Write = output_fun(Text, ToShell),
+ Shell = output_shell(ToFile, Write),
+ FileOpts = output_file(ToFile, proplists:get_value(wrap, Opts, false), Opts),
+ {[{file, {local,FileOpts}}|Shell], LogWin}.
+
+output_shell(true, false) ->
+ []; %% File only
+output_shell(true, Write) when is_function(Write) ->
+ [{shell, Write}];
+output_shell(false, Write) when is_function(Write) ->
+ [{shell, {only, Write}}].
+
+output_fun(false, false) -> false;
+output_fun(false, true) -> fun(Trace) -> io:put_chars(textformat(Trace)) end;
+output_fun(Text, false) ->
+ Env = wx:get_env(),
+ fun(Trace) ->
+ wx:set_env(Env),
+ wxTextCtrl:appendText(Text, textformat(Trace))
+ end;
+output_fun(Text, true) ->
+ Env = wx:get_env(),
+ fun(Trace) ->
+ wx:set_env(Env),
+ IoList = textformat(Trace),
+ wxTextCtrl:appendText(Text, IoList),
+ io:put_chars(textformat(Trace))
+ end.
+
+output_file(false, _, _Opts) ->
+ "ttb"; %% Will be ignored
+output_file(true, false, Opts) ->
+ proplists:get_value(filename, Opts, "ttb");
+output_file(true, true, Opts) ->
+ Name = proplists:get_value(filename, Opts, "ttb"),
+ Size = proplists:get_value(wrap_sz, Opts, 128),
+ Count = proplists:get_value(wrap_c, Opts, 8),
+ {wrap, Name, Size*1024, Count}.
+
+
+create_logwindow(_Parent, false) -> {false, false};
+create_logwindow(Parent, true) ->
+ LogWin = wxFrame:new(Parent, ?LOG_WIN, "Trace Log", [{size, {750, 800}}]),
+ MB = wxMenuBar:new(),
+ File = wxMenu:new(),
+ wxMenu:append(File, ?LOG_CLEAR, "Clear Log\tCtrl-C"),
+ wxMenu:append(File, ?LOG_SAVE, "Save Log\tCtrl-S"),
+ wxMenu:append(File, ?wxID_CLOSE, "Close"),
+ wxMenuBar:append(MB, File, "File"),
+ wxFrame:setMenuBar(LogWin, MB),
+ Text = wxTextCtrl:new(LogWin, ?wxID_ANY,
+ [{style, ?wxTE_MULTILINE bor ?wxTE_RICH2 bor
+ ?wxTE_DONTWRAP bor ?wxTE_READONLY}]),
+ Font = observer_wx:get_attrib({font, fixed}),
+ Attr = wxTextAttr:new(?wxBLACK, [{font, Font}]),
+ true = wxTextCtrl:setDefaultStyle(Text, Attr),
+ wxFrame:connect(LogWin, close_window, [{skip, true}]),
+ wxFrame:connect(LogWin, command_menu_selected, [{userData, Text}]),
+ wxFrame:show(LogWin),
+ {LogWin, Text}.
+
+setup_ttb(TPs, TPids) ->
+ _R1 = [setup_tps(FTP, []) || {_, FTP} <- TPs],
+ _R2 = [ttb:p(Pid, dbg_flags(Flags)) || #tpid{pid=Pid, opts=Flags} <- TPids],
+ [#tpid{pid=_Pid, opts=_Flags}|_] = TPids,
+ ok.
+
+%% Sigh order is important
+setup_tps([First=#tpattern{fa={_,'_'}}|Rest], Prev) ->
+ setup_tp(First),
+ [setup_tp(TP) || TP <- lists:reverse(Prev)],
+ setup_tps(Rest, []);
+setup_tps([First=#tpattern{fa={F,_}}|Rest], Prev = [#tpattern{fa={F,_}}|_]) ->
+ setup_tps(Rest, [First|Prev]);
+setup_tps([First|Rest], Prev) ->
+ [setup_tp(TP) || TP <- lists:reverse(Prev)],
+ setup_tps(Rest, [First]);
+setup_tps([], Prev) ->
+ [setup_tp(TP) || TP <- lists:reverse(Prev)].
+
+setup_tp(#tpattern{m=M,fa={F,A}, ms=#match_spec{term=Ms}}) ->
+ ttb:tpl(M,F,A,Ms).
+
+dbg_flags(Flags) ->
+ [dbg_flag(Flag) || Flag <- Flags].
+
+dbg_flag(send) -> s;
+dbg_flag('receive') -> r;
+dbg_flag(functions) -> c;
+dbg_flag(on_spawn) -> sos;
+dbg_flag(on_link) -> sol;
+dbg_flag(on_first_spawn) -> sofs;
+dbg_flag(on_first_link) -> sofl;
+dbg_flag(events) -> p.
+
+textformat(Trace) when element(1, Trace) == trace_ts, tuple_size(Trace) >= 4 ->
+ format_trace(Trace, tuple_size(Trace)-1, element(tuple_size(Trace),Trace));
+textformat(Trace) when element(1, Trace) == drop, tuple_size(Trace) =:= 2 ->
+ io_lib:format("*** Dropped ~p messages.~n", [element(2,Trace)]);
+textformat(Trace) when element(1, Trace) == seq_trace, tuple_size(Trace) >= 3 ->
+ io_lib:format("*** Seq trace not implmented.~n", []);
+textformat(_) ->
+ "".
+
+format_trace(Trace, Size, TS0={_,_,MS}) ->
+ {_,{H,M,S}} = calendar:now_to_local_time(TS0),
+ TS = io_lib:format("~.2.0w:~.2.0w:~.2.0w:~.6.0w", [H,M,S,MS]),
+ From = element(2, Trace),
+ case element(3, Trace) of
+ 'receive' ->
+ case element(4, Trace) of
+ {dbg,ok} -> "";
+ Message ->
+ io_lib:format("~s (~100p) << ~100p~n", [TS,From,Message])
+ end;
+ 'send' ->
+ Message = element(4, Trace),
+ To = element(5, Trace),
+ io_lib:format("~s (~100p) ~100p ! ~100p~n", [TS,From,To,Message]);
+ call ->
+ case element(4, Trace) of
+ MFA when Size == 5 ->
+ Message = element(5, Trace),
+ io_lib:format("~s (~100p) call ~s (~100p) ~n", [TS,From,ffunc(MFA),Message]);
+ MFA ->
+ io_lib:format("~s (~100p) call ~s~n", [TS,From,ffunc(MFA)])
+ end;
+ return_from ->
+ MFA = element(4, Trace),
+ Ret = element(5, Trace),
+ io_lib:format("~s (~100p) returned from ~s -> ~100p~n", [TS,From,ffunc(MFA),Ret]);
+ return_to ->
+ MFA = element(4, Trace),
+ io_lib:format("~s (~100p) returning to ~s~n", [TS,From,ffunc(MFA)]);
+ spawn when Size == 5 ->
+ Pid = element(4, Trace),
+ MFA = element(5, Trace),
+ io_lib:format("~s (~100p) spawn ~100p as ~s~n", [TS,From,Pid,ffunc(MFA)]);
+ Op ->
+ io_lib:format("~s (~100p) ~100p ~s~n", [TS,From,Op,ftup(Trace,4,Size)])
+ end.
+
+%%% These f* functions returns non-flat strings
+
+%% {M,F,[A1, A2, ..., AN]} -> "M:F(A1, A2, ..., AN)"
+%% {M,F,A} -> "M:F/A"
+ffunc({M,F,Argl}) when is_list(Argl) ->
+ io_lib:format("~100p:~100p(~s)", [M, F, fargs(Argl)]);
+ffunc({M,F,Arity}) ->
+ io_lib:format("~100p:~100p/~100p", [M,F,Arity]);
+ffunc(X) -> io_lib:format("~100p", [X]).
+
+%% Integer -> "Integer"
+%% [A1, A2, ..., AN] -> "A1, A2, ..., AN"
+fargs(Arity) when is_integer(Arity) -> integer_to_list(Arity);
+fargs([]) -> [];
+fargs([A]) -> io_lib:format("~100p", [A]); %% last arg
+fargs([A|Args]) -> [io_lib:format("~100p,", [A]) | fargs(Args)];
+fargs(A) -> io_lib:format("~100p", [A]). % last or only arg
+
+%% {A_1, A_2, ..., A_N} -> "A_Index A_Index+1 ... A_Size"
+ftup(Trace, Index, Index) ->
+ io_lib:format("~100p", [element(Index, Trace)]);
+ftup(Trace, Index, Size) ->
+ [io_lib:format("~100p ", [element(Index, Trace)])
+ | ftup(Trace, Index+1, Size)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+write_file(Frame, Filename, TraceOps, MatchSpecs, Output, TPs) ->
+ FormatMS = fun(#match_spec{name=Id, term=T, func=F}) ->
+ io_lib:format("[{name,\"~s\"}, {term, ~w}, {func, \"~s\"}]",
+ [Id, T, F])
+ end,
+ FormatTP = fun({Module, FTPs}) ->
+ List = format_ftp(FTPs, FormatMS),
+ io_lib:format("{tp, ~w, [~s]}.~n",[Module, List])
+ end,
+ Str =
+ ["%%%\n%%% This file is generated by Observer\n",
+ "%%%\n%%% DO NOT EDIT!\n%%%\n",
+ [["{ms, ", FormatMS(Ms), "}.\n"] || Ms <- MatchSpecs],
+ "{traceopts, ", io_lib:format("~w",[TraceOps]) ,"}.\n",
+ "{output, ", io_lib:format("~w",[Output]) ,"}.\n",
+ [FormatTP(TP) || TP <- TPs]
+ ],
+ case file:write_file(Filename, list_to_binary(Str)) of
+ ok ->
+ success;
+ {error, Reason} ->
+ FailMsg = file:format_error(Reason),
+ observer_wx:create_txt_dialog(Frame, FailMsg, "Error", ?wxICON_ERROR)
+ end.
+
+format_ftp([#tpattern{fa={F,A}, ms=Ms}], FormatMS) ->
+ io_lib:format("{~w, ~w, ~s}", [F,A,FormatMS(Ms)]);
+format_ftp([#tpattern{fa={F,A}, ms=Ms}|Rest], FormatMS) ->
+ [io_lib:format("{~w, ~w, ~s},~n ", [F,A,FormatMS(Ms)]),
+ format_ftp(Rest, FormatMS)].
+
+read_settings(Filename, #state{match_specs=Ms0, def_trace_opts=TO0} = State) ->
+ case file:consult(Filename) of
+ {ok, Terms} ->
+ Ms = lists:usort(Ms0 ++ [parse_ms(MsList) || {ms, MsList} <- Terms]),
+ TOs = lists:usort(TO0 ++ proplists:get_value(traceopts, Terms, [])),
+ Out = proplists:get_value(output, Terms, []),
+ lists:foldl(fun parse_tp/2,
+ State#state{match_specs=Ms, def_trace_opts=TOs, output=Out},
+ Terms);
+ {error, _} ->
+ observer_wx:create_txt_dialog(State#state.panel, "Could not load settings",
+ "Error", ?wxICON_ERROR),
+ State
+ end.
+
+parse_ms(Opts) ->
+ Name = proplists:get_value(name, Opts, "TracePattern"),
+ Term = proplists:get_value(term, Opts, [{'_',[],[ok]}]),
+ FunStr = proplists:get_value(term, Opts, "fun(_) -> ok end"),
+ make_ms(Name, Term, FunStr).
+
+make_ms(Name, Term, FunStr) ->
+ #match_spec{name=Name, term=Term, str=io_lib:format("~w", Term), func = FunStr}.
+
+parse_tp({tp, Mod, FAs}, State) ->
+ Patterns = [#tpattern{m=Mod,fa={F,A}, ms=parse_ms(List)} ||
+ {F,A,List} <- FAs],
+ do_add_patterns({Mod, Patterns}, State);
+parse_tp(_, State) ->
+ State.
+
+get_selected_items(Grid, Data) ->
+ get_indecies(get_selected_items(Grid, -1, []), Data).
+get_selected_items(Grid, Index, ItemAcc) ->
+ Item = wxListCtrl:getNextItem(Grid, Index, [{geometry, ?wxLIST_NEXT_ALL},
+ {state, ?wxLIST_STATE_SELECTED}]),
+ case Item of
+ -1 ->
+ lists:reverse(ItemAcc);
+ _ ->
+ get_selected_items(Grid, Item, [Item | ItemAcc])
+ end.
+
+get_indecies(Items, Data) ->
+ get_indecies(Items, 0, Data).
+get_indecies([I|Rest], I, [H|T]) ->
+ [H|get_indecies(Rest, I+1, T)];
+get_indecies(Rest = [_|_], I, [_|T]) ->
+ get_indecies(Rest, I+1, T);
+get_indecies(_, _, _) ->
+ [].
diff --git a/lib/observer/src/observer_traceoptions_wx.erl b/lib/observer/src/observer_traceoptions_wx.erl
new file mode 100644
index 0000000000..e27f565abc
--- /dev/null
+++ b/lib/observer/src/observer_traceoptions_wx.erl
@@ -0,0 +1,675 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_traceoptions_wx).
+
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+
+-export([process_trace/2, trace_pattern/4, select_nodes/2,
+ output/2, select_matchspec/3]).
+
+process_trace(Parent, Default) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Process Options",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER}]),
+ Panel = wxPanel:new(Dialog),
+ MainSz = wxBoxSizer:new(?wxVERTICAL),
+ PanelSz = wxBoxSizer:new(?wxHORIZONTAL),
+ LeftSz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, "Tracing options"}]),
+ RightSz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, "Inheritance options:"}]),
+
+ FuncBox = wxCheckBox:new(Panel, ?wxID_ANY, "Trace function call", []),
+ check_box(FuncBox, lists:member(functions, Default)),
+ SendBox = wxCheckBox:new(Panel, ?wxID_ANY, "Trace send message", []),
+ check_box(SendBox, lists:member(send, Default)),
+ RecBox = wxCheckBox:new(Panel, ?wxID_ANY, "Trace receive message", []),
+ check_box(RecBox, lists:member('receive', Default)),
+ EventBox = wxCheckBox:new(Panel, ?wxID_ANY, "Trace process events", []),
+ check_box(EventBox, lists:member(events, Default)),
+
+ {SpawnBox, SpwnAllRadio, SpwnFirstRadio} =
+ optionpage_top_right(Panel, RightSz, [{flag, ?wxBOTTOM},{border, 5}], "spawn"),
+ {LinkBox, LinkAllRadio, LinkFirstRadio} =
+ optionpage_top_right(Panel, RightSz, [{flag, ?wxBOTTOM},{border, 5}], "link"),
+ SpawnBool = lists:member(on_spawn, Default) orelse lists:member(on_first_spawn, Default),
+ LinkBool = lists:member(on_link, Default) orelse lists:member(on_first_link, Default),
+ check_box(SpawnBox, SpawnBool),
+ check_box(LinkBox, LinkBool),
+ enable(SpawnBox, [SpwnAllRadio, SpwnFirstRadio]),
+ enable(LinkBox, [LinkAllRadio, LinkFirstRadio]),
+ [wxRadioButton:setValue(Radio, lists:member(Opt, Default)) ||
+ {Radio, Opt} <- [{SpwnAllRadio, on_spawn}, {SpwnFirstRadio, on_first_spawn},
+ {LinkAllRadio, on_link}, {LinkFirstRadio, on_first_link}]],
+
+ [wxSizer:add(LeftSz, CheckBox, []) || CheckBox <- [FuncBox,SendBox,RecBox,EventBox]],
+ wxSizer:add(LeftSz, 150, -1),
+
+ wxSizer:add(PanelSz, LeftSz, [{flag, ?wxEXPAND}, {proportion,1}]),
+ wxSizer:add(PanelSz, RightSz,[{flag, ?wxEXPAND}, {proportion,1}]),
+ wxPanel:setSizer(Panel, PanelSz),
+ wxSizer:add(MainSz, Panel, [{flag, ?wxEXPAND}, {proportion,1}]),
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(MainSz, Buttons, [{flag, ?wxEXPAND bor ?wxALL}, {border, 5}]),
+ wxWindow:setSizerAndFit(Dialog, MainSz),
+ wxSizer:setSizeHints(MainSz, Dialog),
+ wxCheckBox:connect(SpawnBox, command_checkbox_clicked,
+ [{callback, fun(#wx{event=#wxCommand{}},_) ->
+ enable(SpawnBox, [SpwnAllRadio, SpwnFirstRadio])
+ end}]),
+ wxCheckBox:connect(LinkBox, command_checkbox_clicked,
+ [{callback, fun(#wx{event=#wxCommand{}},_) ->
+ enable(LinkBox, [LinkAllRadio, LinkFirstRadio])
+ end}]),
+
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ All = [{SendBox, send}, {RecBox, 'receive'},
+ {FuncBox, functions}, {EventBox, events},
+ {{SpawnBox, SpwnAllRadio}, on_spawn},
+ {{SpawnBox,SpwnFirstRadio}, on_first_spawn},
+ {{LinkBox, LinkAllRadio}, on_link},
+ {{LinkBox, LinkFirstRadio}, on_first_link}],
+ Check = fun({Box, Radio}) ->
+ wxCheckBox:getValue(Box) andalso wxRadioButton:getValue(Radio);
+ (Box) ->
+ wxCheckBox:getValue(Box)
+ end,
+ Opts = [Id || {Tick, Id} <- All, Check(Tick)],
+ wxDialog:destroy(Dialog),
+ lists:reverse(Opts);
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ throw(cancel)
+ end.
+
+trace_pattern(ParentPid, Parent, Node, MatchSpecs) ->
+ try
+ Module = module_selector(Parent, Node),
+ MFAs = function_selector(Parent, Node, Module),
+ MatchSpec = select_matchspec(ParentPid, Parent, MatchSpecs),
+ {Module, [#tpattern{m=M,fa={F,A},ms=MatchSpec} || {M,F,A} <- MFAs]}
+ catch cancel -> cancel
+ end.
+
+select_nodes(Parent, Nodes) ->
+ Choices = [{atom_to_list(X), X} || X <- Nodes],
+ check_selector(Parent, Choices).
+
+module_selector(Parent, Node) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Select Module",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER},
+ {size, {400, 400}}]),
+ Panel = wxPanel:new(Dialog),
+ PanelSz = wxBoxSizer:new(?wxVERTICAL),
+ MainSz = wxBoxSizer:new(?wxVERTICAL),
+
+ TxtCtrl = wxTextCtrl:new(Panel, ?wxID_ANY),
+ ListBox = wxListBox:new(Panel, ?wxID_ANY, [{style, ?wxLB_SINGLE}]),
+ wxSizer:add(PanelSz, TxtCtrl, [{flag, ?wxEXPAND}]),
+ wxSizer:add(PanelSz, ListBox, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxPanel:setSizer(Panel, PanelSz),
+ wxSizer:add(MainSz, Panel, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 1}]),
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(MainSz, Buttons, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 0}]),
+ wxWindow:setSizer(Dialog, MainSz),
+ OkId = wxDialog:getAffirmativeId(Dialog),
+ OkButt = wxWindow:findWindowById(OkId),
+ wxWindow:disable(OkButt),
+ wxWindow:setFocus(TxtCtrl),
+ %% init data
+ Modules = get_modules(Node),
+ AllModules = [{atom_to_list(X), X} || X <- Modules],
+ filter_listbox_data("", AllModules, ListBox),
+ wxTextCtrl:connect(TxtCtrl, command_text_updated,
+ [{callback, fun(#wx{event=#wxCommand{cmdString=Input}}, _) ->
+ filter_listbox_data(Input, AllModules, ListBox)
+ end}]),
+ wxListBox:connect(ListBox, command_listbox_doubleclicked,
+ [{callback, fun(_, _) -> wxDialog:endModal(Dialog, ?wxID_OK) end}]),
+ wxListBox:connect(ListBox, command_listbox_selected,
+ [{callback, fun(#wx{event=#wxCommand{commandInt=Id}}, _) ->
+ Id >= 0 andalso wxWindow:enable(OkButt)
+ end}]),
+
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ SelId = wxListBox:getSelection(ListBox),
+ case SelId >= 0 of
+ true ->
+ Module = wxListBox:getClientData(ListBox, SelId),
+ wxDialog:destroy(Dialog),
+ Module;
+ false ->
+ wxDialog:destroy(Dialog),
+ throw(cancel)
+ end;
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ throw(cancel)
+ end.
+
+function_selector(Parent, Node, Module) ->
+ Functions = observer_wx:try_rpc(Node, Module, module_info, [functions]),
+ Externals = observer_wx:try_rpc(Node, Module, module_info, [exports]),
+
+ Choices = lists:usort([{Name, Arity} || {Name, Arity} <- Externals ++ Functions,
+ not(erl_internal:guard_bif(Name, Arity))]),
+ ParsedChoices = parse_function_names(Choices),
+ case check_selector(Parent, ParsedChoices) of
+ [] -> [{Module, '_', '_'}];
+ FAs ->
+ [{Module, F, A} || {F,A} <- FAs]
+ end.
+
+check_selector(Parent, ParsedChoices) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Trace Functions",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER},
+ {size, {400, 400}}]),
+
+ Panel = wxPanel:new(Dialog),
+ PanelSz = wxBoxSizer:new(?wxVERTICAL),
+ MainSz = wxBoxSizer:new(?wxVERTICAL),
+
+ TxtCtrl = wxTextCtrl:new(Panel, ?wxID_ANY),
+ ListBox = wxCheckListBox:new(Panel, ?wxID_ANY, [{style, ?wxLB_EXTENDED}]),
+ wxSizer:add(PanelSz, TxtCtrl, [{flag, ?wxEXPAND}]),
+ wxSizer:add(PanelSz, ListBox, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ SelAllBtn = wxButton:new(Panel, ?wxID_ANY, [{label, "Check Visible"}]),
+ DeSelAllBtn = wxButton:new(Panel, ?wxID_ANY, [{label, "Uncheck Visible"}]),
+ ButtonSz = wxBoxSizer:new(?wxHORIZONTAL),
+ [wxSizer:add(ButtonSz, Button, []) || Button <- [SelAllBtn, DeSelAllBtn]],
+ wxSizer:add(PanelSz, ButtonSz, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 0}]),
+ wxPanel:setSizer(Panel, PanelSz),
+ wxSizer:add(MainSz, Panel, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 1}]),
+
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(MainSz, Buttons, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 0}]),
+ wxWindow:setSizer(Dialog, MainSz),
+ wxWindow:setFocus(TxtCtrl),
+ %% Init
+ filter_listbox_data("", ParsedChoices, ListBox, false),
+ %% Setup Event handling
+ wxTextCtrl:connect(TxtCtrl, command_text_updated,
+ [{callback,
+ fun(#wx{event=#wxCommand{cmdString=Input}}, _) ->
+ filter_listbox_data(Input, ParsedChoices, ListBox, false)
+ end}]),
+ Self = self(),
+
+ %% Sigh clientdata in checklistbox crashes on windows, wx-bug I presume.
+ %% Don't have time to investigate now, workaround file bug report later
+ GetClientData = fun(LB, N) ->
+ String = wxListBox:getString(LB, N),
+ {_, Data} = lists:keyfind(String, 1, ParsedChoices),
+ Data
+ end,
+ wxCheckListBox:connect(ListBox, command_checklistbox_toggled,
+ [{callback,
+ fun(#wx{event=#wxCommand{commandInt=N}}, _) ->
+ Self ! {ListBox, wxCheckListBox:isChecked(ListBox, N),
+ GetClientData(ListBox, N)}
+ end}]),
+ Check = fun(Id, Bool) ->
+ wxCheckListBox:check(ListBox, Id, [{check, Bool}]),
+ Self ! {ListBox, Bool, GetClientData(ListBox, Id)}
+ end,
+ wxButton:connect(SelAllBtn, command_button_clicked,
+ [{callback, fun(#wx{}, _) ->
+ Count = wxListBox:getCount(ListBox),
+ [Check(SelId, true) ||
+ SelId <- lists:seq(0, Count-1),
+ not wxCheckListBox:isChecked(ListBox, SelId)]
+ end}]),
+ wxButton:connect(DeSelAllBtn, command_button_clicked,
+ [{callback, fun(#wx{}, _) ->
+ Count = wxListBox:getCount(ListBox),
+ [Check(SelId, false) ||
+ SelId <- lists:seq(0, Count-1),
+ wxCheckListBox:isChecked(ListBox, SelId)]
+ end}]),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ wxDialog:destroy(Dialog),
+ get_checked(ListBox, []);
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ get_checked(ListBox, []),
+ throw(cancel)
+ end.
+
+get_checked(ListBox, Acc) ->
+ receive
+ {ListBox, true, FA} ->
+ get_checked(ListBox, [FA|lists:delete(FA,Acc)]);
+ {ListBox, false, FA} ->
+ get_checked(ListBox, lists:delete(FA,Acc))
+ after 0 ->
+ lists:reverse(Acc)
+ end.
+
+select_matchspec(Pid, Parent, MatchSpecs) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Trace Match Specifications",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER},
+ {size, {400, 400}}]),
+
+ Panel = wxPanel:new(Dialog),
+ PanelSz = wxBoxSizer:new(?wxVERTICAL),
+ MainSz = wxBoxSizer:new(?wxVERTICAL),
+ TxtSz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, "Match specification:"}]),
+ BtnSz = wxBoxSizer:new(?wxHORIZONTAL),
+ SavedSz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, "Saved match specifications:"}]),
+
+ TextCtrl = create_styled_txtctrl(Panel),
+ wxSizer:add(TxtSz, TextCtrl, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ AddMsBtn = wxButton:new(Panel, ?wxID_ANY, [{label, "New"}]),
+ EditMsBtn = wxButton:new(Panel, ?wxID_ANY, [{label, "Edit"}]),
+ DelMsBtn = wxButton:new(Panel, ?wxID_ANY, [{label, "Delete"}]),
+ wxSizer:add(BtnSz, AddMsBtn),
+ wxSizer:add(BtnSz, EditMsBtn),
+ wxSizer:add(BtnSz, DelMsBtn),
+
+ ListBox = wxListBox:new(Panel, ?wxID_ANY, []),
+ wxSizer:add(SavedSz, ListBox, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(PanelSz, TxtSz, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(PanelSz, BtnSz),
+ wxSizer:add(PanelSz, SavedSz, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ wxWindow:setSizer(Panel, PanelSz),
+ wxSizer:add(MainSz, Panel, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 1}]),
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(MainSz, Buttons, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 5}, {proportion, 0}]),
+ wxWindow:setSizer(Dialog, MainSz),
+ OkId = wxDialog:getAffirmativeId(Dialog),
+ OkButt = wxWindow:findWindowById(OkId),
+ wxWindow:disable(OkButt),
+ wxWindow:disable(EditMsBtn),
+ wxWindow:disable(DelMsBtn),
+
+ Choices = ms_names(MatchSpecs),
+ filter_listbox_data("", Choices, ListBox),
+
+ Add = fun(_,_) ->
+ case edit_ms(TextCtrl, new, Parent) of
+ Ms = #match_spec{} -> add_and_select(-1, Ms, ListBox);
+ Else -> Else
+ end
+ end,
+ Edit = fun(_,_) ->
+ SelId = wxListBox:getSelection(ListBox),
+ case SelId >= 0 of
+ true ->
+ #match_spec{name=Name} = wxListBox:getClientData(ListBox,SelId),
+ case edit_ms(TextCtrl, Name, Parent) of
+ Ms = #match_spec{} -> add_and_select(SelId, Ms, ListBox);
+ Else -> Else
+ end;
+ false ->
+ ok
+ end
+ end,
+ Del = fun(_,_) ->
+ SelId = wxListBox:getSelection(ListBox),
+ case SelId >= 0 of
+ true ->
+ wxListBox:delete(ListBox, SelId);
+ false ->
+ ok
+ end
+ end,
+ Sel = fun(#wx{event=#wxCommand{commandInt=Id}}, _) ->
+ case Id >= 0 of
+ true ->
+ wxWindow:enable(OkButt),
+ wxWindow:enable(EditMsBtn),
+ wxWindow:enable(DelMsBtn),
+ #match_spec{func=Str} = wxListBox:getClientData(ListBox,Id),
+ wxStyledTextCtrl:setText(TextCtrl, Str);
+ false ->
+ try
+ wxWindow:disable(OkButt),
+ wxWindow:disable(EditMsBtn),
+ wxWindow:disable(DelMsBtn)
+ catch _:_ -> ok
+ end
+ end
+ end,
+ wxButton:connect(AddMsBtn, command_button_clicked, [{callback,Add}]),
+ wxButton:connect(EditMsBtn, command_button_clicked, [{callback,Edit}]),
+ wxButton:connect(DelMsBtn, command_button_clicked, [{callback,Del}]),
+ wxListBox:connect(ListBox, command_listbox_selected, [{callback, Sel}]),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ SelId = wxListBox:getSelection(ListBox),
+ Count = wxListBox:getCount(ListBox),
+ MSs = [wxListBox:getClientData(ListBox, Id) ||
+ Id <- lists:seq(0, Count-1)],
+ Pid ! {update_ms, MSs},
+ MS = lists:nth(SelId+1, MSs),
+ wxDialog:destroy(Dialog),
+ MS;
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ throw(cancel)
+ end.
+
+output(Parent, Default) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Process Options",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER}]),
+ Panel = wxPanel:new(Dialog),
+ MainSz = wxBoxSizer:new(?wxVERTICAL),
+ PanelSz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, "Output"}]),
+
+ %% Output select
+ WinB = wxCheckBox:new(Panel, ?wxID_ANY, "Window", []),
+ check_box(WinB, proplists:get_value(window, Default, true)),
+ ShellB = wxCheckBox:new(Panel, ?wxID_ANY, "Shell", []),
+ check_box(ShellB, proplists:get_value(shell, Default, false)),
+ [wxSizer:add(PanelSz, CheckBox, []) || CheckBox <- [WinB, ShellB]],
+ GetFileOpts = ttb_file_options(Panel, PanelSz, Default),
+ %% Set sizer and show dialog
+ wxPanel:setSizer(Panel, PanelSz),
+ wxSizer:add(MainSz, Panel, [{flag, ?wxEXPAND bor ?wxALL}, {proportion,1}, {border, 3}]),
+ Buttons = wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(MainSz, Buttons, [{flag, ?wxEXPAND bor ?wxALL}, {border, 5}]),
+ wxWindow:setSizerAndFit(Dialog, MainSz),
+ wxSizer:setSizeHints(MainSz, Dialog),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Res = [{window, wxCheckBox:getValue(WinB)},
+ {shell, wxCheckBox:getValue(ShellB)} | GetFileOpts()],
+ wxDialog:destroy(Dialog),
+ Res;
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ throw(cancel)
+ end.
+
+edit_ms(TextCtrl, Label0, Parent) ->
+ Str = ensure_last_is_dot(wxStyledTextCtrl:getText(TextCtrl)),
+ try
+ MatchSpec = ms_from_string(Str),
+ Label = case Label0 == new of
+ true -> get_label(Parent);
+ _ -> Label0
+ end,
+ #match_spec{name=Label, term=MatchSpec,
+ str=io_lib:format("~w",[MatchSpec]),
+ func=Str}
+ catch
+ throw:cancel ->
+ ok;
+ throw:Error ->
+ observer_wx:create_txt_dialog(Parent, Error, "Error", ?wxICON_ERROR),
+ ok
+ end.
+
+get_label(Frame) ->
+ Dialog = wxTextEntryDialog:new(Frame, "Enter alias: "),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ wxTextEntryDialog:getValue(Dialog);
+ ?wxID_CANCEL ->
+ throw(cancel)
+ end.
+
+ms_from_string(Str) ->
+ try
+ Tokens = case erl_scan:string(Str) of
+ {ok, Ts, _} -> Ts;
+ {error, {SLine, SMod, SError}, _} ->
+ throw(io_lib:format("~w: ~s", [SLine,SMod:format_error(SError)]))
+ end,
+ Exprs = case erl_parse:parse_exprs(Tokens) of
+ {ok, T} -> T;
+ {error, {PLine, PMod, PError}} ->
+ throw(io_lib:format("~w: ~s", [PLine,PMod:format_error(PError)]))
+ end,
+ Term = case Exprs of
+ [{'fun', _, {clauses, Clauses}}|_] ->
+ case ms_transform:transform_from_shell(dbg,Clauses,orddict:new()) of
+ {error, [{_,[{MSLine,Mod,MSInfo}]}],_} ->
+ throw(io_lib:format("~w: ~p", [MSLine,Mod:format_error(MSInfo)]));
+ {error, _} ->
+ throw("Could not convert fun() to match spec");
+ Ms ->
+ Ms
+ end;
+ [Expr|_] ->
+ erl_parse:normalise(Expr)
+ end,
+ case erlang:match_spec_test([], Term, trace) of
+ {ok, _, _, _} -> Term;
+ {error, List} -> throw([[Error, $\n] || {_, Error} <- List])
+ end
+ catch error:_Reason ->
+ %% io:format("Bad term: ~s~n ~p in ~p~n", [Str, _Reason, erlang:get_stacktrace()]),
+ throw("Invalid term")
+ end.
+
+add_and_select(Id, MS0, ListBox) ->
+ [{Str,User}] = ms_names([MS0]),
+ Sel = case Id >= 0 of
+ true ->
+ wxListBox:setString(ListBox, Id, Str),
+ wxListBox:setClientData(ListBox, Id, User),
+ Id;
+ false ->
+ wxListBox:append(ListBox, Str, User)
+ end,
+ wxListBox:setSelection(ListBox, Sel).
+
+filter_listbox_data(Input, Data, ListBox) ->
+ filter_listbox_data(Input, Data, ListBox, true).
+
+filter_listbox_data(Input, Data, ListBox, AddClientData) ->
+ FilteredData = [X || X = {Str, _} <- Data, re:run(Str, Input) =/= nomatch],
+ wxListBox:clear(ListBox),
+ wxListBox:appendStrings(ListBox, [Str || {Str,_} <- FilteredData]),
+ AddClientData andalso
+ wx:foldl(fun({_, Term}, N) ->
+ wxListBox:setClientData(ListBox, N, Term),
+ N+1
+ end, 0, FilteredData),
+ FilteredData.
+
+get_modules(Node) ->
+ lists:sort([Module || {Module, _} <- observer_wx:try_rpc(Node, code, all_loaded, [])]).
+
+optionpage_top_right(Panel, TopRightSz, Options, Text) ->
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ ChkBox = wxCheckBox:new(Panel, ?wxID_ANY, "Inherit on " ++ Text, []),
+ RadioSz = wxBoxSizer:new(?wxVERTICAL),
+ Radio1 = wxRadioButton:new(Panel, ?wxID_ANY, "All " ++ Text, [{style, ?wxRB_GROUP}]),
+ Radio2 = wxRadioButton:new(Panel, ?wxID_ANY, "First " ++ Text ++ " only", []),
+ wxSizer:add(Sizer, ChkBox, []),
+ wxSizer:add(RadioSz, Radio1, []),
+ wxSizer:add(RadioSz, Radio2, []),
+ wxSizer:add(Sizer, RadioSz, [{flag, ?wxLEFT},{border, 20}]),
+ wxSizer:add(TopRightSz, Sizer, Options),
+ {ChkBox, Radio1, Radio2}.
+
+
+create_styled_txtctrl(Parent) ->
+ FixedFont = observer_wx:get_attrib({font, fixed}),
+ Ed = wxStyledTextCtrl:new(Parent),
+ wxStyledTextCtrl:styleClearAll(Ed),
+ wxStyledTextCtrl:styleSetFont(Ed, ?wxSTC_STYLE_DEFAULT, FixedFont),
+ wxStyledTextCtrl:setLexer(Ed, ?wxSTC_LEX_ERLANG),
+ wxStyledTextCtrl:setMarginType(Ed, 1, ?wxSTC_MARGIN_NUMBER),
+ wxStyledTextCtrl:setSelectionMode(Ed, ?wxSTC_SEL_LINES),
+ wxStyledTextCtrl:setUseHorizontalScrollBar(Ed, false),
+
+ Styles = [{?wxSTC_ERLANG_DEFAULT, {0,0,0}},
+ {?wxSTC_ERLANG_COMMENT, {160,53,35}},
+ {?wxSTC_ERLANG_VARIABLE, {150,100,40}},
+ {?wxSTC_ERLANG_NUMBER, {5,5,100}},
+ {?wxSTC_ERLANG_KEYWORD, {130,40,172}},
+ {?wxSTC_ERLANG_STRING, {170,45,132}},
+ {?wxSTC_ERLANG_OPERATOR, {30,0,0}},
+ {?wxSTC_ERLANG_ATOM, {0,0,0}},
+ {?wxSTC_ERLANG_FUNCTION_NAME, {64,102,244}},
+ {?wxSTC_ERLANG_CHARACTER,{236,155,172}},
+ {?wxSTC_ERLANG_MACRO, {40,144,170}},
+ {?wxSTC_ERLANG_RECORD, {40,100,20}},
+ {?wxSTC_ERLANG_SEPARATOR,{0,0,0}},
+ {?wxSTC_ERLANG_NODE_NAME,{0,0,0}}],
+ SetStyle = fun({Style, Color}) ->
+ wxStyledTextCtrl:styleSetFont(Ed, Style, FixedFont),
+ wxStyledTextCtrl:styleSetForeground(Ed, Style, Color)
+ end,
+ [SetStyle(Style) || Style <- Styles],
+ wxStyledTextCtrl:setKeyWords(Ed, 0, keyWords()),
+ Ed.
+
+
+keyWords() ->
+ L = ["after","begin","case","try","cond","catch","andalso","orelse",
+ "end","fun","if","let","of","query","receive","when","bnot","not",
+ "div","rem","band","and","bor","bxor","bsl","bsr","or","xor"],
+ lists:flatten([K ++ " " || K <- L] ++ [0]).
+
+
+enable(CheckBox, Radio) ->
+ case wxCheckBox:isChecked(CheckBox) of
+ false ->
+ [wxWindow:disable(R) || R <- Radio];
+ true ->
+ [wxWindow:enable(R) || R <- Radio]
+ end.
+
+
+check_box(ChkBox, Bool) ->
+ case Bool of
+ true ->
+ wxCheckBox:set3StateValue(ChkBox, ?wxCHK_CHECKED);
+ false ->
+ ignore
+ end.
+
+parse_function_names(Choices) ->
+ StrList = [{atom_to_list(Name) ++ "/" ++ integer_to_list(Arity), Term}
+ || Term = {Name, Arity} <- Choices],
+ parse_function_names(StrList, []).
+
+parse_function_names([], Acc) ->
+ lists:reverse(Acc);
+parse_function_names([{H, Term}|T], Acc) ->
+ IsFun = re:run(H, ".*-fun-\\d*?-"),
+ IsLc = re:run(H, ".*-lc\\$\\^\\d*?/\\d*?-\\d*?-"),
+ IsLbc = re:run(H, ".*-lbc\\$\\^\\d*?/\\d*?-\\d*?-"),
+ Parsed =
+ if IsFun =/= nomatch -> "Fun: " ++ H;
+ IsLc =/= nomatch -> "List comprehension: " ++ H;
+ IsLbc =/= nomatch -> "Bit comprehension: " ++ H;
+ true ->
+ H
+ end,
+ parse_function_names(T, [{Parsed, Term} | Acc]).
+
+ms_names(MatchSpecList) ->
+ MsOrAlias = fun(#match_spec{name = A, str = M}) ->
+ case A of
+ "" -> M;
+ _ -> A ++ " " ++ M
+ end
+ end,
+ [{MsOrAlias(X), X} || X <- MatchSpecList].
+
+ensure_last_is_dot([]) ->
+ ".";
+ensure_last_is_dot(String) ->
+ case lists:last(String) =:= $. of
+ true ->
+ String;
+ false ->
+ String ++ "."
+ end.
+
+ttb_file_options(Panel, Sizer, Default) ->
+ Top = wxBoxSizer:new(?wxVERTICAL),
+ NameS = wxBoxSizer:new(?wxHORIZONTAL),
+ FileBox = wxCheckBox:new(Panel, ?wxID_ANY, "File (Using ttb file tracer)", []),
+ check_box(FileBox, proplists:get_value(file, Default, false)),
+ wxSizer:add(Sizer, FileBox),
+ Desc = wxStaticText:new(Panel, ?wxID_ANY, "File"),
+ FileName = proplists:get_value(filename, Default, "ttb"),
+ FileT = wxTextCtrl:new(Panel, ?wxID_ANY, [{size, {150,-1}}, {value, FileName}]),
+ FileB = wxButton:new(Panel, ?wxID_ANY, [{label, "Browse"}]),
+ wxSizer:add(NameS, Desc, [{proportion, 0}, {flag, ?wxALIGN_CENTER_VERTICAL}]),
+ wxSizer:add(NameS, FileT, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALIGN_CENTER_VERTICAL}]),
+ wxSizer:add(NameS, FileB, [{proportion, 0}, {flag, ?wxALIGN_CENTER_VERTICAL}]),
+
+ WrapB = wxCheckBox:new(Panel, ?wxID_ANY, "Wrap logs"),
+ WrapSz = wxSlider:new(Panel, ?wxID_ANY, proplists:get_value(wrap_sz, Default, 128),
+ 64, 10*1024, [{style, ?wxSL_HORIZONTAL bor ?wxSL_LABELS}]),
+ WrapC = wxSlider:new(Panel, ?wxID_ANY, proplists:get_value(wrap_c, Default, 8),
+ 2, 100, [{style, ?wxSL_HORIZONTAL bor ?wxSL_LABELS}]),
+
+ wxSizer:add(Top, NameS, [{flag, ?wxEXPAND}]),
+ wxSizer:add(Top, WrapB, []),
+ wxSizer:add(Top, WrapSz,[{flag, ?wxEXPAND}]),
+ wxSizer:add(Top, WrapC, [{flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, Top, [{flag, ?wxEXPAND bor ?wxLEFT},{border, 20}]),
+
+ Enable = fun(UseFile, UseWrap0) ->
+ UseWrap = UseFile andalso UseWrap0,
+ [wxWindow:enable(W, [{enable, UseFile}]) || W <- [Desc,FileT,FileB,WrapB]],
+ [wxWindow:enable(W, [{enable, UseWrap}]) || W <- [WrapSz, WrapC]],
+ check_box(WrapB, UseWrap0)
+ end,
+ Enable(proplists:get_value(file, Default, false), proplists:get_value(wrap, Default, false)),
+ wxPanel:connect(FileBox, command_checkbox_clicked,
+ [{callback, fun(_,_) ->
+ Enable(wxCheckBox:getValue(FileBox),
+ wxCheckBox:getValue(WrapB))
+ end}]),
+ wxPanel:connect(WrapB, command_checkbox_clicked,
+ [{callback, fun(_,_) ->
+ Enable(true, wxCheckBox:getValue(WrapB))
+ end}]),
+ wxPanel:connect(FileB, command_button_clicked,
+ [{callback, fun(_,_) -> get_file(FileT) end}]),
+ fun() ->
+ [{file, wxCheckBox:getValue(FileBox)},
+ {filename, wxTextCtrl:getValue(FileT)},
+ {wrap, wxCheckBox:getValue(WrapB)},
+ {wrap_sz, wxSlider:getValue(WrapSz)},
+ {wrap_c, wxSlider:getValue(WrapC)}]
+ end.
+
+get_file(Text) ->
+ Str = wxTextCtrl:getValue(Text),
+ Dialog = wxFileDialog:new(Text,
+ [{message, "Select a file"},
+ {default_file, Str}]),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Dir = wxFileDialog:getDirectory(Dialog),
+ File = wxFileDialog:getFilename(Dialog),
+ wxTextCtrl:setValue(Text, filename:join(Dir, File));
+ _ -> ok
+ end,
+ wxFileDialog:destroy(Dialog).
diff --git a/lib/observer/src/observer_tv.hrl b/lib/observer/src/observer_tv.hrl
new file mode 100644
index 0000000000..05e4f928d0
--- /dev/null
+++ b/lib/observer/src/observer_tv.hrl
@@ -0,0 +1,34 @@
+%%
+%% %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%
+
+-record(tab, {name,
+ id = ignore,
+ size,
+ memory=0, %% In bytes
+ owner,
+ reg_name,
+ protection = public,
+ type=set,
+ keypos=1,
+ heir=none,
+ compressed=false,
+ fixed=false,
+ %% Mnesia Info
+ storage,
+ index
+ }).
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
new file mode 100644
index 0000000000..c41f0f006a
--- /dev/null
+++ b/lib/observer/src/observer_tv_table.erl
@@ -0,0 +1,829 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_tv_table).
+
+-export([start_link/2]).
+
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_sync_event/3, handle_cast/2]).
+
+-export([format/1]).
+
+-include("observer_defs.hrl").
+-import(observer_lib, [to_str/1]).
+
+-behaviour(wx_object).
+-include_lib("wx/include/wx.hrl").
+-include("observer_tv.hrl").
+
+-define(ID_TABLE_INFO, 400).
+-define(ID_REFRESH, 401).
+-define(ID_REFRESH_INTERVAL, 402).
+-define(ID_EDIT, 403).
+-define(ID_DELETE, 404).
+-define(ID_SEARCH, 405).
+
+-define(SEARCH_ENTRY, 420).
+-define(GOTO_ENTRY, 421).
+
+-define(DEFAULT_COL_WIDTH, 150).
+
+-record(state,
+ {
+ parent,
+ frame,
+ grid,
+ status,
+ sizer,
+ search,
+ selected,
+ node=node(),
+ columns,
+ pid,
+ source,
+ tab,
+ attrs,
+ timer={false, 30}
+ }).
+
+-record(opt,
+ {
+ sort_key=2,
+ sort_incr=true
+ }).
+
+-record(search,
+ {enable=true, % Subwindow is enabled
+ win, % Sash Sub window obj
+ name, % name
+
+ search, % Search input ctrl
+ goto, % Goto input ctrl
+ radio, % Radio buttons
+
+ find % Search string
+ }).
+
+-record(find, {start, % start pos
+ strlen, % Found
+ found % false
+ }).
+
+start_link(Parent, Opts) ->
+ wx_object:start_link(?MODULE, [Parent, Opts], []).
+
+init([Parent, Opts]) ->
+ Source = proplists:get_value(type, Opts),
+ Table = proplists:get_value(table, Opts),
+ Node = proplists:get_value(node, Opts),
+ Title0 = atom_to_list(Table#tab.name) ++ " @ " ++ atom_to_list(Node),
+ Title = case Source of
+ ets -> "TV Ets: " ++ Title0;
+ mnesia -> "TV Mnesia: " ++ Title0
+ end,
+ Frame = wxFrame:new(Parent, ?wxID_ANY, Title, [{size, {800, 300}}]),
+ IconFile = filename:join(code:priv_dir(observer), "erlang_observer.png"),
+ Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
+ wxFrame:setIcon(Frame, Icon),
+ wxIcon:destroy(Icon),
+ MenuBar = wxMenuBar:new(),
+ create_menus(MenuBar),
+ wxFrame:setMenuBar(Frame, MenuBar),
+ %% wxFrame:setAcceleratorTable(Frame, AccelTable),
+ wxMenu:connect(Frame, command_menu_selected),
+
+ StatusBar = wxFrame:createStatusBar(Frame, []),
+ try
+ TabId = table_id(Table),
+ ColumnNames = column_names(Node, Source, TabId),
+ KeyPos = key_pos(Node, Source, TabId),
+
+ Attrs = observer_lib:create_attrs(),
+
+ Self = self(),
+ Holder = spawn_link(fun() ->
+ init_table_holder(Self, Table, Source,
+ length(ColumnNames), Node, Attrs)
+ end),
+
+ Panel = wxPanel:new(Frame),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
+ Grid = wxListCtrl:new(Panel, [{style, Style},
+ {onGetItemText,
+ fun(_, Item,Col) -> get_row(Holder, Item, Col+1) end},
+ {onGetItemAttr,
+ fun(_, Item) -> get_attr(Holder, Item) end}
+ ]),
+ wxListCtrl:connect(Grid, command_list_item_activated),
+ wxListCtrl:connect(Grid, command_list_item_selected),
+ wxListCtrl:connect(Grid, command_list_col_click),
+ wxListCtrl:connect(Grid, size, [{skip, true}]),
+ wxWindow:setFocus(Grid),
+
+ Search = search_area(Panel),
+ wxSizer:add(Sizer, Grid,
+ [{flag, ?wxEXPAND bor ?wxALL}, {proportion, 1}, {border, 5}]),
+ wxSizer:add(Sizer, Search#search.win,
+ [{flag,?wxEXPAND bor ?wxLEFT bor ?wxRIGHT bor
+ ?wxRESERVE_SPACE_EVEN_IF_HIDDEN},
+ {border, 5}]),
+ wxWindow:setSizer(Panel, Sizer),
+ wxSizer:hide(Sizer, Search#search.win),
+
+ Cols = add_columns(Grid, 0, ColumnNames),
+ wxFrame:show(Frame),
+ {Panel, #state{frame=Frame, grid=Grid, status=StatusBar, search=Search,
+ sizer = Sizer,
+ parent=Parent, columns=Cols,
+ pid=Holder, source=Source, tab=Table#tab{keypos=KeyPos},
+ attrs=Attrs}}
+ catch node_or_table_down ->
+ wxFrame:destroy(Frame),
+ stop
+ end.
+
+add_columns(Grid, Start, ColumnNames) ->
+ Li = wxListItem:new(),
+ AddListEntry = fun(Name, Col) ->
+ wxListItem:setText(Li, to_str(Name)),
+ wxListItem:setAlign(Li, ?wxLIST_FORMAT_LEFT),
+ wxListCtrl:insertColumn(Grid, Col, Li),
+ wxListCtrl:setColumnWidth(Grid, Col, ?DEFAULT_COL_WIDTH),
+ Col + 1
+ end,
+ Cols = lists:foldl(AddListEntry, Start, ColumnNames),
+ wxListItem:destroy(Li),
+ Cols.
+
+create_menus(MB) ->
+ File = wxMenu:new(),
+ wxMenu:append(File, ?ID_TABLE_INFO, "Table Information\tCtrl-I"),
+ wxMenu:append(File, ?wxID_CLOSE, "Close"),
+ wxMenuBar:append(MB, File, "File"),
+ Edit = wxMenu:new(),
+ wxMenu:append(Edit, ?ID_EDIT, "Edit Object"),
+ wxMenu:append(Edit, ?ID_DELETE, "Delete Object\tCtrl-D"),
+ wxMenu:appendSeparator(Edit),
+ wxMenu:append(Edit, ?ID_SEARCH, "Search\tCtrl-S"),
+ wxMenu:appendSeparator(Edit),
+ wxMenu:append(Edit, ?ID_REFRESH, "Refresh\tCtrl-R"),
+ wxMenu:append(Edit, ?ID_REFRESH_INTERVAL, "Refresh interval..."),
+ wxMenuBar:append(MB, Edit, "Edit"),
+ Help = wxMenu:new(),
+ wxMenu:append(Help, ?wxID_HELP, "Help"),
+ wxMenuBar:append(MB, Help, "Help"),
+ ok.
+
+search_area(Parent) ->
+ HSz = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Find:"),
+ [{flag,?wxALIGN_CENTER_VERTICAL}]),
+ TC1 = wxTextCtrl:new(Parent, ?SEARCH_ENTRY, [{style, ?wxTE_PROCESS_ENTER}]),
+ wxSizer:add(HSz, TC1, [{proportion,3}, {flag, ?wxEXPAND}]),
+ Nbtn = wxRadioButton:new(Parent, ?wxID_ANY, "Next"),
+ wxRadioButton:setValue(Nbtn, true),
+ wxSizer:add(HSz,Nbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]),
+ Pbtn = wxRadioButton:new(Parent, ?wxID_ANY, "Previous"),
+ wxSizer:add(HSz,Pbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]),
+ Cbtn = wxCheckBox:new(Parent, ?wxID_ANY, "Match Case"),
+ wxSizer:add(HSz,Cbtn,[{flag,?wxALIGN_CENTER_VERTICAL}]),
+ wxSizer:add(HSz, 15,15, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(HSz, wxStaticText:new(Parent, ?wxID_ANY, "Goto Entry:"),
+ [{flag,?wxALIGN_CENTER_VERTICAL}]),
+ TC2 = wxTextCtrl:new(Parent, ?GOTO_ENTRY, [{style, ?wxTE_PROCESS_ENTER}]),
+ wxSizer:add(HSz, TC2, [{proportion,0}, {flag, ?wxEXPAND}]),
+ wxTextCtrl:connect(TC1, command_text_updated),
+ wxTextCtrl:connect(TC1, command_text_enter),
+ wxTextCtrl:connect(TC1, kill_focus),
+ wxTextCtrl:connect(TC2, command_text_enter),
+ wxWindow:connect(Parent, command_button_clicked),
+
+ #search{name='Search Area', win=HSz,
+ search=TC1,goto=TC2,radio={Nbtn,Pbtn,Cbtn}}.
+
+edit(Index, #state{pid=Pid, frame=Frame}) ->
+ Str = get_row(Pid, Index, all_multiline),
+ case observer_lib:user_term_multiline(Frame, "Edit object:", Str) of
+ cancel -> ok;
+ {ok, Term} -> Pid ! {edit, Index, Term};
+ Err = {error, _} -> self() ! Err
+ end.
+
+handle_event(#wx{id=?ID_REFRESH},State = #state{pid=Pid}) ->
+ Pid ! refresh,
+ {noreply, State};
+
+handle_event(#wx{event=#wxList{type=command_list_col_click, col=Col}},
+ State = #state{pid=Pid}) ->
+ Pid ! {sort, Col+1},
+ {noreply, State};
+
+handle_event(#wx{event=#wxSize{size={W,_}}}, State=#state{grid=Grid}) ->
+ observer_lib:set_listctrl_col_size(Grid, W),
+ {noreply, State};
+
+handle_event(#wx{event=#wxList{type=command_list_item_selected, itemIndex=Index}},
+ State = #state{pid=Pid, grid=Grid, status=StatusBar}) ->
+ N = wxListCtrl:getItemCount(Grid),
+ Str = get_row(Pid, Index, all),
+ wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w: ~s",[N, Str])),
+ {noreply, State#state{selected=Index}};
+
+handle_event(#wx{event=#wxList{type=command_list_item_activated, itemIndex=Index}},
+ State) ->
+ edit(Index, State),
+ {noreply, State};
+
+handle_event(#wx{id=?ID_EDIT}, State = #state{selected=undefined}) ->
+ {noreply, State};
+handle_event(#wx{id=?ID_EDIT}, State = #state{selected=Index}) ->
+ edit(Index, State),
+ {noreply, State};
+
+handle_event(#wx{id=?ID_DELETE}, State = #state{selected=undefined}) ->
+ {noreply, State};
+handle_event(#wx{id=?ID_DELETE},
+ State = #state{pid=Pid, status=StatusBar, selected=Index}) ->
+ Str = get_row(Pid, Index, all),
+ Pid ! {delete, Index},
+ wxStatusBar:setStatusText(StatusBar, io_lib:format("Deleted object: ~s",[Str])),
+ {noreply, State};
+
+handle_event(#wx{id=?wxID_CLOSE}, State = #state{frame=Frame}) ->
+ wxFrame:destroy(Frame),
+ {stop, normal, State};
+
+handle_event(Help = #wx{id=?wxID_HELP}, State) ->
+ observer ! Help,
+ {noreply, State};
+
+handle_event(#wx{id=?GOTO_ENTRY, event=#wxCommand{cmdString=Str}},
+ State = #state{grid=Grid}) ->
+ try
+ Row0 = list_to_integer(Str),
+ Row1 = min(0, Row0),
+ Row = max(wxListCtrl:getItemCount(Grid)-1,Row1),
+ wxListCtrl:ensureVisible(Grid, Row),
+ ok
+ catch _:_ -> ok
+ end,
+ {noreply, State};
+
+%% Search functionality
+handle_event(#wx{id=?ID_SEARCH},
+ State = #state{sizer=Sz, search=Search}) ->
+ wxSizer:show(Sz, Search#search.win),
+ wxWindow:setFocus(Search#search.search),
+ wxSizer:layout(Sz),
+ {noreply, State};
+handle_event(#wx{id=?SEARCH_ENTRY, event=#wxFocus{}},
+ State = #state{search=Search, pid=Pid}) ->
+ Pid ! {mark_search_hit, false},
+ {noreply, State#state{search=Search#search{find=undefined}}};
+handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{cmdString=""}},
+ State = #state{search=Search, pid=Pid}) ->
+ Pid ! {mark_search_hit, false},
+ {noreply, State#state{search=Search#search{find=undefined}}};
+handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{type=command_text_enter,cmdString=Str}},
+ State = #state{grid=Grid, pid=Pid, status=SB,
+ search=Search=#search{radio={Next0, _, Case0},
+ find=Find}})
+ when Find =/= undefined ->
+ Dir = wxRadioButton:getValue(Next0) xor wx_misc:getKeyState(?WXK_SHIFT),
+ Case = wxCheckBox:getValue(Case0),
+ Pos = if Find#find.found, Dir -> %% Forward Continuation
+ Find#find.start+1;
+ Find#find.found -> %% Backward Continuation
+ Find#find.start-1;
+ Dir -> %% Forward wrap
+ 0;
+ true -> %% Backward wrap
+ wxListCtrl:getItemCount(Grid)-1
+ end,
+ Pid ! {mark_search_hit, false},
+ case search(Pid, Str, Pos, Dir, Case) of
+ false ->
+ wxStatusBar:setStatusText(SB, "Not found"),
+ Pid ! {mark_search_hit, Find#find.start},
+ wxListCtrl:refreshItem(Grid, Find#find.start),
+ {noreply, State#state{search=Search#search{find=Find#find{found=false}}}};
+ Row ->
+ wxListCtrl:ensureVisible(Grid, Row),
+ wxListCtrl:refreshItem(Grid, Row),
+ Status = "Found: (Hit Enter for next, Shift-Enter for previous)",
+ wxStatusBar:setStatusText(SB, Status),
+ {noreply, State#state{search=Search#search{find=#find{start=Row, found=true}}}}
+ end;
+handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{cmdString=Str}},
+ State = #state{grid=Grid, pid=Pid, status=SB,
+ search=Search=#search{radio={Next0, _, Case0},
+ find=Find}}) ->
+ try
+ Dir = wxRadioButton:getValue(Next0),
+ Case = wxCheckBox:getValue(Case0),
+ Start = case Dir of
+ true -> 0;
+ false -> wxListCtrl:getItemCount(Grid)-1
+ end,
+ Cont = case Find of
+ undefined ->
+ #find{start=Start, strlen=length(Str)};
+ #find{strlen=Old} when Old < length(Str) ->
+ Find#find{start=Start, strlen=length(Str)};
+ _ ->
+ Find#find{strlen=length(Str)}
+ end,
+
+ Pid ! {mark_search_hit, false},
+ case search(Pid, Str, Cont#find.start, Dir, Case) of
+ false ->
+ wxStatusBar:setStatusText(SB, "Not found"),
+ {noreply, State};
+ Row ->
+ wxListCtrl:ensureVisible(Grid, Row),
+ wxListCtrl:refreshItem(Grid, Row),
+ Status = "Found: (Hit Enter for next, Shift-Enter for previous)",
+ wxStatusBar:setStatusText(SB, Status),
+ {noreply, State#state{search=Search#search{find=#find{start=Row, found=true}}}}
+ end
+ catch _:_ -> {noreply, State}
+ end;
+
+handle_event(#wx{id=?ID_TABLE_INFO},
+ State = #state{frame=Frame, node=Node, source=Source, tab=Table}) ->
+ observer_tv_wx:display_table_info(Frame, Node, Source, Table),
+ {noreply, State};
+
+handle_event(#wx{id=?ID_REFRESH_INTERVAL},
+ State = #state{grid=Grid, timer=Timer0}) ->
+ Timer = observer_lib:interval_dialog(Grid, Timer0, 10, 5*60),
+ {noreply, State#state{timer=Timer}};
+
+handle_event(_Event, State) ->
+ %io:format("~p:~p, handle event ~p\n", [?MODULE, ?LINE, Event]),
+ {noreply, State}.
+
+handle_sync_event(_Event, _Obj, _State) ->
+ %io:format("~p:~p, handle sync_event ~p\n", [?MODULE, ?LINE, Event]),
+ ok.
+
+handle_call(_Event, _From, State) ->
+ %io:format("~p:~p, handle call (~p) ~p\n", [?MODULE, ?LINE, From, Event]),
+ {noreply, State}.
+
+handle_cast(_Event, State) ->
+ %io:format("~p:~p, handle cast ~p\n", [?MODULE, ?LINE, Event]),
+ {noreply, State}.
+
+handle_info({no_rows, N}, State = #state{grid=Grid, status=StatusBar}) ->
+ wxListCtrl:setItemCount(Grid, N),
+ wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w",[N])),
+ {noreply, State};
+
+handle_info({new_cols, New}, State = #state{grid=Grid, columns=Cols0}) ->
+ Cols = add_columns(Grid, Cols0, New),
+ {noreply, State#state{columns=Cols}};
+
+handle_info({refresh, Min, Max}, State = #state{grid=Grid}) ->
+ wxListCtrl:refreshItems(Grid, Min, Max),
+ {noreply, State};
+
+handle_info(refresh_interval, State = #state{pid=Pid}) ->
+ Pid ! refresh,
+ {noreply, State};
+
+handle_info({error, Error}, State = #state{frame=Frame}) ->
+ ErrorStr =
+ try io_lib:format("~ts", [Error]), Error
+ catch _:_ -> io_lib:format("~p", [Error])
+ end,
+ Dlg = wxMessageDialog:new(Frame, ErrorStr),
+ wxMessageDialog:showModal(Dlg),
+ wxMessageDialog:destroy(Dlg),
+ {noreply, State};
+
+handle_info(_Event, State) ->
+ %% io:format("~p:~p, handle info ~p\n", [?MODULE, ?LINE, _Event]),
+ {noreply, State}.
+
+terminate(_Event, #state{pid=Pid, attrs=Attrs}) ->
+ %% ListItemAttr are not auto deleted
+ #attrs{odd=Odd, deleted=D, changed=Ch, searched=S} = Attrs,
+ wxListItemAttr:destroy(Odd),
+ wxListItemAttr:destroy(D),
+ wxListItemAttr:destroy(Ch),
+ wxListItemAttr:destroy(S),
+ unlink(Pid),
+ exit(Pid, window_closed),
+ ok.
+
+code_change(_, _, State) ->
+ State.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Table holder needs to be in a separate process otherwise
+%% the callback get_row/3 may deadlock if the process do
+%% wx calls when callback is invoked.
+get_row(Table, Item, Column) ->
+ Ref = erlang:monitor(process, Table),
+ Table ! {get_row, self(), Item, Column},
+ receive
+ {'DOWN', Ref, _, _, _} -> "";
+ {Table, Res} ->
+ erlang:demonitor(Ref),
+ Res
+ end.
+
+get_attr(Table, Item) ->
+ Ref = erlang:monitor(process, Table),
+ Table ! {get_attr, self(), Item},
+ receive
+ {'DOWN', Ref, _, _, _} -> wx:null();
+ {Table, Res} ->
+ erlang:demonitor(Ref),
+ Res
+ end.
+
+search(Table, Str, Row, Dir, Case) ->
+ Ref = erlang:monitor(process, Table),
+ Table ! {search, [Str, Row, Dir, Case]},
+ receive
+ {'DOWN', Ref, _, _, _} -> "";
+ {Table, Res} ->
+ erlang:demonitor(Ref),
+ Res
+ end.
+
+-record(holder, {node, parent, pid,
+ table=[], n=0, columns,
+ temp=[],
+ search,
+ source, tabid,
+ sort,
+ key,
+ type,
+ attrs
+ }).
+
+init_table_holder(Parent, Table, MnesiaOrEts, Cols, Node, Attrs) ->
+ TabId = case Table#tab.id of
+ ignore -> Table#tab.name;
+ Id -> Id
+ end,
+ self() ! refresh,
+ table_holder(#holder{node=Node, parent=Parent,
+ source=MnesiaOrEts, tabid=TabId, columns=Cols,
+ sort=#opt{sort_key=Table#tab.keypos, sort_incr=true},
+ type=Table#tab.type, key=Table#tab.keypos,
+ attrs=Attrs}).
+
+table_holder(S0 = #holder{parent=Parent, pid=Pid, table=Table}) ->
+ receive
+ {get_attr, From, Row} ->
+ get_attr(From, Row, S0),
+ table_holder(S0);
+ {get_row, From, Row, Col} ->
+ get_row(From, Row, Col, Table),
+ table_holder(S0);
+ {Pid, Data} ->
+ S1 = handle_new_data_chunk(Data, S0),
+ table_holder(S1);
+ {sort, Col} ->
+ table_holder(sort(Col, S0));
+ {search, Data} ->
+ table_holder(search(Data, S0));
+ {mark_search_hit, Row} ->
+ Old = S0#holder.search,
+ is_integer(Old) andalso (Parent ! {refresh, Old, Old}),
+ table_holder(S0#holder{search=Row});
+ refresh when is_pid(Pid) ->
+ %% Already getting the table...
+ %% io:format("ignoring refresh", []),
+ table_holder(S0);
+ refresh ->
+ GetTab = rpc:call(S0#holder.node, observer_backend, get_table,
+ [self(), S0#holder.tabid, S0#holder.source]),
+ table_holder(S0#holder{pid=GetTab});
+ {delete, Row} ->
+ delete_row(Row, S0),
+ table_holder(S0);
+ {edit, Row, Term} ->
+ edit_row(Row, Term, S0),
+ table_holder(S0);
+ What ->
+ io:format("Table holder got ~p~n",[What]),
+ table_holder(S0)
+ end.
+
+handle_new_data_chunk(Data, S0 = #holder{columns=Cols, parent=Parent}) ->
+ S1 = #holder{columns=NewCols} = handle_new_data_chunk2(Data, S0),
+ case NewCols =:= Cols of
+ true -> S1;
+ false ->
+ Parent ! {new_cols, lists:seq(Cols+1, NewCols)},
+ S1
+ end.
+
+handle_new_data_chunk2('$end_of_table',
+ S0 = #holder{parent=Parent, sort=Opt,
+ key=Key,
+ table=Old, temp=New}) ->
+ Table = merge(Old, New, Key),
+ N = length(Table),
+ Parent ! {no_rows, N},
+ sort(Opt#opt.sort_key, S0#holder{n=N, pid=undefine,
+ sort=Opt#opt{sort_key = undefined},
+ table=Table, temp=[]});
+handle_new_data_chunk2(Data, S0 = #holder{columns=Cols0, source=ets, temp=Tab0}) ->
+ {Tab, Cols} = parse_ets_data(Data, Cols0, Tab0),
+ S0#holder{columns=Cols, temp=Tab};
+handle_new_data_chunk2(Data, S0 = #holder{source=mnesia, temp=Tab}) ->
+ S0#holder{temp=(Data ++ Tab)}.
+
+parse_ets_data([[Rec]|Rs], C, Tab) ->
+ parse_ets_data(Rs, max(tuple_size(Rec), C), [Rec|Tab]);
+parse_ets_data([Recs|Rs], C0, Tab0) ->
+ {Tab, Cols} = parse_ets_data(Recs, C0, Tab0),
+ parse_ets_data(Rs, Cols, Tab);
+parse_ets_data([], Cols, Tab) ->
+ {Tab, Cols}.
+
+sort(Col, S=#holder{n=N, parent=Parent, sort=Opt0, table=Table0}) ->
+ {Opt, Table} = sort(Col, Opt0, Table0),
+ Parent ! {refresh, 0, N-1},
+ S#holder{sort=Opt, table=Table}.
+
+sort(Col, Opt = #opt{sort_key=Col, sort_incr=Bool}, Table) ->
+ {Opt#opt{sort_incr=not Bool}, lists:reverse(Table)};
+sort(Col, S=#opt{sort_incr=true}, Table) ->
+ {S#opt{sort_key=Col}, keysort(Col, Table)};
+sort(Col, S=#opt{sort_incr=false}, Table) ->
+ {S#opt{sort_key=Col}, lists:reverse(keysort(Col, Table))}.
+
+keysort(Col, Table) ->
+ Sort = fun([A0|_], [B0|_]) ->
+ A = try element(Col, A0) catch _:_ -> [] end,
+ B = try element(Col, B0) catch _:_ -> [] end,
+ case A == B of
+ true -> A0 =< B0;
+ false -> A < B
+ end;
+ (A0, B0) when is_tuple(A0), is_tuple(B0) ->
+ A = try element(Col, A0) catch _:_ -> [] end,
+ B = try element(Col, B0) catch _:_ -> [] end,
+ case A == B of
+ true -> A0 =< B0;
+ false -> A < B
+ end
+ end,
+ lists:sort(Sort, Table).
+
+search([Str, Row, Dir0, CaseSens],
+ S=#holder{parent=Parent, table=Table0}) ->
+ Opt = case CaseSens of
+ true -> [];
+ false -> [caseless]
+ end,
+ Dir = case Dir0 of
+ true -> 1;
+ false -> -1
+ end,
+ Res = case re:compile(Str, Opt) of
+ {ok, Re} ->
+ Table =
+ case Dir0 of
+ true ->
+ lists:nthtail(Row, Table0);
+ false ->
+ lists:reverse(lists:sublist(Table0, Row+1))
+ end,
+ search(Row, Dir, Re, Table);
+ {error, _} -> false
+ end,
+ Parent ! {self(), Res},
+ S#holder{search=Res}.
+
+search(Row, Dir, Re, [ [Term|_] |Table]) ->
+ Str = format(Term),
+ Res = re:run(Str, Re),
+ case Res of
+ nomatch -> search(Row+Dir, Dir, Re, Table);
+ {match,_} -> Row
+ end;
+search(_, _, _, []) ->
+ false.
+
+get_row(From, Row, Col, Table) ->
+ case lists:nth(Row+1, Table) of
+ [Object|_] when Col =:= all ->
+ From ! {self(), format(Object)};
+ [Object|_] when Col =:= all_multiline ->
+ From ! {self(), io_lib:format("~p", [Object])};
+ [Object|_] when tuple_size(Object) >= Col ->
+ From ! {self(), format(element(Col, Object))};
+ _ ->
+ From ! {self(), ""}
+ end.
+
+get_attr(From, Row, #holder{attrs=Attrs, search=Row}) ->
+ What = Attrs#attrs.searched,
+ From ! {self(), What};
+get_attr(From, Row, #holder{table=Table, attrs=Attrs}) ->
+ What = case lists:nth(Row+1, Table) of
+ [_|deleted] -> Attrs#attrs.deleted;
+ [_|changed] -> Attrs#attrs.changed;
+ [_|new] -> Attrs#attrs.changed;
+ _ when (Row rem 2) > 0 ->
+ Attrs#attrs.odd;
+ _ ->
+ Attrs#attrs.even
+ end,
+ From ! {self(), What}.
+
+merge([], New, _Key) ->
+ [[N] || N <- New]; %% First time
+merge(Old, New, Key) ->
+ merge2(keysort(Key, Old), keysort(Key, New), Key).
+
+merge2([[Obj|_]|Old], [Obj|New], Key) ->
+ [[Obj]|merge2(Old, New, Key)];
+merge2([[A|_]|Old], [B|New], Key)
+ when element(Key, A) == element(Key, B) ->
+ [[B|changed]|merge2(Old, New, Key)];
+merge2([[A|_]|Old], New = [B|_], Key)
+ when element(Key, A) < element(Key, B) ->
+ [[A|deleted]|merge2(Old, New, Key)];
+merge2(Old = [[A|_]|_], [B|New], Key)
+ when element(Key, A) > element(Key, B) ->
+ [[B|new]|merge2(Old, New, Key)];
+merge2([], New, _Key) ->
+ [[N|new] || N <- New];
+merge2(Old, [], _Key) ->
+ [[O|deleted] || [O|_] <- Old].
+
+
+delete_row(Row, S0 = #holder{parent=Parent}) ->
+ case delete(Row, S0) of
+ ok ->
+ self() ! refresh;
+ {error, Err} ->
+ Parent ! {error, "Could not delete object: " ++ Err}
+ end.
+
+
+delete(Row, #holder{tabid=Id, table=Table,
+ source=Source, node=Node}) ->
+ [Object|_] = lists:nth(Row+1, Table),
+ try
+ case Source of
+ ets ->
+ true = rpc:call(Node, ets, delete_object, [Id, Object]);
+ mnesia ->
+ ok = rpc:call(Node, mnesia, dirty_delete_object, [Id, Object])
+ end,
+ ok
+ catch _:_Error ->
+ {error, "node or table is not available"}
+ end.
+
+edit_row(Row, Term, S0 = #holder{parent=Parent}) ->
+ case delete(Row, S0) of
+ ok ->
+ case insert(Term, S0) of
+ ok -> self() ! refresh;
+ Err -> Parent ! {error, Err}
+ end;
+ {error, Err} ->
+ Parent ! {error, "Could not edit object: " ++ Err}
+ end.
+
+insert(Object, #holder{tabid=Id, source=Source, node=Node}) ->
+ try
+ case Source of
+ ets ->
+ true = rpc:call(Node, ets, insert, [Id, Object]);
+ mnesia ->
+ ok = rpc:call(Node, mnesia, dirty_write, [Id, Object])
+ end,
+ ok
+ catch _:_Error ->
+ {error, "node or table is not available"}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+column_names(Node, Type, Table) ->
+ case Type of
+ ets -> [1, 2];
+ mnesia ->
+ Attrs = rpc:call(Node, mnesia, table_info, [Table, attributes]),
+ is_list(Attrs) orelse throw(node_or_table_down),
+ ["Record Name"|Attrs]
+ end.
+
+table_id(#tab{id=ignore, name=Name}) -> Name;
+table_id(#tab{id=Id}) -> Id.
+
+key_pos(_, mnesia, _) -> 2;
+key_pos(Node, ets, TabId) ->
+ KeyPos = rpc:call(Node, ets, info, [TabId, keypos]),
+ is_integer(KeyPos) orelse throw(node_or_table_down),
+ KeyPos.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+format(Tuple) when is_tuple(Tuple) ->
+ [${ |format_tuple(Tuple, 1, tuple_size(Tuple))];
+format(List) when is_list(List) ->
+ format_list(List);
+format(Bin) when is_binary(Bin), byte_size(Bin) > 100 ->
+ io_lib:format("<<#Bin:~w>>", [byte_size(Bin)]);
+format(Bin) when is_binary(Bin) ->
+ try
+ true = printable_list(unicode:characters_to_list(Bin)),
+ io_lib:format("<<\"~ts\">>", [Bin])
+ catch _:_ ->
+ io_lib:format("~w", [Bin])
+ end;
+format(Float) when is_float(Float) ->
+ io_lib:format("~.3g", [Float]);
+format(Term) ->
+ io_lib:format("~w", [Term]).
+
+format_tuple(Tuple, I, Max) when I < Max ->
+ [format(element(I, Tuple)), $,|format_tuple(Tuple, I+1, Max)];
+format_tuple(Tuple, Max, Max) ->
+ [format(element(Max, Tuple)), $}];
+format_tuple(_Tuple, 1, 0) ->
+ [$}].
+
+format_list([]) -> "[]";
+format_list(List) ->
+ case printable_list(List) of
+ true -> io_lib:format("\"~ts\"", [map_printable_list(List)]);
+ false -> [$[ | make_list(List)]
+ end.
+
+make_list([Last]) ->
+ [format(Last), $]];
+make_list([Head|Tail]) ->
+ [format(Head), $,|make_list(Tail)].
+
+map_printable_list([$\n|Cs]) ->
+ [$\\, $n|map_printable_list(Cs)];
+map_printable_list([$\r|Cs]) ->
+ [$\\, $r|map_printable_list(Cs)];
+map_printable_list([$\t|Cs]) ->
+ [$\\, $t|map_printable_list(Cs)];
+map_printable_list([$\v|Cs]) ->
+ [$\\, $v|map_printable_list(Cs)];
+map_printable_list([$\b|Cs]) ->
+ [$\\, $b|map_printable_list(Cs)];
+map_printable_list([$\f|Cs]) ->
+ [$\\, $f|map_printable_list(Cs)];
+map_printable_list([$\e|Cs]) ->
+ [$\\, $e|map_printable_list(Cs)];
+map_printable_list([]) -> [];
+map_printable_list([C|Cs]) ->
+ [C|map_printable_list(Cs)].
+
+%% printable_list([Char]) -> bool()
+%% Return true if CharList is a list of printable characters, else
+%% false.
+
+printable_list([C|Cs]) when is_integer(C), C >= $ , C =< 255 ->
+ printable_list(Cs);
+printable_list([$\n|Cs]) ->
+ printable_list(Cs);
+printable_list([$\r|Cs]) ->
+ printable_list(Cs);
+printable_list([$\t|Cs]) ->
+ printable_list(Cs);
+printable_list([$\v|Cs]) ->
+ printable_list(Cs);
+printable_list([$\b|Cs]) ->
+ printable_list(Cs);
+printable_list([$\f|Cs]) ->
+ printable_list(Cs);
+printable_list([$\e|Cs]) ->
+ printable_list(Cs);
+printable_list([]) -> true;
+printable_list(_Other) -> false. %Everything else is false
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
new file mode 100644
index 0000000000..b276965f83
--- /dev/null
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -0,0 +1,353 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_tv_wx).
+
+-export([start_link/2, display_table_info/4]).
+
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_event/2, handle_sync_event/3, handle_cast/2]).
+
+-behaviour(wx_object).
+-include_lib("wx/include/wx.hrl").
+-include("observer_defs.hrl").
+-include("observer_tv.hrl").
+
+-define(GRID, 500).
+-define(ID_REFRESH, 401).
+-define(ID_REFRESH_INTERVAL, 402).
+-define(ID_ETS, 403).
+-define(ID_MNESIA, 404).
+-define(ID_UNREADABLE, 405).
+-define(ID_SYSTEM_TABLES, 406).
+-define(ID_TABLE_INFO, 407).
+
+-record(opt, {type=ets,
+ sys_hidden=true,
+ unread_hidden=true,
+ sort_key=2,
+ sort_incr=true
+ }).
+
+-record(state,
+ {
+ parent,
+ grid,
+ node=node(),
+ opt=#opt{},
+ selected,
+ tabs,
+ timer
+ }).
+
+start_link(Notebook, Parent) ->
+ wx_object:start_link(?MODULE, [Notebook, Parent], []).
+
+init([Notebook, Parent]) ->
+ Panel = wxPanel:new(Notebook),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ Style = ?wxLC_REPORT bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
+ Grid = wxListCtrl:new(Panel, [{winid, ?GRID}, {style, Style}]),
+ wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxALL},
+ {proportion, 1}, {border, 5}]),
+ wxWindow:setSizer(Panel, Sizer),
+ Li = wxListItem:new(),
+ AddListEntry = fun({Name, Align, DefSize}, Col) ->
+ wxListItem:setText(Li, Name),
+ wxListItem:setAlign(Li, Align),
+ wxListCtrl:insertColumn(Grid, Col, Li),
+ wxListCtrl:setColumnWidth(Grid, Col, DefSize),
+ Col + 1
+ end,
+ ListItems = [{"Table Name", ?wxLIST_FORMAT_LEFT, 200},
+ {"Table Id", ?wxLIST_FORMAT_RIGHT, 100},
+ {"Objects", ?wxLIST_FORMAT_RIGHT, 100},
+ {"Size (kB)", ?wxLIST_FORMAT_RIGHT, 100},
+ {"Owner Pid", ?wxLIST_FORMAT_CENTER, 150},
+ {"Owner Name", ?wxLIST_FORMAT_LEFT, 200}
+ ],
+ lists:foldl(AddListEntry, 0, ListItems),
+ wxListItem:destroy(Li),
+
+ wxListCtrl:connect(Grid, command_list_item_activated),
+ wxListCtrl:connect(Grid, command_list_item_selected),
+ wxListCtrl:connect(Grid, command_list_col_click),
+ wxListCtrl:connect(Grid, size, [{skip, true}]),
+
+ wxWindow:setFocus(Grid),
+ {Panel, #state{grid=Grid, parent=Parent, timer={false, 10}}}.
+
+handle_event(#wx{id=?ID_REFRESH},
+ State = #state{node=Node, grid=Grid, opt=Opt}) ->
+ Tables = get_tables(Node, Opt),
+ Tabs = update_grid(Grid, Opt, Tables),
+ {noreply, State#state{tabs=Tabs}};
+
+handle_event(#wx{event=#wxList{type=command_list_col_click, col=Col}},
+ State = #state{node=Node, grid=Grid,
+ opt=Opt0=#opt{sort_key=Key, sort_incr=Bool}}) ->
+ Opt = case Col+2 of
+ Key -> Opt0#opt{sort_incr=not Bool};
+ NewKey -> Opt0#opt{sort_key=NewKey}
+ end,
+ Tables = get_tables(Node, Opt),
+ Tabs = update_grid(Grid, Opt, Tables),
+ wxWindow:setFocus(Grid),
+ {noreply, State#state{opt=Opt, tabs=Tabs}};
+
+handle_event(#wx{id=Id}, State = #state{node=Node, grid=Grid, opt=Opt0})
+ when Id >= ?ID_ETS, Id =< ?ID_SYSTEM_TABLES ->
+ Opt = case Id of
+ ?ID_ETS -> Opt0#opt{type=ets};
+ ?ID_MNESIA -> Opt0#opt{type=mnesia};
+ ?ID_UNREADABLE -> Opt0#opt{unread_hidden= not Opt0#opt.unread_hidden};
+ ?ID_SYSTEM_TABLES -> Opt0#opt{sys_hidden= not Opt0#opt.sys_hidden}
+ end,
+ case get_tables2(Node, Opt) of
+ Error = {error, _} ->
+ self() ! Error,
+ {noreply, State};
+ Tables ->
+ Tabs = update_grid(Grid, Opt, Tables),
+ wxWindow:setFocus(Grid),
+ {noreply, State#state{opt=Opt, tabs=Tabs}}
+ end;
+
+handle_event(#wx{event=#wxSize{size={W,_}}}, State=#state{grid=Grid}) ->
+ observer_lib:set_listctrl_col_size(Grid, W),
+ {noreply, State};
+
+handle_event(#wx{obj=Grid, event=#wxList{type=command_list_item_activated,
+ itemIndex=Index}},
+ State=#state{grid=Grid, node=Node, opt=#opt{type=Type}, tabs=Tabs}) ->
+ Table = lists:nth(Index+1, Tabs),
+ case Table#tab.protection of
+ private ->
+ self() ! {error, "Table has 'private' protection and can not be read"};
+ _ ->
+ observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}])
+ end,
+ {noreply, State};
+
+handle_event(#wx{event=#wxList{type=command_list_item_selected, itemIndex=Index}},
+ State) ->
+ {noreply, State#state{selected=Index}};
+
+handle_event(#wx{id=?ID_TABLE_INFO},
+ State = #state{grid=Grid, node=Node, opt=#opt{type=Type}, tabs=Tabs, selected=Sel}) ->
+ case Sel of
+ undefined ->
+ {noreply, State};
+ R when is_integer(R) ->
+ Table = lists:nth(Sel+1, Tabs),
+ display_table_info(Grid, Node, Type, Table),
+ {noreply, State}
+ end;
+
+handle_event(#wx{id=?ID_REFRESH_INTERVAL},
+ State = #state{grid=Grid, timer=Timer0}) ->
+ Timer = observer_lib:interval_dialog(Grid, Timer0, 10, 5*60),
+ {noreply, State#state{timer=Timer}};
+
+handle_event(Event, _State) ->
+ error({unhandled_event, Event}).
+
+handle_sync_event(_Event, _Obj, _State) ->
+ ok.
+
+handle_call(Event, From, _State) ->
+ error({unhandled_call, Event, From}).
+
+handle_cast(Event, _State) ->
+ error({unhandled_cast, Event}).
+
+handle_info(refresh_interval, State = #state{node=Node, grid=Grid, opt=Opt}) ->
+ Tables = get_tables(Node, Opt),
+ Tabs = update_grid(Grid, Opt, Tables),
+ {noreply, State#state{tabs=Tabs}};
+
+handle_info({active, Node}, State = #state{parent=Parent, grid=Grid, opt=Opt,
+ timer=Timer0}) ->
+ Tables = get_tables(Node, Opt),
+ Tabs = update_grid(Grid, Opt, Tables),
+ wxWindow:setFocus(Grid),
+ create_menus(Parent, Opt),
+ Timer = observer_lib:start_timer(Timer0),
+ {noreply, State#state{node=Node, tabs=Tabs, timer=Timer}};
+
+handle_info(not_active, State = #state{timer = Timer0}) ->
+ Timer = observer_lib:stop_timer(Timer0),
+ {noreply, State#state{timer=Timer}};
+
+handle_info({error, Error}, State) ->
+ handle_error(Error),
+ {noreply, State};
+
+handle_info(_Event, State) ->
+ {noreply, State}.
+
+terminate(_Event, _State) ->
+ ok.
+
+code_change(_, _, State) ->
+ State.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_menus(Parent, #opt{sys_hidden=Sys, unread_hidden=UnR, type=Type}) ->
+ MenuEntries = [{"View",
+ [#create_menu{id = ?ID_TABLE_INFO, text = "Table information\tCtrl-I"},
+ separator,
+ #create_menu{id = ?ID_ETS, text = "&Ets Tables",
+ type=radio, check=Type==ets},
+ #create_menu{id = ?ID_MNESIA, text = "&Mnesia Tables",
+ type=radio, check=Type==mnesia},
+ separator,
+ #create_menu{id = ?ID_UNREADABLE, text = "View &Unreadable Tables",
+ type=check, check=not UnR},
+ #create_menu{id = ?ID_SYSTEM_TABLES, text = "View &System Tables",
+ type=check, check=not Sys},
+ separator,
+ #create_menu{id = ?ID_REFRESH, text = "Refresh\tCtrl-R"},
+ #create_menu{id = ?ID_REFRESH_INTERVAL, text = "Refresh Interval..."}
+ ]}],
+ observer_wx:create_menus(Parent, MenuEntries).
+
+get_tables(Node, Opts) ->
+ case get_tables2(Node, Opts) of
+ Error = {error, _} ->
+ self() ! Error,
+ [];
+ Res ->
+ Res
+ end.
+get_tables2(Node, #opt{type=Type, sys_hidden=Sys, unread_hidden=Unread}) ->
+ Args = [Type, [{sys_hidden,Sys}, {unread_hidden,Unread}]],
+ case rpc:call(Node, observer_backend, get_table_list, Args) of
+ {badrpc, Error} ->
+ {error, Error};
+ Error = {error, _} ->
+ Error;
+ Result ->
+ [list_to_tabrec(Tab) || Tab <- Result]
+ end.
+
+list_to_tabrec(PL) ->
+ #tab{name = proplists:get_value(name, PL),
+ id = proplists:get_value(id, PL, ignore),
+ size = proplists:get_value(size, PL, 0),
+ memory= proplists:get_value(memory, PL, 0), %% In bytes
+ owner=proplists:get_value(owner, PL),
+ reg_name=proplists:get_value(reg_name, PL),
+ protection = proplists:get_value(protection, PL, public),
+ type=proplists:get_value(type, PL, set),
+ keypos=proplists:get_value(keypos, PL, 1),
+ heir=proplists:get_value(heir, PL, none),
+ compressed=proplists:get_value(compressed, PL, false),
+ fixed=proplists:get_value(fixed, PL, false),
+ %% Mnesia Info
+ storage =proplists:get_value(storage, PL),
+ index = proplists:get_value(index, PL)}.
+
+display_table_info(Parent0, Node, Source, Table) ->
+ Parent = observer_lib:get_wx_parent(Parent0),
+ Title = "Table Info: " ++ atom_to_list(Table#tab.name),
+ Frame = wxMiniFrame:new(Parent, ?wxID_ANY, Title,
+ [{style, ?wxSYSTEM_MENU bor ?wxCAPTION
+ bor ?wxCLOSE_BOX bor ?wxRESIZE_BORDER}]),
+
+ IdInfo = {"Identification and Owner",
+ [{"Name", Table#tab.name},
+ {"Id", case Table#tab.id of
+ ignore -> Table#tab.name;
+ Id -> Id
+ end},
+ {"Named table", Table#tab.id == ignore},
+ {"Owner", Table#tab.owner},
+ {"Owner Name", case Table#tab.reg_name of
+ ignore -> "-";
+ Id -> Id
+ end},
+ {"Heir", Table#tab.heir},
+ {"Node", Node}]},
+ MnesiaSettings = case Source of
+ ets -> [];
+ mnesia ->
+ [{"Local storage type", case Table#tab.storage of
+ unknown -> "Not available";
+ ST -> ST
+ end},
+ {"Index positions", list_to_strings(Table#tab.index)}]
+ end,
+ Settings = {"Settings",
+ [{"Source", Source},
+ {"Key Position", Table#tab.keypos},
+ {"Table Type", Table#tab.type},
+ {"Protection Mode", Table#tab.protection},
+ {"Fixed", Table#tab.fixed}
+ | MnesiaSettings ]},
+ Memory = {"Memory Usage",
+ [{"Number of objects", Table#tab.size},
+ {"Memory allocated", {bytes, Table#tab.memory}},
+ {"Compressed", Table#tab.compressed}]},
+
+ {_, Sizer, _} = observer_lib:display_info(Frame, [IdInfo,Settings,Memory]),
+ wxSizer:setSizeHints(Sizer, Frame),
+ wxFrame:center(Frame),
+ wxFrame:show(Frame).
+
+list_to_strings([]) -> "None";
+list_to_strings([A]) -> integer_to_list(A);
+list_to_strings([A|B]) ->
+ integer_to_list(A) ++ " ," ++ list_to_strings(B).
+
+handle_error(Foo) ->
+ Str = io_lib:format("ERROR: ~s~n",[Foo]),
+ observer_lib:display_info_dialog(Str).
+
+update_grid(Grid, Opt, Tables) ->
+ wx:batch(fun() -> update_grid2(Grid, Opt, Tables) end).
+update_grid2(Grid, #opt{sort_key=Sort,sort_incr=Dir}, Tables) ->
+ wxListCtrl:deleteAllItems(Grid),
+ Update =
+ fun(#tab{name = Name, id = Id, owner = Owner, size = Size, memory = Memory,
+ protection = Protection, reg_name = RegName}, Row) ->
+ _Item = wxListCtrl:insertItem(Grid, Row, ""),
+ if (Row rem 2) =:= 0 ->
+ wxListCtrl:setItemBackgroundColour(Grid, Row, ?BG_EVEN);
+ true -> ignore
+ end,
+ if Protection == private ->
+ wxListCtrl:setItemTextColour(Grid, Row, {200,130,50});
+ true -> ignore
+ end,
+
+ lists:foreach(fun({_, ignore}) -> ignore;
+ ({Col, Val}) ->
+ wxListCtrl:setItem(Grid, Row, Col, observer_lib:to_str(Val))
+ end,
+ [{0,Name}, {1,Id}, {2,Size}, {3, Memory div 1024},
+ {4,Owner}, {5,RegName}]),
+ Row + 1
+ end,
+ ProcInfo = case Dir of
+ false -> lists:reverse(lists:keysort(Sort, Tables));
+ true -> lists:keysort(Sort, Tables)
+ end,
+ lists:foldl(Update, 0, ProcInfo),
+ ProcInfo.
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
new file mode 100644
index 0000000000..e433bea8c2
--- /dev/null
+++ b/lib/observer/src/observer_wx.erl
@@ -0,0 +1,614 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(observer_wx).
+
+-behaviour(wx_object).
+
+-export([start/0]).
+-export([create_menus/2, get_attrib/1, get_tracer/0, set_status/1,
+ create_txt_dialog/4, try_rpc/4, return_to_localnode/2]).
+
+-export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3,
+ handle_call/3, handle_info/2, check_page_title/1]).
+
+%% Includes
+-include_lib("wx/include/wx.hrl").
+
+-include("observer_defs.hrl").
+
+%% Defines
+
+-define(ID_PING, 1).
+-define(ID_CONNECT, 2).
+-define(ID_NOTEBOOK, 3).
+
+-define(FIRST_NODES_MENU_ID, 1000).
+-define(LAST_NODES_MENU_ID, 2000).
+
+-define(TRACE_STR, "Trace Overview").
+
+%% Records
+-record(state,
+ {frame,
+ menubar,
+ menus = [],
+ status_bar,
+ notebook,
+ main_panel,
+ pro_panel,
+ tv_panel,
+ sys_panel,
+ trace_panel,
+ app_panel,
+ perf_panel,
+ active_tab,
+ node,
+ nodes,
+ prev_node=""
+ }).
+
+start() ->
+ case wx_object:start(?MODULE, [], []) of
+ Err = {error, _} -> Err;
+ _Obj -> ok
+ end.
+
+create_menus(Object, Menus) when is_list(Menus) ->
+ wx_object:call(Object, {create_menus, Menus}).
+
+get_attrib(What) ->
+ wx_object:call(observer, {get_attrib, What}).
+
+set_status(What) ->
+ wx_object:cast(observer, {status_bar, What}).
+
+get_tracer() ->
+ wx_object:call(observer, get_tracer).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init(_Args) ->
+ register(observer, self()),
+ wx:new(),
+ catch wxSystemOptions:setOption("mac.listctrl.always_use_generic", 1),
+ Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Observer",
+ [{size, {850, 600}}, {style, ?wxDEFAULT_FRAME_STYLE}]),
+ IconFile = filename:join(code:priv_dir(observer), "erlang_observer.png"),
+ Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
+ wxFrame:setIcon(Frame, Icon),
+ wxIcon:destroy(Icon),
+
+ State = #state{frame = Frame},
+ UpdState = setup(State),
+ net_kernel:monitor_nodes(true),
+ process_flag(trap_exit, true),
+ {Frame, UpdState}.
+
+setup(#state{frame = Frame} = State) ->
+ %% Setup Menubar & Menus
+ MenuBar = wxMenuBar:new(),
+
+ {Nodes, NodeMenus} = get_nodes(),
+ DefMenus = default_menus(NodeMenus),
+ observer_lib:create_menus(DefMenus, MenuBar, default),
+
+ wxFrame:setMenuBar(Frame, MenuBar),
+ StatusBar = wxFrame:createStatusBar(Frame, []),
+ wxFrame:setTitle(Frame, atom_to_list(node())),
+ wxStatusBar:setStatusText(StatusBar, atom_to_list(node())),
+
+ %% Setup panels
+ Panel = wxPanel:new(Frame, []),
+ Notebook = wxNotebook:new(Panel, ?ID_NOTEBOOK, [{style, ?wxBK_DEFAULT}]),
+
+ %% System Panel
+ SysPanel = observer_sys_wx:start_link(Notebook, self()),
+ wxNotebook:addPage(Notebook, SysPanel, "System", []),
+
+ %% Setup sizer create early to get it when window shows
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+
+ wxSizer:add(MainSizer, Notebook, [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxPanel:setSizer(Panel, MainSizer),
+
+ wxNotebook:connect(Notebook, command_notebook_page_changing),
+ wxFrame:connect(Frame, close_window, [{skip, true}]),
+ wxMenu:connect(Frame, command_menu_selected),
+ wxFrame:show(Frame),
+
+ %% I postpone the creation of the other tabs so they can query/use
+ %% the window size
+
+ %% Perf Viewer Panel
+ PerfPanel = observer_perf_wx:start_link(Notebook, self()),
+ wxNotebook:addPage(Notebook, PerfPanel, "Load Charts", []),
+
+ %% App Viewer Panel
+ AppPanel = observer_app_wx:start_link(Notebook, self()),
+ wxNotebook:addPage(Notebook, AppPanel, "Applications", []),
+
+ %% Process Panel
+ ProPanel = observer_pro_wx:start_link(Notebook, self()),
+ wxNotebook:addPage(Notebook, ProPanel, "Processes", []),
+
+ %% Table Viewer Panel
+ TVPanel = observer_tv_wx:start_link(Notebook, self()),
+ wxNotebook:addPage(Notebook, TVPanel, "Table Viewer", []),
+
+ %% Trace Viewer Panel
+ TracePanel = observer_trace_wx:start_link(Notebook, self()),
+ wxNotebook:addPage(Notebook, TracePanel, ?TRACE_STR, []),
+
+
+ %% Force redraw (window needs it)
+ wxWindow:refresh(Panel),
+
+ SysPid = wx_object:get_pid(SysPanel),
+ SysPid ! {active, node()},
+ UpdState = State#state{main_panel = Panel,
+ notebook = Notebook,
+ menubar = MenuBar,
+ status_bar = StatusBar,
+ sys_panel = SysPanel,
+ pro_panel = ProPanel,
+ tv_panel = TVPanel,
+ trace_panel = TracePanel,
+ app_panel = AppPanel,
+ perf_panel = PerfPanel,
+ active_tab = SysPid,
+ node = node(),
+ nodes = Nodes
+ },
+ %% Create resources which we don't want to duplicate
+ SysFont = wxSystemSettings:getFont(?wxSYS_SYSTEM_FIXED_FONT),
+ %% OemFont = wxSystemSettings:getFont(?wxSYS_OEM_FIXED_FONT),
+ %% io:format("Sz sys ~p(~p) oem ~p(~p)~n",
+ %% [wxFont:getPointSize(SysFont), wxFont:isFixedWidth(SysFont),
+ %% wxFont:getPointSize(OemFont), wxFont:isFixedWidth(OemFont)]),
+ Fixed = case wxFont:isFixedWidth(SysFont) of
+ true -> SysFont;
+ false -> %% Sigh
+ SysFontSize = wxFont:getPointSize(SysFont),
+ wxFont:new(SysFontSize, ?wxFONTFAMILY_MODERN, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL)
+ end,
+ put({font, fixed}, Fixed),
+ UpdState.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%Callbacks
+handle_event(#wx{event=#wxNotebook{type=command_notebook_page_changing}},
+ #state{active_tab=Previous, node=Node} = State) ->
+ case get_active_pid(State) of
+ Previous -> {noreply, State};
+ Pid ->
+ Previous ! not_active,
+ Pid ! {active, Node},
+ {noreply, State#state{active_tab=Pid}}
+ end;
+
+handle_event(#wx{event = #wxClose{}}, State) ->
+ {stop, normal, State};
+
+handle_event(#wx{id = ?wxID_EXIT, event = #wxCommand{type = command_menu_selected}}, State) ->
+ {stop, normal, State};
+
+handle_event(#wx{id = ?wxID_HELP, event = #wxCommand{type = command_menu_selected}}, State) ->
+ External = "http://www.erlang.org/doc/apps/observer/index.html",
+ Internal = filename:join([code:lib_dir(observer),"doc", "html", "index.html"]),
+ Help = case filelib:is_file(Internal) of
+ true -> Internal;
+ false -> External
+ end,
+ wx_misc:launchDefaultBrowser(Help) orelse
+ create_txt_dialog(State#state.frame, "Could not launch browser: ~n " ++ Help,
+ "Error", ?wxICON_ERROR),
+ {noreply, State};
+
+handle_event(#wx{id = ?wxID_ABOUT, event = #wxCommand{type = command_menu_selected}},
+ State = #state{frame=Frame}) ->
+ AboutString = "Observe an erlang system\n"
+ "Authors: Olle Mattson & Magnus Eriksson & Dan Gudmundsson",
+ Style = [{style, ?wxOK bor ?wxSTAY_ON_TOP},
+ {caption, "About"}],
+ wxMessageDialog:showModal(wxMessageDialog:new(Frame, AboutString, Style)),
+ {noreply, State};
+
+
+handle_event(#wx{id = ?ID_CONNECT, event = #wxCommand{type = command_menu_selected}},
+ #state{frame = Frame} = State) ->
+ UpdState = case create_connect_dialog(connect, State) of
+ cancel ->
+ State;
+ {value, [], _, _} ->
+ create_txt_dialog(Frame, "Node must have a name",
+ "Error", ?wxICON_ERROR),
+ State;
+ {value, NodeName, LongOrShort, Cookie} -> %Shortname,
+ try
+ case connect(list_to_atom(NodeName), LongOrShort, list_to_atom(Cookie)) of
+ {ok, set_cookie} ->
+ change_node_view(node(), State);
+ {error, set_cookie} ->
+ create_txt_dialog(Frame, "Could not set cookie",
+ "Error", ?wxICON_ERROR),
+ State;
+ {error, net_kernel, _Reason} ->
+ create_txt_dialog(Frame, "Could not enable node",
+ "Error", ?wxICON_ERROR),
+ State
+ end
+ catch _:_ ->
+ create_txt_dialog(Frame, "Could not enable node",
+ "Error", ?wxICON_ERROR),
+ State
+ end
+ end,
+ {noreply, UpdState};
+
+handle_event(#wx{id = ?ID_PING, event = #wxCommand{type = command_menu_selected}},
+ #state{frame = Frame} = State) ->
+ UpdState = case create_connect_dialog(ping, State) of
+ cancel -> State;
+ {value, Value} when is_list(Value) ->
+ try
+ Node = list_to_atom(Value),
+ case net_adm:ping(Node) of
+ pang ->
+ create_txt_dialog(Frame, "Connect failed", "Pang", ?wxICON_EXCLAMATION),
+ State#state{prev_node=Value};
+ pong ->
+ State1 = change_node_view(Node, State),
+ State1#state{prev_node=Value}
+ end
+ catch _:_ ->
+ create_txt_dialog(Frame, "Connect failed", "Pang", ?wxICON_EXCLAMATION),
+ State#state{prev_node=Value}
+ end
+ end,
+ {noreply, UpdState};
+
+handle_event(#wx{id = Id, event = #wxCommand{type = command_menu_selected}}, State)
+ when Id > ?FIRST_NODES_MENU_ID, Id < ?LAST_NODES_MENU_ID ->
+
+ Node = lists:nth(Id - ?FIRST_NODES_MENU_ID, State#state.nodes),
+ UpdState = change_node_view(Node, State),
+ {noreply, UpdState};
+
+handle_event(Event, State) ->
+ Pid = get_active_pid(State),
+ Pid ! Event,
+ {noreply, State}.
+
+handle_cast({status_bar, Msg}, State=#state{status_bar=SB}) ->
+ wxStatusBar:setStatusText(SB, Msg),
+ {noreply, State};
+
+handle_cast(_Cast, State) ->
+ {noreply, State}.
+
+handle_call({create_menus, TabMenus}, _From,
+ State = #state{menubar=MenuBar, menus=PrevTabMenus}) ->
+ if TabMenus == PrevTabMenus -> ignore;
+ true ->
+ wx:batch(fun() ->
+ clean_menus(PrevTabMenus, MenuBar),
+ observer_lib:create_menus(TabMenus, MenuBar, plugin)
+ end)
+ end,
+ {reply, ok, State#state{menus=TabMenus}};
+
+handle_call({get_attrib, Attrib}, _From, State) ->
+ {reply, get(Attrib), State};
+
+handle_call(get_tracer, _From, State=#state{trace_panel=TraceP}) ->
+ {reply, TraceP, State};
+
+handle_call(_Msg, _From, State) ->
+ {reply, ok, State}.
+
+handle_info({nodeup, _Node}, State) ->
+ State2 = update_node_list(State),
+ {noreply, State2};
+
+handle_info({nodedown, Node},
+ #state{frame = Frame} = State) ->
+ State2 = case Node =:= State#state.node of
+ true ->
+ change_node_view(node(), State);
+ false ->
+ State
+ end,
+ State3 = update_node_list(State2),
+ Msg = ["Node down: " | atom_to_list(Node)],
+ create_txt_dialog(Frame, Msg, "Node down", ?wxICON_EXCLAMATION),
+ {noreply, State3};
+
+handle_info({'EXIT', Pid, _Reason}, State) ->
+ io:format("Child (~s) crashed exiting: ~p ~p~n",
+ [pid2panel(Pid, State), Pid,_Reason]),
+ {stop, normal, State};
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, #state{frame = Frame}) ->
+ wxFrame:destroy(Frame),
+ ok.
+
+code_change(_, _, State) ->
+ {ok, State}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+try_rpc(Node, Mod, Func, Args) ->
+ case
+ rpc:call(Node, Mod, Func, Args) of
+ {badrpc, Reason} ->
+ error_logger:error_report([{node, Node},
+ {call, {Mod, Func, Args}},
+ {reason, {badrpc, Reason}}]),
+ observer ! {nodedown, Node},
+ error({badrpc, Reason});
+ Res ->
+ Res
+ end.
+
+return_to_localnode(Frame, Node) ->
+ case node() =/= Node of
+ true ->
+ create_txt_dialog(Frame, "Error occured on remote node",
+ "Error", ?wxICON_ERROR),
+ disconnect_node(Node);
+ false ->
+ ok
+ end.
+
+create_txt_dialog(Frame, Msg, Title, Style) ->
+ MD = wxMessageDialog:new(Frame, Msg, [{style, Style}]),
+ wxMessageDialog:setTitle(MD, Title),
+ wxDialog:showModal(MD),
+ wxDialog:destroy(MD).
+
+connect(NodeName, 0, Cookie) ->
+ connect2(NodeName, shortnames, Cookie);
+connect(NodeName, 1, Cookie) ->
+ connect2(NodeName, longnames, Cookie).
+
+connect2(NodeName, Opts, Cookie) ->
+ case net_adm:names() of
+ {ok, _} -> %% Epmd is running
+ ok;
+ {error, address} ->
+ Epmd = os:find_executable("epmd"),
+ os:cmd(Epmd)
+ end,
+ case net_kernel:start([NodeName, Opts]) of
+ {ok, _} ->
+ case is_alive() of
+ true ->
+ erlang:set_cookie(node(), Cookie),
+ {ok, set_cookie};
+ false ->
+ {error, set_cookie}
+ end;
+ {error, Reason} ->
+ {error, net_kernel, Reason}
+ end.
+
+change_node_view(Node, State) ->
+ Tab = get_active_pid(State),
+ Tab ! not_active,
+ Tab ! {active, Node},
+ StatusText = ["Observer - " | atom_to_list(Node)],
+ wxFrame:setTitle(State#state.frame, StatusText),
+ wxStatusBar:setStatusText(State#state.status_bar, StatusText),
+ State#state{node = Node}.
+
+check_page_title(Notebook) ->
+ Selection = wxNotebook:getSelection(Notebook),
+ wxNotebook:getPageText(Notebook, Selection).
+
+get_active_pid(#state{notebook=Notebook, pro_panel=Pro, sys_panel=Sys,
+ tv_panel=Tv, trace_panel=Trace, app_panel=App,
+ perf_panel=Perf
+ }) ->
+ Panel = case check_page_title(Notebook) of
+ "Processes" -> Pro;
+ "System" -> Sys;
+ "Table Viewer" -> Tv;
+ ?TRACE_STR -> Trace;
+ "Load Charts" -> Perf;
+ "Applications" -> App
+ end,
+ wx_object:get_pid(Panel).
+
+pid2panel(Pid, #state{pro_panel=Pro, sys_panel=Sys,
+ tv_panel=Tv, trace_panel=Trace, app_panel=App,
+ perf_panel=Perf}) ->
+ case Pid of
+ Pro -> "Processes";
+ Sys -> "System";
+ Tv -> "Table Viewer" ;
+ Trace -> ?TRACE_STR;
+ Perf -> "Load Charts";
+ App -> "Applications";
+ _ -> "unknown"
+ end.
+
+
+create_connect_dialog(ping, #state{frame = Frame, prev_node=Prev}) ->
+ Dialog = wxTextEntryDialog:new(Frame, "Connect to node", [{value, Prev}]),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Value = wxTextEntryDialog:getValue(Dialog),
+ wxDialog:destroy(Dialog),
+ {value, Value};
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ cancel
+ end;
+create_connect_dialog(connect, #state{frame = Frame}) ->
+ Dialog = wxDialog:new(Frame, ?wxID_ANY, "Distribute node "),
+
+ VSizer = wxBoxSizer:new(?wxVERTICAL),
+ RadioBoxSizer = wxBoxSizer:new(?wxHORIZONTAL),
+
+ Choices = ["Short name", "Long name"],
+ RadioBox = wxRadioBox:new(Dialog, 1, "",
+ ?wxDefaultPosition,
+ ?wxDefaultSize,
+ Choices,
+ [{majorDim, 2},
+ {style, ?wxHORIZONTAL}]),
+
+ NameText = wxStaticText:new(Dialog, ?wxID_ANY, "Node name: "),
+ NameCtrl = wxTextCtrl:new(Dialog, ?wxID_ANY, [{size, {200, 25}}]),
+ wxTextCtrl:setValue(NameCtrl, "observer"),
+ CookieText = wxStaticText:new(Dialog, ?wxID_ANY, "Secret cookie: "),
+ CookieCtrl = wxTextCtrl:new(Dialog, ?wxID_ANY,
+ [{size, {200, 25}}, {style, ?wxTE_PASSWORD}]),
+
+ BtnSizer = wxDialog:createStdDialogButtonSizer(Dialog, ?wxID_DEFAULT),
+ Flags = [{flag, ?wxEXPAND bor ?wxALL}, {border, 5}],
+ wxSizer:add(RadioBoxSizer, RadioBox, Flags),
+
+ wxSizer:add(VSizer, RadioBoxSizer, Flags),
+ wxSizer:addSpacer(VSizer, 10),
+ wxSizer:add(VSizer, NameText),
+ wxSizer:add(VSizer, NameCtrl, Flags),
+ wxSizer:addSpacer(VSizer, 10),
+ wxSizer:add(VSizer, CookieText),
+ wxSizer:add(VSizer, CookieCtrl, Flags),
+ wxSizer:addSpacer(VSizer, 10),
+ wxSizer:add(VSizer, BtnSizer, [{flag, ?wxALIGN_LEFT}]),
+
+ wxWindow:setSizer(Dialog, VSizer),
+ CookiePath = filename:join(os:getenv("HOME"), ".erlang.cookie"),
+ DefaultCookie = case filelib:is_file(CookiePath) of
+ true ->
+ {ok, Bin} = file:read_file(CookiePath),
+ binary_to_list(Bin);
+ false ->
+ ""
+ end,
+ wxTextCtrl:setValue(CookieCtrl, DefaultCookie),
+ case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ NameValue = wxTextCtrl:getValue(NameCtrl),
+ NameLngthValue = wxRadioBox:getSelection(RadioBox),
+ CookieValue = wxTextCtrl:getValue(CookieCtrl),
+ wxDialog:destroy(Dialog),
+ {value, NameValue, NameLngthValue, CookieValue};
+ ?wxID_CANCEL ->
+ wxDialog:destroy(Dialog),
+ cancel
+ end.
+
+default_menus(NodesMenuItems) ->
+ Quit = #create_menu{id = ?wxID_EXIT, text = "Quit"},
+ About = #create_menu{id = ?wxID_ABOUT, text = "About"},
+ Help = #create_menu{id = ?wxID_HELP},
+ NodeMenu = case erlang:is_alive() of
+ true -> {"Nodes", NodesMenuItems ++
+ [#create_menu{id = ?ID_PING, text = "Connect Node"}]};
+ false -> {"Nodes", NodesMenuItems ++
+ [#create_menu{id = ?ID_CONNECT, text = "Enable distribution"}]}
+ end,
+ case os:type() =:= {unix, darwin} of
+ false ->
+ FileMenu = {"File", [Quit]},
+ HelpMenu = {"Help", [About,Help]},
+ [FileMenu, NodeMenu, HelpMenu];
+ true ->
+ %% On Mac quit and about will be moved to the "default' place
+ %% automagicly, so just add them to a menu that always exist.
+ %% But not to the help menu for some reason
+ {Tag, Menus} = NodeMenu,
+ [{Tag, Menus ++ [Quit,About]}, {"&Help", [Help]}]
+ end.
+
+clean_menus(Menus, MenuBar) ->
+ remove_menu_items(Menus, MenuBar).
+
+remove_menu_items([{MenuStr = "File", Menus}|Rest], MenuBar) ->
+ MenuId = wxMenuBar:findMenu(MenuBar, MenuStr),
+ Menu = wxMenuBar:getMenu(MenuBar, MenuId),
+ Items = [wxMenu:findItem(Menu, Tag) || #create_menu{text=Tag} <- Menus],
+ [wxMenu:delete(Menu, MItem) || MItem <- Items],
+ case os:type() =:= {unix, darwin} of
+ true ->
+ wxMenuBar:remove(MenuBar, MenuId),
+ wxMenu:destroy(Menu);
+ false ->
+ ignore
+ end,
+ remove_menu_items(Rest, MenuBar);
+remove_menu_items([{"Nodes", _}|_], _MB) ->
+ ok;
+remove_menu_items([{Tag, _Menus}|Rest], MenuBar) ->
+ MenuId = wxMenuBar:findMenu(MenuBar, Tag),
+ Menu = wxMenuBar:getMenu(MenuBar, MenuId),
+ wxMenuBar:remove(MenuBar, MenuId),
+ Items = wxMenu:getMenuItems(Menu),
+ [wxMenu:'Destroy'(Menu, Item) || Item <- Items],
+ wxMenu:destroy(Menu),
+ remove_menu_items(Rest, MenuBar);
+remove_menu_items([], _MB) ->
+ ok.
+
+get_nodes() ->
+ Nodes0 = case erlang:is_alive() of
+ false -> [];
+ true ->
+ case net_adm:names() of
+ {error, _} -> nodes();
+ {ok, Names} ->
+ epmd_nodes(Names) ++ nodes()
+ end
+ end,
+ Nodes = lists:usort(Nodes0),
+ {_, Menues} =
+ lists:foldl(fun(Node, {Id, Acc}) when Id < ?LAST_NODES_MENU_ID ->
+ {Id + 1, [#create_menu{id=Id + ?FIRST_NODES_MENU_ID,
+ text=atom_to_list(Node)} | Acc]}
+ end, {1, []}, Nodes),
+ {Nodes, lists:reverse(Menues)}.
+
+epmd_nodes(Names) ->
+ [_, Host] = string:tokens(atom_to_list(node()),"@"),
+ [list_to_atom(Name ++ [$@|Host]) || {Name, _} <- Names].
+
+update_node_list(State = #state{menubar=MenuBar}) ->
+ {Nodes, NodesMenuItems} = get_nodes(),
+ NodeMenuId = wxMenuBar:findMenu(MenuBar, "Nodes"),
+ NodeMenu = wxMenuBar:getMenu(MenuBar, NodeMenuId),
+ wx:foreach(fun(Item) -> wxMenu:'Destroy'(NodeMenu, Item) end,
+ wxMenu:getMenuItems(NodeMenu)),
+
+ Index = wx:foldl(fun(Record, Index) ->
+ observer_lib:create_menu_item(Record, NodeMenu, Index)
+ end, 0, NodesMenuItems),
+
+ Dist = case erlang:is_alive() of
+ true -> #create_menu{id = ?ID_PING, text = "Connect node"};
+ false -> #create_menu{id = ?ID_CONNECT, text = "Enable distribution"}
+ end,
+ observer_lib:create_menu_item(Dist, NodeMenu, Index),
+ State#state{nodes = Nodes}.
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index 072aa165e7..61fd6d1787 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.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
@@ -75,29 +75,41 @@ 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} =
+ Shell = proplists:get_value(shell, Traci, false),
+ DefShell = fun(Trace) -> dbg:dhandler(Trace, standard_io) end,
+ {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),"@"),
+ fun({N,{local,File},TF},{CS,S}) ->
+ {TF2, FileInfo, ShellOutput} =
+ case Shell of
+ only -> {none, shell_only, DefShell};
+ true -> {TF, {file,File}, DefShell};
+ {only,Fun} -> {none, shell_only, Fun};
+ Fun when is_function(Fun) -> {TF, {file,File}, Fun};
+ _ -> {TF, {file,File}, false}
+ end,
+ Host = case N of
+ nonode@nohost ->
+ {ok, H} = inet:gethostname(),
+ H;
+ _ ->
+ [_,H] = string:tokens(atom_to_list(N),"@"),
+ H
+ end,
case catch dbg:tracer(N,port,dbg:trace_port(ip,0)) of
{ok,N} ->
{ok,Port} = dbg:trace_port_control(N,get_listen_port),
{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}, ShellOutput}}),
+ {fun ip_to_file/2,{FileInfo, ShellOutput}}),
{[{N,{local,File,Port},TF2}|CS], [N|S]};
Other ->
display_warning(N,{cannot_open_ip_trace_port,
Host,
Other}),
{CS, S}
- end;
+ end;
({N,C,_}=Client,{CS,S}) ->
case catch dbg:tracer(N,port,dbg:trace_port(file,C)) of
{ok,N} ->
@@ -519,7 +531,7 @@ ensure_no_overloaded_nodes() ->
[];
_ ->
?MODULE ! {get_overloaded, self()},
- receive O -> O end
+ receive {overloaded,O} -> O end
end,
case Overloaded of
[] -> ok;
@@ -620,7 +632,7 @@ stop_opts(Opts) ->
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} ->
+ {false, false} ->
case lists:member(nofetch,Opts) of
false -> {fetch, FetchDir};
true -> nofetch
@@ -687,6 +699,11 @@ loop(NodeInfo, SessionInfo) ->
{MetaFile,undefined}
end,
loop(dict:store(Node,{AbsoluteMetaFile,MetaPid},NodeInfo), SessionInfo);
+ {ip_to_file_trace_port,Port,Sender} ->
+ Ports = proplists:get_value(ip_to_file_trace_ports, SessionInfo, []),
+ NewSessionInfo = [{ip_to_file_trace_ports,[Port|Ports]}|SessionInfo],
+ Sender ! {?MODULE,ok},
+ loop(NodeInfo, NewSessionInfo);
{get_nodes,Sender} ->
Sender ! {?MODULE,dict:fetch_keys(NodeInfo)},
loop(NodeInfo, SessionInfo);
@@ -715,7 +732,7 @@ loop(NodeInfo, SessionInfo) ->
lists:keydelete(overloaded, 1, SessionInfo)},
loop(NodeInfo, [{overloaded, [Node|Overloaded]} | SI]);
{get_overloaded, Pid} ->
- Pid ! proplists:get_value(overloaded, SessionInfo, []),
+ Pid ! {overloaded,proplists:get_value(overloaded, SessionInfo, [])},
loop(NodeInfo, SessionInfo);
trace_started ->
case proplists:get_value(timer, SessionInfo) of
@@ -736,7 +753,7 @@ loop(NodeInfo, SessionInfo) ->
end
end.
-do_stop(nofetch, Sender, NodeInfo, _) ->
+do_stop(nofetch, Sender, NodeInfo, SessionInfo) ->
write_config(?last_config, all),
dict:fold(
fun(Node,{_,MetaPid},_) ->
@@ -744,6 +761,7 @@ do_stop(nofetch, Sender, NodeInfo, _) ->
end,
ok,
NodeInfo),
+ stop_ip_to_file_trace_ports(SessionInfo),
dbg:stop_clear(),
ets:delete(?history_table),
Sender ! {?MODULE, stopped};
@@ -766,6 +784,7 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
end,
[],
NodeInfo),
+ stop_ip_to_file_trace_ports(SessionInfo),
dbg:stop_clear(),
AllNodes =
lists:map(
@@ -784,6 +803,19 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
end,
Sender ! {?MODULE,{stopped,Absname}}.
+stop_ip_to_file_trace_ports(SessionInfo) ->
+ lists:foreach(fun(Port) ->
+ case lists:member(Port,erlang:ports()) of
+ true ->
+ dbg:deliver_and_flush(Port),
+ erlang:port_close(Port);
+ false ->
+ ok
+ end
+ end,
+ proplists:get_value(ip_to_file_trace_ports,SessionInfo,[])).
+
+
make_node_dead(Node, NodeInfo, SessionInfo) ->
{MetaFile,_} = dict:fetch(Node, NodeInfo),
NewDeadNodes = [{Node, MetaFile} | proplists:get_value(dead_nodes, SessionInfo)],
@@ -1255,14 +1287,17 @@ 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({metadata,_,_},{_, only} = State) ->
+ip_to_file({metadata,_,_},{shell_only, _} = State) ->
State;
-ip_to_file(Trace, {_, only} = State) ->
- dbg:dhandler(Trace, standard_io),
+ip_to_file(Trace, {shell_only, Fun} = State) ->
+ Fun(Trace),
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(),
+ %% Store the port so it can be properly closed
+ ?MODULE ! {ip_to_file_trace_port, Port, self()},
+ receive {?MODULE,ok} -> ok end,
case Trace of
{metadata, _, _} -> ok;
Trace -> show_trace(Trace, ShellOutput)
@@ -1279,8 +1314,8 @@ ip_to_file(Trace,{Port, ShellOutput}) ->
erlang:port_command(Port,B),
{Port, ShellOutput}.
-show_trace(Trace, true) ->
- dbg:dhandler(Trace, standard_io);
+show_trace(Trace, Fun) when is_function(Fun) ->
+ Fun(Trace);
show_trace(_, _) ->
ok.
diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile
index bf99f07081..9df0591da5 100644
--- a/lib/observer/test/Makefile
+++ b/lib/observer/test/Makefile
@@ -82,11 +82,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) observer.spec $(EMAKEFILE) \
$(COVERFILE) $(ERL_FILES) \
- $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/observer/test/client.erl b/lib/observer/test/client.erl
index e756f9d6e8..90b72d3f8f 100644
--- a/lib/observer/test/client.erl
+++ b/lib/observer/test/client.erl
@@ -23,6 +23,6 @@ get() ->
put(Thing) ->
erlang:send({server,server_node()}, {put,self(),Thing}),
- receive ok -> ok
+ receive ok -> timer:sleep(2), ok
after 1000 -> no_reply
end.
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index d1c65f97e8..520fcdfd0d 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -19,7 +19,7 @@
-module(crashdump_helper).
-export([n1_proc/2,remote_proc/2]).
--compile(r12).
+-compile(r13).
-include("test_server.hrl").
n1_proc(N2,Creator) ->
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index fdc4a2f1ff..6f882d0be9 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,7 +70,7 @@ init_per_suite(Config) when is_list(Config) ->
application:start(inets), % will be using the http client later
httpc:set_options([{ipfamily,inet6fb4}]),
DataDir = ?config(data_dir,Config),
- Rels = [R || R <- [r12b,r13b], ?t:is_release_available(R)] ++ [current],
+ Rels = [R || R <- [r13b,r14b], ?t:is_release_available(R)] ++ [current],
io:format("Creating crash dumps for the following releases: ~p", [Rels]),
AllDumps = create_dumps(DataDir,Rels),
?t:timetrap_cancel(Dog),
@@ -318,7 +318,7 @@ browse_file(Port,File) ->
%% The page where a filename can be entered
title(Port,"read_file_frame","Read File"),
-
+
%% Load a file
Url = "http://localhost:"++Port++"/cdv_erl/crashdump_viewer/read_file",
Html = request_sync(post,{Url,[],[],"path="++File}),
@@ -414,6 +414,10 @@ special(Port,File) ->
_ ->
ok
end;
+ ".strangemodname" ->
+ AllMods = contents(Port,"loaded_modules"),
+ open_all_modules(Port,AllMods),
+ ok;
%%! No longer needed - all atoms are shown on one page!!
%% ".250atoms" ->
%% Html1 = contents(Port,"atoms"),
@@ -496,6 +500,26 @@ expand_binary_link(Html) ->
expand_binary_link(T)
end.
+open_all_modules(Port,Modules) ->
+ case get_first_module(Modules) of
+ {Module,Rest} ->
+ ModuleDetails = contents(Port,"loaded_mod_details?mod=" ++ Module),
+ ModTitle = http_uri:decode(Module),
+ ModTitle = title(ModuleDetails),
+ open_all_modules(Port,Rest);
+ false ->
+ ok
+ end.
+
+get_first_module([]) ->
+ false;
+get_first_module(Html) ->
+ case Html of
+ "<TD><A HREF=\"loaded_mod_details?mod=" ++ Rest ->
+ {string:sub_word(Rest,1,$"),Rest};
+ [_H|T] ->
+ get_first_module(T)
+ end.
%% next_link(Html) ->
%% case Html of
@@ -565,7 +589,7 @@ create_dumps(DataDir,[Rel|Rels],Acc) ->
Fun = fun() -> do_create_dumps(DataDir,Rel) end,
Pa = filename:dirname(code:which(?MODULE)),
{SlAllocDumps,Dumps,DosDump} =
- ?t:run_on_shielded_node(Fun, compat_rel(Rel) ++ "-pa " ++ Pa),
+ ?t:run_on_shielded_node(Fun, compat_rel(Rel) ++ "-pa \"" ++ Pa ++ "\""),
create_dumps(DataDir,Rels,SlAllocDumps ++ Dumps ++ Acc ++ DosDump);
create_dumps(_DataDir,[],Acc) ->
Acc.
@@ -590,7 +614,8 @@ do_create_dumps(DataDir,Rel) ->
case Rel of
current ->
CD3 = dump_with_args(DataDir,Rel,"instr","+Mim true"),
- {SlAllocDumps, [CD1,CD2,CD3], DosDump};
+ CD4 = dump_with_strange_module_name(DataDir,Rel,"strangemodname"),
+ {SlAllocDumps, [CD1,CD2,CD3,CD4], DosDump};
_ ->
{SlAllocDumps, [CD1,CD2], DosDump}
end.
@@ -600,7 +625,7 @@ do_create_dumps(DataDir,Rel) ->
%% not connected node, and with monitors and links between nodes.
full_dist_dump(DataDir,Rel) ->
Opt = rel_opt(Rel),
- Pz = "-pz " ++ filename:dirname(code:which(?MODULE)),
+ Pz = "-pz \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
PzOpt = [{args,Pz}],
{ok,N1} = ?t:start_node(n1,peer,Opt ++ PzOpt),
{ok,N2} = ?t:start_node(n2,peer,Opt ++ PzOpt),
@@ -648,7 +673,22 @@ dump_with_args(DataDir,Rel,DumpName,Args) ->
?t:stop_node(n1),
CD.
+%% This dump is added to test OTP-10090 - regarding URL encoding of
+%% module names in the module detail link.
+dump_with_strange_module_name(DataDir,Rel,DumpName) ->
+ Opt = rel_opt(Rel),
+ {ok,N1} = ?t:start_node(n1,peer,Opt),
+ Mod = '<mod ule#with?strange%name>',
+ File = atom_to_list(Mod) ++ ".erl",
+ Forms = [{attribute,1,file,{File,1}},
+ {attribute,1,module,Mod},
+ {eof,4}],
+ {ok,Mod,Bin} = rpc:call(N1,compile,forms,[Forms,[binary]]),
+ {module,Mod} = rpc:call(N1,code,load_binary,[Mod,File,Bin]),
+ CD = dump(N1,DataDir,Rel,DumpName),
+ ?t:stop_node(n1),
+ CD.
dump(Node,DataDir,Rel,DumpName) ->
rpc:call(Node,erlang,halt,[DumpName]),
@@ -711,6 +751,7 @@ rel_opt(Rel) ->
r11b -> [{erl,[{release,"r11b_patched"}]}];
r12b -> [{erl,[{release,"r12b_patched"}]}];
r13b -> [{erl,[{release,"r13b_patched"}]}];
+ r14b -> [{erl,[{release,"r14b_latest"}]}]; %naming convention changed
current -> []
end.
@@ -722,7 +763,8 @@ dump_prefix(Rel) ->
r11b -> "r11b_dump.";
r12b -> "r12b_dump.";
r13b -> "r13b_dump.";
- current -> "r14b_dump."
+ r14b -> "r14b_dump.";
+ current -> "r15b_dump."
end.
compat_rel(Rel) ->
@@ -733,5 +775,6 @@ compat_rel(Rel) ->
r11b -> "+R11 ";
r12b -> "+R12 ";
r13b -> "+R13 ";
+ r14b -> "+R14 ";
current -> ""
end.
diff --git a/lib/observer/test/etop_SUITE.erl b/lib/observer/test/etop_SUITE.erl
index a0782ea809..06577f82cc 100644
--- a/lib/observer/test/etop_SUITE.erl
+++ b/lib/observer/test/etop_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,11 +57,14 @@ end_per_group(_GroupName, Config) ->
Config.
-text(suite) ->
- [];
-text(doc) ->
- ["Start etop with text presentation"];
-text(Config) when is_list(Config) ->
+%% Start etop with text presentation
+text(_) ->
+ case test_server:is_native(lists) of
+ true -> {skip,"Native libs -- tracing does not work"};
+ false -> text()
+ end.
+
+text() ->
?line {ok,Node} = ?t:start_node(node2,peer,[]),
%% Must spawn this process, else the test case will never end.
diff --git a/lib/observer/test/server.erl b/lib/observer/test/server.erl
index c1b1fea562..f6d3542c96 100644
--- a/lib/observer/test/server.erl
+++ b/lib/observer/test/server.erl
@@ -16,8 +16,9 @@ stop() ->
loop(Data, Num) ->
receive
- {put,From,Ting} -> From ! ok,
+ {put,From,Ting} -> timer:sleep(2),
received(From,Ting),
+ From ! ok,
loop([Ting|Data], Num+1);
{get,From} -> From ! Data,
loop(Data, Num+1);
diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl
index 1fd8b4c892..695d41b48a 100644
--- a/lib/observer/test/ttb_SUITE.erl
+++ b/lib/observer/test/ttb_SUITE.erl
@@ -37,16 +37,30 @@
-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"),
+init_per_testcase(Case, Config) ->
?line Dog=test_server:timetrap(?default_timeout),
+ ttb:stop(),
+ rm(?OUTPUT),
+ [rm(Upload) || Upload<-filelib:wildcard("ttb_upload*")],
+ rm(?DIRNAME),
+ [rm(At) || At <- filelib:wildcard("*@*")],
+ rm("ttb_last_config"),
+ %% Workaround for bug(?) in test_server - if the test case fails
+ %% with a timetrap timeout, then end_per_testcase will run with
+ %% faulty group_leader - which in turn makes test_server:stop_node
+ %% hang (stop_node is called by most of the cleanup functions).
+ %% Therefore we do the cleanup before each testcase instead - this
+ %% is obviously not 100% correct, but it will at least make sure
+ %% that the nodes which are to be started in a test case at are
+ %% terminated.
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
[{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
+end_per_testcase(Case, Config) ->
+ %% try apply(?MODULE,Case,[cleanup,Config])
+ %% catch error:undef -> ok
+ %% end,
Dog=?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
@@ -81,6 +95,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ clean_priv_dir(Config),
Config.
end_per_suite(_Config) ->
@@ -102,7 +117,7 @@ file(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"file"),
?line {ok,[Node]} =
ttb:tracer(Node,[{file, File},
@@ -119,7 +134,6 @@ file(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?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")),
@@ -130,6 +144,9 @@ file(Config) when is_list(Config) ->
end_of_trace] = flush(),
ok.
+file(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
file_no_pi(suite) ->
[];
file_no_pi(doc) ->
@@ -139,7 +156,7 @@ file_no_pi(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"file"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -150,7 +167,6 @@ file_no_pi(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?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")),
@@ -163,6 +179,10 @@ file_no_pi(Config) when is_list(Config) ->
?line true = is_pid(RemoteProc),
ok.
+file_no_pi(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
file_fetch(suite) ->
[];
file_fetch(doc) ->
@@ -172,7 +192,7 @@ file_fetch(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line ThisDir = filename:join(Privdir,this),
?line ok = file:make_dir(ThisDir),
?line OtherDir = filename:join(Privdir,other),
@@ -201,7 +221,6 @@ file_fetch(Config) when is_list(Config) ->
?line [StoreString] = ?t:capture_get(),
?line UploadDir =
lists:last(string:tokens(lists:flatten(StoreString),"$ \n")),
- ?line ?t:stop_node(OtherNode),
%% check that files are no longer in original directories...
?line ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch"),
@@ -228,6 +247,10 @@ file_fetch(Config) when is_list(Config) ->
?line ok = file:set_cwd(Cwd),
ok.
+file_fetch(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
wrap(suite) ->
[];
wrap(doc) ->
@@ -237,7 +260,7 @@ wrap(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"wrap"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
@@ -251,7 +274,6 @@ wrap(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([nofetch]),
- ?line ?t:stop_node(OtherNode),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp")),
?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
@@ -280,6 +302,9 @@ wrap(Config) when is_list(Config) ->
end_of_trace] = flush(),
ok.
+wrap(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
wrap_merge(suite) ->
[];
wrap_merge(doc) ->
@@ -289,7 +314,7 @@ wrap_merge(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"wrap_merge"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
@@ -303,7 +328,6 @@ wrap_merge(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([nofetch]),
- ?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-wrap_merge.*.wrp"),
@@ -318,6 +342,9 @@ wrap_merge(Config) when is_list(Config) ->
end_of_trace] = flush(),
ok.
+wrap_merge(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
wrap_merge_fetch_format(suite) ->
[];
@@ -328,7 +355,7 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"wrap_merge_fetch_format"),
%% I'm setting priv_dir as cwd, so ttb_upload directory is created there
@@ -348,7 +375,6 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([format]),
- ?line ?t:stop_node(OtherNode),
?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
@@ -360,6 +386,8 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
?line ok = file:set_cwd(Cwd),
ok.
+wrap_merge_fetch_format(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
write_config1(suite) ->
[];
@@ -371,7 +399,7 @@ write_config1(Config) when is_list(Config) ->
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_config1"),
?line ok = ttb:write_config(File,
[{ttb,tracer,[[Node,OtherNode],
@@ -384,7 +412,6 @@ write_config1(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([nofetch]),
- ?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config1"),
@@ -410,6 +437,10 @@ write_config1(Config) when is_list(Config) ->
end,
ok.
+
+write_config1(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
write_config2(suite) ->
[];
write_config2(doc) ->
@@ -419,7 +450,7 @@ write_config2(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_config2"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -433,7 +464,6 @@ write_config2(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([nofetch]),
- ?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config2"),
@@ -459,6 +489,10 @@ write_config2(Config) when is_list(Config) ->
end,
ok.
+write_config2(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
write_config3(suite) ->
[];
write_config3(doc) ->
@@ -468,7 +502,7 @@ write_config3(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_config3"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -496,7 +530,6 @@ write_config3(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ttb:stop([nofetch]),
- ?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
@@ -522,6 +555,10 @@ write_config3(Config) when is_list(Config) ->
end,
ok.
+write_config3(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
+
history(suite) ->
[];
@@ -534,7 +571,7 @@ history(Config) when is_list(Config) ->
?line S = self(),
?line Nodes = [Node,OtherNode],
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"history"),
?line StartOpts = [{file, File},
{handler,{fun myhandler/4, S}}],
@@ -552,14 +589,15 @@ history(Config) when is_list(Config) ->
?line ok = ttb:run_history([3,4]),
?line ?MODULE:foo(),
?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_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
-
+
+history(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
write_trace_info(suite) ->
@@ -571,7 +609,7 @@ write_trace_info(Config) when is_list(Config) ->
?line {ok,OtherNode} = ?t:start_node(node2,slave,[]),
?line c:nl(?MODULE),
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"write_trace_info"),
?line {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
@@ -582,7 +620,6 @@ write_trace_info(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?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,
@@ -594,6 +631,9 @@ write_trace_info(Config) when is_list(Config) ->
ok.
+write_trace_info(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
seq_trace(suite) ->
[];
@@ -602,7 +642,7 @@ seq_trace(doc) ->
seq_trace(Config) when is_list(Config) ->
?line S = self(),
- ?line Privdir=?config(priv_dir, Config),
+ ?line Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"seq_trace"),
?line {ok,[Node]} = ttb:tracer(node(),[{file,File},
{handler,{fun myhandler/4, S}}]),
@@ -669,7 +709,7 @@ diskless(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 Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"diskless"),
?line {ok,[RemoteNode]} =
ttb:tracer([RemoteNode],[{file, {local, File}},
@@ -680,7 +720,6 @@ 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([nofetch]),
- ?line ?t:stop_node(RemoteNode),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(RemoteNode)++"-diskless")),
@@ -688,6 +727,9 @@ diskless(Config) when is_list(Config) ->
end_of_trace] = flush(),
ok.
+diskless(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
diskless_wrap(suite) ->
[];
diskless_wrap(doc) ->
@@ -696,7 +738,7 @@ 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 Privdir=priv_dir(Config),
?line File = filename:join(Privdir,"diskless"),
?line {ok,[RemoteNode]} =
ttb:tracer([RemoteNode],[{file, {local, {wrap,File,200,3}}},
@@ -707,7 +749,6 @@ diskless_wrap(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([nofetch]),
- ?line ?t:stop_node(RemoteNode),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(RemoteNode)++"-diskless.*.wrp")),
@@ -715,6 +756,9 @@ diskless_wrap(Config) when is_list(Config) ->
end_of_trace] = flush(),
ok.
+diskless_wrap(cleanup,_Config) ->
+ ?line ?t:stop_node(ttb_helper:get_node(node2)).
+
otp_4967_1(suite) ->
[];
otp_4967_1(doc) ->
@@ -733,7 +777,7 @@ otp_4967_2(doc) ->
["OTP-4967: Trace message sent to {Name, Node}"];
otp_4967_2(Config) when is_list(Config) ->
io:format("1: ~p",[now()]),
- ?line Privdir = ?config(priv_dir,Config),
+ ?line Privdir = priv_dir(Config),
io:format("2: ~p",[now()]),
?line File = filename:join(Privdir,"otp_4967"),
io:format("3: ~p",[now()]),
@@ -767,8 +811,6 @@ otp_4967_2(Config) when is_list(Config) ->
ok.
-
-
myhandler(_Fd,Trace,_,Relay) ->
Relay ! Trace,
Relay.
@@ -872,6 +914,27 @@ start_client_and_server() ->
?line ttb_helper:clear(),
{ServerNode, ClientNode}.
+stop_client_and_server() ->
+ ClientNode = ttb_helper:get_node(client),
+ ServerNode = ttb_helper:get_node(server),
+ erlang:monitor_node(ClientNode,true),
+ erlang:monitor_node(ServerNode,true),
+ ?line ?t:stop_node(ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ wait_for_client_and_server_stop(ClientNode,ServerNode).
+
+wait_for_client_and_server_stop(undefined,undefined) ->
+ ok;
+wait_for_client_and_server_stop(ClientNode,ServerNode) ->
+ receive
+ {nodedown,ClientNode} ->
+ erlang:monitor_node(ClientNode,false),
+ wait_for_client_and_server_stop(undefined,ServerNode);
+ {nodedown,ServerNode} ->
+ erlang:monitor_node(ServerNode,false),
+ wait_for_client_and_server_stop(ClientNode,undefined)
+ end.
+
begin_trace(ServerNode, ClientNode, Dest) ->
?line {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
@@ -912,10 +975,12 @@ fetch_when_no_option_given(Config) when is_list(Config) ->
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*")).
+fetch_when_no_option_given(cleanup,_Config) ->
+ ?line stop_client_and_server().
+
+
basic_ttb_run_ip_port(suite) ->
[];
basic_ttb_run_ip_port(doc) ->
@@ -924,9 +989,9 @@ 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).
+ ?line check_size(10, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode).
+basic_ttb_run_ip_port(cleanup,_Config) ->
+ ?line stop_client_and_server().
basic_ttb_run_file_port(suite) ->
[];
@@ -936,9 +1001,9 @@ 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).
+ ?line check_size(10, ?FNAME, ?OUTPUT, ServerNode, ClientNode).
+basic_ttb_run_file_port(cleanup,_Config) ->
+ ?line stop_client_and_server().
return_fetch_dir_implies_fetch(suite) ->
[];
@@ -948,9 +1013,9 @@ 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).
+ ?line {_,_} = ttb:stop([return_fetch_dir]).
+return_fetch_dir_implies_fetch(cleanup,_Config) ->
+ ?line stop_client_and_server().
logfile_name_in_fetch_dir(suite) ->
[];
@@ -960,11 +1025,11 @@ 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.
+logfile_name_in_fetch_dir(cleanup,_Config) ->
+ ?line stop_client_and_server().
upload_to_my_logdir(suite) ->
[];
@@ -975,10 +1040,10 @@ upload_to_my_logdir(Config) when is_list(Config) ->
?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_logdir(cleanup,_Config) ->
+ ?line stop_client_and_server().
upload_to_my_existing_logdir(suite) ->
[];
@@ -990,9 +1055,9 @@ upload_to_my_existing_logdir(Config) when is_list(Config) ->
?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).
+ ?line {stopped,_} = ttb:stop(return_fetch_dir).
+upload_to_my_existing_logdir(cleanup,_Config) ->
+ ?line stop_client_and_server().
fetch_with_options_not_as_list(suite) ->
[];
@@ -1003,11 +1068,11 @@ fetch_with_options_not_as_list(Config) when is_list(Config) ->
?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).
+fetch_with_options_not_as_list(cleanup,_Config) ->
+ ?line stop_client_and_server().
error_when_formatting_multiple_files_4393(suite) ->
[];
@@ -1018,11 +1083,11 @@ error_when_formatting_multiple_files_4393(Config) when is_list(Config) ->
?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 Files = [filename:join(Dir, atom_to_list(ServerNode) ++ "-" ++ ?FNAME),
+ filename:join(Dir, atom_to_list(ClientNode) ++ "-" ++ ?FNAME)],
?line ok = ttb:format(Files).
+error_when_formatting_multiple_files_4393(cleanup,_Config) ->
+ ?line stop_client_and_server().
format_on_trace_stop(suite) ->
[];
@@ -1034,10 +1099,10 @@ format_on_trace_stop(Config) when is_list(Config) ->
?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").
+format_on_trace_stop(cleanup,_Config) ->
+ ?line stop_client_and_server().
%% The following three tests are for the issue "fixes fetch fail when nodes on the same host
%% have different cwd"
@@ -1050,9 +1115,9 @@ trace_to_remote_files_on_localhost_with_different_pwd(Config) when is_list(Confi
?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_remote_files_on_localhost_with_different_pwd(cleanup,_Config) ->
+ ?line stop_client_and_server().
trace_to_local_files_on_localhost_with_different_pwd(suite) ->
[];
@@ -1063,9 +1128,9 @@ trace_to_local_files_on_localhost_with_different_pwd(Config) when is_list(Config
?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_local_files_on_localhost_with_different_pwd(cleanup,_Config) ->
+ ?line stop_client_and_server().
trace_to_remote_files_on_localhost_with_different_pwd_abs(suite) ->
[];
@@ -1078,9 +1143,9 @@ trace_to_remote_files_on_localhost_with_different_pwd_abs(Config) when is_list(C
?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_to_remote_files_on_localhost_with_different_pwd_abs(cleanup,_Config) ->
+ ?line stop_client_and_server().
%% Trace is not affected by changes of cwd on control node or remote nodes during tracing
%% (three tests)
@@ -1100,9 +1165,9 @@ changing_cwd_on_control_node(Config) when is_list(Config) ->
?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(cleanup,_Config) ->
+ ?line stop_client_and_server().
changing_cwd_on_control_node_with_local_trace(suite) ->
[];
@@ -1120,9 +1185,9 @@ changing_cwd_on_control_node_with_local_trace(Config) when is_list(Config) ->
?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(cleanup,_Config) ->
+ ?line stop_client_and_server().
changing_cwd_on_remote_node(suite) ->
[];
@@ -1138,9 +1203,9 @@ changing_cwd_on_remote_node(Config) when is_list(Config) ->
?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 true = (2*(NumMsgs + 1) == length(Ret)).
+changing_cwd_on_remote_node(cleanup,_Config) ->
+ ?line stop_client_and_server().
one_command_trace_setup(suite) ->
[];
@@ -1148,19 +1213,19 @@ 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:start_trace([ClientNode, ServerNode],
+ [{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).
+one_command_trace_setup(cleanup,_Config) ->
+ ?line stop_client_and_server().
dbg_style_fetch(suite) ->
[];
@@ -1169,12 +1234,12 @@ dbg_style_fetch(doc) ->
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 ttb:start_trace([ClientNode, ServerNode],
+ [{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("."))),
@@ -1182,15 +1247,15 @@ dbg_style_fetch(Config) when is_list(Config) ->
%%+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)],
+ ttb:start_trace([ClientNode, ServerNode],
[{server, received, '_', []},
- {client, put, 1, []},
- {client, get, '_', []}],
+ {client, put, 1, []},
+ {client, get, '_', []}],
{all, call},
[{shell, only}]),
- ?line ttb:stop(),
- ?line ?t:stop_node(ServerNode),
- ?line ?t:stop_node(ClientNode).
+ ?line ttb:stop().
+dbg_style_fetch(cleanup,_Config) ->
+ ?line stop_client_and_server().
shell_tracing_init(suite) ->
[];
@@ -1198,19 +1263,19 @@ 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:tracer([ClientNode, ServerNode], shell),
?line ttb:stop(),
- ?line ttb:tracer([ttb_helper:get_node(client), ttb_helper:get_node(server)],
+ ?line ttb:tracer([ClientNode, ServerNode],
[{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.
+ ?line local_client_required_on_shell_tracing =
+ try ttb:tracer([ClientNode, ServerNode],[{file, ?FNAME}, shell])
+ catch
+ exit:local_client_required_on_shell_tracing ->
+ local_client_required_on_shell_tracing
+ end.
+shell_tracing_init(cleanup,_Config) ->
+ ?line stop_client_and_server().
only_one_state_for_format_handler(suite) ->
[];
@@ -1221,11 +1286,11 @@ only_one_state_for_format_handler(Config) when is_list(Config) ->
?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_for_format_handler(cleanup,_Config) ->
+ ?line stop_client_and_server().
only_one_state_with_default_format_handler(suite) ->
[];
@@ -1236,10 +1301,10 @@ only_one_state_with_default_format_handler(Config) when is_list(Config) ->
?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_default_format_handler(cleanup,_Config) ->
+ ?line stop_client_and_server().
only_one_state_with_initial_format_handler(suite) ->
[];
@@ -1255,11 +1320,11 @@ only_one_state_with_initial_format_handler(Config) when is_list(Config) ->
?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.
+only_one_state_with_initial_format_handler(cleanup,_Config) ->
+ ?line stop_client_and_server().
run_trace_with_shortcut(Shortcut, Ret, F) ->
?line {ServerNode, ClientNode} = start_client_and_server(),
@@ -1271,8 +1336,7 @@ run_trace_with_shortcut(Shortcut, Ret, F) ->
?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).
+ ?line stop_client_and_server().
fun_for(return) ->
{codestr, "fun(_) -> return_trace() end"};
@@ -1286,6 +1350,8 @@ run_trace_with_shortcut1(doc) ->
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_shortcut1(cleanup,_Config) ->
+ ?line stop_client_and_server().
run_trace_with_shortcut2(suite) ->
[];
@@ -1294,6 +1360,8 @@ run_trace_with_shortcut2(doc) ->
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_shortcut2(cleanup,_Config) ->
+ ?line stop_client_and_server().
run_trace_with_shortcut3(suite) ->
[];
@@ -1302,6 +1370,8 @@ run_trace_with_shortcut3(doc) ->
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_shortcut3(cleanup,_Config) ->
+ ?line stop_client_and_server().
run_trace_with_shortcut4(suite) ->
[];
@@ -1310,6 +1380,8 @@ run_trace_with_shortcut4(doc) ->
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).
+run_trace_with_shortcut4(cleanup,_Config) ->
+ ?line stop_client_and_server().
cant_specify_local_and_flush(suite) ->
[];
@@ -1317,13 +1389,15 @@ 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).
+ ?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.
+cant_specify_local_and_flush(cleanup,_Config) ->
+ ?line stop_client_and_server().
trace_sorted_by_default(suite) ->
[];
@@ -1334,11 +1408,11 @@ trace_sorted_by_default(Config) when is_list(Config) ->
?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.
+trace_sorted_by_default(cleanup,_Config) ->
+ ?line stop_client_and_server().
disable_sorting(suite) ->
[];
@@ -1349,11 +1423,11 @@ disable_sorting(Config) when is_list(Config) ->
?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.
+disable_sorting(cleanup,_Config) ->
+ ?line stop_client_and_server().
%% -----------------------------------------------------------------------------
%% tests for autoresume of tracing
@@ -1367,6 +1441,8 @@ 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(cleanup,_Config) ->
+ ?line stop_client_and_server().
trace_resumed_after_node_restart_ip(suite) ->
[];
@@ -1376,6 +1452,8 @@ 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_ip(cleanup,_Config) ->
+ ?line stop_client_and_server().
trace_resumed_after_node_restart_wrap(suite) ->
[];
@@ -1385,6 +1463,8 @@ 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(cleanup,_Config) ->
+ ?line stop_client_and_server().
trace_resumed_after_node_restart_wrap_mult(suite) ->
[];
@@ -1394,18 +1474,18 @@ 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).
+trace_resumed_after_node_restart_wrap_mult(cleanup,_Config) ->
+ ?line stop_client_and_server().
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,_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).
@@ -1428,3 +1508,27 @@ helper_msgs(N, TracingType) ->
_ ->
ttb_helper:msgs(N)
end.
+
+priv_dir(Conf) ->
+ %% 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.
+
+clean_priv_dir(Config) ->
+ PrivDir = priv_dir(Config),
+ case filelib:is_dir(PrivDir) of
+ true -> rm(PrivDir);
+ false -> ok
+ end.
+
+rm(This) ->
+ case filelib:is_dir(This) of
+ true ->
+ {ok,Files} = file:list_dir(This),
+ [rm(filename:join(This,F)) || F <- Files],
+ file:del_dir(This);
+ false ->
+ file:delete(This)
+ end.
diff --git a/lib/observer/test/ttb_helper.erl b/lib/observer/test/ttb_helper.erl
index 19fdc0e159..76b06cd3ce 100644
--- a/lib/observer/test/ttb_helper.erl
+++ b/lib/observer/test/ttb_helper.erl
@@ -70,7 +70,7 @@ msgs(N) ->
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
+ timer:sleep(200). %% allow trace messages to arrive over tcp/ip
run() ->
ttb({local, "A"}),
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 76e2f591fa..4eb10ae4e8 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 0.9.10
+OBSERVER_VSN = 1.1
diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4
index 151fd5ea5a..a76594d86f 120000..100644
--- a/lib/odbc/aclocal.m4
+++ b/lib/odbc/aclocal.m4
@@ -1 +1,1872 @@
-../../erts/aclocal.m4 \ No newline at end of file
+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
+
+AC_DEFUN(LM_PRECIOUS_VARS,
+[
+
+dnl ERL_TOP
+AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory])
+
+dnl Tools
+AC_ARG_VAR(CC, [C compiler])
+AC_ARG_VAR(CFLAGS, [C compiler flags])
+AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags])
+AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler])
+AC_ARG_VAR(CPP, [C/C++ preprocessor])
+AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags])
+AC_ARG_VAR(CXX, [C++ compiler])
+AC_ARG_VAR(CXXFLAGS, [C++ compiler flags])
+AC_ARG_VAR(LD, [linker (is often overridden by configure)])
+AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overriden by configure)])
+AC_ARG_VAR(LIBS, [libraries])
+AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)])
+AC_ARG_VAR(RANLIB, [ranlib])
+AC_ARG_VAR(AR, [ar])
+AC_ARG_VAR(GETCONF, [getconf])
+
+dnl Cross system root
+AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)])
+
+dnl Cross compilation variables
+AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for retrieving process CPU time: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+
+])
+
+AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
+[
+erl_xcomp_without_sysroot=no
+if test "$cross_compiling" = "yes"; then
+ test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes
+ test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot"
+else
+ erl_xcomp_sysroot=
+ erl_xcomp_isysroot=
+fi
+])
+
+AC_DEFUN(LM_CHECK_GETCONF,
+[
+if test "$cross_compiling" != "yes"; then
+ AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false])
+else
+ dnl First check if we got a `<HOST>-getconf' in $PATH
+ host_getconf="$host_alias-getconf"
+ AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false])
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ dnl We should perhaps give up if we have'nt found it by now, but at
+ dnl least in one Tilera MDE `getconf' under sysroot is a bourne
+ dnl shell script which we can use. We try to find `<HOST>-getconf'
+ dnl or `getconf' under sysconf, but only under sysconf since
+ dnl `getconf' in $PATH is almost guaranteed to be for the build
+ dnl machine.
+ GETCONF=
+ prfx="$erl_xcomp_sysroot"
+ AC_PATH_TOOL([GETCONF], [getconf], [false],
+ ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
+ fi
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_WINDOWS_ENVIRONMENT
+dnl
+dnl
+dnl Tries to determine thw windows build environment, i.e.
+dnl MIXED_CYGWIN_VC or MIXED_MSYS_VC
+dnl
+
+AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
+[
+MIXED_CYGWIN=no
+MIXED_MSYS=no
+
+AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment)
+if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_CYGWIN_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
+ elif test -x /usr/bin/msysinfo; then
+ CFLAGS="-O2"
+ MIXED_MSYS=yes
+ AC_MSG_RESULT([MSYS and VC])
+ MIXED_MSYS_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_VC=no
+ MIXED_MSYS_VC=no
+fi
+AC_SUBST(MIXED_CYGWIN_VC)
+AC_SUBST(MIXED_MSYS_VC)
+
+MIXED_VC=no
+if test "x$MIXED_MSYS_VC" = "xyes" -o "x$MIXED_CYGWIN_VC" = "xyes" ; then
+ MIXED_VC=yes
+fi
+
+AC_SUBST(MIXED_VC)
+
+if test "x$MIXED_MSYS" != "xyes"; then
+ AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
+ if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([yes])
+ MIXED_CYGWIN_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_MINGW=no
+ fi
+else
+ MIXED_CYGWIN_MINGW=no
+fi
+AC_SUBST(MIXED_CYGWIN_MINGW)
+
+AC_MSG_CHECKING(if we mix cygwin with any native compiler)
+if test "X$MIXED_CYGWIN" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_CYGWIN)
+
+AC_MSG_CHECKING(if we mix msys with another native compiler)
+if test "X$MIXED_MSYS" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_MSYS)
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_FIND_EMU_CC
+dnl
+dnl
+dnl Tries fairly hard to find a C compiler that can handle jump tables.
+dnl Defines the @EMU_CC@ variable for the makefiles and
+dnl inserts NO_JUMP_TABLE in the header if one cannot be found...
+dnl
+
+AC_DEFUN(LM_FIND_EMU_CC,
+ [AC_CACHE_CHECK(for a compiler that handles jumptables,
+ ac_cv_prog_emu_cc,
+ [
+AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+lbl1:
+ return 1;
+lbl2:
+ return 2;
+],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+
+if test $ac_cv_prog_emu_cc = no; then
+ for ac_progname in emu_cc.sh gcc-4.2 gcc; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_progname; then
+ ac_cv_prog_emu_cc=$ac_dir/$ac_progname
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ if test $ac_cv_prog_emu_cc != no; then
+ break
+ fi
+ done
+fi
+
+if test $ac_cv_prog_emu_cc != no; then
+ save_CC=$CC
+ save_CFLAGS=$CFLAGS
+ save_CPPFLAGS=$CPPFLAGS
+ CC=$ac_cv_prog_emu_cc
+ CFLAGS=""
+ CPPFLAGS=""
+ AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+ lbl1:
+ return 1;
+ lbl2:
+ return 2;
+ ],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+ CC=$save_CC
+ CFLAGS=$save_CFLAGS
+ CPPFLAGS=$save_CPPFLAGS
+fi
+])
+if test $ac_cv_prog_emu_cc = no; then
+ AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables])
+ EMU_CC=$CC
+else
+ EMU_CC=$ac_cv_prog_emu_cc
+fi
+AC_SUBST(EMU_CC)
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_INSTALL_DIR
+dnl
+dnl This macro may be used by any OTP application.
+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
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_PERL5
+dnl
+dnl Try to find perl version 5. If found set PERL to the absolute path
+dnl of the program, if not found set PERL to false.
+dnl
+dnl On some systems /usr/bin/perl is perl 4 and e.g.
+dnl /usr/local/bin/perl is perl 5. We try to handle this case by
+dnl putting a couple of
+dnl Tries to handle the case that there are two programs called perl
+dnl in the path and one of them is perl 5 and the other isn't.
+dnl
+AC_DEFUN(LM_PROG_PERL5,
+[AC_PATH_PROGS(PERL, perl5 perl, false,
+ /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH})
+changequote(, )dnl
+dnl[ That bracket is needed to balance the right bracket below
+if test "$PERL" = "false" || $PERL -e 'exit ($] >= 5)'; then
+changequote([, ])dnl
+ ac_cv_path_PERL=false
+ PERL=false
+dnl AC_MSG_WARN(perl version 5 not found)
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SO_BSDCOMPAT
+dnl
+dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux)
+dnl
+AC_DEFUN(LM_DECL_SO_BSDCOMPAT,
+[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat,
+AC_TRY_COMPILE([#include <sys/socket.h>], [int i = SO_BSDCOMPAT;],
+ ac_cv_decl_so_bsdcompat=yes,
+ ac_cv_decl_so_bsdcompat=no))
+
+case "${ac_cv_decl_so_bsdcompat}" in
+ "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[],
+ [Define if you have SO_BSDCOMPAT flag on sockets]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_INADDR_LOOPBACK
+dnl
+dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default
+dnl
+
+AC_DEFUN(LM_DECL_INADDR_LOOPBACK,
+[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h],
+ ac_cv_decl_inaddr_loopback,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>], [int i = INADDR_LOOPBACK;],
+ac_cv_decl_inaddr_loopback=yes, ac_cv_decl_inaddr_loopback=no)
+])
+
+if test ${ac_cv_decl_inaddr_loopback} = no; then
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h],
+ ac_cv_decl_inaddr_loopback_rpc,
+ AC_TRY_COMPILE([#include <rpc/types.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_rpc=yes,
+ ac_cv_decl_inaddr_loopback_rpc=no))
+
+ case "${ac_cv_decl_inaddr_loopback_rpc}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
+ [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h],
+ ac_cv_decl_inaddr_loopback_winsock2,
+ AC_TRY_COMPILE([#define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_winsock2=yes,
+ ac_cv_decl_inaddr_loopback_winsock2=no))
+ case "${ac_cv_decl_inaddr_loopback_winsock2}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[],
+ [Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ # couldn't find it anywhere
+ AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[],
+ [Define if you don't have a definition of INADDR_LOOPBACK]) ;;
+ esac;;
+ esac
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_SOCKADDR_SA_LEN
+dnl
+dnl Check if the sockaddr structure has the field sa_len
+dnl
+
+AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN,
+[AC_CACHE_CHECK([whether struct sockaddr has sa_len field],
+ ac_cv_struct_sockaddr_sa_len,
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>], [struct sockaddr s; s.sa_len = 10;],
+ ac_cv_struct_sockaddr_sa_len=yes, ac_cv_struct_sockaddr_sa_len=no))
+
+dnl FIXME convbreak
+case ${ac_cv_struct_sockaddr_sa_len} in
+ "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;;
+ *) ;;
+esac
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_EXCEPTION
+dnl
+dnl Check to see whether the system supports the matherr function
+dnl and its associated type "struct exception".
+dnl
+
+AC_DEFUN(LM_STRUCT_EXCEPTION,
+[AC_CACHE_CHECK([for struct exception (and matherr function)],
+ ac_cv_struct_exception,
+AC_TRY_COMPILE([#include <math.h>],
+ [struct exception x; x.type = DOMAIN; x.type = SING;],
+ ac_cv_struct_exception=yes, ac_cv_struct_exception=no))
+
+case "${ac_cv_struct_exception}" in
+ "yes" ) AC_DEFINE(USE_MATHERR,[1],[Define if you have matherr() function and struct exception type]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_IPV6
+dnl
+dnl Check for ipv6 support and what the in6_addr structure is called.
+dnl (early linux used in_addr6 insted of in6_addr)
+dnl
+
+AC_DEFUN(LM_SYS_IPV6,
+[AC_MSG_CHECKING(for IP version 6 support)
+AC_CACHE_VAL(ac_cv_sys_ipv6_support,
+[ok_so_far=yes
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no)
+
+if test $ok_so_far = yes; then
+ ac_cv_sys_ipv6_support=yes
+else
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in_addr6 a6; struct sockaddr_in6 s6;],
+ ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no)
+fi
+])dnl
+
+dnl
+dnl Have to use old style AC_DEFINE due to BC with old autoconf.
+dnl
+
+case ${ac_cv_sys_ipv6_support} in
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ ;;
+ in_addr6)
+ AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)])
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this])
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_MULTICAST
+dnl
+dnl Check for multicast support. Only checks for multicast options in
+dnl setsockopt(), no check is performed that multicasting actually works.
+dnl If options are found defines HAVE_MULTICAST_SUPPORT
+dnl
+
+AC_DEFUN(LM_SYS_MULTICAST,
+[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
+[AC_EGREP_CPP(yes,
+[#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP)
+yes
+#endif
+], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)])
+if test $ac_cv_sys_multicast_support = yes; then
+ AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1],
+ [Define if setsockopt() accepts multicast options])
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SYS_ERRLIST
+dnl
+dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared
+dnl in a system header file, stdio.h or errno.h.
+dnl
+
+AC_DEFUN(LM_DECL_SYS_ERRLIST,
+[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h],
+ ac_cv_decl_sys_errlist,
+[AC_TRY_COMPILE([#include <stdio.h>
+#include <errno.h>], [char *msg = *(sys_errlist + 1);],
+ ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)])
+if test $ac_cv_decl_sys_errlist = yes; then
+ AC_DEFINE(SYS_ERRLIST_DECLARED,[],
+ [define if the variable sys_errlist is declared in a system header file])
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes
+dnl [, action-if-found [, action-if-not-found]]] )
+dnl
+dnl Checks if the declaration "declaration" of "funname" conflicts
+dnl with the header files idea of how the function should be
+dnl declared. It is useful on systems which lack prototypes and you
+dnl need to provide your own (e.g. when you want to take the address
+dnl of a function). The 4'th argument is expanded if conflicting,
+dnl the 5'th argument otherwise
+dnl
+dnl
+
+AC_DEFUN(LM_CHECK_FUNC_DECL,
+[AC_MSG_CHECKING([for conflicting declaration of $1])
+AC_CACHE_VAL(ac_cv_func_decl_$1,
+[AC_TRY_COMPILE([#include <stdio.h>
+$3],[$2
+char *c = (char *)$1;
+], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")])
+if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$4], , :, [$4])
+else
+ AC_MSG_RESULT(no)
+ifelse([$5], , , [$5
+])dnl
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl AC_DOUBLE_MIDDLE_ENDIAN
+dnl
+dnl Checks whether doubles are represented in "middle-endian" format.
+dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
+dnl as well as DOUBLE_MIDDLE_ENDIAN.
+dnl
+dnl
+
+AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
+[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
+[# It does not; compile a test program.
+AC_RUN_IFELSE(
+[AC_LANG_SOURCE([[#include <stdlib.h>
+
+int
+main(void)
+{
+ int i = 0;
+ int zero = 0;
+ int bigendian;
+ int zero_index = 0;
+
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+
+ /* we'll use the one with 32-bit words */
+ union
+ {
+ double d;
+ unsigned int c[2];
+ } vint;
+
+ union
+ {
+ double d;
+ unsigned long c[2];
+ } vlong;
+
+ union
+ {
+ double d;
+ unsigned short c[2];
+ } vshort;
+
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ u.l = 1;
+ bigendian = (u.c[sizeof (long int) - 1] == 1);
+
+ zero_index = bigendian ? 1 : 0;
+
+ vint.d = 1.0;
+ vlong.d = 1.0;
+ vshort.d = 1.0;
+
+ if (sizeof(unsigned int) == 4)
+ {
+ if (vint.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned long) == 4)
+ {
+ if (vlong.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned short) == 4)
+ {
+ if (vshort.c[zero_index] != 0)
+ zero = 1;
+ }
+
+ exit (zero);
+}
+]])],
+ [ac_cv_c_double_middle_endian=no],
+ [ac_cv_c_double_middle_endian=yes],
+ [ac_cv_c_double_middle=unknown])])
+case $ac_cv_c_double_middle_endian in
+ yes)
+ m4_default([$1],
+ [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
+ [Define to 1 if your processor stores the words in a double in
+ middle-endian format (like some ARMs).])]) ;;
+ no)
+ $2 ;;
+ *)
+ m4_default([$3],
+ [AC_MSG_WARN([unknown double endianness
+presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
+esac
+])# AC_C_DOUBLE_MIDDLE_ENDIAN
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_THR_LIB
+dnl
+dnl This macro may be used by any OTP application.
+dnl
+dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also
+dnl checks for some pthread headers which will appear in DEFS or config.h.
+dnl
+
+AC_DEFUN(LM_CHECK_THR_LIB,
+[
+
+NEED_NPTL_PTHREAD_H=no
+
+dnl win32?
+AC_MSG_CHECKING([for native win32 threads])
+if test "X$host_os" = "Xwin32"; then
+ AC_MSG_RESULT(yes)
+ THR_DEFS="-DWIN32_THREADS"
+ THR_LIBS=
+ THR_LIB_NAME=win32_threads
+ THR_LIB_TYPE=win32_threads
+else
+ AC_MSG_RESULT(no)
+ THR_DEFS=
+ THR_LIBS=
+ THR_LIB_NAME=
+ THR_LIB_TYPE=posix_unknown
+
+dnl Try to find POSIX threads
+
+dnl The usual pthread lib...
+ AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
+
+dnl FreeBSD has pthreads in special c library, c_r...
+ if test "x$THR_LIBS" = "x"; then
+ AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r")
+ fi
+
+dnl On ofs1 the '-pthread' switch should be used
+ if test "x$THR_LIBS" = "x"; then
+ AC_MSG_CHECKING([if the '-pthread' switch can be used])
+ saved_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -pthread"
+ AC_TRY_LINK([#include <pthread.h>],
+ pthread_create((void*)0,(void*)0,(void*)0,(void*)0);,
+ [THR_DEFS="-pthread"
+ THR_LIBS="-pthread"])
+ CFLAGS=$saved_cflags
+ if test "x$THR_LIBS" != "x"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ if test "x$THR_LIBS" != "x"; then
+ THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
+ THR_LIB_NAME=pthread
+ case $host_os in
+ solaris*)
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
+ linux*)
+ THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
+
+ LM_CHECK_GETCONF
+ AC_MSG_CHECKING(for Native POSIX Thread Library)
+ libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
+ if test $? -eq 0; then
+ case "$libpthr_vsn" in
+ *nptl*|*NPTL*) nptl=yes;;
+ *) nptl=no;;
+ esac
+ elif test "$cross_compiling" = "yes"; then
+ case "$erl_xcomp_linux_nptl" in
+ "") nptl=cross;;
+ yes|no) nptl=$erl_xcomp_linux_nptl;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);;
+ esac
+ else
+ nptl=no
+ fi
+ AC_MSG_RESULT($nptl)
+ if test $nptl = cross; then
+ nptl=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $nptl = yes; then
+ THR_LIB_TYPE=posix_nptl
+ need_nptl_incldir=no
+ AC_CHECK_HEADER(nptl/pthread.h,
+ [need_nptl_incldir=yes
+ NEED_NPTL_PTHREAD_H=yes])
+ if test $need_nptl_incldir = yes; then
+ # Ahh...
+ nptl_path="$C_INCLUDE_PATH:$CPATH"
+ if test X$cross_compiling != Xyes; then
+ nptl_path="$nptl_path:/usr/local/include:/usr/include"
+ else
+ IROOT="$erl_xcomp_isysroot"
+ test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot"
+ test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot])
+ nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include"
+ fi
+ nptl_ws_path=
+ save_ifs="$IFS"; IFS=":"
+ for dir in $nptl_path; do
+ if test "x$dir" != "x"; then
+ nptl_ws_path="$nptl_ws_path $dir"
+ fi
+ done
+ IFS=$save_ifs
+ nptl_incldir=
+ for dir in $nptl_ws_path; do
+ AC_CHECK_HEADER($dir/nptl/pthread.h,
+ nptl_incldir=$dir/nptl)
+ if test "x$nptl_incldir" != "x"; then
+ THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
+ break
+ fi
+ done
+ if test "x$nptl_incldir" = "x"; then
+ AC_MSG_ERROR(Failed to locate nptl system include directory)
+ fi
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need THR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $THR_DEFS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h,
+ AC_DEFINE(HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ fi
+fi
+
+])
+
+AC_DEFUN(ERL_INTERNAL_LIBS,
+[
+
+ERTS_INTERNAL_X_LIBS=
+
+AC_CHECK_LIB(kstat, kstat_open,
+[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat])
+ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"])
+
+AC_SUBST(ERTS_INTERNAL_X_LIBS)
+
+])
+
+AC_DEFUN(ETHR_CHK_SYNC_OP,
+[
+ AC_MSG_CHECKING([for $3-bit $1()])
+ case "$2" in
+ "1") sync_call="$1(&var);";;
+ "2") sync_call="$1(&var, ($4) 0);";;
+ "3") sync_call="$1(&var, ($4) 0, ($4) 0);";;
+ esac
+ have_sync_op=no
+ AC_TRY_LINK([],
+ [
+ $4 res;
+ volatile $4 var;
+ res = $sync_call
+ ],
+ [have_sync_op=yes])
+ test $have_sync_op = yes && $5
+ AC_MSG_RESULT([$have_sync_op])
+])
+
+AC_DEFUN(ETHR_CHK_INTERLOCKED,
+[
+ ilckd="$1"
+ AC_MSG_CHECKING([for ${ilckd}()])
+ case "$2" in
+ "1") ilckd_call="${ilckd}(var);";;
+ "2") ilckd_call="${ilckd}(var, ($3) 0);";;
+ "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
+ "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
+ esac
+ have_interlocked_op=no
+ AC_TRY_LINK(
+ [
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <intrin.h>
+ ],
+ [
+ volatile $3 *var;
+ volatile $3 arr[2];
+
+ $ilckd_call
+ return 0;
+ ],
+ [have_interlocked_op=yes])
+ test $have_interlocked_op = yes && $4
+ AC_MSG_RESULT([$have_interlocked_op])
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_FIND_ETHR_LIB
+dnl
+dnl NOTE! This macro may be changed at any time! Should *only* be used by
+dnl ERTS!
+dnl
+dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link
+dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS
+dnl except that the ethread lib itself is not included), ETHR_DEFS to
+dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the
+dnl thread library which the ethread library is based on, and ETHR_LIB_NAME
+dnl to the name of the library where the ethread implementation is located.
+dnl ERL_FIND_ETHR_LIB currently searches for 'pthreads', and
+dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS,
+dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the
+dnl empty string.
+dnl
+
+AC_DEFUN(ERL_FIND_ETHR_LIB,
+[
+
+LM_CHECK_THR_LIB
+ERL_INTERNAL_LIBS
+
+ethr_have_native_atomics=no
+ethr_have_native_spinlock=no
+ETHR_THR_LIB_BASE="$THR_LIB_NAME"
+ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
+ETHR_DEFS="$THR_DEFS"
+ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS"
+ETHR_LIBS=
+ETHR_LIB_NAME=
+
+ethr_modified_default_stack_size=
+
+dnl Name of lib where ethread implementation is located
+ethr_lib_name=ethread
+
+case "$THR_LIB_NAME" in
+
+ win32_threads)
+ ETHR_THR_LIB_BASE_DIR=win
+ # * _WIN32_WINNT >= 0x0400 is needed for
+ # TryEnterCriticalSection
+ # * _WIN32_WINNT >= 0x0403 is needed for
+ # InitializeCriticalSectionAndSpinCount
+ # The ethread lib will refuse to build if _WIN32_WINNT < 0x0403.
+ #
+ # -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it
+ # and save it in ETHR_DEFS.
+ found_win32_winnt=no
+ for cppflag in $CPPFLAGS; do
+ case $cppflag in
+ -DWINVER*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ ;;
+ -D_WIN32_WINNT*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ found_win32_winnt=yes
+ ;;
+ *)
+ ;;
+ esac
+ done
+ if test $found_win32_winnt = no; then
+ AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS])
+ fi
+
+ AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
+
+ test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes
+ ;;
+
+ pthread)
+ ETHR_THR_LIB_BASE_DIR=pthread
+ AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
+ case $host_os in
+ openbsd*)
+ # The default stack size is insufficient for our needs
+ # on OpenBSD. We increase it to 256 kilo words.
+ ethr_modified_default_stack_size=256;;
+ linux*)
+ ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE"
+
+ if test X$cross_compiling = Xyes; then
+ case X$erl_xcomp_linux_usable_sigusrx in
+ X) usable_sigusrx=cross;;
+ Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);;
+ esac
+ case X$erl_xcomp_linux_usable_sigaltstack in
+ X) usable_sigaltstack=cross;;
+ Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);;
+ esac
+ else
+ # FIXME: Test for actual problems instead of kernel versions
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-1]]|2.[[0-1]].*)
+ usable_sigusrx=no
+ usable_sigaltstack=no;;
+ 2.[[2-3]]|2.[[2-3]].*)
+ usable_sigusrx=yes
+ usable_sigaltstack=no;;
+ *)
+ usable_sigusrx=yes
+ usable_sigaltstack=yes;;
+ esac
+ fi
+
+ AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used)
+ AC_MSG_RESULT($usable_sigusrx)
+ if test $usable_sigusrx = cross; then
+ usable_sigusrx=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigusrx = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
+ fi
+
+ AC_MSG_CHECKING(if sigaltstack can be used)
+ AC_MSG_RESULT($usable_sigaltstack)
+ if test $usable_sigaltstack = cross; then
+ usable_sigaltstack=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigaltstack = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need ETHR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $ETHR_DEFS"
+
+ dnl We need the thread library in order to find some functions
+ saved_libs="$LIBS"
+ LIBS="$LIBS $ETHR_X_LIBS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ if test $NEED_NPTL_PTHREAD_H = yes; then
+ AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \
+[Define if you need the <nptl/pthread.h> header file.])
+ fi
+
+ AC_CHECK_HEADER(sched.h, \
+ AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \
+[Define if you have the <sched.h> header file.]))
+
+ AC_CHECK_HEADER(sys/time.h, \
+ AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \
+[Define if you have the <sys/time.h> header file.]))
+
+ AC_TRY_COMPILE([#include <time.h>
+ #include <sys/time.h>],
+ [struct timeval *tv; return 0;],
+ AC_DEFINE(ETHR_TIME_WITH_SYS_TIME, 1, \
+[Define if you can safely include both <sys/time.h> and <time.h>.]))
+
+
+ dnl
+ dnl Check for functions
+ dnl
+
+ AC_CHECK_FUNC(pthread_spin_lock, \
+ [ethr_have_native_spinlock=yes \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
+[Define if you have the pthread_spin_lock function.])])
+
+ have_sched_yield=no
+ have_librt_sched_yield=no
+ AC_CHECK_FUNC(sched_yield, [have_sched_yield=yes])
+ if test $have_sched_yield = no; then
+ AC_CHECK_LIB(rt, sched_yield,
+ [have_librt_sched_yield=yes
+ ETHR_X_LIBS="$ETHR_X_LIBS -lrt"])
+ fi
+ if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.])
+ AC_MSG_CHECKING([whether sched_yield() returns an int])
+ sched_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #ifdef ETHR_HAVE_SCHED_H
+ #include <sched.h>
+ #endif
+ ],
+ [int sched_yield();],
+ [sched_yield_ret_int=yes])
+ AC_MSG_RESULT([$sched_yield_ret_int])
+ if test $sched_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_yield=no
+ AC_CHECK_FUNC(pthread_yield, [have_pthread_yield=yes])
+ if test $have_pthread_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.])
+ AC_MSG_CHECKING([whether pthread_yield() returns an int])
+ pthread_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [int pthread_yield();],
+ [pthread_yield_ret_int=yes])
+ AC_MSG_RESULT([$pthread_yield_ret_int])
+ if test $pthread_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_rwlock_init=no
+ AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes])
+ if test $have_pthread_rwlock_init = yes; then
+
+ ethr_have_pthread_rwlockattr_setkind_np=no
+ AC_CHECK_FUNC(pthread_rwlockattr_setkind_np,
+ [ethr_have_pthread_rwlockattr_setkind_np=yes])
+
+ if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \
+[Define if you have the pthread_rwlockattr_setkind_np() function.])
+
+ AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP])
+ ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
+ AC_TRY_LINK([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [
+ pthread_rwlockattr_t *attr;
+ return pthread_rwlockattr_setkind_np(attr,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+ ],
+ [ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes])
+ AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np])
+ if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \
+[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.])
+ fi
+ fi
+ fi
+
+ if test "$force_pthread_rwlocks" = "yes"; then
+
+ AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \
+[Define if you want to force usage of pthread rwlocks])
+
+ if test $have_pthread_rwlock_init = yes; then
+ AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.])
+ else
+ AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found])
+ fi
+ fi
+
+ AC_CHECK_FUNC(pthread_attr_setguardsize, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
+[Define if you have the pthread_attr_setguardsize function.]))
+
+ linux_futex=no
+ AC_MSG_CHECKING([for Linux futexes])
+ AC_TRY_LINK([
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <linux/futex.h>
+ #include <sys/time.h>
+ ],
+ [
+ int i = 1;
+ syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
+ (void*)0,(void*)0, 0);
+ syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
+ (void*)0,(void*)0, 0);
+ return 0;
+ ],
+ linux_futex=yes)
+ AC_MSG_RESULT([$linux_futex])
+ test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
+
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(long long)
+ AC_CHECK_SIZEOF(__int128_t)
+
+ if test "$ac_cv_sizeof_int" = "4"; then
+ int32="int"
+ elif test "$ac_cv_sizeof_long" = "4"; then
+ int32="long"
+ elif test "$ac_cv_sizeof_long_long" = "4"; then
+ int32="long long"
+ else
+ AC_MSG_ERROR([No 32-bit type found])
+ fi
+
+ if test "$ac_cv_sizeof_int" = "8"; then
+ int64="int"
+ elif test "$ac_cv_sizeof_long" = "8"; then
+ int64="long"
+ elif test "$ac_cv_sizeof_long_long" = "8"; then
+ int64="long long"
+ else
+ AC_MSG_ERROR([No 64-bit type found])
+ fi
+
+ int128=no
+ if test "$ac_cv_sizeof___int128_t" = "16"; then
+ int128="__int128_t"
+ fi
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32, 1, [Define if you have __sync_val_compare_and_swap() for 32-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH32, 1, [Define if you have __sync_add_and_fetch() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND32, 1, [Define if you have __sync_fetch_and_and() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR32, 1, [Define if you have __sync_fetch_and_or() for 32-bit integers]))
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64, 1, [Define if you have __sync_val_compare_and_swap() for 64-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH64, 1, [Define if you have __sync_add_and_fetch() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND64, 1, [Define if you have __sync_fetch_and_and() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR64, 1, [Define if you have __sync_fetch_and_or() for 64-bit integers]))
+
+ if test $int128 != no; then
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [128], [$int128], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128, 1, [Define if you have __sync_val_compare_and_swap() for 128-bit integers]))
+ fi
+
+ AC_MSG_CHECKING([for a usable libatomic_ops implementation])
+ case "x$with_libatomic_ops" in
+ xno | xyes | x)
+ libatomic_ops_include=
+ ;;
+ *)
+ if test -d "${with_libatomic_ops}/include"; then
+ libatomic_ops_include="-I$with_libatomic_ops/include"
+ CPPFLAGS="$CPPFLAGS $libatomic_ops_include"
+ else
+ AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found])
+ fi;;
+ esac
+ ethr_have_libatomic_ops=no
+ AC_TRY_LINK([#include "atomic_ops.h"],
+ [
+ volatile AO_t x;
+ AO_t y;
+ int z;
+
+ AO_nop_full();
+ AO_store(&x, (AO_t) 0);
+ z = AO_load(&x);
+ z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1);
+ ],
+ [ethr_have_native_atomics=yes
+ ethr_have_libatomic_ops=yes])
+ AC_MSG_RESULT([$ethr_have_libatomic_ops])
+ if test $ethr_have_libatomic_ops = yes; then
+ AC_CHECK_SIZEOF(AO_t, ,
+ [
+ #include <stdio.h>
+ #include "atomic_ops.h"
+ ])
+ AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used])
+
+ AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations])
+ if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations])
+ fi
+ ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
+ elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_MSG_ERROR([No usable libatomic_ops implementation found])
+ fi
+
+ case "$host_cpu" in
+ sparc | sun4u | sparc64 | sun4v)
+ case "$with_sparc_memory_order" in
+ "TSO")
+ AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
+ "PSO")
+ AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
+ "RMO"|"")
+ AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
+ *)
+ AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
+ esac
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
+ if test "$enable_x86_out_of_order" = "yes"; then
+ AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
+ fi
+ ethr_have_native_atomics=yes;;
+ macppc | ppc | "Power Macintosh")
+ ethr_have_native_atomics=yes;;
+ tile)
+ ethr_have_native_atomics=yes;;
+ *)
+ ;;
+ esac
+
+ test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
+
+ dnl Restore LIBS
+ LIBS=$saved_libs
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ ;;
+ *)
+ ;;
+esac
+
+AC_MSG_CHECKING([whether default stack size should be modified])
+if test "x$ethr_modified_default_stack_size" != "x"; then
+ AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size])
+ AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words])
+else
+ AC_MSG_RESULT([no])
+fi
+
+if test "x$ETHR_THR_LIB_BASE" != "x"; then
+ ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS"
+ ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS"
+ ETHR_LIB_NAME=$ethr_lib_name
+fi
+
+AC_CHECK_SIZEOF(void *)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers])
+
+AC_CHECK_SIZEOF(int)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int])
+AC_CHECK_SIZEOF(long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long])
+AC_CHECK_SIZEOF(long long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
+AC_CHECK_SIZEOF(__int64)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
+AC_CHECK_SIZEOF(__int128_t)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
+
+
+case X$erl_xcomp_bigendian in
+ X) ;;
+ Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);;
+esac
+
+AC_C_BIGENDIAN
+
+if test "$ac_cv_c_bigendian" = "yes"; then
+ AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
+fi
+
+case X$erl_xcomp_double_middle_endian in
+ X) ;;
+ Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
+esac
+
+AC_C_DOUBLE_MIDDLE_ENDIAN
+
+AC_ARG_ENABLE(native-ethr-impls,
+ AS_HELP_STRING([--disable-native-ethr-impls],
+ [disable native ethread implementations]),
+[ case "$enableval" in
+ no) disable_native_ethr_impls=yes ;;
+ *) disable_native_ethr_impls=no ;;
+ esac ], disable_native_ethr_impls=no)
+
+AC_ARG_ENABLE(x86-out-of-order,
+ AS_HELP_STRING([--enable-x86-out-of-order],
+ [enable x86/x84_64 out of order support (default disabled)]))
+
+test "X$disable_native_ethr_impls" = "Xyes" &&
+ AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
+
+AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
+ AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
+ [prefer gcc native ethread implementations]),
+[ case "$enableval" in
+ yes) enable_prefer_gcc_native_ethr_impls=yes ;;
+ *) enable_prefer_gcc_native_ethr_impls=no ;;
+ esac ], enable_prefer_gcc_native_ethr_impls=no)
+
+test $enable_prefer_gcc_native_ethr_impls = yes &&
+ AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
+
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
+AC_ARG_WITH(with_sparc_memory_order,
+ AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
+ [specify sparc memory order (defaults to RMO)]))
+
+ETHR_X86_SSE2_ASM=no
+case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in
+ yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64)
+ AC_MSG_CHECKING([for gcc sse2 asm support])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -msse2"
+ gcc_sse2_asm=no
+ AC_TRY_COMPILE([],
+ [
+ long long x, *y;
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
+ ],
+ [gcc_sse2_asm=yes])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$gcc_sse2_asm])
+ if test "$gcc_sse2_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
+ ETHR_X86_SSE2_ASM=yes
+ fi
+ ;;
+ *)
+ ;;
+esac
+
+case "$GCC-$host_cpu" in
+ yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
+ gcc_dw_cmpxchg_asm=no
+ AC_MSG_CHECKING([for gcc double word cmpxchg asm support])
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "pushl %%ebx\n\t"
+ "movl %8, %%ebx\n\t"
+#endif
+#if ETHR_SIZEOF_PTR == 4
+ "lock; cmpxchg8b %0\n\t"
+#else
+ "lock; cmpxchg16b %0\n\t"
+#endif
+ "setz %3\n\t"
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "popl %%ebx\n\t"
+#endif
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new[1]),
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "r"(new[0])
+#else
+ "b"(new[0])
+#endif
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test $gcc_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+#if !defined(__PIC__) || !__PIC__
+# error nope
+#endif
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new)
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
+ fi
+ fi
+ AC_MSG_RESULT([$gcc_dw_cmpxchg_asm])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
+ fi;;
+ *)
+ ;;
+esac
+
+AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
+[Define if you have all ethread defines])
+
+AC_SUBST(ETHR_X_LIBS)
+AC_SUBST(ETHR_LIBS)
+AC_SUBST(ETHR_LIB_NAME)
+AC_SUBST(ETHR_DEFS)
+AC_SUBST(ETHR_THR_LIB_BASE)
+AC_SUBST(ETHR_THR_LIB_BASE_DIR)
+AC_SUBST(ETHR_X86_SSE2_ASM)
+
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_TIME_CORRECTION
+dnl
+dnl In the presence of a high resolution realtime timer Erlang can adapt
+dnl its view of time relative to this timer. On solaris such a timer is
+dnl available with the syscall gethrtime(). On other OS's a fallback
+dnl solution using times() is implemented. (However on e.g. FreeBSD times()
+dnl is implemented using gettimeofday so it doesn't make much sense to
+dnl use it there...) On second thought, it seems to be safer to do it the
+dnl other way around. I.e. only use times() on OS's where we know it will
+dnl work...
+dnl
+
+AC_DEFUN(ERL_TIME_CORRECTION,
+[if test x$ac_cv_func_gethrtime = x; then
+ AC_CHECK_FUNC(gethrtime)
+fi
+if test x$clock_gettime_correction = xunknown; then
+ AC_TRY_COMPILE([#include <time.h>],
+ [struct timespec ts;
+ long long result;
+ clock_gettime(CLOCK_MONOTONIC,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);],
+ clock_gettime_compiles=yes,
+ clock_gettime_compiles=no)
+else
+ clock_gettime_compiles=no
+fi
+
+
+AC_CACHE_CHECK([how to correct for time adjustments], erl_cv_time_correction,
+[
+case $clock_gettime_correction in
+ yes)
+ erl_cv_time_correction=clock_gettime;;
+ no|unknown)
+ case $ac_cv_func_gethrtime in
+ yes)
+ erl_cv_time_correction=hrtime ;;
+ no)
+ case $host_os in
+ linux*)
+ case $clock_gettime_correction in
+ unknown)
+ if test x$clock_gettime_compiles = xyes; then
+ if test X$cross_compiling != Xyes; then
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-5]]|2.[[0-5]].*)
+ erl_cv_time_correction=times ;;
+ *)
+ erl_cv_time_correction=clock_gettime;;
+ esac
+ else
+ case X$erl_xcomp_linux_clock_gettime_correction in
+ X)
+ erl_cv_time_correction=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_linux_clock_gettime_correction = yes; then
+ erl_cv_time_correction=clock_gettime
+ else
+ erl_cv_time_correction=times
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_linux_clock_gettime_correction value: $erl_xcomp_linux_clock_gettime_correction]);;
+ esac
+ fi
+ else
+ erl_cv_time_correction=times
+ fi
+ ;;
+ *)
+ erl_cv_time_correction=times ;;
+ esac
+ ;;
+ *)
+ erl_cv_time_correction=none ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+])
+
+xrtlib=""
+case $erl_cv_time_correction in
+ times)
+ AC_DEFINE(CORRECT_USING_TIMES,[],
+ [Define if you do not have a high-res. timer & want to use times() instead])
+ ;;
+ clock_gettime|cross)
+ if test $erl_cv_time_correction = cross; then
+ erl_cv_time_correction=clock_gettime
+ AC_MSG_WARN([result clock_gettime guessed because of cross compilation])
+ fi
+ xrtlib="-lrt"
+ AC_DEFINE(GETHRTIME_WITH_CLOCK_GETTIME,[1],
+ [Define if you want to use clock_gettime to simulate gethrtime])
+ ;;
+esac
+dnl
+dnl Check if gethrvtime is working, and if to use procfs ioctl
+dnl or (yet to be written) write to the procfs ctl file.
+dnl
+
+AC_MSG_CHECKING([if gethrvtime works and how to use it])
+AC_TRY_RUN([
+/* gethrvtime procfs ioctl test */
+/* These need to be undef:ed to not break activation of
+ * micro level process accounting on /proc/self
+ */
+#ifdef _LARGEFILE_SOURCE
+# undef _LARGEFILE_SOURCE
+#endif
+#ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+
+int main() {
+ long msacct = PR_MSACCT;
+ int fd;
+ long long start, stop;
+ int i;
+ pid_t pid = getpid();
+ char proc_self[30] = "/proc/";
+
+ sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid);
+ if ( (fd = open(proc_self, O_WRONLY)) == -1)
+ exit(1);
+ if (ioctl(fd, PIOCSET, &msacct) < 0)
+ exit(2);
+ if (close(fd) < 0)
+ exit(3);
+ start = gethrvtime();
+ for (i = 0; i < 100; i++)
+ stop = gethrvtime();
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+}
+],
+erl_gethrvtime=procfs_ioctl,
+erl_gethrvtime=false,
+[
+case X$erl_xcomp_gethrvtime_procfs_ioctl in
+ X)
+ erl_gethrvtime=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then
+ erl_gethrvtime=procfs_ioctl
+ else
+ erl_gethrvtime=false
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);;
+esac
+])
+
+case $erl_gethrvtime in
+ procfs_ioctl)
+ AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1],
+ [define if gethrvtime() works and uses ioctl() to /proc/self])
+ AC_MSG_RESULT(uses ioctl to procfs)
+ ;;
+ *)
+ if test $erl_gethrvtime = cross; then
+ erl_gethrvtime=false
+ AC_MSG_RESULT(cross)
+ AC_MSG_WARN([result 'not working' guessed because of cross compilation])
+ else
+ AC_MSG_RESULT(not working)
+ fi
+
+ dnl
+ dnl Check if clock_gettime (linux) is working
+ dnl
+
+ AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time])
+ save_libs=$LIBS
+ LIBS="-lrt"
+ AC_TRY_RUN([
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <time.h>
+ int main() {
+ long long start, stop;
+ int i;
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0)
+ exit(1);
+ start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ for (i = 0; i < 100; i++)
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
+ stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+ }
+ ],
+ erl_clock_gettime=yes,
+ erl_clock_gettime=no,
+ [
+ case X$erl_xcomp_clock_gettime_cpu_time in
+ X) erl_clock_gettime=cross;;
+ Xyes|Xno) erl_clock_gettime=$erl_xcomp_clock_gettime_cpu_time;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);;
+ esac
+ ])
+ LIBS=$save_libs
+ case $host_os in
+ linux*)
+ AC_MSG_RESULT([no; not stable])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ AC_MSG_RESULT($erl_clock_gettime)
+ case $erl_clock_gettime in
+ yes)
+ AC_DEFINE(HAVE_CLOCK_GETTIME,[],
+ [define if clock_gettime() works for getting process time])
+ LIBRT=-lrt
+ ;;
+ cross)
+ erl_clock_gettime=no
+ AC_MSG_WARN([result no guessed because of cross compilation])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ LIBRT=$xrtlib
+ ;;
+ esac
+ ;;
+ esac
+ AC_SUBST(LIBRT)
+ ;;
+esac
+])dnl
+
+dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY
+dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
+dnl AC_LANG_JAVA instead...)
+AC_DEFUN(ERL_TRY_LINK_JAVA,
+[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
+changequote(, )dnl
+cat > conftest.java <<EOF
+$1
+class conftest { public static void main(String[] args) {
+ $2
+ ; return; }}
+EOF
+changequote([, ])dnl
+if AC_TRY_EVAL(java_link) && test -s conftest.class; then
+ ifelse([$3], , :, [rm -rf conftest*
+ $3])
+else
+ echo "configure: failed program was:" 1>&AC_FD_CC
+ cat conftest.java 1>&AC_FD_CC
+ echo "configure: PATH was $PATH" 1>&AC_FD_CC
+ifelse([$4], , , [ rm -rf conftest*
+ $4
+])dnl
+fi
+rm -f conftest*])
+#define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
+
+
diff --git a/lib/odbc/c_src/Makefile.in b/lib/odbc/c_src/Makefile.in
index dda896bcd2..5b37b352fb 100644
--- a/lib/odbc/c_src/Makefile.in
+++ b/lib/odbc/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
@@ -128,12 +128,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
ifdef EXE_TARGET
- $(INSTALL_DIR) $(RELSYSDIR)/c_src
- $(INSTALL_DATA) $(C_FILES) $(H_FILES) $(RELSYSDIR)/c_src
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_DIR) $(RELSYSDIR)/priv/obj
- $(INSTALL_PROGRAM) $(EXE_TARGET) $(RELSYSDIR)/priv/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
+ $(INSTALL_DATA) $(C_FILES) $(H_FILES) "$(RELSYSDIR)/c_src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_PROGRAM) $(EXE_TARGET) "$(RELSYSDIR)/priv/bin"
endif
release_docs_spec:
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c
index ab2d7fe210..6d4460014f 100644
--- a/lib/odbc/c_src/odbcserver.c
+++ b/lib/odbc/c_src/odbcserver.c
@@ -176,7 +176,7 @@ static void encode_column_dyn(db_column column, int column_nr,
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);
+ int i, int j, int num_param_values);
/*------------- Erlang port communication functions ----------------------*/
@@ -212,6 +212,7 @@ static db_column * alloc_column_buffer(int n);
static void free_column_buffer(db_column **columns, int n);
static void free_params(param_array **params, int cols);
static void clean_state(db_state *state);
+static SQLLEN* alloc_strlen_indptr(int n, int val);
/* ------------- Init/map/bind/retrive functions -------------------------*/
@@ -1157,7 +1158,7 @@ static db_result_msg encode_out_params(db_state *state,
break;
case SQL_C_BIT:
ei_x_encode_atom(&dynamic_buffer(state),
- ((Boolean*)values)[j]==TRUE?"true":"false");
+ ((byte*)values)[j]==TRUE?"true":"false");
break;
default:
ei_x_encode_atom(&dynamic_buffer(state), "error");
@@ -1579,37 +1580,48 @@ static void encode_data_type(SQLSMALLINT sql_type, SQLINTEGER size,
}
static Boolean decode_params(db_state *state, byte *buffer, int *index, param_array **params,
- int i, int j)
+ int i, int j, int num_param_values)
{
int erl_type, size;
long bin_size, l64;
long val;
param_array* param;
TIMESTAMP_STRUCT* ts;
+ char atomarray[MAXATOMLEN+1];
ei_get_type(buffer, index, &erl_type, &size);
param = &(*params)[i];
+ if(erl_type == ERL_ATOM_EXT) {
+ ei_decode_atom(buffer, index, atomarray);
+ if(strncmp(atomarray, "null", 4) == 0 ) {
+ param->offset += param->type.len;
+
+ if(!param->type.strlen_or_indptr_array)
+ param->type.strlen_or_indptr_array = alloc_strlen_indptr(num_param_values, param->type.len);
+
+ param->type.strlen_or_indptr_array[j] = SQL_NULL_DATA;
+ return TRUE;
+ }
+ }
+
switch (param->type.c) {
case SQL_C_CHAR:
if (binary_strings(state)) {
ei_decode_binary(buffer, index,
&(param->values.string[param->offset]), &bin_size);
param->offset += param->type.len;
- param->type.strlen_or_indptr_array[j] = SQL_NTS;
} else {
if(erl_type != ERL_STRING_EXT) {
return FALSE;
}
ei_decode_string(buffer, index, &(param->values.string[param->offset]));
param->offset += param->type.len;
- param->type.strlen_or_indptr_array[j] = SQL_NTS;
}
break;
case SQL_C_WCHAR:
ei_decode_binary(buffer, index, &(param->values.string[param->offset]), &bin_size);
param->offset += param->type.len;
- param->type.strlen_or_indptr_array[j] = SQL_NTS;
break;
case SQL_C_TYPE_TIMESTAMP:
ts = (TIMESTAMP_STRUCT*) param->values.string;
@@ -1661,9 +1673,13 @@ static Boolean decode_params(db_state *state, byte *buffer, int *index, param_ar
if((erl_type != ERL_ATOM_EXT)) {
return FALSE;
}
- ei_decode_boolean(buffer, index, &(param->values.bool[j]));
+ if (strncmp((char*)atomarray,"true",4) == 0)
+ param->values.bool[j] = TRUE;
+ else if (strncmp((char*)atomarray,"false",5) == 0)
+ param->values.bool[j] = FALSE;
+ else
+ return -1;
break;
-
default:
return FALSE;
}
@@ -2014,6 +2030,18 @@ static void clean_state(db_state *state)
nr_of_columns(state) = 0;
}
+/* Allocates and fill with default value StrLen_or_IndPtr array */
+static SQLLEN* alloc_strlen_indptr(int n, int val)
+{
+ int i;
+ SQLLEN* arr = (SQLLEN*)safe_malloc(n * sizeof(SQLLEN));
+
+ for( i=0; i < n; ++i )
+ arr[i] = val;
+
+ return arr;
+}
+
/* ------------- Init/map/bind/retrive functions ------------------------*/
/* Prepare the state for a connection */
@@ -2118,7 +2146,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
(double *)safe_malloc(num_param_values * params->type.len);
} else if(params->type.c == SQL_C_CHAR) {
params->type.strlen_or_indptr_array
- = (SQLLEN*)safe_malloc(num_param_values * sizeof(SQLINTEGER));
+ = alloc_strlen_indptr(num_param_values, SQL_NTS);
params->values.string =
(byte *)safe_malloc(num_param_values *
sizeof(byte)* params->type.len);
@@ -2136,8 +2164,8 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
params->type.len = length+1;
params->type.c = SQL_C_CHAR;
params->type.col_size = (SQLUINTEGER)length;
- params->type.strlen_or_indptr_array =
- (SQLLEN*)safe_malloc(num_param_values * sizeof(SQLINTEGER));
+ params->type.strlen_or_indptr_array
+ = alloc_strlen_indptr(num_param_values, SQL_NTS);
params->values.string =
(byte *)safe_malloc(num_param_values *
sizeof(byte)* params->type.len);
@@ -2159,8 +2187,8 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
params->type.len = (length+1)*sizeof(SQLWCHAR);
params->type.c = SQL_C_WCHAR;
params->type.col_size = (SQLUINTEGER)length;
- params->type.strlen_or_indptr_array =
- (SQLLEN*)safe_malloc(num_param_values * sizeof(SQLINTEGER));
+ params->type.strlen_or_indptr_array
+ = alloc_strlen_indptr(num_param_values, SQL_NTS);
params->values.string =
(byte *)safe_malloc(num_param_values * sizeof(byte) * params->type.len);
@@ -2201,10 +2229,10 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
case USER_BOOLEAN:
params->type.sql = SQL_BIT;
params->type.c = SQL_C_BIT;
- params->type.len = sizeof(Boolean);
+ params->type.len = sizeof(byte);
params->type.col_size = params->type.len;
params->values.bool =
- (Boolean *)safe_malloc(num_param_values * params->type.len);
+ (byte *)safe_malloc(num_param_values * params->type.len);
break;
}
params->offset = 0;
@@ -2411,7 +2439,7 @@ static param_array * bind_parameter_arrays(byte *buffer, int *index,
}
for (j = 0; j < num_param_values; j++) {
- if(!decode_params(state, buffer, index, &params, i, j)) {
+ if(!decode_params(state, buffer, index, &params, i, j, num_param_values)) {
/* An input parameter was not of the expected type */
free_params(&params, i);
return params;
diff --git a/lib/odbc/c_src/odbcserver.h b/lib/odbc/c_src/odbcserver.h
index 56b6148777..a76cedf1af 100644
--- a/lib/odbc/c_src/odbcserver.h
+++ b/lib/odbc/c_src/odbcserver.h
@@ -156,7 +156,7 @@ typedef struct {
byte *string;
SQLINTEGER *integer;
double *floating;
- Boolean *bool;
+ byte *bool;
}values;
} param_array;
diff --git a/lib/odbc/configure.in b/lib/odbc/configure.in
index 2369e16813..bec65c71bf 100644
--- a/lib/odbc/configure.in
+++ b/lib/odbc/configure.in
@@ -1,7 +1,7 @@
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2005-2010. All Rights Reserved.
+dnl Copyright Ericsson AB 2005-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
@@ -63,25 +63,11 @@ AC_PROG_CC
dnl ---------------------------------------------------------------------
dnl Special windows stuff regarding CFLAGS and details in the environment...
dnl ---------------------------------------------------------------------
-AC_MSG_CHECKING(for mixed cygwin and native VC++ environment)
-if test "X$CC" = "Xcc.sh" -a "X$host" = "Xwin32"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_VC=yes
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_VC=no
-fi
-AC_SUBST(MIXED_CYGWIN_VC)
-
+LM_WINDOWS_ENVIRONMENT
+
AC_PROG_MAKE_SET
-AC_CHECK_PROG(LD, ld.sh)
+AC_CHECK_PROGS(LD, ld.sh)
AC_CHECK_TOOL(LD, ld, '$(CC)')
AC_SUBST(LD)
diff --git a/lib/odbc/doc/src/Makefile b/lib/odbc/doc/src/Makefile
index e2f09733d0..cd9bca0a55 100644
--- a/lib/odbc/doc/src/Makefile
+++ b/lib/odbc/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
@@ -29,14 +29,6 @@ VSN=$(ODBC_VSN)
APPLICATION=odbc
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -89,32 +81,10 @@ EXTRA_FILES = $(DEFAULT_GIF_FILES) \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -128,8 +98,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif # Copy them to ../html
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -144,32 +112,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%) # We depend just to copy them to ../html
@@ -182,43 +124,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
-
-
-
diff --git a/lib/odbc/doc/src/make.dep b/lib/odbc/doc/src/make.dep
deleted file mode 100644
index d62e8dd8f0..0000000000
--- a/lib/odbc/doc/src/make.dep
+++ /dev/null
@@ -1,27 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex databases.tex error_handling.tex \
- getting_started.tex introduction.tex odbc.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: odbc_app_arc.ps
-
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index 9c6ca8a017..08763163b8 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -31,7 +31,43 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.10.11</title>
+ <section><title>ODBC 2.10.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An ODBC process should exit normally if its client exits
+ with 'shutdown'</p>
+ <p>
+ There is nothing strange about the client shutting down,
+ so the ODBC process should exit normally to avoid
+ generating a crash report for a non-problem. (Thanks to
+ Magnus Henoch)</p>
+ <p>
+ Own Id: OTP-9716</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.10.11</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/src/Makefile b/lib/odbc/src/Makefile
index b48dd768c8..7ca82d784b 100644
--- a/lib/odbc/src/Makefile
+++ b/lib/odbc/src/Makefile
@@ -108,13 +108,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXT_HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXT_HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
- $(RELSYSDIR)/ebin
+ "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/odbc/src/odbc.appup.src b/lib/odbc/src/odbc.appup.src
index f3a3af8c29..c7c83ea079 100644
--- a/lib/odbc/src/odbc.appup.src
+++ b/lib/odbc/src/odbc.appup.src
@@ -1,10 +1,8 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"2.10.10", [{restart_application, odbc}]},
- {"2.10.9", [{restart_application, odbc}]}
+ {<<"2\\.*">>, [{restart_application, odbc}]}
],
[
- {"2.10.10", [{restart_application, odbc}]},
- {"2.10.9", [{restart_application, odbc}]}
+ {<<"2\\.*">>, [{restart_application, odbc}]}
]}.
diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl
index 68497292db..9633b85cb2 100644
--- a/lib/odbc/src/odbc.erl
+++ b/lib/odbc/src/odbc.erl
@@ -451,7 +451,7 @@ init(Args) ->
%% Start the port program (a c program) that utilizes the odbc driver
case os:find_executable(?SERVERPROG, ?SERVERDIR) of
FileName when is_list(FileName)->
- Port = open_port({spawn, FileName},
+ Port = open_port({spawn, "\""++FileName++"\""},
[{packet, ?LENGTH_INDICATOR_SIZE}, binary,
exit_status]),
State = #state{listen_sockets =
@@ -748,11 +748,17 @@ handle_info({'DOWN', _Ref, _Type, _Process, normal}, State) ->
handle_info({'DOWN', _Ref, _Type, _Process, timeout}, State) ->
{stop, normal, State#state{reply_to = undefined}};
+
+handle_info({'DOWN', _Ref, _Type, _Process, shutdown}, State) ->
+ {stop, normal, State#state{reply_to = undefined}};
handle_info({'DOWN', _Ref, _Type, Process, Reason}, State) ->
{stop, {stopped, {'EXIT', Process, Reason}},
State#state{reply_to = undefined}};
-
+
+handle_info({tcp_closed, Socket}, State = #state{odbc_socket=Socket,
+ state = disconnecting}) ->
+ {stop, normal, State};
%---------------------------------------------------------------------------
%% Catch all - throws away unknown messages (This could happen by "accident"
%% so we do not want to crash, but we make a log entry as it is an
@@ -939,9 +945,11 @@ fix_params({sql_bit, InOut, Values}) ->
fix_params({'sql_timestamp', InOut, Values}) ->
NewValues =
case (catch
- lists:map(fun({{Year,Month,Day},{Hour,Minute,Second}}) ->
- {Year,Month,Day,Hour,Minute,Second}
- end, Values)) of
+ lists:map(
+ fun({{Year,Month,Day},{Hour,Minute,Second}}) ->
+ {Year,Month,Day,Hour,Minute,Second};
+ (null) -> null
+ end, Values)) of
Result ->
Result
end,
@@ -957,15 +965,15 @@ fix_inout(out) ->
fix_inout(inout) ->
?INOUT.
-string_terminate([Value| _ ] = Values) when is_list(Value)->
- case (catch
- lists:map(fun(Str) -> Str ++ [?STR_TERMINATOR] end, Values)) of
- Result ->
- Result
- end;
-string_terminate([Value| _ ] = Values) when is_binary(Value)->
- case (catch
- lists:map(fun(B) -> <<B/binary,0:16>> end, Values)) of
+string_terminate(Values) ->
+ case (catch lists:map(fun string_terminate_value/1, Values)) of
Result ->
Result
end.
+
+string_terminate_value(String) when is_list(String) ->
+ String ++ [?STR_TERMINATOR];
+string_terminate_value(Binary) when is_binary(Binary) ->
+ <<Binary/binary,0:16>>;
+string_terminate_value(null) ->
+ null.
diff --git a/lib/odbc/test/Makefile b/lib/odbc/test/Makefile
index bc6449242e..84551f0eb1 100644
--- a/lib/odbc/test/Makefile
+++ b/lib/odbc/test/Makefile
@@ -101,8 +101,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
release_docs_spec:
diff --git a/lib/odbc/test/odbc_test_lib.erl b/lib/odbc/test/odbc_test_lib.erl
index a8439d5fb6..e814cd2aca 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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 @@
unique_table_name() ->
lists:reverse(lists:foldl(fun($@, Acc) -> [$t, $A |Acc] ;
+ ($-,Acc) -> Acc;
(X, Acc) -> [X |Acc] end,
[], atom_to_list(node()))).
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 120ed9ee3d..3bb2fe5bce 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.10.11
+ODBC_VSN = 2.10.13
diff --git a/lib/orber/COSS/CosNaming/Makefile b/lib/orber/COSS/CosNaming/Makefile
index 28b4d9cacc..a61fcd08a6 100644
--- a/lib/orber/COSS/CosNaming/Makefile
+++ b/lib/orber/COSS/CosNaming/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
@@ -113,7 +113,7 @@ debug:
@${MAKE} TYPE=debug
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC)
@@ -141,11 +141,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/COSS/CosNaming
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILE) $(RELSYSDIR)/COSS/CosNaming
- $(INSTALL_DATA) $(GEN_FILES) $(RELSYSDIR)/COSS/CosNaming
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/COSS/CosNaming"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILE) "$(RELSYSDIR)/COSS/CosNaming"
+ $(INSTALL_DATA) $(GEN_FILES) "$(RELSYSDIR)/COSS/CosNaming"
release_docs_spec:
diff --git a/lib/orber/c_src/Makefile.in b/lib/orber/c_src/Makefile.in
index 56f0d57545..5953d41ff3 100644
--- a/lib/orber/c_src/Makefile.in
+++ b/lib/orber/c_src/Makefile.in
@@ -89,23 +89,23 @@ include $(ERL_TOP)/make/otp_release_targets.mk
ifeq ($(findstring win32,$(TARGET)),win32)
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/src
- $(INSTALL_DIR) $(RELSYSDIR)/priv/include
- $(INSTALL_PROGRAM) $(CC_FILES) $(RELSYSDIR)/priv/src
- $(INSTALL_PROGRAM) $(HH_FILES) $(RELSYSDIR)/priv/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/include"
+ $(INSTALL_PROGRAM) $(CC_FILES) "$(RELSYSDIR)/priv/src"
+ $(INSTALL_PROGRAM) $(HH_FILES) "$(RELSYSDIR)/priv/include"
else
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/priv/src
- $(INSTALL_DIR) $(RELSYSDIR)/priv/include
- $(INSTALL_PROGRAM) $(CC_FILES) $(RELSYSDIR)/priv/src
- $(INSTALL_PROGRAM) $(HH_FILES) $(RELSYSDIR)/priv/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/include"
+ $(INSTALL_PROGRAM) $(CC_FILES) "$(RELSYSDIR)/priv/src"
+ $(INSTALL_PROGRAM) $(HH_FILES) "$(RELSYSDIR)/priv/include"
else
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/src
- $(INSTALL_DIR) $(RELSYSDIR)/priv/include
- $(INSTALL_DATA) $(CC_FILES) $(RELSYSDIR)/priv/src
- $(INSTALL_DATA) $(HH_FILES) $(RELSYSDIR)/priv/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/include"
+ $(INSTALL_DATA) $(CC_FILES) "$(RELSYSDIR)/priv/src"
+ $(INSTALL_DATA) $(HH_FILES) "$(RELSYSDIR)/priv/include"
endif
endif
diff --git a/lib/orber/doc/src/Makefile b/lib/orber/doc/src/Makefile
index b8e26d5ba3..c429c1d80b 100644
--- a/lib/orber/doc/src/Makefile
+++ b/lib/orber/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
@@ -28,14 +28,6 @@ VSN=$(ORBER_VSN)
APPLICATION=orber
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -128,32 +120,10 @@ EXTRA_FILES = summary.html.src \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -167,8 +137,6 @@ $(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -184,35 +152,6 @@ clean clean_docs:
rm -f errs core *~
rm -f $(JD_HTML) $(JD_PACK)
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(INTERNAL_HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
- rm -f $(JD_HTML) $(JD_PACK)
-
-endif
-
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -224,42 +163,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/orber/doc/src/ch_install.xml b/lib/orber/doc/src/ch_install.xml
index dde4bf4006..89c0e19173 100644
--- a/lib/orber/doc/src/ch_install.xml
+++ b/lib/orber/doc/src/ch_install.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>2010</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -394,84 +394,16 @@ nodeB@hostB> orber:start().
<cell align="left" valign="middle">The same as <c>iiop_ssl_port</c></cell>
</row>
<row>
- <cell align="left" valign="middle">ssl_server_cacertfile</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_certfile</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_verify</cell>
- <cell align="left" valign="middle">0 | 1 | 2</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_depth</cell>
- <cell align="left" valign="middle">integer()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_password</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_keyfile</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_ciphers</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_cachetimeout</cell>
- <cell align="left" valign="middle">integer() | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
+ <cell align="left" valign="middle">ssl_server_options</cell>
+ <cell align="left" valign="middle">list()</cell>
+ <cell align="left" valign="middle">See the <seealso marker="ssl:ssl">SSL application</seealso>
+ for valid options.</cell>
</row>
<row>
- <cell align="left" valign="middle">ssl_client_cacertfile</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_certfile</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_verify</cell>
- <cell align="left" valign="middle">0 | 1 | 2</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_depth</cell>
- <cell align="left" valign="middle">integer()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_password</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_keyfile</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_ciphers</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_cachetimeout</cell>
- <cell align="left" valign="middle">integer() | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
+ <cell align="left" valign="middle">ssl_client_options</cell>
+ <cell align="left" valign="middle">list()</cell>
+ <cell align="left" valign="middle">See the <seealso marker="ssl:ssl">SSL application</seealso>
+ for valid options.</cell>
</row>
<row>
<cell align="left" valign="middle">iiop_ssl_out_keepalive</cell>
@@ -698,40 +630,20 @@ nodeB@hostB> orber:start().
<item>If set, the value must be an integer greater than zero or
<c>{local, DefaultNATPort, [{Port, NATPort}]}</c>. See also
<seealso marker="ch_install#firewall">Firewall Configuration</seealso>.</item>
- <tag><em>ssl_server_cacertfile</em></tag>
- <item>the file path to a server side CA certificate.</item>
- <tag><em>ssl_server_certfile</em></tag>
- <item>The path to a file containing a chain of PEM encoded certificates.</item>
- <tag><em>ssl_server_verify</em></tag>
- <item>The type of verification used by SSL during authentication of the
- other peer for incoming calls.</item>
- <tag><em>ssl_server_depth</em></tag>
- <item>The SSL verification depth for outgoing calls.</item>
- <tag><em>ssl_server_password</em></tag>
- <item>The server side key string.</item>
- <tag><em>ssl_server_keyfile</em></tag>
- <item>The file path to a server side key.</item>
- <tag><em>ssl_server_ciphers</em></tag>
- <item>The server side cipher string.</item>
- <tag><em>ssl_server_cachetimeout</em></tag>
- <item>The server side cache timeout.</item>
- <tag><em>ssl_client_cacertfile</em></tag>
- <item>The file path to a client side CA certificate.</item>
- <tag><em>ssl_client_certfile</em></tag>
- <item>The path to a file containing a chain of PEM encoded certificates.</item>
- <tag><em>ssl_client_verify</em></tag>
- <item>The type of verification used by SSL during authentication of the
- other peer for outgoing calls.</item>
- <tag><em>ssl_client_depth</em></tag>
- <item>The SSL verification depth for incoming calls.</item>
- <tag><em>ssl_client_password</em></tag>
- <item>The client side key string.</item>
- <tag><em>ssl_client_keyfile</em></tag>
- <item>The file path to a client side key.</item>
- <tag><em>ssl_client_ciphers</em></tag>
- <item>The client side cipher string.</item>
- <tag><em>ssl_client_cachetimeout</em></tag>
- <item>The client side cache timeout.</item>
+ <tag><em>ssl_server_options</em></tag>
+ <item>A list of the SSL options when Orber is the server.
+ In general it's just to remove the 'ssl_server_' prefix from the old options,
+ i.e. <c>ssl_server_verify</c> will just be <c>verify</c> in this option list.
+ See the <seealso marker="ssl:ssl">SSL application</seealso> for the correct list of possible
+ options and their values.
+ </item>
+ <tag><em>ssl_client_options</em></tag>
+ <item>A list of the SSL options when Orber is the client.
+ In general it's just to remove the <c>ssl_client_</c> prefix from the old options,
+ i.e. <c>ssl_client_depth</c> will just be <c>depth</c> in this option list.
+ See the <seealso marker="ssl:ssl">SSL application</seealso> for the correct list of possible
+ options and their values.
+ </item>
<tag><em>iiop_ssl_out_keepalive</em></tag>
<item>Enables periodic transmission on a connected socket, when no other
data is being exchanged. If the other end does not respond, the
diff --git a/lib/orber/doc/src/ch_security.xml b/lib/orber/doc/src/ch_security.xml
index 938025a629..a25a8a5052 100644
--- a/lib/orber/doc/src/ch_security.xml
+++ b/lib/orber/doc/src/ch_security.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>1999</year><year>2009</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -55,40 +55,15 @@
<section>
<title>Configurations when Orber is Used on the Server Side</title>
- <p>The following three configuration variables can be used to configure Orber's SSL
- behavior on the server side.</p>
+ <p>There is a variable to conficure Orber's SSL behavior on the server side.</p>
<list type="bulleted">
- <item><em>ssl_server_certfile</em> - which is a path to a file containing a
- chain of PEM encoded certificates for the Orber domain as server.</item>
- <item><em>ssl_server_cacertfile</em> - which is a path to a file containing
- a chain of PEM encoded certificates for the Orber domain as server.</item>
- <item><em>ssl_server_verify</em> - which specifies type of verification:
- 0 = do not verify peer; 1 = verify peer, verify client once,
- 2 = verify peer, verify client once, fail if no peer certificate.
- The default value is 0.</item>
- <item><em>ssl_server_depth</em> - which specifies verification depth, i.e.
- how far in a chain of certificates the verification process shall
- proceed before the verification is considered successful. The default
- value is 1. </item>
- <item><em>ssl_server_keyfile</em> - which is a path to a file containing a
- PEM encoded key for the Orber domain as server.</item>
- <item><em>ssl_server_password</em> - only used if the private keyfile is
- password protected.</item>
- <item><em>ssl_server_ciphers</em> - which is string of ciphers as a colon
- separated list of ciphers.</item>
- <item><em>ssl_server_cachetimeout</em> - which is the session cache timeout
- in seconds.</item>
+ <item><em>ssl_server_options</em> - which is a list of options to ssl.
+ See the <seealso marker="ssl:ssl">SSL</seealso> application for further
+ descriptions on these options.</item>
</list>
- <p>There also exist a number of API functions for accessing the values of these variables:</p>
+ <p>There also exist an API function for accessing the value of this variable:</p>
<list type="bulleted">
- <item>orber:ssl_server_certfile/0</item>
- <item>orber:ssl_server_cacertfile/0</item>
- <item>orber:ssl_server_verify/0</item>
- <item>orber:ssl_server_depth/0</item>
- <item>orber:ssl_server_keyfile/0</item>
- <item>orber:ssl_server_password/0</item>
- <item>orber:ssl_server_ciphers/0</item>
- <item>orber:ssl_server_cachetimeout/0</item>
+ <item>orber:ssl_server_options/0</item>
</list>
</section>
@@ -97,50 +72,22 @@
<p>When the Orber enabled application is the client side in the secure connection the
different configurations can be set per client process instead and not for the whole domain
as for incoming calls.</p>
- <p>One can use configuration variables to set default values for the domain but they can be changed
- per client process. Below is the list of client configuration variables.</p>
+ <p>There is a variable to set default values for the domain but they can be changed
+ per client process.</p>
<list type="bulleted">
- <item><em>ssl_client_certfile</em> - which is a path to a file containing a
- chain of PEM encoded certificates used in outgoing calls in the current
- process.</item>
- <item><em>ssl_client_cacertfile</em> - which is a path to a file containing a
- chain of PEM encoded CA certificates used in outgoing calls in the
- current process.</item>
- <item><em>ssl_client_verify</em> - which specifies type of verification:
- 0 = do not verify peer; 1 = verify peer, verify client once,
- 2 = verify peer, verify client once, fail if no peer certificate.
- The default value is 0.</item>
- <item><em>ssl_client_depth</em> - which specifies verification depth, i.e.
- how far in a chain of certificates the verification process shall proceed
- before the verification is considered successful. The default value is 1. </item>
- <item><em>ssl_client_keyfile</em> - which is a path to a file containing a
- PEM encoded key when Orber act as client side ORB.</item>
- <item><em>ssl_client_password</em> - only used if the private keyfile is
- password protected.</item>
- <item><em>ssl_client_ciphers</em> - which is string of ciphers as a colon
- separated list of ciphers.</item>
- <item><em>ssl_client_cachetimeout</em> - which is the session cache timeout
- in seconds.</item>
+ <item><em>ssl_client_options</em> - which is a list of options to ssl.
+ See the <seealso marker="ssl:ssl">SSL</seealso> application for further
+ descriptions on these options.</item>
</list>
- <p>There also exist a number of API functions for accessing and changing the values of this
- variables in the client processes.</p>
- <p>Access functions:</p>
+ <p>There also exist two API functions for accessing and changing the values of this
+ variable in the client processes.</p>
+ <p>Access function:</p>
<list type="bulleted">
- <item>orber:ssl_client_certfile/0</item>
- <item>orber:ssl_client_cacertfile/0</item>
- <item>orber:ssl_client_verify/0</item>
- <item>orber:ssl_client_depth/0</item>
- <item>orber:ssl_client_keyfile/0</item>
- <item>orber:ssl_client_password/0</item>
- <item>orber:ssl_client_ciphers/0</item>
- <item>orber:ssl_client_cachetimeout/0</item>
+ <item>orber:ssl_client_options/0</item>
</list>
- <p>Modify functions:</p>
+ <p>Modify function:</p>
<list type="bulleted">
- <item>orber:set_ssl_client_certfile/1</item>
- <item>orber:set_ssl_client_cacertfile/1</item>
- <item>orber:set_ssl_client_verify/1</item>
- <item>orber:set_ssl_client_depth/1</item>
+ <item>orber:set_ssl_client_options/1</item>
</list>
</section>
</section>
diff --git a/lib/orber/doc/src/corba.xml b/lib/orber/doc/src/corba.xml
index cae0e09b0b..08ec555f94 100644
--- a/lib/orber/doc/src/corba.xml
+++ b/lib/orber/doc/src/corba.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>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -221,8 +221,7 @@ Example:
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>Object = #objref</v>
</type>
@@ -287,8 +286,7 @@ Example:
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>Object = #objref</v>
</type>
@@ -319,8 +317,7 @@ Example:
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>ObjectId = string()</v>
</type>
@@ -360,8 +357,7 @@ Example:
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>Object = #objref</v>
</type>
diff --git a/lib/orber/doc/src/corba_object.xml b/lib/orber/doc/src/corba_object.xml
index e0f9a9f503..ef440f1a2d 100644
--- a/lib/orber/doc/src/corba_object.xml
+++ b/lib/orber/doc/src/corba_object.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -75,8 +75,7 @@
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>Return = boolean() | {'EXCEPTION', E}</v>
</type>
@@ -117,8 +116,7 @@
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>Return = boolean() | {'EXCEPTION', E}</v>
</type>
@@ -149,8 +147,7 @@
<v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
<v>Interface = string()</v>
<v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
+ <v>Key = ssl_client_options</v>
<v>Value = allowed value associated with the given key</v>
<v>Return = boolean() | {'EXCEPTION', E}</v>
</type>
diff --git a/lib/orber/doc/src/make.dep b/lib/orber/doc/src/make.dep
deleted file mode 100644
index cf5aad747d..0000000000
--- a/lib/orber/doc/src/make.dep
+++ /dev/null
@@ -1,62 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: CosNaming.tex CosNaming_BindingIterator.tex \
- CosNaming_NamingContext.tex CosNaming_NamingContextExt.tex \
- Module_Interface.tex any.tex book.tex ch_contents.tex \
- ch_debugging.tex ch_exceptions.tex \
- ch_idl_to_erlang_mapping.tex ch_ifr.tex ch_install.tex \
- ch_interceptors.tex ch_introduction.tex ch_naming_service.tex \
- ch_orber_kernel.tex ch_orberweb.tex ch_security.tex \
- ch_stubs.tex corba.tex corba_object.tex example_part.tex \
- fixed.tex interceptors.tex intro_part.tex \
- lname.tex lname_component.tex orber.tex orber_acl.tex \
- orber_diagnostics.tex orber_ifr.tex orber_tc.tex \
- ref_man.tex tools_debugging_part.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ch_contents.tex: ../../../../system/doc/definitions/term.defs
-
-ch_idl_to_erlang_mapping.tex: ../../../../system/doc/definitions/term.defs
-
-ch_install.tex: ../../../../system/doc/definitions/term.defs
-
-ch_introduction.tex: ../../../../system/doc/definitions/term.defs
-
-ch_naming_service.tex: ../../../../system/doc/definitions/term.defs
-
-ch_orber_kernel.tex: ../../../../system/doc/definitions/term.defs
-
-orber_ifr.tex: ../../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: firewall_nat.ps
-
-book.dvi: interceptor_operations.ps
-
-book.dvi: dependent.ps orbs.ps
-
-book.dvi: name.ps
-
-book.dvi: iiop.ps theORB.ps
-
-book.dvi: dataframe1.ps dataframe2.ps dataframe3.ps \
- dataframe4.ps dataframe5.ps dataframe6.ps \
- dataframe7.ps dataframe8.ps menuframe.ps
-
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index c8477d9252..72cd808d20 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -32,7 +32,73 @@
<file>notes.xml</file>
</header>
- <section><title>Orber 3.6.22</title>
+ <section><title>Orber 3.6.24</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix number of arguments in orber dbg printout</p>
+ <p>
+ Own Id: OTP-9887</p>
+ </item>
+ <item>
+ <p> The descriptions of <c>ssl_server_options</c> and
+ <c>ssl_client_options</c> are corrected.<br/> Seq. Id:
+ seq12018 </p>
+ <p>
+ Own Id: OTP-9966 Aux Id: OTP-9773 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Orber 3.6.23</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Remove usage of ssl:seed/1 in orber test cases. </p>
+ <p>
+ Own Id: OTP-9728</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p> The SSL option handling has been changed. There are
+ now two new orber options <c>ssl_server_options</c> and
+ <c>ssl_client_options</c> which takes a list of options
+ to the socket. </p> <p> The old options are now
+ deprecated and removed from the documentation but they
+ can still be used for backward compatibility as long as
+ the two new options not are used. </p> <p> If
+ <c>ssl_server_options</c> and <c>ssl_client_options</c>
+ contain an TCP option that <c>orber</c> needs to set to a
+ specific value it will be skipped and a warning will be
+ written to the error_log. </p>
+ <p>
+ Own Id: OTP-9773 Aux Id: seq11932 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Orber 3.6.22</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/orber/doc/src/orber.xml b/lib/orber/doc/src/orber.xml
index 5e38e4cf9f..35e9f57008 100644
--- a/lib/orber/doc/src/orber.xml
+++ b/lib/orber/doc/src/orber.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>
@@ -356,7 +356,7 @@
<v>Type = normal | ssl</v>
<v>Port = integer() > 0</v>
<v>ConfigurationParameters = [{Key, Value}]</v>
- <v>Key = flags | iiop_in_connection_timeout | iiop_max_fragments | iiop_max_in_requests | interceptors | iiop_port | iiop_ssl_port</v>
+ <v>Key = flags | iiop_in_connection_timeout | iiop_max_fragments | iiop_max_in_requests | interceptors | iiop_port | iiop_ssl_port | ssl_server_options</v>
<v>Value = as described in the User's Guide</v>
<v>Result = {ok, Ref} | {error, Reason} | {'EXCEPTION', #'BAD_PARAM'{}}</v>
<v>Ref = #Ref</v>
@@ -378,7 +378,7 @@
counterparts (See the
<seealso marker="ch_install#config">Configuration</seealso> chapter
in the User's Guide).
- But the following parameters there are a few restrictions:</p>
+ But for the following parameters there are a few restrictions:</p>
<list type="bulleted">
<item><em>flags</em> - currently it is only possible to override the global
setting for the <c>Use Current Interface in IOR</c> and
@@ -450,92 +450,32 @@
</desc>
</func>
<func>
- <name>ssl_server_certfile() -> string()</name>
- <fsummary>Display the path to the server certificate</fsummary>
+ <name>ssl_server_options() -> list()</name>
+ <fsummary>Display the SSL server options</fsummary>
<desc>
- <p>This function returns a path to a file containing a chain of PEM encoded
- certificates for the Orber domain as server.
+ <p>This function returns the list of SSL options set for the Orber domain as server.
This is configured by setting the application variable
- <em>ssl_server_certfile</em>.</p>
+ <em>ssl_server_options</em>.</p>
</desc>
</func>
<func>
- <name>ssl_client_certfile() -> string()</name>
- <fsummary>Display the path to the client certificate</fsummary>
+ <name>ssl_client_options() -> list()</name>
+ <fsummary>Display the SSL client options</fsummary>
<desc>
- <p>This function returns a path to a file containing a chain of PEM encoded
- certificates used in outgoing calls in the current process.
+ <p>This function returns the list of SSL options used in outgoing calls in the current process.
The default value is configured by setting the application variable
- <em>ssl_client_certfile</em>.</p>
+ <em>ssl_client_options</em>.</p>
</desc>
</func>
<func>
- <name>set_ssl_client_certfile(Path) -> ok</name>
- <fsummary>Set the value of the client certificate</fsummary>
+ <name>set_ssl_client_options(Options) -> ok</name>
+ <fsummary>Set the SSL options for the client</fsummary>
<type>
- <v>Path = string()</v>
+ <v>Options = list()</v>
</type>
<desc>
- <p>This function takes a path to a file containing a chain of PEM encoded
- certificates as parameter and sets it for the current process.</p>
- </desc>
- </func>
- <func>
- <name>ssl_server_verify() -> 0 | 1 | 2</name>
- <fsummary>Display the SSL verification type for incoming calls</fsummary>
- <desc>
- <p>This function returns the type of verification used by SSL during authentication of the other
- peer for incoming calls.
- It is configured by setting the application variable
- <em>ssl_server_verify</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_client_verify() -> 0 | 1 | 2</name>
- <fsummary>Display the SSL verification type for outgoing calls</fsummary>
- <desc>
- <p>This function returns the type of verification used by SSL during authentication of the other
- peer for outgoing calls.
- The default value is configured by setting the application variable
- <em>ssl_client_verify</em>.</p>
- </desc>
- </func>
- <func>
- <name>set_ssl_client_verify(Value) -> ok</name>
- <fsummary>Set the value of the SSL verification type for outgoing calls</fsummary>
- <type>
- <v>Value = 0 | 1 | 2</v>
- </type>
- <desc>
- <p>This function sets the SSL verification type for the other peer of outgoing calls.</p>
- </desc>
- </func>
- <func>
- <name>ssl_server_depth() -> int()</name>
- <fsummary>Display the SSL verification depth for incoming calls</fsummary>
- <desc>
- <p>This function returns the SSL verification depth for incoming calls.
- It is configured by setting the application variable
- <em>ssl_server_depth</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_client_depth() -> int()</name>
- <fsummary>Display the SSL verification depth for outgoing calls</fsummary>
- <desc>
- <p>This function returns the SSL verification depth for outgoing calls.
- The default value is configured by setting the application variable
- <em>ssl_client_depth</em>.</p>
- </desc>
- </func>
- <func>
- <name>set_ssl_client_depth(Depth) -> ok</name>
- <fsummary>Sets the value of the SSL verification depth for outgoing calls</fsummary>
- <type>
- <v>Depth = int()</v>
- </type>
- <desc>
- <p>This function sets the SSL verification depth for the other peer of outgoing calls.</p>
+ <p>This function takes a list of SSL options as parameter and sets
+ it for the current process.</p>
</desc>
</func>
<func>
diff --git a/lib/orber/examples/Stack/Makefile b/lib/orber/examples/Stack/Makefile
index ccb65038a3..b03d7c3b86 100644
--- a/lib/orber/examples/Stack/Makefile
+++ b/lib/orber/examples/Stack/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
@@ -96,7 +96,7 @@ ERL_COMPILE_FLAGS += \
debug opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES)
+ rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) IDL-GENERATED
rm -f errs core *~
docs:
@@ -118,8 +118,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/Stack
- $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(CPP_FILES) $(IDL_FILES) $(RELSYSDIR)/examples/Stack
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/Stack"
+ $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(CPP_FILES) $(IDL_FILES) "$(RELSYSDIR)/examples/Stack"
release_docs_spec:
diff --git a/lib/orber/java_src/Orber/Makefile b/lib/orber/java_src/Orber/Makefile
index 49da975a8b..4e52ed3635 100644
--- a/lib/orber/java_src/Orber/Makefile
+++ b/lib/orber/java_src/Orber/Makefile
@@ -63,8 +63,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/java_src/Orber
- $(INSTALL_DATA) $(JAVA_FILES) $(RELSYSDIR)/java_src/Orber
+ $(INSTALL_DIR) "$(RELSYSDIR)/java_src/Orber"
+ $(INSTALL_DATA) $(JAVA_FILES) "$(RELSYSDIR)/java_src/Orber"
release_docs_spec:
diff --git a/lib/orber/priv/Makefile b/lib/orber/priv/Makefile
index 2847727035..7957f7bbf0 100755..100644
--- a/lib/orber/priv/Makefile
+++ b/lib/orber/priv/Makefile
@@ -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
@@ -58,8 +58,8 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(HELP_FILES) $(HTML_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(HELP_FILES) $(HTML_FILES) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/orber/priv/blank.html b/lib/orber/priv/blank.html
index 44e86908a0..44e86908a0 100755..100644
--- a/lib/orber/priv/blank.html
+++ b/lib/orber/priv/blank.html
diff --git a/lib/orber/priv/info_frames.html b/lib/orber/priv/info_frames.html
index 75456a67a4..75456a67a4 100755..100644
--- a/lib/orber/priv/info_frames.html
+++ b/lib/orber/priv/info_frames.html
diff --git a/lib/orber/priv/main_frame.html b/lib/orber/priv/main_frame.html
index 056a92812e..056a92812e 100755..100644
--- a/lib/orber/priv/main_frame.html
+++ b/lib/orber/priv/main_frame.html
diff --git a/lib/orber/priv/orber.tool b/lib/orber/priv/orber.tool
index 910a7d7e45..910a7d7e45 100755..100644
--- a/lib/orber/priv/orber.tool
+++ b/lib/orber/priv/orber.tool
diff --git a/lib/orber/priv/orber_help.txt b/lib/orber/priv/orber_help.txt
index a6580dc30a..a6580dc30a 100755..100644
--- a/lib/orber/priv/orber_help.txt
+++ b/lib/orber/priv/orber_help.txt
diff --git a/lib/orber/priv/start_info.html b/lib/orber/priv/start_info.html
index 0ad521c90a..0ad521c90a 100755..100644
--- a/lib/orber/priv/start_info.html
+++ b/lib/orber/priv/start_info.html
diff --git a/lib/orber/src/Makefile b/lib/orber/src/Makefile
index ed62c94b98..a57d6d948b 100644
--- a/lib/orber/src/Makefile
+++ b/lib/orber/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
@@ -212,7 +212,7 @@ debug:
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
rm -f errs core *~
$(APP_TARGET): $(APP_SRC) ../vsn.mk
@@ -254,12 +254,12 @@ 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) $(ERL_FILES) $(YRL_FILE) $(GEN_HRL_FILES_LOC) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(GEN_HRL_FILES_EXT) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(GEN_HRL_FILES_LOC) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(GEN_HRL_FILES_EXT) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/orber/src/orber.erl b/lib/orber/src/orber.erl
index 386c07d227..5ab240e046 100644
--- a/lib/orber/src/orber.erl
+++ b/lib/orber/src/orber.erl
@@ -36,6 +36,7 @@
-export([start/0, start/1, stop/0, install/1, install/2, orber_nodes/0, iiop_port/0,
domain/0, iiop_ssl_port/0, iiop_out_ports/0, iiop_out_ports_random/0,
iiop_out_ports_attempts/0,
+ ssl_server_options/0, ssl_client_options/0, set_ssl_client_options/1,
ssl_server_certfile/0, ssl_client_certfile/0, set_ssl_client_certfile/1,
ssl_server_verify/0, ssl_client_verify/0, set_ssl_client_verify/1,
ssl_server_depth/0, ssl_client_depth/0, set_ssl_client_depth/1,
@@ -524,6 +525,15 @@ iiop_ssl_port() ->
nat_iiop_ssl_port() ->
orber_env:nat_iiop_ssl_port().
+ssl_server_options() ->
+ orber_env:ssl_server_options().
+
+ssl_client_options() ->
+ orber_env:ssl_client_options().
+
+set_ssl_client_options(Value) ->
+ orber_env:set_ssl_client_options(Value).
+
ssl_server_certfile() ->
orber_env:ssl_server_certfile().
diff --git a/lib/orber/src/orber_diagnostics.erl b/lib/orber/src/orber_diagnostics.erl
index c115d79524..3ab55c448d 100644
--- a/lib/orber/src/orber_diagnostics.erl
+++ b/lib/orber/src/orber_diagnostics.erl
@@ -2,7 +2,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
diff --git a/lib/orber/src/orber_env.erl b/lib/orber/src/orber_env.erl
index d80edb4ee0..8758450104 100644
--- a/lib/orber/src/orber_env.erl
+++ b/lib/orber/src/orber_env.erl
@@ -2,7 +2,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
@@ -20,7 +20,7 @@
%%
%%-----------------------------------------------------------------
%% File: orber_env.erl
-%%
+%%
%% Description:
%% Handling environment parameters for Orber.
%%
@@ -49,20 +49,22 @@
iiop_max_in_connections/0, iiop_backlog/0, objectkeys_gc_time/0,
get_ORBInitRef/0, get_ORBDefaultInitRef/0, get_interceptors/0,
get_local_interceptors/0, get_cached_interceptors/0,
- set_interceptors/1, is_lightweight/0, get_lightweight_nodes/0, secure/0,
+ set_interceptors/1, is_lightweight/0, get_lightweight_nodes/0, secure/0,
iiop_ssl_backlog/0, iiop_ssl_port/0, nat_iiop_ssl_port/0, nat_iiop_ssl_port/1,
+ ssl_server_options/0, ssl_client_options/0, set_ssl_client_options/1,
ssl_server_certfile/0, ssl_client_certfile/0, set_ssl_client_certfile/1,
ssl_server_verify/0, ssl_client_verify/0, set_ssl_client_verify/1,
ssl_server_depth/0, ssl_client_depth/0, set_ssl_client_depth/1,
- ssl_server_cacertfile/0, ssl_client_cacertfile/0,
+ ssl_server_cacertfile/0, ssl_client_cacertfile/0,
set_ssl_client_cacertfile/1, ssl_client_password/0,
ssl_server_password/0, ssl_client_keyfile/0, ssl_server_keyfile/0,
ssl_client_ciphers/0, ssl_server_ciphers/0, ssl_client_cachetimeout/0,
- ssl_server_cachetimeout/0, get_flags/0, typechecking/0,
+ ssl_server_cachetimeout/0,
+ get_flags/0, typechecking/0,
exclude_codeset_ctx/0, exclude_codeset_component/0, partial_security/0,
use_CSIv2/0, use_FT/0, ip_version/0, light_ifr/0, bidir_context/0,
get_debug_level/0, getaddrstr/2, addr2str/1, iiop_packet_size/0,
- iiop_ssl_ip_address_local/0, ip_address_local/0, iiop_in_keepalive/0,
+ iiop_ssl_ip_address_local/0, ip_address_local/0, iiop_in_keepalive/0,
iiop_out_keepalive/0, iiop_ssl_in_keepalive/0, iiop_ssl_out_keepalive/0,
iiop_ssl_accept_timeout/0, ssl_generation/0]).
@@ -87,38 +89,39 @@
[flags, iiop_port, nat_iiop_port, iiop_out_ports, domain, ip_address,
nat_ip_address, giop_version, iiop_timeout, iiop_connection_timeout,
iiop_setup_connection_timeout, iiop_in_connection_timeout, iiop_acl,
- iiop_max_fragments, iiop_max_in_requests, iiop_max_in_connections,
+ iiop_max_fragments, iiop_max_in_requests, iiop_max_in_connections,
iiop_backlog, objectkeys_gc_time, orbInitRef, orbDefaultInitRef,
interceptors, local_interceptors, lightweight, ip_address_local,
- secure, iiop_ssl_ip_address_local, iiop_ssl_backlog,
- iiop_ssl_port, nat_iiop_ssl_port, ssl_server_certfile,
- ssl_client_certfile, ssl_server_verify, ssl_client_verify, ssl_server_depth,
- ssl_client_depth, ssl_server_cacertfile, ssl_client_cacertfile,
- ssl_client_password, ssl_server_password, ssl_client_keyfile,
- ssl_server_keyfile, ssl_client_ciphers, ssl_server_ciphers,
+ secure, iiop_ssl_ip_address_local, iiop_ssl_backlog,
+ iiop_ssl_port, nat_iiop_ssl_port, ssl_server_certfile,
+ ssl_client_certfile, ssl_server_verify, ssl_client_verify, ssl_server_depth,
+ ssl_client_depth, ssl_server_cacertfile, ssl_client_cacertfile,
+ ssl_client_password, ssl_server_password, ssl_client_keyfile,
+ ssl_server_keyfile, ssl_client_ciphers, ssl_server_ciphers,
ssl_client_cachetimeout, ssl_server_cachetimeout, orber_debug_level,
iiop_packet_size, iiop_in_keepalive, iiop_out_keepalive,
- iiop_ssl_in_keepalive, iiop_ssl_out_keepalive, iiop_ssl_accept_timeout]).
+ iiop_ssl_in_keepalive, iiop_ssl_out_keepalive, iiop_ssl_accept_timeout,
+ ssl_server_options, ssl_client_options]).
%% The 'flags' parameter must be first in the list.
%-define(ENV_KEYS,
-% [{flags, ?ORB_ENV_INIT_FLAGS}, {iiop_port, 4001}, nat_iiop_port,
-% {iiop_out_ports, 0}, {domain, "ORBER"}, ip_address, nat_ip_address,
-% {giop_version, {1, 1}}, {iiop_timeout, infinity},
-% {iiop_connection_timeout, infinity}, {iiop_setup_connection_timeout, infinity},
+% [{flags, ?ORB_ENV_INIT_FLAGS}, {iiop_port, 4001}, nat_iiop_port,
+% {iiop_out_ports, 0}, {domain, "ORBER"}, ip_address, nat_ip_address,
+% {giop_version, {1, 1}}, {iiop_timeout, infinity},
+% {iiop_connection_timeout, infinity}, {iiop_setup_connection_timeout, infinity},
% {iiop_in_connection_timeout, infinity}, {iiop_acl, []},
-% {iiop_max_fragments, infinity}, {iiop_max_in_requests, infinity},
-% {iiop_max_in_connections, infinity}, {iiop_backlog, 5},
-% {objectkeys_gc_time, infinity},
+% {iiop_max_fragments, infinity}, {iiop_max_in_requests, infinity},
+% {iiop_max_in_connections, infinity}, {iiop_backlog, 5},
+% {objectkeys_gc_time, infinity},
% {orbInitRef, undefined}, {orbDefaultInitRef, undefined},
% {interceptors, false}, {local_interceptors, false}, {lightweight, false},
-% {secure, no}, {iiop_ssl_backlog, 5}, {iiop_ssl_port, 4002},
+% {secure, no}, {iiop_ssl_backlog, 5}, {iiop_ssl_port, 4002},
% nat_iiop_ssl_port, {ssl_server_certfile, []}, {ssl_client_certfile, []},
-% {ssl_server_verify, 0}, {ssl_client_verify, 0}, {ssl_server_depth, 1},
-% {ssl_client_depth, 1}, {ssl_server_cacertfile, []},
+% {ssl_server_verify, 0}, {ssl_client_verify, 0}, {ssl_server_depth, 1},
+% {ssl_client_depth, 1}, {ssl_server_cacertfile, []},
% {ssl_client_cacertfile, []}, {ssl_client_password, []},
-% {ssl_server_password, []}, {ssl_client_keyfile, []},
-% {ssl_server_keyfile, []}, {ssl_client_ciphers, []},
+% {ssl_server_password, []}, {ssl_client_keyfile, []},
+% {ssl_server_keyfile, []}, {ssl_client_ciphers, []},
% {ssl_server_ciphers, []}, {ssl_client_cachetimeout, infinity},
% {ssl_server_cachetimeout, infinity}, {orber_debug_level, 0}]).
@@ -129,33 +132,33 @@
%%-----------------------------------------------------------------
%% External functions
-%%-----------------------------------------------------------------
%%-----------------------------------------------------------------
-%% function :
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%%-----------------------------------------------------------------
+%% function :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
start(Opts) ->
gen_server:start_link({local, orber_env}, ?MODULE, Opts, []).
%%-----------------------------------------------------------------
%% function : get_keys
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
get_keys() ->
?ENV_KEYS.
%%-----------------------------------------------------------------
%% function : get_env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
get_env(Key) when is_atom(Key) ->
case catch ets:lookup(?ENV_DB, Key) of
@@ -164,13 +167,13 @@ get_env(Key) when is_atom(Key) ->
_ ->
undefined
end.
-
+
%%-----------------------------------------------------------------
%% function : get_env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
set_env(Key, Value) when is_atom(Key) ->
case catch ets:insert(?ENV_DB, #parameters{key = Key, value = Value}) of
@@ -179,20 +182,20 @@ set_env(Key, Value) when is_atom(Key) ->
_ ->
undefined
end.
-
+
%%-----------------------------------------------------------------
%% function : info
%% Arguments: IoDervice - info_msg | string | io | {io, Dev}
-%% Returns :
-%% Exception:
-%% Effect :
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
info() ->
info(info_msg).
info(IoDevice) ->
- Info =
+ Info =
case orber_tb:is_running() of
true ->
Info1 = create_main_info(),
@@ -211,7 +214,7 @@ info(IoDevice) ->
string ->
Info;
io ->
- io:format("~s", [Info]);
+ io:format("~s", [Info]);
{io, Dev} ->
io:format(Dev, "~s", [Info]);
_ ->
@@ -220,14 +223,14 @@ info(IoDevice) ->
create_main_info() ->
{Major, Minor} = giop_version(),
- [io_lib:format("======= Orber Execution Environment ======~n"
+ [io_lib:format("======= Orber Execution Environment ======~n"
"Orber version.................: ~s~n"
"Orber domain..................: ~s~n"
"IIOP port number..............: ~p~n"
"IIOP NAT port number..........: ~p~n"
"Interface(s)..................: ~p~n"
"Interface(s) NAT..............: ~p~n"
- "Local Interface (default).....: ~p~n"
+ "Local Interface (default).....: ~p~n"
"Nodes in domain...............: ~p~n"
"GIOP version (default)........: ~p.~p~n"
"IIOP out timeout..............: ~p msec~n"
@@ -254,18 +257,18 @@ create_main_info() ->
"Debug Level...................: ~p~n"
"orbInitRef....................: ~p~n"
"orbDefaultInitRef.............: ~p~n",
- [?ORBVSN, domain(), iiop_port(), nat_iiop_port(), host(),
+ [?ORBVSN, domain(), iiop_port(), nat_iiop_port(), host(),
nat_host(), ip_address_local(),
orber:orber_nodes(), Major, Minor,
- iiop_timeout(), iiop_connection_timeout(),
+ iiop_timeout(), iiop_connection_timeout(),
iiop_setup_connection_timeout(), iiop_out_ports(),
iiop_out_ports_attempts(), iiop_out_ports_random(),
- orber:iiop_connections(out), orber:iiop_connections_pending(),
- iiop_out_keepalive(), orber:iiop_connections(in),
- iiop_in_connection_timeout(), iiop_in_keepalive(),
- iiop_max_fragments(), iiop_max_in_requests(),
+ orber:iiop_connections(out), orber:iiop_connections_pending(),
+ iiop_out_keepalive(), orber:iiop_connections(in),
+ iiop_in_connection_timeout(), iiop_in_keepalive(),
+ iiop_max_fragments(), iiop_max_in_requests(),
iiop_max_in_connections(), iiop_backlog(), iiop_acl(),
- iiop_packet_size(), objectkeys_gc_time(), get_interceptors(),
+ iiop_packet_size(), objectkeys_gc_time(), get_interceptors(),
get_local_interceptors(), get_debug_level(), get_ORBInitRef(),
get_ORBDefaultInitRef()])].
@@ -277,7 +280,7 @@ create_flag_info(Info) ->
FlagData = check_flags(?ORB_ENV_FLAGS, Flags, []),
[Info, "System Flags Set..............: \n", FlagData, "\n"]
end.
-
+
check_flags([], _, Acc) ->
Acc;
check_flags([{Flag, Txt}|T], Flags, Acc) when ?ORB_FLAG_TEST(Flags, Flag) ->
@@ -289,7 +292,7 @@ check_flags([_|T], Flags, Acc) ->
create_security_info(no, Info) ->
lists:flatten([Info, "=========================================\n"]);
create_security_info(ssl, Info) ->
- lists:flatten([Info,
+ lists:flatten([Info,
io_lib:format("ORB security..................: ssl~n"
"SSL generation................: ~p~n"
"SSL IIOP in keepalive.........: ~p~n"
@@ -316,26 +319,26 @@ create_security_info(ssl, Info) ->
"SSL client ciphers............: ~p~n"
"SSL client cachetimeout.......: ~p~n"
"=========================================~n",
- [ssl_generation(), iiop_ssl_port(),
+ [ssl_generation(), iiop_ssl_port(),
iiop_ssl_in_keepalive(), iiop_ssl_out_keepalive(),
- nat_iiop_ssl_port(), iiop_ssl_accept_timeout(),
+ nat_iiop_ssl_port(), iiop_ssl_accept_timeout(),
iiop_ssl_backlog(), iiop_ssl_ip_address_local(),
ssl_server_certfile(), ssl_server_verify(),
- ssl_server_depth(), ssl_server_cacertfile(),
- ssl_server_keyfile(), ssl_server_password(),
+ ssl_server_depth(), ssl_server_cacertfile(),
+ ssl_server_keyfile(), ssl_server_password(),
ssl_server_ciphers(), ssl_server_cachetimeout(),
- ssl_client_certfile(), ssl_client_verify(),
- ssl_client_depth(), ssl_client_cacertfile(),
+ ssl_client_certfile(), ssl_client_verify(),
+ ssl_client_depth(), ssl_client_cacertfile(),
ssl_client_keyfile(), ssl_client_password(),
ssl_client_ciphers(), ssl_client_cachetimeout()])]).
%%-----------------------------------------------------------------
%% function : iiop_acl
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
iiop_acl() ->
case application:get_env(orber, iiop_acl) of
@@ -352,7 +355,7 @@ iiop_packet_size() ->
_ ->
infinity
end.
-
+
iiop_port() ->
case application:get_env(orber, iiop_port) of
@@ -368,7 +371,7 @@ nat_iiop_port() ->
Port;
{ok, {local, Default, _NATList}} ->
Default;
- _ ->
+ _ ->
iiop_port()
end.
@@ -378,7 +381,7 @@ nat_iiop_port(LocalPort) ->
Port;
{ok, {local, Default, NATList}} ->
orber_tb:keysearch(LocalPort, NATList, Default);
- _ ->
+ _ ->
iiop_port()
end.
@@ -407,9 +410,9 @@ iiop_out_ports_attempts() ->
_ ->
1
end.
-
-domain() ->
+
+domain() ->
case application:get_env(orber, domain) of
{ok, Domain} when is_list(Domain) ->
Domain;
@@ -449,7 +452,7 @@ nat_host([Host]) ->
{ok,{multiple, [I|_] = IList}} when is_list(I) ->
IList;
{ok,{local, Default, NATList}} ->
- [orber_tb:keysearch(Host, NATList, Default)];
+ [orber_tb:keysearch(Host, NATList, Default)];
_ ->
host()
end.
@@ -462,7 +465,7 @@ host() ->
{ok,{multiple, [I|_] = IList}} when is_list(I) ->
IList;
%% IPv4. For IPv6 we only accept a string, but we must support this format
- %% for IPv4
+ %% for IPv4
{ok, {A1, A2, A3, A4}} when is_integer(A1+A2+A3+A4) ->
[integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3)
++ "." ++ integer_to_list(A4)];
@@ -489,7 +492,7 @@ ip_address_local() ->
_ ->
[]
end.
-
+
ip_address() ->
ip_address(ip_version()).
@@ -526,7 +529,7 @@ addr2str({A1, A2, A3, A4, A5, A6, A7, A8}) ->
int16_to_hex(A3) ++ ":" ++ int16_to_hex(A4) ++ ":" ++
int16_to_hex(A5) ++ ":" ++ int16_to_hex(A6) ++ ":" ++
int16_to_hex(A7) ++ ":" ++ int16_to_hex(A8).
-
+
int16_to_hex(0) ->
[$0];
@@ -613,7 +616,7 @@ iiop_max_fragments() ->
_ ->
infinity
end.
-
+
iiop_max_in_requests() ->
case application:get_env(orber, iiop_max_in_requests) of
{ok, Max} when is_integer(Max) andalso Max > 0 ->
@@ -653,7 +656,7 @@ iiop_out_keepalive() ->
_ ->
false
end.
-
+
get_flags() ->
@@ -706,9 +709,9 @@ bidir_context() ->
?ORB_FLAG_TEST(Flags, ?ORB_ENV_USE_BI_DIR_IIOP) ->
[#'IOP_ServiceContext'
{context_id=?IOP_BI_DIR_IIOP,
- context_data =
- #'IIOP_BiDirIIOPServiceContext'{listen_points =
- [#'IIOP_ListenPoint'{host=host(),
+ context_data =
+ #'IIOP_BiDirIIOPServiceContext'{listen_points =
+ [#'IIOP_ListenPoint'{host=host(),
port=iiop_port()}]}}];
true ->
[]
@@ -819,7 +822,7 @@ get_lightweight_nodes() ->
_ ->
false
end.
-
+
%%-----------------------------------------------------------------
%% Security access operations (SSL)
@@ -838,8 +841,8 @@ ssl_generation() ->
V;
_ ->
2
- end.
-
+ end.
+
iiop_ssl_ip_address_local() ->
case application:get_env(orber, iiop_ssl_ip_address_local) of
{ok,I} when is_list(I) ->
@@ -876,10 +879,10 @@ iiop_ssl_accept_timeout() ->
case application:get_env(orber, iiop_ssl_accept_timeout) of
{ok, N} when is_integer(N) ->
N * 1000;
- _ ->
+ _ ->
infinity
end.
-
+
iiop_ssl_port() ->
case application:get_env(orber, secure) of
{ok, ssl} ->
@@ -923,6 +926,52 @@ nat_iiop_ssl_port(LocalPort) ->
-1
end.
+ssl_server_options() ->
+ case application:get_env(orber, ssl_server_options) of
+ {ok, V1} when is_list(V1) ->
+ V1;
+ _ ->
+ []
+ end.
+
+ssl_client_options() ->
+ case application:get_env(orber, ssl_client_options) of
+ {ok, V1} when is_list(V1) ->
+ V1;
+ _ ->
+ []
+ end.
+
+check_ssl_opts(Value) ->
+ check_ssl_opts(Value, []).
+check_ssl_opts([], []) ->
+ ok;
+check_ssl_opts([], Acc) ->
+ {error, Acc};
+check_ssl_opts([{active, _} |T], Acc) ->
+ check_ssl_opts(T, [active |Acc]);
+check_ssl_opts([{packet, _} |T], Acc) ->
+ check_ssl_opts(T, [packet |Acc]);
+check_ssl_opts([{mode, _} |T], Acc) ->
+ check_ssl_opts(T, [mode |Acc]);
+check_ssl_opts([list |T], Acc) ->
+ check_ssl_opts(T, [list |Acc]);
+check_ssl_opts([binary |T], Acc) ->
+ check_ssl_opts(T, [binary |Acc]);
+check_ssl_opts([_ |T], Acc) ->
+ check_ssl_opts(T, Acc).
+
+set_ssl_client_options(Value) when is_list(Value) ->
+ case check_ssl_opts(Value) of
+ ok ->
+ ok;
+ {error, List} ->
+ exit(lists:flatten(
+ io_lib:format("TCP options ~p is not allowed in set_ssl_client_options()",
+ [List])))
+ end,
+ put(ssl_client_options, Value), ok.
+
ssl_server_certfile() ->
case application:get_env(orber, ssl_server_certfile) of
{ok, V1} when is_list(V1) ->
@@ -932,7 +981,7 @@ ssl_server_certfile() ->
_ ->
[]
end.
-
+
ssl_client_certfile() ->
case get(ssl_client_certfile) of
undefined ->
@@ -950,7 +999,7 @@ ssl_client_certfile() ->
set_ssl_client_certfile(Value) when is_list(Value) ->
put(ssl_client_certfile, Value).
-
+
ssl_server_verify() ->
Verify = case application:get_env(orber, ssl_server_verify) of
{ok, V} when is_integer(V) ->
@@ -964,7 +1013,7 @@ ssl_server_verify() ->
true ->
0
end.
-
+
ssl_client_verify() ->
Verify = case get(ssl_client_verify) of
undefined ->
@@ -986,7 +1035,7 @@ ssl_client_verify() ->
set_ssl_client_verify(Value) when is_integer(Value) andalso Value =< 2 andalso Value >= 0 ->
put(ssl_client_verify, Value), ok.
-
+
ssl_server_depth() ->
case application:get_env(orber, ssl_server_depth) of
{ok, V1} when is_integer(V1) ->
@@ -994,7 +1043,7 @@ ssl_server_depth() ->
_ ->
1
end.
-
+
ssl_client_depth() ->
case get(ssl_client_depth) of
undefined ->
@@ -1010,7 +1059,7 @@ ssl_client_depth() ->
set_ssl_client_depth(Value) when is_integer(Value) ->
put(ssl_client_depth, Value), ok.
-
+
ssl_server_cacertfile() ->
@@ -1022,7 +1071,7 @@ ssl_server_cacertfile() ->
_ ->
[]
end.
-
+
ssl_client_cacertfile() ->
case get(ssl_client_cacertfile) of
undefined ->
@@ -1040,7 +1089,7 @@ ssl_client_cacertfile() ->
set_ssl_client_cacertfile(Value) when is_list(Value) ->
put(ssl_client_cacertfile, Value), ok.
-
+
ssl_client_password() ->
case application:get_env(orber, ssl_client_password) of
@@ -1108,10 +1157,10 @@ ssl_server_cachetimeout() ->
%%-----------------------------------------------------------------
%% function : configure
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
configure(Key, Value) when is_atom(Key) ->
configure(Key, Value, check);
@@ -1125,10 +1174,10 @@ configure_override(Key, _) ->
%%-----------------------------------------------------------------
%% function : multi_configure
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
multi_configure(KeyValueList) when is_list(KeyValueList) ->
case orber_tb:is_loaded() of
@@ -1144,7 +1193,7 @@ multi_configure(KeyValueList) when is_list(KeyValueList) ->
end
end;
multi_configure(KeyValueList) ->
- ?EFORMAT("Given configuration parameters not a Key-Value-pair list: ~p",
+ ?EFORMAT("Given configuration parameters not a Key-Value-pair list: ~p",
[KeyValueList]).
multi_configure_helper([], _) ->
@@ -1237,7 +1286,7 @@ configure(iiop_port, Value, Status) when is_integer(Value) ->
%% Set the NAT listen port
configure(nat_iiop_port, Value, Status) when is_integer(Value) andalso Value > 0 ->
do_safe_configure(nat_iiop_port, Value, Status);
-configure(nat_iiop_port, {local, Value1, Value2}, Status) when is_integer(Value1) andalso
+configure(nat_iiop_port, {local, Value1, Value2}, Status) when is_integer(Value1) andalso
Value1 > 0 andalso
is_list(Value2) ->
do_safe_configure(nat_iiop_port, {local, Value1, Value2}, Status);
@@ -1312,12 +1361,20 @@ configure(iiop_ssl_backlog, Value, Status) when is_integer(Value) andalso Value
do_safe_configure(iiop_ssl_backlog, Value, Status);
configure(nat_iiop_ssl_port, Value, Status) when is_integer(Value) andalso Value > 0 ->
do_safe_configure(nat_iiop_ssl_port, Value, Status);
-configure(nat_iiop_ssl_port, {local, Value1, Value2}, Status) when is_integer(Value1) andalso
+configure(nat_iiop_ssl_port, {local, Value1, Value2}, Status) when is_integer(Value1) andalso
Value1 > 0 andalso
is_list(Value2) ->
do_safe_configure(nat_iiop_ssl_port, {local, Value1, Value2}, Status);
configure(iiop_ssl_port, Value, Status) when is_integer(Value) ->
do_safe_configure(iiop_ssl_port, Value, Status);
+
+%% New SSL options
+configure(ssl_server_options, Value, Status) when is_list(Value) ->
+ do_safe_configure(ssl_server_options, Value, Status);
+configure(ssl_client_options, Value, Status) when is_list(Value) ->
+ do_safe_configure(ssl_client_options, Value, Status);
+
+%% Old SSL options
configure(ssl_server_certfile, Value, Status) when is_list(Value) ->
do_safe_configure(ssl_server_certfile, Value, Status);
configure(ssl_server_certfile, Value, Status) when is_atom(Value) ->
@@ -1434,9 +1491,9 @@ code_change(_OldVsn, State, _Extra) ->
%%-----------------------------------------------------------------
%% function : env
-%% Arguments:
-%% Returns :
-%% Exception:
+%% Arguments:
+%% Returns :
+%% Exception:
%% Effect : Used when Key always exists (Default Value)
%%-----------------------------------------------------------------
env(Key) ->
@@ -1445,10 +1502,10 @@ env(Key) ->
%%-----------------------------------------------------------------
%% function : init_env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
%%-----------------------------------------------------------------
init_env() ->
application:load(orber),
diff --git a/lib/orber/src/orber_ifr.erl b/lib/orber/src/orber_ifr.erl
index 9631a268e4..4004ffa005 100644
--- a/lib/orber/src/orber_ifr.erl
+++ b/lib/orber/src/orber_ifr.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -478,7 +478,7 @@ get_module(Id, Type) ->
What ->
orber:dbg("[~p] ~p:get_module(~p, ~p).~n"
"Id doesn't exist, mismatch Id vs Type or DB error: ~p",
- [?LINE, ?MODULE, Id, What], ?DEBUG_LEVEL),
+ [?LINE, ?MODULE, Id, Type, What], ?DEBUG_LEVEL),
corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
end.
diff --git a/lib/orber/src/orber_iiop_net.erl b/lib/orber/src/orber_iiop_net.erl
index 58eba9f039..2eed0b538a 100644
--- a/lib/orber/src/orber_iiop_net.erl
+++ b/lib/orber/src/orber_iiop_net.erl
@@ -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
@@ -161,31 +161,51 @@ terminate(_Reason, _State) ->
%%-----------------------------------------------------------------
get_options(normal, _Options) ->
[];
-get_options(ssl, Options) ->
- Verify = orber_tb:keysearch(ssl_server_verify, Options,
- orber_env:ssl_server_verify()),
- Depth = orber_tb:keysearch(ssl_server_depth, Options,
- orber_env:ssl_server_depth()),
- Cert = orber_tb:keysearch(ssl_server_certfile, Options,
- orber_env:ssl_server_certfile()),
- CaCert = orber_tb:keysearch(ssl_server_cacertfile, Options,
- orber_env:ssl_server_cacertfile()),
- Pwd = orber_tb:keysearch(ssl_server_password, Options,
- orber_env:ssl_server_password()),
- Key = orber_tb:keysearch(ssl_server_keyfile, Options,
- orber_env:ssl_server_keyfile()),
- Ciphers = orber_tb:keysearch(ssl_server_ciphers, Options,
- orber_env:ssl_server_ciphers()),
- Timeout = orber_tb:keysearch(ssl_server_cachetimeout, Options,
- orber_env:ssl_server_cachetimeout()),
- [{verify, Verify},
- {depth, Depth} |
- ssl_server_extra_options([{certfile, Cert},
- {cacertfile, CaCert},
- {password, Pwd},
- {keyfile, Key},
- {ciphers, Ciphers},
- {cachetimeout, Timeout}], [])].
+get_options(ssl, Options) ->
+ SSLOpts =
+ case orber_tb:keysearch(ssl_server_options, Options,
+ orber_env:ssl_server_options()) of
+ [] ->
+ Verify = orber_tb:keysearch(ssl_server_verify, Options,
+ orber_env:ssl_server_verify()),
+ Depth = orber_tb:keysearch(ssl_server_depth, Options,
+ orber_env:ssl_server_depth()),
+ Cert = orber_tb:keysearch(ssl_server_certfile, Options,
+ orber_env:ssl_server_certfile()),
+ CaCert = orber_tb:keysearch(ssl_server_cacertfile, Options,
+ orber_env:ssl_server_cacertfile()),
+ Pwd = orber_tb:keysearch(ssl_server_password, Options,
+ orber_env:ssl_server_password()),
+ Key = orber_tb:keysearch(ssl_server_keyfile, Options,
+ orber_env:ssl_server_keyfile()),
+ Ciphers = orber_tb:keysearch(ssl_server_ciphers, Options,
+ orber_env:ssl_server_ciphers()),
+ Timeout = orber_tb:keysearch(ssl_server_cachetimeout, Options,
+ orber_env:ssl_server_cachetimeout()),
+ KeepAlive = orber_tb:keysearch(ssl_server_cachetimeout, Options,
+ orber_env:iiop_ssl_in_keepalive()),
+ [{verify, Verify},
+ {depth, Depth},
+ {certfile, Cert},
+ {cacertfile, CaCert},
+ {password, Pwd},
+ {keyfile, Key},
+ {ciphers, Ciphers},
+ {cachetimeout, Timeout},
+ {keepalive, KeepAlive}];
+ Opts ->
+ case orber_tb:check_illegal_tcp_options(Opts) of
+ ok ->
+ check_old_ssl_server_options(Options),
+ Opts;
+ {error, IllegalOpts} ->
+ error_logger:error_report([{application, orber},
+ "TCP options not allowed to set on a connection",
+ IllegalOpts]),
+ error("Illegal TCP option")
+ end
+ end,
+ ssl_server_extra_options(SSLOpts, []).
%%-----------------------------------------------------------------
%% Func: parse_options/2
@@ -266,23 +286,28 @@ handle_call({add, IP, Type, Port, AllOptions}, _From, State) ->
Family = orber_env:ip_version(),
case inet:getaddr(IP, Family) of
{ok, IPTuple} ->
- Options = [{ip, IPTuple}|get_options(Type, AllOptions)],
- Ref = make_ref(),
- ProxyOptions = filter_options(AllOptions, []),
- case orber_socket:listen(Type, Port, Options, false) of
- {ok, Listen, NewPort} ->
- {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, Ref,
- ProxyOptions),
- link(Pid),
- ets:insert(?CONNECTION_DB, #listen{pid = Pid,
- socket = Listen,
- port = NewPort,
- type = Type, ref = Ref,
- options = Options,
- proxy_options = ProxyOptions}),
- {reply, {ok, Ref}, State};
- Error ->
- {reply, Error, State}
+ try [{ip, IPTuple} |get_options(Type, AllOptions)] of
+ Options ->
+ Ref = make_ref(),
+ ProxyOptions = filter_options(AllOptions, []),
+ case orber_socket:listen(Type, Port, Options, false) of
+ {ok, Listen, NewPort} ->
+ {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, Ref,
+ ProxyOptions),
+ link(Pid),
+ ets:insert(?CONNECTION_DB, #listen{pid = Pid,
+ socket = Listen,
+ port = NewPort,
+ type = Type, ref = Ref,
+ options = Options,
+ proxy_options = ProxyOptions}),
+ {reply, {ok, Ref}, State};
+ Error ->
+ {reply, Error, State}
+ end
+ catch
+ error:Reason ->
+ {reply, {error, Reason}, State}
end;
Other ->
{reply, Other, State}
@@ -461,3 +486,31 @@ update_counter(#state{max_connections = infinity} = State, _) ->
update_counter(State, Value) ->
State#state{counter = State#state.counter + Value}.
+
+check_old_ssl_server_options(Options) ->
+ try
+ 0 = orber_tb:keysearch(ssl_server_verify, Options,
+ orber_env:ssl_server_verify()),
+ 1 = orber_tb:keysearch(ssl_server_depth, Options,
+ orber_env:ssl_server_depth()),
+ [] = orber_tb:keysearch(ssl_server_certfile, Options,
+ orber_env:ssl_server_certfile()),
+ [] = orber_tb:keysearch(ssl_server_cacertfile, Options,
+ orber_env:ssl_server_cacertfile()),
+ [] = orber_tb:keysearch(ssl_server_password, Options,
+ orber_env:ssl_server_password()),
+ [] = orber_tb:keysearch(ssl_server_keyfile, Options,
+ orber_env:ssl_server_keyfile()),
+ [] = orber_tb:keysearch(ssl_server_ciphers, Options,
+ orber_env:ssl_server_ciphers()),
+ infinity = orber_tb:keysearch(ssl_server_cachetimeout, Options,
+ orber_env:ssl_server_cachetimeout()),
+ false = orber_tb:keysearch(iiop_ssl_in_keepalive, Options,
+ orber_env:iiop_ssl_in_keepalive())
+ catch
+ _:_ ->
+ io:format("hej\n",[]),
+ error_logger:warning_report([{application, orber},
+ "Ignoring deprecated ssl server options used together with the ssl_server_options"])
+ end.
+
diff --git a/lib/orber/src/orber_iiop_pm.erl b/lib/orber/src/orber_iiop_pm.erl
index bf36b353bc..927d12b3b2 100644
--- a/lib/orber/src/orber_iiop_pm.erl
+++ b/lib/orber/src/orber_iiop_pm.erl
@@ -2,7 +2,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
@@ -108,44 +108,82 @@ connect(Host, Port, SocketType, Timeout, Chars, Wchars, Ctx)
end.
get_ssl_socket_options([]) ->
- [{verify, orber:ssl_client_verify()},
- {depth, orber:ssl_client_depth()} |
- ssl_client_extra_options([{certfile, orber:ssl_client_certfile()},
- {cacertfile, orber:ssl_client_cacertfile()},
- {password, orber:ssl_client_password()},
- {keyfile, orber:ssl_client_keyfile()},
- {ciphers, orber:ssl_client_ciphers()},
- {cachetimeout, orber:ssl_client_cachetimeout()}], [])];
+ SSLOpts =
+ case orber_env:ssl_client_options() of
+ [] ->
+ [{verify, orber_env:ssl_client_verify()},
+ {depth, orber_env:ssl_client_depth()},
+ {certfile, orber_env:ssl_client_certfile()},
+ {cacertfile, orber_env:ssl_client_cacertfile()},
+ {password, orber_env:ssl_client_password()},
+ {keyfile, orber_env:ssl_client_keyfile()},
+ {ciphers, orber_env:ssl_client_ciphers()},
+ {cachetimeout, orber_env:ssl_client_cachetimeout()},
+ {keepalive, orber_env:iiop_ssl_out_keepalive()}];
+ Opts ->
+ case orber_tb:check_illegal_tcp_options(Opts) of
+ ok ->
+ check_old_ssl_client_options([]),
+ Opts;
+ {error, IllegalOpts} ->
+ error_logger:error_report([{application, orber},
+ "TCP options not allowed to set on a connection",
+ IllegalOpts]),
+ error("Illegal TCP option")
+ end
+ end,
+ ssl_client_extra_options(SSLOpts, []);
get_ssl_socket_options([#'IOP_ServiceContext'
{context_id=?ORBER_GENERIC_CTX_ID,
context_data = {configuration, Options}}|_]) ->
- Verify = orber_tb:keysearch(ssl_client_verify, Options,
- orber_env:ssl_client_verify()),
- Depth = orber_tb:keysearch(ssl_client_depth, Options,
- orber_env:ssl_client_depth()),
- Cert = orber_tb:keysearch(ssl_client_certfile, Options,
- orber_env:ssl_client_certfile()),
- CaCert = orber_tb:keysearch(ssl_client_cacertfile, Options,
- orber_env:ssl_client_cacertfile()),
- Pwd = orber_tb:keysearch(ssl_client_password, Options,
- orber_env:ssl_client_password()),
- Key = orber_tb:keysearch(ssl_client_keyfile, Options,
- orber_env:ssl_client_keyfile()),
- Ciphers = orber_tb:keysearch(ssl_client_ciphers, Options,
- orber_env:ssl_client_ciphers()),
- Timeout = orber_tb:keysearch(ssl_client_cachetimeout, Options,
- orber_env:ssl_client_cachetimeout()),
- [{verify, Verify},
- {depth, Depth} |
- ssl_client_extra_options([{certfile, Cert},
- {cacertfile, CaCert},
- {password, Pwd},
- {keyfile, Key},
- {ciphers, Ciphers},
- {cachetimeout, Timeout}], [])];
+ SSLOpts =
+ case orber_tb:keysearch(ssl_client_options, Options,
+ orber_env:ssl_client_options()) of
+ [] ->
+ Verify = orber_tb:keysearch(ssl_client_verify, Options,
+ orber_env:ssl_client_verify()),
+ Depth = orber_tb:keysearch(ssl_client_depth, Options,
+ orber_env:ssl_client_depth()),
+ Cert = orber_tb:keysearch(ssl_client_certfile, Options,
+ orber_env:ssl_client_certfile()),
+ CaCert = orber_tb:keysearch(ssl_client_cacertfile, Options,
+ orber_env:ssl_client_cacertfile()),
+ Pwd = orber_tb:keysearch(ssl_client_password, Options,
+ orber_env:ssl_client_password()),
+ Key = orber_tb:keysearch(ssl_client_keyfile, Options,
+ orber_env:ssl_client_keyfile()),
+ Ciphers = orber_tb:keysearch(ssl_client_ciphers, Options,
+ orber_env:ssl_client_ciphers()),
+ Timeout = orber_tb:keysearch(ssl_client_cachetimeout, Options,
+ orber_env:ssl_client_cachetimeout()),
+ KeepAlive = orber_tb:keysearch(ssl_server_cachetimeout, Options,
+ orber_env:iiop_ssl_out_keepalive()),
+ [{verify, Verify},
+ {depth, Depth},
+ {certfile, Cert},
+ {cacertfile, CaCert},
+ {password, Pwd},
+ {keyfile, Key},
+ {ciphers, Ciphers},
+ {cachetimeout, Timeout},
+ {keepalive, KeepAlive}];
+ Opts ->
+ case orber_tb:check_illegal_tcp_options(Opts) of
+ ok ->
+ check_old_ssl_client_options(Options),
+ Opts;
+ {error, IllegalOpts} ->
+ error_logger:error_report([{application, orber},
+ "TCP options not allowed to set on a connection",
+ IllegalOpts]),
+ error("Illegal TCP option")
+ end
+ end,
+ ssl_client_extra_options(SSLOpts, []);
get_ssl_socket_options([_|T]) ->
get_ssl_socket_options(T).
+
ssl_client_extra_options([], Acc) ->
Acc;
ssl_client_extra_options([{_Type, []}|T], Acc) ->
@@ -814,6 +852,36 @@ init_interceptors(Host, Port, {SHost, SPort}) ->
%% Either 'false' or {Type, PIs}.
Other
end.
+
+
+check_old_ssl_client_options(Options) ->
+ try
+ 0 = orber_tb:keysearch(ssl_client_verify, Options,
+ orber_env:ssl_client_verify()),
+ 1 = orber_tb:keysearch(ssl_client_depth, Options,
+ orber_env:ssl_client_depth()),
+ [] = orber_tb:keysearch(ssl_client_certfile, Options,
+ orber_env:ssl_client_certfile()),
+ [] = orber_tb:keysearch(ssl_client_cacertfile, Options,
+ orber_env:ssl_client_cacertfile()),
+ [] = orber_tb:keysearch(ssl_client_password, Options,
+ orber_env:ssl_client_password()),
+ [] = orber_tb:keysearch(ssl_client_keyfile, Options,
+ orber_env:ssl_client_keyfile()),
+ [] = orber_tb:keysearch(ssl_client_ciphers, Options,
+ orber_env:ssl_client_ciphers()),
+ infinity = orber_tb:keysearch(ssl_client_cachetimeout, Options,
+ orber_env:ssl_client_cachetimeout()),
+ false = orber_tb:keysearch(iiop_ssl_out_keepalive, Options,
+ orber_env:iiop_ssl_out_keepalive())
+
+ catch
+ _:_ ->
+ error_logger:warning_report([{application, orber},
+ "Ignoring deprecated ssl client options used together with the ssl_client_options"])
+ end.
+
+
%%-----------------------------------------------------------------
diff --git a/lib/orber/src/orber_socket.erl b/lib/orber/src/orber_socket.erl
index ec2cf8f42a..07a0e09ccc 100644
--- a/lib/orber/src/orber_socket.erl
+++ b/lib/orber/src/orber_socket.erl
@@ -14,8 +14,7 @@
%% basis, 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%
%%
%%
%%-----------------------------------------------------------------
@@ -37,7 +36,7 @@
%%-----------------------------------------------------------------
-export([start/0, connect/4, listen/3, listen/4, accept/2, accept/3, write/3,
controlling_process/3, close/2, peername/2, sockname/2,
- peerdata/2, peercert/2, sockdata/2, setopts/3,
+ peerdata/2, peercert/2, sockdata/2, setopts/3,
clear/2, shutdown/3, post_accept/2, post_accept/3]).
%%-----------------------------------------------------------------
@@ -75,8 +74,6 @@ connect(Type, Host, Port, Options) ->
case Type of
normal ->
[{keepalive, orber_env:iiop_out_keepalive()}|Options1];
- _ when Generation > 2 ->
- [{keepalive, orber_env:iiop_ssl_out_keepalive()}|Options1];
_ ->
Options1
end,
@@ -251,8 +248,7 @@ listen(ssl, Port, Options, Exception) ->
end,
Options4 = if
Generation > 2 ->
- [{reuseaddr, true},
- {keepalive, orber_env:iiop_ssl_in_keepalive()}|Options3];
+ [{reuseaddr, true} |Options3];
true ->
Options3
end,
@@ -362,8 +358,8 @@ peercert(ssl, Socket) ->
ssl:peercert(Socket);
peercert(Type, _Socket) ->
orber:dbg("[~p] orber_socket:peercert(~p);~n"
- "Only available for SSL sockets.",
- [?LINE, Type], ?DEBUG_LEVEL),
+ "Only available for SSL sockets.",
+ [?LINE, Type], ?DEBUG_LEVEL),
{error, ebadsocket}.
%%-----------------------------------------------------------------
diff --git a/lib/orber/src/orber_tb.erl b/lib/orber/src/orber_tb.erl
index e6d5ee4400..26a36df0e9 100644
--- a/lib/orber/src/orber_tb.erl
+++ b/lib/orber/src/orber_tb.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,8 @@
-compile({no_auto_import,[error/2]}).
-export([wait_for_tables/1, wait_for_tables/2, wait_for_tables/3,
is_loaded/0, is_loaded/1, is_running/0, is_running/1,
- info/2, error/2, unique/1, keysearch/2, keysearch/3]).
+ info/2, error/2, unique/1, keysearch/2, keysearch/3,
+ check_illegal_tcp_options/1]).
%%----------------------------------------------------------------------
%% Internal exports
@@ -179,6 +180,38 @@ error(Format, Args) ->
Args).
+
+
+
+%%----------------------------------------------------------------------
+%% function : check_illegal_tcp_options/1
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
+%%----------------------------------------------------------------------
+check_illegal_tcp_options(Options) ->
+ check_illegal_tcp_options(Options, []).
+
+check_illegal_tcp_options([],[]) ->
+ ok;
+check_illegal_tcp_options([],IllegalOpts) ->
+ {error, IllegalOpts};
+check_illegal_tcp_options([{active, V} |T], IllegalOpts) ->
+ check_illegal_tcp_options(T,[{active, V} |IllegalOpts]);
+check_illegal_tcp_options([{packet, V} |T], IllegalOpts) ->
+ check_illegal_tcp_options(T,[{packet, V} |IllegalOpts]);
+check_illegal_tcp_options([{mode, V} |T], IllegalOpts) ->
+ check_illegal_tcp_options(T,[{mode, V} |IllegalOpts]);
+check_illegal_tcp_options([list |T], IllegalOpts) ->
+ check_illegal_tcp_options(T,[list |IllegalOpts]);
+check_illegal_tcp_options([binary |T], IllegalOpts) ->
+ check_illegal_tcp_options(T,[binary |IllegalOpts]);
+check_illegal_tcp_options([{reuseaddr, V} |T], IllegalOpts) ->
+ check_illegal_tcp_options(T,[{reuseaddr, V} |IllegalOpts]);
+check_illegal_tcp_options([_H|T], IllegalOpts) ->
+ check_illegal_tcp_options(T, IllegalOpts).
+
%%----------------------------------------------------------------------
%% Internal functions
%%----------------------------------------------------------------------
diff --git a/lib/orber/test/Makefile b/lib/orber/test/Makefile
index 996d0d1874..8eef1934a4 100644
--- a/lib/orber/test/Makefile
+++ b/lib/orber/test/Makefile
@@ -176,6 +176,7 @@ clean:
rm -f idl_output/*
rm -f $(TARGET_FILES)
rm -f errs core *~
+ rm IDL-GENERATED
docs:
@@ -208,12 +209,12 @@ release_spec:
release_docs_spec:
release_tests_spec: tests
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) $(COVER_FILE) \
- $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- $(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
+ $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
$(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- $(RELSYSDIR)/$(IDLOUTDIR)
+ "$(RELSYSDIR)/$(IDLOUTDIR)"
diff --git a/lib/orber/test/csiv2_SUITE.erl b/lib/orber/test/csiv2_SUITE.erl
index 95cd8c56b3..60ffa1eb09 100644
--- a/lib/orber/test/csiv2_SUITE.erl
+++ b/lib/orber/test/csiv2_SUITE.erl
@@ -70,46 +70,46 @@
profiles =
[#'IOP_TaggedProfile'
{tag = ?TAG_INTERNET_IOP,
- profile_data =
+ profile_data =
#'IIOP_ProfileBody_1_1'{
iiop_version = #'IIOP_Version'{major = 1,
minor = 2},
host = "127.0.0.1",
port = 0,
object_key = [0,86,66,1,0,0,0,24,47,70,77,65,95,67,73,82,80,77,65,78,95,80,79,65,95,83,69,67,85,82,69,0,0,0,0,4,0,0,4,186,0,0,2,10,81,218,65,185],
- components =
+ components =
[#'IOP_TaggedComponent'{tag = ?TAG_SSL_SEC_TRANS,
component_data = #'SSLIOP_SSL'{
target_supports = 102,
target_requires = 66,
port = 49934}},
#'IOP_TaggedComponent'{tag = ?TAG_CSI_SEC_MECH_LIST,
- component_data =
+ component_data =
#'CSIIOP_CompoundSecMechList'{stateful = true,
- mechanism_list =
+ mechanism_list =
[#'CSIIOP_CompoundSecMech'
{target_requires = 66,
transport_mech = #'IOP_TaggedComponent'{
tag = ?TAG_TLS_SEC_TRANS,
- component_data =
+ component_data =
#'CSIIOP_TLS_SEC_TRANS'{
target_supports = 102,
target_requires = 66,
- addresses =
+ addresses =
[#'CSIIOP_TransportAddress'
{host_name = "127.0.0.1",
port = 49934}]}},
- as_context_mech =
+ as_context_mech =
#'CSIIOP_AS_ContextSec'{
target_supports = 0,
target_requires = 0,
client_authentication_mech = [],
target_name = []},
- sas_context_mech =
+ sas_context_mech =
#'CSIIOP_SAS_ContextSec'{
target_supports = 1024,
target_requires = 0,
- privilege_authorities =
+ privilege_authorities =
[#'CSIIOP_ServiceConfiguration'
{syntax = 1447174401,
name = "Borland"}],
@@ -124,7 +124,7 @@
supported_identity_types = 15}}]}},
#'IOP_TaggedComponent'
{tag = ?TAG_CODE_SETS,
- component_data =
+ component_data =
#'CONV_FRAME_CodeSetComponentInfo'{'ForCharData' =
#'CONV_FRAME_CodeSetComponent'{
native_code_set = 65537,
@@ -151,15 +151,15 @@
-ifdef(false).
%% PKIX1Explicit88
--define(AlgorithmIdentifier,
+-define(AlgorithmIdentifier,
#'AlgorithmIdentifier'{algorithm = ?OID,
parameters = ?ANY}).
-define(Validity, #'Validity'{notBefore = {utcTime, "19820102070533.8"},
notAfter = {generalTime, "19820102070533.8"}}).
--define(SubjectPublicKeyInfo,
- #'SubjectPublicKeyInfo'{algorithm = ?AlgorithmIdentifier,
+-define(SubjectPublicKeyInfo,
+ #'SubjectPublicKeyInfo'{algorithm = ?AlgorithmIdentifier,
subjectPublicKey = ?BIT_STR}).
-define(AttributeTypeAndValue,
@@ -178,26 +178,26 @@
-define(UniqueIdentifier, ?BIT_STR).
--define(Extension, #'Extension'{extnID = ?OID,
- critical = ?BOOLEAN,
+-define(Extension, #'Extension'{extnID = ?OID,
+ critical = ?BOOLEAN,
extnValue = ?OCTET_STR}).
-define(Extensions, [?Extension]).
-define(TBSCertificate,
- #'TBSCertificate'{version = ?Version,
- serialNumber = ?CertificateSerialNumber,
- signature = ?AlgorithmIdentifier,
- issuer = ?Name,
- validity = ?Validity,
- subject = ?Name,
- subjectPublicKeyInfo = ?SubjectPublicKeyInfo,
- issuerUniqueID = ?UniqueIdentifier,
- subjectUniqueID = ?UniqueIdentifier,
+ #'TBSCertificate'{version = ?Version,
+ serialNumber = ?CertificateSerialNumber,
+ signature = ?AlgorithmIdentifier,
+ issuer = ?Name,
+ validity = ?Validity,
+ subject = ?Name,
+ subjectPublicKeyInfo = ?SubjectPublicKeyInfo,
+ issuerUniqueID = ?UniqueIdentifier,
+ subjectUniqueID = ?UniqueIdentifier,
extensions = ?Extensions}).
--define(Certificate, #'Certificate'{tbsCertificate = ?TBSCertificate,
- signatureAlgorithm = ?AlgorithmIdentifier,
+-define(Certificate, #'Certificate'{tbsCertificate = ?TBSCertificate,
+ signatureAlgorithm = ?AlgorithmIdentifier,
signature = ?BIT_STR}).
%% PKIX1Implicit88
@@ -206,66 +206,66 @@
-define(GeneralNames, [?GeneralName]).
-%% PKIXAttributeCertificate
--define(AttCertValidityPeriod,
- #'AttCertValidityPeriod'{notBeforeTime = "19820102070533.8",
+%% PKIXAttributeCertificate
+-define(AttCertValidityPeriod,
+ #'AttCertValidityPeriod'{notBeforeTime = "19820102070533.8",
notAfterTime = "19820102070533.8"}).
--define(Attribute, #'Attribute'{type = ?OID,
+-define(Attribute, #'Attribute'{type = ?OID,
values = []}).
-define(Attributes, [?Attribute]).
--define(IssuerSerial, #'IssuerSerial'{issuer = ?GeneralNames,
- serial = ?CertificateSerialNumber,
+-define(IssuerSerial, #'IssuerSerial'{issuer = ?GeneralNames,
+ serial = ?CertificateSerialNumber,
issuerUID = ?UniqueIdentifier}).
-define(DigestedObjectType, publicKey). %% Enum
--define(ObjectDigestInfo,
- #'ObjectDigestInfo'{digestedObjectType = ?DigestedObjectType,
- otherObjectTypeID = ?OID,
- digestAlgorithm = ?AlgorithmIdentifier,
+-define(ObjectDigestInfo,
+ #'ObjectDigestInfo'{digestedObjectType = ?DigestedObjectType,
+ otherObjectTypeID = ?OID,
+ digestAlgorithm = ?AlgorithmIdentifier,
objectDigest = ?BIT_STR}).
--define(V2Form, #'V2Form'{issuerName = ?GeneralNames,
- baseCertificateID = ?IssuerSerial,
+-define(V2Form, #'V2Form'{issuerName = ?GeneralNames,
+ baseCertificateID = ?IssuerSerial,
objectDigestInfo = ?ObjectDigestInfo}).
-define(AttCertVersion, v2).
--define(Holder, #'Holder'{baseCertificateID = ?IssuerSerial,
- entityName = ?GeneralNames,
+-define(Holder, #'Holder'{baseCertificateID = ?IssuerSerial,
+ entityName = ?GeneralNames,
objectDigestInfo = ?ObjectDigestInfo}).
-define(AttCertIssuer, {v2Form, ?V2Form}).
-define(AttributeCertificateInfo,
- #'AttributeCertificateInfo'{version = ?AttCertVersion,
- holder = ?Holder,
- issuer = ?AttCertIssuer,
- signature = ?AlgorithmIdentifier,
- serialNumber = ?CertificateSerialNumber,
+ #'AttributeCertificateInfo'{version = ?AttCertVersion,
+ holder = ?Holder,
+ issuer = ?AttCertIssuer,
+ signature = ?AlgorithmIdentifier,
+ serialNumber = ?CertificateSerialNumber,
attrCertValidityPeriod = ?AttCertValidityPeriod,
- attributes = ?Attributes,
- issuerUniqueID = ?UniqueIdentifier,
+ attributes = ?Attributes,
+ issuerUniqueID = ?UniqueIdentifier,
extensions = ?Extensions}).
--define(AttributeCertificate,
- #'AttributeCertificate'{acinfo = ?AttributeCertificateInfo,
- signatureAlgorithm = ?AlgorithmIdentifier,
+-define(AttributeCertificate,
+ #'AttributeCertificate'{acinfo = ?AttributeCertificateInfo,
+ signatureAlgorithm = ?AlgorithmIdentifier,
signatureValue = ?BIT_STR}).
%% OrberCSIv2
--define(AttributeCertChain,
- #'AttributeCertChain'{attributeCert = ?AttributeCertificate,
+-define(AttributeCertChain,
+ #'AttributeCertChain'{attributeCert = ?AttributeCertificate,
certificateChain = ?CertificateChain}).
-define(CertificateChain, [?Certificate]).
--define(VerifyingCertChain, [?Certificate]).
+-define(VerifyingCertChain, [?Certificate]).
-endif.
@@ -314,15 +314,15 @@
%%-----------------------------------------------------------------
%% Func: all/1
-%% Args:
-%% Returns:
+%% Args:
+%% Returns:
%%-----------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
cases().
-groups() ->
+groups() ->
[].
init_per_group(_GroupName, Config) ->
@@ -335,7 +335,7 @@ end_per_group(_GroupName, Config) ->
%% NOTE - the fragment test cases must bu first since we explicitly set a request
%% id. Otherwise, the request-id counter would be increased and we cannot know
%% what it is.
-cases() ->
+cases() ->
[ssl_server_peercert_api, ssl_client_peercert_api].
%%-----------------------------------------------------------------
@@ -361,14 +361,20 @@ end_per_testcase(_Case, Config) ->
ok.
init_per_suite(Config) ->
- case orber_test_lib:ssl_version() of
- no_ssl ->
- {skip,"SSL is not installed!"};
- _ ->
- Config
+ try crypto:start() of
+ ok ->
+ case orber_test_lib:ssl_version() of
+ no_ssl ->
+ {skip, "SSL is not installed!"};
+ _ ->
+ Config
+ end
+ catch _:_ ->
+ {skip, "Crypto did not start"}
end.
end_per_suite(Config) ->
+ application:stop(crypto),
Config.
%%-----------------------------------------------------------------
@@ -385,272 +391,272 @@ end_per_suite(Config) ->
code_CertificateChain_api(doc) -> ["Code CertificateChain"];
code_CertificateChain_api(suite) -> [];
code_CertificateChain_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('CertificateChain', ?CertificateChain)),
- ?match({ok, [#'Certificate'{}]},
+ ?match({ok, [#'Certificate'{}]},
'OrberCSIv2':decode('CertificateChain', list_to_binary(Enc))),
ok.
code_AttributeCertChain_api(doc) -> ["Code AttributeCertChain"];
code_AttributeCertChain_api(suite) -> [];
code_AttributeCertChain_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('AttributeCertChain', ?AttributeCertChain)),
- ?match({ok, #'AttributeCertChain'{}},
- 'OrberCSIv2':decode('AttributeCertChain', list_to_binary(Enc))),
+ ?match({ok, #'AttributeCertChain'{}},
+ 'OrberCSIv2':decode('AttributeCertChain', list_to_binary(Enc))),
ok.
code_VerifyingCertChain_api(doc) -> ["Code VerifyingCertChain"];
code_VerifyingCertChain_api(suite) -> [];
code_VerifyingCertChain_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('VerifyingCertChain', ?VerifyingCertChain)),
- ?match({ok, [#'Certificate'{}]},
- 'OrberCSIv2':decode('VerifyingCertChain', list_to_binary(Enc))),
+ ?match({ok, [#'Certificate'{}]},
+ 'OrberCSIv2':decode('VerifyingCertChain', list_to_binary(Enc))),
ok.
%% PKIXAttributeCertificate
code_AttributeCertificate_api(doc) -> ["Code AttributeCertificate"];
code_AttributeCertificate_api(suite) -> [];
code_AttributeCertificate_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('AttributeCertificate', ?AttributeCertificate)),
- ?match({ok, #'AttributeCertificate'{}},
- 'OrberCSIv2':decode('AttributeCertificate', list_to_binary(Enc))),
+ ?match({ok, #'AttributeCertificate'{}},
+ 'OrberCSIv2':decode('AttributeCertificate', list_to_binary(Enc))),
ok.
code_AttributeCertificateInfo_api(doc) -> ["Code AttributeCertificateInfo"];
code_AttributeCertificateInfo_api(suite) -> [];
code_AttributeCertificateInfo_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('AttributeCertificateInfo', ?AttributeCertificateInfo)),
- ?match({ok, #'AttributeCertificateInfo'{}},
- 'OrberCSIv2':decode('AttributeCertificateInfo', list_to_binary(Enc))),
+ ?match({ok, #'AttributeCertificateInfo'{}},
+ 'OrberCSIv2':decode('AttributeCertificateInfo', list_to_binary(Enc))),
ok.
code_AttCertVersion_api(doc) -> ["Code AttCertVersion"];
code_AttCertVersion_api(suite) -> [];
code_AttCertVersion_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('AttCertVersion', ?AttCertVersion)),
- ?match({ok, ?AttCertVersion},
- 'OrberCSIv2':decode('AttCertVersion', list_to_binary(Enc))),
+ ?match({ok, ?AttCertVersion},
+ 'OrberCSIv2':decode('AttCertVersion', list_to_binary(Enc))),
ok.
code_Holder_api(doc) -> ["Code Holder"];
code_Holder_api(suite) -> [];
code_Holder_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('Holder', ?Holder)),
- ?match({ok, #'Holder'{}},
- 'OrberCSIv2':decode('Holder', list_to_binary(Enc))),
+ ?match({ok, #'Holder'{}},
+ 'OrberCSIv2':decode('Holder', list_to_binary(Enc))),
ok.
code_AttCertIssuer_api(doc) -> ["Code AttCertIssuer"];
code_AttCertIssuer_api(suite) -> [];
code_AttCertIssuer_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('AttCertIssuer', ?AttCertIssuer)),
- ?match({ok, {v2Form, _}},
- 'OrberCSIv2':decode('AttCertIssuer', list_to_binary(Enc))),
+ ?match({ok, {v2Form, _}},
+ 'OrberCSIv2':decode('AttCertIssuer', list_to_binary(Enc))),
ok.
code_AttCertValidityPeriod_api(doc) -> ["Code AttCertValidityPeriod"];
code_AttCertValidityPeriod_api(suite) -> [];
code_AttCertValidityPeriod_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('AttCertValidityPeriod', ?AttCertValidityPeriod)),
- ?match({ok, #'AttCertValidityPeriod'{}},
- 'OrberCSIv2':decode('AttCertValidityPeriod', list_to_binary(Enc))),
+ ?match({ok, #'AttCertValidityPeriod'{}},
+ 'OrberCSIv2':decode('AttCertValidityPeriod', list_to_binary(Enc))),
ok.
code_V2Form_api(doc) -> ["Code V2Form"];
code_V2Form_api(suite) -> [];
code_V2Form_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('V2Form', ?V2Form)),
- ?match({ok, #'V2Form'{}},
- 'OrberCSIv2':decode('V2Form', list_to_binary(Enc))),
+ ?match({ok, #'V2Form'{}},
+ 'OrberCSIv2':decode('V2Form', list_to_binary(Enc))),
ok.
code_IssuerSerial_api(doc) -> ["Code IssuerSerial"];
code_IssuerSerial_api(suite) -> [];
code_IssuerSerial_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('IssuerSerial', ?IssuerSerial)),
- ?match({ok, #'IssuerSerial'{}},
- 'OrberCSIv2':decode('IssuerSerial', list_to_binary(Enc))),
+ ?match({ok, #'IssuerSerial'{}},
+ 'OrberCSIv2':decode('IssuerSerial', list_to_binary(Enc))),
ok.
code_ObjectDigestInfo_api(doc) -> ["Code ObjectDigestInfo"];
code_ObjectDigestInfo_api(suite) -> [];
code_ObjectDigestInfo_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('ObjectDigestInfo', ?ObjectDigestInfo)),
- ?match({ok, #'ObjectDigestInfo'{}},
- 'OrberCSIv2':decode('ObjectDigestInfo', list_to_binary(Enc))),
+ ?match({ok, #'ObjectDigestInfo'{}},
+ 'OrberCSIv2':decode('ObjectDigestInfo', list_to_binary(Enc))),
ok.
%% PKIX1Explicit88
code_Certificate_api(doc) -> ["Code Certificate"];
code_Certificate_api(suite) -> [];
code_Certificate_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('Certificate', ?Certificate)),
- ?match({ok, #'Certificate'{}},
- 'OrberCSIv2':decode('Certificate', list_to_binary(Enc))),
+ ?match({ok, #'Certificate'{}},
+ 'OrberCSIv2':decode('Certificate', list_to_binary(Enc))),
ok.
code_TBSCertificate_api(doc) -> ["Code TBSCertificate"];
code_TBSCertificate_api(suite) -> [];
code_TBSCertificate_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('TBSCertificate', ?TBSCertificate)),
- ?match({ok, #'TBSCertificate'{}},
- 'OrberCSIv2':decode('TBSCertificate', list_to_binary(Enc))),
+ ?match({ok, #'TBSCertificate'{}},
+ 'OrberCSIv2':decode('TBSCertificate', list_to_binary(Enc))),
ok.
code_CertificateSerialNumber_api(doc) -> ["Code CertificateSerialNumber"];
code_CertificateSerialNumber_api(suite) -> [];
code_CertificateSerialNumber_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
+ {ok, Enc} =
+ ?match({ok, _},
'OrberCSIv2':encode('CertificateSerialNumber', ?CertificateSerialNumber)),
- ?match({ok, ?CertificateSerialNumber},
- 'OrberCSIv2':decode('CertificateSerialNumber', list_to_binary(Enc))),
+ ?match({ok, ?CertificateSerialNumber},
+ 'OrberCSIv2':decode('CertificateSerialNumber', list_to_binary(Enc))),
ok.
code_Version_api(doc) -> ["Code Version"];
code_Version_api(suite) -> [];
code_Version_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('Version', ?Version)),
- ?match({ok, ?Version}, 'OrberCSIv2':decode('Version', list_to_binary(Enc))),
+ ?match({ok, ?Version}, 'OrberCSIv2':decode('Version', list_to_binary(Enc))),
ok.
code_AlgorithmIdentifier_api(doc) -> ["Code AlgorithmIdentifier"];
code_AlgorithmIdentifier_api(suite) -> [];
code_AlgorithmIdentifier_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('AlgorithmIdentifier', ?AlgorithmIdentifier)),
- ?match({ok, #'AlgorithmIdentifier'{}},
- 'OrberCSIv2':decode('AlgorithmIdentifier', list_to_binary(Enc))),
+ ?match({ok, #'AlgorithmIdentifier'{}},
+ 'OrberCSIv2':decode('AlgorithmIdentifier', list_to_binary(Enc))),
ok.
code_Name_api(doc) -> ["Code Name"];
code_Name_api(suite) -> [];
code_Name_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('Name', ?Name)),
- ?match({ok, {rdnSequence,_}},
- 'OrberCSIv2':decode('Name', list_to_binary(Enc))),
+ ?match({ok, {rdnSequence,_}},
+ 'OrberCSIv2':decode('Name', list_to_binary(Enc))),
ok.
code_RDNSequence_api(doc) -> ["Code RDNSequence"];
code_RDNSequence_api(suite) -> [];
code_RDNSequence_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('RDNSequence', ?RDNSequence)),
- ?match({ok, [[#'AttributeTypeAndValue'{}]]},
- 'OrberCSIv2':decode('RDNSequence', list_to_binary(Enc))),
+ ?match({ok, [[#'AttributeTypeAndValue'{}]]},
+ 'OrberCSIv2':decode('RDNSequence', list_to_binary(Enc))),
ok.
code_RelativeDistinguishedName_api(doc) -> ["Code RelativeDistinguishedName"];
code_RelativeDistinguishedName_api(suite) -> [];
code_RelativeDistinguishedName_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('RelativeDistinguishedName', ?RelativeDistinguishedName)),
- ?match({ok, [#'AttributeTypeAndValue'{}]},
- 'OrberCSIv2':decode('RelativeDistinguishedName', list_to_binary(Enc))),
+ ?match({ok, [#'AttributeTypeAndValue'{}]},
+ 'OrberCSIv2':decode('RelativeDistinguishedName', list_to_binary(Enc))),
ok.
code_AttributeTypeAndValue_api(doc) -> ["Code AttributeTypeAndValue"];
code_AttributeTypeAndValue_api(suite) -> [];
code_AttributeTypeAndValue_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('AttributeTypeAndValue', ?AttributeTypeAndValue)),
- ?match({ok, #'AttributeTypeAndValue'{}},
- 'OrberCSIv2':decode('AttributeTypeAndValue', list_to_binary(Enc))),
+ ?match({ok, #'AttributeTypeAndValue'{}},
+ 'OrberCSIv2':decode('AttributeTypeAndValue', list_to_binary(Enc))),
ok.
code_Attribute_api(doc) -> ["Code Attribute"];
code_Attribute_api(suite) -> [];
code_Attribute_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('Attribute', ?Attribute)),
- ?match({ok, #'Attribute'{}},
- 'OrberCSIv2':decode('Attribute', list_to_binary(Enc))),
+ ?match({ok, #'Attribute'{}},
+ 'OrberCSIv2':decode('Attribute', list_to_binary(Enc))),
ok.
code_Validity_api(doc) -> ["Code Validity"];
code_Validity_api(suite) -> [];
code_Validity_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('Validity', ?Validity)),
- ?match({ok, #'Validity'{}},
- 'OrberCSIv2':decode('Validity', list_to_binary(Enc))),
+ ?match({ok, #'Validity'{}},
+ 'OrberCSIv2':decode('Validity', list_to_binary(Enc))),
ok.
code_SubjectPublicKeyInfo_api(doc) -> ["Code SubjectPublicKeyInfo"];
code_SubjectPublicKeyInfo_api(suite) -> [];
code_SubjectPublicKeyInfo_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('SubjectPublicKeyInfo', ?SubjectPublicKeyInfo)),
- ?match({ok, #'SubjectPublicKeyInfo'{}},
- 'OrberCSIv2':decode('SubjectPublicKeyInfo', list_to_binary(Enc))),
+ ?match({ok, #'SubjectPublicKeyInfo'{}},
+ 'OrberCSIv2':decode('SubjectPublicKeyInfo', list_to_binary(Enc))),
ok.
code_UniqueIdentifier_api(doc) -> ["Code UniqueIdentifier"];
code_UniqueIdentifier_api(suite) -> [];
code_UniqueIdentifier_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('UniqueIdentifier', ?UniqueIdentifier)),
- ?match({ok, _}, 'OrberCSIv2':decode('UniqueIdentifier', list_to_binary(Enc))),
+ ?match({ok, _}, 'OrberCSIv2':decode('UniqueIdentifier', list_to_binary(Enc))),
ok.
code_Extensions_api(doc) -> ["Code Extensions"];
code_Extensions_api(suite) -> [];
code_Extensions_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('Extensions', ?Extensions)),
- ?match({ok, [#'Extension'{}]},
- 'OrberCSIv2':decode('Extensions', list_to_binary(Enc))),
+ ?match({ok, [#'Extension'{}]},
+ 'OrberCSIv2':decode('Extensions', list_to_binary(Enc))),
ok.
code_Extension_api(doc) -> ["Code Extension"];
code_Extension_api(suite) -> [];
code_Extension_api(_Config) ->
- {ok, Enc} =
+ {ok, Enc} =
?match({ok, _}, 'OrberCSIv2':encode('Extension', ?Extension)),
- ?match({ok, #'Extension'{}},
- 'OrberCSIv2':decode('Extension', list_to_binary(Enc))),
+ ?match({ok, #'Extension'{}},
+ 'OrberCSIv2':decode('Extension', list_to_binary(Enc))),
ok.
%% OpenSSL generated x509 Certificate
code_OpenSSL509_api(doc) -> ["Code OpenSSL generated x509 Certificate"];
code_OpenSSL509_api(suite) -> [];
code_OpenSSL509_api(_Config) ->
- {ok, Cert} =
- ?match({ok, #'Certificate'{}},
+ {ok, Cert} =
+ ?match({ok, #'Certificate'{}},
'OrberCSIv2':decode('Certificate', ?X509DER)),
- AttrCertChain = #'AttributeCertChain'{attributeCert = ?AttributeCertificate,
+ AttrCertChain = #'AttributeCertChain'{attributeCert = ?AttributeCertificate,
certificateChain = [Cert]},
- {ok, EAttrCertChain} =
+ {ok, EAttrCertChain} =
?match({ok, _}, 'OrberCSIv2':encode('AttributeCertChain', AttrCertChain)),
- ?match({ok, #'AttributeCertChain'{}},
+ ?match({ok, #'AttributeCertChain'{}},
'OrberCSIv2':decode('AttributeCertChain', list_to_binary(EAttrCertChain))),
ok.
@@ -663,66 +669,65 @@ ssl_server_peercert_api(doc) -> ["Test ssl:peercert (server side)"];
ssl_server_peercert_api(suite) -> [];
ssl_server_peercert_api(_Config) ->
case os:type() of
- vxworks ->
- {skipped, "No SSL-support for VxWorks."};
- _ ->
- Options = orber_test_lib:get_options(iiop_ssl, server,
- 2, [{iiop_ssl_port, 0}]),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(Options)),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
- SSLOptions = orber_test_lib:get_options(ssl, client),
- {ok, Socket} =
- ?match({ok, _}, fake_client_ORB(ssl, ServerHost, ServerPort, SSLOptions)),
- {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
-%% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
-%% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
-% ?match({ok, #'Certificate'{}},
-% 'OrberCSIv2':decode('Certificate', PeerCert)),
- destroy_fake_ORB(ssl, Socket),
- ok
+ vxworks ->
+ {skipped, "No SSL-support for VxWorks."};
+ _ ->
+ Options = orber_test_lib:get_options(iiop_ssl, server,
+ 2, [{iiop_ssl_port, 0}]),
+ {ok, ServerNode, ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(Options)),
+ ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
+ SSLOptions = orber_test_lib:get_options(ssl, client),
+ {ok, Socket} =
+ ?match({ok, _}, fake_client_ORB(ssl, ServerHost, ServerPort, SSLOptions)),
+ {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
+ %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
+ %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
+ % ?match({ok, #'Certificate'{}},
+ % 'OrberCSIv2':decode('Certificate', PeerCert)),
+ destroy_fake_ORB(ssl, Socket),
+ ok
end.
ssl_client_peercert_api(doc) -> ["Test ssl:peercert (client side)"];
ssl_client_peercert_api(suite) -> [];
ssl_client_peercert_api(_Config) ->
case os:type() of
- vxworks ->
- {skipped, "No SSL-support for VxWorks."};
- _ ->
- Options = orber_test_lib:get_options(iiop_ssl, client,
- 2, [{iiop_ssl_port, 0}]),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(Options)),
- crypto:start(),
- ssl:start(),
- ssl:seed("testing"),
- SSLOptions = orber_test_lib:get_options(ssl, server),
- {ok, LSock} = ?match({ok, _}, ssl:listen(0, SSLOptions)),
- {ok, {_Address, LPort}} = ?match({ok, {_, _}}, ssl:sockname(LSock)),
- IOR = ?match({'IOP_IOR',_,_},
- iop_ior:create_external({1, 2}, "IDL:FAKE:1.0",
- "localhost", 6004, "FAKE",
- [#'IOP_TaggedComponent'
- {tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'
- {target_supports = 2,
- target_requires = 2,
- port = LPort}}])),
- spawn(orber_test_lib, remote_apply,
- [ClientNode, corba_object, non_existent, [IOR]]),
- {ok, Socket} = ?match({ok, _}, ssl:transport_accept(LSock)),
- ?match(ok, ssl:ssl_accept(Socket)),
-
- {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
-%% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
-%% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
-% ?match({ok, #'Certificate'{}},
-% 'OrberCSIv2':decode('Certificate', PeerCert)),
- ssl:close(Socket),
- ssl:close(LSock),
- ssl:stop(),
- ok
+ vxworks ->
+ {skipped, "No SSL-support for VxWorks."};
+ _ ->
+ Options = orber_test_lib:get_options(iiop_ssl, client,
+ 2, [{iiop_ssl_port, 0}]),
+ {ok, ClientNode, _ClientHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(Options)),
+ crypto:start(),
+ ssl:start(),
+ SSLOptions = orber_test_lib:get_options(ssl, server),
+ {ok, LSock} = ?match({ok, _}, ssl:listen(0, SSLOptions)),
+ {ok, {_Address, LPort}} = ?match({ok, {_, _}}, ssl:sockname(LSock)),
+ IOR = ?match({'IOP_IOR',_,_},
+ iop_ior:create_external({1, 2}, "IDL:FAKE:1.0",
+ "localhost", 6004, "FAKE",
+ [#'IOP_TaggedComponent'
+ {tag=?TAG_SSL_SEC_TRANS,
+ component_data=#'SSLIOP_SSL'
+ {target_supports = 2,
+ target_requires = 2,
+ port = LPort}}])),
+ spawn(orber_test_lib, remote_apply,
+ [ClientNode, corba_object, non_existent, [IOR]]),
+ {ok, Socket} = ?match({ok, _}, ssl:transport_accept(LSock)),
+ ?match(ok, ssl:ssl_accept(Socket)),
+
+ {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
+ %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
+ %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
+ % ?match({ok, #'Certificate'{}},
+ % 'OrberCSIv2':decode('Certificate', PeerCert)),
+ ssl:close(Socket),
+ ssl:close(LSock),
+ ssl:stop(),
+ ok
end.
%%-----------------------------------------------------------------
@@ -731,105 +736,105 @@ ssl_client_peercert_api(_Config) ->
-ifdef(false).
%% Not used yet.
context_test(Obj) ->
- IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
+ IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
value = true},
- IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous,
+ IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous,
value = false},
- IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName,
+ IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName,
value = [0,255]},
- IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain,
+ IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain,
value = [1,255]},
- IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName,
+ IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName,
value = [2,255]},
- IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX,
+ IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX,
value = [3,255]},
MTEstablishContext1 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken1,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken1,
client_authentication_token = [1, 255]}},
MTEstablishContext2 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken2,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken2,
client_authentication_token = [1, 255]}},
MTEstablishContext3 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken3,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken3,
client_authentication_token = [1, 255]}},
MTEstablishContext4 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken4,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken4,
client_authentication_token = [1, 255]}},
MTEstablishContext5 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken5,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken5,
client_authentication_token = [1, 255]}},
MTEstablishContext6 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken6,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken6,
client_authentication_token = [1, 255]}},
MTCompleteEstablishContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTCompleteEstablishContext,
- value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX,
+ {label = ?CSI_MsgType_MTCompleteEstablishContext,
+ value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX,
context_stateful = false,
final_context_token = [1, 255]}},
MTContextError = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTContextError,
+ {label = ?CSI_MsgType_MTContextError,
value = #'CSI_ContextError'{client_context_id = ?ULONGLONGMAX,
- major_status = 1,
- minor_status = 2,
+ major_status = 1,
+ minor_status = 2,
error_token = [2,255]}},
MTMessageInContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTMessageInContext,
- value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX,
+ {label = ?CSI_MsgType_MTMessageInContext,
+ value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX,
discard_context = true}},
- Ctx = [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ Ctx = [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext1},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext2},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext3},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext4},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext5},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext6},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTCompleteEstablishContext},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTContextError},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTMessageInContext}],
?line ?match(ok, orber_test_server:testing_iiop_context(Obj, [{context, Ctx}])).
@@ -837,7 +842,7 @@ context_test(Obj) ->
fake_server_ORB(Type, Port, Options) ->
start_ssl(Type),
{ok, ListenSocket, NewPort} =
- orber_socket:listen(Type, Port,
+ orber_socket:listen(Type, Port,
[{active, false}|Options]),
Socket = orber_socket:accept(Type, ListenSocket),
orber_socket:post_accept(Type, Socket),
@@ -847,7 +852,7 @@ fake_server_ORB(Type, Port, Options) ->
fake_server_ORB(Type, Port, Options, Action, Data) ->
start_ssl(Type),
- {ok, ListenSocket, _NewPort} =
+ {ok, ListenSocket, _NewPort} =
orber_socket:listen(Type, Port, [{active, false}|Options]),
Socket = orber_socket:accept(Type, ListenSocket),
orber_socket:post_accept(Type, Socket),
@@ -857,8 +862,7 @@ fake_server_ORB(Type, Port, Options, Action, Data) ->
start_ssl(ssl) ->
crypto:start(),
- ssl:start(),
- ssl:seed("testing");
+ ssl:start();
start_ssl(_) ->
ok.
@@ -887,13 +891,13 @@ fake_client_ORB(Type, Host, Port, Options, Action, Data) ->
do_client_action(Type, Socket, fragments, FragList) ->
ok = send_data(Type, Socket, FragList),
{ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} =
+ {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} =
cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
Par;
do_client_action(Type, Socket, fragments_max, FragList) ->
ok = send_data(Type, Socket, FragList),
{ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} =
+ {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} =
cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
Exc;
do_client_action(Type, Socket, message_error, Data) ->
@@ -918,4 +922,4 @@ send_data(_Type, _Socket, []) ->
send_data(Type, Socket, [H|T]) ->
orber_socket:write(Type, Socket, H),
send_data(Type, Socket, T).
-
+
diff --git a/lib/orber/test/multi_ORB_SUITE.erl b/lib/orber/test/multi_ORB_SUITE.erl
index 608fb23f3e..3c1ffd59d3 100644
--- a/lib/orber/test/multi_ORB_SUITE.erl
+++ b/lib/orber/test/multi_ORB_SUITE.erl
@@ -50,30 +50,33 @@
%%-----------------------------------------------------------------
%% External exports
%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
init_per_suite/1, end_per_suite/1, basic_PI_api/1, multi_orber_api/1,
- init_per_testcase/2, end_per_testcase/2, multi_pseudo_orber_api/1,
- light_orber_api/1, light_orber2_api/1,
+ init_per_testcase/2, end_per_testcase/2, multi_pseudo_orber_api/1,
+ light_orber_api/1, light_orber2_api/1,
ssl_1_multi_orber_api/1, ssl_2_multi_orber_api/1, ssl_reconfigure_api/1,
iiop_timeout_api/1, iiop_timeout_added_api/1, setup_connection_timeout_api/1,
setup_multi_connection_timeout_api/1, setup_multi_connection_timeout_random_api/1,
setup_multi_connection_timeout_attempts_api/1,
- fragments_server_api/1, fragments_max_server_api/1,
+ fragments_server_api/1, fragments_max_server_api/1,
fragments_max_server_added_api/1, fragments_client_api/1,
light_ifr_api/1, max_requests_api/1, max_requests_added_api/1,
- max_connections_api/1, max_packet_size_exceeded_api/1,
+ max_connections_api/1, max_packet_size_exceeded_api/1,
max_packet_size_ok_api/1, proxy_interface_api/1, proxy_interface_ipv6_api/1,
multiple_accept_api/1, implicit_context_api/1,
- pseudo_implicit_context_api/1, pseudo_two_implicit_context_api/1,
+ pseudo_implicit_context_api/1, pseudo_two_implicit_context_api/1,
oneway_implicit_context_api/1, implicit_context_roundtrip_api/1,
oneway_pseudo_implicit_context_api/1, flags_added_api/1,
- oneway_pseudo_two_implicit_context_api/1,
+ oneway_pseudo_two_implicit_context_api/1,
local_interface_api/1, local_interface_ctx_override_api/1,
local_interface_acl_override_api/1, bad_giop_header_api/1,
bad_fragment_id_client_api/1, bad_id_cancel_request_api/1,
close_connections_api/1, close_connections_local_interface_api/1,
- close_connections_local_interface_ctx_override_api/1, ssl_reconfigure_generation_3_api/1,
+ close_connections_local_interface_ctx_override_api/1,
ssl_1_multi_orber_generation_3_api/1, ssl_2_multi_orber_generation_3_api/1,
+ ssl_reconfigure_generation_3_api/1,
+ ssl_1_multi_orber_generation_3_api_old/1, ssl_2_multi_orber_generation_3_api_old/1,
+ ssl_reconfigure_generation_3_api_old/1,
close_connections_alt_iiop_addr_api/1, close_connections_multiple_profiles_api/1]).
@@ -84,15 +87,15 @@
%%-----------------------------------------------------------------
%% Func: all/1
-%% Args:
-%% Returns:
+%% Args:
+%% Returns:
%%-----------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
cases().
-groups() ->
+groups() ->
[].
init_per_group(_GroupName, Config) ->
@@ -105,7 +108,7 @@ end_per_group(_GroupName, Config) ->
%% NOTE - the fragment test cases must be first since we explicitly set a request
%% id. Otherwise, the request-id counter would be increased and we cannot know
%% what it is.
-cases() ->
+cases() ->
[fragments_server_api, fragments_max_server_api,
fragments_max_server_added_api, fragments_client_api,
flags_added_api, bad_fragment_id_client_api,
@@ -134,21 +137,28 @@ cases() ->
setup_multi_connection_timeout_attempts_api,
setup_multi_connection_timeout_random_api,
ssl_1_multi_orber_api,
+ ssl_1_multi_orber_generation_3_api_old,
ssl_1_multi_orber_generation_3_api,
ssl_2_multi_orber_api,
+ ssl_2_multi_orber_generation_3_api_old,
ssl_2_multi_orber_generation_3_api,
- ssl_reconfigure_generation_3_api, ssl_reconfigure_api].
+ ssl_reconfigure_api,
+ ssl_reconfigure_generation_3_api_old,
+ ssl_reconfigure_generation_3_api].
%%-----------------------------------------------------------------
%% Init and cleanup functions.
%%-----------------------------------------------------------------
-init_per_testcase(TC,Config)
+init_per_testcase(TC,Config)
when TC =:= ssl_1_multi_orber_api;
TC =:= ssl_2_multi_orber_api;
TC =:= ssl_reconfigure_api ->
init_ssl(Config);
-init_per_testcase(TC,Config)
- when TC =:= ssl_1_multi_orber_generation_3_api;
+init_per_testcase(TC,Config)
+ when TC =:= ssl_1_multi_orber_generation_3_api_old;
+ TC =:= ssl_2_multi_orber_generation_3_api_old;
+ TC =:= ssl_reconfigure_generation_3_api_old;
+ TC =:= ssl_1_multi_orber_generation_3_api;
TC =:= ssl_2_multi_orber_generation_3_api;
TC =:= ssl_reconfigure_generation_3_api ->
init_ssl_3(Config);
@@ -156,21 +166,31 @@ init_per_testcase(_Case, Config) ->
init_all(Config).
init_ssl(Config) ->
- case orber_test_lib:ssl_version() of
- no_ssl ->
- {skip,"SSL is not installed!"};
- _ ->
- init_all(Config)
+ case ?config(crypto_started, Config) of
+ true ->
+ case orber_test_lib:ssl_version() of
+ no_ssl ->
+ {skip, "SSL is not installed!"};
+ _ ->
+ init_all(Config)
+ end;
+ false ->
+ {skip, "Crypto did not start"}
end.
init_ssl_3(Config) ->
- case orber_test_lib:ssl_version() of
- 3 ->
- init_all(Config);
- 2 ->
- {skip,"Could not find the correct SSL version!"};
- no_ssl ->
- {skip,"SSL is not installed!"}
+ case ?config(crypto_started, Config) of
+ true ->
+ case orber_test_lib:ssl_version() of
+ 3 ->
+ init_all(Config);
+ 2 ->
+ {skip, "Could not find the correct SSL version!"};
+ no_ssl ->
+ {skip, "SSL is not installed!"}
+ end;
+ false ->
+ {skip, "Crypto did not start"}
end.
init_all(Config) ->
@@ -194,12 +214,18 @@ end_per_testcase(_Case, Config) ->
init_per_suite(Config) ->
if
is_list(Config) ->
- Config;
+ try crypto:start() of
+ ok ->
+ [{crypto_started, true} | Config]
+ catch _:_ ->
+ [{crypto_started, false} | Config]
+ end;
true ->
exit("Config not a list")
end.
end_per_suite(Config) ->
+ application:stop(crypto),
Config.
%%-----------------------------------------------------------------
@@ -211,238 +237,238 @@ implicit_context_api(suite) -> [];
implicit_context_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([])),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_call(Relay,
+ relay_call(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
-
+
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-implicit_context_roundtrip_api(doc) ->
+implicit_context_roundtrip_api(doc) ->
["IIOP Implicit Contex roundtrip tests"];
implicit_context_roundtrip_api(suite) -> [];
implicit_context_roundtrip_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
Relay = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
IOR = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [])),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_call(Relay,
+ relay_call(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-
-
+
+
oneway_implicit_context_api(doc) -> ["IIOP Implicit Contex oneway tests"];
oneway_implicit_context_api(suite) -> [];
oneway_implicit_context_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([])),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_cast(Relay,
+ relay_cast(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
- %% We must wait for a few seconds for the client to be able to set up the
+ %% We must wait for a few seconds for the client to be able to set up the
%% connection (since it's a oneway operation).
timer:sleep(5000),
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-
+
pseudo_implicit_context_api(doc) -> ["IIOP Implicit Contex tests (via pseudo object)"];
pseudo_implicit_context_api(suite) -> [];
pseudo_implicit_context_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_call(Relay,
+ relay_call(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-
-pseudo_two_implicit_context_api(doc) ->
+
+pseudo_two_implicit_context_api(doc) ->
["IIOP two Implicit Contex tests (via pseudo object)"];
pseudo_two_implicit_context_api(suite) -> [];
pseudo_two_implicit_context_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- put(oe_server_in_context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ put(oe_server_in_context,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
context_data = {interface,
IP}}]),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_call(Relay,
+ relay_call(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-
+
oneway_pseudo_implicit_context_api(doc) -> ["IIOP Implicit Contex tests (via pseudo object oneway)"];
oneway_pseudo_implicit_context_api(suite) -> [];
oneway_pseudo_implicit_context_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_cast(Relay,
+ relay_cast(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-
-oneway_pseudo_two_implicit_context_api(doc) ->
+
+oneway_pseudo_two_implicit_context_api(doc) ->
["IIOP two Implicit Contex tests (via pseudo object oneway)"];
oneway_pseudo_two_implicit_context_api(suite) -> [];
oneway_pseudo_two_implicit_context_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
%% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
+
Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
%% Add incoming implicit context which must be removed.
- put(oe_server_in_context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ put(oe_server_in_context,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
context_data = {interface,
IP}}]),
- ?match(ok,
+ ?match(ok,
orber_test_server:
- relay_cast(Relay,
+ relay_cast(Relay,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
Loopback}}]}],
IOR)),
?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
+ Conns = ?match([_,_],
orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
?match(true, lists:keymember(Loopback, 1, Conns)),
ok.
-
+
multiple_accept_api(doc) -> ["IIOP Multiple Accept tests"];
@@ -450,7 +476,7 @@ multiple_accept_api(suite) -> [];
multiple_accept_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
@@ -461,84 +487,84 @@ multiple_accept_api(_Config) ->
IOR1 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR1)),
?match([_], orber:iiop_connections(out)),
{ok, Ref1} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[Loopback, normal])),
IOR2 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR2)),
?match([_,_], orber:iiop_connections(out)),
{ok, Ref2} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[Loopback, normal, 9543])),
?match({error, eaddrinuse},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[Loopback, normal, 9543])),
IOR3 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++Loopback++":9543/NameService")),
- ?match({'external', {Loopback, 9543, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {Loopback, 9543, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR3)),
?match([_,_,_], orber:iiop_connections(out)),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
remove_listen_interface, [Ref1])),
%% Wait a few seconds to be sure that the connections really has been removed.
timer:sleep(4000),
?match([_,_], orber:iiop_connections(out)),
-
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
+
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
remove_listen_interface, [Ref2])),
%% Wait a few seconds to be sure that the connections really has been removed.
timer:sleep(4000),
?match([_], orber:iiop_connections(out)),
-
+
?match({'EXCEPTION',_},
corba:string_to_object("corbaloc::1.2@"++Loopback++":9543/NameService")),
?match({'EXCEPTION',_},
corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
-
+
IOR4 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR4)),
ok.
-proxy_interface_api(doc) -> ["IIOP Proxy Interface tests",
+proxy_interface_api(doc) -> ["IIOP Proxy Interface tests",
"This case test if the server ORB use the correct",
"interface when exporting IOR:s"];
proxy_interface_api(suite) -> [];
proxy_interface_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR1 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR1)),
IOR2 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR2)),
ok.
-proxy_interface_ipv6_api(doc) -> ["IIOP Proxy Interface tests",
+proxy_interface_ipv6_api(doc) -> ["IIOP Proxy Interface tests",
"This case test if the server ORB use the correct",
"IPv6 interface when exporting IOR:s"];
proxy_interface_ipv6_api(suite) -> [];
@@ -550,103 +576,103 @@ proxy_interface_ipv6_api(_Config) ->
Reason
end.
-proxy_interface_ipv6_api2() ->
+proxy_interface_ipv6_api2() ->
Loopback = orber_test_lib:get_loopback_interface(inet6),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
?ORB_ENV_LOCAL_INTERFACE)}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_IPV6}])),
-
+
IP = orber_test_lib:remote_apply(ClientNode, orber_test_lib, get_host, []),
IOR1 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
orber_test_lib:remote_apply(ClientNode, iop_ior, get_key, [IOR1])),
IOR2 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
orber_test_lib:remote_apply(ClientNode, iop_ior, get_key, [IOR2])),
ok.
-local_interface_api(doc) -> ["IIOP Local Interface tests",
+local_interface_api(doc) -> ["IIOP Local Interface tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
local_interface_api(suite) -> [];
local_interface_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, Loopback}])),
Port = orber:iiop_port(),
?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService"])),
- [{Loopback, RemotePort}] =
+ [{Loopback, RemotePort}] =
?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([{IP, Port}],
+ orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
?match([{IP, Port}], orber:find_sockname_by_peername(Loopback,RemotePort)),
?match([{Loopback, RemotePort}], orber:find_peername_by_sockname(IP, Port)),
- ?match([{Loopback, RemotePort}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_sockname_by_peername,
+ ?match([{Loopback, RemotePort}],
+ orber_test_lib:remote_apply(ClientNode, orber,
+ find_sockname_by_peername,
[IP, Port])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_peername_by_sockname,
+ ?match([{IP, Port}],
+ orber_test_lib:remote_apply(ClientNode, orber,
+ find_peername_by_sockname,
[Loopback,RemotePort])),
ok.
-local_interface_ctx_override_api(doc) ->
- ["IIOP Local Interface tests",
+local_interface_ctx_override_api(doc) ->
+ ["IIOP Local Interface tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
local_interface_ctx_override_api(suite) -> [];
local_interface_ctx_override_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, IP}])),
Port = orber:iiop_port(),
?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
[#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
+ {context_id=?ORBER_GENERIC_CTX_ID,
context_data = {interface, Loopback}}]])),
- [{Loopback, RemotePort}] =
+ [{Loopback, RemotePort}] =
?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([{IP, Port, Loopback}],
+ orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
?match([{IP, Port}], orber:find_sockname_by_peername(Loopback,RemotePort)),
?match([{Loopback, RemotePort}], orber:find_peername_by_sockname(IP, Port)),
- ?match([{Loopback, RemotePort}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_sockname_by_peername,
+ ?match([{Loopback, RemotePort}],
+ orber_test_lib:remote_apply(ClientNode, orber,
+ find_sockname_by_peername,
[IP, Port])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_peername_by_sockname,
+ ?match([{IP, Port}],
+ orber_test_lib:remote_apply(ClientNode, orber,
+ find_peername_by_sockname,
[Loopback,RemotePort])),
ok.
-local_interface_acl_override_api(doc) ->
- ["IIOP Local Interface tests",
+local_interface_acl_override_api(doc) ->
+ ["IIOP Local Interface tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
local_interface_acl_override_api(suite) -> [];
@@ -654,74 +680,74 @@ local_interface_acl_override_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
ACL = [{tcp_out, IP ++ "/18", [Loopback]}],
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, IP},
{iiop_acl, ACL},
{flags, ?ORB_ENV_USE_ACL_OUTGOING}])),
Port = orber:iiop_port(),
?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
[#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
+ {context_id=?ORBER_GENERIC_CTX_ID,
context_data = {interface, IP}}]])),
?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService"])),
- [{Loopback, RemotePort}] =
+ [{Loopback, RemotePort}] =
?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
- ?match([{IP, Port, IP}], orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([{IP, Port, IP}], orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
?match([{IP, Port}], orber:find_sockname_by_peername(Loopback,RemotePort)),
?match([{Loopback, RemotePort}], orber:find_peername_by_sockname(IP, Port)),
- ?match([{Loopback, RemotePort}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_sockname_by_peername,
+ ?match([{Loopback, RemotePort}],
+ orber_test_lib:remote_apply(ClientNode, orber,
+ find_sockname_by_peername,
[IP, Port])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_peername_by_sockname,
+ ?match([{IP, Port}],
+ orber_test_lib:remote_apply(ClientNode, orber,
+ find_peername_by_sockname,
[Loopback,RemotePort])),
ok.
-iiop_timeout_api(doc) -> ["IIOP TIMEOUT API tests",
+iiop_timeout_api(doc) -> ["IIOP TIMEOUT API tests",
"This case test if timeout configuration behaves correctly"];
iiop_timeout_api(suite) -> [];
iiop_timeout_api(_Config) ->
-
+
%% Install two secure orber.
- {ok, ClientNode, ClientHost} =
+ {ok, ClientNode, ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_timeout, 6},
{iiop_connection_timeout, 3},
{iiop_in_connection_timeout, 3}])),
ClientPort = orber_test_lib:remote_apply(ClientNode, orber, iiop_port, []),
-
- {ok, ServerNode, ServerHost} =
+
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_timeout, 6},
{iiop_connection_timeout, 3},
{iiop_in_connection_timeout, 12}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[timeout])),
- %% Tell client_orb to interoperate with server_orb.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ %% Tell client_orb to interoperate with server_orb.
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
lookup,
[ServerHost, ServerPort])),
%% Interop worked fine, perform delay tests.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
timeouts,
[ServerHost, ServerPort, 6000])),
-
+
%% Create a connection to the "client_orb", which will now act as server.
- ?match({'IOP_IOR',_,_},
+ ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.2@"++ClientHost++":"++integer_to_list(ClientPort)++"/NameService")),
%% Check that the connection is established.
?match([{_, ClientPort}], orber:iiop_connections(out)),
@@ -729,13 +755,13 @@ iiop_timeout_api(_Config) ->
%% have been closed.
timer:sleep(8000),
?match([], orber:iiop_connections(out)),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
[timeout])),
ok.
-iiop_timeout_added_api(doc) -> ["IIOP TIMEOUT API tests",
+iiop_timeout_added_api(doc) -> ["IIOP TIMEOUT API tests",
"This case test if timeout configuration behaves correctly"];
iiop_timeout_added_api(suite) -> [];
iiop_timeout_added_api(_Config) ->
@@ -743,18 +769,18 @@ iiop_timeout_added_api(_Config) ->
{ok, Node, _Host} = ?match({ok,_,_}, orber_test_lib:js_node([])),
Port = 1 + orber_test_lib:remote_apply(Node, orber, iiop_port, []),
?match({ok, _},
- orber_test_lib:remote_apply(Node, orber,
- add_listen_interface,
- [IP, normal,
+ orber_test_lib:remote_apply(Node, orber,
+ add_listen_interface,
+ [IP, normal,
[{iiop_in_connection_timeout, 3},
{flags, ?ORB_ENV_LOCAL_INTERFACE},
{iiop_port, Port}]])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[timeout])),
- ?match({'IOP_IOR',_,_},
+ ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService")),
%% Check that the connection is established.
?match([{_, Port}], orber:iiop_connections(out)),
@@ -762,9 +788,9 @@ iiop_timeout_added_api(_Config) ->
%% have been closed.
timer:sleep(8000),
?match([], orber:iiop_connections(out)),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[timeout])),
ok.
@@ -772,27 +798,27 @@ iiop_timeout_added_api(_Config) ->
%% API tests for ORB to ORB using pseudo call/cast, no security
%%-----------------------------------------------------------------
-multi_pseudo_orber_api(doc) ->
- ["MULTI ORB PSEUDO API tests",
+multi_pseudo_orber_api(doc) ->
+ ["MULTI ORB PSEUDO API tests",
"This case test if data encode/decode (IIOP) for pseudo objects",
"produce the correct result, i.e., the test_server echos",
"the input parameter or an exception is raised (MARSHAL)."];
multi_pseudo_orber_api(suite) -> [];
multi_pseudo_orber_api(_Config) ->
%% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
+ {ok, Node, Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node()),
Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[pseudo])),
-
+
NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
corba:string_to_object("corbaloc::1.1@"++Host++":"++
integer_to_list(Port)++"/NameService")),
- Obj =
- ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+ Obj =
+ ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
orber_test_lib:corba_object_tests(Obj, NSR),
@@ -809,11 +835,11 @@ multi_pseudo_orber_api(_Config) ->
orber_test_lib:test_coding(Obj),
%% Test if exit is handled properly.
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
+ ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
orber_test_server:stop_brutal(Obj)),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[pseudo])),
ok.
@@ -821,77 +847,77 @@ multi_pseudo_orber_api(_Config) ->
%%-----------------------------------------------------------------
%% API tests for ORB to ORB with local flags definition set.
%%-----------------------------------------------------------------
-flags_added_api(doc) ->
+flags_added_api(doc) ->
["MULTI ORB PSEUDO with local flags definition set"];
flags_added_api(suite) -> [];
flags_added_api(_Config) ->
%% --- Create a slave-node ---
IP = orber_test_lib:get_host(),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([])),
+ {ok, Node, _Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node([])),
Port = 1 + orber_test_lib:remote_apply(Node, orber, iiop_port, []),
?match({ok, _},
- orber_test_lib:remote_apply(Node, orber,
- add_listen_interface,
- [IP, normal,
+ orber_test_lib:remote_apply(Node, orber,
+ add_listen_interface,
+ [IP, normal,
[{flags, (?ORB_ENV_LOCAL_INTERFACE bor
?ORB_ENV_EXCLUDE_CODESET_COMPONENT)},
{iiop_port, Port}]])),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[pseudo])),
Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.1@"++IP++":"++
integer_to_list(Port)++"/NameService#mamba")),
- ?match({'external', {IP, Port, _ObjectKey, _Counter,
- #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=
- #'IIOP_ProfileBody_1_1'{components=[]}},
- _NewHD}},
+ ?match({'external', {IP, Port, _ObjectKey, _Counter,
+ #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
+ profile_data=
+ #'IIOP_ProfileBody_1_1'{components=[]}},
+ _NewHD}},
iop_ior:get_key(Obj)),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[pseudo])),
ok.
-
+
%%-----------------------------------------------------------------
%% API tests for ORB to ORB with limited concurrent requests
%%-----------------------------------------------------------------
-max_requests_api(doc) ->
+max_requests_api(doc) ->
["MULTI ORB PSEUDO with limited concurrent requests tests"];
max_requests_api(suite) -> [];
max_requests_api(_Config) ->
%% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_max_in_requests, 1}])),
+ {ok, Node, Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{iiop_max_in_requests, 1}])),
Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
max_requests(Node, Host, Port).
-max_requests_added_api(doc) ->
+max_requests_added_api(doc) ->
["MULTI ORB PSEUDO with limited concurrent requests tests"];
max_requests_added_api(suite) -> [];
max_requests_added_api(_Config) ->
%% --- Create a slave-node ---
[IP] = ?match([_], orber:host()),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([])),
+ {ok, Node, _Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node([])),
Port = 1 + orber_test_lib:remote_apply(Node, orber, iiop_port, []),
?match({ok, _},
- orber_test_lib:remote_apply(Node, orber,
- add_listen_interface,
- [IP, normal,
+ orber_test_lib:remote_apply(Node, orber,
+ add_listen_interface,
+ [IP, normal,
[{iiop_max_in_requests, 1},
{flags, ?ORB_ENV_LOCAL_INTERFACE},
{iiop_port, Port}]])),
max_requests(Node, IP, Port).
-max_requests(Node, Host, Port) ->
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+max_requests(Node, Host, Port) ->
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[pseudo])),
Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.1@"++Host++":"++
@@ -899,7 +925,7 @@ max_requests(Node, Host, Port) ->
%% Can we even contact the object?
?match(ok, orber_test_server:print(Obj)),
-
+
%% Invoke one blocking call followed by several invokations.
spawn(orber_test_server, pseudo_call_delay, [Obj, 15000]),
%% Wait for a second to be sure that the previous request has been sent
@@ -912,8 +938,8 @@ max_requests(Node, Host, Port) ->
%% allow one request at a time to the target ORB.
?match(true, (MegaSecsB + (Before+8)*1000000) < (MegaSecsA + After*1000000)),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[pseudo])),
ok.
@@ -921,17 +947,17 @@ max_requests(Node, Host, Port) ->
%%-----------------------------------------------------------------
%% API tests for ORB to ORB with limited concurrent connections
%%-----------------------------------------------------------------
-max_connections_api(doc) ->
+max_connections_api(doc) ->
["MULTI ORB PSEUDO with limited concurrent connections tests"];
max_connections_api(suite) -> [];
max_connections_api(_Config) ->
%% --- Create a slave-node ---
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_backlog, 0},
{iiop_max_in_connections, 2}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
%% Claim connection 1 & 2
@@ -939,26 +965,26 @@ max_connections_api(_Config) ->
corba:string_to_object("corbaname::1.2@"++ServerHost++":"++
integer_to_list(ServerPort)++"/NameService#mamba")),
%% Claim backlog
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
+ {ok, ClientNode, _ClientHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node()),
spawn(ClientNode, orber_test_server, print, [Obj]),
timer:sleep(5000),
?match([_], orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [])),
-
+
%% Try to connect. Should fail. Due to the behavior of different TCP stacks, backlog 1
%% might not be the precise value. Hence, we also need to define the iiop_timeout. Otherwise
%% this test case will fail. For the same reason we must GC this connection.
- {ok, ClientNodeII, _ClientHostII} =
+ {ok, ClientNodeII, _ClientHostII} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_setup_connection_timeout, 5},
{iiop_timeout, 5},
{iiop_connection_timeout, 8}])),
- ?match({'EXCEPTION', _},
- orber_test_lib:remote_apply(ClientNodeII, orber_test_server,
+ ?match({'EXCEPTION', _},
+ orber_test_lib:remote_apply(ClientNodeII, orber_test_server,
testing_iiop_string, [Obj, "Fail"])),
-
+
%% Remove 2 connections. We need to wait a moment so that both sides has detected it.
timer:sleep(5000),
?match([_,_], orber:iiop_connections()),
@@ -968,23 +994,23 @@ max_connections_api(_Config) ->
?match(ok, orber_iiop_pm:close_connection([{Host, Port}])),
timer:sleep(5000),
?match([], orber:iiop_connections()),
-
+
?match([_], orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [])),
?match([], orber_test_lib:remote_apply(ClientNodeII, orber,
iiop_connections, [])),
- ?match({ok, "OK"},
- orber_test_lib:remote_apply(ClientNodeII, orber_test_server,
+ ?match({ok, "OK"},
+ orber_test_lib:remote_apply(ClientNodeII, orber_test_server,
testing_iiop_string, [Obj, "OK"])),
-
+
timer:sleep(4000),
?match([_], orber_test_lib:remote_apply(ClientNodeII, orber,
iiop_connections, [])),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
[pseudo])),
ok.
@@ -993,18 +1019,18 @@ max_connections_api(_Config) ->
%%-----------------------------------------------------------------
%% API tests for terminating connection by using an IOR.
%%-----------------------------------------------------------------
-close_connections_api(doc) ->
+close_connections_api(doc) ->
["Close outgoing connection "];
close_connections_api(suite) -> [];
close_connections_api(_Config) ->
%% --- Create a slave-node ---
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IP = orber_test_lib:get_host(),
@@ -1028,108 +1054,108 @@ close_connections_api(_Config) ->
ok.
-close_connections_local_interface_api(doc) ->
- ["IIOP Local Interface disconnect tests",
+close_connections_local_interface_api(doc) ->
+ ["IIOP Local Interface disconnect tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
close_connections_local_interface_api(suite) -> [];
close_connections_local_interface_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, Loopback}])),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address, IP}])),
Port = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService"])),
%% Check that the connnection is up and running using the default interface
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([{IP, Port}],
+ orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
%% Try to close the connection
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
close_connection, [IOR])),
%% Wait a moment so that both sides has detected it.
timer:sleep(5000),
%% Now the connection shall be gone.
- ?match([], orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([], orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
ok.
-close_connections_local_interface_ctx_override_api(doc) ->
- ["IIOP Local Interface disconnect tests",
+close_connections_local_interface_ctx_override_api(doc) ->
+ ["IIOP Local Interface disconnect tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
close_connections_local_interface_ctx_override_api(suite) -> [];
close_connections_local_interface_ctx_override_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, IP},
{ip_address, IP}])),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{ip_address, IP}])),
Port = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
+ orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
[#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
+ {context_id=?ORBER_GENERIC_CTX_ID,
context_data = {interface, Loopback}}]])),
timer:sleep(2000),
%% Check that the connnection is up and running using the default interface
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
-
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
+
+ ?match([{IP, Port, Loopback}],
+ orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
%% Try to close not supplying the interface.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
close_connection, [IOR])),
-
+
timer:sleep(2000),
%% The connection shall still be up and running
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([{IP, Port, Loopback}],
+ orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
%% Try to close not supplying the interface.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
close_connection, [IOR, IP])),
- timer:sleep(2000),
+ timer:sleep(2000),
%% The connection shall still be up and running
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([{IP, Port, Loopback}],
+ orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
-
+
%% Try to close supplying the correct interface.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
close_connection, [IOR, Loopback])),
%% Wait a moment so that both sides has detected it.
timer:sleep(5000),
%% Now the connection shall be gone.
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
- ?match([], orber_test_lib:remote_apply(ClientNode, orber,
+ ?match([], orber_test_lib:remote_apply(ClientNode, orber,
iiop_connections, [out])),
ok.
-close_connections_alt_iiop_addr_api(doc) ->
- ["IIOP alternate address disconnect tests",
+close_connections_alt_iiop_addr_api(doc) ->
+ ["IIOP alternate address disconnect tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
close_connections_alt_iiop_addr_api(suite) -> [];
@@ -1137,12 +1163,12 @@ close_connections_alt_iiop_addr_api(_Config) ->
%% --- Create a slave-node ---
Loopback = orber_test_lib:get_loopback_interface(),
IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{giop_version, {1, 2}},
{ip_address, {multiple, [IP, Loopback]}}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[{nameservice, Loopback, ServerPort}])),
%% Create two connections
Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
@@ -1151,25 +1177,25 @@ close_connections_alt_iiop_addr_api(_Config) ->
?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.2@"++Loopback++":"++
integer_to_list(ServerPort)++"/NameService#mamba")),
- timer:sleep(2000),
+ timer:sleep(2000),
%% The connection shall still be up and running
?match([{_,_}, {_,_}], orber:iiop_connections(out)),
?match([{_,_}, {_,_}],
- orber_test_lib:remote_apply(ServerNode, orber,
+ orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
-
+
%% Try to close the connection
?match(ok, orber:close_connection(Obj)),
%% Wait a moment so that both sides has detected it.
timer:sleep(5000),
%% Now the connections shall be gone.
?match([], orber:iiop_connections(out)),
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
ok.
-close_connections_multiple_profiles_api(doc) ->
- ["IIOP alternate address disconnect tests",
+close_connections_multiple_profiles_api(doc) ->
+ ["IIOP alternate address disconnect tests",
"This case test if the server ORB use the correct",
"local interface when connecting to another ORB"];
close_connections_multiple_profiles_api(suite) -> [];
@@ -1177,11 +1203,11 @@ close_connections_multiple_profiles_api(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
%% --- Create a slave-node ---
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address,
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{ip_address,
{multiple, [Loopback, IP]}}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
install_test_data, [nameservice])),
%% Create two connections
Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
@@ -1193,23 +1219,23 @@ close_connections_multiple_profiles_api(_Config) ->
%% The connection shall still be up and running
?match([{_,_}, {_,_}], orber:iiop_connections(out)),
?match([{_,_}, {_,_}],
- orber_test_lib:remote_apply(ServerNode, orber,
+ orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
-
+
%% Try to close the connection
?match(ok, orber:close_connection(Obj)),
%% Wait a moment so that both sides has detected it.
timer:sleep(5000),
%% Now the connections shall be gone.
?match([], orber:iiop_connections(out)),
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
+ ?match([], orber_test_lib:remote_apply(ServerNode, orber,
iiop_connections, [in])),
ok.
%%-----------------------------------------------------------------
%% API tests for ORB to ORB with iiop_packet_size set
%%-----------------------------------------------------------------
-max_packet_size_exceeded_api(doc) ->
+max_packet_size_exceeded_api(doc) ->
["Exceed the maximum request size"];
max_packet_size_exceeded_api(suite) -> [];
max_packet_size_exceeded_api(_Config) ->
@@ -1219,11 +1245,11 @@ max_packet_size_exceeded_api(_Config) ->
{ok, LS} ->
(catch gen_tcp:close(LS)),
%% --- Create a slave-node ---
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_packet_size, 1}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber,
iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
+ ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
ok
end.
@@ -1231,7 +1257,7 @@ max_packet_size_exceeded_api(_Config) ->
%%-----------------------------------------------------------------
%% API tests for ORB to ORB with iiop_packet_size set
%%-----------------------------------------------------------------
-max_packet_size_ok_api(doc) ->
+max_packet_size_ok_api(doc) ->
["Not exceed the maximum request size"];
max_packet_size_ok_api(suite) -> [];
max_packet_size_ok_api(_Config) ->
@@ -1241,7 +1267,7 @@ max_packet_size_ok_api(_Config) ->
{ok, LS} ->
(catch gen_tcp:close(LS)),
%% --- Create a slave-node ---
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_packet_size, 5000}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber,
iiop_port, []),
@@ -1251,7 +1277,7 @@ max_packet_size_ok_api(_Config) ->
end.
-
+
%%-----------------------------------------------------------------
%% API tests for ORB to ORB, no security
%%-----------------------------------------------------------------
@@ -1259,49 +1285,49 @@ max_packet_size_ok_api(_Config) ->
light_ifr_api(doc) -> ["LIGHT IFR ORB API tests"];
light_ifr_api(suite) -> [];
light_ifr_api(_Config) ->
-
- {ok, ClientNode, _ClientHost} =
+
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, 128}])),
?match([_,_,_,_], orber_test_lib:remote_apply(ClientNode, orber, get_tables, [])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ install_test_data,
[nameservice])),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, 128}])),
+ {ok, ServerNode, ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{flags, 128}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
?match([_,_,_,_], orber_test_lib:remote_apply(ServerNode, orber, get_tables, [])),
- Obj = ?match({'IOP_IOR',_,_},
+ Obj = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaname::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib, test_coding, [Obj])),
?match(0, orber_test_lib:remote_apply(ClientNode, orber_diagnostics, missing_modules, [])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
[#orber_light_ifr{id = "FakeId1",
- module=non_existing,
+ module=non_existing,
type=?IFR_StructDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
[#orber_light_ifr{id = "FakeId2",
- module=non_existing,
+ module=non_existing,
type=?IFR_UnionDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
[#orber_light_ifr{id = "FakeId3",
- module=non_existing,
+ module=non_existing,
type=?IFR_ExceptionDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
[#orber_light_ifr{id = "FakeId4",
- module=non_existing,
+ module=non_existing,
type=?IFR_InterfaceDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
[#orber_light_ifr{id = "FakeId5",
- module=orber_test_lib,
+ module=orber_test_lib,
type=?IFR_InterfaceDef}])),
?match(5, orber_test_lib:remote_apply(ClientNode, orber_diagnostics, missing_modules, [])),
@@ -1316,14 +1342,14 @@ light_ifr_api(_Config) ->
absolute_name="::Module::NonExisting"})),
?match(ok, mnesia:dirty_write(#ir_InterfaceDef{ir_Internal_ID = "FakedIId5",
absolute_name="::orber::test::lib"})),
-
+
?match(5, orber_diagnostics:missing_modules()),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
[nameservice])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ uninstall_test_data,
[nameservice])),
ok.
@@ -1331,23 +1357,23 @@ light_ifr_api(_Config) ->
%% API tests for ORB to ORB, no security
%%-----------------------------------------------------------------
-light_orber_api(doc) -> ["LIGHT ORB API tests",
+light_orber_api(doc) -> ["LIGHT ORB API tests",
"This case test if a light Orber can communicate correctly",
"with an fully installed Orber."];
light_orber_api(suite) -> [];
light_orber_api(_Config) ->
%% --- Create a slave-node ---
LocalHost = net_adm:localhost(),
- {ok, Node, _Host} =
+ {ok, Node, _Host} =
?match({ok,_,_}, orber_test_lib:js_node([{lightweight, ["iiop://"++LocalHost++":"++integer_to_list(orber:iiop_port())]}],
lightweight)),
?match(ok, orber:info(io)),
?match([_], orber_test_lib:remote_apply(Node, orber_env, get_lightweight_nodes,[])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[light])),
-
+
Obj1=(catch orber_test_server:oe_create(state,[{pseudo,true}])),
?match({_,pseudo,orber_test_server_impl, _,_, _}, Obj1),
Obj2=(catch orber_test_server:oe_create(state,[])),
@@ -1357,11 +1383,11 @@ light_orber_api(_Config) ->
'CosNaming_NamingContext':bind(NS, lname:new(["mamba"]), Obj1),
'CosNaming_NamingContext':bind(NS, lname:new(["viper"]), Obj2),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
light_tests,
[LocalHost,
orber:iiop_port(), "viper"])),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
light_tests,
[LocalHost,
orber:iiop_port(), "mamba"])),
@@ -1370,17 +1396,17 @@ light_orber_api(_Config) ->
catch corba:dispose(Obj1),
catch corba:dispose(Obj2),
- catch 'CosNaming_NamingContext':destroy(NS),
+ catch 'CosNaming_NamingContext':destroy(NS),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[light])),
ok.
%%-----------------------------------------------------------------
%% API tests for ORB to ORB, no security
%%-----------------------------------------------------------------
-light_orber2_api(doc) -> ["LIGHT ORB API tests",
+light_orber2_api(doc) -> ["LIGHT ORB API tests",
"This case test if a light Orber can communicate correctly",
"with an fully installed Orber. This case test if we can",
"start as lightweight without first setting the environment",
@@ -1389,16 +1415,16 @@ light_orber2_api(suite) -> [];
light_orber2_api(_Config) ->
%% --- Create a slave-node ---
LocalHost = net_adm:localhost(),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([],
+ {ok, Node, _Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node([],
{lightweight, ["iiop://"++LocalHost++":"++integer_to_list(orber:iiop_port())]})),
?match(ok, orber:info(io)),
?match([_], orber_test_lib:remote_apply(Node, orber_env, get_lightweight_nodes,[])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[light])),
-
+
Obj1=(catch orber_test_server:oe_create(state,[{pseudo,true}])),
?match({_,pseudo,orber_test_server_impl, _,_, _}, Obj1),
Obj2=(catch orber_test_server:oe_create(state,[])),
@@ -1407,12 +1433,12 @@ light_orber2_api(_Config) ->
NS = corba:resolve_initial_references("NameService"),
'CosNaming_NamingContext':bind(NS, lname:new(["mamba"]), Obj1),
'CosNaming_NamingContext':bind(NS, lname:new(["viper"]), Obj2),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
light_tests,
[LocalHost,
orber:iiop_port(), "viper"])),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
light_tests,
[LocalHost,
orber:iiop_port(), "mamba"])),
@@ -1421,10 +1447,10 @@ light_orber2_api(_Config) ->
catch corba:dispose(Obj1),
catch corba:dispose(Obj2),
- catch 'CosNaming_NamingContext':destroy(NS),
+ catch 'CosNaming_NamingContext':destroy(NS),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[light])),
ok.
@@ -1432,13 +1458,13 @@ light_orber2_api(_Config) ->
%% API tests for ORB to ORB, no security
%%-----------------------------------------------------------------
-multi_orber_api(doc) -> ["MULTI ORB API tests",
+multi_orber_api(doc) -> ["MULTI ORB API tests",
"This case test if data encode/decode (IIOP)",
"produce the correct result, i.e., the test_server echos",
"the input parameter or an exception is raised (MARSHAL)."];
multi_orber_api(suite) -> [];
multi_orber_api(_Config) ->
-
+
NewICObj1 = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([])),
NewICObj2 = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{regname, {local, newic2}}])),
NewICObj3 = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{regname, {global, newic3}}])),
@@ -1448,34 +1474,34 @@ multi_orber_api(_Config) ->
catch corba:dispose(NewICObj1),
catch corba:dispose(NewICObj2),
catch corba:dispose(NewICObj3),
-
+
%% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
+ {ok, Node, Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node()),
Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[nameservice])),
-
+
NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
corba:string_to_object("corbaloc::1.2@"++Host++":"++
integer_to_list(Port)++"/NameService")),
-
+
?match({'EXCEPTION',{'CosNaming_NamingContext_NotFound',_,_,_}},
'CosNaming_NamingContext':resolve(NSR, lname:new(["not_exist"]))),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+ Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
?match(ok, orber_test_server:print(Obj)),
- Obj12B = ?match({'IOP_IOR',_,_},
+ Obj12B = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.2@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj11B = ?match({'IOP_IOR',_,_},
+
+ Obj11B = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.1@"++Host++":"++integer_to_list(Port)++"/Mamba")),
- Obj10B = ?match({'IOP_IOR',_,_},
+ Obj10B = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Mamba")),
context_test(Obj12B),
@@ -1484,7 +1510,7 @@ multi_orber_api(_Config) ->
?match(ok, orber_test_server:print(Obj12B)),
?match(ok, orber_test_server:print(Obj11B)),
?match(ok, orber_test_server:print(Obj10B)),
- ?match({'EXCEPTION',{'CosNaming_NamingContextExt_InvalidAddress',_}},
+ ?match({'EXCEPTION',{'CosNaming_NamingContextExt_InvalidAddress',_}},
corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Wrong")),
?match(ok, orber_test_lib:corba_object_tests(Obj12B, NSR)),
@@ -1493,22 +1519,22 @@ multi_orber_api(_Config) ->
%%--- Testing code and decode arguments ---
orber_test_lib:test_coding(Obj),
-
- ?match({'EXCEPTION',#'BAD_CONTEXT'{}},
+
+ ?match({'EXCEPTION',#'BAD_CONTEXT'{}},
orber_test_server:
- print(Obj12B,
+ print(Obj12B,
[{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {interface,
{127,0,0,1}}}]}])),
-
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
+
+ ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
orber_test_server:stop_brutal(Obj12B)),
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
+ ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
orber_test_server:print(Obj12B)),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[nameservice])),
ok.
@@ -1516,9 +1542,9 @@ multi_orber_api(_Config) ->
%%-----------------------------------------------------------------
%% API tests for ORB to ORB, no security, using basic interceptors
%%-----------------------------------------------------------------
-basic_PI_api(doc) -> ["MULTI ORB API tests",
+basic_PI_api(doc) -> ["MULTI ORB API tests",
"This case test if data encode/decode (IIOP)",
- "produce the correct result when using basic interceptors,",
+ "produce the correct result when using basic interceptors,",
"i.e., the test_server echos",
"the input parameter or an exception is raised (MARSHAL)."];
basic_PI_api(suite) -> [];
@@ -1526,21 +1552,21 @@ basic_PI_api(_Config) ->
%% Change configuration to use Basic Interceptors.
orber:configure_override(interceptors, {native, [orber_test_lib]}),
%% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{interceptors, {native, [orber_test_lib]}}])),
+ {ok, Node, Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{interceptors, {native, [orber_test_lib]}}])),
Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[nameservice])),
-
- Obj12 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+
+ Obj12 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.2@"++Host++":"++integer_to_list(Port)++"/NameService#mamba")),
-
- Obj11 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+
+ Obj11 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.1@"++Host++":"++integer_to_list(Port)++"/NameService#mamba")),
-
- Obj10 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+
+ Obj10 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.0@"++Host++":"++integer_to_list(Port)++"/NameService#mamba")),
?match(ok, corba:print_object(Obj12)),
@@ -1552,13 +1578,13 @@ basic_PI_api(_Config) ->
?match(ok, orber_test_server:print(Obj10)),
- Obj12B = ?match({'IOP_IOR',_,_},
+ Obj12B = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.2@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj11B = ?match({'IOP_IOR',_,_},
+
+ Obj11B = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.1@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj10B = ?match({'IOP_IOR',_,_},
+
+ Obj10B = ?match({'IOP_IOR',_,_},
corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Mamba")),
?match(ok, corba:print_object(Obj12B, info_msg)),
@@ -1568,7 +1594,7 @@ basic_PI_api(_Config) ->
?match(ok, orber_test_server:print(Obj12B)),
?match(ok, orber_test_server:print(Obj11B)),
?match(ok, orber_test_server:print(Obj10B)),
- ?match({'EXCEPTION',{'CosNaming_NamingContextExt_InvalidAddress',_}},
+ ?match({'EXCEPTION',{'CosNaming_NamingContextExt_InvalidAddress',_}},
corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Wrong")),
?match(ok, orber_test_lib:alternate_iiop_address(Host, Port)),
@@ -1583,8 +1609,8 @@ basic_PI_api(_Config) ->
application:set_env(orber, interceptors, false),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ uninstall_test_data,
[nameservice])),
ok.
@@ -1593,62 +1619,95 @@ basic_PI_api(_Config) ->
%% API tests for ORB to ORB, ssl security depth 1
%%-----------------------------------------------------------------
-ssl_1_multi_orber_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+ssl_1_multi_orber_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
"This case set up two secure orbs and test if they can",
"communicate. The case also test to access one of the",
"secure orbs which must raise a NO_PERMISSION exception."];
ssl_1_multi_orber_api(suite) -> [];
ssl_1_multi_orber_api(_Config) ->
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
1, [{iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
1, [{iiop_ssl_port, 0}]),
ssl_suite(ServerOptions, ClientOptions).
-
-ssl_1_multi_orber_generation_3_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+
+
+ssl_1_multi_orber_generation_3_api_old(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+ "This case set up two secure orbs and test if they can",
+ "communicate. The case also test to access one of the",
+ "secure orbs which must raise a NO_PERMISSION exception."];
+ssl_1_multi_orber_generation_3_api_old(suite) -> [];
+ssl_1_multi_orber_generation_3_api_old(_Config) ->
+
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
+ 1, [{ssl_generation, 3},
+ {iiop_ssl_port, 0}]),
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
+ 1, [{ssl_generation, 3},
+ {iiop_ssl_port, 0}]),
+ ssl_suite(ServerOptions, ClientOptions).
+
+
+ssl_1_multi_orber_generation_3_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
"This case set up two secure orbs and test if they can",
"communicate. The case also test to access one of the",
"secure orbs which must raise a NO_PERMISSION exception."];
ssl_1_multi_orber_generation_3_api(suite) -> [];
ssl_1_multi_orber_generation_3_api(_Config) ->
-
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+
+ ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
1, [{ssl_generation, 3},
{iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
1, [{ssl_generation, 3},
{iiop_ssl_port, 0}]),
ssl_suite(ServerOptions, ClientOptions).
-
%%-----------------------------------------------------------------
%% API tests for ORB to ORB, ssl security depth 2
%%-----------------------------------------------------------------
-ssl_2_multi_orber_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
+ssl_2_multi_orber_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
"This case set up two secure orbs and test if they can",
"communicate. The case also test to access one of the",
"secure orbs which must raise a NO_PERMISSION exception."];
ssl_2_multi_orber_api(suite) -> [];
-ssl_2_multi_orber_api(_Config) ->
-
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+ssl_2_multi_orber_api(_Config) ->
+
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
2, [{iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
2, [{iiop_ssl_port, 0}]),
ssl_suite(ServerOptions, ClientOptions).
-ssl_2_multi_orber_generation_3_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
+
+ssl_2_multi_orber_generation_3_api_old(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
+ "This case set up two secure orbs and test if they can",
+ "communicate. The case also test to access one of the",
+ "secure orbs which must raise a NO_PERMISSION exception."];
+ssl_2_multi_orber_generation_3_api_old(suite) -> [];
+ssl_2_multi_orber_generation_3_api_old(_Config) ->
+
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
+ 2, [{ssl_generation, 3},
+ {iiop_ssl_port, 0}]),
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
+ 2, [{ssl_generation, 3},
+ {iiop_ssl_port, 0}]),
+ ssl_suite(ServerOptions, ClientOptions).
+
+
+ssl_2_multi_orber_generation_3_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
"This case set up two secure orbs and test if they can",
"communicate. The case also test to access one of the",
"secure orbs which must raise a NO_PERMISSION exception."];
ssl_2_multi_orber_generation_3_api(suite) -> [];
-ssl_2_multi_orber_generation_3_api(_Config) ->
-
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+ssl_2_multi_orber_generation_3_api(_Config) ->
+
+ ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
2, [{ssl_generation, 3},
{iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
2, [{ssl_generation, 3},
{iiop_ssl_port, 0}]),
ssl_suite(ServerOptions, ClientOptions).
@@ -1656,79 +1715,135 @@ ssl_2_multi_orber_generation_3_api(_Config) ->
%% API tests for ORB to ORB, ssl security depth 2
%%-----------------------------------------------------------------
-ssl_reconfigure_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
+ssl_reconfigure_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
"This case set up two secure orbs and test if they can",
"communicate. The case also test to access one of the",
"secure orbs which must raise a NO_PERMISSION exception."];
ssl_reconfigure_api(suite) -> [];
-ssl_reconfigure_api(_Config) ->
- ssl_reconfigure([]).
+ssl_reconfigure_api(_Config) ->
+ ssl_reconfigure_old([]).
+
-ssl_reconfigure_generation_3_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
+ssl_reconfigure_generation_3_api_old(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
+ "This case set up two secure orbs and test if they can",
+ "communicate. The case also test to access one of the",
+ "secure orbs which must raise a NO_PERMISSION exception."];
+ssl_reconfigure_generation_3_api_old(suite) -> [];
+ssl_reconfigure_generation_3_api_old(_Config) ->
+ ssl_reconfigure_old([{ssl_generation, 3}]).
+
+ssl_reconfigure_old(ExtraSSLOptions) ->
+
+ IP = orber_test_lib:get_host(),
+ Loopback = orber_test_lib:get_loopback_interface(),
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_},
+ orber_test_lib:js_node([{iiop_port, 0},
+ {flags, ?ORB_ENV_LOCAL_INTERFACE},
+ {ip_address, IP}|ExtraSSLOptions])),
+ orber_test_lib:remote_apply(ServerNode, ssl, start, []),
+ orber_test_lib:remote_apply(ServerNode, crypto, start, []),
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
+ [ssl])),
+ ?match({ok, _},
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
+ [Loopback, normal, [{iiop_port, 5648},
+ {iiop_ssl_port, 5649},
+ {interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]])),
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
+ 2, [{flags, ?ORB_ENV_LOCAL_INTERFACE},
+ {iiop_port, 5648},
+ {iiop_ssl_port, 5649},
+ {interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]),
+ ?match({ok, _},
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
+ [Loopback, ssl, ServerOptions])),
+
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
+ 2, [{iiop_ssl_port, 0}|ExtraSSLOptions]),
+ {ok, ClientNode, _ClientHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
+
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ install_test_data,
+ [ssl])),
+ orber_test_lib:remote_apply(ClientNode, ssl, start, []),
+ orber_test_lib:remote_apply(ServerNode, crypto, start, []),
+ Obj = ?match(#'IOP_IOR'{},
+ orber_test_lib:remote_apply(ClientNode, corba,
+ string_to_object, ["corbaname:iiop:1.1@"++Loopback++":5648/NameService#mamba",
+ [{context, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = {configuration, ClientOptions}}]}]])),
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_server,
+ print, [Obj])).
+
+
+ssl_reconfigure_generation_3_api(doc) -> ["SECURE MULTI ORB API tests (SSL depth 2)",
"This case set up two secure orbs and test if they can",
"communicate. The case also test to access one of the",
"secure orbs which must raise a NO_PERMISSION exception."];
ssl_reconfigure_generation_3_api(suite) -> [];
-ssl_reconfigure_generation_3_api(_Config) ->
+ssl_reconfigure_generation_3_api(_Config) ->
ssl_reconfigure([{ssl_generation, 3}]).
+
ssl_reconfigure(ExtraSSLOptions) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_},
- orber_test_lib:js_node([{iiop_port, 0},
- {flags, ?ORB_ENV_LOCAL_INTERFACE},
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_},
+ orber_test_lib:js_node([{iiop_port, 0},
+ {flags, ?ORB_ENV_LOCAL_INTERFACE},
{ip_address, IP}|ExtraSSLOptions])),
orber_test_lib:remote_apply(ServerNode, ssl, start, []),
orber_test_lib:remote_apply(ServerNode, crypto, start, []),
- orber_test_lib:remote_apply(ServerNode, ssl, seed, ["testing"]),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[ssl])),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ ?match({ok, _},
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[Loopback, normal, [{iiop_port, 5648},
{iiop_ssl_port, 5649},
{interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]])),
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
- 2, [{flags, ?ORB_ENV_LOCAL_INTERFACE},
+ ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+ 2, [{flags, ?ORB_ENV_LOCAL_INTERFACE},
{iiop_port, 5648},
{iiop_ssl_port, 5649},
{interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ ?match({ok, _},
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[Loopback, ssl, ServerOptions])),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
2, [{iiop_ssl_port, 0}|ExtraSSLOptions]),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ install_test_data,
[ssl])),
orber_test_lib:remote_apply(ClientNode, ssl, start, []),
orber_test_lib:remote_apply(ServerNode, crypto, start, []),
- orber_test_lib:remote_apply(ClientNode, ssl, seed, ["testing"]),
- Obj = ?match(#'IOP_IOR'{},
+ Obj = ?match(#'IOP_IOR'{},
orber_test_lib:remote_apply(ClientNode, corba,
string_to_object, ["corbaname:iiop:1.1@"++Loopback++":5648/NameService#mamba",
- [{context, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ [{context, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
context_data = {configuration, ClientOptions}}]}]])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_server,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_server,
print, [Obj])).
-
%%-----------------------------------------------------------------
%% API tests for Orber to Java ORB, no security
%%-----------------------------------------------------------------
-%orber_java_api(doc) -> ["ERLANG-ORB <-> JAVA-ORB API tests",
+%orber_java_api(doc) -> ["ERLANG-ORB <-> JAVA-ORB API tests",
% "This case test if data encode/decode (IIOP)",
% "produce the correct result, i.e., the test_server echos",
% "the input parameter or an exception is raised (MARSHAL)."];
@@ -1741,38 +1856,38 @@ ssl_reconfigure(ExtraSSLOptions) ->
%% Arguments: Config
%% Depth
%% Returns : ok
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
ssl_suite(ServerOptions, ClientOptions) ->
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[ssl])),
%% Tell the client to interoperate with the server. The purpose of this
%% operation is to look up, using NameService, an object reference and
%% use it to contact the object.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
lookup,
[ServerHost, ServerPort])),
-
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
+
+ ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
alternate_ssl_iiop_address,
[ServerHost, ServerPort, SSLServerPort])),
-
+
%% 'This' node is not secure. Contact the server. Must refuse connection.
NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++
integer_to_list(ServerPort)++"/NameService")),
-
+
%% Should be 'NO_PERMISSION'??
?match({'EXCEPTION',{'COMM_FAILURE',_,_,_}},
'CosNaming_NamingContext':resolve(NSR, lname:new(["not_exist"]))),
@@ -1782,8 +1897,8 @@ ssl_suite(ServerOptions, ClientOptions) ->
'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
%% Uninstall.
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
[ssl])),
ok.
@@ -1795,7 +1910,7 @@ setup_connection_timeout_api(suite) -> [];
setup_connection_timeout_api(_Config) ->
?match(ok, application:set_env(orber, iiop_backlog, 0)),
%% Wait to be sure that the configuration has kicked in.
- timer:sleep(2000),
+ timer:sleep(2000),
{ok, Ref, Port} = create_fake_server_ORB(normal, 0, [], listen, []),
?match(ok, orber:configure(iiop_setup_connection_timeout, 5)),
?match(ok, orber:info(io)),
@@ -1815,7 +1930,7 @@ setup_connection_timeout_api(_Config) ->
%%-----------------------------------------------------------------
%% iiop_setup_connection_timeout API tests for ORB to ORB.
%%-----------------------------------------------------------------
-setup_multi_connection_timeout_api(doc) ->
+setup_multi_connection_timeout_api(doc) ->
["iiop_multi_setup_connection_timeout API tests for ORB to ORB."];
setup_multi_connection_timeout_api(suite) -> [];
setup_multi_connection_timeout_api(_Config) ->
@@ -1840,7 +1955,7 @@ setup_multi_connection_timeout_api(_Config) ->
?match(ok, application:set_env(orber, iiop_out_ports, undefined)),
ok.
-setup_multi_connection_timeout_attempts_api(doc) ->
+setup_multi_connection_timeout_attempts_api(doc) ->
["iiop_multi_setup_connection_timeout API tests for ORB to ORB."];
setup_multi_connection_timeout_attempts_api(suite) -> [];
setup_multi_connection_timeout_attempts_api(_Config) ->
@@ -1866,7 +1981,7 @@ setup_multi_connection_timeout_attempts_api(_Config) ->
?match(ok, application:set_env(orber, iiop_out_ports, undefined)),
ok.
-setup_multi_connection_timeout_random_api(doc) ->
+setup_multi_connection_timeout_random_api(doc) ->
["iiop_multi_setup_connection_timeout API tests for ORB to ORB."];
setup_multi_connection_timeout_random_api(suite) -> [];
setup_multi_connection_timeout_random_api(_Config) ->
@@ -1901,17 +2016,17 @@ bad_giop_header_api(_Config) ->
orber:configure_override(interceptors, {native,[orber_iiop_tracer]}),
orber:configure(orber_debug_level, 10),
?match(ok, orber:info(io)),
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node()),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
Req = <<"GIOP",1,2,0,100,0,0,0,5,0,0,0,10,50>> ,
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
+ ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
message_error, [Req])),
-
+
application:set_env(orber, interceptors, false),
orber:configure(orber_debug_level, 0),
ok.
-
+
%%-----------------------------------------------------------------
%% Fragmented IIOP tests (Server-side).
@@ -1929,34 +2044,34 @@ fragments_server_api(doc) -> ["fragments API tests for server-side ORB."];
fragments_server_api(suite) -> [];
fragments_server_api(_Config) ->
%% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
+ {ok, Node, Host} =
+ ?match({ok,_,_}, orber_test_lib:js_node()),
Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
+
+ ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
+ install_test_data,
[nameservice])),
-
+
NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
corba:string_to_object("corbaloc::1.2@"++Host++":"++
integer_to_list(Port)++"/NameService")),
-
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+
+ Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
Any = #any{typecode = {tk_string,0},
value = "123"},
- Target = #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
+ Target = #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
value = iop_ior:get_objkey(Obj)},
- %% Fix a request header.
+ %% Fix a request header.
{Hdr, Body, HdrLen, _What, _Flags} =
cdr_encode:enc_request_split(
- #giop_env{version = {1,2}, objkey = Target,
+ #giop_env{version = {1,2}, objkey = Target,
request_id = ?REQUEST_ID,
- response_expected = true,
- op = testing_iiop_any,
- parameters = [49], ctx = [],
- tc = {tk_void,[tk_char],[]},
+ response_expected = true,
+ op = testing_iiop_any,
+ parameters = [49], ctx = [],
+ tc = {tk_void,[tk_char],[]},
host = [orber_test_lib:get_host()],
iiop_port = orber:iiop_port(),
iiop_ssl_port = orber:iiop_ssl_port(),
@@ -1971,11 +2086,11 @@ fragments_server_api(_Config) ->
<<AligmnetData:Aligned/binary,49>> = Body,
list_to_binary([AligmnetData, <<0,0,0,18,0,0,0,0,0,0,0,4,49>> ])
end,
-
+
MessSize = HdrLen+size(NewBody),
ReqFrag = list_to_binary([ <<"GIOP",1:8,2:8,2:8,0:8,
MessSize:32/big-unsigned-integer>> , Hdr |NewBody]),
- ?match(Any, fake_client_ORB(normal, Host, Port, [], fragments,
+ ?match(Any, fake_client_ORB(normal, Host, Port, [], fragments,
[ReqFrag, ?FRAG_2, ?FRAG_3, ?FRAG_4])),
ok.
@@ -1988,9 +2103,9 @@ fragments_max_server_api(suite) -> [];
fragments_max_server_api(_Config) ->
%% --- Create a slave-node ---
IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{iiop_max_fragments, 2},
- {ip_address, IP}])),
+ {ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
fragments_max_server(ServerNode, IP, ServerPort).
@@ -1999,37 +2114,37 @@ fragments_max_server_added_api(suite) -> [];
fragments_max_server_added_api(_Config) ->
%% --- Create a slave-node ---
IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([])),
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node([])),
ServerPort = 1 + orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [IP, normal,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
+ [IP, normal,
[{iiop_max_fragments, 2},
{flags, ?ORB_ENV_LOCAL_INTERFACE},
{iiop_port, ServerPort}]])),
fragments_max_server(ServerNode, IP, ServerPort).
fragments_max_server(ServerNode, ServerHost, ServerPort) ->
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[nameservice])),
Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname::1.2@"++ServerHost++":"++
integer_to_list(ServerPort)++"/NameService#mamba")),
- Target = #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
+ Target = #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
value = iop_ior:get_objkey(Obj)},
- %% Fix a request header.
+ %% Fix a request header.
{Hdr, Body, HdrLen, _What, _Flags} =
cdr_encode:enc_request_split(
- #giop_env{version = {1,2},
- objkey = Target,
- request_id = ?REQUEST_ID,
- response_expected = true,
- op = testing_iiop_any,
- parameters = [49], ctx = [],
- tc = {tk_void,[tk_char],[]},
+ #giop_env{version = {1,2},
+ objkey = Target,
+ request_id = ?REQUEST_ID,
+ response_expected = true,
+ op = testing_iiop_any,
+ parameters = [49], ctx = [],
+ tc = {tk_void,[tk_char],[]},
host = [orber_test_lib:get_host()],
iiop_port = orber:iiop_port(),
iiop_ssl_port = orber:iiop_ssl_port(),
@@ -2048,8 +2163,8 @@ fragments_max_server(ServerNode, ServerHost, ServerPort) ->
MessSize = HdrLen+size(NewBody),
ReqFrag = list_to_binary([ <<"GIOP",1:8,2:8,2:8,0:8,
MessSize:32/big-unsigned-integer>> , Hdr |NewBody]),
- ?match(#'IMP_LIMIT'{},
- fake_client_ORB(normal, ServerHost, ServerPort, [], fragments_max,
+ ?match(#'IMP_LIMIT'{},
+ fake_client_ORB(normal, ServerHost, ServerPort, [], fragments_max,
[ReqFrag, ?FRAG_2, ?FRAG_3, ?FRAG_4])),
ok.
@@ -2065,11 +2180,11 @@ fragments_client_api(_Config) ->
application:set_env(orber, interceptors, {native,[orber_iiop_tracer]}),
orber:configure(orber_debug_level, 10),
orber:info(),
- IOR = ?match({'IOP_IOR',_,_},
- iop_ior:create_external({1, 2}, "IDL:FAKE:1.0",
+ IOR = ?match({'IOP_IOR',_,_},
+ iop_ior:create_external({1, 2}, "IDL:FAKE:1.0",
"localhost", 6004, "FAKE", [])),
- spawn(?MODULE, create_fake_server_ORB, [normal, 6004, [], fragments,
- [?REPLY_FRAG_1, ?FRAG_2,
+ spawn(?MODULE, create_fake_server_ORB, [normal, 6004, [], fragments,
+ [?REPLY_FRAG_1, ?FRAG_2,
?FRAG_3, ?FRAG_4]]),
?match({ok, Any}, orber_test_server:testing_iiop_any(IOR, Any)),
application:set_env(orber, interceptors, false),
@@ -2085,16 +2200,16 @@ bad_fragment_id_client_api(_Config) ->
application:set_env(orber, interceptors, {native,[orber_iiop_tracer]}),
orber:configure(orber_debug_level, 10),
orber:info(),
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node()),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
Req = <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,100,50>> ,
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
+ ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
message_error, [Req])),
-
+
application:set_env(orber, interceptors, false),
orber:configure(orber_debug_level, 0),
-
+
ok.
%%-----------------------------------------------------------------
@@ -2102,22 +2217,22 @@ bad_fragment_id_client_api(_Config) ->
%%-----------------------------------------------------------------
bad_id_cancel_request_api(doc) -> ["Description", "more description"];
bad_id_cancel_request_api(suite) -> [];
-bad_id_cancel_request_api(Config) when is_list(Config) ->
- Req10 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 0},
+bad_id_cancel_request_api(Config) when is_list(Config) ->
+ Req10 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 0},
request_id = 556}),
- Req11 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 1},
+ Req11 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 1},
request_id = 556}),
- Req12 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 2},
+ Req12 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 2},
request_id = 556}),
- {ok, ServerNode, ServerHost} =
+ {ok, ServerNode, ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node()),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req10])),
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req11])),
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req12])),
+ ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
+ message_error, [Req10])),
+ ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
+ message_error, [Req11])),
+ ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
+ message_error, [Req12])),
ok.
%%-----------------------------------------------------------------
@@ -2133,141 +2248,141 @@ pseudo_calls(0, _) ->
pseudo_calls(Times, Obj) ->
orber_test_server:pseudo_call(Obj),
New = Times - 1,
- pseudo_calls(New, Obj).
+ pseudo_calls(New, Obj).
pseudo_casts(0, _) ->
ok;
pseudo_casts(Times, Obj) ->
orber_test_server:pseudo_cast(Obj),
New = Times - 1,
- pseudo_casts(New, Obj).
+ pseudo_casts(New, Obj).
context_test(Obj) ->
- CodeSetCtx = #'CONV_FRAME_CodeSetContext'{char_data = 65537,
+ CodeSetCtx = #'CONV_FRAME_CodeSetContext'{char_data = 65537,
wchar_data = 65801},
FTGrp = #'FT_FTGroupVersionServiceContext'{object_group_ref_version = ?ULONGMAX},
- FTReq = #'FT_FTRequestServiceContext'{client_id = "ClientId",
- retention_id = ?LONGMAX,
+ FTReq = #'FT_FTRequestServiceContext'{client_id = "ClientId",
+ retention_id = ?LONGMAX,
expiration_time = ?ULONGLONGMAX},
- IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
+ IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
value = true},
- IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous,
+ IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous,
value = false},
- IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName,
+ IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName,
value = [0,255]},
- IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain,
+ IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain,
value = [1,255]},
- IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName,
+ IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName,
value = [2,255]},
- IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX,
+ IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX,
value = [3,255]},
MTEstablishContext1 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken1,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken1,
client_authentication_token = [1, 255]}},
MTEstablishContext2 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken2,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken2,
client_authentication_token = [1, 255]}},
MTEstablishContext3 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken3,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken3,
client_authentication_token = [1, 255]}},
MTEstablishContext4 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken4,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken4,
client_authentication_token = [1, 255]}},
MTEstablishContext5 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken5,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken5,
client_authentication_token = [1, 255]}},
MTEstablishContext6 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
+ {label = ?CSI_MsgType_MTEstablishContext,
+ value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
+ authorization_token =
[#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken6,
+ {the_type = ?ULONGMAX,
+ the_element = [0,255]}],
+ identity_token = IDToken6,
client_authentication_token = [1, 255]}},
MTCompleteEstablishContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTCompleteEstablishContext,
- value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX,
+ {label = ?CSI_MsgType_MTCompleteEstablishContext,
+ value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX,
context_stateful = false,
final_context_token = [1, 255]}},
MTContextError = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTContextError,
+ {label = ?CSI_MsgType_MTContextError,
value = #'CSI_ContextError'{client_context_id = ?ULONGLONGMAX,
- major_status = 1,
- minor_status = 2,
+ major_status = 1,
+ minor_status = 2,
error_token = [2,255]}},
MTMessageInContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTMessageInContext,
- value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX,
+ {label = ?CSI_MsgType_MTMessageInContext,
+ value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX,
discard_context = true}},
- Ctx = [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
+ Ctx = [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
context_data = CodeSetCtx},
- #'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
+ #'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
context_data = FTGrp},
- #'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
+ #'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
context_data = FTReq},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext1},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext2},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext3},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext4},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext5},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTEstablishContext6},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTCompleteEstablishContext},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTContextError},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
context_data = MTMessageInContext},
- #'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ #'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
context_data = {any_kind_of_data, {127,0,0,1}, 4001}}],
?match(ok, orber_test_server:testing_iiop_context(Obj, [{context, Ctx}])).
create_fake_server_ORB(Type, Port, Options, listen, _Data) ->
{ok, _ListenSocket, NewPort} =
- orber_socket:listen(Type, Port,
+ orber_socket:listen(Type, Port,
[{backlog, 0}, {active, false}|Options]),
Socket = orber_socket:connect(Type, 'localhost', NewPort, [{active, false}|Options]),
{ok, {Type, Socket}, NewPort};
create_fake_server_ORB(Type, Port, Options, Action, Data) ->
- {ok, ListenSocket, _NewPort} =
+ {ok, ListenSocket, _NewPort} =
orber_socket:listen(Type, Port, [{active, false}|Options]),
Socket = orber_socket:accept(Type, ListenSocket),
do_server_action(Type, Socket, Action, Data),
@@ -2301,14 +2416,14 @@ do_client_action(Type, Socket, fragments, FragList) ->
ok = send_data(Type, Socket, FragList),
timer:sleep(3000),
{ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} =
+ {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} =
cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
Par;
do_client_action(Type, Socket, fragments_max, FragList) ->
ok = send_data(Type, Socket, FragList),
timer:sleep(3000),
{ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} =
+ {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} =
cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
Exc;
do_client_action(Type, Socket, message_error, Data) ->
@@ -2325,4 +2440,4 @@ send_data(_Type, _Socket, []) ->
send_data(Type, Socket, [H|T]) ->
orber_socket:write(Type, Socket, H),
send_data(Type, Socket, T).
-
+
diff --git a/lib/orber/test/orber_SUITE.erl b/lib/orber/test/orber_SUITE.erl
index be6ffa201c..26dc656b63 100644
--- a/lib/orber/test/orber_SUITE.erl
+++ b/lib/orber/test/orber_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 @@
-module(orber_SUITE).
-include_lib("test_server/include/test_server.hrl").
-
-define(default_timeout, ?t:minutes(15)).
-define(application, orber).
@@ -31,7 +30,11 @@
% Test cases must be exported.
-export([app_test/1, undefined_functions/1, install_load_order/1,
- install_local_content/1]).
+ install_local_content/1,
+ otp_9887/1]).
+
+%% Exporting error handler callbacks for use in otp_9887
+-export([init/1, handle_event/2]).
%%
%% all/1
@@ -40,7 +43,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app_test, undefined_functions, install_load_order,
- install_local_content].
+ install_local_content,
+ otp_9887].
groups() ->
[].
@@ -76,6 +80,27 @@ app_test(_Config) ->
?line ok=?t:app_test(orber),
ok.
+otp_9887(_Config) ->
+ orber:jump_stop(),
+ application:set_env(orber, orber_debug_level, 10),
+ orber:jump_start([]),
+
+ mnesia:create_table(orber_light_ifr, []),
+
+ error_logger:add_report_handler(?MODULE,[self()]),
+ catch orber_ifr:get_module(foo, bar),
+
+ receive
+ {stolen,Reason} ->
+ {error,_Pid1, {_Pid2, _ErrorString, ArgumentList}} = Reason,
+ 5 = length(ArgumentList)
+ after 500 ->
+ test_server:fail("OTP_9887 TIMED OUT")
+ end,
+
+ orber:jump_stop(),
+ ok.
+
%% Install Orber using the load_order option.
install_load_order(suite) ->
[];
@@ -192,5 +217,10 @@ key1search(Key, L) ->
fail(Reason) ->
exit({suite_failed, Reason}).
+%% Error handler
+init([Proc]) -> {ok,Proc}.
+handle_event(Event, Proc) ->
+ Proc ! {stolen,Event},
+ {ok,Proc}.
diff --git a/lib/orber/test/orber_acl_SUITE.erl b/lib/orber/test/orber_acl_SUITE.erl
index b43a00be19..ab2c2c872c 100644
--- a/lib/orber/test/orber_acl_SUITE.erl
+++ b/lib/orber/test/orber_acl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,7 @@ end_per_group(_GroupName, Config) ->
%%-----------------------------------------------------------------
init_per_suite(Config) ->
if
- list(Config) ->
+ is_list(Config) ->
Config;
true ->
exit("Config not a list")
diff --git a/lib/orber/test/orber_nat_SUITE.erl b/lib/orber/test/orber_nat_SUITE.erl
index 625f168520..ee31b162c2 100644
--- a/lib/orber/test/orber_nat_SUITE.erl
+++ b/lib/orber/test/orber_nat_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %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%
%%
%%
@@ -50,14 +50,15 @@
%%-----------------------------------------------------------------
%% External exports
%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
+ init_per_testcase/2, end_per_testcase/2,
nat_ip_address/1, nat_ip_address_multiple/1,
nat_ip_address_local/1, nat_ip_address_local_local/1,
nat_iiop_port/1, nat_iiop_port_local/1,
- nat_iiop_port_local_local/1, nat_iiop_ssl_port/1,
- nat_iiop_ssl_port_local/1]).
+ nat_iiop_port_local_local/1,
+ nat_iiop_ssl_port_old/1, nat_iiop_ssl_port_local_old/1,
+ nat_iiop_ssl_port/1, nat_iiop_ssl_port_local/1]).
%%-----------------------------------------------------------------
@@ -66,15 +67,15 @@
%%-----------------------------------------------------------------
%% Func: all/1
-%% Args:
-%% Returns:
+%% Args:
+%% Returns:
%%-----------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
cases().
-groups() ->
+groups() ->
[].
init_per_group(_GroupName, Config) ->
@@ -84,25 +85,38 @@ end_per_group(_GroupName, Config) ->
Config.
-cases() ->
- [nat_ip_address, nat_ip_address_multiple,
- nat_ip_address_local, nat_iiop_port,
- nat_iiop_port_local, nat_ip_address_local_local,
- nat_iiop_port_local_local, nat_iiop_ssl_port,
+cases() ->
+ [nat_ip_address,
+ nat_ip_address_multiple,
+ nat_ip_address_local,
+ nat_iiop_port,
+ nat_iiop_port_local,
+ nat_ip_address_local_local,
+ nat_iiop_port_local_local,
+ nat_iiop_ssl_port_old,
+ nat_iiop_ssl_port_local_old,
+ nat_iiop_ssl_port,
nat_iiop_ssl_port_local].
%%-----------------------------------------------------------------
%% Init and cleanup functions.
%%-----------------------------------------------------------------
-init_per_testcase(TC, Config)
+init_per_testcase(TC, Config)
when TC =:= nat_iiop_ssl_port;
- TC =:= nat_iiop_ssl_port_local ->
- case orber_test_lib:ssl_version() of
- no_ssl ->
- {skip,"SSL not installed!"};
- _ ->
- init_per_testcase(dummy_tc, Config)
- end;
+ TC =:= nat_iiop_ssl_port_local;
+ TC =:= nat_iiop_ssl_port_old;
+ TC =:= nat_iiop_ssl_port_local_old ->
+ case ?config(crypto_started, Config) of
+ true ->
+ case orber_test_lib:ssl_version() of
+ no_ssl ->
+ {skip,"SSL not installed!"};
+ _ ->
+ init_per_testcase(dummy_tc, Config)
+ end;
+ false ->
+ {skip, "Crypto did not start"}
+ end;
init_per_testcase(_Case, Config) ->
Path = code:which(?MODULE),
code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
@@ -125,12 +139,18 @@ end_per_testcase(_Case, Config) ->
init_per_suite(Config) ->
if
is_list(Config) ->
- Config;
+ try crypto:start() of
+ ok ->
+ [{crypto_started, true} | Config]
+ catch _:_ ->
+ [{crypto_started, false} | Config]
+ end;
true ->
exit("Config not a list")
end.
end_per_suite(Config) ->
+ application:stop(crypto),
Config.
%%-----------------------------------------------------------------
@@ -143,13 +163,13 @@ nat_ip_address(suite) -> [];
nat_ip_address(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
{nat_ip_address, Loopback}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR)),
ok.
@@ -158,14 +178,14 @@ nat_ip_address_multiple(doc) -> ["This case test if the server ORB use the corre
nat_ip_address_multiple(suite) -> [];
nat_ip_address_multiple(_Config) ->
IP = orber_test_lib:get_host(),
-
- {ok, ServerNode, _ServerHost} =
+
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
{nat_ip_address, {multiple, ["10.0.0.1"]}}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR)),
ok.
@@ -174,13 +194,13 @@ nat_ip_address_local(doc) -> ["This case test if the server ORB use the correct"
nat_ip_address_local(suite) -> [];
nat_ip_address_local(_Config) ->
IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
{nat_ip_address, {local, "10.0.0.1", [{IP, "127.0.0.1"}]}}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR)),
ok.
@@ -190,19 +210,19 @@ nat_ip_address_local_local(suite) -> [];
nat_ip_address_local_local(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags,
- (?ORB_ENV_LOCAL_INTERFACE bor
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{flags,
+ (?ORB_ENV_LOCAL_INTERFACE bor
?ORB_ENV_ENABLE_NAT)},
{nat_ip_address, {local, "10.0.0.1", [{IP, "10.0.0.2"}]}}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR1 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.2", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {"10.0.0.2", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR1)),
IOR2 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR2)),
ok.
@@ -211,13 +231,13 @@ nat_iiop_port(doc) -> ["This case test if the server ORB use the correct",
nat_iiop_port(suite) -> [];
nat_iiop_port(_Config) ->
IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
{nat_iiop_port, 42}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {_IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {_IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR)),
ok.
@@ -226,13 +246,13 @@ nat_iiop_port_local(doc) -> ["This case test if the server ORB use the correct",
nat_iiop_port_local(suite) -> [];
nat_iiop_port_local(_Config) ->
IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
{nat_iiop_port, {local, 42, [{4001, 43}]}}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
IOR = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {_IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {_IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR)),
ok.
@@ -242,27 +262,27 @@ nat_iiop_port_local_local(suite) -> [];
nat_iiop_port_local_local(_Config) ->
IP = orber_test_lib:get_host(),
Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags,
- (?ORB_ENV_LOCAL_INTERFACE bor
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node([{flags,
+ (?ORB_ENV_LOCAL_INTERFACE bor
?ORB_ENV_ENABLE_NAT)},
{ip_address, IP}])),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
orber_test_lib:remote_apply(ServerNode, orber_env, configure_override, [nat_iiop_port, {local, 42, [{ServerPort, 43}]}]),
IOR1 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, 43, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {IP, 43, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR1)),
{ok, Ref} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[Loopback, normal, 10088])),
IOR2 = ?match(#'IOP_IOR'{},
corba:string_to_object("corbaloc::1.2@"++Loopback++":10088/NameService")),
- ?match({'external', {IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
+ ?match({'external', {IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
iop_ior:get_key(IOR2)),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
remove_listen_interface, [Ref])),
ok.
@@ -271,103 +291,204 @@ nat_iiop_port_local_local(_Config) ->
%% API tests for ORB to ORB, ssl security depth 1
%%-----------------------------------------------------------------
-nat_iiop_ssl_port(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+nat_iiop_ssl_port_old(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+ "Make sure NAT works for SSL"];
+nat_iiop_ssl_port_old(suite) -> [];
+nat_iiop_ssl_port_old(_Config) ->
+
+ IP = orber_test_lib:get_host(),
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
+ 1, [{iiop_ssl_port, 0},
+ {flags, ?ORB_ENV_ENABLE_NAT},
+ {ip_address, IP}]),
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
+ 1, [{iiop_ssl_port, 0}]),
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
+ ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
+ SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
+ NATSSLServerPort = SSLServerPort+1,
+ {ok, Ref} = ?match({ok, _},
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
+ [IP, ssl, NATSSLServerPort])),
+ orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
+ [nat_iiop_ssl_port,
+ {local, NATSSLServerPort, [{4001, 43}]}]),
+
+ {ok, ClientNode, _ClientHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
+ [ssl])),
+
+ IOR1 = ?match(#'IOP_IOR'{},
+ orber_test_lib:remote_apply(ClientNode, corba,
+ string_to_object,
+ ["corbaname::1.2@"++IP++":"++
+ integer_to_list(ServerPort)++"/NameService#mamba"])),
+
+ ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
+ #host_data{protocol = ssl,
+ ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
+ iop_ior:get_key(IOR1)),
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
+ [ssl])),
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ remove_listen_interface, [Ref])),
+ ok.
+
+nat_iiop_ssl_port_local_old(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+ "Make sure NAT works for SSL"];
+nat_iiop_ssl_port_local_old(suite) -> [];
+nat_iiop_ssl_port_local_old(_Config) ->
+
+ IP = orber_test_lib:get_host(),
+ ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
+ 1, [{iiop_ssl_port, 0},
+ {flags,
+ (?ORB_ENV_LOCAL_INTERFACE bor
+ ?ORB_ENV_ENABLE_NAT)},
+ {ip_address, IP}]),
+ ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
+ 1, [{iiop_ssl_port, 0}]),
+ {ok, ServerNode, _ServerHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
+ ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
+ SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
+ NATSSLServerPort = SSLServerPort+1,
+ {ok, Ref} = ?match({ok, _},
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
+ [IP, ssl, NATSSLServerPort])),
+ orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
+ [nat_iiop_ssl_port,
+ {local, NATSSLServerPort, [{NATSSLServerPort, NATSSLServerPort}]}]),
+
+ {ok, ClientNode, _ClientHost} =
+ ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
+ [ssl])),
+
+ IOR1 = ?match(#'IOP_IOR'{},
+ orber_test_lib:remote_apply(ClientNode, corba,
+ string_to_object,
+ ["corbaname::1.2@"++IP++":"++
+ integer_to_list(ServerPort)++"/NameService#mamba"])),
+
+ ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
+ #host_data{protocol = ssl,
+ ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
+ iop_ior:get_key(IOR1)),
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
+ [ssl])),
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ remove_listen_interface, [Ref])),
+ ok.
+
+
+nat_iiop_ssl_port(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
"Make sure NAT works for SSL"];
nat_iiop_ssl_port(suite) -> [];
nat_iiop_ssl_port(_Config) ->
IP = orber_test_lib:get_host(),
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+ ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
1, [{iiop_ssl_port, 0},
{flags, ?ORB_ENV_ENABLE_NAT},
{ip_address, IP}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
1, [{iiop_ssl_port, 0}]),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
NATSSLServerPort = SSLServerPort+1,
{ok, Ref} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[IP, ssl, NATSSLServerPort])),
- orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
- [nat_iiop_ssl_port,
+ orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
+ [nat_iiop_ssl_port,
{local, NATSSLServerPort, [{4001, 43}]}]),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[ssl])),
- IOR1 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba,
+ IOR1 = ?match(#'IOP_IOR'{},
+ orber_test_lib:remote_apply(ClientNode, corba,
string_to_object,
["corbaname::1.2@"++IP++":"++
integer_to_list(ServerPort)++"/NameService#mamba"])),
- ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
+ ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
+ #host_data{protocol = ssl,
+ ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
iop_ior:get_key(IOR1)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
[ssl])),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
remove_listen_interface, [Ref])),
ok.
-nat_iiop_ssl_port_local(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
+nat_iiop_ssl_port_local(doc) -> ["SECURE MULTI ORB API tests (SSL depth 1)",
"Make sure NAT works for SSL"];
nat_iiop_ssl_port_local(suite) -> [];
nat_iiop_ssl_port_local(_Config) ->
IP = orber_test_lib:get_host(),
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
+ ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
1, [{iiop_ssl_port, 0},
- {flags,
- (?ORB_ENV_LOCAL_INTERFACE bor
+ {flags,
+ (?ORB_ENV_LOCAL_INTERFACE bor
?ORB_ENV_ENABLE_NAT)},
{ip_address, IP}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
+ ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
1, [{iiop_ssl_port, 0}]),
- {ok, ServerNode, _ServerHost} =
+ {ok, ServerNode, _ServerHost} =
?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
NATSSLServerPort = SSLServerPort+1,
{ok, Ref} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
+ orber_test_lib:remote_apply(ServerNode, orber,
+ add_listen_interface,
[IP, ssl, NATSSLServerPort])),
- orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
- [nat_iiop_ssl_port,
+ orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
+ [nat_iiop_ssl_port,
{local, NATSSLServerPort, [{NATSSLServerPort, NATSSLServerPort}]}]),
- {ok, ClientNode, _ClientHost} =
+ {ok, ClientNode, _ClientHost} =
?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ install_test_data,
[ssl])),
- IOR1 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba,
+ IOR1 = ?match(#'IOP_IOR'{},
+ orber_test_lib:remote_apply(ClientNode, corba,
string_to_object,
["corbaname::1.2@"++IP++":"++
integer_to_list(ServerPort)++"/NameService#mamba"])),
- ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
+ ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
+ #host_data{protocol = ssl,
+ ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
iop_ior:get_key(IOR1)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
+ ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
+ uninstall_test_data,
[ssl])),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
+ ?match(ok,
+ orber_test_lib:remote_apply(ServerNode, orber,
remove_listen_interface, [Ref])),
ok.
diff --git a/lib/orber/test/orber_test_lib.erl b/lib/orber/test/orber_test_lib.erl
index ffc13d0e3c..2bfa1ef871 100644
--- a/lib/orber/test/orber_test_lib.erl
+++ b/lib/orber/test/orber_test_lib.erl
@@ -41,28 +41,31 @@
end
end()).
--export([js_node/2,
+-export([js_node/2,
js_node/1,
js_node/0,
- slave_sup/0,
- remote_apply/4,
+ slave_sup/0,
+ remote_apply/4,
install_test_data/1,
light_tests/3,
- uninstall_test_data/1,
- destroy_node/2,
+ uninstall_test_data/1,
+ destroy_node/2,
lookup/2,
alternate_iiop_address/2,
create_alternate_iiop_address/2,
alternate_ssl_iiop_address/3,
create_alternate_ssl_iiop_address/3,
- test_coding/1,
- test_coding/2,
- corba_object_tests/2,
+ test_coding/1,
+ test_coding/2,
+ corba_object_tests/2,
timeouts/3,
precond/3,
postcond/4,
oe_get_interface/0,
create_components_IOR/1,
+ get_options_old/2,
+ get_options_old/3,
+ get_options_old/4,
get_options/2,
get_options/3,
get_options/4,
@@ -89,13 +92,13 @@
%%------------------------------------------------------------
%% function : ssl_version
-%% Arguments:
+%% Arguments:
%% Returns : integer()
-%% Effect :
-%%
+%% Effect :
+%%
%%------------------------------------------------------------
ssl_version() ->
- try
+ try
ssl:module_info(),
case catch erlang:system_info(otp_release) of
Version when is_list(Version) ->
@@ -114,10 +117,10 @@ ssl_version() ->
%%------------------------------------------------------------
%% function : version_ok
-%% Arguments:
+%% Arguments:
%% Returns : true | {skipped, Reason}
-%% Effect :
-%%
+%% Effect :
+%%
%%------------------------------------------------------------
version_ok() ->
{ok, Hostname} = inet:gethostname(),
@@ -151,8 +154,8 @@ version_ok() ->
%% function : get_host
%% Arguments: Family - inet | inet6
%% Returns : string()
-%% Effect :
-%%
+%% Effect :
+%%
%%------------------------------------------------------------
get_host() ->
get_host(inet).
@@ -172,13 +175,13 @@ get_host(Family) ->
[IP] = ?match([_], orber:host()),
IP
end.
-
+
%%------------------------------------------------------------
%% function : get_loopback_interface
%% Arguments: Family - inet | inet6
%% Returns : string()
-%% Effect :
-%%
+%% Effect :
+%%
%%------------------------------------------------------------
get_loopback_interface() ->
get_loopback_interface(inet).
@@ -193,12 +196,12 @@ get_loopback_interface(Family) ->
_ when Family == inet ->
"127.0.0.1";
_ ->
- "0:0:0:0:0:FFFF:7F00:0001"
+ "0:0:0:0:0:FFFF:7F00:0001"
end;
_ when Family == inet ->
"127.0.0.1";
_ ->
- "0:0:0:0:0:FFFF:7F00:0001"
+ "0:0:0:0:0:FFFF:7F00:0001"
end.
%%------------------------------------------------------------
@@ -220,7 +223,7 @@ js_node(InitOptions, StartOptions) when is_list(InitOptions) ->
{A,B,C} = erlang:now(),
[_, Host] = string:tokens(atom_to_list(node()), [$@]),
_NewInitOptions = check_options(InitOptions),
- js_node_helper(Host, 0, lists:concat([A,'_',B,'_',C]),
+ js_node_helper(Host, 0, lists:concat([A,'_',B,'_',C]),
InitOptions, 10, StartOptions).
js_node_helper(Host, Port, Name, Options, Retries, StartOptions) ->
@@ -234,8 +237,8 @@ js_node_helper(Host, Port, Name, Options, Retries, StartOptions) ->
ok = rpc:call(NewNode, file, set_cwd, [Cwd]),
true = rpc:call(NewNode, code, set_path, [Path]),
rpc:call(NewNode, application, load, [orber]),
- ok = rpc:call(NewNode, corba, orb_init,
- [[{iiop_port, Port},
+ ok = rpc:call(NewNode, corba, orb_init,
+ [[{iiop_port, Port},
{orber_debug_level, 10}|Options]]),
start_orber(StartOptions, NewNode),
spawn_link(NewNode, ?MODULE, slave_sup, []),
@@ -247,8 +250,8 @@ js_node_helper(Host, Port, Name, Options, Retries, StartOptions) ->
end;
{error, Reason} when Retries == 0 ->
{error, Reason};
- {error, Reason} ->
- io:format("Could not start slavenode ~p:~p due to: ~p~n",
+ {error, Reason} ->
+ io:format("Could not start slavenode ~p:~p due to: ~p~n",
[Host, Port, Reason]),
timer:sleep(500),
js_node_helper(Host, Port, Name, Options, Retries-1, StartOptions)
@@ -279,13 +282,14 @@ starter(Host, Name, Args) ->
vxworks ->
test_server:start_node(Name, slave, [{args,Args}]);
_ ->
+ io:format("slave:start_link(~p,~p,~p).~n",[Host,Name,Args]),
slave:start_link(Host, Name, Args)
end.
slave_sup() ->
process_flag(trap_exit, true),
receive
- {'EXIT', _, _} ->
+ {'EXIT', _, _} ->
case os:type() of
vxworks ->
erlang:halt();
@@ -296,8 +300,7 @@ slave_sup() ->
start_ssl(true, Node) ->
rpc:call(Node, ssl, start, []),
- rpc:call(Node, crypto, start, []),
- rpc:call(Node, ssl, seed, ["testing"]);
+ rpc:call(Node, crypto, start, []);
start_ssl(_, _) ->
ok.
@@ -310,68 +313,106 @@ start_orber(lightweight, Node) ->
start_orber(_, Node) ->
ok = rpc:call(Node, orber, jump_start, []).
-
%%-----------------------------------------------------------------
%% Type - ssl | iiop_ssl
%% Role - 'server' | 'client'
%% Options - [{Key, Value}]
%%-----------------------------------------------------------------
-get_options(Type, Role) ->
- get_options(Type, Role, 2, []).
+get_options_old(Type, Role) ->
+ get_options_old(Type, Role, 2, []).
-get_options(ssl, Role, Level) ->
- get_options(ssl, Role, Level, []).
+get_options_old(ssl, Role, Level) ->
+ get_options_old(ssl, Role, Level, []).
-get_options(ssl, Role, 2, Options) ->
+get_options_old(ssl, Role, 2, Options) ->
Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
[{depth, 2},
{verify, 2},
{keyfile, filename:join([Dir, Role, "key.pem"])},
- {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
- {certfile, filename:join([Dir, Role, "cert.pem"])}|Options];
-get_options(iiop_ssl, _Role, 2, Options) ->
+ {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
+ {certfile, filename:join([Dir, Role, "cert.pem"])} |Options];
+get_options_old(iiop_ssl, _Role, 2, Options) ->
Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
[{ssl_server_depth, 2},
{ssl_server_verify, 2},
{ssl_server_certfile, filename:join([Dir, "server", "cert.pem"])},
- {ssl_server_cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
+ {ssl_server_cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
{ssl_server_keyfile, filename:join([Dir, "server", "key.pem"])},
{ssl_client_depth, 2},
{ssl_client_verify, 2},
{ssl_client_certfile, filename:join([Dir, "client", "cert.pem"])},
- {ssl_client_cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
+ {ssl_client_cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
{ssl_client_keyfile, filename:join([Dir, "client", "key.pem"])},
- {secure, ssl}|Options];
-get_options(iiop_ssl, _Role, 1, Options) ->
+ {secure, ssl} |Options];
+get_options_old(iiop_ssl, _Role, 1, Options) ->
Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
[{ssl_server_depth, 1},
{ssl_server_verify, 0},
{ssl_server_certfile, filename:join([Dir, "server", "cert.pem"])},
- {ssl_server_cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
+ {ssl_server_cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
{ssl_server_keyfile, filename:join([Dir, "server", "key.pem"])},
{ssl_client_depth, 1},
{ssl_client_verify, 0},
{ssl_client_certfile, filename:join([Dir, "client", "cert.pem"])},
- {ssl_client_cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
+ {ssl_client_cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
{ssl_client_keyfile, filename:join([Dir, "client", "key.pem"])},
- {secure, ssl}|Options].
+ {secure, ssl} |Options].
+get_options(Type, Role) ->
+ get_options(Type, Role, 2, []).
+
+get_options(ssl, Role, Level) ->
+ get_options(ssl, Role, Level, []).
+
+get_options(ssl, Role, 2, Options) ->
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ [{depth, 2},
+ {verify, 2},
+ {keyfile, filename:join([Dir, Role, "key.pem"])},
+ {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
+ {certfile, filename:join([Dir, Role, "cert.pem"])} |Options];
+get_options(iiop_ssl, _Role, 2, Options) ->
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ [{ssl_server_options, [{depth, 2},
+ {verify, 2},
+ {certfile, filename:join([Dir, "server", "cert.pem"])},
+ {cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
+ {keyfile, filename:join([Dir, "server", "key.pem"])}]},
+ {ssl_client_options, [{depth, 2},
+ {verify, 2},
+ {certfile, filename:join([Dir, "client", "cert.pem"])},
+ {cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
+ {keyfile, filename:join([Dir, "client", "key.pem"])}]},
+ {secure, ssl} |Options];
+get_options(iiop_ssl, _Role, 1, Options) ->
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ [{ssl_server_options, [{depth, 1},
+ {verify, 0},
+ {certfile, filename:join([Dir, "server", "cert.pem"])},
+ {cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
+ {keyfile, filename:join([Dir, "server", "key.pem"])}]},
+ {ssl_client_options, [{depth, 1},
+ {verify, 0},
+ {certfile, filename:join([Dir, "client", "cert.pem"])},
+ {cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
+ {keyfile, filename:join([Dir, "client", "key.pem"])}]},
+ {secure, ssl} |Options].
create_paths() ->
Path = filename:dirname(code:which(?MODULE)),
" -pa " ++ Path ++ " -pa " ++
- filename:join(Path, "idl_output") ++
+ filename:join(Path, "idl_output") ++
" -pa " ++
- filename:join(Path, "all_SUITE_data") ++
- " -pa " ++
- filename:dirname(code:which(orber)).
+ filename:join(Path, "all_SUITE_data") ++
+ " -pa \"" ++
+ filename:dirname(code:which(orber))++"\"".
%%------------------------------------------------------------
%% function : destroy_node
%% Arguments: Node - which node to destroy.
%% Type - normal | ssl
-%% Returns :
-%% Effect :
+%% Returns :
+%% Effect :
%%------------------------------------------------------------
destroy_node(Node, Type) ->
@@ -385,13 +426,13 @@ stopper(Node, _Type) ->
slave:stop(Node)
end.
-
+
%%------------------------------------------------------------
%% function : remote_apply
%% Arguments: N - Node, M - Module,
%% F - Function, A - Arguments (list)
-%% Returns :
-%% Effect :
+%% Returns :
+%% Effect :
%%------------------------------------------------------------
remote_apply(N, M,F,A) ->
case rpc:call(N, M, F, A) of
@@ -412,7 +453,7 @@ remote_apply(N, M,F,A) ->
install_test_data(nameservice) ->
oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
+ Mamba = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
true = corba:add_initial_service("Mamba", Mamba),
NS = corba:resolve_initial_references("NameService"),
NC1 = lname_component:set_id(lname_component:create(), "mamba"),
@@ -421,7 +462,7 @@ install_test_data(nameservice) ->
install_test_data({nameservice, AltAddr, AltPort}) ->
oe_orber_test_server:oe_register(),
- Obj = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
+ Obj = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
Mamba = corba:add_alternate_iiop_address(Obj, AltAddr, AltPort),
true = corba:add_initial_service("Mamba", Mamba),
NS = corba:resolve_initial_references("NameService"),
@@ -431,8 +472,8 @@ install_test_data({nameservice, AltAddr, AltPort}) ->
install_test_data(timeout) ->
oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], {local, mamba}),
- Viper = orber_test_timeout_server:oe_create([], {local, viper}),
+ Mamba = orber_test_server:oe_create([], {local, mamba}),
+ Viper = orber_test_timeout_server:oe_create([], {local, viper}),
NS = corba:resolve_initial_references("NameService"),
NC1 = lname_component:set_id(lname_component:create(), "mamba"),
N1 = lname:insert_component(lname:create(), 1, NC1),
@@ -451,7 +492,7 @@ install_test_data(pseudo) ->
install_test_data(ssl) ->
oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
+ Mamba = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
NS = corba:resolve_initial_references("NameService"),
NC1 = lname_component:set_id(lname_component:create(), "mamba"),
N = lname:insert_component(lname:create(), 1, NC1),
@@ -459,7 +500,7 @@ install_test_data(ssl) ->
install_test_data(ssl_simple) ->
oe_orber_test_server:oe_register();
-
+
install_test_data(light) ->
%% Nothing to do at the moment but we might in the future
ok;
@@ -480,7 +521,7 @@ uninstall_test_data(pseudo) ->
NC1 = lname_component:set_id(lname_component:create(), "mamba"),
N = lname:insert_component(lname:create(), 1, NC1),
_Obj = (catch 'CosNaming_NamingContext':resolve(NS, N)),
- catch 'CosNaming_NamingContext':destroy(NS),
+ catch 'CosNaming_NamingContext':destroy(NS),
oe_orber_test_server:oe_unregister();
uninstall_test_data(timeout) ->
@@ -494,7 +535,7 @@ uninstall_test_data(timeout) ->
Viper = (catch 'CosNaming_NamingContext':resolve(NS, N2)),
catch corba:dispose(Mamba),
catch corba:dispose(Viper),
- catch 'CosNaming_NamingContext':destroy(NS),
+ catch 'CosNaming_NamingContext':destroy(NS),
oe_orber_test_server:oe_unregister();
uninstall_test_data(nameservice) ->
@@ -504,7 +545,7 @@ uninstall_test_data(nameservice) ->
N = lname:insert_component(lname:create(), 1, NC1),
Obj = (catch 'CosNaming_NamingContext':resolve(NS, N)),
catch corba:dispose(Obj),
- catch 'CosNaming_NamingContext':destroy(NS),
+ catch 'CosNaming_NamingContext':destroy(NS),
oe_orber_test_server:oe_unregister();
uninstall_test_data(ssl) ->
@@ -513,7 +554,7 @@ uninstall_test_data(ssl) ->
N = lname:insert_component(lname:create(), 1, NC1),
Obj = (catch 'CosNaming_NamingContext':resolve(NS, N)),
catch corba:dispose(Obj),
- catch 'CosNaming_NamingContext':destroy(NS),
+ catch 'CosNaming_NamingContext':destroy(NS),
oe_orber_test_server:oe_unregister();
uninstall_test_data(ssl_simple) ->
@@ -531,27 +572,27 @@ uninstall_test_data(_) ->
%% Arguments: TestServerObj a orber_test_server ref
%% OtherObj - any other Orber object.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
corba_object_tests(TestServerObj, OtherObj) ->
- ?match(false,
+ ?match(false,
corba_object:is_a(TestServerObj, "IDL:orber_parent/inherrit:1.0")),
- ?match(true,
+ ?match(true,
corba_object:is_a(TestServerObj, "IDL:omg.org/orber_parent/inherrit:1.0")),
- ?match(true,
+ ?match(true,
corba_object:is_a(TestServerObj, "IDL:omg.org/orber_test/server:1.0")),
- ?match(false,
+ ?match(false,
corba_object:is_a(TestServerObj, "IDL:orber_test/server:1.0")),
- ?match(false,
+ ?match(false,
corba_object:is_a(TestServerObj, "IDL:omg.org/orber_parent/inherrit:1.1")),
- ?match(false,
+ ?match(false,
corba_object:is_a(TestServerObj, "NotValidIFRID")),
- ?match(false,
+ ?match(false,
corba_object:is_nil(TestServerObj)),
- ?match(false,
+ ?match(false,
corba_object:is_equivalent(OtherObj,TestServerObj)),
- ?match(true,
+ ?match(true,
corba_object:is_equivalent(TestServerObj,TestServerObj)),
?match(false, corba_object:non_existent(TestServerObj)),
?match(false, corba_object:not_existent(TestServerObj)),
@@ -563,32 +604,32 @@ corba_object_tests(TestServerObj, OtherObj) ->
%% function : lookup
%% Arguments: Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
lookup(Host, Port) ->
Key = Host++":"++integer_to_list(Port),
- NSR = corba:resolve_initial_references_remote("NameService",
+ NSR = corba:resolve_initial_references_remote("NameService",
["iiop://"++Key]),
NC1 = lname_component:set_id(lname_component:create(), "not_exist"),
N1 = lname:insert_component(lname:create(), 1, NC1),
?match({'EXCEPTION',{'CosNaming_NamingContext_NotFound',_,_,_}},
'CosNaming_NamingContext':resolve(NSR, N1)),
-
+
NC2 = lname_component:set_id(lname_component:create(), "mamba"),
N2 = lname:insert_component(lname:create(), 1, NC2),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+ Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
'CosNaming_NamingContext':resolve(NSR, N2)),
orber_test_server:print(Obj),
- Obj2 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+ Obj2 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
corba:string_to_object("corbaname:iiop:1.1@"++Key++"/NameService#mamba")),
-
+
orber_test_server:print(Obj2),
- NSR2 = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
+ NSR2 = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
corba:string_to_object("corbaloc:iiop:1.1@"++Key++"/NameService")),
- Obj3 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+ Obj3 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
'CosNaming_NamingContext':resolve(NSR2, N2)),
orber_test_server:print(Obj3).
@@ -596,11 +637,11 @@ lookup(Host, Port) ->
%% function : alternate_iiop_address
%% Arguments: Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
alternate_iiop_address(Host, Port) ->
IOR = create_alternate_iiop_address(Host, Port),
-
+
?match(false, corba_object:non_existent(IOR)),
?match({'object_forward',_}, corba:locate(IOR)),
?match({'object_forward',_}, corba:locate(IOR, 10000)),
@@ -610,145 +651,145 @@ alternate_iiop_address(Host, Port) ->
%% function : create_alternate_iiop_address
%% Arguments: Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
create_alternate_iiop_address(Host, Port) ->
- MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
+ MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
component_data = ?ORBER_ORB_TYPE_1},
- #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
+ #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
component_data = ?DEFAULT_CODESETS},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
+ 'HostID' = Host,
'Port' = Port}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
+ 'HostID' = Host,
'Port' = 8000}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
+ 'HostID' = Host,
'Port' = 8000}}],
#'IOP_IOR'{type_id=TypeID,
- profiles=P1} = _IORA = iop_ior:create({1,2},
+ profiles=P1} = _IORA = iop_ior:create({1,2},
"IDL:omg.org/CosNaming/NamingContextExt:1.0",
- [Host], 8000, -1,
+ [Host], 8000, -1,
"NameService", MC, 0, 0),
- #'IOP_IOR'{profiles=P2} = _IORB = iop_ior:create({1,1},
+ #'IOP_IOR'{profiles=P2} = _IORB = iop_ior:create({1,1},
"IDL:omg.org/CosNaming/NamingContextExt:1.0",
[Host], 8000, -1,
"NameService", [], 0, 0),
#'IOP_IOR'{type_id=TypeID, profiles=P2++P1}.
-
+
%%------------------------------------------------------------
%% function : create_components_IOR
-%% Arguments:
+%% Arguments:
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
create_components_IOR(Version) ->
- MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
+ MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
component_data = ?ORBER_ORB_TYPE_1},
- #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
+ #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
component_data = ?DEFAULT_CODESETS},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = "127.0.0.1",
+ 'HostID' = "127.0.0.1",
'Port' = 4001}},
- #'IOP_TaggedComponent'{tag = ?TAG_SSL_SEC_TRANS,
- component_data = #'SSLIOP_SSL'{target_supports = 0,
+ #'IOP_TaggedComponent'{tag = ?TAG_SSL_SEC_TRANS,
+ component_data = #'SSLIOP_SSL'{target_supports = 0,
target_requires = 1,
port = 2}},
- #'IOP_TaggedComponent'{tag = ?TAG_FT_GROUP,
- component_data =
+ #'IOP_TaggedComponent'{tag = ?TAG_FT_GROUP,
+ component_data =
#'FT_TagFTGroupTaggedComponent'
- {version = #'GIOP_Version'{major = 1,
- minor = 2},
- ft_domain_id = "FT_FTDomainId",
+ {version = #'GIOP_Version'{major = 1,
+ minor = 2},
+ ft_domain_id = "FT_FTDomainId",
object_group_id = ?ULONGLONGMAX,
object_group_ref_version = ?LONGMAX}},
- #'IOP_TaggedComponent'{tag = ?TAG_FT_PRIMARY,
- component_data =
+ #'IOP_TaggedComponent'{tag = ?TAG_FT_PRIMARY,
+ component_data =
#'FT_TagFTPrimaryTaggedComponent'{primary = true}},
- #'IOP_TaggedComponent'{tag = ?TAG_FT_HEARTBEAT_ENABLED,
- component_data =
+ #'IOP_TaggedComponent'{tag = ?TAG_FT_HEARTBEAT_ENABLED,
+ component_data =
#'FT_TagFTHeartbeatEnabledTaggedComponent'{heartbeat_enabled = true}},
- #'IOP_TaggedComponent'{tag = ?TAG_CSI_SEC_MECH_LIST,
- component_data =
+ #'IOP_TaggedComponent'{tag = ?TAG_CSI_SEC_MECH_LIST,
+ component_data =
#'CSIIOP_CompoundSecMechList'
{stateful = false,
- mechanism_list =
+ mechanism_list =
[#'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
+ {target_requires = 6,
+ transport_mech =
#'IOP_TaggedComponent'
{tag=?TAG_TLS_SEC_TRANS,
component_data=#'CSIIOP_TLS_SEC_TRANS'
- {target_supports = 7,
- target_requires = 8,
- addresses =
- [#'CSIIOP_TransportAddress'{host_name = "127.0.0.1",
+ {target_supports = 7,
+ target_requires = 8,
+ addresses =
+ [#'CSIIOP_TransportAddress'{host_name = "127.0.0.1",
port = 6001}]}},
- as_context_mech =
+ as_context_mech =
#'CSIIOP_AS_ContextSec'
{target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
+ client_authentication_mech = [1, 255],
+ target_name = [2,255]},
+ sas_context_mech =
#'CSIIOP_SAS_ContextSec'
{target_supports = 11, target_requires = 12,
- privilege_authorities =
+ privilege_authorities =
[#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
+ {syntax = ?ULONGMAX,
+ name = [3,255]}],
supported_naming_mechanisms = [[4,255],[5,255]],
supported_identity_types = ?ULONGMAX}},
#'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
+ {target_requires = 6,
+ transport_mech =
#'IOP_TaggedComponent'
{tag=?TAG_NULL_TAG,
component_data=[]},
- as_context_mech =
+ as_context_mech =
#'CSIIOP_AS_ContextSec'
{target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
+ client_authentication_mech = [1, 255],
+ target_name = [2,255]},
+ sas_context_mech =
#'CSIIOP_SAS_ContextSec'
{target_supports = 11, target_requires = 12,
- privilege_authorities =
+ privilege_authorities =
[#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
+ {syntax = ?ULONGMAX,
+ name = [3,255]}],
supported_naming_mechanisms = [[4,255],[5,255]],
supported_identity_types = ?ULONGMAX}},
#'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
+ {target_requires = 6,
+ transport_mech =
#'IOP_TaggedComponent'
{tag=?TAG_SECIOP_SEC_TRANS,
component_data=#'CSIIOP_SECIOP_SEC_TRANS'
- {target_supports = 7,
- target_requires = 8,
+ {target_supports = 7,
+ target_requires = 8,
mech_oid = [0,255],
target_name = [0,255],
- addresses =
- [#'CSIIOP_TransportAddress'{host_name = "127.0.0.1",
+ addresses =
+ [#'CSIIOP_TransportAddress'{host_name = "127.0.0.1",
port = 6001}]}},
- as_context_mech =
+ as_context_mech =
#'CSIIOP_AS_ContextSec'
{target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
+ client_authentication_mech = [1, 255],
+ target_name = [2,255]},
+ sas_context_mech =
#'CSIIOP_SAS_ContextSec'
{target_supports = 11, target_requires = 12,
- privilege_authorities =
+ privilege_authorities =
[#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
+ {syntax = ?ULONGMAX,
+ name = [3,255]}],
supported_naming_mechanisms = [[4,255],[5,255]],
supported_identity_types = ?ULONGMAX}}]}}],
iop_ior:create(Version, "IDL:omg.org/CosNaming/NamingContextExt:1.0",
@@ -760,11 +801,11 @@ create_components_IOR(Version) ->
%% function : alternate_ssl_iiop_address
%% Arguments: Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
alternate_ssl_iiop_address(Host, Port, SSLPort) ->
IOR = create_alternate_ssl_iiop_address(Host, Port, SSLPort),
-
+
?match(false, corba_object:non_existent(IOR)),
?match({'object_forward',_}, corba:locate(IOR)),
?match({'object_forward',_}, corba:locate(IOR, 10000)),
@@ -775,37 +816,37 @@ alternate_ssl_iiop_address(Host, Port, SSLPort) ->
%% function : create_alternate_ssl_iiop_address
%% Arguments: Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
create_alternate_ssl_iiop_address(Host, Port, SSLPort) ->
- MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
+ MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
component_data = ?ORBER_ORB_TYPE_1},
- #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
+ #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
component_data = ?DEFAULT_CODESETS},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
+ 'HostID' = Host,
'Port' = Port}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
+ 'HostID' = Host,
'Port' = 8000}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
+ #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
+ 'HostID' = Host,
'Port' = 8000}},
- #'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'{target_supports = 2,
- target_requires = 2,
+ #'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
+ component_data=#'SSLIOP_SSL'{target_supports = 2,
+ target_requires = 2,
port = SSLPort}}],
#'IOP_IOR'{type_id=TypeID,
- profiles=P1} = _IORA = iop_ior:create_external({1,2},
+ profiles=P1} = _IORA = iop_ior:create_external({1,2},
"IDL:omg.org/CosNaming/NamingContextExt:1.0",
- Host, 8000,
+ Host, 8000,
"NameService", MC),
- #'IOP_IOR'{profiles=P2} = _IORB = iop_ior:create_external({1,1},
+ #'IOP_IOR'{profiles=P2} = _IORB = iop_ior:create_external({1,1},
"IDL:omg.org/CosNaming/NamingContextExt:1.0",
- Host, 8000,
+ Host, 8000,
"NameService", []),
#'IOP_IOR'{type_id=TypeID, profiles=P2++P1}.
@@ -814,11 +855,11 @@ create_alternate_ssl_iiop_address(Host, Port, SSLPort) ->
%% function : timeouts
%% Arguments: Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
timeouts(Host, Port, ReqT) ->
- NSR = corba:resolve_initial_references_remote("NameService",
+ NSR = corba:resolve_initial_references_remote("NameService",
["iiop://"++Host++":"++integer_to_list(Port)]),
NC1 = lname_component:set_id(lname_component:create(), "mamba"),
N1 = lname:insert_component(lname:create(), 1, NC1),
@@ -828,21 +869,21 @@ timeouts(Host, Port, ReqT) ->
Viper = 'CosNaming_NamingContext':resolve(NSR, N2),
?match({'EXCEPTION',{'TIMEOUT',_,_,_}},
- orber_test_timeout_server:twoway_function(Viper, ReqT, ReqT*2)),
- ?match(ok, orber_test_timeout_server:oneway_function(Viper, ReqT*2)),
+ orber_test_timeout_server:twoway_function(Viper, ReqT, ReqT*2)),
+ ?match(ok, orber_test_timeout_server:oneway_function(Viper, ReqT*2)),
?match({'EXCEPTION',{'TIMEOUT',_,_,_}},
- orber_test_server:testing_iiop_twoway_delay(Mamba, ReqT)),
+ orber_test_server:testing_iiop_twoway_delay(Mamba, ReqT)),
?match(ok, orber_test_server:testing_iiop_oneway_delay(Mamba, ReqT)),
-
+
%% Since the objects are stalled we must wait until they are available again
%% to be able to run any more tests and get the correct results.
timer:sleep(ReqT*4),
-
- ?match(ok, orber_test_timeout_server:twoway_function(Viper, ReqT*2, ReqT)),
- ?match(ok, orber_test_timeout_server:oneway_function(Viper, ReqT*2)),
-
- ?match(ok, orber_test_server:testing_iiop_twoway_delay(Mamba, 0)),
+
+ ?match(ok, orber_test_timeout_server:twoway_function(Viper, ReqT*2, ReqT)),
+ ?match(ok, orber_test_timeout_server:oneway_function(Viper, ReqT*2)),
+
+ ?match(ok, orber_test_server:testing_iiop_twoway_delay(Mamba, 0)),
?match(ok, orber_test_server:testing_iiop_oneway_delay(Mamba, 0)),
timer:sleep(ReqT*4),
@@ -853,11 +894,11 @@ timeouts(Host, Port, ReqT) ->
%% Arguments: Host - which node to contact.
%% Port - which port the other orb uses.
%% Returns : term()
-%% Effect :
+%% Effect :
%%------------------------------------------------------------
light_tests(Host, Port, ObjName) ->
- NSR = corba:resolve_initial_references_remote("NameService",
+ NSR = corba:resolve_initial_references_remote("NameService",
["iiop://"++Host++":"++integer_to_list(Port)]),
NC1 = lname_component:set_id(lname_component:create(), "not_exist"),
N1 = lname:insert_component(lname:create(), 1, NC1),
@@ -868,7 +909,7 @@ light_tests(Host, Port, ObjName) ->
'CosNaming_NamingContext':resolve(NSR, N1)),
NC2 = lname_component:set_id(lname_component:create(), ObjName),
N2 = lname:insert_component(lname:create(), 1, NC2),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
+ Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
'CosNaming_NamingContext':resolve(NSR, N2)),
Nodes = orber:get_lightweight_nodes(),
io:format("Light Nodes: ~p~n", [Nodes]),
@@ -890,165 +931,165 @@ test_coding(Obj) ->
test_coding(Obj, Local) ->
%%--- Testing code and decode arguments ---
?match({ok, 1.5}, orber_test_server:testing_iiop_float(Obj, 1.5)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_float(Obj, atom)),
?match({ok,1.0}, orber_test_server:testing_iiop_double(Obj, 1.0)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_double(Obj, "wrong")),
-
+
?match({ok,0}, orber_test_server:testing_iiop_short(Obj, 0)),
?match({ok,?SHORTMAX}, orber_test_server:testing_iiop_short(Obj, ?SHORTMAX)),
?match({ok,?SHORTMIN}, orber_test_server:testing_iiop_short(Obj, ?SHORTMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_short(Obj, atomic)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_short(Obj, ?SHORTMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_short(Obj, ?SHORTMIN-1)),
-
+
?match({ok,0}, orber_test_server:testing_iiop_ushort(Obj, 0)),
?match({ok,?USHORTMAX}, orber_test_server:testing_iiop_ushort(Obj, ?USHORTMAX)),
?match({ok,?USHORTMIN}, orber_test_server:testing_iiop_ushort(Obj, ?USHORTMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_ushort(Obj, ?USHORTMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_ushort(Obj, ?USHORTMIN-1)),
-
+
?match({ok,0}, orber_test_server:testing_iiop_long(Obj, 0)),
?match({ok,?LONGMAX}, orber_test_server:testing_iiop_long(Obj, ?LONGMAX)),
?match({ok,?LONGMIN}, orber_test_server:testing_iiop_long(Obj, ?LONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_long(Obj, "wrong")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_long(Obj, ?LONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_long(Obj, ?LONGMIN-1)),
-
+
?match({ok,0}, orber_test_server:testing_iiop_longlong(Obj, 0)),
?match({ok,?LONGLONGMAX}, orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMAX)),
?match({ok,?LONGLONGMIN}, orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_longlong(Obj, "wrong")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMIN-1)),
-
+
?match({ok,0}, orber_test_server:testing_iiop_ulong(Obj, 0)),
?match({ok,?ULONGMAX}, orber_test_server:testing_iiop_ulong(Obj, ?ULONGMAX)),
?match({ok,?ULONGMIN}, orber_test_server:testing_iiop_ulong(Obj, ?ULONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_ulong(Obj, ?ULONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_ulong(Obj, ?ULONGMIN-1)),
-
+
?match({ok,0}, orber_test_server:testing_iiop_ulonglong(Obj, 0)),
?match({ok,?ULONGLONGMAX}, orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMAX)),
?match({ok,?ULONGLONGMIN}, orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMIN-1)),
-
+
?match({ok,98}, orber_test_server:testing_iiop_char(Obj, 98)),
?match({ok,$b}, orber_test_server:testing_iiop_char(Obj, $b)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_char(Obj, atomic)),
?match({ok,65535}, orber_test_server:testing_iiop_wchar(Obj, 65535)),
?match({ok,$b}, orber_test_server:testing_iiop_wchar(Obj, $b)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_wchar(Obj, atomic)),
-
+
?match({ok,true}, orber_test_server:testing_iiop_bool(Obj, true)),
?match({ok,false}, orber_test_server:testing_iiop_bool(Obj, false)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_bool(Obj, atom)),
-
+
?match({ok,1}, orber_test_server:testing_iiop_octet(Obj, 1)),
% No real guards for this case.
-% ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+% ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
% orber_test_server:testing_iiop_octet(Obj, 1.5)),
IOR12 = create_components_IOR({1,2}),
?match({ok,Obj}, orber_test_server:testing_iiop_obj(Obj, Obj)),
?match({ok,IOR12}, orber_test_server:testing_iiop_obj(Obj, IOR12)),
PObj = orber_test_server:oe_create([], [{pseudo,true}]),
?match({ok, _}, orber_test_server:testing_iiop_obj(Obj, PObj)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_obj(Obj, "no_object")),
?match({ok,"string"}, orber_test_server:testing_iiop_string(Obj, "string")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_string(Obj, "ToLongString")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_string(Obj, atomic)),
?match({ok,[65535]}, orber_test_server:testing_iiop_wstring(Obj, [65535])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_wstring(Obj, "ToLongWstring")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_wstring(Obj, atomic)),
- ?match({ok, one},
+ ?match({ok, one},
orber_test_server:testing_iiop_enum(Obj, one)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_enum(Obj, three)),
- ?match({ok,[1,2,3]},
+ ?match({ok,[1,2,3]},
orber_test_server:testing_iiop_seq(Obj, [1,2,3])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_seq(Obj, [1,2,3,4])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_seq(Obj, false)),
- ?match({ok,[#orber_test_server_struc{a=1, b=2}]},
- orber_test_server:testing_iiop_struc_seq(Obj,
+ ?match({ok,[#orber_test_server_struc{a=1, b=2}]},
+ orber_test_server:testing_iiop_struc_seq(Obj,
[#orber_test_server_struc{a=1, b=2}])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_struc_seq(Obj, false)),
- ?match({ok,[#orber_test_server_uni{label=1, value=66}]},
- orber_test_server:testing_iiop_uni_seq(Obj,
+ ?match({ok,[#orber_test_server_uni{label=1, value=66}]},
+ orber_test_server:testing_iiop_uni_seq(Obj,
[#orber_test_server_uni{label=1, value=66}])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_uni_seq(Obj, false)),
- ?match({ok,{"one", "two"}},
+ ?match({ok,{"one", "two"}},
orber_test_server:testing_iiop_array(Obj, {"one", "two"})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_array(Obj, {"one", "two", "three"})),
- ?match({ok,#orber_test_server_struc{a=1, b=2}},
- orber_test_server:testing_iiop_struct(Obj,
+ ?match({ok,#orber_test_server_struc{a=1, b=2}},
+ orber_test_server:testing_iiop_struct(Obj,
#orber_test_server_struc{a=1, b=2})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_struct(Obj,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_struct(Obj,
#orber_test_server_struc{a="WRONG", b=2})),
- ?match({ok,#orber_test_server_uni{label=1, value=66}},
- orber_test_server:testing_iiop_union(Obj,
+ ?match({ok,#orber_test_server_uni{label=1, value=66}},
+ orber_test_server:testing_iiop_union(Obj,
#orber_test_server_uni{label=1, value=66})),
- ?match({ok,#orber_test_server_uni_d{label=1, value=66}},
- orber_test_server:testing_iiop_union_d(Obj,
+ ?match({ok,#orber_test_server_uni_d{label=1, value=66}},
+ orber_test_server:testing_iiop_union_d(Obj,
#orber_test_server_uni_d{label=1, value=66})),
- ?match({ok,#orber_test_server_uni_d{label=2, value=true}},
- orber_test_server:testing_iiop_union_d(Obj,
+ ?match({ok,#orber_test_server_uni_d{label=2, value=true}},
+ orber_test_server:testing_iiop_union_d(Obj,
#orber_test_server_uni_d{label=2, value=true})),
?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_union_d(Obj,
+ orber_test_server:testing_iiop_union_d(Obj,
#orber_test_server_uni_d{label=2, value=66})),
case Local of
true ->
- ?match({ok,#orber_test_server_uni{label=2, value=66}},
- orber_test_server:testing_iiop_union(Obj,
+ ?match({ok,#orber_test_server_uni{label=2, value=66}},
+ orber_test_server:testing_iiop_union(Obj,
#orber_test_server_uni{label=2, value=66}));
false ->
- ?match({ok,#orber_test_server_uni{label=2, value=undefined}},
- orber_test_server:testing_iiop_union(Obj,
+ ?match({ok,#orber_test_server_uni{label=2, value=undefined}},
+ orber_test_server:testing_iiop_union(Obj,
#orber_test_server_uni{label=2, value=66}))
end,
@@ -1059,258 +1100,258 @@ test_coding(Obj, Local) ->
C4 = orber_test_server:fixed52negconst1(),
C5 = orber_test_server:fixed52negconst2(),
C6 = orber_test_server:fixed52negconst3(),
-
+
?match({ok,C1}, orber_test_server:testing_iiop_fixed(Obj, C1)),
?match({ok,C2}, orber_test_server:testing_iiop_fixed(Obj, C2)),
?match({ok,C3}, orber_test_server:testing_iiop_fixed(Obj, C3)),
?match({ok,C4}, orber_test_server:testing_iiop_fixed(Obj, C4)),
?match({ok,C5}, orber_test_server:testing_iiop_fixed(Obj, C5)),
?match({ok,C6}, orber_test_server:testing_iiop_fixed(Obj, C6)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_fixed(Obj, #fixed{digits = 5,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_fixed(Obj, #fixed{digits = 5,
scale = 2,
value = 123450})),
?match(ok, orber_test_server:testing_iiop_void(Obj)),
- ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
+ ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
orber_test_server:pseudo_call_raise_exc(Obj, 1)),
- ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
+ ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
orber_test_server:pseudo_call_raise_exc(Obj, 2)),
- ?match({'EXCEPTION',{'orber_test_server_UserDefinedException',_}},
+ ?match({'EXCEPTION',{'orber_test_server_UserDefinedException',_}},
orber_test_server:raise_local_exception(Obj)),
?match({'EXCEPTION',{'orber_test_server_ComplexUserDefinedException',_,
- [#orber_test_server_struc{a=1, b=2}]}},
+ [#orber_test_server_struc{a=1, b=2}]}},
orber_test_server:raise_complex_local_exception(Obj)),
%% Test all TypeCodes
- ?match({ok, #any{typecode = tk_long, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
+ ?match({ok, #any{typecode = tk_long, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
value = "wrong"})),
- ?match({ok, #any{typecode = tk_float, value = 1.5}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_float,
+ ?match({ok, #any{typecode = tk_float, value = 1.5}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_float,
value = 1.5})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
value = "wrong"})),
- ?match({ok, #any{typecode = tk_double}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_double,
+ ?match({ok, #any{typecode = tk_double}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_double,
value = 1.0})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_double,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_double,
value = "wrong"})),
- ?match({ok, #any{typecode = tk_short, value = -1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_short,
+ ?match({ok, #any{typecode = tk_short, value = -1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_short,
value = -1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_short,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_short,
value = atomic})),
- ?match({ok, #any{typecode = tk_ushort, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ushort,
+ ?match({ok, #any{typecode = tk_ushort, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ushort,
value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ushort,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ushort,
value = -1})),
- ?match({ok, #any{typecode = tk_long, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
+ ?match({ok, #any{typecode = tk_long, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
value = "wrong"})),
- ?match({ok, #any{typecode = tk_longlong, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_longlong,
+ ?match({ok, #any{typecode = tk_longlong, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_longlong,
value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_longlong,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_longlong,
value = "wrong"})),
- ?match({ok, #any{typecode = tk_ulong, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
+ ?match({ok, #any{typecode = tk_ulong, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
value = 1})),
- ?match({ok, #any{typecode = tk_ulong, value = 4294967295}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
+ ?match({ok, #any{typecode = tk_ulong, value = 4294967295}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
value = 4294967295})),
?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
value = 4294967296})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
value = -1})),
- ?match({ok, #any{typecode = tk_ulonglong, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulonglong,
+ ?match({ok, #any{typecode = tk_ulonglong, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulonglong,
value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulonglong,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulonglong,
value = -1})),
- ?match({ok, #any{typecode = tk_char, value = 98}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
+ ?match({ok, #any{typecode = tk_char, value = 98}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
value = 98})),
- ?match({ok, #any{typecode = tk_char, value = $b}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
+ ?match({ok, #any{typecode = tk_char, value = $b}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
value = $b})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
value = atomic})),
- ?match({ok, #any{typecode = tk_wchar, value = 65535}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
+ ?match({ok, #any{typecode = tk_wchar, value = 65535}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
value = 65535})),
- ?match({ok, #any{typecode = tk_wchar, value = $b}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
+ ?match({ok, #any{typecode = tk_wchar, value = $b}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
value = $b})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
value = atomic})),
- ?match({ok, #any{typecode = tk_boolean, value = true}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
+ ?match({ok, #any{typecode = tk_boolean, value = true}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
value = true})),
- ?match({ok, #any{typecode = tk_boolean, value = false}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
+ ?match({ok, #any{typecode = tk_boolean, value = false}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
value = false})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
value = 1})),
- ?match({ok, #any{typecode = tk_octet, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_octet,
+ ?match({ok, #any{typecode = tk_octet, value = 1}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_octet,
value = 1})),
- ?match({ok, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"}, value = Obj}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"},
+ ?match({ok, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"}, value = Obj}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"},
value = Obj})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"},
value = "No Object"})),
- ?match({ok, #any{typecode = {tk_string, 6}, value = "string"}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_string, 6},
+ ?match({ok, #any{typecode = {tk_string, 6}, value = "string"}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_string, 6},
value = "string"})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_string,
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_string,
value = atomic})),
- ?match({ok, #any{typecode = {tk_wstring, 1}, value = [65535]}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_wstring, 1},
+ ?match({ok, #any{typecode = {tk_wstring, 1}, value = [65535]}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_wstring, 1},
value = [65535]})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_wstring, 1},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_wstring, 1},
value = atomic})),
- ?match({ok, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
- value = two}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
+ ?match({ok, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
+ value = two}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
value = two})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
value = three})),
- ?match({ok, #any{typecode = {tk_sequence, tk_long, 3},
- value = [1,2,3]}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_sequence, tk_long, 3},
+ ?match({ok, #any{typecode = {tk_sequence, tk_long, 3},
+ value = [1,2,3]}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_sequence, tk_long, 3},
value = [1,2,3]})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_sequence, tk_long, 3},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_sequence, tk_long, 3},
value = false})),
- ?match({ok, #any{typecode = {tk_array,{tk_string,0},2},
- value = {"one", "two"}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
+ ?match({ok, #any{typecode = {tk_array,{tk_string,0},2},
+ value = {"one", "two"}}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
value = {"one", "two"}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
value = {"one", "two", "three"}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
value = {1, 2}})),
?match({ok, #any{typecode = {tk_struct,"IDL:omg.org/orber_test/server/struc:1.0",
"struc",
- [{"a",tk_long},{"b",tk_short}]},
- value = #orber_test_server_struc{a=1, b=2}}},
+ [{"a",tk_long},{"b",tk_short}]},
+ value = #orber_test_server_struc{a=1, b=2}}},
orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_struct,"IDL:omg.org/orber_test/server/struc:1.0",
"struc",
[{"a",tk_long},{"b",tk_short}]},
value = #orber_test_server_struc{a=1, b=2}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_struct,"IDL:omg.org/orber_test/server/struc:1.0",
"struc",
- [{"a",tk_long},{"b",tk_short}]},
+ [{"a",tk_long},{"b",tk_short}]},
value = #orber_test_server_struc{a=1, b="string"}})),
- ?match({ok, #any{typecode =
+ ?match({ok, #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=1, value=66}}},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
+ value = #orber_test_server_uni{label=1, value=66}}},
orber_test_server:
- testing_iiop_any(Obj,
- #any{typecode =
+ testing_iiop_any(Obj,
+ #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
value = #orber_test_server_uni{label=1, value=66}})),
case Local of
true ->
- ?match({ok, #any{typecode =
+ ?match({ok, #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=2, value=66}}},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
+ value = #orber_test_server_uni{label=2, value=66}}},
orber_test_server:
testing_iiop_any(Obj,
- #any{typecode =
+ #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
value = #orber_test_server_uni{label=2, value=66}}));
false ->
- ?match({ok, #any{typecode =
+ ?match({ok, #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=2, value=undefined}}},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
+ value = #orber_test_server_uni{label=2, value=undefined}}},
orber_test_server:
testing_iiop_any(Obj,
- #any{typecode =
+ #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
value = #orber_test_server_uni{label=2, value=66}}))
end,
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:
- testing_iiop_any(Obj,
- #any{typecode =
+ testing_iiop_any(Obj,
+ #any{typecode =
{tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
+ "uni", tk_long, -1, [{1,"a",tk_long}]},
value = #orber_test_server_uni{label=1, value="string"}})),
- ?match({ok, #any{typecode = {tk_fixed,5,2},
- value = #fixed{digits = 5, scale = 2, value = 12345}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,5,2},
- value = #fixed{digits = 5,
- scale = 2,
+ ?match({ok, #any{typecode = {tk_fixed,5,2},
+ value = #fixed{digits = 5, scale = 2, value = 12345}}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,5,2},
+ value = #fixed{digits = 5,
+ scale = 2,
value = 12345}})),
- ?match({ok, #any{typecode = {tk_fixed,10,2},
- value = #fixed{digits = 10, scale = 2, value = 1234567890}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,10,2},
- value = #fixed{digits = 10,
- scale = 2,
+ ?match({ok, #any{typecode = {tk_fixed,10,2},
+ value = #fixed{digits = 10, scale = 2, value = 1234567890}}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,10,2},
+ value = #fixed{digits = 10,
+ scale = 2,
value = 1234567890}})),
- ?match({ok, #any{typecode = {tk_fixed,6,2},
- value = #fixed{digits = 6, scale = 2, value = 300000}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,6,2},
- value = #fixed{digits = 6,
- scale = 2,
+ ?match({ok, #any{typecode = {tk_fixed,6,2},
+ value = #fixed{digits = 6, scale = 2, value = 300000}}},
+ orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,6,2},
+ value = #fixed{digits = 6,
+ scale = 2,
value = 300000}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
+ ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
orber_test_server:
testing_iiop_server_marshal(Obj, "string")),
-
+
RecS = #orber_test_server_rec_struct{chain = [#orber_test_server_rec_struct{chain = []}]},
?match(RecS, orber_test_server:testing_iiop_rec_struct(Obj, RecS)),
-
- RecU = #orber_test_server_rec_union{label = 'RecursiveType',
+
+ RecU = #orber_test_server_rec_union{label = 'RecursiveType',
value = [#orber_test_server_rec_union{label = 'RecursiveType',
value = []}]},
?match(RecU, orber_test_server:testing_iiop_rec_union(Obj, RecU)),
%% RecA1 = #any{typecode = unsupported, value = RecS},
%% RecA2 = #any{typecode = unsupported, value = RecU},
-%% ?match(RecA1,
-%% orber_test_server:testing_iiop_rec_any(Obj, RecA1)),
-%% ?match(RecA2,
-%% orber_test_server:testing_iiop_rec_any(Obj, RecA2)),
+%% ?match(RecA1,
+%% orber_test_server:testing_iiop_rec_any(Obj, RecA1)),
+%% ?match(RecA2,
+%% orber_test_server:testing_iiop_rec_any(Obj, RecA2)),
ok.
@@ -1333,14 +1374,14 @@ Result : ~p
ok.
%%--------------- Testing Missing Module ---------------------
-oe_get_interface() ->
+oe_get_interface() ->
non_existing_module:tc(foo).
%%--------------- INTERCEPTOR FUNCTIONS ----------------------
%%------------------------------------------------------------
%% function : new_in_connection
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
new_in_connection(Arg, CHost, Port) ->
Host = node(),
@@ -1354,14 +1395,14 @@ To Host : ~p
To Port : ~p
Peers : ~p
Arg : ~p
-==========================================~n",
+==========================================~n",
[Host, CHost, Port, SHost, SPort, Peers, Arg]),
{Host}.
%%------------------------------------------------------------
%% function : new_out_connection
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
new_out_connection(Arg, SHost, Port) ->
Host = node(),
@@ -1370,73 +1411,73 @@ Node : ~p
To Host : ~p
To Port : ~p
Arg : ~p
-==========================================~n",
+==========================================~n",
[Host, SHost, Port, Arg]),
{Host}.
%%------------------------------------------------------------
%% function : closed_in_connection
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
closed_in_connection(Arg) ->
error_logger:info_msg("=============== closed_in_connection =====
Node : ~p
Connection: ~p
-==========================================~n",
+==========================================~n",
[node(), Arg]),
Arg.
%%------------------------------------------------------------
%% function : closed_out_connection
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
closed_out_connection(Arg) ->
error_logger:info_msg("=============== closed_out_connection ====
Node : ~p
Connection: ~p
-==========================================~n",
+==========================================~n",
[node(), Arg]),
Arg.
%%------------------------------------------------------------
%% function : in_request_encoded
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
-in_request_encoded(Ref, _ObjKey, Ctx, Op,
+in_request_encoded(Ref, _ObjKey, Ctx, Op,
<<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8,T/binary>>, _Args) ->
error_logger:info_msg("=============== in_request_encoded =======
Connection: ~p
Operation : ~p
Body : ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, T, Ctx]),
{T, "NewArgs"}.
%%------------------------------------------------------------
%% function : in_reply_encoded
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
in_reply_encoded(Ref, _ObjKey, Ctx, Op,
- <<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8,T/binary>>,
+ <<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8,T/binary>>,
_Args) ->
error_logger:info_msg("============== in_reply_encoded ==========
Connection: ~p
Operation : ~p
Body : ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, T, Ctx]),
{T, "NewArgs"}.
%%------------------------------------------------------------
%% function : out_reply_encoded
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
out_reply_encoded(Ref, _ObjKey, Ctx, Op, List, _Args) ->
error_logger:info_msg("============== out_reply_encoded =========
@@ -1444,14 +1485,14 @@ Connection: ~p
Operation : ~p
Body : ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, List, Ctx]),
{list_to_binary([<<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8>>|List]), "NewArgs"}.
%%------------------------------------------------------------
%% function : out_request_encoded
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
out_request_encoded(Ref, _ObjKey, Ctx, Op, List, _Args) ->
error_logger:info_msg("============== out_request_encoded =======
@@ -1459,14 +1500,14 @@ Connection: ~p
Operation : ~p
Body : ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, List, Ctx]),
{list_to_binary([<<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8>>|List]), "NewArgs"}.
%%------------------------------------------------------------
%% function : in_request
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
in_request(Ref, _ObjKey, Ctx, Op, Params, _Args) ->
error_logger:info_msg("=============== in_request ===============
@@ -1474,14 +1515,14 @@ Connection: ~p
Operation : ~p
Parameters: ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, Params, Ctx]),
{Params, "NewArgs"}.
%%------------------------------------------------------------
%% function : in_reply
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
in_reply(Ref, _ObjKey, Ctx, Op, Reply, _Args) ->
error_logger:info_msg("=============== in_reply =================
@@ -1489,14 +1530,14 @@ Connection: ~p
Operation : ~p
Reply : ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, Reply, Ctx]),
{Reply, "NewArgs"}.
%%------------------------------------------------------------
%% function : postinvoke
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
out_reply(Ref, _ObjKey, Ctx, Op, Reply, _Args) ->
error_logger:info_msg("=============== out_reply ================
@@ -1504,14 +1545,14 @@ Connection: ~p
Operation : ~p
Reply : ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, Reply, Ctx]),
{Reply, "NewArgs"}.
%%------------------------------------------------------------
%% function : postinvoke
-%% Arguments:
-%% Returns :
+%% Arguments:
+%% Returns :
%%------------------------------------------------------------
out_request(Ref, _ObjKey, Ctx, Op, Params, _Args) ->
error_logger:info_msg("=============== out_request ==============
@@ -1519,7 +1560,7 @@ Connection: ~p
Operation : ~p
Parameters: ~p
Context : ~p
-==========================================~n",
+==========================================~n",
[Ref, Op, Params, Ctx]),
{Params, "NewArgs"}.
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
index 29b21e8e01..f891440600 100644
--- a/lib/orber/vsn.mk
+++ b/lib/orber/vsn.mk
@@ -1,3 +1,3 @@
-ORBER_VSN = 3.6.22
+ORBER_VSN = 3.6.24
diff --git a/lib/os_mon/c_src/Makefile.in b/lib/os_mon/c_src/Makefile.in
index b81d3f564b..45dc01e993 100644
--- a/lib/os_mon/c_src/Makefile.in
+++ b/lib/os_mon/c_src/Makefile.in
@@ -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
@@ -131,10 +131,10 @@ ifeq ($(findstring vxworks_simso,$(TARGET)),vxworks_simso)
release_spec:
else
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(C_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_PROGRAM) $(TARGET_FILES) $(RELSYSDIR)/priv/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(C_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_PROGRAM) $(TARGET_FILES) "$(RELSYSDIR)/priv/bin"
endif
release_docs_spec:
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index 9c5f9a6aa5..a0432b3093 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -458,8 +458,18 @@ static void error(char* err_msg) {
* 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));
+ char buffer[256] = "[os_mon] cpu supervisor port (cpu_sup): ";
+ int i = strlen(buffer), j = 0;
+ int n = strlen(err_msg);
+
+ while(i < 253 && j < n) {
+ buffer[i++] = err_msg[j++];
+ }
+ buffer[i++] = '\r';
+ buffer[i++] = '\n';
+
+ /* try to use one write only */
+ if(write(FD_ERR, buffer, i));
exit(-1);
}
diff --git a/lib/os_mon/c_src/memsup.c b/lib/os_mon/c_src/memsup.c
index 241e7718db..593a066f98 100644
--- a/lib/os_mon/c_src/memsup.c
+++ b/lib/os_mon/c_src/memsup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -327,27 +327,27 @@ get_mem_procfs(memory_ext *me){
/* Total and free is NEEDED! */
bp = strstr(buffer, "MemTotal:");
- if (sscanf(bp, "MemTotal: %lu kB\n", &(me->total))) me->flag |= F_MEM_TOTAL;
+ if (bp != NULL && sscanf(bp, "MemTotal: %lu kB\n", &(me->total))) me->flag |= F_MEM_TOTAL;
bp = strstr(buffer, "MemFree:");
- if (sscanf(bp, "MemFree: %lu kB\n", &(me->free))) me->flag |= F_MEM_FREE;
+ if (bp != NULL && sscanf(bp, "MemFree: %lu kB\n", &(me->free))) me->flag |= F_MEM_FREE;
/* Extensions */
bp = strstr(buffer, "Buffers:");
- if (sscanf(bp, "Buffers: %lu kB\n", &(me->buffered))) me->flag |= F_MEM_BUFFERS;
+ if (bp != NULL && sscanf(bp, "Buffers: %lu kB\n", &(me->buffered))) me->flag |= F_MEM_BUFFERS;
bp = strstr(buffer, "Cached:");
- if (sscanf(bp, "Cached: %lu kB\n", &(me->cached))) me->flag |= F_MEM_CACHED;
+ if (bp != NULL && sscanf(bp, "Cached: %lu kB\n", &(me->cached))) me->flag |= F_MEM_CACHED;
/* Swap */
bp = strstr(buffer, "SwapTotal:");
- if (sscanf(bp, "SwapTotal: %lu kB\n", &(me->total_swap))) me->flag |= F_SWAP_TOTAL;
+ if (bp != NULL && sscanf(bp, "SwapTotal: %lu kB\n", &(me->total_swap))) me->flag |= F_SWAP_TOTAL;
bp = strstr(buffer, "SwapFree:");
- if (sscanf(bp, "SwapFree: %lu kB\n", &(me->free_swap))) me->flag |= F_SWAP_FREE;
+ if (bp != NULL && sscanf(bp, "SwapFree: %lu kB\n", &(me->free_swap))) me->flag |= F_SWAP_FREE;
me->pagesize = 1024; /* procfs defines its size in kB */
@@ -493,7 +493,7 @@ get_basic_mem(unsigned long *tot, unsigned long *used, unsigned long *pagesize){
#elif defined(__linux__) && !defined(_SC_AVPHYS_PAGES)
memory_ext me;
if (get_mem_procfs(&me) < 0) {
- print_error("ProcFS read error.");
+ print_error("ProcFS read error");
exit(1);
}
*tot = me.total;
@@ -582,7 +582,7 @@ message_loop(int erlin_fd)
* Wait for command from Erlang
*/
if ((res = read(erlin_fd, &cmdLen, 1)) < 0) {
- print_error("Error reading from Erlang.");
+ print_error("Error reading from Erlang");
return;
}
@@ -603,19 +603,19 @@ message_loop(int erlin_fd)
break;
case 0:
- print_error("Erlang has closed.");
+ print_error("Erlang has closed");
return;
default:
- print_error("Error reading from Erlang.");
+ print_error("Error reading from Erlang");
return;
} /* switch() */
} else { /* cmdLen != 1 */
- print_error("Invalid command length (%d) received.", cmdLen);
+ print_error("Invalid command length (%d) received", cmdLen);
return;
}
} else { /* Erlang end closed */
- print_error("Erlang has closed.");
+ print_error("Erlang has closed");
return;
}
}
@@ -641,15 +641,12 @@ static void
print_error(const char *format,...)
{
va_list args;
+ char buffer[256];
va_start(args, format);
- fprintf(stderr, "%s: ", program_name);
- vfprintf(stderr, format, args);
+ vsnprintf(buffer, 256, format, args);
va_end(args);
- fprintf(stderr, " \n");
+ /* try to use one write only */
+ fprintf(stderr, "[os_mon] memory supervisor port (memsup): %s\r\n", buffer);
+ fflush(stderr);
}
-
-
-
-
-
diff --git a/lib/os_mon/c_src/win32sysinfo.c b/lib/os_mon/c_src/win32sysinfo.c
index 2a155aae87..9d4587393f 100644
--- a/lib/os_mon/c_src/win32sysinfo.c
+++ b/lib/os_mon/c_src/win32sysinfo.c
@@ -89,6 +89,7 @@ typedef BOOL (WINAPI *tfpGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER,PULARGE_IN
static tfpGetDiskFreeSpaceEx fpGetDiskFreeSpaceEx;
+static void print_error(const char *msg);
static void
return_answer(char* value)
{
@@ -98,7 +99,7 @@ return_answer(char* value)
res = write(1,(char*) &bytes,1);
if (res != 1) {
- fprintf(stderr,"win32sysinfo:Error writing to pipe");
+ print_error("Error writing to pipe");
exit(1);
}
@@ -107,9 +108,8 @@ return_answer(char* value)
while (left > 0)
{
res = write(1, value+bytes-left, left);
- if (res <= 0)
- {
- fprintf(stderr,"win32sysinfo:Error writing to pipe");
+ if (res <= 0) {
+ print_error("Error writing to pipe");
exit(1);
}
left -= res;
@@ -248,7 +248,6 @@ message_loop()
char cmd[512];
int res;
- fprintf(stderr,"in message_loop\n");
/* Startup ACK. */
return_answer(OK);
while (1)
@@ -257,12 +256,12 @@ message_loop()
* Wait for command from Erlang
*/
if ((res = read(0, &cmdLen, 1)) < 0) {
- fprintf(stderr,"win32sysinfo:Error reading from Erlang.");
+ print_error("Error reading from Erlang");
return;
}
if (res != 1){ /* Exactly one byte read ? */
- fprintf(stderr,"win32sysinfo:Erlang has closed.");
+ print_error("Erlang has closed");
return;
}
if ((res = read(0, &cmd, cmdLen)) == cmdLen){
@@ -291,11 +290,11 @@ message_loop()
return_answer("xEND");
}
else if (res == 0) {
- fprintf(stderr,"win32sysinfo:Erlang has closed.");
+ print_error("Erlang has closed");
return;
}
else {
- fprintf(stderr,"win32sysinfo:Error reading from Erlang.");
+ print_error("Error reading from Erlang");
return;
}
}
@@ -309,10 +308,9 @@ int main(int argc, char ** argv){
message_loop();
return 0;
}
-
-
-
-
-
-
-
+static void
+print_error(const char *msg) {
+ /* try to use one write only */
+ fprintf(stderr, "[os_mon] win32 supervisor port (win32sysinfo): %s\r\n", msg);
+ fflush(stderr);
+}
diff --git a/lib/os_mon/doc/src/Makefile b/lib/os_mon/doc/src/Makefile
index c9765749c9..aa8fb4b60c 100644
--- a/lib/os_mon/doc/src/Makefile
+++ b/lib/os_mon/doc/src/Makefile
@@ -109,16 +109,16 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6DIR)/* $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/os_mon/doc/src/make.dep b/lib/os_mon/doc/src/make.dep
deleted file mode 100644
index b657f2e036..0000000000
--- a/lib/os_mon/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex cpu_sup.tex disksup.tex memsup.tex \
- nteventlog.tex os_mon.tex os_mon_mib.tex os_sup.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index f641bbd828..6674d7b722 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -30,6 +30,54 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix segmentation fault in memsup</p>
+ <p>
+ when /proc/meminfo does not include information about
+ buffers/cache (for instance inside OpenVZ container)
+ (Thanks to Anton Vorobev)</p>
+ <p>
+ Own Id: OTP-9913</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.2.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.2.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/mibs/Makefile b/lib/os_mon/mibs/Makefile
index a361fef378..a6d8ab5042 100644
--- a/lib/os_mon/mibs/Makefile
+++ b/lib/os_mon/mibs/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
@@ -88,13 +88,13 @@ $(SNMP_BIN_TARGET_DIR)/OTP-OS-MON-MIB.bin: \
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/mibs
- $(INSTALL_DIR) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DATA) $(MIB_FILES) $(FUNCS_FILES) $(RELSYSDIR)/mibs
- $(INSTALL_DATA) $(V1_MIB_FILES) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_TARGETS) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/priv/mibs
- $(INSTALL_DATA) $(BIN_TARGETS) $(RELSYSDIR)/priv/mibs
+ $(INSTALL_DIR) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DIR) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DATA) $(MIB_FILES) $(FUNCS_FILES) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DATA) $(V1_MIB_FILES) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_TARGETS) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/mibs"
+ $(INSTALL_DATA) $(BIN_TARGETS) "$(RELSYSDIR)/priv/mibs"
release_docs_spec:
diff --git a/lib/os_mon/src/Makefile b/lib/os_mon/src/Makefile
index 9a75446a89..a8ad26f6a1 100644
--- a/lib/os_mon/src/Makefile
+++ b/lib/os_mon/src/Makefile
@@ -94,11 +94,11 @@ $(EBIN)/memsup.$(EMULATOR): $(MEMSUP_HRL)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index e414e2c10b..34251178ee 100644
--- a/lib/os_mon/src/cpu_sup.erl
+++ b/lib/os_mon/src/cpu_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -764,8 +764,7 @@ port_receive_cpu_util_entries(_, _, Data) ->
exit({data_mismatch, Data}).
start_portprogram() ->
- Command = filename:join([code:priv_dir(os_mon), "bin", "cpu_sup"]),
- Port = open_port({spawn, Command}, [stream]),
+ Port = os_mon:open_port("cpu_sup", [stream]),
port_command(Port, ?ping),
4711 = port_receive_uint32(Port, 5000),
Port.
diff --git a/lib/os_mon/src/disksup.erl b/lib/os_mon/src/disksup.erl
index 308cd1b7fa..c7abb7a386 100644
--- a/lib/os_mon/src/disksup.erl
+++ b/lib/os_mon/src/disksup.erl
@@ -43,24 +43,24 @@ start_link() ->
gen_server:start_link({local, disksup}, disksup, [], []).
get_disk_data() ->
- os_mon:call(disksup, get_disk_data).
+ os_mon:call(disksup, get_disk_data, infinity).
get_check_interval() ->
- os_mon:call(disksup, get_check_interval).
+ os_mon:call(disksup, get_check_interval, infinity).
set_check_interval(Minutes) ->
case param_type(disk_space_check_interval, Minutes) of
true ->
- os_mon:call(disksup, {set_check_interval, Minutes});
+ os_mon:call(disksup, {set_check_interval, Minutes}, infinity);
false ->
erlang:error(badarg)
end.
get_almost_full_threshold() ->
- os_mon:call(disksup, get_almost_full_threshold).
+ os_mon:call(disksup, get_almost_full_threshold, infinity).
set_almost_full_threshold(Float) ->
case param_type(disk_almost_full_threshold, Float) of
true ->
- os_mon:call(disksup, {set_almost_full_threshold, Float});
+ os_mon:call(disksup, {set_almost_full_threshold, Float}, infinity);
false ->
erlang:error(badarg)
end.
diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl
index ba07a529bc..54771b4703 100644
--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -112,7 +112,7 @@ get_helper_timeout() ->
set_helper_timeout(Seconds) ->
case param_type(memsup_helper_timeout, Seconds) of
true ->
- os_mon:call(memsup, {set_helper_timeout, Seconds});
+ os_mon:call(memsup, {set_helper_timeout, Seconds}, infinity);
false ->
erlang:error(badarg)
end.
@@ -802,8 +802,7 @@ port_init() ->
port_idle(Port).
start_portprogram() ->
- Command = filename:join([code:priv_dir(os_mon), "bin", "memsup"]),
- open_port({spawn, Command}, [{packet, 1}]).
+ os_mon:open_port("memsup",[{packet,1}]).
%% The connected process loops are a bit awkward (several different
%% functions doing almost the same thing) as
diff --git a/lib/os_mon/src/os_mon.erl b/lib/os_mon/src/os_mon.erl
index ef368571db..2b6cd7c498 100644
--- a/lib/os_mon/src/os_mon.erl
+++ b/lib/os_mon/src/os_mon.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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 @@
-behaviour(supervisor).
%% API
--export([call/2, call/3, get_env/2]).
+-export([call/2, call/3, get_env/2, open_port/2]).
%% Application callbacks
-export([start/2, stop/1]).
@@ -79,6 +79,22 @@ get_env(Service, Param) ->
Service:param_default(Param)
end.
+open_port(Name, Opts) ->
+ PrivDir = code:priv_dir(os_mon),
+ ReleasedPath = filename:join([PrivDir,"bin",Name]),
+ %% Check os_mon*/priv/bin/Name
+ case filelib:is_regular(ReleasedPath) of
+ true ->
+ erlang:open_port({spawn, "\""++ReleasedPath++"\""}, Opts);
+ false ->
+ %% Use os_mon*/priv/bin/Arch/Name
+ ArchPath =
+ filename:join(
+ [PrivDir,"bin",erlang:system_info(system_architecture),Name]),
+ erlang:open_port({spawn, "\""++ArchPath++"\""}, Opts)
+ end.
+
+
%%%-----------------------------------------------------------------
%%% Application callbacks
%%%-----------------------------------------------------------------
diff --git a/lib/os_mon/src/os_mon_mib.erl b/lib/os_mon/src/os_mon_mib.erl
index a4ce274a16..ea17f928cc 100644
--- a/lib/os_mon/src/os_mon_mib.erl
+++ b/lib/os_mon/src/os_mon_mib.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
@@ -65,11 +65,11 @@
%% Shadow argument macros
-define(loadShadowArgs,
{loadTable, string, record_info(fields, loadTable), 5000,
- {os_mon_mib, update_load_table}}).
+ fun os_mon_mib:update_load_table/0}).
-define(diskShadowArgs,
{diskTable, {integer, integer}, record_info(fields, diskTable), 5000,
- {os_mon_mib, update_disk_table}}).
+ fun os_mon_mib:update_disk_table/0}).
%% Misc
-record(diskAlloc, {diskDescr, diskId}).
diff --git a/lib/os_mon/src/os_mon_sysinfo.erl b/lib/os_mon/src/os_mon_sysinfo.erl
index 5d12bd95d1..fb732d1e3a 100644
--- a/lib/os_mon/src/os_mon_sysinfo.erl
+++ b/lib/os_mon/src/os_mon_sysinfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,9 +108,7 @@ code_change(_OldVsn, State, _Extra) ->
%%----------------------------------------------------------------------
start_portprogram() ->
- Command =
- filename:join([code:priv_dir(os_mon),"bin","win32sysinfo.exe"]),
- Port = open_port({spawn,Command}, [{packet,1}]),
+ Port = os_mon:open_port("win32sysinfo.exe", [{packet,1}]),
receive
{Port, {data, [?OK]}} ->
Port;
diff --git a/lib/os_mon/test/Makefile b/lib/os_mon/test/Makefile
index a240640f92..954cfef7fb 100644
--- a/lib/os_mon/test/Makefile
+++ b/lib/os_mon/test/Makefile
@@ -84,9 +84,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) os_mon.spec os_mon.cover $(EMAKEFILE) $(SOURCE) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) os_mon.spec os_mon.cover $(EMAKEFILE) $(SOURCE) "$(RELSYSDIR)"
-## tar chf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+## tar chf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/os_mon/test/os_mon_mib_SUITE.erl b/lib/os_mon/test/os_mon_mib_SUITE.erl
index 4bd256a3f7..a137efc441 100644
--- a/lib/os_mon/test/os_mon_mib_SUITE.erl
+++ b/lib/os_mon/test/os_mon_mib_SUITE.erl
@@ -718,7 +718,7 @@ del_dir(Dir) ->
{ok, Files} = file:list_dir(Dir),
FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end,
Files),
- lists:foreach({file, delete}, FullPathFiles),
+ lists:foreach(fun file:delete/1, FullPathFiles),
file:del_dir(Dir).
%%---------------------------------------------------------------------
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index f000e24a8f..b92bdf3c1a 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.2.7
+OS_MON_VSN = 2.2.9
diff --git a/lib/otp_mibs/doc/src/Makefile b/lib/otp_mibs/doc/src/Makefile
index bd2810034b..16a5bb39b4 100644
--- a/lib/otp_mibs/doc/src/Makefile
+++ b/lib/otp_mibs/doc/src/Makefile
@@ -102,14 +102,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/otp_mibs/doc/src/make.dep b/lib/otp_mibs/doc/src/make.dep
deleted file mode 100644
index 2885155315..0000000000
--- a/lib/otp_mibs/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex introduction.tex mibs.tex otp_mib.tex \
- part.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/otp_mibs/doc/src/notes.xml b/lib/otp_mibs/doc/src/notes.xml
index 94c1dd4228..3d3a1272a4 100644
--- a/lib/otp_mibs/doc/src/notes.xml
+++ b/lib/otp_mibs/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,26 @@
<p>This document describes the changes made to the OTP_Mibs
application.</p>
+<section><title>Otp_Mibs 1.0.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Otp_Mibs 1.0.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/otp_mibs/mibs/Makefile b/lib/otp_mibs/mibs/Makefile
index 5e59824d3f..7ef8480b3e 100644
--- a/lib/otp_mibs/mibs/Makefile
+++ b/lib/otp_mibs/mibs/Makefile
@@ -76,13 +76,13 @@ v1/%.mib.v1: %.mib
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/mibs
- $(INSTALL_DIR) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DATA) $(MIB_FILES) $(FUNCS_FILES) $(RELSYSDIR)/mibs
- $(INSTALL_DATA) $(V1_MIB_FILES) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_TARGETS) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/priv/mibs
- $(INSTALL_DATA) $(BIN_TARGETS) $(RELSYSDIR)/priv/mibs
+ $(INSTALL_DIR) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DIR) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DATA) $(MIB_FILES) $(FUNCS_FILES) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DATA) $(V1_MIB_FILES) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_TARGETS) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/mibs"
+ $(INSTALL_DATA) $(BIN_TARGETS) "$(RELSYSDIR)/priv/mibs"
release_docs_spec:
diff --git a/lib/otp_mibs/src/Makefile b/lib/otp_mibs/src/Makefile
index 833a439adb..c9c40fec3a 100644
--- a/lib/otp_mibs/src/Makefile
+++ b/lib/otp_mibs/src/Makefile
@@ -95,10 +95,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGETS) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGETS) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/otp_mibs/src/otp_mib.erl b/lib/otp_mibs/src/otp_mib.erl
index e8b0e51b91..619104007c 100644
--- a/lib/otp_mibs/src/otp_mib.erl
+++ b/lib/otp_mibs/src/otp_mib.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
@@ -48,11 +48,11 @@
%% Shadow argument macros
-define(erlNodeShadowArgs,
{erlNodeTable, integer, record_info(fields, erlNodeTable), 5000,
- {otp_mib, update_erl_node_table}}).
+ fun otp_mib:update_erl_node_table/0}).
-define(applShadowArgs,
{applTable, {integer, integer}, record_info(fields, applTable),
- 5000, {otp_mib, update_appl_table}}).
+ 5000, fun otp_mib:update_appl_table/0}).
%% Misc
-record(erlNodeAlloc, {nodeName, nodeId}).
diff --git a/lib/otp_mibs/vsn.mk b/lib/otp_mibs/vsn.mk
index c2fa7c9474..f070288032 100644
--- a/lib/otp_mibs/vsn.mk
+++ b/lib/otp_mibs/vsn.mk
@@ -1,4 +1,4 @@
-OTP_MIBS_VSN = 1.0.6
+OTP_MIBS_VSN = 1.0.7
# Note: The branch 'otp_mibs' is defunct as of otp_mibs-1.0.4 and
# should NOT be used again.
diff --git a/lib/parsetools/doc/src/Makefile b/lib/parsetools/doc/src/Makefile
index 6e693e0cf0..464ea66af0 100644
--- a/lib/parsetools/doc/src/Makefile
+++ b/lib/parsetools/doc/src/Makefile
@@ -105,14 +105,14 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/parsetools/doc/src/make.dep b/lib/parsetools/doc/src/make.dep
deleted file mode 100644
index 3a09ecdedd..0000000000
--- a/lib/parsetools/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex leex.tex ref_man.tex yecc.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-ref_man.tex: ../../../../system/doc/definitions/term.defs
-
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 0c611db1ec..ac29cbb893 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.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>
@@ -30,6 +30,26 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.0.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.0.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl
index f638529aa4..3672394fc5 100644
--- a/lib/parsetools/include/yeccpre.hrl
+++ b/lib/parsetools/include/yeccpre.hrl
@@ -28,10 +28,11 @@ parse(Tokens) ->
-spec parse_and_scan({function() | {atom(), atom()}, [_]}
| {atom(), atom(), [_]}) -> yecc_ret().
-parse_and_scan({F, A}) -> % Fun or {M, F}
+parse_and_scan({F, A}) ->
yeccpars0([], {{F, A}, no_line}, 0, [], []);
parse_and_scan({M, F, A}) ->
- yeccpars0([], {{{M, F}, A}, no_line}, 0, [], []).
+ Arity = length(A),
+ yeccpars0([], {{fun M:F/Arity, A}, no_line}, 0, [], []).
-spec format_error(any()) -> [char() | list()].
format_error(Message) ->
diff --git a/lib/parsetools/src/Makefile b/lib/parsetools/src/Makefile
index 89e079e411..e228ee88ef 100644
--- a/lib/parsetools/src/Makefile
+++ b/lib/parsetools/src/Makefile
@@ -89,12 +89,12 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/parsetools/test/Makefile b/lib/parsetools/test/Makefile
index 624c4e6975..430386bfe5 100644
--- a/lib/parsetools/test/Makefile
+++ b/lib/parsetools/test/Makefile
@@ -70,9 +70,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) parsetools.spec parsetools.cover $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- # @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) parsetools.spec parsetools.cover $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ # @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index a5f66b48e9..3d26adf1be 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -1197,7 +1197,7 @@ yeccpre(Config) when is_list(Config) ->
catch error: error ->
ok
end,
- try parse_and_scan({{yecc_test, scan}, [exit]})
+ try parse_and_scan({fun yecc_test:scan/1, [exit]})
catch exit: exit ->
ok
end,
@@ -1650,10 +1650,11 @@ yeccpre_v1_2() ->
parse(Tokens) ->
yeccpars0(Tokens, false).
-parse_and_scan({F, A}) -> % Fun or {M, F}
+parse_and_scan({F, A}) ->
yeccpars0([], {F, A});
parse_and_scan({M, F, A}) ->
- yeccpars0([], {{M, F}, A}).
+ Arity = length(A),
+ yeccpars0([], {fun M:F/Arity, A}).
format_error(Message) ->
case io_lib:deep_char_list(Message) of
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 093523f0e7..e2594564cb 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.0.6
+PARSETOOLS_VSN = 2.0.7
diff --git a/lib/percept/doc/src/Makefile b/lib/percept/doc/src/Makefile
index f0d43c5a01..e749103783 100644
--- a/lib/percept/doc/src/Makefile
+++ b/lib/percept/doc/src/Makefile
@@ -175,15 +175,15 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTML_EXAMPLE_FILES) $(HTML_STYLESHEET_FILES) \
$(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/percept/doc/src/make.dep b/lib/percept/doc/src/make.dep
deleted file mode 100644
index df16cffd4f..0000000000
--- a/lib/percept/doc/src/make.dep
+++ /dev/null
@@ -1,34 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex egd.tex egd_ug.tex part.tex percept.tex \
- percept_profile.tex percept_ug.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-egd_ug.tex: img.erl img_esi.erl
-
-percept_ug.tex: sorter.erl
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: img_esi_result.ps test1.ps test2.ps test3.ps \
- test4.ps
-
-book.dvi: percept_compare.ps percept_overview.ps percept_processes.ps \
- percept_processinfo.ps
-
diff --git a/lib/percept/doc/src/notes.xml b/lib/percept/doc/src/notes.xml
index 95c2bbda56..1ac1a5ab62 100644
--- a/lib/percept/doc/src/notes.xml
+++ b/lib/percept/doc/src/notes.xml
@@ -32,6 +32,21 @@
</header>
<p>This document describes the changes made to the Percept application.</p>
+<section><title>Percept 0.8.6.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Miscellaneous documentation build updates</p>
+ <p>
+ Own Id: OTP-9813</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Percept 0.8.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/percept/doc/src/part_notes.xml b/lib/percept/doc/src/part_notes.xml
index 4965e67640..4965e67640 100755..100644
--- a/lib/percept/doc/src/part_notes.xml
+++ b/lib/percept/doc/src/part_notes.xml
diff --git a/lib/percept/priv/Makefile b/lib/percept/priv/Makefile
index 7c37ccd98b..4d7942c49c 100644
--- a/lib/percept/priv/Makefile
+++ b/lib/percept/priv/Makefile
@@ -77,20 +77,20 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
# Finished
- $(INSTALL_DIR) $(RELSYSDIR)/priv/logs
- $(INSTALL_DIR) $(RELSYSDIR)/priv/server_root
- $(INSTALL_DIR) $(RELSYSDIR)/priv/server_root/htdocs
- $(INSTALL_DATA) $(HTDOCS_FILES) $(RELSYSDIR)/priv/server_root/htdocs
- $(INSTALL_DIR) $(RELSYSDIR)/priv/server_root/conf
- $(INSTALL_DATA) $(CONF_FILES) $(RELSYSDIR)/priv/server_root/conf
- $(INSTALL_DIR) $(RELSYSDIR)/priv/server_root/scripts
- $(INSTALL_DATA) $(SCRIPT_FILES) $(RELSYSDIR)/priv/server_root/scripts
- $(INSTALL_DIR) $(RELSYSDIR)/priv/server_root/css
- $(INSTALL_DATA) $(CSS_FILES) $(RELSYSDIR)/priv/server_root/css
- $(INSTALL_DIR) $(RELSYSDIR)/priv/server_root/images
- $(INSTALL_DATA) $(IMAGE_FILES) $(RELSYSDIR)/priv/server_root/images
- $(INSTALL_DIR) $(RELSYSDIR)/priv/fonts
- $(INSTALL_DATA) $(FONT_FILES) $(RELSYSDIR)/priv/fonts
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/logs"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/server_root"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/server_root/htdocs"
+ $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv/server_root/htdocs"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/server_root/conf"
+ $(INSTALL_DATA) $(CONF_FILES) "$(RELSYSDIR)/priv/server_root/conf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/server_root/scripts"
+ $(INSTALL_DATA) $(SCRIPT_FILES) "$(RELSYSDIR)/priv/server_root/scripts"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/server_root/css"
+ $(INSTALL_DATA) $(CSS_FILES) "$(RELSYSDIR)/priv/server_root/css"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/server_root/images"
+ $(INSTALL_DATA) $(IMAGE_FILES) "$(RELSYSDIR)/priv/server_root/images"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/fonts"
+ $(INSTALL_DATA) $(FONT_FILES) "$(RELSYSDIR)/priv/fonts"
release_docs_spec:
diff --git a/lib/percept/src/Makefile b/lib/percept/src/Makefile
index 5dfc72575a..4b9a10cdb8 100644
--- a/lib/percept/src/Makefile
+++ b/lib/percept/src/Makefile
@@ -93,12 +93,12 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
-# $(INSTALL_DIR) $(RELSYSDIR)/include
-# $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+# $(INSTALL_DIR) "$(RELSYSDIR)/include"
+# $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/percept/test/Makefile b/lib/percept/test/Makefile
index d927386d1c..ee70966b01 100644
--- a/lib/percept/test/Makefile
+++ b/lib/percept/test/Makefile
@@ -81,10 +81,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) percept.spec percept.cover $(EMAKEFILE) $(SOURCE) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) percept.spec percept.cover $(EMAKEFILE) $(SOURCE) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/percept/test/percept_SUITE_data/ipc-dist.dat b/lib/percept/test/percept_SUITE_data/ipc-dist.dat
index 14ab6c0c5d..14ab6c0c5d 100755..100644
--- a/lib/percept/test/percept_SUITE_data/ipc-dist.dat
+++ b/lib/percept/test/percept_SUITE_data/ipc-dist.dat
Binary files differ
diff --git a/lib/percept/vsn.mk b/lib/percept/vsn.mk
index 3b4d9bbb64..9267a41055 100644
--- a/lib/percept/vsn.mk
+++ b/lib/percept/vsn.mk
@@ -1 +1 @@
-PERCEPT_VSN = 0.8.6
+PERCEPT_VSN = 0.8.6.1
diff --git a/lib/pman/doc/src/Makefile b/lib/pman/doc/src/Makefile
index 4e116cb23e..ec759091ab 100644
--- a/lib/pman/doc/src/Makefile
+++ b/lib/pman/doc/src/Makefile
@@ -103,14 +103,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/pman/doc/src/make.dep b/lib/pman/doc/src/make.dep
deleted file mode 100644
index 2f6a8a06cd..0000000000
--- a/lib/pman/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex pman.tex pman_chapter.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: main_window.ps options.ps trace.ps
-
diff --git a/lib/pman/doc/src/notes.xml b/lib/pman/doc/src/notes.xml
index 27e3b5e5fe..778f960004 100644
--- a/lib/pman/doc/src/notes.xml
+++ b/lib/pman/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,41 @@
</header>
<p>This document describes the changes made to the Pman application.</p>
+<section><title>Pman 2.7.1.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The GS applications is now deprecated and will be
+ removed in the R16 release. The following GS-based
+ applications have been superseded by the Observer
+ application and will removed in R16: Appmon, Pman,
+ Tv.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9907</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Pman 2.7.1.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Miscellaneous documentation build updates</p>
+ <p>
+ Own Id: OTP-9813</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Pman 2.7.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/pman/doc/src/pman.xml b/lib/pman/doc/src/pman.xml
index 84d5a5772a..48eaf9167c 100644
--- a/lib/pman/doc/src/pman.xml
+++ b/lib/pman/doc/src/pman.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,12 @@
<module>pman</module>
<modulesummary>A graphical process manager.</modulesummary>
<description>
+ <warning>
+ <p>
+ The Pman application has been superseded by the Observer application.
+ Pman will be removed in R16.
+ </p>
+ </warning>
<p>A graphical tool used to inspect the Erlang processes executing either
locally or on remote nodes. It is also possible to trace events in
the individual processes.</p>
diff --git a/lib/pman/doc/src/pman_chapter.xml b/lib/pman/doc/src/pman_chapter.xml
index 141b488415..ce4adbec45 100644
--- a/lib/pman/doc/src/pman_chapter.xml
+++ b/lib/pman/doc/src/pman_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,12 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ The Pman application has been superseded by the Observer application.
+ Pman will be removed in R16.
+ </p>
+ </warning>
<p>The process manager Pman is a tool for viewing processes executing
locally or on remote nodes. Its main purpose is to locate
erroneous code by inspecting the state of the processes and by tracing
diff --git a/lib/pman/priv/Makefile b/lib/pman/priv/Makefile
index 43f9d45d94..a89278fd3a 100644
--- a/lib/pman/priv/Makefile
+++ b/lib/pman/priv/Makefile
@@ -50,8 +50,8 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(TOOLBAR_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(TOOLBAR_FILES) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/pman/src/Makefile b/lib/pman/src/Makefile
index e573e57220..2cd1c64c49 100644
--- a/lib/pman/src/Makefile
+++ b/lib/pman/src/Makefile
@@ -103,10 +103,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(TOOLBOX_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(TARGET_TOOLBOX_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(TOOLBOX_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(TARGET_TOOLBOX_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/pman/src/pman_buf_converter.erl b/lib/pman/src/pman_buf_converter.erl
index b6f560411c..c8b3fe37aa 100644
--- a/lib/pman/src/pman_buf_converter.erl
+++ b/lib/pman/src/pman_buf_converter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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 @@
%%----------------------------------------------------------------------
-module(pman_buf_converter).
+-compile([{nowarn_deprecated_function,{gs,start,0}}]).
%%-compile(export_all).
-export([init/2]).
diff --git a/lib/pman/src/pman_buf_printer.erl b/lib/pman/src/pman_buf_printer.erl
index 74e935171a..3284c57559 100644
--- a/lib/pman/src/pman_buf_printer.erl
+++ b/lib/pman/src/pman_buf_printer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,8 @@
%%
-module(pman_buf_printer).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
%%-compile(export_all).
-export([init/2]).
diff --git a/lib/pman/src/pman_main.erl b/lib/pman/src/pman_main.erl
index b68da1d2c3..2f51284293 100644
--- a/lib/pman/src/pman_main.erl
+++ b/lib/pman/src/pman_main.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% %CopyrightEnd%
%%
-module(pman_main).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%% Main process and window
diff --git a/lib/pman/src/pman_module_info.erl b/lib/pman/src/pman_module_info.erl
index cfd711a6e1..944fd4a462 100644
--- a/lib/pman/src/pman_module_info.erl
+++ b/lib/pman/src/pman_module_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% %CopyrightEnd%
%%
-module(pman_module_info).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% Window with module information (View->Module Info...)
diff --git a/lib/pman/src/pman_shell.erl b/lib/pman/src/pman_shell.erl
index 0b13890460..2d2b8ce000 100644
--- a/lib/pman/src/pman_shell.erl
+++ b/lib/pman/src/pman_shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,10 @@
%% ---------------------------------------------------------------
-module(pman_shell).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% ---------------------------------------------------------------
%% The user interface exports
diff --git a/lib/pman/src/pman_tool.erl b/lib/pman/src/pman_tool.erl
index 1d33fb9764..36382745af 100644
--- a/lib/pman/src/pman_tool.erl
+++ b/lib/pman/src/pman_tool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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%
%%
-module(pman_tool).
+-compile([{nowarn_deprecated_function,{gs,read,2}}]).
%% Listbox selection window
diff --git a/lib/pman/src/pman_win.erl b/lib/pman/src/pman_win.erl
index 52d5a237cf..350bc2dd7f 100644
--- a/lib/pman/src/pman_win.erl
+++ b/lib/pman/src/pman_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,16 @@
%% ------------------------------------------------------------
-module(pman_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% ---------------------------------------------------------------
%% The user interface exports
diff --git a/lib/pman/vsn.mk b/lib/pman/vsn.mk
index d190164053..13dce1a7a5 100644
--- a/lib/pman/vsn.mk
+++ b/lib/pman/vsn.mk
@@ -1 +1 @@
-PMAN_VSN = 2.7.1
+PMAN_VSN = 2.7.1.2
diff --git a/lib/public_key/.gitignore b/lib/public_key/.gitignore
new file mode 100644
index 0000000000..d30fe62c9d
--- /dev/null
+++ b/lib/public_key/.gitignore
@@ -0,0 +1,7 @@
+# public_key
+
+asn1/*.asn1db
+asn1/*.erl
+asn1/*.hrl
+include/OTP-PUB-KEY.hrl
+include/PKCS-FRAME.hrl
diff --git a/lib/public_key/asn1/DSS.asn1 b/lib/public_key/asn1/DSS.asn1
index 77aca3808b..77aca3808b 100755..100644
--- a/lib/public_key/asn1/DSS.asn1
+++ b/lib/public_key/asn1/DSS.asn1
diff --git a/lib/public_key/asn1/Makefile b/lib/public_key/asn1/Makefile
index c4f8d65aa7..d48f48a5d5 100644
--- a/lib/public_key/asn1/Makefile
+++ b/lib/public_key/asn1/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
@@ -38,12 +38,12 @@ RELSYSDIR = $(RELEASE_PATH)/lib/public_key-$(VSN)
.SUFFIXES: .asn1
.PRECIOUS: %.erl
-ASN_TOP = OTP-PUB-KEY
+ASN_TOP = OTP-PUB-KEY PKCS-FRAME
ASN_MODULES = PKIX1Explicit88 PKIX1Implicit88 PKIX1Algorithms88 \
- PKIXAttributeCertificate PKCS-1 PKCS-3 OTP-PKIX
+ PKIXAttributeCertificate PKCS-1 PKCS-3 PKCS-8 PKCS5v2-0 OTP-PKIX
ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-ASN_ERLS = $(ASN_TOP).erl
-ASN_HRLS = $(ASN_TOP).hrl
+ASN_ERLS = $(ASN_TOP:%=%.erl)
+ASN_HRLS = $(ASN_TOP:%=%.hrl)
ASN_CONFIGS = OTP-PUB-KEY.asn1config
ASN_DBS = $(ASN_MODULES:%=%.asn1db) OTP-PUB-KEY.asn1db
ASN_TABLES = $(ASN_MODULES:%=%.table)
@@ -82,8 +82,8 @@ docs:
%.erl %.hrl: %.set.asn
erlc $(ASN_FLAGS) $<
-$(HRL_FILES): $(ASN_HRLS)
- cp -p $(ASN_HRLS) $(INCLUDE)
+$(INCLUDE)/%.hrl: %.hrl
+ cp -p $< $@
# ----------------------------------------------------
# Release Target
@@ -91,13 +91,13 @@ $(HRL_FILES): $(ASN_HRLS)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/asn1
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/asn1"
$(INSTALL_DATA) $(ASN_ASNS) $(ASN_ERLS) $(ASN_HRLS) $(ASN_CONFIGS) \
- $(GEN_ERLS) $(RELSYSDIR)/asn1
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(GEN_ERLS) "$(RELSYSDIR)/asn1"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
@@ -113,3 +113,8 @@ OTP-PUB-KEY.asn1db: PKIX1Algorithms88.asn1 \
PKCS-1.asn1\
PKCS-3.asn1\
OTP-PKIX.asn1
+
+$(EBIN)/PKCS-FRAME.beam: PKCS-FRAME.erl PKCS-FRAME.hrl
+PKCS-FRAME.erl PKCS-FRAME.hrl: PKCS-FRAME.asn1db
+PKCS-FRAME.asn1db: PKCS-8.asn1\
+ PKCS5v2-0.asn1 \ No newline at end of file
diff --git a/lib/public_key/asn1/OTP-PKIX.asn1 b/lib/public_key/asn1/OTP-PKIX.asn1
index ad704191a9..e94a77a3e7 100644
--- a/lib/public_key/asn1/OTP-PKIX.asn1
+++ b/lib/public_key/asn1/OTP-PKIX.asn1
@@ -91,7 +91,7 @@ IMPORTS
id-ce-certificateIssuer, CertificateIssuer,
id-ce-holdInstructionCode, HoldInstructionCode,
id-ce-invalidityDate, InvalidityDate
-
+
FROM PKIX1Implicit88 { iso(1) identified-organization(3) dod(6)
internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
id-pkix1-implicit(19) }
@@ -114,8 +114,20 @@ IMPORTS
id-ecPublicKey, EcpkParameters, ECPoint
FROM PKIX1Algorithms88 { iso(1) identified-organization(3) dod(6)
internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
- id-mod-pkix1-algorithms(17) };
-
+ id-mod-pkix1-algorithms(17) }
+
+ md2WithRSAEncryption,
+ md5WithRSAEncryption,
+ sha1WithRSAEncryption,
+ sha256WithRSAEncryption,
+ sha384WithRSAEncryption,
+ sha512WithRSAEncryption
+
+ FROM PKCS-1 {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)
+ modules(0) pkcs-1(1)
+ };
+
--
-- Certificate
--
@@ -213,7 +225,17 @@ dnQualifier ATTRIBUTE-TYPE-AND-VALUE-CLASS ::= {
countryName ATTRIBUTE-TYPE-AND-VALUE-CLASS ::= {
ID id-at-countryName
- TYPE X520countryName }
+ TYPE X520countryName } -- this is currently not used when decoding
+ -- The decoding and mapping between ID and Type is done in the code
+ -- in module publickey_cert_records via the function attribute_type
+ -- To be more forgiving and compatible with other SSL implementations
+ -- regarding how to handle and sometimes accept incorrect certificates
+ -- we define and use the type below instead of X520countryName
+
+ OTP-X520countryname ::= CHOICE {
+ printableString PrintableString (SIZE (2)),
+ utf8String UTF8String (SIZE (2))
+}
serialNumber ATTRIBUTE-TYPE-AND-VALUE-CLASS ::= {
ID id-at-serialNumber
@@ -295,6 +317,9 @@ PublicKeyAlgorithm ::= SEQUENCE {
SupportedSignatureAlgorithms SIGNATURE-ALGORITHM-CLASS ::= {
dsa-with-sha1 | md2-with-rsa-encryption |
md5-with-rsa-encryption | sha1-with-rsa-encryption |
+ sha256-with-rsa-encryption |
+ sha384-with-rsa-encryption |
+ sha512-with-rsa-encryption |
ecdsa-with-sha1 }
SupportedPublicKeyAlgorithms PUBLIC-KEY-ALGORITHM-CLASS ::= {
@@ -340,6 +365,18 @@ SupportedPublicKeyAlgorithms PUBLIC-KEY-ALGORITHM-CLASS ::= {
ID sha1WithRSAEncryption
TYPE NULL }
+ sha256-with-rsa-encryption SIGNATURE-ALGORITHM-CLASS ::= {
+ ID sha256WithRSAEncryption
+ TYPE NULL }
+
+ sha384-with-rsa-encryption SIGNATURE-ALGORITHM-CLASS ::= {
+ ID sha384WithRSAEncryption
+ TYPE NULL }
+
+ sha512-with-rsa-encryption SIGNATURE-ALGORITHM-CLASS ::= {
+ ID sha512WithRSAEncryption
+ TYPE NULL }
+
-- Certificate.signature
-- See PKCS #1 (RFC 2313). XXX
diff --git a/lib/public_key/asn1/PKCS-1.asn1 b/lib/public_key/asn1/PKCS-1.asn1
index b06f5efa9d..c83289e779 100755..100644
--- a/lib/public_key/asn1/PKCS-1.asn1
+++ b/lib/public_key/asn1/PKCS-1.asn1
@@ -33,6 +33,9 @@ sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
+sha224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 14 }
+
+
id-sha1 OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) oiw(14) secsig(3)
diff --git a/lib/public_key/asn1/PKCS-8.asn1 b/lib/public_key/asn1/PKCS-8.asn1
new file mode 100644
index 0000000000..8412345b68
--- /dev/null
+++ b/lib/public_key/asn1/PKCS-8.asn1
@@ -0,0 +1,143 @@
+PKCS-8 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-8(8)
+ modules(1) pkcs-8(1)}
+
+-- $Revision: 1.5 $
+
+-- This module has been checked for conformance with the ASN.1
+-- standard by the OSS ASN.1 Tools
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+-- EXPORTS All --
+-- All types and values defined in this module is exported for use in other
+-- ASN.1 modules.
+
+--IMPORTS
+
+-- informationFramework
+-- FROM UsefulDefinitions {joint-iso-itu-t(2) ds(5) module(1)
+-- usefulDefinitions(0) 3}
+
+--Attribute
+-- FROM InformationFramework informationFramework
+-- FROM InformationFramework;
+
+-- This import is really unnecessary since ALGORITHM-IDENTIFIER is defined as a
+-- TYPE-IDENTIFIER
+-- Renome this import and replace all occurences of ALGORITHM-IDENTIFIER with
+-- TYPE-IDENTIFIER as a workaround for weaknesses in the ASN.1 compiler
+--AlgorithmIdentifier, ALGORITHM-IDENTIFIER
+-- FROM PKCS5v2-0 {iso(1) member-body(2) us(840) rsadsi(113549)
+-- pkcs(1) pkcs-5(5) modules(16) pkcs-5(1)};
+
+-- Inlined from PKCS5v2-0 since it is the only thing imported from that module
+-- AlgorithmIdentifier { ALGORITHM-IDENTIFIER:InfoObjectSet } ::=
+AlgorithmIdentifier { TYPE-IDENTIFIER:InfoObjectSet } ::=
+SEQUENCE {
+-- algorithm ALGORITHM-IDENTIFIER.&id({InfoObjectSet}),
+ algorithm TYPE-IDENTIFIER.&id({InfoObjectSet}),
+-- parameters ALGORITHM-IDENTIFIER.&Type({InfoObjectSet}
+ parameters TYPE-IDENTIFIER.&Type({InfoObjectSet}
+ {@algorithm}) OPTIONAL }
+
+-- Private-key information syntax
+
+PrivateKeyInfo ::= SEQUENCE {
+ version Version,
+-- privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+ privateKeyAlgorithm AlgorithmIdentifier {{...}},
+ privateKey PrivateKey,
+ attributes [0] Attributes OPTIONAL }
+
+Version ::= INTEGER {v1(0)} (v1,...)
+
+PrivateKey ::= OCTET STRING
+
+-- Attributes ::= SET OF PKAttribute
+Attributes ::= SET OF PKAttribute {{...}}
+
+-- Encrypted private-key information syntax
+
+EncryptedPrivateKeyInfo ::= SEQUENCE {
+-- encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+ encryptionAlgorithm AlgorithmIdentifier {{...}},
+ encryptedData EncryptedData
+}
+
+EncryptedData ::= OCTET STRING
+
+-- PrivateKeyAlgorithms ALGORITHM-IDENTIFIER ::= {
+PrivateKeyAlgorithms TYPE-IDENTIFIER ::= {
+ ... -- For local profiles
+}
+
+-- KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+KeyEncryptionAlgorithms TYPE-IDENTIFIER ::= {
+ ... -- For local profiles
+}
+
+-- From InformationFramework
+PKAttribute{ATTRIBUTE:SupportedAttributes} ::= SEQUENCE {
+ type ATTRIBUTE.&id({SupportedAttributes}),
+ values
+ SET SIZE (0..MAX) OF ATTRIBUTE.&Type({SupportedAttributes}{@type}),
+ valuesWithContext
+ SET SIZE (1..MAX) OF
+ SEQUENCE {value ATTRIBUTE.&Type({SupportedAttributes}{@type}),
+ contextList SET SIZE (1..MAX) OF Context} OPTIONAL
+}
+
+Context ::= SEQUENCE {
+ contextType CONTEXT.&id({SupportedContexts}),
+ contextValues
+ SET SIZE (1..MAX) OF CONTEXT.&Type({SupportedContexts}{@contextType}),
+ fallback BOOLEAN DEFAULT FALSE
+}
+-- Definition of the following information object set is deferred, perhaps to standardized
+-- profiles or to protocol implementation conformance statements. The set is required to
+-- specify a table constraint on the context specifications
+SupportedContexts CONTEXT ::=
+ {...}
+
+
+CONTEXT ::= CLASS {
+ &Type ,
+ &DefaultValue OPTIONAL,
+ &Assertion OPTIONAL,
+ &absentMatch BOOLEAN DEFAULT TRUE,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+
+-- ATTRIBUTE information object class specification
+ATTRIBUTE ::= CLASS {
+ &derivation ATTRIBUTE OPTIONAL,
+ &Type OPTIONAL, -- either &Type or &derivation required
+ &equality-match MATCHING-RULE OPTIONAL,
+ &ordering-match MATCHING-RULE OPTIONAL,
+ &substrings-match MATCHING-RULE OPTIONAL,
+ &single-valued BOOLEAN DEFAULT FALSE,
+ &collective BOOLEAN DEFAULT FALSE,
+ &dummy BOOLEAN DEFAULT FALSE,
+ -- operational extensions
+ &no-user-modification BOOLEAN DEFAULT FALSE,
+ &usage AttributeUsage DEFAULT userApplications,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+
+-- MATCHING-RULE information object class specification
+MATCHING-RULE ::= CLASS {
+ &ParentMatchingRules MATCHING-RULE OPTIONAL,
+ &AssertionType OPTIONAL,
+ &uniqueMatchIndicator ATTRIBUTE OPTIONAL,
+ &id OBJECT IDENTIFIER UNIQUE
+}
+
+AttributeUsage ::= ENUMERATED {
+ userApplications(0), directoryOperation(1), distributedOperation(2),
+ dSAOperation(3)}
+
+END
+
+
diff --git a/lib/public_key/asn1/PKCS-FRAME.set.asn b/lib/public_key/asn1/PKCS-FRAME.set.asn
new file mode 100644
index 0000000000..69b6727bef
--- /dev/null
+++ b/lib/public_key/asn1/PKCS-FRAME.set.asn
@@ -0,0 +1,2 @@
+PKCS-8.asn1
+PKCS5v2-0.asn1
diff --git a/lib/public_key/asn1/PKCS5v2-0.asn1 b/lib/public_key/asn1/PKCS5v2-0.asn1
new file mode 100644
index 0000000000..fe7e16c7fa
--- /dev/null
+++ b/lib/public_key/asn1/PKCS5v2-0.asn1
@@ -0,0 +1,142 @@
+-- PKCS #5 v2.0 ASN.1 Module
+-- Revised March 25, 1999
+
+-- This module has been checked for conformance with the
+-- ASN.1 standard by the OSS ASN.1 Tools
+
+PKCS5v2-0 {iso(1) member-body(2) us(840) rsadsi(113549)
+ pkcs(1) pkcs-5(5) modules(16) pkcs5v2-0(1)}
+
+DEFINITIONS ::= BEGIN
+
+-- Basic object identifiers
+
+rsadsi OBJECT IDENTIFIER ::=
+ {iso(1) member-body(2) us(840) 113549}
+pkcs OBJECT IDENTIFIER ::= {rsadsi 1}
+pkcs-5 OBJECT IDENTIFIER ::= {pkcs 5}
+
+-- Basic types and classes
+
+AlgorithmIdentifier { TYPE-IDENTIFIER:InfoObjectSet } ::=
+SEQUENCE {
+ algorithm TYPE-IDENTIFIER.&id({InfoObjectSet}),
+ parameters TYPE-IDENTIFIER.&Type({InfoObjectSet}
+ {@algorithm}) OPTIONAL }
+
+--ALGORITHM-IDENTIFIER ::= TYPE-IDENTIFIER
+
+-- PBKDF2
+
+-- PBKDF2Algorithms ALGORITHM-IDENTIFIER ::=
+-- { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ...}
+
+id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12}
+
+-- algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::=
+-- {algorithm id-hmacWithSHA1, parameters NULL : NULL}
+
+PBKDF2-params ::= SEQUENCE {
+ salt CHOICE {
+ specified OCTET STRING,
+ otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+ },
+ iterationCount INTEGER (1..MAX),
+ keyLength INTEGER (1..MAX) OPTIONAL,
+ prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT
+{algorithm id-hmacWithSHA1, parameters NULL : NULL}}
+-- algid-hmacWithSHA1 }
+
+PBKDF2-SaltSources TYPE-IDENTIFIER ::= { ... }
+
+PBKDF2-PRFs TYPE-IDENTIFIER ::=
+ { {NULL IDENTIFIED BY id-hmacWithSHA1}, ... }
+
+ -- PBES1
+
+PBES1Algorithms TYPE-IDENTIFIER ::=
+ { {PBEParameter IDENTIFIED BY pbeWithMD2AndDES-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithMD2AndRC2-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithMD5AndDES-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithMD5AndRC2-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithSHA1AndDES-CBC} |
+ {PBEParameter IDENTIFIED BY pbeWithSHA1AndRC2-CBC}, ...}
+
+pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1}
+pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4}
+pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3}
+pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6}
+pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10}
+pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11}
+
+PBEParameter ::= SEQUENCE {
+ salt OCTET STRING (SIZE(8)),
+ iterationCount INTEGER }
+
+-- PBES2
+
+PBES2Algorithms TYPE-IDENTIFIER ::=
+ { {PBES2-params IDENTIFIED BY id-PBES2}, ...}
+
+id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13}
+
+PBES2-params ::= SEQUENCE {
+ keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+
+PBES2-KDFs TYPE-IDENTIFIER ::=
+ { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... }
+
+PBES2-Encs TYPE-IDENTIFIER ::= { ... }
+
+-- PBMAC1
+
+PBMAC1Algorithms TYPE-IDENTIFIER ::=
+ { {PBMAC1-params IDENTIFIED BY id-PBMAC1}, ...}
+
+id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14}
+
+PBMAC1-params ::= SEQUENCE {
+ keyDerivationFunc AlgorithmIdentifier {{PBMAC1-KDFs}},
+ messageAuthScheme AlgorithmIdentifier {{PBMAC1-MACs}} }
+
+PBMAC1-KDFs TYPE-IDENTIFIER ::=
+ { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... }
+
+PBMAC1-MACs TYPE-IDENTIFIER ::= { ... }
+
+-- Supporting techniques
+
+digestAlgorithm OBJECT IDENTIFIER ::= {rsadsi 2}
+encryptionAlgorithm OBJECT IDENTIFIER ::= {rsadsi 3}
+
+SupportingAlgorithms TYPE-IDENTIFIER ::=
+ { {NULL IDENTIFIED BY id-hmacWithSHA1} |
+ {OCTET STRING (SIZE(8)) IDENTIFIED BY desCBC} |
+ {OCTET STRING (SIZE(8)) IDENTIFIED BY des-EDE3-CBC} |
+ {RC2-CBC-Parameter IDENTIFIED BY rc2CBC} |
+ {RC5-CBC-Parameters IDENTIFIED BY rc5-CBC-PAD}, ... }
+
+id-hmacWithSHA1 OBJECT IDENTIFIER ::= {digestAlgorithm 7}
+
+desCBC OBJECT IDENTIFIER ::=
+ {iso(1) identified-organization(3) oiw(14) secsig(3)
+ algorithms(2) 7} -- from OIW
+
+des-EDE3-CBC OBJECT IDENTIFIER ::= {encryptionAlgorithm 7}
+
+rc2CBC OBJECT IDENTIFIER ::= {encryptionAlgorithm 2}
+
+RC2-CBC-Parameter ::= SEQUENCE {
+ rc2ParameterVersion INTEGER OPTIONAL,
+ iv OCTET STRING (SIZE(8)) }
+
+rc5-CBC-PAD OBJECT IDENTIFIER ::= {encryptionAlgorithm 9}
+
+RC5-CBC-Parameters ::= SEQUENCE {
+ version INTEGER {v1-0(16)}, -- (v1-0),
+ rounds INTEGER (8..127),
+ blockSizeInBits INTEGER (64 | 128),
+ iv OCTET STRING OPTIONAL }
+
+END
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index afb17399da..928aa62c1b 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -29,14 +29,6 @@ VSN=$(PUBLIC_KEY_VSN)
APPLICATION=public_key
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -79,33 +71,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_PART_FILES:%.xml=%.tex) \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = public_key-$(VSN).pdf
-TOP_PS_FILE = public_key-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -118,8 +87,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -134,33 +101,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ min_head.gif \
- $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -173,41 +113,15 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
-
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
info:
diff --git a/lib/public_key/doc/src/make.dep b/lib/public_key/doc/src/make.dep
deleted file mode 100644
index 2675556f1b..0000000000
--- a/lib/public_key/doc/src/make.dep
+++ /dev/null
@@ -1,21 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex cert_records.tex introduction.tex \
- part.tex public_key.tex public_key_records.tex \
- ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index efd4a37eb9..4d3a9856eb 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -34,6 +34,57 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 0.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Changed ssh implementation to use the public_key
+ application for all public key handling. This is also a
+ first step for enabling a callback API for supplying
+ public keys and handling keys protected with password
+ phrases. </p>
+ <p>
+ Additionally the test suites where improved so that they
+ do not copy the users keys to test server directories as
+ this is a security liability. Also ipv6 and file access
+ issues found in the process has been fixed.</p>
+ <p>
+ This change also solves OTP-7677 and OTP-7235</p>
+ <p>
+ This changes also involves some updates to public_keys
+ ssh-functions.</p>
+ <p>
+ Own Id: OTP-9911</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 0.14</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ public_key, ssl and crypto now supports PKCS-8</p>
+ <p>
+ Own Id: OTP-9312</p>
+ </item>
+ <item>
+ <p>
+ The asn1 decoder/encoder now uses a runtime nif from the
+ asn1 application if it is available.</p>
+ <p>
+ Own Id: OTP-9414</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 0.13</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 9a3832c68b..5c227557f2 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -61,11 +61,14 @@
<p><code>string = [bytes()]</code></p>
<p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey'
- 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'</code></p>
+ 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'| 'PrivateKeyInfo'</code></p>
<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>
-
+ not_encrypted | cipher_info()} </code></p>
+
+ <p><code>cipher_info() = {"RC2-CBC | "DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)} |
+ 'PBES2-params'} </code></p>
+
<p><code>rsa_public_key() = #'RSAPublicKey'{}</code></p>
<p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p>
@@ -79,9 +82,9 @@
<p><code> rsa_padding() = 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
| 'rsa_no_padding'</code></p>
- <p><code> rsa_digest_type() = 'md5' | 'sha' </code></p>
+ <p><code> rsa_digest_type() = 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512' </code></p>
- <p><code> dss_digest_type() = 'none' | 'sha' </code></p>
+ <p><code> dss_digest_type() = 'sha' </code></p>
<p><code> ssh_file() = openssh_public_key | rfc4716_public_key |
known_hosts | auth_keys </code></p>
@@ -118,7 +121,8 @@
<funcs>
<func>
- <name>decrypt_private(CipherText, Key [, Options]) -> binary()</name>
+ <name>decrypt_private(CipherText, Key) -> binary()</name>
+ <name>decrypt_private(CipherText, Key, Options) -> binary()</name>
<fsummary>Public key decryption.</fsummary>
<type>
<v>CipherText = binary()</v>
@@ -131,7 +135,8 @@
</func>
<func>
- <name>decrypt_public(CipherText, Key [, Options]) - > binary()</name>
+ <name>decrypt_public(CipherText, Key) - > binary()</name>
+ <name>decrypt_public(CipherText, Key, Options) - > binary()</name>
<fsummary></fsummary>
<type>
<v>CipherText = binary()</v>
@@ -198,7 +203,8 @@
</func>
<func>
- <name>pem_entry_decode(PemEntry [, Password]) -> term()</name>
+ <name>pem_entry_decode(PemEntry) -> term()</name>
+ <name>pem_entry_decode(PemEntry, Password) -> term()</name>
<fsummary>Decodes a pem entry.</fsummary>
<type>
<v> PemEntry = pem_entry() </v>
@@ -213,7 +219,8 @@
</func>
<func>
- <name>pem_entry_encode(Asn1Type, Entity [,{CipherInfo, Password}]) -> pem_entry()</name>
+ <name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
+ <name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
<fsummary> Creates a pem entry that can be fed to pem_encode/1.</fsummary>
<type>
<v>Asn1Type = pki_asn1_type()</v>
@@ -224,7 +231,7 @@
dsa_public_key() and this function will create the appropriate
'SubjectPublicKeyInfo' entry.
</d>
- <v>CipherInfo = {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}</v>
+ <v>CipherInfo = cipher_info()</v>
<v>Password = string()</v>
</type>
<desc>
@@ -389,14 +396,14 @@
<name>sign(Msg, DigestType, Key) -> binary()</name>
<fsummary> Create digital signature.</fsummary>
<type>
- <v>Msg = binary()</v>
+ <v>Msg = binary() | {digest,binary()}</v>
<d>The msg is either the binary "plain text" data to be
- signed or in the case that digest type is <c>none</c>
- it is the hashed value of "plain text" i.e. the digest.</d>
- <v>DigestType = rsa_digest_type() | dsa_digest_type()</v>
+ signed or it is the hashed value of "plain text" i.e. the
+ digest.</d>
+ <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
<v>Key = rsa_private_key() | dsa_private_key()</v>
- </type>
- <desc>
+ </type>
+ <desc>
<p> Creates a digital signature.</p>
</desc>
</func>
@@ -446,7 +453,7 @@
<desc>
<p>Encodes a list of ssh file entries (public keys and attributes) to a binary. Possible
attributes depends on the file type, see <seealso
- marker="ssh_decode"> ssh_decode/2 </seealso></p>
+ marker="#ssh_decode-2"> ssh_decode/2 </seealso></p>
</desc>
</func>
@@ -454,11 +461,10 @@
<name>verify(Msg, DigestType, Signature, Key) -> boolean()</name>
<fsummary>Verifies a digital signature.</fsummary>
<type>
- <v>Msg = binary()</v>
+ <v>Msg = binary() | {digest,binary()}</v>
<d>The msg is either the binary "plain text" data
- or in the case that digest type is <c>none</c>
- it is the hashed value of "plain text" i.e. the digest.</d>
- <v>DigestType = rsa_digest_type() | dsa_digest_type()</v>
+ or it is the hashed value of "plain text" i.e. the digest.</d>
+ <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
<v>Signature = binary()</v>
<v>Key = rsa_public_key() | dsa_public_key()</v>
</type>
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index 5f97d80f7e..2475295974 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -23,6 +23,7 @@
-define(public_key, true).
-include("OTP-PUB-KEY.hrl").
+-include("PKCS-FRAME.hrl").
-record('SubjectPublicKeyInfoAlgorithm', {
algorithm,
diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile
index 5a24b02d2a..8a72da477f 100644
--- a/lib/public_key/src/Makefile
+++ b/lib/public_key/src/Makefile
@@ -42,10 +42,11 @@ MODULES = \
public_key \
pubkey_pem \
pubkey_ssh \
+ pubkey_pbe \
pubkey_cert \
- pubkey_cert_records
+ pubkey_cert_records
-HRL_FILES = $(INCLUDE)/public_key.hrl
+HRL_FILES = $(INCLUDE)/public_key.hrl
INTERNAL_HRL_FILES =
@@ -101,12 +102,11 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
release_docs_spec:
-
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index 5ab9642279..b76e32a2a0 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -351,7 +351,7 @@ extensions_list(Extensions) ->
extract_verify_data(OtpCert, DerCert) ->
- {0, Signature} = OtpCert#'OTPCertificate'.signature,
+ {_, Signature} = OtpCert#'OTPCertificate'.signature,
SigAlgRec = OtpCert#'OTPCertificate'.signatureAlgorithm,
SigAlg = SigAlgRec#'SignatureAlgorithm'.algorithm,
PlainText = encoded_tbs_cert(DerCert),
@@ -376,6 +376,10 @@ encoded_tbs_cert(Cert) ->
digest_type(?sha1WithRSAEncryption) ->
sha;
+digest_type(?sha256WithRSAEncryption) ->
+ sha256;
+digest_type(?sha512WithRSAEncryption) ->
+ sha512;
digest_type(?md5WithRSAEncryption) ->
md5;
digest_type(?'id-dsa-with-sha1') ->
diff --git a/lib/public_key/src/pubkey_cert_records.erl b/lib/public_key/src/pubkey_cert_records.erl
index b86d7a1f0c..33fe940ea2 100644
--- a/lib/public_key/src/pubkey_cert_records.erl
+++ b/lib/public_key/src/pubkey_cert_records.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,15 @@ transform(#'OTPTBSCertificate'{}= TBS, decode) ->
transform(#'AttributeTypeAndValue'{type=Id,value=Value0} = ATAV, Func) ->
{ok, Value} =
case attribute_type(Id) of
+ 'X520countryName'when Func == decode ->
+ %% Workaround that some certificates break the ASN-1 spec
+ %% and encode countryname as utf8
+ case 'OTP-PUB-KEY':Func('OTP-X520countryname', Value0) of
+ {ok, {utf8String, Utf8Value}} ->
+ {ok, unicode:characters_to_list(Utf8Value)};
+ {ok, {printableString, ASCCI}} ->
+ {ok, ASCCI}
+ end;
Type when is_atom(Type) -> 'OTP-PUB-KEY':Func(Type, Value0);
_UnknownType -> {ok, Value0}
end,
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
new file mode 100644
index 0000000000..43f6c42f10
--- /dev/null
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -0,0 +1,213 @@
+%%
+%% %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%
+%%
+%% Description: Implements Password Based Encryption PKCS-5, RFC-2898
+
+-module(pubkey_pbe).
+
+-include("public_key.hrl").
+
+-export([encode/4, decode/4, decrypt_parameters/1]).
+-export([pbdkdf1/4, pbdkdf2/6]).
+
+-define(DEFAULT_SHA_MAC_KEYLEN, 20).
+-define(ASN1_OCTET_STR_TAG, 4).
+-define(IV_LEN, 8).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+%%--------------------------------------------------------------------
+-spec encode(binary(), string(), string(), term()) -> binary().
+%%
+%% Description: Performs password based encoding
+%%--------------------------------------------------------------------
+encode(Data, Password, "DES-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:des_cbc_encrypt(Key, IV, Data);
+
+encode(Data, Password, "DES-EDE3-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data);
+
+encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_encrypt(Key, IV, Data).
+%%--------------------------------------------------------------------
+-spec decode(binary(), string(), string(), term()) -> binary().
+%%
+%% Description: Performs password based decoding
+%%--------------------------------------------------------------------
+decode(Data, Password,"DES-CBC"= Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:des_cbc_decrypt(Key, IV, Data);
+
+decode(Data, Password,"DES-EDE3-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data);
+
+decode(Data, Password,"RC2-CBC"= Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_decrypt(Key, IV, Data).
+
+%%--------------------------------------------------------------------
+-spec pbdkdf1(string(), iodata(), integer(), atom()) -> binary().
+%%
+%% Description: Implements password based decryption key derive function 1.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+pbdkdf1(_, _, 0, Acc) ->
+ Acc;
+pbdkdf1(Password, Salt, Count, Hash) ->
+ Result = crypto:Hash([Password, Salt]),
+ do_pbdkdf1(Result, Count-1, Result, Hash).
+
+%%--------------------------------------------------------------------
+-spec pbdkdf2(string(), iodata(), integer(), integer(), fun(), integer())
+ -> binary().
+%%
+%% Description: Implements password based decryption key derive function 2.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+pbdkdf2(Password, Salt, Count, DerivedKeyLen, Prf, PrfOutputLen)->
+ NumBlocks = ceiling(DerivedKeyLen / PrfOutputLen),
+ NumLastBlockOctets = DerivedKeyLen - (NumBlocks - 1) * PrfOutputLen ,
+ blocks(NumBlocks, NumLastBlockOctets, 1, Password, Salt,
+ Count, Prf, PrfOutputLen, <<>>).
+%%--------------------------------------------------------------------
+-spec decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{}) ->
+ {Cipher::string(), #'PBES2-params'{}}.
+%%
+%% Description: Performs ANS1-decoding of encryption parameters.
+%%--------------------------------------------------------------------
+decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{
+ algorithm = Oid, parameters = Param}) ->
+ decrypt_parameters(Oid, Param).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+password_to_key_and_iv(Password, _, #'PBES2-params'{} = Params) ->
+ {Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen, IV} =
+ key_derivation_params(Params),
+ <<Key:KeyLen/binary, _/binary>> =
+ pbdkdf2(Password, Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen),
+ {Key, IV};
+password_to_key_and_iv(Password, Cipher, Salt) ->
+ KeyLen = derived_key_length(Cipher, undefined),
+ <<Key:KeyLen/binary, _/binary>> =
+ pem_encrypt(<<>>, Password, Salt, ceiling(KeyLen div 16), <<>>, md5),
+ %% Old PEM encryption does not use standard encryption method
+ %% pbdkdf1 and uses then salt as IV
+ {Key, Salt}.
+
+pem_encrypt(_, _, _, 0, Acc, _) ->
+ Acc;
+pem_encrypt(Prev, Password, Salt, Count, Acc, Hash) ->
+ Result = crypto:Hash([Prev, Password, Salt]),
+ pem_encrypt(Result, Password, Salt, Count-1 , <<Acc/binary, Result/binary>>, Hash).
+
+do_pbdkdf1(_, 0, Acc, _) ->
+ Acc;
+do_pbdkdf1(Prev, Count, Acc, Hash) ->
+ Result = crypto:Hash(Prev),
+ do_pbdkdf1(Result, Count-1 , <<Result/binary, Acc/binary>>, Hash).
+
+iv(#'PBES2-params_encryptionScheme'{algorithm = Algo,
+ parameters = ASNIV}) when (Algo == ?'desCBC') or
+ (Algo == ?'des-EDE3-CBC') ->
+ %% This is an so called open ASN1-type that in this
+ %% case will be an octet-string of length 8
+ <<?ASN1_OCTET_STR_TAG, ?IV_LEN, IV:?IV_LEN/binary>> = ASNIV,
+ IV;
+iv(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC',
+ parameters = ASN1IV}) ->
+ {ok, #'RC2-CBC-Parameter'{iv = IV}} = 'PKCS-FRAME':decode('RC2-CBC-Parameter', ASN1IV),
+ iolist_to_binary(IV).
+
+blocks(1, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
+ <<XorSum:N/binary, _/binary>> = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
+ <<Acc/binary, XorSum/binary>>;
+blocks(NumBlocks, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
+ XorSum = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
+ blocks(NumBlocks -1, N, Index +1, Password, Salt, Count, Prf,
+ PrfLen, <<Acc/binary, XorSum/binary>>).
+
+xor_sum(Password, Salt, Count, Index, Prf, PrfLen) ->
+ Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
+ do_xor_sum(Prf, PrfLen, Result, Password, Count-1, Result).
+
+do_xor_sum(_, _, _, _, 0, Acc) ->
+ Acc;
+do_xor_sum(Prf, PrfLen, Prev, Password, Count, Acc)->
+ Result = Prf(Password, Prev, PrfLen),
+ do_xor_sum(Prf, PrfLen, Result, Password, Count-1, crypto:exor(Acc, Result)).
+
+decrypt_parameters(?'id-PBES2', DekParams) ->
+ {ok, Params} = 'PKCS-FRAME':decode('PBES2-params', DekParams),
+ {cipher(Params#'PBES2-params'.encryptionScheme), Params}.
+
+key_derivation_params(#'PBES2-params'{keyDerivationFunc = KeyDerivationFunc,
+ encryptionScheme = EncScheme}) ->
+ #'PBES2-params_keyDerivationFunc'{algorithm = ?'id-PBKDF2',
+ parameters =
+ #'PBKDF2-params'{salt = {specified, OctetSalt},
+ iterationCount = Count,
+ keyLength = Length,
+ prf = Prf}} = KeyDerivationFunc,
+ #'PBES2-params_encryptionScheme'{algorithm = Algo} = EncScheme,
+ {PseudoRandomFunction, PseudoOtputLen} = pseudo_random_function(Prf),
+ KeyLen = derived_key_length(Algo, Length),
+ {OctetSalt, Count, KeyLen,
+ PseudoRandomFunction, PseudoOtputLen, iv(EncScheme)}.
+
+%% This function currently matches a tuple that ougth to be the value
+%% ?'id-hmacWithSHA1, but we need some kind of ASN1-fix for this.
+pseudo_random_function(#'PBKDF2-params_prf'{algorithm =
+ {_,_, _,'id-hmacWithSHA1'}}) ->
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')};
+pseudo_random_function(#'PBKDF2-params_prf'{algorithm = ?'id-hmacWithSHA1'}) ->
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')}.
+
+pseudo_output_length(?'id-hmacWithSHA1') ->
+ ?DEFAULT_SHA_MAC_KEYLEN.
+
+derived_key_length(_, Len) when is_integer(Len) ->
+ Len;
+derived_key_length(Cipher,_) when (Cipher == ?'desCBC') or
+ (Cipher == "DES-CBC") ->
+ 8;
+derived_key_length(Cipher,_) when (Cipher == ?'rc2CBC') or
+ (Cipher == "RC2-CBC") ->
+ 16;
+derived_key_length(Cipher,_) when (Cipher == ?'des-EDE3-CBC') or
+ (Cipher == "DES-EDE3-CBC") ->
+ 24.
+
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'desCBC'}) ->
+ "DES-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'des-EDE3-CBC'}) ->
+ "DES-EDE3-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC'}) ->
+ "RC2-CBC".
+
+ceiling(Float) ->
+ erlang:round(Float + 0.5).
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index c26815bc04..910473d629 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -43,8 +43,6 @@
-include("public_key.hrl").
-export([encode/1, decode/1, decipher/2, cipher/3]).
-%% Backwards compatibility
--export([decode_key/2]).
-define(ENCODED_LINE_LENGTH, 64).
@@ -69,23 +67,23 @@ encode(PemEntries) ->
encode_pem_entries(PemEntries).
%%--------------------------------------------------------------------
--spec decipher({pki_asn1_type(), DerEncrypted::binary(),{Cipher :: string(),
- Salt :: binary()}},
+-spec decipher({pki_asn1_type(), DerEncrypted::binary(),
+ {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}}},
string()) -> Der::binary().
%%
%% Description: Deciphers a decrypted pem entry.
%%--------------------------------------------------------------------
-decipher({_, DecryptDer, {Cipher,Salt}}, Password) ->
- decode_key(DecryptDer, Password, Cipher, Salt).
+decipher({_, DecryptDer, {Cipher, KeyDevParams}}, Password) ->
+ pubkey_pbe:decode(DecryptDer, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
--spec cipher(Der::binary(),{Cipher :: string(), Salt :: binary()} ,
+-spec cipher(Der::binary(), {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}} ,
string()) -> binary().
%%
%% Description: Ciphers a PEM entry
%%--------------------------------------------------------------------
-cipher(Der, {Cipher,Salt}, Password)->
- encode_key(Der, Password, Cipher, Salt).
+cipher(Der, {Cipher, KeyDevParams}, Password)->
+ pubkey_pbe:encode(Der, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -127,8 +125,20 @@ decode_pem_entry(Start, Lines) ->
Type = asn1_type(Start),
Cs = erlang:iolist_to_binary(Lines),
Decoded = base64:mime_decode(Cs),
- {Type, Decoded, not_encrypted}.
-
+ case Type of
+ 'EncryptedPrivateKeyInfo'->
+ decode_encrypted_private_keyinfo(Decoded);
+ _ ->
+ {Type, Decoded, not_encrypted}
+ end.
+
+decode_encrypted_private_keyinfo(Der) ->
+ #'EncryptedPrivateKeyInfo'{encryptionAlgorithm = AlgorithmInfo,
+ encryptedData = Data} =
+ public_key:der_decode('EncryptedPrivateKeyInfo', Der),
+ DecryptParams = pubkey_pbe:decrypt_parameters(AlgorithmInfo),
+ {'PrivateKeyInfo', iolist_to_binary(Data), DecryptParams}.
+
split_bin(Bin) ->
split_bin(0, Bin).
@@ -160,37 +170,6 @@ join_entry([<<"-----END ", _/binary>>| Lines], Entry) ->
join_entry([Line | Lines], Entry) ->
join_entry(Lines, [Line | Entry]).
-decode_key(Data, Password, "DES-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 8),
- IV = Salt,
- crypto:des_cbc_decrypt(Key, IV, Data);
-decode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 24),
- IV = Salt,
- <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
- crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data).
-
-encode_key(Data, Password, "DES-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 8),
- IV = Salt,
- crypto:des_cbc_encrypt(Key, IV, Data);
-encode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
- Key = password_to_key(Password, Salt, 24),
- IV = Salt,
- <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
- crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data).
-
-password_to_key(Data, Salt, KeyLen) ->
- <<Key:KeyLen/binary, _/binary>> =
- password_to_key(<<>>, Data, Salt, KeyLen, <<>>),
- Key.
-
-password_to_key(_, _, _, Len, Acc) when Len =< 0 ->
- Acc;
-password_to_key(Prev, Data, Salt, Len, Acc) ->
- M = crypto:md5([Prev, Data, Salt]),
- password_to_key(M, Data, Salt, Len - size(M), <<Acc/binary, M/binary>>).
-
unhex(S) ->
unhex(S, []).
@@ -228,6 +207,10 @@ pem_end(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
<<"-----END DSA PRIVATE KEY-----">>;
pem_end(<<"-----BEGIN DH PARAMETERS-----">>) ->
<<"-----END DH PARAMETERS-----">>;
+pem_end(<<"-----BEGIN PRIVATE KEY-----">>) ->
+ <<"-----END PRIVATE KEY-----">>;
+pem_end(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
+ <<"-----END ENCRYPTED PRIVATE KEY-----">>;
pem_end(_) ->
undefined.
@@ -242,18 +225,14 @@ asn1_type(<<"-----BEGIN PUBLIC KEY-----">>) ->
asn1_type(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
'DSAPrivateKey';
asn1_type(<<"-----BEGIN DH PARAMETERS-----">>) ->
- 'DHParameter'.
+ 'DHParameter';
+asn1_type(<<"-----BEGIN PRIVATE KEY-----">>) ->
+ 'PrivateKeyInfo';
+asn1_type(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
+ 'EncryptedPrivateKeyInfo'.
pem_decrypt() ->
<<"Proc-Type: 4,ENCRYPTED">>.
pem_decrypt_info(Cipher, Salt) ->
io_lib:format("DEK-Info: ~s,~s", [Cipher, lists:flatten(hexify(Salt))]).
-
-%%--------------------------------------------------------------------
-%%% Deprecated
-%%--------------------------------------------------------------------
-decode_key({_Type, Bin, not_encrypted}, _) ->
- Bin;
-decode_key({_Type, Bin, {Chipher,Salt}}, Password) ->
- decode_key(Bin, Password, Chipher, Salt).
diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl
index f342eab159..f0c94e29a5 100644
--- a/lib/public_key/src/pubkey_ssh.erl
+++ b/lib/public_key/src/pubkey_ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -146,16 +146,7 @@ do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
Split = binary:split(Line, <<" ">>, [global]),
case mend_split(Split, []) of
%% ssh2
- [Options, KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, string_decode(Comment)},
- {options, comma_list_decode(Options)}]}
- | Acc]);
-
- [KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
+ [KeyType, Base64Enc, Comment] ->
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
[{comment, string_decode(Comment)}]} | Acc]);
@@ -166,44 +157,32 @@ do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
[{comment, string_decode(Comment)},
{options, comma_list_decode(Options)},
{bits, integer_decode(Bits)}]} | Acc]);
- [Bits, Exponent, Modulus, Comment] ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- [{comment, string_decode(Comment)},
- {bits, integer_decode(Bits)}]} | Acc])
- end;
+ [A, B, C, D] ->
+ ssh_2_or_1(FileType, Lines, Acc, A,B,C,D)
+ end;
do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) ->
- case binary:split(Line, <<" ">>, [global]) of
+ Split = binary:split(Line, <<" ">>, [global]),
+ case mend_split(Split, []) of
%% ssh 2
- [HostNames, KeyType, Base64Enc] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
+ [HostNames, KeyType, Base64Enc] ->
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
[{hostnames, comma_list_decode(HostNames)}]}| Acc]);
- [HostNames, KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, string_decode(Comment)},
- {hostnames, comma_list_decode(HostNames)}]} | Acc]);
+ [A, B, C, D] ->
+ ssh_2_or_1(FileType, Lines, Acc, A, B, C, D);
%% ssh 1
[HostNames, Bits, Exponent, Modulus, Comment] ->
do_openssh_decode(FileType, Lines,
[{ssh1_rsa_pubkey_decode(Modulus, Exponent),
[{comment, string_decode(Comment)},
{hostnames, comma_list_decode(HostNames)},
- {bits, integer_decode(Bits)}]} | Acc]);
- [HostNames, Bits, Exponent, Modulus] ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- [{comment, []},
- {hostnames, comma_list_decode(HostNames)},
{bits, integer_decode(Bits)}]} | Acc])
end;
do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
- case binary:split(Line, <<" ">>, [global]) of
+ Split = binary:split(Line, <<" ">>, [global]),
+ case mend_split(Split, []) of
[KeyType, Base64Enc, Comment0] when KeyType == <<"ssh-rsa">>;
KeyType == <<"ssh-dss">> ->
Comment = string:strip(binary_to_list(Comment0), right, $\n),
@@ -212,6 +191,46 @@ do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
[{comment, Comment}]} | Acc])
end.
+ssh_2_or_1(known_hosts = FileType, Lines, Acc, A, B, C, D) ->
+ try integer_decode(B) of
+ Int ->
+ file_type_decode_ssh1(FileType, Lines, Acc, A, Int, C,D)
+ catch
+ error:badarg ->
+ file_type_decode_ssh2(FileType, Lines, Acc, A,B,C,D)
+ end;
+ssh_2_or_1(auth_keys = FileType, Lines, Acc, A, B, C, D) ->
+ try integer_decode(A) of
+ Int ->
+ file_type_decode_ssh1(FileType, Lines, Acc, Int, B, C,D)
+ catch
+ error:badarg ->
+ file_type_decode_ssh2(FileType, Lines, Acc, A,B,C,D)
+ end.
+
+file_type_decode_ssh1(known_hosts = FileType, Lines, Acc, HostNames, Bits, Exponent, Modulus) ->
+ do_openssh_decode(FileType, Lines,
+ [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
+ [{comment, []},
+ {hostnames, comma_list_decode(HostNames)},
+ {bits, Bits}]} | Acc]);
+file_type_decode_ssh1(auth_keys = FileType, Lines, Acc, Bits, Exponent, Modulus, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
+ [{comment, string_decode(Comment)},
+ {bits, Bits}]} | Acc]).
+
+file_type_decode_ssh2(known_hosts = FileType, Lines, Acc, HostNames, KeyType, Base64Enc, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{openssh_pubkey_decode(KeyType, Base64Enc),
+ [{comment, string_decode(Comment)},
+ {hostnames, comma_list_decode(HostNames)}]} | Acc]);
+file_type_decode_ssh2(auth_keys = FileType, Lines, Acc, Options, KeyType, Base64Enc, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{openssh_pubkey_decode(KeyType, Base64Enc),
+ [{comment, string_decode(Comment)},
+ {options, comma_list_decode(Options)}]}
+ | Acc]).
openssh_pubkey_decode(<<"ssh-rsa">>, Base64Enc) ->
<<?UINT32(StrLen), _:StrLen/binary,
@@ -231,7 +250,9 @@ openssh_pubkey_decode(<<"ssh-dss">>, Base64Enc) ->
{erlint(SizeY, Y),
#'Dss-Parms'{p = erlint(SizeP, P),
q = erlint(SizeQ, Q),
- g = erlint(SizeG, G)}}.
+ g = erlint(SizeG, G)}};
+openssh_pubkey_decode(KeyType, Base64Enc) ->
+ {KeyType, base64:mime_decode(Base64Enc)}.
erlint(MPIntSize, MPIntValue) ->
Bits= MPIntSize * 8,
@@ -412,6 +433,12 @@ is_key_field(<<"ssh-dss">>) ->
true;
is_key_field(<<"ssh-rsa">>) ->
true;
+is_key_field(<<"ecdsa-sha2-nistp256">>) ->
+ true;
+is_key_field(<<"ecdsa-sha2-nistp384">>) ->
+ true;
+is_key_field(<<"ecdsa-sha2-nistp521">>) ->
+ true;
is_key_field(_) ->
false.
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index 1963bd05d4..4cc81ea573 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -3,10 +3,12 @@
{vsn, "%VSN%"},
{modules, [ public_key,
pubkey_pem,
+ pubkey_pbe,
pubkey_ssh,
pubkey_cert,
pubkey_cert_records,
- 'OTP-PUB-KEY'
+ 'OTP-PUB-KEY',
+ 'PKCS-FRAME'
]},
{applications, [crypto, kernel, stdlib]},
{registered, []},
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index 4986801dad..aacd3b866d 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,70 +1,8 @@
%% -*- 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, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.9",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.8",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ {<<"0\\.*">>, [{restart_application, public_key}]}
],
[
- {"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, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.9",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.8",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ {<<"0\\.*">>, [{restart_application, public_key}]}
]}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 33fcce2c44..d5df53e848 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +45,11 @@
ssh_decode/2, ssh_encode/2
]).
-%% Deprecated
--export([decode_private_key/1, decode_private_key/2, pem_to_der/1]).
-
--deprecated({pem_to_der, 1, next_major_release}).
--deprecated({decode_private_key, 1, next_major_release}).
--deprecated({decode_private_key, 2, next_major_release}).
-
-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
| 'rsa_no_padding'.
-type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
--type rsa_digest_type() :: 'md5' | 'sha'.
--type dss_digest_type() :: 'none' | 'sha'.
+-type rsa_digest_type() :: 'md5' | 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'.
+-type dss_digest_type() :: 'none' | 'sha'. %% None is for backwards compatibility
-define(UINT32(X), X:32/unsigned-big-integer).
-define(DER_NULL, <<5, 0>>).
@@ -104,22 +97,23 @@ pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der);
+pem_entry_decode({Asn1Type, CryptDer, {Cipher, #'PBES2-params'{}}} = PemEntry,
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
+ is_list(Cipher) ->
+ do_pem_entry_decode(PemEntry, Password);
pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
- Password) when is_atom(Asn1Type),
- is_binary(CryptDer),
- is_list(Cipher),
- is_binary(Salt),
- erlang:byte_size(Salt) == 8
- ->
- Der = pubkey_pem:decipher(PemEntry, Password),
- der_decode(Asn1Type, Der).
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
+ is_list(Cipher) andalso
+ is_binary(Salt) andalso
+ erlang:byte_size(Salt) == 8 ->
+ do_pem_entry_decode(PemEntry, Password).
%%--------------------------------------------------------------------
-spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(),
- {{Cipher :: string(), Salt :: binary()}, string()}) ->
- pem_entry().
-%
+-spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
+%%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
@@ -137,21 +131,36 @@ pem_entry_encode('SubjectPublicKeyInfo',
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
-pem_entry_encode(Asn1Type, Entity,
- {{Cipher, Salt}= CipherInfo, Password}) when is_atom(Asn1Type),
- is_list(Cipher),
- is_binary(Salt),
- erlang:byte_size(Salt) == 8,
- is_list(Password)->
- Der = der_encode(Asn1Type, Entity),
- DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
- {Asn1Type, DecryptDer, CipherInfo}.
-
+pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
+ Password}) when is_atom(Asn1Type) andalso
+ is_list(Password) andalso
+ is_list(Cipher) ->
+ do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password);
+
+pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
+ Password}) when is_atom(Asn1Type) andalso
+ is_list(Password) andalso
+ is_list(Cipher) andalso
+ is_binary(Salt) andalso
+ erlang:byte_size(Salt) == 8 ->
+ do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
+
%%--------------------------------------------------------------------
-spec der_decode(asn1_type(), Der::binary()) -> term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
+der_decode(Asn1Type, Der) when (Asn1Type == 'PrivateKeyInfo') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo')
+ andalso is_binary(Der) ->
+ try
+ {ok, Decoded} = 'PKCS-FRAME':decode(Asn1Type, Der),
+ Decoded
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end;
+
der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
try
{ok, Decoded} = 'OTP-PUB-KEY':decode(Asn1Type, Der),
@@ -166,6 +175,16 @@ der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
+der_encode(Asn1Type, Entity) when (Asn1Type == 'PrivateKeyInfo') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo') ->
+ try
+ {ok, Encoded} = 'PKCS-FRAME':encode(Asn1Type, Entity),
+ iolist_to_binary(Encoded)
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end;
+
der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
try
{ok, Encoded} = 'OTP-PUB-KEY':encode(Asn1Type, Entity),
@@ -222,15 +241,15 @@ pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) ->
decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
-decrypt_private(CipherText,
- #'RSAPrivateKey'{modulus = N,publicExponent = E,
- privateExponent = D},
- Options) when is_binary(CipherText),
- is_list(Options) ->
+decrypt_private(CipherText,
+ #'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D} = Key,
+ Options)
+ when is_binary(CipherText),
+ is_integer(N), is_integer(E), is_integer(D),
+ is_list(Options) ->
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:rsa_private_decrypt(CipherText,
- [crypto:mpint(E), crypto:mpint(N),
- crypto:mpint(D)], Padding).
+ crypto:rsa_private_decrypt(CipherText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
-spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key()) ->
@@ -288,69 +307,86 @@ encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},
encrypt_private(PlainText, Key) ->
encrypt_private(PlainText, Key, []).
-encrypt_private(PlainText, #'RSAPrivateKey'{modulus = N,
- publicExponent = E,
- privateExponent = D},
- Options) when is_binary(PlainText), is_list(Options) ->
+encrypt_private(PlainText,
+ #'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D} = Key,
+ Options)
+ when is_binary(PlainText),
+ is_integer(N), is_integer(E), is_integer(D),
+ is_list(Options) ->
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:rsa_private_encrypt(PlainText, [crypto:mpint(E),
- crypto:mpint(N),
- crypto:mpint(D)], Padding).
+ crypto:rsa_private_encrypt(PlainText, format_rsa_private_key(Key), Padding).
+
+
+format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D,
+ prime1 = P1, prime2 = P2,
+ exponent1 = E1, exponent2 = E2,
+ coefficient = C})
+ when is_integer(P1), is_integer(P2),
+ is_integer(E1), is_integer(E2), is_integer(C) ->
+ [crypto:mpint(K) || K <- [E, N, D, P1, P2, E1, E2, C]];
+
+format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D}) ->
+ [crypto:mpint(K) || K <- [E, N, D]].
%%--------------------------------------------------------------------
--spec sign(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
- rsa_private_key() |
+-spec sign(binary() | {digest, binary()}, rsa_digest_type() | dss_digest_type(),
+ rsa_private_key() |
dsa_private_key()) -> Signature :: binary().
-%%
%% Description: Create digital signature.
%%--------------------------------------------------------------------
-sign(PlainText, DigestType, #'RSAPrivateKey'{modulus = N, publicExponent = E,
- privateExponent = D})
- when is_binary(PlainText),
- (DigestType == md5 orelse
- DigestType == sha) ->
-
- crypto:rsa_sign(DigestType, sized_binary(PlainText), [crypto:mpint(E),
- crypto:mpint(N),
- crypto:mpint(D)]);
-
-sign(Digest, none, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X})
- when is_binary(Digest)->
- crypto:dss_sign(none, Digest,
- [crypto:mpint(P), crypto:mpint(Q),
+sign({digest,_}=Digest, DigestType, Key = #'RSAPrivateKey'{}) ->
+ crypto:rsa_sign(DigestType, Digest, format_rsa_private_key(Key));
+
+sign(PlainText, DigestType, Key = #'RSAPrivateKey'{}) ->
+ crypto:rsa_sign(DigestType, sized_binary(PlainText), format_rsa_private_key(Key));
+
+sign({digest,_}=Digest, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
+ crypto:dss_sign(Digest,
+ [crypto:mpint(P), crypto:mpint(Q),
crypto:mpint(G), crypto:mpint(X)]);
-
-sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X})
- when is_binary(PlainText) ->
- crypto:dss_sign(sized_binary(PlainText),
- [crypto:mpint(P), crypto:mpint(Q),
- crypto:mpint(G), crypto:mpint(X)]).
+
+sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
+ crypto:dss_sign(sized_binary(PlainText),
+ [crypto:mpint(P), crypto:mpint(Q),
+ crypto:mpint(G), crypto:mpint(X)]);
+
+%% Backwards compatible
+sign(Digest, none, #'DSAPrivateKey'{} = Key) ->
+ sign({digest,Digest}, sha, Key).
%%--------------------------------------------------------------------
--spec verify(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
- Signature :: binary(), rsa_public_key()
+-spec verify(binary() | {digest, binary()}, rsa_digest_type() | dss_digest_type(),
+ Signature :: binary(), rsa_public_key()
| dsa_public_key()) -> boolean().
-%%
%% Description: Verifies a digital signature.
%%--------------------------------------------------------------------
-verify(PlainText, DigestType, Signature,
- #'RSAPublicKey'{modulus = Mod, publicExponent = Exp})
- when is_binary (PlainText), DigestType == sha; DigestType == md5 ->
+verify({digest,_}=Digest, DigestType, Signature,
+ #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}) ->
+ crypto:rsa_verify(DigestType, Digest,
+ sized_binary(Signature),
+ [crypto:mpint(Exp), crypto:mpint(Mod)]);
+
+verify(PlainText, DigestType, Signature,
+ #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}) ->
crypto:rsa_verify(DigestType,
sized_binary(PlainText),
sized_binary(Signature),
[crypto:mpint(Exp), crypto:mpint(Mod)]);
-verify(Digest, none, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
- when is_integer(Key), is_binary(Digest), is_binary(Signature) ->
- crypto:dss_verify(none,
- Digest,
- sized_binary(Signature),
+verify({digest,_}=Digest, sha, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
+ when is_integer(Key), is_binary(Signature) ->
+ crypto:dss_verify(Digest, sized_binary(Signature),
[crypto:mpint(P), crypto:mpint(Q),
crypto:mpint(G), crypto:mpint(Key)]);
-
+%% Backwards compatibility
+verify(Digest, none, Signature, {_, #'Dss-Parms'{}} = Key ) ->
+ verify({digest,Digest}, sha, Signature, Key);
+
verify(PlainText, sha, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
- when is_integer(Key), is_binary(PlainText), is_binary(Signature) ->
+ when is_integer(Key), is_binary(PlainText), is_binary(Signature) ->
crypto:dss_verify(sized_binary(PlainText),
sized_binary(Signature),
[crypto:mpint(P), crypto:mpint(Q),
@@ -535,6 +571,14 @@ ssh_encode(Entries, Type) when is_list(Entries),
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password) ->
+ Der = der_encode(Asn1Type, Entity),
+ DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
+ {Asn1Type, DecryptDer, CipherInfo}.
+
+do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
+ Der = pubkey_pem:decipher(PemEntry, Password),
+ der_decode(Asn1Type, Der).
encrypt_public(PlainText, N, E, Options)->
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
@@ -632,20 +676,3 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
sized_binary(Binary) ->
Size = size(Binary),
<<?UINT32(Size), Binary/binary>>.
-
-%%--------------------------------------------------------------------
-%%% Deprecated functions
-%%--------------------------------------------------------------------
-pem_to_der(CertSource) ->
- {ok, Bin} = file:read_file(CertSource),
- {ok, pubkey_pem:decode(Bin)}.
-
-decode_private_key(KeyInfo) ->
- decode_private_key(KeyInfo, no_passwd).
-
-decode_private_key(KeyInfo = {'RSAPrivateKey', _, _}, Password) ->
- DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
- 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded);
-decode_private_key(KeyInfo = {'DSAPrivateKey', _, _}, Password) ->
- DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
- 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded).
diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile
index 6889ae9a8a..41d77f103b 100644
--- a/lib/public_key/test/Makefile
+++ b/lib/public_key/test/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
@@ -21,7 +21,7 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-INCLUDES= -I. -I ../include
+INCLUDES= -I. -I ../include -pa $(ERL_TOP)/lib/public_key/ebin
# ----------------------------------------------------
# Target Specs
@@ -30,6 +30,7 @@ INCLUDES= -I. -I ../include
MODULES= \
erl_make_certs \
public_key_SUITE \
+ pbe_SUITE \
pkits_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -77,11 +78,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(SPEC_FILES) $(ERL_FILES) $(COVER_FILE) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(SPEC_FILES) $(ERL_FILES) $(COVER_FILE) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/public_key/test/erl_make_certs.erl b/lib/public_key/test/erl_make_certs.erl
index 8b01ca3ad4..254aa6d2f9 100644
--- a/lib/public_key/test/erl_make_certs.erl
+++ b/lib/public_key/test/erl_make_certs.erl
@@ -1,7 +1,7 @@
%%
%% %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
@@ -175,7 +175,7 @@ issuer(true, Opts, SubjectKey) ->
issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
{issuer_der(Issuer), decode_key(IssuerKey)};
issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File),
+ {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
{issuer_der(Cert), decode_key(IssuerKey)}.
issuer_der(Issuer) ->
@@ -185,7 +185,7 @@ issuer_der(Issuer) ->
Subject.
subject(undefined, IsRootCA) ->
- User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end,
+ User = if IsRootCA -> "RootCA"; true -> user() end,
Opts = [{email, User ++ "@erlang.org"},
{name, User},
{city, "Stockholm"},
@@ -196,6 +196,14 @@ subject(undefined, IsRootCA) ->
subject(Opts, _) ->
subject(Opts).
+user() ->
+ case os:getenv("USER") of
+ false ->
+ "test_user";
+ User ->
+ User
+ end.
+
subject(SubjectOpts) when is_list(SubjectOpts) ->
Encode = fun(Opt) ->
{Type,Value} = subject_enc(Opt),
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
new file mode 100644
index 0000000000..380a67db7b
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -0,0 +1,259 @@
+%%
+%% %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(pbe_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+%% 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) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ 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) ->
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ 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) ->
+ 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
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ pbdkdf1,
+ pbdkdf2,
+ encrypted_private_key_info].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+pbdkdf1(doc) ->
+ ["Test with PKCS #5 PBKDF1 Test Vectors"];
+pbdkdf1(Config) when is_list(Config) ->
+ %%Password = "password"
+ %% = (0x)70617373776F7264
+ %%Salt = (0x)78578E5A5D63CB06
+ %%Count = 1000
+ %%kLen = 16
+ %%Key = PBKDF1(Password, Salt, Count, kLen)
+ %%= (0x)DC19847E05C64D2FAF10EBFB4A3D2A20
+
+ Password = "password",
+ Salt = <<16#78,16#57,16#8E,16#5A,16#5D,16#63,16#CB,16#06>>,
+ Count = 1000,
+
+ <<16#DC, 16#19, 16#84, 16#7E,
+ 16#05, 16#C6, 16#4D, 16#2F,
+ 16#AF, 16#10, 16#EB, 16#FB,
+ 16#4A, 16#3D, 16#2A, 16#20, _/binary>> =
+ pubkey_pbe:pbdkdf1(Password, Salt, Count, sha).
+
+pbdkdf2(doc) ->
+ ["Test with PKCS #5 PBKDF2 Test Vectors"];
+pbdkdf2(Config) when is_list(Config) ->
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 1
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = 0c 60 c8 0f 96 1f 0e 71
+ %% f3 a9 b5 24 af 60 12 06
+ %% 2f e0 37 a6 (20 octets)
+
+ <<16#0c, 16#60, 16#c8, 16#0f, 16#96, 16#1f, 16#0e, 16#71,
+ 16#f3, 16#a9, 16#b5, 16#24, 16#af, 16#60, 16#12, 16#06,
+ 16#2f, 16#e0, 16#37, 16#a6>> = pubkey_pbe:pbdkdf2("password", "salt", 1, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 2
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = ea 6c 01 4d c7 2d 6f 8c
+ %% cd 1e d9 2a ce 1d 41 f0
+ %% d8 de 89 57 (20 octets)
+
+ <<16#ea, 16#6c, 16#01, 16#4d, 16#c7, 16#2d, 16#6f, 16#8c,
+ 16#cd, 16#1e, 16#d9, 16#2a, 16#ce, 16#1d, 16#41, 16#f0,
+ 16#d8, 16#de, 16#89, 16#57>> =
+ pubkey_pbe:pbdkdf2("password", "salt", 2, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 4096
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = 4b 00 79 01 b7 65 48 9a
+ %% be ad 49 d9 26 f7 21 d0
+ %% 65 a4 29 c1 (20 octets)
+
+ <<16#4b, 16#00, 16#79, 16#01, 16#b7, 16#65, 16#48, 16#9a,
+ 16#be, 16#ad, 16#49, 16#d9, 16#26, 16#f7, 16#21, 16#d0,
+ 16#65, 16#a4, 16#29, 16#c1>> = pubkey_pbe:pbdkdf2("password", "salt", 4096, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "password" (8 octets)
+ %% S = "salt" (4 octets)
+ %% c = 16777216
+ %% dkLen = 20
+
+ %% Output:
+ %% DK = ee fe 3d 61 cd 4d a4 e4
+ %% e9 94 5b 3d 6b a2 15 8c
+ %% 26 34 e9 84 (20 octets)
+
+
+ <<16#ee, 16#fe, 16#3d, 16#61, 16#cd, 16#4d, 16#a4, 16#e4,
+ 16#e9, 16#94, 16#5b, 16#3d, 16#6b, 16#a2, 16#15, 16#8c,
+ 16#26, 16#34, 16#e9, 16#84>> = pubkey_pbe:pbdkdf2("password", "salt", 16777216, 20, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "passwordPASSWORDpassword" (24 octets)
+ %% S = "saltSALTsaltSALTsaltSALTsaltSALTsalt" (36 octets)
+ %% c = 4096
+ %% dkLen = 25
+
+ %% Output:
+ %% DK = 3d 2e ec 4f e4 1c 84 9b
+ %% 80 c8 d8 36 62 c0 e4 4a
+ %% 8b 29 1a 96 4c f2 f0 70
+ %% 38 (25 octets)
+
+ <<16#3d, 16#2e, 16#ec, 16#4f, 16#e4, 16#1c, 16#84, 16#9b,
+ 16#80, 16#c8, 16#d8, 16#36, 16#62, 16#c0, 16#e4, 16#4a,
+ 16#8b, 16#29, 16#1a, 16#96, 16#4c, 16#f2, 16#f0, 16#70,
+ 16#38>>
+ = pubkey_pbe:pbdkdf2("passwordPASSWORDpassword",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, fun crypto:sha_mac/3, 20),
+
+ %% Input:
+ %% P = "pass\0word" (9 octets)
+ %% S = "sa\0lt" (5 octets)
+ %% c = 4096
+ %% dkLen = 16
+
+ %% Output:
+ %% DK = 56 fa 6a a7 55 48 09 9d
+ %% cc 37 d7 f0 34 25 e0 c3 (16 octets)
+
+ <<16#56, 16#fa, 16#6a, 16#a7, 16#55, 16#48, 16#09, 16#9d,
+ 16#cc, 16#37, 16#d7, 16#f0, 16#34, 16#25, 16#e0, 16#c3>>
+ = pubkey_pbe:pbdkdf2("pass\0word",
+ "sa\0lt", 4096, 16, fun crypto:sha_mac/3, 20).
+
+encrypted_private_key_info(doc) ->
+ ["Tests reading a EncryptedPrivateKeyInfo file encrypted with different ciphers"];
+encrypted_private_key_info(Config) when is_list(Config) ->
+ Datadir = ?config(data_dir, Config),
+ {ok, PemDes} = file:read_file(filename:join(Datadir, "des_cbc_enc_key.pem")),
+
+ PemDesEntry = public_key:pem_decode(PemDes),
+ test_server:format("Pem entry: ~p" , [PemDesEntry]),
+ [{'PrivateKeyInfo', _, {"DES-CBC",_}} = PubEntry0] = PemDesEntry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry0, "password"),
+
+ {ok, Pem3Des} = file:read_file(filename:join(Datadir, "des_ede3_cbc_enc_key.pem")),
+
+ Pem3DesEntry = public_key:pem_decode(Pem3Des),
+ test_server:format("Pem entry: ~p" , [Pem3DesEntry]),
+ [{'PrivateKeyInfo', _, {"DES-EDE3-CBC",_}} = PubEntry1] = Pem3DesEntry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry1, "password"),
+
+ {ok, PemRc2} = file:read_file(filename:join(Datadir, "rc2_cbc_enc_key.pem")),
+
+ PemRc2Entry = public_key:pem_decode(PemRc2),
+ test_server:format("Pem entry: ~p" , [PemRc2Entry]),
+ [{'PrivateKeyInfo', _, {"RC2-CBC",_}} = PubEntry2] = PemRc2Entry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry2, "password"),
+
+ check_key_info(KeyInfo).
+
+
+check_key_info(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
+ privateKey = Key}) ->
+ #'RSAPrivateKey'{} = public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key)).
diff --git a/lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem
new file mode 100644
index 0000000000..eaa06145aa
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE_data/des_cbc_enc_key.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA
+MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y
+9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ
+0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo
+f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO
+Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v
+aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks
+2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM
+75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem
new file mode 100644
index 0000000000..22ea46d56f
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE_data/des_ede3_cbc_enc_key.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA
+MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/
+koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8
++MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5
+6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi
+5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ
+BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8
+z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr
+u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem
new file mode 100644
index 0000000000..618cddcfd7
--- /dev/null
+++ b/lib/public_key/test/pbe_SUITE_data/rc2_cbc_enc_key.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA
+AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop
+7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f
+wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21
+RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6
+VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1
+MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz
+tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH
+2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO
+6DA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index a325a975e9..e59f299399 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -72,7 +72,8 @@ groups() ->
[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_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,
@@ -116,14 +117,12 @@ 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.
+ try crypto:start() of
+ ok ->
+ crypto_support_check(Config)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
end_per_suite(_Config) ->
application:stop(crypto).
@@ -134,109 +133,109 @@ valid_rsa_signature(doc) ->
valid_rsa_signature(suite) ->
[];
valid_rsa_signature(Config) when is_list(Config) ->
- run([{ "4.1.1", "Valid Signatures Test1", ok}]).
+ run([{ "4.1.1", "Valid Certificate Path Test1 EE", 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}}]).
+ run([{ "4.1.2", "Invalid CA Signature Test2 EE", {bad_cert,invalid_signature}},
+ { "4.1.3", "Invalid EE Signature Test3 EE", {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}]).
+ run([{ "4.1.4", "Valid DSA Signatures Test4 EE", ok},
+ { "4.1.5", "Valid DSA Parameter Inheritance Test5 EE", 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}}]).
+ run([{ "4.1.6", "Invalid DSA Signature Test6 EE",{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}}]).
+ run([{ "4.2.1", "Invalid CA notBefore Date Test1 EE",{bad_cert, cert_expired}},
+ { "4.2.2", "Invalid EE notBefore Date Test2 EE",{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}]).
+ run([{ "4.2.3", "Valid pre2000 UTC notBefore Date Test3 EE", ok},
+ { "4.2.4", "Valid GeneralizedTime notBefore Date Test4 EE", 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}}]).
+ run([{ "4.2.5", "Invalid CA notAfter Date Test5 EE", {bad_cert, cert_expired}},
+ { "4.2.6", "Invalid EE notAfter Date Test6 EE", {bad_cert, cert_expired}},
+ { "4.2.7", "Invalid pre2000 UTC EE notAfter Date Test7 EE",{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}]).
+ run([{ "4.2.8", "Valid GeneralizedTime notAfter Date Test8 EE", 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}}]).
+ run([{ "4.3.1", "Invalid Name Chaining Test1 EE", {bad_cert, invalid_issuer}},
+ { "4.3.2", "Invalid Name Chaining Order Test2 EE", {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}]).
+ run([{ "4.3.3", "Valid Name Chaining Whitespace Test3 EE", ok},
+ { "4.3.4", "Valid Name Chaining Whitespace Test4 EE", 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}]).
+ run([{ "4.3.5", "Valid Name Chaining Capitalization Test5 EE",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}]).
+ run([{ "4.3.6", "Valid Name UIDs Test6 EE",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}]).
+ run([{ "4.3.7", "Valid RFC3280 Mandatory Attribute Types Test7 EE", ok},
+ { "4.3.8", "Valid RFC3280 Optional Attribute Types Test8 EE", 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}]).
+ run([{ "4.3.9", "Valid UTF8String Encoded Names Test9 EE", ok},
+ %%{ "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10 EE", ok},
+ { "4.3.11", "Valid UTF8String Case Insensitive Match Test11 EE", ok}]).
%%-----------------------------------------------------------------------------
@@ -245,9 +244,9 @@ 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}
+ run([{ "4.5.1", "Valid Basic Self-Issued Old With New Test1 EE", ok},
+ { "4.5.3", "Valid Basic Self-Issued New With Old Test3 EE", ok},
+ { "4.5.4", "Valid Basic Self-Issued New With Old Test4 EE", ok}
]).
basic_invalid(doc) ->
@@ -255,9 +254,9 @@ 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",
+ run([{"4.5.2", "Invalid Basic Self-Issued Old With New Test2 EE",
{bad_cert, {revoked, keyCompromise}}},
- {"4.5.5", "Invalid Basic Self-Issued New With Old Test5",
+ {"4.5.5", "Invalid Basic Self-Issued New With Old Test5 EE",
{bad_cert, {revoked, keyCompromise}}}
]).
@@ -266,16 +265,16 @@ 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}]).
+ run([{ "4.5.6", "Valid Basic Self-Issued CRL Signing Key Test6 EE", 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",
+ run([%% { "4.5.7", "Invalid Basic Self-Issued CRL Signing Key Test7 EE",
+ %% {bad_cert, {revoked, keyCompromise}}},
+ { "4.5.8", "Invalid Basic Self-Issued CRL Signing Key Test8 EE",
{bad_cert, invalid_key_usage}}
]).
@@ -285,7 +284,7 @@ missing_CRL(doc) ->
missing_CRL(suite) ->
[];
missing_CRL(Config) when is_list(Config) ->
- run([{ "4.4.1", "Missing CRL Test1",{bad_cert,
+ run([{ "4.4.1", "Missing CRL Test1 EE",{bad_cert,
revocation_status_undetermined}}]).
revoked_CA(doc) ->
@@ -293,7 +292,7 @@ revoked_CA(doc) ->
revoked_CA(suite) ->
[];
revoked_CA(Config) when is_list(Config) ->
- run([{ "4.4.2", "Invalid Revoked CA Test2", {bad_cert,
+ run([{ "4.4.2", "Invalid Revoked CA Test2 EE", {bad_cert,
{revoked, keyCompromise}}}]).
revoked_peer(doc) ->
@@ -301,7 +300,7 @@ revoked_peer(doc) ->
revoked_peer(suite) ->
[];
revoked_peer(Config) when is_list(Config) ->
- run([{ "4.4.3", "Invalid Revoked EE Test3", {bad_cert,
+ run([{ "4.4.3", "Invalid Revoked EE Test3 EE", {bad_cert,
{revoked, keyCompromise}}}]).
invalid_CRL_signature(doc) ->
@@ -309,7 +308,7 @@ 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",
+ run([{ "4.4.4", "Invalid Bad CRL Signature Test4 EE",
{bad_cert, revocation_status_undetermined}}]).
invalid_CRL_issuer(doc) ->
@@ -317,7 +316,7 @@ 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",
+ run({ "4.4.5", "Invalid Bad CRL Issuer Name Test5 EE",
{bad_cert, revocation_status_undetermined}}).
invalid_CRL(doc) ->
@@ -325,7 +324,7 @@ invalid_CRL(doc) ->
invalid_CRL(suite) ->
[];
invalid_CRL(Config) when is_list(Config) ->
- run([{ "4.4.6", "Invalid Wrong CRL Test6",
+ run([{ "4.4.6", "Invalid Wrong CRL Test6 EE",
{bad_cert, revocation_status_undetermined}}]).
valid_CRL(doc) ->
@@ -333,18 +332,18 @@ valid_CRL(doc) ->
valid_CRL(suite) ->
[];
valid_CRL(Config) when is_list(Config) ->
- run([{ "4.4.7", "Valid Two CRLs Test7", ok}]).
+ run([{ "4.4.7", "Valid Two CRLs Test7 EE", 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",
+ run([{ "4.4.8", "Invalid Unknown CRL Entry Extension Test8 EE",
{bad_cert, {revoked, keyCompromise}}},
- { "4.4.9", "Invalid Unknown CRL Extension Test9",
+ { "4.4.9", "Invalid Unknown CRL Extension Test9 EE",
{bad_cert, {revoked, keyCompromise}}},
- { "4.4.10", "Invalid Unknown CRL Extension Test10",
+ { "4.4.10", "Invalid Unknown CRL Extension Test10 EE",
{bad_cert, revocation_status_undetermined}}]).
old_CRL(doc) ->
@@ -352,9 +351,9 @@ old_CRL(doc) ->
old_CRL(suite) ->
[];
old_CRL(Config) when is_list(Config) ->
- run([{ "4.4.11", "Invalid Old CRL nextUpdate Test11",
+ run([{ "4.4.11", "Invalid Old CRL nextUpdate Test11 EE",
{bad_cert, revocation_status_undetermined}},
- { "4.4.12", "Invalid pre2000 CRL nextUpdate Test12",
+ { "4.4.12", "Invalid pre2000 CRL nextUpdate Test12 EE",
{bad_cert, revocation_status_undetermined}}]).
fresh_CRL(doc) ->
@@ -362,7 +361,7 @@ fresh_CRL(doc) ->
fresh_CRL(suite) ->
[];
fresh_CRL(Config) when is_list(Config) ->
- run([{ "4.4.13", "Valid GeneralizedTime CRL nextUpdate Test13", ok}]).
+ run([{ "4.4.13", "Valid GeneralizedTime CRL nextUpdate Test13 EE", ok}]).
valid_serial(doc) ->
[""];
@@ -370,9 +369,9 @@ 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}
+ { "4.4.14", "Valid Negative Serial Number Test14 EE",ok},
+ { "4.4.16", "Valid Long Serial Number Test16 EE", ok},
+ { "4.4.17", "Valid Long Serial Number Test17 EE", ok}
]).
invalid_serial(doc) ->
@@ -380,9 +379,9 @@ invalid_serial(doc) ->
invalid_serial(suite) ->
[];
invalid_serial(Config) when is_list(Config) ->
- run([{ "4.4.15", "Invalid Negative Serial Number Test15",
+ run([{ "4.4.15", "Invalid Negative Serial Number Test15 EE",
{bad_cert, {revoked, keyCompromise}}},
- { "4.4.18", "Invalid Long Serial Number Test18",
+ { "4.4.18", "Invalid Long Serial Number Test18 EE",
{bad_cert, {revoked, keyCompromise}}}]).
valid_seperate_keys(doc) ->
@@ -390,7 +389,7 @@ 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}]).
+ run([{ "4.4.19", "Valid Separate Certificate and CRL Keys Test19 EE", ok}]).
invalid_separate_keys(doc) ->
[""];
@@ -408,11 +407,11 @@ missing_basic_constraints(doc) ->
missing_basic_constraints(suite) ->
[];
missing_basic_constraints(Config) when is_list(Config) ->
- run([{ "4.6.1", "Invalid Missing basicConstraints Test1",
+ run([{ "4.6.1", "Invalid Missing basicConstraints Test1 EE",
{bad_cert, missing_basic_constraint}},
- { "4.6.2", "Invalid cA False Test2",
+ { "4.6.2", "Invalid cA False Test2 EE",
{bad_cert, missing_basic_constraint}},
- { "4.6.3", "Invalid cA False Test3",
+ { "4.6.3", "Invalid cA False Test3 EE",
{bad_cert, missing_basic_constraint}}]).
valid_basic_constraint(doc) ->
@@ -420,20 +419,20 @@ 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}]).
+ run([{"4.6.4", "Valid basicConstraints Not Critical Test4 EE", 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",
+ run([{ "4.6.5", "Invalid pathLenConstraint Test5 EE", {bad_cert, max_path_length_reached}},
+ { "4.6.6", "Invalid pathLenConstraint Test6 EE", {bad_cert, max_path_length_reached}},
+ { "4.6.9", "Invalid pathLenConstraint Test9 EE", {bad_cert, max_path_length_reached}},
+ { "4.6.10", "Invalid pathLenConstraint Test10 EE", {bad_cert, max_path_length_reached}},
+ { "4.6.11", "Invalid pathLenConstraint Test11 EE", {bad_cert, max_path_length_reached}},
+ { "4.6.12", "Invalid pathLenConstraint Test12 EE", {bad_cert, max_path_length_reached}},
+ { "4.6.16", "Invalid Self-Issued pathLenConstraint Test16 EE",
{bad_cert, max_path_length_reached}}]).
valid_path_constraints(doc) ->
@@ -441,12 +440,12 @@ 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}]).
+ run([{ "4.6.7", "Valid pathLenConstraint Test7 EE", ok},
+ { "4.6.8", "Valid pathLenConstraint Test8 EE", ok},
+ { "4.6.13", "Valid pathLenConstraint Test13 EE", ok},
+ { "4.6.14", "Valid pathLenConstraint Test14 EE", ok},
+ { "4.6.15", "Valid Self-Issued pathLenConstraint Test15 EE", ok},
+ { "4.6.17", "Valid Self-Issued pathLenConstraint Test17 EE", ok}]).
%%-----------------------------------------------------------------------------
invalid_key_usage(doc) ->
@@ -454,14 +453,14 @@ 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",
+ run([{ "4.7.1", "Invalid keyUsage Critical keyCertSign False Test1 EE",
{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}}
+ { "4.7.2", "Invalid keyUsage Not Critical keyCertSign False Test2 EE",
+ {bad_cert,invalid_key_usage}}
+ %% { "4.7.4", "Invalid keyUsage Critical cRLSign False Test4 EE",
+ %% {bad_cert, revocation_status_undetermined}},
+ %% { "4.7.5", "Invalid keyUsage Not Critical cRLSign False Test5 EE",
+ %% {bad_cert, revocation_status_undetermined}}
]).
valid_key_usage(doc) ->
@@ -469,7 +468,7 @@ 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}]).
+ run([{ "4.7.3", "Valid keyUsage Not Critical Test3 EE", ok}]).
%%-----------------------------------------------------------------------------
certificate_policies(doc) -> [""];
@@ -503,32 +502,32 @@ 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}]).
+ run([{ "4.13.1", "Valid DN nameConstraints Test1 EE", ok},
+ { "4.13.4", "Valid DN nameConstraints Test4 EE", ok},
+ { "4.13.5", "Valid DN nameConstraints Test5 EE", ok},
+ { "4.13.6", "Valid DN nameConstraints Test6 EE", ok},
+ { "4.13.11", "Valid DN nameConstraints Test11 EE", ok},
+ { "4.13.14", "Valid DN nameConstraints Test14 EE", ok},
+ { "4.13.18", "Valid DN nameConstraints Test18 EE", ok},
+ { "4.13.19", "Valid DN nameConstraints Test19 EE", 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",
+ run([{ "4.13.2", "Invalid DN nameConstraints Test2 EE", {bad_cert, name_not_permitted}},
+ { "4.13.3", "Invalid DN nameConstraints Test3 EE", {bad_cert, name_not_permitted}},
+ { "4.13.7", "Invalid DN nameConstraints Test7 EE", {bad_cert, name_not_permitted}},
+ { "4.13.8", "Invalid DN nameConstraints Test8 EE", {bad_cert, name_not_permitted}},
+ { "4.13.9", "Invalid DN nameConstraints Test9 EE", {bad_cert, name_not_permitted}},
+ { "4.13.10", "Invalid DN nameConstraints Test10 EE",{bad_cert, name_not_permitted}},
+ { "4.13.12", "Invalid DN nameConstraints Test12 EE",{bad_cert, name_not_permitted}},
+ { "4.13.13", "Invalid DN nameConstraints Test13 EE",{bad_cert, name_not_permitted}},
+ { "4.13.15", "Invalid DN nameConstraints Test15 EE",{bad_cert, name_not_permitted}},
+ { "4.13.16", "Invalid DN nameConstraints Test16 EE",{bad_cert, name_not_permitted}},
+ { "4.13.17", "Invalid DN nameConstraints Test17 EE",{bad_cert, name_not_permitted}},
+ { "4.13.20", "Invalid DN nameConstraints Test20 EE",
{bad_cert, name_not_permitted}}]).
valid_rfc822_name_constraints(doc) ->
@@ -536,9 +535,9 @@ 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}]).
+ run([{ "4.13.21", "Valid RFC822 nameConstraints Test21 EE", ok},
+ { "4.13.23", "Valid RFC822 nameConstraints Test23 EE", ok},
+ { "4.13.25", "Valid RFC822 nameConstraints Test25 EE", ok}]).
invalid_rfc822_name_constraints(doc) ->
@@ -546,11 +545,11 @@ 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",
+ run([{ "4.13.22", "Invalid RFC822 nameConstraints Test22 EE",
{bad_cert, name_not_permitted}},
- { "4.13.24", "Invalid RFC822 nameConstraints Test24",
+ { "4.13.24", "Invalid RFC822 nameConstraints Test24 EE",
{bad_cert, name_not_permitted}},
- { "4.13.26", "Invalid RFC822 nameConstraints Test26",
+ { "4.13.26", "Invalid RFC822 nameConstraints Test26 EE",
{bad_cert, name_not_permitted}}]).
valid_DN_and_rfc822_name_constraints(doc) ->
@@ -558,16 +557,16 @@ 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}]).
+ run([{ "4.13.27", "Valid DN and RFC822 nameConstraints Test27 EE", 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",
+ run([{ "4.13.28", "Invalid DN and RFC822 nameConstraints Test28 EE",
{bad_cert, name_not_permitted}},
- { "4.13.29", "Invalid DN and RFC822 nameConstraints Test29",
+ { "4.13.29", "Invalid DN and RFC822 nameConstraints Test29 EE",
{bad_cert, name_not_permitted}}]).
valid_dns_name_constraints(doc) ->
@@ -575,33 +574,33 @@ 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}]).
+ run([{ "4.13.30", "Valid DNS nameConstraints Test30 EE", ok},
+ { "4.13.32", "Valid DNS nameConstraints Test32 EE", 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}}]).
+ run([{ "4.13.31", "Invalid DNS nameConstraints Test31 EE", {bad_cert, name_not_permitted}},
+ { "4.13.33", "Invalid DNS nameConstraints Test33 EE", {bad_cert, name_not_permitted}},
+ { "4.13.38", "Invalid DNS nameConstraints Test38 EE", {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}]).
+ run([{ "4.13.34", "Valid URI nameConstraints Test34 EE", ok},
+ { "4.13.36", "Valid URI nameConstraints Test36 EE", 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}}]).
+ run([{ "4.13.35", "Invalid URI nameConstraints Test35 EE",{bad_cert, name_not_permitted}},
+ { "4.13.37", "Invalid URI nameConstraints Test37 EE",{bad_cert, name_not_permitted}}]).
%%-----------------------------------------------------------------------------
delta_without_crl(doc) ->
@@ -609,20 +608,20 @@ 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,
+ run([{ "4.15.1", "Invalid deltaCRLIndicator No Base Test1 EE",{bad_cert,
revocation_status_undetermined}},
- {"4.15.10", "Invalid delta-CRL Test10", {bad_cert,
- revocation_status_undetermined}}]).
+ {"4.15.10", "Invalid delta-CRL Test10 EE", {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}
+ run([{ "4.15.2", "Valid delta-CRL Test2 EE", ok},
+ { "4.15.5", "Valid delta-CRL Test5 EE", ok},
+ { "4.15.7", "Valid delta-CRL Test7 EE", ok},
+ { "4.15.8", "Valid delta-CRL Test8 EE", ok}
]).
invalid_delta_crls(doc) ->
@@ -630,10 +629,10 @@ 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}}}]).
+ run([{ "4.15.3", "Invalid delta-CRL Test3 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.15.4", "Invalid delta-CRL Test4 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.15.6", "Invalid delta-CRL Test6 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.15.9", "Invalid delta-CRL Test9 EE", {bad_cert,{revoked, keyCompromise}}}]).
%%-----------------------------------------------------------------------------
@@ -642,10 +641,10 @@ 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}
+ run([{ "4.14.1", "Valid distributionPoint Test1 EE", ok},
+ { "4.14.4", "Valid distributionPoint Test4 EE", ok},
+ { "4.14.5", "Valid distributionPoint Test5 EE", ok},
+ { "4.14.7", "Valid distributionPoint Test7 EE", ok}
]).
valid_distribution_points_no_issuing_distribution_point(doc) ->
@@ -661,13 +660,13 @@ 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,
+ run([{ "4.14.2", "Invalid distributionPoint Test2 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.3", "Invalid distributionPoint Test3 EE", {bad_cert,
revocation_status_undetermined}},
- { "4.14.6", "Invalid distributionPoint Test6", {bad_cert,{revoked, keyCompromise}}},
- { "4.14.8", "Invalid distributionPoint Test8", {bad_cert,
+ { "4.14.6", "Invalid distributionPoint Test6 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.8", "Invalid distributionPoint Test8 EE", {bad_cert,
revocation_status_undetermined}},
- { "4.14.9", "Invalid distributionPoint Test9", {bad_cert,
+ { "4.14.9", "Invalid distributionPoint Test9 EE", {bad_cert,
revocation_status_undetermined}}
]).
@@ -676,7 +675,7 @@ 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}]).
+ run([{ "4.14.13", "Valid onlyContainsCACerts CRL Test13 EE", ok}]).
invalid_only_contains(doc) ->
@@ -684,11 +683,11 @@ invalid_only_contains(doc) ->
invalid_only_contains(suite) ->
[];
invalid_only_contains(Config) when is_list(Config) ->
- run([{ "4.14.11", "Invalid onlyContainsUserCerts CRL Test11",
+ run([{ "4.14.11", "Invalid onlyContainsUserCerts CRL Test11 EE",
{bad_cert, revocation_status_undetermined}},
- { "4.14.12", "Invalid onlyContainsCACerts CRL Test12",
+ { "4.14.12", "Invalid onlyContainsCACerts CRL Test12 EE",
{bad_cert, revocation_status_undetermined}},
- { "4.14.14", "Invalid onlyContainsAttributeCerts Test14",
+ { "4.14.14", "Invalid onlyContainsAttributeCerts Test14 EE",
{bad_cert, revocation_status_undetermined}}
]).
@@ -697,8 +696,8 @@ 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}
+ run([{ "4.14.18", "Valid onlySomeReasons Test18 EE", ok},
+ { "4.14.19", "Valid onlySomeReasons Test19 EE", ok}
]).
invalid_only_some_reasons(doc) ->
@@ -706,15 +705,15 @@ 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",
+ run([{ "4.14.15", "Invalid onlySomeReasons Test15 EE",
{bad_cert,{revoked, keyCompromise}}},
- { "4.14.16", "Invalid onlySomeReasons Test16",
+ { "4.14.16", "Invalid onlySomeReasons Test16 EE",
{bad_cert,{revoked, certificateHold}}},
- { "4.14.17", "Invalid onlySomeReasons Test17",
+ { "4.14.17", "Invalid onlySomeReasons Test17 EE",
{bad_cert, revocation_status_undetermined}},
- { "4.14.20", "Invalid onlySomeReasons Test20",
+ { "4.14.20", "Invalid onlySomeReasons Test20 EE",
{bad_cert,{revoked, keyCompromise}}},
- { "4.14.21", "Invalid onlySomeReasons Test21",
+ { "4.14.21", "Invalid onlySomeReasons Test21 EE",
{bad_cert,{revoked, affiliationChanged}}}
]).
@@ -723,9 +722,9 @@ 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}
+ run([{ "4.14.22", "Valid IDP with indirectCRL Test22 EE", ok},
+ { "4.14.24", "Valid IDP with indirectCRL Test24 EE", ok},
+ { "4.14.25", "Valid IDP with indirectCRL Test25 EE", ok}
]).
invalid_indirect_crl(doc) ->
@@ -733,9 +732,9 @@ 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",
+ run([{ "4.14.23", "Invalid IDP with indirectCRL Test23 EE",
{bad_cert,{revoked, keyCompromise}}},
- { "4.14.26", "Invalid IDP with indirectCRL Test26",
+ { "4.14.26", "Invalid IDP with indirectCRL Test26 EE",
{bad_cert, revocation_status_undetermined}}
]).
@@ -744,9 +743,9 @@ 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}
+ run([{ "4.14.28", "Valid cRLIssuer Test28 EE", ok}%%,
+ %%{ "4.14.29", "Valid cRLIssuer Test29 EE", ok},
+ %%{ "4.14.33", "Valid cRLIssuer Test33 EE", ok}
]).
invalid_crl_issuer(doc) ->
@@ -755,11 +754,11 @@ 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}}
+ { "4.14.27", "Invalid cRLIssuer Test27 EE", {bad_cert, revocation_status_undetermined}},
+ { "4.14.31", "Invalid cRLIssuer Test31 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.32", "Invalid cRLIssuer Test32 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.34", "Invalid cRLIssuer Test34 EE", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.35", "Invalid cRLIssuer Test35 EE", {bad_cert, revocation_status_undetermined}}
]).
@@ -780,7 +779,7 @@ 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",
+ run([{ "4.16.2", "Invalid Unknown Critical Certificate Extension Test2 EE",
{bad_cert,unknown_critical_extension}}]).
unknown_not_critical_extension(doc) ->
@@ -788,16 +787,18 @@ 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([{ "4.16.1", "Valid Unknown Not Critical Certificate Extension Test1 EE", ok}]).
%%-----------------------------------------------------------------------------
run(Tests) ->
- File = file(?CERTS,"TrustAnchorRootCertificate.crt"),
- {ok, TA} = file:read_file(File),
+ [TA] = read_certs("Trust Anchor Root Certificate"),
run(Tests, TA).
run({Chap, Test, Result}, TA) ->
- CertChain = sort_chain(read_certs(Test),TA, [], false, Chap),
+ CertChain = cas(Chap) ++ read_certs(Test),
+ lists:foreach(fun(C) ->
+ io:format("CERT: ~p~n", [public_key:pkix_decode_cert(C, otp)])
+ end, CertChain),
Options = path_validation_options(TA, Chap,Test),
try public_key:pkix_path_validation(TA, CertChain, Options) of
{Result, _} -> ok;
@@ -1134,6 +1135,7 @@ read_crls(Test) ->
[CRL || {'CertificateList', CRL, not_encrypted} <- Ders].
test_file(Test) ->
+ io:format("TEST: ~p~n", [Test]),
file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem").
file(Sub,File) ->
@@ -1150,79 +1152,246 @@ file(Sub,File) ->
end,
AbsFile.
-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|do_sort_chain([],First,Try,true, Chap)];
- false ->
- do_sort_chain([],TA,[First|Try],Found, Chap)
- end;
-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.
+cas(Chap) ->
+ CAS = intermidiate_cas(Chap),
+ lists:foldl(fun([], Acc) ->
+ Acc;
+ (CA, Acc) ->
+ [CACert] = read_certs(CA),
+ [CACert | Acc]
+ end, [], CAS).
+
+intermidiate_cas(Chap) when Chap == "4.1.1";
+ Chap == "4.1.3";
+ Chap == "4.2.2";
+ Chap == "4.2.3";
+ Chap == "4.2.4";
+ Chap == "4.2.6";
+ Chap == "4.2.7";
+ Chap == "4.2.8";
+ Chap == "4.3.1";
+ Chap == "4.3.3";
+ Chap == "4.3.4";
+ Chap == "4.3.5";
+ Chap == "4.4.3"
+ ->
+ ["Good CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.1.2" ->
+ ["Bad Signed CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.1.4";
+ Chap == "4.1.6" ->
+ ["DSA CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.1.5" ->
+ ["DSA Parameters Inherited CA Cert", "DSA CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.2.1";
+ Chap == "4.2.5" ->
+ ["Bad notBefore Date CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.16.1";
+ Chap == "4.16.2" ->
+ ["Trust Anchor Root Certificate"];
+
+intermidiate_cas(Chap) when Chap == "4.3.2" ->
+ ["Name Ordering CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.34";
+ Chap == "4.13.35" ->
+ ["nameConstraints URI1 CA Cert"];
+intermidiate_cas(Chap) when Chap == "4.13.36";
+ Chap == "4.13.37" ->
+ ["nameConstraints URI2 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.30";
+ Chap == "4.13.31";
+ Chap == "4.13.38"
+ ->
+ ["nameConstraints DNS1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.32";
+ Chap == "4.13.33" ->
+ ["nameConstraints DNS2 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.27";
+ Chap == "4.13.28";
+ Chap == "4.13.29" ->
+ ["nameConstraints DN1 subCA3 Cert",
+ "nameConstraints DN1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.21";
+ Chap == "4.13.22" ->
+ ["nameConstraints RFC822 CA1 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.23";
+ Chap == "4.13.24" ->
+ ["nameConstraints RFC822 CA2 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.25";
+ Chap == "4.13.26" ->
+ ["nameConstraints RFC822 CA3 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.1" ->
+ ["Missing basicConstraints CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.2" ->
+ ["basicConstraints Critical cA False CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.3" ->
+ ["basicConstraints Not Critical cA False CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.2";
+ Chap == "4.5.5" ->
+ ["Basic Self-Issued New Key CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.1" ->
+ ["Basic Self-Issued New Key OldWithNew CA Cert", "Basic Self-Issued New Key CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.3" ->
+ ["Basic Self-Issued Old Key NewWithOld CA Cert", "Basic Self-Issued Old Key CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.4" ->
+ ["Basic Self-Issued Old Key CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.1";
+ Chap == "4.13.2";
+ Chap == "4.13.3";
+ Chap == "4.13.4";
+ Chap == "4.13.20"
+ ->
+ ["nameConstraints DN1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.5" ->
+ ["nameConstraints DN2 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.6";
+ Chap == "4.13.7" ->
+ ["nameConstraints DN3 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.8";
+ Chap == "4.13.9" ->
+ ["nameConstraints DN4 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.10";
+ Chap == "4.13.11" ->
+ ["nameConstraints DN5 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.12" ->
+ ["nameConstraints DN1 subCA1 Cert",
+ "nameConstraints DN1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.13";
+ Chap == "4.13.14" ->
+ ["nameConstraints DN1 subCA2 Cert",
+ "nameConstraints DN1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.15";
+ Chap == "4.13.16" ->
+ ["nameConstraints DN3 subCA1 Cert",
+ "nameConstraints DN3 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.17";
+ Chap == "4.13.18" ->
+ ["nameConstraints DN3 subCA2 Cert",
+ "nameConstraints DN3 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.13.19" ->
+ ["nameConstraints DN1 Self-Issued CA Cert",
+ "nameConstraints DN1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.6" ->
+ ["Basic Self-Issued CRL Signing Key CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.7.1";
+ Chap == "4.7.4" ->
+ ["keyUsage Critical keyCertSign False CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.7.2";
+ Chap == "4.7.5" ->
+ ["keyUsage Not Critical keyCertSign False CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.7.3" ->
+ ["keyUsage Not Critical CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.3.7" ->
+ ["RFC3280 Mandatory Attribute Types CA Cert"];
+intermidiate_cas(Chap) when Chap == "4.3.8" ->
+ ["RFC3280 Optional Attribute Types CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.3.6" ->
+ ["UIDCACert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.4" ->
+ ["basicConstraints Not Critical CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.1.26" ->
+ ["nameConstraints RFC822 CA3 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.3.9" ->
+ ["UTF8String Encoded Names CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.3.10" ->
+ ["Rollover from PrintableString to UTF8String CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.3.11" ->
+ ["UTF8String Case Insensitive Match CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.7";
+ Chap == "4.6.8"
+ ->
+ ["pathLenConstraint0 CA Cert"];
+intermidiate_cas(Chap) when Chap == "4.6.13" ->
+ [ "pathLenConstraint6 subsubsubCA41X Cert",
+ "pathLenConstraint6 subsubCA41 Cert",
+ "pathLenConstraint6 subCA4 Cert",
+ "pathLenConstraint6 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.14" ->
+ [ "pathLenConstraint6 subsubsubCA41X Cert",
+ "pathLenConstraint6 subsubCA41 Cert",
+ "pathLenConstraint6 subCA4 Cert",
+ "pathLenConstraint6 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.15" ->
+ [ "pathLenConstraint0 Self-Issued CA Cert",
+ "pathLenConstraint0 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.17" ->
+ ["pathLenConstraint1 Self-Issued subCA Cert",
+ "pathLenConstraint1 subCA Cert",
+ "pathLenConstraint1 Self-Issued CA Cert",
+ "pathLenConstraint1 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.5";
+ Chap == "4.6.6" ->
+ ["pathLenConstraint0 subCA Cert",
+ "pathLenConstraint0 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.9";
+ Chap == "4.6.10" ->
+ ["pathLenConstraint6 subsubCA00 Cert",
+ "pathLenConstraint6 subCA0 Cert",
+ "pathLenConstraint6 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.11";
+ Chap == "4.6.12" ->
+ ["pathLenConstraint6 subsubsubCA11X Cert",
+ "pathLenConstraint6 subsubCA11 Cert",
+ "pathLenConstraint6 subCA1 Cert",
+ "pathLenConstraint6 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.6.16" ->
+ ["pathLenConstraint0 subCA2 Cert",
+ "pathLenConstraint0 Self-Issued CA Cert",
+ "pathLenConstraint0 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.7";
+ Chap == "4.5.8"
+ ->
+ ["Basic Self-Issued CRL Signing Key CRL Cert",
+ "Basic Self-Issued CRL Signing Key CA Cert"].
error(Format, Args, File0, Line) ->
File = filename:basename(File0),
@@ -1340,3 +1509,12 @@ 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 }].
+
+crypto_support_check(Config) ->
+ try crypto:sha256(<<"Test">>) of
+ _ ->
+ Config
+ catch error:notsup ->
+ crypto:stop(),
+ {skip, "To old version of openssl"}
+ end.
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesAnyPolicyTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesAnyPolicyTest11.pem
deleted file mode 100644
index 8f00499440..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesAnyPolicyTest11.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=anyPolicy CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfDCCAeWgAwIBAgIBJjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMYW55UG9saWN5
-IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGOGYJ7e91FozKo0McZ6T1
-zTYa4IXfHqChuqKgri79fgKVZZsKwOyoHWJfsLn6ClknlWE9NJATHZfQp8GfLy9k
-MbdXEKgZQoyWOV2Q0s37ez+I4yuR33JZpxtpKqYQW2fKdhhOdR+DcLwgWUJ4s1Gg
-KCXhxYnC4nfSho/lgR3h/QIDAQABo4GFMIGCMB8GA1UdIwQYMBaAFPts1C2Bnson
-ep4NsDzqmryH/0nqMB0GA1UdDgQWBBQ+s56i5EOF+2dAMYYTm8Zh7YbV4jAOBgNV
-HQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAAMA8GA1UdEwEB/wQFMAMBAf8w
-DAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUFAAOBgQA8JxYIM/manOaFxyoO3y+p
-th/jCQFiR6fDo5mhYEOjZuHDWdejSZvNtbpPfNnKmM6W/qI57hZBgVDil9P/CMSi
-wYPJvKl0ofonnhhPd+uMPhJENho/NhWyc1cgruABceTtBP966dRIhejL3K7SewrT
-aV+IWdHVMKREjOXtHakoKQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=All Certificates anyPolicy EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=anyPolicy CA
------BEGIN CERTIFICATE-----
-MIICfzCCAeigAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGFueVBvbGljeSBD
-QTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGQxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE5MDcGA1UEAxMwQWxsIENlcnRp
-ZmljYXRlcyBhbnlQb2xpY3kgRUUgQ2VydGlmaWNhdGUgVGVzdDExMIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQDXI8MbFkMJTmeIdP1EpYg8qYdNkQRq1yNQYMHH
-9TxFgw3L7sCGGxJS6PN4SS67CdnNZKNseFT+qAIDIbBw+p6uuAB4PWZEireOFo+s
-PSdbG2Os76qFi12SpIniE64W5aSMzmccMf6RqzuqUROYH8wOzk8w6y+RI2qnkqDx
-0HxJrwIDAQABo2UwYzAfBgNVHSMEGDAWgBQ+s56i5EOF+2dAMYYTm8Zh7YbV4jAd
-BgNVHQ4EFgQUC8LFyye3gbbbFeNrasBg1Fq10JYwDgYDVR0PAQH/BAQDAgTwMBEG
-A1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQUFAAOBgQAmASNJNMm+5XfUYE/I
-IhtOmsbGvCrIWyMyhcv7gosAMSsXYU+8CzWpkjP0zS42rEphyqP8zUAWjR/BqUJV
-9uwenHlpNeVflKgq0UVqYeoqc+afpvgLe+2o2Fe81Uz2tQ+LjwRQCm0/dhEVeZ4B
-JutCF8LtmT3hv2RlWp5v1mmG4w==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=anyPolicy CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3E:B3:9E:A2:E4:43:85:FB:67:40:31:86:13:9B:C6:61:ED:86:D5:E2
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2a:c3:2d:e7:f3:91:d6:67:7b:66:88:f9:22:e8:64:c9:80:a2:
- 88:bb:d7:a0:84:a3:75:ab:d5:af:72:d0:fa:1f:ed:4e:42:29:
- 62:23:32:25:59:4d:a3:45:c1:bc:ae:37:c8:b2:d0:79:00:96:
- 84:0d:7d:a2:f0:58:d7:c4:99:64:cc:4e:8b:5f:88:f6:6f:cf:
- ee:39:54:34:8c:7b:0f:e7:43:0b:26:d8:6e:c4:f8:6a:ed:80:
- 9a:47:d3:38:bb:82:9b:fe:bf:6b:01:6e:c9:e7:8f:3e:cc:b1:
- 4a:a3:df:86:3a:2d:ca:62:6c:dd:27:a8:51:c2:b4:3f:c5:ba:
- 90:6c
------BEGIN X509 CRL-----
-MIIBOTCBowIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGFueVBvbGljeSBDQRcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUPrOeouRD
-hftnQDGGE5vGYe2G1eIwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAKsMt
-5/OR1md7Zoj5IuhkyYCiiLvXoISjdavVr3LQ+h/tTkIpYiMyJVlNo0XBvK43yLLQ
-eQCWhA19ovBY18SZZMxOi1+I9m/P7jlUNIx7D+dDCybYbsT4au2AmkfTOLuCm/6/
-awFuyeePPsyxSqPfhjotymJs3SeoUcK0P8W6kGw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2.pem
deleted file mode 100644
index ea336fce35..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2.pem
+++ /dev/null
@@ -1,107 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=No Policies CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICWzCCAcSgAwIBAgIBIjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEIxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEXMBUGA1UEAxMOTm8gUG9saWNp
-ZXMgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWH/haSHmzYQAYFLKMA
-cbwROk7OaY3N6TMLQIz4yWrwGzpy+kiIDZ2xVPnyHRHp12VlAI5u78kQKAivhpNw
-ovjgrUmE86zb3/OOa341tubElI6Y9G1Y1tnzPCK+hi1vjrHAHr1Glf8VOgZ9ijpU
-SjXOsw5pFlz22uc7BRI7S/K1AgMBAAGjYzBhMB8GA1UdIwQYMBaAFPts1C2Bnson
-ep4NsDzqmryH/0nqMB0GA1UdDgQWBBRTwRQlfeVbPleR+JYOkJ5dxiWoujAOBgNV
-HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBr
-G1ayCZm1VdyAqi1JuxUTt6bQcd8iNR0vvnl49QzjKgCNRqNV69RCH0U4ZST8D57t
-TVN8DJITlnH+Kbid6OWcgkb+vi5C0SPLPNym18RVzKNQtR88lJCByvNbx/CprRYl
-EfsMrs6FA8loVY0rVrUpEsTjVxyDh+fb8GZ3CAJIng==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=All Certificates No Policies EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=No Policies CA
------BEGIN CERTIFICATE-----
-MIICbzCCAdigAwIBAgIBATANBgkqhkiG9w0BAQUFADBCMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFzAVBgNVBAMTDk5vIFBvbGljaWVz
-IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQDEzFBbGwgQ2Vy
-dGlmaWNhdGVzIE5vIFBvbGljaWVzIEVFIENlcnRpZmljYXRlIFRlc3QyMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbFHIGRAKQBl4eS/EWvFaVcb/7H30je7Yf
-LmXoIYQGeWJZQfXWSsJyXyoaMhf4uLonxy8mi1Ap8vy3Fqc9b55Cm48xatNCao6D
-W6YbSQu9hiSXCMxjXWnrYfi62KywO6I2y5JbT0CZ2PbQO0lFXYKPaTFDKzgf9l4x
-ppvlkUQdsQIDAQABo1IwUDAfBgNVHSMEGDAWgBRTwRQlfeVbPleR+JYOkJ5dxiWo
-ujAdBgNVHQ4EFgQUy5AB5Gdr2u2a+KXtJZFHFSHyopEwDgYDVR0PAQH/BAQDAgTw
-MA0GCSqGSIb3DQEBBQUAA4GBAGk2l02zPeeK5Xca7UysnHmcjV08jAnZw6WqKJlS
-ZK/upXnIu/i4JXjxhC/aBpFDs1foGPEPb7vPwJBq6psJ/qvrL3FxzWnmp08P4iUP
-c7e9vxXYaMIQC3duKeV6SOn5VrpSPYRfchw/i70FJ+QCw9xAvNZ2X45Pzi9k9xUg
-VfLw
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=No Policies CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:53:C1:14:25:7D:E5:5B:3E:57:91:F8:96:0E:90:9E:5D:C6:25:A8:BA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 32:a4:9a:ca:5f:51:9e:91:db:fb:8a:0a:85:9b:64:c7:08:ef:
- d5:17:43:34:7b:ad:53:90:4d:d1:43:10:f9:47:88:de:f3:78:
- 67:2a:3a:4b:0e:5c:1a:a5:ee:19:b9:ef:f9:eb:3f:f1:39:2c:
- 31:ab:e5:14:a7:90:8a:87:71:c6:78:a1:75:df:84:aa:3a:68:
- 37:8a:ba:65:79:1f:31:93:8c:4e:6a:f1:1c:3b:fb:68:79:34:
- 55:5b:42:55:8d:f3:2d:9f:f6:47:8d:64:6a:02:84:0b:97:aa:
- 2c:c6:96:18:ed:b3:b1:a1:62:b4:73:40:83:00:1f:1e:96:ec:
- d2:ff
------BEGIN X509 CRL-----
-MIIBOzCBpQIBATANBgkqhkiG9w0BAQUFADBCMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFzAVBgNVBAMTDk5vIFBvbGljaWVzIENBFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAWgBRTwRQl
-feVbPleR+JYOkJ5dxiWoujAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQAy
-pJrKX1Gekdv7igqFm2THCO/VF0M0e61TkE3RQxD5R4je83hnKjpLDlwape4Zue/5
-6z/xOSwxq+UUp5CKh3HGeKF134SqOmg3irpleR8xk4xOavEcO/toeTRVW0JVjfMt
-n/ZHjWRqAoQLl6osxpYY7bOxoWK0c0CDAB8eluzS/w==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2EE.pem
new file mode 100644
index 0000000000..0c32ce2edb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesNoPoliciesTest2EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 2A D0 22 62 8A 0E 0C C6 9F EB 81 2D 56 D1 0F 7A 3D B2 F9 79
+ friendlyName: All Certificates No Policies Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=All Certificates No Policies EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=No Policies CA
+-----BEGIN CERTIFICATE-----
+MIIDfjCCAmagAwIBAgIBATANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEXMBUGA1UEAxMOTm8gUG9s
+aWNpZXMgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBqMQswCQYD
+VQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE6MDgGA1UE
+AxMxQWxsIENlcnRpZmljYXRlcyBObyBQb2xpY2llcyBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6WDyHxhLZpA4ge
+LxU8BbeIOR03CkUXr/Vvnl1X/ncT1gvBBBnQ7Po7o90+gGpGzBPMjif4gMSkUJ8q
+Q+R0STU5SIHBBPl3mxEKU6htvRX47h0hvUzRWKnN2lvQyzD4GkwQhJC7Tv2TDLCr
+tVm5E324xPUAmBYLnbILJ4yQjLXWIa+usF0r1rm0L77cjkVz7HQp9hT/VAOEof8u
+/TWuHTr6CoPEJQLsybS6/tP9WbyD3aPS0F/X//QGM2jwbVVcwlkuodxKrFz5DaMb
+D4EaG5cr5NdDyjbnd71OUXG6j/LuQYuRb2fmXo3YQE3KK6/iStbqEudSUqma7DdD
+7PhI3McCAwEAAaNSMFAwHwYDVR0jBBgwFoAUQiQD7aVLdpyXmFx06gU6G/w15Jww
+HQYDVR0OBBYEFNpNr/S+ZFlUsYAeWIckHljqxZp+MA4GA1UdDwEB/wQEAwIE8DAN
+BgkqhkiG9w0BAQsFAAOCAQEA0xqFOkeCtxlsvCwBTB4pfZNN6qpoRnJFjYD7vmaU
+6XJQAO2EUUCVefK8eYoxPYwgbg2uTYk4HtTTF4cbvsr04hNjh0rBm7F0X7BlyvcF
+TLBW7FEk5aAKjtNGca9kJw7aPo/5vaDkPjnrwTwkUBzEfRveXJE8JqS7KIL/0+SS
+QCNhqf/Fn9KOpcwhQRKZXLcLlvVGtAqkexNM8ZNWuSLidt1Aeihudf0h/dC7g/fx
+NTGfhBSvoKVyGS3AdadQvv9Ce3l2IY3P1NAczdaY/RY+gE2ccmEiRSc3IXETiUXj
+gyzsUXK129XEY9fOQ88ns7RLifh3JBp4NhIvCx0oDWcezQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2A D0 22 62 8A 0E 0C C6 9F EB 81 2D 56 D1 0F 7A 3D B2 F9 79
+ friendlyName: All Certificates No Policies Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F93E81F0FC4D6CD1
+
+8/7NnGtFRy+0fJgWW6hMw8LZ4Hm65YTBb/+ft8ET419gDdlc4exP6dWbvUNTx+3n
+xM59XpMjLFRFKhM72sBWc5ORymftUErbvWz6Mk2Uij6V2kVGUZ9GyCwQIkcixem6
+BH9vjXvu/v8R78fYfXbwhRFLmDxVs7d+J08a4vRR5bZkNkVHycGPBPojQYQ2AUrt
+IBgn5l/HY6tMMNDOBe3VGXCHesGcnsxnjmTcYhG4VTAFchZj6NqSwCmEuV8RDwCd
+odkN9BqFvbYp8uuBT87THx8+QYYySFmMfSlpJcTibQVkvCEyBSF0lccAeqW5WPCW
+6l4ACED5lBBoVzxYERtfiEE1i1C/c0tMYahGDyRtjX5khh3IT2WDLbt0ktaBBViB
+3BbBv7pkJEyMp1SjjFXwXiBwOqEWqEjGgnQB9LYafpjxSn7ZwGZ8/ihnqBUUr27Z
+o3TmQV4JV+Ar4/sSz3vjg3/vKgjCymjLKw0hAB4fodJN0CAdTeK6gPhFp4gjcu5B
+a4sc4loF6xKf5YCOIGb9xWZLi+w4M5Yp6wWHI6KvNTC8Pp9/dt+7F/hiZ7q1YeG5
+YN2LDHmHgCjMAGMlScJ0+D/fgCFrCA30BkOmzXPRaudCSg75zSuBh/oYPkLBDOof
+ko4zs4TFplXqL1Omi25H2h6eF/0PBo8DQL6KYzBrCvzw5hLcrAY3cHRCLMfBUY7y
+bE56+LTb53z/dGK/2KfjgdTGcimGe5AQ6DQTFnelqDNzODXjnc7x+Bt5ngK16N/H
+cEWE5IUvmYf66aUGiImP4cyvDq4gChNj8AUxh2HpXYN9kYGz0qjPJyS8jsvN0cMe
+SWN38A8jXCc63Di6Bqj8JLTJ0kSFnTyiu1tFm2EDCgLT5JLMe8dkfKCX1eN9vvZQ
+JG9iMt0SMm/kNnxKWP/aV79W112FYZKjkceus6MUDkxqGXbcmF6TRSEFl7E2Nh9t
+ebEHGznMVUef0v2o/ksggndfQZGYrvPJZ6/rBiWA85FHCerbtATm2JuIP0uuGpLw
+Hp9xZJTo7Q8sMvP7KCKAq+3c/c1gRgggWsmGvLhTNg1Y2InGGVGcF4TA5PfNxHrM
+XRFwqMwt7hEZpzJFzuc+Q2QwbUcjIgTmzYgPc0u22L7cgB7zykihmuqHNtA8jZFn
+dEVffyO6kPM579Ebrb75d3QUtY8mJXzc4ZFczV9sXlzxC0MctvB2INUfgYwTBHqh
+kNv1vh0HvXEkKUCMmmvEMY+dmscDZN4HzLfqRsOBTbNQPIwOxj4RnSco1tiz/JxM
+EmIrjUvX6/5FrHdr3IeRdECO2+/oGO9MYj+siqKwnPsqbIcX1Agz2h6KGJYxXPPz
+IoTM8g7AKjL3z2zkuckW47EvH2tJgBi3GXxVMUzOxhZKrvTVyA4UgNq5B5dZqnJL
+JOK7xlbGCf1D4hXNG8Hzv7Gf/uesog2pUt8wEApRAUDxXTWrhUQyXfRkkc9FDWBy
+36QCTtRt4EE2kn+TLSbtAoVzHXb5lxBdHEoQ+57yXA9tLxDUgNE79c1LSi1AqRdD
+27CN5LFKEEPf1RzHhrlc6u9KVYke1Z+PhXHE4x2/RlLLmzTLmDNcdg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10.pem
deleted file mode 100644
index 62412e9602..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBJTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPUG9saWNpZXMg
-UDEyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5unCMuN8PuVFWbqxO
-/wnIQsciPiEo1GoKWjM6+kb9l3h6wWyWYwmst2c158qcJLY9PxaUMhqQd/SY0Tt9
-WlHXVcE8rMoWSGmFxfK33UpeCtqwz9ugPSWwZkqx2lI/0ozQXgjYb0J9/EoKw1O0
-CxxrdQdPQkyLD4Uxe87/MlpzsQIDAQABo4GZMIGWMB8GA1UdIwQYMBaAFPts1C2B
-nsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQA42XpgdSGuccd5/MzOQZeTBGl+TAO
-BgNVHQ8BAf8EBAMCAQYwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFl
-AwIBMAIwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GCSqGSIb3DQEB
-BQUAA4GBABX9GMyAC90FH8BvpnNh6SDn2MIT7iINc4/9u64d1dxEhqogqcR58khK
-btHyx8YrgbCcqUNS4Xs7ckW5k2VNAd9dG0Chc0uk6rwkv+sD1/zJi8LIGd/3cFjk
-biIVYqPxb7WpKqo97V+43tMFsTqJNBSh+6W14vlP55+Ep5IlxcOm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=All Certificates Same Policies EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=Policies P12 CA
------BEGIN CERTIFICATE-----
-MIICmjCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD1BvbGljaWVzIFAx
-MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGgxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE9MDsGA1UEAxM0QWxsIENl
-cnRpZmljYXRlcyBTYW1lIFBvbGljaWVzIEVFIENlcnRpZmljYXRlIFRlc3QxMDCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmrdM0DTddXChaxuvVK1/9AmbK3pj
-B7nrBT7FrZ4f+6sp0e/vN7kCNEiAaRq1BDUFjyiesHIoL7gVKw96xoYTQ1qdCGZO
-04GFQtVjtBx8SZCDsvjWgaXxs2BPj3ooNV199aMCiKTeNPm1TwL2zpmGRBaV5As8
-X8eCNYjiya9c6jMCAwEAAaN5MHcwHwYDVR0jBBgwFoAUAONl6YHUhrnHHefzMzkG
-XkwRpfkwHQYDVR0OBBYEFMb2N25TEoHRRp8AmP8/XLXv9HDaMA4GA1UdDwEB/wQE
-AwIE8DAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjANBgkq
-hkiG9w0BAQUFAAOBgQBM+wZzcjByDVKWb9MADcwg0VTmgmhOhSmt3fqhHagC9q3G
-ZY6+OWkM6gCdmw1JBr9JRTHPl1uo/W5dI4OVIupjsct4ObPWx1yn29VM30lyaYDR
-iBhgjOp5tonCixdFbt7pMnviPwsIDKdQLQz0k8m7d/au9BVHVSlyDoqm0I0uSg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:00:E3:65:E9:81:D4:86:B9:C7:1D:E7:F3:33:39:06:5E:4C:11:A5:F9
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a2:21:e6:6b:0b:99:66:79:2d:86:a7:9b:cd:37:9b:4d:73:1f:
- df:91:63:c4:de:55:15:53:b0:32:ac:c8:3c:bd:96:aa:ae:c9:
- 4f:b2:7c:9d:40:d7:f4:5d:99:8e:fa:2b:44:2d:75:ef:01:38:
- 86:c8:59:ae:e4:62:e4:83:b4:73:03:34:d1:7f:52:bc:3d:bb:
- 77:7e:7c:c9:41:09:4c:08:4f:a9:7f:d9:d9:0f:bc:46:9d:05:
- 70:2f:66:0b:d4:0d:80:ec:11:83:4e:1b:90:95:ad:86:02:77:
- e8:19:aa:a6:48:29:a3:9f:36:c3:ec:9a:f5:a4:9a:0b:f5:11:
- 1d:72
------BEGIN X509 CRL-----
-MIIBPDCBpgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD1BvbGljaWVzIFAxMiBDQRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUAONl
-6YHUhrnHHefzMzkGXkwRpfkwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-oiHmawuZZnkthqebzTebTXMf35FjxN5VFVOwMqzIPL2Wqq7JT7J8nUDX9F2Zjvor
-RC117wE4hshZruRi5IO0cwM00X9SvD27d358yUEJTAhPqX/Z2Q+8Rp0FcC9mC9QN
-gOwRg04bkJWthgJ36Bmqpkgpo582w+ya9aSaC/URHXI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10EE.pem
new file mode 100644
index 0000000000..3db8e63cbc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest10EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: ED 37 7A 96 E4 F4 B9 50 1C 32 6F C3 52 F4 15 29 25 8A CA 1D
+ friendlyName: All Certificates Same Policies Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=All Certificates Same Policies EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P12 CA
+-----BEGIN CERTIFICATE-----
+MIIDqTCCApGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPUG9saWNp
+ZXMgUDEyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowbTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExPTA7BgNV
+BAMTNEFsbCBDZXJ0aWZpY2F0ZXMgU2FtZSBQb2xpY2llcyBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0MTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQIvsOjHjY
+csCDpWm9SJNK2Lwz8/4bpvlcdaG59lROqyk6OL+0/Rd214G74S26m6BrgZuzoLbH
+MlAaCjdFDbUSjh086jFDMgXHwdud78f442+V3ms02gqmijFPvSsOWWyRu0BzTz0P
+bW9IWYtIAG8DDqGflBISatXkxS8wQHCuZdY/x+XjjISn7oSOjPamfdoqT5jEThof
+50jzBxDEdW1vbjU4afAwQBD28t6fZCdCG5kUO1uZ3CED0R44ZV0gajS1Oah9qvrH
+jeCFGGRmoi1biVzNqe9N9tyqw4PWZ+TnzANsaf+InI09mZGyPoiQXB6mbfJFnuCD
+ZQ7AcQiP1VPbAgMBAAGjeTB3MB8GA1UdIwQYMBaAFNhfNeKawTcqJs6DzHMOcBUq
+OuIxMB0GA1UdDgQWBBQKlt4EYF5FmsVHFjO1gRk49P4KtzAOBgNVHQ8BAf8EBAMC
+BPAwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIwDQYJKoZI
+hvcNAQELBQADggEBACu8kiAp80ujcBGHavjXgp+HpVSQTqRzTLKbf0EFFib6KedE
+sT67cvLjuTZMcPmwYHnUjBk/KGdyn9IwetblMTj3hueKNx1yKXfYYNVmE13KPPpN
+NcPe4Eal9g4I2noPVt8Eg3SgNIghPFz3XJQNGjN5hMdhmcQfeaEJe1Mlwv2cdgs3
+D02kpjI/KGca9whyDpE0jpu77gkO4ZmRXZxaGe8i35xaRrrs124Zhz0qtJn7iIaV
+s7ouezKkvE1UinCY2pdTZHMTs8LSklBE/IL0Ojwqpt81FptUFMihOaMtMrg01E/D
+rahtaL5Nbj8nVUGlVwiEkUy1CII3ALs50xqw8gM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: ED 37 7A 96 E4 F4 B9 50 1C 32 6F C3 52 F4 15 29 25 8A CA 1D
+ friendlyName: All Certificates Same Policies Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0EB98A807DC3D399
+
+fhnzBwxtkklORe+Yh4iudRuENOFlYa9T0GStebQUNLB4fpdxlVUWKCd6hGDhVdAh
+xrTDyXWAE/CUquhCUphGt3vhZgThk03pYX4MiAGyC/Dyw4VGSkqujc+P/3oMpWyI
+Z7Q5yKYxmXIPo0ueQMXL9gMJjOJfmHweVMEaGZGozIh0fNO3QLC8X65yttS9xxT+
+dMG+3o5B+wRcwFMxe5i44FbGiDHdarsaHTYrmxiuWgsQaxD5iSM4TSXfFReAerkG
+3/M6GdeHGbyd/ePTzbLY6APLoj3zREmrRlxPdV+pqMXp1TJORyoea3Dwwn8tzlEC
+juh/7dvzeUCX3yFZmO70nyC3YY3pVHE44yj8tx5JswNvQUWnXPK/imvJbRgs7RfH
+syU6uFD2nOrHa9DoKNDUENZuSt8Ck+6xpLwUfgrzE0IcP0S+o7xC7lfs8KfjbkgO
+CtMxS8AacRkfv5GQCDcS7aT37aQz1Z3chZkjbacW/FljDupK6FZBmQo/KIvrRZWQ
+KhaTG7EfLEwDGzHQB85dAyTcacNRzpZg0tccdfBFNzj/52vLVWm+ng2pvR/TudaL
+M5xA9I6Ykp5VNFR5jwNwNvOhxQ7T2I4dfTXbhFW9VgMJYTqoTxtdt5skL8mSiRHd
+24pnV+B3Io17jPhuNXPpJgtbCFd+H8Nx24yo9Lo3L/lAQvgvwuAD8rrAnSBVY7mG
+vXuabzh93vgEt6tL4UJEVBMTIEuclcDTsSPPWVAcdcHqFFbXseQwJDGRSHRRMIP7
+UAb71S6jx0CBeO5igiIwpPBpfmDujskCo6CihN9fxH2TqaCvR2dYaE/V9qj0tBWb
+nze8mdsTfo0l2zKp5F2EWfnE047vDRS2M6fCS1hCIkvN1DLsDcSd19dafG4SKEgM
+lHeY6wf0cnus/fhK6Z7yaG6mffHALPHhZBk4yGV8pwB3413DCG/0cEHNO4DSSQBB
+113ZUUcnzeSvjYYeUV2LHRPi1+bc+Go35j12PZ1xk3wQq23yPfcJdGdNzpNvMM5g
+F2KMJhdJXfZoDgqDpiS0F/UNnivYl0/IDmcdalMhc9NATBtDSQvSVvCcDlKeo7QK
+cc08JwoBN1aF7XDCqb1fxr4GZDk6V5qgRFOAEXm83QjE9ADNJ3tS/1u6PwEAebWs
+KJjE4EvYG3bcADvoyoU6I1BbewUtHCxEvorYuj0t0wZxodnOew9Lx7JeDNFQTmxW
+PB10T16LEu4Myw+/W3zZ/oGOJsGfVZ/f0eSnkrfHMMGiBg+BYpliyZvBtrXTkGLA
+7yAFUwu0yiIfpt3y7aJjjYyujyKDqKuMz3nSIoAANEVHyGdlMIknlxqsf1FVpM7L
+muN46G5nn5howKX52NPe7zyEb61NwkalDHriVl6a8pImGv991ZMfVjavc5ODubXf
+sJl+hTCejauRGf878kyomrb/ullIz8t2WgaAePfKvw4cGsmZ2N3kqfjKYWg7K/gJ
+jC4HrmnRc/Wak01ZVgRL4hk3R2AQu1lklzdSBSZKO3rbzIOe65qsSK/Bh2ViA7y2
+hUlzqaotDhjZ21oOa6+wfzYx0oe/I+jzmOvV7Qb8XyVJWS4BDFTC1ZLLS/SyIYoM
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13.pem
deleted file mode 100644
index 888f8c117a..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P123 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICojCCAgugAwIBAgIBJDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEQxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEZMBcGA1UEAxMQUG9saWNpZXMg
-UDEyMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuGtVArq1otVEuN/s
-xR5XSOEfVzIms1FiprO4UReYXUDbKzmCYC6YypbEnOP2JpLQOPwAfVqLL8FV7xiS
-o+HmK25R0aK9nQGFUPX0U9o4b5NRcWFAoYBAF2GOFBNqGF6d9wBFPlijGMT8nWr5
-ahnujYSC1Emy88N4hkp1fj4o7yMCAwEAAaOBpzCBpDAfBgNVHSMEGDAWgBT7bNQt
-gZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU0L/Nm9/xkf2Ch1oQz5Cvi7zyxcww
-DgYDVR0PAQH/BAQDAgEGMDMGA1UdIAQsMCowDAYKYIZIAWUDAgEwATAMBgpghkgB
-ZQMCATACMAwGCmCGSAFlAwIBMAMwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTAD
-gAEAMA0GCSqGSIb3DQEBBQUAA4GBAHcVVBwhebD5vRKleXMh71kleQIL8QOQFpHM
-jVYS/KJiBsVUTebOeONSU0cuPmzomEkpLyYPz8cDroidExtxGEpkKgYBGi1c5ext
-cDUGFsTWENTFFWjZ7xA56XUtGd8alXJfY0v6QSHqoYFosJvoqU2bjX6jqQVK5HbY
-kko1SxlW
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=All Certificates Same Policies EE Certificate Test13
-issuer=/C=US/O=Test Certificates/CN=Policies P123 CA
------BEGIN CERTIFICATE-----
-MIICqzCCAhSgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAMTEFBvbGljaWVzIFAx
-MjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBoMQswCQYDVQQG
-EwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPTA7BgNVBAMTNEFsbCBD
-ZXJ0aWZpY2F0ZXMgU2FtZSBQb2xpY2llcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTMw
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ6RCve4HAIbl7RQiw7tPY3IJ0oT
-KvS2jsUu4eNuzThRoKW0cWW3N+Jk1rkqgaaebVodXrb9cuDFONWRL0X2DZazb5h/
-4FX3obShqywkydsz7vBoixmRXa/oKtIa78h5zQTSDPR0sJeWIikOUJZMIJv4CNw1
-Pwvu3Y3i9CwT6m2fAgMBAAGjgYgwgYUwHwYDVR0jBBgwFoAU0L/Nm9/xkf2Ch1oQ
-z5Cvi7zyxcwwHQYDVR0OBBYEFGqUba1DKQxc60sgeqLAqyOR/22bMA4GA1UdDwEB
-/wQEAwIE8DAzBgNVHSAELDAqMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjAM
-BgpghkgBZQMCATADMA0GCSqGSIb3DQEBBQUAA4GBAAd1diIEB4YaH7gH6DO1vptE
-G2YpbuvISfPDhWjrLI/sLSJTH3l+kC/GE4FDEHJ0Rc76la5gyUbRwX1zTZKHGyxx
-NhuE3i0XkrAlR6xRUJRcb1SgD7JqMzup7ZuFP9h3+txi71G33fMStCxKGa6ijUKd
-LTzImFXGxbWm6SZujuyJ
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D0:BF:CD:9B:DF:F1:91:FD:82:87:5A:10:CF:90:AF:8B:BC:F2:C5:CC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 81:c2:63:b3:65:bd:c4:2d:98:7c:e0:85:dd:5f:07:d7:b4:1b:
- 7a:64:a7:7f:60:3d:62:3a:70:af:d5:97:23:23:9a:48:e3:b7:
- 8b:c0:3d:43:c1:66:e8:24:db:ed:a9:ab:0a:70:51:d8:7d:65:
- 92:ea:e9:6f:cb:96:8e:3b:cf:94:e9:9c:d2:27:54:29:8c:81:
- 84:1d:a6:22:65:85:46:70:07:da:1d:e9:79:9f:e7:3c:4e:96:
- 1b:11:d9:08:ec:f7:95:15:c9:db:8d:a7:17:16:3e:76:bb:41:
- 98:15:94:b3:1a:19:6f:1e:dc:10:24:c8:ae:bc:38:93:c5:04:
- ef:9d
------BEGIN X509 CRL-----
-MIIBPTCBpwIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAMTEFBvbGljaWVzIFAxMjMgQ0EX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFNC/
-zZvf8ZH9godaEM+Qr4u88sXMMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AIHCY7NlvcQtmHzghd1fB9e0G3pkp39gPWI6cK/VlyMjmkjjt4vAPUPBZugk2+2p
-qwpwUdh9ZZLq6W/Llo47z5TpnNInVCmMgYQdpiJlhUZwB9od6Xmf5zxOlhsR2Qjs
-95UVyduNpxcWPna7QZgVlLMaGW8e3BAkyK68OJPFBO+d
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13EE.pem
new file mode 100644
index 0000000000..286627830f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePoliciesTest13EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 98 55 92 32 22 6E A5 AD A2 4F EE 02 A2 E5 67 24 74 DF 79 20
+ friendlyName: All Certificates Same Policies Test13 EE
+subject=/C=US/O=Test Certificates 2011/CN=All Certificates Same Policies EE Certificate Test13
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 CA
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEZMBcGA1UEAxMQUG9saWNp
+ZXMgUDEyMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMG0xCzAJ
+BgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMT0wOwYD
+VQQDEzRBbGwgQ2VydGlmaWNhdGVzIFNhbWUgUG9saWNpZXMgRUUgQ2VydGlmaWNh
+dGUgVGVzdDEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuonnfN9t
+4ddPZ+ia26RVmETsLKghhyuChxjPOzey0QTTUvM7qpHFYdIxV33GrQo6A7gFqhHd
+fWyAk0/BneTtf7NMzEVpBhgN/ALibFRF+gtg+9+PRECBOBTE4/Fn3NTVei0br+vY
+IHq3/S1YmJfbaT75IMLxJLevjBaIEg1ZAC8e42BydhD6yOvclRCtQaTmlVMPAF2w
+16xXisHhOlIdkmoTvVUNsggM7sfp3Mh7rdUsUgZTdx7lN7COEYIo+i3IU8YqOfeo
+nonwyxPR9p+vHCCau0445QquJxq6BBiIIFBqyEKPbw2y0a5tXWu9HAqkWSZD+1oJ
+y15//w8dWuiHwwIDAQABo4GIMIGFMB8GA1UdIwQYMBaAFIwoCtoNCRRi7j09lrhx
+kxKJ6uhjMB0GA1UdDgQWBBQV5I2I9FFatmEJLjYrRhl3ENmoajAOBgNVHQ8BAf8E
+BAMCBPAwMwYDVR0gBCwwKjAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIwDAYK
+YIZIAWUDAgEwAzANBgkqhkiG9w0BAQsFAAOCAQEAebUg/2b+Scy+m8LoFzpVGpLL
+81MsDH+Ft+90ub0m3BPmLhy6M+pL6I3w4roiOqdnbokcNWiUKLV+0aGR0T+fLw7H
+mhltaORuZHTZAPZq3X1GwRS80r7kPBJDCmT5sf0DrxMg9e0tpJSKu3UQrONk8DyH
+z64u6w4tlg702fdr2VZv4VLlUtLkx2cMPwMK+ZKJ+FBK07z/69EroGdakfaJqMA8
+SW+VOyqg+koUo35DUv1n/t8/DaE7rNux298Ii1JZj8umtVmIet4sHBuIf5Y4nmYD
+KJxml+xOmIJ2jXfAb0A0VmpGg4SYCcUTH4gWKA7oPAYnic4llcUeM71RGKzuoA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 98 55 92 32 22 6E A5 AD A2 4F EE 02 A2 E5 67 24 74 DF 79 20
+ friendlyName: All Certificates Same Policies Test13 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6598F90C651D7B14
+
+gLVeHzEcRzOUseMCKz1TMOnYdSgh9Vc/Miav9QDr3v24THseAgHafvP/HSB4YUSL
+O83vdnoePDKsNavnbhgKIeW+c6N+ByqWGbuerECn6m41aJJ5VSoch6RwMva8W1T1
+DiW1WR1mqU0heCgd6iMP3ja+oL49GQdBcT3RHBT5Vj+eHJaruOTCGMlG1q2Z5vVy
+Ofj7ZXIx42RP5AkLRTXXTORpLqnG8E0wA5u+S3EYDpEecrjNlq/lejCgwEWh2++U
+ODFw4FqZ24v03RLqpzeWQvT8oCrLv/HuZUqeGHK/PBCMNzRkNHsF7E78m2SdhbCo
+ysIGCwfZzHk+yKf6+xktAfDFf1XpFZ4gEfjddfH/IsKLMcrAwLQnqKUpN1eUvG6l
+JUteVwwpxHIP46ZdOvMHExYp82uGFE92yyGrJS/3z5JGISpLqh1PqA5lhqd5a5eW
+7p6qdcvwzSuBPLVKbwgKE3QROHNjvmCmVDeY/U+U7bYhZ535Zq5vdm1ZLpclhcP9
+qE1XOGl+Nf1nnyGEk2ITECnZFSdsUo+HdSA27qCqQ6IHgI1P6I5vGCLWuuE2OQ6N
+EckKeOw+NXKUxqDJDCXhOLa2UMDYHopOO3hx4MjMg5d0CZHv9Dbc11sPnpENx+dX
+XO2qJGuhQV2a1O0B2hFMGkDAUkcSoFXyWf8kJVh5s9Og8GDP3IeskUzbEKmhBsb6
+5nKBq/OX0dZFuObEBiDuG069yGlxSut8L5d3agB8F965efezS/tJmAjfK+JVXxGw
+Kq4rE30aOhxVybbUrJYCLsq6g4GmRtPGxWyCGrteJHSr6iMJwU8IqpKShM3XV+KD
+I/8V5H+3/QoF2BLiz6HaP+uwQZmoXX1/5QCvzqArLYeBGx8ucoPDuAnw6acS9khi
+pKuZwBsVX2UfuqPdWNNR/DC5kf95/ldg31cfgiU/5YyjtvuK82PU06nJ7SYchlZW
+QZ+4b6LY4X+rhxIzDJ6CeTDnYq5RuqaUA5Kteu9Tg+4xmijS1paatZghRJjnYrgc
+Gy96sn6LwmHWcIvlEXPEZJ0YKkF189FpJNWRpnpjz3+bvLDi/MeBx4c6zWOlDmtU
+OZyU4k4C9sphpmX3QslS6pVNV0wkkGJNScgGePjkviAC3RIwf8fHozAub4tLKG9Q
+onhrdCV+ivoHO193GZq2FbKn9XkeGKfJLrA3mQaebjiYln0O79+B9vdzF5ceDDLS
+eLvK2sFmyxt9EWtCRy847uW08xUU3Get2g50v8o4blbRh0G0I0JcMjFGaoFPaMP7
+kWC4DaBEHHSP131NV0rq6boQx4kWTaEZnXBf+F/A838+7jSTXfsWbvwhkLmi7XtI
+trFU11oYTHx1KHhhyA68GdDH+kCbg7NrPdF+ur06kpG4N87iSBeCpiodYmlDv0wA
+7MUYlH3cZ3OYG6MJdWwA2hjSNeqeNvqLJE4+wfFUxkSs8JZEMQLCqaS8+4rvXAgb
+/rzzTnI+MVFQWNen6bvobvMFHpEhn77FMmE6WPdhvp/bR2nFoEH4QAXUbgpIw9K5
+wwhVODTI4Ux0eIpKFKeC+7OXUmFQdESB2qdSHEhyVwuFrJL2YPMOKA9yyNT0LxyG
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePolicyTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePolicyTest1.pem
deleted file mode 100644
index de409f5895..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesSamePolicyTest1.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICajCCAdOgAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGlZhbGlkIEVFIENlcnRp
-ZmljYXRlIFRlc3QxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtpKu/a6Co
-7KcKOymboEA+MmgoryXHT1dxExmQ1lO7yah2L8j8RG6ox5Tr37TV8Y21ti3MopcF
-H+iXDSX31fixsYCZkcpjMI4kbjXmjGOeFKu1vnbBmcb5JBISiUeg22tIRFoJ4zTh
-i3GLVecGijyOVReA5LiPymEKG7fAB3241wIDAQABo2swaTAfBgNVHSMEGDAWgBS3
-LqaCy8LIvKh7J0TXNTPfmhWUxzAdBgNVHQ4EFgQUOsyUZQyFqTzB4K9RMyoUSI+e
-kVswDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
-hkiG9w0BAQUFAAOBgQCkaGfCqYi0681n9Dit36lg3U/9gTZoNqPMaAaLUQV3Crzx
-x2MGInhTyKchYydbV8HD89N2jzzYq7J2KM/ZEAfjskCdsj1SiMNkbYZe3rZZOldr
-PCGFgzUGTNakQxkpxU5j7plivQic/OZ7+mMTi0fnjGRi9M+aa744VmH6FgCt1w==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesanyPolicyTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesanyPolicyTest11EE.pem
new file mode 100644
index 0000000000..4cc6cfff41
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AllCertificatesanyPolicyTest11EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 59 4F 91 03 49 2A 65 52 E3 14 F7 53 14 56 CF 19 A0 86 25 43
+ friendlyName: All Certificates anyPolicy Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=All Certificates anyPolicy EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=anyPolicy CA
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMYW55UG9s
+aWN5IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowaTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExOTA3BgNVBAMT
+MEFsbCBDZXJ0aWZpY2F0ZXMgYW55UG9saWN5IEVFIENlcnRpZmljYXRlIFRlc3Qx
+MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMKLRwAzuUEtOy/V47M/
+rUpbPiMDRXuhXbrcDN+erHgrUrGHJA5FpjmB6PRYL7fR1mJl+yGRCDrquNaHkEoi
+iUVGpuC59jBUIguJr46ZPrAg4XYzWe/Wh8JTCDubDKEVlbN5F3c+ih8N8aKxQpGW
+ZPm/CWaMljKSBgZeyFzDN4lrAvQYfFeR5yvRQ1rZbQPi3mLjUHG0JwsaCbPYSv3y
+v8XSye1NENSaPaDQ9H/CzLfUKldvkNCnZmeFaI6UKkaqr7RMvqymdIpSjz/Ic7fR
+96ZZgQzCX3EPZ5k4qyaTDgvuLCvlMrYVmHRy3oj8XHkb0VP1zEFmVYyx8gM1UBk0
+HKkCAwEAAaNlMGMwHwYDVR0jBBgwFoAUu8neyByV50LikKKOrgNcqyRgfoUwHQYD
+VR0OBBYEFP0x7qhv8jhIP4wDRMsNB2Ztq9jpMA4GA1UdDwEB/wQEAwIE8DARBgNV
+HSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAGpQqQ5cWZS64sgYSqdC
+NW7g6xU43pbHIqs0NxBefMaYoHRcnBZKZZ51mesxhLHBqOQmJZfEGmUVDJvdOfDD
+N2ShmiO9sZhVqkPZ+PMu3M1hNcnuhyNO7XnlmKKzWXApasvMivL9qM6ZNa0yHELY
+2sgKEo3y/pL4Pxld5usNH+dBib7FrhEvCZzgOKZcfC6ZQskkVDiduhtPlRM8FRtl
+wlrWwLPEPMrYe9rtqGozEOKS7HP8SWI2zzkhIZK5dVXYUpJ+oRAYtLmKuiIAJ+PY
+hWFAwNYtyafe1P164tjeT/JtHAGPQ5ogzcelmzRk8UDG+G/V/MW9wqQTCDzkCR1c
+Fmo=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 59 4F 91 03 49 2A 65 52 E3 14 F7 53 14 56 CF 19 A0 86 25 43
+ friendlyName: All Certificates anyPolicy Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F7043571D5460386
+
+EEhobVClGaXIyJ/GA9o6jtbCSsogPBfCwuUDW0AsT/M5xV1I8L0q5D/IhNM3QJj+
+acq0D04zTNEJQC+06OdxYA4XiLXLJrepc8+e6crkS25+YkCPaWhxVElquJIrORca
+nl7fH8CbF/sTzNVs3dO8pA+WmIqaYdkZCMOT4U3P7chwyqszBQn8PHvS14Il1YCX
+MINX3YiYr9YCsA2yMy5QwBnQx2G74O/+gdyfpJzbP5Rs8L2x4aYHm+w+MlQTF0Hl
+wo+LMbGC2Eu0AWTOSH88d41nDzZPBnCY8CKUWu00JP7OAWEODTe/MAlqn5AZ5Edx
+M9c1PknSgHFB3atXTgc7oEMaX14xDmCxET26mWOfmixDvBVIGh613Eh9FUba0rlV
+BsUhD49w4E2phyz4vy12BPihlthYGHtg9osWOSPFtAWGk0JjcbwgvwT2SlBUs5/E
+zl5lfB2YIA+OkdyTKIG0sdAZqyXdZX0cuwV7sir8WtfJQusXRqEtFIqbNaTFpoB3
+r32YavVyG7Vjlz12BuznCmlGazQeLlHw1LZISVFBzPaIwzDwJPRXjVyB19sxOLCv
+LdrTQHSRLJosfFoMxbKOqm1Lzhh/ExOQ2ZLBCul4PH3e9Txy+h/eQbuS/P5ee2G1
+6zFXhMQT+M8oyDfJJ+QsfOoevk4bG98uQr+6IRx+1IifUpx63DYHTpnQUVzdnhCg
+qHTgxbyJRRkxNWgXb3feSw0T0ZUkyG4XMOF+iqCuaADwtk1DlAG7Dxq0D8YnbUAF
+JNRRxTFgrIW5Rea9zqAyg2dPLqJ6vAl7QezVRIc8QG1QQr0z24neQ6hKLOhhHzdD
+X7NNfAQHEFmMncJBd4EsY0HdBYK3ZkXIYgJtzVopBEW6XTlmRe0mj+LQ//Vz2nzj
+SP63MY6zmNlCklF30O2raSKjBew2EM602jNHu/S5RYDPzFASWDvzWboY2gDYGDzF
+zhhucl1Ij/kyejH6EF8uSOdAJvxfolXlVn73+zAHt3lk1TaHDygtBdD3lRWVYa7Z
+GUg08X2GBrEGo9v0CkdD6/YiFU2M0/oFhNdm6Wej2MJ9+a3LDuXAi8/HsU7QtxA6
+xg2wCB58x4Lk+dR/sUWQxjVeQfkiZkjJfGYtOMp1b07AjCWI5w+EQmc0THwrteE9
+WAq2RKmqexXkTmCEMzgzeJnk5YxuwgzNqwxzl9O5ja95H8iXQgy94RDIIqIsX4oZ
+nRVlr15PpH3oAHlkX7+uCBYuZb84I5pz+lqiXEOkEDIXRc2oSExxW5tEhkmTmSB8
+KLlCtzxg3ALXulXc4VbqJUrRkJGRFx8GJlhuNE9bnc1stcpg5fpbEqTMD+NQuiDz
+0m5NZSS83hHClPyFebiOlXYrZQR9FThWezPmDOzCuVVFO3szL/IZ7YOG3Lt0NJaM
+Kz4HmJsF8h9SENI6+nWbYAow7F/gwgADx5AsqLBdmmq0pouawsZYPNZSqz+++p+u
+/ZYzPflLW8HOwqbH0H/gq89H3675/YbwHSPNpfTLkUOBSkwpwerkF40/U1w5a3e3
+fMs8UNwxyv2h1hhEO7CCVE2hmODBsyM5tOAAF7abgVXqNL90ztjoOg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14.pem
deleted file mode 100644
index 82576fb4a3..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=anyPolicy EE Certificate Test14
-issuer=/C=US/O=Test Certificates/CN=anyPolicy CA
------BEGIN CERTIFICATE-----
-MIICdDCCAd2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGFueVBvbGljeSBD
-QTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEoMCYGA1UEAxMfYW55UG9saWN5
-IEVFIENlcnRpZmljYXRlIFRlc3QxNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEAosJmcfDGby4vpcrZs7/LeCfqnvDfXgZakoRonLHgudPwLK839x7AtBqsAAsx
-wYNmtj+gGNu9x2hjBOrEFHjxVhCZbr+V2b3NuZ0C2p+OcSZ6nKYxxmgtP9NrTYZs
-MVo8uJ/d9zDXB7/Hflbl2iOtwHe4CpWlWkAcb55leIZdFx0CAwEAAaNrMGkwHwYD
-VR0jBBgwFoAUPrOeouRDhftnQDGGE5vGYe2G1eIwHQYDVR0OBBYEFEAG933vDjVc
-5TJ4xVFIKNj24AmHMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFl
-AwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAHS2x3KJlEZ/YeT5mje964ccV/zmiYkiy
-SP02lLjIQuB7b4R8xS4TYb6lXC18dc0776mMu6BQVqECrBq71A77N5cd5Xuc/+5U
-5ZMyLiowPxjhgjqMOZV6Vno6zYQh+4bdFIqNZ4Wv1l0KyhvD5KU5gBQ6uK/Gbmgx
-gC2356iQiJE=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=anyPolicy CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfDCCAeWgAwIBAgIBJjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMYW55UG9saWN5
-IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGOGYJ7e91FozKo0McZ6T1
-zTYa4IXfHqChuqKgri79fgKVZZsKwOyoHWJfsLn6ClknlWE9NJATHZfQp8GfLy9k
-MbdXEKgZQoyWOV2Q0s37ez+I4yuR33JZpxtpKqYQW2fKdhhOdR+DcLwgWUJ4s1Gg
-KCXhxYnC4nfSho/lgR3h/QIDAQABo4GFMIGCMB8GA1UdIwQYMBaAFPts1C2Bnson
-ep4NsDzqmryH/0nqMB0GA1UdDgQWBBQ+s56i5EOF+2dAMYYTm8Zh7YbV4jAOBgNV
-HQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAAMA8GA1UdEwEB/wQFMAMBAf8w
-DAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUFAAOBgQA8JxYIM/manOaFxyoO3y+p
-th/jCQFiR6fDo5mhYEOjZuHDWdejSZvNtbpPfNnKmM6W/qI57hZBgVDil9P/CMSi
-wYPJvKl0ofonnhhPd+uMPhJENho/NhWyc1cgruABceTtBP966dRIhejL3K7SewrT
-aV+IWdHVMKREjOXtHakoKQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=anyPolicy CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3E:B3:9E:A2:E4:43:85:FB:67:40:31:86:13:9B:C6:61:ED:86:D5:E2
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2a:c3:2d:e7:f3:91:d6:67:7b:66:88:f9:22:e8:64:c9:80:a2:
- 88:bb:d7:a0:84:a3:75:ab:d5:af:72:d0:fa:1f:ed:4e:42:29:
- 62:23:32:25:59:4d:a3:45:c1:bc:ae:37:c8:b2:d0:79:00:96:
- 84:0d:7d:a2:f0:58:d7:c4:99:64:cc:4e:8b:5f:88:f6:6f:cf:
- ee:39:54:34:8c:7b:0f:e7:43:0b:26:d8:6e:c4:f8:6a:ed:80:
- 9a:47:d3:38:bb:82:9b:fe:bf:6b:01:6e:c9:e7:8f:3e:cc:b1:
- 4a:a3:df:86:3a:2d:ca:62:6c:dd:27:a8:51:c2:b4:3f:c5:ba:
- 90:6c
------BEGIN X509 CRL-----
-MIIBOTCBowIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGFueVBvbGljeSBDQRcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUPrOeouRD
-hftnQDGGE5vGYe2G1eIwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAKsMt
-5/OR1md7Zoj5IuhkyYCiiLvXoISjdavVr3LQ+h/tTkIpYiMyJVlNo0XBvK43yLLQ
-eQCWhA19ovBY18SZZMxOi1+I9m/P7jlUNIx7D+dDCybYbsT4au2AmkfTOLuCm/6/
-awFuyeePPsyxSqPfhjotymJs3SeoUcK0P8W6kGw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14EE.pem
new file mode 100644
index 0000000000..2ea5812527
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/AnyPolicyTest14EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 5F 71 8A 9C 9E FA B6 77 CB 18 B2 A0 2F 5D 73 4E 72 B5 2C D8
+ friendlyName: AnyPolicy Test14 EE
+subject=/C=US/O=Test Certificates 2011/CN=anyPolicy EE Certificate Test14
+issuer=/C=US/O=Test Certificates 2011/CN=anyPolicy CA
+-----BEGIN CERTIFICATE-----
+MIIDgzCCAmugAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMYW55UG9s
+aWN5IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowWDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExKDAmBgNVBAMT
+H2FueVBvbGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTQwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDKV4x9YSxioiuPeQ7ngd0MdwlQUnIwpX/DTeU+Zjxw
+UXS4MzHRn8zuzbGP7DfS6lmx9RMpFE0UV+zyo6/iXaeGgSYIoDoP+mX+o2Fy1ctK
+sJjDmq42VSs4OOKsYGm4kVvLhRI3xPdj/OzB38aukiJgBpyBa6d/y9RoTSdRibE1
+yjgI7GeZq1Oe8L6U4JwHTDG4HXZe1cHYROPtr0favOsOsROEvScIOG6nzNtcdCgy
+yHcRODBMqI7huxuQdgdUDk1oc7upF6H/RHLIWnIYPTT7zR1J5+6LEt4OG9jKB2/X
+M8FbTR0OYcg5gpAHMNfWozYLLolyNdo/PUz8os9N9T9BAgMBAAGjazBpMB8GA1Ud
+IwQYMBaAFLvJ3sgcledC4pCijq4DXKskYH6FMB0GA1UdDgQWBBSxz2HJeKGhgtmf
+nkgFMNb1Oc+6ZzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMC
+ATABMA0GCSqGSIb3DQEBCwUAA4IBAQBPBpWPbfq2YB7SyxdRFRsYl0Y88JvLRKme
+jmCrJlUPetIxVd64HNJrcrguqsXM/iWn+U4Z3lyNS0gGDUkazuKi5yoWonFqdrzg
+z9e7c7HY9NoLfb0c3dNmfll9ZGLB977XFWOIPj7Nwrfaoge6LvjyUT/hT1QqZ1aX
+2DOGOwucC6HoO1S3uDQuWDO5ZvVrLLP9oydpd3nfHtBu1S04qG1fZ0A58YYLhT1k
++IiZX35xhNtNDKbiCQPu6uYeN5zABQuL+e5SjDujOPVHJDeHphAGLgpbFIu5+NkO
+SXbxdzrX+dllyieqlkyWIuEPHWa9SSNRRUv1kQSqd9ON+iL7DilL
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5F 71 8A 9C 9E FA B6 77 CB 18 B2 A0 2F 5D 73 4E 72 B5 2C D8
+ friendlyName: AnyPolicy Test14 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,057D52701BD0DDD5
+
+JLZVDDBeeuWyNhonJgsHH8oLBq9lCLmBtMlJcSnDCCd1p3q8BwqpnXKEu06luy1d
+pBBSnx1UrYdslgGV7NumlcuOnDY/YwgpqxvFVHWk8cpUTZArqkij36YDj5ItGuhN
+V7OtGMxz/9dvc/8X9QiSaINo7WWkNr2ac4mHjltgCCnIiyFRKeX156inNdrrHhr6
+0UU0I8Q4CYf6rRH03pLhGCdDFV8fI1fSagJ80nGsYNPis06RFXjIS3vwNfT7PNeM
+LGnLjTnRJWjIQ4Oes6gQ63GFrq2Pyhrd9sBuZZDidhLGosbYWWMlVcX4lEsuN/Wo
+BIRIS4C37WGLCQPTizlTHFLlUBZEVkhW9yiTxDeKeg6cZDEuYLKPaiD6+UnmxUlN
+WW+ag+BMisyGSBJHcTMRiV4yisNM2Hfwl9yd0RLK8my8iXXjpx0DEy4Eqmol9vwF
+GqC3TfhqDCKVN311JeDJDj+4JZ7Cf1EtNT6SYgu1feS1cPX9MJOm4xshF3Dpys/3
+Wv0Z7rZi3QczqFt4D+Dr5YV7iYXuX+i27zECMQsjFhT283f4YdZVJ2OegCXNQIKY
+g75IiIUqNRJPlkolyeUHs0q1fP6DyTfOMRzu/WmQtnmwqLml6+pE62ZjxKyJz3bB
+H/9cm7WmsFKzRMPf/53NsofLHzkr3VXxC5hb3zLKoAKfAyih2jpov5EWDr2USEMF
+gII54p2s7x1dh43/sBCfZ9ujM0MMuhvI6nG2mkvOf+XnnSA4zP1Chvo3JlcBmJVf
+dWamIjZi0EeBcSo9oqXj3lo96fFBIzx+pPb4E/mxdnBagWCWyu4s7/GTm23Pf9AI
+UdzlMpZuzEMQslRMJy0ikb6OGL21qs7JkhQ3XnQxawSl0+sBto5Em6jkIB1FhAeR
+UCuN7MZQ9QuxOHJwO5yMqG6IeslWGex96GVaoq3dKQh6SPkFXO0WaTOlvs4836c7
+jpBEZdJq3180WYwMOvm6U09FiIP0oWDsnn2REydlO579DuT8vkpDdJCJmNRwqcAb
+uDTulMEDuodGP28cojooGzRh6SaqXHXLUqUD0iPgzo5+jtvww7IdNCsCaC8DbvT8
+OGdjpZm/QMtjpl8C9sAIMhB8UvrT6uJfeknPshrzpmi90YM6eRZsoRtCNWNyZFJq
+ATbOY0EdCyujOknEVO9sqdKIRyFaA3nyOpalT54Gp5Y0LiQPZsWvuEigC00JLwD9
+AsVjnhr65mA7ySL8+8A4QVmVTokByWxc7byp+AG40FkzYcnUw/3Z1+klikpnXCDQ
+mIaEiPvH27OVHL37jtp3y0umbsrd58YsdUqo8nRa/5jv6MRqt6GmfN0mB//MkBFS
+MZBikweEmGj0YVW33o6wlNpxL8l+AMMw8lucu2ZtpqDrwq/n95GjIuIWwo+qRvWH
+GBiV/T77L8ktuE2PPhgPaDnh0/LspJ017ocHGANHOLbdeDHj6AQcJjP2Ow+R0Rzx
+4EjDxGPmmZ/LPKXqOnVKpJRNp0Na05ZjnyYY9m3HKEpwVUG9soKUYZ9iTukBcWbP
+jwx8Z+YPZWQ7Khze0JL6hORGf4vyu0udFl5IcaX49C3nFKb5Ld6Zdg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLIssuerNameCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLIssuerNameCACert.pem
new file mode 100644
index 0000000000..af919d4076
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLIssuerNameCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 6C 2E 70 1D 7D 2F 76 3F DB 8C 72 E3 FE F8 E8 EC F0 51 EA 09
+ friendlyName: Bad CRL Issuer Name CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Bad CRL Issuer Name CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDizCCAnOgAwIBAgIBCTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+FkJhZCBDUkwgSXNzdWVyIE5hbWUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDF7G8LGjdh/MYdt6lQvrWQX7aQBOGHFSdheaon8f6pFkeQ6kE4aIKq
+Iw++7OQ6YfzkVfZRRJXC9SxqjdR+hGjUlGcwV4g5hDHRzZwyDa14++AMjmSMM+VB
+j9qcz3OviM4zmJf0Rlt6znCxVO72cARGJ2Qzly+RKlkN+/uKdayvHKhnVp+YVfyr
+C7gt7bfq7pjNXSrfS8F6UAU5u9f2z46volJYEaCzAoWa88PGtNbg8hwwydsZxuZ4
+WtZFuogcZJG+G1+gOA0Fz75xb8WL5dVLj4SCiqwjmncy1x3nosWjalb3kmHF5RXQ
+mLlVX6TRuOlS1MoOuucFEULpC7hNcCDtAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9
+X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQRcvI1XQTVDkogBwdBKP2UcAAc
+cTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACss9Ku6BdiLgwVZq4DX+N6E
+dZWy5a3zfTRVo7Xb9nLTuzxlu+OeoCwgMf/+hCtFxJoAuQWWvhU00AaYQHGyG7ol
+odpaA1Ys/vqEg3XnDpIlHWbTYE5PSRS5Kcfh2bUk+o2BimVwxMYazaltdktclOXD
+ajPu5aE5fgLHoCi/fLghLGcr5WEzBR2l/pYvK40CtsUutuA1PgL1GIGql8yYeZT0
+jQ6ohUM7I/kTzvQcMjML7rFPJkyzjEuji2d5/4Vehh29wg3kap/FuDiPSYwAsxto
+0+uPT9Uu/vgcMq/js5sP65AJ6A3NiciYaq4/Mgfic+zOKz5MDq6+WILzoWnY96I=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6C 2E 70 1D 7D 2F 76 3F DB 8C 72 E3 FE F8 E8 EC F0 51 EA 09
+ friendlyName: Bad CRL Issuer Name CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7EC803DAA0D9D267
+
+7RECEzxjaCmI3Tg6198FOdR4qkfyYprNug4mGyspIeBsHfpsfkyNOi7Iz+zR/NjB
+ad52bL9B9MIxU7VDN2+dPQtPoBIhir23O59ct7S/2Jxlw6W0aFOUZ+KuuAuuwsVg
+2wGJ+kdpzn2M/Gg8MZ3DBzIB7GUWzUU5EBF2M7TmgrPZ8Ga6UoIvo9ae02hkTXeR
+YASFVlLbfr30RF6h7XPVzwVHDmsikdcdbFAafFJuKMeCz4/JurpSf8ywbgw5BfJD
+Jx60v8JWEGt5JuXYCMd8ZeGGDJfO8NXjV54sp5oiKRM5b1ldeQfzciihmtCwEbrt
+Jxk0Mu3tyl3tvnzHTK7MiRU3txvA22//MkR9XpGZDTEKh+OSG0hcDf5Y6Qzwp7FK
+1elWJ6DDZrXyZeqQMnVFy1K+ZdGFG0K2Q9D9Ff6GfD8gurEDrGOuuY2DRVvGpvKp
+yZcPcjAnMB85oQKmw5k2JLWmMhtf6Ur5Zim/HqbXUTh+pGS+pa7SCT/G2Rj9uPa3
+1sYPhI9AYMmP8lMfUycc2UF0Oh7yIUou57MzcwK1YatEmsnnnkbMB3dOngv8nS/7
+FV+maszUmn7YvP5+HRqsLfN2qA8aV4ovBdBdD7XGbznyvFS/bHbfbiMKPfRhPf4H
+CmSfgFa3n3dA2Htokp3vhxds/6tKFf+zZclN8Yb9TWrXhlahkGVtBe6Y0nt8u0oz
+LBQSJJ458dzU9Q0aeU8tSAmbYZo19FkzveMpQihSHWrCxJUw+vYV0JYkKBobjsnV
+8aq2HIgvHv168rZisoNxJ+AVc8wYheGhHiZDQFXHe9NRyt5p0buCof4eMeEDenUP
+N2VAvRIjm+YWt0EbcPS1xknormptWPH8QvRS95R7nivsPPRbijQidrqmZ9VIbBd4
+JWJ5XqFqdZmVl/Bneid/DqMMkd4ATNnPow16MUWLi61xuLY8ILLJoYGVGZ8Y+fyC
+DGTlbSS5RLCIncImxui/yVmL/ZCdryvAs7yutkNFYkMqfz0fTvhTTklzsktt5MN8
+BlW6JR46qbj0rksJ0ELoCfxY07JaNDZakkC/aY8fvuNX9HP3A4BhNBDHAO0AnbQU
+Pq3bM3PLdopsWeFraQlHj1gex0RbjCzBXJX8eQB2UEyOjqOiWZfSvHBAODKnKFu9
+DUup46HrdBSYMEsJ3voQtyT3tLW2FTP8HiX3zm6/qittG0rOdyB3syW55QtqXt6m
+CmsJ14b7JDbeRhBXZMjKG8HCw3RuCIXifUqnWpTBArKm3bKV5qx5JaPQyvSKpTXZ
+p/yDEREYJCKUrRoAQC5aN1hHiNThmMaXoxBvI9iYliB7ql/1NkZ2TW9OfkkNr67o
+cv1AtD6i9u7BDqKFMH7LTUbd2Y5k1+97AXYW4nQW/5bdZQ+93E/KJoTG52YJ6/Lm
+I6e+GR/UMPS4OcdFEaqPAJZmjlULKB6WltEiiSJlGKbK1q5lWIZj+cpDW2BY7NW/
+kq2r4zHwbDsHTojGQE48B3ng2qv9xvSADJeq+w4DzmDMB012+ejFBSB9orJYs/w9
+Y4551TT74ecSgtHQf1m8+HhVilIQk0t3nen5hWsxLPbfY8aax5Ee9E3NKl91JV3d
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLSignatureCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLSignatureCACert.pem
new file mode 100644
index 0000000000..b9676c0c12
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadCRLSignatureCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: DA B9 9D 19 8C B0 DB E4 62 3D DB 90 AF C6 87 F0 8E A1 DB AF
+ friendlyName: Bad CRL Signature CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Bad CRL Signature CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNVBAMT
+FEJhZCBDUkwgU2lnbmF0dXJlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAopjCrwdkeFD3gKtDsVn8LE7eimUrRMYO2xbIQvoovb7ovBhk5DSjwQcH
+IPV10+5GZi2mTMN1/EIVbljKPn+flNvMv/TQRlyGL4OlX6Cn8jgs+YQomw+xPWC6
+jW5x3lLxzkGF+5XJEJFMLDBAYOQUNj41BMlJX47wWalyulucuJAnbbesOdJ3DUso
+1sDlkZ+GGHQB/U49naBOqf4EbSP/TAQbGNfOd8vuZl77D97eDYD1/SpgW6BbwdU7
+2aeKVkOqg7l0efHzTlgpnKmrlyDrAj5HFD3aqbOdOBezhTwz57rAufiJbpPJo8PY
+zTJ6YxBtJ5z11P80SN5IPgI6rUpTbwIDAQABo3wwejAfBgNVHSMEGDAWgBTkfV/R
+XJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUMYs1jZ5EYTAU3ucLLhQZSCTb+b0w
+DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
+Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAsBDSBWEBw5h39jknYGFWZO8XM
+4ZH0g/9MXqCIhvGwQqAqs62pcMlEWhhXJkxTlKHEBeNqb+L5iffq7RhfH2CMeWbM
+FW896V2CHxnYXToKQTq+y550qOX0m7Wm9OvFebCW4B2OCKWZde9esxkTZvlNCCkm
+wVFBvb3+nrlW3fLFsAmfixxftD+pYkA91Bud0M9zJElT/vKwzXa5nNrvc2UmIATg
+D4i3+iR75+yXdJ3e4xe8LAjJqqMXJfjgHOmM2IJTIuBOKKwkuEFuQYRAQsrPd4j6
+l7ibnhqlEkAF2gsaHkQhL55l/8d7H//Qjk5TSUuYThqhqeZEHfabdVUJAUEv
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DA B9 9D 19 8C B0 DB E4 62 3D DB 90 AF C6 87 F0 8E A1 DB AF
+ friendlyName: Bad CRL Signature CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F7EBA9B2412BFCCD
+
+JfZvfm1e18aeiPLCPi8xpXJui/JMWaxa2yNeIaDVWvfIvLxKPKUZrwj4bvCColo4
+H5z2ibaZaHjkykulFaLTDfZd4RwQdKy4kL35IzfQj1ZwczXvq0vrqbmk7t2os1JN
+6X7D4rAl/cjzjnmjeMVqkv+M1I0vew7UQ0AzSPrtoDQn4Tn9ePu1RUFzYPa4z+fZ
+umqxCXQJ7OdYMtc4Sryjehc930DTXa9FMKjnckpq7AJ1vJbMn+FdOEv34tzVmwiv
+7XT+/7Db1e/lfVyPb+eoltGANuzku5Ov1Ow9gzhuN1rFWXAsCKlnpGm86Oeo5Xh5
+mUx0nyYt+OXkb/HwaLVHYVglUcN/BdUu6YFRjnyoebwFltoniCslfRko4Jntn1XN
+PazLe7yDBGCYDE+mNlHhpsNQm1GU52HxDknb4QQ/UiqmIh0+hABQL/xWmPkh87mi
+0QfHJClNeATOoux4vERgRnQBAwjNp2kumDbYZopQzRlR/4APL+Rj+gZQDwSdPar/
+PGLm4hKwoHkR/qql60Y/9UOzkmMAND3Gx2mg02uwr34XkNUtpssc7I5S6W+C8lJ8
+jbZledwVLWP9Nc5heZHo51HejD6ewzuC3QLfkkSfo3TO+NcZt/nBmnvf1avg4t35
+eRQVeWAk2SclJ2snD69sYxQKRN6owRZz3KnDUZaGXyVjzKmLlGg/rkiXvD8h1V0u
+tgEsSF2EPeGIQiExgbausGNxZMxPgOxc2esdjipxZJ9Kd3P4DeBrhF5eOyE68Ikc
+g2E1omF1ZgUv5OlEjfpS4k7d0kQXaSfYAuCBMA3ayvaIDe8cXpKXMJ1hGB/o7mvg
+rEkQAAWExtdJofFSfGI4KtMKgcxcMDbTZoAQNL2s5D5ImnsDjnyonFGL8zxYIhFo
+g9N4I495b7yy7v1e/6m6TLB2BAWRaa2M6aI6f8w3vEuMclloDP6AUJCiLavld0E6
+iOk9uUB45XLM9ZnZRC5uzJZ3JwI6kBrEatHOkLxXevUfnxyCvEqKsJAIlC4NNkvm
+aE6LCfCK+Tq2joGWAxArBK/ZwGLskJWGddmCcaH2Z78mOmLdwqUsk0xAuQIQLtvO
+Roj1rJqhlukXgzu/6VD6u0rCLIPK6+wKNIoFT9IPRpf2FqD7JntSRPUjb4WEE+6d
+AqA7+5T04cc1VDGqjy39zz8AgQkV2ze5/y57d0YkyfEFzbM0HU2xFplnuuq4/8VE
+RZtJvOohrq+7qrG1d0MVWtxCJl+0cwM/pX7x3iphtM1f7KiiJpYvSHXvEKkO6eFr
+e276hHFQ2+qHmTGpXhjAgCUdoWJ/F4XL5GKaKzei7vMnJrJIV9E6GEHJcvbH0C69
+wAuuYznu2eujeryPtb85ze+BHStBuRDhGTWURZV7bMCkS4lrSI/WxyFjJCOJh5yl
+spIykbdqDeKHtXcB42GL0WGtiwhLIul+VKTfqEBK6RS0t/JiN/n5iViGTvwnBrHy
+E+mYHMlrBDiMUQGgktAmf1+Aoo+5ArXOuTsGoCEdHy/u3y01PGS5kIP/nofNriEC
++/8fQh5CTahXzAZs4kgxb4WYCm12CEoc43xIHWSz3YRgD1XprueTa4m5oHsjZ52l
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadSignedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadSignedCACert.pem
new file mode 100644
index 0000000000..7e1c0cbd44
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadSignedCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 78 48 C3 C1 72 F3 54 5B C2 57 A6 5C BD AA 01 AB 25 C7 06 D9
+ friendlyName: Bad Signed CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Bad Signed CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgjCCAmqgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFjAUBgNVBAMT
+DUJhZCBTaWduZWQgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDf
+77zrq/d3vnq9i8r8Trn+BmzL4FkkTxewQRXNUnk6QnZ3Zi929sKAyv6cHCJK0r3p
+JQj89gjkcHFt4Wsqzo9cRS/39ynAiCBoPqdOdCiy6J1AhKjMAVjrx0U597QUMKXj
+jQvxpsLptqnn6kEX0VQzHqrChCbYogCHGVzyOEM8EA4KK8byAf2ZwUE34FqcSYjb
+XtX2Kl+NsNGEBMTiqNEE82w+HmuRM5XYxG9+3EnCuT5O5b4WWqzsvYHAXEzgu+K0
+ghe4Wail7rFP1Ho046GZCwUzi+U518bek8liQ9qiqS1L6oVa8dnQf7QDImDBIb5F
++2IJmU/NPAJwTNAhK3mBAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWu
+vnW2ZafZXahmMB0GA1UdDgQWBBR73RA7SuDI3USFTog8WovNmSKTrzAOBgNVHQ8B
+Af8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQELBQADggEBAWS/T/8EU0O0tLjvTs5hWudZV+co6/NMpRBk
+gUjCI8VuNjpi/bmhLuNioJ3tCgLWlZ4Lhd9fLyOvktEo5HtJ0HNedz1Nq6+L4S+u
+h8yYAIXSawnnyZLof8p67U4Z0hz7typr+a9FLpbkvOi6KUykbEgNOwES0+2PZLlf
+0O3/I4JLkA7w0JXQi6CyOgVlRxF6fxw4O3Z/C+u560TndrUaISdyugt9a00gTmZc
+9cQpAfZUn6WS0xp4D+xQ1h1l8BU0nXR32uODwxTh4PHh6sjZhY4pWrwbRgBjKkzI
+iqEDzQlzqYwtPjIntlbAkwC4KM1pFaMwZU+WJ79rrPJGMGWFF3Y=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 78 48 C3 C1 72 F3 54 5B C2 57 A6 5C BD AA 01 AB 25 C7 06 D9
+ friendlyName: Bad Signed CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C048FC6B63AB6285
+
+DawdHO3mXL21Xkgpb/P19gucgX1ie3SOsq91XIvu5o6fhnoWjLjyhXCAFEAW81Ch
+lZqDMwAHIh7VVGpaSh2lhbaX3gncOiPbI7JXoZtBKuv8tRSY24/B6Bllnp2igveS
+7uTrD6RZKgiZ11zbPzUk31ikV8s28GXkhFd9wXDKYqvyBUHnPHBJ283RxirE6KTA
+e6LASDhQckX47Knjb2tQFuH/geRGxvaE9DpR45gppDqvguMsaKNOFl5cB/XotePj
+VDqCOB5+Syj+yVM86U92fB9lYnIzhwT+fPuZoBnXolegb0FxzzBvp2A8X9srQ5Iy
++W1mIXtSLzjXUhoKyVH0LEaw0/gS5qTfNTBpJJ2qCxahiUviydXBaOPxU0k+EC+S
+2tVJDgC8P+uQML/X02kHdzhf1y/0j40GBUCUhiXVcv2koXpjxrNt732RhsH+2z1s
+5FbtgZ8OCNGtyx8CwUBrL6eqEhN/QJWypDlAbaidZb8OAljVv457nQYvztoRBS7S
+e/zwpUQb6afUHij5ZkrRA4DxT88HUIiCxOhlbTbY1a+f+4pk3I1zCqZlutITvIx7
+RbAzmXKCGbsb+W087tew4MmqqNw9f+RTTia0ZzB0+Y1O6ABL5OBj+/lK57nQHzLK
+g4s1MOLqM3BSuAMqVfoHcWuzew8xGKoPm0W7aGU8oRTeSGQRgqsFUd57F9x5ekB8
+HzWlyVjoSMNiaijy0dqAzsQmz2AzpAQzD3Ri8PG+nRysvu0xuRLfgE/23zW619Hh
+1Sj0P/S+GiSZF2K2Tt4jkWGzZytfEoyRpueDxxM45wRHSzLfg+4EsWpKyFRNQMI4
+arYmsiZeQwSZbwgT//rJbpxuUQyDVa0u6xR6EIL7USqH/ZoPBVfeGG3Q3E9swzjb
+/DXh7aTNt4ACBVfIe94p1cLkxB2px1aONmtA66gsmHPkR4YLydySdcdqlBwH1+h0
+FrheWxP48P6okxZit3HJgTENa6CTLfGnC5QHARU6zvpFC1OuZxyWmM9xXmERGOUy
+fff499oyEl86KDjCySX2nAGRzJ1UqPIL5xu2NwEIsGF/IP2kG5BsmBoEoHy6SjLz
+0U3Esx6aUCFS7tI8QiqE16N1yzswtG2GHBVurhHvsU6q08b3nP4RQYSlnBrWsAGp
+D6xBuIFQY8LVuhDbM3iLiEiZThbv7iEw2olJWCxsiyuyFAiVs13xfMwIFVW9QRtU
+zSISktCZ0h2qT0+R5o97cetHR3YKoDgpGT6Vf/asm2HwwcBjAsDnUOJrbfW+Aqar
+Igi8lNhTPKXXowc93l6rXvRY1P62pRnu4IMSdqWFboDOS5aTTzPWJX+lywKH8aY+
+BEnVMVwMHR21Wi6vMbMU3l89TCOLTtdDzwv47vEMPhn6y6Wv7H+jRPKNmLYPFptt
+/utX9RtwsPLLqGqtX1/ZXWFaQbV0iGLLEV02h6kTiW75qyqZMKaQItmThIbKzV5D
+EA62TMKyKfbXmEd/6TU6V2MATTGJjLhTIan6gxAeYSpolrirXrukOEGUPEXLDbaJ
+2UR+KFUiXm8wtzNIorzqVOpPfSdOsqcAzaGnus/d9QBXj6r7CT79Rdfbm1XN+hIf
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotAfterDateCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotAfterDateCACert.pem
new file mode 100644
index 0000000000..948c1aaeaa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotAfterDateCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 9F 98 F9 64 49 AB 11 7B 7E 52 9C 0F BD C6 5E DC 60 CF B9 66
+ friendlyName: Bad notAfter Date CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Bad notAfter Date CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBBTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTExMDEwMTA4MzAwMFowTTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNVBAMT
+FEJhZCBub3RBZnRlciBEYXRlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAypzKnjMK9B852wzLGnbU3ueOStmx1eypNdu7Hp4p+tGo4yA+MtHxmowk
+V6+nvIJPlouENL+PsGm5hG78ZUcZdyJxIWDjSwdq3xI8nLFWfNftlDBg46lWJUoq
+NLktefuraN7VVdxT3BAS2qTV0t4jjXHwgwln+cnQbxWPD1wjLY87yip9vkhPVMnR
+bLjdPIkvW5C99JjcqCyDn29T0mbWuYtUmsYbYYdIAbwAHU915tJQJ15JqHucNfu8
+Xk67nakILTO6vzc++lmYSkVJEkGE7Gen2BMpOCAjLjmRU9nFBfp2d8SOVl5aggu2
+hJrok70GS9auRuJBwZoQJjp0PiTJkwIDAQABo3wwejAfBgNVHSMEGDAWgBTkfV/R
+XJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQULA799+4886Rm7OcFn4iz4s90Rtgw
+DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
+Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCmiMVZwyJLiTnmwJLfGZ5jfdi4
+nNcnS202Eao1JeJ7+N1npN3KyAj6lHsey8PtRvsliHAtTOgILzAKdY7pfXoqbUKg
+KB0lwXQAquIA0yXuVZRledjaSvqoyadymyDds+5oFuk1X1i4VQAxzF6PmTu669E5
+WGQryGH8oR6+xLAB+kQ3xAkE/X1NsQSrwp87GKGBAG2VXTvBEVCXovRBWEhqQLaK
+OXS/YMCySS+G9WHXQdW4IPj7lB/2ri/N/+zUE59szrmO5Q2uqZsMqHAiSzj3cWhq
+o7jIJZfyQ9biZZVo5NnR4Eltpev0Tl+4Z/OqZt4is6dHKI2A1p7ze4KqZrQm
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9F 98 F9 64 49 AB 11 7B 7E 52 9C 0F BD C6 5E DC 60 CF B9 66
+ friendlyName: Bad notAfter Date CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B48D9A8A87153757
+
+/XVUIfzT/dqBk4T1wAytV/NIEjXjYgeCG73089udaZQ+0uvOxpWaMlyeX3pi0fQ9
+Cff16gFGpthFZV1FGzghdG8Ycb8Pkaxz8f5b6E6rfgUuoWdY+TJnS1l/hIPrK7jp
+NaL0/atBVOEiFucipTPZ2DTfNCtZ0oRh7R6BSKosy7WVERrQWMy9PCNH4BqlezbS
+dgiGKwQ1CNFrrePRoJLzfesRFZ1ogw9F0v9WzbV+8hHNiJKnJCEFYlHnNKiJKFX1
+YhnSnNFQfJ/RGSLUVpOZziU9yJs6DwpO7rcLY9WW+H8KGhzD8b5pVoE/SFd5MznM
+0HjAkk6hAJ9wRiOFCPaE0ziBg73yfR51I307JY0FmWMfcQQp/t8aBfMnUP9irRwV
+sb2g7ud4zGDzc1dq9qPMvT2pjrLJVLJnAg07cYg6RjFw7DdnradQICVEnmuDbry2
+aggynkfiFKvNiZ+57LQJYzNJZpTjJcTdpfEL4UBK3PuUSpz6W8AHLnPcm8m3zUXd
+dqCgkIPVy2kCAD5pvLA1wtl8Q13VMT0/SJywjJWx/vx+g8jDirxXN8TwOa0hc2BK
++gyXufS/phlv6NqMKYxmMGkoScCkcxaUidHP3h0H/RpaLhPxD5JpgCjvHtMWhCHS
+s1JXAPBLDewrZdvc7R6A/GCnznrJ/BpV8iwDjtC5vKf4mSdqm/1KJMdi/PHYRDBr
+EqsQfBa2Y11DL0OqMBkBUT+2aYc3cDfIZqsIj91Hk6z7E41/j0b5SfaXFqWSL3rH
+mbkUCoH45UR2Yo/dHFIOyyMCckfkQChbjOiVpJ/pX2qaG0u/j7JkF5eqdBpsEK3d
+ke1OOLvbwkHhwmj9u6Fy+HobF3F3he81L72iuYkqTqPPx+qT138ovbrgj/1thYox
+xEj8tDJv4R4w3vG1pebV1Rq/2HN+Z9c2I16xO5lQJrHtnMEIksO1UuQ6pyDF5hX/
+p4ez0TSq9PEXMC4iqaz4du4Zx7/sUYmo2fFVEll9jWpURcsRf4qbQXEsFf19hsuh
+bsv3bV5gWEgxSruXYcCAXDzuYnW29yh3XQuq1w3T0XiSZLp6rYoU2GNxTRjJgyOm
+UBGr4zyHJa3pauo1+C3XftpmmFvu7tCGH39ZlFk0iMuCDVrTeMAiaCeMrgfbIDr/
+K8c13FwapkpFxy3Pm3cnGN6/vtxyxWB6TgEuILQJrO4Msnmoh/AF9mkZ+odeLD/s
+9BuiIH5CaF8pTF410b/xIVeRhc6K2HZRRf9LNBNYeDu+c8ji/RBWWNj0nJpMyzJc
+DMfuf3EmN92pt77t1/Ow2M/MgsFhTdQQjfuLAP8NOABumYXLpjgAivirhwEbhMF1
+SOPy719UpJ871VLAAobjNxVvq/kgLxmdFBbw/Vpk5wjBCtppRYyum4XRE1QBK2EK
+imLZvpFn65RK0yr1cG2e6MukI5bAcZshBn0Yxr5q4C9GN+5UDDytLVAf+hfFwcBu
+CHt5ec385GqphIYFxJ90h9dLRYDbJNglEm7fc2lT80dhTBepbVVn1GkCNsi+bcf3
+aGITjjQBqGHXYBrzRhuaSy95ZqVqjJKmHyvBv+rSznGUeh+e/XaN9Mb2p5BX6tLf
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotBeforeDateCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotBeforeDateCACert.pem
new file mode 100644
index 0000000000..65a6a205a7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BadnotBeforeDateCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: D0 48 89 61 17 78 37 17 95 F7 CA 06 62 4B 39 71 31 8A C7 5E
+ friendlyName: Bad notBefore Date CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Bad notBefore Date CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTQ3MDEwMTEyMDEwMFoXDTQ5MDEwMTEyMDEwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAMT
+FUJhZCBub3RCZWZvcmUgRGF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKdTl1qhx5hGD+CvPHQU/pDSJCVnLWeXmdblHoJ746b/bW3/GkXFSUPl
+1yT36yl6CZJzUJqOYzFkSE3aN2vDcrjviJOAInET39JOxLTkc7J8DxCpz13PmliN
+KpQl5p3fY3Lll8UumG/5mZsdphQSp2gIN6w68nJKS6Nmad46or/5l1qsAteEjIGx
+a26CC6tV5yEqchk1Htsd4hJz7xUi7vijBM987pOidUjCYNltpZYQYvdbGIjl2LnX
+ILVLy2B7Sska+bMVllQM6d932/mzFUxCXCR7eow5ZKo3dPAKOuwTnjTAR3MHfCij
+/mRVgxSBDh017j55dVB16y0Si9flCfkCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFGM+vBqe+6HyWaEvS5X+5t5WuIZA
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAtkgaLAbOwuudAqkh/5xJw8ur
+RsA3e1joOqVXy3iP5Uj8o663gzdoBl+sIyDGntdx0h5GjR4QM/SWPlz5yxFrExe/
+AaoxXHr77fYZfkgGBCLblxo3wb0iNpKz5OKmb4qtwEOpHygOpSSiV5e2wZDjhN1q
+yR3v2lR5L2exD+k4l2Td/0w4uCpom62k+sWY36/h/zKiWFWhnIWqpHYyYOGhYzTM
+EtJNWj6H0EWEoB1YNsNZYT3f2w4jOFa7oxfiqFS9kzXIjenc+MIt9uU6+oLFjdzt
+jVCxa181mRD3+OiQw9SDtTZXEwPQmp0jj7B5bLGSKK477cAIX1uqxE7jyO8t2g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D0 48 89 61 17 78 37 17 95 F7 CA 06 62 4B 39 71 31 8A C7 5E
+ friendlyName: Bad notBefore Date CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0854315DC810CC2B
+
+oU+cNRSsrQLPHupZquTWR5MxFD5aQCMQ98zPAIBMby8OcQgmJK75sTatLp3R2tTO
+uux6L2ITikqV4OX5oWqF5rkqsukF7OvtXpFjZfOvg+an+3LymMhWfMRT+YflUGvJ
+XFu2tq9CbQ7Ov1Dwv35SFAzX6lDG0/c9ct148i90vMFrLZUpIl5fxI2x6B+lLALL
+tJ3T0oXCh5Ux4x3YEgG/NpCMyfB5QeX6C69/Dv/qbr4GkK35OktT2LkcO+9o2dj9
+lC/B8Jx2lpNDw+wAw/nURngTRMvSoYCInCq3m3PnZaSAzq4/XKS0wjznYqBhSDrD
+uUjf0K3b6MK/DxKFdp/F6sH77CwNapTH5SLrXL8wEKK9AHM3HEab8Ec8i9gFFrku
+irVkDXFkvFNDohE6xAPcHRHKLmQI90L92lepUuBp7Eb3AQu3V3OKfLW1Onpuh3kd
+RAUbhtzGAEGB1Nl+C9GJ8G6gCS3hKPBDyM+QXdulkurz3XuVRxcxboH7eB5HFA2q
+NH1kjmvHCXszOHltUDq4MxcjaGlI7apBtyrgWaPBWjGg7M+yiCHhTC9hl0ZOxgzV
+NaatnTAJk0JwZ5I5b8hy5SyTV38QRQo3DmW6TC/oS2jmAC9dWUXh0SwGoViWRqBF
+6Xx3B9To9tgEtpfTG5m7snLNwxqtW/FX3uZn01Yz2WMwUYxh8DTTOF5q+dWyhTYF
+vBvSxqmetd9zVGJHIdik5zfVwnzbHanrMhW1+zEVUeO+kz+2i/clJmvnmBhWNMHe
+ElLj8tGifpWMGAZbz270k539SZL+O4DcMaukA5oyp0vhl8kVWkvmw9L5+pZH2gUR
+PoV0AZ/9gYEAgzFqvNLcNkkjQWcjYkc+htxVbaKdCVFTm+LC4hEkjT0WUz38IZoF
+vufOUTlaRHZpHOIALn5vlmnt2VZ9LUWKdWLQHU87pDBKkwLNl7i03+PGnzVhdUrf
+daSY38cOxEOaqkaV8ZPu7p7nSRMTwrrC4aaUYLjrKVNVXY+ULj2Jy+K0tgOa1ast
+p3VXCnAEBmbvQ0xAiWnkTz2iljE1GTPs0i8iZYfuCM5Y0ZzBcdD2KDjM/C9MykUR
+iv+1QQ2uvYwOlQw9jMVsXfqAvh6Bwlzacc5bIZNO/C2EQZiXBW/w1AmNcqU2I+bS
+h3rAnBIpR3yYFH/E+m78m70hQt2b9a/OF54ncjBoJPI/wCyEkbuX6BdZzmnwEeon
+NzKqgO3auHBnaGwmV58jnhHm8nSUttj2D/9xHgPmkbIMeF4Rb9ri558XXh4yF1Q7
+P+vxmk7Lev8qxCV7S1Cuj7zjkiIKM32qT0gJO57dSxHYY6LwGWlCHHkdXFMBMNNz
+2FqjzPyPqfA9vA8hd/y8E6mGAibIrJtbn+XAd4tG2qVI+AObYGWUR7N/AR/NDLdV
+e+n8xyudrcdhxQ2VzLN+R75H8ogNyUypp/COlULBnj5GsxCfmiujqIpfM6mOUyoj
+f4c4B70aDbf+GTMmVU/w3XjPCRfft83tQDdDj58iOh5h5kHTHIRypLp5atXJDKIN
+1E8ar3xB+hKJutkBoP+xIRQTE9ma52+nJ0OMuZWnFI3hkpfTFHCbBusGentg38Ty
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCACert.pem
new file mode 100644
index 0000000000..914736b9ef
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F7 AB 05 2F BA 7C E0 A7 7C A8 B9 C5 C7 44 3B A3 F3 79 36 83
+ friendlyName: Basic Self-Issued CRL Signing Key CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued CRL Signing Key CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBFTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLTArBgNVBAMT
+JEJhc2ljIFNlbGYtSXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJvLh5HoW8mGRzWeJaiULtvBNwejGSVKBBvs
+kgOl3tZPkDrTH+O8gQ1os1sTlAGpEbCeXJ4wBFM7++R2BT5uxrAM/DThMcSakEuz
+IK7p896N+CzCy+ylZt8q/3mlND5z4uWH9f9sUSv/iA9Gppye3aqQWQfFcgeCF4PX
+6loBMiEpfccBQL1bWSRYklkZFVzMwqVZurxqOqlLVkX3YiWuKdP4d1H92NzMCSY6
+bd4qYOeNx3pEHeW//Xn6JV9UPa2NrsBgAFxsXCEq3EgIk/Vy6yrJ1gM4c6hQZNo5
+mMHHhfwFJ9W7nI4v6G38Ih8R1BimvAMgbB67QWbB1M9fvs7dKfcCAwEAAaN8MHow
+HwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFCmaRS42
+lZ3s8l5UnBPV2fZEkSwTMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAlYZp
+OypzMxPbyQTGr4YyG6KfC6jsXWoDPjKTQ0Hf1MxJqwRhwmS4VfAff+mVu4E/c7D5
+6RM94oLGUSvhDOY/i4Sd3GvRMCHcMl+oIx+2ixhSVhekvtdZayPWTmSDzAjw02yg
+6KSCHolEL0pKs9+SuvelVQtO/r8/7AL3vVfJyS/S8bG3Q8rPG1G7LY6y92kbsq4i
+uxHWR8y9kY4nJDgXztdPmQND89UeqmhhgiSj2vEI7nSFDNRqtVFmLJubjhc335q1
+O4ziqvRFfhrFoEAuZdo5ivsYA4lVR7OSiAA2CBu7p5AKhn5njeGXSfqXRE32xzAj
+AlBwl0hRSkow5npWfw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F7 AB 05 2F BA 7C E0 A7 7C A8 B9 C5 C7 44 3B A3 F3 79 36 83
+ friendlyName: Basic Self-Issued CRL Signing Key CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,44D03361F214F3FE
+
+4G8csmNRDxV5P5lDILi1qKO7gK12cBhwKnzMbPzpxMmABdmisgALWgDBfLBBaimq
+d0YAT4S+O++fBaJnFwO441VMAy1qKWdcfGmyBOqKyAE1jeLV6lBKr96rLjZ0Ues7
+L9e3AsIE45dpn0cP3VENj8BKD8g5kK3QeqsoRSybF88FtJGdemx4kuulMfBSoDja
+wBB+4p6HHZqgDl8/bOFY+KI5p3ToROyhmcM6DioCDRcxrMh0bco9LoES3WHmBROH
+w8NcMv22BG6armqMW8iIG3u/f1RtEy9fSfKTX3bt8qRPMKhJIov6I9YuEWpjUPee
+Jq+I1IHof4GMKh1wQQIXG23Ya18vLTwg9NFh8PL6eu5s3Z3gef+POGIJqsY+25Sq
+mLTqjSNUur1yCm2JEshgu9aFQs7kQwwjcbozxKlRVQWY2QmSdbkuZnxXtRrZJqy6
+e/DHG/URstn7u0Z91cvjhwgeOkDc0HToqNRu50gn2QiSXvYJnHI+FKjcfRpNiCgl
+dA7e6dBOZiXiev7Jj6ThYH4uwiGsABkiwY/Lm25ufrnl6DFERC10Phw7qpyPt6YO
+Saw8u+6OzyhDMFVRXquOxVp0R0my398OWPZgU2CUa4ofJTYq5xZPYoFnd9VGElTY
+wDnWIF7O0QpSiyVoFHeV7WuZH6JHzXZB/r8KcrW4qNYOztOuuKMNshxBaJAPqKVr
+uvSRqd14518ZyLfPzRSFbJXEOLL9tAwLFcbFC3SpdJdHBYUQ+oB9ULxqMS6PBw+P
+m6pBVK84a5VCmQp0e4wlmSG34i/Sjm2aZ20avaUrlu/PvJR572wzrmY6CzV4L8ea
+lhTpJGjop+o9XUUeCSldvNPRoCJJOEV3q+3MVGnh7/on5buBEj7pbULd/IzV8p4N
+/krV1N99ikIELRoSNKzFVPF7ivgkQOCdVw3+rwa8nCSCOC6bqVfx6145fFouGUoI
+COEzt3HG187d2aUvXwcACvlxkjPLN05pzHrrKu019AU/6mDOZLm+wxzsrfQYqSjK
+n9hHpdOkf0MTwaO5mYDP/J0/fUE0KPla491SJIoPwGUHFG6t77xj+PlyOZK3u1op
+ySmC7aBx0WwbQ8RaX1WBAVTmo++J4tGxobpftJx7dlpjs98rP5+EUjph2oBoszCY
+hgXOWxVpAhEup9MSKx5TZI0qkH1Ory7/p4lNOgSpAALFlXpTTZmGMGhR40i+N+uR
+iM4akQ9A0tVUvXZEynMEK10n4W8G51HhbJB/BPcq20VeJaPm3hdDgHmbyDmnn51n
+iDKJCSJ5wn3EsB7qDwxbMsMN8OTLM1c6nsvdvoZzITUVG2VMSYx2py636OXwRClB
+3okmWP1CM0XyKF/ZjTpcKcoGK/k5UfEgM9qtfiK63Lrj+ZCTcTAU6msTUqjd30Xb
+X+JLvgWfWHzJjx4gV4OjiSY9SeFKtZRL0BU5GWvEMzN9bh8ypSZhgvcXVakuGpnU
+7WpSHjtVHCMNsTIK+QcmBwQL8TU/yeBQcc+Bv2VlkwdwdjP1YEhlwRj2xqqDaKj5
+Z3SWFzdYa0C37X91LrmgA4jyOQ5JDwvmSuiyEXgB2b2ubQ5aL9hDCA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCRLCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCRLCert.pem
new file mode 100644
index 0000000000..d26b6e327a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedCRLSigningKeyCRLCert.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 7B 46 A6 9E 26 6A DE 25 57 81 65 81 4B 80 C3 BB DC 97 03 B4
+ friendlyName: Basic Self-Issued CRL Signing Key CRL Cert
+subject=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued CRL Signing Key CA
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued CRL Signing Key CA
+-----BEGIN CERTIFICATE-----
+MIIELjCCAxagAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEtMCsGA1UEAxMkQmFzaWMg
+U2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMB4XDTEwMDEwMTA4MzAwMFoX
+DTMwMTIzMTA4MzAwMFowXTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2Vy
+dGlmaWNhdGVzIDIwMTExLTArBgNVBAMTJEJhc2ljIFNlbGYtSXNzdWVkIENSTCBT
+aWduaW5nIEtleSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMB7
+JPY6CCsaf7+x7xOXYuekYA6S8sncRWor8AbIH0EXsWYHwfoE6cWVmtYrvewbvug4
+iO39JecD8f5/U3v400q9tM9wnLK1WQeGMktU9y9kv5qcbLDpO+ayIo64MCT+N1zP
+QMMjaTTT0p7bKxDBXJ9xfQ/WRDd4XCHpR/i1VdJwUz3XM1NF3rwdYQo9N4ZOCqlw
+oWo5cUiAsU8kJNqO7oS6O4SbEgTpE4b3k0+a0vWFbLB4GVgC33VBPYW2yh+0f9b5
+4XUkz2xTk8q48xHxQSD0QV4F2AyHLjuTg+ynSZwLVoQ/Z6muzDjmDZ92lX1aWp+G
+IflBWKEVf9NcFb0e4kECAwEAAaOB+DCB9TAfBgNVHSMEGDAWgBQpmkUuNpWd7PJe
+VJwT1dn2RJEsEzAdBgNVHQ4EFgQUJMFVcfqe4SGFKvCtYacVudVNQxcwFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMA4GA1UdDwEB/wQEAwIBAjCBiQYDVR0fBIGBMH8w
+faB7oHmkdzB1MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTFFMEMGA1UEAxM8U2VsZi1Jc3N1ZWQgQ2VydCBEUCBmb3IgQmFzaWMg
+U2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMA0GCSqGSIb3DQEBCwUAA4IB
+AQApbC4TkWyKb+M6KLhhxF8tjfw/GjGv1laoCAlhW/kUWaJluNiOjIPvcrd+yx9y
+1Fqq6HGPaNv73GaO+rEp8aGG3tiCiviCaWq9SB2JpTgvQRz7qOGJ3boMTN4i55zl
+5+acq11NdMbLxnFb7Lpzc2QbnIKIuXQ2EJ2wgGm9jfs6cFLNKfNQiBkObeQVRSf2
+es9xqkY9X4Dj4h0HDYW9qOg/50r9/6kCByUWmTNAFm17IgqBwMK6n8N9O8qAPnhr
+E55WLuUUTllwQME1BukTrtrALVXFlFohEzA58wtNoZQ2PPGPP0TO/pQ7VtGCi8pW
+TJxkdlqxBhl/uyOGYopFSjw2
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7B 46 A6 9E 26 6A DE 25 57 81 65 81 4B 80 C3 BB DC 97 03 B4
+ friendlyName: Basic Self-Issued CRL Signing Key CRL Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,81E92508AFE521EF
+
+VYXB1vTlA6McBsEVnThW2sKdDnJiTghN6vmfRJ9gytkwgmlpc6zY9AmNg9xhDRQL
+zf96D+W6HoI+sU8Qv1s7zADF9FOxtDntwgH9Uhw0Fj6QWsXRcGbs6m6KgmdDGN9G
+fZWct3qI0j8n4LFn8Kc2ygR/WbeOZAthBD5Rj8rCceoEMbKmCh43XOJe/0UGybZi
+p3C2HMfkNPPeKZ37Mpwy3ucM3gVjk71fTbi9VXHRvn9SSAjiFQSstKGH23TuP3gj
+wxBMvzOqDZhtmRtzXFV9RAEhs/ryKpZg61OV97tW9wZm8p3tJePKxbmdaa/VHurf
+As8OKzG3x3VR/fUN95uTjchxMSckeAoVuQNCW3z4SI4RO/eA6LhZED03sSe1M1W6
+qCquSGVmkHknb5AqxgrWtINKQOqu/iV+gD+rlzcGjCSrzIKbNbElrE2YRtdvEf+d
+E7hm/zdFwo0Ag/lF8o5s7A+ygTI+3dkwwVuWPTq7JINGApspXDgehIJf7zIKregK
+XnwNr+MvlP9qJm6LrzTrJW6IW8aaJo7vSLg7jKRXcjMOhnkkYag2pvYgeTODARIl
+2LUaH9xcfKQwuo7hXOCOgz3mDzuFNSrqA/8LPKaGASFQCsJ+JWlqQNqMxTxU57RE
+4DyrEezMmUMBGgtf5k5QyrAThx16+zdbJPbkLJ1F4cMHYhDfowRXwNkZNCOqW3zl
+u7fciLynocwD0xwh8z/Fr6wSelVRL8cb7iTc3aEfMSBPGp6GLUcO8wDT8Kg5dQUM
+F+AgxooIUdHqZbwIT25g9hZWhv78hJfUPdRCFzi3LE7owvwyKxinUw5gZ8eqcqrJ
+AAuNRPUJWfbk7q5JuImHIgQltwiCycYRazjwvckJvX3KTsxDOJR44Zkl9cS3AA1r
+abBpI8MDjEIoC8Is+IuXdqX1wyA7fK9w6UUXSqzfd23CNpXZDLH2gV7U4WiMVJjB
++6Vr/j7uRTjUmEQ7H/UuCgQprs/4HD09L6J7rvncs+dq8CGccQG4HLuywBgzQd+N
+6I3WpMtmnflPJAHRMb7Z/XLeed5wAy+GHX2oYnauMdIvBfMiycXtx0U03Dmei8YQ
+ymgR0+AR3tCjKZkWFDcutED1Bs8+uvYx8Quc1CMM3Aoclkov/yMbldwOzMyBY8uY
+9GBSd7HYk7y51ksbOKyusHO43v8vh+Y+jkoOKGYqwCMBRepXhPn6Zi/lhuduITXn
+Jp+CFzzdglaqXNXoBzm0i3BdMrymmHpOOax5WOb3RCePNHau94Ohck+7WizVJd38
+2dhAEPnOyTS4ABhCkV1VkLHvXEFFgGBqHG1oqJxz8UI20jc5NXiaJeHX11/U9Znu
+itcrTBZ3VgLkIXkd4bV1olpXNM33GK0tvOA+pOqeG6kYJiIW9XVILwZcCJTLyFVj
+w31PCbEVD+RDQNw5brCOtTFA2xhnKjqEo5JrBNJbzQvZaPp8W88wuGDGeu6S4q4R
+gAZmcYpUrMfpM2bHk8di/clepLwlT551b6aFfPbuLvgYZbPauJM8Mm/L06P4WXRu
+mow3wA49YZtkBqfUPrGyO9sLMsOFO8T4lYBuqVLQTwFH21q5+fJFDWEtcqoDKwSu
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyCACert.pem
new file mode 100644
index 0000000000..0c57da8dda
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 8A B0 4E 26 B4 94 C4 F4 FB 01 1C 89 1E 7A 47 7F 7E F3 90 EE
+ friendlyName: Basic Self-Issued New Key CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued New Key CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIBEzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJTAjBgNVBAMT
+HEJhc2ljIFNlbGYtSXNzdWVkIE5ldyBLZXkgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC5XNHuGz6iZWNrbQQ+XdMzbP1SPooVGGXGj+rqjwsBJMBd
+apOl0bPLVFAikdp9fDHrH35OtKliNJDYMF8bHIDNAslp4XzXSL5c375aKBwBh45E
+qqMf5Ny3Hx4rD6T8bGgusQfLpkByPW3vXvJdvMVOxBebK86wjlRzqtkJmR8sUFZb
+1LvX2lqPV+kAEMRET7EpvYYsEtWK2v4JxwM3AXn4BO6/q4CZnOkdscQ0s0l6wE81
+TWepi1DQ2gXQdCsRYMT38MhKfUnOC2E3N7YKgR7lvs19p15Zbjzo7yhC+jNvbDdu
+/IpQFYp7Zx5FXN7VVoYnUL9LtVlDRx8lekzidFo7AgMBAAGjfDB6MB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBSg/MAs61XukgZsqR7p
+X1+in2IjlTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEVk+zdazhBmjrFG
+k8gFU/zIFK2usFkMJEJKlrNib05uBQZOb2CImrFQyPnxtBb8ejZRk9d1zlTXQs4G
+6O4k9Z24Pd9zbTq/rponVyu7VmW1vAkNJg+716lTeH1VtuqTuqX63mBkISHRY7Tb
+O/KpL7cla8EfoH/I8iITinQR6c2jbqtUhuiEPsgvLXJg1MRuLY4fjJavcH156FZE
+R3ctID4Ww0uesZfVsV6sIBkw8S/EbCmGxs0aSph4qPIzSa/ay+HWN+gXR3PucFoL
+K8Ryx/7FB2JHAUu52idJF2liIhrEeA0Mneiu+RY1RPUel3t/YIVFtqcFJvVz143U
+M6elH8Y=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8A B0 4E 26 B4 94 C4 F4 FB 01 1C 89 1E 7A 47 7F 7E F3 90 EE
+ friendlyName: Basic Self-Issued New Key CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1CA182710FD852CF
+
+NoTa0aX1LM2mIEhbAb/Dfvueb+Io0G+kEJcuIV/07hQ09nMvb6azUEYh9T8b5nul
+a+tsYrIba7vB+xqhk595df66YKMay0JwLzBF9zABlRB/XpomHTcyA1cc6r9kclpw
+fyhLMiN6GxW4zJZrq6/UipFIhBHSdYcf7SnqeweaUO+Al0691ieWrDzc6qC781Pm
+gBsvTwOtehUJhd58G+rZAcz8XKKlNKmPedD9Ljoba+pQLe16jTqKLEmYOkqfROng
+nUAp60UhDZiM8ea6VTvQpE+TT/as91msr0daH6II/ztVALFKnYGg+0JMA3XEo1lU
+QTvxpc30u7XCIcPWO3yiyvmkiyQFUFslfuMK4yfM2GVTDNs3q53X/32iiQEjR2B1
+/bHXWCXrJfjTw/R0oSyKZAIRE6oiVnBD+HxmaQPAAOU5yVQMRdPAWEhlmt8iJzsM
+zb2GU32FF6G5P4KPM8e5bQXIv1wOS5OHOJ6FF9UMW2uMa3IgVWR1fvc/r6L3nauV
+BK3QWDfrqWargvW/tYnK+oKKJfbKwl2uUO4uBaENZQDxOptmCMjRi1xcNBnmvPzV
+EJVM+Az3fpL7wEmJJW1rap6DmoLiMC1qNvIIAo23PjUnz0CVbrYlXY3WMHzoSnrA
+aZF63VS0wKdlVQzvX07nbck0XoPAeaU4imj1Uo5DiSeaaHZtI6HjvydDpO00jJ/x
+r6pBphRUZrLyO+qm2X4iM8yZV+Tpx00DdwFxOqCq1nkOOxo6sgmc2SS+p6Bjo/Qw
+PfY48SyXaYPyDYuJNnjiYG69Vn/LxCbUH9iIpOzNNhR5V4L08C9fGsAnCIWD58Gu
+vQFM2eCwJoWpSpO33K8hlrgkODcNW4djbFY59qDNhSeSN2Vek+R7Mxg5s1n+WEb/
+ETMnmZXhar4eazlYlbTyBJC/GP6W7bT+TCSpMmBdEpQ/oaMVanax/gnVB8LFaa0D
+LadAY/fD2jgM7tZS7k2g8c3M07pMjE8Mhv3CJkgalH0Ruzf8wndfqWp0BRw0EKss
+yamMO9RUhCHXdBVdmkgOy49v8BhC+yCd9Jml8s83pGNkqprU36Zz+hZTLYxtouU0
+HeMw3aa5D78CpO/Hr4PN5QxVQMvzvBBG3SQFE8M0Au+u316pIZjUp5qHEJATazFz
+o9ZlAieuN9O21drccNYPBCWssXbV+GtfQxTjngHnqrrJtBhiUyqQOH6FzBmQnjfu
+uZaP5wNeWxdejV7/QQlt4mtNdEztHyKqNe2q4l1FR/VeBCi79uA/uSuazSe4xqoC
+nY1tEpKtQ0u/Z0uu8jjVtNlFskvWUJUikM0o/LOHkk/9DuphqoR2gKXdVsDpA5u4
+SFk7LSdEKnkDCyx7flzoIcyfWFhN6UCkKlmypHpnCRhWEeIRhtwILLUNNU9hBd8W
+80bmUd1bOVzlEHqmzmJA5qlxiBn7Fo6j5zemA5CtiPhduNsecKvdOa4hIzvtuJev
+vUI+qurHN9ep4FVVXzsExW7aLRKEpm9QhNj3N1ubTSic8B++RkrAAzBgQqpnAJxB
+BLWHT6NyCCm/sBAXTwlLr+uasGFbJAOOF+k4ENapkAbrtkQmPG+wfg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyOldWithNewCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyOldWithNewCACert.pem
new file mode 100644
index 0000000000..c04ed686f5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedNewKeyOldWithNewCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 11 8B BC C3 76 8B 8A 53 89 80 E1 B5 AC 95 25 AB 3F 34 CB 36
+ friendlyName: Basic Self-Issued New Key OldWithNew CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued New Key CA
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued New Key CA
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgTmV3IEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSUwIwYDVQQDExxCYXNpYyBTZWxmLUlzc3VlZCBOZXcgS2V5IENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyuYeWkqqoBSkNp3YdQQ4G+ay
+LFZFCn+bnYVlzzsOkYPtTBLCrGmO4pbRT17KlawJz6BHgKuorO6P3gDDtxyJA4Ia
+i4E3JFxtv496ZacKkj8ktM4GpSPK3e7GioWaGd7lUqS9OYAIJxrphwHE2Vg069r+
+EmwSDZFGl97qxJsEkapd/FfrnYGCmCeIxZix5ulH8+cQbBwZJ3sLCW4S/HYhmYc+
+9yaL3A29enmnPMRtqhqv0yeSugUweimx9BcZ5LmQL3usvWnsvC/OwuuXVt9u9SMF
+NvrM1YNraYPYDCXt5Iin38J/N7tQDoohgbZJ08nBfQk8ki+wSYiu/e5dC2UKlQID
+AQABo3wwejAfBgNVHSMEGDAWgBSg/MAs61XukgZsqR7pX1+in2IjlTAdBgNVHQ4E
+FgQUdnzYZAQ0CU/fcSF0DwwWmzaogtcwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
+A4IBAQANwgEHq+Gto3HLdtdiToVQjR+jvcI2oAMSwxwU0eHK1gxXvcT4zZR6i+aq
+Y7wtO+dHmo30QF4AeHGK7k1sYrlg3gbmd2dYKkhDmGO/Jz+Ca+4ekt/6TKgNMaVp
+30vI4wZrWaF0WGgjAhmvnqVn2FJR3QvYODBnLP+FI7wPejWa8zotkGqwfItm0UMF
+0VSKJ9OYB6hdNX01INtZmCdP7oPaH2syEHAmjjrotbQjdX1IQCzUCRoWAY6vs1ig
+pFuraG04tCBR/iqw1FYiASQuYEnlDezh6/g5939WqY4DFdXZDDmPx5P6E8hsLeNN
+1KkYRLxXEMcNVa9szORpOQP16nuU
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 11 8B BC C3 76 8B 8A 53 89 80 E1 B5 AC 95 25 AB 3F 34 CB 36
+ friendlyName: Basic Self-Issued New Key OldWithNew CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B88FDDABBD002B91
+
+Ye82Wk/TIzdwItiZon6+kZrsjnbUdVdTaw8BxIwYtP5m1nbKHpKCtGzk4kM79iLD
+gqjwSidKu8aaK0on/QJiUvAv/r8PusRTcSuJ/2tXeLAxcPjFjoamHmfJtfW/sx1z
+nahpijCH6qL/GlznyvbokF3Ay6PRWYhcCyc6KBKkJtNs2wLDNV+cwjr/9xjRKmvz
+MbPBfzScPyYHTnKs7OtvVXBCrIw8yX0xkfTOd+o9JVJVoGjwvIofau1jQwbWXOn9
+KBJw0hO+yTd1xHC0YdEIJJcCfkd4m3IMCmREgASTtIyc9aEtNB+5goC2hj31g8yn
+ma77pYegInyt3mzN5idiBq3DfSsj4k1McsllrtJ6ZhThmEkKRw0y1iyXUDJt8HZe
+Mh99A2M0I/kafvqnfkBp50pEfLY5mOw1LlKfYSWncmgtUpnZRTl5mm/gw9x5zVLU
+Fn5xuPo+5fSqf73FTfww9cJ7iB9Q5Ye6B8081KPJYD/0tyBi51+2KEy0iltcNRhi
+Pe8vLKNfMWJYx0FneZWdLg2d9NyfderEZSkFuIjwKGpoRQL0DQoUxqOrKjudDy6V
+eotuDpp1J1iZjxgUejtzTbmH9pxASFAfuhMyaQo5ktDjVVpjABC0Uy2CHMhcJ5CI
+EGb6lVRAnAiYSnH+FKDa3EqYFGEYLMn6bs9eo6htWJF/P1uWPve6ID59Fa/QzHVS
+B/xiiLsy6XmAETsh5kUwvftJ45SXEOBVhfFOGqU0N7aQ8dBWwjUD2CsiKn5IWyw+
+J8H1cerc0jPsB+K8Wj6NO3TbLr/GmeefvxjvKi3GlUApf479L8Mw2SBnUBnPDnmp
+aw95YfWaCs/3DgqOcAfpEXt8stsuZSoLQfYkMfJBJObIcvd6mQChe2/ifFVNtknD
++5DBeKB/+HH3fpTU/57uQQpO7hfLebSVIf7O07ToPOo9FLevTMg5iTcux3NvsfCW
+kVmIOfkT8sPgeeGbqpCHGMRSZB56ZJlogQE7zXjJeSeR2/uTQT3amiRLZDBIxk0V
+sA9tcMNW8re79QjQQnTOjYYrRmrq6Dg6fLLbWWdJZUpAhXBE5J2Qk+BI/8rY0AU5
+VRnjqq5TfURuPPozQhVsQZHBGDNJQUOICeF0ELNn7/PAtNdh0BtqiAfowZx+2Adq
+2nw2CaqaGOdyxbrRC9rYHULA6nrjCGquL9XGWONFjL5qwCyprasYOuE/N3g5dEiF
+I9STgmrTjqR98ydBPo7iORWPWgtmAv/YEywjOahKYWcSaymJMkFMvvyLEaswdR74
+0ETMllJlun83DpRiAiYBcQ3aHN7QEcB//YcVnXAp0Ce9BZKZfU/OqJyMrQVznCjq
+p7nXXcUdw6xolRwumuWdzADiwbs+0WKQbDnQZAIGe9Btl1JhZk5ZUJq9TWjLHdfT
+x3vAy8/PHh1qsY5D16r/If9wlKftSQqABEqKJTkD95dZx6QEvoYb+6S8EPcJsSgI
+p+aMnTcupRxrPMd32SYDkhsCIo3QD3myJvr2r/81cV2jaKusihdSvxD6B4Aw6kjI
+R+9itv+ciAr5D9woo+ty0S+qLx524wd919/UgYhzBlTGhOEntgNVQw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyCACert.pem
new file mode 100644
index 0000000000..13d9b8cad7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C1 21 F7 65 9F 11 1C DC 53 33 E9 C3 7D 17 B2 88 64 29 E6 81
+ friendlyName: Basic Self-Issued Old Key CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued Old Key CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIBFDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJTAjBgNVBAMT
+HEJhc2ljIFNlbGYtSXNzdWVkIE9sZCBLZXkgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDON/+4hQq8n9yn0+zOChnBhoToiUxpbFbxeXd2nZuipHsT
+I6CihmiMA+KSX2Dmugp79bMcGt2V0q8wpFzH7unuyGj2J46gLJzE59a9CY9K9SaW
+aW3cnQdpY3XpaqvYX/5VNvbC9xNsdM78d3wYQtWGWF4q19orG5zbWkASYmDjiwGR
+inJcWBtZ+wcBiAKjMBIthvuKlr48QCwhda7xETbcd6Ms1xPVJNMF9NHEVcLgpXbl
+4ZEAlsUu9pqT+4re9wzgNrHCGTxzsz5uOHUl/kFhpSaSbEYmqwGnMH0Y0W/okVZX
+/sXUaaGeyEgLeoT/3/WjQte2X1Axbi33LFnm6egPAgMBAAGjfDB6MB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBTdDXWNU2gSxMsVQMAU
+hhQWMKG+rzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAI+gcK03dWLaBlfh
+1iFqzeQoN9IffPfdEr45bA0kKELDQ2mhez7xqmZc05p54BJQVCldcZ5L+L8HRuYA
+rDXQxoaahQE6QevQtsvdcoVfixLF5xc4nkizsHCx5foyZlo9l9mkeyBmLQtMn8iN
+UnOkZOhkPxsWrgOLE5F/3y+UAf2vYu9AblcXz0w9UOecDkNrzt/6BB54DzIHYWCZ
+v/CC9cwPpwVOgOAwZ9oUfb3IPDhsolRLFlXKSdZEK2MO3B/ATqrvDm1ndETnPs5N
+PB2K5jXS9ydHxNJhm8SUT10gxOV/WNIqATHZAHxEWL/7wGi3sZVqLdUegxBDV2Ap
+8GR6OMg=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C1 21 F7 65 9F 11 1C DC 53 33 E9 C3 7D 17 B2 88 64 29 E6 81
+ friendlyName: Basic Self-Issued Old Key CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,686BA42463727BE8
+
+eCspoSk+HBiBPxPw3/jc6CjBbtpzrvvAvUdXwjNr4dVcyUBoApqhs7DvMk9WaHNz
+hvKgkqB3uis+cS7nJqYD75/Fkkm9hNQBj0jSORAlkLdhERMURTLE51Lgfw1U8wX0
+n0jcO+6tQaN3VADG8haui4RRZ01y6pTtYxnN9ry98/WDKgNdkMI76U9o1k6dTXhO
+anSzkbtCL/N/nlTDvcZGdT+PQcHUy1pjYgpfcE6xxC4vNWpgcfMRFtZ7KZHv5QzW
+dexqgBoTP6VMgVUpbpUm26L4sQ0Vs6wpVQrHrHjIo2ZThuIUH8iX8GNreZl/LhIH
+foYNeY2LtWca9+qOZGUNWzFwnXtK6vtfbmQMWYtYg3YxOIlqKbzkbkJufErP4dnL
+6Idfwz7mgw8KfNpvh1VamoHiGZV2FksZazv5N5fsKvuUokK82FvyfY9eIIU6ObRA
+fROowXltBFobm0VGIfjGvRlZrNFFJdkbDTIZLqF01+u2/E5SO92QiZ6N16SmuJxE
+hAEcW/NRFz4b2JhHaYO3dLxtI/QLXhuW0jvMZaRyAB3jTdsVIzT7S4HIOgHnJi/G
+Z3o39Ss/cdGCuejzDfVarPx2CTSmFI5Xy2T20DJkvQU4gKYeZWZarr1UMIUybXPs
+A9aBZHjisoSWe8eevsIH3ywbeP9TUC9OFQy2K8gZ49g4/Is9ETMz+FpuqVXIqDLl
+gm7nVFX5nNDEvnzHcJKa0Sor28I8mI6a7Fr8/6eXjWkJdn9xWoMTiqnFiZ7+6kmK
+hIJ457ZLJ1LVwD3vHA9xtZTv6S0CiaJp+qUpTT94WuZm+bE6/10h15JHTWIR1Cz8
+z4lAI7EDNMoeso2Z9F9UvhLnfcwRqsZ2DqSlYv+DBPH/3GaEk1CbLhMc+CFoiSJ1
+YAs6utmbPxqDRuKnvBrlLUGdFuIepzcCWv6z/IH/gCcnrmE8domcnQQHAm+nNQWa
+0K/XX1uPjhdMaq/vsj1LT8Lx2atmVFVEHTRJTPlPB0Pn8ySmgutIqn1+7JrWBwqF
+oNX1aTDg6tOm5Au3CD4Pn0kQYuR3aQouc+QHBjlDoMXfQAEThnZTPpkUEqFWmkCD
+yQh1ptEbp4OLDasG/4ZSqW+8hisy6KBw94vnuDihyipEjXCcNyl7OuiaLnaoqlpC
+2f3uAdWPl1SiQmqdpvNeTAa13P7ZhZM9bhY4+5ihczRv0OTMYevfjpNJWfdG7cI9
+8MKRMsGL4SmlZHAhQnalvjrH5+5xO3u2Jpne2rwe5kAqx0tXKfVCIQo/gXfCg3Rj
+qgGizdk3DebGq0NPSju+iaqhcXGTz6nkpGrIoUYq72RBQ7zDN4xN5x6ujeCMHCHG
+vXrk9M+QMzWy8IPKjpWVSWwA8OMLAq8UeN3xlvMxpeDsY3j8PQ41mjyXTzi1xGxB
+jmFj0AiC5VFEds/UA5RRU74QYpjD6I9ugIj1nZgsF03k2nPo9736UNt0vsc1HQrI
+GyTU+JI/eT2lAT6jSW2LFkRf3QtNOqhdQfLx2qHZxmUpkeFf5SkBUWixNPsEm1kM
+V4SsRP8ofaSV/ek6/mSw9E2sJ1dDXVeToBEsSpa6hv3mDGxXunJDgg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyNewWithOldCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyNewWithOldCACert.pem
new file mode 100644
index 0000000000..25358166c3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/BasicSelfIssuedOldKeyNewWithOldCACert.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 8A 32 06 AC 0D 6B 5A F8 27 70 A5 01 B0 CF FE DF B4 D7 33 5C
+ friendlyName: Basic Self-Issued Old Key NewWithOld CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued Old Key CA
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued Old Key CA
+-----BEGIN CERTIFICATE-----
+MIIEJzCCAw+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgT2xkIEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSUwIwYDVQQDExxCYXNpYyBTZWxmLUlzc3VlZCBPbGQgS2V5IENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwnBPMPPNq8WIRK88icq0J2qG
+OEExybgfxxPFyBcrFCWbj0inqiig0WPqiSCrcW4ZT6VZISTr6QCAl1dLOcVbuQee
+RAb0cAmOQjJi0uwwJbU0x7v/SXnDVRLsfSVEr/MidweYBGypXZGAKgkdc970LaZG
+929yh9RUliQ5BCSskTfrigH49LEgGBAW3apYmxtEMQb/ut/RcDXHKd7737AGlOAt
+b8X8scwNro1xtAg65ZAZC/QJUtSb/M8RuwWFoR5MJJPJIIqseUnWEfdJkbD847eJ
+GdqXrOG1mg7sbrV7ZP15aGoDPQBxaMMfIZfHcHUGqTQ3IiGzC7yr69PtEN9ZCQID
+AQABo4IBADCB/TAfBgNVHSMEGDAWgBTdDXWNU2gSxMsVQMAUhhQWMKG+rzAdBgNV
+HQ4EFgQUiF++PzU5ZprrTcImGyaxKie1CCowDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MIGABgNVHR8EeTB3
+MHWgc6BxpG8wbTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExPTA7BgNVBAMTNFNlbGYtSXNzdWVkIENlcnQgRFAgZm9yIEJhc2lj
+IFNlbGYtSXNzdWVkIE9sZCBLZXkgQ0EwDQYJKoZIhvcNAQELBQADggEBAGstwlRN
+EPUE3/8XGiiovpDxI2IFDQui4YhbkoxuY0Cn99tG6XeAnO2RNmERe02iTqDTM+dQ
+VRBNkmCSN4doDsi8/14pFeoDz4KSwQeV8H1bFZn+BPHs3E1rCiZOxNSPsgPseReT
+F/FkVyLsChKEJpPC+mCFB6DUUAaoun3EMFKFZzL0BqAHOnQPWj5mff1XKth0CyPD
+4KLl/n+n/IXyMPftmCDaFpvC3QcYDll2jnSXB7VVcipEcSJbzbCRKU0WEEYl7cd+
+agEmeuwWa3KldkWU2hZ5iiGxPPrZOzemyRRu1a2bWARcGJIrnZaJHiDrPmRZmYNX
+VIztjeAlYFC/hDU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8A 32 06 AC 0D 6B 5A F8 27 70 A5 01 B0 CF FE DF B4 D7 33 5C
+ friendlyName: Basic Self-Issued Old Key NewWithOld CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EE464B14C12B703D
+
+kPOe+CWFp+pW4sWunL4ROXcBMn2cNwjylW9O5KugAhvwh8zRntaVyltp/JQTz5ly
+zVIeTOsdWkaOq0sT1gAXqBQ8ZAsHFPFxuxYGMLHZaIllbgZh9DV0AV9NjmDpsCJv
+eqTg/uvwLY1qbMF6qkiaM6pHxglhF0sgkZBhmJGXTkoyuoB+PpBtm5E4to22ks/s
+WkPKFgOt9qX5Pe8qEYfCxvnZ0mfg+iyQFPLMgTH+NaOzvGoQl0KrsNDCiuWEFswA
+2Y0mJ7y+dVkeaYyIy6XSjymvWF9vMuqozC5jpbc1OloAtdCNClsPJ3sD75Jz/+Rd
+TMxgamq9oeB6OZrLK2Ep25uBF7NsHxgidcoBLdxck1LlJD90vs/9+dockrwfFScj
+FSfU9O9Tkg3+m5oYchI2jeIQuscVGJHKxd7/j6sBEhJyYiZzQsbMqhZjNGuYZxBm
+wDih9bawzIdu7GGE63bu58gdYrEFuU2/DNUuu7OcGn106TYiEkQZC2yMIud5lOYe
+Vt/m9t8iBxZBDXRWqer+YCcYvsN5fRDmtAKbJe3Josi0RRpCcEL0+J8PcSbA51yE
+q94iEPWIA5gAuROzDs8BzUxqefMVh2jfMCmnmCT7/TSQsTaYs2lm3MuUg2MDEN4W
+xe5Tv4JHIvx6bx+wfU+Qt31MGoVEhhdtLCUlJVkbv0rwLZWbllmBPVlqkBBMFP9V
+CPQN+ujEpFH9v76uBnYf66bQYcMYcnRC5ZAgI3aEgG1sCdTL6WIewqaSBhV2rzeR
+ZG0THu/a68IuQ4RFmNOBxYBSV0U5j3qTgQWNtritn9yA2sJBqtYrxeJBOaLGvs/G
+70VVNv7JH7VfY2BpefcmixoyOUHegj6/y1kTy2PAnchF+uW/MndqdgZQwBp2WqWI
+yYAXyqteQedhXKPAIkSqhkXuRTzFmNs+0ePk0ai6D3Emjujx+9JPu/onex6ft+lm
+4tctQL3O7m3TMqhJ4epyWHOeinIu7794NBH8BM1eCJg+Hnmfy9eHGhcmBUH3FBR/
+cuENsrlPAhZrZ55P0vIMq4CL8sImcDKmjDuf1HNftTLRfu1ujq9VISwV5jIGWm2v
+zNG+E+H9oDWOwVWihVn7RW8pOQnsy3JS0dMw5JTUHl3096uZvfy4P9sFicKRrFm7
+AaH1266VcV9dcmVwIKy5QUYiXdAQoY8AGzLBbMqo+ItjNrvyiFYeAjRZevBLnyhk
+vFHK+L3V3IcHgag2Y+ELzLXu1vrKYKA5b1jJGvYsCZACgDFJjlIg1uwbPZAwb65/
+50+7UFjhiC9DnrW73d6LnsmsronNhUqUMmQbt3+U5b97+5EOdrHl33DiAEE5oWYt
+4BWaKJ/aEPIKTFAVKdm1N6G83CinQDnpYTMWIVNt5+m1MVm+eyEi1j4pXI6JxePG
+3cK+1Byg4y8dQJDRMdbUfeYqjCgSMT4L2th14w6bDmy128TEqXo2K3Rv9qvgr11o
+rl1uyVR3pVbMTU/X5qdk1W36JaUqdByX3jyXjdApecfKMCXccwWI2gl/V9MmLZ8d
+tg4dAMfeLNZHpQJ5cYSH/OXLCmjEkqGlOUTkbUUxa6s42ENKBGE21/Ti9e/XMOa+
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20.pem
deleted file mode 100644
index bd06526d83..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20.pem
+++ /dev/null
@@ -1,120 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=CPS Pointer Qualifier EE Certificate Test20
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICuTCCAiKgAwIBAgIBFTANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBfMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNDAyBgNVBAMTK0NQUyBQb2ludGVyIFF1
-YWxpZmllciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjAwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAMoJaBG/FNuQhA4cgeiGiLpg79tevgtM1J+7DRztxWNGR1ETJ2fT
-76YKUm8p81GifGLyp0GPixlRYrORVU04fWNYnx8Zf7rkoCPeVEDinuLDtIrrENam
-41t/iHh8pI2pzuA+AUUT9MOXDyVHFx+hGhjOseGtcUIJB0h641auD/XtAgMBAAGj
-gagwgaUwHwYDVR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oVlMcwHQYDVR0OBBYE
-FMLcmlwicNMKSIWer8jYAJSooOpzMA4GA1UdDwEB/wQEAwIE8DBTBgNVHSAETDBK
-MEgGCmCGSAFlAwIBMAEwOjA4BggrBgEFBQcCARYsaHR0cDovL2NzcmMubmlzdC5n
-b3YvY3Nvci9wa2lyZWcuaHRtI3BraXRlc3QwDQYJKoZIhvcNAQEFBQADgYEAfDo9
-XQCL4ynO7TfTvX9MENaHI304AZw1YU+SP2zkPuDd4HxsI1FK04q1NbIaJ+TOVfk3
-Fke0kNKWelXWa4JcqZ8eg1RxzRsqB47a0IdMOcVwwjKNI5U9KkHRvHjCBMip0wjU
-j6Qw2ktcJRAOZf2zsNks/lq7d2+7udwTCiASQ84=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20EE.pem
new file mode 100644
index 0000000000..88d531697b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/CPSPointerQualifierTest20EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 10 DB EA EB 83 D9 52 B0 6E 6B FB F7 D3 A1 04 D5 B2 47 49 0F
+ friendlyName: CPS Pointer Qualifier Test20 EE
+subject=/C=US/O=Test Certificates 2011/CN=CPS Pointer Qualifier EE Certificate Test20
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBFTANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGQxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTQwMgYDVQQDEytDUFMg
+UG9pbnRlciBRdWFsaWZpZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDIwMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxhW1cwuWNSLDxdyrOixpJM40XwVpspuF
+pFGa73TiwQs58B/3i6tfcGygyAAmZHYGoVKjIq5LvPbirMTnCYQ4AtPQwji0AuQN
+KmCwSAAjY8WPT73mSvAEpv1C6vhWq/PYcNbHq1PHstsD+V3dXc/sLvBXAXPFEbD+
+nyhBpIReB+efZ+fcLDRg34th2GezPq07Q7OsROHL+35JDqtMTPibpsNSSMETa8B/
+5wW0j9PxpQqufx0sVPpSXtrcK7tn0dlhhwW6UnDfOQn1XwFqmYG/UQ7fKU/uIH1a
+VQTAA7GnemZ4W0XFZwoccOOiDapNmlMfMIs4JhlkpUd1uTinDGCzPwIDAQABo4HP
+MIHMMB8GA1UdIwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJMB0GA1UdDgQWBBTu
+QtAPWnapZlaIwYeYrcROSL3D4zAOBgNVHQ8BAf8EBAMCBPAwegYDVR0gBHMwcTBv
+BgpghkgBZQMCATABMGEwXwYIKwYBBQUHAgEWU2h0dHA6Ly9jc3JjLm5pc3QuZ292
+L2dyb3Vwcy9TVC9jcnlwdG9fYXBwc19pbmZyYS9jc29yL3BraV9yZWdpc3RyYXRp
+b24uaHRtbCNQS0lUZXN0MA0GCSqGSIb3DQEBCwUAA4IBAQBqPx9Nphzkn+AqwLQC
+tz30JaETh2kPhqKYjS7nUwbHzXz/zxeTrbQ7fRy6UGa8c1hyUtnekKZ7Y8T/cNAv
+ltT+mxWtye/58YbSBSu+RdTJmJZIXbr7ZHFDwZC6gcMwvIuOe5nGRom6Yxthmciz
+rCQ7m6H0VqkwZLMc2rKPKw9t2MmkUMHgxCIyh+Fa0x7jvkbe4cUP/7+CRr9tT7m+
+Lh/94RYNQ16zIN/GCZnH9s4sjQLnOiGMQ41fa9zKngazpS4fMrxXPGc+NgFjVrk6
+qZ+NRavzckQPEGoIZrR+8i4GFxfjFzTD+rGUiKHb/LO+n/+GKJhc3EhyIuHulRV4
+eB2G
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 10 DB EA EB 83 D9 52 B0 6E 6B FB F7 D3 A1 04 D5 B2 47 49 0F
+ friendlyName: CPS Pointer Qualifier Test20 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7280BC01FA9C2DEF
+
+hO0TJe62lPeI7f8ZwXJ6u89ylbiT79g54Mbri0gQDYk1oAZDn+7JkkNOwsZyI7Bw
+mdPQYqnSaWYkIZXCqm/vuQuWpO58SgxqLoL9PfAkG9M0I8FpEmI4BaXrv9m30Kkx
+1d52XSE3h6d9LdJ51qXsxgSngM7tUaKo/6mk3u/MLdfhETfqB19Q19wLR2yoeYsn
+SaizInE9STM6yswayHOrlrhVDGDtbRi7gavaxaM6WgQ/8P98JwrcZ+IK+4K/kdkl
+KhhOZsyZYrJ19HlWccv0Vxn/rX/K+2Ddu8MLr/g79E7Q8k6TAcS1ExAhmMtqXVlR
+oF3fGa96Ai3cjehUgIrgsx/lKjB9bMTV0m7Nvzlfr5ERuaEHR/Xr7jl+rpAU3jPc
+7gAThCQe90xFzOnNhFhw7xcAPMZX4NFtED6LXt0sEV/NbBxVcHBeYaLBZRXi7dNu
+PggRhqAA19Sl7DDyf+VFAdlVTbHRllU4SMsW/2xbicM0SzVrjs1h47n4SiJZzR1n
+RXZ5WY11ADHUyep74Ba+wgZJASPj0t2/gjRg8FCmUq+sAy8oAo95Khkm1rx/wOBA
+gINsYtfVql7Rj7Nnh1e6W28Mml1o4xrjYzLcqHWTqnt3NH1xHSPm51PKKUnb74qT
+JzgXbABQ4u1JTKMmlxPPUBnKLswap3fdazvr5rlNiKN+tW4qEj4JLNtib2NpLExn
+aceBVaH2G5IuuUGAachdvEGO61ZC+lXHEarffCsQD7xAt0w3zu4nYs4FTudtdn3X
+iVFqC+a9fPPR93YfHB+m6pD3LfTeP2IVGhSAIS5C9OV7iHqR/Hzzt+kitaQxjj4S
+dZpKFh3w1G5hbkfyHII0AWWPgIKJyOEz+9pJVsIogXRC9elZIFwAcDPr/ugoiErL
+hVWKxgbQe9KkPEnEogrU3zcAlqTPiDIHWSqZ7nEdImBDR0LF9yAXBEy0tyPynNHU
+vqR0vjp372HN3CyH1huszkJ6l58qiU8JnOBS8xjnwnE+aZR1zPVuLFyqYmUxwhFd
+rR8LCCR6k1JhKFgZoGDYEqRmFB78pKajK8YoZlF/7oYAfjVh8bygHMYuFIXl2+BX
+lyHOmGUGawsW3VuHMWM6nprLckqt3EA7faG5ifXYvYUy2REqzfUaRocHHm3sNs8V
+vhkSDakppHozbUyfnqU4GWkp5xI8rPHRyoKl14RRsVd2vphVTACoACXLzZNh0u2C
+iX5dXJ4wQdoecDKtF0mgtRqjJ14ps8pBVFk5wA2oZGUO6t89cdKdYNGW2o+agmep
+u5xAh9rhPd5tWSoyzydM1jBfKcGGa9RyqoHe6YYjfpYdGnI+gHsm+qr21FaT2CAt
+hVB4pygAoB6l9uFXsPbm4QMRTPwloquHOHJUUN5bEjxhcQR79T5qPtYxSEWzRxda
+Eb6qiD0x143h94j7PAV5uC750Vr5abQqMpqwfV7Q6JgNBvhqw3CLN91G/1YBZ+e5
+2gxfSR3a8T0ExkFEtYjB1XCs62jnujUcqrEWYuiE6lmxUidXyIyw5FQHwmIPPFq2
+axismUOyMVjarITj+KlE30ZLrolKzgkQMpC0vwjMJYlIhdPZY65UXX8T+n/wqSQ4
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSACACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSACACert.pem
new file mode 100644
index 0000000000..b6eb97d8bc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSACACert.pem
@@ -0,0 +1,48 @@
+Bag Attributes
+ localKeyID: 6D FE 06 FE 1E 1C B9 70 5C 82 34 BE 5A E9 49 2C 2D E1 99 AF
+ friendlyName: DSA CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=DSA CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIEETCCAvmgAwIBAgICB9EwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDFRydXN0
+IEFuY2hvcjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMD8xCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMQ8wDQYDVQQD
+EwZEU0EgQ0EwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA3+URPtrptm4Q1uqd4p06
+sEe9RADHVsjMbtAzhFZHNT32VMjjwq27unXzLzMMpvkx7Gfj5Zlt/CluqleIcjTi
+jgCQ4KOsZI7A9jwdj7TISkgwXn+qnHYmC9sTczODl8DFs+Y39T7/FQ3UoS66Mfir
+h9gLzHeYQm6sk5jCvS57NAsCFQDPBgTY/4vrAOn2XAeWc/2WZTovBwKBgQDM4Xyw
+zpJfY+w4u0S63ZI0tl6+ZXvYcXcEnexmfDsEzrbzUv4PklUC704Sq12aLi9uVvNw
+7GrtmyK4qBPLDJwW6sEKjiEmRKUM+aDsYuBwMcxo9QuFpEobbnn0wfk2WjhvTu+E
+U99n/cz3WWKPnJzNEI9cpA+ctwfsYPO+r345mAOBhAACgYAm8r68RrnkebglcwaR
+1iwnDKicj8nv2gXOXfK9O7sigjC4yPmhGy9h5RrMWu/BS88O0U+nfGtn37ap9xYy
+cmH0x6ionWK0gfjwiP274z1r27bbXVQ6hbaP9z1vizdHHPPNiP1sRFJMWBSKt5SO
+cfWhPir+cD8ln0CrcSVAm6e5x6N8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+
+dbZlp9ldqGYwHQYDVR0OBBYEFI+Qxox06HsMyFnHfTxbVFlgJQuxMA4GA1UdDwEB
+/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAGE4aQgafVYNodDWs4oastLldKjYFnOlegU3B
+iKKfHJTPRF7ibMpIEx26666j+8r/yAo3mdO3AjjEcRYpY861CTnwXFbwvkZ+LDCm
+oWVRj4E7yElt9B6VlL0kkKGvsQsuVTOF6wBApuBRezet6egoy/tlnvhy/BIzEWpd
+2O1Id4Ty8p52hujNqVLWS4WV0zObdvNc9hv028L/hcuXPKFsSUBZLxdAezJqu5Lp
+SS5XKS8jW7qkkzMqnlj5JwZlZ/MkbR74zHzr2YYf4N4oH4LjlQLaTMeoul/Gx4c1
+4baQloxKPHAS6pZgSLW4Q2FEGJMAz8CXT3sFjrX3m+H4V/u1UA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6D FE 06 FE 1E 1C B9 70 5C 82 34 BE 5A E9 49 2C 2D E1 99 AF
+ friendlyName: DSA CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FF088FBCDF515038
+
+0/MfMzElgraRX9os51FaeJdcx6A9jjAzUNa5OUxtrvUKd6DzckyDweCe1boFF/hF
+29DeFyqQZPiHcRA1/hKgGaXhOD469xGlbcdBEVfP+uhdknwihEer+llPlZBndbQx
+ue6w3urDVOI6bU/YkQtFIGah8FCvviPVK08/6HFHqn47+S1cyqaZwGUpwKqDFqI3
+mwujq3jFLs5iqb9q6pBybrxQ8Dq9rYyxM9LW15PjU2qev4e18vK3zhyY4l61xPqr
+m/9PWTvt10OFsusjOnQFsrnhGmKfAYBVlFZMGjJOkmGuuWr2GCdAih0r0rpys2hF
+5G2HvFB1fUbYz0YNnsR+HmGel7FkLlhkVwLmKE/shXGKaLOKEM5A1VxfHAyl/4Xw
+d7ytkUScDWJ1Q0MOZRI8NZXCPagVUFwxYy0GyrSqSyKJS+nlIGSDuokuUYNBEDYT
+5eYamXAS6QvyK71nQa9/+8LTqoWblvUITYlXgfABxiNQklxjc1PfOfihqeLHuMyz
+j+JwpUK+OVAXkyo7jY6AgjQFehk1ce/2VQtVkvo/KZKw8q1z+4p/WNeeMUbXe+H3
+Ni9y/gecu4oNjYZK1ZQIlm+ucDFs6J4e
+-----END DSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSAParametersInheritedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSAParametersInheritedCACert.pem
new file mode 100644
index 0000000000..eb0e3f5a1b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DSAParametersInheritedCACert.pem
@@ -0,0 +1,38 @@
+Bag Attributes
+ localKeyID: 17 40 D3 E7 90 C7 A5 D9 5D 9E C7 97 9F FC AB DD 19 CC 36 F7
+ friendlyName: DSA Parameters Inherited CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=DSA Parameters Inherited CA
+issuer=/C=US/O=Test Certificates 2011/CN=DSA CA
+-----BEGIN CERTIFICATE-----
+MIICHjCCAd2gAwIBAgIBAjAJBgcqhkjOOAQDMD8xCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMQ8wDQYDVQQDEwZEU0EgQ0EwHhcN
+MTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBUMQswCQYDVQQGEwJVUzEfMB0G
+A1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbRFNBIFBhcmFt
+ZXRlcnMgSW5oZXJpdGVkIENBMIGSMAkGByqGSM44BAEDgYQAAoGAdC9PddCBVyNv
+LWZjkNFCIMtDn07i9ToU0tjH6t3zsh6BmmEQQAmyelHzZvk2I3BU6OlmepSlsfQb
+MRhWXb+KGRZHkWCq+Y1FXAJLf2ezAvaPbRS5zWSQ3QyIx8RLEtG4vjKgn7lKhDPD
+q7ZCS0sy7Sk9B/gHfqL32KJWU3EqU3ujfDB6MB8GA1UdIwQYMBaAFI+Qxox06HsM
+yFnHfTxbVFlgJQuxMB0GA1UdDgQWBBRlgZ9wOoyt9kMdyOePVY7oS9uH4jAOBgNV
+HQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQF
+MAMBAf8wCQYHKoZIzjgEAwMwADAtAhRH8JjJuwWpgsURK3pfyRHlg5C32QIVAJPh
+C76tJQgAB4hw38NZTyKc6tQP
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 17 40 D3 E7 90 C7 A5 D9 5D 9E C7 97 9F FC AB DD 19 CC 36 F7
+ friendlyName: DSA Parameters Inherited CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4582A07BDBECD705
+
+pDmXrWFfJ+/o5nvbPDvx4ixcy5zuqvwYuAIkUqfl0KbsgtnEtnbmx/Nx0PnELeTF
+CsC9BXd0ojXHd5kV/xp8iU0IT3YoKl7OZ2wzm2rKQ3EA4GhKLlJGcVjpTX1Xu78s
+Yl2qUhl/Y9UCfT8bltXeLxT3A2qJAkiGE2UC0BKz7ZRjVWeus8eSw6mjtuZxquqr
+vAwC1ridF+Xg/ENgv+NpxqXvN8alKjiBdI2t+hjyKsYjEjf+fCX8XXObLmpRru8s
+MZdn/Zxi6FODJE6lm1no+k7zc9Em+MQ3ZCcdy9ebI4ibFCf1uCzzOR+SOGUe+6Hh
+1vX9wch8GYLaCg4nZDj+TI1YxcxVP0lKhRJrvUaeiGBd61s9iqwpctGvLFGGG7zw
+eEpWnrecPtXrqAadYyK7y1SFABf9rxiyBz8VsXgeDnXK4LbK0ftkA71neFi+dXM8
+AewSr0h+K5isEQrUneGwRGohVuedL/W3PnEZEHMg20ixOm4oPBO4EpoBbb0oJVg2
++wfMFUnyil66xR3YI3uAZjh17TbFYhvx+jb5+5YF9GucBsbZxgEt9bkwHJpmjss5
+YSuS69n7MCK69o1y3cW3MA==
+-----END DSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12.pem
deleted file mode 100644
index 4084a4851c..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test12
-issuer=/C=US/O=Test Certificates/CN=Policies P3 CA
------BEGIN CERTIFICATE-----
-MIICfzCCAeigAwIBAgIBATANBgkqhkiG9w0BAQUFADBCMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFzAVBgNVBAMTDlBvbGljaWVzIFAz
-IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowXDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTEwLwYDVQQDEyhEaWZmZXJl
-bnQgUG9saWNpZXMgRUUgQ2VydGlmaWNhdGUgVGVzdDEyMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCyCzdT70A8+vsLoViq8TWIYg7Eta6CLxVYgGuIT/jHnsK+
-+FbOsG9GIxdLYhdZrrlKG4cAlkpS/6K9L23KfQGiNNjQ4LaWC/geLyNeOOOrnXBk
-nMhffhtlQ4PzTnEtjtr0fUr5iNZtCZpTUSQKxvZfEL8s8HUbsiPagLV9TwXO3QID
-AQABo2swaTAfBgNVHSMEGDAWgBSOvWaPjlVlz1HkWabJKh5iv/elvDAdBgNVHQ4E
-FgQUgYdlKg2WZsyn5n9xnCVxsVRQwz4wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwBDANBgkqhkiG9w0BAQUFAAOBgQA+sKsTmg7nH6jqpWTD
-0+ku3zH37P/CeNynrYlFtFA/3QZZNSeBUtmPEgSANp/iYSgpIOeqcUR+vJZhsIXT
-+0wX4SS7+hy3sHAuDmSZ7d4XXowNWmfn2MElY7INaPvTzjRY3+XIeTfMK43LglF5
-sftSt0FIy+7QSZiQwKIX35Hdig==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBJzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEIxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEXMBUGA1UEAxMOUG9saWNpZXMg
-UDMgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKzB4tlymiLVW8a6Ps0y
-porV4ZwLRY6O21qBHaMeOvMroSc49aMMmsNM5Hq1c37ETR2NROBT065S3xFyQT58
-Q+6gu30masLdypu0ewe1f4waXVKzrOrXleRrha2wyu33duzC9XoU5rLxLJUrPXjd
-F7bYw/NIHmdKb2gKdGDD5ZhlAgMBAAGjgYswgYgwHwYDVR0jBBgwFoAU+2zULYGe
-yid6ng2wPOqavIf/SeowHQYDVR0OBBYEFI69Zo+OVWXPUeRZpskqHmK/96W8MA4G
-A1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAMwDwYDVR0TAQH/
-BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GCSqGSIb3DQEBBQUAA4GBAGIeHrFlfEpz
-33KeWUQrArkcbXi4ONGl0zsMAelL8FjVyZJqVjBi4/z+31K608b9FleH0H4QlO1V
-pADcQhn+/9ChWXCvHtSUuBsIPFO3WWIdgYTtmSAqxsEq3uwQIR3ku8NoMpgiak6B
-EdVSLx709Z1oHVmuqVn1fYV/0968h9fo
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8E:BD:66:8F:8E:55:65:CF:51:E4:59:A6:C9:2A:1E:62:BF:F7:A5:BC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 70:a1:09:11:c0:05:80:09:b9:cb:96:bd:30:59:49:1e:07:57:
- d3:9b:e2:f1:41:3f:f5:f1:d7:90:67:ab:db:81:2f:1f:b6:6d:
- b4:e5:45:ba:94:55:25:9c:e1:11:06:71:a3:dc:ed:1f:6d:eb:
- 91:33:7f:7d:1f:40:2e:1c:84:1a:c2:45:8a:26:ed:0c:a5:6f:
- 1c:00:50:99:fd:7b:d1:3a:cf:a0:1a:da:0c:f0:7a:9a:4e:b5:
- f1:fb:90:9b:ab:54:57:1d:55:ab:b7:c3:a6:c4:27:e9:c8:6b:
- 83:28:68:cc:9e:0b:f0:99:7e:0a:f5:f2:ca:35:28:7b:78:59:
- 7c:88
------BEGIN X509 CRL-----
-MIIBOzCBpQIBATANBgkqhkiG9w0BAQUFADBCMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFzAVBgNVBAMTDlBvbGljaWVzIFAzIENBFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAWgBSOvWaP
-jlVlz1HkWabJKh5iv/elvDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQBw
-oQkRwAWACbnLlr0wWUkeB1fTm+LxQT/18deQZ6vbgS8ftm205UW6lFUlnOERBnGj
-3O0fbeuRM399H0AuHIQawkWKJu0MpW8cAFCZ/XvROs+gGtoM8HqaTrXx+5Cbq1RX
-HVWrt8OmxCfpyGuDKGjMngvwmX4K9fLKNSh7eFl8iA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12EE.pem
new file mode 100644
index 0000000000..9f256c30ff
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest12EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 00 D8 F9 29 B3 56 E8 17 FD 7D D0 C2 BC 92 05 FD 79 AA 2B A9
+ friendlyName: Different Policies Test12 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test12
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P3 CA
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIBATANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEXMBUGA1UEAxMOUG9saWNp
+ZXMgUDMgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBhMQswCQYD
+VQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTExMC8GA1UE
+AxMoRGlmZmVyZW50IFBvbGljaWVzIEVFIENlcnRpZmljYXRlIFRlc3QxMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPN0T7wjQBhGUgt53voETJXwpFYH
+7LSwR966p1DkDY/sTYGE7D/xxxxrz8FP0BPUvcAncfBKwBkEJ0ioEc7Wjgz9vnaJ
+o+tzJxiC3Ez1aRXEcEUNCYybApVy4hWAoKBqFp3sSZJjrZ97hzYkihCJEkTewMDg
+nE7Ru8WTt1JjSaplKZ5OajYdhdLGvESIOpFGMEbA4RlptpHeUjN8TU5a2E18vHfP
+yOs5tZzD3H9ZnmdKosn6RswkMO2W7gMO+nmvo4BfDnpmXgwMzBzDVoS+rW7MGVwP
+eMNNVz7h9UYlBYhRDSceAjF8DThevpzMAYfr4+g1lmdxmVT0ATXZ1OYl6FECAwEA
+AaNrMGkwHwYDVR0jBBgwFoAU2AWrLKCLw5Lcxq1qP7/zxpjl3P0wHQYDVR0OBBYE
+FMNvgVWsNk7EWKBgwL8ilshd+5PVMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAQwDQYJKoZIhvcNAQELBQADggEBAKMG4iNWYroyty8c3qaz
+37GdWGbiDQEhIQ6xJqxykoNZoi7D+ixkbH4OxT3pGB407ig84zH6rSHTgUrGh+gZ
+nrNWzDJY1qUc6NDcmH4VkoX0XpGoxqcWe3F9WV9HA1ZHY24Oa9wPTg3Srjdg9V7/
+eMe8KiObAMGy19rgrmiPX1NrhsYL+E79qfp9UpjwrSr4YWwQo8vzxwFxClAdFbK0
+eeNxr8/kn4+9Q8+z2R9L7NMpKU4nSsZdozcJBqPsmRRKDjbBxKQg1defVscbp0Wk
+i8eOL7EJYT0oljx5QMQ1o3HUDzsYGQ84MfJ7fCkLcT2kQpRR9cF743q0CZMYl4JA
+XTo=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 00 D8 F9 29 B3 56 E8 17 FD 7D D0 C2 BC 92 05 FD 79 AA 2B A9
+ friendlyName: Different Policies Test12 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DBA3E0F11E927D17
+
+eYd1nqpaoKS3dlDv+Ge3fOtBToNio0qP5xYCCdtWRoW6cBAMGLAeU6fA+225MCD/
+cc4sDMIs+17o8sGH+CHZosLY/MJyEnM/uZELt1VbQ7vKvvz2Umkotv5HEoyk/BWX
+BK0iWlYwL6rzYZMKssKczdCpSnUB06lKAx54LsIm2Zvjk96FkD2uDyDyvq8qVzCH
+ssyjbWiybrlYVIJsqW3Q/5SnEBv+GJ6kVqPEhfILLzSgJS9mL+DdINawWTL0IIJU
+eYjxfz+McHYGP7EYyVNUpCoUmv5kojy9b93gAXXiXpskseBC7Smxiw6SSupWVcDG
+Sv8+3gIRW0P2emzaLBUf5z5y6o6++s7NMFIieMiRk/BXr9jjjXyQjmfXNb/YxHFw
+9RSn3wou5v7z6dLjgAmMiTaQdkAhsXBp+Lyg5l2Sy25K4b2TEN9WFb4VKZzg4vM8
+GdUpxlcaOQoPfSGdzqq3D9SPyzGBpflkPv3isJo3P7EL6B9fPXC6ZG7AlTWAsUIL
+v7JJvtbe02P/mVObkqINnYztAsbQT0goDA2l09Lv4QlqC0qDFv755kLCoZiUABS8
+gs6+OUmouBrog2YmmHk/WWTrzdqq1yIXSiZNztTkgkcVc76OfpspeOt2B4FEFlAj
+Vpr42EPjVYlfxUr10Eotv5UsKmpYo0bxJvH7HZMC8JOC93mw7IuLRqsIncRov+Z3
+3OkYFM1NCxSMWi9csQM03EG6gs0jG8ofeWryySKfTy5oGYDO19YrYw1/v3Ydmyj0
+0xY9oz5eoQEFjsaikfcAKJMLlfg4G8HNJsrl6WFSXxqtKn8mP+dHU9QNHLOpU48x
+t//Yw6yrRg0KajrxmCCQLhyk/qmfTYV0RBmpPtcQGPGznY+Xfro78q1gpKKkjwmC
+scxb3SHnMAZ2m3w/szPxjnKHsT8URkrYga69McNgNUtupckDrQqaIvRciIap44Oy
+pw1YBuj4YVUlsy5JjSIXuFDHts/bF4lbwgvYb9fwEaUmU94INnyaIccbxuXHB0Np
+1uFHo0Trjr4uNpWrbdk4V0SfpU9wTF/pztciVIIfjItjJJM/HWUZrvilKl6LbmA7
+OxV0S6BkO+elzNOD7GTuGvNytta3GSD74rfy2ybIFSzOU/o0AMANCfk3HHEMHJoK
+QhnC3a0P2QaPF3y7IpCNDtYd4MgQjYjO0f2IZCbbnGc8Dz8e8qV05uHaA6A8VnWT
+oAFJXrfGrGHCa6JfjQensBph7R0gi8aMSlde+MWgVuCsegHe4hwWHNR6dfuVA66z
+zp96xLgpe5nhYKheXsbNfGaa5mpfr6LqPPfgl2Ea9/IVO0QPVLsLLIrPc2mAU6Hw
+Zch6w6ncqE//Rba48b5/t/21gZhVGD5W5lrP3CDPd0qX5Y6FivVEFZIYdaMIzW74
+fdJtdoXrY0X8TqsLqWXQSyCn8hndq/QasfLBXcBHEjA/lwZ9xsaGuH5egnSDaV1M
+sTxWTAxywse94eFTxopJ4dkQ/i5gMHfEiRvsKOrgbjVVl7dMwUgg2+aIIVojxbKK
+LdITZTwfoqtKRYl1o3xsy2i7CV/ptgC1/EvL/UU5MA+kyGcBBTc9q/Hq1o/Icsp8
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3.pem
deleted file mode 100644
index 81624cdd69..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3.pem
+++ /dev/null
@@ -1,170 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P2 subCA
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBEDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBFMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAMTEVBvbGljaWVzIFAyIHN1
-YkNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFuj/BeKqm7wDc+UMIp7Qh
-eY7RqfB/VGqZuKUb5UNpLiXT37UrhteMqYSqBkd76l1qvhhBwRPJt9Nq2tf5slrS
-NJOAnUfF0McB9RUJMGhkITa9As3KZy0u31hre09MUaacltcuJx4irpHKUEjn+qY1
-ZdZ7NNEzH9VXWN+6lARLIQIDAQABo3wwejAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7
-J0TXNTPfmhWUxzAdBgNVHQ4EFgQU5FhKqtjykfUZF2iehQcjbgo0680wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAGilgDaBiDA1cbd6xUxAl/K5DVQ8ack+2fk1
-P8G5fTuQoQtDbWX6eA7Q/nXFXBCj2i1tmJF/q8Pzh1GU6MKQ5f7J5ibEstM1+lgb
-hidM5kd85uVTxTBL7GSS94BSfXFnNOOSWbRTyhSIZRxScCjERfnSfF8yBDRIbFGO
-ma6qPeAC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=Policies P2 subCA
------BEGIN CERTIFICATE-----
-MIICgTCCAeqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAMTEVBvbGljaWVzIFAy
-IHN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowWzELMAkGA1UE
-BhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTAwLgYDVQQDEydEaWZm
-ZXJlbnQgUG9saWNpZXMgRUUgQ2VydGlmaWNhdGUgVGVzdDMwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBANc03XT9xYcVcwSWI/zfZ5VWnTC4uy5WFMe8/BNL8QuP
-5xFw/xGTjgkS/ABNJJJ+a/RWsi0Q92MSeMbVNkgD0/i94SgjALWOdsg9k4LI3iH1
-ziOZ1OWKjKsJIxgCbTls+JRu7bRi4dnVYHB96WnGFVsVp9xyoS3hUYYwpCFXYLWz
-AgMBAAGjazBpMB8GA1UdIwQYMBaAFORYSqrY8pH1GRdonoUHI24KNOvNMB0GA1Ud
-DgQWBBRyOnvPdzFG1aaQtBqWQiKlfmoaPjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATACMA0GCSqGSIb3DQEBBQUAA4GBACWQn4A03gqLgppl
-ROwBGIIxHZD+wVr9BgoDJj2xwX6NaofqHfhAyVq9hDqEwylmfr0rH6m8PBAgnST0
-CnoWgQEQQ2sESHf6f/7/CTcVLlx8UQDXaTlA22nhmoJG9Y4iOdjdzhgvn/9yYySs
-aTByh3KCB3TV4q9GJw6nUNAmnoOo
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P2 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E4:58:4A:AA:D8:F2:91:F5:19:17:68:9E:85:07:23:6E:0A:34:EB:CD
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c3:6b:fd:b1:c9:49:fe:a7:76:33:87:24:1f:f7:df:41:31:b8:
- 37:15:f2:3c:ae:8e:c7:17:a1:30:ea:a6:53:99:4a:8b:a1:7c:
- ae:c1:4e:58:81:4f:65:e2:0d:eb:a0:cc:2d:f5:a2:ba:03:ee:
- 1e:81:1c:64:3a:b1:9f:2b:d2:40:27:69:6f:32:95:fa:85:f7:
- c8:76:8b:4b:7a:11:12:8d:7c:fa:1f:54:84:d7:ff:72:23:63:
- 46:55:0a:e4:d2:38:1d:83:2c:57:bb:60:21:dc:44:0d:6a:95:
- 11:ad:f0:b5:57:82:68:f4:20:37:f4:d7:46:93:cd:c4:c6:90:
- fd:c1
------BEGIN X509 CRL-----
-MIIBPjCBqAIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAMTEVBvbGljaWVzIFAyIHN1YkNB
-Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAWgBTk
-WEqq2PKR9RkXaJ6FByNuCjTrzTAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUFAAOB
-gQDDa/2xyUn+p3YzhyQf999BMbg3FfI8ro7HF6Ew6qZTmUqLoXyuwU5YgU9l4g3r
-oMwt9aK6A+4egRxkOrGfK9JAJ2lvMpX6hffIdotLehESjXz6H1SE1/9yI2NGVQrk
-0jgdgyxXu2Ah3EQNapURrfC1V4Jo9CA39NdGk83ExpD9wQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3EE.pem
new file mode 100644
index 0000000000..1862cf4545
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: BF 95 B8 E8 8F 67 D3 65 DD E4 08 43 E1 5E 46 35 4E DB B2 AC
+ friendlyName: Different Policies Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P2 subCA
+-----BEGIN CERTIFICATE-----
+MIIDkDCCAnigAwIBAgIBATANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UEAxMRUG9saWNp
+ZXMgUDIgc3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBgMQsw
+CQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEwMC4G
+A1UEAxMnRGlmZmVyZW50IFBvbGljaWVzIEVFIENlcnRpZmljYXRlIFRlc3QzMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2L32QT0g01F68LYjocgXqdQT
+T3dlBxvACUPsrp2+NKeweuoSK2yPKvs/QN4Ce4ox41QANy0KredM+kotXEl38eDC
+PTdSueu4Aib8XwXqNN47H0jXb3GXebDzdSdJRbrkLvV4hNYaf/PVWxtKdL/W4R7Y
+zWCisxXow4MIXFcGS29ZGcx4yReMxwZ1UCbk0Vg7lfxIIsM0AJ7mCKXWKpGAYxrl
+nAOjI1fvdD/NdEncadoeBL/Nv0wa9MA1k+EumSoPggSSZEmQJICZOJMeEiI12Lqv
+oOgbPaCkDIlpnRzk06h8D2JC1LxIxoX56lSkzQKLBBtS0X4Y0LNOqjHUr0KZYwID
+AQABo2swaTAfBgNVHSMEGDAWgBRePIRznjBwcnGYroE2GdsiDnyvAzAdBgNVHQ4E
+FgQUWCD2nzAOZgQ9p8fRaOygrwpU7vYwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOCAQEAZKkhGrleiJkNwbr5
+/sNaPHcU8EvmcsUyyxHIUoQmXOcVDAFiUxs0TVTDoopeTMD6Mw/H2HXX1EOz41dI
+MiHRWAZGKl9v1Y0t67D5aNoZly9QZxm7hkZ7O9SdC2pdE3y9xyQK4cTIafEedLLh
+2+qOIFhB8GZlU+drtdCV9SVK+1R2vcurVkTHYeOeK7Clisfo4vEdhqFNnxKtnIvu
++LXurxBQvol14NuLoOTPvysuR+K9oNogoAUZMbpy76fkDO4usRkrE3+cJb3kx/pd
+W1BlJ95+daVa30HVXq+jD1VwFyoX9wonijkfjgmk/nWBxjgeVxk/xwAdvF0qI8CH
+Ggqn5g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: BF 95 B8 E8 8F 67 D3 65 DD E4 08 43 E1 5E 46 35 4E DB B2 AC
+ friendlyName: Different Policies Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,57D8FF98C92B6676
+
+1JVtB1HPXYvncvcKeUmtRWpZQ9fnqS4ea22mgzVZpRjqq3EuU8O2cfb0gi+ZnaUg
+sWjSUaK9nEnEnxTCHrfr7+IQAG6DcdwOYv0nH4udLEQbj2avZ0hn2XI2UGalEp3q
+vquIqtI7SLVF8U2vYc2e8XXJ6lsKv2CR+5z9mP4uL2KnwhXYz94sD3K7r9ForKo/
+TBl5lfXK5rGoYRV2PbtyX/YnACsIlj/RuCCxiTqZIxUJ0Ic4F9APYLd6yrNhe0PX
+2jahWnYkJUaAk1fn1x9X+rQiC732WvEXPcWgM644i+6u1qRGNNMmCw/kRCxXFN2E
+gLWeRpeNZYxiqzcQlDD1N61FwmRDIomCtPvMVvhhYB0N8JKyMMpSz8qEU3Q5bStG
+KYUvOsyt0dulrA9cWqSB5sLGeSIaqvVwE8BrP26m2T6D3E6BvlbD9dPpFhnAFnmI
+mrHU0nWV1x9DEEACBTVVohQ7f+235UUjXjt93aTxVaKqWv9yr6M9NozKTukoxAQI
+6rcyBwwIBpTeQwOGcb9PcROWmN7xoUqahxerxN1Ti6ePcOlXAe1RAiMV9WRrJudj
+OnQzcFHXCZ2qzYDcr1dIDPqnsLF5N6pHvMFvkYSXKd9eWT+BfOrrvCHiMGJQgsBf
+NfLBBgdomEoCwarvjt8fW6p38HZ0EpUbKtb9e+Zv+bY3W2je4t301w1zqlLbV7hT
+gmd/P/opiILDj0pg4cUmJH6IFxmeSQ2jPb7TV4uUhaJWTWaTb67FUKvijT6QGMZC
+uYxIG5dw8caYb9hlYzwI6Uy6PO609Y387QZTpi1ZdVyH392s9YdC1I4eYkYCbF5s
+pYKxCP9CFtstwe9FNnDrt8UIF2rEzlurLAgo9lUP8RTqOPKpt5jY2TZn3t9Zw//c
+LfTvOCFw1KDRhJyCjhXg1XCqxCF2JzGd+YLhoNA0feZAWdif1lvHNoHCy1ypP1V6
+ErsMpQAz4KD3k0gpVbIZYdj4nrPpSc8hRWKMSHmihanPG6VKETm4wuzL+FY6jtPa
+bSZ79R1ckie+TpCV3EEQhUkFOtFG7qWDk8Ypo0XqeN19YVo9JS5ACBpBOxkRTRZc
+8pr2CqWEEGQr4aUBe1ba4JkKV/AWOyGiVoFETO5efL0UF2JNEQgDqyEwHhfX34it
+CZrowX/1TjAYV/Jq5KrlP6PIWmKaDKge2iUJ9ED1IJdtM3LFqCTeHsi1xbnNdcHl
+h3oJAPKT+dC6+2CdZHuzPJCDXr0JHGsT/Hw0b9UlhkYRpWEYlh1owfUAeZYFz6AN
+7BkOwU/Bv1my8OmgwTu6v7X08+9kjmhG62x0c8Mj4iXy1/kIn2Wbp00pceXkwWqr
+ZTtMoVHkd0JfuSXxjAyPfUdTy6z8fPWT6SpKTLRG8B2PSKw+BpHlVkf1QxzzLgmI
+SA9VX3tfrBJ3DySTdC6AH1dVElLeIz5+Gopts7+tK7H9PQYp+6vhjO7W7r/9ePSy
+wM3SWtnLS7pm9qeNJSgRzuDa9pPue+EKlJnjypzB+Xhq8w9QROKe56oHFAQOSk4U
+NUkVhKDzT0o9vuVFbgIPKosfWYbMuB/NwfP+8miY9wqyXjOd2S6tqQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4.pem
deleted file mode 100644
index 42c902dac2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4.pem
+++ /dev/null
@@ -1,170 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=Good subCA
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQUFADA+MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEzARBgNVBAMTCkdvb2Qgc3ViQ0Ew
-HhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBbMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMDAuBgNVBAMTJ0RpZmZlcmVudCBQ
-b2xpY2llcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAo97r9TnN6B3H+x4fSXruIfEelkjmA4Ti1Q93FP3Op0Pfk8ybf7W8
-/meQsMFMMXAVrZ+pwfLj3YvzTspivZUbJGWA4o7r2DwkVkuXr6Rv2n3OhPlCwljb
-TAFxb5S3wOOJ53FHJw33R19R8d3B0CpxKxLK1oXQVOOu0t3UKizFJakCAwEAAaNr
-MGkwHwYDVR0jBBgwFoAUfFxpfJ3IVbEiBSlD+8R7j+rquH0wHQYDVR0OBBYEFOIy
-WsL+F3ByhN7vnBDlbJNEkZS3MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAIwDQYJKoZIhvcNAQEFBQADgYEAVoBWMI/tY2C3bNKXPdDQHwOq
-+JplKCmu37pLQlMNSVP8yssW5khRqkKYi48Jz7b21NKFN3w3/0MuV2AxjEA6ROZX
-MBwaIKyeHMRCRDJndHYU3CkOvex/eDDnLXvNxTXuda755S3qZUbhNKRZnLv1iDzH
-KN6TmIq39yQReXlNoNo=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good subCA
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBETANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA+MQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEzARBgNVBAMTCkdvb2Qgc3ViQ0EwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPPDgvwjnBtonTcZM5RPe+FqtX3glBmw
-zdb+WOm6gKoAp5euYnW2UZOOjSztJyTUKsmnK3qhKgntDjO8z/ito6Pz0Uo7zoby
-wftFeKr76K0iBIp0t2DJQ4khnA8KjIB7LJp5CKIT1rhPdrLhPbc/r+LcUTZrAfRt
-ZcQkxbznhxZxAgMBAAGjgYswgYgwHwYDVR0jBBgwFoAUty6mgsvCyLyoeydE1zUz
-35oVlMcwHQYDVR0OBBYEFHxcaXydyFWxIgUpQ/vEe4/q6rh9MA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAM
-BgNVHSQEBTADgAEAMA0GCSqGSIb3DQEBBQUAA4GBAI8yIYi19lr+NUCxlq3CXkpZ
-TAgRtU0pqH1VbEootkv0o7apbF2cC8SHB0UDiih/yqZjqw3kHtpbBaf75KHxqoQ4
-PKqoZXt3K4rjiQooU+2cyC+mxI3uegcFjQ444R10jXwv5EqNQ4joXhz5hocJA/PF
-JGFA0gkGm2pMEBR567ka
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:7C:5C:69:7C:9D:C8:55:B1:22:05:29:43:FB:C4:7B:8F:EA:EA:B8:7D
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a1:14:35:58:41:58:4a:93:ea:8a:e7:cc:c1:be:02:22:8c:9a:
- 21:32:d6:a9:bf:1d:df:7d:60:8c:ba:f2:8c:01:a9:38:a4:94:
- 8a:6d:69:46:e5:ac:63:48:17:e5:c9:c0:de:df:13:73:c6:ec:
- 3f:b7:ed:61:a2:6c:42:d8:cf:7a:ff:3b:35:41:8a:04:c8:fe:
- 85:37:b8:7d:dc:a0:05:35:ba:e0:bb:39:c8:be:2a:79:57:82:
- db:f1:da:21:e0:c6:54:2b:37:2a:e1:0d:82:aa:2f:47:ab:15:
- fc:30:11:dd:52:ba:93:cf:bc:46:39:a7:94:29:7d:e0:2a:5c:
- d4:ce
------BEGIN X509 CRL-----
-MIIBNzCBoQIBATANBgkqhkiG9w0BAQUFADA+MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEzARBgNVBAMTCkdvb2Qgc3ViQ0EXDTAxMDQx
-OTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFHxcaXydyFWx
-IgUpQ/vEe4/q6rh9MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAKEUNVhB
-WEqT6ornzMG+AiKMmiEy1qm/Hd99YIy68owBqTiklIptaUblrGNIF+XJwN7fE3PG
-7D+37WGibELYz3r/OzVBigTI/oU3uH3coAU1uuC7Oci+KnlXgtvx2iHgxlQrNyrh
-DYKqL0erFfwwEd1SupPPvEY5p5QpfeAqXNTO
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4EE.pem
new file mode 100644
index 0000000000..c03b2ee55f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest4EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: E7 47 03 92 87 C2 13 AA D2 64 83 7F E3 21 B5 CE 86 91 D5 66
+ friendlyName: Different Policies Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=Good subCA
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTETMBEGA1UEAxMKR29vZCBz
+dWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGAxCzAJBgNVBAYT
+AlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTAwLgYDVQQDEydE
+aWZmZXJlbnQgUG9saWNpZXMgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxty81j9zfbcl+YtNeRrNlpCRHCO1tJ7MZ
+0EjEu8j64WkbvrzcPfxHeYAyzwduXLOORu3FJar1wJ+ZTJ4ay4ONqvTiOnnw/tLx
+KFI3aQSu4SWDl/F16bL6cfelY+B+tc2J7QoMMNQLvNGShnaefeqtS2xNQeCB8Zjk
+quY9lsQlmafVfOPxKtJA9EjnokOU9+mfnhh/ngbr24NKkT1uuRQ0Tg6sWoa7QB0V
+S+gGV6CNGEB7pJo58cCEOu7Tsxjd3q4bhazCXf4BQCtsF/MtkyFXfdkL2D+WzYzu
+XoEyQL/o/2SM4SU13PfhtrF0StEnRbvlNF5Hefxhd8SLPFRjf9uXAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFDIHLJ50XS1dKbuxeo07FVK0fUJ4MB0GA1UdDgQWBBSxPono
+OMkTA43/Ahv4n1sw3dzLdjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATACMA0GCSqGSIb3DQEBCwUAA4IBAQBiTlDMrFBwu0cpUufJeAXPXKdQ
+ohGYFCCTW2DA/T+PsQHnvRlRizHgt9kIJI6+4lqKAKmw240r1rsVecwDBd/Y++HP
+LGofEWvgA66DjnSOI45C7uJC01fu9Xhc4QJ3FGgDNHncsqFIJs/Bijol94PnPYjZ
+Tf6xUYy4pAU/CMWuc+sox34TZE9KjXgQp7JbjYHRrFWNTyDoFBQKqoechN3tWGH+
+bIRx9Ck8RT6mhkUouR2KP+d8212wOEE/6ctpFCslGXyMt7jZjcuSlYAOcRNQWhkM
+hiRoCMkvqO1yGAHvXCo+kGeHe5flqzQdcmuEknkDmPZx8XEse+XjtR5hI7D3
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E7 47 03 92 87 C2 13 AA D2 64 83 7F E3 21 B5 CE 86 91 D5 66
+ friendlyName: Different Policies Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,78D7FC965498441D
+
+P87XTD3VLVwqhAUwYB4Ulb8Xi35NMdW+5ajmm2za5Pk99uwJ9iXEchDPEG4LRhOp
+sR9q0d7Sn3Z5cs2odT0+a6sun2ijAy4tTC7ZqDJRsW2NPzo4mbUamsLqcS9jLNAM
+8cq/RA2EdTb40bKOgherEPZmwiZYkLrGoYApUCP8uneOGZf2wVifSOSTKxysNELC
+XSlz+sISR5Nj8gfMDVtlZf2k38kUn8GE1YfJItr4ALAva66Vo4ix6YRhQqLRdw8e
+vjGoDG7gXfhQttgqr5pTaMYcrhEH4IRpeB6AIgthKZkrYXHniYL30tiCghHhdtob
+Sjoym+I4TAnZu5PgfuJeAX6xaxRlFJcZtl1/+Of4Z0w5Ap2qXB52yDp2fMzxLkOL
+A5Cu94A9XXJTVU1R54LnF2BPOFYW9pt0eKdQ4RwbxXHIpq5ik5/JVZZQb8FiRxEL
+1Oapr+339WsRdpAHbksFGfhY9IEsS4P4nfPqW08moc1ryM6aNIjr/J4XO23Qmgw1
+WMxH52fg1cR2nHWpw8NmHWGxoNi7rIC0QjUMlTZlLM1ZASWrBwY1xaNgAfO1kj6/
+BTgbHBqXq6bhTBJ8lBaQm21IfCBv4GUKyFzCnAcVtqWJiCiXP99arSyBWIqkh02K
+Hejinsb3zYgYbZrurPcWEr96LQL8hjDlrMSD8Jiw8wQzSpasvMiaexBxG3gQ0MNq
+VIkpNd2QtvdhiK7zRVdkvRv02vu4ELYPNFzCgud+aapH4Zun/QfFKrvSgmX6AoUL
+HOc2ufDHxfj6JcFoT/MvAHM11xcSANhOKB5lb1fPi+8G3BoSfoxf043+aShIPX4p
+d2xTreOmA919uhGS2zuGrvFse2xkiTFHWBXtcpX1qOLCnQ7CDvGkx9NMJpjHMpQn
+MPgcJuxHHQo3l8MdOesfs8gTnX2wTAkEEla6v5sYtGsxUfoFlUoUaElbtBkP5Xul
+imdt75jxlE6AifsZ6mw4a1XGqCU8yvkKCFleuR+6ZntfRQ617j8EAD8G0nxoAbdb
+hmUL1h7q6HxxjxrHcw4SiaeZPkEeKhxkdW1baQ1zi96obw9PGR5BBaCSVS9OQ15T
+4D3lumHaXoqJihul8xapaISU9a97ApOuJiKYsLTPyctV0gSYymlUAFhpZIVKt/vA
+7043fcoElNWwhq+FvHUtRCl+go7lftinYJyaf1mWTRumm45jxtvgsXw7eUc8qqMK
+F7rpOmSSV0jD1eEXAgcLc1l1COL4Vm7Cv+s8CzKXYAFp9HM7PbgzKc+z/frW+RYT
+pEWN+7WyufYPIcbXXtG2pkI/TfqKpPGNlUN/1NOJpssZHxGYUJZaZO8lN9eH8aE8
+ppD3bwrfB2XMY+2Qq0G0ous5pX98fWp8hsQ5BIyqP9/fZTI7PCKUN5toJqJwlvBs
+dY+7QRe9xxSpQCX5XzD+swQHuWtYPvgukpgumg1wgwxBz+GqctFbzNs24zY0NDQ/
+EHMFDdBZalY8uC5NT9j871DeJlnLhK3TNVB0zwtCid8R0fP0tV22oDJ4oyt0biE/
+ChrQlI6SVqRXaWdCjGcp5xEpiGi8aBnWlINayceaLFQ37yoESDMgjNplZCs2zuLP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5.pem
deleted file mode 100644
index bb476975c0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5.pem
+++ /dev/null
@@ -1,170 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=Policies P2 subCA2
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBATANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGzAZBgNVBAMTElBvbGljaWVzIFAy
-IHN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFsxCzAJBgNV
-BAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4GA1UEAxMnRGlm
-ZmVyZW50IFBvbGljaWVzIEVFIENlcnRpZmljYXRlIFRlc3Q1MIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQCwZH5VW/9MO5bUFBrHnWcQmxnLKiqHAu593o6kFZKt
-zkkYkVCA/vu0Wqgk09UeJz2jQPFuJEFYl/VdkkyS3U5TMdJBBcIHMYpmVTeTJSzP
-G+II79/nOVLpVRfuMtKclAU+oCCJb29oiXRaOFzZjzbXuU/NvSXZu24sVctBtFQA
-DQIDAQABo2swaTAfBgNVHSMEGDAWgBRx6y8V7VGl/4VJjHwa9kumm6SUBjAdBgNV
-HQ4EFgQU0BTRTBvIbX1D6I9/J/Wkp7/iGNwwDgYDVR0PAQH/BAQDAgTwMBcGA1Ud
-IAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQAVgTBnKECQtHJE
-rSdkBjW41mPMbdbsbYgsl00518Qv4kS2bIsmMOB4V6kl48oIlmIql2dgUqb0QgvA
-JFFmwyLWdyUy1Ngv1H4tT2i9htTQAG7Yhx619BHqWCfqCiue49ySUsKOefY3ZYuy
-Ew2nYu2yBbFQuBajQDA+6rT6RjvF+Q==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P2 subCA2
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICgzCCAeygAwIBAgIBEjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBGMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGzAZBgNVBAMTElBvbGljaWVzIFAyIHN1
-YkNBMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtLTO6yKdiF3dWPmvdMIU
-ljhMl5k5/mSISipm74fsNPvCJOAfdPJa7ZsmCH2mXZeXa5xOUPG9YzcqgSoj8YEa
-L6h9u4t40L+OyapOZKiYykXi9hoZEzCuilIIu3km9rU0jF/hTntZ5QSdE65fM5qn
-iMQnAPkod5ehi3XASsHZu9cCAwEAAaOBizCBiDAfBgNVHSMEGDAWgBS3LqaCy8LI
-vKh7J0TXNTPfmhWUxzAdBgNVHQ4EFgQUcesvFe1Rpf+FSYx8GvZLppuklAYwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAjAPBgNVHRMBAf8E
-BTADAQH/MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQADgYEApvxtR+QrmkV9
-u+IYUO9+MXgIGn7U3aab9pnQfxH2Dqkx2uPGGYsw3+Md7m0+Y29god0WgGwgrmlS
-9VnFhuDw0Sks4ofgjOWCrO0gK10fO2AHzYMwxcbsaqrIPS0dIkUflnnB6vUPoz1t
-0/y853VkBY8fwZC5lSrXe1j/wkrITt4=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P2 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:71:EB:2F:15:ED:51:A5:FF:85:49:8C:7C:1A:F6:4B:A6:9B:A4:94:06
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0f:c9:61:2b:d8:db:62:52:36:67:85:d2:bf:79:00:4e:44:4c:
- 3b:2e:a1:0f:58:1d:06:1d:47:bb:2d:b2:3f:62:d5:9c:7d:da:
- bd:34:86:5d:44:f2:ec:42:d8:cb:37:16:8d:87:d7:73:3b:d1:
- 82:e3:e9:2c:d6:db:6f:f5:f3:db:d4:11:bf:bf:aa:15:10:7a:
- 51:76:d6:56:e5:f6:27:00:54:54:87:14:e8:0f:5a:e1:5b:64:
- 16:53:de:31:1a:69:c2:6b:a5:fe:77:8c:bc:f2:42:d6:ad:84:
- 6a:f5:bb:94:16:c0:12:64:af:4a:2e:68:64:2f:f5:14:5c:b1:
- c5:cf
------BEGIN X509 CRL-----
-MIIBPzCBqQIBATANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGzAZBgNVBAMTElBvbGljaWVzIFAyIHN1YkNB
-MhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU
-cesvFe1Rpf+FSYx8GvZLppuklAYwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQAD
-gYEAD8lhK9jbYlI2Z4XSv3kATkRMOy6hD1gdBh1Huy2yP2LVnH3avTSGXUTy7ELY
-yzcWjYfXczvRguPpLNbbb/Xz29QRv7+qFRB6UXbWVuX2JwBUVIcU6A9a4VtkFlPe
-MRppwmul/neMvPJC1q2EavW7lBbAEmSvSi5oZC/1FFyxxc8=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5EE.pem
new file mode 100644
index 0000000000..5b2666edb1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: BB 77 D6 04 86 C7 AF 5A 53 52 F6 9C AF 07 E5 C4 57 9E B2 73
+ friendlyName: Different Policies Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P2 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEbMBkGA1UEAxMSUG9saWNp
+ZXMgUDIgc3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYDEL
+MAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMDAu
+BgNVBAMTJ0RpZmZlcmVudCBQb2xpY2llcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANc7eW7KCq7KAlGjq9aqVs2M
+lsnXH8C8SqOXRofpJ0M/j53afDE0ILmH4hgoaOVhxyRcpVmcC/72sVP4gSTpAHck
+XHULhlvx5E3tUr+ki6goatM9qKTboJymwV/hmx10idGMNVWT6ejet9ji/J23RiC+
+EQ+TxjIsAF/fWdB74H4zCvPXnxRWy1CitydVL26GH8MnekOcp4njmDmIyVWrAwUF
+geTwAB3xHz6/7iA9C9W95xRCTtHXUHeMAIEdELouBZotgsP725TXCC+pm1tUvbZi
+a0P2LxR9QcMgZCsDfO7t7My49fegLLaZpJqd7V6+b/2JlJeIcNrDmmrNiopd9VkC
+AwEAAaNrMGkwHwYDVR0jBBgwFoAUFyzqA7gHd4E9ZaW/Mx/MetKY/L4wHQYDVR0O
+BBYEFJiUy7I6Fq3xRsRaizIrMbUtUg75MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAE
+EDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAB+8jMz17pv82w09
+6pJhu2R2WHjLME/wzJ5dRBzcG8tniwcSXKzravLiOVJPFIHt4K2WGHK5D06E+6yw
+VU4BLu1lvL8jsZwsmdXishdolGNpmZEdOH8X9siOUvtxmApeVnwsyKCEsc41Y4Sr
+itz2siDC2nNtvG+MtVGi4tbGBsAD2+COHFWGSqjc5nBG7RBTxJL9c2JpZ+Ln8udp
+7ccOfxSrF/LgVkdPyHj+6CvO7R57WWjcBIT2UTACl9ERGGxhAIEe0T/odhaU+9P9
++qkb4ZxyYBAuarU8/qRGzk2lAnjv0gfnurCrRCjLwh83uF9dF/eo9SF0N9/6J1bT
+OOZB0Ek=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: BB 77 D6 04 86 C7 AF 5A 53 52 F6 9C AF 07 E5 C4 57 9E B2 73
+ friendlyName: Different Policies Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CBA4E381EE361867
+
+p9Hn+TnHC4Q+ErF33Ril0s0y84bpX+RK9zwxK1s0I/xSEneCjV9TaL7BORl8P6kB
+3+zZKnNR9jb2fqJVG3UWW+UIpjxsDsplIcn+QAbUfU7mzGwsTa3yb7K/0omItCWI
+XJvlbxhytb+zgOOZGg9ES28quIGJtXpAwEx4fLKQuXaMKsnUMFUjPt+KZTCDcsNs
+e4cM9PFk5L1w2JFckYyfe7eW0DTuNsmLH0QQqq/QkspIQXhJYeE1JTNEW9LlV9cT
+ZGTTK2JBWg7ipKX2F1OgXW2OvMKUkdTke1U95FkJh6oGD4kGgwhdtB9EnnbTrc3L
+vvEzvNCeZZaVNazhby2e/+5qPOfxhe4EPPHhtHejZdmt2xwqcRU3JjMF78zab8ro
+m5zIUdKkU0X1YLO2O6QE1yA1Hyy+AvOfT27aU4+nE8hAkZxcp4E0uG5N4IJVRKbW
+MuOWJZgEGSRI31Z5yhhthGbM7B9Su/lS8lKqTv0ZuZvwtjAZIBbLocVvjt47KTY1
+q7MHB0wlrgPUVv4zqbfkp40Mgr892Jow7gHeVTCTSbeF48zg/I2NbrDGaSMkuqee
+X6fpbXPiYMcHMMZWaBXmhqqsBB035JeAIG7cfkcJi5+6IrM3Ttg41klvdJTihrV3
+iEfJLwQcIR62Qa9OGVdanT9oJKoDhkFbO8KjI36Lj5XcJR+SvtJ4WnFI87U2vEY+
+TqL9B9M41wLPh8RPyKWXd4ppqUV5TsGvAakVFUeTlDMET/1smHC544vryJnLTdCH
+2IWJaRjqUi7oUazKvXcgEETQ4sko9F5Hgjf34OVchxUe1QZOOOUfCP4tSTtUG3AJ
+bkSTtAJ5mHviEL115RYwLbJMD5j3y10ynQkmQHQbT/v1/3zBsiUPJ4lq+ELvRSSS
+rYYileo/RTH0kp5hD0tOyJRSLXmWfhpEtccpJZOw6EBFOHs8l0RubK0kvQgCnqn5
+MxZwxP0JnL+amE1MsttK724Uo2bXcf8rInBwsuyhNobHsApli7buerVhSGn7xa7b
+EmO5GZUMEywe5SMKNMyk9L4G6G7in0tW+qrAHRbpid+BpOFmZ7hTs4hGEfDd2gbH
+NP4HuOiMMQz24ckcyPq4fPECCWYyaixxt39TbD0RSgwwQxzRj/V8OyL8+PLN1Eld
+i7ijnvpasIz1Xa1FyrynYjfU0KMRr+Xh2R2iPAR6kZxQu1Y1ORAm7Lhe2aElHiDb
+oNCcoufceGTkXB8uzMYOgH6LrtfQcrjRIZdZyvHlZPlbMsMbKokamAJNtzHuhH0T
+QDkQVtHV4ext11mf1ebSt4wKmTVTiXS79ieVHWAcxVX0OOFOQeKKfrlpY3UNxUF1
+y1rSWp879v9DyiJmy0/pVrtAXf8a4WHoU1btyAQBvFv0LL2Ta7em35ytmpYS8cst
+hUjXbUtMDha08no0jzwFLsX5SZ975ILA26E/qtP7PLcbwezb8B0VKQpsPmbp+/1m
+iyoUQaMdYo2I/lkAHj/MLjXLwZBn5jTYGtLewVNTRSFRze8doZ1JD5G1Extd0bBh
+FjKSe4WmSXZ/EO5M1ADH4JOEUnK045DCYSxPfAhuueIUulKXr8cvLw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7.pem
deleted file mode 100644
index 64913817fc..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7.pem
+++ /dev/null
@@ -1,211 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P123 subsubCAP12P1
-issuer=/C=US/O=Test Certificates/CN=Policies P123 subCAP12
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlBvbGljaWVzIFAx
-MjMgc3ViQ0FQMTIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBPMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMT
-G1BvbGljaWVzIFAxMjMgc3Vic3ViQ0FQMTJQMTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEA3JEcFcmqBaOdX0aQIeLKgr184G8kZkUDCWXFVa8Rl8JEbH8nKumt
-oT+D502p0fAxQ/lu67/+Wz9X+0bAwkuPsCzJ1QCXR2UIRpVr1NxN7Rpz/7c6kzfL
-/DJwrly/lSBnj0R0YirNdtTRRbIo0/YEP7P2B0gorC16aSbZViLod4ECAwEAAaN8
-MHowHwYDVR0jBBgwFoAUWocIIfvckxBtmgt8x2qxaEvfVdcwHQYDVR0OBBYEFCOJ
-nPgjYULoGZabFjVqvDC9XoqCMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBE
-8ZcL9nvf0LT9xC+cY0M+u5LPMYNxkecfdmiF5H1xmtqQ+pyLB7lUIyeSE0FWSbFS
-HxkKQAkO31yPfR0lvAkmJS8uVhZf7kiMfNhK/iHQA2LE4ubMmgyfbnAidPaVhPJ/
-waAqgUmU3waTfWo4RyKCWsWN6L95KJNO3HkS5l83zg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P123 subCAP12
-issuer=/C=US/O=Test Certificates/CN=Policies P123 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAMTEFBvbGljaWVzIFAx
-MjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBKMQswCQYDVQQG
-EwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlBvbGlj
-aWVzIFAxMjMgc3ViQ0FQMTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOll
-J21WulD37Mn1rV21nTiHp+5zJm7d2iKVBk051MbS63EnC5jnUm0D6a5QJiQR8Ai2
-tuB17ppJED42WQtI7o8exytiya4Y4BvDOeGlVbVZSGgbk2vjlTzg+caDcAkVSzWD
-YMs02A14NrbFODXEyAyJ7rsOTycvQorNHm6zUBvRAgMBAAGjgYswgYgwHwYDVR0j
-BBgwFoAU0L/Nm9/xkf2Ch1oQz5Cvi7zyxcwwHQYDVR0OBBYEFFqHCCH73JMQbZoL
-fMdqsWhL31XXMA4GA1UdDwEB/wQEAwIBBjAlBgNVHSAEHjAcMAwGCmCGSAFlAwIB
-MAEwDAYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAD9AiTI21pU5RaP49a5YdThygUEjL+Hvvoq4cbbg7dN3qbjYJBXUruTWyY+c
-pSqrS3q3rUlt99O+9JFqZSX8LCVRMg0yWSlwymdeY8a5EBS099ZFB+r9v4tIndk0
-r1uaX/PyEiMNd+eT8GdxBwl+Jo+AHTvuHx0G9iRwLbS5Es0u
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=Policies P123 subsubCAP12P1
------BEGIN CERTIFICATE-----
-MIICnDCCAgWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1BvbGljaWVzIFAx
-MjMgc3Vic3ViQ0FQMTJQMTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFsxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4G
-A1UEAxMnRGlmZmVyZW50IFBvbGljaWVzIEVFIENlcnRpZmljYXRlIFRlc3Q3MIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq7BLYQUkQ5JoVVov7G3lnh8JAEwYq
-LMbqpRCqw7cUk5pzpmQsxkZs6/Ucuz/aR9dCCaRZJ+YQ8GZSQ+igOWzOfGwugT2P
-1F9uHaqW5hLEm4nKD0sCR7e+SSsZcVLDu43aKeP9M9W+eIiVgBDqqO/sIiP+H9lA
-XGxBY7aZKR9PbQIDAQABo3wwejAfBgNVHSMEGDAWgBQjiZz4I2FC6BmWmxY1arww
-vV6KgjAdBgNVHQ4EFgQU8kOeHdO942r3cR78izbu/QscRBMwDgYDVR0PAQH/BAQD
-AgH2MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0G
-CSqGSIb3DQEBBQUAA4GBAB7JKK79k5557tO3m4Z6Ggwb+wna9YjHdiEEmFrP0CbG
-ydKsCOn176W5roPXJfVz4LNWRaQ1VD9hJBRNk7l7hCgrbazLj9TtrU9RrklDu54/
-tyZH3BQrH0znl+dxlEgYdfzhd0XQhMP4AGAlIzZUANHCnmjRKkqikPNXO5bMpnza
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P123 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICojCCAgugAwIBAgIBJDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEQxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEZMBcGA1UEAxMQUG9saWNpZXMg
-UDEyMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuGtVArq1otVEuN/s
-xR5XSOEfVzIms1FiprO4UReYXUDbKzmCYC6YypbEnOP2JpLQOPwAfVqLL8FV7xiS
-o+HmK25R0aK9nQGFUPX0U9o4b5NRcWFAoYBAF2GOFBNqGF6d9wBFPlijGMT8nWr5
-ahnujYSC1Emy88N4hkp1fj4o7yMCAwEAAaOBpzCBpDAfBgNVHSMEGDAWgBT7bNQt
-gZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU0L/Nm9/xkf2Ch1oQz5Cvi7zyxcww
-DgYDVR0PAQH/BAQDAgEGMDMGA1UdIAQsMCowDAYKYIZIAWUDAgEwATAMBgpghkgB
-ZQMCATACMAwGCmCGSAFlAwIBMAMwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTAD
-gAEAMA0GCSqGSIb3DQEBBQUAA4GBAHcVVBwhebD5vRKleXMh71kleQIL8QOQFpHM
-jVYS/KJiBsVUTebOeONSU0cuPmzomEkpLyYPz8cDroidExtxGEpkKgYBGi1c5ext
-cDUGFsTWENTFFWjZ7xA56XUtGd8alXJfY0v6QSHqoYFosJvoqU2bjX6jqQVK5HbY
-kko1SxlW
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D0:BF:CD:9B:DF:F1:91:FD:82:87:5A:10:CF:90:AF:8B:BC:F2:C5:CC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 81:c2:63:b3:65:bd:c4:2d:98:7c:e0:85:dd:5f:07:d7:b4:1b:
- 7a:64:a7:7f:60:3d:62:3a:70:af:d5:97:23:23:9a:48:e3:b7:
- 8b:c0:3d:43:c1:66:e8:24:db:ed:a9:ab:0a:70:51:d8:7d:65:
- 92:ea:e9:6f:cb:96:8e:3b:cf:94:e9:9c:d2:27:54:29:8c:81:
- 84:1d:a6:22:65:85:46:70:07:da:1d:e9:79:9f:e7:3c:4e:96:
- 1b:11:d9:08:ec:f7:95:15:c9:db:8d:a7:17:16:3e:76:bb:41:
- 98:15:94:b3:1a:19:6f:1e:dc:10:24:c8:ae:bc:38:93:c5:04:
- ef:9d
------BEGIN X509 CRL-----
-MIIBPTCBpwIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAMTEFBvbGljaWVzIFAxMjMgQ0EX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFNC/
-zZvf8ZH9godaEM+Qr4u88sXMMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AIHCY7NlvcQtmHzghd1fB9e0G3pkp39gPWI6cK/VlyMjmkjjt4vAPUPBZugk2+2p
-qwpwUdh9ZZLq6W/Llo47z5TpnNInVCmMgYQdpiJlhUZwB9od6Xmf5zxOlhsR2Qjs
-95UVyduNpxcWPna7QZgVlLMaGW8e3BAkyK68OJPFBO+d
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 subCAP12
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5A:87:08:21:FB:DC:93:10:6D:9A:0B:7C:C7:6A:B1:68:4B:DF:55:D7
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 67:b8:b5:f3:01:89:95:0b:52:9b:23:ed:15:82:33:84:16:99:
- d5:19:f9:2a:ba:7a:1a:fd:61:2e:32:9b:bf:50:d0:02:cc:b8:
- 5e:0c:f9:8f:7d:6b:d7:ce:29:7d:cd:9a:0d:01:4a:c9:ef:38:
- 13:2e:a6:46:a5:13:4a:ba:01:58:71:13:21:6a:52:1a:e5:2f:
- c8:58:ba:dd:bb:b5:18:3e:a0:5b:94:3a:96:d0:47:05:fa:a4:
- 84:37:c0:e4:5a:42:31:19:c3:86:cc:42:90:32:85:aa:e4:70:
- 23:e2:cf:eb:fe:f3:fe:e0:83:17:bc:c4:15:07:0f:b8:c0:d9:
- 57:d2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlBvbGljaWVzIFAxMjMgc3Vi
-Q0FQMTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFFqHCCH73JMQbZoLfMdqsWhL31XXMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAGe4tfMBiZULUpsj7RWCM4QWmdUZ+Sq6ehr9YS4ym79Q0ALMuF4M+Y99
-a9fOKX3Nmg0BSsnvOBMupkalE0q6AVhxEyFqUhrlL8hYut27tRg+oFuUOpbQRwX6
-pIQ3wORaQjEZw4bMQpAyharkcCPiz+v+8/7ggxe8xBUHD7jA2VfS
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 subsubCAP12P1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:23:89:9C:F8:23:61:42:E8:19:96:9B:16:35:6A:BC:30:BD:5E:8A:82
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 38:53:72:c0:cb:e3:f9:84:7d:49:58:c4:73:96:61:3f:7d:1a:
- 78:47:82:fa:be:2b:9a:55:99:d4:73:ad:49:14:9d:a3:3c:5e:
- 99:66:20:f4:df:d9:c3:d3:03:61:75:0d:18:f6:c4:b8:29:0f:
- e7:e3:e9:37:f3:0d:e0:74:a0:ef:8e:9f:fa:12:18:20:a2:8a:
- 3a:bb:72:e6:20:4f:2a:2b:7f:22:5d:56:01:e8:fb:76:fd:62:
- 44:16:83:a8:7e:53:4d:6a:4a:0c:94:10:64:85:02:07:1d:d3:
- 28:57:9f:e7:57:65:99:37:99:f4:52:ae:de:5e:4f:5c:e9:08:
- f2:cc
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1BvbGljaWVzIFAxMjMgc3Vi
-c3ViQ0FQMTJQMRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUI4mc+CNhQugZlpsWNWq8ML1eioIwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAOFNywMvj+YR9SVjEc5ZhP30aeEeC+r4rmlWZ1HOtSRSdozxe
-mWYg9N/Zw9MDYXUNGPbEuCkP5+PpN/MN4HSg746f+hIYIKKKOrty5iBPKit/Il1W
-Aej7dv1iRBaDqH5TTWpKDJQQZIUCBx3TKFef51dlmTeZ9FKu3l5PXOkI8sw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7EE.pem
new file mode 100644
index 0000000000..37fd72a219
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E3 C8 85 A5 89 54 F8 7A 74 DA 95 B7 7D 60 D7 81 41 5E 30 A6
+ friendlyName: Different Policies Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 subsubCAP12P1
+-----BEGIN CERTIFICATE-----
+MIIDqzCCApOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUG9saWNp
+ZXMgUDEyMyBzdWJzdWJDQVAxMlAxMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowYDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExMDAuBgNVBAMTJ0RpZmZlcmVudCBQb2xpY2llcyBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0NzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALX5qIQqd/Uw
+7MRg2gQjHoTe735/Mxlza2yZGICgJIvj2V7auQHGGXTgsFg1rWaJUXJMGGql2z07
+xZa7WLruITA+1kU1BZ87zY4aifFG/WvgItXFhtDB+OT4kSEJZiNWOg8996AwuhcV
+6w8pZ0cm7idgb/gMJ6lbeI5DN04of9ojxKbuq6JzLKLLxLQmha1XC2PqSUHOHiS3
+yfX9hElPnrORJGjnDZ03p/l8eIb/J8s+L9osoqQ363Km837bdxuioYv42D4YHHLy
+lBm9vTuxd7R234qTINJ7jOSg43/0DPg0gO8gMfZ12JRvy+DyP+Askl7RDGMuxTRq
+z8moPGpV1TkCAwEAAaN8MHowHwYDVR0jBBgwFoAU5Bs+RrfmyKnY7dEzfwXh8V0S
+JMIwHQYDVR0OBBYEFJn4esVCw8dzBLgHq2Sp4l01/p9yMA8GA1UdEwEB/wQFMAMB
+Af8wFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMA4GA1UdDwEB/wQEAwIB9jANBgkq
+hkiG9w0BAQsFAAOCAQEAfzbl1OcrDaD7SGeIH23hl+fmPWKKJhbP6QUM9NRGHVIr
+FaxxdfvL1YJrU5Y4zcqK0O2pYespDfNRJOFJMVAoOzwWrhi4f9lkZIiEaUyIppXP
+mDpI2UQeru/mvOrMvuvd9/FeKi2KtqyxNHCJgj3Z9pdYPUv3pad7cdIILVV3jRbz
+YPS4WguwQhCEEw3ft9D+B2PXMSPhvEBNfAUC0xan6yODR1XjgIihkLuiQe/80Bql
+d5EX0ib/SO9JK/7ybfssFcmxzjas+0geZyg2gDP4H1J1PBoZLw6SXTJ4DO6CIud0
+EhNY3lZQpWUlN7CXlAJiqiQ4tPDto9XZcQJ4S2nHJQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E3 C8 85 A5 89 54 F8 7A 74 DA 95 B7 7D 60 D7 81 41 5E 30 A6
+ friendlyName: Different Policies Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C81C50A3417BD7AC
+
+35uZCwoHIukL6Eoc7HT9txdqgFWZO7UvF2/K1+AU8WplGZAL/D62oWsT+xlEOrug
+FsGiIH/6GpVkF/8NOB2nlWAVv4F6hkDdzfFRIt4vJJmQlGZnG5YKpMfmm95ZnFre
+TE5l3eGnZyhEUK++4Bfq3GwN3AHMV9QSKSjq+EY3D00yaThjWJw3D8YHvXjSIAFz
+gQq6PY9YjtrTFbTgwYo5C7VscvMEhClQs4awU8lBKzt8SFQJVnrG6c8TrQDCq8T5
+N7jNbraxlX0A68djM1ZtisIOTJ5ZoiamshSBU6RFoxPPo714AcSeAYd8dy/7AzAC
+o9FGqxjQe5vRu7OBDTVvKez9hqVgQhEoXBYFDGq1ztRdbBSPc8osXSOlrh+TZjWf
+BrMBznxsP5I07MNaRteQpfFZVQCyIbaeyMO7u5Vb65RNvl/KBoVrN/mu6ONoWInY
++cJBxeA9T9TJmHkA+X1ljR9ofdiRG6C1TQx3XSy5BS7ABaO5RfJpk3tDokAZLB6k
+GnQGu1qfaERGPhOgmejatEs8YKHbUss4jFTzehteJzC9YTvjnd6azAQ1ig2/i0ki
+9PZ1if7o+LkQ9otIM9PzHK04VMf5kv9OgfYSFOTx3wZXisj6kplBgEFl5owKzNHZ
+uAQd/hdPvZU9Cg2MjOnnQg0N6w6ld9GFyVmBWqStibYxLu7z5XrmGrhy5o4C+zTw
+PUjUxKW15GgG3StbOPD/IEgMPOJYgBMZiIM/9kJ1PfmSCVVc4gsKeqTsLsMDzKMM
+QwgAz5Ay1fsJBefxv46KGnubeVPJ427UcUUOMQIajrP6zdKRkPDY1H10l2SV7Jgh
+MQV3lO032PkT/bj+DyXSUnnj5Lr9T/zvPYMml+Rws+P6HFkq1o3VaMxt2p1hHkLY
+ytjaGOsvwGGhIRom0zFsZx39elkG88hqQS46yjR+sV19k+TozKgWwd34LxYhejE+
+qtMa1tunKwJPk7x8zZZRS9X402ZCuds9/6knwlMBtIiSjW3wLv2wYJxyZoyljZ1o
+jUjLzG89VwbLGigf+MZxBMvCH242Gbt8TeyquMTZgX9soXVxqiItzH+jWpEoq8Dp
+CkNOa8bpxFi2ff2hNmfejFB+qdYEWX6Bha4wvXtazSySwKgQjzZZ2++UHOuH+k+v
+/7M7GutB1ZEzsGIErH0FUPKORFHAFR8bbW0GYz3Lxr264HW1JQL31+WDGMUfiRLG
+iI6uwn5ZoCxfjaQ7NKgjlGQsmplDCEeiOEjQEypYdNE01pv5vhIdF9BOGjFVq+Ud
+wnrLYQqk1v1EucB/sb8IatsHu+eQDS4kIRJBlxiMKSNc0uEVqBDBGnE5QXOb2fKi
+pCw7dkdVjgsl92ZJpAhUOQ1KVNTMQku2hi+cCJXtHes8+DcB6G5saJHrNoZBi85O
+gtJQOVbhTqdLke3/6ZuAt3aJHGhUDosQGKAsM7UFJWJWYau5AfA+oiqwtkwF9PxT
+RIrjwmgEMU1xqxssAGvwQFYOXs5IsA4BZg5fL6aTiJFfRWc9nrsrwod7ddU9dPOx
+TbblMBSQCMWjuLIgYXfYx2FHGjdJ1VZKosl4EG3h4rVdtTxrFkP6jza1fgGyJbkq
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8.pem
deleted file mode 100644
index 0468f302f0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8.pem
+++ /dev/null
@@ -1,210 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P12 subCAP1
-issuer=/C=US/O=Test Certificates/CN=Policies P12 CA
------BEGIN CERTIFICATE-----
-MIICfTCCAeagAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD1BvbGljaWVzIFAx
-MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUUG9saWNp
-ZXMgUDEyIHN1YkNBUDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKniBOhW
-3+GUH9cLSjfU8TnmUuKC8zu+bx+7Vd8N20wFU83y33ReAvzS9j5mBAT6qqLMg52i
-t5h4ni8MAttxqQivCwZR6U+Mg2KMdHEAbvTp8ya69ZdGzc8StBaJ1OIIRHtRicl2
-Ek85wzHazjfWPtmnO0EaIzJImL3U24pAKDq3AgMBAAGjfDB6MB8GA1UdIwQYMBaA
-FADjZemB1Ia5xx3n8zM5Bl5MEaX5MB0GA1UdDgQWBBRCiBzBeLdD2gCvvd66Q6fl
-tWH/8jAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
-A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAYKVZU12G6lcEkxyRYlMJ
-umN4xtytcDe50I4AFgMJlgCcLvupgFN+5QWwSGtdBpSrN3lDBFTUQ/ZrAL3O4nzA
-HaKM6LaBCQS1//FE6qbi2UvRHfp8RoYUH4hM1nzTb7/Za0wsWTwegcz1uOZ4aLQ5
-M7QKfWfzax6EarTJ4jorUQA=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P12 subsubCAP1P2
-issuer=/C=US/O=Test Certificates/CN=Policies P12 subCAP1
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFFBvbGljaWVzIFAx
-MiBzdWJDQVAxMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTTELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQDExlQ
-b2xpY2llcyBQMTIgc3Vic3ViQ0FQMVAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQCgzy2UzpvEK8JSY1wMRMaoYi/MuP+Hkmtwerm88lsIWe07HlT55nuxjp5/
-vSPZEgCYm+wk0AU87yD2n6OkCJn+oUVbeucGoJSwuTEs7HK0YZq+RyYdzcoZ7Z4Z
-EzNUC2I+vPj01u9NL0XBZLJ7g5h6Au8d3zGEkn6bEPk565LiewIDAQABo3wwejAf
-BgNVHSMEGDAWgBRCiBzBeLdD2gCvvd66Q6fltWH/8jAdBgNVHQ4EFgQUZ+UNjYxs
-KrtVbS3oIqoES3MriCowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZI
-AWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAESq+2Cg
-vywkdxLqsugNl7K/+BK8s0yadUr/Q/DZKPALlPRaVW7GzKJ7aCGw1xRiMmkV5Z1Z
-UjSdHXTJetXdNpCfjpVnnrAB9DjkA7RrKI1KTPxhnywtwQNTpD4gceRP6icRwaN6
-7Y/GlL6Fi1LbuHlGF94I9XchvB1mTQ0PF52O
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBJTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPUG9saWNpZXMg
-UDEyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5unCMuN8PuVFWbqxO
-/wnIQsciPiEo1GoKWjM6+kb9l3h6wWyWYwmst2c158qcJLY9PxaUMhqQd/SY0Tt9
-WlHXVcE8rMoWSGmFxfK33UpeCtqwz9ugPSWwZkqx2lI/0ozQXgjYb0J9/EoKw1O0
-CxxrdQdPQkyLD4Uxe87/MlpzsQIDAQABo4GZMIGWMB8GA1UdIwQYMBaAFPts1C2B
-nsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQA42XpgdSGuccd5/MzOQZeTBGl+TAO
-BgNVHQ8BAf8EBAMCAQYwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFl
-AwIBMAIwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GCSqGSIb3DQEB
-BQUAA4GBABX9GMyAC90FH8BvpnNh6SDn2MIT7iINc4/9u64d1dxEhqogqcR58khK
-btHyx8YrgbCcqUNS4Xs7ckW5k2VNAd9dG0Chc0uk6rwkv+sD1/zJi8LIGd/3cFjk
-biIVYqPxb7WpKqo97V+43tMFsTqJNBSh+6W14vlP55+Ep5IlxcOm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=Policies P12 subsubCAP1P2
------BEGIN CERTIFICATE-----
-MIICmjCCAgOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGVBvbGljaWVzIFAx
-MiBzdWJzdWJDQVAxUDIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBb
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMDAuBgNV
-BAMTJ0RpZmZlcmVudCBQb2xpY2llcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0ODCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxJrMY6Ju+VhfX1vaWidfiPUdCuUMy5lF
-7s2Vle2r9FOQQ8se76y2jPKssqb3XIIG+VLRlS5GMp8T4t6VgLtE+gqb4mcBuIdV
-KMwJtDrYnfNFML4yyCKSvh51ionton2akkJGnJ2POvQ4z7sLXrKKCKcGTWvbVqej
-BwfkNvwk9KcCAwEAAaN8MHowHwYDVR0jBBgwFoAUZ+UNjYxsKrtVbS3oIqoES3Mr
-iCowHQYDVR0OBBYEFOEf7/tJiP53/PPTMiuw+1ENh3KRMA4GA1UdDwEB/wQEAwIB
-9jAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAIwDwYDVR0TAQH/BAUwAwEB/zANBgkq
-hkiG9w0BAQUFAAOBgQAkAFezJ/Jf3nv9Kuw+VwXEuX91e8e8wClFff+eY0Af+kXl
-fvUJnXN2TOh1iBU8C21WkavgIS9o8grJb3hbDpS03Yodnt/0151BiCMdLQI02sFK
-mHABJwiZZlLj7peF4avVV4Piw4arjXD7Z1bKYlHOZeTHF1hgS/XINAc8IUsfDQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:00:E3:65:E9:81:D4:86:B9:C7:1D:E7:F3:33:39:06:5E:4C:11:A5:F9
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a2:21:e6:6b:0b:99:66:79:2d:86:a7:9b:cd:37:9b:4d:73:1f:
- df:91:63:c4:de:55:15:53:b0:32:ac:c8:3c:bd:96:aa:ae:c9:
- 4f:b2:7c:9d:40:d7:f4:5d:99:8e:fa:2b:44:2d:75:ef:01:38:
- 86:c8:59:ae:e4:62:e4:83:b4:73:03:34:d1:7f:52:bc:3d:bb:
- 77:7e:7c:c9:41:09:4c:08:4f:a9:7f:d9:d9:0f:bc:46:9d:05:
- 70:2f:66:0b:d4:0d:80:ec:11:83:4e:1b:90:95:ad:86:02:77:
- e8:19:aa:a6:48:29:a3:9f:36:c3:ec:9a:f5:a4:9a:0b:f5:11:
- 1d:72
------BEGIN X509 CRL-----
-MIIBPDCBpgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD1BvbGljaWVzIFAxMiBDQRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUAONl
-6YHUhrnHHefzMzkGXkwRpfkwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-oiHmawuZZnkthqebzTebTXMf35FjxN5VFVOwMqzIPL2Wqq7JT7J8nUDX9F2Zjvor
-RC117wE4hshZruRi5IO0cwM00X9SvD27d358yUEJTAhPqX/Z2Q+8Rp0FcC9mC9QN
-gOwRg04bkJWthgJ36Bmqpkgpo582w+ya9aSaC/URHXI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P12 subCAP1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:42:88:1C:C1:78:B7:43:DA:00:AF:BD:DE:BA:43:A7:E5:B5:61:FF:F2
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 38:85:fb:83:ec:f4:d5:e4:42:27:68:d3:d6:5f:c9:d5:60:4a:
- fc:33:39:94:ce:d9:28:71:4e:fe:aa:e6:61:05:6b:1c:42:96:
- 56:40:e4:48:e6:96:65:21:17:f2:e6:8e:69:50:6f:44:8f:33:
- a3:8c:28:e9:f5:85:d6:de:55:bb:03:30:02:eb:bc:49:70:3b:
- bb:12:c6:f0:8c:8e:d6:5f:3f:30:aa:58:a9:6a:4e:3e:46:a1:
- f6:76:e7:a8:7d:28:e8:d8:44:32:58:76:88:f0:05:5f:37:27:
- 03:28:e0:b3:88:c3:75:41:50:81:c2:fe:04:22:be:ea:4a:2b:
- fc:a1
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFFBvbGljaWVzIFAxMiBzdWJD
-QVAxFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRCiBzBeLdD2gCvvd66Q6fltWH/8jAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQA4hfuD7PTV5EInaNPWX8nVYEr8MzmUztkocU7+quZhBWscQpZWQORI5pZl
-IRfy5o5pUG9EjzOjjCjp9YXW3lW7AzAC67xJcDu7EsbwjI7WXz8wqlipak4+RqH2
-dueofSjo2EQyWHaI8AVfNycDKOCziMN1QVCBwv4EIr7qSiv8oQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P12 subsubCAP1P2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:67:E5:0D:8D:8C:6C:2A:BB:55:6D:2D:E8:22:AA:04:4B:73:2B:88:2A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 25:a2:e2:75:db:ff:f0:10:9c:e2:59:90:7c:f9:c6:8e:63:cc:
- d4:d1:19:7e:d4:97:09:0e:ea:09:59:88:13:b4:ec:07:f9:58:
- 7d:fd:87:4e:85:00:16:e2:e4:54:c3:ec:fe:0e:bf:f3:ab:59:
- af:49:e4:97:ba:c2:df:6e:45:e9:4f:e9:0e:4a:07:41:85:8e:
- f5:7c:da:c7:21:73:33:37:ff:e1:e0:fc:ae:98:29:f6:04:2d:
- d1:4b:54:a4:fb:ee:17:ae:4d:73:b9:ff:ca:6e:6d:56:c3:27:
- d8:d2:b4:d5:9c:c6:3d:40:48:f9:37:8d:2f:22:bb:55:4f:84:
- 07:65
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGVBvbGljaWVzIFAxMiBzdWJz
-dWJDQVAxUDIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFGflDY2MbCq7VW0t6CKqBEtzK4gqMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBACWi4nXb//AQnOJZkHz5xo5jzNTRGX7UlwkO6glZiBO07Af5WH39
-h06FABbi5FTD7P4Ov/OrWa9J5Je6wt9uRelP6Q5KB0GFjvV82schczM3/+Hg/K6Y
-KfYELdFLVKT77heuTXO5/8pubVbDJ9jStNWcxj1ASPk3jS8iu1VPhAdl
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8EE.pem
new file mode 100644
index 0000000000..768abb6848
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B0 E5 E0 9E 85 E8 D6 CB 4B DC EE DE 28 1C 24 C5 7D 32 B6 7A
+ friendlyName: Different Policies Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P12 subsubCAP1P2
+-----BEGIN CERTIFICATE-----
+MIIDqTCCApGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZUG9saWNp
+ZXMgUDEyIHN1YnN1YkNBUDFQMjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMGAxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMTAwLgYDVQQDEydEaWZmZXJlbnQgUG9saWNpZXMgRUUgQ2VydGlmaWNhdGUg
+VGVzdDgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBmcAEklgPYV1v
+LOS3HNnWEIU4xixNfJqIAwV8nqXrQx7a0eymXeQ7ijyCkGPTOG+X5SHl7MT1EYun
+ASdRHbAgauU8IMhcG3a9GW6cP1uT04cHpS5WJ9SU71MDPRmLN9YorypgZP3ZxqIm
+Jp4g1KWYqwqegJ26wu+8JpmFFhj79MYGRmbM9TisxgPZP0kyJroYcSrdNJMXOXaU
+bmsJpQwwuzuDn4NtH+nTpaHx7ab2BKyqKYKyxkFLmr84YbD9Hqa9/czLJGF0Tf+u
+IUwenhHylbsWRlHirRA0FqHagTIl1O9+ptNsYcQGtYKE4mqMtRohd3GMgKqJx7IK
+yjG9uSWHAgMBAAGjfDB6MB8GA1UdIwQYMBaAFMelN6fQ+iTlfN/b8l1p2+7K9pnu
+MB0GA1UdDgQWBBQXoW+qF2xTgQ0UHV2q7B8e9Jbn9DAPBgNVHRMBAf8EBTADAQH/
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAjAOBgNVHQ8BAf8EBAMCAfYwDQYJKoZI
+hvcNAQELBQADggEBAASApMwfhokiI14ONWgsD8Q0fVCOMZAHpFBEFWWsI7FPtyPR
+sLVIdpHCBg1CqlW8hM9EMOa8IGBlN/rfsX/EbWFtOTUD5VNXG7HD9qfexVdddf01
+hqyLKW6IQUZdiGy8ljN2nuLN5kjrv6EaAYbbcrfgkrSiB1dNMvSG0ZCZfALNXAl8
+5ny4g1l6uvzGmb6k3O6F6s1NOMpJuUpHlgZ9Ggd6NZG61vpYDSMHzknfduvzbHhy
+r5A57ceLPfJrCzdGXNhKhtIrq63zfkIFCC8MygAWcySXN3HtxcHu7QTz4M3rVID6
+tVUg+PqT+oteuGr6tqeJpZwM4xZk9VabHaVr4i0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B0 E5 E0 9E 85 E8 D6 CB 4B DC EE DE 28 1C 24 C5 7D 32 B6 7A
+ friendlyName: Different Policies Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0FB51308505B1026
+
+tYU/hbHcZnDlwz+bcFhFWFNLw8Ha/+9Rg+i9j1SaFMEQAWkj/tBkhoXKd3+8F/IQ
+gIonTU2u3keet25wJueGZnryg8c/tGAcWaZby36qIA6Q2BFK8UYu1NsRKKGMJF+V
+RQ2W0NuHNCfvM8J//9BmFggNtK/IDWa9KgbDstIJW70Q3Y4pJdrgSiiR4+nj0G/4
+oxH+rIy9Wds+8BgacJkwbPSVgzNjFwlxDZHefOeA6kUBcp9G6ZhnoAv0C4IBL2nH
+rIGzuyJuZ4ziU7I2D6ABGdzc0kcLqbP3D4d7iVILh7Bn2P1RWqmnzwHmFO3Obcvm
+e7amM0y2KCQyPqrtCXB+1a5jBsYE/KI4w7Ckp1X4ZylFx8gNgW4OHJHoHBor6nss
+rb+sL8sRviary3nbtUFIjWSHxDaebo7m4nP32dk7k3fd+EKq3FegSCLeUpbhk0+L
+dw/Gn0xWJIgrMcHgYYil+h+VKIJ8zhLY2BmRb1u8uGcGzKh7XkKLP1tBuzxdmwa8
+gLfpBeqT+4GAxFb1CeiTgoBoJSci0taRyNa8+BAtiVfZTf1NgAneqvK0ElpmAu6F
+H3cH1H+Suq+rL0nBDKtY6VwTZsSAigYVky4ZI6lGKUFT+qilK6V0TqTWNfTJ+Cxg
+RqK8jESxzRWWkF7cXe7FCEuUiBIQPjEp4CJiv5pfVfUoFpIF2yWw29MxmlZvb1g2
+xAaY7m6jjXuHovWMzKJfc1bXCW3uq02hTlk5NHcJtnSOYok1tZ+YjmJU1Uv8wKYF
+A3IzGAqUMQUjIxYNQDe3Osy90tqKnqjX9FrwRi58cpdWu4vejPp91mnWuvGvfdBQ
+FIi3m6hUFTCIN8bZXwBswEjCcztjWgPCDBthLST1B2MKgdHHbSQ15L6o8njMvN4j
+zeufk1L5/+RaBPvKtaE5Oa542DdZIMOSx6u9FeZ7PtPqw8bU8JfMqvt9iP1SPvvo
+55OC8Nmxv+liwEgZ6bK3PwBGJDBEutgNvrlh8LC9DxYh3Xp+DTdeZHLljr6FWmWq
+f2gGHh5lP0L2bLLVk8rioiTy/SYaX0ik96cBzAyy4IUMIbfFB8B0zYNyP8YSbDHD
+gnk39nwpDHm7LaT3LL8zg+8nSSAnXdJonjOCV8s1f5At2Gg0JJXx197FlH8S/tIm
+VLe49xTMs4MsXgW7Yn7Pe+obc8P5GkYBaprXW7b3JTpox8AhTJPXcwIXs3CorosN
+yTdDunGLXbSFIUdA/xEzJOfiuOaiBTk7ippGeT+2ZgMVRvaztnH2hcgAjTJ0I3t0
+HYu4Ax1y3w+q+x5viRvDbC2zQF1Mpl041dvwngI0kevx7p/BOdZaslZiAwVm0k8m
+1+KZFkVTxa06uVCOas3LnaxF49NOrLnW0dVLJPVl85ucPpZp5y7wKV9Z2lSNF2m8
+hBbVT7JV+gQjJC9l1CFbtzTNV54XHEsNYptv73/JkdVz5IBOylfrY7QzILF47BYG
+ecmTZqvFuNS0bFSyev5OEL4ZtQoA6Bvnpmq0+prtQ4lbyahCBmXaCaF8xATLbVB6
+wwOMl2DL64fIIAtNzq2tDE5oqWr5T8+9t3jp8jdeMVTn8D7vK11HKg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9.pem
deleted file mode 100644
index 4b2ed859a9..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9.pem
+++ /dev/null
@@ -1,263 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P123 subsubCAP12P2
-issuer=/C=US/O=Test Certificates/CN=Policies P123 subCAP12
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlBvbGljaWVzIFAx
-MjMgc3ViQ0FQMTIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBPMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMT
-G1BvbGljaWVzIFAxMjMgc3Vic3ViQ0FQMTJQMjCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEA/QzSHTVMWeTWiSZ9qa++M+UWF0AfCPT9oTdaLUwN0Tnb845G4Jh5
-Ov5u75dfUmAmvRM1brlhZoYZZa3cBvQP+1YoAOosVY1qy4xX/6OE2zqM45IRhyLd
-VlAJ2WJ96jOpb/HV3vodX2vjDndDMMxKRXd0WIHzbC/aZGzWYXwUvfkCAwEAAaN8
-MHowHwYDVR0jBBgwFoAUWocIIfvckxBtmgt8x2qxaEvfVdcwHQYDVR0OBBYEFIvs
-OfOjrm45cGR/aCtNVJAsjgXAMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCg
-uNxU4/XUIM6O0+DSr6607Epm4PaQEAnvLsgMdHGHCLXL0mwL/9sNnSXGQg08zVpa
-k5RjmIGMD+UcMJ28kArNA9u3q4QNB5OXZtrhoPTGhBaBtwR3rL2ZEvQxUw67t2wV
-TpBcguqwCt7IIuNbBOoN3Uilox3T4WptJ/A7+zW8oA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P123 subCAP12
-issuer=/C=US/O=Test Certificates/CN=Policies P123 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAMTEFBvbGljaWVzIFAx
-MjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBKMQswCQYDVQQG
-EwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlBvbGlj
-aWVzIFAxMjMgc3ViQ0FQMTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOll
-J21WulD37Mn1rV21nTiHp+5zJm7d2iKVBk051MbS63EnC5jnUm0D6a5QJiQR8Ai2
-tuB17ppJED42WQtI7o8exytiya4Y4BvDOeGlVbVZSGgbk2vjlTzg+caDcAkVSzWD
-YMs02A14NrbFODXEyAyJ7rsOTycvQorNHm6zUBvRAgMBAAGjgYswgYgwHwYDVR0j
-BBgwFoAU0L/Nm9/xkf2Ch1oQz5Cvi7zyxcwwHQYDVR0OBBYEFFqHCCH73JMQbZoL
-fMdqsWhL31XXMA4GA1UdDwEB/wQEAwIBBjAlBgNVHSAEHjAcMAwGCmCGSAFlAwIB
-MAEwDAYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAD9AiTI21pU5RaP49a5YdThygUEjL+Hvvoq4cbbg7dN3qbjYJBXUruTWyY+c
-pSqrS3q3rUlt99O+9JFqZSX8LCVRMg0yWSlwymdeY8a5EBS099ZFB+r9v4tIndk0
-r1uaX/PyEiMNd+eT8GdxBwl+Jo+AHTvuHx0G9iRwLbS5Es0u
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Different Policies EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=Policies P123 subsubsubCAP12P2P1
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAMTIFBvbGljaWVzIFAx
-MjMgc3Vic3Vic3ViQ0FQMTJQMlAxMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0
-NTcyMFowWzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVz
-MTAwLgYDVQQDEydEaWZmZXJlbnQgUG9saWNpZXMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKiBlSODZy8jLC4WxxNVbFCA
-SbxY2A4DLV2OXhCjWmUmHQvZhiXk2p/wQCX/9VMcX7XRH9a3JLM9l6ZSEIGVT6lO
-R55lGOjNfpF8x+pGe/t0yPB/6ntPn5e9ZSNhDJDoYkJHfdplTFu2AZLbaVPlysXL
-AoO69sbnDPVxAjxFX2zLAgMBAAGjazBpMB8GA1UdIwQYMBaAFNMqu/C1V0GVUt3P
-qLuSnOARbnO8MB0GA1UdDgQWBBQg7JO9uU0ScBZcuzznmEWH36QRTzAOBgNVHQ8B
-Af8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUA
-A4GBAEeaZ7Bsae+J0lNKAzqJhR4MHfT/5SBBazWGVSwIbpWl02esU9RtrStOTA8d
-zcMp2eLg3KDI+XRsYkxFb+fmJDckIYhGk2g3B9kW1a24k8DetYIqOXtFvleJ55dG
-iROwoCaH8/bW75CMK0alSXqJCAnTq+Pbg5i0nPX0ShJlSjAf
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P123 subsubsubCAP12P2P1
-issuer=/C=US/O=Test Certificates/CN=Policies P123 subsubCAP12P2
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1BvbGljaWVzIFAx
-MjMgc3Vic3ViQ0FQMTJQMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFQxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEpMCcG
-A1UEAxMgUG9saWNpZXMgUDEyMyBzdWJzdWJzdWJDQVAxMlAyUDEwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBAMa9AAnNzFuqJqv1OdC4F1PtY4Lqcc+JJQBnnaIi
-roTN/plb6fUL5m/SFbfSZnf/qQbYUkosko2p0cdF5VrblaCvx7vB6l12at9Zskn4
-wKneBrfSJUVDEgSyWm7mY6t1Fla7OSfywUObt1NWEzq3pyWoSKTIQxpMJ3jnYERr
-/wJ9AgMBAAGjfDB6MB8GA1UdIwQYMBaAFIvsOfOjrm45cGR/aCtNVJAsjgXAMB0G
-A1UdDgQWBBTTKrvwtVdBlVLdz6i7kpzgEW5zvDAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
-AQEFBQADgYEAgk/D/ABBm/yIi8Qk1ISreDz7OgEaqXoqyrQY9uq3nf/Xzlmrktxe
-C7bEDiYGugly0cHFHGProTJppes2ECdcVmrpXoIHSlbP3WucAOsWcyIW9tfH+Xsk
-HAts3bXwDmfI5WEndwM+p6kMKwRsMT8/q8XJ3ZCNgsu34eoKRWhBzlQ=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P123 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICojCCAgugAwIBAgIBJDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEQxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEZMBcGA1UEAxMQUG9saWNpZXMg
-UDEyMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuGtVArq1otVEuN/s
-xR5XSOEfVzIms1FiprO4UReYXUDbKzmCYC6YypbEnOP2JpLQOPwAfVqLL8FV7xiS
-o+HmK25R0aK9nQGFUPX0U9o4b5NRcWFAoYBAF2GOFBNqGF6d9wBFPlijGMT8nWr5
-ahnujYSC1Emy88N4hkp1fj4o7yMCAwEAAaOBpzCBpDAfBgNVHSMEGDAWgBT7bNQt
-gZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU0L/Nm9/xkf2Ch1oQz5Cvi7zyxcww
-DgYDVR0PAQH/BAQDAgEGMDMGA1UdIAQsMCowDAYKYIZIAWUDAgEwATAMBgpghkgB
-ZQMCATACMAwGCmCGSAFlAwIBMAMwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTAD
-gAEAMA0GCSqGSIb3DQEBBQUAA4GBAHcVVBwhebD5vRKleXMh71kleQIL8QOQFpHM
-jVYS/KJiBsVUTebOeONSU0cuPmzomEkpLyYPz8cDroidExtxGEpkKgYBGi1c5ext
-cDUGFsTWENTFFWjZ7xA56XUtGd8alXJfY0v6QSHqoYFosJvoqU2bjX6jqQVK5HbY
-kko1SxlW
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D0:BF:CD:9B:DF:F1:91:FD:82:87:5A:10:CF:90:AF:8B:BC:F2:C5:CC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 81:c2:63:b3:65:bd:c4:2d:98:7c:e0:85:dd:5f:07:d7:b4:1b:
- 7a:64:a7:7f:60:3d:62:3a:70:af:d5:97:23:23:9a:48:e3:b7:
- 8b:c0:3d:43:c1:66:e8:24:db:ed:a9:ab:0a:70:51:d8:7d:65:
- 92:ea:e9:6f:cb:96:8e:3b:cf:94:e9:9c:d2:27:54:29:8c:81:
- 84:1d:a6:22:65:85:46:70:07:da:1d:e9:79:9f:e7:3c:4e:96:
- 1b:11:d9:08:ec:f7:95:15:c9:db:8d:a7:17:16:3e:76:bb:41:
- 98:15:94:b3:1a:19:6f:1e:dc:10:24:c8:ae:bc:38:93:c5:04:
- ef:9d
------BEGIN X509 CRL-----
-MIIBPTCBpwIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAMTEFBvbGljaWVzIFAxMjMgQ0EX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFNC/
-zZvf8ZH9godaEM+Qr4u88sXMMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AIHCY7NlvcQtmHzghd1fB9e0G3pkp39gPWI6cK/VlyMjmkjjt4vAPUPBZugk2+2p
-qwpwUdh9ZZLq6W/Llo47z5TpnNInVCmMgYQdpiJlhUZwB9od6Xmf5zxOlhsR2Qjs
-95UVyduNpxcWPna7QZgVlLMaGW8e3BAkyK68OJPFBO+d
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 subCAP12
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5A:87:08:21:FB:DC:93:10:6D:9A:0B:7C:C7:6A:B1:68:4B:DF:55:D7
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 67:b8:b5:f3:01:89:95:0b:52:9b:23:ed:15:82:33:84:16:99:
- d5:19:f9:2a:ba:7a:1a:fd:61:2e:32:9b:bf:50:d0:02:cc:b8:
- 5e:0c:f9:8f:7d:6b:d7:ce:29:7d:cd:9a:0d:01:4a:c9:ef:38:
- 13:2e:a6:46:a5:13:4a:ba:01:58:71:13:21:6a:52:1a:e5:2f:
- c8:58:ba:dd:bb:b5:18:3e:a0:5b:94:3a:96:d0:47:05:fa:a4:
- 84:37:c0:e4:5a:42:31:19:c3:86:cc:42:90:32:85:aa:e4:70:
- 23:e2:cf:eb:fe:f3:fe:e0:83:17:bc:c4:15:07:0f:b8:c0:d9:
- 57:d2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlBvbGljaWVzIFAxMjMgc3Vi
-Q0FQMTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFFqHCCH73JMQbZoLfMdqsWhL31XXMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAGe4tfMBiZULUpsj7RWCM4QWmdUZ+Sq6ehr9YS4ym79Q0ALMuF4M+Y99
-a9fOKX3Nmg0BSsnvOBMupkalE0q6AVhxEyFqUhrlL8hYut27tRg+oFuUOpbQRwX6
-pIQ3wORaQjEZw4bMQpAyharkcCPiz+v+8/7ggxe8xBUHD7jA2VfS
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 subsubCAP12P2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:EC:39:F3:A3:AE:6E:39:70:64:7F:68:2B:4D:54:90:2C:8E:05:C0
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9a:7c:38:8c:95:0d:e2:8e:c6:fb:4c:43:f5:4f:c6:0f:4b:ec:
- 2e:bb:a1:8b:67:77:3f:7f:55:8a:02:ed:2a:f0:4e:0a:7c:e8:
- d8:c1:26:37:47:28:ba:e5:47:de:79:74:30:b4:a1:66:8f:bd:
- 8e:7d:9a:4f:37:52:71:ad:c6:50:b1:fb:ce:eb:0b:f0:58:54:
- a8:22:51:9f:d5:d3:92:06:20:35:f6:e2:4b:8e:7f:a8:12:f8:
- 38:a3:51:fb:cd:92:4b:2d:40:2f:f9:b9:ff:25:4d:f0:7d:9d:
- 20:00:e3:eb:94:24:fe:05:ed:e2:b3:7e:fc:fb:1b:c1:4e:cf:
- 9d:30
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1BvbGljaWVzIFAxMjMgc3Vi
-c3ViQ0FQMTJQMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUi+w586OubjlwZH9oK01UkCyOBcAwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAmnw4jJUN4o7G+0xD9U/GD0vsLruhi2d3P39VigLtKvBOCnzo
-2MEmN0couuVH3nl0MLShZo+9jn2aTzdSca3GULH7zusL8FhUqCJRn9XTkgYgNfbi
-S45/qBL4OKNR+82SSy1AL/m5/yVN8H2dIADj65Qk/gXt4rN+/PsbwU7PnTA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P123 subsubsubCAP12P2P1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D3:2A:BB:F0:B5:57:41:95:52:DD:CF:A8:BB:92:9C:E0:11:6E:73:BC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 37:cf:8e:70:a0:12:c6:cf:ee:13:28:cd:1d:e3:f8:8c:6b:09:
- fd:d7:31:1a:c3:2c:77:f5:13:3e:ff:6e:b7:23:0d:4d:33:3f:
- a1:f4:37:4d:c2:84:0f:6d:2a:25:df:40:f8:25:96:40:7a:fb:
- 59:29:4e:99:c8:8d:63:7b:23:b6:c8:eb:72:70:8e:f3:ca:5a:
- 2a:36:bb:c6:9a:80:45:63:49:c9:9f:68:32:90:84:e4:a6:ca:
- 22:52:d9:99:16:fa:34:93:38:ec:ba:f9:81:0d:26:b9:5b:03:
- 3b:0a:ce:85:43:8e:bd:47:ca:de:50:4b:42:e8:97:91:74:12:
- ac:5a
------BEGIN X509 CRL-----
-MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAMTIFBvbGljaWVzIFAxMjMgc3Vi
-c3Vic3ViQ0FQMTJQMlAxFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8w
-LTAfBgNVHSMEGDAWgBTTKrvwtVdBlVLdz6i7kpzgEW5zvDAKBgNVHRQEAwIBATAN
-BgkqhkiG9w0BAQUFAAOBgQA3z45woBLGz+4TKM0d4/iMawn91zEawyx39RM+/263
-Iw1NMz+h9DdNwoQPbSol30D4JZZAevtZKU6ZyI1jeyO2yOtycI7zyloqNrvGmoBF
-Y0nJn2gykITkpsoiUtmZFvo0kzjsuvmBDSa5WwM7Cs6FQ469R8reUEtC6JeRdBKs
-Wg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9EE.pem
new file mode 100644
index 0000000000..6771c05fc5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/DifferentPoliciesTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 81 22 E6 1F 10 35 F9 D3 8E 1C 0B 35 C9 38 1A BE 5E CA 1B 30
+ friendlyName: Different Policies Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Different Policies EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 subsubsubCAP12P2P1
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEpMCcGA1UEAxMgUG9saWNp
+ZXMgUDEyMyBzdWJzdWJzdWJDQVAxMlAyUDEwHhcNMTAwMTAxMDgzMDAwWhcNMzAx
+MjMxMDgzMDAwWjBgMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZp
+Y2F0ZXMgMjAxMTEwMC4GA1UEAxMnRGlmZmVyZW50IFBvbGljaWVzIEVFIENlcnRp
+ZmljYXRlIFRlc3Q5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvves
+edFLgv8vlu0sxCTplwV97n0bNnx9po9ihH5BWII4NuhB1SG566w+qeo+LxlUDCr7
+SF3lwgxIvo+PaKcNP7SIiFEt++kSyhk8DjX5qKNZjPWDNWDDD6ZJBTLAl9YGlUdY
+knJdMBfjmsCQ0BP66ip203PSnQTCuhLdRN/syXTP5GC7MejAmILFCyIddxBi9wwd
+nDNMKNl4qhwcYdU8gCAB52ERHJ/WFJ9fSGkVWus81ViI5FaWblGC33EgUm8jqFX4
+hlvygwD4Q/9bjVVJefDXXXJ6uStLrY+K6Vf8rwtTLneOo51ZE3QMfkL2VqR9sB1v
+8Yx4HcOez04D3XiIvQIDAQABo2swaTAfBgNVHSMEGDAWgBSJIBeE+6y7CdfeXl6e
+aPY5UB9AiDAdBgNVHQ4EFgQU4wZXd/NUEr4ONS0cVpjBz6mlU+gwDgYDVR0PAQH/
+BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOC
+AQEAO8XGc+e+gxRvjmGI9a7myCl3mhrS9UuU+yid6C6u+C00it+ummR7SeHikTDJ
+j4VGXGpsaIRTPg0O+ddfegXB+WsQ8Rls4dpjUz7RLfMZFVvr7vWBMBDSZjQPYieE
+BYvzK0boQRrTeAchP06/SOl9JHfFuYm/YOqvgofTJaG1SiEULCdC3kqhU6V5rY1w
+oJPvgmBOyw0Cudj4H2zdLlcWqF0wl9Tc+BECqyJe+A4WW1nbrCmS98aHtLOnWlSI
+nAfWDY6emd7hja7EuJdNqWVenkX/mske6yMlH7PNNEhMjeNVQMt9YlLNb+A7i/XP
++W/k74kCn3JDwq9dfLK1kya+xQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 81 22 E6 1F 10 35 F9 D3 8E 1C 0B 35 C9 38 1A BE 5E CA 1B 30
+ friendlyName: Different Policies Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EA41D9D067E8186F
+
+20aVc5sPdsVTrKZiDEgRPqQDKgU5ItFmVr9RfnxMnSqLAS35g5nTuIpKrpX1n4oi
+rUqa86/MEW//0BFkaw9+N4wTfhbuASR5PulqxwaREjhlcbwQaeGyenJMv/Kk0ZlR
+EvTQl8ATW6Z3zAnfmDB5AEwjy/0uddw1ApYgk8uRh5K1aXYKYW7iBIju0nqu8+Dm
+7lwlVvJXGRf+YUUeMIYHFPAY6OIdLFGPJrIGxmc717a4pGXKRyUw8g0EGAc/wR7+
+ZzJCo1DBMphBXIF9NOYBbOBjQqXW7+Pq9lFfXq7SbVzGCnJnJ3rJm54Pkh+RBosS
+Dhv8WsKHwH4szC2isG8vWiK0ymIDYak6ii1joPmR9kRBjxGRgdfVoluUHdWZ9XcT
+y5w/XULCdiRv0j1rLtGTP/A7th+urJUONHd4S5fh/RQVhGN7MCK54V9pwULHvGz7
+qWSE221o2lAjPW73G0aGESqMTE5w9Hx70GWtdeCO0uBTizf0TVL73Ycfa0+5bGpc
+tT/kNvYT2cxiM9dgSY9fc4v3X77V9AdibgA5/rVS1w+XQpsYVA4OpeOiNoT5+3X9
+cq1eS5U2iceom/uL2lXa+s3WGopFpl31b8zRyd49AMnqFD2OSn7VSy9SXff8nj1Q
+7QdU8d+3seGzEqolAfJuOmPUDAL6C2gx0Fyov9BIFcuTYfsS5XB77uxcdoaMsUSN
+Oq7F0DEHYEi09ZJtxjvsUXMALib12j8v0YhU1oOF6S+XGytBhfzNeZlKFXiiY5o3
+TRyJyldpH3uLn7CC17NoCqC4SEmDxJTHFdItvGNX1YnRz1TGw4wiLKdao+IBytqB
+MV7RzC0PGFVeEkbd5w6NoLdyydT1lYMN6WntX+maf0VPUfDjoEp6qAPctW05Hj/I
+4VjdBpf5AlNHh0heOgEMYhbckyLvfUAEBCCKSAAnxkHIoqF4IcQpYXG1IEQg63KJ
+EeFAX+ea8U0ggzbHMkCWKTFp4FmBbDR9mgggv+eCNWKhmU23yxuBXDIilqRlBA01
+5QbwHLJEyUcznsAuyU1q7EC957Zxu4rFrxVmE59Fh9rRY9WyoCE7unHoqYpP8HFE
+fJw9+xYYgDnyfGad6q0o+RwSXNhvaG2nxMGap48nkHISmONY1um5ikFotyir6sA3
+4p25JKJADhHWFHMvZzReaS749hAlduWfN8Es9vwzuPGxSiimfBeMBblcOC4j7AO7
+iJF6cQXvrR437XxkJ7UbB0zp+6bFXjQuYOtbTP3tEYKuovdGSD76PsqSzcZYdEC5
+6dWvIGO+1ThdJQwrRyKAG19cXdPwPW79ziPeiOrLXPEHwADOVebpfBCGUz0aY/eq
+NDJhwxRBttgQZRojV7DMQt0wVGlW2eFWBHmrxKk08gx3BUcurW7+3Y30esB9kQdn
+/EvI5GTmUaGxhpSAftvlVL5JCw6ro2f5MFr8xtKIgFX5EpVeEDDIF0Mq19kgkTFq
+hKPA9joU4FFX4DR046n0IIonsH+uFig8p0n1TvqEWNX8CO754ppQauoxfr/uysxp
+rgFIGwVhUmzE0iDEnuleLTKZZ/Tmb3Kk7kApVhnAw5EChe1GzSEx/g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GeneralizedTimeCRLnextUpdateCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GeneralizedTimeCRLnextUpdateCACert.pem
new file mode 100644
index 0000000000..5b4e1a8184
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GeneralizedTimeCRLnextUpdateCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 4A AD A2 3C FC C5 21 08 24 A2 27 F2 BF FB F5 69 7E FA DD 72
+ friendlyName: GeneralizedTime CRL nextUpdate CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=GenerizedTime CRL nextUpdate CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIBEDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowWDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExKDAmBgNVBAMT
+H0dlbmVyaXplZFRpbWUgQ1JMIG5leHRVcGRhdGUgQ0EwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDIYwPTkYLo2i4nGu322ECa0tqWdZ8/nED3T6b9CkeI
+qHuEoNkfyqjF5BUs0WdomqKXQtJ3UB0MOX0E5j0QUBaU/Hlg8/JQw7v1E44AeNFQ
+nAaQIXzIppIPl9DXe1UZebGRW2DzYS5sBhtxqpJ9xsdcK5oAUKETy/SoBNL7k9r9
+d5vdC0Au1b0W++GhavoJvgPDaoiYNZB2Mm8D4Q/KlR6WpWkOK4PVxFpOdteyJOIP
+6Iw17x6g7WKiBg3NhJnKjmACxPjZLJSqSocyFRRGGLiHd5/drpO8zPysx52IklDz
+dYm2VWvGTqPUJYzTGExj3ZJfOReyHnBDr3aOkRT/+503AgMBAAGjfDB6MB8GA1Ud
+IwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBR+KnXvDDbHS+cg
+2X9hSEeOEoMaLDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
+ATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKpBfr1XfvGm
+jFyTY4aoS/B9PFwiKgDbh0QVQ98D5vH/1kEsz45DwjaIbhiPXQd4pa/y+om6j/Vj
+dNrbxhUTKGsl/HHQN0kUDK8h2HbNEzgaRSiaENVcCef8N8HzoljsF+M1CglctyaP
+j4b2oFcqoJDezN1Bcmvwte0WmQ8zEhIh4gwzhmoMcSlV0cOoZtB66JRou28Z8FeD
+q5ns/Q+C/fOlFv19RuzhLhps9l4LylzzBx72fUdAGzeyvsVxJCG6if/jBG+DB1Ty
+hqKBozIY/MncXochP7Pkkixx43pomL942n5eLmflhJS9g/Yl0tutw7EtjTDmURCa
+TpyqzihsbBQ=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4A AD A2 3C FC C5 21 08 24 A2 27 F2 BF FB F5 69 7E FA DD 72
+ friendlyName: GeneralizedTime CRL nextUpdate CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,82A93BC67947ED12
+
+TwDHTK6R5L4AYOO4XVPJjzV+CvgWSREM7UgQDzniSlI/Ll4jLylVXELbgrbfChDl
+tpVy01j3pzzXAdLLyJlafT/LMOzO6XkC+IBPEtK0OmkTZy74yy9qF1/s0Rcn5y4x
+0OcvUvKiB5BdmNYwsWVIPxIewExuXJXFpiUzAsSKfVQGfrBHI87QvXfLv6ozTlcX
+YeTAF+7yvQjkYYi7ibO9+Tc2VNlUNRsx86EnMjN8osqQYG4cUnpYeYGDhdeTd3nh
+gHXq0cuHYjMr4RWj7ZtDOLAxahDv1qRL6V/mfdWtXuiaMyN8f23s7GI8hDNSsxXA
+PlvE7tiSGlvCZNtRR7rXWo6tkZdvot+yn3XoRE8fwOm7gIAeD2GQDKaGr5B6XWG0
+dXFwZ10kIXeYEMSFOMWf17AT1cXl0JyfFLCpzPXuWPBgeMeuESrOm+f51pgbYMJL
+7iRwAWppAdQXCNcXSaAs4XCHOm89tEFT6uNUVwatzdMpYwWe0lE+W+pImWcH8/rp
+Mcn5j8mL50KDH3nKjLisj4nSu8t/A1mUfspLsz3GymnTsPO7pRhFhl92nQp+GGSK
+kNFCEYkFTk02eJE6XhGVP9+0pdG7tK1aGlnymQkqDTvhYID1dxIGGIg7pb1ZQy2Z
+zc9w9ka/bJsVTxt+v3ey8r6K3oqM7chOkOQOK/7HXHK/NSoejWoT4Wne8GxDIWbY
+ok63wZ2bLxumA2Odg3kzNSB/pvwzhK4GMJ1ETuFsAQJv4zkxUBf1+2P9g2i6OKOD
+P1sY3VjkbuSsRHUC/qxGsM7sMLjDmSKSJYcf/0vnJbAEG1Qo+r1g+wO7nFnRw50m
+/3sRYQtmgjP78ikN2fLedqzJluF/xj44beluU2mCoHsDAd4z5szK2YlHrTf8Wib9
+0Aef1QI7leym+/8meKpkL2HxWb1O4FnUJelmJIxgTT1pMZ9pYn5U2TMNIN+Zt5Yo
+Z1KfZN+4BuUc1v3jsZ/WuRI+zoRer36iCf7OwwvjOE6uX/4UZHVNRX0EhDEf5+Xt
+fVjeT3NE+6Y/E2kYHT7mnHOTL7wNEvL1FRyt2Ii9161VIP4BZTA/pc/1MTuwN6O/
+rCLM4q08VucXxc10fW6y0HfMci1XK3sw7VhQtxEjBlZk4fS8aUPm+QPKvHfn1h8M
+8H21FWaFDzuDPBQutOdjE8SZPejQinPAfYkYWpynBrmio+1gv1F0NBUcjYbSVZwO
+tYMTu8/7tfcT3zhsBblP+g9CGetVxw9eDrRTQF7+K/nCgToPTCg5znHMZ1j8N59X
+GwS/YsGM2DNrW8aldQ5nJxRS+aEGwlcHfqLc1CXv1uHkUxBUMwqm8aoGF2hIGGJ/
+62l06ZzkirqlJtxMxAZ8MOz0v05bqkvggVoafiNQBgZLg/rMO8KNRIYckszQOwLK
+L1UOupVEgPtrQvmjw16yuUbTDk5Q/cBuB4FytxmPD29RiBYVkk3bn8/oum7PRm1V
+TJtWPmsZf9kymTmHZaYarR3G5DgVFM7sdEDGtCUtGHwc3CtToHg6dmMLmU8Ap7bw
+UfjUmU25Ys9rt/j3QTNMfM6hf2tVZyguLPqD4+NIjzfd+MJ7i10eBdZhMd3gpaUa
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodCACert.pem
new file mode 100644
index 0000000000..ac9006fab1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 6F 49 77 95 33 D5 65 E8 B7 C1 06 25 03 EA B4 14 92 C3 8E 4D
+ friendlyName: Good CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Good CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowQDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEDAOBgNVBAMT
+B0dvb2QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQWJpHYo37
+Xfb7oJSPe+WvfTlzIG21WQ7MyMbGtK/m8mejCzR6c+f/pJhEH/OcDSMsXq8h5kXa
+BGqWK+vSwD/Pzp5OYGptXmGPcthDtAwlrafkGOS4GqIJ8+k9XGKs+vQUXJKsOk47
+RuzD6PZupq4s16xaLVqYbUC26UcY08GpnoLNHJZS/EmXw1ZZ3d4YZjNlpIpWFNHn
+UGmdiGKXUPX/9H0fVjIAaQwjnGAbpgyCumWgzIwPpX+ElFOUr3z7BoVnFKhIXze+
+VmQGSWxZxvWDUN90Ul0tLEpLgk3OVxUB4VUGuf15OJOpgo1xibINPmWt14Vda2N9
+yrNKloJGZNqLAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZ
+XahmMB0GA1UdDgQWBBRYAYQkG7wrUpRKPaUQchRR9a86yTAOBgNVHQ8BAf8EBAMC
+AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggEBADWHlxbmdTXNwBL/llwhQqwnazK7CC2WsXBBqgNPWj7m
+tvQ+aLG8/50Qc2Sun7o2VnwF9D18UUe8Gj3uPUYH+oSI1vDdyKcjmMbKRU4rk0eo
+3UHNDXwqIVc9CQS9smyV+x1HCwL4TTrq+LXLKx/qVij0Yqk+UJfAtrg2jnYKXsCu
+FMBQQnWCGrwa1g1TphRp/RmYHnMynYFmZrXtzFz+U9XEA7C+gPq4kqDI/iVfIT1s
+6lBtdB50lrDVwl2oYfAvW/6sC2se2QleZidUmrziVNP4oEeXINokU6T6p//HM1FG
+QYw2jOvpKcKtWCSAnegEbgsGYzATKjmPJPJ0npHFqzM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6F 49 77 95 33 D5 65 E8 B7 C1 06 25 03 EA B4 14 92 C3 8E 4D
+ friendlyName: Good CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A56D1AC2450522CA
+
+ie3dH3qeOIyFqScl7j3cb0iu+A+OWH0vEz1BO1dVcqv/APWWvSbNl4zsBoFdeIHn
+SGSDnSskPpBgH0ca25h7xo3jOfxxAVoA7lCGT1fNlFtxCNaztHSP31Dyyn6ZpXY1
+OMSllMqNfH0aateQFl8aE+0TPg8oUq2wS0axrWMU0qQe/TOxuliDTfXskJxp7Jag
+jk8sp5PoZ2qmlO7fhvbWL6jljFdoTYeJGCHGEkc57FpD0gE6PVfJ+hZ9DYwpz//5
+yiONS1IjuY3b5BB53/cZ5WerPNZoHpGmAq4FsrP19IAXz9GdRvTlfNelBh8lwhoU
+T/YLB90JRegpbcFzzVCenD7NvXk/0Tk6qwP6JfED+1755HnknP8M1E26uFZYKFLf
+N7KCKEdZ+cim0EYH5cJyeHk3dD1laBdaxz1bK1n2Vle4Ymps1xpyj1YKAhIjEl3s
+guJg2TRDL2t056AhuXrk6J0qzO8Zj17KVq2RMXKqIGLJqi3ggfin52hL1n1idkoR
+IRj9Oo9TN8/qxt6i7xXr9Hmt4oyrJE1xfoRofwgNNM8N8Ku3Q67g4Ky2iAI6SGgU
+aqPCCPdrEIh+bQyklS6yOCtHb4S477sPr3R7raypUmrD4zqczA8sE56OCnOyW69C
+Y3JKGcfOAL3v3e8YehGmgtpMRitAIDQEIYyvBr+Bup8lNyEF4PZF4zdeuDmuk1ga
+BtPKyz6VxCoK3lLTyuky8SqL/SaAVWpazrZpbMlv8XDUIbZOcRlaAhowyyW9MSKg
+j1jJ4u3zkqUL6nJIUcjqVTKWPJC4f10LcHa63SGYu6IWK6YKbtKKXKOpuOc/HVUt
+3YStOhVdB2OJZvPGqp0xVo9alhjQrHnIQ/CAkfOWt3x5VneHw1cli4PJAzlzs11L
+isLtJTIlPSxCK1BIWH7KbSMUj3TWQYzanvomOiLqNdE+HH8EbusylOUhJilCj9tO
+lcxHwwRu5lhoYvnlDLy9ulocCsPpiNzVyZsI/efRXf1NAcjASVSO8S9KBFw27kqV
+/jKHME01NPM4sFZmbnbcH9HoNk+XBhxNcsEnIhh7CKcf0QH6M2x3eTKyomHwB3G0
+MZxp0TtlgB2ynGsDgnWkSAduKZdDruGauUvj3ykT6ErYkK/nrXPZspRlrYaoFiHt
+n++sACgyrhDY5EyZrx8kiBjvdoTpXvG2jD2tPkj7VO5jYP9kmfwya+VYXI3pm2zp
+qIDgP3Rj8ZwmMuZJbSgwfjEJ2wBGOIAoDWYlVaJ+CRXe5/z6NPSjgOheOATOXZJJ
+3+HCe+8V79k6W+pWlA0lIPYmHvpTZvvGgpEB8DEFqvVCYuxh8TNxUREGi4vzUf0/
+/7T21PeCuTUzUDLMxV3a5C7Y88G2DxiupE3xD5SnQ0Yue51RUurVEGTD4dIuPSR9
+T8luhGHJon1BtsYDHPKRqqO12tIEZCVOHOkPcIVjxuQQtV00/rAFiIN7x4Z/Y7bH
+yqr/dRb+t0l0crgk8GlW5ReLokplkaApD58ypueken9PifDbfehz/yChLA/7SlFY
+8BJC7dF3t6lQSw9BXZmgP5Ukx7Wqqjn4bOBi5WYan7MZxD02Ovnpfg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCACert.pem
new file mode 100644
index 0000000000..c169547ead
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: CF B2 F3 BA B8 E9 70 C8 5A B2 DA A5 F8 DE 28 23 A2 59 BE 41
+ friendlyName: Good subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Good subCA
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBETANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMEMxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRMwEQYDVQQDEwpHb29k
+IHN1YkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsg6YlsgUI+Jx
+eULQ+eIB+57x/d39rz5zlcqfjzxk95+il+BC1o3VuwtIIxYMSNmi/5GvBuGLtjA0
+/XLCvM9GnONzZhmBUGU6voomA7W/WFZAqi7cDNEEzT9E7oJAoiQBNXPXngmJX8OL
+G9yLMOTolFlLoUvmAoDGryln42gYcYXdJMoWCq+JkAaxs4tVCl+OkAfLRM7yh/IZ
+rhjfeQpMcy01e+Oku2AqdJTQSDjDBrvI21+rB3LnjJvWbpm7NbJL35LmOc/kd2YP
+yFw4vJ0uFdn95lKEuM6HY/PtkJNr36/qwJ0ixntXPCyYLyDSFqaSa+9LGbcJrp6y
+RoCD4hcZOwIDAQABo4GLMIGIMB8GA1UdIwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1
+rzrJMB0GA1UdDgQWBBQyByyedF0tXSm7sXqNOxVStH1CeDAOBgNVHQ8BAf8EBAMC
+AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDAYD
+VR0kBAUwA4ABADANBgkqhkiG9w0BAQsFAAOCAQEAcX2vRsH1O1HQsB/7Jlf+ov4p
+fIwfT5PAvv+p4bo+wWcumPIC1DjUk8xnOQUz3RkhQyqTbE+1OGuA1fjO0VJZ7Yev
+KlO6MHkMYT4N5mge2ZuxMW+35ohZ23DHEHGk174QY6V8l4ICau2s1/SRajFqfRmY
+3s8gZFo0UBX0KIcmXSu0YHfaHWXnq7bs8kCODW0qMQnlpsUtbwdlPn5jt1kbMnRk
+rKzjruehXGm7gXC2QlHgH/MfJgpawne/n0DwPBVMs/KVuR/HRadunSuGf5Vy/rm6
+kZ8Lnu8+sk3pfWXdwEK2tWArcVUv3wh6jROOasEQC1Ah3H0iXv/ETCv3BnBHFQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CF B2 F3 BA B8 E9 70 C8 5A B2 DA A5 F8 DE 28 23 A2 59 BE 41
+ friendlyName: Good subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0C57A135D4BC7FE7
+
+MudOD7QTH7R0S0CeaqyAAHnkZQhrmWUqA+ZRYQLsN48JP/xaCrJ0yn8dcKpPxCr/
+Qv9TCnMStiRu4wRBqVSx1yIrIkEnWNFEXntzRM2+I486+kpXO038R9tg0U8Is9hl
+A++U5DM5+W07bhlJ5BRbwmBSXhqIqWozjOclAw4bTpkQEiiJFBgwo7ZBxZW0pDWq
+cldBvQvswXPkn42XBNKKebz+cAQENWqGUuz8GEx59UjUVg5Bj6GFknUSc6q41pdF
+dQw5acMtkHQwY7kvMBiy26Upx/vuZwlkPZxdf4C8jBwg9r/dCtHcQRhjZV70fiax
+SAwZbPwmf9cMweSrKPZ1WmG1fTqKW9zPd+tEsPTQTeri2zS70s6EsqwIYIZIifGI
+P1mS+LZ9cUXHfaQT9R9WjLM+mPZjzSkeEltx/30e9L2/UvE6/cYXYeTiKmusxD8b
+nb1ZQGhoqf3efij0+pfvCp709156LGyLe/g6Xg5SgpijQfTQkFfuXtk8cyHpa4/n
+9/JDAClHTa4sRo3uii30Y0Gvcu2bzG5McPmhjRQiIsHrEKq8M3f2h8VMeAktEwiO
+cc9FQy4ODUlO3TQ5CwUsTSBUhF/SvHP3e0jMpgEj+l88bxIyfVLz5grnbwTm3BHA
+4sjm4cCCae/OdRb6kqtyrKdFXRaiAfTX9d6gdJwrQPsaeW9bjeMJDHviMkwJ13Jx
+YBeaU9VOi/sf0vxgnWDndRcLQzKwDeGwH+LlNIur94QcKv98X4wpFJ9CrpDpap0W
+wHnWit/2dNWkbL8GeAsCnLhx5blaPY/TvAxnuUKgZ9o97MEUf2gBDhg/buHA8YGi
+c9eg5XWtwrfny7/HWRYtdnrG0eqY1uhBKeFCNz7sG5IY6vT0RHadOlTFzmFAmHp7
+8UG01hUHnMZKFPVTb19PQw8ZgmjmnIAhhwXvrVjddFtqqOjIkIg/Vfzyjl6aE4UN
+jPzc8j24p78EYqo+6gqT73Mci4x3wSjlYNQRVCKDMOQ6fhWV/TRe6jEpykRLdTJb
+B9oeRIbwIH90VcbTarhW5MqRSgpPi8dNc5XkrYlqXzJjghQGEnnjbHYYUvJkbNfk
+08XVP1SIDk212veafCGou78BzCUM1NXyQwy9zcKlb02/F7KYItaPQ99oyKxOk0h3
+/1iNUdesBBKfyowG6BOpD/aknUxVJVehKutmDTirbEMcIBWyu/7ehp7J1+GhmtTC
+CxhgoWtqozHDTf+O0ZHk9cYb0/SzveAvziJOuKzAP0cEW4+VWD+JSj6E/B5h0AGl
+Fr6ROjVTNFDZRdAPGisW79klZZuiqllWgwLTVOnSuFrwn+BHsYk9XuYBWBTXxDfN
+424SLBEHpWNcad8syLz5bpx9EOLrE2llWwXlYc/3DjN+bOFzkRrapZwHtUKjLIZ+
+Q0HF/rwYTaC5HiFuznGj98yhFlZ6r7pMSZtSs6e4ZDWe26B6WiGkFw3PIOXzwKNM
+4NrG6c1x8ERwKA1tI7bn+OGhthjj9oHVFBGnIesR/F86iU4pq9kLlcNTTf9IVSFh
+h3fgE5MREQNeJ2VxNmoNwEc/qYBfejVGA/fLsi85FJoJ39JTqbpAQTDo2o+1fn0a
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCAPanyPolicyMapping1to2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCAPanyPolicyMapping1to2CACert.pem
new file mode 100644
index 0000000000..a06c938cbc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/GoodsubCAPanyPolicyMapping1to2CACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 8B 5F BB 21 90 3F 65 D3 30 D6 81 F7 76 B1 A6 AC 31 5D 51 42
+ friendlyName: Good subCA PanyPolicy Mapping 1to2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Good subCA PanyPolicy Mapping 1to2
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDxDCCAqygAwIBAgIBFjANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMFsxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSswKQYDVQQDEyJHb29k
+IHN1YkNBIFBhbnlQb2xpY3kgTWFwcGluZyAxdG8yMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAyHIxLkjNU7QX3AYrkULGwUqy03uLcvbUEHQInt9Bp/Pg
+XVX+CqX7DX4nF+BumfO3NZ1vgPO7fYrpw2igH+2wgB/eebl5xHhGzurjNNKJf1Rj
+ikk0VDg7HVHpEoFZO+LQj+GVNj42mkrjEF9zhk8Gz1+K7I+MsdNN4qqJsavkO99s
+ZKh8tuleFRUakUSdMDA8LrJbQgsfvVgrO2/AYiIwPiLbSRDqhNse3Hg4/+c9rQ5f
+AxUBaW6j5gyNDbo3x9Zv4frFmtKqutRSzCHTfPXPsPduRozkQ9klYGOw2BDxiWfj
+QTJYTESOFXwamS5hui8Y8J4Vunngk6WFtse3+VSTQQIDAQABo4GtMIGqMB8GA1Ud
+IwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJMB0GA1UdDgQWBBRbc3mZ464G04qm
+M04UeOSgHbHkyTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAMBgNV
+HSQEBTADgAEAMBEGA1UdIAQKMAgwBgYEVR0gADAmBgNVHSEBAf8EHDAaMBgGCmCG
+SAFlAwIBMAEGCmCGSAFlAwIBMAIwDQYJKoZIhvcNAQELBQADggEBACIjsluMNLOx
+owudQB61hn4d2AhLpSGzbgqU0PE7p/666w49TrJ66XGuIq0c+z/Xtl8mdGQ/lz2Q
+CZqGNX0rb5NdjMV1MNJtEaiied89eI9sLBwbvu0cFAXeW6EYjyRCaQwh8/kn3K/b
+Wvr1Tnj9SmBfyGaPoTZDpQ60rE2mrDL0CbKGnp4H/jIYtHnItuRe+ETOvkSiF0qG
+X382kqIBHKji6xTF7HNHQr+C86OzdU0hffbCf38gt3LwUYn8MOKdInt1UEmKwG8W
+1kqf3Y/IaGhhfBNEN8yNaJFNr+Bjj0blSkuqtt53jxHjXrZ9NPVmE6A7IAIx8av/
+u7BUc8H7ALE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8B 5F BB 21 90 3F 65 D3 30 D6 81 F7 76 B1 A6 AC 31 5D 51 42
+ friendlyName: Good subCA PanyPolicy Mapping 1to2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0C5018292BD2605F
+
+M3Ol5bfO74yfUMcETlL+y/qZXK6sPzgX7ae0iWbHucn1l9UGwfDbdq9GMhjdXoeH
+LcZhgBNNhQ9uqABdmHnULn/0oot9BntYDLtj5j2TAK1a8HHf0sAhNuugpEcSuN1Q
+m6ewmF2HKpFBE0QIxn52GOussAQkwqQ1TFpCBK39E3pUf23U1KZxtZnTWMuIxX6q
+TwrjKb20AAzLIkja0dlFluQzQyRLDbUo17yXjoiYMzqUtbQekvNcxThtH6xnAsjv
+ItIRWOiSmoMoNwTHMuuhhKOacYpHpdofbfxeLphvXRBGnwGuG6r4+mepxDTKUa7D
+DiFLRT95vPfGCd7SiOEK8IadIjIMDEPLoW1eTVKMgESCxaULDM9O1X/qLq/17wDD
++a+9/+jOhfypJ+tb0qVlfRY/uzrwsYqepKcg5OwhWRc/c9moSv6GNbDrA5QJRV/r
+I0sQ0KzK8AkapeQXDhkM5Bmr21HVtaQtTSozf5xIhninpRSIQMfxDPHRqgKgP9xH
+tqG8bBFSygzlmHR7U9YBvm5G0tNXhyIyumEMj3ljpJqbxe08+feIiZqv17HwEhVE
+/N+J1Ou+dk5p3CwUH0Zs61NY3W90TwVut7L0nF30VaGg4FHFKmUNZIZR4zxcgBec
+Wyich+jHlowm91DQeazmTec6EJKCyPlLGOP6p0ez2qX3+Qnu4zrFBmFkpqYdpbOp
+maCnsvzrYn3J5gC0yp7UhPFduDLi7oSFlNQs6GYVKjGjVhghx+un2mb+SwPboC1f
+6ok3Y5q3POY2WL/ox4qzToppMjulYiXJwCPv1IqxJGc4xyOplJfJSvCjJOg1StT+
+8+MjWcBMrjnWDB7YO/ZXFfnecQVlskbFG2u3TCjpMMdkyIZTTBgUZAm1dy3TJM1x
+EczaWDipUsgrs9p6Ip9UHwytclLk3Sl2Xf/V260myoWj6Nfv8QpXOzYH4lID3kp9
+tMw8wXUpZDXQAB6VvyAgrJX6s/9jCGDZn6WXvahaRN7eEyvMT1AbTgKmPzbjZOO9
+/JR3dIpAdeUHjfhrfec+x3qo3JZFKWn+2M2z8TQfng6jTs+o9+Tzh3xsclAO8lB8
+08T/Mp84hSZJ2sYHpLFi9qpmQCdMOJ209FIoP/q6yqlivU2ZEcWdoWIzuNw4s+6R
+29KQ8+nDm89nlsBR1jgJUJO6nX2IiLjQSr9TEUdcpTwvlKGz6lkr+WuvyfzgV4fm
+5sBczXMHmudkV14TWfHEUH2wb5TzLk+6EbFLb20y7knwu7TIaw9TAtXA6wgsFCkg
+1tcXzWnt70cZHOOVWHc3V3mlUx6lmWgakLwS8NaQp5MpqLucS+YuZAbyBvKjWOW2
+IEQyuKKRC9iNCWzg6D1MvBF9A0bZ6iIu4mNj6NhMEul5/dmTKQSy5pCo6mv36kYx
+NWaZsie3Dwqk63op5VPBoz9xkGzTcUDPr3kqQ/kwZPMsdx6+aasyWY6w9f511dDr
+ml08wn/zF72P00Go2Jl7PCdwJIeK0Ggu+4nMJSrTp8jn2wKt6NREjY1tA/C/8MCu
+ivdfNGnhMjBwfkO4nodwc2+tyIikYP1+LCXHGgsxCbB4T6KNsNmyGpgKOGuuvkyn
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5.pem
deleted file mode 100644
index f8cfbfdebc..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Bad CRL Issuer Name CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfDCCAeWgAwIBAgIBCTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWQmFkIENSTCBJ
-c3N1ZXIgTmFtZSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8VTZxnGg
-pV60/E3F2RBR9N0VgI/w8ZdVENnRoqcpmY276I2t0UaRM95qNori4u/6Rb6RI6Jy
-BL5dPaJuS4hoVphnqLjMMF+huDF61ov49vcOtMo9Qw7NJYgeoINC4KcUrxvn5O33
-IjvyvGkMbrzczslZh1IaGrquWlS9DQDv3jECAwEAAaN8MHowHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFMg02+C1YxZR0VCkMtLFWfhD
-jOBnMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCYg+l+IX369jmWSOMWB2Gw
-tuancmzEylYvy1g4di3sVNNOTRaST6hG6M0QkyVJDpr5wYwDCAu1me4CkJlaRHT9
-RZB8rW2LK9ydBJG5peFQa8QPQv9phrb4Hc7/2xjr0Eq6sUAQOBsCL09IY5pi2jxH
-o4m0vETRDlhl/Lqsc3dLTQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Bad CRL Issuer Name EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=Bad CRL Issuer Name CA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFkJhZCBDUkwgSXNz
-dWVyIE5hbWUgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBkMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxOTA3BgNVBAMT
-MEludmFsaWQgQmFkIENSTCBJc3N1ZXIgTmFtZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0
-NTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmWwjDb3FCLH56CnXApSXwVHB
-KUEdYLsDL5afA0uwYq3CutM9nFTfpI4wfWoh8z8rbcyzMhNU/b90XnkcJeUlLe4R
-GVC87g/Oh67ONY431E5nS0t2mU3gA5A+QJwCJ5GgkoRJy4aZS7IhIVayya97aITa
-eeInMge1hpOIbhG4RWMCAwEAAaNrMGkwHwYDVR0jBBgwFoAUyDTb4LVjFlHRUKQy
-0sVZ+EOM4GcwHQYDVR0OBBYEFLIo4xfziwpQ8zkzEpaYHC7RAmffMA4GA1UdDwEB
-/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQAD
-gYEAYRbr0XdXa3sve8krgu8sJ/Dj90/LJexPg4kRViyO7965tP3sBCNUAIO1Q8QW
-n27WeL4IjVXDSrspE/72yM2b8MNWJ4phd+PJMkQb+ioBbC8qPrNvnesSKPbqNcDR
-qLz/G2oPMHBWA5zuzG1O2ecxU1MLUV3tY4QxY1oNRuMunPo=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Incorrect CRL Issuer Name
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C8:34:DB:E0:B5:63:16:51:D1:50:A4:32:D2:C5:59:F8:43:8C:E0:67
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2a:95:96:bc:9d:a1:bc:e9:8b:10:db:0c:3a:19:c0:f6:b3:bc:
- a0:15:ef:97:6c:c5:83:6b:e6:ee:c3:8b:fa:54:c7:86:7b:ba:
- e8:73:c0:9d:d6:e5:1a:90:74:4c:8c:71:bf:ce:81:e7:36:df:
- 95:4a:d8:6a:71:e6:16:6a:20:ab:9b:7b:de:eb:c6:ec:2e:83:
- e9:0d:61:4f:62:df:3b:5f:02:28:98:01:04:5b:d7:19:18:1a:
- f9:18:63:83:62:2f:de:0b:9f:a8:5a:d4:8b:91:5b:94:cf:bf:
- 44:d8:18:71:89:fd:99:14:c9:92:7a:a0:6b:ed:15:13:5d:37:
- 91:fd
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGUluY29ycmVjdCBDUkwgSXNz
-dWVyIE5hbWUXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFMg02+C1YxZR0VCkMtLFWfhDjOBnMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBACqVlrydobzpixDbDDoZwPazvKAV75dsxYNr5u7Di/pUx4Z7uuhz
-wJ3W5RqQdEyMcb/Ogec235VK2Gpx5hZqIKube97rxuwug+kNYU9i3ztfAiiYAQRb
-1xkYGvkYY4NiL94Ln6ha1IuRW5TPv0TYGHGJ/ZkUyZJ6oGvtFRNdN5H9
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5EE.pem
new file mode 100644
index 0000000000..c3d5661683
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLIssuerNameTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 83 38 B9 B1 1E 8B 1A B1 01 EC 85 06 77 73 50 80 9E 77 8D 72
+ friendlyName: Invalid Bad CRL Issuer Name Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Bad CRL Issuer Name EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=Bad CRL Issuer Name CA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWQmFkIENS
+TCBJc3N1ZXIgTmFtZSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MGkxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MTkwNwYDVQQDEzBJbnZhbGlkIEJhZCBDUkwgSXNzdWVyIE5hbWUgRUUgQ2VydGlm
+aWNhdGUgVGVzdDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbUQc/
+aDfzozsGi/PMBuOvwbdh4u/eGd5PwWOqPgwARtSrxA+gRKdsLq/Gh9ySRhABGV+h
+92N/B4xPnilGJJt2SUULOZz65G2Jb8yUZrO2RSLXcGSzExmQL58GC8jQ13rPveDn
+tChy8oiRh1Q+Qswy1dIP/iya8fhceDjt6YhP35Du/CzDaPIEdxlMYfnsiM5PZukl
+Yc/0+bg/T59xvjypk1oAOxVdGngaXEpkpwDyKoTdXMATrWWIIoA+NgmsJfTRlwes
+l/Mzy2pJxRRql9tW8yteW78ddNBIMHeSfJkqcwJ9y3rdW6CC4qE2ih+5O119FMTU
+hlkdv0bKseMyrb8zAgMBAAGjazBpMB8GA1UdIwQYMBaAFBFy8jVdBNUOSiAHB0Eo
+/ZRwABxxMB0GA1UdDgQWBBTJMGp5bfvpKIG6aOzEVAK6YN1WYzAOBgNVHQ8BAf8E
+BAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IB
+AQCNUhve7sX9MgDZzE0LREXi85Qx+HDApJzt7BZ0n7jjN+mKBR7z3mGqfvIWd+nd
+yEtDj2G5+PEd59nPp/tlNGwcKHuD2ht/83jX2tjrNZE1XizGyPS6m7vI07OiVhNi
+8CODBlCX5jimwwqH6i+2WNFI/3xQZwqjx//q5izI9TMryIDbX8mwWGYtDd9O04u5
+3Ey1oZdm7fxE9QJ5Hsg3zOGHKNVr0JFlIHx2yaub9F4CUEHVx56rAdY/13v89iUD
+yD3KEZHOxuGRLD1nKvK4rU7vEmYOXRF1z2iobzxA9VbBuybrsJwZyaCZRZ9C09XU
+kw1e5M/h7zZuDUtLKIyzA0pJ
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 83 38 B9 B1 1E 8B 1A B1 01 EC 85 06 77 73 50 80 9E 77 8D 72
+ friendlyName: Invalid Bad CRL Issuer Name Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,619AE424395184AF
+
+fidkvMzQmt7seLs9JoKXAFeoeWyIs/Dn0wWqjju6InvbFGt5e9dBqJOHqXOiR2Ad
+hSGbVkcvXRyUokJudi60t1cHjXd37l/8tK1f0Cji6EUUMUekG08BlF4jrsA2R3Pb
+5Q2Ya9uhNO+2FDf1dYk7+Tyvg2SOUPtyN3xS8S54+Ao6761jSy9yGHm4KOws8ViQ
+c0njkI8erjzYo/H9TPgOtW48JHBxa/GA5gBWFF/2z/AOIhSLtOMeIiJEcqiENlnm
+pOzHXp+UnCDdVb+xEO5lYKyNA9h2BPhZ6x9SA5VXjNK+S+rC6g0Vj6bgX58JfAg3
+DoFKy+RpkYBB4MXskmU8+SWVXrXmcd3JTZS2dN+pkFRxEvdR+Xj6Wi7XIpZIY9Dw
+BL/YNX5+ruefdisDncgR4WdDy0rWuKnJvFl8FyE3M3cQl+LBUwxwf46TotGcIHwj
+Lb43hD0p1xPSPwcElVi0iJIZClVEDM4jNXv0rYk0fD1GUD5I3f3jTILxlTrIjWcr
+y0I3c74aRgRBp4B+Wh6Vh8OzHDVZeko4e8WCWT9QnknQw0b56/yKQErymhT5xCSe
+ZxLZ+JsveW5s6u8ySC2iScdRh/TTHag8Y2y1aIkc4iZRCFcLi/Udh/EuZ9unNHOE
+4lSEMD5gwHaeb+y8iVdwHOVIdelp0RceTmHiyzd/OlDCZOKt2Ha2TasdVdK1g43e
+MNqvW77Lz4isgIuROIZmn8vwBoprFXXSPZBnjDvEtichw6i3kRJbLtI60CkVK7dx
+P5Ffx7IhwOIFoxfxzMxOaxB2FknnciEoUpAyTUOqI007BVuwx+mQk6Anzh2/Osc6
+AvVf8SvuufJYAaTYovAmJlwFpTETkwUui6zH2Qt1k3x5njTN2EXscUJDLAJ8PWGW
+QNj3YlKdQdT5bfQGRolmQN/Aki5BhjhNamGzN66T5Bi+MjTmaK9o2kz+ed1sdGUO
+M9g7RPJ390RzTjMf2g+pagVw6Q5jzNFmgKn/3QPnhREeFZXUby2KkrENqf5Gv34C
+s10//lqT2ln0Qx6OZjYn/ydWt0fmdn3msDYzMn0UcSxSRqHZgf5Z/J7GAPeUtxzE
+1sTo/qx5gkZ7KV+HAkODoGOjUWDY56aVTzNvukzZ7g/HoB+71m06ce01hgxEhduu
+eDdVoWlRaV3MWATYKGsEO7G2dOP8oouzYYXxip8TZClYy0QJkfSxrHx+eoYDU16M
+SxGrtYkSRf9SvBTAjpcI1IYJwCmLOXbyJldhNDz/XgXjE7VNjwpucy4n/NSkGA98
++cE4oG8FKPvU1rlAZP8uSi+jW64yOykMYrGyCRfe72Gc0WrDp/TPVoJpFiDulLJt
+06XV+LA1A7Iv+aOgej4NMYvQDHUuDlQGgTPeU6aWSgiFQZkMWyxt1r63MTC0qeK6
+6buWTP/teEyzDyJlTb2dTwsUJaK9BwT6Cm4M0MW75zlQw0lnR4VWwKHCnAn1OQka
+ojcVVmSs2ixDCAB8fOBrcqRZIEw427lb8rJyHhvqCdMyje+D3s/T87vTtPaYaaYV
+SAF6BFFcV+3bAymDNnVB01QLIOlQbucjE/M49Y+J+ZS1gke6WFRGPdV4SvcHtYaR
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4.pem
deleted file mode 100644
index 6fd7c1dc31..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Bad CRL Signature CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBCDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUQmFkIENSTCBT
-aWduYXR1cmUgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJdogWv9CPXo
-9rQEcxwXXws6b/WT7R/AspFsq4aVO/l7puHNxGIQybx5jK5W55wqPtHa5PPGSpJA
-YkcuKVXL1ZqZh8A+VenvazNg0XoldwJZalTN0AwR3FprLL3cXYIwu8FFFERp8l/S
-YgHz8wHRlA37Ph4a7cU78oLWK0wziElzAgMBAAGjfDB6MB8GA1UdIwQYMBaAFPts
-1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBT7CxX9unvmOEiZWhVgVVCXqjZs
-QzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
-EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAmZ8+7Hn2elBnvNREi2gDIa3P
-POFc8RHEq6ajCkhgeJoQRygSFdfenhTKGtfvet/3j6hBZRHEVI2e8x5yiyBN/ZKV
-SAdRCjXTg99nJJtkkqDhifkO5uUaxfcgj2LFt9DI7/b/jZzlNSD8BXqcifbjAf1s
-IIlWmY0HVZgwucYLmC8=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Bad CRL Signature EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=Bad CRL Signature CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFEJhZCBDUkwgU2ln
-bmF0dXJlIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYjELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTcwNQYDVQQDEy5J
-bnZhbGlkIEJhZCBDUkwgU2lnbmF0dXJlIEVFIENlcnRpZmljYXRlIFRlc3Q0MIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQDbS7uYXT/RjXcp9qBIMFgzo5WJJA
-3/1rXCiA/BzowTDl87A4iGOmZ+LEkwpLarYI8mFzGmQAVIlJCn3KlTO4AuTWaMth
-VZPgVZ5gVxVHQbqdb2VZXHVJGYB/yn+PJrghL5uy+kv9qzocq/jUrEHcnvBTQ+iI
-8mutd/z8C/Qy9QIDAQABo2swaTAfBgNVHSMEGDAWgBT7CxX9unvmOEiZWhVgVVCX
-qjZsQzAdBgNVHQ4EFgQUK1L621YMk2XrXnaVZG9PC/61mSYwDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQA5
-Kis0tSW5S+c/zwTmKqh6DTRRISk2nn+KeQSUJdi6YXcuX3YIX/P4SxWNQ46dwKDl
-lNNDVR3u7fiwwYf9BxICorMqY2FhrdFOoGclO1mCpRuBMhmER7hWivrftdi7ekeE
-2aEHKWWnWwzU/qs6Z/6FK9waN4GviF8X+sqt/EHo+A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Bad CRL Signature CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:0B:15:FD:BA:7B:E6:38:48:99:5A:15:60:55:50:97:AA:36:6C:43
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 68:7d:ef:9b:2c:27:82:c2:3c:2f:16:6a:09:27:73:ac:90:da:
- 2e:66:07:a0:f4:c2:4e:4c:3a:52:02:f7:23:dc:52:f5:3e:2e:
- 94:29:22:b8:f4:f1:c7:44:85:5e:84:8a:6e:37:5c:84:16:5e:
- 70:b5:f5:13:81:8e:89:09:b6:48:0e:51:9c:15:94:21:f1:21:
- e6:38:14:50:a4:c3:85:4c:84:e9:eb:f6:b7:6a:a4:cc:12:02:
- a5:0f:42:af:9a:1c:d9:c0:4c:98:c3:1c:12:2e:f7:84:d8:fa:
- 24:4b:68:3c:20:c6:7c:60:78:d6:46:37:68:28:4f:81:c1:b7:
- 32:30
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFEJhZCBDUkwgU2lnbmF0dXJl
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBT7CxX9unvmOEiZWhVgVVCXqjZsQzAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQBofe+bLCeCwjwvFmoJJ3OskNouZgeg9MJOTDpSAvcj3FL1Pi6UKSK49PHH
-RIVehIpuN1yEFl5wtfUTgY6JCbZIDlGcFZQh8SHmOBRQpMOFTITp6/a3aqTMEgKl
-D0KvmhzZwEyYwxwSLveE2PokS2g8IMZ8YHjWRjdoKE+BwbcyMA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4EE.pem
new file mode 100644
index 0000000000..2ee07eb3f4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBadCRLSignatureTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1A DE BE 1C 7E 70 F5 E1 0E BA 55 EB 2D 41 E2 4C 7D F6 6A 8F
+ friendlyName: Invalid Bad CRL Signature Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Bad CRL Signature EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=Bad CRL Signature CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUQmFkIENS
+TCBTaWduYXR1cmUgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBn
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE3
+MDUGA1UEAxMuSW52YWxpZCBCYWQgQ1JMIFNpZ25hdHVyZSBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0NDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKoh2hBRa2n/
+4/sUJnItoF7DlFyPUGn2CSBjfW61rFCpa0UFPhjN18/5HPV2AvDSyfeVsQbaOqBN
+mGcN+3ClEaDM0MxDR373PtXwfZlqxBeyufsFrgskpV77KB0dwTPJBkFDDf5K8Z+d
+kRv6wf8L3TVQkWCZmqtBGyYpb+ciqjqlON79M+mX5rGy+95P49jqzq3Ufe7/frQ3
+twWzfLyvT16+X3erXinXrkMBOJqKvH9n0AmeV7H244Ekak/kyYjn8cMKCHptmpyO
+XXB2dhDrSSkFClVE6Qyk/ynFBPo29lq1ZBM4WeKI961/Sku3DL8cE9LgNvzRx448
+wM8vF++T9EUCAwEAAaNrMGkwHwYDVR0jBBgwFoAUMYs1jZ5EYTAU3ucLLhQZSCTb
++b0wHQYDVR0OBBYEFDFtEQEQ4iF+FFSg1ZEs2O0msQvFMA4GA1UdDwEB/wQEAwIE
+8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBACXx
+1TSmGPZscKlY2e9Zuqp5LP8ehTiXLtWOErouEeF9tfobMh+hOGruSmdtJv7tmqz7
+ePchR3c+ROsT51qEpOW+y7Hjv8opoRaWJdMJZ4zVGiH6wlaj9Iy1rrxFMnbRM2ZN
++md4SDJnKmMzbUf1H05qAuiCDiDleVkPycyIOLWInwEX+5cW9SOaeoiBnO0GmkBe
+RJPNV9rrTNpcq8cDoQh08xaaoKRPtIlxR14XP25SNfljdbCVZQXIoKHEsQV+UV27
+RVKCSqzZAv9W1nXeZX7rH+8kEKvQR8y5fMYi7Hi9zk3tqH53A/8QGPKrCqRJaw/+
+UAQA3LZBkaU9hpO5JAU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1A DE BE 1C 7E 70 F5 E1 0E BA 55 EB 2D 41 E2 4C 7D F6 6A 8F
+ friendlyName: Invalid Bad CRL Signature Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6CD186847B6D8CF0
+
+e+e0uY4ANLFnP1kBMLdAz6JO7+Tq5FRSVOAEOGNG8Sx3QgbEpLfgJ/MkMC6n3Fw/
+AqnQFZh7Edi0RsFAr0GWyOzcyz3fpUfMS1WtRpIgC7E5Cx6MK4iOQN3yUinvtKnI
+9qV1nHMw+UlvBV7mfODEBHOum3M4wXtgWcjDXGE3VrDqwxeYTqb2z/gMMFSUDRGZ
+2ZFYveiiIT8B2nGAxtTKTeG0Yv4BzRhArKLSMD0zJl+x3QM3PH7a5WhKS+b69uzy
+PaCxjdRzYsNsVNjnIhVFdnXtFJ3njDL6Shn5yCJkNWdoJk3wnG4FUuhR5FKCCEtO
+2mLRGcVXj6fonOy5KZ79GN7kp6N0L6EtUhZiO7Gn2Xp34EjfoXyCoGRKQsVr6Xmk
+vyaR+Ui+81ro1xGRpMGRyyFzovXFWTMSIvq6RDC3ru555/OCQ0HisCSDfxu/xAIQ
+VhAENI1Fmj5TJuzS39nZsDfNX+G9mkv0W8V5YNR2mZSEeurGWFOYEqxPNXEdZgci
+pMkjN8vVIv12pDds9YYqpJuexjCFLaS8ZS3ZU/55KBNY/U+/q9MuhKO49sdtNBxq
+5ffXYc2ybnHKDTcN9bzLgbBuqYP3bfGtgn+BSK2nxX24PRckFjj9h7QqSXot05mX
+Z9WdQMRs0vAsnhhEZXOjMhxusLeJIOssnXY2EuXt79Z/Sc4BEE7KFWQ+ZTgZ7kv2
+l/vJWlYBLcUrlbcgWdu5DgLau45fgWFfx7Z7R+cg5cB6W0ZVlE89+c8FRTh4v1UR
+rfG/k0QMIzP1CNMuc4rngEjVLpWn53jXlNM1ljeQynOYQTBZuCiwyXCJs59ZU3v+
+AYr129U2ooPpe24N+Nvu6qHnQ9V+jeHgoU4nbOD9/akhy68xukVaeDIDgezVD7oa
+BIAOziVFo37SHFC6Fbi0/JNQCoByhRbpUnHiG5PRsBO5OEY3Ud3irlhuPFofg27y
+QJ5qnl+qdlGbH0iBZrGXwiE7ZUjpEPPxR3+IaLSvj7k0l7zxOtK4JoHAa4njxXNC
+VAKdjrekp+6lbfJwZjrAVVSU2wuTQ5UFbdZLugfyHgWH7qb6BFePytfM69eD73b5
+ZaU4lWcTFaa+IEdqAZZG+DJ79jcYiynBHdOVOcLnRt+hKlo/NGY7nP46hytuEefh
+0ppwNMkXXWxNGVzfUKiWoKBUNpkMyRcPveQKJhBQpbNt/soCTkh0csH7CieRXQj8
+7LQMKC15St07nncPVsXYtcD9fPMh0aU576SdoYTW9sb0kTThV9evEAdS/NFervwJ
+yqBa/a5kCxhpi78LrfljTkfL2/9weS80UNj/4ebC/Et8uuES1WeUyDE7ELFqMoHg
+NBfBnsyu82KRRxU8BpEqZ05CX7VrZHHL9hGPIp9+7isSFyjx2t4PUZmab93CwI5z
+Psj+z+IsR2ZLA25ttpi3bOcnqKJ91okUBVJCaiR533Ss3Ar+/tl+ZRESSDhh8vbP
+Wqgd6YpXVOADF3F4tdRwPhwTSUM4mJ/0JFVNINOkONfMai/hEbHZfPh9XMfctspF
+XWXsaBMejr6WBE8wUYQ9tI68cQld2Y6tr+LyBYy04fglExIn9GmPYWsfEMoUipC0
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7.pem
deleted file mode 100644
index a70e68731c..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7.pem
+++ /dev/null
@@ -1,175 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBFTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEtMCsGA1UEAxMkQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCfjlwgIWm+Taynv+38GP1Yf2hDPMT5pcsPYlRaeFeg7Tsr/GhTZQKB
-qfO7h8J6JjoKD1m1BTcrdiHbRBnn183kxyhljulJLu87gOUt6LlTGTBFeaUhNNxv
-wpzF5uQ7xQcChTE7GF4kxt/oyehJFi9TGtnjdjlSi3LXG/xfQn81GwIDAQABo3ww
-ejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUScn8
-twM8Z20KAJOp5NalHpIftREwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABV8
-zJCN9czUhadFLy10H1usL1xGEcB8SRR3Row0a+Zmj8T9Se71hTgW7LfXQj3bCDJV
-3AyAd+WA4N0y0+eSRWRGNAcMrOeqNp1/Ki6iGNYceZ41Goudsc34StO7symFfatg
-hTr8/7eU6NXu2o9cDREBOJujBK/Uy52E4rx/Faxk
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Basic Self-Issued CRL Signing Key EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
------BEGIN CERTIFICATE-----
-MIICqzCCAhSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYt
-SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0
-MTkxNDU3MjBaMHIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmlj
-YXRlczFHMEUGA1UEAxM+SW52YWxpZCBCYXNpYyBTZWxmLUlzc3VlZCBDUkwgU2ln
-bmluZyBLZXkgRUUgQ2VydGlmaWNhdGUgVGVzdDcwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBANehtRiWYBhPipRRR0tIxuV4U49+DofUBRVQP5JDT79DtTbKaVOR
-HWgSi30ZrKSm3WkblfZoncF9ZMN/ocoqxeUNXwBqp8/wJYbE6js5YwBGTsfi3UfP
-s14vC1mU4ssE+ogwozLkXRcJGuFtJwNTZcEf43OkjdjLWiIH5DVhj9ZXAgMBAAGj
-azBpMB8GA1UdIwQYMBaAFEnJ/LcDPGdtCgCTqeTWpR6SH7URMB0GA1UdDgQWBBTa
-6ZIK1lgoOotgyyB2SLZbDxCDHDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAA/4ne7fgjMJuty5+P1V3QiH
-TxmpO+boz9+NO3Wc2Nj23sToATQqIcc6W1G3yKbN7uQEXtHgtPcIz5diAIJ8JNQl
-INBUxGlFASTWHNfnNJDgN7lwn4VjSAE7HzEKIJ3+HVTXI6+mdiCl/IYL9q02KSGi
-djAHT73bFgK6ydVH8Cal
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
------BEGIN CERTIFICATE-----
-MIIDGTCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYt
-SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0
-MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmlj
-YXRlczEtMCsGA1UEAxMkQmFzaWMgU2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5
-IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXGyrLR0BviK/81C9C/igI
-9zh+808dGICz2wS1Oh2CWCeYia4J/65Y7XBDRBW1TJbQLdrxt2289Lc/gc9+PW9j
-gwVpGRuYkFf+AwbMgLa1Ro5zqoIbD7WjTu7vgGdDvJmrSVLfSXavpeUBzp37Dsw6
-KzSHcBjPwGes7q3pjfhOMwIDAQABo4HyMIHvMB8GA1UdIwQYMBaAFEnJ/LcDPGdt
-CgCTqeTWpR6SH7URMB0GA1UdDgQWBBQPcsozQ6nEEVGrY9pEhw9hpPS+RzAOBgNV
-HQ8BAf8EBAMCAQIwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIGDBgNVHR8EfDB6
-MHigdqB0pHIwcDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMUUwQwYDVQQDEzxTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBCYXNpYyBTZWxm
-LUlzc3VlZCBDUkwgU2lnbmluZyBLZXkgQ0EwDQYJKoZIhvcNAQEFBQADgYEAjoyS
-h7zhrGkL40stundacKPqIEZ3HyWW0NQhD0wBhWslGAOvlCaf44kuTKggRY6r96sy
-4kWEjvfGu/r/dBgrFaCCGNv0ui5FfXu8WeZ4jvHg7wZbx5ATx5Jpumqbm0PcEYCr
-YnA6WBCstG0lohNV2ohM/wqRFmBB0WL1K+9IdfQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:0F:72:CA:33:43:A9:C4:11:51:AB:63:DA:44:87:0F:61:A4:F4:BE:47
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 5c:cd:8f:a3:3d:9e:64:f7:64:73:9c:2c:39:e2:e7:d7:0e:b8:
- 1c:3e:9b:1d:14:dc:98:c2:8e:5a:1f:e5:47:31:fd:7e:a7:d5:
- 9f:52:31:c8:10:f7:d0:a2:84:3f:77:c7:f1:ba:7e:24:62:ad:
- 05:ae:1c:7b:ff:f0:e2:ce:55:f5:27:d3:cc:24:7f:c8:1d:a6:
- b8:ce:42:05:e1:06:ec:1f:87:4c:d5:69:8d:78:59:d2:33:94:
- 1c:3b:27:68:80:3d:6f:3d:a6:c7:9f:2b:39:9f:d7:c3:83:eb:
- 77:bd:cc:7f:96:b3:ad:24:68:99:d1:1a:bf:05:1c:8c:3e:2a:
- 02:f8
------BEGIN X509 CRL-----
-MIIBdTCB3wIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYtSXNzdWVk
-IENSTCBTaWduaW5nIEtleSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjAiMCACAQMXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0j
-BBgwFoAUD3LKM0OpxBFRq2PaRIcPYaT0vkcwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAXM2Poz2eZPdkc5wsOeLn1w64HD6bHRTcmMKOWh/lRzH9fqfVn1Ix
-yBD30KKEP3fH8bp+JGKtBa4ce//w4s5V9SfTzCR/yB2muM5CBeEG7B+HTNVpjXhZ
-0jOUHDsnaIA9bz2mx58rOZ/Xw4Prd73Mf5azrSRomdEavwUcjD4qAvg=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:49:C9:FC:B7:03:3C:67:6D:0A:00:93:A9:E4:D6:A5:1E:92:1F:B5:11
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0x.v.t.r0p1.0...U....US1.0...U.
-..Test Certificates1E0C..U...<Self-Issued Cert DP for Basic Self-Issued CRL Signing Key CA
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2e:12:1f:54:36:68:73:b2:5c:f6:11:48:f1:d6:7a:bf:ce:1d:
- d9:21:7a:96:29:44:bc:83:26:d8:8c:f5:11:36:9a:f1:23:78:
- 57:00:8b:13:c6:74:57:4d:3d:ba:ee:d4:ac:d4:40:b1:d0:80:
- 91:f1:06:81:91:ba:a4:f8:1e:c7:6b:d6:20:3c:92:26:23:94:
- 80:33:df:c7:3b:ac:fc:94:ea:e8:3d:d0:37:c1:d5:e9:ba:53:
- 83:9e:26:ed:da:fb:10:0a:6e:d8:cd:d7:20:42:2c:d6:7d:18:
- 32:6b:75:2a:3c:51:03:dd:4d:a1:80:e6:d8:95:6a:2c:b0:b6:
- 72:31
------BEGIN X509 CRL-----
-MIIB2zCCAUQCAQEwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMS0wKwYDVQQDEyRCYXNpYyBTZWxmLUlzc3Vl
-ZCBDUkwgU2lnbmluZyBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFqggbcwgbQwHwYDVR0jBBgwFoAUScn8twM8Z20KAJOp5NalHpIftREwCgYDVR0U
-BAMCAQEwgYQGA1UdHAEB/wR6MHigdqB0pHIwcDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMUUwQwYDVQQDEzxTZWxmLUlzc3VlZCBDZXJ0
-IERQIGZvciBCYXNpYyBTZWxmLUlzc3VlZCBDUkwgU2lnbmluZyBLZXkgQ0EwDQYJ
-KoZIhvcNAQEFBQADgYEALhIfVDZoc7Jc9hFI8dZ6v84d2SF6lilEvIMm2Iz1ETaa
-8SN4VwCLE8Z0V009uu7UrNRAsdCAkfEGgZG6pPgex2vWIDySJiOUgDPfxzus/JTq
-6D3QN8HV6bpTg54m7dr7EApu2M3XIEIs1n0YMmt1KjxRA91NoYDm2JVqLLC2cjE=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.pem
new file mode 100644
index 0000000000..f5ae145d4c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E6 12 3F 89 00 F0 C6 9C 39 A2 C7 8F 9B 88 6B D5 E4 71 62 9F
+ friendlyName: Invalid Basic Self-Issued CRL Signing Key Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Basic Self-Issued CRL Signing Key EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued CRL Signing Key CA
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEtMCsGA1UEAxMkQmFzaWMg
+U2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMB4XDTEwMDEwMTA4MzAwMFoX
+DTMwMTIzMTA4MzAwMFowdzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2Vy
+dGlmaWNhdGVzIDIwMTExRzBFBgNVBAMTPkludmFsaWQgQmFzaWMgU2VsZi1Jc3N1
+ZWQgQ1JMIFNpZ25pbmcgS2V5IEVFIENlcnRpZmljYXRlIFRlc3Q3MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJ1Ncwjk9f7Jh7x49a+7BccpR9imE9kX
+WNxzQRvvBx/ps0H6O0u1zIdwap06h2+FtZTsrSUn86di4rh93ebVSvSdyvjRTZ8C
+9Wzp2bL+hkeKHLwDWu9EMXUGCudejQGRzcSdR3UBA8vyQcxzG0fNqaXVv6R9OLcW
+fOg4hZCB7eROyjQlGw5EbDQb1Mwn5b3uqTtW13lFLIcCcoW4RfhyW75japyyi9Oh
++tCN54yJsOOwjZ52PLbHTYr6/iRRKXkosL8BLS5B+B4WkIRXeFkwlq7wJRFfFiI7
+tyd9h5vHk7cwBl2ZiZCvxQ/Nlfi9wzXEFPto0LbD1feSoZ1BkWDmqwIDAQABo2sw
+aTAfBgNVHSMEGDAWgBQpmkUuNpWd7PJeVJwT1dn2RJEsEzAdBgNVHQ4EFgQUV4fq
+Vxkw9RXSdq1WA6DhF8IkJzcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEATKc5gYlWDtz8z6JjAO7O2AuY
+LB9lOLe6vRxZHjGME9s9lrupp3rM1lMEvDEcOkfo/36AR0ZWmdWbW0m94TUyu8wd
+MmF3aXQxxkJGHAdwgD8OzpzVQWYM966uD4awzXMLvzx3IqymLwiLK4veDIaNeOVU
++LTZO/CgO8jp9lbyhNs3PLU/jeeAXSpx2WCIwHVMzuetpicwWAab57FAov7p5MPo
+Est9Pk7dk9iXe5XvnnNyOavoCSbOP5XddVUR370ghSNXnoFsgzh40LWDe6HSrgXO
+ZyaArB/ECUADegv99A29DiKxDSmM0zM5NzTrmbQEpALzt57CfnsHt1T2C5ck2Q==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E6 12 3F 89 00 F0 C6 9C 39 A2 C7 8F 9B 88 6B D5 E4 71 62 9F
+ friendlyName: Invalid Basic Self-Issued CRL Signing Key Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,276B857A89B89609
+
+ucRyf9n3BU/DKfv7RVXPVBnyhidmBvM5gIlW+KzmUFP/h6oGZaW8OaU7HC5frMZ2
+GTMBvXwAootFy2HHGOoiKawgo2Zq+Fs3O0amgrn4RTIFYwfn3Dlg1fU+JnCU+ST+
+ZlGtAjPQ8vfSeCRlxkz1SSA28R+8mKQymBFF6ZkLGBraZNVFmIxGPs9PFJewX2hD
+iC+UoIdLulYgwg1RrXRy5hVxKkvaYDBUIMlYOyqzUmkQRaJhC3pr+ngb5THJj6y5
+T78tVRhkuo70/WoB6fVXF2XTd3fujEN4ksW5S2LkgWs+9XfMsntP3jeVZouOyinP
+SHySjke0TCOdzcZYedAaLcHZUsnheevsvQa5pmNSuxJBYX10f5y5sehojgcvL/uy
+c928kBlyd3b3jTzbuirTV0/AO4081BT1733bQmIfArplPWngSex4ADIF8cgIPjT0
+A2WgBOaZWNIsP5KyNiokVc4hM7ulcyurI37E1mgHMlS0cUyv53dvZcrg6g+ScjMu
+rco2GhA1LlGKWofyTC8dWpikip8S00FR2JAggL/4LQMoPJioqLv3PywU43FJyK41
+OG7CZ3GEzXJgkx2h7bbJINjz/CvhC12CBGXejXJP0kU+1fp2Pr0LBYMYOUbj2tXA
+hfMpSWElN+XZaRRsIOaYxgVIMvTpsKHudr4o4Jo7+BgJZ3V6Po60z4QZCZi7TdOV
+FZVFM9yjCzFPRU5Xv09eSf9zTVM8AKXDJvMIQ+FcaErTsO4EpdB90/jCgsk4W9R/
+ZooWrSARU0DBd7V+OIRLt0FbSXC0BKm68zg5eqLG/skbWVvZzrU0ef9BNiOuAyck
+IKcex2M0Aw3TAvpj4ZKW6ADGfBANl4/IbNDn6kU+c/7NoGGIo9c5AqAlGFKSaHkq
+y7AJdC55HqR03Y9604mB48cHwcHhpqjw6L3TF4/nv/CTYeUGw3ng1er3bxDdLdZJ
+A2ephKjF1uYYWsjmXWmAxLs1zasXC5QCTRKOWr3J/UN7f2jtTYfux5hmnh+73aQ7
+3khln5kT0s7AoWt9ML69TivVT1rdZnPDxyIBUBfmplrnHZobdpDNpapwuJxzFyQn
+QrFd/flMDvMaoTczflg0+koN4iEmOhPQpzcIDC9DikHSbryf9zcVl044qdUADI88
+saczJwKYSSKdtCAF7oldisvekfhZcERLkXLi6WrNGzI1YX4Qf6MhWyOvTs9danxR
+ukGQ8WOmb/TfQftwa/r5v9L122qJVZLjPAOPO9lGgUa/DydPYiABjOKVIfbo8u28
+KFDoP/BSAZ6ibH/2XmIfEPyf9Hr0BXDWgFiV0IbuPxE/TD6SCH0dnu/MOZiHC2Gh
+Tq14PMr/8+kmZkw0btc9/3rOsm/Phmf5BaqpQzp+KjQim7XYx2VwbJUyEXoAPNBY
+Vq8WstHlvZWe87WeMlCfjAxzP14BqqC6tCUEHi47dVoOEmC6QR3VxESWBPV6VE6j
+1vP4d9TFkamwfxQHFSdbverYgfxnWw5DcJGDaOc/BKmucFi7RwO7PImw5mYnPdSF
+Z8pTqupvQEz2ZL6gYBAHptwykG16VqNYI+4t65ZmVk2HW7Tw0/1BIR5qefjXL8BR
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8.pem
deleted file mode 100644
index 1865a68006..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8.pem
+++ /dev/null
@@ -1,175 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBFTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEtMCsGA1UEAxMkQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCfjlwgIWm+Taynv+38GP1Yf2hDPMT5pcsPYlRaeFeg7Tsr/GhTZQKB
-qfO7h8J6JjoKD1m1BTcrdiHbRBnn183kxyhljulJLu87gOUt6LlTGTBFeaUhNNxv
-wpzF5uQ7xQcChTE7GF4kxt/oyehJFi9TGtnjdjlSi3LXG/xfQn81GwIDAQABo3ww
-ejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUScn8
-twM8Z20KAJOp5NalHpIftREwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABV8
-zJCN9czUhadFLy10H1usL1xGEcB8SRR3Row0a+Zmj8T9Se71hTgW7LfXQj3bCDJV
-3AyAd+WA4N0y0+eSRWRGNAcMrOeqNp1/Ki6iGNYceZ41Goudsc34StO7symFfatg
-hTr8/7eU6NXu2o9cDREBOJujBK/Uy52E4rx/Faxk
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Basic Self-Issued CRL Signing Key EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
------BEGIN CERTIFICATE-----
-MIICqzCCAhSgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYt
-SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0
-MTkxNDU3MjBaMHIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmlj
-YXRlczFHMEUGA1UEAxM+SW52YWxpZCBCYXNpYyBTZWxmLUlzc3VlZCBDUkwgU2ln
-bmluZyBLZXkgRUUgQ2VydGlmaWNhdGUgVGVzdDgwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAKvhIgfCe7osai3K6RoZSmpIrNAB/YJ7ImOrOZihxenRuEczoaGn
-0dC3ajSeX3sg2RIomf4JTDpzcBM2swr8JOcChUwnFzOZ/Fz6Q6OREST65hRxXECk
-GbkjgRrFnTgv3/s/v9Ilt/GbdIcgBxJ1797Fr+rOEDkwld4TGgIAIOO/AgMBAAGj
-azBpMB8GA1UdIwQYMBaAFA9yyjNDqcQRUatj2kSHD2Gk9L5HMB0GA1UdDgQWBBRx
-0uz3/5i8F8pGl1n7xes8mS3ymzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBABvl4GhXI+6jjTcXaeraQVtN
-9WsB0kIXPXptGui6yVAMTsB6MhCgqlhY3xihDUJIIXRy1oV4efSfFO7UbRWOoN5T
-MikwqCAVoLnl3KAZZ4qXuwi6+OIUSXx0m8CfPRNAYdEAHCHJT+KFR8wtY4eAgyVw
-ZVhFDwnSxbqX6ThJ5wdN
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
------BEGIN CERTIFICATE-----
-MIIDGTCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYt
-SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0
-MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmlj
-YXRlczEtMCsGA1UEAxMkQmFzaWMgU2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5
-IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXGyrLR0BviK/81C9C/igI
-9zh+808dGICz2wS1Oh2CWCeYia4J/65Y7XBDRBW1TJbQLdrxt2289Lc/gc9+PW9j
-gwVpGRuYkFf+AwbMgLa1Ro5zqoIbD7WjTu7vgGdDvJmrSVLfSXavpeUBzp37Dsw6
-KzSHcBjPwGes7q3pjfhOMwIDAQABo4HyMIHvMB8GA1UdIwQYMBaAFEnJ/LcDPGdt
-CgCTqeTWpR6SH7URMB0GA1UdDgQWBBQPcsozQ6nEEVGrY9pEhw9hpPS+RzAOBgNV
-HQ8BAf8EBAMCAQIwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIGDBgNVHR8EfDB6
-MHigdqB0pHIwcDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMUUwQwYDVQQDEzxTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBCYXNpYyBTZWxm
-LUlzc3VlZCBDUkwgU2lnbmluZyBLZXkgQ0EwDQYJKoZIhvcNAQEFBQADgYEAjoyS
-h7zhrGkL40stundacKPqIEZ3HyWW0NQhD0wBhWslGAOvlCaf44kuTKggRY6r96sy
-4kWEjvfGu/r/dBgrFaCCGNv0ui5FfXu8WeZ4jvHg7wZbx5ATx5Jpumqbm0PcEYCr
-YnA6WBCstG0lohNV2ohM/wqRFmBB0WL1K+9IdfQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:0F:72:CA:33:43:A9:C4:11:51:AB:63:DA:44:87:0F:61:A4:F4:BE:47
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 5c:cd:8f:a3:3d:9e:64:f7:64:73:9c:2c:39:e2:e7:d7:0e:b8:
- 1c:3e:9b:1d:14:dc:98:c2:8e:5a:1f:e5:47:31:fd:7e:a7:d5:
- 9f:52:31:c8:10:f7:d0:a2:84:3f:77:c7:f1:ba:7e:24:62:ad:
- 05:ae:1c:7b:ff:f0:e2:ce:55:f5:27:d3:cc:24:7f:c8:1d:a6:
- b8:ce:42:05:e1:06:ec:1f:87:4c:d5:69:8d:78:59:d2:33:94:
- 1c:3b:27:68:80:3d:6f:3d:a6:c7:9f:2b:39:9f:d7:c3:83:eb:
- 77:bd:cc:7f:96:b3:ad:24:68:99:d1:1a:bf:05:1c:8c:3e:2a:
- 02:f8
------BEGIN X509 CRL-----
-MIIBdTCB3wIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYtSXNzdWVk
-IENSTCBTaWduaW5nIEtleSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjAiMCACAQMXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0j
-BBgwFoAUD3LKM0OpxBFRq2PaRIcPYaT0vkcwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAXM2Poz2eZPdkc5wsOeLn1w64HD6bHRTcmMKOWh/lRzH9fqfVn1Ix
-yBD30KKEP3fH8bp+JGKtBa4ce//w4s5V9SfTzCR/yB2muM5CBeEG7B+HTNVpjXhZ
-0jOUHDsnaIA9bz2mx58rOZ/Xw4Prd73Mf5azrSRomdEavwUcjD4qAvg=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:49:C9:FC:B7:03:3C:67:6D:0A:00:93:A9:E4:D6:A5:1E:92:1F:B5:11
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0x.v.t.r0p1.0...U....US1.0...U.
-..Test Certificates1E0C..U...<Self-Issued Cert DP for Basic Self-Issued CRL Signing Key CA
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2e:12:1f:54:36:68:73:b2:5c:f6:11:48:f1:d6:7a:bf:ce:1d:
- d9:21:7a:96:29:44:bc:83:26:d8:8c:f5:11:36:9a:f1:23:78:
- 57:00:8b:13:c6:74:57:4d:3d:ba:ee:d4:ac:d4:40:b1:d0:80:
- 91:f1:06:81:91:ba:a4:f8:1e:c7:6b:d6:20:3c:92:26:23:94:
- 80:33:df:c7:3b:ac:fc:94:ea:e8:3d:d0:37:c1:d5:e9:ba:53:
- 83:9e:26:ed:da:fb:10:0a:6e:d8:cd:d7:20:42:2c:d6:7d:18:
- 32:6b:75:2a:3c:51:03:dd:4d:a1:80:e6:d8:95:6a:2c:b0:b6:
- 72:31
------BEGIN X509 CRL-----
-MIIB2zCCAUQCAQEwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMS0wKwYDVQQDEyRCYXNpYyBTZWxmLUlzc3Vl
-ZCBDUkwgU2lnbmluZyBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFqggbcwgbQwHwYDVR0jBBgwFoAUScn8twM8Z20KAJOp5NalHpIftREwCgYDVR0U
-BAMCAQEwgYQGA1UdHAEB/wR6MHigdqB0pHIwcDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMUUwQwYDVQQDEzxTZWxmLUlzc3VlZCBDZXJ0
-IERQIGZvciBCYXNpYyBTZWxmLUlzc3VlZCBDUkwgU2lnbmluZyBLZXkgQ0EwDQYJ
-KoZIhvcNAQEFBQADgYEALhIfVDZoc7Jc9hFI8dZ6v84d2SF6lilEvIMm2Iz1ETaa
-8SN4VwCLE8Z0V009uu7UrNRAsdCAkfEGgZG6pPgex2vWIDySJiOUgDPfxzus/JTq
-6D3QN8HV6bpTg54m7dr7EApu2M3XIEIs1n0YMmt1KjxRA91NoYDm2JVqLLC2cjE=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.pem
new file mode 100644
index 0000000000..f615bcf744
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F4 66 4F DE C2 E1 DB FC FB 51 0B 82 61 B3 31 5C 81 09 D3 DD
+ friendlyName: Invalid Basic Self-Issued CRL Signing Key Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Basic Self-Issued CRL Signing Key EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued CRL Signing Key CA
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEtMCsGA1UEAxMkQmFzaWMg
+U2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMB4XDTEwMDEwMTA4MzAwMFoX
+DTMwMTIzMTA4MzAwMFowdzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2Vy
+dGlmaWNhdGVzIDIwMTExRzBFBgNVBAMTPkludmFsaWQgQmFzaWMgU2VsZi1Jc3N1
+ZWQgQ1JMIFNpZ25pbmcgS2V5IEVFIENlcnRpZmljYXRlIFRlc3Q4MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAol4o/PaoUHfmfauJSNBudpqdHZMlL9Sy
+AWTgosb1N1sDIAswsQmo0kHLjxW1p1zcVljpQso+13cnjBtP+k6PGCmfQ7uAuRGb
+r4zljd0X5talJ+jaCcQrmoDDcl/aznqVQySJ1jLSuDKLqSEjvObatrLvyhrawMH6
+9oEuno612WHt2L0kxjDtrTqauVCkUDsbC40LK4Qc4UBponYRqgOedeFnGJSmt5WF
+SeLEELadfaxCSVeT+IEUFQ3HV6D3icKhRsS9YKneOnOUn7BvuTHFUEisz07Q7wJp
+3NatsukCsRMW0w7KJhzYh8QElm188tzJoScQR/ETIQw49tDBH1M1qwIDAQABo2sw
+aTAfBgNVHSMEGDAWgBQkwVVx+p7hIYUq8K1hpxW51U1DFzAdBgNVHQ4EFgQUaAjV
+TuVUjiYIJGsaF16hnMaOnu0wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAmAQkit0tiMpNN+36ZZKdZgJ4
+h4s5B/oh+1NS53RzqD2fSEcLuh2zaX5Lq4GJJ5q0KQTn4yhyLDZbXSGNnmR+T3vM
+b6cBIA173e2na7ZaYmNsdTLeSdX29QFxJvWGFeGrnpft1JW0uQStrRTaqu5WCCJF
+7tWCNs/Y4V6VmnjXKs54TophgffFFSizMHOq5eedZ0ZLDQCct36gPPHcF4MFdEDB
+kpatcioxP7NA+ANWxkkQ3bm469ivlolt6cM3qhVwaQdXgv1kPUNsgpe1rZi4n4pJ
+ldddkxuiu0SYBnxtAsutBl9tA0cfUrORcDyMOTJI51Ql1FKq4qVPHBCi/uDn/A==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F4 66 4F DE C2 E1 DB FC FB 51 0B 82 61 B3 31 5C 81 09 D3 DD
+ friendlyName: Invalid Basic Self-Issued CRL Signing Key Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C9EEE21DB0A49417
+
+kjbZTeNlxh/qNwryOSveCeSjWhfJXP2/eMetmVAJ2roO5FIoy2WK8fqpsRu68rq2
+1UIwv3hl39NmfxIXzvX5s70HyzXzNLfm82ElvVKjrCzFS3b47pdcZQCczMYzz3ht
+2XDxqubJqaj8zIZxizdokvkg8656jRM78sr5vhxd59Wkp6VHwh/8Z1iYnx0RuRRd
+7K4GwkfbBqn4BMEvw5j40MSC//48hGDljNVwLNIcWPHybzGXHwjvwaynkqjYo9X4
+BuwlBZZdd4sPKUCaGmpz2gOTBOyPVuVJFKjCjZYAV333CQu0WBJu0r+BB96RJ7c4
+Hoby3fkmO/QlIYtCCWrHOCnulUTyP5HNWy7qN22Cs7XTaWFw0hAV3EmJ9xDdYyMp
+DoEoJAdu1npfDCw69qURfJqZdZWcRHV0IdEiW0lEDaXwarHO4465+rLQ6Cz+fXoq
+ThRxbMwqWC0xcaMvrzu4DmQ/0gaWxAOgBm6mhhcgVXEAs/gmytGwesTBWLFembLg
+DT8HEYuaP+JUzvblpPNqNsmDy7Awg8VFns6UmdN1/BPcjcN55Ex/S8HUi/6nrcTc
+EEEp36OKRG+MeYKLN6M5XKVFIyjpba/3uN4cftvcp93R4tPaopfOvZeVua5SVVch
+Q8pYrCwe6h6Cjo+SkYiIKsMZWN9azFaj5cHHDbqy8v9kXvVtnumAKJarb6l3ET9W
+R9IKboeoNWFxNdrJJ0nIwVW8bFdBGSNU3nRdunLcukvyNk9kKMNtKW31MmnDTPvX
+lyzE63H4U6HiXxYGF0Kkw9URCL42qkUumDgjQEOOCaVdA5/FfuhiPJH9m9cHVBO5
+ZivnvMw1SExTthqUgMZCWhRpTR+rvfnUi7OJ1bWcjcz7Ot0CkXrFkbqeOb4o1Zvf
+LKQxtD/rV+7A2hvjFvDvYG72txT7JSlpPmK3/70MVB21DVKQf1vLYeEV+Tc/9zPh
+UKezzpUhZVfn0EJXtxItuwT8ZR+LQdsZRTGFA1U/PjXDamBfmHFQCOkdFkAgnNLz
+ErRq13os5jChZ23citg5+cQnmlzgQXHMidyOylHqagohJ2ZVuo3hXna+dVD2yTTs
+UMPO4JJ6MLtsNbtFJ9wI8wpC9upnr0jIxVcPhzNi4uIi6B5qkQGcjSTFtqwHxll4
+n1WW4PKArth+v54FGI7BzROHzsU0rX2y8eZJSuWH/yLwFpj/osQtrdsYP0If+ZqN
+AHuf1LyFA+8XOGU1HAgxu5dVWdaqpIVib8BdkLBSMsvXtBY8vx16KIYyD5Wnrcds
+dj9fy1wgpBoalkOuDG4UXPf2tEZ58oM64fgho56z721RT5WKLqIMpvS7dclkzAs6
+IBCDrZwGWl5oEGmyqQAqBjSxrDUfzrwDS2y85ULfukqqw7rWdNH74jUvYsny1uq8
+FzGUbfLeDlyyGX0GIKilL5e1eNVoYgH66lYqDATpfwxWqV3Hx9eZviOUr4dYbI1J
+f8k3Y8x8Yz9ooAuWXJq0c46Zt5mOiSMpu457+fK6/AW1n313s15Dx6Lor8DgQLrv
+rR264AasTQDI2rZdYqrMRj2UTkE7sfpHK9kbGbnqInm/KWYUXKALuph4ZACiQj+T
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5.pem
deleted file mode 100644
index 51a795fa99..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5.pem
+++ /dev/null
@@ -1,175 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBFDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgT2xkIEtleSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-q8Gbt04t1VYDzow3lv3G+lNNQ/gCP0fz7/PBxNPzAwluA2Qzeix8gg74cXMpRe8u
-PosT3EZZ9iK1PyFmcNq+CjzCuvi8d+1gaGS36wkcQBB6g7HiKRQ8ERQ4cEE6CH21
-ntbFzVbn3d+NofzVo6e1AIdHDNPm7G0+F6f034Lo508CAwEAAaN8MHowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFPqiarnu+k/Fcp11
-00t6bYzkXDkkMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBzQl++7X/MYd9h
-3E0XroNDuD8TflER0UTgWOwN5UO8BXz8j402hmhEPyw66u6R27V7U1/wf8wtCAli
-W7LnTcJKWFy9HKnpibiz50ike8zgsVmv1godVgDn/xvQPRAnWq+OX9Abc+6OTqiw
-aDNRQp2WD1ph+daLu1XQgeAoD4Gajw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Basic Self-Issued New With Old EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE9sZCBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBvMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRDBC
-BgNVBAMTO0ludmFsaWQgQmFzaWMgU2VsZi1Jc3N1ZWQgTmV3IFdpdGggT2xkIEVF
-IENlcnRpZmljYXRlIFRlc3Q1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCT
-jnQuWQQfSAPHMxbQs5/JPin7talEYrAwqnyOVuFLu5omsqP9HAX7nkKxNRfOUlP6
-af7Ha9u8C+frLG5WwPmnf9XYIBaisUdEiga8saNMEGChSlZmaPoLD/LTNlCcwCEt
-HaHuhAAN62AgP9WMXsrfctRTccjIaQVsJnnTOCUAqwIDAQABo2swaTAfBgNVHSME
-GDAWgBT6omq57vpPxXKdddNLem2M5Fw5JDAdBgNVHQ4EFgQUUw9DlHqj5ferws7b
-XdljGKM4E7cwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATANBgkqhkiG9w0BAQUFAAOBgQAzzPXRKubQgAmne7+Rqggy+8Ezi3Q7+1cNjILV
-wVSnnVggqbd6C/cOV9P4aw1ljohm6fH5IXxfCpP1UqahccTT/m0482gfIxmCobF4
-MBi/cq6qlhQQIjBxGRkyysQIb911FCME2mVUlLQJbjkgpzl6oMu0M2Lt8m8ypgVf
-YqDhRA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
------BEGIN CERTIFICATE-----
-MIIDETCCAnqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE9sZCBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBQMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAj
-BgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVkIE9sZCBLZXkgQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBALQ4a61C9wpu5W0cACccONm+QLNESmbHtLwy498fByU6
-h5UnHkutUfy7DbIv3rELFXUd2yM5xQI/QuQZ20EjXOZiCSJEcvzfoAyFLrAPf1pN
-xQybX5HhLnJK+oGlwmD4ZatL7oDqV5IhlIS0So7g+SBOCh5lkKdzbH3l6D7nQXSD
-AgMBAAGjgfowgfcwHwYDVR0jBBgwFoAU+qJque76T8VynXXTS3ptjORcOSQwHQYD
-VR0OBBYEFBu6jCGHcwcFmPrrudlvQaRF1YbqMA4GA1UdDwEB/wQEAwIBBjAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zB7BgNVHR8EdDBy
-MHCgbqBspGowaDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMT0wOwYDVQQDEzRTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBCYXNpYyBTZWxm
-LUlzc3VlZCBPbGQgS2V5IENBMA0GCSqGSIb3DQEBBQUAA4GBAHDVnYLXKN//Mu1w
-BZS8DbfQ8p/DlXZ0n9EmdXRzoHXReDWeOaoiHU1H1HNJcLMe4YgEjsttTEBGfsZo
-OvyNNUZ7C/oQymaDykP9W/m1TX3ZVLmx96zj36gCkVPczoG78kQ5zVjoLl5G5BJQ
-4YX3NumsNd2WpHY34K21Cd/KJ5KJ
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:1B:BA:8C:21:87:73:07:05:98:FA:EB:B9:D9:6F:41:A4:45:D5:86:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 62:de:93:8c:36:dd:b2:71:56:bb:4e:e4:32:37:51:de:6e:19:
- 01:dd:3e:25:8c:d4:81:7e:fc:66:54:74:0d:32:30:d2:11:49:
- dc:ad:6a:b4:fc:8f:ec:e6:56:fe:e6:ec:53:9e:41:66:31:2c:
- ee:3a:be:bd:74:34:9b:71:c1:67:1d:3b:28:04:b9:85:e5:72:
- cd:f0:2b:a7:d9:d5:e3:43:25:4a:52:2e:79:24:52:cf:75:e1:
- 3c:35:82:d1:5d:1e:f6:05:8b:45:24:67:ed:84:9f:c7:8d:c0:
- 19:55:5e:52:76:3e:2f:f4:af:13:ae:d8:24:a3:17:68:5d:b5:
- 45:74
------BEGIN X509 CRL-----
-MIIBbTCB1wIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVk
-IE9sZCBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgEE
-Fw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFBu6
-jCGHcwcFmPrrudlvQaRF1YbqMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AGLek4w23bJxVrtO5DI3Ud5uGQHdPiWM1IF+/GZUdA0yMNIRSdytarT8j+zmVv7m
-7FOeQWYxLO46vr10NJtxwWcdOygEuYXlcs3wK6fZ1eNDJUpSLnkkUs914Tw1gtFd
-HvYFi0UkZ+2En8eNwBlVXlJ2Pi/0rxOu2CSjF2hdtUV0
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FA:A2:6A:B9:EE:FA:4F:C5:72:9D:75:D3:4B:7A:6D:8C:E4:5C:39:24
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0p.n.l.j0h1.0...U....US1.0...U.
-..Test Certificates1=0;..U...4Self-Issued Cert DP for Basic Self-Issued Old Key CA
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8c:6b:ec:1f:5b:3d:31:1c:fe:c6:40:ca:e3:c5:52:30:a0:9a:
- 55:ee:f8:c3:bd:cd:b1:45:d0:7f:44:f6:42:1c:0f:b9:df:8f:
- 4d:25:0b:ba:5b:bd:0c:68:c2:ce:b0:c4:17:e7:be:81:de:73:
- 55:5c:6b:d6:3d:e5:e2:18:31:d7:5f:6e:1d:4b:0b:31:cd:44:
- fe:29:d5:27:77:f5:83:bc:ee:3f:46:31:d5:66:5a:a1:9b:1f:
- 16:d0:8c:ef:ae:bb:36:75:a4:b3:62:be:16:cd:de:b8:90:bd:
- 5f:26:1f:a7:d8:1e:59:ce:27:af:ee:ab:de:9d:1d:66:ef:9e:
- 49:cb
------BEGIN X509 CRL-----
-MIIByjCCATMCAQEwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSUwIwYDVQQDExxCYXNpYyBTZWxmLUlzc3Vl
-ZCBPbGQgS2V5IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoIGuMIGr
-MB8GA1UdIwQYMBaAFPqiarnu+k/Fcp1100t6bYzkXDkkMAoGA1UdFAQDAgEBMHwG
-A1UdHAEB/wRyMHCgbqBspGowaDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3Qg
-Q2VydGlmaWNhdGVzMT0wOwYDVQQDEzRTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBC
-YXNpYyBTZWxmLUlzc3VlZCBPbGQgS2V5IENBMA0GCSqGSIb3DQEBBQUAA4GBAIxr
-7B9bPTEc/sZAyuPFUjCgmlXu+MO9zbFF0H9E9kIcD7nfj00lC7pbvQxows6wxBfn
-voHec1Vca9Y95eIYMddfbh1LCzHNRP4p1Sd39YO87j9GMdVmWqGbHxbQjO+uuzZ1
-pLNivhbN3riQvV8mH6fYHlnOJ6/uq96dHWbvnknL
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5EE.pem
new file mode 100644
index 0000000000..b517fee0c2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedNewWithOldTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E0 6A 28 AF FC A8 53 FD 75 C8 02 E3 3A 5D BD AE F4 8C EA 46
+ friendlyName: Invalid Basic Self-Issued New With Old Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Basic Self-Issued New With Old EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued Old Key CA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIBBDANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgT2xkIEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHQxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUQwQgYDVQQDEztJbnZhbGlkIEJhc2ljIFNlbGYtSXNzdWVkIE5ldyBX
+aXRoIE9sZCBFRSBDZXJ0aWZpY2F0ZSBUZXN0NTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKdBgafx2op0ilCfXFnMomtQos2eWUOojL0pa0weh+1coc/s
+JP0Bi4a/lqr4zKPuomUMUG9rjaA+PW85qbCBh3I7MliOmaEfIrbjrBjXv5xOv7PL
+IJSUAYCfCsvLtm2djtMOxfSiOFCqCcP0wBUI7lKRAvFvodF+cNs6h8Uyb7Q29DgS
+W9Qz6oAXIXLCkLGbIE1aPqwja7bznjJOd7YcpH7muDaVIripW2INqJViDvHDPXnA
+29KTjY4i5sre9W/k9iudexcHircRRdLDCeSjccmhR0ogzZEeVctQ32icG2+Yl4ak
+PgqCrMwCVOXomDyVYakR9eo9vLC39EUNssATgtECAwEAAaNrMGkwHwYDVR0jBBgw
+FoAU3Q11jVNoEsTLFUDAFIYUFjChvq8wHQYDVR0OBBYEFLQGHiravKZOSLcCXHIN
+6rlg79jcMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DQYJKoZIhvcNAQELBQADggEBAHlrlGfh2haGDB2u/qW9ngyAyYIMXbEOf9548qyp
+yNLIu5SKP4oMnhJoMQ4sG2rxAtABo9UjGv+yOLAGOZQlP8n1dPc3n09i5QFroAnQ
+mV2SwHnalmq2IIxhsvs1TcLDLwIV3bOikZq4U8rFdly/Qh9j3VcJvmJdBhP+0roW
+XDyLIfqQdAeTtxszKdDSTatd2uKyGh/Sef2Z6A2T2s7Yn8txRWHPIj0QeTaE49r9
+TQVjJZ3lLD4O2f0qXFbvYWy2x19LizWWkNR+79Xivfo1lSxp2D32gwd0HFvpqVHp
+RyA9g3kOvZuzTe3J5n50iTH4fxWotF1tNnmuwZFHC1qs+q8=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E0 6A 28 AF FC A8 53 FD 75 C8 02 E3 3A 5D BD AE F4 8C EA 46
+ friendlyName: Invalid Basic Self-Issued New With Old Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C00A44F6FBA277D7
+
+OWjEf2A/4WUr/ODkDuwfwtuhFPz1X11cB7hYcaiY54tjOo8QdWjFHI77buK+Q46m
+fL7Mq/GE3KINNNIxCMNN9HLMBNG+g2724TCsJZq+misTQiVx1FWk+rtKs5W/HIrD
+PfJ8youcyd9Ngw1BWDZ6QWuBcsu/MmCBZxA/vUyplhOac4MZH6Gorkb3yBZiWrCj
+xbq02XsImhif45rOjtJ4yHVJEpBLSasjbO+lMB4sQ1ihHU7pZIWrd5epVKSLXkRU
+355xjT2Nsw9UY5KSN258FgEHzQq7G/sUGXw8vp7S2rT/P/3iJr+Q72AZKsKT9yBG
+OGNBEfGy/CsptoKU1sOlbpVZml8vV30pM1SMPAvyqau4Chj3K2Sj+DT0CcRgqAjC
+JW3NHqZpTR0A4I77unNOfT0LWwCAAQNxcC+RjjN7ZHL8F1PzIB/9JzCey8sXYgHf
+X97E8lAH905xdfhyBg+R5CsLRL62KCdebu5wJj8993jNCIQKuHlLqnUXdOFS0s/C
+KjHYgL3aMDIf36QxCk0Fsmdqhxp7DdRihw0Kv00IhrRZHKW+7bMrR1I+9kh3L6sB
+zrjWGNXFbIkB6/ZuW4t4l3mc6pOLfFS0yuRxfZbEVCKO9bjoASTfImELoeeHj7qA
+n50NFidOD9AKn220BrDgnH/9vuDp8bRrEQTLNpncVyp2gv47REosIDfn+0AdxcrD
+JUB8gzN1lvqQl5Sns17zTl/74kkxW0B020ih7acF0d38DnDkiVGUrZd3OcabpKxd
+axZ1WxY9ZhNxr7+Nz774twnL4NRX9RVy9Ofw9XQMqA4yl3nYrl/tD3PE4DvDivSg
+o/HpfldrBnYVfS1Ts7HdhidXqm5EW0sFYNXysOnDHiqM7YSaya2xFPI+37jhMOlL
+Nn3WrKEfPUXlBhkEVNNPC+1ANpLoGgf6hEwHbjho/znOzPWAlWITqtaiZoL82gZD
+zGox5aBSOfdkRX+tFSn+wOD4QkH0YUr7jUtLROIAPUUCs+OWCwdwc05fTmaz9vi3
+r3WeU329HUtl/NUOgxidZSMDw9+HHKLzRfRASEmK7qvy/FEL7zC2mAiThv+90Tct
+37KnfMifUcsRyORjontpmmor5Y5agaE2h3CnPQpxKKs7SyrUGAhpHJ7zzd+Q1HXY
+Ya7JGduB7T83EJv2mRpNQxJ5kXcIk3RBEhwVUjVVtqK+FP+/ZZL14VaNbxgps2j4
+LakQAZG2WOi/wv46fVrS63seYG8yu1/c2D21jfRT6kK8+Qs6V/zaXbuDxhd7TsMy
+T/khtdChhr1kt8Rz7XNbc2H4DREeKTqwhpVFG+o73ySfALgO0ECVMBS8POhytBqf
+URP5GUQwGDqDwBKvS7JotpJSkrCApAesduv/7Vq5I/+7B2HUiYt5RLVUYL4tgYdo
+gtPKrerlGu+zXJ672z2kmKg5LVWd2zsw96efGgFop5s129BpCzY+d5axCP0Y/oCj
+Jpas8ODtvadh611R2YqNOcgKcTH7lhTEOGc9IzKI0rf2pFL1eUvDOwe8Edwldn0M
+EgZAf9jZm8yVb+AdTBfhiusnDtftQge5PXiJQFnpujVe8LNy4SWPJjBxhbidx54/
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2.pem
deleted file mode 100644
index e0924953b8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2.pem
+++ /dev/null
@@ -1,134 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBEzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgTmV3IEtleSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-tCkygqcMEOy3i8p6ZV3685us1lOugSU4pUMRJNRH/lV2ykesk+JRcQy1s7WS12j9
-GCnSJ919/TgeKLmV3ps1fC1B8HziC0mzBAr+7f5LkJqSf0kS0kfpyLOoO8VSJCip
-/8uENkSkpvX+Lak96OKzhtyvi4KpUdQKfwpg6xUqakECAwEAAaN8MHowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFK+5+R3CRRjMuCHi
-p0e8Sb0ZtXgoMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCuRBfDy2gSPp2k
-ZR7OAvt+xDx4toJ9ImImUvJ94AOLd6Uxsi2dvQT5HLrIBrTYsSfQj1pA50XY2F7k
-3eM/+JhYCcyZD9XtAslpOkjwACPJnODFAY8PWC00CcOxGb6q+S/VkrCwvlBeMjev
-IH4bHvAymWsZndBZhcG8gBmDrZMwhQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE5ldyBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBQMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAj
-BgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVkIE5ldyBLZXkgQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBANa7RRhusOV0Ub10qBKMsUMG7QViaonYz0IcJLX0FKEI
-EpTq0SV6NeVjjzmcrSrzjHQfJpkywOHRiMw7XvYunmzlwGSoD6TW1ZUYVDaQbKUT
-oWooVoCzVstf6AsZiJiHQtBt4x4OHap7QRcJdlh7aPhp6TR+zq8gB1HsG8yUlG0x
-AgMBAAGjfDB6MB8GA1UdIwQYMBaAFK+5+R3CRRjMuCHip0e8Sb0ZtXgoMB0GA1Ud
-DgQWBBTJW9PRvwbxAcF5XLtzDY1MRsst2TAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF
-BQADgYEAhIZ09WrNK3jX+b8HugQygNCBEVVfX7TOCCFkmRaxp4R/QBHWvcts0YQT
-6M5ZC6b877id6zRYegHadKekVVqwFbLKEO0MnpD2yGhGgDpbil2HlEaQ9yKQXpGF
-CBx05/e7jkNhk/zGDsBqmNzkozrJOYBohkwUOjVFkAuLyovPhTY=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Basic Self-Issued Old With New EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE5ldyBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBvMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRDBC
-BgNVBAMTO0ludmFsaWQgQmFzaWMgU2VsZi1Jc3N1ZWQgT2xkIFdpdGggTmV3IEVF
-IENlcnRpZmljYXRlIFRlc3QyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv
-b2Xj8btEB2QsPM7mVVrsnON6Aw/LdDQc2nszxDNBn133XQWeVkHORkod3p9DEg4i
-TEdCG+rweF78vMSAhWAucXcFC59NAjUgxMiaIneUK2lKDW3afmmLHzV3nHjlNkj2
-DN/BvUmo3Pp2lhrmdTY1WFfvQdueeiZKbCB5dor8+QIDAQABo2swaTAfBgNVHSME
-GDAWgBTJW9PRvwbxAcF5XLtzDY1MRsst2TAdBgNVHQ4EFgQUJuUNG88pizoZguKT
-iPPiMZLmggYwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATANBgkqhkiG9w0BAQUFAAOBgQDGIVBl9ctXIMIN1Zy2QYgGnP8POYBiHPRkHZwT
-IGhox7QsinsIS/Lc83H8Y4OeUaJWrGGL2HkSTR/eQgSFGwf2u297IhHOwtutllNJ
-MvzlnvuG6uNAfRCuJftf8hSU3ouJoVVCi9CuCg1IhW6Eg61/oFIqZW33Jr6EvI8R
-WDDSrQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AF:B9:F9:1D:C2:45:18:CC:B8:21:E2:A7:47:BC:49:BD:19:B5:78:28
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 73:fe:c5:db:86:ee:6b:0e:f8:68:85:d2:0d:c1:44:01:d1:33:
- 5d:9a:42:14:a7:a9:20:bd:38:30:c1:f1:3e:c1:b8:d9:4c:ba:
- fd:3d:7c:a9:66:5f:94:fa:46:e8:23:94:4e:8d:09:1c:45:6b:
- 21:ce:b5:cf:3f:e6:18:33:d0:ac:a6:ea:c5:f9:32:6e:75:31:
- 79:6b:1a:8e:50:05:86:89:f9:f3:e9:8f:67:e7:93:b7:d3:05:
- b0:9f:2c:97:9c:b7:7e:01:7e:c6:5e:f8:72:4d:11:6b:9d:30:
- f2:69:df:68:5d:aa:a0:84:f1:07:68:15:fd:93:f6:14:a1:f9:
- 90:ce
------BEGIN X509 CRL-----
-MIIBbTCB1wIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVk
-IE5ldyBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgED
-Fw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFK+5
-+R3CRRjMuCHip0e8Sb0ZtXgoMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AHP+xduG7msO+GiF0g3BRAHRM12aQhSnqSC9ODDB8T7BuNlMuv09fKlmX5T6Rugj
-lE6NCRxFayHOtc8/5hgz0Kym6sX5Mm51MXlrGo5QBYaJ+fPpj2fnk7fTBbCfLJec
-t34BfsZe+HJNEWudMPJp32hdqqCE8QdoFf2T9hSh+ZDO
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2EE.pem
new file mode 100644
index 0000000000..add056fc3c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidBasicSelfIssuedOldWithNewTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 93 4A 83 29 A5 7E 8E 01 5A 7D 6E 64 BB BC 80 08 D1 AD EC 46
+ friendlyName: Invalid Basic Self-Issued Old With New Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Basic Self-Issued Old With New EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued New Key CA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIBAzANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgTmV3IEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHQxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUQwQgYDVQQDEztJbnZhbGlkIEJhc2ljIFNlbGYtSXNzdWVkIE9sZCBX
+aXRoIE5ldyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAONFtaBbEeY/tf224reAYPfWB1koSJrZRslSjHqNiok5MQ1J
+d8kfXe8BJafeKWnWfmwg4aoVR82DdeUlRjZwiypHduV85fP4Vt/BYAmlM3xZB9bX
+Pz0H4Frzk7//+RXs5TOhdpgVoCD6GmVvx/leAjdcPXbFoM+QmDa7ZZ9ef6Cdy71d
+4Wed7Ps/2NlGda2fBbVAeVE1RVNAeEEzu/6y431aoCaIZgNRMKqu6AhieUV9Ivzr
+Z4pdThxoR+nLSATSD2/hT+OENQuU58KeluxHOSSrNdcikbLU2dg7ZEeAh0lt8kJr
+IVmHxiXAB4ijXHjsExkbOrXtztcaZR89K/cko1kCAwEAAaNrMGkwHwYDVR0jBBgw
+FoAUdnzYZAQ0CU/fcSF0DwwWmzaogtcwHQYDVR0OBBYEFGCc3XbGoH8/97MyHZJe
+FFeD8q91MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DQYJKoZIhvcNAQELBQADggEBADwA+jd4g5vKoR+8C1UXnL8eCHaiO3TNCL58JLqe
+BAErAUSEzOtdZ7g4eefuWwOGiLy0gP8CmnZ8F0g9urAVT18h8VmbnT+h9sfUI/6V
+bcTourPNHdB3YzcwC9rX/wx3DK14NNIMPMM8vwLaroGNYvVZjyTWkIQGmDlZqC32
+ibV4zFYTaw+MuqcqmKC2IrUXQoNLE/aQzEKZk4rSs6o0l/0ikDrsQUgvJMf1DBVV
+cae81wsyvqyg+mbm+lBXnE8D3lfuQHZisx9zxCMmk/VHCtHG8FBZtyvuobSpfMKq
+uUwnwRtDO35UgLdA5/SGtuSvGrMUyjUTH/PK+VySElBtA14=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 93 4A 83 29 A5 7E 8E 01 5A 7D 6E 64 BB BC 80 08 D1 AD EC 46
+ friendlyName: Invalid Basic Self-Issued Old With New Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2767B788F932E013
+
+xnFbMzgh5RkhuVCWZqr0bLQ7assqqQTViX9rNT41QM6gCGKywyGn14fB6i6fSRe6
+xeRXske/LUmJO8Vi8hcCANGj6Bb3WUBqxfGO2LX2q+pBvqh9qztx51/7uF0x7A/p
+w/1M4eIVltBJl3gpDzc78ISRUIb6KRAQswcNSOhvavlE+e3VbJ3iFP5c5hLvTBC6
+ogT8GcjpvQIMWHyDIZIXJuZyMojWhuddQxGplB4korkB4cSRcM0uleTSkyVFyjgA
+n/wm0k5juurwdhXP89Gp0TtiC3eL4+b7ygwFZpND81eFptXzwNCE1cLZX38ubFcU
+jY0cqufvpvCcU2afW01OtFObc+3RXPAjSz3anaX6Hu4etKZAjGw9fiqRcqdNTYE7
+GEzWqfCIAG/7mE/lcNT9HVJtolLQhjcl+LoYrWc5IWSuoJauZ7gs6/ENM6PPeU+h
+nktNe+J8flQLiPufJDdsbICYIBYyA+rBJWRyHAxb7WBrNFuFfrkLEKRAj39YlbzP
+ryQ92uXCLGWcp/d6uKYNuegjw12mxnP3yb+6ngUYQkoeZNXLRAEyWb5nO/iZQiNO
+RwDyFBmmJTFnO+dSoKE1Mf4EyppwrHoi/dITvqu55bOohIHQ4+XaX2we+G5CQzb/
+QiTreQudv57y1tH9alx9Hw6WdW225TpDDCNG/PI8OpQZLpK6duUoEN8I1tG8kTq7
+kJwOS9x8QymT0gIUQ5zOCH0SWHodM3+JdukocKds+J6St0YmCIjFpKNeMAEpg7VX
+oVjEWCEOHaDuViRerXiEkPzZGh0/BLqjiBeyTogXfjvN31hZAyxmDxst1MlwhiAz
+H8KIDqPZmDSxUHAYouulA0grrpA77OJFGXgINXxi5OtkEywe/6fmy0gWg+U/o9nK
+ctkURuXfJej398hjRI7Z2/gN5vM5GeDPMJBIp8sQrbZqueXXuyyXSbBV9X7I05WS
+m09jBpflDoRZANx5CLz3o+EXA1pb3carkCipakcHVunCCjT6RZv043leZVymREd0
+WmHngxm+gDreNJPzcxWpbj3lRsrq9lzZZHQRYosyga1fLOK9966G9AwJnClaI5EV
+Gp/fMMkBQS5n6s4k9uwX3m95PLkypG2gK7vyXmsdQGMx8RSeJT4gx/l3zoOibn61
+EONf9A7geaApsEDDoxS9i1m2N7dUbv73E0IUT4W5qSBidNCj+PniWB2ostRiH80d
+6r0GkvboaAMxfKTYatdo2ZURmFC0P1JNmM9tCuhhxBkQ3RGgnqgUcKE8vFV/S0Aw
+nBqatpC+r1KpmoMG7AzunAeA7nZJXkBbq8lGEcArKiEvxo4brDM+OnxE3o3Kn8/W
+mmpOwuaUTfNbGgAvwLYf18ltCqXHRwqm74T/o1pl9Ax8UoHVR2n3rn6ivs7idtDQ
+d4aEfaLer3trPOZ2Ljesend2A7P6mqvEAnF5bSebx+VE8HgxrEpnPUBKmx7DtIVO
+PGTedGW+Y8MOLBhtKQEcM4240pBCDSda9E3LkB7kAtGiwf9ncvRKlxRSwj5uhKSt
+QX5nyHBLdRv/woaLUhTJrPQu7WbIlHYBgjCDGvHmi5TCR3fXZqJqkg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2.pem
deleted file mode 100644
index 520f583902..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid CA Signature Test2
-issuer=/C=US/O=Test Certificates/CN=Bad Signed CA
------BEGIN CERTIFICATE-----
-MIICcDCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMTDUJhZCBTaWduZWQg
-Q0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGkludmFsaWQg
-Q0EgU2lnbmF0dXJlIFRlc3QyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw
-QAB1tOhQDQfPXGHNyIA/wyXWG+GAx10kyG++1vTg81Le2VcCJjiZqVFLmLfBA9n1
-cD4b9zSs2MrdUpnwVRWbHmeVYLW558PktB5UwAoEPQuV73PuRiN3GQQULGgh2AlF
-k8PciufvFGkmYEco5d8AEM9Gv3QIgOKEraQME0I/NQIDAQABo2swaTAfBgNVHSME
-GDAWgBRCG2+XCyN5H8EIV546pgqckIgf2DAdBgNVHQ4EFgQUfIdcwY2/jxziMCvk
-H33rpDMUuV4wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATANBgkqhkiG9w0BAQUFAAOBgQBgBJI+iPa3EWEHQqZr88JOAiU+tMO54vqLZ56J
-visDO48tZuOHCSkrqHvBzsabiTuHjDvcHtivavtV43IyHAnyrajntNrs4lPBJlr3
-XvTn5qVlsmuNGJqUrbxiyeNH/y1OB1Embx/RaoSOy0ffruRpL5PXyFvhn9z30I8f
-2zkCOA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Bad Signed CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICczCCAdygAwIBAgIBAzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEExCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEWMBQGA1UEAxMNQmFkIFNpZ25l
-ZCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA16COIB4MAs+kpSoCuSHv
-grtYTFABazGQDi3rvkQzAbL4QlKE64PAaeN4S3E9A1wg7uWYiru7ZM2D4k6grNKR
-3QGx9APutE7yZHZt8Wd2upDOP62BTYHPrP7hWBSDWBmOKi367A3eviObljIH6BeF
-EY6XcgDZg3o5AisPFzKK/pECAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6
-ng2wPOqavIf/SeowHQYDVR0OBBYEFEIbb5cLI3kfwQhXnjqmCpyQiB/YMA4GA1Ud
-DwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUw
-AwEB/zANBgkqhkiG9w0BAQUFAAOBgQASa6C+NTUfhhObLuxx8/8DFxAuEv5l+BQV
-S7NV/MAZBPHBSw89ffEPEfbxBTcBYRI+UP59a/zHrzscTSqri7WoTEy/8tKIegHd
-QDjTSXNL6oYGiQXDJY/r2kQB2mArrcL+KzKkC++gNgrdoJlpk6+4lfaBLiETQNtD
-RBJVYzR5MA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Bad Signed CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:42:1B:6F:97:0B:23:79:1F:C1:08:57:9E:3A:A6:0A:9C:90:88:1F:D8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 11:91:7d:19:a5:03:4e:a7:f1:1f:18:62:94:fa:97:a0:46:41:
- 96:31:95:19:49:79:a9:e5:f1:84:aa:c8:dc:c8:7f:92:07:e4:
- fc:66:96:9b:2e:8e:73:aa:ad:70:11:19:fd:8e:be:f2:74:3f:
- 79:02:5a:e6:2a:67:b4:46:d7:1d:8a:de:c8:d0:b7:cc:f6:85:
- db:90:a6:46:9c:ad:23:09:47:aa:f0:44:45:63:f5:40:dd:fc:
- 75:bf:4b:85:2f:fa:74:09:f8:19:8f:29:97:92:ae:34:5c:6e:
- 6b:6b:40:74:51:58:26:df:95:b7:72:13:3d:b1:76:9a:0a:43:
- 37:31
------BEGIN X509 CRL-----
-MIIBOjCBpAIBATANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMTDUJhZCBTaWduZWQgQ0EXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFEIbb5cL
-I3kfwQhXnjqmCpyQiB/YMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBABGR
-fRmlA06n8R8YYpT6l6BGQZYxlRlJeanl8YSqyNzIf5IH5PxmlpsujnOqrXARGf2O
-vvJ0P3kCWuYqZ7RG1x2K3sjQt8z2hduQpkacrSMJR6rwREVj9UDd/HW/S4Uv+nQJ
-+BmPKZeSrjRcbmtrQHRRWCbflbdyEz2xdpoKQzcx
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2EE.pem
new file mode 100644
index 0000000000..6bb7e343f8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCASignatureTest2EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 1D C0 51 02 E4 A0 E0 B0 BF 9D 2A F0 E7 6B 23 E0 39 16 90 FC
+ friendlyName: Invalid CA Signature Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid CA Signature Test2
+issuer=/C=US/O=Test Certificates 2011/CN=Bad Signed CA
+-----BEGIN CERTIFICATE-----
+MIIDfzCCAmegAwIBAgIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEWMBQGA1UEAxMNQmFkIFNp
+Z25lZCBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMFMxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSMwIQYDVQQD
+ExpJbnZhbGlkIENBIFNpZ25hdHVyZSBUZXN0MjCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAJpto6V//mi4jC6Q4e/y1J79mi//TInYf0KaP3Aw5rsaMhC8
+IJbEAdkIhfj6Skvg6uPj6gJB0zsmN9Tf8NVArEfcRwjAq7IvvDtVrDz6I5Ie0bFD
+8MGkcdP0otJIpbTTHAcefxoqQQeTCt39X9viZokrLeBHWnB4L6zE4d05f/7Wh8ca
+KlDiKjRQl8aIqj8wPsu4MlVC4jnSYTQ6wEd6cA3gJRygcUWkaLaVleaV+PYyUqD7
+8X7p3+i16q1DzgtL9yXUP1b0rt48UWqfGBiIkTNUB0zN9heA7GyI/ilo1Ga8THpN
+pha2SLqNB1rMWl3T9fRTsu0HGKRHZobhzGi7zJsCAwEAAaNrMGkwHwYDVR0jBBgw
+FoAUe90QO0rgyN1EhU6IPFqLzZkik68wHQYDVR0OBBYEFK0h9T1WA6JYJDOopjeq
+QZiYko4FMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DQYJKoZIhvcNAQELBQADggEBAJKcaDXNDhjePhSydqe+QrUBUS0YNqamRezwkiQ/
+NoKO8CMTNvta/bbq/tIYarPtac6n4d0rTuHURuCSC1l6VsruAWsNgn6Ja+G3nqeV
+MP8WM5XYIToIPHy8OMzCXfu04IV2dAuaX4igWL3hn0PXrh7JnrTwfnK5ytSbzxbh
+IWcFLpSqxL0XzEAfJz24325SbAyXqvwx+McF5UU34JHgEUQcvTUTXjr2Xp1i5moV
+68a0CjqYABdZ2pDpHAWoFzvVrcv7o93Y+/DbR+5dVpuN2184q7cJcoez/c7aSp8W
+A7R6Ggi+lJEic2RkktRRZTjh0oMM0ndj5c9Ya7CGfEN3gEY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1D C0 51 02 E4 A0 E0 B0 BF 9D 2A F0 E7 6B 23 E0 39 16 90 FC
+ friendlyName: Invalid CA Signature Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,AB5FA72411EBEACC
+
+W5xxITU6f1vDKkdkfxFdGDxGjjQPgqDQzeqA7LqNAtn8uc814vH8D5HzzMTau2HX
+M/NMlo21ewfEUKlm7VFKu1GLnTKS1gOJ2KQTg6/IUTx+OPPN5AnwFZsnsJ2z1RqA
+M3VZQPEofeODlNBTxujCQr2TR+F2pQd/uZCuiiLtY/I4YjYMu9ueyycgyhh9Xu4r
+UKqaQD/JYtSkW+pQelS+pK1FoHn+5wOUXEO+02cAn+n9L8/1ztSZalEZcpmEZ60O
+tXNhIaPtAVlMKRh9LP2kD35deL6I7VDEeqLrz+4L150w9mCNFEYeiHrr9EszeGf0
+KAvej45ALQqZhVTPhP8ySZvUy0C7bVk+eY3XWZ9BIevmIhoruZNGFapoSSyDbp0j
+FBXptGYFi2FUKQClSUAg6YEoHV8Sh/r4vWJBdhWbaiGSl2umak4kTE15tUdv6QuJ
+qWcEQwgAEGhfjm+fCJ6Pf2KA6R1Ywe8TulmCtIjEPk6+jTQ4AXEqfw0gIvQ7STYj
+9kwTeYvtYODk7QHYBUEH30IQKTj/KhDq2Ld8/2V2GDPsj6zTzEM8PW6UHZj1Ngj6
+14qFEc21iDRKhAiRjQ6G40mZVtBdONL7HrG6CKrAfsniEMXrdmceRCI6/mWmVUNF
+WQzQUbMUtFj6h8aemQhUUR+AT1MgzKhNQwSNhKiIjmGRniLEaZ4CkAuZyQzwmr/x
+GckD0Nho39EhoTNGHl08gN6yQM/1mYf4lQg0w6DZN2hazEplBvnn87b0BT0/Gji1
+WfVGIsiYqnhtP9pC12TQbQnpg3ICxZBKLsrKxIdnMlwJRidKhsWzWRuDrwa9f4ox
+6ZAGYICdaaxur2xwWk3xQrzRgSJOqqFh99U5VGnASr76OoX58yLnF1UvB7nnhaKK
+GOKVhgRnIqB68Vr7FBAAy0qq6o2xQZD8djMsTHS0Oyl9bzy5Ov8eW1+1j0uREfsg
+Z3rGVxcnPdQSvbN42xHF2qJ4P9IrMZB8EDfVLcfuUKAb8VsT0eN6gR5OsWaOlHTu
+C+DHXaBgp7qeIFCDKZYdj1mOEhSoEVI7h4IYnrqlRAD7U3sYNNMaWLiZnu6n6Lk2
+ECLUomojHHljU4EoJYGVft4cDy5uijcZv25x60wJM+RnqYr6Xt0ckHWYLwyBp3kW
+YSlRJ7olV1mJqJp9FekUGcbR09KnOtksqLiaS2PSALTU527bFAVeHZCAPtk/7T/A
+I/Ek3TTaLSvj+3gA9u7Xdm82w/qxfn2H0snLaCyU8LDT5Y3JHD27gmCKBUqVAAHo
+qzSUOPr93j5LsXBRx7mcZPESjz3MmxZxYovo/OKtT2JDRGZgxU9BjYHpEW8jIdna
+qpXyvCLaz7zd4zSob530Wnhg21X5KKOhsatypGOkedBDBoGyMOOJyIycyhloHpCc
+GVti6QjBrx8tzYjJ8Zl6qmyn/NFftRK4S1+z7Hor68rPC/E5xgKWGXIR1BG5X7iw
+JTmzqVTLhdKDW5J2juyKMRh/AInLl4cH66R226yhzka4n9XR8uPGEfAsj/0RYkHK
+927AA61HiHcggeEhyHxxt7xxNQKCwJyy7XRWvHd+h8XVaCB3PDVdgQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5.pem
deleted file mode 100644
index db8f821780..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Bad notAfter Date CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBBTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0wMjAxMDExMjAxMDBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUQmFkIG5vdEFm
-dGVyIERhdGUgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO8t6F1gCSiD
-eAh0EXEEP1RGW1G+zM3TmSeKbm0GLmH4SJp7HbsjBab4wtNEVlOrYMG5phm3dro3
-P6YEmVt0q2yzDo8OkpfbYwJEy6e/vdjF9itss2yajms7qA6xPbggpdYElK4y/1Ei
-o0+nUli6dZQpEz7/V5tSk8S3zvh+lJ+jAgMBAAGjfDB6MB8GA1UdIwQYMBaAFPts
-1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQtDCY+YSMuNxOnyukyqVHgELUF
-MjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
-EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAMDkUbWtYhitXM+mGr3TBaTgM
-IlnMLUMsqxka0EQ7fiEaLtVsOD8CjMRKeNcWo6ZwVfJk7EDOnV4+E1TlAzNp1m9z
-rHB+fc97XJlIaQwOF1WMnjaZl96TO5Tb8FIaebsIeknz2m8IhfZ/EuWPfqs37ZxQ
-b0YPNilIGsUSrT3rTBk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid CA notAfter Date EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=Bad notAfter Date CA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFEJhZCBub3RBZnRl
-ciBEYXRlIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYTELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTYwNAYDVQQDEy1J
-bnZhbGlkIENBIG5vdEFmdGVyIERhdGUgRUUgQ2VydGlmaWNhdGUgVGVzdDUwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOhmxDd5kdaDqSlvran3+R64X7ilMaOb
-DINojoBxIW3XAxrXD3TFdV/twdn97GoxEkeh14g1W9IV7RTwfDoVf95tjNli7Zsg
-ye+NVj1gYVV+DdMpxy44biOW6s9l2wRqNqoeE1AFSj2su1PgamWIHiGo4BQkcE5F
-bMwHbJCR8znNAgMBAAGjazBpMB8GA1UdIwQYMBaAFC0MJj5hIy43E6fK6TKpUeAQ
-tQUyMB0GA1UdDgQWBBRsW4S+GLLshXYDAKY/yVcV2NlPtjAOBgNVHQ8BAf8EBAMC
-BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBANJW
-FdT2Ss72xFAtOuGm5EoRp7tP32SI2iyLmeLRi7YeIo/95FVK6xVzjZ8zT3pjyKvx
-7qe2O/cF9SyQssnebmTqLJQxCeWHWzt0BpbI4U9GZJF0vEeqTU/psLhr6p+20T6R
-XmeWECYyRGe0Wmndt5GJ74PBYrUjR5mtDojhKn/o
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Bad notAfter Date CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:2D:0C:26:3E:61:23:2E:37:13:A7:CA:E9:32:A9:51:E0:10:B5:05:32
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a6:dd:d9:bd:87:0d:1d:95:02:a5:1f:92:e9:dd:bc:1f:16:df:
- b4:5d:31:d9:76:6f:06:90:cf:da:09:6e:f8:15:1e:bd:41:d6:
- 4f:a3:f4:78:a8:67:96:1d:ef:8a:c1:77:e8:b2:83:81:5e:d0:
- f3:53:36:a8:78:39:d2:cf:eb:b7:57:e6:13:ac:33:87:9c:19:
- 64:08:a3:14:5d:71:79:b7:10:88:93:44:a5:32:79:85:fc:fa:
- a5:a5:81:d6:99:60:2e:a5:2e:2e:6a:60:41:29:70:2a:27:b7:
- 9b:52:75:fd:9e:06:e2:80:f6:6e:0e:19:39:75:9e:a8:70:b3:
- ca:d7
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFEJhZCBub3RBZnRlciBEYXRl
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBQtDCY+YSMuNxOnyukyqVHgELUFMjAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQCm3dm9hw0dlQKlH5Lp3bwfFt+0XTHZdm8GkM/aCW74FR69QdZPo/R4qGeW
-He+KwXfosoOBXtDzUzaoeDnSz+u3V+YTrDOHnBlkCKMUXXF5txCIk0SlMnmF/Pql
-pYHWmWAupS4uamBBKXAqJ7ebUnX9ngbigPZuDhk5dZ6ocLPK1w==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5EE.pem
new file mode 100644
index 0000000000..3b3758fc03
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotAfterDateTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 71 89 00 06 55 9E 49 96 C1 F6 06 A4 66 6A 0E 6C AD 32 17 AD
+ friendlyName: Invalid CA notAfter Date Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid CA notAfter Date EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=Bad notAfter Date CA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUQmFkIG5v
+dEFmdGVyIERhdGUgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBm
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE2
+MDQGA1UEAxMtSW52YWxpZCBDQSBub3RBZnRlciBEYXRlIEVFIENlcnRpZmljYXRl
+IFRlc3Q1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3CcZ0DqE9Pw6
+P0I9jfc3becBcujw8y+uEiSGI2WWZvtY/5cEnif001zkbDJYCCXsaegUoJeh1/uv
+GL+wFCAw9ZKJ/po3NzuLSq9ER+jZrkjQeskhs1TWFVAL5Z1HphBRruutpMB31nhx
+P6MCP1ZS1wxbWwZRTtg2yINKqX2wRRGTIPB2dWa5Dlv0UL7DfypPfQsVoQF6XZ/7
+X6yWyYmRsiL9OJRh07ExsVAQFALZ/6tIXrWpgyQWRJInygoNwmkSTTc9gmetr53d
+5e0W/EPBSr8sCbmYpDI6MWJsyZvh16lAc3Zf6sx1PHJtaZ9tt6/WJ148aLV0ffUS
+gnvHrdBjjwIDAQABo2swaTAfBgNVHSMEGDAWgBQsDv337jzzpGbs5wWfiLPiz3RG
+2DAdBgNVHQ4EFgQUc086TbYTKqLTmNpBE0qlpFjKkKMwDgYDVR0PAQH/BAQDAgTw
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEANsYL
+aZkskh6vUFY0z42Z3HqV7ewk535l/Zcqytm9JFoUtt4tX11iVVLvzKRzE1xRZQrI
+1SIvfCSexc+vwMjw4bIRV8PSytQqXI6R27RERT5RLkpSBFfSXYJXrl6z4txFcEGD
+ed9220tfXUDOt5lZ/V9qlvOKInpq1gKj2C8mknHDYm6643I4Sefi+Mw5M3ohPfEs
+8y1AdEwow02R702NYa2dvBDu309BpjryhYrRxfXezN2l0Yc7z8Y2bISXclx3W2dh
+dqeABI571GE28EkfhPbRKuW+yQOUnjyMqvik6y5A7jtnFicTeoi/IIT8COWEg7gE
+/6N/kRUqqgeRucK71g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 71 89 00 06 55 9E 49 96 C1 F6 06 A4 66 6A 0E 6C AD 32 17 AD
+ friendlyName: Invalid CA notAfter Date Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7AF8507B66BE68CC
+
+c+7/e3hmItJX4kdcx342E2hSdfXjFdUSN2T7OGDruPUtWjolA8t00FXibbhk4HFn
+J/PB5+gdQaouG63l9AIHGpSjIfc0djUVi+fr6ceQELkQ0JdsZvgPLD7OnRIN+GiH
+GGkiLschzGxHi/+GvhpACDSgPOhuOkO3aOaO3RfQxLmWNo2Ufpulh+pmii2mAcwz
+F9IblPWkFHj/86VQVxWC7OF/XnydfZA1QBTGOp8XCnmyUErrcXLqS9RsaTupxpzs
+MZINtHcluFL4jpoNDzkgmxts1zfqSRJAbcwzUd3OSPAYXHg5/NPt2PGRL+LL54YU
+D8yczY+FGwlVJcAJ6pVv2LJ+Qah7ynoo265+wtPX24WpdoecqPoBmYaIYQmnPAay
+CAn5Rgs3sjtfmb99/P3lOUsmguKbJCZFmnGEDzZHBlKDw2Q5EpyLGXV6khVsmaUC
+/+8BAeUkuHwA9tHYPHTFnlRSlN4eDVavE6dkOWXrgE8zkbMNTfxqi/UG0kdQR0RA
+P1ND+jLEwst5fauzSIIsTUwwB0M65fIdm5syQiLuyV7B5BwKshE4dbjFRSBMBWiC
+pyA+eEjuVwn9AoZLcnWyQ6nVtRIzx6YeP3B+SoeDpboTtXIlfIveO10bffctE2F9
+hsc9BXzWpjSvqF4uWM2dDnCTOhXDymOlynZQLphTChILPJihsdWtzIG6wtaJaZU1
+ucWncCwv+3nx8L5cH4PXHvn2gkCeHo/6E8maZwwVpfOWcc/azhS1F06jvIrN9DmZ
+wFBve3317ehzYAc4TpACqUqtI9oZusH84R2HBuATBBimzkBJjkMLGJy782MJQQf4
+P/uJJx5Ov2Op0YfSYrHxWlEqLnpKn4gLCzro7sjwbBp2rrZ96LL8qIxcOzisXz/t
+XYZiJS+PZsAsXHCBUf8UJ2Bb31Fl9HSKXqIUL22bOOtyZxyeZR57bZGmnsfYmjck
+GNPa8ZRupbYDCDiCPWA4cOiiSvqpPpr0ABYptZh2KkirQJ9kkU6CLnN7wjGCPJTd
+g89MxnUWF/FjdTcD8URi8oJ1EVMi28BqvYNLBtoG+oWCGZeejSPOJgbM4b+5gLBq
+AJqB54BUX8IoIW0So1AUwj1OhL5vsFYByNiPMe+suCLLi7KrljqROMWtavgEKxcE
+7VZEalyrUQ5kW5ctZ8TVjW58nRBgP1oQRaspqox5L6RxnGUpGlI4PU0/E/HAKcFm
+v0XMwoG2+03Sfa+H9gXjsjP2C5TR8RVb+AqsKKMH3FczH3h2mLVran/AQe72z8Gy
+h/LF4GtN/1W4tDWX9WqCpWzdhEt67mA1XjDtR3XmLjOYXnS1gcvcPDHVltfUNKYM
+MfjFepzaU57WmCy7o7LgwsP3qkhS5Cb8N37hyhCutyASsaQ2lM/AQu7SK2Lmwanr
+tGIt85QmIiSMuamLDz7RvnPQ+AaRwx7MRu9JMiA2ck1Saa2mdlHE8RDF7WylxSQ+
+91KDyN1ea+98COzfG40/jbIuw5uJyWV/SCsz/Z3WU18CKBdfRris+uRJRT99LIMb
+DkQPq+iK7PTI6bxDVCjUmXvv/Rmn8C0tnskXDMRP3zwVAewg4hjluwohXwUr5QOO
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1.pem
deleted file mode 100644
index 6a9d14d41f..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Bad notBefore Date CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw00NzAxMDExMjAxMDBaFw00OTAxMDExMjAxMDBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVQmFkIG5vdEJl
-Zm9yZSBEYXRlIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJp+RthgxM
-5Y+NQaGv+L8CNjnEejXyimG9JuXmo6Uc6ZjMhYgIlr3iAA+dcZRCJhsJxY7RXaS4
-q3rRLSR7ROQdjSDNbuGXRht0SGe3MlOoIJEqFVGWppp3BVY4GUwN/s5zmgj/vE+2
-eCwl96Fk8NWIm/qvugmG7+bvAy80zDvMLwIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUHnoz+COKGJwqbE84ItXL/Z2Q
-fVgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAJpC5ygICALpvY5i3Q5a3179
-Ao05EA6N8ZKZHoS49lok81lUMy/MLGY5zQlggicV916WyTdDd2CO8q/lSCMTRO3C
-CrsU9kd4w1V1J/OnfYDuHoRIH0hqowTdm6bEnyMhuq2YnRotAKhkX2g/ekDYuC9A
-Lo8Ispl3HslMbhf/mhGj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid CA notBefore Date EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Bad notBefore Date CA
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFUJhZCBub3RCZWZv
-cmUgRGF0ZSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMu
-SW52YWxpZCBDQSBub3RCZWZvcmUgRGF0ZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuT/PBuMdSN+JtQHVYA67GVmByJJV
-4dw76fphkGkaVX0EhLBs1ZK0jH4H+/rGlzrmDGTT5k2xwYc73ZJOkGDq+5EPnKy2
-0MMuiU34oORcfElE/rYu4tqGwh9aARFDBpjzBNqCNMTR6wD5uIJ1HpZI3KfyuP1b
-sX5KW83tw4qRbmsCAwEAAaNrMGkwHwYDVR0jBBgwFoAUHnoz+COKGJwqbE84ItXL
-/Z2QfVgwHQYDVR0OBBYEFGl/WT2zZWdmw1t+EsACdTdTWeWwMA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEA
-bf33IqIzT3eBs8IJCqw6hFy40WjrIDPUgfNMdPE02k+Z8/0y+QCczqm4PXynRsyk
-Zrn38tggQf2IVs/q+1IJsZS+3FWaj/iucO3twNWqPGqq60uc0xwpRhbIx1V8s1Dt
-1Jh1zD4+KU9o+ai5aN2ErGWfCjBpIlFhwI1XXT0NLKY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Bad notBefore Date CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:1E:7A:33:F8:23:8A:18:9C:2A:6C:4F:38:22:D5:CB:FD:9D:90:7D:58
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8a:4b:5c:e0:02:33:0e:3b:5e:59:a5:2d:7e:5c:16:2d:22:fc:
- b4:11:aa:00:7f:9c:51:f3:38:85:a3:84:33:3e:68:e5:7a:0d:
- d9:e1:c7:6a:f9:48:cc:f0:ee:0c:c8:15:b4:41:b7:a6:20:2a:
- 9d:68:8e:74:dd:b6:ee:eb:03:ae:fa:4d:50:c4:80:e7:7a:6a:
- 0a:0e:eb:64:ca:a5:a6:64:e4:98:96:75:f1:50:9f:c3:a6:c8:
- b6:d5:b7:64:7b:8e:ce:40:f2:bc:13:1b:16:52:4a:e5:8b:22:
- ae:9a:59:a9:e3:a7:44:0a:8f:92:b6:15:76:cc:25:f3:c7:a4:
- 1c:f0
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFUJhZCBub3RCZWZvcmUgRGF0
-ZSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUHnoz+COKGJwqbE84ItXL/Z2QfVgwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAiktc4AIzDjteWaUtflwWLSL8tBGqAH+cUfM4haOEMz5o5XoN2eHHavlI
-zPDuDMgVtEG3piAqnWiOdN227usDrvpNUMSA53pqCg7rZMqlpmTkmJZ18VCfw6bI
-ttW3ZHuOzkDyvBMbFlJK5YsirppZqeOnRAqPkrYVdswl88ekHPA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1EE.pem
new file mode 100644
index 0000000000..832f36523f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidCAnotBeforeDateTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 85 27 76 BF 51 D8 74 A2 97 51 FD 88 33 89 7E E5 84 06 67 8A
+ friendlyName: Invalid CA notBefore Date Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid CA notBefore Date EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Bad notBefore Date CA
+-----BEGIN CERTIFICATE-----
+MIIDmzCCAoOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVQmFkIG5v
+dEJlZm9yZSBEYXRlIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NzA1BgNVBAMTLkludmFsaWQgQ0Egbm90QmVmb3JlIERhdGUgRUUgQ2VydGlmaWNh
+dGUgVGVzdDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8ENtBwoEZ
+CsDl8JmmxVIgE7Oxt2NxKj5KrXslioWozKJzjRKKK1N2jHF/RHEmzFYoolOnNMJJ
+gIFFYSeAeJshYirpGm9mI5xZ9l72ZfaxtA7SA8m2UhE78WwJJ+oa82CDIiqoOCEm
+26yEV1M8OgtFFu/g3by/PcknMXXLd3C7zYPynO/ExnHUfiPfTsorYCTEPqr/p7Ds
+yGjTRwdNbF9diPObop4B29TZanZ3gYOVBOTn9N0k1oy2eLF12W9W5CwY+FgywI4R
+ZMYQHNK3XNde4KuBoUxgXdAGUBzL/Puz2LY3Vd+2AjNS/hl3i76SKKwK9VrbUkXl
+v0EVWvc00ZDJAgMBAAGjazBpMB8GA1UdIwQYMBaAFGM+vBqe+6HyWaEvS5X+5t5W
+uIZAMB0GA1UdDgQWBBSp+Lh7Vm9xnfn/IdnPPSVIJfemjTAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBK
+OJZjmGp4sWnBQ541UKsMzBO4X8+YGKPA8tGpC/ZjLPG/G7zwq9IUaKekb6KZ3Q17
+KeX8YwORze2nSsMzAkED+rJKa8Bgx7+OFBU10b5qTdVc0Ac9PCDhhq9CGa/sj/yv
+ggEXLKq3f2BRnDLKdWO20hR2+FkOrmqtDx4q7wZQDtspGFl20AigOV83joWKHPcB
+DtjS5/N8zxeOzciNMHhxy1Sv6A9RCUw95ujhrs7c6WM7yXqWbsWhF2sT2856/FIH
+m+Hl4rSmu2MMsrZbcWSbga3AbanFdDX2wsccdmsqAPBzYGpJbTdR/s5HXnPei4fw
+PY7kH4Kc9zHuOqFxkL6k
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 85 27 76 BF 51 D8 74 A2 97 51 FD 88 33 89 7E E5 84 06 67 8A
+ friendlyName: Invalid CA notBefore Date Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BEED679442F2FAAF
+
+DS4CtEvKIWfQlTyjruaWDz4w7XphOaMNg5RW4vKNL/VJ4D7UKOH9VqCPFrrdsybI
+S2BMpR3vwR84ZKF2ZOOjawzT9CC8ZFAjvCCnVJgetSNI93bvbrM6C38wwro51y9N
+P0vjOF1IaK9JZ/XPWG35Q2h09Z4oESK7HZyxD9FpiCueNW1wM5FQ0kGQdhvLWQaA
+S65EkfZZ1dBjAMywmxjsFdIYU51p6kLFhvh20p7ev+Y1kkwLiYB3/Bbo8z8Ktotc
+1bPC9HS0tjDxRVdg91uKto31VRRK0Lqi2/L5NsInQtxgGWkzxFgbM9BsmZ6WxJn7
+by5FvlzmNvwQZMwIE0XH5y+35RCeRY6Iy8FjbRO60567gh73b5gM8zD3C85gD0EX
+uZFJ3nBn+AaUaiPi99y0Vc+JKJmfVmGQ007FIQgjdlOO/XqPoanmzagfETI3tqgC
+blvTsK1eFnXu6INi7KkxQRkGqYi8T1LqcfKXF++woL6U8d5ypovRwtGWJPKc574h
+xagG5n0sw5/nTPH1YiK1KpP7/VuxRCjuWG9kQ8QPp0HsW8pRSZQnOUR0ySrRE19A
+SW6jO/1QZf75WkQFtGVYrA0GDfVzY31d8qtSv3+kcp2hkZuudqoEpR8TrZCgoUpW
+6sWOKEifzXTO1r3Hw9iPtP58BHDX+/Ojv2B+u8Jocv8MMicrxVaiEGyOtttkZ63Z
+uG4e0JBkxhWvztDP83/BtWRxm0yKs+PXntlIEz25wg79vzcDNZg5pP3/TW8GkrWW
+WxO4J2CzgVNvrWih8W5IGwfytslFhzzkNJRS3kY7CRT5VSWHu8pCG7scN8Vdia6Q
+1yjcxu7VwQ+lU2qbHPQAmbUqDU+F/Lq3SmMZ6fN9FrYPPoxAHRH9d+SyA9TyJdNQ
+kyxtpA2jLX66g1gIcrQGeOSIEKgWRi1XinUaMMRVeHmrjtYyEmKh/ydD+bZIDueN
+Lwgv3Gxwmykhux27PPo2LAP2Ep9+O5TCpDHz95mlpQrH+e4/up/x9ZTXCTMzp+tA
+YJ5CYqijDG/yOL2LPC50AFup0TIcF7MUlDMOrAxkZpjxJH9SeM6jM0voC2eASuQx
+9Y6ZWROyk8xNh0agvY/iCkjC0ko2hSANEDAE61+JDuby3kzk9s0XEtTw/c7lB1av
+dG0ZjaHcmlLrXpa97fdLVl5p09RU2mXkI147575EN/7odJFWPtbynSDVQpHRBtwB
+6yAR1nU0FUyl8KbJ7L9jbnPKPVqXsHSta2tpqNWCMN36d7688lAs0i5tP1vVDkxK
+LdwJSh964kFI0eYhrqyS08YIlk1x/HWQ6O+J/+Y4TJlOT5mkoJePzmdlBR4V34Te
+tHdbuBk4O1hQvw2m9WKNKuxgb2W3j4AIvc0ZJRJp9yKLBcPQRJroMeeB/kjPfGG8
+Qnxuy4ZRbhPaoRuJllTwunPc2m7ejbHr7yhJTEpGO2eB7YXjO3dGMMwIh1VZ9y2d
+Vdp5MJzNIofqXBfG1JOMQTlLkInZAAP6RN1PklLa8wzuelUIaPsIU+EYUdyvWhdH
+G2rOcQ8OhSZd7DtoSCqkjunKF3R8SwpX4aK4KRIxdg2L6cbLV4ZMxQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31.pem
deleted file mode 100644
index 732af1b50b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBRjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIEROUzEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKF4cGWB
-eAaOHCGkAPlmkE9/9XtvEpanIGNf1g0ab0PBnZR8ffY+IK2+rwOeMVtfXmJbaxi/
-Z70teNn94XkPXH6Pmz/pL170Q96CasAsPU2uQC4AtNjkUSeFbSoY7Ul2NaBYqLrW
-yQ7O3jEXdX76KQWqYcihAq1Jw+AEruMq98WrAgMBAAGjgaUwgaIwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFHXnZ0cYCavxiIjbno3V
-F1KO/HN4MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoBgwFoIUdGVzdGNlcnRpZmlj
-YXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAzUV5anoiOD8wQQnetIFcg5wLnNlr
-dPixWje4q2JQcPnqZk3TW9O0GDtWHmZwVoS3PixQlJPHZGvkliTKM9vO7a8J2FDl
-/ZFRNrm2rHFjZxygk+UTwj+SI4CO8kmtSesvV0ViWwNNyfOV/nmvBjqy6pEbTnCD
-pax2/2P2ruVALCk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid DNS nameConstraints EE Certificate Test31
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
------BEGIN CERTIFICATE-----
-MIICwjCCAiugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBETlMxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQD
-EzFJbnZhbGlkIEROUyBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDMxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8Xm5JY/SJcUmQCDr+0GM+
-besWWL+OVllIdYjVus23p+8nx/r0PV4GQIKxh/12lQHPVKesX5OzuXUnlrFs0MNS
-hDKURr8PbBBD9pCKfwqTuDVGjcYNbxgOR7uCxwIWs62VK/yw3NqulTjTxjVba+Ih
-NDJEggvzeyEavzd9UoppGQIDAQABo4GbMIGYMB8GA1UdIwQYMBaAFHXnZ0cYCavx
-iIjbno3VF1KO/HN4MB0GA1UdDgQWBBQvlbhY4sw3ciETxMClyRfo7svC/DAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMC0GA1UdEQQmMCSC
-InRlc3RzZXJ2ZXIuaW52YWxpZGNlcnRpZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEF
-BQADgYEAS0/t3TgdHeRWJY1IdcR6w3gBMrNIweoAzXNnKgrodk3esABKU4lZrMr8
-UMW4sDbD1yNjLhGagmSj+1joyqYLTCh0NYgGbj7xS+zQfAGBdbctVpKYJ1l/pmxe
-CVPOHHU/YkBHnWMouumAnTpEcgbtHTMvsxQNef/pH9IcCBlnOSY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:75:E7:67:47:18:09:AB:F1:88:88:DB:9E:8D:D5:17:52:8E:FC:73:78
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 90:61:77:a1:94:8e:c3:62:6b:dd:eb:ec:3f:0d:e0:dc:1f:b9:
- 04:fa:e1:74:e4:5d:d2:0a:cb:42:4f:41:9a:a5:91:d4:2d:57:
- d2:6f:1d:5f:cd:9a:2c:24:5f:3d:21:9f:87:78:17:33:96:09:
- 1b:d1:bd:f9:50:b7:17:c1:e0:af:50:95:7a:9d:03:9e:2c:95:
- ef:f2:c2:a2:74:93:d3:9c:c2:73:74:96:90:b0:78:15:69:e5:
- eb:b4:5d:dd:19:4d:ea:9a:78:af:ae:a4:b5:69:78:58:aa:7d:
- 5d:9e:05:ee:a8:8d:2d:16:03:86:18:62:6b:cd:67:8c:5e:13:
- 1d:46
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBE
-TlMxIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBR152dHGAmr8YiI256N1RdSjvxzeDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQCQYXehlI7DYmvd6+w/DeDcH7kE+uF05F3SCstCT0GapZHULVfSbx1f
-zZosJF89IZ+HeBczlgkb0b35ULcXweCvUJV6nQOeLJXv8sKidJPTnMJzdJaQsHgV
-aeXrtF3dGU3qmnivrqS1aXhYqn1dngXuqI0tFgOGGGJrzWeMXhMdRg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31EE.pem
new file mode 100644
index 0000000000..7271d9b923
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest31EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: AB 42 AA 02 73 01 C7 1E AC CB 57 EC 44 91 72 EE B4 07 CC 97
+ friendlyName: Invalid DNS nameConstraints Test31 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid DNS nameConstraints EE Certificate Test31
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS1 CA
+-----BEGIN CERTIFICATE-----
+MIID0TCCArmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIEROUzEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE6MDgGA1UEAxMxSW52YWxpZCBETlMgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRp
+ZmljYXRlIFRlc3QzMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMWz
+PkxcjfrTx5HDvt3XZVNg70GescrEk15PleNAp9F5sKxnbKvlJXk9Ei6imacf6tqY
+GH4gtc0fdD/Tk77oT26I+Q6E/hPk+QvoFi5CyHEKa1EsupAWS+/yudrVkKCxQgoi
+43pTUFPVZf2OgnTyGAqR+n4EjOeFKCQbXblGQjOQm0gHXiSDqYgsAam1Hw3P/R33
+6SNSrs1ClBL6m2cLE36e5zANzNfl9ev0avuc2QS46XNteE+Dol6d6B0StjCV2CSi
+Ipl0tqvurU/fYPJsYFVVPt2cdHEmig35BY3R+A+LLyYtT8j565p0tsoFtpTxC07e
+FaV7CAwwF6qtUj0TpPkCAwEAAaOBmzCBmDAfBgNVHSMEGDAWgBSxqhfw48/M0qeJ
+poMH3f9u2gfjSTAdBgNVHQ4EFgQUcth3X+ns0hx1Nih4TvYCKoI/bXMwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAtBgNVHREEJjAkgiJ0
+ZXN0c2VydmVyLmludmFsaWRjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBCwUA
+A4IBAQA6HLry6wY654Uab5ADefymDgTAUI+zFlTB4rxL+zz5H01iwjyFOQDhkpWO
+yJLbj7Ncwr1AZW19zYAeJ9et3mWTv6assHW22CRecv1M/oSFGmNlbTUYS/UPO4wc
+rCOx4rAnTXwIPaUdzF88HVdGqlTr45sUuH9OwQDnPmb+TKLCkLfRo+TUsvBhzjeF
++tuaca3sFhLvw8hZixlySkpYRmQ2Ih+w16G2ocA3tfqSb4U+vhM4PAqeRP/E1i5K
+1WRY5ZTuSn2nMS3s+ItayivhPoWjMBa3+LIqvlZM1vB6ALREKt9ab5B0lj9IO3Jf
+SHQ4skVRdnOis7u2cSrdZnbCy3Xx
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: AB 42 AA 02 73 01 C7 1E AC CB 57 EC 44 91 72 EE B4 07 CC 97
+ friendlyName: Invalid DNS nameConstraints Test31 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,97EDBBB8B797E455
+
+5vqItS7ic0Fq6H4D7dklCCKzIo8FvyQsXz4LYVTLhRbBnAx5hO4oNNQB54+l0gpj
+zHOQUnJoexwy/3ozzhs/zRLswktS0b0gBOo2aiVnO8ypNuTFfOUuWt+lj3dx1UAe
+ILT5kGJjsI0wqEB8l9gZtm4042m1TaWuFTaMrQYWsb0DIU/Enf3XJmVDRwO2o3Sa
+jze7+pX+okd86ZHm5MAXSFPdAakWOz020sL9vt3EMue93lwP0kfn0FYJTnlJ5Qaj
+hez0VA3y17gzmT2TJyEYuI66wxLXPgYB5ppujH9DPOscQsioumiD2b1XhruXb9u4
+rcw8ppML7eyV/gB+SC0L3MkSBL7etxB9Is1RyyXh5WFgIn2Y/sLzLgWCxG67JVQ8
++Vfu/IevfQ1WwjH6JLLY6imBbNXyKLXQu9jjlH/IwixPzIi+LqjTcq26W9VBZkB/
+LOCmmO+t+x7LKUyFzeZ+sq5wKjVpVKV5mXni6FXKgmA0zbx+MK27LkGbd71ZEP/J
+bYp5oJqON2xKaXs+oAs/9KCHlz4VWCUl1yLxRN63XbhLtRc1xlQeSKoqzmWTQXdN
+xy6K+sutPJkLbmleAVDy3exyyz7Zs17b5Tk8yAUxdGpxnyYgNmOmjpZXVsxVLuz/
+TX2mAHAS0XHjT5Ry+oRwi6HXu0dGkpWxE6H96vhbQCg5boPz4aYj3acOqkXDQ0y9
+4LasYPgO6EE0u+tFtgQ4tHZ2MItQ7Lun6XFOMfBqAYYISwvrppNOO0VPd2ra/gd+
+1XVbWLCyM+C5HATHNB4unsEX9A1zqzmJeIJzRlwPUOgS3gSGULFoHjLS+Q6gzVIa
+HQqftYuiJ5oKw32UAHZK70WXbNd2yO9oOOWAgK06C1d5PDxe6y+eMb3Rr80upj3T
+OsFni+rOkX0TxT/3t2VXB0sxX7fw2NkvVnACV3P+udjqQcqHPQy0M4n5e8N4qgmS
+wnVosaDxL65vyRHrl3rDMsi0yCCBE+vJCvPPK2jmy64IUYsGi70Fe+K/ZGrQPkam
+0B6CNbF+DzOC8OHK4hZLMXhp5hwWSYmai3SMTJ0l366bajY24gN9KQVZ5Y+G1QCj
+3DgE08T3XhiMbz1wlTleQ09BmMUB4h+LPhSG3TdsthRCg6SBDq2eyUcLDU53XEin
+jWElYmxDV1XRTRHHhT1VBymtSKSvGwRZLFYhbTxWfpH7FgBxBdxyfeRLaoJLIsST
+ASKTuts+QcTQ2hadEmpg7kNZXmJ/Ccd4iCmiP/oV2P8vg7W4MkvUVk4ZIJtdNRlu
+L2Mg6wkr7Z8ENasEdDfCULwNlYFEE+AiDqgwl2Iw1fgVbize+eEFzwCNQLd7f8r6
+LlveOwtnUlVHqjDe/gOb2CuenWhVR2sNYMHImDMr13Hmxfsv9v/bYJSVd/jcpcfg
+1F2umrq10UPFzI5Lth9vWiws8AtJ88E7hTMJTRWGna2BHA/2Mvg3O5ggYacoNcUl
+sCFCA+hKCngy9c0PnqnXDLLtPT0HWIo4t7K4SQ2upcbU5PGrHYfitCIIjEWqLN/J
+Bjg1wDGNxsQ20K/2CPMYaRac1g4MXahKQWRiBWbq5asv/vrEJTmbWg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33.pem
deleted file mode 100644
index fc1e759012..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DNS2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBRzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIEROUzIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANmefIFU
-RUgrahNMyIfzibuPD5LXv1aF765kc/ROx4BQYuBUZehjaB0G3eHv0wGu5rSJbnoy
-Lpdv0XVvBKEai/K+9iIereljhcwZzKTbHHvAdhCtgImX/Zz/KZ7OU4GZJGkdcj9r
-e/szQBEqTWkWB7hT25WM4ghi5xAz1Tn3foOxAgMBAAGjgagwgaUwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFH6Q3Dvq3pzSm0JE73sa
-zW6PkuC0MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zApBgNVHR4BAf8EHzAdoRswGYIXaW52YWxpZGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAekwpteebcTHJ3RTTqNmNlRsw
-aSa2MtBlaOVNyWi/Qsgy/LO5We9Ahkq56VlKB4WTWCFBdrbbnZ4k1Dpgj+NA8YBD
-Ysuq9KofKqycs+alN4JOOMtKHzbm05wPqkhY1qbBFAUbrEm5felp5drbJys97mCX
-bm7XHTxTuImtWM4ESC4=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid DNS nameConstraints EE Certificate Test33
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DNS2 CA
------BEGIN CERTIFICATE-----
-MIICtzCCAiCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBETlMyIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQD
-EzFJbnZhbGlkIEROUyBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDMzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxL/NbfBumGy235WIg06BG
-/D3/nRm8g5DewpBeSbgEPD/1yljXiblJ9TItVB7HrbJsewZWk28/396FVXb69SeD
-rmYXPflrEmgQlCp6IT0axE+gS6zTeS6qCAeHVWGLLvKOx6/9j/xqw2zUUDb1kZTy
-IedQLQlkNsdE966MUxr7fwIDAQABo4GQMIGNMB8GA1UdIwQYMBaAFH6Q3Dvq3pzS
-m0JE73sazW6PkuC0MB0GA1UdDgQWBBTg13snqN9OjzwRLPdrP94IHHcERDAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCIGA1UdEQQbMBmC
-F2ludmFsaWRjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GBALVLczfP
-n/oPIoeyzrVNW7swi6hL0k/Hp4Ki4rB1HA+cXcuGMJTM1mnk7gLd9Mjjyp0Iz7DP
-82k+Kv+9+EpOWHhwkvAJVJisKGVO4NrUbuxGhoYggP+ig5gsuHAfCAlzLfzQgW+V
-BtejP9VrkYTGxKno9uiIjXfO/VQ9w8pB1Kci
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DNS2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:7E:90:DC:3B:EA:DE:9C:D2:9B:42:44:EF:7B:1A:CD:6E:8F:92:E0:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 02:f1:3c:9c:25:d8:e5:f3:99:97:72:47:d1:94:a1:f0:11:0a:
- 8d:ef:9f:4c:c6:3e:93:23:1c:76:92:f7:68:f7:8f:9d:d0:ab:
- 7d:73:20:ba:f8:ea:1c:90:10:59:01:07:c3:11:36:15:70:b3:
- e1:80:3f:38:65:42:77:78:95:79:6d:a9:88:c7:54:59:b2:52:
- 9d:da:5a:58:a1:73:1e:07:78:00:01:67:02:41:9e:82:b4:ab:
- f3:d1:74:00:8f:ce:fa:78:8b:c5:ff:ca:40:ca:88:90:ac:74:
- 78:41:4b:60:85:3f:43:31:7e:1c:60:bb:3d:91:09:df:9d:f3:
- 6a:40
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBE
-TlMyIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBR+kNw76t6c0ptCRO97Gs1uj5LgtDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQAC8TycJdjl85mXckfRlKHwEQqN759Mxj6TIxx2kvdo94+d0Kt9cyC6
-+OockBBZAQfDETYVcLPhgD84ZUJ3eJV5bamIx1RZslKd2lpYoXMeB3gAAWcCQZ6C
-tKvz0XQAj876eIvF/8pAyoiQrHR4QUtghT9DMX4cYLs9kQnfnfNqQA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33EE.pem
new file mode 100644
index 0000000000..98e9795eb3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest33EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 37 53 53 19 AB 78 01 73 27 05 18 43 EE 87 32 9E C1 06 7A D1
+ friendlyName: Invalid DNS nameConstraints Test33 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid DNS nameConstraints EE Certificate Test33
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS2 CA
+-----BEGIN CERTIFICATE-----
+MIIDxjCCAq6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIEROUzIgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE6MDgGA1UEAxMxSW52YWxpZCBETlMgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRp
+ZmljYXRlIFRlc3QzMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMYb
+B1v9GpRI/WrpcpiPQwAnQbViU0MATTXN5t8MypI72+0ExFrnmC3gPpZkImwXOlIn
+EpFA/EU2xNrc5+1mzC+rfPUzZ9W1xpM189Nsdobp7UP8laTGpeP1qB/5bYKwHr3w
+poPYnm189HfyTcVfOBqrb4w8SxyfZBZv9znzHlNayguKAgx+7v1IBrPSYz2dQKpm
+44UfeKpdRLfBYmfwtFn8fo7G+gSzLev19SdPiiTM6Mm/7c3wvSjPfoFChOmCDjmR
+hHcDC/Y3IOp9913OU6MyfX1JWWtCekDmovPzH9FdYvmYA4qJEP+RTHLG3Tjjx1MY
+rGfjZf+FnQktoa7DG1kCAwEAAaOBkDCBjTAfBgNVHSMEGDAWgBRGSJxCCY5dU3DY
+Fh7gwckYFTUKBjAdBgNVHQ4EFgQUqPuoi5cYHAfhxk4Sb8kAu3oLs1MwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAiBgNVHREEGzAZghdp
+bnZhbGlkY2VydGlmaWNhdGVzLmdvdjANBgkqhkiG9w0BAQsFAAOCAQEAL59qoRdK
+H5WO0ZnkKiOAfs0egI4Hm9xbC+xax2LVNHxtmsXa1ksxOgX9dMuJH4uo6XXzNqyp
+KbZ3m6z6g1lAsdfww1o7d+7EOIGhTNOBWhRZOxYe+XEWxzIKKgO7qPGffYbEhpM4
+HI+2QsGnKGP2iBcVWS22KE3O/3xRGjiSUff9hGsroTtv8xTbPBA93d4Vr36VzRp6
+noAywsV0iZt45Zpoo368aX+Ph62TqXCg/1+VERrG8OJe3+lWQqeBfKo05pwZhh7D
+Vi1VnGCLRptvUiwJuiOBksuCI6Uidi9vEN2DaIz5K+8mGAWn9C9Qjps/Kat9dHFD
+ctZ9Gd4lR1XzyA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 37 53 53 19 AB 78 01 73 27 05 18 43 EE 87 32 9E C1 06 7A D1
+ friendlyName: Invalid DNS nameConstraints Test33 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,42DDDCCC4E0E0812
+
+InO/EZ0bUhdxLdwVzylMQPQR9u4xMA41CFhQBlg8yS4ovqtRm1MVkKsVHOEm0VgT
+Xnez/9FZqk6KilG9MCXFGeQCbK3fhtIlRJMp4pft+7P3MpNYj09crslN4DqPWosc
+4ffNKCbHcfxYknEjn5CvxEmSwcSYXGs99n80jb4TNc9h22rIJPMxcA4JjZVJymyG
+Ym80H+9BKpgWgG47VWH9E4Pe7rsYKQNYlOEeK32xNQe/Ukj+/ANlPyCssMt1W6FZ
+1NVdme/Vhiwp4aYdCvUP4c878Yu3BcqWakw5JfKTghSiLosqu0YcqQGd5GATe0iI
+OWhANpFojMvJXeQdOzWL+VnSmqtMsixJ0l0DtiWJIF/PAA/j4Ab50yWUOoSrusp4
+9OWPdLfXRqEqdIL2GrEBbYd6AxP/5QG2cFq/K5oKpK4KzHWY3RhmWXy6rqD0VMZf
+y+GfjSUmrEH+S7oKhLPBH4Mq+iAfX8R2YfXFM3QCf8yhWQiOmUft2XDxq8BVULnH
+zLFZWY8WI6+ZgUAcDZGmN4Hki3sjmt6gGiI1CouN8wlrDs4doneb+GWyB18k4EmN
+8FboI5b1kjr//76kpIhAG7yIIDQcXS3GU7I1iD8wcjV3u0dYYnnsc9jcRnkgTbkD
+U8F42AVFdfC+nCKR9oKRBlqBnD97SFbneNcZS3PyOaEUY1AxeMPfbBXeEOmUBp/r
+YVYBNSUbIyIcwpe+gMkX76/pTZkaOnnzN/vLXnYTlW9Mbh0oNIpnAD+BAyT2dc0R
+LMUVlu1+t+RMQaBgDEiWw5jdHf9JRjYO6Lf8G8nNbZupbhGtkY+mAroK7MoPRGlc
+1WQkQD3P6Y31IEAli0iObCAS2MOLL75XPhbapja0KHiTX1QGWiY6JT1QTsJ5ZPDc
+r7ZtVHJRyL6omdz1xLKqD69IG0krmbjWZUq+aeFg1LbsEPX10r3yzaz12BMs0Gmy
+ZG2qA3GGiQMrh5toE0uWZCBvZCLqpM2GauWKF7R8Bsj59rSPtYpIpSGib80lUAbL
+eYB1NOeoPzQQOVRS+C2UiTGmZmq0ID94Vnb7vWcHVk3zLYi3sQ0XozqJ2T6vI2XU
+5DLzUqUW6jSnWDQA5Y93/Y5W3b8bdyxWKfTAKVBNjciGlTM2s2sk6sQie3/c8Gye
+SZ+HFnX1jGTROgprJvcFZTFUuVDIQx4mdIufm7IiwY4V/zJRiDTfybzVxDD6pr59
+8RTQNvZpggWvtwSM9zlxBGnQ4Pg5HWJi06xZsOwgZ8Pvve6TW+GgOlbVKrdUwdUe
+V8t8MMa/48rR77/xb5k2xI8uwWuxE/bpiYzUjpsi0ZPh/GX0ruNZn+hn9ph2thx8
+QYMHbNIszbBAY6FSZSuaOTUOKu7Jg2zzAR9rxYDkyaRbF431NRjHEIhS32EL6k2l
+98abtTqhtMUJ+Odq6B9vttvOBunGQh7ym3jiWbT54b9wFgVcHtu2CsPu3H7A/E9k
+5trrY8QKvcmyZt/Y57OQ8yDoYcVLG+6boI7F7c9IZWNDocF7gEV0/rEFwIudVRr3
+bxy1izO7o1l2X1V+/E0yvV21MY+0c/yrrO+n8yrK+wvy5xB/fns5eDhAyNkKByDu
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38.pem
deleted file mode 100644
index 7930eb4ddc..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBRjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIEROUzEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKF4cGWB
-eAaOHCGkAPlmkE9/9XtvEpanIGNf1g0ab0PBnZR8ffY+IK2+rwOeMVtfXmJbaxi/
-Z70teNn94XkPXH6Pmz/pL170Q96CasAsPU2uQC4AtNjkUSeFbSoY7Ul2NaBYqLrW
-yQ7O3jEXdX76KQWqYcihAq1Jw+AEruMq98WrAgMBAAGjgaUwgaIwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFHXnZ0cYCavxiIjbno3V
-F1KO/HN4MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoBgwFoIUdGVzdGNlcnRpZmlj
-YXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAzUV5anoiOD8wQQnetIFcg5wLnNlr
-dPixWje4q2JQcPnqZk3TW9O0GDtWHmZwVoS3PixQlJPHZGvkliTKM9vO7a8J2FDl
-/ZFRNrm2rHFjZxygk+UTwj+SI4CO8kmtSesvV0ViWwNNyfOV/nmvBjqy6pEbTnCD
-pax2/2P2ruVALCk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid DNS nameConstraints EE Certificate Test38
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
------BEGIN CERTIFICATE-----
-MIICtjCCAh+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBETlMxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQD
-EzFJbnZhbGlkIEROUyBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDM4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLztSKsWY+S4ZhmNgTffbb
-H8aIXhiw0mDQqoBzB40KjeMgX3OEnxCBBmDLNqdQtcMhlcKST+FbcFNUzrWySjDL
-UhFqTes5kgzTAyyIeMKHG/Y8b9D7mNuH3GJmtCWOCcajKBy7g9IuPRTtOu/f217J
-pqw42pwtbI+7PX2v2cTiVwIDAQABo4GPMIGMMB8GA1UdIwQYMBaAFHXnZ0cYCavx
-iIjbno3VF1KO/HN4MB0GA1UdDgQWBBQtwjU8JMdU3wDsp2MQVttA0RtaVTAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCEGA1UdEQQaMBiC
-Fm15dGVzdGNlcnRpZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAYzw7EH4l
-W8Vcu3FH96T5cE/RL5hRpoj2PU440l6/1ScnutWvY2WXwCAhO5LkkyDdE+a8Pv4S
-v5BusKldAEzFQy3H6jlDnK29Z9m/6RNIrskTys2Jqt04I+JWV85ZNVCyTu4px5iY
-SmR9uXP/4hfVB74Ct8bSrOBQVy0te1ZcR08=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:75:E7:67:47:18:09:AB:F1:88:88:DB:9E:8D:D5:17:52:8E:FC:73:78
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 90:61:77:a1:94:8e:c3:62:6b:dd:eb:ec:3f:0d:e0:dc:1f:b9:
- 04:fa:e1:74:e4:5d:d2:0a:cb:42:4f:41:9a:a5:91:d4:2d:57:
- d2:6f:1d:5f:cd:9a:2c:24:5f:3d:21:9f:87:78:17:33:96:09:
- 1b:d1:bd:f9:50:b7:17:c1:e0:af:50:95:7a:9d:03:9e:2c:95:
- ef:f2:c2:a2:74:93:d3:9c:c2:73:74:96:90:b0:78:15:69:e5:
- eb:b4:5d:dd:19:4d:ea:9a:78:af:ae:a4:b5:69:78:58:aa:7d:
- 5d:9e:05:ee:a8:8d:2d:16:03:86:18:62:6b:cd:67:8c:5e:13:
- 1d:46
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBE
-TlMxIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBR152dHGAmr8YiI256N1RdSjvxzeDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQCQYXehlI7DYmvd6+w/DeDcH7kE+uF05F3SCstCT0GapZHULVfSbx1f
-zZosJF89IZ+HeBczlgkb0b35ULcXweCvUJV6nQOeLJXv8sKidJPTnMJzdJaQsHgV
-aeXrtF3dGU3qmnivrqS1aXhYqn1dngXuqI0tFgOGGGJrzWeMXhMdRg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38EE.pem
new file mode 100644
index 0000000000..dd33413a94
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNSnameConstraintsTest38EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 48 A3 C9 BB D3 CD F0 ED F5 84 3A 8C 2E 9D E2 86 7D 30 E7 6F
+ friendlyName: Invalid DNS nameConstraints Test38 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid DNS nameConstraints EE Certificate Test38
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS1 CA
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIEROUzEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE6MDgGA1UEAxMxSW52YWxpZCBETlMgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRp
+ZmljYXRlIFRlc3QzODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKh6
+dMeji/U5K/ekBPo8CedDexJtu59S60Zbb3AdsoCF+t7mMkB7bkSY9aNOPXfsmBfi
+YH7FJFNzIwIoG0yHAB8qROxhbt4STVpB4c3XyqkWByLdHAzPM/+CAwX2ZtYTLF81
+FqT8KM7QmUMbjkcNx87nD+r8OQ795j0fAQQ3fC8XXgYVdDdfuoACAyYVgJplwLMF
+ejdjj72LERuDgiJKHy5BiUrtOr74ZRRoysDnX6C9cAD6BJjkrvFryQmCsnifit41
+3X5TWR3nSYY+93/ioiZ8kr+xDCtx6ODFs8DohTpue+SNnTW8w7QwtoR4gxnLWw2C
+3FNRWu1l++/VOOZEd0UCAwEAAaOBjzCBjDAfBgNVHSMEGDAWgBSxqhfw48/M0qeJ
+poMH3f9u2gfjSTAdBgNVHQ4EFgQUzkAnIqjWGiY7B5H+8RntUEbOS3cwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAhBgNVHREEGjAYghZt
+eXRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBCwUAA4IBAQBFZ1PNe87h
+xxEKYU1zDBenTJ4doWDxfNls/SC1fl9y4sV5gYdVvXMfMvFNpv3cuO9RdFhc/r7U
+an8zS8YA1bP+ts5EDma3yIuRkOAifEeE1ivPjzmEH0acOsfFmjgF5OBqS850KFqS
+Gtxa5YDgeuV6/GaUh+QTnkweGcQau51QIalB34UMxmG93hsNI3M4ZxPAiInJjb5n
++XKyQBWwAhaPhGPVbLIU0BtnyafxIs3fkksxFvp0TvrxNoDKmyGn1xMPf66rKgPV
+ziiayHvu9e8uhwEjXmugCy0T5zxb67CVVgHofZZfphlk99gUzeqr0rxA+7gPsoVt
+99WV0A+bbNk7
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 48 A3 C9 BB D3 CD F0 ED F5 84 3A 8C 2E 9D E2 86 7D 30 E7 6F
+ friendlyName: Invalid DNS nameConstraints Test38 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6E7BE2BB1EBDA90D
+
+/3LYRb7V6mLvFHL6h6V+UcL+eHtdgcQIYRfMJnf9duANOgPmFcASfUGnwWP04Kzz
+cmG9hi7a5mHX1ZMLL6r5xw/TI+ui15RGKL1QqJKU/bs0W7A8Pv7fJPXIkRyozXvo
+qk4Y8oGUHYFGZ4CSNl6B6MiBghjHitDxcYq8HSiLpuZc0eoRNvGx+2K08tz5e99r
+69w3sRTMrjdwraRuH2I/KUVGd6zsYc0Y58EbimoakEuAmU85fQV5CSmFJrxY4VQ9
+W0EHnUMt6ay3eKe9CpdDVZL0REjaNeBA3wm+aD8o2ajnZgHZh3q/HTTAn+05x9mY
+bGzJE01HmJnqskot8RWGFUfgcIXFOH3I9w3gF7niJrRBl1IjXprZlPAxEMdas70w
+WMI7ereIJbe1HOYd7s8B5TZXhJr400rw/KkcPFJaYRTRPpe0k7R+hxzVI+o8zDV8
+Cq1/GKENTcnI9Y1FlrH7yt5vLo0nJD+jXhbj6etgshYQnfdyNs9qEJVftaYeKnGj
+C10l2YmsLrn1F/OtfDNUYIfEPw11t9PNxygTGBmOcZ0rCsPcpcimdWh+qWnhjcYr
+SqanW0CZj4RKhE0R7zPvUbBGkssGu165NkPSyTDLrwQJtoAX3hjPuJ9R58Wc50Cy
+fFdglrp7WhLJ3IGTlWSv4TbLYjQfrSVgwHcUnnUGjkK4Akd/bxNKFq7hCHosb9aC
+oiFwRuIPUh9Xk7cAhqL3ELZpmvHUMoU8KzXOu0zL81C5J7j5n4w0/64Ih3qe3MRP
+bLm9fyOQU2dNc+onffryZF7BhHOwicV57GqV2awUUGqSln6g+CGcFOMzvTv+txr5
+Gk7mjIoIM2Cm/Y+kRhJkKmAwystZMnxVJfauSO0uNCtOuU/ay29br7V4mixZPUAL
+xTF+aRlYQGsH91UVkAJZqqiUe4ZjCKuoYgahim9UMViyq7XHzCq9tvfMLTHT9Q/q
+NPbzmqXcupL2/o23dtPHcF9YBTvfZ1bFdJPianLBt0LrC0Rxz0E3t5glt7tPfDpf
+uFmoisv1/APxyo5m796LzJg+tYl1HjlKEw+CUEZczmuvCvLh5ChwofTGmg/cA/tw
+fMjkMeFBmd1Hgqf7+q7v4wlIZwNnINXPj6yBqTX35TTxEaotlnCD9IJ5yfQsoEEl
+0qPPiLBKwUDUK2GyA/+jJMOUTodoTc+vuFHngdrhQ0Y2y9gwwX/sy8DcgIcGfN/E
+wGZLMoaI3Cz6q6JPg9su+gEToivrWwJE9ESgOmBMPa2lguBU/4OKkYcmtNeNfWeZ
+Wcq1UavyfhJ92ybnEXHJnTYSDixbRQh4A8ghK01ES4LVGK2Bb1dC5lc8DECo+iLw
+ogpKsVPYjbyeMYq4AN/B8qDP7BSm8ejQ5yTy92HouO1e9rc7/9LFr1M24OhsTYTr
+ONzxGwxf4joBPYyuJQ4Om9llVpLEbXNYeuotga3cUnshAc/e+Aj+6pSlY16gfGsb
+vUHEKa24nvEaOD4Tan7ojRg6+dcgiG9OPLZb8gCuL3sU1jEecMNzaq63UDYmkokC
+2JXgDG9UngFxugmBrhhLKHm2y6pVtRx4DZ+ZIK/wezyGPiFKvNeHpg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28.pem
deleted file mode 100644
index 18fb09781b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIC0DCCAjmgAwIBAgIBCjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBqMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4x
-IHN1YkNBMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aIkV7sYy0JnIQ6
-oLcZr4T5fsXvU6SzOxBfPrtNDpq884ix+hP3zDxAwCSO5mU0znQe9s5im5Mf9yKK
-0FIXOAHFwMb5M5mAZNwn7Tx0XYxDfBx94lsMvJdBDCddmTB5akZgQF5Iir+Y52y7
-yiWRJM+ZmowFfoi5rp/PgkSOJxsCAwEAAaOBpTCBojAfBgNVHSMEGDAWgBROLqPn
-2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQUV6v4nCfI0vTmz2+qIAs1ZwSDJGsw
-DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MCYGA1UdHgEB/wQcMBqgGDAWgRR0ZXN0Y2VydGlmaWNhdGVzLmdv
-djANBgkqhkiG9w0BAQUFAAOBgQBlTO2ECGQPZsbXzVHd/rGejurHrD9MHfTQYJCn
-pFjAPq3wSo4qFVopG5gl9s4rdpNU+XvoY5zO8MVxTnfFi5G+y2CWZTG0iIWQmC8b
-ReqDdpVeAV3ictgaDyoU1ApdemyOS2pHV0mgm7vPYCx+17EXzFBphUICViSFv45n
-cu1nCg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Invalid DN and RFC822 nameConstraints EE Certificate Test28
-issuer=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
------BEGIN CERTIFICATE-----
-MIIDBjCCAm+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1
-YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMzAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGLMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRy
-ZWUxMUQwQgYDVQQDEztJbnZhbGlkIEROIGFuZCBSRkM4MjIgbmFtZUNvbnN0cmFp
-bnRzIEVFIENlcnRpZmljYXRlIFRlc3QyODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEA5P+v5wlPmnZe/uEH6HyaKnq85ORqBL8HNiSn0EhAtQNHISd/M6VJvcrJ
-YCdSaQbE+A61yEjhCfckVgjt0lY081fJsDvDU757lDPe7SLP5hyrVS+myINWP3V3
-Fnu8BeK5Lz4Ytkx6uvnfE73jdWSregNtKqtyQD7kyLMTFVlVXt0CAwEAAaOBmTCB
-ljAfBgNVHSMEGDAWgBRXq/icJ8jS9ObPb6ogCzVnBIMkazAdBgNVHQ4EFgQUDvHN
-oL4nbNoIN4BmY5QBKMupyFQwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATArBgNVHREEJDAigSBUZXN0MjhFRUBpbnZhbGlkY2VydGlmaWNh
-dGVzLmdvdjANBgkqhkiG9w0BAQUFAAOBgQBtZkdww8Uz1loAnrdjOhd30Om7eO4h
-Ph2kKsyLJm3aeptHUIKnAXrY4+drzXmVlzMcMK0t7VT0CMP2vWSVrzHyUXnGxpsK
-ZGKNRLzdCrr4sEVtsYjGvMK9LzM66kx1CFVbl2IftM7cVEgadA7RyfakTHJJAAQw
-by2klF/gQrv13A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:57:AB:F8:9C:27:C8:D2:F4:E6:CF:6F:AA:20:0B:35:67:04:83:24:6B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9a:01:ff:a2:5a:8d:4a:16:d9:8f:d1:7d:40:a2:bc:eb:6f:fc:
- 4d:58:3b:b2:03:77:79:60:99:5e:f7:f5:b0:39:62:10:15:8f:
- 67:ad:12:b7:a6:2c:ef:de:76:3b:90:26:79:b7:1b:7c:3c:25:
- b7:bd:11:82:78:21:93:5b:11:66:15:e2:e3:d9:77:e6:a1:18:
- 6d:dc:46:88:f9:13:7f:28:5e:17:95:7b:a6:da:4a:00:c3:44:
- 8e:f4:00:50:a6:a0:52:86:90:cd:40:54:66:92:30:0a:64:0d:
- 09:19:17:64:41:33:08:5d:c3:11:b5:ab:d8:61:5e:a2:60:56:
- a7:d5
------BEGIN X509 CRL-----
-MIIBYzCBzQIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRyZWUx
-MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMxcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUV6v4nCfI0vTmz2+q
-IAs1ZwSDJGswCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAmgH/olqNShbZ
-j9F9QKK862/8TVg7sgN3eWCZXvf1sDliEBWPZ60St6Ys7952O5AmebcbfDwlt70R
-gnghk1sRZhXi49l35qEYbdxGiPkTfyheF5V7ptpKAMNEjvQAUKagUoaQzUBUZpIw
-CmQNCRkXZEEzCF3DEbWr2GFeomBWp9U=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28EE.pem
new file mode 100644
index 0000000000..eed50ffe62
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest28EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: CD F3 00 7D CE 6A AB C7 2C 72 7B 2B A8 53 D8 C4 04 A5 77 3F
+ friendlyName: Invalid DN and RFC822 nameConstraints Test28 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Invalid DN and RFC822 nameConstraints EE Certificate Test28
+issuer=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0
+dGVkU3VidHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0Ez
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgZAxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJt
+aXR0ZWRTdWJ0cmVlMTFEMEIGA1UEAxM7SW52YWxpZCBETiBhbmQgUkZDODIyIG5h
+bWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjgwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC4vbpQh0jJq3Nji3nx4Sfd4a9Ek4bG4H6jLwpj
+rsy/shoK6yz8nnXe/w8ZSIYH/pETrz72I3kEz5/VI6rxHf9Qo+lqLURImkRhxwSc
+ylpDPcbu6LApCackMGAms8ocHu+g6ZELzg5ubrcfg7IcHjnZMdUjXqEWptkZf74X
+cDGjkJtpA1jJgvEiwSy5A2MkBRkf51/4SGxpN0tbnLyW4P9T4s9p0ZECanXijTK0
+px8Ln6lAaV8/mwjat4G1WzpMsiMKYkzD7dC4uSunEY+1+M0NOsiWJwxS8oIA8AcF
+DOzTjx9WV8xeofZeY3ZJQJyJoCI+L70s+/9dwHxeXVbBbkGbAgMBAAGjgZkwgZYw
+HwYDVR0jBBgwFoAUJ0nkBNlF+myYlGz87Q3DJFJtVUQwHQYDVR0OBBYEFK8MG92q
+3AJ6cZcpow9Tp0emF1RiMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwKwYDVR0RBCQwIoEgVGVzdDI4RUVAaW52YWxpZGNlcnRpZmljYXRl
+cy5nb3YwDQYJKoZIhvcNAQELBQADggEBAIZk5m0SIfQF5ZF59PLUTrwGaG3jiJKm
++IdyCCM2JsVcKiJ/DoWkU3Ao14nmJkyjAFG3HoYqap5lxKyWpwvmv9VzBGmvJun5
+v38Z6zVGWSAKMt/w4yAJBVWWaDKHTP4nfBBYX8uAKmAewlNxn4LjWuZ3AWKfbuqx
+ve0yYWP9wBs95PlW47j9ky9uYjwAgXX3z4XnG3NkOH13uxPI6ZjBCdacVuIKDVZt
+3pqzHcBT5FV+9JrwvPxnaIauRpb07aWopvcl8vUF5Z2ndZjtBIjAtlnH8AHo3dwy
+b1v4tBbIjYfNUSlCtBjUC2SrlX0AiAqzq0jPL9YBiT+E0VnjRaYHmM8=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CD F3 00 7D CE 6A AB C7 2C 72 7B 2B A8 53 D8 C4 04 A5 77 3F
+ friendlyName: Invalid DN and RFC822 nameConstraints Test28 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1D6AA7F606ABEB63
+
+B44Kh+Eawf7VN46/8/zrkiV2Nx5S/ABhA1JNcjIUoXWr1bsHOwPrru1/PZMzh2pT
+Xi+U5L0pAVLKGNxAzx2iyOEHQLKHNqmxLJ05kcn4edJYY38dmP/Mv/VobSmIFcQ0
+7o5ZSCP43dcSHCAtoRYvNfLRrWnaXkm4bMz5j1OfPSN5fu15F5HvAW84yd5WgGoI
++1d5dwdRrxtm0BYtdJqNjxk/zKsxAkP27Qj0YxaLZCEt5mMcKIqRvnW41k0vFDUZ
+xovH3/X+VeQJCJSQtibLqwhiN/16q+BLicADRiN6Tr+18nn7qYNjIPNBbGnYWKsi
+KkRx48nhkOa66HIqs3mPupQi8vLoYqB/nFkrT7kRwZt1fspbfUuSqWaGwYLbgwpH
+bTEWI82g/5emW21YXwIekvI13YwzQb0tXSJH8uUQENXqiWtQwJ2ke8tI/6sYqIWj
+CrDQEGX1iZmedCvuPtZpS1oPO70n+5RaKmBg43QP2fhp0mrCHR3zMof/wt6t/yUe
+Zs3KL5yp3pb00FxivqYlYhsBMwhc7LkBZz8auIsunXyoF6BZ9ZoHb2AkXHetQc/H
+GY1W0zpVWG1dFIrpQogNWtpZmd78915iepHXAHyl0cFTF30fj31Ae90lhJU3ivRM
+3LdqdnOAU3khHIIzJfEnFa1bP4860RBhbHoNmwykE68BrlOsdfpZ0DrcB4H6yhC3
+hl3DnJI+BARFWD4ApWkSNMbfYwFkHbcSebJ33k/bR2k0KjAIJYfcznVoPEXbGL8E
+5uKaqgTloQH8tCpPPd52IhyzMQBkqR3/Iv25jua2L4Cq9lgaQXoGYsxj0e0BCRqs
+cOgLQVahRPX8HJr9dZA1lyjg+0/usQAlm0GcpPqw/NZOFdGXyjxnPCXUQOxjSfSt
+PqUkTUzqUjK2SOKKxn4acil7O/zg7n0H9Y85rKB7pieouVen5du6Z824hZQySlMN
+JWEsjg4YbRVP6aqrU8sUpkXRyThJvtDA2dADGNVqUfD5k4UkP7XlNqEqmzXKZnXu
+S9pmo93kY7i0k6ebzzCurc5D3fg69TDcFREfXOow6Wo9VbP0PB+wo1FDrejQynAu
+4KaPN9KS5Cwv8SfH44T17VltAOuopHkZyLaFN30CyENyJksFvVGCi9UH9pLqQaaZ
+B1GU+twMzxG8uNwkhzy4Wen1D7PxfqiH35ruxQxRavodft2OXRCeq0Nemr9dnDGt
+wEymDDFVlYSdLgasWLosEQhnsgeUy5xdT06minlE9eOBuxA1Hx7tg5n0c+t3ulFT
+08nF7m0pxhCDpPF/RVEgoZp4eO2/4OUfNroGunAvNnL2zmKPMkZmREprfewa+q6z
+STCVLXjVmK97nZLjfZRPNFuqd17aSs9BMdGE6+eMCCXd612vAntzbKF5zzfQjlqU
+yHJ+c5h3VrYLxlgdBsZaMR6ymNk8KS4aKiZoSStplenXVO//N3+a95KOUGiqDVa6
+ZYVuQ4jxxmMFCK3wfvcR1PHE76eILoRH6TaOTKy044IY+/sE7+vDsDSBdEG4z7PH
+qQOPHsYzCmT/h7oK8fmRwk5Ka/xHO9Vl5phWbadMjFUY2aehN/WWqpgoWenOQafR
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29.pem
deleted file mode 100644
index cb31959b73..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIC0DCCAjmgAwIBAgIBCjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBqMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4x
-IHN1YkNBMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aIkV7sYy0JnIQ6
-oLcZr4T5fsXvU6SzOxBfPrtNDpq884ix+hP3zDxAwCSO5mU0znQe9s5im5Mf9yKK
-0FIXOAHFwMb5M5mAZNwn7Tx0XYxDfBx94lsMvJdBDCddmTB5akZgQF5Iir+Y52y7
-yiWRJM+ZmowFfoi5rp/PgkSOJxsCAwEAAaOBpTCBojAfBgNVHSMEGDAWgBROLqPn
-2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQUV6v4nCfI0vTmz2+qIAs1ZwSDJGsw
-DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MCYGA1UdHgEB/wQcMBqgGDAWgRR0ZXN0Y2VydGlmaWNhdGVzLmdv
-djANBgkqhkiG9w0BAQUFAAOBgQBlTO2ECGQPZsbXzVHd/rGejurHrD9MHfTQYJCn
-pFjAPq3wSo4qFVopG5gl9s4rdpNU+XvoY5zO8MVxTnfFi5G+y2CWZTG0iIWQmC8b
-ReqDdpVeAV3ictgaDyoU1ApdemyOS2pHV0mgm7vPYCx+17EXzFBphUICViSFv45n
-cu1nCg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Invalid DN and RFC822 nameConstraints EE Certificate Test29/[email protected]
-issuer=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
------BEGIN CERTIFICATE-----
-MIIDCDCCAnGgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1
-YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMzAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIG8MQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRy
-ZWUxMUQwQgYDVQQDEztJbnZhbGlkIEROIGFuZCBSRkM4MjIgbmFtZUNvbnN0cmFp
-bnRzIEVFIENlcnRpZmljYXRlIFRlc3QyOTEvMC0GCSqGSIb3DQEJARYgVGVzdDI5
-RUVAaW52YWxpZGNlcnRpZmljYXRlcy5nb3YwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBANFptsaiuqG58SeSbnVMTNr7XG3kbwY6wtsLkDomOXBGR/46vTeRu4CG
-CaubArviUAJ+JILIVs3bO02m4H6NUk6clLHjb1iou8cA0UR8XHkzJ1ZNmDZJiBJA
-CAqNmtpuolbgToov0SeuLYdDRTwLlkLpjykO6EMiAjI0bs0u769XAgMBAAGjazBp
-MB8GA1UdIwQYMBaAFFer+JwnyNL05s9vqiALNWcEgyRrMB0GA1UdDgQWBBR/JuUf
-MNbcNM7ktf6v5K72qnwyNzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
-hkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAHgiOAzfqxYOlP2ugGMXcXWDQai9
-VcfKXZM4zdBV3TmksgiLkZTyhj51RfoZOhQn8RB90lDZYdSqRGnGHuUZW6ejX+A2
-JXWuY3uhE2d2WwJIwYHItLSl+DVv2Jm0Wrv8BFY2PnKaDKJgLG3WM0bp2LKn2dzi
-FXK5SfJJE0q4WU2x
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:57:AB:F8:9C:27:C8:D2:F4:E6:CF:6F:AA:20:0B:35:67:04:83:24:6B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9a:01:ff:a2:5a:8d:4a:16:d9:8f:d1:7d:40:a2:bc:eb:6f:fc:
- 4d:58:3b:b2:03:77:79:60:99:5e:f7:f5:b0:39:62:10:15:8f:
- 67:ad:12:b7:a6:2c:ef:de:76:3b:90:26:79:b7:1b:7c:3c:25:
- b7:bd:11:82:78:21:93:5b:11:66:15:e2:e3:d9:77:e6:a1:18:
- 6d:dc:46:88:f9:13:7f:28:5e:17:95:7b:a6:da:4a:00:c3:44:
- 8e:f4:00:50:a6:a0:52:86:90:cd:40:54:66:92:30:0a:64:0d:
- 09:19:17:64:41:33:08:5d:c3:11:b5:ab:d8:61:5e:a2:60:56:
- a7:d5
------BEGIN X509 CRL-----
-MIIBYzCBzQIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRyZWUx
-MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMxcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUV6v4nCfI0vTmz2+q
-IAs1ZwSDJGswCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAmgH/olqNShbZ
-j9F9QKK862/8TVg7sgN3eWCZXvf1sDliEBWPZ60St6Ys7952O5AmebcbfDwlt70R
-gnghk1sRZhXi49l35qEYbdxGiPkTfyheF5V7ptpKAMNEjvQAUKagUoaQzUBUZpIw
-CmQNCRkXZEEzCF3DEbWr2GFeomBWp9U=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29EE.pem
new file mode 100644
index 0000000000..90a2b0d652
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNandRFC822nameConstraintsTest29EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: D7 F1 F2 82 16 4C 9F 48 C4 47 62 0A 5F B4 7F 6C B0 9E 94 A6
+ friendlyName: Invalid DN and RFC822 nameConstraints Test29 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Invalid DN and RFC822 nameConstraints EE Certificate Test29/[email protected]
+issuer=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
+-----BEGIN CERTIFICATE-----
+MIIEFzCCAv+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0
+dGVkU3VidHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0Ez
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgcExCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJt
+aXR0ZWRTdWJ0cmVlMTFEMEIGA1UEAxM7SW52YWxpZCBETiBhbmQgUkZDODIyIG5h
+bWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjkxLzAtBgkqhkiG9w0B
+CQEWIFRlc3QyOUVFQGludmFsaWRjZXJ0aWZpY2F0ZXMuZ292MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnoHPUN2bg6yLDHBYTGVFhMWB7jFvgUuh1geM
+i3nK4E4UqszjE3nm6YRJDExcfBRCPuH4NoiF7aQtOXqAP90h6hY+6ikQ18WZDx07
+1FxSDTqwSgDpNS3UyheEDvTyD9d5GpcVasvuLmQ4ITibTT3GHaGcV6Tg7jwif3lY
+6GxNl73YoOzscwtYuzSNmVerlrUAoy+w5LhLjuwWxPzeoaUHayamLXipBwiaKLWL
+4WYr/S7rNHz92cHFzIHjF3bQuFLpP9r6El3MDfZbXmu6K5vj/LDGKcOj1gCHbIC5
+GZIW0tbPxuMfLh4CPZfsrpGw7Cw+fnTocUPTv1yasn46YzhA1wIDAQABo2swaTAf
+BgNVHSMEGDAWgBQnSeQE2UX6bJiUbPztDcMkUm1VRDAdBgNVHQ4EFgQUKqooRqSK
+ejekpkSf3GDoIwRd8JgwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZI
+AWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAIJzDlmebZhMjzkhP+mOudtaSDpex
+GaQjDFetxOQ84CcVDofcsMoxWqRv/DRBHd3YfY90nbRpxNVPx55/C8hjYugK+KIB
+tY8JfMZrLY+nb4Ol2IFdPIDBX129nKrpaudrRE7onKdCAmfneGQfZIA4Hy7PozB2
+I0AscYOZp+e4F/0YBo5iaO74fafllHCN5nj3WL5+hRcghhvTaOrmTea3D14OIl17
+wn1aIdclzOQoMu/SQUXuwflUDDbDHntudZBpr9TTtm0M+fuAYcJvsXdrT0PfoQSj
+BpV5kId6JE3tjhsIc0e+Hv27Hrifq2xQAIonuOgqlDLPqlTHeoAgofv43g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D7 F1 F2 82 16 4C 9F 48 C4 47 62 0A 5F B4 7F 6C B0 9E 94 A6
+ friendlyName: Invalid DN and RFC822 nameConstraints Test29 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3D2649F13B51B3AB
+
+Ohs7+yDEVD1+Km2b7OswFMWhpy90ZHv69BL+zOULt5p9bpAMvG1kZwsIkdMqK/3N
+dT78GnLlgvLflgvVf8mCeJ0Vu7YG9wyD2hU058v7y5bELb2PZpP40y5QUDFI5gy9
+yoWfMy6/5DSpIP9uNgDNHRQ2DXo1hR7v/PSTSU21LvkwdaIsmSf2F/oOXD9UMbWm
+SnDmT6UuPqQaimgE4ejXrztGr5Bac1pPKj3t3iOnpVPTltN+A27bSKXgFUVJ3rxc
+DVUms/BzCwyxnnA2lT7IPidq0ZtZhX8075gFd7Fug5v6GRxd0OhBNC2TvO0Bt8m7
+K96BvurO7nveZqwtnL/zIRFVbnjAo2B6t5Y37uPzDtZcpB2sGhMcaZEA2aF4Pb6y
+ZiSY9BHm8AxoIiI5Wpo03vtPyAKvBXRP8xsEizmyPkf95ji57hB0zTsqx8SyiQLg
+HGigqleXR4aDMadnXlPUG6h7xcAimmSbxkIbdGNRf6pG8EcP8eE5Uk4gho1q+sji
+j6BZpu+7qy5UIlpLJIxoYEGA3+zMsUgzYokFyLfIf3Q9lNAwoSV72cpqkNHUKYH0
+IYk/kTk4Ej+Ypha/Ex2Yy0PJsJsaUQTlV0EC/GEkSyxu7nGItGfzIJoZPelC3PAU
+KwSzlKyJaR53QGN+kgd2K40XFxnpr0QPVJSGgQcq/rb1gPzoTxLOWC4bufVDvimW
+2VKVtlzcOPuSWM57psVWavi0XeIf1hAqtcWwbwXN6wYWkbtXIH32Arg5m9hYogKA
+ml1PIbgRyPK/2cK7y9DVW4UGZC14a0jUZ6JWZLA5sH+MtZ9TZ+lh5/0nEDPpxSKp
+HpO75Bs7aFywUwmGj3kxVZgmOBY97X+GpNnyye8RFaxQhXm6tQcGnYP8GnXnb2Ig
+YG5g4L+C3giVaUiYIVjGQY88kRC8u+ZwKFsnrkIzhtRmofuMwBhwJAZ5n0SIzUqh
+oDNPKWXWVTWV5cbssTdNAXiPwDh7om/htkf6rYn2HcWJssERFqD+WOWm61yKaa4N
+4CckPcH9G9gC/rVMAhBp/xmeH/KOHz72ygZYDgPskT35z4wpXy835OipyLJuDafg
+qtXtVPoXCzfdqjacQ0Y/yTXtGM+Ti9dri6Mbu8nSIa2RlVtf9GxAgv7lRbzRln14
+htlZpjrzdwnXV+kNbybqP525K+iKwjIwAwcqX8H+GMkkHRQOsyBDR5fRrnziC9yS
+Syl/5nkfiR2YR1qLpUK6/Nvs89vogX/o+rb+1ixw2ZevRG8rGLoY3OVaJ4HT6GWZ
+wN1Fpl3Iq7pxEpNvYkiVhf9QDRYLmZa0171LL2FWJGPQu3Z+d4JXg9PlWN2Gv7o1
+NIlF72ExRD5eRUjVKy1s7NxyxTK5McKm9OUNfn9VCW0nL7lj0X3iEz/SQRClAeSO
+YJheKoST8PKuyORHHI6PffbeShcgAl/N6Cj1RBb+87XlYAa8dSU3BpQ6jKJsgnXd
+/5PimVl9vbzWfxYu3oVMky8+GuDvY1njxuMBuam9ciQIfJVK9t026ZV4iamXxxxi
+bXyZYyVmO6BzIJ3toXCdNGCFdUoPlCOpzuudo2doNOomSEb64IDJ1Bu2kv4gmugX
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10.pem
deleted file mode 100644
index d79077aaba..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10.pem
+++ /dev/null
@@ -1,113 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN5 CA
------BEGIN CERTIFICATE-----
-MIICxzCCAjCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjUgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjCBmzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQL
-ExFwZXJtaXR0ZWRTdWJ0cmVlMTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVlMTE5
-MDcGA1UEAxMwSW52YWxpZCBETiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNh
-dGUgVGVzdDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4wtLGQI2aSdxL
-gklYOXIk2EqQgeDaSAj8Qxcobr8rZ0rgMBdG0A4ygWX+jdsMNqu18m+WGLs4W84P
-I3+0QpnI7DrNez1cOAzew7lPKnkDW9tnBqKQaGzafp/L9i/QwFxw7q0/OyJXLNqx
-96I70felgr/e9i6Yk/NzhfHNoKqL1QIDAQABo2swaTAfBgNVHSMEGDAWgBQSNZ+s
-wbmh4zr+8S+6d7IITk1Z7TAdBgNVHQ4EFgQUwaAOiJj2GtamtV9rZWhiH3jfonUw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
-9w0BAQUFAAOBgQAsM+4rszF68aQzKZtZ+iLup5xun1WT0hwwvbL4qbzJuLAcCNWj
-22+3xcVPnJ/ODouOh8JN6vzYFUIm4Zojsdm6VJQlcf8Avp09vAMUWLyo7ScyNJgi
-/BXluYQ6PfjP/XwskA4RlOGYZ33Ewmh1xaic85c78iFgRWe1UfjmPxvMQA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN5 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDRjCCAq+gAwIBAgIBQjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIERONSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxmMyGO18
-wxt7plFRZcGPd5GxKiCL+NJ+O/UB82qQ1+GhwlsBTSo86QNLh9KPIjs3rrARYIo0
-FqA86FPnpIiE/yWOfuQOeI3t6yvWf0XsXvcffhjW6n6sErOqhXX7voiJODZMseiM
-wQ2Md8CcE3j78i6crfbdO6xGp2xNX63VmkMCAwEAAaOCAUQwggFAMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQSNZ+swbmh4zr+8S+6
-d7IITk1Z7TAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wgcMGA1UdHgEB/wSBuDCBtaBLMEmkRzBFMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBl
-cm1pdHRlZFN1YnRyZWUxoWYwZKRiMGAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExGTAX
-BgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTEwDQYJKoZIhvcNAQEFBQADgYEAp32j43pb
-BqBj+2V14kyvmo+pgQ9H/ag1zf7WG4ei+McEkF7yvHSC6nfXJA19r+q2fAnvIU4M
-TriscCGq9oE6qzd3VIQ5wx8eJp8v9SG62gxZe3n1A8gzG37TvTwBOeEgxOKBa/BS
-8MNUbMO2SJwuE2pi9fnMhCgx9JxUQvQLou0=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN5 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:12:35:9F:AC:C1:B9:A1:E3:3A:FE:F1:2F:BA:77:B2:08:4E:4D:59:ED
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 74:3d:76:85:10:61:c5:e4:1e:19:16:23:27:99:ac:bf:2e:c9:
- 07:40:7b:fb:45:44:5d:c1:6e:d5:5a:e5:6d:35:d1:4e:9c:e1:
- b7:21:0c:2a:7b:7f:27:ed:9f:f4:59:15:1c:67:1d:4b:8e:ca:
- 19:7c:a2:78:22:bf:28:67:31:5f:bf:f3:73:73:ed:c3:9c:fe:
- 2f:16:56:80:ea:ec:27:dd:7a:85:15:2c:e8:fd:c5:80:2d:ad:
- 36:ac:8f:39:5b:d9:79:ff:54:82:c6:61:37:e2:b6:07:46:8b:
- df:2c:86:2b:69:ca:d1:c3:71:4f:3f:c7:e9:4c:c9:23:85:85:
- 19:9d
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjUgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFBI1n6zBuaHjOv7xL7p3sghOTVntMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAHQ9doUQYcXkHhkWIyeZrL8uyQdAe/tFRF3BbtVa5W010U6c4bchDCp7
-fyftn/RZFRxnHUuOyhl8ongivyhnMV+/83Nz7cOc/i8WVoDq7CfdeoUVLOj9xYAt
-rTasjzlb2Xn/VILGYTfitgdGi98shitpytHDcU8/x+lMySOFhRmd
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10EE.pem
new file mode 100644
index 0000000000..dc3b928db1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest10EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: A4 C4 39 FD 46 16 0B 83 D6 45 2A E7 E8 2A DC 7C FC 5D 92 26
+ friendlyName: Invalid DN nameConstraints Test10 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN5 CA
+-----BEGIN CERTIFICATE-----
+MIID1jCCAr6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIERONSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGgMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExGTAXBgNVBAsTEGV4Y2x1ZGVk
+U3VidHJlZTExOTA3BgNVBAMTMEludmFsaWQgRE4gbmFtZUNvbnN0cmFpbnRzIEVF
+IENlcnRpZmljYXRlIFRlc3QxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMtcOJE/RnaVHILDfZtHlUhM1+XAYb43ZVRpNwV5FSIRq9QuSR5liQ/UspVX
+Sf8+7TtcTN2jsJf8mpTsMFRg7bM7U9MYdtKkEMCuSZw23p7ViAdMXA8C1ZTrQP/a
+eqWRqjxcnywYAygYhxq3zJ+JPUzKJSOosgfd5bzhnteVXKUktQeOZkoJyi421/1b
+eXkMGK6EeMl7wQY0LofwaXVdjo07iv9T5c4CeHhTTctGqxEvpvkx5tf/eP7wEdvV
+5sQ9/FxcG+lzlnsi5G1ScvPoHrbWzSL18qnm7cVkTnl5qhKVWrGluFca9UDNgXEZ
+fMjrPn0KbHzma61GVkg9+W5SSRkCAwEAAaNrMGkwHwYDVR0jBBgwFoAUup8JypA5
+nE53Wuv7EJWs06dKXScwHQYDVR0OBBYEFPh89wp4MlOC1+WYAt+HqvvzZdLQMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
+AQELBQADggEBABeqoXPiGjUdCzGWnsb1grkUibPx8tfb31bfSFuo0iWoKA+RVecI
+xaepmZjcSRFdYN3lKRiPpmCXsBa8zN3vnQzAc53FGkxKmX/0FCUI/tKAKdeWN4Tj
+dahGQAjXBVWBUCaRlonqQ8xDzkWEGIuYS2/indcUZ3b4mp2QOD9tWMbglcRIpwoo
++Jp/VT0GjCncj/NOr5tnsImNUbZDSXUSQEatXsjQCK4kPqRhe56A7AWAXvS28L+2
+1BOYIyshE8G/2zYHwexSna4gvhrN23NbvLE0Jib+XzHekc2s2sss26qY7ZlkzMLq
+Ad88C6Kz0Va/w3kSxfmhF1fUrmYWgHkJ75w=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A4 C4 39 FD 46 16 0B 83 D6 45 2A E7 E8 2A DC 7C FC 5D 92 26
+ friendlyName: Invalid DN nameConstraints Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,306CF9F2D3E6B1A6
+
+Zp9pcPFWANIirpQvHK1Oo/0T8DgG7mQeMIIuDWfKIv5pVvgFMchXizcEoqPCGtAA
+oH1UJhJCXbqO7Iwckv27OzpT8H6q9fQkQhd1sIYN++h0eOfwlC98Dc+Chq1sUFNx
+KzDU5qa51Io+K5m1KB+IDFmUmodpF2abmHC1EGF3DrR+a0GK/gZKEDiQ/80H0Uhq
+nyVj6Db3t8CQfFSvOoDFOQ4SnDOQ5Dd6yl55spw5LxO3fvFpXKtp8VMAmeAYMfKq
+2nJB0FhRNFNVDsnFmlHfAFrDZNCXWcCzE5s6uRirmnkNkwic6UZG1shPym/Ov6E7
+TxsMW5lLMPpHup2tCHcFl40LvH+6dIteDIvH/RW+/GU2RQMSqexoVjLKVeIRsCJN
+2YaSSYWXbu1r39ago1hxZpQpiAb/zSFX9WLnbwwkgF+LxXkRGhCDN9CF/+OaEvCR
+6zhuEChW8H24LCZ1Eiylv1jwL/tGaxgJgaW1WZx5+rgdtm1kDA3yljyPNzNQM5gq
+hQtvnCR8xvvl/oRpP1pfOJT01hw/CIGVMaAbuD4GkUbyq8qbACPoUV7VkAdyNYtC
+p+4cpsfibY3z2mG3Ln76zqCH8fFanAmKgvK8ywR0J7g6T9DWmIeqx2uexdoGNLag
+GWJkE7/Gl8149SN3Yl9foTf6+xnfHkgCZkLeYRaOU659pNrqsDjZ+/tXIaDh1de4
+YEs2F+LhKZB+U3+gh7vs1c/4+rViHcexFBagr8fSVnvFZyH968vb41al1tyPxXke
+I/MCqAvq84vA/WSE3jdpu1/1FdS8+hbiT5hGgClJJqYCFBXuQ5IeSQX75cNQgU4W
+BUkbiZqA/gMAjoT0Yr1C4dWgK6099WfEVqhlJTwRNGleDI6kQWTUnBUIo+ZU6u6C
+AXKllUPix9dlIKW+c2pOs+eAhM9oP4QXPP+63xFnVlTg7yuSzbZ8Xfnv66FKSq1c
+1HRbkIw1CO8A5r3u/ysK/iZdyA/EaBXSmgK0iy4Q3kMyYgqdbWrFyaxZIe4r0180
+dXE71fhUCiSIaF27KUPd/ZHQ+YDLec/ZW2nnA9DcLqAaMIEjLgszyt6DTqerS/YL
+zwv5fSZw9jlFQQPoiyuCRx1iXlVjeBDLwpH9iBBb1PZTbx544O+yYW/JtMwpBRg8
+d7zneCezW81dKMczmJvxhGEoGNIZ9FPAbfRbqWg2Il1Zz5mYyinUbso/UTYa1RUP
+tzkuZulPM6aPYEQbm+gMlFUqhZJ81VozDgj4k2XHIXiHApmMVXRyOvlEcCxOWJSh
+SksqVxwNjf+OlNZ0SwYDqdqxd/o3zovsSW0viH1dmorG+R9Yjil2HkZTxh9c8VOJ
+9EUWdlGmdV0YsiV2VkZ7Pl5x90mKZ8Jac5iZdPE1T8soQTlow/fGO3PCILun1Sym
+W5nR0amYd/xswerC63u5pd8XPGZZxcrLhZED9aipGSo51N2mwUFDcu2wI25VetDr
+DJdLglyIjWWIakrCEAYNcN8ekPDpxTJENPj1QoLMIb9T+n++TPiDAv+ourN4Cjfo
+FuwyMRdBEk9hRUo1oV2cdPO/oq6TTC0iEvYRjB7gCjoYXb4Va4y5W3PzVoYnmeu/
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12.pem
deleted file mode 100644
index 4b5c41460e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12.pem
+++ /dev/null
@@ -1,166 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test12
-issuer=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA1
------BEGIN CERTIFICATE-----
-MIICzDCCAjWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1
-YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMTAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGAMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRy
-ZWUxMTkwNwYDVQQDEzBJbnZhbGlkIEROIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0
-aWZpY2F0ZSBUZXN0MTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK3EJPKm
-RDv1REuSTNdGYi/Gay9ESpl/z2BBw2n0WqiF9SLFNEuRfTZ7FQVNFQ0qhoP4V2xa
-YUeaSgmwZNcIdZg159xf8j2Qkc3uGAQoMGmRp4vbcj1Ev5yFXhvVLPnhp5eE8wKx
-u96ZMOfL8M/sxSRrI0zUKEUCMbzK2E0Mr/RBAgMBAAGjazBpMB8GA1UdIwQYMBaA
-FO65z9YvjsiFkwj+EBDuo1BY/kIwMB0GA1UdDgQWBBRlWUYl70WL4wPhhb56CsXD
-+SjqmzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
-CSqGSIb3DQEBBQUAA4GBAKnGr+IbKqqwN2t7AB4bae9QRHntR6fokA0gcPPMY7qA
-GxZGcA1fClTM+WZKr4AoCiDelOsxy45Pim+0bZUtzqtfhWKulkfgpS5cdPZmNj2r
-UkLeXnjjTjDm5s8YsQovhy20KPc4VoeYRMhkB5Wika28mXV2l0jFTG1VxcDZ2BxV
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA1
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIDHzCCAoigAwIBAgIBBTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBqMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4x
-IHN1YkNBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtpBRaRDexKAJwtC+
-60QonOrQnFJ3VA/u5f6qj4iI30hKCIXL1aeAM5c2KmzL5gO3Vg7dZWw1f9gW2uaj
-mpHjfGmScQpaIFP7yNbI29PIlN0h8H2o4I6v7zDCteSnYy2qAkDkNLX6fbVENa7f
-eHcx8cvG7W1VNi0PKVQdVBz/PHkCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBROLqPn
-2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQU7rnP1i+OyIWTCP4QEO6jUFj+QjAw
-DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MHUGA1UdHgEB/wRrMGmgZzBlpGMwYTELMAkGA1UEBhMCVVMxGjAY
-BgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0
-cmVlMTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTIwDQYJKoZIhvcNAQEFBQAD
-gYEAm5m4xlbfmnv2vDQ/hGoNbPv96saVQ2NMhkH3JVSF5lGUWfamMIsH866TS9Jm
-BDWOWMPDF1kL5hLEiGLSWA8ki5s+29AwhYXt0jcwdIbGfGCwVX1w3KF5k1nYv8RR
-FhwwXNlM+EKqqLc1nWgaXnsE8fSRMesdyNjQaJdCqRAYFXI=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:EE:B9:CF:D6:2F:8E:C8:85:93:08:FE:10:10:EE:A3:50:58:FE:42:30
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 31:75:7f:a7:8f:25:e4:4b:09:d0:29:6a:68:0c:3c:54:a8:42:
- d4:f8:f7:6e:be:e5:b0:bb:f1:4a:e5:1d:e7:1d:b8:d6:98:ba:
- 3c:6f:23:4d:a0:8c:53:2a:5a:13:7e:4f:3c:1b:fc:16:c6:18:
- 54:05:e5:fe:b6:48:84:fb:c1:0b:7a:ea:bc:44:55:bf:4a:7a:
- 51:1a:e3:a6:d5:94:0f:37:3c:fa:4d:f8:51:ae:c6:74:de:06:
- d8:41:69:92:8e:a2:a8:d9:6c:73:98:d1:63:5d:52:61:7d:90:
- 88:c2:0e:ee:ba:eb:74:c9:19:b8:c8:20:f3:09:a3:50:7f:10:
- f9:e0
------BEGIN X509 CRL-----
-MIIBYzCBzQIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRyZWUx
-MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMRcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU7rnP1i+OyIWTCP4Q
-EO6jUFj+QjAwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAMXV/p48l5EsJ
-0ClqaAw8VKhC1Pj3br7lsLvxSuUd5x241pi6PG8jTaCMUypaE35PPBv8FsYYVAXl
-/rZIhPvBC3rqvERVv0p6URrjptWUDzc8+k34Ua7GdN4G2EFpko6iqNlsc5jRY11S
-YX2QiMIO7rrrdMkZuMgg8wmjUH8Q+eA=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12EE.pem
new file mode 100644
index 0000000000..2905cbe756
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest12EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: E0 B4 95 9A 2A 9C 56 3B 18 FF 89 B7 70 82 97 38 1A 1E 3E 3F
+ friendlyName: Invalid DN nameConstraints Test12 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test12
+issuer=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA1
+-----BEGIN CERTIFICATE-----
+MIID2zCCAsOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0
+dGVkU3VidHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0Ex
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgYUxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJt
+aXR0ZWRTdWJ0cmVlMTE5MDcGA1UEAxMwSW52YWxpZCBETiBuYW1lQ29uc3RyYWlu
+dHMgRUUgQ2VydGlmaWNhdGUgVGVzdDEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsaY3YvZQ0g7cMEm8Ci7BM6eT6NjOLozJ+1H72HTRBstqGwFfoQow
+3jyt9v5Ea1qcrsDbzaCtV2JJDEx5jmt3//MkuJLNpXJRic2AZzK5zBlV5PoxzjId
+TiB28gPJ9JASOO6tC142FjxfZzn1/Id4xcEf4WccFfJiQbNMUe9kuIIBfEVLfVco
+gfEB1Vo5WblyMPbUWwt+b8xY7wFF2NQpNb8Cg6ebTGqPy9OSOaraNZQ+mLQOVVDT
+NqfwAaEY3QoqObS/zoI+aDE/ebim7U6MvWzZU1NZkbWY1ngD0+pLZX9l8op4NjJV
+Z4SOoUvhdn5NRdcEqYcpCXMW2ETJnMj9jwIDAQABo2swaTAfBgNVHSMEGDAWgBTh
+OA4UGBRDXM7nS2LHGsGS9maC6jAdBgNVHQ4EFgQUhQ2EBOSyja4LSx4MxUG0kb2e
+/jkwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
+hkiG9w0BAQsFAAOCAQEAj32dGQGImnemdjlbIgsR+DypC8tThQ6wED4/9HUarJ34
+NJ7yHV3s3GhPyfjGr+WiGgqp6Yo1Prd/epDxbDvdBKfrTV0yDZI/yCYZtZ6WHc9J
+x/ThYTx2XyTKdZs6GrgOMviX+ZgpV8147nxK6DKZv5jk0WoshMh7nYh84JeehjQY
+UON3XZ5NoiQD57HCUSNGrc0M7pUOK1CQHZzDh9pJnqSbR1sHERVgD8U38bEUFfUv
+mweQov0WolmQJmcVuzPZioDeNlhv72gt4qg9gAZEgbQDSyKo72qbcEZ7EMVB4nFU
+QOcPMqU0aq6HXBcML7OcgGZQm0iqDJrCpVwlqsaWlA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E0 B4 95 9A 2A 9C 56 3B 18 FF 89 B7 70 82 97 38 1A 1E 3E 3F
+ friendlyName: Invalid DN nameConstraints Test12 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E3F57532B0E11C3A
+
+IhKIRIJX5AaatoF08s5ynXUb6FbIPL2Rbb0YcUFAw1pFgq87cvUAXWyyTkFna+H/
+bL395/7gnF7AdVAHYuRDhr38mgi5JPFkkB61s8j6Xts7RflSs87WV5lhDRV6d6z9
+/Ym13Ci9F9maC+ySb/ueTshw4htYQL8nK1wL7W8K+RKD3EHubHG4dd8fKkVWsA+C
+yrllIQKAxq03Biu0yjVqNweZXfLEer0nkh+3gh4xiS27EyuwOR875rdv+WXpHfdk
+bJWJVLCZ8KzwJumgQvHCWs7vXzjOtp9szlfshheA+VzngAw0wng03z9VqM60xtg0
+RfjgoTRkkGCgYTWDzrYIJ/pKYKIm+VmWlOXX4utPUtH2P3JQRJfjGVQiwlrQ4nP2
+m/aiLNGp4+wuaMg+fwDJGs1pZNZqy1EO3nuQSvVtwuZw1EcgAn0yn2XFoJWKxNZF
+rdSDpqV7zbmQMkRapqoRK89JG3wlaz+c5uCsHaAMBxmmxH10ZWz+uIIa69M3JCGj
+8pYA2KTI/e4Fic2sKrBMECzZvQf5AZvZIp9YbUR5PBzWLQ7FUDL2AAYtwBFi9QV6
+A9JAXFxH4Fe8Qop+zefRzcnl+8JPNNirkMx/GM+LsBhWyXUyRrC/PexSoL+S6L3J
+ub/zTPbIHUYUHn6Pt1yxQ1Xz0V0a28uaP/BVsDayC7dMcUJ9gYoJbTTNq0or18oy
+PyQ/Ws3vEYGYtmjvBJuXWdOi3vdhK+OGZ4qz/+/W2BKaVFoLD+x0rCZGrqTDR/Cd
+7yHlM6jAVlB27N3TiOLq+U7xHdTag5WQfhlAzJe3LpXzR3pngfw2+s5NYnEAf48k
+UIz5oonMVKGJ5s9XBIOOG9OXiooEfmRD4w+0YLiY2DEPaKAgU9VT+rdk3BZAdCtM
+4aeEe60YzTHU5xQJO/fe4BrEOGfyF5Lr9doWa0x7Bj1kZIUwuAX6Oa/egMqsReX9
+MxFb/fhRsl2x+O6LAcrWuS0ZagdUzpaKtqw77viXDO52fplUbRINyMtsjRHnZ5vP
+4e5z7NU/ER6IiFLLwXLATUPEmtozGUefL2wt9RzBH+UpZOohKWjc/eET5DvejBAU
+e+QepPEnLVVjqI1veeuo3gzdGMUczRwyPw7t6bhKaxf+fmR9xVxV1pjpX++QzMx6
+842Rd3eKMwPI9jdpSq5U21K/7NlNzQZKa9T6y1lBIgWY8F+ocdPU1Oi8x7X0Vhkr
+NP1kFG+D1kBMcd34gfQw+orvMACI++DgXWb8zQzwlTlPkQjmPTHjn0aeIZii1ZMt
+zTUGeojlP/9aaBrjhrhcAUdTvGBK5MS+TSxc2IAgDtM+XrmHxK/L5OJWhOLlfsvt
+OjOh4Bz8lRe4ybz7znywoGpISK9KtJsh47m+WON8XrIGRxlQDw4HlPi42XBbleqa
+FrQWaat16buFiG2OoJL6qKe2fqpuaT/zd4vQBEuBE0Be4zhBEoJZ1hJyFq157LBD
+9u6XAat3riRv6kzJ2G8RvFwGbTVoYtIOSIwzVdRtk2HHPaE6yp3cc/tpis1ig5cG
+xI5qksskLmPRC5FGvQ0i3K3t4YJrWQisrVwth4wSe/5YvfbNpD+QjA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13.pem
deleted file mode 100644
index f80308db49..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13.pem
+++ /dev/null
@@ -1,166 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test13
-issuer=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
------BEGIN CERTIFICATE-----
-MIICzDCCAjWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1
-YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMjAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGAMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRy
-ZWUxMTkwNwYDVQQDEzBJbnZhbGlkIEROIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0
-aWZpY2F0ZSBUZXN0MTMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKzBUwkX
-ODmjiKuO7MZlzTSc4Re/YVclO6AWzJbjVn1RazUtEisXPWkpv08n2R5ufbWSSnp9
-Q2/iMhNutgXf1w1kQ3tCZ/T3bhIR1c6w/ouwi8ykUP/dQlCo91V9PBaGbA/ARORv
-R5mJqw113jWqok2Mr9xcMe393f7kLFt8yx5fAgMBAAGjazBpMB8GA1UdIwQYMBaA
-FNWvaygNna1IbAyCKv/SaAkvFG1XMB0GA1UdDgQWBBSCt3/nyCSzztm6BrD2K2Fl
-4aJOtjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
-CSqGSIb3DQEBBQUAA4GBAJaAuvc9jA52+D7MggYkPmix9SdKXbI3nEcYpIXuzwO2
-hAzPuV6wpHgf4Ol9x+zrbWQ2KVvJ7zXGEKOjbKZb7O7ynb0yqDv9nRbOWIEU4lwD
-Fzj8Pb3n9FnnF7awDloK1pMoqxOXeLWsk7RP+psMqVuAQgVxrYYBbTwQXqMCAmIi
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIDAzCCAmygAwIBAgIBBjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBqMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4x
-IHN1YkNBMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAteRgCqKcIeCHmYMc
-xyzmM+fCjW6MAEl+OFQ9Q7UJ1n9YE0TuaGiSxjTkrTXwDF2JoDwMtC6FoqnvEyEk
-kAxNlM0oiLhRxM9FcNCow3VK458jtPozrIgd/7PAP+FXsqPanD2DRYj4c1gNKSl4
-U/l6HyTj+yV6ax5EkPgQDLQlJksCAwEAAaOB2DCB1TAfBgNVHSMEGDAWgBROLqPn
-2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQU1a9rKA2drUhsDIIq/9JoCS8UbVcw
-DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMCVVMxGjAY
-BgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0
-cmVlMjANBgkqhkiG9w0BAQUFAAOBgQANN5YtrqXFWfdpK19qY+rn50d/fYdLaOU5
-dSIAqmnB5woTCXdWF0LUADF4DkPfcWBxbE36lwBuGXBfiInH/5yLRy0Y9cZbtHSg
-QwTIf2a+38pR6QyBniftVBmBTuhO/PV+/kA8gKAZ6X4+vGMv69YjU9avYeS1o+XW
-liQdX8l7vg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D5:AF:6B:28:0D:9D:AD:48:6C:0C:82:2A:FF:D2:68:09:2F:14:6D:57
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- af:f5:73:47:0b:2b:ce:c1:5c:82:7a:07:ed:cd:ce:55:02:85:
- 34:07:7e:46:10:13:e0:94:7e:8c:27:9c:f5:52:89:55:5b:fc:
- e9:08:32:b3:54:75:03:c0:ad:8a:b7:e3:fa:5e:73:10:90:5f:
- 26:ca:6e:1c:e2:68:e4:99:4c:06:38:3b:56:25:ce:82:a5:7a:
- 3f:0e:c5:a4:78:8b:19:d2:fc:a6:4f:f2:6d:d6:12:5f:69:03:
- 98:b8:00:c2:0d:4f:9e:47:fd:66:3e:ac:e4:fb:55:f3:4b:bf:
- 42:54:ce:46:a2:5c:fd:c4:5f:d8:61:5a:61:9b:a1:2c:af:0a:
- a2:2e
------BEGIN X509 CRL-----
-MIIBYzCBzQIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRyZWUx
-MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMhcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU1a9rKA2drUhsDIIq
-/9JoCS8UbVcwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAr/VzRwsrzsFc
-gnoH7c3OVQKFNAd+RhAT4JR+jCec9VKJVVv86Qgys1R1A8Ctirfj+l5zEJBfJspu
-HOJo5JlMBjg7ViXOgqV6Pw7FpHiLGdL8pk/ybdYSX2kDmLgAwg1Pnkf9Zj6s5PtV
-80u/QlTORqJc/cRf2GFaYZuhLK8Koi4=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13EE.pem
new file mode 100644
index 0000000000..a630148db1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest13EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 4A 1F 06 92 A4 FF A8 63 D9 EB E7 9D D9 DB B8 18 BF BA 17 DD
+ friendlyName: Invalid DN nameConstraints Test13 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test13
+issuer=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
+-----BEGIN CERTIFICATE-----
+MIID2zCCAsOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0
+dGVkU3VidHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0Ey
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgYUxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJt
+aXR0ZWRTdWJ0cmVlMTE5MDcGA1UEAxMwSW52YWxpZCBETiBuYW1lQ29uc3RyYWlu
+dHMgRUUgQ2VydGlmaWNhdGUgVGVzdDEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAuD/PFvZ4Qii7uYsJkBh3y1o8UCIOhlno/UJa9fVTjh3hwChhv4mR
+V2+1yfOib7xKN7694HOCyl/u13ZrsLG7rG/7FcQnZmEd43+1gpinF1Y9QNYv6Ilh
+/inHyGe4iLRveuNCzneUH5JcDtklbuaEhUZvVBch9BWEeD/Jp/th2q0ojbFzltMI
+3dG2a24zL4BGbNHBdD8PkbfKdE2N9CYC6f2Rd1c0TYdhZ8ZCW2WZ7zUiK70zUKAO
+Ng/Bs1VGhaB1DjWu3gbrC+d4z4Q77FN1h1ZPJP5ON/SC7Tf93TWHHXHfWT1lCot7
++abuzyuN6kCKjunaC5tRCaMXGTT5EMEt3QIDAQABo2swaTAfBgNVHSMEGDAWgBSi
+L1iDW0yVl7fu9oe0lw7gf+CXFTAdBgNVHQ4EFgQUwJd0yB0ypi+GIJqugHjmrt1C
+HB8wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
+hkiG9w0BAQsFAAOCAQEAJv/hxkQtOORch6bfYubBEe1urCmntR2Fj73iIooxcewT
+5iC1EPgWR3IluR44YUoWulHhmRNeUqnAtfJYJu5HhYIt1NLXU5yODWJKJ+ZSIUsa
+WkFqdPAVp1GDRhDUP4shZC1Nur3gH0wXBQQ3pxsWjwPWNccxF9ZHR7gJxPRPPdE+
+FYGeeTyfzpOaDdiQ8Tgihhjh3CTk463nA5XaFWd/7MG+YjnbvGQWb/ag5TZh4yHo
+O0Qm5dWFzqyY/UUDV8D2YaDY9DFEk0rpJsfRTCg6fvq+PviGAY+D6uC4YMe3mVBz
++HYIIgOC1OOet4dCoXsgIiy/0nyx5lRU1LSWOCUCSw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4A 1F 06 92 A4 FF A8 63 D9 EB E7 9D D9 DB B8 18 BF BA 17 DD
+ friendlyName: Invalid DN nameConstraints Test13 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0EFE45D2311943BF
+
+t2sVjyqv8j4shfBShB9JGyHiR66fXfETyuBtShElRz9MZAEVETzBGUunQoY8nkcB
+VkntDIige6tpxLUM55A0JNqsd9wfaR16FtJyEa0yVjaaKHgLjKfp+Kjg/t6tXnmR
+V7RV6CpyVkyXaBnXFg35JC1KPl5SNJQM/RlYAPI1uigyFuEQdLdArA5L+eY4p+Xt
+m0xwkZDVFAkQDnjz/I1+d8HkXzNfwFZI/F/CkwCdkDaezKTxUix5h9DDmTcxa63+
+xWUF3jmXRw7UQP3WKAlAQQp0H8uWLfS3iEQSsq9L1vPFG99sXQG3QxRihDBilUKb
+Qj7JMst36B/xSRH8vHAU+VqellZaKHM2HB9p+wk9t76j2yS9HQqwW5InjM0KEabq
+Ik9dZg0TJ2lXJGHKWn0zUv1u+yCZZslES6n+7kFspDGhu4Z7tUnlBzWCM0xTyt+b
+PtE8cnudvqUzOgic2GOOyb8fZQ82IONasVHgkFSMt5swBcB9zp6vmNoi7U7POjxh
+h4HajSQiPRTUE1J5hePLVkAqC92PxsT/Nl8IJDuSOySojFGepuOddL2o1KbyYru/
+7UEnSJHliaEQPwiCCI4crMFx6Km4W7UagalhqF3g3aqjPS3TnID9gQKpv9SN67FQ
+9D3E98AEEV0G0SBLzSu6ZFD9cfDhg120FX5m7xwkLdFjy9P3n9M/sqTiV9GyewGa
+HO9tnJZ6fh6+PR+Yd+RYf6827KTCHbVs9Ure1g2SsAtzjjg84tnjpEm+aHQxGa12
+IGnWTdAFr2gNG+7nq4I0gaqPpbdTwpT108hrv/IO6JZnjolTl3fQ99QyiP8YPqXt
+kuAuJLf2wKM/KJzdq/UW/94s9G17FOkmxdnXKs5dh+wNivcpUtlWGPcEorCTU+mH
+I4Saic1oT1/zgH3ldvAlWjKc4ht4nxRJdnwAwssEZqu0beqUu+35IjeblkpATzAW
+6ec/DR3P/Cq5UwT1ZbEO9E0y/NzbDKb8TE4fTWe2G9PU6e1IQ3J70kCyMEcY9wJu
+UN9p8qEa8NZUL5b5fN4dOfg0MeeOIwGIu7H3j7OlBkdc15WEWUAnoKgg2m/E8mL/
+72JcmiWeWXvuwK0FVln2XhDdOSAn4S5xg02zftorRQSP4Mg8OMigG7goq0qZAX5F
+VOGJewlfsyq2vD4NRPxVhRw9AvECpox3hDW9xHaxiyf4VjDOZzAPgM2aYqnmxJ4o
+XxrAqlKu8mBf69eCd+WFdL+dzSht7x6s4FBZ87Bj+A0Yr8+X2G6+XMIY4xh/hrIN
+gtlNwVlqduguhFgBBN1mKAds/wQT4EiHoeP6ctveHI9c/FgRuT5NsVYQgum/cxIR
+MW9zMJxOySC77Q9OSMRP1TL2pBETBqVX+rI0Bhzoh4Aw+Eav9w6Be1zJN/8rW8Yx
+FLdRnKbXeUduW41E/MC4pnLMHWCriXjBzN4w3rAIHUz9Rb/rcBpicY9ELfGO4ynT
+nrTVGd/Pr/XOgartdpCBenRsnKAy3pOksHI6POpbEB4oNUspFIEPooJ9jH/xiDuV
+4UIBhmbDgt7yu+x2IJ4wwOhQHxRdFVaNaqHc57o0QLyePTBH+aQJDg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15.pem
deleted file mode 100644
index bc87ba867d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15.pem
+++ /dev/null
@@ -1,164 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test15
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA1
------BEGIN CERTIFICATE-----
-MIICrjCCAhegAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBETjMgc3ViQ0ExMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-fzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYD
-VQQLExBleGNsdWRlZFN1YnRyZWUxMTkwNwYDVQQDEzBJbnZhbGlkIEROIG5hbWVD
-b25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTUwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBALLQPz8+2Ja6+sIASgBJ/ylBL061WtWS7vJK/LRNLFf9MyYG
-VjXkjZyk9ZzlafhinCiXgrG77RGH8mVjuSwDNewt+DGGphh4dSnvg/MHRdi+NdSX
-hjVOzH76HO6U0iKSSQCvNPSlTJrPWQkZDfj6AGO+5Pmn5RXRX7vwRuKDSsAdAgMB
-AAGjazBpMB8GA1UdIwQYMBaAFK2SFB0uK9H4irG3IS5+jhlpPDR1MB0GA1UdDgQW
-BBSpk2fPoInUxlgPeiQDw8iOa8Xp6DAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBACfYnz7Xr82ytcccJe6v
-+1rv6v8SSi/dupn3lA8ZLFPQiM8Ep2kf5XkmrQCHk498pBRQJirzWX20QQSTv83B
-M9DG721LCvFZuFB17sf03DMGDXw4ISy3bs+3I87HwHyziC9OtryWACWfZ2lAGUpD
-V3U25s5CA62+qbg1jhc5LAKq
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2DCCAkGgAwIBAgIBQDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAti5Odfo3
-pSf6p8iGjNMBwSlKozpyyMbXSxEjpiDvuZpllmjLqoXe6tiWiee19xCly8MnbxXl
-4Pc6BglZNZd+adRIlPrFUPIVmBM51RJLvzQKjiTRPwrPwsJnizD9KLcr0Kf+e9Gi
-LHBlqZM41/0oBCVuAX/5Y5zNNiFhFeOnkNECAwEAAaOB1zCB1DAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUi+O4WFafA2rfPdgHO7MH
-NuHLtsowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFgGA1UdHgEB/wROMEyhSjBIpEYwRDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBleGNsdWRl
-ZFN1YnRyZWUxMA0GCSqGSIb3DQEBBQUAA4GBALkukW5Jb4GxdEYN7MeIVxnZX8fn
-4Ulh/l6uDFKi+R8UZyMWYp0oi5F0sYQrrsjBwpg/ivfpJtxLh1uMEAWp98vMQPFZ
-Hoo+ma1Ulfh6qAGv8C6EgA5sxWuNO0VrZsMbNsQeqVLXKvkBsYxrUAHXBd5ufqEA
-Wofw3VBcFpqgolnA
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA1
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
------BEGIN CERTIFICATE-----
-MIIC5jCCAk+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMT
-Gm5hbWVDb25zdHJhaW50cyBETjMgc3ViQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCmh9zeM9BeyKndgrRFYNxn7+qDC4AKVdFmpv1ciqlk3RwU04FCEhC9
-kN1hhqnghWi2XzHZ67kQD/azFMLQZU1b0JTg062pMox1ezyVsZCejrXUK8kMHEnW
-SNSHkU6KnrSC4aHU5jSV8T2uANRsR0wQ80iBfuq+XcyF3r8jVsbpqQIDAQABo4HX
-MIHUMB8GA1UdIwQYMBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMB0GA1UdDgQWBBSt
-khQdLivR+IqxtyEufo4ZaTw0dTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wWAYDVR0eAQH/BE4wTKFKMEik
-RjBEMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAX
-BgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTIwDQYJKoZIhvcNAQEFBQADgYEATe1pMNm0
-Ae3tuDLPpXrBaSog47WFgLklqGnB7xH9+4x4SGehRirWS/0TH839Rbb/rmp0XptG
-ECuOUS+tqrhiMPYmWxv65XMpPfwKHjxj9etcu/MgXytG7l1kFwuHP08zu43BEqRS
-JY0NuHpCTzI4Natc8cB3JTktdUOAF2P22c0=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:E3:B8:58:56:9F:03:6A:DF:3D:D8:07:3B:B3:07:36:E1:CB:B6:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a9:3e:f9:c3:5c:b0:eb:85:59:db:c9:72:3e:b4:2b:30:6d:22:
- dc:9c:9f:fc:8a:ad:9b:1d:48:b0:19:9f:47:3e:d2:44:6c:3d:
- c4:6c:03:bb:82:6c:26:85:eb:7f:1d:9c:48:93:a0:9c:66:25:
- 85:b1:5e:fe:71:a3:d6:2d:4d:c0:cb:3f:1a:46:fe:ea:31:8a:
- db:d2:1d:f5:0f:b3:48:ad:0b:48:0a:b4:19:cd:e9:c5:5d:17:
- 6a:3f:f8:bc:99:39:5b:29:88:2d:7d:0f:b4:be:94:e6:8e:a1:
- 7e:12:31:2a:46:f9:3c:1f:d1:c2:69:c3:be:62:f4:bb:b0:6b:
- 16:a2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAKk++cNcsOuFWdvJcj60KzBtItycn/yKrZsdSLAZn0c+0kRsPcRsA7uC
-bCaF638dnEiToJxmJYWxXv5xo9YtTcDLPxpG/uoxitvSHfUPs0itC0gKtBnN6cVd
-F2o/+LyZOVspiC19D7S+lOaOoX4SMSpG+Twf0cJpw75i9Luwaxai
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:92:14:1D:2E:2B:D1:F8:8A:B1:B7:21:2E:7E:8E:19:69:3C:34:75
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2e:dc:3c:fd:cc:c2:50:20:4a:d3:de:11:60:93:75:ef:28:af:
- 87:35:19:c7:47:5e:f2:c0:73:35:5c:47:4a:bd:54:84:f9:04:
- 30:4c:a1:32:27:85:14:cb:ca:72:9e:77:70:14:ac:20:72:a9:
- d2:6f:50:b2:ae:b4:29:03:fe:00:c4:92:96:14:68:81:b3:d2:
- dd:60:41:d5:ee:d5:66:db:b4:f0:d4:5f:a0:6c:93:d8:3e:e7:
- a2:59:90:af:9f:05:22:b0:1e:f1:67:06:2b:85:eb:dc:a3:16:
- 13:ad:74:89:dd:db:2a:71:8d:a8:22:8e:2f:f8:ca:7b:15:f3:
- cf:32
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBE
-TjMgc3ViQ0ExFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBStkhQdLivR+IqxtyEufo4ZaTw0dTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQAu3Dz9zMJQIErT3hFgk3XvKK+HNRnHR17ywHM1XEdKvVSE+QQw
-TKEyJ4UUy8pynndwFKwgcqnSb1CyrrQpA/4AxJKWFGiBs9LdYEHV7tVm27Tw1F+g
-bJPYPueiWZCvnwUisB7xZwYrhevcoxYTrXSJ3dsqcY2oIo4v+Mp7FfPPMg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15EE.pem
new file mode 100644
index 0000000000..f0fe0166dd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest15EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 60 0A 20 9C 91 CF 51 0B 4C ED 5E 8F 9D 2F 1D 28 18 91 9E AE
+ friendlyName: Invalid DN nameConstraints Test15 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test15
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 subCA1
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIEROMyBzdWJDQTEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjCBhDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExGTAXBgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTExOTA3BgNVBAMTMEludmFs
+aWQgRE4gbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3QxNTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK4B4XI7DVIEJPX7gqGREXO6XSno
+4X9Z4RamnbW0YiB1VGZeK6xusEN/StHlO4bDt/KfrvqUXJvm9D1oJjPX2rE6By+t
+Mi5al/5fCGE9rUov73jyKb4eUSCy5aTHfyjuu5b/ts46WkYOKqGEwSBCQLPqGR4O
+YXK5/QSZPIJwuvVJXwEp5/4dv9Fg2WRwRab7EXQfYut7AbQcyb4FrMwGPpja84JW
+q5jCvM7EsdmWZXhRvoDrqUtap+aotmfhps67INDFvoL4waIKzrTX2gmjO5kU62VT
+78gJfCWE2boB0tUsGGZLyRdvJ8SPbd0eEKykBejqvHcXb51ea205H8xZarECAwEA
+AaNrMGkwHwYDVR0jBBgwFoAUgLzHLveOGn/xOHv0Nevd6VjGPFAwHQYDVR0OBBYE
+FHfYNlCl24s86ePnQaSo5hQFK+GuMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAGqCCsaPWvIjVZbJd4Eh
+wY/G7O/cnYbUjVR4IRbj5Ce0lS2+nspJK3D6gqT+DCOxZF6LJQuGOJP6sQUX9OHR
+T2oAbrb02A0UqlrpA3s9DtbspM1/yWcHoU9hAP81zVcNq5VNrcdqdFMvmV2MwSiy
++Fvlc6K8QhHxnDaL6kSfdci+C27FWCahH5r2N/1l3Bpou8WhTtjsRqvAgzj2yHRd
+DgJhZKMjtieSQkSWQF4yvkUMH/AVnD5xOpSqceaiVFqUFfRSRhHKbtq/eCNZW0RY
+i1she5uNHI3aMZS7cajWOltPZ6GYCQ9ovLddg5foIcr6YMaH5u3BYAUCdvMwZeZw
+8Qw=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 60 0A 20 9C 91 CF 51 0B 4C ED 5E 8F 9D 2F 1D 28 18 91 9E AE
+ friendlyName: Invalid DN nameConstraints Test15 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FC1B613AD21A2C7F
+
+Ebd82tkOQya0n0wh75My+7nzbmeoUtouc5grb4vdfB5fiU6VOE+W+tV6qJLOUBXr
+Bue1GRFfVMkOKhHdzfK6fKKoaVSOxMZJhM8uieJrFnfGPwMhl52el81y4A6lvN80
+VKwybkHXZZ43kyi2CwUN1Qrj/AsXSpwQ4pJntYt8ukqqp1NN52HUbNFraHP+/xrN
+qGinXGbcwYJCmBhwEyC9LvLWDP8svwJFBsRN2RCfZarlKNjNxqxiyJzej0C/1qp3
+0ATwsmMhGkLq8UBNeaJtzppKQJh/SEeLS0FpKybImxXJ4L5vKOkTsTeDH42SpQnq
+xQCBf+4S2ZMOtyyD6LYVeR4pkWycJIdDtlfKNdsNt0ynitlyLDPqGM3L1hShfqpE
+9O7TL5rNzccnejc4KzqiSISjAF3tM5nYTPbyfOlx44XS11K36OMnMewPQ2Yu1+os
+NGam/6TTM2wshx2zH2bgxq2gGKIEcNn9Tlab3bB2fxt5Gu0WJZ+LuMW0KtWEGLJy
+K1kWkUE7cnF/sqtsbz6sZd5ooyJyOuJfgI+Y3xNeqbAaBDddYUsuORrXbRzRNIrs
+PlwddJQzcZoQ9lyN2KsTUi44zv2oc1BNBWQtRDZqimgdFouybnnhcjAD7Nj3mNLG
+ewf1vFubZeQRIGFkgwBBMgjU5HST1BDNbOrMxZiwmvVF01k6sCDvRlxRVaSZepBA
+ewwenA4hoaYpcXkgooFDuLfRFzlrtkVsO/3mpLT9PYGrWbETfdkKbWhQ0dwi/Vo2
+7eptrrZNJy6oyLzNk7ptXf1M5DVXDCjqg0yH+dE1RrGH+ursq0q845j3iwhMX7sL
+xlJcj/Fi8kkKI2YrzsDNbB557JK3RuudID2WPu7EuUYgbSVckX8Jl8P2OhH+DrDi
+PBHkJvnxaWLs9tZA3edfS7uFGeTobNP2Lk5Xvc3ecf1vGsnnLsN3F4UgT7u2+cKP
+WQ1CO0fQcJd7V79NzDqf/q7fPn3XM4PlykhZIVQF6fZvGpo+BJKyqOGRuNz/0YSF
+D8mqyA3RJxxkiIuUi9hogA52kuuMd1Jb+rZWMJzpg9OB6/B1X8TVR9NGcSS7qxyl
+Fl8+Vu9MdDT1VTtrWrAV9WjdBHUfrZ7ZGeEMoe6ZZHz7V7H31mUZlNZ8TWrRlv4r
+e2ph1qYp2DPNpX2hFyp62q/2niSZ4o98Z6IcIxF3ARjP5NpEH/n4lyeegXhBfC+E
+BEc33I6FFiq/vLixq51DkE4Dl2ou4TOZzpdSive3WYU+KVCQSaOFQIMPFwjY0ObN
+5rk7in6sac7IxPgAr4wB1xdwiAwKisDs3okGAAXzhXmkiN48P1CGaznDKUqgViih
+xiA+3cxCn5xzviO+lpb6A7V8NEgIHeSqL8BeRTkx07a8smQEHZFi/wjIc9DNYd57
+xDtwbcdvXfoJmtTQGgkzIWdzXuy0Gy7f3FmDV83WBfsv9RN9Kpgy8wn9Wbj4Z5E6
+HaIwE1/hQkXQSft2EmUrnGH5zmHDNf6FS+HR2w0OauvIsfkZ5ULrj8iy4byTzVbi
+4YGMGQTdBSCuVV06seeFhQpdSkVIBSM2U4ks6o3hea9MRx2U1CeT8sYria7trvdJ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16.pem
deleted file mode 100644
index febf0898f0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16.pem
+++ /dev/null
@@ -1,164 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree2/CN=Invalid DN nameConstraints EE Certificate Test16
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA1
------BEGIN CERTIFICATE-----
-MIICrjCCAhegAwIBAgIBAjANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBETjMgc3ViQ0ExMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-fzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYD
-VQQLExBleGNsdWRlZFN1YnRyZWUyMTkwNwYDVQQDEzBJbnZhbGlkIEROIG5hbWVD
-b25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTYwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBAOHnVdpKkQqlze09wh5nIsO6XQJwHBHVdhdaB5eaMXveb0Vj
-yiVBMk4NTrzIJ/7lL9J/qc4WzXAr1u1AFed4shRiiOEMAT10BXPoDfS3FjPytZC5
-UWXRE49DyE8Ksc9hSa0IBwf77wKXBAIM/ygc8XXYwFLHWy0Nbq1C2mo5AFpFAgMB
-AAGjazBpMB8GA1UdIwQYMBaAFK2SFB0uK9H4irG3IS5+jhlpPDR1MB0GA1UdDgQW
-BBT3GktmXZE00780GNgXA/GoC2kWPzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAJtYdflHLEVQC1ar27ke
-RBKtpwSsi61XphZ/gDlrI7bo3wG41pjy5tvPv8xuIOsC5isYgU8dyjJw3CF5LRdF
-FweDdftBHwQ/zmwL1sWj0h01k2ggA4c0AHDqG1J9gPKRO42rdqcRUQ2wgq1rZSDu
-iaJY1seFNoxyls5MxFF26Gue
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2DCCAkGgAwIBAgIBQDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAti5Odfo3
-pSf6p8iGjNMBwSlKozpyyMbXSxEjpiDvuZpllmjLqoXe6tiWiee19xCly8MnbxXl
-4Pc6BglZNZd+adRIlPrFUPIVmBM51RJLvzQKjiTRPwrPwsJnizD9KLcr0Kf+e9Gi
-LHBlqZM41/0oBCVuAX/5Y5zNNiFhFeOnkNECAwEAAaOB1zCB1DAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUi+O4WFafA2rfPdgHO7MH
-NuHLtsowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFgGA1UdHgEB/wROMEyhSjBIpEYwRDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBleGNsdWRl
-ZFN1YnRyZWUxMA0GCSqGSIb3DQEBBQUAA4GBALkukW5Jb4GxdEYN7MeIVxnZX8fn
-4Ulh/l6uDFKi+R8UZyMWYp0oi5F0sYQrrsjBwpg/ivfpJtxLh1uMEAWp98vMQPFZ
-Hoo+ma1Ulfh6qAGv8C6EgA5sxWuNO0VrZsMbNsQeqVLXKvkBsYxrUAHXBd5ufqEA
-Wofw3VBcFpqgolnA
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA1
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
------BEGIN CERTIFICATE-----
-MIIC5jCCAk+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMT
-Gm5hbWVDb25zdHJhaW50cyBETjMgc3ViQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCmh9zeM9BeyKndgrRFYNxn7+qDC4AKVdFmpv1ciqlk3RwU04FCEhC9
-kN1hhqnghWi2XzHZ67kQD/azFMLQZU1b0JTg062pMox1ezyVsZCejrXUK8kMHEnW
-SNSHkU6KnrSC4aHU5jSV8T2uANRsR0wQ80iBfuq+XcyF3r8jVsbpqQIDAQABo4HX
-MIHUMB8GA1UdIwQYMBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMB0GA1UdDgQWBBSt
-khQdLivR+IqxtyEufo4ZaTw0dTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wWAYDVR0eAQH/BE4wTKFKMEik
-RjBEMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAX
-BgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTIwDQYJKoZIhvcNAQEFBQADgYEATe1pMNm0
-Ae3tuDLPpXrBaSog47WFgLklqGnB7xH9+4x4SGehRirWS/0TH839Rbb/rmp0XptG
-ECuOUS+tqrhiMPYmWxv65XMpPfwKHjxj9etcu/MgXytG7l1kFwuHP08zu43BEqRS
-JY0NuHpCTzI4Natc8cB3JTktdUOAF2P22c0=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:E3:B8:58:56:9F:03:6A:DF:3D:D8:07:3B:B3:07:36:E1:CB:B6:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a9:3e:f9:c3:5c:b0:eb:85:59:db:c9:72:3e:b4:2b:30:6d:22:
- dc:9c:9f:fc:8a:ad:9b:1d:48:b0:19:9f:47:3e:d2:44:6c:3d:
- c4:6c:03:bb:82:6c:26:85:eb:7f:1d:9c:48:93:a0:9c:66:25:
- 85:b1:5e:fe:71:a3:d6:2d:4d:c0:cb:3f:1a:46:fe:ea:31:8a:
- db:d2:1d:f5:0f:b3:48:ad:0b:48:0a:b4:19:cd:e9:c5:5d:17:
- 6a:3f:f8:bc:99:39:5b:29:88:2d:7d:0f:b4:be:94:e6:8e:a1:
- 7e:12:31:2a:46:f9:3c:1f:d1:c2:69:c3:be:62:f4:bb:b0:6b:
- 16:a2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAKk++cNcsOuFWdvJcj60KzBtItycn/yKrZsdSLAZn0c+0kRsPcRsA7uC
-bCaF638dnEiToJxmJYWxXv5xo9YtTcDLPxpG/uoxitvSHfUPs0itC0gKtBnN6cVd
-F2o/+LyZOVspiC19D7S+lOaOoX4SMSpG+Twf0cJpw75i9Luwaxai
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:92:14:1D:2E:2B:D1:F8:8A:B1:B7:21:2E:7E:8E:19:69:3C:34:75
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2e:dc:3c:fd:cc:c2:50:20:4a:d3:de:11:60:93:75:ef:28:af:
- 87:35:19:c7:47:5e:f2:c0:73:35:5c:47:4a:bd:54:84:f9:04:
- 30:4c:a1:32:27:85:14:cb:ca:72:9e:77:70:14:ac:20:72:a9:
- d2:6f:50:b2:ae:b4:29:03:fe:00:c4:92:96:14:68:81:b3:d2:
- dd:60:41:d5:ee:d5:66:db:b4:f0:d4:5f:a0:6c:93:d8:3e:e7:
- a2:59:90:af:9f:05:22:b0:1e:f1:67:06:2b:85:eb:dc:a3:16:
- 13:ad:74:89:dd:db:2a:71:8d:a8:22:8e:2f:f8:ca:7b:15:f3:
- cf:32
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBE
-TjMgc3ViQ0ExFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBStkhQdLivR+IqxtyEufo4ZaTw0dTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQAu3Dz9zMJQIErT3hFgk3XvKK+HNRnHR17ywHM1XEdKvVSE+QQw
-TKEyJ4UUy8pynndwFKwgcqnSb1CyrrQpA/4AxJKWFGiBs9LdYEHV7tVm27Tw1F+g
-bJPYPueiWZCvnwUisB7xZwYrhevcoxYTrXSJ3dsqcY2oIo4v+Mp7FfPPMg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16EE.pem
new file mode 100644
index 0000000000..c316526811
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest16EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: AE 1E 1A 0A 94 59 91 60 A1 B2 34 57 3D 1B F4 FF 56 01 07 37
+ friendlyName: Invalid DN nameConstraints Test16 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree2/CN=Invalid DN nameConstraints EE Certificate Test16
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 subCA1
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIBAjANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIEROMyBzdWJDQTEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjCBhDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExGTAXBgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTIxOTA3BgNVBAMTMEludmFs
+aWQgRE4gbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3QxNjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANZg8OxefrZytpf0OyjRrUzPyqCB
+BZveBF5ZuHB7qRZwF/Qq1v05U23mk3+7fz7oE6xGAgPvNKjktkfflGZI2hRdPNlN
+GGqlc2YwMWDwLTmtS0hyyT8Ui7AL0cwHJrDeau7litk6uFOBP6VE7FlUEnMU9ENm
+hHBOmYt/tjARDf+kzSle2+saArLbWqBPdMtLtRwD3vTS9Zr+DvccEn2Jx7YiSZDM
+tRJaPgoiv+15Voln0E2/XS2fDdog4olDCO5fZ51KNIokMmp+6r55yevXxWxUae2j
+ZBLFyfD7hS3NTGDBhCFEry2dbRZb/sXOlPSwKN+x+QwCWBRo63UArRoi348CAwEA
+AaNrMGkwHwYDVR0jBBgwFoAUgLzHLveOGn/xOHv0Nevd6VjGPFAwHQYDVR0OBBYE
+FGC39OnVftLAciz19L+MYPKsjyXGMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAE7YpcJArWSxTC/zSZh/
+22a7N/+JOQysAJJ+wKuudXUeN//eiycICbpkUy+hVF9JtZ8Ryy07GyEXm/CMg/Ub
+PX1EEvIkH3nyAI6rw13hw2PywCzRabDXwaipbRU8A4dhTh3IAcuQoCcnO4gYVBk5
+2Z2Wl5v1jXsCzgEj9gUuZdwLeWqJ2NIQvrOIvauRDP11OcUs69lC7zjJLWgCQ9y3
+2UC8nFkkN85P7Mc4A90HcGPJuc1DnPCTvhY5JdXem9/snjVcpa7PTbusyZbrh0X0
+inB2hldbyOVTyX4mpUsUW1h2X3rOETdkBHZuLwWRwbyXc01ElGuGnfgihaX1w1i5
+BoM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: AE 1E 1A 0A 94 59 91 60 A1 B2 34 57 3D 1B F4 FF 56 01 07 37
+ friendlyName: Invalid DN nameConstraints Test16 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EF370C6F852FA1AF
+
+Q+F/GgVNCGwQOIJ1hUTYigCtf69Z66XJ4h79h2Tq3LzgC3OS55xpdLWgxqDXftbv
+gxZuben61n/Ui0vpQs5g870JJcYLJfic5DXAlRHsP+aXOyUssvJ4IV3UetqnGjF/
+0p2rC0jgjdIR+jdlXLjPU8JaegWMdd1/Mx67PW49CfWg+ZvnbIs0UB3ADwrjBrb4
+OKL9dkVXqg0+pPjXhOgD62GT8DUXtAH24o76E6gJLBaivXHnihxx36dVdmOYampv
+kVn9NHir0isprjjpY7Es8QLDXc16HvEyO2oUSRcE2x8tmblUyuTrm8+CFfYQ2Y8P
+0zfa8bwDdxr8L3/DTAgsam/ckjo6wdOhvkqvMiiErl8DdoLyAysCNRhhDROkr62V
+syFeJfzOP+5RvHDkMaHTt8QpsV/2yqW8LoIyxhnDHxh4+SrZDjxg/3sh0aNApWOl
+m/WVsBITcdX4w5XtnkqqOWVr3YH72aPy7RQ6MSYLHSh1q2vrYOrbigcFnwFWFag1
+ZlavGpxatKwADvpCslZqM7NtSQDF8onL0vDaZ/1hU7BsLamfSCmXhlzeLyqCKeLN
+XtC3fMog4Gy8qOYC/JEYAIptZMjjuocDfbGVhUrJVhXxqzBgUxxAtw4Pm1ZgNxTD
+0qS438itpk9U2ZT15YqTOidKclWOIYEtJx1BHIZXCbgXl+YToHH1WhSDlPrOEr8v
+6Ptbd6KgkZhlpkzEi5wFo5iWCtHSXPD3dcv36goD/eNU/FcjtuTSWUtQdrS6sBks
+m9luLlHosaVb8VImmbQpyzLyWBVWg5NnlO+DjWM7pmQbFRGsIuHc9eP8H4TJ+6ci
+P8AiV3GF0zQbYVBT4Uvkk3J8lGSsKYOFYkDIrxaLid66dWEjBvTO/McXTbs0EhqO
+iOLms7t+CH1Y0FWhL5fYOWj5GxjY+ZNPv9L1geVSPydGKw0nCtpASXyeC5RTJ0lC
+DOBEBL727nwXe847qxdt2IcKJPEHiTkyO2+wUxw52Ge/Wbb3iwF3uWJBDZwiMzdL
+3RGAYe1pCL/rh4nJ2abp7iLY5iaqqTlKebSV8KQf8jb0o/oNvNPP9Mpkcis3afIG
+ntlCE/lxCSSxG9VxMmRUZaYIiRP16c3yGCNaBi3DKXTNLXUZ7q+9USq0co5IgpkO
+f9eA+GZPYBkvfxXUgIN396nGpMOxlbkueDjK24oQmdYqynVRslmj0VxYGC53nrzw
+8EO5qdETufndMNCWWB1yy9xxxNjDI8DibSdC2nd/b/U4egRC6OJad7RwpOWy6Kdl
+dPQHosJBaLJLkpCjA8HXgnEcuk3PrdzjL7MiO67QxbW64ZRA1OD7ib8iS60/ijyi
+7kloHMH4WJlf956AKxTENts8dbKaXP5H45yxuc90H0LhZzenSOrgcFIIwGzGZtow
+yjFHY+5O/lXvXOgKSC3UnsdVXVqrw6pvKrnWioodr647xfUYw252KSD1D/xW54wc
+Mi337lAgoExNUJEzXilq/FVYksTvcnzCgIJarut6jqCuGPzTvVPWz6h6bgQv6A7T
+fyUTgdS3WCH5nBhGQ1k/CWySuIsDHuxrQVbYBpBl2u8xLEKxTgOx7q3IZly3FWj/
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17.pem
deleted file mode 100644
index 0c9aa3554b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17.pem
+++ /dev/null
@@ -1,163 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test17
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA2
------BEGIN CERTIFICATE-----
-MIICrjCCAhegAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBETjMgc3ViQ0EyMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-fzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYD
-VQQLExBleGNsdWRlZFN1YnRyZWUxMTkwNwYDVQQDEzBJbnZhbGlkIEROIG5hbWVD
-b25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTcwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBANw5GunDquXK+XElcoKtGRzY1ESARSYhxi+qK4BM6L0rxSe5
-tXiajO4Eb379Qv2z7wkn224q4lkLiiry/gmRj27aTjhch3XF5C7E2hIeHz5qGtcu
-uY6vyT4DxweIYibYubyBZC/MCk2YuLtsLiSd5QuyXXmQYZzeyu2SpRax/nXHAgMB
-AAGjazBpMB8GA1UdIwQYMBaAFAtIvihxakgkCjziStQFKuLXHjXvMB0GA1UdDgQW
-BBRFrHYfuo8284F89Fc//hnutkf4KTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAEPuGBhTmRXtD/1JNHgo
-Jj8yfLsXQzG8AENHe1KZs7Kpj45M3p4u0TGUJI2S3MXh3IY8gEf33t9eQbJIY0s4
-AiUXe1G/CjtDeo5ZkfTpZHRd654czJ9oLQ3c2vczwYEeaeLxQXqEFS0xewIz5udq
-AUVVqV79i9BB/BOmAx9qBkiH
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA2
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
------BEGIN CERTIFICATE-----
-MIICyzCCAjSgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMT
-Gm5hbWVDb25zdHJhaW50cyBETjMgc3ViQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDCH3OWCAvPFZXpNTKMN3DoOML+FK32+icT19l0MQXIXBqoJyw8qF2z
-xcl4ahdLxfSFpf8OF3ttKbzN5fk2/Dxue6beAMs0L1r4VUilJaUhOmTMrlYXB6UI
-QX2nzlu6lZbNrI0VFt8qM2C9CdbG+2ZQuJQQO0BtHXWJC9el4t68/QIDAQABo4G8
-MIG5MB8GA1UdIwQYMBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMB0GA1UdDgQWBBQL
-SL4ocWpIJAo84krUBSri1x417zAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wPQYDVR0eAQH/BDMwMaAvMC2k
-KzApMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMwDQYJ
-KoZIhvcNAQEFBQADgYEAV7W8Yarxgw2gPgl0gz1Vz7IdH6ZbzLBpsB0W+gyPTd+R
-toE/N42Efda3DIG5BoxqTj00uc9j2GF5LqBgKaEieenzkv5E6qbTrZ0F/FdX1c17
-DBpRvkchpd4FACNL+FhSq824LEKdBDOx669LmsH664nk6NSPtv04LjUxa+822aw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2DCCAkGgAwIBAgIBQDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAti5Odfo3
-pSf6p8iGjNMBwSlKozpyyMbXSxEjpiDvuZpllmjLqoXe6tiWiee19xCly8MnbxXl
-4Pc6BglZNZd+adRIlPrFUPIVmBM51RJLvzQKjiTRPwrPwsJnizD9KLcr0Kf+e9Gi
-LHBlqZM41/0oBCVuAX/5Y5zNNiFhFeOnkNECAwEAAaOB1zCB1DAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUi+O4WFafA2rfPdgHO7MH
-NuHLtsowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFgGA1UdHgEB/wROMEyhSjBIpEYwRDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBleGNsdWRl
-ZFN1YnRyZWUxMA0GCSqGSIb3DQEBBQUAA4GBALkukW5Jb4GxdEYN7MeIVxnZX8fn
-4Ulh/l6uDFKi+R8UZyMWYp0oi5F0sYQrrsjBwpg/ivfpJtxLh1uMEAWp98vMQPFZ
-Hoo+ma1Ulfh6qAGv8C6EgA5sxWuNO0VrZsMbNsQeqVLXKvkBsYxrUAHXBd5ufqEA
-Wofw3VBcFpqgolnA
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:E3:B8:58:56:9F:03:6A:DF:3D:D8:07:3B:B3:07:36:E1:CB:B6:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a9:3e:f9:c3:5c:b0:eb:85:59:db:c9:72:3e:b4:2b:30:6d:22:
- dc:9c:9f:fc:8a:ad:9b:1d:48:b0:19:9f:47:3e:d2:44:6c:3d:
- c4:6c:03:bb:82:6c:26:85:eb:7f:1d:9c:48:93:a0:9c:66:25:
- 85:b1:5e:fe:71:a3:d6:2d:4d:c0:cb:3f:1a:46:fe:ea:31:8a:
- db:d2:1d:f5:0f:b3:48:ad:0b:48:0a:b4:19:cd:e9:c5:5d:17:
- 6a:3f:f8:bc:99:39:5b:29:88:2d:7d:0f:b4:be:94:e6:8e:a1:
- 7e:12:31:2a:46:f9:3c:1f:d1:c2:69:c3:be:62:f4:bb:b0:6b:
- 16:a2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAKk++cNcsOuFWdvJcj60KzBtItycn/yKrZsdSLAZn0c+0kRsPcRsA7uC
-bCaF638dnEiToJxmJYWxXv5xo9YtTcDLPxpG/uoxitvSHfUPs0itC0gKtBnN6cVd
-F2o/+LyZOVspiC19D7S+lOaOoX4SMSpG+Twf0cJpw75i9Luwaxai
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:0B:48:BE:28:71:6A:48:24:0A:3C:E2:4A:D4:05:2A:E2:D7:1E:35:EF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c0:0c:a7:28:80:0d:2c:71:66:4d:67:82:ec:c7:30:4f:48:29:
- fe:d4:20:82:f2:5c:e6:ef:24:8b:9f:f2:b8:c5:3b:e0:86:53:
- f4:b5:fc:67:db:b2:1d:45:77:8a:78:47:eb:63:bb:43:b8:14:
- c0:05:ff:ca:7b:d5:1f:fa:df:e7:7a:a5:39:e7:00:ed:4a:d9:
- 6d:fd:d1:78:a1:44:f0:71:f4:89:4c:52:d5:ef:99:5c:59:eb:
- 80:c4:5d:ed:48:2b:5a:55:0b:d1:df:4a:a5:49:69:f1:67:a2:
- aa:ce:9d:99:9b:74:0f:ec:da:60:d9:3e:14:45:a3:6c:5b:47:
- fa:d0
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBE
-TjMgc3ViQ0EyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBQLSL4ocWpIJAo84krUBSri1x417zAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQDADKcogA0scWZNZ4LsxzBPSCn+1CCC8lzm7ySLn/K4xTvghlP0
-tfxn27IdRXeKeEfrY7tDuBTABf/Ke9Uf+t/neqU55wDtStlt/dF4oUTwcfSJTFLV
-75lcWeuAxF3tSCtaVQvR30qlSWnxZ6Kqzp2Zm3QP7Npg2T4URaNsW0f60A==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17EE.pem
new file mode 100644
index 0000000000..7cf51db10e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest17EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 0A F8 83 93 BF 5D 4F FC 86 5C 8F 47 1B 63 B2 D7 BC F4 A3 A2
+ friendlyName: Invalid DN nameConstraints Test17 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test17
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIEROMyBzdWJDQTIwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjCBhDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExGTAXBgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTExOTA3BgNVBAMTMEludmFs
+aWQgRE4gbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3QxNzCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMP9rpCat1D5Io1BWYqPNBT3HkkQ
++k2vKuqHt9zXif0WRtnmGzqUvpy5crHBlToyawqJQAMVPMt5W/gTJrzzV+Bf79+X
+yetrlM3qs5n5eNfIU5D897S1AEfPIkRdjR9kdL1xZYkDZrEBmFHgsRS9TDK+01rt
+aJ2qOKscJI1z1ngZUZscSLwCwznvw44W5AP6WLxX+g0ERBsNRjakWQS6JlWgGvn5
+oq5PYqnrIh7TgtGgjL9jVX+xbz8lg/f5iLwbfTw6SxGMZV+89jrMPHjW+58NMUDy
+2kn5W7B6eUqUOA2Eb+oYKWLujNqYeaoUZa5TUBo2iUV9WnJ4ndiMHwzveOUCAwEA
+AaNrMGkwHwYDVR0jBBgwFoAUzATtaigdft5k6gCIKux1Eb+lLmcwHQYDVR0OBBYE
+FBFLTj7lB0xsW4f9PPb1I2VfHkVqMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBADjr4s6VekQmcVVddOQH
+8wbIQNXHEQINEtlqUQqaCE+wlszME24sKPs3qMNEuVyQVFvwZdpnPXF7/oSxAyMw
+yO/hzSGcJmBEd1VvlabY0IJ/PAy5vq5XuQk0sWbWRAOF4bcgAdn8gH0vCX+6+ajC
+o7znSglF/G0vsEkaqPhaUk7Ookee59hpHSKOOqhp/f82/BFjrF6lo+AJcRKqj3rx
+aMckYizxJ4+pLPEtG7shS5KKZsz8PW6DHDhJpNe733gSKU4wx/Lf9BNBRdlKmnqo
+EmIG/lzkZWwd4kh3/CGOko7qTLcLQy3ARHRQg6z+8qhmtTySJriamAHL/3nIFKCx
+z84=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0A F8 83 93 BF 5D 4F FC 86 5C 8F 47 1B 63 B2 D7 BC F4 A3 A2
+ friendlyName: Invalid DN nameConstraints Test17 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,076EA454D8F48AD9
+
+znVgT6cIGCKODD69NLk8D1gEFWz5Z73ySLjV0FgXUrhyxphSEAeEcg0VI9bP7qzJ
+LBTpalVSXEaydZM6cHxjD68IYb3C6hnX4D0DHshzq425oK/BUTh8623SLxDTFLA3
+pt8iX21ubhngnFRNseZAZgZLp9xdH63mlW/DwAn0PGgks4mhdjHcJUmkKqsVUavZ
+GSoAjyC/xi1TEE/sasofRr5BvoO3xbn2NnzgO5hPPbZFgZzJ7KCHl/QHm0NH9LBl
+Vmmb0es8oAqL+z3NfcdAJJE7Czz2ItXfl/iZX9bmOv+u+RWPZlHI1PwTnaCCebcS
+Ks+n+9J1CaS1pu1ztvOSJXD5C2zOCpcWTwjTnsLs9y8Vc+MBls5PDWLA4qx9tiqR
+dF3rZBBN+xSWZt0ahbHLkI/F1jMBZtA8OOc0eKs3+kmadSUr/koGvyN51jydWBJx
+VRsku6Frhj6/RSfOEi2nB1wg6D7lryg29+x5/UCj1vZeT31r3J9k6UIZvd0c2D77
+rh9OiIwO2bNb3enSiEd2KfRPCHKK5LuEwq9sECZRYjCYksRt0vmFRflGbR22nvAV
+bBEwxxcGxC+T+XWgDJiIoWq2d/C77PiSAQTVaSE5WHEMFJ0MtxEvw5mAv2g74lIP
+cj/hD0tC27mB94xaLIfcHlQT6CtCHwYSB/7zlVdMBHJbwyjTIAvqIFYwhvLweCGC
+Q0aUKqXwBVaVvZypZkGKnjsUukLeX0ISLkrmMv0r156nTmh2pyY2AaSDJi3jcjbd
+UAnE1wHbuELkOTsyznDgxMiOFGlySEyyzGWSimzrmvCnecQOi8nV0YnfG7S+ITpb
+FBVY9tfP1ExOJT0TJURihJpWmXNKmd1LiJZTa+eXZVaqNKz3pgb81tPFcXZue9rA
+vtyG/fG67CFoJsPorFEO2r5PwbIgxl+S55/oTyc1DUDGF8jGa5CCj7V8OnPH2/fr
+eJ4x4pk/bsjzWIZg5cFHmQEFZZZTjVnsf5uiVGCxKgOImd4maWXZFv2nsG4RXUNf
+IwgJcNXeDxgEUA3RDFyljIRC/qtedSo+dRiPJ2O2yjsnjwg/o56MzjB8EkBIUrH6
+AD6CmUxweF90v1XShplFKa8/Z9suBTmXAvuwZPXLbES4PpLwXANxDGCSbLNaWfyl
+P5Vs9AmwuMbI0QBKjiWrxw4mijFy2Oim5JX8GP9HIYhtFIvYy7JcbBBsI6EZgyCi
+ZVAjdyHg/ECwrPBsRRIRckjYfCCJ02ZiIxYQNec/AMlvJUo6MeKl7Hl7cjyAANDQ
+GXZxilURtg+ITxh+8NtjIrtQDIjxKdyTNq99Bk5UuN0bAu5AklnA8asConrhp+su
+4VcFnYMnlrhwNra6BWna+Mlw79+DF484nMbaIcuDg0vPuzYCVwgJvdV6JOWWXM4b
+nb4cIr2oY6VD+he3ZkFYTArPS0A+aZ0eZphwJJdPy2T1B4Ed5bicBRIq1eEN5JEI
+L+eUyW9HdSf8lso6eMRZ7MWPO7L0KNfXf9yPMwMoATgrOoX/3H3ktIguKQWNiAuT
+ekMbzY4kgpm50T7wsBPBw7K4+1HLIdW0xxj/pGKKXstvNiEigu3BTtUqLSO5ZGGm
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2.pem
deleted file mode 100644
index 04a7eb62a5..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIICqTCCAhKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB+MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAsT
-EGV4Y2x1ZGVkU3VidHJlZTExODA2BgNVBAMTL0ludmFsaWQgRE4gbmFtZUNvbnN0
-cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3QyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCbvVmVPGFgKGPBqkMhQ8HfwsS10dQ7ark92qOnKM0cmOtqxp7Y+5xK
-fVwtP4znhPQr3rGzj2x81FCIghi3hwSRBg2O6DhpFdTAXAwHnM0QkUb29QTNqRfW
-E4jOPciTY/BonXFJXf+VM61ntdAT4aoVshmiy64p2SBUhRYA/QrYuQIDAQABo2sw
-aTAfBgNVHSMEGDAWgBROLqPn2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQU3rps
-AkOOTOy07L8tC4ckaa3lRqMwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQCOtc7hRrlpfYG3VtjPhElE0x7R
-VEiASfooTBrkKHNkajTVNgolaJq1+1UqMpIFCe0KBUL+k9YQgsjDbr3m/oL7ml3x
-9iNWxEjBOH8YRaPvArpcb6HMvMVTdbInB7T/ogFDs2bdUBWt4H2KJLoogGJjLBX/
-NkpGvXdFmxasmv0wkw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest20EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest20EE.pem
new file mode 100644
index 0000000000..3635391d3a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest20EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 3B 85 87 B8 28 20 E2 20 BE E0 2F 14 5E 60 AD D7 A5 CC DA A3
+ friendlyName: Invalid DN nameConstraints Test20 EE
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBCTANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+ME8xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MR8wHQYDVQQDExZuYW1lQ29uc3RyYWludHMgRE4xIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA1ExvqY+GA/Rkxpv9Ks8KcNqtdknXm5idOg9XrvIe
+d8xy9vkyIs8iZbBgoOI9JI2mhabIchnw9ALe+XFtKL64UEWS2dTH8EqhLgkoIfBB
+B8kHZhNaiUxf6kjvOx+/H4TWeTws9iawctciW2FwmmP4G4bZlBP10tZFAspJj/fu
+UWJ4rZn4jks7qHNpUOpZw4z8Q8Xf7cKLLSloCIDIJtyUxpM2bT/fC5w2Q6Z3MmKQ
+BMi38zWscyG7z7zy6ceYyRBlG5xRsgCYUsj5sWVvtHn3uDpJ6XAW27Im3YxqnRuA
+R7fO/i4pNX2RZpkFuJhQ+CveyXXvj0loAbcyDAX8OcbnHQIDAQABo2swaTAfBgNV
+HSMEGDAWgBRBeEJGzU6ogufhOd/3qRbACvzvhjAdBgNVHQ4EFgQUWEq64IDyyEM8
+lrIC90qylY3WwjMwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUD
+AgEwATANBgkqhkiG9w0BAQsFAAOCAQEASvXlo2YzLidKbhlVkkfFsdclc0NAn1yT
+YgVEgLpFixmVilXQqH4lX1cZ/wkFljd90H7VUQacMnqfacLOyJyHLBhxA1kBv+bG
+bERpTDveXwmBgNxs2uMinO+EbCEZbWdSrALyUyLrJUaiqVln/m9gtA3tnLJ6/9lS
+uHcZ8uYHjZC05SQOgCp2GI6yo/nS0Pm4D9Z6Ljh676Zoc+Xqe8mbOPUdCNfnv/xS
+6jIIN7HtRNLUWlrq0RfT7T2oOls0lVX6vE6tunEwh5Nqw+aHLFcQNRJw8nqeoJ3o
++1t4936HAgpU6H9+qejS3qXKnGSalhyEZF4B7YIjMw+QgMq1iy3FDQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3B 85 87 B8 28 20 E2 20 BE E0 2F 14 5E 60 AD D7 A5 CC DA A3
+ friendlyName: Invalid DN nameConstraints Test20 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3BAB1EB257C75977
+
+RJHzKgebVBCq5Ke0uIHW19JC7LSCkTYhTIdLpy9yRhD3dFndup70fBmZrWu6Sgsw
+FNU22CTI1L4JfftRwry0/xsM48FGHdW9Jo8D++OOeC1Rkzplw/SC7gPpDpE0YP/f
+iedr244vRtUemUI2Zqqh2Np/lzrIl8GWraoRKsCGbGzWe7axPtnrlMaP+/YR3m2D
+cOVmDl3iYwwkMYgDZrO7lHop6fdfCRnU32Aws3ooio/eR2/GUbYJVmkxP9p4Z1Uk
+t6SaBau1R/YnEKYAxJCbiUhStiSonBgvrMkZ7uMGdsMTkGUqAmHgtzsKWq8EKJct
+viHL5AZ2+tGB+feO4HGnT7ANEO5V9+ygYpfvbolGSpB2Ym4E8I1e7henuQtOSTu+
+dmib/dKHovXFtB5AVy3kdeP2cw74/bLScuads1oMR4GKn3VaNzyFbdY4JkQJiK6Z
+rfKYdJkna6Go6bSVHAb7nwvDLcyrFc+5mR6bEz8j25gq/RWm2N22dqRG8bBo85iM
+53KAhOYrYwd5AivXjGtZ2gkHAbZ6ilublmd5/7lNsFQbUatHMa0w7Db/8cFADDfC
+wB42czsmHFBE68jqV4AUvIWssDCPXiGyGsZbpRwxDPkZLg3iXS04LmB03m0+f+L2
+D0DxtBiVuczD4jhnfCYokjL41PWGT1gNaovyd3JcXNUjOit6m8ndZ3hih1B51i67
+gLXxjaj80ZFbNljAUXo58GFinvYM5PlRKTOGN96PZflivJQuy6RK8UY30O40Ir4k
+9RX7MFkaIKDnoprm3hv8KPaAP6QFXuCUNwG0XMdEX2Q5I0LKi+Gu2ADfMnEq9Ka1
+rQSzFt+Wq0AWrisUy48kgAlQeBYkfzE0t6njTO4gJJPnMwSptBhPnFhVHH9mF/Fw
+PQl5kn0sHi9sNucvQ0Oc7k1QuhbZPM2oK6YngEEBC10t5Bu/9mDZnBOqNQIJbUxL
+D8pBk5XiPNal5MQkeTCFqya0vJTXZNIcvsgZTKDEfmx1o+rblG2YSRZ+nKux4nGf
+iPAPYRjymw8+YyAnpbPRcI6pzF+aKY1C20gs2AqWC5dgQkOlcKY+8kFqeXp3Rh7t
+S2uz6p/uCupugKKd+q5DrGsNQB9eO0D5vdZ4Aw4rnLK67MEbJgIaneXzl34xoQ76
+5Lf9ws7jLo0jvhq7HztTyKTvHUJXG+8aOb6Zg/S1LK2LtlGly+h81FECtNmXR7LL
+t0F84jkQeMrIcEtmg0QYoJ4fTAvukwhdeRfggYgEO3EXl+CIDWMSXVcn0++/SFCO
+QXufLmU2ISwZGc53oRvC/eiDQmT46AygqJCV5fMoDwa5o7X4uYXh9+H9Ayxa9Zmu
+VT/59nvNhU5oNI1owaLgsDAywLm6l0vaRbQQVpHYxwH8D49uXXJu3Ad+cz1NcSlr
+/L3qrGJ+42FNaMrT8NfrC9MjjAOgGA/yHAs3C9KdJq3SVB9Ff9r7lFujJGHVIItd
+sO5nhzgGXwjDL5E/3CTuqm2eTiLm0xxeXX5aK2KwQ7dR7NXcriQgNSQv09jgWlqa
+KAopv//ImlmYGdOrb2UN6+ICTti1hhf6iXEJmAI9YLwEBvuqT66VPw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2EE.pem
new file mode 100644
index 0000000000..60e47e3724
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: DB 51 E4 D1 79 AE CD 38 A2 4C 2A CC 70 48 05 19 03 13 80 04
+ friendlyName: Invalid DN nameConstraints Test2 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGDMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVlMTE4MDYGA1UEAxMvSW52YWxpZCBE
+TiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDIwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEhHHtIQeSm0sk2SFRU1s6R4tZgm0tafsm
+dRRDgwig7Ne2fUawQFelK+hr+kMzQJMCb+ogMkzZfPtgOjDnhH7Z2964MaZPHzpf
+JlxY4aM6A91wZ4WopRp24jyeMmKlH/CO19LqjOc+UBuhtGUHKk4ZFdPac3PMXIXj
+x9ogd57ttbYdjIk9Ix+X+o/tPnrL1Lp4RSjhkPs4VnsOkm90rgxEwNZTyCTgNVkc
+qhJE/0eXgBIV7ZXc59uS1TDVImybZa8NY79ClvJ0Lhl6mvtPnoUvOgOZh+SQu0nh
+OOuy8hzmhqNLqTYkTDzjtVzOHW4wKZ1qfwVjcmXq0fCR7uyHdup7AgMBAAGjazBp
+MB8GA1UdIwQYMBaAFEF4QkbNTqiC5+E53/epFsAK/O+GMB0GA1UdDgQWBBT8c/+k
+4lqB9ybLskI79g0ctafZ1TAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBW6ljxbVxaa654QlFBrLWa3bDc
+FfC1lnbmE0Ya1pzkcIbsD+ayZ0JcKcuLPUjWp36m7BpuIrmEpndmc1O0cEQyqveH
+R9vfSDxd3/R6jVMQbFfa10HVNDmlKrjYyIq+FQla0qv3qn3W2icJWRds031t92+6
+gb+fLBd3YMXEtEH7+VCQNyfVZo+9F2xoUTxKWSr52jsxsMaIdRXjZUIZBI8pZI21
+QcYSdNPk4TxvHgbQijY8+n9y8qV0aPUckZOjo00KczVPtytT9v5tzvNk3JubXJ9W
+hh+9WSe9uJT92xu6e3aAt1WVhCx0XIdg49GK0hFQs50dTT1mLAoi6aGEd8+R
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DB 51 E4 D1 79 AE CD 38 A2 4C 2A CC 70 48 05 19 03 13 80 04
+ friendlyName: Invalid DN nameConstraints Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3A5D187640629E66
+
+R+I5lkrhsMjEbdFbvxmcljp5A0rL8EcZXNyXp1qZtrvNK2wLbKwGuYJfVhLnsKMJ
+y5Iloj/U8UHGe5GhUbxdE3iCmUu3UXheHTyU+IGWQvnH2F6KZm8dopYWMAqZAJfj
+PHJyz8Clv4c03i681QCQ7LBHSa7voWOEHp/9oeheeZFWeGrIR/sUJ9cfSxIBeeDR
+fkNwDsEzWmGtMhT+LAN5A/cA031ILesY3mdDY+ILePSAy5/+x1dcuU8vbebjgvSk
+qx2iXR++ygK6or8UWYP3Cf+xyAloCm5eKmLwQUMZ+IwrR66pXPdCEKEbrMw5p9Qx
+ZrCctSzIH1Aw+Gmy8gTSUCNdx85vRCa8Tn7joj2BK53YzMGtKGzA8BzsV8L3erKY
+oRT3fji5cT4dJRTvxROWU1GOwW/r2lYOYggg+uNjEo6OwWydX06X29rC3fymnkuL
+hsVNOPxDc2ie6rcDyGqHjDpmiYOEppQd23utZKIHQyPhag6rTC3V7AgPCjL92c19
+BT15n6Wa8VXXos6PBIQHWZb4dUj1B9XwTQtLoZZv/RVnUjEMo+NNCpUwvK+5ke0V
+9/xtiFNnKedcbaMVNku9XlmSaKjX+fsmT+wulA65Osc+ZEobJ/EXC4AVChRsMl9v
+ujiG1z+Vo/UKEmIf4/8PXVZMFSLNLEaUAO9wiJeDpeGAvfAT3ScIH70nTyR4q3qf
+4DRXq404NTy8AzCy36PufW944a5+3FP+q3afLuuzWVvytQun6byFZOE6fo7zcOn3
+mEnbG42n9f+3SyS1ND8yVwAR0VoqRcmk5QtacUE1tPrX5pvVyphIZaKsadmf9fsC
+X+TJ1jgkGDCY0RxGhR9uGiPNYPjNBg48o7/w1LSYiOQ6LHwf3PBYHe56E2MSOOeh
+bvpu7eN35J8uwswfXOZxefmEQ3COUGAZnMcHn/q46cyLpEqlf1s7tPyAjIAV2yvi
+9ETgUD+KCpcQSn5qednbVPStEgljRTTM4pR+PFNhNGNgqntuY8HMWzHFjsO2uafF
+0mhn8ytDbziAc6IvNo7xbkTOzjY+CcuirfN7FsRcyxs0qvwQTWcB4yj+c7Wg0W7S
+O8qZ0siZajvOXAgMNHNnYZFG7YiVl/IwMXWTQD2pk6Ff2PEw6pD1c+w4hPO51z5W
+7kUXuwb1tlcmSeYz1PDu1ozcbhJOpSuECq5E1ezX4HrNIbpysTrVlzx3cnSVyhhW
+0AJ7dvVH0NuRBSLhfKlr45K5uVTW/Y1zX5GPte6fauqj2JFvG9NNOeUYoK78HBk+
+dvrrrKpoLHsCiRPL5OJPRRb510+b6lZK7YLW5uIF0PvH3duS5v2m54jcB9HUBr4+
+z8Z2czuSirHRjH7gXp4OTfURUkCI9HMRz1neYw9G+SxwhJWOYoD8iOzEuqmAbLOE
++ErjtU9vz7So8VsvhDSmZy5cyY+pmg1HGAqZvUllR8ZEFPMXk5c53I7NEoHURO1k
+KQAPj3uIv8ONuReC/2/HLH/0qtaLmVdJNuRVqI9fX1X30Z2RmcvKio4GpZYzNddr
+MvwSluhTd8Ir/2KJJ/uQ6mgFSrTvtU/iWJAyft0DOIJMrcziBTDVpg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3.pem
deleted file mode 100644
index 7c2b410b91..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3.pem
+++ /dev/null
@@ -1,114 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIDPTCCAqagAwIBAgIBAzANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB/MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMTgwNgYDVQQDEy9JbnZhbGlkIEROIG5hbWVDb25z
-dHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAyUV/VUccWeiLd97UNg9PsfI5JBKyMkLviLCMbEGIggBG9W+5DKyu
-loDjDpVTzzz4pO4/LQqcZgxP61RsM9sdvJTyxHWpU8fEb3CFFPX47WEEdzFEjvay
-iqEorgwgt0OuiDc6ygpjvje94MD9/tn2oXGXiZXf225UPJOAg/4G2CECAwEAAaOB
-/TCB+jAfBgNVHSMEGDAWgBROLqPn2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQU
-XNZp2F2DSh5YkgNExED/5j5eRE4wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
-DAYKYIZIAWUDAgEwATCBjgYDVR0RBIGGMIGDpIGAMH4xCzAJBgNVBAYTAlVTMRow
-GAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0
-cmVlMTE4MDYGA1UEAxMvSW52YWxpZCBETiBuYW1lQ29uc3RyYWludHMgRUUgQ2Vy
-dGlmaWNhdGUgVGVzdDMwDQYJKoZIhvcNAQEFBQADgYEAF0YtbEJ7UriPhjA5X7Ms
-bjlEt6/l18J5LUKX6SdvzojVZW6wSnfiinjESVIMS7+nvplPU1D5y6BBzB2jCHZx
-uxC/Db9r8CeNek1COMl9nvav4pyuA1e+INl/it59qgfHMZ/pBdsYkYKI3B31oinp
-TSHj4AKIIi1y358PHk3BZWw=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3EE.pem
new file mode 100644
index 0000000000..bbb2dabaed
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest3EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 8F 46 F1 9C B9 73 85 3F E8 0D 08 C5 23 3E 06 4A 97 E9 29 90
+ friendlyName: Invalid DN nameConstraints Test3 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIEVTCCAz2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGEMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExODA2BgNVBAMTL0ludmFsaWQg
+RE4gbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3QzMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxQ+BCdHFQbNq1Bp0GEuyOvaYS2gc2xwp
+YD7153M9L0wHxwNCAnjTjFdAc5e2SLlaCI8Bb3ZbGl8yTKyXaJ25CceHxpyzNWW+
+elq9FJDZjGpxZ5hbiYnhdkS9RVwgkDbVXwv4QfU2blSlQy1vyAH8gfy4mF5XJqfh
+58o+tcECrOZcD+116VHrK4HIMsp+FBGowH6VNhuyOOp3FaXII0NLLUVjBsjGwbkj
+3gFoTq5dPnTuFkr5Q3RQw55A9vcJkmzxHbZko1UiywiVIbcXHneqWrKgyJCp00sb
+w3gEc1Gk8jpKtluNsj3ogmnRrG27SKjcpVhZi+KLzOkAEOvBAVU2/wIDAQABo4IB
+BDCCAQAwHwYDVR0jBBgwFoAUQXhCRs1OqILn4Tnf96kWwAr874YwHQYDVR0OBBYE
+FDipyuJ4S5MA+1KCLlTd2a5ByjG0MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwgZQGA1UdEQSBjDCBiaSBhjCBgzELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGTAXBgNVBAsTEGV4Y2x1
+ZGVkU3VidHJlZTExODA2BgNVBAMTL0ludmFsaWQgRE4gbmFtZUNvbnN0cmFpbnRz
+IEVFIENlcnRpZmljYXRlIFRlc3QzMA0GCSqGSIb3DQEBCwUAA4IBAQAbvjL5yhOt
+fWiiB5PSQ+FM3M39S/xDOI5uMQpo0Z/KMs/ENKT5SVqKeOGuNOItovk0pNpBfrOr
+8jHuo4KuZbWiVUFSrUeB7gX6lJHXoM+Vqa602UHkrxKeZVQGEQ899RTysUH/zW5e
+RIRTbU4GVuYYyFl6PXp5Ve7Fb5grC6moak+bzuF0eN/GTrp1o7l036LHSdAbi2qz
+Blg5KbihSptmhELFjnC2lZyD6eyYvpcBeW0qUjH+PqQzqdOnrxpfy2aH0qGWceMa
+y7RE3OZklQsUbF06hrhuviBgkz988Ih/fVXtANKOIrdsEZXx2UoHOGILDpZxa+WG
+Fov/1Hl0j699
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8F 46 F1 9C B9 73 85 3F E8 0D 08 C5 23 3E 06 4A 97 E9 29 90
+ friendlyName: Invalid DN nameConstraints Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C504397326E13FA8
+
+JVQONDk8Fa+egVOWef6gv8NQR9V+3X5PzOPmNMWb3WIipTeXloazJEki4ei8DaPb
+CA2TkayTEfIm5jN072iS2aUQtSaQvwX6uh8xm6mEmPz+zcyeolxhMfTsIz8n1kVP
+a0FRWb7u75H953g/ojaR1JhiYXzo9RkjbQHnCu2iwt2lpE2aZ8nf1ngJx2p0hcSl
+xWZmWU7DFF1AQIK2oHCjd/iWQr/yEi+Btlr60Z8dVRiRHxVj+UHhmn2+mB2JzL0f
+CFwP2xOQ6z0ksg+GzvVu0CvM0NQn2/SrmlvfiGkoFbCzX3b/I/6raiS7hYR+G9Ju
+X4NK/2jOsFRX5itDjCn1SADuKz1hP4sy6B97psrvDr8aYvDw+nN4Z17mOI2zrvF6
+sP3OOTMnFuWfY9fs23qCnyZ0mmLfZrw3vKxQPH/oBlGDbtM+tRG7jUOdU/NP6XMG
+7mYRU31GKHHsQXYBWSLMRyEBtsnP/fbzU/krPk56v1EdZoEgXt5TeBIt+C5XQpe/
++8eZvxJp2VDkYjE1OTi9CGf4A5aobWy/OnjMMXLzm+R1O0Vc7Tn8rObEDgoEYNl8
+7DfH2ESGEWLbdrto7WmyI6oEPyqRcsxGSIgb7oKLKEcu1dqfmyNxrgRcUUB6t3XF
+1becWs93DrU2p1MIaqJ/rCOE/VavhLXsY1siAFS+04+Fpb0eKgCiffHjAVGa3pgB
+47urVqUo1ztDKZgX2mbrTrPfhfd3nockXoNq/+BJvNsMEXrwwn0SRrMAy4MGhU6Y
+vwlUbnEi2GIXjauvGEF3L1xLtL4m7IuhBuLld+bzo9tqcohdgKpnQttuOP2uz81r
+uphiyTcP5kvEdcY4qNx4C3N/VvryYzyrNK8VwiA790jTYJ4Vvquv9j13NAYYNkv+
+Bu6vkw0js6KZeKKsevMMfS/OR5HboXJjB4yiBpPRtt3jPIikXxfZpokAbfqKReeu
+4StZjZS6KrgRnVCUom7dhVU+N9+KByEk1kNna2dh+tt+bd4RNI6H0ZDb7nnW6yjc
+0rV45zcNH+Hwfn+H7+1wg2ayd8mF/DarKXANKGYXQ6BPa1n8oc39so6vsMO87CtK
+5n8UwiIgKpteEAEy/ktysgi3Hi8ieLJaTylOwZBec/rW8l91AqNzXQYas1xYQU2s
+nbuaLK8n6tgHQPDtq69KCRm2Ds2Mibxoa44uTSWFaWGVDCQT8HwmPdmQLe5xcD/0
+y5uHHsnMrUmw7uGh/BgcKI1D8jCKs8ehVAZNKcXLE5aYzVfKXFVps7L0BmFs3M6H
+6yH6Z6Xmn2oHH7aeuAjqPN+0KCFiDpi5+3yRovgvi0qUXI/h2qvKTLemmOO32Ld+
+x+itnJY6vLRt3q6RE/iLGvCPJTtd5DNyvsHFoaxGZp4arOzlAZfkbKNC5SFu0ijJ
+4LXOkaPYGR8p/2eroUtGqg02tUFz0f3jXOk8d5NTNoiqDawgXJ3E6yTGvJH9Km5e
+eH8WFD8g7OWvwSvcQVQ35hqnoDvpFptf79AZ2qymQAD3rghvmAA/nslcrHzEXk9x
+zVJXK/0I6gQhy1VV2pR0wBHO/XD2mAHrVATuEB+Z3bxQcgL3rP/pGXqui99BNKOS
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7.pem
deleted file mode 100644
index 66b10244d4..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
------BEGIN CERTIFICATE-----
-MIICqTCCAhKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB+MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAsT
-EGV4Y2x1ZGVkU3VidHJlZTExODA2BgNVBAMTL0ludmFsaWQgRE4gbmFtZUNvbnN0
-cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Q3MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCTL1HBt+N66tLKmFW98QfimYn+8h4asDqh1Q919/M7TSNyoUAS9y3U
-ZCRVwviSwB78P1HReztqDDX7dkKHazvtXY28fVhPwv1lCxj8sh+U3QoprauZoukz
-wx6J56XR40wEckL6qf6l2qNeVTuPEQW21ZRBgPEKIqikZYLjl1c/jQIDAQABo2sw
-aTAfBgNVHSMEGDAWgBSL47hYVp8Dat892Ac7swc24cu2yjAdBgNVHQ4EFgQU8nNR
-dG/7HQqs2Y/HH+yF2vQ6QYUwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQA4Lj7z67AHCPqJNPK30vJT6DzO
-BIMzF5uXn1uLFPibVYwzith0bxt+lS6X+XY0D8JVcCoGvQXIajaOz6SQW1Rjl9d4
-/ZtQK/Fa4aWO/SNJ/mUev7+CaFuSpzVNwU6TyY8mBs3THbFis9zVbllRK8ejAkZz
-CrLUsdP7tsReU49LLA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2DCCAkGgAwIBAgIBQDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAti5Odfo3
-pSf6p8iGjNMBwSlKozpyyMbXSxEjpiDvuZpllmjLqoXe6tiWiee19xCly8MnbxXl
-4Pc6BglZNZd+adRIlPrFUPIVmBM51RJLvzQKjiTRPwrPwsJnizD9KLcr0Kf+e9Gi
-LHBlqZM41/0oBCVuAX/5Y5zNNiFhFeOnkNECAwEAAaOB1zCB1DAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUi+O4WFafA2rfPdgHO7MH
-NuHLtsowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFgGA1UdHgEB/wROMEyhSjBIpEYwRDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBleGNsdWRl
-ZFN1YnRyZWUxMA0GCSqGSIb3DQEBBQUAA4GBALkukW5Jb4GxdEYN7MeIVxnZX8fn
-4Ulh/l6uDFKi+R8UZyMWYp0oi5F0sYQrrsjBwpg/ivfpJtxLh1uMEAWp98vMQPFZ
-Hoo+ma1Ulfh6qAGv8C6EgA5sxWuNO0VrZsMbNsQeqVLXKvkBsYxrUAHXBd5ufqEA
-Wofw3VBcFpqgolnA
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:E3:B8:58:56:9F:03:6A:DF:3D:D8:07:3B:B3:07:36:E1:CB:B6:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a9:3e:f9:c3:5c:b0:eb:85:59:db:c9:72:3e:b4:2b:30:6d:22:
- dc:9c:9f:fc:8a:ad:9b:1d:48:b0:19:9f:47:3e:d2:44:6c:3d:
- c4:6c:03:bb:82:6c:26:85:eb:7f:1d:9c:48:93:a0:9c:66:25:
- 85:b1:5e:fe:71:a3:d6:2d:4d:c0:cb:3f:1a:46:fe:ea:31:8a:
- db:d2:1d:f5:0f:b3:48:ad:0b:48:0a:b4:19:cd:e9:c5:5d:17:
- 6a:3f:f8:bc:99:39:5b:29:88:2d:7d:0f:b4:be:94:e6:8e:a1:
- 7e:12:31:2a:46:f9:3c:1f:d1:c2:69:c3:be:62:f4:bb:b0:6b:
- 16:a2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAKk++cNcsOuFWdvJcj60KzBtItycn/yKrZsdSLAZn0c+0kRsPcRsA7uC
-bCaF638dnEiToJxmJYWxXv5xo9YtTcDLPxpG/uoxitvSHfUPs0itC0gKtBnN6cVd
-F2o/+LyZOVspiC19D7S+lOaOoX4SMSpG+Twf0cJpw75i9Luwaxai
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7EE.pem
new file mode 100644
index 0000000000..57dea771a7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D7 12 98 EE 93 96 EE E1 85 90 C8 0F 4E 99 FF 95 78 10 1A 4A
+ friendlyName: Invalid DN nameConstraints Test7 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 CA
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGDMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVlMTE4MDYGA1UEAxMvSW52YWxpZCBE
+TiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDcwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeg0Q4UuYbfP+YbFOzQ9YSaIj6bLj1XqVJ
+wNegsJlRNNFOlEqGjLx2s7WKQQz+GhTXN49e09Dnsf8V1uYS02UlaSMM5NKF5mJ/
+xq7eOAbq+yzYMjl9GsL8HQghiy9E6igRDOIrvfYDIJydWGMAyMO2AjW0MGJHzvFl
+F/kV3c9b9goVmWSvxCzHuv2aTyaPPzXQQpY5ZNkquU12xRiujJzCdiXU7csjySJA
+1FHHI3n8oE/+fi/LMnPdBO+rpaLfr/IA5XKUeJUHb3WEXJ3iwi+mMoZrn9doiUvb
+gnWUsKmPSoQ85RL0HWVSU/Qw7vItixSHKcKrXCSanL7A4jRWrI9VAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFAbcW77HEjdZpIpAdHwJnUU8SqHbMB0GA1UdDgQWBBSFsJW4
+SPk0c+uYjBzxBnzjY03dtTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAihLqlYMuqWs3P74TsKop+Ilgy
+d+zng8ltbEFodH7lYIIdbghsS4nHHmYIApf8Fd++zpf2Vg5NY1Celolriqb8v6nb
+VeygO1Mhtwq/yKUCAU2DgSpj3KkbcP4gaS8PwHtSTNzus/soD8jaRd1y3/37QGMl
+LxatbtPI3+nHsaVPqwQJfeeyQAnOXGyB2t11LD171aS2uoRkGp+9ZwX1lhXEGV2D
+oNnwQ9NzO1JJUWYtnDl0Q9xbWzT2AZ2FXQr4uVBnkdtTOPvpH88gNpRt8y5WIkjd
+0pQDFt+EyePgBAKk2HXPImtseHPPH3z+ZRoRUGet4iESVIFVekv5/olJrfeL
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D7 12 98 EE 93 96 EE E1 85 90 C8 0F 4E 99 FF 95 78 10 1A 4A
+ friendlyName: Invalid DN nameConstraints Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B45FD083D1103F77
+
+SBwOS6JkHV4xazjf3hMz+pQIdJABaX+JxoOLhDp77GtVbTXTL7gVYK7JDAU2dSAv
+MUCI2V0EL+3lsu9afJcTqYMBa6dWAUXA+HQ+4ztQ7oqeHuHvYuAKIm+ks1QF+YdV
+CrYjmto1LN+UDt7HA0tFf0LEGC9Axdlc0hxf/EhX1UV7BiIs/AFL8dI2TEMzHBSL
+Ugx+7HxpZ86mJYwfqyV57lWFIlZHDZ0w221wcb9tZj0jPhfZQ6iWsiFB9uk8CA+M
+z7vFpCHc1+/m4G+gAX0R+diYA9rSVjSS3068O3kkW31aSQGwTlM3u/Fnr5ouRfSj
+JoQEhCSGY+Axo2lJi1jRdZ86Uc4Fy5k/ou/Na7YAuZRvFe88BgMonjrEaD8hZOaq
+F5sZFKfLfLInQ7mHj6RPR9lwYdh0MsoHKhJztSkVnCpkRJFwAgZavPQ2AiYE/Fiy
+WPOwQPszKyjSFCTWQxCefiOCj6RCkcW0y/2xvy+nvSGtD8Lbt42uz/8wErpnKnIC
+50LT5t8bwC2O2pcjnZ3wdaOXT4PVdUu/rc4UgetzkkLxBfpNyHSpjyamVIY3S95e
+dnmVEJ9P0Ga/rNxIHK9l/BNLouMf8n6f6DJTn/fFbWeUYByp/WZUi5MUngg9qfop
+Zw371/PhyhhpQghj3SJEmfLZZlZfVBYIlFUT5xQyNP3L840HTog+11LW+uFabsFf
+VqlWUDHGKJN/cVOMYiijTrtNF8kpemqXS7Y7eS7mvbW8U6nyHGqQXrji1pQo1O0W
+d1bfNY4jlPR9pIgP++TG1IqCeu4GFMo6BZMi0Exir+0Ag8VB0zcjKgXWZMzXOWYN
+aYZgI1bEkAAPC6HJ0UOwQ1BBT0SxiQyeyZSRyvO+rYNZPzHvrxB8ChM6QyDJD4Se
+DfnWcBwUeC37oKuqsk3abkWiF615/KnuEFF6AcR5sbiIq+STRZmCvS+GXqksR1Qd
++gdBaKBqhlbNrciNQXsFqX1Z4JYG0zRM/MC3tTEhq7xpU1rOVdCzyT0yd67chK8b
+G58ZXl+PckkWe8IC/06NWECsjtVAR8pqBnQmNfVIVCS1U9dHQ8L6j84n3/qF3fpN
+++OG8Wqmql/ZB9/X4yk1XWEnb7vI0chnDQBJPg/0sdLM3hzVwZ7xH9WC4CX/5URL
+NUlMazP5zFS49lUyY07kps+P6/jJdl6rqMQNDJ2BliBSUe6JXsgZ7fcLTehJ6ltJ
+bOrnelOfh9HyrGEgynGweEG2/ouCh+8k7L/Wfada8ad2G7MpSTrWF+IGvBSSlR/X
+pFv2Jc1W6LjjrrC0MTD1yojnykfN3jgU/9CVGnKFLdCc3WX7MeLki+aIJndlq6iF
+Co7/rN0aZsuNPpQQ+XXF5Zacn2iPgoAaLzrRCaG4wIG6sliuZIinMobi1aLruZOM
+JZFR7EQp8LZMkVxeNtdYWfk16NaASUJt+oeFRZW3sBs3WRZxuCErZzI7fBReCtGr
+mjrg2XXW0sEJy91PyPoN1EtxGvTTnibB1SivT+/o7ainX4BFXEd41uxWoRL7h+DM
+FIDNy7O4xM9N87c2WaUbA8ErtTghYapiEkfb74jQY1xd+2YEnB4Zmk0WttWKEnnV
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8.pem
deleted file mode 100644
index de2503fe99..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8.pem
+++ /dev/null
@@ -1,112 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN4 CA
------BEGIN CERTIFICATE-----
-MIICqTCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjQgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB+MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAsT
-EGV4Y2x1ZGVkU3VidHJlZTExODA2BgNVBAMTL0ludmFsaWQgRE4gbmFtZUNvbnN0
-cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Q4MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDRLWTNLHouiD2wN3hJ0jdnrj4fTjlz2+99l/B+6xTOCtwBUJpACTye
-HIN9D2KKM0Qmh9stFmyS37OoOs2WPy4d6zXJI09x3ENRMHVD4XL8zIYvdc554XCO
-r6r5F4NDD9PXfx7zbY5zIa8xvuuRodLcz7HjxXCATmiy/Ylbq/tAvQIDAQABo2sw
-aTAfBgNVHSMEGDAWgBQzKeiMgEymrSeDjSUCZ8XltnYEzDAdBgNVHQ4EFgQU2i3L
-WI4ETNSzaANnEBgojWiA0sowDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQCF1bG1gRn+77BAUXRG0YGUPMgR
-9DHNB3htuZ16XVRT2TqgE6hFiTROTrYgQekzo37hAKapBXUk09KjbIEZZWimwkzo
-lsh96Mt3Mri/s1KHNnRsPWR7Z9noTDZW2doxIx9IdZnbpceQ/z+E9xHaEZZX2QTU
-oFgdRZWQ6koAHlJt+A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN4 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDKDCCApGgAwIBAgIBQTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIERONCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy/f6yuk+
-9T8iA8JCNC3qD0GOvAIXRNgKM4QLcAsVsDZkgrXmmyKyX3e+W5lgLeuzzgLxM9Fc
-Pm1NCRAX+AleMx8MI9Vyii9xcNT3KY90roWbXvSiixffCQyKwgjcNazm4nMgcKcY
-GCrTnvtjwDq4r0ov0chfZ4FYvOdxRXKJIscCAwEAAaOCASYwggEiMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQzKeiMgEymrSeDjSUC
-Z8XltnYEzDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wgaUGA1UdHgEB/wSBmjCBl6GBlDBIpEYwRDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBl
-eGNsdWRlZFN1YnRyZWUxMEikRjBEMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVz
-dCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTIwDQYJKoZI
-hvcNAQEFBQADgYEABIMFw3c0vt6dsO0Lzu4cyBPZB6GobaJ9EVCLCKcuwdvmyMgo
-YamK8D4AEsT88YhCFji3zELvEeg4P8QsRhtIsr0nto5r+CV02degP3F2XAPQr8gw
-qBP/8ejUC0UPnOz3QlkiM4mZ3mN3A3KJPCmPmtRIVst622/8nt4HWGLYi38=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN4 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:33:29:E8:8C:80:4C:A6:AD:27:83:8D:25:02:67:C5:E5:B6:76:04:CC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 7d:57:1e:3d:c5:08:85:5b:0a:d1:cb:66:61:ba:9c:ad:1e:d1:
- 7c:28:1c:08:2f:2e:52:53:18:63:ac:0f:c1:fd:30:d2:f1:90:
- bd:fa:89:97:c4:2f:73:a9:c7:36:bf:5d:e6:2a:21:f2:d9:81:
- ae:f3:47:05:14:8c:ec:fc:80:c9:c5:3d:37:cb:5a:e5:8c:56:
- d7:be:e7:ed:8f:f7:21:0f:d6:6c:e3:f8:cd:dc:c6:bd:70:90:
- b6:30:bd:d1:76:47:62:33:02:ba:bf:97:41:a1:cf:62:12:21:
- 4c:1f:d0:49:a8:b7:50:f9:a3:63:40:5e:f9:0b:5b:ac:de:7e:
- f4:27
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjQgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFDMp6IyATKatJ4ONJQJnxeW2dgTMMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAH1XHj3FCIVbCtHLZmG6nK0e0XwoHAgvLlJTGGOsD8H9MNLxkL36iZfE
-L3Opxza/XeYqIfLZga7zRwUUjOz8gMnFPTfLWuWMVte+5+2P9yEP1mzj+M3cxr1w
-kLYwvdF2R2IzArq/l0Ghz2ISIUwf0Emot1D5o2NAXvkLW6zefvQn
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8EE.pem
new file mode 100644
index 0000000000..1e804be846
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B0 F4 81 5A CD C5 8B 61 B1 98 71 20 81 CB B9 D4 74 B9 44 6A
+ friendlyName: Invalid DN nameConstraints Test8 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree1/CN=Invalid DN nameConstraints EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN4 CA
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIERONCBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGDMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVlMTE4MDYGA1UEAxMvSW52YWxpZCBE
+TiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDgwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDd8E++Do+azS0Y/46cd+mli2KpLKET6z1f
+h6a2XTdv41TEtc0FJwgrEUxzzPX9gbx/NVNU0lHpVs9xoZ3/g8k4sC3/tSB5Ud8o
+dNy5yjOzrkCqMmf3dwxQ5bmf/8pQUsN4qch/nCnnLH6LllR8S6ZlO7HD2+jqS7jS
+FnGm/ExZs1fvBz647RQi1RxojTdd8ek18y2xMMf5c+0BqNBjuuSQ2l7iWCSPsT9n
+UVrvwhJopi5irEti0QP/bUcax7okraeFT0RnJTGrrxIREx+/bvTJ8jc4yFAsmuu5
+KsMzROuEPWz6tPjXHJItIAy9hhtIjHOE5tkfFwfBQI6KJpwi0RzXAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFGxJNq0uWIkSNlFBO1RSJiQA08p1MB0GA1UdDgQWBBQdy6zN
+eXfT6urnrougyDWvP3JkPDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAmvLMakt11xX2Nh0adOhzCqqB2
+Ea9gZ1LAusrw87JblOzSrHUGrwR3cL/yTAdyNhuudqJQTe4aobU+7DorluFEF29v
+hvwtIEHAhw+WRmX/pNZ9txamcYTfH4Pi/HHaSxG0nFNNT4LWTr0ACO61wkIH8FhZ
+Y+K6iHx7+e1vvGfuUFimKyH6lW2Ia59LCo3E02OUEv7r/d8z4oc2sH7wYZ1fFlOF
+RHzcE/rMmO+3t41Ejwg8WXCrojdeYpWxXjA/kL7dOQoYs4E0fffiousFtMkAi57V
+daf/BhKsPsr6vCIucSZVcoFXqVTXhRdKR9bqcczLjG8um0VXD+GcABkC/5Rs
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B0 F4 81 5A CD C5 8B 61 B1 98 71 20 81 CB B9 D4 74 B9 44 6A
+ friendlyName: Invalid DN nameConstraints Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D0469F3B107F0E0E
+
+uKVaM0Ffc6kK79EkfZBuI/L2JuyQphClPbrmZNq9puVY+VLlVLwjEq3S/JK7clhg
+ofOl5OJbVF0vWrqDW2hR/vbMplgtn9CJ/u8A0UJG4mHln+0EclUqZQlAg2MI2FCV
+3uEe6Z6Z2VD6R8QwNEMkC4bBLcX/kwvIKxUi4lRB5bPzWiHvEGjN70b1FEO1Ewy+
+CNEMJ82REYzZ1ddH+N6KfTYtZxT87Jv/4YjcRVK5vKdlMnEmuMWW4EQM8l/Ey0lx
+DL6tjTfjcQ/idf2lO+tPrYEWYKGQLwotsF8iHgcW3umgMPA9CbeId3em7Aa9Fuzy
+tGp6DUMGWdmeVFL6bipNXYNgwia/wSKZcLcldWzSzcMdWDm64rP7UF8bDi2UWSBb
+jGvLzmTlVORMHhkqF6qzDbZWJjN0HCpoOClux8H9hoEY3n/WGsyzZaMAzoemHMMt
+3adetPrQYXUt0qGeJzf8IZrgds3TQhjakzDhPoi0Vjf1MY/+THp5z5A5zWJrcL07
+0eZOdNt1ahys94lHeILgh3eeqHCPP+q5hcmDbuxSRzeEnu7wjtPACuExYYTpNnfW
+1aHtGicw29jQcucPJlh1V9Dq4rVJVtVnr+AtNyPvq3FxIQ5rzniPHvAoZgzB7pmj
+oE/TNR2Pf6LIbc5JoiuAuH+2wMynDqZbD6X8QbYOxZazu0FX6JkdsVk7luH+B7Wz
+fZsXijSC/Kb5VOoQddJ+4pLXBForVWgwfULvFyF0sXN7cwxfTIC93N3q7jfWfd/q
+dsizeO2v/qbcXL6PTCGxPBtXQu5oTeur31/xeXeYPMXp2QMAjgFJN03au3W48NCi
+vxjrTVkxHaK550B7i5KfYNrvCtqYBctZNaCcRVwTsbfyxKfLzW5n9jDp47ataDn+
+bxu/hjgJNaZ/eJl36bJXXMK+WsF50lMhtNztD32pCwCBC/wjHWQc67ughlhExuFM
+hOZTOZd8B9OTAQZcPf8g/aoXrd3rxHY/TsHgGQsTPUJPPkEnvXnwy70vn/6ORb0o
+K6ftAMAYwZ7epmnNs7o3eMgjyEA6FegUQBuSr6upvM1+xBHQ6dWnYJfRJYY8j06+
+Cffd0k7yd3700KSeFMHNyaXkzIs5ixyZ8Ambb6LsnLQta40HcT4hBG6fjCQMKBLn
+K2AKHxcwIOp/GZ7u6lrjamuZ6v8LHF3vNaS+lvMUkWTLXt2t8cw4ddG5qPzXhavL
+a1eBeOv03QuFXgTLo6xNDFlZYBReHCnPomU72UiM6F/Adl+FL5BtSd6lda5YYAxU
+QS77VUc4M+YjZCmfkisch1fQ/byksgP/e/dhNJAXg6nywNemjUOfk3CW7NZK+0SI
+nyghbuwcc94aOOcjdh7k+DtUQxOeAEXta7Jb/FQJnnvdqtsd7oCiadCnU6oP+DVv
+wxfE7dA7ghqaND6SG0RfM2ve9h+Odquq9Xo64xOyByHL7Vl+CiWz3SUOM4i8qZol
+eHIQe3FybwC5VLZJVTWBRPo4r3WMVaRlMtcFR7Z+M77KOoUfCMsv547hSXWbQVHl
+eOoaJIlqZkYDbYvtO2VZuD9A+S1ItU8eWDzBJXx8Csh/uNEAs/+hfA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9.pem
deleted file mode 100644
index 450c232004..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9.pem
+++ /dev/null
@@ -1,112 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=excludedSubtree2/CN=Invalid DN nameConstraints EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN4 CA
------BEGIN CERTIFICATE-----
-MIICqTCCAhKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjQgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB+MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAsT
-EGV4Y2x1ZGVkU3VidHJlZTIxODA2BgNVBAMTL0ludmFsaWQgRE4gbmFtZUNvbnN0
-cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Q5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCh34/kUYUgkdgErLgpO39ywlNRcYoZme/9B+Qf6xXvtvQsMVSTRlYj
-SSl7WicS1s0i8wU0jrejAaH4wKVmEKpUXvDAnMWqnRTgL7EN4ni4vaorV9S5/6+A
-qXnmW+4GGg76TP9cj+SQ31mg5DHaHMGc5WeGygDJ0iaYXHqtUczkQwIDAQABo2sw
-aTAfBgNVHSMEGDAWgBQzKeiMgEymrSeDjSUCZ8XltnYEzDAdBgNVHQ4EFgQUWfRX
-bghjCb+4MfpDq1DFnXXWtZkwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQBqpi8ums5mTqAUxfvjuqAIdAzU
-vDfiJ9uAvSRyTLckdIKvbvqgn1xK4LFKEHh98dWr48RosYc8wkofI0wHpwYrhYcP
-y2kgyqtaTrdeSgbBcBibusuagwpz9o25LUTRTMVg9sq+1yJJYlGHGV9LuTnn/ZcP
-vCtQwWgLy74cJC0WvQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN4 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDKDCCApGgAwIBAgIBQTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIERONCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy/f6yuk+
-9T8iA8JCNC3qD0GOvAIXRNgKM4QLcAsVsDZkgrXmmyKyX3e+W5lgLeuzzgLxM9Fc
-Pm1NCRAX+AleMx8MI9Vyii9xcNT3KY90roWbXvSiixffCQyKwgjcNazm4nMgcKcY
-GCrTnvtjwDq4r0ov0chfZ4FYvOdxRXKJIscCAwEAAaOCASYwggEiMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQzKeiMgEymrSeDjSUC
-Z8XltnYEzDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wgaUGA1UdHgEB/wSBmjCBl6GBlDBIpEYwRDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBl
-eGNsdWRlZFN1YnRyZWUxMEikRjBEMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVz
-dCBDZXJ0aWZpY2F0ZXMxGTAXBgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTIwDQYJKoZI
-hvcNAQEFBQADgYEABIMFw3c0vt6dsO0Lzu4cyBPZB6GobaJ9EVCLCKcuwdvmyMgo
-YamK8D4AEsT88YhCFji3zELvEeg4P8QsRhtIsr0nto5r+CV02degP3F2XAPQr8gw
-qBP/8ejUC0UPnOz3QlkiM4mZ3mN3A3KJPCmPmtRIVst622/8nt4HWGLYi38=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN4 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:33:29:E8:8C:80:4C:A6:AD:27:83:8D:25:02:67:C5:E5:B6:76:04:CC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 7d:57:1e:3d:c5:08:85:5b:0a:d1:cb:66:61:ba:9c:ad:1e:d1:
- 7c:28:1c:08:2f:2e:52:53:18:63:ac:0f:c1:fd:30:d2:f1:90:
- bd:fa:89:97:c4:2f:73:a9:c7:36:bf:5d:e6:2a:21:f2:d9:81:
- ae:f3:47:05:14:8c:ec:fc:80:c9:c5:3d:37:cb:5a:e5:8c:56:
- d7:be:e7:ed:8f:f7:21:0f:d6:6c:e3:f8:cd:dc:c6:bd:70:90:
- b6:30:bd:d1:76:47:62:33:02:ba:bf:97:41:a1:cf:62:12:21:
- 4c:1f:d0:49:a8:b7:50:f9:a3:63:40:5e:f9:0b:5b:ac:de:7e:
- f4:27
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjQgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFDMp6IyATKatJ4ONJQJnxeW2dgTMMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAH1XHj3FCIVbCtHLZmG6nK0e0XwoHAgvLlJTGGOsD8H9MNLxkL36iZfE
-L3Opxza/XeYqIfLZga7zRwUUjOz8gMnFPTfLWuWMVte+5+2P9yEP1mzj+M3cxr1w
-kLYwvdF2R2IzArq/l0Ghz2ISIUwf0Emot1D5o2NAXvkLW6zefvQn
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9EE.pem
new file mode 100644
index 0000000000..d0a035da68
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDNnameConstraintsTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 7B D8 8F 64 F4 1A 03 69 E2 8A 68 DD 4F 46 8B 56 B8 6A B4 FA
+ friendlyName: Invalid DN nameConstraints Test9 EE
+subject=/C=US/O=Test Certificates 2011/OU=excludedSubtree2/CN=Invalid DN nameConstraints EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN4 CA
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIERONCBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGDMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVlMjE4MDYGA1UEAxMvSW52YWxpZCBE
+TiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyBT5iEc/Tv46A838epWd5siS3H6q5kdzw
+winlJhMTUca8dVCuiZ9Xwgh+N86g54NvIJXzQiAey/KJan+2DXRcMu5EGOJjABk8
+t6jc/oTvdX4KjMkvYobBKcSsRuhuMkCn3vy47e40e8nxhmVhO/f0crEsmWGE4Eaq
+pnrcFD3YPRZLaW/2HRWXiOn0TpwJLpus+NYxghAwvI/IKDh5ymBj2BywUvvxngT3
+iKQ4BgoT5W/4Ce5XMekn/S78BD/DWiQMHqNjBPeb6eH+WvyPXpn6pTuIGg/Vpn3d
+KJzpl9t3WMo0yQaFzYlrUhNYGOJMXWboX27tHetlmdhQ7kF+E8WPAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFGxJNq0uWIkSNlFBO1RSJiQA08p1MB0GA1UdDgQWBBRQpDE2
+BhuO18HQzangbKt4zr2s7zAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQCom5SmP8qsQSlBzA8HM0nOGzLG
+oD7VEV8/kxv8VBLzXzgI7bijCIWzSReTUFCp8gBzdMYLlvXHkfy+5kvC9fIEmzyw
+uq7vNwjmFOA2sXtoGcbn5LwOhEepf0qdi2Y5oOxqQRrj98FelZ62bsXjOEKdR5g9
+J+2+VcU3P0ENrAQisVy7mw/MteuUEL7v8iEtfpvxjR6ZP9IsRQY2XsPXNX5hzlzZ
+C+M3eKDVmg3c4QEjXvbBdhntVU9H+YYaEtQZ2F0vKH/lv2f2/Vj7yupxExakxpQP
+6ukRNeDvnG6ujitq8qhWu6QDEfCdzzEx2ZuAVZqTJjAKWC6HwfZUioDjhHFZ
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7B D8 8F 64 F4 1A 03 69 E2 8A 68 DD 4F 46 8B 56 B8 6A B4 FA
+ friendlyName: Invalid DN nameConstraints Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,454FD50E5AA86909
+
+snoxER3TwKSfJIMUgfnKUjqQ96OcVNV92TihvkayHtqbUXsaqgQ9z+zIRp7Q+oiy
+7kkNkgPXPLVVM0SfIEIdtxRH70Fg6nwV+We8YH/3etFY8yxhr+qbbx9ouIVzk5YA
+4inJNfS2OU13J+26BGzi/eqosJzgNJ8jMBxsxbCQNb1TDC/WfFQiOUUW+Qxha5c9
+vNhJwQeI8s4YCic7HJ2a1xUviMLAkFXBtn+1uptLR4M0eZh9yZA4udYzsugk/uvW
+h5Wz3ZjZgM0mRYsBzsymxOBc/UhmXMFvMsiEmoO/TEexvGEXODhsALxzUhxQttgT
+7BlBko7cqKN01cxie8ePJKXa0BmLRcY2fQklVi5Nts90Yr15QFJ3R41Iah4zoigT
+PJ9U8f4fDhMkDdiriAcXYFpSDYd+jQ99EsoQi6c9LH/PtX4EUsVAWsM2xjlVUGCq
+iaVx5lKEjsN4UCtxEu/LdLwExnYUZwgiJEC0lCZoRTz8iPEoblMtB2mYmJp2coPx
+9JjULNwUiKa7+4UoxzBMOjGjsRel1J+NkXXjaA6tGI3ul3SeQ542SSAesv4MLwJR
+weNL6hEFdLtJ98TqhaXibr7iupjmAIqdN+IwdbViLeSHa/YaxtI/W/5D3ub/KdjX
+tegv0+IJrPg+HSFB7FZY+HDha8h5xNariyjz/K7EgfWqYl0XyMFvEHZ4VWr+M4aY
+kUGLfnoIVWBl+7n3YhzzCyyRgzos09SkWPuqsj5NAIDFIruFZ45TcQ6wRP1UV59a
+iPrEsmv+bwAYw+L71LtGKgWp4OfhjuxZp8XmEtcMcRPq+luNny/oZO2GVJ75mm++
+b9Aqdl8tkWjFRYleDv/IBu/eRqhQH387gICxQORpjIIo/tuHyOGdYbIIXL08cbMQ
+h+cNSGR3kQ24IFoFUGBnF/LgsfftretK09zV4Uk1uPUdOHZjt3eZf2VWk3aWoLQz
+krgL3yR2Y+yqfrdPeDAzfzQr2QtyS9ioN0fNDqk6vdCz138YGr/X/wfPZoj8ynxY
+1NbDQHKNl8Wp+4a/OQJT+SleL/SsHkCj/st+UBDZ5eGNdZGT9Zc+4wwPY5oXUFU0
+owqODQFLhEpU9a2tru39wTTrQQJJgUBTTHfjrMACCbatlOIDBNrf2kf8R4q8Jqtu
+wXrpbOiINsGqv+Mi9/qHOXXQO9M7keyMoIcg4nRCtTVmqz1aMs3NTEbPV8das8E8
+gd6AgGWOCmQUUh9z8v2U8zLOCR30mTmh3kstV+v6UniPzmVBMLj5SZSDJyCor/az
+bx2LQvTQ187fmKrSJwbVzQa5GHWeKQ5x6MU7la/5CjdlGxLmkzgd10Quk3RAOzAb
+aIPDUk49hV0Wb7VuMjkerhXyDX6ZE0o5O7UWNBXxDX6qUGKnq85f2XNxqUjvkZZ2
+fbUuVrbOC2gei52XzRhbaDiFbESg/mxTRprjIIBx+tPYgWzSFYBENRBYqUQQQSN4
+W1RM99Z6q838RXAFTKQr4jNtaZnSP3LOpDyuo9TbxHHSM6c+ldtgaL51mY8jHJO/
+p6clyR6EaRhKFeS4VmrTqUszOiaOeq2Cv/wRaxuXN+FDUrtV0FF9ZHpKDSxOTkFg
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6.pem
deleted file mode 100644
index 55164dda04..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6.pem
+++ /dev/null
@@ -1,104 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid DSA Signature EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=DSA CA
------BEGIN CERTIFICATE-----
-MIIDNzCCAvagAwIBAgIBAzAJBgcqhkjOOAQDMDoxCzAJBgNVBAYTAlVTMRowGAYD
-VQQKExFUZXN0IENlcnRpZmljYXRlczEPMA0GA1UEAxMGRFNBIENBMB4XDTAxMDQx
-OTE0NTcyMFoXDTExMDQxOTE0NTcyMFowXjELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMTMwMQYDVQQDEypJbnZhbGlkIERTQSBTaWduYXR1
-cmUgRUUgQ2VydGlmaWNhdGUgVGVzdDYwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEA
-vbB6Gzy0SX2N5smRzWMqz0VoZRd5JR2pZblQy69qF7L9wXPemawRZc4n8w8GB+4+
-IDHq2L8Uex+2KP9lRuXNnaUp+C/BCIB1cHBBJwA2Wzqhe0uyoVb9qvDOQuU27zRU
-dymarmOqSfc+ruHC+faJMv+ZaHv5zjRd8XwpZHs0ZK0CFQCXYwgNQsqfF7gNfgA6
-5QUzpC5bwwKBgGBfbUNGPILwforCRr06QOuBEKduLdWEZngS7RkwrK5N12jxDw34
-bvbzjzqlldmdKRu8kUG2bhSV9aF/EzvyppEkVBZ0j4NmnQtO/kvigCL12hmSucnN
-3Ir4+32prJX4ycxuECJYsbU5LPfHicJT9x5o8Yy4IcxJkzfkL/O3WE1KA4GEAAKB
-gC1pr90wK1tDu2BegyCB0M5MOerDtoYTJ+js/5N0yrMApqjdguHSRoq6nyc/33dn
-gAlOKsmYuClo4V9v5sQ1rPYYa4Pt9DL105oCu3uZAlASTSqiUc6FV1IYlEEyErXp
-JM5sYFEtet0LoIq2QvmcbHx3OZXrTS7ZgvKCNwNFBQ3Qo2swaTAdBgNVHQ4EFgQU
-3GZpOXKnsDrffRsT0zC/TrR+oPEwHwYDVR0jBBgwFoAUdBXVJBy9XmWIH+GLCX5/
-6hlITmEwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA4GA1UdDwEB/wQEAwIGwDAJ
-BgcqhkjOOAQDAzAAMC0CFQC8jW6jJtLFOVb/3gB8Ud6zDADC1AIUXggJS+znTQfq
-yuMe+SHndjnV3Gw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=DSA CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDhjCCAu+gAwIBAgICB9EwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxUcnVzdCBBbmNo
-b3IwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA6MQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxDzANBgNVBAMTBkRTQSBDQTCC
-AbcwggEsBgcqhkjOOAQBMIIBHwKBgQDf5RE+2um2bhDW6p3inTqwR71EAMdWyMxu
-0DOEVkc1PfZUyOPCrbu6dfMvMwym+THsZ+PlmW38KW6qV4hyNOKOAJDgo6xkjsD2
-PB2PtMhKSDBef6qcdiYL2xNzM4OXwMWz5jf1Pv8VDdShLrox+KuH2AvMd5hCbqyT
-mMK9Lns0CwIVAM8GBNj/i+sA6fZcB5Zz/ZZlOi8HAoGBAMzhfLDOkl9j7Di7RLrd
-kjS2Xr5le9hxdwSd7GZ8OwTOtvNS/g+SVQLvThKrXZouL25W83Dsau2bIrioE8sM
-nBbqwQqOISZEpQz5oOxi4HAxzGj1C4WkShtuefTB+TZaOG9O74RT32f9zPdZYo+c
-nM0Qj1ykD5y3B+xg876vfjmYA4GEAAKBgBHyudi+QivFhL6RAhz8jDJyi6hsIdeI
-ihS6MGV1wBw9gmllp6yQehQdhXvlU8Jg/LHPZ6/B8i4IMmo4x5FOO7w8CdD5cW0I
-3ydJjQV02L1G0NtRpVO6h/P6XSWDT38KdeWp44mnQXdjQF8rLITSwXF4CttrVxnh
-5xQMnsT2MjkOo3wwejAdBgNVHQ4EFgQUdBXVJBy9XmWIH+GLCX5/6hlITmEwHwYD
-VR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
-DQEBBQUAA4GBADo7ch93LLrc7PUdW0XOP3+kP+Sywfqf2ApcmOLufmM60siw4rzA
-1ssoITB2Rs3TPQKBiJzMdFKrq8tQ+8TcpXJ9M4SVfbAFB0P0vB4UC2Eg6iSnVJbB
-tsZFj12gpqv5Gawo3yUTw34h3opDGSX1pz6eZUIZBFKpAX5gyIpiEBI2
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c7:32:ea:21:ff:7d:01:d4:f3:d9:c5:a9:ea:04:35:21:81:d2:
- 13:f2:35:d3:e4:53:c5:03:93:de:a1:2d:25:56:64:bc:52:20:
- 81:53:69:6a:a6:90:26:38:bd:ed:31:7f:a9:7b:c1:e8:a9:e5:
- 07:97:82:bb:3e:8a:f9:79:ec:2e:bd:16:4c:31:6b:b6:80:ca:
- ba:ba:0c:35:0a:d6:08:3c:31:78:fe:d3:3d:06:69:6c:3a:e4:
- 07:4d:6e:84:21:d3:c3:90:60:8f:99:90:62:a9:16:38:25:2f:
- 7e:08:5f:2f:cc:59:d7:7d:9b:2f:d8:0b:e7:70:d9:64:f7:01:
- 38:8d
------BEGIN X509 CRL-----
-MIIBOTCBowIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU+2zULYGe
-yid6ng2wPOqavIf/SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAxzLq
-If99AdTz2cWp6gQ1IYHSE/I10+RTxQOT3qEtJVZkvFIggVNpaqaQJji97TF/qXvB
-6KnlB5eCuz6K+XnsLr0WTDFrtoDKuroMNQrWCDwxeP7TPQZpbDrkB01uhCHTw5Bg
-j5mQYqkWOCUvfghfL8xZ132bL9gL53DZZPcBOI0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: dsaWithSHA1
- Issuer: /C=US/O=Test Certificates/CN=DSA CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:74:15:D5:24:1C:BD:5E:65:88:1F:E1:8B:09:7E:7F:EA:19:48:4E:61
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: dsaWithSHA1
- 30:2c:02:14:46:20:d2:4b:f9:cd:91:09:e9:71:6a:bf:d2:3e:
- 88:5d:d0:47:ee:aa:02:14:25:ae:d3:6a:ca:3f:a4:54:41:d9:
- a3:57:74:b3:48:ab:c5:9f:01:f9
------BEGIN X509 CRL-----
-MIHYMIGZAgEBMAkGByqGSM44BAMwOjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMQ8wDQYDVQQDEwZEU0EgQ0EXDTAxMDQxOTE0NTcyMFoX
-DTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFHQV1SQcvV5liB/hiwl+f+oZ
-SE5hMAoGA1UdFAQDAgEBMAkGByqGSM44BAMDLwAwLAIURiDSS/nNkQnpcWq/0j6I
-XdBH7qoCFCWu02rKP6RUQdmjV3SzSKvFnwH5
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6EE.pem
new file mode 100644
index 0000000000..767c46f04a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidDSASignatureTest6EE.pem
@@ -0,0 +1,44 @@
+Bag Attributes
+ localKeyID: 9E E2 98 1C FE 0B 6B 55 A4 BD D5 C2 22 34 2D C3 98 4E F4 8A
+ friendlyName: Invalid DSA Signature Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid DSA Signature EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=DSA CA
+-----BEGIN CERTIFICATE-----
+MIIDTzCCAwCgAwIBAgIBAzAJBgcqhkjOOAQDMD8xCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMQ8wDQYDVQQDEwZEU0EgQ0EwHhcN
+MTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBjMQswCQYDVQQGEwJVUzEfMB0G
+A1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEzMDEGA1UEAxMqSW52YWxpZCBE
+U0EgU2lnbmF0dXJlIEVFIENlcnRpZmljYXRlIFRlc3Q2MIIBtjCCASsGByqGSM44
+BAEwggEeAoGBAL2wehs8tEl9jebJkc1jKs9FaGUXeSUdqWW5UMuvahey/cFz3pms
+EWXOJ/MPBgfuPiAx6ti/FHsftij/ZUblzZ2lKfgvwQiAdXBwQScANls6oXtLsqFW
+/arwzkLlNu80VHcpmq5jqkn3Pq7hwvn2iTL/mWh7+c40XfF8KWR7NGStAhUAl2MI
+DULKnxe4DX4AOuUFM6QuW8MCgYBgX21DRjyC8H6Kwka9OkDrgRCnbi3VhGZ4Eu0Z
+MKyuTddo8Q8N+G728486pZXZnSkbvJFBtm4UlfWhfxM78qaRJFQWdI+DZp0LTv5L
+4oAi9doZkrnJzdyK+Pt9qayV+MnMbhAiWLG1OSz3x4nCU/ceaPGMuCHMSZM35C/z
+t1hNSgOBhAACgYAQWbmkwRf6MP4B9U3eJlPnnlqXNvSHUkc20sM1M+rUzpCjtMD9
+A19x3QZBz2/6zKHJH5FErjnPtTzrGeTf5Z+TKVJZhnu0h7488ylP6DH1xHlIGotx
+192SGnw2XbuwsovncnWlqcT7+Agh9y+xdVzyUJ0FhE3Qx+x/teDgzlz4lqNrMGkw
+HwYDVR0jBBgwFoAUj5DGjHToewzIWcd9PFtUWWAlC7EwHQYDVR0OBBYEFIZoDvoq
+SWtJ8EVev2KlUt2FIGBFMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAOBgNVHQ8B
+Af8EBAMCBsAwCQYHKoZIzjgEAwM+ATAtAhQ/pOQA65i8c4YUyXW7sZs/U+tedgIV
+AIgP6varGB6QfVQJyKjqwXPCn5iiAAAAAAAAAAAAAAAAAAI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9E E2 98 1C FE 0B 6B 55 A4 BD D5 C2 22 34 2D C3 98 4E F4 8A
+ friendlyName: Invalid DSA Signature Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4EAF1A94DD24EEA9
+
+DVXBBzQxV6Wl7CrTeW5ZOsIk2TDqnaxGZecFTO2LrzXipC8TwHQjNnB1qi/XHgUU
+z8fnnHYvcEexfyUpR79IWaZaf4e6i3ptKAPtVqxTZjic1Kjg/JTARpP51s3AkFwW
++5dvcjJbA4NRq29N5ciVs5kCTmXOOy7VvC81to5b2g6rZR+xEDNnjuMjbhph4vBV
+RyFpNGMjkC8ZMy8ykXGt14aHIv7tSdSjObIZO5/xrlpfx6ldAQxZS6RwgbjumPu9
+sRYxh+e//cOv+qbl+a4VCqEovlpCZAj2ycwPGRLxbQi8NpgM2LH0D+eVjDio9ft+
+Kxv7DFVQPGJvWD5ZtF8x90DAEM2qdx/5ILO8X85Spmc2zDzqd4Sq43BU9ftPTOw1
+A5ih2j1bZu9euZakhEB3v+XneXslXNwri0+N9WSXMthSWYzXVRQR+kYkfFEh1GUF
+GwUYg3YUKFO8B7gn4s/f7imqStJOftrYWz11cDuBNXDDHJwvWglwRfptuNwd96LL
+8rCYpqY6wvcq0zTKt72ohfqVkLa3DoKKX9id8AQ3XvD13/x39NXakiyUNcGGbz2K
+yKcBBRVnq4Q9FpNQPMV92Q==
+-----END DSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3.pem
deleted file mode 100644
index 998b139518..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid EE Signature Test3
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGkludmFsaWQgRUUgU2ln
-bmF0dXJlIFRlc3QzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYuEosZMlo
-4XLnLFz0FHAoAVIElosiQpT0Z0p3AtLcG9tCIN83S7m8WXOBhuRBoRLaHQvEnPE0
-n5azBwJ+zhWD4+MglyPcJ1FrO7SPiHOB9UotWr0EG4cjkAVUMrrkFRLfoLIPJqz3
-sNEYnP5qPOe32IGDKbXybjoddfzHbompcwIDAQABo2swaTAfBgNVHSMEGDAWgBS3
-LqaCy8LIvKh7J0TXNTPfmhWUxzAdBgNVHQ4EFgQUU/uacMtyT3ntU/H7h/8/HstM
-ebcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
-hkiG9w0BAQUFAAOBgQBHY2fzJrZTRjpqPLxzU7ZABeS9O/01ZTY/9uYl0JrJsfN4
-WlxaYMtSRcTJceQAvfyrafk1x354iJF+GjW7XIJR9RhGlkQXquT1Pqlv/Z2vpSjq
-glf4JuAbERm1V92qP2Acyiphm+P98Pu21c/Vq9xK3Jh/9/GUSOCmPIhvVG00MA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3EE.pem
new file mode 100644
index 0000000000..7f8cb9673c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEESignatureTest3EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: B2 88 B6 C1 D4 45 AC 2D 04 63 A5 A8 3F 32 C7 47 65 EA 65 78
+ friendlyName: Invalid EE Signature Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid EE Signature Test3
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDeTCCAmGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMFMxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSMwIQYDVQQDExpJbnZh
+bGlkIEVFIFNpZ25hdHVyZSBUZXN0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAL0hKwE3BTkysVg5uG7li7trnzIg3Nr5gt86tdXWBMvUxtobZoTirYpn
+xeWYd7nak/BcsY1/s2PG0eKHK7p0/U8TwSiOKrjaY4MbEXD9nnWdsOttQbNufHvj
+clD+rj4qxFjpUPhDNO4hlC97x+A3PUwarY7UfPbmHSOxwhXdaC+ewQ5PP0KpjYdV
+ImdRiDW/6ViFocaoEi7X6oxa7wq+fX0I+EIYF9ff5gQWXjH7627CGS5Mb4pPMIqu
+uNAucKCUhm5ebNp+4IGm0aS8NY/Nps5Ar2bj7tJqneiUDi/NtMRF1DG5f1hrNTMc
+URVDk+EGDknqLO8FfOH/T2ePhrYFo3MCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGE
+JBu8K1KUSj2lEHIUUfWvOskwHQYDVR0OBBYEFMGDz5JBPp/wUvjh7G5TzmS74rxC
+MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZI
+hvcNAQELBQADggEBAAOz8GXBwa0o8jyF/ebFdC11whr/04CPLRHs8QK3VAeOaeKU
+qnN3retPzhN69/6vVl8ZngJqFZMQFVZ727iSDsva1w1j4eNbugjU6Hv8754pVBsz
+7aaR9Aza/JobeMmQ8iWZ0H3oR7ArV7vLbMwrDPpAMM4fT4lUnitVtbcggiY9H+LG
+guH2d8PbtEv2CZsE3nj3kSW+Tbo3cVd3BmRMyRvgqJGwEnRlJl33bWi2g0n2n5P9
+liABaYGW0oVeGPGHaKLrj7mIfKJHiz8xWHgouzjYv0amTHRqat01y9HCuRTvw0VS
+EXfdrlGih5HJj6SPux0KTr5O4PeaPJVrlFHi7Ts=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B2 88 B6 C1 D4 45 AC 2D 04 63 A5 A8 3F 32 C7 47 65 EA 65 78
+ friendlyName: Invalid EE Signature Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B5DD1EEAB4CFFF8C
+
+eG6G3FYzv3Cw+pSy2czXeDfoSoe3uR0FcWK2ZHPR3ZqIPOJAytegNUW8e2rGwuA1
+dIJjE1FVKG7aREmp5MNNxxU4pS2LtmMh+tsoprWGuCHNGe3MMCkRpLDFhMI6HEKk
+I/XIWmGRAvXExp/u86IghVb7hLBOpBprtcX/AoYA3Wca/USq/XjG70dxcub2U5Al
+0Iu01dsYoNv1yjMBXAyDLwVeOBhgeAN/xb+xSaCG+i85lIL2GFQCi8B+mc7j5EVf
+DVhNrXR+uRZ2LeW72Z6XwMnbQRiaqd8rDTJWlLWGagPWYeCaKRB8eYR5GksZzmko
+YA0bUBuj9lhhmPWWq7ExifNlMBm+nqBxzOiDk0HkzvndGaUUaNPXOXL1ImjBZ3Uv
+iG76OcBh0OnABW2SGj7Nk8DRbJt0WpSKq413vZbfCxPZkbpw/Lo/Zil5tqDM+7G4
+aTW9DDx4lXGotgFVR0yn6AwSs71BjpzTf3AI1DzCc9N1xU6Q3M4YLezvX43WX3Zv
+wcygNFLrSJScJwhu9glNluPsD7leJfczNUMeclSbXSrIx6VWSEVuadQr1hriqZK6
+ELdGSeKeYU/Eg30umu6QcA8SoF5jIDpVjZSHI290rWLwEN38pgohBSZ58XrdObSO
+3gTHIQqcTBBucDKpAD0tcwx+tNyjht/4m8oer6ROk8/ewkCHOZFVpK97MJA0J9aB
+MFfqpe/yJ5uTXy8PR8uxw0r8DgvWOqM3VwCdguNlcKVE+SgIARi+gX6jq7InkQBu
+VCsnR6+ZosQNXNH248XzOoeiXL4JNUi+d3U6dlb5DbY2adC5VwNgC1JlUmkk1clF
+V/P42cCwDn9DmGM8+Wpe4eT9hwZ7iTkxb9s/kcjNGJg1cME1kFjFxZw9cPMfgqRA
+UOgEprTXSBFTuBsOnzQSQ6HsdaBCHrVwxBn0mn2NH+nwQ8Pyk7XW+WCKW2OT02fW
+PQz7KYPcm9Exoozkn1eHyULqpGNY4Sw9nKmmjMa8Zty/VfrYwwz8xfm/t9+LOi8m
+415J2IQIslxutzbD6/aNDsZLlvvnSLkGaTA5tPdT/GO9A2tk1kY3d7/nArnOQTWR
+jZulgzLWi33fABX8rXBU+JtWmX7RKbM9yP6cKXG2BumJb8xMqULGkupynv3a/iFX
+nmkkl99DFqwGmhliqQEm0swjB/p7lY4LpiaNkwMmX/jXkKXet+qtIpYMH4Uo88vZ
+oWfoyOzKEKl/p6/lRTVO2toLU79rejdzTwAbL3mbiMYWjFM38aJGQQ8GQiNVcLvq
+JFnpa3JxkFhTZPQlfqAHD3Y9dyR4cNU/6jP2rGYKJlrkqA1KmhgdJVDWyYRkiYgn
+vZFtbnuHSPrRmrdjoaSCR6UIm7Xmwpe9Tv35IHrXAi9wQphZo3CTMFedInQi5Z6o
+wrYifORXu0f1CBlJeWAgFw9yZIslVmKQiGsV7o5GXPC6sFSvAisJ5tL0nZkZaQ8Z
+gkubFwqQ06fOP/1UZK/ck2veBueNG7/PHgNSP2rhQGXhAoqdcmxXMvgEUNh15B9c
+TC3eQ+z+90tksKUZNmlx/U7eO97TMAXqx7KysqwAL4xXdnr6whxjIw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6.pem
deleted file mode 100644
index a9fb2b27fc..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid EE notAfter Date EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICfTCCAeagAwIBAgIBBjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMDIwMTAxMTIwMTAwWjBhMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNjA0BgNVBAMTLUludmFsaWQgRUUgbm90
-QWZ0ZXIgRGF0ZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEAyCOeDYaml7SOL+2x9UWcwqcMIR9a0vGlP8Do87TNFZz+wiLZ
-0nMYVMfnQWT28E37L2tcdoZUM7SW8dlvfMfTKIoSKeXUiD4bRftrWVj4/s9Ipb/h
-8Gl9k0GwUmg9gN3LDvdRw2z2CiBtP6xsNJZ9vFW+o5QIhd84r74TPs1H2xECAwEA
-AaNrMGkwHwYDVR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oVlMcwHQYDVR0OBBYE
-FP4ipJtrQCKWa5Vq2wk2HfpPnJnGMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
-MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEADdATbChw44x7r1EYA7A2
-1BGzR/9Qmz2Dhd9d1stBum7SiD6Rclpo9A+CfwMmPhzNuaAScE6jL7LGwOYIbKp0
-LczJhPXVy5XLwf+pciCQFDFVc04/qEIugQJm25iQkm6W0E6kpOuwrOlpUU6SRAB8
-AktPedUhRoKNsB06vemChz8=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6EE.pem
new file mode 100644
index 0000000000..e80dbea823
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotAfterDateTest6EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: F6 4C 36 C8 65 51 7B A9 5F 73 BB 49 44 AC 4A EF CF DC A6 CF
+ friendlyName: Invalid EE notAfter Date Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid EE notAfter Date EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDjDCCAnSgAwIBAgIBBjANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0xMTAxMDEwODMwMDBaMGYxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTYwNAYDVQQDEy1JbnZh
+bGlkIEVFIG5vdEFmdGVyIERhdGUgRUUgQ2VydGlmaWNhdGUgVGVzdDYwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVkIXCcTqIC0o6oloj+rv8wFYVu8ss
+0yLlBy5nINdpFsuWwMezsprPdut5NnThg0m+t6SiQpFqJcqQKVh2i+z8/DUWfWNr
+1H6ShCDO7xPupe2o5pSJe5dTonyC2LHLABc9HQxGxCvL6hAXz+/nMciADvYrCHlr
+n8ztVSKXI6jaBZwb0KzcsWHtjFxVWbPZ2KVp2yElWUJxUdX9rUnOYVATeKVKHohV
+QFYA6wAe/UETnkCdz1JWqs+vG3QMjw5/w1V1lthf+SFbJiT3PVV8VCxq23bNy4wF
+M5GVeDJYs3lIm7rIo0/d7PvLhVUCQWmsQKMyLwS3xgBrOeIWNsVAPM5LAgMBAAGj
+azBpMB8GA1UdIwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJMB0GA1UdDgQWBBQl
+6Mt3tdW2ryNfEQ9WI7oGr62koTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
+BgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBUXyfp0KcfRQdV031V8bA9
+gngzQtrEI05Aa0VbgTv3b7VKeIcgwsUMeNjuJZ5hUxAISm8+xwoY5e27EOHxWG+y
+Dtk2Czfv46Ga7Pau5P5wag2QkPk2WlmVovMp92zb+GI5vyLFnEdNY3zkTtFxCbYI
+LEMROtRjDM3EGkXmkoblz+Z+u7NaLW4cKI9gBYytP3Ezg0R8dCRjDRkXy+95CE8q
+6taAwnxIQ6FqGxjBgf84oXVW81qcIf8N3i+ZztMK2a3swEDY1CyeSnj9WAX4kt18
+Qou/YP2hqVJxApNFFcBfqybSUOyLu8mbYlBAAYNB70QchygcEayvAXOIXX/NunA5
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F6 4C 36 C8 65 51 7B A9 5F 73 BB 49 44 AC 4A EF CF DC A6 CF
+ friendlyName: Invalid EE notAfter Date Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D12A38D94C74CBDE
+
+7qNutaQU4Li4WSh6pGKQKoSS5jbHR/a2L5H6DcpJYGjDaHRyWmf5FEC/VEC0NXda
+QA8xVcZD8AMM1e1HnlniqwGDE4+SwPSNHOZ5qnIPmnwz/9iW0HxkQT95bMzcur+Z
+Nuew4iwrJ0VfjbB5DeX8OZSW/Ut9kQMRakWSPsygjTudsC+RMG+/SJDBDsA+8A7N
+SELORpkRB8WL5szF+tifUMg1fCLeXIWk1S1ByBezSNYkUmtVkdpzBWCHWQ6CjL2s
+a0aU56Vb3AYex4srhgM1Hp6XOvrRAAYmSU0DMoy2xh1XHgi2pK9dx0+hveuHTTIU
+/XbK5CQgMFGvOvSMx6qlMlp3diEFsw6JtC0Iqc6RX5iSHmJ1S5uL0Uk6vw+/UV3W
+68D1DzaXr12gLF1kpMFq/16mVBzvBAlGBQAKNwvPtZRgU866V5rf3/bWh1p5FlAI
+vaiokUR/tUQuDQjAQ8PwgH1csHtKW6BpGHDZK5D9FXtAQOZNP8l6LOX+4LRpcgZx
+x2Yp8sOhuzjO359cxGt9TZnIKpEjX/M/tQEO298q8EMjHTWSRzTb03PwoUUIgZyZ
+3lyCGY456MORDM8DUpl028kG/hwJi68EyfDmDR9jFAy3UNHyK9fEhP+VInk+82Ix
+GemQXlGr998QeuOodUisUufn+yYyE7hIIahTDlHW05earGfg3UhYHjb+w4WYM3Gd
+aQRiEqF8srAGZL7HXnl5OGXSABheyIaqi0SLzPpJTtoWcKOi5TthXavMpHNnz+3q
+WXD2XkzJBCZyiMkDW/BYmmtOoVdIawEAuFoIuyIht3TmjQQmao6II2LlT3a/XFLB
+p8Rm2zw2IF23+nDdHQ1o3MJ6JBQPChAjDGMrXI4aKWXURqO75+9Z8VaK2zBwB0EQ
+HsJUAlFnCVrEic7m0PQbJcfU0XjCOaYT26ICmX6InwkdQH3p/jFxaSpT7dRiijUL
+SGqP4Gtv+Um+ZJ+IdfZvYDqZ54Ga9wFoJvDvuSkptasrzre2IfJXm2+sj2WNYP5L
+eNAaBWfY66NJ7Smfl9WBmyQ99yX8J50Yyq+CKOvRupNSYHWLnXOq8a7rhaTGNPse
+KjbVtsxG81wkOMed+7t2LWLj585FVBqIpHkAiAdFEZW54eWXC2Fc48VSmfBJfmqF
+Ub3petrSdSC642Bpx8FUlvLz8dQOMT9l0Y0MiHIrS579hihlEkC5D+ycYVO9PhtB
+gDV5xSHaILQ9IzMg1bmoFXvIOcFN0/qRfo257znG0nMUMeemQsQJLLzH2BQStHrM
+Htjbty4n03oYuiTd/B51ztLHd0Ou2y7X6hBpKuAHSsA95tAJ2rPG+nf5ylXXC4AY
+2CBysvFPm1TWthSiwL4X9TRTjxTw5PKB2hZzxBEZJ0o3/I7RMH6pq3KEn0Xl5yhC
+PErTitHGfMCUkol3o1C/C1PJJXIepEcrahZKSUriCTvRZgrg7wHfODGmKncroHHi
+i0g38wYLdqVy8GkK69zOuSexeJZk4G3/eZwxBDJ+ST1m9oYLVHCz8YAVIr9Jr5N8
+ZskNdz+wSV2xyfFTbzmG7s+dpb5y9CcP+jTfGZG5TvfpMzS1cuv611o8EzFlQJ6L
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2.pem
deleted file mode 100644
index 6208b7d277..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid EE notBefore Date EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-NDcwMTAxMTIwMTAwWhcNNDkwMTAxMTIwMTAwWjBiMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNzA1BgNVBAMTLkludmFsaWQgRUUgbm90
-QmVmb3JlIERhdGUgRUUgQ2VydGlmaWNhdGUgVGVzdDIwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBAM6vu936ab1N3e528zJ2ryTW9quJh45gf03iwH7dWEYsZpO5
-t9UBImXpFR+j74ZQenhHmcgGQNy58Zc4KwbzxnNMnvW7INMVc36TZzdvq5hfXCsV
-SX5gBctkPQ1hgh6LZHLQoUnxJiI7iijUUE6P2p4HfaqfEkh1tQfjivyF2yo1AgMB
-AAGjazBpMB8GA1UdIwQYMBaAFLcupoLLwsi8qHsnRNc1M9+aFZTHMB0GA1UdDgQW
-BBShT/d1PnEn2vh4FZtBbivDFsd2djAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAGYyJnIuxfaHwIyiOnLc
-T3IRt4wcrAOMimrliGD1dHOozDxUnNA2gZqA11JYlTJ6QzScfOQ7Wg8XKu3mxA8u
-c2A/x1cX9PYiJ5Js37f4OBW3/sWTk+X+9G5iS3cDB4e7LDqCdf+Q4eEGlyEZ8xw3
-FgxmIZrL8hh7RlY8QIAMRc3S
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2EE.pem
new file mode 100644
index 0000000000..24330b19a6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidEEnotBeforeDateTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 44 B4 F4 DB 49 50 44 B5 A2 25 5B 57 D9 F2 92 13 9E 7E 9D 39
+ friendlyName: Invalid EE notBefore Date Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid EE notBefore Date EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw00NzAxMDExMjAxMDBaFw00OTAxMDExMjAxMDBaMGcxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTcwNQYDVQQDEy5JbnZh
+bGlkIEVFIG5vdEJlZm9yZSBEYXRlIEVFIENlcnRpZmljYXRlIFRlc3QyMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtc20YJ/j2rSNlGJ/J9rqsxZKwQvD
++f2lCf9yV6nowMsJGRYdX5ERKWoqW29xpRaseNUf38roqv9TiBy5bXzOoJ3a6zfN
+SvhWPf//uk4zP5fBAEwq7VL8+UrpZBsKpbTaVIvIeOfTpvWr9qW1N9J1aH0Y5B8D
+VsFsdzrGc7rjbDvb3bz2bymkDKGW2A4XClecaAIGJiJOguEuYMhq4B5tndQ0cAQN
+QcDXS9li//HO3vlYyiRYv40hZwaTt41m5cQ21xTfFOa/ORsCa96sAL2TR64sT/u4
+DWck/9kh3qxsw9gRSkRydr1xOX3HjA6gYUl7nv04OmUSHwf/w590ry4elwIDAQAB
+o2swaTAfBgNVHSMEGDAWgBRYAYQkG7wrUpRKPaUQchRR9a86yTAdBgNVHQ4EFgQU
+mXSnPUJsL24xEXiVXHTV4VzB9nIwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAPSuzpUlBOhAZ8lTzHWdq
+Zoo5cC8+mX8vg3YOTm02idO47H/HcqUjQMJZaUr/gsnr0dABy2kuiU802/JbLp3i
+jLGTygmGtU7Wqj2t9IEgDeZdQflrYfaCm8rPqNeiwrQb0Mw52dXLMz3YFLqG1BAG
+Fqrxg2utLDQfstLrpMs2BHXsSxSBq6ad7BS32qRweNr1KXQJ4QNnRGFrOARTMxi6
+MBY3zCiMJWYtgtV6aCt9t/q1kt1NFCkc8CzFdpgV8/rz4poS4FNweXhT+RqyF7UT
+PBzHycgL90/QG2N6LlTHxux9ElHQYy8HwwxlJoE+lPv89DSLNwra1mQ8MJMu7h9+
+qg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 44 B4 F4 DB 49 50 44 B5 A2 25 5B 57 D9 F2 92 13 9E 7E 9D 39
+ friendlyName: Invalid EE notBefore Date Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CAAA900EEACAED9E
+
+d+pM/3UW90Y4Ig/6oE1g9MLVEkCn//6Oo3HubTLjk3NM88UFOAyLp1Ifm1Dhhz2r
+njXXB7Hxz1LkRin974RKvNfHZMmrFBHNCHHGpfWP6680dVmCBygdUnBX1Ex8d9Ua
+pt2+MIq/O4ceA5ajoCLENp/l1oBaqkBNEmzJ0vO6UWjOe9TipYzmhzyIbw8K6Q7E
+BoXnQCt5kKWOWFJx3wlfhap9ecd1YxFG9C+EXzI9rJhbZ72Nm5VJSFefQ+YmnerW
+oOV05pXUm76QrcpJH5SUAMdIajUnlrXlHKXTyBAIG8iKSBg17fU3kBJil9sLBrL6
+wp9/hW54KiUBdGhQ4jyqOp0rbHALHF7Rrj0iOn8oxG+vjXywMlvH6UDY9iLBRqwq
+q0fQ3W2T/fG9XQHLBjRD/y6OgG3k4nWtOatOzPsyZsUwU97jNzVtUd4gHR/vc3im
+DmecIfmNrt4owEv1dOi6vGoowgA+tSAzzD+r+brHwynTM5YFXHBtHKlt5EaA9A6M
+hBA4hpwnhBcBVI+Ai9FZhUfPl70K9vGYlF4Xv+yclGLlTKDryVfqrT/XH7I4oImB
+LwgcywnocjjP895Te9MDpxZE+FSeiTnLoI4dks0O/kMwZ4g2R4wmc+3h0RWXFCEL
+PMCgBbHVJ/n/8vt/L6AnKgShx5dcP6gEh+2zUxzPocQP4oJt/kJslGiINQlYXzXn
+wZ7b1iKz8zfFzPhzDp9qpYH13xs6/NvAXq/VdWUqZfkHSZEs6BL5wc3LHIsrwoQm
+aPqMTn2roBW1/gRaaa6bjErKf8Kfk7S/aVyyck1LB6hhgzAtHd6ZWBegRZaEguse
+0RlePqDtJ1Aj1FkogR26ZQhVmP1k7XpQtsvOO+fGE9IAEEv2OlxLCnD9IULxbeK2
+QDiPd/AKkMXtQ1C445ayKbEYOfIU1DEBRXzXz637dy0HiOHPyslRjEKz8KwvKcMt
+Z4uLTt7h9uNzn9GuNrDZPy5k8qieM4QTCKLvgA3NUxuEQnfrVo5ySQ5yNh635AOC
+NRRhv2wpEDivSUzpOK2rdw76K4Yu81st5nwi3NSvvfX5maEV0AqUneIzZr2qK42I
+Myrq9ZVqgt9mrrKIgV2qVfStVOpYaJ0aL8Qlo8MVtjpcZ06/eIpBsE3zVcTr9xfs
+QIV4LH+/5/pEXVRQuhYLMRcpTheIUDLex/dfELb4xe/Ekf0v7/RllB2nVgxMRauT
+Z54UTj5fE4aw8Sswcg00D8Bi/BuCEnNmtR6upGsVN/8Ltpj04Ql24+YzEt0YJ4ua
+3XjM9QVd1YwsNnwIUxX4GLBFfXVLmUKUM3Ou9CuIJPcW4Ea3H/bFgl6Zf9nAX7JU
+hE7esuv6KMOgKZsTjlPhZ/k/Z3NSyNqPRQdjlaL2Ax6DGBO2Pseiyp3idLjwMyov
+P9+y/IWlR+poqb5NvZnx6LVWvIc8Zc+0ygIvOi+olaB3F+ziiYse49V298CiAAVI
+E7a24HgcjkYVLihaZ+qZInQnu5eX3JznGC6s/PTToLjDqTWrb0MJeLTjEokc7S3e
+gKA4ka4Uwx0Qhcbiag8JCr4/RMm+JTeQ5pgwOXWAw2TxKm7+qa2p/hhgH07tXTGh
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23.pem
deleted file mode 100644
index e8f2b80b3d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23.pem
+++ /dev/null
@@ -1,116 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKnNvKCUbOkr4mNPrV
-EBeh0vWaSj7DMTMuBhMM4N5zT6XkBdghaAMQis36dJASxXYtGiiAY0Wv3oicc66t
-vag7yMp7Iy71oHzCSrw+YF6oBOV+krjeaNIg/5/CGLkMr5KXC3egPap4fv/EQbAD
-ZbMw+Qndc+mnj7AAnfb8i2AJPQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUbMEUX9inLeCGkxlcC/BJuSVb6BwwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABA2o025rmbJVizdycoV/q2zarMz87Ki
-QJimcOjKcZTSmDiAxKCTYzBFWeUZWZqVDm0QbhOThmX5nkaYjiz3vLAgdDDUr6zA
-tYmNsP2oA7ajpSmcze5/VwkBgMKt7Al5w6xT91R0tCltLcppOPJhE85jMd724jTc
-XHLxTJCox/SL
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid IDP with indirectCRL EE Certificate Test23
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA1
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBMTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGYxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE7MDkGA1UEAxMySW52YWxp
-ZCBJRFAgd2l0aCBpbmRpcmVjdENSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjMwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJR1Ogq33bnWdnMPT8T7u4psSBkPFbwr
-6mSgwNE1ZPPI3wkF66/zJAKMPK8LTskPhZ9QVaKvAt2MnLz004Yv+rS2N5H+cvTL
-oeXp0h0SbIgwRsgHWNBoOLACifcpIqR+dGuSakGD7dHG+NClC6jVJp8mf9EzxW84
-bjJvdhmADg7LAgMBAAGjazBpMB8GA1UdIwQYMBaAFGzBFF/Ypy3ghpMZXAvwSbkl
-W+gcMB0GA1UdDgQWBBTbRhIag+0VzAQ6Vki6uTqYN+IjxzAOBgNVHQ8BAf8EBAMC
-BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAGxw
-5QQhnpLypGVABOGVcbBYU+WO8Wkdo3htkGA1XHJSVggDQSbnHzX+1V/ETnAicQrh
-6ktOuzBTCLOG5TjmgKKcnS5y7rIndkGZ/3lo3DJydBzVGoLVUs5FWAvuWjIikQZO
-BEymYFtHwJh7iV0ma8n5No+re9BhnsQuWIfS7YXX
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=indirectCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6C:C1:14:5F:D8:A7:2D:E0:86:93:19:5C:0B:F0:49:B9:25:5B:E8:1C
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6c:ab:91:4b:38:62:8e:f2:48:86:10:a6:b8:b9:c3:c2:28:e5:
- c1:d8:3b:c5:8c:6f:62:44:37:f6:1e:2f:d4:04:be:ff:bb:28:
- a4:3c:71:1f:69:58:85:95:60:3c:cc:f7:65:22:4e:9e:44:e2:
- 6b:45:16:9d:67:ae:da:ff:57:e7:d4:ef:34:cf:1e:86:52:13:
- 25:77:a7:7d:fc:ec:94:62:bd:b1:76:a9:66:c1:ef:82:bb:3e:
- 9b:21:c4:ef:49:9b:2a:e8:5a:ef:39:82:ee:da:97:5f:77:89:
- a6:3e:42:26:77:b2:15:97:c4:db:ee:ca:8c:ad:d2:cf:18:3e:
- 87:e8
------BEGIN X509 CRL-----
-MIIBcTCB2wIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBMRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcy
-MFowDDAKBgNVHRUEAwoBAaBAMD4wHwYDVR0jBBgwFoAUbMEUX9inLeCGkxlcC/BJ
-uSVb6BwwCgYDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4QB/zANBgkqhkiG9w0BAQUF
-AAOBgQBsq5FLOGKO8kiGEKa4ucPCKOXB2DvFjG9iRDf2Hi/UBL7/uyikPHEfaViF
-lWA8zPdlIk6eROJrRRadZ67a/1fn1O80zx6GUhMld6d9/OyUYr2xdqlmwe+Cuz6b
-IcTvSZsq6FrvOYLu2pdfd4mmPkImd7IVl8Tb7sqMrdLPGD6H6A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23EE.pem
new file mode 100644
index 0000000000..919f66170f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest23EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1C 9B 82 D8 89 4E 86 A0 03 5B 14 40 C5 CC 2F C7 D4 ED 03 97
+ friendlyName: Invalid IDP with indirectCRL Test23 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid IDP with indirectCRL EE Certificate Test23
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowazELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExOzA5BgNV
+BAMTMkludmFsaWQgSURQIHdpdGggaW5kaXJlY3RDUkwgRUUgQ2VydGlmaWNhdGUg
+VGVzdDIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtm7caH1lpNAI
+shNu0OY69PXWaaBENPHHSe3ot0KHTb7EN9Rc4Ypl9KadClpdSmNdgUvL0QSqmdZA
+k592lYXRBS6kSlumWQpIx2SA3MWsc1XWAeWOE/aw0m6fhTQ8yL/4S97stjfJgjwl
+97G0sXcMF4DDeTNR3NHleo11/SPasoZqQvjCWfKEJ+vuzP0zW6JR6PzJdhll+VzO
+A9txxI6Vtq6gusfoq2e3Gf+9YTl03G/ta0S3Ssf/G1FZbNS9U1hSJlff969925kE
+Py2cgVq0i99mGGSf9dxLj21jgZH7lTuPYDiXz6mR6qdgK+5EKJroI+ev1qH6921R
+XOAzsi0wzwIDAQABo2swaTAfBgNVHSMEGDAWgBQl+K/8r7apGht5S9vLZCyLS7EV
+zTAdBgNVHQ4EFgQUTEZlYAf0YvkjTogjZLSWonv4Q1UwDgYDVR0PAQH/BAQDAgTw
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAdWW7
+g+KdfMOKQal4UHHE9pxyR/z3CLnVck4gGmGkdnsuaUV4BsuPC3PHCeKyNJcrLneS
+vb56GZm6WcLohMLBIsasqg7H7VK9ActQx4fC23qV2zRqtLsATIcWOKVLSYP0XNxS
+1yu967LvXoOlgF5RojE62aaLfAWgi9L8+DNyUiFMxM8ymKOr3K+AmgAQRtT3s+99
+V/t6q+2pHMQkA48GOU/0us9Pb5dQs6KDEZUmt8g5jvLiX1XrXKl1zBODmFJMViJx
+VWtSwncbqzE2DwWpmUPxN/tMFtzC9vcxf/Y3DW65hA6654YR6esTw6xJBknJv5NB
+PyJyp1AOs8KblEtA7w==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1C 9B 82 D8 89 4E 86 A0 03 5B 14 40 C5 CC 2F C7 D4 ED 03 97
+ friendlyName: Invalid IDP with indirectCRL Test23 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,48A5FEA583B75121
+
+BvzSOqMhhehMvvoyLiaXS9wzeebKAz0sV7pRF6OjYeM1yV166w4vEaU86z4Q2rQ1
+GkvIfnJ0TP+EmpHmK/qUaJALEy7GCYEcceNLNF1+ciN1wBP8z/n16ff7pOeVQHsF
+N7Zwx1oPKKMl6K3zdsNrbIYMbLMa7dx/U4+0JtAI7EtMwZ6Xuj9htCjkf+KLkSU4
+2hfom4dyTjJLiffl2Wq5YqyoJZyVgq99/LOPjIltDpL1Atrv9BSbNpZpZV7c4i8r
+R82feIJqaQwT/T3rg+7hfp2EiJGwlQv2umtlywm5Se3W6y79tjC/CSBS/kKI03SZ
+d7RETnqczKXi27wB2vSjKIQIMP4LyydfLLvSNzKQyIlWAiSELLKR4hUD8vhFykGf
+/PFox9uXQ8hP/Mzd3ZXOZwOpiLKg8aJ4FUD4VWwtnuBA7YHxPXMr5egZaALp/aYa
+9FAQgLr6qkMXBwQu9XCr7E5eXlhh6DMghNwIrnrjnecpUcUpYO9i5Gsp6jGyoGJ/
+V7UroRL4cfw61Pegz5C5KbwXtWVn8Bj6EU+TNvTdLCKUGvaoyR/7Fw1FyjHn670V
+0/P+MWtaG/Wv9TFGr+xW6ytM0lJ4E7fNXyzMDnaRKZKYLFik+Z8VsqTmrNZp2MMi
+iOEre4X6sjYY9n4o5R16H2XjOPSzCokg9DfmVN/kRZU1RrVmlSUPFeQqnGFH/Prw
+f52/LPx6mECYYj3muFSIehzcDf2GAYn/JA8xTSbKdTiJzH8OZwVqdePMpwM+3bHz
+/JfdU/+6UKAhONcHCgaFnLCUXNiEIn0eAqGsxlFDlzxVsm7GOG8a3U+LLJohx1O7
+FTLKLE95MPryQ4exC3Q4U0VvqbI1aN8oYqoOyYor2A48oPo2ptc1kZqNVHKrvBEh
+ujJTGy7KZNaidCz8zgVBEKFz/LlmAdvMprMQdxz/00RSoWXugqDDdt7X9L7pY6Fv
+4vZAW6pDFORPGIV1q9Y1zninGaMn6Yjou8tWmTl3r/lT8DsKD6pi/djhSiU8/KWH
++c2odEWSU9YSlp7yG5eylV9d/ki0iBMEp5gE4pqiybfnqOjOKSYzNBWNWPtbc3EW
+rHSrcwVRecviTLrCfN2849oyibnoN2vf2N/8KNv6+ysivEgmMpq4lmDksmNkB3ir
+kgRzjASm4zZaXbgIghn4pFWxmcfOBpJLQegX7F3sFVSoUQv+DFBOlocMlAXJKCY8
+/H1THWUVJGwlw30uQc47qt9d9SfmxgsRfGR8fPLC5WtGf3o+S/UaMvwtHmTX42TC
+GbAS9bP/ymPmK0iUyxngTmGJ3Ke8kWRihRK6M5bPdHkOHFveFbBs34e0OfLMObc4
+tX1vi+wsNT1hPEpWJisKtzzXaZ+h7msiuZrb7IODtKzwUgDL756uCgK/vxrl+VLu
+LNd9QEnnNWlfteaDNSPB7PXb95BeJ3T8kX0NCjbSQRQWq2DW1NNrgy/E49+k4VPz
+PP9XZPo4+cabHWzv8GKF/N6YceD6qAZv06x4RuKV4oGuVtnr+REIcTb8dK3CxOyL
+WQD+zIEggED3WeiAyygyV7FANxi27LbSzYJQCJnDlDQSVZ052ZhnU4Ih/dUbA2S/
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26.pem
deleted file mode 100644
index ec66261d9d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26.pem
+++ /dev/null
@@ -1,137 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKnNvKCUbOkr4mNPrV
-EBeh0vWaSj7DMTMuBhMM4N5zT6XkBdghaAMQis36dJASxXYtGiiAY0Wv3oicc66t
-vag7yMp7Iy71oHzCSrw+YF6oBOV+krjeaNIg/5/CGLkMr5KXC3egPap4fv/EQbAD
-ZbMw+Qndc+mnj7AAnfb8i2AJPQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUbMEUX9inLeCGkxlcC/BJuSVb6BwwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABA2o025rmbJVizdycoV/q2zarMz87Ki
-QJimcOjKcZTSmDiAxKCTYzBFWeUZWZqVDm0QbhOThmX5nkaYjiz3vLAgdDDUr6zA
-tYmNsP2oA7ajpSmcze5/VwkBgMKt7Al5w6xT91R0tCltLcppOPJhE85jMd724jTc
-XHLxTJCox/SL
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDblDsGRxVahA98R7vE
-/DS4nbSbyoerDINPIyc8wkOtWcS+y+f9O5IIdDJOZm2I5px1PA840SXYHh15o3ZW
-Vn4gFU3AgKF/CWMJ1g79LAYAMnQN/T7kSfuz/0rqhLH9tjz3Qtjt+/zy45YIny80
-7JOBLH3eLX0H2aOmsJUenp5ExQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwa+CD9XTTxDwMWI8WIm5inS7nAEwDgYD
-VR0PAQH/BAQDAgIEMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAEvc066az+E8sftMAgkECVeJVw0Mcr2y
-YlJ0SAbZUNaU7KbzXxm3j8Q5v8K8GDy7EB4H0Gyh0vgsbChTAdLip7xQf7V7SetA
-nE66H4ikF/UAhXlSz+E48Qe2+L3w2weGbU3zwmNMeYkI6dmGFMfEut7hL9ak0Ulc
-0meAGzOu5kHt
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid IDP with indirectCRL EE Certificate Test26
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA2
------BEGIN CERTIFICATE-----
-MIIC4zCCAkygAwIBAgIBAzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGYxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE7MDkGA1UEAxMySW52YWxp
-ZCBJRFAgd2l0aCBpbmRpcmVjdENSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjYwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJWG0QMGGkC8v7EYNdgiIW21p0tpEHdc
-A5GWLdFuWvXKCk0fjKc6H/xux8sQgSPzqQkSVwRCvoQZuP8YbELalcOpbU1KN+NY
-xJUjVXB1FZwvz+9tBl8EXV6h+WdvQ5i0H9q5HIhiRqKx3ol2pTbnbE7Tq2lSeFZs
-J9pjj19d2bEvAgMBAAGjgcMwgcAwHwYDVR0jBBgwFoAUwa+CD9XTTxDwMWI8WIm5
-inS7nAEwHQYDVR0OBBYEFNqqzRuM3BRGiQozMByWP0u9kYvjMA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwVQYDVR0fBE4wTDBKokikRjBE
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGTAXBgNV
-BAMTEGluZGlyZWN0Q1JMIENBMXgwDQYJKoZIhvcNAQEFBQADgYEASYGU+PXCspmb
-cqsXmUr/HLCeEc9QXXTDPtkqweBOdgVc27fLaugIkTOEcwkHnxGBst2VRxbG7TXR
-sdcakIKE52+VN4ll8u/oPLs+rp+Fp4Xe9nMj0scOzjcSzBRMTN1VtpVoFUM1Jp5T
-JFEnAXzAMD3ex1dtQYriGo4yHKWcpkc=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=indirectCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6C:C1:14:5F:D8:A7:2D:E0:86:93:19:5C:0B:F0:49:B9:25:5B:E8:1C
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6c:ab:91:4b:38:62:8e:f2:48:86:10:a6:b8:b9:c3:c2:28:e5:
- c1:d8:3b:c5:8c:6f:62:44:37:f6:1e:2f:d4:04:be:ff:bb:28:
- a4:3c:71:1f:69:58:85:95:60:3c:cc:f7:65:22:4e:9e:44:e2:
- 6b:45:16:9d:67:ae:da:ff:57:e7:d4:ef:34:cf:1e:86:52:13:
- 25:77:a7:7d:fc:ec:94:62:bd:b1:76:a9:66:c1:ef:82:bb:3e:
- 9b:21:c4:ef:49:9b:2a:e8:5a:ef:39:82:ee:da:97:5f:77:89:
- a6:3e:42:26:77:b2:15:97:c4:db:ee:ca:8c:ad:d2:cf:18:3e:
- 87:e8
------BEGIN X509 CRL-----
-MIIBcTCB2wIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBMRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcy
-MFowDDAKBgNVHRUEAwoBAaBAMD4wHwYDVR0jBBgwFoAUbMEUX9inLeCGkxlcC/BJ
-uSVb6BwwCgYDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4QB/zANBgkqhkiG9w0BAQUF
-AAOBgQBsq5FLOGKO8kiGEKa4ucPCKOXB2DvFjG9iRDf2Hi/UBL7/uyikPHEfaViF
-lWA8zPdlIk6eROJrRRadZ67a/1fn1O80zx6GUhMld6d9/OyUYr2xdqlmwe+Cuz6b
-IcTvSZsq6FrvOYLu2pdfd4mmPkImd7IVl8Tb7sqMrdLPGD6H6A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26EE.pem
new file mode 100644
index 0000000000..6e70b85799
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidIDPwithindirectCRLTest26EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 3D B0 2E F2 05 35 87 13 B6 6F E8 54 C2 6B DF F5 0E DB AD E9
+ friendlyName: Invalid IDP with indirectCRL Test26 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid IDP with indirectCRL EE Certificate Test26
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA2
+-----BEGIN CERTIFICATE-----
+MIID9zCCAt+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowazELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExOzA5BgNV
+BAMTMkludmFsaWQgSURQIHdpdGggaW5kaXJlY3RDUkwgRUUgQ2VydGlmaWNhdGUg
+VGVzdDI2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzJp7Mm8AkEMq
+W4e034nVkgFmlWsFMdAxhIzcgHthAQ7sIQTi7sN7P0EenZOMSSeP0K10xy4EXyzW
+AQXFU9P4fsVpQDgh2U6fHO3t0YNikBvfOvaiZ9eQ4WPhIPx4RO0cw4iBpq5ysfSP
+WedNqTG/pc4qH3f7fXz2m85kMaNj2hUwe7/bJL00ey+PPtNU/Rt9p/fH9B+Y+iPw
+fjwIkzS79mhQqYrMlnozbZoNGPgEhIfOK7evenqKzx7uSF5U2Hl7Nhn8FyDKDSEj
+Hn7uwH0xyxwNiur6LEPT1tjp9UPAF1gkxkoTA6TsswvqYLv6AdZn9AQv2RShzjtU
+ATC1fwKXqwIDAQABo4HIMIHFMB8GA1UdIwQYMBaAFIgj4bOz8mz+Mam+i2GqO5KH
+BaSjMB0GA1UdDgQWBBQdm73CEymor8YNtVmDdOAPqDK4LDAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMFoGA1UdHwRTMFEwT6JNpEswSTEL
+MAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGTAX
+BgNVBAMTEGluZGlyZWN0Q1JMIENBMXgwDQYJKoZIhvcNAQELBQADggEBAAL+uBvK
+t4dq2d7MweVluDX0HLIGnti0R6b4E/IVXl10IPGh+X1XijPwVfV2Qm/5hDw6BXqh
+t/rs1JoEwEEJ6y+O2XAJjJtHWwI9hzwgW3DOj9qIK5BZ1iGlvINyF2zCbTfrralf
+6xWNJ1ranPB881cS0LzAMt0BhfhzjPC/NSs4gwu1MXY7MEUR6WPlUzhw/s4gnEtC
+0ZJFHYC8ZxC3WNHOgS9P4hVibw9dvZVFrtF+eNogqxuJqABvMv5qWJFd2h96ErVk
+ZjYHStm+iX+qoygvbRV/b88Oby7CCLevBru0T/TsyFPfxxx4m1bLjpdfaz2wPrZV
+RnN3PlAouVSXbb4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3D B0 2E F2 05 35 87 13 B6 6F E8 54 C2 6B DF F5 0E DB AD E9
+ friendlyName: Invalid IDP with indirectCRL Test26 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,890D36A52515C723
+
+BuvcGzvcJdjeMJfbJwLTep9xfmuaoQmVL7ApyJF7FLCghz6Uay8cCpaULPB27Z69
+LRSHtaZB23jYdSSdC0dy/94a1QsAPRdt+OfrnXE2M/pd/TGLM36EKANr0uslDIaF
+B3DBHsM3fV00UqCVCLZANUEKGEF3DNQ7F9uXQYDgvpWkLdoenC/bnIw6f9NO7ZZE
+kQYLZj9WH8KIo0EH3DlAg456UeVkawsYYlBRQTnUUbFEOpsM1q+xwMjpiDJfg9vI
+72nGeElfy9O7QWDQzEKui8LrMiIk7YVev42awnwjCiEhGIqKrwpQv+JPv0tAf9KK
+v5nrzpitqv9/jtZTkGoIQDg9CueDr1UvDGSBOKgFSdgDihwTbmS7xzM2cS1awXMF
+2RgFIrRSg0fR4iU6mJn3tqzxFmzg7TKYWEKvGhcEuJsKo3637Ru6xzpq41iMfccw
+FtzLLAVdYW3t3DVd0Dwkg2WzJCxm8W0mLnQ1Sa6rsXiK4uaFKnbIC6L/wZyZqnCf
+GzyPHmjh1Watm/znXrbUV8wtpKPX4UD4kxt9O5HO0XdM50Fq3QkEw0KCfbKzkcqG
+2ARJzY/Z+DfK/atudcg1LNy8RieTPrgUcuPkrlN8Vvu/vpqGt8bHKFh1SOOju8fX
+WwWUb0MQBOordLkD+sTPBn9SYZ7GnfHxtIbzCWkzkuBIDVWx8bvW/01+i59k0wed
+96WRazUK5cz0w94DgZ9MLdY1tUGoR9LdykLdQxrQO6m5WuFy7+aqLrF8+1UBqqXj
+WmaP+soIGcc83f2Yx7No5PD0oEJzbTRCSVK7/Yf84UvrptHAF8bLYeX84D+9DTEp
+HuVpsteNClcXuw6qlj2+RgwjFtZ/a4dECtuIWg6yC17YB+kuso0A4F0ESSEC9ghL
+CWz7bcvtE2UxPG51RC1UY/xWDdOdtTVEWdrGen2ypU9h0m7Zgd78LivGZ0mL/mmF
+ykZDHY+zok28LJiKuLdX6VEoP82uKD7pJ389QkRVUIgseQtq3egGt0HZ73PRFB1E
+kXvqHtJz63voKyyd165fscJ7kl+gJO1m1cZa0pDRVGv491fNboukFrRDcaGyrp2d
+G1L54kvoy+gcKF630Ob4DYvRdi1ti78r7PJ/uwnNfpEE+bBu+AL7HO5TTYPn3V8h
+ARYmHJ3UOEOdoU0We3DSn3yYQSEsSlsL8asAat3qCNuPr8/1siCD52238TqPl5wA
+86fQmEd80rK87iJx8mpYZ4GVK54abh9FMuhajpR9wfNPF9ts+cwPnFOajKmK8IFU
+KXZbSVG2zFMl1wb6WEV0KVsVNZI1rmyrI8pa/l6ZxEKRKITtrV/pX2c7+4QWe6aJ
+iIPHTzjEDtLztB8GVFaRKtUp2GVXE0K1XN5WWTXLTmdG8ZqJ53lKfKrSnV3MOa5c
+Q3lT9dZnSc+kMPiGbJEVlZSqaNlbRtxpyssvRmH3apd76KdmYHSgs3R7rBJU1iA1
+4jzQFQvu1yA92Yy5ODuv8hTwrXxim7WH8oQmhvaQ2qkkhG+NMy/Hebrn3EMEFBoe
+cjIti5UdMcN9/kSmUuuQSHsTxyTwYpGjtgvFGwedSJ1XcOig+/xsVA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18.pem
deleted file mode 100644
index 81cb0d51d7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18.pem
+++ /dev/null
@@ -1,115 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Long Serial Number CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBEjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVTG9uZyBTZXJp
-YWwgTnVtYmVyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1mCudsqPk
-irIFe3XQBPzhyyRQyreJH26B3Yg6kYq1Obd6I1j7Ber4BDVyCCAvnS6rNkzsbaJf
-+sWVf27Vug0uhasZx/3XGc0DbhZNr5iYknU1LEh8Ccq1Oymq0LPolAHqaJNOaYpb
-K5Fq0P0RDcBK/ENgmtdY0CJrR7MWUTttqQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU3z1I++My57kmUova7PgJT7PH
-36YwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAHJqd5P8eBN05uB3+fPCfVjO
-qX7csbAx6X1LNibOoWDlB9Y6fElHQS+i8HDPmIIdC7N/9xoCW/fhzZqb6VKDQXNM
-9pwf6jOJKnNQOaQISdoIvj2Jn1FoE4Bo1SGGQo6ZgCWfXPA1TE93BXTua9Oa+FZ5
-fhG3y3gMYLC6ciKePSDf
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Long Serial Number EE Certificate Test18
-issuer=/C=US/O=Test Certificates/CN=Long Serial Number CA
------BEGIN CERTIFICATE-----
-MIICoTCCAgqgAwIBAgIUfwECAwQFBgcICQoLDA0ODxAREhMwDQYJKoZIhvcNAQEF
-BQAwSTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4w
-HAYDVQQDExVMb25nIFNlcmlhbCBOdW1iZXIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcN
-MTEwNDE5MTQ1NzIwWjBkMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0
-aWZpY2F0ZXMxOTA3BgNVBAMTMEludmFsaWQgTG9uZyBTZXJpYWwgTnVtYmVyIEVF
-IENlcnRpZmljYXRlIFRlc3QxODCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-2sI1yl0rje3fSYBkT9yPudlTELF0ndMo5oaWr8vE9UjhpBrgSFFtYu6GZAbqeZEB
-i0faI9SWBl06pWZj47auSdPeU0Akrzn6If3Vc2eVJKCtAHQuxnd9dToJDqjIiA0z
-YVT7YTE7zLs9d0HHhDhM/VYqBKqtqrOTEhss0ryQRSsCAwEAAaNrMGkwHwYDVR0j
-BBgwFoAU3z1I++My57kmUova7PgJT7PH36YwHQYDVR0OBBYEFLVbztWeCD3WQICU
-BucmQT4POFoDMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDQYJKoZIhvcNAQEFBQADgYEAZjyhu29ssno3io8WqDGabhCgGRL6lS3tgEsq
-k5sxDXO5xgZf//iGlwXTy8w2H+MZ/SX+2acfmFnALYXcGkK5ZHjKQjMOpJZwF/kB
-mzJP4HDEVY5lsvPyVKYqks4lRkbJOMXVBh3Ub5/ag1eOcTeljYhwU66DUMByVzQP
-1RwAcK8=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Long Serial Number CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DF:3D:48:FB:E3:32:E7:B9:26:52:8B:DA:EC:F8:09:4F:B3:C7:DF:A6
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 7F0102030405060708090A0B0C0D0E0F10111213
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 7a:20:63:9e:55:8d:d1:c3:ab:3f:37:97:45:61:6c:a3:21:9f:
- 83:bd:ce:63:48:7c:a8:ca:36:15:02:3b:1b:51:66:e0:23:df:
- de:ea:86:72:e6:92:9a:63:c7:0e:31:30:ee:62:83:1c:3e:23:
- 20:29:23:ec:aa:2e:f6:18:ba:94:45:e7:af:5e:44:0d:3c:2b:
- 13:6b:8c:7c:7a:6d:a2:f7:b5:9e:ea:d6:f9:9d:4d:31:91:8f:
- ea:4d:b7:ef:5f:5a:2e:63:fc:37:02:5a:db:a6:3e:de:6b:a7:
- 84:83:d2:a7:5b:e2:07:85:9f:0a:03:f0:33:53:eb:a3:d1:d4:
- 16:02
------BEGIN X509 CRL-----
-MIIBeTCB4wIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFUxvbmcgU2VyaWFsIE51bWJl
-ciBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA1MDMCFH8BAgMEBQYH
-CAkKCwwNDg8QERITFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8G
-A1UdIwQYMBaAFN89SPvjMue5JlKL2uz4CU+zx9+mMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAHogY55VjdHDqz83l0VhbKMhn4O9zmNIfKjKNhUCOxtRZuAj
-397qhnLmkppjxw4xMO5igxw+IyApI+yqLvYYupRF569eRA08KxNrjHx6baL3tZ7q
-1vmdTTGRj+pNt+9fWi5j/DcCWtumPt5rp4SD0qdb4geFnwoD8DNT66PR1BYC
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18EE.pem
new file mode 100644
index 0000000000..3fda53159a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidLongSerialNumberTest18EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 92 F9 81 17 68 15 DD D6 FE 9B CD 7C E0 AA 62 28 9A B4 D5 7E
+ friendlyName: Invalid Long Serial Number Test18 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Long Serial Number EE Certificate Test18
+issuer=/C=US/O=Test Certificates 2011/CN=Long Serial Number CA
+-----BEGIN CERTIFICATE-----
+MIIDsDCCApigAwIBAgIUfwECAwQFBgcICQoLDA0ODxAREhMwDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExHjAcBgNVBAMTFUxvbmcgU2VyaWFsIE51bWJlciBDQTAeFw0xMDAxMDEwODMw
+MDBaFw0zMDEyMzEwODMwMDBaMGkxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMTkwNwYDVQQDEzBJbnZhbGlkIExvbmcgU2VyaWFs
+IE51bWJlciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTgwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDGM6BFTNKAqi4hroDetUQaaLcSL1wz3qHK8yuKvBRb8Xfw
+OUPa8/hk8GA1HMsJSbs+X5vdq3mTlGehpLFFWimXhMUPY0GbYgo9wR68xGohj4SB
+57eYDXqc5X3Yu6N1nspAH7VxHkeLtKVbj8ggJzw1nsoW2f9Qd1FKHvH8+ds1HiqR
+FabGg2Aeyq0roXZNBASnXPagI+t2Qe3XME2ZDkdtUW8p4L15IegiNSNYnbVGiT94
+KVHtnEmuXmj7pslehnPu884Bi0KBzVRVQujp3bmu6lW59JAXRmNhTrMHyHrTdmOC
+zR5jds44d9e96mM25boq3k3Q8ItLi+FsIj6r86IZAgMBAAGjazBpMB8GA1UdIwQY
+MBaAFAtjt0euwgcyG39v4zq46gv/12SkMB0GA1UdDgQWBBSioFR+93C1hrptVnU8
+tv8CWImEdDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA0GCSqGSIb3DQEBCwUAA4IBAQBZtZv/5s2Km20KY3ZKpVYTYffZ/ITIojuqcInT
+P6lsq+tT5+Akm26rPffWJ7gUkjHKr5vpMpScFTMLYCIs9KWoSmv9INeZBjsbFt+N
+B/GPj7PM0zYlgoRdVZYlmXOgJ+XBhIZ3QwgK+Es2DBWpEdpXBmls8o6QfbwUx7bN
+mJ5UhtC8SOrPsHz9BkiZ5oD1PmbcMY4m8Z6wmjiQzHUw2c9sDdWrxqJ9Gw/uCZif
+C8OFAtKeCUbIS/1H4r+PQV6k51tgFZH8nluvWYTQPL/uCbAbfHlDpbWqQRRJce2/
+OtRZsO6qQznDK+2y75B5aTCq2fhT8UvxA6NgKHhh4rFBdTrG
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 92 F9 81 17 68 15 DD D6 FE 9B CD 7C E0 AA 62 28 9A B4 D5 7E
+ friendlyName: Invalid Long Serial Number Test18 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,34BA072362B77DFE
+
+BP22t+h1zL/WWHrXvkKh5OFPlIwzhZ2jkQMTxl49VtK1AyIo58NsQQnghfoQ3Ct8
+mBfrFDuG3qyyshyDp47CvXiOyckjOX8eyG4BOhfuadqk8/d2bAUddXLSw9ijE/hL
+C9P6OdRU6WdTc1UiMF7sLfIcO22cewEuoR/+ZKMT4ZI4fCDyD6gbvtu5au9xcSdU
+q58vvWTOQ5zCZktiqWphRzv9cBe2B7bzvSRvzuFWiw4reIZZa30/H+Al5p+T98f8
+3Pujr5Fnigb+xHUnk3kokSoWXUX9gh0ckU5sGpeWXma00EF4gkW/qV9lOTlTAycV
+7X8lsIKwsUnBcE/nNmvku21M+BpKP4EKBefTLFCKqLUjltDobSzPqoNg2fdZGqDj
+tb32RwEowFV3kFfRe2OpdXiaTwMk0s9tytEf1F21NKVhqZ6ILNgnWHp/Vk263XXT
+bedwgSEel/I3c3DGRaR71ETabsrkpQ5vi6+0AUm4XuW5H84gqXXJ884Z+RNkXEAT
+lpRhfg3JV1WR5ardhyTDKcx3VZHjRSxBLUvDp9O5YwAEecENQgf+QTAYnPnOeXHX
+fye/sspezzKF3fb1rAB3yuUDjzTd2ov5Z1eJqmzsaI17lw60TONTACMEv4QL/T/f
+AKyE5h0f90EjVkU/vj9YhA8JF1kt1NEPZWaGvw3LdXY6vLa68/KQcS4auUI3CH2U
+MzgYT6VCjiOwZUlrW73oFRKA9dfQhgVjxeG6pj5GvN8gYkiHRLSJnBYrmZJGEveF
+WGYVQKr1HRz67GDGvAF9AnMcYaXJNrAGwMdO+xm0I9hKoYdfeLhxyXLMfl6+YZxN
+lHSvY4F0tv514A3P1ISELU306JtGuKiVI9ZwTJukak2QGYHd1ctokPJ/yvOJ3UfK
+QYOxGLgUR/HKVpkL+X7IuDoRoiybK+NaPhnJvQSttl8F3ZRkuhXkB5S5n4FdizXk
+kEpL8ojKm+C2oJqnrDLVUBfOFjShqDzbbfVBTY2T6vI8lyH/IwHn6rBkU8HaP/X6
+t4REr7Vk6F9f8PlBfIAGSIHeWhoPalUWcY8WxxatwODX3X7+o2ylvfqAyYwLn2lg
+kvIawM4Dpfv7n63NxLdNpG4g9pnPTicrasGCBRKiEJ9WvGGXJmClKoi+dXLaZsci
+0eS06glbt4Q7JU+BhM4ehnjOJNdKWBH9fLpTybEiT4o5mBbMPU3rsxhaClSA08iB
+v6tMSvltG3hZpfd6x0uz/j6x+Bby6F0plMVcLyf/4Vn9ld7N3Kml9fH9ACYZaiWx
+pmppHMiUMS+VRtbj4fS5IXe7lYEb3TTbtUccYGkUiI0lDkoF1fMlarQ+MLHjANWo
+cn3bi/+GHp8//dPcO8z1z7B/fTctrs7IsIp3foaqLLxGKIqrYApDLTzBDiX5PLcc
+/5uyy+q9F/jf4UWwHa0RhfwIRZJp4ZNbnMnbzuJpWQjG3609kw6eSJtE4czM2X+T
+3n252jwqRZFK77eXns9ovYU6eEISj5CoK/HFLOt0kHP5zVOWiKFm8x+qY4iyEXlh
+3ZVw3/MLrrLbmNbbgTfPeSUAvNZ+xJTpbHT/qFpFwmyzpH2x3CIg8lTzaUjCgGWV
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7.pem
deleted file mode 100644
index 792032e282..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Mapping From anyPolicy EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=Mapping From anyPolicy CA
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGU1hcHBpbmcgRnJv
-bSBhbnlQb2xpY3kgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBn
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPDA6BgNV
-BAMTM0ludmFsaWQgTWFwcGluZyBGcm9tIGFueVBvbGljeSBFRSBDZXJ0aWZpY2F0
-ZSBUZXN0NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtfiBNk2i7y/WBuI5
-GCW0+6q3VwFnT3frj/wV+Ie2r2bKy2iasXlilOldX5jcywoO2qcMHUmoeK2eE6rM
-/ffDK4Zd4EhJJ5RJdgoWhjBpfKNGD73JlCIAVGGooCiVx9zJICN9DFl/X6hybpM8
-Gs/BWxcHB7vzpzCGqKwI91lstiUCAwEAAaNrMGkwHwYDVR0jBBgwFoAU98GrNdgv
-hgNaNjdZb8HBpG2kpEgwHQYDVR0OBBYEFNuifbLkKO+WtPZNnKM58l/XwUD6MA4G
-A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
-AQEFBQADgYEAXZ+i/Dd4d11xpuKLT90bOID/badZcsjgBbJ2hTG4JhzrHQN6kxzI
-Xt3L5FBaqgg1SfvC0K6/eex8SDEdEJ5LlbmflMths7r8DICoo3Dyo+y/G6ziqRR7
-fOrYKBk6zhliAHXNqrtQ/fUCCNke/OMk62U7WgbaQuELj+tzZHPHShA=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Mapping From anyPolicy CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICrjCCAhegAwIBAgIBMzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZTWFwcGluZyBG
-cm9tIGFueVBvbGljeSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmMII
-TPwdFq+61dFOwrrjLrVHakDcX3fO14s58oprgJ0Qcm88Fjs1+HyurbqB1r7rySfg
-zIZhJjb6ZZqV4qwd2fyQGhYHSctVTxOfxYc+JnK/eLQ09eCM0Uv2U2e9AyyObT0A
-Gt8DpfnfiMrkyadyKRICC/6dOHLb/OnT82jrw/UCAwEAAaOBqjCBpzAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU98GrNdgvhgNaNjdZ
-b8HBpG2kpEgwDgYDVR0PAQH/BAQDAgEGMBEGA1UdIAQKMAgwBgYEVR0gADAgBgNV
-HSEBAf8EFjAUMBIGBFUdIAAGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAP
-BgNVHSQBAf8EBTADgAEAMA0GCSqGSIb3DQEBBQUAA4GBAImTlpjaX4CkEQLrZZsd
-iyLe+gkOFWF7maBKcZQcCHDUNuIGFeYmRqB+eXsYqooAvYOUfSz30L709ODiWLH4
-Zm5y79xssrJYzS+sDfDHmNMjKo/U9Dj4nVO+ln6PGGe8PPW7P04gUXcQjJFHCLfh
-+czJLt8J7JUOUznIvSEIIsto
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Mapping From anyPolicy CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F7:C1:AB:35:D8:2F:86:03:5A:36:37:59:6F:C1:C1:A4:6D:A4:A4:48
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 05:b0:d2:68:c9:a0:5c:dd:e8:e0:e1:ed:95:35:cd:01:70:d6:
- 24:88:d7:37:d3:05:59:04:38:c3:51:64:ca:aa:c4:07:31:80:
- c5:12:d7:9a:38:5f:67:c7:dd:0b:05:98:71:a1:b3:65:dd:09:
- cb:87:c5:8a:e2:bf:26:27:0a:56:0b:8d:c3:46:b1:75:4f:f3:
- 03:5b:3d:ec:84:f9:e1:03:ee:a1:8a:c7:e9:22:6f:29:b2:6b:
- 64:02:e4:aa:7b:5e:bd:84:fe:af:a9:25:98:7d:7b:b8:f0:ef:
- 3f:df:f9:26:a6:84:d0:16:6e:b9:2d:bd:15:95:8f:47:7a:a8:
- 28:28
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGU1hcHBpbmcgRnJvbSBhbnlQ
-b2xpY3kgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFPfBqzXYL4YDWjY3WW/BwaRtpKRIMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAAWw0mjJoFzd6ODh7ZU1zQFw1iSI1zfTBVkEOMNRZMqqxAcxgMUS
-15o4X2fH3QsFmHGhs2XdCcuHxYrivyYnClYLjcNGsXVP8wNbPeyE+eED7qGKx+ki
-bymya2QC5Kp7Xr2E/q+pJZh9e7jw7z/f+SamhNAWbrktvRWVj0d6qCgo
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7EE.pem
new file mode 100644
index 0000000000..f378d4d029
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingFromanyPolicyTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 0F 0F B4 FA C4 86 AD 59 C5 CB 92 28 10 E7 7E AF 50 2F 13 C3
+ friendlyName: Invalid Mapping From anyPolicy Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Mapping From anyPolicy EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=Mapping From anyPolicy CA
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZTWFwcGlu
+ZyBGcm9tIGFueVBvbGljeSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMGwxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMTwwOgYDVQQDEzNJbnZhbGlkIE1hcHBpbmcgRnJvbSBhbnlQb2xpY3kgRUUg
+Q2VydGlmaWNhdGUgVGVzdDcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDF9e5qo1oWtVVI+OfFQW0ZD4HihKuXcOZyHrCSc/UQJuc4inG5/g8CLClzXX9g
+xSnOeyREom5k1AY0N+W/ynyH31lbKPVZvBmT/nMMhgzIVq691d3O3wSIiYEH44Oi
+wMyhkY+mCRHerh0LktpIX5fnmS0FvT1wYAVFiECrFPCOR2cNsvKL8KZOutoJYtIG
+nM2QtKcUYfdYhwpKq+3f1ae8nlErlhWS8GIn0C7E8x1HPeoCPAoPBuM9BDsa4q7R
+tQ8vkCiL+7mMMf02mBvY6qddPK+LpCvaFZSTFGFZwX7T+TQUXnZtYRFjI0aMWajm
+X7NGQYjwDrojn0v07UMmjLmlAgMBAAGjazBpMB8GA1UdIwQYMBaAFGhzFOALNM9y
+QNqUltYVq3qkby6MMB0GA1UdDgQWBBQxi4iTbnfO7LvkRyyrlaUs+tKzdTAOBgNV
+HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEB
+CwUAA4IBAQA730R9YAV/PansUKZky4hN5m2RQibLIju1MNH6xqQD0T7Bkq4aP1mQ
+TqzZbk7n7v1hcLpLxDZDQnZZ1AQAHQl5JNjLMwKgonL8gX0YLIypXXFeZtxU7oJR
+zdmVNPxTmcnPgLcMm6uPVRGR76qV2DhhgSWYV4C4ewIuEG1Zl6x4azJ5eOkL5xp1
+yM9ara/0T+lGywgOr06T0+76/Kmwrr+kF+fHXkb5r8unU32lvSpIuKKxkyjEcN6A
+1s9g6BxFkfpNVzZUuXphYoAy0olkMAvUWmrAeMz/jP9Zq4Bmq8UHLGmFFg4y5+fh
+6OV3RFRDk3BzX8WuG40rlzE1IYgDDmV/
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0F 0F B4 FA C4 86 AD 59 C5 CB 92 28 10 E7 7E AF 50 2F 13 C3
+ friendlyName: Invalid Mapping From anyPolicy Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A906794B7E07D855
+
+oFcaEPtdmJzgte9y/6wrEQ3s6bIGNZNXWACnA+udLYD/fHdN62qALuN+ajqeeIPP
+Kr4BxU+M4TLcImd4zpqLqvJyDtySGIBZhc7dplXjviJOaG5/DzrvvSesg2oOugqI
+B721nJmoeKilLMd5StbBFt/4xPe60eB6IeUlura3IMMitV2WK3SR390LfnU9H48g
+10jlzTxyoyFpXfLkoV2SHlu6ujz5MXdvnaKeJUbFvsAGXnzyU+c+Z0sTzlkiE3Lu
+8CPDVMDNQDcbSoUOoI81v4cI71j2QVdnH2W2wtsrjImoxtUUkSOc2e2HM75UTorh
+PgsS7WzMxWONng6OurElcH7mbciVCmEc0razbJb2NHnbp5tp+iLeJAAeDSCgUpwM
+QaqLBciEY4ds5/6guGd3AuKOX3D6oi1ARTvyXSDAFoGVgMdiBj7yc28W2xatqJHI
+q8DBt6Qhl0JoYu9uyg74PZf9VBD85/vIlZXrNRWwwJ2iTwbY3pBehqpXMCbYBZ3F
+gjRj9tn+peVlpggZlvYo6gRm0Uo2HnLLqURljHCFKzxh7B2he3Ud+xJrxrMlpQsN
+XQDB87Ej1RjjRfzBIZbQhZsxoqEoHrSbsHDMa5zVLN0Uy/yCEmw99YaZx0utrsGK
+0ZWawS58TqvfFRFne8zFl/8ZFB420yXpBWh248IYCF45atHzGTAqxtpuKxAbxcc2
+DcuchCX1zGFpcoyBl5aytL9TVSaxeNARzk35nGx8JrO/niIM59VwgGVI5UCarhqI
+dfsS2wY3f74vSGlv8i2d1r3GT7UMM6hm9UDRqR+78KKicQ98eCVrqDylghOa1udZ
+mFaOcdlm1lJYh/rLPZynLBXjzaAqjCS/vo0zMV/+i/mOGOCcYzXCBw7oNSWSGOcX
+9jCZkDpNorgfzsuS7pl7xyUi2Lk/7LF5s+qwiT+DdQkNN+nPf0QfQBcB/cQcOM+U
+pksQbvIV7v2y2iqiQYpNp6I/PWROaKWpGAUjLevtKpxYezaJjjmtpx4y+5mQtSxh
+BZi8HUjSXA5qGtjj0eozhen9WFsweuXMQL1RmIBL8UWvXFNcH2DIZ92KnkwPcVKU
+0qF9TSkV/mMEPAXjxu03V4ByEaJiiQ1tmmT8MUJxR2DnPLDwXhLQrxC4atfNxPGH
+NNdLGFt9CEE7VSjyDs1H+sLlHEsK1Oh/ADVbHmg/iOR5ZfFyDS7vj9g6PjTB2qsQ
+Lv1qjtns+XpLkknri04PqcxEadolJPu9wfMERdjq4GVwTvoSb5H31IdcOZKoBksy
+bvSeTfpoIGXR39lDPfYWQdc1SyORg2JKYXvEUo2BVaAK6MDmhQ63nyTVxO9I6oNM
+ZUE15sTeuHmYU9MXVqjM4vviON0pTzuTSobTxtdCZljYZqoWI8yVUFiQTzwFGvCj
+kBvImf6h4G67dkLr1y8oWuEqVdVyTIUmgmdvtFhXI7M/7xtsGpOqbG53QYC73G5R
+nrNdMMLMBd+sCV+G2XFSYhlCCB2EctBqegMoN4/ZbXkC9QjFQT1Ce8B8JzxhwBOA
+tv2N8hHzXMH/gexgaIYjmweefcWMB5Mx22b0l7v5NNK8PwWoBmjYIXM3Py8MxrJ1
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8.pem
deleted file mode 100644
index 9981bba023..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Mapping To anyPolicy EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=Mapping To anyPolicy CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF01hcHBpbmcgVG8g
-YW55UG9saWN5IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQD
-EzFJbnZhbGlkIE1hcHBpbmcgVG8gYW55UG9saWN5IEVFIENlcnRpZmljYXRlIFRl
-c3Q4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1bl/gTqVbi6yVtJxnXxNx
-DlekTcCxPmcwCs7HEqTWzpbyvYxgoXfNIP7bjtabs/IK9+SG1YQpqAHt/UFImBzC
-jdgEBzfRwt2eGR4wSeGN09s2jAjT2aq9dbkF+Ib99D2DNKjlPKBbb4GeNWnNEDno
-yf4eZEPAx8P3QSsAfUqocQIDAQABo2UwYzAfBgNVHSMEGDAWgBS6gMx6LKdjWhCr
-Tj+ExFNVCmn6HTAdBgNVHQ4EFgQUm+ENjbV3/gxDFuaWw6Dwa1YRk3swDgYDVR0P
-AQH/BAQDAgTwMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQUFAAOBgQCQ
-H92kSHC9YZU7taUlRQda3eEkg775JMosyIMd1DwSzbT/wRoWU7/6BnsV99dq1Ja8
-2pZn316o7wfz6POeSg/VzNFd4HC+j84NTUMBrFt/SSdoqh1CkUXNAKbqffDzn4gN
-Sry4MX5zRGXwI3GYFol9TnNutj6HQl9Tr3iolkPufg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Mapping To anyPolicy CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICsjCCAhugAwIBAgIBNDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXTWFwcGluZyBU
-byBhbnlQb2xpY3kgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJrojWZR
-mKqz0wTzKWxK+BvdLHiNYkl7deU8v1nJqthPCd0D2ZxiM1IwaskiG9Nm+sO+91AZ
-pk/QFCW8XKa70to819onqj29QyYeO8ukMtlXuLI0pXVjyN4cWxfHH9o5IUH897/t
-hcTbFWYC1+TqZUNaPASnCw67YZejfdZZtD4VAgMBAAGjgbAwga0wHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFLqAzHosp2NaEKtOP4TE
-U1UKafodMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-IAYDVR0hAQH/BBYwFDASBgpghkgBZQMCATABBgRVHSAAMA8GA1UdEwEB/wQFMAMB
-Af8wDwYDVR0kAQH/BAUwA4ABADANBgkqhkiG9w0BAQUFAAOBgQC4HMzKV0x+spl2
-wCvBKf+ArCiSCklHEDKpj3HrJ7zIH1lqU73rZjOJQB3hsnSMYEB+ch4DQNDzOQIB
-bGspRwEeTIRjZ1u6CZ9h+kIVu2R4eyfq9mNYOvYFeY/kB/zwrMQnoeJtJ9sQ6IQi
-rwtT53uxl1gZv4pBZRIURDq8KEyoUQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Mapping To anyPolicy CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:BA:80:CC:7A:2C:A7:63:5A:10:AB:4E:3F:84:C4:53:55:0A:69:FA:1D
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 92:da:09:1f:2a:48:11:8d:5a:7b:8f:a6:74:bc:32:70:4a:03:
- 30:8b:f1:26:b4:cf:a0:9c:9d:89:84:98:71:48:4f:93:09:59:
- 08:c0:07:e4:65:bf:12:ca:49:90:3d:36:f3:31:83:3e:34:b3:
- 9a:df:d3:a4:f6:7d:cb:ee:5b:1e:cf:e0:70:25:94:0e:0e:54:
- 9c:32:4a:50:41:ea:bf:f4:57:d3:53:02:7c:c7:bc:d4:04:a9:
- 9f:36:51:04:26:6f:37:1f:62:8a:ea:f7:7b:2f:d1:24:53:17:
- de:db:e1:ce:89:00:3e:71:23:73:b2:da:af:79:f7:4a:2b:a4:
- 2a:bb
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF01hcHBpbmcgVG8gYW55UG9s
-aWN5IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBS6gMx6LKdjWhCrTj+ExFNVCmn6HTAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQCS2gkfKkgRjVp7j6Z0vDJwSgMwi/EmtM+gnJ2JhJhxSE+TCVkIwAfk
-Zb8SykmQPTbzMYM+NLOa39Ok9n3L7lsez+BwJZQODlScMkpQQeq/9FfTUwJ8x7zU
-BKmfNlEEJm83H2KK6vd7L9EkUxfe2+HOiQA+cSNzstqvefdKK6Qquw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8EE.pem
new file mode 100644
index 0000000000..7ec0a9a27e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMappingToanyPolicyTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1D F9 67 26 C4 8C DA E1 53 C3 F9 DF DC FE BC EA E0 D8 AF 13
+ friendlyName: Invalid Mapping To anyPolicy Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Mapping To anyPolicy EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=Mapping To anyPolicy CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXTWFwcGlu
+ZyBUbyBhbnlQb2xpY3kgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE6MDgGA1UEAxMxSW52YWxpZCBNYXBwaW5nIFRvIGFueVBvbGljeSBFRSBDZXJ0
+aWZpY2F0ZSBUZXN0ODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMr1
+1erPw8vN57992tE1rFW83nzG1kHn6XMLHEmZkIdJASQbO/ZReTiFot1Xi+K6PpBO
+mGbcSQ8uXLxWZVCk4fIwD6a0MU2Jmy5oHWFd4dqDmsBUroCbhiU5wrDWv49zV6ap
+PmqPeQrLsN7FV0cwrFqS6YqU7MHaBkEoRlFvT8FyvyDb2SYaMbF1Vc3GPWudBQPo
+Uq8qwpBYriAflA3P2dO4bTnr09XDZxV2FGbH6cVuKVpwErEHFYZ77ykngP9VfTQO
+dXhygSD0jWvCgTqg5jXkcdfyyT1zxbVSGusMw+lBh3wBJKo0hJWq0Qup7GQkFV09
+m0iTMj1vhbasHvBCPDUCAwEAAaNlMGMwHwYDVR0jBBgwFoAUFCztk/EeGnAVlIst
+k7SY0rcFCKwwHQYDVR0OBBYEFKLkfME6MVHySnJusYPgXpJL2uCoMA4GA1UdDwEB
+/wQEAwIE8DARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAE2j
+J+NBiXf7fiA+1jBa1NWMTi/Fkrt7h35JicUUr6GGsfmS722UHOxcnqsxm22aqu04
+HYld9m4FA6/ntPRQj1uDw26FM3r9sPXKExdF+Ohufqd7ACiiE4KXF94Be5oHk6YP
+tfbMxoNx1C6gJqAr5nqLLGxuV/NfUKH2RnvU2QDVNZ1MjlooubzTtEeORrVnLqIh
+8Qt3olTa1dYY1t+bAmea7+vyVd7aK+CXQ/iSCyVpX+oMkJGh263OLXGsniXK1A3d
+HWf5jgBRLr5aUQe4prFZ/cgM+gFe0QNe88ObgrgKHL14OJw210WKHazf1xQKErar
+Jk9IJeH/nwZq46/Nhn0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1D F9 67 26 C4 8C DA E1 53 C3 F9 DF DC FE BC EA E0 D8 AF 13
+ friendlyName: Invalid Mapping To anyPolicy Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4ECA13BB3BB90EC3
+
+SDIdiEs9qfLaXJ4j393SyXyi1O9vQdH+XanYSz8aVIMNPXL56Kz1UkiV+JBqhTVI
+C44UDsPE/Hra72K8RA9GeARFBS5SggpUm4UoefVHq/v6Utm+UAZQGLKr+W2NCLMH
+KpJPRs1iECtVZ4iyVVxtAAWZGE2kf2aEknOiVhiQnZfiR9YA/5wigmJKQJK8JrLh
+XWgTDqXtXVRI4sJjomLfVRSBy4Robmoed4o24rLY9MD2Te4v7ASDpJYGXH6oVBBf
+V5GB0vRWJ/nmNuNGLmcW2dS+gaaeFQl4+rECtsXUqT/AK+nLH1Cr2B+FN1IRBIzA
+Q7o4LsObBn6BDZyk8jpFgEkq3j4EPF3SB5zM6gFWmER9UQgaSZKSjwbbChKVAZDC
+DbKViSJ9WcyA2tQYI6rYYIkDHI3ipVcYwvg1cVzWqVvX4q68QOfesaZcOHApv3G1
+rgDdanA85hcf/2l8nGdlDBAjuPazygc1eZM2ircZtRQXFlEfqsc7vtQOg9y3no4w
+5G8C6EslaIgbncaNHdr1E8iEO6PKRsoQGmAZrodUnsXXxW3V0/XHHL5DM47Ye1UJ
+Xm8S9LUfH2F05p9YaJ2ZUlx6glE2q7SrRmALUVLWVzVRZHbFVx4cpvVEpTYANgBe
+qN6KpvjDCAxKly6GtoWuSH+HtjZaPoIi7Ksg8jnAg6VGolAenGUmdeIrMSHDLdt0
+bmJIp7o/Gx3U3deAcvyIGZzDK4A8z21HdxRu1/hLq4981wHJxHeZZPgHZToP0+PQ
+jSoSyeO7cKoBlex3xFz92y5fsf+xu8g2UR8ghYUzsrRK8jsbkQEhP8pmRgCBDkKe
+Gq5iVshIWSI9M8A8hmxwhNCAr83pEqmY4uIeQzMz8JA8fA5z7bZQ7/Kdo1MBac1D
+vGL7uO7rEijBMiL7K5Q5P8fTFG7z0tNd19OaTa/kZ38FSKa82lgZmEB7+mQoaRk+
+7JwmW39vGsKeJ9NxAZ+cBvS6ECCi1L4ze4uGRjos2X1yrjFziWdTp76Ys8MuHkWZ
+LIQhpSCVkYJBTtL9kWf4dWlBIU8LV3LdvKlHVUVxVgpFgWh68N/JSbPhL2G9NxQG
+mF/BR9NchW83nE79tOpUKv9Xz82xWphTgh1vx3pSBV21rxZtCwkE6aOzZtN1GOzf
+BlrAAzB5OE8LDm5RDSkDgVcOE5Wy3IWFn+1tbVY+TsnHExuyrBr8q/rfys50PfCc
+9mAQgXQpD+MR1MnkdTLKXi4hBbX/wlA8Jtq9nsuap2MgDPX0SfwLWeV1vKG7xnqL
+FfnG/ZYLuv1P+ia7dPdfQclay8kLLPd/fO4OAFOVAV7v4MbZHT8PCtIftGx6NkEs
+iFMiEyDC3oQBQvnUvq6PwEa7GXBfFV7gJGOrDZKiFcN7zdV+kF8LhiTYSvBL+xF1
+EN8Gz8RPFXekevqL5LQcwI2movy0uXKpzhCOKkvfLChBQQpl9gK8vPk6ZwDUMsSK
+qgTpuiKFdLZt3RSf/AwGaG6cQjHcPtg2qOgBM27fOQdt4L6v1yvW3FAkKhgM5GHt
+EvD30T+Xua1v1o0G3Y5AmoA1uU/Mshkvw1akhbmuD3HhEMri4zBcmrPd64Q4Iw66
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingCRLTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingCRLTest1EE.pem
new file mode 100644
index 0000000000..e424cc9db2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingCRLTest1EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: A3 3F 2A A0 BF 95 C5 73 EC 6E B9 44 71 6A A6 87 2B 36 17 06
+ friendlyName: Invalid Missing CRL Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Missing CRL EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=No CRL CA
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTESMBAGA1UEAxMJTm8gQ1JM
+IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYTELMAkGA1UEBhMC
+VVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMTAvBgNVBAMTKElu
+dmFsaWQgTWlzc2luZyBDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwDJ7k0JNn4/Y2C7aFezOHrjKJg7+w523p
+euAG+QWBedeSq3v7KwwmYK8B/xT4lqkMsujlYZ2VZOuClpvStmSE6/scFnoLSpjR
+Irw5ATpG3PuqclSElxMqufaxZbHo0Or/YOM3Ik6m+sP2bg+PZVzmM4EqylvF2Yfd
+BtlWSgNykgJ423auEY6eTc+bMtqD+76pBY30iBuDnEal+t+ToFP79JuY5MbbCRFG
+0ub7n1tJdJ4TIT59HBjrQhUevqtJWvP7B7RVu+aTyaCfupuqgU8DDgC9dtugV9RK
+T4obzxGqrazxH6Fc7EQ5YlhdnlOlZWPPDjjANxxtI5a6RlZws6HJAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFG6uRdP5/cyueml//bgG0kwH7AIWMB0GA1UdDgQWBBSApNzR
+MY0z53gpJM2Z2jxyk7abfDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQCnahkAQGoZS+74N7JrW2MEYonr
+q+Dj4rRjyMKBQtTfTMds6/6hkExRLIXBiqc5mlGpeP+QHggU1L+1KTlXxXxJNG1I
+dXCYV2JNRmS3rtt3taKtvZHiJmWI0anc0x04wqVffmiIECuLdjP26Kd02WlK6djp
+EVBYK9SzthVfNAiJ5FJbHcoG+wuMWmiL7V6JkLNJXlzPV5XqDfUvnjte8BDAyxYc
+uquJd1uKqX+pdCLhho4QL0QXth4lXtyyhQ1Y7b31QHI8hySnqXbrArZeuFg7o/Ed
+fOmwvmwt8Tu4YQ0Q7gdj5YLpxhthAPaNd0csdKXzfiIcMoWC3Y4L1vtszqPS
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A3 3F 2A A0 BF 95 C5 73 EC 6E B9 44 71 6A A6 87 2B 36 17 06
+ friendlyName: Invalid Missing CRL Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,ADA5D50F350C44C2
+
+/hPizfAKmJuQrbvRfUq70yiL3owIVL25akrbu/Y4MqYc+RzLjB6c8k7tC8Rf+GQQ
+9Ky6ngj6wfiRSiFYkajAWRa7tHu3kw9TommWCSFVVVqx01+c3wshMWh5EBCCG0wY
+ysWw5vfDJYWlFj51rbEOeSJrVVeNusUmHATqbk/QRXm7DeAuTd5yQosYJTGQcebg
+6e3OfTV+e7ysUd28RBva72h+fHTXmL7KzO+RiVx5IMNd9fiYl2VVYovxJLRdVyhM
+iBqs59krueWWHxp/Z2FL9lIMmH1zU2VwDwgAG13IWNSeXKox1C/XuDG4OY+rSuFE
+l20xShbrEPoZ8HyIdwyUlqkIBz83hf1sifdC5mWWEBdMzZk2/25R2mx8idZuObRC
+xRzRUTyay0UOUVSQwKJKXhha3FdYlsQGODNRnX8wsleb8Ps1ME85P79XU8ymL/X6
+IkO1blRIec9U/q5cNeUr+6GlS28Rp7SnAuLSmVY4NxeUbyQVm/eCIKRE9Da38mph
+xyfLijm6j9J2UQvJdQY0NDTHQ1djJvHpGWZ1XfVfFF2mM7ur/zr+HijUWd0+0rbd
+iyMgXiuGsN5inZn53ge2KJM3OgQBDxXy47SRb4jzOlh0xmhAYsRANQ42V2R1Sj3z
+cWHcEzzsg2eumbqGVpOKWKG8YPe8OpRkvkSfh3F6fLhySCqkr576D7pF0PD6ZL/q
+nM6f05sIpQAGnRah9opHjLIVCggXREwrZXWnIEyUb4/UYGYxs3Sj5QIEVV7j8bdm
+8wlXmoUA648KxS/PUfPjFqjBisXrSmYtDUJCmKqCJhR+F8fuiAtGqnYkOelV8BqM
+697v7jtkPbond/WDa6MN7Ga2P5fwm6qaUht0tuqb59UFBeO37n+Ayc2kXCX5CL3j
+wtXajaiYfhcP5zpr6cmot1utKZ0WHYYx0srwMC9Derof6Tryj5aWnlS6cG4JZZC7
+qoAccg6d7dweMVq2KlYdUlwzln06L9hslorPq1jx9/kIdyM52hV6w7cTPDYZAczd
+JWbUQhluWFQlvuCju8LLYsN/HgHunEC2WV1Nirj02qEPGB2xFX75jMTykcUajKlw
+A7sQg9upSuDIqPy1H3vX/csj7JGX/uz7omF8DeFL7Jf6MjxGqf6nQXGk/pjiByQy
+R/+1qxUFccLE7ike9PolA07dUChNGYZ4uvAv2e6AMUiPW0dtF4o3ic+PIpAom+/9
+krfoHpk7poD/RbvMOOLG7jDpokt5EjU6HmQMYcKRPqNXO8ISHtc5E7w0OQoDnsTH
+nyjCLiRt1QnJPM4Fu1b59DcVfWTsgwaBrgAyTBCeC2E2QV/ph7KOJ1jL9VjIUXpr
+RmEeoZARSXjOWx2oq/NQ7yT0QOLDNHgCc8VWYwEfDiyEqkHAMbWL7gb3yv8h0qly
+Jh/y+LK+CIfXHwk79CBtH4vaC2RvXIK6Kos2+J12Ww+VA4Hc7afUGcjabggijjrC
+tKE7yfHjXjYe+KeLwjWJMWZPP0T798AdtNjm9KVUXY16Uv7qAhZToDNaB0yvGCpD
+kPEeaVZVhV7PHYSk0Ph8fFGeNDKj7YKLVsFL2cdvO4xTyFYKD6+0kYlzFCFSaAC7
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1.pem
deleted file mode 100644
index 77a888caf9..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Missing basicConstraints CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcDCCAdmgAwIBAgIBFjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbTWlzc2luZyBi
-YXNpY0NvbnN0cmFpbnRzIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO
-9yKuCeu6dhjdDO1FYBjOw7a3vWSCZ6ukoQAD5724THVzb548yc2GIGKHC0mWgXiX
-fB6PBIQAwAhwCIetZaZICbOaJLAEgrfYEc2BK1uYPcnPDq3akXxh5lwFwL8N/xT9
-ajSDOeq+fWCIH4K3cgzvQFksXSMBrCLeSqRqpxg7aQIDAQABo2swaTAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQURqBdN9KpBRGTRazt
-XDHnzRcB9gEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATANBgkqhkiG9w0BAQUFAAOBgQCIvIvzmMIwJ8YV4vFP0812ct/Jsheq3QAcCH22
-0akUpHCoryoLL8cVkdCCP6lG5QD0BdEszwovHnuu6X1kPCe/85mpvlueAMAcr3Wh
-sSZA7vot2fdmAqwje/64fADpW2pI3muEixUfmNSMsjXFzGSFT2tWJ1XNfFAI9EYK
-j0nmiw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Missing basicConstraints EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Missing basicConstraints CA
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG01pc3NpbmcgYmFz
-aWNDb25zdHJhaW50cyBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MGkxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE+MDwG
-A1UEAxM1SW52YWxpZCBNaXNzaW5nIGJhc2ljQ29uc3RyYWludHMgRUUgQ2VydGlm
-aWNhdGUgVGVzdDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIu/B3NsTKFd
-3NwujgznvY/HGzG+YIVddeXJ/bIUYqj0gIh6FNebF1p5DnC4tljBvuux5UMrmGOi
-6/MoDmiVL8VyVr87z69Hx4DKUjwmHa8KOQ8L5KcklyNCiqovL+IWvl/ifcvU3tQ2
-olOq4vjYRupu8NdmpY4IZl6UQScR5P6lAgMBAAGjazBpMB8GA1UdIwQYMBaAFEag
-XTfSqQURk0Ws7Vwx580XAfYBMB0GA1UdDgQWBBT7lvAQxDdV8M61puLxGf+ZGq5u
-WDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqG
-SIb3DQEBBQUAA4GBALqhV3pig7Li1sMxfgarLLYB4xxjsbFinx7EtEDlju0sTe3j
-F7e9rh62n7fnZqZ8KSyRCikPu3r3qBCLx2TV+i31inM/GqvU2yrBGdVm9HUi2CSp
-YUePLjOyojWECk+rYNq3vVYFVKJkonzfR3533mruAKakqDJ0PQLTEx84ugv9
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Missing basicConstraints CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:46:A0:5D:37:D2:A9:05:11:93:45:AC:ED:5C:31:E7:CD:17:01:F6:01
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 94:49:47:9b:06:de:66:8d:df:13:40:35:7f:95:83:f5:1c:92:
- da:0d:33:78:99:cd:9c:34:02:32:14:17:ea:86:48:3a:9e:ba:
- c6:5a:de:0e:5b:68:0d:1e:9c:f5:07:b6:81:e3:47:fe:29:45:
- aa:c4:51:01:21:b6:70:ed:1b:28:cd:c1:81:f2:43:e7:12:00:
- 48:78:7b:6e:28:5f:71:8f:f9:56:2a:22:8f:3a:7c:8b:8b:7c:
- 8a:f4:2c:23:67:c7:b6:b4:85:02:99:d9:48:01:29:c8:6c:ad:
- be:24:a7:3a:8e:56:ea:92:4b:e4:8d:d8:9b:f7:17:b3:e9:b5:
- 87:fa
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG01pc3NpbmcgYmFzaWNDb25z
-dHJhaW50cyBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAURqBdN9KpBRGTRaztXDHnzRcB9gEwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAlElHmwbeZo3fE0A1f5WD9RyS2g0zeJnNnDQCMhQX6oZIOp66
-xlreDltoDR6c9Qe2geNH/ilFqsRRASG2cO0bKM3BgfJD5xIASHh7bihfcY/5Vioi
-jzp8i4t8ivQsI2fHtrSFApnZSAEpyGytviSnOo5W6pJL5I3Ym/cXs+m1h/o=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1EE.pem
new file mode 100644
index 0000000000..b244a1b201
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidMissingbasicConstraintsTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F5 04 22 89 16 8F 33 16 74 FC EE 68 D4 17 0A 0A 64 05 88 D6
+ friendlyName: Invalid Missing basicConstraints Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Missing basicConstraints EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Missing basicConstraints CA
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbTWlzc2lu
+ZyBiYXNpY0NvbnN0cmFpbnRzIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowbjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExPjA8BgNVBAMTNUludmFsaWQgTWlzc2luZyBiYXNpY0NvbnN0cmFpbnRz
+IEVFIENlcnRpZmljYXRlIFRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAz0Q7jVXn/KP1L4kWn3MnNkLMHv4kNcWGV8Sz2Z2VUq8WlLhFuzpFvyPh
+NXcaZ98iVRqDqvSmb25/Gf5HoyrLTFxayY0wm72Drm5VW6REQ9evIg3xJV2x/4pg
+7qHE1ikSCD1yHSgrhQvWVVbkYnnTSgVERxm81TDFMmn6nOQzuvjLr50dgcdz9tI1
+sULjP7pyk7vDuBRNhsphW+QP7iUDr02Fph7IO2nJevAZ1p+80O4lMoLLAWelO7c5
+KKyhGa2NqZOCqSsS+cUMtkhUGhEyDdlxC1maCPpsS6zfmtWasUKBn1FLLGXDzALC
+COWJwxztub3n2UVKu2bFEn6aYK9iFQIDAQABo2swaTAfBgNVHSMEGDAWgBQwVrwV
+EY1PxibGtZyhcJLS+U8NeTAdBgNVHQ4EFgQUTfAA8MgHRVCO/ShtbVSoByR2AIQw
+DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
+9w0BAQsFAAOCAQEAVnYgcBUarDoQoiuDXLPNBtPKARX91BCSAJSI4s0yP8Ba307d
+28L6BUVWzbYevwBKK1042PTO3Baz5WTc8I/cgNMUolZKfSbjrTCZ5H3MLVpH1Zdj
+zr7Y4bNppL3aGwXPjjaDHHE6F3h4ukFZaoX9fTr1OTxcyOmz96/hLJ3NbHmRPHPv
+pA1y5yepi3RDltyIMQsXIGPIofZ19LQ/+hCjYuh01wrd2r4DEQYDmyEEDMXRaeFy
+LSZqGQBhvOwcrfX6iz2cIz8YnbfU/cte5C2Id7V7zW5GZP4oCgjHsANbe+hGVbsR
+AUSJ4G96MY5zlwVFYdpLldKm2BywOGs+CU+uxQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F5 04 22 89 16 8F 33 16 74 FC EE 68 D4 17 0A 0A 64 05 88 D6
+ friendlyName: Invalid Missing basicConstraints Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FBCC7DE9B3E67417
+
+ddz83O0BO0HXwyO0stvbC3Vgu0Xdmk958NkNArfvUA6xAU11fif4N+53XHRy5azv
+4dcEBgdx1cMq2FH0Fsq3NjNKDALJV6jCewzHkPTOgqbJhkwbAZxpVDjnAf8j1cyK
+SV7f7aPg33n9/If8lOao3ZSIYZoKaiOY3oLxchNHNWLZoH83hocKgtx6rcZxOpEf
+Q4ySjllF+jn+jBMTpURJ+WBTwSebP+spHe3vi9jnKxpXhZq42GdMeFLa7RmFCmXZ
+yfgI9VJY/YFtCqivKmWRlAvTA7MTPGnGr7j1T7jAzg+wfgiuAtBssVAKmXFwSrYz
+r/TW6AxvVVj0sgovGPuxrpdSmHdThlm42UVUfw4HaSLjYBK3BD5vFPVaLfLwwYgr
+oN8/mOslZlUkPVr4JV+uAzpVniY5d98YAUSnYn7ASrH6KGrQgbPQFUv6IWY9nS9r
+n5stGf15Ncbx/NnnqsuuIglSHnYQlhXnoBdJGvqMiXAL/QPxxAMNJAsTA22Je55f
+M9xmPxOtszKXAiDB66bhVN1msfDC6i896vLgwsggdyPH3ljJbVHNh+YAmmVtrGgJ
+5sfoPCI8anpBf+LzIzV1rtmV2uQT9aR8cQ4nzkFViS/UKI9BfZPSlXeIkZbjb0fQ
+nwJXYn4xAXhXdV6B33zX2Ih6b/5aXVrdZ6AcZDtSfTwSEEdLgHmQaZAMX8IsGI+y
+gzGnbQTYk4jMyL/C0Z9ikmd/DOGrNCepM3ui9eXxal74qiDla4rVZGXMCghyNt7O
+Ak8TxTogNmcQUNKFWCT5eNCSq5Ewljq+ivdSWbw2vE42JFSWmXSDQycWyi2/bDcr
+0qEksyaJYgbcff+KON6zomidVZOeNl7vHjUHSAzdzN4uCQ1f/EgQsJy2kwUg+Q4Y
+/zM0wTLkl0gELwYi8IhpOkcNtBX8+IE9fG0wg3mzcD9iadOEymBfgGpxRk8MvGyF
+46LJRWZv9UtuuuJRnGGu7czCMYAMJfV+gzm47B6Kw21OHREoEZXtVZaJnUL4AIyD
+cWfTPZOOrUNgKlNIgxNGsHxYK9ATpdDCAh4bV9W7e4WdcBFDgI7e94bQhC2RrK4w
+xN9b1+inE8rlANVn2brIBYuFZoIHeVz0qRBAgNOWo/94puFcafWhyZ4uGZ4wS/a4
+slmsz/T5+sOArZxgrlcMdhtPntonDUZKv7uEvfNl78L8G6rkw6Y7ePDv/1723UuO
+p5SigZc0BFse3wJwvrLKkka/qX4ZXXBm96+atfIappYR4GNpGLKjRyThFp9MQ5AR
+u4be4qNfx2fTWJT+vODocWS0dx9QFZxP9QZan1/hP94Xl1wIMcFgDpATY7yZXfyI
+M0a2baduud6dzjnJ0V0pBYMHG/PmfeEWJU/xCCgHq8Eemxq28HXmNjXSAjOAyQWk
+gl8WRUh0MZm6F/hSR2r4IPbjGNbBVvmhYmXYw0iPMpimMIapI01eVHq8QvCfjjFW
+KTVDcHW/XgdX96k6fO9wVfpHhgGhWj6dPYvFQ+RxpvcyyHzZgaEYRC0mTFY++UW6
+KJk4OrJsoEbPA01cvfflIZNAIaz6HJDiUSUKCanbPbXT3Ca50evkPHMGkGpBNVXL
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingEETest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingEETest1.pem
deleted file mode 100644
index ce0428ec3b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingEETest1.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Name Chaining EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Good CA Root
------BEGIN CERTIFICATE-----
-MIICfzCCAeigAwIBAgIBCTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDEdvb2QgQ0EgUm9v
-dDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEzMDEGA1UEAxMqSW52YWxpZCBO
-YW1lIENoYWluaW5nIEVFIENlcnRpZmljYXRlIFRlc3QxMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCtoV9f+SA4KyB9i+bRylcLprvUHWg6W/anXTtNepZjeYRI
-h45BCVfF9mYQIoBvqYkSOdB64I/qUShwGf3kj75YiGotm1AzP/e8A1dIyvdxVT75
-vZwCWaOjqX5wEyaGnXS2u1NDzvZ/5JBtwo1KumaVAd9bLw2nhHAwbJ65Hx1eWwID
-AQABo2swaTAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAdBgNVHQ4E
-FgQU0QFCXwgNnxwQuYUlKF7ehgYiFvYwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQB8cokOobcm6ZNTDk59
-Ieo9rWzeCUeh8ku0vO2bp0hyVadPHfCvXRRFlWZ6WKMTkBXOs/i5gHEtEGB9cLDO
-kmOOHijG06pi9KyYqh54As2hG8wKngUEyOZsIkKK6JfdMx9besNZ5lQlSK3SZpV4
-wTIx6poqzlbJx24yad7rPgiUxg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2.pem
deleted file mode 100644
index dd9f0a5d86..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2.pem
+++ /dev/null
@@ -1,113 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=Organizational Unit Name 1/OU=Organizational Unit Name 2/CN=Name Ordering CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICwTCCAiqgAwIBAgIBBjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGOMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAsTGk9yZ2FuaXph
-dGlvbmFsIFVuaXQgTmFtZSAxMSMwIQYDVQQLExpPcmdhbml6YXRpb25hbCBVbml0
-IE5hbWUgMjEZMBcGA1UEAxMQTmFtZSBPcmRlcmluZyBDQTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAz4GBJOnsdl/i9wT8fK6n4zN5AHkLGLTaV9MLbBL5heti
-HmMEj4t80NsHynN8WrNyxjxjeDoAnlUixCHAT6totgzgeWKumN7Pt48lWyP7K9eV
-j0mJ/e0X8EYCrm1idgjBevSpFpC8sT0m7Lgo60wWBrYqKBE2OW2oLqjK2a9itJkC
-AwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0O
-BBYEFP/4JkT0Lojo+NeoS4SRoshoYlphMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAE
-EDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUF
-AAOBgQCrzt7jsc3zpys78suxiiHSl9hYrO0L3UJE4TYhMKsTdu2r1KStNCY1MA05
-8U2gLxTSvnibuRTn81AHALvjm5bd3oiKFRr3ISzo9SkBx6wXO7x23f26giO4h6WR
-Yjce1wWutjpvkyXJWxLqKD5eE2PVqwjujs3eiNAV0KkiQTqZkQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Name Chaining Order EE Certificate Test2
-issuer=/C=US/O=Test Certificates/OU=Organizational Unit Name 2/OU=Organizational Unit Name 1/CN=Name Ordering CA
------BEGIN CERTIFICATE-----
-MIIC1DCCAj2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSMwIQYDVQQLExpPcmdhbml6YXRp
-b25hbCBVbml0IE5hbWUgMjEjMCEGA1UECxMaT3JnYW5pemF0aW9uYWwgVW5pdCBO
-YW1lIDExGTAXBgNVBAMTEE5hbWUgT3JkZXJpbmcgQ0EwHhcNMDEwNDE5MTQ1NzIw
-WhcNMTEwNDE5MTQ1NzIwWjBkMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxOTA3BgNVBAMTMEludmFsaWQgTmFtZSBDaGFpbmluZyBPcmRl
-ciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEAlIUiHjq7IwwwfDgHAnDwX3nPnYsaZ6Bu8w8lZNS/15MDdOmQg71tVoCIC0he
-PJBMDiqwuUQ3pbgsavDR26tQnAXGzmJllHIFry4XfdUozW3Du9KUR4eFHDkgiQCj
-IXj4VSgaMAXyDSGO8tQpZvweKQLreeur5220Pf3K7zabhcMCAwEAAaNrMGkwHwYD
-VR0jBBgwFoAU//gmRPQuiOj416hLhJGiyGhiWmEwHQYDVR0OBBYEFEu0FDAWAxWm
-n1pTTcqqIcZ0G7JJMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFl
-AwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAHrnqIOietTCGSRZ38iulDWfnU8JraF8Z
-x0MJGiOWHh5iM21Rfwux8XyoJ022fncuDoZAsUjriRwBn3u0faPPFouOEEVMglWU
-woUFoMYymfDUYmA+kavP7A4gRhSfhi4JJJHdb1AbnNkHbMfIBRSz48wsphGJEyk/
-NE5gmcum3Bg=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=Organizational Unit Name 1/OU=Organizational Unit Name 2/CN=Name Ordering CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FF:F8:26:44:F4:2E:88:E8:F8:D7:A8:4B:84:91:A2:C8:68:62:5A:61
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- b4:c4:1d:56:f0:e3:a4:27:bc:09:13:d4:99:6e:6a:94:5c:0a:
- 5e:33:09:0a:a0:6c:df:0f:3d:a5:03:15:e8:da:cd:53:10:e0:
- 26:82:d4:82:34:2e:75:62:f0:8d:a5:b0:17:ba:77:e5:1c:b2:
- ca:d4:71:78:2c:fb:3c:cb:51:58:4f:1f:b8:90:22:7e:60:c1:
- 60:03:64:04:58:60:3d:a8:36:c4:37:6e:b4:c1:28:0c:4d:16:
- 89:5e:31:4b:1a:7d:4d:33:35:8d:0b:92:38:90:f2:70:e1:f4:
- c6:14:7e:fd:3b:9c:c2:d7:da:8f:ce:1f:6d:36:3b:ce:5e:28:
- 1b:fb
------BEGIN X509 CRL-----
-MIIBiDCB8gIBATANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSMwIQYDVQQLExpPcmdhbml6YXRpb25hbCBV
-bml0IE5hbWUgMTEjMCEGA1UECxMaT3JnYW5pemF0aW9uYWwgVW5pdCBOYW1lIDIx
-GTAXBgNVBAMTEE5hbWUgT3JkZXJpbmcgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQx
-OTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFP/4JkT0Lojo+NeoS4SRoshoYlphMAoG
-A1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBALTEHVbw46QnvAkT1JluapRcCl4z
-CQqgbN8PPaUDFejazVMQ4CaC1II0LnVi8I2lsBe6d+UcssrUcXgs+zzLUVhPH7iQ
-In5gwWADZARYYD2oNsQ3brTBKAxNFoleMUsafU0zNY0LkjiQ8nDh9MYUfv07nMLX
-2o/OH202O85eKBv7
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2EE.pem
new file mode 100644
index 0000000000..6cbfdc3a6a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingOrderTest2EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: D2 C7 3A EE 21 D6 E3 2F 8C 6A 2A BC 1A FF A1 9B 04 2E 74 92
+ friendlyName: Invalid Name Chaining Order Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Name Chaining Order EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/OU=Organizational Unit Name 2/OU=Organizational Unit Name 1/CN=Name Ordering CA
+-----BEGIN CERTIFICATE-----
+MIID4zCCAsugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBkzELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAsTGk9yZ2Fu
+aXphdGlvbmFsIFVuaXQgTmFtZSAyMSMwIQYDVQQLExpPcmdhbml6YXRpb25hbCBV
+bml0IE5hbWUgMTEZMBcGA1UEAxMQTmFtZSBPcmRlcmluZyBDQTAeFw0xMDAxMDEw
+ODMwMDBaFw0zMDEyMzEwODMwMDBaMGkxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZU
+ZXN0IENlcnRpZmljYXRlcyAyMDExMTkwNwYDVQQDEzBJbnZhbGlkIE5hbWUgQ2hh
+aW5pbmcgT3JkZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDIwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCmGHtkF4itTUq3AQnzZatlEBh9xeYcGGHKW4YG71VW
+tuN7bK7l/LNJ2rANrU4d3FvjcjS/uz1mInuC8Jmc83z4O6E07zDERh3vJMuMYZRM
+/3Gq/b5MfGc2SSPiE0x3I8K7IVOjwa2GtYAKm7W3nEJ80//fkdRbzu9WYXLpKGfx
+ffEZq4j8kBwmNGYLO2eyOmIKLeY/UdnzN+IV/wy9u4CvNQEoagLCXsaAsLJZWPeO
+e+92n90GVdAdKB/Ml9PMTBfDh0R1jrmOFAEOcJfIYGpfj0tFIsAZ1AdcDNPXSx4s
+A0cLfSG0xuJu6iBxHHIsCRW2Q2cK8yo2aIq7FNNE8bvPAgMBAAGjazBpMB8GA1Ud
+IwQYMBaAFL9Ki4GbTYwUMYxb6czdL+h5ElFQMB0GA1UdDgQWBBRXIRom3xYohMEv
+pN0iRtvORdgoWDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMC
+ATABMA0GCSqGSIb3DQEBCwUAA4IBAQAynecH6qf01AWM0adG9SZ3BQ5N/oBfcu7e
+WjwU0dPuMZP5O3+Ak0x7lt9F4QRwmcoyHsB7AZgGMNu5xWE3dpebr4mF09RP0+pa
+T0lli8Vi5QMUCaqYkbXOfchl/A9k2py5H5xrZ0OJZrZonmAGZTMmSuAhY1xu6scW
+gs6X2CSnU8siNg9Zcd7jqbfHUWSLvz4k9N7UzTqT7Pzwof1vaTPqcggDGUC/jQV3
+v6BgnIcxxHjRL4VSg4Z/fMh4hwXQlEFZGHoyBzzYNhYPnpgpxU/64cVHbOLNC6X0
+sUVsT9JfCt/kFAPOoWnBOifSzjeqVXmteVsb/9SP4wF/f4gBmJjg
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D2 C7 3A EE 21 D6 E3 2F 8C 6A 2A BC 1A FF A1 9B 04 2E 74 92
+ friendlyName: Invalid Name Chaining Order Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4EBB2B43D79854E2
+
+M4O8H3FXV/0Q8oJmUXqDk60NUbwnBWNKvGM2twA2XZU1rEodmvWWlwo0mmH+j8rX
++A0itJomhWox8Q88Sdi56G8PhZfBk2ocPPAIDrG2z4EFqbjCNATqJlIJmMyukzbl
+B6tYDt3Tx/vWdYRZSFyNPtn4GTuY+KIGTNlyf2F1hBhbSU4MKPoEAgF0JLRvKj5E
+tZIZO+EHfHctq6cTcqLdqBhP0bS70UqqqlvZ/232SwpPmaXWvMYjnqMo9W3neBID
+XIEP5mF4vmaTLoVcH2hoRM5qvh5DDSYfp5StfFcN0R6d5bl5v//bP+1tu79kLr4W
+HPvXQcApsUrNUgmtGNUiqM/uwEdlgYiyjN+yQpSrc7I5lT+5nBYWfJ4fsUD/K5Nb
+2/rECornDiP53DJ5daM26Q4P/mpNCHZQzBXCFb84aSSLtUvijvOtUxt4Ej2rGtHb
+t8F5ucVb9JmU7CkP9a5uy/t43z/NPxVqqgxltlb3Qh+4Pky8xUd9j24578KevBUd
+Ufi0kErFk+1ShcYBVab1QcQh4zeuq0oPWmfgyWjWZ3KyKwdMDo613YA41MgoCvbh
+OtZmi52rtoFJ/dIrYp7ls8o3L9H7UZDugRuSQmDNsFYN7+xSSb/6Tgzq1vQIo5CY
+g5At1yRtiirZoKPA4NlrCtXTVe4hAdGRQOKC2uSmZAC3pbES03lCxtTsAQncxBfL
+Z3eeR/n57waMKPykDwrIzIvbxebA7obPfpX2Pqapt/WGRbseX4/JPDYQVM/6vLfA
+DyTwC16eMO2XUIAMJ3ThBmRCzz/2cMxsMIVMGEZKFOSmcvL6FvqCtve9/vEUxCs1
+BbUWetauDkZypEPEHWPVYCGl7aMOG2SmeeUECx2xoTCCPC2gp03L2LlS4STvgKig
+Nwe+A7WwTVQlxUq+x2BXJEcU3lZh+qemj/b6bcomvkuszWyiiLh1yUSERdTZDUSC
+oYyasTIlDpERQGyyAcn3vqSKx3gdcOqX/bl8o8yR/EdUncAde5KMKegpBZlxbF5V
+TkXHeOUBJotq7qMjcxBbT4+YKwmBO6QwK79bwpuFuzBswCAquVPsg/uRylT78Qpz
+GRit5SxH+S4KkFxGAmPAzQLILGpS35qxVrFBv47MzWbxBOakFpFvBWujWC2eBVfq
+y1YnF5NU1++kIRFORX05sq6aDdeIhcA/OnCZESQKp92Nud2Br8wHHHpbDr9sF9tY
+17qjulQQ75JXuGm0CEp+wwud3Lfc++IlMRI8bUSn8xGe06bZng1mK3kdHyK2tkgM
++4pljAh3JVzfv2q2sB4ZAv7omkBFemfoeiqrxF+8jpOq961v+nySeFYsHV64LRyQ
+hoISt1GrdsCL59/dd7PX/3YYqUGIsKSdzxJVPlds+Gn7uku0jPSUgCF0RfVtri7t
+cpXGiz7irjZV4RDkvBKfM4NQpIKLGW/Hf1NnUM11Yc8aEhzaUgw6NwqB98CBTaUg
+8QhczEGBSQhzVBuEINKwbopB91UwsmdHQXhth75e2+miV+T15JBievUfS2LFC1jK
+qhBPfRfWK4I9JMzAiI3lN6sL07O/z74c9coci28MKLg0iSEtCw7H3//MdHsRLWek
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingTest1EE.pem
new file mode 100644
index 0000000000..97ff96bc49
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNameChainingTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 7D 6D BF 10 BB 59 DF EC 2A 3E D7 D5 26 AE CF 0A B3 5A 21 F5
+ friendlyName: Invalid Name Chaining Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Name Chaining EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA Root
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIBCTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMR29vZCBD
+QSBSb290MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMzAxBgNVBAMT
+KkludmFsaWQgTmFtZSBDaGFpbmluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL+nEW5gQmCvT4PQ4bfEwb8YmHX2
+bhQjlGRTHO894s1c8ntn8sOGipmZujpyWKEnuLYYXnrx/8d6EaQ5iHWc2STa5xO2
+/FYakp8YF7+wGIrvAKI2gXIaIFzFC6BBtZiDBb9esrLPA3tiu6u5F9WBsGWuA1TQ
+jKqaTll9i5WvnXY8Fq4JbfHOeh9SCJKnyLtY/o6QqfJu4IvGIy3SVMUOpy35ZR6O
+Hdy4JXBISnOe44NDd27PQNnkb7VlcvspL873wQSp5YJKW5tvoPMtCGegEssZIGGN
+lN9bNTzeXAB+BfwtYoqP0Ej769uC6863UgGeWztLxe5YlvyS7CXaMmNdyosCAwEA
+AaNrMGkwHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2lEHIUUfWvOskwHQYDVR0OBBYE
+FBrADjt6tfm3fhTgKkOCvTN+XnXkMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAHmYLicHjD0aYoBwgy4J
+fY9KHQVyP3enwjKFrzxt3lLh0+hvUeJG49oxt3lRPjU5d7GJYSzB9hmbECnD8hYf
+/NVRIa6UnLTK/blp3yc0fgYrZSFgzU77f6i51hxScIwprI/rNKUKjwYwPBQ6XZoS
+Lb5nZkbFoSaPjorD7/rTBp1A0vPt9QNn8wBph59HSKyUnHm256Y5kv67Knkt5W11
+tazp3HAc2nsE21MClKg4S4IHQYCva6p3KhViH5Wntu0AaG6Cl3eVbMDe+rzu2i7a
+SsP+m1IhK/geXvUOHGkKQd0ESsNaHakpy5mQXpYbxxpem1NCcsbPPlipMa0AN5p/
+ksU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7D 6D BF 10 BB 59 DF EC 2A 3E D7 D5 26 AE CF 0A B3 5A 21 F5
+ friendlyName: Invalid Name Chaining Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D8417684F15C42FF
+
+vKv6b2ZRAwVHf3IhthcuPQrJKx3OAjv8c+lHRnmJfHrFJkUf1am4rrCc05dszvUF
+TjTR92O3UYb41SmqEJhgidYEcM1I8ktzt5It1pItk/ZHlnrJ30qoWmtYx7GGI6En
+fXsV4tuL7jEvgKlkrYztkaUCpbauktbKcgLCeZM0YQ1WTHsDFK3KTGnz+a7Y0Wvs
+sl7UtwwjaiGLzJBF3AxKIDwGatxAxZaSUR5+9/17pLJ9Aw4irQUlERtjwKcs2LdS
+EZDbgbfPMqXOmZoZO1zCD+ZfyUM3BNOfXs9S7DqzHYjW0EeOmQiOLOWDApUPpSwl
+Ywp/hr/8DCv7POi0uiAO3xK+DNRMKHtig33+d3xU4YkEw8yZDmesgByeEEF8KlzW
+lWasO6kimeIBSmhccj7E2bu1+FEg6x3m5AJkVUxOs5hj+D5zOuihofhatD3aCJ4G
+jdRZenNZAre4l/5rKHsndQVsKOOFjVhMBP7Id+wv//eRez+OHS1yxlRzunm0O05T
+1a+jypMOV8v9lb/UYTx3CRsEtXJeqB6tObGZP/BcLDw4e3qhrEZ8wj4ys8J6Gk1q
+czlYliZzVEc6qCCnIRMf4q2jMSb++klUAuWO9ieU9uD5ms2CYyKDM2b+Swky852z
+PBh9b8/pKidwhXc5xSGxEP2lDjVHajBhlzloPpmTz31bACS1RMsYnmskU6PAFuWY
+sUVObgF3C0hbjCCZlubAqEgmfAJTfsta5ILZ9t3yn+ucS05fniAXQGPZ2dTg5zh+
+r86+Bz7h7ZVEF5aQIx4nYouJsW6vUYNBb6FV0ej7n1QbS25d9BtIlicncKaGNIis
+OIXYNICAD267B2Y0+7/NJTjO6LZwE2sFAZM5k/5fjK28DiR+Z7TqZxzcbMurTguZ
+FmbKunAe+wBaaN3cunbi33hwIMIVNuFfRYiYNnPvoLpIzm4zfxpDXfVNEqpWqIuN
+J0Aj+dq95RFo7cHiwp9wXAwkM36rMK9I0ahutISvEWIDDyw7qk9E9ivUHcMk5YT4
+Mn+IVromU0cXcM6sp1pxX8sDeu5M72nw4NDSvEvHtj0fIxHvzhlwsBy9US2yEAsK
+SUxlQsDnkDJrY5G+yEt7MkuibJBPgR4CYQKoq/GIGPyjB86TQqAeRTV4OTHE3xkY
+t4CuqoKOwzy1ieFZtgW67n6qpMsD0tPNYk4zWkIDM58yOpZ77PdMclSuUjffHAKm
+v5SAFXoAB2n/ld+k9j3cOsuBKvrlRZNADZmgeYM9ttNDM3n6pyPi2+yyc4RqfEfk
+CMckhOCI6OL8Rkl8UvPyo50+kYzBNsrEUDgtgXh6zTNzE+0KCoMcvgW/dRjjGJwQ
++VEKwPOSTXMQJAKx6g8qjOoM76gZrr10geiHhalicn6a16gaa8E2or3DlgXUV9ZG
+Mac3Esvn5x/gnljjLnkaNzf0ehfe/blTlaCeqJjLv7j+ZD+zt0tL5mfBmkS7zaY4
+3p9AvHVaLB/wFT2z6BCxBAm0hAu3Cxd54NhKrYg6aI5hKiJ8DMROCadRsc6ydM6h
+84WRHdKOI7J3jkTVDyKG/1Zug7IgHkv6nzC6xvpwMYIHJttUoz2F0g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15.pem
deleted file mode 100644
index 9310adbf42..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15.pem
+++ /dev/null
@@ -1,114 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Negative Serial Number CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfzCCAeigAwIBAgIBETANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZTmVnYXRpdmUg
-U2VyaWFsIE51bWJlciBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw5yD
-rVmP3dVETqSrKKVXvXWAnpc5K5Xh6mhHBvy/YpoERigE1MP8A/6eE3mY6OnMJVAh
-QJRWniYBrIDg5zR873cTAbn1O7MwSfs3LLxEO81iAf2k4nFFxAGtQp5AUwx0cQVK
-8oMVty8BEcAkazVA87HQgpycQySqDLmklHNqkncCAwEAAaN8MHowHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJCMpyNNS/fqobISh7nA
-0w4zWMuCMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBYz9xXPhMcniA6W0RG
-0A59JbhJJpAZmnLBusWQjWYIZsVit1M1OXc/zDGAP/ik3blednL+t+wbdJc1qg9m
-4bgoXS14lg+6IGMF2VWcoKkDJDIHpkVrdQc9WGNm0qqPyHGW0ggbi5VrBv1potkF
-xBtl1WkY3ZTLuI71pJ15ebGZ/A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Negative Serial Number EE Certificate Test15
-issuer=/C=US/O=Test Certificates/CN=Negative Serial Number CA
------BEGIN CERTIFICATE-----
-MIICljCCAf+gAwIBAgIB/zANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGU5lZ2F0aXZlIFNl
-cmlhbCBOdW1iZXIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBo
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPTA7BgNV
-BAMTNEludmFsaWQgTmVnYXRpdmUgU2VyaWFsIE51bWJlciBFRSBDZXJ0aWZpY2F0
-ZSBUZXN0MTUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANKczL4/N4jrniwj
-6tO7tR683qVrEG+1DB4XcrWL4wENZS5O2qkppGZD7cOXkGuOemheT0QGmaEtQjOa
-yRVw86jvq4n3iQdSEvRb6C2GtYQ7hFASTBsQn4qKbcldkhv+XQAzLMc65GcFv0l6
-n0xR1miZq8E0mDxBLg9J5iv6abyHAgMBAAGjazBpMB8GA1UdIwQYMBaAFJCMpyNN
-S/fqobISh7nA0w4zWMuCMB0GA1UdDgQWBBR1iOR4fH+ykQ1KqxHgeC1Wl2TuQzAO
-BgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3
-DQEBBQUAA4GBAAAfyUd30ByRjggXgiu4vNE7KBbaY6fbiYYugGriPx/HPPIJM3M9
-3W2m85AhLW9Qt/dpaXQGeICkDfrLrpTCV8MWnedoVwQMBla8v5QNs4pUdkTXuV7R
-9LZqxgeDvUTEadGrNLjZ4WumiFApRA+DRjJE0LsnS58wWtklsYDoHJtH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Negative Serial Number CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:90:8C:A7:23:4D:4B:F7:EA:A1:B2:12:87:B9:C0:D3:0E:33:58:CB:82
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: -01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 7d:55:77:de:74:f8:ae:25:02:35:ad:53:74:92:6f:89:f9:ed:
- b3:4c:bf:a7:70:b1:0e:20:4a:c3:03:7f:a9:99:01:5b:5a:a0:
- 67:df:cd:74:08:d6:80:2d:ca:f7:c0:be:9e:68:35:d3:79:89:
- 45:a7:6e:f2:75:86:e5:28:d0:00:2c:96:14:03:96:eb:75:d0:
- fa:a7:78:f8:50:e7:70:6b:cc:1a:9d:8a:30:1e:c5:5d:22:a9:
- ef:dd:07:48:85:87:d6:2f:15:02:d0:07:81:2c:bf:fa:c6:ce:
- 49:03:44:08:37:f3:f3:79:b1:61:ab:c7:f9:21:29:3f:4f:cb:
- 36:c0
------BEGIN X509 CRL-----
-MIIBajCB1AIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGU5lZ2F0aXZlIFNlcmlhbCBO
-dW1iZXIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgH/Fw0w
-MTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFJCMpyNN
-S/fqobISh7nA0w4zWMuCMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAH1V
-d950+K4lAjWtU3SSb4n57bNMv6dwsQ4gSsMDf6mZAVtaoGffzXQI1oAtyvfAvp5o
-NdN5iUWnbvJ1huUo0AAslhQDlut10PqnePhQ53BrzBqdijAexV0iqe/dB0iFh9Yv
-FQLQB4Esv/rGzkkDRAg38/N5sWGrx/khKT9PyzbA
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15EE.pem
new file mode 100644
index 0000000000..7479b46674
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidNegativeSerialNumberTest15EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 17 72 29 99 FA BE 47 81 E4 B1 01 CE DF FF 1E 8F 24 20 D0 99
+ friendlyName: Invalid Negative Serial Number Test15 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Negative Serial Number EE Certificate Test15
+issuer=/C=US/O=Test Certificates 2011/CN=Negative Serial Number CA
+-----BEGIN CERTIFICATE-----
+MIIDpTCCAo2gAwIBAgIB/zANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZTmVnYXRp
+dmUgU2VyaWFsIE51bWJlciBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMG0xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMT0wOwYDVQQDEzRJbnZhbGlkIE5lZ2F0aXZlIFNlcmlhbCBOdW1iZXIgRUUg
+Q2VydGlmaWNhdGUgVGVzdDE1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA62KPWxrURH3uoUly4l86zjX1hpi4DnpB94DYzQ9LSGGpGznlFDt+RyvkNjRB
+UomO6ZpzUw05LdrHNwEKY/Lt8l23PrRH6rUQW+epbYq8F7xXb2UMlmgjRw+IVY7+
+sVnLKk4bWzyCOOU4QXY1MZnoaOJGnZauWePVvA932WDny1MEV6THpnb3TUR4GVoY
+wP1rTv8knj+kMr822fT/QixZiAm6Jimm7ja0Nlj/FpXx/9Gv/LP8LMMnQ2esKJUM
+iLBZHPNtZhHcGKzVzqxAhrzRTZUddXmBS24k2doY1iV1KypyxgG7WBFX0MfLlqCK
+jC+9IpoPA6manH6k3R1UJfZ0KwIDAQABo2swaTAfBgNVHSMEGDAWgBRi5C41xg/F
+6JHQC8GN3rav2ojZPzAdBgNVHQ4EFgQUkfQx97LimEmUaVujcr+gLY2rJqkwDgYD
+VR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0B
+AQsFAAOCAQEASWqVVZv1Mi0Wor1uUCsSnDwNn1qBhzHRgCJ7RvTS5I/uKey6YqtG
+ozvw22AfDPOa43ltwuCuOeVX0rG1BpC57ZzHEJgQcksysR6iZ/uY/vN0tD4chgHp
+yi+8sTayGRPBqrpANbgTD2vzNULrcHo/nZIBiUAWs5I/38iWMAnRvuskzwEhAZcJ
+xU3Z7laFlU5TQGoTMxLeyMzKbJRJWW098aYscKWhG8bEy8CIRsXiuF+BcrFqqzTb
+jZA9n2Yn6S805yMK+TuDWDh+VzPwHRZliww4+ROGHT7LgRdxeN9ZlKx+XqJ1yvVo
+OSsRBKUwZyf/8dm9ItkC5J6XM6dfreX/bg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 17 72 29 99 FA BE 47 81 E4 B1 01 CE DF FF 1E 8F 24 20 D0 99
+ friendlyName: Invalid Negative Serial Number Test15 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,89AF3DBDD02217E9
+
+uv4c65SWYATqAOZuPg0VAf2OWnVv4nfLYiMSqgjc5mHTtRKWvXrA6uP8otgl3iQb
+PmyXN/C2eFwFfzM+JU2VnREj7Y40YVLMPKARJ/sbY/SfUhZOVsI/IuKWk/o3EiBV
+LDulYfkt+9yPOdvJRivNx96Tr6+6ItdMGiNFfouZMIA8N6GI8PyWcygI+XQU43Bx
+hVdoQsD/yrpSKzNUVqXEYbPcK34D4W7wVMkxToQHwKe7N+GDFMQbc+yqC+do97of
+lK5Ps8dv7U1SAhXb+bAxnwvRqQ20+KKlXb4FGlS56rK7ksKrGpr5lTAVbDGrCu1K
+Ib6rmdLwDM6lz+it3JM4hwlDg5s3v0uND3BIBkVzIi5b71VRNBsEoXVt96LsTCoi
+pwW7cDZm7pG2uDH/jVrpEtqfDskRWuFz5KwB4uP3Ne9g4/uAOj8QIDkmqH4gxep6
+XEmTaVEQ1kDAn5NoURExr8Z6uW5EsVpfKeXiWg5AlnqrUKoCLXxf7+bYxzd8KbF9
+QixAGeUy2Hk4l39afPcAOg5/av/UZL6S8YHMWZ5H6ks8bPnLPoYMBtwegxFRMvXP
+QS/z83bhAkw2s1DKlU4jkBM2McFAJJgl3D5G10Ps8BNNERpZr9pdiKQOPXz1RIAp
+bhaYE4EvYWV8yV1pODnYH8Y0YN9RaG1L1D9PuGBpZAtsVc/kcMz0JLzNPzp3LYbb
+aoJzoXj3VdrqdgefYmj5FbjgdIl887ZcAnm+3t1MydwDZQDtk6WluSw13/Pm8nM1
+O/bRCUadOyCSIfUHP54AABGlpto4wH8pPB2OOSe+2oEHqDq2qBRZ4mH5gDquPSPo
+TdQTgQVltNiAE9H2P3wEOob0xk8uxZgq+tR7ZYrsevBkOMXL+egimccgqndEh0pn
+bg7j1TPC/6dj5UVYpvEhcvZ1oEWEPMcMxm6Tmvr2PtcfT2Z1M5+jGYVRQVknWL6R
+ELJMLeoZ8QchYnHBg7IlRaLyKt5OAl3PpAjrQOtnXdjmEy51C2ujrpTyelZ8q9lh
+KKzGg3N0wtT7Bwg97fyYQP37wHDi7fuyPtbdF8T4JnCZxeCXgNyXUOZ0NbEUgMVC
+tC7Azst1YdtyR1ErUirsu9kAbr91KWqF9dj49wgzzuoiOsuxr3O7WykzuGf4iBIe
+WSGoucPvyStZc0ZTDtJiLsqYE52VXAjJmGarh7i64bP2v2v/ssMEKY0WNPiX4Wtb
+955ippwJsI2b+MEr1BpisujKkzoreRLAT7Tnx9tz5Z7R12iNKP4w0uhPVwZDUHBT
+qz+GB5sukQMCzhSMXhbEkHZvQhZNVp4Vkn2E6CYi0LvLLGDF+Q7docAoo5ciw95Y
+tjffPgYVSaHSMg4ndhgGxFIxJMci6IbZF0j1Mmf6A8UQET05gr6trD/yj82irR/i
+Quyj4ZkV3Hjb0K7JXS5KCxGfYZHvN7y27s5712dhuO+fIr19VUc+erlMVbcEXGlg
+ligwtLjZDp74ZA7Vbi3HyRLlhHDN9bGQcRIL7CiJCC/9Bm1B3PRPZ1q8x2Bpakg4
+l3WIs6epQEaYWO7IrgHBeS2G/M34gl3jwV+DdaVSMU2Z+eOK6LOlQk/xKvFAoWFu
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11.pem
deleted file mode 100644
index 43f4c11eeb..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Old CRL nextUpdate CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBDjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVT2xkIENSTCBu
-ZXh0VXBkYXRlIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3mWvvYS5A
-sFNH3PbxcSFtUQ/3TzWlO4y6wINHN6Ypk9Okpx3uHSwBpkQ1N0htmUhGQYFyhzBx
-ATrb4vlB4KzylhOwfX0F4cYko464NaCZNL7OzwjzOCgZ8097o6RD+Z2vsM0GmOeD
-ycpB9yeqLhC4e30k8dFJqxzCAEJC0Et5swIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwGrz/yOO0EdEUB5DUcJ8XjGJ
-zAcwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBADOSGYLxhRxOj7gm33bTOeiQ
-PIlmAlvVtqg+44hgkcovBETHehNU1xBQRF/tdPACobZUA1/0YoyNZTHIY87qLDkJ
-Ks0twBDEHmgmadu+IKhutKIZzHSsU9xVfyipeAX7BfgDDeEaRdyPCan3KO9hpbhS
-CruOE+/WuIQiY2bS2SPs
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Old CRL nextUpdate EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=Old CRL nextUpdate CA
------BEGIN CERTIFICATE-----
-MIICjjCCAfegAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFU9sZCBDUkwgbmV4
-dFVwZGF0ZSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGQxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE5MDcGA1UEAxMw
-SW52YWxpZCBPbGQgQ1JMIG5leHRVcGRhdGUgRUUgQ2VydGlmaWNhdGUgVGVzdDEx
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvSHDwBMR2xa4zMZPJ+4WCtp4V
-RyIBBXrHretH519ipC4dqURqRrI7/N9ApYs6t/xevUxi+T2rDzXZB8L6x3AhE+BZ
-xOknZ/gpSN3du4ofSeM8DT7vzkwkj9S+bdEcU480Om0P40OwnQUIiR92HM8xO5r1
-qNrXauV14rf3F461HwIDAQABo2swaTAfBgNVHSMEGDAWgBTAavP/I47QR0RQHkNR
-wnxeMYnMBzAdBgNVHQ4EFgQU/pqWPiQxXU/VEoME39jSmPZFApEwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOB
-gQC2hDiZpMieKwCdZ3STNKZnLhmmgmcxMnshFx6iQ2B8XIbpY8fNvTUCPf9MMEvP
-a+1O7EDTEdrQCEpnKZWExBuB5qpOeP6ddjsedieij7YZUsPCn8aYxz3Cc8uBailz
-2ooOjU9ubv3hI/vnWXYKhZZwPdognMfenzqgqVonVkrt7A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Old CRL nextUpdate CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Jan 1 12:01:00 2002 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C0:6A:F3:FF:23:8E:D0:47:44:50:1E:43:51:C2:7C:5E:31:89:CC:07
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 09:dc:b4:50:29:96:87:a1:e0:b8:2e:39:6e:17:6e:95:7c:a2:
- 45:a8:24:5d:ce:da:6a:00:6f:8c:7a:19:77:5e:d8:d6:ff:63:
- 12:a5:68:c5:3e:e2:17:87:57:98:08:d7:2b:26:2e:1b:3d:12:
- 56:39:9c:93:8c:0e:c4:ed:19:af:37:4e:9c:2e:4a:54:85:8b:
- 54:2f:b2:a5:c9:ca:5a:9c:d2:a7:76:c5:00:1f:92:c0:cb:3e:
- 1d:0f:69:63:4c:f9:40:fe:40:d7:17:fa:ae:b2:5f:e2:f4:8b:
- 01:b1:2f:bc:7e:8a:b4:05:1a:97:21:8a:84:66:94:ec:5f:fa:
- 4d:28
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFU9sZCBDUkwgbmV4dFVwZGF0
-ZSBDQRcNMDEwNDE5MTQ1NzIwWhcNMDIwMTAxMTIwMTAwWqAvMC0wHwYDVR0jBBgw
-FoAUwGrz/yOO0EdEUB5DUcJ8XjGJzAcwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEACdy0UCmWh6HguC45bhdulXyiRagkXc7aagBvjHoZd17Y1v9jEqVoxT7i
-F4dXmAjXKyYuGz0SVjmck4wOxO0ZrzdOnC5KVIWLVC+ypcnKWpzSp3bFAB+SwMs+
-HQ9pY0z5QP5A1xf6rrJf4vSLAbEvvH6KtAUalyGKhGaU7F/6TSg=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11EE.pem
new file mode 100644
index 0000000000..61ed3e8504
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidOldCRLnextUpdateTest11EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 3D 56 D6 60 D6 34 00 EC 8D B6 50 91 FC DA 09 9A F3 9B 79 A5
+ friendlyName: Invalid Old CRL nextUpdate Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Old CRL nextUpdate EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=Old CRL nextUpdate CA
+-----BEGIN CERTIFICATE-----
+MIIDnTCCAoWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVT2xkIENS
+TCBuZXh0VXBkYXRlIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+aTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+OTA3BgNVBAMTMEludmFsaWQgT2xkIENSTCBuZXh0VXBkYXRlIEVFIENlcnRpZmlj
+YXRlIFRlc3QxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMUCQ6ht
+nIHGtGfWIymBLnkyZ/b+51EMYGK3oG2KyVWoC+++h1CzZaDiG8p0Gv54dQjJm5Vi
+z3SPO5TTkzmEIWCa/1uKIQPjOVVRey0qApCvymRoXXEJf59gnBqPDx26bXb6NsoZ
+fGk6yEkvhH+MhGzQCHN95ARUNMtYSbPgooEDzJR0ym+qj2LFmZhRwKEp0IubF109
+JPVk/NQIbI3HPZXUdCzp5jK1clTWl+NGS958LnnO4jEK9xJ6euTg/6x/uR+t1oRa
+IxLnB28PFaavkhQG4vVQ+M4Nb8QGBsXmjl8XyOB0YLf+ZVbDXZ1f1UG3MYsjY/4Y
+vksxOmddND9NtIMCAwEAAaNrMGkwHwYDVR0jBBgwFoAUztof2lrMjpf6IBUpT6yW
+jSrNeBMwHQYDVR0OBBYEFFZ23wygTM9MCKaXTBWP52hKEFSlMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEB
+AK1ocp8QO0gPKOT/sFZ92czs4wkA6tiiPte/lWgK1OQ5bPt5u3kT51mqBp+7c2T5
+Vph6MyKO3mp9gLEwFQPyxp4DyZd2i0GfTz50sIM7JUYFvpjThENKLkBwIHDB+fFp
+O2K6JtboC2dutQXhseGvWNc9nadR6/MaNlYEZGBCtcRv7jkNzsqzrVCwKZySxh5a
+Gz+yM9JeDcTJQIIi9FTtiI5EmBAmWU9Ny2GuehF71srlR6Vv+TNxZHZCPc+jAzBh
+3CAV7MPCTIDXbBTtRrh60063/x94KJQ6RIvnqnkX+y3A0wIbEDv8XtwvG8GI8q7a
+Ff95NQbv9wnAVBcG7YoEI6k=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3D 56 D6 60 D6 34 00 EC 8D B6 50 91 FC DA 09 9A F3 9B 79 A5
+ friendlyName: Invalid Old CRL nextUpdate Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6D678DE8D634ED06
+
+vwypvzYx+kueXlE9gvBOHTXYAezmvVluBqFSC8jJO+am6Qe6ky3oQFcPMZ2xP9n3
+nHwS5xwXEdabH/uLxZ0t0uE41oWW3L6cpnhR+Rc4zY7qHB4pF/9fBya2jUg0fREe
+ItQrFbLZdTfLNMF5+DGuLwxE5RblToi9InTMBrZyUHBvE6sj8YFuZ//qzkV1VnD+
+JmIRZUNOBwUXsfCG4qoBrjOcrFgktQz8SsAxGflwWkchf15X6s5OxtHm5dImXpPN
+EPzewQSvQnnE9P8/44BLtvEwFRLbuR8oT+YLFcyJO//KgoZN2ojpjRB1/skW5BNM
+ABe91qhsyAMdFmNcWQz5HZ+ouovZByaP2CI3+J1WDUjakAY9roWS7X1pBXV792+W
++w7S1gd62vKS/+lds/SF6mrKPzJz21NJlgAtqPj5QrKvgN88MYfpEp3GxN8D7k7A
+lgeMVrHhh/v3aFaJ/G/Hl+nJmzunNaIdTXrqwIj70sqy+QWVOZOTkVevaW31nG4v
+Hs5V/ZC7+4gdG+Pu4XCFoRgVQKJd+XBkOgZXaX2XDi2WvCDfnPJA0calf+eUVUjq
+owoYbQCX5brOwUgqmkBzHWyFRqxBxvJqOLCreFykvWDQpSN6gmGaBlpb/V28ltLr
+V3rFBoZ6+tVnocDlUhvOkCrxpd99E+hmBkofyaQRH2az1fJCv/0unooxNFdy3FAU
+tsaQik2vo5NUpBhn14/XkN7/qv84CXVek54ip+ho9zJiuz+tAyu39dGdlZ4W5pMx
+euuR6NdVoeXmGzsDMW7AV+d+skgDSajlBgurbN6uIZqUS4emRjDizbmmHkecg8K+
+Q8UwKFVc3lQYdetgIdHEXPebSrhtfjfGSo7Ie8LIkX0vx0CAGeElsUwIYDfQxZUi
+Pe0K0HiDGG0f+Cj5lozDJM/Qlf4a0QK00qwABuoI10Tn9dfa0snUJcSC0gi9X5j6
+gwLUzKhb6KlSeU2YxPQFioIzWBMEy4Fb4P3vkwnEeTYe8iAwXXGuZ80iVeIkU3sI
+CffT4O+u9OTNNHqXAa9AHtyNyjK7RybJAahPThzriiMrBAgJfA7JsDEYbBfDIuIM
+O5Tj6MPHcRXLjoZp4shSfLzREvoZ67iSjwfc5rXMVgdCez4TQiq2KGsiYtxSt/gY
+mlioWnkyLsMpITAt68rJBGxM3Q22hBI1VeDPg6HOk4IBb4oDruum+/DpHgx62T7F
+UCPRbxybGqIoIFd1m4toOh/Wtsgj6uukAqLCc2mZF6LZCzV2jS9+KdDi/2dISNEE
++R5KlNAXTtlnhlfjwWTmbw9Xk+x8Km8LSldHgDPC8J5ZlQskxECKcMD7mC6qxZoJ
+6mcdyMKpJo2fqwyAkrDMal7lnFt04/O43zCobhVojfptju0GFXpXVIgRsr37t08/
+ULdYl/ZU1aa5jJNrlxM7XnyzE9s5ln3dJOz36Un/VeoMF4ffOotex9EV5NOzrPnq
+fXv2YG3pDfGHPPhrnQ+VJPeQspYplCDaRSX7m1yFw5B7wKXxCgh5+cTlG2FadXYr
+vkGg7YiBDPVd3IF0NhrI55ghEo8Q71WhzWFZibnjqPFpeh0inSKAQw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10.pem
deleted file mode 100644
index 3c896b358d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10.pem
+++ /dev/null
@@ -1,172 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Policy Mapping EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=Good subCA PanyPolicy Mapping 1to2
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTIkdvb2Qgc3ViQ0Eg
-UGFueVBvbGljeSBNYXBwaW5nIDF0bzIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBgMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxNTAzBgNVBAMTLEludmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNh
-dGUgVGVzdDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChB9eTYlpZl1JR
-8TrbGxGjxB92HiDmmZ2KLK8LOAzDhLn6pDzsOGwkyo7M6CDyAoWz/eaCmRD1i6qy
-QKVu2sn162p7KlvlNyd1JYAVIAPjkGR/a8VfCm9q3N/lRKwsSj/GZIek/8iSW/KC
-FdaqSGbsEbHK6Fn8vcQ4Lh4eUroNKwIDAQABo2swaTAfBgNVHSMEGDAWgBSR1+G1
-pJYIkfGicS9m2Sd7SoKTmjAdBgNVHQ4EFgQUqFpT/L04k96R6J+5dQbd8YN6qoMw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
-9w0BAQUFAAOBgQADIM+40SMZ1r8wWXESNPXd8FCdvGJyWdeFjUA0Ads0pN+XIsnC
-4sPLYgWB1xdrSQyNdrwkLoyy2UGPHgSTwlhlX7NxZHyfxaMZRN1FKRPHs6alDc/M
-603qZ04FrwJd54rHiHLAI5/fgJzZRu5bOUBiDFxW7skEOp/4AiVZG4+8Wg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good subCA PanyPolicy Mapping 1to2
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICtTCCAh6gAwIBAgIBFjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTIkdvb2Qgc3ViQ0EgUGFu
-eVBvbGljeSBNYXBwaW5nIDF0bzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-ANGY6UqVJ9oB3KneANaPiYS3vFaEAo7CVhPn358boVTv2/wQv8iwT9MvDcASa4Fi
-5kaob+B5k7T8qjNOtxaZJb69UDUDsAYww6r/NK5pkS1KNf7CJZW6/RQC06GsivKO
-kQoudXfGEjAMhmHNuEXS4biTlRuVUXJqLPq2yLwAJPZ1AgMBAAGjga0wgaowHwYD
-VR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oVlMcwHQYDVR0OBBYEFJHX4bWklgiR
-8aJxL2bZJ3tKgpOaMA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUdIAAw
-JgYDVR0hAQH/BBwwGjAYBgpghkgBZQMCATABBgpghkgBZQMCATACMA8GA1UdEwEB
-/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUFAAOBgQBNuXYJvgOn
-wez9J/K4ZZhWpMPo/7Qso2S6BAoJh7QdTymJKxD6nDnPwetIpbQkbEtq+V30ZA+o
-6v+0cntT/I7cm9JKOXMOKn35BODzS8u5UJTDwWc/l5SA0scCSRfTT9LJambCyz+m
-C0/k+v5zw5VpFozVY4FoV4/KnwIhJPuDwg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good subCA PanyPolicy Mapping 1to2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:91:D7:E1:B5:A4:96:08:91:F1:A2:71:2F:66:D9:27:7B:4A:82:93:9A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 97:e7:b7:e3:46:cf:59:49:72:d2:0e:de:0e:f6:c3:1a:ca:34:
- 59:50:f1:2d:fb:11:31:f7:bb:b2:f7:dd:0e:fb:bd:6b:7a:7f:
- e7:dd:02:be:6c:7b:36:1c:49:50:38:d9:85:67:97:a5:0f:84:
- 49:de:8a:d5:0b:d0:36:fc:6c:4a:82:cb:83:73:ed:1e:af:31:
- dc:0f:6f:eb:69:18:67:b7:fb:1e:a8:1d:a5:36:84:dd:05:72:
- 52:f1:51:e1:93:6a:ff:2f:92:6b:7a:c1:67:90:0b:7f:66:0e:
- f1:83:22:d9:52:5e:f7:58:5d:5c:7a:1b:69:84:91:da:b1:18:
- 11:c2
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTIkdvb2Qgc3ViQ0EgUGFueVBv
-bGljeSBNYXBwaW5nIDF0bzIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFJHX4bWklgiR8aJxL2bZJ3tKgpOaMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAJfnt+NGz1lJctIO3g72wxrKNFlQ8S37ETH3u7L3
-3Q77vWt6f+fdAr5sezYcSVA42YVnl6UPhEneitUL0Db8bEqCy4Nz7R6vMdwPb+tp
-GGe3+x6oHaU2hN0FclLxUeGTav8vkmt6wWeQC39mDvGDItlSXvdYXVx6G2mEkdqx
-GBHC
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10EE.pem
new file mode 100644
index 0000000000..9f7ffefc55
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest10EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C3 F9 93 C4 0D 7F C8 D2 5E 2B F1 AA FD B7 35 76 2B 93 F7 1D
+ friendlyName: Invalid Policy Mapping Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Policy Mapping EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=Good subCA PanyPolicy Mapping 1to2
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMiR29vZCBz
+dWJDQSBQYW55UG9saWN5IE1hcHBpbmcgMXRvMjAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTUwMwYDVQQDEyxJbnZhbGlkIFBvbGljeSBNYXBwaW5nIEVF
+IENlcnRpZmljYXRlIFRlc3QxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKgYrs2bp2rDpT6ZXc4PgBYjMV+WHjSqGUgrAPdR62UDChqzNHrE1Pw0Lgh2
+IoWY+M7poGGp2Gsl9puYwBnXoViJ4dcD3EHwJGG0FvlWGpvKbV3l1AAd7cEJHokv
+S72hma5YVH20kPfdF3Kd34WZNZTY14L0k+h/COfBuL9EQfq47rmSAiWLy1K+4fBF
+jgc2Fo+UG37bpSxjZqTVt0dPmHzaJT5Ft9WfElx9GDQPl8tMES5gbY2asmubPk6q
+FmG6ey1hM5Tn4EvoouxgHEEAKqeo6jZVPbVgDgL6vKiMbmDUUvB+ujR+diuvmp2L
+HxrVx1s2bXkD9mkal41OxPy9/c0CAwEAAaNrMGkwHwYDVR0jBBgwFoAUW3N5meOu
+BtOKpjNOFHjkoB2x5MkwHQYDVR0OBBYEFPG//ujd6Iehzjh3gjYhBFAefR0kMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
+AQELBQADggEBAK96lyXiY85zaUn/7YefYb8m7f0S+IghFiiq8tbityudKhvMlna6
+0C/os+x2O5Mhy84okB3MBcjghp9/Nl2WUnyYyO+BjCeDk51xyAFNtXl5VkEsa029
+vfMKMWWOy51egYnVzErYmeud4H5pOFB7+x/55hMbMRrs6ww2eqtuM+i14iYKLNaM
+MIAMJKMjGUu20CoNnEeYz/lLCtcD3+/qlMrBcnM+H662A46e6L+5Q/o7mMyQQCvc
+jMKI90clD+5t7o6pA/rhv0wSpYz/GAcGciuAA5GMuJJOZjHSycMISz3nrBFvo6Jr
+F5tYb+cl5W0BUCJDswlj4X0wWsXvblfOG20=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C3 F9 93 C4 0D 7F C8 D2 5E 2B F1 AA FD B7 35 76 2B 93 F7 1D
+ friendlyName: Invalid Policy Mapping Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A32053B6D3456380
+
+b3XSd0KkeY/Put6bpMXSPKWjmmmQGmo1oBTol3Gucht0gv9oVx3WQ2F2C0Kcl3q5
+GngVI39rccFLRt4uLbBugJ+FwvGuukeCW2OYF/PH+vuYZXfzKrS/DcuVV0q/KchN
+CkqWwSGFCLtUibk+jDwtSS0N7WzLmmXTBhBUrk7vXSP4dQex5xEuVJtl0/rXvV6j
+jQno4k5UwFldNY1Ynffaq15lxu0p0x67f4rR3mJjTwXS0mHR6T6t5uNqUUlQLl7f
+fVjSakaAHlVLhZmKNJ2vgVTaHDMOZaDOiQ99DFseaKajhUB/tCYd5sq7PLeOoeLW
+pLm5VcRt2LQyzMicoHTDfDSKNpcfzVxv7uCAExOaGE9DzPpe8WqwiWRvhuyN4+XT
+f4L2ZjOXxvcM05v41x/xxTKDDZEt7YitP53YQWgmLwR7mrba0jYYRWK6WyR0VzsS
+kW9KCvapfBNO0LVTfUhEVrpqk88pIy0X3vLk/Fa52G2N4bj8TU+hDyudilJCnL5c
+gHIPOyP2YGkatRdMsZh5janilmom28RV/wnoESMKIfRL0Gt8Ct7k6syg5rp1X6r8
+WRD9pK1vp3BQb7dGOzDM13S3ZFD49hqoIQb1p3Lc8S1hlDKQO0pVvuPHK2EltbwV
+R0nAFbGW506dTNdpEbAR13zXS0H/WtisIAxVtpiKPY3vEEFX+dmyU7uKICCcttkQ
+LV3LqGo30fg5NgX554g4x37pW4wj+SDbHnmw+YaTAgSJN+n2zfBYmh2nb7WZgBSO
+5cRRwDson3j4HUX4Kdxbi1zNzQy/R7PKwtq9i/BpSxFLvFFt/nVbKCH2AQ1p5bqT
+kaYdL2b9L8eb82nJE42gOJ2m9mLG6FmLWEcb5EAyH2MTCET403T//cun+EVu2raw
+iJ9oUuNQfVGbU9dIkrVQ+fpMKkO3yiB9GoPYy0U8zMXRvKJEruKZpLKGgz/RNWex
+Rb4umWp43DhxO0zCLVWVAdr/Bj2qgGjDDO8j6TuYO1zIb8M3Y6HlQJ//3GDmmEys
+yzuLmIMpSJTbqQG5+sXdjpUfH3UHEYSda3x9g8irkkAPv5GOlZwoSaw+un4VvAK5
+qE2zj0k3PH57/1YKdddUZUqYJm/L1TP9TzBxWYyDgWH3DxY/mGtz2hcIDs48wTj0
+IaiBenFCy0ulz/+zg5e8bgFXPqzyFkOYQg90Kj1Tm+E73Bd0/my7FpBGbDvs+xzV
+aZIrG5XxeOumLXRMr3SrjpgqMR1izY8oSpbWsBXGKyuBWaBGS3Qxd3riIOnFXPxO
+89XO/Jn2Ts3VneDvQaOotAcgrzNT/FwiMtfwk502Xes/Mg/Chb1C+hloIGwJBD0D
+NuE3R69v4Ky/BgvRUNmIvcK5sKuRgnDW0bMmEP6KdLx3IDxPVME6TV7W0pDVSiU3
+j3WmApXzM+Fha+W6aKfZuIu4rqVmQKaNc7zDD+5Zc4YkyjMW43r05vbjBR4GDp2K
+DptJ/xlDLNiUDJ8IdP8t+5Uz1rPRb9VL4aOuSvvM3F2CgaeECQ13BEzMqX3TIrKt
+n2BXWScOnLxDb8EpgA5AjjGRHrwtJ3LsaKC+ck5bYj2sM+aXuhduzA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2.pem
deleted file mode 100644
index 43fc124d7d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Policy Mapping EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=Mapping 1to2 CA
------BEGIN CERTIFICATE-----
-MIICgzCCAeygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD01hcHBpbmcgMXRv
-MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF8xCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE0MDIGA1UEAxMrSW52YWxp
-ZCBQb2xpY3kgTWFwcGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjCBnzANBgkqhkiG
-9w0BAQEFAAOBjQAwgYkCgYEAoadvCebWnauqUaHFp40w4mCV71scsCOfYsKd2A1Z
-qG7a+bY47N5PYZ3U5Ma08y9eYo1tp/KdyjpqVjRyjuThypOpD9w0G+SKNSSO9qWC
-MDvLPUi28tTApRjWztYYwN/g5vFkSu17fxV+2UFjktKI5L7kajObs+ukIn+CZjp2
-ZJsCAwEAAaNrMGkwHwYDVR0jBBgwFoAUNzuKobqNp3SbwOvWOcshDI2jVn0wHQYD
-VR0OBBYEFP3Ru6m0Dy03xmdc1XvYMeSY1zK/MA4GA1UdDwEB/wQEAwIE8DAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAGhBCvmaevxrJ
-N0Kz2kBu8iSaQ909Y6uo5N0DyRRCZQGADpcApXIr7/C/Uu4qBIyC3WTBsx2cxZFV
-5FThscR7x6s7loGSYxVh2GrCKj3t643zzznkIP7iMZxSGBdVJpEsjScMJ/7tXnkp
-IaawhSXoSuDs35Gvi32ldHbXmUh9NvY=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Mapping 1to2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICrTCCAhagAwIBAgIBMDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPTWFwcGluZyAx
-dG8yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXwTHRx8gVHWtSe1VX
-oLPFQmGX4Y0U4v535jowfMd9254hmwW4VbZzK7rrXGOAimFxGHKwa7mkPEo80MIW
-8YQC5HZs3jaXLh/xsmV1qlzwceCXooef+wu8W0pgoJ63MmY+ZJWiNK2ygRV/EVFF
-x2ii8ZGDW+SKEX2WIYI7JhmcTQIDAQABo4GzMIGwMB8GA1UdIwQYMBaAFPts1C2B
-nsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQ3O4qhuo2ndJvA69Y5yyEMjaNWfTAO
-BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB
-/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/
-MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQADgYEAphAVDZECciXjDiCta9HU
-ZubezLaRjcl0IaUmTlvuhUqkfGG2x1KhB6QTq7JGCmBrlxL93qhU+8sGW1k26/3p
-c3hc60bKZ5oBG96iN05oLWWF3udbqBESMO7gn1zX14s97qLtuqQAyuERy2L2uOkk
-n/emInqTFTixe284WjHR3XY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Mapping 1to2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:37:3B:8A:A1:BA:8D:A7:74:9B:C0:EB:D6:39:CB:21:0C:8D:A3:56:7D
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 29:63:8c:57:a4:35:bb:2c:2e:a0:1e:7e:c1:e2:0e:39:2c:83:
- d6:5f:29:3a:03:70:63:aa:1f:42:e8:fd:3f:64:f6:8b:ad:86:
- 27:c3:a6:5d:48:9d:ef:6d:bc:be:7a:24:a9:6d:b0:4e:4d:58:
- 4f:52:c8:bf:dc:70:7c:ea:8d:5e:54:12:db:5d:62:c5:63:06:
- 2e:00:b4:d2:fa:51:6c:da:3f:41:04:36:14:ce:63:b5:46:e6:
- 7d:10:01:db:50:07:69:82:6a:34:45:0b:38:5e:f2:d5:8b:77:
- e4:ea:6a:7f:9a:18:fa:74:ed:b4:5a:ba:68:f2:68:c4:d2:55:
- 17:9e
------BEGIN X509 CRL-----
-MIIBPDCBpgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD01hcHBpbmcgMXRvMiBDQRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUNzuK
-obqNp3SbwOvWOcshDI2jVn0wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-KWOMV6Q1uywuoB5+weIOOSyD1l8pOgNwY6ofQuj9P2T2i62GJ8OmXUid7228vnok
-qW2wTk1YT1LIv9xwfOqNXlQS211ixWMGLgC00vpRbNo/QQQ2FM5jtUbmfRAB21AH
-aYJqNEULOF7y1Yt35Opqf5oY+nTttFq6aPJoxNJVF54=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2EE.pem
new file mode 100644
index 0000000000..d371a30fe0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: DD 2D 93 ED 79 0D 8A 49 8F 16 40 52 06 71 64 BC A0 C3 D0 B8
+ friendlyName: Invalid Policy Mapping Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Policy Mapping EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=Mapping 1to2 CA
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPTWFwcGlu
+ZyAxdG8yIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowZDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExNDAyBgNV
+BAMTK0ludmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDIw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP0ZnJwVL9VAfdOd5XKlTy
+DBfVk0gJc5L/Xc1KAvdB4p8wMJnx08oy7X9zp2zJUdN8nMP8+C/PL9LssmwLIPCz
+MfZJmiCynpann3CPnoXjlRyYZtHFMeW6D8ganSXetE4O1vKrCR0KOVU0xEwp5PuE
+JvC2c9QrTyZQYKgv7Gj3zZ2QFNi46Mullsibu3FOWfVpncFDZMebzPS+qIfv5I5U
+Vjec7wYjoSY25aL1/vDLwkzlTBkrPjGJeGb2oKeK1cmuDzHB5k6kPTpyBXYpF2z6
+ifqjU/wLFo94hASA0l4cMh2IstJ+koKUZIuWOipTR5K2nDMywNpLyrHwdJ9Nwzwt
+AgMBAAGjazBpMB8GA1UdIwQYMBaAFJnFeGnLPTN2wpmsROWwDv659NvHMB0GA1Ud
+DgQWBBQc93qRn7CZN550xzB1rEvWIX+9tTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQDGxaCY0Qeaztw8
+J0tdbO75i+EoXmPj8SdrzEvPS4YNnCsOt0sgBKQeP5BpfFScQgIoGHTt3leCUXlM
+c6hu8rLTLB1Shs0ZSAPj+nmNx4LdppBbgZQ3KNBzhsgvz16CXK3PceMIuDfrcyRR
+DtpqeIXCTp66esYzwq1LsdJuBdusYlkywZ/Q4NR8cHubhcAFM+iA289XjucldDDK
+Xo1L2XERrSqXK3R4p1ZUIIcbYeFsOhZyBPU5UnXJcac4DG5LPZnnZxMAbUL8Rq+9
+nx4NpZeML+uuIu+heoU51t2PzKDjJZOFhnspC7ZwrTmAYYIxTblTaZULF97Zvvc5
+QKBZoV2y
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DD 2D 93 ED 79 0D 8A 49 8F 16 40 52 06 71 64 BC A0 C3 D0 B8
+ friendlyName: Invalid Policy Mapping Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9AA315A6F70CA697
+
+UpFJgV3wr8eBPi/ZnZni/I2XHHWMLBoM8LbF33siJxRhRGuWxqbg8ja0HwbY1KCM
+whlDYTc+wWp1VwEf8vxSykcdwBjgPlS9ITjf09Qr9A+YquKVZD8kLt9kBWeoFtz9
+RKlsZ2a0MNoQ9aEA9KgrR21K3iuxHhyKgacba4anc4wDNOJgmMqww7KkTTVN+y5C
+4P2mFxPR+57MH7sDyAdCrtL21kXdlzoAUqp7HdExKqJhb9RDbSiaIPDuCdIV4GuG
+U1N1dVVJRU+dpnLVOACmBZWJF9RoavZzo/CIL9aSHgYCqBpqMyM9xRL0ZzXcHtyq
+jTeqkSY5L+ffKmZQrdpz5/zAYlcAgpWDfnvH2VhqTw9jOjbXT168/zIXhoX9ZfSw
+WTX6Ko3s6Hxdq2xds4AFAt4eFJ321JVuRa1pwMbm/B682QVxsEQMRGmsZQRd46rc
+Hk1RCP4IEkh1ERU/1R6s48rL72j3nhKgs3reh67p8Eyawh1UToF1nerghUBlqHu7
+KOaUBOHwHWAAdEINf2wQKnJsgJJ2+4u/g2nwhUgyvn/XikstUCHMkx7Sx80aq16C
+tyQHZohWFU91grZO6Xixxbj57nJgtzD8hrPsbhNZ530ECNiHBC7BilJ5QXGRGAjP
+BWFSuNpP7payaETMQkWts+m+yHFEgSsdEFo4q4kZLLm/unR1SYQGcJTMF68efBlg
+MUc+//uXGBkeL6r2iwPeg75l/T0vrSdhRDSH64+2vitoJ4MXu+QotDeZKBwPuJXG
+umk4Lusz2lKbaBGhKTCn7zqZPKR+7ixKDhOYMtlquczeoQVBv4qzCdeI0+EKpTCz
+zQeRkS6J9NUiaJopMqY0LAzisWfAEOIu0++kJ6t8+XyGTIKNR7Onlh14p66pP+EL
+WaPBrIB4gXlEj4Sf+lrrv+k8scah7iTsQA+y3vpqGv/f8clZ4vB2OHp2UtXFxhka
+bcYUuXrRk8z48Y8YinQr/KYXLWbJAqOcHn0K6IkhbNusT8FRrQFFKJmBFkWfWeW5
+7Nllrf3jsQC8qeVb+PiKt2nmaP5iJzK4Z9djxSyusDIszTklDTmX5L1+K4jEa8lv
+ch6pGEXNBr5LC5QOl8OBfKzRgFRjCjFchEAHiuw9eeMQLd5mxXA+z3xQxr7jdTpj
+K+SMIKIHzzsX7pGmzyZY1LbpyN/DvfCT2EgkXOtiGvV8GuHCsDMtkeMUIij4aTV3
+0aRkjOM58AVUVGNwN8TqnOZIxcv+1Jdb2/JGxK9b0y/ksinfBUr+bulHUx7C608F
+y5mbNEVA1mlRX7PV7cywWXeyPtcQchqHgi5IHIg2xKkUZhZOYbB6NIfaVhzNdV83
+7AlZ5w/04tFCZgkoCq95ndcov8Rxdjx/5KDDwx+07GcXalMQCfKO0lGFNYMlLtxJ
+NjFHh4RcIMS1gwQYwkuWbB4DYg63Vp+oUapeSMbxm4Jh3TatdMmh8fMV9fjE3hVJ
+XzD8mbBgD1SbU07CIWCFaYMmqZcaYparGe09XdbjoguNRiTQyMI+kVMeS3Iuk1wi
+bRn/dirFwfRdB1TkoEJZ10VUT7FAD7fosGgs8/wY6IK/jvf6T+Gs+A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4.pem
deleted file mode 100644
index 5c77a406bd..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4.pem
+++ /dev/null
@@ -1,214 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Policy Mapping EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subsubCA
------BEGIN CERTIFICATE-----
-MIICjTCCAfagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGVAxMiBNYXBwaW5n
-IDF0bzMgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBf
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNDAyBgNV
-BAMTK0ludmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDQw
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJprKoJhJkwv9iBN1IYtMV3uRD5s
-uHrGKo8QKVwNvqYLHai3buTlKV5MkXVGAX4jOoo4gsNST1yqaYHmB/PN8gpC5Zei
-k0+5yWdAraOAj6IeMEJzs6Vu9ajsCKNQ/hbc6SBJ7wYIxviyUzvUVS9L7tGbO9ww
-+pDzJ+GDcBzAhMJNAgMBAAGjazBpMB8GA1UdIwQYMBaAFPYssbcpta6Vf7D4OUFT
-LS4PBOPHMB0GA1UdDgQWBBSEY/EgMg6/W2kqOBHmu0ZzH+8FdjAOBgNVHQ8BAf8E
-BAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATADMA0GCSqGSIb3DQEBBQUAA4GB
-AI26nbSlHGf56TsealBKtrzfLJm4+UtAODZ+a5qU/JtzajvXGdh66TgEK+NFB83w
-h3OtGs/OQ39fhXosCcXXmXk8mNBj6MokhRptFdnJz+edT9yqz96ufAHZSKpG1Di2
-d9bllknCKDikzWUOGTOiCuHc2n7ymexbgnYnUAdvLw2s
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICvzCCAiigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UEAxMTUDEyIE1hcHBp
-bmcgMXRvMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmTEwLH6u6mb6
-kvz4ulbBVFC2Ea6WdEv2uH/vNi23mER2Nl+xAbeopiy3OLEiXavvD3uvVjX0bSOH
-BGk2j/ern/Urw6djfKt5V4O3NMYi6Grvfm346kdutjJuBcNlhLOE8mLXUguspocr
-AoAEjrQtuS4Bkb9A5wj3OYy4jr2JhtMCAwEAAaOBwTCBvjAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUreIKE61SbSWszamYogoEaK1y
-rrIwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUDAgEwATAMBgpg
-hkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEw
-AzAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQAD
-gYEAEelnHhW6SAs3Zj4a5YMVTKDe7vCThen9bA1Awt3yFincViRt5/s2ZyzTN5fr
-Xi+2m42Gm+Anb3D7rpV9IJ/PahHq4yrKSrcAzhT3IcHbuHFNwiw8Z3T+31hhjJUx
-3atYpYOZZPYwuT0inFHJWRfBNA8NGBtqYlxI1C+/ucdy7ik=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subsubCA
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subCA
------BEGIN CERTIFICATE-----
-MIICwTCCAiqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlAxMiBNYXBwaW5n
-IDF0bzMgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBNMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMT
-GVAxMiBNYXBwaW5nIDF0bzMgc3Vic3ViQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBAJjo4/4TekqllLI7gPzmE2OceB30SRuraEVWVdR/lmFpFTks5fKkqf96
-WjYpnJZwaqE1ZdUQxgeNsswPm4pUAhVmU9IHvqBaM+bNXFsrwBOYYhfZY3xnwcxp
-IZsvkLPuEq1vLwxpn+0zTDOpDGf9zhiTrswEUoGYBwOVqRDaToYdAgMBAAGjgbMw
-gbAwHwYDVR0jBBgwFoAUXcS6eHk0JsNyV9FZ9KPiVKcocdEwHQYDVR0OBBYEFPYs
-sbcpta6Vf7D4OUFTLS4PBOPHMA4GA1UdDwEB/wQEAwIBBjAlBgNVHSAEHjAcMAwG
-CmCGSAFlAwIBMAMwDAYKYIZIAWUDAgEwBDAmBgNVHSEBAf8EHDAaMBgGCmCGSAFl
-AwIBMAQGCmCGSAFlAwIBMAgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUF
-AAOBgQCass0kmtqSdWX5lffBs/tSTSvnGK38REo2IwTFLHduO4cvzAyS7ProbF/J
-al8FtT9mdnl+NpwrH4KlFNu+uti47wFj9xov/kbcmp21DvZ/m8ihmStk4FG2r6Ad
-0gdmVfBYem0mOu/1r/F8deNFP/Dpd8w3KFnv3Dd9wZd/Eb5hrg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subCA
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
------BEGIN CERTIFICATE-----
-MIIC1TCCAj6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE1AxMiBNYXBwaW5n
-IDF0bzMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBKMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlAx
-MiBNYXBwaW5nIDF0bzMgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-AMsNrOgngQPHY/5QvmR5y8mHOJJ2T8Vjf+3/DPv5eMF+q11urxfCat4faDdtchBa
-QXOWQ2TEy6tqpR7u8UJ2wnI7phld51gAcT2I8V7swo/EM1Ga1i5bWa5G10vPmZw5
-l7QwqT/D6JkHdthcaJdQrBP9zesYPEp13RFQU9mP5451AgMBAAGjgc0wgcowHwYD
-VR0jBBgwFoAUreIKE61SbSWszamYogoEaK1yrrIwHQYDVR0OBBYEFF3Eunh5NCbD
-clfRWfSj4lSnKHHRMA4GA1UdDwEB/wQEAwIBBjAlBgNVHSAEHjAcMAwGCmCGSAFl
-AwIBMAIwDAYKYIZIAWUDAgEwBTBABgNVHSEBAf8ENjA0MBgGCmCGSAFlAwIBMAIG
-CmCGSAFlAwIBMAQwGAYKYIZIAWUDAgEwBQYKYIZIAWUDAgEwBzAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAHwK+aOYJpXAoXSRQ1o82pqD++jA/uvr
-2eJoXbcch64CAdRNuCA7rQoRAx1nSUgjoLmHcTDrowQzodrVXVmCmYqXxB5XswG6
-z5Oj09NorxHxpAs7E/izElYwEXl5n0NMInD6S2r1SWOnRpGnCL8PYM3gW+xne8rJ
-CZMIMADOWvrc
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:E2:0A:13:AD:52:6D:25:AC:CD:A9:98:A2:0A:04:68:AD:72:AE:B2
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 94:34:62:ba:34:51:b4:ad:dd:01:40:fe:3d:eb:bc:6c:7c:89:
- cb:f0:7e:e5:38:03:50:93:5b:68:ba:d1:ca:14:39:ec:a8:9c:
- 37:24:c3:0f:01:eb:14:67:8c:07:fc:37:1f:bb:45:b9:4f:5f:
- 56:ad:f3:85:03:23:a8:bd:93:1c:ca:01:e8:b5:1c:c8:60:18:
- 13:95:bf:5a:11:11:b2:3c:3c:27:69:bf:97:08:c0:b7:4a:7a:
- 39:5e:03:2c:67:5a:11:a0:4f:6f:8d:70:4e:e2:b5:31:73:2a:
- bf:5b:15:af:5b:4e:14:e0:73:5b:f1:2d:cd:bc:75:44:42:d4:
- da:3b
------BEGIN X509 CRL-----
-MIIBQDCBqgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE1AxMiBNYXBwaW5nIDF0bzMg
-Q0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaA
-FK3iChOtUm0lrM2pmKIKBGitcq6yMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUA
-A4GBAJQ0Yro0UbSt3QFA/j3rvGx8icvwfuU4A1CTW2i60coUOeyonDckww8B6xRn
-jAf8Nx+7RblPX1at84UDI6i9kxzKAei1HMhgGBOVv1oREbI8PCdpv5cIwLdKejle
-AyxnWhGgT2+NcE7itTFzKr9bFa9bThTgc1vxLc28dURC1No7
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5D:C4:BA:78:79:34:26:C3:72:57:D1:59:F4:A3:E2:54:A7:28:71:D1
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 15:bb:13:8f:22:9e:5f:ae:7d:26:76:5b:6f:8d:8b:a4:37:1d:
- fa:87:83:61:23:70:ca:f2:bd:ba:ae:72:04:3e:0a:21:70:4e:
- 01:97:4c:e3:16:d0:ef:d9:31:50:6f:5b:ff:51:10:40:73:82:
- 0f:f2:00:90:1a:bb:f8:93:68:b9:0c:15:9d:b2:c3:5b:56:73:
- 52:d3:1c:0f:75:2f:51:5b:40:3f:8b:71:42:54:33:af:55:20:
- c8:ff:bf:ff:68:43:78:93:55:01:fb:7e:4d:db:a8:57:36:34:
- df:a2:90:75:bb:fa:23:f3:9f:de:e4:4d:92:30:65:8c:f2:64:
- e0:01
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlAxMiBNYXBwaW5nIDF0bzMg
-c3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFF3Eunh5NCbDclfRWfSj4lSnKHHRMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBABW7E48inl+ufSZ2W2+Ni6Q3HfqHg2EjcMryvbqucgQ+CiFwTgGXTOMW
-0O/ZMVBvW/9REEBzgg/yAJAau/iTaLkMFZ2yw1tWc1LTHA91L1FbQD+LcUJUM69V
-IMj/v/9oQ3iTVQH7fk3bqFc2NN+ikHW7+iPzn97kTZIwZYzyZOAB
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F6:2C:B1:B7:29:B5:AE:95:7F:B0:F8:39:41:53:2D:2E:0F:04:E3:C7
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 6f:b3:1a:29:36:35:76:c7:62:11:6e:e9:29:e6:83:8b:5e:bf:
- 25:ea:4d:71:56:16:50:25:92:68:a8:a2:e9:4d:09:a3:74:36:
- e2:9b:c1:52:dd:87:0a:64:98:58:da:6a:96:e6:c4:02:90:d8:
- cd:4c:10:71:4c:98:1d:bb:d4:8d:7d:74:f9:34:3f:98:f7:8a:
- 5e:eb:bf:7c:8f:90:2a:7b:c4:f3:29:cc:3c:62:a3:f8:08:c2:
- 0a:ae:35:92:8d:ed:c0:30:a3:f2:a1:c7:7c:a1:68:1d:b0:48:
- 4d:c1:4f:50:7f:1f:af:c6:f3:a1:d0:ad:8a:1a:78:05:84:6d:
- d9:7e
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGVAxMiBNYXBwaW5nIDF0bzMg
-c3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFPYssbcpta6Vf7D4OUFTLS4PBOPHMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAG+zGik2NXbHYhFu6Snmg4tevyXqTXFWFlAlkmiooulNCaN0NuKb
-wVLdhwpkmFjaapbmxAKQ2M1MEHFMmB271I19dPk0P5j3il7rv3yPkCp7xPMpzDxi
-o/gIwgquNZKN7cAwo/Khx3yhaB2wSE3BT1B/H6/G86HQrYoaeAWEbdl+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4EE.pem
new file mode 100644
index 0000000000..2ba54b3a1b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidPolicyMappingTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CD A2 F4 2B 63 C8 3E C1 A4 26 1B 31 5F A7 8C 6B EB 6A B7 B5
+ friendlyName: Invalid Policy Mapping Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Policy Mapping EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZUDEyIE1h
+cHBpbmcgMXRvMyBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMGQxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMTQwMgYDVQQDEytJbnZhbGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmlj
+YXRlIFRlc3Q0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuOegev0I
+rw/xlikpHk/FMYCcY96SImlDS0RBDaTJkie8ehC41c2dn4GAWeTxoFn5c+joQ6dq
+Y1Po7teA59bYP4USHordfUKh7UjD36NPQnzbfU4GVUmVksb0f5PdABQnRwmYH+AX
+ZaCfS37WRuoge7+XqUza3YLgY32y1Fh9VPNRygcGfvbhyYv4S2T+qruvc70C5ILB
+lBGt+deKtqDqngE+7DZEZN6hn3H8Fgme8AAPdx48JNTLi4apId9Aag0BR7MMb0nC
+Ntz463ci+/EhcD3HYZihuoZQ+kDlF2/zQOukhnebBpUv3VZqDuCvGJUAZPRrDRRo
+dK5QZ6BSyfJ1zwIDAQABo2swaTAfBgNVHSMEGDAWgBQAXTk+D+WqKl4t9q5oKq0z
+mz2bczAdBgNVHQ4EFgQU8p5RygFbuse22sy2ekGu4lIT1zQwDgYDVR0PAQH/BAQD
+AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAzANBgkqhkiG9w0BAQsFAAOCAQEA
+bXWDCbc7hJbeoWLcbO9gVwLftrtj68acV7Z+Jq0giW79OirTxTOZz9qmrkHiVZ+M
+l5EdyY8TYchJBzxztll0mpbCc8j4tdin6H7I5X6/+RnTp3OBN6yln9X9Ap1iJTzA
+t8y0K0LR55ytAMboQBvv7Qzd5AaWV3LP5Ue1QbrSMBwy5CBeUz6wKktrgzXUn/UM
+Nmuf01iaEAt/GbhrSxC4EaUIF3P3H1u/TI/8Jw3uKdKnCMl1I/FGxeJyQL5CqJ9a
+jFoZCpRcYKFItuPzr3HIpcjqaiZTB/qJXCLOQr4Vc2HAIOtt/eV2FXIc3pgqi87p
+wojndjN58Fvx90EZIkOiMg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CD A2 F4 2B 63 C8 3E C1 A4 26 1B 31 5F A7 8C 6B EB 6A B7 B5
+ friendlyName: Invalid Policy Mapping Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7784074D4170A74D
+
+QuOusDv3vk1IUQEPwqV+p8unoJTsvfgFwSOgKI4keWDWGC8v8jlcKduJkHrDAGmk
+X4oBRY82mcMjOtD7VvYVSvGkdVUPz/CQF6FdUNCpzTR9DrZHDO3dYnqNZfO6xFd0
+ZTa8HYiiiM7/NOb6Vjms/1HVg2dw3gWcUaiX4o27JYoEi3VvggMAv2W021HHGlud
+ppHw/RvY+VhLZsLT/JfgF5NvSUP/n2nkKvej+mFwuwuRRqp6TNqlwOF4iAgtiCWX
+fqdq8/XWmyvGf43M/n1Ipz/q4zQxIzNrq/ZNN7C255cQGKVf8n0H7b5zxoQcLDGz
+odVr16t01X/PM+i/wJiph1BcY/xYRXGkIGpu8l/JfGx7rwZCS4IhaEHnjOzosrnH
+U2wGuVkC+AVBBCz0dQzEcqm38TRl/c/8c+lrepDpY5H9WsMAfo7fBKPT2FyO0Diw
+G8PX6NDyEsE0L41Wbqpob7gmyApNmF5iH3LPTuLapXw0OQiwEj3KyBf6ktSO0dCP
+/gP9k8FKqVmzuwGd7/1f4NoZxYEg1F7CODSAxKxPJphSHKeQi7e0SxqvT7AsEFqe
++BZ7crQ+B0+sSDsMbSzNUeX5tQFg8NyHs9IbbvSCeDV/8mF1T/xxlIlUs0A6YKAY
+IByqE4dYbVvIXKcLPUdDMHu9nIusna7tcgHk7MDzLqRs5JLADdQRyLe3zolRaAdr
+QJFLiE1yDdspJS5iyfeYr4fDzSs7wg5A+M9oF4JNTRarZgUMz8CBwowV5QY1XZS2
+8i2LMKUSC2iTwz9TwwnkaSQSJHf9Zc50iAn+BW5Sq3QgDUATEiRDmmXQfq7DiFQI
+BTM/INoyYA/BoqnV1Tn5iJLC9m2XGBUNH+PEwcyADC1Jjv6gqZOe8XMizMUcqKko
+0yZMERleSwvDOeTIctkiHLaEFUwYOQnnHd4KIJ3UZMt+9Ce/UnwZYQMV+mtMiYEH
+2j8BIOz51h1GLCPa8Lc1KRVHDwn8riBpugH77NL6XcfsiAI/1DpUG2u/hcnt8Tp4
+VZeMQT1ugJQUVQNxqRFrT8vvwyk5IsmgVa9RbSGmuIJk7dT3lDMFMmgEpEFDa+wH
+A5bL6y83zbYV5bzNjv8rHn0Vj0Zoo8dnkBva20OyPSlLAWH7Uo3D7TPIZNJ2PJwa
++6OlaVaPOQ/iEJqv20TqJ4qHkTynkt5dpJZDeXTzE1w6+6CABcWPdnE1bhdDTY3u
+Mrsw17n4gRnp/AXCgUZSg7dO49x4ZdNcsOQwIrmRrjXZ1vtX4nMaewN3e61KHc2H
+q6llFD1//0qLmWC8tAkW+jLDJalblJPo+BqjefGcp9ts6+/RnqR0jfDX8nTVNf9T
+alpIef//juR9V/nEloUQm28tvW26MDd6k3ESgs9qBWtofx/4TQ8hfF2T0Qg7dLfQ
+tQVcWcQQ2ZcPdv9rV5y80k/sCJpWvSZYkRb0pTHMtueD/GZg36XK9kLsbw6OermC
+DI6qNMIywpC527nYgx2ENnjAB53TCylfaOWrNaOfCrXnkmapGcwrv1kMNRClGCQV
+aXeDZEQhpWrCGLfpRanYDUvUJ1BFc1XvULQGSOH2+9viVWuFMdfF3vo0NZ3U27kD
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22.pem
deleted file mode 100644
index 074716e415..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqzCCAhSgAwIBAgIBQzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMabmFtZUNvbnN0
-cmFpbnRzIFJGQzgyMiBDQTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOYG
-d2HszTJIsVTazKriCUJ/ExxUo4U4HEZN9+/XVXsQVkZYIzWtyCTC3IFmSAyb9ZED
-Gu3jmF/evXpfNXmxiURUu6W0bLEpIkZiVpPpTKqoJx2EHj+wXOfe31AD0OmKidXP
-66+LVgIJLWGMr3Msbzb4T3gpKb2ynQc2/XnE3RkbAgMBAAGjgaYwgaMwHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFON/hXqOojue7rgS
-HXkTqsS9LlmtMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAnBgNVHR4BAf8EHTAboBkwF4EVLnRlc3RjZXJ0
-aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GBAJjXEGmrQ1/Muud+NZwajR9x
-it/32SNVvHI+/O7bopout/RnhJudrmsdqGlcSk0KXfcXI22cJOkAYe1M39znxgba
-VitYYLxfsS+3O2pLpMgQMFCZuOJATfAQUlui+dVtPTaIam7jimms5Qam2K2SuZ/t
-eJ2J/rIDHCOrIGktQS8H
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid RFC822 nameConstraints EE Certificate Test22
-issuer=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA1
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBSRkM4MjIgQ0ExMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-aDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMT0wOwYD
-VQQDEzRJbnZhbGlkIFJGQzgyMiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNh
-dGUgVGVzdDIyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ3Uy3P0KWoLsX
-XvhOf4ODgEJBTbtvW+xeevCGrTVdm3mG+1Lobp74rIRSpQShRCN+ltNnmEOHPIeJ
-YuV92pX3FQbBX9mz3ZgKznyb9qVBwysiyfX19PBeESDLn+O6Kcvl9XfUu3HdXMQP
-KA+UPU6txM1pbhkvRK5OSG/TBaRI+QIDAQABo4GWMIGTMB8GA1UdIwQYMBaAFON/
-hXqOojue7rgSHXkTqsS9LlmtMB0GA1UdDgQWBBT4EdpzVCY8SgosOEgawdqBAjYT
-5zAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCgGA1Ud
-EQQhMB+BHVRlc3QyMkVFQHRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEB
-BQUAA4GBAENRegfOIUdgTAhpzFZDtmSaJUrYqkW4ft0v2t+flv6Nf+uAjlYMXThj
-7Q4LUtevMKeoFkGX5gnGL7HKo0/QwTPETD0qTCYcQo9uw3SCdVie4kp7X0/w/rHo
-sNUMPAPe86k7l98/xN3/zO6P4o82pX4vp5xqgs5koOZKqExh8kzH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints RFC822 CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E3:7F:85:7A:8E:A2:3B:9E:EE:B8:12:1D:79:13:AA:C4:BD:2E:59:AD
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- b4:77:73:f7:12:e7:d7:20:9a:bd:e1:00:a8:b1:6a:7a:65:1e:
- 8e:56:c9:ca:38:33:7e:d5:37:41:c1:e7:95:a4:81:ab:9b:40:
- 31:1d:aa:6c:14:f9:19:e4:3f:85:6b:24:ff:d6:bf:cb:fd:27:
- a9:65:35:5c:b7:6b:82:87:b7:e1:c2:4d:34:ca:42:5c:46:66:
- 45:11:d2:c0:48:0f:08:8c:b0:a7:58:66:63:9d:ae:0a:68:0a:
- 5b:5b:ee:fe:12:93:77:03:90:6e:a4:8d:32:2e:56:56:cf:1f:
- 85:b8:95:52:f7:73:78:5e:d0:04:66:2c:8c:ca:78:36:da:43:
- 10:07
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBS
-RkM4MjIgQ0ExFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBTjf4V6jqI7nu64Eh15E6rEvS5ZrTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQC0d3P3EufXIJq94QCosWp6ZR6OVsnKODN+1TdBweeVpIGrm0Ax
-HapsFPkZ5D+FayT/1r/L/SepZTVct2uCh7fhwk00ykJcRmZFEdLASA8IjLCnWGZj
-na4KaApbW+7+EpN3A5BupI0yLlZWzx+FuJVS93N4XtAEZiyMyng22kMQBw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22EE.pem
new file mode 100644
index 0000000000..1cb3880747
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest22EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 79 FA B2 5A 2B 67 0B FA 4F F3 76 2A BF 0E F3 F3 06 C0 C2 8D
+ friendlyName: Invalid RFC822 nameConstraints Test22 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid RFC822 nameConstraints EE Certificate Test22
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA1
+-----BEGIN CERTIFICATE-----
+MIID0jCCArqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIFJGQzgyMiBDQTEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBtMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE9MDsGA1UEAxM0SW52YWxpZCBSRkM4MjIgbmFtZUNvbnN0cmFpbnRzIEVF
+IENlcnRpZmljYXRlIFRlc3QyMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBANL6mw8zfZFK7YonjGlE008qAPEdOsOk+EExeugqWGTUCv/Dq74SUVM5jDWf
+CsQtfPc/miyUEvcl5ep3fISwLriz3lSSQW3Qn5RzYJdpA5U4ahg4FKqMjNTqt9/2
+VAEsRiP3tdsyYREY1G0QT9ROpN95Cr6siEm2qVa2r4iPApydbxxYr2yR4uIk5HsY
+IZ5gnJvnrP68ibAoKrhVr0V5Y9bhsYEreS4LpBpHGwidcrN49vg3WhuRNFVhCNz7
+qgfAU2vnCJdWsE/4R4rlhmlm7uvorkDX2++YoOMKxS8Q7OreLzMHdDqAFMtjyj9C
+N+FEQZBku2asKYHBehARSa8nCL0CAwEAAaOBljCBkzAfBgNVHSMEGDAWgBTIao6x
+D0uqpYi4p4+R2+ozSujV4jAdBgNVHQ4EFgQUz4Q/P/5DzDB2OPkED44YfyyeisEw
+DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAoBgNVHREE
+ITAfgR1UZXN0MjJFRUB0ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkqhkiG9w0BAQsF
+AAOCAQEAAU/7LeKzJxvHV8Z871YW+xG1i2nsULXHrweWhaKU3u6L7HYNxvZJSHti
+9vhgqOBc8JyyIvu8GUCyqED7S0/VDalPwCysrbAJDNTfgxx2amlOp9gb2LBgpMVv
+EROwfwFsZhl486M57w8qK/PvRuVFDhm1+QhDm1q7boTU4+az+9DgX+UjBtWPPYGq
+nAMyH/0X9Abmkv7Tm9egKtVxe3ScjV1P0Ti385LaUVqIekrxjItWZIU8lMBgsbXV
+1jA3HKOwHNJGyL8D0TnoF/8Q2GRA4j747hHyz4bkSxnLi/GwTLb4ldEab87vzzOp
+tlNkycHkL4+iAMH1ZBHG5CnoVVmg6g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 79 FA B2 5A 2B 67 0B FA 4F F3 76 2A BF 0E F3 F3 06 C0 C2 8D
+ friendlyName: Invalid RFC822 nameConstraints Test22 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,55CCC16C61DECF36
+
+Xyu6redjnchvrC3oGfm0cnAJKK4XAWtzVg3aj7+4jh/7Gab9LDBBSzzoY9WFPKzi
+/FNaZotEfW4vgsTVGZk4HqI94RqX5CjAxbcrWivNVdc9whEsIOuEqKb8oYYfU1Q4
+ZA1Sv8UPfFOPKIw/IUyev7brY/BddG8zvbDqQNOYsZG3KhZ5s6n3i/taNhUmOWV8
+Oei/vLkW8SYjlaY2mgOohWmQQ9Pi449Tl0mX0Ng47cWCXqsy5k3AC8oQnyMMnQ4V
+FN+iDJyRePYNxTJRL6/7dAWAvlBRd4aL+4Qvwy/WAozfWWO6g/5/YOasbZph+Dav
+twZIgyV7QV410VRTNNA2ipqzSVl1/aPyq1Q15nS9GOa+HJMEuJUFjEl+q5Xa2lbt
+XeI/N77iJgmSWQvVuVyyr6azwiivDFL/Nq6RE00Vl938PgOnBiWwlik2VSzXuyD7
+ZbKgGpBt/hnF/mt3Vl71QW8FB9llffrYXvoBcAw/9mMeT5pt0lxKSTm619UdlAR7
+r2DB02VfWue58nhZ/UldpjkGVbALaCxlPavS8zi9Vhp3tIMrNX0K+BYY4vZhzgJZ
+HSw1png5MUqZVQQkSg6RuhW+cN9ZJWcmGZpvHKEOjRM6AG8qrsGc657Zg8D2eV+s
+S3w1ZssF2Eca9j2ZVdt+hDJ4yBZHDPgO+clM7oMqb0PP9LJSPHayFkrG2rtYniI3
+zwO/qrv+OuW1AIufZJtE3SQDjgf9sAcDi0iFcMtW7X748BvOKZJSDr7mgET8mPRS
+Zyt0RVKB/rvvajk1j5zgPncY4dQ1t+eNVtr5f4T6fZ2SwqfdDK/u11+PfJAL/owf
++yEHScSQm6EqOxLEdUli/H5QICT9yy5KkDgusc2yo8WDU2mqzdCEqq+0ZtA3hbZH
+33ZCqg+wfpGgMpxzSgOU1oFv4Fh+Pxenlj+GppLpX3STtDA/a/TaSeyHPyl+p2xX
+6k9heoiEPQRvD6PU9WMICMtjcvIOAdXBin4ImnpSOGOy2F6RTy2fbUIXN6qnWUU5
+5JOjoH+gr67lXOG3xDLViw5qLp9U3OyQlixU7ZdC7YlOEN2c4o4qWJGBfzIvN8Hj
+O3B5tBat+IxlozMLeWHmVwj1HsfkuKpw29ET4bh37vKGzU/U5cHNw+BSxlYoZjJ5
+7dtQjE+Nci1JWg927kpK8FnKuY7JxlW62l21S8MDHrCCgNVY6KTcU6YFbEVOWVhS
+WY588wAIR9bkMDq+mqinyHn6rV2jwoJR757vALTQOXG8F1XYpW5/axE203m/S0pq
+qWTLmY+IZP7xn7sApm0y4LTToBn/mb9VJ6xSkUWhwJfxbNtQDmkoBNwHwG2rABaT
+f5Q5hCrjzojFs4IvrALSj8WUJPTnsCUgr5MAXHVPdk0vFPhOaYDEKifFtKyDOOz5
+hM0p6PwdnbPin7UPM5gjXaVFqKzutZvIjUV4jWmMPylDGqXvD/HaPiVGg6a942bx
+T/cMrrCQEjm/LX6rkEpJnJJLWl1PDT7jIn9OXw22+j88QURqjbMHMiHxE8y3yMIP
+xUQNfSTPzbSP24llbuBfVYt2rcpIZ15dZ+b2sY2Wyga50SRu27FvThFzVvwVFfUq
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24.pem
deleted file mode 100644
index 10cf51c207..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBRDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMabmFtZUNvbnN0
-cmFpbnRzIFJGQzgyMiBDQTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMPZ
-S8+5+/2AgG2N8tsByPeKGxCC5bOrNXho0b3fSjvK452P3luNUPIf46KvIBU6UYAP
-4rGMqcUdmgFD+PdXq6TMW8bWNuYRICw6c6ni5uyre5bovptoJCsmBw/IqinDoqbO
-Qyoq0YDltds+lSROlTUCA/7qOBHOdwpcjhVfYJSJAgMBAAGjgaUwgaIwHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFBQbKzZmdEuTqzFV
-h6QxqzZjbzXJMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoBgwFoEUdGVzdGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAsOYxl05xGFDRHUO8Myp9EM/X
-ahfChzUabmgo1Tqpk+TLbxcZw+GfesxOp+jCd7jtTBJKhB0HeX1vaCVUpURbWEAt
-fuE35slQQr/c9dgwCw/JwBNdkFFT2z/73nDEN96rUK3GYs2OO8OJVMqdKb4iBUxH
-M/bZyCy4CB3+hthr4to=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid RFC822 nameConstraints EE Certificate Test24
-issuer=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA2
------BEGIN CERTIFICATE-----
-MIICzjCCAjegAwIBAgIBAjANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBSRkM4MjIgQ0EyMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-aDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMT0wOwYD
-VQQDEzRJbnZhbGlkIFJGQzgyMiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNh
-dGUgVGVzdDI0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqPW6bvTBs4Led
-75oTaGYT0mZgPeMvygJtDc882QlIF9vXBnhm4761p+ULe5iKwIWjfjyGva96UcKU
-bFfkfWeMxS+dDwb9v7pBjxCUMp9tTVWIFZDPZJTi/RpNCwPVSN9pE7JxoXKPHZsN
-20WcbrGJtUvvKFhei9eltGndiYkSrQIDAQABo4GhMIGeMB8GA1UdIwQYMBaAFBQb
-KzZmdEuTqzFVh6QxqzZjbzXJMB0GA1UdDgQWBBTyvLyqMRiaUCgziZZt9Dl46omW
-eDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMDMGA1Ud
-EQQsMCqBKFRlc3QyNEVFQG1haWxzZXJ2ZXIudGVzdGNlcnRpZmljYXRlcy5nb3Yw
-DQYJKoZIhvcNAQEFBQADgYEArrFpI+Kiy9ZDD8Q9WoEG1XixP5/icUu/fk+PYsad
-2fU9G82dE2gBtN0L/T5FqgYo7uMY8R/ZDptaB6l/exqrPIGsA7xvvOYBzO8sAPyS
-GZul8SmHmKX117/0ZhZ6Ln9vCMK/IablztFZ+LcEDvpldAu8ro/lW2XXgd/KLdY5
-m8g=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints RFC822 CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:14:1B:2B:36:66:74:4B:93:AB:31:55:87:A4:31:AB:36:63:6F:35:C9
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 47:93:cd:d6:9b:31:b0:dd:6a:d8:c4:e2:5e:3a:73:cd:2b:69:
- 5c:47:1a:75:56:6b:56:1c:a4:2f:c2:66:4c:6b:a4:9a:86:53:
- fb:26:39:3e:61:d2:14:1b:85:1e:9c:f0:1e:ac:c8:c1:73:a5:
- c3:29:1c:c6:12:21:08:4c:4a:5a:d6:1d:21:4e:eb:7d:16:14:
- a4:a8:18:07:2e:e9:31:ef:39:ce:f8:6e:2b:d7:09:c1:ad:be:
- 6a:c3:d8:46:24:95:12:ea:cf:2c:c6:84:50:bf:78:31:91:79:
- 35:8c:02:47:d1:11:0d:aa:55:34:22:d6:d4:a2:ac:be:b8:07:
- 60:3c
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBS
-RkM4MjIgQ0EyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBQUGys2ZnRLk6sxVYekMas2Y281yTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQBHk83WmzGw3WrYxOJeOnPNK2lcRxp1VmtWHKQvwmZMa6SahlP7
-Jjk+YdIUG4UenPAerMjBc6XDKRzGEiEITEpa1h0hTut9FhSkqBgHLukx7znO+G4r
-1wnBrb5qw9hGJJUS6s8sxoRQv3gxkXk1jAJH0RENqlU0ItbUoqy+uAdgPA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24EE.pem
new file mode 100644
index 0000000000..d17a9a393a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest24EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 33 67 FA 2A 63 B5 47 5E B4 8E 48 32 E1 20 9A E0 3E 2A A3 E5
+ friendlyName: Invalid RFC822 nameConstraints Test24 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid RFC822 nameConstraints EE Certificate Test24
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA2
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIFJGQzgyMiBDQTIwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBtMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE9MDsGA1UEAxM0SW52YWxpZCBSRkM4MjIgbmFtZUNvbnN0cmFpbnRzIEVF
+IENlcnRpZmljYXRlIFRlc3QyNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAO3QrhcrFnARNcuvNoKoiR9dNECwpiyjNYIMkr/sbcZQnnDHLTX+KgQf09Mm
+5DI6sXWmBwFlZCJYDP03ntCXO5thnb9X2fU5eYlsKivE/gPsasDXYjBCkhiztSzG
+n8P504ZOy/lfnn4AryvauvAnN/2PjPCoysWp5hUmSotCCbpu7i6MyLdjVx1slPbg
+W+nIthsZGIbo/6n4eXq70D+PA0fpnS47DLaT2wgmveiXE+493ilAE8LcQqhcHJo6
+Pw08KQtPo23Fpf3o3Kh5QWOPm8lw4AAE2A7btkYJr8LsN8hYF3EApmEjFelHI4wW
+3OpRe0FKh6l00rZzmWyrwom8nrMCAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBRRgM36
+SXJIPO0OTgvOzh9AZRJwoDAdBgNVHQ4EFgQUjKQ6o0y35k1d94MC6HLB+wAbONAw
+DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAzBgNVHREE
+LDAqgShUZXN0MjRFRUBtYWlsc2VydmVyLnRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0G
+CSqGSIb3DQEBCwUAA4IBAQAw+N6NgtahpWR9GAlOpTU6BDQ1jAUlL04btBcufBrr
+6QCBibzNfigkYBS014FyJ86qCj7JoRLjzyYP7C6PE3tKBXklxB1hwoqE6CdLL200
+amMPsWfORjIBp5vSC1m99pPUOVyxFJSFV4oRZQ752AoXEWXJj7qYlqL+3hdNdxjH
+xw1UQQITlsEYmPJSmhh/HrBXNB6+5rRxyu0uYo3y3f1B8khq10wSrQV5pXj1Jowk
+oZjjqd/pMUWWJU7UoJom9FdwKUZ9hhfEwL8pT75yVgZLvqoqGsqR/o3ni1NJ5LK0
+GST2v+jrlvs4riCqbFPRMk70Ix6UOoO3Psv2urfsxTx0
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 33 67 FA 2A 63 B5 47 5E B4 8E 48 32 E1 20 9A E0 3E 2A A3 E5
+ friendlyName: Invalid RFC822 nameConstraints Test24 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BC2846C0A372C848
+
+AOoji699wLDwE10c4MhSQDvO4d3D6IQwEESJ8cMXQwkQYJqgmLUf1xYbhpH0/+uu
+5CPbz5QcdyXuu50LnkTNXIkVfVC2Vx0w8Q9HuCZRQFjR+XQgRzzWC3LJkpTd5dy9
+OsMR9ZN2+TRvue8kFTt2zbV+JaHAWKOPQqx4+mEf9eI73jqIHhznjaNF+OaIfBB4
+t4BFo9yLDzabgD5WR15sQt/S1zzdm0jOZurcpB6gjlZMjjaMglynxeBR+JJIsf5L
+pGkC+AMP89ghoaNDMX3deD3x2pdZFGOQN9jVJzW7ambDl0ASQWqz9OROPwWxIU7K
+E5fmI2ZDizsKGo1+YE/3qeJwsNNEx2xMJDqjA3IeF4WcvEUmAcsEAPQ7awqH8Pwy
+u/cSLJqmwzN6F81VNX4u30VwR42pHqyKrGbHLHIDZxmbKvNx42zu9XzSTORIW6qj
+qouAQc3vz5NYs00S34llMvzNp+ncxEAmhEiF6YNjTBPnbYnBtXcGq/iDyU794j00
+T89FxT/4FT/gwbRugkEMYGZ6XqcGqoYRfYQANEZoUrVrzBEer+lrqMlz/IYvmktp
+3hbyZJAHpruaM3IdhDiEMWLABXqTZCu/nLal61nkhIFOWrmI+gAQ1rHFCRpwWgus
+mMLYAFyS3bve+M/vwSjmk3ZnjQ3J3TxhMSPGFPfdRSMo2hOY5ecw+f95am5zE4SB
+qhPekhGVtTiwfl2fafjHe08T8MNvM9rYMhgJqelqWmWSg3GSFEQ4svBBSAUOFnG7
+s2AzXvZesEiAhm/ocwmmWydgTUV2JGXC+WKC4O2LYNC/vJ8h47F9aoihYicwp/nE
+8QUlpcht+lOOKcVA5NeKbLDdKCbYiAqA85qW25Gzu7l3bAGboTo0IzyL1pe+GVrs
+sQgJLXXXn/xnh1A8KCEqr5KP8ZLEJk2rya0NQI+LFfUyomjGrrd7FZ1QXomBGTUJ
+mDqYqR4hwWHEPSPJ+jsV0TxdnlWgReeW5Ge1Ma2kj5UQz7GNZoCHRbFrMc81rMU7
+N30kI2UMo9yw/lN9G51GAVuq8tyZ6eEWG4xfCiBas0ilfyHlbkScmjbLQ6kh4YKg
+I3mAnJwqcBeF6AFIJB8T+ctp5IromVxW3qlZ/J1KlXUuszOqobGLoMzTIYMPwf/C
+SRZ9vwShbIqI1jr+nIsjaedUCmXGCFNDT4tqKryVZ6JBBYfDbFvYU66Q6lji3JIO
+ziDg250XZJYkpId7OcZlU1Cubh/onqSV534Ll9CJeLsBiXvarbn7bPtc5qE/h4by
+lZS/7YW1bmpxxerRFFuLBz+GhRVFUQ/NdQsvwinTQUbF5YF2YOHoq4rtwnuk079W
+f6yLLIJfycmtgIevnA8vhLk2zfwF+3eBXfHjT2c9bOOLItG+emBpiehmhiEzOHSP
+jFv7UaVlKUU4Pq8oer4rBvvvlIGK+DuI8HWhg93i1nEKvGWkaPVSmeLbbICGIdgH
+U6qIKB+fQJ8t+zQheYuOh9P5wn1Bs8OKcUFsYozfAkW/8bUJC85filjE0ClTTIUM
+m8AY8YcVBxNMQTF6KjxmL2FZOuNRzFMRoV+vll1XPUycub1HGn7xbE1tUpoo0Het
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26.pem
deleted file mode 100644
index 05b770b3f2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA3
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBRTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMabmFtZUNvbnN0
-cmFpbnRzIFJGQzgyMiBDQTMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMii
-1odFMCSlNLo+1reNBLAhQ3rkRllmPUUfznMkHE+tVOXNCuGNSPuCJPQNO5495PH/
-vsBZUVltMrhOpo00ibzoFrcLwaxj5Gmb8rNV/aPwDiRX8frLslhpw+QEjxMZKP8O
-bdOlItBR3dFauvxrwLz1DUUlG7aX/QoEtws/fE59AgMBAAGjgaUwgaIwHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFOq3bporCYA2Z2m1
-jdo1pYY9KXgcMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoRgwFoEUdGVzdGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAcyB2R0h4mQZ671JhQ0r6cmPF
-iaEHtdJL+REJT8yGWiERgT/2wh65vHtCierHK8+0aJ8Wy/nJzUAWcKeGESTPVTey
-IxQg08VdFJIohXm1lvJ3hfzgHIcFPk2tXZvYSk3qYllYHt8tGCoyh4p3q4vpyTou
-HcOOTD0ogzE9KbjD3Dk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid RFC822 nameConstraints EE Certificate Test26
-issuer=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA3
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBSRkM4MjIgQ0EzMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-aDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMT0wOwYD
-VQQDEzRJbnZhbGlkIFJGQzgyMiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNh
-dGUgVGVzdDI2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7jNtdzJgwipTJ
-BBs5x+7Zode/Av/i5gvFc0vC7CQSf8VCYp5gKT5H1lXopLZt6hYd0cr+IuDRVMCU
-ipwl1nRUgnh+5XOWwN83Eu4AVd8B/aAWOngoac5Th0S+Dm4jCE0MNgOEySMKDZEQ
-niPNQo8/t6RyIkKxWqVbIyazMwecSwIDAQABo4GWMIGTMB8GA1UdIwQYMBaAFOq3
-bporCYA2Z2m1jdo1pYY9KXgcMB0GA1UdDgQWBBSUvOjq7LDrQWg4ycgFgZma5kZn
-KjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCgGA1Ud
-EQQhMB+BHVRlc3QyNkVFQHRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEB
-BQUAA4GBAMNNCicEAT2nht/rinoSsxFccd2XKYncNITOUA/eKz2SqXcRPCimQjHn
-CEfGgdPU+/Sw47+dBQ2aFNUmGyJazLIdnx18TczXpVmTIcgyUQGWOkG+RdAeSn15
-kIsvSAdiDQuzrptYG9TvTicyLKcl+FuOCLN+uBJ5FutlSWvMNIpa
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints RFC822 CA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:EA:B7:6E:9A:2B:09:80:36:67:69:B5:8D:DA:35:A5:86:3D:29:78:1C
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8c:6d:0a:0a:c4:67:91:af:de:5d:89:9f:fc:df:e2:7a:7a:52:
- 3e:4d:ec:50:b9:46:83:3a:7d:2d:9b:5d:84:8b:6d:ba:bf:4b:
- 41:74:e3:3b:c1:90:73:a2:83:02:4f:e4:04:b8:b9:7a:70:7b:
- 0c:bc:59:f7:db:83:93:00:87:98:53:43:a2:71:d5:2f:d0:fe:
- 2f:c2:46:55:d5:64:54:01:90:72:4f:a2:37:dd:88:b8:3b:63:
- 24:df:d3:ed:7e:6d:da:2f:57:9b:cc:d7:96:67:48:7e:a5:b0:
- 6d:cb:c9:5e:e9:78:58:c6:be:f0:cc:b1:16:e3:4a:57:45:86:
- 90:12
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBS
-RkM4MjIgQ0EzFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBTqt26aKwmANmdptY3aNaWGPSl4HDAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQCMbQoKxGeRr95diZ/83+J6elI+TexQuUaDOn0tm12Ei226v0tB
-dOM7wZBzooMCT+QEuLl6cHsMvFn324OTAIeYU0OicdUv0P4vwkZV1WRUAZByT6I3
-3Yi4O2Mk39Ptfm3aL1ebzNeWZ0h+pbBty8le6XhYxr7wzLEW40pXRYaQEg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26EE.pem
new file mode 100644
index 0000000000..6922557d6d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRFC822nameConstraintsTest26EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 96 5F 97 3D 72 E1 88 14 07 36 12 E7 DA 47 93 EE 6A D1 1D 01
+ friendlyName: Invalid RFC822 nameConstraints Test26 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid RFC822 nameConstraints EE Certificate Test26
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA3
+-----BEGIN CERTIFICATE-----
+MIID0jCCArqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIFJGQzgyMiBDQTMwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBtMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE9MDsGA1UEAxM0SW52YWxpZCBSRkM4MjIgbmFtZUNvbnN0cmFpbnRzIEVF
+IENlcnRpZmljYXRlIFRlc3QyNjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAOPaHJrQm/Kqqf/4/xBLsdQP9fekUUNe2JiuIA3XdwLgabu6paTFdV5jVcR/
+imqnAWJ8Wx2IBlfy6li6la4rhHrc0aU1T2mmiqXcbFyxnslvKsPTOevBh++PfbLx
+zP+NkPl8tA6W33/oLnCQsDBYmqdZiLrjL5hZStWAq0YugLKE2HSjRorXTRT6Ged9
+xwawSrbCsG2RRP5+jJtvtu/AhCjx+75mVBsBinhlDN10/7TNmwA1hYNQ1BBiszxZ
+PuWkI72jCjsJtI4uG5Ds9B4FzWMLjCRMS/eCO4/wX3WbeQHzHsTbPg+qsgo4kElv
+XvInxXNc7ZJH8UC1WfKbryDd4L0CAwEAAaOBljCBkzAfBgNVHSMEGDAWgBSaujlN
+2iF1r+pBwzxsUdioRal/ozAdBgNVHQ4EFgQUImSefsikOFzboCbTld2bd2ooI/cw
+DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAoBgNVHREE
+ITAfgR1UZXN0MjZFRUB0ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkqhkiG9w0BAQsF
+AAOCAQEAXr9hF23UlbewDYWKUwzUTOrAUaEQ3SiN8f+D9c0bX0S61RUZWDcsiqVb
+pThRuIamdDPEPoyxOSJOGNHKJc/mIixymmnjDRwSCho+FvbI75T710aOecpmrQ8k
+IymBEXfebP9GXc1jQxi0tDKYpv4avAz1zMnKs4JLxiUYftwiQd99JizQKnG9bqsS
+M2Ogn1QWsZRzW/YZD8i4k69WQIV/a4M45b510y/qHU6T5U61JO/EXiEJPxsjOwta
+W613Q0ow022r4b7pTyU8gKyDgi0sgF6k2GL+cD9Q0+rcFwT8w0OQlynq5yM9n1Dp
+gHWSV1lpJjz1R59LX1j77NESaDhDyw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 96 5F 97 3D 72 E1 88 14 07 36 12 E7 DA 47 93 EE 6A D1 1D 01
+ friendlyName: Invalid RFC822 nameConstraints Test26 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4C6FCE24D6C96FB8
+
+wMA3pyp1K7bxUCEYDMA6/xklluUcN7LlYpYddtOz0PvbskbEANGyd3jWAdQDGDJv
+LZvSGYXEVYgXKO1kZJC27wGisYnnN1XpgiBrg3I84Uh34FB2iVioAK7Ngs4gaW7Z
+uPysTJSmurhCmp2HQ5p0hIHxtUsC1jVV8Un3lsnVlNVB2uWYXilqqb+9cJXL498o
+SdMn4R/F7/m5MipDlk12dBJQywbSlEj0tVR3MPxadpZRgMT6URFQEHbdqtLYE25m
+9DzFMuSQNQIDi5CPV9s2RLsHXUgGMhWDAMsNem7SXDkZ/0F95BIBtRLXtrVxp8Jf
+8lZV7+ndJlI+6Nx9dup366O6ogb4wQUZ0B9JNLJLy2n58CV3UQq4nz04fCZGg/M8
+vwFRxF9SAwsKstrm7+5CIK5hSriApS7W2QnKA0SyRcl4OkCBKCEya5OsIHuW+H4H
+LGo2NMbo6HKxIRuT2mvSH3EhIRQ/EJHsd9vsUQOB1ax6ZUT9GmUsdllntbnwJo3r
+bzhQ65PI/xe3lc7GU3NQylQjDND/RtS3ZahxRFFlPxD+vn4geVpdQDfjCSq9hoJy
+Kxjzzzt8aZKfKFAZoL/cuvN2c4KzRCjSIfPGhgeUg2g/rCYrFc3RrqaA8u4H5B4O
+hhGEca8g6oxwKNFICFOo4Oq/BE9u/HDXx/Fr30sPD5WbsqvwP3oa458Yjg5Sp2+2
+xvufYBFd09mVqSDn1VCaBEM7xUhs8ncRD2v4aklYS0ByBQSadL7xKvwsnPwD/d8i
+6nlPQvcDz2Lk9d+pmrJWBxMvfYxvl7H3z+GUJV3acVXamTr6Ju0xBZRHctrEDRId
+MDWXdy8ILy9mSD8RwAA+VV+YGUJ4XBTONGP2lb4tLcYIphXhTbm9jlI2Ey1IR334
+y4+LsYku5l8zUz6fqDVnZUbYfMxQ2gnlKUsD6SM26eRYdcG6QSheh8VoPQz6aM8s
+5Z1FLVCHr9HKKeAar8DtOwp1lfRRgCk0iG4bTzh4OwFGdR64rUZe6BnmH9F6C6PE
+jjm6G686fCIbuw22gM8DAE48XoA00rL3F2JjfiC1n8C1JqYFAVosU+LVAS10mbcf
+eWNCj81sknWtP25KZAKx8VJT6p1pYPGIYSYCQIMdxkSggXGvCMuRUmZ9RrBd+Ag4
+IpVOB8So5wWnwu7xX7/gcJMNepE9b/Iwr4bO+hbe2eycFrSSWZwfOD0IUCwMbVkR
+v/0D1QVOajeAA2Ns7WJ27ir579jR2CznW5Dpea2CbCw35CxlIwAxw+LJJqWZMX/F
+gj5DA0lFbch6XNgApfxoqOQeKRekjgghSLN6AnnIqYW/47FKdXWWYpmiY3rKfPOR
+vpG9liCJnNswSxV8TeV5zg9fFaR6Yn9Zu3AO8xbw9ZDG4tzUF+PDpnirhqFaqEaq
+2hXly5xFm7lhZ70l6v/POq6YEy6HIYFd7zI5yapB3Xk82fdP+ZbgktglT2Q94EgL
+SHW14KgNwT7XwgIJoYNVMVGK0QacrAB6wkyWk+hu7bfEr1asHRXGsVEwYJBBtcmK
+hjwDVnruEiH/GGhwnN1Xel4yL/ZBWCs0K+EomCXrlScm2Dq6KqDCWDArIKxiVLKZ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest3.pem
deleted file mode 100644
index 1b70f7cd0f..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest3.pem
+++ /dev/null
@@ -1,262 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid requireExplicitPolicy EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 subsubsubCA
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTInJlcXVpcmVFeHBs
-aWNpdFBvbGljeTQgc3Vic3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBmMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxOzA5BgNVBAMTMkludmFsaWQgcmVxdWlyZUV4cGxpY2l0UG9saWN5IEVFIENl
-cnRpZmljYXRlIFRlc3QzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFGGwB
-xudAxGlVkjikIYygmyMRqHU1E/QoVNlt9Ebezg0wLbnUUkCIPw2HMIMfbDIHeaJN
-eOaIwT3f4QVMET9H4tp5gWQOKRBl8Lj3Qted/du3ZnX85zwGimmHpE5HPLUus1xJ
-FEDvx8tiCGFe/MThjl7mwPANLHMWEQN0JqJhNwIDAQABo1IwUDAfBgNVHSMEGDAW
-gBT3hCvdsfuVH7p6WmLgczEWsirIeTAdBgNVHQ4EFgQUT4ePIvuBwyFLywgAVQDh
-kO/dvOwwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBBQUAA4GBAJkkSBpAtETJ
-/dkW/B+frVBgw9yRjQ5r03xtGarbShYju5enZfbWEg2t8HkbDzyw3b0Upp8GcSyX
-zrbFBiGyo2hxjN8U6j5w+MCd9NJtGEW1C2O8m3S2uP44Zi0rTALMCI1thhoiDezC
-+To+oSu15R1fOkNPNHwlpaFpryy8ZJM2
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 CA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTQgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBQ
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNV
-BAMTHHJlcXVpcmVFeHBsaWNpdFBvbGljeTQgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBAKa5BuVP6ndJvlLbsZTTbB4nvZWYbY2Ihc7C5sly521U1EBj
-aLheGs9ObXh32aFJ3kZQuAj8VpBEakL9zChjwFkBU7dEWO9OQFf8NV+RD01i6c7g
-NquatLdDUmTvS16/E23aZBNa9jDAQ4nQffOf/cx06GbvOBF80dnNnM8TXve5AgMB
-AAGjfDB6MB8GA1UdIwQYMBaAFCV+kLQN0LLzwRNH8EF577JC5jX7MB0GA1UdDgQW
-BBQjYThxLAlhvqK819WJ1thQPr3rxTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-gYEAzVx4zKfg2OZPg4KGdTVJSzYGD69T0AfuFdTI101IvDNbKuc2SEmpmul33Px4
-z5gMKCZsIpsVXzf4rm6kuxl89PofVdztUuHIivKy5gr4iBt07YDmUNZZfl86CPoF
-7aARp2XRQ0rJCbF1RU0YVWZRyn//oFYyY49Bq1aDelri0WM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBLDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5NCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5LYa
-vXx/4T4pOwg2eV0ZZmBRTcjTivfmUhGf4t3BjAXalsDsWFkwmVCVg0jnQW4iuT3s
-a3lq9JO4ZUMcejACcPBO0AyXyrTo6DjXDy7Snf89AIpyDx/ct/WqvnO07ceHwTDO
-CZY11pYLMerONqANweAyCKsio69S35piBx1QqmcCAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUJX6QtA3QsvPBE0fw
-QXnvskLmNfswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQQwDQYJKoZIhvcNAQEF
-BQADgYEAPUNGMb0+cubTj0DAP3jW3mlPGZeGtc6jDLe/Fdrf30Au88GX5G2FJTql
-/I7wFlUgHTGQyHF3Zad9Qfzf6+dO0j9RhlEqgCk5+FqFsboPQ9E8rtCrABUUuovD
-RgkPDAKZsSLR7uQBUDgk0A3OqN1UpiMKKxFz1O1ya8u1DgGWxJU=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 subsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 subCA
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTQgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBTMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAm
-BgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBvbGljeTQgc3Vic3ViQ0EwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBANF3obVmdl9+Tj44uOFKTDkrdPu/AlUyitHu0YQC
-vsUY7GjYy3dKjm70g7hQfnCtA3XIwm3H1a36Wo41R0Dvj8QJ/8qPhQNejONRzBzB
-jnXx2Lr+bfh3zxebwgUmDyzCkPXj8tjFerVTpxc8aAgfWcSLD6xK9h5OtKy17aME
-zZ9zAgMBAAGjfDB6MB8GA1UdIwQYMBaAFCNhOHEsCWG+orzX1YnW2FA+vevFMB0G
-A1UdDgQWBBS+bKwACUxTlLgb5MIRkSOlqwdjCDAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
-AQEFBQADgYEAF1/+ajWFOu2Im9slgmi4YnPnqk5oWYqOrOh3yAR44wEchHfHD74/
-ed+jlGZewF+V4QotdYoG8dnld7lbYZzkdtTxcOUr4k/aUgml3yTeb5O8rBXNXytN
-JqEKXEp/ggaG4rKzUyA8zwYm9fIjG1jL0KU/1L9JSMzmwJAmR6aIq0Q=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 subsubsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy4 subsubCA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBs
-aWNpdFBvbGljeTQgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-KzApBgNVBAMTInJlcXVpcmVFeHBsaWNpdFBvbGljeTQgc3Vic3Vic3ViQ0EwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALjYqyTd452AWgD9QeSfn+Exc56nVJkK
-dx0FEleM5YEqeEUl33GTd7FRwtkYdznsQzeFYOWbWluYE5Gl3DapcqpMlu2PQmo6
-dZMbzh1Bi2yahE1wWmY15NSjOz3TFAJBZRZk0PgxvohpdPP8LLCwA9zQUlTnpG7D
-LBESzn390XCLAgMBAAGjfDB6MB8GA1UdIwQYMBaAFL5srAAJTFOUuBvkwhGRI6Wr
-B2MIMB0GA1UdDgQWBBT3hCvdsfuVH7p6WmLgczEWsirIeTAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEFBQADgYEAJzvxMRdZl5IWypM7YNiMcWqk7GpMuRvozUyoRQq8cA+z
-fdskZk75lh97jsW2RFnP/fyA30/5NAfVuD2R8+TqJaF28jgHOnU/6qTcM5sxnRJ0
-h+icRKt6II8LNfWUQ1zv+pBxfuy/yOrYpw7/7ba2Zeson/cLpa0dhLFNCGEkfbs=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy4 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:25:7E:90:B4:0D:D0:B2:F3:C1:13:47:F0:41:79:EF:B2:42:E6:35:FB
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 98:e7:69:c4:4c:c3:6b:08:80:30:4c:81:3c:d8:b3:06:88:91:
- e8:a3:c5:d3:c0:35:51:35:f0:16:8e:38:0f:b3:e6:26:20:d1:
- 45:39:1a:a9:08:be:f0:5f:e1:00:8c:a6:91:54:ff:ec:32:bd:
- e2:17:92:a3:41:f3:c0:fc:e0:84:86:54:18:ff:b5:89:9d:15:
- e9:a9:92:a8:96:a7:4e:97:02:2e:d5:e5:e5:f7:70:5a:1e:5d:
- d2:6f:40:34:f5:c6:63:65:5b:85:c9:b7:6a:4b:60:5a:76:35:
- 12:01:1c:80:59:9a:d3:1a:a7:27:7d:f4:f8:00:ea:b7:f1:3a:
- 62:e6
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTQgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFCV+kLQN0LLzwRNH8EF577JC5jX7MAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAJjnacRMw2sIgDBMgTzYswaIkeijxdPANVE18BaOOA+z5iYg0UU5
-GqkIvvBf4QCMppFU/+wyveIXkqNB88D84ISGVBj/tYmdFempkqiWp06XAi7V5eX3
-cFoeXdJvQDT1xmNlW4XJt2pLYFp2NRIBHIBZmtMapyd99PgA6rfxOmLm
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy4 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:23:61:38:71:2C:09:61:BE:A2:BC:D7:D5:89:D6:D8:50:3E:BD:EB:C5
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a3:9c:67:02:44:57:a0:9d:d2:78:46:fb:e7:76:bb:66:cc:60:
- 1c:2c:7a:7e:d6:ec:a4:c2:4d:2c:51:8a:97:1a:e2:c2:7a:0e:
- e7:7b:4d:79:49:c2:6c:a2:b7:a5:e1:74:64:9a:03:f5:7a:5d:
- cc:18:2e:25:dd:a2:fd:84:03:ae:d8:cf:1d:17:ea:fa:59:77:
- 9e:22:3b:7e:97:f5:74:12:34:71:c1:10:6a:4b:03:6e:92:d0:
- a9:6d:cd:ca:5f:69:7f:c8:b0:b5:97:78:5f:14:b1:34:d3:30:
- 09:36:f3:03:2e:dd:01:52:33:61:2c:8d:cf:74:01:71:47:9e:
- f4:66
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTQgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFCNhOHEsCWG+orzX1YnW2FA+vevFMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAKOcZwJEV6Cd0nhG++d2u2bMYBwsen7W7KTCTSxRipca4sJ6
-Dud7TXlJwmyit6XhdGSaA/V6XcwYLiXdov2EA67Yzx0X6vpZd54iO36X9XQSNHHB
-EGpLA26S0KltzcpfaX/IsLWXeF8UsTTTMAk28wMu3QFSM2Esjc90AXFHnvRm
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy4 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:BE:6C:AC:00:09:4C:53:94:B8:1B:E4:C2:11:91:23:A5:AB:07:63:08
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 84:fa:09:1f:fe:84:d0:14:26:86:5c:37:6b:2c:31:aa:04:7a:
- 22:84:ec:b0:df:99:15:99:f0:b7:e9:d6:fc:70:9a:8f:4f:50:
- d5:24:28:0b:12:79:90:85:69:a3:56:ca:0e:16:79:5e:77:d3:
- 7a:62:9f:14:58:8a:d5:7d:de:e2:6f:a4:0f:d1:2e:27:ec:25:
- 82:a2:91:67:0b:44:39:cc:b2:e5:21:49:ac:25:2c:91:df:33:
- 95:1d:08:6e:ab:8d:8b:fc:2a:59:7b:8d:5d:c2:68:90:c2:a7:
- 06:00:26:e0:cd:40:6e:f3:37:1f:37:61:f6:6a:50:a1:dd:92:
- 53:fe
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBv
-bGljeTQgc3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFL5srAAJTFOUuBvkwhGRI6WrB2MIMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBAIT6CR/+hNAUJoZcN2ssMaoEeiKE7LDfmRWZ8Lfp1vxw
-mo9PUNUkKAsSeZCFaaNWyg4WeV5303pinxRYitV93uJvpA/RLifsJYKikWcLRDnM
-suUhSawlLJHfM5UdCG6rjYv8Kll7jV3CaJDCpwYAJuDNQG7zNx83YfZqUKHdklP+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy4 subsubsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F7:84:2B:DD:B1:FB:95:1F:BA:7A:5A:62:E0:73:31:16:B2:2A:C8:79
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 05:e0:f0:e8:75:5d:d6:4f:dc:29:ea:db:22:b6:bb:72:13:f1:
- ff:b5:e0:03:31:9c:64:d9:3b:2b:4d:78:f7:5e:ab:0b:e5:82:
- 13:7e:61:18:95:79:42:bb:9d:56:78:dd:9a:01:92:5e:0b:e8:
- fa:78:b3:b3:e2:4a:9e:d7:d1:30:60:03:7d:31:e4:04:13:61:
- a0:de:ac:e9:0e:a0:97:16:aa:03:81:40:56:de:36:a8:e2:13:
- 45:f6:08:72:c2:4e:d3:2d:55:25:9e:0c:dd:da:40:82:d8:75:
- 01:44:75:35:92:92:fc:79:bb:d8:b1:54:83:7f:ff:13:da:df:
- 11:ea
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTInJlcXVpcmVFeHBsaWNpdFBv
-bGljeTQgc3Vic3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFPeEK92x+5UfunpaYuBzMRayKsh5MAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAAXg8Oh1XdZP3Cnq2yK2u3IT8f+14AMxnGTZOytN
-ePdeqwvlghN+YRiVeUK7nVZ43ZoBkl4L6Pp4s7PiSp7X0TBgA30x5AQTYaDerOkO
-oJcWqgOBQFbeNqjiE0X2CHLCTtMtVSWeDN3aQILYdQFEdTWSkvx5u9ixVIN//xPa
-3xHq
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest5.pem
deleted file mode 100644
index 8eccc6c3b0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRequireExplicitPolicyTest5.pem
+++ /dev/null
@@ -1,266 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid requireExplicitPolicy EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 subsubsubCARE2RE4
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBcMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMTAvBgNVBAMTKHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTcgc3Vic3Vic3ViQ0FSRTJSRTQwHhcNMDEwNDE5MTQ1NzIwWhcN
-MTEwNDE5MTQ1NzIwWjBmMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0
-aWZpY2F0ZXMxOzA5BgNVBAMTMkludmFsaWQgcmVxdWlyZUV4cGxpY2l0UG9saWN5
-IEVFIENlcnRpZmljYXRlIFRlc3Q1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQCg0lngplHQSomxVxizv8r33zMQpbWDB+H13FvEhgFq5KE02tWBVkz7vXAr2hXP
-Y7LVgaGSQIOZqHrbMR+Izv57cGr+79ResVXZ4ulw8qxCgVrA/1Bty6kmyvQiyQZ/
-1z8EARO+Mu2R/XgSx2uCasNmLtgo3Stuop+2coLPfwqW9QIDAQABo1IwUDAfBgNV
-HSMEGDAWgBTnAqvOKOVo6WoEaT4ppTZjcAShmjAdBgNVHQ4EFgQUUj/qKg3WunpK
-bbAcCDrHDB8Awg8wDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBBQUAA4GBAAZO
-rTXTH1bBaJ1hKzh+NWBuI+gHfWUhVlxs3mgw4oCtqqhrbDCBQwA+D5sN/91EPODR
-oEUqrZbyUgTQWas37LqDXhoxm9uvX0Z3521iA5pwllvHgtmrNpPxNE1ylbIT5lLa
-927kjS03tbzpOlbvFj/OTmh4yyPaeL2oJyvDaC3X
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBLjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5NyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoN8Q
-UsSTUjVJGaxxoQdGouge30kgdc3+9+sup5NAWj8oyZQiGa/FlrayJlgnNXIO5xbA
-Foe3dhwCEAfsrDIofXlPacb6W9dTxdlh3GwG4GJY9gvfuVfkEb4EaYVyU8J+tmPq
-WDI/P7B03nMhQNNChUFIcuBKaAzDRwqIIGd5I7cCAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnSIV59sBcIhO8mIv
-cMu1wc0QTk0wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQcwDQYJKoZIhvcNAQEF
-BQADgYEAL+ADYS2dJuo7zZ5LoNXv2wNfJcyaTU25ajW4jvi4dN4jwEPgqCfrQ1Vy
-lf1YHDAzKYc6nIZnG031PEqEFTZmuXCcngo+CFmOpT3O8WOb/vHVolb6Cd5MhCZj
-AWkQgkXQ7HW3nIEkPFqNC5ljPrmRkGtu1MjN5jAq70iztFF1hpw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 subCARE2
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 CA
------BEGIN CERTIFICATE-----
-MIICpTCCAg6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTcgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBT
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNV
-BAMTH3JlcXVpcmVFeHBsaWNpdFBvbGljeTcgc3ViQ0FSRTIwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBAN8u+z8KfD1wxuMq85cY2R9ISBwrx0kSTvHcxkgfd8Hh
-/aOd/f5SUqPS0TsXeUJZ4491ildJLBmeyOsaMXfR1wUCjs1GzCTV2lwmHy1v8TEA
-Y8Zk77Z0xk7JM+Qa6sYNBQDvcqMerys/5ky8Lvqentpzs/rW1L3SBQYg2PfJX3S9
-AgMBAAGjgY4wgYswHwYDVR0jBBgwFoAUnSIV59sBcIhO8mIvcMu1wc0QTk0wHQYD
-VR0OBBYEFOtoCcblL8PzCgZRS7NYc5w5GD9LMA4GA1UdDwEB/wQEAwIBBjAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8E
-BTADgAECMA0GCSqGSIb3DQEBBQUAA4GBACFHfp/nuX3TO1xb40P5+iKE+BZPRduA
-ftJoYKvefkbjxlmMHoUdIUcntVLAyhaJlW797m/y+C+FDfkqtbBUFDjycGuAmFgA
-y59FSYCF8j4X1ghg+neMHyCzvkhN2IokMmzt3IITVLINy17XKITOwuMtJJSaR34A
-e0IQMPlYYnGK
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 subsubsubCARE2RE4
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 subsubCARE2RE4
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTcgc3Vic3ViQ0FSRTJSRTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEw
-NDE5MTQ1NzIwWjBcMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZp
-Y2F0ZXMxMTAvBgNVBAMTKHJlcXVpcmVFeHBsaWNpdFBvbGljeTcgc3Vic3Vic3Vi
-Q0FSRTJSRTQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALo8WG8R0uWydjHS
-XfEB/PfNI/TnhECaPZoH2W5ht/eblnw1w1zAJGFgDQt3USnxkZvjIa/Eud0VJ3KP
-1WFyD2IA40YtxHQsVTWF608T2eRLc1URZ23e/C7Op7EiXdo+YoJ7KwhiUyhNxxS6
-oIa1OQlAEOurYT7cU1BSxe4X+oY5AgMBAAGjfDB6MB8GA1UdIwQYMBaAFMsSDLuK
-o5HnMkT9UFBgNQkdakUmMB0GA1UdDgQWBBTnAqvOKOVo6WoEaT4ppTZjcAShmjAO
-BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB
-/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAR64KcgRdPGS/TLDzWJlnI2aOww1U
-eFC/9/IQbIeFS6Q6uwO58GzT7DdeGDwBiztdMcGMUx0z0HX9lTVEQu1zWMNnTWuz
-7LJPjucrwXeA/s2vhMTA44l0hgMIJjjiLDOJWm3/gI2DWh0HPOGCo/cRdLeXKiyO
-O9E/0IzZw84Ul+k=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 subsubCARE2RE4
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy7 subCARE2
------BEGIN CERTIFICATE-----
-MIICsTCCAhqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBs
-aWNpdFBvbGljeTcgc3ViQ0FSRTIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBZMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-LjAsBgNVBAMTJXJlcXVpcmVFeHBsaWNpdFBvbGljeTcgc3Vic3ViQ0FSRTJSRTQw
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALR5w4GO7XWupkCybIrksb86Qn9A
-XltnfkZIGhDabLaMyFOrnfcfJnh1RKKwqJfi8/pF7xDxJL301Qud+jUZc78vFUYT
-lMO6u7jmYYl6zLgoshCc4T95EMH8r/qoGx7U4S1o5B9maWm/Xrov12WP7mjPxeBb
-BmWY4BAPOQBt6gS9AgMBAAGjgY4wgYswHwYDVR0jBBgwFoAU62gJxuUvw/MKBlFL
-s1hznDkYP0swHQYDVR0OBBYEFMsSDLuKo5HnMkT9UFBgNQkdakUmMA4GA1UdDwEB
-/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
-/zAPBgNVHSQBAf8EBTADgAEEMA0GCSqGSIb3DQEBBQUAA4GBACwLeGO55YLNW2d9
-1sZkNe3ulFUkXCfVtxfO7FoO7gvCv9xKjnGOef+hnMFeLj5L4UtOUeekpnipm/51
-pi2QP8O9Vvwt6YtZ57t+ednuOPORQsvh/SaPSo7GT5H6ILwf4E/JaFiAtuwgYJQX
-D9YTw88ufWnBrPQ1yX8ReXseLZPN
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy7 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:22:15:E7:DB:01:70:88:4E:F2:62:2F:70:CB:B5:C1:CD:10:4E:4D
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 95:5b:d2:82:80:08:3a:f4:5f:8a:3a:63:b6:7e:46:e6:49:5f:
- d1:ea:1e:82:24:cf:15:80:4b:37:bd:f2:e4:b7:28:10:54:eb:
- 60:d8:3b:e5:be:a0:3e:38:70:aa:d0:7b:0e:98:99:55:9a:0c:
- 30:2e:8d:86:ce:65:a1:16:5d:60:55:e9:b4:af:c1:a2:df:cb:
- 63:c7:a3:45:82:85:87:4e:2c:7a:3b:52:e7:3f:37:0b:0b:8a:
- 41:f2:a8:e8:d9:db:2a:a9:e5:e8:50:4a:bc:f5:51:b2:47:fd:
- 8c:73:13:57:cf:97:35:dd:0f:08:a3:c7:cb:ac:2a:cb:53:0d:
- df:45
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTcgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFJ0iFefbAXCITvJiL3DLtcHNEE5NMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAJVb0oKACDr0X4o6Y7Z+RuZJX9HqHoIkzxWASze98uS3KBBU62DY
-O+W+oD44cKrQew6YmVWaDDAujYbOZaEWXWBV6bSvwaLfy2PHo0WChYdOLHo7Uuc/
-NwsLikHyqOjZ2yqp5ehQSrz1UbJH/YxzE1fPlzXdDwijx8usKstTDd9F
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy7 subCARE2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:EB:68:09:C6:E5:2F:C3:F3:0A:06:51:4B:B3:58:73:9C:39:18:3F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 00:dc:24:0a:9b:ba:25:d9:fb:09:b0:e6:d8:9c:61:d1:09:f9:
- f9:d8:09:86:fb:ea:e4:13:5a:c6:0e:0c:53:c6:e2:38:78:70:
- 1e:6f:39:25:5c:b5:4f:b7:5c:07:7c:1a:7f:b4:8e:0b:7a:b3:
- 6e:85:c9:88:9a:8d:07:d4:f2:8b:8d:e0:49:f0:86:7e:b7:2b:
- a2:be:c4:8d:e5:36:03:b4:47:3b:c1:8d:eb:8d:34:3e:a1:97:
- ce:97:10:84:e9:06:79:72:c1:a1:4c:7a:b3:78:99:97:01:1f:
- 90:cd:a4:ed:30:2c:df:36:64:46:ff:c1:0a:9d:61:26:89:c7:
- 40:b2
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBv
-bGljeTcgc3ViQ0FSRTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFOtoCcblL8PzCgZRS7NYc5w5GD9LMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBAADcJAqbuiXZ+wmw5ticYdEJ+fnYCYb76uQTWsYODFPG
-4jh4cB5vOSVctU+3XAd8Gn+0jgt6s26FyYiajQfU8ouN4Enwhn63K6K+xI3lNgO0
-RzvBjeuNND6hl86XEITpBnlywaFMerN4mZcBH5DNpO0wLN82ZEb/wQqdYSaJx0Cy
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy7 subsubCARE2RE4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:CB:12:0C:BB:8A:A3:91:E7:32:44:FD:50:50:60:35:09:1D:6A:45:26
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a6:50:12:5a:4a:b8:b4:85:a7:62:1c:b0:bf:67:05:d6:37:9f:
- 56:37:ff:51:90:9e:8e:f1:7a:27:03:e2:02:8d:2b:64:0f:fc:
- db:28:76:69:63:2c:36:63:48:43:12:3f:06:7b:29:87:cf:2d:
- 7a:05:9f:8b:03:3f:be:fd:e7:0f:fb:5c:19:fb:c1:35:b1:27:
- 17:dd:00:b4:10:70:f0:92:79:33:0b:05:89:8b:07:c1:96:2e:
- 72:03:00:ce:db:e7:a0:f6:05:69:15:e4:c7:7f:4a:ba:e7:ff:
- 9a:f0:6f:98:f9:e9:aa:df:d4:c4:7b:14:d6:1e:8d:a7:83:48:
- 33:a8
------BEGIN X509 CRL-----
-MIIBUjCBvAIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTcgc3Vic3ViQ0FSRTJSRTQXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFqgLzAtMB8GA1UdIwQYMBaAFMsSDLuKo5HnMkT9UFBgNQkdakUmMAoGA1UdFAQD
-AgEBMA0GCSqGSIb3DQEBBQUAA4GBAKZQElpKuLSFp2IcsL9nBdY3n1Y3/1GQno7x
-eicD4gKNK2QP/NsodmljLDZjSEMSPwZ7KYfPLXoFn4sDP7795w/7XBn7wTWxJxfd
-ALQQcPCSeTMLBYmLB8GWLnIDAM7b56D2BWkV5Md/Srrn/5rwb5j56arf1MR7FNYe
-jaeDSDOo
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy7 subsubsubCARE2RE4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E7:02:AB:CE:28:E5:68:E9:6A:04:69:3E:29:A5:36:63:70:04:A1:9A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 01:2e:d1:19:d1:46:60:25:13:6f:1e:9c:04:5b:c9:4f:6e:e2:
- fe:f6:3a:8c:eb:4d:50:cd:03:36:d9:aa:cf:ce:14:30:7e:8a:
- 0c:24:6d:67:63:c8:87:69:a4:1b:cd:86:aa:d2:3b:40:38:c9:
- f9:ff:19:47:8d:23:f1:3e:dc:f8:9f:d1:af:30:a5:47:59:cf:
- 8a:c2:0e:8f:2a:8c:9c:d9:78:63:5d:8c:cf:18:1c:79:fa:13:
- 0e:3e:f0:8e:0f:97:dc:67:28:af:5f:19:6d:01:87:e5:e0:26:
- 8d:03:8b:91:f5:69:f6:09:30:f8:5e:d0:79:e2:86:51:36:32:
- 1f:48
------BEGIN X509 CRL-----
-MIIBVTCBvwIBATANBgkqhkiG9w0BAQUFADBcMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMTAvBgNVBAMTKHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTcgc3Vic3Vic3ViQ0FSRTJSRTQXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0
-NTcyMFqgLzAtMB8GA1UdIwQYMBaAFOcCq84o5WjpagRpPimlNmNwBKGaMAoGA1Ud
-FAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAAEu0RnRRmAlE28enARbyU9u4v72Oozr
-TVDNAzbZqs/OFDB+igwkbWdjyIdppBvNhqrSO0A4yfn/GUeNI/E+3Pif0a8wpUdZ
-z4rCDo8qjJzZeGNdjM8YHHn6Ew4+8I4Pl9xnKK9fGW0Bh+XgJo0Di5H1afYJMPhe
-0HnihlE2Mh9I
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2.pem
deleted file mode 100644
index da9273524d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2.pem
+++ /dev/null
@@ -1,170 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Revoked subCA
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICbjCCAdegAwIBAgIBDjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBBMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMTDVJldm9rZWQgc3ViQ0Ew
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOOm11GxhTUrNTzIsGL2HeKkXDSY
-fuue6iKn5fTFuhHFBY9sABHgqkRwS7lT9J5OL+Li0oTfq3En9SzqPZ1pTG7nI0tc
-qo/XLks9e9E5GrdjiSPJSvcdETspZ4MKgNIeEQXyX/KqhvOlFuIkvQ6CkB26h0Ys
-ds/2NM1G2HIcqoGdAgMBAAGjfDB6MB8GA1UdIwQYMBaAFLcupoLLwsi8qHsnRNc1
-M9+aFZTHMB0GA1UdDgQWBBR49b1LlhuzLeZAUDLruLRHVAvySDAOBgNVHQ8BAf8E
-BAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8w
-DQYJKoZIhvcNAQEFBQADgYEAUGhyEOC1558EMH9u+aVPXS5vZ39mJh2Y719gMZiT
-OXDZsqIbxJ5npOYdL40yZD5vhio5mvpKFm0DtAmAQsp6SF5nTdj9Rn70rqQI0rdN
-9m7nF1ZRRL6YBRkSymloliboDsspsoZUSitT7yMtxcIocV9V0QxcGFSFw1i6W3/H
-OYw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Revoked CA Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=Revoked subCA
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMTDVJldm9rZWQgc3Vi
-Q0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBYMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEludmFsaWQg
-UmV2b2tlZCBDQSBDZXJ0aWZpY2F0ZSBUZXN0MjCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEA2aktQuUqYvrSvuQR0Y5vu/X29VQgITZB3a39NV5uIZXvWgUWyD1Q
-SGYbtu0YzKSDMzLAeuSgs9c6u4r1wTxno9XgzSJvcaupysi94Eeqqt3OCaJmLg5Z
-sV12741X6CqpUSZ6Tap8rsFqYspyzMExUZqJ0d1zszbDQ9uqfCan5ocCAwEAAaNr
-MGkwHwYDVR0jBBgwFoAUePW9S5Ybsy3mQFAy67i0R1QL8kgwHQYDVR0OBBYEFD7V
-xiNcO7bHOzxBFfhSNMhrEZnyMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEA3uoPgaDGPEy7AddpjA6a7Dm4
-3Mm2CcAZuFUSURGmmoYfaTQldWpf6ySCHr9t7vOm+7Gv607TPdqF1Gw0BU6DpC7h
-Et/uaN0/vE/XHxyYEi3Gfzx//aNgr9ZcDnhr6iGmVAAxjfSmVoq1SYvWo2cskAq1
-UO8Ub1+lilBTCeJDLTo=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Revoked subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:78:F5:BD:4B:96:1B:B3:2D:E6:40:50:32:EB:B8:B4:47:54:0B:F2:48
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 38:13:8b:21:ea:c4:2e:36:3b:d1:23:d0:aa:e8:87:13:62:4b:
- 63:07:14:68:8d:92:b1:00:5a:22:3a:99:5e:72:a7:92:01:41:
- b6:b0:85:f0:ff:48:ea:da:58:d2:77:26:c2:e1:56:52:69:45:
- ca:38:98:f5:ab:9d:1b:4c:fe:9a:30:64:58:64:e3:68:f7:a5:
- 3f:86:1c:ff:3a:82:bd:56:a7:a3:a2:5b:fb:f7:21:8d:14:98:
- 0d:00:3b:81:bc:09:3d:94:90:8c:df:4f:6b:14:b5:10:68:3c:
- 07:cf:e7:06:69:71:4c:0d:b1:7a:53:24:5c:49:8f:fa:05:05:
- 18:9a
------BEGIN X509 CRL-----
-MIIBOjCBpAIBATANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMTDVJldm9rZWQgc3ViQ0EXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFHj1vUuW
-G7Mt5kBQMuu4tEdUC/JIMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBADgT
-iyHqxC42O9Ej0KrohxNiS2MHFGiNkrEAWiI6mV5yp5IBQbawhfD/SOraWNJ3JsLh
-VlJpRco4mPWrnRtM/powZFhk42j3pT+GHP86gr1Wp6OiW/v3IY0UmA0AO4G8CT2U
-kIzfT2sUtRBoPAfP5wZpcUwNsXpTJFxJj/oFBRia
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2EE.pem
new file mode 100644
index 0000000000..b3ebd9f981
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedCATest2EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: F8 11 2E B1 BB 28 D9 92 63 FB 6C E9 A9 9E AD 87 A3 15 51 D5
+ friendlyName: Invalid Revoked CA Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Revoked CA Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=Revoked subCA
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEWMBQGA1UEAxMNUmV2b2tl
+ZCBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMF0xCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMS0wKwYDVQQD
+EyRJbnZhbGlkIFJldm9rZWQgQ0EgQ2VydGlmaWNhdGUgVGVzdDIwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ9Y5RCWTe1kcC0UDNMfNbMB7mhZg2IYyd
+wVIZ0H7zUCGeRgP+EnH5/lCL7F2FAUGgC6iYOY89bJ3a5/CsYyMXrO4iRqxM9kUt
+fGKJRTCYlOjuWEEOPzcFTo9bdrZk9k5oxwhAqk17m0IvPpoOTAIDKqLaoIz0gqyy
+ziEmaRRxGehXBLCgJwDA7zs1qRZPOiJ7LI8EIXm7l940eGUbU5Rs+XlA/YY/HeG2
+IfKKo9I/fCwV3kFTvYWiL0TCrRtKEyihLwytrpa+NsG2Pk+lHjtmXnRnDCzTkDF8
+g4BT+6WYI8puLUFxzOEpRhVUycH8S9FLP3Gfrkosc4fb0ZaE5O4PAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFJZvkpmg6XZ0u1/U+PsZ2c8dBaDvMB0GA1UdDgQWBBSsAecm
+BprTTYb0YInq5LHji2iDxjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBy+xF3B7mOc/clEsV/pqovLkjI
+iBu5SIcDpgbLDC4ob53X0xFC6EPo+FTkjVNBMZ6ICQOI+NWCHrhAe9NgfWivzORF
+dDiP/w4v7n7QL8XFug9+Ib+KKO98TSEAO0X9DY0YNyOHHO17Zo5Ev0sU7UuZ/3za
+9A7gG8P7Fjl1u53FnR6BT7S7pLmQabCEy+cVnN41giSUX82Wtc+VLo7AuOAxbXqE
+/fy6+/bvldsbMz9KcgoG5Qdj6E6nVyaENDaJe7eWZhfLeXKb905YkqXU4H0T8bLM
+YA9BW15DSOhrylXqLHIg+pa79+ujLyqlw9Xz9shQQedLz4y4nf8DbjmYa/nA
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F8 11 2E B1 BB 28 D9 92 63 FB 6C E9 A9 9E AD 87 A3 15 51 D5
+ friendlyName: Invalid Revoked CA Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,10B18725F104434C
+
+G1BIGWw8PiMynohCHUCkVX8obnqxs7hNDvjaAjqm70Tyli2vUjjH+o0IR2liO0VC
+2F2ecwJZUBuLGWGkd/8N1lXW2ishF0Y/7AtJGpOoUpH9kgRyShNbjIJzkBSDhxtP
+x3Uh6jJ7i64YnWdaW2/Cfm9s3SXYT9DJ4HJVohFosnLCKimaEdAfM0ui9OD+/kYU
+zsGqcXAqQ4St6oXmwPqcVbv1UP4+sLO+VQrddFvJbs8hkZpI2eoSo7LD+axsC+Tx
+fa0cRuregZlRm/xIKobBkdEeLANUszDcWKKNGNPa/ywX9brgkQlzS7vTUrZdeVKU
+/rLuQTjoh34h1NdZkux4LsdWnbff/TK3twj2Ge/ZsdmS6Sq9wKniqQDE+LUUlj+k
+BeL6jjxAsd36cTUWTDTU/zmCFoFjhQteSK1ldY+PWK59cQS13tawvn98I1FWz/83
+Q6O6bfzB3/8v5DDx6TPv37IuwN82WNxWPYyy/tFx8rlW5jHIxmP1foTnxgeQSDx9
+8lukOJJjPt0byE/pNcJbdfaU5mOOwsaXPiYrvCN36kQkPxWTrN6zqv+AXpU55r2N
+DB3oA1MS4FghmQjXr6uDA1ugmN3xQEJl7/biNdPk9TL/5ur38tJ2utb68hXKey/s
+xG1EWxvRO38btEZjlI7W4b5LlfmEOaEss5l5d9W3O+Fl8Pk1TD//5zx0ielHcqbd
+7wdAluO0Yq2KgSIzj8wHmzJsHqoamoP6VbwnIq9igYkzIw7wgOEGpf2iGCia3Ptw
+hqr0VYZwKODUj4ZaidckmjS4ncbf3Fk2TwXOPI0Udqo0qU50U0uV/6LM0i27/ygY
+EM0MqKU/9L6PC73Cm2Qgp8iCbN+nN2s8LQ95MfoJ/i9wWcB8xlx0cbdD6c+L72xq
+K4THPxfWkgULbZYVPbLvTlw5jVdyzxaH6szLGhiUz9Z2d2xFl29o0WWvlXtTQcHB
+m+WL83LmmvV508Rmi/yhHmGFSG9kUgyCZF9K4iPLQ+33kgAif6sg2fXaJ2Kxhfi4
+twLtue6PZsrJm4pjFhCMbG3LLFE0Epo/1D1dRfUab4Bi1L2hf9h0nijAwFh9eay4
+19Oldc2x7bB/KRk4i4/h4bmWscJj6nhFREzqs6dL87Gpl9pZHtTBnQEc0y4gacCz
+jv13Nl2g8PH/YTQd7tvdbOUn7MqZA8oP6lff511Ef3gHNWp6LaxqFDGB9wumwAy+
+9CY6dBPjRXf+Bfya6Q4qUrVrw8DL1LrUf5gta++eSOgWW2eFVjPiffY+FE3TqaHC
+J7QcbR6G8hJqFYrAc6yrbe8nCLF0CP5r5U2k/JaJJXA85ZtvPke1Q3LGd+anRLgg
+HE/BxMafRRQHEQQ4gCLT+3ZN+G1hi3dTBmP0ufSAXCwgYRIMikkXEOHG2DKLtYBb
+fULiXYAfFKqtgLqKKLunKHyI99gCGKLNZ2tBKPqypJoemFV9fCwlnXARsgwreRmX
+Kiu98Xc0SMImSL8N94jwGsHI6k5y4FlGn88JWlZjrtAo90A7Vj/UHPAdpUusLmXP
+uFIHQaQrCM+WpspxugtWAP3LuUOYoqvmkvcv9i1Ufn3ThDUtp00IHP9u80pkWmCv
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3.pem
deleted file mode 100644
index 1463a6fd34..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Revoked EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICdDCCAd2gAwIBAgIBDzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBYMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEludmFsaWQgUmV2b2tl
-ZCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEArULgNTYVsg53ILvaQpaeciApmyq6N0bmhjEiwYKYPdZSQ6A5tHN2X0hNYGEf
-Qg37W+OVgufTdQYW9KHRNQDisSLHoFpDaxdeSJbRshvd3iaY70ad01q0/L+mAhoq
-ULHc6QVDrE3PiDd2M2Rt+JNpIMX07CPN/nq8EyiJQUYI5AsCAwEAAaNrMGkwHwYD
-VR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oVlMcwHQYDVR0OBBYEFJyIJr6rimQM
-qOzR65FZzrJ1clsAMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFl
-AwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAHLF0HF9GpuEFWTdc4BuejhAejEBiOTAb
-YfTbYZYqwl0l+JU5CtXiOOdbOcY0XNpPI1XwN1HtIhTiFIxjaRLQ8uSd7yExaiJp
-HR2lqTC8A1efBd0eFY2MuknW6tGu3XWv+2I/NKGGyIKfWAwpPZbt3EdRnjKGhfgU
-VixHhlnpHlE=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3EE.pem
new file mode 100644
index 0000000000..2921552453
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidRevokedEETest3EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 1A 57 03 C4 6F 9F 1A 40 19 C8 9F F9 43 D9 A8 59 9D 9C A7 02
+ friendlyName: Invalid Revoked EE Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Revoked EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDgzCCAmugAwIBAgIBDzANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMF0xCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMS0wKwYDVQQDEyRJbnZh
+bGlkIFJldm9rZWQgRUUgQ2VydGlmaWNhdGUgVGVzdDMwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQC3CqKP+NqhATHU9Ype3p9gqwZT2yJYnoZS0jqLff20
+2TShaoPJ7V0RtaTdle3RMAw6nsu5jehIzYk21kGlNURVYcKO6y+undUfJgYTXX0F
+ZHSCMuMAWuGVdla5oFSqVlzNS9m4gIHlYunhBuzJRFSJQV+eKzPr/ITdO14QEGrO
+DNzu2N1MEMlBzwuExczNN5ZIRWvqLyd52380a+oD9vujGIM8oZQOHcBPZTvbgn7q
+RaH1719locD7oMhj67trLALbsHuRnP2APe/0vuaM7mNTlLzUpb9mAefSjY8o5t93
+38am1l2Z3BDBDLu4BgBi3q8131dczc3y6IrrBtYfpREzAgMBAAGjazBpMB8GA1Ud
+IwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJMB0GA1UdDgQWBBQHFry9nAga3iH1
+aQqYBs0caFrLfDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMC
+ATABMA0GCSqGSIb3DQEBCwUAA4IBAQCCPGXUH3RC5BlNt3cfMDGxsZkfsxYhftwU
+m2b9gwZwBYcHppIxBzHV1ktOPl3uJgpFar02ypnHKWANAcIUIjFZaHhZ6X2YlBeA
+5iQalPQvOyPEUwncGSwWTYNo1KdCev8p29UgyjvZnmdEtMMBUejzDfVHfdyvo0Le
+Z3Gvclnqpn7tu4xkMrYbVGwDmcNRAGhSpXzINk1SUDcHvONQk0n2swPZs3/NjxR5
+oQK3prqEj/ANim+ujHAWVIRIuRwhR1hOQ7SwbZ5CSF7rYB2QZVlpuORrsNurmonK
+JOLp2lDXvMiR6JFO7JAy89bQSCkUNqpPjNIaF8KQ9bEbCZ8qH9W3
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1A 57 03 C4 6F 9F 1A 40 19 C8 9F F9 43 D9 A8 59 9D 9C A7 02
+ friendlyName: Invalid Revoked EE Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8B62CB31A9ACE059
+
+9GmR577tNmXpWrBhkP0uF+4EUaEXZt2RbDCE2iFeGK8muqDRlK9857ybYNuq0cQ+
+tMqJrXHtoqGEomrH3L0slGVhopdlZTuIyT4iy+XPQs0ArZYZfie0mfhtXWiNJrSd
+TJFdFsMp9KZ+/jaP90DltOPmg7CVt8PBBNEvdVtvHfRTOZ1ytNZACgNeMxMSDng/
+UXu4kZ+zEQWDttZxCv8DD4emZJ6PYei9szEHosjYGVFLCiPHvvMV5JBWq42tnvOm
+cRxmOxZ8qx2J8NMpluEZN2bgEPIjdlXbG7slayqFkUqoPgzKYnBDjR6Vi4Tq+1xd
++Zw5d2f6Z0LB/938imM8ZM+y6BTN+6v4I/Mc4vEnan+klMDqGCW/3wcYH0YaRfS9
+eD2ViJuGNApQ5t/Y9W+yOoqWkz43wL/9UUPzFlJOG3+Qoks95ZqhVaQI07vH61z/
+hUXHiaUmQOn07QKrgcRiFkSrV8v6B0hXK3FCOPIlzJkqGr4GswaNM6cd8y62UISX
+UqoZm3gUVBpPrgqbqmabyWEFtBk+RgObs8S3lbtvRaLJMSqiYfoUheXX+3USfOsp
+hS6O6CzeD0zPClicf8dekZWTge6vmUTZNyd8Wrze2X3nrQ0KFWlZjQkQAId3KK3I
+T3ZrBbnqNTyqqVWFbXwltMeqcfVj24GSaYWTcTPbzWPiwNkhbTsBATNtcgKVsPYr
+fpHcxmq4EZNSk5+aPiDrltrYAPgLjWV5+7wXs9wueRoQtsLEJdKa2B+8yak0OZ7E
+v8OILfX7oDaKYldahTBbYCZEAIh9YMcyPIwn/n8RrUM9Mqw+4kUnv7ug1nlrLT/0
+nk6NqtvDCHPMuwnGOvWs0b2qjhQ/8QELPgbp2vlg4Qc5/3owJ/3micil35WyOH2O
+8SmXgeDeBRiNAprlSjB0lCo0Z3cTECFqPpAVrmZMgC3yaTUbvywoDak8muqeh3zv
+Zv8UOgS5zzuKyUtKoB6pLaPPflX0uX89wGYZ2pZyvY2NzjYNRbKbSy6LTFFd3Krm
+c9ub/6N3F/p4JxOx47Baw0Dc7NlkNfuSZJDKK4oflW20DqNl+DPmO9Qmler3Z0a6
+cxAjfgZCOITJzQGL9DV99gAAy9KiNRuem8/5WutIX0wT3StvRK9r5yUyaF6hh6Ru
+c/4sgveqxox7wxEsX20IQVoNGNd+Tw87A+8xiXtL1jOWjApATepDygRRvzCZFCDZ
+jjL0p4TUth0xIfKVrLAeWYyO4s9VHQG3eh2XW9eOuQYK2+fFsqks28kkmI6E+eDi
+tnanUjjv/vTXVAGugmfxuNI6Qr02otA2TXipkfuTAl+b3z1RgKPC7SCB0FbTfFzK
+fx19/89KXHRi3078u/Dsgc1O6S3zNFlydgwIxFQCUQWMu649S/o4XGPb8oYEZ71+
+tlRBuecqmECiiOLSk6t4T8rtiVsP84j82/FFBu8LEP4AMpmMUAnecIue4nK4x680
+L4iI/tUZW9puzgC+qKS0w1kHaQU431yzR7A6RwpRAXZuAQzf3CdQCUajTCr2m3Y6
++Z1qmrV+7rN4Bp+goSuUcuf5kIFRsgh0QaIMKspzZ9zDP5t99zvbJuNYT2SCUwDK
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedDNnameConstraintsTest20.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedDNnameConstraintsTest20.pem
deleted file mode 100644
index eb302f72da..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedDNnameConstraintsTest20.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBCTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBKMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMT
-Fm5hbWVDb25zdHJhaW50cyBETjEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBANItJYQvAndzEuOPLnWhU3+T5fsnTmDZ6JJ02F66VAcrpMjpsFaFiojEgiY/
-nfnbJzFwi6A0VjvStsiM6fOFbVY0vALdhKMSl1OJvPspcf6YMW1MUg68akqffpG2
-1zIqiltFmmT4Lvq/yg9+q2A9W7yB68fS6173hf2h+fGzR8JDAgMBAAGjazBpMB8G
-A1UdIwQYMBaAFE4uo+fZ3YungjtBSsOefFkjV05TMB0GA1UdDgQWBBShuvXAVFzy
-kwUMm0EKULQY2GdPITAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAElrFa8GafGokZssZp8xXcrnM2FIcSbd
-JXCXQeSFsH7JvXS+3BT1v+0saEhJou7UQ55B7Z0t6COKHryuC0E0ySNyDAOMHGJy
-nbbqmdyyKeXb8cEzFUWN+jTte+P4bCc7qJW+mBGNMLjWFZ0sD6R//NF/LiS8kDhU
-CSYphECUPTcs
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10.pem
deleted file mode 100644
index 7462210961..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10.pem
+++ /dev/null
@@ -1,178 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgDCCAemgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhp
-bmhpYml0QW55UG9saWN5MSBzdWJDQTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAOJaxR70a7a1EjJOHlf9fG9BEsSto4MGr1bnQLMud29/o1aka1mDrcT4ehXL
-RT2j2lOFHI+7Cv5UrjI2iI/CWsH+z+PM+sB19pJmrqshzC5FwfeHDzFTUsn8D+5R
-WJAx3NZbB++nDKkIIPql/K61Z8VyKD+3k7nNSHvXV+dKCWd3AgMBAAGjdjB0MB8G
-A1UdIwQYMBaAFKeFECzgAW7nVCNqd6KPFwSv++MSMB0GA1UdDgQWBBSryEEAJtDV
-TOYrVmfs74LEwt3yVTAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAA
-MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcBSBfFavoevmu4Jr
-Fzz3LyHSA3rWhajms8ZL6AtVPDfyQaJsZizVZqKYejWLXv3jNCri/c5BBB2XTXdD
-zAQfwr2W2FfXMkNDUWt95C0NOF7NK5Z2XbmFMGaqn8y/rsYv+Zj7zl98yp0efRKw
-JEDyqFgkV/+0sLFjQvvcCdY9ucM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBAzANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR0wGwYDVQQDExRp
-bmhpYml0QW55UG9saWN5MSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-vcxz0dHrlH/i+DaS78z2Y0O98xlH0yo64kCvWxGo//3ZvMZl+wyQwcAOqDnIH20X
-Fi+G9BhwuyzlaqMenvEQFImtvvDspxYtq/xqmTHET1+9rkF0f8Ex8uV9VgGGMJFB
-Kjax2S+jexoGNro4EeLopi6cOXBgeqwkzcpdi0C3ugECAwEAAaN8MHowHwYDVR0j
-BBgwFoAUZtu1lMcFxLM+K5G538io0E0rNEQwHQYDVR0OBBYEFKeFECzgAW7nVCNq
-d6KPFwSv++MSMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDGuWkVLrBfOy6K
-Y46FaTMnWYkjBWyjC9mgPrq97h90tejc8Z+5Q7u+WD+f//iSoC19Uy65lnk10g56
-UqaqA7zZQ25N28un3YqnKwS1pWrtUGNiAi3vYPUkmwq+6PJvWAcVl56td6OmQOIO
-hDwXMBUcDUYTCVAMRY5fiMx7ARRmeQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBBTANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UE
-AxMYaW5oaWJpdEFueVBvbGljeTEgc3ViQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCd/67ojjbNifZYVq2WHl1rQRvHb6qWjPGD/UvROusJiCTgq+tLG56G
-Yhb5//E5lAwUUzNZIfrwHml2Pn4iH3vJeRDzhdlPd0IIlP6Q2Dxy2/QrBf7k4luQ
-F9TLihsAH9NuOh1bR/+hB4tV3/E2fvztlVmHOlxbAW/c0xE3jI+WiwIDAQABo3Yw
-dDAfBgNVHSMEGDAWgBSryEEAJtDVTOYrVmfs74LEwt3yVTAdBgNVHQ4EFgQU7253
-ms8B2VtX6DNkqlHmWAPzWTgwDgYDVR0PAQH/BAQDAgH2MBEGA1UdIAQKMAgwBgYE
-VR0gADAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACgW+giBnGTr
-WXyUZ38pVKHUK9uAxjpPOw5UZC2krfC4nqifiItuVLJgqbPmvETc+8fGD4hi07Lv
-owJkVeBq0ZQGlYoxtz7z6/gEt46nf+lK5gU+al33eTzgga0845cxLE7kpKRYsyhX
-eCRGC8Cmifmc+1AJ12kj61Ys7XE8P9q+
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AB:C8:41:00:26:D0:D5:4C:E6:2B:56:67:EC:EF:82:C4:C2:DD:F2:55
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 85:eb:03:68:bb:91:5d:9a:09:2a:f7:5c:73:90:8d:e8:4b:23:
- 92:c3:d6:b3:8b:81:ba:d2:b9:dc:a1:e4:48:29:a8:98:cf:59:
- db:2b:1e:de:1a:ce:db:cd:5a:dd:de:f5:f3:91:13:9c:1e:a6:
- c8:4c:d1:ee:24:10:7c:95:df:a0:ed:4d:f9:a5:16:43:89:af:
- 18:f6:1c:24:b0:70:9c:62:86:07:f8:0c:e1:61:d6:99:ed:7b:
- 88:58:9f:79:d6:3a:1e:ba:aa:52:97:13:5e:00:7d:00:ce:9a:
- d2:34:9f:0d:bc:18:09:f8:10:2d:c5:d2:8f:d7:eb:a9:59:25:
- 45:1c
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kx
-IHN1YkNBMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUq8hBACbQ1UzmK1Zn7O+CxMLd8lUwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAhesDaLuRXZoJKvdcc5CN6EsjksPWs4uButK53KHkSCmomM9Z2yse
-3hrO281a3d7185ETnB6myEzR7iQQfJXfoO1N+aUWQ4mvGPYcJLBwnGKGB/gM4WHW
-me17iFifedY6HrqqUpcTXgB9AM6a0jSfDbwYCfgQLcXSj9frqVklRRw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10EE.pem
new file mode 100644
index 0000000000..e1d36aaa9b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest10EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5E D2 45 B6 7F E4 4B 8E 8E 55 E5 51 AB A4 39 EA 62 3E 9D 43
+ friendlyName: Invalid Self-Issued inhibitAnyPolicy Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBBTANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowUTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kxIHN1YkNBMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBALF4YK3LWtJiBgUl5Tn3nfwLF69a8RzoolTy
+yaH+AC5GnpkNUDC8Mae8jF0rRErvKDlDgHmHFYrEXoZ6ROCsqx2m0PCYcM0aSc5I
+Nt0zfc0V/SjB8PEitoIsDTBNWQHoWBysMKdEvPcPgEbQ6g/I9AMuo2ENAu3JAK/k
+mFT7y5P4Auk3pwAzK9eM/qiVVSoK62ykN2e90B/v/W8Mp2B1oSLkbrUq+pZdG0Cl
+lqPw8jaA6/GRttWiOINW1MERdhyYXIZa9HrhE1vHQNBWT9ZNs0z8WXlSx0qSe5Bf
+ZRC6U4A7HagfKnp97XwcfgzLEZVeRzq8ydhdKyYL/GIQ6skBA00CAwEAAaN2MHQw
+HwYDVR0jBBgwFoAUjAXc335k22K+20tRZIxqZthco6MwHQYDVR0OBBYEFNeq4+x4
+jtMItdkkxE+pjUaRGjiSMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRV
+HSAAMA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQsFAAOCAQEAw+zWEOZ2oOy7
+pak+z0Wn3q9yg06WNlv55x61qIF9FLPsUKHcq5HZNHUqYUXhsGP08cU5bIq20epK
+xuAj34fGieLjH1KgbgG+Bwe8pkG43gzh7ggqdqcUEXQZFOMLlZz6AnRWeG8/ZoKt
+J1u5XBLhBO6poXF8n3T8t0us4f+HtVOjdNeRdrS1QEiHrXLOanN6YIViBraciCOd
+ezeYCJvDquy2ZCoAUDpJS6dofveoHGr4BpMDgLe1g19JWAbZhvHQ/WHzTJrMnd/q
+rvpQcTRAwaLr/Sp3zY5tp4Mb7AV4iYYszVbwQQyHhsq0E590x6kQz6lVtKh7joOU
+4naDVzv2ig==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5E D2 45 B6 7F E4 4B 8E 8E 55 E5 51 AB A4 39 EA 62 3E 9D 43
+ friendlyName: Invalid Self-Issued inhibitAnyPolicy Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9DBA21FEB1BBF3A3
+
+vEXQyEjZcFlzS31kO8IeWEvB/hYjpm7DzvDAFbfVZtfW9/khycLB1pUhbMEzVvH8
+L6pKBRETAoU33dCwAIkySaegzKzLCd9WFpmlOIeFH+WSyVoRs4nnSHPBk42mBKj/
+NK5ue63pzko+QZVIiFPt8x7R44i2lGRXRCgaqiyIJkSyby98aPlAxi3AUChU49vA
+ZXCDUg1YQIe4xVqJ6ONYRmyVk5DbIWY6aQSV7jQ0OL3olL8+WgXmUiQFuvva1rdL
+s3Z2MTGQMJH4wU0lpsAtX6UCgGvoSy6PSu+W0OUH7zG/4/MjCp82BnY5xJLzmPKi
++2jEWuw9CfdiFMLrFNLew1SIe1attx8CZ6sYAKakOcyZ856HiOsO634yzaRgOhh5
+SmmNN49StebbBv261z4cmVc4VeDPvjyvkGKjLxBYLMgWwsvZOhskednUDwGi3cJ2
++3FMFDorpbJ4+7o2MkyjIAMuvqVI/cWaKlzTsi7NWVeNQf1Shg1P+m6jLL1SueiH
++4Ce1Mah3OujFO+Rd3Vb0NcKgobKklL7Jc828ArMC2t1P6xmEUJPG2PngXC3mDII
+x3aj+ApQ7Fbt2UIXRGA10z+hRYvELAACGUA4lPMI/7/p2xoEgE/2+6pyKaGhZc7r
+VEhygISd46RcMUb053KqY4vPP4lDRjyZ7N1ebGVYGrJ85mMWR35B2Lh2jGqbCecx
+X2jMqvOUTGScgx0afxA4gPHO9McQwusrG3AePcmRrR4qxiur0DhK8veK1j8wFuRk
+ZwXhXSP87NLtUQ0F5TzJm8zFviF8Ad8+Tpb+nEYrZK4XEnwVzJZXwAeikJu/wWmZ
+23w56a8YAR5KEz/lXhFgJqXV1x2RteToTNKp7X5ofVHjJeySdRvrJbwEPokRoHgz
+mhwK8rEBeAjeQpImLzjjACV2gU1BybOnnB67WoM5z9mByscCFumy/bni+5Dogqua
+WApGMeRdqLPl3KX5bc9Q1F1b6gXygSYxGsBVAIFxwxmJdKlShat8qP2rYUySE4Pi
+c0WoXMwx4bHgLM7eXlMgfM1D9sV+kww9B2kQlC33cVMTkqcPcP87sJJXXO933xQQ
+RxNnPQ5SlkbapVZAiajhagcALhNLVFxgxz+wJX8cxoGj5aZutJcKEsRpt/UGgx78
+ZMDHLEelO5dt2KUci3Zd4qQTVBkxkfLIGyV/6nZUyPNK2l36yTRmd64DiAMyF8NY
+vU8aNb/aiVtTKLTr5edZOTJ84inTqLdsORpsWqRU2i25epB9TkHsTQHky83kUSqX
+at7iuELBsREAhhUmviJgnRwPiH/FZUVAwaS1frZ27kxEPuicZZKqTL7sz0tHduQA
+TiQvrbuKUDdyLjLRGYLow1LZFDpL1DXZcEI8YhzDVCfU5u0EaAGFeBq+3owBjpVi
+RJCdp9ZRl1SGdY/Lbs+/S+Jxgq4MLqFs/d2+NRijh+jTZfTHCggih5vbkB+A36pY
+CUYmYOsnLmcV4cD2K9S4X1Rgl51rLqnYRuJLIgNW2yRh/g2bCHakLqUeHOb7UlQq
+H8CIaxiSjdS5tVntPnQQYr9DwZ137JY4xBLMzasFYcU70DWkCO/xTA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8.pem
deleted file mode 100644
index c4536e1bc9..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8.pem
+++ /dev/null
@@ -1,230 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgDCCAemgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhp
-bmhpYml0QW55UG9saWN5MSBzdWJDQTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAOJaxR70a7a1EjJOHlf9fG9BEsSto4MGr1bnQLMud29/o1aka1mDrcT4ehXL
-RT2j2lOFHI+7Cv5UrjI2iI/CWsH+z+PM+sB19pJmrqshzC5FwfeHDzFTUsn8D+5R
-WJAx3NZbB++nDKkIIPql/K61Z8VyKD+3k7nNSHvXV+dKCWd3AgMBAAGjdjB0MB8G
-A1UdIwQYMBaAFKeFECzgAW7nVCNqd6KPFwSv++MSMB0GA1UdDgQWBBSryEEAJtDV
-TOYrVmfs74LEwt3yVTAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAA
-MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcBSBfFavoevmu4Jr
-Fzz3LyHSA3rWhajms8ZL6AtVPDfyQaJsZizVZqKYejWLXv3jNCri/c5BBB2XTXdD
-zAQfwr2W2FfXMkNDUWt95C0NOF7NK5Z2XbmFMGaqn8y/rsYv+Zj7zl98yp0efRKw
-JEDyqFgkV/+0sLFjQvvcCdY9ucM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBAzANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR0wGwYDVQQDExRp
-bmhpYml0QW55UG9saWN5MSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-vcxz0dHrlH/i+DaS78z2Y0O98xlH0yo64kCvWxGo//3ZvMZl+wyQwcAOqDnIH20X
-Fi+G9BhwuyzlaqMenvEQFImtvvDspxYtq/xqmTHET1+9rkF0f8Ex8uV9VgGGMJFB
-Kjax2S+jexoGNro4EeLopi6cOXBgeqwkzcpdi0C3ugECAwEAAaN8MHowHwYDVR0j
-BBgwFoAUZtu1lMcFxLM+K5G538io0E0rNEQwHQYDVR0OBBYEFKeFECzgAW7nVCNq
-d6KPFwSv++MSMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDGuWkVLrBfOy6K
-Y46FaTMnWYkjBWyjC9mgPrq97h90tejc8Z+5Q7u+WD+f//iSoC19Uy65lnk10g56
-UqaqA7zZQ25N28un3YqnKwS1pWrtUGNiAi3vYPUkmwq+6PJvWAcVl56td6OmQOIO
-hDwXMBUcDUYTCVAMRY5fiMx7ARRmeQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subsubCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8x
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UE
-AxMbaW5oaWJpdEFueVBvbGljeTEgc3Vic3ViQ0EyMIGfMA0GCSqGSIb3DQEBAQUA
-A4GNADCBiQKBgQCSWo7+2d9aVEIC1GxMTDBcE+ozTf3DLetgbtqH0eb/EK+ZLwVz
-cVTjWrdl1UTfNgUR9FkYIxWkXmme/JXqvYFtYTmNiz0Yj4KGpl25Mi4qoxtRFk2M
-BKLOpp+oY4PsNGSc5CMRc3sfZHeKe8jZK3nA4G5nv0/KELI4m69QKI7u4wIDAQAB
-o3YwdDAfBgNVHSMEGDAWgBSryEEAJtDVTOYrVmfs74LEwt3yVTAdBgNVHQ4EFgQU
-Iskd1THdwnbnw9yS/MCFk6rmzc4wDgYDVR0PAQH/BAQDAgEGMBEGA1UdIAQKMAgw
-BgYEVR0gADAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBADf72Lgp
-rqTepmy2dScOvurWUGzi/mA303snWu2b/DOnZOn2MJmmN2OIau2+7H9N1CVJDq+9
-gF97Zy3sIukm2yyJ623TL2sO5JeKNIP87CGXEiuU8qe/7BaW8C4dkm9dE0hIq82/
-vPG+JF3KAey6HeGOdaLoj+DyiSWJsJmzb1OC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued inhibitAnyPolicy EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subsubCA2
------BEGIN CERTIFICATE-----
-MIICnTCCAgagAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRBbnlQ
-b2xpY3kxIHN1YnN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MG0xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFCMEAG
-A1UEAxM5SW52YWxpZCBTZWxmLUlzc3VlZCBpbmhpYml0QW55UG9saWN5IEVFIENl
-cnRpZmljYXRlIFRlc3Q4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ/9Ia
-17vdObtOssUs8md1zwyBeKcC3f6mFfybdaruKZpzVmuAkDJec9ZV+ye3BJUB/5Vd
-FE+xni7v7HcxxRwnFHLMDEqoBYuAuMxi8tWDpWAT9bG9tlMH27i6in9PqUFDtMba
-A2eI2p7J64Nm+mtNtbwY8obe+0CbvRPJDnBU+wIDAQABo2swaTAfBgNVHSMEGDAW
-gBQiyR3VMd3CdufD3JL8wIWTqubNzjAdBgNVHQ4EFgQUON+KAQ3zmTRqwEhvTM0g
-vMZUZF4wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAN
-BgkqhkiG9w0BAQUFAAOBgQBxH+ujnhDuJ8w84wkOZvsaXK8TaJMO7AkbWriyl9Bm
-rMj0tb0bKud0bFlnK+uuetnpFGNysBArTwGQMpQ8C9KsHDEDVoC5A7TAUXHJgtyG
-geWX6fiC8ZBA/LDkDjqLchdfF2r/Enjo84+EbjA28xHQeJt+AMv2PrX41z7EWjjj
-dA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AB:C8:41:00:26:D0:D5:4C:E6:2B:56:67:EC:EF:82:C4:C2:DD:F2:55
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 85:eb:03:68:bb:91:5d:9a:09:2a:f7:5c:73:90:8d:e8:4b:23:
- 92:c3:d6:b3:8b:81:ba:d2:b9:dc:a1:e4:48:29:a8:98:cf:59:
- db:2b:1e:de:1a:ce:db:cd:5a:dd:de:f5:f3:91:13:9c:1e:a6:
- c8:4c:d1:ee:24:10:7c:95:df:a0:ed:4d:f9:a5:16:43:89:af:
- 18:f6:1c:24:b0:70:9c:62:86:07:f8:0c:e1:61:d6:99:ed:7b:
- 88:58:9f:79:d6:3a:1e:ba:aa:52:97:13:5e:00:7d:00:ce:9a:
- d2:34:9f:0d:bc:18:09:f8:10:2d:c5:d2:8f:d7:eb:a9:59:25:
- 45:1c
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kx
-IHN1YkNBMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUq8hBACbQ1UzmK1Zn7O+CxMLd8lUwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAhesDaLuRXZoJKvdcc5CN6EsjksPWs4uButK53KHkSCmomM9Z2yse
-3hrO281a3d7185ETnB6myEzR7iQQfJXfoO1N+aUWQ4mvGPYcJLBwnGKGB/gM4WHW
-me17iFifedY6HrqqUpcTXgB9AM6a0jSfDbwYCfgQLcXSj9frqVklRRw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subsubCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:22:C9:1D:D5:31:DD:C2:76:E7:C3:DC:92:FC:C0:85:93:AA:E6:CD:CE
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1d:88:c0:b5:68:f8:c5:35:0c:66:d2:54:82:7f:06:cd:fb:e4:
- 14:7b:81:fd:e0:ff:7f:0c:33:e4:b4:07:82:8e:40:8e:46:36:
- 5c:05:8c:72:bc:b9:83:50:2b:c9:d5:23:08:40:c9:a3:47:ca:
- cf:41:15:86:1d:a8:fe:50:a9:ec:75:78:c9:d1:6f:94:00:86:
- c3:05:3d:e4:39:af:b4:a0:9e:07:88:24:fe:66:f9:7b:f5:95:
- 7c:dc:08:c5:ca:e4:4c:d3:82:bb:6c:de:07:8a:f2:18:71:ff:
- 8b:d2:a0:95:2d:c4:e2:12:37:bf:12:cc:e9:bb:75:de:16:9f:
- 86:32
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRBbnlQb2xpY3kx
-IHN1YnN1YkNBMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUIskd1THdwnbnw9yS/MCFk6rmzc4wCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAHYjAtWj4xTUMZtJUgn8GzfvkFHuB/eD/fwwz5LQHgo5AjkY2
-XAWMcry5g1ArydUjCEDJo0fKz0EVhh2o/lCp7HV4ydFvlACGwwU95DmvtKCeB4gk
-/mb5e/WVfNwIxcrkTNOCu2zeB4ryGHH/i9KglS3E4hI3vxLM6bt13hafhjI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8EE.pem
new file mode 100644
index 0000000000..55fd665be7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitAnyPolicyTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CC 64 FB 32 6F 67 8A 1E 96 53 A4 EC FE 77 2C 95 89 CE E7 02
+ friendlyName: Invalid Self-Issued inhibitAnyPolicy Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued inhibitAnyPolicy EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subsubCA2
+-----BEGIN CERTIFICATE-----
+MIIDrDCCApSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJp
+dEFueVBvbGljeTEgc3Vic3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowcjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExQjBABgNVBAMTOUludmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJpdEFueVBv
+bGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0ODCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANrGXh8C+n2LlFXpLZsOJgBIEL0cYBmcOraLKe7Uvg2hJc9AD8r/
+z8WHmVQlSq4B8l5SFHNeRfZ80BEnvnpsTYyLF8ANVwtG5OT/tYqaJnda7njYnjML
+hMkR8VHTaeplaXavFjQAesIG/JXDzHpX4U3FzcLo32jX30Jl0t1wSSVgufSYzPmz
+vN4snvG+K/U6wIwW1Zj+bzDTf+WFNTL2KW+jEr7X8XfWi7gqNUaWdqkskRAkBM0n
+CyiuRiEe9bFulCodYxEJB2pJKwdjXCxdHtJS3FiwOq86oOXgvThoQdHgxbAt7JWC
+RqwyDXmi1cLLG5sioGKwAKDcE1jtuL9Ep2UCAwEAAaNrMGkwHwYDVR0jBBgwFoAU
+EX3AnIp2+Ukz96SBS44wdZU76IgwHQYDVR0OBBYEFJ/nMvWSZoe1IShDy5EYfznX
+2OM+MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJ
+KoZIhvcNAQELBQADggEBAJjr02r+qm4q+XG/oDosR+zfakP0pcDGVwwLwHqHV6i6
+hf32iODdTy7N+3GfB1vOdWJ1HKJT8TbXcM/zyYyglvw9rXAWdeaTeZLExRaavB+k
+LlIAycxXFl4gSslEqbxnGl7FN4BN8DAa+4WtHwW0Ff3U0wTbSNMBx4x7skvP/9ZO
+8Qllw94V7dAwBUDwbVL185tJsJI87lMXUqxMdrBCGoa0lqS1I8ZFCYXV0TOCeeTI
+ruSYrANu8eHRJliHGb4+SAZ9xVWFqsqAJyqrs+pJHFm4+7q/YdBeVjV70jTjN+R+
+Jxh+nojv3Cn5l9DmG8xQZzc4Q3QTsd7Dpmb51+N+N7Y=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CC 64 FB 32 6F 67 8A 1E 96 53 A4 EC FE 77 2C 95 89 CE E7 02
+ friendlyName: Invalid Self-Issued inhibitAnyPolicy Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6A1C69F9982793EE
+
+k71tl+AyI5R0Zaid9r0W4MdpNwhQHzNbrE0OybQzNpvyMYEd45AAPZSkTw3P0loK
+MyWXVvI9Y8xTBtorqE0bHlPbpJhdxBqv8NO2glThprJYVG+G8m9O3y2/vKSFCOqr
+nsHAHR7X4KjpPif3gTovYdKLGRDBSpFnTzwGGEHX47Ey/7goy+r6gbHYfpGaCHwQ
+UcDpatkSc3GUkgSwSodNZPvWeymvdZBXyHyp73GWN+tgX0WyQYsh5bADAjIsReXu
+D0wnzYcXQtHxmbQbqv6QyXiBPY91GNxcvAwa/1QcbiI5O20EIieOesTQI31yCRHT
+a8mp/E47C191Gn+9DrgXtk4/YyR2JIWxhsbHceTOCN3JLnPngFHKZ6A0bNfLtZP9
+Uj7ZclhcVz6dxoqs3hM3j4MEGJ2PMNp9u+03He2Rt1NMZuns81ioXSzHAWsGzVSn
+PcUyqUMafdzHlGYLxq7NHzw95+SpSvWAIXDnfOfrlZiP1LOnWNwxFXWnQ8JksahG
+rQQPCv7YFhTJzr8MvlKdDrOoG709ANpsnWgf+G1vD9MVuZ7ZrBHSFFzjnyZu4OW9
+c2JTlB+ZPWfspMDNMhuVhpVkOWktPFGpHz1sB+r/GsAq3MqeuefcQVeR9hHApbdZ
+CBwHqjZVatSDMV6DCXGPAjShRLLNAi22wa+Nsu/k4AqSiSnnT/6UWyFTwYDBxk0f
+fTqHgOd18A2vVjL90tlAlyzC6vcYM/fM1xmBaX9y8M+MesZPBIAhMHN1Axl4iX5W
+q5vkqh9u1pxtKJnhn9pQ9g/hqZbcRp1T/na7HWAzwOoty9157Kl6WrkRFiJXicy5
+7MsEzjyUPtCv51YVgvNHVGadCeQprKkVNYjuZAzXt0E901xqyOLMOeFv2LSwAe6N
+BE3BMBOq4QIUYw1ia9bKeju8GdfdDKpCwbtnjns1Pk5O04TCJFuAk/1VWzKnfGUp
+4+JrN9VCM6x+Rhwlw+uHiDDQwgRU0W41BUJv+EI3Ol47NnnuaaRYGx36q3k2XVhk
+/F/KoDDyDcc2P9oxGJTdkimmgSeW2XTkoiet7Oop+9SOmr8+6QiPuSe3hTJq5548
+5ihfZVZRzT8AOL3wYr1RTYfcEW3/Yhnlm3r2htLphB/05NxcZJTubVpybHFcfZSD
+KNqqjZicL5MwMR8Jx3/oDKJ0Y2Hl335HUZez3d4SFuNf2FTVe8gLPEe2l82SFLJJ
+WOyIpmKyGI3GzkIet7hi4V33va4Yvvh02IPfKd4JsDXYMNoj8cusVRuDwobFbLF6
+rB1UXfYH799oAUBnZBzNLip2WKCBqU8NJi4aYpyszq4afuZ6umG9oXuXzXBtSt0j
+32kdr8/7WrOJzAb4qpzKjY0uPrh/W8hR0tJphVQB71qFMs6jKc6TFdeuDORnX5Ky
+45U5ZL+WeRF9+s7Aoist+n0ObC6kdVUMd64Ft7VPmRwv0ayOuMvdBvKTUMOeDgFV
+c9vaPZHNo5d7Rd5WGn53A7f+9vs54sx/GcXyYZgsfewKqmautEGmzmwCxP2PA9KL
+6r2mgE3b7WI+AfaORZh3s6r5GK0jtbxLyobFxWfG+I/bjjj4cLDXJ6fzcpSWM7uD
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10.pem
deleted file mode 100644
index 5d5bad56aa..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10.pem
+++ /dev/null
@@ -1,200 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-ME8xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIG
-A1UEAxMbaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCX3X8GrbxUXCENLok/vrVUA4snN0DJ+ja+Vct+doODtUFE
-99ZdYrT+qEPGAkioxAKElsWQDHoAjlv/TjoSxbV6BURJiMk+pIdN/N3oOtLz9N5y
-emO4Nq8Wv3A6dmTeqV/BvhEmKyKd9h/0Vy3gTP/eIqA8vhyxOpPLAB/gKIIWUwID
-AQABo3wwejAfBgNVHSMEGDAWgBSqaWS1UuWiYwoKoPNqFz8gsgPUtDAdBgNVHQ4E
-FgQUbFzipWxbYKUZ3ncFU1rjNTWvrRswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAImoE0/jphqmO48yRD2BCE5RlbnLVfXqKMbZ61lxs7X2Z2oC7QmmXJ8xH0vu
-YmnqpQTJjLwJc6janX9zk3DIdokB0PPu6HAtSb3GeETMG2tQFA3aeDyg8xjqGNBD
-OHfNDd64bvLnKZWb3bLEPfnZf6WTaRV/x56wf+7+NPg+zJop
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBOjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA
-643DGHdT8CXwVc2GtZQbRQTdptkiSzy79NPJD2XLU9LpWnrgyGzl4j7xUeYVspxY
-Ws/mpZCQOb2hs8eDfHKisjtcKj8Y8r0S8Csb3dsG19Rmjbg/2SiF5ZMaHzPi0QAk
-m008o0bwHaSBlFHigtvqu563VpgMs52ksx3BV1BKZQIDAQABo4GRMIGOMB8GA1Ud
-IwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSqaWS1UuWiYwoK
-oPNqFz8gsgPUtDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBATANBgkqhkiG
-9w0BAQUFAAOBgQA3+2MqCUqi2aRGC2CQMzptfla5lfBz0GLy7p1VBIoKLOe6/rAb
-IhVjO2X7pWEJosnjfmKUOggaCctxUuGgA/okQKTXTXQwXJwJNv2qS5lf1AHD4B99
-pZ5ebQ5FJ+RZBB6HiUWabWVfJ41WPI7ceJ8fh/Riau+XJg2KLE8myngRMA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICpTCCAg6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMHIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFH
-MEUGA1UEAxM+SW52YWxpZCBTZWxmLUlzc3VlZCBpbmhpYml0UG9saWN5TWFwcGlu
-ZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTAwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBALSurY6um4v6Evz2ZZkBR0WlROEOIvWcYk9AFjbvZnEXlHBzmkfiz93q0Bi1
-a98FZyy05zNbGmfXdXDbAuNwWdWnYFJqFQF5yKUTSQOjNNy5afttfVbM3ibrmE52
-KsMfdN73UU2pHclkhpRJ9ex52s3nofBFCXZQVRZzoeOqe/tfAgMBAAGjazBpMB8G
-A1UdIwQYMBaAFEGmJOdLRsqNTr1i/ZUfoEVERdaDMB0GA1UdDgQWBBThQ779KH6I
-bjPzWxJ3ysMVnek3RjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATADMA0GCSqGSIb3DQEBBQUAA4GBAHsSdG99XQKSMIQzQLp/vngNcqtmTCC5
-jBCt3KnnUwJ/Nrk2oEQpRwjetItPwFFYN/IR1MUnb0TtKwr+WqFeMI5MgyzkuiG8
-b8Wi8Nfa+GP+ZaWx9W0hIwlvixhloYr/wO5roHJLmZdiyrUJlEGb/7VLK5ZlmSDd
-LhmwYoEZUDxg
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUG
-A1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDlD9RQqLmz1R8mmDv95sxGdTT50F3U2U2PHAx0M0R/
-EmmreJx8mubNNUzKpH+jIQCsgKqAH+CJH/LDeCzow3F/cS0bcKYF/x1hJhJHO+pP
-uBgIa0yNq+hkNY9F+V/b+auEovg9yqIThiE9atAWfL1IRnRW5qpSi7si8qQdGWGt
-iQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFGxc4qVsW2ClGd53BVNa4zU1r60bMB0G
-A1UdDgQWBBS2psHqwFJT34b9ZknktEa+YzMMFTAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEw
-AQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
-AAjqz5quHRrfjyt+VRbtAM5KfKQS9G5SMsxGGdD/A8Nu5JYAN5FGi9X+RjLqeBzD
-6hmnFNNPFZx9LtO1s4wBoM06zoAddrIISUWehidWkxh7YEJSt4OSQ3fHNO0lgHaC
-WnvV8cZ3JLFezL+4ZDzXUJYoxmGCjerFTfIszoyvBuu6
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICwDCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEn
-MCUGA1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQC8nvl2y4d/yNUHP7aG5vOrKPi3d7UXdNZHRGzP
-KFYbJk+OVhNwnX26uR8hCEDDfjBI28f/541hjsDbgy60IS+nCklaPQkS5uD2R6Lq
-9WPZpnSNT+obNGFQqIuE0iQbBIXeXKy/E1lxCIQazKZHl7/QhjIso5/eRagUVF6m
-ahAnsQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFLamwerAUlPfhv1mSeS0Rr5jMwwV
-MB0GA1UdDgQWBBRBpiTnS0bKjU69Yv2VH6BFREXWgzAOBgNVHQ8BAf8EBAMCAQYw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUD
-AgEwAgYKYIZIAWUDAgEwAzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAKKfnJVgNVANlABGqhZPFB+MA6EeX9BLJIERR69poKaUCigLoIdovWQx9/sT
-MYvGE/gIulPhyTI2P+UM8yJHPmsucrlDwVwgyTE9WCsfVRZOV/DVqGzvHtpUGetp
-GZVUYWRIJtdAFXq1h04c6KSFenC2BqH6A19N8SkUyT9v8khC
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:69:64:B5:52:E5:A2:63:0A:0A:A0:F3:6A:17:3F:20:B2:03:D4:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:01:00:85:8d:99:b7:5b:7f:63:14:5b:20:de:25:35:78:25:
- 50:56:9d:78:eb:ac:15:34:90:c7:18:cd:03:ad:4b:80:9f:b2:
- 09:73:d0:8d:c9:dd:a2:5b:e5:c2:9e:30:ad:09:06:ad:8c:56:
- 7b:39:76:aa:1e:13:a6:21:2b:68:c4:93:f3:39:fb:7c:7a:f7:
- 2d:e4:d3:ac:5c:a6:38:07:9e:f5:b7:c2:54:6c:e7:76:9b:2e:
- 74:5e:cd:83:1f:25:c0:d6:4d:af:ab:29:47:dd:b0:87:79:86:
- f3:4d:89:80:2c:21:14:68:ec:4d:cd:67:d0:88:94:63:d1:db:
- f7:a4
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUqmlktVLlomMKCqDzahc/ILID1LQwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAjQEAhY2Zt1t/YxRbIN4lNXglUFadeOusFTSQxxjNA61LgJ+y
-CXPQjcndolvlwp4wrQkGrYxWezl2qh4TpiEraMST8zn7fHr3LeTTrFymOAee9bfC
-VGzndpsudF7Ngx8lwNZNr6spR92wh3mG802JgCwhFGjsTc1n0IiUY9Hb96Q=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B6:A6:C1:EA:C0:52:53:DF:86:FD:66:49:E4:B4:46:BE:63:33:0C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- aa:fc:6a:e9:aa:6d:46:16:9f:65:05:ec:bb:4a:e3:de:fc:ee:
- 4b:6a:61:7b:4f:ca:b0:86:90:90:f9:3e:ee:42:70:bf:70:51:
- 0b:ab:f0:b5:51:4f:78:f2:03:59:1e:5b:01:1d:6f:79:b6:d9:
- c2:38:83:22:b4:ae:64:06:63:5a:af:04:58:6c:a1:e2:3f:64:
- ce:f2:24:20:0c:a4:77:52:e1:cc:23:3f:5f:a7:89:20:85:fb:
- cd:f8:c1:09:98:bb:62:c3:62:0b:75:38:01:b0:93:d6:bf:22:
- d0:18:ff:04:52:25:72:bc:c9:d4:e5:77:fa:b6:84:9d:bb:d9:
- 45:a0
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUtqbB6sBSU9+G/WZJ5LRGvmMzDBUwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAqvxq6aptRhafZQXsu0rj3vzuS2phe0/KsIaQkPk+7kJw
-v3BRC6vwtVFPePIDWR5bAR1vebbZwjiDIrSuZAZjWq8EWGyh4j9kzvIkIAykd1Lh
-zCM/X6eJIIX7zfjBCZi7YsNiC3U4AbCT1r8i0Bj/BFIlcrzJ1OV3+raEnbvZRaA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10EE.pem
new file mode 100644
index 0000000000..c06445050d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest10EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 2A 05 D1 E1 38 BC D1 DA 42 C0 F7 50 50 DA 43 FD 84 D8 96 20
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApygAwIBAgIBBDANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowdzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExRzBFBgNVBAMTPkludmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJpdFBv
+bGljeU1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDEwMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAp5QAd+u/Uos7XJmpFiMxS2UfCoX4S7F2Z8X+H5aE
+ROK+YmaczS0wMScaDNXiqifUvntr2PEVPGpjAdVg711oP4yJUO6yxljUqZl/DVV7
+//qRPkD76MUCIxNx1dxLrsOd6PDmFV3ZcS1w5R6dB7E4AGV6jG2ikMHAp1UH69sJ
+nxbMKCtpigzpxYTQtcH9+oB59lMkkAtSk0k09NvW0GHlDR6+suZgQHHfmJMV8C1+
+WitpjZncCSlS6jc0QnYpGeytIPY3JVq5I9xaaiBsKLQAxf+N2XSNzs/SoUWDNfPy
+tBlUdU9h8HmLx5ZB6OV8fF0G8jTH/kJ9qhOtzOBGuz26BwIDAQABo2swaTAfBgNV
+HSMEGDAWgBRZuWxk6vOuluq2UVwljzvP7fWTDjAdBgNVHQ4EFgQUKnl4yMYjPGWd
+wygY26eKCylWgpowDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUD
+AgEwAzANBgkqhkiG9w0BAQsFAAOCAQEAmjzrR+7LxCOYhqiancHFg4jAXcy8IQNF
+w8M3p9yWNIusPl3UwTBGf1o6nn7Pbp+sWPrqsdRETfOk+14+UpVFwwIu4tpNdNZN
+KQGsovaMjGdr1ZawnSxGg7s7aRaTA/EN66brxdWQosoDVPByNjDIqzLx89UIcEPt
+qVSK6UukAx6UqPPyZSj31V3VK/5zCvpaSmekzBdmRYoRyhTyCE9Siqqtqh+MOJYn
+QRGpn1qPp+wZAqH9x4g+lsuUVjU3mll81rwQGHAWke/ZAbUmzZIkw2i6G08SJUhY
+M6a3CsWate1y1nryzWjsVOzERK1X1dkKC5GsYm1X36COcZq+lkIshw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2A 05 D1 E1 38 BC D1 DA 42 C0 F7 50 50 DA 43 FD 84 D8 96 20
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,45343F863105C0DC
+
+jROO6JFmYZtrJFFPJ803OpyapdIAijSNsy44v78PGRCPbqp5qCErYohOUfD+o/au
+iQZIeAOqfJQA4M8PISN7fyIQjfCoKT58HJ2O3R1x65CkbL7eSC1VKkTvOcZed4v4
+kSCqWp66spB51u1akvAwd9EYTtdZh6HPFg6wf89Lpav1sagKX42e5A3E6WhUasdk
+/WGvLJiar6rRbrCxw/ydicSgM2VmGV4X+drp7OVr2Mgl6mJ0FTbnSFFMREUHncE9
+MHM30XIU1/Cm4cH3jUspYftlRmJetghwLI1MZrKONIHz4Ko5ZXgKA++6f4cKKnCK
+ycCXTj3NOG3VRor/auTzMZ2lqYFsUjjH3QnrfxSKvz1K7Jj81mkdRQDP47vAbi3R
+gNgg2r7vwRpxzQgoVd4Bl2cL2VwQMspXH9RehhuAoMcVOuRBWUKed2abtjwuNBPC
+nENtMKeVfovnbEVkurNVSAROmQ4LEf2XA4HnAIXOKN2TvE4Z64yhuZvU9r9Si5JW
+VEXPpYUFrgFCr9lvGzYQWl2lbS1r8tmZJRbLz/FWm++fXHt3j60IEGMREZw96Wlz
+dasKD/sx96PSa/8PPzwsGGgn8+fvTc3T9F4rQ9AVNlvEs9ynU7Nzxk5NxomgMqBz
+NvTVA6+jzzGP3rmIV0fxdnmTXHSJVb5Z47R34KMmVXBHQBcJ/4jjQKK+ayItymSS
+TYDGlde65C8YRUKg/OGSrUvhKAPh1hxEDza279vTV46+HFDO2uus888+UH/M81tY
+Qjks7kz3l7SjXD9tb8bsI93nI5Ab1fjqJ44xN8GMVehUCFDsrpgQjZzHHUPagXig
+zotyOh5P2OCFuANf1KNmkkbP3xHqGMMnfA9VmGZHMrvfrAh0HfmfS/vrtL9iuPfK
+j/xi7cTHx23FuAx+aUbHzu6vkvdu4pcZoieI9CvZuQwmSTHsuD3XzLEKc51rI7HV
+W6GxUDWb4bSEQMidT9npTtIXpjyGoIYkZyChqJTxqi6UQmvf20AONH88crHpaID6
+cBbtcHjob13A/yxVD54es943TCWFdR8eAhXEcmbAiayhRULWSgNKlsLykPHQ3ldo
+AX4gQKZWtxm/aIEGyoGcWQ14JAz1Seo5B/lmG23gKIs9gtqwXN7rslKPR1dhGFMY
+g2KazhBpXinjFXQayRatQVWjko0R7jJoTlHOewHm1JiQzOcphLugrDIwVKRAnPJ4
+MTpbRrNAJp+zAhoS0PUB51cYzQrWNzgslN+g9D90+fYEPxhTlNkoG9oeSJPdT7sT
+JQhe2tucqY8BHB17uSMsdSlXDJvryefplRtfnveO/b2Q8xcauj/1BSDAw5FNHnAs
+meunYTQIT+DxdD3HWnoJGj0hqHGwzfO3pnFzMz/Y2f0Wl7BBC2exRYwrMmXLFr5Q
+IdQd4FSpg12EpBo7DsMyMGG3VejUa744Lg4cHMgpvHmVnUMzE1a1Yv+KWFLyfxzh
+w44r9fdyveDrtHxcQbyz7TngSRUcQKLcoUwVK6jDWEK7AG8uM2VbuRJwDetqMVAo
+ucVr5gScU6tepyHwSsC1/kSG8YDFtnJtdNy0hhuWcSSAEUAsfwkHbA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11.pem
deleted file mode 100644
index 30cfbd8ac3..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11.pem
+++ /dev/null
@@ -1,200 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-ME8xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIG
-A1UEAxMbaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCX3X8GrbxUXCENLok/vrVUA4snN0DJ+ja+Vct+doODtUFE
-99ZdYrT+qEPGAkioxAKElsWQDHoAjlv/TjoSxbV6BURJiMk+pIdN/N3oOtLz9N5y
-emO4Nq8Wv3A6dmTeqV/BvhEmKyKd9h/0Vy3gTP/eIqA8vhyxOpPLAB/gKIIWUwID
-AQABo3wwejAfBgNVHSMEGDAWgBSqaWS1UuWiYwoKoPNqFz8gsgPUtDAdBgNVHQ4E
-FgQUbFzipWxbYKUZ3ncFU1rjNTWvrRswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAImoE0/jphqmO48yRD2BCE5RlbnLVfXqKMbZ61lxs7X2Z2oC7QmmXJ8xH0vu
-YmnqpQTJjLwJc6janX9zk3DIdokB0PPu6HAtSb3GeETMG2tQFA3aeDyg8xjqGNBD
-OHfNDd64bvLnKZWb3bLEPfnZf6WTaRV/x56wf+7+NPg+zJop
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBOjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA
-643DGHdT8CXwVc2GtZQbRQTdptkiSzy79NPJD2XLU9LpWnrgyGzl4j7xUeYVspxY
-Ws/mpZCQOb2hs8eDfHKisjtcKj8Y8r0S8Csb3dsG19Rmjbg/2SiF5ZMaHzPi0QAk
-m008o0bwHaSBlFHigtvqu563VpgMs52ksx3BV1BKZQIDAQABo4GRMIGOMB8GA1Ud
-IwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSqaWS1UuWiYwoK
-oPNqFz8gsgPUtDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBATANBgkqhkiG
-9w0BAQUFAAOBgQA3+2MqCUqi2aRGC2CQMzptfla5lfBz0GLy7p1VBIoKLOe6/rAb
-IhVjO2X7pWEJosnjfmKUOggaCctxUuGgA/okQKTXTXQwXJwJNv2qS5lf1AHD4B99
-pZ5ebQ5FJ+RZBB6HiUWabWVfJ41WPI7ceJ8fh/Riau+XJg2KLE8myngRMA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICpTCCAg6gAwIBAgIBBTANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMHIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFH
-MEUGA1UEAxM+SW52YWxpZCBTZWxmLUlzc3VlZCBpbmhpYml0UG9saWN5TWFwcGlu
-ZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBALCdOCljPs8W35hbzEaZA4tSBiEAP7TpJfmh7c+CyK7UORyXxmyvM6U8V4Gs
-PBqmswzgVMkMhosS/Bhk73RmCn38i5dNYizu/3yOGp9piOxNNtktH6bhKyeHq/wM
-hHhgiZhACGBZZDdZFinn4ohF2SmbpxFuugZsJPnX4tj1KZJRAgMBAAGjazBpMB8G
-A1UdIwQYMBaAFEGmJOdLRsqNTr1i/ZUfoEVERdaDMB0GA1UdDgQWBBTTdhSEDG2I
-nAn6zC50pNDdzdZIezAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATACMA0GCSqGSIb3DQEBBQUAA4GBAK/N3uvvde9B7whxXVd4IA0MSe3DHGLK
-n/OBEw3cIXCYST42xPqPV8mkuz82JMTlete1834sdk/ayNFUloeyXzQTAdDg1JoD
-s6Cq3DzqfG1sVcu3wcsYbmpq7zxjXAERJQb2xSOYTvaJC0eb8FSfY6pXWx57qak/
-EPSox/J2fkc6
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUG
-A1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDlD9RQqLmz1R8mmDv95sxGdTT50F3U2U2PHAx0M0R/
-EmmreJx8mubNNUzKpH+jIQCsgKqAH+CJH/LDeCzow3F/cS0bcKYF/x1hJhJHO+pP
-uBgIa0yNq+hkNY9F+V/b+auEovg9yqIThiE9atAWfL1IRnRW5qpSi7si8qQdGWGt
-iQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFGxc4qVsW2ClGd53BVNa4zU1r60bMB0G
-A1UdDgQWBBS2psHqwFJT34b9ZknktEa+YzMMFTAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEw
-AQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
-AAjqz5quHRrfjyt+VRbtAM5KfKQS9G5SMsxGGdD/A8Nu5JYAN5FGi9X+RjLqeBzD
-6hmnFNNPFZx9LtO1s4wBoM06zoAddrIISUWehidWkxh7YEJSt4OSQ3fHNO0lgHaC
-WnvV8cZ3JLFezL+4ZDzXUJYoxmGCjerFTfIszoyvBuu6
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICwDCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEn
-MCUGA1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQC8nvl2y4d/yNUHP7aG5vOrKPi3d7UXdNZHRGzP
-KFYbJk+OVhNwnX26uR8hCEDDfjBI28f/541hjsDbgy60IS+nCklaPQkS5uD2R6Lq
-9WPZpnSNT+obNGFQqIuE0iQbBIXeXKy/E1lxCIQazKZHl7/QhjIso5/eRagUVF6m
-ahAnsQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFLamwerAUlPfhv1mSeS0Rr5jMwwV
-MB0GA1UdDgQWBBRBpiTnS0bKjU69Yv2VH6BFREXWgzAOBgNVHQ8BAf8EBAMCAQYw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUD
-AgEwAgYKYIZIAWUDAgEwAzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAKKfnJVgNVANlABGqhZPFB+MA6EeX9BLJIERR69poKaUCigLoIdovWQx9/sT
-MYvGE/gIulPhyTI2P+UM8yJHPmsucrlDwVwgyTE9WCsfVRZOV/DVqGzvHtpUGetp
-GZVUYWRIJtdAFXq1h04c6KSFenC2BqH6A19N8SkUyT9v8khC
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:69:64:B5:52:E5:A2:63:0A:0A:A0:F3:6A:17:3F:20:B2:03:D4:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:01:00:85:8d:99:b7:5b:7f:63:14:5b:20:de:25:35:78:25:
- 50:56:9d:78:eb:ac:15:34:90:c7:18:cd:03:ad:4b:80:9f:b2:
- 09:73:d0:8d:c9:dd:a2:5b:e5:c2:9e:30:ad:09:06:ad:8c:56:
- 7b:39:76:aa:1e:13:a6:21:2b:68:c4:93:f3:39:fb:7c:7a:f7:
- 2d:e4:d3:ac:5c:a6:38:07:9e:f5:b7:c2:54:6c:e7:76:9b:2e:
- 74:5e:cd:83:1f:25:c0:d6:4d:af:ab:29:47:dd:b0:87:79:86:
- f3:4d:89:80:2c:21:14:68:ec:4d:cd:67:d0:88:94:63:d1:db:
- f7:a4
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUqmlktVLlomMKCqDzahc/ILID1LQwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAjQEAhY2Zt1t/YxRbIN4lNXglUFadeOusFTSQxxjNA61LgJ+y
-CXPQjcndolvlwp4wrQkGrYxWezl2qh4TpiEraMST8zn7fHr3LeTTrFymOAee9bfC
-VGzndpsudF7Ngx8lwNZNr6spR92wh3mG802JgCwhFGjsTc1n0IiUY9Hb96Q=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B6:A6:C1:EA:C0:52:53:DF:86:FD:66:49:E4:B4:46:BE:63:33:0C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- aa:fc:6a:e9:aa:6d:46:16:9f:65:05:ec:bb:4a:e3:de:fc:ee:
- 4b:6a:61:7b:4f:ca:b0:86:90:90:f9:3e:ee:42:70:bf:70:51:
- 0b:ab:f0:b5:51:4f:78:f2:03:59:1e:5b:01:1d:6f:79:b6:d9:
- c2:38:83:22:b4:ae:64:06:63:5a:af:04:58:6c:a1:e2:3f:64:
- ce:f2:24:20:0c:a4:77:52:e1:cc:23:3f:5f:a7:89:20:85:fb:
- cd:f8:c1:09:98:bb:62:c3:62:0b:75:38:01:b0:93:d6:bf:22:
- d0:18:ff:04:52:25:72:bc:c9:d4:e5:77:fa:b6:84:9d:bb:d9:
- 45:a0
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUtqbB6sBSU9+G/WZJ5LRGvmMzDBUwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAqvxq6aptRhafZQXsu0rj3vzuS2phe0/KsIaQkPk+7kJw
-v3BRC6vwtVFPePIDWR5bAR1vebbZwjiDIrSuZAZjWq8EWGyh4j9kzvIkIAykd1Lh
-zCM/X6eJIIX7zfjBCZi7YsNiC3U4AbCT1r8i0Bj/BFIlcrzJ1OV3+raEnbvZRaA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11EE.pem
new file mode 100644
index 0000000000..df95d54f0f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest11EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 13 79 42 A0 AC F6 47 3D B9 5E B6 E8 5D B5 7C 8B 86 3B 91 37
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApygAwIBAgIBBTANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowdzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExRzBFBgNVBAMTPkludmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJpdFBv
+bGljeU1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDExMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA7Ubrj1mNP+NcBMyG2sr7H6cZ6y3lj+3xG6IfCsfO
+TWglSnkb2CjlNIx/NjcGYn1YNubiDge31rG7CZNdO61NGtYgFxiAl3DQtg2HR+se
+TWg7h8ZdTt6bCV2ccoGTajtCzKtfJbxEjC+ah94NvIk+IHcEu7JSf9A94efdSxnH
+ESeVTat7aPkW7UlwTUZ/ua3oJ+1WwdUN3KgVmB9mDbATCYfiRk63RL/X1cKQZr2C
+qYGnhh8ugZme/BgoClJrvDw0rYnepgPxYyV/XDTHe1F/KCclUCt2X74n9kwIGcyk
+89i9pk4Tmr4WWDkSViuBBym+f/SDxnUFsgg4d2k265vaWQIDAQABo2swaTAfBgNV
+HSMEGDAWgBRZuWxk6vOuluq2UVwljzvP7fWTDjAdBgNVHQ4EFgQUsEmMF+z3zVR8
+cNCXb40wgeCroccwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUD
+AgEwAjANBgkqhkiG9w0BAQsFAAOCAQEAShWF28EnDlNq3BCLCZnLPBE173JUcUzG
+W8M3dA/+WBXujtD0xCKDnWMy+2QVNZkiao4ovBJBhZQXVVhkv1lGulx6kpuQwv/f
+G8HB0esbeYOvGsRntOQM28vpioCKn2+7jG79SURwXGLO9k4QtQKEVrbOyQq+ki1O
+r4ZUIBsKnsQe14SJJWN/vqAOfvoA6StL6l0LHoGr58TZdEyqINecPq0Uw+KWQLpN
+oq//RG53Vm9P6yujzumBLf6llJII1izqotfy7jjFPS0azvJUO+LrtNMZB0Zf+8/L
+0yj1hgvr5+em6YVvaOX4kG8xBQuSNYLyPF2O9aUo97lqZLKvyNm7Kw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 13 79 42 A0 AC F6 47 3D B9 5E B6 E8 5D B5 7C 8B 86 3B 91 37
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,713450B885AEA6B0
+
+XUgfUQQxUwpHLBeZxdJ/HzBHng6cMez7ndN+8M68U02XwYk6Ypa31Ny5FzdCV6Nn
+tNDPlFUuc3aoH28fAcVccb0wFmsGYcodnYDqlsEyB4ednidgyTB46m4wK34kPH7H
+86wztEN8ruPKZIXUQM/blOC6NMbJsbFSGS0v+izolbX9ne3YaHqUJ/8/fxJ7HV61
+ZPk8f0xlojgbYBetrzD0bAzmJfTTjUgnBDTwE7HxS0lydnqZM6BBE59usDZ+n0Py
++TzRl5v+IE8aC9Y6n2LzxzoXNNdsIG/ooSmPYwx9lGFW1meXtALaGDsEKS/fJLN7
+N1CEOpatI5lKbpJX/g5Z3sKmFLdDaqlOBWaY4rqp3OeKmCDsDonu4urBfCwGmWMl
+LCEXXqsz51BtVoLiP/x1zzjdutgLYx3M4dV4qkD9hiCPeaq+BCz/N8nc2bKu/ldt
+j1jV+/xQs3VYNitR/lhN3Hg32m0C/VSZ428jJUMKbjXQBca5CcYN2yGEpLAC7pnG
+C+IW2Z1w4nBJfs4KCeB0WIeDc6KMPgsiG5Joc4LlGEssmMJL4fHENyiXnA48Lc/s
+jF6vnWSjOU9Lck/0aoJYhNMoXebVhOddexAS9vjl90IV90MYMBChcPVfzqRbMOWB
+PMX8z5RDOV4lcDfE1whYmkkjwnU7H3iMYXv3vCxropvj/YRk3cu7DCS9FN60BrNJ
+ybU+uGsTFog1Rl4hFP5KQ233dy9+cpkkgc8qL6QSUeO9iebDPEVyP8uiHv/n5Add
+yEQTuyHIy4EsAFmeVZV1A3zXi0RX0UoHJ/275EJhh2apV4T9hhvAkoOxy8EC2n8m
+UocPHdBs5HQXcyVa2nmiRwSnXm04V6SldsunJ21XiGMWAckDLfSxPYuwNgZxZx+/
+lrd20Ol1tj6vic5k15iCnNK+kaTjO+EkS4/0XrJBtve1Fa5HO2RVuLiGG3ddqfsY
+Zdy6pH4N0Sb6B7y1d8qFRcRE56sWK6bGwQH6Uwq4IREMwfNjWKYghl0Vg/qh6+WU
+djCXwySkWkxzR4sswSisAAFqH+NBdBPRgFU0UBy6ayggEO8Ry12UnDV3Ver/TmpV
+KX/tiZ+lz4DRHj+MbVMIOXJtpNxlfiByof0MMIRQ3RE6Jne/S9JCVqUWTLVb030J
+RXEa0Z0K7w+6eWKF/oSaNj4u7TQvX+sO9+DNYAfwVcW4XXnIfTUovsfrC+rYaQ6P
+/9kuB4vDmV06sCzCcBs8Xuq+wywAUJOu9t9xGNHmiEfCCcHrz/qx849flTIAFrvB
+yxR7KQ/4bCJu5f7NmdN6ZY6T5luQY7BRmE8Sf0D9IdpWxXO8rlmhnnk8NJeY4YdJ
+Fz8xaWb2AtvBcaVHkgK/mxlE0GuHVQqXUVf7p9N2Jy8wCbgk+YN6ycEqD0DTJHAz
+MhsSbkHICtLQ+hccdAZyzQjVnggzjfgrejJRKvguDvTa4kS2Up0yfo7IZWkQITfU
+iyKgd5gs0yM1tnUEI720CKYkuwVmgeB8PhbvKeAUh4aMCsWGtYyo6EoQdFR/RvLN
+4LcYszGIv8kVZtUO1jNinHSCQ0S+aMUwv5MkVzgstZBudIY59YUR9A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8.pem
deleted file mode 100644
index c6ef8e0f7a..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8.pem
+++ /dev/null
@@ -1,233 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-ME8xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIG
-A1UEAxMbaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCX3X8GrbxUXCENLok/vrVUA4snN0DJ+ja+Vct+doODtUFE
-99ZdYrT+qEPGAkioxAKElsWQDHoAjlv/TjoSxbV6BURJiMk+pIdN/N3oOtLz9N5y
-emO4Nq8Wv3A6dmTeqV/BvhEmKyKd9h/0Vy3gTP/eIqA8vhyxOpPLAB/gKIIWUwID
-AQABo3wwejAfBgNVHSMEGDAWgBSqaWS1UuWiYwoKoPNqFz8gsgPUtDAdBgNVHQ4E
-FgQUbFzipWxbYKUZ3ncFU1rjNTWvrRswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAImoE0/jphqmO48yRD2BCE5RlbnLVfXqKMbZ61lxs7X2Z2oC7QmmXJ8xH0vu
-YmnqpQTJjLwJc6janX9zk3DIdokB0PPu6HAtSb3GeETMG2tQFA3aeDyg8xjqGNBD
-OHfNDd64bvLnKZWb3bLEPfnZf6WTaRV/x56wf+7+NPg+zJop
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBOjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA
-643DGHdT8CXwVc2GtZQbRQTdptkiSzy79NPJD2XLU9LpWnrgyGzl4j7xUeYVspxY
-Ws/mpZCQOb2hs8eDfHKisjtcKj8Y8r0S8Csb3dsG19Rmjbg/2SiF5ZMaHzPi0QAk
-m008o0bwHaSBlFHigtvqu563VpgMs52ksx3BV1BKZQIDAQABo4GRMIGOMB8GA1Ud
-IwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSqaWS1UuWiYwoK
-oPNqFz8gsgPUtDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBATANBgkqhkiG
-9w0BAQUFAAOBgQA3+2MqCUqi2aRGC2CQMzptfla5lfBz0GLy7p1VBIoKLOe6/rAb
-IhVjO2X7pWEJosnjfmKUOggaCctxUuGgA/okQKTXTXQwXJwJNv2qS5lf1AHD4B99
-pZ5ebQ5FJ+RZBB6HiUWabWVfJ41WPI7ceJ8fh/Riau+XJg2KLE8myngRMA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subsubCA
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIWluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMHExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czFGMEQGA1UEAxM9SW52YWxpZCBTZWxmLUlzc3VlZCBpbmhpYml0UG9saWN5TWFw
-cGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0ODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEA2ZkYyttS3QceAgvQBMI8apGZ8GOGdNJJrZmaGrXTlkDpRqFBGwv5vx0I
-D958BpDYH1LIN7/T0VKWubFI7UIsU8brS5aic8C92RXCvZM2QdGkQKoiWLE66AeH
-+Fy35j8Tkrk/hoO764l/U3eQB3MD2u4Hf5NuqRAGcngjWAJyIjsCAwEAAaNrMGkw
-HwYDVR0jBBgwFoAUfpdDpAJ93mWROzcZfSe9EqTz0KMwHQYDVR0OBBYEFDKnsv6Y
-5OcDK1R9UWEjFuJ9ytbxMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAMwDQYJKoZIhvcNAQEFBQADgYEARAcPbJvFFgARsBpZO6o4SSHkn4if
-ZfTlwL3z5foZWrjQ0JDVIBj6uz9n3sP0V/xTfR+ZYVH13WgaoIxBIRMhV8lzW7yu
-d2Zz/d98BA0wwE8C9yxqVUuPje9zLRlmAEVQcYY4eWMlFZz2d8XHyckt/LcrCYrK
-iNQtbHdgmlb3dDM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUG
-A1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDlD9RQqLmz1R8mmDv95sxGdTT50F3U2U2PHAx0M0R/
-EmmreJx8mubNNUzKpH+jIQCsgKqAH+CJH/LDeCzow3F/cS0bcKYF/x1hJhJHO+pP
-uBgIa0yNq+hkNY9F+V/b+auEovg9yqIThiE9atAWfL1IRnRW5qpSi7si8qQdGWGt
-iQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFGxc4qVsW2ClGd53BVNa4zU1r60bMB0G
-A1UdDgQWBBS2psHqwFJT34b9ZknktEa+YzMMFTAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEw
-AQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
-AAjqz5quHRrfjyt+VRbtAM5KfKQS9G5SMsxGGdD/A8Nu5JYAN5FGi9X+RjLqeBzD
-6hmnFNNPFZx9LtO1s4wBoM06zoAddrIISUWehidWkxh7YEJSt4OSQ3fHNO0lgHaC
-WnvV8cZ3JLFezL+4ZDzXUJYoxmGCjerFTfIszoyvBuu6
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMFUxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEq
-MCgGA1UEAxMhaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YnN1YkNBMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzSzQEVqFvTtWkK35YRQKG14a/Ui8zOCix
-lDhIv5FBbG4G15V4laMoRYB38uWxU4/v0K/7UsU7J2ZQZA0iJNgZdYZmM9mMF//t
-37x13Zxd4GcHDbX0FoSgZUNXxSF/AUN86GXCCjrFMhHZAFgqLuYaust5NQdTk9Li
-tSFfyfRl1QIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFLamwerAUlPfhv1mSeS0Rr5j
-MwwVMB0GA1UdDgQWBBR+l0OkAn3eZZE7Nxl9J70SpPPQozAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZI
-AWUDAgEwAgYKYIZIAWUDAgEwAzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
-BQUAA4GBALHfJ6kZFXxW875Sui9xpPd2/OXVv4ltULYqS4sYa6iAKR2nNl2dwe4x
-g4crvrxXC8Dp29uqsmno4zOqNaSVjEYctbN3htkL/k/QG4Y9GgklkdqZosT2UXV7
-BI1xQXAiQVbBwcABjHTEAoW4flzUO7+GhapXp36TsEUOYA32+n5X
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:69:64:B5:52:E5:A2:63:0A:0A:A0:F3:6A:17:3F:20:B2:03:D4:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:01:00:85:8d:99:b7:5b:7f:63:14:5b:20:de:25:35:78:25:
- 50:56:9d:78:eb:ac:15:34:90:c7:18:cd:03:ad:4b:80:9f:b2:
- 09:73:d0:8d:c9:dd:a2:5b:e5:c2:9e:30:ad:09:06:ad:8c:56:
- 7b:39:76:aa:1e:13:a6:21:2b:68:c4:93:f3:39:fb:7c:7a:f7:
- 2d:e4:d3:ac:5c:a6:38:07:9e:f5:b7:c2:54:6c:e7:76:9b:2e:
- 74:5e:cd:83:1f:25:c0:d6:4d:af:ab:29:47:dd:b0:87:79:86:
- f3:4d:89:80:2c:21:14:68:ec:4d:cd:67:d0:88:94:63:d1:db:
- f7:a4
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUqmlktVLlomMKCqDzahc/ILID1LQwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAjQEAhY2Zt1t/YxRbIN4lNXglUFadeOusFTSQxxjNA61LgJ+y
-CXPQjcndolvlwp4wrQkGrYxWezl2qh4TpiEraMST8zn7fHr3LeTTrFymOAee9bfC
-VGzndpsudF7Ngx8lwNZNr6spR92wh3mG802JgCwhFGjsTc1n0IiUY9Hb96Q=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B6:A6:C1:EA:C0:52:53:DF:86:FD:66:49:E4:B4:46:BE:63:33:0C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- aa:fc:6a:e9:aa:6d:46:16:9f:65:05:ec:bb:4a:e3:de:fc:ee:
- 4b:6a:61:7b:4f:ca:b0:86:90:90:f9:3e:ee:42:70:bf:70:51:
- 0b:ab:f0:b5:51:4f:78:f2:03:59:1e:5b:01:1d:6f:79:b6:d9:
- c2:38:83:22:b4:ae:64:06:63:5a:af:04:58:6c:a1:e2:3f:64:
- ce:f2:24:20:0c:a4:77:52:e1:cc:23:3f:5f:a7:89:20:85:fb:
- cd:f8:c1:09:98:bb:62:c3:62:0b:75:38:01:b0:93:d6:bf:22:
- d0:18:ff:04:52:25:72:bc:c9:d4:e5:77:fa:b6:84:9d:bb:d9:
- 45:a0
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUtqbB6sBSU9+G/WZJ5LRGvmMzDBUwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAqvxq6aptRhafZQXsu0rj3vzuS2phe0/KsIaQkPk+7kJw
-v3BRC6vwtVFPePIDWR5bAR1vebbZwjiDIrSuZAZjWq8EWGyh4j9kzvIkIAykd1Lh
-zCM/X6eJIIX7zfjBCZi7YsNiC3U4AbCT1r8i0Bj/BFIlcrzJ1OV3+raEnbvZRaA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:7E:97:43:A4:02:7D:DE:65:91:3B:37:19:7D:27:BD:12:A4:F3:D0:A3
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 04:cc:f2:b1:f4:89:f0:41:53:c8:66:c7:4d:6f:88:a1:63:45:
- 28:ff:81:51:07:c0:ef:98:b9:b5:a7:9b:b3:77:d9:1d:ed:f1:
- 6e:80:66:f4:0d:cf:35:ab:67:18:fd:e0:10:7c:0c:06:50:44:
- fa:4e:bd:eb:1a:69:b4:e5:80:56:a2:21:b2:8c:0c:36:6d:13:
- ac:b4:1a:00:86:bb:90:69:00:ff:66:c4:a2:16:bf:e3:70:5f:
- 2a:dd:c1:78:cf:a8:cf:1c:d3:33:4b:b2:67:6d:16:96:23:3b:
- 08:68:e3:00:c0:71:88:38:16:17:7e:fd:fb:f7:5a:79:77:f6:
- 6c:f5
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIWluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUfpdDpAJ93mWROzcZfSe9EqTz0KMwCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEABMzysfSJ8EFTyGbHTW+IoWNFKP+BUQfA75i5taeb
-s3fZHe3xboBm9A3PNatnGP3gEHwMBlBE+k696xpptOWAVqIhsowMNm0TrLQaAIa7
-kGkA/2bEoha/43BfKt3BeM+ozxzTM0uyZ20WliM7CGjjAMBxiDgWF379+/daeXf2
-bPU=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8EE.pem
new file mode 100644
index 0000000000..7f8ad6be61
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1D 6D 26 20 E8 AE 2F 69 0A A5 F2 4A A6 C3 8A B6 AD 96 4A 2B
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YnN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowdjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExRjBEBgNVBAMTPUludmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJp
+dFBvbGljeU1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDgwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC21AXVGQebH8AHBIoewxwmy42xH3DuTS5GYC9g
+FXijp4jeOhdLJCM2uAzHMM7Qib+uSYR0O/Cdz9NKQ/Np9gudh49XgtGMzflsjSM7
+SgijS2qF97/TYv3wq8BkFjATs/PXJWo2S2VQuPce/yHzo63LO8ObEjnHcC1j4r5G
+LY7718RgxXw6NeJDSXOxwJtFjPLMrXEFSVOiPh0vbew3EM1x9ieqJqVwcSaiBUpX
+qIawbxJczfi2UqTuj9SVa7zuObF8qrDdhkdNUYOEFc2IzuVVIOskotPcAB4PwbDE
+HFw02dcwdFrG5BUHhpdvIOmEy5IxQXwMyvsd0Phv/kwqNw/rAgMBAAGjazBpMB8G
+A1UdIwQYMBaAFD5FdKKL0vFWjEYBZnhwJMYiwQOeMB0GA1UdDgQWBBSyFwdJn4xf
+l/2lQPJVfyRDZWC6gTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATADMA0GCSqGSIb3DQEBCwUAA4IBAQAY3dfWtAt0zVsSibvIAi3jQ4bHtVq6
+jSo+i/7Cl2E2qevfmDrS/uUPwjjUXLOsJeiyFIPl/lB8yNC8KkT0oEe1PTr34gLw
+9TTnLt3ZRdCbKqg2WRMv9Y1PsBgWTRcYED+/0U8UQxePr2pyHDetdpJuT+phwvRc
+2GvvJ10UjVJvRCVw521PuHwDyF8JBmpsJQSPOe/L+jnLWOehAxHOeI7CMaqsddpq
+JEq6LZ5ofOV7JaFJMxYscuj9mLRKcXTAnnWUp/9PzrUGI6wr1WG5OdECNwQHqO9s
+uxeEelksAhiqK4Yg1BFJeppQvyfKwd/Njw7ohwTYBcsfojiSLl2a//HO
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1D 6D 26 20 E8 AE 2F 69 0A A5 F2 4A A6 C3 8A B6 AD 96 4A 2B
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,63347D0B822C10C3
+
+HPQLqJ3F6WsoqOtawonx9WdBroYveRAPN69bZFHKZ0pygr/kwvoCe7hY7FWZP/4k
+JlmpQ0fVTmh6nPRcl4KLc9Dk3CoJYLZwejlKMhjpF5SEBMuoYEqZYC8MGgV4NOZt
++KLZCxTsgXVz1HOXVbXXKZuWaf+X2ecbUPU71/aij6GZzYQ9uoJAZ8lPmW4T2Ndd
+ibtiMvwJO4R6V6CTdGvfaaQ2wrD0h5MsR6ZZXdLLKyu4KviFQtX5kOhn3K8eUFTT
+IDLmnE7mZahEiKmDDQ3p+eO9xlgUihwG9L7l2hXaSHvxEtdglqAPW52Ym4gzKzfD
+LJlA5la3tXz13c+syqO80xkhZOs9ZAJJYvvrcVG05kFWADr/Mx6qeik52uMdizVk
+a+ugMhLzdnaMQDGbH0DPaes0mV7vqkVv+3M9Zhad7S6VpqkE10SMy0zpOKuNdPu8
+ZpaEN/DyCwLGcpYRs7KnsCnI7pZV0stizEGx4SzuMiL0JTEcky550fxGVO72GLlM
+RuMHohNxAB9ie5kCJoM5QiNGaDaw8x1k0duTSGpsN+ZDFvE/0KTq46Mwumfx9cVU
+mPhkPiiJ89tQx7Ejv9wUK1J4w14DkATQyAEueZePTQ04YMF/spBGXb1YtaMqhbpF
+HDwcnwL+dXH5N8R3HBxUsVKk6fJMM9VfzmmJxw6g77quo/amRsQqQBptD8pBDms5
+LziokjnLT7Jpmc2g44HtTTwKFmFi1E/DZTRQp3nx6WcsYI4o8waHDk2KSY0A4ll0
+2OgNYwiEh5J60dsxMebTORFO/DsATVHE3kCUGvS0I2uwnADgteO8jrTCRaw6Mq08
+VucKsKddHLiC6McgdQukFiRq0w0vr1vcd+IWJwTSlHcRheDWOfaguJYoX8SMBPu9
+Et15NwYkYl03cZB3FNPXhUouRqYIwL85dNCdYlyp43hWQRg/LX+ENaSNr/hJ7+ea
+9f8jYvH1whWj34YKVYpFfbXu2yJyvw2Tz8yTBRiKWszcSXm/uXRJczIzWZFfWRp5
+Su1Qeh6CBjpj/yXd68xsqdOc/akI/ftZvrvklJxbUcJ7u35oTvcTtUE8k+aIvGBU
+HvA+cX/Jg12XuYFRIsdHaxyocuWNum35RY9IktqEkcc4xhY550kAzCvgTFawA8fj
+ODQexc0n8SEc3a57VpRnXLPRe7uKjvNeqjbymRrFhohyvB1pfqgFGKmAb7ppUk0d
+1KIART1MaKtG7/IbddaEmyZ60QaP5N6UtiOWbtZHMSGV265XOoh7YWiT15F9p5go
+voqg0d/RHqlxisDcXOyTS3c3dWsqixFEoocEgocpDVCQ8I6VB6cQ8bCicwdp2AXQ
+c1cTmuOlQHmnQbGR7wahWEauEMMa0QUFz75hEQO+qwygtrTxwetTmEzXlVVU2Ruq
+56Hu4IjlXrYpC2NAsE79hmbguTGZkdlCbVzTC/vKjKaOJ6KlWUDdfbgHFJzRkSoJ
+uC0D5I+fFy6kdBpavlCEYktrvR/PnHVRtrE32i3UevEsfc80+n5QENqutYS40d9P
+tL+xPb3QYYkiLbgfLBf2vttk52aImULXlPQWqzf288dSE+WUKaExM/qMVii0t2Ka
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9.pem
deleted file mode 100644
index ecd49f4f58..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9.pem
+++ /dev/null
@@ -1,233 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-ME8xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIG
-A1UEAxMbaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCX3X8GrbxUXCENLok/vrVUA4snN0DJ+ja+Vct+doODtUFE
-99ZdYrT+qEPGAkioxAKElsWQDHoAjlv/TjoSxbV6BURJiMk+pIdN/N3oOtLz9N5y
-emO4Nq8Wv3A6dmTeqV/BvhEmKyKd9h/0Vy3gTP/eIqA8vhyxOpPLAB/gKIIWUwID
-AQABo3wwejAfBgNVHSMEGDAWgBSqaWS1UuWiYwoKoPNqFz8gsgPUtDAdBgNVHQ4E
-FgQUbFzipWxbYKUZ3ncFU1rjNTWvrRswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAImoE0/jphqmO48yRD2BCE5RlbnLVfXqKMbZ61lxs7X2Z2oC7QmmXJ8xH0vu
-YmnqpQTJjLwJc6janX9zk3DIdokB0PPu6HAtSb3GeETMG2tQFA3aeDyg8xjqGNBD
-OHfNDd64bvLnKZWb3bLEPfnZf6WTaRV/x56wf+7+NPg+zJop
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBOjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA
-643DGHdT8CXwVc2GtZQbRQTdptkiSzy79NPJD2XLU9LpWnrgyGzl4j7xUeYVspxY
-Ws/mpZCQOb2hs8eDfHKisjtcKj8Y8r0S8Csb3dsG19Rmjbg/2SiF5ZMaHzPi0QAk
-m008o0bwHaSBlFHigtvqu563VpgMs52ksx3BV1BKZQIDAQABo4GRMIGOMB8GA1Ud
-IwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSqaWS1UuWiYwoK
-oPNqFz8gsgPUtDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBATANBgkqhkiG
-9w0BAQUFAAOBgQA3+2MqCUqi2aRGC2CQMzptfla5lfBz0GLy7p1VBIoKLOe6/rAb
-IhVjO2X7pWEJosnjfmKUOggaCctxUuGgA/okQKTXTXQwXJwJNv2qS5lf1AHD4B99
-pZ5ebQ5FJ+RZBB6HiUWabWVfJ41WPI7ceJ8fh/Riau+XJg2KLE8myngRMA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subsubCA
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIWluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMHExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czFGMEQGA1UEAxM9SW52YWxpZCBTZWxmLUlzc3VlZCBpbmhpYml0UG9saWN5TWFw
-cGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0OTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAylxeQoRBPgPQvR6PrLfrhYdQPa+pAircmIyNSp/en2b65foW6Dvx/sHc
-Y9lLvbx48Dv+XPUR4a0xsGGvX0GBy4GOUv+6nqaFOdce8VYwmIFybQGDaxoqytYo
-bhhZZD8g6dfyWuWMQ5LUt5vyIL2FbCnDevgD/ivnIwBKJFEn/B0CAwEAAaNrMGkw
-HwYDVR0jBBgwFoAUfpdDpAJ93mWROzcZfSe9EqTz0KMwHQYDVR0OBBYEFN+F7ghB
-89TFNj8vas0p8wMYmcU1MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAIwDQYJKoZIhvcNAQEFBQADgYEAKODQTLmhlOsijlIfpBZNXzohZOzj
-J27r0eok4ACPAFNwUCue2GMNerlrKqHiHChov8zvh4AoQDfcZBwRFcGnRMq8QyDn
-EkxvE9P/4Ib7XERwVDPmVPgvQYvcqC7hz7B7oYO7rigckrroh2X2x/tynphxnIRS
-6Mpc00/1Fs34Cv0=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUG
-A1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDlD9RQqLmz1R8mmDv95sxGdTT50F3U2U2PHAx0M0R/
-EmmreJx8mubNNUzKpH+jIQCsgKqAH+CJH/LDeCzow3F/cS0bcKYF/x1hJhJHO+pP
-uBgIa0yNq+hkNY9F+V/b+auEovg9yqIThiE9atAWfL1IRnRW5qpSi7si8qQdGWGt
-iQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFGxc4qVsW2ClGd53BVNa4zU1r60bMB0G
-A1UdDgQWBBS2psHqwFJT34b9ZknktEa+YzMMFTAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEw
-AQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
-AAjqz5quHRrfjyt+VRbtAM5KfKQS9G5SMsxGGdD/A8Nu5JYAN5FGi9X+RjLqeBzD
-6hmnFNNPFZx9LtO1s4wBoM06zoAddrIISUWehidWkxh7YEJSt4OSQ3fHNO0lgHaC
-WnvV8cZ3JLFezL+4ZDzXUJYoxmGCjerFTfIszoyvBuu6
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMFUxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEq
-MCgGA1UEAxMhaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YnN1YkNBMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzSzQEVqFvTtWkK35YRQKG14a/Ui8zOCix
-lDhIv5FBbG4G15V4laMoRYB38uWxU4/v0K/7UsU7J2ZQZA0iJNgZdYZmM9mMF//t
-37x13Zxd4GcHDbX0FoSgZUNXxSF/AUN86GXCCjrFMhHZAFgqLuYaust5NQdTk9Li
-tSFfyfRl1QIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFLamwerAUlPfhv1mSeS0Rr5j
-MwwVMB0GA1UdDgQWBBR+l0OkAn3eZZE7Nxl9J70SpPPQozAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZI
-AWUDAgEwAgYKYIZIAWUDAgEwAzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
-BQUAA4GBALHfJ6kZFXxW875Sui9xpPd2/OXVv4ltULYqS4sYa6iAKR2nNl2dwe4x
-g4crvrxXC8Dp29uqsmno4zOqNaSVjEYctbN3htkL/k/QG4Y9GgklkdqZosT2UXV7
-BI1xQXAiQVbBwcABjHTEAoW4flzUO7+GhapXp36TsEUOYA32+n5X
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:69:64:B5:52:E5:A2:63:0A:0A:A0:F3:6A:17:3F:20:B2:03:D4:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:01:00:85:8d:99:b7:5b:7f:63:14:5b:20:de:25:35:78:25:
- 50:56:9d:78:eb:ac:15:34:90:c7:18:cd:03:ad:4b:80:9f:b2:
- 09:73:d0:8d:c9:dd:a2:5b:e5:c2:9e:30:ad:09:06:ad:8c:56:
- 7b:39:76:aa:1e:13:a6:21:2b:68:c4:93:f3:39:fb:7c:7a:f7:
- 2d:e4:d3:ac:5c:a6:38:07:9e:f5:b7:c2:54:6c:e7:76:9b:2e:
- 74:5e:cd:83:1f:25:c0:d6:4d:af:ab:29:47:dd:b0:87:79:86:
- f3:4d:89:80:2c:21:14:68:ec:4d:cd:67:d0:88:94:63:d1:db:
- f7:a4
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUqmlktVLlomMKCqDzahc/ILID1LQwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAjQEAhY2Zt1t/YxRbIN4lNXglUFadeOusFTSQxxjNA61LgJ+y
-CXPQjcndolvlwp4wrQkGrYxWezl2qh4TpiEraMST8zn7fHr3LeTTrFymOAee9bfC
-VGzndpsudF7Ngx8lwNZNr6spR92wh3mG802JgCwhFGjsTc1n0IiUY9Hb96Q=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B6:A6:C1:EA:C0:52:53:DF:86:FD:66:49:E4:B4:46:BE:63:33:0C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- aa:fc:6a:e9:aa:6d:46:16:9f:65:05:ec:bb:4a:e3:de:fc:ee:
- 4b:6a:61:7b:4f:ca:b0:86:90:90:f9:3e:ee:42:70:bf:70:51:
- 0b:ab:f0:b5:51:4f:78:f2:03:59:1e:5b:01:1d:6f:79:b6:d9:
- c2:38:83:22:b4:ae:64:06:63:5a:af:04:58:6c:a1:e2:3f:64:
- ce:f2:24:20:0c:a4:77:52:e1:cc:23:3f:5f:a7:89:20:85:fb:
- cd:f8:c1:09:98:bb:62:c3:62:0b:75:38:01:b0:93:d6:bf:22:
- d0:18:ff:04:52:25:72:bc:c9:d4:e5:77:fa:b6:84:9d:bb:d9:
- 45:a0
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUtqbB6sBSU9+G/WZJ5LRGvmMzDBUwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAqvxq6aptRhafZQXsu0rj3vzuS2phe0/KsIaQkPk+7kJw
-v3BRC6vwtVFPePIDWR5bAR1vebbZwjiDIrSuZAZjWq8EWGyh4j9kzvIkIAykd1Lh
-zCM/X6eJIIX7zfjBCZi7YsNiC3U4AbCT1r8i0Bj/BFIlcrzJ1OV3+raEnbvZRaA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:7E:97:43:A4:02:7D:DE:65:91:3B:37:19:7D:27:BD:12:A4:F3:D0:A3
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 04:cc:f2:b1:f4:89:f0:41:53:c8:66:c7:4d:6f:88:a1:63:45:
- 28:ff:81:51:07:c0:ef:98:b9:b5:a7:9b:b3:77:d9:1d:ed:f1:
- 6e:80:66:f4:0d:cf:35:ab:67:18:fd:e0:10:7c:0c:06:50:44:
- fa:4e:bd:eb:1a:69:b4:e5:80:56:a2:21:b2:8c:0c:36:6d:13:
- ac:b4:1a:00:86:bb:90:69:00:ff:66:c4:a2:16:bf:e3:70:5f:
- 2a:dd:c1:78:cf:a8:cf:1c:d3:33:4b:b2:67:6d:16:96:23:3b:
- 08:68:e3:00:c0:71:88:38:16:17:7e:fd:fb:f7:5a:79:77:f6:
- 6c:f5
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIWluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUfpdDpAJ93mWROzcZfSe9EqTz0KMwCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEABMzysfSJ8EFTyGbHTW+IoWNFKP+BUQfA75i5taeb
-s3fZHe3xboBm9A3PNatnGP3gEHwMBlBE+k696xpptOWAVqIhsowMNm0TrLQaAIa7
-kGkA/2bEoha/43BfKt3BeM+ozxzTM0uyZ20WliM7CGjjAMBxiDgWF379+/daeXf2
-bPU=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9EE.pem
new file mode 100644
index 0000000000..9529a12af2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedinhibitPolicyMappingTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 03 9C 43 5D 1B 7D 07 1F 16 A4 A8 35 4A F8 11 40 8E FF 44 71
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued inhibitPolicyMapping EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YnN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowdjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExRjBEBgNVBAMTPUludmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJp
+dFBvbGljeU1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDkwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDh7DaIU7QitpglwGQwVBh4gziggxUNZYv4N9CF
+ua9cMz1wtL8igEcrkH3bS7ExC4XDquZH5UQpQ/rrMvW5McM8DB8yoHcDq6PdTHts
+swQ/IhF9IxGcHYlC6xXf2IDFk/QVa6PGEa8a+M///xPK5m3ikh6LJDJhWwOjcYyh
+uOh8CR5E7qN2F48w/Rn3JkOVEfYzR+x36DUE4qYZ9prP1EE9f8zurYqPNfGRRfou
+pSANSXjvEd4WJgWeL6Hc0KnEbxTvGywdIZFopeyxyWFpi5Dhl0XoM5ViS5IqL2yG
+6yJgtrnhkwRV6vTRr0pZlHul1LPLVf92wGHGe3VdiXRBwI7jAgMBAAGjazBpMB8G
+A1UdIwQYMBaAFD5FdKKL0vFWjEYBZnhwJMYiwQOeMB0GA1UdDgQWBBQGUJPs1t5H
+/XdkaQnJb4buZH4dZjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATACMA0GCSqGSIb3DQEBCwUAA4IBAQBd4fpr0FEBAS7pX+anaaynR6VwZngp
+VoG0SZ0FUwOTvUAU80cI8G0QJCcjQ7Ho6/KmeKznOb7zXJj0j6bmdlUvOTTQCDtd
+Qh3Exa0x4Yv1s/wp3FVMFt8kc5V31ABQDj480IrFjHW5TZF7lsSE3eHpxKkl70oK
+idmdbcVUbLHRm1+S8RYAUMrQn1kJpnP61URJZgiYoFzbCYgcswaIrf0oFZwdTZ/C
+ueXiVLJdlbVkYp4u6FoC77Oo7vcIe8kw8i1byu2PaOmIjpmI4xjOBlYbwnqOeG7X
+Z3vfgaVVMZ/fygknW+LpZZakKSnAkDun7Pm5WRNDCiRRn8rVL0NIYnuK
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 03 9C 43 5D 1B 7D 07 1F 16 A4 A8 35 4A F8 11 40 8E FF 44 71
+ friendlyName: Invalid Self-Issued inhibitPolicyMapping Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E7BB37E587E6FC08
+
+qCYMlRWoxSwmtR9ff3GkkMZm92syFY5jMFQmaddFj3gBagBR7MCMlL8t8MUEvuFA
+VCyYG9xfgDyAGE4o0ALc4jy3ZQG1wqf1WuUeNxNmx1JHtmGGvUIIkIK21hIQVWP6
+1CgGOh1MoCOp3SEI7bBTC//3rqdelq1QvC0tCORmbFZYdNCn0YUjwmLOeaWh1VhE
+YK5O21MUkkcGOaeDEvq8TNQ8GXMCZQVYa0ooselhZpFG7puKQ3Gm4D2IIqXOXtnv
+HuUlxpCYedxF7ggNkJRLhEDYv4HQ7jyHiRompH8dYVTNEhHSw1ivI3TxVC0Rbd0R
+jspNZL3rn8yb4Lf3yembLHLozmREBoKArQPc7rY2SGeuz5lG2szibuJLTkx3qMGt
+6agb1wGVfdlnTd1AOgUL2ChoYiMR56IJFcNzbkfNI5jGuq4TaIStkgdWygnQGJzS
+N86elMc+LgnCUI1P0HZm4RzLV5MTrh4N7MK56rAU6OVCRSLPSqN7ds8V54owjHBt
+RycZLp3E/7o2m93Vp+/IcLSpuVHs3aW0hA49DbOH4UyONIKwSFpPfsfFRIgftrCy
+Tc1AD6rEuJzmbbHPeiB1sxbgSxMPL26r+DiDBwTo61FpGWAoRPEbBptjFzLyKESi
+B6I/DWpIIJLSq0uYtTpE1JzIYisK7GV2YUf2DcmWOT9kfXLlsLNGWOalk5taYuft
+T8vVPcF+ALXQElcr0Gf5WY2UnpWDZ8J2rQZvJZHYVm5SsnvmoX48aUvp1+HcC5BR
+2GLM7bMerNvLQDGBtFrbvLwhFDxBJ6b4MCQ5lLa5siw+tUqRoLJl9IbzruH1mGoe
+zilz8uYUeJ9MGy8vMkxFbG+LeQLQn6bT+3WiWjJoB3K1foloZHOHHYwjiUaguMWZ
+giMBC52RYZRfFI8TmwReTreJFFuEsTwceUaLKg1mlHq+c32MRrNb5133ir863rFu
+tKy7PNe2buXgC1Url8BBC9C3UYUy8ISVLbdUfWmjfeqBrk1uWRdGsb84ZvxMfVzw
+iBbdXCayyMX86PlVCp6NboTn/K+Tth4bQQx9wRSB+sfr/fe6eDnaIQ85LsdoXr+k
+sJ8pOoH8DtTwbiQRsTh6pnivOiN+zTJK4VGDT+7AeFBjRRi7sMF9AkuZWcNiiKj1
+bbYJAEMNVC6bioxnWb4240wCy1TBelFITStR7RtfnVFLTmV1SmFtkLDoGqe80w6c
+I+zPVrbTgoHfa6U7fFIFid5BEhf1oKoySYPV9JlFTvwvJZV7W7EmRx6ycH62r/1u
+lauM0tFYhhuwWvmGB7ha5uHne9wKPb4rJrzApG1lgQEi2IR/MYBGj1UkILAqx7sv
+3VxBP82zMKJ7otH1TiiDMPWqanj61jUFfGhKx3S0SpDNm1jklIKtO6U/1bC9T7Xy
+jXw7fVPDpH26/gBSycX199ve96uvolzAmeF1qY9PY1CF2fnJNaZRzoo6glAfNr5u
+LwCP3jKOT8YRVUfLDMKJlWU7/8OJDR5FQCIjjaIDaue5dzRQYPAmmqd69h1QcG/7
+bdJOy46SR5R0dMV2BpGkf5T5Vk7oP8I0I1Qtb6hy0Ew90HH5Dhut6kHr7Sju2kPm
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16.pem
deleted file mode 100644
index cec2eaaf87..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16.pem
+++ /dev/null
@@ -1,179 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXXXPbNnk
-MU3wxjjwCdA/Pj+lwkDk8WSxKGdOrcPMnFnrCdUnSqEES3K6/T7JRQyv6Y13Rt6w
-LAhrQI94UBcsAAQND4SOPyJUE3PonzcolJQ+EzkSB9qq6cxJokxTvxVTx2VN7bN1
-RJ7FrWovHu/vmKnwsOy3zv41U6KBfuf04QIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUIQy1AXZ207MqrCb8qqZP8tah
-b0swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJUd83zrSjxfaGwFdTCt
-BSI1mTeztSKFxIzrWeTxD3C0JHAxt1oM1AN8DQ/Ej8ja3rxhzsFQaWzdi3ixvnGr
-NbjLZH7EPWBPSSC2rTAcvLzVs2AuPsBkv7IKxg7HTJZtLbXDOIatWT+24OuKwTzE
-6cbcSe7zaz5qdojy0B72dLHC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMV
-cGF0aExlbkNvbnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDDqMCqoLUxLw5wCcxhD3+5J80k2C5ESu+Co4n3V3Nu2SyzcfKET0wx5QvxYm5V
-bzsntf6IudJpfXgzxHIwJ4i5v+Ycc8NYiqmCNhsW5sFRzhjQDyTWu0fEYm+tmyBv
-FavwXAcp8ptUMElDMAv/bKSD+7MDC9uHZQOmVsY0ndcNUQIDAQABo3wwejAfBgNV
-HSMEGDAWgBQhDLUBdnbTsyqsJvyqpk/y1qFvSzAdBgNVHQ4EFgQUOK0lyEJa1w3p
-SvQY5iylU6RQ9EwwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAA9NjcDXXcF4
-FXkwZWIDYtowLXCpbshsU80nGx0/7QVNApSTnUq9pe0t8qAClcYZuaXgB/uYINl5
-qozAW6KR4wFaNUv6mnm+0ppWeiTnIn5O37IycPbAKVZRhauf3p/cTkZ6RZ3MJ5Q+
-fMTJscvSXtMhU+Q3Pp5PGRXlXhs1zFNp
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 subCA2
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIICiDCCAfGgAwIBAgIBBjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQwIHN1YkNBMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAsFRY6folIcigIrpQ/iMlyqdk9EBMIL6NqCJEqkvun/36zcYeHsPv8t29
-hFHDBrhQT/Fi+9MNOXx0uiJT0cetYETo/HiiAqub27NG0Z82sxwsEiLASEWZ4ctu
-8AIom0mQl11rsK/4z4OemcI4Mxh5j6fCiI1ouogv1Vx4us4ew/UCAwEAAaN8MHow
-HwYDVR0jBBgwFoAUOK0lyEJa1w3pSvQY5iylU6RQ9EwwHQYDVR0OBBYEFAJSemtC
-TrDjzYKlY89uAwAjlIk1MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCFLUIH
-3Nuh+TAs+Kpg/tZTFK3cl2DGM1+W+wnsgn3pQhJnqIYCI/iAuPRs2bJGH1lQ0CTr
-HAQU9y0kmWpsNCzI6k9ZyuLd2w7MdXezVhjpE3iwAQCnVG1vw0MTFGzyR7wMeWp0
-Ejrp6mVdwu8LV6lngeqmNv0QNjYSutrFAsDHUg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued pathLenConstraint EE Certificate Test16
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 subCA2
------BEGIN CERTIFICATE-----
-MIICnTCCAgagAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50MCBzdWJDQTIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBv
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRDBCBgNV
-BAMTO0ludmFsaWQgU2VsZi1Jc3N1ZWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2Vy
-dGlmaWNhdGUgVGVzdDE2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfnEYg
-5tV8iksMhoNkR/PLNDStGXw9l6sTCiF+m+EF+/pDeN0Y/509SepxvXOZbQ8D7CkB
-PfgmSL8hs0dxdE3Fvf/AjvTFyyjI1q5wkFXd/qWMewquuMMm2j+FWn0fmSoFnyM6
-EEYvKLhqj1QuWiJJN/250ngjuufsh51HnlR/6QIDAQABo2swaTAfBgNVHSMEGDAW
-gBQCUnprQk6w482CpWPPbgMAI5SJNTAdBgNVHQ4EFgQURA7pZi8vxURs7KKf3U9B
-ItsxSAMwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAN
-BgkqhkiG9w0BAQUFAAOBgQAweIEFGj6V0Kr9Dz4wEyhUVK5bf5Frg+J8ap0YnoNT
-EmoLFqQtKPB3MVfcUkXrZAY149XFJJLI0v5VCK2mBN535do/Grxve2MMW8BbmmU4
-FQOKJruMJARneqYEHxbZUEmBvEoIoi4C/2SLxO7hOnhpiK+6UsetU35F19FPfGVp
-UQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:21:0C:B5:01:76:76:D3:B3:2A:AC:26:FC:AA:A6:4F:F2:D6:A1:6F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:7b:a5:e5:64:8b:31:64:fa:9f:8f:a3:25:ab:8b:c9:c2:ba:
- cb:b9:e3:5f:3d:e9:b9:f4:f4:f4:d8:00:4c:cc:9e:5a:36:b3:
- d3:53:12:aa:d5:ba:ad:94:a5:21:16:c4:9c:ac:3d:3c:e3:2f:
- 53:69:97:6c:2e:e5:82:98:31:e8:47:f9:8d:dc:ab:e2:8d:ec:
- b9:3f:b2:61:20:ad:22:24:f6:ff:90:4a:14:92:38:0e:9b:80:
- 3f:1e:11:f2:d8:7b:fd:d4:0c:90:06:82:2c:48:f8:9e:7e:91:
- 55:0c:21:e8:dd:95:ac:90:c7:d7:02:af:84:f4:23:08:bb:da:
- cd:a2
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUIQy1AXZ207MqrCb8qqZP8tahb0swCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAVnul5WSLMWT6n4+jJauLycK6y7njXz3pufT09NgATMyeWjaz01MSqtW6
-rZSlIRbEnKw9POMvU2mXbC7lgpgx6Ef5jdyr4o3suT+yYSCtIiT2/5BKFJI4DpuA
-Px4R8th7/dQMkAaCLEj4nn6RVQwh6N2VrJDH1wKvhPQjCLvazaI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:02:52:7A:6B:42:4E:B0:E3:CD:82:A5:63:CF:6E:03:00:23:94:89:35
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 23:10:0e:ae:60:60:7f:db:a0:d8:fe:8e:bb:0e:99:db:df:36:
- 32:a0:54:7c:1c:ea:79:12:34:f1:a5:cb:75:f7:4b:d6:5d:6e:
- df:56:9d:c1:d9:a2:a1:ab:7e:53:ac:ab:4f:fb:61:c6:86:bb:
- 60:ec:f2:44:14:49:22:54:6e:5e:72:96:23:b0:bb:d7:8f:e8:
- 4b:c1:5e:f1:16:d7:1b:2a:68:ef:ca:25:1c:63:15:21:7b:a3:
- 80:c3:50:97:f6:41:81:b1:ec:5c:5b:77:b2:df:1c:cc:48:97:
- 61:56:01:b2:9e:6e:8e:c0:89:05:82:7c:42:1f:61:34:e8:12:
- c6:72
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-MCBzdWJDQTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFAJSemtCTrDjzYKlY89uAwAjlIk1MAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBACMQDq5gYH/boNj+jrsOmdvfNjKgVHwc6nkSNPGly3X3S9Zdbt9W
-ncHZoqGrflOsq0/7YcaGu2Ds8kQUSSJUbl5yliOwu9eP6EvBXvEW1xsqaO/KJRxj
-FSF7o4DDUJf2QYGx7Fxbd7LfHMxIl2FWAbKebo7AiQWCfEIfYTToEsZy
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16EE.pem
new file mode 100644
index 0000000000..edf314a84d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedpathLenConstraintTest16EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 16 21 0C FD 5B A4 24 DF 48 9A F6 49 6E 38 F4 BF F7 79 21 9A
+ friendlyName: Invalid Self-Issued pathLenConstraint Test16 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued pathLenConstraint EE Certificate Test16
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDrDCCApSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExl
+bkNvbnN0cmFpbnQwIHN1YkNBMjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMHQxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMUQwQgYDVQQDEztJbnZhbGlkIFNlbGYtSXNzdWVkIHBhdGhMZW5Db25zdHJh
+aW50IEVFIENlcnRpZmljYXRlIFRlc3QxNjCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMUAJaSBrAZoZKqqNKxkwBcU+6HyF8FbDUmVONn7QXBreqY5hP/u
+iH4t1VgIIQfYuDq4KuFG8w+j8XlwNyG1/LRipLXAGFPTthfve4YqxksDMlEtjKEv
+6/Ed2/u27iRmTN4Xclfae50TcS/lPI7LcGhA3xb8i1zRV9jhwSOze/lUrH7w7XTd
+S0l+PZXwjFlz4rQF0nglux9GWUIIfi6j98lKkSlozIJ+i9UheODwktnaLcYIJdvW
+fh7c5g023RzmkF35VetdYnalZRQuAoqxRMMMJbUP4fQdHePTSG4N4tazyjeFebnE
+bvZcaXaTpXPe4EGW4oLQQ4yg6RP5f3hQEkECAwEAAaNrMGkwHwYDVR0jBBgwFoAU
+xgkqG/u46T5oYHrHl86zWFF7dt4wHQYDVR0OBBYEFPfHm47xpBBMA/uidLHze1WU
+6Yn1MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJ
+KoZIhvcNAQELBQADggEBAEaV6lhnnBOu4mwaZuNF2UldqMeLtPZchw0uoVW0fwjL
+9BLVSV6A8kwJnxINPrpcCOY56IHjfYR8cT1cbGRABEq+FDsdNFhRLXnUWnaPprGW
+fZo/Fb1KS6EfGupVp2h3jKG8fsSD81KfRaJNc/jbEJi0vKoHIlW87/SHk1B2sN57
+wMWG1d13zwbVULq34Dr125HMU4kgvvwyBPx2pf3tf4mAeXK8WlLyu5s3aTrLACso
+ZYRkh6hcY+LNx5nUa6xwU6LmwNg6VgnHu4aHCrjcofFDcF9Ww488XisnugMVo7FR
+8QiAz8k5MWqiBbvpfHkgvWLOdpj56uvH+waD3GjD+04=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 16 21 0C FD 5B A4 24 DF 48 9A F6 49 6E 38 F4 BF F7 79 21 9A
+ friendlyName: Invalid Self-Issued pathLenConstraint Test16 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A518FB9EF9ABBD73
+
+bCPVUoj67Xsx51BOv9b+sk6qYULYNCbXCXzMs9Db8Aos1p3jz24J8z2RuPss3WuO
+AewIRUEoQXvJ1WomHEfON62mxw7RSi3stDFNLpQ/V1JiMv0WZzUQrIynJIXxSoGC
+rMIkBHvX3kV5FnImE1AwU1YXWwtR8Hi4vpZpQzwyEk/nR5kzVPfHmbflje8yy+aR
+ZNEpxrlpceZ3KcroyAItehWl0LbLutbFeQlWIUp8rh4O/rjoBvmiOR66FpL3KvKI
+gh8tOA575bG+dMBGOBvDFBSjP16VBxtg+goxkCBqDz3j+k7/VVP+N3FcssR5Bq/V
+3uqRLUuxQI8dsn+TY6UcGrJTNd37Lizb6z9rjxTQzGlCX6cOWeZDnmfIpyETNLOG
+e1q4/OB2ru+z2Os4N8wuBVQYFhO4RcZja5MkTut+e/gi7LS1Kpb2F5EfyllL8A6u
+BPj8HcDe51devdgojvwaq/0GwYR+DtvYfhXm0TwgqorNWhp3LTjw0ZAQxL9IX2Sb
+cBIwIR6TVIoHbFsOQUzsyZSujms7nRM3Hrmfod7Cv1gNRUJiNurQDKuOYFxj4Dlr
+vhDgQ5LxTPu2QLise8tS/a2wDhyVZ727D53n+iLSGZFEiIw2FMAZbG1nXTv46KZ1
+J/oXU7OSvKyKRroGPuXIk65yQnLcmINfgQgTeB8OpKEL4Wsyx9MHsRAMGhFLpYUI
+z6wvPis5Vi1hk0KTQOYFSRe2lRJpqAdgmxPyafRoOFwwJg1wqpqvy1kK/PHUbj/i
+r9biXV8SZ/6DBKdR9bqZm8EPzLx4Gs7ZDl2uQp/tSAuTKGPoBKzGIshMmC1/RhbP
+H8kb3uUu0VSgOQgU0d4dDkhLjYpEYRTkCcX6QFmnBG3GcNC9OyZeNvSyU3IfsTgD
+2DwPRkTF6HeLGSV9sQHM/+TQsof+wEnDEFmXdgdcMmBWzmOC8ljExx9YdWiocjz+
+NlJDEovng6ks3DNLf1xtsBDOsHarPwJG+spPQ3pwoyww9PrRYXi7VCyhxjMb+JbV
+xuxSFQiy7hdPZb3KGC95obRYXU+x+pJNaZaiU3jXMvo9UjlawHVxqr7h0pTTu/uD
+IeBshxhA1Ag/V+hd38Lm06lpM5pr6fXE73s6+ax4e+it6OEjUv8RkPSOpWcoIieD
+Ooqpruqq8KmXx1jpcxmCGyrAEGvzpFcc1/Zh/mO1G8cEpEAtEUQVhYMScKqTr0cH
+0A8Jy56wpolGumTNlMTGXFCzfemfrEchinpYJtRJzfdfcynjvtn2amrr9sgBk61L
+GL5kHYbBa+juZbIIKcRrNGZTpGkJcVgDs2hRkGQ9wjTfAmmVbDL2nSDR075u/SMC
+4wWX8JrSy2zAjN3gOxbmaJ2JlwUAqXE14TF/Lz93rJbh+bAfGhvkkaSArSX9CJbW
+c2Bv8GiHwUH2ZnFauxFJo/SrJDsvKj6AQlqn7vZS9dKrnscThEWRhC/EHWR/Y/Rc
+LYYoFX2aMNsY/xdyO1Wta52VTPBpoWHNdnEVTwhumd4wOWZj5R8l4iDWzyTxEwrU
+bCbEMR8d3sXJZI6Nmz1x8GghU/VVEItNQHS0FqwqPce9shcBpWA5+7DTjwPgYl4H
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7.pem
deleted file mode 100644
index 317350f047..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7.pem
+++ /dev/null
@@ -1,178 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued requireExplicitPolicy EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjByMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRzBF
-BgNVBAMTPkludmFsaWQgU2VsZi1Jc3N1ZWQgcmVxdWlyZUV4cGxpY2l0UG9saWN5
-IEVFIENlcnRpZmljYXRlIFRlc3Q3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDXic0buOl4pV10DvAMBMgoZ3V0agmq+0F+nQLwUbtdeSIl99vQg0Mm1p7TLuBE
-ABo1EoiXuHlZCog5DA4XokYy6FpTEonY7whLXSUYYCfOzPAvG9v83mIGwoIlGyAf
-r80gVbCuYRpW2LcaqwmGiplI/k7AW4HgDPnPNoTI6wndIwIDAQABo1IwUDAfBgNV
-HSMEGDAWgBTeKdbm40+XHQOoOqbqTeRGX4+CMDAdBgNVHQ4EFgQUq/kyDfFv0NrK
-Hsyq7J+/np0Fn38wDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBBQUAA4GBADdS
-qEYYNaD9ukw0/coVvMDpPV7exx7R58ORlWTm0f/OMOI/dQv35ePIHaJCgInLtKgZ
-/e6UcxGi76E3j9oFzHjd3B9LIYeleJD5w0oASN+63KCbbtpVphjTo7KdsJUli+Cl
-WZJMNDS1X6486Y2zjJcQZ6F8SWW3+ij1o/JqEyfq
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBN
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNV
-BAMTGXJlcXVpcmVFeHBsaWNpdFBvbGljeTIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBALnxr9bA0oGlaihhiPR0d8F/y9ai99F6w8+DtAfGlFtJ4WU3GPih
-ftUTRqZelcu+u6hZgekMwVhjUHyo6sFt5SfbCzJEmjWxI1anTrGAAcH6pG7zF2Z0
-iae8kVE7C8GOgwm+F1Y1RHkw8Wz/UbZ4QGIhzA++KPDi2du40LEGD4BZAgMBAAGj
-fDB6MB8GA1UdIwQYMBaAFHHCPE47NWL3JYefvaMBHjjgJXTIMB0GA1UdDgQWBBQT
-5ozBKw9nS0x6HQ62wCFaJJlQhDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
-B6X+ALEMO8yG/lXfGuoX4XPyaZrb1A8oWFk2ZNCx9QIzI6CQ0vRfO47TF20iK5wr
-HN8y7yXpJGZcNTa5+697/kRziJ/zrNiL4b4BP6QRxYv+3Edq7FOb842JguqWw6nP
-SfsshPhMilo3C4X3PESiI67m18AlqgJcYcmemF1R6Ng=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBAzANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBQ
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNV
-BAMTHHJlcXVpcmVFeHBsaWNpdFBvbGljeTIgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBAJ2xj97xq5PBOjaij1jBcMKFCjaRE1wlUR+5Zz8QkwCtipee
-6O1spOPGECu/sOzZ766YgD6B9GrGQsjXYGzHSxnOl8rcgpkeN99/57f2LYSLxKfc
-/qvcMvgHk6SZiGtpkYOvlLl1r1qUMedtPK29920CI0sp5sxygDaL6PgMvtoVAgMB
-AAGjfDB6MB8GA1UdIwQYMBaAFBPmjMErD2dLTHodDrbAIVokmVCEMB0GA1UdDgQW
-BBTeKdbm40+XHQOoOqbqTeRGX4+CMDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-gYEAH0fkK5ieWFtKe6g/7cN3kI240vvPajxZTkTPnacLXOL4nCfA7kkHnhVVIgzP
-liF4TQ60/yMlUBSBBgTV3/AaMaSO4eZlEdLkKchYp9OwrZ9dfyKdJW3wuEFyGKpZ
-6END4vk7F87/ZyFQNkhMPLD890f4ArarDhqw5eHuFoarvxo=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBLzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5MiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnrdC
-9sroeA9MJlV1ukIu8XNT9cUF70XCDwxMm5vKZZc2+XVNwgxe4aGse4bPdZ9okZ7y
-2ZMuLyDLEBZaA7GsBzG6snQRgHkmMFS6v+pC3ep9ieqtpnrP3b1f743Y1jFp9zvX
-ZDoddeI/xvYF/73KgiYdTFPLa9ARaKiwpQPMXyECAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUccI8Tjs1Yvclh5+9
-owEeOOAldMgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQIwDQYJKoZIhvcNAQEF
-BQADgYEADGhYvyIjl02LK5PZdbH9TrAFF66SGgdk+7nl93vr3XB9UnpvJqUfyG55
-ljoX+kKaRd7Z2O+GLTMmH+tqjMQ6bW+7RawMpFVzfhE3EdAr9/K31K6Q6lft8NuP
-wgqhDrrVqYMPa3YM7n+ebATJ0DJ26evfQu5HfIL7Cs/w+CpXi2E=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:71:C2:3C:4E:3B:35:62:F7:25:87:9F:BD:A3:01:1E:38:E0:25:74:C8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 95:0a:96:af:24:83:ca:92:a2:7b:e7:d9:50:bb:49:ec:22:19:
- 7b:a3:b9:3d:5f:b4:8c:5b:76:25:27:88:6a:26:24:c1:e1:cd:
- 3e:b6:ef:b4:0f:ef:85:7c:0e:95:9b:13:fa:dd:c0:bf:7c:fe:
- e1:d9:fc:2a:7a:2f:fd:48:0d:11:58:69:6d:5a:e8:37:26:30:
- 67:83:83:90:4c:b1:9e:6b:1b:04:d0:8d:60:42:88:13:25:91:
- ae:42:24:ea:61:ba:5d:34:6a:7c:22:6b:be:cf:2c:e0:67:36:
- db:28:0e:5c:be:bd:7a:75:3d:ac:cf:3c:9a:44:8e:ca:30:7a:
- e9:97
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFHHCPE47NWL3JYefvaMBHjjgJXTIMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAJUKlq8kg8qSonvn2VC7SewiGXujuT1ftIxbdiUniGomJMHhzT62
-77QP74V8DpWbE/rdwL98/uHZ/Cp6L/1IDRFYaW1a6DcmMGeDg5BMsZ5rGwTQjWBC
-iBMlka5CJOphul00anwia77PLOBnNtsoDly+vXp1PazPPJpEjsoweumX
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DE:29:D6:E6:E3:4F:97:1D:03:A8:3A:A6:EA:4D:E4:46:5F:8F:82:30
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 85:5f:f9:84:20:e3:84:f0:ea:6b:4e:78:c8:18:98:e9:17:56:
- 9b:ed:99:2f:d5:94:89:60:a0:11:82:40:e0:7f:94:0b:36:76:
- 9e:1b:88:e2:bb:e2:41:81:cd:f7:66:e4:85:e7:ad:63:d7:e0:
- 07:7a:9b:4e:54:27:76:49:c4:8d:30:07:c6:ce:6a:e4:b7:d9:
- f5:9d:94:02:e7:91:5a:17:bb:ef:23:8a:66:20:27:cc:34:f7:
- 3f:e0:f0:57:43:1e:72:4f:2f:ac:75:48:a6:ab:74:19:95:a1:
- a2:38:5b:3b:6d:67:4b:69:6b:01:ca:96:b0:76:83:2a:b5:1e:
- c3:fe
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTIgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFN4p1ubjT5cdA6g6pupN5EZfj4IwMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAIVf+YQg44Tw6mtOeMgYmOkXVpvtmS/VlIlgoBGCQOB/lAs2
-dp4biOK74kGBzfdm5IXnrWPX4Ad6m05UJ3ZJxI0wB8bOauS32fWdlALnkVoXu+8j
-imYgJ8w09z/g8FdDHnJPL6x1SKardBmVoaI4WzttZ0tpawHKlrB2gyq1HsP+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7EE.pem
new file mode 100644
index 0000000000..b33f740e03
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ friendlyName:
+ localKeyID: 26 65 4C D2 03 03 A2 AA 2D 7A D7 81 A3 81 F7 32 DA 05 2E D3
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued requireExplicitPolicy EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 subCA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWly
+ZUV4cGxpY2l0UG9saWN5MiBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHcxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUcwRQYDVQQDEz5JbnZhbGlkIFNlbGYtSXNzdWVkIHJlcXVpcmVFeHBs
+aWNpdFBvbGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NzCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMpH5Ypo+vnXJBia4f1mbnxhkV5cPzmsJbefrK6N19Q1
+/eCApM79FHX9P+kh0bZnbdbjXiUKwNsQc9JAG1Il66+qu9bfOvF73Au7qAvYH4Yh
+bAvpARaQZD9sIXjUfOY1t4NK6uRdNOSoykfpVqwa2GhsI2NfVgKNzJj4HwO2/k2c
+qcOUTds82VbcOHM9Z9AcXwK4TvQo6gUs0HkNNXVO7Vj3+Y4JXG5BFG0K0xoJT1tj
+M4ZKn1z29+TOkIDoYD9qM2ZGVMGhDLam2+OXM/f/d6C3eVGMBc4wLPYZxwnExrwY
+07GQUBn6dgM2DVMY7BDVqQG8frfDa4kIZ+vZzD9BoysCAwEAAaNSMFAwHwYDVR0j
+BBgwFoAUIHf+TDCN4rNRHY+w9xx/HYOYDkcwHQYDVR0OBBYEFBdp3Tg8vwRCOWFC
+TfeJoRRkfWArMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEABr0a
+hM0sHQk9v6Z/9xK3gKE0iphqV5SrOUgtJz/DBzm2VapDSY0No7dTsSweTR8toL4f
+1ynzt3V8u3NP4Se82nphDaFD2eaUDnGWcFCj604pfhlt+rJtjF1mWgWAy6HQP2qf
+5+jhDE+S0AqqlOwlkj4wVEVlodDTUJyeU54kR2aUIXMTs/OD2PtNJ+7w0Sl9UspB
+SBuiJ964Qi+MdZRoFOpYCR3avVagU3CpURNyLm/l5rNu15sbnpFLhCsDx2jffIGP
+yikRtq3rrmY/xeGj4lX06KJkOCa6jAjlZEjlOPDXWOZtx93nowyliPZI1yjVfCYj
+zVx3huyEnj+ozMCnlA==
+-----END CERTIFICATE-----
+Bag Attributes
+ friendlyName:
+ localKeyID: 26 65 4C D2 03 03 A2 AA 2D 7A D7 81 A3 81 F7 32 DA 05 2E D3
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,450C5A5904CAA6E4
+
+qgynPJ6g496fN3uZ6Wnmbobkj52yLp9F8A3yI+fjFvmrIdQuqsLS2h4bbItcHhvk
+ohe6axiG+WIkOrdzfjkPq53PbTdZ1/aW2AkKFcF8D6lQJFM678lYQpQq64m7h3Rq
+bLr9ood2HzXoKVh0b4lVSICXXyEj43WPPnkRQ8w2gSX93Ts+Yf/JEEr8E2u4div1
+6dkX8ifdp7vTt9ocCPTySRE7R3AAJX3sxBjTK/XCR8AHllQIRIVzsOQrq7kKCjcS
+1SZT9v3GLdyKKfsur5bNuHBaAv/B4UvNTlfsOcX4ul/MEet2cylhvIlhoNkvGCT5
+YgyelRm8IQ1hL+KNFIOWzomaDXETJBjpycHNg/RbhBcJf5pfb5tJNU0m3xPKsq2Y
+ZcSrmddcdICbgedZXaqYTkxrgl5cpdJG0OztIgXTw8WWhAe8LgLsjQ2W3T1+mBFL
+hKRzqXUgR0PHRwTvgJYHS36UWkSU8BUb3L1076CFssmdxKZe4ptiMIFQoDZqfv+0
+pY7RCCC2AoaaBR540myOWV/FgiQu6DP/KhFcqHa/Ba1LXJ9r1qgbZ+uGpZnZ1dOY
+7dtwcoLTBR3PUlp5BIzeWW2eDZuBE2pHmFhxiJlozmvN/ClKEO91SZ+RWEEnlu6s
+kWSYNUQSXrcrjBzfXserdVqYF8DU0qceFKwaX6dCYEkYQT0BEE/3/6d8PeygGzuJ
+fFKecRVK+vO36cXvxXIDVt2GRVZ9bo23yQRp+afNGQhJfjwwWOrjCaw6QM+cld+p
+nybgnPmkzMRhvAuz0r8qyc+gbiuiYIgGkP6a0QLWPz0UfdT1LtlVGd5Lkw1+0zsW
+mvaW4y+RqIzLqkOqlZ69N3e0OyKe4lB8znpCWYsmGCh/ZiMzIzFt7fxklbwcL/nx
+4Lbecqy19V4rbxmWQET5kHgh5T24TfYjuo+63f0s7pfiHTpXW7ledqdN+kWpXrt5
+p6aWCRuQMTpKvGCJUP4a/zj8ENrtiqv1+yHcyXTq1oILUrHnyxzBR2dwAZiRuZNf
+UJQzF//0g2XHbzjU4jgSmo34FC16mTSy5s6RfOwvBi+UGlInpVSo7Zrc9GZG346m
+Xvf1y9FY5ijOWKcW/EeL5Zwuvp7BFtA/jGSTFWZNbfOrpwvLTRibyjZNpzfg3lEZ
+w5i0SZpmi0elv8fiZuHfepdapbhu2lMIZS8nozbIDcsCFSI+4L47BQuuQYt4mLnx
+i/MwIS1xc/VLY99EqVw59meXjtmbCniX7LGjYRcE2bBJxTjH4lLfLMZ9FWSciom1
+Pqb2CHlMr8wEAamuKkqck5f2NskJn0svrz8gGHsdA15vmZ30Dnvwt2GxP9dB1F0J
+NgqlUdYNkbXE/czDp1RWygNgRgjAM3Vm6cwrtaiFLULbAvVio/fSfm4WVQXkKR4u
+wg//bgbIiLJc/u33LOaUiRBtNcsGoXSBF+Wy+4k681pzAGbNi4hWUS2eY77z8w0q
+5kKmemOpt1RWirmJMEbw5jZJGPY0Y1eKnGpwAKCXOQxHCpnGAslHlS5foSo1VHEq
+Vj0Ts24KKqUGNXxvKBaCMy4ZeycuWVUK1Vw6nfoeskq6422jkHev/azgbOXxdyRP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8.pem
deleted file mode 100644
index d87c1081b1..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8.pem
+++ /dev/null
@@ -1,197 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Self-Issued requireExplicitPolicy EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjByMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRzBF
-BgNVBAMTPkludmFsaWQgU2VsZi1Jc3N1ZWQgcmVxdWlyZUV4cGxpY2l0UG9saWN5
-IEVFIENlcnRpZmljYXRlIFRlc3Q4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDJsMQQW4ogbj2q9WRWxOqmrcy6BVtHesg3yJh2pcqzUxvNGZWtrZ3M/JI82WbD
-Ns4kgihlmrZZH3sZhjzcdMw/+m05p+rvy7//zB6P1qCRraiYdNJHquzG/7HSnf6f
-i6GdUBsK6YzhP7MtTwfpwVRIUepSCNPIXMVlbIqmh+7fdwIDAQABo1IwUDAfBgNV
-HSMEGDAWgBTTC/BpEgViARafFwSWNmeHq7iGMDAdBgNVHQ4EFgQUjuHoODqDJSoy
-729WEoyqq6oPRNYwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBBQUAA4GBAKvn
-C5ifYeQnv76PvBmEmSAh1whhdRDKTrua+Zl86HgUZZY7/NJl3ny9FyJr0kE9DAN9
-+KRem7jju5ciq8gEwArflK87sdGcpAIq+jiPbGFnD698w7EANZIhIefy3d+lcB6k
-LWpjLAY3+ontoTQAB+/iTBtv4mXMzEh/M7kC3CSC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBN
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNV
-BAMTGXJlcXVpcmVFeHBsaWNpdFBvbGljeTIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBALnxr9bA0oGlaihhiPR0d8F/y9ai99F6w8+DtAfGlFtJ4WU3GPih
-ftUTRqZelcu+u6hZgekMwVhjUHyo6sFt5SfbCzJEmjWxI1anTrGAAcH6pG7zF2Z0
-iae8kVE7C8GOgwm+F1Y1RHkw8Wz/UbZ4QGIhzA++KPDi2du40LEGD4BZAgMBAAGj
-fDB6MB8GA1UdIwQYMBaAFHHCPE47NWL3JYefvaMBHjjgJXTIMB0GA1UdDgQWBBQT
-5ozBKw9nS0x6HQ62wCFaJJlQhDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
-B6X+ALEMO8yG/lXfGuoX4XPyaZrb1A8oWFk2ZNCx9QIzI6CQ0vRfO47TF20iK5wr
-HN8y7yXpJGZcNTa5+697/kRziJ/zrNiL4b4BP6QRxYv+3Edq7FOb842JguqWw6nP
-SfsshPhMilo3C4X3PESiI67m18AlqgJcYcmemF1R6Ng=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBAzANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBQ
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNV
-BAMTHHJlcXVpcmVFeHBsaWNpdFBvbGljeTIgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBAJ2xj97xq5PBOjaij1jBcMKFCjaRE1wlUR+5Zz8QkwCtipee
-6O1spOPGECu/sOzZ766YgD6B9GrGQsjXYGzHSxnOl8rcgpkeN99/57f2LYSLxKfc
-/qvcMvgHk6SZiGtpkYOvlLl1r1qUMedtPK29920CI0sp5sxygDaL6PgMvtoVAgMB
-AAGjfDB6MB8GA1UdIwQYMBaAFBPmjMErD2dLTHodDrbAIVokmVCEMB0GA1UdDgQW
-BBTeKdbm40+XHQOoOqbqTeRGX4+CMDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-gYEAH0fkK5ieWFtKe6g/7cN3kI240vvPajxZTkTPnacLXOL4nCfA7kkHnhVVIgzP
-liF4TQ60/yMlUBSBBgTV3/AaMaSO4eZlEdLkKchYp9OwrZ9dfyKdJW3wuEFyGKpZ
-6END4vk7F87/ZyFQNkhMPLD890f4ArarDhqw5eHuFoarvxo=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBQMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAj
-BgNVBAMTHHJlcXVpcmVFeHBsaWNpdFBvbGljeTIgc3ViQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBANKdKlFcL/bTvKva2ieqdnoU22tpCEtz1o0HfL/Pz/O0
-4DV5ZVG6hKXh69ev5TjepWl25LTNShr/q+MzVRAEaZ2nxmlAcK9/bneomo1JEuyi
-nE2YDexqxrA8mvilh7k7KF88FBLM6x62rRoW5Pa3rImUa7BruBnOVENN9FiT+Bzr
-AgMBAAGjfDB6MB8GA1UdIwQYMBaAFN4p1ubjT5cdA6g6pupN5EZfj4IwMB0GA1Ud
-DgQWBBTTC/BpEgViARafFwSWNmeHq7iGMDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF
-BQADgYEAG301e612hE7Pdkp3cuJYqwZjTc3NpGnxXnr9uwU44o7qHInBBN0S9GDe
-L++I1sIIiGLIeCflVfEsrGNpkRdHUM2fpfAR7iI0fOfQE7bnAxzFMRyVXXnBoTu/
-N6DupbEncPs47o/raseXsxSBteu7BkiORxBEOXxGtbCktIZ+tRk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBLzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5MiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnrdC
-9sroeA9MJlV1ukIu8XNT9cUF70XCDwxMm5vKZZc2+XVNwgxe4aGse4bPdZ9okZ7y
-2ZMuLyDLEBZaA7GsBzG6snQRgHkmMFS6v+pC3ep9ieqtpnrP3b1f743Y1jFp9zvX
-ZDoddeI/xvYF/73KgiYdTFPLa9ARaKiwpQPMXyECAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUccI8Tjs1Yvclh5+9
-owEeOOAldMgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQIwDQYJKoZIhvcNAQEF
-BQADgYEADGhYvyIjl02LK5PZdbH9TrAFF66SGgdk+7nl93vr3XB9UnpvJqUfyG55
-ljoX+kKaRd7Z2O+GLTMmH+tqjMQ6bW+7RawMpFVzfhE3EdAr9/K31K6Q6lft8NuP
-wgqhDrrVqYMPa3YM7n+ebATJ0DJ26evfQu5HfIL7Cs/w+CpXi2E=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:71:C2:3C:4E:3B:35:62:F7:25:87:9F:BD:A3:01:1E:38:E0:25:74:C8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 95:0a:96:af:24:83:ca:92:a2:7b:e7:d9:50:bb:49:ec:22:19:
- 7b:a3:b9:3d:5f:b4:8c:5b:76:25:27:88:6a:26:24:c1:e1:cd:
- 3e:b6:ef:b4:0f:ef:85:7c:0e:95:9b:13:fa:dd:c0:bf:7c:fe:
- e1:d9:fc:2a:7a:2f:fd:48:0d:11:58:69:6d:5a:e8:37:26:30:
- 67:83:83:90:4c:b1:9e:6b:1b:04:d0:8d:60:42:88:13:25:91:
- ae:42:24:ea:61:ba:5d:34:6a:7c:22:6b:be:cf:2c:e0:67:36:
- db:28:0e:5c:be:bd:7a:75:3d:ac:cf:3c:9a:44:8e:ca:30:7a:
- e9:97
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFHHCPE47NWL3JYefvaMBHjjgJXTIMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAJUKlq8kg8qSonvn2VC7SewiGXujuT1ftIxbdiUniGomJMHhzT62
-77QP74V8DpWbE/rdwL98/uHZ/Cp6L/1IDRFYaW1a6DcmMGeDg5BMsZ5rGwTQjWBC
-iBMlka5CJOphul00anwia77PLOBnNtsoDly+vXp1PazPPJpEjsoweumX
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy2 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DE:29:D6:E6:E3:4F:97:1D:03:A8:3A:A6:EA:4D:E4:46:5F:8F:82:30
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 85:5f:f9:84:20:e3:84:f0:ea:6b:4e:78:c8:18:98:e9:17:56:
- 9b:ed:99:2f:d5:94:89:60:a0:11:82:40:e0:7f:94:0b:36:76:
- 9e:1b:88:e2:bb:e2:41:81:cd:f7:66:e4:85:e7:ad:63:d7:e0:
- 07:7a:9b:4e:54:27:76:49:c4:8d:30:07:c6:ce:6a:e4:b7:d9:
- f5:9d:94:02:e7:91:5a:17:bb:ef:23:8a:66:20:27:cc:34:f7:
- 3f:e0:f0:57:43:1e:72:4f:2f:ac:75:48:a6:ab:74:19:95:a1:
- a2:38:5b:3b:6d:67:4b:69:6b:01:ca:96:b0:76:83:2a:b5:1e:
- c3:fe
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTIgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFN4p1ubjT5cdA6g6pupN5EZfj4IwMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAIVf+YQg44Tw6mtOeMgYmOkXVpvtmS/VlIlgoBGCQOB/lAs2
-dp4biOK74kGBzfdm5IXnrWPX4Ad6m05UJ3ZJxI0wB8bOauS32fWdlALnkVoXu+8j
-imYgJ8w09z/g8FdDHnJPL6x1SKardBmVoaI4WzttZ0tpawHKlrB2gyq1HsP+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8EE.pem
new file mode 100644
index 0000000000..6c39f75247
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSelfIssuedrequireExplicitPolicyTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D6 2A B2 F2 66 0C 2C 58 01 B2 A2 CB E5 34 90 29 F7 A6 DB 9D
+ friendlyName: Invalid Self-Issued requireExplicitPolicy Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Self-Issued requireExplicitPolicy EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 subCA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWly
+ZUV4cGxpY2l0UG9saWN5MiBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHcxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUcwRQYDVQQDEz5JbnZhbGlkIFNlbGYtSXNzdWVkIHJlcXVpcmVFeHBs
+aWNpdFBvbGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0ODCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMy56QuuWL4z4T/hWo/3VB/kVEeDeGVv1rUBciSdtpBc
+G+dYzJ0Y4IhU5rTLKjCPgL9NWXJAlZ1xCHG1NKDtNXKhXFtWUBvjGg8cVn0K3g8Y
+FMOR9rxiDaXyzTQSBSMhUXfyc+T93eyt5OdlKSh5dljxtLI4L3UZunZ31hqCOxTd
+N41T7S7XBKlmFnh+ICv44ApWOxndOjY6X72Yfgn1JOaz52YyDDRK/fLzSevInhee
+IJVfWEqj3nSZ4SK1AFGID8JK5yxhtO/aa0M92TYNCBZDJb+Ow1aA1sS1gAt94kwV
+4l+VBqmLyJehvfNfH3zYDGLDN0AQ1Pt6bsuEu05JrKECAwEAAaNSMFAwHwYDVR0j
+BBgwFoAUSQpnYVZHjdJZl68iZjBRd1Cq3KIwHQYDVR0OBBYEFMgulWC04OIHYKL5
+NsodeizMbr+rMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEAPXjo
+buDiYyD2GJrx/C5uDJWDWnvG8RQpPaPjexNQqyOXqopA8g/64QkBZHnzfDtsxmIo
+182199sp8LhA0IK1kOktpKdDwpVdwavDHmVwEdEBSaz9JL7kRUHZ7ui+Z9Ka/gi+
+/RyBOqMfVrugxdru0CthfGAtap7OpADZcbactgL6/F+jMgHhGQDkSY8fe3Dg+JvR
+BLW42PItCICC1LvD45w7oVHVgnQlgYfJhxf6ZKKqy5oHeOtpX6FMqs7TZ1+6V+qV
+9wGpYNk812vN8AykTv8MO6iTOoafhfTSDB8vuxSBA6ilQ8BXOzgf7iBGUedKAiDo
+Xf9GhVMsdvLU83Eogg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D6 2A B2 F2 66 0C 2C 58 01 B2 A2 CB E5 34 90 29 F7 A6 DB 9D
+ friendlyName: Invalid Self-Issued requireExplicitPolicy Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2FE0DD66672C2306
+
+8Gn+x7A90lItKcrrp3OBpBvu1rQQRDWKvaHtLjjiX1WE1Wibym1iJfY0dq9ARYYf
+R/97+Bdrw3pufmLgOiFOKUpKFnDBWb4mgXOrkB1QK9s7E8v4PQFF2Sjhr408B4zp
+2obPk5j+snftrBhtNFsqnxcXdpmYXmO1RYys6LztVyg604OPpyQXTk5Gj49ZZjJt
++rS7r0Ecuy8SOXrR6rhPGLqS/fKd8b/36hI5x1nXKDkX02EwMksffpdufg2P6UGk
+7yXYriDXo2LDD4e8V4QwqbO2G5DYxIqqVoNgwnMyXMSsUPRLfESBKgKw730lCCps
+GOwD4Ae1B8Inr0Hsf9/bsQ3Ll9tgFHle4K0y3Kx6MRia1r+SZ4c6mjbjWXzMw7MJ
+s+66X6OqrrBs1NX7TfWD29NsYDOAv6fyheQo4FKYXMRSx43kr2N+fBZWsU2VKJ1C
+FvAO4W0zd9WsbZYKVaMZq7pT6I/+ZepE9tvMXeOTUm+3wTPcfIjcEq3JD9paOSYh
+92+JRCcW/KKGd+WPeUJR5HEoxnLi3uQHhBriG84xWEYSm/NMJFENFLPS144/K8D0
+PERXi5jqoB+TLS9NHcZgGmmW4tVUi5SqGURXArHdyN97wkh+wuisa8yDYPO1A5lH
+DghmYj8u1BpX9VCWgJGPN+IQJYea2gnoYIPXxy4p6xB6v+k4WytVzlkCVocWf/7a
+1ZgdbeOF9JKEYDmzV8gJLYDF05TONI9tN1czfcUReRHINp2WvMdoyup7n8JPbckg
+OcVnrUc7GyQNQMkCHDT81UTTgLOZJBfN20JCFqZRGAAtFavkE7uy+lP4UCLYrAsr
+pvw6MTdvJKbO/4vZey82M9mjwplCJrGNvwjhZLx/xcjPrOqjOUCTgEfuQphfv4yG
+s0zFzfq4wA9n9ecApPfkGl417/S+YST7sWSV+MsOxm92bQCk5rHyI7zENvTgfuvr
+L0+9Ld8mTUgS09Rl1IBxuA9KLJSK6dDjguxBS9uRoeGCm5IlDFZlqZ6hxR8K9gpn
+Io4ZbhBXbErk5DHpo4f6TgMPJtUmsvHq+V3mlybyFb6eLZyf/xMV31fOK7+bwa9V
+4F4ynGHiLxjy1hsHKwNqJvnFCx2Pq4Ps6fu8TEQ8zZ4QPgoeUdA45gp9e8pd7GUK
+Q/ikA8gq9JOpLb4ha1F73fDDu/eKQcaAOj/ddA3hJERfjMLUjn4PgeT5cfi+eNr9
+EIe0Gtg+7sS8bMmLZTN/TzpI2MYpEarIyAo4K3cLLZv2bsq70USTe+m1YSuqSQqu
+FaJW2NQTivug2pksUEkbXwAs3UoX3c2re4m9dLwtKmjoezaq0qYBydOQ0MlSlD33
+ssAd9Hi9ghURMGE6KqXZfGmXh6GWe7sT1eSsvCnwMkZOxMyZDunv+QsJSTUWoNWt
+NHqe9bA2DVTnxrLK2HwL2+4PX0Y1CkanADx//+seTPbeYVmkdGhHXMg4ZjXgsNie
+POVSEqQ0MkSYMjQtqMNJPnckMqCw1RWdZ2OQ7qIL6tSR9TV+sFqGSINGwGR5oLRR
+8Y5iwuytQ1NpwQ7GJu0cr4t1MOZ9GcnmK7Nu727vsyaXVCtaM8qqEPtrfZ49YCGH
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20.pem
deleted file mode 100644
index 8850f5ee64..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20.pem
+++ /dev/null
@@ -1,134 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBZjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlU2VwYXJhdGUg
-Q2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAzpVbQYnufknoy1tKbCSY840pKcfP2S+jFm6OFC9hzkLFn9uiYzCV
-rCjczQI8lFfM/4p9rUApMIgp4IUAxCOEcgJuKPKmiuoTwPD9XxbmZ/uv+iaLXqF+
-QVcbDGouj0z6RMNz3KGtf0pbgg+/+/wIK4c0XOIM9wTSK0aJVqweAnECAwEAAaNr
-MGkwHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFIr9
-Qil7WXhSSvdIHHG3xHGKplfbMA4GA1UdDwEB/wQEAwIBAjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAo0h6slmGQJsCsth+yeyOMK3j
-2CqJ9gEajx3fWs7x2JJ8LM4zfbFFYctGPKpXdGRBTO8Dj9lQJCr7i1IMMHTitTa/
-xpjn8E0SQgzvkB/0BnSt7DiwV0LXCdtBlLxOS2Fw9NdvbE7jsuBK2W4KDOPElhHJ
-TKQ0T3TjKv8gwxTq8mw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBZTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlU2VwYXJhdGUg
-Q2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAtI4Yuumg8WznOojgeWHVZxG23imfdB9ntiQccDxAnvywEfQv6Vlq
-HNVQ5vsVQfvfUZCad2Nbf42DHRtpmVhlxIhKBjoNu/m6xdvz/A6/kvDvrEg+7M7N
-A2ZRVI0T3Z/mMaPuLHuCzKwU20TF6NonxgZXIbATrppAqRUfSY+UQCsCAwEAAaN8
-MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJtc
-UbwiJzEiQJQJJf/Pg3mto4EZMA4GA1UdDwEB/wQEAwICBDAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBs
-BZsxRaZk1qx3balE6qmVZd7jG6C9Gg/n+I5QfXR75ZIus+0Y6GAviBzywvJ8CDZ3
-kIOOrYolpnycedLS17Jnv4D/IDP6OwvmT6/0XvforKDQlmAk6ioJBRAwHRDYHBZg
-lj8FXyMNUS313Un0l2FXJBhfJNBqb1ZqYwWcmJ2t+w==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Separate Certificate and CRL Keys EE Certificate Test20
-issuer=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
------BEGIN CERTIFICATE-----
-MIICrTCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJVNlcGFyYXRlIENl
-cnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTEwHhcNMDEwNDE5MTQ1NzIwWhcNMTEw
-NDE5MTQ1NzIwWjBzMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZp
-Y2F0ZXMxSDBGBgNVBAMTP0ludmFsaWQgU2VwYXJhdGUgQ2VydGlmaWNhdGUgYW5k
-IENSTCBLZXlzIEVFIENlcnRpZmljYXRlIFRlc3QyMDCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEA19qbNR+soft39JVcTiKn2OTKmaGswAGUpi1lZGYOE4O7xiq9
-FIlSEq2xDeNXvcOEx0GFhZxKefbPzGp8mxtaGpfnV17G1SS/dCxeGZL4D8FUGlzg
-Q0GmhbMZvgroxNvGQD6X/+kdpA34fc6mtgHcR94KE+O5sYTKO4MhqLczr7cCAwEA
-AaNrMGkwHwYDVR0jBBgwFoAUm1xRvCInMSJAlAkl/8+Dea2jgRkwHQYDVR0OBBYE
-FDep7bd0aDt8e8YpJLYhvRpdGYqPMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
-MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAAMSu/B2VpmHV3q3fxUJ3
-7MbeT000oqwthzAG8xJUMten8hTYui0iB5EdxQXBnai07+ZHPBKZVSu6kya/W/zU
-PbSkjS5Agq5eVUDUjCnuVkjOwQsZGA4V86i3oLxyrYeUgmxUSl2/O2tbonLm2u7o
-jkncAUpUj+Sk1N2wFIiBenI=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8A:FD:42:29:7B:59:78:52:4A:F7:48:1C:71:B7:C4:71:8A:A6:57:DB
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:7f:8e:79:fc:1e:57:0e:34:9e:bc:05:3c:28:df:90:bb:1f:
- c7:f4:6a:a1:95:51:f1:d2:b4:1f:3a:64:41:35:b6:42:62:b7:
- e7:14:1c:bf:0b:ed:6b:ca:f6:4c:c9:a7:48:ab:42:9e:04:9e:
- 0a:b5:f1:86:99:0f:b1:7e:6e:dd:d6:a6:b3:b1:3f:fc:79:6a:
- bf:f0:39:3f:03:ac:69:15:b5:2f:5a:17:12:64:8b:e9:46:9f:
- 82:09:f2:09:91:90:b4:fd:56:a1:ab:04:79:a0:17:33:26:c6:
- 49:6a:96:d9:42:8b:44:a5:ed:ad:69:82:63:78:8e:e7:96:1d:
- 17:2d
------BEGIN X509 CRL-----
-MIIBdjCB4AIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJVNlcGFyYXRlIENlcnRpZmlj
-YXRlIGFuZCBDUkwgS2V5cyBDQTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowIjAgAgECFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1Ud
-IwQYMBaAFIr9Qil7WXhSSvdIHHG3xHGKplfbMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAAV/jnn8HlcONJ68BTwo35C7H8f0aqGVUfHStB86ZEE1tkJit+cU
-HL8L7WvK9kzJp0irQp4Engq18YaZD7F+bt3WprOxP/x5ar/wOT8DrGkVtS9aFxJk
-i+lGn4IJ8gmRkLT9VqGrBHmgFzMmxklqltlCi0Sl7a1pgmN4jueWHRct
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20EE.pem
new file mode 100644
index 0000000000..99c9ac1734
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest20EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D7 96 E0 4A FD 8C 92 2F 28 EB F9 C9 A3 99 B0 57 7B 21 8E ED
+ friendlyName: Invalid Separate Certificate and CRL Keys Test20 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Separate Certificate and CRL Keys EE Certificate Test20
+issuer=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA1
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlU2VwYXJh
+dGUgQ2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMTAeFw0xMDAxMDEwODMwMDBa
+Fw0zMDEyMzEwODMwMDBaMHgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENl
+cnRpZmljYXRlcyAyMDExMUgwRgYDVQQDEz9JbnZhbGlkIFNlcGFyYXRlIENlcnRp
+ZmljYXRlIGFuZCBDUkwgS2V5cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjAwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCy9hAZ7ztyJhNh2rSY+hM5b60feX34
+EeKvDgFGMYroiDVjUnlDnvdS0bIDNbw2FPl1ArAutE8uxS6uu682pT15YJXGXUDV
+rgW+/IKHUDXOvoXL+CsaykJQv2Ev5L//GKsL1m9XsClk++WHcZoB+9CmV9rvWQkV
+OzOY2H+Ql8uCtaFb2bPEB5+p2z+wcRYG+flPR7g5VlzTjOeim6mH3g+KpPTl9CMR
+1QLFhkrJiSIKJCo/v1vSOHG7ZwVgwgwsS8+MJcA1syIhPktec8misa/3X22w7KeI
+/teFMGIfXfPQNhYRsz9KU8l48H+zLmBJr/8eJQcl0sYOZ6GHQDrYpBpDAgMBAAGj
+azBpMB8GA1UdIwQYMBaAFPBl2j8aF1re1bZImTsXFBDXTBSkMB0GA1UdDgQWBBQm
+qTfRPNZ64UsoODQnQmbEedR80jAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
+BgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBmHeWnPEFJr+PH5Qpxg/Kw
+jlLc1+sL/wVjqMyYsL2xZxalijHZaYrW48cT6fuLkOMLEZaJaXRu0rj+mTY6rhmu
+ZOpBA+rBaHFlC41h+z2sWmutmSbZPQuhqTzH3/5+8NKVgnpTdV0WElzqfC+vOjZ9
+3Etny1E5GpdwwOUZEcKW6xqhUCysVY9zJzWhMPCvs9GJaQbjAG2X8Sz0o5boSVux
+PX8oftrzRx4uAbAPDX/UCWpcOmLaBYqVxZEjyz3cqO3IPgwMifSggtlKFxsRVS37
+mu2+InNHi6pWLxFTgNRkK0tdEjpORbacDZwkWUWE89WtJ84WEgLuCZEO3kCepZuy
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D7 96 E0 4A FD 8C 92 2F 28 EB F9 C9 A3 99 B0 57 7B 21 8E ED
+ friendlyName: Invalid Separate Certificate and CRL Keys Test20 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0EA55018A4C99C6A
+
+CQpOARkAEerLL+qYOQp9l2E9YcuNSOSPXcGnP0qV3KzZhC3LIHnVwVZu2htiwhZ4
+Qn8yddIzJKLm87TEmsMOV0Hp2Oz5XFbaNTbai92/EdNgu1MVp78SEqkr5STHyvmc
+yLREBia+D43509LGNRKAk610qUNf+RJ/mIGfiweEQITd435G2C5G4uKRUj6Zo6mB
+E0WYA36b27/RWPsjikQHKw8BkgMgc8Tc22vOfESUzx6Q8QAQ905QFAnOv5zrAsd2
+CjVL0XudrZXn+wDg9V1x9mvPdV8YEtA3j03L+ajSmYvafKqw6o0YW6hlxtwIZKnn
+MNn6CXVQ9J6fih9r+GAs0ouwk4l2y7Dxj3iL/WlEJE91y5YUpuwEPqihNVx2jJht
+5O30u+HXVypznzMirPLjuX7ORJF30r4rIzVu1KORYuvK5JY7741o2qCsDOCOJVQ3
+JB4v3aRxJoghUdzUwHtLWRMD+AAZ48bOr8pMcx2y1wCGBqQEyTt9ASUBR/lixfeH
+slm5KK02kB15V2RYiPpCeJ6wpHYueX6Tbwy0lxT9PTPOxE+NE5u5plfllU8tL8t1
+7ZB+olVdEVkmoZ+xGTySkRa3QC80gx9IzqcAprHlnfdWq2i9k4THDfDMxickEYxA
++ufhOI2iXe3apBs7Wa9caNuNwIfdziZ2/bc+hbJlJdPOsxGdk10ASAofk+7TkY41
+ntCNTPaa82AM8hTymWpK8yU5oKGzEV/4c2A9pLEEX36vi+D7/mJhs2gijNKA63UN
+aZfBfta43AKCoEpsgf5ijBtK9x+9lyjIQNYpG0o3s1b42K6g4q/DmjUHSJzFqBro
+7QGMbFtrdLfxehbhOLJa3U2+eCT2/nXx1xErzQIyUq7X+vxgcPEVJT1uEzg/9NoJ
+4v0w78L8izWg5nGEAVeQ4p9UHBSA6NQs2xrsfilUMWkbRLmRdYLFCzFjBhhJ4rcN
+ty+ZWj5xbcK7p2ix8rRDDpV8AHJ39+g+vHvTeZTxtjKw5yltcaF21IJPzrV85Q0O
+UTIRBiPIy8pI0j+JglRdS9WkIl4MSryC6lWLyk3bI1mbYwOuSxnP5F/j+L1F/mXu
+8GLaEIjqGvM9Jgm2wQ7hMdEdevy+FIF85cHUfUgKM9nIEWseV1lrIa7pgb3PwpUj
+cYaqzfu7ml3r5oVIXRQMsnQx+S8PC7agYmmTTDelgz14qhmjFIQTiktnCSCflBfE
+trcxcTfWSb7pRQzpkWOXGPQBvAiKtZnzWwbJkJ0uKfz3C98N6WjOi2RgvYvfGc3D
+2Dc+8yX++Q3V9TAI3o0wMDnvIgFBK8e9vmg/DYtBGWQ1+8VWM1ExTIzFRNTjvyxz
+fE8b8c+wO0rivUrRT+L3f9b0jxsj710DPZAfTI8bESvlSBujeX4GHyVEpqyz/Tf7
+J+H6G8mQqsj9lGrhKjf6E/RF+aPgqAh6GLRAdv703ySNLec71LMrWI8D6dmfNiB5
+J9wlJwVNr84SFdr6LtfliVUWvQK5QaGm0trFgidDvSxmGRLUw65VHfXtZwsrbUPi
+KFZBezCmGvPODOvRoA+8U5wbsSnErBceW32bSoPEcyNB3pNsLlNu6Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21.pem
deleted file mode 100644
index 10fae293df..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21.pem
+++ /dev/null
@@ -1,129 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBaDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlU2VwYXJhdGUg
-Q2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMjCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAkE8ewG6H/K9jn0Mr7uh5z08m2Q6L7j8F5TVV2RmRs5Pg7bhbYp84
-NplFussZhcF8atUil4VjtO7lRP7tJU1+whPYfXiGfJD4zPT/Xm6lmDdSFc8R2y0q
-tzJgoGWHlJgV//Pqd+n+UOLGZ5zGu6RW032gStSaTqwSKJZb4teHKEECAwEAAaNr
-MGkwHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFFX8
-0tqrZMOyYTeQKZ7TKM9hKhqnMA4GA1UdDwEB/wQEAwIBAjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAQED5V5G6uHHjObLE3i2wzZcA
-u6p/+2z2HqalTsdJp8Nrbi6HIYSknqTJISfZtamnd7a5yoevYv6NCt2pE35uXibI
-4RppXx1RfRHygFa/owUulclmTIfUnF2OqAvKJ2kIHyaEaS4xOZsH2czU9tHC63Nf
-ps1BS8MMZbABdGW8398=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBZzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlU2VwYXJhdGUg
-Q2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMjCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEA3KYLjNA57lhgkT+vLnGuU5pyEDLnM+ziS9ieLUKICACgJVoWIffi
-mlCwAibbpcCvUUXOXuJafNB0BrgRf40KooyTOQJUckIm4UsMNuth0c0rkM0uT8sO
-dzfZ2OmD4or6Og4QQlHHFnSJJ/Z8sELlzOot8jb1LmpNW+j9DamSUq8CAwEAAaN8
-MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFLgZ
-mHzJeDS0JL5/mP3lo87ejVq+MA4GA1UdDwEB/wQEAwICBDAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCt
-w82gQMooCa5xgbsT0eM6FUdx767nks7Ty/HLHe0EJ6NwKxIV1JQ7QO1A9+B/i3oX
-I4bStXzp7xb6I0F+9vkpjDf/rOLN384olQ5WMvck2yiud7606uYPGPKNY5pK2KbP
-Au452W+m5r1g5hzg7Cp/VolIepWLazfVISLk/D3EuA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Separate Certificate and CRL Keys EE Certificate Test21
-issuer=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA2
------BEGIN CERTIFICATE-----
-MIICrTCCAhagAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJVNlcGFyYXRlIENl
-cnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEw
-NDE5MTQ1NzIwWjBzMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZp
-Y2F0ZXMxSDBGBgNVBAMTP0ludmFsaWQgU2VwYXJhdGUgQ2VydGlmaWNhdGUgYW5k
-IENSTCBLZXlzIEVFIENlcnRpZmljYXRlIFRlc3QyMTCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEAz5LVC14LIVOAWSDaOhj3dMdR3uhZoXO8IIu2MptactPNTm0y
-vKDMchcc9c33HActpSJH6vGOrl1DWTMfFv7g+lAfhxAyD7/Pe+MY82bUCee/2y3M
-5hlk9MlVlFKCuZ3w3GST1bOxnwIunLQ3OuZw90o88OWQ56udtd1pDlFSs3sCAwEA
-AaNrMGkwHwYDVR0jBBgwFoAUuBmYfMl4NLQkvn+Y/eWjzt6NWr4wHQYDVR0OBBYE
-FIRTaV2lGD+eaFK3LoplVXGjlEG0MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
-MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAX8GUnKuy9YrVyKYhWiNY
-XXNHf78GfFyK+477KeBSUdNQlX3swh3jQZAMgEY0hy/SrunP4TcO/G9Wba1y+O3T
-dO7bBLaMNHNcbnfJZL7py11wtl0BryXFbQWeWQulRw/8AohgtrAzhz4C6KCNZBKl
-x5j9BiH1ClsZAQMLLFjZYEk=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:55:FC:D2:DA:AB:64:C3:B2:61:37:90:29:9E:D3:28:CF:61:2A:1A:A7
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 73:25:e2:82:ca:46:5a:88:06:0d:a4:bb:97:86:32:d8:a0:c7:
- 8e:04:6d:f3:43:05:d5:a5:e3:87:f6:6f:19:5a:56:49:87:15:
- c1:f8:26:67:e2:ec:28:c3:e1:3f:ab:aa:ed:3f:40:9a:0d:e0:
- 16:22:47:ba:3a:c2:b4:ff:ea:5d:80:82:df:68:0d:ad:b0:11:
- bd:15:3c:1d:1c:56:87:81:2e:d4:e8:cf:53:ac:c0:41:fa:5d:
- 22:53:3c:f5:6e:25:e4:8f:43:59:c8:17:22:4f:13:da:38:55:
- dd:92:d3:b0:23:27:8e:c5:85:35:1e:28:e2:a7:6b:79:f9:25:
- 43:ee
------BEGIN X509 CRL-----
-MIIBUjCBvAIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJVNlcGFyYXRlIENlcnRpZmlj
-YXRlIGFuZCBDUkwgS2V5cyBDQTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFqgLzAtMB8GA1UdIwQYMBaAFFX80tqrZMOyYTeQKZ7TKM9hKhqnMAoGA1UdFAQD
-AgEBMA0GCSqGSIb3DQEBBQUAA4GBAHMl4oLKRlqIBg2ku5eGMtigx44EbfNDBdWl
-44f2bxlaVkmHFcH4Jmfi7CjD4T+rqu0/QJoN4BYiR7o6wrT/6l2Agt9oDa2wEb0V
-PB0cVoeBLtToz1OswEH6XSJTPPVuJeSPQ1nIFyJPE9o4Vd2S07AjJ47FhTUeKOKn
-a3n5JUPu
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21EE.pem
new file mode 100644
index 0000000000..7979fc7e21
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidSeparateCertificateandCRLKeysTest21EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F4 5E 46 CB DF 93 A7 E4 A7 49 A0 16 D6 07 DD 5F 5B 7A F2 38
+ friendlyName: Invalid Separate Certificate and CRL Keys Test21 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Separate Certificate and CRL Keys EE Certificate Test21
+issuer=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA2
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlU2VwYXJh
+dGUgQ2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMjAeFw0xMDAxMDEwODMwMDBa
+Fw0zMDEyMzEwODMwMDBaMHgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENl
+cnRpZmljYXRlcyAyMDExMUgwRgYDVQQDEz9JbnZhbGlkIFNlcGFyYXRlIENlcnRp
+ZmljYXRlIGFuZCBDUkwgS2V5cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjEwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4eso2FdVu4KMbGh5ZSUiUNKvacwKd
+xo+zNg9SrAdzpn+b6f1MroSAsBHEt6nKNF2CxLET40hRCUzV/YWVIfSLhnA4J685
+PcSwahhEUdO0b0yHpre8eH4jzvccREjJYfY0GlMc4w0IwQ4GHFlazUZ0lSWyC8vQ
+OgldRnRIRwODBtaQeTe3Q18A14M1bvrhnyUcj55QzqOrHLLrN+e86TV5bIs0Ju1n
+9OmT9CiA4sQt4clJUWpKSfE92tMRN7MTQiSYQA6s25+TgAOJUVsrwHsqXKmLYN8n
+r5wJyCaZP+0m6t4OmYLIY1VL3Jecg9sgQMoyX+Rn/in5y8mrYDo0FhOnAgMBAAGj
+azBpMB8GA1UdIwQYMBaAFDijFoE4jhhORX8H9hGi4kBnm3TgMB0GA1UdDgQWBBQY
+XHzOUCQFF6+ld+krVQWdvRm5fTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
+BgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBTLc/iHmqWng5utaXE8hhP
+V3alhBweT+f8to1OhLB/2uwsFS2IUWtcalvNsfJQ6uxRzuC4Yomalxj/fHBUr5pT
+SnPlz+ToE+7Ic6rJ1UJrweZ+6t43+wgvpUVPj5kaCngZZ6qzHLd+kiaVHc2GQF9C
+/OZoBcY0AUvRDlvICdxlR0CLJXIvJG5mr0ypqS/zm0U70HDVgRkt2YX/uUbP2l2r
+ZUF2rnpVVjB3lyD3bweR6pJ3nKCdjf+LMKtDyWYow2o68NlQUArJdVqRdWCBsPJn
+923k+3wXHxmlYphFLXKrpzfvsnawWQZih/g/Vo1NQrbNeYEQu0x/WDoV1f6H1eba
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F4 5E 46 CB DF 93 A7 E4 A7 49 A0 16 D6 07 DD 5F 5B 7A F2 38
+ friendlyName: Invalid Separate Certificate and CRL Keys Test21 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0201561735544790
+
+j71gmSgbPl7vHaG1iNScu8Fu8xpELkYq1CswaVOepZlXZk7seVupIl3gLzPBNLa0
+3YRX75NT6IZNKvzoKFcV0kwCpgZ0KFTahZbBpkzhdVnjE8C6Te9HB8OvtZlhP9z1
+6hHNcyCtoqB99PFLklIoTm52QXNN1hUIEfNIWFL/lZ00df3u/7Iq4gBhezIdSeQR
+JzPyTt8ymxMcFS+cdb/FvyIlgWoKDJ2KVl/+0KI38FMTGXIN0gdoJayRMfR/kx9i
+y9BmbWWvlXTr+bwOuCtw7Vr/RNynCa7YsJB10FnBDvvONFu/vzRNhAwsC4efuTVd
+ash4mKMKSNgALDS8y/vMpC1j7+cN7xNhxCAyI/RLVVc943NnxMK75G8q+C4rWCaH
+39/8aDAOLhUib7VMGgtPAvKWJXoTLqG0LRZIbmWYeeiEciqdgg0nEYVQ+0ycCakX
+zFwLfrLTYI1oMDVRJ24M5gLjO38kThlmzsxPyXLMAE01TENweoV/XkQ20NSnzP2x
+Tr8Sw6I2/o6PBZ0denVl1RER8VfeZd4K/PPXfQuC3bXOkHl1DCJxyuzrlhXI9e9U
+VADhdE4fACaq5PBLQNnDKNZEfO8L6AgCO0CixnoY+/fI/xQz5XDr6N+UFvwUNnW8
+fvwFyXKDLGIRRlO0xRtXHuqGiVbyDW5chziPqAuoODroA4+cA6DGk/pdTW8oicOB
+MYTtJL7v0yBwU3xDdflRXneJxPhAlbTYfrA9q4iM8BPoD7HSHuBd6jxMizUHN+7z
+GP+UpTvK/ulKF1gc55M9G9MpxLlMW7AIwe0oiZhv6oZLG7JeymuPoKtbzooIRqtL
+uXAEynKHPkNs00IwQ4S95uwjkv5gKKo8gNuG3X0lclle+9ZED6MCPxBN2+3xjBsi
+Jw3hQAG1W/D0sPlVS95gDQO8RntpMlV5CeRKBEgE+Psrsz5rbDtV2nd0o6ywCHGX
+gxS1qMLdXgsXVEzVhi1o01DSpuFPMZnV/Yx7mzG5wCB6Hwxqp/dOKQ7bOZy9MCtg
+6vjmoV+ftEbovwX6HxcTtvnxEfpDmTvhuvX/nnI4guFIthL+EACQnIgwYnUMhiMx
+CXCX56FdxqldA/Q+o8+XpnpoDl+v+d50kCOZKCPBGlWh5YUZD40OyFKQH8mmPKu5
+1TgwgzK2TC+qV1zZEA54fNsA0l8APfhjt9/3KGxxsReuHw/uMJkbY/NM/+pmCYAr
+uxzW7pxKT8EdqH5FsVj59OJegfK5adzS++VO5MffS/xA6pGsK3Jot5UOpW/FodTr
+xJMCuxTUi1TSXTRP06VmbGpQKy5kVHkNPeZyGP8KzV8EAwdZUIZPAuhgmiPaXFCO
+WFfjKcrYgi0p+2P3wsa83aSHsH8wUchQLGIADJMGkwA388lufE5OL2CEz9HJ2xpC
+nV8F0E4q3g/m8R+aRIVXWsnf1SD0FX8SA3NRWOggIdaHmd65V03c46a5dQtGASt+
+cwIrx44UWggJyZ6iwmmPo+eKK2Sc/fVbm3r0TVcDCta3flUda+uN+ZUEishDzok5
+W5Q3yy/nlsHJkLUo0JSWRq5fSRMAq22XyvVoMmX9EXFUyfVsTgO4gw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35.pem
deleted file mode 100644
index 8cda2ecdb0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints URI1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqDCCAhGgAwIBAgIBSDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIFVSSTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKxL9gyE
-2WbKCoEEU+RviucDsSOeDHQfoVxci7AD0RhpGDZkMaDQhM+DUHywwIo9zUpLVeGi
-xQNu1+1bQ4SzVBT6k7vcf8ZxPOUI+8WQzMNO5H2/PGz3XGpfIw/RJrRH79ICwZlC
-6QzvSbLJhOtJTQS9kFTECA4AeBzHEN3f0igTAgMBAAGjgaYwgaMwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFKwdFrpLHgtf4rxhruHZ
-ZFp5vkXWMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zAnBgNVHR4BAf8EHTAboBkwF4YVLnRlc3RjZXJ0aWZp
-Y2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GBAHbVqbpvjgN0GV8abRGms01xVNHT
-PtqMarG3/zQImm9xDzqUqv81kX/8DOy9I/lo3Mvp83M9B74mEEiTTnxkYEpaSouE
-fE3/VAW8dTJb35NeZcOCNWDQv3eA7bufOVO+4KjEHERlxBfEYlPEkJGSLD98SF62
-OYmmR3Cda8cKBk6p
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid URI nameConstraints EE Certificate Test35
-issuer=/C=US/O=Test Certificates/CN=nameConstraints URI1 CA
------BEGIN CERTIFICATE-----
-MIICyDCCAjGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBVUkkxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQD
-EzFJbnZhbGlkIFVSSSBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDM1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq7pFXOed1oA+6DHAsdURi
-YtGnBPvAO55F3hR42UcP8vCvKmdtq0HpJsn34xYHoFPjGctei8AiFVXnj1jrbb8w
-LyDLTRVPFPFHmy3Q956KRU0DteJ8ptI4FRQRT7KeqKADvth4tP91aH2DyFy4MTr4
-wvUfV1mnYKgY7gpfBGlOPQIDAQABo4GhMIGeMB8GA1UdIwQYMBaAFKwdFrpLHgtf
-4rxhruHZZFp5vkXWMB0GA1UdDgQWBBRJujI3sGa+0thW8SoF9JqAlJH04zAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMDMGA1UdEQQsMCqG
-KGh0dHA6Ly90ZXN0Y2VydGlmaWNhdGVzLmdvdi9pbnZhbGlkLmh0bWwwDQYJKoZI
-hvcNAQEFBQADgYEAMZko+lW6d/NUyq1yPydllz9hzKbH8duOaaM8azG14FqmvYnz
-EylKSfh2WuqTwkvpusjhdtr/33S7AFU74OJ9dJy1IgqvLWhD/qCm4fbEq44Ejhr5
-sChHIwMIvecNIEOi6e2R7Ue9ivA2gtFEQCfse4ZVPf/f3MLErRsp1dtITxI=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints URI1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AC:1D:16:BA:4B:1E:0B:5F:E2:BC:61:AE:E1:D9:64:5A:79:BE:45:D6
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 48:8d:62:fe:d7:4c:f3:06:9a:78:4d:e0:96:d6:4b:12:b3:93:
- 23:96:6d:00:b6:6b:7f:35:25:e3:94:20:1b:fe:c8:cb:3d:5c:
- 7b:e8:f3:cf:c3:db:96:d3:62:4e:b7:5b:93:05:11:c3:7f:41:
- 94:e8:75:d2:8a:67:bf:f3:b0:81:25:22:99:a3:4c:02:9f:1c:
- 87:1d:b1:20:a6:0f:b7:c8:f2:2b:e5:b2:4d:b4:e1:bc:c3:85:
- b7:54:29:13:e8:7e:53:ed:d2:cc:a7:95:3f:71:32:5d:3a:09:
- a1:fe:af:ba:45:14:41:1a:67:fb:8f:46:03:6a:fb:78:26:71:
- 02:1b
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBV
-UkkxIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBSsHRa6Sx4LX+K8Ya7h2WRaeb5F1jAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBIjWL+10zzBpp4TeCW1ksSs5Mjlm0Atmt/NSXjlCAb/sjLPVx76PPP
-w9uW02JOt1uTBRHDf0GU6HXSime/87CBJSKZo0wCnxyHHbEgpg+3yPIr5bJNtOG8
-w4W3VCkT6H5T7dLMp5U/cTJdOgmh/q+6RRRBGmf7j0YDavt4JnECGw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35EE.pem
new file mode 100644
index 0000000000..ea4090779e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest35EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: B9 9C EE E5 06 0B AB 05 CA 39 77 87 BA 12 4E B5 D9 31 F3 BC
+ friendlyName: Invalid URI nameConstraints Test35 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid URI nameConstraints EE Certificate Test35
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints URI1 CA
+-----BEGIN CERTIFICATE-----
+MIID1zCCAr+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIFVSSTEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE6MDgGA1UEAxMxSW52YWxpZCBVUkkgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRp
+ZmljYXRlIFRlc3QzNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALA8
+CtHPii7fw28cFZaZuH3dG0rXPq84FZPv6pvNJw69Z2qgNbiwyudr+U3JacGVOQl0
+DxncAg+RfSCSzkZoIwtukH9TC+IFD3J4POTu1uLATudMVsiDM0gmzHR64zc9GRSQ
+2pfSDs5zHFStkdfcZau0xxSff0vXU59UtO+n6AuVOZcZfosrFWTxSf2hEyyt04MH
+FVH/vDIT0mym1kChxQ+NYLqo7A104ZTrJq4ejxFP7Fp62JGqvDGLSnisFNjkcVac
+5f1dehlAIm/ssRyMHK+Q6Dh2KrjPRdkcSuYzDFz82ZhWGaoBj3OrYYljISCZnT8p
+s0HqA6BFbBXhveCFVgMCAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBT6KK1BFt4qaBfI
+DxwjPyYD3gIUAjAdBgNVHQ4EFgQUokLglRky7eXtrwkCdqZ9KB4g5tMwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAzBgNVHREELDAqhiho
+dHRwOi8vdGVzdGNlcnRpZmljYXRlcy5nb3YvaW52YWxpZC5odG1sMA0GCSqGSIb3
+DQEBCwUAA4IBAQBY+uta9QOhKurTMvpDULkPL4HU4wWHAN7+kL+Q9va6SDimwLTt
+N+PT5OfoPbALrC3ETTdcfyJXcvvEbuLcu2/mozR8ZPE76pLeV03v73UlApv3pfzM
+u0ydogvBtA+//I2cZv9JDN55LwM2NxHzEps0GBNjDSqgF5jEPqOqJYZF3U5JvIvd
+tx6OzIGAbq4Y1p4iiyMjEhOZUZ11V9V37LPl7wkWxbp7a6a2+jZCupfWJbDLJHiR
+MrEM7imDoSbkOkwgajrtmRHksuQi1fk/faJfP84fVRFIrBzHhPgG8yV5fLSmLgTp
+O7lmeu5uvo7psQ2Qa1JHtMbw+9YqgK23nR2I
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B9 9C EE E5 06 0B AB 05 CA 39 77 87 BA 12 4E B5 D9 31 F3 BC
+ friendlyName: Invalid URI nameConstraints Test35 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,25C09EB350EDA71D
+
+fzMhGZFyuZHOZar1Ex1YnClyTLjlH99699MkjHMwap8R7dljeW2EcgW5AmE9FfZ6
+36OUWMoleVzXUc3Maz6Cmm+9uaaPY8/OyJN8F56Nkeyh66O/3C3ZpcYP6xLiPfRW
+qp3qtpDqrXlPQ+7agcnEAvcAkPtMU8+8LxSbam7AVdYegUrKBTF6n/8sXWQkBQ1b
+MaH6dsEqBI8dpa42mC+DSXtj68ep6uoLupbLkBy+1KAekkLTRARwjCjo2yPclMIO
+XvOF+o0/tIntRwmkyqV+m0aVTEoI828ptbjQsRXyIozdRiZBYQpb7evweLrr1OGE
+bQb3VU81mczr0gvaRoS3977eHasbPKnLRNaEhn/YtuqJZzWqM9m7F5ZhX18Jw2VT
+hKlShw0qHLQwO5RgelNxiq99l/EICtR1ZdAe0rW1UPyho17XTRDBSLVHB5/bKc78
+Qgpz0Jn7iCRSur4n3w+MYhtpH1B4lctNrcU4rbj2GLBwYaps3H9Zh6qtlyhiRgpq
+4mUhbELsVZgIAEA1I5coax6EKQ1INTEjNInQ2qXXfXpFOzQiXRZN5FyTdJcr3eYp
+lW4w1Ftx/gCcnd39ASOuNHFu9wI1zud0FglhuLYqP9MKzQxKp8vsri8DaU/08eDi
+/xhR9yhiNlTgoMrVXs9ymW5bMQVPuXOem1wnaOj10tS+7IUt4dMvWYaSwBhNhs4Z
+WYUNNF/+K+uXwGLLG7olR8KDGAz1Ntcj/YFJ0gFxHOO7VHzneJPQaEGV7F7S/+m0
+G6xqRTjv56ZA7RdZYvyhhcJ6+8040b7bXAuxeBILg/R2yoi26KDsXlUN8VkqTQJi
+rvlymcRkPdA1P77mcBZ2FIGvDT6kfpmQ4J3fgAlxeRA6Z1yud1MWYjI+QjhH8k98
+3TRmHiITXssfAAAvFauWBef9waFydBuksceDgMgVcMaAL89hC7SlKSJ9EIKBWqB0
+Z27UIZXVjz6qlLu+1k9yLVjE8v3isfIN6WUBb/Epw5tyOUReIH3a4Ejo7C7sG8W5
+SajwycO6+fGYpb5H1ins0CHbGYqFMkjKVsiI707ZC83D4hXuubXp2YbWM2LLqVlx
+MQHiISQRhS7u3Edqnx0iK2s7cxwgn4RnAglzgE7OwgrOF/tRVF68ljKNYyb2+dvJ
+P+B0tHWe9leMyoWNNl/cKkHmDXBbjSQlNkE154Af0q4ncKY2WRmCA9G4LuNIONuP
+TRnaBMxikRWAPEJBt8X5CEsiXzRC8+Aa9ULwdrid3Blv2QiaUlPJ9D6z5ffDDXue
+xJFEKYOcMwkVHzJ0+DO/gdtNLXsDdGrsjGRjDwJIKaOY5Z5YgEMQRnsjSoxhGqIP
+QfFFNaoyidM3paJ7+0Cj9J0716Sv4dNiALkA0wHuTQfGZ7JZITYGsQ0errFqnq8R
+ZmlUEs8gXMd8iE98D+gmegENCaUe1MtN3lTpuomzzN4p1PljDYGeioFSm96Uw4QA
+2IKLQuJi9Njfn6/E3sMdZpgZ4lxl1rOY1MQIYTYIdrOKRFyrJNJXRW4xdmmHdoFd
+Eb9YHCkR9DCy5hDRaVXxW3DJNKTEnwUD+e32UkOj9C5LaiwKwKzC4QoAIFsn95Ju
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37.pem
deleted file mode 100644
index 8564b40553..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints URI2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBSTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIFVSSTIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANCu/tVS
-XB6TUXM4bU2lQ7EKvQrGMy49TSnHlIwEVZ9UNvbSA/ChnCxPIKWiVWlqdqr0evlL
-xdLPxQe6xHuVjkvgFleY6RjA9LqD7YFFvf8AnDD6BV0kIr3itChNI2abON8Dh6IG
-+o48bCPAt9bqxCepQbrSn4mYSlcKjyn66Ev7AgMBAAGjgagwgaUwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFIakVWPxjKAjp6e8y2yq
-bdBaxg9aMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zApBgNVHR4BAf8EHzAdoRswGYYXaW52YWxpZGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAXeaQUlCHmmhg1rKHYxVfKaCq
-S574GPbDh1QtQoNmVqFF+yGHse9s4hcYcv7VZB74kYKCFUShbBWl1VcmgPbJLDnc
-MDjP1B35WdH4IGAxCBLHOiuv/1AWL9EfHUdhX2ZoFpJqNty9lFkahCZ6MARJwtS2
-fBh60OItInetzMDECnE=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid URI nameConstraints EE Certificate Test37
-issuer=/C=US/O=Test Certificates/CN=nameConstraints URI2 CA
------BEGIN CERTIFICATE-----
-MIICyDCCAjGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBVUkkyIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTowOAYDVQQD
-EzFJbnZhbGlkIFVSSSBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDM3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7RoVBb6HAXuZfLDEJZHtZ
-ZqQoQWTPZt8PsM1IGx7uBWtoC8OpBufVE0QTJZV7uKwsbPCvIAHlsKsoTgxWMPpG
-83/daynjox1RbmbI9Vlc+tK/SbwbkIVJ7bO65t52t1SDIfnPSxBa24BxP8wPqbCj
-d1alYdvUt+5ERxY6pW+3tQIDAQABo4GhMIGeMB8GA1UdIwQYMBaAFIakVWPxjKAj
-p6e8y2yqbdBaxg9aMB0GA1UdDgQWBBQJ/mqtsTQDfDnYag36Bwgfh5EMFDAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMDMGA1UdEQQsMCqG
-KGZ0cDovL2ludmFsaWRjZXJ0aWZpY2F0ZXMuZ292OjIxL3Rlc3QzNy8wDQYJKoZI
-hvcNAQEFBQADgYEAWfo3+4bDtxvUvo7zJGGkAMWVXpX27OK57XmNG8U6Ge4H9ruL
-S3OImTHGFt4EbUhw7OIxtSSCdT9x3SAg+jLVLn5FZYM3tkPk83lLSgSS1kvoRJNN
-zf69vibTDpsT9yzeMDt0vFKe/YN4RJwfBWm0ty7yrI6uUu3oxcwLsV7+Wbo=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints URI2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:86:A4:55:63:F1:8C:A0:23:A7:A7:BC:CB:6C:AA:6D:D0:5A:C6:0F:5A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 73:1d:ee:ad:1d:21:24:88:c7:70:27:82:cf:68:1d:fa:61:18:
- da:2c:a9:9e:05:0d:b4:7e:e3:ac:49:fc:82:76:d0:6c:80:1c:
- b3:b0:36:4c:44:da:e9:0e:aa:9a:df:66:1e:0a:80:f4:f0:0c:
- 84:02:2f:57:47:96:e1:f7:ae:e6:be:85:9e:53:e0:97:1e:9a:
- 68:7e:f2:32:8c:d7:89:1e:63:dd:3f:47:06:30:44:e3:42:ee:
- 30:c2:d6:ce:3a:46:4f:6c:8c:e2:43:c3:7e:5a:51:ce:5e:73:
- 7a:ed:f7:5a:04:a8:0d:f2:f0:67:af:e1:0e:b8:eb:9f:cd:2b:
- 24:62
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBV
-UkkyIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBSGpFVj8YygI6envMtsqm3QWsYPWjAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBzHe6tHSEkiMdwJ4LPaB36YRjaLKmeBQ20fuOsSfyCdtBsgByzsDZM
-RNrpDqqa32YeCoD08AyEAi9XR5bh967mvoWeU+CXHppofvIyjNeJHmPdP0cGMETj
-Qu4wwtbOOkZPbIziQ8N+WlHOXnN67fdaBKgN8vBnr+EOuOufzSskYg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37EE.pem
new file mode 100644
index 0000000000..6bef580768
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidURInameConstraintsTest37EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 53 75 D0 B7 C9 37 05 AB BE 60 9B 70 09 E6 46 C4 1D BC 94 63
+ friendlyName: Invalid URI nameConstraints Test37 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid URI nameConstraints EE Certificate Test37
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints URI2 CA
+-----BEGIN CERTIFICATE-----
+MIID1zCCAr+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIFVSSTIgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE6MDgGA1UEAxMxSW52YWxpZCBVUkkgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRp
+ZmljYXRlIFRlc3QzNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM2x
+nbrTtgYrZ7vvgjKR+rj+GcPuu7hubTLNz64dJYq4bO1F2Pp3AGeit4SFt5mWT67B
+p+jjMo8dpqoO7+Y6+sebnJv1pharZ0fzQodcfl9/wTPTCwQ3hd5hOIwIKEC5rwhF
+OfC7CfAG0LBIc3L8ayYbDu3rfvHr43tSrXeNQCDs4sT50yYrkmSc9cSx9zrBin7y
+1XEEsyvcxbwG6vfazFyBtWylBIxrryPqp8/tCpj4v+YKpjNtBXbtI/rh3NQRWqmC
+0/byyDKuu+ZqkOwBZ/VWX0QysdoH+z010rhboJp09kQqL9P9hgB8WW+8zBk1mjnK
+fhk9TBzniVk7SZFntLUCAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBRN64lx3/AEAbL6
+djpYsbpg3YzTwzAdBgNVHQ4EFgQUtJ9QNnzYVFt58I4Udp2pJfKkuSAwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAzBgNVHREELDAqhihm
+dHA6Ly9pbnZhbGlkY2VydGlmaWNhdGVzLmdvdjoyMS90ZXN0MzcvMA0GCSqGSIb3
+DQEBCwUAA4IBAQBB9r2UKkXqMVYrheLH937+0QmR/JOtK+oaJcw+mJBOzy2NbIPO
+7m9OEAElkt/PSaONwtLyuoEm3/c2Z9DVyFE/ep1ndQ/58Ow9vj0WE2mwU1zhwn1x
+R/pZz2WAfFQrgJZLqFoACN38Hsb4SsGbDIWGQrJSabtJPr2XDfKE6TBhVAMHYtcs
+Xia5zyRiL8c4BEATlHrBlw1CngLBfBIDGDc9sKaXboOoz44uyisAwG6FJ9XR/v47
+Wt1hVvxa2WF7AJAI+HZn8KdlLyJK9zi+eCETErxPu0hwMLhe53M+MllHSzD9kOfq
+7gHu2jUzx/W4G4YH5jEo0EW8qEUcCEQX1cR9
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 53 75 D0 B7 C9 37 05 AB BE 60 9B 70 09 E6 46 C4 1D BC 94 63
+ friendlyName: Invalid URI nameConstraints Test37 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,75BC6CB11B15DF92
+
+3DizqDfEvcgL0nq3ByKA+fh1S3y6pB6VUxFVsKq3gqNoh/y551DDwYTXq9f6ZlSD
+j984y50YtYufkDg948E+w31Ja4J2/Q6LWSQ6KsHSRzao+rYVIGY5Bi6ClPJRZH9/
+ffym90Xi3HHhmdqBbmUGeWGegYcXLUR8bxH/EMRP3QVuxeMr4oXkNWIa2Daw3SGO
+ea6hvfUOOqLVj/22zswqBiu2u8IJYhL4ZSECTck8uFLvs8ys4CP4RkSQ3lqW2cJ/
+BeGqWWTO1naMkNvyywaObDkiM5IuKH5AkN7aMYr+VTAWJXOlQnrsixMZgRQsBAD4
+sz4sN88En7ZnGCxVrzEKdigvYlwUqTOl5Al1Z7Lb/u+//jyHw8ooF92f9RcLhkFZ
+9o3riTn7PJUNiyHC1i7XfXm0o2TC0NEJrNeTTs6a7JQDjY+1vcUT0KGPJ9CYWWOn
+k6MTqq7Y0CwrOiI5LGnrXn0BGMLD3lLtCve03Io0XthCKcLWa7pyiHmlKyAg1LsH
+Q4uVRMIy/Vc50k4MF4q58UKj+LVZtoFOBBR/aMYK77QtfobrVLJk+9qgscS8iz7h
+YdeE08tvk64AOnzyOZGXXkvHDifXTILbdwsM9yiweKoAMMLRelX6IKaldcku+sa7
+OmR6bOXv6jqWl9PuYte/T6HOqQEqFGOUMR58pC9si8LWiNYzEEGXdcduysZ3lF+o
+UtmfmKHRKBWf5xFLma81mhhp3RbZG8gRKkDqnIJRUBBs7oJEDxZGMX3THCkx2FP+
+TfS2ToyOFk3fIUxR7s/e3ej4wmM3panPmZjwy88AKl4Vjd4c0FLR6FHORlYgdTj3
+c1Rfvj+8TNZVuzn4OL3L5mnuc0q9MqhELeQtNE9E4uVifD8//IAknnEABrJpGgcT
+XbJGmM7ZGMm21jMKnZkDgV4bvCNeuPp2SmM++v6tu8fX+nUePbMMbzFt8tbGfjLp
+6addsVIwNGrsh7XYIV9KvcwCDVMPFbQ3oJd3QS+UYvTwxNvSpAXBeMpmToxuCn9l
+E4JVRWrL9yKEo1GF+2mVGHOasuicjQ2RjXFJ2vtJBk4RDdE9/4b454hL9nXN2ghg
+mAKkn53PypLprugnvywhRSEQ3YBgqLQkq6bRjcJElUFv3YfQdWOamI/KAKn82J2r
+FO5AiNgFAilZHuBSxsfCmK3VAdKE+CZlWWkDEJsjlMFdYY8Lg5iHzDjfMJD8iSDm
++urOHgyvh2eSaOW9SB+7+1ucjga0xIIkotUzxv7HqLdCMYNk/6YYRR8fHmc+Czid
+mMTScS0FZaBLZrR6k6DUBvE2NCzhVu/8w8fYq2yeZch3sv7wIyhVvct91g99gIfr
+wUCw6KAOAJXtCSR4neqKQDh3yKUj9CPCeSUPAwtH+9KDRRaiNuGFgXejLjRsYlwe
+EpJPHcnXy2P7/AWCMmjx24CAgtezPoqkLr8aK8cJcA2CUkO3bSVe30MZzgqWxQ7R
+u26EjHPWF/fOmCPpx2D6mTh/nZa1yqSxmgOVecODKkD4y3m2iF0m1ZPAZdhZNDzb
+2KnX9sAjPjw9t3YFEd5+Jm607M9DfZLr+c6YnRiQKJ1GDCFhQt8LNw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8.pem
deleted file mode 100644
index 0834f93e74..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Unknown CRL Entry Extension CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBDDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFIxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUGA1UEAxMeVW5rbm93biBD
-UkwgRW50cnkgRXh0ZW5zaW9uIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQC4N3fv71Sg97CctA2gdnDYdBCxvD0dw26KQaNDbFJBOuoUZ2YczhV1669VascT
-67yTxIEcK9/IDZ3YH24KxfGvQ/QPio8W8AMrVyCcHJvX6LyAe8VOYc1STiqxmpxi
-lp0TtHeYT9eIybRSaoqtDChQrkbPKB3unwxZbFwK7EJz+QIDAQABo3wwejAfBgNV
-HSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU9Vvr2srl76qI
-n9lsv1vOk2kRTYAwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAAHH0P2ABpSL
-gN0JmwJ5PRblM4ot5qt69t9Qxgui/fn5pIZa+tDA3zKtJx1/S1Sm3gdZb+2A71hS
-3h/LIkmSD7rTwgJTfjtKd2rVxvPhLlvC6Pt+8cOlOAfxT88Q5atXsU0P+7ZMw/4U
-3F6PnahEk6JTNn1ylgi/e3jRoVAew8qv
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Unknown CRL Entry Extension EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=Unknown CRL Entry Extension CA
------BEGIN CERTIFICATE-----
-MIICnzCCAgigAwIBAgIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHlVua25vd24gQ1JM
-IEVudHJ5IEV4dGVuc2lvbiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMGwxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFB
-MD8GA1UEAxM4SW52YWxpZCBVbmtub3duIENSTCBFbnRyeSBFeHRlbnNpb24gRUUg
-Q2VydGlmaWNhdGUgVGVzdDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPIB
-J/eXGbgEoIPq9cvpKM1LhdR/nU/V8FVZG6E6cGIPHhm6FpNthtmafeQMPHMkT4eV
-41lXx8f9O4+xj0BUXNv/WhGhsT1PHxs+VzLNTG2mp4a6gOaLprNo0vi8C0jMfyQ/
-QMqq0d3vM/QmM4H1AJnguuG4xoSFqLZqIAYC1Xb1AgMBAAGjazBpMB8GA1UdIwQY
-MBaAFPVb69rK5e+qiJ/ZbL9bzpNpEU2AMB0GA1UdDgQWBBQoe5/NueRG8dILVNg3
-c7z7YF5PVjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA0GCSqGSIb3DQEBBQUAA4GBADjyBhwUgM1wXGm948RATjxho9tRdPLLVwj3K0Mh
-JSy5uURrxX2u5UUutqr2ZOpMjUcO0KY0qePFA7Oi2i1Wh49awyxUEqYVxRgBxNtB
-sKxMJG/iV6sX+9X3ObXDCG960+AD2q16GmjPiVrqxE3JQE/1dvdEyHduVgugTEpu
-WOKs
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Unknown CRL Entry Extension CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F5:5B:EB:DA:CA:E5:EF:AA:88:9F:D9:6C:BF:5B:CE:93:69:11:4D:80
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.16.840.1.101.2.1.12.2: critical
- ...
- Signature Algorithm: sha1WithRSAEncryption
- 46:89:76:03:d1:a8:eb:7d:04:de:bf:a8:1f:86:48:8a:d9:78:
- ae:21:21:62:91:3d:ba:79:b0:17:d4:ca:41:ae:d3:43:4c:77:
- 2d:9e:99:65:93:59:dc:72:dc:d4:90:04:e4:f3:ec:ed:63:bd:
- 09:59:3c:a8:0b:ae:fa:ef:11:73:b2:a4:9a:e7:6e:c2:fe:11:
- 04:f1:f5:58:78:95:d2:24:2d:4c:4b:7e:7b:f1:8e:9f:ce:82:
- 76:be:a5:5e:77:e2:33:10:a5:d1:2a:2a:c8:e2:f5:09:6d:e2:
- e7:c7:9c:cc:5b:3c:52:29:f4:a0:3d:6e:8a:87:8a:94:2a:65:
- 74:fb
------BEGIN X509 CRL-----
-MIIBhDCB7gIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHlVua25vd24gQ1JMIEVudHJ5
-IEV4dGVuc2lvbiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA3MDUC
-AQEXDTAxMDQxOTE0NTcyMFowITAKBgNVHRUEAwoBATATBglghkgBZQIBDAIBAf8E
-AwIBAKAvMC0wHwYDVR0jBBgwFoAU9Vvr2srl76qIn9lsv1vOk2kRTYAwCgYDVR0U
-BAMCAQEwDQYJKoZIhvcNAQEFBQADgYEARol2A9Go630E3r+oH4ZIitl4riEhYpE9
-unmwF9TKQa7TQ0x3LZ6ZZZNZ3HLc1JAE5PPs7WO9CVk8qAuu+u8Rc7Kkmuduwv4R
-BPH1WHiV0iQtTEt+e/GOn86Cdr6lXnfiMxCl0SoqyOL1CW3i58eczFs8Uin0oD1u
-ioeKlCpldPs=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8EE.pem
new file mode 100644
index 0000000000..64d05c4a64
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLEntryExtensionTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CA 4B E6 E6 B1 A7 D1 4B 05 CA E0 3A 9C D6 BD CC 66 FA B4 EA
+ friendlyName: Invalid Unknown CRL Entry Extension Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Unknown CRL Entry Extension EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=Unknown CRL Entry Extension CA
+-----BEGIN CERTIFICATE-----
+MIIDrjCCApagAwIBAgIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeVW5rbm93
+biBDUkwgRW50cnkgRXh0ZW5zaW9uIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowcTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExQTA/BgNVBAMTOEludmFsaWQgVW5rbm93biBDUkwgRW50cnkgRXh0
+ZW5zaW9uIEVFIENlcnRpZmljYXRlIFRlc3Q4MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA8pQkABHQjAg0Rtoy+Yv5tsEOzBdRIAZdfoierPmbsVp9mOZG
+LkHAevOhNvunCVK8NeFinVz7NEaIaxsBdbAOqcQOez338byeOKLTA3woSTTHK0Yz
+yE2P57stG28RtP6oDYBN/+7Em1V7HT3+nZmvut6hX/ijhYM3wCtq/wwb0Yvopms3
+fMKM8wJ2XCBHIdKhFrQ7d9rW03VYQvsRnLEasOCYIDaoguRgM60pHfdQVCj+ahUs
+9/ZEJCg6bSmnybJnhdEjiy48AOJJwx5dE51diw8aCruouIlpZcuAjx8QGHmtDl41
+VhjDT5UvvsI1Zl4LIF8aCnO/7PAZGtOaRB05dQIDAQABo2swaTAfBgNVHSMEGDAW
+gBQAphnLoS1NKC8i89JMN8//TDDN6jAdBgNVHQ4EFgQUmuFGJWWGdlodm00iyfNS
+V8B1N6wwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAN
+BgkqhkiG9w0BAQsFAAOCAQEAhom7StGhTRkAiy7XBsP7ToZ/jg3ErbepTvpGLQw3
+TH+zX5Sc1b3R8tR4zJ6RChxonMEWq3HvLNdn8ddyI/n0z9yJxanvt3MTg1OPYIBU
+zV6Oua7ryA4BaVNQ6Mg21pdYtFFxoVfhdP6O/2T97GeW8fp9cvKLagDIegl/KQoX
+CGM9uqjiFup6u/EllniCZsx0EKJXsjxA8CptSxbEgiqxFdo+t+7LM+UMMhcqynMx
+imHOzUGLh8H7WSiPo8H0+KNCDRCh8mO1CANEt+PuW6o3hD1K79QTd3b5qBzMPlW6
+5UWHk/Ncn72YrKxKZT8gc0QMdOtGO2L2h7fH2hPXZWETbA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CA 4B E6 E6 B1 A7 D1 4B 05 CA E0 3A 9C D6 BD CC 66 FA B4 EA
+ friendlyName: Invalid Unknown CRL Entry Extension Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8ED5E5A518FD8B64
+
+5a8ty0N+/lsBZJVhArhMOdNjFyjrJZyD5xea97tdyu8+xtqWQguWvFbhvnHktP1J
+ZKEVrSa+KY/3RWa9/tYs7fpMrQf2FHBB8Dnrx0sw03RAdKiKEnB+9psQxGPBYfEG
+nGFtJvDgrASnrDdpRW1izeixNTMA3/w63wt0InU26KV+5CfV8iRVH0OFm1mmhEnY
+ZKvRxVAtR3WX7DvaYyaRhLRIHWOYT+NzQ+i/I4p0LXTaeYcMTEc3zVHNELpqGiEY
+FQ48IFvqR73reeC5T79OCfXRlDtRvTACZIeig6KsDQET60/cz3DKzJnBJ4m+uQF8
+kVoxz6zVSjTdqwUiA2QBeJ0HYwR5H0617M+OOegG8KC+UmKy3OSkq4DI1A7pzAMZ
+fRxSaQ3jVUX+BJZZt0QKRQdvlKCV7p2wnvb+YCaZ3WwczlM8MLgJ2XtEmHsqsy0m
+ReU/aP5BukEambvjwa/dw8zvDXZehCwqmNoLjT38u/Z4hAMS8vhH0B5bPMabWINU
+fv3uZUsssRg2/1cwtaOU1QaWWKruKDXMFoZ1Q6CEQpZCsYSEoEb3MCAKqZ72KGCh
+XWKWiXL533z8e1PoTJfaWplUSd0ki11xZVrawcJq+zY9nD8z2z5C5C3p97Cko9Hq
+F8Ub/eYPIb32S6jH+U0kbKnjXxq+3/71gianVgUoHb5+V9O9mwVUR6C6eVf68P3L
+tmcMQK6GUu+XKyVMM4lwd/Ql11fyj+LO7EYNCFtne9nYV1K70H4l83FM/ptDeh9u
+IADB8XPzHtm9cxDmEaDD0qSkZJdTWO54RSa9pXR6dljYA61b618ydq2uG9vz/PME
+VLQBy+7VyK8wU8srI9GWtTUD16GrX3CuYhZHo33pqbnkFPDwFqKHkaI0ya4y0lDD
+tUTpBkv9a9v6gzXvb4ZlRWr6Qapm1x5YeU0KZKrOrsbW5WqJeMaraIJPDJtNnCGu
+Uva+oAdtpXOa7yvw1nZS+uU22SoM4q8duLwd4xJO7++V0/iL0Mec5OBIKsSLuGdW
+bbzQs/r/u5wjXhn/iSUrPD+OrllCAHHZI/LYjBr7A/MFoXx3BTCGWKbGf78gPTpi
+fjCtBBxdlOSaDa29dkKddNJ3QHTaCY38e+pfY+nYTc6dzybH1azWKzEUDKWOX+/8
+SSNMLkOD81guneMVIduKhfujej+gQia1ZARIAcI1SoJI++LaEZBgvIxGuK6Es9pn
+mUEXWKWBk6cWEV4o98PdOK8Odx4qfXT0nEWJlrnIUeccfYjmfhwl9dmWoyPy0PlT
+/QNPPQ4/dgPwQc6MaDrxfqecIJs3ng1o+CEsJTLYgEKreD84HXNUoiOswbqGAHaX
+QUjiQFr8Xo6m5slci7Le2WFzNELJhwAYicEZXeBkN+cShcgOjbVHQiNmkaZBLhqZ
+plX0K9kGFRRsAstse5LIoIlgaq4DeKfvYglIukZy0JTGWDWdsnU2mqVwPuc15SbL
+yoPaVX5a3oPv5MxeLiZP3y2r3sisid0+AOCc9Ey6P/iZGiorVu+RBLfE3ft/cROr
+ZxLGPRV3YBguu1WnhBNneSDGaRm0O8O4NrtyQwXt7EAy4XAIqMP4w51RNrkjtSiP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10.pem
deleted file mode 100644
index 8dc7416970..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10.pem
+++ /dev/null
@@ -1,117 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Unknown CRL Extension CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBDTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMYVW5rbm93biBD
-UkwgRXh0ZW5zaW9uIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCytAs/
-JAs2Ja8c89As83uwUulH9T9tQPZcA7nYHvlyElO2ck8TAyHsxyTJEX3dSXo5IOhG
-VD2Onq3BDeRFf6pu5OMpoQ3OGJbb4q22/qZtN6etR0haIBvS2ftAIPX1mJHU48rv
-TuMEQ0hoVtFxKdyYSeFaw9iBTbcaZdPUCMbnIwIDAQABo3wwejAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUao8V/5j0N/1M9CcF3W7o
-YaFVtKswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFoi3BNwtKmwgQu7YVgw
-RJCuLiqFCNPny8zbrLdJOyTSB1MqnPBzrnx0E2U6i+5RTiuIUrD5V54/46OcAenb
-ABT5jTygyoV5M03Iy6ZRQ71ZqeX2hc8LeHetvMTN1fZiNOtwt6Qn4LtWGyw5KH34
-KMAytthglbz5meZVb+cbK820
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Unknown CRL Extension EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=Unknown CRL Extension CA
------BEGIN CERTIFICATE-----
-MIIClDCCAf2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGFVua25vd24gQ1JM
-IEV4dGVuc2lvbiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGcx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE8MDoGA1UE
-AxMzSW52YWxpZCBVbmtub3duIENSTCBFeHRlbnNpb24gRUUgQ2VydGlmaWNhdGUg
-VGVzdDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCi6/iZeRoibZWIgFQb
-pVXsmxIdt4k56SpvzvPgJPyoxkehfaVCNpZQ9udynRLZaogzk1Js85Xmf+O3MBul
-a/xJq4BU0Mit5jPBDcfqEpOu4ovFBfX7i+nBDbBiS+2v+QkqntokkwaDKKCnDRV2
-qjQdAnTFbFNpkpyO3yhWJ6ASOwIDAQABo2swaTAfBgNVHSMEGDAWgBRqjxX/mPQ3
-/Uz0JwXdbuhhoVW0qzAdBgNVHQ4EFgQUkm2zSID0l7fhHwrbvsB+O9PRHtkwDgYD
-VR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0B
-AQUFAAOBgQCMYaiiImk6MCNreccITRisfSs0mHnXu7opjgpXuD6GcKnQtOhN/52T
-12dfAZMp+ROHHg2hZ1xWY7Uvn5IWbWEepjY0SpyGDsuzLgEO2xXg7DU5n1yxZpao
-mnsYHYHJPrTQK7jpsbutOP27RSNid2jQNfnyDoYsn2uCl6zen1aoCw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Unknown CRL Extension CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6A:8F:15:FF:98:F4:37:FD:4C:F4:27:05:DD:6E:E8:61:A1:55:B4:AB
-
- X509v3 CRL Number:
- 1
- 2.16.840.1.101.2.1.12.2: critical
- ...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 87:83:34:a5:84:cb:5a:ea:95:df:cf:c0:15:aa:4a:32:5a:e7:
- 29:82:92:af:40:f0:c1:5b:0f:f8:4f:c5:ba:af:bf:12:16:85:
- b2:d9:df:d5:f3:5a:da:bd:15:8a:ec:d3:a1:af:e7:8f:80:48:
- 54:1f:22:c2:8a:74:9e:c1:c8:5b:33:a4:8f:6a:30:43:91:35:
- 0b:08:c2:87:c5:5a:b0:b4:30:6c:f4:f7:22:7b:71:b6:ff:7e:
- 3f:ae:da:aa:b7:d2:4a:a7:10:7c:70:b7:6a:10:85:d1:9f:d1:
- 5d:bc:36:44:30:32:6c:bc:a6:8e:24:96:62:d6:68:c0:24:13:
- 55:3a
------BEGIN X509 CRL-----
-MIIBfjCB6AIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGFVua25vd24gQ1JMIEV4dGVu
-c2lvbiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQEXDTAx
-MDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBAaBEMEIwHwYDVR0jBBgwFoAUao8V/5j0
-N/1M9CcF3W7oYaFVtKswCgYDVR0UBAMCAQEwEwYJYIZIAWUCAQwCAQH/BAMCAQAw
-DQYJKoZIhvcNAQEFBQADgYEAh4M0pYTLWuqV38/AFapKMlrnKYKSr0DwwVsP+E/F
-uq+/EhaFstnf1fNa2r0ViuzToa/nj4BIVB8iwop0nsHIWzOkj2owQ5E1CwjCh8Va
-sLQwbPT3Intxtv9+P67aqrfSSqcQfHC3ahCF0Z/RXbw2RDAybLymjiSWYtZowCQT
-VTo=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10EE.pem
new file mode 100644
index 0000000000..346ce3a3ad
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest10EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: A7 BB 02 45 25 F3 7D F1 D8 E1 43 94 79 35 18 70 BF 19 F4 03
+ friendlyName: Invalid Unknown CRL Extension Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Unknown CRL Extension EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=Unknown CRL Extension CA
+-----BEGIN CERTIFICATE-----
+MIIDozCCAougAwIBAgIBAjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYVW5rbm93
+biBDUkwgRXh0ZW5zaW9uIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowbDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExPDA6BgNVBAMTM0ludmFsaWQgVW5rbm93biBDUkwgRXh0ZW5zaW9uIEVFIENl
+cnRpZmljYXRlIFRlc3QxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKxv/RraXalQIMNtg/u4DOowVy6Z42Ie7yUF43FcKATg9O4UDlM6fPF/Kex2QvwX
+zFx5gy3obUkZ+IdCmuURe+zb5NpPWdvT6XnMG4gkNsXnjWIXA2aSLJocDfktOcZ8
+xDpagVh0LjRgXJ0sZqYBG5xV3AS60+2ZZ76F6sS5DieU5ZM8kjVPtZg+keG5iB66
+N0VSeoeunx12TABPn98i8pqkhqd29KWKLZ0fAa9nwx+W79BDvEhitdEl+RZtiHmI
+XojnB8nlNWNqQd22Ecr2HVxDXZ7K2rraHnjfecQL3Hfi5/0IGdPxO1GAjW+3v2bv
+Ok7qDdZt7DMnzmrCSMB0wwUCAwEAAaNrMGkwHwYDVR0jBBgwFoAU/f/+GU3bDJ3F
+otiCVuuw2RBh4zEwHQYDVR0OBBYEFOvpVndbfwazHTWOwGmszyZU2w5AMA4GA1Ud
+DwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEL
+BQADggEBACtOcemz0wi8/F5s10MSmAelSSFXOe9srcYq+E6wGW2tdBgf4hDZZ7wo
+RixYJgU0ia5ZhIcEvpU97rZV/wRwDhl/W9mSgj9WFpKNaS1BVl4dmLlQ366Ssxqj
+lMxugFKpqA1lK8R3CG/XlMXVfJYQD5yonkkw7H9Ozu5tqn7sXmRRvMGD2GpyoHDq
+h5TXQ9X/gEcEpvilOUqju0PxZ4XGqf7v12X+RaQRg3CSwZR1OufNQxBUYDkfhW91
+MD0rFQLdXZMTLtvWD7N/8Ycqb4d6BUWgWfIC3hzO+LBlGSPio+2G51XbsjoJbF2N
+1rHplRvqqoK7mUx5TaxKmRmB3O/N0C0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A7 BB 02 45 25 F3 7D F1 D8 E1 43 94 79 35 18 70 BF 19 F4 03
+ friendlyName: Invalid Unknown CRL Extension Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,44BA9792D4E9C9EE
+
+7XjVfX5tOxPAvijjneOooE1jtYcjKeKaOAdWnwPa5hSobrsxgyIvTUKuTkaiNmFC
+viD5YeOMD02uRdoUE56QnSFFgm/7KUw7B+ei6b7x/Gw+T0o73Po7Kn0MSS6LZ81P
+kBCyETCrt8nGnVXunU1ufyKZQuoQr8egypfg+iNaOJ2m74KZMoXHeZWIfX2sh6HO
+8jZdlRbjQip1mR37c+pxf2aNMN7M1L2yy4HXGcATI3GRgWyoHT/Y2N96fplG7q/f
+ql72slc7kA2590sDFLLndIJYbkNTshjcwds6/EhimEdQ/ji4rnh2srp4mNgLbz3X
+GAsJxmrd1OHycZ4nhxgGHwk9ww/sI/sb7FNsc0+uKWUNcN7MPqVdX1R4N/hn/H3z
+S4UNFdRG6fX0qjDFccRzq4CSPqdcarNwRKrLSN2WairHdY1N60gSDPdt1rgdxhsm
+4myi2h+nIJc1qKU9ddUox3+mJ4r/xmXxeD1U1bXU5pvsiTP1GGQMQcVBsuzHINkP
+FCAVnOREP6wVCKbgZwg6kFe65NeJ19hBSFHZKFim9rjwFSfAfQoVsh7nUHCoAOGI
+FtabfzLbyucleuUk24s1Qtcc67FOGbZCsTgshzqjAkeyciEVDyx0JiuNb51DCsEP
+oav665KQodNU1rZHz2nBI1veDaiHBMsuoTytuVg5q77w9THo2HqJOp6zIiO4dJbt
+k95boKUOw5oQCPEj2ALumzBT3W6maYwNDXKiC4IPnJr6OcgqAKv3UdECgOUYNTAJ
+78ogF7fv4cSA3iwj05cIsiE2vN5Sqk/3HyD+OrSrk8BUQzD0MCv1B3M8GlVs3cvj
+/6q+p+u5q3VK2IymLnm7kb+cI6s/l5COpTA6P/Np4G2Y1JGus0L3p0Y5GsGbeFap
+YHl+e8TtvAZTqALnNlx1844VOOgp3GdYDlKpgChs+Od3ARuLTNpppm2yUhpbeQ2h
+uNkuzYgkZuXZT94ExPaOHEF4OmHz8iWLF3i22+F2UmvqGMYAO4EpS0y1CrIcNFTZ
+BiW2a98/uWmwffp8PuMAATABqbU8xbPJEhyxhl8VLnef8j+mlUJDsCq3Kq235Pvq
+zuSTK8mFz7NHbRzH+LUl588Xg42nhgLkDzVSpql6sONENrdoEU1KVxBEp/LpXA8c
+Wks+vQVkXLpNLB4PmtraOiRtYbmYk7QLNv/Woxjr4BljrOS6uz71dvHcZnCGopuY
+4FHDYF92Z2HmkTjHMEIKzVWlBAeBiYn4WQlS+n8Ov3t2odUBlXZYrcNU9uMsdrJF
+HH+Ja4B1QW1xT6qg736fssi5xD7hdOinNV8hliQ9mAlYuTtPVZSFvYDu5Xwe0N5g
+fqc49ifyy7RUOoK9m993sx+6JQc3MoaKZnW1GlgV0QX99AQ+60sVCJDqgm+kAioa
+sLuJZlBDGXnsxYktWvKVmgwndj3QfFXEx2CQr4csjrUzQEJNotrje644hd6dOHuu
+Ol8dWNgkRiJV0xmP9H9eX2ybFdmDadnind2ntwqV0z+UJxWnujqDC7oxnbb+gLO1
+K/w/PlfbJGpvhGqa24JelP2v5/zersCzPmliw6pzRCF73FcBLhJoozyxMfQrNVzQ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9.pem
deleted file mode 100644
index ed2ddac429..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9.pem
+++ /dev/null
@@ -1,117 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Unknown CRL Extension CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBDTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMYVW5rbm93biBD
-UkwgRXh0ZW5zaW9uIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCytAs/
-JAs2Ja8c89As83uwUulH9T9tQPZcA7nYHvlyElO2ck8TAyHsxyTJEX3dSXo5IOhG
-VD2Onq3BDeRFf6pu5OMpoQ3OGJbb4q22/qZtN6etR0haIBvS2ftAIPX1mJHU48rv
-TuMEQ0hoVtFxKdyYSeFaw9iBTbcaZdPUCMbnIwIDAQABo3wwejAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUao8V/5j0N/1M9CcF3W7o
-YaFVtKswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFoi3BNwtKmwgQu7YVgw
-RJCuLiqFCNPny8zbrLdJOyTSB1MqnPBzrnx0E2U6i+5RTiuIUrD5V54/46OcAenb
-ABT5jTygyoV5M03Iy6ZRQ71ZqeX2hc8LeHetvMTN1fZiNOtwt6Qn4LtWGyw5KH34
-KMAytthglbz5meZVb+cbK820
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Unknown CRL Extension EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=Unknown CRL Extension CA
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGFVua25vd24gQ1JM
-IEV4dGVuc2lvbiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGYx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE7MDkGA1UE
-AxMySW52YWxpZCBVbmtub3duIENSTCBFeHRlbnNpb24gRUUgQ2VydGlmaWNhdGUg
-VGVzdDkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAN5hxrET3bqQkPGYoOqM
-k59f/6Bz8rfuR0w0CP8UqMM+W2xDKIj+J1+sHfl1rsbgm3kKLrIF/DeRgOUS9k+m
-1gTj4NxYqTLXRu3AeqoWe7Z04z8WxqhHyD40VbqJeZgRl960H7nqSS7FUCE5Uhrz
-cBhoLlhH2/lYNtZmNFemPVA9AgMBAAGjazBpMB8GA1UdIwQYMBaAFGqPFf+Y9Df9
-TPQnBd1u6GGhVbSrMB0GA1UdDgQWBBQ/ld8yhWsnGl6nmqhcM8TxDa9n7jAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEB
-BQUAA4GBADFhplcYCh5Wt/vpCzwZMGj0be5RMlPSh+6UWKY8gR+TknXyeyhIN0TU
-R7DRXv/XE6ZRQda9Pslooz1WB/VBez54Sg3EirsB8hK/E+PS//mo0NN5ooOdWb8s
-WqML3eEo3XVs0Fj1mYc+8U4bYRPrtDVO4Mr/SnyKNNCf1O5R+X74
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Unknown CRL Extension CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6A:8F:15:FF:98:F4:37:FD:4C:F4:27:05:DD:6E:E8:61:A1:55:B4:AB
-
- X509v3 CRL Number:
- 1
- 2.16.840.1.101.2.1.12.2: critical
- ...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 87:83:34:a5:84:cb:5a:ea:95:df:cf:c0:15:aa:4a:32:5a:e7:
- 29:82:92:af:40:f0:c1:5b:0f:f8:4f:c5:ba:af:bf:12:16:85:
- b2:d9:df:d5:f3:5a:da:bd:15:8a:ec:d3:a1:af:e7:8f:80:48:
- 54:1f:22:c2:8a:74:9e:c1:c8:5b:33:a4:8f:6a:30:43:91:35:
- 0b:08:c2:87:c5:5a:b0:b4:30:6c:f4:f7:22:7b:71:b6:ff:7e:
- 3f:ae:da:aa:b7:d2:4a:a7:10:7c:70:b7:6a:10:85:d1:9f:d1:
- 5d:bc:36:44:30:32:6c:bc:a6:8e:24:96:62:d6:68:c0:24:13:
- 55:3a
------BEGIN X509 CRL-----
-MIIBfjCB6AIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGFVua25vd24gQ1JMIEV4dGVu
-c2lvbiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQEXDTAx
-MDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBAaBEMEIwHwYDVR0jBBgwFoAUao8V/5j0
-N/1M9CcF3W7oYaFVtKswCgYDVR0UBAMCAQEwEwYJYIZIAWUCAQwCAQH/BAMCAQAw
-DQYJKoZIhvcNAQEFBQADgYEAh4M0pYTLWuqV38/AFapKMlrnKYKSr0DwwVsP+E/F
-uq+/EhaFstnf1fNa2r0ViuzToa/nj4BIVB8iwop0nsHIWzOkj2owQ5E1CwjCh8Va
-sLQwbPT3Intxtv9+P67aqrfSSqcQfHC3ahCF0Z/RXbw2RDAybLymjiSWYtZowCQT
-VTo=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9EE.pem
new file mode 100644
index 0000000000..242a518027
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCRLExtensionTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 22 6C 84 58 83 E7 67 7B 55 13 23 18 2F 9F 0C 4A 9F 44 5D F1
+ friendlyName: Invalid Unknown CRL Extension Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Unknown CRL Extension EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=Unknown CRL Extension CA
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYVW5rbm93
+biBDUkwgRXh0ZW5zaW9uIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowazELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExOzA5BgNVBAMTMkludmFsaWQgVW5rbm93biBDUkwgRXh0ZW5zaW9uIEVFIENl
+cnRpZmljYXRlIFRlc3Q5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+sZdrxzcECX8Ri0LLXI1mzV9xmBAlrK0DAO2FWpm7H/EojNUfwYjmGK5Im4UWJ/Gj
+HpOopwkum3ZmnsjIGZwv/8xZhzTvirJwlvXluaTLpxjjec38Ns/aS4KMRBZfYTe3
+nffklLOsmYUiEaDehtA8igBCA7PQCMmi/UzEPx4oBBErihBid80k1fooZy2Rdm1q
+Y9oWRDZtDZQnoloPzp0Z9NjqB7AzaTMYnhmo7kJu5LyUeGM/oWjHw6K5XFT0Ktiw
+d7RUquN0FbMKgYJlpuB0SygFqkO7Vd/Cik0qDfgzfSN3Q7e5bwF9gWKBxJHh8oeW
+vjJIhJlaDCJjyG6wCBq7SwIDAQABo2swaTAfBgNVHSMEGDAWgBT9//4ZTdsMncWi
+2IJW67DZEGHjMTAdBgNVHQ4EFgQUqInp6e7BpgRmX50LwW/1K/AeplgwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsF
+AAOCAQEAK0J7ckIbbVyqqgEXIzziD1qpliCNXcjw0ei9x873IYVdmkGqFF0aFAo5
+lRdzVw451cGt81zHoJekwpQSUKneH1bFEsXWY1Z2wSbu8VFSGwcdnvMHhvhRJ2vv
+qeX/GG4VZm8QH6Ut9MKQB0ouQ4WCNR9nSeomSomQd7NapE9JcxZ7s1c0nBpGeIaX
+q5+MN4vVMrkEv6RvaeXJEtQw2S+wz4ZLgT74bzi52VxpCW9L1ilH+LO6LVqL+LWO
+SghiO/N5LT7oPT6+uIUCAXZn1JQw0j5v3+ljPLiuxHzr8bJKQu/dnqgsz9VA4C+B
+HRsOqzFlVMaEjl4nJtiLhm3NEs4Xlw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 22 6C 84 58 83 E7 67 7B 55 13 23 18 2F 9F 0C 4A 9F 44 5D F1
+ friendlyName: Invalid Unknown CRL Extension Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B4184B7D6FCDA35C
+
+yM86fFbHKFOUuwVFtV3YvfqNhikDBjZqcXZHqEErVMcks6oU5aSFzKXZKENZRSK/
+2mSlo2d2/9bNC+2Q+e7PPanZ/pyst2c3TcfL4Zvkx4qe9rR1Lys6el0eQEVv4reO
+Bvnh/kh7G/+bkYNiAIS54A3XH6bdSI+nde2B3ZODePJNFuRkAlOzEVzTSlxgia/B
+P3a6TrmlrkfMHavoue5AQj+pmNJkrSfWrzo/Qx0lrpJpOoHEpIyCM1vMEz5gR0xI
+OjuVcA9jVwaVttiOlSfPsPMwNbi3JwRc/x2IRFvL92z1ZkaEOlPIP0g4e1d2M//8
+OPqouTcPH/mFq1i0PPnQllX3+uhkk67Y4zFKcr745an9t5fH+g0gD/D+K8cZ7hha
+DRVRJx3kWhqv1TNrMQmssd3qgApmB++P/LlV3uEwu3Sam+Vv/DCesxSd4rEEFv7E
+KMWa+7aQfZ9HWdG7HEHfGrx9v06cWiBEN15SPF7+BERQSV137M8ElUlpwQj5WY5r
+Xo9dkqc6c2yt9s3xlHilUrinOi+fWhoE7cpd/6LEiOAEKq/j6QI3Uaj2/ih/tsBc
+7EVwSQeSIasf+eIPGq8BDouMCIQ3nBxGfUHwJ+U4zGLzqpPPGXT1QfvS+9SnstSq
+5RL3HpBHKfclSC5HYLdE7h9PVDYW1baVt+jDSOYJqntDK4+KeiIVTLQu3aIrzssv
+sLGKfofCAxDvNMCEZjyoPXjwo5qdltSx4qZ2u+7knsMmeIaP0no9dTS0ZbZaRfLW
+DfX2TMZdXl++jrQh9VHiNwvJN/vM0gOpLdOjvn3CPnms6m0/YRf/nj2yYkT6AMay
+EaxXlKPS6G3MAtPwoJ24X1k7WliDJztZzP11nF+CHllbtUpTgUoOfOKOmuPk4b8K
+SWO/udoNjrXFQwD/zI4RoF1z5Hz46JpmYDYH7XrX0y0rbUuLfEp9SCK3BfTEmMzM
+HZ1lefBDXDBImkbugtf2Zd6xaxTHL0BeE245mnOiEkwPon+lW6JkSavhSEfH7I5M
+LvO86Ovy2y5T+YZz2mXky8UfywFhGPPUW9SIOkTgGwrS71n+7c3j28U4OiCG4JB4
+8JzxqJ2O9rufxFYF+HcbWYK1vd5+jq47mnvSCRn7EMLZKtK/IenFyENRPHNhPicm
+0n52bn2lGz8BzD4EX/OTOzPyrS6Lm/g+82RMX5ygu4CRf4WwmNOi/3mPj/tNnLeN
+yGIYN9k70MTSdaoI1HBp4X8o9/tJGmcLEtu0/tLtRr66034kqqz/L6SZT5NV5wym
+W2HAGz2ae5LsOL19rr1Sr/x7PYPURTJnFY1N6nkEHZ/4+lfekAd1JKPtMk40RljG
+Vix75xnH4CVlb/DjXl5aq6kxrD2Xmpssw02VxGlcIu42FXyI9UfkH8qkQBuQYyE5
+8L3yOehKV/b5IdtCVMZ0JUfT8ugqK4g27KTXS4FCAvbJsbv3A0PpQ67XNU8eDAMo
+aKBPsM6gcyd3asAU5lERXuT8VQT2yxlYQo6l4pTk8WbTh8TmXDsYlldfkdIFtSkX
+gQMXf5gcj6XotTMchY97Qarv7mUsujxg23e9CnbijWpceV8aA4VUHVFLG6ctVn39
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2.pem
deleted file mode 100644
index bf772ff279..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2.pem
+++ /dev/null
@@ -1,58 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid Unknown Critical Certificate Extension EE Cert Test2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBXzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMHAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFFMEMGA1UEAxM8SW52YWxpZCBV
-bmtub3duIENyaXRpY2FsIENlcnRpZmljYXRlIEV4dGVuc2lvbiBFRSBDZXJ0IFRl
-c3QyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdgE9VN0Ghm/NmN4sGBIWC
-mYNYrK8ADbOxwu75ug/F5jR3Wq3Hlg4aC8SCNQ2h/sEnsGhZ1nsQwF1mDWMvsGrR
-87vV31pE9SlPQvMPG5S9UlqHO0b/4wj057sWoMHSvOcROdgJti2Dzt9p9+ArbK56
-kYAf4TYDVQi/UvCb4TYe9wIDAQABo4GAMH4wHwYDVR0jBBgwFoAU+2zULYGeyid6
-ng2wPOqavIf/SeowHQYDVR0OBBYEFCWr0F6axQ7dDvC4QVdDsvqzwEdgMA4GA1Ud
-DwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwEwYJYIZIAWUCAQwC
-AQH/BAMCAQAwDQYJKoZIhvcNAQEFBQADgYEAC49hK2AAPynegAqkmf6gK9o2lbGR
-G1PQFqTf+zLATRWYbB+S1lvMJEOYcf1/T2arOgWO6xXJHvQ2xvYr6VbfBSnIdhUW
-OoIQIAowM3RWpZaHu9Ze31BXnoiw3AJxmzIzuD5l+4RyE5OeqTtfJK15kOpeJVdH
-aMmBFW2/5/9zl0k=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2EE.pem
new file mode 100644
index 0000000000..1a90066703
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidUnknownCriticalCertificateExtensionTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 20 42 CE B3 BB 2A 33 9E E1 57 6F BA 05 88 00 FB 02 43 03 E9
+ friendlyName: Invalid Unknown Critical Certificate Extension Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Unknown Critical Certificate Extension EE Cert Test2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIBXzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowdTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExRTBDBgNVBAMT
+PEludmFsaWQgVW5rbm93biBDcml0aWNhbCBDZXJ0aWZpY2F0ZSBFeHRlbnNpb24g
+RUUgQ2VydCBUZXN0MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL11
+HGmB8QxySRRl7MvXOzraGLZJeos5aZMRg3lNXzHEmkW+O4/2YkjzYUvj10VhEs9D
+lUAejvIboJ6ZXkYiFx87pZww1Ab7tp0TbrSzT4N2O3+oYosaRNTyYB9Rl6+JOmAQ
+nmk0Wz6Q7KbFzhQPG10mbFtP6WZPW36l9M+KNiLgTdpbPk3R+cVI+ICwaHBC+8Tv
+dNlDsK//6P5NwqS0LyYTT24Tjk7WTpt7f/i/Uczr4k+2hG3hGbMh9x18sZcsSsZi
+5QdsTU0PgefHt1dFlyRP+zY7xBEyCDkLR2KWZdPW6f19qPNagNOLzu7k88oa50v4
+YAegSLRu8SI2dA1Ys0UCAwEAAaOBgDB+MB8GA1UdIwQYMBaAFOR9X9FclYYILAWu
+vnW2ZafZXahmMB0GA1UdDgQWBBQK0YrYt0innsAmNsSrdytVebzazDAOBgNVHQ8B
+Af8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMBMGCWCGSAFlAgEMAgEB
+/wQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQAckvMPK/r5WshWWXP+qSdUqT7WOfj7
+hdAJfI0aAdCT4sNrR0boObpmHl7sqo9CVRhW9GCgsavFNl4yjEOOdjyz/9wzs08Q
+YI3qgnbqV/r6OiklMuSar8PLoy4v2EmSnB7RLQ2ErbAtLv/gK7lKYj/Rq3Ktyfds
+rnudx2kHpi7t4M1rmHa9SxlheEj4JCTTiDjkn0dVyMov0dvgegQ2bfvTBOmvjt6e
+yo7uiCo0UqrDyoV1ZFa00ylk4EgoenpMfsXbQMUgzS/m0w5O4nPA2YxyBxL+pJAf
+4XP9PD0Ro2E8EKk1i81OuEucKruaXBy774BEGrdZ72TTo0XJSp/TT4L1
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 20 42 CE B3 BB 2A 33 9E E1 57 6F BA 05 88 00 FB 02 43 03 E9
+ friendlyName: Invalid Unknown Critical Certificate Extension Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,651BDA338F446BFF
+
+AZUCywxK4m9yRJrXqO2HqYZyh099Z1G0dOf0B9Bj3onzixwTb/2NJphl/KP3qeoR
+N/TqXCawDW6VtEHD2beiP/6AMbucgK0aPwHn6S/RYU0Y3tedPD9ZfiIx7Wu024Jf
+2XMCM+WhNv4MRcW8lq08lm3eRk6awQOtNJKUpA1AsPtxwjGVNSVKgaZS4/IHREdu
+r2AYg1R4amj7/PFfZFAymPyWXwNFGHIf4IlORu2yOyjnVFm96OZYm6H89DgKZtkk
+y29ZKEVhyljM4CIfqAT84OVRKLN4182dPL+F+GKoctQjVP/7+CgNya+d5SObsBSy
+s0SNwJ2bz9Ea3H40s2tjSy1tK/NbsgIf8QMODvUqzaB+09vBXrhH0fVR6NeA+8KV
+0gpoZI7lfcJUcCf90bosVxSSWcxNZkqbO5dUmrDS5ZeT8/O+62Ibnb5nmJCzqQZ8
+s7mlbzNaZ+gxQjdpPQufLN9iiVVR3hQPWxbev71DoQEI3HC1iq5/CwlDyOPKVUcp
+Yvboxki+vsYEpxDklSgOcVNnEnRZcSk/YnwGJbOCaWo4bWqAoR7EIfXFiSDW65Pn
+vuJOFQPDFXejfT6MIoqpxhquIh/9CtE0mnfFq4ZvqNzLlaTA0j8nb2tXiimXlMtX
+iosOCPSmKhkzam5NeoiXxo00LAJLISolPA0nfOEF/WWkzE6cw9+6UGo1UZYBKwp6
+O4bwHzv4LAjn98sXOQlEJF9n9ODH10oM+Q6b/ZTfeSA0OfZkV8g+s3/WkXVg2Pwn
+KiPdAnwzj1puY2sdeaDxraJdf8G1F7eerwMILDdkdftb2NjUl9dBhnQuOSp4srwb
+8oLvJMFDqqHWcRW+phkNIUDep19iDfgfiDDTzhSFZdeVIqHywzoXj/KttiQT57n+
+mZtRvdvoUJ//5OioMhuiXBaRL90GfA6/i326mTgWELdI6XGsohsVzH6rPZDJiWFU
+sABwl4fMTTAsSkDA76kFb4SwwENY01uRDbF/U3GqKt8Wl3gil0PkMs9vaBM/zyBb
+xuwjVrFAYl8qLyfYcs/r0prYwp8pIvjZNzo9po4RXGLIu0DXZaHCH0Gl4lgAfDar
+vK8U96JM6m1BW1ktNZO9WW7IVyiytxhRMVEL4qV9bwb/77aMAGe6mHrivh7N1HT6
+9pRrM+fUB2/8xIqpnGR7EJ3e+Ci79MPbD2Kt4UW7XuhzOBlY9Hc5Yh0SaYcVPfUO
+iBXwkUbuEIMIjJbnVowW0+fM8dCMABO5n4LTULJG4LejSLFhNC6RKhddHK471HbH
+Sunz1bsnOPkukh6ipjdZvn4jtRvR8frY66qvmi/bEqUJ9Zypy7iz1H3I8aD9v9ly
+WVuKLkDFOu/p4Yw0yU6UGZl+XNGmXm1eOw7Rqf0J4Xk8HA7XJB4fOplBhXbt79+P
+e5Z7u8uo8BZhXHAZaEPnFf7JAVBEfP4Y8J4ptcWLvISv+5cy3zX9VcrXOxPCBIm9
+crSxMn6VqbpnyEzvmZQlCJKBCNxckAciqHJsVOjSKi0yiJYNPc7q794H8dK2hXij
+szapKjWjmPPd3hzOrEMHqFqhuL1LPfZ4uD71D0RG9QJw7LC0UPOIIBM/E9APGIW5
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6.pem
deleted file mode 100644
index 7f10e7695f..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Wrong CRL CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBCjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMV3JvbmcgQ1JM
-IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrjpkZYUtNf/4W6weCyaK0
-JDUtJyXxK8YEL9R2hpnPnGceXRXEkq7XPWyNBAC+lpGPd+mWjvX4A/MAsGHsOiY3
-I35sJHR0ViNoDDIpACYBuNhtFTQ0JHS34zOZR+jG0BYSib4h+svHctlVWGOY3l8F
-lp8EWSm8YZ3kt7kycshWzQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQU1G3jwp/Wffea3VwN0SfwS1Rpd6gwDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAI844RkGSuDIY9HF+gW3Nd6C3sILutA0Zsqw
-Ih0wWh/y9VOV6TNvPd8BlF1i0WkAMcswgqhrODgySpG7fdDlgMTSI/Tz0ObYbsA/
-Dcd3OplmCfRKi8biDWnBn6LdZysZ9uiIOBFyOFr5cfWGlgSctiXxtZc15sju+TTA
-EwWcPVar
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Wrong CRL EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=Wrong CRL CA
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFdyb25nIENSTCBD
-QTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEvMC0GA1UEAxMmSW52YWxpZCBX
-cm9uZyBDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDYwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBALC3wWGmw5/yOOPg3RNvStJ9JJIfBz6CyFWksquf/4icnW/wL4rx
-hCxN1vNOSiH+IrOgWYTpkpGPiMvbvn4h9I2Ytzimw1O0EPTXFAE6CdJagxdcsFHA
-1UJMR/+666NEypeYmyaFMPduqmcR7rED7TZZgQGhltY2+06s0SghWO1fAgMBAAGj
-azBpMB8GA1UdIwQYMBaAFNRt48Kf1n33mt1cDdEn8EtUaXeoMB0GA1UdDgQWBBTI
-T2I2nkS+ARaPkr3QPXOlb30emTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAKM9XsZ6SDRWXHk1nyBsa28P
-ItsxtO1B0ZnK4Aboih9fOPg14udmRCVjgc7Z3UCl+F8YXFWKkisitt55o74MCv60
-2vlEaBrRBPMvTpHwqyNIWCcuDYBT4JrfC+iF8RwHtts9c0KUUn/bwXAuvDclEg79
-XUWTzrxsqFVOnMEktZUm
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c7:32:ea:21:ff:7d:01:d4:f3:d9:c5:a9:ea:04:35:21:81:d2:
- 13:f2:35:d3:e4:53:c5:03:93:de:a1:2d:25:56:64:bc:52:20:
- 81:53:69:6a:a6:90:26:38:bd:ed:31:7f:a9:7b:c1:e8:a9:e5:
- 07:97:82:bb:3e:8a:f9:79:ec:2e:bd:16:4c:31:6b:b6:80:ca:
- ba:ba:0c:35:0a:d6:08:3c:31:78:fe:d3:3d:06:69:6c:3a:e4:
- 07:4d:6e:84:21:d3:c3:90:60:8f:99:90:62:a9:16:38:25:2f:
- 7e:08:5f:2f:cc:59:d7:7d:9b:2f:d8:0b:e7:70:d9:64:f7:01:
- 38:8d
------BEGIN X509 CRL-----
-MIIBOTCBowIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU+2zULYGe
-yid6ng2wPOqavIf/SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAxzLq
-If99AdTz2cWp6gQ1IYHSE/I10+RTxQOT3qEtJVZkvFIggVNpaqaQJji97TF/qXvB
-6KnlB5eCuz6K+XnsLr0WTDFrtoDKuroMNQrWCDwxeP7TPQZpbDrkB01uhCHTw5Bg
-j5mQYqkWOCUvfghfL8xZ132bL9gL53DZZPcBOI0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6EE.pem
new file mode 100644
index 0000000000..8a764dae01
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidWrongCRLTest6EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 49 9A 22 5C 7E 4F 47 9C F9 9D 01 7F BA C4 B9 7D B7 18 B9 A2
+ friendlyName: Invalid Wrong CRL Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid Wrong CRL EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=Wrong CRL CA
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMV3Jvbmcg
+Q1JMIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLzAtBgNVBAMT
+JkludmFsaWQgV3JvbmcgQ1JMIEVFIENlcnRpZmljYXRlIFRlc3Q2MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLSUqSQ+ff5gAG8H8PWG4MFHgx2SKmPN
+Rr1wAwhfFEIrA9cJWns8gYqTKXRkfTHoQlqHXdg+7dzmZ3QRy9DZ8FHDTGK1YikH
+lTTbTo3j19OmOY7pVmByLa7FOHitP+0ck0QdFTw1eS5frVgs7K9abmLbvz+4YZY5
+bPAdVttyOnw0h4IoHEftx1K+7F+aZUc0WR9GD/XL3gsrnRkiNYVOraX+07frVn4a
+3hLtDWqOEn/0GDZoSfDuMdsjFhwjkObbnzzOQGZOMZerLdwva9c3F5nl52H7iNk+
+4UfaSahjOPfcCNDSQf/teiId+VnO0mCMMqkDxDh+dAENlKwbjGfO1wIDAQABo2sw
+aTAfBgNVHSMEGDAWgBQMJUbgiXpRB0qvNa/NkMRyDreoBjAdBgNVHQ4EFgQUg4Fm
+s0iyLn2sM7+I9tk78gxwvKEwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAIhouVXz76OgM7KW9IxI4DJ5N
+SYjcUdKLaVKMmmxsvAt4M5dqPFEmpJMRon+gcR7rFF/M5BkNw0nBQZHUarzMG42F
+u73I2sJWTEbEbg3usXPJKnDISUrvJTBA9y5R+DZ9aRlnZ/OCJz05cS59R2MKdIJ4
+ntOEvWVKeRet0oz1UScIY1hc1DqdZ8YgjUR3waTMKLxRayESKysAAoOxDILlWovk
+WPTD32as+5goMh44r6+0Ntwj0vZ5W0Sg4F24m/R6ZEHhs+elV1ilPNCgghMJ85Tp
+pbE/8xN3Z2ndZzhXlXkFQLdWGQwpQ+2Lld2NFrsn+2+OXGEzT6v+QRLZse0WOw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 49 9A 22 5C 7E 4F 47 9C F9 9D 01 7F BA C4 B9 7D B7 18 B9 A2
+ friendlyName: Invalid Wrong CRL Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DB3B0C652578E1F9
+
+WTacPVyIqEiSiv5N8GuiGcrH3xfwU/TZehvEIPBwkx9PginD2FwfwVqltOaCHSBd
+OXs9LCoWsAsAoCcp8GlNwSTYer4lgJsBNnJlGVF0WUMvMandeHrmnR9Ig4LJLH9M
+WHFtmLyY+2Il2aRYN5PPCKKAV9ifAB4bygdOsm76Rat8SFNLC1HD4lmjSEwPmvxR
+bhgs19wti5I708K7kFnV4OdQpqcMIbfgRLA3HZxPdTnN53tGxXUjRxEEAP6SG8pC
+WAleiIS2tyoIYTu0lZSO/OiPb2wQ5mLVxIDrN2PgN6HrqrpRRXwcaAQmuUpA3nkX
+Bx04EtNXHJo59kK8+a6r3BXlT9FxUl+liTZemxC+6aek79zhHgM7xaExOvUdgQWR
+2rY2KZtDkSp7k06hPe0f08kW8GfpRCmkBNIltk3Gn+PxszsPUwZSPZPKjMagmWGX
+AVEKrvMZoVmhTVJAlS4km+sQ246XjrztUGeWwKndsB7YmKYxc1mozguKt/pd9pwF
+DhGKjh9IHxWLSEc0DniLHEDWgwnVOa+TCZVwSPqQHNfXQzKeRSiGCvxBF3mLx4ge
+QGcFKkAPxBb30ZGKlrHxbkFHl+kusXXEZ3neSYZBDwR8H66aAb3lgDmybPeb0kgS
+XP5pW1yk4ldngaEr03NomxqxjtX8p4Dn2TUqnTRzBSGkBSw/2khdgk/s+bgF8QnO
+fEl3gzcGFEcqqH1R8UMJ5lEtRqA2ynVDlAb1d2+5pFkpLh7B3DqiYXz+a0ITf3/X
+sHR+7oTg7olwCLR5xEAPhTKC3QyNBtX4jpt3y0V+HqZCqphJnb49XcJjSPcZF2mk
+quE1kpgjP8U465PR6fmRl6lx82YOWXren0/QMH8FIL18dTXFVJr/+HqluARx4cIQ
+1R4bvG066jYOy4yUPrPDDhqIwBccxVfOWH18wHMBIM0GVUg43glYnKL4Vf8eJwnx
+YXXgC74daXMQK747+/CUsxn7OLk7OrIW8/7969TwQphEoKXxnSNbJy+P/32t5ikb
+HPQ48TBlRoXF+/pD1Jh/BDT2gZT35KrukCUdtzyqkIrl2pd6KVJfXHqObEInysQv
+QXSbhoug1lJZtmzkhF9LcGEFU6fp4suEhmsj39K5UpXIrjjcY17gGOafEVg3FN30
+tetlrlGSrzTg/7i9HwZoB1W2CQmr+D/2v6PdFDJOXAoeYft1clWKNowNY+t9X81v
+NHEwJ8/TY1//TOQHJ+TlrrHgmtP+Z4pehsXvU9ILopFxeaE56KTggsEE32QMC2Iw
+BiyxwYWiM/b3sirmxJ+KdCzKKX8WOvVKflsAYqK9UhrofEsjblwtGtoAvjm/5tjQ
+M+vPvwrHA1pr6O+Ttq7QA+AvVOGPTBSN0DJ+FJgIqLJa5mGZ1Aeshuh/4bqijoCl
+x5/02Hg+YMqxCgqObq/ddlgQRIRelNCyBJA+LD1PMT5wtg992udAFPjtpgISDXr9
+BjaGp9J29L1LevQNQa4T8wLs8XCgLWdW4jEt8mW+b5pPFvkMH7LRFIND+m6fjttO
+G7re6NHwzVsUImFR7pEgZvL1BLTOQUMbS53NBUtxux3wDhdnusPONg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2.pem
deleted file mode 100644
index f64a9bb06c..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=basicConstraints Critical cA False CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICiDCCAfGgAwIBAgIBFzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlYmFzaWNDb25z
-dHJhaW50cyBDcml0aWNhbCBjQSBGYWxzZSBDQTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAsmocvHtIhy06xoGU8RgpDv0nBGXIPSXRG6Poy/+IGxarpbG06NmC
-maF9YsRYKMKl35fIYgRSJXsZQNbNdFp+OP0unEc2gkWnRFkd5UYXaUYUw+1joRBQ
-rv66WNwMkTSpFnzmb0Pvvxw+5Yy8MMzvfYTwnw4GIgLtTrffpS9B4V8CAwEAAaN5
-MHcwHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFMdH
-T3Qigo2QmpSYRbO1Q8N1GDbOMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOBgQCYmJK2
-5OMOWxlviglY0yKGvQpDwTyJ4CJmsGGI/rtSjvfFiqHPmq2c/QGm+pAdKMqkhGXN
-FjVPKm8pLqrFbAnWXSG5OeWq5wEMckNe1Qjp91ag5gmWEVwdq86eNxkkA6w/+hjp
-BxoCAT74c74EqPpOX8c6NGlI3VyN0hODzePSHA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cA False EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=basicConstraints Critical cA False CA
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJWJhc2ljQ29uc3Ry
-YWludHMgQ3JpdGljYWwgY0EgRmFsc2UgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEw
-NDE5MTQ1NzIwWjBZMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZp
-Y2F0ZXMxLjAsBgNVBAMTJUludmFsaWQgY0EgRmFsc2UgRUUgQ2VydGlmaWNhdGUg
-VGVzdDIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWAnb4eGXIMKqcvxV1N
-I1WYOIgPGw0pmor0ePIVaJFQZALxDndu3IUvzZCuK/m5nBAn3qtGItKULZEqeZx1
-sqbagMshYrHDkntnRShl1luH40b/RdWn0SnkWcYiA+ZTmcUYTV4t0OmgeUzQMtMj
-LRQ76i3JymtkR6MDgbJ6NWQzAgMBAAGjazBpMB8GA1UdIwQYMBaAFMdHT3Qigo2Q
-mpSYRbO1Q8N1GDbOMB0GA1UdDgQWBBTQ3jc8Qy+MJLvnf+0PWJpzZUdgHzAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEB
-BQUAA4GBAKhCguYapRZdH/DcOaj9Mtc/x8+/QbXwwWTyETUNHItDAWqwXgCbEHKN
-tbgWB6IZnzhzWvLcNk0HJrqf8jnYEC3EWj9ruOl7oaCWRuq5uLwtnf6MCI32zjzT
-yJDh7QLWt2STzMDmppGt84nl3PjN8MaQhp2qTJyP9f8ue+n+Ng0D
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=basicConstraints Critical cA False CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C7:47:4F:74:22:82:8D:90:9A:94:98:45:B3:B5:43:C3:75:18:36:CE
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 32:bc:12:1f:84:d0:b6:3e:72:a0:fb:d9:75:99:ca:e5:2a:05:
- 09:e6:c8:27:74:47:1c:dc:0c:d4:9f:bc:9f:b2:62:25:b4:6d:
- 5b:e5:0b:e8:2a:8e:07:eb:3e:6b:c5:1e:9a:d2:14:fd:89:5b:
- c3:10:bf:19:77:67:0a:33:45:1b:bc:6c:ed:af:84:30:59:fb:
- 7c:71:95:63:60:31:9b:9b:0a:ea:77:f1:70:f1:b9:2e:d1:a9:
- 04:42:66:94:b9:54:48:db:44:56:56:1a:57:5a:01:0e:7c:4d:
- d7:c0:1f:5c:6f:13:f5:a3:57:88:6a:9a:71:cd:d5:ae:c3:00:
- b1:28
------BEGIN X509 CRL-----
-MIIBUjCBvAIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJWJhc2ljQ29uc3RyYWludHMg
-Q3JpdGljYWwgY0EgRmFsc2UgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFqgLzAtMB8GA1UdIwQYMBaAFMdHT3Qigo2QmpSYRbO1Q8N1GDbOMAoGA1UdFAQD
-AgEBMA0GCSqGSIb3DQEBBQUAA4GBADK8Eh+E0LY+cqD72XWZyuUqBQnmyCd0Rxzc
-DNSfvJ+yYiW0bVvlC+gqjgfrPmvFHprSFP2JW8MQvxl3ZwozRRu8bO2vhDBZ+3xx
-lWNgMZubCup38XDxuS7RqQRCZpS5VEjbRFZWGldaAQ58TdfAH1xvE/WjV4hqmnHN
-1a7DALEo
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2EE.pem
new file mode 100644
index 0000000000..1c8a8c279c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E5 65 2B 75 8B E9 2A F9 2E C8 83 32 11 38 9E 62 D2 61 91 73
+ friendlyName: Invalid cA False Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cA False EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=basicConstraints Critical cA False CA
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlYmFzaWND
+b25zdHJhaW50cyBDcml0aWNhbCBjQSBGYWxzZSBDQTAeFw0xMDAxMDEwODMwMDBa
+Fw0zMDEyMzEwODMwMDBaMF4xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENl
+cnRpZmljYXRlcyAyMDExMS4wLAYDVQQDEyVJbnZhbGlkIGNBIEZhbHNlIEVFIENl
+cnRpZmljYXRlIFRlc3QyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+5pPuSskaT7pQvNS0XtLWfsJa8Jtq4V2jt2MY0BMegVCjknFfUEajR7X40eKlCACB
+QD9awY8FrNrkR+k6IHrtNsn7YhwyO7gxC+8loRip9NEnrKweYDB1MiYGEhmep3wu
+IXUrFdNVIXbazuQDQzTNVRnJGGSKxP8SlxIrLg6C7gxmYpr61WlajauE87FtalMe
+lAMQp3pJUiwF8Ooy36Ja/38fgyVhEX/0Qw+OcMfAg4Oe8xVhLaffWF8ZBpji/z45
+NqiNJ/ZJ+IqwfcAp+8vhcM26GBX4l0c7CBXfjSCi2NvUdsHjv2XeloDRDdfZfoBx
+lGdkeODccKklxTJE72ylVwIDAQABo2swaTAfBgNVHSMEGDAWgBRw30QvA5kcF3MY
+8jY8FDTQCdHy7TAdBgNVHQ4EFgQUfLh7mOwGIojKj5FQ2sTCLnyBGFIwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsF
+AAOCAQEAYrhQ0Oit0VO721Zoeuz9vRSVb5pEyWOkXstseN4oBBCAwd+L63rzNYGT
+SIzFTMh7ePO160xVWOJnSjbCDhEDdLG48yYI1bIZ5B7mdOaGqfo+kh3+oWXbM8CE
++hQu0PbS2d931zpzKgikars+50o3g8veVaD59Wxft/JGeiIIK1Hld97vjNRnsi2o
+7wqeYVTQHeRT4kksFTPfY0O2DgeGDVvCwIPP11DtSxkgBkonxBqCSUIqngKdDPV9
+nD1PbNFiabVgIB1AWLThO0zAge4ZjiHSzaY6lZwCzqW7KWLgjscmvHDd2Y2DTIR3
+xE8o44JWsXaJAO5uYDD8w0iQQ2Zagw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E5 65 2B 75 8B E9 2A F9 2E C8 83 32 11 38 9E 62 D2 61 91 73
+ friendlyName: Invalid cA False Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,55AFA660EF18FA45
+
+kf6xL6LLcWVhm2YeI9NLp7e/QJi8iblF79iSwggzH3uozQOYuAaeA3tVfIxRHu5o
+CvsnvytZmsF0uaxGhm1mtPerBOQZHtqOXU2J1jKIZguAWW8qNID3CitLVDmibx/J
+jOr8m2gtgGEbJ6Z/Oa35JgNQPU5rbypAQJIrxiW9Uh3CWWVXXNyab1/WtxE2CzF+
+8eegosPhUSyjP1qrGdij+tsmgygQbnp+sShHb+/viY2dpfuzkBX6HzK5YdDpssp7
+hf+5mijMck80JrJIIgdMCCkpv/C/Xjk7bF8apchmUEDCLGva4QKKZ/Qh3+LJD9+m
++BXGab0Hh2PdGkLLZR41Mgjt6CYz+UgoxSlkJNK6TzovmXPlJ29mVBo8+L/ECWW6
+5amVM6ZHax2PLRfskZYl2Dj06aCJcbz+Hgnh4dMoL76KEb4p1rGXkULO/zewM+pr
+4j2zVpOKgJi2iv6QI39MfpIWuxM5MDKqgYsYcdDhuuXn0R+VcGPeQoGPWJ2VCoFr
+8tTL+SFpilNrtLmrlw1x7RmrxKpifWAUUQNHd9D5o5cbpwPwq7GYaIE2AKtrps4r
+NFzq57NZPak1kN4tzFfgiW/etl6A1zCS80Keb7/uZ3W8/rsaT3PwJF4tRxkQgRHe
+9l8Avk6g7Suu+viySRXXyL+bPVt3OonxKdN059sKyqaWl0iTLBk9nK6HX55gG+FI
+lmSf2fHixg7b13ur65SE5ypg/TUmF0kRMGusscwv4EP9JJv8eFcOo5LfzmkMsHhB
+chTZz6EEw8NK1okSSyzYnQF00XrNpeo3bIb1dAg1XeGI97XuJn3c8cc3KdMBKLsG
+OG4Df08YFCVInVkeKyGvQYec5eGKlkByXTpriDiQ4hlMzu6enGzVkRggffSRnX1G
+VK49gPBqIDA3872xizE3CV+h5yGyjaI6c5wokkt0XbCQmpO1ZmocMrvlgrt2SirC
+IOPC9WYkwumsvaS/ne2uPnPkEAdWQWllvHW/u9GFD00wb4aYW54xiXepxYM+ZR8n
+jXUt6X6r3SA0VYPsM0vxVqyPyFGnbkKiG16EK7EqL2HwFCbujIABUSVn3i/tYRSL
+uV6wrkmPN/XtgWXANChCsZ62n6bTKj7Red/W9FZPPWw8RHJrdCBPX6+EjHnGW9To
+J/CpXlkJoqZHXnqbqIvk/HTwQCGFUDRvLwAJamxAnkQbxSoowsKgaaKy3NiMH/AX
+vsKXhL+hwpQuyHNaOt7TxFq3YmbLMjXldl5yhzPJ2HjZNhkm3U7Gr/REq4vZjmEj
+q2o5cQOLhsS39Ao2G4hRdKbIg9N2e+vNzWPlS626m8Zc2vCySdJ/GR6d049nve5o
+cavpyiXav2VF9tZQfGrI/y+SuRYIoQAz/1BmP4RY3zL6b7vCNgTGq93vlR2Db0VT
+H389riCMDpV8M3GDpZBhu7CO4C6KUM2JM93prRN9vHZNZzFcDQIZofRpNlnvzXS/
+Lw73X1WbxLHcI2BoyvOZRfO1bKBbWr73M8ZtEEFuQ/K4umfEnIXh2KjUVEVTb+I8
+KJZqJbulxVkfnRxx9ihb3+TmP/APxJu/0IedxU02CYKD95+13STPQrec097TUz26
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3.pem
deleted file mode 100644
index 8784c21050..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=basicConstraints Not Critical cA False CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBGDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEyMDAGA1UEAxMpYmFzaWNDb25z
-dHJhaW50cyBOb3QgQ3JpdGljYWwgY0EgRmFsc2UgQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBALebKuy5EJW95AkM4MZ0p12UxwWQqlclzW+C7Ntov96ejAjA
-ciH9FrTh8IzXl99nnQnHHO8O+pZ1jzh8hQx+kAGx6ENV87E9ByTgcNUwSgHgEHX+
-59fIr8RTbdUtF2T1U8iyFM88FkpI682I0GvNDuej65588/P/OAHTmZbqcWrfAgMB
-AAGjdjB0MB8GA1UdIwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQW
-BBTEleK6dmzd47tLaP1CRfgUVOxbzTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAhjgF
-Diuvic63KpOvuZxczWMf0K//uMCtUxtXXRTI3/Wm4ryKa+yI52FUGhUcNB5wRAES
-R1tJSuphGx6rdcSHZTE95gLo24lnyc+oTZQ3gcK2xouTy3F3CvhmPs9QMMjaqtfn
-NDJKzUyBvAasUQ9SZxk+bifeeSQ/RDzmQxNKHr8=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cA False EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=basicConstraints Not Critical cA False CA
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMjAwBgNVBAMTKWJhc2ljQ29uc3Ry
-YWludHMgTm90IENyaXRpY2FsIGNBIEZhbHNlIENBMB4XDTAxMDQxOTE0NTcyMFoX
-DTExMDQxOTE0NTcyMFowWTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2Vy
-dGlmaWNhdGVzMS4wLAYDVQQDEyVJbnZhbGlkIGNBIEZhbHNlIEVFIENlcnRpZmlj
-YXRlIFRlc3QzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5JEpPUEhR94hD
-geH4nu6tuBiM/sUvTffvOfzdSftTXOQ/4pHuZPXKDz7SrM5gAimRZMXlC0ZngP7z
-9Q7StXqOqMvZI75GjHGYr3S3W56vvCxfDh639L/x3UlhfKqEzn3rMLMDC52lJzcH
-npMqMRIYWdedIvqg6OaxMDj30va12wIDAQABo2swaTAfBgNVHSMEGDAWgBTEleK6
-dmzd47tLaP1CRfgUVOxbzTAdBgNVHQ4EFgQUxBUts6LKOH9HITo2TnmeY1hdGNsw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
-9w0BAQUFAAOBgQAnnZ9Y8fdKeA3cdodXsQqz302mCLQLH1jhcE7UnfAYrTdecJ5s
-8xxE7AKdNEG7/KUAoSwKDsGw0HBIQDPD62kblZEWKViT4+e4isf4Dy3G31BRbkiu
-bcJsDKzOOdCeCdXJvGXAJ18su8P+4srOddrQuINqRy2YgDG5Rka2WArY2g==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=basicConstraints Not Critical cA False CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C4:95:E2:BA:76:6C:DD:E3:BB:4B:68:FD:42:45:F8:14:54:EC:5B:CD
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a4:53:e8:4c:ac:c5:d6:66:9f:c8:a6:4c:ad:d2:6f:2e:31:b6:
- 48:37:6b:9e:e8:76:8a:ff:23:80:3a:49:a2:91:d4:94:0a:bd:
- 9b:2c:0b:cd:c3:9f:e8:a4:7e:b1:ce:37:ea:23:5c:ff:c2:76:
- 6e:c4:84:d3:21:2a:ef:7d:2e:fd:71:54:2d:8a:ef:f5:96:73:
- f1:7a:c9:1a:7c:77:86:b4:df:0c:47:a3:8b:9b:b1:f7:bc:21:
- 64:6d:19:97:ca:b2:1b:e8:4d:f7:66:c4:78:75:5d:76:b8:7c:
- 5d:88:f4:ae:b8:6c:27:11:c4:96:09:b2:35:fb:6a:da:f8:fe:
- 73:df
------BEGIN X509 CRL-----
-MIIBVjCBwAIBATANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMjAwBgNVBAMTKWJhc2ljQ29uc3RyYWludHMg
-Tm90IENyaXRpY2FsIGNBIEZhbHNlIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaoC8wLTAfBgNVHSMEGDAWgBTEleK6dmzd47tLaP1CRfgUVOxbzTAKBgNV
-HRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQCkU+hMrMXWZp/Ipkyt0m8uMbZIN2ue
-6HaK/yOAOkmikdSUCr2bLAvNw5/opH6xzjfqI1z/wnZuxITTISrvfS79cVQtiu/1
-lnPxeskafHeGtN8MR6OLm7H3vCFkbRmXyrIb6E33ZsR4dV12uHxdiPSuuGwnEcSW
-CbI1+2ra+P5z3w==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3EE.pem
new file mode 100644
index 0000000000..54a073fb11
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcAFalseTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: BE F6 72 6E EE 29 F1 27 15 4E CD 61 48 20 85 A7 AA 00 6E 1B
+ friendlyName: Invalid cA False Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cA False EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=basicConstraints Not Critical cA False CA
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEyMDAGA1UEAxMpYmFzaWND
+b25zdHJhaW50cyBOb3QgQ3JpdGljYWwgY0EgRmFsc2UgQ0EwHhcNMTAwMTAxMDgz
+MDAwWhcNMzAxMjMxMDgzMDAwWjBeMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVz
+dCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlSW52YWxpZCBjQSBGYWxzZSBF
+RSBDZXJ0aWZpY2F0ZSBUZXN0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAOMqfzk11boRFBbpNA1tq4GZJbk1M45bsflY/IBB0d8KUdhotWgSOm065GL3
+sB10F5JZI/sLVpXuH7R9TABBvnZu8XqX5RKKkNB7zMXlkpr4TFXGZnYgSmX09ta+
+fuZ4TQgj6BdztW1l/634f4exa7qZirzCISqddB99CN318WhQgMqxmounqUfkUD12
+e1UM3TjOPKqI7eYOJIfnfw2Ea6BhT55ncTXp5lcAhAajos+iWYhiqlPWc+cd1c8U
+3VrVi7kuKK6uuVBqA68QTiDnuaPEJsxadp9AuYY5WYGT4HT2HpsXzCd6R2fk94hZ
+iV/C0hSIAq0mVtq9FJF9qh/XwsECAwEAAaNrMGkwHwYDVR0jBBgwFoAUOdCbt08p
+N77TsIp26mqeze9GvlgwHQYDVR0OBBYEFI/4W2j9iCltyb9KCY6b8q11whJ3MA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
+AQELBQADggEBAG22QQs5JmmHtqLDRPAiJP+IjtpGyiOCH7IhyGLW6MKk88cjH9xe
+M066O9SE3asTYTrhQBirfy+nOxV1Qg+DdSmtA6ibr3USxTkH5xcz3OR+Sd3fkxEI
+qkjK5nYkXWs6B/xbX8A3iUrRmG2Yp/gLI4Fs3ZEobwh93E7wIamQ8PJ1SbnXTTcx
+xBy/IKY/usd7NdwtobmHP6fH2bWM0GyNxmOscLCxAhESLjmuq30srVG/jHs/Q0vL
+Jww3lWZSPbJXcRxKMzlu35IrP92RZWjtByv1Wndugh7q5rjT1ccw0eF95b/U5whx
+X2XPc74bSpqoh8dfNGTWjtq2JeHhGoJd+9k=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: BE F6 72 6E EE 29 F1 27 15 4E CD 61 48 20 85 A7 AA 00 6E 1B
+ friendlyName: Invalid cA False Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CF0C33F0D543AF3F
+
+TqNxwYWalKi89i8CJ27L6UcVTOqnEwzxawfBToP2sP2gwAcuYy/XrECuWOyTyeX3
+yJcZdmSSbHdXEyxZPgcRLTB3rzn5fb3tJHy7pU257nJtm7NnyT/4iPUXYe5QRpeZ
+SrIPxY8IXG26zv8hgs4hxwKWUFOzBKJrHLB1Q7MXlTxGYltJahDUmS6nwEcKBRJK
+pxhFQb+804FuNyrhidWfh1ubibvPX9AGX4QgWEcaL42trTbVFjc6VNAN51vE8j4t
+L/bIGdhEUbbE+SHxIBityvyntiiMb1lJyQpsvNr5svsvzXdv9adMFdiBzRxkf9RI
+hJWsPTqQvBN5mtX+aw9Ag4xCYwkE2eb6Vy6pWyow1WsXDaYbH89T7rPZEAl6ZmK4
+FNnycmLQWlmcuKB7Qd3vUIrjiUZ569vuQobdkEq/HjYpgIQVLKFb60tLLrVwraly
+ZEZAHIRf3kxR4P9tlcI3MvTXPSR2FdLCHNvp+JfRcXulFfPLOSJiMQo/t/TJjRVi
+iLv1W+UAp6flSOArCTf/SkEBnF101kf+KMVQoJrhRlEDdWGOCWxchrcni3LRxl+r
+wyZqqZYsA2UKGSB7E9ZWgN1XKxIxIUAh4xBu1amwm8KOfIiNSwarOi4E/73wAiW4
+f4WBzD4nhh1x6JwY9b0Ot+tqgCRL/LYcdCfJwLd+aO3cIiYFyVER2TV387QANCy+
+QgO6CC91I75pdPt0yLuyFQeoEuvzBpsZnC4d7pN6xI/JeUfBhaHzgDWX8ay6iH0G
++mON7WpEXqZXEgJCZovBtPx98gqE6fuBvdN2DpljQnDsVSzxqZ5TpfNE2NNUNFlK
+pXgq3F5MyueCHm3GT/yl5EIxJo0mB47h9rIV8iPIqDOdb5BjlfRqNbQhl9DBWDvq
+dtWNp8PBpVRU51IswMoVRqSMqTlWnZyyX/vjPkbErpei37NGfLeJadqaM970XAid
+IjVzGNEWKVo0Oc6coK2si7GVF1Dq1gTwiAJDdqbjEBlM4YgDOHxuYWg2/0vONZM1
+AuxdJftyJonRctNoc9r+AmEihjPKsbJb5uMBXUKyz7h/m34rU8X0gmRC3LD0IIsO
+IXV7+MSWWPISg+rdmYk1QN+imQuUv9qgxXfwEnHt/ZX3Eki4bed4NYfHZFCk5yMn
+vIM/oCIJStlIIE0aEUG9AJhaYSLFsnKWEjZBT5tQhmewi/I1YJ2NtcBSbELjRa3Y
+QbgICdGWP/FvvtX50oPSApRkfA+6UmxajF7FotYcupF7jD+dYuL19JaDY1D/zBYu
+QzYE4SY14SVyMazzk7meRAGE82C3p5gTx8hIxXq7Em5H9Ls+V/+JgKDv843gsf0W
+qdbk57p39Ib0LP3JROfPibPPTBVOsQ03UjD1a2WUxvWLBgCRC3P3QVbZVkcqztzV
+cLGnxuqAKziFQPcjp2djCy/7SOZ/WSnLh4UPtyryjCtEo37ojtiPeWi9hiHnT3MD
+Q4pYnLafEapb5U5c+4VfnF+6c/gH20jg6so7RpRZj7LYt8rCIeaLrfZFBsiuhAsN
+1t1Auz4G9Q4IG2RMZzl8C8QvkMnXjIc8DSy8mIjEdPj9bmAur5nAXKfJgK9WJc53
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27.pem
deleted file mode 100644
index 357566f6e2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27.pem
+++ /dev/null
@@ -1,140 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDblDsGRxVahA98R7vE
-/DS4nbSbyoerDINPIyc8wkOtWcS+y+f9O5IIdDJOZm2I5px1PA840SXYHh15o3ZW
-Vn4gFU3AgKF/CWMJ1g79LAYAMnQN/T7kSfuz/0rqhLH9tjz3Qtjt+/zy45YIny80
-7JOBLH3eLX0H2aOmsJUenp5ExQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwa+CD9XTTxDwMWI8WIm5inS7nAEwDgYD
-VR0PAQH/BAQDAgIEMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAEvc066az+E8sftMAgkECVeJVw0Mcr2y
-YlJ0SAbZUNaU7KbzXxm3j8Q5v8K8GDy7EB4H0Gyh0vgsbChTAdLip7xQf7V7SetA
-nE66H4ikF/UAhXlSz+E48Qe2+L3w2weGbU3zwmNMeYkI6dmGFMfEut7hL9ak0Ulc
-0meAGzOu5kHt
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cRLIssuer EE Certificate Test27
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA2
------BEGIN CERTIFICATE-----
-MIICzzCCAjigAwIBAgIBBDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFsxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4GA1UEAxMnSW52YWxp
-ZCBjUkxJc3N1ZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDI3MIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDBePXreW7TEQz9U98u5IjkoUpf/CRELuDW4EWLSx0ib7kJ
-njp5do8pREmTX9nvLo1/CiJnv0RRNY4hKwqjR3V+j/2+BT7JDu5T8YuM3MmgWlJt
-G46pHVekb8uXAofDTqMlvAtGTQauE9F3JU7oJ1FJebMo9SRHwIBQvvwnLIn2qQID
-AQABo4G6MIG3MB8GA1UdIwQYMBaAFMGvgg/V008Q8DFiPFiJuYp0u5wBMB0GA1Ud
-DgQWBBRA5ST4jwbcfGOGKDw9sAjuw+hKSzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMEwGA1UdHwRFMEMwQaI/pD0wOzELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRAwDgYDVQQDEwdHb29kIENB
-MA0GCSqGSIb3DQEBBQUAA4GBADHmdwVGWHDLCpX0n65DVgDpC2wWpGgu929rlB5w
-nhGi79lgn3z2a5+3UCaXHQY+vMhJgMFVYoOfmUCNd4cnTgHMtr5Ai9tOS934lj0Z
-xL/XOfx1v6ownw2VOZ5LWxMi2YnYTqC8323wPhcHjTecnE9JprakdJa6q54gsbZR
-j1fs
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27EE.pem
new file mode 100644
index 0000000000..ef47e0ac46
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest27EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 8C 29 EC 44 7C D6 41 58 5C 23 39 CD A4 39 0F B4 06 89 86 7B
+ friendlyName: Invalid cRLIssuer Test27 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cRLIssuer EE Certificate Test27
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA2
+-----BEGIN CERTIFICATE-----
+MIID4zCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMDAuBgNV
+BAMTJ0ludmFsaWQgY1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QyNzCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALvJAVQl+mEVV76pxF99Fc9KxIhU
+DuSfs05Fqh87Pl42ZCLpoiPbhudnMaqp2y1ifi3dxPvDIAxH5Tc/N3SoftcSPxdn
+W3DE4tS1A4uymQeWnY1eGHnhz5Y6NsqYCbm/lxCZQLRO/krnm7xrTH57QG54M9E+
+MTMpEidf1718C5K8y/OvGbtv15Edefc+k69SplhiTJc394PYUxt0LI9HzHdOlsXt
+WAQwhjZnt0EXuqn+J6NFum9IM6MYaFsTjZaGHSRroKz+UfAzFGW5tA/6EXLBVGD6
+DPLZta+5Z1LUfveWbBoKkgnH8PUwBtrEDY5SBENtlO9NSVWiXJ3VsrfIPpMCAwEA
+AaOBvzCBvDAfBgNVHSMEGDAWgBSII+Gzs/Js/jGpvothqjuShwWkozAdBgNVHQ4E
+FgQUVSJwCEr2Q8gS6e/AwFKOUnZdz2swDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATBRBgNVHR8ESjBIMEaiRKRCMEAxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRAwDgYDVQQDEwdHb29k
+IENBMA0GCSqGSIb3DQEBCwUAA4IBAQBf33KnXHUpBAiIQXAWCZAEbyNYB6Fk/BIa
+zgm21r/1dqB9Wuovu+AiacxaeqOfusdB8HsQHKk8uTxK1LS1Zqmf0Ym37tPd3Qtp
+dK1D+Lnthbw89dBBjr9MTbwZKblrsqArmhulfo2LB+OYLaODU24zy8i+pwUkJuMF
+lApg5z1ksE2+Hhcavz7ZljjSrQTZU4gZ7rq5IleXw6i4a4RqROQdwGXSdAMKO2fr
+14aq/21J3VZ8hqIPy8KLokwwD/7979H0AvKCyWJh6UHGqWiq+2tLOzXTMSVEDztF
+V3lYqmXmnK4YmWwD+L4YO3JI1Har+eC1Xr2WRD/IVhELgJzybsUQ
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8C 29 EC 44 7C D6 41 58 5C 23 39 CD A4 39 0F B4 06 89 86 7B
+ friendlyName: Invalid cRLIssuer Test27 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FE17934CAEAF3C91
+
+ssa3xZ1gRO+SH8hvfDW0uJsR43CM1VKsQCNm9IRuH+qhEgRA1ElYCCvH02lLGTJ5
+MR+sPJFrDM3Wf2Ho6g9E1UZ5OfyPmNIk5iHCUvdQbRB0TGRhnTMcG5EbI371DPyv
+tU0DwTqgItTsJyWmw9gLdE400rP5BgYZpmt47/DVKNheXfSeeg647Wt3baSxHxUb
+iy4iOdbYhVnEouT9zJC8Bbp05hhNtQaOBpF3MyUUi1OHtp31Ep+3YWKFz/3ghiB6
+r8Fgy8CZ9wfXQDnjPB0FRnBlz14lcbyxM2et8fdqFFnyIoQ1tU8wJbVB6QTursSZ
+FSVX8Nm3T9xqHiv5yzpoM4Jxrqmq+jzFeaNX1NekLhREybhBHZweW5tWrjcsshAx
+uWa8AaL2X4Fpq1XdnNHfTBIn1jDfAa2dwyB56gXXgm1GHGRaakvxkP3nLfeHtj8e
+DFEZN1gc+T0djaxaoO/b+J9cnML4mqY+faWHkJTCh+mbtTHwLcil63HIWSvohtWM
+xMhcJkLhNVo+8kjlu6+BzYG6Uf9tX/W4nBT77qrTBjUyYeVF6r0OlyQzA4kf1O9T
+eUQmrQ10mcMrc5rVrDXRlBeivio+uuc5LvdgG8rV5XzlEFf0OXPbDMh5/1UHXrkM
+lT8egxMrAtC0yx/3zTPBTLd8681OAZiqX6WUHWk0e9BxnQmYW1DayQWJnMODmyPn
+m2cMtLn47/MFOPIMQSzMfdT463wjPTRybhJR5eLKXXJWTxlPktqEoG5ZFz/9KtfH
+HH7maYTHiRv5TgvU4vH4x5y7IXjt7m1KB1EUympq5MYmQ5/9j5npPKfxeToZQxJk
+50fwcss7zQW2fbDrudy1Rl35dVgr91A04DHHhzuPnxbHgBsJtPOF5NuvQByTDvf8
+yhleM9HNchEPW3Ohu5aVL8oFRyFfFGntAVtSiGFUHM+JqXwpT0dp7AIx3pwfVnAy
+eDY6b44cuq51f+26fw593uxKNcwvPkQVl6xMDThGuF9j/lrAj0vySxof67uybDgK
+wP36pId5bfSLApDFj7Kk7hHhAA4hM2MOmw1nsf9vf+rpXuyyuMPZpqQXmRdaqz4d
+pw9S2neKBl2MtWNIL/YJqMkFdTj0DxE7hhOLGGbJ7pMUyVH7YC7ZYN3ztlJNLekH
+/3lfG/hFLsqTRI79Rl8wneNDfncdPkhT8LJxz7qF3VJsE1iwGdPuK9DJeT24brqx
+N6qubGkzIWIyGEDfrNR4fi+TRfzabnVixL9tREyTbGmL17RWDePhzNwSu7SZMVSP
+bqRctEsUpgJxKWNR4Tr3Sx0B8ZLogoMmQeOgf9zLh3l4UFLlituCc/1QTS8GcpPt
+6l1akizdOBEAyW66QReVPwj9HIaUiN8Fs33nEbA8dMRuWuhMxz4Ly20LJYUeDQLV
+wZpL0WCO9WMmee3P2a4gMPT4QkHFFJPzn6fnQ1M1cLA+BgFNAE3YrcWDLM/c+LC3
+1B9uQZS8cY8OhLTk8mZaAN2PYvSR3Zur9MlXMEA0YQ4e+nh9WI8WL46BMGpoq6BD
+mZ1mRLC64lIb9mxh96r7dTlexKoIh9rej80/eoXObqf1mpe0eSkGzUOP6dP8b8qf
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31.pem
deleted file mode 100644
index a370fa86a3..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31.pem
+++ /dev/null
@@ -1,226 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA5
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0E1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx678FWV/yNhQZJRyI
-iaMmsrcrL1oSrYNu6oCM7kFCgk9PSYQRh+4SVNGyvyuQQ74+C4MLKd+GgMPRtHok
-km0S1dv/hLd6qZcVzhL+XHQ+ufLEbZqs1ZXSUfqTJFJpAgu4qLqMS8iZxijRGaDM
-6cQdbVcLMhxTC6sYFzuYtl78gwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlK0S0eEOfsO7N0tBPW1ZgD9EV20wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALAhR+3HUAbz9RiSD7M2UTI/CO2tE7dn
-6zSaQvkfm/UVsDvNLmSaeXS/29C8sHeoEVpmDdGbgCPcMwB3lTNt2pKI5jhr9f7J
-7BE1W43gZMR2YFRrkMX8AhQKVRN5LVpQIKjGMm8CkTPH9ecvH8kGwYcB3qLZwD3H
-sN+wLRApTQTr
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA6
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0E2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5/raWoeX0Fp14qkKY
-Ypdts+gzpB6uEBcK8SpAa5FzydBYcIJajJ7MbWLlH1o1nzd27E2YQQPaVuRvB9vS
-4Tih5plnbOXvkaUVh/iohILhb0Q49JWe4JU2yQsphppmzXgUH7C0Zygn3N/fd8JF
-MUxK0kDYmuerHsZ7DDIJsAOTpQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwhs+qhpOwTOKGqpZSQOxZqIc8H0wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACMudfomzqT284TDQDAaT8SdUGpP0bH0
-ofTP/6WODMD3M2+AYgM5ES2McuNKWBx/iifIy42icqmtiP4EjbwjK5JKPJzSSyIF
-/BL1+/TdNfvGBuDBG7qoVzqALx4QeAdCh9tjM9eZQbwVuIIUiI94VPU3hT1OcJRE
-ZCkFIjgPYCPR
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cRLIssuer EE Certificate Test31
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA6
------BEGIN CERTIFICATE-----
-MIIDUzCCArygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBNjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFsxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4GA1UEAxMnSW52YWxp
-ZCBjUkxJc3N1ZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDMxMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDF62+bmWqsIJDuZD87vUAXArOAHy8ctB87FGlfVI/UMp3x
-SJEM7Bb7cFD9DtWIsr+NcvEGIJIHqxSS+uqbSTkhLRkkQ6V3vZBWw9iK4YCixNHV
-4ngJovgzMWKjjTHBN0+8wtZz2gccx4lD4l8gvC41scMQ7qyQqIX0ByUafTEMAQID
-AQABo4IBPTCCATkwHwYDVR0jBBgwFoAUwhs+qhpOwTOKGqpZSQOxZqIc8H0wHQYD
-VR0OBBYEFDRJXOe+nS5RsQPtEvFYSSZSIXVPMA4GA1UdDwEB/wQEAwIE8DAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwgc0GA1UdHwSBxTCBwjCBv6B0oHKkcDBuMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsT
-D2luZGlyZWN0Q1JMIENBNTEpMCcGA1UEAxMgaW5kaXJlY3QgQ1JMIGZvciBpbmRp
-cmVjdENSTCBDQTaiR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENl
-cnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RDUkwgQ0E1MA0GCSqGSIb3DQEB
-BQUAA4GBAIPT9aAYLcz53VCc4i5LC7bw2UhSE06ovDozPQVlLW7ykaoApryS0aRb
-jRDf/csLFBaDbcmymFBGlYDsnDMv1+R2Azj5eUy4ssEpCYDsKyJnNvY1AD1aldyn
-hwyrIcLgWdU0rmHIT9m+/yLKdk31P8B3WKl6nNEtJVe1hlyeR8Fs
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:AD:12:D1:E1:0E:7E:C3:BB:37:4B:41:3D:6D:59:80:3F:44:57:6D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0..Y...R...N.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA6.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA7.h0f1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51!0...U....CRL1 for indirectCRL CA5...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA7
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 07
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 08
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 09
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0A
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA5
- Serial Number: 0B
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:49:47:a1:74:fb:1b:35:e7:63:c3:18:3f:ff:34:5b:ba:1c:
- d3:05:5c:a5:3f:2e:d1:1b:fe:d9:91:8b:25:a9:b1:e2:42:9c:
- f0:f9:98:c2:ae:94:da:1e:da:b8:38:51:6b:42:c1:6e:c5:9e:
- 44:bc:3a:b4:36:57:f8:56:a1:ae:4c:04:ca:b6:67:2e:da:ce:
- 51:b3:17:b7:9e:1d:12:af:54:9d:37:88:d2:58:9f:c1:a6:53:
- 79:c8:aa:90:45:b2:ff:61:63:e9:5e:2c:7b:4c:6e:a8:71:ab:
- 7b:10:11:aa:c4:bd:45:ce:9a:09:d5:f7:ac:0d:83:7c:62:3c:
- c7:af
------BEGIN X509 CRL-----
-MIIFfDCCBOUCAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowggLKMCACAQEXDTAxMDQxOTE0
-NTcyMFowDDAKBgNVHRUEAwoBATB1AgECFw0wMTA0MTkxNDU3MjBaMGEwCgYDVR0V
-BAMKAQEwUwYDVR0dAQH/BEkwR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RDUkwgQ0E2MCACAQMX
-DTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBATAgAgEEFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwdQIBBRcNMDEwNDE5MTQ1NzIwWjBhMAoGA1UdFQQDCgEB
-MFMGA1UdHQEB/wRJMEekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBNzAgAgEGFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBxcNMDEwNDE5MTQ1NzIwWjAMMAoG
-A1UdFQQDCgEBMHUCAQgXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUEAwoBATBTBgNV
-HR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMRgwFgYDVQQDEw9pbmRpcmVjdENSTCBDQTYwIAIBCRcNMDEwNDE5MTQ1
-NzIwWjAMMAoGA1UdFQQDCgEBMHUCAQoXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUE
-AwoBATBTBgNVHR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwIAIBCxcN
-MDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIIBnjCCAZowHwYDVR0jBBgwFoAU
-lK0S0eEOfsO7N0tBPW1ZgD9EV20wCgYDVR0UBAMCAQEwggFpBgNVHRwBAf8EggFd
-MIIBWaCCAVKgggFOpHAwbjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2Vy
-dGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGlu
-ZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E2pHAwbjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENS
-TCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E3
-pGgwZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgw
-FgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxITAfBgNVBAMTGENSTDEgZm9yIGluZGly
-ZWN0Q1JMIENBNYQB/zANBgkqhkiG9w0BAQUFAAOBgQAFSUehdPsbNedjwxg//zRb
-uhzTBVylPy7RG/7ZkYslqbHiQpzw+ZjCrpTaHtq4OFFrQsFuxZ5EvDq0Nlf4VqGu
-TATKtmcu2s5Rsxe3nh0Sr1SdN4jSWJ/BplN5yKqQRbL/YWPpXix7TG6ocat7EBGq
-xL1FzpoJ1fesDYN8YjzHrw==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31EE.pem
new file mode 100644
index 0000000000..90560091ca
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest31EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 04 69 7A C0 F8 D1 7E 3D 6C D4 CC E2 AB EC D3 47 99 21 7F 3A
+ friendlyName: Invalid cRLIssuer Test31 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cRLIssuer EE Certificate Test31
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA6
+-----BEGIN CERTIFICATE-----
+MIIEbDCCA1SgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0E2MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMDAuBgNV
+BAMTJ0ludmFsaWQgY1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QzMTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOdZlYRiJUYOp5WYFV1jVCmoQisZ
+Wrsuz0ZIazNWxlXfUx6xCMZrSVa4uixQ8dwvvqUbQ6/H3DLXdhp9R6br11Fw9Hcb
+E7cCYSJ6/NuP1koE0eBHooh78n5thPOzOJks0DfVYPwoXM63B+z1MN+w0juSdNYH
+5ck2QeCO6FU0xlk2UnkmuWhoIvA2UFFx9LQgv4nX0WfmHg/k5e6dSU/O1hcjxT/r
+ivNnvBNLKjRhLrEOb57Fv47C0rs2nOruQSK95oxuBRgGaSSDdrT9TTFSgHQ3POUD
+pqm5vhrBzBPwBsoWZYMHaYz/HnQlBhIWgBDP47Vq7OrXx38n56Q0tcbaYqECAwEA
+AaOCAUcwggFDMB8GA1UdIwQYMBaAFB/JII0Lo2wtd08T3kL0C7beKnYxMB0GA1Ud
+DgQWBBSRqu0FdQ+STZMQVrOX23I4Bqkh5jAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMIHXBgNVHR8Egc8wgcwwgcmgeaB3pHUwczELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNV
+BAsTD2luZGlyZWN0Q1JMIENBNTEpMCcGA1UEAxMgaW5kaXJlY3QgQ1JMIGZvciBp
+bmRpcmVjdENSTCBDQTaiTKRKMEgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwDQYJ
+KoZIhvcNAQELBQADggEBALJdyQ0VWtdTlrYjwxr1svYyFO4orqmxszn+1Bjhbqy2
+9jTBWUv5Cf/+wnRjFsS74OuLxS+CXkR5LJ5K9Wzk0oVBIS32QqSVZf4RkP935p5r
+D4QpQVnKqdzoqGJ+qfWkayXjNW3kxaXc33v12Z3JeAnh5kpZv7CmBe1FDpoAVu72
+wGbbZ4joNc5QV0qTTw0jHL/mH2iaaPiJClmC0l5zB9w/t3OXCWOyr4fBmnUag2vu
+ROYeTpfBXPBLJqxtDoAnkr2fqeNiyxJ+ORGC0sbbI2cIbs7TWomS5l6VnJCv0R+X
+TpqqCqwccXjJmR/qhF3iJkn9bxrDgrixX6H3FcXcIiM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 04 69 7A C0 F8 D1 7E 3D 6C D4 CC E2 AB EC D3 47 99 21 7F 3A
+ friendlyName: Invalid cRLIssuer Test31 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8DF42EF54A7ED06E
+
+4nKZD/ybq6VJE6lI6y1Xk4SDZ7OPMhDEsnLnYqu+/V03g8ItSWKWwZG/wQ02LlSt
+NXGLPbx2hURYayjCjGKMgHPTfImuKUcurL7qKaftZ1D8YoroyybQ6SMLmmdanBAX
+y1SDOyMud73jgrfDj80Dej2eX8CL3ip5myGmFr3HJ4riysWLOaS9lttcXgXXs2kl
+LTC5HUKLtr9wPjbgC9PD25Rx1gG00XnSUWthYn8ATVVrRhf41VbIDM9ZGISBa2j1
+ibfIZ3Bl/AerrTRknDJe/tHILGX6Q8Zy0Umep6K5ByM9O1rsjuTbcCNxXiO+bGYk
+tehb+1e+i/dkv92NZ7xC2NCAI+bSqwi0vvKL1E9Vlrp8ix1oBAIy2bY7qYETRFY/
+qNKqa7oyo9f4ThTDo94Cfk8wp36/PMyqQD4addS1yYTQFbTAPqtM7NApL23O9Q6q
+a9kSE+yereIu3ztAAqKwaEGBZPqrLS1ldXt9xBtxUr7F1KoytENESylVo8ULVSfc
+/ew5/2toQGVB0YkJfzPKL+ZCqGnaelwh/m+V3D7o+RJlZhfd8cTMAEP0MI8xO78R
+VeG7nowYvLSd+fbG+ehyALH3JRPdLrjnyjlta3ALa1bfNh08U9ZCswdh8+mAca5x
+p4VQwgAtDo1Iu8lYpmJa1oYMdJhRsE+x6KwI1/ZL8tE3h2q3YDEZrieHu5FniIod
++0gz6EGUNYiSel4gxNEvcDs14itsy9AM97fEDWR3U3M7u9y/hS5/htICWsyOXtGD
+SPqwWtD4nlsmWkd1TM9eUyKI1PmrRPQXkEb2i1G5gAFXn1JXV2ju2CCvqoLaLBHE
+UJgTujUAx6A851T3/K1WtJT4/eVvlC2P3KlkYAaKysEHzvHVzPmR/JeutgNdtlk0
+pwMO4ITTCdjWkjbAaIImlpbrDGTROcjaf/CllSfcTXPQwV5V4rotW2UYOwGEgidS
+x2+17lQkVnJRQlhVMY3iwNK+mg3VD6hrV9ACWZ4uf8o0Y33UcAea35qeXj+JktUz
+ZcQwO3N2ZRRK90vipd7SlL11oGgPeHS6YHCPDI4nzy6JX9WyK5WLxcbMw2m5rx25
+pDw7ZH8As6IDcQVX3w/SlMXjJsSL4mX+nqKTo9sGzOButih0ZzLbvK6Ty0ZllPSG
+IGbllNI/JZmNbu1ozkKYn/1X2H1/8+igfXYaMlJsR/QRcLseGbHWUOuCS/VvnnUa
+HnUtWpQN1nDzv/6zGhCEe0aLM3OeQG6KjmUpyFakF/GVPpuCmkcTsOkL2HOQv+r/
+fvYgpiNCC0/bR1D4m0U9byIIg8qVBEItex7q6eMBgHNYVuOVvzVhK2AWcvuM6n3U
+2hluJHJPRKoODvBqlzlTz7Hh1P6eROWlKRB8sokKWe+pEYQro1oSGpOCOpWbe2Y/
+oYADEZ+CgKeCglKAtXeDBOSrUo/lmvrLFsMI08pdddNHgdFwApNFfy6ZNo51LAA9
+GvjJ5NxEKbbIscGUhEQ/RVTObduQqUpcuYqkcnEqtJAEgZR6qy8bos9cLR5bG5Y0
+oN0RB8NRTPw4l7Bldp1+iDRmlYM2TvKqBwtbV04/TPcrxKAzjIgZmw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32.pem
deleted file mode 100644
index 5dab635a7e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32.pem
+++ /dev/null
@@ -1,226 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA5
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0E1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx678FWV/yNhQZJRyI
-iaMmsrcrL1oSrYNu6oCM7kFCgk9PSYQRh+4SVNGyvyuQQ74+C4MLKd+GgMPRtHok
-km0S1dv/hLd6qZcVzhL+XHQ+ufLEbZqs1ZXSUfqTJFJpAgu4qLqMS8iZxijRGaDM
-6cQdbVcLMhxTC6sYFzuYtl78gwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlK0S0eEOfsO7N0tBPW1ZgD9EV20wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALAhR+3HUAbz9RiSD7M2UTI/CO2tE7dn
-6zSaQvkfm/UVsDvNLmSaeXS/29C8sHeoEVpmDdGbgCPcMwB3lTNt2pKI5jhr9f7J
-7BE1W43gZMR2YFRrkMX8AhQKVRN5LVpQIKjGMm8CkTPH9ecvH8kGwYcB3qLZwD3H
-sN+wLRApTQTr
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA6
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0E2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5/raWoeX0Fp14qkKY
-Ypdts+gzpB6uEBcK8SpAa5FzydBYcIJajJ7MbWLlH1o1nzd27E2YQQPaVuRvB9vS
-4Tih5plnbOXvkaUVh/iohILhb0Q49JWe4JU2yQsphppmzXgUH7C0Zygn3N/fd8JF
-MUxK0kDYmuerHsZ7DDIJsAOTpQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwhs+qhpOwTOKGqpZSQOxZqIc8H0wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACMudfomzqT284TDQDAaT8SdUGpP0bH0
-ofTP/6WODMD3M2+AYgM5ES2McuNKWBx/iifIy42icqmtiP4EjbwjK5JKPJzSSyIF
-/BL1+/TdNfvGBuDBG7qoVzqALx4QeAdCh9tjM9eZQbwVuIIUiI94VPU3hT1OcJRE
-ZCkFIjgPYCPR
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cRLIssuer EE Certificate Test32
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA6
------BEGIN CERTIFICATE-----
-MIIDUzCCArygAwIBAgIBCTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBNjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFsxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4GA1UEAxMnSW52YWxp
-ZCBjUkxJc3N1ZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDMyMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDGNK1Y+eOYRm50GYuyrg+CaupAyx1885TUh0lz/2sHwXp2
-OmsLIqfukEyyIfBt/gEHZ4e3CvSb8unsTq/Jlt++srjlPkTPaJAJZmVhhLBS33c/
-L4t1J9CE+W5JEzzQjzhhtAgsOxH4gy6PqQ7MQ3LPRSUFqwtFlOjUaVDekanP/wID
-AQABo4IBPTCCATkwHwYDVR0jBBgwFoAUwhs+qhpOwTOKGqpZSQOxZqIc8H0wHQYD
-VR0OBBYEFCFEpTMSRVJmDIG3biuYZ63bFngaMA4GA1UdDwEB/wQEAwIE8DAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwgc0GA1UdHwSBxTCBwjCBv6B0oHKkcDBuMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsT
-D2luZGlyZWN0Q1JMIENBNTEpMCcGA1UEAxMgaW5kaXJlY3QgQ1JMIGZvciBpbmRp
-cmVjdENSTCBDQTaiR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENl
-cnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RDUkwgQ0E1MA0GCSqGSIb3DQEB
-BQUAA4GBAKZ16nizt2hCVkrf+WfJV1t/frRX9W7Oi4whQqH9BEA2nEZ9LVeGnCAZ
-he10WnY1rXA2JHICijj3YDBoAlOMWtp43Qhv32QJ4dFR08kuSWjvCygSokh9uyoX
-Q/zpF1amF1x/Br/uteHCBILXFFGLLsSauW15U4HWUiJQHob56396
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:AD:12:D1:E1:0E:7E:C3:BB:37:4B:41:3D:6D:59:80:3F:44:57:6D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0..Y...R...N.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA6.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA7.h0f1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51!0...U....CRL1 for indirectCRL CA5...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA7
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 07
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 08
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 09
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0A
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA5
- Serial Number: 0B
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:49:47:a1:74:fb:1b:35:e7:63:c3:18:3f:ff:34:5b:ba:1c:
- d3:05:5c:a5:3f:2e:d1:1b:fe:d9:91:8b:25:a9:b1:e2:42:9c:
- f0:f9:98:c2:ae:94:da:1e:da:b8:38:51:6b:42:c1:6e:c5:9e:
- 44:bc:3a:b4:36:57:f8:56:a1:ae:4c:04:ca:b6:67:2e:da:ce:
- 51:b3:17:b7:9e:1d:12:af:54:9d:37:88:d2:58:9f:c1:a6:53:
- 79:c8:aa:90:45:b2:ff:61:63:e9:5e:2c:7b:4c:6e:a8:71:ab:
- 7b:10:11:aa:c4:bd:45:ce:9a:09:d5:f7:ac:0d:83:7c:62:3c:
- c7:af
------BEGIN X509 CRL-----
-MIIFfDCCBOUCAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowggLKMCACAQEXDTAxMDQxOTE0
-NTcyMFowDDAKBgNVHRUEAwoBATB1AgECFw0wMTA0MTkxNDU3MjBaMGEwCgYDVR0V
-BAMKAQEwUwYDVR0dAQH/BEkwR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RDUkwgQ0E2MCACAQMX
-DTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBATAgAgEEFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwdQIBBRcNMDEwNDE5MTQ1NzIwWjBhMAoGA1UdFQQDCgEB
-MFMGA1UdHQEB/wRJMEekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBNzAgAgEGFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBxcNMDEwNDE5MTQ1NzIwWjAMMAoG
-A1UdFQQDCgEBMHUCAQgXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUEAwoBATBTBgNV
-HR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMRgwFgYDVQQDEw9pbmRpcmVjdENSTCBDQTYwIAIBCRcNMDEwNDE5MTQ1
-NzIwWjAMMAoGA1UdFQQDCgEBMHUCAQoXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUE
-AwoBATBTBgNVHR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwIAIBCxcN
-MDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIIBnjCCAZowHwYDVR0jBBgwFoAU
-lK0S0eEOfsO7N0tBPW1ZgD9EV20wCgYDVR0UBAMCAQEwggFpBgNVHRwBAf8EggFd
-MIIBWaCCAVKgggFOpHAwbjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2Vy
-dGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGlu
-ZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E2pHAwbjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENS
-TCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E3
-pGgwZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgw
-FgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxITAfBgNVBAMTGENSTDEgZm9yIGluZGly
-ZWN0Q1JMIENBNYQB/zANBgkqhkiG9w0BAQUFAAOBgQAFSUehdPsbNedjwxg//zRb
-uhzTBVylPy7RG/7ZkYslqbHiQpzw+ZjCrpTaHtq4OFFrQsFuxZ5EvDq0Nlf4VqGu
-TATKtmcu2s5Rsxe3nh0Sr1SdN4jSWJ/BplN5yKqQRbL/YWPpXix7TG6ocat7EBGq
-xL1FzpoJ1fesDYN8YjzHrw==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32EE.pem
new file mode 100644
index 0000000000..913d2a06e6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest32EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 83 AF 9B 57 E2 15 82 8D AD 37 03 DC BF 66 47 87 B1 78 53 6F
+ friendlyName: Invalid cRLIssuer Test32 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cRLIssuer EE Certificate Test32
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA6
+-----BEGIN CERTIFICATE-----
+MIIEbDCCA1SgAwIBAgIBCTANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0E2MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMDAuBgNV
+BAMTJ0ludmFsaWQgY1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QzMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANR/hypQd5ZfgQVkP+On0t+Rs82X
+m+cbn8RfIKdGJ16TJx+umPn5RbrBegqLCsNMlnuSayqfI8dRDNud1lygtx3o8jVq
+7Hghl+UKnhzgq6kJoQLTcps12ELcEU78o8hkf7p//zpHTu4KgPu8uOlHHeh4poqG
+2HumXXJjVXgl3YTUeufUCIp83N0U+bzZ1hJp/1giElpUO7mzg3Fgqod8pklHsIab
+NwYPMA7nBGpOgd5U2OTJezmxd0s+qIpB8pE2TOHkg0j2K3o28YHHtCdRR+0eR8bv
+e/9c1JguAgwlOxYexaw8ILTF2AIRCdCqKQGzuayx1wkuyMrbTbZRhIQrSdkCAwEA
+AaOCAUcwggFDMB8GA1UdIwQYMBaAFB/JII0Lo2wtd08T3kL0C7beKnYxMB0GA1Ud
+DgQWBBTzLCUxrEFAGDyfXPzyKzqsnz+oMTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMIHXBgNVHR8Egc8wgcwwgcmgeaB3pHUwczELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNV
+BAsTD2luZGlyZWN0Q1JMIENBNTEpMCcGA1UEAxMgaW5kaXJlY3QgQ1JMIGZvciBp
+bmRpcmVjdENSTCBDQTaiTKRKMEgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwDQYJ
+KoZIhvcNAQELBQADggEBAH6YyaHCZXx+PWVzfSNQJClpQbMWgdnFe6430QrRzXXq
+djUbh94OnKIJsv8Q4IjN2dgcClEm/UMyPmE5BYNhrUwtTJ1qkaVJPXWDhUHACKiM
+fpyvFedpP744+uyE5hjGe/d6Yy67XIJ31Utj37u9dqA1u51nN+lsy4UN8a8OVeqO
+Coe7QZjlVLn3VVr981YvW/3zbk+RE1AZlOtZ6UhRfUaYSJpKjBf4PO1NzGVEWSgQ
+2I97mAcgjwgt/xY4ydOUqPvExGvsbG3fC0tBmzbqPuV4ISoZ64bWW2sEX8Wuz1aw
+yTzhyxQSkCTUNlGS7DRkguwFpjMGUr8D4i6QOdkAnCY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 83 AF 9B 57 E2 15 82 8D AD 37 03 DC BF 66 47 87 B1 78 53 6F
+ friendlyName: Invalid cRLIssuer Test32 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B98AA6601A7ABDD2
+
+MrLMqzxICNQXMq2sBzGu6gIhOpr0VCPS50gHE8ZaiQo1Fo5cburZWUG3xwtivTxK
+spxUCoomPrP3vgyK/xZLuIVxsblHuRn3UnlgESB5fNoTbpkhA2ayz892tC9e5vw2
+wnQOW876vd4XT3vB6U9zH7QXGh5IJP5ynbtvHu0j9hQZbYuUBXBCXt9WWzAEpSEp
+udL3BLUJ8LsMkCExS7rRwKd6DauL1Wl3/PZx7wMiAX1xgoAatQJt2R8fC5cK50Pk
+rUpGXASy7tAYvkKgXDtoSePpZPeQG1JBH/Atr6MNuIBNvCR/FCWTb/RHcZONi1k2
+TaQ2lHwK69hV+irlsmnU0x0GXwlSW16PRcwp5I5OBqJDGUdKVBhcb8+oqu2ihNaj
+mPx9fY+BS89RdMwHWZPopgxzvsOfOO1yXK6Iv5jA5GZGoko5BswKjfC8AdZcNvay
+IjQ/tOhQIfxZUjYAuKvItR5lUEy189nMJBApQ5a9H6c6gdnBk6qvlKVJuzwW0B5X
+2WcQuf9aFL5H1vugKCQZYOQYVN3sm8/t0zTjs3eKQTU/opIVoz7QialxljJUa5Pg
+loNFztRsvkB2SjowGy4tkKWhiIWqGCl628RQHrZdDrye2S/+OgfiOsBZKm9K4wAX
+aMH7lIxlnsgZTW6VCN2FP53TRV2CA4eNqXec8Pu0WXyXkglN+VNZ5r2wL25mdwDq
+eRRM2nKzypS2tT3FpxbU+orZtfVQV4nEhMPCs4rYsq+R2+OITr+2DGcTLGnsMyBj
+K8+lQ4PVaWJuzank5TSjK9wZtlOtyp9ewZ/TZ8evyQ8SvKm908CiTtSBGUfUfeRt
+SS2Nh2UlsSIQ6FT59vjf6/N+mZevXoWLSaLyVZLVANLKSQ5VkAPtrVJaM9c5Bij/
+axO7+gPMuCI4Ee6OJsKEfc+VglKnyA4rdr3RRmXQjjuWItrsxrt++VRoOuoMGTrJ
+tnymW8vAykeXQYUEsfNbeXqsC4NdKG7EBuSkEKpV8x03PIyqpyQoNUT3W6QeiPHs
+FtRiRcTlfP9T9f+8vZnsCMn3m2tciAvZCBzodCZLWuAtxfFm45evG8NzwnVPSmQb
+aBrdW3l/QOwPmdQMv81sd1fkn4Cc39ZN1+49KSiJlX70BgnDCBRxRNPGCBiyg4Cn
+bLZhUZW+ctPMkj5wEXxcveairewFJqvpc6rRTg5MG4Yo5sfKj0F4xwWYY+I0BzKW
+4gCXSXiPnmPR8Vnw0mKOxUyBCFW7/kx0K6h+PyqUQO3yNAZqs3lr/qRCnVqs9PHf
+cXTqfqKjavbLKTejYgdSnzJlYRShFjE2E4YB+0c9OkJbV0epua/N9wrFxj3ineXv
+wYQclFFY9ZWXpdh+8Z9Mh0EJk8z3UC8wV6/+nh77cHGOY8NnTyxCMIHyVtoQe73h
+ang99VGp0KwC7AHReWWorS/m1jldGKtXnFgs+ImuLa8cVAr3g6hYpOI4+gyDgvbs
+jvkaw/sWFznat664Ztvi/08s6SfS4CpqqLrQiHh+NExso8mmt+N1mKNuSBfFlQiX
+Pjm7yMZEc/Oy6cOvjWt9qU9z3JyTwS341E/jojBMX4VO417KLib65A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34.pem
deleted file mode 100644
index 2e62d70320..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34.pem
+++ /dev/null
@@ -1,205 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA5
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0E1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx678FWV/yNhQZJRyI
-iaMmsrcrL1oSrYNu6oCM7kFCgk9PSYQRh+4SVNGyvyuQQ74+C4MLKd+GgMPRtHok
-km0S1dv/hLd6qZcVzhL+XHQ+ufLEbZqs1ZXSUfqTJFJpAgu4qLqMS8iZxijRGaDM
-6cQdbVcLMhxTC6sYFzuYtl78gwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlK0S0eEOfsO7N0tBPW1ZgD9EV20wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALAhR+3HUAbz9RiSD7M2UTI/CO2tE7dn
-6zSaQvkfm/UVsDvNLmSaeXS/29C8sHeoEVpmDdGbgCPcMwB3lTNt2pKI5jhr9f7J
-7BE1W43gZMR2YFRrkMX8AhQKVRN5LVpQIKjGMm8CkTPH9ecvH8kGwYcB3qLZwD3H
-sN+wLRApTQTr
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cRLIssuer EE Certificate Test34
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA5
------BEGIN CERTIFICATE-----
-MIIC/DCCAmWgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBNTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFsxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4GA1UEAxMnSW52YWxp
-ZCBjUkxJc3N1ZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDM0MIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCSaPRkABN56ESU2SA5P4mVXVChuwxsllnznUrRrpaH+L60
-m9Sa11iyGiUqTcGPQbEsPUN8zQQmsjnGSpIMtMRrnkaOTaUmzszVKp9xOuZ5vgSd
-8KeQJjqISqeeJL/oSynuMBOfir1TH2HToo+HetNsfXhumdPDKUojywjZcp1N7wID
-AQABo4HnMIHkMB8GA1UdIwQYMBaAFJStEtHhDn7DuzdLQT1tWYA/RFdtMB0GA1Ud
-DgQWBBQ4QCS2SjHLQtR3kH7i8O8sleHk8DAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMHkGA1UdHwRyMHAwbqBsoGqkaDBmMQswCQYDVQQG
-EwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGly
-ZWN0Q1JMIENBNTEhMB8GA1UEAxMYQ1JMMSBmb3IgaW5kaXJlY3RDUkwgQ0E1MA0G
-CSqGSIb3DQEBBQUAA4GBAAppj9RM8AKRmrj/d56ZzOcNlN79bi39iFp7ZuxrkdL7
-ZcnUm4A5y0u2ZoywD1LTUUYh+egAhtpccsYYjmMVQVbEtgwVKorXOwcm6iNmENQ6
-lsZPlEkEXBLlfZLuhPr4Ju+QjaMo7SLAiXOG9lwry8ZFcfAGLIfpLlQyGZ2cnahX
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:AD:12:D1:E1:0E:7E:C3:BB:37:4B:41:3D:6D:59:80:3F:44:57:6D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0..Y...R...N.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA6.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA7.h0f1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51!0...U....CRL1 for indirectCRL CA5...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA7
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 07
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 08
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 09
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0A
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA5
- Serial Number: 0B
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:49:47:a1:74:fb:1b:35:e7:63:c3:18:3f:ff:34:5b:ba:1c:
- d3:05:5c:a5:3f:2e:d1:1b:fe:d9:91:8b:25:a9:b1:e2:42:9c:
- f0:f9:98:c2:ae:94:da:1e:da:b8:38:51:6b:42:c1:6e:c5:9e:
- 44:bc:3a:b4:36:57:f8:56:a1:ae:4c:04:ca:b6:67:2e:da:ce:
- 51:b3:17:b7:9e:1d:12:af:54:9d:37:88:d2:58:9f:c1:a6:53:
- 79:c8:aa:90:45:b2:ff:61:63:e9:5e:2c:7b:4c:6e:a8:71:ab:
- 7b:10:11:aa:c4:bd:45:ce:9a:09:d5:f7:ac:0d:83:7c:62:3c:
- c7:af
------BEGIN X509 CRL-----
-MIIFfDCCBOUCAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowggLKMCACAQEXDTAxMDQxOTE0
-NTcyMFowDDAKBgNVHRUEAwoBATB1AgECFw0wMTA0MTkxNDU3MjBaMGEwCgYDVR0V
-BAMKAQEwUwYDVR0dAQH/BEkwR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RDUkwgQ0E2MCACAQMX
-DTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBATAgAgEEFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwdQIBBRcNMDEwNDE5MTQ1NzIwWjBhMAoGA1UdFQQDCgEB
-MFMGA1UdHQEB/wRJMEekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBNzAgAgEGFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBxcNMDEwNDE5MTQ1NzIwWjAMMAoG
-A1UdFQQDCgEBMHUCAQgXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUEAwoBATBTBgNV
-HR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMRgwFgYDVQQDEw9pbmRpcmVjdENSTCBDQTYwIAIBCRcNMDEwNDE5MTQ1
-NzIwWjAMMAoGA1UdFQQDCgEBMHUCAQoXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUE
-AwoBATBTBgNVHR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwIAIBCxcN
-MDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIIBnjCCAZowHwYDVR0jBBgwFoAU
-lK0S0eEOfsO7N0tBPW1ZgD9EV20wCgYDVR0UBAMCAQEwggFpBgNVHRwBAf8EggFd
-MIIBWaCCAVKgggFOpHAwbjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2Vy
-dGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGlu
-ZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E2pHAwbjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENS
-TCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E3
-pGgwZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgw
-FgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxITAfBgNVBAMTGENSTDEgZm9yIGluZGly
-ZWN0Q1JMIENBNYQB/zANBgkqhkiG9w0BAQUFAAOBgQAFSUehdPsbNedjwxg//zRb
-uhzTBVylPy7RG/7ZkYslqbHiQpzw+ZjCrpTaHtq4OFFrQsFuxZ5EvDq0Nlf4VqGu
-TATKtmcu2s5Rsxe3nh0Sr1SdN4jSWJ/BplN5yKqQRbL/YWPpXix7TG6ocat7EBGq
-xL1FzpoJ1fesDYN8YjzHrw==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34EE.pem
new file mode 100644
index 0000000000..c59c3f3943
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest34EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 89 5F 98 0C B1 66 E7 9E 21 5E 85 65 34 D3 11 DC D3 14 31 8E
+ friendlyName: Invalid cRLIssuer Test34 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cRLIssuer EE Certificate Test34
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA5
+-----BEGIN CERTIFICATE-----
+MIIEEDCCAvigAwIBAgIBCzANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0E1MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMDAuBgNV
+BAMTJ0ludmFsaWQgY1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QzNDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZM/UiUPAWzidGDMrvQQbEw5ccN
+ZDki0OBiRr2Tu3rM4VqPd/QD7mFrjNMrncCBdxjE1Qsz3ZEJ89HXf+G6M8uYosh2
+spbvAtn79j73GDlVAhhZwFSx9zgd4pgpsFmufyFdHQrh7UldgyJ6pmEbtxbWcee7
+ZqkSPY5rtvNEDRcF16sUjkXGdfQK+5my17lltU8uZJtmZ/5xY61HpfvI0Owjy6Ay
+tHCf9/Kf2WXHFT4ezwIQW1eTA3cNtQFHOIBuQu0C1EtiZFJBHthJyG4u7plg9FOr
+V7b8rtv9hIerEX6FGJ+/Jw8H+gPInhaFxdzOtkCV3LBiwgM4XhStsTegLGUCAwEA
+AaOB7DCB6TAfBgNVHSMEGDAWgBSB96q9SHVZgLDP3yMYndiTRoIWszAdBgNVHQ4E
+FgQUiiMx2fHS3UBFAJNBSQUGJhyCgP4wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATB+BgNVHR8EdzB1MHOgcaBvpG0wazELMAkGA1UEBhMC
+VVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAsTD2lu
+ZGlyZWN0Q1JMIENBNTEhMB8GA1UEAxMYQ1JMMSBmb3IgaW5kaXJlY3RDUkwgQ0E1
+MA0GCSqGSIb3DQEBCwUAA4IBAQBtVJxXc5x2a9fH2xCyJz8Rb2A/vJhatQ5J13Tr
+yPCuFcFfadOtMHGAZJL4A0bHxyiML5zhaNeXn7vk22RQxzLa/lSsJB9dRoSR3R9/
+XCK+f0babRaz5MxjGg6Xak+L2ZAYqhyHDeE+P13Hq64QZFsz8wuhX3dK6fd8pEOg
+3BtLHFjgOnrYZ3q93i7f6ehf3skfkEANC1rIiVwuTQdMutnVQzdw8tKw9pQHWgLZ
+f7r8zNr5YZV2RcPlK8alAfcGANKikTi6l+9SpOIpUDx/ebOjEekNA2tA1SPQCvqU
+J2nP9ZZ3l8MFwJHA56doOY+wy0Ee6AJZvYMjjx9RMAGXPyVX
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 89 5F 98 0C B1 66 E7 9E 21 5E 85 65 34 D3 11 DC D3 14 31 8E
+ friendlyName: Invalid cRLIssuer Test34 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,55A1A3201C7E23DA
+
+OAZ2ghpfbykGcuAG0gn6n5Jr84azhS9N/KWE1AsXazS1Za6WsDRP5c5fdKf/7Q2C
+7f/G60/zxazydN5IjhGnowKjkam9qQIoe5fpOYwBQ/cS2BOYiUUvnqgf7x2MMpKF
+lLdpSMR+/UgfQV61e26IqsYCv6Fxqsy2Mrido569V1UFR1HS5UoV3hU64d9DIx60
+hItCW+bk0SeHsj3V9DqyWW22jNJ5udGFEjEzUXyla9xr1NUt69uPvyFpyrajLNSD
+6VzDZOTGTQ55QAAYMDO3G4sSZI3SUAueOZdW4IFa8p4PdJaNaIIXmHu94WKGJwAp
+PMhHsY5V43VO9eHDwbDHpw3qQ7t/fpg3wy7M2GDSaCreilnojgss/Y02s6+lU8mH
+Hsn+2NcAwqrtdLkuCmLx4AtAWdsO+rqtMVHDwFaHrlaOezBlYTvycCQhpu3NAAkR
+zWVXLqageP2oBRCdjLshUE5XH5AqDjws+YANM3LUyEFojGeA14nJsCmGFKoUdSCh
+rorhOm5DxtA/0ETzBhkr64iE9RGMIg9lYl3WVZ+IewFoOhcO0jPnv/wRnQFpvNxV
+pXamOAnfdJzaBDhobizVK2XnSkI1gV4CVeBkf2PxjcsQwC/qfxPW+4L6wa/ISiTF
+9/7QnEF9ejY9JSbv0wKCZsCw64CPatVmgDN3HYc166VEQG9uKM4nhJzbrf3qFHu9
+3AWdObVlIBTBRanwW0/iRLlGZJTsyJ57bQgHU3dxWwafWtycgLfvDXe6+zV2FH9e
+inZwNUB+gQtNC07V0YmozwDO6XM9Mm7eul46suit8NFC7RTeEezzHDB8Wvprf9Bp
+lR7UVCyS2NrEWxpjEgSCv+kNKMqQLzZGnBt7+KPbWMR12EzHgvxuyaglK9CqjW+8
+r8GSwbWBpCfRr7QxR26zyF9eaS92E2io/WKHOD+bidzl8eesCohHxCqFqYvm97sy
+e2zqUPJHU8lUVjr9W7IdUDwTdQfV9+F+y+otPsahu9DhxGqTp7COjeluxb1Ef6AW
+3rBhLxyWk7tGtzaBkQlJoQbQc2/JxVz/M2CEGqJ1PEcodulYRTr6Pp2IB5triivQ
+1GCUjOL0mlSJqBcexvx8/P7u0czhfefZW4MT/iMV9J7Dt1L9N/nTqpm+yYghYr4+
+/l7YhXZ1Gv39FTlh+FTmhNyZRPSt3mY2fnHF3vzLukV76r1Zw+sN/xtTYyJw4tIQ
+NC12TofcaZ69cQGj3qDQv8EajEfAhUcX2vEb7x15sYg+LjKjcfe1dpMgWx9U++Ie
+MlACrfZKc/QtIhPgG+alrR/tbmuUBU9+RyEM46IyWf3i0FU+6BMDjJk0kNWGLnYq
+XGZrQriPoqNvH3cG4qeC/1lFblEuseoMCZyEurGYRR48actk0fV6wahKDGE1whq8
+JVreifyiAtPjelNsMdjd8KBqFIWQ2zL3exyW3JkmoyxTl/ykHTFtPhFDZ9X7fqv+
+lvtUwpsH6s1I5jh8q8Se04Zv9d1RlCuZpax8e9q3ImP8c06/097BEAS8N74cnW7E
+pW6Nft+fN2jY1Rcvi8/34OFpO9P7ZSXp9BhJgehMosDXPKEvTdTm0e0oK/g4ozRZ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35.pem
deleted file mode 100644
index 814ed525f6..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35.pem
+++ /dev/null
@@ -1,207 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA5
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0E1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx678FWV/yNhQZJRyI
-iaMmsrcrL1oSrYNu6oCM7kFCgk9PSYQRh+4SVNGyvyuQQ74+C4MLKd+GgMPRtHok
-km0S1dv/hLd6qZcVzhL+XHQ+ufLEbZqs1ZXSUfqTJFJpAgu4qLqMS8iZxijRGaDM
-6cQdbVcLMhxTC6sYFzuYtl78gwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlK0S0eEOfsO7N0tBPW1ZgD9EV20wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALAhR+3HUAbz9RiSD7M2UTI/CO2tE7dn
-6zSaQvkfm/UVsDvNLmSaeXS/29C8sHeoEVpmDdGbgCPcMwB3lTNt2pKI5jhr9f7J
-7BE1W43gZMR2YFRrkMX8AhQKVRN5LVpQIKjGMm8CkTPH9ecvH8kGwYcB3qLZwD3H
-sN+wLRApTQTr
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid cRLIssuer EE Certificate Test35
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA5
------BEGIN CERTIFICATE-----
-MIIDSzCCArSgAwIBAgIBDDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBNTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFsxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEwMC4GA1UEAxMnSW52YWxp
-ZCBjUkxJc3N1ZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDM1MIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDcad27MapNxZI8cHsmcsbc69H6JrfyxEdrb8jo4H7kREvw
-Ysye/I+06+hyhrY2ziYjoPjk5qwOT6MZoD6a8nysxt+wJwTtwWP7qrrHUrTTM4wZ
-825zHunib1GDGS6NDkRGi3ZZyHgwYGJIpNFvpZ2tYbnQ1YCd+82ApJ/pVK7luwID
-AQABo4IBNTCCATEwHwYDVR0jBBgwFoAUlK0S0eEOfsO7N0tBPW1ZgD9EV20wHQYD
-VR0OBBYEFHF/hceoUsXQv3cfdoCyVLgI9NqMMA4GA1UdDwEB/wQEAwIE8DAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwgcUGA1UdHwSBvTCBujCBt6BsoGqkaDBmMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsT
-D2luZGlyZWN0Q1JMIENBNTEhMB8GA1UEAxMYQ1JMMSBmb3IgaW5kaXJlY3RDUkwg
-Q0E1okekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBNjANBgkqhkiG9w0BAQUFAAOBgQAH
-2pRXjertT5rd9nPU9I5ZthZL8EBhTAfMObbfi8/CYJ+Cftct++cBQATBDBr6ho3Z
-TNjd6Qkd1wPPR2EgMk1HWJ6QS4/eQooeTsqstbgz6n/KcMB/+gQeYZbEyFoVu5e6
-C13SPmHSsdy1dtEVVELLreIOhfgSjoMBBQYMCJwffw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:AD:12:D1:E1:0E:7E:C3:BB:37:4B:41:3D:6D:59:80:3F:44:57:6D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0..Y...R...N.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA6.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA7.h0f1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51!0...U....CRL1 for indirectCRL CA5...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA7
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 07
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 08
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 09
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0A
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA5
- Serial Number: 0B
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:49:47:a1:74:fb:1b:35:e7:63:c3:18:3f:ff:34:5b:ba:1c:
- d3:05:5c:a5:3f:2e:d1:1b:fe:d9:91:8b:25:a9:b1:e2:42:9c:
- f0:f9:98:c2:ae:94:da:1e:da:b8:38:51:6b:42:c1:6e:c5:9e:
- 44:bc:3a:b4:36:57:f8:56:a1:ae:4c:04:ca:b6:67:2e:da:ce:
- 51:b3:17:b7:9e:1d:12:af:54:9d:37:88:d2:58:9f:c1:a6:53:
- 79:c8:aa:90:45:b2:ff:61:63:e9:5e:2c:7b:4c:6e:a8:71:ab:
- 7b:10:11:aa:c4:bd:45:ce:9a:09:d5:f7:ac:0d:83:7c:62:3c:
- c7:af
------BEGIN X509 CRL-----
-MIIFfDCCBOUCAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowggLKMCACAQEXDTAxMDQxOTE0
-NTcyMFowDDAKBgNVHRUEAwoBATB1AgECFw0wMTA0MTkxNDU3MjBaMGEwCgYDVR0V
-BAMKAQEwUwYDVR0dAQH/BEkwR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RDUkwgQ0E2MCACAQMX
-DTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBATAgAgEEFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwdQIBBRcNMDEwNDE5MTQ1NzIwWjBhMAoGA1UdFQQDCgEB
-MFMGA1UdHQEB/wRJMEekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBNzAgAgEGFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBxcNMDEwNDE5MTQ1NzIwWjAMMAoG
-A1UdFQQDCgEBMHUCAQgXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUEAwoBATBTBgNV
-HR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMRgwFgYDVQQDEw9pbmRpcmVjdENSTCBDQTYwIAIBCRcNMDEwNDE5MTQ1
-NzIwWjAMMAoGA1UdFQQDCgEBMHUCAQoXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUE
-AwoBATBTBgNVHR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwIAIBCxcN
-MDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIIBnjCCAZowHwYDVR0jBBgwFoAU
-lK0S0eEOfsO7N0tBPW1ZgD9EV20wCgYDVR0UBAMCAQEwggFpBgNVHRwBAf8EggFd
-MIIBWaCCAVKgggFOpHAwbjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2Vy
-dGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGlu
-ZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E2pHAwbjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENS
-TCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E3
-pGgwZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgw
-FgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxITAfBgNVBAMTGENSTDEgZm9yIGluZGly
-ZWN0Q1JMIENBNYQB/zANBgkqhkiG9w0BAQUFAAOBgQAFSUehdPsbNedjwxg//zRb
-uhzTBVylPy7RG/7ZkYslqbHiQpzw+ZjCrpTaHtq4OFFrQsFuxZ5EvDq0Nlf4VqGu
-TATKtmcu2s5Rsxe3nh0Sr1SdN4jSWJ/BplN5yKqQRbL/YWPpXix7TG6ocat7EBGq
-xL1FzpoJ1fesDYN8YjzHrw==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35EE.pem
new file mode 100644
index 0000000000..4df5ca0eff
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidcRLIssuerTest35EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 27 B3 78 2D BE B8 62 40 21 6A 96 79 23 0F 12 D1 10 89 05 8F
+ friendlyName: Invalid cRLIssuer Test35 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid cRLIssuer EE Certificate Test35
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA5
+-----BEGIN CERTIFICATE-----
+MIIEZDCCA0ygAwIBAgIBDDANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0E1MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMDAuBgNV
+BAMTJ0ludmFsaWQgY1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QzNTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMEZ3vjFkn5G0Phb9GsSjLsBjr69
+XZacj4oUQYXZE6KTPrGTuLxdS2p9kfr63rMkSLoKY+XcbcHDuc3MC9a8JUxCLLts
+TCi1XmiuiEy+/cTS8k0rQf/A/9uKZvqdp6AoVQmtIxWFbKV3SiOz9nz7d5tva6zV
+oxcpy6tNNuCB9On/t6teb548WBpMM2S28uzLLvTYKfB0J7QHCRf/kUhnWJX+ZkIG
+hq8b1UMZPSFNmm9pw7tYPNcra2u9MkP7FxnoBM7W0rQAEMZaKwhKQv8aE23pJyVD
+df59MBeqMEk7Jmejf4FQ+EiyF9EFdFnGc3VARqPYxk7RQzG4aXJxodf361sCAwEA
+AaOCAT8wggE7MB8GA1UdIwQYMBaAFIH3qr1IdVmAsM/fIxid2JNGghazMB0GA1Ud
+DgQWBBQ0OaRqmcOBlY37EyGFHakWthy79zAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMIHPBgNVHR8EgccwgcQwgcGgcaBvpG0wazELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNV
+BAsTD2luZGlyZWN0Q1JMIENBNTEhMB8GA1UEAxMYQ1JMMSBmb3IgaW5kaXJlY3RD
+UkwgQ0E1okykSjBIMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZp
+Y2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJlY3RDUkwgQ0E2MA0GCSqGSIb3DQEB
+CwUAA4IBAQBL5cTjpHCWMwkWTeogYVLdVYyuUsPNyTJrGmx3Z9j0zBz4iEJoNJ92
+85zcB2deTuHIlFT+U3UZEk6ifJ8zUOE9TBC8Oyjl84EDOguoPgK0oQ3Jj/6b55Hl
+OS8A9CrB57Tn4slKocrF00uFdCiqmEjU1v+sbu6ABVBvAVd50qO2Tvy7kYu7H/eO
+M3hQPS5fo76cYJTtsn3ASFjtHZ2Zy06LRuE8YA4/h8h7Lvf26MfHeSJilhdibbmK
+C6qzmPhSKJTX4aFwhy4p/y5vNeSWy11eEjuCK8Szqhg/wfo+b5gtSlbUQLhXJAqQ
+24n2R4wWJ4Qic9ILAGdWLSa0uKAh3Vam
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 27 B3 78 2D BE B8 62 40 21 6A 96 79 23 0F 12 D1 10 89 05 8F
+ friendlyName: Invalid cRLIssuer Test35 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DDC5EBDD1E2194D9
+
+Eo+ohoIFCoEj7N81YA/LxKJRjP9pBtRPlbBr4NBi5s/aUb/xB9zcacJHmnKxhoda
+bJQsd18mTuoGW9LZaIEjt9bYyLXIK/4xfep8Cysn23AQJXzkLpY3x5g2aOVnX0B9
+Ou9LUtZvQWQdZlfceA9LeDZPYsAaf+UGw1H36KVIwPyChZ/G68MKnNUPkbNNM2y2
+ndft9/HmIYB5/KzXdx5BnHkvXG2eU/bVuzUSzfdtHra8IJEHcY0Ox6dymoVW+sSG
+6H5t2kUIp/z9z7gAv9JH4L0asVs2HYb5puWP7Lt/4iKuOTF839YeJ/7h2DkGv5Vv
+mGfJIyqUHZzpi+SIVj7X88Ab8DPs1j/7OHAWp7BYFdE1Owa7X5gtBW1sHJmPbTfq
+3moN3miZoti9hFj13N+S/+BR5GpRHott3QO/Y5SUq5CKfAZsFS8SPSBNDn7tZ7gF
+atS1dHQfWXG53L5qN0JUWMuNCae1IrWGF0ChbwWG3GkRnckhZWo+5Yi9MxX3NfjC
+EUWn0Csb9BjLap1JSXRzoQIhEYsephk1xlYm4z93Li+6+ixiPldxN4NSp4osdpFc
+JBsewhkYgyiYBhZ4hC/SorLeWNupjfSi7kI7VPgMWA3Xi9qTkLoxjh1kfTKAlf69
+x0HqjdByVof1/n29mke01yyq6Q0XZExDtj82ST7lNK43job76NNYqdH+eEWu31aD
+qUcGT1veiuE4oi5wpiO/RNyPZ9cknXNJUk8zgEEah3BLp137FYJ5LpRc886yXw9z
+TNbNhQMdEQLDmZgJwYYEoDTNB48Iu3cghH1PN9Pmf36RDZPkWvLt8+8UhabgwtIf
+Qlmgm9Ux7GML+E7Ijs3+2XiIXx8VaNHJF969pWOkzJV3v/Y/lpbYnb/cJ149k178
+kfCKZNDLXUm1Nm8I94/X4m75K1bLzUXDbCkMbLnAhsfy9kMHNKKAeVzJ7jcdw4av
+h0RsWUy6c39xtxlm8ZvnDW/3xZ0HXRT00jxmqSb36J1gtSrsK7rcFf5XyCoqjH1n
+uwgXN13VpMelQTg6FV6OsnJZHnHdIEcOQ5+H8VQwizJz/D0C1IgD/YsxMRlZYzPG
+3hwNy2XbCTWh0oK0ddEGeFotuLDKpthaLb0euW4UHv5hPoNoMb7r0lpbt57tzjV9
+qQJXf8unpPNLPtS2lbHKGiy6eAPQiy+LFK6tLT8bWDM9/mcGid+N5jM6WI8yXjNo
+391XgOpIFK385rEslj/yNbn2aRfBjtPJzAe8QSnv2+t6zDUBW1CTSEUvWa5aVkp3
+Gq/1hwGKRE0WUmAEWQYOn8wrhUKnBtWgFvpOWeNcT0wtDxD188W4rLCYJ6WSMAMv
+0Jta6Lirm4DlW3MAMW6ZJ3Tc6NtKGEoZKU91g/DIE2g7rFlESTeSNirLjIYjXnJb
+PlurzxN7Sj9Ssy46V0RLmFJrVQIwnwp3IjLr2NAKMs2pq4onpACGUagmDU3H4cr4
+2AOUT/aR+IEHREeO+6r33vzcvFq7zp78rcubRk2/ftw14IZmyO9HFwUQBHLaFS4C
+4JlJtknLnOlPoygMe3gCeQCWfi8r+Q3OimxRwuUiO3y9WOVYVjBTmQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1.pem
deleted file mode 100644
index 3cafe6afb8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRLIndicator No Base CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBWjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcZGVsdGFDUkxJ
-bmRpY2F0b3IgTm8gQmFzZSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-oG4BhBi9qCt4Gbrc/LcngtoFA7DzmY22GBOLt1eBY0FyQGpf4K9UJ/LOfsnV+Q1z
-VMrQi85AV2IqI6mgtxHLyw698P62RlAXRHWMHyj7K/bgc9YjZXUrY7Dy/rAbHaww
-JVlnlNsli3eVdnIPzuxxJ4qRhRgxixJng9IvLPDQaSUCAwEAAaN8MHowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFIvW/54p6SweUNEj
-eV1lB9tgcPTTMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQARpTTRRjgFmYIu
-Mnx53B9cpWlZhaDRm9P+XdLuN3Tc4rdqxW3PccPPBB02TbfuXKXNGOQZpKhhF2BR
-oulfvRUkwEfeB7DHQNuEGVct08IknDXryj2KFLPQgWdprgO0hOgZxF1SPuUOh1q7
-iSvok8TmmeNswbnOq7EszJMT6EmnUA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid deltaCRLIndicator No Base EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=deltaCRLIndicator No Base CA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGRlbHRhQ1JMSW5k
-aWNhdG9yIE5vIEJhc2UgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBqMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPzA9
-BgNVBAMTNkludmFsaWQgZGVsdGFDUkxJbmRpY2F0b3IgTm8gQmFzZSBFRSBDZXJ0
-aWZpY2F0ZSBUZXN0MTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvGpcW2w
-QEDfvwR7XCYsQkH0qjyrTAjaWC37qTDFXdVea7SsRiN2tW0REkGLtoF/BGWwq3/K
-KNS47aRTkHkYyNJIlv+1vRXEYxlHI0k6HGfH+50i/40w6T3EzV7RUhcGUGQzP2bT
-K9Bpc6fHT2sjEgqChhY1By2i/j1sQcIt9TMCAwEAAaNrMGkwHwYDVR0jBBgwFoAU
-i9b/ninpLB5Q0SN5XWUH22Bw9NMwHQYDVR0OBBYEFGc/qnf9bJRTuHQc0l5B5FN/
-kKYbMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJ
-KoZIhvcNAQEFBQADgYEADuC/4FucvKYngf2DKlHL2CRM7Io+GiuRab4hlwCc+ma1
-VPQC6R+vlIABlQvMPmw4WG+SuFUDZNUssb8KPHQZdrvlnFHPjim3wRzYsdvAPIJt
-5zncVjkebsrXuA///nNffcUlemq0f871Une/4Vtxe1VBbGzCZ7s8DxQumEH4B6E=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRLIndicator No Base CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:D6:FF:9E:29:E9:2C:1E:50:D1:23:79:5D:65:07:DB:60:70:F4:D3
-
- X509v3 CRL Number:
- 1
- X509v3 Delta CRL Indicator: critical
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 73:84:e0:d0:5d:12:bb:90:a4:b0:49:2d:9c:98:2f:c5:8f:39:
- aa:08:09:8d:4a:14:7f:5b:59:00:a0:4d:f2:b6:47:88:33:fb:
- a8:51:d9:b1:44:71:66:7d:48:c4:02:fe:ee:fd:2b:ab:80:0d:
- 07:ad:41:d6:51:cb:86:03:c8:8e:99:0a:6e:b3:65:72:65:58:
- 3b:f1:b9:af:cc:75:ab:ac:7c:59:18:32:59:8e:ca:d9:cd:50:
- f2:f9:03:d6:4e:41:13:5e:62:2a:e2:3a:98:12:d8:ff:08:cb:
- 14:6e:1d:69:4d:d6:19:74:cf:b5:2d:c7:2d:3c:60:a6:30:95:
- 34:4c
------BEGIN X509 CRL-----
-MIIBWDCBwgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGRlbHRhQ1JMSW5kaWNhdG9y
-IE5vIEJhc2UgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgPjA8MB8G
-A1UdIwQYMBaAFIvW/54p6SweUNEjeV1lB9tgcPTTMAoGA1UdFAQDAgEBMA0GA1Ud
-GwEB/wQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAHOE4NBdEruQpLBJLZyYL8WPOaoI
-CY1KFH9bWQCgTfK2R4gz+6hR2bFEcWZ9SMQC/u79K6uADQetQdZRy4YDyI6ZCm6z
-ZXJlWDvxua/MdausfFkYMlmOytnNUPL5A9ZOQRNeYiriOpgS2P8IyxRuHWlN1hl0
-z7Utxy08YKYwlTRM
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1EE.pem
new file mode 100644
index 0000000000..cf4a0188f3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLIndicatorNoBaseTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 14 51 E3 D7 23 38 AF 15 1A E2 D6 76 9A 9B 1A EE 53 65 D3 16
+ friendlyName: Invalid deltaCRLIndicator No Base Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid deltaCRLIndicator No Base EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRLIndicator No Base CA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcZGVsdGFD
+UkxJbmRpY2F0b3IgTm8gQmFzZSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMG8xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMT8wPQYDVQQDEzZJbnZhbGlkIGRlbHRhQ1JMSW5kaWNhdG9yIE5vIEJh
+c2UgRUUgQ2VydGlmaWNhdGUgVGVzdDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCbhw2QqOjic0nMo+o+00dV/CeqcpriB+Ybd37dJoPpNPan0fliKh7L
+gC5qlfRMl1/G4aiY9/rn4c6IZKHKvZvtqxWeWdk9rfkZrzd5jdchg3X9js3W+Pew
+os3xdg0s5C6LAxUpdZKXUfnp+rgXJP+5DBJbp0zT0E+E2+wFCEFmCwvBXsdC4wS5
+V37eh0xM3D+AmmRpmZU1sNwE6CHCXS/FxAT6M0l2uOrrsAasOAlYyKomNrwuI4JX
+F3o2iOP2FmcUdfbipILts/m/i9IXBbD7Y6CHpxaxwO5C5M2QGmbrzpWRwnH2X5si
+lC9xrwWMDkDICl4iWZM0EpD/fvylKDXnAgMBAAGjazBpMB8GA1UdIwQYMBaAFPQ4
+diWrpOMcwMh1jI0Ta2MjtoqBMB0GA1UdDgQWBBReXpncoHSAGA199holyuOyoazn
+5DAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqG
+SIb3DQEBCwUAA4IBAQBJ/eVvOyfvPW6TIbZC836c9ReK6HHWGskd3H5FmhJpOGRD
+yqKrWC44Zg9TaEcnMUZdvGT70DPTKaHVte9hOzQHWlXPDZlpIPQie2luL4i/6hsY
+r4kGcK3jbPw/rexK0R8K6s0ZE+CpP5VQnRbRzCxdQiWny1m/PACa9zhklI/wEovL
+ha+CdOwDNBNDQzA1dsz8IqRAyIRiHJ1W/n71rkK72xCphrl0EcIZRk+aIkDNrO6j
+EHYzDFuGiknsLCZ9nrxUbdx16eeTaqG8wEkiZP/f8hERqB4TqNw+J0d2m4IVdo/B
++ZbHSIBkCA4aE92Z+PM4gibKanjLggGYrkPMshkJ
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 14 51 E3 D7 23 38 AF 15 1A E2 D6 76 9A 9B 1A EE 53 65 D3 16
+ friendlyName: Invalid deltaCRLIndicator No Base Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3AF61BEF1EAC1D72
+
+dWuz0jfIsicCkLiRuz0wUgfo5h7OVwLWI3sJEz8MJV5O9BEiF5t4ixGeIboEHbap
+4IBUKJ6MTWmtY9tmfXvKSWxM+BkyZXeAj0SzqTfNiPPOfG9wJqBgWKjVKQCnN1CV
+jM+A5IXthf/4Frbgbqccrzzd2fLOhJICaVOrcrTh//1ryATG2rUnMYMVbbLlxeHz
+8vWsJQZRNElgPl3BHeBRL6/K4qrP8UWQo/uivNmpVRY1OmzNtpFfOIt2jC5m7Hni
+6iVyta8GNn+633oxjn/Ji19JIX/yTjY7G4MoQY2MnQyML2mS9GUVllIiQqwN6tMn
+4Xk5CbxKKXx3Mqv6WN01o0oObRahhXx3GDHi8i0rWXFi+L6vz2fRPxInX4b0USIS
+oZvBS6JXJnYGctRp8akBajUEd9zb+cdP06J6YHlEV2ZzHVjulYPW10tgyLkJHesF
+n8bbfeUkaokt4yThN8cRiLqwj6r8/sLeo7DEguHkV/S7XKo5G5+AKT8TMg9qjEku
+pRmMnITqgtwQlNm/04g7woWLod7SdmOASsOhi1zko86MOLUKkCUSFa4ABOszpx3y
+oQEbnSHPI9Zaj93XLikF/RwS9pGdj3UHqbcuEvAowWlttt85JmD7VQR6JH7Q3dw5
+ISIdQJZVIVH3/IFCxe0tpw3Otqlee42m+OLq6DQOxrHJDyeHds0PTz9revgV2YTv
+4TGgxZSJMf+eRjNhxXwEB2+a3op/jWLv/kcV7ZN5tO8YbiaU/4v2DzLZu/rqRFz5
+HiMSVUc6wRVUm+EFasFBut/Hria/SDta4ayL+OUDXJ0G3NewngH7OG8H65v2jKbQ
+3hm3iaQgnm4YMwcRyOiF4qt6wPaR+uZXJcaflPfvR/nBnoN6L93dy4hpRuI0KIDW
+Wq7/KpVnBqEVJST2sOq1wGskbSvr2ozse02lObk0xAtlBLDFCkaRZDPZnG0tJ0F/
+j5dLAYe9e0j8SBkmY7AnxQyC82u4silVdMYk4tF9uuc2SuOswD0BFcy6+pwvJ9US
+gP5LRnVR0cCm9sdmitmulkMME6RzRXeXtLrfcv+XWOgT9anL/on/qOJ2JfWkTWhj
+z0wgwe3iIPvLYixOj25V2IPH4jz00ma9aLS8byebwWBLUZ8nN+oib7wQL/I6iOD5
+ARMcTb7SsJyiz5wWtJOkCRSnZrm6IsdRc2apuKIdjCivN+sIZiSIpqg4xfgB3bl5
+X/w9DtXHc/gWDOopWvDTC5BCjF00pZhvBclypVu9xsnjqcrW2IVBrz21Rb7RY2UW
+y78+DzkrE2FhrpgIgCltOe+J38gF7ywC+LEjL0BzDwFtF+wHthH9nPiaq3qrhrfe
+X2ynSuD8Y1D+2ygbO6gLZZvZBe8kY09h2F1qpcnezXwWYxnHThGsllzo8sh+yFTY
+xL0eU7ID/H7oVJaRrF3n6Y2r6OCu9lbjmrvJsvJ5T/RoY4IkxOFQ8gh0mxrHH5Fq
+kavoB/OjUGTgVTyjDslAKnbdUXI88SwyjOczbiX919PISbrnGsvsdU8O4eTbfK2K
+PfNniDgCGDc/aWRyfs/a+RjKG4lUmd7gGIjriXg+etZbbNG8/xbDzg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10.pem
deleted file mode 100644
index 4ca36378b2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10.pem
+++ /dev/null
@@ -1,150 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA3
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBXTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0EzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyjb9j3IekGOkHy1SMKbO2
-cxwOgq+Yl8JiAoQJk+wbolHouwKi3RFA75+gpgOiN0SeLz08puksttu+6NNeBmlI
-VBHm6vN402CMD2mE5JN9ze88PmgzLW/NusnlGNUoYksZn6JLwIyAMqCq9ftTWh/d
-Dy0s9MipYeAfErZCKqRoewIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQU4hgGT7/eQNb/M10iVoncEPfOcL0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJ3F2hdP5d9HdGajPqfdokQc5GBFeZOqwu0M
-3NB8RwFrC1PmrnRvCZETjCk9bMAlDIYde7XTym3nNwdl2xrMWn6xBBnBtVBU1uAo
-96PxqkGgbm/uFUgMLUlww+CwMtAWfpZylChZNNxZSK40iS4jOlN5JajF1iLB+CTG
-rC1IKMyc
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid deltaCRL EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA3
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MzAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEvMC0GA1UEAxMmSW52YWxpZCBk
-ZWx0YUNSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTAwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAPg+ULgLYvxSkvSwcxwt2gPwS+Snwayze8EhWojhINAcpYlb8sPh
-4OaEgcnDvdOrOUGPIB2D/KOYrKEAqlRmM5zx12ZvpLevcV81RvNfe4FTRCqAqwhK
-Vs+5ktfrGpJxjBVWC0Lds9VitDFQpVoA8ksVekcaTe2bHsI0Ovr0DJiXAgMBAAGj
-ggEXMIIBEzAfBgNVHSMEGDAWgBTiGAZPv95A1v8zXSJWidwQ985wvTAdBgNVHQ4E
-FgQU10CyKhocLN3j/y/kw/ue6MjvEF8wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATBTBgNVHR8ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNS
-TCBDQTMwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYTAlVTMRowGAYDVQQK
-ExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwgQ0EzMA0GCSqG
-SIb3DQEBBQUAA4GBAAUoNQS5AyzkN32ziPcC+VbKBJACILROlR93/RKUabl710wa
-BNk1iOD+MQ9iUwOLXI/bAo5bqQP43gvVFETGio6KpzbsDfofpXMbliYNRyX6NYqy
-38eEMeX/Tu2GvtAwIWPlW2rdCrAl0KS57hwRtpXvyikNxUHoYGmtREmOdFN+
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA3
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E2:18:06:4F:BF:DE:40:D6:FF:33:5D:22:56:89:DC:10:F7:CE:70:BD
-
- X509v3 CRL Number:
- 3
- X509v3 Delta CRL Indicator: critical
- 2
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 14:8e:0d:04:69:d0:fb:fc:c1:e0:51:af:b2:9c:b1:0e:d6:8d:
- da:4a:f1:94:a2:23:3e:6f:c9:9c:4d:d6:b0:03:6e:ae:c7:23:
- fc:6c:69:3e:66:ee:12:fa:2d:b4:12:08:76:16:e7:45:7c:6b:
- 7c:b5:ca:dd:f3:67:81:c7:78:d0:0a:54:52:05:0e:a9:8e:36:
- 5c:3e:9b:b7:b5:f1:18:a9:04:61:5a:95:4c:3f:a9:d2:76:c3:
- 71:dd:2a:9a:78:27:4d:3e:e8:02:93:40:21:42:14:02:a8:0d:
- 86:f4:27:53:8c:3c:07:ab:d4:70:29:2e:42:6b:db:5a:2d:06:
- 54:e9
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENBMxcNMDMw
-MTAxMTIwMDAwWhcNMTEwNDE5MTQ1NzIwWqA+MDwwHwYDVR0jBBgwFoAU4hgGT7/e
-QNb/M10iVoncEPfOcL0wCgYDVR0UBAMCAQMwDQYDVR0bAQH/BAMCAQIwDQYJKoZI
-hvcNAQEFBQADgYEAFI4NBGnQ+/zB4FGvspyxDtaN2krxlKIjPm/JnE3WsANurscj
-/GxpPmbuEvottBIIdhbnRXxrfLXK3fNngcd40ApUUgUOqY42XD6bt7XxGKkEYVqV
-TD+p0nbDcd0qmngnTT7oApNAIUIUAqgNhvQnU4w8B6vUcCkuQmvbWi0GVOk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Jan 1 12:00:00 2003 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E2:18:06:4F:BF:DE:40:D6:FF:33:5D:22:56:89:DC:10:F7:CE:70:BD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA3
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 87:f9:64:9d:19:1d:03:e9:68:e0:a8:3b:2a:8a:f2:74:a3:26:
- 8a:2b:00:7e:6c:b3:4f:ae:70:d1:e3:ad:39:b5:ba:70:25:34:
- 31:9b:12:06:6e:b2:59:f0:a8:56:24:67:c9:fc:76:54:74:4f:
- 28:14:6c:7d:51:20:d7:8f:52:69:12:e1:67:2b:3a:d1:70:03:
- d6:8a:e5:c5:92:1e:61:29:9d:e5:55:c6:54:bb:8a:a9:b4:b7:
- f6:3b:ee:b1:63:90:a3:39:2c:29:b0:f3:2e:00:1c:f4:dd:76:
- 46:40:31:0c:7e:29:ab:fb:35:ae:a8:73:8e:ca:a1:23:1c:12:
- 8e:50
------BEGIN X509 CRL-----
-MIIBkDCB+gIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENBMxcNMDEw
-NDE5MTQ1NzIwWhcNMDMwMTAxMTIwMDAwWqCBhTCBgjAfBgNVHSMEGDAWgBTiGAZP
-v95A1v8zXSJWidwQ985wvTAKBgNVHRQEAwIBATBTBgNVHS4ETDBKMEigRqBEpEIw
-QDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYD
-VQQDEwxkZWx0YUNSTCBDQTMwDQYJKoZIhvcNAQEFBQADgYEAh/lknRkdA+lo4Kg7
-KorydKMmiisAfmyzT65w0eOtObW6cCU0MZsSBm6yWfCoViRnyfx2VHRPKBRsfVEg
-149SaRLhZys60XAD1orlxZIeYSmd5VXGVLuKqbS39jvusWOQozksKbDzLgAc9N12
-RkAxDH4pq/s1rqhzjsqhIxwSjlA=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10EE.pem
new file mode 100644
index 0000000000..1b705fb0e3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest10EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 68 FE 2C E6 EB F7 D1 DC 72 5F E6 EF 20 5A 31 AD 25 7D 30 FD
+ friendlyName: Invalid deltaCRL Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid deltaCRL EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA3
+-----BEGIN CERTIFICATE-----
+MIIEQjCCAyqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0EzMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLzAtBgNVBAMT
+JkludmFsaWQgZGVsdGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDEwMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvANALh142nlDnxUbBVwMZf4H8TGU6+cn
+B3S/k65XoHWSCIQaHJm8ViPDebtC2Y1lxXJAuUQ5vrXhMNViCXvsXVv3Fyqh0v8Q
+xWCcW3Mx8f1uIBa4iWs+GyD2978gvyy4wOLeAYAESUYG0XStMq2JvmLqAugT21T0
+0CrRVBXBcG4tsbxJFoCMFN/UrS87ampiKLDfUrer1kKOpTIYVZJ/tLqy/MIyTzsl
+cll6n2Qs6BH77TijvQ+SzRja+f3jbrUHUZuHSoJ1VF9hsyKO6jnVwIqzIMXOox5G
+n4jqfRmMVf77zPZF87XJ2lqgDoqmiEzxth/B94GOqxavMadaVT+czwIDAQABo4IB
+ITCCAR0wHwYDVR0jBBgwFoAU72PTqE6x+d9h4g3DBaOYGNKTmecwHQYDVR0OBBYE
+FBLdWepYnXF0v83nAlTQiBuan5S7MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwWAYDVR0fBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0
+YUNSTCBDQTMwWAYDVR0uBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNSTCBD
+QTMwDQYJKoZIhvcNAQELBQADggEBAKpHl7P1CWrLLGUFP6PuAz4hr9Y0OyCV2JLt
+sravF+p4eArmXPaAVzZz6/lYajw2i+b4eVQxm3qds6WoxgIIKSGyHPEBU2kz/93B
+kHP87Lwwk5yPG7XdX18t0dJ7AQhbPhyACkUbpwsZrN0tNCUby0S6iHUgCDBPU5MW
+duSUqgptZCka9niVz6eVtTbY5796ayHh36+MWGzodBQByJQqNum3/Wxhftbj04Ng
+wlL2MfEcDnE3swKRRE4uxe/GEdaaUmSzbFsQX+fokCrHO6udaaoMLpKIa/HZpb4f
+xvCy+cimsD/LjJ8hIo1A0sgGbeM4oybqfLkQ3ELSljF9R8+svdY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 68 FE 2C E6 EB F7 D1 DC 72 5F E6 EF 20 5A 31 AD 25 7D 30 FD
+ friendlyName: Invalid deltaCRL Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,AC1EB1F42BAD4578
+
+Cs8dov7sh8fRdw/5WuIE9nxqQvg/rjIq5qYQnxcyNZXsr7ktj1Y+JPybHvcku8Md
+8Wrg8u/C0vINm5f0/dyzdF5KwidTg3EI0x++5HQmvK+3agest+PldX+8Kvpr6EyL
+TZKqvsMqAYoAsSbC4jeMoFUGRF/7kzIar7mkY0yw+v155q9Ot3wvUwvcEqug720m
+4zJ6kGAZNIzQvoZjdf9bvQgaFXJ5gWuHCmKdOyb2Jd2rSzVdE7vgtF7Gi6ID3NUy
+kDek+PLQQFbTlUWdG8KaSqI9qEp3j1Cbuqc6CKtTLPcNWDZ1rHP39ag1ZFnP89uY
+9DX5Xekraq54c1CYozZ2PKtLSXmWqW8io+c4/LurIvMKjJR0gAuIUZtD1m813h8L
+w07izH6QKZjAJ0ALNa/SBkOKeSNSN9o+2u3cCh9KmFMYcebNXoCPeacdNSpRrl3F
+cWXwaGUP8JGn2HMYJOYE1KdQKmeiIAigrrKYgNilQtKzo43TVHkG0758gaEz3P8L
+fogsqPHDWIf+t9c0PSnE/g1ZsXOVTDQmkk+inW4RzAOW0i0leIRklA0WQLrdpPBI
+O509+0WsPsdN0dFtQa4GhmsskjGt5JTDgfi/5Yge8TgGmHEoeSZuz5M8HRpfjMr2
+BRn5WBkOUgwEHsP08fE7YyjEE7lpiBRtSqryPpezN1JfBUllbgHMQ2x3MMmKUyvN
+Q8wqH0bG3+ORSU/swn0xemObXf0Y/dzlCxlF2t6yd6m2HrE2oCkT2AW1eF2mVBZR
+zzQugVYSudBRHH6AvtohGdoIBE7tDQ7DqL7BQi1rbCtZ1THEpVTiSENxRUumP08K
+ElP1G5lb96GdZJepltrKJ9iXEbxMjHbYejZ3X309zmCOKymJvanAAhs7BleED1Yz
+0EdD3mAHVaycjnXn8SxC6/libT3jsU8sO/Hy5u1qxqwFHUlIJhxu7foV9KMMyVML
+sXo+H0kiflUg3iHKNFBI/UM07ml2Z+VVSbxTl3D0zxpJFRUaUD8JSdwZos+dqNhP
+qpig4z04eMzGTSTzaoQ6VHx3TvAIbyLFjGzynk1upk/lDVOsNR8mxklV8XkvPV2p
+onSQ9xzX9o44SMlp+KsBmPOBiJI9Vgzhz0EwspTHs0r4w9B9kg6sfPpAo7BsJWzb
+PNJgxyXyIsqW765VR0btgSJjA4g46GzhzrKo7irwtgZtXe2SjeglyIileefBbj+b
+OHI/0IS05TFR7l0MqpPZFhpLBY5NLwV2cCsZ+Fgq9rHq/o//XfEgNI4hlr0TvenU
+g+wiO1K4Hh+zlgTGor654HFoUepehXjOEvhBAuj6+6weusjXGg1PEpNWZQ2qcrqV
+EfT4bYpf3AsLYt3AXRu4HUM7JyRX7VCgNZ8onBVosG36rdv2Dw53vqKDTnD5ISPB
+MeiKYjKJAFK8090u+T4H4qZKfwa/wa81rqQ4Ussfio3J6nkMqUDBr95wVmcvD6Or
+KSQQDqXdtwP8fNWvqKO/QOapGfzVVWRtvdciipuicjYWdXZudKAuBd8x5xrrg8yx
+ClR34LtK8hg87MIMfT0ppXUe2TanG34+86GGHeq81lKlpTiqN7jX/A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3.pem
deleted file mode 100644
index b76c876c1e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3.pem
+++ /dev/null
@@ -1,190 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBWzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWAdMOZhkDHEp9KBGE+XuF
-msopQ2J+rJDtUrJ4pDANd3KgvUwmAZnDOopO+3hIw/w6tsB48EJwMCiofofFALAT
-zbGJidQOgpLF2if/SwmyWzUKqB8XirB9z5z0NLfE/0nnUhVQnAJ54W1jOz/+wMfg
-7oWdQC0ZAd1ndBLf+mtqHwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUk49NvPIc1wyuIEisujIaDdfoDc0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJhiiwAX8BQouosN8thaL0+ZHNhiuQ2gr8Mi
-xgaJCB4DVxE5teLk0eeWz+KVJBQwDdrlK4l0BO595r8cldkYkKJkJl+ZGPbNSDys
-XuVwXGbgfcUNPCeD1UIErQASVfomr3io69Nc62HwaBpTgARQO0wvfnIOFNAQSZH9
-247eEnnm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid deltaCRL EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA1
------BEGIN CERTIFICATE-----
-MIIDKDCCApGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlSW52YWxpZCBk
-ZWx0YUNSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAzxx97S8BoEgN9xfoNoA/Llxt6uPlOWZ+ivv604fkNJjK8fwEFgGh
-IX2rOp0JvgxD9GNhW03cAb99VuVWaKCGZetc3qdUF2xWlxxXgYBV1Js2xsyjmGbR
-pqAvaRtcrtlqE6hmltSJmkP92c49XhgCOIkV/KNyODYzPpFNe5RyZ/MCAwEAAaOC
-ARcwggETMB8GA1UdIwQYMBaAFJOPTbzyHNcMriBIrLoyGg3X6A3NMB0GA1UdDgQW
-BBSxLLxeL6rboh2Wk+01TTFMKEr2LTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMFMGA1UdHwRMMEowSKBGoESkQjBAMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JM
-IENBMTBTBgNVHS4ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZI
-hvcNAQEFBQADgYEAjeR/ZFSYPKsGsR0G5k/dJwEp8GMQM/lG8s5DOWP1JbD8Ebl6
-aao3oD0FCF9jzK+rtRkL1GVRXX48sLANOStAEInSVm06g7LocOuGGb7NRggCbLRY
-rMCjHVqCHM8aJLARHyGGvUlhNfuzWxTNX4Ru6LnhGQmXqvWcGlY4dVv4vUg=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 2
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Signature Algorithm: sha1WithRSAEncryption
- 63:e6:6b:e9:cf:44:29:c8:8b:e5:8c:ba:ab:26:57:a5:4f:a8:
- b6:e3:81:35:ff:73:8b:40:e0:79:7a:d7:69:8a:c5:a3:d9:85:
- 29:ff:ef:e4:7a:4b:f5:36:51:34:79:9a:85:01:cb:ac:03:48:
- 9e:2d:b7:b6:9e:82:57:b1:0a:b7:49:06:a8:cb:c3:71:2c:71:
- 58:7d:e1:68:22:6a:11:3d:e6:ac:2a:58:d8:1d:97:3b:46:98:
- d0:f5:f2:85:85:7f:b5:c7:57:a4:0e:e4:fc:c8:cd:7e:b0:2c:
- 1d:2d:86:30:1b:06:70:36:33:e0:69:47:60:98:5b:f5:93:35:
- 90:7a
------BEGIN X509 CRL-----
-MIIB1DCCAT0CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAz
-MDEwMTEyMDAwMFoXDTExMDQxOTE0NTcyMFowgYgwIAIBAxcNMDEwNDE5MTQ1NzIw
-WjAMMAoGA1UdFQQDCgEBMCACAQQXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoB
-CDAgAgEFFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEIoD4wPDAfBgNVHSMEGDAWgBSTj0288hzXDK4g
-SKy6MhoN1+gNzTAKBgNVHRQEAwIBAjANBgNVHRsBAf8EAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBj5mvpz0QpyIvljLqrJlelT6i244E1/3OLQOB5etdpisWj2YUp/+/k
-ekv1NlE0eZqFAcusA0ieLbe2noJXsQq3SQaoy8NxLHFYfeFoImoRPeasKljYHZc7
-RpjQ9fKFhX+1x1ekDuT8yM1+sCwdLYYwGwZwNjPgaUdgmFv1kzWQeg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 48:32:1b:da:3a:c2:71:37:ea:24:5a:90:2f:19:b8:9e:00:96:
- b3:e1:2a:6d:ed:b5:7b:eb:90:30:ac:87:c0:8a:6d:ca:24:f4:
- 73:dd:bd:b7:f8:cc:55:31:f3:d9:e2:a2:5c:7c:51:60:6d:a0:
- db:43:12:52:9c:94:fa:10:86:32:e6:a6:7e:ce:e6:c1:00:2e:
- fe:33:22:b3:5f:66:e9:d3:03:de:05:c4:94:bd:09:2b:1d:2e:
- 06:86:e8:26:f5:f4:38:39:62:7e:e8:0e:bb:cd:c8:bb:82:92:
- 71:96:8a:01:73:d7:ef:fa:a5:c2:94:53:e9:2c:34:a7:50:7d:
- eb:4e
------BEGIN X509 CRL-----
-MIIB+TCCAWICAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwIAIBBBcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEG
-MCACAQUXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBBqCBhTCBgjAfBgNVHSME
-GDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAKBgNVHRQEAwIBATBTBgNVHS4ETDBK
-MEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEASDIb
-2jrCcTfqJFqQLxm4ngCWs+Eqbe21e+uQMKyHwIptyiT0c929t/jMVTHz2eKiXHxR
-YG2g20MSUpyU+hCGMuamfs7mwQAu/jMis19m6dMD3gXElL0JKx0uBoboJvX0ODli
-fugOu83Iu4KScZaKAXPX7/qlwpRT6Sw0p1B9604=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3EE.pem
new file mode 100644
index 0000000000..3f2d5cfb17
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest3EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: DF 2B AC 36 40 9C 8E 17 CD FB D5 7A 6B 23 8D A1 F0 05 94 5A
+ friendlyName: Invalid deltaCRL Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid deltaCRL EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIEQTCCAymgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JUludmFsaWQgZGVsdGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDMwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0thD2uHKXQil6QX9ihT20V55pfCU176xg
+xfE4bF/rUqIJr1QtBB3go+0Haquuzo9Nnm13khuoWMyaSmjdzvSCT3w0GW3ynnU3
+yYJ/p7fJZ3jlVWPkvMn3Meba6o2+txfsws25NSzmKdImawaPbWTeBPuzOGXNY0Lq
+ApdYfUd+Qq2jf+RWWMYQExBlgXwP2k5PgtmVqsKcbNKTC6rUP1L5McjM2ZFi5h9W
+HsHgOObOsGKYKIiVX+7pEQQkdNTSbPmiuS3f668FY9CCXwCGtyfrFt1OeL1ZTnDx
+/yjc0LppdCQv0EMuj0CORDhUjk8Uocu6GkieECZXF1s127oZ3+arAgMBAAGjggEh
+MIIBHTAfBgNVHSMEGDAWgBR3GCPldoTIFJQ/gtCB6nSx4KQvMzAdBgNVHQ4EFgQU
+psHlOGWlxb4PmdbGfVntoeCyBNgwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATBYBgNVHR8EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRh
+Q1JMIENBMTBYBgNVHS4EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MTANBgkqhkiG9w0BAQsFAAOCAQEAYHmgNuF1unFbwYcC0qsNM9gWmk3vbXFecTPL
+0EPYmRqi9MUgxFQGrNN89TJiCMiTqnUVHJy2jq16crGIQQPTknd+h1UehoyQ27qA
+yxHJK3dJK76vaWAU7+MJU2cWAxZ5eRD5kvpfjTvIWjEvCt3HJUAlkXnbn4GNkKAx
+XMkk3jQ/7xzHrSYEBLfuFrw6Kyphs4AACCY/b8AUONImu3BBAF3jKHr6CubpiuEF
+fOAUDfJdtxf71i7dUVPARF8Yo9IZdRW9OXXXjlWsXwKsCdiutyjaXXdyeHIFK59T
+IYDaSBblRRwTeVYrW2O04AQgyeSIj6L5M+OjsffPMNSc0+ib+g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DF 2B AC 36 40 9C 8E 17 CD FB D5 7A 6B 23 8D A1 F0 05 94 5A
+ friendlyName: Invalid deltaCRL Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3432D17D5C1A80E7
+
+9MtYHI+46l3XbWivigwkEoOJorfDpDN0SfjSL6zaWqT7sC2Q6wV4IY+l709oc/o9
+Yj0NanvgWxEVpFFw4mwQ8UkQcuIeZS4uh8+5w0QeYZa4vbX/SdpOX0rD9oNocmTl
+kVpLc2TTDNk9ve9S9FZp8XtgUtutXk5xal7WIj2CNooJm2FnT3S9C343nPajCchU
+ElCaxJk/tOijvvnk/AkucWgjdxi8eU89zC18ffvzPSnx2X7wJu8BoHtLiewm3mNI
+AY+FK3R+Cd2xrfISlQVVznJ5Ydg3iZFTLKwPzWVKBYpGNvskKSHZDHmvkqYFiKZW
+xqFyLpDVCAjtGwIGYpQVg0EPuWnhHlm1X5cd7/XJFt3XaXuvrAqixgZAa9PpN/sj
+CwvOvsjlUsvPFJtpnSykQ66pa5Q3Dxt/OxYqkF7/PRWO1+0RU5/ilV6+aG8Mt7JI
+PDnG8pGVHs+ItOwjUcJl8W3gxGJy1MWX3mC+jNKcNYbp6pY6XFO2zOriGgHJCgLU
+hxX+GmVwmkxxC4grURsRBqbY+eE66qaMkTlcdXL3POsyi7CQ4pBBTM1RXHm8I6hx
+HP6SyWePXcR7ayd/zxIH8RT7hkFV9CCty0Adg2P4WKPgyBubZp4NzrqYoYM6WsT/
+ala1iUpwayas2S/5Mqwo9bwXBUVgLQA5zKz/epAX+d/SIg+7LJeeaZ3N5YOL8XNM
+HbxgjHvcA4MHhZTO4uPiT6nG2Q5G8/y1FYr9nneJc/mIP0M/90ecGVLcSoMfrgPD
+74oLyB05QPZA5jpT+kCqHhHfPNF6yiMinMCw0JiXNbC2If4GckIalUmVUysiIyNk
+7XQ8/zPWqIppefMBRCuxdlr5IPhyLXet/qSD2MSOZUB6dtG29BycOwI144xvcXDO
+erJQSBdoRVLzH8Lwwq7lM1M7Vt1e3TW3Dw68LOx7eNs+A9hx7kexFB3LnGjIwSGP
+wOAqWMLY4RMpg3hN/CHl9TViI1P6WxJIj/Zcc8IkCM8x47bb+eTyscj/fW/9YDiu
+1eyvNajjFXJ7BT4FB+VknysFB7GLIcs8uImTM8adtmQC8X5p1PtCg0yuICgeHnQV
+UrzjVPY74QnI8UcWgnfiyeJ2r8rl38ldwjSQSL8Sp3/72C15iB/NoZF1NmANQobg
+ZvwZVpgPhB8+z/iQgtBKCKsfaqZ3tat0P9PqwljoXI1o1tCRdd+rmed/qbEfwD5Q
+m3M59rRPgkMvgxWerdBzU9QpjC38+wInuIJBhLG5ESmTM5ILQWcGbthdHpteOIlv
+iyp3/aEB+5eAI3ZR41vmaVhCrhySLMCE1wHW3YJlR2gbbK78lluPVy0IbsJUW32C
+wDU8RMQnW7Vihc6p2uyjd+jMmllXzu18EyVJ0wFE04ukeGY3MhU54396LLZSgkra
+CR4xaFEq3RywIjZ40Xdxv3pYkuaG5JVcAf9fs0OLUvX4u5M8M8ArRC8GlflVPwCo
+6tiRJg5H/jE+s51iLeQp0r8Q9m+Vd1rKIoMYSUB+SGqd+68aT+wQFHIFcOqELKhg
+ZP3LRnJHvxutJNVykZhRi6wdjcBZ9PorVS70Wcs1ATd4o4wRqfvcUA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4.pem
deleted file mode 100644
index a23bf8d464..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4.pem
+++ /dev/null
@@ -1,190 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBWzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWAdMOZhkDHEp9KBGE+XuF
-msopQ2J+rJDtUrJ4pDANd3KgvUwmAZnDOopO+3hIw/w6tsB48EJwMCiofofFALAT
-zbGJidQOgpLF2if/SwmyWzUKqB8XirB9z5z0NLfE/0nnUhVQnAJ54W1jOz/+wMfg
-7oWdQC0ZAd1ndBLf+mtqHwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUk49NvPIc1wyuIEisujIaDdfoDc0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJhiiwAX8BQouosN8thaL0+ZHNhiuQ2gr8Mi
-xgaJCB4DVxE5teLk0eeWz+KVJBQwDdrlK4l0BO595r8cldkYkKJkJl+ZGPbNSDys
-XuVwXGbgfcUNPCeD1UIErQASVfomr3io69Nc62HwaBpTgARQO0wvfnIOFNAQSZH9
-247eEnnm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid deltaCRL EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA1
------BEGIN CERTIFICATE-----
-MIIDKDCCApGgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlSW52YWxpZCBk
-ZWx0YUNSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEApl35weU2/WxOlBNEikRZQw51mRQgwiHdME99VsoaDgFPYglJARYk
-IQDYMoImgMANlcfHOiVaOAyXU4lXuGmpw8z64BNhazbSkSEl5lHedJaTrG3pwst8
-RIaAAvQbxOYAqrZyDz+9InoAj7ci9+TPhthUrmjkHxs7x/Bmkbmj9pcCAwEAAaOC
-ARcwggETMB8GA1UdIwQYMBaAFJOPTbzyHNcMriBIrLoyGg3X6A3NMB0GA1UdDgQW
-BBSZxHSKiyXXvxkmVXDhDuryYei0YTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMFMGA1UdHwRMMEowSKBGoESkQjBAMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JM
-IENBMTBTBgNVHS4ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZI
-hvcNAQEFBQADgYEAVQbnMvz/UBEqrjWC/M/CNgiN/9NfiIj2+eYySOYG+HoJrVWC
-qCDdYeXfKIHh8CtoS6s+S+xaYpEschIVX3kOjn/VMGOmvAtWlR3iy0nvVoRUoGDa
-4eBv1NPq2MlQn5L7WsYHJFnJrLx+z9lWgfFYNKPiDY60dVmNPSfFzQpevu8=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 2
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Signature Algorithm: sha1WithRSAEncryption
- 63:e6:6b:e9:cf:44:29:c8:8b:e5:8c:ba:ab:26:57:a5:4f:a8:
- b6:e3:81:35:ff:73:8b:40:e0:79:7a:d7:69:8a:c5:a3:d9:85:
- 29:ff:ef:e4:7a:4b:f5:36:51:34:79:9a:85:01:cb:ac:03:48:
- 9e:2d:b7:b6:9e:82:57:b1:0a:b7:49:06:a8:cb:c3:71:2c:71:
- 58:7d:e1:68:22:6a:11:3d:e6:ac:2a:58:d8:1d:97:3b:46:98:
- d0:f5:f2:85:85:7f:b5:c7:57:a4:0e:e4:fc:c8:cd:7e:b0:2c:
- 1d:2d:86:30:1b:06:70:36:33:e0:69:47:60:98:5b:f5:93:35:
- 90:7a
------BEGIN X509 CRL-----
-MIIB1DCCAT0CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAz
-MDEwMTEyMDAwMFoXDTExMDQxOTE0NTcyMFowgYgwIAIBAxcNMDEwNDE5MTQ1NzIw
-WjAMMAoGA1UdFQQDCgEBMCACAQQXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoB
-CDAgAgEFFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEIoD4wPDAfBgNVHSMEGDAWgBSTj0288hzXDK4g
-SKy6MhoN1+gNzTAKBgNVHRQEAwIBAjANBgNVHRsBAf8EAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBj5mvpz0QpyIvljLqrJlelT6i244E1/3OLQOB5etdpisWj2YUp/+/k
-ekv1NlE0eZqFAcusA0ieLbe2noJXsQq3SQaoy8NxLHFYfeFoImoRPeasKljYHZc7
-RpjQ9fKFhX+1x1ekDuT8yM1+sCwdLYYwGwZwNjPgaUdgmFv1kzWQeg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 48:32:1b:da:3a:c2:71:37:ea:24:5a:90:2f:19:b8:9e:00:96:
- b3:e1:2a:6d:ed:b5:7b:eb:90:30:ac:87:c0:8a:6d:ca:24:f4:
- 73:dd:bd:b7:f8:cc:55:31:f3:d9:e2:a2:5c:7c:51:60:6d:a0:
- db:43:12:52:9c:94:fa:10:86:32:e6:a6:7e:ce:e6:c1:00:2e:
- fe:33:22:b3:5f:66:e9:d3:03:de:05:c4:94:bd:09:2b:1d:2e:
- 06:86:e8:26:f5:f4:38:39:62:7e:e8:0e:bb:cd:c8:bb:82:92:
- 71:96:8a:01:73:d7:ef:fa:a5:c2:94:53:e9:2c:34:a7:50:7d:
- eb:4e
------BEGIN X509 CRL-----
-MIIB+TCCAWICAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwIAIBBBcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEG
-MCACAQUXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBBqCBhTCBgjAfBgNVHSME
-GDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAKBgNVHRQEAwIBATBTBgNVHS4ETDBK
-MEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEASDIb
-2jrCcTfqJFqQLxm4ngCWs+Eqbe21e+uQMKyHwIptyiT0c929t/jMVTHz2eKiXHxR
-YG2g20MSUpyU+hCGMuamfs7mwQAu/jMis19m6dMD3gXElL0JKx0uBoboJvX0ODli
-fugOu83Iu4KScZaKAXPX7/qlwpRT6Sw0p1B9604=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4EE.pem
new file mode 100644
index 0000000000..0be4778f49
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest4EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: AE 85 DF 8C 89 D8 AB 19 F7 29 2B C4 7B 9B 8D FA C7 F9 9B 92
+ friendlyName: Invalid deltaCRL Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid deltaCRL EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIEQTCCAymgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JUludmFsaWQgZGVsdGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZqiQixIeBTrVSToKowkdbwEHI0yH5H5QQ
+6K1sURO5gJwPnZhXO1S5cFaQo7WwKYfxbFMcEx/kPI3lmcUfm5tBVk11bAjgp5Ft
+Y0vW80Vz6ABCOjPtaF2lVItqBMFroDU7H2ZVjwuhunj5AzURHqMIR1N4N1a/L46/
+/nyR6uZRLe2FDH4XmymO/Yh/hqEgnyOwYIQWnm5oE8CLh90Z4sc1Xw/CanCvhaDc
+AM7VFiZH1r/0hx/ogQ7ZzhfZ7IY5OWK7c+ww+StDOiIOG/7kHChh09yoURji7a/Z
+c8Rx2BB05jTSzjI/RxoRNi22Iq3lCTX45PQub8KRTA8cRugPT/inAgMBAAGjggEh
+MIIBHTAfBgNVHSMEGDAWgBR3GCPldoTIFJQ/gtCB6nSx4KQvMzAdBgNVHQ4EFgQU
+yMWFM4r6w1i+BiUVek9gmjbgnAEwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATBYBgNVHR8EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRh
+Q1JMIENBMTBYBgNVHS4EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MTANBgkqhkiG9w0BAQsFAAOCAQEAWIZ2nB1hbPwnabw3PDZdYtB7oAg69uP4Bes1
+alM0Wr/mwFeWf8TVF/GuVt+5Ef1IK2hgbx6YpwDC6762CoHUCC0jsu2VtmSESITk
+tRTOMNLpzp5qbxg21Hs9q2dIJXBZyltzKqh95+kERpsanp8x2u++/0JZycKzvZZr
+0W557uKJSforuvrYXIk9+PtAdF/HqEhCI8UWufJsMNeGjn14SnnXy0id7leIBWfs
+5AuGkSR/AnlBQYcImdBJtlHbq6a7llTwZOuOrQvtIPkwdkKeFC3oxhKUU7Psn7Vw
+6bVE0zECH4cx86j3jEdXzQfA+93hFBL/9D7ngXheTNDftFKT/g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: AE 85 DF 8C 89 D8 AB 19 F7 29 2B C4 7B 9B 8D FA C7 F9 9B 92
+ friendlyName: Invalid deltaCRL Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7BB7D5713526F3DD
+
+XgiCoLDnlzYySBOR7RpxZ6PYgYBgtkfG5/1UuarivwaJ5AhS3quH1pNZM5FCG96u
+icSAGBAy02/mT2tWK53NsEhpS1iKR1577PgeBYAFt+3UEfSok8eUtyYdy5ubb3+P
+NGtwNVvr5oc67XcMtxKVeOccDb8vYUyrGfhxQA7aAxjEd3+5YPec5x3n/FjJvFy3
+VJIzF9OzE4jrJsyC/Wj11q/R4aTC2qKBu04B7U4N9+7HWvmT26zB/yismeDFJTWC
+Lng6xTaVW8C/HcRsGUH/rmaByYotIbptz03nomZINWRKoJhOjDL/H29UbnMak35v
+CUuilzP//VLW1IFJ0KlorqbfVu0NIHcI2yF925SFgGW4S5r4QlnTYwqi9umjg0XQ
+YySKHqA+pVt5cHM6w/8AITb+o/e27yClm/UmMr9x26DYkNLXaGJht4n3CL6sD+bq
+tw6F+ZYNzrvZ14p0/iyNv11iR92dXLCPN8EJr8AtFUvX8ioNveEN6RanTfmUq3q9
+0CCXWThSIreab8qnaUkOa02IivgBHYW1OdRWAA8pH31JHYGMGdqGh5xhBpgx7vke
+nHv8btoQ/Ur9BqZN8hlwWSgMT6V45JOweSv2mR18EqryMUj+cWom2GEgwpuY/C9U
+TAMi8qSFBRtomvbag4wFVvs4mvN8hG0wSxbGCC0wRT/bn711FexwwM5rmeHVILRV
+HMrCpihBI9ZKelGiSSDGdeMWXqXsjVgrIzxzQUfro53XVzMfFAiFvNCgrnM5ViDS
+uxmUjdu580Ncz20MZt0pom4T5h1VjQ+f3grfnOfcW3mIkZS1gLCmTHRrcMEQqVDL
+nXh7CyFwAF2pKbInkmx9NAtVYjld0cU+e7WehJBwwzNAJmTh1DsuXSbjuOdgXPbm
+4xCZCqeJGPKa1KuwS9zFiwdgTN5rR9BuqG2ad+F/glkYV9v8SAhc7YVjRVBCRNsS
+xQP+WgZFWkGZlsdei6aib8/3C8ktR8vga2jr1tZ/TTcNz1i7RssgUjxN0BQLjz53
+tRmBNklFn0PeJ9LmlEULoRQR35nmHfSBPQ3QwRhDxQ32jbKLe073ZekBZc+M0Rdh
+Cvgd+A7Gcnrct+PnzUDccyMk4uhAdiRRnmawscYupGid3Vm4CsJJaNxWeSRQuH7X
+4u/EHvI89r9ixJd4s87bi6VhFa22sg8eGDEgBUNfH5UqVSI9RRVfW4Iz2GkRR2WN
+ZcjWjeunn5PbQRcKOzn7x81ZfF3IBuCbmWnzNl1B8DGrDsQytTzE4ar3pBGNHZ6+
+HBj42b8hBAY7OXyoob91mn8b9RvOxsI+jxd8frdoNXgGLWsmy3fcPNY/SOXDkgle
+mNIYOkTl/XxUlQMdnCsLv1u8Dyy5ZEdhRYFX93k5XIOvfASU6KuxuHMT6hY3hNzo
+6X/Jc58AYC2+pVoMW3Z7DJaXFc3byhwEudfgYrrUtJNfrzSyU1Ic1qktDzsiDBa6
+59zHO99ftdB6WC5RhCtcljBSPKnOhD/5oAnqLTiY3irgn/wdqBvMJn0dkSiWrT8a
+aGpWOAO0QfmAfvZYUk8LQrtTakNa7lW9Msd4+3aaVJruqcVrh+2OSQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6.pem
deleted file mode 100644
index e918530f97..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6.pem
+++ /dev/null
@@ -1,190 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBWzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWAdMOZhkDHEp9KBGE+XuF
-msopQ2J+rJDtUrJ4pDANd3KgvUwmAZnDOopO+3hIw/w6tsB48EJwMCiofofFALAT
-zbGJidQOgpLF2if/SwmyWzUKqB8XirB9z5z0NLfE/0nnUhVQnAJ54W1jOz/+wMfg
-7oWdQC0ZAd1ndBLf+mtqHwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUk49NvPIc1wyuIEisujIaDdfoDc0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJhiiwAX8BQouosN8thaL0+ZHNhiuQ2gr8Mi
-xgaJCB4DVxE5teLk0eeWz+KVJBQwDdrlK4l0BO595r8cldkYkKJkJl+ZGPbNSDys
-XuVwXGbgfcUNPCeD1UIErQASVfomr3io69Nc62HwaBpTgARQO0wvfnIOFNAQSZH9
-247eEnnm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid deltaCRL EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA1
------BEGIN CERTIFICATE-----
-MIIDKDCCApGgAwIBAgIBBTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlSW52YWxpZCBk
-ZWx0YUNSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAscrNGz91htFkIREH4kXyOxo9/1St8nJA9dIDFUm8mrrSSju1W8oD
-Xp8EeOhyKguxnDGTfGnp5SIrvLUB3IEn2Jjme0QUKtz3lVdWYMNZcyESeKIhz2Hs
-GCFxmYHAzafSbJ4dh9VLWVEkARbN31prGZT9BIls24r6PWhRDanqOZ0CAwEAAaOC
-ARcwggETMB8GA1UdIwQYMBaAFJOPTbzyHNcMriBIrLoyGg3X6A3NMB0GA1UdDgQW
-BBRyJcnOHzbSUbchF1gWSl+d/EKipjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMFMGA1UdHwRMMEowSKBGoESkQjBAMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JM
-IENBMTBTBgNVHS4ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZI
-hvcNAQEFBQADgYEAUGZgoTW4dnlTr4u8+RArHmwDwiSDY0cXQimlo5QXcoeZczkt
-s6hrTXRDO2ZiijUqoKqP+F7hBWROoKc2U9kq0yLfZXxsRBx5atus0zwV9PE2pYS9
-5doAUve+eXvnEBzwjBzlPNoWo0yklkwaVIhBZFY8HS2G8P115VnipQebcZk=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 2
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Signature Algorithm: sha1WithRSAEncryption
- 63:e6:6b:e9:cf:44:29:c8:8b:e5:8c:ba:ab:26:57:a5:4f:a8:
- b6:e3:81:35:ff:73:8b:40:e0:79:7a:d7:69:8a:c5:a3:d9:85:
- 29:ff:ef:e4:7a:4b:f5:36:51:34:79:9a:85:01:cb:ac:03:48:
- 9e:2d:b7:b6:9e:82:57:b1:0a:b7:49:06:a8:cb:c3:71:2c:71:
- 58:7d:e1:68:22:6a:11:3d:e6:ac:2a:58:d8:1d:97:3b:46:98:
- d0:f5:f2:85:85:7f:b5:c7:57:a4:0e:e4:fc:c8:cd:7e:b0:2c:
- 1d:2d:86:30:1b:06:70:36:33:e0:69:47:60:98:5b:f5:93:35:
- 90:7a
------BEGIN X509 CRL-----
-MIIB1DCCAT0CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAz
-MDEwMTEyMDAwMFoXDTExMDQxOTE0NTcyMFowgYgwIAIBAxcNMDEwNDE5MTQ1NzIw
-WjAMMAoGA1UdFQQDCgEBMCACAQQXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoB
-CDAgAgEFFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEIoD4wPDAfBgNVHSMEGDAWgBSTj0288hzXDK4g
-SKy6MhoN1+gNzTAKBgNVHRQEAwIBAjANBgNVHRsBAf8EAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBj5mvpz0QpyIvljLqrJlelT6i244E1/3OLQOB5etdpisWj2YUp/+/k
-ekv1NlE0eZqFAcusA0ieLbe2noJXsQq3SQaoy8NxLHFYfeFoImoRPeasKljYHZc7
-RpjQ9fKFhX+1x1ekDuT8yM1+sCwdLYYwGwZwNjPgaUdgmFv1kzWQeg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 48:32:1b:da:3a:c2:71:37:ea:24:5a:90:2f:19:b8:9e:00:96:
- b3:e1:2a:6d:ed:b5:7b:eb:90:30:ac:87:c0:8a:6d:ca:24:f4:
- 73:dd:bd:b7:f8:cc:55:31:f3:d9:e2:a2:5c:7c:51:60:6d:a0:
- db:43:12:52:9c:94:fa:10:86:32:e6:a6:7e:ce:e6:c1:00:2e:
- fe:33:22:b3:5f:66:e9:d3:03:de:05:c4:94:bd:09:2b:1d:2e:
- 06:86:e8:26:f5:f4:38:39:62:7e:e8:0e:bb:cd:c8:bb:82:92:
- 71:96:8a:01:73:d7:ef:fa:a5:c2:94:53:e9:2c:34:a7:50:7d:
- eb:4e
------BEGIN X509 CRL-----
-MIIB+TCCAWICAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwIAIBBBcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEG
-MCACAQUXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBBqCBhTCBgjAfBgNVHSME
-GDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAKBgNVHRQEAwIBATBTBgNVHS4ETDBK
-MEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEASDIb
-2jrCcTfqJFqQLxm4ngCWs+Eqbe21e+uQMKyHwIptyiT0c929t/jMVTHz2eKiXHxR
-YG2g20MSUpyU+hCGMuamfs7mwQAu/jMis19m6dMD3gXElL0JKx0uBoboJvX0ODli
-fugOu83Iu4KScZaKAXPX7/qlwpRT6Sw0p1B9604=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6EE.pem
new file mode 100644
index 0000000000..33323e9a29
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest6EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: EC 20 A3 FC BF 35 4B 38 27 1D DB B9 77 DE DA F1 7C 38 13 B2
+ friendlyName: Invalid deltaCRL Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid deltaCRL EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIEQTCCAymgAwIBAgIBBTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JUludmFsaWQgZGVsdGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDYwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQChdlfiKhgkVBZls9SSGM+R/2fkQXuDV0hM
+wkswSv31By0st3Rxv/Rdk2M5HQYcG9BJwfWqHmmfIywnsfWXY8hXl9W81O5xCQT8
+6I2qVmxulBwFDGa21Ik6vyOaVkh3GjNoUYDFvngr1srEpd8Y9j6ooDr6uQBuvaeV
+p7loDWGnCQFldjlZfHoSvmiOyx9oV14ZIW+8o6IoUQTOrnTuXXtr7whOd63KMBjg
+tPTczxQ6pGIF4c5CjmEzasNs0bcovGhmRfL078elh8VrB5sv2XMAeCUNWQP/GSoy
+OdP8R+FDzke+teFQmBaAJkKPLlHlBFRMIFoZ6WG76hB8GzaoflGZAgMBAAGjggEh
+MIIBHTAfBgNVHSMEGDAWgBR3GCPldoTIFJQ/gtCB6nSx4KQvMzAdBgNVHQ4EFgQU
+spIp9bjrEucJCdPG4GtrsDiEOD8wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATBYBgNVHR8EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRh
+Q1JMIENBMTBYBgNVHS4EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MTANBgkqhkiG9w0BAQsFAAOCAQEAGTUyGnLvpOUE4M2D+spZazvR0m54B0BHclY1
+rNqvv0PZ2Qg4hi9l/bntIH0q5F8OpH0LSZ/4CgcJfmflRtOgxU0R7m76yYZpH+K3
+7qhwBzd9Ij7tZWD1C1eKwaLGSduMVm01PbjjqHG1wuoGM14524GKoq/6g049c6Nm
+dOqVSxFf10LhI1StU/ptj3RhSz1YXquDHuMimPeFxI/yPpdVUNO4kF4qZrj7Nwp1
+L5zFnmpXpSo2QeIEfWjgCfEKOyGo7jgNshhsoEwogFQp+VS8opaKnJn5J6uNkrPz
+4UgLpsTk4UYXqgYMLDx54HTzVELXocW+YdeRv+H70w2XyfBwSg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EC 20 A3 FC BF 35 4B 38 27 1D DB B9 77 DE DA F1 7C 38 13 B2
+ friendlyName: Invalid deltaCRL Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6BF125E43F84522D
+
+yYCvvGQ/1feC0wRhswMyrwY/pF3JbXfstV3xlG00CXrVeZ8NlZdAg5Q6QJ9krJPD
+VRYziXTi+aMZbF4auvwRFe/CNuFxclKTHGDSQwIl9qRz/1EPKUhiJi4Xp/RSnAY8
+PBSYL/Pg/53apWqMOUHwAdoQ/9EkYC09gd8nXk/XfKuNRXDrAYd2x9dfmLZ743dl
+aXLr+6L+AzjzTNKLLjbhSPh2QRfUPwaiG44uAkl3mch7W8yNF41rBOLDuXbpzI82
+iAH3D34mtpiZmD7a8psm0R+2NgxYzfnAIe6ak8DmKTXGYk1OBhoKQTvABteai7dv
+utZD3JAQeCt4+Reom2bu+trjD4iAP4Rl/vCu7r4PnaVxRKsPsrAWapzIJmdBWdud
+4rTmSvnZzBmlTF/VrND52a09T4GgmXndWPhJdCyi9obOEpkNHFNBqQcntU3IW+Ow
+a3RBKIeKOuXhOLo86VblzRqP1xt4GJ5dp/8EK93hosocEos7T9e+0w0FF+IgjK3Y
+FfDgwdfepNS6FBs7gVxq8wuly9GNe2NrQezmNtQzLwM/IvuRLHh7oSWnjnwi/4Ux
+lbMYdQZduhHYvVbqTYgKaxn7Jye+8naQsJ6eWq9wLVSEx4dvHISWv5Fu3HeiskGv
+7GSqE174AaqCr4K/vQvxNVMy5PI1tdqTvPU6CeDwPM658hzuCS51qADbJkFY4pOj
+XaS1+phNt1a9t/sIrOLpX7I4bT6b094qVXqy6OuKWHLyky9QsL4Abp6MpnLShi8W
+QrUiCcw0I4BbtCGJRqfggRI5kR70zfTEDs7eBOWhuzTDTCm5sG2jaGLdH5mKFC7D
+aw7u774F3aIZA08ktj9tqeUDmJ0I3X7zWm3/CW3MdFkX0qehCqL7rk0IaO9cJtjT
+05/l9CTSEWQqQPryV+W8EyHJf9jEsDcY435hxD4x+q9PSeztcBMqOG4eh/l3XfLN
+JQXWdi0xIESrJUcOK/ca/psKcRIEIlw2LUdZupXFdJwuxrcjxfmwie5WMMXFv4tH
+pDKDOmDb9tJ/eJ0o3HLllPQ3VSzuKsSHcxKmx76MEqe0a5HcZ+7tzlSXIgFQ/7hM
+VUH7PBn+knEL+OSw1lfgfVmRiQm1B1FVAK4e/0IkqWZB09/7V/NO2zOvErR2bbWP
+ZpjLo8jJ9P9SjWiW7RCmvBS1SYdLtqAU+A8blpDpxMpXN3WKpRzhBt1MRj3ymSyO
+Ze7nm17FmfYQumU8DNqHR0gKSXVT7Swty9vmjUh/5X1MxPizVEnpxAWbvZ4E5wPm
+L4nMHIywYNWfaDXICBffWQm3Pv7wkCTTOqhQW1I27nYxz1CiVTWIExnEJdU1oXK1
+aM54hKv1v25xVctT4KFT0/gO2JpNcTAkWGhjvosPSI/FKXK3/KYdzo6jI0faGtR2
+BU+XYH9frKc68kwHbRu8DTem4IMl1WJ64MnJ3GsOr6S+V6r58UW9rFkcSOnAiocM
+bOrROd1qQhiv778dHseayZx2Si4T6jXviV/qV2ATQhJNbjTWwAltX40h7JZ4BN1i
+AxGR7TWCWtdkrauff5cXQujwWHAt1vRgPG/CtvdM9E+gOFBopayb8g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9.pem
deleted file mode 100644
index f96feae051..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9.pem
+++ /dev/null
@@ -1,162 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBXDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCr2MUpxzH8HIqzmAylEvng
-qJvVIxI4xzM8NSpC7P7T2R1dmFXK/19W+m5yqOagB9VxgxP9IYbI2VJ/FrbQSD/+
-afpuHA8++piSAs2e/1BoRagiln3PnQTLemPsmVy00eSLnsw6QRdC0MIZjme0/SHv
-Z6XuWPNvicDyA/Uml2pCqQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUo5OrV2YmbXI6bLyDZaOa/I4MQwswDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAFnKbCQCHJI6HhnaoKJkHKk3dBK/E1DNHc3a
-u9yx3wYdmqwkoG5iKJjssQDLcbLfpjuF7jU9nKbk2gcmOIa5//lgCmUaok4WZSUA
-u8bzMnpiZyzIjjoW78RyuntCMXbZzcs7umsOKfOlDXj4wwsev4E7m5nvP2Qv7hEX
-ECR/9DaG
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid deltaCRL EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA2
------BEGIN CERTIFICATE-----
-MIIDKDCCApGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlSW52YWxpZCBk
-ZWx0YUNSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0OTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAuJgOh28x++Wg1L68WeOKQN8XdV1qhrZmuHQgwEWL8HA4HNqPU18v
-laXijT2AqIMjNJs0Ja41CFGbeaiVSNrV7nMsuQAiXTiiS6R8yrRScEd1baqSvzRT
-PPgXoN1qSTYKXXeEYR3dKsHZ2DVAjdlvm/bwIm6lGKGchu4FxwoHCecCAwEAAaOC
-ARcwggETMB8GA1UdIwQYMBaAFKOTq1dmJm1yOmy8g2WjmvyODEMLMB0GA1UdDgQW
-BBRJKQemGd+zHC3BYsO7nLEzQ8rHazAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMFMGA1UdHwRMMEowSKBGoESkQjBAMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JM
-IENBMjBTBgNVHS4ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTIwDQYJKoZI
-hvcNAQEFBQADgYEAf2NJLZQsLgMF9j1YG0b0IP3nQETOE/M1kAExKmgex/QteM25
-DBV4d4vJzuh6DFQxNk91Y9K9bR7qIPlsK31NGGpq4lbct4XgbIlM0+4phq3sORcJ
-AU3cfsMvJwZNmfJ6W22nEhF9Dgd0JNo+9g9FQGlSH6z2O34vBB/jPtkDJEU=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA2
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A3:93:AB:57:66:26:6D:72:3A:6C:BC:83:65:A3:9A:FC:8E:0C:43:0B
-
- X509v3 CRL Number:
- 3
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 25:e0:e6:a0:65:11:f0:81:2b:f1:ed:47:8c:1c:a4:dd:79:26:
- 78:05:22:84:96:35:60:de:7b:13:ec:70:ee:50:3d:ac:d4:9a:
- 22:fe:e3:9a:77:a4:fb:bb:86:98:21:80:3e:d3:20:85:57:b2:
- 0f:2e:bd:53:d4:7a:ac:96:02:3e:17:00:67:67:6d:16:01:9d:
- 93:cb:fc:b6:f1:c2:23:0b:e2:de:c2:02:5a:70:05:34:35:8a:
- 72:8c:cb:78:ad:62:96:86:50:5d:6c:ba:1a:bb:e5:b8:e8:5f:
- b6:7c:33:8f:8b:aa:c6:b1:78:a7:e4:56:12:76:09:7a:db:ae:
- f5:ff
------BEGIN X509 CRL-----
-MIIBbDCB1gIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENBMhcNMDMw
-MTAxMTIwMDAwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaA+MDwwHwYDVR0jBBgwFoAUo5OrV2YmbXI6bLyDZaOa/I4M
-QwswCgYDVR0UBAMCAQMwDQYDVR0bAQH/BAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-JeDmoGUR8IEr8e1HjByk3XkmeAUihJY1YN57E+xw7lA9rNSaIv7jmnek+7uGmCGA
-PtMghVeyDy69U9R6rJYCPhcAZ2dtFgGdk8v8tvHCIwvi3sICWnAFNDWKcozLeK1i
-loZQXWy6GrvluOhftnwzj4uqxrF4p+RWEnYJetuu9f8=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A3:93:AB:57:66:26:6D:72:3A:6C:BC:83:65:A3:9A:FC:8E:0C:43:0B
-
- X509v3 CRL Number:
- 2
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA2
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6a:af:6c:a0:70:12:90:02:5b:70:fd:d4:b6:8d:28:9a:51:5c:
- fd:04:ed:47:e1:a0:5a:60:e7:41:83:23:ff:a3:e0:c6:b1:fc:
- 71:db:cb:8e:a7:20:0e:f6:9a:ae:e3:fd:61:33:a6:21:69:4f:
- 7f:7f:23:cc:33:47:45:23:bc:fc:a1:79:02:31:3f:8d:77:e7:
- c0:9c:8d:90:ef:6a:9d:38:fe:13:b7:03:dd:ac:36:72:b5:94:
- e5:7b:43:a8:7a:96:ce:16:bc:55:00:bd:cc:1b:a7:81:93:40:
- f7:f6:11:bf:c6:dd:7a:ab:32:e5:be:fb:88:32:e2:06:41:9f:
- 5f:d5
------BEGIN X509 CRL-----
-MIIBtTCCAR4CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTIXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQGggYUwgYIwHwYDVR0jBBgwFoAUo5OrV2YmbXI6bLyDZaOa
-/I4MQwswCgYDVR0UBAMCAQIwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFD
-UkwgQ0EyMA0GCSqGSIb3DQEBBQUAA4GBAGqvbKBwEpACW3D91LaNKJpRXP0E7Ufh
-oFpg50GDI/+j4Max/HHby46nIA72mq7j/WEzpiFpT39/I8wzR0UjvPyheQIxP413
-58CcjZDvap04/hO3A92sNnK1lOV7Q6h6ls4WvFUAvcwbp4GTQPf2Eb/G3XqrMuW+
-+4gy4gZBn1/V
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9EE.pem
new file mode 100644
index 0000000000..cbb9429d12
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddeltaCRLTest9EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 9E 19 61 2D 56 31 8E 7E 86 26 8B 26 46 08 30 44 ED 1B C6 A9
+ friendlyName: Invalid deltaCRL Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid deltaCRL EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA2
+-----BEGIN CERTIFICATE-----
+MIIEQTCCAymgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JUludmFsaWQgZGVsdGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcE10fbivD8YbnEDA+sI0O+XaIUsukUp/a
+yfj/WxEn9t2eUiwN5UbG579KJ8eLcFDNQhZrRjzsy1yWNJllb8pBjjRRyQozZ7rd
+mHlzW492WmaspKUVT/enEDTGOXlmvxGFRz91isOCgEqGPZ+6MLcXx5halMlQfD80
+X6qsJjaSFGSMxPPFUij4eyghF2dnmAzdJrLW8UKjSDjFPCrTY+1AGkzIaifpKDN1
+qdxUR936ago3xfCKujbRhOkjbeaAHxwBVdAPZQhmsJejhRl6kY5k0rA0Hbz8I03K
+6Ev61b9y6j/WFIU/GSnTvvZ98gwpI24lIRS/7uE47Uyf2pgXU6tFAgMBAAGjggEh
+MIIBHTAfBgNVHSMEGDAWgBR82Pa+A0zOz7c/oRm7M6u11437xDAdBgNVHQ4EFgQU
+lHekQ7FVrwObog3Zam6ZJLkbICowDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATBYBgNVHR8EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRh
+Q1JMIENBMjBYBgNVHS4EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MjANBgkqhkiG9w0BAQsFAAOCAQEASXs9VkAAMDzy/RNxg/DiQJf6z53J8rBmrKZd
+LgHqb0nWVu42Ibgmcc9GvE3jRekXAkoZOESOKzwnzTKFoNkSh4iOf2TwDajamAwZ
+4NTsy33kgxLggaVOqx+YHJDVGxc8LBPVlQK/1fgNuq0zQdCbzp2qcK5cFJ9PY9Xv
+4ktwPMZb7mDMuO6Oav3JjAy9obJ413mF7RAo75wrHL/+fUfFGpVT0sN5dNR9kjeo
+undhANx2cP4tuCvTq3IUROFr8s6qNFHsYP+kCIAsQHLYK8vnaJ8APIZfm589SAeR
+ohx5pQ/4gghyE1vBqnuDf4tzZyari1c7EQ7CTe2PVJF/g2nsHA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9E 19 61 2D 56 31 8E 7E 86 26 8B 26 46 08 30 44 ED 1B C6 A9
+ friendlyName: Invalid deltaCRL Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7FF86D7F3F2E87A3
+
+6vAuGMtew8Lpbmh+ROvHn4bEG1cDfkxZ5zJZigKNUagHN4nwEP9lD5y3Bv/K65gf
+d4/ac4RHMnaexNBR/8e5Dq7UqFWJpJSV1IgQBn0dlloLoqhXgHl2vsLEXGlJFZKa
+w8/V1yRW0+Gt/GxtpjdOzLE5dVH7JH/9GETETF83Bz0LTBCQZK0soRXPKRuQZqmF
+ukAuZKPz5bROEipUIe4DWm8O5jN7joP5irs+wdB7KnI2rOlZAQZT0GIONWOWfVQ0
+zhFzKVxB1ETU+8eUnY42NUXdArvILK/Adh+lCfv6wYabF8ezmZQpFNTf1wSDu1Ug
+Q1jd48shwbu1ZzR+86w2BjAA3kgHfSC3ljkVrVLOyGw2HMPHekAGm68vxchsv1vU
+DTrHWIU/hQCvsOmLXGhfF/sPVg+uivuI6fc8UVm/AFAOm5AcaSBnIcoUNjKHOq0A
+JzbJG1ATpNfQ1kn2aWAhl+VwT2wf6lhrNNyqnpAzUbpNe5Xt39x8YrQH7j3eXCjT
+JS5mDHiLq5iMmsATTF5u8+ZSZB+2+Xh31joNyf85qS90KccxyxwvXkSUUmvhaDYy
++chSCNwYnPHpy3/B0LrZt5ixs0a0kQAxhx10lpWFc/OSvwnOmITAtD0jD5iYftZs
+IMs9V0EDfwCU5rI2RLQcEZkG4DzlXbhnu91dSmssMrMp5GCgOHlrTOWKMMdEnVQ4
+/e1v3YHArSHWMUureOXIb23TQjZuqVFbWU/UlRO+xYgCbLrhlNQ6/67UUc5OaY6Q
+1pikMkJxpaeQmMqJ5p501QLVRfr0Tvt21GjGmKS6n6o+mrklGhBzWNS0qmuX2Kpk
+0ZrTNckSiWtjfvxMCWG8erQsTayws2gpJkXOSzqWEZhhwBZ5OacqQGi4N875mZ+f
+yjNWp2PYxcnxy8NwS6xgFBBtXrPlF2iJHNV+SgXrJiAVC4W3hG4p54e0C+xsVX/H
+w2iJkyMSVUTKdYxcqaJdCQbx2QrV4LVoFIubOIAz3a078RKPoWdLcvB29tWCn+g6
+M88Ciz0Bljq6SbsyBRwtH6rwPuM1WrupWTXyZhVKs/ni3kPBXUsWUQzfmAEllfT9
+gj7HuQRoKl5iZh2LAYNuFnrcgPHzdgWEwE8YcZCZCmDNSFqZusgouQ5Wwjgq1Tex
+KTFOnEbQ8e7oKxTm8k/cUQFcXBTp09NnmbwkEZklWEni8VyoM8wu1o+hVqwvBOto
+Jqm9qXUTqY/VTJPumnxrWBtBhQTO70L07c5WAk8rqLHA954XRvG1SAR0JC3LnS/I
+o9TtyGdSJEHHy9DdMvLfb0305eeeSo5vO7VTZwfSZIXRuzrx56UjVBRMzDZlB0YC
+FiKvWchbLnmC7uzDc9p2qBvrvawP1lql3pE91BOyi3Mk23Ew5ssJVXva9qFIzLfK
+1yCfPKDv5sDq4B1sriVsNvz1l8x/dbeyptE2QEqZiVsSOT0Yc3Ka25yMvG4ZRGxs
+wO/pX+5hnXCh2WwzvfTHXcZmak96HLJaPDl+QNydGqc4BSQ52Hb50w2Sd1v+QzPK
+acM2W5mjpgvxUwAOjkCx29dsrv1EYiBqkWmmgfVyaDBzZKcN0X9pOJcb5rFlpTl0
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2.pem
deleted file mode 100644
index e2b8ef58dc..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2.pem
+++ /dev/null
@@ -1,123 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoVIDlX8Ue
-jptTAccp199par4Wi+6zdvpzdmUXj6UICGge/S5OJUY6nmBMligfESDLwjhbFB9V
-wm194odW9eAiWfUenAN7i4xIyorZwf5dPqHZVOcv9M3jRBce9j/ZuO8ard6c8Dp+
-UQ7gGH0Avyz4IM9x52TNBjYLthRcxwRPywIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnh8dUFdqhW8b+OZBXut6ujB+
-uvQwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMM6gfNW7Hs8z/E7U5NW/M1Y
-eT2VxqvZaq+HqK/GnxQeJUalPUbLk66F3XU5QmU/gQ/F6wP5yEV8UZALVj7OuJ56
-Vz21USzCSPGXPazeDdBQSx0otXHbKVtamBKYMn+jFqYPuPmNxUWzu4iczvEsBZFK
-0dm+b6846EQQbmI8jNru
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid distributionPoint EE Certificate Test2
-issuer=/C=US/O=Test Certificates/OU=distributionPoint1 CA
------BEGIN CERTIFICATE-----
-MIIDFTCCAn6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMu
-SW52YWxpZCBkaXN0cmlidXRpb25Qb2ludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA737UO+PFs1t9bQRYiD1XQvoj5CgT
-W0o3qMiBsk3AhuMx4ozSScw86kyooet/wxn2pJeFuHhNbdmWF5Mz4kyUuTWHl11Z
-T0aauPWb15KkPWKyYGcwMPrh1xNR17ddZWhDJsgvtraLthiXLTiumcoof7LrTWd8
-lR6y9AZzJkxw3aUCAwEAAaOB8zCB8DAfBgNVHSMEGDAWgBSeHx1QV2qFbxv45kFe
-63q6MH669DAdBgNVHQ4EFgQUDby2uXBoHkNmqlHt58+tVdKbG6UwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATCBhAYDVR0fBH0wezB5oHeg
-daRzMHExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEe
-MBwGA1UECxMVZGlzdHJpYnV0aW9uUG9pbnQxIENBMSYwJAYDVQQDEx1DUkwxIG9m
-IGRpc3RyaWJ1dGlvblBvaW50MSBDQTANBgkqhkiG9w0BAQUFAAOBgQDcQ+nXCvsA
-WSXbtnoQr+PKV/BOIwQGVJgCtsiEj3Qt04kNFEDjXnXwsKB4LNclGBe5Hi/PsxLG
-nrxqkXIoArMFjjZe4eNbkZotgOz2xN1lH/e4+5O1Ji7CbuNXbtSABVh4ZJYzZJYu
-d418yGh18wIXgBC0R7QwhHtX5I5tRJPSOA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9E:1F:1D:50:57:6A:85:6F:1B:F8:E6:41:5E:EB:7A:BA:30:7E:BA:F4
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0y.w.u.s0q1.0...U....US1.0...U.
-..Test Certificates1.0...U....distributionPoint1 CA1&0$..U....CRL1 of distributionPoint1 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- bb:36:57:87:39:3f:49:50:07:42:5f:a4:2b:3e:b2:04:52:a9:
- 1b:dc:5e:8b:c1:6c:47:19:83:1d:5f:81:da:ae:bf:ba:1d:57:
- 8d:a7:f0:41:bf:d1:40:e3:f8:7f:bf:80:ac:8d:2d:97:15:88:
- 6c:91:39:87:3d:0d:45:79:a3:b8:41:a2:17:b6:a3:24:cd:a9:
- 7b:f2:f9:57:b5:98:a0:a7:07:2b:3e:5a:2a:d8:5b:84:7d:25:
- 75:25:51:9f:58:1e:6f:ea:f9:3a:62:59:e6:54:01:d7:76:91:
- 2d:0f:b9:f5:2a:ce:0c:46:e4:dd:b1:3c:23:92:a8:67:d2:39:
- 6a:49
------BEGIN X509 CRL-----
-MIIB8TCCAVoCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGggbgwgbUwHwYDVR0jBBgwFoAUnh8dUFdq
-hW8b+OZBXut6ujB+uvQwCgYDVR0UBAMCAQEwgYUGA1UdHAEB/wR7MHmgd6B1pHMw
-cTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYD
-VQQLExVkaXN0cmlidXRpb25Qb2ludDEgQ0ExJjAkBgNVBAMTHUNSTDEgb2YgZGlz
-dHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEBBQUAA4GBALs2V4c5P0lQB0Jf
-pCs+sgRSqRvcXovBbEcZgx1fgdquv7odV42n8EG/0UDj+H+/gKyNLZcViGyROYc9
-DUV5o7hBohe2oyTNqXvy+Ve1mKCnBys+WirYW4R9JXUlUZ9YHm/q+TpiWeZUAdd2
-kS0PufUqzgxG5N2xPCOSqGfSOWpJ
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2EE.pem
new file mode 100644
index 0000000000..c734f6b3b7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest2EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 84 11 59 C5 D9 70 BC F6 E2 E3 AE 65 5B 85 ED 97 AD 51 92 82
+ friendlyName: Invalid distributionPoint Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid distributionPoint EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint1 CA
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NzA1BgNVBAMTLkludmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNh
+dGUgVGVzdDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTYO+uijkL
+kLhQ6RCPP/jdjZaflgwCZ/5vJf836R0+nLLKy1a5ixBZRJZpBCo38Yu0dhUSFNaB
+sb+GCrY1qVbRaAndL1k2vNJibkXPaixlOxi6ujXoOCZmRNL5bAhxosUxjp9YPFYP
+dLMaCPMfOy/cg3r/gbI2g7ZG5DYeJxyuRfZN73P2klfctSmIfAVQprTT++L0VvAY
+yFO6tZkpRVMeFN/MmhNh96414DyXFFrkItsuvG8GexZneUVQHT8QZJsX0ObzJn9t
+ctienvZ9AQGKWB715t78MU4UCRcqB++KFCZIl9lKM/VQZi/ZLn1xukwyDZ2Fgv69
+gO5EiDlezxU3AgMBAAGjgfowgfcwHwYDVR0jBBgwFoAUETBzvY1wKILSb8/SN+3N
+6yOR2+8wHQYDVR0OBBYEFEPX0sGOqiykogAik/m2vAhdQh/oMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwgYsGA1UdHwSBgzCBgDB+oHyg
+eqR4MHYxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2ludDEgQ0ExJjAkBgNVBAMTHUNS
+TDEgb2YgZGlzdHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEBCwUAA4IBAQCI
+cEp1LqU+I90nVxwQnTlwlRtzX/Y7WOva6Ob7orHrFXCaT0ZFr6J2xs2wio7rML5F
+x5swu8SPOgCMtEh/LQdqyLYu3VP4IR1QMTjdELWliX68HJt8ySe1g3gpFchv4U5F
+JiOfSawNJqx0LPFdNNq5lJsY1BBgIvp6v9vucDcNOiASWeCDlHQzZ8AFOUMO7smK
+23qjZjUP5xAEOqeGEQ72ASfLJ8toA19FxT+JoP4A+y78d9P/kROrrPtLJOqJPCd0
+cAvuHv7beOJpeceSjxdJ9rbrcWQ3D7G/ln+Q8ljD+H74UWuo2Toy2m3Q9KaeMY2v
+r8GAm558Phcf5kn5wfyc
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 84 11 59 C5 D9 70 BC F6 E2 E3 AE 65 5B 85 ED 97 AD 51 92 82
+ friendlyName: Invalid distributionPoint Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,788F49663AD6ABE8
+
+WghmPOUfBAREyv5bDVqkJvMinWhwqTqEdQXEEb6A12s8mWvKA5GFH59GmiF0VZlQ
+2t48KNtCbpfZQE2SjCULKif1y8ENnsSogv3mYPo0RwdaEd0on1pPBi8APrrJkX9q
+44Os0s95LRhWU/9xZalOVTJhelgJWUXt2hoCJLNy9Hy1AnzGxYWYUb3ybV5E4n1S
+69p4AF6F+nKc8R5Xq5oEbTN/Me8wn9+bmUe135SWZXlnkJgTVE1fXm63rTQ6Y6Xf
+9H04vWz3NSowE6oyoEk0+oK/e9yi1O7fwg83W/2d2Bxdfns81rBEnulLUAZ/prqY
+cg+EOcTd2UN6/MqhGfpf4ymg/uT52jpuzw0YQtyBKEre3JU6OZlhm9Q4kRQ6DfdV
+rSArKVC+rWoTR1j1NnWmP1J+Hckh42hob4OlyYCpMEVWPkA0HQLIjD3THUoQVoSu
+aIPSBPLchTi/SLAX7/hq1mhl7iu1oDeF/PoGtN7PP2DNjWYVI3lN2uPBH4eQDBbO
+4zvUEFP/6RP3/CPfCG6g14KsRTV4j3VfVAYDOQE9S2sZwLpbLrFQnJcYvgn7C97P
+kpjdF4irqSJFnxWrRjkAc6a26FZH9p72NF4JqCtQQPkvaDAhLSOP8Bf+SPhdbmym
+mf1gKde9jXG+Wh0YgjXdVKx2PvRNMaXP4ezhuQqdQM0Pg+TdnrDm0GOrCk00iHs7
+g6ZiOa1SCi1yl8OTpLiAG3Z/1Hy6Fa5u0KzZOw5C9JPO1HWC2IRuO+xNef5YkacC
+l6BqKvny/W6TzAvIiA8zLh5v/X/OH+QHMHRtn/sickxeCnAcPBxB39xwDVVxVQI1
+vZr3ya016Y5hL/NtxhxbcpT5BdzVHysHMS7QHKXKUdZ4W08oWZ/MQD8u7kWGFZ9c
+CJXfYAyp+vA/esa/grpNSVJJE7cl4bt+5JMrXlsnLEbav6mjZknt0j/zUj2LcJ70
+648FUu+GgEk7f0mWbNwnxch7wBNSOKYKYHYNPht+cia+BTX10ln2FbWrROxfkZIX
+XEDqxhypqIxAAVri3PljkDdAXwqmqV+HtBBoPc6YJvXb7ekIfd4BZIxPrJf6n/iG
+jW53P5lYJqrZ50sZva7VyihgE4q+VBgGNvkSd8V8qM5BM+UkJ3ZIk2DsegJDqiNI
+lBw9q/GGxjdMSbRFdg9lE5eAhUqqdvWlhI7Gvu37KiQ+BPVFX2Xcm05ONo0Y6DK8
+yRUynfvlDZP19+a8FEk0oEuw4xBn4/XUqtq/GbwmTx8waoVJFAc50FqDtpcG4Fev
+b1oB7G36MfBnagevljMRJW7q7GIN0ZoSlYhciH536dESqgekJBj1M4fg7+c98kZQ
+3sIHNhddclj75cYWnWxLr5CkwPYlwiwwbgczUJYu+GO0Rer6uURHr+Tb1iOi7QXg
+uUkZoSbdTxlIzfd2MeQblf9b8sTSEdDHexvnw3TJnKCZaOeeKHtK97HD1hHoZ2Kj
+NFjIRog88KW+2+JvCQws0x5wCB/1fxzTyZoYpYJMCHwlQ9mk2dinUMapefPkqirP
+moRBI9R7F7Kiysfp5MNszbAJqjkIIb5tOgH+ITQlZI76XEd26nN/q43AMccA05S1
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3.pem
deleted file mode 100644
index 2772115950..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3.pem
+++ /dev/null
@@ -1,123 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoVIDlX8Ue
-jptTAccp199par4Wi+6zdvpzdmUXj6UICGge/S5OJUY6nmBMligfESDLwjhbFB9V
-wm194odW9eAiWfUenAN7i4xIyorZwf5dPqHZVOcv9M3jRBce9j/ZuO8ard6c8Dp+
-UQ7gGH0Avyz4IM9x52TNBjYLthRcxwRPywIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnh8dUFdqhW8b+OZBXut6ujB+
-uvQwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMM6gfNW7Hs8z/E7U5NW/M1Y
-eT2VxqvZaq+HqK/GnxQeJUalPUbLk66F3XU5QmU/gQ/F6wP5yEV8UZALVj7OuJ56
-Vz21USzCSPGXPazeDdBQSx0otXHbKVtamBKYMn+jFqYPuPmNxUWzu4iczvEsBZFK
-0dm+b6846EQQbmI8jNru
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid distributionPoint EE Certificate Test3
-issuer=/C=US/O=Test Certificates/OU=distributionPoint1 CA
------BEGIN CERTIFICATE-----
-MIIDFTCCAn6gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMu
-SW52YWxpZCBkaXN0cmlidXRpb25Qb2ludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuS5Lgb3o+ul4HsVLgHgzRL9MeLx1
-KnKHTzQ7EedCPCAL/7h2oNWVaOCqaRzy5E4ke3W53AP0lHEyygZjKFnLw2QjEtGj
-1qytIz79bI9YKeHX1pnOldsesBJtKAfb/RBhtwEsieibfV3nFTTckFhqtMWkRX+b
-xgbfcd5yKPMhQRECAwEAAaOB8zCB8DAfBgNVHSMEGDAWgBSeHx1QV2qFbxv45kFe
-63q6MH669DAdBgNVHQ4EFgQUxeG0ipAP1oMfhg4iMi/dmI5iNgcwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATCBhAYDVR0fBH0wezB5oHeg
-daRzMHExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEe
-MBwGA1UECxMVZGlzdHJpYnV0aW9uUG9pbnQxIENBMSYwJAYDVQQDEx1DUkx4IG9m
-IGRpc3RyaWJ1dGlvblBvaW50MSBDQTANBgkqhkiG9w0BAQUFAAOBgQDnY+V8RkGw
-+kpIYbTDHFKNX/7Tkk4ZRLWJXXk21ah6V7OqKJblsAWGSOKJa65p4GKLrf+uNvW5
-BuOTRbdFpJrjslIZ87Z8XSdWXo/guQWTLacYkBPfKeimVeBInc2uoKkzt3L3gunO
-zcm1s3DmNsCcQFvuG+GsDDn3xIkTxnTkHQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9E:1F:1D:50:57:6A:85:6F:1B:F8:E6:41:5E:EB:7A:BA:30:7E:BA:F4
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0y.w.u.s0q1.0...U....US1.0...U.
-..Test Certificates1.0...U....distributionPoint1 CA1&0$..U....CRL1 of distributionPoint1 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- bb:36:57:87:39:3f:49:50:07:42:5f:a4:2b:3e:b2:04:52:a9:
- 1b:dc:5e:8b:c1:6c:47:19:83:1d:5f:81:da:ae:bf:ba:1d:57:
- 8d:a7:f0:41:bf:d1:40:e3:f8:7f:bf:80:ac:8d:2d:97:15:88:
- 6c:91:39:87:3d:0d:45:79:a3:b8:41:a2:17:b6:a3:24:cd:a9:
- 7b:f2:f9:57:b5:98:a0:a7:07:2b:3e:5a:2a:d8:5b:84:7d:25:
- 75:25:51:9f:58:1e:6f:ea:f9:3a:62:59:e6:54:01:d7:76:91:
- 2d:0f:b9:f5:2a:ce:0c:46:e4:dd:b1:3c:23:92:a8:67:d2:39:
- 6a:49
------BEGIN X509 CRL-----
-MIIB8TCCAVoCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGggbgwgbUwHwYDVR0jBBgwFoAUnh8dUFdq
-hW8b+OZBXut6ujB+uvQwCgYDVR0UBAMCAQEwgYUGA1UdHAEB/wR7MHmgd6B1pHMw
-cTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYD
-VQQLExVkaXN0cmlidXRpb25Qb2ludDEgQ0ExJjAkBgNVBAMTHUNSTDEgb2YgZGlz
-dHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEBBQUAA4GBALs2V4c5P0lQB0Jf
-pCs+sgRSqRvcXovBbEcZgx1fgdquv7odV42n8EG/0UDj+H+/gKyNLZcViGyROYc9
-DUV5o7hBohe2oyTNqXvy+Ve1mKCnBys+WirYW4R9JXUlUZ9YHm/q+TpiWeZUAdd2
-kS0PufUqzgxG5N2xPCOSqGfSOWpJ
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3EE.pem
new file mode 100644
index 0000000000..fa5abf8e5d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest3EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 40 7F CC 7C 2C 8B 21 AC 98 C5 2D F7 70 0F B2 6A 0A BC 2F D0
+ friendlyName: Invalid distributionPoint Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid distributionPoint EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint1 CA
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NzA1BgNVBAMTLkludmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNh
+dGUgVGVzdDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCD0xHj/74
+p3hpJkJHrM7PT5avhjPpoPT3z/V3qkE6pwe1wFF4WGpuCEN1CsOlyESi1LoT5vxb
+BeMk588wa+n/hr1T5bwn2EfyzbLLJDbuNE4NvQunN3byvnBUw1wcEMns4WAPzI5Q
+UQ9wt+w6yt9fzZECOODbpR4vLK3BKgVv0+LCwNeNfHXaalzGgChMo0xTDwknSLY8
+2Pvf3j5aP4X8ly/XksCgEZzzosn9a+4DHPC3jhR8D4vHj6k4IDZK3gz0nw2e14QV
+bhRov6qkHFNuRNFImxwdVcaII2D3O/s7ktHvuxQYuVpu9Xi2be8FZXn48qlnDrDC
+Gn3yo+rUdahXAgMBAAGjgfowgfcwHwYDVR0jBBgwFoAUETBzvY1wKILSb8/SN+3N
+6yOR2+8wHQYDVR0OBBYEFGakshok498dtHSxxOvB7FKt50npMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwgYsGA1UdHwSBgzCBgDB+oHyg
+eqR4MHYxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2ludDEgQ0ExJjAkBgNVBAMTHUNS
+THggb2YgZGlzdHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEBCwUAA4IBAQAU
+agmCYpMQKrh7PpozaNQM9OFYe7O27WlMMCVh+nkAsoyABAeO7lVI/ey+D9E8ntAt
+aJZf6EnG2k/DQcpZUWwGtbx+uIDL3zpaKxGZ0x0Or6OF/UjjAURx/Hfs4iOLpwR5
+jtFG2Y55j3AQMsFtXBuocJh13pLKO8rTwK31HezwIq2le9CqZh0UzAEharNYEuxp
+x0cE04sEutiOECDVaoVPUoA3WXinaW69lc/nLKI1upWoSRslPAqn472nozcQQ29B
+CrSibOfrxuN5AwmX0VPfqyQCqAwRcQLZqhZMZu2NDTGxpAe0gJi1wHrQ49LfRRSp
+Xs5hGFBfB9kzE7VuoalE
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 40 7F CC 7C 2C 8B 21 AC 98 C5 2D F7 70 0F B2 6A 0A BC 2F D0
+ friendlyName: Invalid distributionPoint Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DA935BF2297D8F72
+
+kIAs9fHkWQqKBc6mGkdMTENh0UIAeYw6k28cbsgRsVL3TDGlRSA7ukrQrj6OlUy6
+vES23ccL/K2p7x3YdM+4/D+s7vWZU4phiu93jG2RGYK8E/r62kllwRAM8AVF0eDe
+uJvZXM3XrcW+L8W0j3lFHwM1hWXYVZiY+xGMpQH5WyNfzN5UwOyiR48/sQdUWCrJ
+meVcOmTEgFBTgRj6SdNiw8cIqRBtYSJoNYPYctPGTt4Dm0BTki659/7Cms+mubVR
+CR2X5R8/GTbb4ymvQoiQ/Pf/46VVR6iuG7nJ6n0tZ3sLAGUTDmCeBqwNKThQoYjn
+h6AK6+GFM2B2/VZu6BzvdJamw15O3fuEQJeLQr7lGzK5LbVk7whzwSEwuFkWOt/t
+6XKRCrTWF6gDhBuQTd/JtVX+Hu0D4OnI7Da5SX+sRZRkrtFduN4NrO1BHHFU6pLB
+Hr3qJYTJSkJzTCBFiOOGmXQb/uPpPZinOC3xBTILlMJ8GmTXBRil7Wez4RDyvuKn
+4UC+832/X014xmANYgbYOZfS8PBglN9DrNB0OnWgLOxsQkdI03zNu/tjfqXSaYPt
+1hu/iJJ+Z1b9f2ffL7rE7aAc7VsuL3+auL9Q7SQxAlMqxWibauoltJBdm08WDxeX
+dYRvQWnjTd8txwnjN5emJkpCa9WrfuziFLHEZTnLuuIz05rQSDbIsAD3d4R87LmM
+8HWQrOeN7fryk/dYVCrSTQAH0UT+RlFuTsQmGSEc/3dl+LdK09CuG40V86g08d12
+Qku5FAe/b6yREqZhWNlQjWolfkQzUML98Ry0mekZuWqKwGkSebYpk05S/DxcSzPX
+6PNl4M04rEM8SlyEFwNbTTweKgJ3BdVFixhp/00MeMuBN+x25/MfqVCxCOEjmZo3
+ossHKoZjpU2eUgaV1JQ5bA9t4Vz3wBpA4sXsATFcH7NLfW1NYL5lNS6bg9dGsyQ7
+U0z1YrmEcAmaId6BJbALu+9B0CKKmpCy2GGdX5s3iQ9v/U3jTCKMOHDsAzJid9Se
+aneyFZacnAmAuKSGkovHIdFRRpQ0dDt4rIMvY0zmhGy0PN1F4Q8eB9I0XIUE0o+0
+Tyqu6BTgE5qXD2zAaSi6s5/3PC0dJz5r1Zg0J0h/uvXBsIEDXqFB9/B3YS1bebiW
+z/GSFpsx4/qYjsV7kRZNG4WbGiHu0B/TZ+swQkeYBawORdDWZa8YFDYvv/WzWiP2
+503mTd5dIYsI1f2rBexeapv/oZKG8pwOQnBo+BbfVXp1xgC7Zd92N9zv4RcrXG1z
+jz8Lsy6YQLRQxuI/A+u6EBWUu/qWslbY0PnVQ1njzR+pxQKJsBV4vJrX6SFTRZ/u
+IBUe0cEGZ14yaZOqypyP4SsqlpYeEqRQd7M2KiLJQD4MGnSqkPh1zr2bt9KbKEOB
+D8jcIv5zLynb/YnDCCtTU0XKIWWMhS4nj4SSYoH42tttBmFHWAHF0txr7oqCQxoe
+SFWeYw1W2KgxosKPa0RJmHvpHviapcRJrfE8pdDaYMSKQKzr9mcCCv/2jpgFpmJO
+F2DNjtfScbY1D9sLK2OmD+NTWMO96TMTrVUzbps3DASrEmRmknj1hQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6.pem
deleted file mode 100644
index 0d018c8e11..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCs1jD9UP9Z
-XFXO9pXlwQaq3g11cXEADTlDc+W2RuUiBJXRjOhbt9pBqMwI7EhS41KMALd8ISna
-SAp5DDvmtp2z4X95eoizwZ9O5vtIw6XA7d5EwFr2c89INmIXFw2OA0K2Xj9K7eKK
-u95rUFjJM7qfZueTDyR8/qrUEUUhq+7gtQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUOjSLBeN2WFjEhwSYfX4djKxd
-uU4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMagar2d/lP05a6g8iDgAc4i
-8GOkbbNIOguMdW9fwv9DvIJyDO/ruRnKgZJdY9osVBqR8pVP1qErhwboe+dIBgLA
-p1yRVbcPKEd/1xXrFhjoH9Wlp6CK6Al0LIJ7iQMoufcUzay6Bux5caNEH06+BnJF
-nhKgwK6jkVuYAf9HHtVh
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid distributionPoint EE Certificate Test6
-issuer=/C=US/O=Test Certificates/OU=distributionPoint2 CA
------BEGIN CERTIFICATE-----
-MIICxTCCAi6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMu
-SW52YWxpZCBkaXN0cmlidXRpb25Qb2ludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwbnDywy9lvaPs3ihfyfLPtBoMo+v
-C+fBtx91KNEmBz2ACO825iLx9Cyq+vbSLMDPiBbEbBpUtXDAXuaa6omJ1BnyVp+4
-dDmnpIB7IZm6z2mwQ1/xp1Nse1vb1zxkbDnMVVpkSJTqaTqMUnR5s9ht0XI62DgL
-ZEFlpTiBkCVCWFsCAwEAAaOBozCBoDAfBgNVHSMEGDAWgBQ6NIsF43ZYWMSHBJh9
-fh2MrF25TjAdBgNVHQ4EFgQUNTlA81m7xBu1FOhMV8hYWiP2hpIwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATA1BgNVHR8ELjAsMCqgKKEm
-MCQGA1UEAxMdQ1JMMSBvZiBkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcN
-AQEFBQADgYEANn9ezG9vEUyKzHQDQt0yQTrF9KcG5PUqzKQiaIIzKvEBLX9d/nj5
-N0wEpklLq//fxWFFPlhZS7qsDal+jjkPnccIlgIDLNAYYOXEm05+6eeXXKMKwC9I
-TdJghmMFwSDvbp2s/dnQvjOrHIexlatSbbCEDS9XnSeMmHVJ0lx7aZ8=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3A:34:8B:05:E3:76:58:58:C4:87:04:98:7D:7E:1D:8C:AC:5D:B9:4E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0*.(.&0$..U....CRL1 of distributionPoint2 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 8c:94:d4:ed:c7:a8:0e:9d:16:d2:aa:4d:3e:d5:a4:72:af:7f:
- e7:9e:83:e9:93:a6:92:a3:0e:48:39:60:27:0c:6e:75:4f:e0:
- 1d:84:89:17:3e:09:85:f8:ac:32:b5:76:76:ab:09:64:95:4e:
- ef:01:2f:34:69:4e:3d:53:96:7b:05:5e:c9:b4:84:62:a2:06:
- bd:5f:6e:6f:c8:08:be:8e:d1:4f:33:72:5e:8c:0e:e1:2e:f3:
- fb:23:7a:3a:34:3e:69:3f:6a:44:e1:a5:fe:cc:5d:60:23:95:
- a3:48:97:bf:72:dd:2f:ab:fd:59:5c:d2:11:c1:4c:e1:f7:ad:
- d9:03
------BEGIN X509 CRL-----
-MIIBnzCCAQgCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgZzBlMB8GA1UdIwQYMBaAFDo0iwXjdlhY
-xIcEmH1+HYysXblOMAoGA1UdFAQDAgEBMDYGA1UdHAEB/wQsMCqgKKEmMCQGA1UE
-AxMdQ1JMMSBvZiBkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQAD
-gYEAjJTU7ceoDp0W0qpNPtWkcq9/556D6ZOmkqMOSDlgJwxudU/gHYSJFz4Jhfis
-MrV2dqsJZJVO7wEvNGlOPVOWewVeybSEYqIGvV9ub8gIvo7RTzNyXowO4S7z+yN6
-OjQ+aT9qROGl/sxdYCOVo0iXv3LdL6v9WVzSEcFM4fet2QM=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6EE.pem
new file mode 100644
index 0000000000..586acb4680
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest6EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 36 B9 D3 99 DD 92 AE 80 2E B9 68 DA 6E 73 9C AF 01 68 DF EA
+ friendlyName: Invalid distributionPoint Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid distributionPoint EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint2 CA
+-----BEGIN CERTIFICATE-----
+MIID1DCCArygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NzA1BgNVBAMTLkludmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNh
+dGUgVGVzdDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV4IgjGn5Z
+rdXDjs4TsxeXIQB2TgPlOe/PcBeqCUIlP1YAWrevsPt/Py2Qr2EYRaMGjtGGtgok
+tZGSrRRCo2cf187WWyAs3iycMhRIwfh4ZAOC/kGhKY2nsZeScqid/3tlB4HC5xFt
+fpR9Yx3KU/KNKY8qw8ecHNayu3d5Zj6RflcvQuv2LmfUWorIYBcv+Bm/lc83Tb6P
+cGem7WLCqN2AGe2fbT+IDjffHNjJyuAILv4EBAeht44bkNNGHyjkhgMxkinJmcuV
+kdwTNw8Zo4M6cFrQzYhN4nAwJknflLWB4Pkoo0++ZoAyuf0HGVq+ZmzHQv/NQi1G
+XxICk4yWBq6XAgMBAAGjgaMwgaAwHwYDVR0jBBgwFoAURGzu229/605Jf3j+zeUY
+oOy7YGswHQYDVR0OBBYEFHsvpwhX2kU3OE6JlvWn2bNsPJJUMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwNQYDVR0fBC4wLDAqoCihJjAk
+BgNVBAMTHUNSTDEgb2YgZGlzdHJpYnV0aW9uUG9pbnQyIENBMA0GCSqGSIb3DQEB
+CwUAA4IBAQBN6kTmJtDkGt05YiGKwnHkV7cbwRVAMCzmco2ulLYMXKsYGOTTfTYc
+w5qlHizxUygLyqWRByTpFWA8NXTc8VGQOrBrhtczKGdE2tir9bH5N53PcNWTvS0g
+GQr4AkCpd/aBm9WIx6iK4rK/f+B5E9TxLkJiubbbV2aWz8LUPpjU+9NxUm53ihE7
+XNg69ZhEqU1f61S6k7Rm44sXrJ9jQvD4ioC2FivP8H3NmQxNQlkxE6eo9cZqaW+n
+jeulLanRbnGTCKr38w3sjNJrWHdhserC5owK+toTPkZMNo7qQRrIvEVFiY1x8uOZ
+qPv9L26IlojDBKab6fjPOSZ6EaYaWl5L
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 36 B9 D3 99 DD 92 AE 80 2E B9 68 DA 6E 73 9C AF 01 68 DF EA
+ friendlyName: Invalid distributionPoint Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DD4CD9F490AFA91D
+
+pDLSI0fVUz5UXLvYn5W7dr7xx00QG0G1qW/NGiXRvwwhXzA1BPKzYPqf/xJe858X
+nuONm7bsOuYWrvTIRElM1M47eRITuqdYBbNGB96UK245A/T/67C8x+yVV3r26YoQ
+rnzbreb7Lk0xoVtDzG39BtEJQ2GnKEtKrQ+jhhAta4ZhAMTmaCD/JX0iCVHK6Ine
+tHbRK9S++B6RIX4LT5vBPo3CSBhXMT1hK8i4WQs+sfYtP/Kj2mgx1baZBMlcrGYT
+5F6hK80aUeJYpVxiz4IhKkg8ssTKatMGDULSR9WiuUbWCdI4A3IT8iuFzb2yaCys
+A1rKtUrbkufE0dsn/jceYLhpbHSLiIwDBy9K1+M4RzZk8cqe3urgFgWNN4usRX2D
+eW/gS4EWmcgvHkWv1Pi3YLuU0cYmUtKzryOTInMEyjbIKkRqhTsffPdiXxB4BpFn
+R8Tk1x3MZvHtt/j1NGiWX5f8+giSqfXuEDkjKFHuotsRuEMQ8tJk3KRJ9imVeQSQ
+NIopXNxypyDurLYE507f2rxJgvRDVSSk5a1mPdXw4H1YJWtFJ49Wa4mNWT26oEPX
+tpz+ifqIiAwtU7RAOJRSdbTaFmHh2gx7PocEE+26w6iQMXKqHTsooq4W0QKPk2e3
+2TON2XrEy6oLQxcYNwVucfVCkOddpcQyXe8D0UxSkiGFppLoGPC90SFI03xwj4Hl
+CiITSLznaMjXp/t2dT5DHNUSNYn3e0h/RGz190StT0Jrx31UvHeO1NBeKdKDAod1
+x54rH5ePECBMt9Wzd2zTNbpFJfSuNP2WCWD+PGji44ICpGYJlgRsNRzw1wED+cwW
+6txxmDBXH0kudLNE5aCoIvJPBJUkZxwu2Nib87Ekh4KMYPHs8k2DXfk2txPl6evo
+rRNjDxGT8+YAMmuLAvNRw8Lvco0GsQjrIzjUED9lb7qmks8JBaJN2gYztPBq8LXa
+NWU4mFGBEkRvJI+IBLZ5Cv504ztosfcuXVTQM3yW1fM2kWQYkkhaUfMNOEWrpGMy
+epGV2SU/ZImnpQE5azAeoyI8/g6Sq/TYSZ1rAsN0eiTTOb6iu9QwQ0G2ISPWpWbN
+DriYzoGWAfpG5qElsKF9+44q95TPfOg6VKoxGGWjdNfQpduS7hcsccchbJfvOcgQ
+wL9mubUhRIsmd+80TIGmsdlkkunPCTDjrr6A8S4VCSFVMnWb0pf9Pz4E2fgzNztq
+oZ4awGu2A4f9JzPPqYGNzAEJierpDiOIJeq+a4RWmoSXqVgVJwld1J03ZrcttPao
+OWlQilY+M0+nNpGJ84kW/ClsLFdTWEek4qpkbNeKAdGSkWsszuQh13wZ5SNpx2DO
+GXELXcqTCSX5ykAmmyTNZpjIU/wYgOPVVeli5WYtnOSM7na4iZNKx0q/vkLxKwv8
+v6PC/N0K8OxmImQ59Dy51UOxhSQaRGKCzZTH/KNPF4R2oIRogu/iv3VE02g/BHdi
+i9MaUbYL6H7wy+v2qNzu+XgFhvq2pOEq6raWFFwN+UXsY5N7FHgr4YuMYLTIzpDU
+w7LBJXMtUgCPkIiv0ccWHnsMu8YpMo/GyZ1nTxASrp+ADPRU96+geg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8.pem
deleted file mode 100644
index 2ccff7ecb8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCs1jD9UP9Z
-XFXO9pXlwQaq3g11cXEADTlDc+W2RuUiBJXRjOhbt9pBqMwI7EhS41KMALd8ISna
-SAp5DDvmtp2z4X95eoizwZ9O5vtIw6XA7d5EwFr2c89INmIXFw2OA0K2Xj9K7eKK
-u95rUFjJM7qfZueTDyR8/qrUEUUhq+7gtQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUOjSLBeN2WFjEhwSYfX4djKxd
-uU4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMagar2d/lP05a6g8iDgAc4i
-8GOkbbNIOguMdW9fwv9DvIJyDO/ruRnKgZJdY9osVBqR8pVP1qErhwboe+dIBgLA
-p1yRVbcPKEd/1xXrFhjoH9Wlp6CK6Al0LIJ7iQMoufcUzay6Bux5caNEH06+BnJF
-nhKgwK6jkVuYAf9HHtVh
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid distributionPoint EE Certificate Test8
-issuer=/C=US/O=Test Certificates/OU=distributionPoint2 CA
------BEGIN CERTIFICATE-----
-MIIC7DCCAlWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMu
-SW52YWxpZCBkaXN0cmlidXRpb25Qb2ludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0ODCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtqwbk/YTst4JgaZksbi+cItOdDg1
-ZDBk0znRRey4EXHLWBRaSV8RAAw9bNbbQEuq8IgHKD2Gny2ObJsV1WXdoGXwz/Kt
-zGLxkxN7VMH/euhCh/0aMr7sO4yRZgC72ub09FOxmDtEynuiurF5+jGJ8FoLHkke
-TMWpLls04hy4ITUCAwEAAaOByjCBxzAfBgNVHSMEGDAWgBQ6NIsF43ZYWMSHBJh9
-fh2MrF25TjAdBgNVHQ4EFgQUsMTcbBp2ScLfBL5qe3q9w9pjVuUwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATBcBgNVHR8EVTBTMFGgT6BN
-pEswSTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4w
-HAYDVQQLExVkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQADgYEA
-lvXRt3px1v5T+WzaqJpecpxWzan+l2WrMC4vCYTcyFyQvQKDZl2jGO2PubJTDLym
-xwenSbt7quBVMKJ9pbXkNe9gFQInbT/3+NMPsI9Kc3Ajn7cfWW8TslHPaxtG5pcM
-XQR5wls8vzdmE9pirEbf4HDsnKBfC5sP1GOAYhIt/Ms=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3A:34:8B:05:E3:76:58:58:C4:87:04:98:7D:7E:1D:8C:AC:5D:B9:4E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0*.(.&0$..U....CRL1 of distributionPoint2 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 8c:94:d4:ed:c7:a8:0e:9d:16:d2:aa:4d:3e:d5:a4:72:af:7f:
- e7:9e:83:e9:93:a6:92:a3:0e:48:39:60:27:0c:6e:75:4f:e0:
- 1d:84:89:17:3e:09:85:f8:ac:32:b5:76:76:ab:09:64:95:4e:
- ef:01:2f:34:69:4e:3d:53:96:7b:05:5e:c9:b4:84:62:a2:06:
- bd:5f:6e:6f:c8:08:be:8e:d1:4f:33:72:5e:8c:0e:e1:2e:f3:
- fb:23:7a:3a:34:3e:69:3f:6a:44:e1:a5:fe:cc:5d:60:23:95:
- a3:48:97:bf:72:dd:2f:ab:fd:59:5c:d2:11:c1:4c:e1:f7:ad:
- d9:03
------BEGIN X509 CRL-----
-MIIBnzCCAQgCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgZzBlMB8GA1UdIwQYMBaAFDo0iwXjdlhY
-xIcEmH1+HYysXblOMAoGA1UdFAQDAgEBMDYGA1UdHAEB/wQsMCqgKKEmMCQGA1UE
-AxMdQ1JMMSBvZiBkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQAD
-gYEAjJTU7ceoDp0W0qpNPtWkcq9/556D6ZOmkqMOSDlgJwxudU/gHYSJFz4Jhfis
-MrV2dqsJZJVO7wEvNGlOPVOWewVeybSEYqIGvV9ub8gIvo7RTzNyXowO4S7z+yN6
-OjQ+aT9qROGl/sxdYCOVo0iXv3LdL6v9WVzSEcFM4fet2QM=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8EE.pem
new file mode 100644
index 0000000000..791d9ca257
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest8EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 14 55 C6 99 6E A5 E7 3C 42 E9 30 3A E9 9B EE 2F 04 5D 2C 93
+ friendlyName: Invalid distributionPoint Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid distributionPoint EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint2 CA
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBBDANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NzA1BgNVBAMTLkludmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNh
+dGUgVGVzdDgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC203pOwsFZ
+g4ufpsQb/dtjKIoc8xzFlvmEwLV/KKdqUOwpmtCAVzP+KVT1S77NGtErNItytt9l
+lzeDn4Kdu/Vgy19LLbjU2RPYbi0WqXihFrh2Je9lHoc+Rb+pofpf3M8Ou9BtqKRg
+pSpqR7Q/d/uu0mmlpqKXRTM/ok1ExfFJoub3C0siQWRmHRDs9ob7qQK5erpvFNf+
+R5HTEg/LacOauYWGuD2czWeZ7iYhCc1G7dAdtq5ufauPA8LzSSROvzhp62Yaqhme
+vnBStTlE01ZtT/quS5shxpcn50EaI6Za51oW49fzQoNjeCm99cXZLYfv32i7Xga3
+6jhZdZLP3NNXAgMBAAGjgc8wgcwwHwYDVR0jBBgwFoAURGzu229/605Jf3j+zeUY
+oOy7YGswHQYDVR0OBBYEFIQjF/h4qPlUpp067Gu9q64IfsVZMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwYQYDVR0fBFowWDBWoFSgUqRQ
+ME4xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQELBQAD
+ggEBAFEGXuXGGGNMBSosWxFRbvB1/VkumjXFubrMkUb6n8RYdNlBiQ9aO9QsYXoO
+fRoSds0ZyFvClBV5ohPH0IQgQrBKDUmUdas9BtzACdjjeLTsPNFLYR1BiKv5iCWU
+gLuakMFiEKCJXry+DglaJPWQR63b/eQWvXuWixYxCX/urpluCvQrmTQcbhYlHzeJ
++s7Fbr+IEIsn0bpyd5fFXkuw70Yj4iYwkA3GdD5/KjHRaBWj0sfUz1RJdHzZTNce
+sTW6RZtz5eHPIIj//1G6rB3llO4eUijSTObnl8VXzkhTNyC/Ln/IkI71RCerrWpL
+T2WQ7NXT+oaKNdWkNV2goYgdFsI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 14 55 C6 99 6E A5 E7 3C 42 E9 30 3A E9 9B EE 2F 04 5D 2C 93
+ friendlyName: Invalid distributionPoint Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D8EF51F4CFB3050E
+
+9lUj0kxhfaJBYQ1BPgfR8YhA9kjcjpsGE5na7KM4T2HOCqubF7Bpmbq73W0m1ngY
+SKXcBkURwCcnZG527YQ74pf+HZ5Ar3yrE4UVAnMqlRCzEoFEvereQ2/MUobb8lxE
+E4sPKBXCk5XJ2/xj66U22wQycB9PEJahIGSPNe1hBl6UPLdBQQ4vBzQMkitAarjx
+K2O61FdXBZdqPNf7uwoWyJhBOCI9Yf25b4+90RkQhYhWE9g+CYI7yEyujayN7+a3
+Q5Eb2By5HdituZO0DWQDmJPvVACDACFTOw4jE1uW2c4CTOldSLMoci5MlpuMCY+U
+v1ymketI9rm1wKPG+4Aagvcgyf2gsqx1Zh1f+YqkWcZ8VR/1ohplPpzS9/gVtlUu
+2xNu+KUojCseqzbwJxWOqEEqbAV1YhnT9h4dkBFGVCUNhZRieeqli7E13/+XHLZv
+z2xltvd1xBEfr5XNv5RGdpbD9L7/X8reQLHkLwOi3w3fBHAO2uw3aCt6fWIHT8qv
+r8o3mP/sJ3M9kXuLOkQaInswafzKGzvVhE7/FeGLAG3JiF365aiVpCedeYaWhTL4
+IUG1km3edyZXyAs1NntHB9WG3RPtR8jNOdbeySZp04Cz/nHYB7v+Hd+FlecDnl0W
+fUEXAAlPlRS3J66bKP40QlnW3BSh3+ESwXy74MQIoKXpMdTG6oU8efp5x6wVjMG2
+VeHJRC6WMWwSqSFlugyV7csoqcym0L5jeIw06LAl/OrqohEdZrp5kOK0S6ZIkyTA
+IiZgHK2R85m3WjGw0SGWj9qAlKm72syDDvkpkoet1CWbeQZZzF5r4MCNtskNTOTv
+EvKMsThqaI4Ao4yT4Hq98/DMfscYC+mlymvqOUYxFFxHecQ4QKVsUv5IpXmplYBS
+vi4jRarAxk8HCpwAGzZ43NSA9Fv3fLaxlTTbf36itIq1LP3h1AtapkzOoac6KXTg
+25IPi6VtLxUIFWKEwzhkNB/SLiNqAgCtriVEd/P51OorWDUFYvAZolVmks/ON6Il
+EqHWGsBIfUKHhX0dk2684PekGEAZr7g4U9/Wef1WMkCYppnhoH7tUEqIJkuuqyYL
+MEIl5OxGgeUnr140Gh7bx48vbZZPNLBpFRzWcDbi97Mw3VDxTUIg4CO3LHMOEMff
+Wyev77l9sy6cp/+wNJaRnlnlbEPKo39RZrow/awWFzJLTqee531PTaOxzPL4eO+i
+b+lMquN2KO7eGSndp14JLVL5HHZS9O9FiYoapjr7WOP9QLibL3MlbQhecRG5X4EB
+pxGIesurYKuDNirrwuG75HIqNo1lczQNpX0qBZ3WxBqQH0u9PE3/IQXLEPGm3Ka6
+2erK5KYHf9fGwGpDSe/armKLhTU9hTGXJWY2UtGg5U1jVjdQFqD7AkODMP+3Xhdr
+8pMMe/ZLj+I9Yop4A4g/BD9cEqc6gzM1GidFu0lP1DkVFTgtxaUUqU+dI0PCLD7X
+d38/olQaUKrmjlboL+GyAuhI/h9wFS5eJT9mpYcADjfZgRS3ULkcwC6vOVlC8KGO
+Gro/DBndgzyF1QCOL+uXC9L9MxPlbPDssYbqcJjyOPbISo1FfYp7hg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9.pem
deleted file mode 100644
index 3a3eeefc07..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9.pem
+++ /dev/null
@@ -1,117 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCs1jD9UP9Z
-XFXO9pXlwQaq3g11cXEADTlDc+W2RuUiBJXRjOhbt9pBqMwI7EhS41KMALd8ISna
-SAp5DDvmtp2z4X95eoizwZ9O5vtIw6XA7d5EwFr2c89INmIXFw2OA0K2Xj9K7eKK
-u95rUFjJM7qfZueTDyR8/qrUEUUhq+7gtQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUOjSLBeN2WFjEhwSYfX4djKxd
-uU4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMagar2d/lP05a6g8iDgAc4i
-8GOkbbNIOguMdW9fwv9DvIJyDO/ruRnKgZJdY9osVBqR8pVP1qErhwboe+dIBgLA
-p1yRVbcPKEd/1xXrFhjoH9Wlp6CK6Al0LIJ7iQMoufcUzay6Bux5caNEH06+BnJF
-nhKgwK6jkVuYAf9HHtVh
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid distributionPoint EE Certificate Test9
-issuer=/C=US/O=Test Certificates/OU=distributionPoint2 CA
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMu
-SW52YWxpZCBkaXN0cmlidXRpb25Qb2ludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0OTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/suVDtpZX4ZdGIHhrhtDHDiiy4k
-5awaeTNhUVeZhKlIDNnniPSVG5/0Q2JlWvIywo/Ch0y41j/ihleGbI69zoL1p5z8
-hh+yK51J32JdQ5gpc49P1NnVtoNSZApTJt1VUR4LwJv1/AhIksEEOg6YHN3/yq/C
-wVMoMv7wnisqqykCAwEAAaNrMGkwHwYDVR0jBBgwFoAUOjSLBeN2WFjEhwSYfX4d
-jKxduU4wHQYDVR0OBBYEFLYB9DyXTb7g1exMOFd6gOIt97g+MA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEA
-HdkglZQIYTBxilyAJvuFkSrvNo90F3wuIb0FmfVrjH6Hs147bgRF9nsp3sh/VvC4
-gf7pwYRING0tY/RV+n79U2FxHcE3MN6WNGA+GX77LcWth+s3Sa6Hr5QMaUcapGbq
-2B+bkzQUiWX8sXPvX0KWzBmbcY3Aup56MpwytlF7ywQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3A:34:8B:05:E3:76:58:58:C4:87:04:98:7D:7E:1D:8C:AC:5D:B9:4E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0*.(.&0$..U....CRL1 of distributionPoint2 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 8c:94:d4:ed:c7:a8:0e:9d:16:d2:aa:4d:3e:d5:a4:72:af:7f:
- e7:9e:83:e9:93:a6:92:a3:0e:48:39:60:27:0c:6e:75:4f:e0:
- 1d:84:89:17:3e:09:85:f8:ac:32:b5:76:76:ab:09:64:95:4e:
- ef:01:2f:34:69:4e:3d:53:96:7b:05:5e:c9:b4:84:62:a2:06:
- bd:5f:6e:6f:c8:08:be:8e:d1:4f:33:72:5e:8c:0e:e1:2e:f3:
- fb:23:7a:3a:34:3e:69:3f:6a:44:e1:a5:fe:cc:5d:60:23:95:
- a3:48:97:bf:72:dd:2f:ab:fd:59:5c:d2:11:c1:4c:e1:f7:ad:
- d9:03
------BEGIN X509 CRL-----
-MIIBnzCCAQgCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgZzBlMB8GA1UdIwQYMBaAFDo0iwXjdlhY
-xIcEmH1+HYysXblOMAoGA1UdFAQDAgEBMDYGA1UdHAEB/wQsMCqgKKEmMCQGA1UE
-AxMdQ1JMMSBvZiBkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQAD
-gYEAjJTU7ceoDp0W0qpNPtWkcq9/556D6ZOmkqMOSDlgJwxudU/gHYSJFz4Jhfis
-MrV2dqsJZJVO7wEvNGlOPVOWewVeybSEYqIGvV9ub8gIvo7RTzNyXowO4S7z+yN6
-OjQ+aT9qROGl/sxdYCOVo0iXv3LdL6v9WVzSEcFM4fet2QM=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9EE.pem
new file mode 100644
index 0000000000..aa001dbd71
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvaliddistributionPointTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: EB 5B B8 8B 0B 10 C2 79 81 7B 27 2E E7 9B 75 D9 E6 E0 DD 62
+ friendlyName: Invalid distributionPoint Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid distributionPoint EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint2 CA
+-----BEGIN CERTIFICATE-----
+MIIDmzCCAoOgAwIBAgIBBTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NzA1BgNVBAMTLkludmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNh
+dGUgVGVzdDkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLKyk8HE6e
+PQjbQTZ9IkLDPjf+22btjiqAtAWS+6W2uVxyU6dliSHMswdSVOO+08YgmZtcRFVD
+rsw85o91RW5i4Pm20IIeCBNf+WVgmFUJ7t3uy5biH0s930zWyxkCqfyI9eKrxia9
+ej0hU1vdJ4K1L0XBSDpkHmn3vG74ARa7k2ZrlnD5NMn7UhEegwaLs8RKTCcH0kWW
+u7cfYgBD+AUjTbP6iR1ll4V7UNIGVcmyc4LdSnZE4+ihyWdwzPGp/E4ph1G6lGmX
+1knyIKhpIC9BW92e3DMCAPA7DjBVQNduGqaCIxrZ3nPk3GBVXqumNowmVb8+K+kN
+0CAe6eX1pO2BAgMBAAGjazBpMB8GA1UdIwQYMBaAFERs7ttvf+tOSX94/s3lGKDs
+u2BrMB0GA1UdDgQWBBQHhKpeEYEjvTDgLVQu6PXIjYv0CzAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAq
+yXgKDIVqTrgboHhLxi4heoZnxuohXK8Ag/1xFQ0DWLL0mgLemNqzrutLhWwQC2LD
+MHXbDT9B3ZgIOIgWBVDG2qV642Ln4xG5VCug+AWk+N2meTvDUaE7HtjQ9qvL4Zbn
+X+0pafFSuY1q6xcW7s2EDggf7hnnyb86LXSJwiP5St2er86QJ08Z47DKrrEkTaJY
+mx5lhCJYdtA0/pWeS4teEmDskJU8GDRlc4ZA+okCHVgU4zvLig5t5Q4tS7I8ICd8
+KtstuDiUyIdVy1MN4pVetIQO5cu4kQfCliHKH99+c/QYz3GIzz3U/9TiMv3wBlLg
+vZl51izphB8ha9hzCzJN
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EB 5B B8 8B 0B 10 C2 79 81 7B 27 2E E7 9B 75 D9 E6 E0 DD 62
+ friendlyName: Invalid distributionPoint Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CF20677602086B07
+
+NYiiAl4fxd7wtuqSspb2fJi+hJaU2mxNuf1QQdw0Jhr9EmD+2OhqGEbaUBHXw62X
+6rONswcLoz6oawOaQtnYzbG36E6b5q1cgowCc6o4+hk/T2NFhVZ9GOaEbIq8qqXB
+iZLOD324II0VHMAU/OOkJ/l848dMiJEJTizxfiUAB5er1RgFpGF7eqqkjy4OSd7N
+q90RIhoSgWy8+wwOgZ5Wg2fdxki9Ja/UvXYuYMY5qAGFL4J1+vjggLPLD8D+gN9r
+Rgj4Zz/MWDY1brdY9xjHFWUAxvr5s5zpXQg4U3GFAd4PJZRthvw6ta6Pta5cKOFu
+yGkTr9UX6PYGjyxbnEcdKXMbnl0uAIkXIacGUdVxhNHVLxDsGN0k5mF9SYEkH0IA
+AC0B6CYLTo1ATTCqucvINxXuoV6AwbC+IbWq95RgVqxgkn94BTdGTsal0fv4QzGE
+4n/P05tqdKZYVntp9YTDGGaf0mbFmN3B68mqWghM8MEW31SB6uUqIdnZtF6FPjgg
+kKnfuIc0lTpc8YKh/UjKiyF2+jvN11v5srJ0UyUnUmI+5R6uTuYPKBbIkFydoFHU
+66iuXfLjilJMD9pw370qxTVfaLnVtDZbhyj1oX6zB5Knf70EfyClSbEHgXxwZwWP
+OhmlGxGD3ggeat+uhlETH1qiZfH9c3fUN+HDhnVC6tzBMzQmpk6Q2VGpvvcjc1Qu
+7S9wB/6EDWKyXliVBa9W5+woKPOWs5cOkuUyPKNgUhTu9dwBwnDZo9fePMEnznb6
+xJ1dIzwN7oZp31NofTiNxTKt1i2ih9Eiiqy2NlGUACuD+04CWTKvi89V/PufCW/W
+q44dEHCbm4PrLclSI/rqs7NUq5zsBMRkcgFeEe1gARXGt+qbLEV4spWBZv8DzuJ3
+xL7PQuAofN1dOHSSX8aP7NOBEWMt0Zlh8lpu0UJN8xIgLQciXrb/QXevYrXugqRe
+TdH/a3o9IqjabXbMM7qPTlrsh6D4xv6aQHmht/4gLgpPZxua2xBFDXsdyXw9i8Ic
+wPd65o00smrOeJjDsVdbCrPSCfJDUUoSIXk8G60OTSY0R0vRW7S1Wy387cF2vYH7
+LEX10/Nm81xeKzDi4cMOp/hPtGSEtCFj69eeDTVX8+oVRwRPSb/KZkYNq/JaHQFd
+uZ7jbqNkomrAK9PAnBdZAHwSlNOVZMPUWMCQOPcTP2rKC7IVrjtzmpvfvuNNfeOs
+d1x1Z3XwdhlKr8aNff2BjOlmuH+ZTaua8CJi93Qf//+klpWxCLVniHIea9ZPZ1VI
+tVeyD+MuQlEoHVuxuKnNvxDp1vzzY7IRT1uRpjV6bkfetq9LcTdiZtebTQ6sVeks
+/fzUyrkD0t2qC27lan4YlFze/0bILXeVCuGt15uyv/N9ug3Im4xQErp2vnZRpiR9
+uO0dkBnpw2b2YTex9j974Lb4CYqXouq1LwEKKlvov1e6i+9A1DI3HOA0TB7YvgNC
+p4Tq2SVf3bp2OfSTkvMfaXTyW60iIxoeuGFPfXf5u86uRBqjqdREJVLkH7Epfvsk
+KFc/qbi9cdzybWqfS6lpWZNaCkZu7wCFQX8X+ohIEQdQZjgb9gQI8R68U/KwbBSl
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1.pem
deleted file mode 100644
index c873549a35..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitAnyPolicy EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy0 CA
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kwIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYTELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTYwNAYDVQQDEy1J
-bnZhbGlkIGluaGliaXRBbnlQb2xpY3kgRUUgQ2VydGlmaWNhdGUgVGVzdDEwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALU75+fsqkoJ1rj9rLPys9PtX999U+V+
-71N40CaTnqxIlY4+U6A/BBm3iqNTQdcyEGo3Buy3OJEELx0+8jI3Sm9ja4iR/4tk
-gi9OYh29Ps0LcRyqUihECPaPFOvI2vEFJId74DFoUPgwNfPD0CzYkm1bYwNcMHwb
-0QMmUcxk8yTDAgMBAAGjZTBjMB8GA1UdIwQYMBaAFJ1AmGAI5sj9XNHYLwvqAOwa
-RQbPMB0GA1UdDgQWBBRgJfQvy84RFEADVPWlCcnfV9YiljAOBgNVHQ8BAf8EBAMC
-BPAwEQYDVR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBBQUAA4GBAI1bh7Hi4BQZ
-w7LpH+0QxTA+hUMNiV3kKdM9vhGFAwm+UbQvTYeIDaIpDxX42Sv2j7Vw9Z9nkMc1
-UyaIcxezk4LAN4vG3WIJiO/eAFuCz49QWhE53AbRVprrra8N/Mzv0yB/8ysQ9fUJ
-AVMgwRz+4Fd2AoK0CWNHeDRUD+IN+enU
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBOzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTAgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALXCzoaXAEbX
-pgMPDk3SCu2nzrt+I18MsI4lg/0oLjQAgPsD0np8LOGHMzo3UBtfJtpV0BXCc+E+
-+Ni+ehXFWfA4BXjFc3GdUdJmn7y3F9X7XSIauTE1GSYR2+bMW/IRbmjpMDzldmRs
-WNb40N+jWAxw1h+YN61Pv0MD7Ef2ds0NAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJ1AmGAI5sj9XNHYLwvqAOwa
-RQbPMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEAMA0GCSqG
-SIb3DQEBBQUAA4GBALhhUDb9VolIM2bKpbpat4dNjGrkOmVT/HvGBl+FGwSXa7Mj
-cLgZ3WygZ9gil3l7X+wL7lM9zKpXljV5WNpX+58RclQ2kK7Yk4qcY0tpPEUn8R4/
-9yg64Nferl/2gn9W79ODU3BiBFF/GiAJJ4SiwvLWl/JnPDoQuJv67IS24+Oa
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:40:98:60:08:E6:C8:FD:5C:D1:D8:2F:0B:EA:00:EC:1A:45:06:CF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 60:ab:a2:8a:e3:22:04:cb:95:4a:c5:ca:68:46:70:0a:d0:31:
- b0:98:cc:ad:4b:23:8c:3e:fc:b4:c7:7a:93:0d:6a:31:68:c4:
- ff:30:37:7b:5c:48:01:6d:e1:85:f7:d0:9b:73:53:ca:62:36:
- 00:5c:29:c8:af:a6:40:62:d5:f5:af:32:a9:4a:b6:a2:a7:0b:
- cb:bb:72:2e:3e:0b:77:64:17:8d:2d:59:2f:fc:cf:2f:1f:a6:
- 77:83:9a:7c:68:b0:15:f6:5a:63:67:74:b2:3a:fa:74:b8:d3:
- a9:70:e6:87:04:bc:4c:79:ef:c8:b4:31:70:17:ae:f3:ef:ae:
- 7a:3b
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kw
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBSdQJhgCObI/VzR2C8L6gDsGkUGzzAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQBgq6KK4yIEy5VKxcpoRnAK0DGwmMytSyOMPvy0x3qTDWoxaMT/MDd7XEgB
-beGF99Cbc1PKYjYAXCnIr6ZAYtX1rzKpSraipwvLu3IuPgt3ZBeNLVkv/M8vH6Z3
-g5p8aLAV9lpjZ3SyOvp0uNOpcOaHBLxMee/ItDFwF67z7656Ow==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1EE.pem
new file mode 100644
index 0000000000..ba817eea6c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B1 B5 95 BF 5E 4E 68 BC 59 6E D1 37 D5 5D 8A D0 31 AF D1 F7
+ friendlyName: Invalid inhibitAnyPolicy Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitAnyPolicy EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy0 CA
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTAgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBm
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE2
+MDQGA1UEAxMtSW52YWxpZCBpbmhpYml0QW55UG9saWN5IEVFIENlcnRpZmljYXRl
+IFRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsNW1wTtifNXg
+S/7/6OTB9nSbSKSw2BLiidrM8x0nGdCwUY++tWaryTAV6tJVLmfDOSrlcqgNgubo
+U2ufM/4Kxrkt4I7I8V7GIuXMVSOSG9DjroelJDTfv/PKfxd/Eb+6mV0lrfempURc
+27X5CfAfKmM22sCPohtfBzKwjsi22RA5dZ6nlUygOhrJgvz3D7/3Gzrrnt+fEtye
+USyq+8nR/zXX+JbOi9gC2WsZMvyRb7pR5+9Lu/qQjXQldZaY+trrEfUmLRUmrxUZ
+CwFjs3eV+vObbmsXnORZWwuTPhw/GBMx227uefpgnZ6x1uJB+YEitiHX72MDkS4q
+6I4Y8p3y2wIDAQABo2UwYzAfBgNVHSMEGDAWgBQYoKB6av9qnYWCJM3DJoX4v4o3
+BjAdBgNVHQ4EFgQUBKSzfwBnruEoSD6YjRYo9lI4/ZcwDgYDVR0PAQH/BAQDAgTw
+MBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsFAAOCAQEARGD3khHtk07o
+014aVan3Tjr0c4mX7zn4cgm4Vgep+/DOtUEcV44m13/YZ4KjUXR9zaHc8OQhOZW2
+oWCAaEyL0Qw4im0m5LVWkKhlomLU4TJPT34u6m2xlURUwmcUkAaaKf4Jpy949zH6
+x5SFLFB0VCWUgsxSgIgTI0cdl1gnd8WE5nsc3yUKbC/1HRscx0RgjH3y0UFE85FC
+fkcICoA6prUdt2Q328dRd+mY82AI0/lD4Amr1gvbyUC1M0znxTsCZPNHRPQDVqbx
+rQLcUDlh4004RiOEkfPyvm4OsfTD8df7euRyegy/gPde/vipEYQP4bARJalAC+ae
+/U1rEo3zNA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B1 B5 95 BF 5E 4E 68 BC 59 6E D1 37 D5 5D 8A D0 31 AF D1 F7
+ friendlyName: Invalid inhibitAnyPolicy Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,83990521C98D081C
+
+PVZi2XabBgzng1zcjU/P0sUAiwIEJmPAIQAnbG9kzRvv+a1qFXm6LvXFsW/lb+aO
+hZPOcBrO4ABhZl3ctCHpMDb2oHpQ2HxA3y2YgS+LCm/+VR4LbO3TCTmcuX0oKGWD
+4wqbJQKmKLzDiXNDvZYm/7FMmFtp4cXVqECiAEAx8peRlfEj4YvfS3vQMXWbLCK7
+v06Ge/HJJ5byyhIxRUhSMSZdPuhZLq6UYw0wAdpW99f1gEv7GPY2MVPxJQ5pDE3g
+4xeRGdWAYdUSPi/eSj3JDQucMV1ujm9DfAPxc/LaRo+nLcy8FCvrw+HmPBL778Ic
+cN6ryTqjzsQacPrhtvzB91BbMKgKRM2rgPafgmSmNBcWFE++X5OJUQe0/4liT4Sk
+tFUd4eahfXj+LsXoqlJa3l+jTTJN68OivyHNesJm75mRFnTkURs5gNBCwibs8wlq
+SSDkQlUEKXs7/6Un9hpZj3Xb5Uv0jhXpAz5iNfOe6+z/nLYB52B2cGege0NZPNot
+4738AyHrxPIxYanLiFZCMA+X5tdfc7sgMi6siY95c3VdWwdkVVk2oYxJ0QGYR9/b
+D6Si23/trJZOVbfIkqqOYTR75T05FJA1p5tP1xfKt4+/dcJ4ZO4q6dsEvAR5RGqG
+VPpRyhFYxGBqLwncfYqH9C+vZ75uWyJHAxC6G0DOre8h3KUOs6/DsPBe19c99oUR
+G8/65pMxrGrEcR/T79CKbcF8zEMC4xexP+JAvbILdEMO4b8IgfPlNGZRjcok0VZ9
+Y7WAOlOr/Wj5qkUKmHYbCHb0+Y2uawZW3kA+TzBXvAbddzL4gCELIo5IFig0qG91
+6TJyn5EmmAy3B8J8DFioZBdy4zYw9m6xmpElGpSzFHAQodqCNlREiwihhG8hI2Eo
+zgVtKMPoY1h/722M5kMZnQ33Y30pi7Dqo5Eeph07pI0G5wxJ+SzyKoAqj623Cdz0
+ofxRLoWb8g0BVfJ/S0kkFhgG2pq7Z9/huNCBySk1SHwT+wqWXT4l2AD19gvSe3QO
+SgVv2igWo3Kc8ORbYxW69szAescLoee/50Y9Di/uTNaBd7/KV1BVaPxocVFNReGf
+17nZdjRi9N09FISZ3kRLG37rl7A1yp8ihdqbsVRXo+TSsW3K3/mjdkJjhC7IveRu
+07nSM+xo8BT4Lpvd8cOY4nxTJ75r159Z6mRCeTDFsarjsRg9ZZk9+qvLFiAY1JvD
+5IDb1zpVeo6NKTIbD2u1YrArI1HR1A50XGS2R9ywSv545A8imQFH/lh8rJdW3KQU
+BY73YnJVg/TlueyKzIi2nG5+S076S3QIXbeKegtIoELxMNvMogZG3UoGN+MtRVtJ
+pCK5oBbOg3zgsBtyPYBu4RLx4TYUBudsZdwa9YFmf0OwtKYl1GVoUoNeAcoZRX7S
+DRkX8PLWdbVq6f3n3AthHZlGp2T36yc2gFU9JOupUb9iXutML3cHpBelfBhmggBo
+5MIoQKb9huNXTJV4WR4tV0vGKqi1gkcsJm6kN8SpxrgyWqKPl8GWxc7oWxSVQRjs
+d0c0xL+s6Ffz8kM8dHl2O2SL3yFHdH4IF1CJV7SfwRTqF/r/g9SIMg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4.pem
deleted file mode 100644
index a81968caaa..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4.pem
+++ /dev/null
@@ -1,159 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA1
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgDCCAemgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhp
-bmhpYml0QW55UG9saWN5MSBzdWJDQTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAMvuM5rrG+hunxSZwR8TVsLND7teVaTAzIxbnJv0xpVvawDeQiN1A+CIdJH8
-TUXrgcfdU+E04StBCqDRBr1+DBMt/PuBDS/I2PcKqBuP6sfkSDr/lPYkbRBI8wZ9
-87H/ke7seqh7cSVORfqg4KupdEE3i2gxONHlTT/7XV0C5aOlAgMBAAGjdjB0MB8G
-A1UdIwQYMBaAFGbbtZTHBcSzPiuRud/IqNBNKzREMB0GA1UdDgQWBBQpIHiUjoSQ
-KUJLfKsOgyq+NVs8FTAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAA
-MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAuKZUyh6gvU8Ab5pl
-P79yddRQcx4G1navwUD3YSS7q2rnmqY2ucmHX8H1JsOhQUqvLL81fIqAkWPANAmQ
-K4NU/ZSkkjtfTcJy5oYsVXjz0MyLKOwrt52j8MLZsUW/TIf5e57kPbORC7RQhEr+
-yMDT6AY3En8iF4h8mqMhwnQnO3U=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitAnyPolicy EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA1
------BEGIN CERTIFICATE-----
-MIICiDCCAfGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGEx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE2MDQGA1UE
-AxMtSW52YWxpZCBpbmhpYml0QW55UG9saWN5IEVFIENlcnRpZmljYXRlIFRlc3Q0
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCulajzJmaByVbyDkLDGhU38CXN
-JW16bKIyjnbsg1tPLvigEcShDVU6jXZt8gRlscw+5nINvdOEYD9l/0QEzonMhVRP
-0GFT8aToKcCcPBlmhIA0PJqChMNZBGp4uitZKXKi8F8lGo09eB84V7bGs5YvP1LK
-J/G7vkncZXQbCUaX0wIDAQABo2UwYzAfBgNVHSMEGDAWgBQpIHiUjoSQKUJLfKsO
-gyq+NVs8FTAdBgNVHQ4EFgQUhUkKnqSDJde1NS49+ClAYeMS9kswDgYDVR0PAQH/
-BAQDAgTwMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQUFAAOBgQDK4Dok
-Sw1YWZrBgRIF5omNPAn9ZimPP/+5QRuYz42bdOl0F3v0uID3CnVfk+7UHbeylW/2
-n2KlU7OeOk5/B/FtFEm9RFaQIoeMkZadszaleUIvZxkrYkkwd///I0T9LzBBKUGV
-gDbif+oCGUYlgqLCQ/aXPDWA0mHKwmHD3FdRoQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:29:20:78:94:8E:84:90:29:42:4B:7C:AB:0E:83:2A:BE:35:5B:3C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 75:3b:42:7f:44:c5:fa:ab:b2:c4:63:ac:10:89:84:e0:50:32:
- 4b:96:80:48:15:1d:19:1c:b8:49:6d:42:c3:4c:b4:bd:a0:29:
- e0:14:56:1a:1d:df:92:90:19:27:a0:b7:f3:1b:7a:32:32:2d:
- cd:ee:29:38:d0:75:8e:8c:51:9d:02:7f:92:a6:af:08:ef:23:
- 8e:bc:b2:a6:47:36:d1:9c:e6:dd:4b:05:55:1c:56:47:1a:40:
- 67:4b:01:bd:b4:d0:74:12:5a:97:83:20:d5:4e:a7:d2:bb:ad:
- 52:a5:ac:13:44:fc:95:1f:d9:70:fa:a2:05:fb:73:e2:9d:15:
- 61:ac
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kx
-IHN1YkNBMRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUKSB4lI6EkClCS3yrDoMqvjVbPBUwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAdTtCf0TF+quyxGOsEImE4FAyS5aASBUdGRy4SW1Cw0y0vaAp4BRW
-Gh3fkpAZJ6C38xt6MjItze4pONB1joxRnQJ/kqavCO8jjryypkc20Zzm3UsFVRxW
-RxpAZ0sBvbTQdBJal4Mg1U6n0rutUqWsE0T8lR/ZcPqiBftz4p0VYaw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4EE.pem
new file mode 100644
index 0000000000..1c375e882b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 35 94 63 D5 71 32 01 BB 1C FB 48 70 19 F2 ED 4D 8D 71 71 2C
+ friendlyName: Invalid inhibitAnyPolicy Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitAnyPolicy EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA1
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowZjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExNjA0BgNVBAMTLUludmFsaWQgaW5oaWJpdEFueVBvbGljeSBFRSBDZXJ0aWZp
+Y2F0ZSBUZXN0NDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKOzb2us
+Rap/gcyEbEwwK0iXF70rX0khyal5XsZa1RjAWbLF+wifYFR/Y1Pee1seu+5+Y9d5
+Y6OlpDWYZd81RunoYs10UNfSC+MdbLEJrqKsX9Ol/iDg3PaGnsHHqJPkPpnZgCxM
+9KgV3SxPXgg9UzDeFgNs142NbrFeCUjtU4s6Z3h4CRNUG08DTB06aq5c5PWnNJDo
+HGXkssX6+seFinJZC1S4og/wJOclr0g3+6rBw6aftcvQgsUMl1aeLe6adl9yLuYt
+HMopbU0wbgiGeNyjs/Z1/sZZ52xrsGCt6iUMZ6i+EAEoqCrwhNMG/zRUSDyXN3m4
+9lZCX4HJh9VGHxMCAwEAAaNlMGMwHwYDVR0jBBgwFoAUdKDVWNkrU9IrsM1dccah
+v0OnyBUwHQYDVR0OBBYEFBIkx7AI9TiDfo2NT4HTCl44Z0KyMA4GA1UdDwEB/wQE
+AwIE8DARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAHhbECZV
+VvZ3I4PTD5AZubZbJlT4CrJXvqc02fLFqiG5/n/XsEwIBAPBiHw+ni6N/10w9Sl1
+SZxkONAMLx688plmbZl1sq+uWVLo7Zn8oLte1ka5di5YteBL3Q9xgxTiT/n5gLip
+AamIJ2+Sconm6lw/ox2Bwk9GvQ1V9BhTCXZYpA636a2qwhgsgypHcvBtxxo5dpAH
+76B1+opjDl90vtMmOLYZ3DDmE05SdQOW3hu3FyOZWlo9hveSKp1jCpI9YTBh5xs7
+YtziLdcidNDuWF5qCrkAfJKn2bVIgWCV6QUGsa68tMzM2tX9PDEIulsjIrEy7TDE
+TWdj2tcah6t6zqQ=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 35 94 63 D5 71 32 01 BB 1C FB 48 70 19 F2 ED 4D 8D 71 71 2C
+ friendlyName: Invalid inhibitAnyPolicy Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,42A99473A944A1DF
+
+5zr76H83m6KniZ1E38SpAkE9Ha9JPtTrSaRfDt6p7We0CbiD0BDdBaTjy5iDnp2s
+CRAnwCuzfdLZNaYtc29N55KPfdWDoxp2uk9AVYovCPtWI8gPS5q9WUVw//MniWOz
+EgR13VdqTOMeW74wYvcVt4TBtTPZ468EbPUDSnrHU3htehvudOojgXKw2oeTpbVJ
++Yh9yWJoRUIhxkk1IoDK7+06Fb7Uxh29HdX6ZWxp4LPbgjB4iXV1bIp/5Ee2p0W1
+dhKu1RE7F1IPRdRG2JGv4LBQAPu/Roq68XvUNjqcnnTLC9M0d9ukTajwM1fcLzj6
+AxW40V3xT357tY34Swh+WlXlogfymD+dVIgkfS+lPPYhJxF0QpuLWLegIyRrbiVH
+ssu2p2phv+MjkcwKiMBWS92cJ8ev6p1E9yD8U+43Ri9TyES4xtz0EerJWMj/8AQ5
+PBBq4kLflT95PxdUlltfl9vpQE3USlOSCOx0nTTU0lOoKxRcVWmeuDPDF6dAAqEH
+vIW6SYX919Ty5glcLTxD4kyBKEZowecjsxxQHVSWL8C0/sZJaNz4JYYaUILgRcXO
+Vchs05mbh3d3Z06jDPleBCGAelL9hDZMlt9nIVqS0TJL1VtsuWbothe9npeDMv57
+h/AxQr8RCWMzslIKRRKsVchBjHfVieu659Yz6c0Ot3AH3jGNCn9L1KRjHZU9oAN4
+xLkw+iGgrMVvefiU3WW3BnDGmw1bjjIVO+sQl7aihtq6HinhLixYd8AMlgivsjVb
+RWWHt4NBBkizbHv2lRzwZOA1KNtw7RABmmyz1vbSQ+I2VGsyApADcRZMuYb7CnSs
+q8GsLhNkI6cag+RqDu6Msqs04yktB2mJOdg5oxYHhubfVGKVp+J3yhfcmHHY5/2L
+kiZRA0PdBR2CxS1CrDIme5ML/mwLAw1nbQatGnJIihey9wgalJ1jPSMiyEMcA2xj
+0p4FHsWGE+cUtRurogz+FjpKBlagriTqesnEYOsMRXM+Z8wyKoGJXmoB8uZCippa
+wdsb0k3qSiyZitrs4ZAENKza6BQJGM8+27T5jP0HOjCM51imH2jPgHFFn6Q5XjSI
+mpZ1mp5IGF3qMAr1Gi3/aDZxSC3Q2QWC9Mpd9gsyjZdAhFd+Vh+3BUmd106/LI74
+qBsGGd2PcWW0S8e7wq3GxPqOOvz4UPfCyYyEgaAoteW77ysTDxBcRCDv322Yvz+U
+FDWH7her6L3SraX588aZ+sxqRH/NLoTKwf288bSFJTXzIgYbt5NYR+pBSip1gjpz
+HLISC/jUtDUL8WSd1YLGjwe8J3bay49F9vsODmrm6w7yKyNbYvzxqHHdoLPtLLSr
+UHRyCQsGez2cxJrR9YKdyD/wkY4TvK2S7aI+C2dt/Qk4Eh146UHAbjupe/ls6jW/
+POPOJm5z5huX8D5w4lGnAP3/8++8RTabbTNuQtbVVZP5bAN2raKJbR2e4QibZHrC
+U1u/A5xbd9Wj+8R9fSH2B60f7416QVzyZ547U5QgI6T0M6Sm3fkFUFpUO4f84W3j
+Ep0CV7eKYtUwFMLZDaim8rcahMN8RJc2LOwfElpKA5M8fLEww34pSzHa6vpPoi+f
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5.pem
deleted file mode 100644
index 20f42c20ac..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5.pem
+++ /dev/null
@@ -1,210 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitAnyPolicy EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy5 subsubCA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGmluaGliaXRBbnlQ
-b2xpY3k1IHN1YnN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-YTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTYwNAYD
-VQQDEy1JbnZhbGlkIGluaGliaXRBbnlQb2xpY3kgRUUgQ2VydGlmaWNhdGUgVGVz
-dDUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALJx+sbJu7vInzoWetJ2rz0L
-6GPGRCd/xtyjMfyMSExsWdgxczZPdBMn9ON9XI/ASBPwvhcoq2pB9VqD+g2X9tfV
-y7usPePkKYweFOPmIlrWZb9tAEfTgwkoHYiWEWazYt+6y65407713raA+9DmYQgX
-m9RHrTFiSVJ3Z9RAtBEHAgMBAAGjZTBjMB8GA1UdIwQYMBaAFHMQBPkM9GScsvEb
-je+3VaqkohmvMB0GA1UdDgQWBBQTUueG5HoT3TWlqqICt/b/VK5ROjAOBgNVHQ8B
-Af8EBAMCBPAwEQYDVR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBBQUAA4GBAEp6
-lUPLqrzZI5cW9d33rfE+6PJIi7fI3T6aRuc2eG0GuaiGnwOJvwDXA1uHC2GzbiJZ
-U61janUuTgxWCdE7uDZFU7f4M6Ws0V/RP0BDzWca9mLZenhrmNFYwCp+9ve9QMMx
-6WjbrV0PBuEStbrdAH4wRquSNws7JKnHrpW2O88C
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy5 subsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy5 subCA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF2luaGliaXRBbnlQ
-b2xpY3k1IHN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSMwIQYDVQQD
-ExppbmhpYml0QW55UG9saWN5NSBzdWJzdWJDQTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEArf8a4YQqh0caACibKN+ne7IKGYWnwL8N2E4534sCUjlfic+5O3/s
-ELf3kOpyOfw7NMoMTXQcsi+9wtB24eilTbHwdStKU/Mt15FCe5go7GepA2TbdomL
-3mKUocf87YN4pZc8QBPA/hs5sYPbnCx4X2TK2oCNCwvfUgWWhnCN2mMCAwEAAaN8
-MHowHwYDVR0jBBgwFoAUSndiWCMHosO57sdu3+0AiYhNl28wHQYDVR0OBBYEFHMQ
-BPkM9GScsvEbje+3VaqkohmvMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCG
-LcmSqA61BeAN21ekDRt5DAa9UGDAU8Bp/txAT+4H81/dzp5710w8QBHUcViEoL7l
-Znf4/IR4isqKlRS6ctmN/K2BRJ/19TQiYN8JiaZQAluzpLlgMUV4iC+/JwZHnJZu
-2c4mhWPSSBfUqHME3sp4dQxsrZNou/yOwzhTjmsNVw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy5 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy5 CA
------BEGIN CERTIFICATE-----
-MIICljCCAf+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3k1IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSzELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSAwHgYDVQQDExdp
-bmhpYml0QW55UG9saWN5NSBzdWJDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEAqzUjeD5TJL7TtPxRXU0nMcnBDmkPWyIAC1pNu3Tv0XwSE59I5Wr/Ytc+wMkJ
-dM4d1IFPKtN+MlzNv4dHwxOQrb9Fi3ItNVRIOLRIttgQFMvCWl0FTh9svTC8NIUZ
-lKD8zzDoBGD2ZEwHTYX1qLzneeTf3hMN4AyvxDVGekJWsdECAwEAAaOBjDCBiTAf
-BgNVHSMEGDAWgBTGAIxxpplipn/SVG/ybgTKMLU6vzAdBgNVHQ4EFgQUSndiWCMH
-osO57sdu3+0AiYhNl28wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZI
-AWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GA1UdNgEB/wQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBABOzlfB8CEJvHMdfoVtuMRmwTdF+Ypyvb6ileMKr9P+8j4gRzVgr
-jZiHkH/a8ODtOat8ADR9USeVUAMIv2LZnw33x6xKWCZNJCwPysTVz72PLIPQ+2c0
-yeOayIZxdJb9hidU7BT4q6FdbFecUUgSZS5FySOod8WI1jYTyHNEZeLa
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy5 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTUgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJDz7OZ8u34K
-hjI6cDaSvyyjIWPPGVdObfPls5iLOT434gz5hx3uyX17mOJnw+/5rOgcqatRDJ1I
-mAI1pl0ZUVaaattiyBifI6LONlUpzVOmtr6yotsGY0DiCmtKBJh4geA9jQl/UCou
-of64Smt1vsIL3SqiWkqCg0XFrXpTCCz1AgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFMYAjHGmmWKmf9JUb/JuBMow
-tTq/MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEFMA0GCSqG
-SIb3DQEBBQUAA4GBAGt+M+PIMRTWFAO2C58l6vCjg40P4NFF6B3LWjGcpPnRDYP4
-injOp/wD4IVvnXRpIFOq59qlJzmOJJDxCHGB11jkkxJK0v+pi7gvDrDw2av8wznR
-K735aiuC7KCpEy7tQ59Ive9M8PPOuQ+Vd3CgKhv0GuGNb/6M+3cojz0fCNx6
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy5 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C6:00:8C:71:A6:99:62:A6:7F:D2:54:6F:F2:6E:04:CA:30:B5:3A:BF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 4e:c7:09:29:78:ea:ef:43:a3:de:f8:6f:a5:b6:13:f2:ac:8e:
- 93:7b:ce:f9:4f:12:e3:48:f5:f5:1e:47:b1:39:20:b4:ce:33:
- ea:bc:72:c1:11:a0:ab:75:59:68:03:68:dd:c8:96:02:1d:73:
- 7f:fa:39:9d:2a:88:ce:53:d0:3d:73:27:d3:61:6f:d3:75:01:
- f2:2f:f8:02:cb:d4:00:63:71:eb:0c:84:19:10:d9:ac:48:6d:
- 77:8f:3a:23:36:9a:63:98:4d:9a:16:bd:bd:08:1d:77:4b:59:
- 98:21:d2:89:fd:1a:f5:f0:70:86:40:08:c5:be:59:5f:de:a8:
- fb:f2
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3k1
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBTGAIxxpplipn/SVG/ybgTKMLU6vzAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQBOxwkpeOrvQ6Pe+G+lthPyrI6Te875TxLjSPX1HkexOSC0zjPqvHLBEaCr
-dVloA2jdyJYCHXN/+jmdKojOU9A9cyfTYW/TdQHyL/gCy9QAY3HrDIQZENmsSG13
-jzojNppjmE2aFr29CB13S1mYIdKJ/Rr18HCGQAjFvllf3qj78g==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy5 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4A:77:62:58:23:07:A2:C3:B9:EE:C7:6E:DF:ED:00:89:88:4D:97:6F
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 86:aa:0d:7c:0b:72:97:47:34:6d:6c:97:58:2d:d9:6a:0d:c5:
- 8c:df:04:31:39:f7:22:cf:a8:20:3f:06:71:91:7b:72:cc:08:
- ae:bd:b5:c6:21:ec:95:a9:7c:95:8a:4d:b0:f5:ab:ff:0f:bf:
- 5c:24:8f:01:fd:f6:1b:d2:08:61:ef:d0:8a:6e:84:29:cf:6c:
- 32:bd:79:b6:bb:e1:cb:71:c9:ef:eb:17:14:fd:ca:87:4d:c9:
- 54:5b:47:ee:f9:39:c4:9c:c2:fd:64:0e:2b:66:8d:0a:a8:6c:
- 83:9b:07:e4:fa:5d:8a:34:91:99:e9:9a:0d:34:60:7c:0c:20:
- ba:44
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF2luaGliaXRBbnlQb2xpY3k1
-IHN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBRKd2JYIweiw7nux27f7QCJiE2XbzAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQCGqg18C3KXRzRtbJdYLdlqDcWM3wQxOfciz6ggPwZxkXtyzAiuvbXG
-IeyVqXyVik2w9av/D79cJI8B/fYb0ghh79CKboQpz2wyvXm2u+HLccnv6xcU/cqH
-TclUW0fu+TnEnML9ZA4rZo0KqGyDmwfk+l2KNJGZ6ZoNNGB8DCC6RA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy5 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:73:10:04:F9:0C:F4:64:9C:B2:F1:1B:8D:EF:B7:55:AA:A4:A2:19:AF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1d:c7:8a:0a:91:d4:7e:b5:29:3b:00:db:72:e0:8f:61:ef:9a:
- d1:b2:cc:11:bb:06:bb:aa:dd:6b:aa:76:8a:44:f5:57:b4:d2:
- ae:b5:28:29:7b:eb:06:a6:1c:c9:de:0c:61:d5:f4:6d:df:76:
- ee:9f:d4:00:6b:29:2d:15:18:e6:cb:02:52:4b:48:38:4c:b1:
- ed:4e:50:1d:60:68:92:85:86:b5:fb:98:d5:b5:1a:52:ba:a1:
- 7e:d8:22:fe:b4:f1:04:b6:8b:6d:cc:5f:1f:dd:25:a2:a6:42:
- f0:13:60:de:bf:2e:fb:d6:38:dd:ed:ec:ea:7c:dd:5d:f0:a7:
- 4a:c3
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGmluaGliaXRBbnlQb2xpY3k1
-IHN1YnN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBRzEAT5DPRknLLxG43vt1WqpKIZrzAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQAdx4oKkdR+tSk7ANty4I9h75rRsswRuwa7qt1rqnaKRPVXtNKu
-tSgpe+sGphzJ3gxh1fRt33bun9QAayktFRjmywJSS0g4TLHtTlAdYGiShYa1+5jV
-tRpSuqF+2CL+tPEEtottzF8f3SWipkLwE2Devy771jjd7ezqfN1d8KdKww==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5EE.pem
new file mode 100644
index 0000000000..a9363a60c3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 45 86 77 29 4F 2D 37 B5 A9 F8 51 C4 B6 73 CF 2F 85 37 6F 80
+ friendlyName: Invalid inhibitAnyPolicy Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitAnyPolicy EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy5 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMaaW5oaWJp
+dEFueVBvbGljeTUgc3Vic3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBmMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE2MDQGA1UEAxMtSW52YWxpZCBpbmhpYml0QW55UG9saWN5IEVFIENlcnRp
+ZmljYXRlIFRlc3Q1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA195F
+jNz2GSpq6/NfJwsI1oWaPDb/TIRaMvsEhof4Du7/nnHZLHEKCHncySsw3S1wqAaf
+gJCqFiOuUUQNc7KORn2p3OQjnQ6Rx+bqFTRFhUopVriqtIohLh14uvN30gZCwz4b
+cw7uw2I5uEzPWVZjF6gnY3p+mVHCRR5+rp7glk0TIzOUDK8nvu9iUUPB88rRwlm4
+4CwQZPMCnd7+3TEcX2Z53do2w7OStN/J28/tuEO7CMwYeOFZZ+Umy3xX6fD1GHTa
+d3aeqdKGHpTs3UzKS55z++st87x9o/9SDMzDhzuiJv7eVtW5w/df8B6YCXZajDq0
+D7pcygmL2EZsRbvpuwIDAQABo2UwYzAfBgNVHSMEGDAWgBQx4T/8Ym6AZc2peRAA
+K26JWugFwzAdBgNVHQ4EFgQU7ezFAtleK5pOd1B3fpcAOhJ7b5QwDgYDVR0PAQH/
+BAQDAgTwMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsFAAOCAQEALvsV
+SM9/5C8mjAMEOnsUzL6HCXvgRuQ8nHmTEDTOThapesSndUMoJQMPlXlCbeRP1apB
+zUsPuavZxi4DAmSs+xdge9QLVDbVzf6uC698FeHXKMoVs77HNKFQOpWATB9J+1OL
+zgSzZYGdrFQyYl8rQFdrpXTguzMDKAbCcyQiSoSGr4zlHg2yJXUP/nxtgsDVqYfF
+SIpduRdnil3dV5h9GH/74QIqBZC/9sKO6jVnxD0RbIc64nL35LoVlMFSke4UBS6Z
+PmcQzvnfMtpK4Gi3v4H8btSpKstdIt+jgUpgz48xzejGlaRX5Ad0MNgNjFmN61ib
+XANJSNmGQZWK4w1woQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 45 86 77 29 4F 2D 37 B5 A9 F8 51 C4 B6 73 CF 2F 85 37 6F 80
+ friendlyName: Invalid inhibitAnyPolicy Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,56DCA0D712C9A6A3
+
+k/kKgh/wqFfQslGzpJ0/Vqt5MnfjMpCCf9qmbLS856/K48AUhDnY2bkLrC8PP6cJ
+/aykfk4CNZODl+a8xh3G3CBdKsCH92VNhKqtAQdNHVRNJJA8CA95LsftMhUZ9ajM
+52KWmXbbB1H/wCbV5ZcNtvnDtTJGGMAOmYBvxpynP9+aVlFuIWiDYdoINv2NZR/K
+Qixw6k475ERS8nixxNAOiDtoZZ+vy4xSIIrMzkkQ2hlqklrzB47uBn2UORtUuot8
+TDhpNo864EEKb2lvRW+AQ0EM3zvpO4Px6vOVvS2dGv0eSDsmNWZh99ZABtu3WHPX
+3nAqQTSAI6zLmRLVq9rCeD6eX0YfvdtRty8eqJbVp6N9pz2ejudAfX3bx04kmXK9
+CXlqOyXo03iprSe8EACZDFvB9p/lCS1MCkNBmq829zC3VVyGjSMNP6JJ7+mxkhwd
+MnnjJ8MjR103FE7gxnsE/68wrJN7o740yuV5AE8axxJtaGpafjc/D2KlfXvxnjyV
+078BFgp3u3lFHPEKPEwzJePvnbC+yE7nxUbBKoLyk58+0ge7eQAbgwyLLsQws3PP
+nJukh68PubJEXveMAK5+o4pVqEG86EcCwRQ2M/VkpIPTcw4YIZaS6BlbLqcvCLL8
+QSg+N15RsegNJHq37Urdq7gXLwoD5EHnPWn3DjL8sqDr9p1EO8Z4im9fE8aCMaW2
+K3zOiIoAWlZEHTrjkg2gwcpbCMIuB6wlxm+4sF5coUdcRAfVzPO9c5730xA9NSHc
+gdkcMooKrte2HqrpRxI3qR+J4501ND1YIIdnJS//ebKVy1UMT/m9/+8Hz2i9h7Bh
+vk2xZE+F8XW8GVDftCKCi4Hhbo2DLGQSNYjfpqPW6M0chdtEFCECEJTohso0/2hy
+OYq9MChRUHpsYf8r046lnB/kiKHZBB/Q/9wLeEUC1+/P9WPBlPvUONJtwVl5hWdI
+lwxy0dg/gvo3SxVetYnbqQIz4RrHpQj8bD5OInUVkzXdy7ESTj4pNb6cJjZsW/ym
+7thBFsJza/XcWPuwvUB53YHy40SqqYUJ4LL/yEYB5SeDZv2ykPC6W/p5f1kGzGMr
+wIWKxzoyfRuEbHM6ckn/kZ+qVzGUJl/ErPwl5gAZXl67Y08QS8AdzvnJ/niUty4+
+ia3Q9KgssqS2dCQgXkGNcsapVk3CH/7srxrB7JtHnGok2vr83+JaZixQCN7iXaDD
+tHNh+ODJ2h+Pq0mWUr9aX4AA6W2ar0JMOdlEoHQPpAnDDVyVX99oVkqydASefToX
+i7rPun8430TLGXmfD1Y4Y+6EvhioHgCkTgGQur9yhqf8h9BGPVULAfzjiBj1blwS
+6sIMn0u3PwuoekTeW0E3Dz+EqoYsoTE1HigHnigt5iwG5+zJJerpzCPI00JiNgYc
+GJRAchiiHxKSognw4rjOQb9ov0XmN7YHYXk3jQyhQVuw2eHeAvKdnrTSZvGtzI0O
+8+l3bQ45GlNtsjpNohUBw9QKyAELUHGrPpZ9YXJxmN8PMYSywL4xIs8pCc/3nmIy
+ApVjOExkqMfFpVv1r98zVuAJvgx5b6ANgCWOKd5+gud4h5c0WRgD4S9kOppwwyMJ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6.pem
deleted file mode 100644
index ed99033596..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6.pem
+++ /dev/null
@@ -1,159 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitAnyPolicy EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCAIAP5
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBSUFQNTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MGExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE2MDQG
-A1UEAxMtSW52YWxpZCBpbmhpYml0QW55UG9saWN5IEVFIENlcnRpZmljYXRlIFRl
-c3Q2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDmovuW9G83CLO5Kfr9ogDW
-3M2PMCzM46Btwj9BIzBg6T+Z0toxnoHQHTRXf2tp8Nj5bLXb66AotgJeHWXGrGxI
-Kjx0w4OKRuhiBVjMsT7gJmbmJ9neH+D6gfc83LPzHtMNrH0OPlfAEiCXGfTeHBug
-bMfQlc3WJ747aWkIv54emwIDAQABo2UwYzAfBgNVHSMEGDAWgBQFKWMS3ubCghc9
-e190DHOosBJvaDAdBgNVHQ4EFgQUswzkrq5gD2HHDjnsZYw9qjeh7WEwDgYDVR0P
-AQH/BAQDAgTwMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQUFAAOBgQBl
-Ndj1mSjoh6od200M/46rSMjCcoQ92FMFygp/7mEK3MomCWTKikCKTp1xDYS20vE6
-R2hCQlhkV2nRYNoSLvYM88uba0diTZDbX+txbiJ1DX82U9f0/zpXhCVLxc962ftK
-ZneaZF9AzYxqTvGS1yOwGFV7jimzg4ZdSKWcUX44+g==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCAIAP5
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICmjCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTzELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSQwIgYDVQQDExtp
-bmhpYml0QW55UG9saWN5MSBzdWJDQUlBUDUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBANW9X4Le7QZci9gVhxS6PY2u0Fxe2EtutUH8zZO66QHNyygwW510D4dQ
-tOvvKfuiS+Ciu2PV2zjc2AcL5U1x9j6hGKIl7NbVFo+mZbBV6GzWLP+oaTy8oz69
-BNSDXwFW6FPTOQbaiyRa8f4nXVFl3QQYM8jTdGGS9lalXnxusSE3AgMBAAGjgYww
-gYkwHwYDVR0jBBgwFoAUZtu1lMcFxLM+K5G538io0E0rNEQwHQYDVR0OBBYEFAUp
-YxLe5sKCFz17X3QMc6iwEm9oMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgNVHTYBAf8EAwIBBTANBgkq
-hkiG9w0BAQUFAAOBgQCzfOac7wbFryN6VSS2bfYlcBtdLypBJugZaDururS3VvRk
-Y9SVSAQSh/m+ydbzhZ8LyNw7e7Uj4mjGuyFzznlAHsWxyO0JTPbhUwutJ3QrQhJW
-kIbsGR97otFLnmhZwotzU9dr0LhhJEqeyrM64zPoOT2SyhbooCh7Oh27eUSSjg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCAIAP5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:05:29:63:12:DE:E6:C2:82:17:3D:7B:5F:74:0C:73:A8:B0:12:6F:68
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- cf:a9:d2:6e:1b:81:59:22:25:1b:6b:2a:df:26:ac:ee:64:cf:
- 2d:65:1b:ad:15:43:22:fd:7b:ec:84:c0:8d:4e:b1:17:dc:9d:
- ae:d3:45:ba:91:2d:b6:7c:be:a5:80:5c:d6:e2:89:80:fe:54:
- 8e:15:90:f8:dd:e4:0d:c6:16:c2:24:6e:61:94:44:6a:fe:4d:
- 44:ac:be:fb:46:4c:c7:3b:24:36:10:c1:d5:9c:89:3e:a6:f8:
- f3:7e:0c:79:08:65:68:a0:c5:18:30:4c:d3:e4:c1:c8:7e:2d:
- 9a:65:b6:e0:84:2c:b2:58:e2:fc:96:8f:95:13:cb:e1:e5:fa:
- e8:9b
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRBbnlQb2xpY3kx
-IHN1YkNBSUFQNRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUBSljEt7mwoIXPXtfdAxzqLASb2gwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAz6nSbhuBWSIlG2sq3yas7mTPLWUbrRVDIv177ITAjU6xF9yd
-rtNFupEttny+pYBc1uKJgP5UjhWQ+N3kDcYWwiRuYZREav5NRKy++0ZMxzskNhDB
-1ZyJPqb4834MeQhlaKDFGDBM0+TByH4tmmW24IQsslji/JaPlRPL4eX66Js=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6EE.pem
new file mode 100644
index 0000000000..bc14434030
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitAnyPolicyTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 42 42 4D 29 08 2B 18 F3 76 C6 31 67 2C 5E 89 BD E2 5C 75 00
+ friendlyName: Invalid inhibitAnyPolicy Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitAnyPolicy EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCAIAP5
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0FJQVA1MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowZjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExNjA0BgNVBAMTLUludmFsaWQgaW5oaWJpdEFueVBvbGljeSBFRSBDZXJ0
+aWZpY2F0ZSBUZXN0NjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQU
+JVlJJR67nbtRHW3D6vzK+HBOXh5S097ZMQEPce170libKgRiLesqEC9fNpzls8pN
+VPwxOcZOgaHes1XlzdDkbf4TVXuprfJwcvHT6KWfzIehUopULihB/oJuMa289M0q
+VFhS0XAhzLR8KPzNjyqEew5g20u4uvpDG2TQOO4QQgLJ8nQEtQuSTsAPK8E6d0sD
+jgsHLOGETorVSgjW7zSIp2RZ1dNx8AEGm3l7tCl+xhkzKl7Me2W2qXJg+Iy17Jl5
+0Ik0uj38yZaUt0LNuddEQaqZVGwh+19uZdbj8wD6QgHcF8sUBLeOHbKrsI8VaGvH
+SHgiBW8dGWLp7rETQqkCAwEAAaNlMGMwHwYDVR0jBBgwFoAUiQRUdAZgs/cAbqBh
+jhX7vlICBiYwHQYDVR0OBBYEFAOX8L+bVJZR0b0hAu1UhcFEzOxMMA4GA1UdDwEB
+/wQEAwIE8DARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAFFd
+fv8IwDnGrwxVdDqlMHz2fz7dZOnpMPRX5sleEzs0q11YJpVWu2VZJhDtqEFoLtZ8
+7HRCdkeN3kI0RWsXhj/j5F1UdPKu3exA5aQ/+BQeeboF8DqbawC2kTf71cY48sS8
+ECgGbXmd4dNI2ByZjMLVsq8ow9566ZpJZsfTEAw0dQ7TU9/4fasWSQ7LDFK/N9Z2
+hqUS5eIJdveMB2HDL9o8pNohsA8smIfX0ARKCkcEbMTjLjEABcZKtK+y9cwdln3p
+hQoA6GPCFY29vEqaq/T8XMNcWaTobelNsDMgKD9GZfa1CVnh1rwDve4f3PairHKm
+h+iOTwouhOvswtsridM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 42 42 4D 29 08 2B 18 F3 76 C6 31 67 2C 5E 89 BD E2 5C 75 00
+ friendlyName: Invalid inhibitAnyPolicy Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F9AA48841E5D1B2E
+
+B6CcWA4SnOnxWmixvDlAO44VUbwuTRWzqz1Zwx66zlVkLDwnyxisRrBKzkx7TY9j
+IGZ3nT2WDSsmRifc2Up7iwO+e3cHJPgK1IMxEAzX+W/0G2b9oG7Y7FObIk9xF84/
+XHwy5yVzGVKfskLiXSSUS3y7v0KFDD1hs6XyZ7ZhioG0Dzkpka7BcgZmf/mwWIxB
+uXmFY1pMs1fIrSe7h+C8JSoYHk7mtD9GWin5SomqI8/MCEDUmVr2/5+QiKgg4Miz
+C9wAUM97wfo1pGhNRtHpfLcm7pliZ9bh5bYYhV4J1CnCSiwYmYJC2WMk9z8107kE
+wMYYmDORSuKkxLDD760jTeZ+T6ggnfocZQjZG7cBZG8lfji7S06mFK9y5pkd2a+z
+LQQPCmGGCZ7jT7MQgdqitw7x7iR3KNaPXECitVS8doMbL1g9ueo4rNJ/vblD8tDn
+H5gTbaLv9MzPghyvO/Pk9HHK1uT50nTpEKVjNGA5f+soB8/1dDZAMz/hCma+4qhL
+anN0QpcW3Cg7WtFjpoGV0UDqd+XAwYT8niWwaEz4YCvRFOqKk4UbnQHobxaPWuI3
+iXyNSTk6FKx8L08j58vqFHKnxLMVUbOLokq8Cm6oDEIKQO1Xm2h5/Lo7KTWCSXEU
+EnGbVMWy6S5+qjvUDp4A10GIxQ5G3owyhanv94arbiGSmj2CJIR5XnjUwxKXdRR/
+e4739AqJ32kbSWu8/aFnYrCsy5lrtuvikLQGPERAT6UgHXNC+hoWCEzu62K1//PK
+35GKaS1V437hJJfzdrxboJSapEe4u58lBOy2ZWiJMT8UWxrQzwPWXgIgrZppet0E
+9Ep/3cgvLbydq1Tipg6YXXUn3+RHWbdzH6tVjIe5yU0kQtb6UlevC27xau+1tb0K
+kyCh96ZlHrZuoaLsFS0QnTOg+f4w4M/EBLkgjd/ezU9TSlLZibMK3Y/OGf5uoxlj
+TCqGkoPgMI/lU7QbNBu/ZOPEBIxXAihVwl5AQeCBldj6kWYFw8DqUG0lKEYceEdg
+TeIKQQk5WMZ1rWLIf+x7Lm4HxCW3gf04yExwWW/o0EXieE8m2vwFrCYTV9iGVUCO
+rq1/IoCNNjnVjYJdFol633/xPwVYeCCzoOU0ulUwHjIzPE5FW/qRKKnlRvVg/V7T
+NZuGDuNhHAtRldXpMgDFH+3/iXjQ8jNFnbQmFhY2QxogPSt9O0f+oSk5dIjgsTXR
+qizviC+Qz9AuB1e2h+98kNog/e6c9bFaF2H/j4AdX4H1t+QnILEMW8tTwNRcN1aF
+khpI8fpx8PFrLCTx41meBYJYTwfSQErat8/OafS+qf21rMG0OeDbFRSBs32/7IzJ
+tpRpATwZphMks0ke0y5r3b7ey4Vs44AsuJclBryecfMzLbbP1BP1wgUnOAb1U+Cv
+h2JaN0VRjS6MCdTjNCRamr5n4HQJ5eeY48iD81skBuVVsV1GjrTqKAdZ2R1eRnA5
+1ApHYGMepNuw6VcONLoyQxOVKx2/vBEi4SK9g5/IhQ875TKsyZrEQ9wiZ9EylFAW
+OipkcTblhCJ7n1+lJHazw0hlshnIqAdD3HxwOA1EmFJX5XcummtU/ZT9LdLr3o8r
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1.pem
deleted file mode 100644
index 785448794a..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1.pem
+++ /dev/null
@@ -1,161 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClDCCAf2gAwIBAgIBNzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMYaW5oaWJpdFBv
-bGljeU1hcHBpbmcwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQIzx8
-7J8x9DkeOhXlBG/eAUo6B99wk9uPjSwrZ7f+CXzaECXTCOk88n35mahe/lgpBbr8
-ujs9D6bCgS+AVciyqJAtZFW45FX6xjb6fcLzebF4HTOpBYVxkqlJ9nLLCkaBHMIq
-1U5jR8jDZhgTnMBvNm0yBdNFo6Lh6A5d+Gr5jwIDAQABo4GRMIGOMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBRs6ccKAUJAQfXzcI7u
-4dFSXtc3WjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBADANBgkqhkiG9w0B
-AQUFAAOBgQDR8om42wMsHX434zvF/Yl3Lm4GBdFmFWIiRNpqH5iS8X1lGbi1pEAg
-m37Pvvobd5tcsZd2tsz0/DOTvntZhUdX5rmvN4x0i3JUXb9bOPMDs2iJs5oFF6Iq
-TSk9wJXUwsPy3ltGGWpU817s4uj8HU3tffkyOyc7j1u3l8x2LJWPvA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitPolicyMapping EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping0 subCA
------BEGIN CERTIFICATE-----
-MIICozCCAgygAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMCBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MGUxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE6MDgG
-A1UEAxMxSW52YWxpZCBpbmhpYml0UG9saWN5TWFwcGluZyBFRSBDZXJ0aWZpY2F0
-ZSBUZXN0MTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsNiBmaKBCN2+twi8
-zZHkggWucFtI5ZszQOXjX8ivFQMOkIaUz2HqFIeurNmSEN2Ta8WHJJ/thRgpUF4l
-p8ovjgthh7/tScnTlJMN60ros1uQl6+qm/dzqn8kQ42EGLA9n6Ut5LuJ8AGCil+L
-9TFs7vbPktHo0h2YcwCvEjyyZRECAwEAAaN5MHcwHwYDVR0jBBgwFoAUMLGv3K7V
-MPIMOabjLBUhOK+ii9AwHQYDVR0OBBYEFDO/lIeGch/Q9DaWzigYcWwKxuVBMA4G
-A1UdDwEB/wQEAwIE8DAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUD
-AgEwAjANBgkqhkiG9w0BAQUFAAOBgQCKhd9JcXnw+W9w7fb+IhKEeepUh2J7y4w6
-11+U8Skm7KgNeSHdCzQjFMqGyeoJK+XV1j21mGK1YqXrbLjo+fHbHF68tf2rzWTC
-Y2igOFwDQFpFFbqrKbYogBOuqR8TCR3LFH9mypYIqbcfiohQF5XSwMnyNEzDc8WH
-hEapxbpusQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping0 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping0 CA
------BEGIN CERTIFICATE-----
-MIICtzCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRQb2xp
-Y3lNYXBwaW5nMCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8x
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UE
-AxMbaW5oaWJpdFBvbGljeU1hcHBpbmcwIHN1YkNBMIGfMA0GCSqGSIb3DQEBAQUA
-A4GNADCBiQKBgQDWkQsHOT5qYxFfYJsGV/LbLwMtr5DBFdB/k19gzvAjYpjlKgVD
-MgfJDc/d3WyMB8t5oICqdJDVFEq4JBU+T/J27G89SJusZSRJdmQXogfiXWHSOXtA
-f3Z4IcRxAwjoNJaF6n9LR2q5YTDIoiEK3+h1jhOiNoFwYmvTajzcJ15SKQIDAQAB
-o4GlMIGiMB8GA1UdIwQYMBaAFGzpxwoBQkBB9fNwju7h0VJe1zdaMB0GA1UdDgQW
-BBQwsa/crtUw8gw5puMsFSE4r6KL0DAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZI
-AWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAKnjTqcv
-cg3JfloLHCOwWWPdk64BNIs0gLMI584sPNdiQR5bCz4KCoKMzvzIEZDL+kVo6RnR
-l39fdQ1rIbv5lE6nUVlTJNcj5Mq66NMsdVFsz5plRGUN4YpEDhz30hiwjkoo/B6N
-Bs76rDEC1VReVfNcwcglyKXIIEjHTMMsG0GH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6C:E9:C7:0A:01:42:40:41:F5:F3:70:8E:EE:E1:D1:52:5E:D7:37:5A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- cc:98:13:01:ea:eb:7a:16:12:f0:2e:66:3a:2e:6b:fd:c4:2a:
- 17:89:46:64:18:5a:ca:d2:00:55:3e:bd:00:bc:ce:f4:76:7e:
- 68:bf:f2:73:cb:d2:04:b4:e4:b4:21:6b:e0:4e:ea:c5:61:20:
- 3d:b8:db:61:e2:d5:27:19:48:65:cb:47:d1:66:3b:29:a9:c7:
- 66:f6:11:09:2c:48:9a:c3:37:a9:b0:74:16:91:b3:d4:ea:90:
- 2c:af:a8:4a:6a:1f:4e:fb:40:b0:e8:5e:13:58:f6:cb:82:53:
- 47:43:79:ef:05:89:6b:5e:e9:99:1c:1e:83:07:10:5d:40:ed:
- f2:06
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRQb2xpY3lNYXBw
-aW5nMCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUbOnHCgFCQEH183CO7uHRUl7XN1owCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAzJgTAerrehYS8C5mOi5r/cQqF4lGZBhaytIAVT69ALzO9HZ+aL/y
-c8vSBLTktCFr4E7qxWEgPbjbYeLVJxlIZctH0WY7KanHZvYRCSxImsM3qbB0FpGz
-1OqQLK+oSmofTvtAsOheE1j2y4JTR0N57wWJa17pmRwegwcQXUDt8gY=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping0 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:30:B1:AF:DC:AE:D5:30:F2:0C:39:A6:E3:2C:15:21:38:AF:A2:8B:D0
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- ce:d5:06:91:52:5b:f0:21:b9:9e:d1:3b:5c:d3:17:a9:f1:b7:
- 70:51:ab:64:ac:d3:3d:4b:e6:bd:eb:68:fb:0b:45:7e:04:45:
- 4b:26:b5:fd:ca:66:7f:39:9b:42:2d:bc:1a:56:92:65:39:2a:
- 28:6b:d3:6a:7e:6a:8f:eb:c6:2c:3f:29:1e:73:75:9e:dd:01:
- 19:29:e5:d4:5c:fd:d8:ce:15:81:35:f7:8c:45:19:1a:64:35:
- 79:e2:00:cb:3c:38:56:63:11:38:05:07:c6:1c:c4:27:61:fb:
- 0e:a8:b1:1a:3c:6f:8c:e9:0f:3c:8e:ab:d7:3a:45:bb:15:4b:
- 41:60
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nMCBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUMLGv3K7VMPIMOabjLBUhOK+ii9AwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAztUGkVJb8CG5ntE7XNMXqfG3cFGrZKzTPUvmveto+wtFfgRF
-Sya1/cpmfzmbQi28GlaSZTkqKGvTan5qj+vGLD8pHnN1nt0BGSnl1Fz92M4VgTX3
-jEUZGmQ1eeIAyzw4VmMROAUHxhzEJ2H7DqixGjxvjOkPPI6r1zpFuxVLQWA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1EE.pem
new file mode 100644
index 0000000000..2689b692e8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 71 15 64 2C 19 9D 4E F7 74 B4 7F D7 B0 5B 4D 45 4B FF F6 D0
+ friendlyName: Invalid inhibitPolicyMapping Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitPolicyMapping EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping0 subCA
+-----BEGIN CERTIFICATE-----
+MIIDsjCCApqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJp
+dFBvbGljeU1hcHBpbmcwIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowajELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExOjA4BgNVBAMTMUludmFsaWQgaW5oaWJpdFBvbGljeU1hcHBpbmcgRUUg
+Q2VydGlmaWNhdGUgVGVzdDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDN0IaRs5W2GuI+RQoATLnfq2uut62sjrBHpXm+/0DkgNuM/dfoGsYDLwBKfGn3
+qgoAo6ji6khYrCtR/+SKIurS8zuH+I/cYeiRZ12Ibg/Ua8/xKRbh/7nd/80SBDiA
+9CxbInnuiP+oHXSLf40ITa8aFCfrlPah71XFk5J7LBWKrGgNmQoA23m0tP1R8QWS
+OvvlxEVeQGazDd/2gQlr5t/cmbvzGTS7beiHjq+guzeoaERJ1oYldpvk9hYf2IsG
++MaVIyNLj935jopLVkAG5Zt1zVfYeSgm8Rxba3+S2OcCmHlAOM3XBUxBUVJN9WsC
+PkLXw+Dk0SAGw8zDQXh9a6+NAgMBAAGjeTB3MB8GA1UdIwQYMBaAFP+0c2JSjVyW
+OlqQrhq8uDx5gWMeMB0GA1UdDgQWBBRGnoIVM9ZVKmQsZhmhhwsQpoe8VTAOBgNV
+HQ8BAf8EBAMCBPAwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIB
+MAIwDQYJKoZIhvcNAQELBQADggEBAIYTbq4NLd0+LIfk3ppsdEzOz5LONFBc54w0
+sh386ycVC5SBgXxibYDy0oN238lmZoAjvx6TWgAeVMP7TRwPyjMrOWivYWN2wBQy
+8wE4g+Bo/NoLBzAHm9yaWUeILEG7xDm9Qpkj81Am/2jDJv4RTHkPqhC90Tbh/j9I
+itkoVftRQlxsXx0NxJoSsfjDoG4+0LRM5elYHfBIldlHYLQiPcI4z4YW5FgtIs8m
+WTAzVduck7L/ttW00UBYyWjek8HE6eDkTJFvHFfwOQ832M6inyBLrFiB0lD6w/qH
+wekDTXqRelr/dtJvG0LpHq8/dEZeachaKBkm1oJoLKARAFkZWtE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 71 15 64 2C 19 9D 4E F7 74 B4 7F D7 B0 5B 4D 45 4B FF F6 D0
+ friendlyName: Invalid inhibitPolicyMapping Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,588D74E5A29155F8
+
+QG7xbh7WoC9L/rNrseIj+nvQux4U7zOP9BdQSRKJaTb20ydKw/loQoSHLfDyR4OK
++qs2RFYTXuq9x0UwJVBZxVirlvkfikGaOaYX3PdsHyQJxgi5mvXkGzey9sHGPBOT
+qBkU/Bkn41Fle+UGoYesfQ3kZx2j0u8AN8C6r9EoQHRbOD8a/B0ls5q7n6YQ+MYc
+BfmELzhRCkRzBHkwbhBaurI1SfNIlO5ze/VTV0UzDZcRkpzBIiEYBKt3R/wV6rSV
+dEgrdFLgKk2y0a92Ai4GqevmtnJFboKUPb7gHj8hfInN+5M5po76ahHw9fpRlS0D
+/GYzw9Uh2R2cxMr7Gv10GW9MNHB9+zHoOa4v5RH+zPp2edttXAEUCFFFzi952ehb
+dwkJ8HVD1phftmSpmpy6RetpUoMlKjWyGWjE/A/WGrGvnIwrbPfFPo560PZDtNtC
+VUN4hZTiUYe+bf2tycKgSouPP9N5y5Y6t0eIFWh3U0A2YV+VFac7rWHYT8gDr23b
+YYvYdnR29W4M9g23rO65nb4+dMEOfLte1BgdI404/kVVNaBXJL7FndKnCYsUaz7T
+TaL2gh/oT2jA1BxTrJGy/koXjyydLMyPL9NpWETIfjssiDSc6AVp6MuT72Mz33Rb
+e53QYH0shuxRjJ9tQ+iRN85IoJzlzwhEwgo8QjMi1XCd3SIRArrbtzehgAb0HRxC
+QGLVF6mIaGeT7LkBp347v4qM8ezkYEhsF7Sh9Cpb9hxJMCBsv8U6rIyHQUV9xYfJ
+l6gVkis83Fqa1zLydbDIpFxyPO8t1qeCNXMU/PSgi3QQBeq2DvDREJel+eYCXNUc
+0GvZjQXs13e8DwrWufp2dIOW7FwgAR9BtkHSc2gbDoIotVBQPiqC0Yyy8vcSmpLf
+b+NXzqLm6MRTW6+i6qkEqeOVGNRQLyTFoBAiGpVsYhTqdeNMBAulkLc9Wwjbtemu
+lDmfjPoAq/funxct+7NMl+JI3UtmDfa8t6dQ1v5soYa8cby3vcN7pqb/Fe9GwSce
+pkUem8sffrM9Vr0EPNlKi27flJYtu9qbM4wn3JRfIkd5XIeyO0CSHCL5rVgvAHL8
+k6Q1HB0iIT3SJivlVT97ilvVhV5DsRlI52FYQj+a5WExHLgjdx7XtTqaUTnHMLnr
+NSbammoSyY4MKSrf3gNK5u76nMls4QmDumPb+DxDZGqQK/k041bb6oWblJeBQ0RA
+ZO0KHDfNNd+Ksi6dXCATAJ4jOfU9ohbq7kYGjhQZ/y+4/qhe9Z3g6mRRFg/ygc7B
+GEra8F2JiFFzYVqZbRcOeTVfeFsZJ5xP7RVtO4qFdjk+q1udkSQ+CfuEM61A8dXv
+2ByLevRVfAq9BxivadALLcXq6P/Q5/dcjQDB6U7ptgHdDHvjXcVQllGu7esgXLUH
+oK7H3GlRkwVRgdFbJehYEAnc+qee67J4V/QrOXQqaGi5V4i1KHg5RMpN6HDJnY2z
+d54v6DPMOE08xfVai8YSOXx6+mP0kPpQvd+66eD35WrgJf+Kct2uQGcW9SuIQW2q
++rCkdeAWv4PVJTMt5yT1J1j4vQYxKu4+G8QzngeSfCBYIU4rTIBqoRVq1H8Abtd2
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3.pem
deleted file mode 100644
index b1fe680fbd..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3.pem
+++ /dev/null
@@ -1,216 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitPolicyMapping EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCA
------BEGIN CERTIFICATE-----
-MIICnDCCAgWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTImluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBlMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxOjA4BgNVBAMTMUludmFsaWQgaW5oaWJpdFBvbGljeU1hcHBpbmcgRUUgQ2Vy
-dGlmaWNhdGUgVGVzdDMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKb7DrW9
-Hb+KTJCO7IrKHRUs3FihVXeQr2+m4mUyxOo1SFMZQq+7bojuyImkv08GBbeMXPqV
-RHdNWwVUgMMfynWekNRrlwGFNAfSKd+vxmPUTTqzH6fxQqCRx1CGp4dVV1o9BTES
-DuwmZurFPYEu2/tf6gnxaHBNUUsYqRdztXIZAgMBAAGjazBpMB8GA1UdIwQYMBaA
-FFqTS++Wnq4+QxYmpBgeeYui5pshMB0GA1UdDgQWBBS7Wt9YatmqgSrox0Q7yWRL
-lJU+9zAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAFMA0G
-CSqGSIb3DQEBBQUAA4GBADOVfkwUiMO6wkkOxQ/lMXr+bjJlFLz4nFQx7/YBmUBH
-cn7z1B8KAhf9SlqwOmMSz0OD/1ALmdjyX0oymWVB9RWyQyvvmin7tTZKBW0KdcQZ
-GKmRog0HaZ8rHx37ewB3ANJfyarjBABp9einu4Aj8ak+aePYU1mth1YNGS1YVwfb
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpjCCAg+gAwIBAgIBODANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxMiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-s4T6CQeTrbqUSlSczfx8iMSRK4ip9F4liS7giqCrZeZYEuP+/XoRZKzqmT3G+io6
-zcenL7cegP9DJnTNuZ1nHEoeJTlhQZq00PD1n33OMK0zhMIirByYBpabztuw1dJ0
-MKKcRzJ1AswgccI8seh2W1FXdFo/vGkDOkcD21Se0XUCAwEAAaOBnzCBnDAfBgNV
-HSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUj3Ywg1+jhUuQ
-FB4GBHs3AQUgJmYwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUD
-AgEwATAMBgpghkgBZQMCATACMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgw
-BoABAIEBATANBgkqhkiG9w0BAQUFAAOBgQCXSeQ5mEkpmqCHstAZJbAGVSNrj3ka
-eA0k2v+n7vDeZ+9F8bByDiBBz3RMTqmdZxQ6zroOPsw66HLxv5D7oJImbhyvFrnN
-uxPGh8hvvP67N7UT9cM0RAoIQHmoI+3+o9cqOnTIJWXXPyq5q08yTrUt1lzFyrcK
-wGB7PyQXRRDWjA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
------BEGIN CERTIFICATE-----
-MIIC0zCCAjygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-KzApBgNVBAMTImluaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgc3Vic3ViQ0EwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJiRgbTlXD7Tr33rE8bkM1fLhA/0RcC0
-n6UIcVb6xSELqRqVIpXK2C038i/3Ta6+eoiCdjT6kvQwsM9uMBJnB7uePzDzpkSE
-G3Php6MSbnAO+6LPrGFBJ0LNo6yXvsV3HQ1Uwh8iND8Yt37obPJ05PzfU6hSnMgV
-47YDMrmE5h+5AgMBAAGjgbMwgbAwHwYDVR0jBBgwFoAUF3qKMAb26lw2QA2u2J+/
-ub2CzFIwHQYDVR0OBBYEFFqTS++Wnq4+QxYmpBgeeYui5pshMA4GA1UdDwEB/wQE
-AwIBBjAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAMwDAYKYIZIAWUDAgEwBDAmBgNV
-HSEBAf8EHDAaMBgGCmCGSAFlAwIBMAMGCmCGSAFlAwIBMAUwDwYDVR0TAQH/BAUw
-AwEB/zANBgkqhkiG9w0BAQUFAAOBgQCh/ZM7m2L0OxzF6RXxeVUhY5xlTjRO0HGd
-0xOnDkOesSYfCI4gUflMo6/T9Ot67Vnb9mgzwWSEXB6g2R22/3DVR1ord/UgZFKe
-w4llbMnwRS5e3zjqLGsLeWk2ZdyjoD2vmKiFBiX+rlHvaLk+5xYcGEfOupTVqWMO
-OHuz9iinWQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
------BEGIN CERTIFICATE-----
-MIIC5zCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBTMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAm
-BgNVBAMTH2luaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgc3ViQ0EwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBAMX6LszkJcSryGVxfI4egJDv3zFztB0M+jGHKEc8
-uPkbpVlPSjM2LWqUOks/C1q34lfaC6J5O+V3/DmN7GjLpJmdjBDn7k/aqGeE7XHR
-Wns707M/rcEWxPP/ErMQNIsqSkvy92GtwuaG7wsY4a+KyB0YCdqikJr6oK2Cvhwf
-LmC1AgMBAAGjgc0wgcowHwYDVR0jBBgwFoAUj3Ywg1+jhUuQFB4GBHs3AQUgJmYw
-HQYDVR0OBBYEFBd6ijAG9upcNkANrtifv7m9gsxSMA4GA1UdDwEB/wQEAwIBBjAl
-BgNVHSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjBABgNVHSEBAf8E
-NjA0MBgGCmCGSAFlAwIBMAEGCmCGSAFlAwIBMAMwGAYKYIZIAWUDAgEwAgYKYIZI
-AWUDAgEwBDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAE3ZflJR
-6b/Pwip7bO1ZIkiym+8uTzlT5nx3CF4P5Yyhje4VKVqoAOdljbZoaL5x1Zdd733W
-MxbQk/QP+wziLjZJlnqX+lSxg4wUiSU6mGtDJ1rPwMsbiiVBld7iP5JhFAWoTg0b
-XJ0ZSTHABPtNeMg2desSHwfh2I5WtX3hpXwE
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8F:76:30:83:5F:A3:85:4B:90:14:1E:06:04:7B:37:01:05:20:26:66
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1f:20:b6:9f:f6:68:a0:22:5f:24:73:c0:ac:bc:8b:05:86:58:
- 7b:97:ad:38:8e:70:61:7c:17:9d:38:21:06:0a:72:b5:41:3c:
- b6:9a:93:77:6f:e3:15:e6:06:74:67:90:b1:95:56:f2:be:52:
- 21:6a:de:f7:bf:d9:2c:12:11:9d:dc:f9:ba:46:f9:92:24:75:
- ef:83:af:a2:8b:3a:79:da:ca:c5:72:a4:7b:19:e1:a2:f7:02:
- 18:92:eb:a6:1b:74:bc:ba:62:51:d6:9f:69:af:20:34:3d:43:
- 08:e7:15:da:75:79:b7:81:6e:ae:95:08:cb:7d:e0:3a:50:7e:
- c1:7e
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFI92MINfo4VLkBQeBgR7NwEFICZmMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAB8gtp/2aKAiXyRzwKy8iwWGWHuXrTiOcGF8F504IQYKcrVB
-PLaak3dv4xXmBnRnkLGVVvK+UiFq3ve/2SwSEZ3c+bpG+ZIkde+Dr6KLOnnaysVy
-pHsZ4aL3AhiS66YbdLy6YlHWn2mvIDQ9QwjnFdp1ebeBbq6VCMt94DpQfsF+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:17:7A:8A:30:06:F6:EA:5C:36:40:0D:AE:D8:9F:BF:B9:BD:82:CC:52
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 01:73:17:d4:24:e8:3a:79:6d:9c:a4:96:74:fd:60:fa:65:82:
- c6:0a:26:9c:64:d6:f8:c5:01:8e:ce:70:b2:a4:1a:a0:1c:41:
- df:1e:a2:36:1b:4f:2d:56:6f:ef:e2:fb:e7:84:d3:aa:0c:08:
- 04:44:67:57:88:8b:34:b1:74:8c:57:96:9b:e2:b7:dc:2e:d4:
- a3:05:41:bb:24:fa:be:2c:a4:cf:be:0a:aa:8d:64:ff:6f:ee:
- e1:24:c8:06:8e:15:fb:fd:19:fe:92:d6:55:84:ae:71:58:2c:
- 6a:65:53:34:39:20:43:1a:5b:20:41:81:00:6c:5c:10:25:b0:
- 3f:f3
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFBd6ijAG9upcNkANrtifv7m9gsxSMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBAAFzF9Qk6Dp5bZyklnT9YPplgsYKJpxk1vjFAY7OcLKk
-GqAcQd8eojYbTy1Wb+/i++eE06oMCAREZ1eIizSxdIxXlpvit9wu1KMFQbsk+r4s
-pM++CqqNZP9v7uEkyAaOFfv9Gf6S1lWErnFYLGplUzQ5IEMaWyBBgQBsXBAlsD/z
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5A:93:4B:EF:96:9E:AE:3E:43:16:26:A4:18:1E:79:8B:A2:E6:9B:21
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 64:90:80:33:7a:e3:e8:e4:66:09:4e:4d:1d:ae:cb:f4:f5:b2:
- ea:4d:48:24:be:04:8f:39:9e:c1:da:6c:14:fa:0a:a5:be:47:
- 84:19:27:c0:3e:15:ab:18:78:71:0e:93:e7:6e:c8:05:ea:f2:
- bd:c3:7b:fc:52:04:be:fc:b2:22:80:81:35:b3:ab:57:7b:23:
- ca:39:66:ed:47:19:cd:1f:2c:ab:14:4a:28:5d:23:ab:24:7b:
- e3:51:bb:78:79:05:20:25:ff:13:4f:c5:d1:2c:e1:67:b3:e4:
- 29:35:2b:1c:5e:aa:01:17:aa:49:bb:04:66:52:a3:1a:7c:0b:
- f5:57
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTImluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFFqTS++Wnq4+QxYmpBgeeYui5pshMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAGSQgDN64+jkZglOTR2uy/T1supNSCS+BI85nsHa
-bBT6CqW+R4QZJ8A+FasYeHEOk+duyAXq8r3De/xSBL78siKAgTWzq1d7I8o5Zu1H
-Gc0fLKsUSihdI6ske+NRu3h5BSAl/xNPxdEs4Wez5Ck1KxxeqgEXqkm7BGZSoxp8
-C/VX
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3EE.pem
new file mode 100644
index 0000000000..5b1e4ed0c8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: EA 9D E0 FA 86 7E 3B 5C B8 87 06 8A FE 4B 65 C3 6F 21 7F D7
+ friendlyName: Invalid inhibitPolicyMapping Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitPolicyMapping EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqzCCApOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMiaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGoxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTowOAYDVQQDEzFJbnZhbGlkIGluaGliaXRQb2xpY3lNYXBw
+aW5nIEVFIENlcnRpZmljYXRlIFRlc3QzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAv52QYQ1BWUErsri346fudEihcaQNINeU16WfsFvSYR/3ouv3u2Iu
+kK9BngF3VahW7oyBeXwxmj/iAV2jimT/Fi1g2h639V3eHn8mOa5f9xzRbnUDk7vz
+HqIx8UYup1zPcup4grk44BrkYyJoE3U4CRxDQB2Vw6lNV6osd+MuNyxkFZLnOie5
+Hcl3UoXWG4lc5nCN5iNxxkaooKKlnOh4UR0Zd1jUh+AVP2zkzjw3OtER8PILl3fv
+9hN/qcwW+0BSAemGQJDV5Nd7D5fCNJzbbXHToA3k/Bp3F3BqeE45IdFv4varhUjc
+9pXAmno8Y9TXt6QAM5iN5UaJvOLTHkqqUwIDAQABo2swaTAfBgNVHSMEGDAWgBTX
+gFwTi45BdroKtXNx6KNAgHQO0TAdBgNVHQ4EFgQUfdcKiPEJVz+3CWS6VMEBm+M5
+jCIwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwBTANBgkq
+hkiG9w0BAQsFAAOCAQEAVLVv3n3zSEYB7Pva607pG1mONfUdPsSkK+F+2SA3tSDW
+v39v9BuFVejJ/WcJi8S9Oj7dB4F8GkbH/Mgjlr/SGWNC2gG5z1eG/Xa5ZsVYxT8M
+o1XTK4S8TKdPPT2fvL3rHFwfsvhjama4zbB9/cG4HV0rRGOZIl2Dr4DwfdKxVllu
+pF8syWwTfzNOPiwbBVGRVDqVapQ0s/qjMkwKYmVj0E+xcVphBmjG5f4KLzB3fTiL
+YQHp6e/hD6fqDy34gnJKnvIdIpPS3mCJ32jUvs00gihBUXytvmF9mDmtx4D0gr/I
+HW06yZ8bXGZay35h+u/+32Qi8rs6E5p9xZjqhk7yzA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EA 9D E0 FA 86 7E 3B 5C B8 87 06 8A FE 4B 65 C3 6F 21 7F D7
+ friendlyName: Invalid inhibitPolicyMapping Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2EFFAF2EC16FBA85
+
+mnA8D/OO9/bRdXRtgF1460ooWSCBxgdMIp/ykM51o530doJX7pWwntIUnJstg5aZ
+wHhC7vJUrpcojZl1jzjNlMPAQ2GD5Tf3vGgvn+RoNrslRY8b0ipPh1R+73tn6ChN
+6dRI/GFbX0DbyxECglvrNynf1jbQaK+ljECnvypbjkBic4daBEAZzREP0RqWXzb4
+54MUmDGBFiOuGYNrUmFBk/1T2neOTHI0ry0nYVQqtU80QsNVbsYTs63dY7YR4RZQ
+voC+jW8xsrRFnCZkkmAsXFPzJPK8aUI5oAuOuE/cq0ymOXz3PcjGtZ5J0pCK7ruC
+i/YdtSmHwoJH/TEV/hWErlSduHziitORjqk6KHnSRUbU+bd2CEcgo9JBwn9OV56o
+QdUpPFfdrGFA768qPqmQnXSCeCUGvtqIR/sxdUhQ0LLUbdbMDgLsaOqXkXwchTPC
+LvWexL2kbtQUaUaV0pgDlaBfRYx/Vdm7hhM+b8Fdd6zy1eET+60fdsLyZuh8eyXx
+jDIWCRh7htT1XPdxGsCTXBMzgjG2PmbMfXWuZ293YnRsWx0Ll5Ed48kvzQiLjPEq
+duVDh9PIw3lOnjZGBk33ubn+8b/ZmCkTCVbNT0c7a060TXgekJnoXxut/7bexlf+
+nq57Z9JBmhVpUrT8Nu0Qrss/OwNuE2ZPUPDxzYoPqXu+WEUqlgs0wmpcpCFxc79z
+ELYXJAK1pVkw9ddVouLXbB+u+C7YpmoxZg8biUb0Z09eTDcw5ngHu8MoUMBLQpho
+TSrC/pH0fEpe192cqWyUY1oaAfFFzzRLvTSfBvzHYEGI3pPL9+4JSKbBvRjyIIz9
+yiPnXm673/mchrkKM4kfACRvhIlbUtF3VcZAE10mI24teFnsS+pjBij+hDI8fh8z
+W4CE9KUj/AhXGfjFveFRVmJ1vi4WX9h8Sl76Ne1MEqzyha7jNc+8orwMOEoHXI+v
+Dkws7KLCtVfhsRY14vQXFuOw02H3hQI39VfMhb7gerfllO33ZjdR8ygNuGc0DI0l
+H4Zib5SgtuawMpxKLH9hTCCQqkssKS6UZUtCP8iOnz5xq3+x7aRLblZqpINVdBEv
+DkPcROdqssbzHT29kheDd0KfZJF8zAHzRBvdM1LFLyvlJuSyWnnGuRDJj9Ttno+g
+/QZVRbjs/LIz74FOQjx33rFJGYGewH41mz6+4BbFjYDo8Kee9sqxte4Dj3YnNgdV
+Wcb3UDFHNv0qy9Ec/U/6a2JNx0fT3sKl624j+GMDddJv7/2ToR2GWYb5vF9peoUE
+KaeyGlIdi6nfCtTJzbTlg6on+i3T8xnft0IdrfNyfm8h6q7TtBYgsBhJYHX1sccc
+YY9oOcfq8Ymm7M1ER6wdTKYZY8WFXRCOtUrK3N3TrVStpjhIxlYgCILeCYo2/ceC
+GzJLjSlaXUWGZi0JziP0jym1K5poLrhVQGaRQ/NZheSmJ4H+s3BDFwy2g92Slb8b
+pw58GvcOukDjrAPafNRn8C5unDLBkHjHI0OzS1VvksldFRHuLhqvYmzFgbGq68M5
+hzakqEVOTr+Ny3vqF6nXOpVn1ckkUbMa54uPtiTM/LxJPpODjvCYXA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5.pem
deleted file mode 100644
index a14824bcb7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5.pem
+++ /dev/null
@@ -1,264 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subCA
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nNSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUG
-A1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmc1IHN1YnN1YkNBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQCzgPv0jUMseTafKoAOspqZCAtVctNqO5SipAee2vLt
-7PijWRyqmveQUmDdJ5SFkFnevzRHhOINFIhKjygmtJQe0px86XknNJhW6OPICI2M
-jxgzst9Cs5w3cYjsOxsD5+FXzritqz6jSQ8Fa52IhmBYcbRncSOcu2IOGGMOUfLf
-7wIDAQABo3wwejAfBgNVHSMEGDAWgBTvkHRdvSchXG13RCZt3L/7vmNrCzAdBgNV
-HQ4EFgQUBN9qa50ER9oRS3e69lS0UhaUJsowDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
-IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
-BQUAA4GBALo5V4PwqAf314Emx79p7ce/cKrLjdi63pS2BsN4dFQ7TbY4Uru6/0Gc
-lZvOzyBVyvb4KxYTgvmOUkaNIpEe6xyRjHN5oAOEuOOgnXjL6kQz1st793h3WaTA
-hTg1AyHkktBRVhr0g1rCHCsGdrq6HSU9jZqvOOPaWomS+woTciNh
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClDCCAf2gAwIBAgIBOTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMYaW5oaWJpdFBv
-bGljeU1hcHBpbmc1IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmgb4z
-lKzduO0U0YgdsR69hYe1HUrPtFTUc7C3KMaX2LsYdutgdW5fQ5atnORTBTTRY11C
-G4hIuo7WabxJOcSK9lrleEw58bZjDsNc5/o8xo3cF1zkmc6/DH4P5CGxk0nOzeLY
-XJ9vyj/nZc5i0k6H7NU+cde/s5tknCDntmnf3QIDAQABo4GRMIGOMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBRAFr9wLgI4+Lavp1rZ
-sgNDWZj1TDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBBTANBgkqhkiG9w0B
-AQUFAAOBgQAfLQvmb/5mx+Mi05zSJQyITwTfrw+AMrYezSpljeUZcymBLkK64BCs
-eVXrxImcI3hi3oWPcJL2dt5mmQB/o96qOYkEBbxDD0WQ0rwKgXOODhD+Di5aZPqB
-g9ZeBDxQgveLqLpEh0JL0MwJDLXH8Lca6XVdmPmFuaob3aIOP/zdcQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitPolicyMapping EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subsubsubCA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIWluaGliaXRQb2xp
-Y3lNYXBwaW5nNSBzdWJzdWJzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMGUxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czE6MDgGA1UEAxMxSW52YWxpZCBpbmhpYml0UG9saWN5TWFwcGluZyBFRSBDZXJ0
-aWZpY2F0ZSBUZXN0NTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqU2HY4J5
-i4TyagwhHyTz6DgQT7GKk0xSor3iKrPjBUTpEVWM041qODnfp8RL42lhZ24okQbQ
-8DoNH5dL/jtH5RsbZnfJnhHL8GDttKjLwHpRVRLbv4IlV4eQoPzTSRR7D0ishs06
-PdRXDoy0+UhNcABrm3ko1gZjAcPRL/ammFMCAwEAAaNrMGkwHwYDVR0jBBgwFoAU
-JLZxrVfA94Sar1a34h5IbPP9rjEwHQYDVR0OBBYEFEqYOSxfq1nokOSM2rwp2uDB
-0O6pMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAIwDQYJ
-KoZIhvcNAQEFBQADgYEASMkNNbv9N1yfYt5C2j3Lmy5rhbrTjrEDjNCJsQ1Pun3c
-qrJCtX52pGRNef3Sabh2W4jOExljobE/P45PdPw5uJtQd7YgGN58cr6wOz08SA2c
-j4vAlaNjcbNW5d3sUX6LgXFOHsamawjTncegVpR7mCY8lqVjxmW9ha9NF7h6ACY=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 CA
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRQb2xp
-Y3lNYXBwaW5nNSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8x
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UE
-AxMbaW5oaWJpdFBvbGljeU1hcHBpbmc1IHN1YkNBMIGfMA0GCSqGSIb3DQEBAQUA
-A4GNADCBiQKBgQDcDskVa22gKY6hi1NN0qxc3EGcrc7Ef9QD5LomWJ0NbPF2omux
-VOp4diM850F8rFaVpqHpOI6ElWc1K4PYVN+gp/sZ5V6unFR0ixzEvpsPTZa38btH
-kcqGMFfxw/f5HtdvgB1dt09da6xG2UFKxnubgQuxUPEx9FcEYSCrbLq3gQIDAQAB
-o4GOMIGLMB8GA1UdIwQYMBaAFEAWv3AuAjj4tq+nWtmyA0NZmPVMMB0GA1UdDgQW
-BBTvkHRdvSchXG13RCZt3L/7vmNrCzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0kAQH/BAUwA4EB
-ATANBgkqhkiG9w0BAQUFAAOBgQBNZ4dVlouj30O2fD0c418lyzVO85YIAuof3wDW
-LW4XjH/r40L/BUPDyFJceZXA7Yaym+UuYLZh9RQBEtkplLkcqgezH5GT5EkefBjQ
-CrQFgsqRttLQAuw03v+2I9a8vHY3u0L2puzJQ1l1GkV4gqSAgEv2YVdva0gkq7sQ
-52udtw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subsubsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subsubCA
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nNSBzdWJzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMFUxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEq
-MCgGA1UEAxMhaW5oaWJpdFBvbGljeU1hcHBpbmc1IHN1YnN1YnN1YkNBMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDT9hQ7qYK6NHbsH0I4rzox6PZHPasVXKNr
-Er1k+U5DVQ4tuCaZk6QEdBpLSMc4V62MtVl6mu/Zox73h6yvllHZDBuH63fEVFLc
-WWCQ0TejhcMx4wp6A0TVqocawS4C1gMhOeXrYZ18ZWakU8DPVwOb23y4/zseqUt6
-1tXPvs2uwQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFATfamudBEfaEUt3uvZUtFIW
-lCbKMB0GA1UdDgQWBBQktnGtV8D3hJqvVrfiHkhs8/2uMTAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZI
-AWUDAgEwAQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
-BQUAA4GBAHwn3D10SDne03e21/XMdNEGPmNE+jCS3S12gtAPbeHa3KxqsmmuBcEv
-ahsKPoF8CtAAPiLUK4M9GqwK5Vf0bsBlduOnF6vSnZQGKp9OQKOhbTfIoLSWRGIF
-TtQX94lVnOBpO+qXCl+FBKm/eUGyAa6/K1s6vwVtNwW2uT1YPKe/
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping5 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:40:16:BF:70:2E:02:38:F8:B6:AF:A7:5A:D9:B2:03:43:59:98:F5:4C
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 6f:3b:6c:aa:51:1a:cf:0c:81:3f:8c:c1:f0:60:03:0a:7f:36:
- 01:0d:82:fe:71:4a:14:99:5d:f7:cd:33:30:2c:e5:11:0c:8b:
- 6e:7e:79:6f:56:9a:eb:cc:20:49:44:c0:1d:33:2a:3c:52:98:
- 3a:dc:32:37:d1:54:16:96:4c:b8:e5:32:39:ae:93:d5:8b:1d:
- 36:06:b8:bc:05:d5:d9:71:bf:79:4f:b9:45:6d:86:50:38:b1:
- af:af:68:eb:32:c5:77:86:53:6f:d8:dc:f1:a8:bc:e2:fd:e0:
- 4b:81:5b:1f:33:7f:9d:2e:45:c9:66:1d:5d:8c:da:ad:79:aa:
- 8b:7f
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRQb2xpY3lNYXBw
-aW5nNSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUQBa/cC4COPi2r6da2bIDQ1mY9UwwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAbztsqlEazwyBP4zB8GADCn82AQ2C/nFKFJld980zMCzlEQyLbn55
-b1aa68wgSUTAHTMqPFKYOtwyN9FUFpZMuOUyOa6T1YsdNga4vAXV2XG/eU+5RW2G
-UDixr69o6zLFd4ZTb9jc8ai84v3gS4FbHzN/nS5FyWYdXYzarXmqi38=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:EF:90:74:5D:BD:27:21:5C:6D:77:44:26:6D:DC:BF:FB:BE:63:6B:0B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 33:e0:23:55:35:fa:8c:e8:35:21:f8:35:28:a6:2f:57:5b:6b:
- df:3e:12:97:76:05:15:72:73:5c:da:7b:17:86:63:13:80:19:
- 33:5e:c8:f6:3b:13:a1:33:e0:06:ed:1a:8e:1f:ef:8a:02:cc:
- 9e:33:22:c2:b5:94:05:32:98:0e:65:71:02:c4:ae:e8:36:9d:
- 81:d3:9e:24:51:01:77:ea:d1:a9:a1:e6:04:c5:62:bb:82:2a:
- 7f:aa:3a:59:a6:72:48:95:07:91:ba:34:20:26:a9:d4:ef:6b:
- 11:09:57:8e:64:19:29:70:77:34:92:e3:eb:82:9a:c1:ee:a9:
- 83:32
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nNSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAU75B0Xb0nIVxtd0Qmbdy/+75jawswCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAM+AjVTX6jOg1Ifg1KKYvV1tr3z4Sl3YFFXJzXNp7F4ZjE4AZ
-M17I9jsToTPgBu0ajh/vigLMnjMiwrWUBTKYDmVxAsSu6DadgdOeJFEBd+rRqaHm
-BMViu4Iqf6o6WaZySJUHkbo0ICap1O9rEQlXjmQZKXB3NJLj64Kawe6pgzI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:04:DF:6A:6B:9D:04:47:DA:11:4B:77:BA:F6:54:B4:52:16:94:26:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1c:39:2f:17:f0:d4:ca:3a:70:97:52:46:b0:ed:08:8e:3a:3a:
- 92:e3:5e:f5:33:4c:73:0a:a8:14:49:ae:ca:d8:90:6f:e1:ec:
- 23:36:9f:95:e8:a9:d2:b1:6c:2d:99:94:21:f2:6b:7f:98:c8:
- f4:e7:f0:a8:26:e4:58:e6:a1:f4:68:dc:10:33:a1:c6:c5:0f:
- a7:a6:7d:1b:4e:cf:6e:b7:72:71:a2:6a:d2:e5:e5:e1:b8:d7:
- 88:3a:a8:d2:e7:bd:a4:ce:ff:1f:ca:f5:7e:7d:fd:2c:4c:03:
- 2f:96:87:d8:4b:ba:35:a3:63:e2:87:cd:95:2e:c9:34:97:9c:
- fe:30
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBw
-aW5nNSBzdWJzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUBN9qa50ER9oRS3e69lS0UhaUJsowCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAHDkvF/DUyjpwl1JGsO0Ijjo6kuNe9TNMcwqoFEmuytiQ
-b+HsIzafleip0rFsLZmUIfJrf5jI9OfwqCbkWOah9GjcEDOhxsUPp6Z9G07Pbrdy
-caJq0uXl4bjXiDqo0ue9pM7/H8r1fn39LEwDL5aH2Eu6NaNj4ofNlS7JNJec/jA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping5 subsubsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:24:B6:71:AD:57:C0:F7:84:9A:AF:56:B7:E2:1E:48:6C:F3:FD:AE:31
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 35:d5:ce:cc:ec:10:2e:1a:1a:f7:ff:19:1f:16:bd:7e:46:c2:
- ea:f8:79:b1:36:48:74:28:e9:6a:68:59:f0:a0:32:c5:9f:64:
- f4:02:5a:bc:5c:2a:bb:62:10:2f:73:66:a7:cf:de:b7:77:26:
- 1b:c8:7a:95:6a:2f:1d:e6:3e:db:1b:15:02:3b:fe:bf:e1:5f:
- 3f:08:29:6b:a7:84:0a:08:46:6f:66:f3:71:84:41:97:8f:96:
- 02:39:ab:ea:c3:c9:21:99:1f:6f:93:5d:19:4b:df:95:59:60:
- 0a:71:2b:a9:e6:a1:bc:e0:e4:fc:5e:b4:a6:2c:99:a0:2a:76:
- cd:d4
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIWluaGliaXRQb2xpY3lNYXBw
-aW5nNSBzdWJzdWJzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUJLZxrVfA94Sar1a34h5IbPP9rjEwCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEANdXOzOwQLhoa9/8ZHxa9fkbC6vh5sTZIdCjpamhZ
-8KAyxZ9k9AJavFwqu2IQL3Nmp8/et3cmG8h6lWovHeY+2xsVAjv+v+FfPwgpa6eE
-CghGb2bzcYRBl4+WAjmr6sPJIZkfb5NdGUvflVlgCnErqeahvODk/F60piyZoCp2
-zdQ=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5EE.pem
new file mode 100644
index 0000000000..3c52fc5fc4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: DE 8C 5F DA 70 9A 8C 60 6F F9 AE BB A1 65 E3 82 D9 09 27 B9
+ friendlyName: Invalid inhibitPolicyMapping Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitPolicyMapping EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 subsubsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhaW5oaWJp
+dFBvbGljeU1hcHBpbmc1IHN1YnN1YnN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowajELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExOjA4BgNVBAMTMUludmFsaWQgaW5oaWJpdFBvbGljeU1hcHBp
+bmcgRUUgQ2VydGlmaWNhdGUgVGVzdDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQC0i3fp+XfZPUG9DSTq/8OqOa6mw5BfqUR2OVuxulyooJ4qHigWqHCk
+muBd/ACPkowfECXCUCBypLRZ9hfDv+jZ+Jm5VWVMQ9N5qEkKae0BIxa7yv+r2r7Y
+5zHMWK67D0qIh29nCdCJE9aH4q56ig/8oz5icRc5tA723KT7/nDHVBGIfr5EPkAI
+/W2x1uNEwq85Qvy1bQdCUQkH4tbe0qLpYs013UQNFNH/NLuRQpDYFTMTyGApf34r
+gNlFzcnwNtbDj8ewQITe4LWC0zw54McUtzmqdvSdSaawg91XyXg7bg6ecDoRCnPn
+Ig/bCtm5RYKwPOIG5TMBFpn/vUtdUcyhAgMBAAGjazBpMB8GA1UdIwQYMBaAFK5j
+y9fiw3Hj9M5u/DX0m9JNPtwXMB0GA1UdDgQWBBQMlU4t80WgAZvBvO7pkJDrW61R
+nzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMA0GCSqG
+SIb3DQEBCwUAA4IBAQAubNdSsC6g4XBAAeavQ+94LbgE5Doy/MprXYSH7gGUDEDJ
+aLUiqgOS4imF0gdBv2v4PQpsD3yALD4igMdIwO8M7wMSEwY2WyCNHa95KGmzvbSl
+CcYjpPqXsrZOrZjYWF3JSSjIBEFVzWgSM5pGbtAnRD+wRXygTBGkUzKq9Rj6pFUs
+FWs90SxaR0EBCc5vtNcpIQK5iXnYCO3rPHzcdcSN5Cr8VCrt5WvCrbxLFIoKr/Kz
+KKoj1CbFqedcGBnRwwskfTLvEZdDs9xTr8I+A9DAZEoIPrcVB0rz9MH4biZBPDBg
+GxCqwudDV9TUmuqh1Udp39odeV1CPWfTSzJz/gK2
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DE 8C 5F DA 70 9A 8C 60 6F F9 AE BB A1 65 E3 82 D9 09 27 B9
+ friendlyName: Invalid inhibitPolicyMapping Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,00F5B427B5DC90D5
+
+HL3b7J8zUgENhTrSgUcPeQKTGJF3nUZi2FSeAC6x9TQW2jciLcI+ySs6oovnLbpv
+KRRcr9wgPwjw8fbzajYEVK6Q041QNE7XdOocq167PtSdKmQVMlLTabzsNNvHnatb
+A/vXXFk7OGWEKuit8HBTYiK38Ur1xI2YNT7kx6Fu7udBoimPZ1dj5y8dktbzWFCq
+pcf2xrhKbXhCZvTAcaDZgQHJWcnQIzTFdEa6L78r1eavrtD35ebEYyNRePSGSmNp
+1cDJ6CF5INsSvmdAjWIXHYmmoqdRe1buLSq8ar9pc9jfxYZjH+RnqWqiNdakti2a
+FUMn966dQCxaTOmWeruSg4ySXos/E1ZWwhY3qzuwc0PSc45dLr/FNY1YB5VtrHlZ
+OXd+s/CdElmXATjt1f05+AZAzRw32JENUHBNPLlG5v0Ze79y8aQyq4FWIZvfawoE
+su0W0hIM9EEb+Jgfl1Lew9FeKHETnzOQcOKvxQwnzbiwwG3v/ttFkquRAN9y3rn+
+uT1Ab1uBK/KptHBJlC1xcL4PLmM9vxsM13xsPdzbnRXvgvouAmZUirrwdQkau0K9
+mPP5GfhmV+yueaUleLa+KitNH2sSQ8hYUHZL8JfUFR1T+XAL+njZsVw0kdmbVsTs
+FCmRhPUYABxZInGRUXS49AFKbS+nz6+m5p825R2/kGmu6Kj9AX273fzWUvQT28J1
+IL/GEbIrp9uMm8rokUhCJNKW7us5A1M2cxXCVtGGxX0SuP0UdrOvaeepBFAqoqV1
+2X/jNPaEpu82pIXjYOZU2p/JSdQiwHrojcJUeiWl3gALhNkuwaesPOrIYow5Yv+u
+Nyro+J2aSYcunfuUgD/0A7lhpXae2PGFG6dP/GxJzsNYvaj/YCZb4MSGh/K9qpP7
+e+1YTxwRE4jcpwLb1RrpcuuPVmT6c836hbHPTJHnq8ELyDYooDum6BwquVifebZj
+nUaxpmL5hHgR6QR9GdmGiQBlWlGZo4lmOBMBIVqnW+OWKSgJFUSdsWTmZBGmYrG3
+cp9bj8hNFfGt/G/11atg/A8jJZlv17s1xYWcM6QUcAhCnCwvftL+N2odYYwhcD6e
+RIO11B5MN/jDDA42qvZic1wk2MKp0Vs1c/LcvDhyvYv2KxbTg4ytyy1g+LvVBZFY
+aJxgrSaZ+kuvccc2KWgDe4XSOnxqv5vh6mTY4d4RxJPAvDrjWMcTqJSDoKyApKZf
+k49dNtwzLQj1iZM5T6aDYOAMhCvphHlIFqBaF/XPtdoPbzOSSjnfBxORYRfQ4/ON
+v+LcBcDMBOJPzyD2IIvQCUrhS3e5+1KLBARrDH7Z4i7g6XP47mirM9tujdTmBeL+
+UCxgqpjEChegVP8aMWj6jVzjewDHLhv4S6PIte254vBHROT0WRPgRwP6qgeN2/pm
+auULnZwpXuYe3bwUtIYWMrO8Esi6AMvwWhVcLpZy6aV3hbqkUsUL+2t47VLToReZ
+p3ZKcwKs2lzCLyFc3eV6ZfuCrUfk3cZxISPs1ENS92KUGPKCsgWAybCJrKmjJTtB
+SyiNMKvAUySLMeyxe14tgIp+3cMOvksQmFXbWWWm7ZmcU/pRze1Be3jJaCO+MB5k
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6.pem
deleted file mode 100644
index 1e617839c9..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6.pem
+++ /dev/null
@@ -1,217 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Invalid inhibitPolicyMapping EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCAIPM5
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLzAtBgNVBAMTJmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3Vic3ViQ0FJUE01MB4XDTAxMDQxOTE0NTcyMFoXDTEx
-MDQxOTE0NTcyMFowZTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMTowOAYDVQQDEzFJbnZhbGlkIGluaGliaXRQb2xpY3lNYXBwaW5nIEVF
-IENlcnRpZmljYXRlIFRlc3Q2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA
-pIyvpHy1AEaR244X+WehPi6kJ4zfm/clYT73uCvd/wtRc1ecFT83WALtOg6iWRxn
-DxQ/Av2+6Sb5BGvOIyHVT/2cJIf325EZ/zxW6u9qb6+u2oWp8PX5ddUbH7yKAmXm
-l3p3cVsZB1GkL4KdBrCQGdF8Khnb5cF5YBSuYEPZXQIDAQABo2swaTAfBgNVHSME
-GDAWgBQkqwNVlYuV1wNEx93/fv32kbGgFjAdBgNVHQ4EFgQUYSBfuS0yhqXL/Jfv
-5l9yYaw12g8wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-AzANBgkqhkiG9w0BAQUFAAOBgQBa/IMv8cgYRBzo8cjsbIb+tzD4986MKnaHn5lL
-SEdCOU8nZTscVwdXEg0N1Bza86ara3HXHtgpLauXgmcA0L7BUkGJty9vIMzqc6LN
-VfDTX5iZoftoIKzFx8AsQio3Y9BlGRGU1NxKWyvrZj+PvT9lXym/Moe+b5pxez8b
-WLtRZw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpjCCAg+gAwIBAgIBODANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxMiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-s4T6CQeTrbqUSlSczfx8iMSRK4ip9F4liS7giqCrZeZYEuP+/XoRZKzqmT3G+io6
-zcenL7cegP9DJnTNuZ1nHEoeJTlhQZq00PD1n33OMK0zhMIirByYBpabztuw1dJ0
-MKKcRzJ1AswgccI8seh2W1FXdFo/vGkDOkcD21Se0XUCAwEAAaOBnzCBnDAfBgNV
-HSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUj3Ywg1+jhUuQ
-FB4GBHs3AQUgJmYwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUD
-AgEwATAMBgpghkgBZQMCATACMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgw
-BoABAIEBATANBgkqhkiG9w0BAQUFAAOBgQCXSeQ5mEkpmqCHstAZJbAGVSNrj3ka
-eA0k2v+n7vDeZ+9F8bByDiBBz3RMTqmdZxQ6zroOPsw66HLxv5D7oJImbhyvFrnN
-uxPGh8hvvP67N7UT9cM0RAoIQHmoI+3+o9cqOnTIJWXXPyq5q08yTrUt1lzFyrcK
-wGB7PyQXRRDWjA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCAIPM5
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
------BEGIN CERTIFICATE-----
-MIICujCCAiOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBXMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLDAq
-BgNVBAMTI2luaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgc3ViQ0FJUE01MIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCg4hWz7PbBhsTO+fpr6qznJLoay+MQhSxm
-gq7gcER+qcx6hOwpIxvX2HUQ/q5RqJ6X539C1HyngpS383VGDqxzWTILMJ9p79He
-5GhleTga2r/BSvq51G4uSJz4iJUJDEhzhQncRKUY65v1L8dz+lh/IHLRBGues3zP
-dWc1cRQ1mQIDAQABo4GcMIGZMB8GA1UdIwQYMBaAFI92MINfo4VLkBQeBgR7NwEF
-ICZmMB0GA1UdDgQWBBTm3o5WsPOWysSqTpK6CZqUqZRwPjAOBgNVHQ8BAf8EBAMC
-AQYwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIwDwYDVR0T
-AQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgQEFMA0GCSqGSIb3DQEBBQUAA4GBAEge
-Ag2ZoOuHLLqscTmz4NbRwXvWWtesM8lVBhQtShOlAgBpxm6c7kd4e1LMeAPN7yPD
-63DL3mDZnK+qtyvqXaK3uVSMg9CMGsGCqXGDRbmml0nbxbkLNGKYEtkJVzmIR9nZ
-vf0ZHnAqC4006H8s1uFPNIJwjb6hfK6oecY1nqms
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCAIPM5
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCAIPM5
------BEGIN CERTIFICATE-----
-MIIC2zCCAkSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLDAqBgNVBAMTI2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3ViQ0FJUE01MB4XDTAxMDQxOTE0NTcyMFoXDTExMDQx
-OTE0NTcyMFowWjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMS8wLQYDVQQDEyZpbmhpYml0UG9saWN5TWFwcGluZzEgUDEyIHN1YnN1YkNB
-SVBNNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoWsXQ0sXtSdVHZZ6NBai
-/YaSnuULPstaxcOXjt23ujwGnhffZLbzqoz6crjhOj3j7u5CAl76NNcQPuYi9/EW
-vxys93HyGAbgpl+YZ/zKL61BPTj5sBK4l5NEQoKUoPZsoeTDTXyD3HDWMDlJifXK
-gDYpaao45yFD8N0WCfd8pccCAwEAAaOBszCBsDAfBgNVHSMEGDAWgBTm3o5WsPOW
-ysSqTpK6CZqUqZRwPjAdBgNVHQ4EFgQUJKsDVZWLldcDRMfd/3799pGxoBYwDgYD
-VR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUDAgEwATAMBgpghkgBZQMC
-ATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwAzAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAImakMw5q9O9ghGN6g4TQ/IG
-gI7NgrjqoAKQiqZuD+kmbzSf1sGONmiLK44kykgJ0zZY4xbkoXVOQiNrnqDclNdf
-Za0+Fmvfx9vVTlSoLQGwSHE3oWDKcamton847GkEmnP0RacqUkRkgpZam83tnDEX
-c6eHTCxBYDmTTPuFe4fi
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8F:76:30:83:5F:A3:85:4B:90:14:1E:06:04:7B:37:01:05:20:26:66
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1f:20:b6:9f:f6:68:a0:22:5f:24:73:c0:ac:bc:8b:05:86:58:
- 7b:97:ad:38:8e:70:61:7c:17:9d:38:21:06:0a:72:b5:41:3c:
- b6:9a:93:77:6f:e3:15:e6:06:74:67:90:b1:95:56:f2:be:52:
- 21:6a:de:f7:bf:d9:2c:12:11:9d:dc:f9:ba:46:f9:92:24:75:
- ef:83:af:a2:8b:3a:79:da:ca:c5:72:a4:7b:19:e1:a2:f7:02:
- 18:92:eb:a6:1b:74:bc:ba:62:51:d6:9f:69:af:20:34:3d:43:
- 08:e7:15:da:75:79:b7:81:6e:ae:95:08:cb:7d:e0:3a:50:7e:
- c1:7e
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFI92MINfo4VLkBQeBgR7NwEFICZmMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAB8gtp/2aKAiXyRzwKy8iwWGWHuXrTiOcGF8F504IQYKcrVB
-PLaak3dv4xXmBnRnkLGVVvK+UiFq3ve/2SwSEZ3c+bpG+ZIkde+Dr6KLOnnaysVy
-pHsZ4aL3AhiS66YbdLy6YlHWn2mvIDQ9QwjnFdp1ebeBbq6VCMt94DpQfsF+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCAIPM5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E6:DE:8E:56:B0:F3:96:CA:C4:AA:4E:92:BA:09:9A:94:A9:94:70:3E
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 14:9f:a7:ad:6e:15:65:a1:9b:cc:49:11:63:ae:0e:76:54:26:
- 5f:8b:a3:f4:12:98:db:47:80:4f:38:bf:c0:0a:f6:d8:df:b4:
- 07:7e:06:6a:ae:f2:9c:6a:c2:9c:6a:75:99:df:19:36:ee:d3:
- de:59:91:32:7f:08:93:c3:31:6c:b1:cd:42:cb:72:74:04:27:
- 1c:49:66:33:e0:10:8a:99:32:7b:66:6b:8b:8d:48:21:23:6d:
- 1f:c4:b4:40:d6:8f:76:00:00:9c:6e:a1:bf:90:95:5e:b8:8d:
- e9:c7:a1:18:f1:bc:5c:28:05:7c:73:72:85:da:f1:a6:00:53:
- 5c:0e
------BEGIN X509 CRL-----
-MIIBUDCBugIBATANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLDAqBgNVBAMTI2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3ViQ0FJUE01Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-oC8wLTAfBgNVHSMEGDAWgBTm3o5WsPOWysSqTpK6CZqUqZRwPjAKBgNVHRQEAwIB
-ATANBgkqhkiG9w0BAQUFAAOBgQAUn6etbhVloZvMSRFjrg52VCZfi6P0EpjbR4BP
-OL/ACvbY37QHfgZqrvKcasKcanWZ3xk27tPeWZEyfwiTwzFssc1Cy3J0BCccSWYz
-4BCKmTJ7ZmuLjUghI20fxLRA1o92AACcbqG/kJVeuI3px6EY8bxcKAV8c3KF2vGm
-AFNcDg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCAIPM5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:24:AB:03:55:95:8B:95:D7:03:44:C7:DD:FF:7E:FD:F6:91:B1:A0:16
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:dc:20:33:f7:b1:e9:f8:9d:47:00:86:08:2e:56:bc:02:0a:
- e4:46:90:48:a0:cd:37:63:71:fb:69:34:e1:0a:d0:aa:e4:f7:
- 61:67:46:a7:b8:ba:11:67:30:eb:1b:85:e1:1d:0c:9b:e6:fd:
- fb:50:ea:c9:f3:e4:19:73:05:85:6b:cc:c3:f0:4a:2b:bc:75:
- 7e:0f:b4:d1:64:39:b6:38:39:dc:30:77:33:91:b8:77:52:b6:
- 70:ed:24:b3:34:7a:b8:ef:46:93:78:f7:7e:6d:6a:ae:2e:c8:
- a0:d7:76:ac:46:47:ff:1e:9d:fa:51:9b:47:cb:06:c3:c6:85:
- 4c:9e
------BEGIN X509 CRL-----
-MIIBUzCBvQIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLzAtBgNVBAMTJmluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3Vic3ViQ0FJUE01Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaoC8wLTAfBgNVHSMEGDAWgBQkqwNVlYuV1wNEx93/fv32kbGgFjAKBgNVHRQE
-AwIBATANBgkqhkiG9w0BAQUFAAOBgQAD3CAz97Hp+J1HAIYILla8AgrkRpBIoM03
-Y3H7aTThCtCq5PdhZ0anuLoRZzDrG4XhHQyb5v37UOrJ8+QZcwWFa8zD8EorvHV+
-D7TRZDm2ODncMHczkbh3UrZw7SSzNHq470aTePd+bWquLsig13asRkf/Hp36UZtH
-ywbDxoVMng==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6EE.pem
new file mode 100644
index 0000000000..9ec0bff532
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidinhibitPolicyMappingTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 41 AF E0 5C 50 DC 4A F2 4A F9 36 A6 FA 5A 12 CD 25 20 65 6D
+ friendlyName: Invalid inhibitPolicyMapping Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid inhibitPolicyMapping EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subsubCAIPM5
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMmaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBzdWJzdWJDQUlQTTUwHhcNMTAwMTAxMDgzMDAw
+WhcNMzAxMjMxMDgzMDAwWjBqMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBD
+ZXJ0aWZpY2F0ZXMgMjAxMTE6MDgGA1UEAxMxSW52YWxpZCBpbmhpYml0UG9saWN5
+TWFwcGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBANL0XE/6QZLLGmP45AS6Fok2FJ3qtjzy+nkJFlJ4QfdgvkLA
+F/wf/aCbiX/p41LtukSbRGLWwVPfwN6uWZRvZcj4SOxhIRAgvWK4WrwNtgqVwGNE
+3lt8AOJ83NFUArK+FANDH2rtzbY8igJOIEGQ0H1CPyYHM0g6O9gbACN6iABkxeoS
+UrAFL6u+cjDFg7Huwt3C0DgZzZZk3zmi82K4RyfQnQ5n4sFHhJHCDviY3xQvW8u/
+gC7o4LxeWrPJWSgn2jFUly771l+bg557D9CbR40HH37/JNf328clwHIFqwweU1gp
+2MNz6/IobTvdSL9b0AgSUjbwpjCn1CtuN4p46t0CAwEAAaNrMGkwHwYDVR0jBBgw
+FoAUEocbNWfwvKGgNroVqCkZ7RqbW3AwHQYDVR0OBBYEFJCTnO92Cq+5fy1mUiJ4
+S7FH+7GqMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAMw
+DQYJKoZIhvcNAQELBQADggEBAKWNC8GBMa/d2a5ls5LSN4BVRt0OK2AK41N0Ts/Q
+A6D5aE29h4nScxZ20I7LB+8fMcuNyfT2rZFuBgZQ62Oqad+XsDsBFRj4NITol6M3
+1OdW86Dezbc272tAukA2KqYAo/Z4j+/ag167leUKu5tf+5Cz/xrAx8/FbVZEXS3K
+kyprlh/fy27UadewavhCgc88KTLF3DMnTPg15Ov/0SEtDZ46wdy7V4D7ao57Xe6Q
+V2pPUHl6w5mvgCtscZkCqf0+AL3AUL81ks+wUghBnzCUBdn9Lsv/lfHYIUanRO7z
+0VEto1h+4ot/XjDSG1nqJ3bTAJ++VB7pBJMGuiHeiEyhKQM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 41 AF E0 5C 50 DC 4A F2 4A F9 36 A6 FA 5A 12 CD 25 20 65 6D
+ friendlyName: Invalid inhibitPolicyMapping Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B9A03DDA465C74E3
+
+clCgBK0EV4rLPjpjo7s1sVyde1o38htaXjfAdmsQxZM4RoNr+XxkGRmPp2JU9/K4
+nzyYCl7E+ONJPogEVLv7P7PAfDrDNo6eCWPWksKP6tP+aIaTmA0jHjqAHDxuUOTp
+Oa7D8VhtDs7d2JIWQv5tgz8N45DC4XA+lfH7lTpgXbKzdbCaLNwWpJ4rHLtGpMJ5
+u3eADc+oVG1RY+5Ia8Towk6Va1t155vjiZZsOgMfogeCEYaG6jLPZX5RftB0Pr5n
+RHdVjDCeasLxLK0wSAQ+AX3j8mXEtP3DQNfhKM4MwQK6wPd2JwKAtZ3f9UimcaAJ
+t88ioUP7ODiRU2QPuBLNO7YnvFmBmPh+ogUPElVZPu6owqS4kTEVB2/f1SgwA1V2
+YaGPyhOoGlxi5BCFFN+mg0tWe/f6d05WFWIvA4p5phAfZcd6SySaaV/DG1EP0+DP
+xL9M0LZmPnqJQ/ZINakDvmn/dHA2AK2GAwgOyrXuwq1ODUfp24k7kqUAY8ZDC932
+rMkAp0HemgeZ6TXO6sIbAzTceboYxEEnYklfuM8wnpVwejkT5bwevfL46Pde8WKU
+uL/0L3BEMxSB0Yt1zNErTBvKJupRjRk8V+VC+O20O8PpIdey7Sj1Ai8fkxgIfRe3
+4aCRzIvCFe2a0FrFxKQiUjVLRXKUbuQfr6Wh0PC84rdY/DKjPAB0dG97FPQjDfTW
+CWb8MmpEHaj5Jh+LY/GJp1FkeB4xHPCJseyCQoRVvmt6WeAntoorHXk17+esGod6
+y3wWEC1kpZyT3kFbBI/QLku87SJe2cG3C3qLmLZgPOBNvD5tijryVziC0ydg8c8M
+D7IFXhs0/lwyZeQZkw+DbqMWRh6HyjR869/7M7SKiYtS6KeCDY0T/b7Dw61Vde8L
+5VeddnonZ6akZBxT62QqdqUZC9Xp0fsD2kQnHCOTOFkc1aV21/1ldzJ8z6NBe6NQ
+SqIFBNzfGzudSaXoznpIWeiAfayc3gFULYeP80ZjorVbb4LFI33M/X6K2jkKcQkY
++SNlPzE2u3jskw3eyh8CLsWp02Ax7wdlyHC25BPsbR95IJcVjOYym1JbDZeqU3C0
+afb2atFq1QM2PZQswl0W/DGDiri3BLi2Fo0VnX+99Kxjdw9F1lqlyKjW3T8EXYIB
+ohK90Vs0PaD9TcZuw36TrgvjnbwOmw+3dH5PG5WQ9qxDDxsjE5lDSfpKqn6trV3b
++EBiHiuYyiJin4Ib6aOGy/+fONkVG7eUHpXttzhtPOGbjtmas3bOjgIBs/JBzqjm
+VH4l5rEkgM9sVIPzgWHLj0z5VtZjKSIkcFwSG/WfcEHZ5dzkbybWFryEfnP5hrA3
+3QsfxBH3gzKsDdh6BqTmj2FqSf5uS+ImUOn6KEk4XaXCNsLgadh7UbKS3kP6eZq0
+rgtmIYNDkOHmiYkH0/K7NP89satMkNbIi4DD7o9WvHqGHhsAczDkEqnmP5GXdxpx
+GYsl03gV/F5OjqG19mVmuMV9sSJRqF2pH6str9WNCDHTTVcDXn3Aam/U79310/vB
+J8ko2grQRkTPox8P995o+ocp2yIRq+5XTmMmvHsb/R+v/w5NA9UDbQ2Ve6TeA81r
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4.pem
deleted file mode 100644
index 12418ff1a1..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=keyUsage Critical cRLSign False CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICiDCCAfGgAwIBAgIBIDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFYxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczErMCkGA1UEAxMia2V5VXNhZ2Ug
-Q3JpdGljYWwgY1JMU2lnbiBGYWxzZSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEA4iwG9rt4eJXUwy+UTNrUEq7gFuAYWGYaf0DCMDkLcYPIAwlWow99RTeX
-jXir2B5PC/YcGARB1+bLQDTn7C8R2bilNXujkHWU4w10Vt56sONz+0ASNoIXCPn4
-EFXAneC3z7q9ZONoU4U3MBxMhuepSqGeBWNgh5KI/ICyYI/P61UCAwEAAaN8MHow
-HwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJSB6cRQ
-9gcgcCaUPO/fMC7eP3TNMA4GA1UdDwEB/wQEAwICBDAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvUd6L
-OoQLwzSqlbFY2JYA5GGxYuAdrT0FxeuRK2wGwiPmNCKn0w8t/wwQTrbPdrENV2Rc
-gzeZ9A5RY/Qs6EogNvy0qfC6lw2aUZsjEFjpPvnXmjb23sL2A3twFUWuoZdy8Wtd
-PTGWD96vq7KEdsMb3IRwUMk0XxyPZ4MUOqtVyg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid keyUsage Critical cRLSign False EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=keyUsage Critical cRLSign False CA
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTImtleVVzYWdlIENy
-aXRpY2FsIGNSTFNpZ24gRmFsc2UgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBwMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxRTBDBgNVBAMTPEludmFsaWQga2V5VXNhZ2UgQ3JpdGljYWwgY1JMU2lnbiBG
-YWxzZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAy7qxBfmtCspcqkqi9Slrzqm5Oaxst+HoLMAM77zVMEmIDI2IYsm1+PKV
-WNIdR8whYpz9OvVP16/Ujt4D4902/HLCQGcMfprQ4M7S2ba4Ujvig4fe6SFwVCRs
-YbCOmVA7rHiPEz2uguVgeAkJolSooUz/QEtakvGSEKGO8zhuQFsCAwEAAaNrMGkw
-HwYDVR0jBBgwFoAUlIHpxFD2ByBwJpQ8798wLt4/dM0wHQYDVR0OBBYEFOsTlV2h
-OTNSDv1rZhunjIMov0boMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAgST/vGwENhUdJayqletDgqTapBVi
-mXOpojLaV5Q71AWzCA6oY3D0ATMW3QbzK9OBaDtURLb6zyKPLtx/2jZU3hw1c1Ia
-bIIKe8MPc9VVlABo3GW8vYwKucYZValIq4YAV9AbtFYz+5L+7UAsZC3iU9t5UJ9G
-GftSrxstYAKAeRg=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=keyUsage Critical cRLSign False CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:81:E9:C4:50:F6:07:20:70:26:94:3C:EF:DF:30:2E:DE:3F:74:CD
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- df:6c:04:71:99:bd:11:54:35:2e:e7:bb:54:60:3c:46:38:0c:
- cb:d3:e9:06:bd:55:2a:03:35:2b:cf:e5:a3:b6:f1:13:5c:8b:
- 43:5e:9b:8c:10:8e:c6:82:83:ee:af:1f:50:3a:14:2c:f3:a4:
- 43:00:90:21:f9:59:4b:15:c4:5c:30:1c:86:75:2a:cb:a1:86:
- 33:b1:f9:75:46:99:34:07:64:dc:4f:6e:d1:f2:cd:f5:0b:7f:
- 00:1d:ca:9e:60:0f:93:8a:c5:22:cd:59:46:e5:21:2d:26:ef:
- 98:ff:6d:50:2a:7d:5e:15:81:4c:b8:3c:ca:9a:1a:b5:1b:6f:
- 4c:9f
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTImtleVVzYWdlIENyaXRpY2Fs
-IGNSTFNpZ24gRmFsc2UgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFJSB6cRQ9gcgcCaUPO/fMC7eP3TNMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAN9sBHGZvRFUNS7nu1RgPEY4DMvT6Qa9VSoDNSvP
-5aO28RNci0Nem4wQjsaCg+6vH1A6FCzzpEMAkCH5WUsVxFwwHIZ1KsuhhjOx+XVG
-mTQHZNxPbtHyzfULfwAdyp5gD5OKxSLNWUblIS0m75j/bVAqfV4VgUy4PMqaGrUb
-b0yf
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4EE.pem
new file mode 100644
index 0000000000..19ff6b3bf4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalcRLSignFalseTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D3 3B EB 31 DA B7 F3 2C 87 7D 9A 83 E1 31 FF 35 A2 20 88 61
+ friendlyName: Invalid keyUsage Critical cRLSign False Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid keyUsage Critical cRLSign False EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=keyUsage Critical cRLSign False CA
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMia2V5VXNh
+Z2UgQ3JpdGljYWwgY1JMU2lnbiBGYWxzZSBDQTAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMHUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMUUwQwYDVQQDEzxJbnZhbGlkIGtleVVzYWdlIENyaXRpY2Fs
+IGNSTFNpZ24gRmFsc2UgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDEU52VUxkPNxFuLOEIPwROevCUVbZbolJu2uOK
+hMqmu3yXDYKR1FBC5xGsxfZeep3tn+PGr9z5+O2gaD39SGxlMhxvSdbVc/QT1u25
+0fTq1U0gte59c0JsrG9MhvZBwz0kC7jMkc/1De1UTKtz8kSLwTqZgKQKruSHBgM1
+QLeMl47cR27fiUnzXAa2ZEOGIByyxdEG37yXJ924NHffS3Ig9PrPYFyt74Ck9Fir
+pc+gS5ayFmJLrmerYNTDkA1lVehXWkxZeK/xwj1+PIhlOFylbKKPrB3gFN6fqppT
+TkP/PSLoJcAA40b91W8T1sJvqRvgx31t/72sTup5zEUIHnglAgMBAAGjazBpMB8G
+A1UdIwQYMBaAFMLKafW0rxMt9JzyEVXLKjCz0lpJMB0GA1UdDgQWBBQ+1JjhVKTI
+Ycfsx9NS9lCKWrDbIjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBiFYY8R0mw8pMTdH+nZzSKMKj3aONg
+mhYYsS5cKGpx8oQOv/iNdYZf+W2f20nLKt9iKoCwbV7qWFai5HasT2AeXypTgEMc
+nRcn5NkQCIkOFYjKwouSFUF9Lt5gcRfQhD2E6yEORH+6OuhRhkydk0NbmOu3EctI
+hR9RKSIY3cCS1got9Kxmj1N8/KFqKTOXleg6tdC27Fqo3tfPQOYccxagBPAzmZbR
+f17XUbqiY0fl0CVUBZImmUY1C18ov0xgnUF5m7vc+DQOhFemNemdi3wMbIN77Dva
+925L/R1Pek6PDaTRYrikU9zS+CkdEgfB7Pt/+PkV01xA11ew60ob+QEB
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D3 3B EB 31 DA B7 F3 2C 87 7D 9A 83 E1 31 FF 35 A2 20 88 61
+ friendlyName: Invalid keyUsage Critical cRLSign False Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,336947DE40803472
+
+8ihZdQwa7EBBTKR6EeY4EW9YEwdyd4+xMA3jGB6d89YisIsJ+xBpMRDI8CzEWG2d
+rWJ7Tsoc1EfcAC5TP6ObS7BHhcDaebA23xMBdrInYaZFqLUKVBTL4tGP8auqQuAJ
++Y4fxnd2DTlXIjSAtuFA8PLmqMdtbAmI8pf0qmG/60R6yMExB7tYdEdkGJALaleB
+C4VJtcd6kRqfyuXcs15QDc5+dohTn39t7i+flu1srBxVkqLUNcS3P1Juo7FEtRAb
+xSE1hgQyz1b14PqnSOA8Z7G3aS3uZRwyq4lR/aip6qJmfbREKvxY3BXOE+1woqbO
+76glocZMWcUJ7rZawysJAZCA0ixGk2pIBhcvacCAsGczojkhADnTlie0KOyIuYsw
+0ExHSVeSGNlQqvT2SoDIgnZkb7Cbnc6yqK5mjVjRlG/PKrBbSztmbEbNxwFllsJQ
+oHBeyp/QGVhEkjNyf08OYfY2WZkYMkXnNGzoM8keW6Lya+sckfP+RWLfHC9c3Mmf
+U+tmKz9Cxizfuq2OVJyFSsRTLr3sOsz7NUWp3e7rzo8H28986nH+Omr7RXJBmUMz
+vHtKFNgZc1+06KYmfWRMtOYuRpUAODRF0Vw47JqUPbLg5J+BuAE26pbqbvPSY9rx
+RFNgnvxUM6L2sZim7UgfM8jAJip11NMtn5e19QmQw3jcO6KH9sFn6rGxRMOsDTvU
+qoPlYRhR+JvJPG24q2M6uWAGzkq3Cdp7IgRbfj+RD6bhuPlII2ODQVHYL3LWQvOF
+MsugpnZIqNcN69qQuRjvmq1+xOWC5EOzjgIXsSirT0Odw6At2pxxDros8lgVeq3D
+WTsuogGG1knw4kUB5cbvrnCdn5xHf3CXfSzuZAuBnMFI2BtFznDSSv6E52eQRMG1
+BUno9M9UsBSlqVNem3tmjaT0Lil1q3GPaJ5kguBPEddiYY1uUrym6hIUVxk14Bbv
+Hn9oVmIR86h94H18p4Qt+wrC+yl4uv5PAeXOnLjtgt9BvDYiAU6aikfyB+ij/jMv
+X/OotNasHmv6N8dlLI5r4XaaLIK9vKnQFRg7+Q2nkXTC3f3rbfrJS4chIcxKLzK5
+WRrwtZW5SueY/nDXF7wH4VVWD9aBKR7oJSUsIqPsF13Lf3O/WolzpwQyhyJGQV7h
+DMaeloxnp7fF08QKuowYYScAUJgHiNRUawLLldr+uHcBgt1JyZhsFNRpJL959jFU
+1JqTI43tWplzN56O5vzO5KO/P5ub7kqJWNFzI8wxUBq9/0MEuru9mDs8BiaNP6cP
+mCMp/KY7RpQ9Rr9EomplXLrroPp97kLzbWfKG59DHYLn6YynRaOjqcSsl1iLT7FX
+AQPhIKIMZGxJePHgFvzAbx+XlABrf4+AOErI7m3lBTOyKcq0+fQFgFxNxtXlRQko
+xlS0bFh2koJlbKtzY/ris68r0dz2ahIzdfI+v+HUAY3pBbr4Ptsz66fI9yzuwVDI
+DNX0vZ7rKLwlUwpZ6ZuDKdV8JJTYWb1p9EcPRYo1izO1S+jXbpDfH0ajkKuBVaw3
+fnSMTZGWZfu2iBTLXk3LuPvoNBLuIT+Kq6p0nN7XZWofgnAJ+HV+3TwF1JAhrEOD
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1.pem
deleted file mode 100644
index 70eca0a203..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=keyUsage Critical keyCertSign False CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBHTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEvMC0GA1UEAxMma2V5VXNhZ2Ug
-Q3JpdGljYWwga2V5Q2VydFNpZ24gRmFsc2UgQ0EwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBALm+L1UcoJG+mviuHuN0sBN3JeuYb9p4T8GP3zMU2o4qU0bwjq9L
-PcOqj8RnfIrHIMUR9kgNmxJVXX+02rORMvzU9LsxdQxFNxN8sokG04ZZv5iqSr4W
-NnG/UD+RYlBLRrHuNx0fDoW1zAac8JO28LeCdhot2Un+J1W8knpYlAt9AgMBAAGj
-fDB6MB8GA1UdIwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSU
-Abz4nHw/6JK2TckGtNNyMU46NzAOBgNVHQ8BAf8EBAMCAQIwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
-ifJcYkKWo1wikfXTF8s9sBKQjt+cMW2Kn2+25hF8KBXRmo3lJzJXyKtMQucC/+6W
-rWB4brLC4KiyxVC9OCbEIxlsc9Mx35cgX39iXI5b2BEn/pZt9ceios9WPQYU6t/Y
-D78koBp3ni6yy5WGa3mpU/xh18UaG/8VnfARvbTQcGs=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid keyUsage Critical keyCertSign False EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=keyUsage Critical keyCertSign False CA
------BEGIN CERTIFICATE-----
-MIICrzCCAhigAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLzAtBgNVBAMTJmtleVVzYWdlIENy
-aXRpY2FsIGtleUNlcnRTaWduIEZhbHNlIENBMB4XDTAxMDQxOTE0NTcyMFoXDTEx
-MDQxOTE0NTcyMFowdDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMUkwRwYDVQQDE0BJbnZhbGlkIGtleVVzYWdlIENyaXRpY2FsIGtleUNl
-cnRTaWduIEZhbHNlIEVFIENlcnRpZmljYXRlIFRlc3QxMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCgVfrVarIrsGAAz+ak13NJrkcspcEeCVsjrOtzHf619eeO
-TDalq7iyspJxTEhn7lG7q/UazRqEp6lBu1fVFkdFBPHi1uuNtyLB80MNy0ztjPAf
-Ct0/wV1jDvNbaCg/TFXflKtDTY+jcVWTOmWMwI6hZwokQ7Csbee02czrHw3gLQID
-AQABo2swaTAfBgNVHSMEGDAWgBSUAbz4nHw/6JK2TckGtNNyMU46NzAdBgNVHQ4E
-FgQU9ghpzs2MqUouYVwzB2XsoCyL6W8wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQADeKlzkdXLEofSM2r4
-SIPYc9g0A4EXIb1h+1YhhYyiuhSRb3zpAHlvgtfDaHu/ic2pHNDRKAjHGf6349p8
-OCAnqQvl9yZIvOa5/N7F13V1Ay+igdgGSPXmKRD76jX5ccQvoEQUQlA9G4P5/qaC
-IonfinaLZXjcklWJuhV/XMzYWA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=keyUsage Critical keyCertSign False CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:01:BC:F8:9C:7C:3F:E8:92:B6:4D:C9:06:B4:D3:72:31:4E:3A:37
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 37:7b:99:a3:64:09:89:d3:3b:eb:15:ec:5c:bf:4e:86:74:eb:
- de:88:f2:7e:33:ee:e1:2a:ed:04:81:bd:f3:bb:33:69:16:ca:
- f0:89:38:11:1f:5c:11:ba:83:2a:be:e4:8b:ff:12:68:c5:58:
- d4:fd:cc:fd:58:8f:49:5c:6f:2d:86:7c:1c:86:b8:b9:3b:4d:
- 47:06:4d:e3:f5:d3:c4:f0:b0:e2:56:41:19:b9:a7:08:77:78:
- 80:49:55:f9:7d:d7:b0:84:92:28:bb:25:e2:83:75:e2:59:a9:
- 12:8c:cb:d0:7b:03:c7:30:13:c2:79:d6:c5:9c:f3:73:7d:63:
- 3a:e0
------BEGIN X509 CRL-----
-MIIBUzCBvQIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLzAtBgNVBAMTJmtleVVzYWdlIENyaXRpY2Fs
-IGtleUNlcnRTaWduIEZhbHNlIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaoC8wLTAfBgNVHSMEGDAWgBSUAbz4nHw/6JK2TckGtNNyMU46NzAKBgNVHRQE
-AwIBATANBgkqhkiG9w0BAQUFAAOBgQA3e5mjZAmJ0zvrFexcv06GdOveiPJ+M+7h
-Ku0Egb3zuzNpFsrwiTgRH1wRuoMqvuSL/xJoxVjU/cz9WI9JXG8thnwchri5O01H
-Bk3j9dPE8LDiVkEZuacId3iASVX5fdewhJIouyXig3XiWakSjMvQewPHMBPCedbF
-nPNzfWM64A==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.pem
new file mode 100644
index 0000000000..b3509c2e69
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 26 27 30 F3 44 29 A8 E5 D9 F4 4B 83 92 0A AE C3 05 CA 79 96
+ friendlyName: Invalid keyUsage Critical keyCertSign False Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid keyUsage Critical keyCertSign False EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=keyUsage Critical keyCertSign False CA
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMma2V5VXNh
+Z2UgQ3JpdGljYWwga2V5Q2VydFNpZ24gRmFsc2UgQ0EwHhcNMTAwMTAxMDgzMDAw
+WhcNMzAxMjMxMDgzMDAwWjB5MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBD
+ZXJ0aWZpY2F0ZXMgMjAxMTFJMEcGA1UEAxNASW52YWxpZCBrZXlVc2FnZSBDcml0
+aWNhbCBrZXlDZXJ0U2lnbiBGYWxzZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANf896E4DA1yEvLrX3/cGYNrRlVf
+A76pwTLL8ttdnT5H5CjhJ+iiSRGJex/SIqyw65lOAji765fxX7F4zxrYr3fdS+d2
+dPzMwT4K7a7EHoM+CbjS4cK6/8h6YinfliLa8vsma1/cNNTImaTCAwbJu12j7PzY
+9c/z6mkdrrtl2FFO2QNATVfkr+W0ySGvl6i3ptILE4cveSRZcUBXJZRF5PF35ntz
+DETThlUZ3gm3BpW+qVskj4EkaVvdsVh4dAU1knFbzC5QeamvtIsaVnOcGl4bq7dy
+PQcNI1BNUfcM8ohqq8DaHl+lxpIkL2Wctd+C/TivzyP7dAXFk6tkjWcJ/SkCAwEA
+AaNrMGkwHwYDVR0jBBgwFoAUNFULZ/wcsdzCcgoU8GPp1JvwY/kwHQYDVR0OBBYE
+FIQbJBPifwi611fyrtWctSgqZB4dMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAJmjrWO0GlQGCOakvQrm
+qhUsHPSqpZKgM1i2NSp+MnJp3zJoHa9kp8jwkykLSK2AuKKfoLOixQ4r6dLmwLkJ
+rlB5V5vmNVUCSqgIjD+vN2QAiNsE9R0ct40c0XUiTNv+87XTzZ0Y9XrsvHi5OAhy
+t0d3R6lFVDmLB0S0/BueNpW9JPW0R6Hj5p9aDJyYHllAWNzONsr6PVwIfKAw3I2T
+PTS2uEwVSCRi1bp1itJJOsefwogh+EXVwAaT4CcA98XllAGn4aw7l3niL3GRhDN0
+r4a80Zy4bCS42pAvqpq7BvzGlP3UaW5vRSPwV3MGyX2W7765rm05lT/QuGApTZ+K
+Igk=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 26 27 30 F3 44 29 A8 E5 D9 F4 4B 83 92 0A AE C3 05 CA 79 96
+ friendlyName: Invalid keyUsage Critical keyCertSign False Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,813B1DE6E55637D1
+
+baDEG0KJJmA76GdmNBYhREkCTLfiBp9GtpJIOrbe4/Y/GFmSqQrGpk4Xd60VAaRb
+crmQOYbN0A0Xnack4U060+KskFg11RpR/pE6MBN4WxyOx1R3wUSiuaPh/taxFwMA
+loI+Bdyxc+jA63BtC+cwhzllusE2T2pNLW50YMnwV1XmmjO61VMJLLKs2P6FCi1Z
+nE8z6ycuQl9mP6VAB1p2mB9rzLY4BkQS6vpOhpxVGj+flMu9qJyVmn1y+TIdjJTP
+xrpyJrXfnJa9uvdAgzi/XAN4W0/mCyMqiTa+Q1oKfjAGCItG/Hfqozh+GY5OsEIc
+acKW+i+3KPNy+4oqo+IYqDRFD1YfUntV1DafkFBV0Cqjphv3iHUh+gmvPPRlhDI2
+TupL6/zUogp4jEqq9LSROWNOqvQMjmUPDaaPiHfNd5Oaf2yvMuLhWiZDeqvePjNw
+BOOftWofOWOa+a0WNq3l/O2ldjCafUOAzqDzrWjMtPy4GlZy1KVtopS53Jrrd92Y
+cyX55wc2cUG7QGzWhYqbTC36C/ePg6Gunqz1+28vkReKdsfF/Rn7GVuT++H0kLPk
+GdzjjOaTBB3PO+gpubpq9oXQTj8W1Imt09rfCZhmaatWstqGc3j89ypSDTd2unfm
+DHrGsDsbIAPfDsqX8RhlGouoB46GrsxcT30VztHabMQ2G/x2Kc4RmMbCxp6INaP2
+dq3g/2sFpiLycHmXFGu+rRYWUP+PlSuQnRiOaLGaLnzibWgmR7tGcHSUcU64dWHK
+TgwselBiKHQUnaMz4zY4Z+BATbZonL5bIWIEofRiGEeGyyaRguMAc7jQJRN4kb0h
+dynrxzD6mZLZ7gA5gh/Aay61CrDhA2/7NTwVhrZeYDukKTvJox7WT5DpS7Mg+RGu
+uH0HzEfWw9Y97l2N79t0PCvfXcfAO/RhbisLp4m0FpFACiENbBVatYrIKwTWmgh0
+KL32vu8HFGxR5Aw1CFIez7+J1QJ6wvcvGhDtMN6lU7N8AfgUhS53kMBumz7FKtyd
+J1jmDBY5iDfPPcv217VENjF/3mBPIAZtw7+gbIThuG+8fjcKKp4LqaaRdBpeMv2g
+eaN89jRL7/bO+/7jnQymSPm5DHHMHbKwA1ueY/eW+TaHgDnSp2PWvtRSi9CKSMSY
+3x+viL4wjDqlv+ruiDjIgrx8dNpZc+hv9nFYHH3jYT+VlzAK8CHxHXnySD9Y+47L
+kclbK7QZvOrl2XmP6QHjQE+BQBtNpxkbqkEuDQCuKCqew7+7bGBXkXFQ+3NS8zab
+YwBr0FVOiwFKOocJgW16CdAD3fQNIdrT74lBVQBLaAWTZVsvGV9jSSu1Tict7ku6
+GIcZjZWG1anwH8327XoXmjG7Vii+ZHZUAZ29TPucMmICWyQjcBXM9MD/Ip57qe//
+CxuNovlwwgcn/VTJ07c0zp04iTnG2CvYDEhmHBQ65HPl3nR0T77j/06V1/fwesMf
+lADnfRsHXYajjj7oawzhawGtv+74dUTMKVWgOK6tJyRR0XnU5gZCHLkX/d07vQcW
+c+C/3BxYLD8opbX34Z2UVxFQxxF4LrX+sd0Dob8oDuCfT0ixrxSdsrLRTg255Q2N
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5.pem
deleted file mode 100644
index 0efaff7138..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=keyUsage Not Critical cRLSign False CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBITANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEvMC0GA1UEAxMma2V5VXNhZ2Ug
-Tm90IENyaXRpY2FsIGNSTFNpZ24gRmFsc2UgQ0EwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAMLOm8AZjGbhdJ7A5TMeS8YqKDv+sSvYbu/N0xYhBYw9btWqMvhg
-UQRchnPigIMNH270hJTB0xUODgi5kEfd3aMcqP4p7092jT7nGwWiWqMfcOiDob/B
-jwJbfa/pcDWtLtL9gGu3mD5phBMV422/vXk7DNPVTOsm0LK+kYcbkutzAgMBAAGj
-eTB3MB8GA1UdIwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSb
-FqRb5CIAWLVWFP8usoK/Iuj2+DALBgNVHQ8EBAMCAgQwFwYDVR0gBBAwDjAMBgpg
-hkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAXayz
-RGBvRtkZyRHdFZY+3aIHHo7AdgjRSbvWFShHnbrZnd2E8mbkkk5NH7sD6IQygi5b
-6s2ZEpMFRDc8NNSG1Qh5NagIp8Wguyqa8HgSA15CytfKd9nDdIY8NSFPiqXCXIOp
-AXIf+LI9d8QnF/zOuRdKQiX26iVbh/Ofiij5b8s=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid keyUsage Not Critical cRLSign False EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=keyUsage Not Critical cRLSign False CA
------BEGIN CERTIFICATE-----
-MIICrzCCAhigAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLzAtBgNVBAMTJmtleVVzYWdlIE5v
-dCBDcml0aWNhbCBjUkxTaWduIEZhbHNlIENBMB4XDTAxMDQxOTE0NTcyMFoXDTEx
-MDQxOTE0NTcyMFowdDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMUkwRwYDVQQDE0BJbnZhbGlkIGtleVVzYWdlIE5vdCBDcml0aWNhbCBj
-UkxTaWduIEZhbHNlIEVFIENlcnRpZmljYXRlIFRlc3Q1MIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCniZx3i5eOoYfB4+DHDtBDWS3+uKOzezExgLASJeRuST/z
-FBDywPOCHD9BqbsVdo+fQMjOEBs5C2QePhrQmo36vBpuTGeS6o0ZwnPqZEiR7BDm
-BhaU5GfHWArITIQqqKeGMrcd6inS3EgiNfLoIgErgIYUE2Ay7N3jNAkZ+gHFsQID
-AQABo2swaTAfBgNVHSMEGDAWgBSbFqRb5CIAWLVWFP8usoK/Iuj2+DAdBgNVHQ4E
-FgQUO/h+SZvyJuF7i3RkSFnq+ekut+kwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQB63lqdcOrQ5elffexi
-Pm+erQomlHA4QBd/o7W9oGu3wh9o/OxaXUX+q1y/xsFQPWY8rnd9WX2K/GbDnAkg
-b9VumR4AI31DBsR9ON1LP252rSHzpH5VeLVX4yp+RU1J6VvXAFXD3RgVwYE16JFC
-NKsFf0HL8FRjpLQp9+/qcp6A7Q==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=keyUsage Not Critical cRLSign False CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9B:16:A4:5B:E4:22:00:58:B5:56:14:FF:2E:B2:82:BF:22:E8:F6:F8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 09:d0:9f:43:ea:14:8b:96:bc:51:a7:26:e2:ad:a1:d9:85:d4:
- c4:54:67:72:3b:27:b9:51:74:ca:a5:72:a2:88:21:2d:f0:46:
- 21:ca:5e:36:02:5f:bb:9c:1f:a4:84:63:64:8a:52:5a:17:b8:
- d5:5f:3f:d5:73:38:f0:f5:7e:e3:59:80:ef:1a:70:89:da:37:
- d4:b1:31:4a:94:01:ea:c9:71:98:aa:c4:ae:e2:8c:18:ab:7d:
- a9:7a:fc:23:1b:57:ee:90:81:0e:29:4b:c6:1f:78:2f:65:4d:
- 38:df:f9:6e:74:90:71:57:a1:aa:06:4a:8a:a9:15:ab:87:17:
- 1a:ee
------BEGIN X509 CRL-----
-MIIBUzCBvQIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLzAtBgNVBAMTJmtleVVzYWdlIE5vdCBDcml0
-aWNhbCBjUkxTaWduIEZhbHNlIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaoC8wLTAfBgNVHSMEGDAWgBSbFqRb5CIAWLVWFP8usoK/Iuj2+DAKBgNVHRQE
-AwIBATANBgkqhkiG9w0BAQUFAAOBgQAJ0J9D6hSLlrxRpybiraHZhdTEVGdyOye5
-UXTKpXKiiCEt8EYhyl42Al+7nB+khGNkilJaF7jVXz/Vczjw9X7jWYDvGnCJ2jfU
-sTFKlAHqyXGYqsSu4owYq32pevwjG1fukIEOKUvGH3gvZU043/ludJBxV6GqBkqK
-qRWrhxca7g==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.pem
new file mode 100644
index 0000000000..56a6656ed1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 3A 45 96 8B E1 9F 54 7B 94 F1 83 24 33 A5 5A F0 D8 3C 7F 09
+ friendlyName: Invalid keyUsage Not Critical cRLSign False Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid keyUsage Not Critical cRLSign False EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=keyUsage Not Critical cRLSign False CA
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMma2V5VXNh
+Z2UgTm90IENyaXRpY2FsIGNSTFNpZ24gRmFsc2UgQ0EwHhcNMTAwMTAxMDgzMDAw
+WhcNMzAxMjMxMDgzMDAwWjB5MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBD
+ZXJ0aWZpY2F0ZXMgMjAxMTFJMEcGA1UEAxNASW52YWxpZCBrZXlVc2FnZSBOb3Qg
+Q3JpdGljYWwgY1JMU2lnbiBGYWxzZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6kAGMAGNnO8CvJ2PjAYd6v3pcL
+vPjKj7gXi4mOj0xJc1rp6f/8pxy/Ua1aPCyRiGonwfc8rZb/mdR+HKpTTJjZgygW
+26aX93qRrJIvvb/Vie0yu63PraLINIUKzg4FeTIAmCu3g58FhVdsaLALdA9wD6st
+Ru+BcE5BbZCssejYjMxiAxjrv7GWE08R/O+6u5GxqE+3ZWg4StDq1UyvDL/HhEjc
+DmuODxI/sruN7fMv3SN4o+GfkkennaAnYE4YWK37p8gbeUSglVsTHliyEPFcclH0
+sAElmBLEOfkZK6XRGQVln7g4+CjmbSuvuoZUKT4RHOPTwdoXB68uwIALDW8CAwEA
+AaNrMGkwHwYDVR0jBBgwFoAU+X5SoHlmBAhECGV5EA7dkOZD8dgwHQYDVR0OBBYE
+FP/OMrJ781bfdvIdIFOwNrNmArfaMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAIvo2bd8LXplAdh4RhqY
+XGsOB5E6oyj5lqaZ9SH+wi8ss5J+Oiv28rYRYVqYnS4ceffJz0q9waAuab8GIbfS
+NWXIfsXTncRqEq2kM3W+/77qIItkjcfEOCxV3rtWayCd/ugW+dwO+YChBRdiAMV6
+VkBLR4lo8pO+rT/pS4REBTZbdoZ2ToQB3RF2M4AJMrHGzeBi4vMNcxTVo9iMnvOb
+QvGLwU20mmMt5+WsR8HZviXmOnyhikb/pba5sLhFm+kY6VZoZ4eMaGIjbs9okOjs
+hOyxLkfZYsICWxDMrHeLnat1/hV7dQ2jZd4iZzvXaHfRK16y9c9kX6nXeQRDuays
+HpM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3A 45 96 8B E1 9F 54 7B 94 F1 83 24 33 A5 5A F0 D8 3C 7F 09
+ friendlyName: Invalid keyUsage Not Critical cRLSign False Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,15F9F9CF3F6BEE9B
+
+EfR+sG4W6NxweenHODSkvOFk6tg9VJLdcV4Ui6KXy36UW24j1fztUlUu6RJE7XKc
+EVvhy9sXPngo3eFOS5ziK5aY+rVMuDHp00kRfG76P4iCUpiPo6BGXrt+gBf6CQ39
+Z9Z5U890M2Ljt4cpKj4lTdHSsAef83Y7GZM4xgH2V5ihTOgO71OuDnZdtDrfoVtJ
+r901xr35u+1spyA9EscEMZqgbffFGQK8rBEdCR3dH2EPawxdrkj0Ud6Aa7meY1BQ
+IGkzbGDasO7aLJMxqtJfwWe2xaESgDKo+g5Z4Yh2xcAGH6MlHLIt8iN3OhFh7qaC
+kTnGOySSL46dh4oHdk0QoiSjVuICYkXFZLXxiaP7+4IRRFo1+4YTL5Hw2nd9afO3
+1xb5vqewZULv7td7NT8NGBHHFDnhY2Vi5Ilg5NHNhc8VIqsi9DBT50ShaBgAdxLO
+2X1SkBXFeYPFVfVgJUhDLAzFU6lm0GNGkX9kz4r6f5bmrgEAaPC1Ct0rq5m92Orn
+VnfNsKg2F/AHa/VzLHA9HNHqPatin/cFC5rhLRLpssKdFuyJVnuBg6LeUeuiCh1g
+FmU2w1Ka0h0/0YEBOxY+QfeGWoF7gEhX22o8ttcUTsFs2BQpnVKmuW6S0JZcH/f2
+p6ykr9pN1Sl7C/sE2MLoF7zaCFxHBUG4pdabi1D3Gx0ch9bD28M23W4NiJYudACd
+mf3scQDlABKsvN2AV+StGcza+kbvRJOjz9EsyEffienzc2qfPcgm8G/NyX0TiQn9
+8Ci261Db7gpdDdJKDYjCfi3zMhLhyw+hVGI4f3rb66GYGwIOk9yf8vhwsMaNuvHm
+eCM0AEX+RTHaZixPhPSfCo/LLdK/YN0zGwERcdii7/8sS8WrhZk5u03il9gf57l4
+vHf03lAcZSZB/5aZJs0YJil0Whb3li9BIZRd0g5GF36qajHEGbS1aNgmyQ2H8Xuf
+9B7/sVDgkK4X2NOqxMqsrSJmDJ+vF1+UN3e/pKlwSNNffTzSMwTHzexHOrsDdHnm
+GqoLOhtnCtqTq2f/r9LWCzkg0nj/oboZfIxIZKfnRV252N+2/XWKkLyJZnLvfrdC
+NYiKukdLQpYVCvwknIq3aWrnOZLXogqhFcMHCQY5W7F5mWUefFtklYZ3SYB0i7Y1
+lSka1MHLVxkDiycVh4EW4MwEJ3S58I5lPqOclktKuz2p00C56D369lS85Uds0L2L
+jRi0Ojz8C0QctT/QTunJwX9ev7XJSR5UNLPjkGsEcGF1YEd0UReKFo/wZTM39bvq
+uGWfYEAS4MrkSqNHlXeoAY/luhb6PIbTOE1/Y0Sl8hXf91GeJNWDfLSo+HuhObtL
+GmXTdW8NTWmDnHPbQTh/qnFCWwZLDZD0cytnrUKpgEqW0n6/kTKURlvQRtDAVWWu
+U67Bc1Jypui6OLWaOX43ef8HFF0KTORX/luz11cBu0aiU1T5lwdAcYCEZSHWNhLw
+x1DiNKhQcnu6PSRnlRCp2KLcF8A+oLDyjBAaEVT7Mw51o+dt5dZM6qrDmv2UDWL1
+wFHJW7E/MRw9S07KCB3YgnLQUKC2hHK9pjIw4qDcn3RxpaVouXaZbg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2.pem
deleted file mode 100644
index 7fc272ea18..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=keyUsage Not Critical keyCertSign False CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICjTCCAfagAwIBAgIBHjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEzMDEGA1UEAxMqa2V5VXNhZ2Ug
-Tm90IENyaXRpY2FsIGtleUNlcnRTaWduIEZhbHNlIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCo1QPZC5T5F1L7XkkAguXC8vf9C9YbYfj8VbP8CXU6/3EG
-wUPK43eDJfWBzzwk7bgumreNheNFRcFW+dcroOFvVflXXBjj/UR7qkXULMf9DqK4
-dqMYYafyTrI3QrgNfdN06ngaY0qNnXa4Z58ecPAQPnQprJHJ0fDTlwultqudJQID
-AQABo3kwdzAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4E
-FgQU3wy5NIl1eNIjkh7wgSHfwnYXZbQwCwYDVR0PBAQDAgECMBcGA1UdIAQQMA4w
-DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
-AFYPjvJm9+IVM7cHs7OMJLoeNCnhUL5nlx9HuDLzP6/+0o4V3aQgiP787/zfOBFj
-yWLTLfKqJTkm+8fs+TLFf675Vs2s3dPELXJLvFwgQFYDiSQpV46thD7NLw474dse
-tN1i9Scl7y0RsDHbi9qBIPsRX4UV8/8nawbo9yW8hpqt
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid keyUsage Not Critical keyCertSign False EE Cert Test2
-issuer=/C=US/O=Test Certificates/CN=keyUsage Not Critical keyCertSign False CA
------BEGIN CERTIFICATE-----
-MIICsDCCAhmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMzAxBgNVBAMTKmtleVVzYWdlIE5v
-dCBDcml0aWNhbCBrZXlDZXJ0U2lnbiBGYWxzZSBDQTAeFw0wMTA0MTkxNDU3MjBa
-Fw0xMTA0MTkxNDU3MjBaMHExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENl
-cnRpZmljYXRlczFGMEQGA1UEAxM9SW52YWxpZCBrZXlVc2FnZSBOb3QgQ3JpdGlj
-YWwga2V5Q2VydFNpZ24gRmFsc2UgRUUgQ2VydCBUZXN0MjCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAp67g5m0ja/YdBc6nUr+UTz3XzQoajL7y9/EF7M0He7yq
-nlQvh/d2kEpE3e0EUZviJtg9L9sxQRgCFWVR+f9rLpPNEBIAZ2HQ83SxFRr+UbfX
-LTOLNaLhasu4lG9LY8DtyYxjrnvmOHkvTk14kD9L+YPJbR9LmCjNHbmoFiNu0Z8C
-AwEAAaNrMGkwHwYDVR0jBBgwFoAU3wy5NIl1eNIjkh7wgSHfwnYXZbQwHQYDVR0O
-BBYEFLkvB65lcMDXjd55uk984ACgePDSMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAE
-EDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAf9WmZ9PcF2mY7Fst
-f0t6wDbfkMenvluK5yTnfZGZi1Xa5WFt+1ifSxYjkxTMTw4DJ5IXWRZNr40+NhCo
-2dvFQbeTEh90GuwSrFOY1LoT6stxoc/OXatyOCuO4rved9tzjRAArQndpnd6Zqsd
-p/cT+7yvFwM9fxMinMUy3p6rR9E=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=keyUsage Not Critical keyCertSign False CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DF:0C:B9:34:89:75:78:D2:23:92:1E:F0:81:21:DF:C2:76:17:65:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9e:b2:db:db:fb:42:09:bb:05:d6:af:1d:1e:b5:2a:e7:88:75:
- f0:e6:a9:52:0d:ad:a3:4d:a6:64:06:e3:53:b4:39:db:4f:96:
- 08:5d:ea:da:bb:09:d1:d6:32:53:91:62:ed:33:e9:0d:87:6c:
- f9:12:a0:4a:c5:e9:e9:6f:d5:d1:02:8f:22:9a:d7:7c:82:d2:
- 17:48:0c:c3:2a:c2:d9:e5:f7:0e:77:1b:52:e7:1a:9c:2c:7d:
- 5f:31:a3:aa:90:32:ca:9e:ad:42:ef:b3:9b:cd:11:da:13:36:
- 7c:cb:85:48:75:59:7e:6c:03:9a:a0:70:e3:19:d4:c1:dd:c5:
- 7a:3b
------BEGIN X509 CRL-----
-MIIBVzCBwQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMzAxBgNVBAMTKmtleVVzYWdlIE5vdCBDcml0
-aWNhbCBrZXlDZXJ0U2lnbiBGYWxzZSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU3wy5NIl1eNIjkh7wgSHfwnYXZbQwCgYD
-VR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAnrLb2/tCCbsF1q8dHrUq54h18Oap
-Ug2to02mZAbjU7Q520+WCF3q2rsJ0dYyU5Fi7TPpDYds+RKgSsXp6W/V0QKPIprX
-fILSF0gMwyrC2eX3DncbUucanCx9XzGjqpAyyp6tQu+zm80R2hM2fMuFSHVZfmwD
-mqBw4xnUwd3Fejs=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.pem
new file mode 100644
index 0000000000..713655159d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 96 66 5F 5A DF 09 34 F8 08 18 23 5C 0E E1 91 99 9E CB 07 77
+ friendlyName: Invalid keyUsage Not Critical keyCertSign False Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid keyUsage Not Critical keyCertSign False EE Cert Test2
+issuer=/C=US/O=Test Certificates 2011/CN=keyUsage Not Critical keyCertSign False CA
+-----BEGIN CERTIFICATE-----
+MIIDvzCCAqegAwIBAgIBATANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEzMDEGA1UEAxMqa2V5VXNh
+Z2UgTm90IENyaXRpY2FsIGtleUNlcnRTaWduIEZhbHNlIENBMB4XDTEwMDEwMTA4
+MzAwMFoXDTMwMTIzMTA4MzAwMFowdjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRl
+c3QgQ2VydGlmaWNhdGVzIDIwMTExRjBEBgNVBAMTPUludmFsaWQga2V5VXNhZ2Ug
+Tm90IENyaXRpY2FsIGtleUNlcnRTaWduIEZhbHNlIEVFIENlcnQgVGVzdDIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc8DNtbU9YabxHAoWqRyRxHTrx
+VL8YwSE94cbcBbMA4tskut30Eqd/j1CYbCrD9KIyn68THeypVDFGL82wg3/N2lZM
+P44b8KvH2ouJNqljDVDhipAu8Tjiun0y+3L9diMlpsfrx2ZSdDO+WbeHoUjovd8Y
+DrPtG0U6THisgQj9sgWI8oIgPpQRjoMIb1ZAC/IsMPYVNJL/a14dlqit2PsGpLnW
+RYEG064MAde5SHUfgV66pwAxisEWH5xl/v4Bbrh2mqMsQ16izLKStQiuW/sVMEdH
+iEJefQh4y8anEbWkudAUDvV31mUyHivZmfz8eldAy9ICi2RdSEOf0QCfARalAgMB
+AAGjazBpMB8GA1UdIwQYMBaAFLIl0igw0FVobky1wkjzypsV8kBFMB0GA1UdDgQW
+BBTzsk4G1clcuVdkoLbl/++tircPZDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQB4eFm1jkEg53bNCSXO
+pa2ViAfw7FgAGt0+trq/MaMv0SVuIWZRgkhDWSuTffNi6zC0cIXO+H/IlOA9pPz9
+CHnH9FRigpZleyl8/WMx9EeEYzpS8Bde6LLZh8nzeLiBsXZ3A9+Bp8lqfgMoj3kW
+GUIcMGyN0MS4PtXuuwz0Ur3FXfyXEEJCqwQ3iyiIfDvYaA2Qq+ttHZcJlwkzeMEZ
+pwM/lZZEnapou8sdKtfbA9h0+0ep6tamOC6tRv7Gz4OGtPKWstl0jdf382Oq60hX
+0TqCs8uCX5l46vnYweDOFzj9118sceZ9XXCYxNmRXPNbEf2guCrirvPZCRXcmE0v
+7AOi
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 96 66 5F 5A DF 09 34 F8 08 18 23 5C 0E E1 91 99 9E CB 07 77
+ friendlyName: Invalid keyUsage Not Critical keyCertSign False Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,76FDB2972170DCBE
+
+EaoMivLV7+N1+6wNegyZ2zfOaRVnjO+se3Y5Py1dOOrrUs6R7tv42WSmrU5nYbXe
+DkgVoQrH6xBqPbTLqewzqjvBycQM8qdVXUAI444cosm4tFV0V+UlU7F97jDYBrR/
+0c75ee+8dfUM0iS92TfO0+znPYFjstsvNczbL7O9XFS2IzdBVXDHWsevvzmTjOiV
+KA3iPFrpzUWhrTCYmZsnmjy5w2e+KTGQLhgN0RHDSj4kja7YZJWi7+nUtUjHKtIs
+T6AnvuthxCieYmaC2RCsqT0ptU6gyQQahMkr6ZTJqgvmhQTqDDdRE5xx07V2xol/
+JGzOCxvi/LlUR2HXyxt2Ip6k+nHixE6E3/PCmkHm2EfM766z6jS777etp+TOKsuT
+j/hyr3FT67qfp1/M0p4jTttJgSfQ+gmlIaNzYu31VklODJGzXJ6l1QxOx7TWgefn
+/K2Qi2WaQjEfKlcUZXVilt/DucRDsDPnMV70yMzl6VXiVkDDXSgUZg85AK0v/sKM
+EbqrDmZq+QbNZOh93/lQdd402ujrIcmk89O0Pq8V+9t2/Lkjiu0PWoEbAfUYe49r
+dMSh7biAlqfe6dXA+9h/Ggco00dm1diXtSZpdDrv1yyttLyCpaF1en8suqXc69FD
+30jjXsRSGZ5xRKnj1hfFiET8PD9TKuCvHDHCc4k1KttQaRtSzAEUvHIuN89SWVdr
+CiXTcw+FM8wrtRYM2I/GmrNU/klyHBycgog0hppUPUGnRJSevnw9CO2HiBLtSScj
++NlId3IjXi/zO6vmtxYtqAl18hK9aS8KU/lxsvZGhCHs1CDea8TQUW8womcYOKk/
+WFAs8KWcgeuVPPSExFXh9L0Gmcd45qBQLfSuFyc3IwBbptpOPTxnPqsam8fe7ohp
+F6DBClXexeZIOSCWFYI2x+heoO76W9caw31zkIAJpBGFB10FOoBy9uCApGdPj0zz
+zVHPD/EH7xkxeBGf0jMBTcf/j0w8otkNRSMc0TwZxuCN+1rMvG+5pcKNQA5xeAhG
++ViOO8Pbm+/iNY7Q23rSW6n8Og+6rZhgmD5LyIVW5lSJ5KH9yXJX2IhvHSYL1VZW
+5bAnPemCdIESLovzgj4D+ZQQVOPyoBO5jaltisqySTGVFKjWTvA2KHpB2khJQI3h
+sxUHAORjmSNOjHw9k/JFEIAr8o4U9XP1X9fsLyORVqNxAGuhatmllFRUv8QGEAVo
+IZfYZB1OL6qN3azk/hERP3DjHrnrNochgMmXgV6XDZC8D7fc20JcX3+LhpoVgIU0
+P+BBumdym8t1wH6XNLUUIS71V/BrWayt0luiJwiiju5AflV0rkdQ74wjanvcU5Av
+bQTyZYXTP/tw/qV9cLeNtyjBXHcoLXjWn6fyZmZRZfipGrGdIYmBtQIVUW+QDunW
+TSdG1pzZDOI5PHeIGpmeRiz7PXj1W0bTnuBaca/LH0DXu5DbuMcqS/plysObH0Za
+An9Mw9UFzlo445TXP9gwEllgeEeCiy33QCTmssgBRBiHNCSHW5C25igewYkChvvm
+7HtIjHWQF6hld+zE+YRPmR/DWbSvztovy7wPr9zlOzpOffC6f6r9SA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14.pem
deleted file mode 100644
index f1d3094eed..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14.pem
+++ /dev/null
@@ -1,112 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlyContainsAttributeCerts CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgzCCAeygAwIBAgIBTzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFExCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEmMCQGA1UEAxMdb25seUNvbnRh
-aW5zQXR0cmlidXRlQ2VydHMgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-ALSCJ7MnQSSfqf3cAKyFUJRK6CV6MSLa2t9JmoGgpu6snUGfPogvAguvdYP27085
-2+7ZAe2MA5+VRBKl2gtUJeS0qdMlrQyLMw8SBfIuCc0cMrbGnRHqeBPHPVdq1n3b
-xx+pwvDV2egYWx53Vyq72HVv7E6QhdGjEwO41216OFXzAgMBAAGjfDB6MB8GA1Ud
-IwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBTFKJWbEsMCo9m4
-+7Yd323jU625IjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAH50jqtmZxb9s
-51U/Olz2Z4OskoazeeNVJ0LXvUzF2vYzqBhXseLUd996wDmvQWsoczt8etO5zJdI
-/iXtC61WyqmSDgSSSEvoIAL/xWFYQh1QAjG+FD7qHxfJ5TUiVFUzkQe/nE2wSWYL
-oiZe8DkJHsi/T6sBMbZeNLcXa8CliLI=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlyContainsAttirubteCerts EE Certificate Test14
-issuer=/C=US/O=Test Certificates/CN=onlyContainsAttributeCerts CA
------BEGIN CERTIFICATE-----
-MIICnjCCAgegAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHW9ubHlDb250YWlu
-c0F0dHJpYnV0ZUNlcnRzIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowbDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMUEw
-PwYDVQQDEzhJbnZhbGlkIG9ubHlDb250YWluc0F0dGlydWJ0ZUNlcnRzIEVFIENl
-cnRpZmljYXRlIFRlc3QxNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnRFu
-rk1+JntR2FWOywl3/YsAK7L4yrNCEx5T7OIJOPeYo2gQ4HcNYzhCfrs8BnXBgRWm
-SmYiz83DHjDXf1v1EYvmLbuorfhe6oqbZjFFmFSFVYoBBQGoweqSBuEP+Dfz5JCQ
-3j/U5P9kHacuVt5EvNDFuxC2QpNlKDMKVp1kO1ECAwEAAaNrMGkwHwYDVR0jBBgw
-FoAUxSiVmxLDAqPZuPu2Hd9t41OtuSIwHQYDVR0OBBYEFH75KmUzZ/T1lVkx9E97
-tlW7zv91MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DQYJKoZIhvcNAQEFBQADgYEAcnsbImj6Bq19wrmv1lsHuwr0rR9v5AU5A5BvxBGX
-7L9250MNODFbkR2trDXDu8Aj4xDl14ksrH1CW5oqqvhSIN890dWabjEIWXzPJPXm
-Ogj5ekGTXsXnOsbO8CEfvjAvg8zfRVlWuR+mxGvk8qw4t0xB0GIqutURQegGF/zY
-tJ4=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlyContainsAttributeCerts CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C5:28:95:9B:12:C3:02:A3:D9:B8:FB:B6:1D:DF:6D:E3:53:AD:B9:22
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 4d:d0:f1:a7:37:36:13:e4:57:d2:e5:1b:bb:c0:68:35:91:0c:
- 84:53:55:01:9e:2f:bf:4b:d4:7e:55:4f:ea:6c:71:f4:54:a5:
- b7:38:50:ac:43:c7:85:b9:13:88:4f:36:5c:35:5c:83:56:49:
- 1d:ea:d0:34:ce:bf:d6:21:40:f8:4a:62:ee:c4:88:74:f7:05:
- 13:cc:15:90:46:d3:8e:04:5f:00:2e:ef:1f:43:cf:da:84:d4:
- 27:b1:22:c6:b5:ad:83:cd:aa:8b:cf:0e:d7:1f:76:37:a6:29:
- 8e:3a:e7:3f:58:12:8d:2b:77:58:b1:eb:7f:35:6d:96:74:f6:
- 48:1d
------BEGIN X509 CRL-----
-MIIBWzCBxQIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHW9ubHlDb250YWluc0F0dHJp
-YnV0ZUNlcnRzIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoEAwPjAf
-BgNVHSMEGDAWgBTFKJWbEsMCo9m4+7Yd323jU625IjAKBgNVHRQEAwIBATAPBgNV
-HRwBAf8EBTADhQH/MA0GCSqGSIb3DQEBBQUAA4GBAE3Q8ac3NhPkV9LlG7vAaDWR
-DIRTVQGeL79L1H5VT+pscfRUpbc4UKxDx4W5E4hPNlw1XINWSR3q0DTOv9YhQPhK
-Yu7EiHT3BRPMFZBG044EXwAu7x9Dz9qE1CexIsa1rYPNqovPDtcfdjemKY465z9Y
-Eo0rd1ix6381bZZ09kgd
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14EE.pem
new file mode 100644
index 0000000000..efbb15d909
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsAttributeCertsTest14EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 70 8F 11 3C FD DF C2 D5 D0 76 89 58 15 1F DE C6 C9 D9 E4 D5
+ friendlyName: Invalid onlyContainsAttributeCerts Test14 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlyContainsAttirubteCerts EE Certificate Test14
+issuer=/C=US/O=Test Certificates 2011/CN=onlyContainsAttributeCerts CA
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdb25seUNv
+bnRhaW5zQXR0cmlidXRlQ2VydHMgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjBxMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTFBMD8GA1UEAxM4SW52YWxpZCBvbmx5Q29udGFpbnNBdHRpcnVidGVD
+ZXJ0cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCupG+ZQFa1+AF3vKIN0iZQf4EAprxupX4n8IgjFQWXI42ZN8sQ
+rgpjM7GU/jQbheNxHcuZSPIkp9MAYkaoESZsq81ai045iqZRKEsCnoL8rWN9OJVK
+wRSkHXLeKfaRhYo86JFfjx0KkefPGw4G4IIxbtlulVcc/q4OSa0cKNEhrDQWD2uM
+dTNhHDYQQxt6kHaYZRb8krtPWwlEl+s3oYAVfzYo/b55hKlWCBkGa17X2RfFreGQ
+WcV+EseidphAB5YytCiZMsZ6L6CW0DEICVYi0OhH/0UX0BgRdOIvfgd2PRmL6uGj
+Jwd4yqI5aGfLOTF7bxrjqHdPOhdNJXHlk4VPAgMBAAGjazBpMB8GA1UdIwQYMBaA
+FE0H/vYtvLUZGlBN35kEem0zcJBOMB0GA1UdDgQWBBT/0UE0DUG+pU7lJIfWua/D
+vs0c6zAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
+CSqGSIb3DQEBCwUAA4IBAQCOPkqYnbLIBrJBXY6Jdcs0/qHhYCKjUGuwSM0xV+ui
+/11R419qTZlDeVEkUnF6wzHa2LrvGOxQuRfGcW4GeOnEq4p20iJy3h/kkZjwhuTO
+4GfrWYkHIH3wFdQ8xwSOW0egU4h+zdki7Z5ABi0nUYWQMV0bcIj5t69r8YM2Y/DD
+dddGgtxOkM5wJ1zuaFEvDT7YXrPXv2ndPy1j2ZecQ1N/87XS5Vt1y9whcfUyT2E1
+vy42AkyG+ePgNG4Z/ldDXOXYpCmfsITWgipmmkBgHztWgfdCRq780P1zKRwfMWyl
+C1ajhmo05Zm2uO2rQ1QoyzseVqS9d5oW9jEPaRQ3Q/FU
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 70 8F 11 3C FD DF C2 D5 D0 76 89 58 15 1F DE C6 C9 D9 E4 D5
+ friendlyName: Invalid onlyContainsAttributeCerts Test14 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,60AF22A385D8A200
+
+vOM/Va8LUV+WEEoQr2eSsCybH+PMQPzHDwFvGiy7JEPwODr0e6qeaEaWFYj44RDN
+/SWUbgktQFzykev9OCIiyUP9cbGOD8T3O62k5omFStgZpMIF7SysnBLK1Tb4wLrR
+U/xA+h04SsZpUXWbVtTV8kIzG7zjoEVFZQkTMYTM46ax+wVCsF6O199rofHjtUBV
+hOwqE6ae2ntBrAioWIPI2iiZMhdJUk5fX8Meq7rQLBmEXgrNZlRVJn6OIjAjTpin
+UDu6Wh85Y4oEA6F/+JzhA5fF0iglRL+8NQEAwGTx8uLs3BzUGNisSBtiURtLoNvK
+/LU/iUcUfoU7YZDW9SgfE5LCcEJEHHj/kiCFsu491sCFS+6fqNMM7E20bxZZ3Ufn
+3ZJ/eBXapNI/rhqTlFhyBWxrOFhMcbuK8smmTsG1EOrl+B+9JcGZbjJhNfX0MIhL
+w4nLxg2+GS2f3pxz43c8+RkxdENCPe2DSaeTn15kNgo3KD1gg0aORN0OqFee8X3r
+lWbSmj0jwjLtxoEwy36A1K+sCVzvNy7ai2iHwk2XzPEgMK7rvPjjL0XPEI36YvMX
+LeAm2MGjAUHlzBoqcCQI4juhRT+tyudaW3+zfQeoM4adlja4RYpSV+7CGJsjvZ7I
+GxO99Wojl7sD3B0LhFpMAqFob38dqyadETWys9L9OcqQJwi657b8VfmnfIN0V61Q
+H5Nuo0rHmHiz+QJOEBwXj9KwMpPEBp6wl1KJsMuf0YbVDERd6uFdlH+nz7JnxJqU
+TE7GBDI1CC1Sw0eRBwHLMgNnJGF8BDa9dtTDCGhfOU0OWaslmMMsno/I7ujztQ0Q
+HElkSzLasv9u7eDeBN7c5D6e3Wew0FNpzG9c98SWbGa7UZRU24hKlBy6eLKNmCAg
+e+YrtxfJ6LZ1BGiq/1wAK+wePdG4WPAcOEmj3LmDTvCwwvs9tp93wxVdNK2U3eKD
+MN9aAHZvYBRatOkuuF5xdTUXHSD/xOCPCvrGckGPhd3UP4TXmynqJxXDeJLZRRQ6
+Xtm9TB/AyWDnfBqNQY+oWEUzwxHPge/rexI14MCptsA6vJwHHVZISwHyTme9yeUX
+XnXudqEoFpDPp6CJufFXQJZsIadgc9gFlRfQ+daqzziKoTy4HplpZ9uTjsPS5soD
+hO1ZqHX7XU/7m0eSRKzp0I2/HdZr/JycnU1Pj19vzbrMsgccfOq8Ih8et+JJsid4
+50/x5sbNdj8UCDEbF08sn+TyOqnPSibburaug3K3mLFOhCb1ss6NV2nsnRV1xquU
+GzbYay1ig7I1un9XDnNzva4jcuQYUfQt2mogStozmkmBrvDIJr6VgJdoUWU7MNwK
+CT7wZsrP760mh5Lf5YrRJm8DSu/QjdZ/Kq7b45DTHeBjDsdj3KPecZ8qG1gBcmNN
+eODKpKqmXMQDDioJFXp8ljOIr4zgZHd7w2HiuxX0BqnQZUNyenymEmHEABzM3Qn5
+WpsvZT3uB5HY5R/sRcu/mPqm90V0Kyv+68WvKfZSWacOZpYP0QEaLMcpqoT3QnL4
+F9ccIQ4dx0Wg0V3+sVFnjaZGYYbV4mJHOYlyD++eHwERceloZPIZ7A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsCRLTest12.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsCRLTest12.pem
deleted file mode 100644
index 14d5cba2f9..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsCRLTest12.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlyContainsCACerts CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfDCCAeWgAwIBAgIBTjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWb25seUNvbnRh
-aW5zQ0FDZXJ0cyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqP8z3Y0v
-UCVXIVXCpbr+dcdoZFi0UZQPvl77hqqVORSs9FefV5mTeuoDDfhtUYa+O6Wzh2v/
-Yzv1MzPQzePG3eho/6CLs4pzqVWZDzYTG6OXubjPvYT10WykqfaWuivcn5YxbHuA
-cRitNsBAvY1Nq/kPDtsPJz1t5+PDRVO64gsCAwEAAaN8MHowHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFPOhB0Zne+mPWavrVYaTyKzk
-VbcYMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDGkMUjQFfto4SQpRJ2fAeU
-qXp2dn4kt+s/ITPOIykUFaybQ6eaGRcWN4kTi7IufbSeI7lmaa4SC+bq14tfSf/w
-gJSpwu58pIbPHKN0IgB+9S8eRS8wmB4HcBflmNZz/NX6wJzwJt15ZC+gek+eZGUw
-Qck6L9wt5i1wMFyRwBmAHQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlyContainsCACerts EE Certificate Test12
-issuer=/C=US/O=Test Certificates/CN=onlyContainsCACerts CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm9ubHlDb250YWlu
-c0NBQ2VydHMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBlMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxOjA4BgNVBAMT
-MUludmFsaWQgb25seUNvbnRhaW5zQ0FDZXJ0cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0
-MTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANFmoy4sb7+FLLRfH0FTJkEA
-4DUgy6WKlx+o6gViRTKyicSNbY5GWZ31r5z+B8SyeL0HaAYwkDBBNIJ2tLhSgKCs
-YASvqHqBa8YgpnDs3fh7d7perSH4t7SLblf2Ul9ABuDvFt/lCizK2LXgfDhcdrUU
-D7ZeOZTr59cuMd+tAN+vAgMBAAGjazBpMB8GA1UdIwQYMBaAFPOhB0Zne+mPWavr
-VYaTyKzkVbcYMB0GA1UdDgQWBBSsVnmrX9OpfaLqvFvE4FydtKiYrDAOBgNVHQ8B
-Af8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUA
-A4GBAFqv88cSXJ667X0tM4dQ5AyFGYONJIioud7mI0SXcDeh0Me/J1wmqDmlS7oj
-3vVTE6unv0EjjtEcLJr6FkHqYIksi9Fsuudte8FvQQ7aJEz6nzBpTe+kBINtK59k
-picBSyDN77AoX8AMqoDj39NP9DCaiq7fO3XL2Ei0MF4uG/1Y
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlyContainsCACerts CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F3:A1:07:46:67:7B:E9:8F:59:AB:EB:55:86:93:C8:AC:E4:55:B7:18
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 54:27:ac:fc:b5:7a:93:93:e7:f2:e9:63:f7:52:ad:20:08:4c:
- 52:08:62:e6:f6:81:71:1d:72:f4:1d:bf:db:06:52:d6:4f:8b:
- 86:68:4a:ca:01:4a:fd:b9:7e:5d:7a:df:48:67:36:9b:31:12:
- dd:13:29:b2:8e:b6:ba:c4:20:31:57:4f:7e:c6:d1:3c:0b:e5:
- 1c:a0:c2:15:c6:09:5b:77:ca:95:37:31:7d:a8:08:4d:ae:60:
- 4f:3c:b4:ef:92:9d:f1:11:5f:a1:1b:2d:ff:e6:2e:07:88:4e:
- 2c:88:54:b8:e1:be:4e:6c:22:90:0e:37:0d:b2:8d:61:21:46:
- 36:29
------BEGIN X509 CRL-----
-MIIBVDCBvgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm9ubHlDb250YWluc0NBQ2Vy
-dHMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgQDA+MB8GA1UdIwQY
-MBaAFPOhB0Zne+mPWavrVYaTyKzkVbcYMAoGA1UdFAQDAgEBMA8GA1UdHAEB/wQF
-MAOCAf8wDQYJKoZIhvcNAQEFBQADgYEAVCes/LV6k5Pn8ulj91KtIAhMUghi5vaB
-cR1y9B2/2wZS1k+LhmhKygFK/bl+XXrfSGc2mzES3RMpso62usQgMVdPfsbRPAvl
-HKDCFcYJW3fKlTcxfagITa5gTzy075Kd8RFfoRst/+YuB4hOLIhUuOG+TmwikA43
-DbKNYSFGNik=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsTest12EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsTest12EE.pem
new file mode 100644
index 0000000000..7ee148209f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsCACertsTest12EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 13 FC A4 6D 9C FF 3E B8 F2 54 76 76 5F 2D 50 2E 88 CB E7 9E
+ friendlyName: Invalid onlyContainsCACerts Test12 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlyContainsCACerts EE Certificate Test12
+issuer=/C=US/O=Test Certificates 2011/CN=onlyContainsCACerts CA
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWb25seUNv
+bnRhaW5zQ0FDZXJ0cyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MGoxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MTowOAYDVQQDEzFJbnZhbGlkIG9ubHlDb250YWluc0NBQ2VydHMgRUUgQ2VydGlm
+aWNhdGUgVGVzdDEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/4K
+0zMGaBEBzUZZ6uDkrqE773KlasKE7Ymp+9lwJD/u21K+67usJGF5nAdf8TJo39zd
+gzRiXpjJDEi6vHev7JQF7ZAfBUzpawXXCWKE22qrXC5mPYuaVKpGVgVqcPc2wscl
+LgqbTx+M/Jv6tT3Fc7v6i0xTdr0dC/ibu6Z2RIYRzK9oqzBMlSNbRhtK+dAUJWd/
+8eLtuLcjZYnEpomjCvWrx5g+rG6fYynQVY8vatECuuqNl8xzKhjvR19OX5PTTU/i
+1Nk8UynsEEBfdY+E0p+wXbsTMbUT40F07tc6QdOOzl2h3vxAD/ndNElaGeaN6myk
+98oly7EBZvDdxiW/MQIDAQABo2swaTAfBgNVHSMEGDAWgBQlOMOuyi11eltN1MAD
+kogTIsdsVDAdBgNVHQ4EFgQUR+X98QRRekMAokMlz+LSmBXnQUcwDgYDVR0PAQH/
+BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOC
+AQEADDWIC5mPJ09cQA+cNKz5Q+ChL1bQA0/1BLW5pKJQnG32QprScoDhWue75BZf
+3xR3XvpQA1TQSDdZUSVyO3p2gr7EwZEfpmM6VqXV8V4CH5J5ftXdHXVZxjauLxXg
+xaS7ijTZYuz20GryP01mqFdd5xrtE2Vc8DeAs4sES5HkPYcmlMV+tlplmDO9S4Fn
+rGigBRCu/+AnyJqDXipXNn3cEY3FXPx/e8z4Ol0N+UeVq8QyRNDAvwO3h9mXlQQm
+tQ219UqTn8gUfIl0P89PC8FRXK+kzcHW+oqDeiMGqMov1SQaAnYUCJ7dS9j7LtKt
+I6J24jnmVifPHYRTxEoggCGWHg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 13 FC A4 6D 9C FF 3E B8 F2 54 76 76 5F 2D 50 2E 88 CB E7 9E
+ friendlyName: Invalid onlyContainsCACerts Test12 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,024C1D296C254FC7
+
+u65GxQQYdsrHdpxx4wp7d0J4WnlUBfQXvJnCauLK21H6ucElJUF9ILhdTst5vKSs
+jkNtGorKh7b7M2r91Wvc3GkzxhNBNgKJHW9/XsIXWc7KaO0X3d1rnts5VMsD3hmk
+ad4oO5NOslsJ02TKy/56rPTiQ9uRH6Y+jalbY0DPcy+6ul/IsRn6EZ+eRLcy/Bp6
+fSNiR6IvUWV8yr0qXuE/koxxW4m6JgL7x3hwi52GFEMewJ4u0Tk6ytTvmhMkQyAj
+pE12zRd3szUjO7OkSzqp3r4Kgahx5dmJBei6S0rc/nqoHDoy746uTVG0h55Dnvul
+rhOg/3Ioe1Qs0kToQBy/WFjzkJKD3opz0Y1vUm/KG2S9Wwsw5s6irkwO5s5tBwp6
+RJnW2TvS6bKZ6AJsvLGAhIh6m2MOeJV5H3FEqttA0cahzNfhLjIJKR3imEYVm2mS
+BU2LztU7sxlFSpJg0uGW1x6N5LQ4vTM6dS/SD+J5FpT3JSkokrjoI35xt15vkPQV
+94uIQuP5A5j3xFhakoWKvnX11ivb7VTr5kO4rcLMSsoqeRVD1+9Q/j6UFky1Uitb
+nwjRBHj8Xe9yBIJQQGhSe0f6HlC3DHsEMWgKpTHtUCNUuwEU5tDYJ6iULkpXz4if
+4adDW5d8yOWAywfdvOMyizl+GCbeyaGhHPUoFePmkoqLUtpBDhPgEUqUiUI7GlTk
+H57XnCBBvkwLmIRyrpcItU78GB9qFoRKK2/oyVGbtlct28Jt02GXQ0i6OVWyFUIe
+5uTlUrYJX51rcCbksk0zrLBkzYrUV1Jv+MRso1u5Ik/Zl8It3LGZSvrFcVjbQgf3
+mab0A7p19mElW51KmbQGTcWqXUNTsLD/7VPKEve8CtnQJ/gqWdM7ZN+w66X52uJX
+xvGgEDZf529wBfTuqLX13EVMovtcYql60MO9haH2Nlr1xs96vE1Vk8iYhxRt+c6Z
+HSZHGSJWhvt66pKRHxhyFM/csjoh2MAJPfKT9Ybrm2pz6rlSXdZ8I1UiBeN4Y/Ps
+97mxctU5iZI678tt7toQLF6PCyqrQKqWydLccd1145jz+R7tzwsBBfxCSsAJxZ8q
+exLe/FVRlkUK2yzRD5eDq0Axla3QuK3yzZ3BWV5Y+StUh+6BitLwFAZSNE7QZSRC
+tDUwWeyWMLuQLg2aWG/Lc+OPH8ypRQNeMj0fouQyxx0KFxP9cbK0Ue+k6lMwK62q
+1lYI0Ovv7dQ9CV9weSrmay0pPnv1mXhmBvQYN7jpT5VJIxYOo4n0/q5PfhpZLlj+
+OJB69K+AwPiPi5hPvX4LXn8CBSFJxb8fdR4lpGnU+MkKWxAoy8JUoQ1DZNxJCXyj
+qJzenggc5hmdaZBbjwFbSeqdwFuq3kk4lZkb90L/lIVTjS88pgsdRct/Q/bs3MYx
+HzZDRo0xB8nJNi5mZZyKYBAfG6hpFrPmTqTSgeEz9UjVY4AI2sS7Yoc0LZ6Vb+eJ
+DJ2pWSMmdfU7ziRp7eaiCs7TPzsk0aT92dhCcbKGX/mudxmguqtHYdlRgIJmmUUh
+9SAsK/4/yQx+GR49kpUcPlmBekrAoX7HcEOAjRHpgYk4V/UlT0PRrw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsCRLTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsCRLTest11.pem
deleted file mode 100644
index 237f79a05e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsCRLTest11.pem
+++ /dev/null
@@ -1,112 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlyContainsUserCerts CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBTTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMYb25seUNvbnRh
-aW5zVXNlckNlcnRzIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9uYsu
-53u2+DI6YJnVIbUEBXbifJtOvR4Id3dAWtLRtp1J1/cjbUdtunT8MP8UdMiOu5GH
-qkkjCow40bwn18zVUFC+tbTitFHZwkcY6vpoBiYh7kfUGyOWMuGhYDDmL6f1GyGq
-1cPMSG3TI65vxTRu69NqZ6A69+6oecCzEhZwDQIDAQABo3wwejAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUWss3HtJGmFwTlfjfuDr/
-EUCtFfIwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAB4p94csINQawOHlCIzE
-BoDqe6fIaND41iV0Ho1HK5OQyoKdGUAUm3cuoyXOmA++mMrGdqZd+xqQswur3Ve1
-iKj1z3ZAfFHI07GT7nOS9yTHPwIwW1FaFsaMkJyHm5McmiVJ2RVPcuhZM8Hg/O1t
-lEtxFRbVcGf+7bi5eI/HHmmB
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlyContainsUserCerts EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=onlyContainsUserCerts CA
------BEGIN CERTIFICATE-----
-MIICpTCCAg6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGG9ubHlDb250YWlu
-c1VzZXJDZXJ0cyBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGcx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE8MDoGA1UE
-AxMzSW52YWxpZCBvbmx5Q29udGFpbnNVc2VyQ2VydHMgRUUgQ2VydGlmaWNhdGUg
-VGVzdDExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgvtvHKcfaEySW+gTB
-goP/idcErgtO4WHFdiTLJV2wwSRVKNwruXMNUfgnsksQ+Tqa24KJWAJpnh44cvcT
-C63piJcmXs35SuSRbS3kefpDW1HmvkZUJ+xEp+jouS6IXKBI+bX0iASJpBC8rDtw
-TdyTa1MWv7veksCshAZr3cxBgQIDAQABo3wwejAfBgNVHSMEGDAWgBRayzce0kaY
-XBOV+N+4Ov8RQK0V8jAdBgNVHQ4EFgQUb0/1XSOZ9YvHmG7rvM8eBcBgOI8wDgYD
-VR0PAQH/BAQDAgH2MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAJybyf0fbsSEKPlQbxKeyZBQXdWfQGeo
-1NVyDN87XSKQUe9fech7qiUC4Ua2z7mWrIIbDBylvl7ff0NFiPTK6+tl4Rt+zaX9
-qzA+dIuVr/7NPrlaTSmJglaX5n1/2h/dYhFbJUXe5L5FOpE3uq/Cp83MC5AQzDxR
-UrWoUQdNtOhm
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlyContainsUserCerts CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5A:CB:37:1E:D2:46:98:5C:13:95:F8:DF:B8:3A:FF:11:40:AD:15:F2
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 52:63:40:55:91:4a:88:23:0d:64:84:b4:3e:50:a2:0c:ba:30:
- 81:b2:86:2f:ce:0e:b5:b7:e0:c2:d5:10:63:82:0e:88:ab:90:
- d6:a4:df:11:22:96:15:f3:7e:cd:ce:0b:87:54:0b:3f:60:c7:
- 6b:a6:04:9a:25:8d:51:af:b2:c4:da:f9:d5:63:57:f2:b8:f8:
- 07:d1:bf:0b:a3:77:a7:e6:e3:87:a0:97:5d:4a:41:07:b9:36:
- 98:bd:54:93:95:32:d9:7c:07:83:e5:d7:54:77:be:e4:eb:e1:
- 03:fa:e7:83:fd:78:45:4b:a0:42:87:52:c1:1c:18:06:4f:39:
- f3:09
------BEGIN X509 CRL-----
-MIIBVjCBwAIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGG9ubHlDb250YWluc1VzZXJD
-ZXJ0cyBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqBAMD4wHwYDVR0j
-BBgwFoAUWss3HtJGmFwTlfjfuDr/EUCtFfIwCgYDVR0UBAMCAQEwDwYDVR0cAQH/
-BAUwA4EB/zANBgkqhkiG9w0BAQUFAAOBgQBSY0BVkUqIIw1khLQ+UKIMujCBsoYv
-zg61t+DC1RBjgg6Iq5DWpN8RIpYV837NzguHVAs/YMdrpgSaJY1Rr7LE2vnVY1fy
-uPgH0b8Lo3en5uOHoJddSkEHuTaYvVSTlTLZfAeD5ddUd77k6+ED+ueD/XhFS6BC
-h1LBHBgGTznzCQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsTest11EE.pem
new file mode 100644
index 0000000000..c12b5a1934
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlyContainsUserCertsTest11EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 88 56 67 0E 71 41 E6 F2 AA 69 74 97 F7 89 E4 5B B5 28 28 BB
+ friendlyName: Invalid onlyContainsUserCerts Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlyContainsUserCerts EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=onlyContainsUserCerts CA
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApygAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYb25seUNv
+bnRhaW5zVXNlckNlcnRzIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowbDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExPDA6BgNVBAMTM0ludmFsaWQgb25seUNvbnRhaW5zVXNlckNlcnRzIEVFIENl
+cnRpZmljYXRlIFRlc3QxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AOaBsVf5mQNZERJjfa68546sUDPNfixGH/qzKOIBzlTFSfSuD7jIYTRkIr6qrbBo
+dPF2V2Rnsz+lJNYvNol8D1BfKkZgjpz5QPCqOQ1JBskqQfO6MXG8xl2DBb7FH6Ge
+jURHGJu7RS30qob03dvQTGEFc7aS7lAj/Ul2D2+IjMDJxIICb3/SwI1lOcWFmmJj
+wm2nBat41oGiUZ41C+lJZ8vbOs3e7BwsJIi7NdnDH2ke4AKTnavfO22CvSs1RVbB
+1kHMvi+Ux5/dQVZAqmv03oXkC4BgHjCra3vLv1O08jRg8f32fdxDCLAA2gQsOQIH
+1wcJaTWap7Ls5IxiaVEWt1cCAwEAAaN8MHowHwYDVR0jBBgwFoAUnbwAqdwBzf4d
+loh9tZ5Pmd4k0gUwHQYDVR0OBBYEFIeuKR8BSlP4kL3Yk3Y4khRKcv8MMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIB9jANBgkqhkiG9w0BAQsFAAOCAQEAdaRcEMmTAKhn8X7yDP1m5Rztq5pvbDbh
+C11BkkMph0iaaGqfv9+rLhoSUsSPMcI10R3mGb4lJnG0pRSWOg3ue8FaLTqSK7Eh
+QrdLjieU2w36bsp8yUg5XIXvhjYA0TLJ7SxqitUmoniOLHpERNd04nAP5bXJMNvo
+G45/n99z1jXUugbCs2DND84EMXSjKekhzN3cO73VFaT4b+BIlbnqVx89CvMNj+eJ
+O3xfgd4eBmMvPC6mrxGuXw3E83sUOOqlumIZsmf0zcWci8aJIPvgih3yEBa5Tihm
+BPnFS6XFB48CEs/iiPTVzSL8VbHudw0rxrT/ZAfi3C78mXEPzu/AZw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 88 56 67 0E 71 41 E6 F2 AA 69 74 97 F7 89 E4 5B B5 28 28 BB
+ friendlyName: Invalid onlyContainsUserCerts Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,AC64C592EFCB03CD
+
+nlYYtTW0DxFH9vpDyxm7PKRBLHiz8SrqsKUelN8D7C3uuynXtssBXf++0Y0zNHZj
+qcRd2yuIKhMnBrrIDOC3RzMcKRfAIxbW+AdUsV8sWuhvnTdXwEj7tmnDmtL5vuG+
+zqTe5/4l0oo7QQEUxNUWriPb1ZQyPFAsxdtzcihd30EgLOIUM8cfNl4FVikGPZ3X
+Qm8FDsEWnvPBaDV6pfd4Nh/YnrB1vfHsal2eJJ5Txkqc3gUjnoADwmith2/6ZTBd
+S6b5PiqiZSyqtDO7zxvueV1Qa5Dn7k4b6eG+lOnCo11FP2Tk4Ltz2/3QxIGCSv7F
+C1MpSkmNCZANcCHii8qZBQbB5Rm3tiR5mIY58EWBk2ZaX5086QCr9fzViQnLbCFd
+a0fjx1P/qb5ZbsSki6DI5es0+UrjkoTXyDSmvj+9NyClA99Wl2zCIyeFD4heie4J
+Cn512Js850qTCuE81tXg1HDOvbRz+jSBHrvj9KSMTZdS9e37Mqi4sZbNPBoQ+B7k
+Z8FBHnZKqJY2ojVbU01yeVUq3ztclRUbgsmUS3Cb65TACiOfwrUF5BL0M7THy/Tq
+0Ztdefmn1iwBF8qLySSt25d2yQGXTyRXu3sHtsiqVis7QCYwmMOVWeAzi/BwjaM0
+TLuMIm3lGJWs+Y0U/S4ZthjMR2CjpY+h07wlxjJiLOSczCYnhduo18D92OZ/r279
+OtaSOhlAbTYXPGufIeHAN3mANaq5jWezLQHGD6D5vdn6W25r80qbTOuFPxb87dsd
+tj8UBb6ybik3Ub2z0kUcuoL9kIzQp23HQeJn9D4jQor3vAT7A2JdpVcuAn21pWiq
+MO6rLla2eCJIUo5hn48jbjBbQxxt/PZApVZZiqKz3lCwhYRM1kilHrseGgv49p2i
+pULQoYZk2hfWn660H3T7Y/Y5hBX1HeCzJmvNsrqJSgsKRsYsgzoR2xRm89jdO1kh
+TUO4dbM7olL6ASECNAnLh37VHV4/KDp2wXUC9lZI4aXqH+GZrKvW1UUs4JD6Ste4
+lYTAklrnMVla79fI7PPfy1n+ihIlzdzelhI/CTyTzs8xxNh+2mPM9+CIHAmzyVOs
+gApir62xWFb2sid9qY4NyuKvkeDQ/cQIE9/ULfeL3GIkhtB7KoaRkBAtsZ5+lSQ/
+fjhczdDkPXg2ZqxsHYhNaw1PRMCRhE5l69D3nluxZpoCb+moJxtb+Pi2EAYzvC7S
+px6oGEZYYL4Hu8zJvVvoTeku0QK5nBXUXQg8A4mjUYoj9jCurOyQsqXrxnkz2MBZ
++mCjAq93lsfpy98+jEBByM8d173wzjmaMGnS0Ub6YoqJ/NVjKF58ZxGNDSmoJPk1
+LaR+/B/SdD3JbPO7QdUN2h3e+6QK+S21gz3KX7tRy2by2jKmJbtPKXkbdXEbX4O3
+ENm0xwJuh6qdllaVpBG3sPQYNy4M9R6WXoiYVW9KCCjIFry7JvGWc3LqZ6t21nNU
+G4tJzb51ysMda5NWZr5mRAcN+z1BE1drFxTS5Sdg55kVFnn5CrRcj0RHg5FppJCK
+/MrF3vDRuyu0Y5IjnBdrncP/vgjoJKeHVd3lq+y/lSprOQIPkHp5xw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15.pem
deleted file mode 100644
index 819cc4017f..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15.pem
+++ /dev/null
@@ -1,156 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlySomeReasons CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UEAxMTb25seVNvbWVS
-ZWFzb25zIENBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqY5YemfCgwOg
-IB+hdOlRZFTinhkf1OaHBpkEgH6r2jJPiuhXh30ZT2TwX9aBiEGnnKuHuZmwGUK/
-DCnAfvpZ621Oo7LXsNQFtGDYrh8Rfu93TxunsJNZQ9ZXWEcIjot4YGkbOO8Nu0il
-Z/zLKJKQUSKKBW/5glVtiynAaixm6k0CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFOBimt8FUL0fD1sYSf6+cB3M3Dlu
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCbnkFzDActclPpCRyu9PWbUrnQ
-ZU76d5EXV40N6ma0OBngkU+7TJgmUNS2anUuxF51tkeYvMlqADT7KijrN/rGSipZ
-yVR/ds2UaXdbfIfuFOs5TuVeClJ21BkYQgrmZ90/ti2fgIKn+cA1MQcnthtmtGJx
-1JuSgthIOVfbeMWdCQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlySomeReasons EE Certificate Test15
-issuer=/C=US/O=Test Certificates/CN=onlySomeReasons CA1
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVh
-c29ucyBDQTEwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBhMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNjA0BgNVBAMTLUlu
-dmFsaWQgb25seVNvbWVSZWFzb25zIEVFIENlcnRpZmljYXRlIFRlc3QxNTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAlsynYvXyvl+q7eNnQ1pHRTzYR3jQt0ko
-GQ/U1Q9AsMdHihxgohDFbqyRbq2ODI6t3HGT/h8JPCPLT+dLhvwixeYhgms3m/TJ
-+mnXebr5bHI3PjF61Cw/mJe45Ab+arDxdumnvJRtw4EIB5lDwOrD9bHBE/WS1mem
-ndOkBLQNG8UCAwEAAaNrMGkwHwYDVR0jBBgwFoAU4GKa3wVQvR8PWxhJ/r5wHczc
-OW4wHQYDVR0OBBYEFKqEMbmbidNhzPioeu9tHpG1I305MA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAIIqO
-DY8YnDAv4BQddow4PTv5P8bnPkA2Ogs3Du04Lps9gxrBVYHDIT7UQVZ5hzZeXnmW
-rLwQeI2wDJNhjMhemXksv4rrf1pL65em4hQCuwlCsY0Nlc3z5hJjLslTd85fgQXk
-mDYbw0db0b1fRGsA+RkiIRM7ynpuT6753gVv4ho=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlySomeReasons CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E0:62:9A:DF:05:50:BD:1F:0F:5B:18:49:FE:BE:70:1D:CC:DC:39:6E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....`
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 99:f8:e1:09:a8:5d:d4:4d:a9:18:5c:91:9c:2c:a2:51:7c:dd:
- 61:bd:4a:38:0c:5c:88:46:56:55:06:29:70:0f:cc:1d:cf:44:
- d9:9a:b9:11:94:82:53:48:b5:08:4d:19:89:42:c0:ff:7d:42:
- e0:39:98:43:6f:40:f3:e9:5e:8e:fe:56:3f:f4:4c:60:0e:22:
- 29:c3:90:7d:2d:ea:d2:96:f1:3d:ce:35:d4:30:72:f2:9b:fc:
- 86:44:fb:05:b7:3a:08:d2:bc:95:e8:d3:2b:18:a1:64:c9:25:
- 19:3f:6e:8a:a5:9b:99:e4:f4:ac:1f:f9:ea:72:9c:88:b8:8f:
- ac:e9
------BEGIN X509 CRL-----
-MIIBdjCB4AIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVhc29ucyBD
-QTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgEBFw0wMTA0MTkx
-NDU3MjBaMAwwCgYDVR0VBAMKAQGgQTA/MB8GA1UdIwQYMBaAFOBimt8FUL0fD1sY
-Sf6+cB3M3DluMAoGA1UdFAQDAgEBMBAGA1UdHAEB/wQGMASDAgVgMA0GCSqGSIb3
-DQEBBQUAA4GBAJn44QmoXdRNqRhckZwsolF83WG9SjgMXIhGVlUGKXAPzB3PRNma
-uRGUglNItQhNGYlCwP99QuA5mENvQPPpXo7+Vj/0TGAOIinDkH0t6tKW8T3ONdQw
-cvKb/IZE+wW3OgjSvJXo0ysYoWTJJRk/boqlm5nk9Kwf+epynIi4j6zp
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlySomeReasons CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E0:62:9A:DF:05:50:BD:1F:0F:5B:18:49:FE:BE:70:1D:CC:DC:39:6E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0......
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 5a:9a:70:59:4f:6b:42:27:d8:2a:70:9e:91:bf:f5:09:c0:2c:
- 8e:21:5d:6a:76:0f:70:61:ee:f8:20:c3:00:cf:7b:40:78:c5:
- 25:5d:17:cf:c7:74:61:29:40:93:91:c1:52:68:4c:02:e3:b7:
- c2:0c:e3:26:ab:fa:2f:e2:0e:70:60:d9:ed:34:ec:72:4b:98:
- 57:8c:5a:dd:1c:50:d2:6c:44:ee:4b:89:d6:f9:d4:79:64:9f:
- e7:f2:4f:e9:10:0c:8b:12:c4:ef:e4:2d:f8:8a:c6:94:9a:59:
- 24:1b:f9:d4:6e:4c:19:4d:ed:4f:3f:e8:b1:29:f6:6e:2e:0c:
- d1:ef
------BEGIN X509 CRL-----
-MIIBdzCB4QIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVhc29ucyBD
-QTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0MTkx
-NDU3MjBaMAwwCgYDVR0VBAMKAQagQjBAMB8GA1UdIwQYMBaAFOBimt8FUL0fD1sY
-Sf6+cB3M3DluMAoGA1UdFAQDAgEBMBEGA1UdHAEB/wQHMAWDAwefgDANBgkqhkiG
-9w0BAQUFAAOBgQBamnBZT2tCJ9gqcJ6Rv/UJwCyOIV1qdg9wYe74IMMAz3tAeMUl
-XRfPx3RhKUCTkcFSaEwC47fCDOMmq/ov4g5wYNntNOxyS5hXjFrdHFDSbETuS4nW
-+dR5ZJ/n8k/pEAyLEsTv5C34isaUmlkkG/nUbkwZTe1PP+ixKfZuLgzR7w==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15EE.pem
new file mode 100644
index 0000000000..26e7942db8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest15EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 91 3A 6A 9B 0C 86 1F ED 56 FB E5 1A FD F7 57 70 9E 4C ED 88
+ friendlyName: Invalid onlySomeReasons Test15 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlySomeReasons EE Certificate Test15
+issuer=/C=US/O=Test Certificates 2011/CN=onlySomeReasons CA1
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNv
+bWVSZWFzb25zIENBMTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGYx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTYw
+NAYDVQQDEy1JbnZhbGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MTUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMVrlEw9XZiZPi
+mepF7QiknCt+8ohKGyg8nAGV5rVbeT+oyOa3yqjcBBh8ON02JWnb8TD/TJMT3WwY
+UUc7AWPuKhK5tL8eaK9OvkN1R5adVRHW8P0XQ/DyObtxFP+bGHt+XvjBCGQWd0gP
+lrMo+24AgFgijyTRtbAVi5RDg2vG8PAVIPgO1kV5Ly7tIpp7ovQB4wpVbdjoD+Xy
+zmgm2kxbYy5j6TV1phFV0GNVr7Pb2+4FSOuvqCp54XSqO/qeXVSc0oUD/ZZznQzD
+23GQ3lIvdKhjfefhzlKExEGIbPEo1gYEZ4DI6M7+aERB1+1STbZRUE6o/wMOTJHQ
+75Fim7QPAgMBAAGjazBpMB8GA1UdIwQYMBaAFFBo0QlBJ4fnCk63eFb7F47uBAdx
+MB0GA1UdDgQWBBSmoXAX8YjFXLcBX1sI6Uhdu0kKQTAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAlWQIc
++Zh8/MirsIMTkslJm7tGZ/WLZlhRf0t0xqAc9gNvfh+tGkAe6jKWBrm3Le3wLsQl
+BfwAnI7gA58qqDvO7KQqaaQS2WJH9seZjG33Wtxwy92Ct+4koh5zNEXGVwmAtGQR
+hD7Fo7H0E/gRVXnpkv29ObPJBluGh/zYMCVAXfyCDUjHjDUyrLXAYHieNzBIUQgg
+GRuzrOy42lrO5PZl8Y+BANpKXzL0mmrWC0bjMdaQjWm6obqPOiSrK+/g2Q+k2Jjc
+I4GxzuuRKrDc4+q1w2R5OWe3yY2u4ecQWrGKL6t/TO7oB3F0JLYxqvwzE6Mr15et
++ygEE42T8tUSuz9G
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 91 3A 6A 9B 0C 86 1F ED 56 FB E5 1A FD F7 57 70 9E 4C ED 88
+ friendlyName: Invalid onlySomeReasons Test15 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,90A5B5CF0638D715
+
+Y25oaoeE+pbdQJ3tN2fVM8ZLJvFDiLjeT5oThNrK/6yS08BfU88nIDsLrVebi2Aw
+IxHE+TbWDtmLdbg5Ql8/DO8VlRZKDAvsPKrGs3s3O8fv8BLEUnwPgXP1g0Ko7Exx
+NrnzD/+p4LlKOpHxiCyZwXckCitFY3uNwFiH7fHY2KyupFS7vM7AES0b8tl+vyma
+IfAdL+uiAMqKh7x7um9dywyJbuX2008qRIK6BF6HRLNQUyjPyV7qLjM6r4g6I6iN
+YD3QMqXimPdrdC5yrl/nBGuESczO5JEdIc21MKkyssz9kc17YbfAPv1OdP7+P2iL
+3hvqemLmfm2jRay5bu/OiofegXfoN6P4g7q9qQ3RoBTnamSSuI7UUWxrnnO5SlA5
+F9MmpLG40WAm34SYlkYxHsicntKrs+rRDKkntfxER8c3tOOMhyKHBDkDzHHvSHSe
+M6QUXsNimcU/vfcO1XeD8x7X+hYW8NGzwAO7nD8ViBm/d36Sud7gnfnmYv3ZkNiP
+JU2Xhf1ngZCbrFjniiOTltVJoGJfdlJkPjxAReEO9Uk8hshoVygfRM7syYVEbNaU
+SJmxh9AGg7Xma67yVVlPwQlFBcp+wKe6dCXq5aoFeYQxiOA3BPKkpKhir6IdjS/p
+Y22wBBUUrwhqhfxWLi4PwZwgX44oAXmjGyWbs5sVaRn8aXLbSs7+Y6I3B3eL+8Wg
+uBFfBEbugXtnt4Bb/SCzn6B1RqsFC/vNb1x1vqrA0l/y2+2hPVetEaiD1vlUIDC0
+kvxbWSH6EarH4k6eM1dI6ie+rZ87hM12LfFbKzjrJxoxdo8Rep4h7B0cStzz0Vc3
+I75ZnUmncB9gDrF+cbVi/5yQ6O5JKTpwFyFilV3kyWUJJpIdMg/UBlDXN3Xq8B9O
+T+k98F8cOzapFu7sBFj/euD27zubl2WQFvYjzsP/l9BB0GruMAFAxqNrvvpq6/Uo
+r2xVvBrmpXbqd8uXsaGg+cLCw5p8mlPaOcRVXeuveP6bvAy8u0PP9wlTOVj0f4vB
+Rz4VOg/0GderyudWgz5WqSTSmk/AuRVM7txtQwRoTKR0pNB62AM2/LBNymfoNcwn
+My/dfWqvUQXLqVwK/Rq8aln4W2GJhw9ABAzsfin4gOupIqFmOIsMx9DmKw++ETg6
+OE6a/Qrtp9I2gbxshEQkYDg5DMFXApSwC25dO9kpXmRQUWqMTyglRXeldmJLA/Yc
+m74FQrsaTznEm7ji1XPUEgkM6Es1fdXJiXj5WuUKZrcfsgMVeRHockanIAgO7svj
+hdNn7AAmcXhzWqF4m/992Sc3V4VIuZKsCskT5fxMHRUVNXh3nZYBNpMLKbU89p7k
+W9u3+tTdT9yXtaDHg6sXGK5Dz0HIMa1i929cAPggzinqY/fUAXoH5wIABCa6vHEz
+o74lnyMxcHvu62/KKvuv8ba7jdFmtW0pKPMUxjKLSAPNDOeZVt98+Yip0Hx2BeLM
+1mnNWFPVbQBOcswVFToqH6zPzrB+/p46JArv8PlIYbsnPLHDpmhFm16C6VDF0vvm
+/QKcsYWA6D+f2ghn1ggxz12b+kUDbP534MsxTSIpWvKUAR8D7BEDxQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16.pem
deleted file mode 100644
index 76ef3b7b53..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16.pem
+++ /dev/null
@@ -1,156 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlySomeReasons CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UEAxMTb25seVNvbWVS
-ZWFzb25zIENBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqY5YemfCgwOg
-IB+hdOlRZFTinhkf1OaHBpkEgH6r2jJPiuhXh30ZT2TwX9aBiEGnnKuHuZmwGUK/
-DCnAfvpZ621Oo7LXsNQFtGDYrh8Rfu93TxunsJNZQ9ZXWEcIjot4YGkbOO8Nu0il
-Z/zLKJKQUSKKBW/5glVtiynAaixm6k0CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFOBimt8FUL0fD1sYSf6+cB3M3Dlu
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCbnkFzDActclPpCRyu9PWbUrnQ
-ZU76d5EXV40N6ma0OBngkU+7TJgmUNS2anUuxF51tkeYvMlqADT7KijrN/rGSipZ
-yVR/ds2UaXdbfIfuFOs5TuVeClJ21BkYQgrmZ90/ti2fgIKn+cA1MQcnthtmtGJx
-1JuSgthIOVfbeMWdCQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlySomeReasons EE Certificate Test16
-issuer=/C=US/O=Test Certificates/CN=onlySomeReasons CA1
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVh
-c29ucyBDQTEwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBhMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNjA0BgNVBAMTLUlu
-dmFsaWQgb25seVNvbWVSZWFzb25zIEVFIENlcnRpZmljYXRlIFRlc3QxNjCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAlmAr5pfd8vA/RDJSfo8qPEDAbLwbxhVf
-lv1WYCncGfhiyC77BYzSvBHiEp+84tJW6lBUUEewGRBDKerNZAnqkirYwLYccwav
-76qQJnSFTKmjDS7BofPWH8/bVZXjwjGikKAChuVcBykwZt9zOhFCM4y5wUv1IEHe
-iiDpoHEIPqsCAwEAAaNrMGkwHwYDVR0jBBgwFoAU4GKa3wVQvR8PWxhJ/r5wHczc
-OW4wHQYDVR0OBBYEFJdQKB8LbKa2dsGgu3qroJY+rlmzMA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAG5qf
-f86xb10ogmC7H1f//9eykm6gAA0EWFwyXzjCkIlk9WPjGOTBU3WNURziN5LdblcZ
-Csf3gFtni07sN4ISdLTnJFzuW8Nk9vfmmhV74guH9wvMv4fCVInMBZEaak0bR2dY
-LxvWYJ8K2rgUN4E3A5nNFA81/1xxbwCq7c2koa8=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlySomeReasons CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E0:62:9A:DF:05:50:BD:1F:0F:5B:18:49:FE:BE:70:1D:CC:DC:39:6E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....`
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 99:f8:e1:09:a8:5d:d4:4d:a9:18:5c:91:9c:2c:a2:51:7c:dd:
- 61:bd:4a:38:0c:5c:88:46:56:55:06:29:70:0f:cc:1d:cf:44:
- d9:9a:b9:11:94:82:53:48:b5:08:4d:19:89:42:c0:ff:7d:42:
- e0:39:98:43:6f:40:f3:e9:5e:8e:fe:56:3f:f4:4c:60:0e:22:
- 29:c3:90:7d:2d:ea:d2:96:f1:3d:ce:35:d4:30:72:f2:9b:fc:
- 86:44:fb:05:b7:3a:08:d2:bc:95:e8:d3:2b:18:a1:64:c9:25:
- 19:3f:6e:8a:a5:9b:99:e4:f4:ac:1f:f9:ea:72:9c:88:b8:8f:
- ac:e9
------BEGIN X509 CRL-----
-MIIBdjCB4AIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVhc29ucyBD
-QTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgEBFw0wMTA0MTkx
-NDU3MjBaMAwwCgYDVR0VBAMKAQGgQTA/MB8GA1UdIwQYMBaAFOBimt8FUL0fD1sY
-Sf6+cB3M3DluMAoGA1UdFAQDAgEBMBAGA1UdHAEB/wQGMASDAgVgMA0GCSqGSIb3
-DQEBBQUAA4GBAJn44QmoXdRNqRhckZwsolF83WG9SjgMXIhGVlUGKXAPzB3PRNma
-uRGUglNItQhNGYlCwP99QuA5mENvQPPpXo7+Vj/0TGAOIinDkH0t6tKW8T3ONdQw
-cvKb/IZE+wW3OgjSvJXo0ysYoWTJJRk/boqlm5nk9Kwf+epynIi4j6zp
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlySomeReasons CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E0:62:9A:DF:05:50:BD:1F:0F:5B:18:49:FE:BE:70:1D:CC:DC:39:6E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0......
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 5a:9a:70:59:4f:6b:42:27:d8:2a:70:9e:91:bf:f5:09:c0:2c:
- 8e:21:5d:6a:76:0f:70:61:ee:f8:20:c3:00:cf:7b:40:78:c5:
- 25:5d:17:cf:c7:74:61:29:40:93:91:c1:52:68:4c:02:e3:b7:
- c2:0c:e3:26:ab:fa:2f:e2:0e:70:60:d9:ed:34:ec:72:4b:98:
- 57:8c:5a:dd:1c:50:d2:6c:44:ee:4b:89:d6:f9:d4:79:64:9f:
- e7:f2:4f:e9:10:0c:8b:12:c4:ef:e4:2d:f8:8a:c6:94:9a:59:
- 24:1b:f9:d4:6e:4c:19:4d:ed:4f:3f:e8:b1:29:f6:6e:2e:0c:
- d1:ef
------BEGIN X509 CRL-----
-MIIBdzCB4QIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVhc29ucyBD
-QTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0MTkx
-NDU3MjBaMAwwCgYDVR0VBAMKAQagQjBAMB8GA1UdIwQYMBaAFOBimt8FUL0fD1sY
-Sf6+cB3M3DluMAoGA1UdFAQDAgEBMBEGA1UdHAEB/wQHMAWDAwefgDANBgkqhkiG
-9w0BAQUFAAOBgQBamnBZT2tCJ9gqcJ6Rv/UJwCyOIV1qdg9wYe74IMMAz3tAeMUl
-XRfPx3RhKUCTkcFSaEwC47fCDOMmq/ov4g5wYNntNOxyS5hXjFrdHFDSbETuS4nW
-+dR5ZJ/n8k/pEAyLEsTv5C34isaUmlkkG/nUbkwZTe1PP+ixKfZuLgzR7w==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16EE.pem
new file mode 100644
index 0000000000..f4692f06c6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest16EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: FC 19 32 E3 5B 7A 6F 8D 2A 12 5C 1F 0E 6C 58 47 CD 38 02 B3
+ friendlyName: Invalid onlySomeReasons Test16 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlySomeReasons EE Certificate Test16
+issuer=/C=US/O=Test Certificates 2011/CN=onlySomeReasons CA1
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNv
+bWVSZWFzb25zIENBMTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGYx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTYw
+NAYDVQQDEy1JbnZhbGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MTYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCq8KivhrS5GZix
+Tpa3ipGTij1/L7BsHNs4DNbMHldcc8b0clfqiS4/svyHh0VryHBWmHRdCgZbkQey
+6DjkzmCk4w3bCP1HtEiMGY5Wxr/XdDBuzCwb87pqKb1KFFqgzgxRfnIswCBPlmY/
+IE0+WL2hbMDCOcfswi0ErEjBAhLglYqzuCb8r4md8jbkn5G1slSeR81NEpBoB/RJ
+0pRFlAlToLm5rp3B19nOYg10J0xhUe+UvQ+4VA9waWVj+X0YrAPebjU68TGP09XO
+r4bmI8Wr+3evvbG5YoibP2xKxkaM3TIvkKKMwvAwXF9riZwIgH8jzr0gvPquRDWG
+d+/X9HdrAgMBAAGjazBpMB8GA1UdIwQYMBaAFFBo0QlBJ4fnCk63eFb7F47uBAdx
+MB0GA1UdDgQWBBSpmSNi0uf7AXBBlsBPTYcCUJ5jZDAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBxIJ/R
+TDz+JlEBsKmnazaVAZqhgitlJffJGlWgsWj/Upaw/3CcGtvfY0lOjD3+IFdloKNm
+gmoiDvovGFwx+a498KvDG+xiiAQ80sJfCWhSrobV+CfqH1zI5KIenbk0tziaUyX1
+BudL/+68UPc8gvuTy+nGZlF2TNx0ur9fQ0YTxHMQqInRzI1S8lRDGAWnXiE9j98a
+BUvTPgJIe9g4TUBJmzDg4A4WQjyLbyHgzk5nT5QAkwcejbw+eBlIR4fMAIcKFTp7
+7VMxuHNgLCeRq2kejdJ8sFoeInFVJg6+WDP/3KMiKZ1DnSVOsIKJpIiwBXR0hg2u
+7qYSQLZQDhrFf1CT
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: FC 19 32 E3 5B 7A 6F 8D 2A 12 5C 1F 0E 6C 58 47 CD 38 02 B3
+ friendlyName: Invalid onlySomeReasons Test16 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,401E21BDD2BD841A
+
+0atul2/gZlaBAQfxewjEVGTp5EG00HVEpV4Ll+94rY+pUyCz3QTOb2/kY1++6HY3
+M5a3BWCVONvlEhNJHhq3DDCmroo8sdt3prhUAIu36JNeguySL78FY+KYb07mtygY
+74dHdI1InXkEQYApCkcDL7umrRXh5Wb+wbYoXBjlom+yL4THQLYDhhfEJVpJKVO1
+oCLdCzD9Lt1A10siesKHvqiIokuaGz+iZitY6lIiIgtFp4W1u+L+bbZd3JRddpuQ
+xZFtwW5SCf7tb1zUx9bcFxQDlm64+dLtklxdTbN5uLc2HcF22YPyip2qmmhxnkX2
+VE16SALv++CqVhHL4a7q2ZoWbteddRvvu0KTdVXkzTJPni1GikR0UexaL9mxodLY
+ctNrxvi1vnv0bH54VKRwDFJD6cG6poMjrbmZvr/8q/33o62qU4+lSyKkl5iqwqXr
+CwW98+USoQ3Zh7jYNtou+/8HShpqiDEO8sR0Z/8DUscxs8e88ZXIE5q2jfglP2qx
+gshFKUEEF1dwP/0rzVDZIKBOqTG5fDvBeKM+38ZELt/EiD+FbIIkV7ZX3MlHa8np
+zQXYZqD15Ns3Sl5lbO5KgCgGLvHq9QAcFb2GenJWX+18j9nrT5A7kaZpk6/nRQn/
+rPCORm/Xz5Sd3rNlI3MrqtP+hqEECUYm9KrnYUrjtfeRGoftQrMTHLiL3ryDrowv
+XyPjVKjSlVBKAbFCvqYqeBq6VMDWaPtu/kRlBZ5NqKGXu+PcEcbzlHfp3KwTsvJY
+qxh+atDb68RMAooTkXRs9zDEJOcSsGeozSYpKuypBrJiQ4K7l3qxeo3flAjUbGYI
+zSCVY2PqvAktHoqe/tUzPiUfDoVJ/ohxKw8oAPjy0+1czV0k4vGBs3gEj6lfqBGY
+6oaMtOaTwcYJJWAklH1S55JC09pNvsy04wtRSH//AvVrAwbPrVKXyIfg7pborWX5
+AZw6/ccYszPbASmLlSFQRBkoF4JrxIXMsG/M0WqMHETjdFVT0rYJ6WVZcTlb9Rk9
+AfoNifeMS6cBJXszAAV8wCdA0gI2s6AuGEInFbuuIezNg8KqJ/hsiLYSxGJfSLs2
+4Mu+48vY1JrvbyBZ5fbs4A35jZ4RmrqjkaiVgArgWxcarJcrOiqgxzJPv22l2Xqc
+UntQ9MmeZrSGx2Zp83CdcYt63H5UX1pxt9annguYaVFyZ8P1S7/QtWWauUTHyxpn
+sdwQWXHTNKcn1D+xqtdRDZkTnkcbHLZYJxN38UfAUL+yG8TsSE4YL3i3zlmI+T+q
+Z7rRddx7jrZAXYpWOVQF62kpV5Uolw7ycYUawjKD3zzy/hn5O0ZxTrwlRH7ikHP2
+7OSUW4TIgoCDr16brTvxMWq9W/JuwC6atjQhOE7DcVKtl59lszihZTabrMbFV30f
+eaHvamBqZaEK65vRuVeJeG4diEysTam2PJA4905Ji/6oRj1VtvrnwoW19x5WH61J
+23+CvEj/cJDrzUtX5sEDuvj0U2drmlDjauuoR6OZJfrB/gzrq+s3pvT98g8loCML
+yMDrZBPtFm4o5UkgJMXCjUKQNtHVbq+t2wOJZWpLPRDoQnM4VsZn/Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17.pem
deleted file mode 100644
index c20945cd91..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17.pem
+++ /dev/null
@@ -1,146 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlySomeReasons CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UEAxMTb25seVNvbWVS
-ZWFzb25zIENBMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxjus5muZnJK+
-vbTiSr7l+wNZkm4bBceUnfDkXaEsbIwJRhzBb2TVPT0Do+y3R/r9DGfLYXxCHohP
-OsEkgaaxsJcVNb560ICl7I/WjFftw3D82YeCiqtUageZZbHBGBpb/utZyPdGLoc+
-F6OmUprS/F3KhP6SSVq5/tN8vYA7dqsCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFKqh79hc2DiyM4fnkx5FQRjQinuN
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAn3+Yq1ETHIYeBdtTuzCeQHWWo
-VC03XoW3PZMLAKJZof8WbYui9I0Mz8eF7Ae1tgk4luOkc+1VEuf9Yj1R3/DnrFYR
-Ws6bImkBgnSYYiUSo1GuqCC6L3FuD7KLs7vaCp+9EfS0igqOXxJwEESXgJixsOkz
-/lp/IH1QU84Vh6fKlw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlySomeReasons EE Certificate Test17
-issuer=/C=US/O=Test Certificates/CN=onlySomeReasons CA2
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVh
-c29ucyBDQTIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBhMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNjA0BgNVBAMTLUlu
-dmFsaWQgb25seVNvbWVSZWFzb25zIEVFIENlcnRpZmljYXRlIFRlc3QxNzCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr8VCnAdQKISRnLmjaXbkkMYcS02qC5Mj
-4f2jw/FDEJKBWKopXex3k9qR+Dvaz6yGEJoi2wj1sUo8xdChVd1XbjGEYxwkaqpe
-cOPYjHlvVF43YGWYhqWOtohBZfIT5uJi0rxZNApuHARfo6UGBaceSk/DUFbos1ag
-lCxoF4pf+5cCAwEAAaNrMGkwHwYDVR0jBBgwFoAUqqHv2FzYOLIzh+eTHkVBGNCK
-e40wHQYDVR0OBBYEFK5QFuk+bZ4HFuTJCRy2qPFS7YZ6MA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAOShO
-p8bEYTzkGWyiUXPs0fZAQzFbgCpN3Q+ky2VZblbIuJTOToG/UiyIQ2FNCq53oBYe
-ZYiuewxa/WWDunOwx7LwPtcksOo3M5BzFmZEqTKALQryiXj9X3ob3tZJFTpAs+X2
-joJ0q+U06GYvbXscfXdm8nvBNA+r5BczWTlAG/4=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlySomeReasons CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:A1:EF:D8:5C:D8:38:B2:33:87:E7:93:1E:45:41:18:D0:8A:7B:8D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0.....
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 38:01:7c:3a:47:fa:d7:7a:f9:a0:3c:17:f8:db:94:e7:1d:a0:
- fa:47:07:6b:ae:03:68:f4:f8:b4:4c:7b:70:a5:0b:5f:92:8c:
- b8:c3:32:e9:55:34:38:53:61:ba:d9:3d:dc:8f:39:45:dc:51:
- 5c:ab:7b:67:80:47:b8:60:6c:88:4b:1a:8a:57:fd:73:69:0a:
- ff:2d:c3:23:8a:62:ea:31:c3:4a:07:3b:8b:89:a6:dd:4e:e8:
- 8b:99:67:71:62:92:db:40:1e:af:e0:b4:e1:09:62:1d:42:69:
- b6:45:64:d8:94:4f:30:40:43:e9:38:3a:59:29:6d:0f:8d:72:
- 0d:8c
------BEGIN X509 CRL-----
-MIIBUjCBvAIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVhc29ucyBD
-QTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgQTA/MB8GA1UdIwQYMBaA
-FKqh79hc2DiyM4fnkx5FQRjQinuNMAoGA1UdFAQDAgEBMBAGA1UdHAEB/wQGMASD
-AgEGMA0GCSqGSIb3DQEBBQUAA4GBADgBfDpH+td6+aA8F/jblOcdoPpHB2uuA2j0
-+LRMe3ClC1+SjLjDMulVNDhTYbrZPdyPOUXcUVyre2eAR7hgbIhLGopX/XNpCv8t
-wyOKYuoxw0oHO4uJpt1O6IuZZ3FikttAHq/gtOEJYh1CabZFZNiUTzBAQ+k4Olkp
-bQ+Ncg2M
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlySomeReasons CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:A1:EF:D8:5C:D8:38:B2:33:87:E7:93:1E:45:41:18:D0:8A:7B:8D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0.....
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0e:a8:95:98:a1:9d:34:e4:fd:7f:b4:bf:94:48:d5:42:03:a5:
- cc:e1:85:55:65:15:c2:e7:cb:33:a1:fd:d8:cd:12:04:92:50:
- cb:bf:ea:6c:e2:ae:bc:55:48:cf:4a:29:61:6b:42:00:4c:08:
- 35:f6:49:30:e7:37:94:a7:38:bc:bb:3c:8c:c3:11:ea:11:f3:
- 0e:bd:9f:8f:a0:32:a2:b9:8a:03:cf:6c:eb:75:d7:5d:5f:f1:
- fe:97:f7:d8:33:e8:9d:9e:21:b6:8e:ba:2a:63:c1:0c:57:64:
- dd:90:98:34:4f:db:a1:d1:11:0e:77:13:87:f4:b0:61:c1:36:
- 1f:c8
------BEGIN X509 CRL-----
-MIIBUjCBvAIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE29ubHlTb21lUmVhc29ucyBD
-QTIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgQTA/MB8GA1UdIwQYMBaA
-FKqh79hc2DiyM4fnkx5FQRjQinuNMAoGA1UdFAQDAgEBMBAGA1UdHAEB/wQGMASD
-AgMYMA0GCSqGSIb3DQEBBQUAA4GBAA6olZihnTTk/X+0v5RI1UIDpczhhVVlFcLn
-yzOh/djNEgSSUMu/6mzirrxVSM9KKWFrQgBMCDX2STDnN5SnOLy7PIzDEeoR8w69
-n4+gMqK5igPPbOt1111f8f6X99gz6J2eIbaOuipjwQxXZN2QmDRP26HREQ53E4f0
-sGHBNh/I
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17EE.pem
new file mode 100644
index 0000000000..c8452ff291
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest17EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 93 C2 7F 92 78 A5 D0 5C 78 50 72 A5 F6 62 FD 93 CA EF 6B D8
+ friendlyName: Invalid onlySomeReasons Test17 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlySomeReasons EE Certificate Test17
+issuer=/C=US/O=Test Certificates 2011/CN=onlySomeReasons CA2
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNv
+bWVSZWFzb25zIENBMjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGYx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTYw
+NAYDVQQDEy1JbnZhbGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MTcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdyWxytNcj3eU+
+PWXaYyWOlUWPg260Q+7EygIhIMtLWwazFS1aJlH2AYPhjpz2u439OI1iijK/koDI
+oxH9CiCJPRWL+IwKA0YKgfxrcFy+g98ZcMiuIPvO8aYVIX61oaCWt2megEMv+iaT
+EiCd7FY7wtY2hFNYnsxaWzVnFw4uvWBJRtq01eyseDnbZwBkYprLZBruZ2NUuFmr
+Q3UGTZUyIDbJLGDcXI18oPcVRZCy/H0nZ74G2Tlp1lXedwmq+/bS/4dJ+mi/Pp1/
+oKJRmK68qws5/5CSrZdTTxij6Y4X71YjTAxT7nncv90Y74kp7r9kXBzE5AmRngCH
+JYeWOm+XAgMBAAGjazBpMB8GA1UdIwQYMBaAFGBj39IjpCnWQaSsyoZ5mKZlAUiu
+MB0GA1UdDgQWBBRzj0ftEusY+0fq1BL8qXXHBtuKYzAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAZ2lOz
+SmjaLWMxDGxzcQ4GFP3G6AmmmvZ1sVAnx4sOR+felUoU2Y5rSdP04zN5loCrY+gM
+vP4YIbgHGqvoapdvTLTwVCjxXKIt49fYBiT8u7KErvtgyFC4HMh98SlPjbVLPwFH
+NPfcx2CtdiVaMFpw4k0MFwhSWfLyEqHzYG9qVJUZ2FdlgJ7/fjM+Xw8+OyN6z5ey
+Z5HVIdS1aFHcR6Je08WL63GQGz4DmpASlMMtuQCgNz/kESJlXhD+4kwchA8v3xc7
+NtXeGL/qF/J7EQmH1JwGytg1n6WUWUmOakv3F7pL6Xj4Ivf9OOKFI4FpdeYBzuQw
+TTaBNhknlz9zwf1Q
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 93 C2 7F 92 78 A5 D0 5C 78 50 72 A5 F6 62 FD 93 CA EF 6B D8
+ friendlyName: Invalid onlySomeReasons Test17 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,26B819BA3A805333
+
+e62CbjykF8e9NCDf3Zq9VJMGKdo6vwbHCy4HNfbIGUAzUbLkYw94cI1fEuD9BapB
+gaazv0Bss+FlieKLqqv4Euv+t8+dOjX5zorXZTIaHjz5ABLbPSpvPyBuThgQGLQH
+dzY45kBRU7S14lM27R5ZhSVVljb8c1afY24B8r9YAavWInPGMMCNs0/GRSzk/YLK
+Cx27HunJgnkssgvS8TMyQKjd4Hth+tjvb23JRCspAY/dP/cWDUUTBpRnc50aztQn
+4OXS8XE6inkpKhT/sg6B4jlOoW3xdLiis7lS/pRZKqT2Sqcum+FTeXtl4Li9/h9P
+93mg+7Fnv+YdFKjlZYgWkqRui920SRBWTZb7yynjCqRvA8GRRcz/MLMqc2xCyvXQ
+Y/pcCR/N+uFu5ZAon7f3qQ7ZZgKJ1zYRPg21WoWwWpPCbL5zI3+5m5+ERAGQIGHG
+wv4044esRpxbZRCzCWvWCwYObY42dXoDWuhHN/Pk47wc9dxu6118rrE9H1g4fqRy
+Hoi1mARNWWTcpSJWKaph9St5M7JLzkOA8Oen6oSMoXXBnN1CiFSofoI0ibymM1NI
+1MTVda9DabToMpV365yvR7Jb1CR74jhtHN8EzV66zdz2jQUJ+32OA+TKAxqZRPlR
+B/1NK0L4ZL/t18DpUf2l7aw7jaM25iviwJRkEZ0BWMNc70E43Qsza4I1YJrw9pk7
+njTYse901rURDB7++ptOntB7n85wi4wbgpEAXxnRlApzyRKwqdjkWamT5n7MSwAo
+eKO3XU8OJAZKlsQn7oraRY5yzsr188k0G6qoicXfOf8oGpQZZ+WE+3MNJk1QYxNX
+eTyu6xNiGfM9ZPBSM5tvstjd0vOl4USaPAYEpWOPT4oEHjVWrVX/RwmbHr8yFJZc
+9GgVjwAbE7eMo8+yd6mDmQND9QS7qkn7ciMt9FyW10U3eWj9zTGTl5xUx10ocFVn
+RcXvVEBvKZlWSVYXHZjN0F1X7e6HRzlaYt8LG0F0GFub++WBoDjYxATiTF+vH3wH
+9NWB8WPVgNwcoJHpg8vaUkf7LDB4HU2dqUwfzTGszd7PctTafbvAlR0OjW3tGUXr
+E3EdckoFmwsBepsWZ38oLId44n+jJEfYTL4/1AaQcvoIj1SAoqHkU98+vckhU9+1
+1vP3h7/UNGA5HJH/SvNlp0V2wrv8b5SYZmNYcjQZvScurMXLHNibSfTUWo4CZK2w
+cn9qLSCtgHWeLrI41Fb+GzgHZrhUYtkPDHUa3UkEKameaSuP8kq0Zw3Y/76OST4R
+fDqxsjEayJfJ18vEArTXj2+/lVKasMt9Sz3O7ZZzc/safPf2jimCp3D87x41v8YE
+X7LzfKrymF7sNayxG2QhXZITvE0Y1cVHcBBiVdLmWXtyJmOlQF+yxfwltKfETa2z
+6rbKTMHwl5N7oRDCVhASsfWHFHLXb25AZVzApqmSk+dsc4LSzPxnEudj0VrIR+pL
+OlIfv9UdUnTWYIU5f9pryJ9sP6jubJ4LhC9/0RlbYIv8JY8s/jLv3fS92VWIZMn0
+b8GNIIM/Z5IzP5dkfB06grHR2gqrmlH76/kuCkA9/a+VJRSwaTrGghTYJUDlwX0l
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20.pem
deleted file mode 100644
index 91c6b1fb56..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UECxMTb25seVNvbWVS
-ZWFzb25zIENBNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApawx8YRMPlMQ
-024rS3sld90L6veeiaILQ6LHaLsGJq3VdzR86qrSqOOIC4riSla8gYRwgMxS4ex2
-wjXsRFQbvsG09PcFyRJKJ0NLsY8FiVdShUDwLEohR/cdfL4Z+iCgZdY4iMaILI8a
-MHiBRffd7isOjbgUd8JKQ6DM4ercJksCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFD++QPH3awL7sFnDAKRa4JdUCOkZ
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAzmsqTCqqsyknqgNHYbj4aH461
-hKTEkZRpMSUHjJwKJWFK4fzqdC8DDlCw9rfmNld7RwxcC3/o0J5v3T4KG3C4s9Rr
-eVSmm4Kwvgjmj0tsm0TQbG+B4uLqaFAAmlBTZPYl9ABodUKUP2eKcAL7f98INanN
-/veMciSwQ7N4Ku7Zjw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlySomeReasons EE Certificate Test20
-issuer=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
------BEGIN CERTIFICATE-----
-MIIDZDCCAs2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAsTE29ubHlTb21lUmVh
-c29ucyBDQTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBhMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNjA0BgNVBAMTLUlu
-dmFsaWQgb25seVNvbWVSZWFzb25zIEVFIENlcnRpZmljYXRlIFRlc3QyMDCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo/2deWn2P1temSytp9fRh3t+UZIp62k5
-iNe1RKLHz08HxSTMrPeCRNnJFp5opbLpQEsUk8xludZeIcWGyLtBTN5w46xk04gh
-1Px8Z2+/mnT/ngizwoMvKZf1dqA1/IYacDNHoZB8wlR7iMEa3scvBmFE/B/Ieudc
-hxnOxEhEprUCAwEAAaOCAUQwggFAMB8GA1UdIwQYMBaAFD++QPH3awL7sFnDAKRa
-4JdUCOkZMB0GA1UdDgQWBBT9Hi+HZ9Okq+jLk3TXM424X5IyqzAOBgNVHQ8BAf8E
-BAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIHUBgNVHR8EgcwwgckwYqBc
-oFqkWDBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-HDAaBgNVBAsTE29ubHlTb21lUmVhc29ucyBDQTQxDTALBgNVBAMTBENSTDGBAgVg
-MGOgXKBapFgwVjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwy
-gQMHn4AwDQYJKoZIhvcNAQEFBQADgYEAEyLMappHZG7NaHTIJRCcyylzQD0od1Bi
-cIsRgkSX4W6BWas7pnbYsIaBtY7SX6PU8lcrIBdjUlKUmzZP+0f08ptO5a4ZPaY3
-mJ7GjPUXPN8T/P8cfpU5A3AlaLam894aWe2vJuwmNlrEs6I0mP20WbXkYjmg2qzP
-joyjMV62Zb4=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0b.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL1...`
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 0c:c9:cf:ae:6b:51:3a:d8:ee:4f:85:3b:a7:18:30:00:6c:cd:
- 0f:1a:59:06:50:fd:75:49:44:9a:af:71:a5:74:ca:25:02:e1:
- fe:c2:0b:15:f4:db:0a:8c:7f:ca:9b:de:cd:bf:1a:2d:3e:10:
- 1a:a9:4a:9b:a9:64:75:01:1c:dc:26:b2:f6:ab:2f:d2:7b:3d:
- 01:f6:fb:64:a4:c8:53:65:b2:80:5a:1d:22:e7:3b:9c:12:92:
- 96:01:0d:74:83:d2:72:c3:a6:34:cb:54:bc:75:c4:34:12:c1:
- 4e:40:2e:e1:28:d7:ea:6d:c1:9a:4b:80:dc:2d:7c:7c:a5:a7:
- 28:75
------BEGIN X509 CRL-----
-MIIB1zCCAUACAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIGgMIGdMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG4GA1UdHAEB/wRkMGKgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgwIFYDANBgkqhkiG
-9w0BAQUFAAOBgQAMyc+ua1E62O5PhTunGDAAbM0PGlkGUP11SUSar3GldMolAuH+
-wgsV9NsKjH/Km97NvxotPhAaqUqbqWR1ARzcJrL2qy/Sez0B9vtkpMhTZbKAWh0i
-5zucEpKWAQ10g9Jyw6Y0y1S8dcQ0EsFOQC7hKNfqbcGaS4DcLXx8pacodQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0c.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL2.....
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Affiliation Changed
- Signature Algorithm: sha1WithRSAEncryption
- 3d:11:d9:b5:4a:98:2e:f6:01:84:ec:e5:d7:d5:20:45:06:18:
- 19:5e:18:1b:89:27:c3:fc:7a:ea:a7:3e:3d:bc:ff:26:f1:69:
- 90:73:a1:2f:d6:0e:82:36:1b:f7:98:7d:26:2f:07:86:05:58:
- b4:5f:ce:84:6d:ef:4a:51:e8:40:4a:51:b2:57:46:b6:76:e1:
- 8f:0e:b8:03:16:88:72:c3:88:74:74:76:38:1d:44:87:88:c2:
- a5:ce:34:cb:a9:bf:a1:6f:e9:96:e3:a7:ab:3f:be:a5:60:b2:
- 4b:e2:bb:f8:1b:84:4e:eb:69:ae:01:f2:5a:e9:78:9d:ac:38:
- 45:4d
------BEGIN X509 CRL-----
-MIIB2DCCAUECAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAxcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEDoIGhMIGeMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG8GA1UdHAEB/wRlMGOgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwygwMHn4AwDQYJKoZI
-hvcNAQEFBQADgYEAPRHZtUqYLvYBhOzl19UgRQYYGV4YG4knw/x66qc+Pbz/JvFp
-kHOhL9YOgjYb95h9Ji8HhgVYtF/OhG3vSlHoQEpRsldGtnbhjw64AxaIcsOIdHR2
-OB1Eh4jCpc40y6m/oW/pluOnqz++pWCyS+K7+BuETutprgHyWul4naw4RU0=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20EE.pem
new file mode 100644
index 0000000000..b290e103b2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest20EE.pem
@@ -0,0 +1,66 @@
+Bag Attributes
+ localKeyID: D3 C5 3E C8 EF 55 F3 CD 93 1A 83 A1 DA FA E6 40 04 A0 52 2B
+ friendlyName: Invalid onlySomeReasons Test20 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlySomeReasons EE Certificate Test20
+issuer=/C=US/O=Test Certificates 2011/OU=onlySomeReasons CA4
+-----BEGIN CERTIFICATE-----
+MIIEfTCCA2WgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UECxMTb25seVNv
+bWVSZWFzb25zIENBNDAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGYx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTYw
+NAYDVQQDEy1JbnZhbGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MjAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiRMsPRNlOugMy
+cCBZrkN/m6EPMxUK2+PNt+QSx4QWPS3OlSLxzUhhD6yc+zMeMyluGW0rTvlaiFeG
+/6zZKonarHmHwwqc142IFGSZU9WFT08sZ/w/j80GROqxD/Jtn1IREh62S8KeWJMg
+1zxPgJYXS4CzI+MGs0B0J9aSAngRlca6nGN2a8VoQP0vdw68Ndty5R6+/eTHjY0K
+av6WdqC2C6sJVTXuL/5gTewVfVsGd/jKWsVdS4l0gIMSyfB0XxuCUzOhLgiKJ8BL
+eWjanMWO5QhmFbfe3HhMzJAS6K3FL2uLc5V7cFElCoJpnXVqld+zqcVCoBsUcDx/
+NJOG7aT9AgMBAAGjggFOMIIBSjAfBgNVHSMEGDAWgBS+ZtweDAY79tOINJFTJoEN
+aBduyTAdBgNVHQ4EFgQUGACS0xeS/VfcsU8QUHe/mKls0JEwDgYDVR0PAQH/BAQD
+AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATCB3gYDVR0fBIHWMIHTMGegYaBf
+pF0wWzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExHDAaBgNVBAsTE29ubHlTb21lUmVhc29ucyBDQTQxDTALBgNVBAMTBENSTDGB
+AgVgMGigYaBfpF0wWzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExHDAaBgNVBAsTE29ubHlTb21lUmVhc29ucyBDQTQxDTALBgNV
+BAMTBENSTDKBAwefgDANBgkqhkiG9w0BAQsFAAOCAQEAlo+iWYN5GvvLUmNv/OOK
+T5LL4QSHSsEsRdsq5ZJsM53pqDVm0/DtGncdiknY450Gf0194CTntp19YXmOOWWe
+FTr90lahPlXb60lRMngOFTpusFymkxhfwqVukhu6wGrq7B56lozEziFc4TB+HLX2
+z4I+n88inNtPN6diUh8ga4PGtqAJoHUYPRwPFRTw+wi4NlHSQZggGKEpNHHkj7yD
+hJtgv3QYSTHvolbYx9Yp4u1RpFX0qEK0koIHVgHGEFxNMLcMScPrmfA1R0zrcRAT
+PSu6f8jlT9RA+Z3InPSQg4FBrUzt5BLORt54CCpHWu/I6DDfoBHrsLiyRFvQiENm
+qA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D3 C5 3E C8 EF 55 F3 CD 93 1A 83 A1 DA FA E6 40 04 A0 52 2B
+ friendlyName: Invalid onlySomeReasons Test20 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,936BF71DC9DBD730
+
+5tsLFC8puE+be9YJclRpByPGMUuvjdyd3zuCN63T6QCm9KH+ZVw0oaT1RVKg+Q1R
+w4ejiaqjxXJtsTu5cig5LMJvRzA1/9EB6b0Oa91SibME3AK3l1i0GoA274KQZ/J0
+FcEgMNTcFN2yyfL0uVW+aAZLYnQ36tLp6Z0pHQay6bfgpahDpRA/BpHoyYhxnqoU
+GeArspTdLdhy4f7+HBSVkMnEET9pBtOYXywOfjsj3aWKLy3Y9Tz+LVH7Ezi631Em
+x1/fauHxQxNXIP2eaV6Y3g+YaAIVGe83014V2KSH22YT2rHeO1OOyt/Vfss5dsfH
+D2wFvpB6/c4jBGHL3wGW0dIl6LJSSVSOXx+P4s1hi2otksacO851HNctZicv6s3O
+1b4V7KuTlSO85milbMl/XCjMvQ/lj0ZN41/FPwFLokcV5VDFLmRYRpM8X/FHa8na
+1AikczhWU0LlhH65JLYA4erQLsnehf2zyZS7L77MpZPZHRAoVYTAggHRUE0h9D7m
+qNNYqtdHvjxNyv090Iv+qs3HRhc+YWpLQGlBRDeCeiDSweSlKv2MIVXv9jRAQvtV
+IQuBfpzjrBlwU0OGnTR/LfRCZqEqoJxnnuVwuVuxgaO+zFY4HeEHAm3P6jPX5BHC
+Wbnhly5yne3lZQNcklLXu7W7lqW0SjT3lOiJmZoWqQsPmOBaWu77Q1DRr/NwnA7n
+lD+jZ4MioZcOkI/WKOkeKnFMwRfceEo8HaHYxfWPtm0MpC5TDD6CjSc34w3xLZ31
+83HfUlLeZdbkJ680SecLm2A918lob8sZjSOZAjx1ZoJQeaTVhm5mLTAhAAWE9K8Q
+KBo/exosNh9b8mjtxe5QG3puXd+p2almF1w+Xa0URiAzWFo5rDfHE4pURbYWUs6d
+m9telasFGEikjJkJBnvKz5wPRIjWGNbOzg2oTU42wyZpCwpqiKNAZ4hi1j/nUGlF
+nX4Ku7fKLebD/vvoJN5z/kFz9zpxa8/ygq4OR3IooOBHP75fcVYQeIDa8zRUYu2g
+M8v6vydKgSKBS53zC9hGVxSmg0EeI86XzJVGFaxMArkkybs2Qcm4VpaTtRsRWc//
+tjHePHUzEjgeI6eN7sDlTNY0euzRrrTEUXBPIrLbhUDrAQO0Agnt0ibqND0T/BGp
+8YN8v2fjgI0mvAlh82hn/oFC4b1d+NqEbZyUL+bcLuf8kPYSq8UYYpdE8npW0TZS
+sIA0eTGWLT0apKBcRIBT+fuhvn3F6sqagL2d4SQBLWelt5bImOf48PWBDocngY4U
+MdenQAGxGPc14yPBx9NigcLj7kfXywcnZYNum9NbUgTITIlkXsTS+Y9AI2TNGPvy
+/KCZSoXDX/aoNWuhIa5FCGjJ3tAnHBSCFOxwLYTpsVV3xu7aCB622strxP0XzYNf
+C05Fr6LAsZckRyp6lcrPNeWksh1TPIVxZuQgbTaiGfqbMa5WqsMezWkRWhd55R53
+EBl/g52D2v8DAucROQcja72O6GYq1QNRLFhUUR/IRn1ZhrkdosgKWt/wWvNEoflB
+edxk1kI4xNxRI7Xiabc0DC/V8wc1ot/daAeO+lMfBAXpgxMjwGjTLCBlLDgrsz05
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21.pem
deleted file mode 100644
index 07b5c9b27a..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UECxMTb25seVNvbWVS
-ZWFzb25zIENBNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApawx8YRMPlMQ
-024rS3sld90L6veeiaILQ6LHaLsGJq3VdzR86qrSqOOIC4riSla8gYRwgMxS4ex2
-wjXsRFQbvsG09PcFyRJKJ0NLsY8FiVdShUDwLEohR/cdfL4Z+iCgZdY4iMaILI8a
-MHiBRffd7isOjbgUd8JKQ6DM4ercJksCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFD++QPH3awL7sFnDAKRa4JdUCOkZ
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAzmsqTCqqsyknqgNHYbj4aH461
-hKTEkZRpMSUHjJwKJWFK4fzqdC8DDlCw9rfmNld7RwxcC3/o0J5v3T4KG3C4s9Rr
-eVSmm4Kwvgjmj0tsm0TQbG+B4uLqaFAAmlBTZPYl9ABodUKUP2eKcAL7f98INanN
-/veMciSwQ7N4Ku7Zjw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid onlySomeReasons EE Certificate Test21
-issuer=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
------BEGIN CERTIFICATE-----
-MIIDZDCCAs2gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAsTE29ubHlTb21lUmVh
-c29ucyBDQTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBhMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNjA0BgNVBAMTLUlu
-dmFsaWQgb25seVNvbWVSZWFzb25zIEVFIENlcnRpZmljYXRlIFRlc3QyMTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzgd55Gu4oIU3A4rk6mO8UVYckksUPNUx
-c+r5iyehCTZg5HpsL0JSKVXAlRwGm5Q7YtHJE+teXB2BM0iMSAIZGNX8fktIN8nK
-Lrw3CHA+5ZySf38wiaNzTgw3V7UTBQ01sd50PWuvL+jOm+AcaCMvdcqFJBP0yhCS
-nkdd2MUeY1MCAwEAAaOCAUQwggFAMB8GA1UdIwQYMBaAFD++QPH3awL7sFnDAKRa
-4JdUCOkZMB0GA1UdDgQWBBT41fIkHaXWHPGTFvG2DPuOcjtPXDAOBgNVHQ8BAf8E
-BAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIHUBgNVHR8EgcwwgckwYqBc
-oFqkWDBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-HDAaBgNVBAsTE29ubHlTb21lUmVhc29ucyBDQTQxDTALBgNVBAMTBENSTDGBAgVg
-MGOgXKBapFgwVjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwy
-gQMHn4AwDQYJKoZIhvcNAQEFBQADgYEANlJq9PF7a+NShO7uJTf788sIG++L3xeT
-OiO5bnuAe91jbQN8l4j+dHxDiT4CdVBdlUPwlENF5rtuKsjSn6baeKMwAo5A6ji0
-7YObkqeg6Be0P6fIKT29KyT17o0bXi7rRTK6PqODvOePJ/kf+x5pMpQrHEutym09
-VmHbVhUkHEA=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0b.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL1...`
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 0c:c9:cf:ae:6b:51:3a:d8:ee:4f:85:3b:a7:18:30:00:6c:cd:
- 0f:1a:59:06:50:fd:75:49:44:9a:af:71:a5:74:ca:25:02:e1:
- fe:c2:0b:15:f4:db:0a:8c:7f:ca:9b:de:cd:bf:1a:2d:3e:10:
- 1a:a9:4a:9b:a9:64:75:01:1c:dc:26:b2:f6:ab:2f:d2:7b:3d:
- 01:f6:fb:64:a4:c8:53:65:b2:80:5a:1d:22:e7:3b:9c:12:92:
- 96:01:0d:74:83:d2:72:c3:a6:34:cb:54:bc:75:c4:34:12:c1:
- 4e:40:2e:e1:28:d7:ea:6d:c1:9a:4b:80:dc:2d:7c:7c:a5:a7:
- 28:75
------BEGIN X509 CRL-----
-MIIB1zCCAUACAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIGgMIGdMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG4GA1UdHAEB/wRkMGKgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgwIFYDANBgkqhkiG
-9w0BAQUFAAOBgQAMyc+ua1E62O5PhTunGDAAbM0PGlkGUP11SUSar3GldMolAuH+
-wgsV9NsKjH/Km97NvxotPhAaqUqbqWR1ARzcJrL2qy/Sez0B9vtkpMhTZbKAWh0i
-5zucEpKWAQ10g9Jyw6Y0y1S8dcQ0EsFOQC7hKNfqbcGaS4DcLXx8pacodQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0c.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL2.....
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Affiliation Changed
- Signature Algorithm: sha1WithRSAEncryption
- 3d:11:d9:b5:4a:98:2e:f6:01:84:ec:e5:d7:d5:20:45:06:18:
- 19:5e:18:1b:89:27:c3:fc:7a:ea:a7:3e:3d:bc:ff:26:f1:69:
- 90:73:a1:2f:d6:0e:82:36:1b:f7:98:7d:26:2f:07:86:05:58:
- b4:5f:ce:84:6d:ef:4a:51:e8:40:4a:51:b2:57:46:b6:76:e1:
- 8f:0e:b8:03:16:88:72:c3:88:74:74:76:38:1d:44:87:88:c2:
- a5:ce:34:cb:a9:bf:a1:6f:e9:96:e3:a7:ab:3f:be:a5:60:b2:
- 4b:e2:bb:f8:1b:84:4e:eb:69:ae:01:f2:5a:e9:78:9d:ac:38:
- 45:4d
------BEGIN X509 CRL-----
-MIIB2DCCAUECAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAxcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEDoIGhMIGeMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG8GA1UdHAEB/wRlMGOgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwygwMHn4AwDQYJKoZI
-hvcNAQEFBQADgYEAPRHZtUqYLvYBhOzl19UgRQYYGV4YG4knw/x66qc+Pbz/JvFp
-kHOhL9YOgjYb95h9Ji8HhgVYtF/OhG3vSlHoQEpRsldGtnbhjw64AxaIcsOIdHR2
-OB1Eh4jCpc40y6m/oW/pluOnqz++pWCyS+K7+BuETutprgHyWul4naw4RU0=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21EE.pem
new file mode 100644
index 0000000000..0e0fa5d206
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidonlySomeReasonsTest21EE.pem
@@ -0,0 +1,66 @@
+Bag Attributes
+ localKeyID: A4 66 39 01 86 64 7F DC CC F1 85 53 E8 29 9E 2A 83 BC 7E A9
+ friendlyName: Invalid onlySomeReasons Test21 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid onlySomeReasons EE Certificate Test21
+issuer=/C=US/O=Test Certificates 2011/OU=onlySomeReasons CA4
+-----BEGIN CERTIFICATE-----
+MIIEfTCCA2WgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UECxMTb25seVNv
+bWVSZWFzb25zIENBNDAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGYx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTYw
+NAYDVQQDEy1JbnZhbGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDorS+B8w/Omx4m
+EBUTz7QShkAsc2IODZ7s92lMmuyrwsunqvs4+eECVas4ESRfTfQ02x9wV8GnX51y
+ftm+/CZfpw3Ly7KGWKKy8+Hhb3vgoXM6GJLpkeI4GpipGl8bWrk3vJio0GbvQ+hD
+TxCoVolLgg3oCS6B0Wc8sc+90BQuPWEGYJrF9hoAICWifdEcUgFoYMYo26T2f9UT
+Mh2uipdxxgoTl6AMb4GlFYAIuzo4nnHL2C7q4DEnGX9eHCl9EJvyxhXMf/FDYMxz
+NxkE00KphWnRYnCczcnRb5kNfGD0VeEa6Qf/gLKpQ88zlaIpdGl1HeVuW2qRLJE7
+s2SetEYpAgMBAAGjggFOMIIBSjAfBgNVHSMEGDAWgBS+ZtweDAY79tOINJFTJoEN
+aBduyTAdBgNVHQ4EFgQUJzdl7+nc9pHBPeuaqXr8BGm6JRowDgYDVR0PAQH/BAQD
+AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATCB3gYDVR0fBIHWMIHTMGegYaBf
+pF0wWzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExHDAaBgNVBAsTE29ubHlTb21lUmVhc29ucyBDQTQxDTALBgNVBAMTBENSTDGB
+AgVgMGigYaBfpF0wWzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExHDAaBgNVBAsTE29ubHlTb21lUmVhc29ucyBDQTQxDTALBgNV
+BAMTBENSTDKBAwefgDANBgkqhkiG9w0BAQsFAAOCAQEALZ6z/4QBq+fcjAsk42c4
+f/6/CitFWZY+db1jZuyjnhZcUyNqZXWczjEaIfwUeEcxPHIzthqyn+6Hw+QoY2Af
+bcvePuof71KqTwlyNvS95ggqzIDvB5JfUYYoqLX3uGsHIY8qRg91QIhwvHRv/Y7H
+EC10wckgUqUGPEvVfvX5h0FJVvedXM27SbhkfOhxufcLFnzO9a5+Hn+s/KDxPgBD
+QXxGz+uQk+h5dvanVXXVNjwQxwIKAz8SSnzob1XTiZShrhkKd0qBq3yYv/98/prM
+DH6Z4IWT5w3xpaHpmgtUNcteCXutoDAts1AMilmDV7cHLU3Pjp/zPdHAKAz0aeky
+4Q==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A4 66 39 01 86 64 7F DC CC F1 85 53 E8 29 9E 2A 83 BC 7E A9
+ friendlyName: Invalid onlySomeReasons Test21 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0A28CE1427426524
+
+8v0WCIu3uMxm+zbaXC1cKoL4XunvJPSAed4XjMX9L1mHli9XxExo0xdaNuSAAfZq
+6B/twZt1FFO3uVfOBMjTupUFIXDRiJ4DMpWsliN1XXzotdsW9f/brWHbb6QZM34D
+LPYhxd7m2wzRyA7O8OWOAFKSnZMUeH69RdTFQD02EYxhhV+sHOr55K8Bf12rtySj
+09iwMCgOBOhCZ2/cyT2AyN4sPaVpgkPX9ndlcqzhAaH2ExIpeBzdRj63rWV8mZh/
+q2K4bWV1RXO79vuJRZuA6nsdynCP8j04wqEFXh5pKbbVnEOUBkeE9I9xih2YB6H2
+dZSnKqAPXRTyKu0QyiY9orM6bDtpGE8lp7f243zdIb9boYBy7yfOc7KI0J1Tt6jN
+zVM7SsltNUAS0MQ7NR4cyH+C+mDL0FGN8U9K6CUmb9fkDpFwfDTiFpJ4O4z3Q27M
+rNgE5393wU/DoWwNzi1Q43+46nrRBtD8x1az63xEvDzlRxd/JY1QXRKGVnpA6mPl
+JyjL6BdwOvySRNDwS+gvU8v50W8HDpTMPIWxrkL+hGFFBHKyK/EErVxpWb+a1pio
+hY28vhs2yk9TTI93gqNGDe+VBduLs0KnTxeWNI67/ML8ATftYN73A+TExGAs2Xis
+ahCV1vNv3kKWOq0tgeqGCmaL3umpsPAb8sPE51UULc0W5Kj9OJ+qTsOS6pRE0+KA
+RzhKfrLe3Fr/JBY2zONyroxcfzSW1qUamTgCh7EhbTHUq5INWTx3vaKOqeI9N49i
+wM24/ZGDULF6yckVHKbDVx8gOrame2DAOMivmglQ4ZiQ5Sr6cAfM1KZ5offji0td
+CyRS20Ou5dukqI3sbSMV+W5Vl5giAC0s6ICRjvZE8ECg3I02KZ2JvBBI14XEJbtH
+Dqb0cQsahHh0vxtkZA81J4b6hF5RjaWbwrJP7Jo9bEjhgS8335C3/kAqYkAgXEPO
+a3/esjyuzH6IM8OGjsieFbkto/WTl992ERDj885Gm1RTLAD+Jqnnv7y329cUfK0G
+BEiqDQd0nU/8qBwT0C/Tc4V2UoEuHp8mUULDawnjbIODFjbTuaO5g9Iv3+LCfbJ6
+i3GYrsQ3NF0B0/L87s96Cv2IcEhEcqc5PR4hwE6YQap4V/IWKgcZyw5WjZWY2maW
+YL2p7Pqc0VlR4SqRreg9HsvjUP5N7mNSG7YUHO7mjwTkXBnEHXddzuFPtFXg5G9Y
+Mv5M97Ix9rbNEeF+OmkZpxxZ0yE4HbxHzMwMdT08DfGL/b0A/666Q5ydsLggQ+4h
+kG8WJhEA+MaMFJft5t2po/Jqw3GLUT/NgPMpvrTY1wTjE/fQumz2xHGdPC7D0uGs
+TTzjKi8JZ9F0Il/gyxIf5YtiOnxH2uwvpx6yJW8+gIQy1deGmQrrO0txwju5vVIj
+2ogU7MEm4Rf54c/z6qruJJEd15qCt0L3oCqRxE3TQQV6iH5i2M0Rj91ov8nr+nT/
+OCtmKP56/WeqCMiGQZyaaa2V7MghQBX7U2OPZnHP3pYnLtTewsGbx0W2K4d0op0d
+PPLuQ+Uk3dyaWSzkZhq13QmMflfcTLM+Y1JRBdJXI8CySwdxxL2E7NuI9/huwNVu
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10.pem
deleted file mode 100644
index 1ef60f3971..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10.pem
+++ /dev/null
@@ -1,211 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQ2IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbfycd4Ehd
-RlHiRJp0MMk0H94GHYCYxpVEzfiC5V9w2M0NWJotHuHxdTvH02XZquFdQptZI0qZ
-AGeBgE3+FBJAGOK0ZxYJgSyscFWBTLGzFZu2Y09siuEwlr5W4z6iByJpFYsEK0JS
-icx7LPYOYyHmFpmDSdcUXwV59VWlaQn5HQIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnY+0pLeirrl2tR7LH2QWpXoO
-hUowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKJlZqSQSA4tpA42dNOs
-k5r0RU2BrRu2bPXhSEZHD0o46NJlNTNTfCAus4HtZ6GE1AvTIy3smHPGb1O4jth2
-9hYXVqNHIEIlejhxgSE0trBBT5L5vodq5Pu5qoTWPZ2Uu8pdqRvdmypKr7gI5inp
-Cu6s2eBv0+DeibQTg73sQuTj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA0
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50NiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQ2IHN1YkNBMDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAt36UX+gq562CFiw9L16IZ/AjJhU0BB9ji/77uw3AfvBGggmikeDq79BD
-yzBFrHys/L5UeXepakX1v+XvlxFjwvc8c226jf6uKEop5KJZDI8aV4byQvc1C8Ol
-MdgZ4pd6ofTl28r1VDkdDt94c7+Gl0CqBo6LawwGmNfSHUWqf6UCAwEAAaN/MH0w
-HwYDVR0jBBgwFoAUnY+0pLeirrl2tR7LH2QWpXoOhUowHQYDVR0OBBYEFAJIeLnM
-AVExdH85KjfCRJN+mGmAMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQUFAAOBgQCm
-Qa7i6335O64eyxJjXl3U2Bw5wN3JaK9t7f4dJAxfOlcblWbbes+Gk12UCYtxTZDj
-oZ70F4IoGU7JQt5CcdB2yQtctPK+X7A3/Vsxjknm11nCn4IhcU7LDkEiSovBGLR0
-KV3NAqQQhr1WQoY1Uf3Ncpl7b+SaZscZ3r35UJo4iw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA00
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA0
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJDQTAwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBR
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNV
-BAMTHXBhdGhMZW5Db25zdHJhaW50NiBzdWJzdWJDQTAwMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQC3rH58cOqP9U5iyQflKaVyYw+1LMhr3jDW9/Q3aedlH/TY
-iLmT71FUjHaJMWOCO6sAEYMphrRdIUy82rai3iJgrNtJ21uIFOlmjgwgl9amHX8B
-yT+qgiwLs8kzE6NgPYHgLgbKEIqgZ+AZplCt60tCbeGKLR/WtXrxAIgqU+ar1wID
-AQABo38wfTAfBgNVHSMEGDAWgBQCSHi5zAFRMXR/OSo3wkSTfphpgDAdBgNVHQ4E
-FgQUauYRxUFtrRo+gtywXa3yGfFQzgswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEB
-BQUAA4GBADnBidpEzasWbrLankXCoCaeizozu2dGAMMWpbs02cplC/vIlcr0myWK
-noFSuxUuQa7sMxp72p5r2ziJp5pk1gT2KX/kgOYlQqgbJ4UmARGP7er+zIPulXib
-suMShSCGO1xC+fXppdhPy+YQq8a7Mzi7XKqP5su+aTWw/B3a8ys9
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pathLenConstraint EE Certificate Test10
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA00
------BEGIN CERTIFICATE-----
-MIICpjCCAg+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJDQTAwMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowYzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTgw
-NgYDVQQDEy9JbnZhbGlkIHBhdGhMZW5Db25zdHJhaW50IEVFIENlcnRpZmljYXRl
-IFRlc3QxMDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr0SfgP3iREpEpoxL
-34yNQOjycTI5wM/Y9YXQ6E26DxRndEt8gy0Nt+w7/WcO0aJ/EA76704ckmtzahRW
-gH7YAntSVCkBwyB8EDt0eBxom9vWRhPmqJgF6PJtcuAZnkISqXfw7zurQN/p1HzT
-iBta6ocTlilBTPujtQ/X4O12W5kCAwEAAaN8MHowHwYDVR0jBBgwFoAUauYRxUFt
-rRo+gtywXa3yGfFQzgswHQYDVR0OBBYEFLsMSzv8dfhgJ3MxRW07FltMDKkGMA4G
-A1UdDwEB/wQEAwIB9jAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/
-BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAfOH+DXogRwi00dAkv43qzCo23eOg7
-uaaD7fgNVn7RrEYkyc0RZWf1P56IXe9aTM41eVmi1PyblkZ0aXH9e7ShaOW11Jk4
-OpIpx+vR7HqBjW0yqIXES3pbA6Vm26gj1WDuq0oSps0+BxKTL5cHxVlCT9+YES4B
-T1SmCaLl/UdsEA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:8F:B4:A4:B7:A2:AE:B9:76:B5:1E:CB:1F:64:16:A5:7A:0E:85:4A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0d:f1:3d:54:c8:22:83:d4:1c:69:d2:12:e3:82:09:7e:b6:c0:
- af:f4:41:9b:51:c5:04:d4:c5:ca:51:73:5c:c5:14:c5:d6:d0:
- 11:6c:40:ce:49:e7:80:49:a9:35:94:84:b5:bb:52:37:62:c3:
- 5e:0e:18:48:57:44:b1:cd:97:a2:44:ef:9f:75:44:16:9e:58:
- ff:db:7f:18:8e:d5:07:fc:01:64:17:c3:00:79:4d:02:af:dd:
- 08:88:37:03:be:cc:80:7a:cb:fd:e7:5c:53:03:b1:f2:17:16:
- 1a:14:25:f4:ea:50:8c:14:ff:58:e9:2f:fe:e4:75:d9:67:78:
- fa:7a
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-NiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUnY+0pLeirrl2tR7LH2QWpXoOhUowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEADfE9VMgig9QcadIS44IJfrbAr/RBm1HFBNTFylFzXMUUxdbQEWxAzknn
-gEmpNZSEtbtSN2LDXg4YSFdEsc2XokTvn3VEFp5Y/9t/GI7VB/wBZBfDAHlNAq/d
-CIg3A77MgHrL/edcUwOx8hcWGhQl9OpQjBT/WOkv/uR12Wd4+no=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subCA0
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:02:48:78:B9:CC:01:51:31:74:7F:39:2A:37:C2:44:93:7E:98:69:80
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 44:34:f6:c5:c0:16:f7:24:42:33:a8:e4:ca:74:71:94:76:93:
- e7:4b:7c:a3:8b:ac:ae:11:ab:46:94:f6:0d:88:b6:e0:96:1f:
- ab:04:6a:92:b7:6d:4b:aa:6a:b0:13:58:58:a7:7e:06:de:c1:
- 26:d4:09:e0:7b:a9:e4:dd:73:da:b0:cc:a0:61:ab:c4:c7:cb:
- c2:e1:66:f9:f2:2a:c2:c9:59:5f:05:c6:74:f8:bd:bb:92:24:
- 77:12:34:23:7d:95:99:bf:35:e0:6f:cf:2a:b6:19:29:9e:59:
- d2:0b:2f:07:44:25:66:6a:e9:5a:ed:7f:99:33:b5:3e:65:69:
- 57:95
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJDQTAXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFAJIeLnMAVExdH85KjfCRJN+mGmAMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAEQ09sXAFvckQjOo5Mp0cZR2k+dLfKOLrK4Rq0aU9g2ItuCWH6sE
-apK3bUuqarATWFinfgbewSbUCeB7qeTdc9qwzKBhq8THy8LhZvnyKsLJWV8FxnT4
-vbuSJHcSNCN9lZm/NeBvzyq2GSmeWdILLwdEJWZq6Vrtf5kztT5laVeV
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA00
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6A:E6:11:C5:41:6D:AD:1A:3E:82:DC:B0:5D:AD:F2:19:F1:50:CE:0B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 42:5b:18:71:be:d6:f0:b4:80:f6:33:3c:cd:99:0d:26:f3:90:
- 70:42:44:f8:f9:61:72:1c:b3:91:02:0a:14:55:67:d0:1b:23:
- 06:f0:90:76:49:c6:82:23:70:da:3a:15:95:90:80:aa:8f:0e:
- fb:4e:5b:9b:66:38:21:14:15:c1:65:71:1d:e5:b6:90:ae:b2:
- 7a:73:84:9a:1d:3c:f2:2f:65:0a:b4:7f:52:90:a1:1d:37:a6:
- 24:a8:7f:5e:72:e5:1a:8b:89:31:ac:dc:0a:3a:d2:15:7f:f5:
- 97:f3:1a:82:d6:fd:74:b5:92:0f:d5:d3:a5:74:1d:a3:7f:62:
- 1b:c4
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJDQTAwFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBRq5hHFQW2tGj6C3LBdrfIZ8VDOCzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQBCWxhxvtbwtID2MzzNmQ0m85BwQkT4+WFyHLORAgoUVWfQ
-GyMG8JB2ScaCI3DaOhWVkICqjw77TlubZjghFBXBZXEd5baQrrJ6c4SaHTzyL2UK
-tH9SkKEdN6YkqH9ecuUai4kxrNwKOtIVf/WX8xqC1v10tZIP1dOldB2jf2IbxA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10EE.pem
new file mode 100644
index 0000000000..2d7bbd0916
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest10EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E5 50 22 A8 C1 4E 7B 5C CB 90 98 45 C4 A7 F0 0A E0 ED 2E 33
+ friendlyName: Invalid pathLenConstraint Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pathLenConstraint EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA00
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YkNBMDAwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjBoMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTE4MDYGA1UEAxMvSW52YWxpZCBwYXRoTGVuQ29uc3RyYWludCBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0MTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCXqvJf0Sbty1YiHYZ7PHwNkMnllNAX+ilKxDm339jET5zegwNzwyTXh0nk05rc
+wLCqE0slxm6iWWfh3sK7DE+zWyj5RwiiwbT7K49hFLgnZ7/3x3wARVb0lLhN699d
+iRJm+Af3vNDVGkQ1FSpy4OBiUuc2XMiWktOV/smBAty8HvjZOBB4Zy0ijV1YZK+/
+ihX/Feqm0PjLsrASBqH5PAVYDzTXH406ayeUCK+daoxc9nO3jShm9bvTZwoc9tN5
+M/VzFHoG8S5lMWNBcnZd/8++FCEKb8H8FnLktCOYKGWahdYjiIMuGzwyM6XooCEJ
+rxfe03QfYtEknHXO5NZWF1oRAgMBAAGjfDB6MB8GA1UdIwQYMBaAFLq54oj31Fkl
+iuMp30+gBjjdcXSCMB0GA1UdDgQWBBTYF8STFBH7QOb0JnwVIxfQr6560zAXBgNV
+HSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAfYwDQYJKoZIhvcNAQELBQADggEBAPWrCmLHcQdJfIVQpCQ6ZAWKOStZ3fqB
+G6hjLBxvA54p3+y2yq7p/0pRR3w22yHOBUNqVjiR6WWRaZBBzQTxt0hj3Dlbj+CH
+qyBc1bbBWk7m/tKziUfcxdPuo9CcG0u1nLTgIE32OHUgSzTmpWO8/JDICCQ4dd6q
+ugfxqWJnlJVGhQSyrSUk7ZcCFG3H2oHDMPYiv2spEv6g6lbno4YrYE/8vl/IbE4w
+BDAjtU3v+DUvI9vxWUa7pocGyb2dBE87ED/4HqmfUmj6cZnzIYRTKX1zoEueu3ei
+bf8l1natz4YwVbQItLU8STxkCRQiYH8d01JBMVlIRA4g8YhPc9Bwmao=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E5 50 22 A8 C1 4E 7B 5C CB 90 98 45 C4 A7 F0 0A E0 ED 2E 33
+ friendlyName: Invalid pathLenConstraint Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,772EA7F9D57E3F11
+
+5Cj9j5qaOVLoai3GpY+FqYYvsjrAKoTHbLkjhIgjpRzrT1qGkdVe33DZ3mmw3td3
+gGVT8zN0sqvBW2nMAHkPMzpu93XZ0spQXuURePeletXPNTybPJRp5MFSFJynd/aq
+7ClQImECrXzKN4BR3bcSa5Dxld4K7ii4dOdlIQp2yhwOjpTk2o6EXj4eUy9EaKjI
+IOtwWNIXfOdMwc2+ABGSgZ4V1hinfuTm9h9UKMsg0U7AvUIIfk9jpl9AY0ZXT+Zl
+26fz9cM93p5afUFqHnKC1hUgzDY2RGGbipYXJhcFYyGMybXmR/9FpfdHBBbjTdDl
+KyVt7J0oKh8rknounW9or4M7MBdde74Gph2fCui+qh7ti75rgUuuxvjn7mW9+hbn
+RTyVudQ+Qde9NBi+FaQ1T3A7CdlnyfTcEVHtUoEaDUWz5QVuN4U7wwLfk3p8ifdy
+Ws2qoc4YINEXiv01LmQ1RXlYWBTqqQ+giMlS5pagttzppIvEZ/C7aalUEmJleIeV
+O8LHL8SXxfKbzayt0B4TA9B2A1JLQw9GNUzPSqRHTAdYF/oyQouHuij1N86gYub2
+tFIUCd8I2GGcKRgXM04NUslBc+aN0YWxKBqDCnJy9RlVF7SMcppnmyfvRmBPhcI4
+SCFNfKoZCywAVvjMc0rdAgWGG06bBg+8OUG5jfH07Rn0ydbp+StiURp4/xYUqc8U
+i3yDx+NljZdDt/JYM8z3sZKXNltfbypdK+1BCV4sxyfzWzjYqd6smmmtjR2A8AOD
+sMAAWMQPZSCJ6PtgNBEXNnDuQtdMNwrIpdHhUfTv9xB3ePdxpzfuKuZ7ncqfrTQ7
+De45pEt/eEWvlQuEABW7KKSPilRj7LKzFxk+qK/bwT5YB59q3veQ0ktpvo+KhUMB
+Ku7efDPV0TTbreNriUlM0ipUTdN8O30FHbxOX6ZzZ7YvpBQRZtKgG01OXpPsUOv9
+qi5JdkQuETK0YHKxy9Kg36VdPKS+pm58nxd7Vk1NL4Uw5Btb/6/96VdC/U4HTE4V
+dV/BsPV1SZQOONutjRIyMI2IPDlEfMcQgyojfHYRMG9VvHQvXfL9oRv+5eU6pxkE
+IILyicibk+tE2hNR1lZuCwHZ9qF3bcu7FvJVTiUeqrBMFtmyQYgQXrXNT7SwO0UC
+GECT4Jd2f+BnS4OgW4uKxJWqhwmTfxyevEGBQfAKGhL30J/foblBZDbc5yPIPiTv
+5PhyqHqlsYDEp/7phdyExgpMCnnqBO0NA2ET2yY576FpiWpaCVIlYODixK0xPNuE
+ziw6bZ2OOGUzj743b7CFVNUesd1S7CbPB1m4A3J+iimsuFUq1XGsesdM1ldOxZlA
+4MyBbkvweHtBP7YH86odh6nASA7n8I8RRVHOGa1dLAcwKHDs3qhjPd0EnZmrrrba
+t+SC2aunuXee2eyeM780obWfkSOmtJlXm2seq7bScNiAYzsCL+9Z3tOkCsH1LjNv
+mETaxgW+RRAklGMuVzRUzfprt+4pqeRdDrz5Uq/kJpYKx8d1Mi1YKuWN2JugPyOu
+qOEF0J+h+ydTBNL9d4DeME69PvD4JMq6Vny/lL4OVpS6ip+Tg75vpQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11.pem
deleted file mode 100644
index 259d24610f..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11.pem
+++ /dev/null
@@ -1,262 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQ2IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbfycd4Ehd
-RlHiRJp0MMk0H94GHYCYxpVEzfiC5V9w2M0NWJotHuHxdTvH02XZquFdQptZI0qZ
-AGeBgE3+FBJAGOK0ZxYJgSyscFWBTLGzFZu2Y09siuEwlr5W4z6iByJpFYsEK0JS
-icx7LPYOYyHmFpmDSdcUXwV59VWlaQn5HQIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnY+0pLeirrl2tR7LH2QWpXoO
-hUowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKJlZqSQSA4tpA42dNOs
-k5r0RU2BrRu2bPXhSEZHD0o46NJlNTNTfCAus4HtZ6GE1AvTIy3smHPGb1O4jth2
-9hYXVqNHIEIlejhxgSE0trBBT5L5vodq5Pu5qoTWPZ2Uu8pdqRvdmypKr7gI5inp
-Cu6s2eBv0+DeibQTg73sQuTj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA1
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50NiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQ2IHN1YkNBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAmzChDurmjaO/gLW4mwfnkQwkFgDcZvpMdZEqpd4u4+RaoyI7I6LlTFQ+
-wkZ0cnLVA8C/F6+ZqpMXg4s9pb04PuHb0xsgBHFefpSASxTCIBWVOmLq462zY6o8
-Iun/AQo4JVGx175EcIUkcldAg19+3l1NV4fg7BN7waHWiVfIzS0CAwEAAaN/MH0w
-HwYDVR0jBBgwFoAUnY+0pLeirrl2tR7LH2QWpXoOhUowHQYDVR0OBBYEFEQ04VAm
-/zwjDK2/vU7Ge+AMSIqqMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQUFAAOBgQCK
-Fy4Zq2RJVwWE4qzs2QbzST7CRcwqzwlUwH2S53MA3J38uXAEjqjJLyLSG7k9xjYq
-Xwq0hQZIfdeOkSMfSEUl3XWgYfQFGfmHdsUPJ0NX79NXXoyxsfZPRH9LF+CPnv8d
-kwA/on1VypfAuAv4/M6L3p7jFDISJRRGcXRBRB13lA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA11
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA1
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJDQTEwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBR
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNV
-BAMTHXBhdGhMZW5Db25zdHJhaW50NiBzdWJzdWJDQTExMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDSXWC7L0WLN2ZeSCkEhh0EhpdojjOAr8wqSRoVWRnyzGMM
-swGD3i80PXaZFl1qIeaER7LF0udID27SF6sC5g+kklfiK3UAn0YscNa2U6r27vwO
-2pj95+SfvnAuFgQoO82T4VQtUJnUOB+NAwWHGZ0Y9WiAxus6qNqEVTbr3CcT4wID
-AQABo38wfTAfBgNVHSMEGDAWgBRENOFQJv88Iwytv71OxnvgDEiKqjAdBgNVHQ4E
-FgQUs8D3URQQ9lyaTiyHUFHlkdNYWyswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEB
-BQUAA4GBADYFuhgJI8Nyw7Mhpcq5n2NHNEXkP8g5ibaa86O1I//NQRsXnQ42VQrQ
-UemJMwtYlYjXHCL3MaiZOOXv+jaJDAbAE8zDq1c11WuKYBQ/ABNR+jCYnOlnR4lH
-1Ibtl3Y4v7sEq5V6MyO6DugCihflJSVSOV8UFaYxZQ3cb/AgI41q
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA11X
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA11
------BEGIN CERTIFICATE-----
-MIICmDCCAgGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJDQTExMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowVTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSow
-KAYDVQQDEyFwYXRoTGVuQ29uc3RyYWludDYgc3Vic3Vic3ViQ0ExMVgwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBALXNtkOI9gcg1V1Ecg8VBS17NqL8yaeNOG8h
-VgH8Peay4GsCzxqYOSnPDeBKtlMJ+TAmMmz30FZ4XtEJScvx9yllHjEM85LdyvTM
-ZD6gy7yWApPgkhMipi9vww7JUtH6RrDQmKurTvtx5BhM/lYWlDVSnxX/CmWFm22r
-vwk/Rbz1AgMBAAGjfDB6MB8GA1UdIwQYMBaAFLPA91EUEPZcmk4sh1BR5ZHTWFsr
-MB0GA1UdDgQWBBRqNvBXdT9CFVC16QgdKDfFreIGvDAOBgNVHQ8BAf8EBAMCAQYw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
-hvcNAQEFBQADgYEAXlaYIT0dDTF0GGAJ8H41hvUkovy3ge8i7YDWofVBhdt+rEeC
-v0tvUcc+7mPSj3i5flZgJnbXMwS7wNlLhttOpbBMqL5/vWyIcvrgXm3qmXowQF0H
-WuW/WllHgGzQ8tIbGUWcl2bvkFNA5nIeumCrK1vmIgNqYaRUdOH9xuPuvxw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pathLenConstraint EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA11X
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJzdWJDQTExWDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMGMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czE4MDYGA1UEAxMvSW52YWxpZCBwYXRoTGVuQ29uc3RyYWludCBFRSBDZXJ0aWZp
-Y2F0ZSBUZXN0MTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK/Kz6a5RrnL
-VxjtAz2f5jD2LFhGyAiWK8+D2zGdebUqwosPmO1bFaTy4UpTN1y2NDdhbZJ9u6q4
-UyBlEswNHWLbKw2eAhhlj4tL8W7qCcCTiIDusf+/it87dawc9FbLFDa6ZhPQn3zf
-fOKdROTtdR1GLihtxkPeVht0YCU0Y5jBAgMBAAGjazBpMB8GA1UdIwQYMBaAFGo2
-8Fd1P0IVULXpCB0oN8Wt4ga8MB0GA1UdDgQWBBSms0sRlWo2giuUP4b24hz3mOOT
-ZjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqG
-SIb3DQEBBQUAA4GBAGVBiyATRLrOnNHi80uCRg3a7ZWI4275SlflSYwZhFBkGkd2
-C4kyAGKsNrFGtuCpDNM7IgF4xbQweHBODNwwCOfsdc9OahGntqhxeKxUQpDkwc8a
-3Faqn6fs/BnZqkNzepiZdHCsTdiyiiB7LxL9LVo7575vfuB0yBsCk2lGgbkz
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:8F:B4:A4:B7:A2:AE:B9:76:B5:1E:CB:1F:64:16:A5:7A:0E:85:4A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0d:f1:3d:54:c8:22:83:d4:1c:69:d2:12:e3:82:09:7e:b6:c0:
- af:f4:41:9b:51:c5:04:d4:c5:ca:51:73:5c:c5:14:c5:d6:d0:
- 11:6c:40:ce:49:e7:80:49:a9:35:94:84:b5:bb:52:37:62:c3:
- 5e:0e:18:48:57:44:b1:cd:97:a2:44:ef:9f:75:44:16:9e:58:
- ff:db:7f:18:8e:d5:07:fc:01:64:17:c3:00:79:4d:02:af:dd:
- 08:88:37:03:be:cc:80:7a:cb:fd:e7:5c:53:03:b1:f2:17:16:
- 1a:14:25:f4:ea:50:8c:14:ff:58:e9:2f:fe:e4:75:d9:67:78:
- fa:7a
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-NiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUnY+0pLeirrl2tR7LH2QWpXoOhUowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEADfE9VMgig9QcadIS44IJfrbAr/RBm1HFBNTFylFzXMUUxdbQEWxAzknn
-gEmpNZSEtbtSN2LDXg4YSFdEsc2XokTvn3VEFp5Y/9t/GI7VB/wBZBfDAHlNAq/d
-CIg3A77MgHrL/edcUwOx8hcWGhQl9OpQjBT/WOkv/uR12Wd4+no=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:44:34:E1:50:26:FF:3C:23:0C:AD:BF:BD:4E:C6:7B:E0:0C:48:8A:AA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:23:83:69:3d:e9:a9:b9:0c:9f:fd:64:34:97:b1:1e:e3:c6:
- 25:62:c4:d5:cb:ee:87:98:04:d6:96:04:0e:7e:96:3b:22:7c:
- 3f:e7:f6:f8:a5:d4:14:a2:86:2c:10:d6:b6:08:a6:da:2a:3e:
- 7e:70:f1:d1:e6:a0:6e:55:1c:68:10:4f:65:d2:1f:51:d7:a0:
- 6b:d7:df:db:7e:2e:f6:8f:5e:64:5e:6a:ca:48:2b:8c:f0:85:
- 37:f3:70:67:c9:44:c4:8f:7f:ad:93:93:e6:d9:c0:7e:8d:0e:
- 01:16:01:82:e2:b9:a6:28:1f:3b:e9:0a:d0:ea:d6:23:a1:c4:
- a5:1a
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJDQTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFEQ04VAm/zwjDK2/vU7Ge+AMSIqqMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAI0jg2k96am5DJ/9ZDSXsR7jxiVixNXL7oeYBNaWBA5+ljsifD/n
-9vil1BSihiwQ1rYIptoqPn5w8dHmoG5VHGgQT2XSH1HXoGvX39t+LvaPXmReaspI
-K4zwhTfzcGfJRMSPf62Tk+bZwH6NDgEWAYLiuaYoHzvpCtDq1iOhxKUa
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA11
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B3:C0:F7:51:14:10:F6:5C:9A:4E:2C:87:50:51:E5:91:D3:58:5B:2B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 5f:3d:a5:ee:09:93:d8:4f:cf:28:3b:05:87:8e:8b:08:7e:2d:
- 36:0e:c2:f0:cd:54:94:05:54:07:2f:9d:e6:8d:1b:9c:f5:fe:
- 92:7e:3f:bc:94:d5:fd:82:c0:87:dc:93:32:c8:ab:01:59:3b:
- 6a:df:8e:af:cb:14:f7:f7:39:50:da:8c:ac:02:7c:97:24:27:
- ce:11:a9:9b:38:72:6e:32:c4:a1:0a:f3:34:5d:62:9d:f8:ea:
- 21:1a:bc:0e:22:98:6f:80:25:1f:5c:c4:fe:1e:7b:ff:9c:4a:
- 83:ec:02:29:db:a0:6e:cb:9e:98:89:33:be:25:8c:2d:48:9d:
- 70:3d
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJDQTExFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBSzwPdRFBD2XJpOLIdQUeWR01hbKzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQBfPaXuCZPYT88oOwWHjosIfi02DsLwzVSUBVQHL53mjRuc
-9f6Sfj+8lNX9gsCH3JMyyKsBWTtq346vyxT39zlQ2oysAnyXJCfOEambOHJuMsSh
-CvM0XWKd+OohGrwOIphvgCUfXMT+Hnv/nEqD7AIp26Buy56YiTO+JYwtSJ1wPQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA11X
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6A:36:F0:57:75:3F:42:15:50:B5:E9:08:1D:28:37:C5:AD:E2:06:BC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 93:c1:d4:9f:53:f4:86:55:66:46:ba:2f:82:df:c3:81:ad:52:
- 95:0f:cb:f0:c0:25:ca:b2:fa:80:c7:b4:50:a3:95:70:ea:01:
- b1:30:fe:c9:da:a0:b4:fb:a6:9f:55:ec:3f:df:12:37:bb:44:
- cf:6a:5c:7d:fa:34:93:7c:9d:5f:f0:d6:fc:dc:07:9f:1f:2d:
- bc:02:3f:80:59:de:31:ba:19:c8:e8:a9:3c:e7:1d:28:e8:cb:
- f7:4d:e2:f6:26:cd:45:2f:d4:70:77:68:ae:1e:5d:0f:55:c6:
- fb:f4:5d:64:3c:e0:30:a7:2d:3a:ed:4e:7b:a1:e2:13:70:da:
- 30:e4
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJzdWJDQTExWBcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUajbwV3U/QhVQtekIHSg3xa3iBrwwCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEAk8HUn1P0hlVmRrovgt/Dga1SlQ/L8MAlyrL6gMe0
-UKOVcOoBsTD+ydqgtPumn1XsP98SN7tEz2pcffo0k3ydX/DW/NwHnx8tvAI/gFne
-MboZyOipPOcdKOjL903i9ibNRS/UcHdorh5dD1XG+/RdZDzgMKctOu1Oe6HiE3Da
-MOQ=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11EE.pem
new file mode 100644
index 0000000000..6c456d7ec8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest11EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E6 98 9F F1 E4 B5 04 FF 24 2E EC AB 3E 07 30 38 21 C7 01 FF
+ friendlyName: Invalid pathLenConstraint Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pathLenConstraint EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubsubCA11X
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YnN1YkNBMTFYMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowaDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExODA2BgNVBAMTL0ludmFsaWQgcGF0aExlbkNvbnN0cmFpbnQg
+RUUgQ2VydGlmaWNhdGUgVGVzdDExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA1cl8/9ip/J/At2SsSX+IJEEVyheRfuATAjbGXo7Cxrc0hDSRHTovhpBn
+9bvr2U3tLle6PnM+04bGz+Xt4+XAwq3bYepL0Y9TKx6S9sFwdVSWM3tpfS15OfeB
+G0dIugOZMSm+o8VQUoFRkEazcWCOUdu+9KEHXBecAeWxRof3IM0R6i3cTprfjCs5
+yXgsCln5HUPLDw5twRYOEE5mnEWtraWEFUeYE8xVFwwk69N9b95gpTsEvzPnyc7Y
+vcEeVGDsezBQmPxDSOXA1pDOqBswDj90rFy/ZxQWPSOdV7dSk08Aa2KayXgL30gz
+mO6ENzNWfIZ0g6TN9Oq8K+lhRx/E6wIDAQABo2swaTAfBgNVHSMEGDAWgBSD2ri1
+xp3Iiwh8iz/tGnIl4q8b6jAdBgNVHQ4EFgQUOVf5EG2PkPu3WYGjOi+xdDjbuacw
+DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
+9w0BAQsFAAOCAQEApEdV59RrhEgGjn1V6YgmOZrmFoy7Vr1Ss36w+MY7OqJ5zdYj
+BJPk/cDWct/Fk/X+i735WzzY11K4KrLc1DVkfrTyRPLHChRFma5g0p5OUUDvofyj
+5gky5i8S3+3l8GthFqJyVgjqagILlj6+az/liTiCLrlKk3+MOeI3xZfqu0fhfWTL
+CMmxAhrG5hjMR/YAcoSLsM3Vu7cwWVn8zB7PA22EnEBspIxwjrH1diVSSix0Mr2U
+VIjrBMmLHIuYv2s4ZS29iPsKcikiXK6+GynT6QuNf0hXEB9a/H1NEBu69+AnXnNN
+8KDP6+hPJxVKCLApWqbmGqJE8b6swlhRomACaA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E6 98 9F F1 E4 B5 04 FF 24 2E EC AB 3E 07 30 38 21 C7 01 FF
+ friendlyName: Invalid pathLenConstraint Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,686D0DE45DA2B6C2
+
+VaAU12sWq1Yg+V760zkDSlnQXjjyrXCaIhGOwTxTgbrD7+7ZxAnKlXuV4oNnJQm3
+bIn7RQlR7UiOVdNhgMLz0Mq4J2zpqgCJMTm+mkLIukiICn7a7f/e0VlMyBfFQeWH
+gsCUz0pIwJ/dT+hPTFkcBmnpN/2gPkZTb2roGFksUZ6Vk2rV2Ut4tg2rqG3SoYws
+BSNx3ZAl0updwkLjjwa+/YtGOOAfqqUfJHsLmhkYgaZ0l4gumy6oxz8wcc9YLOCC
+qX+5MHfV0cpgjw39N64RYY/vbEvUp1lVFT+LZW2PQF1IJTlw7JvRk2RDxpKTkAai
+QcqYmFoTnPQrcPQ6YtJn6lFTd+iHts7bA/zn+FXkd/a2wm0zwhGLFmYIVfxICC+d
+1zHZBg5BEYBEq4IYx9vbHGXyLnWbe6/jqBQZs+iWmLoia00CwtLy03JFIU+K0xAW
+bCNd7KHo+gtV3H0WREVl07/a1zsjUEx0hbfENQJL6I674WQpYR5+ca6RK6JFhchc
+OiuAOz5X0tYcV/0dZwdN4iu3ezTbnz/wjeTbxvkFyX5GMgJ2QN0IB4ZKedEbmdhC
++a1S8Q4DHMC7XE89R8jC4nIV0TsSbAmGhK8PwelKamBRG+WZrd9r+j+JQ4Sikn2g
+djGA6/7I3BdRppMScqwhRxc72tWPLguwU4oA9eLcatZ53MFiYd6ntVuTeRVjRpeL
+IhapZxZDSvNubE8+ObyvmKGTxUgedotSWHJXyv8+2GKGCwl30LSTBVrizsXry+Tf
+0H6gHC8OY4v6S6UdsLVauXojkdVI7xH1GBco9XDGibmvi9HxggBC9QMRdRE3PU90
+Xl2ur/CWEkMMrmjz0ZfXapQZgGSaLUy+PJShX5SxKifoNT9tLZmHPSTgYlIT8ijc
+pu/DUL/bkF7J8Pv0660T7Gj3RWnfIe+2MX0AUObKRBgP7heVJB2a9xmX7VbHLP+9
+0zp7Omk15r3DrWVEqZJQhnM7/0B77NWRXWtdyTlO7jA6fW6i9q0ZIsgcxAf+VqN3
+tpeKI42jby51SopRNwdbVwi8WmVonzpYnwuDeXlRScBMZpDaqbn5+fQjsMzt3Pjc
+Ly6Nqq1tngz9f1QAb2a2RLSM1RKuWoGvDzSQCgdcgH9C3XOXi/6WNI+9/oaIcvKg
+PACApYS6OfoHzb9o6pntUAXTWHV4djx71TX1tcpDRoR8OKlMbF4ZzWOVX+iOmnkz
+LUVyILMB9HWuns7l/Dr7oogP3sTua1GyVuywCZBgVIxrrMtVJJJfKH3B+rte9jDy
+lvKFAxlPOT3lwTcd/1Dx7FX7RVQM0l1uB8qWH3h+2N/H+4y+ETBg6yadKKrfzjro
+I+JDpQU2oGBNdORnNSBHBYXYSlYE5heqfeNz02GsT5uhPkhV4yWP1FOnxi5A/kcV
+iDkKYk7jAjVx/2dlZPa4oPHiGf9PNGE72cn3nMdlPNNcM+bjJogLAc1czNeU9B6u
+mWraqdYS56WRNkOIZmw/2JrSNAQOSGx+WM5UL6qaPqdlylVzPsHQEpTQ0mepbwfH
+Ftecmyrb9VyAkW5qmOnpFPhNVvPAGi3paxm1gFBKYSsynO4tkw9VUJMPEOOcyff6
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12.pem
deleted file mode 100644
index 3325707a9b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12.pem
+++ /dev/null
@@ -1,263 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQ2IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbfycd4Ehd
-RlHiRJp0MMk0H94GHYCYxpVEzfiC5V9w2M0NWJotHuHxdTvH02XZquFdQptZI0qZ
-AGeBgE3+FBJAGOK0ZxYJgSyscFWBTLGzFZu2Y09siuEwlr5W4z6iByJpFYsEK0JS
-icx7LPYOYyHmFpmDSdcUXwV59VWlaQn5HQIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnY+0pLeirrl2tR7LH2QWpXoO
-hUowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKJlZqSQSA4tpA42dNOs
-k5r0RU2BrRu2bPXhSEZHD0o46NJlNTNTfCAus4HtZ6GE1AvTIy3smHPGb1O4jth2
-9hYXVqNHIEIlejhxgSE0trBBT5L5vodq5Pu5qoTWPZ2Uu8pdqRvdmypKr7gI5inp
-Cu6s2eBv0+DeibQTg73sQuTj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA1
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50NiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQ2IHN1YkNBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAmzChDurmjaO/gLW4mwfnkQwkFgDcZvpMdZEqpd4u4+RaoyI7I6LlTFQ+
-wkZ0cnLVA8C/F6+ZqpMXg4s9pb04PuHb0xsgBHFefpSASxTCIBWVOmLq462zY6o8
-Iun/AQo4JVGx175EcIUkcldAg19+3l1NV4fg7BN7waHWiVfIzS0CAwEAAaN/MH0w
-HwYDVR0jBBgwFoAUnY+0pLeirrl2tR7LH2QWpXoOhUowHQYDVR0OBBYEFEQ04VAm
-/zwjDK2/vU7Ge+AMSIqqMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQUFAAOBgQCK
-Fy4Zq2RJVwWE4qzs2QbzST7CRcwqzwlUwH2S53MA3J38uXAEjqjJLyLSG7k9xjYq
-Xwq0hQZIfdeOkSMfSEUl3XWgYfQFGfmHdsUPJ0NX79NXXoyxsfZPRH9LF+CPnv8d
-kwA/on1VypfAuAv4/M6L3p7jFDISJRRGcXRBRB13lA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA11
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA1
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJDQTEwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBR
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNV
-BAMTHXBhdGhMZW5Db25zdHJhaW50NiBzdWJzdWJDQTExMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDSXWC7L0WLN2ZeSCkEhh0EhpdojjOAr8wqSRoVWRnyzGMM
-swGD3i80PXaZFl1qIeaER7LF0udID27SF6sC5g+kklfiK3UAn0YscNa2U6r27vwO
-2pj95+SfvnAuFgQoO82T4VQtUJnUOB+NAwWHGZ0Y9WiAxus6qNqEVTbr3CcT4wID
-AQABo38wfTAfBgNVHSMEGDAWgBRENOFQJv88Iwytv71OxnvgDEiKqjAdBgNVHQ4E
-FgQUs8D3URQQ9lyaTiyHUFHlkdNYWyswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEB
-BQUAA4GBADYFuhgJI8Nyw7Mhpcq5n2NHNEXkP8g5ibaa86O1I//NQRsXnQ42VQrQ
-UemJMwtYlYjXHCL3MaiZOOXv+jaJDAbAE8zDq1c11WuKYBQ/ABNR+jCYnOlnR4lH
-1Ibtl3Y4v7sEq5V6MyO6DugCihflJSVSOV8UFaYxZQ3cb/AgI41q
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA11X
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA11
------BEGIN CERTIFICATE-----
-MIICmDCCAgGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJDQTExMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowVTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSow
-KAYDVQQDEyFwYXRoTGVuQ29uc3RyYWludDYgc3Vic3Vic3ViQ0ExMVgwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBALXNtkOI9gcg1V1Ecg8VBS17NqL8yaeNOG8h
-VgH8Peay4GsCzxqYOSnPDeBKtlMJ+TAmMmz30FZ4XtEJScvx9yllHjEM85LdyvTM
-ZD6gy7yWApPgkhMipi9vww7JUtH6RrDQmKurTvtx5BhM/lYWlDVSnxX/CmWFm22r
-vwk/Rbz1AgMBAAGjfDB6MB8GA1UdIwQYMBaAFLPA91EUEPZcmk4sh1BR5ZHTWFsr
-MB0GA1UdDgQWBBRqNvBXdT9CFVC16QgdKDfFreIGvDAOBgNVHQ8BAf8EBAMCAQYw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
-hvcNAQEFBQADgYEAXlaYIT0dDTF0GGAJ8H41hvUkovy3ge8i7YDWofVBhdt+rEeC
-v0tvUcc+7mPSj3i5flZgJnbXMwS7wNlLhttOpbBMqL5/vWyIcvrgXm3qmXowQF0H
-WuW/WllHgGzQ8tIbGUWcl2bvkFNA5nIeumCrK1vmIgNqYaRUdOH9xuPuvxw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pathLenConstraint EE Certificate Test12
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA11X
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJzdWJDQTExWDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMGMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czE4MDYGA1UEAxMvSW52YWxpZCBwYXRoTGVuQ29uc3RyYWludCBFRSBDZXJ0aWZp
-Y2F0ZSBUZXN0MTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKYWPPc7psjO
-loPqdJ0NVow1+jFLB3yaoLHoJ+72kbII2gHjDiiZqm3e1E8Bqo136BrJlUrf5ZBj
-5G7DoA0OWn12+0bHhTNOEucIAFe/M6DpdHEIRR3l9CA20h4VMN5dUnQlVRt5uzGb
-RWcxgL5F79IUTDI1M2JJz2z8Aj/WIsbRAgMBAAGjfDB6MB8GA1UdIwQYMBaAFGo2
-8Fd1P0IVULXpCB0oN8Wt4ga8MB0GA1UdDgQWBBQfCYLms5akqSyTnpkK+G20CC7J
-7zAOBgNVHQ8BAf8EBAMCAfYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
-EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEABeLBzaJ0fJ0vgFUpXxNodli4
-jWo3oP+YW75X3NsMhhl31MbHAyUVw7CCEspHiIIRtSfJCALAaH9Ug7kMFjFDrxTH
-2790IdTodWieyUn/sdU9WWVRXiR7d5M2SVIYwdc6NjmsSVg6m++W99Uv5pBzoTAA
-ClExK3cmR6k5T7cF58Y=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:8F:B4:A4:B7:A2:AE:B9:76:B5:1E:CB:1F:64:16:A5:7A:0E:85:4A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0d:f1:3d:54:c8:22:83:d4:1c:69:d2:12:e3:82:09:7e:b6:c0:
- af:f4:41:9b:51:c5:04:d4:c5:ca:51:73:5c:c5:14:c5:d6:d0:
- 11:6c:40:ce:49:e7:80:49:a9:35:94:84:b5:bb:52:37:62:c3:
- 5e:0e:18:48:57:44:b1:cd:97:a2:44:ef:9f:75:44:16:9e:58:
- ff:db:7f:18:8e:d5:07:fc:01:64:17:c3:00:79:4d:02:af:dd:
- 08:88:37:03:be:cc:80:7a:cb:fd:e7:5c:53:03:b1:f2:17:16:
- 1a:14:25:f4:ea:50:8c:14:ff:58:e9:2f:fe:e4:75:d9:67:78:
- fa:7a
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-NiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUnY+0pLeirrl2tR7LH2QWpXoOhUowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEADfE9VMgig9QcadIS44IJfrbAr/RBm1HFBNTFylFzXMUUxdbQEWxAzknn
-gEmpNZSEtbtSN2LDXg4YSFdEsc2XokTvn3VEFp5Y/9t/GI7VB/wBZBfDAHlNAq/d
-CIg3A77MgHrL/edcUwOx8hcWGhQl9OpQjBT/WOkv/uR12Wd4+no=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:44:34:E1:50:26:FF:3C:23:0C:AD:BF:BD:4E:C6:7B:E0:0C:48:8A:AA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:23:83:69:3d:e9:a9:b9:0c:9f:fd:64:34:97:b1:1e:e3:c6:
- 25:62:c4:d5:cb:ee:87:98:04:d6:96:04:0e:7e:96:3b:22:7c:
- 3f:e7:f6:f8:a5:d4:14:a2:86:2c:10:d6:b6:08:a6:da:2a:3e:
- 7e:70:f1:d1:e6:a0:6e:55:1c:68:10:4f:65:d2:1f:51:d7:a0:
- 6b:d7:df:db:7e:2e:f6:8f:5e:64:5e:6a:ca:48:2b:8c:f0:85:
- 37:f3:70:67:c9:44:c4:8f:7f:ad:93:93:e6:d9:c0:7e:8d:0e:
- 01:16:01:82:e2:b9:a6:28:1f:3b:e9:0a:d0:ea:d6:23:a1:c4:
- a5:1a
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJDQTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFEQ04VAm/zwjDK2/vU7Ge+AMSIqqMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAI0jg2k96am5DJ/9ZDSXsR7jxiVixNXL7oeYBNaWBA5+ljsifD/n
-9vil1BSihiwQ1rYIptoqPn5w8dHmoG5VHGgQT2XSH1HXoGvX39t+LvaPXmReaspI
-K4zwhTfzcGfJRMSPf62Tk+bZwH6NDgEWAYLiuaYoHzvpCtDq1iOhxKUa
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA11
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B3:C0:F7:51:14:10:F6:5C:9A:4E:2C:87:50:51:E5:91:D3:58:5B:2B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 5f:3d:a5:ee:09:93:d8:4f:cf:28:3b:05:87:8e:8b:08:7e:2d:
- 36:0e:c2:f0:cd:54:94:05:54:07:2f:9d:e6:8d:1b:9c:f5:fe:
- 92:7e:3f:bc:94:d5:fd:82:c0:87:dc:93:32:c8:ab:01:59:3b:
- 6a:df:8e:af:cb:14:f7:f7:39:50:da:8c:ac:02:7c:97:24:27:
- ce:11:a9:9b:38:72:6e:32:c4:a1:0a:f3:34:5d:62:9d:f8:ea:
- 21:1a:bc:0e:22:98:6f:80:25:1f:5c:c4:fe:1e:7b:ff:9c:4a:
- 83:ec:02:29:db:a0:6e:cb:9e:98:89:33:be:25:8c:2d:48:9d:
- 70:3d
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJDQTExFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBSzwPdRFBD2XJpOLIdQUeWR01hbKzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQBfPaXuCZPYT88oOwWHjosIfi02DsLwzVSUBVQHL53mjRuc
-9f6Sfj+8lNX9gsCH3JMyyKsBWTtq346vyxT39zlQ2oysAnyXJCfOEambOHJuMsSh
-CvM0XWKd+OohGrwOIphvgCUfXMT+Hnv/nEqD7AIp26Buy56YiTO+JYwtSJ1wPQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA11X
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6A:36:F0:57:75:3F:42:15:50:B5:E9:08:1D:28:37:C5:AD:E2:06:BC
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 93:c1:d4:9f:53:f4:86:55:66:46:ba:2f:82:df:c3:81:ad:52:
- 95:0f:cb:f0:c0:25:ca:b2:fa:80:c7:b4:50:a3:95:70:ea:01:
- b1:30:fe:c9:da:a0:b4:fb:a6:9f:55:ec:3f:df:12:37:bb:44:
- cf:6a:5c:7d:fa:34:93:7c:9d:5f:f0:d6:fc:dc:07:9f:1f:2d:
- bc:02:3f:80:59:de:31:ba:19:c8:e8:a9:3c:e7:1d:28:e8:cb:
- f7:4d:e2:f6:26:cd:45:2f:d4:70:77:68:ae:1e:5d:0f:55:c6:
- fb:f4:5d:64:3c:e0:30:a7:2d:3a:ed:4e:7b:a1:e2:13:70:da:
- 30:e4
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJzdWJDQTExWBcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUajbwV3U/QhVQtekIHSg3xa3iBrwwCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEAk8HUn1P0hlVmRrovgt/Dga1SlQ/L8MAlyrL6gMe0
-UKOVcOoBsTD+ydqgtPumn1XsP98SN7tEz2pcffo0k3ydX/DW/NwHnx8tvAI/gFne
-MboZyOipPOcdKOjL903i9ibNRS/UcHdorh5dD1XG+/RdZDzgMKctOu1Oe6HiE3Da
-MOQ=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12EE.pem
new file mode 100644
index 0000000000..0f42c6ad35
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest12EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B9 41 D4 07 1D 24 78 06 BC 38 DC A0 11 D0 45 7A 76 7E 26 78
+ friendlyName: Invalid pathLenConstraint Test12 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pathLenConstraint EE Certificate Test12
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubsubCA11X
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YnN1YkNBMTFYMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowaDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExODA2BgNVBAMTL0ludmFsaWQgcGF0aExlbkNvbnN0cmFpbnQg
+RUUgQ2VydGlmaWNhdGUgVGVzdDEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAmVlts3N4uHNv7lGOT4GLaF+tsPvd1uviRc+qIdHp7qZNONV0TCr2Kt9l
+K9MGtM0OSLUhrrKN/oooKo3oVgqfGBMEzbPERKF2oy96WHjhA7WoVcHpQyPKOuUP
+hUY8rhMXYoTFeRakKK5kFobrKE70mI8tsmfOBA4JJKMBLSlu8ivgMigK1CT+bhHl
+uazZCm58czJ5Lw+ol00v5xQUKg8eJnYu++BBftkFkDU9QHW/2WH6ceiAcwzL9IUV
+1wuCQYfKfUklUtzcqSCoOCWNE0Yp3GaOgmgR6ssn5p2lyqXxZiVtGx1KcDhy42AE
+fbd5Kp3/FSQRV6UEr/KoJ86sBpkBmwIDAQABo3wwejAfBgNVHSMEGDAWgBSD2ri1
+xp3Iiwh8iz/tGnIl4q8b6jAdBgNVHQ4EFgQUF5D2PD0NAiPAZIw+M6ZDoKxgu7Mw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
+AQH/BAQDAgH2MA0GCSqGSIb3DQEBCwUAA4IBAQCSRSJrJvGXtMVNUy9eDgXRV2P3
+ujCOCX3LsZAqd1x99DQorAhKoq1Hjd47XDmZherCmEpkkz6uq71sAg8UilLHEcwB
+cJ+IXJSohUIme3G2iil7BIU7FhIw3gbr+jpDlroqKTsx/9BKzh1Ms0c+PwoQGfHs
+CsIsYBb1Op7JQuJrpgggdTWskDIfcWOKg0QIRaTn72e/jF6IBKSr1S6D2xtFAxGm
+Kda8HVzltawA/WKcSy0U5qvLrBv8FK8vjkWut4wjid+eAmmsMQwOuwZNcqaXR2ve
+tDg1aWhFKdhmcOAirsC4wsuS5V0hTObIZR3d1BriitU8VhUq3PvlgAzrTaiE
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B9 41 D4 07 1D 24 78 06 BC 38 DC A0 11 D0 45 7A 76 7E 26 78
+ friendlyName: Invalid pathLenConstraint Test12 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,16A8528E11F2A947
+
+5QYPlv/Y0/58FuOcUlQgeS5owcOToBQQwmhiQNhFREiB4KdIEL2E3mEmgwvw6kjs
+RfjAALCN6akHebaTinBAodceQlWBkxCdC+LaQZ9nlZOenliuKtIgrCsu2DOQYRNS
+Q9kzTH0uRD1uJopiO18ov0R30Vs+nBr/L+JYS/saFalMylMW92eZmxz+4/bJfIwl
+S9SPhu2KIkpfEu1OTnE7KHEXei63/aMA5sIv4hO1fLwQQnfkWypDSyAJb7Yvh+tu
+bziY7yWe9hJq2GZSLk3rvf5mNmfz4Op7c0CROH1Eq4+uMfKB4ud3+s/nItxxgMmg
+TrXUzbYLYR2Zz+pIalwd9Kbt5fnNEGuGQRNfyd2WWMKqLyHwG4EztoCl9fkhek10
+jySn5Mi2gdeHSOykYMo60By6So+fdTOh7DFP+zXd0f9jp/ihGgm/Zbtby2g65cy5
+rt6WXD7px321jxxubUkdtv+UhBZgj0zasyoj36gpZjuptwfxMp1pc+Gbw3NsCFOu
+IjxiW6pbdip3Endvy8tUD6nljA0TKNyRL4ynpU2vqCsx70KE+UFBkg2oO2VB6FP9
+LmSmGT8IHqZD5n4slyLXpu63aX71ez7kWEMoP7oxASDT65dMDz3prkCJ1OTAbpOp
+nL3PO541KHo/e7OLfCo1SSYTSeiEOVcaM2GeuewmmaC18d4Jp5K9FT3ymyu5/PvQ
+XGmpQLnByoBVaf2/845r/AiVcmXL+AoP0/wmQD+6Unvlqe+bjcyfe6PcOP8iR7jK
+8U05B1qBzQkS+4l1UnsR+5ykSRVvx5U4QBqAf8xd4HwT9qPOtnIee9j/ubQWYy3B
+Rri8q2XvsaCPPkKgvnL8GtltODOC8aCGuROpEUR40Y0hm0q5Hpl8fUtr19wbVbhm
+3IMJrN/QKTLHz+qvme54GIwC2hiNbRX0xnR00eKHPNwyhXJ8hlwFst0RX4uN/4lo
+ZfmRnbHIHXEsDwsu5fRiZNlC5gT8omyDTgFNFdWtBRm8otaLzAzopHh9WGHw8/Qs
+S17hqB5qgbkmFSGpqHGfMQ6l4hAk2bmXC+lyABNa1K0cxx5oRVW+hnhjM4FFS7SM
+qu1Q4izlpEXZ55lq+hRTASwvdLCxli7V+dqsKtmsB8RVCLDSxv8gQOS5haMjZZTR
+Ojd6ODvdWXFw2PVPEIKBEYszi5XWZDaHcPNnFKaV5swqgqIGJNnEaxr0/5I+xOVV
+GtxHp62u01+fiZfqXCh5a1NtZ1IsMKLQd+SQESyDkqBsmF8gzUyYFkYaq+3HAPu9
+3DBclVJLkmDLXTc6fIirQ3pVerNEljrLL/sG83VLtegqCJCl96i1oSABjKtpCJ09
+MPlEbd1kQPNN7VYnArGbh9MYqhbt4GhXAb0jOCpFhvUIG+MZ7ne9keOxW8iuFtV0
+7hv8KvjtZQsIIOcO5767vXcTkIpSOK8rwUIclCZBWF80E6u46L/tbJPD+1AA0jNk
+OybgVukzWJj87kajWtgnA7lMmnu1zhsMZMl/MCpL9IdAQ4xfXT4wRtditk77s0Ng
+Gqrd5xJPrSIVs8n+lgbZ1vSAepao96RNiZxfbl/mY5Sxn36TaAk9VxBnGOGa4j/P
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5.pem
deleted file mode 100644
index 6f28f19db3..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5.pem
+++ /dev/null
@@ -1,159 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXXXPbNnk
-MU3wxjjwCdA/Pj+lwkDk8WSxKGdOrcPMnFnrCdUnSqEES3K6/T7JRQyv6Y13Rt6w
-LAhrQI94UBcsAAQND4SOPyJUE3PonzcolJQ+EzkSB9qq6cxJokxTvxVTx2VN7bN1
-RJ7FrWovHu/vmKnwsOy3zv41U6KBfuf04QIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUIQy1AXZ207MqrCb8qqZP8tah
-b0swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJUd83zrSjxfaGwFdTCt
-BSI1mTeztSKFxIzrWeTxD3C0JHAxt1oM1AN8DQ/Ej8ja3rxhzsFQaWzdi3ixvnGr
-NbjLZH7EPWBPSSC2rTAcvLzVs2AuPsBkv7IKxg7HTJZtLbXDOIatWT+24OuKwTzE
-6cbcSe7zaz5qdojy0B72dLHC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 subCA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMY
-cGF0aExlbkNvbnN0cmFpbnQwIHN1YkNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQC9F8qrs0xS57Qn1kibsZC0kS6JQNJyITUgX+oGjw6Y9R6Jh9m5WVI7BwMI
-FsyIDhUK42ZsG9b6hMdQyp5NKHZbYOh53VhWzsEAk3veMZvsEyE6K2Ip6SZO1xDq
-ta7FYY4SF+2S3nw8tyJGqXqNEG4Aob2k+QW1L7UgcsPyrAE66QIDAQABo3wwejAf
-BgNVHSMEGDAWgBQhDLUBdnbTsyqsJvyqpk/y1qFvSzAdBgNVHQ4EFgQUjh+rRpwO
-S27n5VeIDCeT/ifW5xIwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZI
-AWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBADW1rIN2
-092d2UN+8PysNq18Cl0i7qsx9JbK7SUwreNTgbpyw9Uh7HFYzJwBW9ACs94rDhZo
-iqG0u0K4zLTijCS3ixy9sVKVha/+QTy6YxHFcjLmriX4bfiYUjXJPqmmZFExM3vO
-XMyum0wyXdEc+hbuAj1+6WBRec8clffFlRdv
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pathLenConstraint EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 subCA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25z
-dHJhaW50MCBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UE
-AxMuSW52YWxpZCBwYXRoTGVuQ29uc3RyYWludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0
-NTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsZWQnm88nqSXHt/QuMDuN373
-VZ5lU/JhChuvs6DBS9f9L9NFBKtTS7+iq0QmlWuc3qB1RDAUjwAF85QyXYlqujEL
-h22h7CWzEP26t43/megvHJFuT/wCuRBzbTm+fzKTlWI2v7u8YILgQcOxb9vbRKzc
-FpwTBBqlnT//Xqavj98CAwEAAaNrMGkwHwYDVR0jBBgwFoAUjh+rRpwOS27n5VeI
-DCeT/ifW5xIwHQYDVR0OBBYEFDsP7IkBHltfUoRf9AuD3aINP8pHMA4GA1UdDwEB
-/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQAD
-gYEAeuTAbPsAB5hEhGMN18ygmQ2hryyEu5o0OlbfiZbwgOSaNISSeYEUGr/+1uxV
-MHb6zNrauChrz4hTCgHMmhThDhfxHeIlh0bM/xKd1dOmlB9g/WMr59Uy8R6vvo/4
-HZC6bTc4Ukzj7n2maNkUNogPKghLEho3hlGx/dZoxOr59pI=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:21:0C:B5:01:76:76:D3:B3:2A:AC:26:FC:AA:A6:4F:F2:D6:A1:6F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:7b:a5:e5:64:8b:31:64:fa:9f:8f:a3:25:ab:8b:c9:c2:ba:
- cb:b9:e3:5f:3d:e9:b9:f4:f4:f4:d8:00:4c:cc:9e:5a:36:b3:
- d3:53:12:aa:d5:ba:ad:94:a5:21:16:c4:9c:ac:3d:3c:e3:2f:
- 53:69:97:6c:2e:e5:82:98:31:e8:47:f9:8d:dc:ab:e2:8d:ec:
- b9:3f:b2:61:20:ad:22:24:f6:ff:90:4a:14:92:38:0e:9b:80:
- 3f:1e:11:f2:d8:7b:fd:d4:0c:90:06:82:2c:48:f8:9e:7e:91:
- 55:0c:21:e8:dd:95:ac:90:c7:d7:02:af:84:f4:23:08:bb:da:
- cd:a2
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUIQy1AXZ207MqrCb8qqZP8tahb0swCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAVnul5WSLMWT6n4+jJauLycK6y7njXz3pufT09NgATMyeWjaz01MSqtW6
-rZSlIRbEnKw9POMvU2mXbC7lgpgx6Ef5jdyr4o3suT+yYSCtIiT2/5BKFJI4DpuA
-Px4R8th7/dQMkAaCLEj4nn6RVQwh6N2VrJDH1wKvhPQjCLvazaI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8E:1F:AB:46:9C:0E:4B:6E:E7:E5:57:88:0C:27:93:FE:27:D6:E7:12
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8b:2d:ce:68:13:85:60:64:90:ea:5e:1d:ad:93:65:9c:93:9e:
- a7:20:49:c9:bc:37:41:b6:05:bb:6e:b9:8e:c6:20:5b:d8:6b:
- a5:76:f7:d1:40:f0:73:d7:19:68:a4:b0:68:ad:63:f0:b1:b5:
- a0:52:b8:f6:ec:55:74:22:37:a5:2f:01:c0:af:a9:69:b8:54:
- e3:0a:3c:06:10:23:3c:0b:7b:0d:e8:6d:ad:9c:36:b3:d3:54:
- 9c:6f:4d:c2:e6:35:e0:6b:0b:3b:a8:10:3a:86:78:76:1d:17:
- 08:b6:ec:1e:da:17:a1:3c:1b:ed:a7:e3:41:cf:45:cd:d2:b3:
- b5:83
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25zdHJhaW50
-MCBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUjh+rRpwOS27n5VeIDCeT/ifW5xIwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAiy3OaBOFYGSQ6l4drZNlnJOepyBJybw3QbYFu265jsYgW9hrpXb3
-0UDwc9cZaKSwaK1j8LG1oFK49uxVdCI3pS8BwK+pabhU4wo8BhAjPAt7DehtrZw2
-s9NUnG9NwuY14GsLO6gQOoZ4dh0XCLbsHtoXoTwb7afjQc9FzdKztYM=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5EE.pem
new file mode 100644
index 0000000000..739d9ca02e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 0D DE 1F 6D 7B 18 6E DB 7A 45 1F 51 B6 34 BC C0 AB 06 CF 1C
+ friendlyName: Invalid pathLenConstraint Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pathLenConstraint EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 subCA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYcGF0aExl
+bkNvbnN0cmFpbnQwIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExNzA1BgNVBAMTLkludmFsaWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlm
+aWNhdGUgVGVzdDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPgxp+
+Hpglfzp9XX1K1glTgljSpG1M9dGpAlVk7K39GMVwkmnAtSBhQVBdG8GDNnr3kqCC
+J7LPOrNTDcRRkO4T7xdBL1RqmzOAuHHgJCiFt51qziQe//kZcmyIOwY8pgHN4Cy1
+q0BeWybbU4B9ybMiIVzFImOoOPUzkaADKic1iW1OBj5NpGCZ91qFyZx0Itk/iBC3
+v7CN2B8Qaho3hypDTCSRmVHiBB1kD/AKFU8UohIiHXsyGxbCg1bBLuKmWRTZ43y7
+L1m4qHBOg2i3do13YLss2oZoknsoOHOBa0YLrFXPPMQTNrOU6Im4IYiUU+Ge7+1g
+2a05ooIRBTS+QhSTAgMBAAGjazBpMB8GA1UdIwQYMBaAFBRiZxB90jfFcgbQ3n+1
+Fh3Ko3NeMB0GA1UdDgQWBBQPpyPBesQ9pYPwqgwp6+Jq4890gDAOBgNVHQ8BAf8E
+BAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IB
+AQB/58kEOCkIVV2FaRCkyOKRYGVC3KnDEBQjc6w3ZEm+f3vFHJyB8V63J+zf9MBi
+i2LvwwRTaUusfrrVteAcCYcoXOSHmRo82sY4vWJ0KBn0CDHuQw/WakD12geNfcjn
+yTu2LTe+0as0RhQ91krC5qJuzoN4FBVj8eKhVoD9YQFCzoD+Rq7WqabgUVVjowvL
+UzSm4adqK9x0pGxgwFwuBgdjuY6gKyAnLUpbC0E2mkLuuhQh0tAcYu9LIPpM/l+M
+6c2DlhKdQ/I3KvPxjCpaUxTVQ6iX8OyocQlszKp+LWb4NRBnHYmBpiO5vSC3aBPg
+Ga3ewshaPQBSsN7f29AEHSgh
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0D DE 1F 6D 7B 18 6E DB 7A 45 1F 51 B6 34 BC C0 AB 06 CF 1C
+ friendlyName: Invalid pathLenConstraint Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,AD8B97178BCB0120
+
+CWmHiiIThJdI8Ot9R8wU/LfTFZL6YYbu37opP6dAaC+LUrUFtZfwCZ/eP4arKCh4
++FsAL5A61YhoVhqW/nAm2I5W8+q0NjU552LANcVkpgTej0cqU4e/Gpgd9iArrI//
+RI6JeUyb367JARXbJUqtLVXfyEg7ijZrC63S6orqk//+CcZkrmcV25/rWp7AL3vZ
+z0qhEYV0r9jFqMP+u2/I75MATEYWz6VOFIxr+oieM7ulqkUgvMiUCWydXaU86YAc
+TclzwvjQNDXlSw+fGRWJ/qTu4cBy98jI6SHqdCB59o+DieNjEpK3Ywvz6ARjhFmX
+IJXoXCkl7Q3gqTrqrHLLKR0ed3V7x0Cfd98OxumzA8Cfvl/KhfORI5Pn5bWcK3Hz
+NXrjoagTAsmyBrejvLK3HVKqN1GdOzR+veRo/EYxuN2uEABmjj74Lfisrkq6gEeW
+/ZvireBbwWOScSlu/AV4N5gYCocSXU4lhffzpOTC7p9tcSxC8FFDooORrC9ccpZd
+4ucW75OMXaYym2mu+ImSkNS/SgIq/ZVnDT1k5V1WEF58WSqOvpuH5QguB5p7CeFw
+UQn/Yz8i+0bZG6gFp8Er2pfhGENX8Ca7KLwt7f7dw/33kb6MpBCWSc1NG4gEQ4zS
+dO1Ketts1nY6hmwls1aMU3fPmUOBQGvFzA5Di9Hjbqfbb2Llz7x7hRAurh8ci/sv
+pw1wNIb0Cjlw/3v5vTpvCMnK4rrPh/isfUKA/4NAW8TL1wF6ZXfVGqylIGx/DsG0
+AJ1pfPBv6W+CDWlbh2XDjGbuqTWDffM2sa+5D0ohTIaB5ZduFTJArqA+bb4/sLzF
+HVqOydvAdzNdEK8XaZJCqdZ2tfv1weZzrv33wyzwx7wz09kX6/2o5LWQ9r9mCwNR
+s5Lp8J/6sjV6zsUOJbiGIKba2rdvo7SPLygM+T75TCOSAUlNOGjSEDTVrIWqCSe7
+mXDZ5YPBnN/0GKG2UMMpgNobkZRSVeuSb5biNKa7jYFTCh4+gK4gPa4LUGvWXkLN
+u28IndKHZ81ZILg8WNgsgAMhjRc2sXWPsghXJ22xXGMPx+ILKnoLtzIiBEKLLvRU
+4oIuEuNIQYwBJo+DLWW2zxT2vngU7lipH/zTCT7ZTw3uI6TqHtu/PD42NJyeQBNC
+2zsX4jsRKlaEunbKs7uRgwxV/r+KjZHf9r6FCFGhvfnYn5IL9AHcB1xE6VR6qHd7
+9jiUMA60ATCocS7mGGLobf+bnPy7OQf4k8amqskyfmC3hP3q7WPWPEZEhR4wbUIJ
+sQtWjvTJc6D6G2414olgk9hhRi38rrCbWOEHbOW1cKKeWKPxoOUfa/5mozGAgBBh
+02xSMGupni6D5LNpYS2cWe0OBpWxcHCfH6KQU0bkmtgpMi6Q+nOoIcmxjOwCSUAk
+wF0g52PlQC5nEgpBxKa9KGYU/657NFUDC1ao4TVKnYwRkuYUT0QGLNVlpPxf6MpK
+SkDGGm+QM4GJnC7Ot0uI1+tjfARdtgXwzsPLLIP2dR4GO+m5ni/Sj8qObph0yW5p
+TMmJs6V7j+O9SHpPKJt0l8HDSuS10nW3Iu1k6E7KRNgA5iUWvme/p5IMwtxiDmK7
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6.pem
deleted file mode 100644
index c4fdb25d66..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6.pem
+++ /dev/null
@@ -1,160 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXXXPbNnk
-MU3wxjjwCdA/Pj+lwkDk8WSxKGdOrcPMnFnrCdUnSqEES3K6/T7JRQyv6Y13Rt6w
-LAhrQI94UBcsAAQND4SOPyJUE3PonzcolJQ+EzkSB9qq6cxJokxTvxVTx2VN7bN1
-RJ7FrWovHu/vmKnwsOy3zv41U6KBfuf04QIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUIQy1AXZ207MqrCb8qqZP8tah
-b0swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJUd83zrSjxfaGwFdTCt
-BSI1mTeztSKFxIzrWeTxD3C0JHAxt1oM1AN8DQ/Ej8ja3rxhzsFQaWzdi3ixvnGr
-NbjLZH7EPWBPSSC2rTAcvLzVs2AuPsBkv7IKxg7HTJZtLbXDOIatWT+24OuKwTzE
-6cbcSe7zaz5qdojy0B72dLHC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 subCA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMY
-cGF0aExlbkNvbnN0cmFpbnQwIHN1YkNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQC9F8qrs0xS57Qn1kibsZC0kS6JQNJyITUgX+oGjw6Y9R6Jh9m5WVI7BwMI
-FsyIDhUK42ZsG9b6hMdQyp5NKHZbYOh53VhWzsEAk3veMZvsEyE6K2Ip6SZO1xDq
-ta7FYY4SF+2S3nw8tyJGqXqNEG4Aob2k+QW1L7UgcsPyrAE66QIDAQABo3wwejAf
-BgNVHSMEGDAWgBQhDLUBdnbTsyqsJvyqpk/y1qFvSzAdBgNVHQ4EFgQUjh+rRpwO
-S27n5VeIDCeT/ifW5xIwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZI
-AWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBADW1rIN2
-092d2UN+8PysNq18Cl0i7qsx9JbK7SUwreNTgbpyw9Uh7HFYzJwBW9ACs94rDhZo
-iqG0u0K4zLTijCS3ixy9sVKVha/+QTy6YxHFcjLmriX4bfiYUjXJPqmmZFExM3vO
-XMyum0wyXdEc+hbuAj1+6WBRec8clffFlRdv
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pathLenConstraint EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 subCA
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25z
-dHJhaW50MCBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UE
-AxMuSW52YWxpZCBwYXRoTGVuQ29uc3RyYWludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0
-NjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqRnKex0cxpUb1ZFo+pXGEX8V
-39ndPC9BNFgD6o0pAqBpYd6zlYIIkQo+rpciQ1vHnizx6WP3ulT6unn4w5UhXCP7
-S9h+TKQt6KFwZNXaCASi/VTEgHt5XLrwqjrhCtIDamjCgEcR1L/VS6N+c+SARpEG
-aWQzmao86RmaEKBaI10CAwEAAaN8MHowHwYDVR0jBBgwFoAUjh+rRpwOS27n5VeI
-DCeT/ifW5xIwHQYDVR0OBBYEFCw8vCsEA7QX0lC4KFyI8IP18fO9MA4GA1UdDwEB
-/wQEAwIB9jAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
-/zANBgkqhkiG9w0BAQUFAAOBgQAUW32gQakGpEtbmPGP8WBo5wdAtIRXbRp/VGK0
-zZZzXsoEoME9XCHEOVvWO09Qcu1VP7hwwnaEqgYGWl1ooUih33plStn8ETtzLcQ6
-BhOfvj216EgmZINuLcozCAusomtXZJ9yRHO0uRveEebjOJYPWqqv3zD9NgKck6cm
-kq1Hlw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:21:0C:B5:01:76:76:D3:B3:2A:AC:26:FC:AA:A6:4F:F2:D6:A1:6F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:7b:a5:e5:64:8b:31:64:fa:9f:8f:a3:25:ab:8b:c9:c2:ba:
- cb:b9:e3:5f:3d:e9:b9:f4:f4:f4:d8:00:4c:cc:9e:5a:36:b3:
- d3:53:12:aa:d5:ba:ad:94:a5:21:16:c4:9c:ac:3d:3c:e3:2f:
- 53:69:97:6c:2e:e5:82:98:31:e8:47:f9:8d:dc:ab:e2:8d:ec:
- b9:3f:b2:61:20:ad:22:24:f6:ff:90:4a:14:92:38:0e:9b:80:
- 3f:1e:11:f2:d8:7b:fd:d4:0c:90:06:82:2c:48:f8:9e:7e:91:
- 55:0c:21:e8:dd:95:ac:90:c7:d7:02:af:84:f4:23:08:bb:da:
- cd:a2
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUIQy1AXZ207MqrCb8qqZP8tahb0swCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAVnul5WSLMWT6n4+jJauLycK6y7njXz3pufT09NgATMyeWjaz01MSqtW6
-rZSlIRbEnKw9POMvU2mXbC7lgpgx6Ef5jdyr4o3suT+yYSCtIiT2/5BKFJI4DpuA
-Px4R8th7/dQMkAaCLEj4nn6RVQwh6N2VrJDH1wKvhPQjCLvazaI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8E:1F:AB:46:9C:0E:4B:6E:E7:E5:57:88:0C:27:93:FE:27:D6:E7:12
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8b:2d:ce:68:13:85:60:64:90:ea:5e:1d:ad:93:65:9c:93:9e:
- a7:20:49:c9:bc:37:41:b6:05:bb:6e:b9:8e:c6:20:5b:d8:6b:
- a5:76:f7:d1:40:f0:73:d7:19:68:a4:b0:68:ad:63:f0:b1:b5:
- a0:52:b8:f6:ec:55:74:22:37:a5:2f:01:c0:af:a9:69:b8:54:
- e3:0a:3c:06:10:23:3c:0b:7b:0d:e8:6d:ad:9c:36:b3:d3:54:
- 9c:6f:4d:c2:e6:35:e0:6b:0b:3b:a8:10:3a:86:78:76:1d:17:
- 08:b6:ec:1e:da:17:a1:3c:1b:ed:a7:e3:41:cf:45:cd:d2:b3:
- b5:83
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25zdHJhaW50
-MCBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUjh+rRpwOS27n5VeIDCeT/ifW5xIwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAiy3OaBOFYGSQ6l4drZNlnJOepyBJybw3QbYFu265jsYgW9hrpXb3
-0UDwc9cZaKSwaK1j8LG1oFK49uxVdCI3pS8BwK+pabhU4wo8BhAjPAt7DehtrZw2
-s9NUnG9NwuY14GsLO6gQOoZ4dh0XCLbsHtoXoTwb7afjQc9FzdKztYM=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6EE.pem
new file mode 100644
index 0000000000..4d8dd52863
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: BC 5A 37 7B 3E BE BD 85 D6 14 A6 8F B1 6C 24 04 8A 7D E4 08
+ friendlyName: Invalid pathLenConstraint Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pathLenConstraint EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 subCA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIBAjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYcGF0aExl
+bkNvbnN0cmFpbnQwIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowZzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExNzA1BgNVBAMTLkludmFsaWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlm
+aWNhdGUgVGVzdDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGDA3e
+m7k1Do5rvpYClVMdIDcvCU2SHLNNPewpFXamFNP7kZlxryeHmk+0HSg4iwu1Xtnd
+t3FQwV3EtxGfZGTtrQse5dozWQbtLh3sPvI9nEFOj6TuktbSkT01Bnb+HXxA13od
+QKj+Y2jJK8CfbzIQHh2JFfHY+rIjFL7hTgLT/IR8juMmaQxLTOtgBv7E07Vth4jA
+ry3Cs99c4F/NSIkLS8jphIbLXsmDHNeW4eqMl1DSRXJjygW48rdnmRLv88mp2HMI
+MNKoyiAyRogziAWD5bVcpnR2aSUgn1yt/hBRxjcKXOMfEDQEJIcMdgvq1oPmr53g
+TfwzCsWgTm0LV/KjAgMBAAGjfDB6MB8GA1UdIwQYMBaAFBRiZxB90jfFcgbQ3n+1
+Fh3Ko3NeMB0GA1UdDgQWBBT9iekRTg+hv4S/pIHUQuasw7wnATAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAfYw
+DQYJKoZIhvcNAQELBQADggEBAIiEa74JBZwpz1Y1MWdNpLE6YVBLeBfNDYLBLXgt
+t7pbeclKlY/28YLMWpACQysthnYfGOdXHOpHusbVbQBh1f1BiKHA8BfwqCC3oQu6
+9bugMmGSab2/UeNylWiIO4C3q2LCuFjNfE04V1Xl3XVMfFbMEPOqFkOhh4U0PuAe
+cYfCq23PRNyRtcYAWkQ0uPujg//EAyq5CVJKn2SZ4274stQVDeVHniaS4vYe+PJN
+lkqAicrYITjOlFmU7UerAN2F7rRcFWbuEF1xz4/vZItbidCdFl3I302/a94nQmzF
+BtoYYNVZPypEd0G2a8s47+mgAqG5leVPp7+GZb9igx2x7ig=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: BC 5A 37 7B 3E BE BD 85 D6 14 A6 8F B1 6C 24 04 8A 7D E4 08
+ friendlyName: Invalid pathLenConstraint Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,801664664B826479
+
+opViAlS7IYK44zekgL+iExW/Z6hZoZNylw89IwApslwn5EoKViqcLUu15ZaaWyk0
+pvhWm4yQVM7AL/GRpGADjTwZnIvmKvInsVTWXwnW2SVMpCUrtGjXonN3ijInwd3s
+v8vW6eeeg5jGTN/pS7OAVdQ2a63fIZD3eKPG21aWsPp7MhodpVbtW3tzlJsj/e0r
+VqiQ/O3J9wUij+nxolRhBRk39WvaotaYCOw0nNQuTf3/KEbunDPUgyJtorHiFZLN
+h8l7owjD/71KodEuYf37f2nosb1FphAlRsVKzNGbv4cUU0OuxjRhjNuZGxTeHk+r
+4kVO3PMhggubShSz53RSWtYuD9g+0ohBqHdvg2FMLyaRpjkPNN/vjmejuowGPc3F
+l+h4CdayR3MrHMK8Bjoizj3Xoz/FuyqxbyVnU/6td1m5GAFK3wfKju2ylZCwx+df
+pB4c1RJH79O4G6B3fUC+Z2uJ/7fWs0EbNoVgQFYf1FXqjW0IWyS15RqDDdvBKLFp
+a1yai9kCwd+zvHAwpIjtOfBF6w6QsneCKxP/AZzW44wQWh9b05cUNnU8b/07cO7b
+KM6KFOhUF6Zzw5O8BZtjzGSpvWB3w/aXCyrTqmaoc0zR+SqHsN+xuR3gKxVzgDpt
+AoP0/f6kLP6ig/roAWfKVDJEv/Hki6cxpWjEE6rYs2gaHdTWGdVamRaf0OvDF1UY
+U0AzN1AwEW7fSsOx4Ulu8PyiHIHg+EPkb61JgrUzvA8HKAvPyq4U+CettPUZLyzf
+W4ZSqRovjHSgGFnTkqhV5f8RLMveGeyP+4LM542WMSHkKmR7o/MiMOw/hsqpWiFI
+KeJYEiGkka5hh54K9vtkyTpQeNjv2IkXmreJUyZ54ylCCOdQVxhtINfZnhqDZNOu
+XQ9scCs0/Nh5dHDBC7lpFTda+0vCBdYljEE1tXCpHAr75jKONelW/EtijXuWw/Ji
+/57Je0zo+CJ5uxc97fEztbVj/Ie7gudXL2odo1I6FCDiHETdsWUdqxR3Q3qTgLKP
+vWE8hHR9xXRThAUh9wQpe8tHENs9rpuhocJUHxZu1zmXlFMPqpN2ht9w1Hlip0it
+PqwZN05TAa/fMSgkA6ENmAVU3vDLryTHtbyiwRaJ/Kx4u4Vy8qa20Ot/PI4P2feA
+9Y3nEKfrOMf0zwcd6rj6B+5SjHZMOP0F9fCvofmXsTYxF6b7y3PiesB7bPuJSixB
+k2Zbcgiyf9GJFpwG5o/TfQXWJ9f5gEJRBkSlYAgMywRTKWJtzSdddbNby+d6tgRt
+g2iHFMHzmjmcXzNOqIlXUl2QDKtXvVs+e5UNTXu+pXS62WW82gZoxG3Kc5ujlFvS
+yQnt3ArJA7KZIjHaO4jYKh4lfIvWxhvioHYb1x/DAfP+47PwXoAk0fn5NPVtVG+k
+hF4xakmkPBts6QT1GRWOg4gIXTB77i82c48zYLCozMbMsGfXpmidMprQhttkWobf
+A7EfK8NhOIl9mfnvo1ZzPWLLBBHQXPBsehpLaLwn2uiNKHSa4DotclkhRkfQQpbo
+JtXb+kk/KgBB5ZcHwLE5Tpn+KukxV7+tHesdu2MFiNlPZ9wzw+nFOA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9.pem
deleted file mode 100644
index 8b61201901..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9.pem
+++ /dev/null
@@ -1,210 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQ2IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbfycd4Ehd
-RlHiRJp0MMk0H94GHYCYxpVEzfiC5V9w2M0NWJotHuHxdTvH02XZquFdQptZI0qZ
-AGeBgE3+FBJAGOK0ZxYJgSyscFWBTLGzFZu2Y09siuEwlr5W4z6iByJpFYsEK0JS
-icx7LPYOYyHmFpmDSdcUXwV59VWlaQn5HQIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnY+0pLeirrl2tR7LH2QWpXoO
-hUowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKJlZqSQSA4tpA42dNOs
-k5r0RU2BrRu2bPXhSEZHD0o46NJlNTNTfCAus4HtZ6GE1AvTIy3smHPGb1O4jth2
-9hYXVqNHIEIlejhxgSE0trBBT5L5vodq5Pu5qoTWPZ2Uu8pdqRvdmypKr7gI5inp
-Cu6s2eBv0+DeibQTg73sQuTj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA0
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50NiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQ2IHN1YkNBMDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAt36UX+gq562CFiw9L16IZ/AjJhU0BB9ji/77uw3AfvBGggmikeDq79BD
-yzBFrHys/L5UeXepakX1v+XvlxFjwvc8c226jf6uKEop5KJZDI8aV4byQvc1C8Ol
-MdgZ4pd6ofTl28r1VDkdDt94c7+Gl0CqBo6LawwGmNfSHUWqf6UCAwEAAaN/MH0w
-HwYDVR0jBBgwFoAUnY+0pLeirrl2tR7LH2QWpXoOhUowHQYDVR0OBBYEFAJIeLnM
-AVExdH85KjfCRJN+mGmAMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQUFAAOBgQCm
-Qa7i6335O64eyxJjXl3U2Bw5wN3JaK9t7f4dJAxfOlcblWbbes+Gk12UCYtxTZDj
-oZ70F4IoGU7JQt5CcdB2yQtctPK+X7A3/Vsxjknm11nCn4IhcU7LDkEiSovBGLR0
-KV3NAqQQhr1WQoY1Uf3Ncpl7b+SaZscZ3r35UJo4iw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA00
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA0
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJDQTAwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBR
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNV
-BAMTHXBhdGhMZW5Db25zdHJhaW50NiBzdWJzdWJDQTAwMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQC3rH58cOqP9U5iyQflKaVyYw+1LMhr3jDW9/Q3aedlH/TY
-iLmT71FUjHaJMWOCO6sAEYMphrRdIUy82rai3iJgrNtJ21uIFOlmjgwgl9amHX8B
-yT+qgiwLs8kzE6NgPYHgLgbKEIqgZ+AZplCt60tCbeGKLR/WtXrxAIgqU+ar1wID
-AQABo38wfTAfBgNVHSMEGDAWgBQCSHi5zAFRMXR/OSo3wkSTfphpgDAdBgNVHQ4E
-FgQUauYRxUFtrRo+gtywXa3yGfFQzgswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEB
-BQUAA4GBADnBidpEzasWbrLankXCoCaeizozu2dGAMMWpbs02cplC/vIlcr0myWK
-noFSuxUuQa7sMxp72p5r2ziJp5pk1gT2KX/kgOYlQqgbJ4UmARGP7er+zIPulXib
-suMShSCGO1xC+fXppdhPy+YQq8a7Mzi7XKqP5su+aTWw/B3a8ys9
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pathLenConstraint EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA00
------BEGIN CERTIFICATE-----
-MIIClDCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJDQTAwMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowYjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTcw
-NQYDVQQDEy5JbnZhbGlkIHBhdGhMZW5Db25zdHJhaW50IEVFIENlcnRpZmljYXRl
-IFRlc3Q5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxOmk5mQAdlYGqq0qW
-czN6fmOoFbl/XRAhBs0fzOYu7b06yC5QFIdW3963nkjYahDg/x0F2buDbOSNRvG9
-DPmercWLmz3Sar1KgPxqTCQ5XiTZ0t+20u/oYEM+0anic4RKiQNtuF9Ro4U83wdW
-w8ljyEFY255kWP0HVLh8REn+dQIDAQABo2swaTAfBgNVHSMEGDAWgBRq5hHFQW2t
-Gj6C3LBdrfIZ8VDOCzAdBgNVHQ4EFgQU1Bk+MIR/ztV37I8S8/91EZ2nlYUwDgYD
-VR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0B
-AQUFAAOBgQCWb/JZpNi+GTLgqlUUktJuhFQzGNKwQLHtea991BN5v6GnXYtgGZhJ
-T9plUX42APML+l+b1J6DzyJYlrIw6EXf/1ZtBf0YzmNbJ7robzIjx0+3/EHFeOZ2
-B7X0aaJ6+tt/sgGcLueuSG2C/6j8cnWbKJpAzzocI8hklIO+EWdRWw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:8F:B4:A4:B7:A2:AE:B9:76:B5:1E:CB:1F:64:16:A5:7A:0E:85:4A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0d:f1:3d:54:c8:22:83:d4:1c:69:d2:12:e3:82:09:7e:b6:c0:
- af:f4:41:9b:51:c5:04:d4:c5:ca:51:73:5c:c5:14:c5:d6:d0:
- 11:6c:40:ce:49:e7:80:49:a9:35:94:84:b5:bb:52:37:62:c3:
- 5e:0e:18:48:57:44:b1:cd:97:a2:44:ef:9f:75:44:16:9e:58:
- ff:db:7f:18:8e:d5:07:fc:01:64:17:c3:00:79:4d:02:af:dd:
- 08:88:37:03:be:cc:80:7a:cb:fd:e7:5c:53:03:b1:f2:17:16:
- 1a:14:25:f4:ea:50:8c:14:ff:58:e9:2f:fe:e4:75:d9:67:78:
- fa:7a
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-NiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUnY+0pLeirrl2tR7LH2QWpXoOhUowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEADfE9VMgig9QcadIS44IJfrbAr/RBm1HFBNTFylFzXMUUxdbQEWxAzknn
-gEmpNZSEtbtSN2LDXg4YSFdEsc2XokTvn3VEFp5Y/9t/GI7VB/wBZBfDAHlNAq/d
-CIg3A77MgHrL/edcUwOx8hcWGhQl9OpQjBT/WOkv/uR12Wd4+no=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subCA0
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:02:48:78:B9:CC:01:51:31:74:7F:39:2A:37:C2:44:93:7E:98:69:80
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 44:34:f6:c5:c0:16:f7:24:42:33:a8:e4:ca:74:71:94:76:93:
- e7:4b:7c:a3:8b:ac:ae:11:ab:46:94:f6:0d:88:b6:e0:96:1f:
- ab:04:6a:92:b7:6d:4b:aa:6a:b0:13:58:58:a7:7e:06:de:c1:
- 26:d4:09:e0:7b:a9:e4:dd:73:da:b0:cc:a0:61:ab:c4:c7:cb:
- c2:e1:66:f9:f2:2a:c2:c9:59:5f:05:c6:74:f8:bd:bb:92:24:
- 77:12:34:23:7d:95:99:bf:35:e0:6f:cf:2a:b6:19:29:9e:59:
- d2:0b:2f:07:44:25:66:6a:e9:5a:ed:7f:99:33:b5:3e:65:69:
- 57:95
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJDQTAXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFAJIeLnMAVExdH85KjfCRJN+mGmAMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAEQ09sXAFvckQjOo5Mp0cZR2k+dLfKOLrK4Rq0aU9g2ItuCWH6sE
-apK3bUuqarATWFinfgbewSbUCeB7qeTdc9qwzKBhq8THy8LhZvnyKsLJWV8FxnT4
-vbuSJHcSNCN9lZm/NeBvzyq2GSmeWdILLwdEJWZq6Vrtf5kztT5laVeV
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA00
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6A:E6:11:C5:41:6D:AD:1A:3E:82:DC:B0:5D:AD:F2:19:F1:50:CE:0B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 42:5b:18:71:be:d6:f0:b4:80:f6:33:3c:cd:99:0d:26:f3:90:
- 70:42:44:f8:f9:61:72:1c:b3:91:02:0a:14:55:67:d0:1b:23:
- 06:f0:90:76:49:c6:82:23:70:da:3a:15:95:90:80:aa:8f:0e:
- fb:4e:5b:9b:66:38:21:14:15:c1:65:71:1d:e5:b6:90:ae:b2:
- 7a:73:84:9a:1d:3c:f2:2f:65:0a:b4:7f:52:90:a1:1d:37:a6:
- 24:a8:7f:5e:72:e5:1a:8b:89:31:ac:dc:0a:3a:d2:15:7f:f5:
- 97:f3:1a:82:d6:fd:74:b5:92:0f:d5:d3:a5:74:1d:a3:7f:62:
- 1b:c4
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJDQTAwFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBRq5hHFQW2tGj6C3LBdrfIZ8VDOCzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQBCWxhxvtbwtID2MzzNmQ0m85BwQkT4+WFyHLORAgoUVWfQ
-GyMG8JB2ScaCI3DaOhWVkICqjw77TlubZjghFBXBZXEd5baQrrJ6c4SaHTzyL2UK
-tH9SkKEdN6YkqH9ecuUai4kxrNwKOtIVf/WX8xqC1v10tZIP1dOldB2jf2IbxA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9EE.pem
new file mode 100644
index 0000000000..6588452f7b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidpathLenConstraintTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 55 2B 38 60 25 2F FD 5B 4C CC D5 AB 28 A9 1F 90 7D 80 0E 2B
+ friendlyName: Invalid pathLenConstraint Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pathLenConstraint EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA00
+-----BEGIN CERTIFICATE-----
+MIIDozCCAougAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YkNBMDAwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjBnMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTE3MDUGA1UEAxMuSW52YWxpZCBwYXRoTGVuQ29uc3RyYWludCBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANLGB2+a1z3R1ROq3nfJr1wwDsswYFEnvsa/Wr3TmkHChPZaiqssCUawxeeCR1uu
+FS9X+Lt3CTROXKQ0G3GujkpNxTP+tLTjzSIRUOaxcyN8AipiKL3wwBGm36Mvy5Nh
+PGCOuQnvqpysvKtV4FOt+zlFZRpYnFR/Qom+v26vwECAPKmP86Uxs7o0umgUJtDd
+Sk5ihTMqD/aZ+ig+dCze8Ornxe3fS6NrnnvLWKSB9APN8CI3q2DWaiN5HtSU7la3
+m39Jzu/mPD2tEwrqJr9GZlj1Wgy3a0+zbHjiLYVQmXVcyfsH7LrQzXGuEMc1WKCo
+5KZMqejlnBPgeVTs1fNFa70CAwEAAaNrMGkwHwYDVR0jBBgwFoAUurniiPfUWSWK
+4ynfT6AGON1xdIIwHQYDVR0OBBYEFHkjxiIM9f+ESDif+mKJj9uEIvlSMA4GA1Ud
+DwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEL
+BQADggEBAFDUrcx9Aq6taCu2kipVTgU4GQ9gJ/lEwCW6LP7p+D5iRJZsmXpXHIw3
+YZDBgxGXJXHzUFzeBbySLu/lQfabnq0XcLViWhgi++Ikqr8MPxoqbUvQH412kdbe
+b2Rf90fk3Mu31VrIBLbEp6U/h0QWWWPKJGcY+Z1jgdA14m3b1LPK7/p1kfT1yb3/
+cTtmliG7wzcWsecmK5xz0irZrywun2yWQhcps5g+lhMcMghogHKEmN0XnFqgL7ta
+beXQ4GEHuyyRoRuXrh2QMyDkFgr+CyqCbEQO3UKbvTQD1Q+jPkYpApi58UXxaKfa
+JTfJg896LS1hDrZG1R2AOrhUFidhPXw=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 55 2B 38 60 25 2F FD 5B 4C CC D5 AB 28 A9 1F 90 7D 80 0E 2B
+ friendlyName: Invalid pathLenConstraint Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6432CA2B85F30C35
+
+Mrp7JsvXVS28CIPmVV/xryGbHQaaYvpQD5Zir72ldbioSc05c1sI9lr9wADmtfUI
+clvXPryK4pDNdZnZD+3yhDotv1NYAYBOk5nVsDgzCPu10XSPKs1DmA5OHFOF6AP8
+r2rlSm/boRxnhVG1GupYpYRpPjDRU6ewL4ionfr1E6h5Dy3v+bBFmxynqmp8pbWI
+60YeRDYddcMurKQdfUul9uDnecFxemlJzSSWMX66gURg+T5iafEhG4mwM6mM381K
+TMnhKDqEaVggI61vHerdNc0L0P+tJ4fPsbu+2rIYYgHi8Qd0LKbRIOiGFuA51RrM
+MDSLi8ESPP380fhzm/YQ9BruKA+S8ZkWLnRH8Pgz/3pfIAbMWeetCBgoONJlwu/j
+8Rebetn+d44v/1Mw2Y2FMYjLyjjRrn5kJ669iswBqpo1yGW9TH99fIpHnK8UY/yj
+0amWiBEoLoRZ1/y3ipmnc8nXBHZS9Pz6Z1cfWVftZ5roSivqx5+BF1ijvyBoxGho
+wVZVyq2FkNEJ+27RdY4RyVUz+mhEIlHCelqd1MH61espsxKjX91QSjLPmqUIQTD9
+bemzzG/gK9yD5iXl8Pdo7tGddKSDCxTYMpo3Zb1/4aOw5NWrh4g22Pv4CAojuhx9
+7NIh09xB2XrNg1WrTU6t2uulh36rQCUysc5i8TrhmY0f/KcIKaUFI098fzM6WmjW
+x7K/qBuUmccvcCLPw+qc608Gh9IYLhuZXo1GV0tll506+mycqW4VWU9D7IHrUIz0
+nrp6Qx/zB1UzjFsSZkk10T5BshfsGbgWpsXNM01QsXPQV3VXyrrpvFfCrO10BDpL
+qxAxtLvvhIR7un50IhxlpYJuk2LS8W9yhdkk3WjIMWtKEHICOKl8suGMhQn/wtSo
+f+7S2BSkPc5hTBc/Ikijqxbz63RzF94D7mMHFiVQGYwXXS2pEiLmyeK7DRPoZYCA
+LzNOXt9j/fXU91ZVnrSIFrwk/QNklnIPN0MO8wAFZWEDr321GFghT1izNulkyLJT
+aaIwaFj+ZDXZJS8iu+SAcjggJPNYdobAhhj1pfq7MVoUuSSaTaSdZQtoXRgA3N58
+fjtV4g7evqF78GVfuNC/mI3bW+lzlkB8lunjpqLx/GzWIzugVWa4ypi9AAgl12BJ
+MYXMWyNGYY1xslYrxDwOs3Aqhk33JMS3lEKP3DpaytPAabPDjJlfEOpjb+WPZBgP
+OL3oDdxfrZqDf7vzDkVknAWuk1kvgEn5fgj0uYVbVLeYZ6KUtDbtejskB5KQ+UUG
+VTSvr8md2DZD/4aZfVLABCIuACgNuNjGOWiUSKH7nHrXAqGtMsffOw9JAUJty3V9
+djI3JnyIYeguktydV/VTyHDhDfG9eXv62ifx4QmRuDTVOW8WJmMN+zoFiHu5kdSR
+UaS8oknmc/7ltHdf2wjMaNdsLJKBC9MPBxxzDNWc+aXq/zaO/Ka5HqGXWsJlHDQi
+TJ0jelMY/4jCh03wUbt2/JHo9+SzDEGmaHwdlgon/vJ9SCzNZ+IL6limnAA5nPHr
+p3IP5Xu1iJXD70rJbIZdZCN/2iibX5mrTx9tcUT1ArqFGVPtaSBzvy59BI6oWHZH
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12.pem
deleted file mode 100644
index 2f78fa8423..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pre2000 CRL nextUpdate CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfzCCAeigAwIBAgIBDzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcHJlMjAwMCBD
-UkwgbmV4dFVwZGF0ZSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAlMZQ
-vRTxm+l3FRtimp7Exo1NygL3qQsF8cpvpQMmM4S+vWWIQcZPBAGfTi4eW4ubaKOh
-UqzxbVtY6R97mA0Ng6GHXIclN5ozja/xJdqdIOz9CsB38IvgyXTTQv3kF7nch9Ir
-xAN+7Bf5oWOdRbN6Y+i5iDHb3j7f3r8EFtXX+EcCAwEAAaN8MHowHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFL16NgTVXQmVv12uq+yk
-UWCNJq9WMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQB9/jemk5S7bYWeZC4Y
-bzwXzQEjfRTlrJ5xIj/cOAWG+BvCzeSkaoi3hw+Ltt/T571j6NoAQu84Mx/Jwbt/
-zNBwu4iMmeaeU5GM+9oTVU8JTOog2ZPGR2Yn1luPQv5LwbPE+mysPaEsM/mTl5cM
-OMB0yUOD5/jo/76IJhN/M48tvw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pre2000 CRL nextUpdate EE Certificate Test12
-issuer=/C=US/O=Test Certificates/CN=pre2000 CRL nextUpdate CA
------BEGIN CERTIFICATE-----
-MIICljCCAf+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXByZTIwMDAgQ1JM
-IG5leHRVcGRhdGUgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBo
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPTA7BgNV
-BAMTNEludmFsaWQgcHJlMjAwMCBDUkwgbmV4dFVwZGF0ZSBFRSBDZXJ0aWZpY2F0
-ZSBUZXN0MTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANBocZCE1yNSbZiU
-rcH9R8bB0cZERzxNK6g7d9v0tUsmbo0Gk2JgSaKG9vBnOpxJhJ3hhSxNmpGpp61Q
-QlGo9louMi1AzibkrqOllW+FgXQImr89cxEicI9taSS9QRSIIKPW3kF4EhuZp4vR
-SksCSxXsghAsSWeDqx9CQG772BiRAgMBAAGjazBpMB8GA1UdIwQYMBaAFL16NgTV
-XQmVv12uq+ykUWCNJq9WMB0GA1UdDgQWBBRtKwIpcpf5JIosL9wN9VKKwAiAWzAO
-BgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3
-DQEBBQUAA4GBAIk3Dg2P1RArTBrVZ/kPeRAld8oPoTdmer7YAloo1Zavmcm5Fcvn
-WmJfONAye0p7jsYSkv6HMK3DL2b4/KEnEDB/Ok9CLOdvoTtptk04CiSXOcQcP9uK
-NY3uZgZoTo2O/lBe6KwA2apKitWtaHf/2Ig9AGhPvMBWtiDmgvpWE4T7
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pre2000 CRL nextUpdate CA
- Last Update: Jan 1 12:01:00 1998 GMT
- Next Update: Jan 1 12:01:00 1999 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:BD:7A:36:04:D5:5D:09:95:BF:5D:AE:AB:EC:A4:51:60:8D:26:AF:56
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 3f:41:4b:5b:b5:47:1a:77:7e:2a:87:63:65:06:9e:f7:18:96:
- 8c:41:41:e6:9a:4f:45:91:ed:dd:8c:b1:d6:1f:e3:41:71:70:
- ed:98:51:35:e2:24:bb:cd:26:8a:c9:43:f1:4c:58:43:2a:31:
- 5e:94:a5:5e:09:93:dd:a0:f9:d0:1a:c7:fd:d6:8b:4d:4c:6f:
- 3c:d7:43:6b:b9:87:8d:c0:fd:f6:5a:a7:4b:f0:74:01:23:fc:
- 61:24:fb:3d:32:5e:f7:fd:86:de:52:3f:09:2e:b2:f9:b5:99:
- a2:2d:96:83:2e:b9:a9:99:58:fa:c0:e5:5b:8b:15:fc:0e:d0:
- 53:32
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXByZTIwMDAgQ1JMIG5leHRV
-cGRhdGUgQ0EXDTk4MDEwMTEyMDEwMFoXDTk5MDEwMTEyMDEwMFqgLzAtMB8GA1Ud
-IwQYMBaAFL16NgTVXQmVv12uq+ykUWCNJq9WMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAD9BS1u1Rxp3fiqHY2UGnvcYloxBQeaaT0WR7d2MsdYf40FxcO2Y
-UTXiJLvNJorJQ/FMWEMqMV6UpV4Jk92g+dAax/3Wi01MbzzXQ2u5h43A/fZap0vw
-dAEj/GEk+z0yXvf9ht5SPwkusvm1maItloMuuamZWPrA5VuLFfwO0FMy
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12EE.pem
new file mode 100644
index 0000000000..29dac9a077
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000CRLnextUpdateTest12EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 8E 8B B7 54 59 56 74 8C 94 BD BC EF 08 63 B2 EB C3 32 D1 25
+ friendlyName: Invalid pre2000 CRL nextUpdate Test12 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pre2000 CRL nextUpdate EE Certificate Test12
+issuer=/C=US/O=Test Certificates 2011/CN=pre2000 CRL nextUpdate CA
+-----BEGIN CERTIFICATE-----
+MIIDpTCCAo2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcHJlMjAw
+MCBDUkwgbmV4dFVwZGF0ZSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMG0xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMT0wOwYDVQQDEzRJbnZhbGlkIHByZTIwMDAgQ1JMIG5leHRVcGRhdGUgRUUg
+Q2VydGlmaWNhdGUgVGVzdDEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAyYIKZ04nGTfv/cQgZYw9cORsRCow8lt4l2dL1MVPp50YW8e2yqrhPsjPSJUu
+7cYDAPjXJuBo4qSs1tIpRPU2nafDBsCNUFLRX7lpYXCMwj9yh+70SMmqlNION6Rd
+wLpfGWAH1I/TJ1P+dFctMBp4LOOMZ6nBTpfUfFN3heMmRYGj0XWn4uCBMzMMb0Vo
+HYCinO85FZ4lDAOhrz9hTgsR8GlzipckTmp8/xaTDCtRy4BJXz7gq1hTbGWJbgQZ
+eM5BKetvQsQLMnD5BUtv19lnuLpwt9OPggLQOG/oaMBpTjeri1pjh+jwQwJ7TW2z
+xgIw+ACnsLtZLNG2zNIbkX2u1QIDAQABo2swaTAfBgNVHSMEGDAWgBQeqEecYYBo
+KLFCmimM5igDKZIDzDAdBgNVHQ4EFgQUKCyOURD8t5yIKmvuLGs/+HtieYQwDgYD
+VR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0B
+AQsFAAOCAQEApdQg4JH6mV/wuIWWYaW5mPskzRye1Y4o2fpaX04xvMMnOjhEEOkY
+WmuwByb2dnjP1jYmqUxJJGEzDGuX3GEZuPmM9V2jicHv/SCn30vpQjA5dSo59Y3k
+7VOqInWTvmVX4YA8KO621BUZ0/5bZpjtXdqVLRDO/WEUIeS5YzMufnJTbhjb9Nov
+kmNOAkhOfyN0bTaInfm0p0RLfMOB0Remb+t3HUcQUNQh6dGDo1Q2EK8HnFvGMD7K
+3jXEyeiXeP1h7S+FX0MNmDdjlE9IQV7fbOJEdS/00fTxn2Z8aEGjklWusNfmd5Bu
+IuhmPZjMRN1yOspse7lJDPtVGCRpYlTruw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8E 8B B7 54 59 56 74 8C 94 BD BC EF 08 63 B2 EB C3 32 D1 25
+ friendlyName: Invalid pre2000 CRL nextUpdate Test12 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CAD3CE9838B0CA00
+
+pehCDyTDvbCXH3cQ1BMx4e7zOorF53pZeabAY9jzVzj++tnGRldIwbxecWmz/aLD
+XxLdRr68T0MUho+dcWIiA5OgXbYawu0HUt306xopcFooaXLcudFHBnpWHy7hHBGW
+Ayq63RkY7WpSVNY7vANMZCOy+CjcL8ruQQlvrn70gRlbsIsC3aDTFtk/9ClUFDF8
+HcUC49ie+oJblqL/PcgdUjid3nxLPfX2QWTdmCxCMdDX5SUNoqbnyrWsEdGh2qr2
+mqtJTOTTFou+qIffCiKFWqVIQIU8AcS06cPFXB7hDKynHNrEiAVruh3w8fsb3ks4
+RtWyHiT9aqZW7siubZO3MAviRobczeVEP5V1li6BTWXQI/QK2H25Fh8A6IwsMWkP
+TceuS8MAcwy1y8oSzEkpL7RtnFyDCctY4AygCUYcJsShIx3yoCxMqwEHJUcw02YM
+QqhZsAoIxQEuGHAhFEbFzpbfBeQLE4rL5qx22WQtbvldJwtwsAGZggrLJD2SJg6+
+iAOf4RYoFnNMyeh3j7ajvRr3CUIpTRwNhdkKcTlwNtZSm6V0H7CGtbkJsFcaKF1/
+TEnx2hIT0YUylK4z1zmgtWJOH0iJOXgEbEHdENOckak2MnXSK+x1KNBcyg2sRi0x
+aAMSZKWFNNXkjd4MUoCaqNUgaEeAvgzGGWSvcKaPWAypRxrxwVuWI5AgDbPiKLdm
+jGg+YNaWZiPMuJztgFOHTdI45pSxJghS1NioQpIZPbYtIxPstd7wMgPdPVMo5wLI
+GfMAxDHYBui+6CjYPl7/OCFfGFIdL/50zoM70LL1i07eOXMMuzWmexy0suUBzkrr
+qnLP9eG+EJzgsQdb3/1MtpNHUcRnHIkV7AcQiY1kXd2VKdjFMhqPvlc9vsT8dI+Y
+M8++Pzl7teyjAO+RMmtK/rt+rlmaFJxLc/qYIz/1aFI/OJ1neZfq2rQ7+srfB0Fa
+bcFRgHKcH2nRDOOwZn7Ov6phu0IdZxBDOtMLiETD1mUL8242vfGkwRdrvg8RfwSh
+0MtRGojyejeGKYzzojNxejex7tY+VC7OOZLmGj5GKCUQpsgsE60WaV14AHZ5K9Bv
+pRRul87VRoOIk+GUnK3u+taFu+6DyGiGemU4OUN2LO7KMgxdg1+Ib6Xjl+wKjCog
+5FzVs65TnPStwks7xR4vwr/ZfZ8xIRqoUGkpuXeGORwZu5OVtN2V9TejoXRO43Ip
+8BWteG8K5XHBmV8p7dkFrlM/p4kvYn3VEAibQpMJC6M7CkBhHGFf2qDuVY0xHxwL
+RBB56OkMb7vAnTzjuPgWPGOkBt9i5tS1DZdE8tcG/mtDi9rLuoER7PNbgOGZ9Mcl
+fST1OapCef5m/WVEirMbKwVq81XdbA/FJM5XBHPyU3WnEjZjwYwfmUDF5ifcRAnH
++MJGhr/ge68yJ5TwueyCMrtshNPAKsdW7QEBw3a4VuWNCqtETBTA0jcyaSIxH3ab
+BfhoMOaawdOz6XzCyr7UVRTtSplyPcVsl2ES5vuGXm3L4/zisiEbwJW3T9enE/oQ
+aVSxGpJPzqAmm4i8Rj+QFTgC1m6j9w5W+vx5cfwHGPWzUJAI2socqQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7.pem
deleted file mode 100644
index b36583cba8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid pre2000 UTC EE notAfter Date EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBBzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwIBgP
-MTk5NzAxMDExMjAxMDBaFw05OTAxMDExMjAxMDBaMG0xCzAJBgNVBAYTAlVTMRow
-GAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFCMEAGA1UEAxM5SW52YWxpZCBwcmUy
-MDAwIFVUQyBFRSBub3RBZnRlciBEYXRlIEVFIENlcnRpZmljYXRlIFRlc3Q3MIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7fxx2WFOac683w9E/iwLeqyFtr0OO
-RdS+onLEY/+HO6DR2uuIPEkhZ8MwxAnnLs+6tichSMDs3WUijbbI0KTEulpVVGVz
-D1Y8zI7z7TEWD1B/oB1pSot67IosuyjfSIOMRr3UlQHRonE2nY04nyFUfb4yYE3F
-GlcCUdTLgIEgSwIDAQABo2swaTAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPf
-mhWUxzAdBgNVHQ4EFgQU5KvHTN9wvcrF55wNiarbUUzd0tswDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQAW
-bdxkjCg9Ra6xo4ngUHF/RWRpe2353pvN0p32EjVjMyKTe1p3xZuFzCM9oi/PvMT+
-DlqUJpiiJJa3pDXT3Kh330VeTOYLPaAgRqxqm85gUTM3K+/1aHYOKNzbZCy6180y
-8ARB/lNpi1PO1KeJN1DmmeBdDVuRGte4wUXH+NSjpw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7EE.pem
new file mode 100644
index 0000000000..3f996e944d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Invalidpre2000UTCEEnotAfterDateTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 58 24 DA 1E 4A 09 C5 56 FF CA 11 8B 62 00 BB 7A 00 91 93 90
+ friendlyName: Invalid pre2000 UTC EE notAfter Date Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid pre2000 UTC EE notAfter Date EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAgGA8xOTk3MDEwMTEyMDEwMFoXDTk5MDEwMTEyMDEwMFowcjELMAkGA1UEBhMC
+VVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExQjBABgNVBAMTOUlu
+dmFsaWQgcHJlMjAwMCBVVEMgRUUgbm90QWZ0ZXIgRGF0ZSBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0NzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ8k5yDE7wMf
+wlOhyZcxb9+PlGIC417Lq+G5CDDQQGbytGuZKYQR3+0AhiEUO7YwxfIeOtE4YOBl
+QsZsPUSOgSCb2l4s2rbH7V5QFfRcf8f3RQVDjMqhFXvIIWW5uys1poKMqXVDLw3x
+g3ysL2kVl/zORmqI3obmehIa2m1EUHR3jY++I43rJnFUsTvTNGKsE7HLTpkLDABH
+wptY+Ztt7J+sMc5w/pXweCkYLSdulazQ0EKwjDdmWS4BE/3CLIeQkTCB/CTkkseg
+dHPaD18xeV+4LLjAB2dsAmIwAnRiI+LouvCaF52pVBedX5cg6xMPTz1XfLzX3SkL
+3hj4LgUtuJMCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2lEHIUUfWv
+OskwHQYDVR0OBBYEFNUChZ5TMCZHiJZ+TyOTFmSU8xivMA4GA1UdDwEB/wQEAwIE
+8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBABiL
+KJrH+iYNkDzEmwMr9Iebl4gc2uzCObyDkbaQ/UeuxbCvfUm3x1vYbty3HNEKp+tY
+JBXAEDh2GbHU1cLzhP+tNTYQuqgWzE86ZOKWLYI7wUkezHwL00wtOYI8RQfAScGV
+OySp2qwKgeKjXUAd/BVa6FVOzXkHavXNy903ssmko4d9sD+yb9FFY9UrlmIhXewl
+lR2rcUDtHT0dH5PJf7arPoGTRoePSFWeY6D7IBNuXfuhB3WEj+UQzzoANelmavIL
+VwM88Eszmwmofr2sbWi16b6z7XAKbwQm7n4hrwOd3vYTO/zRM0KBB9Y27p/trFLL
+6CmNjRghrN1erPNL1Z0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 58 24 DA 1E 4A 09 C5 56 FF CA 11 8B 62 00 BB 7A 00 91 93 90
+ friendlyName: Invalid pre2000 UTC EE notAfter Date Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,58E9AEEF18E0642F
+
+lAF8yCrsPn67Fka1CA1NSaky16Uh+B4zjRfG3n3kKiqTvKJvLsr5AiQ5jOUlqQMk
+udlOGVTmt+XcHhAn7FLBWhS36aKrx3KV+YuHDSYzfTBjXupj3Cuhc2mQ9EMLmPj0
+MkcV08eg+Pp6IjMDouzq3+pNQljkBQjA3zNxt4ZXJ8xBiCugYPcIojRBHq6xWX9E
+Lhi6JnkjZzpC9VW7FCbFM7xIcwWCfl2mbOZ/s8E9gkU+nZLqFC8dCf/ZZGuLJRaL
+a6hHfVUvUSiMDJSPvEkx0TnUGQ/BHnwUuol/ICnFYesRSJsJhjAyy/AtjiC8nH+0
+9wcas1x+R2mk9os+EgewtoY1RZ4gO8Ug7JODD6NkVAaRAlUXABdWV8tUEnpNfhVR
+87XydAEmHUaK6zHyjIGZOTAg4uFd3Fd7vRbPbBtMI95d80eUYIBq0ETBQ4P37Gxy
+BVU47cWMWNsVKbA0g9LkGLOrfuQZ0Pv9m0eDV8pG8sumOE2HuxPoPFNRnTmhElCw
++sWX/i9/vDuyE+ZaCYvsyGrjwRouenzqh0J+eqwfVFOy1KGIdTVR6/VP5+IwPrqY
+me6gmDsgqIn3JxJ2tTKXYgK7yeviRJII12qLNfxute0tpHnDuOq+LUeZJfZh9QGW
+hsKhprgmq1R7X2dkG+xshnoJIHN6fxB30ENOON4fk58KlQdzaZLwtL03vq9jixBA
+LmFbf2yJSUsbQDqFDcnty+yLFbHk5fyla/LV2SY0n03TA1HjcFHcdkhZRPo3ZVnL
+TO0nRM+IWHuCUNG47tR1GKuykxOxMZbRWOI6EOGUWxx27iIDzRWeqv+Aw8Q+zsf9
+gIO2oZwOM+6yPrMQCuZViVtDb77b2fMmxMd0CFTNdYVFJUjNrTuArbO7zBPydJQG
+3LfSLmHFNiuLpE/mR0KrHMiRTpeQCdYTj2cemXo/mG7sATWQyBD7Gb3P5UoG07nU
+S9yy9y5/p2Dw87wuHFBY7oMQMX/cx0SPq4U+8nPoVYaqF2qhk2IetAKosyZm8/94
+IoSAo5KTM4OOZmkzICCIRn5FJW36VtwIYJYQ7iMyJXTHYzj3aBe8Zt3lBfHs2sVq
+ULr3jh7gsybyJ6ZLDA5CZBA/nZbsEp9a+fLxpaxGNLskuMy5Q5qdQg+p73VxNT0Y
+56OzvezZkvxpJuLPtHjfiQ9HpHmRVHIFPQq9ivnpTdecqR2jusxs24irbJzK34Ku
+tuo5u7AgamCx5HuCnSiKl3Z7HiXmSaL9d150TlR1S1M1yzI5f2sdmgH+2HJEIY3b
+qvCN5bft1eBrpgA4bfsp7uG6M/B+9cWtPa20HSJhNgg7G5A68ZlkE4vuo+0XdxEn
+KVoOrTi/juPJgS4wgp+l9uoWUkVhZ0bbDo6fo8GFcySnFOP+Sb7S/28KRa6ycBCd
+H9i89IjSkbtkBuuHRZwsy0wNOkngjyNKR1PVgiqRTdJQlCS7VZlEwKqMJUVKU73z
+ndkJ3ONBcy6xAEQDacZsZ+TWTXaz8jsmwWXlmwsDUyFHNHmQmIBuyBCQNF1kcr3u
+qHnLtCYjzFrDWTmZfQiR3IiThQavp6Ke5sP1NkNAS2D/VaV5zVzeGw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest3EE.pem
new file mode 100644
index 0000000000..c562f99fcb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CE 60 90 80 75 16 2C F2 2F CE 0B 9F A6 C2 D5 98 11 63 61 44
+ friendlyName: Invalid requireExplicitPolicy Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid requireExplicitPolicy EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 subsubsubCA
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMicmVxdWly
+ZUV4cGxpY2l0UG9saWN5NCBzdWJzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTswOQYDVQQDEzJJbnZhbGlkIHJlcXVpcmVFeHBsaWNpdFBv
+bGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANHpR/YhLPt/LkhU/hxCFZA3Ug2vdqoc9/PCCQcOHh3ZIZUPP03T
+k023na21kRQ/hNBFJYm89nteKHb/f3RBBYsQtA1tHa0BfTWqesFZavNZF4PVwLpM
+xTkJcxr8sXS6xX+SVIsEGkXgZF7zEo/SJ8Nk3nnP29uQyckOLlqF9c16D95JjlVw
+7WAu+1B+mVJTIsztDkj5sPYzxYvvLLkRmE3noJgpoZ7HqMYB/mfocfqH70PsrXYh
+ldQtkCjistQbF3uem8OEW2l1V+cWat954VUO/YzT1c3yqBD2tsJ28bMOadbkUYQs
+RDEQYfXTpCmxAJa5GFtK0mn/N3k5CCjZ2/UCAwEAAaNSMFAwHwYDVR0jBBgwFoAU
+FLvRJvSegTyLDhLP2XsVsizcoyEwHQYDVR0OBBYEFLIISgVhaKmQrx9w+bAv/uKa
+AXJ+MA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEAVz36vPv/Ucy2
+1a6sbkX49qaUfqge0g1K3YYOMRQy3WGfZlnXkbc82SkvgTOdzMBEIGmxGLrC7vkb
+123Rv+nc6u2G0bninYms1u7qcLaGffjbtwEQxnT160WUvfRFkQnIx12mgkGmRS/J
+GKcCKzQzLiiOwRwxjEJ1hJe8ZyrLlNa0BdqG1i9UrBzGzIlF8w1S/ObHBhH28wVz
+b6gbo1HMT+I09piqPOjDsZF8Zrzsa3fn+uGfGZarNHeK7oJlKoJDYWOG579cxNXF
+YDKFJ3UghQcXcZWidGIgFfwaW2/yFt6y5a76nb0/1l3CF0G/xkuRI2IROptfdsh8
+o5ZpO/ZJkg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CE 60 90 80 75 16 2C F2 2F CE 0B 9F A6 C2 D5 98 11 63 61 44
+ friendlyName: Invalid requireExplicitPolicy Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0A7DDDBDFB3C29E8
+
+RXGJsD02CpUery7PuNN0bVaL9DHlNl12r1u/82Rr6sRHIFIVlgsK2Y4kWV+vsUgM
+HR8dDB5B0IB6Zh9PnVnc207OIRin6jaIule+TGaoSRzYtzXZ7F8IDHgQ9sTHJtRJ
+fKDNOhnZQg4w2LCjd+c5rN/z5CxGlvpZvTSBQCx6GoDz2EBufXzb5su+Jk93hF/9
+wP79J/blG39rwpGEiSs1pXhimDG7xp0HRcLtCLaUxBYpp2ap6WFCnWxgjg9fkbf4
+kYOW5h2fHOf+zbhMO+gd9KPsjimfLt2WJHYBfRKzCr7rr2mIf9NWbo3qFF/HfDdJ
+8SedRm38gpJhEMDiZfbXEV+SPkoX8988aI/3nSmfA8aF5MgemZFV3hzLtIAAPCOP
+/1l1ft0l137kbRZTT8AZVDu9VD4M0SUdGTLLB6mHu/XR/xsKoE6SEEAFPEZLMBmH
+ws7OXerisFualPwLjQ13W7Uer89fjfRX8/oPpLvHRLLFcvgVuAQDRNmQ+L1Hgpuq
+0QcGyMVHxFfsML6he9yyxB+pX1hUBGMwSv+BwJsdaNnklcWuUR53GfD+gBOZ/77e
+Fpq39ZozWTP7BFL0EwR2V0D3RaUuBJrW6cGdHjloHHGVMfuqsoycxw88vW5oVxDY
+bWjJPJipt0hi+ZuWwIvHq9CfbzKuCDoOoNZllrKMbAt3lkbpbwRXzmifod+ueVY3
+OODQL7waiyRuyfWfxD0vL8m4SMBoOYWQjFbsDRLedW8TI+CsINZ7kqzG5Nm3Rho7
+O6UDK2vdFHIvepnmlOMBhVD+/6KpJWzOzonp5DTBhxlsOgwebzRrbI2oxtasIzYP
+DNiZS6uuLm9uJ0ZcD/XFWfxygYVAgsH+AZtGIdGVhdEsncOQIEnO9dfSbcK+42o/
+nhmuoYEbNC/DzhtqPv0Jo8yH3tXtoLUCGQvqbVC7yheMYBfsBNHsL+v5Bi88H4kU
+Uwkb18o0NNvUhw0AYE3Myp1+Sfd0n8L2a4Z+jb5Doi8KTNtKa1nwJztJiUryjc0I
+zt+MX9+whCZPQtUM7OtGXZ1dlwOTjpYfQ754JdVxTYDb5AjzeA/Uf36qeRSJyTBw
+a6w23vS4br6rgqGoR1GNqpTe8QjcpA43tSlfx7Tg2MvHg54iSOMYo3lvqmmWiJOk
+qCcPZ5uj2B24BaRjDQxC9mIJrm2VnIB1/7Vj7rnXuNiKCc6L9dr3SxHAEFb0Qa1l
+8fUV4KmFBf4J/gDmviEbJz646xq1aN6RTzeqVEV4MpXdpndNu3vYfEnw7+houjGI
+alWNvIKidiz9/yovyN77F6i2DeIJ+EFnsc1xv+v96CASKXgFxPc4f8gGpdO5LIpX
+S72QE4Tw+jFi/o6VnPvVV/mhKllXksiqoiZr1X9ifl5hDbl+bMfqTko3S+pbk1Qy
+spEkr0ro+DpVsoKo12shFG5DV12Ic3dP3/mewj50TU/2VvmdIX3mMxNQgSd4P31+
+0T7ZoKq1RSBGeyMCiQLpSKWZNY8XipikKGkpO1vum5uOG+loO5KwDPSl/xRi8s6v
+Lqek+d/A5sixLs4R1EP/MvdEkQ8O95p9/noM3sgsIh/ulbvrrsWR5l7g9XU6moaB
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest5EE.pem
new file mode 100644
index 0000000000..86b197c22b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/InvalidrequireExplicitPolicyTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 10 D8 85 4A 0E B2 DE 50 07 79 D8 6E 26 09 C2 F3 C8 A8 D0 CE
+ friendlyName: Invalid requireExplicitPolicy Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Invalid requireExplicitPolicy EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 subsubsubCARE2RE4
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTExMC8GA1UEAxMocmVxdWly
+ZUV4cGxpY2l0UG9saWN5NyBzdWJzdWJzdWJDQVJFMlJFNDAeFw0xMDAxMDEwODMw
+MDBaFw0zMDEyMzEwODMwMDBaMGsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMTswOQYDVQQDEzJJbnZhbGlkIHJlcXVpcmVFeHBs
+aWNpdFBvbGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAOKog33tBMcvKLdCEtAS4Mehc0LTwRfbt/eJ49owA2W/
+KSzT9XiKoZ7t1s7MPh0NfAkOu2YOlqjt5BOSlzQbQ57h+/3lBdMXkNBT3YEAsrgo
+ADlhGA6CVOIxPuZs7z2x+ux8m8wB54ZXO8h7JFfj+YrIKkMoTvePMltatxlox76r
+TUK2LsXOZKbYZBkKZEqtIUudUcd50N/WTkxg5qE2Up9V4oXhdY369sF//7mMadZ5
+KDBqDmHC3q996y9CERPghc/sZQVaX6widPtlsI+SO74IBMwOX29eIroug7mbeE7L
+JFQc1KYaGyB+Po29y9l+l6C9mfWOHeMLKOCzBlexG58CAwEAAaNSMFAwHwYDVR0j
+BBgwFoAUeyxRYTEVrawsa6m+OzsYGpKqf0QwHQYDVR0OBBYEFLy7jwxuDW3P6K0Z
+wZCQ6vgkqxIEMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEAjMJa
+DaSfZMbvgS2voQaA27koy3de4DX/dlI6a/QG0O2HHilgp3g1/G42thy90ewLvNse
+nkYf0tFM0Fhx3n6KwNTf1nItuwn2HwTIiw9jQ/ERwLqRzmnCor1fKf+maNGWqYg0
+vFmmrxVo897hX/0b9CFTpS+SP1RgMonaVnjkR4/sA79aJ49wUpdPkVZrmXOAaM8r
+MR8ryNohpRY8U2O5+S8MJZRKQEDyMFW0kXeC9Otngb2h4ORErh09DHI/xuGN15So
+90UadDApAMpCi3PijRNIKVcBpge8sAvXwR/iYX9ws8XNuJVkEGYQYJwLKU3t1NAA
+Ynvjy3YgibsBuUcfng==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 10 D8 85 4A 0E B2 DE 50 07 79 D8 6E 26 09 C2 F3 C8 A8 D0 CE
+ friendlyName: Invalid requireExplicitPolicy Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9E632AC14FDE0912
+
+MZ7JO76n4gkNhZ/mbGaQ65kpwMvIaETRiu0Hv+ET579MVjVlGFccGFNNSYKVrISD
+c5xHwIYGp79eivhh6wFNdrTqgjVJMk0QGa35aNL5E528O9q4dT2awVoVgQm6huC8
+ajoQASr+lJttTVw+EFKiqlt5cVapnA/8bnx8I2vAZ3Jf7ZhmvlSD7rQgyRuDEid0
+otLv7u7TuBrBFOmjVSg6froikW9DwZxEMY1mjOyu1pSvOPZueAUN1KEsXMlCv9Uv
+k/U7mD04OqNJvbEZ5AF8viuqzfrDSwym9/XsjWIYhdH8fbFiDhYYaQhDfNwpxyCN
+JmWFUncY8qX2pG1ITr6hImn7xE91ZMK6WyUjQOgI4IvBMSD7OWQ9Ub5UqcO+8nx5
+tjij2bGB9crZ+CGrgpXeiYErVFsRSFayuC5sWGvyBHIbWsm24p7/DN8G9/VCuUbv
+0PQYbdmc0/HnpZHtlwtWGIn0RQXCSCefxl8y3OGFaL6QMPAq5rt3ZdidSFMvJ1QK
+iaZJsamlQdJjxHctGYr8ApLN0ZF3dyHB07aGXqektytsGx+1P5D6IfBPXhSD1u4U
+4rfyK8CBPXc9+hysiqcHVXRss/W/I+jC1mq1FvBSWCIXkZOrtzHMEfC9CiEO/pcg
+hG41fHZXdvBncGvnIcpJfG1NrlzbnVpGk3C63TeZH4U16956wgYoEFxc5GYVCIO3
+zcr/eL8STK9zNc4QuwZBuVKu66UjA5Jr/GKrGWB+2I5c06rfDc7qJO3Asgdm2BAX
+7J74WP+duNDMShd+l1IGeodhXsXZ1O4Ru05sUOVj/SmHG4Fxg8Alk/TuZI/OVqN8
+Rx4Zin/fbB+SAPNT6U0+LeLoHQizTPbzKpfp/0YnhExy7/tfTEMVvvG4CPNATjr6
+oeLjrrCPVSY0mABDO8sDFbcZhQUXvX8DTP61bJbSPgZ+oWtXSeihB0vUNn6aW3pr
+xl3+Nvo1Cs2PwbayJql2BEkarr2Fm4h+CM8s4FoaTErEVQlLVLTn8R9jRtQ9JQkR
+dR/S345k/GKtQajHzXz0YmzUveGsCp8TiEdIgkqf4uBS8ewCopsWtR7BJpyl70nF
+8m5ZfHljKTTpceRMD6kltQ4SM/TqqoTH5N3Nzm5GBdOR/R+wUS5XQiqoY4HqL3wa
+z62dZRfxed2GR/v5w1aX1rqHjpjXtMBdvrKbzeXtuajGd0L9FPEEBZ5Tj+ZdGjMg
+m3JvCz9bmHJEKzi72wUe+k3U+InbeaY3iHzOXDVrP7l7diQ78u4pHEge73QzsDVa
+nK5oXHe2bagyOlcbo8pBBb5WxtCmfHzSnwRthD1DeefP2MQ0pPuKiv5WACNQjTMc
+ATC8ll8X0rs7hICA6qU/4chWyE/qUUKvOf24p5geDLLH/ctO1gtawCWhq3pd56Hl
+gqw58zqhxtLktyMmhQ8VbCCeTCIoAcK/xpDbT8wpOpnHUg1KkoQacG0eAshzOliV
+TxmjLsVLdGIXEfrwrSzbyfOkIErWqfmknstkCtgRGCFhmd2/FwsOd89XyOEJwnbk
+E2vEyHbWiGT6I9rZpubfUUhEjiqLF+wpSVbHq+AUXS0Js6RM+yBljlkd8DEGXOoq
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/LongSerialNumberCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/LongSerialNumberCACert.pem
new file mode 100644
index 0000000000..ef687ce91e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/LongSerialNumberCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 10 2E BD 75 C4 D3 AF A1 57 B4 A1 7B 62 22 2C 50 8B 04 27 53
+ friendlyName: Long Serial Number CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Long Serial Number CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBEjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAMT
+FUxvbmcgU2VyaWFsIE51bWJlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMMaU0IdGR+wVMsv9u/acjIcUN1g1dlYOWamWDZgkiAuzZ2tQKzya2A4
+o5aK+otUElXuqmdqaid3NRyKkybkMdYEeFvK3Wi+CRgyeePBl8/SZNN3ZjPSsDXB
+bhHeCFu86s57lAbtlp/F5T//rHp1ZJeQBFm3YOQ9ffT35hX2qGST01hXhf0YCI8J
+fuCEQUj3SdUErJ9r5nntNi8r3pJfD2JBq1+fE8IO8jWImrxqNrF/3JEaQ3McJGLF
+aM+qIGz5MPUNBhdVxFBljfQrm/9A8N21SKeo6AnT0tRwuAysHgiXeItxd4Em5IW2
+4XJ+TzcC2CA3wy6zh+RrQCLPxeasDPECAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFAtjt0euwgcyG39v4zq46gv/12Sk
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAf1t2PGg+vHksl8WzT5PxQla3
+2E0dBOmg5QWahk7xffR2Uybkj1ZpIV4ljcMviVDXV2AUNpxbsp1gTYDKN9tuBcmX
+3YuHVbJDKlyp0ldFApGAfc85Yau02hoxTHQbuc2n2IC4BK7BHaklDivYUSML0kbj
+0+SF/RXCrCQnGJBiNl6uRtLTDWQLTu++9+RbDIloumrSZKG2IRdNSCMmKN/51Ogq
+BDr656aQEMq+770BJ7SOWKdErMniwoz2jF+8CPkftjvZDZh50ihhF3YciXpUMH1H
+dZ4uwQ2AZzoHtPElpilzQc1XeXUZJ8bEi3+xgRTdUHniOP6KeRjf/cFNN1FdfQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 10 2E BD 75 C4 D3 AF A1 57 B4 A1 7B 62 22 2C 50 8B 04 27 53
+ friendlyName: Long Serial Number CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8B970C0D9EF0C68C
+
+NtlaPOCh6XgFj7iu0GphVsrjvOjyv44kO5ocxgpmnbUOgWBoPmIKdMqgydK5lgF+
+HRN/f9ZZZfSRE202wTZKfnxeIBNyUStlq0BzoMjhpDFnGGuwLVhhGDPjw9w5Yv14
+f6B3eAmloY7gwfItkDWIKY/PwTpYW+g7PJiLKfgfBE3kzx8/R1/Ifc4o5nYV8Bu+
+oGA0h0/ncUZrgnLuUuseCf1xvhwkIUTn1rO/uzJjE35FLKqrHCruPG1BroCQdn8b
+ZXidhDWfrVLGXih5V2zInWz33ejpZPxhtXcog4gX5k0MU60lStzhpIm/mY6z38Q2
+xywJMD3Mxq8vRWKW3nYvsfK8JZ/wLdE49s984tqE0RhP+mys/H6xAYLMTEmxjWt7
+3LvlO6QniNMytr/XZQm8yBUkRGhT2YwJf8wIESdZVfFKHA6YsmU5w+lt17UiS7X1
+hE6zA9543BrCrYYeI6sE0//+KbAPy5EUCAms8xaQhBequwUNteyvuEHofKgKJ4d0
+fzwsxRHJlPJrab504zOj2zLnJDX69pdMynQxhODQFsqBkUEDJae1E5ZzZhSLHdms
+Ul1uSew0/Z821vq9QiZ85oKss+3Up2adpk35DQmCrnlqTxGfDFubCQsAIta/T56h
+4tRfT6ySWz4HNprGeyhBLYGtabhKwxC2HmwolfgFzFvWMaKG7NfYT7f/5Qg6q1za
+zIWKUvNZyZw/Kz6BtFHRn2bR2uzgbC+nJg9YKl1FLETLJHOAUH67whNIU3Uy3Y4O
+idkGvIXH9HgLYnCoDx8SaLPUbmctyza6WABZAuHQMejRTKOe0so9xhBYLJMoDPKg
+TFiG+wGnLKtuqQYO3OePk+c2WDVTrV5toiNDIJXU+JqKZ/tF3JFthTPIE0Iz/leA
+8CC8zORjvKqbmHJwvS75yTuoQTZ0lSyx+o8Xd08b0QC6GkXE6tII/vco8TVgkmnk
+aBPDbDzFwl4vGQ5y7f/Ekmo1aW8NdLouiAGJsZL3aG4BVCuYre5KY04hGguzoqfD
+cHj4OfVrmCbEwxGjvTvUbWEK9OfZOzcvPC6eS6OfjRLXUZNsbFd/8DFLCim1Enyy
+rRuhdTDQjKdYxzXbpZxNXxp7Aua2RclUAPgbuZDo5B5QU1qjjyPXONeOBfltNJyC
+8LQFj0SSYCB2zMuv2lMfQdWC1Jm2MUgIzAoheke9nqO+AlT0aX5MABgpGwmrALAs
+evtEXaS3D48OvSoWZ7mCmEzgRBcIVqx+mCppHnVonYi/6wpIXI8YIsOLKjEJoghW
+P0dkHJk3ZGVRdb49c4nS8zT8hcQY5crFN4luTUcPyNlAXw0sLYrPqaJjE+JnYvCt
+EVTOAWvf1KNZGyU9/y6zquYcOCbs5gjjuG155t2xaLeoqYm5QgFV8GuC07vpj9yC
+DVNSST1PK1SZLhK9qENREHGf692wvq84rleBdxc9FQbV3uCOyo51Esat8yk2zsUF
+CdsjVmbdwNuVQk28cSSbztYfYjHigeyjRZcA9FPyXHXe9nG4SSurQt2Jbkz9nZ7t
+kDeg7Usr09wlYeoBeC2EaRuCgkiDTHWdcQeEl44S+gTX7ATO9bm2kg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Mapping1to2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Mapping1to2CACert.pem
new file mode 100644
index 0000000000..abf2cd6285
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Mapping1to2CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5A A1 7F 4B A2 41 76 28 19 72 F2 B7 8F 5D ED E9 67 77 8F 25
+ friendlyName: Mapping 1to2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Mapping 1to2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIBMDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMT
+D01hcHBpbmcgMXRvMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AOBrczl/53SePwB1Ub5qyWVoVLy1LCGwRkezm19LowdwFJkzJV0YgrlXpEd0TeBF
+Wn3ObRNqZmcPBkvF9rUrRCmuMIuT+164rh+U80zAXVVJgPoCIWwAHKFyskha0L5q
+3DjC+ZsIqZKajL/hQj4OmbKlvJuP0Ptd8Bjiy9bG7NgLohzt7BvI91rjKjFu98vC
+nFvXrpFbPMyeatLKJ/x0kgHfPRQLCOot4ojSkQmbD5MZNNplW4G/4iWFCAwwsk5y
+jA34AkwYIe6mcML4Te1wBGueM71iGaga0pPdLnzodPV5rr5+sjcKsW8yZ2C3jca1
+ui0v1oDcQ5BR0dlvomx/VHMCAwEAAaOBszCBsDAfBgNVHSMEGDAWgBTkfV/RXJWG
+CCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUmcV4acs9M3bCmaxE5bAO/rn028cwDgYD
+VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
+BTADAQH/MAwGA1UdJAQFMAOAAQAwJgYDVR0hAQH/BBwwGjAYBgpghkgBZQMCATAB
+BgpghkgBZQMCATACMA0GCSqGSIb3DQEBCwUAA4IBAQCjpL09JCig5v+7S82FBPiu
+JTT1xgO/XBQqRIvDkfggs3F4HZCJR+XuQiloEGY/H86/laXVMy/dTj5t/Ojq+8cB
++T6jWzmNLTvjQkuIrLkzIQ15bce0+1EYnKEVVw+0BGMfsAObXsJGLDxmE1DYRUZi
+Bx+Ar5ZHwhTRXLNszYWSTXPR0oXfPly5YqFwnFWBAj4r0q6rUsIipcmIe1XuFMhY
+SFNJJNWzpTMS5ay817vhfMb0koA+fdM91hmONDOo8wbT8CDr5hWhss1FEbAqFheI
+RhYXLG7Mll5FWcfc7HbSU9+edq08W6aLsgXyupHF3SYrA0w0duk2l251GqwUgxx7
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5A A1 7F 4B A2 41 76 28 19 72 F2 B7 8F 5D ED E9 67 77 8F 25
+ friendlyName: Mapping 1to2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A1DE75F64A796C44
+
+io90ydFJNbW1sRPZ/CFOPMxQpvArQVmRj71uG6GysSZD892WtIDO8O5+m8oekh31
+3cZJENDZiCGt9HwbN3+qTxTseghUcmYT/le0u5XJRVtKorFwX6HYHwJNutgZ0eL+
+B0U5mSXWK6DVrbuh/tne7K8ER0gr6sGiiArgPlXPWeHqnxa4J77jZWq6q61kBKOV
+jVbpu6uHHKSCLj/3NUNQcKNwSCf49JW2j+dXw0BrWh3WSoaNn8uUoZHCyEoDx62V
+qtRgJenl55dzu3MsrO2fRaThvYX9u6U/n4w+Q11KyboRfhlZ1c0hzq6egcsYJahn
+TSekKbyZtBdvcUbP0RkaP2z5mYxzOWlxgyxPHMaD1+DHzt3qXvdlVNelR5sXwXZy
+lIl4uz7/3LtVUe8Q1ksnyV+VZULxwzTKtJDocn+4Ha323HwWeQk4MwFkeW4V24Ts
+OtBsW0N+HHJMv5ceortjOafIBhMDeM+mWF/tKV/nOnjhzozweuoyOJDRca2LYJwe
+WGKbvp2pubirZl/u0dKR4MfzPJ2rAnQrJkeqG6H28z4JvUMgGzPPoyeL/9pvlk0u
+Juurr6DWX1WDp4ba1DyaqLV6xEU2txOV4ZjbGyTCrgoKOirRHKaLtF0DIA8AYB03
+xSPHEBgTrFodVOzAkfsTX9BMSQrYMWL1gy9V2u+lTpgszSKGaUnYnzv0ocwem7ew
+5A4B7ZziQmEEem4Gmo8Qed3hcPcdZYieAdw7ZddGgjBNqUSPlvR+4bgVT4oDc+Vi
+8o5zJG+itLP/c5ULLNeXM34hPYn/i//7jGBz4vrYd6T65vDo0wO6pUV8m/eFcM1j
+KAf/e8gM6J7TTp8UIvesX5PResiQ5vRr7CE0rPFPyjIRDV/lh+pgn6Z+hUseBvzV
+7n5HB2W4uRPjCnVPHQUDcFerElAZZUPqb7EEOWCbLDDsK7bfxKC0YGymhRSTPxPd
+5te10pFtV0N4JT4GTkebnOYHiHLeVOuhGszEL6FgT7XlM16E0ltMAzmfggEXpH01
+qcrxGUW1OJTIUiwfe3SWBw7Xf2+nrdfq4xH0id9NtNvEFJl/m6J5hgKyc1J02BVK
+KpvoJhg2jgO1FTrvKcAaERNHOxu1AEPWUdOS1zLvzAp9plSKY8wSFoviqiE0iQ8g
+DvcUr6uuhXPvFAYyvUI1YtCczZC4peg9fgqepFJhEYASD1Og3sLwKocq7wh2rb/6
+Gcgy4rX+gu7PUAlpTkEFN9GcNs/ZHW3/SCLeAFMTo4YzEDreBRi2TABCkY6ODy5B
+XD4PCNtnNPinvejnFzveG9I0k9djB3PpERBLAJ3NyIcmDspe0wG5qfrnU9F0DOwT
+uWDh8nzRETDkfBNmKbAPiP/DXI7ROnISoM5uvMH1bcNigmCk4/kbiXIfpQ/oXW6g
+OUnJfKwSjqTMcjH5QPpem8zowWfOYNAPWZZPI2i2UPPUx1D4u5eIybmKx9AkSfv0
+b4T+Awd5bj8G6AnayfrgCTsHJEomEkX/K77W5AZv6V/dIYYSJp2CDJx9LYuU5J38
+qX7PYlIKvvWrtLE6neylW9lPxXxWr2gOkUPUBwuRZqBbhN/5Ecvpnc57SDX57UKh
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingFromanyPolicyCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingFromanyPolicyCACert.pem
new file mode 100644
index 0000000000..ccfbc36f75
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingFromanyPolicyCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 4F EF 0C 1F E1 01 8C D4 7E 71 BB CE 89 E1 6F C9 3D ED A9 F2
+ friendlyName: Mapping From anyPolicy CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Mapping From anyPolicy CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDvTCCAqWgAwIBAgIBMzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GU1hcHBpbmcgRnJvbSBhbnlQb2xpY3kgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCrp6IDBPUKqlzfwBrwMM0/8mXKVyogMBl5xjRYIAzPCs0Mwv7R
+kEQbM1BIsYtbSJgsFJtldgS1u2yhYklqgcTsHZK7NrBL/QleugZcze2gunSlvAYW
+2qO6t9japmswZ5/8l2hTia0T7P7Nk9lcBbDi+HjNDRqZglalb/gXvfWnsWxOxAiS
+QY35dAnqxXl5KlkscU7uvsQubTBmNaQHsDrxoqSAXnMZG8dys1G3ET5Emp6FvYBZ
+LSYQqK2nWkL8xFIbbdureHpD1Af+HWFDTntlZzw1Vb2MXvmz0pYFdRGA75KD7SSp
+LEl5BiXwPLMF/UHmMZWhqVug0MlJ7mWl1UkzAgMBAAGjgaowgacwHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFGhzFOALNM9yQNqUltYV
+q3qkby6MMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBEGA1UdIAQK
+MAgwBgYEVR0gADAgBgNVHSEBAf8EFjAUMBIGBFUdIAAGCmCGSAFlAwIBMAEwDwYD
+VR0kAQH/BAUwA4ABADANBgkqhkiG9w0BAQsFAAOCAQEACkuUlU5OLnBP9XTQLJdC
+4cZ2L1LbaCvAnUSD5ZU1UyDAPHcs+YsbjerZT1Alt/KqnVyD9pvkUuScevjjvLCy
+fSGq4slrV8mHUVBbMuumv5q+0Z4J2PFgNXIvdxHiIRFUq9A189ZiQkfUxSeRPUK4
+M3YmPO0iaeuS0SlAKIQ8a1dxNgm9ax8GOj+SQsx84FxED2wCR024sOajIHIPVvyh
+bWPQMQbdJVSuVULjsfuGDyMZyN6a0gR5uBQ1MXmsIVrnwAia0LTH7kjudgabGYa9
+MJkUVscZiu01jZBYfDqpaCN4MWkXCNvf9gksys7HoBvFlGyHm32/XiFrVKYufBkf
+iA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4F EF 0C 1F E1 01 8C D4 7E 71 BB CE 89 E1 6F C9 3D ED A9 F2
+ friendlyName: Mapping From anyPolicy CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5C462AE8E9116220
+
+y+qcQ5rPSa/dw+OO+v0T3NcA/P8P29G7HJ0cOxdMp5gG8WsyH1eRcy7cxeQ+/qXG
+b0vOgpAOkrI5uVkZTHg4PkB4pP5bqOp5J4gvnDbQRpWFBTWzB/ojqzmBt+OQqSGy
+TeFD4ZyRTL0CLWFRX1EtLJKps+nb4qUaBGuIp1B1iBdo2S9r+saefCbDBM3MW3uG
+3Ji+Bb+ec7GfoW+C7OkU4+lD1AtT2lzFJer0kYH8idY3cYs7acgA9Ir2TVpBdAcV
+7RMk40w+kC8U7qJPauV3WwyoiTjy+ul95JSQWWaOEa4ZUbe3AO8y7tb7on6YQ0tO
+f73uAisqIV63+JsANtt3dWsRQI7WYKpKxZQwABz1jB1oLtpn3XrYsmeiyjW6YcOe
+pJBGRcwW5w/tMIrqtHqMDvN4y6gW29l/LLL7x6yDxDpqCSD8+7ojDwne3dA9lc6t
+wx7XoN5p2oEaGvhwtR2xXyC1rxownGC4LjVWmq/cgPbepZ1WGg1NgDHQTxoSdwmP
+jLQsXNRkNYYOkXZACG+q0aWeeqmqqYMacP1aUZnwF0E2R/isOGMprg5BNEpMM1AY
+rUhjiNPTaVkDkv4uSoGBVRuRYwKOv5pZB39ZsxywrDOuQgqAUzpfx+4FgZKTbQjG
+IqQoMCblsiDoywaqZjPMwFvV8gLYGgOg4MkF6Ba5uVkgWuyO2jSo9ZUmb/MoMeMN
+d/y7PszDQaQO3t4YtUprCD6eRuI5ni6U/jEWHzOirkQ6XZUekM0PEZuyEQNzQK3r
+qOl5hAfboXcQfrxmVL/tmri4R+022kkS5jylHuxg7vs6ADZalaAF238iybqlzAoL
+b24zqZXeKcM/w1F9FYHuVXThJn8ijJvKnWH59zT35sNjPqmnbc6rKxv0QKLoHkqd
+kP6Bzdwufq66PbEXXTZeVnc2gbWDmPywbEQY+WrnKuakdVNtdkczAm0C3tzS486U
+IQFQDG0ffs1AmyntosXmkePvjN4K5KHieMqFvy+tdYwboJBnsD/HnhcM01KaFv/0
+WULj2zQ3l9K4Wgt5p7nbo84CXL700mpadYbKNf0qVU0TBYaU6dnNDOCLs802B/R1
+9icOlaEBz/oGfqH5FLi3di+MAJOss/oXzfVlQ9zhrru864Mci8gKNN6WMuA9oAIy
+losEt512laXp+eAFtco/A51nH1RedJmj5EJV0RSgqhg29RiTDIE8UY1mWny/XM0T
+q3k4eSUHQFtIHUR3e9YvqbRIjqj0uM5J349uG4CirGStm3eCGUnTUL8ib/xi1PNJ
+sXDMOmdpZqbthOJQ2dWfaaMXhidUY4lAX+65wmFan+Jjd61nO5219mSqUZf5pF/I
+duLyTW/H6yC2AKYsnNWvlIfr/1vI4U0F4B3pVq0+xZDWoPxzQTZ6imU2KYgQDrOk
+cYw47YIe5iaos+Dnwk9L+zWVCG3nA3HKABakASOD6F9XfFKzlnmKhCB815aBNMq1
+54hlSzUQpYW4KJkFN2N0ujEkZpcfeR1CmaGwMmqMjm6MbEcU1hAKRf+H9FlxXFHb
+n5SophPEWRRVhjuYHePYIzBHkvBVGJvYT/0V3snUt5uUB7NSEoPpCwhsfzLUO27T
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingToanyPolicyCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingToanyPolicyCACert.pem
new file mode 100644
index 0000000000..04b48d919e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MappingToanyPolicyCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 38 6C D7 9D 70 F8 85 14 A2 EB 28 F0 B1 C8 BC 6A 6A 7A 18 CF
+ friendlyName: Mapping To anyPolicy CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Mapping To anyPolicy CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDwTCCAqmgAwIBAgIBNDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIDAeBgNVBAMT
+F01hcHBpbmcgVG8gYW55UG9saWN5IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEA7l+P4Iahif8g4OYCYpPVwbmJqrG0fnDR/oNBlVnC10F/uJiYK6a1
+7tCVcPXTHeD3N1XtvviZzr4hPny+F8DoVAyYsBQPn5pQ9YchgrsnMfuTmp6NGGt+
+4kTW2K97AwgH+cRwm4/5xZgsKZS4dUVSySds2Vl1tLxK7DH1nrjSvieDO1k6h6Pi
+fHZ/nfVI0CrPP+jwrPdUllp9lNv6IyrwO4gAEWUzVhwuqnEErKDA7FDLCMS/MG5I
+3rWJ+1UMN32/IZlRj7b97Obe5vmXUtcnVOPTtmKPF7Crctq9EnAxOz7aZObY6qAY
+6OJvaNCLA1YhHxNvSACVm6UdXaMeyodR3QIDAQABo4GwMIGtMB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQULO2T8R4acBWUiy2TtJjS
+twUIrDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wIAYDVR0hAQH/BBYwFDASBgpghkgBZQMCATABBgRVHSAA
+MA8GA1UdJAEB/wQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBADHu2GnJgEBdzRt+
+PSfkyzvActmVetZktEWh3fysA8LTQI0lPBN4us1QKw61o9KtO+ssVs83d3OF5l3X
+vkO4ilHyvT6Hz8bH5pXskMmXqYubrJI3lQjn58GohHNyCUDS8bYRDLe1Twz/t8VG
+hLyiQwNQknc/8h6q/oQuilB794AHTDP84np7rsT24X93LOTxQoEdZXhB0gvBK8FE
+j37F12ObeB/3fKRCW0kYo4leBgcPw5G7jm6z6nljCgvn62LBosINe6f4Gy++CLHc
+TVW3OsNOIrgSBqrZr0JfAwykOWfqJGCfOQGcOIP+MyFkGHL6jrS8WnLoM/b4I5a6
+NOBfmzU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 38 6C D7 9D 70 F8 85 14 A2 EB 28 F0 B1 C8 BC 6A 6A 7A 18 CF
+ friendlyName: Mapping To anyPolicy CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3BFE1C8E0764811D
+
+FbLyNuu6zBe/eE8YLhTU2LyHAk12hF/DcPR++oUr1y+YQkRES6ciZ+M2VROJ3oZ1
+9AaUZqvlXcFX1G+/p1YBmDXQzsepmxS4Ofuw44ZuxWzJZCFWFz8zHQRiWqgRMYAc
+k/WNEKvVjRBZHzsCf2mkyry8bdyVJqWjeh2j731ERus28W1LdZC01H6uHYIcdO6N
+/Fe/tTzi1uqCwsNqGjqKcBzVJdXiOgKKygn/4eZDZ+OhvaTLbqsE3WbrrZij1LKJ
+s7brfzBlHIBxR8FiB8h27QQrKjyU7uB08V0dijq3u4sckOd9TzCcGx3GQ+IFLj0R
+Cxu77Hgh6btFAZYUFvxx/eFLF5Z8KQUqDDADfHnreJvu+cVcqdvG9HtBTA1kb1In
+gSbjuGa10I3JxyTGRbjj7MCCKRIy7DVow8qO+0Rbq8bfjBOdUk+dz8hgMvW4wCS4
+toJI8+kAAuQlEjnwGR5YOITvIBjrN+gauOv0yNx9bQM+pdoSfjMb/1f1Y3b6WPbN
+yoWILudv8zFay7hPWk/8MOpEgHUWRyELwLSgTzSSITFDoBziJqcrI+fHgX2jK3+8
+MdTlpvc0G6xkxTdocvmH3+bhba1bJqDFqMiwrG66dqUcYRrVZN2ee6rjj98nNHMs
+tUyfYSpusV82gTjH9p7daoUYPRHwjCm2NUrbAxd3w3uZYEIinanY8GHJjD6PqEBs
+Lwf/Ciq3y5bpn11pg5OzaCUq60nugEjGqU+nN3D/1rntyME0/o7e7GBc3BzQvuLi
+9sW4rh07vq0acZWVi6msm82WYUfgNj37859rlBYGaIV8GnUkl4wC+MvAEO/Bctkd
+ztKiS1g45xLOx+BYTLfs7u+vrVRR9P8hENtq369c7FNayjeSb+FXrQCWNYuqox1m
+hyIhg2o85x35bV+i0DTFru0WoAi2Zj7Ors8gmD1jCx/kiLGHcxb3egNZlJFSDExV
+2N4DsqHrneydplgiVtSat+COB3vUoIvSkBacnDi56YxNWsS/YTryFY0gy6P2daAj
+2jiToALSwfCkcUnwzEsbxV7+NbKi5wt/H/zK5yK2IbJszepwLLqSycZTLPfm1yK3
+aZv+57kL8urATlsCxMKSEDgCuGGQymDA70nKomK+YgW9RQo0+ugNHL1HllA+mnEf
+u9XyYhFDK44caO1TiiWEN30SUJuAOBfsL5sos3Qnagf80Oq9ermxmGUIgzA4FljO
+oQShwiSMMHS0lvqXWG1Aj0WnyF1qTCXgzEV8TK1J6RUuhVp07KY9PsPQ9pK8Zgt6
+ixgxpIF6KVqsRagHe4NN98YBdvXMGdDaOHQ5Y74zJJ2vB6JJmk8KM19pAvcdSBBf
+DnVBq2AxYeT6L9Upzfn2inHT9DBpX2VrtmesJHu8AAvMwpdEqF4s0JFWUtINADML
+hP2YGzy7qWUGn7g8ljV+nBLPvn901TibOkurmAZEnafMl5WcirhEjgqdsyyOX6HZ
+F/eLPKgiDE10D8I1KiCvBblZxo9Fr30fRYBU8W9dqHKhOjxWiUeYYpSMASH8PMHk
++A9JmoZe3p2K8i5OiBmUG8Wp1qNqquwU3uJQerRHQWiF9F6um9gc4Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingCRLTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingCRLTest1.pem
deleted file mode 100644
index fcad66a5a3..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingCRLTest1.pem
+++ /dev/null
@@ -1,76 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=No CRL CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbzCCAdigAwIBAgIBBzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMD0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczESMBAGA1UEAxMJTm8gQ1JMIENB
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvjr78zG/GobZnKabi/siuJQm7
-6k5APCdB3g3SJzzlYR3ivCQg+7i1pEFgHqLLPTEHOCHunC5EedZUGzUGQX0sXAxr
-KYeCqLS/s0+saOR0HBk/YsOaCwW7v6yBHA3s2XrtK8N4qJg6LdZaGEjUefMfUM7p
-iVQQPpw3uAQmZuYf7wIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA8
-6pq8h/9J6jAdBgNVHQ4EFgQUB6jzF5xOAmiWRcwRmAF9yHg/9SQwDgYDVR0PAQH/
-BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/
-MA0GCSqGSIb3DQEBBQUAA4GBAAWDjIUq/V6y1p4vxO+A1xdmmM8c6yRveH2Lq2CM
-OwmpClTYfhLpqkWwm3WSXd2VvjiPUTgTC5y7EquFuZCCZkgLDVvUW9VplIm3a6I6
-dgZiOZDqnXZ5rC+CHGSszfdDo8gwjJ+vA8AV/CNSGNkkbo/ZQ1n7Ppm8dW/bS+8k
-anSO
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Invalid Missing CRL EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=No CRL CA
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQUFADA9MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEjAQBgNVBAMTCU5vIENSTCBDQTAe
-Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFwxCzAJBgNVBAYTAlVTMRow
-GAYDVQQKExFUZXN0IENlcnRpZmljYXRlczExMC8GA1UEAxMoSW52YWxpZCBNaXNz
-aW5nIENSTCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAz8OlGINaG0uEl2RAD7DtTn54qLrlCtUbCKs3O1dr9nEDDohfVU5x
-nLweQfR/m7b9F17BzhHcxFYjfRh26aj4eOQcxHrpBfNMj6U87coAeJ4ERn7okfqM
-lcGlHWS/Wh48iiZvnCvg4jeHhSktwMppTGKIBKmJ2S0L4yKNYCjZ32MCAwEAAaNr
-MGkwHwYDVR0jBBgwFoAUB6jzF5xOAmiWRcwRmAF9yHg/9SQwHQYDVR0OBBYEFJYM
-oy9aXt4kJDgRNj4KDS29NtDXMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAlNJLCSyrRZNUza9eL2Jc6eFS
-bjriRrz8ryND+rn0dnsceIVrXVApplWnVwUjfm8fjOZlNOLM4snxmzRJ+FyTR6z5
-u9nK9TAEkMrGo/NinCET2Y5v4mtxj0E6hJOIaFxfkZoj1mz8BvOYgiEIYxAK65lA
-BNDlWIYdh16AIUEZNAY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingbasicConstraintsCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingbasicConstraintsCACert.pem
new file mode 100644
index 0000000000..1988c209ec
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/MissingbasicConstraintsCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 55 C5 ED 9E FA 09 D0 48 D5 76 97 A4 74 1F B7 33 BF ED AB F1
+ friendlyName: Missing basicConstraints CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Missing basicConstraints CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDfzCCAmegAwIBAgIBFjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJDAiBgNVBAMT
+G01pc3NpbmcgYmFzaWNDb25zdHJhaW50cyBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBALRWdlqDlLWqsR0om+sJgmRxE4QNnMkpzFQdkA65CXM2PzK9
++8cj6UqaHsEvMktB77yHztk2GhmEkrd/i6EAJNjxwBjAq1X0OhcFG4e0llZk1JaH
+50eCwZJ0OG92PZYAQ2l0d99/SvUTSEpZ6v/PmXDIiSS3vtGN+Kfbpw4S+3DMTduC
+vBjx6ibgsBYd68b4Oo0T+gYkKx2v+UZ8n8cV5WjVP0/Uy4tiQIU4MXUeNjZ4UKat
+zRadXVq5mGEK4tmP7RGn+5J+vukGq5TB/hg1+PvzY0QQ6TOLruuLhtGEwbTDZkz1
+uwiUqE7C4NALqABdICfwJonm3gjliEENTC8L9zMCAwEAAaNrMGkwHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFDBWvBURjU/GJsa1nKFw
+ktL5Tw15MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQELBQADggEBAFgnHD7Mz1Gz+3SEuPsr7PgtjvAo5hnRZHgvlAAE
+X+usbcykRvVsgwp+d2SZPgybcYQ6g1CwGtNS9/dEHvoLXe37lkBr3kmE2/kEdjZi
+IHEU1Oh9thXs0X+Eg9m3JJ8ZI0iLuWpQd7xHA+riTlJ46SLE1d1xGHPSwAxRi3fk
+US7X8DAxejxjGixWGF988Ib3NqMMwx2Jcs5pf3u8kUiulP/kyK/+jtiDfCIxIJLw
+IaoFs5osPraKaE5IvvDrSvM0k5yBs+9ZU2WMNoMSzzY3+jy5+OETQPszItgXQ40W
+Jt2Cxs8ZzBFnuym9UsD9m6IXe38eiJOoP2ruwmFn6uaNPak=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 55 C5 ED 9E FA 09 D0 48 D5 76 97 A4 74 1F B7 33 BF ED AB F1
+ friendlyName: Missing basicConstraints CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CAD484F46827A5BA
+
+viFe9mUnjZ5hxyfbi5pxNHOaVC+aiCJ7Yn2fjmxZ+NcjLb2Ccv/cVdMpSO0Soe/o
+vVl2botOROQMXAwibrL30AUf1rsN29C2e3SD9DOB/FLQpq9jJ9ZS4cktDK3phCeh
+MPsxjxUdlE8Zmhos36bypL5mhIaG0wmF6Fuz66y8rhpAj8zl8yNGL6DqNw6JgpvS
+E2i+FZ+E3CB05W6WSjOQOFexPNnWBbkjyeXrFTB30DJ7BjcVhjfek1+tItF7hYIA
+qhUFXT2kur8WV/R5J0bzXlRaK1s4kj4m1VFcmINHYiSbUsExpPWccRmFv3Qbc1tu
+/NhVdjbsnc/BI4FyTdW/sio31VviXjewVWIXxhCeqr7QRqCCluM0HeAEqZFPS6jf
+3F7p1VIxqgz9ibeJ0JyyYtRgroK6iYkVfqCSiCoWh6aJ7/pBPLGmCIIEppbEQKGp
+NBQIRzpOoKTLrzuOlGypLyoTTqAASnNNofgStH5gy+tFTAWl/sKGc1KLFht6hn4z
+XvkMdDYi60zV43nxLlneq5JudABiuC1of7SJCdAbDqN9+oUr0H+3vjDpwgufLvfA
+QVdhT9WhJZg+KLY4drqbuBHEbYQGA+CNwQvXW4CddP85kC0gEBF2pl1FsXrKTA34
+GrRn7K4vJDsb8tRP0wuOAFj0wuKwbuY4y8lBBbaNhJtiosR9ZBacIwG9yh++6dVn
+6lLzJczCF9zQOaSTtNZAPrfQo0u7ldmhBPoR67QOkg0zI1YwRJF8Y5BOI/0dSdet
+CyNhM5bGaQgq/wdi0i4l1UM66I2SIO/agRYVFZdohE/3VzKFZZNvFtDXSTNqaGqo
+GHhp7Ke/rJKoAWx2TcdgKjPDAMBtmgINrWCaGrjt9LDDVsrhE8hIki8vEzKGgUCF
+nmlzPqUIcT6OkOhmBZhW2UqzZAyYmltMq23MpB+xn8UPoYVV3hKohT7batN/mvqg
+4CaLA2vfYomCXE1To+OjqeuqpbSxVljjywPT0N4Mii2yWq4B/f29qWL8cxMl2mWM
+/h5H2SoO8FOr3Hdc/IrSH1fsJ9CUNL8YUKHgBts5B+K653uUy0qubV33OeqXC2Cu
+NlYxiGqkDhO5mi9Tuw1YXLNgXipxqiANOLPZOoaeCP5spOQgnpQR3pxlrxTOw7qR
+wbH+VSRBhtABMDcJsadDLnGTWUnPR1q86ehqpo6XfipZMg1gGnbmN6PNthRWVmtk
+ZPUhekPCWFZnBS4obeFDw4ZRjnbFN8qPE7uHZ0VL+qO1rOoGX6p/2a97l9nJTACh
+anm3AOPE/vWURJsQ8Zc54LLhPJvTQtSoxt+49Xv0oitiz4AB5d23XlQ4IZ+avY7j
+Y5ZXuQpQKdnZeG9eS86aiHcBJ3Fvwt/gVVIu3i/jRrNU8Fk2WyyaJ3epwII8wgC+
+A58NcMf6HxHb8NXufZOGWwUePr/VQxcS5EXBXbFnp9tQynzKS4qUAV4QIhb2Pv4V
+OwL0p3VD5tGlLYj7IWAe7tJcf3u0q+hpzuc5DalbQ08NMZv2vuXjfvQ0ASaQ7nVq
+Sjm8fxoY1CIImWqq3Atuo3Mv8yyx2OvQgp9YWSm7fn0HcSg5Iy+eZg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NameOrderingCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NameOrderingCACert.pem
new file mode 100644
index 0000000000..224d33f30a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NameOrderingCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: D4 8E 43 5F 00 56 32 DA 2A 07 B9 D2 67 E4 66 E7 F2 5E 16 8B
+ friendlyName: Name Ordering CA Cert
+subject=/C=US/O=Test Certificates 2011/OU=Organizational Unit Name 1/OU=Organizational Unit Name 2/CN=Name Ordering CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID0DCCArigAwIBAgIBBjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgZMxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSMwIQYDVQQL
+ExpPcmdhbml6YXRpb25hbCBVbml0IE5hbWUgMTEjMCEGA1UECxMaT3JnYW5pemF0
+aW9uYWwgVW5pdCBOYW1lIDIxGTAXBgNVBAMTEE5hbWUgT3JkZXJpbmcgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4Izk2uos/TlxMQIzTb0CugRjW
+JZgTFHdIYxEN2K6eCpfTkU3yFaIIsqC84Jwc6sCT/uroouCtnBsDvoMw9ExsfX/0
+wBKiXYZ0WmpD+cqNCmXJObrxsw3qs7fb55J9b+4sKMyBPea4hwOwpSpdnk/d9oY/
+QqBac09/+bqQZi4gSM2MdNweomR8fzh8B1IgNwuObNH30EuuNpjjQfwdfPt53HDH
+DlHAVDQgT3/2wrj/kWCXYeairC/r4IZFmCGPfWpwdFBy3SXV14yqG3rzAnOYoTvQ
+qHIhOyj450InVnCJc3f2tP157JEejY3KxxtFT7JCb232thWZz0FduNKKx1IrAgMB
+AAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQW
+BBS/SouBm02MFDGMW+nM3S/oeRJRUDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBAB1RfNIX2NAP+HC88I5JhXw8wDo9r7T051XcB+KVhbUfK7sKE9WXOq8hxsyQ
+b6XaSwDMIlbxWNAeSl/8O7UGQ36IWepI047Y6wCLMGsOINtB5FGzPsg27mgS8txc
+80Y8yyxNrGrztJJOPEjyw0fyfW56Vyjee2z96/5ETtJJMFkr1JnbITqdrXL1+cxJ
+TH9KgJVXFNjr2vAzB4aV0lHcd1JRpfTCB7nRt+ALRqjfyUJze5NI8TN7DseNgGbx
+UBD42AlUMC6aHyTWNytAsUabonJefRatkLzY6BpJ0Ewe8d2ztqIhkYGezCb+IXJL
+m6bBRwtJ5KXTL3kz3toqdTJedcg=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D4 8E 43 5F 00 56 32 DA 2A 07 B9 D2 67 E4 66 E7 F2 5E 16 8B
+ friendlyName: Name Ordering CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,AB3687F56B28B052
+
+2iZ4LeDKI88jUnITK4gw5o/dan2J/GfMGlCirQz8rITqLgUMBGwGqPJhnnwIFfQU
+7r+0RkFP4a4ty5B40YPAIRPBkNQ1boeabw+JaQORugzpBBowS9Gfm/PiZz/7PeQ7
+gcKcoaUKRySd5dosqBh6+u7a4b8YhI5xNKthXU1tmteUr6lwvxmBnMDu6rZf4f2S
+cB17apju088XOPi1blqwXIjnD4Jm167TkAhF47pMjJLyHx/oseURjKglQBHCkMfE
+lV+hySV+0lAA2QK8v1eRSmr+OaQI0lYDKBhsUqKHcNq3qqzgxF4om/RMvCpS/CXJ
+U7VPhnqgSn4HEhv7o5xJ5I+Hlhdq01WahzRoa7793oK+SPPoJaGcrK3659nhBURO
+AKBw/3royll2lldWZM6Q9hiJnYCgaeSxgI2R90zjn9m2vpP0+Lx2QLcKHf1fZLZs
+Z4sH6L61DW/hGpRJxdtG4ZHaec/0+Wwm9RQ+yOXPiyPpBa5wjCogkdis1Uv9tbak
+PJkwsAEAagdBU8W9NbH++yxyW8EB/2FA9WaY+qNWuax4hIMs22E9G1WUJwBQs4S1
+SZRDmTEPjGG/oBfTVwu3huxO81zMB1E4Be4gIwYb0hfLyDsDVPEbceKh5BHpGeJZ
+2zQeQy9bKogl29NHz/eov3QomKYvztGGK+jQW0nz4tzcQa8xEPkhmLetuM8iDsHT
+RGN2aD4Qgch8dPhpjyvINDa+MkwlxhkYvqp2HN7yOqvrdGA0YVFcW4m5oxYqOoEH
+Z9Og6qRoqMU1Jet8t9ko8Q9PnlJoO/vi5+BF0vzgBw76W7r0uE5Bk3QZlasS8BRV
+AxQjp4TZKTGdLWkxs9ZUD+JfPxPve+yKerO8px2XsNpBVzGw3iaCS2AMglvjp0qw
+l/cKD6LjyGuvYGK8dtN0Iz430f4vno5V+kLoFJfpF0fo3Dn+l3yvcsmco6Xt9+wU
+fYzVJllK4YSLC7C/LnX8Kr8pg+TC/oTw44MBdau9WKBwzjr40LaKA2HDWznaBTlg
++6UCybDdKkeD7PvBaWBPgqd/VR/6xc7v0Ecl51vs/TyE483aN/9YToq5dqBahf4O
++eRDzAmIY6JJ/GN1thT04/6WTjV9NS5rXPvO1VoYD2uumeLRxK6GYXI86G5ji8sN
+wbXl5kEUydTKJ9xsjTaLGvuhdPaXI9PXaC0+Ki6SGua75fxZIMrlUWBeywpE01As
+XfFCfjg4CXIeUR04aZ4nByU5cEhNRmm/X002c+NjiuPjNnk1XCag/6n7YKwUHvmW
+eeRZPu8jss2gR0tlgkR5IRYwO8yXJ6eXyFO5kbkeDKz6NngLj2z/Vo9CVxMOZc2O
+vLkHFyNG65i4kYm8f21X1SIimE9T+gGcpCdaePgfcVWxbejm7gIXY9zJBhpDsh+2
+GNXtBP0AtPGhG8avfUNgZb6plFGLfwIJ9+4bNgJ6tZ1dY5jLhrPKVflDmMo7JYmU
+uXpasIL6VKuNESYUxWACkVkGoaJB5NQUWgYHpb2N+KMbGCk487WMljNDaWDinPOH
+m4MGCthMhcQBcuuS21TWknSZ39RRuhDdPCJjWuDgNf/a9Kog8EbmXUFNv2kdpQmw
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NegativeSerialNumberCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NegativeSerialNumberCACert.pem
new file mode 100644
index 0000000000..bd925b26ee
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NegativeSerialNumberCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F8 03 7F 04 4F E2 C0 0C F3 2B AD 63 AC 0F F8 69 BD BA A9 57
+ friendlyName: Negative Serial Number CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Negative Serial Number CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIBETANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GU5lZ2F0aXZlIFNlcmlhbCBOdW1iZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCWz7ZliC4aPKhAsBsy0znZfbesj2UveREHH7BiOb9L3Q0rUODt
+VnQSmWVBb3GPz4kXejT51ad01LDy75YHWFSlSWSAEQC79MaawyiUj4gEPxDLx+fY
+INJNmJb7hQpze4e6sQwgYOMm0Z2c16wCsAzu2P23KMEFWn6hVQWj9NzNjdYSqkBK
+L+nOnnEERNWfsTjNJHiU8TPY4tDxyw6N89LDr4ulAYq8NcZp97PCt7KyqXFQrjBZ
+7saXv1faM8FMvCZOuQg2+SIYghpsqceDQLxO/2iNlmMASaQFBftLI4dVpimRp859
+cdHNPA2o5q26AhV5ib7qjlt4qHx5H2xQ9wq3AgMBAAGjfDB6MB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRi5C41xg/F6JHQC8GN3rav
+2ojZPzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAJgEmVAdEqm2wNErb2/
+Xj9gaOMaWrHhj/4vxtssSnwO1B/T3eq6nDngatSbtjItO1M9UNPX/tgSrXzHmURo
+Zoiq2tURPwiwWsYaGuvNLcZNAY7aTxLWNP+x6B33CJF3TRZVPskQcb/Zm+M6kM43
+fCpOe7i0Lf0C6nz4Zdg+Ej6G2/95STC+vkMzH+LeHtPeMKL0tCzTQMljsYVd3hzg
+c6TNjzsuY1IiD2SQYBAJ/IITEFELXqhojiNjFEX4XaDuD43gVe8DjX5PbXXVHme6
+QkDj8QytkxKpnhaibzxmTjhpDIDlBtnAIbJ8mcet3LAFgeCa7/qbzB2iAaRfYoMm
+ejY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F8 03 7F 04 4F E2 C0 0C F3 2B AD 63 AC 0F F8 69 BD BA A9 57
+ friendlyName: Negative Serial Number CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,96779EBEB0E22806
+
+EbKe+X6uUHMQYjFUN313rKUnO7IK8mf9gKaxIWDUK2qszyI4cbYMTFE+xsH76/3R
+GYf6czYV9ZQPKY6nUeP0jyPfHR6I/cB4P3e6hxIm5tuiUedsIwjiJbaCm37HgeLV
+VNV8gHgrSFoiX6hOfC/l7pzm3M48ht2gEqvdjaVljZG7B/NIP35t2kr/SOxTZtTD
+bVrL0UjnMOaLlslK+oakoCbvmo3J58IRq+IoTnjzWCYRr2bOZ4yrdbC2eYGEIWfi
+0Hm8vTIuRXuf+BCydgdP3Zpp1Zk0shY4kAQc9ublN7ZeDExHVX49klWrBGn12B+G
+e/DraPK6GY4u9s/GdY5WygSe60k75c83U3xidMrj7QCT2PA8B1Lh6mCc1Omb7ErS
+OhMWtAbAIyWIwTDK9AOieLm4e/QdD2PsE54QvZ8rYQC3S5fsYbAH8yGThJ6Ma64m
+sEYHxxAfD2koJYkt814ygDuGdtDiPtZ3WXU2Maa+8KvCx83q2G2gTahz8q9+yr+T
+YqY1SAt6W3isic+vrjVz4vjai+RdPVkHybhvHlTx0Xc9+fnBdBcNFq0lRKM4Onq5
+Ls1Xi+LXkYp8cX5iBt9LbENA4e1GxdfiGIjpHVa2Ogv8BLsHYv8nWteVjCzimJz5
+w1cWC/W8P162E+2wIdefq/+hJlsdzjFLvsOqG2x2koVvs4TxgiaGLnJ4HQ7FhhJx
+cpcpalc2pZUosyibuEI6EwazNV4WvyJiXdE5LLml2mAzOLntHDpx+I/eqH2DbTnS
+vNjzWUaUz83dhDKo5aoViXJIqxrAZO+0fkHL8o6MR/EamJfypHbioxTqWZaI/Avi
+eFeQXZOXvfNqMFAAW0Bjsn5KgOfPJfM2m7f7960mPlpWRrYfOso81UyJsXlbaChy
+fDyYLWyKnOEuQpSp1JU6Odu4Lk0pC/IrLyzVWpm4MvIF2XGr1LrY1GFCrqPUwy4S
+VF6fX6Uf1VX5jTiakQHRJdRiQTgjUSq7o8AIGFLVKEpVFhGc9EQ3gLXsmqxIleks
+vw694zpx1j2MVkUfOUMg7SYGrv2syQmZ6xvxi5pJ37j0JZsuws1WJKeb1CS0M4ut
+mW/g0/6lGjOIFuZ+JzaR1YyJ69rO398sFIcdfp0GqGFNaVkhsIfdw2tZFvaxRvoz
+7TQaQgZS41Ln49sll+29qqcE1rlLeW4XmPGCK/4tUsNuyo8XCcMTTbUS4xzeu15p
+p4WXfjt6vvZ7OXQJzUqtC9jIq00LxCvNph94XyXEROKbkxgAVs2YlL36DKtq3UI/
+Vat5D7ELfGB1FopELgcgsFbhjsAjPYQ+qb/ODK1iMfR7M2dRtHf2AiShMhAgAmCf
+YZ0vbs7m9f5ZYlAaYuzZQF4GpCEGS9iwWrZd6zHMHBPWfS8n44wTo+A/jWPfJ87l
+FA6NYFgd24XJ8hYZVptrRK1yuAZ43sQ7vuFvhH/TK7xmM8pCXpUn4Ec+0RbI4E0K
+p1sXCOZhTwYzP2oG7NrpHyCpDILgO0HzrP1pQA9Yh2GePVaUbq7DP4XVq87qvD2G
+UbUGx1W8S+1EIi3ODMssb3KVouRAYIXFddyeQuy256kBnzVZlEjLnQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoCRLCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoCRLCACert.pem
new file mode 100644
index 0000000000..fea0a3ece4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoCRLCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 6B 47 2A 56 0C E5 3E 2C E4 6E 52 8E 30 60 15 42 EC E3 73 67
+ friendlyName: No CRL CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=No CRL CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDfjCCAmagAwIBAgIBBzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowQjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEjAQBgNVBAMT
+CU5vIENSTCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPK+0hcf
+DWQf4Y/xcch0tBEFy8majp1UWEluOQmlE8rVt2weoWdZfaBF1cN0+brVFt0Z4U/q
+XqdQBA/PvV1yBYBlsgbgCPcJ0+Q8eeWESeKlt/TXoUl35JeNhz1qc1YpQsce78O6
+Qm0F73tvYD6hD/EFwgYqu3uAl2S6pCRNTDkhCBrRXcsjKZ071/pN+Raoll8StUli
+SiIgn/YHeIs/C/fQKVdAH7ZEq6fLfj+HPQLlRSzWGOXAqyca3Nq3nf74dbxWH15X
+RuESMGcIwaduE+26VSZcmWYpEKdR92GOE/X+WSGiU0DmR98pXoiw1MSip8A/QQC5
+WjIwZDIqN5k2h3sCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+dbZl
+p9ldqGYwHQYDVR0OBBYEFG6uRdP5/cyueml//bgG0kwH7AIWMA4GA1UdDwEB/wQE
+AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
+BgkqhkiG9w0BAQsFAAOCAQEAZ9m1wxVMGI0gYbsb28QvULx/Djy/zn5HsopaKobl
+UPHmmEe0LNUvqb4+3kqrKv8uWF9u5os56WdochV6SXaz17Yr6tmB7JeM/IL6VyqV
+Mqd5UNliAPjnIbO5i/wFXMd7jZwmAuZU7l4Uj2IEKyNJcBbgfD4TJZxtFVVtTCo+
+dSVYAO1ZjWpS772MXKmWqVeUpF23OPzAOEa8e7IR8l9zfHMlmohBxKyGTUvuwprn
++TS4ZVXrjjAHNz41aRzX+RYAUuNDHpWtFkuCpcU6FzcuzL76F9l0gRGd7onaT8SX
+ny3QlPHZQLJkgOVbsvn+eIixTzbZAI61iRjySWWbUguOCw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6B 47 2A 56 0C E5 3E 2C E4 6E 52 8E 30 60 15 42 EC E3 73 67
+ friendlyName: No CRL CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DC8376C0C95A435A
+
+n5BynILbtVbjzjbIfMjuMhFd06AsiRtmpmyp6bZSbu7vvGiIhiuUkxiYNZz14jJT
+QdfuD9hP2f85Td0mS5WVN4lXQpcrjQVpc3CiPF6slTQc7bv6EXfv8v0vV/5OV5Z6
+2YfmDkN273p4ytcRLJSYhMzntFKcIQ2F4wdPRsarcy1KqcJsSgneG0B920HXKi4p
+PoDdbSuJsCKVhNxJV/Lhf/53oVP0IEW/H0Q8NTXBBL9x/xLUVzuFM8gLMacoKISO
+MvOmWNv9J/TPp5kLWP6wtaZV4TKhYWB6gfn5x72L4QjHAOOPLtr/4oRUwXZq8enJ
+ixlZa7NczJrsopDvGUOWOSiYcqeRjgoUSOYC2hCGmzV7dBwxuAhETHXN2biXyBSb
+54Ruyswrzx9jTYbosVCng5I2tk+USx7dOiCaOD7PQ37uFycOFXpc9/i/X1brB26W
++176CGKu2JFxI8V/1ZQvAYUShF6YTD0pTnn8CYpuoHwiXVM2ofVES9BVGnt/JiRa
+jUEqr0d2tRICjU5w51I2H7cwEbOR7XEUONRthu3x1EJDxEF1ME3ziu3J0sF6gnzu
+kdzgUPv7WrjKe0mwtjPvEb+MN736hodRGrt6dROvq2GMDng0JHI+PBu4xpl0YSdS
+BjMDg2AFcpo4vKC+5qcHlvyhvNlTjjjackf4bw87KB4RV1XZaWBw5MyUhqdvKH58
+3yFXybTGN75fZKuAjkRYMXnFJvwm/DK0PmUcV4Fgt44lVGeYfbJJj4q9vjRWFZdJ
+WmBzAtLa02qEaRZfMIfIn+7/G/dPjb4lVb/YAfM0hWn+oXI1YnVLw+YIO9TLL8o4
+R65IgFBYsrr7YJ0JKjmnONsXrukoU2YvDEuZSffjIE373Go1kTKmPr8O/mJSqWq6
+q61jmjMt72lk785b4daESIICYeCR6fe5vm1uSDrC6AZCjNMirO0EZyd+Rk6+KEw3
+OD2eCvsMoqXfjgaEwPGeMt6gR5ipnDD8HuYJ0+Ntjas2clxWqjl1U58P/y86TwpA
+QsGo3ohWF7rPVj/hMUwiKphiNsNbiyvf2Ubh2xXS/Gnw+0i362M1Nh4JOeeVfOCC
+i3dNuDwonT2kbb7QS/OFN79jdsIwzjK+AUD7CNBy+mT1FKyH1UWqHydLVMhI6+Mu
+0Y14W5pHpWUnqqt+5gX7A/bNZ4Flfk+JS0lsaq2WZ47936goEpIjrt4bn8t0Mfie
+jdz1lZEV7LElUJ2akV4Mv9HMrakS1U7LySD/NGzyRW3ha+2nstu/JS7hFk+Jf9zk
+lr8SWV8L67SXxRdMekbXYVEJZ/1R9TWUnBSZEg4SKUGWygPMBgm802gKOjgzyOVK
+Hxa95RtEGdccKNGCcjoyHvpvYSLbZ5873zHYngNmWc3jV0k9mF6q8lwYaixgnaFa
+Bt79/zo7I92MtJMMSFsvAVJYlh/km1xPg2ZgzN6o2V7SvDcu2TAnLrxtDnBEeYB9
+8uUJxgdXxhg/hzV7lz8vz/agpQ238F9GjjafJpbyd+ZXyl/mUaXHVtd8uRsCsOHD
+BIVww4sQa1SX+/idOYzaeqMX/oyOokrOTwCHp75jrFU4ysqWF6Qv9mvLlHp8EfUY
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoPoliciesCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoPoliciesCACert.pem
new file mode 100644
index 0000000000..aa1bf01f04
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoPoliciesCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: E0 4C C3 A3 D3 2E B7 AA 3E 7D EF B8 5D 28 C0 A1 4C 10 B5 C3
+ friendlyName: No Policies CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=No Policies CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDajCCAlKgAwIBAgIBIjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFzAVBgNVBAMT
+Dk5vIFBvbGljaWVzIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+1rGRRtklAdQBZAIICc8jB889UiuPhuz42qkRhIXsu7pLBvoK6CJRcKDODBkxmoUc
+qkmyf2+6WIPK706gZ6ICLlaZJtU9XTG4+VdVe1hA09jjKmYQ5/RUoFto2Qn/jfqt
+jAnEgoiJuTpGbhMNcIqmUB8e9U6xF0n8wKRuoO352ZNmKkslQMg9IDTD2CTeg8UB
+Q5FIlTX+6ePUKgw49//7q6hdsOOsun19/Hc7zGfjI+ntqFpHXEL50sckzKVMO05F
+9qwVg5+4a3bL13QHFDUf71SqIaXyh3S2UkvSphEbyVz/XU5oF5mMnoZWsXn+QbR0
+gNqQlHGoqA7q5s78WqUDDwIDAQABo2MwYTAfBgNVHSMEGDAWgBTkfV/RXJWGCCwF
+rr51tmWn2V2oZjAdBgNVHQ4EFgQUQiQD7aVLdpyXmFx06gU6G/w15JwwDgYDVR0P
+AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAB5U
+gIV++5zaqU8TC9lSIq4uTTo+6Q81DBD7Fa7PWhFLqF9cKoZ+VFDnIPQVVhz4laar
+9Gtiz3Ix8vqGP6gPo5p+wpspJ13VF2YQqe61ZsOg0Mh15FETqEjvl6WZeVjdIvfR
+p6xsD+h3T++Am1eYNaAwieBZVi8OGRJGaMSS4Q2RNXs0vzT5I4RnPcYwzLQsE1jT
+7xkAkoNMHPaSMPAiQtfYHX2TqMn42Bp2CFuIIiDoZeKntLuo/vqKe28UW/d/uoUl
+1wE635wC9nhd+YzvbO6vVVjT77sz0H7KWbMA8kn3nx4HNNhVGC5CAtqtZKpQ71MU
+MnIgZeKsGC348hVKpRI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E0 4C C3 A3 D3 2E B7 AA 3E 7D EF B8 5D 28 C0 A1 4C 10 B5 C3
+ friendlyName: No Policies CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4D0B9931D6FCDB0B
+
+xwCEkfEtoqtmk8ThayVcASqeRPvbex5x7XdY71H8DaA2yx3xu9CPwRelu7X+wm9q
+vPl50Ym7nuva9Obnvk6ZYx3ox0YO4NZApg5YZDmQnlrg593vZf6BoiQft8DaqxMv
+KJ/0Ar8mDd97VRZNfd7Alqr33AGlLVdsq6FkXZu/GhcGMIibUgnzdU2bNT20MD53
+rlitHQIj4wp4nd4sv02tDeKWYii6xkxGaWNJWlGHwFBi3+pYJW9lY/6lHgx1LCrt
++pQV8t/0ORoCAokxAZ1O1UHFOlvryvDgfWYayUPJ4riZqLvCRJET44Pd1H0OnY2F
+9w123cxjeDF1IXXbpb4myQUeN+u2XBrQK4mjJbUKytdBhKLrx3ONkGDcAuPgcHHL
+PRcHxJSs0ESwKZ1YxJhMX4CqeaWIachLUIXZu1JZV1OkeU4tTv+JHbxnSqbjPj12
+E0v7oQtyAKVXILXPS19wvVejZWbJviQB37N7xTNe63di8bOg30UhD6/gn0/iSOfC
+3lUEuaXNptx8cmQhPrbVSTHcFlp8GghkLES5NIz8Dbjgq8HG0jQrNDnrlhwou0H4
+Lgvu3uqs70tlsa+ZNI7kTiRjQ8s3b0fKXN3h6UFMejW8bHvaMWakVlayyusF/lyS
+km3HGcu/rZx0IngvyrUvOVKdUy1qMuG+LO2eZCjB5a5Gjiz7FvxK00DQrGNArW7s
+Kw5HyHxL+Qz8auWbsCjsWC9l2lG+wvZwFHdjw2C5gEJuwSdrtnToQoDvqEVLq3xu
+kS+uT1MeF1NPRjyMORMKIWtPjhyJLyCBpjALAIFvrI8ENuGTqeaKjy6YE7WS03iM
+VF3pJbm9/iBquBZU2ZGKRCle4eJNtLVQIt4us5qT3qkz16n3WMATvXBMpxRutPHy
+1J38c7g0f6tbngQz2jEEq6d/wHMVQbOTu8m4JAMkBDChXWFeoh6DK6KNn0j1JOBU
+xxZhKDSMcLjQ5qTO8WHfC0YtnWwDyJH3pdGEq9u+Vur4Lo96/tKMoxSMWTa7HxT1
+qi+DxxYY+zcj+aBDhfRiQQrMXA5v7aYJz7rquQ1h5oJfsBz5pBAhPh531hM2N7Nu
+/dn81tYsX084W6z7dAdHYppM1Ovg96Gl+IkNA1MXKy8ZLMrMJtc4H63z+1MJHfxR
+AY0VOXlsm7iAB8IoZLYM2aeuY+Yu+Xm2yKs98a98SKzXsV8qQO8SLwk8sfJuHv30
+SIql4vepd6otd0iJZEFonDMAV/fnrUfxQS3gET4lkAg1bCEK6j1NZ0HwpRYgvHm8
+iXF4t2wmcnPncfn4HkMM6X60+v+VUZlhl0y+9nqDaWM0n52DjWseHvJu6m5qF0o6
+w7ABt8YzEO/fVNVVWPRMGjxCvJXXgxkGbd/5cYKP8BRx/N47WLTzaah3AqtUpZr/
+ZtazCnraXDAsGbvG3bSBYHOPLBrunjzKuemSSR/wvVPpWbdlcsGhLHp8T/qBsGwL
+EoqbmZY/bPQg4VGD7D8DH5OqibEn9yUdxzXtJ5kinteG0+r0onUVXS7onth441dE
+pwNbzPjBhR1syNQ2bKzZ/93hOvkxTLDjTyv60YISMSyQ9peWfpBW83M3aaSN/DKa
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoissuingDistributionPointCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoissuingDistributionPointCACert.pem
new file mode 100644
index 0000000000..9222c1873b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/NoissuingDistributionPointCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 7D 10 60 ED 0E E9 49 A2 C7 F7 2B 5F F1 3B 4E 43 13 36 C0 03
+ friendlyName: No issuingDistributionPoint CA Cert
+subject=/C=US/O=Test Certificates 2011/OU=No issuingDistributionPoint CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBTDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJzAlBgNVBAsT
+Hk5vIGlzc3VpbmdEaXN0cmlidXRpb25Qb2ludCBDQTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMCr+3UdavfOBl7iCrYG59vDPxixxgNXuhT4Qd2MRQty
+I9ncZ/36pjy08CrKmPWAfmVZqSeNOSSUdf+BFUfRhVlN7wNHa8UqQei+5WfVtBUb
+B+opVvaoswfaRZC5jRf6sPfP8j1WfaMgDTmaHenWZs2DolsuO2C6eGjvm2nYzQi9
+7km64+oqlTXI73rCKT6WWTqHXLn0oK2gBPf3sTSas2olu/WBu6Zp9M3CjbVV+VmM
+7lp8m2EJLNFrI0CMMLCdeeYyElJ2hFqmRObNqnhcWh4eUrp5IVm72Pmsi8/2EbGe
+BGFa/l8dwzgR6EvOLFgoVnGufXcsoR3oPiZey+JQ3iUCAwEAAaN8MHowHwYDVR0j
+BBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFLPLVL9qnfyfxzEO
+kgynR2uZAJ8xMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
+MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAINy+PfPJaZ5e
+hJYhM4p6aSvFXi02p8Jml91EVwGkZu3hwgreINpM+gL1N6sAGRPnIxx+vZyqMOoI
+X7q5TyjO4LjmEGb4yqWANzqUlsEd8nPE7n0jJyEk/fT3EJVnNgMP5tvnW+E/+IQk
+V8e1y345UWk0C7xw4eYUFqjE4jWRqxWLEzLIYOb5nLakI6k/aIfij5BXXQyYv8c1
+H67xMGr5dfy6zsy1+dJB5d8t0voJeYxhWRKE/YHxx81+1Y/Oum/5HrCsGIf07xFu
+AlXdSF2FDH+i/YMlZas1laFLoGxClpfIBKvCR490pQX+0tEihAsZuISUSo/SIp0R
+elkDzLq7nA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7D 10 60 ED 0E E9 49 A2 C7 F7 2B 5F F1 3B 4E 43 13 36 C0 03
+ friendlyName: No issuingDistributionPoint CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8A63FBF19DC0800D
+
+QhG/rbdcof4QsGqihybqEK3EGzxyQu+zRHl3/3d2Jm0y1ByDUu5h//BzYvktwwfD
+YR+05f6rIAQf9l5Ghkl+nT8SuR+P6H+kr7ZXU4H6dYxo5EETL67gBDdqE6pT+DWE
+9H0ez/ZwOMYCYPPrU/c6AQ1N1YSVG3cBoEM7qqkUibOIVWsd8DT1nDSTg7ZW+sS+
+PEUiwLeYmu+qWVCoskKTpNSFUGRe1Xy6uO7qDK7bWaL6WuMMph7KZsudkXJ30d3+
+77VufR+nJ23OS+xrOHBqWHdBBPUBK+zT0u+ocD/imExNBxUKfXvN0+N8Elq7zZzj
+DtjA9LH4CpmEr1zVO+RZgB4DU+7SB14EnaAUZiNFdVfGCQEk//wMkmZw5FUdDBQz
+oOLRVDSuis6VvLFgQgDQCGeQdFVh69je625W9vQnry896v++HX1jSpzHpnrepqyL
+RsRgWsCpxyTC2dO5BxZi5V3OH2tpdgCiPvxAU7yG7gHSwq/ZFBoMYHmJdLH7EJqF
+MeuZ9QAX8BrGY6qOremH0dyXri3pj0jUUDqMBk5AIBSaPBonMBKGxVSWilN11dGb
+222RJCnupmLo6f9zqtEyZqKpCTzOzGXenHrG4Ncwbek30EkQ38NWzwBYucDg6w8w
+Nk51h+8pseLO2ZN72ZIv9WhL7sf0EXal/rcBJxLnVZBGo4X96cmSnIY/UW58Bj4m
+Xtcl/5tMYNgJMdlQhNip9bd+1XIpcVAiYXZ6UneBbIBsE/UGMSvMjqUV/DQEsVMe
+QsCOz0TfezvzJARpF+TQogD65mVRDpzSwoTLk3GJudRHxURxKb0vPBVc28v5G06P
+0yAFn8LWebnG6vXsOIPXnrchMFSDkYU/mnptIqXVBPnA+2EEnqvNrrwm7JkwznOK
+dgBqubSvvbue/Syzj0gA6eN8Zf3ez/yj+t3WyDG+FNkDjtIfiJStkSAwS5iyU5He
+pGmG+LtjVZrlwHhlv9gVQDU1RbLensJ3+cauasDdbs2UZhB99Fhka7kaaMfNonpW
+7Ft5/FvFFlomCosg1MuqJ4Av4H4DMvPKJXVToaMn5Zhl8++c+a78Vnjres0kdov6
+n9F8716q2L/xiBX90G7PdlUfTwTNbokzIowIaKkyz2LVEEYHQ3qIJG/YA2YCzVX3
+vkLKGWWA5y+z2sVr2JucAOKP+qwU8kGCB0BzsEvxjL8ADwZ0wmmWhxhJXIVzHVfM
+4cMKnW0Q2mcAEr9FxrccFSj/JNfo1EBqbKUEOyqeU+MkX+80yyorXsNiQsA6sK8X
+njrck2cwZOshKCe37n399spt8ZBByu4zmTw8Xvy/BiGvRlAoZEgld1KEilLWQtVB
+0rr/rKxCCJoWbaF/Oqr1SSl8yw5TGdoit3u/Bm0YA3ijruOtNjtYXeJRhj4pN9Df
+aFtCtLHpWvNkEYw4WpZD7CFy6dImbqkW7b0+Khg9xEPT8Rog1P97ltN+MqVRqJZ4
+8Dnomm/C5Ahsn6WAh2/WPyfxGXTULPia+jpDlpMZP+NpZNDDNPOHBIU7/I9F+n7U
+JqcDwyTBqGooGtm6z9Kz1ccUxj0cLl6B61AfKaY9OlR5sdqIUyPIJQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OldCRLnextUpdateCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OldCRLnextUpdateCACert.pem
new file mode 100644
index 0000000000..0ec4b21b6a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OldCRLnextUpdateCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 06 21 29 E2 38 20 83 13 82 97 68 45 39 02 F6 E1 06 EA B4 9F
+ friendlyName: Old CRL nextUpdate CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Old CRL nextUpdate CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBDjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAMT
+FU9sZCBDUkwgbmV4dFVwZGF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAL9dKBLjox+erXrb2q/rdAlXUWqvi4uRcldjKQjs+z/Egt/Vz3XSzOqE
+JVFUojykLto2tYO0C4ZM+FGnn6b438qsXkeIPU+WGv1eNqi7Mm0miU/+JKXnCDMG
++Aq+GQSK/1JoQbusbFR1rfhU+a2rH1eMbnclG0CuknK9jhXc+rhR3GcfW1ZC+0rl
+LAjH1CPM/uwyNB9th87sU4FJ1PpzKa46pgB0tCIZqDw5vAMWn3vllBvMRtvVQBOR
+GwmkewDGifBJlvI3IHsEwxvws+uBoGjni/0cM1Zf/LZkjZYdbEalLf+a0uAqzdyv
+VhPCKYwrJP1H85ubTpFRGajNw35h6NkCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFM7aH9pazI6X+iAVKU+slo0qzXgT
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAuSS2lcdw8wEVWsN7SEqN/PFY
+fYY1/sJLPGnE33ItquQhD4Ab9+4b7o0hq6VWkomiQCos0lgrBhQyJgjiBSB3zjAp
+PIYXQp7kzXx0wo3iVhxVITv0MfEOfNbPNP2etUs6ivcOXcO/uxhB1rJvgs/xSzwv
+C1waXG33zCQcABSSHu6Ylkw6xkI16W2nbqbySz1zoilVthP/ulrVB1IffCyrB5Lk
+LpY3pV7O1ibyHjmpOliTfyktarUbJBXt9X6m8oWIRk3p/7dl/08oXD7bAFk+19L9
+BaNzLinwKdp3GvvI3SzmNOtUiweQ83tNJig0eI7YDTeHlfPRZE+hccTfw5DdSg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 06 21 29 E2 38 20 83 13 82 97 68 45 39 02 F6 E1 06 EA B4 9F
+ friendlyName: Old CRL nextUpdate CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C60F4F875B4AE07C
+
+r1mixPIe6yhRKt7pKXN2rL0IbT3xqH1GydMztUKrUSYezhqkuQsw114en6v/1WD9
+RlfiHQvWp1eProra/8t6nVDpRdnrKGwCm1ov6Bxm6mkBQ2e70Wusl0N6Gi8ACjEm
++uMv8WU7ofPAd3Zf7LSdhLwuOpL2/Z6St+NfLU8MMch9PmegwBZ57JcVCPuHT7d+
+1W/k7GSqTfbof7E/A20CajhrzWjkDB0/0+zCxnfZRgy/kF9JJ+J5O0/90/VZQelv
+FzqG5M9ReSxGi+6KHVShuNRke4vPRAFkH3/Uu9sRXHFNcb5GbdxAkxNfJ+3UVegO
+rCdf6bp676QKTCGd+7V/e7gFMc/w1TScYAzU1JDT0qt2hbQuO3Ecr+UY8u4WZGiy
+x/ICs9hI+1Q+bSDRz7t/ozCLmmiRDExw5zUi+xbjbaBSiX6AdcYP4ZpwQLp0Yy1C
+A3lvY9yJGwAB5A5SIrJGnfsqlqg2Tv0aobIANvLzDMcduHuv546mDaiBXPnm4d8v
+gwsDZAaGJmCVDoo1O7Vv8wVf1YYFBTyuSznhj1RQiZBLKG+kfcBzADnThWmxXCQb
+GoiionyRwtLueUuBQLdfa3dywn2SFnd37QFJ3/ditUvWwSs5NLPFSNYsAnw42B3P
+GVCaDXWB8RZ3qnAIrsByMWLox7bes5zndblMKHsveZBWpjQSclqXsvm9vTYH7FcO
+gqN6mhv13G2kP962VUDEu+I083DFBN1BwqWU8qEWCv/qUjRKRg7v4ySC1vz4QeMc
+IfoNqY/CmtgNVx6hWQL+1x9iYPbG6yTxwuu3ke+qmnHkCrAEtVtZNE8Es6iFdckr
+lYMSSl0CmKmU35Es8OoLVVBnY0F4G6+wM6nRCnkFP/9wQk07+bRszz0G3vdv2eX+
+khoD4fs5o6wn7qDuus8peD4z7F7TKiTUATZgF0xa6zKDkAIiokrlaXxOArU/D4ky
+g+IP3fbR6m+3VWt3IMZ6IEWU2ZlzsUBkpCsFvGKLTF/Jos2PeCoPQbVu4eaH5vEd
+RhHL2tyQEFDYA1mLz8H0NFqFw5n0la+3dzIBQBwGU8zTkF7Agaq4FHo+o6JykI1K
+FDLW5Kv0aqO21SyJ4fiTSl4nsD3i9FeL8d8LIQim89L7GzhuVfY9tdk5GUV7D8Vg
+1I4mkISYYTkOeNwo1Bq3yxpslnMaoU/+TrvfvIrtfoozutLNCZmhFCGUzlriHPQ5
+JAP7rBKdhQdG8iBYFyq6hCjnDuAE8BoeuQEhHLxb0nefwZxv1CdS8pr6hVDRiWLy
+C855LiwRZzMhWPQINUnqpfdzVUNOeN4dBsbyuEHgegjXlmg+5K2g29pLofnvQP21
+5uy2qS/e4nAKmMIEMf5BpHjl9cuZcgGlz2f8QeHBC2rsYesptL3SaOukGKNHxUyg
+hWUEY/kMz87FMSZUlIIeGKfH/PLnSqmY2Voevkf7Jq6yxOOZT9uHMYBRXsDa27Lw
+kzn90KqeSvvfbciV47a1X+UVklepdl8KzMM9yFJsapyP9Nc36c9b3Jv1X0i/kb/s
+eRcv1pYK2LrkID+G+WUJJKgEts2qiVwmNucWFh+0xwWmxsSsCr5DyQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6.pem
deleted file mode 100644
index 85f0b79c2c..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6.pem
+++ /dev/null
@@ -1,214 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P1234 subsubCAP123P12
-issuer=/C=US/O=Test Certificates/CN=Policies P1234 subCAP123
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGFBvbGljaWVzIFAx
-MjM0IHN1YkNBUDEyMzAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFIx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUGA1UE
-AxMeUG9saWNpZXMgUDEyMzQgc3Vic3ViQ0FQMTIzUDEyMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDSpQwaDoPydLNMC8zANHGCiwSSV/p+yyB92D3cy4OofA3o
-E/MneZrL0kkAoaM3sxpkniK7a37+ghg7ydyUw5n9CRxAyNMONSetp9uBB9X1+fZy
-9JVVK2W+5ycWBDxh2YOfyFE/wQBbJK7rIIrqtgUgNi7O+6ppcpbnguodB17MZQID
-AQABo4GLMIGIMB8GA1UdIwQYMBaAFLZ7gxmIHEmBIEPO8oJM80aGKITZMB0GA1Ud
-DgQWBBTMtOdc+dU31FBVf7Ixli7kkaTEaDAOBgNVHQ8BAf8EBAMCAQYwJQYDVR0g
-BB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIwDwYDVR0TAQH/BAUwAwEB
-/zANBgkqhkiG9w0BAQUFAAOBgQB4KomH+VcsPxXsULBeuMVL7QtJMD6RoGaCHnL5
-NCdwpt7QE3TVRnWgL88gSXtmMudJ5QIb3ko7PYOsuUhA/6YZvoBvQIdJAnprjYbr
-kxDMfK3PoouD3cQncVSz4xqJ9VcIaH6/oAKGpDt36xSUY2uqOHb1DLO2qmKiStvW
-Cprikw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P1234 subCAP123
-issuer=/C=US/O=Test Certificates/CN=Policies P1234 CA
------BEGIN CERTIFICATE-----
-MIICoTCCAgqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAMTEVBvbGljaWVzIFAx
-MjM0IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkGA1UE
-BhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhQb2xp
-Y2llcyBQMTIzNCBzdWJDQVAxMjMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-ALs/TklxdGqU1GnW9LkoRaacXCpRHoy8tYpTUbUhznd5fkjOW5Dyc9HK7DWs8q1q
-aAvU0KeqAEtguNCACjKFeXPyWtQuYKRB5o5G1WXcqy4pYK2CCHsyaa6hf8+kU1Y/
-3VcEuHoDX0WFJ5JFlaRERNagLbzDTjG6KtM4yhcEnTHfAgMBAAGjgZkwgZYwHwYD
-VR0jBBgwFoAUMLt5B08Db7IYg3poQ6v3TKFAcQowHQYDVR0OBBYEFLZ7gxmIHEmB
-IEPO8oJM80aGKITZMA4GA1UdDwEB/wQEAwIBBjAzBgNVHSAELDAqMAwGCmCGSAFl
-AwIBMAEwDAYKYIZIAWUDAgEwAjAMBgpghkgBZQMCATADMA8GA1UdEwEB/wQFMAMB
-Af8wDQYJKoZIhvcNAQEFBQADgYEAM38BPBwz3qjIhPI9byaqLmDkw3tA5mxae/P9
-N6WYYwW+Dm0KyjXs9SQZ3BlHDl/+D9dJYNScOXjKpc3hnrAUT31rGyhC2CwV52mt
-xGukdJIxKOQgucIylxyxF7N5x66TyC5sxJGUh3sjItg6NAOQGMwBwKOz/5zNTdK6
-qDuaEoI=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Overlapping Policies EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=Policies P1234 subsubCAP123P12
------BEGIN CERTIFICATE-----
-MIICoTCCAgqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHlBvbGljaWVzIFAx
-MjM0IHN1YnN1YkNBUDEyM1AxMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMF0xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEy
-MDAGA1UEAxMpT3ZlcmxhcHBpbmcgUG9saWNpZXMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALT4JJTriZO8+53ZvgYrbg9m
-azzLgmYzgvBJ8/IvzLaXsCv7sw/M2DU/CyOdIPy8g9XchC9QBJrAI65Muvlpf8a0
-CGqWH5AQElXjIkicPMgfC14xd1govVHxaRIrM/g6zNgGPnSivMXOrTm6fMNphEvC
-CnG+SqRQ6oKAkO1k7jWxAgMBAAGjfDB6MB8GA1UdIwQYMBaAFMy051z51TfUUFV/
-sjGWLuSRpMRoMB0GA1UdDgQWBBQLhzG1VDzXbIBJ1rnYkrn+iSfrCTAOBgNVHQ8B
-Af8EBAMCAfYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMB
-Af8wDQYJKoZIhvcNAQEFBQADgYEACuuacGsxw8Rq6HznT/dvzsw93OA250kOCJei
-8VJbyNw5x61+F9LxLZSBUtYgIfCOid3gUBe8MU0W1r8Qpg1PD4Vgq76l5IWyvH+K
-ACy4A7XpJB8a5zF7OUGexEkFC9RQ45PJ6i4JILtMeMLTR7c0pCkRthg2CW/vIc6a
-Cs1zrEk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Policies P1234 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICsTCCAhqgAwIBAgIBIzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEUxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEaMBgGA1UEAxMRUG9saWNpZXMg
-UDEyMzQgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMUyBhDbDKsFVn2a
-KCxh5Y64ZiH8OTq134EGg3NL8l0mqcA01qEhLCasHMR98sd5xKPtNEQB0kN9jf3d
-Zmv4gop4bAAqPlhvkcJ/KUMPLpLdMBT+1xLAdu1yKh7eKpoIo9vfus0fjH0aOWhT
-Wa7rCSuf+9I6DoDk1gC1Q9k57jDFAgMBAAGjgbUwgbIwHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFDC7eQdPA2+yGIN6aEOr90yhQHEK
-MA4GA1UdDwEB/wQEAwIBBjBBBgNVHSAEOjA4MAwGCmCGSAFlAwIBMAEwDAYKYIZI
-AWUDAgEwAjAMBgpghkgBZQMCATADMAwGCmCGSAFlAwIBMAQwDwYDVR0TAQH/BAUw
-AwEB/zAMBgNVHSQEBTADgAEAMA0GCSqGSIb3DQEBBQUAA4GBAMoj83UxGqz/rAVr
-SXl/vP2tx92XqrJj7UYRHcHHcTodTHoJ3j+m3MUHwwsoZrqvnhS1HtIqPQsoD9DD
-8Qg+uHFd5EH+Js40QK7zU7mHBOI64Kl8T8xrpgcnlLgXpg2H88at02UvMTDj4Lix
-ANfajLNnQx1htjJhMY3zzIgPApd+
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P1234 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:30:BB:79:07:4F:03:6F:B2:18:83:7A:68:43:AB:F7:4C:A1:40:71:0A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- bb:b2:2e:86:63:50:7a:60:75:e3:ef:14:96:e2:19:21:90:ce:
- 61:fe:2a:1a:d1:37:59:b0:8f:3d:fe:c3:eb:b9:87:61:3a:7a:
- f4:ef:3d:46:ce:ef:e4:a7:de:a6:7f:ff:25:1e:78:bd:df:4d:
- 8b:96:70:ac:47:8c:e4:77:1c:f2:94:3f:bb:36:18:21:35:0d:
- 10:d9:69:b9:80:42:d0:7e:81:15:55:df:6f:fc:50:b2:9c:b2:
- 53:0d:b5:0d:6c:69:55:b7:0b:65:84:7a:13:9f:74:8f:52:49:
- 58:2e:6c:bd:b7:19:b6:34:eb:d3:1d:cc:08:a9:3f:07:04:69:
- 75:e6
------BEGIN X509 CRL-----
-MIIBPjCBqAIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAMTEVBvbGljaWVzIFAxMjM0IENB
-Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAWgBQw
-u3kHTwNvshiDemhDq/dMoUBxCjAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUFAAOB
-gQC7si6GY1B6YHXj7xSW4hkhkM5h/ioa0TdZsI89/sPruYdhOnr07z1Gzu/kp96m
-f/8lHni9302LlnCsR4zkdxzylD+7NhghNQ0Q2Wm5gELQfoEVVd9v/FCynLJTDbUN
-bGlVtwtlhHoTn3SPUklYLmy9txm2NOvTHcwIqT8HBGl15g==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P1234 subCAP123
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B6:7B:83:19:88:1C:49:81:20:43:CE:F2:82:4C:F3:46:86:28:84:D9
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 45:d4:de:34:51:48:6a:d1:4b:e0:d7:2d:55:52:e2:e5:8d:a5:
- ee:bc:a1:c6:44:0c:9d:b7:61:cb:a2:1c:58:1d:03:a1:cd:8e:
- e5:9c:28:00:4c:07:c4:0d:ae:a3:b1:c8:aa:8e:8a:59:12:41:
- 57:b6:fc:db:34:10:a8:e6:c9:cb:0e:5c:28:6f:b5:3a:00:70:
- 9a:a9:ac:35:83:47:7a:02:24:69:46:26:63:29:0c:c5:51:c3:
- 92:c6:c2:6d:cf:5e:b8:25:eb:d5:b6:d1:62:87:3b:9b:24:6a:
- b1:9e:33:a2:96:bb:14:74:21:ad:b7:7f:98:ab:b2:6a:25:2b:
- 0b:ed
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGFBvbGljaWVzIFAxMjM0IHN1
-YkNBUDEyMxcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUtnuDGYgcSYEgQ87ygkzzRoYohNkwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEARdTeNFFIatFL4NctVVLi5Y2l7ryhxkQMnbdhy6IcWB0Doc2O5Zwo
-AEwHxA2uo7HIqo6KWRJBV7b82zQQqObJyw5cKG+1OgBwmqmsNYNHegIkaUYmYykM
-xVHDksbCbc9euCXr1bbRYoc7myRqsZ4zopa7FHQhrbd/mKuyaiUrC+0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P1234 subsubCAP123P12
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:CC:B4:E7:5C:F9:D5:37:D4:50:55:7F:B2:31:96:2E:E4:91:A4:C4:68
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 5e:89:62:c5:3b:e0:10:f8:22:cd:fd:e2:44:73:c0:23:98:67:
- 89:29:67:ae:39:3b:53:4c:02:24:85:6a:37:16:1b:a0:c8:fa:
- ae:0d:02:27:ed:3c:06:8d:e2:ed:35:53:a3:06:f4:a3:ce:6d:
- 63:d9:86:33:2c:95:ce:47:95:2d:7f:5a:f0:a0:68:79:5a:a8:
- aa:12:5d:79:b9:4a:bb:a2:5a:85:af:39:1d:aa:b6:a0:18:da:
- 39:f6:0a:00:f1:0e:2e:fb:62:1f:6f:2d:d9:0e:b7:da:0e:a5:
- 92:1f:fd:1c:60:73:7d:48:f3:9a:73:2a:14:65:78:2a:9d:7c:
- 88:5a
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHlBvbGljaWVzIFAxMjM0IHN1
-YnN1YkNBUDEyM1AxMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUzLTnXPnVN9RQVX+yMZYu5JGkxGgwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAXolixTvgEPgizf3iRHPAI5hniSlnrjk7U0wCJIVqNxYb
-oMj6rg0CJ+08Bo3i7TVTowb0o85tY9mGMyyVzkeVLX9a8KBoeVqoqhJdeblKu6Ja
-ha85Haq2oBjaOfYKAPEOLvtiH28t2Q632g6lkh/9HGBzfUjzmnMqFGV4Kp18iFo=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6EE.pem
new file mode 100644
index 0000000000..3d5325d7fc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/OverlappingPoliciesTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: ED 92 6F B3 30 66 FE 5D D6 12 7E 34 D2 4F C0 DD A7 7F C6 71
+ friendlyName: Overlapping Policies Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Overlapping Policies EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P1234 subsubCAP123P12
+-----BEGIN CERTIFICATE-----
+MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeUG9saWNp
+ZXMgUDEyMzQgc3Vic3ViQ0FQMTIzUDEyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowYjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExMjAwBgNVBAMTKU92ZXJsYXBwaW5nIFBvbGljaWVzIEVFIENlcnRp
+ZmljYXRlIFRlc3Q2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw9FQ
+t2aGcDvI7U42QCqMgObhOhdJlQWJSgI6EpQj0hEAvhPULpSpC3pqiRnBzmK86R7j
+zEk9TxnGNYFqDS7xM6Mdkj+0rOKmnzVIycEFrcQLHxglYGj8PwSgtvEq/fIuebJZ
+KEoS/jCrryVGnEUY4JWUNg4bqOGDSFTu0JBj9lSKOOH3gh+p9rJg5Hwc+Wbjb0Sy
+8pGRGuSXsumSugGqHKoxSWfErrnTQRcls7VqJ4y8MJwlw99q3+Xa0aVOwoi3ocPM
+mgArtDN0rHbP7+4tNcHsIjl/2WXUokGUn2/9GSW5gBIOJw3Nd6hvtOS2nlGf/qUO
+KM8j/wjWImLGF8MjkQIDAQABo3wwejAfBgNVHSMEGDAWgBRO9F6h+Qgwe2WsksAR
+CyzTtJYHHjAdBgNVHQ4EFgQUkrgz3HUFQnDN7aMnoK34budYbUEwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgH2
+MA0GCSqGSIb3DQEBCwUAA4IBAQBikCXaSOKIYSsx3TQPKgbpM0QMvbf2ios9BSNw
+uJv8LFXz+bxFq+7x5GyTxGZ3KLgB0hypILu6M6RfRpAuH6eRJJwuXfXM6w/y2uqC
+wqNIR5PwyWosBjqtBAUZZf6/VVU5Xd6BnpZ73jBNxxcgJ79svcw+6AFPXlcygLjY
+dhugLPhA7BNyKmA9kxRrnp6kCLh3dI1q7Qpl55Ytz6YuyCAHe3NMdC1Ee6c27RwJ
+GfCjDKhkCB/LSn3jbU+y/9lOSaMRSkAPKn+dkp73UpJnJzX57KJb/XE+q6R44m6h
+FNknITUZyD5S8UuF1g929cjBj+buejxo3P1jxH9Rb1+9/REV
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: ED 92 6F B3 30 66 FE 5D D6 12 7E 34 D2 4F C0 DD A7 7F C6 71
+ friendlyName: Overlapping Policies Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DCC5536BE51EEBFA
+
+sTrmnRG3b+rHlW6MI5TX+ZyhauWPiSVXox1qksQP5vC2MH3pZm7DTmSxRLw01bWX
+ilEGhAyYxi5oX10rWVlEvuTOuR1zbHcke/omUGsyWodDaDI+sF27FvCwLIP9pEar
+OT5rKsYsSzXZePBW69uSyBacplqW53rw7StQ7fykOHufIxbUKmyl91RqlXCMEKjg
+HzOEKYpQu/5w/MJQ01KFdAjCgIewz5gCreBhnPlT+BIIb+sAxbqELXTsYY6dQy1a
+4XZr/lB4O3WshqEgrBmUN648iOgabEr8a6umGcQzn8nRNXUQ76pGD8SrYs5KXDMw
+zFZznVe5NM3pEQOuJB5f3XuKgDzsMmxmkGW7cSlETSLK9q/k0oP1FzPjYd3KxvVv
+wgqkXJeFW3lzqqqb1ppVQtH1GCcp1/HzKWyayulTxNF5xX7oA0hUdLirgUWzs3cp
+VAMn/vAtRFmdD4WZ1fSse48YbmpQr0D9PSwnHUYyMn2X7TPid1OcnQZ0wb46T/pP
+taZ0aNctyDFY1y7H533osK7YhUVHIPkIOOBAtvevPE8LB3VrZGGOf1TQlez+6P2Q
++l2EsguETB3lprKxy1jy0TUZp9R/GXqeGgf7p86o0C52VemiGWO/O19/nwd7lMzO
+Xcxz80nTENB/EdRwPVKtTWcER6EranArYgntW7t0WQOb6XOtmczwMS63K5Bfcf55
+Vm2bLLrjuuKAAMt+AIUM7xbkAKlpVqS6RcfldP8iD0mFxDHSjjT3KIcCF0PLtauf
+pc1q5c/za39VRiuNSQ8yJJtMEMINb+dgXSMY5UQTdVwWxvykRtOssVd2Spq6GSJP
+MnjugwasKNcgt+lzs7zRHbOIcox6rX3Ly4vgpqMYCrSpqQXoAC1WTBlRr12cWnsT
+IwbKvB2STGA/PKgIY1KkSQtfKhGIQr/qULm8NpAwwGcgHoaoRkNgXR2yZwtv0WDK
+E9x0LEQBtvhp5wIVPTwHlG8iCx5e35kGJNTNivzeITgw2wBhJr+xR2N2dL4B4dqi
+6Ee5nxlBLRk/oBM5xGOcLItj1CTsckNOiaBOWuI0CP/le7myMCiQqQtViASci2MN
+/aknFttZlf1yaDNfuSnVS3TZf7FzxD249ZCX0ZpKktRNkDnUsmw6MHzzIJdQEgUr
+QxaYyAIU12rR2E2LbzUASEIzSFdGx7SeC4oO++3qcrIOA6vsuzqHMoEyIqOhmpZ0
+WWjFOffW6ffVw4YMjavn4SIT95GeNNfftLoduWJZzBcfs1U3ziWlRIwcPWT7jlEK
+AvT2uQkKFhgcEtXbrDyWn6U1Hh4/a7eoSVpZtadB+KsbvoeS62OgNymUDdjQapIx
+dtZwo0dTzqlXKrYD3yIUcik50+sJsC6aInguWDs6xqZgE+aQd2p5FEoS8u+c+Ftq
+TAkuS/BK791eqcLduhmdAciut4pVc+xmc6WvD9piL8W00RrzayrwCvWzdVLAzdZ/
+bOiFUG9fzlacfT8tKYs7TD+BWLw8xT/yLAjiaQSjm7jz0qc3ExpkP1S3bBv1rxHK
+LiBN3mwDQ9SC+jRSRR/4v/0THHc058VaoRDecl9u5Q3ItPrVl76VvXuIu5m8jnx3
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3CACert.pem
new file mode 100644
index 0000000000..b368687f44
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3CACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 9D 3F ED 42 23 33 E9 57 BA F9 4B BC 08 49 B9 4E 65 3B 44 79
+ friendlyName: P12 Mapping 1to3 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDzjCCAragAwIBAgIBMTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAMT
+E1AxMiBNYXBwaW5nIDF0bzMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCybxVTY2ahevfz61NSr7Rud7Bmrim/64S25e221g2bswm3M+BTZ71urQ4s
+JsDgpAew9ULwmJPjMBLbSqkkhld/X7p0q9ffmO10Vbgv5BzOHw71pnxP7qQlb6Tf
+F1pDlYFDhxBYqpwxmvtgOuP5XgqlkYpCzcG0fziyhL/EmgOLR4FxaeiTejMvJEpo
+XnN9El0THTG01qtbT6ZwLgz93yo3bxonxLRtQZtvkR6pjSJ6XF84IsUPY1CDoFdA
+8v1Syir5cEHxYeSSkH5yJSf/KwZ+dt3NFPZDk1VAIyFqPk1UpgsG0P41UavWPetR
+jrCB+1aydTyuHovXCrPof65cAbs9AgMBAAGjgcEwgb4wHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFPz0jWEzMoB8fTWH3l9S+2nxHcES
+MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAw
+JQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIwJgYDVR0hAQH/
+BBwwGjAYBgpghkgBZQMCATABBgpghkgBZQMCATADMA0GCSqGSIb3DQEBCwUAA4IB
+AQCQi4Yo6SjeCW1k/l7Txpz5pQjamJUDfBmgcr6v8n6RfCN+1NoMXbXX1hgti03O
+QsU+HAnZpB1B+2GNeNdtN7a8SSutKt0+ouswvZOK3w/3rC1AxJ/MIDMk5IvjBonu
+TBnSQIIvLIWsXcub6aEEG61GpG7cK9GnMeY4NxUH3YIIPDJs9nrrcHEaO78s+6+/
+rlt8+XuH4h2m+xv7xB+7GN8KKKSH3gZ03X1QpayGiw91rDX52O4EhfAQcxtNfX07
+9VvpjEcfn5Lpbe6p8BfkziM+TVf8zZmbfwR3mwinTdcLBB8AxENAbN3Oau965reL
+23HfMPn6+Rf8SYguskWt8K0W
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9D 3F ED 42 23 33 E9 57 BA F9 4B BC 08 49 B9 4E 65 3B 44 79
+ friendlyName: P12 Mapping 1to3 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0E0CA028EA0BAC29
+
+Y2V44KvZbm7BLf1cweYyKkbNiQGtg4aDqH1TkMM0zzzCoc2Kc92wcFaEDywvs1GM
+wu7LI23hK9lUYkMHKT9lmTtclY3bwYT7//1M5Je3RgSF8h3vYXCl3u87imkIkuGx
+HwfdHUgFXmaLuppKFFZ7XYVsSDpYOkXDTzNKEymmSIfh2nldK+Ud0JIU4vrPAwjo
+Y1/R8q8XtrGInYLLeLxs/igDklJfD+QA+477w8lYJhbutuDcQnHG/1R3+GkbSekC
+K0sG4E/cIXy/IYJJRhTOgmRSEdbqbujBZHpyhqlNrsWCDZKiMuMUBrdZHS76y2/C
+8UfsYqDl1uZ6YhODiUh9agvRGW+w+ObqYG0JAhcg8TzwBoqXlZKKBnY7NuWUMtyo
+1bX80YvzjTR/wXLe1Wm1Vlqv1Zx+pF+fgiN5UcskzeK8YnqGwl1A0gl20+diykc7
+VlZBBcw3QRAFll4LPUavgNdZYpZbRzZz7dfq3rc3FdrOTMkdptOJoxCxwErYjCu4
+Mgh1yCzsAYgVnHUzPkv5p9iZtUaOknssq9kx1b52xa32wBoTskG7MNMVWGzYPoA/
+YMwrKsUXS+0kxPKjZITaU6KKNZ/WWzpmGlThXrFzrQotBoAXtrAz/WYLrnQhwA4d
+vvXZX9c5lGrvlMceXF7S8idEj/dhSh3F5f5H1jpPj8gLm8axxSpVzIzipe5rckwQ
+Uci/Dc6Wm/OZks8CTZJaj/GrT0ado0OWn6G3ZYt1YCZepcHhASAxTIJhzdjRqhC2
+GHyhj3C+eivoz2yojemiAV3FazATcWyTOvjA9LYPbtjCFzSTXAVf69NGZmpsKgpM
+xdRG9D987rZk9Gwju92v23zyPzTKFIE1DOkhkccOI4pht7zh1wlrBqn53Pbo3mA2
+yN7hT10+3sI95GDrq54ucPCyGBjersqFGrSvfgmZkcn6SQh86dw2Mpu3i9shyJpW
+F7/lMycuIW7PPueH340ca3SKkgLKMPAlaqimMke0S+JTEtGm9/1UWd+23eMBThsq
+EqwxapZoABAWcfg+n01urzcVXTDNVG8qNacQ4//eWjpTA1bTEcaHXzC73YdBSqSn
+TQkUVAaoQhUUVzelg2HvoTYwkRGpvSkrVOwNN+WbsWLa02k/k0r9GKW0ObSGPCCM
+1cZgU6xP3PRhlXlTiXcNC4cl8pj8AnZ+PEvLPi6wL+Exxq6bpKN41NAF7ZBbAj/W
+pRPOUQvj4adv3tdZumT7UBZThhFaz2LA8sKo1p1jtC4p8miq6B7UB5+o0w3sdX33
+Vk8zm7hDPHmpgzI351MrQkNpdqct0EoOG85r/LlFcPQLnQtCocVOmiPhXZ0x35ao
+YO3c7RyESU6RZ8O38aMbR7mpG2sL4lOwY3K1xlDGc+sLpailzjwO6KwP/zO8tWvE
+FqJ3f/+ADXw8XUc/FHKHPDg80TcyDL9gABIDjNl9PFoEOkrt+ZOWZsKk2DhxtN+A
+SfJd+Mz+GoOV6e4f1GX+ZFmaYBnCTFaH1KBgTiXGJtpQZG21fHNuroOsjUTPaeQ/
+PgU+XkSwTxsKTLo3VHHf/AAFTbDXojVO1BmpYkawDUqNBw3IlMahqg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subCACert.pem
new file mode 100644
index 0000000000..1197d44256
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 85 77 F3 95 01 38 A4 A2 F4 47 6F C9 40 01 4B 69 92 E4 63 7B
+ friendlyName: P12 Mapping 1to3 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 CA
+-----BEGIN CERTIFICATE-----
+MIID5DCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTUDEyIE1h
+cHBpbmcgMXRvMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaME8x
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMR8w
+HQYDVQQDExZQMTIgTWFwcGluZyAxdG8zIHN1YkNBMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAxEQSYM/pUi02SbG3+5QFT/rPnGdsz7WTlK84lI0muKNE
+ZF3ZhSs25xj5+M6Kak1HkGxP0heWALuor0rEPzNX4W4zXbFfeZRzLtYef5vFix3J
+5hVTVeKJncghN+/Ik2RDIubrcm8+rQKHW9f01ufxS0P7bc1cAueQSX+fQx4WaGiP
+fwa3hI1PoWfDZGfZe6Yb/POwHIpwEI8gtmZ5++z42TxBeXktFk88+qmjDzFm3EL9
+aARqFtOvCVnu4kZHNbHatq6mBsYV5WeJMENmihJj0bbOsmwxqmcgyrN+jTCkhyRa
+lIywhZddOIyw5CqnB6ELwU4bEhgcQ3Srogm8sDJYAQIDAQABo4HNMIHKMB8GA1Ud
+IwQYMBaAFPz0jWEzMoB8fTWH3l9S+2nxHcESMB0GA1UdDgQWBBS+exOToeSbxSc8
+MFPXpcnmWpZ6NDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAlBgNV
+HSAEHjAcMAwGCmCGSAFlAwIBMAIwDAYKYIZIAWUDAgEwBTBABgNVHSEBAf8ENjA0
+MBgGCmCGSAFlAwIBMAIGCmCGSAFlAwIBMAQwGAYKYIZIAWUDAgEwBQYKYIZIAWUD
+AgEwBzANBgkqhkiG9w0BAQsFAAOCAQEAbH0Zzzdz7zKpAJHd0euOWLiP0Zs08+9+
+d+JG/wsVrUwaJIFl5D/lBW6tMMqqkMERQNLoXW1PMf0joAeooxapJAcyc80G+CEv
+Qjont75l9RswXOeOJDr6cjKgDfJ0Su488bJ22YAK4/ywiiZMXZ/kFbjFzN6VaUtS
+jLHyB1L/tmahUMD1fWr1R06VFlwtaB4MEyBHRdYd0kr8pPEKTtIpvMYvgbHfpRqe
+yCGfKTgRRCuAnP8T16Xajq9LPkJv2/QjHWpTgeRKA7ddWrmEH0VQcmpHYgoPMIkR
+3uEv8/k8zdsI14AHOj5zUn9muQgFK4znUjvNspmqx4+x4S/3FjEoAQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 85 77 F3 95 01 38 A4 A2 F4 47 6F C9 40 01 4B 69 92 E4 63 7B
+ friendlyName: P12 Mapping 1to3 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,18BF239A1E00FC54
+
+4X2m+xhm6XNIGfVHSKHcXnzZhk7p0USieVlaWMH2TgX6oPy6oL5MTiufkYwoVder
+6MTHiGYW4QgWad3CcK+SFz63GBQjHjA8T95LpIWK19IcmGTiDshjPk41lu/lqNa9
+e4COgKXTFC6/p8u9kpz6+lNXhffgcAJdj29I8fAym431Y4cGC8JKoc3PMTH7cZCW
+/EV0sSdy51eaGUPAGkBr1wgX27L83BwCrb6tYq4pxmyuTgZ8qmOOwg1Zlc1duB8y
+hq8iF2xdvb//Ilep2MC+tuKKgC1V6YW7hpCLOpgUVPzeO2l0PL0y3e9rnnm+Z454
+0ezKIZebCffmTwOtlBSFBOANOsYuSA+zo5v1W9wQjoVOxiSwzLiwa110SZInoygL
+3+Qw28ct6ASDcol7AslYnmW5VNU7ZrqAMkE6YcKu6JoZL+u2ny0I1ET2o8ETXVai
+LyLrbOzGdZhXopIgYT6lb5zvq0SVAbOo+QKFwoGJT56K/k60mteqWPc1AdjKZDde
+e/Ff0TXISMxAa8u6yPJ18tGaOVEyMN1/KkEuxdIWTGvp/Y7ctD5xXaEHmhP8n4a5
++Mg8dlJcheYpOS1zr8mGkFwSZPmf/U5zBmsUH0lBwr4fvNvmRLMVHDE3XzaN2NXg
+Ztnf/DQk2ntmdVF2MJ/pJxorp8aIJZw0g/V8C03A+Skz7oHc72fPhP796usg/H2W
+mqVC40KOO5dCWXtaAcVy8GXfQS84TWPTpGMCpyHaK5y3YW2wPGDeNKBDicDqr/0j
+10xD2KOALKZ0N9osOlYD+5UfZ7J5D27FShuMBXXcUYphugtAKUP4nrCBZxEPoP6o
+7jdilf4ZPtHp4HdptZKkI0NqpQqGh0UMX2mNH9MmBHUibcrXaPaPnh5XwIGN9+iA
+9q+eFqP+/frPQDz9OMdiNHRV9bFvzy4E6X63jEl6CIwdPTR2aARyyVU4uiPZ5T9N
+LFrUzAz0AYbrAkxJ5mC2u3NUjFXpKXu53c/Z4ZYZr2qa52ULsM9heI2uI3NlnPsd
+08FHWVKUAcbXSJ7/5GW1683dgZl0JW9PI31bU+ifyRYSGDJRMZxGu4zAyIVvI0Rd
+hmc8cBzoQuGek4LjttsoQgy4OfBJUxTZwYsmkpvBx5f5ab3gRC74Eznr7GcfxK7R
+ikz4lZDIsv96TVnY2Zrb/UrlOfVcKvblpfmDvanw3hlaBf6OGQRCi5LFTesls6UG
+sejXtgpZpTbPX1roHP3QN2EW1ANRnCdOKOAyqprtDxkbc7UEu0yJ6s559gpZx7J0
+GtysuywbYZ3zT5DNzHJV2drN5bITtw9SjnolzbPmpY5Ousq35uVGmZwDX6uFcN89
+3/zox7p3O3Q1cEbR8lESNZenDcv1dS9hkI+X2HwE5Dksqyfx+zH8mceA8zIHDqE7
+2rz3sVE1r9ZyhrhbkjXQr3YvMcbG9iulFcUzzMABKxLvU0+AIijh+7oXZ77Cy209
+a2xlNATcVUIZ4Iixe/bx26o3kpd55ARlwO+MRPDSJwNbGFt1w+/oauU1Hbl4Zth6
+D83crY1gFDvMuQTTl0TgseUSRHNxDoKwIuFtJVD+GUwMErTKXnu1ZA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subsubCACert.pem
new file mode 100644
index 0000000000..dd468f794b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P12Mapping1to3subsubCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 1B 6C 32 06 4A DF 9F F5 21 F8 5D 2D 85 DD 38 9B 88 D8 37 F2
+ friendlyName: P12 Mapping 1to3 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 subCA
+-----BEGIN CERTIFICATE-----
+MIID0DCCArigAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWUDEyIE1h
+cHBpbmcgMXRvMyBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MFIxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MSIwIAYDVQQDExlQMTIgTWFwcGluZyAxdG8zIHN1YnN1YkNBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtSGFUwgaiWWF5fUjELwFR+ISQbeAbroekuEg
+LzcnZa41l5oBmVXW/YdwIa0lbI8TEYdbSJKMPmj/VBZi1qEWkZMG7AkeS6ZXV5IX
+NZr3z5+xyUgLWNlWVvF5FMOi9oysAe8G3Lykzb7aEULDmSEJF08ZO2BAKmwqwHb5
+YeM/Qpig2XRbR5sPebFXbCPHgtDC21KBFg1RB9mYvkvbyeqqKNivtfaPbDcs7l6L
+Q5V4jxemwubG0n/b147PjTv5atcFsMozbY8AwRXhUZSv80Q3TpclTwbWoaCqc9Jz
+dAlVN4YywNosJr1TuIOWuo5NFHvQZMrDE2UTd6wCsVX9e1hSKwIDAQABo4GzMIGw
+MB8GA1UdIwQYMBaAFL57E5Oh5JvFJzwwU9elyeZalno0MB0GA1UdDgQWBBQAXTk+
+D+WqKl4t9q5oKq0zmz2bczAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAMwDAYKYIZIAWUDAgEwBDAmBgNVHSEB
+Af8EHDAaMBgGCmCGSAFlAwIBMAQGCmCGSAFlAwIBMAgwDQYJKoZIhvcNAQELBQAD
+ggEBACej7rCcrK7NKu8FFh2Rf3IUevcGIbr70Ussmb+ybpHCSgniO5b2qOHtRy4L
+UGgSu4DW8oJpwQNiDfS4uFICS2Xfw1LImpY6WzsooMaBQOLUmpDfSNcW3vp930db
+qWcqShq49BijeENbYGuJ5nJu6XctxdJq4CkfdLULItz057rcMPZ/v0r6WolizKb3
+aOowWWR5iWPCfgKsK/pjA4CRZFdWkQeRcFZtpY9s7T3XWsYgzQ+RVSLKP8tuy+bX
++bXzpj2/FQ51kahd1XSilZ0YIhWrR7odQ1LIdlABuNmIcBAcTONhlpjrzx9Ukkem
+CqvWf4hQHK7beuDqtx3JSiLMakk=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1B 6C 32 06 4A DF 9F F5 21 F8 5D 2D 85 DD 38 9B 88 D8 37 F2
+ friendlyName: P12 Mapping 1to3 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C99FD623F1970FE0
+
+V8J2Tv5dI90kWWonlmglwquiB2aaI4VrjgwcQCkf2UT90Ik8WXNeVNCV4NUBXpYs
+aRizGDFFsyKp7u4p82gqh9K4xmgvLlQ8W2yldahj+jijjMXeTPzSDiQxVoI1DXSs
+TqbLG2mRcNlm9AHqnnSfUZu1MVBp/+BNMl0lmYNCHMSd48x2LSlMTVWdtDmhVPDu
+FjIfUivpcKKD7ja+wIeGF9rnXcQLlvRmcGLmNkIoMVi48Qmqx6mVA0L80D4cdG10
+IvEPV9azLnflZNkHbcMcybcgrATXYtsHqhQxPQmZlPsMsuPoY3+jrRDxlNm2EymZ
+4W8FOV++/bRXtEO0BMuBbluOPkgTjEfP2EcdeHPf8x79fIbO/nn8yzhMmYhnsq9j
+5SJXLmnxzRU57NuAv1kLaQVo5J2sE8F+D9ZU/ovBUKtPALwGyfqnzuJukLhuFeUx
+FSL1suo1HVv6SVf19xwpyQf+eTFco28XrrmCqlJV4I0M0geJDdWhSHSlKyaQdV1f
+gfqqNmeLAensQ6VSDdnCXtpyOyoy1JSegapbLb1GyUrZLYyfmgHMlSpmR2+BCoDx
+SGvhDeygDIRS1iA7czFTcBrrejNNINTJucbkPJszer1ZE3EeaKrCjsnCSV4gEOlu
+u2gMLTJL8sRXr9PZUfC3BqHP5PiaC4sfBmZDDUXMpfm4lvR55cB/MdQ3h0R940y8
+vvX5Kkm6T0WUi2reATjHLH9Lp6HC63rlI6845kgdWL5xCS5Lc3ULG3Mp7CzgAXUB
+hsWRWjKpgRrBpEFZmOIAdth2W28/eV/dcognxd97iDf+pfWmxwDiEj/q0T0rpFjz
+TEKR/z0mEMxBrZufH3j92gw+YXaDUQdzuVazKUoTPUwRqI81G/PrAskUG3DlLBvk
+iipb0ARCu8mNu6imv2g2IwwcrzWVYl/4+mMQKzXnbp9/tUXFAhbyhk1NclXSuIEg
+QQHaVgXYMqk4xvzyp3pc+xmCjEQRTIdzOiIQBuN9soQD4h1kLogheJuFRhzdL5Jr
+KpKpS8xmadt33c0zA+Sm+Pc9AxuLD0JH5zfTaWf7s0uDgOb1jFHozW5JIAjxFkxz
+bcRaACZ8oUtzLNnaA5n0QcDmskVIJmDIWqKS3067xwsu+wOxYY2RsG1+OY78D/ry
+Uj8XGDwKY0KP4zejsrAUZYlAsogQDBXb8gIKyiMVg3klhe5L+KF36iN/CyCUk8o2
+FRf4ER6wNrpDKy24G6TNp8jVyxvmB+vnHBLZH92Xe6Qqc2zpVIN/5jbNf9xTeCeV
+otJGIV/yj6kN+MP5aEYtZkXbQKt3ZyFjzzdbRVI4lppFIx5AS87WppnKTtJqnZUg
+U0+VsvSS7unrBk6qeCI/JufyWzBAO4IhGjuZPVsLOF6gXld89Z6XHh/6XB1wCFG4
+TxCjlj7caePMhPn3GZJ+BPXnhX8hVNmgHVS4UBbcbzpElWbauS5SUVmD12/Fd4ZO
+VCuXMcb8w3eMelsnzJq+zC1+snRicoyixxZdk9PgcdeVBIotarAYs4JWvZBglWw7
+V7W3oKSKREomYFGT0izQPY9BeNbYLoAOsn+FwXNawV1n3T6t+X/BpxNdL/9AvNvZ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234CACert.pem
new file mode 100644
index 0000000000..ae724b8103
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234CACert.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: C1 0B 96 F1 D4 06 3C DC 5C 20 BC 4F 9C 97 BE A9 3E 8C 12 F1
+ friendlyName: P1 Mapping 1to234 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=P1 Mapping 1to234 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID9TCCAt2gAwIBAgIBMjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNVBAMT
+FFAxIE1hcHBpbmcgMXRvMjM0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA6EPLe37qOTEdD6xUQELy7WcT/725FAHRtk/O46EgnyRbLY1VTw/549tQ
+HEAeBnvBkfjD1c65JHMPFER6/LXHu1BT7EXfbaRPNvFFBrxO590dLZ7zkXggq+ZX
+/RDwCs8HMEsOrGa8g61yaYFICkTlMCwC+gWKK9SPQj3TS+YFfkmPFkF22ASIttqG
++QPyy5BHx4WV1k21sjw0dijh9V1Z+tZ6cGLGVp490Bov1syfcz8FTmiscacXTOwd
+hnlv/XFa+URTqDd7qvaiieYe3V7W7j1x0okIRENxZh1giKU0AcbAehfYgmXVT8Pg
+/FG4oxhZ4fflmfgIa+k6tGf1KmDelQIDAQABo4HnMIHkMB8GA1UdIwQYMBaAFOR9
+X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBSVCwGpSXiqdtp/CQ2siBT59fdH
+kjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADBaBgNVHSEBAf8EUDBOMBgGCmCGSAFl
+AwIBMAEGCmCGSAFlAwIBMAIwGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwAzAYBgpg
+hkgBZQMCATABBgpghkgBZQMCATAEMA0GCSqGSIb3DQEBCwUAA4IBAQBFCspJbnGl
+9QA0VGqikE3JqvEe534hgJSjqUj3YXOdbHF3BzthYJxmCC8c8ZAQAj78LDctPO2E
+doS23rw94Hx23MOOMy92xoCYepjNWffZMdSgxUMBeGCVSw+I7TPG82c34h/nRung
+HcZ5OgG4p7j7DSiI6fbhdOxjvNPw1MTjYZd26QMcgqnsK4Ts0oCv2tiHsMWIX32I
+ZZZqMruUNHrapJZoayDbBSbx0ecusf9xxky2I3of8j/EDDWujCSTS+2+ld89U1Hm
+wLiGs4cGEHVkWT3bMpXC4vh6Ioh7MWcTGKGoH034mpOgMtG+Uixh8uWOmqvxlx22
+GWtLzZ8NDh2L
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C1 0B 96 F1 D4 06 3C DC 5C 20 BC 4F 9C 97 BE A9 3E 8C 12 F1
+ friendlyName: P1 Mapping 1to234 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2F36EA26EC93C8FF
+
+d74PxY5ydPqm5kdwAnRDQLghqMnVsPYLnzMPEYQN6nmM7Nq6NPH/rNA5VKaHcMSj
+PGQaiWQq1R+oYzOmeeKyUE8accmmQ1ekGLgl5RM8B+3In9wJNP27G0NnVfYr+KkA
+5P9DlujsNFpUAXY1Iu1B7YC47B95PbaHl7oNYxfrG3h3uZqSHUdRKAYRoEUMtVXE
+jquLnRasDdf32Ykra2/pAZJy68aLrAIfUbp0rBmmfA+q57LjK7/OmprqMUiINXXJ
+/2CH901p0KYAit5YVO0IOPBPXse0TFrFU/w7NmT/jc5K7oIVUAJdIadI2Qv+govY
+oqvBdBtZfvMimbDRlgPBCyJhfx829D8OnIfDA2cMkOJQ72zaXwDkbjeeuCRLcnaF
+Ld6RUEf1BswsORBpnbD3SJyzUnPfxn1uceoul1y3wtjzvxYL8dRf1IsxzyviOjed
+jXOhTlN87LOIPmFs8JZJN0SR7ULvYPy561SH/HTKF+PILbIbD3XmvP0YHHLz2EeQ
+Y9XYp5SdcvoUzq8937eggRdzPD2+tIXNWJD38nWygLP7SBx+POr79UYsZPw+m7Gr
+rDgIg1Kfdi/YvIUqTZxjWdS/HlsCEZ/GrJd1jL2uXKmGIeDu8a0/hca3O83Kmh1v
+UiCrqPJkMT0BB2E0PTLkzl0k3yOBRs9GFpfM0ui30ajEwfnN7em5myL7BTAfqzek
+5Bldy54W0Y1gBPLj9VeokBCPnl3xRiB/Az8uSa7lZDe7GoZspdUmfsNfGfaS8cF5
+vVUzhNubzGTQB/W9mQOjUFEPFg80nSJ3nHf/gIWfR7FKFn3BeMROrY5EUw1vGy9x
+LQRfraio1SYdIYKeMzyHYzF+ILr1xUQDqSlOx2rLVOWuNvzALCnK+oUmOyAcpNrB
+701arwcyp2SAhgPoMD6EfvA48hVFwjvXfNJR+dCOSGkFDYnlOvnoB+3aDayiVG/a
+ACObQyB1yfpuDy5JRL+gd7eGdHHXhd3h2dpQxml8nRCrYuBePDkCM6Z5sKBvi9US
+e2lTIzTkd8aK/svLV4dO+r4VYEtOc1hLYFhNDd8OLLzbjJM2HiX25mY2y7XgTlFq
+lDhJjMeMOE5Qs+gpZKw+BntjUZVEaSIKfDWP8Mp5/bzsRD4dRjxMXs1K5KWwQIr2
+qRWUIt7ILwRSiUzL1XAjkM/vr4CLuM3f1K1nJmw7Fuc9LBzfH9HlOWc3FMW3pnxn
+2zFTeTQ/bKpBp0e0PhtrynriYvTqmVAFfnpkbKyAgE//A+uAaPqluzRZdVMe03BY
+h9a7MdnkRNrl8LetBg4mKGWqM9l2FPpE3JCRLj7i5YzKGhC+nbd+gMsZBPfCP6jf
+Xb794wmEb0y645XTp4F4TWJNiuXJ7TOJlmHUecqZE+BjEYRkDstyc8PjK8u/QwB4
+97Zx0R66NfdEcCa3v05g1aAN8kNAuWA4VjtHcOitcJo6Qu+TmziEadamkT/mEy//
+9HowWzLnSoHvnV1uwZozLfJorYIuzOS2+GYefp1x14HHQzp/3icnG5WkvhHOwvbm
+hFjbHxCeLNzTFyyFw42YyK+4x82aQPx7+5jGdNYoNFIVmfMAe7r3SA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234subCACert.pem
new file mode 100644
index 0000000000..846712d23e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1Mapping1to234subCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: AA EF 0D 39 7E 1C B7 98 0C 76 3A 6D 21 0A B3 C6 87 31 77 96
+ friendlyName: P1 Mapping 1to234 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=P1 Mapping 1to234 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=P1 Mapping 1to234 CA
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUUDEgTWFw
+cGluZyAxdG8yMzQgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBQ
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEg
+MB4GA1UEAxMXUDEgTWFwcGluZyAxdG8yMzQgc3ViQ0EwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDCqo/fkI2CorkBLrk8+SW5B2Vf/V3rrujIfoLvDe7m
+xMzVUsj3fQgZUgeD7yG056J8OLaaV2X6AnYGSOR/IjkmxnmChoDBNZHgfxmjoIBB
+SrWaoYzucLOpPhxbRToBM68OV1YS7JuJyNZNOkpWCVDOnDUUGqZZJAOO9KKU2bW6
+/mWamcohebtrQQsSUAJqatKBd3DFgyJl9toV8bWgINwNHPJOG/zGmfXrM0XpTC6c
+cYqN3FnBO1BhuHvAmT7x9nKEP2d9+njVvSJijL5UefG2i3k73WD6FsK1NsD1TUiM
+W8R1uObBWDJSp7tMnpsRzpWYxN2UrB9DfejvhYwCW60lAgMBAAGjgc0wgcowHwYD
+VR0jBBgwFoAUlQsBqUl4qnbafwkNrIgU+fX3R5IwHQYDVR0OBBYEFAMX5ZUA/So5
+eK/LRvZAmGUKAu27MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MCUG
+A1UdIAQeMBwwDAYKYIZIAWUDAgEwAjAMBgpghkgBZQMCATAEMEAGA1UdIQEB/wQ2
+MDQwGAYKYIZIAWUDAgEwAgYKYIZIAWUDAgEwBTAYBgpghkgBZQMCATAEBgpghkgB
+ZQMCATAGMA0GCSqGSIb3DQEBCwUAA4IBAQABbF8fZ+aayNEPK6IYowHdDmpCNyiX
+ShlGuMbWbiSBilugkXB8z11tg/C+5D1wdeDk57vpcrmr63pjA/NVcJsp6nOFGsBT
+A0l2TQ6GA6Yqk8ptm8nzP3tD60KfDzu1+Ld0eGCkx4BWjwGrOBt7S5K/G/tTAXQa
++fZ0nNP+WGn30vRze055JcSScogmNcTJ0sYLBjnYbxyFjpbyOsdhiudG+FufGcIH
+P++VV//LWKA8t2DgMb4ejFdpihhWV8T8fLuvykmVJhD4QcV4Z+TTTW93QjCAa5oN
+XWhzyqOe4s4GLlO7jZw1LMEHhh8M7Q3SIrEGDA/1exOutvigUAQ8x0eE
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: AA EF 0D 39 7E 1C B7 98 0C 76 3A 6D 21 0A B3 C6 87 31 77 96
+ friendlyName: P1 Mapping 1to234 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E280D00090F07056
+
+Zs/1E8+cofljE9h57m3zNjcZ0Nbw3iFy2vWQb5DayLt5k37yV7SnZVNp1KAGieyI
+8Rzj9NTlc3nuSTW6VxjBDgVqsZ4RXMTivT9PXzcOZZrm17TckytFLUL4ai7g+pUE
+JcihIk/vfzeOeU8xx0UVqkpt+wXLqASx60hDz4d4E7mWcz8tC86xGH6ysk3WINfd
+fTnvq6Ztl2osMUvHhcsFlMNyMFOxrOcrKYisTO6f81V8Z22TdlqDdcddrYEBP+no
+pozv5aNzucptbNDAG2ty/Sn0MWU1UzlDdZtLcrvEQK9/21QZPKRKIfqzCWt7xCxo
+CZ8cD5tzNhP7IiLqDdDfwBzQ/V/uDVgfoJh54SvmYemCYLLkwMax2eviKuj+5WNT
+STvLPt0OryCXz5x2rLsoESb34zmgPELRY1YFDszNggwR75OnhFM1wTEwqrEoJcMB
+Nu3hd4eORZAk616ut04BpQqqIIp7esQbe8Ni3c51NIUXC2TVr6QfbM/V8Oy86guF
+ebhR6aRlrX6n5owVekaunAVrxve0JM61VX1cTBDmztj2dri3SFVRBEZ/kKcVSzxz
+A5p3vN3k5GmO6Nd19R+3NnjGaWEqUCTm1CjZBL1VMYmm3UXSaMlAzSEzfSIgx5VE
+WQqkltma0FI48nwyBzIcF819+dRg6PPi5fvCJj6WJkNJukM4vQUe/BVuR78J1Ii1
+JpIsziBcsPIzd3HRfbrHhz/cwKGY8JJzATdNbB5klI4lfF/SSDvC2/YCKngctFjr
+bL8EQ4gfhpMeOvjhO/52HjZBDk6Xu066NBf/dh5p+BWvGX+r0z3dtPtkhpFuPkrz
+06vL9RCtDKUKUo2TkIbEfjhgIu4/nW4YJdyRxBepz9Rn61RkTPhfeieW25MkKCe2
+vqAtIzEgeNm1YBHh9a3v5sPFgGXyRf5yhOplBJ6Zjemu3p6TF6FYbI+jDvyLRzJq
+rWYW2/c1sDVJykEZ7tvCHOycliB+BZQLxDQr3sM/mybxzWmYCkhbuRNwRPxmW30e
+/kzbc9nbhaI6eGdacoCmCK/T+KmQSCGepnf8Xhn94imESWUDmnbGav/2DvYjK4Ad
+aoOXFmsXhbD+svWQ+uGFx0ifxugnTrtbCbeAywEQPU1vZ6vt/HhhitBtBpBNglbZ
+dADKHRMDNILX1+F//M9H6tw0U0y0gpdsPAxJROJGW+MO0IlYz8EnUOY0dQC2lYbz
+fDbz4PdLWOUYXKUZBceTo1dAq2DXJbaJi7zumLcZY4yLus8rljz7FrPrx41Rf923
+teQP2NrX5PdfX8T9n9NV4KqNZF+/h+qwtKoJxqN7a1ICcxS92kJM//L0pg229nXk
+WJ/bNtzZxAGN6qsvX/vGvhSqDA0025N15mxsfTjTrq/zaU+Ko2cP/FBvMZUS1fST
+2Kb0bm+pipPGKslc3siG0GxsrbG5+UQrkI9tqEaq0C96gVIyZwSzsoH0y2KJ9NUY
+/f+b3sRY3MeMCkh0bSHg5rOi87bGjQk7m0KFNMj4lLqw+ViYzAXONocQ4sm8skm3
+/LZMCOnR7pISZL7miEsMQt8Hrw7hZx1n7SB6W7h9ioJKfgBwDDgkWg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1anyPolicyMapping1to2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1anyPolicyMapping1to2CACert.pem
new file mode 100644
index 0000000000..34c797976f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/P1anyPolicyMapping1to2CACert.pem
@@ -0,0 +1,69 @@
+Bag Attributes
+ localKeyID: 43 43 08 F9 CE 07 63 62 37 45 16 66 E9 B3 C1 63 15 23 19 7B
+ friendlyName: P1anyPolicy Mapping 1to2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=P1anyPolicy Mapping 1to2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIFLTCCBBWgAwIBAgIBNjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJDAiBgNVBAMT
+G1AxYW55UG9saWN5IE1hcHBpbmcgMXRvMiBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBANzb/x7g9fYUZJHLawFd5dXdaTd5QI6b394FF+evA8+llsAl
+r9BqwYe139iY9+RgTrroi8KRFeZaXndYBYANU+fvhLqFWAz3TK0nW+otpf5bJiCZ
+27slpFJEINgrpLQpENt12YVkQ60alGIrvYIxjZkOrhbgwHqTxxMc98Nqdf9PXmaY
+5qai+dWQ7RMewnkoX6bx1TmgQXOT17qlbOfyuAnYM1oabX1+86XEw7W69i6Cb8/z
+/VkC6qeRbV1Pmu3lVRsoidYwGs2cwAyMOzz4MpTflSk3b56w0MbmHhyflr+/d5yp
+mNAkE5dTqu0f4GZEACFbA0AP1qSbtgmG6vc1g5ECAwEAAaOCAhcwggITMB8GA1Ud
+IwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQfAigoMo5KhPi4
+i0HxXXvoJVJrhjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAMBgNV
+HSQEBTADgAEAMIIBeAYDVR0gBIIBbzCCAWswgbkGCmCGSAFlAwIBMAEwgaowgacG
+CCsGAQUFBwICMIGaGoGXcTk6ICBUaGlzIGlzIHRoZSB1c2VyIG5vdGljZSBmcm9t
+IHF1YWxpZmllciA5IGFzc29jaWF0ZWQgd2l0aCBOSVNULXRlc3QtcG9saWN5LTEu
+ICBUaGlzIHVzZXIgbm90aWNlIHNob3VsZCBiZSBkaXNwbGF5ZWQgZm9yIFZhbGlk
+IFBvbGljeSBNYXBwaW5nIFRlc3QxMzCBrAYEVR0gADCBozCBoAYIKwYBBQUHAgIw
+gZMagZBxMTA6ICBUaGlzIGlzIHRoZSB1c2VyIG5vdGljZSBmcm9tIHF1YWxpZmll
+ciAxMCBhc3NvY2lhdGVkIHdpdGggYW55UG9saWN5LiAgVGhpcyB1c2VyIG5vdGlj
+ZSBzaG91bGQgYmUgZGlzcGxheWVkIGZvciBWYWxpZCBQb2xpY3kgTWFwcGluZyBU
+ZXN0MTQwJgYDVR0hAQH/BBwwGjAYBgpghkgBZQMCATABBgpghkgBZQMCATACMA0G
+CSqGSIb3DQEBCwUAA4IBAQAJ4zsy9qL10OJy/VRk1NA5w+0ncD1kOXO0I2cHSqA6
+wtQ6I23JPRgTutDfvR6ktvdBRfkeCwYHPVHHx9zrvfnk2MIAfdDeo93IVAqJEumo
+LIoi+XEUWpRH1MiJbl74CndIpdc7G8H4OOagqMz1p2XsZ4K8RpF/H0WUYGvWsX7g
+78EjEraD0D9PxWr1Na7kfnHoYxrqd/fmRYtnCwt26jO8A1DHXgrWerE/fnUlTxM5
+tHHN1OMOlggOimhGvJ2pn05BdXIhVtmWCdFo6+pTcyWYMm2IvOrzEaQtnGf3Zefp
+lObeComhN1QW5zDtLnzOhHUHc1t4deRAIN1zhE8vpYsG
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 43 43 08 F9 CE 07 63 62 37 45 16 66 E9 B3 C1 63 15 23 19 7B
+ friendlyName: P1anyPolicy Mapping 1to2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,190493828C849E72
+
+3ADKpf4RaFWJNff1Jg2iB1PXZ4JLDWjTsZz4ksV5g9hAXGT7dAIkgGh15NY+A+ng
+pHr65nQ2XENo0MUh/7Zs2bgGGU58Xx9K+DWWTWZfJvSedJU7SKLSmQBHUt6NC/bQ
+NtGzYnL2zymdNwtAbBqeSH6wdvqQWciBMuhG4UGKT3fLeBKEjBHH7mty5Pz2PQ/6
+MjNtLA5aqwxh+R1RveDI0oMsbQ7BV987kLNOs6soy2F1Zkn+6KPRiewIwdBCcB3O
+xkp5Su76YdUZMMfm6Zm0z8/MNSTwe+LSDQmEh28m0bByDKiR8CvmsU5MW3MuPh4N
++4faLrcwFTPk0JizNnlFcdB8wsRCUOKDnWzih7kPXUjGEZXiJTbmNNalEEgQOahE
+ZgHoCNbpSMHF46DRIzp+MTJnLiJDe+YCLqmlIWSAEnivjmkN6Ouj/X3eivPICgkE
+SQ7DAkuGAZoza46qVs1+Dx49HyDM8l/AifK6Y87eQf4fMdPtHC1woAMg+/6hgLdt
+Bz4k2xGPZWLINtUKTrEBieMntL+p5ppOMSKP0dGqArlNYHNLw7e1zone7FTNV15i
+oGZpblu9Iq/7Z6S/1JEo5lo9npHUm69Yo0dzTarVYx8KvqnSn3FPWCNwiEhR38jV
+gELMghyG6vT8kM6bzGVk8PdF5EJRyr6m+JQ9ZVEwjisQFOMHvQp2ecNtpIWvgSu4
+SRK4oMJmxVXdiz4YXFsDKpkLaE+IkpHW0kDKBIUnBckRPWva5zPnOrRjibMvZmRf
+d6w/tjCUR9kMuOhBbXSHJLm2GZpJizNWqLySJE9WgJ/ufnSYlx07gKHi+XnEdI/V
+Bo+LjykYlvubud5RsIG8XUJFLxtinJJ0mks3dNQchFHzmsVldKWJQoLN4mBH20O+
+BgmKCjv2Dg6Irrh2ZcqC+tZYnPh7/hg6q6LXp3HZcZcEsM7uKEZIR3ETrGRuuuoW
+H7z0FzMs7kn4/R81XSM/wEdcqHQk/142VyA1l2bGM7rbDwnHRk5KiDgMipQ5azJe
+gWkR4iso6Zj7RKyrzJ5srfmnlPknx+UPA9H7WrjeyvO6pQ0Crh/0CeitYLKNz/+R
+tInp5BYAv87MY1yByEno9SB2jWa5OkG31gk/8P7AMLtTqTqHBlR5iWIiuQp6pGr2
+nxCtPkaJ71o+d3gxy9V2CIc3Mr91KbOnytiFc6RYc/WZiFNBxVJl/aZBtcXZpal/
+gcYzQJFidHa6zezoFojHJgKvl8NwWIkJPNttdD9bT1DrAh/S4GidhGG3gG6HaKKv
+B+KYRO5nPFH0NRP+dXVd39IHX8SkGzr5ZlOrVBTwMbACM2mB07bcIzUpZceuEMX1
+ZI2bGj2EWLMq1v6+x20tQmxYRHLqMDDiZ2ZEypwfSwSSqH1hqwfyCeAzUvfYrNBR
+KVkJ8V2IVUOBfo/CSbfAfvP5dktG/xxK9CIOsd+PyKbS7kgfkVudODLkx+TU+//I
+PqeSFd5sECKQuSYEHG2O0Q22doufmtJNoygaBkyTG1ckiPitxO4lKIDxiUlId/Yi
+IietXGgeZxNzSs0AjrU3TEpH8f7kc+RzbMj+cl8bSZZUKmGOM44bT6rdEuRRYDNv
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PanyPolicyMapping1to2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PanyPolicyMapping1to2CACert.pem
new file mode 100644
index 0000000000..f0bb491133
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PanyPolicyMapping1to2CACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: EA AF 99 DE EB 5D E6 D0 27 6D B6 3F 8E 59 92 32 1D 51 AC 76
+ friendlyName: PanyPolicy Mapping 1to2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=PanyPolicy Mapping 1to2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDwTCCAqmgAwIBAgIBNTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAMT
+GlBhbnlQb2xpY3kgTWFwcGluZyAxdG8yIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA7it5KgqlOm7kgx373idsdbNuWSP2si6O6lKKZSjz/B/ER+zK
+sbo30/ZnpGepghDagsI2z1pvXZPjFcaX5jThOtKnKiB00ColGZQL9OMl52BYfHV8
+ygtI6FLosSe6J8A5grqnNiFUqupOAMS1MjsLDJssMivMyz1Mmb0FBqXzJOB3pMCS
+nvgsLsM+rXXZYTJ69SJZfv4W31iGyRQer57qoIiKYTypLuBqO2S0baY7J//g040q
+Sav7szmAh+K+Alseyheko9BY6tDW4kFSe2DshTvovJD6dZukmjh1IVLoU8LBMYy3
+/23tKavxkEyXBYbrF5MjJdyfHDulSIw24P5kzQIDAQABo4GtMIGqMB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRHAycvQz3FL9mSrMfS
+dtAzxvl3uzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQE
+BTADgAEAMBEGA1UdIAQKMAgwBgYEVR0gADAmBgNVHSEBAf8EHDAaMBgGCmCGSAFl
+AwIBMAEGCmCGSAFlAwIBMAIwDQYJKoZIhvcNAQELBQADggEBAEzmc6/HFDjAm/BX
+XujVfL34xHXsQ6Hvo5BiQHACompgIWEya5NwZQODcH4pig04UBkUg14d9VayDUic
+gAnwUdsAvL3tHqwnTafckHMmsYJSig0xkxpOyWbqcq/RVHGnMy3pLXGTrX2jpI/0
+1fYdE8EB5pcoL8MmktyTf51FvGJGQhQk0pIaCHhO5cHUADHIBdowWt8G31z4Kv/P
+GqaZygDC2R1YG5btN8EJ4CSGp2bGX0oMJOt2F7knvVVrIFNGH4vYfuXSxuQ7yuma
+kfS42S44/ES8W+FnhTW97iIq13l7Wh4XTvgfhHiT44dxbX9uUHH7TJqJq/rijbF/
+0zDEus4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EA AF 99 DE EB 5D E6 D0 27 6D B6 3F 8E 59 92 32 1D 51 AC 76
+ friendlyName: PanyPolicy Mapping 1to2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9EA299E542CF1FA9
+
+YezJFv2D7hxBVosplQvpAZsgejIrkEKxQUmTVVssLLPNZRmceZopLIsVKc1aXNrq
+6GILnOnDqxdudU97ZetUg4RH1uvbt5sdR2y2dcGHpJfgCXjqAJ8Tsm7fXKDsbnHl
+IRvnzVvzdnML2XkH1Ns77dSCz4eKV9XmFvqanOVNmTYsmYJW3bkTqfz+t39tz32/
+1YKZOblfAHuGl4T2+g9cmnD+nURTm5fKvvosx5H3FwrkGjmvJD9T2FrrmGRTzkoc
+Npc+Q9Oarr4L8/mWnNGHX6VmM6pASR5oeHHZk1gDfmj+8RX0SfVCtP4gNbh8GFhr
+deW7HhxEqb15ya9cbJoxC7C1plUTcYN1OB2dqC8TJIpd0Wk21DlKMyxBMpx5/CS7
+xFnWcG+QzTdXDBm6qXqS5ksbvgWNtMN9jJUbrglFN23Zt9U5XmpT0Sl/5+TWd+J3
+nRfS3JJO04o+vtCzcQK1Cf06omH7r8XEs2VpQXzBwtaQdYSdcDIynfTWQ3YGFKZx
+/ZiVkNVFIa7+6kskKziGl2DB7uhpaIX69sBZ+iBt5xq7Os85RlVJu0mGWw7hsUM5
+GuXmb13glbRxaGHRaYjXIT6Jh3MAn4GuS3jDWH6StgQgYCFEmlyaNk8X6OEF2XrO
+Uov8EOi09gpmo/LdJKZNw40E/FYSm2q9QJs53oovEGEC2THhWr4166oJVFgr72lB
+4qb7HcvQxyDm2n+d8whkGtk77aZ1/nVpUDSQ0QRglRy5WFf/rCDqk/X/I0bU3gH8
+KPwrCHmMggvibYVXnxhFcVOJ+5MU7hrkk1eJjxHLo0e5E8DDVcE9oi37fbELaR7m
+qf6TqAyHSURbRg7a9ynUtQR6Vw+ikREVMulJpnoLZwTS6VBGkH1A93TKnpaaSvm9
+eXYsIgVQQCvLrKj1PJfbb7HnyzZ8vt7uH/u7ZeMld3UWyfGkzM+yVoe4SahjAU5C
+oQhAyjY2VXF8tN+WygxAjLujGfql4uBbDvcrQRecoHEvkfugabFExEw5+9lwM053
+h2Fwbyd0V0QmVxfTmXbhfjUP0A+JG5uGsikknajbdkRHtE/TyDZ/sUyArpmDxuS6
+DOGUdz/S6hz5HAZrHRc6zKbk4cn82sjsAadpl7N53cnDrKA0LaEH+rZogBUt1B36
+PF193qqhLhZEKxo0tb8pN7h9Ib48vhcNvv/W7R3TRgGJMw5wGKDfhXuqfqkVfYtY
+o/YtZuepmOAFQuiRhzwy1zOyORJvoY62xmxXf9zNaRHU5aFMlmYVfaCxQqf5x9zU
+VY4Ma523VgdHuzhT61OOH+jaLd4TYE678oweL3xO6KoPUk2ZontyFXBJFIMiAYTH
+LS3BzagSBLAb44MrUMF6+DIYlsrPIYuF6gFUtJ8lhmSKQTaHOyHiNNVi++XaXn8J
+4djY6qN+n5j+XQ2kq7ckIFKQTxZPUV4uLBWE9MdqvoGGY/DO5KLajNKtc3k3oCPX
+j1olnFJ/91zEoQVE5E3NHEqsNiLqZ86bkKDiWSpxDjQJTN0BVMeZivh0YBGLj8vK
+Z189yusJ0VgByq55uXQhxs1N4+Nv7/INz4EfEuTZQAV9+8utqCuQ5rNh1PV3Wnxm
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234CACert.pem
new file mode 100644
index 0000000000..2d198c343a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234CACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: B1 12 1B 20 2E 0C AD 94 92 A7 5C 4C 84 AF 13 0E EC E3 AF 6A
+ friendlyName: Policies P1234 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P1234 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDwDCCAqigAwIBAgIBIzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGjAYBgNVBAMT
+EVBvbGljaWVzIFAxMjM0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA5Zswifhj2dT7WU826z9T4VZWyc4sgtEpEVLsV7AbMOMFR2ind4R/fSTyrw7e
+szphTfev/5eBa95JdOVqxfPC5M+Cri2NIZEtTSll0ybxk/uy1UJ4s1ZTwCI0QqJw
+m5jR4JnFsoIhfaU2xP5yGOEbh/JpKK8L4Dlm2W5AXs4BCYiqdSJsoDlG/Ay9xBzo
+dP+u8Zv+MlNZWMKExqOQxxxvcsSuVxziTjYZggMchaLTOgUua2PifFWPm7DSVswl
+cOKbtaIsd6ya9VLmiutIGoWEeLOcjpiM8lkx4lk0DGx8SDTzDsT1yfrj/ul76ujP
+Lwf/GABHoLjC0Gv9yLG5699VxQIDAQABo4G1MIGyMB8GA1UdIwQYMBaAFOR9X9Fc
+lYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBT2/amMJiy0z9bT69QerZJqHbskUDAO
+BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMEEG
+A1UdIAQ6MDgwDAYKYIZIAWUDAgEwATAMBgpghkgBZQMCATACMAwGCmCGSAFlAwIB
+MAMwDAYKYIZIAWUDAgEwBDANBgkqhkiG9w0BAQsFAAOCAQEAPCzijaW/6TG6zZls
+SWF2RKrsRSG7qMXa1K7EWMqkCfHw/9QGe7xCtlhQRHC4ujJqwwHblOZx1t/07jLS
+pP2R7VjOfSoCER6a4e1ylKPsP3CrxxjxdngZ6c7JGN12MqO22d38yTuGfgYSiscJ
+ydBXzqygLGCO9ocBscvA1l49aDo7nkbStAc010/2nFiv6xdasBNxu+DLTRyHnDUq
+DaxJ06wsiWxRs+LpSov2m4cYPCG3/hy5LfQD9cRPPUBCSGVH77rk907LBpp5ZnAM
+NRxyldQ9z2EbjE6Kg5ZGIx1UbpvUw36YFX6yAWUj7wUcPT1mArZq7EWZByaVWa2J
+dNwGOg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B1 12 1B 20 2E 0C AD 94 92 A7 5C 4C 84 AF 13 0E EC E3 AF 6A
+ friendlyName: Policies P1234 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,401B0181451A86B9
+
+Dtw0yEa+7EIZXS+q81Gmb1Osr7tYFnQQiRyFaMjkRGB8EGQiAvvt0ha2wZ9Im36E
+t9LcOiLHJbQWiG3g40rGSyJViEVYfaXpid5SzvoTCPYcTLnuun/S0pnZpoGO5ET8
+HfZ5+W4Zc79j1PSN6kzLCNee4rP5ieAcLOHdkimv4Obq19itZZ6r/Ca41cAYgjPP
+i4jsmlMAg20bjnfFJnDB+I6IZY9UkjSLysWE3eWWhCZMULNwYwTxZ8dJBU5zQ5vg
+ktFE1NO9NnYFwxyPp+xY3ALfrclwctskp7TxMzVuxdgcqaZ8jBgkj9EUaC8NmFuU
+Rw0UC06542RIDQC2xy5gmowbAETlG98jLMdIvAVcgLBDFGZDYmdWfaPPwFUBAkQ0
+pz163zON02lf8z1m0zuHy9DFeIMO2B/lmADC0HgY4g4ilk2dmnfdgBuBe/Fe4ba2
+VHxW1lVNelZcZ06PA1L9qSdjBn+8FwAqvd2I5xQjCzS1ELyYJjgS9NZ+QqielEKv
+HylSjAABdhhZ2JrViNWHYBdMbJk5cLn1npAR7rpo14b6YJg4hCh0J5FjvyUVPd9e
+SNf+T2zoZ4sK/WaewnDvIkU1s5Ap+AgsrSg5qfKXv+Tbb/Borhk1D/6NZiANme23
+oewu3r1Ycn3Y/fEs/pV9dHlkpsg/F+Oy65apQVZWfnzW7gmTx6ercFMnef51+wfN
+G5HZfWaJMYnzUDACF9HLmhMK3dGicv9n+8kJp/lK01tV4IXMeRPqVfkkqQGKxbU9
+IJhL0YLMa+Osp9SsPxmtR4XqsXCn/4bdP+uAe7fDOmT9f6F+LxG+rBmT3KlYNdS2
+0zj9lf//N9H7els/EC31Z8Jy7E7sMVQM5CypoTybvBweus6xFTbogiuI6/VhzDwQ
+oHMs0bkoYmJLIqAihmD4BqldfQeIRhjiqdl6jyYgZcrQSXj61t0DrKPhUFYmLdf8
+zbg3A60Dvs9fP+OmCyTCbMacd194UwAZHlgDecNgadyc1RQv9zspYUt5onFhD3vv
+Vqlx2b9A+WebWC+kegZHLrBlBb+g10OHfkSaBWU6wQ5LJmt74m2YKkPRux6dMseL
+lNJsmhL/Q/Vk1VPx1ASbQmc5ByhTIG409QHtmLTCiLVeH3vpToZXwR1l/fHtBRzP
+SFoOY0TKdWc8h1pjiDoDuvWsTa+i9WnH+/n2TtmBZTmPM17RijNRzIZV2WHvOZ1x
+6oNL+dLvBsQWQkQDKGrI+xYzLcRrM9XJeiO1XlLCngrAQ8F1tsjhhqojdZasDCmp
+4sdkv7wJ0d89zjHPlKxEsdT6zny2Q2NTGsba9FMsWBXMRSYvKhSLh4qt15cNpuul
+96hXl4oRaXtgtnR6bgmX3g9fQ6l71yxCTFzWmSR54T29Vo8E6hjKTTv+0E4Maa9h
++TmzCgCnEJOdVJzJ2NRfpH+BHl7524DBZtHCK+i67ACPmhe3g7sn4hbiGk1lU5uO
+9dyMnLryai9YCmL03NgJ7oZsua7/qSqotmlsZtNNbatjg3nl7r9vojk/B5znd56n
+9JB5SYIxZMuLl1zZuksuKCiHKvIFXdqhw4eC2gimsnyXVvlbGBT7RA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subCAP123Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subCAP123Cert.pem
new file mode 100644
index 0000000000..4ab0bd9ccf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subCAP123Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 7A A7 95 0E 2D 5A 6A D1 66 6F 09 32 3C 35 A4 77 27 89 88 99
+ friendlyName: Policies P1234 subCAP123 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P1234 subCAP123
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P1234 CA
+-----BEGIN CERTIFICATE-----
+MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UEAxMRUG9saWNp
+ZXMgUDEyMzQgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBRMQsw
+CQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8G
+A1UEAxMYUG9saWNpZXMgUDEyMzQgc3ViQ0FQMTIzMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAxonRcataWmsQBYe9Vlc/Fw8CXsaN+DAnB1XBH2YXYyPI
+DAfebRTxQp21q6sz2LcepGnSvbnzkzsg0nfB84I+vWmI6q3L6ydRXjRtyppa5qjs
+Zfyknor/AdboEykbvx/b5zEBUBc7Ot2nIHb/8mxhw5WnO7EVxtgxTlx5lE0SZdVt
+uc7G6WVe7/+SXuVqYnIZkq460YcUA3GtoDCx2oYUDfb3rKK3gjOLI3nK/JslrmeN
+A5kujM57Tl5JwAXeni4XXCDLR0aYymGlaJqyeT/3/SvddqEJkByyL92IAvsbun00
+bjPiY5ZRBwsBSdqwtc8wNtPPsouo/HD9gsYuiec/IwIDAQABo4GZMIGWMB8GA1Ud
+IwQYMBaAFPb9qYwmLLTP1tPr1B6tkmoduyRQMB0GA1UdDgQWBBS5qlCBpjRmUWid
+Qu4piGrsHMh89zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAzBgNV
+HSAELDAqMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjAMBgpghkgBZQMCATAD
+MA0GCSqGSIb3DQEBCwUAA4IBAQAPH4fu2YUh72cgr2bFYSRtzSeoosntPN56/dcS
+GPRl8SXABmCu/sIYFZyfRnKyTUwKPObPm0kcokAnEkkMkCd40n0m9jjIJIaSuSvi
+NocDswcOdofQx4fK/w//iW8VevGjjhrDbNUattppOWcaHkOAA+UnycLCRPYZmNco
+eR31JgQ3GbFQD3A9GU5TvQjZkRUbiAyc3ETO/rCuF+zqZ6FMoBMJgJj/Q6pqVyIA
+HLCmwq9MTKuLDhSyUB8X7OBd3vHiuCR+opFSGvIYuFpsyA20Mdmni0cJSu+08BgZ
+xGsDyQtQ14ns++kCw7xSJR+DHvOKk8LojNH6an+IbJM5Wz67
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7A A7 95 0E 2D 5A 6A D1 66 6F 09 32 3C 35 A4 77 27 89 88 99
+ friendlyName: Policies P1234 subCAP123 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E8BAB8F32EEEBDA1
+
+8iT5O9SjBr68ie7Ok+XKZX83jA0rNiVSCY+XzWW2Lkd1pNd0d05qvcBT6VmidQyU
+Sqq3MRX4DUsW2wpYeO5q00u0/hrbGJavdGc2R6VEkK7SLr08Fe/ajDEditrSf55/
+jAFj9VG8WS2TIygXZo9g29PQ6PcEiHbqyTlw7mru6UV024qoYIQBk0tBMfRKYs+T
+dD8/yVuZYLlb7Go2Hd+21w82l3prpm+EezT9+JTyPmzyHoy0898vMp+abY/M3Wt7
+XeVhB+AvxsyIiHXu9ao6V3W/icSFQV4XMWViTAPAw1YKVwie4M7Mods6Jt8qIgcX
+76TXWLEcdEwkOGyoIU60jJx0x0WCpFfS9oKY4WAG7Uy8ZRMco6n8l6flzF2+/MkM
+Fe9ldPjwtJIp9bOFT6DPaoD301sHQOlajFiKeK0Qa9yrp4VG+7hzac5EtvcL6r3o
+NLx1LxGnDno5tVhi5iPzpVw64v2dHgWNEhSzqvywvdhTLBpP3vbmJwRonYRiEvnY
+FSFbJ0kOSh3/wr1Ngu8nkui7OCh8wK6ABr1bXvasuumR6ehz7a98OTHUBM4ZCY6I
+HQHRubFwS+RyinuXseisvXfDctp+e28HP6NF8g1hmSs2gQYLXgqZW6Iv3Fz8FGhz
+hnB1yELUIOX92e2MI4hhrxPlXWHQ7EhuwYhCNraSosRzRUXdEx2LoXF/OalHDDCm
+/YZA3Mq2yukes3b55BeT97stTqFOp1fIo/HkmEtqsjlfqXuDvnqqsjFjVR/OD58S
+hEyL3TIm9XgfgGZ2k+RwBrbCr8GGbgNWTWTk7S9IJBo7LJpkmtExZwolB9AWbQ61
+oHJHvB/REdNVJpeUXD7X6h6z52TlOCoO04BLp/dmFt5s3Xfcoz1uZCNn2izmhOpL
+Ei1WnbrzHzpcVLuqdt8jlYzieM6fsg11SQjbz52DH/nC3rRNON0x2kPdieGkU3Km
+0pEH4Huh3CTky15ilJ48V4o/QDgawLHbuqfIYHNWaLDEMB4XUNFMhdUu/A1OP5Yc
+N6SYqkgT4aZDsKkQOGMmdr0RBR9A9xRIiFWZlF3ZRme1U7bESkcpRbkiTXIxn7uQ
+yC9mecUBWrXSjsFS584IqSgdUvMysHMif6zp8noDQGj+9vVj6eUnxwwFXzcr8XoC
+sDUFS8Ujf0/6F/B/W1yMmNck0dKesUnoCWX/SW8aQvnU0ikXhWb+BE31XM5yJoJ/
+FC9owo0sHhzOuOkaI0Jo0lhdubU992iBYAa/bnTnkA+UVqQO3hsilcKfrCQriGOA
+/s6UIjdq3t2EqqQtt0ckb/s8n9ljMXlWwx5mCtU+oUnNo4kKCiq88zHDcQ8oXYmf
+gsojfiUMGyM7AYHP6xm5gC2u/Me6QJlFQ/nvosaJ+w88pYZ7uJ9QIXa0mCYbr/jI
+MbJ0J50RVZ+8hT4Y2i3HY3IudQPWaWdRn2XgfYAwjtPTNwIN0CDiOBRvqU403u+i
+AkrT+cN6k/PYZnpFdKp/IBdX529ghMcHFrChq2mCgdF0SAEiLtZQZcHC0sKBNKrE
+jfZgBRH80Hr00SDzF+PzMTnDc4HY0d0s6yJ8H3eivRasK9T5DzgnyA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subsubCAP123P12Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subsubCAP123P12Cert.pem
new file mode 100644
index 0000000000..cf519d927c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP1234subsubCAP123P12Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 53 79 7E DB F0 15 0B AF ED 22 CF B8 D8 1B A0 D2 9A 15 02 EA
+ friendlyName: Policies P1234 subsubCAP123P12 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P1234 subsubCAP123P12
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P1234 subCAP123
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYUG9saWNp
+ZXMgUDEyMzQgc3ViQ0FQMTIzMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowVzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExJzAlBgNVBAMTHlBvbGljaWVzIFAxMjM0IHN1YnN1YkNBUDEyM1AxMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKLo3Ua2Xvxtv8WZdDdpkpPFPN/U
+Z2u0Tv18NRxpPcmDI2pHWeA1cHyYL477uK8uKTG4O2RjaJYV0qFuH1dHCPFVUCVC
+i6D77CObOpIBW5HiWykfHK4mpvjavEJ9t0rOOXjBTvloIpT/WaX6J6Qc+M0I3DZj
+D8NZzTztV8zE1VDHwcB24WASkAEIZ7+pI6yRrvJF/RJ+xFG1Bt+XmbT4N8t8Pm8n
+pdYEhOp0tHlMBwI30pe0jBB87UAuytxircSktrSPVl6KWb46zj4kTwIazBTlEQvF
+yXNm0eDWzqnACQo6mETSLB8GSAftaDLmKLnDvkgn3yj3lxBl/wTQ17Q8zdMCAwEA
+AaOBizCBiDAfBgNVHSMEGDAWgBS5qlCBpjRmUWidQu4piGrsHMh89zAdBgNVHQ4E
+FgQUTvReofkIMHtlrJLAEQss07SWBx4wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIw
+DQYJKoZIhvcNAQELBQADggEBALy8qNbHDuf2apnfU6p0pR2HZtWwv9CjY8NlmhEZ
+ezLvgB5yODJvjYkKNgvU6F8pCTLTDhzpnciZ95rbSmPuT6SgcVM3LA4wNhwesgnH
+70TMBv5ArkIaYoTgizJNujAcE/yRJ0nypglb0p7Fscuj6HUSjkOJFtt9hY6JhnYm
+sGlmy7/yB4K30tfCfwqUx+NprBFoh97jCvzFLXfC0BPVAtfl2Yzv+CjTAEL8RK+P
+wqa4jaQKtaotLSTRtc8+Dm4Y6FYnHLLRsPHf6sONiL1RZn7w3m4srmjf0yjCfoPK
+6WuwbFboowgs2XJXX4vtEvwuME49LwdlGo8fxbw1zt85bTI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 53 79 7E DB F0 15 0B AF ED 22 CF B8 D8 1B A0 D2 9A 15 02 EA
+ friendlyName: Policies P1234 subsubCAP123P12 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FDCD4B8C852BEC2A
+
+CyNbcokXAIxoPuGCOOBU/hPlz52XIJnO4l1FugvWwelVVyPM2CzjI+uu6Azdb3SF
+UHem3ki6T4tBk0uPUjl8fWpRLK7OsuqReYcH3E66scc/e082a9m9A2fM7z7H8ay3
+cg2cFMtcZMvw1z11UEp41aFzF6PR+DuoEUN+inTIxWzXyVkLxDilJbwbbuj80+Qc
+fRA71TQZTEuXF135jtuSztpYH6BT2dcIfP/XcQ9QOIfSUK2ahyeyxOF9FMeywNA+
+NFF9kzGFaL2u3SKOgfHX2//vl4O1nFq0MhDimA4vNzMhM23h0dylHnf8vIgf0MEj
+FLnPC8i8ih01AEeQrRCCnH+e7RNmAdfV9aMvsINkHpRtHv2kHusBO61og3d2XzIY
+bVLLwIyAeIUvmkv/sZZnsE4kH9gW/CsJdvKta/IK0luwpdTNc1Ac//QkFpNu/D9J
+UpjMjWU/z6CkC372BJzmHXyuoyuhk8zLV58gdLvv57YfuytIYQpLRMmAgrYjDXte
+aMX4k8RTicU5ji0deAxCy++KJWN1AxpahZuwa2ngJhwRhR3sOFq7LKNowmYgWuwp
+/0fRgg+Z7AEY3Uc7/Ls6+Bao6cJdolKBXiOLAGnJHchSoJtA9dO7EAliCEA1yOtm
++smPGSAGRDPWUmCxFhUXK3YfAgVtxl6sw9h4BnrVFRLo/MrlelQ2QZ/9Qp1irXp9
+L1eyLIF0JICiQgBgXYYQorOVT6j4kvZ8y3l2wbAjXqz/6dykUQwbCMezbsV8rYt9
+KYugm8CvUml/pBjW9eVj5KxPJdPCQGfyWI2cpT8PQnfqzYTKWX4mpRp/3zW1+9HD
+ks6RNvc4D8Jc8kYCBmXFc4RMdeubCBgYwqvBqFvp8YGkRo2+uttyv5vNBQpDBtvj
+6tCq7iwG43tfnfPEwxcAjc2cz9z/2u1ZnSlhzY44l7p+08x3vP6npvMQZF60AgfE
+klEnXg3d3lIr3c+vG5qtFFyq/ryTBlOOygNFM4MDcdMMRR3Md9vxkiV4YR7LFSoC
+u2J1ynXOrJFQd7M669XMXsXYRE15uH/iCAvOpAaYjPnla6jC4wYwD6eACiOyDaZa
+Dtk4bP4AJn+oIdBbua2z5i79UYRbrYxG9rBnKoP86EuqKZHA9PMr9sfeh9Cc/Wqs
+RluoNVXCS77qM99c1S+BTpJg6anyCb5vU0kFqXPMST9YUwlPFjPy4aqmFbf3gj6r
+WO8Ba7XULOYb2KiP0b/lXC61ANbXTj/ot8YE1dyVAW9T8vP42PS8GOW+fB7eZvf9
+LZlFXyNaiJ9JukLZxxvUcjiHJJlGLhS4WoZYXr/OF3Bwzp2H1rWT8RoxJFpLHFaE
+KWZsPKGQxnOWWs4mmC1/5HEOuUZoavNikyVe2QTSphQKyhV8n1+ey9cpC8HUH2Xh
+qYdSTOO+3njCqWugAerkTHpe1Q4FIOH5nqkEbH0FTYxSqHW0NHOfeLNdpI0vHC/7
+z5dtSMaNR7W8TxvnLgilhGrtPbQbZywEwHQy891/uyI5DtcAkaMg7RjOvXOwla1S
++yGgFO0q4BqQHUE2nbwojnTnczk2sJnU8Adsr21mpxlDXMGR1dyy2g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123CACert.pem
new file mode 100644
index 0000000000..597fd7e53d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C8 3E D7 01 6D 13 E8 D2 98 73 69 3F C1 B5 20 DE 12 ED 21 75
+ friendlyName: Policies P123 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P123 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDsTCCApmgAwIBAgIBJDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGTAXBgNVBAMT
+EFBvbGljaWVzIFAxMjMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCffODGihp4HxePe48+r7DuaPS/JNmLYWY1/38FcOJvrd8p1tZIEpi/bgjs6JdW
+n2T5FPfFbQaRiM5Do/3VH5oWxQIZuJi1Wwk1aENpSUZxyXhTDERdgWiMMxWi/4+j
+IX4xb2PX39awlmgArgJpBSHI3H0uqBYTOG9+zt4RUhd5aXXmq6boQA91euaSmXaG
+Y18WP4ehf55cJU7R138Ngbtne1QTE2DX0Z0ylBfS+dWSDnE22BMpcI2I3kFE12Wr
+1q2yyAtWIsN9ZH/DONL1nqUvqRw+boil1ELtr7QSlBFlYX/+mPwnDOJL8kfjRLlj
+RVZYzVZpPQBxkf1P5s/VWMuHAgMBAAGjgacwgaQwHwYDVR0jBBgwFoAU5H1f0VyV
+hggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFIwoCtoNCRRi7j09lrhxkxKJ6uhjMA4G
+A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAwMwYD
+VR0gBCwwKjAMBgpghkgBZQMCATABMAwGCmCGSAFlAwIBMAIwDAYKYIZIAWUDAgEw
+AzANBgkqhkiG9w0BAQsFAAOCAQEAK0X1I254izkWRa0Za2Ur/XYzrvZO+EF6AECL
+1EX1WCaVHxWawOIgZzfJpUHER7b52m9Tn6iTwRj+jJ40O1fjpW77TX+ooe62OgDr
+nxni6ZRq+aq6epkwe2YtdcIa+Qgb8PGKwW/WR0ucI6FnG38fuKa3YF6dzQUQKptH
+CWLoaAdo7Bb4R8nqdQeHFX1XHp8Pqw5mGBCuFAIr65gE0cqlefFs4fS7aAISF2rc
+ORHW9/7kUT2subzmmUmuzbiZHmO9cT4ozph7hrjVNjtN7STrU0PBEAHPw8E77usR
+KXb0M/xu8T5bHkVo347HGIsj5iyt/B564Swpv+BJ5ZlQwIuJDA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C8 3E D7 01 6D 13 E8 D2 98 73 69 3F C1 B5 20 DE 12 ED 21 75
+ friendlyName: Policies P123 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A8B3D2D8BA3D1809
+
+zX4miwYVKvslNFPRqn9b62pmO+46k9RDeD0S4Wf3a7AF7oWdDJ6Wjpp9PYthCefF
+jiUCOFzR97YM/hRq/PXk4Avae1e6DETFo71Cdqa9DQA2j/HYIPizYIst4E/sIHoI
++xj+VmfFPT7ACK7oRYtS9OYwUoxm1epckuQD7xpUi3sLq3t7U62qj+Rz0MfPY+1D
+7m5PWLFB7XfsqMAhx+eEPttvFGCQBennS8LBdoso2sGvt1BVvDGmzC9IGWEbb0Da
+2GlO1b0hfoLgywPtMLdfguWKtaQrGktUafS45VOB7bqynq9a2SdBnKMh4cRBVXBb
+TSG1hMYPo2nRm9COkDx8FNt9zTWi8SwnG/mKHMtUc8z5Rtt7jR/hBDPTLKi9X2+x
+UEpApfnPLVLGlXlxzEDlj/QsU64c2YHZr/Ph3gCh0IIJ57BfcnQowY72gqRhM14A
+BRbiPYtMXu4AxZD4E29OJeD6lnqQikgcrU+yLKvkowoMmvBM77LnqweS/Sq92rP4
+PetuKkC/poHDIVdE3ZVuRozdEWz6pkV/skV/cjWVDyMPb6DrB+EkrBFjcWGsHFns
+6VEMSGA4GNc6DVILbkmDLvxbZbJ3db4uOiK7dT624ZAdZP5FICpcSM9j9dorijUN
+h4YJDhMEaJfAzDVKQyl2rStvTAOKVQBOAuFpr7tOyumc7o9Y5PrwcslAAXLVQhh3
+mnKYGjyK0lL/ubZcgukTDy3Xl34HCQmKqO1yBK0cs9d++mGEkhlDN+bFUO8+uO5x
+JMMwDeOI0s+zm2N8vposIvteVZ+Il/CbvDbqNXLRrsPMEdwIeRdvL2tbMzjSCWAH
+5JxTsUROQH+i8/+39/rJziJdZB2J3+uDzMEaVwO+vYoW3Cro//m/Ri26DaHaIfXb
+SIXK+oAUKaGoffr+NKLnIYewDkg87eiIgatr1X4qrlFjMF+8tvSyJtJ6JLlJWbwt
+9kv4iJohyL8YZ+iieLL9xr2iJ0Bi1WQtBcpfjXhqVPaQiNkY8sg2kWq5MdB1BWp2
+yzJm7KFfYWsOtGbgqtEMCPp6VqXZaM52cNqgb+bkkBsZNRO5WLA0GFhVow1vPUtA
+sJS0NnVr7LYqrsKdORAP6ZQ3jF8OVA3eO3RiNFwSZLPS5wNcFV+G+oT1DfqYwLnc
+S2gSzC7XX4LO5O4THH9Av/3i9eKIm3xIwLRwhjV1i3DRuStlB3wo/vpfP1IR1Qd0
+DVaOd8kLy6asWD4lWeZ9QZ+cFnJxVPZnSF6VoLIXApCr7QU2PfnKw5yQVjK7UfqY
+nUWhQrS8SnOyF2MDWSfR4TDP4Nuy3ijsvft2Lz9YmbJNWnph5eTyypNQ5Wqz7vsU
+tUXEPplGoTFyTujfNa419DJZcJ0CjXjAtTJDZG3RwBCTgtN+i4A8vxrt7z1JID9d
+JOq0Bylps0Dj/MYe87V9tXDyLAczt6l7YTlvwZEBDSUWvzFieAQwF90RsSb/Gojm
+SLy5cAUDxBJgDBGifcYFe6a8tMbo8cskL3CDGhVYIMyJx1zlJexYYybW6M227DaH
+0zfU3J5n2OiVhhqwJ+7HapaLS3hiY72s4NwJT5KZqdi0k+g7ZxW5OQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subCAP12Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subCAP12Cert.pem
new file mode 100644
index 0000000000..d055119eb0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subCAP12Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5C E9 47 35 0B 67 9B 93 0D F6 10 12 23 1B 71 FF 26 6E 32 22
+ friendlyName: Policies P123 subCAP12 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P123 subCAP12
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 CA
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEZMBcGA1UEAxMQUG9saWNp
+ZXMgUDEyMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaME8xCzAJ
+BgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMR8wHQYD
+VQQDExZQb2xpY2llcyBQMTIzIHN1YkNBUDEyMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEArUStqR4b0h47BHbAWPMcIloYkfa4ASeY9bqzOejwnoJWbjR3
+80zGBLHB9BpGM658Nzr0hFJ8lgPAOnAoe3CzHSm7Inkgh+G0LfIFiRh8QpJagzmD
+Drz++lB+0iW9NwnfbxgQz6BlnddAWAY8Za+mvx1y09LE1r5mkfl4+cZh7pCSLekv
+eR2rw9nn9IbovnEg9Hn2f0JX586nNjL/3N/VB94OcnfZRe3Gn4UHlZBxwa6RplSs
+uDweO+g8oPN9QN9j20CP10Q22JYsZuvHPE03hjWylbbxcqrpUIDKOyehygI1K6K1
+7r9CWuSrRzPcQe4ccs6ef+1PN5WZbm91NAXWPwIDAQABo4GLMIGIMB8GA1UdIwQY
+MBaAFIwoCtoNCRRi7j09lrhxkxKJ6uhjMB0GA1UdDgQWBBTOANr9qpNA+MCgea3B
+eM4d1yf2njAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHSAE
+HjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOC
+AQEAV1edqpMmp2JfG73MOcPw3zffoQYGSf3UlbJf6rbmtcBwiKzjYvH2BqvdD0Pz
+wx+Ph6rRvTyuqF6XkAodMYU343ZnS7b62wtlx0XhoJTGSeinwsIFQsVuKdTfdQgS
+bSDGI4QHrSzjyjeFdk4sxyP9kGcKSqqwxTGJ2XWDPV24WWm6oeNkBOuQV0WmUigF
+vOBAohaCXhEyIhJrp3vYT/hmL9hE0BLgRO/mgYaZQq14GK8E/LfzRSA5eBQCCQTc
+iTPJ2rMVXMV3B79Hwa9dBuXpfVCNfafquNa87x//iBZ8kTREbBUc6mRQzpGNAnOE
+59OCcPtzlrEhGwmwAe14N3rCwQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5C E9 47 35 0B 67 9B 93 0D F6 10 12 23 1B 71 FF 26 6E 32 22
+ friendlyName: Policies P123 subCAP12 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,395FD27DFED18F38
+
+3AYCS2UD9WpZLkte/nMex4XRtt8hjokNHYT7DBRmj8nKR883SWC2u3cWQS7smc4E
+lpxM2FAvOdmkKn89bYVM1WmD4Xw5/YyMIs+49k7jqXU0gT752wAPthGzaW2QSCHf
+p9QotZvXPAz4OTvCo6EU/roSoYw6745yLvMR35b6jkVJs5YIS6woRM/sTWUYsLj7
+gGjAFarbqXFM0a9sUAll8K5N0j9e5e7mtPLM+9QvaVdSKyjSvPQbNjuq/53KM8fj
+K73sELQvnKunoC0Asw7j2DKv0U5e/CKODfiY6mnYuYrPCZGkgCtNG/cco4/CKpwh
+If2fCUYAQggBol0CKMndFUr68NTm1lhxY4G3LdGsFM46xZuEvWOdubPQTbNer3C/
+yvhSPxkg46Ow5CHQIGxlJ87DTSkUjAKtsX9H86xjwswO+ddCis6yMEHDYg+4ur93
+XsfoHsly0V8EyEi2G0nvHMmQxtd5XvtI8rw4yMaFxz6EqGEDugUDodVUibtMGqDa
+9lnBqT8SdHqUSNyN2SrpxpPoAouGmZfCcpN6IzSAKolA/mojTAitmm2dveDdX3f+
+k259cz6X8b7ZFKSsDR+3gryUuE8WZd7GMJcU9fiw6+uBVAZscNh1MtO6ve26Jkdm
+lvHe4rtnk94K0Kl1D1AmXgZEB/n20kV6TT5w3YZf+vcf8nXjX1UB413bmH08sU5W
+oZIVsJSS+EB7xVteojpwauD5cO2OezeT2OTdY3byC22d6GO2OnJeKPoawxhES/hz
+kJJb7wS4BDVwSElUaLW2eWWua20wyHGjbXktzFAMkL64ANGg3UBKel3A/wXWBCnZ
+8anX7F3kplo6GNntTuE3ccWbvyVVBgLOKFwjEkFDaFzrttviCT6ClfVwLnIMBCR/
+D7V8Jj0QYcqgkWQG+N//xNXIUYER/HewIut6MAUjDT0iIVBbjtnrMbntSx/LyvSP
+1BVN3HxcUdalpSqLsONVQA4bfYcjXSzT1hqKbPISt0DfiAjNhDpggTo59JSSof9a
+nOE5mzarUlwNjlg2ajpjBmp9EfS/n+qeM4zS92o5JP6EdbpGwBR5pLpc6EDHn7SY
+YyZntBkdeFbaJz1t2ZtUUwO6/HbI7J33Aj0I2qSK/eu3aQJedKUql2/ke/YqyKxv
+GWmr8kfOr3upBvEwIe5Qv6sYPex/1ftWFyzj3+1BSf/QNr/NW5E5gxmy9UpAxfcL
+grJ5qHD1YOcoKmFC+oTFrTpdGGfhnXOTpvVS5gOyGrKkxWg8he+G3pGsy+paJv0t
+5dRo5SbA2T6Td8QL658aOPPeD292YNFiNbjckyiJV6t/vVDsqhp97rAsRh6sFiVz
+x9SoaHxAmAAy1itF7CLZsURN8RPyWREg7Egx8aHU3Oe/7VHmAc1pfMZFygfyw2TA
+ZUfc9UjQtBe3o3IkWzKxBWkNZWPwHm674iW0/NnyyVJDVtFWzxUgTS/ADwUEVHG/
++Y/0e+GhjxIMfiXrwXY3oJS8e26AfYhqJjwF+0t1FRydqg2FCAxswyIijixOYXgG
+s1UBAM6VfRq1+/OCVLRTJjVMwYp8Y/yzHD2haRkW8V+k3wcoOdPMYcSAMIuPZ+BJ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P1Cert.pem
new file mode 100644
index 0000000000..2fc07c16a0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P1Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 73 DB 79 6C 63 27 D1 8F E1 BF 95 2A E1 09 E2 9B C8 07 C6 68
+ friendlyName: Policies P123 subsubCAP12P1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P123 subsubCAP12P1
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 subCAP12
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWUG9saWNp
+ZXMgUDEyMyBzdWJDQVAxMjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MFQxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MSQwIgYDVQQDExtQb2xpY2llcyBQMTIzIHN1YnN1YkNBUDEyUDEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZCOQ4P6kmZd3Oyodn6YD0UBbvotH9OTHX
+5zHKc1eekUGMMH3CRQgj0ze8g+N44aG3T3gVc7QNXpWnywIKQ7kaBBdYUwbE2vYX
+v3vDPK0kkR3A1r5yPAxO3fdrGSiutntn6H3HtGesSVfwTzvVijwG3RT6SfozXeLp
+Od0+arrnmh9QJQS1xxECCul54P/LhJCJlrzqA44b1Aox41nNtQLN+ySjQxX71Wi2
+5cxfgX7M8ZJ1AmQrQbMG+oUD8XPihZ373hbnQIHJoo/evgHpoX31Bj1wgw/ERVT6
+dg9GWwCaV9NML0DFGPmFwvoRdMQtiGO+MLw5yRlSrspde+HLbAYJAgMBAAGjfDB6
+MB8GA1UdIwQYMBaAFM4A2v2qk0D4wKB5rcF4zh3XJ/aeMB0GA1UdDgQWBBTkGz5G
+t+bIqdjt0TN/BeHxXRIkwjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIly
+f4oOX9PIzpaazE/Fp6PRRFXhCQaiSpPoUU/ndYBiLKY+6q3lCeT1NUaeO1RApaHb
+vrV0ZSSoKMoGChHAQG5Ewdo7ypLnknAqzxcDVIkF/DtSFjtM6x7Dd1qqF+svR0ql
+PiMct4NtcOHqtBLgmxPl6hoN050aoZovYWwQ/ZBt28khebKejAfT3lmAcW33VyKw
+tN+J7roGNPDXfJjSSHJ8eYDkoJUGemFhDaC0dwcqE1VjW/1HC632Spx2G347p9/e
+k0VYMAzGxTYk2nsa9zaKrLb5u5a9kFn+0tuFOdUQkoAzoptWuP1YlsWNuy4I4F3f
+P1+O4qZj/ChYIwALJ2A=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 73 DB 79 6C 63 27 D1 8F E1 BF 95 2A E1 09 E2 9B C8 07 C6 68
+ friendlyName: Policies P123 subsubCAP12P1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B17D0ABDD5AA93F6
+
+vooo/LY/GZ+/kkXY3ZFp8gXZwEIsDFmcLdEVy4bLO7hMatwv2vp0dtHjjg0Ls2Qg
++1zIjL8Z9xJ0hOGhkILrK8mSLAZiPg6CFDmm0DcK/OtMfB5W/Wu7ipDcKFoHSdlZ
+bIanNeODhiK8/nidSiBC7xhWzMpG7bzhccJ7hrpdKhc2z5D9ZSymLqTGQy7Nh61/
+TwDtVwugt5QDXV+naJcKIyGmeksmbvTPDHAjumBbk419s/1lJXj37M26cwAR2gDE
+ht5HNF/2ZiYobDKxKskhMfaqe0aricC4dsqzkO8BMnV8ZFFkjecQ1X5SQPtSn0Up
+mLoI7q5LN+3Y4u3CVTF/f7ZI1mlx5OCaJieQFegFKM9faVAPN8PONGPb3cf7qp7F
+sFVR7uw+nn1Eo96BwXXXbMA8/lFLNUwgS3gHCOxSsNvnuIvF79hiN2HIAtEm3BEB
+ynvJVRhForcEKWIk71Qi+4LEJR45TpJmX58ugfo5c9ZVAyWstE33qdSOq86inIqp
+OAxwvOApCwifualLWzwmL7NFis9TPFS8rNxQ4jhRi7W/OKcfNLLgJCL31tSsJb7W
+RxZu5E5ddzm+mdQI+TUN8kDYb4kxBvBE+NT+AusBi2yQYf4xKRLOdXlNSS1fSnj9
+fQAGXa9L7xccnBrcvMy2EXPhKq7EhH4dKp8r2SKB+2Dd9sO9cqEOPUc+ZqhArOPf
+x8VzV16Blx7P4PQ2PflpcT/QW66frdHo0tT2jmkdmH5N0kjdrEO9OV5ln11pWTsn
+Z6YlGYey2HQoRflKimMWM54Iw/3QTkhngCpb2RoIerclMMzLTddtbVQIN3Zv/KOi
+fIBofBUqIcuS/HXWA1KSlyOSd4giQX00KF5mtCK0h0aBTTDohjHjvXiCFVlTKz1u
+z/6qSTntwZEDrUn1iGNOlSbIq3o7QdGjIx8k6nNWIjPlmEvd5jfkFWm7XuTXYJ9V
++Of1e1Bj1fPNSzakrYcrKNd9Cwxd6Jm/uRxm0aVVZof0pN3S368pfXGm8sCUOXJ6
+ZQ/ohRnnB8rex/1wd8cASyJeVRissm848/IFKiL1C/56sPcYGiL860Gds6CpTbAo
+3RGPqEW0yVeaciKnuMZX9bpE/POrDF1BaLISWbfwHb4Hj9/8jEc4ni1gthgNmRYE
+bEhXsx+Cm8bFmcJ93wR9IYctdPIU75vb/Zzh47aeK4h6jJuV7fLRtJJSH0wmeoJz
+VxtdovojcZdtBCod/RjAI32JU/LKy0tyb+RZAtig9gv4OXWASSOGv5SJ7Z7cWoEg
+2XiDT5tgMqQ43YRB9ju2LC1X6daQ8UPV4iSNueJVMLv2OYE2JwQqNx+gPlhQ7HNS
+843ENYJ35MsMHsOzAtF5kh0HayPstuxXy69J72wsS7puljZM7KdlqG1EAZIvpI0g
+eEkAFocdakBQW/p3OaamqF8fyiTBKujRH13FeehzliQ+IlG1iiDEeb8nP3bvoxge
+U+4NGaxG3ePgpGMuc8Dv4ataxomuMCnbfHZOlsR45xq3s9tSUwnHB73Up8+KPORm
+IJvN0P6/m7rHRlIlwpL/jTfhU+bqMunkOhkaocXUwcZgBvY158MrWocIxQkV6ln0
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P2Cert.pem
new file mode 100644
index 0000000000..bb90437ad0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubCAP12P2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1C 49 34 7C 8B 44 C5 12 A9 C7 8F 64 2A AA 52 59 B9 69 B8 B9
+ friendlyName: Policies P123 subsubCAP12P2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P123 subsubCAP12P2
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 subCAP12
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWUG9saWNp
+ZXMgUDEyMyBzdWJDQVAxMjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MFQxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MSQwIgYDVQQDExtQb2xpY2llcyBQMTIzIHN1YnN1YkNBUDEyUDIwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCu2XI0p6/0X+8rTP8FMrqJKjFC2fDJHzer
+MYV5HGjBMbMVJS1+V+mjNrjefbErnD4OlZ6de+ckdTZBMwn7YYcNw0W2YAX8gnXZ
+GRZLEjGbqvVJFXpHsjrwNdftP3k4MnmnvgeMJ3T1bmUFiwStmf9BA/qWpmxblo1Q
+C73IKSRfvOQrKm2x1t9niuBiDFBsEGuGbW+oGMyV6dBgrAfEv5r4RIqbcybqBWWI
+1V2BVFPRQGpIw9IVo3nKY9JU0fPR+m3gB1RozpHVvuHBEyAFG+6QLztmWVcrPXZj
+PC0X+q3JMhE3O3N2CqeeqBRCzJCd2hsN86rJztJjJzhZiM4aXChFAgMBAAGjfDB6
+MB8GA1UdIwQYMBaAFM4A2v2qk0D4wKB5rcF4zh3XJ/aeMB0GA1UdDgQWBBTp/LZe
+VhROBh3RMv2IYGsQ+AUbaTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAIwDQYJKoZIhvcNAQELBQADggEBAE2c
+iEnVpboWIBLYhAY+KzMng7Bo142+HWiVSgn+7nLEXXODv80Y0OgvVplxliiO1D/s
+vCBHuFb84tWG5aIo0tZwir7dGsmiXxUvDBVySLbfftJZWK+NpcpBif1s0E5NOaR0
+Tj0wutAl05tSoZIH8AjZrBVsLiUt0HfYKs4ntAvcJC7CbTPMG3/8NWmWvOcfWLle
+sJUomwPMw6990m4lPLAGiKnYEbb8sy8FTmLdzLuI/Pxgj4n04J9/KRJW57dz42ea
+MfJI9M2gG77kMk0UqmPp2U/6nJkhPfiw3OXDQ+pOvHHG6UFYw99dxgT7o0RDAJHQ
+vAf808JCcAlN+EN/7kU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1C 49 34 7C 8B 44 C5 12 A9 C7 8F 64 2A AA 52 59 B9 69 B8 B9
+ friendlyName: Policies P123 subsubCAP12P2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E57103BBD873AD10
+
+7BEFF8bzxG9RxKtNqMuMrJx1c+9MZyXyWivnDXuMVUeCimHFdFYc28G/jNDJnLPj
+Cgv+0Sq0+pUJ1X8QX19a1onk4dMGdwbn/UsyDTFiZZ3CGKCx86LNEf+krJ4KWvSH
+CkrtPaHJGgFO3yEF4abyYJ8ebv9LIh5zIT1f8jqQv8lNX4ZCjCGD3mNHUucKl2Zl
+xLGPZciqDnVNjmtMn2N9AnwPO6BQsD+WZgjMYV/YRHEE3+Qk5R+QLqQMbFJfRHCf
+eft0u1eBiO7S3qkXRmtm0ny+WrFITZ07RWlbTyekU5gTG6oTIU4AxkBQeuZ4vk6j
+Bi+6JZRlDbC69ND8pFl874yPWM8RWwYqU7B20erIeHr/qI2qUkDtxyeDtNBLCYEh
++hSNh36fZSS3c+wpPv/k/Wy00J0KwvVf2iDGCwvD7bzZJ3E0sDsRcC0FUf/mZTCq
+HHXxj3SZeuPSyhvyNUhmZZaDvsS0LBYxKj7sB3KNQyZUlbOg2TFrUjZyR8U8Moh5
+AFYKwyjIsMbBusZUUwLonXtSuN6oMZPjGXtzHsSYP+Rgc0EKxx4pqpcz6+2hvYJT
+q5YMeuUeQwNG94A+EG0euhxUDjJpFQMmz+6m2YPFmIKD9a2ff5DhOgFFc5Vdn7Da
+J0IygiB1BYi4HCiQxW0+PVOx6Fgqm7JIX9FGvSdY1szLtOk8fpBb3AaBqrAUcwYS
+oseQ6GSJ3eFvuzK0Xrjfp3jcnz4wDNKYsndNR9MsKvdmIOlluZ3apYMg220FcTmg
+QVJgMXHuuBVyIYeDClyERfYph19APnkg7FSoS203UkwSQDVka+b2kpsB75huiL+U
+auAtHG5hbByH5v4B5VQm4UI10vy6zSCjAkomWk1Ld5NJNWqNmXGvEwzEzmz8KsU2
+Hp42y80X7SIeCzO7fdDQQrduDg4/GWtNtzCXCIoZQT1JQkHiKUr1lQASdI6krFhb
+vJQoE4/HaCuwZXAYurClp2cMpcpzNleGgw3C7MkdiYkiVTmg3OxEJLQPxibVVjI2
+GTbHdCib3Ya02lYkUPkbfdSdbRuc7x8bJWXBPuFWhFQTQNMJX1fmavqcNBJk7YoG
+ROz6c2cmt5J7Bss476p/dw/cfR04/PNUAgFH/lnFXzYAYhvYWNKlGqIJuZbcgyly
+rZMZkROnoYP+3vMA59u7TLbggLcco/iHa5dA6wUNA+Vru+vwNdwP5OLaAB5cSfES
+Yoorx/8mKekZYa0SFP8LL25heYB33iz+UxlIamH0VsjjDes/MFg7xzldYLaIKF42
+JpZGQDLi/MVWVQ3JW8j+fIaBJY9vpkIu73Fc1knv8JOQYY6AkbtcXQ+JCLrERK/O
+D9W9UajfhsuiR/m8RGySzKY87vCJ9/c0vrs5crJDO7AmMS5dbfwQqn9nqZekCU0C
+PZGwLY2NlxNB/OI3D8PVW68qVKLVhwc8xK8mNu3Jhu5zJA7Mig8b2xyYJv0aq2nx
+aONGptIRkAMsKeggPDKCE4y7MBgSnCFMdSQUmXcnztdSTKiLUWME5JDQyHQ2Z5CI
+SDTZZY6SBt1bb2DMI1EpP0xrVn9VJd0magit6V6gV83E3YuRr7bJTh60uCJ7h6nw
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubsubCAP12P2P1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubsubCAP12P2P1Cert.pem
new file mode 100644
index 0000000000..12bd21cad4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP123subsubsubCAP12P2P1Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B7 EB CA 1B FC C3 8A 4A FC 54 77 73 A9 9E 4C A4 C4 56 E9 9D
+ friendlyName: Policies P123 subsubsubCAP12P2P1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P123 subsubsubCAP12P2P1
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P123 subsubCAP12P2
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUG9saWNp
+ZXMgUDEyMyBzdWJzdWJDQVAxMlAyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowWTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExKTAnBgNVBAMTIFBvbGljaWVzIFAxMjMgc3Vic3Vic3ViQ0FQMTJQMlAx
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo9X8Ddrh9jmdsYRFm28y
+92U7sqI995aXi5l+dZtIFpZebhYISF1OlBVv830ZcKZgW/npnqbTX4irRR/Si26j
+w3Z9DECHDLWGnAee+O/5wRNuSlbJzfnJfe+rNCPuy0vcAJhAfz6RmueuwyEdy5Ss
+isw92sb0e/UfqKq1ReyTpHh3Q8VDXse5kph0A753UY/1ZBZbPD7/Q/LYrRRnDhLr
+SVUOg6Mlfu93+jsuwFgcB8VIkd9rdbFIkuxS196/VqtycM+KYRlfYz9N3dSUJhzQ
+pL+xYfC7FRySc63BVFRwWYXd8/vmyrwpoGd8657RRp2/e4gp1avZZ5A4mYoPQ3Pl
+kQIDAQABo3wwejAfBgNVHSMEGDAWgBTp/LZeVhROBh3RMv2IYGsQ+AUbaTAdBgNV
+HQ4EFgQUiSAXhPusuwnX3l5enmj2OVAfQIgwDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQBzP6juBoRYCOz8FzuCovzw5TK/XNmUtWAVYOH3mqjqpP0BECuSVbuZ
+BaSFm8IoFE26babq9OQ+W6YzZd2hcJOAQQA6yLHs20Es3sYk+sWpduSgLNDpf6CE
+7PFzgvQ1vwnuTANNlNLQcoNQrA5OYD1bNLnmZlvenAidbNbWDORDTiyL86Bc1JF7
+gKJFTet6SFKnVugZKWz0qcexhJtdTW6dPS7yZ1/HJlc66/KGPvD3Lxanz/qY5ZP1
+lg/32kPI1xOtoh+sL23f7iE/g/UHY6+yC4Ot4ufgH9j2wdAVhkclavvn4y9yd3b+
+nHGboqWnBZgQOPY33l7TvzvZC7bKpT5O
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B7 EB CA 1B FC C3 8A 4A FC 54 77 73 A9 9E 4C A4 C4 56 E9 9D
+ friendlyName: Policies P123 subsubsubCAP12P2P1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,74ED1B9167B80CF9
+
+Vfojb2l8T+nyB0oBZ1ZOmouMar6/f/5RaKVL4YbrODk7vnZWW8aI3p/ROvlVj+nV
+vASmxrVVQAPe/NkY741eBEjDza7hL+WMUiXUVsMh+M3iYUrW1HOWqyPBWpuB893U
+OQShF2kFJr6uquJr0lCv9VfO7mj/PsvvCU0R7B7L8xICPX/4upR9oYqvXYTCEvml
+wwfEkYgcGUtgUkMZL0q5oRevrkcZZ7a7IUAiuHfLB9/6MFqfLp7tlaT71YIJuceC
+XOpIFfs5q3MLGwD0thK23+Nd8XbGZVk+da5eOQe2PNbQUo+Vqy+AQPirTMhY+sug
+N5VbFFeFJGp4kH1j5L8aiQTZDj5AnHVX4Ucxo6taP0GypjPrxkUHS44vhYWG1OkU
+O9zJEY/pBSgjqBcLo7yzz/Rb8Pwa3rxMKpr3lffx8MTiNSE+zDsjVHtSWR/8oBLV
+7zL+NugUKQ5wZfnoNeyR3I3WmOqqyTWdVtxxYUOm9+bvt3rITYYWnfjtsoEfGtUT
+q5ZCf6CpHvZqx/AlnlpPGO/gwSWAWBd68Kn3JZ8gGwRCFS5VyMqg5M1H5LhZhq0l
+4wh6D2EiVyDiNa5Nf7vIzV+CJQOLtVCLwXsqzOiEVCTEpf/5Q8JbZgrawnquUfFG
+yG9eMXgBOaIDdjkUhrPv5vkGk9wQXHdGb5dQ56LTBe7RXVkQnrbZGyFF/UXfmWnN
+YpVIR0S7/ben66DxcTWRIG7URRw0zHXQ2WEqs7g5ha73UJc8/iM3U4kN8NCHzH2K
+AnKEew037xju3MZCNvqkf8eJNKY4z10C2PsVouZV9LC0mmw1diJ5PVXrQ1c4bD4m
+K1U0XMr5qU/Z2sm3WmIZA8Z/IBDkB+lkhGalexT1HB4Y7uTG5NO4QJuCa2EV+uZ2
+trY9T0rOOJuqi2SH/e0q4emLjEZDinJNnkzE9H3vOX0xRDPz2JrEdwzfZZiEvjct
+ODQx37tiBPBSWYurkuGSAv466gjtqW3Ob4Q8XJ5R/f+e+nJN8T06RYMYkJfpCEGH
+bkO05LWKQHMf/Gm61aMBpVKtxXn5ESHLc4Y8DbMUYrmOvUEJmcwNslk+Yo7iQNEd
+ZfwAawTElj44YMhmPAdEWVmpKW1952oprbb1AvDqdnABKTIuzWk1pi+G0tTY4hMe
+o0a/IuocCE54Qb9Oy7zusnQFqDtSsF6gzaTwDl7KUb2ax7BSJmvJJ0tjfWLJYPov
+FSm2yyn58sK0V0p4yxtURGAGk7+otqlHbKLo/bCtSB+aWRqw3QPpqIY0Eo2UqQUe
+vtQ7zyNbX3ExBQqNv6ZxTWYfSZloVy+3Ydbtus0xIdai13YhnZi7egeifdYoXNAQ
+8dsqW0n93FayR24R8PPFzBGwHJOQ2evlYZq+bo4A/RThQ3wsuI/1RTHSTfYnuzjg
+ekj4Xd7Ly0EmfOLOd35WB8s4qSwJWGQxO0gKQHZZywJpk+VDZ/olOcwTHvNmiDJP
+/PSs4OUFNm8btfpOmlfqfbDxwpFrJt0RJHZCcrh8pgg3soKKqhw0goOAU+I2Di/n
+FurVfJv+rzmO92/dhdazwAAZr2a5S/FcwG7OaEmjBKt7NVuS4sDiJg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12CACert.pem
new file mode 100644
index 0000000000..90120378cd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 99 E2 CC 89 93 4E 48 80 0D 84 E9 EC EC B0 1E 67 0D 58 9F 68
+ friendlyName: Policies P12 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P12 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBJTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMT
+D1BvbGljaWVzIFAxMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANRtyEq+rl+FhO+NHVJOJN2OiDDWN2do70bXRgbSRM+hytvZmhVtCwdDvrc66wSo
+nq+/5yMnEMw2SXzpsk4beZflV5IWBVo2TF9jdoRa73FMzVcDIQigT6JZUIGJAmTc
+VpfXbAhGXLpGdzCYV9GrkdWneOLn2C0vtKA9pyBO/60o1J5o3TMGfD79qU/UhZm+
+Up0jlotpuFo/wi1dInTyTWLLwQTOLHl92GCON+jQ7myetjCy5OPSi/YetgO1ivmF
+H6pPE7GClTgS9wKHlsdAKD/NvhJHRXKvUBV/IRo0wmYSbpPmDICaIEAT3jr9HV73
+XN4PkOkI8byCf4uD5zjHA3UCAwEAAaOBmTCBljAfBgNVHSMEGDAWgBTkfV/RXJWG
+CCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQU2F814prBNyomzoPMcw5wFSo64jEwDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADAlBgNV
+HSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsF
+AAOCAQEAkmpY6Gpz8ttXcYTVjZJxtH5HBhZZ4MQjPYWb7Yoz1Fg64BUeuPum8KIH
++KoyJFYJPmQ46Gop3uqosBj2S3kZ9zmzOd8PIBYiCn5iNZ5GzNhKvyOICWWD4nzH
+mIh0MLjON9H5aOKRPYqQj2R2vqyzqr5/YPPsbCAIj31a3XrEVN71161aPOn6wVMk
+l8/NkC+xtLzqpFxNdRlaAdmf7eT5MRy6J4GC/lf+YKp6RaPcLQTjlzTjF4ABxDbj
+57GFiSn5lzz2/eWvN9i0Eg6+LhCa42wJj2Iviruh+gVOqRe4eLjIyVcN3BwcwFCY
+BlFoAnTVg0CnLeR4swMjKUmHU3n86g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 99 E2 CC 89 93 4E 48 80 0D 84 E9 EC EC B0 1E 67 0D 58 9F 68
+ friendlyName: Policies P12 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,477909ADC8726F67
+
+estbwupPlOnz8dKiSRcBipIkO9RbXHOdsiocDzIIoSd9mSxcV7Q4LkWq5hBNkbe0
+bCZwOR8QFGfH/uNTGkohgl21Z/m5MR3lirxC29ucHS6F55Z8oqMxs92RIsaNF8bt
+9vwRRRtEVofwuJaUovh817XZZY0RqWcSmmaEA4kmRTdAIzmxzCRme1JndgBiLra+
+uhS7Z7cj78INoCGX4Hef1ctFw2WPhMU4tDcTugQqaWARAPFtMjI13vdGreQHkj/j
+oLrx/MtPGOiDb1UXXHJtLX95mX+6AX3gCI+x8A8lgtvzPgHi1H7bnutlSXNlbFLS
+KKUwJTFVH1DYooBfiho3+7GLqjHBvT2LgsLbiuzNdzle/4ZBnL36ey0eIcfk3hWj
+vdwD18Arqp9SfR4OYBx6RQcevCkDZbeXI1iUyCbGPJ3ii1AfYtve5fCU2jORSWEt
+oZ35/cBwyK7qAYHaobEoIQP/qiapCBACHZ04BdZCbOKmK9cxZDWQM2lQOA47rrYs
+zPxhwOA2syyJsOOETEB9ZK6NwGHQ7A4pw5lybKZWYxXV76sZp5k4DK5ohbaOPz55
+61JkPY76bJYFYdHt0hp1OJZQm9uN//gd5MTHRwhVgR8p50Vv/1F/JoHSfKkqF6Nk
+YQRJ6q2WY+0dDwPFcq6dcb0vQtheShnpuFO5qUluxTzR9BIzUHRdYNiXCbL8rUhj
+uxmTHe5XmCYExo0ZB3xr7RWd+f70qeWQegUdsPUeHJ/BGdGQM2wOM5+JhhhIEHXJ
+HlwbCbp5AjfNxhxv0S1xU5xSNbXWZkFL3YcCn5ecRnSnxYvgx7WPDxTiIx7WX7AK
+UxpwAp720V52rg2tPYfiru1Ew/agJdcFRKd8APSf8+9hZ7PvpAw7YPyBX+UbggBG
+br0SyzR6ERfcJTYQoq5jRT9Wh+dJMiQ9RZaBvz+PUBRwNhzEM88zyuKYI9TM2T9L
+3kadHiAl9KNNGngJj0FamFNBhhHGa1d3x6/5dLo+oND2zYmaOjEiN42vBR73cBlM
+cl1IwBV7zpj5RvLRrIXQeEGirzPYQqI4Sx+v9s9s7k+Y01qEKNlzY6hVJS8cDHaB
+wy8zM3BVocNGw2kQ+HEviO2QnfULqUsd4fS34FcYXkLX1socBhmf2tOqSkztn+Hp
++YpJs9lQb2ZvAXSSstUghAJ/yarsFDmTFFY29kwr/sloVc1T7YmUlWfgLGlPqByM
+sV7IJG9SExfCDTLAH9Xd0XzcNhSsXhDzRJL6OtL6dZsPNS7vxoMVNPPzitMDtfau
+Oo5ZC6EmQNc1JcxAhXghQCrKjKU28eAbX6a5cjeqzvatmVvnfGWZNENhPVlPu658
+wYO5pVGT8wISe0QZqyLLMN8DMSBYZd5LT8epY13MpfWFf3BcTdCMbqSxijZo9ll6
+eWrdc/6IDKPx9wpyadrmf36/I/QNzS2VakhQ71z9H1QntqUuSoWewi29HWpgStNL
+2SRnRGRKygqy7kyrsZTx0Gjz0lXnQEUhakHxcFjReN5pkwbTpkmnqurhuXbJQhDx
+8xaoP68lOAlS+IWBWsBiMu3OoSC20hwnCPcrmrEeUrywoE8oLGtfqPwuLT8xVY/4
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subCAP1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subCAP1Cert.pem
new file mode 100644
index 0000000000..17d257c76f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subCAP1Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 2A A7 81 DB 5B 2E C0 0B 4F 80 69 F3 74 65 99 7C 24 03 0C C2
+ friendlyName: Policies P12 subCAP1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P12 subCAP1
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P12 CA
+-----BEGIN CERTIFICATE-----
+MIIDjDCCAnSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPUG9saWNp
+ZXMgUDEyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNV
+BAMTFFBvbGljaWVzIFAxMiBzdWJDQVAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAw442fdRTg6Jv+ElCoFqKteS7oejZSQ2gkdvxjcCLHsujyZxb1Uoy
+vAnay9r6w6qOTgsJ4I1YO0XSRJo69S84jF2Y1/M8CdYS/cCIFVLaB8dOFz+c54LM
+gVkNJQGCDJJYmGWWVIvs/yEPX8wIticxl6EVBq/UYhHHq1bvcHi8N2g/uzn1LHWY
+rW2kPkXNbPkA0yUR07+sN4yL+xdi4Lp7IWAYqFgtW9gsQDigqeiAS33gTs0njsdZ
+6omNaJpuKil5y7ml94/8QJ5iJ4V1MFynga6h7fObSMvW8xe+CQY3TPdUe27z4Jf1
+O+ndMFxWgv3rskq5nTsX7lTKjKmGOHB8lQIDAQABo3wwejAfBgNVHSMEGDAWgBTY
+XzXimsE3KibOg8xzDnAVKjriMTAdBgNVHQ4EFgQUIp7XDrhIzgkOOl2+1k1YI1aN
+y9YwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
+HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBQYlzL2nonRz75w9lngMPR
+kh+gIpr+MuOWEaWVYdYv61En2N4HIYxum4dXM/lobJlD3LtNfAwY5MLSld/7xpRG
+/KGJ5VEOg4f5J8cnBoBSCHKJfm+udg1wYz4nsIpsoCoUueLLnaIsJNSIVH/OrcGx
+wcWdKax5udzVGm7v+IKMyn3+S1By3VUACGY8XyGtzeQB4cR2QrhRhoxyUJ/Wthfr
+F5Ust1dUVtCNIZ8BJMEcSTvAsnjzNbmHudj0/DiAuXMF4C3uvUncoZsFoKw+VT3o
+FBsLX1QVPwaeXRvzkJu7vJyZBaWxvm5igkpqCni36UY+oa7OlKzLny7JNGg0ZJ5d
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2A A7 81 DB 5B 2E C0 0B 4F 80 69 F3 74 65 99 7C 24 03 0C C2
+ friendlyName: Policies P12 subCAP1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3B926AC0E223F935
+
+RwLOUodurgoPZ10EUaUobg5vPB5zDoqYjDuRdrDuB6cxiChkZ8vxBPm9mcKpRSPH
+0pahHhjJn++OK1hQgCag0RB98U8KEXuix1lrt16yW/PuXaACx9XXOAgM45SYtXJu
+FlMrkdj16kJIFcM8Za3SMFPiBaxDT3q27+lNuPRmS9kwbZugfqil22GBQaeLhwn+
+Gbx1J0waeXLNFR3maPWcu7mzYajNkJPD93YaHp1/AQQgXEbHmZ05JG8UWpbHBsYO
+5E25H5W1lNi7BDd9OpIVQaOCAwBgyrqtbf8Tlt4F+HbSb+KOf00yS9zkkE9HBo/T
+a34S67e8IoTQwHsC8qabuq3sSK8iViHTFCVt0NCZjnGkXBAzN1pTbtsQE41fiklt
+bY5G09GkO1oiqnIgujGyMEw3Yzzv3uWSDnAQxvl6e+cdWuQku9z4UTcmYkkjRR2G
+CGGtF0+bY3UpknUMHu2AW53bFXgc999JXCCrJteMxA5DYkBXuMbo6AT9o2A2d+D6
+ZXaoRqrwzNr9WjYSIVBn4PW/7cuV/tt22A0EiV5HjDoqZoMPwZQ3V6TgsWojkZMb
+JB9il7iaGBvmkNfHRcTOOYYE61fEzv9rDAiKm5Az8wuYpAecYBPhUCAprrGqXOBk
+bpDVJ+X1bq9EMYpKl27Pexc0rIXCFLh266QVppDzuGBwITsjihP0V0ljishfX2H3
+Z5WSRhSG5chILWnMc9xj4fMsMvNR9+kbRjRFSMupO5pLyTSIJ8XSzUmBYZLNXnaF
+oX2dtDbyCVw8pftJaWDBjZfGntm4Di1U/ic0mmCIT5AGK9sAmSSG5Pb4u55VuUw3
+EyyZlduX7OMArSAHxMmTwA5i+7Fm5CHhXe5Og3Awl3jU8UVvocm3tAMIbiucI0oh
+jik3U/3ZcNJoogzTehTBHYsvLa6ZYkw9duRHvCWalWJO93cfDmlssdu0PceiCRl2
+p1QXkqe1XercJkaQWAEbW5i5Q1UXQNSRA4Ab6SRxRWa06agT++cVuQqeZJdKKzmL
+FxASyjYCi1BTVLcesIKtgyK3YKS1as/BXw4R8Y/XZa/o/KYx33Fg5IcWo64DoLrJ
+XZy9UgqIIfNBZlyqj1Lhf3nDY2jnQlCbz6jRnc3HTtOSWzB7Sf92JT6hThHFbksC
+IQFvMWvcOh+rr1M+kMmmpAv4pn0TbKZ+6XqyvRKpUc/6D3pb1XQ8jCoKSoYvnv1K
+0WkTA+BmP9uhqeQM/DPXxyNLnSxDXVM/prV/Zk6muO9J5/J3vqVwOSlX/d/qnaWZ
+aXPCz8S5u5g1T+l5mAhu6RlA/zQcC99cvocObFrTLcPcmGLvOJKrrpIJqUDxZvD8
+JTUNo5ztAnI64gCQmzbIkeEue9qMlM2iyS+ihgiaYbAS6adtfdpC78nqwcGg2cN/
+pSPbrJx95ydM7MdMiQbxcJXEpWc1iKZ8jBhzZtaKmkwnNNJu2mNDgWhlMILV+MLZ
+ZfWOyJvJegtBUJY0seTv92SR0on84hmpCvNf/ornBIEyeD9US/Px7lzgojV/ST0F
+vtcP1DBx0Rr6D0bu+uq/VxgU7Z5ZLrTM0uDpGh09s0jMqI8lYJouKQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subsubCAP1P2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subsubCAP1P2Cert.pem
new file mode 100644
index 0000000000..e7879f759e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP12subsubCAP1P2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 6B D9 E1 F2 73 99 FA C0 63 3E F1 B7 35 05 BD 8A C6 CA 41 B2
+ friendlyName: Policies P12 subsubCAP1P2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P12 subsubCAP1P2
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P12 subCAP1
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUUG9saWNp
+ZXMgUDEyIHN1YkNBUDEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBS
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEi
+MCAGA1UEAxMZUG9saWNpZXMgUDEyIHN1YnN1YkNBUDFQMjCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALcO073fv8c5JQbdcjDww0pNGK2g+usBAvTQmcWh
+Z3JhRdupod8gbYrEkMWebubmwz0qpdnMT9DN98KvBxnvzT1qUqAGv3XcUjLGg1mp
+AaTvkmSxHmABma74QKv9v/D8VfvHG5kzJU0HPlnJZy9yVTZs5pqdpKdE/8SkmtNj
+0fM96XXKpmprpuCzlhvujpi+3SQSbrXFK2cFgcXHsRp+chRmb3bLhg2W+cyU+Fl+
+YUMr24pljeGGZfPkTEmjXBxGsC8hYjwVWAp6Mpf0UavA9esKTJcsFHn3rMnbBZvx
+vgmV1YNRBo+CmUmH8QWceZ3AthN43SXUPsFDmTa5ThAXwskCAwEAAaN8MHowHwYD
+VR0jBBgwFoAUIp7XDrhIzgkOOl2+1k1YI1aNy9YwHQYDVR0OBBYEFMelN6fQ+iTl
+fN/b8l1p2+7K9pnuMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBcG
+A1UdIAQQMA4wDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOCAQEAS79LmgcD
+s1pCo0RLnthY6dTlCGa1z1TVOERBuf5VWC4mO6UdMZp1ahIegjocC5KJzypNyT6k
+IGSP6NeBN9rDF1smYx1M24mdV0xzQlEG1lcY6fetIvaC/U9i9nAIqRZStNMA59gW
+4LH1ctSlRIoErJFR/DsKkDO0LumnvCE79qs2PikXuJFPj/tD+KnSFNhZkCL4UJKm
+X7g0gXh0y0XQQUqzqwP/VoitGZJZ8ZeNvnQTfeMaS8z4+2bIMzdQN8AyVtSpWtnZ
+05VTmnYBCfFjx5z3f1srHvG84jzAedaN1Kpnebds3wvLW2ud8J/3t/mlLNmgHWFD
+jXYibav3P+Q6Dw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6B D9 E1 F2 73 99 FA C0 63 3E F1 B7 35 05 BD 8A C6 CA 41 B2
+ friendlyName: Policies P12 subsubCAP1P2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5911C827AAE9BB36
+
+tNsN0h+pBaoaYxjnxOvt75qBDO7vz+EawZ91cOaiBqDFSkXBLNpX+6vlzNFRe2Js
+nooSRFh8snOZxZPRa8bPmVg327TsL4sxVq+fpxEKGdevoOnFlMjTbX7WLYQcz/Mq
+60mDQUyvO+Gp0jDjRxOduCUHvzdB9ZoNmkNFuQ41pxKgJ/HjQ6djXiCb4REhhjbL
+lPEJshawWWrzKs3WVkE4xsFM9qoK1lbQ298XGKtWRdx2aeKjkTNbY3ivDfbMbpry
+deP2eEbeSVoUk2JQyqQMbhgffguc0gklEs2x4ioiHFmzzY12zo+UEaJ/8lHKFMBB
+Lb9Y1Ty2FVlnF0nt3bOTRdOjOLS5iePU0/mxQ6VC8OxGo/E5xDjN1JNvD1l8Z/kn
+Wu6Y9dmU71RYCzX6mO+LkJ0C5F1IuZmQjm8yzVj+ySoTNftryb8H0j87q0Yv+K0k
+Jc8YU3ivqIhwKf6Y+UtlyIuGy4bWv6IdleHeEHLUntMPW8wT9mQVY+PvGioZNeQz
+Khm+d5xTV/F2/2OVFJRg8RFTHwvkt/yYeq/8DvkOVGgowptngoLWJsnFiQS/muL6
+99CTkY1Gbv76JovHtILsWnXETar7m6N0UjvDcDpoWWWsOKK/OjGcUU52UPveL5C2
+tHIu9uT2ZjjPXG/XZUj0kIWVnZCgj3ipBRAIVaMBwx26oQlJVSC4HBSblk69K1Ts
+TghKKVR3tZi0ivkULcvKJLQq/RBXpRqnZUUjgmrHG9STK4jtuHUdkkibJqiEd578
+7UYDtXdRll8U4HfeqVz0X/GEAlsRhHNRCHtJVm6zsp1TnkPGmRe0RCZH8KoLePNe
+2Zi9lHwtG58VX3/yk2z7yOejwanHyMdUqu+bcRv/J60PDIWrvB2uxAzhg9DYFEU2
+Al31tZ70OQRXdDxF6Ap/4KD8s+otpwbGPT6qVYY3FDHTr6wRAeLyxI1pvSzRIVKY
+Qm59iuDxA22q/i2YV2Fn9V2pxXKa0pgfl8yJjpq8bObVSgS+Rcb7VBqLJ2/nP5vc
+BkbVOUc5RL+NZRaSJoyf745XRK+GmEHGGjnT3b/0s47kpZcYWaJKX5EOk5JOgTK7
+acYyT2+HpwKom34EjtH+rhaSUycePW1/GWcBlD0nUZAld1+SEHpb/CZwyD8b635k
+g2rWen1zrJSXRxxyxDEGMfQeCKX9bW8PovbzyHjNc8CRTQiI9ekxgguTikmhFeM9
+y5pM1qRP8faCqsXoZohinGuN1SMAA+boWZf9KSMrDuO9EZWpDzLx3XBgf/CqahEe
+aWuIfUQ0GbBIarYaWzeH0YDXKsjTPChRKEEY5E0m8egB3E71CVMIsHf8Yg+pqpBi
+TpCnMF82ejSvFSueaaiASQRl/+FyOdOOPsxm7FdHjiKy8/WLDCzDymXOp/oy49lP
+FZYKEuJl5K3q4VI8o90KGvbl8RLt9MeLKYI68cT4RhcD1JdB+pzPbVDyf8BYsNFX
+K5cfXVbu1oLBpR0RYv9u8QR5OMFTYeMpoTtGaeqiwl+2812UgYw6dCtGThDHUysD
+ypUueOn7uiA6LqIne3BB3r7uI88ieC6N0pm3cDhBsnRy1rMx6NUWEg2dqzr7J1ti
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCA2Cert.pem
new file mode 100644
index 0000000000..e370d68fda
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCA2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 31 29 A9 E0 C8 DF 5A 0A FC 52 44 4C EB C9 1F EF 87 BF 5F C6
+ friendlyName: Policies P2 subCA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P2 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIBEjANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMEsxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRswGQYDVQQDExJQb2xp
+Y2llcyBQMiBzdWJDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA
+1Xz0YVwI3XzROYh8YMIlBawvv7A2+T/y3AJJ4+yHFGsIYWOnM7LtEfERfkeGQlSA
+g9ad8IFH7vr1ZRl5SdgULBfmHAvEz20vdqFePL8ArM0mOuZU/pNNc7W+MgMV9SxL
+5dpwF84+dLuqHVXtm4HNgl6Ov2KxUcAac88mC5dH2cacGFGSgeCdTlmBioRNWCNe
+L9pTjpJ1VgopLB5ZytlScV5p+NgihrnCkRKZaxwKX292SXyTbKLCr6F6OTzbjzX+
+qOuFUPfrJjMISRlK2K1oa7d6FN8bI0mzc1RKiyLRVc28IS8QzXcyNKoS7wAE9mBQ
+8zTn3YfQE9ml7snMbH5PAgMBAAGjgYswgYgwHwYDVR0jBBgwFoAUWAGEJBu8K1KU
+Sj2lEHIUUfWvOskwHQYDVR0OBBYEFBcs6gO4B3eBPWWlvzMfzHrSmPy+MA4GA1Ud
+DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBcGA1UdIAQQMA4wDAYKYIZIAWUD
+AgEwAjAMBgNVHSQEBTADgAEAMA0GCSqGSIb3DQEBCwUAA4IBAQBCi5qkuqZz+Vu+
+Up9cFMNPiH4wEsAkwBs/rDcvCv0yHjpooTNz1Ra91TjgKPnqfkFjO4j9bKQebLAo
+lc0V4O4BP33UgG+jl1zZZVV+vRtC8c3sXDLyQXB4OmR1D9DDol8zgb+NbXn0SHPe
+3a+qmtBultEnrDqIdKl4cgZPKDioiEyBNmORsg/qI3bmmgS4U5LG9QI1HMUmlEsU
+Ccb7UrMih68eQ7lvITV3FRn4x+J5Eq55+gkuWTa4rgbPrjuAoTCHuzt1QH+u6kTm
+F00F+dF0jKW90XMIXq8P7OcUvQwuNERJ0Kn1NXCpyRhNMwW3BzWLT6eRJrr9nU3v
+Prz6Og6z
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 31 29 A9 E0 C8 DF 5A 0A FC 52 44 4C EB C9 1F EF 87 BF 5F C6
+ friendlyName: Policies P2 subCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,697AD95373C83CCD
+
+sX+rlJImW26DSahjR8/AXFABLT4Sa9M+S8quVK+yGb/1ZlS6iw1BWE1OGOk8k+wz
+TyPZNHjTdbljCInaN+TNqxwkj7QdEdXvPlBdpp7zwnasKVXHfRubnIc2E2EYQf9W
+ydBpfH7r+vUbYNfoSJymA9XusFvIw6Gn7HizzyM4f6oZKxn6lTXRKo0rWYKCZJYl
+OSTTRDrTQlJyrGvBTUN7yoa4PPIY7UqTgqS17FRACIf6rRKlFGHAjVhtb1vpYEQH
+xMM6W+9ZXrn4U5iHfxYkhOXttCs7XQ2+4fAO8A4PihuiajYdITI8vyuKPUps2g7m
+SLSz6al5uVncaJcDeUpJ8Sic07ZXwvLjr3gar9bTMCd6DZtFcRbUq5BhAHTErWOK
+dV9qSlN2kH4AScN0c7T5Ex8dtR75I6geW293cdh54TRGcc9H+MCBIoc1cQa/ixzR
+eKbu1mQ7BDRyInMyLYQR/PU/LYieM4VhaJV8+MC0WWrWAARcEtUeaCbEQnL5vN5+
+vyz571ZbIkET9STEo1WF/+W8U3umO2Aaoi0hd/eE1F4UTpUUrJsWFUASMlHcDfa1
+ikcH1LOR4m2I1ljCXlxMT9oRJBlocyVYjLN+wO32rU8WGeoAgrQa4sRLS/emNYX3
+t96yeCkIZ8H1nAfQtyhioqoCg2fEBLhpewiUexu2o2IknJjyYRj38mV4SrtJSWYo
+whV3SndcmaSWrf4fNY1HuEdzWPq/YdKW4TWm2ptD2v3Eq8xLPCO59lQK9y7rvzk+
+B1qoSFYME5DIWYn+yId/dhEXqqprc3ax3ki5HM7TzNZxZbaYlnFZbZDHBpvGQKHH
+6TQFCJBIzPQ7UfLxFHasc0RkQgcCWKfMM0Twya7GRYqAIcPIhn2a6zQWy358orya
+8GYjKZkif8thbVfnrXw8KKlMrIpjgEhbawD7djNp89cfoEU9ZNTVMS+z73pGiiGt
+SOd+2TvsPI8l199GaxHHEh1tKcxvV4aL+s/D4cjoCZamWOVDQmZLwKWhA1yUbL/M
+h8Oqwn5+FDXXSU42ywOT3geipg3dMLefxHD53D8yYURwDOZq+f0svO65nFuNvxaa
+dTt734J/oySW3hloc6cx26mk2b1V7/Ne1q2WXnBit2698M0A9hBRq+cE8eAdBSO/
+l4JpGP8CNXt5Pr1WuYdSN50ZJBI1XppURb7O0h6CDQ/LA0zCFPBYOHC3wmg9cVIG
+en150Z4D10v7Zd3yM+Kj/chVuYTff19iiR+k567/XlZkUsK00bITAwF8gaFY3LJH
+k3mpmpyuqxDSLFuZDY4n6O9yPuJJIzPMwdbVHCxem7Cx4fknG4Xhaealcbu5c9zS
+sxwOkBKyy8aLxGHMba783VNOgBkIf8tVaffsXK0aUmWJiIr4ZPVBzTtP0v935t32
+XTj9B24T+N25HSdTwRL3HzWzNAjx5Ee0nRyoPltAmdQ5/82JrSniOf7MnawJfCXh
+mR1woS7qLblTx4FYtOOO5qMIhcOf2aF0Rf5N2TYgl0Uf3cSpV0JKFfM5yHNgJfXb
+3PThx6JrE0byyiyRxHiF7Bi58tWkxVIk9m7eyhgS+1xhOmlE4Rxta0AmXTkmW1J1
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCACert.pem
new file mode 100644
index 0000000000..4e4382abbb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP2subCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 37 36 52 33 7A E8 77 97 E7 C4 84 96 23 ED 18 38 6E A3 FC 01
+ friendlyName: Policies P2 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P2 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBEDANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMEoxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQDExFQb2xp
+Y2llcyBQMiBzdWJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAONY
+pdHnfkkbKL2heQlsPDaTK3GP8UpxbIYB1XqtUGkKluuwcYbuk5IP8Epdq/PjxCzq
+jS+3tTzOFpNKRk1722cL9fszIEVupG0F69OvZ3LLiz7UxvtTQcPHYdBrOmuJGr/j
+R9Qie+7F9teXcKCdITo+5Zx65qrcR2GWoG0kqorbgEg5ckFeKoe+GnMJeR/HyzhX
+LQhi6BnJEwjFCmhcTNkdxUiIEOgNqV5A5mxYq8Q48bTaQTBkU+1UanUriLd0qcqN
+3uT+ZlvFU29GHZ503xNV0YMisbl4VERoBPZgJb5nIZoPyejMkpiVMTMYiIjCpzwe
+4BRFEJJNI+5NhUrReDkCAwEAAaN8MHowHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2l
+EHIUUfWvOskwHQYDVR0OBBYEFF48hHOeMHBycZiugTYZ2yIOfK8DMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
+AjANBgkqhkiG9w0BAQsFAAOCAQEAdGtNBQ2x5Q2dsg3CvXxLjMO5Ij7kWTJ//BY9
+2QuZ/zZrVlYdCn4zquXXdGo96fSqJy4vK+ERQCVk9uHNs3jTSoQRN0vYGnKoKt85
+rEeMDvmahO44MQaOZlG13PwlleVy598Cu7Ylis1mnq5s3oDozMau6QZZIljdt6VE
+OernrHHcr4EmEmw1HuCIZZf8xcai4hqcrXw5GJPGr34uU6fedvmaKp1/1WWHPoEk
+O5CAiMmo8t/yeYWL1HmVkwvEwHJ79IXZFi8sIyO/8HCufS6DD1FthFlQfBuYHdjo
+fReXC5SMPIxbpHXMAUPJgTwm6HoO9/XW0WzLxCXvu9pMDDD1IA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 37 36 52 33 7A E8 77 97 E7 C4 84 96 23 ED 18 38 6E A3 FC 01
+ friendlyName: Policies P2 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,203ADBD94D3004F7
+
+s28VgMsa5ofnjYv1TT+og1HmS7mZp/DahDg+fL1UdNhM638ec1lX/ArpfBiDXhW/
+KvdQk0I1bsRdpdDYeYnUAARhH3Lj45Hnn935CgpqKVrUiurhLdPUel7zVyW7UcyZ
+7CAAtFJKmCXKutlh73IdNP2g265gtzyupMsm1+rHKx8xxt2J3s49IltaDbpFgjPK
+tpQD2SlxlJbp6QY/hMktqd3jojCz8wh3WZLEC1Wj1zGPNgl5CNtebyb/8S2itoy8
+FbV0xti4shjNR2MQGAw7YYT0B+cyt2E9duv0zfRNLzp8rS6G9wHe9wPtnga+Qxnb
+ZPe7kvQrbxKBZEqKeZKmtI5pHqb1HXNnr07FvWDWIKt0H8iHTzd2hv5fA7lQLJEN
+iGdbl8GzJpANq086bNvnZW4maGaa62nMiCm2Ei/wLSRZ6Hv3HZ3ZluDDnOaW7OW3
+dHH9V5AwG3uDLvTgZDGmixcv77BKAdD2Arcafrw6Ii/XFcLHVn3FvV6xrVP6iY7y
+7XtIt0U22jXBZdcLMiw+f62EZo33K0HihkHEN3jfSMC76e/hgBhwh+XwxB06KvG/
+pqgHrwtQE4hY5s9Pv4kBucpl3CTYieD9VT3kQD6q9Od37q0HHWl3xqX7hvM7K/pe
+mkwpd/ellCR9nrAMuAs72xlAyJ9zVd/OMXA0NxzNxMplOiYG2WXOUAOqkTLt0tq+
+8ILg9pttE30zVHhjpVTZnGyTYrLKGnxU9Gu2QwGlKzBt6mTsT6PY2Rp0hR3RzMSG
+cj97CRBZP7l6TWBYahoZEXkL3AXGfGJd5EkTOnX0PVOe0JRPVd2Hn4AWc7uYtGr6
++1vXFtYngq76dSkErvXwKLbdBuvllFnj5xQbmcVv8/nvCzAmdhcIKDUDhBvZSYno
+kpcBE+1+Gkg74drj3ShYQ43z0y+uyKOb5g3IG5BsEhlEK7L7TZ7l8sFilRhY+oMJ
+g/Wo0aiLk6INFR7CgH8w/r8R+4uwwXIKoS7BvyrREfYJWaBicEld+AxiWNWS9Zbq
+jQoUPHup/cRrX4IpO6eMmWOT5t/anONjWuQ60ZzLVLi5pSFSKFYO2mMcZyH+zsNV
+G7xYMFkqeMr48xEjQTMuk+peXYAndmvy2l2Z4myFvjttNjqmMqffo2+iD0UX/jmh
+fzzHzxvptCdGd2uNGw4800M5oF14yI7GGAF6IqueoyNdnmRUujonThFvzKUe92W6
+GPNYtA9V+QN/ZJ4BoH40tb4L4MFdHWtS7ZQiIFdglbsHK+o1v8ULfz1amjI7XCXv
+H78Geg4CXX209lwW5ZXa9aDYWsuy1BnMhs0xqa3dHvUf5N3QvSuheljopo9nS7Il
+FU6XbKnpxUHOkJlJRggFK35z2FFe0lpJIbDBl8Zt1CoXXcSXL7VyCPxtQdVgrygI
+a+OPnMQ10ibIksGEbW67j5iADURrkN/STXToV9d90ffgsAZFH0isr4Dh7FBq/vn7
+djqLZk8s8uIjZD7iYreETwhdaS6zy9UWXkgblam195/AnA+qdUZUFyTXtRzII0j5
+UGIA0wo3HKiU/B2oZMvaErkV3sVgsz4bLN4Zs6JPIfYh8MEOBoSwIy5AN/ozB2b8
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP3CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP3CACert.pem
new file mode 100644
index 0000000000..9155c3f497
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/PoliciesP3CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C4 72 AB 1A AC 9D 3A DA 8C D7 3D F4 EA 8D 94 4A 8F 6E 61 CB
+ friendlyName: Policies P3 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Policies P3 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBJzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFzAVBgNVBAMT
+DlBvbGljaWVzIFAzIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+4HTZ2qzQpYWTz2Y6/AOG/uDqyc7uIc/bltDD0h+0g3c2Y1cK2couvrTwShS8gxcj
+2va9m9EdMuex5Qk0kiekGoKNmWokKAKxTmVeU8fAgcPz7NJxLjsF4YX7CVVeB4+J
+YeOwT9i+4D7qQ0JjZfmZCqxJIqWKpW/U1C43QwMh2TvJ3EIAFwLpHqQpZanugNJZ
+Ljf5Jpntjn1dLFAvk086cx37dNn1nsFzy4pOpzSfMYK20rHK0VGtyTHc3AMR4mjm
+q2SOv5Xrnx2uI41HNxk5BHvX745TwS3sUBMWRTw2G8DMXTy1HonZxVc84GWDW+04
+RSpgPoh99Inz8xPTTNOTgwIDAQABo4GLMIGIMB8GA1UdIwQYMBaAFOR9X9FclYYI
+LAWuvnW2ZafZXahmMB0GA1UdDgQWBBTYBassoIvDktzGrWo/v/PGmOXc/TAOBgNV
+HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwAzANBgkqhkiG9w0BAQsFAAOCAQEAXXC8Q5AzwLws
+Cynt11pa7Nl4I15DzEd661tWYavZj5o0OH+dKdu8kGRaH5fJi4th1oWdJ5V+y7OF
+XivnxP6fZMZy0CJhLZhoCm1O7y6BsM4PMOFRgZ7kPNgoKTaT9tMmGXTJDsG+x9ph
+/Ro4xL/ZAdREO+fN0r2LmyTZ8zud1D8mV4yrWA0+HLj6MoPe74w5JRnjI1bLp/pX
+6Rw5EwoYNKrKjMp1VutAEY2ZSdKgdzP1tVnMn0WsluxuzQbLMZ/Zzu8U+HEGsBPv
+nYWynisQlZsxqlz4dLqD1FuXv12GExxQSr1AbBJDGcZZg2D/QbDXT39lYKnjRl+U
+J9DHk++AHg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C4 72 AB 1A AC 9D 3A DA 8C D7 3D F4 EA 8D 94 4A 8F 6E 61 CB
+ friendlyName: Policies P3 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1EED1D6BBF5F074C
+
+mL1q7sb93AsGkMS7OHU3oQ45uCR8jlqS4UQ1Vsrk7FIpmFdMrH64USyIOidqT+m9
+ZSJQbNcv01afMqam9oOfqeEcnWk6oniiNDUpl5RO4cfYXtzcvnqJvOwRqYpT/2i1
+KgpfERAM2CxDlvj57L1qa6znG8+cs1+Dht4gpZ15uOzeKg/NNhq+JLMQDOJQ6MIi
+BcO2OAEw5wWCZd+K1/8kvdFPZK3sSC8Cizy5ktHR/OONbH8BzL3RvGnFxZMfQ5Dr
+E8Z+KysFZaX9ZbNYowkT/IcYxb7mwLBtk8owDcBfSFb1bwJD77rEbydxETIjCLyF
+VcSMshOBu31D+3/VuxWFKhrwXW3o6VDnkmoK973ckcfpbJBq/xtFzT7CaNbxEkPN
+wGZzbsfqZhgOeXjBdxEmGwY9RVUt7JUQXj1R/5z3kFzwehWwfX5V/W8gkE07MFQW
+7IQGvkBhj67xpwh2eK1oLhaJRmU/Bdhvw3Sg2qskcdzX6u19FEryGd+WGkuHnV+u
+d3TKTXbUrcZqeHt/+Y2s/6czgDA+3NOUd1WN5CRSerUcCLdemC9KWB/zLruLoFb9
+6neH5V9rmROoMu3eJWdEQTUgYrBx5z38e77Ya/u4gJY3h+kqmsaDQxNLPLdJ0DoT
+qa/JGIXdXlscz6xH9DIw1fvpvq/oNASGk0ln8LFZ9CAE0bA1GxMbfdKgPj2h3IdV
+IrPwwByTurTZP1LLL2z9xI1sqB5l5eHqvkv/QbrG1NS1X+nbHRavQBLQD59ibwsU
+wJIyla5X28e1wI6Jd0zyQamu0UxAumIBz1Rlkp1WN6bE3QR1xwvNu+zEFKfn/x4r
+pzXo0nn8yxEP72/LwBxp31ohl3Km7p13nLwx8IRQMt7ifFZsSFHp5dLNourpOcmh
+ACYjKDwTtkaVx8Sq2UnCp/SWq8ueA8984zZuZ4NxTYkrVx4LWelGjArey+FCdODi
+f6iPz16azcS2/dl7SzwjBescepeUo7w76O2xW8fOjksJ0gVzzNtzH1wKgIb698N+
+WzNZBsxSmg1Oo/fW9zDIhTbCH+HmojlNgYc4wUDK79Vll0H/nizy7Dt3xkT+GWIL
+e3aZLJ12L+0db/xwlIf2s4uKNhuPLPsxWp/ecOt+NEeM6jIuS4Hn9eSQqv2C/M5D
+6VQ/ZKjZpB0vrh0bmDOJG5Ly9hzITDOW5Ryh0q4ahDfoQwP36rhfG6BAIHTV/olG
+KzQUaCvUk/154Nh+kIUtj6MlHKLa4kVYgHGR0AdwZ77QFtxr0Wk8vyhydOhxVbj3
+TjaZKpcgtW9RSIsIHTwR9Yl0Wx2o+/s117cXasubjkwmkofBXzIYpqvrws0feObT
+w+KXNvitg4LLsoRjRNHCKR/5iVVPe2bdST03SPhNr3SBc8RgWT2qEBHvgQrYASTc
+v+lP5Xz3vkcTVF3G9Dudc09eGU1OBeccXd8rdITTwUQLBg4s1z2B22TZm+ZcBdpo
+GeWR5oAKoAKBrY+XJyagywfQsw6PXWfWMkvL09aGOgK52jqGyU4tuI55IisKxfXj
+vRA3dYxyHN2rQXv052S3JRWHv1UVbHWmJSXkpGKQm36iJLWDI/p1GSHHxaBofcZr
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280MandatoryAttributeTypesCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280MandatoryAttributeTypesCACert.pem
new file mode 100644
index 0000000000..af9bb596d1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280MandatoryAttributeTypesCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 4D 87 16 00 23 A9 D1 66 F2 F8 4E C8 0A 4F 9F 45 FD 37 EB F1
+ friendlyName: RFC3280 Mandatory Attribute Types CA Cert
+subject=/C=US/O=Test Certificates 2011/DC=gov/DC=testcertificates/ST=Maryland/serialNumber=345/dnQualifier=CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID0DCCArigAwIBAgIBYDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgZMxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRMwEQYKCZIm
+iZPyLGQBGRYDZ292MSAwHgYKCZImiZPyLGQBGRYQdGVzdGNlcnRpZmljYXRlczER
+MA8GA1UECBMITWFyeWxhbmQxDDAKBgNVBAUTAzM0NTELMAkGA1UELhMCQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUNDElMAVhx/zv4YAsDhenHhRX
+LtmaEBOCTKqCQF+rRfQuf9huc18yfKyylxeh/InZ2lRIsWDl7CSEHmE+mlHNt0xw
+/oei9oPMSrR20+ZN+HqaJ5s4Ds3FNnIjmpgRlOPWokzqqCJ9Gtyu8yKL/cFhbiXS
+YaADGz/ed1FqeiWuvfDKyaxPtG3bYa0Jq5iMuadfBQ3rdwFyPLaM3q6rNkDMrFtE
+Whp34TooxaatF72fQKphvamcnf0QNhCpTQGTjxrdKtGOwI/zsuvSHmm2IsfP5uqT
+DimedyldMhnqVomyNDuxfIUzR8y2Da6/UyCEEU7MN7LEAXaRD2zhLzF+SQINAgMB
+AAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQW
+BBTwURhi785Bx7ewZ3RrArwyCjOZ6zAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBACdlWQg/dlqwHgvP2lBoyEnv/xsOOACG7wzdNrK/CZzYL7vQ3tWrdVaPIEh7
+B4nDconwjPuI61JiZv6kS3BsI50jVq0uIEYcYBPVTZIv334xnqZDyFa/Y65dUdhU
+1Q0wKBxFNNlVo2dJDhlEjHAtUlvTDGVkCTk8sz4qsrAmu4KXC2ypEi6n33EuxF5+
+D9+leUviMx88AEP7/8KwHTUtsHLqvzxCk3l2gt4oY+EuY7+hKGdvvkVev7LtX2My
+5UuWkQ6jroQjHZIplTyOUdM5ZfbjMhaUQjdmJC1A2zNzSzhtslNWWNjKEtcceYt1
+5lfxS/cBIzJv8qLSVwsd136Wa3g=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4D 87 16 00 23 A9 D1 66 F2 F8 4E C8 0A 4F 9F 45 FD 37 EB F1
+ friendlyName: RFC3280 Mandatory Attribute Types CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7C59D422931F29FB
+
+pAfgaxWooTDOmfaFUIm/eDzARkqyXWZcw7AeuE/ZC0l9FYt2qfRsIhZq7FujM4Od
+b6WS16nVPIJsQUDRZ0zV2DePlpW4JJgbOpNMmXRHEXfEVTkaZ70oDJdMSDCovp5K
+JG0ajomEcA88vtSWp2hjbK4ShSXcuHcm1nEdVmmvOZOG+43GW8ornfUcvPH6kbc/
+gWOHNTnZDndTTE0qBPI88fafOputHhpSLZUjTRQEPBk1TsnKcynHo+XR7pxCV7qa
+LvHw8gEZ50hIaAa7Gj1cEl9ito5nLSEIECKyB4b1KN4kS/kDIOi2b/XiNwJeS5U9
+WCJIEakbrodLaY2YZW8aDDEsPKxYoS9YhnPlMyY0UzHy0175GVH6WVohKpHCQLC5
+qIXQBO0+too14txu5CbSWIDT9W1TN0yrXmTYIHhh60CREdjuVFq5pq3kZg0FDgza
+VTqPMlflzmChhTfQ1bxtGfPdKQd2fydzdR36l2C1qOfj32rzBVcN8NrO7/xc1O9w
+R0ZkYXqXIY/68zcGrIFIf/mEJ1Roi2FEa3AVV3MFmwpL8SAC9kHmj7qKJAGcXl23
+4XetVCMIc9YleV/CCWJ+0RCQLnFrXcljEOEHDSGyoGChGl0Uul9Fb2pfq5lOy+bT
+8uI9R5IXI1eTuDVO7t+muMSU+YHCtsOBLx9JJJGAphvgH3N4q+CWd4O9bHLrissu
+3BRTfGo98ndrj16q8vN/qy2eJEpwKGPLsFwGVDNBxbFZQ6kTJy9UjkXLCSH5pv0g
+fPdaFlMMiPyWU9Jf5YT47MyLG1Aiv7uwxtZ/t3Hp40h27EJXrkcbWLQcW4qtvjjS
+PzmvZSO7HHh9xKhqr/D9YJupoRJLjNM8VZ62R+lkmD1lcNdDH343M6XcY8or3Oru
+Q/JFISSt7IqUJUEVT4oj0W5cAsOj3EplZ892XxRWDjd+yeDogo4jiTrbjPQgG4bF
+LQIbWRZwlLK8K801Y7GGFUtJ8o/gwoYigxm9rfMVigL+vncR2vHf7osjXPXVKX5b
+mkc5/v4rgDR6Qv4TpHdmuiBFtzoITxwl24nKwh+HgMLzd1dqYA/TCv9NCvK8nco3
+9xIz8F22960phiE7dB60QoJSq16IeJT4A89fEIDbdpJUyJloZ0R1TzxBzhEzyxRa
+KO6126UDvdA6cJUDb8AnpZiEW+DnBp9EmNGZ8Aa5XuiKqyIISJ5Sj3BrsnFgdyvx
+hh3dhZxmZpJ//z9MYq7e+e93KYg9c6RPZqqPF66wcMiatk402ItJAgmGQYWiQPt0
+EriT44dQg6e2WMKcvVtoQtoG3AJL+qjr7bhjxIU0gH3ct2PdlTLVEE/8BrFVlFK2
+wVvawOfsrYeF7dV1qBUnSDUGuu8tore1MkOrgsxSkSW/VeNstY6bZ8pbY/HuxoGe
+ZU0BlHMVw6s7jXLjsXsXSyWvb/FREyIw3tgDfb8OpFYgntVF/jVq1wuCHzqu4OdK
+Eyk7GA6F4GJDeCjfANsf2IFG51hEknaDDrjcRq6mnf3Fx96BM/icoCVdxMOOAQtl
+BEUwcAfgljViXl5EDjEKVzlGD+KNTxRymTqNvB8+Est8xfXFx6VxKA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280OptionalAttributeTypesCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280OptionalAttributeTypesCACert.pem
new file mode 100644
index 0000000000..2f513ebe28
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RFC3280OptionalAttributeTypesCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: DA 68 43 8D 10 7C 82 D5 84 12 6F 02 DE 4B 7F 0A 58 CC 97 86
+ friendlyName: RFC3280 Optional Attribute Types CA Cert
+subject=/C=US/O=Test Certificates 2011/L=Gaithersburg/GN=John/initials=Q/pseudonym=Fictitious/SN=CA/generationQualifier=III/title=M.D.
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID3DCCAsSgAwIBAgIBYTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgZ8xCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQH
+EwxHYWl0aGVyc2J1cmcxDTALBgNVBCoTBEpvaG4xCjAIBgNVBCsTAVExEzARBgNV
+BEETCkZpY3RpdGlvdXMxCzAJBgNVBAQTAkNBMQwwCgYDVQQsEwNJSUkxDTALBgNV
+BAwTBE0uRC4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/fMlDz5JD
+/7MBJmlwT5o5VSaKNzR9atn91c7krfu5XtXr/o5sYmEj9KjxxFi6lj8aK2Cg/euN
++pnkVq+hDpPfGCpH61mSiEqTUl0IoNGe4OvOVzb4TSJdH/yK1MzWp/j+dsad/xk8
+nvkjKopwAnEDBysTXO6aBQOYFvnQjmCSGBI10Ol8y82eBRIbs6YJOUWNwcM1lbPv
+Xrv0xQjFHKTmUQI+FdL+GMS0bA9KyKUrNaJV+wjkUHLl4VJ6KqfXJHDdlljnyIuv
+I+aiCPLKSRlvyno5Y6TqiNEfSt/TZ5NgULmuRVN0Co3vGQ1SamZktsVMMOwezYfh
+HiI/iqJlgxPDAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZ
+XahmMB0GA1UdDgQWBBSbbm8/iqf057WMMVvOmUuRHHx8vTAOBgNVHQ8BAf8EBAMC
+AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggEBAAj6iDDC+RKlBUsSdZe8/5Equ2UzaVj2P8vP/zYIsxWS
+rJwFkWh4tzgjH73ebe2IgZ5J+C2TvQ1jyfAOR7QulIc6Sm3izVdPLviV4OYA8goi
+1dWKfxz4Aj6FATriooSFmH04ovaFUojUwdqlUkVJnWZTyLrIZJLMrIeP6BDHBjHH
+R3EivHM+Wrz3Jv8s3+wA63dVTfDRn/zC1ngjUvbaQc1XFZKl6nuRFB9EyCz2oAV5
+EyJqI8K12JJqeAwdOSg//FhTS8tQPrYe1XHT8a4yjKj8HXX2PXl9l1N9gXJ1+T6f
+Bmlx99K0UFrm5Ty7bfhLgjKoaBiFKjiLUDLzGkHaV6M=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DA 68 43 8D 10 7C 82 D5 84 12 6F 02 DE 4B 7F 0A 58 CC 97 86
+ friendlyName: RFC3280 Optional Attribute Types CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,31CD9641338E51D2
+
+4LFuZYJt5eix2uTc9RfL2KQ52YS0Z0Vwo9I1BD+KECk2HxHNsaS4YaBmZGc0ddGZ
+bqVfCQx1Ri356spgyqhvmEBG4MvAsFO560/AXErLmABprYqokxxsRcJSTppfttW7
+ivjDcgAFItOkzDHnqigvKaKmJMcSHkzuJcxbvplMP5MoxuPaaq6sC6u525ZoJM2f
+B9hEqjpHcCb/WmPL0dHXt0N4Ev7kJb17/c255z9NlUiMuC1YQ6sd74QTofc5otsa
+su/NqmoRRGvE0bErU5ELiUOa7c+uqKSMr/Cff4BghTW8ZQRJ+2xOAejeqyUgmqdZ
+heyM6znc6kF93NJgJxxDIIUMTla7fjWWI25s7Y6F6NHO3BT1lGN3yresTY2BPKoh
+1+ahTdEqwEb/PWdYoJO6bZ9cfUCAA1UD1whQNwmGhaXMmts4FxTwVRVyjBCU+0JU
+TOabA6vfUURqzy/WFSxKSJ6CL84HAwzebkF0yZ9nXXMqGbi3GO9pAWxEap+ekEQ7
+gfYzhepUjAvIVS6eWQtv5cyNrvOtBkRgFAna9SvEktrp/t5njusiu1x2afVq6g0e
+ZfVvtEMpP9O2rpUhXyDyLmgxPss9fpaM+b44o7SeVF4RnzC95YK/QbX3KporPKp+
+e6FuVkGa3/H1+R1XoXTa/xdrnuPNxqxDpdAs3W001IIRp7ieZ3TI3MOIKVvHaQEE
+mVR2r5pFo5ZasWCZ14RiZGEbBSo201g31FZQJIyFtd7f8s/ThQolFz93gTnxIGxA
+wo4EsuVYEdjjUf8Wrbv2ARX+eMfZ3P+y425VXx3XGVwatKtiL/QJS9BQTGH3Qezg
+GU8g3t7YI4LKJ0RfYAG7s9yT0kxOQX12GFbYTnjF/X02pMYyMofEofwENJIIdWYb
+cuvMk2KFnFixjXGneu+sdfdsmwwoMu+D0Y6+eydHhdjFc1XnP3NKYjRVB6gHJZit
+BePcPvzmWDDvrehGkdY4erEjhaE4rl5w8wcMIkufb+g1b8szK6aqo+auiq4glDc6
+jlt0eXI+IiYEm5hC+BOpqPsrcnc7iP2tknNo/yATP2M7VvyKAffCyKMzEldCC+zM
+hu24bJ1Nc7420u/dbuL0s3RVTN3cR7vDiKc+kmoJjLSn+4t7OxX+bl+XYa4GZrZo
+8fn5l/dV3JIcQsV8RFgVJRHbQj06wfEgX7PdxYZwhCK9gdmqKqdZSMR3CXk/3ifn
+3guiGuwKgk3lVh4uk33r4XTl0vlTKS8vEBGOAA+poKoBJrlX35Eujm2L/E8u4BKM
+UObcSpXsMF1Tkj53dWy7SSUAUXWlaBwcfv/h1iE9xnbfdUwZy46TpTbqD5WhfHix
+1X/set9NxVjlWJhPGM1nvwsAtJt7Hhr7M5fDb+yc8nVGL6DKqMLBNErjVwMcLb4I
+nGX7IeOLX8aCxd/OMgsKeNyKipVSEOEibrCN0jOeg3xm+QbPCwqBeVJ7lLxlO6Kw
+riCD7+NFnOR/P650PIP4Q61/CqilpHZDSLY/SC48+iXeMLTE/ImAlETkvVyhk2Xb
+HWLHptJS6GgkVDoKllPcoPziHOctIuUG1oRxey+Bx33OWBJ9NU749By0b5EH8GDT
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RevokedsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RevokedsubCACert.pem
new file mode 100644
index 0000000000..32578b0876
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RevokedsubCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: E1 41 83 40 CC FB 1C 3A 07 07 8B C5 19 5D 89 0D F6 2D E0 65
+ friendlyName: Revoked subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Revoked subCA
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDfTCCAmWgAwIBAgIBDjANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMEYxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRYwFAYDVQQDEw1SZXZv
+a2VkIHN1YkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApRilogkM
+H6zEvQ1U9XzZKWJeWbmtND2B6Lz5wY6wxo8EriHm7A3tZSrctmPwDwy5WBVvhG9e
+ySTRcoa3ufPTDvYzigh8x2pSUM3Vgp1GuW436kiTkWdM7kyxXSmgMJ7O6utUj2Lz
+nb3/X3XTA0j7AY3Fd9hLa9Jb6QrQYuzR6pAQkB4aiP8OUW6w/FBwcvR2wtDk57Li
+0Sx4eF6oebCkd3Ao5EIPlWhqqWeWRfx+Rl5nSuNSIUq7ac0czQBk+UzLCc7Wo/qd
+E8jc0v5IrxBEcXPtuSAPX5KvMYTpxoChlxOfBwLwAkmJXwvDV/KhREPhlFvegZ6Z
+kneDbUE1zigd+QIDAQABo3wwejAfBgNVHSMEGDAWgBRYAYQkG7wrUpRKPaUQchRR
+9a86yTAdBgNVHQ4EFgQUlm+SmaDpdnS7X9T4+xnZzx0FoO8wDgYDVR0PAQH/BAQD
+AgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0G
+CSqGSIb3DQEBCwUAA4IBAQCHdQQiC/69bsibnkOyswShah4+Y1vm6sf70vQCnKcA
+Rdj6I3NEqVBO4/nFkDZIr8ItbU4QfbKGk52NgcQIvql9dWO9CpwTCCC2tgHFOz/U
+P5bjg2Y0iJaIBA/QX0xcwQs0cG5PXgcF9ywRbodQcKLnqdcInBA+fslFQVHuk3rp
+ZS6juDwJUs/AkB9RBjh3APvCelvjMOb1W54y/vUWP8DUJraHrZeoH6s51USu9cXm
+R5jRBIhrXD0Zgu2TDfmsYVY2gOGADox9Myx4LLjrfKkKcKTHGlNOkfwiEL0IH6To
+ASg23Vl7PA00Roz/tqC2LuVrnu1QVmnNGQgDiFqktcl8
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E1 41 83 40 CC FB 1C 3A 07 07 8B C5 19 5D 89 0D F6 2D E0 65
+ friendlyName: Revoked subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7CC2FB6699EEC94E
+
+SSAqsCQcBeuyF0pejm4wQwIeMMgi0KxnE0XMlHu/9qfv/0ezDDdrswP//EvrFMh3
+ZtkaA0E+MFnUuhRa2Rhr2+ufK7xsgYPsKVwrWEu8XFE5QfCQ6VHa5VtwSjYp0/tM
+2VtFCsXkPT4JHr1IRfOwLzXR17/OVGOjwMZfrfFzUhkMUCUpVrAbWj1WNBgp8v4D
+4ngWedE/dsRmuQl2TDx/PY9ZOq0mFSikOTzOT4rRsztFzKFsAoF9smjz9+IOwvgr
+Da8HTxjWuk7WyJJrfB+qRWSks66+/QWEL51OqIsqpXLGFW/N5tL0sdhMqRTf1VhM
+G0zVZswQRenz7h7aAIex4TuDKviXEJhMUOycpjsYz3BzNtgc242+LMz0NDoO6hrU
+jzfWtvmrACv3aRWKLAvXBBRV9JB7FMEAc1J67X8rthpXI6Qdc/qU1skDBgLL6KFP
+IzW6zYKcW9+nfIU58a9fZXKgHL86zBRhXmQAVmMyRh5Tn2il8pefimgDupr7HA9K
+lgY5e68XxVeDEjbVtH7400DPlBL0uJUTfy50x3asSJJIA462egRJfP0rsxrQn7k3
+NyuzKYJr4Ga7ltXzPivw5fM+lRNYl4uMiFVmpaVptepS5NmdUhXTtXEO2pUkKFVQ
+P1UUc+pEmfywBLYn78h4LuOKsOein1Zg+QsfHqhoNMLErHs9X7eOI8cMCpvFYHaW
+0uri2IU1q2crBf4Q0NRooH6c7yjMAYq6Cgn82s4k5vAQ+qEae9X6Sebl+Fie/hk8
+eVhG1ki2DHtNTSBD0nodjh9OYApGnERh8SYSNpkmwtaR2n1Ht+N3Oq76iqkYGZda
+6meFubYq+qLzITdpqPppd9pbDQ2Qhvn07u/wStPAnrrTfTlpYf/AvsekRUXeWymE
++7gWv5X0QyVDHBIPR47Buj5bpoTzAgTMZdTypo05jCMgzGo7YcrYlrjEwXbTRi1H
+gfDChou+xksAPe3IOnwECIPeVF5cAtAuLaE9K1YpwZFjDJRr+1+Zi0zRqBhiFmau
+U3V5AKvqaWKhJgsfbqn3mbi1BWr5WN6SLjpDJiH50x9t0bQOxbs+I7SxyJ9GnNUW
+DMhLo4zw8kLPbMe+pcfgHvatGtpA0TJ/+aLAyDLKsKqvuXD/rQ575s5iVC0+BAVy
+MS8zbPf4PJbX/m+6MtaQTlyII+LGIK4UN8Hp/CRKPJJLDLUES+PifAm+56D1Mgpw
+V2a22kE9usvhQPQW4yO7AE0eSa1jdyP2PAdjcK1AjgboStHJLrvlIOOf14dKV1uD
+LzifkvZaei602VSxXNPeHzb2XP2QY9vaNkxqSmD9lzxURj64g+mCSPlO+aJ8m52a
+COLQTfZ5CEiBGgjlTdZKy8fFKgXSr9Zujd1oen+N/+mJANbPZIePHNhFYgJ3kMEt
+JiPw407COXeFlX8idmuuNqf7KceA9XghcC9wd2Ezrri5pwAtQjxpGU5RuzQrRMN1
+2khmYv5rdVjcnZQPwpbf+G1Sq3VWCmitJzgqKfJVlFBtwGL1dMDZbvlGb7jtSh8A
+rMDq1/wvncdzBW78t5oPUceCaKV1dAdfGImb4fLsoBYvEcsXS+h6atPKkDZC1bdf
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RolloverfromPrintableStringtoUTF8StringCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RolloverfromPrintableStringtoUTF8StringCACert.pem
new file mode 100644
index 0000000000..17e4e8259c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/RolloverfromPrintableStringtoUTF8StringCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E0 D4 12 A0 DC 4B 51 3E 01 68 B3 B7 0B E0 32 00 08 50 CE D5
+ friendlyName: Rollover from PrintableString to UTF8String CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Rollover from PrintableString to UTF8String CA
+issuer=/C=US/O=Test Certificates 2011/CN=Rollover from PrintableString to UTF8String CA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBADANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJVUzEf
+MB0GA1UECgwWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE3MDUGA1UEAwwuUm9sbG92
+ZXIgZnJvbSBQcmludGFibGVTdHJpbmcgdG8gVVRGOFN0cmluZyBDQTAeFw0xMDAx
+MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGcxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+DBZUZXN0IENlcnRpZmljYXRlcyAyMDExMTcwNQYDVQQDDC5Sb2xsb3ZlciBmcm9t
+IFByaW50YWJsZVN0cmluZyB0byBVVEY4U3RyaW5nIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAuEETE+kVGfvnJPPJHUxpy7khkrkcBdQPlj2HTZ9i
+LbYRvpIAC+Qa2lAVwzAwshljKfoGD6ZuL0sHATtKDC0/+iyDTOG7UJCGesmbO90Y
+bgLR/j7fT9RNMND0BEycIOhBukZ4FkjKWU3+KFjQjMa9nUGECoNXyjYnKTAYj07X
+sR+rsMgmzRm2TzALDArS6D+toFAs8DbNbtT882ZsE1h8O9VmN5GkWzrEVBzDGiKo
+GUAt9P/ZmNVjx4gW5pB0MxacAvK+HxohxcF/y1gRZ3zp2dccZiirFK9GoCst0pDM
+qqEgDRyTTK2a7hZkLtmVRNp2VIh7x5+hk41UnOELKoRErwIDAQABo1UwUzAJBgNV
+HSMEAjAAMB0GA1UdDgQWBBS1bU8oP8e7sZikqaXQqFteSnSz5zAOBgNVHQ8BAf8E
+BAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IB
+AQA4KPELZ6+9+ZDvahZzIrH+QTAWJg50Y4xbi9Zhs739Q4F0TGrzwvXIpCcTY5iC
+IrIBWHSqiE9cEEShxnY+sdGdAgtW7oJdRnVl3JfuNW9moIueVdvk5CbVGGdMzPIu
+FfhNwLUHfpSrUKek+nWpWPIoMpQCmMVbIXVMRbjL7yFJZB4kNxo1650+Er4Kdjzq
+TnedRp+n2+Lm1M4AxLUgJ/StrD6b1WkSjI3LgiqFLxdwOeH/Im99UEUyTulhSUCI
+ZeoOali6JrtcsuMwtE0su8xLuEuHgCuHV3rh54ekfiEFmgUOuviiUSoYU8WoFk0O
+ds/hkFuM1qLbRxFJU4h1AfKz
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E0 D4 12 A0 DC 4B 51 3E 01 68 B3 B7 0B E0 32 00 08 50 CE D5
+ friendlyName: Rollover from PrintableString to UTF8String CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9DDA760B90D3F5F4
+
+odK0zz4yql9kRhptAZajKhjn8Z40phPXVyFw7Oa1H2W07aI8ebO7TFWG/woxEZC+
+AIx53YZA/Wqu4w+rSGokIXv7CMMmx0n1h3YGYE9nbS/Cvtqr02NF447J60Q8GGl1
+GRrOhSacfge3pKkdFZRZWgQwgcJgtZqLbPZI5rGkrqTc6h4AwRIhgNp9NdeSqKSn
+T7abY80UwouSMjaefqARTomvPihqKnVA3SZlKXkxB2Gz8elW5UP5MfWuZZV0yBqq
+NtegLaWeLKFKQOr99t21MUHFTD6vH5ELQr8XDHfYdDPTaMirhfySo+oUSa5ueE5M
+x454cqPbxPJznKoQrAXtfLjRdoFPSN5G6s4paVP327cvHmtIOD1YYgwEtG77H35j
+52lsSz4SOyBVWL0UfdnrlWmY3BaAg+HtfwkaacN+yFiPA/Eirgp8ImWn03GIbSwV
+3Lx6ztmIuDs+ma0n+miGAtJrC5rmAW9tJdwE38q4K/tG5UBASK7D63zm5/z28Jkj
+Wp8D6pmM4SnpTKJ4icARvIN2/BciEiuAUtlmqJel3YJhCDwcMbtdv1r2hyJSjwNx
+d8YwX0HHvQrWU0/yxUcC/aZ/yonRZq3cCujcQlZTILFFHm2uqkJGwHPi+C3TTctw
+Ct93ALYTDlq3YkIQwRY6jqluoDs4YgYlluE+cRv9a6+BnifwDeDnBikRFDhjEbqr
+SpOYNG80P0e4ifuKgngQUuR71GkezCJ633lyerqeG2RsXDRwVpbK9279uEL8IooN
+H8Ud4iQ4kXYUFDD7wRcUQy8Rz/4+DI6cixxhSmMR0/2ljEqDdtWpElnJQXoHgISP
+kY5vj3BT4WyH6xhWbImRI4BKLHriPT8s3zzE4a0UhRsy1YTvoKBp3//JQxx9drb0
+U10OFHOQsU9+dpdGOWmdUhBDdPpOA/iE0CBjwgar6Z+kVmRgiA3YkFI7ezbc4G77
+2Ep4ZD5PLEqK/Lh8MjXY8ysok5Ki6hcclq7R2XyHld2K4RxHIxidQybjH+Rn0NEB
+8RKF5ID5jTKaqe82ivCGpQ4NkbyqS5Vs9iml2yESOzQt8zKDbpoKO7WixBBWm0UJ
+FdRKek9xZj8gBTDLnDgDaXXLy2ZAmuYHo+NNbjbkSaYx21LJ37pGqL00OqMNhKVQ
+vLXaDHVrDVBqHKfnHlULNvR8tV1BH+BplyOebwawojgqSSwlIUCgkg54TC0TFBI+
+MpT71vFv9WzHQwGID5Lzxd0lC/I4osSCxERF2iZtyTdfWeSO8hbSKRea/jdt+DEc
+BPMe/DZuV/QcvrLJhcJKD4Twp6LYyLp7OxcJBaHoBajIznIN97d1VTn6PFYdSIHg
+exqDN/bULO6J/9gLrGlv3HgJzxmG9Zuk3xy81B3ua5Ke7/wkNIpmoInQxZuCH5ES
+x/BdQv4XlakRy3Jw+26sZQKAkAV26YAgj1IUTUUa8WeHfTgXMYKLzcekPimWyu5E
+JkeSjwaFBEf5978Tb3Fw9pM/OTB2dwt7XrZHbPVqdy9rZ3H38wUET42jTFX8QYpR
+/ni1glyQZ2EVGAfyLMNp9w8YB2AKPiZ5y36ePJS6cawoSFZ+yIE1ZQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CRLSigningCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CRLSigningCert.pem
new file mode 100644
index 0000000000..885034098f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CRLSigningCert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 15 14 A0 80 15 E2 88 6F 58 26 40 63 59 58 94 CD D7 81 E0 46
+ friendlyName: Separate Certificate and CRL Keys CA2 CRL Signing Cert
+subject=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBaDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JVNlcGFyYXRlIENlcnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTIwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWmH0sVxVN7JSbzHWG1otmjl6HCXaQjmM+
+q3A7UZr2F/Cem94aL4tzAERsgT0VqpooRlGItI59uT3Ae9aYUHIRLCzs6tL28ZoA
+zqmYVtv9z+sDPfv9wddp/BcFzBh0ChfykqyH36+m+NjRePniF6AUJ7lJqgVKkHu9
+tRaW8BZTwk/BGbhr5d7GkpEiHsflSKlrPWf6GZa/FV/yA0P003s7sUwVOSLQR7l9
+GlE9/BQ1kH2ZmqB1U8Y3au1lvUY7AWSOSLO7RwDTPXjhgzY6DNLtMVFYThcbryrI
+StRZdpFjYoq4COILuJniUdmubgOPhrwD+aYSHsthHaiiFEf9PBsbAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQThD2E
+jx6qfIF3XzHdzWDzl5fZsTAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDgYDVR0P
+AQH/BAQDAgECMA0GCSqGSIb3DQEBCwUAA4IBAQCEm2lpy7GZwfeWqqR1AxiCsBBS
+iQQ7kQwgsqMx1RvP0YpT/Nb5t/Yk5TP0ofSyM42MNwhw/sMiZ9KEShiFy6ZPCG8M
+o2ZHdPLVV+SNcW/MI71ndc0crqhG772BNTkMN15DH0v7aGLcAKzPrE+t6Lb59cnG
+ec3M1+VQ1xNZZqSQuAX1d0OdlfIYkCcZooVcb6vqx/Ddmv/iV1fw6jgjxpY/dwze
+guYIEwugf/FRkIdymxfAiZ9B3AceD84BbOVoasJN1Vu0zj5AUd4murA+Evy9b/Is
+0uFesDDiT/HcOsySEOGlrfJo4TCQAmV/olVxK113cGVIgVP2RMaD1gXt1qnI
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 15 14 A0 80 15 E2 88 6F 58 26 40 63 59 58 94 CD D7 81 E0 46
+ friendlyName: Separate Certificate and CRL Keys CA2 CRL Signing Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E1AD060693CB28B5
+
+XAFfOAUgjK17Ij6zmBZsVKwxp2vXtrlvHYiLHvfpEdWVXAYXrVuhfL/kdCkkhZ4J
+P3F6dkFzavQ0dZ3Qf8370FwxP7WJpJnj+6EgYs3Jg3omO8UL7hhm2kZLPo86/5UH
+atjmbe4imgCln0qPpeZNokbfa7EUEHC4UtGGPeJpeiODVtOkTKlrUDjkZ59Ywez0
+H/s1SclteJ62XFaQMKMLOImbi/PIyGCj/jm5xMJxZdj6eY6HjIpzA84yVofgDxMi
+sSc0sXKbPGqFNnUV9WnDDbI1rapWTuU3IMsGo3zjoIs2HhPW77YEUX4N57ntHn3I
+M39rXG6zFv3XJjCAM7qADfI6I2Pt5sbrVQBm3hszpZCdtxcxs1hC2xggX78vV6dd
+KIUa0zThsx/9hhaydNyysUx8z/Yy2Z2An5uEyIwWtgwO/lMfON2eQOeoP5ZX2zXe
+MjPyMgzog52yQcpJ1uvtuT2+FBrBs3kAczAU9uctauVMWOF0BLl3BTbg5b9pQlsk
++wZoMyn+RhHjWa8mdaOJB5SyOm4XSQsZNpgmcMjWYPSLgHErqcCQZgriaBV7kZVg
+ZFF65APt2a8bpa3bwFHl+EAgncn9MKi71AkJXJpwf/LWcp9WcH3mH32CuwYNaGYb
+vd/Z81XRSBLXU+XMMdAhywW4vTGzFG2RYiImb+GJIN6CSsodJhNyi44rgPt8ofKX
+a+SPps2Xj97DzVvJy8AzDX1C3HZESo3nQV5DBYtVaxAfkbBoSiyuXCx1kXOoaIHt
+FbXz7/O2p2Rw6I152/IqMw/3J4gzvqr3WSfUgpUepb44sT0yT11CQeZIu/ahsvy+
+V9ZW93P7AxYH4Xup8I5/YlxuNxFBRP3XRgI3nJzw0uUdNtY5QqQYJUJ/lL/INv3M
+8GzZh2U1PuZ70bb+nLa2L/XdNMcDGNonYE9H3Pd7/5rtk97sDS0Homnv1toYcqbD
+2oburjwDMTOWV1xDQcbLHnnMXLxYEwPzRYdH4ykSDxYo8QIrAjuX2O3gsQwzdDYF
+coNuNfAFXssWX420htjmNAZPm8vnHoEzWoye3v0mQTQ940pkn6Kr+FrBr18UZBgW
+DRE8WHqkA64xOUXaJJf6CbBQ18ZWyA9TCXbUD3YO7Lnr/K/LSXx4vfunQJRQa63q
+ZTGxQ1YPSMvgpnm4EIb+MIOZD0YLIXz4vUPP62gWhtk0g7yiw3ba9JO/54Vl2vJY
+XqUYTbxQOc3tqBXuFfq9M0675eNmFjplnqzzkLkLgGE43tK+ex6+uxjNmIuZHp3h
+Jxu/DSMJeeOe93eUEx52gBbMntGF+my6u6YDejyiI1rSiFf6+pbBvkC75VQ09vuj
+Jir6RTcWnr/TxJ+3bARFi92zw2pW37NyaQr9D730C1ipqPtxzMNHROGRi8czWpvI
+DbPLOes+e2tSttLSyBSqgX1EQwwwRV37zYH6GFdOCzCtJ2VQAo8/1xfE1SBKLnbb
+yz6Y1NcJBCm4Wgrxex8I2Mm5nBFhmZtpqCGBKYewvyDKAx92X+TIaIYyX2Yy79RL
+xrNKZCxGbPjuXTT8ntsYTldpYMHq/rpH2wfljtNuwzgXA2jH9d3EfskBRyNGus02
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.pem
new file mode 100644
index 0000000000..eadb947174
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: A7 B6 16 A4 3B 15 81 93 4F B7 BA 41 DD 6F BD 0C 92 5D 23 4B
+ friendlyName: Separate Certificate and CRL Keys CA2 Certificate Signing CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBZzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JVNlcGFyYXRlIENlcnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTIwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFYsYa9Wvs1smcULUHZqU/AJq1CmwzH168
+AzGaZnuLzIyYqct5aSydjaYh6pw8Qdo9YGpsGZdrdVIrorR2QXImqG2IdmMP+nyg
+/hEZKk1r2TqExjwextNIOJR40DCrpvtSjGj/zaP8QDGZKdi3cfY9BHIYUJVFHxiq
+dWkNEc0myPYSu+y+uV864I7WT+7w9aIlfwy70DF6o63YS+WYYXMwGKdUspcLg0GY
+7F+rqw8c72xOhAQZfSTUfOn9L8cB76kgvarYGT4zltGh38NrRoftXyMOGk0oRVsy
+1Qgae3u2PXm2H/BP4/JwN72xvv81clmAfhU3O6QD85CHGFrRCRlpAgMBAAGjfDB6
+MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQ4oxaB
+OI4YTkV/B/YRouJAZ5t04DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBAEBL
+58jRnzAPzJLFoI8KtE5sGyo7fTkftuUZlSUeQURg4VKGLGpKClldAzIXUJReOsMq
++79P8b4HnOTztmIw0ax/wM/mCcjQBDPcgNL6xi274neuVQl2d1ekmTE3j0IVsXyd
++ck4EdViI4YLs/m4lllj+o1nhoZBWoPheVJm6meQfIb6bhGJwVZOMGZfzVF5UfIX
+mvW5xJ/ItI9CI+gcxt+Xn+rBD0AQvUimSkxF7ToxcpjaziwL3gMAKK6UrtP+RzcI
+v9egONl1LBx7JcBfbbQEoxyzRad6t6ui9MajKFhHT8wQ5XnLahoXFcAJbII5TPkm
+C1H/b4W7FXQUbnxMCxE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A7 B6 16 A4 3B 15 81 93 4F B7 BA 41 DD 6F BD 0C 92 5D 23 4B
+ friendlyName: Separate Certificate and CRL Keys CA2 Certificate Signing CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,849855E743148C79
+
+JSyzpxxzuTpP4rMHFriEzmS5Nj56E50L7dq3NkZ6mhlKdYSGHhNGU45rYVMY2D77
+1QagCtHIkuDPo0FlwHAuueq2W6lOMuaoUkVRtRXX15lAzkKjgSew/YPFZTljUeET
+5lIvxCLg/bOMXfmCjpN8deScogHIHb9HK7FHqVmoqzuXfoDmFQkrohBo7RaRnu3p
+Mgj67Zw/DqBhSLSN4Ug/AkqpelLYCuGU+hdTai4fMQNXtvDqzi2cp5glUbgNRoXM
+CCvkWGzcCls8bx/UVIlslPqUa9lzFoK8ija5tljhIKl9TSVJi6O+pLmgxI8GNpF8
+Rb7+aMOcxR/2k4O8/eYtRgmJv+TNYCeHxuuyWI5FauxGLfsRJoD4Q4Vat6xIvs/T
+C7itOaWKTnH54h7eUktkNzJwAvbrfNlhUgtlfeH9AHMm54/B8bE0Drv+rv3MJqt5
+GDYIjZcb6my7gZlrJ6RnXC85s2e9sa8tvN7JCDgSGFCK4vd62aPue6TMk29+k1QT
+Mzbfy1XDDQJgk9q9qc97XeKbNeZVYuMW/8PwDR8L/V0TLSWxlPmZt0p5S+Lb7KFt
+sNYBq4UuLRDrMpX4hZ1R3lY6rhlgxEOs44P0Zl+rzYjjoJr5II6QonrRv5BMVjqB
+2sR9cKvfOvFm9AVMvFylzCvEizLvtifDuEcRvYMjd7VBQleUWgOpnxCzydabhWVF
+nZ+BPVlmZZ3UpIENtP+7AGEt/uEZXU3aDiC/ryHY5X/eOHOU4GczVGBK793v4LmH
+qb25dLLhW6SLs5KobUlnRos6Pe2LrOCWo5/e+NSeI2WLQ3FqgGKlHAOENrw9sFSM
+ACcZ0ZuDNoXGj99c/f7uOE9Xryi0ITL1sRvm7qRruQ/goHDLYzJqJWW+uxugYMGR
+RmhLrkjRU8OSFOl1YprxY8JwzpHao/B2263PxUf0gQSbeIEuiH6kxWxABOX9ZkyE
+aBVKXwjtyAe3CJhfCNRZeTZTbeCaWmkY3vHPAcBCsdo1NU7YqgECWn21lXDNTslM
+kIPPvE1MF9GAXWV0EBC+1ihdk15Ml/QYP3R+a7KleRMvbBBdZhuh33z13qBt1WeI
+mThCtLNoTcx4nSdASeuwCa2Mz0hHcBTAaPMkEmZ5G083ehNVPYaxw37A2Ix49d+a
+y1B2qToCvj6N5t/BkQci+Jzfrtj6jOpianS24BLdO+VNIXtq3gX8QmftPNRyT9jI
+UMXAAuInIWlYP1HskPvHmghgemqEh5TuE2cClVM2YfNQKnysrLdaN9Yf30o/Keud
+bY2Eca8OLFQCMM05oC/TshkBaGy6CRvUuZJ4xVf39NeFPtJZimctHH0ChgXNCa/r
+MUMV6QSEYigI8qm7hgpsAyAWm+eeITqIhpdYYY5Wz9x1RfX1InqbHF+3UFKr0d8N
+pSde5byTb7AYRv1HC0IbKWcg1N0te5C+WKI5crvdTKgr4P7FsBbzkdQbUDoAtjOc
+3vq4BU78rqePm5Q36DKG2Ht/s2H6X3GR9PJuviKCRUf5nJyk6RWfzzD1nBWiNd3/
+z5ONNiFWnGLXh4AanZGUrm3J/FY3vxo6qMjxljpk2xZerCfgzrkhNvrTolAk/WH2
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCRLSigningCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCRLSigningCert.pem
new file mode 100644
index 0000000000..d82e527597
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCRLSigningCert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 7D 9A F8 FA A4 D2 DC D2 E8 CD C4 15 46 C3 04 51 78 C6 80 14
+ friendlyName: Separate Certificate and CRL Keys CRL Signing Cert
+subject=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBZjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JVNlcGFyYXRlIENlcnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt3Ehzo3kwZuJWuTbmmbCrbv+6wWb0P+BH
+VCe7s6xJ3E9OxRqvxlshp4j5LDydNpnIIuBlUXcVdNMi9dIrm5ibgYly3H8/AWlk
+oVT3cDJQlv74oJ1F2vM++dx7xpfE7efybfEVbX6/5l7ouqZkGvtHUA1dylN2iwWb
+EgmGkF0XIC1pYChFv8If3Kd9I3eMqoDXJv6eDB5sSWjjXAZAdcuxwWm3ImjaQHDU
+q33ICEEbdCY6Qst4ocbkhi9TcGyYP0UqO500onu3yFXPdPx0YXftEw8biRTAYjnY
+Sk3DR5i2VZc7kOcvO4xuvon2xirQVv4OBY8l1w+m5BFlxavLti9hAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRyikML
+BFs9PcRV4YPGn9+Qyur3XjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDgYDVR0P
+AQH/BAQDAgECMA0GCSqGSIb3DQEBCwUAA4IBAQAh9MHideOQLdw0RnoaSAbA9i5d
+u2K3FdUw7X8o1Wk9VsJmTPHQ/lA3mmohF7sWChwC+YpSwxj/TYYUaT1MQC+t/sYn
+fiA9s4jlz4Xl36Si5ks7m3G2d35ApS/iaeWHWF8NHo6x04jEWaMNNtAwl4cSDzu7
+xljzpSiBpwr1KdEbW5STqnLogu1aSlN74NWVMo+fL5HJds007nO26v9wy2uzJVts
+6tx7C2LYkgu2ZaeenXmKxrSdj3dbpU11/lb5DsEt5xZj6h0qve3f03/Z+jTFcFZb
+hKp8MDt92jt476/yKQZUObKpWtvhekGbhaxeaArUqUXJEXyz63JqWf8+4zds
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7D 9A F8 FA A4 D2 DC D2 E8 CD C4 15 46 C3 04 51 78 C6 80 14
+ friendlyName: Separate Certificate and CRL Keys CRL Signing Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2C08B269BEE274A6
+
+2nCMqz4Z9jAqZu3aJkQLe1ialqresIxKIiqamZwqTUAuRv6SLso0jkCcvDmRvtBb
+bc91dzoHIBdXRFDM/L0aMhTERo9qVIFXRB1hu2JqtNF/6IuATHxltsV11oJmW8F8
+UD6n9SCueAB3L1qVdopurS5/J/+wSwN7JVmJ4mF/yKpFXcmMIiAZ1uheyCflcqel
+3trlDc+/xKftrMIAGpIqLrJVAFRp+LLQQceoGVUSlBRLVtq8CebMz14LWtzof010
+PDJCVAl+hKwqF8KUaLwLqd14ev3NYSZFV0EAardOVmtErq/KpOclCSHOrxji1xXl
+lxdXL518Esj/2VJS36rZd4ex9GISmMcqY6Gj9ERy5dKDvMP0Wmb1tMBj0Zx+cFh+
+ErBAxfZLmD/xcMOZG3Id2Wk+62Z0RHd6cOQuF/hXdsDiMJ1wOqvovnjgu4JjSVur
+XVNzae91ppfMnIQDCjhvw0I4dSs+kV+x2h96oolMgADPg/tEGxqSvyNAtZFD/Bn9
+ISF3SVYEequMPeq/u4wRlm7gOPdzOzRm1Xc05T3bE/+Dpf2djRv6kc2BuDYALUbH
+u/6L9PETZxg7QIV9CrlOn7gA+8CPJ8kzLlOB93Tjr5vORUtCa0f5isVWjHarkSs/
+rySC98EIMwbBE5Gt2cBYkZE/6heTnkbJC6cY+D0136G5L+Z9S3R8MQSIm7fsb26F
+EeOfQj3ov2BZXrJdz/0TLKD9+u5ztSm6pI3Gz9ljztLZsq43JOjhlEdRU2KC7D91
+pFRelbFPyInpknG6OVpOiYLC4s3DthYXa3Iu+eNPCPAoAMRJyWV6L6DfY76PE+JX
+ZoYkHZxSGJ9ldsxY3HGOwPHSmO1H747wjvGvV5w1vyoVqDfsBrvOIYomydD5e8pI
+BLelkb7Cm5pFuO97RzBLfzfRt8m5HmVYx28vzZtQPYG2ES5YutvZIIahw77dhuX1
+Z36hs1EP16jPR83pMVIwRJMPq12lmb+jaHDgpDo8VksYXMItfmNyjSpTYjZrfQEx
+Kmccy4KFi28OJCIM6352kIIRNqbHDBB4b4KDQBQImszT7DkNYuKM+3wNab6xk/eF
+UaoT+4IdxIoB8ClRQdW6hvLkdKfHcITLSIAIhdf/XTKVGPoxUuEcSw0BCNAUHvSj
+nL+PGYUpUH4PmGn9SlQ0f5WrA+rw4qge1xOxaoUdDWpaaiq0Ouwy1QhBvIW/nXs/
+LiET+dRU6CG0LpH8Ia+lUAANfZQ3bX7zvNDpeiAoqxfaGjQw8lNJYgX8DUyPwKuU
+HSKKbi0JeaP31mRzESdvr6Lrcri763kFn/YZelID/NpfxPiDlQJEulw1MtvZBFSK
+tQlUb+5PCG80vC5m7usTfI3JCQDr9ayNEIMhntTWYUImK89VSNs9oNtEcRCY6kS/
+bK0Q+J3tNVqgAxiQEVnwpy1U+zuikNpRRhcx7jmqZ9sfMfPkfLAjgn7q1pL+SxyV
+KcQhi0/r/agn6Ub9AN22ybSBO5b4FMtnn7Emt5HwD58kP/vnXi+BSdqX40Sscycr
+51MWa7zYEv3u9I/+A+TiLxBpPji5i3MUwVydNEbb5LiljNar0ZS051+UGzHof+bU
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCertificateSigningCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCertificateSigningCACert.pem
new file mode 100644
index 0000000000..96b2e52495
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/SeparateCertificateandCRLKeysCertificateSigningCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 80 CA E3 C2 D0 55 9C 8D 74 57 6C 6E 6D 01 26 77 78 EF 0B B4
+ friendlyName: Separate Certificate and CRL Keys Certificate Signing CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBZTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JVNlcGFyYXRlIENlcnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQDDtL08wy2lDqK70D2Rat++J9XUvMChIl
+EzlBcCgkephduAGsuC1OlEoXSwhy1ajQMJWoZgrWr+w4VecOHs1KS/3kt38LOCA9
+Bh7y/eRCfmn7uBcerIL7kgjP3C9qYVKzEVCNIV5SAt55VxraPdv3x+HcvvJWvYuy
+dwjcc16Ik/EET8h24TVmM+TLM9GQFsw6MxJVaPKRr7EPQwCrdZQ2dFQD82Mt5fMJ
+bi1Bt+0wYPtvP9n0h60mEbuYc8FmFPWdpRam9CNaEoh2JGtWoTKviVPzPiDNUCJ8
+y4I00mkos+oUerQSRD2ACwcKy4BZyzqmPis8zV+QQsv1DAXjQNjtAgMBAAGjfDB6
+MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBTwZdo/
+Ghda3tW2SJk7FxQQ10wUpDAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBAEZK
+kUJKVqTUsc/16mk7xqEm9lSFPZ82+KI4Wc6R6Cii4kOv4V4dANxAzwKOGcuKIVkl
+Y+bTze7DmO8BCBQ6YW0mgswkiKn20hl8DrNbjQ8iijTGYFvoOp5CUBP+LPRKN1gn
+/4E5ZxArB2KhCSlAm5GY1eIs9gdfq1al4PDEBRLEK/m6+J0rbsIiJlwkqRgLy+8M
+rPUJYXSGBSsHYg6tuokTqgJ+YUFWahKufCgOduYjfKj+fx6hnMzB63IrGdeVE8xz
+IinTWR5N3cFMngryTH17o7Q0tfTI+Nwlbbk+fXP23HbUYHXK4HKDHMZUHw0qxMeP
+UZXUvPJPMlQvcQqSnQU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 80 CA E3 C2 D0 55 9C 8D 74 57 6C 6E 6D 01 26 77 78 EF 0B B4
+ friendlyName: Separate Certificate and CRL Keys Certificate Signing CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C90A57E276098AC5
+
+OA/Py+SF4VJCx0ke2ZNdVdlQ+M45GGHp6v+XeLSFwQsr7d3UdrePCBuoGUkvYhBn
+CbZAF9WPugpIEzQN7G5ynpSZBbCcLc/SOgEm/A/vbsdbM6O9apaGk6IfYQWrIXig
+gIlezg5KIspbQkI4dcnc8D7KGdgftpTfd9FEU2xIZ5SPr7asUQ+nOT/E3EaLkYCH
+dYZ7ZRSVmhJfafkiYe/wdIp6tHWF2LL/z93iGfp/nm1fRdfa8bBA5N0RVKhBd97C
+GdTbYZj8rGt8ZWQK40xn3emhzLmmEG3NoN8sc1/l7zfX6Wa+4vPvQ/mUW7lWkgj3
+r4MX2pq+TbDSyVfzq5i8JdEVl+79aOMe7kU5r/FGCAf0KGrhUZl8LI3sD7I498tS
++QNmjyqnFucx/8Vgq6RAqPOB1VHFOTBc4e8xJnVIiZTkjhc7Z7g/4MFH77o2Gffj
+wHTHV3vsoTQr0BuwQ5hkbabWLD873rGvXn59meSnc1bHNrRswwBUsamFMpmsdtjC
+Z8wHjdMW7mFrQQqipsyt9xmzYRjo317Wi7LFwCVxGz7pv3F37LxpoHRW6A+pKdSK
+v4paTcBvqQIH0qhOa60reGBuQiqMz4NVoCxZIARd3NfVzOGis5XU7ps8bi3rPe3R
+W2PG/K7MMeyvOeyXxGyM+nDX4E0rlNTDLS03GINdmNLnRbT7geV12KDs8FS6Gy0e
+KSevEnGrO0d6xITwPhYWOhLOtPTxvdJkHx/2pxbh2RU9jTzByKkoNFTS2PGJ7GsY
+jx+zy4y1knrSfBvtPDW11xem5Urb4Jgebp3gHchijLixvjDbZNRZ4wC76LuU5jwD
+6TZbDkdmKYyXOT0vnIesh7qVUAPebP6NNRDwCBU4+dnct681sDU6CiWcBamsjnzL
+rXPSFnx6NDlkd7vW1t6eGGTDMJsqMfdI2EKD4Qm1xzvdIO3zHdJLJTy77uhS3mrm
+ZRn+Qdd4FEZm6OZDDDDwylrWHKifv4ioyiRMGol054/0AC/UZqPoDdTC/V99I0pi
+XjEnfBs/f5mmX2Vz0sgYpDVot10dmM080wzAO05u8WqhMSFCU9HXPuuvihtNtAEQ
+iIP6CncqNvOpI4PCFC3sr9r5iyRpdSNRXevCjYRPtT/jd6yo+wo1Edr2CgnK8nd9
+4A4T3x8LmZPJOIRDIBYWwkdXf9IUPNPWnXlEbhMlam6cexW01/CIXzf7joTEgcnp
+9P5diGkRECfLirQZs0jrAawDRzFNrfTMyCsYNLfAV5CJJAZI+XIyKkYU5Fm0nbK5
+Ij9t0dOTw4n0ChXWpLf6smJbk0yAKu4MJok9dpy/hSnQUMS7xJMU/EYB7oEW+S8J
+1ZbyHi7zn9Udnmozx2G5O8o9Tb0Cp6wbLXSFRZmOPTMBqJ0+1HwYYGpvaqQ4XO3y
+ItnAciO9PzeOrrwF/KttJPMCjYCxDl1LuDIAhGK0C2KrrgBFzdVi3Q7dJKiXyDS5
+xM3gNAxCN69HYYh71mMNYmUViaECAeByjmeyyMSqBqsbS2krdBX2q1sOLV/VP0tW
+dKyIEt/GDLOOP5n4rvmX3ELdxBbIfmCNoKsLAbYpWZJCcTwHUlgv6w==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TrustAnchorRootCertificate.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TrustAnchorRootCertificate.pem
new file mode 100644
index 0000000000..5dae6269c6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TrustAnchorRootCertificate.pem
@@ -0,0 +1,59 @@
+Bag Attributes
+ localKeyID: 9D 70 F8 16 6A 1A CC 2B 9F 0F 39 E9 89 C4 18 34 F2 C4 5C 06
+ friendlyName: Trust Anchor Root Certificate
+subject=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMT
+DFRydXN0IEFuY2hvcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALmZ
+UYkRR+DNRbmEJ4ITAhbNRDmqrNsJw97iLE7bpFeflDUoNcJrZPZbC208bG+g5M0A
+TzV0vOqg88Ds1/FjFDK1oPItqsiDImJIq0xb/et5w72WNPxHVrcsr7Ap6DHfdwLp
+NMncqtzX92hU/iGVHLE/w/OCWwAIIbTHaxdrGMUG7DkJJ6iI7mzqpcyPvyAAo9O3
+SHjJr+uw5vSrHRretnV2un0bohvGslN64MY/UIiRnPFwd2gD76byDzoM1ioyLRCl
+lfBJ5sRDz9xrUHNigTAUdlblb6yrnNtNJmkrROYvkh6sLETUh9EYh0Ar+94fZVXf
+GVi57Sw7x1jyANTlA40CAwEAAaNCMEAwHQYDVR0OBBYEFOR9X9FclYYILAWuvnW2
+ZafZXahmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQCYoa9uR55KJTkpwyPihIgXHq7/Z8dx3qZlCJQwE5qQBZXIsf5e
+C8Va/QjnTHOC4Gt4MwpnqqmoDqyqSW8pBVQgAUFAXqO91nLCQb4+/yfjiiNjzprp
+xQlcqIZYjJSVtckH1IDWFLFeuGW+OgPPEFgN4hjU5YFIsE2r1i4+ixkeuorxxsK1
+D/jYbVwQMXLqn1pjJttOPJwuA8+ho1f2c8FrKlqjHgOwxuHhsiGN6MKgs1baalpR
+/lnNFCIpq+/+3cnhufDjvxMy5lg+cwgMCiGzCxn4n4dBMw41C+4KhNF7ZtKuKSZ1
+eczztXD9NUkGUGw3LzpLDJazz3JhlZ/9pXzF
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9D 70 F8 16 6A 1A CC 2B 9F 0F 39 E9 89 C4 18 34 F2 C4 5C 06
+ friendlyName: Trust Anchor Root Certificate
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,589B438A6C375D73
+
+1Sqkes587j3AgZI7YAdtWcfZKBt6weCesfcJpZLA9jWYXune85Qs6QGZrjDHIQT2
+bDokTc2Icf8E40ayuBEvZ8IVhbxCBGmLv4aKOko0KZCr2/irqrRGc84nYrFQIlZm
+FI7GI+u5mStnM+KR1XaQasFt6wlYDf4sWwqxu5f8oF5D74TsdhuQ6DIjqhaxKdVc
+ju2wVsrrrZ8Aq5z2uy8lmMdsy7E+e1LRuqT1ZyB87Q9eC7LvKaAftFQDzbIu4Os+
+Xx+YxBVF6Rf8/Zzmj30s0GauRWwo8O8W9Iv3Idb0iRiIHlzrWYYLdUmx8TtYe8nE
+jwxovfs8V0BmmzyMSJIFnoYTuq9Mx+8eUUc2bdZvNyYCoNZtyzvdBDriqrMiI1J8
+anV7gXDno7YgpLPRnGB2XG7IU43bqWJPZO2etT0RQPemRA40wJRKcpwSJKn5EpO1
+mmaVnT+CLycq7Fdze/3WZTAPJ2F+i9aLqSCtst2Li6io5fMmhe5zKX8AB0sXNLAG
+28k+s6p6CmOszOs4ADznJQ+ckw7F3eU5671hH8NchQqp9/7OFF7ZTSO0vmgNHrV6
+ZoQGphvD6u29Qam8OfXVxrDU/fr+lJypygcz61WCPkFoOlWBnKOzIper6MJnBwtZ
+Q5Xnq5XaTybjw+9m42H8kKqx9RjbOriJ8O+NEgriGEn+2vKfkCRTMbwRVZAzszEp
+8/dOkueyR4Uvm87383Uxi0k38tQIfI+kHG565Wg65OW+d0i9paB11wUZZZrle+PJ
+/Dm7dskDNEtKh60GxUJV1oUr1dAqSqsicA0q2K1yQApIjH4jyMWr6jFo2lKHSd+4
+V/weG0j8jK+W02ohJ10Ei7cgtn85L+SAHcyiZhRH9eaHlzacZvKrbvEG+BaSTdh9
+Y1derGlf75ITaKmO98LtDVkBVPllxNcQXeYVLSJagcH8OGKDS8TZITAHW9m9BuKO
+T4UOgHAqEDSSWJTVzBLBPRSjLnwup1E48P17bUlg+mUx3B87zKdGrfXmywm0wPpx
+bsTQg8VfRy1B4uwsn4mmPfW1kuP8r1pKlkqDq7u/gQ9jf0R9RF5+ThKOAE7MZHfC
+r+LurSXn0XHZW/1b82vwA50e++xVH9saNv8lrcSmnnU15oWtqTEdQ7huEqbJFIoE
+7EtXQrat2UJixsEgH/xNtMow+k2E6a5cyZlq3Zp1EqoXH4Yz3Om6hSocSigSn9ua
++L+QsnE6RJx7e4ZMT2o4hQ4j/vVrUmWsQi8PV1LjZ7W1PIR7Hk7eTul7XgWidO+U
+3bPd3EG9byKcq86Lr6kUAlLuhIB010d+8RuynZ76RNnEwbSFEIR8fRLQKbhvXx26
+9vrCvjNoYnxr8I/LZcCdg6kVxq8JsHFwyFqzV2D/khu5DjiBAASjPtMt9bK2GY/0
+yrTmTeYr00Q1DNOhZB0xjCG1ncLsrlUbqNlED56lnwx1//UAQxlF221MUOOTGY+o
+n4UXC9mU4nniX7AGTUnRYy92uCOUjhJdmxYsREH8popLPU/GaaEI6SLcRLLYrmTt
+bUUV4KK7y3a85WIkqcdWzKTSxoCYxKKEfKZTIB+m6D+E/okaWWDLBw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TwoCRLsCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TwoCRLsCACert.pem
new file mode 100644
index 0000000000..ead53efabd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/TwoCRLsCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 3E 8B 13 E3 DA A9 B1 FF F5 8E F8 E9 A1 D7 0D 9F 6C 7F CE 49
+ friendlyName: Two CRLs CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Two CRLs CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgDCCAmigAwIBAgIBCzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFDASBgNVBAMT
+C1R3byBDUkxzIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvVVw
+3mINvG9IC82MaVpCjNLN6vTS0MX35ka4XR9DiLjJnct3BjTPol5cSRkUGt4aD7/i
+yY4xH3KZaA1QIqHPrmha3xJq3KDwMOKgX85QpwEJQ79gRoxvh0PLInwOOOLEbgQK
+2m7cfRj8X38DEcLoetizt8bpefYqXg0cK5QQ930x1zdGobj2ZQY1dyfOgEOGbR6v
+b2H2tf4ADjjr5zCuGWgR4WIjeYg1nSKfGyFt1Te8kXYze3ps6JBsZwWbzZL0VzNc
+SyOs/0aSdqas2jeB15GbFx0mBYO7W7/Ruv5tKfQ1Bhndnhy1qOdqCHbjQm7JCW1U
++OQihBTPJua+WcoBEQIDAQABo3wwejAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51
+tmWn2V2oZjAdBgNVHQ4EFgQUEKEB1pmdgONt/efud0tf8UnZPFMwDgYDVR0PAQH/
+BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/
+MA0GCSqGSIb3DQEBCwUAA4IBAQCCV6uwBSTvSBXTOo/xsmUKJB7luilrOqM9S53y
+ZbAZDMR3CkQTgiofSi1AFmma6OKPSZb621YSc5eNkVIaV59TtMTW6birxp5fimet
+J0Gpccz4huD3mCHl19CyfiTRyHYrnv4KTLJNLISwATQ0kGV+H3UnOWwP/R6edMQx
+AdSlpO5Y7WeDLaO9RdcMSII22qn9Iy8dT2V2eOA3yHjnLozB56H9BV9TFFJaV66c
+rxhupQudk87bl5MvOWx5FSKevJKgIV359N2oVm9G04IRI6uxk7HTFOjXq9sSoNoh
+bWH7xSENkdiWaAwBXlZiL0O4M6AEfhCVrlt/vnklD4vLn0Fm
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3E 8B 13 E3 DA A9 B1 FF F5 8E F8 E9 A1 D7 0D 9F 6C 7F CE 49
+ friendlyName: Two CRLs CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2D4935EC571A0129
+
+R1jy0YiS4UdfbW7dq07IosLgsvObjCKFkQP6taBMFazcJRFQEbpW9mYfGiu3WBWe
++CRslantZU4BLBCeRf2XDmMTmSlQcYQDEFKxrpQvChhpaSF1o2F+9nocQ2B9YEQP
+EXfsCaLKgIg9U3NVujHoG2YlRwJi5SWoe/CUwts1czHAHTxpO6l9ArGm6uKD+SBk
+osetLW0RIuhNust8i7sArQULRS0BmW/HkKMxWhreQGQjqkOF8EyW4sWbI6j4WJan
+OBQ0dK2cxDDDoydEj+JQ3EOC9Twe4D8FXEg2zHWonlRfRX0qf7L1EUZEvVFBu8ak
+ltJsAmkEMl1mrJ0HGlmTm6mQ8DObc+kdOepbFXAGP4/7h3sD+cDEu0+vVky5Cw6u
+0Qi1icscf3BVKFPpv6m1SHNsoygVAGdMSTQV0L6i97LmZOnY+XaQ2n34ePfz99nP
+F3sM5lydLRZl5nSB0kZW/VAdC9dUBL0j3qvY0SEjBa0BQH2qExtx2q/Yyd+T6GZ2
+xRS0dWAq3UXbJNG6UJvWYId3hicZMDEpWpgsPYVQ30LaTYjK+e3z+zaR/etZ/de+
+aY0rH71OGXxF76vAZNOHpMGQ+nvVqhDqjTXaaFlHQ9MFUdZmY7f6+K4BZklv8p+4
+xtZzLanvEDudGxMdNCnAWCTM4T8A56Sbfgss/5S/9/XjnHl8wGSw03WUkMzOrplA
+q4fRgu3nTOFrDILfXUuil5iqfVnKj/77j78P3wEda5Y/IX67aCBqlexXrRuHuz8D
+HZR5LyXbxaB6eJHmsL89/VM5q2PtajK8yqIpjT8npX1/PeWNKWAuuXRCR3yNHQzA
+U5zNE+gOZwb05cj3wfV0ni/R72Oy9SXZSAWjKWxF75X3AWBMekJ+ht1AhFK8ydDZ
+DY99wEMNvUHQbOIMdY+0gOULL+azKlV9Z0fhyvrCB3k5Ek4JuBL2F/f4T6dPaenB
+kp7Nc2xL8e5GS9lWEo15EJalkOn5hn9n/0Pk3OKYVWVZ8n/hWZkcp7NhcYMJr7wm
+LwbcZn0yC8dgH624xi4CKF3ouryHFp3ZunJjyzCXwLSUz+Yg7lSjvz5q7XOm+bjo
+Prf6fHD8L3+4/1gDlhX3K1S1m2U+IyZa9uEkaAdsNW0tmEzVxOw5ROaBLZ2+62vB
+H4W378z5Bwjfu3G/Tee9J/gWJfLE3MeO8ZfC8TuSHnkd512ibg2gp17+lk8Tde5I
+zIf2A9Ljo7TSnFcw6OF6aoZDqvuF8tdTlANeusNhlrQpQWTxeDJm0PJnVwJkZSes
+B8Bc2DuECaCRlSihU4Ex0QcOmaTmioSpz2JP/GVmpwkRpPQj7deXYgQF9SDJrWVu
+WJAoR9kg/m7oVsP6SYYXSxHYSIwj6Ul1nJ1985H8jWljElZACnTVYpCNw6LOe3bF
+YBBJGKDAKjLpAeYzt/v5LP5InO1ReSyiVMPrItNoJeQaCzmx6eXxa6qngNquvZiW
+PiN+HWQpO0DrHyahL4Mjkj/XMNQ9El/LEuCpysYe7cmUmlu1a7bDCYcRr0Cd91U9
+0H/TX8smHEiLc8pE6yQcBM/aGYWJj5YXWZp/lKJp90eqo+7HvbtN+yswMG/V6Ebp
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UIDCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UIDCACert.pem
new file mode 100644
index 0000000000..1100bc4d8b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UIDCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 55 ED E1 DB 35 27 4A 71 07 5F CC 53 2D 99 33 77 A9 D7 27 43
+ friendlyName: UID CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=UID CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgDCCAmigAwIBAgICA+kwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDFRydXN0
+IEFuY2hvcjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMD8xCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMQ8wDQYDVQQD
+EwZVSUQgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeFABwDBUn
+ApJRGeo/+64E11KZ3rpoF+VJIX9apBq3DmF5GxhYb5PiFTkOPLN34PwLf3qLez93
+SSgZv/lXeQhWnudJlYLTwyHleDYo6uzFzG97ud10DKLEL4qz6tsNmgOFN7DUsARW
+cniQeA+PlB7FOAq+Np3AU3thtysN9pj/7kfthiHSpnaolauqdQFug2QC/Tsuqlpb
+wdZmC+0jcjz6F7FPOSo/dkTb1gy04sjoA6QRuCAskjlkQvSuviU48CYZwlXJg87m
+R6t5yDk1kv1NSUcL0g7PNC/yIMZiNKzkP+hVOYc/EK8dJv2u8rmp74xCW7Zq6lhe
+jgZF27pmsTuLAgMBAAGCAgUgo3wwejAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51
+tmWn2V2oZjAdBgNVHQ4EFgQUED/FBDDx2EM2hXlcjI2Lne4vHKkwDgYDVR0PAQH/
+BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/
+MA0GCSqGSIb3DQEBCwUAA4IBAQALOuCe7LwozytIfL3W2cNZdLVrhfOXpE/spkte
+1wi3VLrPYFYX/WMaoL++FBP2Ct3vMRaAmBHeAScN+FYPXP5Nc4DUiDlDXIC7oHJa
+BFlZq50K9sUIfDUiH2acsdrNqwh6QRO5+tdah+kNRmSnq1x+b/gSVkruCyo/hgLe
+XuvjLlB9CHf7FcD2TjT6kVHwTztZVOyC3PD0itzmla8BiY+Bx27Mmhk9ivQLeM/l
+ZXScBDdjrKanYIqmcvdrHGVRjBzpMQE/Vq7wwb9pDsm0nUiaHcfJQxrzNOlIsov6
+jtBJCP2luvGQia/7gwP8r6Ft2SsgMqH59wBxSipXP3qpz6sS
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 55 ED E1 DB 35 27 4A 71 07 5F CC 53 2D 99 33 77 A9 D7 27 43
+ friendlyName: UID CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,390F5B5463C07EF6
+
++b561AnTMFle7QTjksjB8FPxB8vnBF+TY5ruzWhIexa39ZBXY64FodVv5tiFbpHy
+r+zHzOkowBnFCgwn7TLyWrKg8cq9hR//07xDlGloK966SIRd+ZJ+pvVWUMZyyN4p
+D40ANS1sBBEhcT7P2ae9+Mz6Mv+cDRE0//qJ7/BEc3Hj/QxeGBIThSMKRReJ66jD
+HScThK8MyEUpfuz7PLd2dTFqxWjk2CuAz1LsseT7RD70zr9wiBmS0q3Fo6JVai3U
+DvTY7xViSPbPtZjkZ0NkiQRkXp2dh4r5yj5gCEbq+8wDDmC3qGhI8tVwF7rRSpUt
+IrWo+MSTgazPd67NsKVai2uFN4c5ZD/FrBOHaS63Boa8zX05VT5gYhfEohnlz/hG
+CptR5Oq1m7D/nSuKmo4YXz6BfkXYE4IWupylKkOs71tlNCyYTBfGUMHtDjqcaLU+
+3rEEFSeUwxlsA069OKubZ30a/A4AJGqhujFM/IQcgDXZnlBe9aSNxYSRFiGedOgD
+RM44jgKJviBx+wzdQ2FPUGPQLLbWd/9QeNyEZZqGVaSDXfaFvmkkKjhqKVKq9qrF
+1EEKFiABCuP8P8eIw6fS1SlPauYE/PRqF1vKZDvtUElsCpWR8uE9837rPmaY3dg1
+9plIDyxZQ8/JELqRu5suIAgZsfO9lCaTCvAtIjDcDVCxp6PcGRU2QX8BAQ5EMVmj
+3ZinX/AKCbiySnLXUOTt7Amo88rXqNRxtNPrcRZaRQGv1Lc+O492tYOZLwawLYAt
+OQPcZnHSfu6yfBK0p9xRroJklX086Q5FLdISb4AbuQlP0plzunXcB5aV45lyJmya
+VAcNh1edLl+WK6WG0/MDoYX7IAtpXuV6OQ6gmuAogPFvhD6Tku7gc6WVA5ADrxew
+H3t9ssfQ0vsWiQdDd7LjC+2ft1kfc0FxGOyA+A9Dbq19fXOjWrYi/oxuAe+RRauC
+zFfzUNvsZJkJFPOHFuMjLrZ5K8SYxkgiromqtgq8lZ8yULme/Ano0sm44wO0No1v
+fClibDyBAedvroSYqaQwHoPd9j1+3hIBBGQGF+t+qZRKkw8CfrSQYzfDYUUcLn3i
+v/GhxTgIOpGw+kxdOYjUQsS760/7Iw1ZuBy6kyz8J3RHntlTUC7bIvnlYTG4kQa1
+/tilt3cOmyZ0ONyIHfX/ErlSf7KBxyN0FHenD3cO888tbRav0fMmRT5EWe2LGg/a
+3a0anl6W70s5ypDPb9dhgfOwuuoTUzTjndF2IyQaPz51IoSoUWagIIjmOumB1lwv
+W/2b3Tw9EAXq+1TyLalAM7rRKLTGvjSEpDJwfvp2VIj8UnM2RZV9oxi60SY+Rc4s
+rqdSXMjnrc/SYZMVNp7J4pm/megIUAIh1k65vA+DdtyzELfXw8CY6reIHhCt5yG6
+/YKajR8Wad+9fV6Yu3fSKQLRtaWGtOJ7sP/Blxs36eGgWglvBx5sXWGvnx70HV6D
+8x07lawJaUv3LTzE8FiY7jmLgCXmaGrV7Liz7mQV9cQQ4qf133JtBZlAXH/9Jnan
+B8tfwvFPCPMUI+5t9fPq0APnfFHIowss70IehYQYqPWMiX7TyzY7mw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringCaseInsensitiveMatchCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringCaseInsensitiveMatchCACert.pem
new file mode 100644
index 0000000000..1fff9f5e40
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringCaseInsensitiveMatchCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 4C E2 7D 0D F8 76 93 B4 5B 55 34 7B 13 B4 B5 CD 6D 3E EB 9C
+ friendlyName: UTF8String Case Insensitive Match CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=UTF8String Case Insensitive Match CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBZDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoMFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLTArBgNVBAMM
+JFVURjhTdHJpbmcgQ2FzZSBJbnNlbnNpdGl2ZSBNYXRjaCBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMG57Err72Y6WVucCLR9vA602ukJ6SGG/fkb
+m3MdFHFnIlwT4bTqW1vVDbWM6JGk6Ats6QdrCKHNepQUivKcTaOf+Z/AM0PF8Dm+
+/46w0H8slEycnjp9R9kVq3RxnfaCVUuoT1GUilrIl6lzYDbLmk586gIDHiKIB6G1
+EB1SbyGrTqUb4PbX6BqTP3DyMagsCXbB9mQtdub0TMopxgLPhx8c9J4dT4GT2zN0
+YhDhy1j2u/fe2IaKQ/cBYdli4UpwlJzvBQj9DChrTUeMU0bE8LUUot/+SgUnJzgM
+00LL1siFE9AwjpdtBp5TZWaGrGJGNWEzV/jiRtmiAKoU5qMr07ECAwEAAaN8MHow
+HwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFGDfGNHK
+qVCSERchRNJ39Wqtpr54MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXDmk
+vYzphSsHCShEza+0eHMVa+8vfRkgzCtHfL9ch77919MmuIbJSuXxvmkV8bwBdIzV
+A9prai62c2AAPgDGlFpQZwUY+ead5JWxnqhdhSbQQ82GguuLbjmwV6nWeGuNwX7S
+bLSt7V2e3aiijWB6grarbdReY0c4r2gceiNA5QpPmFpnL1r10GnE+hCf69dLJGpp
+sAzcGVaokxKA8DZhgag+Jv54NOMZKH6o0L7p4peM0l/acVHkLNvHmZTgjrz9If44
+wHSFmxIjghuYD5gEKtvxUm7blklS1anKqrHHaqQfYWyJfBAwdgNjiASvlfypETzz
+801tbjXPclw1G82spQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4C E2 7D 0D F8 76 93 B4 5B 55 34 7B 13 B4 B5 CD 6D 3E EB 9C
+ friendlyName: UTF8String Case Insensitive Match CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D5A849F04F091743
+
++Se5p0hI32zfLidURyAPBD/QOrv3xuIPNygZ5Pu1RlSfya+tMtQ6Cl1w9FfkjQ3N
+qxunN8Z9QvRgy9ygSzSb43/zdPPG35tQsiihMqW3em90ILyJ+ZnkT9x/FmmQ6xHW
+ixAQPtwkGmC++FqPxdn4CzS2JaKihRkY57fbphw2JbMcccpi3qltSmgnL82mYedP
+2qYmQcwIryLrjU7obwfseTCW/jikAfTRSqHUS7vmXgSObuIi1RLT+botTQj/aV8B
+Gxgkjycbs0iOC5/O8fpw/Izbw+HpdSD5Rm/pEkT466hkrjFZodx1Wv0rUt/Dy47o
+jK6RVf620veoSotzmb+Em9wlkBoow5Mi8dGGT8FxsuKFE/qnG74QmmISNPHqInP+
+gLLfimbJ8IlJr1xVZKBTy6VgzjIwIWC6StaP1W78VC6n4qicSos15G26wrjwW0aW
+U+BRDmM1jEUhn4X77WDwTmk83+ku8PeaKJHCW4smruFWtEetFG1toZC8zCa50/JO
+FZVxVnn3zVFUGpd4m8kNiVXt50yF9zJ0jm2FabOHDGHuFdyyxjXRL3/NRX5inAgM
+/b8oCkLMnrDGbX0DRGTzGYLSLkGijSknvXsCnGoHVTJ0aHfxyK1adHOZT4zcFXWY
+NVg1TrYXfAVI9eZehuTAzfiM0a8tygdF7FqzpI6vFmSjnbyEz65VeT8IlxvSQEfS
+ZxWYH0Il5Zndh77mX2BUlxNThFpE0BHISV3zJpdfKozmaUl74VCn+epaB9P3midf
+7Ku8cCCTr9MFxerQH98BLFrMgKUO8CJ0n8exggk1ozKNQ2KNkKKwDoIvqfFn/TEO
+oJVAQUliB93ioiOHyb0bhrm49tmo1FmMyV4hX4/lPJ4E5O5kQShTDdrDUhQAgQUa
+cma+8oN8apz57CWaBdmXKWGEGNx/tP4LnUnbftN8gXTGIVTt+Vc3ihrwVwhbmzEZ
+Kdsezyi9aPP7OIt+L2156WkC+Da1VnZUnGxvs5n/4NG0sALVmJYqMVsytpzkXuFI
+BgBTp4KJlAjjuqsWe4D8yRgLNQN3Tv8qp6eaFNhkpBZxrPB85B+QoLSog3EgE3tr
+zPx/1+yaM6LNcqyuGB7W7B/kxz0AQ9wekJ+qrtC3aN++l/fc8/wGLkbjro3vEDJX
+0TwlcLt40p7udXIHTukEHztSgD6LaAgEwtWDyfZUPPdZdw4mKofpVhuu4Yc+mXqa
+Ead5sDa/xGHC3H7d5T3Utmyospzs5dStsjUaocmLnC0Fpik1hlU2+I/2Qt31AEWt
+wMvylO8qNzbqtKyxLyBpPN+0LE5NWxUnBpr7pSfI+q4+VvY6BJgJNlgDAoE3Edv6
+9e3gdQ16jVBBfkUDbit8s6Ey0wam1kQwUq9561A1ezpa3HnzeKf4BdJctBa4CFip
+Mq+LjtHR2H76kFNpKjKbjuwsUcpjAug3hbNX/2H8NQdfrA3pjyZS4fQlqnhfVB13
+ZsWgaBOnjHOYm9gvmKijLAsSk5xPLjY3W/xrQDQCbN0LiUZRQrukMYxqE+Qe3w6B
+9f0uzZ4nCiLIOws2RUZgWYTq24R8VHAnEfLfUBVcCvLQeGNwPL2GgQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringEncodedNamesCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringEncodedNamesCACert.pem
new file mode 100644
index 0000000000..3f07a3a22a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UTF8StringEncodedNamesCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 60 31 94 D1 83 3E 52 FF FC EE 93 39 04 04 7B 80 DF 3A D5 74
+ friendlyName: UTF8String Encoded Names CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=UTF8String CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgjCCAmqgAwIBAgIBYjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoMFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFjAUBgNVBAMM
+DVVURjhTdHJpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDp
+FMdocNgWHWbH/yYbXj7cmkTMmrDj9bXTRwJQZM2I/fcTefta90CFELGbDX2RdtAn
+jlSJqkydCKjhhkKXfMQFXJDlM6MQLf4rcQoxEP8UI2KmnbkfEjfsyGBxnSEFWe0w
+ZZ8z5eWrLyIFZYk4x2Zyc5da7szsOnu63qN15kAJRf5qLTQyBVbvG6pJrOQaDF9I
+SrgA1Sj7UW2puqZ40fbX20zywWxMEIeX3QO1Ho4onJXwi81/LMjZ3CvWqtEuGXo+
+D5YJHhMBx2Ok777u34ahScf3f6h5YBixNf69RCCIR41Hki/aJ8Uwir0Ylx9mdT0X
+fE42LskS6v/MsFLGUpCtAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWu
+vnW2ZafZXahmMB0GA1UdDgQWBBQ7Z1tE8g2nSH1zKYyTn9Uk4xJgJjAOBgNVHQ8B
+Af8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQELBQADggEBAAP+S9Kl9ocPuIY66PoFSDnkqzKGoqlaqslJ
+7f7oUQTUwVKGx6hxk18tUGCR4rof/JpLBj6fjYLcfAutev7e/ZZPf+X6X9QlJW3R
+pqLCIcGfa4k0LdLLDIYUGKu3YzeByWf+7AHjrFarwSxlZSHwooknYMokxMrgroLo
+Mkawy5gZSMyykCgLxWtJdCHq/lSxLnseGN7Xfpa4Yr4ST9GgF3oyvMVIgp7jJUAw
+15Yjtfpu0NJ0EkWbLp3k27UG12xDzC4XZUfco5ecXy0Iflj1USDPXUMJ+9etyJQo
+6ctOAf1vXD90OpTS9YynXwm4VCqRRISItnWSbLIvEK0zg+YrB1U=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 60 31 94 D1 83 3E 52 FF FC EE 93 39 04 04 7B 80 DF 3A D5 74
+ friendlyName: UTF8String Encoded Names CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F85DDC9DE7660E27
+
+yaEWNpSej94SaNM/VCAqe163L0r9ncBBhhHlsfECuxJ9sq8eJ/UKfg+CVACGk8fT
+lzS4PDjrQ4Hb5fruvgM3FGMDFDmX/7FURmwKq4Y7yxqwoSzDiz9Fkj/mfHIPBvnV
+WR/LHseGpQsbk9l4fJnT/h9HDFH3edhMIgGZGn226QdvJb0GOOO+VcmnD1wVCu9i
+ljMGJ+x1RsihD2cpXPLsibtTpy37FgGBGsE2Q0yxILF6HpjUXf2GpJ3IKesJXCGv
+IqNj9+JlUs2gWb0sio7BBq5u2pM0xug0HfR96s0R3oKSr6rOUCeqggd2d4200mv7
+o80vbwA6/A76W6oeUV6hpZcGOyGrn1PY3Re0bMzPDOmXzesANaV4iLC9Blcs72b2
+Ip9Mlf9270wyAx87X2itSCrWV8Q2YKHIrKGwpfW+Ew9L8d7nVOn1XSvjZfKuERVf
+ssOcd53yapyM/jRCihvL2TeBUjq0hF0iLvzjfHhfptkbaxVQAGS2h2yVu/HRCfsL
+tYKwa3IoZkxZpv3MA2HAOWs6GQaAsIH9pCtq+PjPSEgSn0dlNv5Xq1F7tXI0/FB/
+16rQyrDh+GxkhKJhMSE7KEGdIWmkFqGAxibVMhGEF7+OvNRsbYKy0w9H4vRdU5p9
+TBRF57fsj2IbWk3f9BNfV5TJn61Wy+g63I1Au9zKBt44UH1MqfDdG8iV/0BcX3M0
+YFuZSE60oqKueZYgEIR0xJM66uQHXCuP8f6FiJ8Y8EnE5fTxrBDDpsnVTZGe4cu6
+7RVAVuPb50jsEerREKNuyzZcIphS+DSIXeMZKxdijP5gHRdCjzVcVcNyMuqJXyi+
+CgfsfcFLcLFhx8UCugp/2ymVVmXp4eZ/hRO/7uPpV5I0vzJtbwocaaavH+6uSZb1
+oznWLPu/EpfjCS9nGWwXiNfuiJxuyQNxmkGSbAOwxHHnk+kBj9XJdVtFRSEgolSU
+5FKkWJeJ90FEN/6XnnLFy62fwH+VdYOp/U7EBPza9jplrwj01EaH672Hx1ijUDyz
++FN+X6Ny/EX4w6+sSqnTBFA43R/iFfZnM0cW2vYCWPCyt3lbVqFxpwb87o1Aa153
+YLENm6i5oCNaCqkdmov95efxVpJCGmz7zRMt0+f6g/VvUHRFCy1aFS5al5l4gduf
+uNpC560+bKO48TZPZkUhrqZGWHZL0qmEN6VkKDTzFc7Fcp+twptI1+Xcr04L1gNq
+o//Rr9D4R8+bfpsQ0b3chB6AnsMrKp1A63JmCGxUfkDyiPPzAC7P6FCmfXUQeNOM
+yaP6RCrqIGKpfApJDiDBjouSZZX4FXXewdehG/yYZBT8Bb70M0MOdme1s/IYWcv2
+qPcQ0hkWBOTOhsV+q8bZiyVZ2Ab7WgqkXnDcZC6Mm8JT0CfydGaQarvpuA3ulYCZ
+3dqCbrXdaC/eyTISfWnmrWWf2yXSqyZxZoQ90CE//ll/+W6MMfQ0v/nQ+9in4xVO
+joJpnzDKCLzH0BDD1xFI6v+IX7OtBoYw1PqEdt9gQyoPL3bS5TwgJKWmU77u8FoT
+hYo19g3+GGFYfuTYb+SNsl5rSLiiWBMpdwAyfU7wiOpy/qOnkQJymbX6CakiX6sR
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLEntryExtensionCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLEntryExtensionCACert.pem
new file mode 100644
index 0000000000..56a0860eea
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLEntryExtensionCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 45 65 43 CC 9B 34 B2 75 2A 14 F8 83 05 A4 1F 89 B3 73 7F 82
+ friendlyName: Unknown CRL Entry Extension CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Unknown CRL Entry Extension CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBDDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJzAlBgNVBAMT
+HlVua25vd24gQ1JMIEVudHJ5IEV4dGVuc2lvbiBDQTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJq2TVjGIQMG94IR0AGNlX+dXBLDqMZwDIJxAQ1UbqD0
+HQs4NhG/NDXeV02qg40uMBG0p4b3s7inEy/NLdw+ttgTkQ7XZhf1Fh1BrDY2md9z
+kgigRRvTPKJjzbW/nxY32ySomL0ABlPyQQQg7Fy27cWeqLbGFGF7K6avwI1sdnGw
+/QzdLvkTGSEWYGRQrfTJgSf74f4YuOXsiHniQ7Ln7pTKcGlhgLDMxGJOSb9bnaJ+
+inxuz8eDlNiCTu71qN4iKwJgT3Ch4waqG7w8JdoIkxDmkKXpd7ETKdyfYk2kUt1c
+26hvv10iWxUPZ+FGjSx6vJzC/S5FGRl2DbBabA4BcKcCAwEAAaN8MHowHwYDVR0j
+BBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFACmGcuhLU0oLyLz
+0kw3z/9MMM3qMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
+MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAn+VVEQ6vEy68
+7EiskrOXl33w1rBT2/JUlSZnws4hRhBd0363UhXIGd0N/fBVGas0ufPXS4LtYQjs
+lFpO5UPj3aJGk8Bq9t+3DvPz5rOnTZCiiSZu+V17QmiDsKnNgS0YWr07ESK46nzM
+5mjXhARQPUkbFR7UEXsFVKU1GTvr/YwGHQ8wTvIryrIjgVI34tB37i1JOEK3j3FP
+lDUAGnaDIz8uAl+qFNX/W66/haHjDtwVa77j97HOA7rrhpfEkNaaOpjDxKPQLSOG
+nKitdrq2S6Q4TA4mHay0XpbaoDstAOHMDKOnZrD9XDo3szNWu3DVXhS/AwiI76Jt
+P15GKWEzOA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 45 65 43 CC 9B 34 B2 75 2A 14 F8 83 05 A4 1F 89 B3 73 7F 82
+ friendlyName: Unknown CRL Entry Extension CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1F9F099D8BC977F9
+
+Pht6nyk49343UgIQNTZHJsR6hqAKFrHqQXCCcMqSU+cUfp9eBZlfY3kIDy1dLYrc
+3XRGZaD9hMqdy4Zb5JwTUiefw/KSs6GE18bz+eIvKz2iq34OZksNYrgF2V0c7IPN
+e94dTUvCL3fnSOh/UnSuJ7G3ySCU5AI0pi6k2J5x99HMIp+I9Hn67rXhOhlMTc47
+dt5HfArr2EaYYdD7NTttRwpr+37mx5EYbByYhN/3q3paC0AxRDMpktSPSniPfp0O
+n2Aj7kaRsOaagh5yi7V3cVJpbBTBKoqyQO+xUoFSZ99JcvOi3IXv9uMsUAcLtBG6
+6qNGVUHadISQ2m6XtVtzdE32az/Uj+AXYPZ7/OKfrU9rmw/LVtvxtvsX6cfxjZ/R
+6TMhwHzVpG6N35G+Pkq8FRpjMMkcdyOurTpUZINxgyeodUgPyKmOhrQwFMae1KMK
+aZgTf6RinXSlS4QOI03wl8+IvqdlWDZnN0AG2ZhsoI5dEKyB3oAG0wz8zlLH2T84
+Latr7ekgncqtXO9rJC/D2Po4rG4jTYrucUmKrRvXdN7hV8stLUSnhQHNjqrcR7+d
+HKKtglQWLiAPq8ytY372zGd1EIpC9qMFZNv/IQAMZqrCt6e+uMN+nXDJDPB0w7ws
+nbvl4t8pAOskfOY05ode2VH5R7QVr+S4FB0iH0ARUmyyVNe43QGPjxCEkocB5gLC
+/cnEs4u+1sKG4g2Jfm98xsDaD4mSJqXBsfz9A59jYMjcNZeuN3ZZ09OyyHmGAAHF
+O4xYOEMzU3RjQ4CAKqD0iaAhw0vxMRPBL6rR0ngTtrxRs3890revN0RwN+zomtTM
+wuyPL7b9KYJq0cFe+262AHIGi73DdgScEsyBLiXs/uwW3YM1WmR2gAy/F17CQLoS
+aRETP4pEcMHzX3vagkS1p8h/BO0cfUyob9ABybJiXaq8HzgUygOFjbRk/wRT558D
+bxzGVSNnTCvsGSoeIkmQuCjzZ7WqWmc4AVCq2yrYGqxhyzQlTjH0LZgfrz0YmliA
+PQINURKMvqPhsqsav0oKJ1LWwUkCYqNhFTAXsx7o3hdxf7mahQVvI+jhWUHhXIG7
+Qh80bLfTQsBy71R02FfBhh4jGJD0OOBxQJV09tkQf1XmeRTtTrt0AhOViZa3/KjS
+d9sGWWjJGeV1tBLJmEan/qNXOozM4josXaz8ot2c/2ERbIapp3lkNiHMh6tyPkRF
+ayaa6E6t2XBLaGl3nlawrXOozAdQbRbzMG8hZ7XjX9XAGQxHR7pOzEQXfJp+6BYN
+KnV3Sl5REI7L3/AuA/cABFA28WqPVOjzgBVAU5MfZNn5wgxqqkHbbpO6oIEw8awZ
+2e3/vpqkU5HNcD3S5fqcMVTx63Lu93Ry6RXzTmRBGoAHtZ3i447sTNTrO2DgckUf
+e6MWcysrUi2TkX6t2wKILhLUx4QboW7HH4WZjXUNVd+Jj/cojX9gXPDoTN5tF1l5
+oALvgZareTUYCW9F5sfqcIIZiGQYvhfFJeAXYbM8WI7ym+tIjzdEfUeP4RdtsE4C
+/xjA1sgGbZFF9FalzCuUmLLSHwsMo0tZZgU13N1/Qon2TdvT/u7BEnnaPPeSm7pB
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLExtensionCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLExtensionCACert.pem
new file mode 100644
index 0000000000..978a8f1192
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UnknownCRLExtensionCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E8 29 F0 F6 2E C4 7A 8D 77 56 2E 28 64 D1 A6 96 7F 3E 14 3B
+ friendlyName: Unknown CRL Extension CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Unknown CRL Extension CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBDTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExITAfBgNVBAMT
+GFVua25vd24gQ1JMIEV4dGVuc2lvbiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAN3+bmlTsYBVkvHVXNA+SAx982qdi4yGQL2u0PlcbbsFaWN5Sl0U
+1ZF83NTAmeqJKesUvJKicpijbLSt4rh2VVlrwDEe2JL+D0R2mSomny8ViNAe2z1Q
+OSolQnAr0IlPE071WQ77b9kSWe0HOunRrORTQNEDmOS9YVBMW9hv2YtSSJP7RMht
+sV14x3JLmoZY25YlNo+nWxakLuabNERqfvK7+aZmlbtjGpkR9QsGouSHMJtH6nno
+tSyjg9R/RJZi5hUqzNz/0iRww7VUcIkr85rVAHLkHJNdOy4AiYOEMXpiq1gSapHO
+iqzo5WwU07AM6eG2pqUNurj/E4j9Q4K24lUCAwEAAaN8MHowHwYDVR0jBBgwFoAU
+5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFP3//hlN2wydxaLYglbrsNkQ
+YeMxMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAOMZEqelK1bLZqjY3Ap/i
+vt/zf0txQmVZooyCElcIZMGvUNrpBOUnAo1Pl9f/I0SZImszjOxY6gS7UJ4TYymN
+n6z968x42BiptCW560/djERAq1+15AGcTd6E6o+bAG1n35uVECkEj0VCovcBRJRf
+l8tDb4FMl9lTU0g4dQb5s2rjy8RWJrZ/DRGBTvniDUE/TYKO4LYKEWmu4uTTNnba
+1RCG8bGe8vheiIp4Pk58HklrLewClA2NiqSXmOgpl44FlGeWuzh7xlkf6cVVUuaH
+553QGvjiDd43pJKBx+ihsFfHzelGfrj1BrQWaRWFoR7lX1GdgUDsYvhOK4ybEKpb
+/A==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E8 29 F0 F6 2E C4 7A 8D 77 56 2E 28 64 D1 A6 96 7F 3E 14 3B
+ friendlyName: Unknown CRL Extension CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BF8997AE3F28C957
+
+Yb3OfRlikZzGcSRuE9Q/nGEx5tpHFL9zZbku9ta9WZLz1NhJYUBIb/rUud7UA+EA
+GN6RcKMDRfXwa7LTQjU8miQFwyfE9QXGsVBKFeRQ/SSPhvyyg+XErYmszsRYIJ06
+6MND+TKTKgbOSi7aTsfLPjLBfsiI9w9dW3Xn+Sp6+ViFZJCN/yqAalVvHsaRR/Ex
+D5DoipwaYcIr9wUW/Is5+xWdJOU46c4ILxao7kGtBvpf8roRfbY/pHND6oBK1YUB
+yZrnI32gz3eUXWyFibAJSvkOqKqXLFw81sN7+WyHLJJmNR403GBBBD5OxPmN74Ng
+n3lRQJt1rG4W1ZlPRylaiOeRwxIATqKyZ89ByJSc8Q8787o070eMGWR6fsYaAiHl
+HmjI63HXyqvF5MZOMBFBrHXjSBPOLqvDLqrccw/sI7su/mA/gRg76ce9Qx/Zg1Pb
+oF7zSo59fmFG7AsROBvVHK8GhPjYLe7t/cTNMh9mpX6Wv1KpH7o11Zw7ldMLGoZX
+t1X89dcj6MX5rN0qOHM6h3nVT1PQMIVPZRGKnbGU+sAzsd1W8wgktWWdHL4H1ubI
+yPCl2NGOLObTBVcmrk1OzGhdiDaexBjpwl/G9oLp+VWCLZ1pIMhn9LLYmT/ii85C
+cI8C1oYRncjgl9nRvdnpFWnsXd/1bewuIa7GS8is/4Yd8+aPwoA7X1ngZVfbvVU7
+nMogbZMp13CKme5NfSLxANLRd0v9sSbsFybg9seXx3nUXBh/GmIOPdYv8ZzcWf9y
+gA7bXH8VQGVdaHEPWrwPUfN4XMFPP7YBZlH8WOjxBm4hQIW48odVOUn/DrxumLPi
+6TvhUuTFnQw8G6xdLRb7HSOq+AEa6Vk/jdjj3K0axopByIUzGkz+a44vl3VnJGO2
+0uMpxbtlWqogEMESI8TzKJiugZpHc1DS/g/vcCx7lXwOVBXVIuXTBMkHAPQosfbt
+4NtB5D080yuOr7XBjzTvxWsMdWAFbbsLq6pElLVUf1ZwCa/xkqPU1FMHqUAJ6cUk
+VMMgy11esel+7Fdjg63f4wCq77me4Cg7pQU20Et66WYpDvKANB8dq9kilUKpSUAk
+ocBoFW9H7ERN/5i+XSzNIDDR/yeB42nqcWyN3Y21Hi0DQtEPwiXC+ye5SQZ0lDqJ
+CwAOGh2ytkiMua8bnDi5j1x1V+AZJYDSYHWagCypCK5ZgpRcOxd/9wAQCLvUoM5z
+F+y8KPvDbjw0Ru74wZoZgNB5ZQQHYcfbHjvglmu94vmL+MfsydFbgLDUXPIQj3/5
+BGiFm04bNP7AdJ0UC6J9yZWt3vL/CKdwQrXVp63Ix/v39NQjOT7MlvN5dZOvwMg9
+ED+7iCvCm+DL2h4wSOaf0xxC/74d2gh/5DzP9iX1YcbIpi5KlapYBEAifHV89HiK
+X6U3PvNVepaeeQmPVKfBVxYDOCQvCyUDZRlqEXVnw5rQhJfPfNj+apuEFL6LwtHx
+lKiuBGHoZMRFXnHgeGw30Ih3clGPvOMJm/Vup2DKEGdpuoAUcpjxOWK9aB961wmR
+p3czkqBheX2IrzIXlITEOM1dL8iud4qYGzTAJudeBaNLaLmcTrHp3A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15.pem
deleted file mode 100644
index d22dbe7f91..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15.pem
+++ /dev/null
@@ -1,59 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=User Notice Qualifier EE Certificate Test15
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC7zCCAligAwIBAgIBKDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE0MDIGA1UEAxMrVXNlciBOb3Rp
-Y2UgUXVhbGlmaWVyIEVFIENlcnRpZmljYXRlIFRlc3QxNTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEA0qDoX3O5t52G/m1yV6MSg0EJQQn8QFWgZUnEutHYAAdA
-GuRrFRXtkbdQkbyePIu4nzj2LCmMAfVM+QlOWLFCnc6/s38tfZDAir7WFHBFyUzB
-gkw+q1a9DIXfaq32yn22txxzus3dqRZJui+5J1DMNLbHPYS1WS7Hu/3dL5ZoR30C
-AwEAAaOB2TCB1jAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNV
-HQ4EFgQUHYqwkDHyipKBoBuH/YaAiORSh0owDgYDVR0PAQH/BAQDAgTwMIGDBgNV
-HSAEfDB6MHgGCmCGSAFlAwIBMAEwajBoBggrBgEFBQcCAjBcGlpxMTogIFRoaXMg
-aXMgdGhlIHVzZXIgbm90aWNlIGZyb20gcXVhbGlmaWVyIDEuICBUaGlzIGNlcnRp
-ZmljYXRlIGlzIGZvciB0ZXN0IHB1cnBvc2VzIG9ubHkwDQYJKoZIhvcNAQEFBQAD
-gYEASWwltYc1aGeHLYySbO4SCTVSgVrZAXfAoa/0RHmL0et8olJXCLdXTMq2/6rI
-gibDeTUDQ2N+5z23QN3hDG+Syz9rDBbj+m3MtvcsvyyXFK62g1NhZxyw1+dFrxwK
-Ci+jbMqXaXsdBG6a9cTYKw2geUpx9ig46FLMyn7idA7OrrY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15EE.pem
new file mode 100644
index 0000000000..27b2cb33d6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest15EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: D6 18 A4 68 95 87 7F 71 A3 B4 18 B7 4F EE 96 67 22 A1 C6 3A
+ friendlyName: User Notice Qualifier Test15 EE
+subject=/C=US/O=Test Certificates 2011/CN=User Notice Qualifier EE Certificate Test15
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIBKDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowZDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExNDAyBgNVBAMT
+K1VzZXIgTm90aWNlIFF1YWxpZmllciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTUwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkS8nR/CBLM63BPIASc/HIZLUW
+rQrETZeD+GSRfJD3dhns+yVXSruNS2NJIb9GJ9LWU759uH95jMGlAmFltbdAyd3a
+AZPqvAYmi8ZpCbS5z/Sg527s6XPHGFVjLWKuK9CN9GUyH0f9dJ2nuQTZESbELZRT
+2G9GOnaPKaNet9jlmu3ykU/av1UNoLOoJ//8hXRh3NaeI6c/3i+N2eTD26t4IpkF
++ez7xx9ULTjw3xAVBJDJK+iz0KdfZcVj65ahMEmhWZRBzn1qLhboVnK7cRzCNqWz
+XF+bIVRt04TaZ42laGLqPKv3cJK7KdRYxt9gRVNXnthIP0U8RODhAKlBeAALAgMB
+AAGjgdkwgdYwHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0O
+BBYEFI+sjau3vxyGncC/k0TJSTOkGg/HMA4GA1UdDwEB/wQEAwIE8DCBgwYDVR0g
+BHwwejB4BgpghkgBZQMCATABMGowaAYIKwYBBQUHAgIwXBpacTE6ICBUaGlzIGlz
+IHRoZSB1c2VyIG5vdGljZSBmcm9tIHF1YWxpZmllciAxLiAgVGhpcyBjZXJ0aWZp
+Y2F0ZSBpcyBmb3IgdGVzdCBwdXJwb3NlcyBvbmx5MA0GCSqGSIb3DQEBCwUAA4IB
+AQChryB49S/BVXmv59TlPzJpVgyW7PstcWfaKX7Qbf+Fg3ef50OA33+0qT3dQz+L
+jU0f8PMJWfrez15/izohc/YZPY2sSiJ5zxzvPGliVqDeHqnJTUc+nWT0yeghmBHZ
+NEoNVSVJvSZEesXLCmNQh9g3BVZ02jx3dRDfRFesaxtTIZt8pazRdmV70aXJlT5y
+f0AiFsHzrk818uk2bTipjZcMGExgV8umbnjbk0P3UQPnhRGmGGH/GNytL1xO0br9
+dtwq0BNDWMELT/Ba/LhebotG1YUCYdd430Z+BxKk7gkwhFADdkbil6yFDmgRsYSY
+wnOpVqmDrMivVvLaqUozgsX6
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D6 18 A4 68 95 87 7F 71 A3 B4 18 B7 4F EE 96 67 22 A1 C6 3A
+ friendlyName: User Notice Qualifier Test15 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4B3BE0AF537F0D9C
+
+qJCpcjplG00+wJZIKUgQSCY4a4afYIbUB51eBwSfEPAOqD1DwB4Blhs8GI0YDPe3
+vgcUUqgMzOjzLNNzMp79X4dHJ2HAWMZ6n8e2nTkjMuRDyoky0OLtnJYQ+qIB66Pd
+UUUNQWz3SU174cjRBiiGy04/l6MDhiSsMAbEcf1qAJAF3/cyJmAefuUrBposYd5o
+1Os2ue3eU5K8bXjPGuo0ygwCM7M9tnK8tlk0ppH7hEuxdSq63yRhQ9zc/LZXtmpz
+zT+BV7QAce8et444v6HDAY5rxCL/guPNm6vqJwRwrQ2+9EbOzjciVEuiSWAIVZg5
+aLrFKjYU0863foC7ohaNDHKu2sBbDo7V7cFIsn/emr7bKs42eE5eS3ihWTjgcuCK
+Ew3jkbgWTFwW69+cb9VLzx5I1eaKBDU4sVwiCydOrF5pvTqC32CUwou5uF72WELv
+krm2b6dldjPn6TB3VfbXjwnKr0kdlnb1KxkK8n3DKuiHgkwSBBi/Tap0Stte5pHB
+c8ezNy4/WWT/lwzQQojWfVLi83m3DDz99uMG2JztxyJtN+PG4Dj+sqctCUf+dcDY
+EXicdcWIF2jvgb3+P4CIjJ8fQ3PammaSNhVTOOpmRb8Mz930E9ylrMxTL72RaY35
+/gkmVeEkTCb9T4+itQ2YJBs0TFlIAVmUkuJTkwunLF6h0N8N5CWVJV5yulmSghSB
+5NBsZKbxWBmx7qaH4ZT0tFBjelvV9isgbi0nuJjKNq6DDNV9ZemAKJC6K7J4m11x
+qUombB+njrrbfBmiXjOV/jnm3CRVcvd1gNFG706ywHm1SXvTUssmOB7t62ETKmNa
+i/4ti1O42ixjXsw8v/dydhFy2PeF3+STAD1+pkgb+2RBcHdSCOWmTMpEudScig70
+NVR6SMl52Knj5fuIvE/mJyCv+YMCJYOSMernEh5YW0YyUAUNz66u8n/I47GDR6gf
+pPu9ohQO16lbW+PIV96NUfChwgoAX5jf77AKAPYR0CQ5kWke4Z/tA/lLk3JLqYHy
+cx6LyMLGzeBgiB3Fh/PHdN582SrbwXxynBT9iBZvwyV2hN0Id6SlcRFEp7b133gA
+bz1J6Zd3zwaefUaI/8mNgFuzVNYy0zkpW1DzOs9ZxjFdijMQn8vpISzj10Z56uI7
+niBJDoWKXhg9aQIYtoyPy+qgSwYF5d1xwAHRnMV0wplGOqnIz55+uZH5FnNk5T9x
+DY5sN/GC9yPeAdTiFbZQ0xm2GGA9J/utE+H3iudyQjTDApTbvOr5eGJcDYAzbaFM
+7GzD0C5RAxXvBghi51i9zUCs/VflTGXt1aBa0Mm+8Z7/CH+WZyaW/fh0O09fPDOv
+x5VA8VX1Y9jCiCC/gBzxD1eJryuyQe2wXhIw+AMtH+Rrty4ttC/UG874PnS2PmkS
+rUhoSUDKloE83LQNCK5Oxp74l3eancMz2hMoWvaqU7K6fd6cs0EVUG8M8EGRc4LU
+VW9PGHRoY1xvvZodfrIU/UK1iJKx6/Ofb/bpaqn7gL4MMDpRdkmZ/I/+TPQJWhj6
+/OJHCka2VaeiiOnVclTFOJd0P94O0AjVb2nmIMYn0K8mjszI+mBPo4MKJX86fDxu
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16.pem
deleted file mode 100644
index df2bc3c515..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16.pem
+++ /dev/null
@@ -1,124 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=User Notice Qualifier EE Certificate Test16
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIIDZjCCAs+gAwIBAgIBEzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBfMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNDAyBgNVBAMTK1VzZXIgTm90aWNlIFF1
-YWxpZmllciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTYwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAKCz6DLhyX/EGx3xwNiwBuBXrfpuLfLcaPz4q3aq3BiiJS+f2vwk
-WI3BqpDluVEq7FW5zE6ATQc/K7hIiuRCHCD5ErXMnYb70mtz8xeVjU97316FzK/z
-eQYQMIIpb2JJ4JEU/ZyVNX5NW3W8tjAhuvEp+4brMLxyCM+xmA+S751zAgMBAAGj
-ggFUMIIBUDAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAdBgNVHQ4E
-FgQUQFe42RtzGbaxdkQ6QallbyGIuDAwDgYDVR0PAQH/BAQDAgTwMIH9BgNVHSAE
-gfUwgfIweAYKYIZIAWUDAgEwATBqMGgGCCsGAQUFBwICMFwaWnExOiAgVGhpcyBp
-cyB0aGUgdXNlciBub3RpY2UgZnJvbSBxdWFsaWZpZXIgMS4gIFRoaXMgY2VydGlm
-aWNhdGUgaXMgZm9yIHRlc3QgcHVycG9zZXMgb25seTB2BgpghkgBZQMCATACMGgw
-ZgYIKwYBBQUHAgIwWhpYcTI6ICBUaGlzIGlzIHRoZSB1c2VyIG5vdGljZSBmcm9t
-IHF1YWxpZmllciAyLiAgVGhpcyB1c2VyIG5vdGljZSBzaG91bGQgbm90IGJlIGRp
-c3BsYXllZDANBgkqhkiG9w0BAQUFAAOBgQCrY2KIowGX/5zlQBKmdhF8WiCRnHfd
-VuzeXhc6C3G4YPpYBWQrnhxO88VH8QbvJefBpvRKIYsxu/tyihlkw2Vy5eztflUq
-Jkj5YbDicL/7U3VKfjfp3sW6ZBgqKKLQY2eDHtYup9wBzB/qzny9xfuVIlQQ+ihR
-vMKO1iVYGVLxPg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16EE.pem
new file mode 100644
index 0000000000..73a6a65652
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest16EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 56 DB 55 2B B8 5D 42 93 15 32 4E D9 4C 09 91 F5 56 A1 05 EE
+ friendlyName: User Notice Qualifier Test16 EE
+subject=/C=US/O=Test Certificates 2011/CN=User Notice Qualifier EE Certificate Test16
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIEdTCCA12gAwIBAgIBEzANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGQxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTQwMgYDVQQDEytVc2Vy
+IE5vdGljZSBRdWFsaWZpZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDE2MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAulbeEb7O7vcRacycC6/ainA+gXxpoasZ
+XBUoU+G+eo5d5yCnsyZ9FSguMM3v3bqc2THkHxZq3/9c9/MCwBEai70AQwS6Etvz
+GGIGk7MAw5c8gWi8smIHMMPY1Zqc6nQjFr1qxk/Bj/nWUKeqMhCWs6S69Q1IsmKN
+uwLYO7/DjcKwc9jgiUXVTcNCnkbzUIdjBM47jsyXrpMwP47D3dMYTA9bzBjKj/fN
+IFS3gLv4JqTu755LxVBjjjpg7Kt8EMXDSrNci5ZyViGdfitwd+F3MU0Q1Q/fnadi
+QpoASYBVHDx0scpwHSt/imQQz02Rfoo5cQ6SS2RVvXhZ6B4YfMm99wIDAQABo4IB
+VDCCAVAwHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2lEHIUUfWvOskwHQYDVR0OBBYE
+FAIO7iA6v+sW5S3aaqon7HTHzsOAMA4GA1UdDwEB/wQEAwIE8DCB/QYDVR0gBIH1
+MIHyMHgGCmCGSAFlAwIBMAEwajBoBggrBgEFBQcCAjBcGlpxMTogIFRoaXMgaXMg
+dGhlIHVzZXIgbm90aWNlIGZyb20gcXVhbGlmaWVyIDEuICBUaGlzIGNlcnRpZmlj
+YXRlIGlzIGZvciB0ZXN0IHB1cnBvc2VzIG9ubHkwdgYKYIZIAWUDAgEwAjBoMGYG
+CCsGAQUFBwICMFoaWHEyOiAgVGhpcyBpcyB0aGUgdXNlciBub3RpY2UgZnJvbSBx
+dWFsaWZpZXIgMi4gIFRoaXMgdXNlciBub3RpY2Ugc2hvdWxkIG5vdCBiZSBkaXNw
+bGF5ZWQwDQYJKoZIhvcNAQELBQADggEBAEgyglT7PF+xqOPfkWfZD+B87fSODdlO
+5HPCqZySlix3IrkJHL4/acMADY4mY4zP+W8dUawWs/6ud2ECVn2UJLQcpzo9n9yk
+XS96jwdihJG4cgOib7T2PUk0CiGU1kkPBHmUx8oCXqMKF3xSvK80fXZdByxg3o1Z
+2MG0xxqok7SNJ9YhFjMNl5KogfNEiY9tsTzM6zPTVqU0iSUSXCW7PQEPAuBhI+Le
+pWFaEPdjZBN7rRGzK8w8YDCBG5d/O/e91PTMO5NtjmliHkFu8XkGu/WBPHOx9qH+
+IyTErE6J6vUrWZ2ycgmrf8Apd62mBopcR48xY9X3acE7QcdtgEe5/Uk=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 56 DB 55 2B B8 5D 42 93 15 32 4E D9 4C 09 91 F5 56 A1 05 EE
+ friendlyName: User Notice Qualifier Test16 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,52CC6EB1780167AC
+
+DfTgiDoKidNkLpLKZqI1RZv5ox0RsMlMzsbz6x9/7z4wFa11nTLHiUfgSSqT+t1d
+ZUOPtacc1tmR26Ix3BNxguSn/EOGldSaCzUcGRenWm0Negf7i5zPb74q7O4SsQgw
+8PzPAH9uB1wQgGNXXN1MoaZVs/8WU7a12D4NicAcXU5Bw+XR1AqDLz3/fzfGLzM8
+Csm8BXpq1A5JqM7HAfMUHb31+t4Sy026OzHvFVyn+r/sEbJ8pJ1bCbrvVvGorjUg
+Nm9+BcgmB9ani+EepglAS7HOSSZGzi5LSadxfBILVb4dEGkL2skzF6WEm7knZukQ
+Ti4zA8SkwYn/M+ltf06O5ZhL7PMdUA7hAr5YorBu+fbWlGXWyhJxNZcJq/jrkATV
+7pvKw6SfUa9IbIJQyZcbFcuzqPANONGBorpbZyW0u67stUkyTUXct+CEMxSxCRsH
+HAAVFGlK+RILNZ222gdblHappv30BVJstEEey9S+rL9He6tsWUKJ6So6iYeyYONR
+wbQkoBfOwxRm2Ga/7GpUo97dDix6ooFpxVuYatOn0PwJo/N5v/g1Q+dmaFY/BizB
+Couc1V6Dq8GiUwldUhcGEcuzVsTOlYmXqxY5WWFxexsydzyz53WIExsUz7wk+nY/
+jdBhNX3pbZxxxYjJ5HBLK/3lfEWRaK6MXpok+dagIBZJt6y9GnyfIhgzHA75VRi2
+TMI6O5nVyOHLOj32T4nJwe8wdBSW2RmpsZZR8BaUIbHFH75X092XpeQSnnr0QtsJ
+k++uGSSi2LteDB8qwBbAmjgbvWB9DaYD3jRrIEVMt7cDLlk34LEc1q9LX7Uvh8ip
+dNsmzZ7DtrVfToUAFn5HcIj6C2JLGbQ1NFMx0p/ElSfHYX1fXw/KCNzDGhPbBKr2
+/HM5EUeCR0mB9quHbUXiazZpaNys6rIDgNGI/ZY/XWCX0K3g3rvuzAMYbLBSaOIh
+kR0xqzUPOkoYWAeKI7flSJykq8CDh8ULSX4DhiKTZrHpOqFYNVoss5FbgyksmFxz
+1TpgQwzP0lvtu3Iz3xRNvcDAMJeczrRG47a7DcuPq3tMqV1x0XhS6KTyjNtoLCri
+w0m8delonjCInjKees3cIjOb/uiBxjuIzl+R+eFfeion1c0wtyyzu3+/JVV35JTv
+u7abnsrdQr474QcdDau1ghFdJGQK+dMC73a/CBC2Hxj/odTbMZ7pNkx8Td+bSe54
+VBCW2vGug5lDZG1r0y6gG+1kVj9hMgbGBgRUaNPVUjvh7VDJ51JAM3U3HBTtd0Y3
+wtgYcbV6pjleZ/Ym4YNHGWEPZp9aEjUMcsq6rKXrESI3bffvx51v0XBLua2c7lqA
+ApUNpRR2tm80XJQfoT2YVunD3Ccn/AveY6wConBcZyqv1N1YxtP7122/3CcduQic
+LPdEJHbkuRE3Kb8UQAgDahK82juPno5L5ZqhmJXIXC83Jtq+5AE/2d2ZsRS12JWN
+Cv8GUsAJbvwi9eYzD2PGEsgzL4Kx5uc+fOEX/hb+7c4hqK36RzPeMsPnJy6qg8iR
+jykMhKeQTeybGkNvKzrDfaHTAJdb0L7CmWasLY0OxtQd+HP/yYjVaw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17.pem
deleted file mode 100644
index de751b01b9..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17.pem
+++ /dev/null
@@ -1,121 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=User Notice Qualifier EE Certificate Test17
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIIC4zCCAkygAwIBAgIBFDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBfMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNDAyBgNVBAMTK1VzZXIgTm90aWNlIFF1
-YWxpZmllciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTcwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBALG5QbkrUYEf/BsUOmiq+gmSjIMtxbiVJ8G4i1XsVOAFNuJhfPyL
-nhsnhig2d+tp2aJHFnDfMbvmjdmCtwPwqrcuxVO5PhjkLyfFo9Pt7zNCF5xtCkLK
-P7LCEtvtBt5jXh7REsOPlQzQkxng4SxG6VdndW1ZiNAJIDAsONONmetRAgMBAAGj
-gdIwgc8wHwYDVR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oVlMcwHQYDVR0OBBYE
-FM7tf43yWQflUjDL35BzbeLwWXDAMA4GA1UdDwEB/wQEAwIE8DB9BgNVHSAEdjB0
-MHIGBFUdIAAwajBoBggrBgEFBQcCAjBcGlpxMzogIFRoaXMgaXMgdGhlIHVzZXIg
-bm90aWNlIGZyb20gcXVhbGlmaWVyIDMuICBUaGlzIGNlcnRpZmljYXRlIGlzIGZv
-ciB0ZXN0IHB1cnBvc2VzIG9ubHkwDQYJKoZIhvcNAQEFBQADgYEAPium8qIa/cDO
-l7vNWoULaBGP7Z9XxxEyexzl2Y83xGab/xw+KGtbV+6+GiGhCw4qpn7XLidQQ6Xn
-t7D2vKo+KoLg3BAdbt/azb3wf5tYakf//0bv4xQZ7ANzWxxH0gP5VdHaRIcfKXXR
-3kHnu/lecCM8V+F9V8pEU8K3zREtp/8=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17EE.pem
new file mode 100644
index 0000000000..922eb98ee6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest17EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 61 F7 C9 40 D2 DD ED DC 92 F4 8B CE 0C 2E D8 41 4E D3 D8 12
+ friendlyName: User Notice Qualifier Test17 EE
+subject=/C=US/O=Test Certificates 2011/CN=User Notice Qualifier EE Certificate Test17
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIID8jCCAtqgAwIBAgIBFDANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGQxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTQwMgYDVQQDEytVc2Vy
+IE5vdGljZSBRdWFsaWZpZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDE3MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtgx/GESPgx+f2iTkGzayiIzcQFdPHoke
+X5w5e985q9OYBAGQR8L3z1N5pzoNK7KdyuLfTH/5ymU9F/TAfMjzVejFuojT0kkM
+YKn0WhTpc7lL43DesIDLfpmVxNseL/AfP52wP5KWfzLPeS12xOwVkkYYk+rXBCsy
+4Wajt7CR/OgYVVZqr+l4eoMZXC8QkbRzpqYMRsPDLDDjWM8TrdJWOcm3fS33pgTA
+IYaihsgfIPRAMV6xbTi970Z5nqjWQuQ1KzdvUe9FUfGNeUDybmOJSIVzQjbNpTQs
+rWQYzW9BcSlCjiGCDi01O8tur062uk7V6vtxQU+LDl2vW+etQZx07QIDAQABo4HS
+MIHPMB8GA1UdIwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJMB0GA1UdDgQWBBT+
+LIExXNIznYNgktX0s3YpDGcmLTAOBgNVHQ8BAf8EBAMCBPAwfQYDVR0gBHYwdDBy
+BgRVHSAAMGowaAYIKwYBBQUHAgIwXBpacTM6ICBUaGlzIGlzIHRoZSB1c2VyIG5v
+dGljZSBmcm9tIHF1YWxpZmllciAzLiAgVGhpcyBjZXJ0aWZpY2F0ZSBpcyBmb3Ig
+dGVzdCBwdXJwb3NlcyBvbmx5MA0GCSqGSIb3DQEBCwUAA4IBAQBfBRO7j1sk6/+/
+03HPnqa/E694vMdtGy/K/d8K3mdRuPTcxNcT2gW9VnVyQ8rKwrtZn0oWjehifnvz
+5DJCIrE8Qf03kY1rbCkcDsQ981Lbg4t11pzBqGARFVrAfzzeiKY1Q9EA7QPbpYvB
+RANQsSXkCSjE3BPvHdz/1ZZeP+kvzNSb+vrXOs0MXA5eAmz6Or9bOak+XOUDZS8l
+CrmEI6GRG8Coe8zy4YAbPy7uO7Zdvd+uQSEGDlwCDCtqQP0H2uWmNCstdAZHoJbi
+RevpMviFe7MFOtYgpJhEwgmK3wNLDcaPgznv5qCuH378n6gXL5Kv0ehBd9LcWPv4
+jZua3QQF
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 61 F7 C9 40 D2 DD ED DC 92 F4 8B CE 0C 2E D8 41 4E D3 D8 12
+ friendlyName: User Notice Qualifier Test17 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0A67EF457602F9DB
+
+YagNBodo9QwnNc4gfwb3EiAHA7kg0zFRJCM2wV4Xy4HGMW4BknPDqBaFCui/iSm0
+4W7Y+LXHRLIzwUWy7xZdu1LfEIG3AHnz1Ben7VBNDLSJtbslPR6N0XC1T2Jh/InA
+WAvmGCmFny4DUGWcILjYJ5lUEistzxoBOF3v1+/5FEN9WpgBRmdvwLLl3cjkxZIk
+fTUYFZdE9vvxdAKs+ErnlRC9xM5xoNw9IN+swqsaGLq+05iUuQFIWSGptmzKbIy9
+RdhShNpCkgfB1hoBsv7mm0ivnjmLP3hx3QoVkP6KaYHtk0R5O9HnV6sgtUmm2evV
+qzPUvTFHu1+Awaf2m/ZAtOxQnlG0jm+SARSywwllRpeZaCHTWlYMMytIgN1qAcrH
+N9XesNJLohjjcF8jJT9Y1TSMR/yBB5CaM24nGdZdod00+Jhmb3M1KRJ52+bopMqx
+CzMu8+yiIk9Jc0gIekOdVhZUaD1mgEovibqlcWIahBfGC2LCU8AC1oczEEB0+dD1
+G3IYIiQtyShDvwhbqSdArmSQ6W4XJLxTVuHut1e0bzbtkRy6IF9eHBv0bfOYoX4r
+OMQH1l5B+Q8XYbDUi1ZXUYqKHEdrowsB3GpyKpideq2LtYx3hJ2+U2DAfaY2BGGg
+2bInIS39NdPqI4d1rCgC85iRg6N2bAqgW0Ack4yjc8orDj0KXZ5ZAjaomWPTRvdp
+Qt34gumzSeoE9shupaYfY2Y9Qwgh2os56ucjkhqanjSAGtkym8jftNsCjouAXVSx
+5kM7xAADzLtti1IMXuh/QZKtkzMjGRg6QxD+kqDQNArEZAr3Lpx4owOqWFjcfuBG
+p49iKbe5kTWITCAjytUOLXjkCsUjEYg+qfBJBAF6kqNZddL5trp3Rp5PF2IGU58n
+YIjE6JUOlWbsM/n0NML8q0s6x2HFn70bq+XHkSZq9UxQxW1Jy/VX2hqoEBXenZgm
+HDXM/gu928PSw3enWdRfpP/V0vIYnrSsO82rFhQd+sob62+ZXUSsQ1IPYThQCKXP
+200mOAw3vgIRYElLB8QxdQX9zZTaUvck+onF/vsUhUjnpfwNHEZsBFTnFRXaxT1g
+pGw4aItY18x7z+m2uRrFdnWZx4JIcYVhO+bWa7GT5eFEwycgmHX6e0UNIB/UG1zq
+biKcKw5g79ONR3iouXvQBRR+GIdGuYQ932TX1leYu335rER+lZuuwKJM/ZFI2kjY
+bpCIWbS6cIPiowH+yp/VqYX2q5lG7vIRVYa4P3t0kE+ylxEjKbzI1EJLJuwdiMuy
+2GEv1RsubsD0uEmJ4nyOw70AGTrLSIyyZyp6if3ivIntUy0V+rSozgWsfe3P2hit
+l3ZR/qzemIiQLLRs8Hm688CC9C4n+MAv6C68/cy5GZjNAVVTJpjh6BoP/GjC227s
+RcPwKbH4qc4xgCZG5gfIC9hRNj+ZInYjzKOUZNjBqWqlAdGpNrb8DlJ+FVJv1P4A
+Crvp5JaVOelF5Vm5zhKae2/CQSgojrS7HAIAf+ERbfZu4v8EnGxNjQJTJ3G9nnbG
+Z6R5twYPiCFR8ec8qbVO4X4xRObYcX9nL7ORNWaS/dguJLShLlaHvw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18.pem
deleted file mode 100644
index 177e92ffad..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18.pem
+++ /dev/null
@@ -1,115 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Policies P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBJTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPUG9saWNpZXMg
-UDEyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5unCMuN8PuVFWbqxO
-/wnIQsciPiEo1GoKWjM6+kb9l3h6wWyWYwmst2c158qcJLY9PxaUMhqQd/SY0Tt9
-WlHXVcE8rMoWSGmFxfK33UpeCtqwz9ugPSWwZkqx2lI/0ozQXgjYb0J9/EoKw1O0
-CxxrdQdPQkyLD4Uxe87/MlpzsQIDAQABo4GZMIGWMB8GA1UdIwQYMBaAFPts1C2B
-nsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQA42XpgdSGuccd5/MzOQZeTBGl+TAO
-BgNVHQ8BAf8EBAMCAQYwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFl
-AwIBMAIwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GCSqGSIb3DQEB
-BQUAA4GBABX9GMyAC90FH8BvpnNh6SDn2MIT7iINc4/9u64d1dxEhqogqcR58khK
-btHyx8YrgbCcqUNS4Xs7ckW5k2VNAd9dG0Chc0uk6rwkv+sD1/zJi8LIGd/3cFjk
-biIVYqPxb7WpKqo97V+43tMFsTqJNBSh+6W14vlP55+Ep5IlxcOm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=User Notice Qualifier EE Certificate Test18
-issuer=/C=US/O=Test Certificates/CN=Policies P12 CA
------BEGIN CERTIFICATE-----
-MIIDxTCCAy6gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD1BvbGljaWVzIFAx
-MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF8xCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE0MDIGA1UEAxMrVXNlciBO
-b3RpY2UgUXVhbGlmaWVyIEVFIENlcnRpZmljYXRlIFRlc3QxODCBnzANBgkqhkiG
-9w0BAQEFAAOBjQAwgYkCgYEAxkN3itGxxUqfb6j8AgRX2jxaI/oIBzr2RuZsAfon
-x/XVoUmmiSxWDooZhr/PlfubyixNG5VJX2K/ukJ6gfIGMXCAqunKm8/9bXgzZB3T
-i2oIgAy6WnRwKE0cgbedH6fY003jwsQNDt/HilRB+atbEJ/engTxLOIpwBcsN1qj
-rg0CAwEAAaOCAaswggGnMB8GA1UdIwQYMBaAFADjZemB1Ia5xx3n8zM5Bl5MEaX5
-MB0GA1UdDgQWBBT8A5L4pL/8ywpme6U8lushm7qgwzAOBgNVHQ8BAf8EBAMCBPAw
-ggFTBgNVHSAEggFKMIIBRjCBnQYKYIZIAWUDAgEwATCBjjCBiwYIKwYBBQUHAgIw
-fxp9cTQ6ICBUaGlzIGlzIHRoZSB1c2VyIG5vdGljZSBmcm9tIHF1YWxpZmllciA0
-IGFzc29jaWF0ZWQgd2l0aCBOSVNULXRlc3QtcG9saWN5LTEuICBUaGlzIGNlcnRp
-ZmljYXRlIGlzIGZvciB0ZXN0IHB1cnBvc2VzIG9ubHkwgaMGBFUdIAAwgZowgZcG
-CCsGAQUFBwICMIGKGoGHcTU6ICBUaGlzIGlzIHRoZSB1c2VyIG5vdGljZSBmcm9t
-IHF1YWxpZmllciA1IGFzc29jaWF0ZWQgd2l0aCBhbnlQb2xpY3kuICBUaGlzIHVz
-ZXIgbm90aWNlIHNob3VsZCBiZSBhc3NvY2lhdGVkIHdpdGggTklTVC10ZXN0LXBv
-bGljeS0yMA0GCSqGSIb3DQEBBQUAA4GBAGFe+mIs7y5351adHxETDUI8/Oki9cBU
-9ShrYKlpGJn8K0ST8XCe3FhVI/EMMxPJ7a7cYnl/7VQjyrFH9ulMmB3zoFiwbijM
-hfv2DyMPMTMB1pN57MpoBl7NEV0ze1I/u0CKcemqthj2jynTljGeLyJOCAd2Oat/
-J0ohqgkjwhfW
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Policies P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:00:E3:65:E9:81:D4:86:B9:C7:1D:E7:F3:33:39:06:5E:4C:11:A5:F9
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a2:21:e6:6b:0b:99:66:79:2d:86:a7:9b:cd:37:9b:4d:73:1f:
- df:91:63:c4:de:55:15:53:b0:32:ac:c8:3c:bd:96:aa:ae:c9:
- 4f:b2:7c:9d:40:d7:f4:5d:99:8e:fa:2b:44:2d:75:ef:01:38:
- 86:c8:59:ae:e4:62:e4:83:b4:73:03:34:d1:7f:52:bc:3d:bb:
- 77:7e:7c:c9:41:09:4c:08:4f:a9:7f:d9:d9:0f:bc:46:9d:05:
- 70:2f:66:0b:d4:0d:80:ec:11:83:4e:1b:90:95:ad:86:02:77:
- e8:19:aa:a6:48:29:a3:9f:36:c3:ec:9a:f5:a4:9a:0b:f5:11:
- 1d:72
------BEGIN X509 CRL-----
-MIIBPDCBpgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD1BvbGljaWVzIFAxMiBDQRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUAONl
-6YHUhrnHHefzMzkGXkwRpfkwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-oiHmawuZZnkthqebzTebTXMf35FjxN5VFVOwMqzIPL2Wqq7JT7J8nUDX9F2Zjvor
-RC117wE4hshZruRi5IO0cwM00X9SvD27d358yUEJTAhPqX/Z2Q+8Rp0FcC9mC9QN
-gOwRg04bkJWthgJ36Bmqpkgpo582w+ya9aSaC/URHXI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18EE.pem
new file mode 100644
index 0000000000..830f8256e8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest18EE.pem
@@ -0,0 +1,67 @@
+Bag Attributes
+ localKeyID: 0A 9B 11 2B C6 B2 2D D5 47 CD 92 4C F1 22 3B 00 9F 2B 67 E2
+ friendlyName: User Notice Qualifier Test18 EE
+subject=/C=US/O=Test Certificates 2011/CN=User Notice Qualifier EE Certificate Test18
+issuer=/C=US/O=Test Certificates 2011/CN=Policies P12 CA
+-----BEGIN CERTIFICATE-----
+MIIE1DCCA7ygAwIBAgIBAzANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPUG9saWNp
+ZXMgUDEyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowZDELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExNDAyBgNV
+BAMTK1VzZXIgTm90aWNlIFF1YWxpZmllciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTgw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC88AhCshO70EgmfJ0LoJAP
+aEyUfJHUOk0+uSHgQxC+TXR4NZUZYKNeGwc97Cn80E3uoygIUKpOIoZLOmA4Xw5E
+ZA9fZNmmT7cIzAjDXUJv6Oy03LcQ+2KNFRUIQ5d5y2e/InkkZjJNVqVxcpt8DdJg
+VknMuYUk5kqD/uf+L8t4C57iEj0KlBQMgsXGa4vNVpc4dI9irDlTQVCPZofSchFk
+5Ek41YVy+wDxDHW59/Opqr7VfXJOmFN0BxZ6NTW3VmXS4wWMV7ZTdi/YMVJVb/b5
+0uCCk/JXtFGHlVz454T++Decj9xf6bFyCzNGJXzf0WMtSyuXVqT1jWsCo/hGzo8L
+AgMBAAGjggGrMIIBpzAfBgNVHSMEGDAWgBTYXzXimsE3KibOg8xzDnAVKjriMTAd
+BgNVHQ4EFgQU4DsI8hwak6jmjAEqCXZrCm8FaHEwDgYDVR0PAQH/BAQDAgTwMIIB
+UwYDVR0gBIIBSjCCAUYwgZ0GCmCGSAFlAwIBMAEwgY4wgYsGCCsGAQUFBwICMH8a
+fXE0OiAgVGhpcyBpcyB0aGUgdXNlciBub3RpY2UgZnJvbSBxdWFsaWZpZXIgNCBh
+c3NvY2lhdGVkIHdpdGggTklTVC10ZXN0LXBvbGljeS0xLiAgVGhpcyBjZXJ0aWZp
+Y2F0ZSBpcyBmb3IgdGVzdCBwdXJwb3NlcyBvbmx5MIGjBgRVHSAAMIGaMIGXBggr
+BgEFBQcCAjCBihqBh3E1OiAgVGhpcyBpcyB0aGUgdXNlciBub3RpY2UgZnJvbSBx
+dWFsaWZpZXIgNSBhc3NvY2lhdGVkIHdpdGggYW55UG9saWN5LiAgVGhpcyB1c2Vy
+IG5vdGljZSBzaG91bGQgYmUgYXNzb2NpYXRlZCB3aXRoIE5JU1QtdGVzdC1wb2xp
+Y3ktMjANBgkqhkiG9w0BAQsFAAOCAQEAfxyDNghdSbzgxj/mObFvvEknTx5cjRIo
+L+CbP8ccGGrcfwJcbNEcZwlkzOSomEjsoROw4XPq6deZDC+x9McnYKYHwt78coSv
+urgue6YqvDga1785BozPcJqN9iTK8babcOeWno7ZPRbUEqNFfpesSfUtRjBoFh4G
++YrgneWORnvSZFS3Cz4X0h3yei0ZMNdPK/Zkt35QymLrPxr9rAIzOewaXOH32+x7
+bPgue6FhSz4na9iJQozynEsP1HSKRQdvm2E12ZYrE59hG7p2bqV/pUQSR8hZNnJZ
+IUC2I3sFck92TKZsdnYQHv3NuCl758S7O3cXnF436gqP31KGAzgcVA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0A 9B 11 2B C6 B2 2D D5 47 CD 92 4C F1 22 3B 00 9F 2B 67 E2
+ friendlyName: User Notice Qualifier Test18 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B169BC8A27090A09
+
+znObGOy88Wfiu93UwhsYd3AH+KGrQzgcBvYNPNOzfdEN9SppYTeU6xuQCAJBe1Y+
+7428CPV/WM0Uf9X/ryEypZ20LA9dabDi19DZzGX4CHqIJBO4EHLepdA/yLkIHXo1
+1n80VaCTiFjSUxorJiMWBLVN+vNhZkuj2bZTpigTHlsrxrvbsGpHJwPuXNJwFXGg
+YKUZ8zgSAUwduMTv9RP2q85zGz0G7jbINmxBP+tImdi1m/I6+du3N3D8OD9gm2ZM
+Wc7GuRYpIweH+grva5lTHqJ6ndwxWvr6L5PoqdyU2MPBMKmtdiEVZKx/jysglBmO
+hSXm4ZQPzQ9gzxzxJImAYAv69wR17Lyd+wvBUdiuq0JB1GNJVo11HxKDzrq5shmE
+BAAFf+cgTU4pK1jlyKPWQ5uphKDjHXZPGarIXoN+zpZl2UAHWH6EUis+Zex/boAA
+8/orX9GYbMzvL7rGv1qWDeh95iBEY9JmoHmBiIbr3f+pmA/Wmk1x647/ylSMAjGM
+GCy4ynca0+o6TKvKrhXe3iZXB19ngSTJLW4+1m7J2kliyl3D9Emqv66vlOyBgBya
+ZXtfM0qQeROjdqrvjLMcnQqScgEQc32D1yWgEAown8z1xstqrR8mvLAK0VNowKZB
++9VhTXfzdamNC+F82YuinJzV2rDM47gZYHdWMEo3v5wahuQMQe7gRCkiDhYA0Y6e
+NH2S0ZdArCCeSav2pBaECBg06ML6JJ9U1z6gZmFYsX1tCirzxelPHefHhMegYRpe
+36JbnYsICtfc0a3fDdfJfI8V1jNHpxM70Je2mIlpT04i+b7pEJZWM8CsbQ1Iqkro
+k05o4WqehI6hGako97XdlZwXLnGDHNqY8fD+LPtK2EznHzPwaV9gIxdFhzSrp3cH
+wdXfGb7wyZTfcg9hr57zN08GrkEpj7b4sOife/bq9y4Vpqpow9TOKaEOv33p54xx
+xfZDK84k+F0cInPwpoGGGUc3JYqnqCXsIsi4UWgG+cyGwFlyv0TOhFQJzFu+haSh
+d/xhhAn9uDbL2Y1QoX+ep43BUi6nGbPYytMxPpFvK/zeZnMVuDYFH+uaGa2yhlj+
+LsWLYFi8FLBElHaNxFKBV9KespbFj0c/rHlYb4W1Ai3yya9NdaEZC3dpNunVNBrD
+e1weVMs5rb8Evff50PjFIpIK4Uv1h9EtzA//APUtT99AKexVF+bDrIIUKjZd3ubF
+8mnOrxI4m9Sl+o6HQI94igfG1f2Y/TBhSrnIWNQ/IgLHm9dCT/QRNv2rkAQSrDbN
+JkJx7Rz22VYZMHqnwhoq7U6MdofOHUlPsaLm3yc7Kmq0Xpd7ntyjDJheo67QLeh9
+YkPwoFar/LQ8934StLWj5/ZseauC9xdNdjfALJiNm5CTZ5n9x65oB4SsT+UkQczR
+pQEiVTJITBCUBrcoBQEwyrx80LdmjO0lyYtm/kLo3+82FHNkjWKGGBK60npBcjmT
+70qB7qmiWITmxZqSUwdp27hF5g+izXOGZwB90dopk588owoz13T4FjxRbSeWKAvE
+JA9rATNY32V9uY8wsAxxzKF7AfKKN3B4akAgSvYlnFsOlW0kU3j2rw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19.pem
deleted file mode 100644
index cdfe8367ae..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19.pem
+++ /dev/null
@@ -1,64 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=User Notice Qualifier EE Certificate Test19
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIID3DCCA0WgAwIBAgIBKTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE0MDIGA1UEAxMrVXNlciBOb3Rp
-Y2UgUXVhbGlmaWVyIEVFIENlcnRpZmljYXRlIFRlc3QxOTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAmkrJdJV6KkYpFv+9djQ5ybyWHKyjUB8Km9OL5bgATpab
-SN8gXK6Jd/EmkSQLM58dolce8oaizez9cBhO/myxYLK4WQGi/eR1zCWhOYz75f/o
-+MUwF1WFbuHvk7JcW6/0e7tI3sxdgtz2k8JDvyDZ6CH3Hb678ZfrlMMuCODEw1sC
-AwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0G
-A1UdDgQWBBR2o4bo1PW8nDTv5jAQJQYPDPfgtTAOBgNVHQ8BAf8EBAMCBPAwggFt
-BgNVHSAEggFkMIIBYDCCAVwGCmCGSAFlAwIBMAEwggFMMIIBSAYIKwYBBQUHAgIw
-ggE6GoIBNnE2OiAgU2VjdGlvbiA0LjIuMS41IG9mIFJGQyAzMjgwIHN0YXRlcyB0
-aGUgbWF4aW11bSBzaXplIG9mIGV4cGxpY2l0VGV4dCBpcyAyMDAgY2hhcmFjdGVy
-cywgYnV0IHdhcm5zIHRoYXQgc29tZSBub24tY29uZm9ybWluZyBDQXMgZXhjZWVk
-IHRoaXMgbGltaXQuICBUaHVzIFJGQyAzMjgwIHN0YXRlcyB0aGF0IGNlcnRpZmlj
-YXRlIHVzZXJzIFNIT1VMRCBncmFjZWZ1bGx5IGhhbmRsZSBleHBsaWNpdFRleHQg
-d2l0aCBtb3JlIHRoYW4gMjAwIGNoYXJhY3RlcnMuICBUaGlzIGV4cGxpY2l0VGV4
-dCBpcyBvdmVyIDIwMCBjaGFyYWN0ZXJzIGxvbmcwDQYJKoZIhvcNAQEFBQADgYEA
-J8J9A+SBJzSCvCFxcnWEMXbjUkKjp4BAEhkrRH5llfYFIwM5+QAqZTFKTvP5mhTj
-eeMD/sF7Ej90V/1wRzadHnmhXe3WRwe09BUVM4Aa4b+/th9PihRNvI7x10+mAuMD
-39/vWkwe5e0DTYQwe0t+8fHohmDgmJ6JkOiccJl0auE=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19EE.pem
new file mode 100644
index 0000000000..b501dcb4b8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/UserNoticeQualifierTest19EE.pem
@@ -0,0 +1,68 @@
+Bag Attributes
+ localKeyID: 39 AE 3C 3A 63 6D BC 12 05 93 3D 33 81 F4 02 28 5A 6E CE A9
+ friendlyName: User Notice Qualifier Test19 EE
+subject=/C=US/O=Test Certificates 2011/CN=User Notice Qualifier EE Certificate Test19
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIE6zCCA9OgAwIBAgIBKTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowZDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExNDAyBgNVBAMT
+K1VzZXIgTm90aWNlIFF1YWxpZmllciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTkwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD3E/MPmQrWuB1FwiUdy39Yth3/
+GCiDQBK1HGlJRkREfH5qLLXoXoXkdTfKoKMz7jetlTwfqh61oQcAGrUxJ+1uXFFo
+Z7rx39ZJy5WHoqh+/0KVFwVHzZlDjx6hRdDAV2wSH3CQA66JeGm6C/Q6seIPhXcs
+5NiM/7x1f+gaA6OKQbFyPhErhvwt6T3MiJgdnATXneT285aE9ERxGxq6pMqLTwCH
+7vnlDNq+86cr7qXwRxqgnrSyKZnd02g2aVRbQQbDe8GYJvn7FeJUruq33nGjYoUu
+cq8taqkWaVEvlAc6rNHjXP9bFUC37Dt/q05ODc7g0vHQvkgVKkcLvIor8GFJAgMB
+AAGjggHFMIIBwTAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNV
+HQ4EFgQUDU0KkzuR4M/gJ9ceN1sBfgKd6ZswDgYDVR0PAQH/BAQDAgTwMIIBbQYD
+VR0gBIIBZDCCAWAwggFcBgpghkgBZQMCATABMIIBTDCCAUgGCCsGAQUFBwICMIIB
+OhqCATZxNjogIFNlY3Rpb24gNC4yLjEuNSBvZiBSRkMgMzI4MCBzdGF0ZXMgdGhl
+IG1heGltdW0gc2l6ZSBvZiBleHBsaWNpdFRleHQgaXMgMjAwIGNoYXJhY3RlcnMs
+IGJ1dCB3YXJucyB0aGF0IHNvbWUgbm9uLWNvbmZvcm1pbmcgQ0FzIGV4Y2VlZCB0
+aGlzIGxpbWl0LiAgVGh1cyBSRkMgMzI4MCBzdGF0ZXMgdGhhdCBjZXJ0aWZpY2F0
+ZSB1c2VycyBTSE9VTEQgZ3JhY2VmdWxseSBoYW5kbGUgZXhwbGljaXRUZXh0IHdp
+dGggbW9yZSB0aGFuIDIwMCBjaGFyYWN0ZXJzLiAgVGhpcyBleHBsaWNpdFRleHQg
+aXMgb3ZlciAyMDAgY2hhcmFjdGVycyBsb25nMA0GCSqGSIb3DQEBCwUAA4IBAQBr
+LA2+uQdk+39kZyVEG4nvYUgMB+UvSTIYiXq7j451qekOwMNV735tLSqtWCzrSGVY
+rZ1tGVgnTBTf5LqcDa+lPVLEGeV1hUx2DnchGWPz8WZLtJXK6jVkG4wZlTx/xRR5
+miliPtgwpdkYsUf9H9MVUmMpawPvf5s3ZNubE4dQxjwN5vN5xemuDrbcOyGYUkDs
++xLxGrkGvdikgVOUIRXP4u0Erh9uTXXwu/ZQK6ygsAYTSO6XmKIzTJUEjeBxzpaP
+C/nEmljPBlHb680hA2nneeW/2HN+hmPpm0S9uDvwcIMNQc0c3q18lDNrhALaJQ1Q
+8NBTUeL4fQnsCosYSygC
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 39 AE 3C 3A 63 6D BC 12 05 93 3D 33 81 F4 02 28 5A 6E CE A9
+ friendlyName: User Notice Qualifier Test19 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,16DBFEB38621F5C9
+
+bVgYG5xc+ER90RYRsDzgsa6txA1tgWk9xDWRusQk+tXyX+N/YyM74LR8Ixi7QaOa
+6JDH0JT8Zk1/ce3DBF0nVyKO30DcZ4pR1xbMPDCGDzS8DRD6JvaT2Eqf/CcpWIU7
+auO5iDT9UG31l9BgzXY81dZIxoUok+keIa3iYaNIwQu6TlZHbig4tlrAg9mfOUSK
+ETWopUIl+uJ0XLc2IVU+AlwJstr8csTkJWsvCKbTo0wEDgogTujYBTo6jwb9giNv
+VziqTQVrzqKajetKvC6wgGsw8tlhYsC5m+O5mik6/dh5R9B/gyNYJhE4DUswY1Xz
+153YejisupKdLkXGGRXIgBlRQs3EhKWmjw+kZqZWcWEFmSl6tpO2IFXO0cCZO+Z6
+y82Vy9HKFewUvhPN47JW3Q4Bskk9AWKaY+A08lJgxSpp2DD6Uw1x734ln8MJHSeC
+0KoOpPjWXxPCtixmqujaYyjfC9IkG0WByXdLONkonnsnp7/L9kyNEOJKqQFms2h0
+St5CLRQfgJ3vQGFQbLbg6JhX6pTSWu5wTMMdyB27lW/n8vZrb8NZTDSQjSWGOWnL
+91dTxzF02aGy5qh03FfX0FMgR692Ne09COm2uE3kcDeC61qeSxgGvGtNWfAMmnt8
+MA+ysbtJr36RfWay0IVYRQ2y/obuFU3dDxEW2GgGztqaN4U1BKfB5E8cbfQXtZy9
+fhTKbP4swQwiy3tTZnUoy8mN5R1KXEvZGB85o4IBBn5oR9HLbLSs8XEeCUES0ea1
+Akb8mfyH3puOVKNY1Hq2CNFdLtdLQvtLuT22q//fbcc/h11TJ3FRBywchUf6eh/A
+hYaHbALcxDCCjiWD6wjfaS/7iwQckIplhOYI29yZoDAPuz5V/4Y2bgjAk2T5d7KL
+ldl4SDSuD/7Mbrt7ZnDECQtyy540fGQnTUZIz2xkvXzKOcs/xj3Gadfl7zaCmrp2
+hv6S2/Mh0rUFmJD3wWM9Karbe3otQvUFwaLQ0NU7IoSa2pOxiGb60lNO1TQo5IBB
+ArUfLXiNmNEhn3I0hO3gJ497KjlcERC1HYfRhCDT+x7GMu9QoH982c3Nt64beGZ2
+53tiiQGZ4Df7/RNKvVvEmzLXTjhajoOLuEcqUD5sH1bWdHBz6pCruA+B8p9+izc0
+fzn1wJNNWCm0hEQl+XCloQVLk9UEvIJFB1hGIjffrAln2BNWVYK/TjKaogns66OV
+QeRf4Hff/ir6cEVukN3Eey1fzQ3Zob+pfUuabnuCMeT+v7bjGpiPJSjGpWpbVwOL
+NOozlqKsIM2285BJ9CBnva63lOEpTmaiE1QU8gFbjbGfXIZyh1tZ18jVep1RD0zE
+aJT0l3Vj6bj/0a3zpeEXV78tlcykbFm8DoyBvXWbF+rpFIwxEAiDpYeflGYlxYl4
+iRNrhz/fEnUe1/B2P0+knQzNi6rBPbo2OOMA6+zj2hN0wB+c3zFpyAbc5xVRiD7k
+PZEOQ3WDHzowaS62Dsgj3hC/wvQbmZwFRL6VXIvKl1yEgdjFu/Q7Fh4w2ojgsZrF
+sZuTwYIUNh6aLCn4yIOQmet6tINdQk97DpmifjLHIz1Ji18aoTa3SckbgvZl4UUP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6.pem
deleted file mode 100644
index a97ce07ad0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6.pem
+++ /dev/null
@@ -1,175 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBFTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEtMCsGA1UEAxMkQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCfjlwgIWm+Taynv+38GP1Yf2hDPMT5pcsPYlRaeFeg7Tsr/GhTZQKB
-qfO7h8J6JjoKD1m1BTcrdiHbRBnn183kxyhljulJLu87gOUt6LlTGTBFeaUhNNxv
-wpzF5uQ7xQcChTE7GF4kxt/oyehJFi9TGtnjdjlSi3LXG/xfQn81GwIDAQABo3ww
-ejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUScn8
-twM8Z20KAJOp5NalHpIftREwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABV8
-zJCN9czUhadFLy10H1usL1xGEcB8SRR3Row0a+Zmj8T9Se71hTgW7LfXQj3bCDJV
-3AyAd+WA4N0y0+eSRWRGNAcMrOeqNp1/Ki6iGNYceZ41Goudsc34StO7symFfatg
-hTr8/7eU6NXu2o9cDREBOJujBK/Uy52E4rx/Faxk
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Basic Self-Issued CRL Signing Key EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
------BEGIN CERTIFICATE-----
-MIICqTCCAhKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYt
-SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0
-MTkxNDU3MjBaMHAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmlj
-YXRlczFFMEMGA1UEAxM8VmFsaWQgQmFzaWMgU2VsZi1Jc3N1ZWQgQ1JMIFNpZ25p
-bmcgS2V5IEVFIENlcnRpZmljYXRlIFRlc3Q2MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQC99k/Db5BB/DrP9cxgHHm842L/I4al7GOXLq3eb2h8ego1QdJ9IsNb
-ExIULQIAAGVlTriZ118rlLqlVxj05ehWT5HaDh0ygcNDziiUc4NoLYqE7Vh+wK6V
-z29q5vKajywEjZ0mAsvkfQvi1aBL9DB28K87sCS7xIEAf3zu7znQGwIDAQABo2sw
-aTAfBgNVHSMEGDAWgBRJyfy3AzxnbQoAk6nk1qUekh+1ETAdBgNVHQ4EFgQUNe4s
-lmPDT3wyx9zkVIWEuwRUL10wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQAtn7y8N9W/74qmny6jUyLJcq4P
-ni0IjpLLS1hl4RYbKPyeekw3t2Lbuk7jdg9LP2GTY68plnzvHyqcKa0IL+gWvk7j
-6g1SHNMi2utPONRFStefcOubKxjT4c/HZHcPjYVBrmnssH4wzOi8bd8MQ8ZfdQLO
-l3ADkB1F2GjjIofr1A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
------BEGIN CERTIFICATE-----
-MIIDGTCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYt
-SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0
-MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmlj
-YXRlczEtMCsGA1UEAxMkQmFzaWMgU2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5
-IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXGyrLR0BviK/81C9C/igI
-9zh+808dGICz2wS1Oh2CWCeYia4J/65Y7XBDRBW1TJbQLdrxt2289Lc/gc9+PW9j
-gwVpGRuYkFf+AwbMgLa1Ro5zqoIbD7WjTu7vgGdDvJmrSVLfSXavpeUBzp37Dsw6
-KzSHcBjPwGes7q3pjfhOMwIDAQABo4HyMIHvMB8GA1UdIwQYMBaAFEnJ/LcDPGdt
-CgCTqeTWpR6SH7URMB0GA1UdDgQWBBQPcsozQ6nEEVGrY9pEhw9hpPS+RzAOBgNV
-HQ8BAf8EBAMCAQIwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIGDBgNVHR8EfDB6
-MHigdqB0pHIwcDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMUUwQwYDVQQDEzxTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBCYXNpYyBTZWxm
-LUlzc3VlZCBDUkwgU2lnbmluZyBLZXkgQ0EwDQYJKoZIhvcNAQEFBQADgYEAjoyS
-h7zhrGkL40stundacKPqIEZ3HyWW0NQhD0wBhWslGAOvlCaf44kuTKggRY6r96sy
-4kWEjvfGu/r/dBgrFaCCGNv0ui5FfXu8WeZ4jvHg7wZbx5ATx5Jpumqbm0PcEYCr
-YnA6WBCstG0lohNV2ohM/wqRFmBB0WL1K+9IdfQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:0F:72:CA:33:43:A9:C4:11:51:AB:63:DA:44:87:0F:61:A4:F4:BE:47
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 5c:cd:8f:a3:3d:9e:64:f7:64:73:9c:2c:39:e2:e7:d7:0e:b8:
- 1c:3e:9b:1d:14:dc:98:c2:8e:5a:1f:e5:47:31:fd:7e:a7:d5:
- 9f:52:31:c8:10:f7:d0:a2:84:3f:77:c7:f1:ba:7e:24:62:ad:
- 05:ae:1c:7b:ff:f0:e2:ce:55:f5:27:d3:cc:24:7f:c8:1d:a6:
- b8:ce:42:05:e1:06:ec:1f:87:4c:d5:69:8d:78:59:d2:33:94:
- 1c:3b:27:68:80:3d:6f:3d:a6:c7:9f:2b:39:9f:d7:c3:83:eb:
- 77:bd:cc:7f:96:b3:ad:24:68:99:d1:1a:bf:05:1c:8c:3e:2a:
- 02:f8
------BEGIN X509 CRL-----
-MIIBdTCB3wIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMTJEJhc2ljIFNlbGYtSXNzdWVk
-IENSTCBTaWduaW5nIEtleSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjAiMCACAQMXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0j
-BBgwFoAUD3LKM0OpxBFRq2PaRIcPYaT0vkcwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAXM2Poz2eZPdkc5wsOeLn1w64HD6bHRTcmMKOWh/lRzH9fqfVn1Ix
-yBD30KKEP3fH8bp+JGKtBa4ce//w4s5V9SfTzCR/yB2muM5CBeEG7B+HTNVpjXhZ
-0jOUHDsnaIA9bz2mx58rOZ/Xw4Prd73Mf5azrSRomdEavwUcjD4qAvg=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued CRL Signing Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:49:C9:FC:B7:03:3C:67:6D:0A:00:93:A9:E4:D6:A5:1E:92:1F:B5:11
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0x.v.t.r0p1.0...U....US1.0...U.
-..Test Certificates1E0C..U...<Self-Issued Cert DP for Basic Self-Issued CRL Signing Key CA
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2e:12:1f:54:36:68:73:b2:5c:f6:11:48:f1:d6:7a:bf:ce:1d:
- d9:21:7a:96:29:44:bc:83:26:d8:8c:f5:11:36:9a:f1:23:78:
- 57:00:8b:13:c6:74:57:4d:3d:ba:ee:d4:ac:d4:40:b1:d0:80:
- 91:f1:06:81:91:ba:a4:f8:1e:c7:6b:d6:20:3c:92:26:23:94:
- 80:33:df:c7:3b:ac:fc:94:ea:e8:3d:d0:37:c1:d5:e9:ba:53:
- 83:9e:26:ed:da:fb:10:0a:6e:d8:cd:d7:20:42:2c:d6:7d:18:
- 32:6b:75:2a:3c:51:03:dd:4d:a1:80:e6:d8:95:6a:2c:b0:b6:
- 72:31
------BEGIN X509 CRL-----
-MIIB2zCCAUQCAQEwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMS0wKwYDVQQDEyRCYXNpYyBTZWxmLUlzc3Vl
-ZCBDUkwgU2lnbmluZyBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFqggbcwgbQwHwYDVR0jBBgwFoAUScn8twM8Z20KAJOp5NalHpIftREwCgYDVR0U
-BAMCAQEwgYQGA1UdHAEB/wR6MHigdqB0pHIwcDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMUUwQwYDVQQDEzxTZWxmLUlzc3VlZCBDZXJ0
-IERQIGZvciBCYXNpYyBTZWxmLUlzc3VlZCBDUkwgU2lnbmluZyBLZXkgQ0EwDQYJ
-KoZIhvcNAQEFBQADgYEALhIfVDZoc7Jc9hFI8dZ6v84d2SF6lilEvIMm2Iz1ETaa
-8SN4VwCLE8Z0V009uu7UrNRAsdCAkfEGgZG6pPgex2vWIDySJiOUgDPfxzus/JTq
-6D3QN8HV6bpTg54m7dr7EApu2M3XIEIs1n0YMmt1KjxRA91NoYDm2JVqLLC2cjE=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6EE.pem
new file mode 100644
index 0000000000..7fe42dcdd0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedCRLSigningKeyTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 34 20 4D 89 51 7B 54 0C 6B 1A 52 FD 0D 72 D3 21 9F 58 87 FF
+ friendlyName: Valid Basic Self-Issued CRL Signing Key Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Basic Self-Issued CRL Signing Key EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued CRL Signing Key CA
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEtMCsGA1UEAxMkQmFzaWMg
+U2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMB4XDTEwMDEwMTA4MzAwMFoX
+DTMwMTIzMTA4MzAwMFowdTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2Vy
+dGlmaWNhdGVzIDIwMTExRTBDBgNVBAMTPFZhbGlkIEJhc2ljIFNlbGYtSXNzdWVk
+IENSTCBTaWduaW5nIEtleSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAND3qOzfoU+xaDx00z/q4nNVyzqNAr1QNbHd
+2Vr3Ny+UIQiQMN6wUgDa5fYlxpAYH3HyHYFGqsJZYqAEi+QOnW55ed5U6fgkuMIT
+n/cmHWrhrWxpkGeg9taQHF7JLv7rOQ7hJFwCpAGMIO8AcI4RT6uLFw4oJWlSFUNT
+U/Nuz3tll9cnN+Yka58LJz7MH8JpKiyKnu5k8rKb1BD31rds5RQtUfj/GGGz771W
+JFuJjDKN1UcL/EOAllJIfw4vmtjG3KwiR0xszG6xoQygEVKwr3eUE4GF7f2KKear
+EXZl2NutzBQqdY8sKD9K4P204/U165InI066R+fyI5qUg/JGQvECAwEAAaNrMGkw
+HwYDVR0jBBgwFoAUKZpFLjaVnezyXlScE9XZ9kSRLBMwHQYDVR0OBBYEFDK9sG1g
+aWR2H3k1G4/tOHKlv+89MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBACfVwWYG76TXRNenzqpOIJ2KRon5
+yMuzHhx7VEYiqjshbtUhBPf5P0WaidDatxO7aRV5F+UW36ZN40ToCkhigxFOaXR6
+lIATMJfqZ0yAP7FDwYzFJGmUO9m+FrZD/rge5aowjbWOuwnKTsjlu6IEz6j/v+cU
+4yO9xT8GgIs4HMagJ/e9qTAI9BhGpQqrkQUmuk8lEdzifR+f7jXLT7uPN1+GWL8n
+sY4eYTT1Saw4mhUFj21AOPwYtr4Bzb6IEEgJ3rU8y0vu0oTU4+e0i9+u0RbQAPWr
+zCY76nRguTsIVvPx/NhrJc8HvBij15cNTdYnWsQLSLGRkZkWV0fE4LtZpVU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 34 20 4D 89 51 7B 54 0C 6B 1A 52 FD 0D 72 D3 21 9F 58 87 FF
+ friendlyName: Valid Basic Self-Issued CRL Signing Key Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0494381DE63BBE79
+
+IudZ0o8BDzB7EEI1+uMk1VOVrcBmrKfMlt3ce2aPGA0l02hF/YsuV3PEs/+8yWqL
+ZBPy+WHS7wc35VWrC1RssivAei/Ie7W4UM0SAKrZRrKUDkCURB90+jT2iZfa2XzP
+nMNeBMcg/27buoq3BJu/zyVU1wRmy8/+vpzu2tbOdND0d3qPGZ399gAGpF8Q8dbG
+3jUCINKvdDIpYeWkN4eKvCSRrcH+POqEpY80pWIBucRPUXk6X8UPgvrGrv6DGrQ7
+V8a2/mz2NTYmUSNJVAn3vVwg78v6YMHvD1tbMx2tb1kKcb4CSCQEvPY+jpBkg1Ab
+YQ3xt300Kg/JMRFRqOFBem7wH0p6E5veL2u4JuR/L3fJAQEwlXYC6VmKQ1HR7foz
+qpmBxmE8/BTzhE0kBjy3nh6VDMW5Q0I0RBu9tRPV5jpPvbTBpF7hle1CT1oiUf3N
+dylp1Oy0oq75nijtLbstgJRoGp8tw+lTR0P9T5zQPU/nR2aFT8nv4H9KgmJdehEc
+sCDvDWWXg5R2pK2hsjGGa6RNomM0KjH4CTnrZXA2qK8v0LO8eVhcY8wsmEhJBzPm
+H/ZtOGzh6uYuTD4yWa3Dl9ZjpQEIPbXhOP4V9aBrtEtpJ4IAdHTz8xawZF0pucy8
+C49a5XJ8bvTC4Sa5PqOqGOSHm+ylrxtqPnHgStDvr3eRo1dxNMUJ4vuCx6x2s7wc
+Bsrj9fwpdiqWKbwcLphJU+9WfkMBrZdSRvo+d697ilJqwvvvjgihlXucinB4gj13
+mvS90wUhIr19cUrJHE2aErLJbFvcnGNITrtDbml5dPZj3FZ4khxTf/d3wQK1l+BI
+h+pci12QVsOiDYncM85H+dz/wSWfpcW2zOka5n6QwKA1BGIF6b4uf6MtwHQp0UOC
+Ih2gCYh7hnCYA0QnF0F1gz4Ty17bRTBvhiHIcZpNKqWUAwbqs7HI1w4WsFMLlpA1
+4Zi4FC/vzUO/AbWq460FqPXAZnzcvxpnQsuCx+kjt7oD351xPbn7XjyjibS1qeDb
+Df0XpuDliV2omg1B1wZN0bf/BvgXpM212oAm65hEEGMIACf5AsJ6v9HSHBKa4zZx
+OGxsgkp2J6l1zdcnuPGdmZrNrR8Go4xAuoa06Z9PlwUak+hh+hWjx3RSBcXde7Tn
+IkiXmT5TnwgJo5GzvZzNnCS9RLmByjISTHvo0G+mcJ2wq5JvMhxrfKBnIFvNebRg
+zGSFtzswIO8NPNhpJd1tFm0fZH71cppWMmaEnAIGK2Vj75/niZqldbCqGkwHMumc
+nS2+eOCDMvNzm63Cata2X5RLozuNJCcuRtPyrbPQ+tBzcruV3AfEoradNGg0Nk3q
+kMbH8lQUpNUehpVBUTi2JgYeczmK7tGzrpar2IuektktzVONkqdy5EsoumaoaP0F
+uAysrVQcX68a+E5IwN0TLz1T/UNLewz6AH95iC09yvpiHiME47ZzVLaOFX+p+V3b
+grd2fvx038AnJXp0McsvRqAp3Ee+oXMIexxiuopm16Jx0N0lg+9tFL84XqESpaRH
+DG+RhhG0qIySIhRc524DIXO//ep4lubujus86NCcb5JaSrp6WCpdNAhCyHDcjohF
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3.pem
deleted file mode 100644
index 1e0db3236e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3.pem
+++ /dev/null
@@ -1,175 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBFDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgT2xkIEtleSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-q8Gbt04t1VYDzow3lv3G+lNNQ/gCP0fz7/PBxNPzAwluA2Qzeix8gg74cXMpRe8u
-PosT3EZZ9iK1PyFmcNq+CjzCuvi8d+1gaGS36wkcQBB6g7HiKRQ8ERQ4cEE6CH21
-ntbFzVbn3d+NofzVo6e1AIdHDNPm7G0+F6f034Lo508CAwEAAaN8MHowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFPqiarnu+k/Fcp11
-00t6bYzkXDkkMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBzQl++7X/MYd9h
-3E0XroNDuD8TflER0UTgWOwN5UO8BXz8j402hmhEPyw66u6R27V7U1/wf8wtCAli
-W7LnTcJKWFy9HKnpibiz50ike8zgsVmv1godVgDn/xvQPRAnWq+OX9Abc+6OTqiw
-aDNRQp2WD1ph+daLu1XQgeAoD4Gajw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Basic Self-Issued New With Old EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
------BEGIN CERTIFICATE-----
-MIICnjCCAgegAwIBAgIBAjANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE9sZCBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBtMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxQjBA
-BgNVBAMTOVZhbGlkIEJhc2ljIFNlbGYtSXNzdWVkIE5ldyBXaXRoIE9sZCBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0MzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAln5v
-UhL9o7sN5MyQTZEB3Fhj6lKfzTNHMBCsngHpQqTP8zlmPvaEGpR53N+RNthxaW8K
-XmN4WVFvyXl8eaVl8+U5cewY1K/m/6OqDIZ6kvjXugMkKLbjL7ptsAGx5VoyHs/F
-xy4n0cEOmAXTZ7dbzFqM4xfqJRLqi2CgQUHnb1kCAwEAAaNrMGkwHwYDVR0jBBgw
-FoAUG7qMIYdzBwWY+uu52W9BpEXVhuowHQYDVR0OBBYEFKVAiq/jp5QN4XgK0S+E
-OKaV0NBCMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DQYJKoZIhvcNAQEFBQADgYEAIgeBhcCa3jeEq1F6/+iNWMXRVgzyV3vsDielCRFy
-wKdpYGocHPJG59OSZEHCUsdDRF2n3hhGkEILL4huEgX+oiiOhyGM/Xrr+ACuEIaS
-qfs4gBQ/HrYydCxNN4OHOuLoFDmotodh/lvY9igeeaRZ1AFI7AicI0D4CAqXyLcU
-9WI=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
------BEGIN CERTIFICATE-----
-MIIDETCCAnqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE9sZCBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBQMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAj
-BgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVkIE9sZCBLZXkgQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBALQ4a61C9wpu5W0cACccONm+QLNESmbHtLwy498fByU6
-h5UnHkutUfy7DbIv3rELFXUd2yM5xQI/QuQZ20EjXOZiCSJEcvzfoAyFLrAPf1pN
-xQybX5HhLnJK+oGlwmD4ZatL7oDqV5IhlIS0So7g+SBOCh5lkKdzbH3l6D7nQXSD
-AgMBAAGjgfowgfcwHwYDVR0jBBgwFoAU+qJque76T8VynXXTS3ptjORcOSQwHQYD
-VR0OBBYEFBu6jCGHcwcFmPrrudlvQaRF1YbqMA4GA1UdDwEB/wQEAwIBBjAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zB7BgNVHR8EdDBy
-MHCgbqBspGowaDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMT0wOwYDVQQDEzRTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBCYXNpYyBTZWxm
-LUlzc3VlZCBPbGQgS2V5IENBMA0GCSqGSIb3DQEBBQUAA4GBAHDVnYLXKN//Mu1w
-BZS8DbfQ8p/DlXZ0n9EmdXRzoHXReDWeOaoiHU1H1HNJcLMe4YgEjsttTEBGfsZo
-OvyNNUZ7C/oQymaDykP9W/m1TX3ZVLmx96zj36gCkVPczoG78kQ5zVjoLl5G5BJQ
-4YX3NumsNd2WpHY34K21Cd/KJ5KJ
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:1B:BA:8C:21:87:73:07:05:98:FA:EB:B9:D9:6F:41:A4:45:D5:86:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 62:de:93:8c:36:dd:b2:71:56:bb:4e:e4:32:37:51:de:6e:19:
- 01:dd:3e:25:8c:d4:81:7e:fc:66:54:74:0d:32:30:d2:11:49:
- dc:ad:6a:b4:fc:8f:ec:e6:56:fe:e6:ec:53:9e:41:66:31:2c:
- ee:3a:be:bd:74:34:9b:71:c1:67:1d:3b:28:04:b9:85:e5:72:
- cd:f0:2b:a7:d9:d5:e3:43:25:4a:52:2e:79:24:52:cf:75:e1:
- 3c:35:82:d1:5d:1e:f6:05:8b:45:24:67:ed:84:9f:c7:8d:c0:
- 19:55:5e:52:76:3e:2f:f4:af:13:ae:d8:24:a3:17:68:5d:b5:
- 45:74
------BEGIN X509 CRL-----
-MIIBbTCB1wIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVk
-IE9sZCBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgEE
-Fw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFBu6
-jCGHcwcFmPrrudlvQaRF1YbqMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AGLek4w23bJxVrtO5DI3Ud5uGQHdPiWM1IF+/GZUdA0yMNIRSdytarT8j+zmVv7m
-7FOeQWYxLO46vr10NJtxwWcdOygEuYXlcs3wK6fZ1eNDJUpSLnkkUs914Tw1gtFd
-HvYFi0UkZ+2En8eNwBlVXlJ2Pi/0rxOu2CSjF2hdtUV0
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FA:A2:6A:B9:EE:FA:4F:C5:72:9D:75:D3:4B:7A:6D:8C:E4:5C:39:24
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0p.n.l.j0h1.0...U....US1.0...U.
-..Test Certificates1=0;..U...4Self-Issued Cert DP for Basic Self-Issued Old Key CA
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8c:6b:ec:1f:5b:3d:31:1c:fe:c6:40:ca:e3:c5:52:30:a0:9a:
- 55:ee:f8:c3:bd:cd:b1:45:d0:7f:44:f6:42:1c:0f:b9:df:8f:
- 4d:25:0b:ba:5b:bd:0c:68:c2:ce:b0:c4:17:e7:be:81:de:73:
- 55:5c:6b:d6:3d:e5:e2:18:31:d7:5f:6e:1d:4b:0b:31:cd:44:
- fe:29:d5:27:77:f5:83:bc:ee:3f:46:31:d5:66:5a:a1:9b:1f:
- 16:d0:8c:ef:ae:bb:36:75:a4:b3:62:be:16:cd:de:b8:90:bd:
- 5f:26:1f:a7:d8:1e:59:ce:27:af:ee:ab:de:9d:1d:66:ef:9e:
- 49:cb
------BEGIN X509 CRL-----
-MIIByjCCATMCAQEwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSUwIwYDVQQDExxCYXNpYyBTZWxmLUlzc3Vl
-ZCBPbGQgS2V5IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoIGuMIGr
-MB8GA1UdIwQYMBaAFPqiarnu+k/Fcp1100t6bYzkXDkkMAoGA1UdFAQDAgEBMHwG
-A1UdHAEB/wRyMHCgbqBspGowaDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3Qg
-Q2VydGlmaWNhdGVzMT0wOwYDVQQDEzRTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBC
-YXNpYyBTZWxmLUlzc3VlZCBPbGQgS2V5IENBMA0GCSqGSIb3DQEBBQUAA4GBAIxr
-7B9bPTEc/sZAyuPFUjCgmlXu+MO9zbFF0H9E9kIcD7nfj00lC7pbvQxows6wxBfn
-voHec1Vca9Y95eIYMddfbh1LCzHNRP4p1Sd39YO87j9GMdVmWqGbHxbQjO+uuzZ1
-pLNivhbN3riQvV8mH6fYHlnOJ6/uq96dHWbvnknL
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3EE.pem
new file mode 100644
index 0000000000..f07496000c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 0B 3F DC 89 46 44 62 27 7E D5 64 8E B1 B6 E3 B6 FF A3 1B EE
+ friendlyName: Valid Basic Self-Issued New With Old Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Basic Self-Issued New With Old EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued Old Key CA
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgT2xkIEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHIxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUIwQAYDVQQDEzlWYWxpZCBCYXNpYyBTZWxmLUlzc3VlZCBOZXcgV2l0
+aCBPbGQgRUUgQ2VydGlmaWNhdGUgVGVzdDMwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCvB9Hx5fpvsmfyxZyAuxLiVbm5ZGySZNIbcBqQlZ4UZ35CG+zq
+H5ViyZ+id9ZDWkQB+RFQB1r93dvpCFiz0wYjRQ1cfxpudCCBQDiVgkTzt4/kD9pc
+iHk9w2ltb3fCqtjXTrLYl25PXXPq4boF10kWnxDvvEaoCl1jZBtEyta9VT3O20wt
+HeTLywU9Byql1qkkUp7fIBj/rgXDuMchFRfcN9C8xD3vSGp0Mn7w3dLkixVtk6fN
+mRgudZ1X4WtAzNJcWUZwzX1oBGMEoZ/p8l64lPuyX1SXtwHIbUkAtKDuUeqDpQa6
+CrtfqP/WfN6I3HCITRvw/K69sGjvXh3Ce9AfAgMBAAGjazBpMB8GA1UdIwQYMBaA
+FIhfvj81OWaa603CJhsmsSontQgqMB0GA1UdDgQWBBQm6qJntGK/v9TM/WTbiNJv
+J4vrFTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
+CSqGSIb3DQEBCwUAA4IBAQAz4udcgcZWr+2UzCvM8M9LWlJZIcpZTTDMgbIDKhAg
+WPcz7zI9T2gGVKy76yGTGisXSRuVPW/qUz6qSfP4OsKhkinToF2wDU8bYKB01AWe
+8JnTI13ZsOjlfunus1A6KXISn/OefW96YMTB9sloWS6YL2xYhs2tVbzAp7BDThNI
+x588Obo5IhjFuaq+v0J+iYl3guCHzfNMN08mbYomYCwZBYzoB6i/YSjrIhdVp+14
+Bfqb39ZLzdpxubzH2Oie/7PXibacCQo3h6IwxdWh/29vkt9p142MtnszMBUqrTOc
++yRvjXJbpv5rr9EmVaNhhIanrgVHHm7ehOcQZh+XDBFV
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0B 3F DC 89 46 44 62 27 7E D5 64 8E B1 B6 E3 B6 FF A3 1B EE
+ friendlyName: Valid Basic Self-Issued New With Old Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A9052792081A4191
+
+QhIGxJGXZ5WORB7p/Sv0ohTZAtTuhVVcLmlwz3p81zuk2usweBDNN22OZiFVOUnW
+hJBfYLthgUz5rwmlb1h5rvyOjOqVVUtwE4CdiD4ZFBUWEX0gnMZhG82nDFHRohcT
+BIw7nE4rnXBdn+RuFrKn+fw4+9TcWPCWlKJsyc+M33DP8qzWWL1PRNl/EyhyGiuI
+/sRCpCFPfUI1wBDeWhXpiDIKB1N6OdZHj+gW5kwUMJsDJS1wPT5BpAPdgMi9yebs
+Jn2zW1osO+dYGeT6dHhyVrfd0ryFpSvVmdM4XwrAVysC9nP81woe1OldNtM9vPuM
+XevTzETwZ88U2IUYT514Zch+XGd5QpIfchDxdVlfxkrkrQ2M73UhAXnIDSQInjbg
+iQBmNQTqAbOTK2KlJdRji1iRfofMzWzHuDQcppDVn+5PgvI/bgqA14pZH2E76BGj
+6ev1vBrKS0U5dU3tUJm8lkDJqZF8JUsMnbiLkGv+7R0/iua+9kdwHEECKabTIaqQ
+jnNN1jb74wEjnKdCs2NPrn+I9mWGjwgPKDQdbYgmkliF9381uIDNs6hAi65pMmMQ
+/ubo609SY4JwMBwDdD0GXPbpoHPLKoPQcSqbP3exbU282ZU1RTrhN/xkaqMW26ew
+hb9A9RWskmJhi6QwLW+Yaw3ERyLWKTcv8yQpzynBy8qbPFKAv/0rJ/iQjbliQ9GT
+FxgvqVZ1TNvbKTLK/XB6+7rjtBbrr3FQU5y7tkfqSKi8FRLrTcTjWhn54tPDFHsG
+Hx+XAiE3+wrwx9pD4O9ZL1zMM3NY9paXsePvThxKt0TWCQJZT/dtQJxp574WxrK9
+NKMg3PmzVSja5TIyy0fiCrqHJ5hyusw9DtJuxQryi1G+S+J3jIzK5horevNMuu0Y
+zQmFyUiBpyiziLTVSJC++OkOqosP/6ikxkV6rXBRM5pSjFVsXVHnF5KfSya9XtTt
+kfiERcC3G2xk08ZMnKSPzYl+XDGcjcKzEBJlbjdeW8qMNhEDd1aL/mjlaJzdXYWN
+F24lh8zx8s9P4zPxxIJoq/+6+dP0SRypECTP79sR7ACv10c1FOS3FALaG2qu4gDU
+75ITWrAiHY5JS4IlTIeUoWuMNeV3EEpbAJdiXbY2lG5wvFcWT6DQ1mTD8nk64Uam
+Z01quDB0vKsbia0HwpuoqJT8q6urX2M/y9zwK1snzsXDJ7kP3EyYcJvI0UoKJD4i
+1kzo+dc9brliCNdVJKMEu2YaTB+gh+Bx9Bni/IleE5FkZ7C2gEMykvv7zlKTksSS
+e8d27GEJL6827JjZk4qqoxxzNU0wgxn8gWbQXcMn+X01PsHLUZTVKMPBDRXMNIZZ
+FshWPNbT+kS0t0O9IHWMZbBJP6H9YAKdo/7MyMHXDpoOdQnhGKeI2H5I5nyerqms
+zS7aXIqxNFuGx4Jg2f3+08XNW2bdHtbud7423k0zaPOMf2HDkaGIxtWzkdDBZjTP
+EyD6dXmO0IR/8Bov52Or/0bOuCz8SL0Kdi4mff+0mrb9oe0xbBOQtOx5dTTcZgOu
+Hq//gPWA5Bi8AZV7AHqZPiyht9P+wJWrwKEfr2+jL6PiOIY0DDuGDdKGAIVXtAjm
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4.pem
deleted file mode 100644
index dc7432e631..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4.pem
+++ /dev/null
@@ -1,175 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBFDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgT2xkIEtleSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-q8Gbt04t1VYDzow3lv3G+lNNQ/gCP0fz7/PBxNPzAwluA2Qzeix8gg74cXMpRe8u
-PosT3EZZ9iK1PyFmcNq+CjzCuvi8d+1gaGS36wkcQBB6g7HiKRQ8ERQ4cEE6CH21
-ntbFzVbn3d+NofzVo6e1AIdHDNPm7G0+F6f034Lo508CAwEAAaN8MHowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFPqiarnu+k/Fcp11
-00t6bYzkXDkkMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBzQl++7X/MYd9h
-3E0XroNDuD8TflER0UTgWOwN5UO8BXz8j402hmhEPyw66u6R27V7U1/wf8wtCAli
-W7LnTcJKWFy9HKnpibiz50ike8zgsVmv1godVgDn/xvQPRAnWq+OX9Abc+6OTqiw
-aDNRQp2WD1ph+daLu1XQgeAoD4Gajw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Basic Self-Issued New With Old EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
------BEGIN CERTIFICATE-----
-MIICnjCCAgegAwIBAgIBAzANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE9sZCBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBtMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxQjBA
-BgNVBAMTOVZhbGlkIEJhc2ljIFNlbGYtSXNzdWVkIE5ldyBXaXRoIE9sZCBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAogdB
-BnysUr/KTFA61NvJ5idc2kOLUlr2Nyx1WK3KTTQwISpC6JWv5b2oERCJDCL7/3g1
-C3k8J0WWk7CG0T6ydQI7A90xJDYMPGdknO2Sc+8vm/JBnwo5Qgfz2X5Oeo0Bedbz
-IDJHs35fj6KCHCxExaw5BHTbxC2cIu9YU35+KTECAwEAAaNrMGkwHwYDVR0jBBgw
-FoAU+qJque76T8VynXXTS3ptjORcOSQwHQYDVR0OBBYEFHx6BhJiF7QEIUB6yCAl
-MoN5MbxqMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DQYJKoZIhvcNAQEFBQADgYEAkmGbvODeNeoPt8PMnRvdgOCxlnqA/pzPuD+JbKui
-VPa3xQM64kKjbdTsq8JU+BtYbgy1Ocx4Lmvv/wdJ5AuIosaWiAfwW/+VVni4f6pq
-lb08+5rRTA6k0Z5lhV2RSx+AomDcQnrwsxgi+LPj2aWfwxPL3RkpQ+gnBnoRdOwI
-Fak=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
------BEGIN CERTIFICATE-----
-MIIDETCCAnqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE9sZCBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBQMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAj
-BgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVkIE9sZCBLZXkgQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBALQ4a61C9wpu5W0cACccONm+QLNESmbHtLwy498fByU6
-h5UnHkutUfy7DbIv3rELFXUd2yM5xQI/QuQZ20EjXOZiCSJEcvzfoAyFLrAPf1pN
-xQybX5HhLnJK+oGlwmD4ZatL7oDqV5IhlIS0So7g+SBOCh5lkKdzbH3l6D7nQXSD
-AgMBAAGjgfowgfcwHwYDVR0jBBgwFoAU+qJque76T8VynXXTS3ptjORcOSQwHQYD
-VR0OBBYEFBu6jCGHcwcFmPrrudlvQaRF1YbqMA4GA1UdDwEB/wQEAwIBBjAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zB7BgNVHR8EdDBy
-MHCgbqBspGowaDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMT0wOwYDVQQDEzRTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBCYXNpYyBTZWxm
-LUlzc3VlZCBPbGQgS2V5IENBMA0GCSqGSIb3DQEBBQUAA4GBAHDVnYLXKN//Mu1w
-BZS8DbfQ8p/DlXZ0n9EmdXRzoHXReDWeOaoiHU1H1HNJcLMe4YgEjsttTEBGfsZo
-OvyNNUZ7C/oQymaDykP9W/m1TX3ZVLmx96zj36gCkVPczoG78kQ5zVjoLl5G5BJQ
-4YX3NumsNd2WpHY34K21Cd/KJ5KJ
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:1B:BA:8C:21:87:73:07:05:98:FA:EB:B9:D9:6F:41:A4:45:D5:86:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 62:de:93:8c:36:dd:b2:71:56:bb:4e:e4:32:37:51:de:6e:19:
- 01:dd:3e:25:8c:d4:81:7e:fc:66:54:74:0d:32:30:d2:11:49:
- dc:ad:6a:b4:fc:8f:ec:e6:56:fe:e6:ec:53:9e:41:66:31:2c:
- ee:3a:be:bd:74:34:9b:71:c1:67:1d:3b:28:04:b9:85:e5:72:
- cd:f0:2b:a7:d9:d5:e3:43:25:4a:52:2e:79:24:52:cf:75:e1:
- 3c:35:82:d1:5d:1e:f6:05:8b:45:24:67:ed:84:9f:c7:8d:c0:
- 19:55:5e:52:76:3e:2f:f4:af:13:ae:d8:24:a3:17:68:5d:b5:
- 45:74
------BEGIN X509 CRL-----
-MIIBbTCB1wIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVk
-IE9sZCBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgEE
-Fw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFBu6
-jCGHcwcFmPrrudlvQaRF1YbqMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AGLek4w23bJxVrtO5DI3Ud5uGQHdPiWM1IF+/GZUdA0yMNIRSdytarT8j+zmVv7m
-7FOeQWYxLO46vr10NJtxwWcdOygEuYXlcs3wK6fZ1eNDJUpSLnkkUs914Tw1gtFd
-HvYFi0UkZ+2En8eNwBlVXlJ2Pi/0rxOu2CSjF2hdtUV0
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued Old Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FA:A2:6A:B9:EE:FA:4F:C5:72:9D:75:D3:4B:7A:6D:8C:E4:5C:39:24
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0p.n.l.j0h1.0...U....US1.0...U.
-..Test Certificates1=0;..U...4Self-Issued Cert DP for Basic Self-Issued Old Key CA
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8c:6b:ec:1f:5b:3d:31:1c:fe:c6:40:ca:e3:c5:52:30:a0:9a:
- 55:ee:f8:c3:bd:cd:b1:45:d0:7f:44:f6:42:1c:0f:b9:df:8f:
- 4d:25:0b:ba:5b:bd:0c:68:c2:ce:b0:c4:17:e7:be:81:de:73:
- 55:5c:6b:d6:3d:e5:e2:18:31:d7:5f:6e:1d:4b:0b:31:cd:44:
- fe:29:d5:27:77:f5:83:bc:ee:3f:46:31:d5:66:5a:a1:9b:1f:
- 16:d0:8c:ef:ae:bb:36:75:a4:b3:62:be:16:cd:de:b8:90:bd:
- 5f:26:1f:a7:d8:1e:59:ce:27:af:ee:ab:de:9d:1d:66:ef:9e:
- 49:cb
------BEGIN X509 CRL-----
-MIIByjCCATMCAQEwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSUwIwYDVQQDExxCYXNpYyBTZWxmLUlzc3Vl
-ZCBPbGQgS2V5IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoIGuMIGr
-MB8GA1UdIwQYMBaAFPqiarnu+k/Fcp1100t6bYzkXDkkMAoGA1UdFAQDAgEBMHwG
-A1UdHAEB/wRyMHCgbqBspGowaDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3Qg
-Q2VydGlmaWNhdGVzMT0wOwYDVQQDEzRTZWxmLUlzc3VlZCBDZXJ0IERQIGZvciBC
-YXNpYyBTZWxmLUlzc3VlZCBPbGQgS2V5IENBMA0GCSqGSIb3DQEBBQUAA4GBAIxr
-7B9bPTEc/sZAyuPFUjCgmlXu+MO9zbFF0H9E9kIcD7nfj00lC7pbvQxows6wxBfn
-voHec1Vca9Y95eIYMddfbh1LCzHNRP4p1Sd39YO87j9GMdVmWqGbHxbQjO+uuzZ1
-pLNivhbN3riQvV8mH6fYHlnOJ6/uq96dHWbvnknL
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4EE.pem
new file mode 100644
index 0000000000..3fb27269be
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedNewWithOldTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 2A F7 87 BE FB A5 B6 5A 03 1F 34 01 8A FC 21 34 0B C1 ED 93
+ friendlyName: Valid Basic Self-Issued New With Old Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Basic Self-Issued New With Old EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued Old Key CA
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgT2xkIEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHIxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUIwQAYDVQQDEzlWYWxpZCBCYXNpYyBTZWxmLUlzc3VlZCBOZXcgV2l0
+aCBPbGQgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC1hupFJIR+fBLxx23/Kru9609/2Of2reiVqs0uGOuzXEzcBfwg
+9WdOmpHE1tgrgnPeg8KPjQEdi3E0FMZ17szaxuBzWaBD82++ZUGuOsyjG+1U5pp7
+nnbay91jYHRKTscjnRRaey8vSorDe4H7lhnTUjeShTXnz1YOZCMf8MLNXbD7Yt5j
+bnwSo9EdvJvh2Te7ZY1jTvS7jWGmFZOTyaeVRXXkwN9jtm4uc+oc5B5D948nRAML
+o8qspGTdP8jokf788nWZrbqc8eFYK9mQxZkmkULPb+wgt/M1aNcTixwXuorxmUGM
++5ZmBxemRqqNIk9OlSScZ3oOKNaFEZ90QQZpAgMBAAGjazBpMB8GA1UdIwQYMBaA
+FN0NdY1TaBLEyxVAwBSGFBYwob6vMB0GA1UdDgQWBBR0xH9Fw7Me7BU1MG+ThFGX
+FlOJSDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
+CSqGSIb3DQEBCwUAA4IBAQCJSpwZJZwrb6ql2kHDQmAuRxn30WNsAenJokeRhyL0
+GMvOWgt+IYyeL2DxoZL477cH5+zUG7JyefyZvXz2oAzfApgPK8MCeQC/opoU1gQY
+oCWuo5kQjFtqI68wosKxrQvGh+VJMhREKBfShcR0z+MQhRut52Snvb2vMpdj0+yX
+iLttI1yQExAATJR2LUBCG4lMIqwW29IgXLUkxDSH8yyMA4NsRKhkawlY6+rGV+8Y
+pqZr1e0rmZXNrkxe7X28c4a23f75cq/+oTAql+9IZVE1FqWE/z7Ae4iKudnZTxnw
+Vh989tNkrWJeVLTOxczANY8ULemtvO3b5192gj3WA0R8
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2A F7 87 BE FB A5 B6 5A 03 1F 34 01 8A FC 21 34 0B C1 ED 93
+ friendlyName: Valid Basic Self-Issued New With Old Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DF2886BBB4A02584
+
+oUu71FFuDSTWIirwHAtUtRXTNC7IU1ZW+ORNKmQqHO356vmTvgT9DcWVWfWn9zgY
+z428amzxjkS2MnVMsM+EEKUY/PcMWBY3GF325nRgHdUylKirNFDXX0jpfA8ic0s6
+gMio4ELZJQzSgQE1Quizz23JkmkaEOWFR9d2lzi8N4N3i/XTogkmyLtX96ELm+C0
+yWBkRc0y73YljPgr5kh8R4iNSBhpdzC2LBDMa2kEUvM8Q4TDzxyY0evyP2V4QSaW
+v+1ovCiII+gwML11+0LiS8sdvpGguGGpop7aFceAmfDZ3BLCsXpfAweS1GQJU3aD
+ZTe8290oS198pmbvVGStlmrb9w75brS0eYFlTEZH8SsM6lA2a5Gf8PoaMxHxoxm+
+3BODRdpRLrpqzWaej+6JgZGv+uot6oOHDpNrRIT/381Vjt8tKQtepUG7ENvOg5y+
+AmquMjJ+3ynD+0GWgM263bcb6+QRX8O4fRY+drkfDR1sd3/tzwuHb1q9FSC0mZR0
+lSVAe4mRW6IiCdbSiqhrrP1KPygd6JGfheVlLN/7drJZaHpjFG/tHqEYVzLPIV4M
+FibSiwzOcuPbTbFTIRIfLFEHYkJqIMnCBeVytqQuIaDBoy6MixggSOLMCcwxkQXH
+BfLOecE2LSI07mMZbPMKbPCGrmsXidUAgqk5us+mSdeYcgUPhUlvJQj7GIfYr22Q
+eKRiyRpZw0C81LY/l35a2bw1Nzpt/Iv0TiY0UJPrnWf6OEZwQRnYJeM20mgrcois
+saP2yW1Vz+PHY3rcZE0zv1n8ZQEe6Cax2QbarUbm7Rwkn0pcAX6TraWfYltTNg+3
+9yMezsmWJuReJr8fr+aLXxFYtETcb7CuSSsEJF93MZW5XuH9rsB+prBACIyhXxSG
+RcVeuqIeFNM6jEzfCu1n9AOtiPuwk7s+gF0qrVnMGvf91eJ+hishC2aSEWfkFKCT
+EYBgAhZGJpVOYC+iI8QNFrbRVzQk9+8/TsQShMU5wWjA50uNbxB4pS9OSg5J1NqJ
+4Nu5y2nyyladU36EiFVuYW18iFLrJAvBf9lpaEL52JgW1UOWwWOorOOhIfSd0AE0
+FXKLyuuklU190vwe50OQaay5gHL14Y/MHlkgcJAwHgvogjtsi6I9NoVVgqeqLVlr
+rWVXLbOQ79J5RIw4A1DXyDJBFPBFsptCqHun0rlx2tj0glbJGU0Y975nGfo2GFSA
+mojl02Y0x07E8Hx2TmPZmirxepIlqUN+f2SRLb97rjZFP3NBVk2URY6iZ5bVW+iW
+JtKctGjyYD/tdtXoG11uPjiJd6Hlb3YEeoRvoUBKVr1ZSH96wVOtljiFKWVWPq8e
+XEeV6mhrvx1tqN08RKz/qZY0TzNmf/cRhztpUNPM6swpgW2pqkTFwGjJ+RF+Admc
+UBz/RqRH9fYQn9R753weJOyHJw2Md2TIW+wiD+PMOg5KoGZVSNKu0qsLhWDNfKCh
+X/CSWxyHQNHSKzip7RgzjEMrVR/dpoLAb4chz7JV8JCikgr8Ei7N0itZzfVJnpJ4
+IjEW4Th2ygeLmuzK9ofeuCtwogx4BCVZOv8QxJpcixZkpXUYLVdWVg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1.pem
deleted file mode 100644
index 8a896652d7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1.pem
+++ /dev/null
@@ -1,134 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBEzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcQmFzaWMgU2Vs
-Zi1Jc3N1ZWQgTmV3IEtleSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-tCkygqcMEOy3i8p6ZV3685us1lOugSU4pUMRJNRH/lV2ykesk+JRcQy1s7WS12j9
-GCnSJ919/TgeKLmV3ps1fC1B8HziC0mzBAr+7f5LkJqSf0kS0kfpyLOoO8VSJCip
-/8uENkSkpvX+Lak96OKzhtyvi4KpUdQKfwpg6xUqakECAwEAAaN8MHowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFK+5+R3CRRjMuCHi
-p0e8Sb0ZtXgoMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCuRBfDy2gSPp2k
-ZR7OAvt+xDx4toJ9ImImUvJ94AOLd6Uxsi2dvQT5HLrIBrTYsSfQj1pA50XY2F7k
-3eM/+JhYCcyZD9XtAslpOkjwACPJnODFAY8PWC00CcOxGb6q+S/VkrCwvlBeMjev
-IH4bHvAymWsZndBZhcG8gBmDrZMwhQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE5ldyBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBQMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAj
-BgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVkIE5ldyBLZXkgQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBANa7RRhusOV0Ub10qBKMsUMG7QViaonYz0IcJLX0FKEI
-EpTq0SV6NeVjjzmcrSrzjHQfJpkywOHRiMw7XvYunmzlwGSoD6TW1ZUYVDaQbKUT
-oWooVoCzVstf6AsZiJiHQtBt4x4OHap7QRcJdlh7aPhp6TR+zq8gB1HsG8yUlG0x
-AgMBAAGjfDB6MB8GA1UdIwQYMBaAFK+5+R3CRRjMuCHip0e8Sb0ZtXgoMB0GA1Ud
-DgQWBBTJW9PRvwbxAcF5XLtzDY1MRsst2TAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF
-BQADgYEAhIZ09WrNK3jX+b8HugQygNCBEVVfX7TOCCFkmRaxp4R/QBHWvcts0YQT
-6M5ZC6b877id6zRYegHadKekVVqwFbLKEO0MnpD2yGhGgDpbil2HlEaQ9yKQXpGF
-CBx05/e7jkNhk/zGDsBqmNzkozrJOYBohkwUOjVFkAuLyovPhTY=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Basic Self-Issued Old With New EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
------BEGIN CERTIFICATE-----
-MIICnjCCAgegAwIBAgIBAjANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYt
-SXNzdWVkIE5ldyBLZXkgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBtMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxQjBA
-BgNVBAMTOVZhbGlkIEJhc2ljIFNlbGYtSXNzdWVkIE9sZCBXaXRoIE5ldyBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0MTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArImc
-Yf7s6ea0+dqzWPAcGg4gZE8CjbYlhP964Da56tk10sqLVKHCKxnRYgymvojftLHO
-4WYGhfOfDGxlEex3i/AvnxEqVlwzH0M1fCU7mvycYjZtMSObA4U1mr/MRoO7U2so
-ege9jkx/dSbZIRGY1huIipH8TjGnOmfa56IBLpECAwEAAaNrMGkwHwYDVR0jBBgw
-FoAUyVvT0b8G8QHBeVy7cw2NTEbLLdkwHQYDVR0OBBYEFLKHIZkLlnQV1U2SSzrY
-JQOcna7uMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DQYJKoZIhvcNAQEFBQADgYEAZu2t7x1PqFyZIdjnp2j/D37jnc5xmuhC2UOUuyt2
-WFggO+apFns8iYM3azA0uj819lQexXHqKAZi5tQnMzPcYJgDjb1ix0kUCwiW3v20
-LlHf39XU7HJjfXn5USPwqNvrHcWADkRfL10y0ve+F7tmkESFvb/yF3ZU+t/OBKb4
-Dgs=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Basic Self-Issued New Key CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AF:B9:F9:1D:C2:45:18:CC:B8:21:E2:A7:47:BC:49:BD:19:B5:78:28
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 73:fe:c5:db:86:ee:6b:0e:f8:68:85:d2:0d:c1:44:01:d1:33:
- 5d:9a:42:14:a7:a9:20:bd:38:30:c1:f1:3e:c1:b8:d9:4c:ba:
- fd:3d:7c:a9:66:5f:94:fa:46:e8:23:94:4e:8d:09:1c:45:6b:
- 21:ce:b5:cf:3f:e6:18:33:d0:ac:a6:ea:c5:f9:32:6e:75:31:
- 79:6b:1a:8e:50:05:86:89:f9:f3:e9:8f:67:e7:93:b7:d3:05:
- b0:9f:2c:97:9c:b7:7e:01:7e:c6:5e:f8:72:4d:11:6b:9d:30:
- f2:69:df:68:5d:aa:a0:84:f1:07:68:15:fd:93:f6:14:a1:f9:
- 90:ce
------BEGIN X509 CRL-----
-MIIBbTCB1wIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHEJhc2ljIFNlbGYtSXNzdWVk
-IE5ldyBLZXkgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgED
-Fw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFK+5
-+R3CRRjMuCHip0e8Sb0ZtXgoMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GB
-AHP+xduG7msO+GiF0g3BRAHRM12aQhSnqSC9ODDB8T7BuNlMuv09fKlmX5T6Rugj
-lE6NCRxFayHOtc8/5hgz0Kym6sX5Mm51MXlrGo5QBYaJ+fPpj2fnk7fTBbCfLJec
-t34BfsZe+HJNEWudMPJp32hdqqCE8QdoFf2T9hSh+ZDO
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1EE.pem
new file mode 100644
index 0000000000..b9dbf00b73
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidBasicSelfIssuedOldWithNewTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 05 3F A6 27 06 55 4B 0C 69 50 D5 0F 5E FD BF 47 A1 9C 82 49
+ friendlyName: Valid Basic Self-Issued Old With New Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Basic Self-Issued Old With New EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Basic Self-Issued New Key CA
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMg
+U2VsZi1Jc3N1ZWQgTmV3IEtleSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMHIxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMUIwQAYDVQQDEzlWYWxpZCBCYXNpYyBTZWxmLUlzc3VlZCBPbGQgV2l0
+aCBOZXcgRUUgQ2VydGlmaWNhdGUgVGVzdDEwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDev0QtgDJfvPcfzwqGf7Xo6oBJMIEKObeQqeEor34N6RpT4gdw
+mhmz/6dR+r0xpAVnpH9peH3F07hanqFzlYmv3oabgCYMmDBAxEFy1cptkE4hDdsf
+UZqruxtd7v84c+hUd55DSPmRjzCZtvbm445wpUJyTcIxTIckpS4Z46TIuM5CCgcX
+CJBLa/UA7nAFJD634GMYzjcIjwqQftmgmyvQxlEkGxc3Y8el2jBt160yHTlbcPUF
+2cB5heUWRvSLHWoYt2nBhL8W75NzJZaKAtL+4zSYQ/uSlutIuV1cAnubaR9kfQJE
+A3tKagf2BP8yokA4aOkXEESnnWV4gh+ZtvoPAgMBAAGjazBpMB8GA1UdIwQYMBaA
+FHZ82GQENAlP33EhdA8MFps2qILXMB0GA1UdDgQWBBQD3ajkIvc9gpRLEUN3LsTP
+J+b/QzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
+CSqGSIb3DQEBCwUAA4IBAQAgcf52e984C7/uhGUkZ6oTOyFsCZy84Vy46uuiCRkv
+Zv4di4AA1XURzEKGEwR+F7ewE3mNbrfsfvwv11ZC//bZn/9nJUN8z/VvxHwnlNm+
+Z0iYclryFKrs5lvWjwzlNG3tZeNl77X8rpGlwpwU1SbFJH2N93JvUWfMBXd0QUcn
+Wor68nK8FUBd/1tAq4njU5OT+nBfII3Cv+Fdg902zrUTqrJXZmdD+jSBifd3S5/m
++nitrP1YAODnCqZGjAmgzDZTq4C33B8b88nhfIZssqK0rEsQoN1qyRZb5nTBHZ9L
+P3LirbQTLxJHYSAZl3GmRQ8sUEODnIN9hkYRSWoJZOtl
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 05 3F A6 27 06 55 4B 0C 69 50 D5 0F 5E FD BF 47 A1 9C 82 49
+ friendlyName: Valid Basic Self-Issued Old With New Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,10B08039DFA4A58D
+
+g68Sb53Ixkr6ma6Vo+HWtS30kwevnOgRyE4CEBC8a5mc3dLcXo+N8igPZh794SLs
+8aVAS+JVZezz6uLoiXXE3kjDeP6ggZMmWaNq87vWkk7dcvSX+JI8fJ04ziZpfOBL
+TGQsgePImkW1sBejluwySCmYywt8Zb8pLDTjrT6aWF5UCO/CoDadNJVL+LQG8NwK
+zsVYicJc0hWmlMuoNzi/yJx4cy74QrHRiX7G6ZA/JdMC+jV+6zgHcRxb7dqAv//C
++8AM7zuhOJUtQxEzeLYVBqBT12BYWEY0FLV1Lz0Kyt5s4Wt4AZLyOnQpFiYhbChT
+7MLuswQIJyi067yarkAcPIqdDbewjDUKEhMjs2IT5BvshlF6dKDvYhlUr0zhgUbw
+O5AsJu8H97vp/jaSisVRu7ZtDcpGn4lXy4ph5Q2o9++diK5v9HbywocigjRdwDqI
+C/704gRJMBUoFPpujM7uI9XkcGGdcDT+ZQ2i8zXtwNYprF3MxhX4vxF9Gp//VKtu
+po7tLpQcucUrMyDywiIJeoTJtWj/hRzmuJsXoNst1caGwoCpqP7TYhL4eGqFEg90
+ubR9B6qbabMCfATgKAEUpQ5NKjvbaJ5QgSm1AAncu/MgPBmH1WxnqH7dA7Qa34oV
+3GSIsKcYFV7EYwjVSTFZpHZACOe9xkL2G+rzY7JVINGzv8mCdau6sr6kQCQAVcY5
+cHMOOQvne9GsxEt7iN8OBr1mBGwFhJFRnoAp7ECHe2vxrJmN1W5rkq9TZHFrwCJq
+F2zWEj3C1It4+1cvdo5kMdvcFvdiK+svhgJu00Vi+clN81MRmre8Xm3HaueJ9Xn5
+BsPYP7M2vLGfd2QOC3wMtgCOjmlCiRQ/r2nLOU3ydYQiaEFltV8CK5SXGiI5i9/b
+UxY5tcdLHACcwlpaFvUADs73yfw7OJfd3RnPOTdLksdI9q0hx65oS4CgIF/haP2X
+K9z8G4C/1OFCx7TYC05QQo5C/K7sALErFzrpMtbVwUFddCzoktKFsG5PB9jsoWw8
+lhmXrJqKCok/f2W8o3hZHVfUEaVddIcPgcXGgKtsedXlBkjfIgqUDdLdcwF5lV8/
+mKw5jL9ozlEkMZmCU8rUOuSGWo161n44W9zGHkgTSxLiVOaOiqxmzACWHfHy7G2V
+9fx0ncJCgTffmcGnTYRJi9S1AizgaQ0OC89CrVxR809DQxykWeSeNpK43u95Lexr
+tKJvVK8lOl0gihDW6rKvwS1bdF7LzvSE1q6544FDx390+SkXYAq47BVQ8dNybif9
+hR4EroJ+C1Q+LjVb0A9w/nqNRFhRo7hTkgWE7BoW43JhRK+mIoV9joY5sa0hCRvZ
+6+B/4hNVQLgYp/tnNRm3k9shpk6jGzQB6a0BLnatDySPS2+MRovYgQsZCrZqcpO1
+kQ4hHfLaJ3jTndN5yytEJ2ZWcCUbCyY5Q48EyNpDpGHZe88iDuniD+H8xbGixn01
+b3xmcvgJ63ZsXiN4I9kjLUql3YxraWqbcaq2Kvh2MD2I8Z+O5dhyJcwaFZcfDF0Z
+3mj2YiTCZJb1xGX5fRQhrjwoEQCb7QjbGVvV8L3DJiSCCnjr6v7QC/c2Du+VCIUw
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidCertificatePathTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidCertificatePathTest1EE.pem
new file mode 100644
index 0000000000..c07567a658
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidCertificatePathTest1EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: E1 28 46 4B E7 34 D0 F8 4B D9 28 51 6C 50 F1 5A 18 B5 2B 96
+ friendlyName: Valid Certificate Path Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDeTCCAmGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMFMxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSMwIQYDVQQDExpWYWxp
+ZCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANncdxgQEBhgQfvneBAP+IR3cO8tblU7EaaZUj9t9L2hl/o2Hm5EQhHI
+U/51hpteNxKIon3ZcQjUSTVxzkbPW9BZjmUf60I9yg7cTJDYVGnPXjiyIGDdg1Eu
+39vVWziRWi3PmjO0b5aQ5XYUYkNphBDPVEH5Neqe1FqXnV4QWb3g5MNZidfe8nmw
+h2sCwFmhKgCCFW9rEREAUzR0PfThzFZiouRl6COxgx1YUwiyMy2WvuV9M54QWidz
+U91dmOJLEVNYkY/qchHsu5TyDQ9QrfIWtRoAJDHlFb0XBpCqJLGs3QxSHvCLaqu4
+9+3fY7TOlGi/XpbQRJbx+PR6Ogp5FVMCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGE
+JBu8K1KUSj2lEHIUUfWvOskwHQYDVR0OBBYEFKg8CZ1n9thHuqLQ/BhyVohAbZWV
+MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZI
+hvcNAQELBQADggEBAB5a2Q+vYqW5Ury87AxhiBMBqgoPDUejnqmyFxv4o9ks0o04
+vjuyz9QxiM/OafSOx7lwBVHABofGlbT2avoxni3EF7Pt5XoZYRhujNHkDtqbbWyN
+BpDuLNF5WNiEzZtB0xji/pHGXwAnFGV7Evovvai/NI4tzxdMWFswDy5pZkUmJiGY
+0/OQrimHWk7Gvegofg+glOb/XLVcT92KYVkOBdL/xWnA04lK0cLlyPTICMP9KiNP
+hABcLEQtg4rCPSLHPGDyinjjG0Zl2pmP+GPB1HqgcKZ6pxCbnax/vhTwRCOHWKwQ
+FejzoL8eJcs2qwJpWq7/wG6wQ54Inhk8pzBujcI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E1 28 46 4B E7 34 D0 F8 4B D9 28 51 6C 50 F1 5A 18 B5 2B 96
+ friendlyName: Valid Certificate Path Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1FE7617D7FAC4636
+
+p0Mn+JrDNgEXb1a+jzTU9Y0tXlkry6sa7zqyl7Sl9Krk1/dIYgWppKRE19A91EeR
+Ksiwo92hb+nfSJETfAr4OTL7egtQJoOf/jWhfb9WpFM8+X04L7EgtZUvL9cJHBpM
+UNrEGnwKC6Z+bJOnaSydWH2D8E6OweMZKpt5am4qjGXRLOv/hW5+N6uL5sbbrgQO
+BEHkEVw6uHBd3IvB5n5vvMfoFbpVPERXwrDRNPgY/2qtMOvGg40PWzTRVsoGm1YQ
+2FiOKkoeKfvc46/2K396npTBY2oQqZBMUb0GWBnpV5cdKHC0HnWzROPk2WZPgz30
+ppJvCzWsNqolQgKKuYYFnjAXY+JrmCuqJqdFsv96b/GdepyOdWj8jQiJa/T9Wp8P
+to85l5HJ5MfeT7LzK3lyWvlMHrUUs/ZT9hfXAJe2ZQRIMtYpwJkIMmRktHJ8kmVd
+u2zGzQxjIA/Yf3iKeVQu3yLS1ODC7jvjIqLEEmBegx5sFWKtVChyFrPn3J0fk53n
+07xZ5D0m5bX2bctLUR1lFADNO3Zvl2mJlz46wpmToIrlQFsKq1gO1JFwo7P7MzQX
+KWQjXOYWEs939TdiDvIk86ZnaWnNwxcuRK3SqzathM7qubKMWGPlQmMd+Irmm1Le
+Y4Lv3stgUJpnil/vhqT+MfqrCxtugyVX3PONdsh5mKIzl7dMsqtwDyRWNrZS+eID
+qXgs71PxU8TT0F+FvXbCnZ7uLUrOgdfXbyP4CF5lQEwZ8HxMTmJ4IOz/QK89uDSO
+VdZHoc6qpnhCnmVPyI8+yxwAGH1C3Qt3ubU7+EUBto1jITqFNyV6q+o/kL8vsUVF
+fwIFJSyHpEahx+9ytQKHxXCy0vPHirle03uGqLZuO3PvxadxE8CniNK1dUzMwsEN
+a7qmDmMjJWeG3ICzHbdirJeUQePApdLBMNOeUrUKGGrAqhH2qHPGcWOW0GxZJgtE
+02eGX9WsxhewEXNP/ccQDl+MyIA/ao9ypfEs2OgU+Y/TOAi1xKwQp8zi4Q3J+gSD
+saZC3mm/HLsAeTk5TYdca5FLDtbiQ5OvT3P+fh5glmSdEgZkq3x84lYnS/nMIjD9
+t8UEmmIQgLUkLqvfSVxzIavZdiszpVaf1cUNVp/0iQrUeocc5wFRV6KbKMKW2mYJ
+taUJeSQSXuZ393mj7dpQxW4puRTZWOztANImpmUm0kgQ3FLnLMCwA3d9W13IXwjl
+J39BmFbyBAsl8rJvD2v/qziflv8HT2SjC2/GbfSZ6C11MmoKTMRW+7NEC/crDk0V
+hBcHjuz/szivPSLHQiTAjYS/Xl+/15AYPhKL7k5d2RmcInNCmN2So1ketSQfeBQI
+9t08lQu759EoZDRJ8dnR+mWBKSAI8zUYThGc7lTtW+cQMOsgDYV9eQO3QkkvzvnK
+7gmmfqCHReWY7xm6Q6SM6iBpPHnQ55000RKEaglCzABv77RgLlS+D1OGRwGGdMr2
+yJOQnygTmlVpJt3bh4Tuh77wh1J9BwWBf2k1wQMkndbelL+5i8Mkvm+33MVEKJYD
+I109GqlY9x8RdI87SlBth3Bv50up/by/seRVcqFpa/7HhCiXhcJqsw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30.pem
deleted file mode 100644
index cdaee8592d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpzCCAhCgAwIBAgIBRjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIEROUzEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKF4cGWB
-eAaOHCGkAPlmkE9/9XtvEpanIGNf1g0ab0PBnZR8ffY+IK2+rwOeMVtfXmJbaxi/
-Z70teNn94XkPXH6Pmz/pL170Q96CasAsPU2uQC4AtNjkUSeFbSoY7Ul2NaBYqLrW
-yQ7O3jEXdX76KQWqYcihAq1Jw+AEruMq98WrAgMBAAGjgaUwgaIwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFHXnZ0cYCavxiIjbno3V
-F1KO/HN4MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoBgwFoIUdGVzdGNlcnRpZmlj
-YXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAzUV5anoiOD8wQQnetIFcg5wLnNlr
-dPixWje4q2JQcPnqZk3TW9O0GDtWHmZwVoS3PixQlJPHZGvkliTKM9vO7a8J2FDl
-/ZFRNrm2rHFjZxygk+UTwj+SI4CO8kmtSesvV0ViWwNNyfOV/nmvBjqy6pEbTnCD
-pax2/2P2ruVALCk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid DNS nameConstraints EE Certificate Test30
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBETlMxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTgwNgYDVQQD
-Ey9WYWxpZCBETlMgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Qz
-MDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA08C22ZtMqDmJQjt6hWE9rPJX
-rWB8T165lEh/iTleDZqyVWl5PRT8V1PTxkkp5aURAXm8BsNc1b7YFZfdsiMx1bjU
-iBSvqDWP8HtarPF6+J0wsXO8Zxp8OV8kCjU1gA4hLHUvVghURkKoVXwzB2cwhlqm
-iJcKkvv65JpzZPinbCsCAwEAAaOBmDCBlTAfBgNVHSMEGDAWgBR152dHGAmr8YiI
-256N1RdSjvxzeDAdBgNVHQ4EFgQUYmleNHVLgQPdh5BhovyETaAgDeAwDgYDVR0P
-AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAqBgNVHREEIzAhgh90
-ZXN0c2VydmVyLnRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GB
-AJCvVAtnYWZDsmocwYuC7e6N0annLwnm6MvbUgS7+KHuXfm1ty9YuZRe3t1SFQxX
-yhuTKj9iERpNsz7ldpdAKftS6PasptiZLlqhi3Z6csOnVtmFErdgN56iJoZgkDlv
-YTSVuG8xVfNBvOTHve/LWxGMlTGPDLMLf0hamDdBTfCK
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DNS1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:75:E7:67:47:18:09:AB:F1:88:88:DB:9E:8D:D5:17:52:8E:FC:73:78
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 90:61:77:a1:94:8e:c3:62:6b:dd:eb:ec:3f:0d:e0:dc:1f:b9:
- 04:fa:e1:74:e4:5d:d2:0a:cb:42:4f:41:9a:a5:91:d4:2d:57:
- d2:6f:1d:5f:cd:9a:2c:24:5f:3d:21:9f:87:78:17:33:96:09:
- 1b:d1:bd:f9:50:b7:17:c1:e0:af:50:95:7a:9d:03:9e:2c:95:
- ef:f2:c2:a2:74:93:d3:9c:c2:73:74:96:90:b0:78:15:69:e5:
- eb:b4:5d:dd:19:4d:ea:9a:78:af:ae:a4:b5:69:78:58:aa:7d:
- 5d:9e:05:ee:a8:8d:2d:16:03:86:18:62:6b:cd:67:8c:5e:13:
- 1d:46
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBE
-TlMxIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBR152dHGAmr8YiI256N1RdSjvxzeDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQCQYXehlI7DYmvd6+w/DeDcH7kE+uF05F3SCstCT0GapZHULVfSbx1f
-zZosJF89IZ+HeBczlgkb0b35ULcXweCvUJV6nQOeLJXv8sKidJPTnMJzdJaQsHgV
-aeXrtF3dGU3qmnivrqS1aXhYqn1dngXuqI0tFgOGGGJrzWeMXhMdRg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30EE.pem
new file mode 100644
index 0000000000..cd8f0db851
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest30EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 02 C8 BA 4D 34 CD 09 12 AB D7 FF 9D 06 11 75 8B 9D A3 D2 54
+ friendlyName: Valid DNS nameConstraints Test30 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid DNS nameConstraints EE Certificate Test30
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS1 CA
+-----BEGIN CERTIFICATE-----
+MIIDzDCCArSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIEROUzEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBoMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE4MDYGA1UEAxMvVmFsaWQgRE5TIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZp
+Y2F0ZSBUZXN0MzAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE3efE
+Ew9OTIYxe07PiuyT1xASI18+bk+gPhFo46a4GTv1BYJLzxKlWNQkeb2yHNhHamis
+09o2kHi8KxtgvEQpSItGO3orpoTNx/ag7GZ+uT7pPQX9NI8HDYaaHbU86E5Gf6l5
+xbFV+g5uVIJY1MKV6N/cJ2qAg3o1/aJOg87sXW0q7Xv3QKXbmzlRwVR38QrSRgdN
+r+BIcZ6r9plX8P3ghHH+/xHRfilCh7FWmrruGf0K3w7gudE0RjMTYm7zHOny4fs2
+W802lvgWW0Kls51YiqdjmT1V+AOoyR53SIzwfZR5jY+FsLqr2o0mPk6GbzwS5Pk5
+XBrbegxQ/UrfP4YNAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUsaoX8OPPzNKniaaD
+B93/btoH40kwHQYDVR0OBBYEFEWSz28Tk7VuNoLpo6HEQTpxsHIgMA4GA1UdDwEB
+/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwKgYDVR0RBCMwIYIfdGVz
+dHNlcnZlci50ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkqhkiG9w0BAQsFAAOCAQEA
+pgUgjEi8b3mM4voUe2Wt14cuFOS0YImUvk/Pr53xJiZPLyJkBOVK821wqBKjmmD3
+29NaX9nshLc54lZfqvQBHTEWWBPeO1um94vimYyRNMVxoIuEA8c+a3RGGQndisFP
+2098JFQjdz55pW4NgG26CJNutjMmCW17GmVTEJCiQEpVrRYS0QEaYUZya1yp2Thr
+mQJGt3FyMi+LuoKqlhJsq1892cb10GO0E0Yhy/X33ihpbCXFMs7e5kqYa4oHRJIi
+cScs+CqFDO98FpiQaccUpWlgIbHIq/R2t6GcXgSsK9+JLrJqn2TMMpS5O2Qmy/bl
+AHzuGjGn+nomfAVFRuEZgw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 02 C8 BA 4D 34 CD 09 12 AB D7 FF 9D 06 11 75 8B 9D A3 D2 54
+ friendlyName: Valid DNS nameConstraints Test30 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,577DCADE8158937E
+
+6IGI3x5K/D7d2IXqI/oa2gxu29K3UVhOrBxkBGoZMIxH+IPsN9xUautRc3j8qkxD
+Z84DO2EQd0f/JEYpJuJmwDP9T3UH9HkT5Gaypcwu/h0ZNpHN/9CyOU4wprh1X+AS
+pyFnr+dou8K6QZYnskttevV2rHEZVc8oHjI4fxYCqLOSD3dQYn0QVyvjMfygg9VS
+Gi4jJW6BAyNuEnoA+Fddo+Wu/BeqHMZyX+rKFwKxEVJnfeUcRE6uOiMw8Gv7ojDV
++n1oBdJ2Eo4JG2Jw1IcDBCSHQkCrMQ18HBw7menMEQQgwpIhOsa+vyK3cCI+wDhk
+MGrEOJPEiQOW8SR+JVEM8YTO0qZamveDGKSoPqWrVpMd+cHtvS2xf4cSOCZceDkd
+j8vPMA9CR93IecrKWDGqDuBSAwtFOW0qfX41JhDb3V6TxO2LNwNDsHpWjp+bKNk5
+VUWp4o6jGvu/YjrmUn3LskvNpZVxC54Z+3KShS0ev8BWHpOdFl6DIZ+3xR4coIcj
+AeyeP1wFqAXcw2VfPtZmQDH9f196jhfBGJqf/RYTzXd3uAMT9WRa69Xs/R2CrI00
+5YR6lu7kRVX56s/1WV04J3rY//wnzO+TWRurBgHqfp79eT0AVfdhWjp/VT10lbiR
+Q6UOcQ1IlSdpZGvx14ds7KAo5jTVh4uZhGomlR27sxxPHinS9mRoP8ka6deRI7ZA
+vDlUwkIjLF2JFK/yLVX9fWH0rL4WhoxiN0eMEu5XUnhlFe9oqWQC+hd9bIKwxfSj
+zMgXGg0N42FYbEygq1rNv+lAfqdZX9Y5VSkFyDeVB5+qYOmxCnk2MpFqQm6c6LX9
+9XWzZnLH20kWqBMxMXcEtEiwYZbrJwQs6DGVwWh80DykLuMU4Dm5L2N3gA3faEH6
+lUlBg8g4Z1pBRw8a9kE+6JQ9YOHEZveBQWgt2QxzoGOdo807kwBPkCzZRsMIr7Gz
+AdqbaeU+5XJJtf7MoCNuXzxWHdkbfDK55IRM57j/Smw9E7QE6BD1QEsZyFExWcm/
+z21b83nxae4QL8cCVGoIxCIWRconx0X6uHV/hmONVsuLqvdkJo6kQ1aRXpn9uTg3
+vaVpepV4stT3iKSZAXIbKQ4m3nzURH2Nca7gEJDwZa7T654ySnj9qLM0mLShUxxS
+m2lc0di6MWBEG9/6CdGCfIzoedyknL20cBXFXmNU1ioYyeyaym58dtvTtTqX6zDm
+547uFHvAOTzpuSNI6p4WfN/IC9K0UkxgOwynOtDmBisNR8q96ieVr4ICB64mFHqT
+Omi/qvy7vo9OaQUdEMRapkdOe/9Cu1X5VhjEgkOQA6Uss7yEJ0CBucLlicKGg8ji
+1pMRn+C0UsY3XWRLp0pzNkzdjiyZjr9Tn9+1gi6LMripWuBeMRd58nYriRXqrkpP
+86qNn3iA9VvvzT0QdOkjXeg6NvBghU7JjKYmbSenSNfMwCO94N2zbTieLUPJ7Vrp
+w0vg+lfk8ut/7yDv/BB7+6I/CXUaO9ane9qfs6vw3YNO1dAl5FtQubBPAV2q4Emv
+J9+OtZHp9pvAL+zMK6OHPX6aMiskglybah444IQs2nXbj4IVyyOvO2LsP8vY/pLR
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32.pem
deleted file mode 100644
index 62413ef929..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DNS2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBRzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIEROUzIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANmefIFU
-RUgrahNMyIfzibuPD5LXv1aF765kc/ROx4BQYuBUZehjaB0G3eHv0wGu5rSJbnoy
-Lpdv0XVvBKEai/K+9iIereljhcwZzKTbHHvAdhCtgImX/Zz/KZ7OU4GZJGkdcj9r
-e/szQBEqTWkWB7hT25WM4ghi5xAz1Tn3foOxAgMBAAGjgagwgaUwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFH6Q3Dvq3pzSm0JE73sa
-zW6PkuC0MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zApBgNVHR4BAf8EHzAdoRswGYIXaW52YWxpZGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAekwpteebcTHJ3RTTqNmNlRsw
-aSa2MtBlaOVNyWi/Qsgy/LO5We9Ahkq56VlKB4WTWCFBdrbbnZ4k1Dpgj+NA8YBD
-Ysuq9KofKqycs+alN4JOOMtKHzbm05wPqkhY1qbBFAUbrEm5felp5drbJys97mCX
-bm7XHTxTuImtWM4ESC4=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid DNS nameConstraints EE Certificate Test32
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DNS2 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBETlMyIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTgwNgYDVQQD
-Ey9WYWxpZCBETlMgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Qz
-MjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA374o7AtX/s5zVHxqAws7oJ0X
-W9efE9ztupuhz0gxjrTuRbVoFj3Z98ikVL8RLG00VdWjgbKd9gWB+UI4GD01A7Wn
-M5bSXi2t5fcyVYPxPjzhrl2gW/DfUYO4U6LHtTqID+ARhddd3Xlz/6WXt+gOLARC
-4zuqAsvNuNpnFbI5yA8CAwEAAaOBmDCBlTAfBgNVHSMEGDAWgBR+kNw76t6c0ptC
-RO97Gs1uj5LgtDAdBgNVHQ4EFgQUpTkqy96R+925D9dnz/clmePZZx0wDgYDVR0P
-AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAqBgNVHREEIzAhgh90
-ZXN0c2VydmVyLnRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GB
-ABBLDmNvZzxO6JM+lTiTscA+ikguaFV+BdfdORenOIJYUHV/j5MhzLCcOqh32U/B
-KZqQ9ataMvRSnqfnTHtRCWo19S5qT0QjVjVfYsDfX8QQy2jJ6bI9S5vn4bLO2HUK
-jLOabPS5lyHm10fdN+g59VKHjcBKmkBkngTkhVqVLOxL
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DNS2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:7E:90:DC:3B:EA:DE:9C:D2:9B:42:44:EF:7B:1A:CD:6E:8F:92:E0:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 02:f1:3c:9c:25:d8:e5:f3:99:97:72:47:d1:94:a1:f0:11:0a:
- 8d:ef:9f:4c:c6:3e:93:23:1c:76:92:f7:68:f7:8f:9d:d0:ab:
- 7d:73:20:ba:f8:ea:1c:90:10:59:01:07:c3:11:36:15:70:b3:
- e1:80:3f:38:65:42:77:78:95:79:6d:a9:88:c7:54:59:b2:52:
- 9d:da:5a:58:a1:73:1e:07:78:00:01:67:02:41:9e:82:b4:ab:
- f3:d1:74:00:8f:ce:fa:78:8b:c5:ff:ca:40:ca:88:90:ac:74:
- 78:41:4b:60:85:3f:43:31:7e:1c:60:bb:3d:91:09:df:9d:f3:
- 6a:40
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBE
-TlMyIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBR+kNw76t6c0ptCRO97Gs1uj5LgtDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQAC8TycJdjl85mXckfRlKHwEQqN759Mxj6TIxx2kvdo94+d0Kt9cyC6
-+OockBBZAQfDETYVcLPhgD84ZUJ3eJV5bamIx1RZslKd2lpYoXMeB3gAAWcCQZ6C
-tKvz0XQAj876eIvF/8pAyoiQrHR4QUtghT9DMX4cYLs9kQnfnfNqQA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32EE.pem
new file mode 100644
index 0000000000..b3becaf563
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNSnameConstraintsTest32EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 81 FE 9A 03 53 0D D4 4C C1 A6 2F 85 29 05 F6 9B 6E 1A AF 1F
+ friendlyName: Valid DNS nameConstraints Test32 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid DNS nameConstraints EE Certificate Test32
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS2 CA
+-----BEGIN CERTIFICATE-----
+MIIDzDCCArSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIEROUzIgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBoMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE4MDYGA1UEAxMvVmFsaWQgRE5TIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZp
+Y2F0ZSBUZXN0MzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjO31Q
+u1gnI8gYuBTTqe7O7qzK1fRNCHmFrxovthEckh/m2yz+SwSMCRV3tYWgOu4g/f68
+Gr0+3+0fhwI8ZNlkjvjZG6ZaaDLQejsfSwRDdB8OcB1V6p2EMSxRBGj6ZyTGObq2
+1XCUJhWE7aT4UDw0gZ9Gw5MsdzP9Mm0ZujF+nknrMx5IcktNwz4GrZ+PXDEd/7BU
+ZoosEtzX33b0toggo9LPTKRlu0c5GJqLbb7dCj9nuErxTaR2x9xGFdYdSuJxhlPK
+NwGCPV/RdbA+b5LmhxfBoCNRYsDHc9SGaxJxuzxJaRke7uqNc8E8xiEBb36uwN6B
++P7SaqaFMB02px9XAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAURkicQgmOXVNw2BYe
+4MHJGBU1CgYwHQYDVR0OBBYEFC+f+0RS6fd7DHdf1A7xDiGx5OcdMA4GA1UdDwEB
+/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwKgYDVR0RBCMwIYIfdGVz
+dHNlcnZlci50ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkqhkiG9w0BAQsFAAOCAQEA
+Afn8pFtzg5Eyk7U4Qz9iaw0+eaMiO4wX5iy8CP32AzJf7EJrykGk2G+/ZCJirXdB
+KJHPHqVa1SuIg/I5OOyku3VAl2nsVvR3FbouEDwrRQMMF9AaRAPHW0Gz6sb3DZWO
+gtoAdJgPQukkQ2t1Usl6DdsObESMNM+lE/O3qZBPvAS5FNuk8/GNt/l+7XUYub5M
+q9myI8bAITKwYNH45K/6uahjVM2Hzzw0cx1DINxfg9PxP4wmA6AbZkgLazgwGaZa
+Tv0xkbdy7RaP0nDXXRTlKpPYvplmmsfiYQiB1J9RedeHXsoShC2RPPcEWe9kAjcd
+ZVx3nY9LshmNiUS5XqpLhg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 81 FE 9A 03 53 0D D4 4C C1 A6 2F 85 29 05 F6 9B 6E 1A AF 1F
+ friendlyName: Valid DNS nameConstraints Test32 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6F7A00D5B9CC3F0B
+
+VQl9PFCblPbDF+VKlw/ar0II/RjNtJlFeOvxArEr9OP58NYpTxVdLPzGV5iESA+k
+ZJUWpH09G7OylczvwVJYkuVCscsd26XrgRAsO7uc35hmwo4kuM6fzcitWdX5AWoP
+6k2Wnl0uT3ZrcUHYUU4TmVjqwG040ZO85zwU7NyG0Sr3rBInCYaOHoWPxYI+w0JM
+elxsMi+Vd/SIMrMdRz9bZe6OW7NnVEEF2dyM8v07zgVNEj2qdeky770urJ0ftIkl
+zFMjRa1O9E1uZfFZ+pMAh2MnB9ZLwHYn7k1jaekOzD3pxaM6L6ywCYULDQ6n4Kd/
+tnBHllU1pcJRgCyiuNSDcBRe1LvDSwY8R38afZVywSk7W3PFFOOb9E6OeWHE+cjG
+Gvz9I/Sm5Od5Ub27LHuqeRp58qExi5gTZvg8QrmSLOisCrWti3kEk4sNixSoTSoL
+DS/IiKie0SecB9rba8N3pyyIi/ExgZX2+z06/7Fxk1sY9WWK2WaQzG7oLyBPWM5R
+0AG9eWYRq9PiF3nVTyHfRR5p/XfrpOKl9i26Y0Ve3pjrr6BD9hA898/zuqqp3Z/F
+lQATWWmzdda8rCym3xH/PTlUfWFyX+eCR4sLlgHxga4TU8maMMImGocBMNvFa5vh
+amSpo+vzlBVtKXIQMUHtIEq9+vsiJgMMh8xbikz9/KCnB6QrR+gOFRaLsC1bVUsK
+DL11crzhbVDVLPwQSpbhut4gEuR85VDemQWKmn2jvQ7czdanVv5VlsfURF+A5IAa
+jspxKQs80+zZ5njoTrZog2peuMJZoh0vz7Rn9C9y0IE9KJu6Sd1eF1qgNT+jAFcs
+MBlTvQX+YZpiJp7kzXQAYdSFmDX3ohmttAGtKMrFDPErqUda47s3j6WBiDZpsRLD
+HB2yET1Tey+fyNq2kMWR63v18gAuW5CI6/8CDw/17kH72ro4Z6HpHEhPWF3lax/v
+AknUlI2vIw9YGCDwFgZnC6/FlhI7cURI5FvzPeeDBn6rZVAV5QDyAGGkI35yWOT0
+MOPmn2kwcAcfb2SFEy7hooSTo/PY2ExpS3gYKX53Zd2NyVDq66ccN99C41s29C8k
+1o31W47g55OLO7CRE8QZWZlgEuCcZqFIycqO/kyyCaY1SvZPG+gjhfzNe+smrm3J
+8asBn/If8czuqy81irL+oUYwW6+4q25zJNzgSHPdphFFuB5betA67+gsMOeTrKj5
+QrgRKyINQ1VDtHakoCxvAbdGDNYUseoZN3TR9935MMzjwZl9b+1C1PL8IvtRBwfU
+rN7sqB+EPP3RBMiXSUP9aDexx1ik0KYPLIZCxoj9EJUr87kI5UCfqgO+TAoSdo+e
+vfo5u8+vSr7yKVY0ldR/rJQ9Gp3csPJDM5vy9nsMg09SPTXZyXziMzsVlc57yqde
+qcl/p67YWULRGesh00UbiZCb0hnIIPBI1AmHwWSx8gVRZuI9IFVDJdXsIKT+b5Y4
+P99FharjpKMxkwXms3Jvrc1zd4F0WscmHJ8SHMkHn25PU1L4XuFdESBIoJ1CJlGt
+lDJ7W0CiP/ZuE3VpRzGJml82zHTIyLhKu5iwUVC6CXP0PUG6vv42ipGmOc9jhyWE
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27.pem
deleted file mode 100644
index 1da7bd70d8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIC0DCCAjmgAwIBAgIBCjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBqMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4x
-IHN1YkNBMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aIkV7sYy0JnIQ6
-oLcZr4T5fsXvU6SzOxBfPrtNDpq884ix+hP3zDxAwCSO5mU0znQe9s5im5Mf9yKK
-0FIXOAHFwMb5M5mAZNwn7Tx0XYxDfBx94lsMvJdBDCddmTB5akZgQF5Iir+Y52y7
-yiWRJM+ZmowFfoi5rp/PgkSOJxsCAwEAAaOBpTCBojAfBgNVHSMEGDAWgBROLqPn
-2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQUV6v4nCfI0vTmz2+qIAs1ZwSDJGsw
-DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MCYGA1UdHgEB/wQcMBqgGDAWgRR0ZXN0Y2VydGlmaWNhdGVzLmdv
-djANBgkqhkiG9w0BAQUFAAOBgQBlTO2ECGQPZsbXzVHd/rGejurHrD9MHfTQYJCn
-pFjAPq3wSo4qFVopG5gl9s4rdpNU+XvoY5zO8MVxTnfFi5G+y2CWZTG0iIWQmC8b
-ReqDdpVeAV3ictgaDyoU1ApdemyOS2pHV0mgm7vPYCx+17EXzFBphUICViSFv45n
-cu1nCg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Valid DN and RFC822 nameConstraints EE Certificate Test27
-issuer=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
------BEGIN CERTIFICATE-----
-MIIDATCCAmqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1
-YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMzAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGJMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRy
-ZWUxMUIwQAYDVQQDEzlWYWxpZCBETiBhbmQgUkZDODIyIG5hbWVDb25zdHJhaW50
-cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAL23wxEGImwm+05H4yzrxRQXdJBQp/RrfHB1tjFbPIUzr6hR7T+xNjC+3M8r
-Y//0sOjggeDwLkrbhDl5TK9qQUui3Oys3QORkLfvuBIKjHtzUYfyizTV86KvAybY
-dMOrY8sc5zivU0N9+FESFwg/Kv+meXt0vgL9DSe7PsFnaC8fAgMBAAGjgZYwgZMw
-HwYDVR0jBBgwFoAUV6v4nCfI0vTmz2+qIAs1ZwSDJGswHQYDVR0OBBYEFN3zmdIg
-RlRJJv9aNE/zRRJu9+n7MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwKAYDVR0RBCEwH4EdVGVzdDI3RUVAdGVzdGNlcnRpZmljYXRlcy5n
-b3YwDQYJKoZIhvcNAQEFBQADgYEAEiXPBPlFwaHGZ5TqIDXXTXn8ViKz9zfr1imR
-nhJlqZJTu2TlScmSN4vEg6++1wS0vVxiPiwNQkrH78lRNTH56MQOH92DxRyxF40M
-5YJc2GuFb6+ZkSKVWDG6UbkbMxjaZvqd+jnODcW1K2lBl1jHiv61hoNxe6VrNb4i
-m1dYiFQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:57:AB:F8:9C:27:C8:D2:F4:E6:CF:6F:AA:20:0B:35:67:04:83:24:6B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9a:01:ff:a2:5a:8d:4a:16:d9:8f:d1:7d:40:a2:bc:eb:6f:fc:
- 4d:58:3b:b2:03:77:79:60:99:5e:f7:f5:b0:39:62:10:15:8f:
- 67:ad:12:b7:a6:2c:ef:de:76:3b:90:26:79:b7:1b:7c:3c:25:
- b7:bd:11:82:78:21:93:5b:11:66:15:e2:e3:d9:77:e6:a1:18:
- 6d:dc:46:88:f9:13:7f:28:5e:17:95:7b:a6:da:4a:00:c3:44:
- 8e:f4:00:50:a6:a0:52:86:90:cd:40:54:66:92:30:0a:64:0d:
- 09:19:17:64:41:33:08:5d:c3:11:b5:ab:d8:61:5e:a2:60:56:
- a7:d5
------BEGIN X509 CRL-----
-MIIBYzCBzQIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRyZWUx
-MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMxcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUV6v4nCfI0vTmz2+q
-IAs1ZwSDJGswCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAmgH/olqNShbZ
-j9F9QKK862/8TVg7sgN3eWCZXvf1sDliEBWPZ60St6Ys7952O5AmebcbfDwlt70R
-gnghk1sRZhXi49l35qEYbdxGiPkTfyheF5V7ptpKAMNEjvQAUKagUoaQzUBUZpIw
-CmQNCRkXZEEzCF3DEbWr2GFeomBWp9U=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27EE.pem
new file mode 100644
index 0000000000..4420519b07
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNandRFC822nameConstraintsTest27EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: E4 9F 6B 9C EC 2A 8E 46 DD 98 0B 0D 37 F5 6B 26 15 4C 2D 48
+ friendlyName: Valid DN and RFC822 nameConstraints Test27 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Valid DN and RFC822 nameConstraints EE Certificate Test27
+issuer=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
+-----BEGIN CERTIFICATE-----
+MIIEEDCCAvigAwIBAgIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0
+dGVkU3VidHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0Ez
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowgY4xCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJt
+aXR0ZWRTdWJ0cmVlMTFCMEAGA1UEAxM5VmFsaWQgRE4gYW5kIFJGQzgyMiBuYW1l
+Q29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDI3MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4YwJBaWuiNbOXsrZHR50iYNo/KP34QUkqySEdyVQ
+XRYjgcVtLO5sRCeH16qBeglO26DxAouS1ofdzD48hjMWLKzNwAumWmrQhkhtUQhP
+EA2ABxV4rFW2fKm+jjWmPNxhLWceJED3XEnY04pHfy83gC8YDgPQeqRn7gEdQbaf
+tgUT5/yzBii6idSbJwWwNtMho6/6a6DabRtdXlz4h0hg4OCPU6aPUuIEa+wupnnZ
+ac1Rl+XSZI9gt0jEMh99WDpi15o6QpItW/aPxiZ6uokdAds0DEEik5JsbGRSzLNZ
+JbiLV5kOQgtzyj/GQ4HcigW0k54UQWx1kjj4YwsgYvpOTwIDAQABo4GWMIGTMB8G
+A1UdIwQYMBaAFCdJ5ATZRfpsmJRs/O0NwyRSbVVEMB0GA1UdDgQWBBTRTIBGyj3H
+PjdjTstrMzXkvcN4pDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMCgGA1UdEQQhMB+BHVRlc3QyN0VFQHRlc3RjZXJ0aWZpY2F0ZXMuZ292
+MA0GCSqGSIb3DQEBCwUAA4IBAQB5K5dCXwefGo7l2SB8szQesEoMosZISkK5QRIm
+xxHkPMc2snn61jVFDOVvL8muOL9hSNPBiOHBNnXC9mypo14FEfQRI5FjLm8MViWp
+doY5fn605DBnB5Cpn0gcwB/MlPe/TDbCVVON8/NNqWqyVZ0y24wF6LLjYaHR9QmV
+zdlMfljjO/gJVNxbhad0GL5IqMTjkUgAIC0z+ubj8M1BJb2qdIOk1v20syn8r9at
+iN/+SBwawEpSfVR7K+GIFL4xSjPCqHytmSMMCX4HkGlCw5rlJulusIvt2tc97Npc
+v2KJSeZ81jehHBt7sUVqV/DgO2XIrysN5qKcD3nZs59qx5YK
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E4 9F 6B 9C EC 2A 8E 46 DD 98 0B 0D 37 F5 6B 26 15 4C 2D 48
+ friendlyName: Valid DN and RFC822 nameConstraints Test27 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,72CEB87CF5E919A0
+
+1kIqFRDkRsg9vR2Y140zuDWapk182kj2r9IZoE9dBx9TEOA19bs0GUqsZRE/DpVZ
+44bOzHVB913aL7wNEK4vEZD3tf6YDu5aduHPM5c3jmzNu4FjnGqby9kZP5DIiGRl
+7H13Esg+8a24sP8Uax1ypHUhhzzvwn07tpVrgpyf5xYyDcgJU/u5REaPq0xdpDH6
+A509+sAyqFm+Yq73NO7OE0czQlm2wyil8c+ngHvrNdD3AaJYhNz+tCy2tq5RXlrZ
+5OYSdPKz7P7y+av0JYki8L5HWp9QhD/qTjeUDn/v5JTD/QV0QtWKVrd9rJqdbAMR
+tGSAlB3PY11hhNq43M1/fgRYwzjqTsBPAjBjmtiWCu2kfqm7v59nOfljbsinbjiZ
+tziKJn7Ep2yWPOv5f5KqLywNU21IshuyuM2JWPWsnDkG+jldkS+PITCVZ1dkJooq
+po6xC4Yf2iY9JUy5zdXdUe/eTaLlpbM6e/R+rhHlfZo7MeyFxdiB5fJEA87T3txX
+hzuDjOIN4HUqND22mCcTwttRki8JJARcZdxPcZXWX65hPpoZh1qXCP7IC6YQ7Ck2
+gZycbr30JLPAMgXCNJvAwduDaU6R5wkI4KYWGTuGodfu+ELAbG1uYKHmf98++HFv
+o1ewQgshmK7fc/Jg1WgFISEu0aNMxy7u/llxzhsK1nWllVMULQ2RkjNkEfXcZB4H
+9m6KJrK8l7T8OSfhJCWr+d1JIso9Nypv98GpKKyq/rbbNizGqoXe7xPtvTjZF8gc
+zAy2ksJ38Kd8W2bxW+pzfsn2oHjyQAgEnyas87zzF1aYW0oVNwQ9LtCy9vgkJdY/
+KM5UPQIo4HT7kioz6RY+3ILug83cxblnM2Iy9ivwwMzvl49N/DIKSXtgntsbzNj5
+EaNMiQndpWTueD00hI3rSpzWDa43K30et9xVkqD5Ypg+pkwVg+OUeZl7jAfCtBFP
+6MOw8VADxerbKTFUSfJDafYA437Zs/34fst3FFCrp8WmNjKeFvjUrnQptv5epsq+
+BFp6dkz0w1VcHNJdVlp2WLtrXb0SRFHMlVsYduN4iwY7bXTewx0BDJXnIVADymsI
+OHykdXEnSxfxm4SephKBKEq3Ro71EOt+P/qLrnLxh6p+8RPbt7fr505QaKqSLO5s
+Znz0daEKhG4G2Fc9oo1YjSdqbTAZabI9o/TGIPF197A87fvjjwHbc+PLkldE++Gb
+x+nG2ufQAGmqepJkbzPNdkhDGtrr35lLqUXkPeX6MZNf+fdK6zCmAyXflyboSggN
+WX+5s4V9KhvMtsCEiiGDfR3ULzxRIdJgtK+In6YwfoXAdOdN6A4MIvnxSQnXy3Zn
+ttKsvEsCuFVnFA3axJuXYj9O+f6O9/I0GgQGyBNj28p8c+YZtNfW23Ct+In617z2
+d556AQI727H9vO9N2EwEeg7IuqVP3IuyrVXSj+jqss0LEkXOaaN4ZhqSkLybqCev
+xfpVV7z7u4dIrmX2GarKGJmwPalwpKLH3Ado1x77ZjxZ10y9RuvZrgVL65rP5qqf
+3E/ADVTPIdfw7CZIBfb2sSlgEKYZs5/iFHujqwEIl1rNiRPP7fJzvlcXpC/kixgH
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1.pem
deleted file mode 100644
index 45a7bb6036..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIICqDCCAhGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB9MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMTYwNAYDVQQDEy1WYWxpZCBETiBuYW1lQ29uc3Ry
-YWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBALJBCTy1/LSNTMnBOuzrGV4EuZM/iXN4/m+w9j5uwlLzfyPGdceIOSA+
-vOAPdr/9ralb/4Wvr2H7ive/ruSrj338JwY50O9BMowjNWiBs+G30rUMo+lFNoHV
-eUfBE9TZF5MiZMRPH2UiH1QqCHSn8Myeb19XahMyIfCVqISqwIEPAgMBAAGjazBp
-MB8GA1UdIwQYMBaAFE4uo+fZ3YungjtBSsOefFkjV05TMB0GA1UdDgQWBBSa/kUI
-iD544eivJJmZZwWNNFasSDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
-hkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAGlp4H06BUnD5PHzz/2nv9PBE7Vc
-UFLCQzhBdC13Ml9hLy/5ZLFWjlxnMKCuL51OVW25ocoUaUubwgvi3crDc4O9p72W
-xYXIEa7PYpuPadAEOKbdZJNB0X1aKWORBpaj6yiK48WMG0UydqIZps0wcfAP3HwK
-yZa23hxUZyeu9lkv
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11.pem
deleted file mode 100644
index 921ee94669..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11.pem
+++ /dev/null
@@ -1,113 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/OU=permittedSubtree2/CN=Valid DN nameConstraints EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN5 CA
------BEGIN CERTIFICATE-----
-MIICxjCCAi+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjUgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjCBmjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQL
-ExFwZXJtaXR0ZWRTdWJ0cmVlMTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTIx
-NzA1BgNVBAMTLlZhbGlkIEROIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0
-ZSBUZXN0MTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJlfx3jHiQnBHgwQ
-XhHjF5QJIB+q+2Mc2w6gHDzym/PiEa5utF2eNcy1cskZiVaLmODreo/HtQpn8Iv+
-YBfTuMT3GDXVTpPFfhVvtm4c7xz+e8QcJhK5TapF4kA4ejKPY8/JzpEtMvIS1tbt
-w4ZQteFe2G55WqBlnMnwK3yQtphFAgMBAAGjazBpMB8GA1UdIwQYMBaAFBI1n6zB
-uaHjOv7xL7p3sghOTVntMB0GA1UdDgQWBBRiLDLb16WReucmARwbU+K2PP+CPjAO
-BgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3
-DQEBBQUAA4GBAD8UOLijF/GmDv8mf/f0lhyLAbW8kylUTYgCUJpSlOL5pbtDoy/d
-9OGqYA3uzDmQJxeaW2dzPwxOjV1IVBVFjA1yBiOpxQrLhc4vDGnVBpYfcvVzy1Dh
-0jntUoxeVGCVSTd5DX1DWqzfQcOvEP3kiPGhodlCrY1udMFkLCuleB7B
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN5 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDRjCCAq+gAwIBAgIBQjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIERONSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxmMyGO18
-wxt7plFRZcGPd5GxKiCL+NJ+O/UB82qQ1+GhwlsBTSo86QNLh9KPIjs3rrARYIo0
-FqA86FPnpIiE/yWOfuQOeI3t6yvWf0XsXvcffhjW6n6sErOqhXX7voiJODZMseiM
-wQ2Md8CcE3j78i6crfbdO6xGp2xNX63VmkMCAwEAAaOCAUQwggFAMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQSNZ+swbmh4zr+8S+6
-d7IITk1Z7TAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wgcMGA1UdHgEB/wSBuDCBtaBLMEmkRzBFMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBl
-cm1pdHRlZFN1YnRyZWUxoWYwZKRiMGAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExGTAX
-BgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTEwDQYJKoZIhvcNAQEFBQADgYEAp32j43pb
-BqBj+2V14kyvmo+pgQ9H/ag1zf7WG4ei+McEkF7yvHSC6nfXJA19r+q2fAnvIU4M
-TriscCGq9oE6qzd3VIQ5wx8eJp8v9SG62gxZe3n1A8gzG37TvTwBOeEgxOKBa/BS
-8MNUbMO2SJwuE2pi9fnMhCgx9JxUQvQLou0=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN5 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:12:35:9F:AC:C1:B9:A1:E3:3A:FE:F1:2F:BA:77:B2:08:4E:4D:59:ED
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 74:3d:76:85:10:61:c5:e4:1e:19:16:23:27:99:ac:bf:2e:c9:
- 07:40:7b:fb:45:44:5d:c1:6e:d5:5a:e5:6d:35:d1:4e:9c:e1:
- b7:21:0c:2a:7b:7f:27:ed:9f:f4:59:15:1c:67:1d:4b:8e:ca:
- 19:7c:a2:78:22:bf:28:67:31:5f:bf:f3:73:73:ed:c3:9c:fe:
- 2f:16:56:80:ea:ec:27:dd:7a:85:15:2c:e8:fd:c5:80:2d:ad:
- 36:ac:8f:39:5b:d9:79:ff:54:82:c6:61:37:e2:b6:07:46:8b:
- df:2c:86:2b:69:ca:d1:c3:71:4f:3f:c7:e9:4c:c9:23:85:85:
- 19:9d
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjUgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFBI1n6zBuaHjOv7xL7p3sghOTVntMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAHQ9doUQYcXkHhkWIyeZrL8uyQdAe/tFRF3BbtVa5W010U6c4bchDCp7
-fyftn/RZFRxnHUuOyhl8ongivyhnMV+/83Nz7cOc/i8WVoDq7CfdeoUVLOj9xYAt
-rTasjzlb2Xn/VILGYTfitgdGi98shitpytHDcU8/x+lMySOFhRmd
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11EE.pem
new file mode 100644
index 0000000000..fce83db62e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest11EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 42 21 9B 4F 53 30 54 1E E6 BC 4C 2E 7E A6 DC 7E A7 74 74 3D
+ friendlyName: Valid DN nameConstraints Test11 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/OU=permittedSubtree2/CN=Valid DN nameConstraints EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN5 CA
+-----BEGIN CERTIFICATE-----
+MIID1TCCAr2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIERONSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGfMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExGjAYBgNVBAsTEXBlcm1pdHRl
+ZFN1YnRyZWUyMTcwNQYDVQQDEy5WYWxpZCBETiBuYW1lQ29uc3RyYWludHMgRUUg
+Q2VydGlmaWNhdGUgVGVzdDExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA01aMPpsarfXTbYAgFvrguR7kpQFB2n1BkbdNNhOcH46ur17thybR4gMhgKVy
+ILcpweStTS146Ezc4LjdRqKH51Lr/6QMfRF78siZfrAjbG7PDHmyX1XS1nYpdwnD
+nkK4Ajzj/CSYEzsASZ0vUt9fjEWGSBjJy2G7GAD4CENSnK9pLStCJiRrOQBNljEp
+i4USasjteKMMsmObpi2UN6i3PaypjubH0quqEaTd1T1okLsLhgZSSFQG67toDyln
+YggwV9KYiQKlBgNkGESKaQ+5scY0yGmpL41HRdehDEyRDfyhGTld8TiOkDBWI0M4
+D0UgdKsEtl266bBheQ72ggr79wIDAQABo2swaTAfBgNVHSMEGDAWgBS6nwnKkDmc
+Tnda6/sQlazTp0pdJzAdBgNVHQ4EFgQUEctmOQ3qs8HYJEuov8tpKBE0oKQwDgYD
+VR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0B
+AQsFAAOCAQEAymcKvWtG7XwsLtRjAAyciN0MvZNaF7nyKiPuY6YjdB+N6DDUwGEt
+N6yPWHIsTGtQ2QbAGoYivFz0uS6bGAmepNcjay+oGsL5pEGV9hPcCqL51FvFt3eg
+w6m0VoEOS6tvmQ9Xd9eKSRtyBgBwVwTdvhbw8qhnh47+F40MThIUa69/Zec1Ihem
+LcGAbdvzLOw7vAdu76gNHoECHEtAx0DntWVJqhHHD68NOtFeWCz5/582KYaAhcK3
+XVPMI8dkSN9vFkUCYW4A+GfXflQFj3IT+qfhfLhu8Xvw8yfr535h0ollM6dN3OaS
+DTwwkN/wHr0evldYdBGOiU44oD0CBxYGUw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 42 21 9B 4F 53 30 54 1E E6 BC 4C 2E 7E A6 DC 7E A7 74 74 3D
+ friendlyName: Valid DN nameConstraints Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B3836AB766A567F9
+
+CSm02WNdI3uzaWtp0BoPy7mdRqQSQwfKgfkYMUO/x8sO6UL82kbm1rHujYf4exqN
+ix8b9bsX7pm6jwL65t6rev7RYnobUlN7UevjKt6qgxTqSvRh2UEmngYcdChxxi5E
+7GBYiJsClbB+FIwIuTMkxjTqH2IiawKSjKaG8uMDYa93/qh/LrkvjlVVDvocdKwQ
+sTIsqlh0151Qib8LcWbNm2yxuGXyMIb29rDn5Kxua8CWrXyJJWOvT/DA6yCBpmK9
+l1uKGUnz0QFy1ut3exLjdvfreAffGAppb/Jax7SHQevMOGPZognQViZudRkq9ryV
+Q7pW4HkuzbHOrRaBSs/gE9mdA1skcFwxTcBQAt6lfcr8r+XFhv/1QYzu6pW3jJ46
+B00O6DWLlW2eKK/Zu4RUvXBCU1rO1feYMe6yp9JXsIresIgSnBfdsGVqBh1OPINQ
+vHgP3ZHjhgH7qGir3fFEuRyA3xo7oOhp5VjdFfKJcBpanzyYycYY9NiUAH6GZsWg
+mvXjCxI69yytzlJ3ueU9Bup6oxE50vFwqnIJ7oXnBgDsKz0irOUolixEPkwmCCeI
+vYM1YD9+6chtYXeWpoNIQvXlwpjYkJWd44FfTB7BJ9TzNIAKkm5GFooRfOcMxInb
+mGL0QVX+bfSv2RA9FzKREBoNhmQ3OFp00ZKy52EENq1YlQPuIxD0ZllmFZTd1aw/
+uMqT23JNznL3W1FWoZdUSSr0BnaHrLZqvxFk4OAha4UMtsjbhEsOEQNV3XyORYnd
+jjhTi9vMVIix+VttltI792klVHfrDVbCD0ZTxf5nW1ymCax2FxHLhe7lreKuFCUE
++lve+uUHxpU7JG1XI4hjeGOTGw6YhOA5z24PMnND/N7UqWPa2LQdIxaiXYW1vVkW
+iqxFAzdE7r5xCHIYzagD6kVY1MI0sDC3wSpXIfF57L18wlak3ELeYDcWhzyFtsJs
+yMn8ExnimlyYs/HBsXQgMm7EjB8qkYhMK5HhQiiM/xJTVcmYpLQcJqt6kCs+vlII
+l50YedYvD73x+CdQ5efYfnPce9L0vgWywLB2T6qSfp8NfdRHiOk6KUop8cSgcwio
+NFH5AwG9sbgjKK40D3cdlfO2rSLoCY99z0GNiNeIYw1U+VUp6vazdQe2kKGyuYHE
+1h61rHfyFqcPEgYRyWeK6figj947UVSEypnBFiSDrvMKLD4CFMShbcwvvyVlb4P8
+RU7+JrFNbGyQrF7RnLKLaty/JYTz5z2r9bb9g1lOK2PUmXctu39iCfBAycFHGrek
+kqyIXLEt2a/XMCealugdsD90SNgzP+BWIGzRRNW+7OR486BBfdgNHv0xL6+LEU0F
+qzLCUKVUulNJ+UIQf8mjhsBB8z9U+EpM48ETP+Rp1yO6JdGTPuzQl/b/7yDeoTRN
+o6asqYCx9+7/bDwJgyU10J3KXpi/tVtOs777pKxUIR6FC0UrqQtf6bEkbEdFw+yL
+R8y8rjca283yMsn6Lyefwx1dnFc83UGMKWuYm0Y3ptDHUu6y5n+C6zKhoPctPwBu
+wK5t+8ZOw6XpYgBadRAKKCx7slNxhS82eLRE0CPJaSz8B9dIAUSXjkVGGU8dMTRq
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14.pem
deleted file mode 100644
index 320f1d446b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14.pem
+++ /dev/null
@@ -1,165 +0,0 @@
-subject=
-issuer=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1
-YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMjAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMAAwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAK5n11EFLCX399YnLoDu+WMSsdD5RH6rHhn9p0cp2PAWiwDuXGka
-pOpn/ZgxpgF/Ydw7ASh9/R0rJD0EfAG7rADF6j3ECZntAJmdiO7euB16HhemfpVN
-ZRiCcehJVtTK+G3vptIsyPFsdWYusjaRHdEniqEv0+rI8ZdP2RBn/pn5AgMBAAGj
-ga8wgawwHwYDVR0jBBgwFoAU1a9rKA2drUhsDIIq/9JoCS8UbVcwHQYDVR0OBBYE
-FDv0z/QxqCSlpmLnB0ps7mSrkwUoMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
-MAwGCmCGSAFlAwIBMAEwQQYDVR0RAQH/BDcwNYEzVmFsaWRETm5hbWVDb25zdHJh
-aW50c1Rlc3QxNEVFQHRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUA
-A4GBAEfjsvrVypBwFe1Fa4RRq10LsqrrCLc1NPiFR0B2yliqIBq81FAJcdEDNmZq
-D8C5gctYTrk9OgXYKgTzUkO8UGNtOYhDPrz1LyBnpND5D1ggYJe+xur2EX0ilhDO
-iq9+08Vo59/dYFQlttOeyY+LJMNzWqQAxxtf3p89oTOgQfxW
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIDAzCCAmygAwIBAgIBBjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBqMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4x
-IHN1YkNBMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAteRgCqKcIeCHmYMc
-xyzmM+fCjW6MAEl+OFQ9Q7UJ1n9YE0TuaGiSxjTkrTXwDF2JoDwMtC6FoqnvEyEk
-kAxNlM0oiLhRxM9FcNCow3VK458jtPozrIgd/7PAP+FXsqPanD2DRYj4c1gNKSl4
-U/l6HyTj+yV6ax5EkPgQDLQlJksCAwEAAaOB2DCB1TAfBgNVHSMEGDAWgBROLqPn
-2d2Lp4I7QUrDnnxZI1dOUzAdBgNVHQ4EFgQU1a9rKA2drUhsDIIq/9JoCS8UbVcw
-DgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMCVVMxGjAY
-BgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0
-cmVlMjANBgkqhkiG9w0BAQUFAAOBgQANN5YtrqXFWfdpK19qY+rn50d/fYdLaOU5
-dSIAqmnB5woTCXdWF0LUADF4DkPfcWBxbE36lwBuGXBfiInH/5yLRy0Y9cZbtHSg
-QwTIf2a+38pR6QyBniftVBmBTuhO/PV+/kA8gKAZ6X4+vGMv69YjU9avYeS1o+XW
-liQdX8l7vg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D5:AF:6B:28:0D:9D:AD:48:6C:0C:82:2A:FF:D2:68:09:2F:14:6D:57
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- af:f5:73:47:0b:2b:ce:c1:5c:82:7a:07:ed:cd:ce:55:02:85:
- 34:07:7e:46:10:13:e0:94:7e:8c:27:9c:f5:52:89:55:5b:fc:
- e9:08:32:b3:54:75:03:c0:ad:8a:b7:e3:fa:5e:73:10:90:5f:
- 26:ca:6e:1c:e2:68:e4:99:4c:06:38:3b:56:25:ce:82:a5:7a:
- 3f:0e:c5:a4:78:8b:19:d2:fc:a6:4f:f2:6d:d6:12:5f:69:03:
- 98:b8:00:c2:0d:4f:9e:47:fd:66:3e:ac:e4:fb:55:f3:4b:bf:
- 42:54:ce:46:a2:5c:fd:c4:5f:d8:61:5a:61:9b:a1:2c:af:0a:
- a2:2e
------BEGIN X509 CRL-----
-MIIBYzCBzQIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRyZWUx
-MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4xIHN1YkNBMhcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU1a9rKA2drUhsDIIq
-/9JoCS8UbVcwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAr/VzRwsrzsFc
-gnoH7c3OVQKFNAd+RhAT4JR+jCec9VKJVVv86Qgys1R1A8Ctirfj+l5zEJBfJspu
-HOJo5JlMBjg7ViXOgqV6Pw7FpHiLGdL8pk/ybdYSX2kDmLgAwg1Pnkf9Zj6s5PtV
-80u/QlTORqJc/cRf2GFaYZuhLK8Koi4=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14EE.pem
new file mode 100644
index 0000000000..a5b3563154
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest14EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 4A 58 B8 8B 2C 1E F0 A3 50 1D 80 57 5A B4 9D CE 6B 94 76 59
+ friendlyName: Valid DN nameConstraints Test14 EE
+subject=
+issuer=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0
+dGVkU3VidHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0Ey
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowADCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBANL44jTyFq7QAleicaquWUZlfqoETqCeRuZqGndG
+rpYU1yDVOmaEtITWmCQ22VaIIu7+IaIeFKNyoU0ELLvkWybmC4eI/uI4pFqQgrvS
+J+lJbD5jtlLcMNAUf78gd0j3bie97KHei9ipYaZtTUD9RD2CKSdSifI472U5ytsQ
+TytctM9miZpgin2XhaqgLIdV3KnrYzXCtYLoegjE8pOTrsYKOURylSDgtJsFwa1P
+HRwFQvPhhguTUGB6kkPGCgrqoyV5PfXWGSCvkaN+LrfNIqzL2x6xKoXeY9RaTXtq
+t8J5bkv2aI/SxH6x37wA1MiU3zuF+MIlMT2LAs2e+PixXx0CAwEAAaOBrzCBrDAf
+BgNVHSMEGDAWgBSiL1iDW0yVl7fu9oe0lw7gf+CXFTAdBgNVHQ4EFgQUXy6VFzDx
+TC6AfvMa6q1deaLwOLcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZI
+AWUDAgEwATBBBgNVHREBAf8ENzA1gTNWYWxpZERObmFtZUNvbnN0cmFpbnRzVGVz
+dDE0RUVAdGVzdGNlcnRpZmljYXRlcy5nb3YwDQYJKoZIhvcNAQELBQADggEBAM30
+T0niDNwc9oxJTmAHuLnIH4LSgOfNAqPC+KqoyjyGmZbsL4bOjpv3D/nvv3cOkuQk
+49bygt+lJsDonEKKYBz4L0jnGOZjC3d8UPu80v7nUkB1yzMaZO+A05rNtxA/iA6o
+t7N0RsDosn2Fu4q+77Dddx1JYp90XfglW1pXj1gdgrwAMwrweF/fDlAMPs5h2qGH
+K7EXhJ5sSToTsEIPVAoLiwDK6yFcCGyui+7koxE0ycDHsDJk0bqRhQVJDKrg7peh
+PBbUQT2g5kNNKu8gCB3UQcyn9K9twWAizjW9DNub8L0wsyttyaXJ9k4QMyO4x+OL
+E5sd13zm4Tfjnw24VUU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4A 58 B8 8B 2C 1E F0 A3 50 1D 80 57 5A B4 9D CE 6B 94 76 59
+ friendlyName: Valid DN nameConstraints Test14 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8EA248F19DC1F227
+
+7Wv/sIjaQUUCWAHs+it1XCJvgYdX0EpK1qXj66wXzUhTbmrHkax3xGe/VaYsmdd9
+o4lUAJUhIUrtTwayn/uZl5f6H4BY4q8baU0XonoFnPmSZ4q3QpzVMq8FV50+3hWq
+mmKD4yhcRchNRKB5tvjC2IZXW8gyQJtaeZgLKQuQSfjXMq5370lLjC1Ri9HAQzqR
+vTxJrI7ShudRoRhF7flg1tV4StDYRMxcK+38k/QoOCtkmwLJ9ASUPwCakg70dRCF
++upuRKLtVe0M/wujFU/tYAQI0+kNdCXc/1YeRUdUD4IrOk4TKi1f6pDoL9hL7Dnw
+Q6J5hh8CFKqzsIvPPNCm4Jo9D9oDktT3ERlKETWRIdvy37UE8lLXiA73JoQ1srkp
+NdLrOb3U7/IoIQSvcRbkg/KNJfgtQSCw2l4oj04ShXMRrCbmlUOEIOAVaCx74Box
+4ycUakWciuEJSIsQ1Mh/H2mh40dWZh4iZju3tk33N0YKzw9azhLUdpCPF+Y0H0sk
+rROyKWKpqxNsft/rCuZcl1I39CFzUXqxRNSbs7WlKOOuh/6qQv1Fpg1AvIT3v2Rh
+SO26RVc47oEQPEK1C2ktnNJRqhCCslm0qqoofnQolMKSfC+3eI27NuvESGkgafcW
+WFXbK5Mp6xGcjE63w5KmBZw/0DnUkmuJoj0hxawAbfxU7dackLn0z54VrnzyuDbu
+2CRzVQkVq6ptz+qQKSvOIYHIzmZaFlSr0MGXR8CJSBNhFG4By8azOmtlIKF7HGG9
+JrZSgBw0ep6I7h7MyxOUEsji4MUPn/+3S5h3UL9Wex/gqXYwboeN4Pm1Pbk03aUR
+1urrLNcmdBWMa6Sllbe+oJaneFM3Ci908cgUOQ218BgyZJYi/Dw5VJPicrcdmmbn
+LkbAW265R9VkDmemyqRSyFHdTwMnH4NBx1fkhzaTX5rli00pK4vd2AG6EUkBKKKe
+eJmoUCtWlXINj66Yl417QpuM4yPGF51Q31Bn30pZ97RZGEeJWNn7vcuIQxESM/4/
+BKsBA0CKqM1wdKz1Vi/Cjb87zTLGgeS90rHBOa+Opr06J6qzH1d7xeWTMBCMkUCs
+PpI10QWEdE/pR8/gXhtPb3Au5s2iWFmPeeAz0QlPtGNogeAMZGxOIJDCSqaXgtW2
+rTApmIF1fmLxrnSIA53YlCO0ZBq/y5LBWn635UjJ4gZtE1Ct2vzx1cCVAVreanoy
+Q/+u63XRe+cPDsNdpUpVhr1giRn9PzU92xRf/Qjh3dp80qvnYCyZrgy3Dxf2cxLh
+aSANrTIiZI416dHI/c4sszZAoqsO2uAavY0ll1q98PTIFx+gXo4Bz0pOW3xs6YA5
+eaWRFQbL/aiYzz8RepZJOv4g4LmFgX71OjSOA6zOW88yiIUfoPKLfJt7K7dGvNFR
+zl3DUieK0MoAnyfKtPLRPqtCfWjxSP0cyFYdiQp1W7Ao3QiP4sAs+bqncz/jXNcV
+iTxvp9WH8NJ6Kpf1h3AzZgXeDd9B4M/g1EHRJH/2uvbf8BzYKAMGOXYThsrdTbXp
+/cm5998qRWj0F7C9B9FFlJbK/bA5DIR8gLVusSbdLIG5kKI9oH2Aiw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18.pem
deleted file mode 100644
index a9762440d7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18.pem
+++ /dev/null
@@ -1,162 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid DN nameConstraints EE Certificate Test18
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA2
------BEGIN CERTIFICATE-----
-MIICkTCCAfqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBETjMgc3ViQ0EyMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-YjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTcwNQYD
-VQQDEy5WYWxpZCBETiBuYW1lQ29uc3RyYWludHMgRUUgQ2VydGlmaWNhdGUgVGVz
-dDE4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDB4Ppc8a/vNVYqFPhznRZF
-lo/ecz5fZXYIuGCaozBBsqZu+6JFjbrAbeA6FbCKH/w1WFNPPTTSvJqSqN4Lw1yG
-yeTCfJoFyUA1wbNUKONsJQgYoOLM+KIuBUpfhZKtHzLrk+NKoCz7pWo52Wy5aQ0A
-B8St+URVVzDNk8Z5+mtaYwIDAQABo2swaTAfBgNVHSMEGDAWgBQLSL4ocWpIJAo8
-4krUBSri1x417zAdBgNVHQ4EFgQUzsfJblSrNLQ6e4Gq3J4kw3O7LYQwDgYDVR0P
-AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUF
-AAOBgQC3FQqH6qw98Em37v12rhcPtdOIRWZPs2z9dGJpRJHDBzNoWr2t5pxwnBhZ
-L7Wy8uNRTy6iTNLgDPIPP4sXYlphcnG2SLe8APJUcTE80aikRwFcht0SO+lpiUhn
-FTrjSWJELeehius13WbzhA4NKTjleW5zkvh3mTYww5msepvgrA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 subCA2
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
------BEGIN CERTIFICATE-----
-MIICyzCCAjSgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMT
-Gm5hbWVDb25zdHJhaW50cyBETjMgc3ViQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDCH3OWCAvPFZXpNTKMN3DoOML+FK32+icT19l0MQXIXBqoJyw8qF2z
-xcl4ahdLxfSFpf8OF3ttKbzN5fk2/Dxue6beAMs0L1r4VUilJaUhOmTMrlYXB6UI
-QX2nzlu6lZbNrI0VFt8qM2C9CdbG+2ZQuJQQO0BtHXWJC9el4t68/QIDAQABo4G8
-MIG5MB8GA1UdIwQYMBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMB0GA1UdDgQWBBQL
-SL4ocWpIJAo84krUBSri1x417zAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wPQYDVR0eAQH/BDMwMaAvMC2k
-KzApMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMwDQYJ
-KoZIhvcNAQEFBQADgYEAV7W8Yarxgw2gPgl0gz1Vz7IdH6ZbzLBpsB0W+gyPTd+R
-toE/N42Efda3DIG5BoxqTj00uc9j2GF5LqBgKaEieenzkv5E6qbTrZ0F/FdX1c17
-DBpRvkchpd4FACNL+FhSq824LEKdBDOx669LmsH664nk6NSPtv04LjUxa+822aw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2DCCAkGgAwIBAgIBQDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAti5Odfo3
-pSf6p8iGjNMBwSlKozpyyMbXSxEjpiDvuZpllmjLqoXe6tiWiee19xCly8MnbxXl
-4Pc6BglZNZd+adRIlPrFUPIVmBM51RJLvzQKjiTRPwrPwsJnizD9KLcr0Kf+e9Gi
-LHBlqZM41/0oBCVuAX/5Y5zNNiFhFeOnkNECAwEAAaOB1zCB1DAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUi+O4WFafA2rfPdgHO7MH
-NuHLtsowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFgGA1UdHgEB/wROMEyhSjBIpEYwRDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBleGNsdWRl
-ZFN1YnRyZWUxMA0GCSqGSIb3DQEBBQUAA4GBALkukW5Jb4GxdEYN7MeIVxnZX8fn
-4Ulh/l6uDFKi+R8UZyMWYp0oi5F0sYQrrsjBwpg/ivfpJtxLh1uMEAWp98vMQPFZ
-Hoo+ma1Ulfh6qAGv8C6EgA5sxWuNO0VrZsMbNsQeqVLXKvkBsYxrUAHXBd5ufqEA
-Wofw3VBcFpqgolnA
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:E3:B8:58:56:9F:03:6A:DF:3D:D8:07:3B:B3:07:36:E1:CB:B6:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a9:3e:f9:c3:5c:b0:eb:85:59:db:c9:72:3e:b4:2b:30:6d:22:
- dc:9c:9f:fc:8a:ad:9b:1d:48:b0:19:9f:47:3e:d2:44:6c:3d:
- c4:6c:03:bb:82:6c:26:85:eb:7f:1d:9c:48:93:a0:9c:66:25:
- 85:b1:5e:fe:71:a3:d6:2d:4d:c0:cb:3f:1a:46:fe:ea:31:8a:
- db:d2:1d:f5:0f:b3:48:ad:0b:48:0a:b4:19:cd:e9:c5:5d:17:
- 6a:3f:f8:bc:99:39:5b:29:88:2d:7d:0f:b4:be:94:e6:8e:a1:
- 7e:12:31:2a:46:f9:3c:1f:d1:c2:69:c3:be:62:f4:bb:b0:6b:
- 16:a2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAKk++cNcsOuFWdvJcj60KzBtItycn/yKrZsdSLAZn0c+0kRsPcRsA7uC
-bCaF638dnEiToJxmJYWxXv5xo9YtTcDLPxpG/uoxitvSHfUPs0itC0gKtBnN6cVd
-F2o/+LyZOVspiC19D7S+lOaOoX4SMSpG+Twf0cJpw75i9Luwaxai
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:0B:48:BE:28:71:6A:48:24:0A:3C:E2:4A:D4:05:2A:E2:D7:1E:35:EF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c0:0c:a7:28:80:0d:2c:71:66:4d:67:82:ec:c7:30:4f:48:29:
- fe:d4:20:82:f2:5c:e6:ef:24:8b:9f:f2:b8:c5:3b:e0:86:53:
- f4:b5:fc:67:db:b2:1d:45:77:8a:78:47:eb:63:bb:43:b8:14:
- c0:05:ff:ca:7b:d5:1f:fa:df:e7:7a:a5:39:e7:00:ed:4a:d9:
- 6d:fd:d1:78:a1:44:f0:71:f4:89:4c:52:d5:ef:99:5c:59:eb:
- 80:c4:5d:ed:48:2b:5a:55:0b:d1:df:4a:a5:49:69:f1:67:a2:
- aa:ce:9d:99:9b:74:0f:ec:da:60:d9:3e:14:45:a3:6c:5b:47:
- fa:d0
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBE
-TjMgc3ViQ0EyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBQLSL4ocWpIJAo84krUBSri1x417zAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQDADKcogA0scWZNZ4LsxzBPSCn+1CCC8lzm7ySLn/K4xTvghlP0
-tfxn27IdRXeKeEfrY7tDuBTABf/Ke9Uf+t/neqU55wDtStlt/dF4oUTwcfSJTFLV
-75lcWeuAxF3tSCtaVQvR30qlSWnxZ6Kqzp2Zm3QP7Npg2T4URaNsW0f60A==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18EE.pem
new file mode 100644
index 0000000000..86209f552f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest18EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: A8 70 FA C4 0E 3C B5 0E 6F 88 EC 8B 32 73 C0 03 35 7A 32 65
+ friendlyName: Valid DN nameConstraints Test18 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid DN nameConstraints EE Certificate Test18
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBAjANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIEROMyBzdWJDQTIwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBnMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE3MDUGA1UEAxMuVmFsaWQgRE4gbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRp
+ZmljYXRlIFRlc3QxODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCc
+FAieQeWV3r7La3dUczH3NGDXPJiaAR+Tqn6f8k320kCvHGdaBRcTKZXH4tX3ZmE6
+vFn8l8xfrX4ApA7+GPrM0MVIUJsMbw3CGjoz872d/Kgz+vS6idpGClTvihDBL3/5
+Nt3TSxejRtxyHVfrIv+zN7f4OH2dZVzdi7ygCv2Kd42XegPi0DKGCdC+ygKWxsta
+0Nti3GppDzGF8UElao99zalmEtdeLgD00v4w0kVGwmmFMn10JhKdwmT2Svu9DteY
+7jum4YaB+yK9IzA/j4Pr0I4FyOC6ZdJNdyrFAU7y5G/eTziM22YEujjzbe5P7X1G
+AUenUiC1R9eaFoHYH78CAwEAAaNrMGkwHwYDVR0jBBgwFoAUzATtaigdft5k6gCI
+Kux1Eb+lLmcwHQYDVR0OBBYEFLQCkqHPGqp0V/N8OEcO5zUqhdd4MA4GA1UdDwEB
+/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQAD
+ggEBAFImhmXh6wbcMuY4ksQzwV9ci+PiOlD+x7nQddqIsuj2CtmLdphO0z+jhw/c
+AcLQiIUJEE2UT0Eow1wYT3IsGV52jV9Xv+4Po9KVIA1S8W87IFJlBhkXPvmzmSeY
+KwHVKq/4fUXpy30yvfxGEWxG3HUKHg7m895xfM2kiKb3RnmC0+FmZQayAi76WaLF
+8u17d9hZo/cLoNd66TyPuxisLiqbXe3Uzvorkbd1RYlwBZUtl+T076+XCluS5ZL4
+Fu5vN9C8+fQWjsJnB1/ifh/oiZqkSkR9K4s+0qAKGOTcrMsf7OfiybRIfkX5Mhc0
+KyfioCAyiP1/9+WcRhdt/NLYheg=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A8 70 FA C4 0E 3C B5 0E 6F 88 EC 8B 32 73 C0 03 35 7A 32 65
+ friendlyName: Valid DN nameConstraints Test18 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1E542095939441FA
+
+cdJyyhnYzLpEmG9qF6WT2BN7QvChbUTEQE1WGGnu62oYRuA2j+dMwoPlqr5tpx8g
+KN7VMXggs9kv6s3QYfIdHlI04eAa8uBN0qXafrVThnJoBmQgfEVX39HmRv7FGf4M
+JVr2aO1y3BE8xTX32w6p1u08jsOt3WCDtw7QGhjHxhtCWYfFgXMTwn+me0y2g8yE
+wnd6Xp6M8SD5Im8bilrPn5saizdiee/JI/99u2u1pVYSz00/2UmIt//x9Q2DHTSu
+wWIv4nja1ZKwGErF/KdAohIGDolhfAYxUqvaA6d74JUB/k6Q9lgVCrkvjqqBGPJo
+W9s1hyNhqi23SbpNcRBDbMcgJENJYObVFzGXNqeFTMhqIvfS1DLJi+5qdBD/d6oD
+aFfWlQxy3lHysoyVEdAp040kbTLwpxgDOY05d23MBGVy6ZxGmfKXvdWMwRM/JedL
+kYtWLz9BzLcIlG2/5uIXc4g7Q6MWlzFtN4I0Y637scar+2tKKM7UEFiZArsGlMp/
+hqTcvNrHMNr/7MgdZe4JyaqKEcwqrNR7TCPTi0B7I/LNBd19dkhucu1oWH5uvToq
+eY+Or54f8pmxzMV6DUuDVWGrJplL1uUOP0CjbjG8yPp9u/a/AFJQb5pwnEJTsHsU
+f3HWV2ZcgAuX82O/HwRYC90E6XNBomUlvcFBFKQ63tc4eYeqoNmvXmFZkjY5xn1e
+A4DsFsk/acCs9islaUvhahm2x0CO4vNJwHoMs+JtJxmjXKFnfZCXYlAzGhqeDk+i
+rcr2cMRo4HCvEu4jQOj5RWsXgWiOTidztcFB0XnSnY51hzH+jOm7ocyQoyIwpXEh
+9Bl84THm/0qBGyjYzxU9W4rOismfuaPzxEHq8hpboxzHmD2VAuiG/KBV4jZYxpL2
+j9be2uU7TFUR/MskI2une5hSm+EJxhzmdkoZy32g5XV+jNhnP7VUhgJEuGXUJ5tC
+yR1TbdY2mCdYSW7EfHDlrbjUCxFQPldaeLn6yGzijQK0A8nHONLUH/EhObfvDHzc
+EQCA4V+ha0mzL8QTQ9jVy7+Y4JSsXl1JkxR0ZLkoCENHClLqSPadklxoyfUxVfSN
+Dlga05jr18QjRr8LqsROy6lcWwJUT5eFc9EBVUkPpvSz3il3cdQTME0Ea4QmMErB
+lDw/K6htlcLRvDOZVy/9Q/uIT4KrIcitxtQK14jhm39lFzd9bOfi5q6tqPOWDg5S
+cqa8HVj+P3oVKHk11F+eW2nsgfoEl/spelBMFb8QfaSuNcMPNwjruxcqcTut1FgL
+AMyQc+EU++OBELkdlXvSotQGbY3OIT6No8vrDhm61Vs18CT05qqu08oNq3B32+XD
+b6HfupCJFlEkaLw3c9u8kZxWtUo5DCrSuWfi1ta1gZNzqtawpP3clJEyt/hvz72k
+QyEpoaifA/y6HfFL8kleKvKTJLTFdjm9b37ttFt8lh1x2GSX6G5SCHYlW6joafu1
+T0dbeXJOWSHg+xmG6xPZ9Vcia7JCvNghyv4dHyth3bjWrOLPzJOpWP9WePcbk2Tx
+/0ScABKYNKvw3+MfhoVC5CpejEhU4BODzD3F+0gmv/5TNYtzfxWjiQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest19EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest19EE.pem
new file mode 100644
index 0000000000..7ad405fca5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest19EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 86 B9 A7 60 ED C4 32 C4 5E A0 3C 59 AC E8 D7 DA DD 2E 00 0E
+ friendlyName: Valid DN nameConstraints Test19 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test19
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGDMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExNzA1BgNVBAMTLlZhbGlkIERO
+IG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZDEN42s2ft+DCcNTzYyJbruK++J4wlPXY
+3JUK4AuI7b55n28caZPvcvtanXRwoQBbvAp/ub04TWtx8o/8etTSciTIBQ6YN0qt
+sh2WW+zsppqt0C+c3Fc2wJJcHh9VQzdMo74pn/mqULaS2K2FQ6msHaplTXcBILHA
+g78xjSQG054NSxqV6z+AsNy1Syw57a92XbmPjeOIsA0oRaHDZfAG8QvQxvWdsh0U
+oyCAM+8IpsSuNOGBpCDViAM0pUuxzeG1WHrYxvyGnQsjjj4HqUqrCXUNWL2yHyD8
+gUv+sYtecxNG56/UowvUeK8eseqmn6BTLur8FC7JC7zeM9ROiEkFAgMBAAGjazBp
+MB8GA1UdIwQYMBaAFEWdG+7F/+PExzA4TFvHXVSZcsC4MB0GA1UdDgQWBBRZQxHX
+4rWSiri1Ka3mWvM/NDr6GTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQCDwHY5/eYX9EpSxTjNmRXVJjje
+8HJ+wB+U9OsMSk7tQb3vsR/ZrgWJXdHuSdaFYUxWDFh6Ufr0kI+AG0nn6V8Kiwka
+73XcU5u9OURprhay2gw331HAcdM4v5Hlv2TQuhFs89MrdzXJ7DJlv//cVg+RTN/9
+OqonUDT/30LUPs90p3PhCBpR5rBqVPX8lzpv849lGQ+eSsdlYd/TG8MM536ImHIj
+xnVMqB+1VlLj77W9XgrxrcdQIBFvAME/oUs2tix9cAbe0+szHinaI46VWCRdkJ/q
+ONNx6C0yX7KwAv5ksINxW7Sy9ajkliArvuq8AfaaO+aupYabnhiqlhF72KF9
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 86 B9 A7 60 ED C4 32 C4 5E A0 3C 59 AC E8 D7 DA DD 2E 00 0E
+ friendlyName: Valid DN nameConstraints Test19 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6EB929EC02FF13B7
+
+e+GE9EM2uqDn5QYh8nfYPqM8KhgU/2MalgZFOVQqpK6sLGBmacKGfS4YilvwSh4O
+UqSxgvLP0ew0/MDhsI+GQwBOK91GBMGIRCae75lewRxsokbAaoiGGCqJ15kWf+fj
+Xg7W66JdrmKDCJ0nm5qcZ4YB0KU8GjjF/H5BDXqrYxDc/yw4qQ8gPlh3vKQjjHdF
+4vbhH0kxFiencJ4OhQI7BN5Gz+/RsnlCULyxA8RjssMD1kY3GtxBf4ZVEiRSMujR
+0m80K/rTRaJla5s9pBnCzCNI06X5Usj+X4QAW/48O8g3qmz/uqTcQtEDGOenFwVg
+qMke6F6nTh4Ctqe4YZRyB+QB0ugKcbc2DBgRnZrTR6NNP7HkEYgdJQkFoCsc3DxZ
+pa+n8IfrSDAssDG5+ALG9YpRCrhosBmhJ0nLKPRb2Af8igyCsnFkZd8IC1Y0/zJ1
+xvx00J9CW/I9Ua93VPOgqiXZ4uJryZBAiorTpJuumYyFvrPYyz9YZkyYL8LOcFkq
+UK3OVcKLCgbTHKAEsTl/jIQgfWaPSGjwtSTwJQr+A5zJxpU5tTc1ZQ52k2qq1tOu
+eKBzTiJQh2YxQNVJruimchRCMYo1TMmo1Mvvdg04BLbyzPKpB6UCgDiaJFhwPqLb
+u/Ah+nGl0BtZ6YPRMcHvigRR4zfH6xFcZaz+DZHAh9A5FIj6T13p2o/TKzwsrgC5
+LQ+/7YU7qRtkjM4Z1gjlC6mWxWFcCCje7w9qlaSCOy7PZWGmIJ4JcGPNC5OocAos
+cK1o0cOdTop+NW3WVpJIDwvrPqgV4a0Ww4tXiKbKyrSvyarj/lK2qo+eRpi1ewDj
+vjTJWlR8j4Zjouw06qxd776TQV4ThPQKj8JgybNxTPmv4xe8SXLnG9sufwzdo+DK
+pSCJALvvrxJYgEW6nAAVkeWCMcZCoYZXSRgkPqcvOgDa1iAGgV4CsqWMmCN2PcYe
+JANcFx2fCwr8c9XLVqjjHRNHfkAir/7Q8tiInxWPF8JuREGhB5FW4oLPRN/ItRO6
+CamTiUfcsXLoMgO1EPHV06T4/R2RzDUQcloQpno7OEzJVgddvnZiqDTWGBeZ9Z7j
+H9Qx4o2LkymfPM16fZzAa4VNJsaE6jsQZol5BBuwzcrS1W+Kp9SMjG4LGCL1n5u5
+PdJuwcA3BxWl+o8q//OHYmqOtCfKSyV6UpBexs1e9+eb+dDt4Q/cx0IKqYfwoDTu
+rQIMVbZnKrNhSQ5u2kk+JWx6JZcQLGAW/5iCZJbeTGN1hKg1P+9moPsFBN8bp8Bm
+M1jY/o9qViP3RE8GsiQYfOyOFynVSw/KKG8vQf20bPvOb802MzdWbY9sNsk+f2xw
+neflXprMsA41TmnDoveszmjBhmFMj25MpeRF7bgpV3YTqxiNGW5GRywIPwFT/EKS
+5RYilsnainDh1tbBSsGA6OXqrxscqGhBIc55QXJB3NqfTkpCcmsDUsJIzVsx7rMy
+Qto2lr8JgStWolDp2Ft5CQSpT2npww3CD9JeusE4W4rq2dtQZrOQcTHrSTduaGig
+UqJv5XA1dFLfRsQILo6ofiIgQUYJFnbMbOYSC6SCCeL5LaAbFAx/4A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1EE.pem
new file mode 100644
index 0000000000..73090f5bdd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: AD 0C EF DF A8 08 5E 31 FB B7 63 F8 2D 53 14 21 B6 68 20 85
+ friendlyName: Valid DN nameConstraints Test1 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGCMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExNjA0BgNVBAMTLVZhbGlkIERO
+IG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMRVH83Hm46JPU28u6W/BR3a95naRI7hTLko
+SOFjXkkjx8tjModC1M4QxWpoMZj2AF0Fd4Aykw75HS8W37wb8UjFS3SrXQ66qVwY
+h0CDz8mNOvtGSanquco3tZeMqoDe8/EXhotzwnf5F83cyp7XB7OiEQPzbplkD4jQ
+GZ5d/SF0lBUdhxilqRlXSemd1kfGop73BOGmgqkQhP+I+4ZZVwxUO5pXGzRpfGK+
+h8ZiOM/JAxpmhdaU1HC6Zf4YDqA2XpKZKQ232myfX4SObpXZ0DUOLNNDzYisj14W
+3ygeNgyIUFVp8hLPI6/BXTJqziW0TqoqCb5Joq+32zjYPwJNxcECAwEAAaNrMGkw
+HwYDVR0jBBgwFoAUQXhCRs1OqILn4Tnf96kWwAr874YwHQYDVR0OBBYEFF3+CfUG
+qPKNIJRROjk0yUUKmZ2SMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAEzeTUMhQZChACqQef2LLNvj+BfT
+VkDB0FVyPo3Yti8bRH8ZnItB8CWkS1iBvv4Bwgp7S8MpAGrgmyBCAO93VjySw5a2
+kEU/55B39tPKMQqWOAvi7DU31mWdWemMwD3u/SuK/8pnPOANjduViBKze8rUj4u0
+tbaYLor/qh4Lxgux9Xw1K+rwKlV9xDvoRLqNMsSReCLfMjMwXkUV7CL/6XjOGACM
+XMPQkJx1SnWLerNLLi2dzO1Ly9Ikr4jTEflJ/lxdw8Fa88eLXNte+JH0OcwwwLQM
+PiSkYK4B8y0A3Psl9309+kocX+YG1ppMoXg64Nt3YQ6kZqw/07gDFODEz3M=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: AD 0C EF DF A8 08 5E 31 FB B7 63 F8 2D 53 14 21 B6 68 20 85
+ friendlyName: Valid DN nameConstraints Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,06836DC2794B1725
+
+7jb9KmEbTz6f9Rml5H8XH3LtwowJdNaQ5jJmtmCsOPGA5F17QXqRbmkcmNGYVTuT
+KhM9CJLw+dT6Y9cpJj3Z9+Ze9OG7m3Ti82TOmzHeLKLzlz4KBUV0u896VhxiImvw
+JMXP+7MOqD/j4oz4U32HBeK7R1AoG/PlREzdZOzYcKEmZ/m/PvIInCHHzxm97rYn
+2q78PQLZVXqaFdp+Xkeli4MzjnyZ9fYN2o2EdoxwGdNgOJ0ZXdScAPLH5x3dcLF4
+MDLL4I/1FvKj4+k3mY+GekZzvdAzpet7no5FVaEjoBX/GkxzWhVN+2vUhhvHZfPu
+OT6upmrrMO/m4s/6IvbEtNbUFtyPfNHdyiethdjbCz8ROa1Yxc94DzsQ4naKynoz
+AY6J7vof5Y19uGdreA7PqeVnX0iQ17Vqc3a8EM1HkiST4g8Lgki9IGFEp3hhQ9dd
+JIi+xj7Nu1Oe8Sei33yJiqubRTLerc+2Xk/IM0+ZHF1YZk1oFODQrvZAx0C/+PvH
+9MvJwpa2KxCb+utf7UsY+5fNbhpMrG1Gudzo3UNxsFw3Wyx0fn8gWeiQH/EJuRnW
+Ek/rMG6U/m1lDodZKnoO9biW/hi6I6nxwd7i8k9jBSjPFgFFGzDY2CpLGBEohv9S
+JyjQbrdjLv3RjMGnkPiRWXs42i4j9IpLrZ1yOdQ7r+kaz3ZLxzzDONjQbqFFrOL0
+nUcpBJQo8caufzdtIg9olKp4O7krveT1REuVwvAsm522GHZ25cdyEHcPQIpcvJ2T
+WKzfQjP/mz2FMBgb6EUTAlZ/lqftiewp16JQWCW5ciGNr0amWR8rcGnVtGgH8G8Z
+GqBsfeqywD5VsoNa3aNqavcFfg+CntHYEPoI2hK8KKQoXtXiTvd41KPWMFAuk6Bh
+quZMLulhPSspe1RS/h5wtrLdm432cYJIUBxPQTerBnRfESEVLu81qJiRPz6K9ZCx
+FHLWSQqxHlKbutDHp3Xa+L76XSbxRUt7Behp+IbVgXZ0aLHfJF4DXsJPJXxvrSRx
+AGQwHxeiCx+y/HgdksnALWJe/j0apT2xfPJvS0zS7oCOSLAX5UigSSPn93kGrl0q
+H/qVU118v1n0oD/jcyuCAOu7ZMIekpQgPocJB854pRVbHl0UQWkGXhv5UdfWb09i
+JJ3gwrIhaS2h4heRbXZWyla9qydsHJdktvDO+dmC78OUJi5e8zxtYuzdVVmp5cfg
+/QUdK65GYAEem1rKPVD+4kQ8SOqzT4RvYtCRhV5iG4fzfNzWG7+9khulFdhoWJ8C
+Yr+uyL6ZvWIXyrvTCFx2MXBe8kWLm35ZZoECDnm54SwPA9nZiXqhqovUK1UmVH2B
+n/yAaWnz3Vj4URFxznv0d3RxXRullVlYJrglI7n4+zS8Lthi/P5tUZYlMjwnuwy8
+/JOOxbX5UR5LQQUqO3FU4veAhhaeiHxUxF/SGX8oL6uFqa7nsBebKb4Hb41voX8N
+y2vsVWUlfB88vZsqZaZQk/59SHvWgooHtJZl1yxO5VtVuSg7ZkVlwNKNBYeUXQLJ
+gZrl0e5fpKn4EsetpubQ+ewty+h7SOnL0ygZ5xTupGXEaUlJaWucoA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4.pem
deleted file mode 100644
index 4ac860600b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4.pem
+++ /dev/null
@@ -1,112 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIC5DCCAk2gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB9MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMTYwNAYDVQQDEy1WYWxpZCBETiBuYW1lQ29uc3Ry
-YWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBALhZkHcTNlH9LLnLK2xDvZYiDsOUcL9iZsUfTjpcENuDJ8rsXGriZDos
-g2p5cYPr4BQ4895UOQPYJo6M7/4aUnQoc/FwnGfeBNagpCJg+nD8GQNpETK9QR06
-nSxOR4/hBD6YqE8UwAIaHejrmpeTrXankCrcei9nFiquQ0Q+rwWbAgMBAAGjgaYw
-gaMwHwYDVR0jBBgwFoAUTi6j59ndi6eCO0FKw558WSNXTlMwHQYDVR0OBBYEFPG4
-BNfdQjQcDcDbjwsrIcrQPg3UMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwOAYDVR0RBDEwL4EtRE5uYW1lQ29uc3RyYWludHNUZXN0NEVF
-QHRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GBAF3XzP3FukeS
-uWBMveZeEBA64M3CPXE4MchDQhtqKcYGa6SlA/t5zpGyFINeThQQrLSuijVGBGr9
-39Hwl9/maACLW3hz5xtL0881tscL2+obZhmF/lGB/e0RrLyGN3Wqql0a+BhEcj/+
-sG0iaxWcpIKdJXNFCi8/rexF7NWS+onw
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4EE.pem
new file mode 100644
index 0000000000..d5ae41d666
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest4EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 62 F8 08 39 E8 97 3F B0 8D 36 4A 19 DE 99 43 64 EB 04 B5 9E
+ friendlyName: Valid DN nameConstraints Test4 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIID9DCCAtygAwIBAgIBBDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGCMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExNjA0BgNVBAMTLVZhbGlkIERO
+IG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwAaxtQyCLrv/YYGDvG+VDVKwvJGevkTOK/
+nOJK5GsXCbEgAwofTRjPkMXBdn7oSucjXzlMKnmPvaKh+e/fQKaNVlicqKoSOomS
+4KpSguNxEIzWUxDuMqfDpOCSZYIVc9PdCcLwbEq8lnYttJrajQrZUTlDCoQoHENv
+W21JsXe0+fbC0zVw2MAHBVniFhssPtRso199CD/J7t0iCBI7phy2tjvWC5cfUUNv
+DObrRNF7si3GPXHPUpMe/GmcEIdvEcAE4H+rCqEWUxKkWlyVPxIoPPsiRzqG6+7l
+AiMFsssbSNQ44qe93TAr7vsm1/ZhZpL0r/LMsZmNGSidHhYSt4cCAwEAAaOBpjCB
+ozAfBgNVHSMEGDAWgBRBeEJGzU6ogufhOd/3qRbACvzvhjAdBgNVHQ4EFgQUCNad
+qrso0AGdiySHpj2VH7iF03AwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATA4BgNVHREEMTAvgS1ETm5hbWVDb25zdHJhaW50c1Rlc3Q0RUVA
+dGVzdGNlcnRpZmljYXRlcy5nb3YwDQYJKoZIhvcNAQELBQADggEBAMLtM5cSPVV5
+t6LSDRihYq2CRqQTpOYhfm6UB87/JqjdIdK1ANoDgNdHWw/CdzwcgbDkt8BhUNwU
+EWovi3i8MbcLbagA3/5OooQ9rvlItrRvrIYVSJ/VPWSIdV/tCeljFGeh0Azfq4O+
+qLQbvjLBJtjCrMUVjVR+sj3eb6TuobLmIXdk7rGziSNKw49nvBQfqtkCkehuesaI
+cr8NCCESNhPopoRBHWRMTilfo1WOeT9U7RAEdolH4fycsnXuq3cXTHpeu9xL0Eqf
+YCgGXJ2Y9KUktGRTzi6WJZrMkzvxsdSkVeuQ0nvJ4czWwNn12VbN//OWgek6lkhg
+QUvZYUxTdrM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 62 F8 08 39 E8 97 3F B0 8D 36 4A 19 DE 99 43 64 EB 04 B5 9E
+ friendlyName: Valid DN nameConstraints Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,92831EC9AD2839F8
+
+9v5IipANmjPzZwsN78OanfxHiuVhNS+BKezMNg1QevK72A7GZ9qRobCRJdUvIMFw
+SxrSYyPAILjf6DnzjXzqIwuogGtshZtzr60oTJmvIge/yUzrl4SyHq7lxuuYcgsV
+9N99XJnwCU7RLH5gI+3OuziNZrMWBh3yDTonutz1qReu6qQvuHqqBzFVTe8XiM5y
+aKucgj5sfPfNESUFW9vZetT18/6ZPrHK2gZlT6IUmAGsj0URIjLaoje5ExYDQ9xi
+WmlEZMR7cPvDS/EBHcvPQzC89XQWpCGHdVj0B6OioVb0YvR/0Z3WGP9jRdZ6mWo1
+A5p+BJkqZVymexXa+TsGrvGkT+deMsJD3CA8Am6a33Xn5AU4tXasl0i1Dg0EdZQP
+VV5trbDEmkfYsoLqQqnHcM00eSWEyY6yzqs8blJAkc8jgKKd9xCbm+mM30JnhCB/
+q38vZ6w1yYsQhR0ykePFupy3jJuKKOiiZAB5mKzeMMPtZF5O8X3DNellirfxWz6b
+nhAxY/U/1W25IdZ66pTa5YGzD5LcRrZQgNWBHM3Pi97ppl/hRSuUOD9szP5oZpIA
+c/OgkZqnfX3EPrgCcbwCn93O1b8I2AWEZThHx0pJYlHTaoRCsfhChNnsSDwLPR0Y
+pq/Dm/G3AD2kHhBUuSWrEm5lNZl/2x09UfFErgBA0KiJRFvSVBfDEbIJ6FycQkWi
+qUyM1IRQe+0pZzYpbRpERH92eA674k3bIESPRyl0X707vcV8JD+xq/tAKIV8w8sQ
+IKuAY0PdJunQwwnOKpUrAYN/xQXLDBGg4Rn/YdI3o/W3eQ0Az1smF/HYIYMbSzl8
+e1IlDuhNPuUezrsFxEkwx4BmOTsyPe8sHFDBflEMI0NgyCzQrsicTy50oO6uLNUd
+n+r1XgzH/7NE1B2vpa5bJAP/qRD1ajxGjmqOtCOiLCZuCgk2igvM8TM88CB0hQ6k
+JQ8eFNoITjF5iOeESWXRVJLTc7DuforJ2DVlQS9hWhs2brg+8ha/vR0lqdAKi3+c
+fcVR62PFm0V4Vc86bJt8xiRHhWqt6Q0C2TFN6TrFGam8XOXg2hDHFShloQUV1765
+ik0x4XEzL9iAFMCaCXEckgAiL2MVkSbzGR3IjMyneVj0Ulw2f7PngodhCkXqh0qD
+zdLmlAtfLVr+G4cK6lHrP4ghoJVrqINUs9zq2SsAeTOwu6JZXKWMTLMJciduXkmx
+N8px7dTdmepHJx9DY9BTsz8l3/YDTGFmGfknXmHfPg+doF8srMGnp/0WodtCZqhi
+3svfenkv9skrrwppA86AEugJkjy24VY2T362o+pSQtMVJPO2Ezrtgs35w/ANnkW4
+0U/8H5S+FtlszRWEuAOzSfQmzWMZJrAWDgxWFiI1OMdfhjpL5Jsl71LaP913EaZQ
+NqEK8UY6WdPR0bwvkT8zS9VRNqxmfhtgEv6Jme5ukkOOqsSTPwfyooRYPZls18Ty
+u0xmL64kqPLeYn2Ij2ITzFkulfZqgzfua7MYhUNGjoI3De7v8kQqTBcYmUQfMpD8
+OXb629RFrcUZW3QYD8brGgCB+o/T0Jyh4PKm1WX/XTyc/RmC8KXWa3W7GNJxeqPh
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5.pem
deleted file mode 100644
index 7f9a94cce7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5.pem
+++ /dev/null
@@ -1,115 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDKjCCApOgAwIBAgIBPzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtF5CubXL
-7jLiEaC4u7BvRC1Z977doXE+03Y8hW6dFiuPJTcVnlMN2mSck2x6VylflhI7XVIB
-PNiZZeRcEzbCJk3AmJL2NDh/20nxHhEr3jxWLmVeyLg1SXhD6WfJKwuvd61cnQkt
-xvFXQEmlzIxBohRZv/YwermH858cZ4wH/9ECAwEAAaOCASgwggEkMB8GA1UdIwQY
-MBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBShfMTSexMLJgKOUfag
-rNt28dFirTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA8GA1UdEwEB/wQFMAMBAf8wgacGA1UdHgEB/wSBnDCBmaCBljBJpEcwRTELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFw
-ZXJtaXR0ZWRTdWJ0cmVlMTBJpEcwRTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0cmVlMjANBgkq
-hkiG9w0BAQUFAAOBgQAw7If++YRGfq6fz1Wm8RpFEbKLi3110GORteylvI+G75Hu
-d6luoo/n/arIfKwWChanGI39YZQ4zYhx00qVeQRbUUuLMjkx14XQVntKAG8sI+KE
-mWmt2cip5+XbIJonQDFQAnQWrhAGpw+ilvfv7v2f+9Q87cYLEoIOPHWstobcug==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN2 CA
------BEGIN CERTIFICATE-----
-MIIDOTCCAqKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB9MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMTYwNAYDVQQDEy1WYWxpZCBETiBuYW1lQ29uc3Ry
-YWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBAMMSbKt/wrsfhfsOqi60ijsWABK1LY20O0SAKCNKW2LuoK3iYZRMPRMT
-2Oym1z29akHaZ5ftLz/WGQ5JuabuVkg4Gx1xRloNkS0RQlIuRMJfLM2mzlXWH5ud
-oXHeHmwbUiYvWFbmwrx4xZbeSaePIYctisexGIa20LJ67Pd8t6OvAgMBAAGjgfsw
-gfgwHwYDVR0jBBgwFoAUoXzE0nsTCyYCjlH2oKzbdvHRYq0wHQYDVR0OBBYEFMRD
-3dYx5+B/4AavhJ+9quSyY66XMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwgYwGA1UdEQSBhDCBgaR/MH0xCzAJBgNVBAYTAlVTMRowGAYD
-VQQKExFUZXN0IENlcnRpZmljYXRlczEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJl
-ZTIxNjA0BgNVBAMTLVZhbGlkIEROIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZp
-Y2F0ZSBUZXN0NTANBgkqhkiG9w0BAQUFAAOBgQCfVuaBKnayPluCi5d9KyF783Oi
-JpQn0SY2yAfXdRAH3cugsfzlo0rsjHyRPj+g5QW5yabg7uJbj11/tnQ/En7u56cj
-mnDBuLqUFrqkJY3Md+k/bCXomEjddbEGKjV8d54oD8ngld0Oy4+fBPQbNo1apc7K
-LqdooapvnR5Nm8qsWQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A1:7C:C4:D2:7B:13:0B:26:02:8E:51:F6:A0:AC:DB:76:F1:D1:62:AD
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 61:8f:48:c3:1c:a7:3f:ae:b4:6b:c3:99:b1:72:4c:ea:6a:b7:
- e7:93:fc:d6:ef:4b:64:a2:cd:a8:45:04:4c:b5:14:5b:60:24:
- 83:f1:36:22:75:b9:96:22:2f:48:86:bd:a9:8d:f5:9b:f0:bb:
- c8:f4:70:13:6d:71:a3:8b:0c:a5:ea:5f:8f:42:45:b7:e0:4d:
- ee:47:1a:39:53:3a:5a:61:3a:6b:8b:39:26:ca:38:f8:b5:c7:
- 8d:44:d3:47:7d:68:29:b9:4d:86:af:fc:26:11:da:02:07:63:
- ff:9a:19:51:33:84:bc:a6:ee:f2:12:61:24:92:86:ae:73:41:
- 1f:b6
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFKF8xNJ7EwsmAo5R9qCs23bx0WKtMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAGGPSMMcpz+utGvDmbFyTOpqt+eT/NbvS2SizahFBEy1FFtgJIPxNiJ1
-uZYiL0iGvamN9Zvwu8j0cBNtcaOLDKXqX49CRbfgTe5HGjlTOlphOmuLOSbKOPi1
-x41E00d9aCm5TYav/CYR2gIHY/+aGVEzhLym7vISYSSShq5zQR+2
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5EE.pem
new file mode 100644
index 0000000000..e3faeae182
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest5EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: D8 C4 14 98 00 CA 37 5A 1D CB 67 24 B3 56 08 D3 F2 30 00 A3
+ friendlyName: Valid DN nameConstraints Test5 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN2 CA
+-----BEGIN CERTIFICATE-----
+MIIEUTCCAzmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMiBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGCMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExNjA0BgNVBAMTLVZhbGlkIERO
+IG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAOd9JgS6UfldtaDuyQBCIZeoLkR28/31qIXr
+Idzjq7FP/alv4nz8AofmEYROX26zxgu2e69X0RSGWNKW2bOTuA6V4jgNBKKg3Znz
+DjAViJ/V6NgEr6xl/uCW+71awSuiI11C6WJJ9ggxYevrUPHyt4OTM927cvjfnQhV
+raL+iKpz2t9/UUyV7xtK8T2rEThTqEeqDeKafwD3gnprACqJpndUR/OgNoUMjdzL
+dD+I2AImKlb510UTH9le4E4budK5qjDX5bX1d9txnXKsOClrQ6h5N6MNMUuMEQBQ
+soetsXWs+xg2EyRSQbsvfiGqdEdrsrKbvQcNSg2R5QUklQp69C0CAwEAAaOCAQIw
+gf8wHwYDVR0jBBgwFoAUo1fZW10Rs2D2AGuJUSuCwwlzqHswHQYDVR0OBBYEFMnZ
+gJavUispfiyQDQtHWo0RKMMEMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
+CmCGSAFlAwIBMAEwgZMGA1UdEQSBizCBiKSBhTCBgjELMAkGA1UEBhMCVVMxHzAd
+BgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGjAYBgNVBAsTEXBlcm1pdHRl
+ZFN1YnRyZWUyMTYwNAYDVQQDEy1WYWxpZCBETiBuYW1lQ29uc3RyYWludHMgRUUg
+Q2VydGlmaWNhdGUgVGVzdDUwDQYJKoZIhvcNAQELBQADggEBAH6QvBXFcVa5nqff
+tPENGZ85VSShfRVZrlseVsXlJEgRR7NEQIiXOQrjj729QVKuvp6ClImPTblzIr3B
+uNEylzfqp90bUCDReuVmQo8MXIviG8IuZFRkMYkrSH5XbUgk+MGyMjdp3Wi4WCdL
+79plNgv6YErDmbDxy2MBf0iHgFRMzcYy/irtmzOhfa4wCim0Ju9sQaPjk8a995QF
+sBhnijwIFrjkJDPiI+JV5EyTPRoE62rshD382LcPmAUvRp4QEbNBHEIh9XmREHeL
+AzWS1mu1Ge37FaR1VKmB6aB2RCpN4cmrDf3DF/Kdd5HZuDv5WdowZwqO9Q5r7juv
+MFes7mw=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D8 C4 14 98 00 CA 37 5A 1D CB 67 24 B3 56 08 D3 F2 30 00 A3
+ friendlyName: Valid DN nameConstraints Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9E196184353CA008
+
+BfNhaU6gpGjaXTdAJonv19FcMgf7QkwfyoVo1y2TGA27U4lYBvRPJMH2XYQq0J7H
+gKlWTNUnQbB9lApHFJ3fucTxgNAVG1+J11vCTiexibvJ/f4HZ3UQUU1lUrAb0SHO
+3vTcxw3UqBih7amYCuvbuDmClmhvP/ogZGv5ecvNDuSb0IwbTtcTDOagpnvgzuIW
+JUM3FXohCBVCY7t/ap1QY4MGhINeRVy1BffMLCuRtPBQb4lYn5jsTMlI1DLzXOdC
+7jWBU4RsoeeOfPhrnVQCcb1nlJl13aN0to2pCw4FKXotQqpR/Ci0etZRnOoIOuth
+vCcIDCyOE0RHFhV4YKr99Xr+TLp870XI+YKk9WLTaImlYBvKPcGVAgZPA6Le0ODX
+oMsbgYCbStQHqc3lJieQvEw7tqo2UYaCgPNArnRroIKSF7+9BuTaNQVqE01DZewN
+QBBEQBaH56QK9gDNOfsSIXP5/imnsTbh4eosxCsvb1OIOh9O+lMxBVJQRplOXSPc
+pfP2ox8COH/ZTeRs6w0cnHFgwXfYtH0F6ZaCA50bqaE7SF4QX2PtnIGOj9MLV2dc
+Qk5WSnt3sjghSN3xFOMZKRnhs/mNc9Vyq7c1/nct0ij5mCLSIUxGf5bS3TDl3hPU
++75QawQ0ynBqdvgvk6wM7v4CnliO9GwQip1mHYLH2yWfIgcc6A0nyhlOCECrANzn
+DW7VlDz7iWucPtXslsV7QEOT4SYg+DJQJ7KDIfw7pRc7ZwfmgJ45Nrpq7t6TEpLJ
+jRa9QqxUmpskm9KOjflxL8s720G31KH4bpjgO6b55yMLvqtb8DWeGgRG/EjFf9xW
+Ir7huGANFgHcscEa/EWhvsFFmuBnNxK0rfMBI6AGix2YPN2T8CDi4oks2ctflmYQ
+KIlf0e3mj7axcFNGBEymzSa6bDMr/sUWK1eUsKvnB8ig7FFlo8WYhYaAGEwWXwvc
+ZTsyAz62czfv53rblY9tdXhRksanrK2d5UVcOCjnsQyWvLO0Y5dnXSlXWsECD6/W
+ORRlHVqgGL0uViQDyQ8aAfRBTW96s9WMKG1QgR+w7NGL/JjBCRpOeQgI3EC4KVaP
+Zh66pYBDGq5MUCF5Mnr377/7QIah7FmcjAvBF7WXw9fvAcaxJJcw6gLQbYcEes2z
+bshbwPHcjTE8GRpCUxDh64ukAr+r2wrRT+32QLKMKJelpO0hi+yOHXA4FAJ9okEq
+Y4LNa0XjV9rY1zrk3mnugKi9PP6HdX09UdeJmV6jNp3yB8OOQg8izL0/myqEVofI
+rwk7FySMefSjbg+VdoaHCSg5lLoIhvkgquitmk4UIUoEDRLq/HVtMB3Cg130kxzw
+SwuBqCyFm7cPhVv8i5W6SH112mBMRRx7pz5GlAEvzwWUaSut4MH+xYLprx1X50j0
+IGbY+LG3Al972tv6UbAQBpsEXKOtr+lo+sAKf58ELZYjxVp3d6pze69oTj2O1iYo
+Kj5h9fNVloyLC0MVErstkDFTt62dqFhtEx9MJIbf5CqIDkOg5ofGfIt6AqJkFI1j
+wAj4dpWgCzUPHxwyWV6+yjX3sXDXaPFIT/IAsRNctj3th2TVoPUbxQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6.pem
deleted file mode 100644
index 35f40caf4b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
------BEGIN CERTIFICATE-----
-MIICqDCCAhGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB9MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMTYwNAYDVQQDEy1WYWxpZCBETiBuYW1lQ29uc3Ry
-YWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDYwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBAOdvJDDcPZf9hCISpQZ3vrpBXxzoFe0eBH7NUTsfOWAh2OGCfOak1DHU
-NApws4o7QUiHWATX1FGzJj9d32W9sROF6qqFJl94jJDinNYS2QeEMZ/T1W7u3+eP
-HZjrIYArjSRN19lgg2VuU5WpIKOXas+cOOQlh/I61dFQjHqyf1W1AgMBAAGjazBp
-MB8GA1UdIwQYMBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMB0GA1UdDgQWBBTohZvb
-MzEoZLMs7htkuG2eUNmvlzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpg
-hkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBABmQhcYL+rwYvVrnWH1LIbYHFhUX
-X0kvvS6SmK7Y+Ea7uDLmhDe5F1QKYmcURJt/Gwhz0xOFOsBCo3Ab4MSIScm00WvI
-3TIXXjLYF4LufXUGle7mdbWcT7SXfd0QVGWbTHDgbVc8SPHmQh3E4r2KVTacFry7
-nbzganMh05d7MTny
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2DCCAkGgAwIBAgIBQDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAti5Odfo3
-pSf6p8iGjNMBwSlKozpyyMbXSxEjpiDvuZpllmjLqoXe6tiWiee19xCly8MnbxXl
-4Pc6BglZNZd+adRIlPrFUPIVmBM51RJLvzQKjiTRPwrPwsJnizD9KLcr0Kf+e9Gi
-LHBlqZM41/0oBCVuAX/5Y5zNNiFhFeOnkNECAwEAAaOB1zCB1DAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUi+O4WFafA2rfPdgHO7MH
-NuHLtsowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFgGA1UdHgEB/wROMEyhSjBIpEYwRDELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRkwFwYDVQQLExBleGNsdWRl
-ZFN1YnRyZWUxMA0GCSqGSIb3DQEBBQUAA4GBALkukW5Jb4GxdEYN7MeIVxnZX8fn
-4Ulh/l6uDFKi+R8UZyMWYp0oi5F0sYQrrsjBwpg/ivfpJtxLh1uMEAWp98vMQPFZ
-Hoo+ma1Ulfh6qAGv8C6EgA5sxWuNO0VrZsMbNsQeqVLXKvkBsYxrUAHXBd5ufqEA
-Wofw3VBcFpqgolnA
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8B:E3:B8:58:56:9F:03:6A:DF:3D:D8:07:3B:B3:07:36:E1:CB:B6:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a9:3e:f9:c3:5c:b0:eb:85:59:db:c9:72:3e:b4:2b:30:6d:22:
- dc:9c:9f:fc:8a:ad:9b:1d:48:b0:19:9f:47:3e:d2:44:6c:3d:
- c4:6c:03:bb:82:6c:26:85:eb:7f:1d:9c:48:93:a0:9c:66:25:
- 85:b1:5e:fe:71:a3:d6:2d:4d:c0:cb:3f:1a:46:fe:ea:31:8a:
- db:d2:1d:f5:0f:b3:48:ad:0b:48:0a:b4:19:cd:e9:c5:5d:17:
- 6a:3f:f8:bc:99:39:5b:29:88:2d:7d:0f:b4:be:94:e6:8e:a1:
- 7e:12:31:2a:46:f9:3c:1f:d1:c2:69:c3:be:62:f4:bb:b0:6b:
- 16:a2
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFIvjuFhWnwNq3z3YBzuzBzbhy7bKMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAKk++cNcsOuFWdvJcj60KzBtItycn/yKrZsdSLAZn0c+0kRsPcRsA7uC
-bCaF638dnEiToJxmJYWxXv5xo9YtTcDLPxpG/uoxitvSHfUPs0itC0gKtBnN6cVd
-F2o/+LyZOVspiC19D7S+lOaOoX4SMSpG+Twf0cJpw75i9Luwaxai
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6EE.pem
new file mode 100644
index 0000000000..e9952d353e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDNnameConstraintsTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1D 74 75 94 8E 7A 83 E9 8A F7 73 F7 6F 4D 5A 87 33 DD 9F 04
+ friendlyName: Valid DN nameConstraints Test6 EE
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 CA
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MIGCMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTExNjA0BgNVBAMTLVZhbGlkIERO
+IG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAM/4iyH3zhj0pIS2GVWhozQpxO7h0Rc0VYwm
+qBRe3BCR0+gLN6FyWhGksoCInhWVgjCp83tO/AV0egq6mtvYVy4/YnzNvPFuU4Ij
+E913+ZktncyEfaJYkjJ8fms83OH/Pah7DpSNVRlxQkvuq8losTpL9l5V7YqLFF+d
+JwHKyXmPFJpujAHtnoqCe3f/WwjyAXeI0M0/2b53eAzqJUmiJ6i+qyygNpPp/OAi
+vunB8NnmVAcshvzRrCWiXF+XChx80fHQclCf0QblOEW7l4pelieJd6BByYfz7Dnq
+Ji3Ep4ULtF5CSVcXyJhtB8tf4XiFAxVh/ifDW3L0SkfuGEwA6VkCAwEAAaNrMGkw
+HwYDVR0jBBgwFoAUBtxbvscSN1mkikB0fAmdRTxKodswHQYDVR0OBBYEFJWht0b2
+Dg93oRjljC30sI++d9gXMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBADApYud9pWALlHw0vcQGRTQvhNRM
+nonPTNJZa2dzI76tcsjPw0BwP08OIKv60ciSIsEQIU/lxUruRSixe7xrxktGygPk
+aaOdXnF/WQHhucPx6HKl7cs/c8zInJQKWSG3DYa3rRCtsNSo9A9J3cwY1mAhsh+S
+JbZHXu9hbFdFoLPaCHNQRod9aqpiAd0ra7SpzrQGSZMTRaWbQi1mHJ93ay/bBQI/
+1PqHZ71szX/EIM9TsHLCV1Q9oJN12xAbDI5VdhuCFdiIDRytGZYu0en48+CDZIGZ
+Bi2sSMaG3zmUU7w9fh0NuuL2YlV7C5p96QljGRtmOZh4qoBgOSbrsa3k9zc=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1D 74 75 94 8E 7A 83 E9 8A F7 73 F7 6F 4D 5A 87 33 DD 9F 04
+ friendlyName: Valid DN nameConstraints Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,997AF21B8BE5B4BA
+
+8yfzhn+GIwBC4tJMwDYhhX3ZaBFBzNQHBs1brCMjJzSQ+4yycS+AH048DHIlsx/A
+uAIme7AS2SBrfkOzAPcHTaVqj4thcbzFKWi2n5/W+XbivtYYQUJfSBFLtp2yGybU
+eizSJrPJV1afxJePlgxOdjh4JukKWTbK8GyOkC1JLEPh/sG141Y30jlExF3T8b0A
+E75yfwwRSHbK5nDwew1HtgzZMoJaP/JM2GUwxSoDDgNVBTYb/MwGmPDeZVgW8FHo
+8f2+AJk4IaoFeO6wp3/PsdPfm1kzHOrsJzK2GP+xaA94E8jwH7J3rlU2LzihJ48L
+mT3BUFxBIBhul91NKpzPhGzqlna604+Syg422PFWk80s3KruXel1ErZ8B5a8ToY0
+A6xOpEcGycWeCi7kvB+iaxtwwyE3ZbAp1HLBM6eU1RhP3lO0/bxeDRnSimOq8+vd
+bzuPznTh9SsBNsYNFxiyXW9Qhw0hHxiu+GVu/fCbg3CNzTcaPiGmMuuIXjqiQ5C+
++RsRrtEqVJBHjiSC+5uTXksB6JpstWxPWiTfStbYb35A1px0VOoMLoEZQoPorbSN
+Z0Q5KqpNmPXIgufE0HYxEvjk51hGMM2bKOuxZiNqnPuG/sbgpkRQvzSQnz2Kem+T
+g0so6vMU4BN0PBsGol+Ktomsj2ZcdOxemF/JtRyQ/wWgnNFQ2ZBAQSCBYOUvXjn7
+rHfzV+csRPs1vXgTy97cveaHDzLm93PEq4exzPXLiXK4JCRDfMyq/uJ3l5ZgJjO3
+8lcqzjWsYaKlYLr7uo/XWwst+zV+EWbPbO+XwEMXS+fkSnBbLxNXnVyJhXDf1ri0
+3RsAVBFlgBdeutl3K/VzqgHHz3JG845m8Dql9hu+zLGrhVLpZgY0CPwE5RzmNubV
+VMiIUPQpCwJ3JdhvocTrzf3PGhlh+dawE8SWqVQqGb6PKGJKCzjO7oMcTujbmDgo
+RG1i7YzRoVBJZ+p/pqtwiIeOX7K5qSgvhmvmhv9DPh+7PATAhfuQgCylt+nBhZjz
+e3TpI5MA6L1OcNQBayn6cgLzRDBcfrzGJ8ya6NaScZIUBazhGW62eCfmPcoUFN7W
+LqY2pIuqSXkdRY5HshGqiE/T1IVskwSLvdc80t190odSERZ+tg3DzhGGgYFysNp0
+URKBHKKeKOWJ7U/JPEYdfjmXwAsVPii1qpYOoQuwM8T6F4IhWfBvt7n77bc/sMEB
+m4Ax65kfJd5e3EIGRlOaPW3J764i78x25jqTHihXgSb/UoUOAoKYEifyB6aMeEb2
+0rYIC+NQ4oGzYXI/EuasyyPIrzGtcorlVFf66fDr6hc4bNlZZ7ZeKCXGVgXHXhOp
+S8snWNMeqiTXFvlE62sH3viS1DQvV4khKKeUlhjBms4/hQt4rlk/uCo2e4p6TWFP
+FFUg8ziw7kUlPf4p4n+evZuMEIROKudtvXQVsRsCWXsAo7zj40Gg47XkvDhsvINs
+T7adLxpEeKbZ5xjcvvjENWTei3vYHgEACfJ/1dayvdEaCJp+6273iipuiXDeCVNU
+yIutyGiKOGk+Qg+8hAfpcQFU7uaEI5cAesvPzOd3sbx9lxlyPu6dOw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5.pem
deleted file mode 100644
index 7b1c148861..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5.pem
+++ /dev/null
@@ -1,141 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid DSA Parameter Inheritance EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=DSA Parameters Inherited CA
------BEGIN CERTIFICATE-----
-MIICMjCCAfGgAwIBAgIBATAJBgcqhkjOOAQDME8xCzAJBgNVBAYTAlVTMRowGAYD
-VQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbRFNBIFBhcmFtZXRlcnMg
-SW5oZXJpdGVkIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowaDEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMT0wOwYDVQQD
-EzRWYWxpZCBEU0EgUGFyYW1ldGVyIEluaGVyaXRhbmNlIEVFIENlcnRpZmljYXRl
-IFRlc3Q1MIGTMAkGByqGSM44BAEDgYUAAoGBAM6LNthcREHH6pqw2JQ5RbNJtGxm
-vdadsOuJvn5b0NszIYMbSpJq13bSo8hLx5uVfEvkGdc0BpoYHdax/d+0xQcq1G2b
-yKxnK+bYJbJhXuvvfEtQJXVoNRneAuD+UX5sAKja0T80w8kTA1/2K0vJMVwExuZb
-OPhYbliV11/6bvxPo2swaTAdBgNVHQ4EFgQUAHhCMlJkgBTrJroWKe1llb8qHx8w
-HwYDVR0jBBgwFoAUXSTuilUa8sbJssK/ivCySU86sxswFwYDVR0gBBAwDjAMBgpg
-hkgBZQMCATABMA4GA1UdDwEB/wQEAwIGwDAJBgcqhkjOOAQDAzAAMC0CFA18iKub
-KQypNt8MvheJ9svsobpgAhUAzoneZ6mJuBahNft2JyeO/YD0xes=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=DSA CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDhjCCAu+gAwIBAgICB9EwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxUcnVzdCBBbmNo
-b3IwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA6MQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxDzANBgNVBAMTBkRTQSBDQTCC
-AbcwggEsBgcqhkjOOAQBMIIBHwKBgQDf5RE+2um2bhDW6p3inTqwR71EAMdWyMxu
-0DOEVkc1PfZUyOPCrbu6dfMvMwym+THsZ+PlmW38KW6qV4hyNOKOAJDgo6xkjsD2
-PB2PtMhKSDBef6qcdiYL2xNzM4OXwMWz5jf1Pv8VDdShLrox+KuH2AvMd5hCbqyT
-mMK9Lns0CwIVAM8GBNj/i+sA6fZcB5Zz/ZZlOi8HAoGBAMzhfLDOkl9j7Di7RLrd
-kjS2Xr5le9hxdwSd7GZ8OwTOtvNS/g+SVQLvThKrXZouL25W83Dsau2bIrioE8sM
-nBbqwQqOISZEpQz5oOxi4HAxzGj1C4WkShtuefTB+TZaOG9O74RT32f9zPdZYo+c
-nM0Qj1ykD5y3B+xg876vfjmYA4GEAAKBgBHyudi+QivFhL6RAhz8jDJyi6hsIdeI
-ihS6MGV1wBw9gmllp6yQehQdhXvlU8Jg/LHPZ6/B8i4IMmo4x5FOO7w8CdD5cW0I
-3ydJjQV02L1G0NtRpVO6h/P6XSWDT38KdeWp44mnQXdjQF8rLITSwXF4CttrVxnh
-5xQMnsT2MjkOo3wwejAdBgNVHQ4EFgQUdBXVJBy9XmWIH+GLCX5/6hlITmEwHwYD
-VR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
-DQEBBQUAA4GBADo7ch93LLrc7PUdW0XOP3+kP+Sywfqf2ApcmOLufmM60siw4rzA
-1ssoITB2Rs3TPQKBiJzMdFKrq8tQ+8TcpXJ9M4SVfbAFB0P0vB4UC2Eg6iSnVJbB
-tsZFj12gpqv5Gawo3yUTw34h3opDGSX1pz6eZUIZBFKpAX5gyIpiEBI2
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=DSA Parameters Inherited CA
-issuer=/C=US/O=Test Certificates/CN=DSA CA
------BEGIN CERTIFICATE-----
-MIICFDCCAdOgAwIBAgIBAjAJBgcqhkjOOAQDMDoxCzAJBgNVBAYTAlVTMRowGAYD
-VQQKExFUZXN0IENlcnRpZmljYXRlczEPMA0GA1UEAxMGRFNBIENBMB4XDTAxMDQx
-OTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTzELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMSQwIgYDVQQDExtEU0EgUGFyYW1ldGVycyBJbmhl
-cml0ZWQgQ0EwgZIwCQYHKoZIzjgEAQOBhAACgYBnjEfaDDaBZDn4GjcL8LvUE/1n
-PUDInJLhOolUsPKXpXDQZBekp3yp6ScJZd+gpRz8BNo+3WJr8AztgVdPXSnICFkZ
-DF+NiPD/jLbodQG+EApk31d7i2xW8FPOQ4i5CZkIPJCvAejZMl3tVgLPYNIBOuMK
-K56RQfbHfN5smWMADqN8MHowHQYDVR0OBBYEFF0k7opVGvLGybLCv4rwsklPOrMb
-MB8GA1UdIwQYMBaAFHQV1SQcvV5liB/hiwl+f+oZSE5hMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAJBgcq
-hkjOOAQDAzAAMC0CFQCoWW8xd7Yg7Dab60thCq9E7XK6KQIUbSLhvU0n9i47H9ed
-1lleyyWGItg=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c7:32:ea:21:ff:7d:01:d4:f3:d9:c5:a9:ea:04:35:21:81:d2:
- 13:f2:35:d3:e4:53:c5:03:93:de:a1:2d:25:56:64:bc:52:20:
- 81:53:69:6a:a6:90:26:38:bd:ed:31:7f:a9:7b:c1:e8:a9:e5:
- 07:97:82:bb:3e:8a:f9:79:ec:2e:bd:16:4c:31:6b:b6:80:ca:
- ba:ba:0c:35:0a:d6:08:3c:31:78:fe:d3:3d:06:69:6c:3a:e4:
- 07:4d:6e:84:21:d3:c3:90:60:8f:99:90:62:a9:16:38:25:2f:
- 7e:08:5f:2f:cc:59:d7:7d:9b:2f:d8:0b:e7:70:d9:64:f7:01:
- 38:8d
------BEGIN X509 CRL-----
-MIIBOTCBowIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU+2zULYGe
-yid6ng2wPOqavIf/SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAxzLq
-If99AdTz2cWp6gQ1IYHSE/I10+RTxQOT3qEtJVZkvFIggVNpaqaQJji97TF/qXvB
-6KnlB5eCuz6K+XnsLr0WTDFrtoDKuroMNQrWCDwxeP7TPQZpbDrkB01uhCHTw5Bg
-j5mQYqkWOCUvfghfL8xZ132bL9gL53DZZPcBOI0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: dsaWithSHA1
- Issuer: /C=US/O=Test Certificates/CN=DSA CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:74:15:D5:24:1C:BD:5E:65:88:1F:E1:8B:09:7E:7F:EA:19:48:4E:61
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: dsaWithSHA1
- 30:2c:02:14:46:20:d2:4b:f9:cd:91:09:e9:71:6a:bf:d2:3e:
- 88:5d:d0:47:ee:aa:02:14:25:ae:d3:6a:ca:3f:a4:54:41:d9:
- a3:57:74:b3:48:ab:c5:9f:01:f9
------BEGIN X509 CRL-----
-MIHYMIGZAgEBMAkGByqGSM44BAMwOjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMQ8wDQYDVQQDEwZEU0EgQ0EXDTAxMDQxOTE0NTcyMFoX
-DTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFHQV1SQcvV5liB/hiwl+f+oZ
-SE5hMAoGA1UdFAQDAgEBMAkGByqGSM44BAMDLwAwLAIURiDSS/nNkQnpcWq/0j6I
-XdBH7qoCFCWu02rKP6RUQdmjV3SzSKvFnwH5
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: dsaWithSHA1
- Issuer: /C=US/O=Test Certificates/CN=DSA Parameters Inherited CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5D:24:EE:8A:55:1A:F2:C6:C9:B2:C2:BF:8A:F0:B2:49:4F:3A:B3:1B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: dsaWithSHA1
- 30:2d:02:15:00:89:33:c4:9a:67:b6:d1:05:d2:fa:c6:db:09:
- a9:f0:01:9c:cb:db:00:02:14:5a:f9:93:bc:2c:9d:fb:be:01:
- 4b:f1:a2:fb:1d:93:dc:98:05:f4:ab
------BEGIN X509 CRL-----
-MIHuMIGuAgEBMAkGByqGSM44BAMwTzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMSQwIgYDVQQDExtEU0EgUGFyYW1ldGVycyBJbmhlcml0
-ZWQgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFF0k7opVGvLGybLCv4rwsklPOrMbMAoGA1UdFAQDAgEBMAkGByqGSM44BAMD
-MAAwLQIVAIkzxJpnttEF0vrG2wmp8AGcy9sAAhRa+ZO8LJ37vgFL8aL7HZPcmAX0
-qw==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5EE.pem
new file mode 100644
index 0000000000..7e17e1dc6b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSAParameterInheritanceTest5EE.pem
@@ -0,0 +1,38 @@
+Bag Attributes
+ localKeyID: 59 F0 D4 26 E2 38 A1 F6 C1 D0 71 F1 06 FD 5C C9 1E 16 E9 6D
+ friendlyName: Valid DSA Parameter Inheritance Test 5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid DSA Parameter Inheritance EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=DSA Parameters Inherited CA
+-----BEGIN CERTIFICATE-----
+MIICOjCCAfqgAwIBAgIBATAJBgcqhkjOOAQDMFQxCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSQwIgYDVQQDExtEU0EgUGFyYW1l
+dGVycyBJbmhlcml0ZWQgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBtMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE9MDsGA1UEAxM0VmFsaWQgRFNBIFBhcmFtZXRlciBJbmhlcml0YW5jZSBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0NTCBkjAJBgcqhkjOOAQBA4GEAAKBgGePd1BDyXeRQ1yb
+OLiczxes0cd6mp1vxtg8Pjtuw/VNgx6/q6dq15cXOXf+I1KDj5KpTr8RU5EqJzzs
+24Rkhd0YIpKnlS+r9YlUbGUqiYgFGxcZIFPWeXtd/HDUo6EtwM/4CKMJIoCj+RIP
+85dMZNOqY3m3VXmUrihAfGMSJ1zYo2swaTAfBgNVHSMEGDAWgBRlgZ9wOoyt9kMd
+yOePVY7oS9uH4jAdBgNVHQ4EFgQUBm+vcNPtCiTeORO8G9ZsstjM7x8wFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMA4GA1UdDwEB/wQEAwIGwDAJBgcqhkjOOAQDAy8A
+MCwCFF8V1SAET1xFJmUxuSyCcxKWdg1nAhRLvW4OnD/rkm/0u8mAPbkq84+rpg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 59 F0 D4 26 E2 38 A1 F6 C1 D0 71 F1 06 FD 5C C9 1E 16 E9 6D
+ friendlyName: Valid DSA Parameter Inheritance Test 5 EE
+Key Attributes: <No Attributes>
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A1A1A940AE90B3FA
+
+X9H/rdRkmXxSAG8Jna6Ip4pqa2PUCyiEbMJU7exzzJ6tx/zP4zU7se6HLZE10YbF
+D+R/mIapOCVSaf1NkZ0xc3Oki2W2E/zQ6S2uX7scHQkBanuBqkjwjY+vDZAvdOmd
+FVsbb55ezxMendKK8Udrd3K5EibzReRbwSl4lLwwGZQzwRLv3LJBWC0m55s2D3QZ
+2wzpJI8WgCMXd9sJY6+453HT/NSUmoWYACIqhJhXxkNxWFmSuoh9IlqoKUkDtw52
+bf1gF2itR8YJ5Fbjg4u7PjVRbkLjCU0BXjAB2G0WasnJr9To6bwSCsGSfGLRTaBd
+XH1uS31MgymzgO5ftqLNiCPy3bxFa5H7LK/ETAlqfnDVC/w0Za3pI9ZGGeR4AIx4
+PXbvrVBrcadyfU/MuHSJzA8b9dWN2bOn9nogf+cMewQWBXnF7Znh3re1o+ElpF7L
+E8h+YgVzMlJVLrFR0HL+1Vs/ch0FrsYW0Y9v0/2VSUnOLL8omoZZrvEOZ7Q/MZj6
+b1cQoEuoEu3rQss8fHsKgSdNG5JeqRngTFnV5zCTqIn0Dyl/bkje4s3ryQ/sMyDI
+6wMdTVMTocYvdldlnRdGNw==
+-----END DSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4.pem
deleted file mode 100644
index 6482e31df3..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4.pem
+++ /dev/null
@@ -1,104 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid DSA Signatures EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=DSA CA
------BEGIN CERTIFICATE-----
-MIIDNjCCAvWgAwIBAgIBATAJBgcqhkjOOAQDMDoxCzAJBgNVBAYTAlVTMRowGAYD
-VQQKExFUZXN0IENlcnRpZmljYXRlczEPMA0GA1UEAxMGRFNBIENBMB4XDTAxMDQx
-OTE0NTcyMFoXDTExMDQxOTE0NTcyMFowXTELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMTIwMAYDVQQDEylWYWxpZCBEU0EgU2lnbmF0dXJl
-cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQDk
-i69AjBXXPXzuA5YSaMEgBegXyp50ZUuaVJcqeDPapcVy6jSzlGhC1Rv9d/CoQp5k
-k5C2wgIxRhN6A2nMmC1WnV4jXyi/rX8P0GmVYlwaBypejHNJfv0SIo5V5VbprnIp
-locIJ9d3Q/CGuAkKGxSl5gPmRXlN6fpTX8EJvX7FwwIVAIA/5PzzTOU+yw8XCipU
-bNBnbA07AoGAZtQWiiCt/tEyn6V/p7PQ6nc/62yi5CnY2Lwh3Zr3zOW0d03f7Nqi
-jJx1Elof/mbTEcLvhEPsqYhuTLpMPzWWx2f8mb0PmSkTkU7YAq7+a69QVqovHrUq
-yO4iRyV4ayHdFD/O8BCB95YdnEG7XkSSXS7GHrjNaciPPzs+0E+iztkDgYQAAoGA
-D1MorDgvPfMRYUHDPafWevf2ATLTIXEQFNXDPk3rGaKMr54IPUEK/8yiR4J6VqGj
-/eyyi7c5tcqgGYWCm5ZoqLtrupCk4a1ltkQx0h4iL1NBT/qc+C/oLEMkFn4r2GT3
-ZPrweUgduQJtkDbM6zYP8jmrfSfs90dv3TPEfk3uJFejazBpMB0GA1UdDgQWBBSz
-M9dRogQNRPudQPESYnGwU/ZpDTAfBgNVHSMEGDAWgBR0FdUkHL1eZYgf4YsJfn/q
-GUhOYTAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDgYDVR0PAQH/BAQDAgbAMAkG
-ByqGSM44BAMDMAAwLQIVAIynyNKZ1ECb+SGSaPMnJglzolkYAhRM/h+AuzCA19hw
-xk52oNmdtPZA6g==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=DSA CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIDhjCCAu+gAwIBAgICB9EwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxUcnVzdCBBbmNo
-b3IwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA6MQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxDzANBgNVBAMTBkRTQSBDQTCC
-AbcwggEsBgcqhkjOOAQBMIIBHwKBgQDf5RE+2um2bhDW6p3inTqwR71EAMdWyMxu
-0DOEVkc1PfZUyOPCrbu6dfMvMwym+THsZ+PlmW38KW6qV4hyNOKOAJDgo6xkjsD2
-PB2PtMhKSDBef6qcdiYL2xNzM4OXwMWz5jf1Pv8VDdShLrox+KuH2AvMd5hCbqyT
-mMK9Lns0CwIVAM8GBNj/i+sA6fZcB5Zz/ZZlOi8HAoGBAMzhfLDOkl9j7Di7RLrd
-kjS2Xr5le9hxdwSd7GZ8OwTOtvNS/g+SVQLvThKrXZouL25W83Dsau2bIrioE8sM
-nBbqwQqOISZEpQz5oOxi4HAxzGj1C4WkShtuefTB+TZaOG9O74RT32f9zPdZYo+c
-nM0Qj1ykD5y3B+xg876vfjmYA4GEAAKBgBHyudi+QivFhL6RAhz8jDJyi6hsIdeI
-ihS6MGV1wBw9gmllp6yQehQdhXvlU8Jg/LHPZ6/B8i4IMmo4x5FOO7w8CdD5cW0I
-3ydJjQV02L1G0NtRpVO6h/P6XSWDT38KdeWp44mnQXdjQF8rLITSwXF4CttrVxnh
-5xQMnsT2MjkOo3wwejAdBgNVHQ4EFgQUdBXVJBy9XmWIH+GLCX5/6hlITmEwHwYD
-VR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
-DQEBBQUAA4GBADo7ch93LLrc7PUdW0XOP3+kP+Sywfqf2ApcmOLufmM60siw4rzA
-1ssoITB2Rs3TPQKBiJzMdFKrq8tQ+8TcpXJ9M4SVfbAFB0P0vB4UC2Eg6iSnVJbB
-tsZFj12gpqv5Gawo3yUTw34h3opDGSX1pz6eZUIZBFKpAX5gyIpiEBI2
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- c7:32:ea:21:ff:7d:01:d4:f3:d9:c5:a9:ea:04:35:21:81:d2:
- 13:f2:35:d3:e4:53:c5:03:93:de:a1:2d:25:56:64:bc:52:20:
- 81:53:69:6a:a6:90:26:38:bd:ed:31:7f:a9:7b:c1:e8:a9:e5:
- 07:97:82:bb:3e:8a:f9:79:ec:2e:bd:16:4c:31:6b:b6:80:ca:
- ba:ba:0c:35:0a:d6:08:3c:31:78:fe:d3:3d:06:69:6c:3a:e4:
- 07:4d:6e:84:21:d3:c3:90:60:8f:99:90:62:a9:16:38:25:2f:
- 7e:08:5f:2f:cc:59:d7:7d:9b:2f:d8:0b:e7:70:d9:64:f7:01:
- 38:8d
------BEGIN X509 CRL-----
-MIIBOTCBowIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU+2zULYGe
-yid6ng2wPOqavIf/SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAxzLq
-If99AdTz2cWp6gQ1IYHSE/I10+RTxQOT3qEtJVZkvFIggVNpaqaQJji97TF/qXvB
-6KnlB5eCuz6K+XnsLr0WTDFrtoDKuroMNQrWCDwxeP7TPQZpbDrkB01uhCHTw5Bg
-j5mQYqkWOCUvfghfL8xZ132bL9gL53DZZPcBOI0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: dsaWithSHA1
- Issuer: /C=US/O=Test Certificates/CN=DSA CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:74:15:D5:24:1C:BD:5E:65:88:1F:E1:8B:09:7E:7F:EA:19:48:4E:61
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: dsaWithSHA1
- 30:2c:02:14:46:20:d2:4b:f9:cd:91:09:e9:71:6a:bf:d2:3e:
- 88:5d:d0:47:ee:aa:02:14:25:ae:d3:6a:ca:3f:a4:54:41:d9:
- a3:57:74:b3:48:ab:c5:9f:01:f9
------BEGIN X509 CRL-----
-MIHYMIGZAgEBMAkGByqGSM44BAMwOjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMQ8wDQYDVQQDEwZEU0EgQ0EXDTAxMDQxOTE0NTcyMFoX
-DTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFHQV1SQcvV5liB/hiwl+f+oZ
-SE5hMAoGA1UdFAQDAgEBMAkGByqGSM44BAMDLwAwLAIURiDSS/nNkQnpcWq/0j6I
-XdBH7qoCFCWu02rKP6RUQdmjV3SzSKvFnwH5
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4EE.pem
new file mode 100644
index 0000000000..2041c76807
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidDSASignaturesTest4EE.pem
@@ -0,0 +1,44 @@
+Bag Attributes
+ localKeyID: 65 80 CC 44 81 EE 42 CA 16 B2 6D 68 60 CE 80 83 F0 2D 6B DC
+ friendlyName: Valid DSA Signatures Test 4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid DSA Signatures EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=DSA CA
+-----BEGIN CERTIFICATE-----
+MIIDPzCCAv+gAwIBAgIBATAJBgcqhkjOOAQDMD8xCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMQ8wDQYDVQQDEwZEU0EgQ0EwHhcN
+MTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBiMQswCQYDVQQGEwJVUzEfMB0G
+A1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEyMDAGA1UEAxMpVmFsaWQgRFNB
+IFNpZ25hdHVyZXMgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggG2MIIBKwYHKoZIzjgE
+ATCCAR4CgYEA5IuvQIwV1z187gOWEmjBIAXoF8qedGVLmlSXKngz2qXFcuo0s5Ro
+QtUb/XfwqEKeZJOQtsICMUYTegNpzJgtVp1eI18ov61/D9BplWJcGgcqXoxzSX79
+EiKOVeVW6a5yKZaHCCfXd0PwhrgJChsUpeYD5kV5Ten6U1/BCb1+xcMCFQCAP+T8
+80zlPssPFwoqVGzQZ2wNOwKBgGbUFoogrf7RMp+lf6ez0Op3P+tsouQp2Ni8Id2a
+98zltHdN3+zaooycdRJaH/5m0xHC74RD7KmIbky6TD81lsdn/Jm9D5kpE5FO2AKu
+/muvUFaqLx61KsjuIkcleGsh3RQ/zvAQgfeWHZxBu15Ekl0uxh64zWnIjz87PtBP
+os7ZA4GEAAKBgCwUuJ3sGoI0YbdjbhY97S8mJRwXyMJzPtX4GILw0J0vhFlgB1IQ
+RlMdNahTZDjWGvBNMV6VscdMD+PlfG1ZVyGwwc9qvny5X8RfYRb0AsmvSN6o3brj
+n5gFsnsHcRxE0fhzbHdbZFPImAVMjTaAIkKXfjIaUaiICOr3qqyhH2yBo2swaTAf
+BgNVHSMEGDAWgBSPkMaMdOh7DMhZx308W1RZYCULsTAdBgNVHQ4EFgQUnHvCTw9Y
+g/WGXCrgdm2oTR/cEDYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA4GA1UdDwEB
+/wQEAwIGwDAJBgcqhkjOOAQDAy8AMCwCFHm10vtlAd/b1cB5Yi/UsmQ8BtYEAhRL
+hwx1Txi7lIfyun0bpsh8km3ohA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 65 80 CC 44 81 EE 42 CA 16 B2 6D 68 60 CE 80 83 F0 2D 6B DC
+ friendlyName: Valid DSA Signatures Test 4 EE
+Key Attributes: <No Attributes>
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,08DE82DDFA93E00B
+
+0fvn08EoMjSFM7RzWoIpU3wJRuMFftIvR7XSeytjH7LVbK5GJviWr1+V8LkgD28s
+tdSNeKVXUN+RwVNv48Ul/60hzarASPQNXvtVz7GFDUwBlm4LkywmJhvKlu0mnmxh
+d17JQ49ypkQrshQPp5k/bDLijhLQ5mY2i/a200g1qtsq7H6qcl5dcCAtQw2/Ei+v
+cYoZFCnF3MHExaq3l0BTEHJ33Z+rjSHjUXq3u4Ivx1qESK48nUMhQt/z6vxgyvvf
+y34qU2b8iytemifLlVP7N9ZUFCZMlQwKRdDKHAPlSAptG8KEsuxG+NFtM0GyugqR
+SoAEpq24sHT+xSk5nKT7UskJ6FYKwliWOf4U30eKKz+Yq0mswstJd3A4VE1a3acK
+kwPHztRlKlhhjcGlmUgB4oGERCOegc/ZklF2NgLAc1jJQCpPQg3N7m3kMJ3VsGS9
+8/In9c2VKT+9+BEKcrR3pQCb/2TTAg6rKvCCCo4MpcTa/Xek8IPCbH6K8tsWkVnz
+t19y7EDrqOjNFqksum5r/W1zn+zOfGpSN6Fb6lK4jY5E9RzkkpHz0foCj54VWDfg
+yUH7H70BtvKPW5KZ1mrtNw==
+-----END DSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13.pem
deleted file mode 100644
index f15bd0771a..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=GenerizedTime CRL nextUpdate CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIChTCCAe6gAwIBAgIBEDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEoMCYGA1UEAxMfR2VuZXJpemVk
-VGltZSBDUkwgbmV4dFVwZGF0ZSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEA0XVL58x4St3rim3S8J3rxCFsMxohlbSezZsM8cVML4M8JqBA2RCpciqMXQ39
-ySW9Va2Mca/dkW/VCXATp9lG6hGPI9uvz5t42IPrYc/CdCMWnMZYPxolMOUJd8rD
-fRjX+PnPtbMonefHo0LclKZkSs5hLEty2zpam33MNLS4L+0CAwEAAaN8MHowHwYD
-VR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFBSGFC5gYrSk
-iBLjiqt4F6Lu0TAaMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFl
-AwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAPS84jJFDI
-dH5hR/XPr96LgBMhK72+PiP/6pgrKYilpao6qSJAf9vIsaWuebDcHUWFO3HcaIwl
-Ku+ejli9fwEZmMcK1l4pj5vf5y4/wYBkWTvnpT65JUGdmuFic0n4c1jEPTkRZPl0
-FVsLl9iYRwWLJH9pq9gaOLZboV3w/HplDg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid GeneralizedTime CRL nextUpdate EE Certificate Test13
-issuer=/C=US/O=Test Certificates/CN=GenerizedTime CRL nextUpdate CA
------BEGIN CERTIFICATE-----
-MIICojCCAgugAwIBAgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH0dlbmVyaXplZFRp
-bWUgQ1JMIG5leHRVcGRhdGUgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBuMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-QzBBBgNVBAMTOlZhbGlkIEdlbmVyYWxpemVkVGltZSBDUkwgbmV4dFVwZGF0ZSBF
-RSBDZXJ0aWZpY2F0ZSBUZXN0MTMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-AJ/BW+Rh38aEJHLhyF2rFsHXLa//8UzBuAOpoiJSzFc4gk4FZMbUeMNc7JEG8d3C
-1iCI6ksf+VPWuZsGVLU8GB1Y01lFSaXPp5jmmDeILhOIhmh7/xGJOC0bftMHU2Ub
-STCDgX+yxmVEzoPNpyWc+NIOUxF4dGZcIVeFKPB6cYQlAgMBAAGjazBpMB8GA1Ud
-IwQYMBaAFBSGFC5gYrSkiBLjiqt4F6Lu0TAaMB0GA1UdDgQWBBRAXKg9gLMI1s2l
-71T3v0X4NAK8LzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA0GCSqGSIb3DQEBBQUAA4GBAJODcolMrKSSYYUM8i0NqwfexPIPQ6X+U/WU
-fh7Q4VMoPii7s2hU2MHjdWM/80GnDbNLmNqWBWqymgR+lkYvyvcMSsXr7SC7ZN7T
-PKpw3Hi2bnOFDJDKA/MGWsX+cehwuRKlxmwep3r23H0ctmF6bYpcVusN6NYXVHzt
-jU0bM66N
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=GenerizedTime CRL nextUpdate CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Jan 1 12:01:00 2050 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:14:86:14:2E:60:62:B4:A4:88:12:E3:8A:AB:78:17:A2:EE:D1:30:1A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- ca:4b:74:4e:30:1a:c3:6c:07:22:c9:4e:5b:2a:a1:2b:9c:7a:
- 82:20:53:df:a4:45:75:15:ab:eb:5a:c2:e8:f2:bf:57:f7:d0:
- 2e:b1:cc:10:56:0c:be:b2:15:72:e3:b4:c8:0f:90:fd:ce:57:
- 9c:1d:b6:cb:dc:4d:80:64:ae:49:4f:05:d8:96:1b:a7:ab:aa:
- 22:61:65:57:63:1b:7f:9c:81:f1:e5:cf:06:b1:6c:00:a1:36:
- 28:26:97:2f:ef:74:37:e1:89:7e:0f:c8:ec:df:ac:91:f2:e3:
- f5:01:a5:27:87:dd:29:b9:35:d5:e1:99:91:a5:07:31:24:80:
- 0c:7d
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH0dlbmVyaXplZFRpbWUgQ1JM
-IG5leHRVcGRhdGUgQ0EXDTAxMDQxOTE0NTcyMFoYDzIwNTAwMTAxMTIwMTAwWqAv
-MC0wHwYDVR0jBBgwFoAUFIYULmBitKSIEuOKq3gXou7RMBowCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEAykt0TjAaw2wHIslOWyqhK5x6giBT36RFdRWr61rC
-6PK/V/fQLrHMEFYMvrIVcuO0yA+Q/c5XnB22y9xNgGSuSU8F2JYbp6uqImFlV2Mb
-f5yB8eXPBrFsAKE2KCaXL+90N+GJfg/I7N+skfLj9QGlJ4fdKbk11eGZkaUHMSSA
-DH0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13EE.pem
new file mode 100644
index 0000000000..921fc43d58
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimeCRLnextUpdateTest13EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F1 27 41 23 90 1D CF C0 11 84 D1 9D 51 63 3E FC FB 96 12 01
+ friendlyName: Valid GeneralizedTime CRL nextUpdate Test13 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid GeneralizedTime CRL nextUpdate EE Certificate Test13
+issuer=/C=US/O=Test Certificates 2011/CN=GenerizedTime CRL nextUpdate CA
+-----BEGIN CERTIFICATE-----
+MIIDsTCCApmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfR2VuZXJp
+emVkVGltZSBDUkwgbmV4dFVwZGF0ZSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMHMxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMUMwQQYDVQQDEzpWYWxpZCBHZW5lcmFsaXplZFRpbWUgQ1JMIG5l
+eHRVcGRhdGUgRUUgQ2VydGlmaWNhdGUgVGVzdDEzMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAud22oPPBDzylInEUq9CguXvnLa25adaw9FxosWhpznk+
+e4A8PL4ObpbKZ3BD4Rgw7l0ptJ9+EXx5JuJNkjjrqjhq92E0APwXSFl+ZBLLPfsC
++yPJoxRQ4NjiCNHrFl7ljDSPPKllzSJxIE0dUXpan546511kuDp5VYiLb3aJUFiZ
+qLh/1uTYqWCZ287zkgcG6rXllTbbBrhOoUhoIt7BCudz8kKr361aJ6CRpgHN/Vq8
+T5xW39XAAifUCiql6gcR/iGLekoP6Ea5xWlCejwA+a6k88boXm22LAx7QWiFUe1e
+zLHZ5Yh4rXtBamDYxOdAk1GYwYAnjBybuGWBxADWXwIDAQABo2swaTAfBgNVHSME
+GDAWgBR+KnXvDDbHS+cg2X9hSEeOEoMaLDAdBgNVHQ4EFgQU4997s71PDhzkuPqx
+jV3e2akJIdAwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
+ATANBgkqhkiG9w0BAQsFAAOCAQEAOaHsLRHQVH5gJ+hxdHvna+IUoWjEE2F5MQbT
+bM998cWDHqN/OAggEpYV+Lihrz3l2zZ3efue0woBgBfcjr6LkPpLLR4jqn3cPtQV
+t9BgXO6fLFntkCvvnTDDFRbXRboCpivS+nS7J74tabTtbcxVjTnnRky9HQrgopz3
+hz+oGR7rFnB6fB1D/ic9BWKtwx+BODB0eK7WmUK7pLtQJaz/wimIhs8kD0X6AB9g
+XWVlBsXFMemvFglNQvtfH1uPPzQk6cZ/JDp+LvLWAMP6HK3ZVdvaAVU95DRm6gK8
+PoyWsA4vasObByzNgCtKQSxULkxjjRnbZRN5j0uRN3mjJ1fKEQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F1 27 41 23 90 1D CF C0 11 84 D1 9D 51 63 3E FC FB 96 12 01
+ friendlyName: Valid GeneralizedTime CRL nextUpdate Test13 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E6118688A1731D88
+
+Dd1EFLgiRKRMZTUclex4I2UHdo3uVBIINpHRPA9+uia/saAEb5j3PpvBxOKlbI9A
+akzemvAU2AQWIrMVw5+kIiSHtj/JLwEmXU3Hxn352sxA8hBHSfbO1RDV3+iXpHBy
+DXePvEo5DloF0z81dxB579mGhhlZm1jh1ILrOxJa4rLRCXbQDBbautETrp0kkVZ7
+uAzEG9PQGH/5y1mdgkcJ7g5s7Hjtj1aFbSJIY4wdBmXzps9RHHgG7is+AKPHDNA2
+hr0P1RYC4XPyRpd3Q6hXaxgS9T/UfZ11epoa81XeRwlc7JHshZw+BMeQA8sJkVZK
+tduaOOa3OpeSxfKeBEbFBRylPgP5SkmteWMmvbDsVBhgLqhDRi9M7L9e4Ty8en1L
+q6T+ffPOsESh7wEO1cHUIDT7alY/zWuqy4uKmSUOEGWjtEOUSRtDuIdZz1uy7xjz
+/iuLLZfoZg/iJCZo8Gvlw4MZwDRn7up4yi4crc5DTxlA6rF0t3GMrxdw5ofVcYhk
+tviu6dbBTAOMyMEKpUKxt6BVUzX24vqO9XuFNFD47sNz1zV4n9eleeC5xSdPpgBE
+jEDZdo17vUHg9kDzNn5mxEFWSBXk20dJCCFIgQbCubZFWj+CqYbaTCDNzBeCr0/4
+DuQqipAn0qat1PqZ9JkgaicK+i4tF9KxmOpWEOL1eWGKbSO/mmOWjjP5+8/OOQta
+jfEVNLmaeY8rdrftcTnOBBA09aP7dMX0habd73Pvhw9SGim5j5waSkLVR2G8pz51
+I0X0zHwGY/rq25EmDgqhwMTIbkrFGlruuweCXrsHAC8ZvFmD5ESplZ1fZri26ICj
+ZEkHuN1HSU/uhZ7Ln9u0cJs1htegtu3QFszdoyFKH9HRIDfZc+ia25drom+uDFgA
+f6ejKK7egCMVyME4qRKRlNOngO1OLBGgreP+VkQv985JhRcp/UgT3EV5I2qUabeS
+r+LFQg502lKogv/2cSfv8oXs5vKmSFQ1c0pGE4/m+O0FmyvlNWlJyWk4B1zu77fL
+/hp2Ovo2L5NCOsUWa2KayDJyDfUa9A777AvKEDSeqA/CLT2zuMnaGI6WiiuE8l1s
+ZoJxiPdErPFLG1axiaM5gMppwG2KG7sx68uPxImxNf3vmoQI0A6x38TJ/UM9uVKN
+Z/Ul2UCRvmX8WLMyGR2+3OJ4IcI1zHCXa3kRybqTLy9/MQc1ytclZtq7W25YomNS
+wJ7rFJB6XJmqsTgFGpvBxb/C5S0EU578m2ScQ2eYb/8rQh9cFPR09TQwzTgcKldc
+WUV/Ii3PGPqfU+YQbB1CW3oH2yd3KqO1ArE8Agwiy9Lcj1MZf1fib3NDcEW9CysV
+CU6mO5j477pEdhhh3YVex2oTy2J6sc854OpeRHjmtRmY5P1Lx8Um7zgru3aYlBiL
+9xIIvEOGYL3jJhzRk6FFEyvwd8jdzx759qFiwqpeEZig5hiki5nytjXoWc6YsRRW
+ktn+41fRoljfyoud/oudnz/R+htweMstFEakD332taJrLh54UiphVSccvZxLUKzW
+M1tSCjeKBdpcWAfZnofwMJ4EVb1HV/VNhp5Wb1ODJKJCOuMjKX+fFQKrQ7br0Q3f
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8.pem
deleted file mode 100644
index df9cce1587..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid GeneralizedTime notAfter Date EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBCDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwIBcN
-MDEwNDE5MTQ1NzIwWhgPMjA1MDAxMDExMjAxMDBaMGwxCzAJBgNVBAYTAlVTMRow
-GAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFBMD8GA1UEAxM4VmFsaWQgR2VuZXJh
-bGl6ZWRUaW1lIG5vdEFmdGVyIERhdGUgRUUgQ2VydGlmaWNhdGUgVGVzdDgwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALuN3xhLcTamwSrg/7HDqFvodu01X/59
-oI6coV90K3bmWeFUWcw5ZNfns6jjgQE1kexWBJIFACT3kFzmEdQ0Diht+5/uEeSO
-PkOZPDfVFZRsZlKiP4F5JRag4K4+Wfrt8M1vzLcj/TRtui1jpwyXKD/Zjtsye3j8
-MayBGrcgQWbXAgMBAAGjazBpMB8GA1UdIwQYMBaAFLcupoLLwsi8qHsnRNc1M9+a
-FZTHMB0GA1UdDgQWBBSikE0CsoDg9dGVN7xsWnkXPID8kzAOBgNVHQ8BAf8EBAMC
-BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBABG3
-77d7XM2ib5Bv0aVQKTDlDZr1fzLxv0CeJt/o6io7LL8Z9gC0ZdoeiB1nK+unnlu0
-GFMygOHAwKUkKMkkChIGFyYSEPrqQV5811YETya4JBE+Ou3GQ2oKNNL49+HP2yTm
-aWT5eiTEg86gF52K2nPXRNaNGYHgT1+Ez2HeI4pO
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8EE.pem
new file mode 100644
index 0000000000..82c7ff7d50
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotAfterDateTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C8 C7 13 ED DD 20 A4 BB 2E 92 00 DB 2B 34 A3 A1 63 97 26 0F
+ friendlyName: Valid GeneralizedTime notAfter Date Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid GeneralizedTime notAfter Date EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAgFw0xMDAxMDEwODMwMDBaGA8yMDUwMDEwMTEyMDEwMFowcTELMAkGA1UEBhMC
+VVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExQTA/BgNVBAMTOFZh
+bGlkIEdlbmVyYWxpemVkVGltZSBub3RBZnRlciBEYXRlIEVFIENlcnRpZmljYXRl
+IFRlc3Q4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3JsqVzyLOC5n
+QkAT5iNLE/lsxf/3jU8ojrjoBbTYdgaUaun44lvZwesI/WEd7WbmIk4bnuLDk2pc
+VQY+UnqPJS3j4exQshmfKSwtJnfnqiCNDsujHAkHP0ETMQGbQCfz2sibFf9TFXrp
+mcIHRX8cXIFcQvcvGyKUzO6pkZXRQ5CH37tVWJCj1q8oACXaBqdC4VRKYFO0lhWs
+epDrq2xWlvF7pOEJr7MvyM2tqaYFEKVgCXomhY1qxY3tWUr9n2OIEOt71o5+671O
+Mqd4cZJREF8vpkelQxEGMMu7DR1+pGbkrxXqyYAmjDE5czfXQOLHrWKJlXsnv37L
+gSb0h6cWyQIDAQABo2swaTAfBgNVHSMEGDAWgBRYAYQkG7wrUpRKPaUQchRR9a86
+yTAdBgNVHQ4EFgQUMT3myQxH68BT3YDCOy2mohpE7iAwDgYDVR0PAQH/BAQDAgTw
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAcDEv
+K/j/gsTTaDIPxcb0iblmMtDBoM6sVI1hp/cpXz47WqedfVQxKpMAj+nyCepRHFw7
+tnjoWzlpDJTbzDX2RaQTyzzZ1hoef9po4LSjt+ukybp0D3bf4m47s6cat+f5XKME
+BqLI+2C9V17tBV6ZM2LbCncc/RnHXwaPCJQUdQV4QOP0+aw6/pmCfUJH0Bn/fM80
+gPxHN3yEds/Xes+JRf3dzFMcGso1IA4fx/S3DqkT+uJG75jl2cI/SUZCdw6G5Aze
+h/wfRrNGyqQYOsgKkNION7NjDmeZ5doj4Nk1MaaYZmm/Znn83fMtXuGchn26BmIO
+UNDDn9zsAsqcF4TkGQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C8 C7 13 ED DD 20 A4 BB 2E 92 00 DB 2B 34 A3 A1 63 97 26 0F
+ friendlyName: Valid GeneralizedTime notAfter Date Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B452F5FA65D5D9EA
+
+pKSxE2vluN/rwAKlIlcx1ujNGmCSZcAUM2RCSJKtU5dfviE+5CrOI2QD5ggla6mb
+lVYfxKHwNl7g5gJ1TA4hDQZKrxW0y0g1wX/88b2sRtkHhNQVPuh3OLo7/bl2dzto
+ndLby7Cdys6NuLQNgVZsa1Ysl7yNr2cmhT5q8D+No4cHHGm51GBwj9FWOBQrFb2v
+EsmSoxOyCcunZ3Sl39M51CH/gaKtGMFfTvHs2N8dj5zdD8ncjylV0SMcO/64wH1o
+bRwfkC+zDfx6KFXd7ROuR4kEbW4tb1Je7zMEc8fz55p8rKP9dfzlEVkqGEeKLWG3
+Gqp5JkUghtvpeHr+PDS1w5RrIfNNIWjY4/AJvOh2EJCh32il0X7+eOrEGYeP8dL+
+f8JxuUBXUEAfkAxGkeqRNFTT0mpXSXcRfnNwiuHvT9fX5h5E//YKgTvRQxBQicPI
+enE3FXA+E6iv63cOGhYjbTvrLvt+GdfZVfUPX9ieUGLbg+cVhiGENub9PHrDD5n9
+v4w21qEuNDWw0EWWzuWybNY6DU0qeu6lbh8xEBxHSy3FsiDIwStqXGhs/nl+w7qx
+IaCo8aP1/zMRXGEAFH8oGYtE+EHDBvJZfuMRVlM3FqQLyomWUtX/9BHapen2/ZzY
+MlAtIlvYu6psP4WLzGaagfRPWMlrI9QIvbaDfdnvzZn4yu6wJ8Lqsc7iu+8bWB6u
+lbvvxTa/YlFuyQEizlf0UJvV9fh1Nb/Hl6GheN0BMqGYHPaAzi8bac1S48+RZya9
+8NPvbxHkrKYV0+RORm1iMaETMz5cgU4BOxBATQB6OC+zDKhf1BMaawp3C9eCm/+d
+9r+tTyfkGMpusuLzevhK5utcqRXjHbfpoazJgnNqUVQrurxG3svrZFY8WdrgRl+m
++nEpoy1Wf8kpX5iTsAdSzZTKdFSKSSLqkPEywmGGA5T/XRAWMQ5+bhkZuPegwFh+
+cc1xhNa83bSlAXhWKOj834WH/CZFa9VGc7q8FuvFXHYzwLwhgAP5h16T3ylV6l6a
+E0/GvNXkBMOK0U0vwXEgXgO7n51peg9KkQM+fMITGznk2QVFu5nB40hkmaN+QAJs
+eBt6hsTwSvL1BtYvS9EC5SqDp/8ot+yDL/HIx+aDon1KicQ1n2D8ZpKtHuRmtgD5
+gdGS5tREqiNTGnklBXsrBJPZodafcDMnwOYSa6ZCUQMo2PDMwfvyseCCI3QJHiyM
+6IuLT1ErXLc/qldNUyO41VwP5GPG6UtrxwS6XGOuK0keTF9oyVcekFjbm9qENqyL
+Yv8XV4hj92+880ZOhP9WkG2QF6X5GehzNuRP+OjDjKU3e28H+rnCkptZcsBIGX3x
+bTRA/g/8InsdGizRBzUFIoQEOKQgFwjsaqLhF0PewSBsfPZqJwyr8DlsrRKVy7Pz
+N7Q49srE3D+zxZsaF0gAKgFPTgqnqi89DPpIs+REidaEaeOTVaiRyJpwadrdLwas
+Fox66s4HpgSVH6ygWl//sK98O4ijqHX2Xbptqioc/8sWJRFqSkMGT8zpJIzREtAs
+TgEYD45Dm5L8wlZYt4oneFY50FOlJ8VEaa0n/5N/vowj0Y6Yw5tgOg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4.pem
deleted file mode 100644
index 8e57181bd2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid GeneralizedTime notBefore Date EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBBTANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwIBgP
-MjAwMjAxMDExMjAxMDBaFw0xMTA0MTkxNDU3MjBaMG0xCzAJBgNVBAYTAlVTMRow
-GAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFCMEAGA1UEAxM5VmFsaWQgR2VuZXJh
-bGl6ZWRUaW1lIG5vdEJlZm9yZSBEYXRlIEVFIENlcnRpZmljYXRlIFRlc3Q0MIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC95eHxRXrYP2LBGJtgztiha9W1jRBa
-tkZEgkmukmElQlc+Nz/uh5pRNpJbg7b+3Mv6XKMr0qncHxRIaap0sD3MY8CQOeWi
-IHCEtT5XGFy6B6eGpqfdejjnvN4MHVdd9uBaxf0Rbo7JlxXLCT5ZrYMNbK128Toq
-qhp0MV1GpfZ1DwIDAQABo2swaTAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPf
-mhWUxzAdBgNVHQ4EFgQUeJSUUvGhyTgLeYzfK/SqlRZsvacwDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQAi
-TR2cFTtIDfG39B3eWiPgzxJebkwj3E1ZcxAxzGcYHoSScb79ueJ4ERjgskZWO7ag
-oNPHokDXVScVCIjeYTG540+aQNawBa6L+HhIMNIuzHw190nKXMOSqPmNk4vbYPwk
-32dtRrn1hIUDujUwTkW5daFxJ25HjyUfVZCMQuwXqA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4EE.pem
new file mode 100644
index 0000000000..c3329e12a3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidGeneralizedTimenotBeforeDateTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D0 8D 9B 81 92 7E FD 77 C9 D1 4D CC 59 10 C2 41 BA C9 F2 F1
+ friendlyName: Valid GeneralizedTime notBefore Date Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid GeneralizedTime notBefore Date EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBBTANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAgGA8yMDAyMDEwMTEyMDEwMFoXDTMwMTIzMTA4MzAwMFowcjELMAkGA1UEBhMC
+VVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExQjBABgNVBAMTOVZh
+bGlkIEdlbmVyYWxpemVkVGltZSBub3RCZWZvcmUgRGF0ZSBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0NDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0TXsIKGzxY
+iX5lX1bWQb/MZ9pouA3EQT8bxiWbQe3iWrZE5xIU4jFopRL8RXASP+lQIROJWqjT
+GtZhEaNQyB9CmNSz5w3Q/dME6LPrdiUF63klD3lY/J1cJheLov0Ql9Rshvrcjluq
+xR0aMebihrCVAbGB9fjapEf4D8xtm/l5SMvO7olLyDZKkibHgmzgZ66/ebGPrc3o
+OmxjoqvkyyH+vlRQgfv4oAVFetdVyYB8i2eJp47d2aFGTsWmn6zIoM7fy4iuu0kK
+07KGV+RGIif3sHoWXv2Uahz56Y7MGr135s/S8e80jA4KrfQpzqpN07ncyEtFGEs5
+3WeTcZi5zLsCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2lEHIUUfWv
+OskwHQYDVR0OBBYEFM3r3nHYztXgRqo9a88ywemUwz7vMA4GA1UdDwEB/wQEAwIE
+8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAHWf
+JSZe+DwVSi+fwy98C4I5bZrrkWUX5P3ffOQkO1NrPjVURAvXqyTXbzYcf+PM5W+k
+J6XD2jJvNCRNQ2R8AIdVbG1fIfAzBR3PhEZPL9qKhi2H1q2IloF1Kw26ghxS5cAF
+cfwkOyQgNUpyFp9kKT2OE+3GM6/zf8SVy0/bFL6Rf/5yrJ273Of0+ymy2CY/irTM
+/4X7WLSkSGyPz9RHiT+LoRSel59eclRDxQKXgyToiTgGTKXbEFcilTBT6+0WCgcJ
+3Lw5qc+s12lQDFF8T903ef6C77dPOYMcxnCD2WlBInOSoqsGhn8NDf6YQYsDFCbl
+Oj2T6kRdn8YUigjmrhM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D0 8D 9B 81 92 7E FD 77 C9 D1 4D CC 59 10 C2 41 BA C9 F2 F1
+ friendlyName: Valid GeneralizedTime notBefore Date Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B9767531CE04E789
+
+YmTFYhbZiq2EbSicLy8vgHiI4r1QOxqwYVNXc6Uy/8Dakry0nY70j27xKuqmZVqX
+tY+e9L3mdvzlLLaLZ2B01uhBWtfxy16fqu87gjWfKCcQ3oJDMnjQHN/LmLOvpCfE
+bpC+xfvVZSuK+/gqfyVywcLqFYwyYG4LSnnSzIm95y6rCGGBxBvdFpsO5+QOASMF
+0e68jsWuj9CO1bUoweg4AWi/XA8mr7OCLAQimCBw6feqiU/lmTOrcVLa2ckSS4Lo
+Lp7K+6pck6prAbxwjJMT40QbniZYZ3a6zVCFY2dHo+BNv6Yr/0ud1zBBjK4gViIJ
+VhPjY1fQ686pYQTSgQAWQ5vwI4M5mN5zyyp2XISuN2vIAxJiaGaEorNArB+sEdft
+RgNNW3A51M06POwAKzfw/S7HYWj03BO7chfrCkdlJt37fFNrb84jO0HzHv3w9DpL
+evrFydUnObVKRLIKv8tJ/v5P1yeaJ5wKAT1tX69bp8fOjFKgh80JNNdPnK1t7IDu
+2dUssf5qzRoi8KGISUkLDnveg4l0+cVZFobTt4y8D01N+ks1lPqKj4PyCBuxIBKb
+XNXQXVnCPbQT+kKy5MBab9/CMpR5tHw8GNGCbFLnwB/ovbaEoov6fr/Jg0f0t4+F
+zVcpNjWlCNQxVm+Qo3Ov9yhkpI/2B1lzodFYHcUYFk+PZlPKUYZmEnyuiiL0i1YN
+R2Zj4RUvnn0m0OCP2NbWOXIzC87Euv4+3Nn91KpcRd0y9tzDtf37TW/gIEZcotLW
++7sHoqm4i39XRrsszRGIZ6qL8WrZZJhoTw4hMQ8qNJ84UfnEk9tq1LUpBQQ0uJzN
+U48Xvjyk3F+WLVcXDLyac1YOrURbD8LCixbhxXXgHHTjUEGjbuoTqLT5SjL/f3jR
+WynPTmMUxINx/Aat7EPRtjWMAKU041mciY9V4QhADEWHSzMB6B4o1VHpAA5I5x61
+y2AL/grN711ZW0OxqmO1iHVWlyZm6/g15gJP6wImCJ3EowXrTprKTrq5RBITilyp
+xOjBBdFRCdCx1foT7Br7SI3MubG9dBmxZOLbWgTfCDVcXHIu4B5dIVJ+jKkKBW9T
+LNsjzXWUkWvG568Kf/HmN1/1NmgC4/z6Kr27IvShfeygg8a+46aj2Ve0QYZOMN2o
+cGl6nVuNEWBsanFu7ysn3i+KSYvvzYgiMvtIA1Ct0yFE/p40kC/0sDdQPVTL2KNG
+skKRlEEyIBLgeS2B15NAkGyiMMOeKGPLOlEvNTcV15ylTH7ml3vCI0kVN7d0PMrF
+6W/I7MabfxcsghEWht7tHXKFKXNeqc0oukqLgRIOtVOjjdutyCQlMvsKfQ1HA4si
+1LqPOnNSLfVDWcgSxSaYPiCV51SVLQEM5jIEE8B0X716QIoIkurp/841cvu3fM6I
+wTAgwyghnaomWchW8mSxg0Du/Kk6f4De9vZevM5I8ssciB7+h7cAZGeOzIksrjkf
+oVSw5V6ZEpoZmJbqHuYvho9SD6wHud+rE3PKcsR6GMYFP71K/6hc4anDh3qmxM5J
+PBCdHMD7ZmdikNGZVGoqr59u6E+ZQIq7lqP9crLcnnt9SEKRK+2bFw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22.pem
deleted file mode 100644
index ca7dc27428..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22.pem
+++ /dev/null
@@ -1,116 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKnNvKCUbOkr4mNPrV
-EBeh0vWaSj7DMTMuBhMM4N5zT6XkBdghaAMQis36dJASxXYtGiiAY0Wv3oicc66t
-vag7yMp7Iy71oHzCSrw+YF6oBOV+krjeaNIg/5/CGLkMr5KXC3egPap4fv/EQbAD
-ZbMw+Qndc+mnj7AAnfb8i2AJPQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUbMEUX9inLeCGkxlcC/BJuSVb6BwwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABA2o025rmbJVizdycoV/q2zarMz87Ki
-QJimcOjKcZTSmDiAxKCTYzBFWeUZWZqVDm0QbhOThmX5nkaYjiz3vLAgdDDUr6zA
-tYmNsP2oA7ajpSmcze5/VwkBgMKt7Al5w6xT91R0tCltLcppOPJhE85jMd724jTc
-XHLxTJCox/SL
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid IDP with indirectCRL EE Certificate Test22
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA1
------BEGIN CERTIFICATE-----
-MIICiDCCAfGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBMTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGQxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE5MDcGA1UEAxMwVmFsaWQg
-SURQIHdpdGggaW5kaXJlY3RDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDIyMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2H58UKDg/MSuu2itx5AvPDHHk0lMX7Bu3
-X3Vok97lKf6HAIseNFrZecQGe7RtIm3ICK1WFaq9tKE3MutSXNCcZ+CrPj0H/pzt
-jlFAlRN1jpTCSj3rVVAUpL9BCHMWrZ9qf8FVWgWI3YMWw7cgqC45VZxRYN0zyyGm
-pz4tN6pyTwIDAQABo2swaTAfBgNVHSMEGDAWgBRswRRf2Kct4IaTGVwL8Em5JVvo
-HDAdBgNVHQ4EFgQU7rkQZsqGMoKvXfmcukPIoHnHBC0wDgYDVR0PAQH/BAQDAgTw
-MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQBqHSrq
-s+MMY0Cfl9rlm+QyuARye7sTvTM5fQkOs/K3US5mAMfA+ei6Prb+u7FqxUya+Y9s
-6Q0AeDutkLkdJWPbJd7B+HsQCT/fWFvYE74YOOu5DTmtII5zVS5bildOaE/xTw2z
-stQtRX9MHe2JVh7WK/CA+TghpnYDlW+IG/iXjw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=indirectCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6C:C1:14:5F:D8:A7:2D:E0:86:93:19:5C:0B:F0:49:B9:25:5B:E8:1C
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6c:ab:91:4b:38:62:8e:f2:48:86:10:a6:b8:b9:c3:c2:28:e5:
- c1:d8:3b:c5:8c:6f:62:44:37:f6:1e:2f:d4:04:be:ff:bb:28:
- a4:3c:71:1f:69:58:85:95:60:3c:cc:f7:65:22:4e:9e:44:e2:
- 6b:45:16:9d:67:ae:da:ff:57:e7:d4:ef:34:cf:1e:86:52:13:
- 25:77:a7:7d:fc:ec:94:62:bd:b1:76:a9:66:c1:ef:82:bb:3e:
- 9b:21:c4:ef:49:9b:2a:e8:5a:ef:39:82:ee:da:97:5f:77:89:
- a6:3e:42:26:77:b2:15:97:c4:db:ee:ca:8c:ad:d2:cf:18:3e:
- 87:e8
------BEGIN X509 CRL-----
-MIIBcTCB2wIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBMRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcy
-MFowDDAKBgNVHRUEAwoBAaBAMD4wHwYDVR0jBBgwFoAUbMEUX9inLeCGkxlcC/BJ
-uSVb6BwwCgYDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4QB/zANBgkqhkiG9w0BAQUF
-AAOBgQBsq5FLOGKO8kiGEKa4ucPCKOXB2DvFjG9iRDf2Hi/UBL7/uyikPHEfaViF
-lWA8zPdlIk6eROJrRRadZ67a/1fn1O80zx6GUhMld6d9/OyUYr2xdqlmwe+Cuz6b
-IcTvSZsq6FrvOYLu2pdfd4mmPkImd7IVl8Tb7sqMrdLPGD6H6A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22EE.pem
new file mode 100644
index 0000000000..0b0792fda8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest22EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 54 4A C0 C4 81 72 39 D4 8A 4E 24 F4 0F 40 3E 74 F0 2E 17 1C
+ friendlyName: Valid IDP with indirectCRL Test22 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid IDP with indirectCRL EE Certificate Test22
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowaTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExOTA3BgNV
+BAMTMFZhbGlkIElEUCB3aXRoIGluZGlyZWN0Q1JMIEVFIENlcnRpZmljYXRlIFRl
+c3QyMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqJ2kFX3rhdZpTg
+Px6TrqsUoVkZnTV1VPB30WHjhSo8PxTV7IIrMS7+Yhe9EvjERdMFUG3bGYx0zDTf
+aUxhAq4zPlgrRpAd/sqGRjWFjuB++XEUhVHdxhUe/ZaPPqtfPlWDT1Qk+HqgMvvd
+o3F8Ajl08Rr1q6rTApSkSrpCsR6Wgqthi89kexDQblsnANxIdul2qW6rrb4Y+QRr
+pxOgBQx7qHUe/Xp/6uqCNUQKQK6Yio3bQGGD5bUnLUuUBNCxi8Y/7Phc32uSyz8C
+nz1wWjRtgUybln9BPvUbC4G5FwQN4t8J22o5dl3Z3HqCDfFuUnWqmvj6UYe7hYQH
+XaY0xm0CAwEAAaNrMGkwHwYDVR0jBBgwFoAUJfiv/K+2qRobeUvby2Qsi0uxFc0w
+HQYDVR0OBBYEFBoLIK5VtXkG9/HqwgoAXXFLiMNTMA4GA1UdDwEB/wQEAwIE8DAX
+BgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAFLJoesb
+KHha5M62n9PMG3uVTq7B5c297IXuHyQ8YrB9AdMlAGnFutnGalFB/F7hZxEGc9bf
+wV8d5h5nQeHQm7UVFwe77JzW8OmG/s1w2sNVsQIA1KLww/p9QUxyOt5sJtNRpkD6
+PBTCEzB9AGyuBCOyFEJYwai4VzVemb6kKQwxhOve6zRpqDInhxLMAbfpZUh+ZqLz
+QteK/QT/55XEbVS1EX8G1cwK6hSY+PzRkapFMJhkqPuwEprDM8V+AtcZqTnh/jaa
+N7XkfPUZSx8Txf5qUcVilaaQJXzua2E8JsGofSpjzAgYYle+U4YkAdNN0AeeO3O2
+87DalX4w2xAbULc=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 54 4A C0 C4 81 72 39 D4 8A 4E 24 F4 0F 40 3E 74 F0 2E 17 1C
+ friendlyName: Valid IDP with indirectCRL Test22 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FCFDAF609DC1BA80
+
+6F1Q05vjm3RZJ2xrIsWtkTUSHybgIdMkOmrSVn/WBbyluMoeCOgMoQRjkAHtvGB5
+HD4+MCchwd5HcxLscomcD7QCP05YNkf6aq2ItdFk6LlqeWKQ3EqF66Q8QK95N/CU
+iWhGmcZD2pS/3527McaHe1g8HRePpXEQWt2UR2DQpMgMc4TiHMPEVqrIP297EEkr
+uPrQuqCqsJh6d1h+MErI7ZRr1brMqtazPzGcD5y+XREgR53nUBE2Tgm9X/gIHHaD
+qVXLo3RiNL4fFfGmApgOrm79zRbbXd4XKemKGA+kbKicYKUMgfMSF3YMJn24qXSl
+AjoUZ8KK4MCgPLcvMgMD6eQ3n2BYeHf9b398cAy8DPIH/bLNhEds6B4Z6qFU/oPt
+VaCParF9FR0AaevuYnieNdKjmsQGGCe2+QdFCRsD5rqpJzsCAg1ZfUSdU5zq+636
+T7aizM/k3NoDf4OqkFfkjc9nOAioYjD8XWY3PwnxslXk9wS9AIMp0yloPjDZtnL8
+ewspHiOpgDHagQ4yE5ZZEivU/7K1CPxAsmtMZXs4QZx5ABiF1R8AQKdAPoL3m566
+7zDBOxUGQlUU7b6rZXeOFxr0iUMfLaR+FJ3/chS6dv2QwGrxQWSGNvcvN3J5coNX
+fCVlheskFBeBxynRAyWz8Akb5miTJks5yHR/e7WL59gLRCBaHUV3DRod2999x0Ym
+BVZ7o4mAN2a/hukaeApxlZKaAvSXyNoBGAmyRd70kKRB0ndvQQJmBAvMPYyCqYef
+rTt3l/I5Dttv4uIXtb+3lAlohVrEDHF26KrrPDmLRET80E452o3HVGLYCwUgb/Ea
+9avL/mXBiyg+4JdKsoMZ9sJ2heRja/zxyZ6Fe0eBEKt0HLQVJ2u3urfkETqPLVqQ
+ZRX/dgY96Y6OmV/3nLojs0DeZYiNoo9TbpSkcccfggkigRV+ZQRub1boGTBC9if+
+56V8EkNHfmgtL2L+S6jYP3keQBYyFeYrNzpukekB1J4Fvji+hpeJO7mn9VQMbPQB
+ow/bJLDfSmVovsii80seOztMK/By4h5N5BPkRkJxPqF/Tulq0IqhZ8Wj3XBDnGfo
+0PbBDHo1ZKwQ+DgLs8/HDMfikv+OxLtBaNUer8hXhJQAvNVGS2i7GyW8e+BulnIj
+QsiboBoFmIgy3GoCZb909VLGxQszl/g/KPskT90XuPLPlMg1FZA7I4SiN2MRp0AK
+fvao6q1ih9X1jcKinTMDzsuuzNIlN4hongKiZPc1c5gVQtoGDn56D72DS/LJ62ql
+AEXwxTl2CO0xQrIHBft5woA7uGKUOO5RCxXLcU9XK5AdgYMchrR3YROhFxR6HYid
+k6zmlUNrxRnJ2jCNnQTfMG3ghqEJaqkhmAtCkVeDzOJmI0M1RnTjs8Vk+sTT6+v1
+dIF5Qs4Ok0RoYti707GGcWFzVQCb+WkyTM/iPtnAL54fKJaegH5FQ6Bt4fq68ToG
+lqZOyp53JbCaekOIGOivpLs2KgqHQyjnJGsjhoULqIXtdryjChtaILDlCeGFdqAA
+H3NocCuJc9avDujeUgzmQ6UkuNPSJ+vQe+Dz7qmNaOOFA4CG221euA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24.pem
deleted file mode 100644
index d069a80b26..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24.pem
+++ /dev/null
@@ -1,137 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKnNvKCUbOkr4mNPrV
-EBeh0vWaSj7DMTMuBhMM4N5zT6XkBdghaAMQis36dJASxXYtGiiAY0Wv3oicc66t
-vag7yMp7Iy71oHzCSrw+YF6oBOV+krjeaNIg/5/CGLkMr5KXC3egPap4fv/EQbAD
-ZbMw+Qndc+mnj7AAnfb8i2AJPQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUbMEUX9inLeCGkxlcC/BJuSVb6BwwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABA2o025rmbJVizdycoV/q2zarMz87Ki
-QJimcOjKcZTSmDiAxKCTYzBFWeUZWZqVDm0QbhOThmX5nkaYjiz3vLAgdDDUr6zA
-tYmNsP2oA7ajpSmcze5/VwkBgMKt7Al5w6xT91R0tCltLcppOPJhE85jMd724jTc
-XHLxTJCox/SL
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDblDsGRxVahA98R7vE
-/DS4nbSbyoerDINPIyc8wkOtWcS+y+f9O5IIdDJOZm2I5px1PA840SXYHh15o3ZW
-Vn4gFU3AgKF/CWMJ1g79LAYAMnQN/T7kSfuz/0rqhLH9tjz3Qtjt+/zy45YIny80
-7JOBLH3eLX0H2aOmsJUenp5ExQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwa+CD9XTTxDwMWI8WIm5inS7nAEwDgYD
-VR0PAQH/BAQDAgIEMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAEvc066az+E8sftMAgkECVeJVw0Mcr2y
-YlJ0SAbZUNaU7KbzXxm3j8Q5v8K8GDy7EB4H0Gyh0vgsbChTAdLip7xQf7V7SetA
-nE66H4ikF/UAhXlSz+E48Qe2+L3w2weGbU3zwmNMeYkI6dmGFMfEut7hL9ak0Ulc
-0meAGzOu5kHt
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid IDP with indirectCRL EE Certificate Test24
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA2
------BEGIN CERTIFICATE-----
-MIIC4DCCAkmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGQxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE5MDcGA1UEAxMwVmFsaWQg
-SURQIHdpdGggaW5kaXJlY3RDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDI0MIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfPjamOqOBJ5I2GqRFerJm5J5EGXpY0CGA
-2i3yoxIxrL4B6vuDMX7x2Zh7+JRcggTd6xwFetZeJWWLahi51RWjfa3RKfwa3/wJ
-yxCvJJfDAdr0zZE2NjXSKDWBdtYxpqvOo/8TCYIvrzKF6kQG44bZ6biAIC30T9vj
-Kezab2UgwwIDAQABo4HCMIG/MB8GA1UdIwQYMBaAFMGvgg/V008Q8DFiPFiJuYp0
-u5wBMB0GA1UdDgQWBBTmjKLn116swFbGYjGlN4lIL3ZOzTAOBgNVHQ8BAf8EBAMC
-BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMFQGA1UdHwRNMEswSaJHpEUwQzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQD
-Ew9pbmRpcmVjdENSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEAe+QvzalpHWA4qr6K
-kSqLzdboAOHGA4+9IYaqUm3rczXhCZrk9cJmWTX7l3grLw4NMMGYkpvy+K/ZRTo5
-7qatlnIg1IxOuR/FQjQUZa+qvhv261Dlk3dH+QlApPxEZyjwCmu9qlXuQaLRWPVM
-Q5FPPtw73O3MCtrfR0D6/mS5zoY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=indirectCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6C:C1:14:5F:D8:A7:2D:E0:86:93:19:5C:0B:F0:49:B9:25:5B:E8:1C
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6c:ab:91:4b:38:62:8e:f2:48:86:10:a6:b8:b9:c3:c2:28:e5:
- c1:d8:3b:c5:8c:6f:62:44:37:f6:1e:2f:d4:04:be:ff:bb:28:
- a4:3c:71:1f:69:58:85:95:60:3c:cc:f7:65:22:4e:9e:44:e2:
- 6b:45:16:9d:67:ae:da:ff:57:e7:d4:ef:34:cf:1e:86:52:13:
- 25:77:a7:7d:fc:ec:94:62:bd:b1:76:a9:66:c1:ef:82:bb:3e:
- 9b:21:c4:ef:49:9b:2a:e8:5a:ef:39:82:ee:da:97:5f:77:89:
- a6:3e:42:26:77:b2:15:97:c4:db:ee:ca:8c:ad:d2:cf:18:3e:
- 87:e8
------BEGIN X509 CRL-----
-MIIBcTCB2wIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBMRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcy
-MFowDDAKBgNVHRUEAwoBAaBAMD4wHwYDVR0jBBgwFoAUbMEUX9inLeCGkxlcC/BJ
-uSVb6BwwCgYDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4QB/zANBgkqhkiG9w0BAQUF
-AAOBgQBsq5FLOGKO8kiGEKa4ucPCKOXB2DvFjG9iRDf2Hi/UBL7/uyikPHEfaViF
-lWA8zPdlIk6eROJrRRadZ67a/1fn1O80zx6GUhMld6d9/OyUYr2xdqlmwe+Cuz6b
-IcTvSZsq6FrvOYLu2pdfd4mmPkImd7IVl8Tb7sqMrdLPGD6H6A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24EE.pem
new file mode 100644
index 0000000000..158615fc6a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest24EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: FB 70 4B DE 3E 97 FF EE 22 28 24 7D A2 8E 92 7E 7F F7 4A 3A
+ friendlyName: Valid IDP with indirectCRL Test24 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid IDP with indirectCRL EE Certificate Test24
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA2
+-----BEGIN CERTIFICATE-----
+MIID9DCCAtygAwIBAgIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowaTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExOTA3BgNV
+BAMTMFZhbGlkIElEUCB3aXRoIGluZGlyZWN0Q1JMIEVFIENlcnRpZmljYXRlIFRl
+c3QyNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANaATLttW/ZFV2eW
+ylu7TX/3e1eXb0QwgbbI+sApv69RhLxQT0hwCVU4Dm2dAEgYo5i8oOi+rTOlnYXU
+4J+v+Jfpr0IzfX7MnyYh4xnkHb7+zZtPlbOJKR+F1+gNRAyWi9vMXNr5Yce5v7OW
+hvlJdJMbGTC+24xywS8PZ0EjTIlLnsgzqEY4y760mvmdzQpw22RHXZkqD8XYjw3W
+PmjJKJ+/YhMh3I+VVr4UKW7B2f3RglOyznk0XJUFM5Pw+6XuFbA26DG/Awm4AHmw
+fTVmV5j0Wr0T4zpqcZWC7mMRs4ggY1mNDfRdH6vOj4ShyZVPhHT1FGXykS3BGp+1
+6mgMC/0CAwEAAaOBxzCBxDAfBgNVHSMEGDAWgBSII+Gzs/Js/jGpvothqjuShwWk
+ozAdBgNVHQ4EFgQUY7Pl5pwRT2IfHI3sZo8MqlHb/kkwDgYDVR0PAQH/BAQDAgTw
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATBZBgNVHR8EUjBQME6iTKRKMEgxCzAJ
+BgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRgwFgYD
+VQQDEw9pbmRpcmVjdENSTCBDQTEwDQYJKoZIhvcNAQELBQADggEBACWXiBBJIk0S
+WXcaAbszXf9HPFRQ9ntKHreNu9ZjWlLv1gc3WVwZDyRa296+uDyAfetZrg2ViU6I
+VCpfmTRmvBfqJ6TO9qSLN9wtfkoAqUxgX4iWczOAnM7S9o3nQOHGRehAw87ub7o0
+4KbwoOENZxqTF4xNHGzw5ZtQIe6CWTMBUN4bnrQm2zt4kzXenxe68lcr3q7JrjhV
+RGh3e+jSJZsy4HuaB79OTFjHQWblxXGXzIPZfRZ/YUJbRhTPpD1ToQIdu/c8ag4h
+6ZFKeeB9pUPruCLakD0WSdCbWW/Fb1kVSLWHM9R7dAVCw7ccm6K3QfAzJK/FhwjY
+s4fPLXGaPrU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: FB 70 4B DE 3E 97 FF EE 22 28 24 7D A2 8E 92 7E 7F F7 4A 3A
+ friendlyName: Valid IDP with indirectCRL Test24 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,45333D253C999BCC
+
+enI4SCgHHLCMKR4XZhjcbC40sQHu2+JEmMmcAfXLxy9mxt8zGpzWDbTJw2j5LaA8
+3TV97t5HWKpfSdOG4Gfswp02EpdZeah5AdSE640TF5eoSv40OJUXxEpg2KhxdFGG
+iFwK9LBBiG0ppx02blIaRcBEnQI8Gweq2lGJy2xsT1IpqnpSqSltwd9GEKicG3mP
+rmdE+MClY1sOadzZeoaptABfftFtJtkKCR7M9ZDwgh0etnJr4sH2C+itxGxhmzkz
+GwT4hRlmCXMlL1n5YgKx4uHGTrwA9DOJAZ3egMmrvMvF0Ohe13D38kD7pjdbASrk
+RzsqnfvCAmZsyq97HsoL4iHO4l/s0u+xioM33ShyZawN7p+sBiZFmuKknl9NyzHx
+ZQ3ZjMiFTLm6dJ7cg7vwU0riwlY/yU0M+Rbbc0aIXkPog4YdZkeFrrrE0OnKe8qo
+eWJYd7VRsGzqQ4T3OSYaq/yJCbjtAJBZH8uaGRI+c79tg1yuIIG1kwd/8rg69+6v
+QPpcckMGcSbjliAydo6nPYABMoBuyTbF40MXS/hYTlOq39enxSqaEqO64YvDMA6w
+mDcicf3Ymasef4PFy0htwGPE5iLhLWoPpPpnuXCHZI0T4nnlwS31rTlV2CRyqwzw
+R5OWgJjYozYzJbg6IJTFohDvQzVdXvXYbt+P1Das/lJuOZ8uZE1JhL7Yurzil8BQ
+RfEXFrZWtwc9b9qfsk9THyYmPPrRt1tl+UGh65TCM09ar58T4DPbAkNsyflupYiy
+r7FILbd9GbF3dZOrvlnvr328iFaywCHG3ZtArYAz3PhypQGtZdMU15n8kL5X7Ndp
+RO7xWVG1iBywHHz3yg5EyG5WW8Ajtn6xVxP0Zj2rGBwJIbpntvHy4LOfdGpRY17P
+ScENZWiGg5qizI6SS1YYvuOenBL0VV7ciAxoWP+mJLY33XlTz5nuEbWUVw1jzka6
+GQlRJkgArBwtsaaZg98s9t9qiDIzvKvCbUbi5WLF5g9AoTlNmKC9hYRPDJhcQkNF
+CIM9YtLtjc7M7qxE1iVfn1S1S/WXxhc8KjCuAVknsRbZmrCeHVE5juyXhcUTBwNA
+hdeeQ/ofp/HoZBQontU8cljhHOp9gn/XmjuuaRCY8KPW0NrwQD12NdOzAt0cTQKY
+76+yYWup+4AOad4NaRUbc0yL68EQ6eBkof3yRWtpMTF7297C67yR2mPNTIu2Tqpn
+xRHFTt7VlOa1DzioBVqxBTY/QrPfDWqLn09llFo9UQgv8jyJiICUd0KuqBkfgzh4
+6em0H1l/Zrjj7wrzEA0ah1Gt+qo6HXTeF3Ji0P0XsRB76KWXxdvEHh3ERo8XeeL1
+RVeSQIwi3dp2Za27XPBjEqAdw36rjTnqw3S+MUiw2T8RZcXKLl70r5vOWgpxm3rS
+Br1pEJauMVQHAppg1nfkTHhFdOhHozMoiGjmqJTLa0WQDH/Es24Ai2QT/usVqiMS
+KDbFq4RrCdNPSghgl1+vK9+epdZKOh5rmHGr+XO/ir3ivPA91rMFb7PoPkrkSTpM
+XSzrD0g8Mu0EgJUKHHHa6HM09hSQYdJitUTOgKIGBGSYaRx400n8TQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25.pem
deleted file mode 100644
index 9861f0f70b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25.pem
+++ /dev/null
@@ -1,137 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKnNvKCUbOkr4mNPrV
-EBeh0vWaSj7DMTMuBhMM4N5zT6XkBdghaAMQis36dJASxXYtGiiAY0Wv3oicc66t
-vag7yMp7Iy71oHzCSrw+YF6oBOV+krjeaNIg/5/CGLkMr5KXC3egPap4fv/EQbAD
-ZbMw+Qndc+mnj7AAnfb8i2AJPQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUbMEUX9inLeCGkxlcC/BJuSVb6BwwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABA2o025rmbJVizdycoV/q2zarMz87Ki
-QJimcOjKcZTSmDiAxKCTYzBFWeUZWZqVDm0QbhOThmX5nkaYjiz3vLAgdDDUr6zA
-tYmNsP2oA7ajpSmcze5/VwkBgMKt7Al5w6xT91R0tCltLcppOPJhE85jMd724jTc
-XHLxTJCox/SL
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDblDsGRxVahA98R7vE
-/DS4nbSbyoerDINPIyc8wkOtWcS+y+f9O5IIdDJOZm2I5px1PA840SXYHh15o3ZW
-Vn4gFU3AgKF/CWMJ1g79LAYAMnQN/T7kSfuz/0rqhLH9tjz3Qtjt+/zy45YIny80
-7JOBLH3eLX0H2aOmsJUenp5ExQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwa+CD9XTTxDwMWI8WIm5inS7nAEwDgYD
-VR0PAQH/BAQDAgIEMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAEvc066az+E8sftMAgkECVeJVw0Mcr2y
-YlJ0SAbZUNaU7KbzXxm3j8Q5v8K8GDy7EB4H0Gyh0vgsbChTAdLip7xQf7V7SetA
-nE66H4ikF/UAhXlSz+E48Qe2+L3w2weGbU3zwmNMeYkI6dmGFMfEut7hL9ak0Ulc
-0meAGzOu5kHt
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid IDP with indirectCRL EE Certificate Test25
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA2
------BEGIN CERTIFICATE-----
-MIIC4DCCAkmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGQxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE5MDcGA1UEAxMwVmFsaWQg
-SURQIHdpdGggaW5kaXJlY3RDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDI1MIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf0B2LJSDNBUNNk9cwJtpviFO4J0nIRbuc
-O6UsC4jXoQrcgUkZOOcYIT82Yz33dg4bv6K2EXqzJwIfBGq6JGvHrAl3djShH1wO
-qasa6FN6vCnmb2Wo1+7KpwCSlDAWAYhNTcb8tGMYGiOGd4FMhEdA/y4sRqmuJEOZ
-Uw7DglXVewIDAQABo4HCMIG/MB8GA1UdIwQYMBaAFMGvgg/V008Q8DFiPFiJuYp0
-u5wBMB0GA1UdDgQWBBSQlj00h5t1ic1A+gEB0E3NRYLbqjAOBgNVHQ8BAf8EBAMC
-BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMFQGA1UdHwRNMEswSaJHpEUwQzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQD
-Ew9pbmRpcmVjdENSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEAHIf/ZJSSoUe0ahpi
-VXce88mnP2i2KJBuOPFVGyJHSY2wGKtm02kgghm1bSdwVzXOLwTLa223rjc+cZcD
-7lYleZJEOeEnibK+8EgTf0Z/D6VnmIsQD/HHhpkmvB69NWVETkG1VtkmEHkaNDdQ
-2WsP41gX0VujQE2K3UK1KDPPNsI=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=indirectCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6C:C1:14:5F:D8:A7:2D:E0:86:93:19:5C:0B:F0:49:B9:25:5B:E8:1C
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6c:ab:91:4b:38:62:8e:f2:48:86:10:a6:b8:b9:c3:c2:28:e5:
- c1:d8:3b:c5:8c:6f:62:44:37:f6:1e:2f:d4:04:be:ff:bb:28:
- a4:3c:71:1f:69:58:85:95:60:3c:cc:f7:65:22:4e:9e:44:e2:
- 6b:45:16:9d:67:ae:da:ff:57:e7:d4:ef:34:cf:1e:86:52:13:
- 25:77:a7:7d:fc:ec:94:62:bd:b1:76:a9:66:c1:ef:82:bb:3e:
- 9b:21:c4:ef:49:9b:2a:e8:5a:ef:39:82:ee:da:97:5f:77:89:
- a6:3e:42:26:77:b2:15:97:c4:db:ee:ca:8c:ad:d2:cf:18:3e:
- 87:e8
------BEGIN X509 CRL-----
-MIIBcTCB2wIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBMRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcy
-MFowDDAKBgNVHRUEAwoBAaBAMD4wHwYDVR0jBBgwFoAUbMEUX9inLeCGkxlcC/BJ
-uSVb6BwwCgYDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4QB/zANBgkqhkiG9w0BAQUF
-AAOBgQBsq5FLOGKO8kiGEKa4ucPCKOXB2DvFjG9iRDf2Hi/UBL7/uyikPHEfaViF
-lWA8zPdlIk6eROJrRRadZ67a/1fn1O80zx6GUhMld6d9/OyUYr2xdqlmwe+Cuz6b
-IcTvSZsq6FrvOYLu2pdfd4mmPkImd7IVl8Tb7sqMrdLPGD6H6A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25EE.pem
new file mode 100644
index 0000000000..a716c1a069
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidIDPwithindirectCRLTest25EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: C7 60 3C 49 21 82 1C 54 08 8E 4E 04 25 0B 12 11 F2 FF 15 09
+ friendlyName: Valid IDP with indirectCRL Test25 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid IDP with indirectCRL EE Certificate Test25
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA2
+-----BEGIN CERTIFICATE-----
+MIID9DCCAtygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowaTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExOTA3BgNV
+BAMTMFZhbGlkIElEUCB3aXRoIGluZGlyZWN0Q1JMIEVFIENlcnRpZmljYXRlIFRl
+c3QyNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMp7IIM5L8j+PX0j
+W3jaOmFU0IZb/uqR7MK/+CPZSm3YN7HvAYvxTVC++HGP8PNZQIn6148vH+shf79U
+h9DYMPtvMpDBsDirZZYe79/9CCdO49n/1nLvt+6Q2RwtoysAT1pfXd359RPZvu78
+oGQvxnJwxH7SI8ZWhueOArm7aUTqUXbWq77bXsE47/zYBohwVNAL4lm1rNIw+nun
+Vj7og5FupDZhd6YTHlm2hMzLh1VXpX7RNGtVLouLEVLcdqQsuzbZWyTmMm7V0jk/
+ELBx2jdcrl3qpyJ8yaPw5mXbVef7YfvlCGRwOEPLY0FPU7ROfICoC9J2CFqq8Opm
+TYdehs0CAwEAAaOBxzCBxDAfBgNVHSMEGDAWgBSII+Gzs/Js/jGpvothqjuShwWk
+ozAdBgNVHQ4EFgQUtY5A4mYCw2O8gaOCAOp+ELpcBt0wDgYDVR0PAQH/BAQDAgTw
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATBZBgNVHR8EUjBQME6iTKRKMEgxCzAJ
+BgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRgwFgYD
+VQQDEw9pbmRpcmVjdENSTCBDQTEwDQYJKoZIhvcNAQELBQADggEBAE6t44yeRc39
+gkxrj/OJMlMhO5PM+NOQeDO9MB4TzbO2lNo08dlbz5bEmfnbFA77mthpoXcSTvkr
+HgVFncAs9qZ6V8zV8lccn5eXiuO/dFpmS42eKE0rhk4VkBSD7wSWPX3vuLXalYsU
+mtFOyExDNRqtKcGAEQMyQcvw0SuwDHWHuRXZ5uALB6WU8X/uNx/jmWjScyQFnooj
+oGhOakKKkLMciGBPF0+2VZUKbaknZmoGVI603yGRXxqlF+LdSaGsEcjfUwpqSiry
+53e6GfDspF2xH/2IQX6y2d7Jx6zH4oT46jDR/uPwVXWAdhQi4Z4S9xj4G9DpHC/F
+NeK7pE3pYSI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C7 60 3C 49 21 82 1C 54 08 8E 4E 04 25 0B 12 11 F2 FF 15 09
+ friendlyName: Valid IDP with indirectCRL Test25 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1B559E6CBE8CBDB7
+
+lzuIKJjyltjw37fK8/bSCA8hm3s588px3Hqnf15Dr5982IuT0gOzDWy0NNodvkwh
+Z8TlM/LBopj8cd24FV9gqKQllGSnpMonIw+jqO8pAu2XI+WAvRUmVdLILD37ccE9
+3r5NRO0PTLoXTStn3K8BNqdNEMriTj7+8qSZ5d+RsUvnt9rD0r8mDY5RvsUcuDER
+63x6AkWEZYXdj7Dh+gLxEWZrBdZx9NDhJ4hGc0Oghh6valpbF0x8MFXFmRXfAwsJ
+0So5Nu6WpW64tfbeI1s7IQKDrT3mg+gPNTYY9P783ULstUEcLGtklFMNG7mnoTMH
+xDMSTICCFuM5I8waJdwj/pa2g9paFjG5H6gye0xRlzFSverVw7vro+IV3EPo6+1q
+33Gj5yPNM2lwSPnioOwsUeC56rQhI/gyKj8HB3yxB8TbF7NGctMfpeJIreXlehp9
+qPXPiCbBxrGRRjcerF9uvPlJAMNXxwwxBloRjVgKqDypbrGZJtpT5g/dG6HzYbUQ
+VruyoD/+Kb0MzQFajfCOLlyzVvYJleOqix9JOH5KKcgHjVH6FtHl+X24m66tCqKO
+7e+fd4NNFW4zOqN7TA5gPG4C7kGjRKs/pdRF/O45h3thhxsNpaEl5ekcLEcWaF5i
+lkUIKC2pNjU+VHHUmotWMYxbt64VGBlvaZxPZgj4HIabe3V5PBUw7UuozVh4IuIp
+4fcvqi5gxlBcuWGwii06IbcskSLPz0zKWx30IUyc2B9gSANpPxO4hv+qTace7kEj
+tImEMHpLsPwRc5wvPxodquJZInH7YcUfga832eyIG17HZsfUOkHSZpd53UIeiLgH
+U/4JziCBuT9r/Q173bXbzFSthooy/jsq9KIppNmA8w9Cn9xVPhCxdREErclMtAO1
+MCXRz2gj66tsihm0I0R4cQpuwHKDio+34pLYnis2nPlCn0gIJ6Paxddg1YBLIAmP
+TuaXfFZKFoB0qjR2by+SKcIevFdbAmYalxAknJupGMm4EMkb/Ho2r6horqKopqWK
+/DN++Om4ugAM+WELeSWZ6sP63Pvy/Twlnh1P9EZHtg/180ZgLqwbr/vGsHdRdGZW
+u0cvbOSSVMFhY5V7DC5K3Gnp6TLoteD+W7M8JHzerww79eOe17HsnIjUKsBwH/Pc
+xIpiXbzaXQsD8MEwB40E9ZwF8/35wn8ARSSiun316yhG+GNEtI8ddt0z8FbVTybF
+Sw4hbv4UC6qS4VkkarBmmUuDzLIbgm9VCisK360q3y1+M2Y9rv9ZVhHBU2/CGsuY
+0wmfXIMekp8iiiCLf/6VG1nrb7E19hxZAtBp98UHSB0Oa8gjwS1JQl+qdWSQXxQe
+uMBMCXehHiIjawp4Xg3+8c9GCt22d5op0w+CbqmR/t1/h4rYR+qf7uqCOmTyfIc6
+2MHY6ArzSRYVdg4xO8+AJFfmw0mn8uu+elsLPxtMYWuW7BFEiVTLw4HvbjOJsDWZ
+I18zW8lGQPIOzsxq2up6k14I4nhyxfWWAEAAol3HvfhDM6YYjt5zSVpspSFefYsO
+N/atLtmzNIeYfbbLaXKKwKALgcAX405wO75wDa7gw2roHXJMnATQcw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16.pem
deleted file mode 100644
index 58a9b915a7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16.pem
+++ /dev/null
@@ -1,115 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Long Serial Number CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBEjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVTG9uZyBTZXJp
-YWwgTnVtYmVyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1mCudsqPk
-irIFe3XQBPzhyyRQyreJH26B3Yg6kYq1Obd6I1j7Ber4BDVyCCAvnS6rNkzsbaJf
-+sWVf27Vug0uhasZx/3XGc0DbhZNr5iYknU1LEh8Ccq1Oymq0LPolAHqaJNOaYpb
-K5Fq0P0RDcBK/ENgmtdY0CJrR7MWUTttqQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU3z1I++My57kmUova7PgJT7PH
-36YwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAHJqd5P8eBN05uB3+fPCfVjO
-qX7csbAx6X1LNibOoWDlB9Y6fElHQS+i8HDPmIIdC7N/9xoCW/fhzZqb6VKDQXNM
-9pwf6jOJKnNQOaQISdoIvj2Jn1FoE4Bo1SGGQo6ZgCWfXPA1TE93BXTua9Oa+FZ5
-fhG3y3gMYLC6ciKePSDf
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Long Serial Number EE Certificate Test16
-issuer=/C=US/O=Test Certificates/CN=Long Serial Number CA
------BEGIN CERTIFICATE-----
-MIICnzCCAgigAwIBAgIUfwECAwQFBgcICQoLDA0ODxAREhIwDQYJKoZIhvcNAQEF
-BQAwSTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4w
-HAYDVQQDExVMb25nIFNlcmlhbCBOdW1iZXIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcN
-MTEwNDE5MTQ1NzIwWjBiMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0
-aWZpY2F0ZXMxNzA1BgNVBAMTLlZhbGlkIExvbmcgU2VyaWFsIE51bWJlciBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0MTYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKtO
-3auJrAWhozm7l0Z1T0lT1bIb6AWcsrX5hHI03QNjnAsiR6TwhLzknLevcqY1FMOd
-3CQ0YGisyl+jQn6u0vn8gQbPvlN+HaEM3KhBED8jqLLcnspGAS6f8oi1dpWNK0fL
-NrOz4DYCp7kQVDXIBmifayg87zrHaz6X4lMhxgxJAgMBAAGjazBpMB8GA1UdIwQY
-MBaAFN89SPvjMue5JlKL2uz4CU+zx9+mMB0GA1UdDgQWBBTJunkp/mY4QxI0f3ob
-s65e11IvhjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA0GCSqGSIb3DQEBBQUAA4GBAENEAZeCPJoLGi9JOR7np7MvjQtU9NWutm2iMthF
-MYTKIG9CmYoDbDGl689tIyEHOSJO576cpCvOoORWfvPNFqUGaDKjTeZ5r43Uq4kM
-G2GcseomSZC95SvZhsH5ZrLkdJLSrOe1B4RiNQV6Dx/EgDr0t/CL0bTNhh5l72LJ
-8cNi
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Long Serial Number CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DF:3D:48:FB:E3:32:E7:B9:26:52:8B:DA:EC:F8:09:4F:B3:C7:DF:A6
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 7F0102030405060708090A0B0C0D0E0F10111213
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 7a:20:63:9e:55:8d:d1:c3:ab:3f:37:97:45:61:6c:a3:21:9f:
- 83:bd:ce:63:48:7c:a8:ca:36:15:02:3b:1b:51:66:e0:23:df:
- de:ea:86:72:e6:92:9a:63:c7:0e:31:30:ee:62:83:1c:3e:23:
- 20:29:23:ec:aa:2e:f6:18:ba:94:45:e7:af:5e:44:0d:3c:2b:
- 13:6b:8c:7c:7a:6d:a2:f7:b5:9e:ea:d6:f9:9d:4d:31:91:8f:
- ea:4d:b7:ef:5f:5a:2e:63:fc:37:02:5a:db:a6:3e:de:6b:a7:
- 84:83:d2:a7:5b:e2:07:85:9f:0a:03:f0:33:53:eb:a3:d1:d4:
- 16:02
------BEGIN X509 CRL-----
-MIIBeTCB4wIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFUxvbmcgU2VyaWFsIE51bWJl
-ciBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA1MDMCFH8BAgMEBQYH
-CAkKCwwNDg8QERITFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8G
-A1UdIwQYMBaAFN89SPvjMue5JlKL2uz4CU+zx9+mMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAHogY55VjdHDqz83l0VhbKMhn4O9zmNIfKjKNhUCOxtRZuAj
-397qhnLmkppjxw4xMO5igxw+IyApI+yqLvYYupRF569eRA08KxNrjHx6baL3tZ7q
-1vmdTTGRj+pNt+9fWi5j/DcCWtumPt5rp4SD0qdb4geFnwoD8DNT66PR1BYC
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16EE.pem
new file mode 100644
index 0000000000..6b5c09b394
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest16EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: BE 0A D0 4C 5E 46 41 6E A9 35 8C 37 3C 87 7E 82 78 E3 80 C1
+ friendlyName: Valid Long Serial Number Test16 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Long Serial Number EE Certificate Test16
+issuer=/C=US/O=Test Certificates 2011/CN=Long Serial Number CA
+-----BEGIN CERTIFICATE-----
+MIIDrjCCApagAwIBAgIUfwECAwQFBgcICQoLDA0ODxAREhIwDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExHjAcBgNVBAMTFUxvbmcgU2VyaWFsIE51bWJlciBDQTAeFw0xMDAxMDEwODMw
+MDBaFw0zMDEyMzEwODMwMDBaMGcxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMTcwNQYDVQQDEy5WYWxpZCBMb25nIFNlcmlhbCBO
+dW1iZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDE2MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA60l+Uxo/EscQHc6uSZTNiff5wN6+vHrzNTO71TXex/ZZkPw6
+h60CNBdw5TPhvdRkYALq7mdMqTMzHntTBnHCc9BVlEOHvyo0FtrcpAplNKxSgMVB
+dlT9/9LfuToh8XtO9EoQXz0zY4857N8rol3bZb3DyG2BpIxbFwRyYYJ35DpKlach
+uJeEGxr/qyV0kb4O4WQtFUz5udNYiMc4HN8jIpFV8JkBkcJVLxbohL32Sz+k0uWD
+K+Nu5R+kPqCUxdI1q/xlexYtbeYqlfCb41mP06tpR8TF6IEFpFVEtAc4Xgf4dwXY
+EMit6jx0/vhWc2uHse2wETOElP/BPHkcQyxFVwIDAQABo2swaTAfBgNVHSMEGDAW
+gBQLY7dHrsIHMht/b+M6uOoL/9dkpDAdBgNVHQ4EFgQUfoW1hg1ZwEl3TiTkftke
+9bK/LLowDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAN
+BgkqhkiG9w0BAQsFAAOCAQEANAtNHPUyv/1huJvEABDV7HL7a4m5e9dwt05KChqm
+I2bNZ2euvr2tmQD4+jCYpD62IYboWhNGc7mOiMe5SqbDvfI+nddwjLg7vbr61LYy
+kmTD+koMayzBsvAMvsD3GnEFZV8mujcQAfvFu7+lT/KjhJTreNwmSsF8Q8jCeC4f
+oHaoT6hnYNgpdzjMrVtDLIwDjB8L/a3XHY1LnCk7Btle3ge7huFnkRkOdPDT9u8x
+HN0tMFXZWi0MbyIyj2RZjgxpxI2vvFNRviGQfd7gcpLzoinD6USFK9f7hUXZr44H
+bCQUme32AqlJ+megWOauS3WUaE/8YA0KDLRDeskZYiAspQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: BE 0A D0 4C 5E 46 41 6E A9 35 8C 37 3C 87 7E 82 78 E3 80 C1
+ friendlyName: Valid Long Serial Number Test16 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E6C9E4D61288FE11
+
+e+AmA7gdL7PjQ0RHgLFFf1j5Ol7nkQwTFTqP9BKrkhNN9YThLPv7AmCmhfNPqUWQ
+M78x+MUoYMr/Cj1OH2iyzER/gwXcX0smv0HQaQo8bydLXAZEpCPEo6HRvd//UPx9
+EdrRjvTwNqJwXaSsZKxj5E69gIbUANCKL/6itKRuxgJpCl9tVwC5rw4aC01rdojV
+QdF1NbNsZ+8e8dq/UHWbw/UGl4i/o+GnZ6257Q1E+enNF67EW0B01Zm4FUGI2lMa
+/LhZa3CxwWs3lTXA9pQumncClV7HjHMjOtPCOc9Pb2dhdhjBngc1wgk0ZRjnRgoS
+Us6pjQ8eMyP1U4tAR51S+cStfeL2SWiE/c33mBGwTjbrXh4HSdXGjxyfOtgVbTWt
+L0eLsDZb5kxfZ9M4UGspk/MLq9lnCbH2dYd+9PppVknhRahOpuPPuabYv+h7AjHG
+QsTdDkKbU0aXGvIVcA84rKn0rlWZbd1q4OwDPLoDSEkwuRmGqisOmOkv/BkjfLNy
+GYKBNJw+AmBX4Mv6Xx3hiX23ht+fBOqUJh1Ye5+l3DWlnpgF1tVaOKCraSeOurJV
+PxQwCbQ0JyTbyxduZ2CQznr8x3n/Gs2rbrFyEco/8YAZqFxdhs9RqMLacavfXI50
+UAY9tqHLT8M5w851ZLxpCHFKM+PMoDMZNVG3LhaH5n7NkRKQe5HdfQmmeqzbGWJS
+0Wx5KPNMbDykIjMFxYdHh6C0ftEERB0qinxQPSwPUDa16/eKqYT0EPdxCUi5QWEG
+77YoKFMLIKOSPEErLQQRlTjpVxtS+EuhGZhzxvIaaVyZf1BVEuSAdwLpixl3Avbb
+jN8p6Ww/aLfLvGkeRvHVaPPihHV5TAokkCbpdUn9ZWVRRgfwaEPrpMzZ9QXxRWsS
++yCkwrQ3sWO4UobJc0F7utfx7OdsLVG3t5LI8sLMACRvDkfkj7sIle3aSq99WYi4
+0H93dFlhlRYK5jK5bqLEeGIPFxFqAFAAxZiTLaQWrEWXPLF/J0PLDJLJd++OyNts
+r1tLJk8TM0KhV4ifFVDXiG6T2y7+hMtAYIn3vPvVzDLp5zsDYg/1OyElY2iEPbHp
+FvkfBRHJwHzBT7hE2P6kPi4tFy3MW7xCzl0jQL0aPR17qobVfre1nHPVFDmjg8RL
++kBbBtaCUTHIWUDM9Qmz3uEQwNdhsJ4T7IDYLvppAGdhblHJZjx2j9QMiQALf+Q1
+F/vSPV8ejSwHpQxXbP8qXIxYl3X8REpZJpBRSBy0HOxOVmpJvT0B8vLo1TWJ9MrK
+PA+72UtMfWlf0SzCfrF3PVR7zNhOkoZG8tkQCHazbgW+wGyPH2yLq7F4Ra+fk/OG
+T/Iyjj7GcW12Y0KJbaWTcl0UHzWnVmEiyp/2iOBdpXNRAzIWSWm4UbD+VX/SFtP4
+xbtv2PDKXi2DXQXU6QFgC1BSk1gGElN8f+JNrdwQkz4YPm4i2eS20jL5XdTGuxYw
+poqGuekkEHQvDfIX4vmQ8tZtdOx84BH/wipf/9VodeLatnrYTkt26rdUDIBqPeWE
+dkVTwIkIRPKjE8JcwInj1/uX73rPsRYMVAWbGoIsVhpbNlGzbQLCmKgBXnJa9iF2
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17.pem
deleted file mode 100644
index 16037a0097..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17.pem
+++ /dev/null
@@ -1,115 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Long Serial Number CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBEjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVTG9uZyBTZXJp
-YWwgTnVtYmVyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1mCudsqPk
-irIFe3XQBPzhyyRQyreJH26B3Yg6kYq1Obd6I1j7Ber4BDVyCCAvnS6rNkzsbaJf
-+sWVf27Vug0uhasZx/3XGc0DbhZNr5iYknU1LEh8Ccq1Oymq0LPolAHqaJNOaYpb
-K5Fq0P0RDcBK/ENgmtdY0CJrR7MWUTttqQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU3z1I++My57kmUova7PgJT7PH
-36YwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAHJqd5P8eBN05uB3+fPCfVjO
-qX7csbAx6X1LNibOoWDlB9Y6fElHQS+i8HDPmIIdC7N/9xoCW/fhzZqb6VKDQXNM
-9pwf6jOJKnNQOaQISdoIvj2Jn1FoE4Bo1SGGQo6ZgCWfXPA1TE93BXTua9Oa+FZ5
-fhG3y3gMYLC6ciKePSDf
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Long Serial Number EE Certificate Test17
-issuer=/C=US/O=Test Certificates/CN=Long Serial Number CA
------BEGIN CERTIFICATE-----
-MIICnzCCAgigAwIBAgIUfgECAwQFBgcICQoLDA0ODxAREhMwDQYJKoZIhvcNAQEF
-BQAwSTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4w
-HAYDVQQDExVMb25nIFNlcmlhbCBOdW1iZXIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcN
-MTEwNDE5MTQ1NzIwWjBiMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0
-aWZpY2F0ZXMxNzA1BgNVBAMTLlZhbGlkIExvbmcgU2VyaWFsIE51bWJlciBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0MTcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMmE
-I5A7RJ2dsFgrNGpTKPbTNkMlTeSA0APdg25ehg2jBXRX32Y18+LwdacaCcVFxWIK
-z16aAT/8U/rmoP3+dPkVosnTcbJamr5D5rE2D+QWqHI+4Q0saPg91CxVTkLhxU9R
-Ck1bLkVggnQngeaqCNLIAHuP8N44+V3Pytm+HddRAgMBAAGjazBpMB8GA1UdIwQY
-MBaAFN89SPvjMue5JlKL2uz4CU+zx9+mMB0GA1UdDgQWBBR7xbA1RfoohD3hr0Lj
-5WUT+PO6hDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
-MA0GCSqGSIb3DQEBBQUAA4GBAGGq1mqUIqGhHvuMEEdcLDESbvJ2tSMigxNjqvGi
-zWc/CpxqrWchwxA3zF1/M54g1Shi2IAxIp7lfBJbh6X8o/8Dzhc7Mff3HrrqTrC9
-NUuJEFGx13X8FRoEPgCKkn/kl8fDLfTvJt/Piww6fE8s+5iiXwqaFwGJjSgz0UqW
-re5l
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Long Serial Number CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DF:3D:48:FB:E3:32:E7:B9:26:52:8B:DA:EC:F8:09:4F:B3:C7:DF:A6
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 7F0102030405060708090A0B0C0D0E0F10111213
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 7a:20:63:9e:55:8d:d1:c3:ab:3f:37:97:45:61:6c:a3:21:9f:
- 83:bd:ce:63:48:7c:a8:ca:36:15:02:3b:1b:51:66:e0:23:df:
- de:ea:86:72:e6:92:9a:63:c7:0e:31:30:ee:62:83:1c:3e:23:
- 20:29:23:ec:aa:2e:f6:18:ba:94:45:e7:af:5e:44:0d:3c:2b:
- 13:6b:8c:7c:7a:6d:a2:f7:b5:9e:ea:d6:f9:9d:4d:31:91:8f:
- ea:4d:b7:ef:5f:5a:2e:63:fc:37:02:5a:db:a6:3e:de:6b:a7:
- 84:83:d2:a7:5b:e2:07:85:9f:0a:03:f0:33:53:eb:a3:d1:d4:
- 16:02
------BEGIN X509 CRL-----
-MIIBeTCB4wIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFUxvbmcgU2VyaWFsIE51bWJl
-ciBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA1MDMCFH8BAgMEBQYH
-CAkKCwwNDg8QERITFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8G
-A1UdIwQYMBaAFN89SPvjMue5JlKL2uz4CU+zx9+mMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAHogY55VjdHDqz83l0VhbKMhn4O9zmNIfKjKNhUCOxtRZuAj
-397qhnLmkppjxw4xMO5igxw+IyApI+yqLvYYupRF569eRA08KxNrjHx6baL3tZ7q
-1vmdTTGRj+pNt+9fWi5j/DcCWtumPt5rp4SD0qdb4geFnwoD8DNT66PR1BYC
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17EE.pem
new file mode 100644
index 0000000000..53afd0945e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidLongSerialNumberTest17EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B9 81 3E 90 D8 72 4A 1A 45 29 50 D0 DC 19 E1 1C 2E 29 C1 44
+ friendlyName: Valid Long Serial Number Test17 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Long Serial Number EE Certificate Test17
+issuer=/C=US/O=Test Certificates 2011/CN=Long Serial Number CA
+-----BEGIN CERTIFICATE-----
+MIIDrjCCApagAwIBAgIUfgECAwQFBgcICQoLDA0ODxAREhMwDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExHjAcBgNVBAMTFUxvbmcgU2VyaWFsIE51bWJlciBDQTAeFw0xMDAxMDEwODMw
+MDBaFw0zMDEyMzEwODMwMDBaMGcxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMTcwNQYDVQQDEy5WYWxpZCBMb25nIFNlcmlhbCBO
+dW1iZXIgRUUgQ2VydGlmaWNhdGUgVGVzdDE3MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAvNWBkGHs4ey3i7wnEUSxL3bZ/wcxijWbLd45CdHlfcrVluMb
+reijfhtxX8DrcfzSzWjMuq+FbReq/XE9Lig3FABFCscvbqMRsbVJBuRxykVx9Xml
+xyMtUScxxhkVFsJdGS6YRyesOX/IQSdDLYt++jRQMZ9WwjCyf3rl0w+vAmwzX9kg
+bHAVJoE71zVHHz6GxlLLuJVrYawr/j6Ao9sjniUNWsR0r/JskIpfwAyOPktOopuZ
+AlsUhw/TagkfTn7PTxTGQsCYabh9NJejgMH67nFWAikqGSsObbkGYKpqf8qOtsk5
+hW8PMGBe4Ry4OBL2ITdSfuU1DZWbAsOBuSs7HwIDAQABo2swaTAfBgNVHSMEGDAW
+gBQLY7dHrsIHMht/b+M6uOoL/9dkpDAdBgNVHQ4EFgQUCkxTRT2mlM7HMRp0Z7qK
+tbsHoHcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAN
+BgkqhkiG9w0BAQsFAAOCAQEAqesLoIqzgv5k02gA0rW61rhlEnQcwQ3v7qcl0816
++Gn8Ozxefx/tN49JM7VlVIDDATsLynepfZzhyb/5Ag+Yq0FMaMp13QN4ZusGsNJ/
+LlbG/L7nQejig+BAYzD6MIdpPKozcaTRYGVZjZ30YYg8SVEN4nr1KTf4ExOvqAH+
+dHlw5JXln9w0GTQfHyhx0Y1rCMAyqlrffbktFJMqDuUnoWM+9YPtRfswATAAY2QO
++OfKOvuYUOvPECybeD2QDFKOHYe7gpXsjQsEuAmUpDAoxvpay6VIEeytVEh6VpYD
+3pYPFGmK/SHDFzLVMMIFyHOpwQaoCiAAgguMsVVS5Md97Q==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B9 81 3E 90 D8 72 4A 1A 45 29 50 D0 DC 19 E1 1C 2E 29 C1 44
+ friendlyName: Valid Long Serial Number Test17 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,44A9DE28D5DB80A0
+
+qqGl9iO5jTbHmXHqEWGf7N4ADTdGCCTfYzjwsTpgw5lWTyoH5cAKkoX0zU95+Sy6
+jBmrxuRnexwbcKG/yAETafgBs8uT/cNfmviYuvrOXjMK/WphkXj4iUDpsKLNoT7W
+shW3WbwQYtPeK2vaF7nLig//b9UD80Iv9hoYO8joBgNqv12rUOiCqGJ6EQqr+gNU
+IxjPTKx6cfEqzbKu5pQEXkT2paD0G8Us6uWQOj9UyESUuYLCciivtGuEAPBsaIxN
+zI+7DDxXD/eFWAjI7Yc0ovGa+gV/AxeiHFNJi0q/bjm0+1PM44hgadbqiphZlcbd
+wyYNccsO8HIE4pepI8xD4/SYCL9BXo2ukdB1B7sBXoLM+a/Gu9p3ZVy94c0RfAST
+nsBe30h/tvomue8HoIXBWsTGZYDca7VOQAwLkObli0atxQOY3rAQW+eKc/WIyX2t
+UGf6qwWf/oHplLanqQchMV2aG905nFCNHhd2T+8fElhbgBYc4YpMQCnLtZVGvs7R
+JRAgSPekBVdj3JyN71xaMcwcuqtAcIiAzHNyFsv13CsxKPcVgBUnE6KUnkANG817
+SwidJ5tL/Lkb3iS8qaR5strMrLqZJdGHfhvZ0kuTvW6jFIPqT9qPpn3MbSW44WIi
+hOFVgSQdbsBxyEIIhlOpAW72qprgGAFHNWD77RqDmtbh1+OQadD3xDws74cObWBj
+Nb8n+9gKFeC1gErZ6EG9y5eHDQiAzB/lSHw//K+el7XDAh6UyR3o1Ob/pVmQaLqS
+VPIGMkmf+HtJUos5wETaqxJIlh9GypA09rVW5ZZSARxYdGh/evNVKRBPukGcQktq
+EUf0MCZcZGw2MH/+tdjtugnd5edGhmzesYRlDchnmSBGwiis0XYB4FuTzDSdKuD9
+S+vsb7e6x6rZFlEsA0KnAwlYNUkm7M2JzGjPs3tG4CLAKMY717wY/C3gsdo2ybR3
+bBESEa+0QHdN5ubeolPY2q4IVPes+Xg1HjPW79c2WoZ6CDGKOlC77aQ4AN4fnFNk
+AOmFFAdTNVVFsnQz5ewrd1fIr/r+rR1XbJBE8MkE8KaUAVxPpOJuwsIYa7IrBKAr
+sVaPC/LwBk+iFtUoN7dUmuu4Y6GCPTSYuxhd6B+75sv2ToK6nfIK9XDhzd5ua1s9
++7U9SjRXuSc81KfSwpy4Ct3zKcTmH2ggqjv5DbzLbI1G9Eodq2a012CDue4bie4H
+znuOAUUqM+7+un/pidIVpxCxxhCFxNShnotaP73LO6xgxkuBOCKVVphHcr4zV5k6
+z5D20cDGwk2vYdXVmI+fQ4CtwdMDm5mnc+P1GwDS5oiA8fCSq46GQDBtAyq++Lz+
+u7m+kLh7O9JNOre3iNeAGpZZrLacpd4sCaIZWi5QOmxcsbl3ojYte/c/r/J1/AT5
+ZAn6qi71xHjuuOdpMPCYOdBapbw12A9PU7VpjlY4f34B1Cdf3u1kz8D2ZVsaFlDj
+d99kDQOKFntH0XOTYMytoK1lsekRiLOsrUUMWkJO1ULtICPdjJtRk8Wl6lr5o7JG
+rA5/hsVnStNN8QDbRGPZgmFcKryroXGEAz/Kt7fPhYc7DKiK+OMmPdRIOEcM8zUP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5.pem
deleted file mode 100644
index 84006ae155..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Name Chaining Capitalization EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=GOOD CA
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIBDTANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dPT0QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBrMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxQDA+BgNVBAMTN1ZhbGlkIE5hbWUgQ2hh
-aW5pbmcgQ2FwaXRhbGl6YXRpb24gRUUgQ2VydGlmaWNhdGUgVGVzdDUwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBAKKjNiRlU/b/0kN4KqqM8GCc/XOogauyq9LV
-K5+grKdIS9Hyb8R/YDK9ilsjzU/nYKRdOvMfUs5NYR7H1UhBJ9GMfo5ZJE7zbV6X
-COFLvi5STvmS1FIA1COnOuW0gCI37YuvoILvExZV0MlgOP+maCzYWDsffOoGujMJ
-/tdFTmufAgMBAAGjazBpMB8GA1UdIwQYMBaAFLcupoLLwsi8qHsnRNc1M9+aFZTH
-MB0GA1UdDgQWBBRM7vD5b8j3gITFAx7LZDp4/fhR8DAOBgNVHQ8BAf8EBAMCBPAw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAFXVuDJL
-2xAKqFtse2QAF5GxQIa8VuJCdOuNF/KCTNQ65dWDvBRYuc1O2O0NaeN71B7vbBaR
-fLAM9acjYghtDQd22u/dErDTmKIS2IEY4Z3P1eGlLcNhpV1DsIAe6cQLgm+fY8jS
-1m63U2bt0Fs4nefPvxpkWCeLXOCr7ewDM2Uc
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5EE.pem
new file mode 100644
index 0000000000..c011252ed5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingCapitalizationTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 66 4A 0D DB 28 1C AA 3E BB D7 DB CE 21 C6 B6 B9 5A 8F 35 EF
+ friendlyName: Valid Name Chaining Capitalization Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Name Chaining Capitalization EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=GOOD CA
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIBDTANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR09PRCBD
+QTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMHAxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMUAwPgYDVQQDEzdWYWxp
+ZCBOYW1lIENoYWluaW5nIENhcGl0YWxpemF0aW9uIEVFIENlcnRpZmljYXRlIFRl
+c3Q1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7uBBbS4stI16Jp4v
+WGJ51twPti1iJLp+mNzQjyNaE/xC+J3w438fQvsKPEJBwl9iuTtIO8ijAGRJiCUA
+nnc7+PeJ7UvYBxE1tcggXXrE7pTJsw893bE6JHy6SxH+/yt/yRfwo+YqbZvtD+6U
+4bCsj/83FQvhWoLdh0ePfU3GiK0wkM13aD+pBNy/aMZHIOm7JjOuv4a2hbQtYWHo
+oYRYkhXfykCr37V3zwCbPsmGyVJ0MLtwLs/Q3Cqxzlp2uIoeFQR4e2H+ISfQg+Lp
+1eIqJCd2E3VJ8oKcIu2oW4soNL9mPNjKZdlwC3VLtRITcvfPH/otHuS2wcAdU+88
+DRMo5wIDAQABo2swaTAfBgNVHSMEGDAWgBRYAYQkG7wrUpRKPaUQchRR9a86yTAd
+BgNVHQ4EFgQUeN6aGkOrZ3hSrA3gtRojk+AnY8IwDgYDVR0PAQH/BAQDAgTwMBcG
+A1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAbqlb8g8M
+w5TaH8PXafNxxswC41xFgxZWx4vdQEytNeeAdFABrQf79V/CxoT+KuXr17wTstpT
+XqEF5zjsahruaSONLcUy1JetjUNW/Z7b6/p4s3NffYhf0TMqqLLatI63CCImH8Ap
+8ceCFU3m+fyIyTdIEHgsnQX67zZ1mpoFjlrTutSYXUHtfhsK9h7LCprkBOwjbjfd
+t2nf6nPx1H05oFKrFGpu2gAHHserXavCToQVsprK8jQ6r/8xHInJS76KK3fMT4Is
+iA6EiRrqGTWkPjh2hd6WaFz/zRhuLm9ODRuz3bgN9rcdxq8jYkDg8Fq6eqhnVLJe
+nwhTghrNhZqV4w==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 66 4A 0D DB 28 1C AA 3E BB D7 DB CE 21 C6 B6 B9 5A 8F 35 EF
+ friendlyName: Valid Name Chaining Capitalization Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8474ABEBEF2EE976
+
+5J1l4vly6GY042QtaorkypQYpT1DxoNh6VGLDt5ceK6iqKZKJc5AoXViAlB69xYd
+qusEHBs/WGdfXysIyThM/d4BVC91K+ZYeJZiknD/RhWLkxFfGeF36pC85Pm4ahxa
+e0Kq0VLCc6FNlPMnJV2clugdNaH3ZSr9A8luQJeU7NUHHAasfq/6DU56LUnBDPQB
+hsnnNlJZDeDF2vzZLYSKL7X0s2C8EHdB1PHWaDAnaDNLk4/3MQbopxoF8Eok50Gd
+jBUsHqo9/qEUP2Rf/W+oejs8ruW/WUBVEIeZ5Vfi+Df9obJB+r8KshRc/JH/8QRg
+9F9uAsUkNlzcCsbNTE+lUK2yY1JSYY3LAU1dUkI5W6rlJr7kASjlWsDb+ShVoBsZ
+HwXyHE0ACFSqgFVlAFCqXmoUXaGAxUsQ4bACE7sWlPtnCcCLp41JV3XobwGz6ZHm
+maY6CBPZXzc8Lcqs2uowAUxa2/jtZJdzpqAXTDks+ZHBgDOv61mvyByYWn+TT+zm
+qY8JGuTxDCUNGO5aGa2aoaZCExYo9HR8x0Pn1P7uJDtyDH1Gk4p0mHIYm4JADw3g
+x0ML+R6jROa1S+TaaYl0tpkmfX3BrZpa2RnARAxQhMuGQIS+KB7jfArgR+MofN3v
+Nq/hiRCZ6tOCuvNInKplDOzAAI9DJbVyMk5GL6KDkuqBEVWr3qhzwt6HnyRw0cVy
+AruMn7xRl3o5XXob/kAPK+WZDavj48LLMTIigObBbluOJMkVLkxqx71Hq3S+9NLA
+nIX0VSWKWjxh+wVczdYQDipX5uHppeaVP+fJSXIqEVVvcDSogPJ747F+Sxiw+KJF
+7DxL21lN4Oa2VFVPVWdYPrqnqSjw3qoVmONYB4Vb4TksHcj9wxo7DQrL4euPHtnJ
+bMWyaC2GMNJJUeW7yZN+Fr6LmhrUZiQKtjdSPNETJpZQEu9iFd9VLfZ/ukjG3MOb
+hHULOkls/rqwLgLG9gdChBf70d88xD2waZnQsTK1RSjQoyBkqvm1fJh7dgB6Lluv
+0On5y1hiRhleV7croW4T5UJxHhB210E/CrJIryaz8MbjVUrgdzlfh2aHH5c5kVJq
+E4HLoFjNIkURQnN0XcMbYJCT6HXhRtQa8vcODxrwtRLu4J/sylUv/3e5dfVeGuDd
+EBGyJ6j6qPdU8h4j8GhHtmjcT5900Mr2Fb+TOCnzQszo+SksndPQVFEmDmIBLUv7
+U62wBHpzl9NmfSGYwvYeVytHO5Ufa34U3pbxWi5IJOyopFMjIA974Hx4En5OAHgh
+qZxeB/A7yZ9PPWc2AkjNowpvCAnAYKtrJBQZMNF1WLajLWwk1CYJcbxUF4j4amGX
+NzNg3KaiBOd+usBFKLWbmaaMXPQVOijbkYkukanPxdk+hxtTykJSp7uMGhGgzQHP
+FQ2/5bfvpt3eSY1AT+NLZyaNAe30I31VSFOVBbYcGy89KTZUgay4oXGFZvpSa75l
+ro/9RNIe7cYOapB/yzgR9BtJB1r3rBpEOrs+FYV0QcaIgBwbBmJnU4Ew4kgT9kcz
+1CZ0mZTB2ysg9jXquvhFTY2n1clRUrD+IAd9Lkx7x2LGAd3ZGOPxS0l+gG1BoMSH
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingUIDsTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingUIDsTest6.pem
deleted file mode 100644
index 224a2cebb5..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingUIDsTest6.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=UID CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcTCCAdqgAwIBAgICA+kwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxUcnVzdCBBbmNo
-b3IwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjA6MQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxDzANBgNVBAMTBlVJRCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyt5HBgA3udSw3/TzrG90sAN/8wyl
-eDWkGAUc1kYzyzCyNNRMYjTspi391pcr4incsgjvOY3Xc6YT8ajMzFw0R+ur6hbl
-oTYcbzdNNZGzr2w66IMDMntKTpZ2PpUH4XoCvJmNc4xIohL60RqPrGofttwpyfS+
-gxXCpVjsfywnR40CAwEAAYICBSCjfDB6MB8GA1UdIwQYMBaAFPts1C2Bnsonep4N
-sDzqmryH/0nqMB0GA1UdDgQWBBTSZXzCH9kXQYjs1VhEmgfiHMx4FTAOBgNVHQ8B
-Af8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMB
-Af8wDQYJKoZIhvcNAQEFBQADgYEAJZCA4IQ1YgY/8DcUafiLUKwirRsP5C7cCdMr
-0POcMDPmF5wyw0VuUGqHnAFEvc3VXjHv7KPJjlq0BPN6Zv/mWpumTOEMZNM8ik5u
-2NwuDmexmwkXHhK63MVV+iVsef6nWxx2Xf3ahbbLQgFnMIbLeNzXpIPzyFlQK0V/
-ABcwlzg=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid UIDs EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=UID CA
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBATANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxDzANBgNVBAMTBlVJRCBDQTAeFw0w
-MTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFMxCzAJBgNVBAYTAlVTMRowGAYD
-VQQKExFUZXN0IENlcnRpZmljYXRlczEoMCYGA1UEAxMfVmFsaWQgVUlEcyBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0NjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA61z4
-7chYRZr2FRLh+/4cPggLdSkDgQkdFCuflGzLsN21pmtZue3b7qADRSFwnmP5wQ9L
-dOEPzufTiCt3wcPEHCaBCCN0Rr+8iWwww76h7HE0jjU9o7IHje6qAOhc7THvZS3s
-kiVb9Nt1J1/KSPM3oltTENEyjuLaXbI9XIYY/p0CAwEAAYECBSCjazBpMB8GA1Ud
-IwQYMBaAFNJlfMIf2RdBiOzVWESaB+IczHgVMB0GA1UdDgQWBBRMlbVlFGZ1ahlQ
-H8QnvM3PBG+n+DAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA0GCSqGSIb3DQEBBQUAA4GBALXKf4ViSQp8LaI9MVvNFJ5b/YG4jXBpGXXp
-htEyinitf4scZy55fdtqANeG0Ph5y7633SFANNBWS+enHNQu3Nti8boG52chWIzf
-/8vANjunWkn/PVQrI6jXORTFNG+Ia/baFDbpKyjIta1g79QVXdqi7xQ9Neo6r81u
-uhx3rn/V
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=UID CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D2:65:7C:C2:1F:D9:17:41:88:EC:D5:58:44:9A:07:E2:1C:CC:78:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 69:bb:bb:27:78:93:70:70:bc:06:5b:eb:d0:3a:9e:78:3a:e3:
- dc:8a:0f:8d:77:93:e1:6a:c9:83:f5:64:f8:0c:5f:27:0b:1f:
- a9:83:a3:c4:f3:87:ea:24:f8:79:41:a4:44:56:1b:93:78:bd:
- e5:83:d9:60:2f:2e:d0:92:1b:41:2a:90:0c:9f:5f:90:1c:07:
- 88:98:b4:6b:cb:78:98:da:30:d2:37:d2:44:19:c7:d3:fc:9e:
- 65:89:2e:f4:77:7d:f5:9f:4b:f7:72:3f:32:d9:90:d8:52:0a:
- dc:ce:51:81:21:f5:25:59:02:11:34:8f:52:24:ad:0c:0d:69:
- 2f:2d
------BEGIN X509 CRL-----
-MIIBMzCBnQIBATANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxDzANBgNVBAMTBlVJRCBDQRcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAU0mV8wh/ZF0GI7NVY
-RJoH4hzMeBUwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAabu7J3iTcHC8
-Blvr0DqeeDrj3IoPjXeT4WrJg/Vk+AxfJwsfqYOjxPOH6iT4eUGkRFYbk3i95YPZ
-YC8u0JIbQSqQDJ9fkBwHiJi0a8t4mNow0jfSRBnH0/yeZYku9Hd99Z9L93I/MtmQ
-2FIK3M5RgSH1JVkCETSPUiStDA1pLy0=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3.pem
deleted file mode 100644
index a2b8d417c1..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Name Chaining Whitespace EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICiDCCAfGgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEb
-MBkGA1UEChMSVGVzdCAgQ2VydGlmaWNhdGVzMRQwEgYDVQQDEwtHb29kICAgICBD
-QTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE8MDoGA1UEAxMzVmFsaWQgTmFt
-ZSBDaGFpbmluZyBXaGl0ZXNwYWNlIEVFIENlcnRpZmljYXRlIFRlc3QzMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnqTq65lI16x9K+4TSv4Kj5oTA79gcaQ1V
-o1Pov5lyumlF8AxDNIBczzkCmRw0G5yTUG0GK47M9jfAWj3nlYjtQY324wjwcRYX
-TqFCcPr4Aw4VdxQ58+hE/Dve+Q9KgH8XJ7KELJoiN9dCmYcTXnkW+ZNnPYGpAtf8
-2QXDyCwO5QIDAQABo2swaTAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWU
-xzAdBgNVHQ4EFgQU7dgiWtJswE2iwyEUO2QMiVBSZGEwDgYDVR0PAQH/BAQDAgTw
-MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQBYEf4J
-9G7Vag3A4nNIKYSRK1FULS5V4XEpbh7h12s4NjEulFrxn9ZKwSbElwar9CYZIOJl
-sW77M3xjTub/6l2DwT+pBp8smD4WdcN8D9453M0nY3+0de6hU09COr7/AWVzbxzd
-UEHnXWDZu5PRgbj14UJKrqBzQiZAbMRx5b8sAw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3EE.pem
new file mode 100644
index 0000000000..dffeeb76b8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C5 EA CC 72 B7 CA 5D 4B 8A 21 2F E1 75 89 75 BD FF 49 9B D0
+ friendlyName: Valid Name Chaining Whitespace Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Name Chaining Whitespace EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIBCzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEg
+MB4GA1UEChMXVGVzdCAgQ2VydGlmaWNhdGVzIDIwMTExFDASBgNVBAMTC0dvb2Qg
+ICAgIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowbDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExPDA6BgNVBAMT
+M1ZhbGlkIE5hbWUgQ2hhaW5pbmcgV2hpdGVzcGFjZSBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALHDyEmorSlP274u
+/18BUHzKkc9SIwgCP7PBHTOfjf6Zy5H5WVZ0iPjotyQpm8nhiZLodmJ7I14LyQaV
+gCQaZJR3gw5dKMYHotPXQcI4jptWTiiG+aNT7bZREbg5BA7jTswTLokWbcQHBSx6
+iN6QfHS1LJP0ah4ccVVpi3sqDvfzhzWsU9s/S2pFUOHM6/iHc6H9Zy/CxceTHrt9
+jw5A3KHRZ9ihMGuwZXZfZn7HHtDuVMUb23QRhBVoPo+QzCCGXb3Kxr1/qM1EiFgW
+mkieRIPGygUkFoGyH+ELQNclyI1bb9jsW4g+vr6PTYgEJofktbQB3WwCRH7ADIW6
+6fpSr/UCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2lEHIUUfWvOskw
+HQYDVR0OBBYEFM+4igHs3RwMuk/hDgGZXsfaFTxTMA4GA1UdDwEB/wQEAwIE8DAX
+BgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAD5C0FF8
+5YCkCu/hOuIAlLhMSkjdlBKlpnFriNjiKtNNPm+lEXUCnN9Iug/QrqevX1wTN7zx
+glDipUTax7bo3/z4eT/eURz5shg4swHdnDofLxRDJybSEG0hEDUgu+lvww13FHFQ
+6ZgGvgC4O5wPE1UVCQmM2EcVkcdn6sMLozzH+sg40gj/VALvh2H6VhobkV7dzI82
+cGPZhPDNjO/w4MjGTfhQjPvMGVuLjazBZxNCyfZeYDjygmIDSDLmFAdum34Vk8OL
+/lGLKLp31rM7EBYhkpu48PhPy8iUXAvR+qPlcKfbQ+k/D8rbzDE3tX/Iw/6LdhU5
+3xt3vd6uvytI5dY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C5 EA CC 72 B7 CA 5D 4B 8A 21 2F E1 75 89 75 BD FF 49 9B D0
+ friendlyName: Valid Name Chaining Whitespace Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D3BDEACC98B28A3E
+
+Nr7q4KiLPfumYbQawi1p1XmHeWRLufp83i14WwnfoIDJ/D592JH9a6e2g78ostDW
+F/S0VMtut7GMOd+e3rzS9vKEN1/KJHuatbgpvt6aMsCxeqsQjWq90cx3XxN9GDSj
+zQ/z7yNE8DbOu3Ohs8uZnAWId94sX6pbFndkjSys3pbdhgwQ86cxNIZvXBL2PHyL
+kP4VgOOolg2gE+1jYbZhzIZxpLv2bVoTtHWqr6NlhmPzWSTrlvLOUlsh31btmGD/
+9bHp/L7WCV++S8J6bDVlkcwVgo3k9m6hoKt7m2AbV7ljztvgpJM0isZ5CDNIQD4u
+sLpPGssVIrJ+90EsrhyEAqOzSmbaL6OEvbXkAilhaaPG8fGjPjJmlSiO/rV3acxc
+wuqt6dipGUBDGzVBTopOE97zLyHgmoRH1Zh2m9JM6IZrSZpx3oYaiwBEhwXpOSD+
+edbC2Jl8h2xJls0KJbP2SfhRvkXBoKHkwDLgEUuCGhD6vXqP0zeGn3oaCe7Bk75q
+l+qIlbNh8ytLTe/ZNaj0xZ9KzuryeiYM8bFoRANsI6iYrPeI6oBo6kv1EYEKPRef
+xhuoTYrtwoRJzou7+SiHPJCDtArWJ2EJAWLIsN3ymX1gaW+Lk1mESSXntT5pKDBL
+63FxoG9hTl4G2/HGMwGmbbxNO2o/IhE4bQRSlsedadQxMnXHKq4NAjB4Jz7Dhk8N
+PhuWB9T6RnZGajwXMPYGVCzJ2ms8pnN6DE9NreZmgCoDHDE203Zh5WQqLJ0fTxy4
+ZvF/Yx0OXe0ZAgoiNpmu8lpKXTuz4nReKrXIdeWDmzeWKdyCMV3z5/+Vh62/UbUE
+hsvCczwL5W+Cial+tIc0r3zX3hpohEqT+oTUAznTRqy5dqpL6vfubZephO/XU3gI
+BLcnyGMbjmXJiAGxotXYjZsYhf8f56yOfzY0EZmjehDxNJbLh/IWh3eWhWyciNRg
++aWL+95YIJnkR5dgNj2mnveS1BdqjZ34WIziYUTrGyIZXWvx4883Ilc15acB9Ul8
+89wGIhVEY0CNFl7mrGnRSuWL5EXNCBk0lhA0LtDivO1wSwqjQ7lji1lKG6MmWJob
+cQ2YBy01ERGt1G8rOzL3V0/Pbr2Bp0zwKkWeD4Y0ebtawmVCcqny+XtrEfz3I38K
+WMqbLwEsnj3YM8KI3rM6FjfPbp3vrlRj1hclaaE89aXy9SYtdfBypJi7am7xpkou
++8Q9LRuXucorLQEVpFT3ZevXvl+hSXEfjEZG8fQ3bsrnXsoP8hB0DII5jgVkvqh0
+rwKQYFmL9yfVHnimGUneNjpnEIaiFDK5cq8KEkR6g29wEof431kVXek9nSG/UkyG
+ylh9YlxwHmbJQKRiJeFYSILWEEz0KsTD1GhXu9qsucRUAlPp6cVdpl4kA7Z/3ERj
+/Zs1f6aEQZokhdOhSZz2QnUb4xMWY6TduM9FqPrFBbjII5/4o5mOJVAPTgpDzI71
+4Bz+C2riSODikKivmeIq5OE1fYpuN/WyL380wx6HkNqpjlNTy/Y1fM302GX+4JCS
+7iBZDndYgQawpPDXz+S4eoehksUP0y7IWaLkoD6SRqh7P3GtvqtHf6V4/aawhu9D
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4.pem
deleted file mode 100644
index 771472db84..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Name Chaining Whitespace EE Certificate Test4
-issuer=/C=US/O=Test Certificates /CN= Good CA
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBDDANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEd
-MBsGA1UEChMUVGVzdCBDZXJ0aWZpY2F0ZXMgICAxEzARBgNVBAMTCiAgIEdvb2Qg
-Q0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBnMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPDA6BgNVBAMTM1ZhbGlkIE5h
-bWUgQ2hhaW5pbmcgV2hpdGVzcGFjZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtFVzL02aRX103n0ddypzMXb4EZ6au9/l
-Cf7wLoF0u6IHixT05tw1feYoDt23vnfJKOjwqqcqnshCi0k949dyrQeTAnFQXsqp
-aPj1xjdYq3ohEKTObPeGRiyinhMAEZHxTLUyIW3hmjooktV827Bg1l9wIozE3pvw
-XyRbd3rAkFECAwEAAaNrMGkwHwYDVR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oV
-lMcwHQYDVR0OBBYEFHeQkes2kV9nbiKaIemSfMP1WNMPMA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAW5OD
-GSTMa2KPAQpLgH0nrncEH6jRAkyk6il7E2N0bz1KJP1itGDbzdrNTtMTs0rD9waM
-K3JrQGfALXvoj0+PD+Z/AbrpO3WKKuDkKOjIPt4Yyf59K36K0ZLKk6zID6ilR6Em
-0BaM9OimGTwDaij8MOU8FMuwXFgOu/wPciMU18s=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4EE.pem
new file mode 100644
index 0000000000..abc0b5bde9
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameChainingWhitespaceTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 3D 5A 26 7E 13 F6 36 79 3C 23 EA CD 54 62 D3 0B 6A 73 28 67
+ friendlyName: Valid Name Chaining Whitespace Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Name Chaining Whitespace EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011 /CN= Good CA
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBDDANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMSAgIDETMBEGA1UEAxMKICAg
+R29vZCBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGwxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTwwOgYDVQQD
+EzNWYWxpZCBOYW1lIENoYWluaW5nIFdoaXRlc3BhY2UgRUUgQ2VydGlmaWNhdGUg
+VGVzdDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4La/z52GYvBOP
+DFvAnfCjhivYpHlbMWtU7svc8tBER62tEOta4nC30i3dcKjgB4jKDM0F/u+OYl5Z
+4yFB30IiJm1OTj7IPf3ByvpExvPpHnVzsDHejQxAYSFIzrncOZbFmVbMy9cX7D4W
+hNQV4NAokTP6yocnUTxjyStNrQdvFvddslImXHlFUhLDSms8iW0DUbxkKoSajmBc
+tUMNb+fF8UXzCKZbrLX0Oe3Yb9DsjooJcbDWPosIx5f4JuoqBPZlAYzbfLY6n2mi
+zuITEX8Y92Frb8IHPV5BiGB6BH6zacuSPpL2wraRdgZ+RDp7LhWLEgeoEgVpKPJa
+9NkL8frjAgMBAAGjazBpMB8GA1UdIwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJ
+MB0GA1UdDgQWBBSbK6wW/RUIeRut/gCL5ZdIwM6pZjAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQCMYzO9
++8BMUK03i/AJRqCMqbqswHkkb9HeVjXHy+NzN7WK766jlSW/uTQ0GQSVdnU7Fsz6
+UH5gLW3U0xngEYRP29iXNVKvcowLt9QDnHFOSyIQDPby499+YulERS5kAOhjm7pt
+Yq75dLt/tNpEueSYzI9oUQzwIGpkyaVVlfmO/FJZdhpJ9MCZjzWoUhuLxXIQm+mD
+UAme2M514vtqwa8RG9xUQdO/CnXZKhAKNp+VK2zn5qt9FynWL5k1kMmxUkuqLapu
+duPbakDGRpP8vsj9QNWSmE2h0ZIZQ620VZ9121qhv9hvngL+RJcryL3aAbgQOmk3
+3eJOprz8zBsDGy4q
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3D 5A 26 7E 13 F6 36 79 3C 23 EA CD 54 62 D3 0B 6A 73 28 67
+ friendlyName: Valid Name Chaining Whitespace Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4424FB8B710FB0B1
+
+s9Ot42C5xYET6pUlfi69SDT8WEn0dPhZlU8nYvNUpjhU4Oe70ZZ/oQXKrBfT+Lnl
+vV9z4M+4R5OaRNx6vZQ6fv37HodsZoAv6cCEtw+zN8l4FxCH55FbtDYgvCCqM7ek
+MOGzEK5cpKgeAk7ayU3PXC2zNKDGVNmUzZ2o4eFcxlG6ZlsqEOqddAQKA6pVlzep
+6hvycuHBaKYutrCgC2H8N5Go0Mxdg0cVi9QUUQQjtGgvpD6k99eicwk3BczNHPFa
+i+pv5exRDf1brZRlAGKiYMc6SjscRAyZmZQW09+IwFC/8+Nz9aA/Z4/hMt7hd0n4
+s4fWl/EnYVd25FH3cG0l1g0SYvi+tkHclftGMVHrkuy01oCi04Ak4qh0XTaDm2Qn
+TVLLrrBhAlRFnKWHxVqSTjT+8myfJII2W09tO/eVYS8n6lBYkT5FyN2SVy8SqV/s
+L6+cwi9ihmIXUjK0DQlDdo41g9fGTkx5SrhNje1Ztpoxymg4B3Y/OHtvnAZ6SskE
+ZqivMN3ugiszipW0akTdGx42auWkH+CZZU38UtwAz3FLUa7TaEGnA96OSBiVSn4F
+mfDg8xj3QtUTexqaQxT5ut3Eyd8s7dn/WbsItwJNRgHku9GyMmgEDNpTR0sAIXEm
+F7PDc6Qd5/7h0KGmQdA6hVMIqGBeND+2zgcyThcjF/JMdzehIC0Ga8lLdc5kYvUY
+cx/dFx4NVWvxQCmJzDvIueZl1YduE6fxugRXElTlSoVjpMNHnVOBW/ZEjVWThBkj
+asvAEBgv88lmPKC1s+scM3MNCWT8CWQyqXjtm3XLIJe3huFg2g7/NcrTicT9FvLs
+bKSOiJMsmTA4wwTyDXduaUv2PIs15fRPgjEOytm+LFb02c/5677cTfHeU2dQJctI
+Z6eSbJYk/B+2QApmyUs+yGh4El3xkEBEF04o6bkipnbceIm3LJxrPnjlSkWJURT+
+6yMB2TeJVG+DFparwjInS43EHTMstpGbf5DaW2se1ZQJPLH0w/ePtSzRI3ysPC71
+ycxIRCK3buGZG7oj+SZMcalA1IsMxxrEgM0bT+gmb1yVitrUbwCqn/o0NlK2uB2K
+TUQkElJnLyTULroBr6DjkmtbRmlogKsfOlU0IxdtEotOD7dFjw4tqXtQXmMOi7fK
+5QbCXl/ddP8PwibQUYxXtAyh9jaGfGKAo8dw0pLz9hg7XmHOfxjYtXkMEnTPKNk2
+LBBxRqLAKGeEQxErVjor7c7K3fYE2b3oRRwEyb6WDXFHdTH60gL5HpNr0YCjxb2Z
+oOeXmCjAZRm8Gyxvk5cCetjdDH94aHfk5t5HMp4roQOqnC1s1LfGloHUFiMgOX6R
+iQhbH1oYdIrhrOIUI6dwBsglmct92oiQySB5SyvLME+AZHZkVl51ckkSDfpJP30a
+iS2NxinNhmbSCuKDpwd/rqRHF0C1sZY+Xj0YC5yxa1gxOMmuJe7HYtbr8Ymlh3/L
+UkcMecNVV2VJyRBJ/2LC1gMbXRmHO6xt2hphjyf0LBO53ddh26VUWK5uSF2SNVzb
+oI5kZI0Rzhp+dmCk8mgyNqWDXkhb42kd0dfqe1AqQur92CrS9fpEzchXUL2ZwKTv
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameUIDsTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameUIDsTest6EE.pem
new file mode 100644
index 0000000000..fc4d93467f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNameUIDsTest6EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 48 C5 C3 96 59 8B 77 F9 C6 6C 80 92 B1 82 72 D7 DA B8 9D C0
+ friendlyName: Valid Name UIDs Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid UIDs EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=UID CA
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEPMA0GA1UEAxMGVUlEIENB
+MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowWDELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExKDAmBgNVBAMTH1ZhbGlk
+IFVJRHMgRUUgQ2VydGlmaWNhdGUgVGVzdDYwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC+CDXTTtVJkN0JuysaGMhtKLPv9bAL5wjPaio74JOJd/yT6Ht6
+Wakzti6sGWJ+ZXZV/b06A0pjX42Ni28NhdQWVYdoePNde5WTbowdR2TOnxEAGJg0
+ztClAEBDgAI6xSk47UJ0Dw0Rfs0hJcbLNQnqAHU1UllAX9XanFDrAVMzucVxYIiA
+DF2dYc8k9qeWYp0iASwG8uNhOjV4yZK2qnP+Zbgvi7rfs9hRGFq41TcWmfgiEaPg
+olDsycWP9+3xN0VeUQWSI+a+m/WqXfn1YlID2fDdBfTAluGZo0XgLDCaFEBTykbz
+txF492qwzSjSDTRTFDOXeFtFrG7D7iw01GmFAgMBAAGBAgUgo2swaTAfBgNVHSME
+GDAWgBQQP8UEMPHYQzaFeVyMjYud7i8cqTAdBgNVHQ4EFgQUtSL+I/d8UPhnT9HV
+xez6eEtAmW0wDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
+ATANBgkqhkiG9w0BAQsFAAOCAQEAVZmul1o1onioRq7Mh7wUzGcIsXfNPryARrfO
+1+dn/QwbrfraBtW5LlUHgaqn0etd/7oy0YslTJ0eR0NvxyrJzTS+qENkN2DVlrUo
+qcwE/P+9iA0eL3oaZROmf5zqOJ6dw0DHYHiEZH6u3rAd6fG1X0gQysvaDIlxMcCt
+d6BaWAaWxn9GR/9Jwi/imjiVwgzZ5xlll2KuDBt5pv7Gl3o39KIGB/kJ4amgBA6l
+ucxz6BnG7Wp5NgTRQpGnSptptIDinQy+0deTYoi7+iCttzXf9mrETOcTJNOZA0PN
+86Y3oRXxtGlORZg9ikd6FpYqtYVw91S+v/r/yfYm10GHltaHbw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 48 C5 C3 96 59 8B 77 F9 C6 6C 80 92 B1 82 72 D7 DA B8 9D C0
+ friendlyName: Valid Name UIDs Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,424E1AF928678900
+
+YwTAyp6DSje4XkbA6+7pLIXYEGioKDM/iFTS+W4bDgiGY9tGEI6Js4DC/lrmTYhQ
+By//w7eBBFF0ELFJBcCgJppFVhSEGslvCf+Uwf6IMPJ12MBCGmGrDoIQB7rlfOrQ
+yRB0QHq4tLBQBFHe6cMPxJck9hFZU1r18rwDpbZDIP/c6Gi+NBBp4jj1lWHhZ+Jr
+NogkD5lv1MLJuZKog8r84W76VdELoR9L6uWkxPC3R9EaafWW7DrMo84FqUgEAQ/l
+XcUng/IRTzXpfr60m4WcvJkbXcaE1R9SDSnt1kn2Y8MJku/s7wjT+iu2RMwEww9c
+XoLHECtPhmUBoDgTSHU98sL6tBlAaonsmrMkYsZTy8bmdmsQlCF3AdHH9sA17FOg
+mUqwyRyZzMk6A/Pnb4Y8/uLO5EaALNpxN0pEd7s6Aycuzzrj7lNgvC6lem+JHZyO
+fDcwCdgCLiIQol4xrYWyALc74fssBh1ZHxQrbAbZVC9jKk6E6akS6xxZpXcV/F9B
+R3aMxOz5oU+cZyhufHjuQelBTe+S6aPKzVfQwO9jJ7ClSD1zoRnwOkIqCMLLmK1q
+0XMSX8vX0AX7zIQfQCOpyelJ8W3lJBm2RHB6XEoDxziRJY13UaT+Vh1ToSvJgbWp
+P/gGP+0M67ZFhO5w6dvaBGEBwpJpB7TrQbpUN/X66bb9qdjPl5/V2NRe7M599LFW
+WaO+Hxyof4Y+fElpDENdxLPT06xRWYEpwsOHdgdCdFBFyy0Tpes3tm8BizQfTDbI
+13CCoCHEwoo53x8jE1IJb8LuvxzVa5Z+CldEqXzXkZY8/I784t8efJ7yeC+9kjgz
+hT/GB65rOT0+2yLJfZnaU0I6XYHvaHfuyBHy+Ah5Y+rzF8DG/aMIMo7GpEH5uCF+
+WyDouWECjzllp4+vOCEua/5+RsBjzS9R2ep63AoDlNBzieHc2FouSaBobUNXHZrz
+SuSziiuiFVLfV1iD68TRgZGclf3BUx5QaoEbyR2poH1BnY1Kf5SQVgctBjA0oROb
+a0ngVuAXnUDIAl9dVNb8CQZlXf563znQVE8QVeuPiCgboyQsN0hwDiYgxUPUAdH7
+0CUKlE44ZfTQtQLPUsvwBiPEmSkDaSg4LwstxMv0kQYjygfaAlCFxUANi1Bg15Zx
+06ns8ACHPhD+QSOCtLqrhK0CAFJqek54Oma+GmdhvBSN7L5SmZ1f3wwhge/zumE1
+OhwJD30Fcq2aoqYJG1Pa8B/dV7i8qpTthCfva/dd0LldmRfnUZRU61rr9eSJ1a63
+NNEnZBGGgMRSeIKGUX4qTi0IltuazgKZ+6JLGR74xTi5RIpQIVz8xpSO4qbE2/df
+B2woTgXGvEjiThx7lC0/elQf/Wsd6xAqF0JPFV4NfnsAYSVnUKKiuy8+Yxn34NIF
+OMd/CJw+CR/HoA7NmpWacdo2TFEnXHbiLDX7YTlU53G/KNvcao5yHhJJUJLabdhl
+9fwca4WDXb3B3rOVATjT4NI1SK2JALP3xaBfo4zmM+EZLqkaZMCZLqL9sA0C7msv
+Q6Z+PSFoHctZsyrpwnqE/uHhDb5iZSB75uLFDNVN+VUhvfCTIlG4hZNPYu0pJ5hY
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14.pem
deleted file mode 100644
index 9a22bdd53d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14.pem
+++ /dev/null
@@ -1,114 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Negative Serial Number CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfzCCAeigAwIBAgIBETANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZTmVnYXRpdmUg
-U2VyaWFsIE51bWJlciBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw5yD
-rVmP3dVETqSrKKVXvXWAnpc5K5Xh6mhHBvy/YpoERigE1MP8A/6eE3mY6OnMJVAh
-QJRWniYBrIDg5zR873cTAbn1O7MwSfs3LLxEO81iAf2k4nFFxAGtQp5AUwx0cQVK
-8oMVty8BEcAkazVA87HQgpycQySqDLmklHNqkncCAwEAAaN8MHowHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJCMpyNNS/fqobISh7nA
-0w4zWMuCMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBYz9xXPhMcniA6W0RG
-0A59JbhJJpAZmnLBusWQjWYIZsVit1M1OXc/zDGAP/ik3blednL+t+wbdJc1qg9m
-4bgoXS14lg+6IGMF2VWcoKkDJDIHpkVrdQc9WGNm0qqPyHGW0ggbi5VrBv1potkF
-xBtl1WkY3ZTLuI71pJ15ebGZ/A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Negative Serial Number EE Certificate Test14
-issuer=/C=US/O=Test Certificates/CN=Negative Serial Number CA
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgICAP8wDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQDExlOZWdhdGl2ZSBT
-ZXJpYWwgTnVtYmVyIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-ZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTswOQYD
-VQQDEzJWYWxpZCBOZWdhdGl2ZSBTZXJpYWwgTnVtYmVyIEVFIENlcnRpZmljYXRl
-IFRlc3QxNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyaurbJH9ZU3CCKl1
-jedpYcQntOZVxoXqpoC11EXMnSgUPLtVfWuoClVqZaOYnkz2hX1aomA+hGT62UOh
-f1CSywco7QnAAlWwu42zT5iJabaCruBWz/PqdvWkSWzcrMfuyybPEsil8hgaN0yl
-VNXZvUwPUtfwUndR4UltFdPmJPUCAwEAAaNrMGkwHwYDVR0jBBgwFoAUkIynI01L
-9+qhshKHucDTDjNYy4IwHQYDVR0OBBYEFB28YeqZDPts27Viz5LcntslD4A4MA4G
-A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
-AQEFBQADgYEAJeShrxatt7S4H209vnaUvVpExfX57AGRT2t2QVz6ztEWMt+BGBQN
-FUeSeU03d2ot+fwxxvrmUcG9ofkKIP69tTUgObSRfwC39UjKModur68cBjYqscl8
-d5fI2pAS/xXHK/+OoBBAmHgAiuMMbWhQn7ZCI0qJT/t4eHAjQlh5/SI=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Negative Serial Number CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:90:8C:A7:23:4D:4B:F7:EA:A1:B2:12:87:B9:C0:D3:0E:33:58:CB:82
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: -01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 7d:55:77:de:74:f8:ae:25:02:35:ad:53:74:92:6f:89:f9:ed:
- b3:4c:bf:a7:70:b1:0e:20:4a:c3:03:7f:a9:99:01:5b:5a:a0:
- 67:df:cd:74:08:d6:80:2d:ca:f7:c0:be:9e:68:35:d3:79:89:
- 45:a7:6e:f2:75:86:e5:28:d0:00:2c:96:14:03:96:eb:75:d0:
- fa:a7:78:f8:50:e7:70:6b:cc:1a:9d:8a:30:1e:c5:5d:22:a9:
- ef:dd:07:48:85:87:d6:2f:15:02:d0:07:81:2c:bf:fa:c6:ce:
- 49:03:44:08:37:f3:f3:79:b1:61:ab:c7:f9:21:29:3f:4f:cb:
- 36:c0
------BEGIN X509 CRL-----
-MIIBajCB1AIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGU5lZ2F0aXZlIFNlcmlhbCBO
-dW1iZXIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgH/Fw0w
-MTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFJCMpyNN
-S/fqobISh7nA0w4zWMuCMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAH1V
-d950+K4lAjWtU3SSb4n57bNMv6dwsQ4gSsMDf6mZAVtaoGffzXQI1oAtyvfAvp5o
-NdN5iUWnbvJ1huUo0AAslhQDlut10PqnePhQ53BrzBqdijAexV0iqe/dB0iFh9Yv
-FQLQB4Esv/rGzkkDRAg38/N5sWGrx/khKT9PyzbA
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14EE.pem
new file mode 100644
index 0000000000..d400051189
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNegativeSerialNumberTest14EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D9 A6 ED 2D 15 8B 48 7E 54 27 B6 DD 2A C5 95 98 23 AE 96 57
+ friendlyName: Valid Negative Serial Number Test14 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Negative Serial Number EE Certificate Test14
+issuer=/C=US/O=Test Certificates 2011/CN=Negative Serial Number CA
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgICAP8wDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMTGU5lZ2F0
+aXZlIFNlcmlhbCBOdW1iZXIgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBrMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE7MDkGA1UEAxMyVmFsaWQgTmVnYXRpdmUgU2VyaWFsIE51bWJlciBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0MTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDlITWnwc4a51AQx39bPSv3yXmoWwt893rOAT2TyUaW0JoL4V429nq2KK4eS73Y
+O9ANnW4wkiIFpwMs7qGErId3x9TpP4K3Fs+QP1lCQtwjYFWGJekb2QI2jYhWPd7w
+YvZbYMM+Op7pQqnH3xuL69qH8hplbGOmwO9DoU/cSmIhFNAz9s9drx4lisU8MZts
+twarz+68DGUJTDIJgbB8Tqkimc6QaZBUQvY68wa0DA6eccxqXYLT1tWTtaru9kY/
+cRvrGFxHIw8E3Tmle9/Nhd8swZOHtKa1OqE7NPPsJtF5ETYZst5vSmk5SaC3qb8b
+IONR+qfNnAi1ZuSxakz20UoFAgMBAAGjazBpMB8GA1UdIwQYMBaAFGLkLjXGD8Xo
+kdALwY3etq/aiNk/MB0GA1UdDgQWBBQAZI4d4yK6xlDmm5mNqCZUF3QxoTAOBgNV
+HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEB
+CwUAA4IBAQA6I7Nx7MJAujumcj5Bl3gfBGd4ALdiiuHCwiO1KoP9FTYYeDVaRHg8
+TjO6YFwmgBBQg+aSvmi2N2m+vbEvpEyWLqlLyWg9WUZCk7cyUIti2+fbrbsATEtr
+iZ4dmVu7xDOF29Imoc8hig99oHBY9UdefJtzjlBQP3Mg/jyih8XvuYPNGxVVT3dg
+WtckNTq2O6v4SG64mbkTJxhbUDdqIBnoYIZvUkOzflWkr77YV7+q5iQzNCLMnNBx
+XRrFF3wV8V8dmuCVzHblVoyoKGmQHHWHpPaDrWy25aSxTSwCLdaUMGK6KCXlHhJf
+FHcc/suYcVKUB6D78BDupzMxpauERnB5
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D9 A6 ED 2D 15 8B 48 7E 54 27 B6 DD 2A C5 95 98 23 AE 96 57
+ friendlyName: Valid Negative Serial Number Test14 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4B42B554B0E77C15
+
+SFJEBFQakKS7qSxbf/aksRqZ0y/tDavD0tnzn9yP6+/FswJs+d/ZXS8fHwW4Vg/M
+cCrouK4zNjbLwC0F/K6fGswfEWxjiXFP4xVOYKfx8+c10gmvaXENpBVXhWsaY3yu
+HIA6Q668DY9K3XCnjDQTuWQPi4725UHxL6/PQ04CFkndsQwJGqShGXTjSNpbAJ+U
+B+R59NW7PANP3S+CevBvHMgkKNCl5SXEJRb/HCzjzsDH/y2ScVkCpC/ImtE375US
+FerM146VBtWc76CBCNdQ19zzEvZnIz6EIdVM8oKVpzGlUd2UfCXh9R5Qu9fexpFC
+5jIpvUk3vTNQmvfyAvDlJ07vnedEgNgnrQn/cVgbcGYvNQncAFFG8N78CAivaSCy
+T1G+LSH+4zbnfWd68XXaC8NGNAMa+woMeta1ZOM+ThFFFM3Rb+8Sx7S8Mj/mNPSO
+wvDb+PIP6K67yQ3GXByHsMSfqeuIbSc2cLwBJ6lAZyqcSJhNoIJwKN0blPIkufBp
+RdJGUHjs1J/8hfp6fO9PsXdp/PzV6YJNHmHMHGlAI933kOYIPeaxPjeiu4RGsY4g
+5qR8wDK6sHr3iJ8Xb5U/vIxldDNWKp9TyGm36wagJ+qz7Q2Ro4/NYS0cmlPKUnod
+nDw7cLP7sxLDZ9/ZjaXOcXttqDiwQhV2sK30GF07Xps8lHvJ2jftwPyBVwp27jwG
+pPddZiO77Ft9numEnxSnVc0KsU4qdttIjxOkJjvgkwjiDFfu68WdHtT1UDj2arhX
+0JBAfo6l5cp7NoUVakDwhlY+/zSPU8iVFwHLl79t6Vdmrr7/6UDk2/gh6oez7ejR
+UAlnXRxQDN1jxT0jad55uZfzmk9u5WxTFRmaDDSH5zRH3PtQEl8AW5rTTmDhp3bh
+xgcqk9+FZ0fwUai85jssXX7iQiBkADe54VLoEukX6aKLZm+DVxayIduMKKDHj1Fa
+Trsz5rRarqcAc76jtC/YbSwFHzwYgAUmiJ36hpA9Lwfqv2au9TZroJzV21OY5hHl
+oki8OpywcIh5FO4rPPPgmcFMrnhEsvQTwMLAsDtqYYHLTpTM2Wv7yWz473Zsy00e
+fcHPhjdr6w1oLnbbHZJ4CBuakayrxA6snlvQ0Rke3ZjL+bystuxJHKBlGDn0ZHEb
+aqcg0razy+W6zudBiUic+PDOQCrDGZKb/adD1X14y5Xdew9hpE86zAaWzHTTN+2B
+H63PAib61sag+nFEgStFhele1iTV6sB5+jOMju/nQmRCmXbZ00Mzq5pho8f92r/l
+08YyD2mJJ7NJSnRmcURz7u9igAArY711McnpnHh8vDDmWDYvamYI65PYm9ZUm4TF
+Pmx/ym7gIn19Sxzxw37N4lF6UgMl/SHpMpSyTmH6EvwHwACRz30l3kbaAz0R11fJ
++tCNwPt7KqziDQmtDuaTB0fxo+XMZuIsuRT0uQYuXzL8rZLzqq5pwa+97Pmek4a5
+/UhW8NMSzWjeHMLUJSbScOwBegzAPsa7WC4HwxmKPX5dNBMD9ck8xdZIjm5NNWvJ
+SPyBScFhhsjcAX4BJ6D1rTpsp29TcC3AF8RPMk8sPs/ayLi+i7AU3xe7v0fcdcQx
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10.pem
deleted file mode 100644
index 88bd982c69..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=No issuingDistributionPoint CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBTDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFIxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUGA1UECxMeTm8gaXNzdWlu
-Z0Rpc3RyaWJ1dGlvblBvaW50IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQC+7yNDGaK8AFxVWkjA1JkTRG1Ze29lXbN/99oD+Gw2q2C9yJHbDB2tcVCeM2wJ
-8pbpFvzPv6TEGbmHVkvO32/pu/fhM5cGgzsZxXvEaQi6+Kb0nasof2lHEnO5T8BO
-HGaef+bGmAPcnJWU3QPU6Ni7kv0b9HLPi9BNFdaUGU+65wIDAQABo3wwejAfBgNV
-HSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQULBOPxQ4nI9HR
-Qd/fYYS5T/Ey7DEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAItv1utyf+4Z
-3pR/ExgGC7oEyQ8VZYYdil+JMtcrqExHY/zVEbgu4Cq1JTu3uC2MGAYO7BD2aVGI
-0g9Ij/ikkEZ2G2mW3Lqar9JL/57BgPyEwIlp9czHYCx4M0tewGXoBeQdmeHK6O+9
-YJS+QJZz/98L8lfp6mHuGoZid1McgVLT
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid No issuingDistributionPoint EE Certificate Test10
-issuer=/C=US/O=Test Certificates/OU=No issuingDistributionPoint CA
------BEGIN CERTIFICATE-----
-MIIDFTCCAn6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAsTHk5vIGlzc3VpbmdE
-aXN0cmlidXRpb25Qb2ludCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMGsxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFA
-MD4GA1UEAxM3VmFsaWQgTm8gaXNzdWluZ0Rpc3RyaWJ1dGlvblBvaW50IEVFIENl
-cnRpZmljYXRlIFRlc3QxMDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuYMU
-46Qzp+krE4xNOAL0bJYv9lOdlPMvMyU1ObejWulK7jGlVjYtf+KtVV+/BCajxoDZ
-LTSqx7R2RSJMaVQ41OzI3aHD5rR0M/ktYNhTotwcy0tFJQ6nwub0fTsjBLPSZZ6M
-UjGg5tiHZ0c/lBKBJj7BTY61F7kTWO5M7Dgz6XkCAwEAAaOB4TCB3jAfBgNVHSME
-GDAWgBQsE4/FDicj0dFB399hhLlP8TLsMTAdBgNVHQ4EFgQUpv9aWeCQYlWo0eBZ
-Sr+FnrT5hmgwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATBzBgNVHR8EbDBqMGigZqBkpGIwYDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMScwJQYDVQQLEx5ObyBpc3N1aW5nRGlzdHJpYnV0aW9u
-UG9pbnQgQ0ExDDAKBgNVBAMTA0NSTDANBgkqhkiG9w0BAQUFAAOBgQAnygifO5CB
-a6drkb7+IIxC6kXu8iPf648/puVdI4z8+u6p7gNdiaLEFmOPTQ8UDz2ih5aIHHl0
-hC5DWNF5udEHFCzGgMarH2kgkM08thSsxhe0rfAAjGVbGEQWpFWDS0+CXTEYLu2S
-A0fgLzVvlU+60EmmSDdOwNMTeKmElbD6fw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=No issuingDistributionPoint CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:2C:13:8F:C5:0E:27:23:D1:D1:41:DF:DF:61:84:B9:4F:F1:32:EC:31
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0c:8e:a7:dd:16:a9:a6:c2:0d:1a:ba:ee:cc:e6:7a:59:dd:b1:
- 9b:f2:70:22:7e:c4:3a:eb:9c:95:0b:63:0c:39:df:67:b8:5e:
- 14:7c:b8:83:75:d8:de:35:fd:9d:bc:1f:2b:87:89:ae:82:85:
- de:35:26:ab:f9:40:16:ae:6c:9e:9a:b0:b5:97:5f:c8:19:7e:
- 7e:de:96:79:0b:7d:df:5c:8d:05:a5:99:fa:b5:bc:ad:f8:af:
- 9d:7c:75:de:70:73:0e:ae:1e:08:e1:7b:36:8b:23:21:99:bc:
- 8b:6c:2d:de:90:f3:c5:df:7f:15:c1:69:89:15:a5:b5:09:21:
- 80:c4
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAsTHk5vIGlzc3VpbmdEaXN0cmli
-dXRpb25Qb2ludCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAULBOPxQ4nI9HRQd/fYYS5T/Ey7DEwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEADI6n3RappsINGrruzOZ6Wd2xm/JwIn7EOuuclQtjDDnf
-Z7heFHy4g3XY3jX9nbwfK4eJroKF3jUmq/lAFq5snpqwtZdfyBl+ft6WeQt931yN
-BaWZ+rW8rfivnXx13nBzDq4eCOF7NosjIZm8i2wt3pDzxd9/FcFpiRWltQkhgMQ=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10EE.pem
new file mode 100644
index 0000000000..bad89bfbb6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidNoissuingDistributionPointTest10EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 15 05 6F 6C 5F D9 9A 75 E4 34 10 14 6D 59 81 D2 57 30 BD A4
+ friendlyName: Valid No issuingDistributionPoint Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid No issuingDistributionPoint EE Certificate Test10
+issuer=/C=US/O=Test Certificates 2011/OU=No issuingDistributionPoint CA
+-----BEGIN CERTIFICATE-----
+MIIEKTCCAxGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UECxMeTm8gaXNz
+dWluZ0Rpc3RyaWJ1dGlvblBvaW50IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowcDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExQDA+BgNVBAMTN1ZhbGlkIE5vIGlzc3VpbmdEaXN0cmlidXRpb25Q
+b2ludCBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTAwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDYnGAHOLgjYWYIB7Bwhy8gdYVPI3JzxjmJzIWNO4uPVoymvcGg
+8CbIcpBtwiMtUpGWzF6atiNmJZRBJNFbzdUnIrxPDNiNaye0dIkK84WQ6uZwM/DJ
+Uisv3AJfMbZn9F9Pla9oHg2M8jiihfcaynBmq217R02tl4fESdxKQ1Nik4PhP2ZC
+UmEFmQBOZ/uc96vO6GubmzgfliuC8sGr7Po+vPFbIMue7PWUO0RKhzy/s0ax1fsT
+wJ6MlTx5ooxGNH1oOzqK/GIILIDt5hLhaDOSNsMh04DYNn7zl8tVwoiytL6l7UCn
+frOaoHG7DiTMe+BQsxrlM6VahvL96yaNcYqVAgMBAAGjgeYwgeMwHwYDVR0jBBgw
+FoAUs8tUv2qd/J/HMQ6SDKdHa5kAnzEwHQYDVR0OBBYEFNyZy4jEXZpmtXy5hf9u
++nIIofF1MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+eAYDVR0fBHEwbzBtoGugaaRnMGUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0
+IENlcnRpZmljYXRlcyAyMDExMScwJQYDVQQLEx5ObyBpc3N1aW5nRGlzdHJpYnV0
+aW9uUG9pbnQgQ0ExDDAKBgNVBAMTA0NSTDANBgkqhkiG9w0BAQsFAAOCAQEAKeZa
+DkaStqGWn5oALrJNBu6TN3iP1I4SQzEzchWs8DgM4EcHqvbP7erNZIRN7YUWKSWy
+Aqo4AFPWQWpWiW8oLdN0lngVBmSDD5BcEZnyAW7sjWp2m9qbaFowRg7VS0IVJ4FY
+2OOsAPefbsOuQQDiF6TRSbpNbu4VmUMjh+dYB3GXpqu1NMjv/L6u22x0AbRhwX6K
+8+DVBNDVN5/8HtW2uCtBNJepBfD67nvnpTJe8a/z43DKhsAhO1gh+ZDgzJ+7ZV48
+Z9BgV9NLRj1klaAFYKvPNWfErmFv4CH0hmr9OvD76MXebJMEfnsAXdK+92syGZUm
+R5IhOaKuIKb8Nj5Haw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 15 05 6F 6C 5F D9 9A 75 E4 34 10 14 6D 59 81 D2 57 30 BD A4
+ friendlyName: Valid No issuingDistributionPoint Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BA6BE07396142839
+
+jnrtJ2XYc6ifyh6GqoXQYNgizHjemzQf905NGFRl9vRyGLKaUtcVBrjxwniUM4PI
+LWt+clqZ6XJNUZk816nmXp4CYZlNiCOZ8m9RH3w2uGS+BpNbPNZMiAXswxOAmlw3
+8527XorK0Bic2r9AystjMF7iOLr2EWlJHMGgFrhdGJRsxKmmcRXLM9SRvUmzBCOe
+XURrQRRDOS1K6ahWunM06UsoNIaqFNsj8kNGetBkGBIaX0nZklMGRPorxUf7EIlk
+QK1mlCZ3IZya+sZnJJe2tp5F0QJMrJeJDJzBkfnLrHl3cgG6QL96HtetMlIXCRGS
+INieUZ+wcHmaoc7odMCcnhFimi3fWMmWdx5DadkmIOyHpDwf61a9ZSTYtMV7DDpn
+RPiKr2JUfkORyApKJkt7Hl8NdjJ6a+xO/wPSAvFcS4e8+vlEQka3Sdg1jqLL9Ujm
+byYgug8eJLz5kag5tWyDa8mDwjQfqLxt6vqGToXK+fqetC8gYF69Ap5fj06453Bd
+/nWb7IRYbctBwECaRie4EU33sl/A+z+0XeOHZEt6EEEa1NkEyKbl9fEx0dM7Hxjx
+mTdR7cVhDcKa2IFNft0JQL5Tz7WfxzNKK5w0DQKX2hemURH7pqXQuWWxzmMjjBuW
+xLw2LHqXe+9d6xNzfJCWRLOiFQ3vgQGsQIkInWg7LwjlFEhmgip4PPokj9oPJyoY
+jRuy70kFDfJm91OY+EFMByHpcTSClRbn0eGiVRJbXfoFCtJBjz3ylgO4eWnIqTe1
+gAVlVXyyED6kTRk2TNQaWrEfyKcW+EnxtfEv4nsMAxSqalr8ysvnp3aIrVYd+t92
+Z9fi2XE+Liuj6D+5jZJkmiIEOVI/ZwYq9TSti6vxh8BSeV6f8T5pzzQZZiJwK3HF
+I7p6est+U+YygiFHL2mKk8pvJGylCV06YaPCeZQYuTatHXCIRlHSKXLhVnk5OIKQ
+GsK6yX3YgFnKyprz6HwYhaP/U9vzcKieVFduUsEKZjTLTJLPHeOdOOEGguPqoqyC
+Ky7JAYFdP1LAQHzEB9EL5OwM6Bd6KRqcvh638AO+//E4pNh6E6ffzmNH9sbb2Kyc
+rcTHKe0VQgxCBpwtpVUmUEYEm9p35DzbgIeTxcGtD9F8FK3I3YNobpPD+LPTLowp
+DvAJCUN0f9ABDM975WQNLlg3rlDOd6zYPrKoF09SgwF9t51auW5VokFpb3tJ/HZy
+JeR9vmzaaxTEdniUNh5NIViATsOiU6GEB+res0jUp9LY1k3AGWQyXvOVfH0hNu+6
+8xdWMnrI5HL5aJPrdW1KbJc/CA2UJZlKBgvkvNlmaE2mMb+TDpf1yjGdnfa4PbgE
+pGVO7q3UMo0YwRQ7nrnnSKKYR/o+qFD3NaqH09aOIC4DBYWLGkpyQBrAIqqpqxWR
+f63qrqCKEr5x4eSlvi8BlTeE1wEmBNYdb31w3mb6abR25HOtBRgL3jwcY0kgbT7r
+KKlMSazk8EauLfjiN78KQQEOmFtAlaTzXDTyQdlc/x7YtBoRaUxW2pUy5gA3EMG6
+TB0eX5ypHp2bT1Z6oTudUskfdas7lSGjeoOtqHN1D+8faN20Yd/GoQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1.pem
deleted file mode 100644
index d149d03e72..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Mapping 1to2 CA
------BEGIN CERTIFICATE-----
-MIICgTCCAeqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD01hcHBpbmcgMXRv
-MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMF0xCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEyMDAGA1UEAxMpVmFsaWQg
-UG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDEwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBALgTGZf83aaKeqRSCQeN8oi48i9I5mqVX9efN9WkjfAK
-0nLfV0GeAH/Y/LTtj99jOSIb2O1g4ayQ2SHb1v1UzTznfAyhVci9Oo7WBv5b5MMj
-+YezniLhIS7ChaLLIXfseVOQx53crjUb+/hfbyPMF4tkeKwNTVkExpxhq3Yp1MLR
-AgMBAAGjazBpMB8GA1UdIwQYMBaAFDc7iqG6jad0m8Dr1jnLIQyNo1Z9MB0GA1Ud
-DgQWBBR4R7AhWkyFIZrXxZjG6W4kxTE3YjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATACMA0GCSqGSIb3DQEBBQUAA4GBAAqwYJLUYNcvDniG
-4QbRntW//ZZ/jickxsLRWl6odrI5ecwfekAm8+zhuhtPTNJE4DvDEpZQDtzyRxQF
-ajMjlWFIZ0TehZVSSLGCX+DXAMgp2YxiDjIH8KsbiFT723q1y02U1RPVFiU4Oik0
-+3Cc7V4svmKHw4Dw+GWM/WuMHwJK
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Mapping 1to2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICrTCCAhagAwIBAgIBMDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPTWFwcGluZyAx
-dG8yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXwTHRx8gVHWtSe1VX
-oLPFQmGX4Y0U4v535jowfMd9254hmwW4VbZzK7rrXGOAimFxGHKwa7mkPEo80MIW
-8YQC5HZs3jaXLh/xsmV1qlzwceCXooef+wu8W0pgoJ63MmY+ZJWiNK2ygRV/EVFF
-x2ii8ZGDW+SKEX2WIYI7JhmcTQIDAQABo4GzMIGwMB8GA1UdIwQYMBaAFPts1C2B
-nsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBQ3O4qhuo2ndJvA69Y5yyEMjaNWfTAO
-BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB
-/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/
-MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQADgYEAphAVDZECciXjDiCta9HU
-ZubezLaRjcl0IaUmTlvuhUqkfGG2x1KhB6QTq7JGCmBrlxL93qhU+8sGW1k26/3p
-c3hc60bKZ5oBG96iN05oLWWF3udbqBESMO7gn1zX14s97qLtuqQAyuERy2L2uOkk
-n/emInqTFTixe284WjHR3XY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Mapping 1to2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:37:3B:8A:A1:BA:8D:A7:74:9B:C0:EB:D6:39:CB:21:0C:8D:A3:56:7D
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 29:63:8c:57:a4:35:bb:2c:2e:a0:1e:7e:c1:e2:0e:39:2c:83:
- d6:5f:29:3a:03:70:63:aa:1f:42:e8:fd:3f:64:f6:8b:ad:86:
- 27:c3:a6:5d:48:9d:ef:6d:bc:be:7a:24:a9:6d:b0:4e:4d:58:
- 4f:52:c8:bf:dc:70:7c:ea:8d:5e:54:12:db:5d:62:c5:63:06:
- 2e:00:b4:d2:fa:51:6c:da:3f:41:04:36:14:ce:63:b5:46:e6:
- 7d:10:01:db:50:07:69:82:6a:34:45:0b:38:5e:f2:d5:8b:77:
- e4:ea:6a:7f:9a:18:fa:74:ed:b4:5a:ba:68:f2:68:c4:d2:55:
- 17:9e
------BEGIN X509 CRL-----
-MIIBPDCBpgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD01hcHBpbmcgMXRvMiBDQRcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgwFoAUNzuK
-obqNp3SbwOvWOcshDI2jVn0wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-KWOMV6Q1uywuoB5+weIOOSyD1l8pOgNwY6ofQuj9P2T2i62GJ8OmXUid7228vnok
-qW2wTk1YT1LIv9xwfOqNXlQS211ixWMGLgC00vpRbNo/QQQ2FM5jtUbmfRAB21AH
-aYJqNEULOF7y1Yt35Opqf5oY+nTttFq6aPJoxNJVF54=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11.pem
deleted file mode 100644
index fb6f7653a8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11.pem
+++ /dev/null
@@ -1,172 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test11
-issuer=/C=US/O=Test Certificates/CN=Good subCA PanyPolicy Mapping 1to2
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTIkdvb2Qgc3ViQ0Eg
-UGFueVBvbGljeSBNYXBwaW5nIDF0bzIwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBeMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxMzAxBgNVBAMTKlZhbGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmljYXRl
-IFRlc3QxMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqoi/6nU3Hb2K96/H
-+9K+tll1HEWk3nCTUyNxX51p/j2CU0KannQFFBA/eohAi2m9L5Yo8awWKb1S3Bya
-vEGNPsdIVYLlSJG9P1epb+In0KNB8zN+UZv9Zrahi/B/3SFS1qUgTV4yLI0/V2n1
-r3YmjyOxr4h+Zqs6X90lEEh4mmsCAwEAAaNrMGkwHwYDVR0jBBgwFoAUkdfhtaSW
-CJHxonEvZtkne0qCk5owHQYDVR0OBBYEFD+Y+xstb3NLUv3ikgoUQ21QbUC7MA4G
-A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAIwDQYJKoZIhvcN
-AQEFBQADgYEAI17tZ0uZ0tu3HpgcRcjJR6m4HmsRao6CJ+ew7HfvWfVRE3x86Deq
-VFDnp9mCv8VKw0ChV4tPFdkw+ceSsgThjSHvxZbghFC6YnG5Ymj9X/zjl4NCujCQ
-Cw37Mi1UZYryKZ7+qODmExTxKry4nIvSUvYei8wDynu54uzjbKv7Jc8=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good subCA PanyPolicy Mapping 1to2
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICtTCCAh6gAwIBAgIBFjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTIkdvb2Qgc3ViQ0EgUGFu
-eVBvbGljeSBNYXBwaW5nIDF0bzIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-ANGY6UqVJ9oB3KneANaPiYS3vFaEAo7CVhPn358boVTv2/wQv8iwT9MvDcASa4Fi
-5kaob+B5k7T8qjNOtxaZJb69UDUDsAYww6r/NK5pkS1KNf7CJZW6/RQC06GsivKO
-kQoudXfGEjAMhmHNuEXS4biTlRuVUXJqLPq2yLwAJPZ1AgMBAAGjga0wgaowHwYD
-VR0jBBgwFoAUty6mgsvCyLyoeydE1zUz35oVlMcwHQYDVR0OBBYEFJHX4bWklgiR
-8aJxL2bZJ3tKgpOaMA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUdIAAw
-JgYDVR0hAQH/BBwwGjAYBgpghkgBZQMCATABBgpghkgBZQMCATACMA8GA1UdEwEB
-/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUFAAOBgQBNuXYJvgOn
-wez9J/K4ZZhWpMPo/7Qso2S6BAoJh7QdTymJKxD6nDnPwetIpbQkbEtq+V30ZA+o
-6v+0cntT/I7cm9JKOXMOKn35BODzS8u5UJTDwWc/l5SA0scCSRfTT9LJambCyz+m
-C0/k+v5zw5VpFozVY4FoV4/KnwIhJPuDwg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good subCA PanyPolicy Mapping 1to2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:91:D7:E1:B5:A4:96:08:91:F1:A2:71:2F:66:D9:27:7B:4A:82:93:9A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 97:e7:b7:e3:46:cf:59:49:72:d2:0e:de:0e:f6:c3:1a:ca:34:
- 59:50:f1:2d:fb:11:31:f7:bb:b2:f7:dd:0e:fb:bd:6b:7a:7f:
- e7:dd:02:be:6c:7b:36:1c:49:50:38:d9:85:67:97:a5:0f:84:
- 49:de:8a:d5:0b:d0:36:fc:6c:4a:82:cb:83:73:ed:1e:af:31:
- dc:0f:6f:eb:69:18:67:b7:fb:1e:a8:1d:a5:36:84:dd:05:72:
- 52:f1:51:e1:93:6a:ff:2f:92:6b:7a:c1:67:90:0b:7f:66:0e:
- f1:83:22:d9:52:5e:f7:58:5d:5c:7a:1b:69:84:91:da:b1:18:
- 11:c2
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTIkdvb2Qgc3ViQ0EgUGFueVBv
-bGljeSBNYXBwaW5nIDF0bzIXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFJHX4bWklgiR8aJxL2bZJ3tKgpOaMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAJfnt+NGz1lJctIO3g72wxrKNFlQ8S37ETH3u7L3
-3Q77vWt6f+fdAr5sezYcSVA42YVnl6UPhEneitUL0Db8bEqCy4Nz7R6vMdwPb+tp
-GGe3+x6oHaU2hN0FclLxUeGTav8vkmt6wWeQC39mDvGDItlSXvdYXVx6G2mEkdqx
-GBHC
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11EE.pem
new file mode 100644
index 0000000000..1dfa4e8164
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest11EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: BF 28 4B 8C CE 26 A8 81 42 DA 3B E4 E0 16 5B 68 08 A3 F0 9F
+ friendlyName: Valid Policy Mapping Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test11
+issuer=/C=US/O=Test Certificates 2011/CN=Good subCA PanyPolicy Mapping 1to2
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMiR29vZCBz
+dWJDQSBQYW55UG9saWN5IE1hcHBpbmcgMXRvMjAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGMxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTMwMQYDVQQDEypWYWxpZCBQb2xpY3kgTWFwcGluZyBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0MTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQC+1d+dhBTDr0hkQGmjN35m1EjSSp6klcio007bUt1XEDFrmlcLqUaXwh7h2Llm
+uQls+Tg+dLpiJNkS+rFqhiMY/8juZ0cJ8kTzzD3tF2Nn6Cjt9643MAFgpJhS2m01
+/6jf4BSbLIy4bZCpes+3X63YPn7HkypNh/praDdnsBl6FVdMVFgSVF/IugL4OQHd
+sDGFTlxLbslcKPdGGKnMWRV1M7Socp1saxeNISc7O0PxN3HZcxthxcmQIw6yYCRQ
+sGM2nbm3kqvjVDKP4A0wxirsP44bIuO+XplnSIjflFDDYmwHdwHRQj3wY9bBBmp4
+cjCNkcCanyNupu7ervRfxQT3AgMBAAGjazBpMB8GA1UdIwQYMBaAFFtzeZnjrgbT
+iqYzThR45KAdseTJMB0GA1UdDgQWBBQ3/goQT3nXcdLj9bsgs0wszyJ9qjAOBgNV
+HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMA0GCSqGSIb3DQEB
+CwUAA4IBAQCqSXXia8C9CKK76G4gSKmXrWLRVJ/uE6oXYEKiGRWKny3sKj1sadSF
+M4k2OfXuYCYUUvs+kZAulOeUZ02oh6WOEY9o4YH508JI5jyFeCzObQYqL4G84NyQ
+Cz96Tedck64RUvcuPw6BqyrpMqVQslCrJGY/O+2jZ5kWi3pRd72r+z/6e7OvS/N8
+F5VRU797A3vTwbbM1tjBlz0nVyezE9rdo81xP68jeKRnveQXsn1RGUSMLnT6vJbT
+KGU80YD/l6dJgBS5qhgGYYk4ZxJuHBkoBfeHuM0NcwZHfqYowccNub7q8x1fiNoj
+lo2TLCGcjka1s6RCQnucPVgfxwq1D8lC
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: BF 28 4B 8C CE 26 A8 81 42 DA 3B E4 E0 16 5B 68 08 A3 F0 9F
+ friendlyName: Valid Policy Mapping Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F840D6C78D9E33DF
+
+lqRQHkeQ/Mysa/UqRSP6CZzr6zT4MUnBJFqXXcnadQaqJhTIN8Uf8pouaLIpskdW
+ddbPI6Tif+OjWPyaMuZSjKIz58XDqPXkIlAokYlZrl/KgdVMUns0H7tZt/ywCql/
+UnNEB5N4K3bDBTKE55qEubh6iwA2EGWpo8VzwZea5kfBBsKFJVtZgAhFuYqnJyO6
+lUnNGhdFLGgmpNed11cvQoA0UKGfQvBlFwsRZyDRTq8iBcZ5fMhp3uuFybK9IluG
+RaZsMai7Sm4hif1PvsTGor3JKFmawWckiOb4sGluvWVRDkEn/2C2LY1uETJZd2Cw
+nGiuhsDf5Feu0nYw+E3p5UIs1QfFYql/jE+1+xbGzDaj2V805l4e7iQmVgjbVYBy
+tzweGtTswnMGoPkppqdRBUH2p2nbtMPcnQyRlmvD61OUWPH7WAtZwg44H+KZ3zQ2
+WlB4ewMXGcvlVN6xhoRq+bQlRmHHlWR1Kx7Uyn6Fkuzx7RnTb9waEgoVXNwd1fWc
+uh/Z9NKb7blyKDsZyf0zMkrJzXSYLTWYD9JnMpi8Z7Z5nd2fd8oRTHSpeudauUE0
+r28vrjTMEFZg8kDHX0pnA7HenZXSBhL93VOR88d6y6e52uG7fb05bhk+xD0HZcg6
++5kEtq7kfAaP6OO10EGwOQJXIY4p1xantw9yDTR6hL5JkP/byG25a7i22onEW5Si
+51Kv6dJuIHG5x1dVxpA/DsDpD1raQknyI0ZS/R1K5GAtjJ9zukagARKBrlaQ4oTp
+zpg7EKQhN8NAE0O8JDlx0WpQ58UQznPrOTl+RLjA4QeI1xRektZygH0sf44mMu1T
+M87ZNfydc3/mjvopj8Ki+AO1Z/8XaxXFCdGwSC7UKHK4+3tAUrolsuYq1mE3TVHv
+GIEuSnojFg9cy5BX5bjdNH5QawWBot/5tbYzrD+OO09uhVPWRaHTW8N4ZW7G4OVp
+eROdhI4SlE2Zgg0vBRKZBL6LTAa46ozF8IM/2kXdXkFtQ4DCd8QAA3HwfCGW3G36
+TxvaWknmvqryn9SwXqv3tAYK///bhNh+5ZqXNkethdWIcGkHRC+DEjxe4XDN1zoy
+YIzkJHq2p1+vD4Iga2Age3IVCKrHBHCLLLk9UbMv+pUas5tK4yIyAG/ND00lUgoD
+ZMDHm3Z+9swm589tg0u+JpwCiCLSg1NIAE0Uj5AnGNil4fyzC8DhjeXJtsZfEMTu
+F6TH5qnPV005k2xTACe3uSavohAY40RwCKsG+RklAfh32muUWJy8tFRHKGkop4Np
+n1ezz15Eq0DsxQo5bLUNvx+1t/dCHxffPtb9xcXM42wEwNP/EOLwmBr8VUSOBNn+
+716CO3jvXQHc56RV+NSEz26kH9k0c9B6vrzeT5RDsrP+TtLPH1hxpyiRz/DtO7X5
+XwDIXZ3Kh3vti7/pwJVGkDJ5VwvF46HsbnClND/UDgnG514++33sBWP95xXEKpQH
+KnvFxgm/10u1AywBl1yq3hE7bulSrcaAcO0Po9EkQXxT7riCAn4eUPEO/x55Jrpn
+rLWP59Ex4GTo56fMXhEctw8DkYg7NDwrTkM42wmD1CqWEbG29x4wTq17mTvyGepy
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12.pem
deleted file mode 100644
index 2f35a62def..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICvzCCAiigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UEAxMTUDEyIE1hcHBp
-bmcgMXRvMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmTEwLH6u6mb6
-kvz4ulbBVFC2Ea6WdEv2uH/vNi23mER2Nl+xAbeopiy3OLEiXavvD3uvVjX0bSOH
-BGk2j/ern/Urw6djfKt5V4O3NMYi6Grvfm346kdutjJuBcNlhLOE8mLXUguspocr
-AoAEjrQtuS4Bkb9A5wj3OYy4jr2JhtMCAwEAAaOBwTCBvjAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUreIKE61SbSWszamYogoEaK1y
-rrIwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUDAgEwATAMBgpg
-hkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEw
-AzAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQAD
-gYEAEelnHhW6SAs3Zj4a5YMVTKDe7vCThen9bA1Awt3yFincViRt5/s2ZyzTN5fr
-Xi+2m42Gm+Anb3D7rpV9IJ/PahHq4yrKSrcAzhT3IcHbuHFNwiw8Z3T+31hhjJUx
-3atYpYOZZPYwuT0inFHJWRfBNA8NGBtqYlxI1C+/ucdy7ik=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test12
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
------BEGIN CERTIFICATE-----
-MIIEKDCCA5GgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE1AxMiBNYXBwaW5n
-IDF0bzMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBeMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMzAxBgNVBAMTKlZh
-bGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmljYXRlIFRlc3QxMjCBnzANBgkq
-hkiG9w0BAQEFAAOBjQAwgYkCgYEAiDGZx3j4WZj3UIYQBpID5IJr0ES7lhC5FAa2
-ErfScZEz3LrPW5r859dobtF5TBB1IGznyZmZBhwl2vmDMTOAJV827Mwn19ELd+Vx
-wAtFUtNszWAw1CQdx+kH+WJka6JxXPNQGWzgn/Q+Cbrq5BStqcZTHtF1NhVX4c+/
-9RdkUesCAwEAAaOCAgswggIHMB8GA1UdIwQYMBaAFK3iChOtUm0lrM2pmKIKBGit
-cq6yMB0GA1UdDgQWBBTkwpjC2Np+iZ8a8Y6b6DTyrLrvrzAOBgNVHQ8BAf8EBAMC
-BPAwggGzBgNVHSAEggGqMIIBpjCB2AYKYIZIAWUDAgEwAzCByTCBxgYIKwYBBQUH
-AgIwgbkagbZxNzogIFRoaXMgaXMgdGhlIHVzZXIgbm90aWNlIGZyb20gcXVhbGlm
-aWVyIDcgYXNzb2NpYXRlZCB3aXRoIE5JU1QtdGVzdC1wb2xpY3ktMy4gIFRoaXMg
-dXNlciBub3RpY2Ugc2hvdWxkIGJlIGRpc3BsYXllZCB3aGVuICBOSVNULXRlc3Qt
-cG9saWN5LTEgaXMgaW4gdGhlIHVzZXItY29uc3RyYWluZWQtcG9saWN5LXNldDCB
-yAYEVR0gADCBvzCBvAYIKwYBBQUHAgIwga8agaxxODogIFRoaXMgaXMgdGhlIHVz
-ZXIgbm90aWNlIGZyb20gcXVhbGlmaWVyIDggYXNzb2NpYXRlZCB3aXRoIGFueVBv
-bGljeS4gIFRoaXMgdXNlciBub3RpY2Ugc2hvdWxkIGJlIGRpc3BsYXllZCB3aGVu
-IE5JU1QtdGVzdC1wb2xpY3ktMiBpcyBpbiB0aGUgdXNlci1jb25zdHJhaW5lZC1w
-b2xpY3ktc2V0MA0GCSqGSIb3DQEBBQUAA4GBACzi00c5I7zzf41Ca5Ln8KYqgDts
-W6Jh0j2NzYtm2W1us5l1tx6UsE5uygoREiVScCXanYaKtiwW5QDqMZb/Uu+izmIW
-QRefqnHnyJqXxKQx8UwS+yNaIjT+ph7SJNF/DQrNwYWtNBD1vKhcNe8MDKWjAr9J
-P7k+rI8qg8ug3og+
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:E2:0A:13:AD:52:6D:25:AC:CD:A9:98:A2:0A:04:68:AD:72:AE:B2
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 94:34:62:ba:34:51:b4:ad:dd:01:40:fe:3d:eb:bc:6c:7c:89:
- cb:f0:7e:e5:38:03:50:93:5b:68:ba:d1:ca:14:39:ec:a8:9c:
- 37:24:c3:0f:01:eb:14:67:8c:07:fc:37:1f:bb:45:b9:4f:5f:
- 56:ad:f3:85:03:23:a8:bd:93:1c:ca:01:e8:b5:1c:c8:60:18:
- 13:95:bf:5a:11:11:b2:3c:3c:27:69:bf:97:08:c0:b7:4a:7a:
- 39:5e:03:2c:67:5a:11:a0:4f:6f:8d:70:4e:e2:b5:31:73:2a:
- bf:5b:15:af:5b:4e:14:e0:73:5b:f1:2d:cd:bc:75:44:42:d4:
- da:3b
------BEGIN X509 CRL-----
-MIIBQDCBqgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE1AxMiBNYXBwaW5nIDF0bzMg
-Q0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaA
-FK3iChOtUm0lrM2pmKIKBGitcq6yMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUA
-A4GBAJQ0Yro0UbSt3QFA/j3rvGx8icvwfuU4A1CTW2i60coUOeyonDckww8B6xRn
-jAf8Nx+7RblPX1at84UDI6i9kxzKAei1HMhgGBOVv1oREbI8PCdpv5cIwLdKejle
-AyxnWhGgT2+NcE7itTFzKr9bFa9bThTgc1vxLc28dURC1No7
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12EE.pem
new file mode 100644
index 0000000000..495ab4e8e8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest12EE.pem
@@ -0,0 +1,69 @@
+Bag Attributes
+ localKeyID: 49 2F EB 88 FF FF A3 77 C3 69 8C 7E 41 1E 11 B1 62 70 EB 33
+ friendlyName: Valid Policy Mapping Test12 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test12
+issuer=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 CA
+-----BEGIN CERTIFICATE-----
+MIIFNzCCBB+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTUDEyIE1h
+cHBpbmcgMXRvMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGMx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTMw
+MQYDVQQDEypWYWxpZCBQb2xpY3kgTWFwcGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0
+MTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsR+um2sZ2YQ1PJDMx
+PRcsr0/O2t34DJXXvPuOJwddAxPoy89/ARwwYTkA9PXt9KgKpui/y4zFKMEbA+8H
+bZLQDzwxIxLtL8sxEarXLfvaCnmRDlw/gW0onAhdfcfxfrmlX2c2IaPulEzU14xE
+DgnBF+c2XgmRDRZcBTVrrdcHf7/pvnYU+De32CTzBJLox3TAALRveoFaHEBI79/9
+BELaRR+ar6oiKByFa3WMM8vszIr60pC1S22V6kq9Mz1EEpZo6RyfqzzbInXQYG0f
+6PS0sz5lDPHxBkNJh1LmIubJ5T4/Wz+eDaHkUYVtj4o8b5Jvab2kbOiy89E5slOf
+xsGxAgMBAAGjggILMIICBzAfBgNVHSMEGDAWgBT89I1hMzKAfH01h95fUvtp8R3B
+EjAdBgNVHQ4EFgQUH9UDtvGnSGlr19U5qGCO40QW4Q8wDgYDVR0PAQH/BAQDAgTw
+MIIBswYDVR0gBIIBqjCCAaYwgdgGCmCGSAFlAwIBMAMwgckwgcYGCCsGAQUFBwIC
+MIG5GoG2cTc6ICBUaGlzIGlzIHRoZSB1c2VyIG5vdGljZSBmcm9tIHF1YWxpZmll
+ciA3IGFzc29jaWF0ZWQgd2l0aCBOSVNULXRlc3QtcG9saWN5LTMuICBUaGlzIHVz
+ZXIgbm90aWNlIHNob3VsZCBiZSBkaXNwbGF5ZWQgd2hlbiAgTklTVC10ZXN0LXBv
+bGljeS0xIGlzIGluIHRoZSB1c2VyLWNvbnN0cmFpbmVkLXBvbGljeS1zZXQwgcgG
+BFUdIAAwgb8wgbwGCCsGAQUFBwICMIGvGoGscTg6ICBUaGlzIGlzIHRoZSB1c2Vy
+IG5vdGljZSBmcm9tIHF1YWxpZmllciA4IGFzc29jaWF0ZWQgd2l0aCBhbnlQb2xp
+Y3kuICBUaGlzIHVzZXIgbm90aWNlIHNob3VsZCBiZSBkaXNwbGF5ZWQgd2hlbiBO
+SVNULXRlc3QtcG9saWN5LTIgaXMgaW4gdGhlIHVzZXItY29uc3RyYWluZWQtcG9s
+aWN5LXNldDANBgkqhkiG9w0BAQsFAAOCAQEAfgUmAvc8LV3+9l0DE8PptL9L43/o
+bdmYSWhMK8uW7yPnOAyuntZKIT/ssu9oSHFL9dBP5HAnJWslHJqimNZAGanekms0
+uXkiqBOIEP6aMcnRKd734CgiZwnpcFzjPcVFySmBmu9/MtPOGXd4t6n8RrOewe9m
+0HEi0c5/FzdmXz4KtIrTxRSeB1MGtle5kz9ks4Jv7YVyqg62vagxSxYIYIQahYTG
+e3ilDUmdh9ws0RmJgp7PTQ/gV5qUwfWfv/tMWhNUyA/9bdCql87yhNTxokTdkmiZ
+N4ZkwYg0No52Fiue+ymxwvF5R6P36fDEP0phyjh6qv6NYxsdXwd97AfS9g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 49 2F EB 88 FF FF A3 77 C3 69 8C 7E 41 1E 11 B1 62 70 EB 33
+ friendlyName: Valid Policy Mapping Test12 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B9E7A9E29418DE97
+
+pngogO5dyMFXmvYywn7YrUkWww8K5kDBvb5Qwg1Nzbqiw9uwhvLFzCnN5g4OzOtG
+0T1A4TvSLdcEiVfnF5ZMxbzG68dVZ+xFu5Gy77CenCwYP8WXsqkLvj0YSqlHvg0L
+Rwv32AfltHb+P/ZpiYktGDECxwW1EeGkmm4ZaJL59VHHxTY+aoSNbc8X0lGTsQ0n
+qVFJ4+T/al8f/gVy0wKek/YxykCW3BAigFjzTvFm4LIEZKpPZTJ2sfMJmS217gr/
+9voeF1CgxM/ZD7ZLqYLvADNgDfE9qY89y5lGd4QNUxi/AwIuat0smoS4O3+XXVk6
+XmBQAir/TMh2QnZh5njazYlmKJgQYVw+ePtLs32Sith0lGWBK2zltVR2JcfHaUmM
+j8sXdlSM3M80ttIIQLImJS46Pi9ncrqoRFMx44EIvR/Acd+931LvaCzXpxDO/NTc
+aO7M4t6o5Ru69rLOigRkzMMQNFRr4zk8cmkoFiQYBtYshB3SOMGkK8jUpuAIRrUc
+8q1hpc8jWFCFim90Q2cLA7O0jROIZcZ1tubXc+uEP38pynbveWgxU0rf/lm2p7j9
+ZL3xp7zrjuGddS13ayR6vTmC67dBqF4ErJYK/3sUGTUwMt4WTGqXrlbSbnoZtee2
+OfqMUtc7GKnQjDFCikP6V9b6lGLsbjB+cuGxNdMliE3pxDQ7k4pLMiQONkBCHOVp
+z2BMZNuiH0Ow7gbQKOvmzmnFtKLCvJ3PSL1EszbG9pIcL7mmGshae0Jk55xdfZrU
+yBuMrAKipKmsKJUEh9yRAD3ikx4XP6X7RSw0o/61EOQs9VLZgmd0DKAdWEvQNlWU
+AYiehEodiNOxxcoGHzdBj20U/J7EP5cxa0KkNGKwQsDhbAY5kBPpTAjtqAfs5yg0
+p/l39O3c7ueXczy9LgoQ0nzNY/pXtF8jvPhQ0wlzkGOecbZSTVAbmUAj0VT62Ntx
+oaUHZ0o4ybpiCV4ezi9zPv3jkKBWYeKYpCAWJmN4uA59BNLnoxaIYonoX7mmg2rO
+GFizGXIfGQfPnm7ZVCLbXnjcgRsrUKhStYWR1+/C+8Ailo9QKz2BPXYk33GgPVXj
+lxqvUGdWRiBGDRIVbBRhbOxFTHltU9JWhQ/i/OquOYs76s7oj8PWFH9UNtUymVyy
+OyBqUse9+HsveOc03EHbWJYOTpgTb4eggQJ7nY7nGl4m/Lr3e+hZWtC2J1AgV2Jp
+VVgNiq+OLek7V3J/xzmqbUDwLgNZLVUD0bD23AbinegemBn+UxyKd51EoXziqh3z
+a6/n9V1NS34O1WW4t9kxRwKhgToWD2D8wFmbnLjFQhBfRm8jSX0VxW/x5Nb1Zmqi
+9Ekjobs2AdF4EpSuz7OrJS8kj8vuSAicAPVfjGjIfUoUvN+qrS+b+S5WFggHoh3o
+8PeqZkVbRFlPqpJhTDjxf3eeuFAWbuWzv5YTa6f4JWbq6zbQBkSCfvxZq7cwGETX
+OOG1InOo7RhTIT43Ir2i4uLyUzx0Ah7C5SMDtzCpnDHEtxJRbxXMDijHJ2/m7M0w
+oC81X+tLMxpvh4UQ9fJubiqR3ON9UiAB88c5CEhr8iDKr7KYWqCP5qQ+OPOh9c3w
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13.pem
deleted file mode 100644
index 2399b4163c..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13.pem
+++ /dev/null
@@ -1,117 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test13
-issuer=/C=US/O=Test Certificates/CN=P1anyPolicy Mapping 1to2 CA
------BEGIN CERTIFICATE-----
-MIICjjCCAfegAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1AxYW55UG9saWN5
-IE1hcHBpbmcgMXRvMiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MF4xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEzMDEG
-A1UEAxMqVmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDEz
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCr5cG4yqBgXjIPkt7dHP/MFNci
-pUHmbTfWoxKfaC+QY/7vElma6sMegYccM49fDN8CJSa7iF0vwS05cS1euHk2PfLF
-nJJamoTpf2iKxjqy6wemAmTH1cnEAtuhyArNadJXjvFmwV8bxyyaFW4GGnMj+yFe
-IJoTD65IuQMOLLg+xwIDAQABo2swaTAfBgNVHSMEGDAWgBQtN9I/nlnZ5r5Xovdr
-DxCCpq0D7jAdBgNVHQ4EFgQU3ZrqolFiawE0EWsHD7qUUa6V4pkwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQUFAAOB
-gQDgNwimYbq6g5crdMRHe8S69POQl1I4Qg6ZD511fwO2OUU/rmIbvqW5faGKHPMq
-Ubun6DrzamYGfx8HCa/vn46jaRVC2tTqXgiy6aWGMHv4MJl1bxS/yR8hqdTEWjG5
-GFkA7UWgU8A3MmmIUaBCs2QK5ZqTmsYuqX2inlGtBcvTrQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P1anyPolicy Mapping 1to2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIEHjCCA4egAwIBAgIBNjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbUDFhbnlQb2xp
-Y3kgTWFwcGluZyAxdG8yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDs
-qiRQp8ZU1kWOS/tvtPAlHT9dGf17useanNh/sRHafDBRsOVVlS+kMA8Ti/8uecSP
-PEMznqfzcf7wvC64FNOt2P3rD/W3oZ7MShTLQF6C5mqsh8A4T+DDgdhNG5xtOAfg
-buRxp+A4KybQ7YMzRHnb5Z6UEKCAOv1NmaQpQU6lFQIDAQABo4ICFzCCAhMwHwYD
-VR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFC030j+eWdnm
-vlei92sPEIKmrQPuMA4GA1UdDwEB/wQEAwIBBjCCAXgGA1UdIASCAW8wggFrMIG5
-BgpghkgBZQMCATABMIGqMIGnBggrBgEFBQcCAjCBmhqBl3E5OiAgVGhpcyBpcyB0
-aGUgdXNlciBub3RpY2UgZnJvbSBxdWFsaWZpZXIgOSBhc3NvY2lhdGVkIHdpdGgg
-TklTVC10ZXN0LXBvbGljeS0xLiAgVGhpcyB1c2VyIG5vdGljZSBzaG91bGQgYmUg
-ZGlzcGxheWVkIGZvciBWYWxpZCBQb2xpY3kgTWFwcGluZyBUZXN0MTMwgawGBFUd
-IAAwgaMwgaAGCCsGAQUFBwICMIGTGoGQcTEwOiAgVGhpcyBpcyB0aGUgdXNlciBu
-b3RpY2UgZnJvbSBxdWFsaWZpZXIgMTAgYXNzb2NpYXRlZCB3aXRoIGFueVBvbGlj
-eS4gIFRoaXMgdXNlciBub3RpY2Ugc2hvdWxkIGJlIGRpc3BsYXllZCBmb3IgVmFs
-aWQgUG9saWN5IE1hcHBpbmcgVGVzdDE0MCYGA1UdIQEB/wQcMBowGAYKYIZIAWUD
-AgEwAQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAw
-DQYJKoZIhvcNAQEFBQADgYEAqZ6Cif011+oMzp6bcMsfzt9sTBgpT4l35AbTC5sm
-zp3ur8X5X2G604yKkSXe1cf0F+fZSE6zjwizb1YG0owt1eGWSxCdAlkIFRang7OG
-Z93bEKBx3ysDYCKvemx0f3shGqJVVzMBo6JP6JX7Jnn385UdwdKO2dWzVhHXsP+P
-9sY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P1anyPolicy Mapping 1to2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:2D:37:D2:3F:9E:59:D9:E6:BE:57:A2:F7:6B:0F:10:82:A6:AD:03:EE
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:52:84:5c:c6:67:e1:f5:70:94:c5:af:b8:de:1f:38:dc:b0:
- 65:8a:69:80:b5:9a:f9:2f:6c:13:8e:83:5a:5b:33:01:1c:d2:
- a9:c6:c7:09:92:cd:17:9f:bc:f4:30:d8:bf:8e:05:c0:98:d4:
- dc:be:b5:31:80:76:30:f8:35:48:45:a5:25:2a:92:df:1d:ae:
- 4c:88:5e:34:d5:ea:39:8c:f2:e4:c7:e4:c1:35:45:3b:6f:6f:
- f3:81:e3:2f:43:ad:ae:e3:98:3a:7e:0e:48:51:cc:a8:15:38:
- ce:38:31:9c:36:5e:a0:eb:f5:16:e9:43:a9:5f:77:a4:bc:44:
- c4:0b
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1AxYW55UG9saWN5IE1hcHBp
-bmcgMXRvMiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAULTfSP55Z2ea+V6L3aw8QgqatA+4wCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAVlKEXMZn4fVwlMWvuN4fONywZYppgLWa+S9sE46DWlszARzS
-qcbHCZLNF5+89DDYv44FwJjU3L61MYB2MPg1SEWlJSqS3x2uTIheNNXqOYzy5Mfk
-wTVFO29v84HjL0OtruOYOn4OSFHMqBU4zjgxnDZeoOv1FulDqV93pLxExAs=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13EE.pem
new file mode 100644
index 0000000000..facfad2ce6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest13EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 01 42 F6 11 D7 E6 2A 0E C5 9E 1E 64 E1 9A 3A A8 E9 5E 83 8E
+ friendlyName: Valid Policy Mapping Test13 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test13
+issuer=/C=US/O=Test Certificates 2011/CN=P1anyPolicy Mapping 1to2 CA
+-----BEGIN CERTIFICATE-----
+MIIDnTCCAoWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUDFhbnlQ
+b2xpY3kgTWFwcGluZyAxdG8yIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowYzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExMzAxBgNVBAMTKlZhbGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmlj
+YXRlIFRlc3QxMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnps/1m
+3VaOuWJUszOp+AmWnTRIwJe3yRXQ/ysvNkLsbmpqhnmrpxIMjmcttViCxNj6BQ8y
+AjVAtnVSADQBiPP0ETES+3NEW8/VghqYzGJJ9H1Oxanks1Ef8mI58uQm9EWkqTJ/
+B+UjxgqCKkHhmkikpVT/SupdPALhgRw4cta4oouQ51jqoW4rDJrRhMdlPJ5Vaiu9
+m1N9vPK3FIKHMQGV3t1x8u/8T4xsed6ZynU+05zTwnzNl9mu3mX60lfRkLeSUeMa
+p31xBaivLBPyEB04dzzGQaXdhBN5PaJfw98+xLjtK18L26+jqSf2BPfUVDitbCQx
+HyLvSWWN6qntVaUCAwEAAaNrMGkwHwYDVR0jBBgwFoAUHwIoKDKOSoT4uItB8V17
+6CVSa4YwHQYDVR0OBBYEFDxAEkPP6QrslaJxGaIDcd2mbH1QMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAIwDQYJKoZIhvcNAQELBQADggEB
+AErtqbfufFlEyw6M9vWlfiVDCONgimPxftB15iPZe0zL/kVsUk6URd1rcQItVKBa
+ORFqxKp+VRg3kYdzgMUeRJB242zed+QryQlZIoaLmp9JGN/rz4P1gBzIYNmTy/pw
+kKqzkUQbzIWlf/0A1wCpI9LAxgT1TRJ5gLF8r1DrAUzB8GwH/vTzNkvPi2VFng+4
+hXds41goc3F49m7lnsKD9bMVEKDwDugcHx3VfeTT4lICGLvILNLkp5noMxSHtnV6
+N/mZvnAHHf3uE/PkXDibuJkm3LscaG85A0fQtiB1UYzm/IFVFW4K0NTHeS0UzyzZ
+UHjkzxIW2sNziGzljpb8+As=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 01 42 F6 11 D7 E6 2A 0E C5 9E 1E 64 E1 9A 3A A8 E9 5E 83 8E
+ friendlyName: Valid Policy Mapping Test13 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,20959387204DF4AD
+
+DLyCmJEN31AHHkhdysWiXGs0yEAb6X9GIaKERbejhYuwjtVDQ4VxL2fE1h3CQ5Sf
+bZ4aGC2MQvCCqoWqyd4R+mVAnKHtNet7f4CSHMqKP+uSZ7xNYsd22KS51I1+n9mS
+2mPVFO3f6e9X/SW2IQkBrmklSYgSeiB+rT5Xcd+vKHOdegPkU/tXw6pz9ljDBeXn
+NauHimvP6431M45vP9AVePUnahDdirlJ0algSEEa1PbyrZRh12GjaHNwLkNBAYM1
+UUBHsJOX1v5fK3dQsZK3ajVKq+YiYdOnNsUOclO8B3cgecrNcRwOJw8sWrmsDmgI
+VmdxWsScQLlN7jXivJaBgp9ZLoPq7EYXjcm3kU2djT74UN+8yv06XaYkUj13tZXZ
+POj0DmlDjPpzQmZfuPbiGxzVPEynAKQiqsDeKLdRfWXLuVZaH8DBjkCPXsGbZVK0
+lvd3iVDrjAIHjWTgudbRjOoKuGiE99TaislJfPGBcKr6VlT+JsepYFst0FqhSA89
+gbbRB95BLRyLKdWuL7NdunipUPKvR6jj8LSOKcmQx5NwSwIkITBlhdnmwq+luLuN
+ySTfTp8u24Wb+mh6tU/x2tzRM3fFCYszN2yuUA65bWrj6KDr565419cKrfb6pmWt
+sCqHNNZbhOxD2X92tfNfrlq6i638Zbb3iLGP2MZ0qxvw6pAIh6SpC2GkqKdl6yM3
+z2V9yy1grmQbGdg7EpXDbQgaAMvHcwdCwVq4U4LYAG9tuUfDY826xK5RDuUqmPAp
+GMGriZSclEFOSSBgIZFX8n6NBzn1FiHGazyjXNG8X02VxPoAsiwS6lNpcGwciiwY
+2V/8Prc/1Zd7Pg2fz66DdIfPRbVLbMt8tpgsEKgx4isgpiF1oD2MHSLXRRt9ILFw
+gBTwI980UWxVMzmuwtsP6p+sVYSywX7RwDOiHr9HlArFM/SkDlv59fRgmHb/uuPp
+tFeB7RKDsIkJPKP22hAxccLAJiyhb9EjgztV1t3fKtbRol0YCe+zYH7drqbeI5vD
+xkp5M36b2FcZV0fxSFNmLJBo5Xgmoviqozs3sXbox86qg1EHcGtTs6J6J6SFu2sw
+PKAkGNLRC+ZdlZ/AWnZA+cGNgc/H3AZ9u11uXhqLx6/d6GSX6t7VIbq+MRnqYb7j
+6dy+iljT3HI2M6yi6DUU9IovVISVPLq3KGJvwMtv5VyO9EuB3fjmf6HpR5oiIl0G
+6T8R/SB5NKYRZ/bOu7ZUcGkgeMRdLlRk4o/V6xXL6ODFezl7rsgY9F/P7mItXSz2
+b0zTOLSQ62fQJIdmfTxFweh+xBX14o23buUGrp/gRVEEqXpmWMGmjx9tZ3Hpf9yu
+v+l0qA1pGCyq+8MM4Kkpn/sa+gQ2yo9IrDZEseejMTSQ9AGDY9cxWMjaeM6N89n8
+a/FNJIpiNAnqeIABdDfiyzbi9w6pp+8GNxYElF0almR3CfCbg6G3KzkjfkpRy3KD
+E2O5r6r6c7tzVwzCG1T9Q9smO6I+3EwacCAGda5hBPqYK7hv3ng5C+h1PvqNjfha
+8nbEkyRxVI8MqCubPc//0ck/8jRC69flpVaraxrc+72imo9eYIM05AhQEZDTTvj1
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14.pem
deleted file mode 100644
index 10b7912099..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14.pem
+++ /dev/null
@@ -1,117 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test14
-issuer=/C=US/O=Test Certificates/CN=P1anyPolicy Mapping 1to2 CA
------BEGIN CERTIFICATE-----
-MIICjjCCAfegAwIBAgIBAjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1AxYW55UG9saWN5
-IE1hcHBpbmcgMXRvMiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MF4xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEzMDEG
-A1UEAxMqVmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUgVGVzdDE0
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw0i1MxqkhMcbORFEu5k6Y4Q0R
-5QY60nT/GZQrbH5OZMueDjhFLTTPfxvN9VWue6NgkPLQ/NgPlm0+DDz0+4dyMi0F
-h93v/27ZAOtBk0eTVvvsCvAyD5EBqW1PWcZHX3oWyaY9AWM2JHrZv8M/toQ4CA2V
-yJOzEOf1bJBfj+SUcQIDAQABo2swaTAfBgNVHSMEGDAWgBQtN9I/nlnZ5r5Xovdr
-DxCCpq0D7jAdBgNVHQ4EFgQUBBCEgvxOOcAPi/H2IhqSJnWk9mgwDgYDVR0PAQH/
-BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOB
-gQAg9tR9jL/eux79Ixd+MLGGfc6YC+FUqLyNErhpSQ7FiCc1jPwAFfyuPLiyBmJS
-k601bFn5fO2LKSSocHH9ezXT+x0XHajvaNlNd2w8YXKtrW5ogwty9q21c4VCuLrE
-ej5cBZPdSyp4RBkdBnjfPc2vRW6x0g3EMA03aYr0Sc712w==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P1anyPolicy Mapping 1to2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIEHjCCA4egAwIBAgIBNjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbUDFhbnlQb2xp
-Y3kgTWFwcGluZyAxdG8yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDs
-qiRQp8ZU1kWOS/tvtPAlHT9dGf17useanNh/sRHafDBRsOVVlS+kMA8Ti/8uecSP
-PEMznqfzcf7wvC64FNOt2P3rD/W3oZ7MShTLQF6C5mqsh8A4T+DDgdhNG5xtOAfg
-buRxp+A4KybQ7YMzRHnb5Z6UEKCAOv1NmaQpQU6lFQIDAQABo4ICFzCCAhMwHwYD
-VR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFC030j+eWdnm
-vlei92sPEIKmrQPuMA4GA1UdDwEB/wQEAwIBBjCCAXgGA1UdIASCAW8wggFrMIG5
-BgpghkgBZQMCATABMIGqMIGnBggrBgEFBQcCAjCBmhqBl3E5OiAgVGhpcyBpcyB0
-aGUgdXNlciBub3RpY2UgZnJvbSBxdWFsaWZpZXIgOSBhc3NvY2lhdGVkIHdpdGgg
-TklTVC10ZXN0LXBvbGljeS0xLiAgVGhpcyB1c2VyIG5vdGljZSBzaG91bGQgYmUg
-ZGlzcGxheWVkIGZvciBWYWxpZCBQb2xpY3kgTWFwcGluZyBUZXN0MTMwgawGBFUd
-IAAwgaMwgaAGCCsGAQUFBwICMIGTGoGQcTEwOiAgVGhpcyBpcyB0aGUgdXNlciBu
-b3RpY2UgZnJvbSBxdWFsaWZpZXIgMTAgYXNzb2NpYXRlZCB3aXRoIGFueVBvbGlj
-eS4gIFRoaXMgdXNlciBub3RpY2Ugc2hvdWxkIGJlIGRpc3BsYXllZCBmb3IgVmFs
-aWQgUG9saWN5IE1hcHBpbmcgVGVzdDE0MCYGA1UdIQEB/wQcMBowGAYKYIZIAWUD
-AgEwAQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAw
-DQYJKoZIhvcNAQEFBQADgYEAqZ6Cif011+oMzp6bcMsfzt9sTBgpT4l35AbTC5sm
-zp3ur8X5X2G604yKkSXe1cf0F+fZSE6zjwizb1YG0owt1eGWSxCdAlkIFRang7OG
-Z93bEKBx3ysDYCKvemx0f3shGqJVVzMBo6JP6JX7Jnn385UdwdKO2dWzVhHXsP+P
-9sY=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P1anyPolicy Mapping 1to2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:2D:37:D2:3F:9E:59:D9:E6:BE:57:A2:F7:6B:0F:10:82:A6:AD:03:EE
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:52:84:5c:c6:67:e1:f5:70:94:c5:af:b8:de:1f:38:dc:b0:
- 65:8a:69:80:b5:9a:f9:2f:6c:13:8e:83:5a:5b:33:01:1c:d2:
- a9:c6:c7:09:92:cd:17:9f:bc:f4:30:d8:bf:8e:05:c0:98:d4:
- dc:be:b5:31:80:76:30:f8:35:48:45:a5:25:2a:92:df:1d:ae:
- 4c:88:5e:34:d5:ea:39:8c:f2:e4:c7:e4:c1:35:45:3b:6f:6f:
- f3:81:e3:2f:43:ad:ae:e3:98:3a:7e:0e:48:51:cc:a8:15:38:
- ce:38:31:9c:36:5e:a0:eb:f5:16:e9:43:a9:5f:77:a4:bc:44:
- c4:0b
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG1AxYW55UG9saWN5IE1hcHBp
-bmcgMXRvMiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAULTfSP55Z2ea+V6L3aw8QgqatA+4wCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAVlKEXMZn4fVwlMWvuN4fONywZYppgLWa+S9sE46DWlszARzS
-qcbHCZLNF5+89DDYv44FwJjU3L61MYB2MPg1SEWlJSqS3x2uTIheNNXqOYzy5Mfk
-wTVFO29v84HjL0OtruOYOn4OSFHMqBU4zjgxnDZeoOv1FulDqV93pLxExAs=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14EE.pem
new file mode 100644
index 0000000000..779f279635
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest14EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 94 4A 53 1F 7E 3A 7F 66 49 42 EB B2 E3 62 53 3C B1 5E 96 C6
+ friendlyName: Valid Policy Mapping Test14 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test14
+issuer=/C=US/O=Test Certificates 2011/CN=P1anyPolicy Mapping 1to2 CA
+-----BEGIN CERTIFICATE-----
+MIIDnTCCAoWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUDFhbnlQ
+b2xpY3kgTWFwcGluZyAxdG8yIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowYzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExMzAxBgNVBAMTKlZhbGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmlj
+YXRlIFRlc3QxNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANJpXBTA
+3EjsCM9UAoN4IpqwMwiEiVinUgeyznx8NNMjAkrsfSYyMGuchz7Ty/nobcdnUdnZ
+50UodPrVCuy/Cyp/8vrseLEElc2iCsXifGYGSNqxw7906l2rVOvXPQocc0Oa6eTM
+PeHQ//CnC3V209gER16XJ2u/cQshC5Hc6y8lnGf5JsMfcSuPn9QuWnsJt68YElOG
+y9UKmK6fbYHUKH2lwKRGHvCU6UyXgTGnaf50Yu+X2RPe7F7tBWYangT+W6JsgBzu
+SINOiTKjoAD4KysSn+jgFMcKQ6wLhFlb6myIFOX5c93qJ2z0pNCdBiKswpBwkxQ1
+BM4Gu6OY0EE2hGkCAwEAAaNrMGkwHwYDVR0jBBgwFoAUHwIoKDKOSoT4uItB8V17
+6CVSa4YwHQYDVR0OBBYEFP7baMrCM949EDtAPOIY3Qz4oLGuMA4GA1UdDwEB/wQE
+AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEB
+AK347siub9i/zLVRrZkhB/xSOaOpN/ReyvDZsgfdj9oyMHsB1J6ToViVwrx8Af2+
+V4a+ajppbH3FK8jq38FQiUqVwNT2N9MBUuBEBIdq74bvtj7saVjpuBWyPuxV0MMq
+X1zLln5p7KA1M1PNT4uB+g5D1a0MP6I8oPCSiFY6s5cDyzR+vPOXvf7/RXwi8rnT
+7hXgSU1KS5gnDt4qRS+j/eQYDQFZnkH3WIdbyupTmpFLkqAIL4FuNfBOwEJWijY4
+lvwET2SIsHPLLgtlg6lzyY+LmlJ0ABeFLxgCjPINOKj7yafvQa2G6kaAp34XU1Ms
+C0bZ/GDrvAwewPgQM54j7lM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 94 4A 53 1F 7E 3A 7F 66 49 42 EB B2 E3 62 53 3C B1 5E 96 C6
+ friendlyName: Valid Policy Mapping Test14 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,704650279CABB0CB
+
+ej/Ec7hBM36U5YZxPRg8gj+A0lhQSeV7ETYlsSNseojvKfFNaRvTIalKKaS3Rkaa
+tiyNNcuufNvy6ddQzN/zX5UFlHAdlNoRyLY+QM4aiuGe/8RZBBRQYwb9jdRd6qDm
+lQI0sd+dB6Bu5Du74mHQe92IvGAXyW0g08HQs1afl1KWGdULH+ONSL3ay+vSzLHW
+7N0Q27c3vR0EFY76cjoA8N/8/AfJukQtlDxAIrysqGEVFP1EqOZrU26dcKFuRY24
+k6oT2VafpewKYaLwx2lHIQPCfMFBQX5qqQ2gvwrYDi5xmFNAgGJ2vpE6NUm9H+mr
+4JVFv/coQivFVIs4yqn5AJ2iZJ2PvG8oW/HMbv2tyrlf3zj+MtH2AjAyKN5Uy0Lk
+6wLEe+AV/Yh3jRzqzwwnYZia0z/hkvV2FC77F8NK8lwANJELoPC2lkHZwOK6da3m
+lWJ1VQoQPY5J2AouOThTCV3IFm4w+7aACx7R0apX26vndOTUSuup/U6PromxLg8J
+tM+xIQZBVKP7uY8Xbh6iBN0XCTTyINrQYByoMKoO7KjzP2lN75mofejFd1mopKZJ
+1UjdHXyGonF2BWupPv5OXuNRo5d8+6pRyqubGEijv8ttWqoW+uFU7679glE9W4or
+JFnvDF9ADclR2geMDc28H1C5rlcA983Qs2jUCo7jH9QqVvcxQcV4chIWTtOiHeyl
+4tk/BSiWJAY4Fa1FhitAXLHIiarj/MkmIA3sYCnOOU7hNvzUpmSu0vz5LRqCjrF8
+quqLhFqOVags5tEYAxH+CGuBNc+oSdL/c1u8mry4lfArs2jV8XQvuJrNEtUPcZau
+u63YuHU3G42O8DQJSboszH7/AB4U5Gp8tbvqmjCaWFarDn1q8fEqXEx9TlVtqNxP
+HtWhfcDuSccRP4JpGQXT5xFI5mF6LnlD+k/cbipn6BMrtRxd86fBU2QzZHUwyikI
+TSoab5MDiS9dpyIqzkO3jfr1PYhzpWyNBSaYJkbc4QFGIyx9FNoSQV+gBw8axO/7
+airaWgrToFsgPSwDAadGWr6rC+Jt8PVvFru7LjIGqcsHdPpWuBWJqn9Q8kqlb8Rg
+AUq3P8Jifg+YbMpukK98Le5pizyxsq0S4HFgB+0ddUvx68doHYl+5OaLSt23UrtQ
+DyF+QT0YbrF0NgkIa/PZd+I4NrxotPDN4G9Pa82jJ2hRJfBkennX3PaTJ6jHIP2K
+2SKD817l2k3Ds86qRCrqEIUm28y5ghNv3orSjY6BELzt5QLE3tuavUGaqXpu7OB4
+8OfxvBAeR4qoT+DvQetzOlIFiALlfjWWNBLXGcwRxIXVGUDOTfStBha8gtPIFZXW
+Pd4Ad6MYfiAn81R5NBrdEdsMF1Zb9yCLaaz8atv6+sWMSAjp5Xaa6arVP/LRg3d1
+ZYj1orrCK3BDlRTKAAycBcQBjwUe8n/0JHO8fS1IZridmbsC7x2HTaHdzXjouvA0
+p+xouoWQz7IVUFcFz0asqvpc9+bIlYN5en2O6gomSTKdOVT4fDOT9JQPWdnPogsd
+cmuLx0noBprZ9h6wHY3oTB7dMXKzBZnkwSm31BMXCpVQlAXAFZelAnElqtfGiqJi
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1EE.pem
new file mode 100644
index 0000000000..5ad8e63db7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1A 3E 81 47 B1 3B 3A 90 4D 6D 14 9C 50 FA B2 C5 E2 97 7A 9A
+ friendlyName: Valid Policy Mapping Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Mapping 1to2 CA
+-----BEGIN CERTIFICATE-----
+MIIDkDCCAnigAwIBAgIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPTWFwcGlu
+ZyAxdG8yIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMjAwBgNV
+BAMTKVZhbGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmljYXRlIFRlc3QxMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1qw4n+hgG57EB2akKG9HJw0U
+1wJcwQKfWv52eTaKNomMg19NaikNJj/iPcP1wdIjZAATRynTDN07kpReiNXkE6Re
+5QdXFp8DzsOreH70CDBHDlPpvx10awKgAU24NiT2vEyGm3vee2V+gayPV4Afl+nt
+Oh9kWODmCIJyDRG6l9j0R0fYLR3/DQT+w0AGb1He2RS2N1i6dO8hTEDImxqMPLE1
+ezZmq+nq5MvWlTAlwbREnLXgB0i1GwZaL0RY1OogQbsxThAaGPqNJRW+qioH3A+U
+qgWEheSueXoz2AZsnhDsw0hL72MvzG28BOFhqtdeRpOW3gddnnJ+peluBdgM/QID
+AQABo2swaTAfBgNVHSMEGDAWgBSZxXhpyz0zdsKZrETlsA7+ufTbxzAdBgNVHQ4E
+FgQUlaI8n8HPjmgNunyqQD8HV1jeilUwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOCAQEAq72hK/CqUQUKPp93
+JCSZAQGtUruzmdRkery177NaQm/EDlhkXR0uEp2HToxIF0MJY20IMwBGR818tVEq
+b/XfO8up2yg1T2gkKCAqU+JMEctVeTD1qzk1eDXKTi0pcfDJ6LPuTHNZ9AInFCmU
+mczg+kqEGSk9Fwn/71Trzlm5oVkIsOv0CgTnoaSyp+qdSiBWYprSmwlwgrBnFMNW
+tOA/ukHDQ7IdVq5iE8lfu0j2do9FV/a1W6uHuxb+ZiEWD9HJ1kJ8a/7c6g/e3Z96
+/PuBVVJUnn8wD5Aun8yexdPAQC3ngJxEmb3a2lLlEI+FA4jRsaCBQHjKlQlZpM99
+Dy3BwA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1A 3E 81 47 B1 3B 3A 90 4D 6D 14 9C 50 FA B2 C5 E2 97 7A 9A
+ friendlyName: Valid Policy Mapping Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C82746A5DC292BD1
+
+ez+wdH0Dut8Ngh7c1y1x2EJhVvIFHRbmZcVpQ9MNZHQSMIxO3qScxJc9/P8/4A1o
+iMLBBq8CLQGONQZa2W+eqf57/YqWGTIb2yNPK1yiF1K806KjHyi8oMGfB2pYX8KT
+x8p3IOH4lzFxarmiTNJze6HZzGUZp15hRcaVb4MAAlSC3Xmw2CEFWpYU4FDL8fg7
+NpdvPNOaGKgHKXQfsVqqD8MsB8jvRHINhpQ+0lUTuNbtDqlcPfvzVa+KKhoXcYGH
+lTajisATNn+Y66JpCcdkobOZ2qhAep39CigHDwltW6uUX6dKlU95Jokz91IsnnBz
+lHGfimrlMDGcN4OOLhSf0yBJrXmLLuWS3KPafF99ZXFlvklL6ophf/lhVi00T9fA
+jlCde7S/AwSlWvrXbFqAAah0EaoNs8/cX7s75Mp9iJ2J2r709F+ywxQXG/YYClf6
+Coiz7JyXm+mXWZtxfnL3JPoY1zLZp0Xq77dFfpyKfBrJUiMKUtJ0uTySYSvdLdau
+pqJWZY3TZO6718WAZOSzET5xe4mgfHrk4lGQDyCNRq3UBKYgRCcY6LqzcQLFODLr
+wHmGg/BZQ78kRow07jqL+fmKhTlWcKc/3uTuR5ZIBc9Y8P7Apnqalj7nvWrkydvQ
+JmtojF9guktjs2NLtzeCUtJkFNCLD8am8uawg79QpRFhyBzFFWVYjf65Dk6IowRf
+25qMaeUor6M9pX6i42lEsi0UgqvYMrGKSmrJ94nBbivvorHbSyXaC8RpAxEUVOhQ
+P1YlLvDx2sVsQ8UiTrKS/+KMfD/Hdj+pncTJvSpsYXHp023Tbw1JbFDZzI/aFj3a
+Z0VWQOyHe9L41NZsN8WsVtRFavlggSQSbXg2XMUKp1+x4y5LttwTx9n4uuCvVFJj
+/u2XO7zRGUezyoYxrobjoDmRNSk/tTPGG9I+TN6V0sW3m80oUQm200cmxrWSD0n2
+m8DUZmH7SRxMkqGFp5+UZA9H04efsZqSQeBu/MXweJaqrGHe+S6svdj+EusLJEj9
+6aYzzgCxw7K0gxvwKNdpR+r+IPLyuZo/rfqz6R/fiIsFFbmcn9QnLa1SiPAMJ03g
+Iuqqxj73alQxdcrSJL/V+etE8RHgK4TVO7bVrYSyGs3RvHlCLCOFuF5F+vI/IhCf
+1lefEU93G6dLnBBDCs7178CyNIkxj5OU7OdZQ2D49rUKpu5g/uEvGIPUFnO3x2HJ
+7GeoaSnv0dDXgc3HEapK8pHjPoLG4t636jkYiLwMuc5Msdg+W+wUdaLKqgbQW3CV
+HzU+E7mVA22nY3ar4iSlcjVtOxXq1A5tow7kOJzl+YErkz/6GpBtTYy5vOv5ohU0
+MbvMV0n7meFlKZlvZckkPyNmhq4PDwHi0IIxI5L+ZvZmfNLlscF1IYrF/nj0PEY9
+5KXCUNxuDbKJLcMORPZ7GYI7umwJ6YY741cqlVhBnPCVILr2YT/NsDMz2Xk8XGAQ
+gFggomds2hPgcLI2GolWaBaXXkgd9Hxfdz/t1EvrR62HK79dlqktNIIOLIx9ZO7K
+XcQbomjX3+yFeOA5Ix60GTNMRFy3U495lc6PMKTTey93/xnoOnY79T/rmKtGzH1p
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3.pem
deleted file mode 100644
index d5af222303..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3.pem
+++ /dev/null
@@ -1,214 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subsubCA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGVAxMiBNYXBwaW5n
-IDF0bzMgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBd
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxMjAwBgNV
-BAMTKVZhbGlkIFBvbGljeSBNYXBwaW5nIEVFIENlcnRpZmljYXRlIFRlc3QzMIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLjaVgcxBArg5ZjazYxWoHTBcfcT/5
-qsS4WoFj+0UELOPixTqQjmJofe3JKjHSI1h9yiTTiyrDVRkKB3DPYLo8zkv7HQeJ
-sleZKw3rgNtSOKuMY/9E5Pex3Q77pOCXZES31n/xZ1BRfCHAkhA6QxSoePkp7Au0
-6R9jYczfn3FZwwIDAQABo2swaTAfBgNVHSMEGDAWgBT2LLG3KbWulX+w+DlBUy0u
-DwTjxzAdBgNVHQ4EFgQUx21mI2aVCGSW1qLGljar1+6L7JUwDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwCDANBgkqhkiG9w0BAQUFAAOBgQAI
-oGNjmv/QvuGxJUK+dcyZqM4egLTHcIlgtNw5QURIbyQz+p0EkQqlEly1G1f6jZg7
-yi0vbf2ng8f39I50HeqyGHay1/H9Koq5m0K+a9GV2mi0huLFL96U7b64ELF0z371
-W/OSduqoyZhrzBnTSuNoiqmlAlV8Z+TXjVSp1HX3Ew==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICvzCCAiigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UEAxMTUDEyIE1hcHBp
-bmcgMXRvMyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmTEwLH6u6mb6
-kvz4ulbBVFC2Ea6WdEv2uH/vNi23mER2Nl+xAbeopiy3OLEiXavvD3uvVjX0bSOH
-BGk2j/ern/Urw6djfKt5V4O3NMYi6Grvfm346kdutjJuBcNlhLOE8mLXUguspocr
-AoAEjrQtuS4Bkb9A5wj3OYy4jr2JhtMCAwEAAaOBwTCBvjAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUreIKE61SbSWszamYogoEaK1y
-rrIwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUDAgEwATAMBgpg
-hkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEw
-AzAPBgNVHRMBAf8EBTADAQH/MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQAD
-gYEAEelnHhW6SAs3Zj4a5YMVTKDe7vCThen9bA1Awt3yFincViRt5/s2ZyzTN5fr
-Xi+2m42Gm+Anb3D7rpV9IJ/PahHq4yrKSrcAzhT3IcHbuHFNwiw8Z3T+31hhjJUx
-3atYpYOZZPYwuT0inFHJWRfBNA8NGBtqYlxI1C+/ucdy7ik=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subsubCA
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subCA
------BEGIN CERTIFICATE-----
-MIICwTCCAiqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlAxMiBNYXBwaW5n
-IDF0bzMgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBNMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMT
-GVAxMiBNYXBwaW5nIDF0bzMgc3Vic3ViQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBAJjo4/4TekqllLI7gPzmE2OceB30SRuraEVWVdR/lmFpFTks5fKkqf96
-WjYpnJZwaqE1ZdUQxgeNsswPm4pUAhVmU9IHvqBaM+bNXFsrwBOYYhfZY3xnwcxp
-IZsvkLPuEq1vLwxpn+0zTDOpDGf9zhiTrswEUoGYBwOVqRDaToYdAgMBAAGjgbMw
-gbAwHwYDVR0jBBgwFoAUXcS6eHk0JsNyV9FZ9KPiVKcocdEwHQYDVR0OBBYEFPYs
-sbcpta6Vf7D4OUFTLS4PBOPHMA4GA1UdDwEB/wQEAwIBBjAlBgNVHSAEHjAcMAwG
-CmCGSAFlAwIBMAMwDAYKYIZIAWUDAgEwBDAmBgNVHSEBAf8EHDAaMBgGCmCGSAFl
-AwIBMAQGCmCGSAFlAwIBMAgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUF
-AAOBgQCass0kmtqSdWX5lffBs/tSTSvnGK38REo2IwTFLHduO4cvzAyS7ProbF/J
-al8FtT9mdnl+NpwrH4KlFNu+uti47wFj9xov/kbcmp21DvZ/m8ihmStk4FG2r6Ad
-0gdmVfBYem0mOu/1r/F8deNFP/Dpd8w3KFnv3Dd9wZd/Eb5hrg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 subCA
-issuer=/C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
------BEGIN CERTIFICATE-----
-MIIC1TCCAj6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE1AxMiBNYXBwaW5n
-IDF0bzMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBKMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlAx
-MiBNYXBwaW5nIDF0bzMgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-AMsNrOgngQPHY/5QvmR5y8mHOJJ2T8Vjf+3/DPv5eMF+q11urxfCat4faDdtchBa
-QXOWQ2TEy6tqpR7u8UJ2wnI7phld51gAcT2I8V7swo/EM1Ga1i5bWa5G10vPmZw5
-l7QwqT/D6JkHdthcaJdQrBP9zesYPEp13RFQU9mP5451AgMBAAGjgc0wgcowHwYD
-VR0jBBgwFoAUreIKE61SbSWszamYogoEaK1yrrIwHQYDVR0OBBYEFF3Eunh5NCbD
-clfRWfSj4lSnKHHRMA4GA1UdDwEB/wQEAwIBBjAlBgNVHSAEHjAcMAwGCmCGSAFl
-AwIBMAIwDAYKYIZIAWUDAgEwBTBABgNVHSEBAf8ENjA0MBgGCmCGSAFlAwIBMAIG
-CmCGSAFlAwIBMAQwGAYKYIZIAWUDAgEwBQYKYIZIAWUDAgEwBzAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAHwK+aOYJpXAoXSRQ1o82pqD++jA/uvr
-2eJoXbcch64CAdRNuCA7rQoRAx1nSUgjoLmHcTDrowQzodrVXVmCmYqXxB5XswG6
-z5Oj09NorxHxpAs7E/izElYwEXl5n0NMInD6S2r1SWOnRpGnCL8PYM3gW+xne8rJ
-CZMIMADOWvrc
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:E2:0A:13:AD:52:6D:25:AC:CD:A9:98:A2:0A:04:68:AD:72:AE:B2
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 94:34:62:ba:34:51:b4:ad:dd:01:40:fe:3d:eb:bc:6c:7c:89:
- cb:f0:7e:e5:38:03:50:93:5b:68:ba:d1:ca:14:39:ec:a8:9c:
- 37:24:c3:0f:01:eb:14:67:8c:07:fc:37:1f:bb:45:b9:4f:5f:
- 56:ad:f3:85:03:23:a8:bd:93:1c:ca:01:e8:b5:1c:c8:60:18:
- 13:95:bf:5a:11:11:b2:3c:3c:27:69:bf:97:08:c0:b7:4a:7a:
- 39:5e:03:2c:67:5a:11:a0:4f:6f:8d:70:4e:e2:b5:31:73:2a:
- bf:5b:15:af:5b:4e:14:e0:73:5b:f1:2d:cd:bc:75:44:42:d4:
- da:3b
------BEGIN X509 CRL-----
-MIIBQDCBqgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAMTE1AxMiBNYXBwaW5nIDF0bzMg
-Q0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaA
-FK3iChOtUm0lrM2pmKIKBGitcq6yMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUA
-A4GBAJQ0Yro0UbSt3QFA/j3rvGx8icvwfuU4A1CTW2i60coUOeyonDckww8B6xRn
-jAf8Nx+7RblPX1at84UDI6i9kxzKAei1HMhgGBOVv1oREbI8PCdpv5cIwLdKejle
-AyxnWhGgT2+NcE7itTFzKr9bFa9bThTgc1vxLc28dURC1No7
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5D:C4:BA:78:79:34:26:C3:72:57:D1:59:F4:A3:E2:54:A7:28:71:D1
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 15:bb:13:8f:22:9e:5f:ae:7d:26:76:5b:6f:8d:8b:a4:37:1d:
- fa:87:83:61:23:70:ca:f2:bd:ba:ae:72:04:3e:0a:21:70:4e:
- 01:97:4c:e3:16:d0:ef:d9:31:50:6f:5b:ff:51:10:40:73:82:
- 0f:f2:00:90:1a:bb:f8:93:68:b9:0c:15:9d:b2:c3:5b:56:73:
- 52:d3:1c:0f:75:2f:51:5b:40:3f:8b:71:42:54:33:af:55:20:
- c8:ff:bf:ff:68:43:78:93:55:01:fb:7e:4d:db:a8:57:36:34:
- df:a2:90:75:bb:fa:23:f3:9f:de:e4:4d:92:30:65:8c:f2:64:
- e0:01
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFlAxMiBNYXBwaW5nIDF0bzMg
-c3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFF3Eunh5NCbDclfRWfSj4lSnKHHRMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBABW7E48inl+ufSZ2W2+Ni6Q3HfqHg2EjcMryvbqucgQ+CiFwTgGXTOMW
-0O/ZMVBvW/9REEBzgg/yAJAau/iTaLkMFZ2yw1tWc1LTHA91L1FbQD+LcUJUM69V
-IMj/v/9oQ3iTVQH7fk3bqFc2NN+ikHW7+iPzn97kTZIwZYzyZOAB
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P12 Mapping 1to3 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F6:2C:B1:B7:29:B5:AE:95:7F:B0:F8:39:41:53:2D:2E:0F:04:E3:C7
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 6f:b3:1a:29:36:35:76:c7:62:11:6e:e9:29:e6:83:8b:5e:bf:
- 25:ea:4d:71:56:16:50:25:92:68:a8:a2:e9:4d:09:a3:74:36:
- e2:9b:c1:52:dd:87:0a:64:98:58:da:6a:96:e6:c4:02:90:d8:
- cd:4c:10:71:4c:98:1d:bb:d4:8d:7d:74:f9:34:3f:98:f7:8a:
- 5e:eb:bf:7c:8f:90:2a:7b:c4:f3:29:cc:3c:62:a3:f8:08:c2:
- 0a:ae:35:92:8d:ed:c0:30:a3:f2:a1:c7:7c:a1:68:1d:b0:48:
- 4d:c1:4f:50:7f:1f:af:c6:f3:a1:d0:ad:8a:1a:78:05:84:6d:
- d9:7e
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGVAxMiBNYXBwaW5nIDF0bzMg
-c3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFPYssbcpta6Vf7D4OUFTLS4PBOPHMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAG+zGik2NXbHYhFu6Snmg4tevyXqTXFWFlAlkmiooulNCaN0NuKb
-wVLdhwpkmFjaapbmxAKQ2M1MEHFMmB271I19dPk0P5j3il7rv3yPkCp7xPMpzDxi
-o/gIwgquNZKN7cAwo/Khx3yhaB2wSE3BT1B/H6/G86HQrYoaeAWEbdl+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3EE.pem
new file mode 100644
index 0000000000..7793d24eb0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1A E6 3A EC 27 20 C7 C6 CC 83 BC A0 DE F1 89 9B C9 66 97 41
+ friendlyName: Valid Policy Mapping Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=P12 Mapping 1to3 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZUDEyIE1h
+cHBpbmcgMXRvMyBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMGIxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMTIwMAYDVQQDEylWYWxpZCBQb2xpY3kgTWFwcGluZyBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANBofqJQybQy
+hloY6wTFGeWWDQq79xScjYNcGS3cgblO19DDYa+gw/1/6p2iVy7NxRnZRUCGSLXi
+f5dXWOaCE1oiyUWBbd0ToHI1MAlsDmXv4LsGceJzr659aeSRNn3aq2uQ4HgezAfn
+vPKL+OqnFTyaXD8VcPwoptkSoCVjG3qO/6O8X5xSI3UJZl+Pr0KeaQZpLJVznUcc
+dGROiHNUYzt/NgkxqPxusg1yfLlv1zKTl8ggf1j5uXbp305FLVAKWFENS0InNiZl
+gbSenXwg110BwtBQjE1cSRmD5xPqrmrCDuNBz1M11vB3TCFTlJLYBcjT/kn56e+P
+P0fixAdywAECAwEAAaNrMGkwHwYDVR0jBBgwFoAUAF05Pg/lqipeLfauaCqtM5s9
+m3MwHQYDVR0OBBYEFFdyv16sxo14G5DAn5RGpP4eU7xaMA4GA1UdDwEB/wQEAwIE
+8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAgwDQYJKoZIhvcNAQELBQADggEBAE0+
+Wkm1qVJobS6Lj4Au2vE32CuEL8H3Oi3jvfREIRH8wyFkYrEIDNnV1yKqMaYtvnxx
+62U1tMJKwXDHYENtgregZDVl9xtFYvNj3VXXBfeWyR/hZA9bsqf5KBmTopPCrADx
+BgZuGWnUhfcFFvUYVCgyCtrwCZXDgdoOab0oFq9gR6RyUJ/MbjSSsBzqILe7sPGy
+7bbKX7zeBN71c0lwfyUqXdqw2Ar/yyqtqY5xR0Y63hBhENwc0FOqlQRqzRdxieX0
+OdrRgGDiWUdPueXm6dE1ID6raiFgkbNjDS8P9w6JITApVYU2lf+FykcXUPJVbXeG
+4fQjsbxrjEFK9aUJduM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1A E6 3A EC 27 20 C7 C6 CC 83 BC A0 DE F1 89 9B C9 66 97 41
+ friendlyName: Valid Policy Mapping Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E8F9024A549F3FA1
+
+7ChMT1T/ZW+0zg91e36RwxSOGvgXXmWJLJBbzK1gFJrdwUJOl5InaNrMZLe2Jh3K
+FYtggzWl3/9XNSELQgQNhHwNI7nc15bugP8Plh6PimoSifls5VO3ZjnEJCa9CyKq
+yh3s/lM9iGy+MgzariSUZSx5nReAyHkNaqWFhVDLbaMcdBIOY9+PZSltz5q3jF7A
+awbb638S/9I2tbHuXeE2DsJJppayYjDsbI9W3wMNmgcYzfXd6m+TCqXep5WijkDk
++L85APUy+p4erB9rgLE7USMAIbvtw81cmpFY6J6rN4EmcniUfZj7tKB/C6JLiwHp
+Qe0S0f0s96LuPqE/ITEk/LynxarFq9wpgMJ/fpIivW7yru/iAuMMW6JHs7OkDSOK
+4jAPtA+7X+EC7jnjFuGSDl8k0KEaVKi5yt/FcAO8I/NPpHJqebFEbSKa+caWkJQT
+aDOICSgx9kRtshUJzyySS93wsHCACL+fx/9A5XfUtsBvKWeJ8Aez5ijEqsmrJ5wh
+qgii2nZQX19u+lur75MAMznUswcJ5Q3MhZoLwhBw9BOSKq0FIeTNxXC05Tm+/hPv
+7yJyVPJaDAdmNBmAX3D6wpkxCrEpNBqtW8dHzLBMuBnW2+7RXvypUpF36sYyRTaD
+jglx3b6nRgnmfeLI4U0UnD/f0vfmb7+NyGognyQVUbeZzToGNR2unnBs9bJVKDyx
+FODIylSi/Pt8FrYTpZ26w2ZgLNshqh2FncCBjsVPwhEKbhL2IYiuTuhuMB8BhzA5
+1yvmgzGN2c7xVeprp8OVYEeWUWmeIHbWKywsRWWD2P2wmV9S5u8qF3Ju3rX6ylWe
+A9S3we2wiu6EEvP9uCWrHbJ4NIIB4YcforIWX6MtLaThSbYpuZrNHd1DPSBLGRu6
+qZtG6JLZ4dk4PzN4htJvEDqZw4lHiBpgovTtvF0N0YDNWWB4FnY4ZuQDucZitvyB
+y0hvM6VWBsaKLXDLeH3DwFX1hiiRv2p+PBRghxGXbfw3dwSSgXwVKtxJhj/N4xty
+lJnx521+8A0vFazzTazZLyDl0Zgfhx920cDL0WjMiSbFqB4dg4enZplUEMaXdMcg
+LMvPGsYzWUEkSyAfZTVjexhWb3L/HLxL4hWSy+nCOFGsbfNr1E1aEZVlHaDgE8GG
+0FF8eC8BcaKVkPG8u4h6NVkXJPbkAL+r58LPLQH1s3O5XqevShJ562NQ7bd33zRx
+gktQavo4Gcf4bGgm5FvugGTVCLN24h//rWBP7s9T80CnU0bxaq+5npVmzNBzSq4+
+CxHX6IUeK3wyr5PSSotljctQENzh1t6C5I1XfAGIubpK1pQnOmxIxzKG6Q3f8o+V
+OlyScauwiGXF3TVbvEJNcdopPfpZOXTiFzjv9gR3H40fNINe8SYqTfpDNao1g57J
+N3E56PuSICjuOf5fvgHFe7ksrRtKNagMGw5y3iUxZTvUGuScce+NkrwFjb/Y+wTa
+61oo/gNXMlnUSRU87iKrA8acXNWrb08KEIbiDCcIl2jmckp+IONiSGBpxmUjDsvz
+BJz/odpDNTQ5FlUZ60yIQAl3pqs/oavurzmcvet39hCxCieM5OMrqsXgt1F/1TYw
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5.pem
deleted file mode 100644
index d916bbbbbd..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5.pem
+++ /dev/null
@@ -1,163 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 subCA
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF1AxIE1hcHBpbmcg
-MXRvMjM0IHN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowXTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTIwMAYDVQQD
-EylWYWxpZCBQb2xpY3kgTWFwcGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu7tA0m9E4vxbGx8d41Nw9YFiUAKWV/rI
-5MXmpuTVeWZr5ELloOLZG/UdWxsbxKWX+FmF+RLDfJ4aAfomI+J/gPjv01gXT0PD
-qXqflxdcvCR8kWU08UNs5Dbks3BtWaR+rF3Zrw/gz9cg6d/fGFn48gjtn8LeQz1w
-vqAP8w3woaECAwEAAaNrMGkwHwYDVR0jBBgwFoAUrQ/vHBeBV326g+8R/4doc9Km
-G5cwHQYDVR0OBBYEFJ/3EWzpeGSBUdimPN2Zptp/EZwFMA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAYwDQYJKoZIhvcNAQEFBQADgYEAmh2B
-OoSik/wvehYBZuSGtFC/NOP3yi9x6PCY/pzav9YZKgJZXeEJF78A5SVPFjP5BJcI
-c6ke+EApOv2lHbViBi7ll5xc+xSh1Ko77NOO4yrlFe8+ZiKz+kXizBsfbcKUYtKN
-KHby2pgphWXv93Xe0fIFKYeSWqoKvL3EHjc8Gtk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 subCA
-issuer=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 CA
------BEGIN CERTIFICATE-----
-MIIC1zCCAkCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFFAxIE1hcHBpbmcg
-MXRvMjM0IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSzELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSAwHgYDVQQDExdQ
-MSBNYXBwaW5nIDF0bzIzNCBzdWJDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEAuxzFRezTkAVZWZReelvBKELugXp5Eq7O4Ye839Rxl3p/kBRLWiFz+bsyeeMl
-YKC2+df3mBhUm5dDtrttv+oGaGL4bquZgb6X5TNxSHDe/D+3BAyxbFn8Qfq642fP
-QvmHsQYWtT+dP5NUxFpss8ElrWi0X2UEzb5ChUalSf2Vde8CAwEAAaOBzTCByjAf
-BgNVHSMEGDAWgBTMp9HShu8hYwWY780byv/gRLPUkDAdBgNVHQ4EFgQUrQ/vHBeB
-V326g+8R/4doc9KmG5cwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZI
-AWUDAgEwAjAMBgpghkgBZQMCATAEMEAGA1UdIQEB/wQ2MDQwGAYKYIZIAWUDAgEw
-AgYKYIZIAWUDAgEwBTAYBgpghkgBZQMCATAEBgpghkgBZQMCATAGMA8GA1UdEwEB
-/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEACas+sr4fsuwRW8lWjQQH9NDBg4OC
-4/j/2+haNy4neNyKBSFPg7g/HTOvalwVvR2OoEiVIdh2cLH4ELt3GVucJkB9Nimr
-nV4trKBPR9Cy/UTVzDvDS9NW7FEyTWtlVbTEU4um4rvU+7HkmY4JjaEUbqrdFcRf
-ho4KQe/QkE0wYcU=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC5jCCAk+gAwIBAgIBMjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUUDEgTWFwcGlu
-ZyAxdG8yMzQgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALkWaQEgKSf0
-Z8Rv+4X37UP7SJyBJFbt6QzzxNxVnCwFX+0X5rL44rsZBya1cg8TN0BvQjpF7hKW
-Ch5A0nARNvvI6cOBqQ5T2UryrVgzPb/dXebSy5e8afDUs8QqRB9dHb/m0AVC+hTd
-mwlok2dgnsm+DdpTaKbgKWi/jjlr8H5BAgMBAAGjgecwgeQwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFMyn0dKG7yFjBZjvzRvK/+BE
-s9SQMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwWgYD
-VR0hAQH/BFAwTjAYBgpghkgBZQMCATABBgpghkgBZQMCATACMBgGCmCGSAFlAwIB
-MAEGCmCGSAFlAwIBMAMwGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwBDAPBgNVHRMB
-Af8EBTADAQH/MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQADgYEAXs0UPa8a
-gMe7mdH0Zuxlka5P2WW5U6NGJTaF88e0d2LNd0rKAIY54kVS6qWRSb4m3fD17BhB
-HYeJt1wRTxJo/oSdKxOYY/2k1BQLH6HyqsgQsOq5V1KTBJSPsCVZxvw7i0dDtw4A
-VH9jyKpEN4XcL3k1hYHJvBU1sH8g1sE6vLQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P1 Mapping 1to234 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:CC:A7:D1:D2:86:EF:21:63:05:98:EF:CD:1B:CA:FF:E0:44:B3:D4:90
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 45:0b:74:18:70:b6:d8:66:8a:81:70:d0:a9:21:e0:0b:b5:9d:
- 71:45:a7:fd:df:50:ee:d6:38:4e:90:ea:eb:a8:84:6b:79:0c:
- 64:6d:0a:4d:e0:36:20:6b:ec:c6:46:8f:13:13:99:18:21:e7:
- 44:60:19:de:b4:f5:ea:7e:70:4b:b7:12:b8:4a:1f:5d:9b:b3:
- 1d:cf:e4:54:5a:a1:8c:6b:ad:fd:51:f3:0c:96:c8:a6:7a:83:
- f2:a1:dc:3a:a9:84:f6:7f:8f:8e:3f:91:ee:ae:e3:85:9c:7f:
- 44:b7:92:89:15:77:f3:b3:dc:13:fc:7e:87:0f:e0:d6:55:96:
- ee:83
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFFAxIE1hcHBpbmcgMXRvMjM0
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBTMp9HShu8hYwWY780byv/gRLPUkDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQBFC3QYcLbYZoqBcNCpIeALtZ1xRaf931Du1jhOkOrrqIRreQxkbQpN4DYg
-a+zGRo8TE5kYIedEYBnetPXqfnBLtxK4Sh9dm7Mdz+RUWqGMa639UfMMlsimeoPy
-odw6qYT2f4+OP5HuruOFnH9Et5KJFXfzs9wT/H6HD+DWVZbugw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P1 Mapping 1to234 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:0F:EF:1C:17:81:57:7D:BA:83:EF:11:FF:87:68:73:D2:A6:1B:97
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 33:53:2c:ad:0e:6e:e9:49:14:44:7d:de:5c:dc:4b:0e:57:35:
- 35:18:f2:d9:4b:94:c6:38:1e:4e:33:a7:7e:6c:b4:b7:d2:72:
- 46:03:28:4b:d5:ef:a3:9a:ca:16:33:03:ec:bf:cf:e9:8f:a4:
- 4a:01:c5:e1:a6:0a:b7:4d:86:ee:08:93:ee:1b:da:ad:da:d7:
- cd:6a:da:95:eb:62:1f:13:19:30:8f:f5:33:22:fa:7b:2a:c3:
- 7f:b8:ca:67:24:4e:f6:4e:0f:be:aa:31:23:42:eb:0d:76:9b:
- f0:64:24:95:f4:b8:62:7b:5e:14:24:fd:6f:6c:8e:82:b3:60:
- a9:c0
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF1AxIE1hcHBpbmcgMXRvMjM0
-IHN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBStD+8cF4FXfbqD7xH/h2hz0qYblzAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQAzUyytDm7pSRREfd5c3EsOVzU1GPLZS5TGOB5OM6d+bLS30nJGAyhL
-1e+jmsoWMwPsv8/pj6RKAcXhpgq3TYbuCJPuG9qt2tfNatqV62IfExkwj/UzIvp7
-KsN/uMpnJE72Tg++qjEjQusNdpvwZCSV9Lhie14UJP1vbI6Cs2CpwA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5EE.pem
new file mode 100644
index 0000000000..e559732c39
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest5EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 25 AA 50 77 49 C5 A1 C4 F0 D9 00 06 E9 3E 2A 34 06 06 02 BD
+ friendlyName: Valid Policy Mapping Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=P1 Mapping 1to234 subCA
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXUDEgTWFw
+cGluZyAxdG8yMzQgc3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBiMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEyMDAGA1UEAxMpVmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUg
+VGVzdDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmiGMLjXA2ijC5
+itMpJVXTbHXhguDwZQ2mcSY5FmZ2nPuO2JBp2lA6yUG7fCuxTKeC1mGSOej41Pz8
+zTkOGiXC/UtDy73yQhJJPHFn/ka7HzC3UlIOzRbY3nXg89sqIrO4wFLKUvrM1VkW
+FqXJw5XbDwrL/0vIhqHh7jyK64snUiP0AAm6kgR1r3aufS1/QwjozIkRGmP4Cxm/
+8Gzz5is4kfB2NuaR8xE/i8BubAM8TnAyIXX6hy99TlyyXSD2tc8dlxTskD8lt6IY
+w0NwwNTi9Rqq41ZKkLtixase00o+s345noAcI5SfLdnTKXM6zUwooJzBW/av+8C7
+YyqmOjS1AgMBAAGjazBpMB8GA1UdIwQYMBaAFAMX5ZUA/So5eK/LRvZAmGUKAu27
+MB0GA1UdDgQWBBRLgjD1Mqn9+vaGwm3k1zO/qu1RFTAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATAGMA0GCSqGSIb3DQEBCwUAA4IBAQBSG/qP
+hRrenfviZJK/kxNaJzIM2ppVq3YbCxbjSApzL/tqPFEKtJuw2r7UlAY05rqzaZyE
+1sxWuvyenub6f/K9BCQRBXHO5cPOnWS142x9komCqDUP7I7F4pnptXAp8nyc8eoL
+zmsOJ8dlZv2aD//mISoFMZ69fvfIku/MAOZCTnSks1CPyT9omAfT6zdnMiDfk/kY
+lZAWFas9/pm16Z88QP8y0z/IMrri12dOLMnFyKNBy/9TXNZof/VPkkD2keJ6eQGn
+MUamXI/OIlBJXqu3AYiUDP9FQbxKxj4uTOtS1MhrZbAtTAI+3eqPKU92T8YFamCr
+A1Z483lYO5ntY6/Z
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 25 AA 50 77 49 C5 A1 C4 F0 D9 00 06 E9 3E 2A 34 06 06 02 BD
+ friendlyName: Valid Policy Mapping Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0CE59FD1BDD6BE3F
+
+ZSsWK88M8cUm0Ar98cUKth20vjDFRCIKPWzlUnrVs+Lk7Kq5T+uRcX8BL1LEKwDj
+k81WTxyck/3tn40bzS2dIqRxDur4DWSWUzRvi7Fs6NdN+AtGL9BOvPO2vV0o4p1a
+LG9aHL4cClxgyVsBHho5tqv5CRlhFqj6Z/TBz9SqKoBMvw5qF5B4/NMDrzoZ7rxb
+NGJfJdKti3VPYE1/qfW40+j4rlqmAbtJVL+yeXQ+jdvOdZNO7vNjKMExkjkDQBFG
+tv46/TqcPToHfT8or6N6hk8Xpfz7a0Qxal7db4HwrqXyRMzzkrczucNieZTcep0c
+4hEhKj3WRxRXWhC2pdqn2xjXD9GZBGPmcDxVF1p2vQrhkTVOYRF6yAqvSPkLAlzB
+K4nK5NTQBErvy9r2Sr8KIElZjQIwpTmjOJEsCKCBXO+8GDcwViCl4px+oNGjUc3p
+oSje1Pe9BYbuIcwMuT7pE3N8ovEpra+b6wlc/WIpOLEiJwROAedubKjcg4FAM1uE
+POYIXLyCLo0a7a7cXxS2rv9dQwKfFxXIUvXFnY8K0jJqhr8WD3L9uOU0BNCsee8N
+DExbBCbPybSbo6E+BkWXPF9fhhhbmlRNY3zpF+HjN+YXUqfGoD+TjLjc5tZT8aZ3
+J/7f3j1aFKlu0mGZWqoHV6aQ2yKsShAWWt5g7Xiv0tdqCTSBxY+141wSD8K/0Lqi
+UPGOKJjbmU5rusT5S/VAxP2tsWxpaITMT/wuANu8d6Hfk9VvIggiGR4MXJMsVM6Q
+4me+GqfbNnXgqgYCiprwZRnAdhlAvyNMTJ5HkbXsLUlNKgunaLdf2fxRVevVlKOg
+4fnK0J/uLyaFfkHI7XjXhHWg8sJAkGKkeC2I8lnkyC4UcIqpI9hsJGl/1+WWPez7
+uojkeFYuURQ/jaeFb9p/SO5Zq7mqxGltPC1oE5Fvn5GlnbgYs9RqOF24yb7/30vs
+fjN0vFBiGtLM/uP1eVbdFOC6/iLgZNRUOxZTJSg3OIBoAmMY1fEUJt/h9ZcRFX+q
+ZK1HDjhhybk4SRafZZV3DuyycZf154w349NdzlrtIdUoXTIcJ0uLilYL8kJDE75s
+EZRRjnHEtJH3vrUkDEIUxWG96FXWo5Lf2r+18CW3ktGAAzGWu5JFiQ3Mny5uC++f
+rNqHPzPrD78c2huhG+TZAO3XyLf5SY3thldAneAtceknOinK6FCxifF5/ZPn2Vra
+YQyFzTbQgHctSSkccC4qHMhi8rGqxXEnCBbN+GpCSlbLWjnYLPBuW/wSVKNYpqii
+T58Ff4WK0PKIBXEu/nINzvNqaIzedpENweo+F0pkd07M8QVW2EoMKI6sfUBQcuBs
+aoHIdIR+9IEOpgLk5Q1TAAIFsuno+vkWAIFAfF8F+CSVXf5tFAdYVP15zhLL5JPm
+k3mNECnrcErMM4m5f1zNAaAwFEIPfuqcTmOGoPj+sl/YzI6ZJ/2QJ0KsAVVKugH6
+1NVWK1yzxSlOzWHZvDUV4Be0d5jmipIgWJYRW/qf6bIdYFBfE1pGohsAj5XXGheR
+wWzkUima13yr3onooRE01ArKNue68/kGZgkyVRrsm4+cflLusEPFCA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6.pem
deleted file mode 100644
index 665a6357fa..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6.pem
+++ /dev/null
@@ -1,163 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 subCA
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF1AxIE1hcHBpbmcg
-MXRvMjM0IHN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowXTEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTIwMAYDVQQD
-EylWYWxpZCBQb2xpY3kgTWFwcGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NjCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAg/jjf7HVRt6r4IitgA9kVxN6rVQy1OLQ
-Kelr3lLXIJbXs7XYoUx53Br5c1SDdSaaRfvhKyMl7m53baO33b+MEeB8VfWHt/on
-35CKtGtyDa/IbfzrrwwJqs0rF4H/t7Ngz1b5rrKaEjy4itjNylcyAzJC1Zjer8aJ
-iXyszL9uGc8CAwEAAaNrMGkwHwYDVR0jBBgwFoAUrQ/vHBeBV326g+8R/4doc9Km
-G5cwHQYDVR0OBBYEFOH+LaLyiRCW05OelA2Y/97NYu1gMA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAUwDQYJKoZIhvcNAQEFBQADgYEAZStF
-y/RNVE9ElY/wKLp8pdE/c4L9rucyOPSv/5zhGO4+GiiN39twvGjjMH3ziIauJpuM
-rCb8q+3s22lzkD6/BSLyRNCXM7Mx5CGWDCdHqnkdFf1Ck9ddAG3hF8FkeKjlZ2MA
-j1g2DpZezCE4srw5r+5mXw95piUHxvBxIXnBUJ0=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 subCA
-issuer=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 CA
------BEGIN CERTIFICATE-----
-MIIC1zCCAkCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFFAxIE1hcHBpbmcg
-MXRvMjM0IENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSzELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSAwHgYDVQQDExdQ
-MSBNYXBwaW5nIDF0bzIzNCBzdWJDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
-gYEAuxzFRezTkAVZWZReelvBKELugXp5Eq7O4Ye839Rxl3p/kBRLWiFz+bsyeeMl
-YKC2+df3mBhUm5dDtrttv+oGaGL4bquZgb6X5TNxSHDe/D+3BAyxbFn8Qfq642fP
-QvmHsQYWtT+dP5NUxFpss8ElrWi0X2UEzb5ChUalSf2Vde8CAwEAAaOBzTCByjAf
-BgNVHSMEGDAWgBTMp9HShu8hYwWY780byv/gRLPUkDAdBgNVHQ4EFgQUrQ/vHBeB
-V326g+8R/4doc9KmG5cwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZI
-AWUDAgEwAjAMBgpghkgBZQMCATAEMEAGA1UdIQEB/wQ2MDQwGAYKYIZIAWUDAgEw
-AgYKYIZIAWUDAgEwBTAYBgpghkgBZQMCATAEBgpghkgBZQMCATAGMA8GA1UdEwEB
-/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEACas+sr4fsuwRW8lWjQQH9NDBg4OC
-4/j/2+haNy4neNyKBSFPg7g/HTOvalwVvR2OoEiVIdh2cLH4ELt3GVucJkB9Nimr
-nV4trKBPR9Cy/UTVzDvDS9NW7FEyTWtlVbTEU4um4rvU+7HkmY4JjaEUbqrdFcRf
-ho4KQe/QkE0wYcU=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=P1 Mapping 1to234 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC5jCCAk+gAwIBAgIBMjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUUDEgTWFwcGlu
-ZyAxdG8yMzQgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALkWaQEgKSf0
-Z8Rv+4X37UP7SJyBJFbt6QzzxNxVnCwFX+0X5rL44rsZBya1cg8TN0BvQjpF7hKW
-Ch5A0nARNvvI6cOBqQ5T2UryrVgzPb/dXebSy5e8afDUs8QqRB9dHb/m0AVC+hTd
-mwlok2dgnsm+DdpTaKbgKWi/jjlr8H5BAgMBAAGjgecwgeQwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFMyn0dKG7yFjBZjvzRvK/+BE
-s9SQMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwWgYD
-VR0hAQH/BFAwTjAYBgpghkgBZQMCATABBgpghkgBZQMCATACMBgGCmCGSAFlAwIB
-MAEGCmCGSAFlAwIBMAMwGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwBDAPBgNVHRMB
-Af8EBTADAQH/MAwGA1UdJAQFMAOAAQAwDQYJKoZIhvcNAQEFBQADgYEAXs0UPa8a
-gMe7mdH0Zuxlka5P2WW5U6NGJTaF88e0d2LNd0rKAIY54kVS6qWRSb4m3fD17BhB
-HYeJt1wRTxJo/oSdKxOYY/2k1BQLH6HyqsgQsOq5V1KTBJSPsCVZxvw7i0dDtw4A
-VH9jyKpEN4XcL3k1hYHJvBU1sH8g1sE6vLQ=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P1 Mapping 1to234 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:CC:A7:D1:D2:86:EF:21:63:05:98:EF:CD:1B:CA:FF:E0:44:B3:D4:90
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 45:0b:74:18:70:b6:d8:66:8a:81:70:d0:a9:21:e0:0b:b5:9d:
- 71:45:a7:fd:df:50:ee:d6:38:4e:90:ea:eb:a8:84:6b:79:0c:
- 64:6d:0a:4d:e0:36:20:6b:ec:c6:46:8f:13:13:99:18:21:e7:
- 44:60:19:de:b4:f5:ea:7e:70:4b:b7:12:b8:4a:1f:5d:9b:b3:
- 1d:cf:e4:54:5a:a1:8c:6b:ad:fd:51:f3:0c:96:c8:a6:7a:83:
- f2:a1:dc:3a:a9:84:f6:7f:8f:8e:3f:91:ee:ae:e3:85:9c:7f:
- 44:b7:92:89:15:77:f3:b3:dc:13:fc:7e:87:0f:e0:d6:55:96:
- ee:83
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFFAxIE1hcHBpbmcgMXRvMjM0
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBTMp9HShu8hYwWY780byv/gRLPUkDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQBFC3QYcLbYZoqBcNCpIeALtZ1xRaf931Du1jhOkOrrqIRreQxkbQpN4DYg
-a+zGRo8TE5kYIedEYBnetPXqfnBLtxK4Sh9dm7Mdz+RUWqGMa639UfMMlsimeoPy
-odw6qYT2f4+OP5HuruOFnH9Et5KJFXfzs9wT/H6HD+DWVZbugw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=P1 Mapping 1to234 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AD:0F:EF:1C:17:81:57:7D:BA:83:EF:11:FF:87:68:73:D2:A6:1B:97
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 33:53:2c:ad:0e:6e:e9:49:14:44:7d:de:5c:dc:4b:0e:57:35:
- 35:18:f2:d9:4b:94:c6:38:1e:4e:33:a7:7e:6c:b4:b7:d2:72:
- 46:03:28:4b:d5:ef:a3:9a:ca:16:33:03:ec:bf:cf:e9:8f:a4:
- 4a:01:c5:e1:a6:0a:b7:4d:86:ee:08:93:ee:1b:da:ad:da:d7:
- cd:6a:da:95:eb:62:1f:13:19:30:8f:f5:33:22:fa:7b:2a:c3:
- 7f:b8:ca:67:24:4e:f6:4e:0f:be:aa:31:23:42:eb:0d:76:9b:
- f0:64:24:95:f4:b8:62:7b:5e:14:24:fd:6f:6c:8e:82:b3:60:
- a9:c0
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF1AxIE1hcHBpbmcgMXRvMjM0
-IHN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBStD+8cF4FXfbqD7xH/h2hz0qYblzAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQAzUyytDm7pSRREfd5c3EsOVzU1GPLZS5TGOB5OM6d+bLS30nJGAyhL
-1e+jmsoWMwPsv8/pj6RKAcXhpgq3TYbuCJPuG9qt2tfNatqV62IfExkwj/UzIvp7
-KsN/uMpnJE72Tg++qjEjQusNdpvwZCSV9Lhie14UJP1vbI6Cs2CpwA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6EE.pem
new file mode 100644
index 0000000000..56e8e3d911
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: DD 2E 16 E1 97 7A C6 59 34 9C 5B 00 D2 4B B6 E1 22 2A 85 97
+ friendlyName: Valid Policy Mapping Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=P1 Mapping 1to234 subCA
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXUDEgTWFw
+cGluZyAxdG8yMzQgc3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBiMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEyMDAGA1UEAxMpVmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNhdGUg
+VGVzdDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvhuKxV6OvBRjA
+hr758hKWi26IfFd2aGOgdDGd0/1i4wrW//nS3R8mVimchkGruRx1lB0KyEBYmAE0
+hmep3SPwapk2xbej0UL9WgLubmfHv5iesAqn+/gFGyNrHx9/uzp+Ua+25BUGYxBC
+bcMIIN06qMTU1dZF/nqNCPTO4uzdgH9VVnQHkI/TWLmrT8rrq44slyOebfCeXZeV
+G2LtDcubaYdJlo4NJPPE15zrXPBxL4m0pFWPHeTUcEyDwJulUjFmX/NIjUF7yyvn
+LlpLDHFFSzA4bVLOh0rI2VSy2ac1izMJx0gDnil7CykRofgkxJ9nmjclJ8pHtDVc
+TKRmps+dAgMBAAGjazBpMB8GA1UdIwQYMBaAFAMX5ZUA/So5eK/LRvZAmGUKAu27
+MB0GA1UdDgQWBBSzX9tBAp4J21F61Yw77Wz/CmsSAjAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATAFMA0GCSqGSIb3DQEBCwUAA4IBAQBpUnko
+RHAEZlhGumDpYCRzwa47JJqYthnJicarIhlRPpk6p+JkxZh1ISOfOtvfi9ApLNgf
+O+Vr2M1Pd7nWfczbWcmKaa2QqcMU7c/r+KZ/1u4kN12BMlW8TY1o0kk7bBsqjpNt
+6qAdQ+drFBIk7CxmaJuruJxSWZq6+EKy6MzeZiXUPOeujDaxqO3qixQK1iphIZMJ
+MpF8Ls+p9Y/KZ3M4HrUteKvYCY37QzApC32yZmuOojxJOm1+kEV3rzb79dA5epJL
+2nm2oLv8/C8gg7c1v4SpXUoR/d6hgLqu1jZCDFPMAN1Fv2eiWwU5sV2DcSY4bs7j
+yxy3p3hdJLiP6KQv
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DD 2E 16 E1 97 7A C6 59 34 9C 5B 00 D2 4B B6 E1 22 2A 85 97
+ friendlyName: Valid Policy Mapping Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6089FA172B6A8809
+
+QKaY7/O5JCscfC7Cp3i5pjL+h+jdtqZZ6yX5zZAA6jAwtlVb3IQba+xfyB+nGq51
+yQaN4otb//j64mydf5RuAn7MUJ/2VGwKBSOYGwe1Fmsmd2Gdzv8lkwFrG8AU5Tq2
+K43+wgYZuz9bklxLf85aLZMvtTRcKM4FRIhhJSig0i3FshbhPzZ+EqjyPlHg2+Ji
+fkDR984Iww+WRYAkifZZPFmTpBNXn4WPRJZ/GwNoLA6MkriAhQUUS4AOQ54j6i4J
+jsgylIEa5Ld1j1WYxULXsnI3x9suxMbdUKHUrjLMavJlPHcYS7tZq47DwebO9yB4
+L5XKU8wUv6kl3hVKZtsOTTSQkj0fM9F6cqOOm1Sg0aqSCc3luAAPQuy/t3h9LwAg
+vnQNnfk8AWwqLErmIhzu0FJd4bYK6XDY7IbePHu2T9rEGZZ+XGMN2Eo33XdwdDtT
+uvBM8eQVt4rAkqNO6m0uPNzBmsX0K01fMYV7dpPrFolKl2gVe+bdZjUNQTsa7Onq
+3rsLlEpdO4RP3G5aDDPHfRYPygfJYQtTj1URj0CFLw3K00oGP/hN3BsGi8Ct5io9
+FlwwCugf9dzwhxEVC7iZb1lPREa45FIHih1eHAb5WmJf6SVqRcLh8KBbnvl5Jl64
+AWayZfb31p98TO5eNPfDsgud8dLZkt0Tcbylm1QqDZAL4Z4FbOmAwzlo3BFtQlG6
+jJN3MMFEegNNzkHxScPT5CYaDHFPvc+ndfL6SCFlDOOzWDTZCbYWuLIFZF6MCxLE
+pmEnh4pVmYXOEiIJ5uNFOX9Utg5s28LGr1KQvGHbSKbT+ohctKBq59lZE/sD5LYt
+j8qceGNc/H9omoYli3b/bqJ0FZobsPi1tjz9efPNPF8zz0brQgDxVP2icJH3gKd4
+3G5Ir71YZCVnTMaI4vwzh9FzXKSmIVUry2T2s3NyzKOwOf56a7FqO8s8S4LCZNVB
+9TerDx5FLW8m1W5d29zDfDHjIYtDOliBknP+4LT8CntcC9zGJ01hZt2z+gDMgOyW
+3g5juBfEuSljwcVqs0h5v3Rm+acci3Jkn/TuVeRtngBhIZ4XApF+Cwv/8GjsI8ad
+HjGJ1EnufggTyQONstqNQeMzujDYil0OVgbNyfnBRfeSJ5oB/1mzCGwgrVVh2NsW
+N1U5WpPFOg72jhb8SD2wCvEBcgC5DiPBVpUjhHISpLBbw9+0w/GBkSg3eBcAWAh4
+ukMvgsMpZAwRah21+q3owMILGZz5Yk9ipH8c/OwKznFVky1dJvKEtet8+S+8R+kO
+exTd1ar/mU1u+I9heI9CRz1kWMUHlwKM3cAcZ2k9BTj0UICweQ8+Vf9KUEteUtWQ
+LU8z9Ssn6WCNh08/FoMZNCt3+P1NVpz9c0o/9W92GGG/0AVPkSXXLvsutQqj+YPI
+nUmTM8aXl4eQdA+8NX+DrK+LCfOyDUTnDuoZyzbrKvYzm5TxAb7jzFbXebfYMa21
+hzs0Zwl1rVTtK3TKwYTn7i57sfJ2u6F0j2k8PSc+ovk9u6S8E/WvKquCOcabHPFE
+PAXKisbusrHRrObCNBIwSZhA6b3OxoiIIq0H3JlvMknwkXb9VOffAKMbe5DNHwUm
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9.pem
deleted file mode 100644
index 252e920ac8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9.pem
+++ /dev/null
@@ -1,109 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Policy Mapping EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=PanyPolicy Mapping 1to2 CA
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGlBhbnlQb2xpY3kg
-TWFwcGluZyAxdG8yIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-XTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTIwMAYD
-VQQDEylWYWxpZCBQb2xpY3kgTWFwcGluZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0OTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2FRrJurp4yzaLVdHeMS3IAQQvUjp
-lPkcXvLpEyQnWVTBYLsXJF9YdVxJJFES2XUxVFTumNnOjc2XcgCuUDwqoUYHPv8P
-UWZuoQ8B2sg8HPNU6G5BHBbtXkzC7lKCDLRshPSgnKngxdmoIDSVDPkz2KBUhbFm
-QZIqhVHE6UPCViUCAwEAAaNrMGkwHwYDVR0jBBgwFoAU0rpPGz5oOOaQ+MHqJa7a
-kq9DNm4wHQYDVR0OBBYEFEhKmk02sJFH9yFXTXKxqodRjaFoMA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEA
-PrcU9aDr57y1wekJ7k+ZJuhDlemNjGY7ggrZcarGL+LsRqkufpgkLpei7Cz13buA
-L/MqHFdc7H7d+GrbF4PAe2NXfcnlJJMLjS9Jw77qSb3aw9eSqYscBFhOxYWNL/Qh
-5GI9hJYugYGFzLxh1Cnl0/Pc8PoBgtaZg7H2hXmlUyQ=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=PanyPolicy Mapping 1to2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICsjCCAhugAwIBAgIBNTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMaUGFueVBvbGlj
-eSBNYXBwaW5nIDF0bzIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPOw
-G+hWDRzfFMkg2CwlHhCBrp/3hveD/ESGWRnpEp1ATKX47bZDyerSn5/9+d2sCsja
-seeR04tpsBmS+o6bUTTy9W5G6gxE/McnS7oH1WJLYNW9e57ckYArd3i85wr+Ecoq
-IaTiDQmy4Ze+TBNA/7CaYTp8agquwDTl40VGqfs1AgMBAAGjga0wgaowHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFNK6Txs+aDjmkPjB
-6iWu2pKvQzZuMA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUdIAAwJgYD
-VR0hAQH/BBwwGjAYBgpghkgBZQMCATABBgpghkgBZQMCATACMA8GA1UdEwEB/wQF
-MAMBAf8wDAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUFAAOBgQBL624FELsxdPKY
-tcreLc/Fz0uWZ7bc3BEIeVTarTWFu536wAOO2Pf4mJdJZ5WVVSYcOJb03Zso6U0G
-h0iYeHFGkXBCrqeOGe1h3zL4ED/C0HYJmPtLcTrtlAwvYq8dq4ABvsqMAUgFrsf4
-JGqkgLsMrbXRCAsLpFver5xKAuQ67A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=PanyPolicy Mapping 1to2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D2:BA:4F:1B:3E:68:38:E6:90:F8:C1:EA:25:AE:DA:92:AF:43:36:6E
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9d:f5:f9:0e:d5:1b:b9:cc:83:35:eb:00:3d:98:52:11:89:63:
- 79:17:97:0b:9a:f5:0c:35:72:44:ab:2b:97:85:0d:c1:3f:26:
- 10:15:81:e4:78:88:59:2d:4d:2b:4a:8b:5a:58:e4:2c:82:76:
- 0f:b0:c3:45:c6:46:34:cc:38:33:da:6b:a0:79:e2:65:2a:3a:
- 54:8d:69:54:6e:77:32:c1:45:8e:63:de:09:f4:3e:9f:a5:19:
- 37:25:92:40:f1:aa:57:f2:61:69:e3:3d:e4:05:85:94:ec:29:
- 51:dd:85:6c:65:c3:83:7a:c4:f9:37:7e:c0:a0:0d:6c:86:2b:
- 47:7b
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGlBhbnlQb2xpY3kgTWFwcGlu
-ZyAxdG8yIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBTSuk8bPmg45pD4weolrtqSr0M2bjAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQCd9fkO1Ru5zIM16wA9mFIRiWN5F5cLmvUMNXJEqyuXhQ3BPyYQ
-FYHkeIhZLU0rSotaWOQsgnYPsMNFxkY0zDgz2mugeeJlKjpUjWlUbncywUWOY94J
-9D6fpRk3JZJA8apX8mFp4z3kBYWU7ClR3YVsZcODesT5N37AoA1shitHew==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9EE.pem
new file mode 100644
index 0000000000..368e85a23f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidPolicyMappingTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 64 C9 0F D4 50 79 97 AF 08 D3 0E 95 4D C2 BD 47 50 08 57 1E
+ friendlyName: Valid Policy Mapping Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Policy Mapping EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=PanyPolicy Mapping 1to2 CA
+-----BEGIN CERTIFICATE-----
+MIIDmzCCAoOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMaUGFueVBv
+bGljeSBNYXBwaW5nIDF0bzIgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBiMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTEyMDAGA1UEAxMpVmFsaWQgUG9saWN5IE1hcHBpbmcgRUUgQ2VydGlmaWNh
+dGUgVGVzdDkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+P2NyLxKH
+FxAPjW+SjKAbIRefIhK1wrsTiAqxwAXyFdd7DGr1yZgRDI01vPYyYCRCx+N4L1S9
+rDC+mmh+zyDlsM9cQOaApF6Q8yoLW203kJIb2RWaxIL3kWhpQZsVVZ/feMaFM/3/
+TlpjJlCTXyG5rBEz9jorFf4gaLzqfqROlojVWNN7ozp0aSe0hb6PrTymHOxA76u8
+ahz41lNzczNv3UgfzijurhYx93GxKvM+uzSkcz6in1HaNVI9EYb/DgeqhnOW+eNX
+lRBVxIt8Bib7ATofuBQCnPRzvC7txybCPX1KN32Ey3enhlRnFNXeGcEdEcevSVLw
+CZ6KkeB+ft+BAgMBAAGjazBpMB8GA1UdIwQYMBaAFEcDJy9DPcUv2ZKsx9J20DPG
++Xe7MB0GA1UdDgQWBBQIZAJOoXdyajkMnsi9d3w/HMoLfDAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQBM
+SaSdAKgMib7Hlpoooy+Du7GZe9IkYyp9XEhiugaOHtQzdD07PS4kUUjjtj/+RjAd
+JB72SZBy6TX0MZoWhz6E4Zn9XwGmxWPAs2RwIcV7ICLq9ZvnThoCk1rUNRJN2GUJ
+rKAaHnnJ8eplpFy7pe+XuSX3+BmuEsB8cY+UJML3DR3pfSP45I8hM4YP6a5C3HTd
+Lif+xigdnT5hBD7UIDXTMxfBFFufc4Ckr5ON3bRRgQKzkV3+FL57dWqBweZV8wIm
+WfW/8BXJVho3Tm7hj2m5Kl7GxuaicnVC9zjC02xSX2zWatlAC9qQ8PebqWHdNCt8
+a+IKJC+4NrcghSNUs/eR
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 64 C9 0F D4 50 79 97 AF 08 D3 0E 95 4D C2 BD 47 50 08 57 1E
+ friendlyName: Valid Policy Mapping Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,875194FAA839BD5E
+
+TWaDWBhDnwciPVhYcNPoNJhJb/3AJQRnKtKsCwIcT456D+Ibf+ASOyC2h/TkC+tb
+ixNCg0qUSng9CUHqtBumy4hOQtxZqVjYni5+EtxBM+pAuc8j7gq1EAVQMNLh/JbT
+0gak/VmVhlKb3CxPWyszP5HTDezqlNZfkgUwxzryWkT/xv7abmv0kwSL5kx9WCaA
+7CvriwCr4/a+Fjey1J0QolUsf85SjwtgW2bjVC2bGdP+rG3GmM9upvLongxoDXbS
+uBjyvg3jMiM80pjXsAx7wrnd5mJxO0VGROkXjOCH0UWU9pEjSPeK8DyEr3xTfcRD
+CBJ4VHuCAR9xB37ibfx6SHSP6lqeFiT+mObiQDHhsFgx51gG2PjsUexOiRDHTYzS
+GqR81IfPVaNLKVyAxyO7Bdq/BlLJw3LKhLS6amGZJP8KLgMDC2EAnQduRcc7kxyQ
+uTGuAaxJRub2S9XXNpGmGT6JOOfdsILv+sKR/xCDetUstIX5HKcqyMG5QusWdtL0
+XD+ujNT25PRgbQ9YnvS1nKDcP/g60/xzWjR0NsPStHJTDO7TBjH6yvj69jH4XtEa
+4pKiYVeLPeOEtgq43tLM3kB3bXNZoXHXaiQBwIlokAa4JfijiltkH3jy4C9lccz2
+xV6HZQT8y8/4aCXEbxJouZ9EtoD36J+QUIrikQYFTZNZ8RAHPlzFFgrzDSb3vUlm
+DSMhWkk6AmlVCuOnKZHFXEFXHLsVov9phq4lvaBTPL3mARyaA7z2ELtTcI1Rq6rI
+/WKQVfq/q/vC1OYsRCubBFmGv7ou7yIeWtAFpFSl7mutJDiL18UIT6wBRuVyd//M
+75XeC7EVZfsl7R8cflFrYiX4FDK872wTnhPa7bFJRMq0pNBqWAnXcIJJN8ySgZ/c
+721NsMHtkFdSC2SLenMZTZw1AjClVLFoZ4Ke0LOvynxUerLP1HySYeEFpd0z1F4i
+jWOfEl52lq77Dlthn2Ax1i5Tgz35XYVjUImjCvbnafRuSzEIUfuoxITGciRSlatr
+r34layA/Ese7oHqfnDpmht0Snx3FKDNr2AOfLpEdTAqkWC2aceu9m9H5erbpu1hy
+gwbwZ4okeUc7rAzBJ3JZwVX5gou6erOsMvq3rrpM9MQut64LDe5UmiTbqk1nScNm
+25n4XJ98Za+ZJXD9S4AkaCjPiLJOVoBa3lwviBZMG8TCCJFqpf5TvRi65wQe186r
+mxP0EDsjDjvZga5tHEBXTVco4LlsQJifdvQzUlpDgH0KVfj7jt88fH4Rq8DthZ9X
+MBBwRRDQDM5xXq9mkV2s20o0OPUEVrCfxPNhavmA6IL/veIGyH/oLrNg3DrRlRpr
+LQr6vUwBdXr3IXFceKygFNHI5m6m70GwCgKEH7zVGLIhaCUwr44JVopCNWLs5LVJ
+8J2GWsRjr7VWXUF/bPhemVvml/DGysKpuDyJerCm1rQd5/Ba0mZcFi/q+uqmGbH/
+QpRje1m4JWP+UA2Mr7cLiGezv53s3iRp3ZXKDLWrKUIXEWMP6iuW30m6bHOD3n2U
+xhZh8opURdbI4cWF+7sSmRvcTUl/deNCMHBq+iolwppR9pz+wX3pLg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7.pem
deleted file mode 100644
index 6a94017c06..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7.pem
+++ /dev/null
@@ -1,113 +0,0 @@
-subject=/C=US/O=Test Certificates/DC=gov/DC=testcertificates/ST=Maryland/serialNumber=345/dnQualifier=CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICwTCCAiqgAwIBAgIBYDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGOMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEzARBgoJkiaJk/IsZAEZFgNn
-b3YxIDAeBgoJkiaJk/IsZAEZFhB0ZXN0Y2VydGlmaWNhdGVzMREwDwYDVQQIEwhN
-YXJ5bGFuZDEMMAoGA1UEBRMDMzQ1MQswCQYDVQQuEwJDQTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAmPmvvNuLBaXi3cYQQzuNFOtq2aeNq1YZodT/+7SSfjl2
-uz1wsLHI7XjOGOuWrE9N0oNBrARmSYh6WrYCJj1cd8vcj+FTymvx5DWEeqPCDmxU
-EO4e+/R+utHsFmCRzrOOUEqKkiHNGoR3iyrYr5zszJRgRDwf1QiYInu0cLMsHr8C
-AwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0O
-BBYEFKAtjaBcqIIIYio2ok1SyOUsUH0rMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAE
-EDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUF
-AAOBgQCXoXCIH5TuCf84dVOweSMfOdb5MzKTudOw55mU7VgDzMk7vzQIEx3jCeP0
-7h8byDM0i/okjN0Ugm4DzOwxx5lAjs/uGGhGRGBVCJIPQ4QemsX3L24YpqSQKoJj
-K+YL+sz8pdoaqX69dDAyIcZNG2i9L/WEvmacw0AnJZ+Rd06jqw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid RFC3280 Mandatory Attribute Types EE Certificate Test7
-issuer=/C=US/O=Test Certificates/DC=gov/DC=testcertificates/ST=Maryland/serialNumber=345/dnQualifier=CA
------BEGIN CERTIFICATE-----
-MIIC4DCCAkmgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRMwEQYKCZImiZPyLGQBGRYDZ292
-MSAwHgYKCZImiZPyLGQBGRYQdGVzdGNlcnRpZmljYXRlczERMA8GA1UECBMITWFy
-eWxhbmQxDDAKBgNVBAUTAzM0NTELMAkGA1UELhMCQ0EwHhcNMDEwNDE5MTQ1NzIw
-WhcNMTEwNDE5MTQ1NzIwWjBwMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxRTBDBgNVBAMTPFZhbGlkIFJGQzMyODAgTWFuZGF0b3J5IEF0
-dHJpYnV0ZSBUeXBlcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NzCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAn3sUmVtQ1OLPODq7WXtzygEZ0tKb60KjAITF+WQQwfYO
-katDsSHQU19m7Uxi3JX3wKeIZOJLDR14VB8aGUsN6pNaKKFCB1B2pgQsjDZsCLDz
-ckA7lYdIC40Smu+8Nb2IGgncTW1Dye6r36lxhEpAU0cqXdOKkhteDDOW42tuZlMC
-AwEAAaNrMGkwHwYDVR0jBBgwFoAUoC2NoFyogghiKjaiTVLI5SxQfSswHQYDVR0O
-BBYEFHv2CemcO4grJLwWGJqNhA9NXdicMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAE
-EDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAQAimtwbz7YQ8Pm8M
-Cg/LHjRpGXaJL82W85ioX8T7hsFsGlQbHp6uAq/Zkk44mG2ziuI5pJF/HnuAXPiF
-xHcnCfDDpHpNh7deC53/nPf9Co375lZRWlBT233KSL14GTyiBZPipzbsUvJ+7FOp
-alTeRK4fPr3lNDo9SEVo4e97i5w=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/DC=gov/DC=testcertificates/ST=Maryland/serialNumber=345/dnQualifier=CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A0:2D:8D:A0:5C:A8:82:08:62:2A:36:A2:4D:52:C8:E5:2C:50:7D:2B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 52:d1:8a:cb:32:66:cf:87:3e:a9:ea:a2:35:90:42:18:74:4f:
- 9e:43:5d:6c:73:09:4e:ec:45:68:bf:3d:c3:1a:97:e5:83:66:
- e0:2a:1c:84:97:8e:d2:29:2a:c6:f2:41:e8:fc:63:3c:8a:5a:
- 1a:8c:40:eb:c3:12:1d:ef:5e:70:a9:af:d9:dc:89:28:03:76:
- ff:b6:cb:5e:e0:82:f7:ad:32:3c:60:58:3c:fe:24:3d:9f:68:
- 79:98:14:e4:0c:80:1a:f7:63:eb:5b:cd:ca:1c:69:80:93:8a:
- 26:55:e3:ac:b9:05:7e:83:64:d4:3b:11:26:bf:fd:df:5f:3f:
- 40:30
------BEGIN X509 CRL-----
-MIIBiDCB8gIBATANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRMwEQYKCZImiZPyLGQBGRYDZ292MSAwHgYK
-CZImiZPyLGQBGRYQdGVzdGNlcnRpZmljYXRlczERMA8GA1UECBMITWFyeWxhbmQx
-DDAKBgNVBAUTAzM0NTELMAkGA1UELhMCQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQx
-OTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFKAtjaBcqIIIYio2ok1SyOUsUH0rMAoG
-A1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAFLRissyZs+HPqnqojWQQhh0T55D
-XWxzCU7sRWi/PcMal+WDZuAqHISXjtIpKsbyQej8YzyKWhqMQOvDEh3vXnCpr9nc
-iSgDdv+2y17ggvetMjxgWDz+JD2faHmYFOQMgBr3Y+tbzcocaYCTiiZV46y5BX6D
-ZNQ7ESa//d9fP0Aw
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7EE.pem
new file mode 100644
index 0000000000..7961ca1f03
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280MandatoryAttributeTypesTest7EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: E6 8E 14 0F 4F 28 27 45 1E 67 B7 AA A8 34 C2 84 FD DF E8 28
+ friendlyName: Valid RFC3280 Mandatory Attribute Types Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid RFC3280 Mandatory Attribute Types EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/DC=gov/DC=testcertificates/ST=Maryland/serialNumber=345/dnQualifier=CA
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBATANBgkqhkiG9w0BAQsFADCBkzELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEzARBgoJkiaJk/IsZAEZ
+FgNnb3YxIDAeBgoJkiaJk/IsZAEZFhB0ZXN0Y2VydGlmaWNhdGVzMREwDwYDVQQI
+EwhNYXJ5bGFuZDEMMAoGA1UEBRMDMzQ1MQswCQYDVQQuEwJDQTAeFw0xMDAxMDEw
+ODMwMDBaFw0zMDEyMzEwODMwMDBaMHUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZU
+ZXN0IENlcnRpZmljYXRlcyAyMDExMUUwQwYDVQQDEzxWYWxpZCBSRkMzMjgwIE1h
+bmRhdG9yeSBBdHRyaWJ1dGUgVHlwZXMgRUUgQ2VydGlmaWNhdGUgVGVzdDcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdZjCEq8H9mVwzW0tJkvsOuE4j
++D3LoEUE2bh5sopUAfj/IOB3xwajLwL3VX4joJQkD/D4efvZKh4pzkHnbC9s82PW
+4HbKW95X1n2s85JFrMYuPGxzD4pDQcHWeptp6NM4iP2nxj/cc3kkxcov30hnk2lq
+mmr3FNXYIJ6/D4e1AgGgZjikNwKFHqiC5b70bZW6QbUTfQ7PtsqsCb2tsLvDreXS
+lBd8pLnB4b+czEFdcgXx9vVPEJf0tWik+k2dO5EbXhEFp9TB4/oOAPz/6J5sniSO
+IkrRfwidMyUAn4/iUj9nzJ1ITJ3ffHhhOpAmEBI9S5yg8ntzwh6zKuxwp/HNAgMB
+AAGjazBpMB8GA1UdIwQYMBaAFPBRGGLvzkHHt7BndGsCvDIKM5nrMB0GA1UdDgQW
+BBQiXTJuQyIRmwrQGxx/oAX3WiwjvTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAU+rnqd3Fx/GnRGW1S
+TkL+CqF8rRHHfVoi+TbwLpbcLltQPiJSm2OzYcPaxR4Q+qbVevA0aLTHFUrKb+dJ
+yX5HIC0Mw1NgEoyMmgqBtxk6qsxawpxtSuiIrqVwC8ZSJA4x5r5OsVwm3BTu4yIG
+BecgzQPToPTzkLpy+miylicd6zUotkx1/fk9H22Noi6CqTea0leemThYEf4UdiDN
+txAI2gGY0++Pg4xS166It6G4VnNsIPF/HV684iwAO3FPGgtxPpu6chf1Z/9D9EZ/
+bVHah6PIQS41hrUKp2dr9rTX4Jbaay8hg9FT4b0Uk4hSJxaDvEO/CcqLjK3HR2lc
+CE8y
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E6 8E 14 0F 4F 28 27 45 1E 67 B7 AA A8 34 C2 84 FD DF E8 28
+ friendlyName: Valid RFC3280 Mandatory Attribute Types Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BFE9C73E2F4F2252
+
+WDp/+1YSU6aYrsDVTkgfP/7jdUE4vXcwtYb8J2Y+4ToItijuV2PLyC3+LDxgdKYV
+N20avLAeuruvWUYkMXpg2KkLfH14wQ716S77yzf5zXSMItZuQhOLAIbziAct68c0
+dCrZrJs8eZ6l7cttPAgui2/8QPF68//fEs7O8SWDVm7vgKfIhacQcpcmJEq/SqFv
+Y9DSlxrXl848ATroZPI6630f2VeBbM4U3+wyS3l8Y77+vhARPJlerQExJgPauzHG
+vur2jVe6CtLHo4bmQu3uVWiVFLVeaycAVkBJVO+PayhC1WZBecuOwuhk4EBMk0Dw
+Wm23QxVUMTveXAbBvoxl+8XCq5WvKK1MywODr0twPMsEs7QzudC4kyvhir0ZTfMQ
+mt5bRtkCyzdBJyOWPmoZ8cGIT3e8yXcVoqwiWwy/i+dQ4EWAUtTeP4F7Fu1n2CGN
+i7Iu9TvYZoeU/RvBH+p1kjdiQx1YsTSxxCMstLoH0+k7WuH6vyNcnPGs1/4/3M62
+3qCPUK+C6O01Pj+wa+hxs1P24SIEN+IbwmDPEFClWk5T9Hg5MYBH2ae1a4DG3DEs
+c4JcAScAjnSInZkBEtAAjpZ0f8D/hDxW8UZ6i+vfgITMIXYqZzWaO0t8RASkTj4x
+F8NC/eC6uWTnfFvEcABDdMQ7TkRzz8QVCHLVWsMBoPpb5XmGnm2maWyD600o+hSi
+03OIEYVsQh09qFTtbnxHpUOwrdjGCQZ/a+VFee3nW8BgUSrax+/7Nv1jX7eFchoY
+5Ma6pYrvPFlD7MQITj9zEhFNy7+DmQ2kWyw0fOaozRVqLpp59jGzYx3ERzmUSxXO
+h3EPTWOxgJ4ggQlKepeRfv9jzI36XMzVcA4kk+hlngNOWkWfFyBO6ZgzlmB8vwLg
+TvHXabA7CE12DzPc0Ydput4abongqJee6I33uZ4vAJSFAY63L8lqm/j34wRSjkzH
+uo7Pw4C/essovBEIAYjgiTS3ZkVps/fO+DTvCiRJAIx9BnebASHFxBmHUyo1nu5t
+DEg9xbK06d6+/m/0S9a/dpAl/nIgXroFUgS+wQAAZ8znJ+OMCzZfyvhFmtNqOwJ/
+OdzSJ9GYXp/qJ4mbFNAzmtMxPRli/kFScaAcKfcDGEmCJOkfglgr6RT+nvYHdwYK
+briRG4GVuSdnRf2BgwCjvpDEFIc8SkWstRydiUj3F0YtcMn/qqz3ee8EUYyaDFMh
+5tfxP7nuV7NlayDIa8eAj4uOMdXHhOpF7yROZbc5fgD9r5rjs18KEu1DJUKGyKaI
+HAbm5Jpwcidw2WLG9I106RcF0tKR+1Y3ZGkK0SwAIKEu77Fadoz6O3FGy7bvx0a7
+547ZOqZXuz8GmkbxXXXdqcI2BJtgxIyXwybfdyefLwRwsWbnQhlTrDQq5xuevWzi
+1NbAToJhf7iVoyqaklPV3wQ/VJTDly27Q7KJjaFdTuGlf8pj7IEDJG6LfX5YppcJ
+Cq4u5Lu+Zsvusn+7N1BBZbNSiNCj0tR83C/muSziuTWtOY23JZvvmHQpJEMKaTyN
+aU0obz9ocoPvipKvPwbWIP67kMHHbaomLxhNmSOwvZYAnppzXXINzwrtImlcu32L
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8.pem
deleted file mode 100644
index fe5bdf3e6d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8.pem
+++ /dev/null
@@ -1,114 +0,0 @@
-subject=/C=US/O=Test Certificates/L=Gaithersburg/GN=John/initials=Q/pseudonym=Fictitious/SN=CA/generationQualifier=III/title=M.D.
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICzTCCAjagAwIBAgIBYTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMIGaMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAcTDEdhaXRoZXJz
-YnVyZzENMAsGA1UEKhMESm9objEKMAgGA1UEKxMBUTETMBEGA1UEQRMKRmljdGl0
-aW91czELMAkGA1UEBBMCQ0ExDDAKBgNVBCwTA0lJSTENMAsGA1UEDBMETS5ELjCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1rYVbBlFi+aAvBEyC1OHaw1KoNLA
-SbwWJQU2M2R18MJ60p/Et24lC5hPnI9+Iaqa0JSHYJ0hY4qWcweJOtNcTNjAgPe/
-jxsQPIOJeI5j0ZDI79wgvj0F7KLW5QKyDbc220ew+FMR2KptqAPxv4exgICooaiL
-M8sOLdN9u/AqLosCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFK+Bn8wZLBKkY0JXV9dXGmMHX3PRMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQBT6cZaPPoR2jyTsaiykedCd4fttTGC/7nzI5s6/riF
-5nxSRhoLM+h8ha+zN2df1xMZao1Ovp6RQGOPrbuPhz8qwnmYrjZ2fdvj47sj+BQY
-xIO6oUyd/DYYwI/nmq3o5bLBOxZDz3qC3AiNFfcfLPiZ2m0eotP0I78nTtDGGUDc
-Ew==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid RFC3280 Optional Attribute Types EE Certificate Test8
-issuer=/C=US/O=Test Certificates/L=Gaithersburg/GN=John/initials=Q/pseudonym=Fictitious/SN=CA/generationQualifier=III/title=M.D.
------BEGIN CERTIFICATE-----
-MIIC6zCCAlSgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBmjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQHEwxHYWl0aGVyc2J1
-cmcxDTALBgNVBCoTBEpvaG4xCjAIBgNVBCsTAVExEzARBgNVBEETCkZpY3RpdGlv
-dXMxCzAJBgNVBAQTAkNBMQwwCgYDVQQsEwNJSUkxDTALBgNVBAwTBE0uRC4wHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBvMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRDBCBgNVBAMTO1ZhbGlkIFJGQzMyODAg
-T3B0aW9uYWwgQXR0cmlidXRlIFR5cGVzIEVFIENlcnRpZmljYXRlIFRlc3Q4MIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBi40mcnzIqaCI8xmKk/hWOkKWbQLD
-++tbFk6jZC91dhYO3PZy1cPsNYJPSz+xSdp/EQz+8TEGRabX2QloXsHxgRZGersi
-xzDg2uh1LS0/k04o+YxsAwJljkd74tub9b0PRX6MzqsUQgy7SWnPvQ6qKJ1uZ8B3
-UJYb/Jr+Jb0BDQIDAQABo2swaTAfBgNVHSMEGDAWgBSvgZ/MGSwSpGNCV1fXVxpj
-B19z0TAdBgNVHQ4EFgQU1AdzbqWGvXGozwcQ3FLKcM0NhdQwDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQCm
-53CaFal2YrwuX9JDOKgfEISGgoAdQjs+hoh0T9fTKMeyzfuEaajj4gKD7YViPd5Z
-SbbTywQKjzTDTP1PiLf7ti3TbOzHmPCT9sOcSMxn7ws9Q/KV4SvNjpYK8W6YPn6r
-WSMe+VuZypOlb/vWxOgHPP5IIY/4vqVjulA0tcqP5Q==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/L=Gaithersburg/GN=John/initials=Q/pseudonym=Fictitious/SN=CA/generationQualifier=III/title=M.D.
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AF:81:9F:CC:19:2C:12:A4:63:42:57:57:D7:57:1A:63:07:5F:73:D1
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 92:2d:88:30:eb:90:92:74:63:32:0b:b7:99:52:78:83:ef:a8:
- 8f:33:89:b8:57:ff:06:f8:f0:41:20:77:9d:be:a9:98:10:12:
- e3:80:bb:b0:48:d2:57:93:be:3b:b8:64:f6:9a:91:05:05:df:
- d4:97:6a:a1:c7:29:04:d3:e6:ab:63:83:99:c1:58:87:8e:ee:
- d7:85:1b:f7:d1:8d:2f:34:c4:a8:77:c3:5d:ff:15:2b:c5:14:
- 47:f8:04:f4:c0:a1:3a:84:07:0c:a4:97:0f:02:f8:ca:07:52:
- fe:42:29:ff:e2:9a:01:e0:ac:1f:4f:e1:15:47:6c:71:d9:da:
- dc:02
------BEGIN X509 CRL-----
-MIIBlDCB/gIBATANBgkqhkiG9w0BAQUFADCBmjELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQHEwxHYWl0aGVyc2J1cmcxDTAL
-BgNVBCoTBEpvaG4xCjAIBgNVBCsTAVExEzARBgNVBEETCkZpY3RpdGlvdXMxCzAJ
-BgNVBAQTAkNBMQwwCgYDVQQsEwNJSUkxDTALBgNVBAwTBE0uRC4XDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFK+Bn8wZLBKkY0JX
-V9dXGmMHX3PRMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAJItiDDrkJJ0
-YzILt5lSeIPvqI8zibhX/wb48EEgd52+qZgQEuOAu7BI0leTvju4ZPaakQUF39SX
-aqHHKQTT5qtjg5nBWIeO7teFG/fRjS80xKh3w13/FSvFFEf4BPTAoTqEBwyklw8C
-+MoHUv5CKf/imgHgrB9P4RVHbHHZ2twC
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8EE.pem
new file mode 100644
index 0000000000..fd69deb001
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC3280OptionalAttributeTypesTest8EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 70 05 A8 EA DC D1 2B 2B 4F 88 9B CF 8A BF A5 7A B3 2F 23 06
+ friendlyName: Valid RFC3280 Optional Attribute Types Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid RFC3280 Optional Attribute Types EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/L=Gaithersburg/GN=John/initials=Q/pseudonym=Fictitious/SN=CA/generationQualifier=III/title=M.D.
+-----BEGIN CERTIFICATE-----
+MIID+jCCAuKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBnzELMAkGA1UEBhMCVVMx
+HzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAcTDEdhaXRo
+ZXJzYnVyZzENMAsGA1UEKhMESm9objEKMAgGA1UEKxMBUTETMBEGA1UEQRMKRmlj
+dGl0aW91czELMAkGA1UEBBMCQ0ExDDAKBgNVBCwTA0lJSTENMAsGA1UEDBMETS5E
+LjAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMHQxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMUQwQgYDVQQDEztWYWxp
+ZCBSRkMzMjgwIE9wdGlvbmFsIEF0dHJpYnV0ZSBUeXBlcyBFRSBDZXJ0aWZpY2F0
+ZSBUZXN0ODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnWd2qWpNr5
+EB4D/X04sWYwHk2O/sNfaCRnyPOdRa04rEwDbcqICC6y40U0nyDFc0EzBcCHVqts
+Cn36EI4hpnibj2BRybDIo2Ntb2PH6z0BbQUfPY/X34yJ+k9uFEBRRL9gNyQQH+DB
+mgN/HoQ2UOiGvmdNJY9Sc5f3srgi+0TLs4W0kaeW3l1/aFImKPBXIE6Dwhqr8x0I
+i2MY1piu/TN6llFXukOkz8cZihj8hetOPNTJPcSjQ/LB+WQpfyQ2RsVlpIhy0tf1
+PpBpWrc9Jljx11MT0uHCJ6Agq/cqO9NxBWR6NN2rCRq+8JwOgBNS+5qH2hex7taN
+QpedWsWMxk0CAwEAAaNrMGkwHwYDVR0jBBgwFoAUm25vP4qn9Oe1jDFbzplLkRx8
+fL0wHQYDVR0OBBYEFFo1tItlb/GOrVNgqo0jnqVlFChDMA4GA1UdDwEB/wQEAwIE
+8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBACLn
+LA2yu+fl/z6CAe91RJeh1g/9ffXA81W2NjqtgRF9p3ryT0M7ZVhVd8qmN4ZbTB+O
+lTTIgspdcgCFbX3SzH6MFOHmTmIug7hsuBkR6xhs4fGbGb9MqbAbcsUhqNSC+EQ7
+35+ti62crD1Ew83xhOn8rPqCfKj8cRlac15f5w05TItgB0v4/laFMQwGGvJcvGkQ
+j8iWgV2SRug22qujOb7ZH5rTJJLWvZ6oLNasiyB+Fe6ExidWRU1YKmFNWrP1OEe4
+Hll70oWjXGLo/Ilkw8dJDe2wxLgktazED5eBsqfS8wPCTHkaaM/YAcbDmlbXvDED
+Rk8uUmjfR/dHOtIdEb0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 70 05 A8 EA DC D1 2B 2B 4F 88 9B CF 8A BF A5 7A B3 2F 23 06
+ friendlyName: Valid RFC3280 Optional Attribute Types Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FC39EB1A890FB19C
+
+mRBIoUlt0n541CPYW0DGxjQbisdR/qik0jn4WUzTQjFUhDqZCS3jox+lVj3+2L0O
+EogtwLej0FCZbv5Wl1+cGTSRnRWsTMcrZF1vUPxbh5AyGyAkHhvkL5VeN3KvQD8n
+GyRE92RwD+UiRcmSNTnN1tzcfUF5WP+ggGsyhqoMh+8A/a7q6fKtKTqA3a0PgMtC
+G+OxoAsZnQbmV2djG8aayd8C84mZtj29qSyzevg5ubYbU4zDFHEJ75tZivxTNWe4
+rgJtTDioizLuuiLZW4lgC8qIZIto49NZxW3NGI4uNf4S9YlH6pwg/WgfP8uDt5BU
+Ya9b7isJkgpkaaB3UaAignwvmxbcK/etmEI90NNYJAo+dNX9vSJgr3tPWD4ihnW5
+t2spd3+9kLHz002tGh8nNOUVSPp/7sBgJZAdCTDBaD3Hn53zcNxjzhHyI2KRi6pd
+X5iU8Ull5ymv7xX2a7hS2nhSvluknO3FrgQboEmZi68RQ2q6TLF3zurUPpWR85iP
+J3ISxm4Np3m1SpPXWyJDc0WldWvo2Y+dqPXhg37nkXw7bkwrCmBc98qzVLGh/iRf
+W92SADj6fLeQjSDF97ts4/Qt9VOCrRBOY8hrOWuFJ34kNbMRqxpruBfRFmizdGYZ
+CzSSSwr5aZCYAe4vMFU1fRO3If2oAzF52IGSpRKmXVvDTU6djW7JMieKAqWWGaQm
+rlIZ/061su9MzGXVH5VF5Fbeooavm7ir0FaMVYhTmtdggo4F61zBY6ubtCQg/9lX
+oQjKc9XADM58zIWk+M3WMTGquaEs4ACcrx34l3RolC+B6WicQAAqq7KcSULahufG
+J8xteOpQ185qRdOVfSBQ/DfRE7cD4CXJvt68uPXn1ts4i3KjU5k//KAr6uVfWOa1
+TNXO1G9zTDiVATXU4NK194ECyVTLUVJVxAGTc4RaVkJOtq9fTn9b+5e3a5kqx25w
+Vwf+bidlEM8U8QWEWrE+ro78v+NSjTAZADR+LfsAqbRLRhlBVyCRFn7VcYDXx9M2
+N32euCqAKZCP/lrKyvk7Ag271IMy6CkTKOVCnd07oR/1LJQFQzUzOrK0oePuUEdZ
+0fm6ErCioCEzPRpq22dEwsZ24axn1AQDeZ7UA0ZId4Ll8e8XALne0LJKr+ydyrjL
+vmNPFXp49+igvesj1K+uBIkp7RsROuh5A5Fj0gq1oAtKGq6ypu36KwJOSFPl8zNn
+8twsR1yRCbgGZreA6fO8lo3lv+q3FvRWWLX10p+6OaOSi8Wh59+R1q1b/BgC2Xxy
+cwdvLjOhf5lPn9kWHyZHaTnhBRn5AgwiMZIJS0u61b0nLBefglIKYDEdIXWVTSLa
+QoG6N6SkcCcmgwEsE+PA2c3ZVFXfjhCaxdBp455cPtPiJSbdBruoNoZrxM5LFyGi
+wG29/Dz1CegDwQkPXLdliDc70ycIOJLWCeArXAcnUJY/JsowtGxk30r6Wufg3n5X
+DSlWR3fPgiTuKXOU/AhTTzxc1QX+fPpU0dyXD0veDDJBD0LVWGxYj6RO3YB28YWv
+9DgQ8hYM8awbiDz2GKg5bp63PFtPHVx94OuQ/yLVDhs00emTM0fsMA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21.pem
deleted file mode 100644
index 0a271fcdc0..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqzCCAhSgAwIBAgIBQzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMabmFtZUNvbnN0
-cmFpbnRzIFJGQzgyMiBDQTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOYG
-d2HszTJIsVTazKriCUJ/ExxUo4U4HEZN9+/XVXsQVkZYIzWtyCTC3IFmSAyb9ZED
-Gu3jmF/evXpfNXmxiURUu6W0bLEpIkZiVpPpTKqoJx2EHj+wXOfe31AD0OmKidXP
-66+LVgIJLWGMr3Msbzb4T3gpKb2ynQc2/XnE3RkbAgMBAAGjgaYwgaMwHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFON/hXqOojue7rgS
-HXkTqsS9LlmtMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAnBgNVHR4BAf8EHTAboBkwF4EVLnRlc3RjZXJ0
-aWZpY2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GBAJjXEGmrQ1/Muud+NZwajR9x
-it/32SNVvHI+/O7bopout/RnhJudrmsdqGlcSk0KXfcXI22cJOkAYe1M39znxgba
-VitYYLxfsS+3O2pLpMgQMFCZuOJATfAQUlui+dVtPTaIam7jimms5Qam2K2SuZ/t
-eJ2J/rIDHCOrIGktQS8H
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid RFC822 nameConstraints EE Certificate Test21
-issuer=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA1
------BEGIN CERTIFICATE-----
-MIICzDCCAjWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBSRkM4MjIgQ0ExMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-ZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTswOQYD
-VQQDEzJWYWxpZCBSRkM4MjIgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRl
-IFRlc3QyMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmgblTsP6gle2uacP
-DDJPff0VnqgTN1VtCh/uqZINqMtzbfcADz7KNpqETX64spwhD8/3m9yEVpJStgPq
-o/mbcf/G2L3+zkx2t7mQLTy115q304S7KBauhK/aen56yKrHOuUv+qmOSYpqZKwi
-ZbobiLq/CMbUfYx6zaM8Bd59VBsCAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBTjf4V6
-jqI7nu64Eh15E6rEvS5ZrTAdBgNVHQ4EFgQUtCANQs2V6ofUY9VPDtbRD+W3O/sw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAzBgNVHREE
-LDAqgShUZXN0MjFFRUBtYWlsc2VydmVyLnRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0G
-CSqGSIb3DQEBBQUAA4GBAB1qFEM9zKmqItkLPuorp06yLsoL0xL3X+c4ym7JP034
-2kYhJ7SoZFmFbIRB6z472KWbJc17oM9LK6GOt08QBEIHhQk1pZrueBJDrCv8WmR3
-7FHwbkNcRn8DFYiV3//yjYP+bgN142Lj3O9SpuUy/a32bsupo0ykWADqwwY1ntmi
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints RFC822 CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:E3:7F:85:7A:8E:A2:3B:9E:EE:B8:12:1D:79:13:AA:C4:BD:2E:59:AD
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- b4:77:73:f7:12:e7:d7:20:9a:bd:e1:00:a8:b1:6a:7a:65:1e:
- 8e:56:c9:ca:38:33:7e:d5:37:41:c1:e7:95:a4:81:ab:9b:40:
- 31:1d:aa:6c:14:f9:19:e4:3f:85:6b:24:ff:d6:bf:cb:fd:27:
- a9:65:35:5c:b7:6b:82:87:b7:e1:c2:4d:34:ca:42:5c:46:66:
- 45:11:d2:c0:48:0f:08:8c:b0:a7:58:66:63:9d:ae:0a:68:0a:
- 5b:5b:ee:fe:12:93:77:03:90:6e:a4:8d:32:2e:56:56:cf:1f:
- 85:b8:95:52:f7:73:78:5e:d0:04:66:2c:8c:ca:78:36:da:43:
- 10:07
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBS
-RkM4MjIgQ0ExFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBTjf4V6jqI7nu64Eh15E6rEvS5ZrTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQC0d3P3EufXIJq94QCosWp6ZR6OVsnKODN+1TdBweeVpIGrm0Ax
-HapsFPkZ5D+FayT/1r/L/SepZTVct2uCh7fhwk00ykJcRmZFEdLASA8IjLCnWGZj
-na4KaApbW+7+EpN3A5BupI0yLlZWzx+FuJVS93N4XtAEZiyMyng22kMQBw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21EE.pem
new file mode 100644
index 0000000000..00a5e61442
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest21EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 23 43 2D D2 5E 36 CC 16 FD 86 12 BB D5 0E C8 08 99 18 ED 9A
+ friendlyName: Valid RFC822 nameConstraints Test21 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid RFC822 nameConstraints EE Certificate Test21
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA1
+-----BEGIN CERTIFICATE-----
+MIID2zCCAsOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIFJGQzgyMiBDQTEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBrMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE7MDkGA1UEAxMyVmFsaWQgUkZDODIyIG5hbWVDb25zdHJhaW50cyBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0MjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQC5yv2YRIEhQf1yjI/+8BH9zoj+WkwrpoJikq3h9IAR3QF1b73DUngYZizZoxi4
+zFK3hJIaln6yaq4VLKImcJzGwf2H80nYKD+cKEo5vFiG9qnm7m6so2sUDT5YYW1w
+rGHDO3qJNlzF3R9cM4Fm/hi7UpABHwWqJ4wApX/HkPg0DQ0JXsgnCS4vr+uIgCbY
+m762QCDH8YvxEDWjj/xy/BhCVb6Rzb4wzJE9DD0+8+Zr3UVKhoPQWsNT68JFLUd4
+t8lMndnhGqQj01atU4lrq1T4bXO4USw4WUYM1Eh/9KvTfRxBlIvrWkEe5UamC1nT
+HxlrUqXfSg+69bXgh89wKqCTAgMBAAGjgaEwgZ4wHwYDVR0jBBgwFoAUyGqOsQ9L
+qqWIuKePkdvqM0ro1eIwHQYDVR0OBBYEFGYJoy8FC+jXyi0Q7O4CokLJZ2PUMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwMwYDVR0RBCww
+KoEoVGVzdDIxRUVAbWFpbHNlcnZlci50ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkq
+hkiG9w0BAQsFAAOCAQEAPS+Re8+Y16TsC07sv0TLKtOFqh3WUaKg0drF7pmruJc3
+xmc9ACF5aBvAOGA/4cVaVQ6qEtA42TcqxRj4RJynb2p6Ay4DAVRYnWYeYH6rjFOH
+a3xE8zXCrUUGpnYYP27plJMDhaM/uR3NUo7Tp9MagVqv/Iv+RUUQi7Hj8vWg5J0q
+ggpJApU8GeqyPsU81Hh4ZXG9go1iQN/QH7p1uYpf4OImMTfsE6RvV1UXNX2fiANt
+1XrEyeYyCl0LEdoo/+vZmEj7XuBpVTHTdFtGDfnzzWyLg4K0J+1ZIsHXtivhnrSY
+aM5R0nE7+ziQV9S6U/zR62TrkQ66aMoxzN4SHgYD2Q==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 23 43 2D D2 5E 36 CC 16 FD 86 12 BB D5 0E C8 08 99 18 ED 9A
+ friendlyName: Valid RFC822 nameConstraints Test21 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EB8AB9A7AEE01546
+
+UZAlaUbmYe/AhCF0Q2dNOjEozcyEB8Ehh/EZCOmsO8vgEbaUT06tbiqpnOJBHdVM
+O9ke33cg54p4g88LVCQWivkEopFW39r40Zya3R6GBP5ewbr/qIIxA7IbDpUhugMe
+FARBWk/521qovA3qcp4hB5PtRIR0+aVaQNe+iEISRMrBlr/87u2rw+shuQnP/K/V
+optX+6PVMQxTiJRMCaJ6EgAF7bgU0ti/3/1r8MBUqpkMEHUCbu/v9i2YdfGWKzpD
+DgL0dw1b43R9hPOR4vP+ytBp3hltSXvqeg4o8dNkbqqqG/Gb5+X5W8de09AsuBya
+rS3xhidIq/L+EclCKCM89zVcZlbuf+wCPGw9Ob8FPIDASw3hk9RCHg/rlXoBcHZw
+uzU2mrsMV4IAwK9ydSAit42DT3FH/s6WlePt64FRc7kMJCqA83h6pNa2f+kKKUGV
+SsIfc64I+6sJWp4qN+HGTQm4dIp0U6upBkMKogwrMtB4rPmGRCxyEK6TGrVj3NJw
+P2wwyKhm9CxsCF56lkDuBcOqUGu473Pqm9ylZ6HaNF3nMShYL0f2N//5w9OPbBUH
+lFWWXj/RVTBnHjeiFKAjJFGyB4kTihC2tzwbufT+o0TV+bq/MTYjsN+9+bm/vC4M
+kVrvvXlRMVOUoVKBqTSWeSD3pTnd4FQyYivNQdss8w/8LHXCv/VTA1IjQwiBEx6q
+KKAXXCXXrN3rjaEMrpov1tEztDHn9lBX/clH4whJ+AJ3Sdcgolcuw/9dhxRFfG67
+XK8QPDnUL3YGarueoOaQloneUHTJSEEsVFaMk97S1oAfOzW0cjizWGHYQU4RRBJk
+4c2J7opvGlpci2LeGb+4ZWvJ8/qLGmLPwtmqNgNWXvRRvs8L0I9KZqbgQ2bGTSWJ
+RSx+ErLDj7qw88xF54DJuivLaREKctKzkmWTSAJq4oWh3bbeSKO4B3HnrE3YRkEK
+SfkspCCJmEhrXT9qQ2wz5v4lqO6VO5PZ1NDGIKcxRhNatjFHQ5smCaN/ek2mWIFy
+0o8sLsVojXVAYqHiBaDwjJs30MEQIliS9sUQOqQb9DPg3Tjcjl0/yLYF/WA41KyA
+SWdNIZ9uRTJeBjoANDseUNoAnWXus3aYb+ZIhgugwqwVFX5FSp6vjxXBGQaiYuz7
+tg5u5oO6BZpVfb0ITuRWaZWbbkoN+nPKoHOgY4Zd0P5RnLfJMHCrbGotmSleOcj1
+zWgZEsi0yFU/GobJUYHDQshKIG9JIchLCHK8/gtXN/rat7JIFdGDcQlYHZn9UpQS
+iC+vFmfwCkhMmNBs2PRIt6aCAeYSBSuM/IXIVhCxyGt61NkppuKcx98/7s5DglBM
+AKSxyGwiyf8Z3pQTIczcDhsjJobD37ygmdGLuOlrVBbRRbttZiPTwq2t+lJby7Zt
+3+STA22gzy3LxCWenKg0laVanUfdsAZGF0Z02JiZFInA5FlkFee9rrjaaAdWtw5j
+A3Sc9/0r/rzrpkZqJKc9KHW3DeiJhh6cNfPyRAgv0GJw3N9S6Y0Zc/jO1n3rIk+5
+wGsXZEim6V/2ejC+As58ERaKI6y71v3Kj54yUKIpvaCJkT9TmLnnpw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23.pem
deleted file mode 100644
index a73a4af25d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBRDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMabmFtZUNvbnN0
-cmFpbnRzIFJGQzgyMiBDQTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMPZ
-S8+5+/2AgG2N8tsByPeKGxCC5bOrNXho0b3fSjvK452P3luNUPIf46KvIBU6UYAP
-4rGMqcUdmgFD+PdXq6TMW8bWNuYRICw6c6ni5uyre5bovptoJCsmBw/IqinDoqbO
-Qyoq0YDltds+lSROlTUCA/7qOBHOdwpcjhVfYJSJAgMBAAGjgaUwgaIwHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFBQbKzZmdEuTqzFV
-h6QxqzZjbzXJMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoBgwFoEUdGVzdGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAsOYxl05xGFDRHUO8Myp9EM/X
-ahfChzUabmgo1Tqpk+TLbxcZw+GfesxOp+jCd7jtTBJKhB0HeX1vaCVUpURbWEAt
-fuE35slQQr/c9dgwCw/JwBNdkFFT2z/73nDEN96rUK3GYs2OO8OJVMqdKb4iBUxH
-M/bZyCy4CB3+hthr4to=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid RFC822 nameConstraints EE Certificate Test23
-issuer=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA2
------BEGIN CERTIFICATE-----
-MIICwTCCAiqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBSRkM4MjIgQ0EyMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-ZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTswOQYD
-VQQDEzJWYWxpZCBSRkM4MjIgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRl
-IFRlc3QyMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo+cdyq6LQoFUo5dS
-h+bsp1TvEaw5776yXg8bXkMcTO+fJGshnWYoTUk7mQwcFnYm5+dQzSLHZTh9dgR5
-5m9ZSKGfmbnSINvGuU7oo9cqEwKrCRzqj/X6MUoyaxQyDW/ft2mTXpPCGrzDaF/S
-52lsNu/rubHKKmmb4EaoVJaWHUMCAwEAAaOBljCBkzAfBgNVHSMEGDAWgBQUGys2
-ZnRLk6sxVYekMas2Y281yTAdBgNVHQ4EFgQUDEZstH+dSCRcJPrmvd6knN2jPfIw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAoBgNVHREE
-ITAfgR1UZXN0MjNFRUB0ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkqhkiG9w0BAQUF
-AAOBgQB4NROaQv0DDKJDl5t44LQ0cosk4/w98WmDCkXF7RVxhFFMApnHJBOQlEPQ
-CnC/fGcChW/KnYKsDnCSAPJiq4D15SYa9EVMa1rw7wCotCVbvjfJezZrheKmMj0Z
-nxIJIutwJ6pOY3gjJRxCRNx18S1u0vhD93uN36wKM1cuWaA+8A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints RFC822 CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:14:1B:2B:36:66:74:4B:93:AB:31:55:87:A4:31:AB:36:63:6F:35:C9
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 47:93:cd:d6:9b:31:b0:dd:6a:d8:c4:e2:5e:3a:73:cd:2b:69:
- 5c:47:1a:75:56:6b:56:1c:a4:2f:c2:66:4c:6b:a4:9a:86:53:
- fb:26:39:3e:61:d2:14:1b:85:1e:9c:f0:1e:ac:c8:c1:73:a5:
- c3:29:1c:c6:12:21:08:4c:4a:5a:d6:1d:21:4e:eb:7d:16:14:
- a4:a8:18:07:2e:e9:31:ef:39:ce:f8:6e:2b:d7:09:c1:ad:be:
- 6a:c3:d8:46:24:95:12:ea:cf:2c:c6:84:50:bf:78:31:91:79:
- 35:8c:02:47:d1:11:0d:aa:55:34:22:d6:d4:a2:ac:be:b8:07:
- 60:3c
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBS
-RkM4MjIgQ0EyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBQUGys2ZnRLk6sxVYekMas2Y281yTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQBHk83WmzGw3WrYxOJeOnPNK2lcRxp1VmtWHKQvwmZMa6SahlP7
-Jjk+YdIUG4UenPAerMjBc6XDKRzGEiEITEpa1h0hTut9FhSkqBgHLukx7znO+G4r
-1wnBrb5qw9hGJJUS6s8sxoRQv3gxkXk1jAJH0RENqlU0ItbUoqy+uAdgPA==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23EE.pem
new file mode 100644
index 0000000000..c15eda6bca
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest23EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 87 06 91 82 82 EA C8 C2 CF 2C 97 9F 19 BA D4 A5 3B 4A 4F 57
+ friendlyName: Valid RFC822 nameConstraints Test23 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid RFC822 nameConstraints EE Certificate Test23
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA2
+-----BEGIN CERTIFICATE-----
+MIID0DCCArigAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIFJGQzgyMiBDQTIwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBrMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE7MDkGA1UEAxMyVmFsaWQgUkZDODIyIG5hbWVDb25zdHJhaW50cyBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0MjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDH97Obgu2TXLwsB+kAldNq3ukQyHc30y36W7dtTniOxGsEMu0pAGqDCLjHvAcM
+NnebR8UQCYbwW5ooli8mhSBwbic2vrs4ox/Zm1wSePT4QlcIme4mru3mL4cDx9jK
+gaRBsa3pOtanpaT2pcK+9PK1RPJiivhLwdBdg5u8TQ50te+QJpbveTyNEP6fd2d4
+0B3ebPIGwxnAZ1OJw8V3nbH4yrGsxHebvPkTooDkTVOW3OkWG870k2m4UgQTs0bK
+Cr6nfMZLh9UHHHSqkhKPATYBUEC78qGG+dJCYmv2ufkdD5Y53WmcI7I0ox5MDBOi
+PProYl1M1eoY3Djq1G522kJpAgMBAAGjgZYwgZMwHwYDVR0jBBgwFoAUUYDN+kly
+SDztDk4Lzs4fQGUScKAwHQYDVR0OBBYEFBekOG7BL12uA/XHxR7u1gLCDUlLMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwKAYDVR0RBCEw
+H4EdVGVzdDIzRUVAdGVzdGNlcnRpZmljYXRlcy5nb3YwDQYJKoZIhvcNAQELBQAD
+ggEBANk0lkglDUSef6Hd7yu/Gqplwo8xx3HVg9x/+T2pIKeK+hd+K97gt0ZEzjjw
+5ul4LabIQFLS2hpT0F1jc4tjfh4pITMW6LAUzAae2LFbHguO3nb3X7/gSP5Bm+7x
+Ppk9eZHoIDFqKKnXbzezK/GOIjnK4zr1u9xVOqFpjwjVgXdvQ1EvjydJwrwcygEX
+u9OY5AUCZ2I+cT3K10Ms+bnupLizv7HCcQuQRLBd0B55z5MtiBhwiju8qJzxoX9V
+hUmOVgSzYdLKZRPlRHzNmZoE3wi5cg+8nIZXyk/+CrZGrbN51P54RvbdDGohocln
+egEMHQLtjaba5v5XxfpHPn+wqyE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 87 06 91 82 82 EA C8 C2 CF 2C 97 9F 19 BA D4 A5 3B 4A 4F 57
+ friendlyName: Valid RFC822 nameConstraints Test23 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,82F1A219404E53A7
+
+R3BFruUHg/5j2+w+XN0/4SVJdWqtKM6U9AiTd8nmxoz99xNvQCxhyhGlcLU4Fhjn
+ED37DGduwuDNnD0xXk2KJuy5lCj0NMIbIiTTTg211ECGNet8/fYMjJ1xlnbAcdJV
+w11InQRl/hYPLkXrjQ7VJD8EiN/KdLkMRLTBVCzlHqIrwrkLWUJVXQzpMYfl9Idu
+StD0y/+dzqeGNnI2c37+bTzWwgpks3E0kor/3SxmYkl4p8bJb5TEro+24Rr/SrdW
+H08/WEtJObqdAcm6QKQXF5EQtmUk1j+2dAT6Cc5bhGpfzjE8nUbUmLzo20qv9VKs
+ff3c4f9mWBXPIF5Qvp1YYzXElHn/qiy1H0o19xSg1tiOIfqsSqnwYltyQBbrAFjZ
+WhZor+SWdUT61uwyuwOySEOS0VHKARCptex5lyPWsiyRs+pyCMd9uH64fLGg+w8U
+6qZ97C6XlfDHT19w04CrQkTSdYav8xqu2PJxKeFBmREszayXUQP33owh9bKVb3nd
+CZVPykBAZJgA5R6ajjvqHhUe3ilw2DZ+XB0QOgSf2XjK3gnpyVaygAh5nExUeCG8
+IDojFKEO7ZK6RodfWA09jeASttvwgFLhrWcNl+y5SGj+Bj3h9Ae7NrPxbDvXfID4
+JeAQ9bsAX2NdoUIJT4tt3ZLV16qoEDubDUbTeKBK/WFk7DeSBUM3TMsMpqZVhDIZ
+neKPt3W+wLQ/YywwaF/+nd2Y/g6iKFQUvK225WJBLqnww41O9EFgrJBGTJ8r2G43
+rMyjY9nHZG8Mt8gasR+0Gr60SG5ZSTv7WATFIjWacptwQYqNPG/aSivz+q+kypUV
+wq3jIJ1nD2Q6Z+JXmkJBdxrFs0OOfjpWxl6+YhPYBed4pUy2J+PtNQ5gfHcBfnZm
+1mutaMCAJeRLZ20YP7zjqUMbmPoHXqWrYOGH5fna5jjRj/ra2E+CULnlU1c6WES6
+qspypZeomFoDHA8LthhKPWQfyKZ+d3a4AbV/RWG85pEkN/Nq9dmk0We4orRi6sm9
+p87zabdO7+FacDYS8L2jLBpu7zZYUqLBIa4wkUEHKK9iuCzs4Ce6q0pX7JcQuEbX
+RkggqEXh9GpR1efuvZkr5c1CXZ9ib1mKO5fc4OctMNw0nea467biReXYXgZZ+2jZ
+Gx8zOGZS/r/DtCWu8BNdcM6flNMi/ZOcSODRGkuvQEwp/xVO8R6xAaGbR6LIzGRw
+nR7SZm/o4ua9by+Avs3A2gmfsgThOR51BOdV24y45h7JiEG8227ujkQs8RHORWu3
+gIoKZ+Q9HDfwH7v+3NaD/r9U3DzUKmcJVj/JLIIXpyMcQHUgW7o3ZzfUDqOd5igm
+dOipz8FDrjmIOz4ZvOKznC/TiPuFc4YMyjp4s3FNrhXegkHavA2OG/kIZ7IhSx0j
+ZJl9fJ+NiJwTK+OX9wQsdA3qlfV2MgvB3Sr4UFVQVeIPHcXhHSuRivzV+8cQYCNV
+PyTNVADRci2QJ7+IYZEv7gEwT2BCZTnriEEEkzxKNARlpQ/4UJY4mdP2aY+1MGaU
+YUaGIN3f80Yh2WVKR/H43lWTR2w5j5P5HU130JQ2npXCSDsSHoGz0rbGNyftAhuQ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25.pem
deleted file mode 100644
index 10308cf5ee..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA3
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBRTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMabmFtZUNvbnN0
-cmFpbnRzIFJGQzgyMiBDQTMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMii
-1odFMCSlNLo+1reNBLAhQ3rkRllmPUUfznMkHE+tVOXNCuGNSPuCJPQNO5495PH/
-vsBZUVltMrhOpo00ibzoFrcLwaxj5Gmb8rNV/aPwDiRX8frLslhpw+QEjxMZKP8O
-bdOlItBR3dFauvxrwLz1DUUlG7aX/QoEtws/fE59AgMBAAGjgaUwgaIwHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFOq3bporCYA2Z2m1
-jdo1pYY9KXgcMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAmBgNVHR4BAf8EHDAaoRgwFoEUdGVzdGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAcyB2R0h4mQZ671JhQ0r6cmPF
-iaEHtdJL+REJT8yGWiERgT/2wh65vHtCierHK8+0aJ8Wy/nJzUAWcKeGESTPVTey
-IxQg08VdFJIohXm1lvJ3hfzgHIcFPk2tXZvYSk3qYllYHt8tGCoyh4p3q4vpyTou
-HcOOTD0ogzE9KbjD3Dk=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid RFC822 nameConstraints EE Certificate Test25
-issuer=/C=US/O=Test Certificates/CN=nameConstraints RFC822 CA3
------BEGIN CERTIFICATE-----
-MIICzDCCAjWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJh
-aW50cyBSRkM4MjIgQ0EzMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-ZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTswOQYD
-VQQDEzJWYWxpZCBSRkM4MjIgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRl
-IFRlc3QyNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAjlu9aIQ7cGou9j2L
-/SEtM4QWvsfK7siztqNkNsuSWFgr/pOI6y6+WOa6B1E+I7zZryvHOSmqtpBzPOeU
-RX19iAHjT3Rf8LeCHS75XCCtVUJJJ2+pJn8hON1vHSQGgHzD+kOPIOwj0ihYD1f9
-xUMHM6MiPsEODMVFGitWAPl6P88CAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBTqt26a
-KwmANmdptY3aNaWGPSl4HDAdBgNVHQ4EFgQU/PF5qIYkniJoxi4J3d64bj3SNwUw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAzBgNVHREE
-LDAqgShUZXN0MjVFRUBtYWlsc2VydmVyLnRlc3RjZXJ0aWZpY2F0ZXMuZ292MA0G
-CSqGSIb3DQEBBQUAA4GBAEwywYR5b8qm30lTjdBl+YvBheITfKcGdkhFRgdAZ/qg
-IfBhWHt3xf8SXXLMoEk9jhuyJ9JGSLY6psPYhDhkqswRkPhJgx5yOc2D05JI0CEU
-RSr9LZE439pCWHI/qFp5e0mvQEJthMvapGETXniDUlnihFlzS0Wv7pzlG9JbHmz+
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints RFC822 CA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:EA:B7:6E:9A:2B:09:80:36:67:69:B5:8D:DA:35:A5:86:3D:29:78:1C
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8c:6d:0a:0a:c4:67:91:af:de:5d:89:9f:fc:df:e2:7a:7a:52:
- 3e:4d:ec:50:b9:46:83:3a:7d:2d:9b:5d:84:8b:6d:ba:bf:4b:
- 41:74:e3:3b:c1:90:73:a2:83:02:4f:e4:04:b8:b9:7a:70:7b:
- 0c:bc:59:f7:db:83:93:00:87:98:53:43:a2:71:d5:2f:d0:fe:
- 2f:c2:46:55:d5:64:54:01:90:72:4f:a2:37:dd:88:b8:3b:63:
- 24:df:d3:ed:7e:6d:da:2f:57:9b:cc:d7:96:67:48:7e:a5:b0:
- 6d:cb:c9:5e:e9:78:58:c6:be:f0:cc:b1:16:e3:4a:57:45:86:
- 90:12
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBS
-RkM4MjIgQ0EzFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBTqt26aKwmANmdptY3aNaWGPSl4HDAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQCMbQoKxGeRr95diZ/83+J6elI+TexQuUaDOn0tm12Ei226v0tB
-dOM7wZBzooMCT+QEuLl6cHsMvFn324OTAIeYU0OicdUv0P4vwkZV1WRUAZByT6I3
-3Yi4O2Mk39Ptfm3aL1ebzNeWZ0h+pbBty8le6XhYxr7wzLEW40pXRYaQEg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25EE.pem
new file mode 100644
index 0000000000..cbd0c58a71
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRFC822nameConstraintsTest25EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 88 BB CB FD 18 80 A8 9D 52 3A 36 D5 FD A2 DF 9A 0C AF 02 29
+ friendlyName: Valid RFC822 nameConstraints Test25 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid RFC822 nameConstraints EE Certificate Test25
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA3
+-----BEGIN CERTIFICATE-----
+MIID2zCCAsOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNv
+bnN0cmFpbnRzIFJGQzgyMiBDQTMwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBrMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTE7MDkGA1UEAxMyVmFsaWQgUkZDODIyIG5hbWVDb25zdHJhaW50cyBFRSBD
+ZXJ0aWZpY2F0ZSBUZXN0MjUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQD14E0HjPDPTkFDMDJGgWqJtdxDgR9z+/bmgopcNwzghAjljVUrFEJ/WIiwcqty
+QonLqNdWtdXrI/0ZuAEhEohgCTIv6xqlhVmryx8w+J1N3Bg+fTlhymbihunTV7BG
+8iGjnecbPaMJ0H5Evgi1XBruq9ALU5UHsujvPcRnlJPToOe5K1RSdDK2trDPfxMV
+zapzN/pIPSnuZvjPiF1TaRI5fEd8yNYhyIoDYU+W4ZCbqOhTmBUGnKde1dNWtMhH
+fFLGWgbbTt94ZK1oHAHAojeWL/bC4WZn7xKYvf4loyiUUPvL9Z5LL7cFJfH/ww1/
+N7ZzlE2Uln8y2vJyg336IE5lAgMBAAGjgaEwgZ4wHwYDVR0jBBgwFoAUmro5Tdoh
+da/qQcM8bFHYqEWpf6MwHQYDVR0OBBYEFCSLs+Nanik16QFtO2bqOxm18KTbMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwMwYDVR0RBCww
+KoEoVGVzdDI1RUVAbWFpbHNlcnZlci50ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkq
+hkiG9w0BAQsFAAOCAQEAXCL3x2CoR+4+uBv3/rjM7X1cWiSc89+ydAsWHOVgHpI2
+nnxYPijuJTyiINCNQCZ2xReOMbd4IkhnaKt81hThsHlulDhBc7j9d29RfkA3KUDj
+QpIWZaBJHhe1668ETpOw/CHBPGfmPb7GhCfL9wZxeqqTytfgBhXHVd+W+ZOlGUPk
+8Ag1yGqnl0gmKXycSTR5uAAQvzwEz9QM2ZOMWF4N7WVEZMzm1mtZyWlI0MOzEEed
+A0j4FLWEkNh+6wf/wQNpDKNSipLnRXqE78IhKqBG9cR8+PDIjexXNCSZ/FvgU0k4
+PrbtJlt1IBitxYNFyXkq5W4p9jeG9li0wTktImmm3A==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 88 BB CB FD 18 80 A8 9D 52 3A 36 D5 FD A2 DF 9A 0C AF 02 29
+ friendlyName: Valid RFC822 nameConstraints Test25 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E966F48CB3EA6A19
+
+qsOLayseOi+mrut/xPkTJnpBQxljMYMFBYwJyELQ9UcApYfUXk356Qurl75iUtf0
+zAX+fUA5o4E/Br7kuve26KiSdE/GfGHsaQM2PYgGMyp4paJ/Wzr5LX/9CFgRb19O
+/9+52zUGto9/QPxGXWsmVqveMLIEQaNkXzLOGtb9QANlzf+lM+IAC9UjYJFVVQQ+
+8ces3QEZ/WwjRWV6ViX+keFnhEQiYZ21rtkkP0Ofo5ddNzrySU/oF9DfvFeiuKv8
+dKLbsYmj2pP8Cw+R47k88dskVxmdv8QkfBqothHAuN7KmV1VUeVDO1FxzgWJVyYI
+WCdBzJcgNJCmNgcSMsDCZ9KG8lsjJ0Iw1CMih7WjqsxPk7UwnKiXjN/r8ac4xApi
+PckwSl6/HiBuwrQkYU56JHJTtjQ7qudIdsxrzquRmNS90Zu19H5WH1YlNLdUgxCE
+Y8lMACZTBm1NCcYlkKDXTflcskDj/+BssECjCQx8fSiH1Uao7jarbqWLRujw0yQX
+d7/qTp2B6q+ptgvNjPr3nThZiZ67Mm5SXrpMcnZmstIw/ZjKuvIA1Vap65u3YGR1
+c/wo3tY2Br3ZN+bSo/CZpwbo9r+PVdWXG1xnjMqbVhfX9ASzGMpL/vDhz7YH12az
+ER1MMAr2fj2O41mnfeFw2V50aUtj4v5CZCvdXv4+jNjkLV3VQPaNmVqT18Lvr4vg
+fC/oXKsa5FNm+5IN9Hdd+GDZgGDHuvavfVhF1BwUhlH96A/7ZUFFzIV/ztftLY4P
+tigYL2XhxIkdCLhgz+lEkK4lm6E95JXDSwsQkHw7USqm9C3ARktNLW+HdL/ccoV2
+wzoWr9WQ91TKvAToE8W0TlW2OCneQUyXxMLI06dp9OyB9e021B32prB3D2gNlc6m
+BBf6ZWGtUSts8ZfXStgwj9ZVUhHRA6Aax07EY7fiUNHsPEm1iTOsiNm9zaunL2N4
+yBiN85xoFxYqyuRJP87jXRghCr2z66gxY1ShqCWPKRm9rZxlQpjgCS0lfLl9u42W
+5Lie5fgQmIHDiXZsrV39QHisendf0MmazW7SCU0Qwb/ZMLipviDvkdzG3R4qmieY
+fEAkzhJQlG67ULT/NYWf4h06un+BywOipUYDTUBZE5M9HPhfMvso3eW40D9NhaSI
+2BG8shP1/LKn1tvUqTHsrIXCa+D0Ir5yKDxoYt8MTrowNCcF1JpOa9Not7PsSebM
+1VtvBj1rWmuSKlRxWxS26eEbhg8N9i5Wnt9i8GiysGgpxlYD3UsTFuZKpCJyt5P2
+h7y9MfXR7ePZssUwL6ioqT+m3G74ZxUD/aLx93pRweze0gkHd91qcsz5TkB4K5Hz
+l/yyGp61nDPsvBLa+1BH/a4jERlzDx6LA3BbPeciZXBPurhVx5AyRpNmwDFOx5+H
+D4sfInJEZvRKRQiz3JlonipdNic9+JTzxufcD4g3CdAOAB8R2hf4/uvTqYa0agqW
+GrNftdaPnzYt7WM5JdOUkNNwHFfE/PiziacuMz5PWdi2VNjj7VH3g3/2HVqWwRzp
+MQTGF3gePbYZdekHCSGWNe0fgaH+DYsOzR98qbK7Cr/BMurlXyQcKE59NGu2UIZA
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest1.pem
deleted file mode 100644
index 4ac8a81b17..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest1.pem
+++ /dev/null
@@ -1,264 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid requireExplicitPolicy EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 subsubsubCA
------BEGIN CERTIFICATE-----
-MIICgzCCAeygAwIBAgIBATANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLDAqBgNVBAMTI3JlcXVpcmVFeHBs
-aWNpdFBvbGljeTEwIHN1YnN1YnN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQx
-OTE0NTcyMFowZDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMTkwNwYDVQQDEzBWYWxpZCByZXF1aXJlRXhwbGljaXRQb2xpY3kgRUUgQ2Vy
-dGlmaWNhdGUgVGVzdDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMtxfTwK
-0K+ya1KGbTjYgKKhZIQ/LGTa7Dspd7Z5tOgMptNRXcZxWTMotzRgl1ndDpQ6VREk
-JM/VBmbP67g0jwIe2n0QcTFkThPANsyPkdUBXahvmC0VEeIMHnflvqjN4vfK9guc
-6nG0XfBZ4/Jlx6SFvgoO6wm6XNtrMl32qwUjAgMBAAGjUjBQMB8GA1UdIwQYMBaA
-FJTXd8VxKtTTGW/0USC22qwIMuOvMB0GA1UdDgQWBBRUf4tLtvX7PjlUltzRvRgg
-phdo6DAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEAnReGZHvu3NJz
-B3B+qMmyfqUmW5eMxNjHymhuRDw3NXTmT7SNUL8O/NC76haxw/5HDE7rVuvGSPl1
-qhciDJOmTF1o09zDDjDM3tlXUvqC2Natm/Xew1+Hy4hfzY90CmlUuUGpKpzQ7SYt
-mHl+zz1o+9Y1jZSK4yDs5xcPnisoUjQ=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 CA
------BEGIN CERTIFICATE-----
-MIICkTCCAfqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGnJlcXVpcmVFeHBs
-aWNpdFBvbGljeTEwIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFow
-UTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSYwJAYD
-VQQDEx1yZXF1aXJlRXhwbGljaXRQb2xpY3kxMCBzdWJDQTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAvWfbIMg2LdPn/geH8Jo29/G6XSDCQm/MPINuucCdUSjA
-PBSponYKGMQNY//7KhwbVj2hQlgl8U6gw0rvIml4YaZmR3SPUXl2O0BXiiFQX0Qi
-bJ7NRaPcgrg04Fl+W19wk2Q2qGBrc1rMCDSG7ZBzwqtJssJpgkb4GSnoGr9FEKEC
-AwEAAaN8MHowHwYDVR0jBBgwFoAU8+kmmZYGhsTVonvsubClbjYNFUUwHQYDVR0O
-BBYEFKNDYb56GPOuZdF0vMDzMPzWBjqUMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAE
-EDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUF
-AAOBgQCX5vf2fqbgsOCFDqP5acUsKiSiuP31Oj/Fy1e0Y1LBph3ZtxRTkqZGIUI1
-imjbT64NLWvt2MMmfeHOlEU/fSRxevhRT+yRUmfaJuw9NBepK1oxpRtJ5tu5cr7E
-WyJMT/zv3wRloA23Feldchzxg6rqsM1LybyAtXXo67sc/EUxdQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBKjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME4xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEjMCEGA1UEAxMacmVxdWlyZUV4
-cGxpY2l0UG9saWN5MTAgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMyF
-/T/s9w6HU3LcURfJCjhjrP4PxbYbTP/c4wcq8vtx+8gb8P6jkdDvpJms19NcshfK
-DnR2b+cp6PfbAWx31AqcF2ynuU/C06PG/GQvNUhC69RziLxcHSMkThbnbN86ccr6
-d1WWb3Mxlkmtc7AhKHmORoz/Kd0b2Poi7L91o7+VAgMBAAGjgY4wgYswHwYDVR0j
-BBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFPPpJpmWBobE1aJ7
-7LmwpW42DRVFMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgAEKMA0GCSqGSIb3DQEB
-BQUAA4GBAC0Pv/aS8/3mmgB+R0A7UTvUGedE/M+DOOM5G8+dwZHjApQbuHYZjwQo
-Yrf6759MH9wKAYOcaJTgFJWFJuwjBJuWQuiglk8tcKmufVqHgRlCsrKtz312inHV
-NfxuGrViA3gp1Tr1fiXjG0gcgyT4QEnripDTLKvpHbOtMWZB6hSS
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 subsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 subCA
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTEwIHN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowVDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSkw
-JwYDVQQDEyByZXF1aXJlRXhwbGljaXRQb2xpY3kxMCBzdWJzdWJDQTCBnzANBgkq
-hkiG9w0BAQEFAAOBjQAwgYkCgYEAqwkZLQpMq2d0v1R/PA5wl+lyQlnehOszQk2U
-0zfHPGI4vJ1TIZZXYpOjVyfodG1wdwO3RCHLzguwsbk12RVNTls+kF2Wu3LtLtMi
-GSKx/imJiKw+ARw6sqBHmrNE9L/1C/e9rb+Su1kZ6WrtOfSAG8EpySytu9zTbGJF
-1YbZT3cCAwEAAaN8MHowHwYDVR0jBBgwFoAUo0NhvnoY865l0XS8wPMw/NYGOpQw
-HQYDVR0OBBYEFG1oMf35X1L5+y7aRMLPezaZ2P8pMA4GA1UdDwEB/wQEAwIBBjAX
-BgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
-9w0BAQUFAAOBgQAbOLTRc1DEC+iOWixska5o4gEOfAPSHWymjRYit+VYE3JdjrP9
-2hbIGQSrLlK8QQ0+9VkNsfncjCydV7J6Q3c1rPNCvd6dlfAzy9DfnXADu/vZuxBs
-pJ3B4EuSv23hMHzjoNnv/iGUnzkrLGfMPPYlB9t8jrbySU1lYX8FcD6YCw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 subsubsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy10 subsubCA
------BEGIN CERTIFICATE-----
-MIICnTCCAgagAwIBAgIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAMTIHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTEwIHN1YnN1YkNBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0
-NTcyMFowVzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVz
-MSwwKgYDVQQDEyNyZXF1aXJlRXhwbGljaXRQb2xpY3kxMCBzdWJzdWJzdWJDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuj3CUHlGX/JYo4Qsdmbzns192OxE
-IC1a8Yc7HhN9/IeStb9BATFCI4MyFiHofxoFG+oPzs4nRkOqmOju0VXYhfu+01j4
-LTKp2iwNleLbIe5CZ/PWasj9ixJfWeMe19fszNKvtnBmn+rCIqimOKmKPh7FIMgk
-IImKUwZ2gV41wHkCAwEAAaN8MHowHwYDVR0jBBgwFoAUbWgx/flfUvn7LtpEws97
-NpnY/ykwHQYDVR0OBBYEFJTXd8VxKtTTGW/0USC22qwIMuOvMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCQJ4CoH8d7JguvuXoxhetUWQz+kj/kW1kbW/vjxhHE
-Ux4rnRd8TUhpocdkzp9xRLF8BvZFw4HwwFbys4rENFq/VpPzIFqIW59j1bvSQzjN
-GWZp1MtaQuhSGtzwc4dfCl/1ozQVVkcjpT7n9iZ2JMYNGKLSmmuFMMLGoViVq0vo
-mw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy10 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F3:E9:26:99:96:06:86:C4:D5:A2:7B:EC:B9:B0:A5:6E:36:0D:15:45
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0c:82:73:e1:99:5d:9f:9c:27:57:43:f6:74:10:b4:76:e1:d6:
- bf:9a:de:84:8f:9b:0e:a6:ba:9a:98:06:fa:ff:c2:a5:a4:cd:
- 5f:b9:8d:4b:e1:67:e6:b3:e3:2e:5b:ea:e4:d9:9c:06:42:c0:
- 96:81:40:e2:99:32:24:c2:7b:d1:47:2d:32:42:c9:7c:cd:09:
- aa:c8:1b:bc:a4:d8:fe:6d:8c:52:79:d5:81:70:89:78:b1:1e:
- 11:2e:13:69:45:28:55:66:43:1d:61:40:fc:1a:78:ea:23:98:
- 44:66:df:15:8e:d1:d5:f9:82:7a:d2:2e:ad:36:8a:03:ff:04:
- 8e:09
------BEGIN X509 CRL-----
-MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGnJlcXVpcmVFeHBsaWNpdFBv
-bGljeTEwIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNV
-HSMEGDAWgBTz6SaZlgaGxNWie+y5sKVuNg0VRTAKBgNVHRQEAwIBATANBgkqhkiG
-9w0BAQUFAAOBgQAMgnPhmV2fnCdXQ/Z0ELR24da/mt6Ej5sOprqamAb6/8KlpM1f
-uY1L4Wfms+MuW+rk2ZwGQsCWgUDimTIkwnvRRy0yQsl8zQmqyBu8pNj+bYxSedWB
-cIl4sR4RLhNpRShVZkMdYUD8GnjqI5hEZt8VjtHV+YJ60i6tNooD/wSOCQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy10 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A3:43:61:BE:7A:18:F3:AE:65:D1:74:BC:C0:F3:30:FC:D6:06:3A:94
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1e:e5:78:df:47:b6:e0:42:9d:78:6f:f5:38:37:a6:fb:e9:8b:
- 00:16:34:fe:da:ae:70:4c:b6:b2:3d:53:7c:ef:58:24:b8:87:
- a5:c0:ca:7c:fd:aa:8d:ba:2e:76:fd:c0:9a:f3:b9:70:a8:43:
- 13:41:22:1b:51:ff:00:20:32:ae:ab:6d:44:ec:b8:7d:4e:4b:
- d5:86:83:ea:98:64:cf:0f:dc:f5:2d:52:ee:20:98:a9:49:ad:
- 06:b6:39:4c:d5:1a:94:a5:22:4e:ad:b5:ad:14:64:49:e5:6e:
- aa:63:9b:36:28:9f:5f:dc:c1:03:7e:7e:c2:ee:48:63:19:7a:
- 04:f4
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTEwIHN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBSjQ2G+ehjzrmXRdLzA8zD81gY6lDAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQAe5XjfR7bgQp14b/U4N6b76YsAFjT+2q5wTLayPVN871gk
-uIelwMp8/aqNui52/cCa87lwqEMTQSIbUf8AIDKuq21E7Lh9TkvVhoPqmGTPD9z1
-LVLuIJipSa0GtjlM1RqUpSJOrbWtFGRJ5W6qY5s2KJ9f3MEDfn7C7khjGXoE9A==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy10 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:6D:68:31:FD:F9:5F:52:F9:FB:2E:DA:44:C2:CF:7B:36:99:D8:FF:29
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 58:cb:cd:7e:81:ea:55:5b:85:7d:b1:7b:ae:0c:70:90:82:81:
- aa:5f:e4:5b:99:72:8c:22:bc:2a:ae:3f:d7:0f:94:cc:02:b6:
- 0f:c3:e9:ab:c2:8b:c1:68:0f:12:ca:f0:7c:1e:31:21:7d:38:
- 5e:2c:0e:9f:af:89:48:e1:2a:1f:12:e6:2a:b6:59:98:dd:d0:
- ba:1e:06:b1:c9:85:b8:75:f8:a9:da:e9:25:6c:e4:9c:6a:92:
- 29:d7:59:fb:f1:80:c4:4c:43:f6:79:5b:60:a7:36:cc:64:22:
- 5f:f7:d8:8e:ba:1c:a3:59:d2:fe:1d:8d:5c:40:8f:0d:2d:ee:
- 11:4d
------BEGIN X509 CRL-----
-MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAMTIHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTEwIHN1YnN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8w
-LTAfBgNVHSMEGDAWgBRtaDH9+V9S+fsu2kTCz3s2mdj/KTAKBgNVHRQEAwIBATAN
-BgkqhkiG9w0BAQUFAAOBgQBYy81+gepVW4V9sXuuDHCQgoGqX+RbmXKMIrwqrj/X
-D5TMArYPw+mrwovBaA8SyvB8HjEhfTheLA6fr4lI4SofEuYqtlmY3dC6HgaxyYW4
-dfip2uklbOScapIp11n78YDETEP2eVtgpzbMZCJf99iOuhyjWdL+HY1cQI8NLe4R
-TQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy10 subsubsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:D7:77:C5:71:2A:D4:D3:19:6F:F4:51:20:B6:DA:AC:08:32:E3:AF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8e:42:22:a8:c7:94:5a:d3:72:4c:98:eb:58:30:58:63:41:cf:
- da:f9:9e:f5:6f:3b:4e:30:17:92:8b:a8:30:bc:cb:ac:2d:94:
- b1:62:ef:b9:69:3e:30:15:01:d4:32:ff:f4:86:c5:5d:8d:41:
- 46:39:52:a0:df:74:e5:35:c4:e6:08:06:58:94:ba:d1:7e:08:
- e4:66:e1:65:8d:15:23:3c:e6:de:61:4e:71:5e:5d:24:03:bd:
- 52:ff:85:a9:ea:7a:63:37:e5:c0:e6:78:4a:71:45:32:18:c7:
- 7d:2b:90:16:bb:f9:35:cd:a2:ab:c3:8e:c9:db:6e:7e:62:94:
- 6b:ad
------BEGIN X509 CRL-----
-MIIBUDCBugIBATANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLDAqBgNVBAMTI3JlcXVpcmVFeHBsaWNpdFBv
-bGljeTEwIHN1YnN1YnN1YkNBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-oC8wLTAfBgNVHSMEGDAWgBSU13fFcSrU0xlv9FEgttqsCDLjrzAKBgNVHRQEAwIB
-ATANBgkqhkiG9w0BAQUFAAOBgQCOQiKox5Ra03JMmOtYMFhjQc/a+Z71bztOMBeS
-i6gwvMusLZSxYu+5aT4wFQHUMv/0hsVdjUFGOVKg33TlNcTmCAZYlLrRfgjkZuFl
-jRUjPObeYU5xXl0kA71S/4Wp6npjN+XA5nhKcUUyGMd9K5AWu/k1zaKrw47J225+
-YpRrrQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest2.pem
deleted file mode 100644
index 40479f9470..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest2.pem
+++ /dev/null
@@ -1,262 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid requireExplicitPolicy EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 subsubsubCA
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTInJlcXVpcmVFeHBs
-aWNpdFBvbGljeTUgc3Vic3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBkMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxOTA3BgNVBAMTMFZhbGlkIHJlcXVpcmVFeHBsaWNpdFBvbGljeSBFRSBDZXJ0
-aWZpY2F0ZSBUZXN0MjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo5atW4GH
-rxxchJEUckmfckvxY4c4sEEgPZIouuIcHeQAIjEjMhCqHNWrA7WiQLldqLSridIm
-FWVRxn9/wlv3oMMbBlf6xFLjr24zYTePsIFWBk5ZPbMBKcl7XqfeuF4jJ/vh0lj/
-Bi9W9Imt5ZvJu0EHSkQzm+NNis/Tgd4aWRUCAwEAAaNSMFAwHwYDVR0jBBgwFoAU
-PqkwZi+ntCWIhGfJrZiTFfiWzsUwHQYDVR0OBBYEFDLXXehvdjv0hNKAOrzbFme1
-lGWtMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQUFAAOBgQBmbv/fgwsL3SAO
-6F4RmXOfTQTewhDfMQDEbwUJOfg7D09LIcIupI+cYY7iqjUq+gUeiAlMlL91ITlp
-oiKGUliex+bhygei8kSfmwT+l09yz3EPxCfdjY1k88ni+TedHBkoK0p7Q/uFG4DP
-Qk7DgGZ57nrx9maK4io59a/VTPM65A==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 CA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTUgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBQ
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNV
-BAMTHHJlcXVpcmVFeHBsaWNpdFBvbGljeTUgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBAKzDYQYB3gcpzJVllE1FhnwJXEpyKjubhg5P3MDpRW9YRYSs
-W1O2TYeX633IhRRS8rsJW22Yzp4tN9M6cXqBTHB2+nwHtREHSxeSei31AnAu+2n1
-Q+XNJ9W5DLbdahLtURESEnEQSyViFMMYQjm7rxvORc/D9OIa4u+tx1ESGOGDAgMB
-AAGjfDB6MB8GA1UdIwQYMBaAFNXihi3xK2gXnA9evyu4ZpmeQxu6MB0GA1UdDgQW
-BBSVhouRNrt6b+KEFZDvRY4BJxZruDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-gYEAB/OvefFEki9VuKt6EwjvNLjvjT1581w8qKpdHgDrYthrMm3JIULpn5zaRqyQ
-KIT8uu40HzKHagNpfdHQ1HNuEQ9qwIAQvtqmtJxqIR+kdeKXw78cN+TJzqaHuZu5
-VTidhmlVHaY/50quu7qqGiIQR4bcYrb4vY+adBBgrpcvUCM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBKzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5NSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAlU17
-mwFm/6Yf08lbJU8q1FquMr1IaWlav4Qh1/UUFR3cRicBZZvQNTpxTcn1jmaSj8xK
-Gm9pUmbmbJBqiDYX5p1IwR1nmsyXxnaYD3SYadHlmb2emlzu1Dg3l6eKvaNh6h3a
-F0XDS/S+GtadjpVmuWdMIiWWrEVIFfGAL2VFaeUCAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU1eKGLfEraBecD16/
-K7hmmZ5DG7owDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQUwDQYJKoZIhvcNAQEF
-BQADgYEAjjGl1NeCLiMI9MFNgftmCe1ehHkE+Qr4TSJQfw9qZ5p0SRd2aOxq7km6
-ZwhF/E+wsS1CEwLRWaK7LqCmFx+XacoXjJi2XP5UjctH1tKyJx2YBhYrfzNkECJl
-u3KBUohmTd/aICG6oVE5ErcFFE/evv7LioMT94kub91V18EDgCw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 subsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 subCA
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTUgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBTMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAm
-BgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBvbGljeTUgc3Vic3ViQ0EwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBANALzpI6Vb5grPqiSrzcOrNfPZ5pbbC4jjs89zo1
-RRGcMLQQt5wPHu1OKE6g2WXvikA0ompVqxKG7qeu/bTIcpm3CHowhRigOk/VJkCV
-Zyv9tdLzlWoiW2elI0uJ4BXsW8oU4sTxlx1/QlJbERwv1BwL5BQD3l02LP4vueE/
-U8HpAgMBAAGjfDB6MB8GA1UdIwQYMBaAFJWGi5E2u3pv4oQVkO9FjgEnFmu4MB0G
-A1UdDgQWBBQK52IWqA5PL7e4PyfIo6lfe0ZrpzAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
-AQEFBQADgYEAmbgnzwSut1UU/jNuzF9ZK+x79DmpTDAv12ASnAPUvZJ8RTQBxYlL
-C/B0gYZsqUnyaEoZAsrSYktMdA2qDedWGFB94d+LVbpHNoNvxQl+0qMTTLh+gO4V
-JIrQ5hj2npLdDHKNi6a91lO83NqsyuITezJ0Nuhbvf9KuApxz069EO8=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 subsubsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy5 subsubCA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBs
-aWNpdFBvbGljeTUgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-KzApBgNVBAMTInJlcXVpcmVFeHBsaWNpdFBvbGljeTUgc3Vic3Vic3ViQ0EwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALw7Jg17lRmWU52pn7qaLPiV7eLBCvpx
-S7uekBx+WtzvAVxUF+iI8whshUqsC4XzNHTs6BvS4QRwpixRMMMWwH/67kGAEADq
-lVYewPK7aMHMdDfCggIukUpy1DVR3KOc7rnVZ2tGKBbCFhAxPMXBgkketIAVJ1V4
-+3nRS/QGSxF9AgMBAAGjfDB6MB8GA1UdIwQYMBaAFArnYhaoDk8vt7g/J8ijqV97
-RmunMB0GA1UdDgQWBBQ+qTBmL6e0JYiEZ8mtmJMV+JbOxTAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEFBQADgYEArpriBQ3ArOVFh+HujQ+8cIihYFG5ri+SairjawVwbUb4
-HatEUky9Nh9YAxGn1YGdBpintIpQU/0WljldKXxvH2yn6hMCNV5ql4hhorP2YfWL
-8+S80IboVToDPKsEdzeAxs5Xeh3BY9DgJPY9RmDgJcXqb6I+1P2+3GIxGDpF/jM=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy5 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D5:E2:86:2D:F1:2B:68:17:9C:0F:5E:BF:2B:B8:66:99:9E:43:1B:BA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 32:06:95:6e:49:2d:7e:9f:9f:7d:d6:0e:3c:b0:73:4d:2a:d8:
- 1d:86:f7:2f:61:f5:39:80:c7:b4:e6:3b:8c:90:1c:11:6c:0f:
- fd:9b:c3:52:b9:aa:2e:bb:8e:25:b9:f6:75:b7:1a:2c:fc:45:
- 81:54:f6:49:69:e2:78:ef:25:d2:cb:1b:7e:f8:7b:96:d9:37:
- ba:f4:66:8f:e1:e7:56:96:ef:76:bd:4c:94:0e:fd:a8:35:16:
- d1:2a:69:28:29:96:18:8b:a5:af:04:00:bc:d9:42:ff:ea:32:
- 35:9b:3d:57:da:9e:a1:d5:e4:3e:e4:4f:4b:8f:5a:48:47:73:
- 38:5d
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTUgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFNXihi3xK2gXnA9evyu4ZpmeQxu6MAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBADIGlW5JLX6fn33WDjywc00q2B2G9y9h9TmAx7TmO4yQHBFsD/2b
-w1K5qi67jiW59nW3Giz8RYFU9klp4njvJdLLG374e5bZN7r0Zo/h51aW73a9TJQO
-/ag1FtEqaSgplhiLpa8EALzZQv/qMjWbPVfanqHV5D7kT0uPWkhHczhd
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy5 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:95:86:8B:91:36:BB:7A:6F:E2:84:15:90:EF:45:8E:01:27:16:6B:B8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 73:84:54:e4:77:a5:7d:03:3d:7c:d0:a6:ea:6b:70:82:11:10:
- 1b:9a:85:8c:ae:3d:8a:06:a3:2b:cc:a7:77:0c:be:7a:02:bc:
- 2f:13:07:ff:83:e6:f6:7a:99:1e:a1:af:12:06:c5:ce:1b:f3:
- 76:77:bc:ef:ef:a2:cb:96:36:3b:fd:b0:ce:5c:ae:30:af:9f:
- ba:e7:16:e8:f2:66:74:82:6e:75:91:90:b1:59:a9:9e:8b:41:
- 37:42:0f:1b:a8:4e:73:31:e1:b1:53:fb:8a:3d:ee:d3:e4:77:
- a8:f8:ea:ea:21:f5:c5:be:1d:b5:e3:79:27:de:c3:d5:45:b0:
- 87:24
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTUgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFJWGi5E2u3pv4oQVkO9FjgEnFmu4MAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAHOEVOR3pX0DPXzQpuprcIIREBuahYyuPYoGoyvMp3cMvnoC
-vC8TB/+D5vZ6mR6hrxIGxc4b83Z3vO/vosuWNjv9sM5crjCvn7rnFujyZnSCbnWR
-kLFZqZ6LQTdCDxuoTnMx4bFT+4o97tPkd6j46uoh9cW+HbXjeSfew9VFsIck
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy5 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:0A:E7:62:16:A8:0E:4F:2F:B7:B8:3F:27:C8:A3:A9:5F:7B:46:6B:A7
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 16:15:3e:47:cd:ae:b2:4b:8b:30:d4:ee:c4:1e:2a:d5:84:bc:
- ca:b1:2b:a9:d3:37:be:f6:11:d1:1f:60:04:41:72:df:ca:d5:
- 0b:74:5a:e8:a7:bd:32:25:cb:e8:e4:6d:c7:be:25:c3:63:9c:
- 43:66:14:4a:0e:f7:ea:e1:83:a4:bf:5e:70:7b:a3:b7:12:c9:
- 36:fc:99:85:58:0e:66:d2:a0:41:6e:a8:07:2e:f7:45:36:fe:
- 71:3e:c4:7a:88:e2:0b:c2:c9:dd:30:81:b9:44:48:2a:1d:07:
- 5a:cc:e1:49:9a:04:a6:5b:c4:6c:2a:f0:3f:8f:3b:04:ea:5d:
- ab:70
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBv
-bGljeTUgc3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFArnYhaoDk8vt7g/J8ijqV97RmunMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBABYVPkfNrrJLizDU7sQeKtWEvMqxK6nTN772EdEfYARB
-ct/K1Qt0WuinvTIly+jkbce+JcNjnENmFEoO9+rhg6S/XnB7o7cSyTb8mYVYDmbS
-oEFuqAcu90U2/nE+xHqI4gvCyd0wgblESCodB1rM4UmaBKZbxGwq8D+POwTqXatw
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy5 subsubsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3E:A9:30:66:2F:A7:B4:25:88:84:67:C9:AD:98:93:15:F8:96:CE:C5
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0a:d7:14:66:2d:1d:2e:49:9d:35:99:54:76:ee:50:80:e2:37:
- c3:d5:6a:64:02:f2:b2:12:d6:97:8c:a5:75:e0:a9:9e:3b:46:
- ca:ce:31:b9:53:fe:fb:99:15:9b:7b:35:68:5c:9a:60:a0:da:
- a9:2d:d8:1e:b8:89:61:89:01:1b:e4:40:76:fa:b9:62:cf:fe:
- 87:6c:95:9e:da:19:db:4c:bd:3e:f1:25:57:3b:d3:ab:94:7b:
- de:5a:ff:55:63:fe:49:ad:3b:45:92:c3:ba:49:79:45:89:3d:
- 70:75:a9:53:1f:95:d6:c2:11:46:43:76:41:c0:02:49:23:d0:
- ef:bc
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTInJlcXVpcmVFeHBsaWNpdFBv
-bGljeTUgc3Vic3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFD6pMGYvp7QliIRnya2YkxX4ls7FMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAArXFGYtHS5JnTWZVHbuUIDiN8PVamQC8rIS1peM
-pXXgqZ47RsrOMblT/vuZFZt7NWhcmmCg2qkt2B64iWGJARvkQHb6uWLP/odslZ7a
-GdtMvT7xJVc706uUe95a/1Vj/kmtO0WSw7pJeUWJPXB1qVMfldbCEUZDdkHAAkkj
-0O+8
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest4.pem
deleted file mode 100644
index 96f230af53..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRequireExplicitPolicyTest4.pem
+++ /dev/null
@@ -1,262 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 subCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 CA
------BEGIN CERTIFICATE-----
-MIICjzCCAfigAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTAgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBQ
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNV
-BAMTHHJlcXVpcmVFeHBsaWNpdFBvbGljeTAgc3ViQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBALoSt6pV4IRQVJ5TV99GOGi3yhBt0wvylEs6VYZL0D677yoV
-AIY3CQWXG27SKUYB8SQ1XC+a1sO4M5Q25mdWLXIN+TUmlNJW4BzLGh6B63bGDSnK
-FG+aVvh8ZvHloIu61d5gw3FokPmBeS0NF6XVBsbJMiLn7TdWeSFqYYTw+awhAgMB
-AAGjfDB6MB8GA1UdIwQYMBaAFHdqs2T1sexRei1lhv8CGH4LSo4nMB0GA1UdDgQW
-BBQHH/BwA0diipbRgYmqAFSJ+JxtKTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
-DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-gYEADvf91AyVaeC72JRsi71sKWf3f71NGoRSjxBnKh8VS/G0fIQElDmHHe01TZ3W
-t2zRBZROqLoG10YCxSheQdd0gE0yoqTdcc9l3kr0ZMhgfM4mRPYNL6kma3azT78F
-OqMJAUrnjjMYruGcLm7MLp3Lq2/7NjAN5q3ffuSrtwUwLHY=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBLTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5MCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvEVs
-LML3To+EEs99KIoLdE98+LzQkf1wQzrLhuqlF6UH8BJvupeClmchb4TFyXh3mkhT
-/DsdlWlScKGl1KiqKyXIrb5x0AebEDEHylhNhUgn7O/zU7WyuGDE4SU0QNR2T/C0
-mOEbjV9WR06GcmbMCp1GUY7zmfThFrZP2Cfj2PMCAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUd2qzZPWx7FF6LWWG
-/wIYfgtKjicwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQAwDQYJKoZIhvcNAQEF
-BQADgYEAWoBbngBiHa90n2Kdb0iXazi7wmnvtPZxJ2xLA/Ubv9qPzFUwoUM/Ikm8
-6o8sI8TYNuCwwni3ZrQwCfagtNsOeUXp0O86mLIVH7jr9YS2nBtuZdXAnL3lZW5r
-VHXxf0Fnmk+Nx3Frxf7tJfZVGGLCJCabwObF9o6Bgya4GP0FL20=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 subsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 subCA
------BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBs
-aWNpdFBvbGljeTAgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBTMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAm
-BgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBvbGljeTAgc3Vic3ViQ0EwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBAMJOPDBu3Iqmav4DjiTzIKi6FmFd6HGBsW+dDPbs
-l6jZbrkDavBUtuqC5RMVJKvOyWY7GYIsUdgoSOJ2YHl38HO6nXhq3OFO8v0r0kU3
-SRPPM7vpiPYf3eMZm5Z77GT5XuGNUPSkepAfxaN1IEAqFoePT7wsGa9Zg77WcLUd
-nEw3AgMBAAGjfDB6MB8GA1UdIwQYMBaAFAcf8HADR2KKltGBiaoAVIn4nG0pMB0G
-A1UdDgQWBBSwQkkzaPMCKs1UIV3mYuFwzqUjQDAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
-AQEFBQADgYEADXoLz5MBvHFKs5z47OgavmZKJQp+vIcDSOu4QUlIZgmIWcbcI7g9
-GKG0SIg5gXZhwoH3OXx3g5miGPzOi9iFtdkZXAZPX9JHsISpHfB9VcZYTfmW1T49
-ZrnCugvmdUnDLBitS9MKHkyU7zL/ACtlXB82SFbiCS1R8bEfU4Oozf4=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 subsubsubCA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 subsubCA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBs
-aWNpdFBvbGljeTAgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-KzApBgNVBAMTInJlcXVpcmVFeHBsaWNpdFBvbGljeTAgc3Vic3Vic3ViQ0EwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANk012Iq+sazBXGTgqICIE0GnFvathib
-YlOHsK/Iop6+DNGleJoAH6bqvS2ZWtkkIKE7WU3nfDUjMVp3IJyr8WDesDKvSJyg
-zy3y0e+XuMv3QtyFXxESXxHmY62UaILPgE9XMgcyAhOnVU4mQe7ScJDAcUeLgjcZ
-fQdBnGGCT/LVAgMBAAGjfDB6MB8GA1UdIwQYMBaAFLBCSTNo8wIqzVQhXeZi4XDO
-pSNAMB0GA1UdDgQWBBRZ1+jibtd5cIJhiBzPFFLktwdJKjAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEFBQADgYEArZnuuewqU0IgdJEU6osnzsuX6E6A4igNSK1ZYUKmhRvn
-eyfrU5kHavTwnM+h7SkVB73S2w+OqHUGin2xIu92RcWzN7NV+oLWldhnYtalSyh1
-KiuKC41mAZweQv1Mrz/+5lIQDOUOtV2JXOjaA+T/JR/qFLo0MoqC+mBxk/w5eDg=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid requireExplicitPolicy EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy0 subsubsubCA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTInJlcXVpcmVFeHBs
-aWNpdFBvbGljeTAgc3Vic3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBkMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxOTA3BgNVBAMTMFZhbGlkIHJlcXVpcmVFeHBsaWNpdFBvbGljeSBFRSBDZXJ0
-aWZpY2F0ZSBUZXN0NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvs6xd2Lv
-4717eCUDGaJKN9HVbjqiBoJd9K18OP5hoJ/iyWNR7u1l+p4xbQNdi8iU8UV1hBrD
-RI2jahY2p/rgx+REkxcyhWXFc0qP5hMqbjUD9IuMyhUrwtSut0la+L/lbKuag7Ry
-pWlMe0FQUjnGev5zpdXCY4U9y2a+7jYuOOsCAwEAAaNrMGkwHwYDVR0jBBgwFoAU
-Wdfo4m7XeXCCYYgczxRS5LcHSSowHQYDVR0OBBYEFEEjHrhpuHHNWtHozi2HzhxK
-KgmLMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJ
-KoZIhvcNAQEFBQADgYEAVpfKjsWKyLdcOfar1+Ejc9eyGUzMXt7F1xXSqdnls/Z7
-RuG7jkY1lvUm1vHhVb2yP/OdC+rwwmx4cjxUAm0dNrE82qZNiRqgaaVO3llJD9zt
-AD5gAi0nJqUdJ7H1b3X6Jt9VGTNlc+0ZAEHnaSID1Ym2pa1433XgPPi1/YflkwE=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:77:6A:B3:64:F5:B1:EC:51:7A:2D:65:86:FF:02:18:7E:0B:4A:8E:27
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9d:78:0f:04:94:97:f9:ad:b6:17:8e:65:dd:6d:ec:65:bb:73:
- 37:9a:1d:66:51:d7:97:b6:31:fb:62:a4:4a:21:3b:20:97:7a:
- 4d:aa:ce:d2:95:f7:36:65:77:51:e8:d5:81:0a:b7:62:af:76:
- 38:b7:77:72:2c:90:0b:8a:7c:31:58:cf:c6:1d:da:24:65:ef:
- 06:7e:d7:21:96:a1:f2:62:dc:5d:fa:10:37:01:99:7b:14:34:
- a8:cd:47:a4:cb:5e:ff:0e:b4:58:69:1f:70:f7:3b:2e:7c:77:
- b4:33:82:7d:18:54:da:f3:5d:dc:5f:a1:1a:96:f6:d9:0b:ca:
- 9b:a0
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTAgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFHdqs2T1sexRei1lhv8CGH4LSo4nMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAJ14DwSUl/mttheOZd1t7GW7czeaHWZR15e2MftipEohOyCXek2q
-ztKV9zZld1Ho1YEKt2Kvdji3d3IskAuKfDFYz8Yd2iRl7wZ+1yGWofJi3F36EDcB
-mXsUNKjNR6TLXv8OtFhpH3D3Oy58d7Qzgn0YVNrzXdxfoRqW9tkLypug
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy0 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:07:1F:F0:70:03:47:62:8A:96:D1:81:89:AA:00:54:89:F8:9C:6D:29
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 7d:a5:df:f8:70:c7:9c:d9:f2:4e:c9:42:63:48:cc:17:87:29:
- fb:99:c0:2a:11:8b:ce:ce:45:31:58:41:32:1c:39:ff:53:bc:
- dc:24:df:9a:b5:10:83:8b:a3:aa:cd:3a:23:92:a7:8d:c3:56:
- 83:19:c1:ed:d8:ad:c0:56:79:fd:c0:6b:bd:e9:bb:56:e6:18:
- 1d:02:28:91:77:90:15:f2:44:51:61:81:ea:1f:92:a6:89:84:
- cf:36:c9:e4:f2:6e:a8:01:11:82:96:fa:94:1b:fc:d7:e6:8b:
- c0:8f:bd:87:30:8c:84:eb:84:3a:e5:21:42:d1:60:82:08:82:
- 45:2b
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHHJlcXVpcmVFeHBsaWNpdFBv
-bGljeTAgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFAcf8HADR2KKltGBiaoAVIn4nG0pMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAH2l3/hwx5zZ8k7JQmNIzBeHKfuZwCoRi87ORTFYQTIcOf9T
-vNwk35q1EIOLo6rNOiOSp43DVoMZwe3YrcBWef3Aa73pu1bmGB0CKJF3kBXyRFFh
-geofkqaJhM82yeTybqgBEYKW+pQb/Nfmi8CPvYcwjITrhDrlIULRYIIIgkUr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy0 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B0:42:49:33:68:F3:02:2A:CD:54:21:5D:E6:62:E1:70:CE:A5:23:40
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 95:8d:6b:ad:bc:a7:38:7a:12:70:e4:e6:bf:06:91:0f:ac:72:
- f0:da:aa:50:e1:51:a1:8c:d2:d2:00:73:2a:6f:54:04:77:ee:
- 83:aa:c1:d4:32:cd:70:ca:5c:98:62:3f:a1:6c:4a:af:53:8b:
- f9:0d:7c:50:17:90:f3:e3:93:4d:c1:3f:2b:59:f0:12:3a:d9:
- 25:5b:15:3b:71:14:bc:29:b0:2f:b7:93:c6:93:b0:c1:fa:88:
- c8:2d:ca:fd:03:c1:ec:dd:0b:95:af:8c:d5:7a:0f:41:48:ea:
- 03:07:6f:57:2e:b3:b8:c6:3e:54:a7:9c:57:4f:27:f4:c3:9c:
- 25:5d
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH3JlcXVpcmVFeHBsaWNpdFBv
-bGljeTAgc3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFLBCSTNo8wIqzVQhXeZi4XDOpSNAMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBAJWNa628pzh6EnDk5r8GkQ+scvDaqlDhUaGM0tIAcypv
-VAR37oOqwdQyzXDKXJhiP6FsSq9Ti/kNfFAXkPPjk03BPytZ8BI62SVbFTtxFLwp
-sC+3k8aTsMH6iMgtyv0DwezdC5WvjNV6D0FI6gMHb1cus7jGPlSnnFdPJ/TDnCVd
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy0 subsubsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:59:D7:E8:E2:6E:D7:79:70:82:61:88:1C:CF:14:52:E4:B7:07:49:2A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- b0:23:c2:ec:e2:e9:c0:87:e9:75:d3:ee:a4:c5:3b:9c:27:c4:
- ab:b2:67:74:79:f8:5b:cd:4b:20:0b:ee:19:32:8e:8b:d2:e7:
- 67:5f:da:83:a7:31:09:08:0f:b8:64:2a:08:96:1c:78:db:13:
- af:77:26:0f:01:3a:e1:98:d7:41:b9:e5:86:9c:b1:36:a8:92:
- bf:6f:cf:62:13:33:3e:1e:79:02:e5:a6:8f:11:69:fb:1e:86:
- b9:12:18:67:cf:6e:c6:1e:d8:bb:2f:a0:86:dd:66:c8:0b:71:
- a5:68:fb:91:9e:f5:ca:58:80:7e:27:18:e0:4e:3a:34:45:23:
- cc:c1
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTInJlcXVpcmVFeHBsaWNpdFBv
-bGljeTAgc3Vic3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFFnX6OJu13lwgmGIHM8UUuS3B0kqMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBALAjwuzi6cCH6XXT7qTFO5wnxKuyZ3R5+FvNSyAL
-7hkyjovS52df2oOnMQkID7hkKgiWHHjbE693Jg8BOuGY10G55YacsTaokr9vz2IT
-Mz4eeQLlpo8RafsehrkSGGfPbsYe2LsvoIbdZsgLcaVo+5Ge9cpYgH4nGOBOOjRF
-I8zB
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10.pem
deleted file mode 100644
index 0f10912926..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Rollover from PrintableString to UTF8String CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClDCCAf2gAwIBAgIBYzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGIxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE3MDUGA1UEAxMuUm9sbG92ZXIg
-ZnJvbSBQcmludGFibGVTdHJpbmcgdG8gVVRGOFN0cmluZyBDQTCBnzANBgkqhkiG
-9w0BAQEFAAOBjQAwgYkCgYEAoNL+uym7FlmTUpQwimiPNXt8IR0+KjdAFbDkTqLk
-zxHkpKBqAjTWzEPRqnhsBmjPfLrS8omVrcKIOBgIbOCoRU098SYWt4/2WRbHhAKF
-kauf7d7NsN4WEDXJmlqiZrJLHDihW686RcpL7luSLrlXVXT1h2dWI08VpDUNrz6P
-L/cCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYD
-VR0OBBYEFDeXpBvbNFU1D8m0TcZ+SxfopIk8MA4GA1UdDwEB/wQEAwIBBjAXBgNV
-HSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
-AQUFAAOBgQDFX488L1PqURnQTZU0RgicEAHXUj3SLP3buSF/vMC1KHZd9JPnmf2e
-y1OGQ0S+B4lNX9VJEnS5f8w5bU0kcpGYQTPuFrTZvNZtN/4ZIZTLauFkEjM8sa13
-0CNwd0zMj/Dl1nQ2z8/wHLnfClEFmJHTZZ39W0jD/Lfg2hQvn43Tcg==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Rollover PrintableString to UTF8String EE Cert Test10
-issuer=/C=US/O=Test Certificates/CN=Rollover from PrintableString to UTF8String CA
------BEGIN CERTIFICATE-----
-MIICsjCCAhugAwIBAgIBATANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEa
-MBgGA1UECgwRVGVzdCBDZXJ0aWZpY2F0ZXMxNzA1BgNVBAMMLlJvbGxvdmVyIGZy
-b20gUHJpbnRhYmxlU3RyaW5nIHRvIFVURjhTdHJpbmcgQ0EwHhcNMDEwNDE5MTQ1
-NzIwWhcNMTEwNDE5MTQ1NzIwWjBvMQswCQYDVQQGEwJVUzEaMBgGA1UECgwRVGVz
-dCBDZXJ0aWZpY2F0ZXMxRDBCBgNVBAMMO1ZhbGlkIFJvbGxvdmVyIFByaW50YWJs
-ZVN0cmluZyB0byBVVEY4U3RyaW5nIEVFIENlcnQgVGVzdDEwMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDDncK1nAho7wt1siRGXkw0eRAeI3uztOfqSwGhT1ih
-XbW47ek9MiPqCRlX1RKOXve8quD7MM0ibzWjiroSxsaeM7gW91nwOZn8V+UfqmJF
-CikNAA17A/y9Nk+IVx8b2VB+Kjixg9HW2ZbqJiSq4Ci9Dkz2mH9sgjI0On0OSLDq
-2wIDAQABo2swaTAfBgNVHSMEGDAWgBQ3l6Qb2zRVNQ/JtE3GfksX6KSJPDAdBgNV
-HQ4EFgQUdLZDDyDir0HSFv0sejwUl8S6IxwwDgYDVR0PAQH/BAQDAgTwMBcGA1Ud
-IAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQAcxCi0hkgCRB1w
-uurTKVDyZTQ5ttLsggNpE6uqL+mGyAk/uYcGTxNM1Wx38DDqb+yJnF6CkLRwBk2c
-mEtKFVYwX3s/h+RPe+MO4WBurdVGfxpE3df2wvyYS7WOnd7iRhRirmm8LMoGPLoY
-w40WU1JjVs4Mg8vHt4OpmiFXlrv7nQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Rollover from PrintableString to UTF8String CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:37:97:A4:1B:DB:34:55:35:0F:C9:B4:4D:C6:7E:4B:17:E8:A4:89:3C
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 2a:72:92:90:cd:32:d0:c4:99:63:47:0a:9b:95:28:27:8e:04:
- 1e:49:38:bc:54:a7:da:f7:2b:58:34:d8:bc:ad:3e:a4:fa:0f:
- 85:84:fb:49:95:3f:7f:a0:c3:fb:94:07:2a:a9:66:44:e1:10:
- 04:55:4f:dd:ba:6c:bd:f8:f9:be:0c:de:28:54:fd:cd:f4:50:
- ac:4c:9e:01:e6:92:bf:11:cd:b6:69:5d:10:f3:3d:25:f9:1e:
- 7f:2d:d4:04:5e:4e:9e:b4:f2:10:94:1f:30:0d:27:4d:2f:6d:
- 41:4e:31:ae:20:2a:d8:90:34:32:92:d6:1c:b1:21:99:57:2e:
- 63:04
------BEGIN X509 CRL-----
-MIIBWzCBxQIBATANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEaMBgGA1UE
-CgwRVGVzdCBDZXJ0aWZpY2F0ZXMxNzA1BgNVBAMMLlJvbGxvdmVyIGZyb20gUHJp
-bnRhYmxlU3RyaW5nIHRvIFVURjhTdHJpbmcgQ0EXDTAxMDQxOTE0NTcyMFoXDTEx
-MDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFDeXpBvbNFU1D8m0TcZ+SxfopIk8
-MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBACpykpDNMtDEmWNHCpuVKCeO
-BB5JOLxUp9r3K1g02LytPqT6D4WE+0mVP3+gw/uUByqpZkThEARVT926bL34+b4M
-3ihU/c30UKxMngHmkr8RzbZpXRDzPSX5Hn8t1AReTp608hCUHzANJ00vbUFOMa4g
-KtiQNDKS1hyxIZlXLmME
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.pem
new file mode 100644
index 0000000000..6baf543712
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 22 94 87 7E BF F6 18 F9 43 13 D1 CF 41 52 7B 3A 8F E5 AF 8E
+ friendlyName: Valid Rollover from PrintableString to UTF8String Test10 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Rollover PrintableString to UTF8String EE Cert Test10
+issuer=/C=US/O=Test Certificates 2011/CN=Rollover from PrintableString to UTF8String CA
+-----BEGIN CERTIFICATE-----
+MIIDwTCCAqmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJVUzEf
+MB0GA1UECgwWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE3MDUGA1UEAwwuUm9sbG92
+ZXIgZnJvbSBQcmludGFibGVTdHJpbmcgdG8gVVRGOFN0cmluZyBDQTAeFw0xMDAx
+MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMHQxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+DBZUZXN0IENlcnRpZmljYXRlcyAyMDExMUQwQgYDVQQDDDtWYWxpZCBSb2xsb3Zl
+ciBQcmludGFibGVTdHJpbmcgdG8gVVRGOFN0cmluZyBFRSBDZXJ0IFRlc3QxMDCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANP+zCkHFztNGKS2jaNu7j8g
+O86LJI1CRdWLEfDjiqoCvEr7LrXRQsQGW79/GqtxZN1fu9yt6eaUBvusLU25JLX2
+johJWagbI4YJdao06kQWtzxk0JRIo8uOjEhAB5cnykYAlGAaRPm5BvMSGlLuMcYw
+80TpK0MtBIoHIa0yqU2+/CWwwFsGf3OKQQGjxpYx3rqL6cC69ybFfREYm6eaC2Rj
+H3bpKBEN1P544WU1ZKsaO3bZXXXa5+ehX+eSalHdOh3KMJxRej+D4xgsi+E9oO8w
+4Rixi9Hb90oZwiO3i2zdgFCd/iwVxk9pUjVAKebqBI4Dv8wsIpF4Rq+/qd7LJxEC
+AwEAAaNrMGkwHwYDVR0jBBgwFoAUtW1PKD/Hu7GYpKml0KhbXkp0s+cwHQYDVR0O
+BBYEFCTnhF1EvGRoOoQ2I1s2vDsOw+E/MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAE
+EDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBADB62jvyJnKCkLza
+PWHwcjg5rGeRYTcD/XvxR3C9e7taMrg8JDied+IzbkItPOq80bqB+mScXHlWSk9B
+mz7fg/Af1Ip6ryhw/fISLxnvHXNWaM7hJcyGJjH1uCAmgm91EDfn7KKJXqi4CkH8
+cBJATJuohy+iUUlOru0ZoeiQGLWO0nkmw+GeIZiztXaKXKmoV+RGfLIAFEwuS33s
+GmrHob2DjHBIgAa9CcP03DOTtW0k/JH62NupGQDciY/dBj75I7eX6tjMGQn0h1vf
+up27UzRHUjBMh8NYpmnvK24LRYQMQC3TaUbaz6gsD9cNYMFiFBXa35AcDjr/Zanf
+H8YRcS0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 22 94 87 7E BF F6 18 F9 43 13 D1 CF 41 52 7B 3A 8F E5 AF 8E
+ friendlyName: Valid Rollover from PrintableString to UTF8String Test10 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,42F368462FD41A6E
+
+J6jl0z2Xi+k0qZhkOOe3pRwWRHtAwleFoK62+A33cMjUCoUdkMgp93wUJhbUHQ6r
+zJQnl45FJIM9liljaTOeFKbcQgZx6w9ROFeqsBbEjZfOmEV30PNA0ozdK4ojfepP
+PJb9TUCCGOTOaLIovgGf7+tjqK3HR9ofvPtqMfLHnFsGMyNnWhD3+DwK0OT02gnJ
+U7tkc0xxMVJEJpLImZIHf96lI9152SxNBZjDXZeA9439DKDCifE4aSy/hiNdB1qP
+2mXAZFAl5fkLVvm0VQqpPJRzhHRmMnFjp7ACzg+rl90yZEVhW0PXpc6sRC1lKNJz
+YKWJoWmhpNJmdp6ZEhf0FkrMIo/FhGB7ZBmi/45DRV+LxsuemqtW8iKRZL9uKKAb
+9OGdLp9lzLLP5YUwklerFvtCDRDG5VpwzlDKBl+3cn7f4zXGCsVinddDuJDcx7Zk
+KOdKJ84eguNBe0Kyv3cjQEJOLVe0L1XCD+468AlR46Skb1C//gzyHFOYQMUHWB6X
+8S7dHKc9eFvgiN2EAhWwts+7g58qH+FAqgJ+mUs/ewjfIODD0fLhlNDPMyLRlKcI
+8Jl+vVezS5li/83cdNN9irnlX9Bg6CQ2SCK1ajQSfZSWRukp0y2vgFKIDlh5Ipam
+b70eqlO3qEmUbvjV9n50O4h2rex5c3194ci07A87P1jq9KiUztKaa+zorohlkJN7
+0S4YTKmb7bmiO0JeaR5XpAMPu13l1VokOXNeUNVb+5kFD+gEsGkTrwlQP3e0+hpg
+KTTzkgahhRJ4JVq5KuF7MrsEr444nFneO+TqJSY8+h/nDFU+etIuBv5B09msKxbv
+UvnvLR5gKNbMMpICsOk53Z/Bx/q/n+C/qglKQgEYKDfbYaGrg5jC3rmIzWopi7un
+LFwmppV8rgM6tWBjwTL1AmEE6LeLDVGd+pdQutq0wSjw5LMeK2YQXRZYpDFBBvhP
+DpOoSX9YFDLP+DzuIhQir3kBFFMixTpTTp4r14slmwejLk8aRoSohX3F8PxbctEJ
+qaBa8fNBGJVcYRSKzkskimbWA7Y26H0Qdfj8DXYfKRnyXsV1HBIhUqDb1Lp+q5Xn
+TaJ5ZVhTh4CME3tdgAev9LkguC+ddsP4ZEe8FXWtBIa9EbUhzqJVvbL9yXC584XQ
+BRx0SwB5SaGogL/6XJJhdBpinoT1zjwZPd0dqRQc7fC22zpJ4vkQL2KvqNkpBrWG
+rMAOKwkCPphOYItWHNx4nyr0JCrxMzrbEkWSE8aMOpkW2w+xq7iVRcwSPcltYxPs
+pfmJE16qlRjzFCsnrgdP1pJ7gqfjtgaOeV1Bwo7iD1gLKqutHx8oxzAo0NZ7ZAxt
+FmAKN4e3sk85jmOmRrfslsgX2hs4goL3VmviqVHBgPWGsiWqHu/a6Wi1x/owtmS7
+sFkb05Z7ZYtd6G6IsSENo3fTsT+m/uM2Cozj+4SBHVmTW2XUfJMrEVmQ3Ttjq09L
++a5W869ClGXL7Q+OuHmILFfhy6SIlLq1zJo5897bviyp3WvIdGdHcGBgTxFDwNnn
+aQu3o5RtAnJ9OCQp51E4RRwy6vp/HYj+ye9G33zF2efEvn5bpa/u7w==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedDNnameConstraintsTest19.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedDNnameConstraintsTest19.pem
deleted file mode 100644
index 32e7d402c4..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedDNnameConstraintsTest19.pem
+++ /dev/null
@@ -1,130 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIIChjCCAe+gAwIBAgIBBzANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBKMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMT
-Fm5hbWVDb25zdHJhaW50cyBETjEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAMqEGhcWtsw26V0XQSph1+hgHUlNVe4yFus4l56oS+MKdra/qys502m3Is9s
-KPNUyWAzPUBCaj37+cC/lnojJTpZw0lyfOSeqDAfbcDMzp39U2ujHbqQ41fGTeIJ
-haOs4hUUIapsmLZ/1iETEyHFfB9ib5oSCPAMvRtDEvNwITDvAgMBAAGjfDB6MB8G
-A1UdIwQYMBaAFE4uo+fZ3YungjtBSsOefFkjV05TMB0GA1UdDgQWBBS3rAnyZ9I5
-cWLbrRE1M5H8lPPz2jAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEALE7Y6U98
-nXWJYm65/DslSMoEgBrKSB8w4Z2y+sE41dhd99EFWOwUV3UFoVk+IPgmvwpdpXcf
-n1CZdWh9MvR7lZ4cBiSRoWLz8D5okZPX1HyarXNSQwJjZv91zs3/xi78DUrOfW5f
-nE5txAvRjHP7PrMcb/gatjC2p9oKDpW6+ro=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=permittedSubtree1/CN=Valid DN nameConstraints EE Certificate Test19
-issuer=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
------BEGIN CERTIFICATE-----
-MIICqTCCAhKgAwIBAgIBCDANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJh
-aW50cyBETjEgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjB+MQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGjAYBgNVBAsT
-EXBlcm1pdHRlZFN1YnRyZWUxMTcwNQYDVQQDEy5WYWxpZCBETiBuYW1lQ29uc3Ry
-YWludHMgRUUgQ2VydGlmaWNhdGUgVGVzdDE5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCtryyDuHNmy8nLnEcuJZ6bwOq0A+ka/Kj0Um0Xgd1sop3boX4Rjv1q
-EpvwNZoizR25z5Cw2J3wfdrtm/CtazuoF+2O9M5/g7STTtPUDAhwiR2uRWnRKpUc
-SEQaxHFmfdaPAJI14E5BhrlRRHxHu6kNuENcF5lwuGUcxuL68jhsbQIDAQABo2sw
-aTAfBgNVHSMEGDAWgBS3rAnyZ9I5cWLbrRE1M5H8lPPz2jAdBgNVHQ4EFgQU0BJ9
-iRt74wy57LStnAe8vRiy+8wwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQBX2LLxEBd+in5MEzdLeQNWFBzY
-B9CJ1quGFFe2AfYozACv7MzAiHJj1rU0ik2bjYw3r8mUIOEBuYyi+5syyK97cV8z
-e2FFWRCkUkcOWt2b7AizbFVt0M9IEFnhTsM2nVCeSD+f3wO1IYBzINkqwMqmnejZ
-zThT0HTy6hrX/maRAQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=nameConstraints DN1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIC2TCCAkKgAwIBAgIBPjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWbmFtZUNvbnN0
-cmFpbnRzIEROMSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnL2vzTK+
-WcGR2rmlezdUTUQkfIvzcTWRIVW2x+BxQPrPfoLqmpYZar4sY8ND0l3pQWcIFsGY
-AYmm2vHULqUxZMW9R/dM3wqstOXd2JJVxvw/v4ajYB5lPNcrv8LyxxjVU2daqlYX
-BCfL9/O6417oYys1UKNtEp6n6HV/ZbEJG70CAwEAAaOB2DCB1TAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUTi6j59ndi6eCO0FKw558
-WSNXTlMwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
-BgNVHRMBAf8EBTADAQH/MFkGA1UdHgEB/wRPME2gSzBJpEcwRTELMAkGA1UEBhMC
-VVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRowGAYDVQQLExFwZXJtaXR0
-ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQUFAAOBgQC9ypqhZWCmrISRla+Nxp/vshOs
-UQcyF9Se7PBrkAfl37dg70aSgX0/6Xef8i5v3MRCar6lM8x+coBMHK41VUG9g6VW
-2DAoCG3ajBCj48vN0Gd4dUwvsGAmmVuIwH0R/+2IBMp00341fpjIjUrMpxcxDFwe
-Ve3YFugTb2fMnETR7A==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints DN1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:4E:2E:A3:E7:D9:DD:8B:A7:82:3B:41:4A:C3:9E:7C:59:23:57:4E:53
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 99:8a:59:ed:d0:76:00:b5:5b:70:91:75:a0:4d:60:16:df:72:
- 71:89:61:43:5b:d4:65:f6:8d:0b:25:39:17:86:6d:1d:c4:cc:
- 19:3c:20:21:71:5f:a3:5f:d4:52:e6:d1:c4:cb:39:92:65:80:
- 74:46:a9:5c:7c:7c:c2:4c:1f:8d:fb:aa:bd:4a:de:6a:3b:0a:
- 29:ba:9c:70:13:84:fd:c7:aa:d3:03:99:f0:93:3a:cf:cb:e2:
- 39:e9:e3:1b:ff:10:07:a3:51:5c:ff:dd:da:a9:29:05:12:3a:
- f0:10:a1:d8:9c:5e:ec:0f:c3:02:cd:f9:ab:b2:d0:36:32:0e:
- e8:eb
------BEGIN X509 CRL-----
-MIIBQzCBrQIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm5hbWVDb25zdHJhaW50cyBE
-TjEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQY
-MBaAFE4uo+fZ3YungjtBSsOefFkjV05TMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAJmKWe3QdgC1W3CRdaBNYBbfcnGJYUNb1GX2jQslOReGbR3EzBk8ICFx
-X6Nf1FLm0cTLOZJlgHRGqVx8fMJMH437qr1K3mo7Cim6nHAThP3HqtMDmfCTOs/L
-4jnp4xv/EAejUVz/3dqpKQUSOvAQodicXuwPwwLN+auy0DYyDujr
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7.pem
deleted file mode 100644
index 4b8f08b93b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7.pem
+++ /dev/null
@@ -1,178 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgDCCAemgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhp
-bmhpYml0QW55UG9saWN5MSBzdWJDQTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAOJaxR70a7a1EjJOHlf9fG9BEsSto4MGr1bnQLMud29/o1aka1mDrcT4ehXL
-RT2j2lOFHI+7Cv5UrjI2iI/CWsH+z+PM+sB19pJmrqshzC5FwfeHDzFTUsn8D+5R
-WJAx3NZbB++nDKkIIPql/K61Z8VyKD+3k7nNSHvXV+dKCWd3AgMBAAGjdjB0MB8G
-A1UdIwQYMBaAFKeFECzgAW7nVCNqd6KPFwSv++MSMB0GA1UdDgQWBBSryEEAJtDV
-TOYrVmfs74LEwt3yVTAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAA
-MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcBSBfFavoevmu4Jr
-Fzz3LyHSA3rWhajms8ZL6AtVPDfyQaJsZizVZqKYejWLXv3jNCri/c5BBB2XTXdD
-zAQfwr2W2FfXMkNDUWt95C0NOF7NK5Z2XbmFMGaqn8y/rsYv+Zj7zl98yp0efRKw
-JEDyqFgkV/+0sLFjQvvcCdY9ucM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBAzANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR0wGwYDVQQDExRp
-bmhpYml0QW55UG9saWN5MSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-vcxz0dHrlH/i+DaS78z2Y0O98xlH0yo64kCvWxGo//3ZvMZl+wyQwcAOqDnIH20X
-Fi+G9BhwuyzlaqMenvEQFImtvvDspxYtq/xqmTHET1+9rkF0f8Ex8uV9VgGGMJFB
-Kjax2S+jexoGNro4EeLopi6cOXBgeqwkzcpdi0C3ugECAwEAAaN8MHowHwYDVR0j
-BBgwFoAUZtu1lMcFxLM+K5G538io0E0rNEQwHQYDVR0OBBYEFKeFECzgAW7nVCNq
-d6KPFwSv++MSMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDGuWkVLrBfOy6K
-Y46FaTMnWYkjBWyjC9mgPrq97h90tejc8Z+5Q7u+WD+f//iSoC19Uy65lnk10g56
-UqaqA7zZQ25N28un3YqnKwS1pWrtUGNiAi3vYPUkmwq+6PJvWAcVl56td6OmQOIO
-hDwXMBUcDUYTCVAMRY5fiMx7ARRmeQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Self-Issued inhibitAnyPolicy EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
------BEGIN CERTIFICATE-----
-MIICmDCCAgGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGsx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFAMD4GA1UE
-AxM3VmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJpdEFueVBvbGljeSBFRSBDZXJ0aWZp
-Y2F0ZSBUZXN0NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6DBDhDh8Fq9l
-WtOenCnLV5XS52CTXaNqy6/fxR6xw6bm0s2p2D0Br1TeO6qn9oxXMMohGo1XU/wk
-hUbde93GnnMNVlPZqTvaGvcq5OjaE9Y7r/QE+P/dSV/mXJsmIbwbba/n4KqgF6yj
-XfJ5QXz2jEVWKIAESIUdsz8i73joVw8CAwEAAaNrMGkwHwYDVR0jBBgwFoAUq8hB
-ACbQ1UzmK1Zn7O+CxMLd8lUwHQYDVR0OBBYEFOlqW20Og/KffGodN27T80jZjAQu
-MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZI
-hvcNAQEFBQADgYEAaRukvyRgU3wxzMNx2864sByNAhV3ujEGeCMnBn3DLfeM5ioo
-PXYjuq2PEs6I+o55xSX1cGwCtcZHay0MGiz292T5DUrhDJoN8nhJ+yNjzsjB2kpv
-zJrDwMEv5liNVCtbsVNMDCBsje+ukkmbmVVVzpRlnmVmwrWsX58V/pX4crU=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AB:C8:41:00:26:D0:D5:4C:E6:2B:56:67:EC:EF:82:C4:C2:DD:F2:55
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 85:eb:03:68:bb:91:5d:9a:09:2a:f7:5c:73:90:8d:e8:4b:23:
- 92:c3:d6:b3:8b:81:ba:d2:b9:dc:a1:e4:48:29:a8:98:cf:59:
- db:2b:1e:de:1a:ce:db:cd:5a:dd:de:f5:f3:91:13:9c:1e:a6:
- c8:4c:d1:ee:24:10:7c:95:df:a0:ed:4d:f9:a5:16:43:89:af:
- 18:f6:1c:24:b0:70:9c:62:86:07:f8:0c:e1:61:d6:99:ed:7b:
- 88:58:9f:79:d6:3a:1e:ba:aa:52:97:13:5e:00:7d:00:ce:9a:
- d2:34:9f:0d:bc:18:09:f8:10:2d:c5:d2:8f:d7:eb:a9:59:25:
- 45:1c
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kx
-IHN1YkNBMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUq8hBACbQ1UzmK1Zn7O+CxMLd8lUwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAhesDaLuRXZoJKvdcc5CN6EsjksPWs4uButK53KHkSCmomM9Z2yse
-3hrO281a3d7185ETnB6myEzR7iQQfJXfoO1N+aUWQ4mvGPYcJLBwnGKGB/gM4WHW
-me17iFifedY6HrqqUpcTXgB9AM6a0jSfDbwYCfgQLcXSj9frqVklRRw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7EE.pem
new file mode 100644
index 0000000000..1a0b274eb0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D1 24 53 94 24 5B D0 43 A2 2E 0B AD E0 FA 9C C4 A9 60 7E 0E
+ friendlyName: Valid Self-Issued inhibitAnyPolicy Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Self-Issued inhibitAnyPolicy EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDpzCCAo+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowcDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExQDA+BgNVBAMTN1ZhbGlkIFNlbGYtSXNzdWVkIGluaGliaXRBbnlQb2xpY3kg
+RUUgQ2VydGlmaWNhdGUgVGVzdDcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDZ9LivETDywp+a/tfvaf8DhVHn9pKQKbNwVl8fS/Dnb9gyV5pPIalWgCr8
+GoG0PFzmXvqA5eqdyEKzVNIJJyfF1ndYOaS+xs7DHBe4bszm56a+VXus9FdMOTSN
+4h4L+D6C0hG6+ock4Y+TmXhPl+RKa2/S/NSLrXjk1pGOjLgoUVey7USRLSr0IP6R
++6E0Bto5TBPayBPUMRBUnhmmjg45nxAyHYxSsz/K9fhgpYFRfKeRafgV6Ndz83oZ
+KJx/OywOV4e77PD1l9Cgzuc1s5OyWmb1tb440r+o9+FzF0eedHGD66qHmXpyCHJy
+77ojQsHrMacGyDGXF8+QeEox1iqFAgMBAAGjazBpMB8GA1UdIwQYMBaAFIwF3N9+
+ZNtivttLUWSMambYXKOjMB0GA1UdDgQWBBTZpaDF6bfRzvZDEtdOEJNc81hQATAO
+BgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3
+DQEBCwUAA4IBAQAjl8+QP5Vo71I9RQDbigx5XlS6Anj0GJ/bVK/WQmZrfHs9JdHu
+FKt7x5LL9AZQ/h7mVmSd8nM2z9KUpK3INlaKV7kJSOvskw3D48KNkD673fJfMkWK
+rcznmtUVKMnkGqDKHBPfGSbXN2XEi2DsLY06Labo1mBEVigtLMxFGJ8OBIMuEtdK
+MlhTISGom3Vs6WjeOcuFwz25vv0AWAJFdv31sFXDcxVvK/vvKkVyAlLJuh0fxw58
+6avoUbtAFZW4gstzibCz+2aYvGoQSp4YatviYArYHYU0qQgYBXk4gF2UZCCJLrmz
+WHhLJIfV/K5UFty8b1PuX2PONdktVBWymOhG
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D1 24 53 94 24 5B D0 43 A2 2E 0B AD E0 FA 9C C4 A9 60 7E 0E
+ friendlyName: Valid Self-Issued inhibitAnyPolicy Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EE86A044B76E661E
+
+PpQ0NzmkhhL7/s+PhSeiuTrZ00n1/Iqx/QU7W/mtKPiRvjq4MIWkemvB0eQWJt1O
+i/stTCta6axqIvM2Zidg7yLIC9ciT9hGf/adFuH9/o0NoartUQCBxfaHNIRo9GXa
+xjRE6W7RTqWCZbuTyqgZFiIehk7Gjm0lzvr0MBk9CN3lPKnfg5GId8W5b6yLWwcl
+10GsXFezVCVF1yQJN9n18/HwcUZYwqyMISGc8o9LIRGMJn5EU6Kii3YsuUwJnvOu
+1Bpp9L78/tmq8cXTwjT0p6dj6CshTacsjqeMgz6sYZgeAzC/Euf+O3mTv45Ah5Ti
+rD1MgvNfuRFazOKbEWyXqzGcEBnmLWI9hQa7yu3BFcYQFDYNgasiizIvMRQTfwjP
+eeG0r735DZzXf+otb80JIvTyZE77qjua6dGbrtaWON1BhV55O23flLXDTf2ov209
+j5X3G9ukMg1UopzLlxoGkevR8EBXwsNa0AT2BiC5oGdtFYDDL7EfbTkDcQIEx/Sh
+veI9CmC24OLPCsUQUJCmqiUiUx4OOubjFIYqXa0NmcwUnO16i1ry3aTa4aA0lS8F
+6zFbuXqFeSHgV4EeLzqu1eZdenl4/TlNzWl6ZGRfQUzyKVoMUUTfhmskTstLBDlK
+UJ7E/BhZ0Up1tbWfjzWjToVXluOg7Aiy5QVR1k6kl5HKkGxq1zB314loPVMjJspz
+cYYbazKOmhNLuSd2Fzg2Q1jRQGFwYtnym1Sjqr0qJ2reQrmEwsdw3kICt4uHrizX
+FKkUTrTT9+65AlVr4YvIGIf6YMC1zW7hrl8Yao0Os4np46hWZLAaCU/RxyZXtsG4
+/YGVUxT2hODR5zTDELQrWCZegx1d3BJveRWldDlU9QWJWbq+X3AzrK+ggjeoiXEp
+/ZY2hLCechvQVCSByt+8TPvge/2A7YHE0MpB9I0M72QAIGy9vAC6BrdzYkKGkR+q
+ypza4n/gS04YnMcLaa8nOo1mdXpEbPT0mCezhQek/eP6Jqzh4WX1ps8uMEk7b1tK
+NDocSlfMOLqarQaKtiwzwoDCdRSlI9/xgu2vMo58DdfV0mzZrIOmY0F0ysZ03SXB
+qRru66RpHXBB0pPkSwfHyVqBdMw7vN8+yXw4ZBXlUIHMAzmLkNMtwdNurdASPmRp
+SwDk9aVT14IryGSevPfZtnrrVMy702CwtxsBJaDfC6KPEsKpJA3qp87WEkQ12Q2s
+xhDNAr9G+v7Q1TIx0EWb8JQfplHdRIlpr54dpLYDNSm1kjCeGEP71CvqLUY69cFA
+aN2QU7+/bEbJOxMB/wG11UvPhRBw4tfH6eV4axLxO2zcVdPct7wlaTQCiUSwKFU9
+rWj4yTugF8zNfs4MVprNHtjF0dA7TEAkcq+6xMKB7elKvxyFt4FN8Ma71+HcPWjb
+pXuwQkbDbiaPuTprbA3UWs7QySRH4D9pjbVHdcSK+GTpVE4mP1lXY06dOvP6c9P+
+qitoYGCUZLVXXuqTzo7v697aV20+lz37na4bI5DcpJ5FsOWQQwIOruHVY/QJSN/Y
+YAF2a0Og5si5SWvjNQnbxr5gqEfNaiLPGnwbM05s6HPdT5crB655cA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9.pem
deleted file mode 100644
index 2ac5275855..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9.pem
+++ /dev/null
@@ -1,197 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgDCCAemgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhp
-bmhpYml0QW55UG9saWN5MSBzdWJDQTIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAOJaxR70a7a1EjJOHlf9fG9BEsSto4MGr1bnQLMud29/o1aka1mDrcT4ehXL
-RT2j2lOFHI+7Cv5UrjI2iI/CWsH+z+PM+sB19pJmrqshzC5FwfeHDzFTUsn8D+5R
-WJAx3NZbB++nDKkIIPql/K61Z8VyKD+3k7nNSHvXV+dKCWd3AgMBAAGjdjB0MB8G
-A1UdIwQYMBaAFKeFECzgAW7nVCNqd6KPFwSv++MSMB0GA1UdDgQWBBSryEEAJtDV
-TOYrVmfs74LEwt3yVTAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAA
-MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcBSBfFavoevmu4Jr
-Fzz3LyHSA3rWhajms8ZL6AtVPDfyQaJsZizVZqKYejWLXv3jNCri/c5BBB2XTXdD
-zAQfwr2W2FfXMkNDUWt95C0NOF7NK5Z2XbmFMGaqn8y/rsYv+Zj7zl98yp0efRKw
-JEDyqFgkV/+0sLFjQvvcCdY9ucM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBAzANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowSDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR0wGwYDVQQDExRp
-bmhpYml0QW55UG9saWN5MSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-vcxz0dHrlH/i+DaS78z2Y0O98xlH0yo64kCvWxGo//3ZvMZl+wyQwcAOqDnIH20X
-Fi+G9BhwuyzlaqMenvEQFImtvvDspxYtq/xqmTHET1+9rkF0f8Ex8uV9VgGGMJFB
-Kjax2S+jexoGNro4EeLopi6cOXBgeqwkzcpdi0C3ugECAwEAAaN8MHowHwYDVR0j
-BBgwFoAUZtu1lMcFxLM+K5G538io0E0rNEQwHQYDVR0OBBYEFKeFECzgAW7nVCNq
-d6KPFwSv++MSMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDGuWkVLrBfOy6K
-Y46FaTMnWYkjBWyjC9mgPrq97h90tejc8Z+5Q7u+WD+f//iSoC19Uy65lnk10g56
-UqaqA7zZQ25N28un3YqnKwS1pWrtUGNiAi3vYPUkmwq+6PJvWAcVl56td6OmQOIO
-hDwXMBUcDUYTCVAMRY5fiMx7ARRmeQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UE
-AxMYaW5oaWJpdEFueVBvbGljeTEgc3ViQ0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCc2RpX4l2ip6DQkyPrZQ5fiP3xdhXT2e4QAznpwy2Z5q9TlYhF0sFw
-yiFNITCwI50K+JrcR/FtOMFTiGkDJdNSD6JJ9KXmV2Ub4/oFXhmdPkkW3+LyckWV
-cpDuhOBoI8E+ni0ZFTuduAa9E8yQX5PKazSSbeERNXFHIdMij7WuxwIDAQABo3Yw
-dDAfBgNVHSMEGDAWgBSryEEAJtDVTOYrVmfs74LEwt3yVTAdBgNVHQ4EFgQU3Ymd
-Zrnid46ozhWkgrKgpMameo8wDgYDVR0PAQH/BAQDAgEGMBEGA1UdIAQKMAgwBgYE
-VR0gADAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAM/wnG9l6jp+
-ViHhfrgGuXyp29iH1trRzZVkRtta2Htz5cEy+DfQ1bKtALeOj+3XycvDjFBK3XFX
-Fj5Kq26Wr29hb46xdtNHFdkYvsyfD9Nmh1OvcqEkW0rmMqtr/+z3bTX+qegUtJ4Z
-vjllBLFSy/60sopz/da7BfJiG3vBvoij
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Self-Issued inhibitAnyPolicy EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
------BEGIN CERTIFICATE-----
-MIICmDCCAgGgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGsx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFAMD4GA1UE
-AxM3VmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJpdEFueVBvbGljeSBFRSBDZXJ0aWZp
-Y2F0ZSBUZXN0OTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqkkaVxrrWKva
-xC65OTtGWaNoO/KVt03UN4EW/fxbAwU79QI6lYLlcnTOpmNlAU9HVGEvunAZ/RBl
-AtZOKSiAGjuEZPkn37sS6SnhR1ANPyNA0KTI9uXIXDKde2sGXwNSbsiQbDko3vdV
-EIfKC00+2GBB7MxARHUpZZ7kGAP4XIkCAwEAAaNrMGkwHwYDVR0jBBgwFoAU3Ymd
-Zrnid46ozhWkgrKgpMameo8wHQYDVR0OBBYEFJf4i3/rlw5BfP8DOFHqMlOM+3vU
-MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZI
-hvcNAQEFBQADgYEAg9u+FJzES1LZQVxwLZwZZ+9Q7q68jcUqdvzV1I0kFxESgspa
-7a+fTUyYDbMr4qZ9zrMbJDDLkwS8a9vSwZJmfLSZYGECYAuTZFTe5p6CeQyToEfF
-l+MA+CUr5ogWe2dpQQ/OmurKn/idqncuvoIpaWH7fvnpOyKcqo27Q2hUhrA=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AB:C8:41:00:26:D0:D5:4C:E6:2B:56:67:EC:EF:82:C4:C2:DD:F2:55
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 85:eb:03:68:bb:91:5d:9a:09:2a:f7:5c:73:90:8d:e8:4b:23:
- 92:c3:d6:b3:8b:81:ba:d2:b9:dc:a1:e4:48:29:a8:98:cf:59:
- db:2b:1e:de:1a:ce:db:cd:5a:dd:de:f5:f3:91:13:9c:1e:a6:
- c8:4c:d1:ee:24:10:7c:95:df:a0:ed:4d:f9:a5:16:43:89:af:
- 18:f6:1c:24:b0:70:9c:62:86:07:f8:0c:e1:61:d6:99:ed:7b:
- 88:58:9f:79:d6:3a:1e:ba:aa:52:97:13:5e:00:7d:00:ce:9a:
- d2:34:9f:0d:bc:18:09:f8:10:2d:c5:d2:8f:d7:eb:a9:59:25:
- 45:1c
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kx
-IHN1YkNBMhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUq8hBACbQ1UzmK1Zn7O+CxMLd8lUwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAhesDaLuRXZoJKvdcc5CN6EsjksPWs4uButK53KHkSCmomM9Z2yse
-3hrO281a3d7185ETnB6myEzR7iQQfJXfoO1N+aUWQ4mvGPYcJLBwnGKGB/gM4WHW
-me17iFifedY6HrqqUpcTXgB9AM6a0jSfDbwYCfgQLcXSj9frqVklRRw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9EE.pem
new file mode 100644
index 0000000000..afba6a5197
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitAnyPolicyTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B5 28 7F A8 5E C4 9B 0C 60 B8 88 80 70 72 A6 FF 8A 00 75 AB
+ friendlyName: Valid Self-Issued inhibitAnyPolicy Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Self-Issued inhibitAnyPolicy EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDpzCCAo+gAwIBAgIBBDANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowcDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExQDA+BgNVBAMTN1ZhbGlkIFNlbGYtSXNzdWVkIGluaGliaXRBbnlQb2xpY3kg
+RUUgQ2VydGlmaWNhdGUgVGVzdDkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDSWk+BxVIg223wvs2weR2LSJ3WElVnaJjergY5PUJWIpvi3rhr36NcMtCi
+KTKwteK0gjEvuC1ViP8SDvC3F1jPx1mJUeCvLO+ykSWCHnoxo4jdtgUUFFazMkQo
+Emf8o2s8xuGab+Me1byMnlNceqPD3q7ncenZumYeleV50CBz4zrz68rdT1/iRd3C
+tSkQzXE15FBx6VVFimfY4b8Gsx/zrCOQtr7uuxwlKljVZIneyV3Oxtk8+9EuYXMk
+Yig9pZSMVMU1nscG/qoPj35p/fduse+KRpGM2N3EebJjMC4WKI731mkenI5rRSOP
+BIwiLPEi4lYgdX/DfqVBiYO2z3WXAgMBAAGjazBpMB8GA1UdIwQYMBaAFMnMP/pb
+8KHa1TcMm86YxnqJK9XrMB0GA1UdDgQWBBTlOtW6qZkT1fSqlvvdOHn/0HslbTAO
+BgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3
+DQEBCwUAA4IBAQAw2XcoqDcFwz7cBnYxG7mEvhoTqnGLOrxF94XpTlAN49BUYfmN
+iQF/mmWo/fA12Y5BwOBcAws7dDB0H428uhtqYBGCxuhzDkIXy3X4zvNO5P5XdrOw
+oel1+zfi4hH3FEKLQmgEjJy2PN2s+JkqZNpxP670/tpp5wwB1DLN2bEc6AARlN5t
+y/pvSd7sVBSXo6FaYO6USn4Fk/m2toWZrCjGZAZCJITWwjwLjQKo19FARC/iUNMQ
+35sIs4EiP8bL/k5HcAZVXECK49Ogr6g9lU9wY9swx5Uudw8/2OstRe4vTQFw99Da
+q6T+4P1VCKTMkXqfc7kR3vey8S1z88l6GO5M
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B5 28 7F A8 5E C4 9B 0C 60 B8 88 80 70 72 A6 FF 8A 00 75 AB
+ friendlyName: Valid Self-Issued inhibitAnyPolicy Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6585A527E4EBD184
+
+dlpKqskl1Pm3ZL7yW6TyxKoq7GkkWTdiIJrvpIVv/49VHbwbkyYuIKOcysl6Ap9x
+0PbPEWvo30f+03azLNfeh3iqGe802aVEiZLo32zVB8I/3ZBOiNEly4w7mWVlQ5ZT
+80QOz2ZvFG73xCh2Ul2/7LDwwaiaUHWo4oj8wsTCHCKMKIU3RK83Rw0P7LmJ7n+l
+qY9TOAiuX7KoWbsRr/wd1Jf4vKtZttp7ymIq72Az8k4K4HQo8JMAgAq8hkkp0/9p
+u41a5oTK1VyvLwKip8+3pdW/BK7I9iYeIKssoLQDduIDBrw9CuGHSJj2OEeA2wvZ
+M7qa/BOJkbVhxjYEpMh29Cga3heJPImY8vvwOwFPGvykTOB+EHujN/aYVv5yt02U
+2vBidukWnB5w2zbJcq6LsBzvYx93b2N+vrXre4YQU6vcxijHOsDdNGW7pZe/osyG
+UMhLGBofkENW0YOq0Q48haOyHLIMeGToKPD5GdOQZx/UXEdIDye7VHbOPJS1ccc+
+Rf931GDa22kzmue5G/Ee+1jh9z3RilMlfbtyVod+Yd1DrIKLFoxr69vtlTWzo1uw
+HkmjqdDeXzq/VEk2CXP6QtP4S3PQJ+FltnT3F0TBe5zX0FF+wKEbEOInYUZr6kH9
+CeZfpyUEp1JYh/4vgpoRxlruVpEBIJiRMXiRVnWwlWZjfmFSoA94SXx4PuknuwcL
+qb1EuvTYwfEMhZ7qyoiJwVPbHsmG8csGh0DtL6/jkq0xCCQ2oYdrTjsUJFPzmmgl
+fLstcU4dNDuwuJoEgfNXg+PqYrPWYZ1VLFlCN4ECH8CRzXhwbd76CDVJv4PAPbNE
+FprSz5G719+1eXcaNUSG+71KAHH14liTxNdW8LAIX9AwhZ1Z014P1Hd2oYWfBUnM
+mnSE33U9QjNdItDP39HZKpp28P4XS9NSwQgJetV/rVlyausQpjE0Puc18o7NzJ94
++bJUg+2oLpMh9399VBymYD/35kRcF1mhcZlcTvu8h9741bA1RQL0D/bdgQLju7Zw
+pb9dfbNiFgFhcjP3WrYy6L/xZ5ifrmnoKE9iu6hrs4omCebowkmlY20MohRa6Dur
+ZBxIsz/Ol2VTlXwHmr+bWTSLfMcrvy0+Fxs+tyhNfhL5Upo02ODEyei+tTE4dXTn
+if7khx2N4ymjWeUEI3W4PsWoTfZGEDXJWxfezD3CQqb8m/Av5pY7v/S1+1Ad2HzK
+2wJ71D3wQpkc4Gp8l6HOvDID52HV0TI2U4028LwhR818qMDOGgEVPtvFTeTLmtvd
+0r2a/WUXJzhB1WycQREadHF1YPYA/Ds/0RSUsBv1KxS8RSk9iTvegY+HcXMsWLCu
+aKKnd9nqhLkL4jnTB16LRJ2zDCKnchdRz4ZZd2R78/nezC4J4m8JmC7FbWZYKJO4
+yCw0wxrvUzbT0iQfOpbC3gbSxAvbQwQU/a9tyMmFE0WLZgOc0879OFIm0UabZoys
+FyR9iPscWcAN2bSCdXBqVeHyVYBfBiOTDmYnybJ8wZOy5u4FiLGDpah1dUbLXkHC
+ZBlI2wJU2PRe5q4kG1unJq9p6Hhl1SEP7fq5WJtAPz87iA9dKhh+8ouGPZ+szY0f
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7.pem
deleted file mode 100644
index 0a0596b259..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7.pem
+++ /dev/null
@@ -1,180 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-ME8xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIG
-A1UEAxMbaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCX3X8GrbxUXCENLok/vrVUA4snN0DJ+ja+Vct+doODtUFE
-99ZdYrT+qEPGAkioxAKElsWQDHoAjlv/TjoSxbV6BURJiMk+pIdN/N3oOtLz9N5y
-emO4Nq8Wv3A6dmTeqV/BvhEmKyKd9h/0Vy3gTP/eIqA8vhyxOpPLAB/gKIIWUwID
-AQABo3wwejAfBgNVHSMEGDAWgBSqaWS1UuWiYwoKoPNqFz8gsgPUtDAdBgNVHQ4E
-FgQUbFzipWxbYKUZ3ncFU1rjNTWvrRswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUA
-A4GBAImoE0/jphqmO48yRD2BCE5RlbnLVfXqKMbZ61lxs7X2Z2oC7QmmXJ8xH0vu
-YmnqpQTJjLwJc6janX9zk3DIdokB0PPu6HAtSb3GeETMG2tQFA3aeDyg8xjqGNBD
-OHfNDd64bvLnKZWb3bLEPfnZf6WTaRV/x56wf+7+NPg+zJop
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBOjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEkMCIGA1UEAxMbaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA
-643DGHdT8CXwVc2GtZQbRQTdptkiSzy79NPJD2XLU9LpWnrgyGzl4j7xUeYVspxY
-Ws/mpZCQOb2hs8eDfHKisjtcKj8Y8r0S8Csb3dsG19Rmjbg/2SiF5ZMaHzPi0QAk
-m008o0bwHaSBlFHigtvqu563VpgMs52ksx3BV1BKZQIDAQABo4GRMIGOMB8GA1Ud
-IwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBSqaWS1UuWiYwoK
-oPNqFz8gsgPUtDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATABMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgwBoABAIEBATANBgkqhkiG
-9w0BAQUFAAOBgQA3+2MqCUqi2aRGC2CQMzptfla5lfBz0GLy7p1VBIoKLOe6/rAb
-IhVjO2X7pWEJosnjfmKUOggaCctxUuGgA/okQKTXTXQwXJwJNv2qS5lf1AHD4B99
-pZ5ebQ5FJ+RZBB6HiUWabWVfJ41WPI7ceJ8fh/Riau+XJg2KLE8myngRMA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Self-Issued inhibitPolicyMapping EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
------BEGIN CERTIFICATE-----
-MIICojCCAgugAwIBAgIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3
-MjBaMG8xCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFE
-MEIGA1UEAxM7VmFsaWQgU2VsZi1Jc3N1ZWQgaW5oaWJpdFBvbGljeU1hcHBpbmcg
-RUUgQ2VydGlmaWNhdGUgVGVzdDcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
-ALAZ39MGl31J7AeGVi+NMkr2Za9Sm9LwaUKnv+U+4kjo1pvbj8KegARFAYToj7LF
-KujtuYlkH9HC9PW9p0X0zlfGyLo+jYBaT28HaJodaa2AmpEz0ZxmLsEBnjVNlC/R
-+vUNa51CNV85Wv2V/FVkznQSlqdRP/89SCfIL/Rd/rLRAgMBAAGjazBpMB8GA1Ud
-IwQYMBaAFLamwerAUlPfhv1mSeS0Rr5jMwwVMB0GA1UdDgQWBBRFegfFmXt1cyLu
-vHj7WA8p2BokYTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMC
-ATACMA0GCSqGSIb3DQEBBQUAA4GBAE1aoLRAB7FVyZHDy+jfyHRnvk2c/hNkhsYQ
-VuxpPqQnt8pCBUl9lUAwlb9W1JoR274/B4pIYmqM869ptHJJjbbNkOBdudX6462F
-v4rtoK+1egfyqLiEcmQNcGSqq7w6tBw1k9DV6t8D1BYvzh6JfN7z+BY4b8dOq5O4
-2eSGt5qS
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
------BEGIN CERTIFICATE-----
-MIICvTCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBa
-MFIxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEnMCUG
-A1UEAxMeaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDlD9RQqLmz1R8mmDv95sxGdTT50F3U2U2PHAx0M0R/
-EmmreJx8mubNNUzKpH+jIQCsgKqAH+CJH/LDeCzow3F/cS0bcKYF/x1hJhJHO+pP
-uBgIa0yNq+hkNY9F+V/b+auEovg9yqIThiE9atAWfL1IRnRW5qpSi7si8qQdGWGt
-iQIDAQABo4GlMIGiMB8GA1UdIwQYMBaAFGxc4qVsW2ClGd53BVNa4zU1r60bMB0G
-A1UdDgQWBBS2psHqwFJT34b9ZknktEa+YzMMFTAOBgNVHQ8BAf8EBAMCAQYwFwYD
-VR0gBBAwDjAMBgpghkgBZQMCATABMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEw
-AQYKYIZIAWUDAgEwAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
-AAjqz5quHRrfjyt+VRbtAM5KfKQS9G5SMsxGGdD/A8Nu5JYAN5FGi9X+RjLqeBzD
-6hmnFNNPFZx9LtO1s4wBoM06zoAddrIISUWehidWkxh7YEJSt4OSQ3fHNO0lgHaC
-WnvV8cZ3JLFezL+4ZDzXUJYoxmGCjerFTfIszoyvBuu6
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AA:69:64:B5:52:E5:A2:63:0A:0A:A0:F3:6A:17:3F:20:B2:03:D4:B4
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8d:01:00:85:8d:99:b7:5b:7f:63:14:5b:20:de:25:35:78:25:
- 50:56:9d:78:eb:ac:15:34:90:c7:18:cd:03:ad:4b:80:9f:b2:
- 09:73:d0:8d:c9:dd:a2:5b:e5:c2:9e:30:ad:09:06:ad:8c:56:
- 7b:39:76:aa:1e:13:a6:21:2b:68:c4:93:f3:39:fb:7c:7a:f7:
- 2d:e4:d3:ac:5c:a6:38:07:9e:f5:b7:c2:54:6c:e7:76:9b:2e:
- 74:5e:cd:83:1f:25:c0:d6:4d:af:ab:29:47:dd:b0:87:79:86:
- f3:4d:89:80:2c:21:14:68:ec:4d:cd:67:d0:88:94:63:d1:db:
- f7:a4
------BEGIN X509 CRL-----
-MIIBSDCBsgIBATANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYD
-VR0jBBgwFoAUqmlktVLlomMKCqDzahc/ILID1LQwCgYDVR0UBAMCAQEwDQYJKoZI
-hvcNAQEFBQADgYEAjQEAhY2Zt1t/YxRbIN4lNXglUFadeOusFTSQxxjNA61LgJ+y
-CXPQjcndolvlwp4wrQkGrYxWezl2qh4TpiEraMST8zn7fHr3LeTTrFymOAee9bfC
-VGzndpsudF7Ngx8lwNZNr6spR92wh3mG802JgCwhFGjsTc1n0IiUY9Hb96Q=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P1 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B6:A6:C1:EA:C0:52:53:DF:86:FD:66:49:E4:B4:46:BE:63:33:0C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- aa:fc:6a:e9:aa:6d:46:16:9f:65:05:ec:bb:4a:e3:de:fc:ee:
- 4b:6a:61:7b:4f:ca:b0:86:90:90:f9:3e:ee:42:70:bf:70:51:
- 0b:ab:f0:b5:51:4f:78:f2:03:59:1e:5b:01:1d:6f:79:b6:d9:
- c2:38:83:22:b4:ae:64:06:63:5a:af:04:58:6c:a1:e2:3f:64:
- ce:f2:24:20:0c:a4:77:52:e1:cc:23:3f:5f:a7:89:20:85:fb:
- cd:f8:c1:09:98:bb:62:c3:62:0b:75:38:01:b0:93:d6:bf:22:
- d0:18:ff:04:52:25:72:bc:c9:d4:e5:77:fa:b6:84:9d:bb:d9:
- 45:a0
------BEGIN X509 CRL-----
-MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0w
-HwYDVR0jBBgwFoAUtqbB6sBSU9+G/WZJ5LRGvmMzDBUwCgYDVR0UBAMCAQEwDQYJ
-KoZIhvcNAQEFBQADgYEAqvxq6aptRhafZQXsu0rj3vzuS2phe0/KsIaQkPk+7kJw
-v3BRC6vwtVFPePIDWR5bAR1vebbZwjiDIrSuZAZjWq8EWGyh4j9kzvIkIAykd1Lh
-zCM/X6eJIIX7zfjBCZi7YsNiC3U4AbCT1r8i0Bj/BFIlcrzJ1OV3+raEnbvZRaA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7EE.pem
new file mode 100644
index 0000000000..bf2a529743
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedinhibitPolicyMappingTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 61 B9 99 CD F8 EA F6 53 12 3A FD 97 C1 1C 23 66 63 10 97 6D
+ friendlyName: Valid Self-Issued inhibitPolicyMapping Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Self-Issued inhibitPolicyMapping EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+-----BEGIN CERTIFICATE-----
+MIIDsTCCApmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowdDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExRDBCBgNVBAMTO1ZhbGlkIFNlbGYtSXNzdWVkIGluaGliaXRQb2xp
+Y3lNYXBwaW5nIEVFIENlcnRpZmljYXRlIFRlc3Q3MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAzlSgxeR9mZZ2DfvlsNsMlfrKR1y6GJY4fciG6sC9DoRB
+7sqa+3lG6pzDngc/9d/M9u85ukn4AMAsPZAgi5X6Q5dz9byxtr/ACLKumzRwWJ78
+7vVSNc1Fl02DimJqpaVgKtpvh74Z0Li2EUONNxVmM86vcI6+K1qVnLMWtdrSpQx5
+RcP0ak4XtVcxSFKBrTpZw7kplIenOiXBIVlO5f2yADWcpaJw299I0n++7v4vQrJt
+3HWs5aDA4if8w5UsQvfWPL6IbYhS5spCRAu2Ta8TAB+mY2k/sLyYo/1HV0khIG1Q
+5J1pFdw091TkMnOf0c+yG48BeXG230snsTTVpV8DKwIDAQABo2swaTAfBgNVHSME
+GDAWgBTzzQc/gzDTxwJi2ubKbAGlsbaAyzAdBgNVHQ4EFgQULYSE/2xcGw+CRD5T
+hkfTUDLk/bQwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
+AjANBgkqhkiG9w0BAQsFAAOCAQEARKXDv0JsjAw+svbFFVLJWn3Fan9X4ilv2XPj
+c25T2Z8dd5ydw+a/fSuZ30rowmL2YFnWeX9D3i+y542eBEQbzHkj+1oc/JFJ/34M
+trqzj39TgmrQbM1D1SOb7Y2uLRXpZu2jPUuAld2jPJvFZxCHTf3LRb1dW8F6uAs2
+SrfZdeFCA7fXoGJRO4z4cCWyROOQY2PHSrMKNAh2yWFq56qlj4iNmdv86/My8MNf
+zlciq5ApLsPhTIZiRwuAiAnDkeVUjo0u1PciJ9oQUZc2TuEqcUudjtl16zTEw59Q
+Qk9v21HXboMBS4QUaQ8WhtwL0sGOMNKSw13LgqFeW5IPswaGsA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 61 B9 99 CD F8 EA F6 53 12 3A FD 97 C1 1C 23 66 63 10 97 6D
+ friendlyName: Valid Self-Issued inhibitPolicyMapping Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5122396833385692
+
+rjnACDyh31Laaa/Y+Bhg7d73sCGPBKAmBkHDMgeWMZHftHStCvjZwQIs/0BKTZoG
+jm7dq2L/Dj6IwEMr0jAVF1eIVuxkJfwMfxGWPVjA8yyaFOdATPiTjkshRLBiTQVG
+7ev3SI9icZl+D5q1vFBuIz10ngHpuPFW+HnBW6VchmT+pJC62F/RfxzoUGqwHGns
+1Zse0tyLFt88yLfFBgm+w2lFBuZ3tzOK3NxacdB9/wOk2ktzgGKw6hjyRSZdDukk
+hZEc/mTMslZ3IApu5exn6x4RbLLBQfJdjGdG8vjOHzE9f5F1QS+feDwv0v8RiKZE
+zcPMF5gS5GjGGCaq8jBsbJBC7L3h9mQib2Q/QUpXp15wznTEpWHQ/QQRd8cRZVDw
+qBllDSLaacMvZZ/1B8vGWwpxdLqj0ABDZe48QD8df+TcXMD2VOXvguPEq5n279pX
+X+cdGcNeITQq4C8dZsVE8xUHrOfEB06mN5JjUcwPnxb08vnYhmEDKWt98qBvKoxJ
+znfAgmdD3/QH2YSgW+VsK1Cs1Xj548zE6wPa7GTbUsmfeEMuVAgLIZJBlaZe6wH6
+0af8RapkwRaPfSYvc4iJKTcs6OOVPIvrILYU2NmFIFEbrfIhc5ezCoHKUVmtkVg/
+PtLOnhdTnj9v0quMCXFJ3TKxe0C4S5QbhkWOTfmZWAntVAbpk1eJ4JPp8F/859O5
+98oA/5g5c2xR1c1jADqSw2KbFrpbyHTPEETAHSL/xqzInCofh7ErknB60Tf7I2gq
+sOLlcFKEqBU9kp1zuma4VKx5MMvJmLYyO7jnUezt05TeTACgeSy49pJ3/or5SHHf
+7kQAIh+oDbmE4jz+MmIBddW3Cfw+3hCCdCM5u3Rb81wvSq/Gs3eHBxqfpDi++fjK
+9H7XhhEcapvpVmKotP0D9iBeqG4PXUWiGgt5+861A1TZe3SFnFgIc8KBsPcgOKqT
+pls/JEd78JWxSCzeHceMwWb2Te9Ej0yVoPePX4b3QDsbdgcaGTtC6RdzBYBhiOZD
+33oFxB86IkTOLVwHechMTY0RRig/BqvZNSgzsTdyvnEa/m1OnkYOwqnvq4vAYfCM
+Uvfl/j74lViRii7fPeixt0Cd9R7PJe1g3hBPw7Q4eytOKRE7Lb/rv5dkCQo0to/Q
+E3B352q4sANo8XQD5v7EnRhv2JSGqL8qzY1t+ECQhT6llVDa8T3Jb2qjwtL4VKOl
+2wEuiT0rGVcGfDppFUgE58ms7ZjdviFKzbT4yL9nsiGQPfFaZ0VmmNem92NLEHuX
+FvOP6oYcrJu9a5dNmLwWPMH28F3cJMvw6JrRmI4/KPxy1QqEUYleTtW5wvp7lfhX
+KwN5vs8NfN3vidFIluh8ILE1/BuTeJl2i9PQt5wn6v5vIuYIlut0VTsMyNI4DUG0
+oYxnPR4L1s0AXn+ONSwQ8+AnUc7hHcS8rhX4yZyioXajLqXhFzhXiK9MfeAxPhge
+gVhylvKZYlO/BMlDejXxeE9JmWuCVBHwcGSLw92D0i0vPq2HpaZal9W5+3IQfACO
+YaRu5tDk13GiqKk7cY8LVjC9rK+BNhUjVvRvz5QI63mPpglQ/gVwkg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15.pem
deleted file mode 100644
index 8a81ff92ee..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15.pem
+++ /dev/null
@@ -1,127 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXXXPbNnk
-MU3wxjjwCdA/Pj+lwkDk8WSxKGdOrcPMnFnrCdUnSqEES3K6/T7JRQyv6Y13Rt6w
-LAhrQI94UBcsAAQND4SOPyJUE3PonzcolJQ+EzkSB9qq6cxJokxTvxVTx2VN7bN1
-RJ7FrWovHu/vmKnwsOy3zv41U6KBfuf04QIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUIQy1AXZ207MqrCb8qqZP8tah
-b0swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJUd83zrSjxfaGwFdTCt
-BSI1mTeztSKFxIzrWeTxD3C0JHAxt1oM1AN8DQ/Ej8ja3rxhzsFQaWzdi3ixvnGr
-NbjLZH7EPWBPSSC2rTAcvLzVs2AuPsBkv7IKxg7HTJZtLbXDOIatWT+24OuKwTzE
-6cbcSe7zaz5qdojy0B72dLHC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMV
-cGF0aExlbkNvbnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDDqMCqoLUxLw5wCcxhD3+5J80k2C5ESu+Co4n3V3Nu2SyzcfKET0wx5QvxYm5V
-bzsntf6IudJpfXgzxHIwJ4i5v+Ycc8NYiqmCNhsW5sFRzhjQDyTWu0fEYm+tmyBv
-FavwXAcp8ptUMElDMAv/bKSD+7MDC9uHZQOmVsY0ndcNUQIDAQABo3wwejAfBgNV
-HSMEGDAWgBQhDLUBdnbTsyqsJvyqpk/y1qFvSzAdBgNVHQ4EFgQUOK0lyEJa1w3p
-SvQY5iylU6RQ9EwwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAA9NjcDXXcF4
-FXkwZWIDYtowLXCpbshsU80nGx0/7QVNApSTnUq9pe0t8qAClcYZuaXgB/uYINl5
-qozAW6KR4wFaNUv6mnm+0ppWeiTnIn5O37IycPbAKVZRhauf3p/cTkZ6RZ3MJ5Q+
-fMTJscvSXtMhU+Q3Pp5PGRXlXhs1zFNp
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Self-Issued pathLenConstraint EE Certificate Test15
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBBTANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMG0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFCMEAGA1UEAxM5
-VmFsaWQgU2VsZi1Jc3N1ZWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlmaWNh
-dGUgVGVzdDE1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCb61LTuxE1l5yJ
-QVfNdf8EYvZcAa0KaD4FMFo6vn3YTkLfUAgn2P0/LUtJQmmXciZPTEU9iKaYsV+/
-ZtyT/p8r/UHfo81aRT9dIzwK4sGKK+9KWFi/rPiRQwG5IB3XiQYW/JGTIPgcXg5Y
-dUXWrtqZVN+7ddhQD1d1ttatbEqajQIDAQABo2swaTAfBgNVHSMEGDAWgBQ4rSXI
-QlrXDelK9BjmLKVTpFD0TDAdBgNVHQ4EFgQUS4ujjGGj4+FAN/SRPltJJo/KxqAw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
-9w0BAQUFAAOBgQBh3iDLcsaywxCRTsUrSXJ+COkZOvwrPiAugkf2KeDXYcrIckKX
-n/+Q3FZeBn0qHNyvGUTLp7yei9kUto1sS0nrShwSV+dn/2zUsL6dr4F9Lfazzvsp
-rIIGkJCHbcJSnMc2b3dBhKr1Oe6MWWnV7OdTVCfjQXeDciB3MTcY1TqedA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:21:0C:B5:01:76:76:D3:B3:2A:AC:26:FC:AA:A6:4F:F2:D6:A1:6F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:7b:a5:e5:64:8b:31:64:fa:9f:8f:a3:25:ab:8b:c9:c2:ba:
- cb:b9:e3:5f:3d:e9:b9:f4:f4:f4:d8:00:4c:cc:9e:5a:36:b3:
- d3:53:12:aa:d5:ba:ad:94:a5:21:16:c4:9c:ac:3d:3c:e3:2f:
- 53:69:97:6c:2e:e5:82:98:31:e8:47:f9:8d:dc:ab:e2:8d:ec:
- b9:3f:b2:61:20:ad:22:24:f6:ff:90:4a:14:92:38:0e:9b:80:
- 3f:1e:11:f2:d8:7b:fd:d4:0c:90:06:82:2c:48:f8:9e:7e:91:
- 55:0c:21:e8:dd:95:ac:90:c7:d7:02:af:84:f4:23:08:bb:da:
- cd:a2
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUIQy1AXZ207MqrCb8qqZP8tahb0swCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAVnul5WSLMWT6n4+jJauLycK6y7njXz3pufT09NgATMyeWjaz01MSqtW6
-rZSlIRbEnKw9POMvU2mXbC7lgpgx6Ef5jdyr4o3suT+yYSCtIiT2/5BKFJI4DpuA
-Px4R8th7/dQMkAaCLEj4nn6RVQwh6N2VrJDH1wKvhPQjCLvazaI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15EE.pem
new file mode 100644
index 0000000000..edbb2acba9
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest15EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 0A 55 CA B7 29 D8 79 D7 91 E4 AA 93 F9 D3 AF 71 37 0A 67 D4
+ friendlyName: Valid Self-Issued pathLenConstraint Test15 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Self-Issued pathLenConstraint EE Certificate Test15
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBBTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+cjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+QjBABgNVBAMTOVZhbGlkIFNlbGYtSXNzdWVkIHBhdGhMZW5Db25zdHJhaW50IEVF
+IENlcnRpZmljYXRlIFRlc3QxNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALTPBtTph0kvovSb31pRYt9egyO+d7Eq9BtlSFiZ5UyYGh5UC2FGcDP4tzkO
+5si6Vn4yZ/rwqIMNyU5bkbfludraX1b/Uc1kObROQfOgEApaE3JuZSVjXEwJsojM
+yBYCf0FErkdYAgzDE5czPhH+NE5ENiI0+cox341aVJ17bK9wK48JP5ajt378Y7Uo
+sLUG8hY6d5fOJvE9Jg2IvqCXLuSfWzJtCunT5Qlf6qASV0rrUJWdmKaqstNbqq9H
+Cj+IpQJTrwkF/8rPkAnuJcjqRbCimdpVqYLqF6EPAv29rTBZyKd1qktm5n3wjcQ4
+hWu4kEHG/KPfSC+pvk3OLa3FD5kCAwEAAaNrMGkwHwYDVR0jBBgwFoAUgOtzvk2Z
+npS9F0ta989Xd3TDX3cwHQYDVR0OBBYEFMjr2VjA7usIwlcHbZp92KG3YZu4MA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
+AQELBQADggEBAIKqRjt2Z9NVFsBaFffuOhB65G9/ZP0VnAz3x+5EKuUn2MhbZEnK
+pMS6dDI51ot5gK7PtxyXH7DwI9Tq8BlkpU5UMspeKKwHuBe97IPsSeAFeQX2zkws
+yz7KW5QIezi7ijyNtWHilzKeK0uMh5pMAkNVoLH++8d1PYgG04EYxZlHZTedGSj2
+QjiBc2bJQ/hTQSoXjXlFK0auVmMOohKxYi6ZgWstGGDdoY+/1qe8vWBqn3e5NSLu
+oqd3L3jD6g1rjc15SEadJfdQO7xMTdgnJWqij0N4rcxo6EzqFVvt8FGUNwCdHJFT
+B1Qi4p0aWzKTaG/KcfnyuEyrAJB42RZI+LA=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0A 55 CA B7 29 D8 79 D7 91 E4 AA 93 F9 D3 AF 71 37 0A 67 D4
+ friendlyName: Valid Self-Issued pathLenConstraint Test15 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4A1C2B404665D30D
+
+uWUUPeXKS8K8I/MHrcV2NhxxM6t454hkTYt5XcYl153J87tuHDi++fxw34rb7+f+
+Pb4o5pJh2COqxjAu8pl49JdZS/UNz2+C/F80K3JvdX1Vo0X1IplqcRSGb2gAa0bC
+1pCbtuyy4Nq9SAmGN6B34lROUOEC8/vIcee4SNCMnxLW1H+RDETzT2MAjMDI2lAy
+vibpRIAbtILZguDzrvIr7I+FGzm5Vc/0vHX4B3E2qGj1EnRotNLNNY5N6kg4vSZR
+E08+L8FBgC6iLAfEDk3jpYkInzSATLn7jgS4eWIbIbEFjuT3mhBPDN21Zqh7U1tX
+qOba61l5fgdxhvreWfRjwxSiuSOnArFxJU3KaaF5hoK/4QkZsLZ7jHUQLIsIzfMd
+ro1LggW03w/X0y/Ip1ArqFbND4YjlN+cDaSy2hKNLb9SqePSwLkdy9QQBv5UMhtl
+RC8l+RtKifQCw4hGHG1+EyznGd+1kh6E6zwmv74QrFOnJmvLI+4kiCLpXTi/4x+O
+RXGvtObalCEjaht7nkwpFZfFzVxmRWae5mHMHYN01fXGwFWwHUfC+Cjocm/8EvGi
+2nmJRfYzQFnrU76dluvAU4d8xYhSfDIkHTOJHF5AAg21UR1neuqj5UgHUm2LM/R/
+T8BZJjuevVj7Fg6uH8AxkHN7vkf7rcxEY5IXUZKvG/IN956QpBDm7VcobT4TFqwL
+UtwYrM/hGza597qIT1oJqy7ah8VIYbKZTE5gmA+fI2eZkjqm4ex/HOsZKW7BzkyW
+3GEiKmU6d7dFN5XewDqjMQzBNlzD9Y5gRhrHv85WeRA82rBm2qv7+20d5SdO2lIU
+VXfggBI+KYclR6JbE+z4qPPdJ1KYH7BQmMgtE4TOGSFhX52/nCfuR4jxT78unGyX
+FByYPuiJJCG5bCXIukwoh88Yyib+o9YbUjaqQ6sfRSgwiv9QocOtwRlxXOA+kZv2
+s0fUr06cK4BSDTZ5VlHFNQJp1Ub5nWxqlseVWXFcJ0JWddlzvGewKg4Unvtl2Q/x
+MbvFF/27VY0Uw/XTHbTazNeeCn5OFFeOigyMvpxE8hpu9Hbl7pWKs+LoE1NsJjaK
+RpGRIIQcX6O3VQbgWeY8NfYRtackF1FwtgkxE/PodNhUC8YV122htf2mzKsXjQ/P
+2z9xGZi5NW/95bTAX5FKPtP6KsdOQXRwpoJjxzVdPkCncbgn3B8PEK8Wzoc7Is5O
+xhjaf0QIkkC6UD2MeFFv5yaUAi45Ivwl2TOXqNaRp2Mjb/rLhSLNCDJ8Vh6P667n
+PrQ5oMcqq914DBqYM20Cg93Pt5ZZk8GZQLywCFTulzuf92oyoxMX3CWepNxXmUYh
+uELcCywkTnwT2kCClFj+cbhFTNuFILN3CnwPs8QpIJjOPcwdnvL7Si19EqGOhUFj
+ifavYAGGKwkUfIlXwf8IuRNkads9jOqZCpALgDH0owHai3afBgKlyx8AEvxYbEV7
+bF6il6oyy8bfo2sz1ikFwF4qFBBgDw4WtiA/Wdmo1j/NfVNvIiRjs/vtu+KzicEn
+/LKj7N4Y1rlJXxEffLYBnKNO7bPbw18o1Hp6IdcPAFFjK/Qy13JzP0p6yV/ivRen
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17.pem
deleted file mode 100644
index 86dae42c9b..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17.pem
+++ /dev/null
@@ -1,197 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBHDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZDGq53SMD
-2pj9pTu5VRCJI+Vm8LxSBkYdxD0jc4IKrbJH1NRh5XCcfeAbJaQ46UJFGEPMa92B
-GOSF60SQg5oIXBDTA/ygWIPFFbfStUt//heg1BfHUHRf14z8JL0HzXDG6xnd+2yK
-FzLzKFu1zexVpeT6nFQr0rjeslXftjJO5wIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQU2nOT4PBlmX3Dv7AfJg72Fi0x
-NVkwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBBQUAA4GBAFm1ZyLmtGk/Ml/36K/q
-S3bdDJ4PWyY0OsgJBm4jiiYU7QvQ5G7cyfPW4h8EBaPOg4HSUGJJdqQQdP89e9WS
-JTFOlLoPT910pCDXbuEjILFrPh54Gv0ydO31Yc8Un/Do/qEraDgWzjNU9s/BAJKx
-zeFg0ajkR1p+VLGzDM+n2aQI
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint1 CA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint1 CA
------BEGIN CERTIFICATE-----
-MIIChDCCAe2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMV
-cGF0aExlbkNvbnN0cmFpbnQxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDEsgspeWC5HV95asByD3T2Xp92XyIayyvxljyNsuyivQG/zdHVuW0QqDbM9+ua
-rkOgDpqwN93uEtbRdQqq4u0MZ2GXR4k6ZduPsubfFKXBKdgvLBoSm1qhOdO1m7BC
-GYe/0e+uiTYZGfLbJCqUuDraLY/o58qeKUHln2Ex8G4wAQIDAQABo3wwejAfBgNV
-HSMEGDAWgBTac5Pg8GWZfcO/sB8mDvYWLTE1WTAdBgNVHQ4EFgQUC9dNxXZ6/vA1
-xTWKZjIu1jdIF2owDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBADwD62Ebsv+1
-RcA3YIonWoTkrnKU9YGmmJf5S9ytmc6cT3phWRpY/sOl+Y0pNRvDsKJeew9ggQWD
-f77Pp+ACX2HvWwSHzclox2iCkxNyX0aNAxa9xun2zKGm2j1Ncb/D2mE9CQemmn0n
-1GxEkjg7psCUxl2FwuTTmRR9UquMxjg8
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint1 subCA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint1 CA
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMY
-cGF0aExlbkNvbnN0cmFpbnQxIHN1YkNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQCp1Y+dMUczZ1H6dsRs9hr8yLDsu+xA1vSG+vHgAEPkfkhzItj+7N02gtua
-ye1hSXd/x5xNHOTWUK0CDY2YnHBpqmVO3nMIYmX40BbsRl8eQiEYQS7ES+URwrbW
-LHC23HLYn/R42TA1lkwp3HUa4Nu4eUEXKRMbCVfpxAE0h6brIQIDAQABo3wwejAf
-BgNVHSMEGDAWgBQL103Fdnr+8DXFNYpmMi7WN0gXajAdBgNVHQ4EFgQUYXPbCWI1
-alu4YhJII+f4K948S9swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZI
-AWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAB0eGyRF
-KEbsyDnKd8pB+6YhJjQBcdZl9AGLASF4jPmFj2iXuF7gr5rT3UTvquUeEJamAZc1
-L3pHiaPZnxbVJ8hTSD4eUF0YMDd+PzboODwLeBS/5AmWQ0O5qiohjgFTMUq3uvkf
-RWemBcsCiI1KenbGIFTJaNEWKdPrsOrocVJw
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint1 subCA
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint1 subCA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25z
-dHJhaW50MSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UE
-AxMYcGF0aExlbkNvbnN0cmFpbnQxIHN1YkNBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCvkVm0hGNZvdPCElTss6nzgzq7tC28/UHHYKozUaenLdgSaARQnZyi
-w3O5hCVSCtOMmUog52Av5lbkjZxVhCTaWKfrBuPDE2FJSsz2RczG+89ho8676aQ9
-Y5tTt3/mECuV21fCVjRh3IU6O6gTGgPSOxmOyE/lMDXTYFYgsfF7kwIDAQABo3ww
-ejAfBgNVHSMEGDAWgBRhc9sJYjVqW7hiEkgj5/gr3jxL2zAdBgNVHQ4EFgQUVVEA
-f8ZkXgn1BiXGzZK3mreZsTgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAJNK
-lQDUQElDsFY24HDYmUDNg4Vg/CkEB2M9JfI5yZYlOKJrjzECJCY219NFeL9TcyD3
-bJY36GS1ZMz/MI9ocVTU0K5ssZqV4IkBI9hXCFlb+kw5jSgO30RoxXm+Nb0nvzUC
-s5kRJVI8Rdm4ONIstsOmX7w7LBMWrgCPBOZN6zkl
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Self-Issued pathLenConstraint EE Certificate Test17
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint1 subCA
------BEGIN CERTIFICATE-----
-MIICmjCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25z
-dHJhaW50MSBzdWJDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMG0x
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFCMEAGA1UE
-AxM5VmFsaWQgU2VsZi1Jc3N1ZWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlm
-aWNhdGUgVGVzdDE3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNwtcQ87sc
-VaUKAcu3QxtBteOc29FtwvZtv86nDNlJ91gIoFTUq1jKdkWcExlR8lh+Ye0QfIRB
-NIDkDs7+2WB/BwJLNMpaEXDh0qETy/SW3uDN0sOX2H3ik97y0xD5ayXquEXTqgIs
-fNtXesmjTnBt3iitX1DkPwrjuJmQf+co7QIDAQABo2swaTAfBgNVHSMEGDAWgBRV
-UQB/xmReCfUGJcbNkreat5mxODAdBgNVHQ4EFgQUOloj8eT4jSRn3dhhzDfEX13r
-FrswDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
-hkiG9w0BAQUFAAOBgQA8hwBcf4CCZAko0xnD1MoTNUBfjdvDcXZB+bTB3jnbDXE5
-zSid6bUVBNo+awlLpnQw3drsAgI1G9TcgFOEslX2n4nMP4FZAxsjpyDPSA7Wdj+t
-xb8/kI5UhKZTjNYIL/LXpfWMvzhiMhTzha8PFxoGFM5hGYMXqh0kK/0zhThOEQ==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:DA:73:93:E0:F0:65:99:7D:C3:BF:B0:1F:26:0E:F6:16:2D:31:35:59
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- b4:8c:0a:8a:f7:34:0c:91:f2:7f:29:9a:e6:6f:dc:e6:a2:3d:
- 90:31:96:5b:53:0d:2b:cd:51:e4:d9:dc:b8:f2:4a:1d:b2:e8:
- 5e:93:60:85:16:53:48:ef:99:f5:13:20:34:84:95:88:1d:df:
- 30:94:e4:e7:71:fa:f2:eb:f8:e4:50:6c:fb:7c:e3:b7:29:e6:
- 91:b7:5e:70:f5:c0:29:ed:50:6c:4d:20:b7:79:e4:a5:63:8f:
- ec:d7:1b:ac:9f:4a:4c:d9:44:3e:f3:17:fa:5a:f6:2f:b5:f2:
- 51:f3:b2:82:90:c7:4a:93:8b:27:7a:a8:a1:00:a8:26:3a:eb:
- ef:4d
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MSBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAU2nOT4PBlmX3Dv7AfJg72Fi0xNVkwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAtIwKivc0DJHyfyma5m/c5qI9kDGWW1MNK81R5NncuPJKHbLoXpNghRZT
-SO+Z9RMgNISViB3fMJTk53H68uv45FBs+3zjtynmkbdecPXAKe1QbE0gt3nkpWOP
-7NcbrJ9KTNlEPvMX+lr2L7XyUfOygpDHSpOLJ3qooQCoJjrr700=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint1 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:61:73:DB:09:62:35:6A:5B:B8:62:12:48:23:E7:F8:2B:DE:3C:4B:DB
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- a7:22:08:25:d7:e6:5b:3e:63:fa:c3:8f:f2:bd:64:39:45:75:
- ec:4c:5f:19:85:38:ca:9c:99:03:95:9b:4a:d1:93:62:04:28:
- bd:18:a9:79:27:31:d8:41:38:7a:c8:ae:81:5a:42:25:e8:46:
- 84:31:cf:e8:38:ad:f3:a4:3e:a8:4d:71:cc:37:18:89:14:5a:
- 5b:7f:3e:a0:ad:6f:95:7d:34:1f:3b:6f:ff:a4:a3:58:14:d7:
- c7:58:e2:d3:bf:33:3d:bd:59:f3:7b:63:fc:57:ab:62:f3:06:
- 27:72:a7:9c:6d:0f:b4:37:12:0b:8a:02:3b:e0:47:3b:23:a0:
- 6e:3a
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGHBhdGhMZW5Db25zdHJhaW50
-MSBzdWJDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUYXPbCWI1alu4YhJII+f4K948S9swCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEApyIIJdfmWz5j+sOP8r1kOUV17ExfGYU4ypyZA5WbStGTYgQovRip
-eScx2EE4esiugVpCJehGhDHP6Dit86Q+qE1xzDcYiRRaW38+oK1vlX00Hztv/6Sj
-WBTXx1ji078zPb1Z83tj/FerYvMGJ3KnnG0PtDcSC4oCO+BHOyOgbjo=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17EE.pem
new file mode 100644
index 0000000000..0ea39a26fe
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedpathLenConstraintTest17EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E9 27 B9 05 48 33 63 E4 D4 5A C9 F7 BF E0 31 5F FC 3A 47 6F
+ friendlyName: Valid Self-Issued pathLenConstraint Test17 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Self-Issued pathLenConstraint EE Certificate Test17
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 subCA
+-----BEGIN CERTIFICATE-----
+MIIDqTCCApGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYcGF0aExl
+bkNvbnN0cmFpbnQxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowcjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExQjBABgNVBAMTOVZhbGlkIFNlbGYtSXNzdWVkIHBhdGhMZW5Db25zdHJhaW50
+IEVFIENlcnRpZmljYXRlIFRlc3QxNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKZ/110TQ4OpgLh88109wvt/7WJQ1YHMugQV99n4Pu3kdI1VQO4ckrNq
+m+LBgYBgZ4Z6EswBTKiEmP46zxnhjiM2j3NXU/qmWvrH/mr1z5gME2iJZgO9r9Lf
+96Bi18e+hA3D8TvaCvZWSJJRyRcGb6eMFPW2YVb4lTUetmaSlI/RW+4nUghXyww2
+SyWnugMA3lS2zg34mchaDWI1OGpDV7HlYI59pPPfdhuGmaZ++dWbtB7EcB8FtQX2
+y30Rajgn8P5J2I7/bl4Y7GLbQMZQoLlG7zjC/OCfew/EmJbzowST3P/SauI0j8xZ
+8ZLW7B6/EhdaiUBSyv1zv6WG+zl8/RcCAwEAAaNrMGkwHwYDVR0jBBgwFoAUeQOH
+Uyk6Hr7o1BjlBDSDK50Rx9YwHQYDVR0OBBYEFB7n3xAM8NB1qQnavi3TtjaSwfmT
+MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZI
+hvcNAQELBQADggEBABZWiiHlZ/a+B0lgBpqprSf/4g2EZOQDPmGOnIm+UhdD3ahy
+z4eVaeNlr+ksEkxeFW+VHOTsoQWEJm01WMgr3m4DJe/VJnyZP3/yKlEZ+IVj5IKD
+hfxsatOwWgETAH7vVlpjLjoH5z1PJsXWKP+Jxa1P1J0DQFA77osQHcWb6m9FUTkq
+EMSv6FYZgTULTfF0EILCP/ldsQvu6YMXeJr0R7QEQ8w1Oe7jujOq2E+kH+LA7t7b
+AxlFz9YFxyxw9ZFTvhCw7qjRijgaHSiT/V6L4uc1p3G5d6tFt6Az+rhsC/3lyYuY
+QDF9LwIhI979SrewoXdbX7LPMQJXRAxBr3eGLn8=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E9 27 B9 05 48 33 63 E4 D4 5A C9 F7 BF E0 31 5F FC 3A 47 6F
+ friendlyName: Valid Self-Issued pathLenConstraint Test17 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4F9E55521636738A
+
+rHxtRgfl+mxRQFp2Shnwex6F1zvPQrZys8bdezcYipvnhPFKp95cQmsC4C0FV1l8
+XAHoENSowrqw+14f1WPVIEAD8kj7uGzu1K398uFUT5YAPZXRMBHVUfdQ5NJLSz4x
+NH5amRGk9ZxfQfvCxs2QxRsWRUPq2BulHbvnaI9JB5ExvyCz+XI5tK3OXNmijt8D
+qp4/byO7UP2wjKwOa/mxmb2xyKJqopq0LrL4oCPqwSJw9NMlByb6xSESBmVwX7gK
+ggVoNGoFbWVKEWKRffGzqvIVhOsOX8kGnuoJxKxyiRtblram4xz5tTK6n3+ZqfnW
+iwVpcEt4s0qwVvjUnSN3Mx4qtdc6tio0nIReBYSQVwmmF3bNYIcsrm7vf13qxN65
+zWXhGr+QHdNLXWqxrluYIGTbITUVgecOwYdt1rS1o7GWJbkqCkxvp+WrUEBNgHPa
+NG1C/ke3RPBNhxQbiZw20rxSuf6+/Gb+hZ6P7I49pRlmjudWTbowcQiGrKwIz3XJ
+j+c3e1vBKtvMJ/7h80g/Li1Rr4sVkxB4/GP/JsvlR2VsaHP3H+taXxR/L0KRuE1G
+RfWXmYig9q9wZS3MKwD+70ARWvyYYewErh/qs1hbsyUhg4ZZlJZzr1vmnwd3LTcT
+VkSd0c25Q4KZSRjb4SOtTORXBuOq26Vqk7n6aQTeckht8qyA1tT/m+iH0zhmOhCE
+7NVH69VWrU+FzJu6qBTMsKwG2st6qXOwWMKTUclybS6qZBpt8Nj6lkQMDcX1o5Lu
+wigm+ZbKmywiSIQfB6Fvy1cGB9ZWTo0z2HGY0mhZdLpdlM/NZ+5HzhQW/ISKTVdh
+mr7mnWoFmUSjjeEoUv8UVrJvpwjupnnY4VPBtgQfIDjxLii+u0K2fKwqiBzQhx8m
+5rJyFvrFtnZn7i5xqoO3rzcLlPWeSY7LPd6LuK7ucpUH1Qg2tJl+GkM64EJSQgaA
+dvIaSG3Miy8uUwKp8hHSpYZQ7fTU4afki76pkzXALVfqV6IGBtwiNF7VcHc1xl1z
+eZ4L39UrNO6DJWiHW0b/cZeL72/UxvA279pW22hV8Js+9LiGBNnIUwf+dseKhVHc
+taIM4UKQryBDM51T7d4bv+zCj7tGh7EmHjL9QciKshKoHGSmS2vxtgTNEKDfn1Yh
+cXSc5D3/ulLjn/0KylSCUPPiphZ1UfzRH7WOWKJWrBoim+zej9KApBd5RHI7mv2D
+XrbWSiaz1gb9fmjgbZf98UDn38JfG00n++QXOCvqcuAK1DW4DXX4nejXxCm4TEto
+OsekMGfIyF1nHh2Wk05JHHeO0KZyEKqJtd16BbjtLdKGg1lkK+oNVnyAW0n/sfEk
+t/B6Ibk64jQlPmij6rc9DkehMsUatXyYr7FI4ZIZ6Y6aAQlVciTXpAcLB/Anmvom
+WGKJQKMDyifu4VqjcINlv/uaQbaUWZqsZTgE/yTWzNDwodL1VnQnVeUm9Z6CT19H
+b+FgAfE9fPTCObTzigMpEqpdZK9R/0zpI5XTYUua8IrloCIcVeD7s1Jb6f6WQBol
+UmifyirkYx/hnGLkwr12fwKeCRYkp2k3oEPwKTu8l6X8zT6i8QDnYw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6.pem
deleted file mode 100644
index 6a4851e249..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6.pem
+++ /dev/null
@@ -1,127 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Self-Issued requireExplicitPolicy EE Certificate Test6
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
------BEGIN CERTIFICATE-----
-MIIChTCCAe6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBw
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxRTBDBgNV
-BAMTPFZhbGlkIFNlbGYtSXNzdWVkIHJlcXVpcmVFeHBsaWNpdFBvbGljeSBFRSBD
-ZXJ0aWZpY2F0ZSBUZXN0NjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoQSf
-MbaUeJHJyhveLx+voUuSWxwNEG56mZ5evCeaSjObXqfeHXkjtfpbQd04wlsSw3CO
-OP2TR4ompdtrgHYGZeSsXW6VhkWz68SG78tn8laoXw3lTMhgrYqAdk+giv71qeBZ
-DYVr+mZTxBnmhrgRiiAQi8fhl9p+Bf89nbW03icCAwEAAaNSMFAwHwYDVR0jBBgw
-FoAUE+aMwSsPZ0tMeh0OtsAhWiSZUIQwHQYDVR0OBBYEFIGUYNMP2TtFxnkarnPH
-B1oeM5PXMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQUFAAOBgQAXMz/QAcFC
-0oNUODgnlOJdP3lcECIPpmtJbhAmc3UABEXUG9ak3/kkMNENOktNt62qe1/K1c+l
-uYkAMsmUn3oOGYV9Zu77IiiChOYDH6touQtxBGtVTG9Ki/gdaPWfqZdfBs0xkGRg
-7mzJCvRrEXDgQZW0kR3C2LJ9B4f2yt2GlA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
-issuer=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
------BEGIN CERTIFICATE-----
-MIICjDCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBs
-aWNpdFBvbGljeTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBN
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNV
-BAMTGXJlcXVpcmVFeHBsaWNpdFBvbGljeTIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBALnxr9bA0oGlaihhiPR0d8F/y9ai99F6w8+DtAfGlFtJ4WU3GPih
-ftUTRqZelcu+u6hZgekMwVhjUHyo6sFt5SfbCzJEmjWxI1anTrGAAcH6pG7zF2Z0
-iae8kVE7C8GOgwm+F1Y1RHkw8Wz/UbZ4QGIhzA++KPDi2du40LEGD4BZAgMBAAGj
-fDB6MB8GA1UdIwQYMBaAFHHCPE47NWL3JYefvaMBHjjgJXTIMB0GA1UdDgQWBBQT
-5ozBKw9nS0x6HQ62wCFaJJlQhDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
-B6X+ALEMO8yG/lXfGuoX4XPyaZrb1A8oWFk2ZNCx9QIzI6CQ0vRfO47TF20iK5wr
-HN8y7yXpJGZcNTa5+697/kRziJ/zrNiL4b4BP6QRxYv+3Edq7FOb842JguqWw6nP
-SfsshPhMilo3C4X3PESiI67m18AlqgJcYcmemF1R6Ng=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICkjCCAfugAwIBAgIBLzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZcmVxdWlyZUV4
-cGxpY2l0UG9saWN5MiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnrdC
-9sroeA9MJlV1ukIu8XNT9cUF70XCDwxMm5vKZZc2+XVNwgxe4aGse4bPdZ9okZ7y
-2ZMuLyDLEBZaA7GsBzG6snQRgHkmMFS6v+pC3ep9ieqtpnrP3b1f743Y1jFp9zvX
-ZDoddeI/xvYF/73KgiYdTFPLa9ARaKiwpQPMXyECAwEAAaOBjjCBizAfBgNVHSME
-GDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUccI8Tjs1Yvclh5+9
-owEeOOAldMgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
-ATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOAAQIwDQYJKoZIhvcNAQEF
-BQADgYEADGhYvyIjl02LK5PZdbH9TrAFF66SGgdk+7nl93vr3XB9UnpvJqUfyG55
-ljoX+kKaRd7Z2O+GLTMmH+tqjMQ6bW+7RawMpFVzfhE3EdAr9/K31K6Q6lft8NuP
-wgqhDrrVqYMPa3YM7n+ebATJ0DJ26evfQu5HfIL7Cs/w+CpXi2E=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=requireExplicitPolicy2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:71:C2:3C:4E:3B:35:62:F7:25:87:9F:BD:A3:01:1E:38:E0:25:74:C8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 95:0a:96:af:24:83:ca:92:a2:7b:e7:d9:50:bb:49:ec:22:19:
- 7b:a3:b9:3d:5f:b4:8c:5b:76:25:27:88:6a:26:24:c1:e1:cd:
- 3e:b6:ef:b4:0f:ef:85:7c:0e:95:9b:13:fa:dd:c0:bf:7c:fe:
- e1:d9:fc:2a:7a:2f:fd:48:0d:11:58:69:6d:5a:e8:37:26:30:
- 67:83:83:90:4c:b1:9e:6b:1b:04:d0:8d:60:42:88:13:25:91:
- ae:42:24:ea:61:ba:5d:34:6a:7c:22:6b:be:cf:2c:e0:67:36:
- db:28:0e:5c:be:bd:7a:75:3d:ac:cf:3c:9a:44:8e:ca:30:7a:
- e9:97
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXJlcXVpcmVFeHBsaWNpdFBv
-bGljeTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFHHCPE47NWL3JYefvaMBHjjgJXTIMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAJUKlq8kg8qSonvn2VC7SewiGXujuT1ftIxbdiUniGomJMHhzT62
-77QP74V8DpWbE/rdwL98/uHZ/Cp6L/1IDRFYaW1a6DcmMGeDg5BMsZ5rGwTQjWBC
-iBMlka5CJOphul00anwia77PLOBnNtsoDly+vXp1PazPPJpEjsoweumX
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6EE.pem
new file mode 100644
index 0000000000..f7b088202e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSelfIssuedrequireExplicitPolicyTest6EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E8 14 25 DF F7 E9 44 A4 76 C8 32 2F 31 E0 FF 93 D7 82 55 4E
+ friendlyName: Valid Self-Issued requireExplicitPolicy Test6 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Self-Issued requireExplicitPolicy EE Certificate Test6
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 CA
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MiBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMHUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMUUwQwYDVQQDEzxWYWxpZCBTZWxmLUlzc3VlZCByZXF1aXJlRXhwbGljaXRQ
+b2xpY3kgRUUgQ2VydGlmaWNhdGUgVGVzdDYwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDbNiXBm0YtSk/Ghd0P94U5XcIcxuUottE08ezytyJXoHrNGEdQ
+qr8VdETgymFh8mzVUeMJkcid8m4WNoWCRgLJ+79DRInPxLrJr0iN/A+KFE4JmtKr
+cshTYXlFRZ2gNdgDtkQ/zS5ZbkssumE/R4Y8RQRUeSTu2VdnRMaAb/Hey6UWvv8j
+cm79m4y7ZJ1m7Q5nykQkzrerHkdSM+9a2d7gQzWxMqPYZr54VEoKHfsWCBpH6vPt
+DfahIBmc0wkScZm3Vty6ILpYqx1dCbRSC1jz0gU7wgCq0PLVwWksfs7uO4XSSIji
+U8tD6x7fkn/KiecfEJ9a8T08CvnBB8ZPPY/XAgMBAAGjazBpMB8GA1UdIwQYMBaA
+FO+r2tjhgDGnQxbuxHYNr+xt8mChMB0GA1UdDgQWBBS9gn/7u3AKjxkoylIClC3A
+ACjrnDAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0G
+CSqGSIb3DQEBCwUAA4IBAQCgEHowL+jSGlcYfdQLxsHaH/Q5gbvXHZXE7VlyZfCZ
+bMB9SL6X1zZYr99nM440HkNQ8kvENLrjG9YzbDCj2ykFpfAmyHGXOa0U+LEXvXnK
+NCPXbm056EYJwHy8rE+LpFaSYD5Qcc7puf0ToqCfeAZbVaVnl18urIP5tTeTqbdg
+w84ha1R7A7vtDaJG0B+ZzhafN0ru0BBWU0POm5boPr5+s/Hm0ywIHhpAELDoQM/h
+gLyUbObTDv9w9m1d4GIREfaUMKt6vANCpxTMUSJI48JC+JyN1EqbyPncXRKWhl+l
+76t2DNnwcWV6R+firtZXTFvdWOPgCJO9JkC9uHBlXxM8
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E8 14 25 DF F7 E9 44 A4 76 C8 32 2F 31 E0 FF 93 D7 82 55 4E
+ friendlyName: Valid Self-Issued requireExplicitPolicy Test6 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,91C67D9C3260E50E
+
+4TaEdXpD/8t5Fppfj+ePTCD/BH+Gle6MObc8lIkh1J8lQK+DGhu4KLfFjDJEA8by
+QrsEk0IYk5wMMHwsBRx1yYY2KYekHNBEDD4SwAtcgx4GtoFWoCUdbQzrTBMNW0C/
+f1q4vV2znxSOYwYDKXNH1DWR6aRaSxW4kHUNejjq2jqs1j8Z1NFrhTrZ6HlKiKcL
+SiSvFC5OL8YqzQlVGL1ZfB/yUU8Y9LSJa0tpAfhnf+GjvXE++QeXO+l6s/xhHpZq
+bgbScTQqwgrAhuTxO2Te/AGTMqCK10LRj0XjqzBRr6rPWz2hXOJTuytXuPOVS+1M
+NwKMoPaElvgOIWZ/xPGyY1hI0lK/+hhK3hmSoPoEQLNxLLo1Re6mTrTfNX+ZQAdc
+RHFX4p67WrI35CUDBUfhOkmuBbGHlKzf9iEQ+Cxk0UDDHhMOtrwxwhT4c96kRSCy
+c8KLigv8w30dPTtdDWZxeRUuJpVly7iaGp5kc0O78HsSCnnduUIzHicXZcZXqHOC
+hydl3pOFjIDfpd8Unn5ATne1asUYDMFo/EdwcbEfssmxMgFfk1x9HrPX1GqmyDx1
+yAWeKzZcLv241yGIoV52Ox7YpGX+HR5gNX/Eyi38dMBNFHWSdHWrKBjluIw2KBUH
+kFW0NKjFJ3ukOel29T6U/6j3a5jNd2Lh3Inpn60PLPzvMn8e2feBKTKNBxSfaOAk
+av5hH0wUpBeuu+l8bpVTGE9/5ypt7Gqa4ncOiIyKeLO4fwFTYSmpyaydWxq7T2Ei
+qmGdIdzp8Mx0Yb8ahmbsImrjOK7JRS+lCvQHGif4Wrl30apkWCsoZMfmQx+qCbua
+Y5sJF+qrJsX27oRj/ud6M13xYl+um8RRTc1JfKO4Ja5bDJ1aCyG9i/aWaoCNydn1
+Nx4lylUCdKRoJLoGOC4WO0xNDMUuecoSEBOUQMYpJvlwgq22sj6dnAb11+y72LAh
+Sg44oavW5AzUhbPDmPdGdaCX5GxtpqNJQ4l4AaJEUfRlRvRDPOmV15FpjtM8VM+W
+Q82b64SV0EF9nOw8n6tfLqcEH2MGHtjbVoHRtqGToSAY135MbqVl+DknwW91en71
+MdBFtQo9Zxpekl89OTHQ0UerE1hkd1NgGgB9G7wp/I8CW6Na/S6/s3t2bc9tDUtk
+lAGVgQjgrq24EUq7Gp4XqmrDdhWstJaO803f/10b9TXHfVFF55nRufwFUZygv5z1
+csm6L9XEEkMDroeJRVghyzLmiVcb4/LCr2n5MkBDLwbbW52ZDsJoYxBID8mgGK8U
+McfcegF+AvJBlSEGYJ2EXOTfEs8r+DIc1IcOYRk9pISm+QFGJtHAHNLeA7HCo56X
+gvoVMAvYvpFwJ84EGgpl8Xa8PgY3xhXPf9YSc29DyR67v1y8x/EYvH2U25u9hUWf
+9aDGWPcKfW2TCRLK3OG3YEISBDLSH6p5FVWBAhUogDyiq7StzjIQn0J7qdHVnFyq
+hec7EOKh8Hvtm77TG4dzfWqAaxhHDbxNu+bFh9JTcweJftu/kvWVhsajYLwGqJud
+bptwGHUYoVtIY+Af2PCRyIxYIvRRxZCpgGBjUUEIRNlwwLh7SjQGhQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19.pem
deleted file mode 100644
index 1af71df043..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19.pem
+++ /dev/null
@@ -1,134 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICejCCAeOgAwIBAgIBZjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlU2VwYXJhdGUg
-Q2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAzpVbQYnufknoy1tKbCSY840pKcfP2S+jFm6OFC9hzkLFn9uiYzCV
-rCjczQI8lFfM/4p9rUApMIgp4IUAxCOEcgJuKPKmiuoTwPD9XxbmZ/uv+iaLXqF+
-QVcbDGouj0z6RMNz3KGtf0pbgg+/+/wIK4c0XOIM9wTSK0aJVqweAnECAwEAAaNr
-MGkwHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFIr9
-Qil7WXhSSvdIHHG3xHGKplfbMA4GA1UdDwEB/wQEAwIBAjAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAo0h6slmGQJsCsth+yeyOMK3j
-2CqJ9gEajx3fWs7x2JJ8LM4zfbFFYctGPKpXdGRBTO8Dj9lQJCr7i1IMMHTitTa/
-xpjn8E0SQgzvkB/0BnSt7DiwV0LXCdtBlLxOS2Fw9NdvbE7jsuBK2W4KDOPElhHJ
-TKQ0T3TjKv8gwxTq8mw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBZTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlU2VwYXJhdGUg
-Q2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEAtI4Yuumg8WznOojgeWHVZxG23imfdB9ntiQccDxAnvywEfQv6Vlq
-HNVQ5vsVQfvfUZCad2Nbf42DHRtpmVhlxIhKBjoNu/m6xdvz/A6/kvDvrEg+7M7N
-A2ZRVI0T3Z/mMaPuLHuCzKwU20TF6NonxgZXIbATrppAqRUfSY+UQCsCAwEAAaN8
-MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJtc
-UbwiJzEiQJQJJf/Pg3mto4EZMA4GA1UdDwEB/wQEAwICBDAXBgNVHSAEEDAOMAwG
-CmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBs
-BZsxRaZk1qx3balE6qmVZd7jG6C9Gg/n+I5QfXR75ZIus+0Y6GAviBzywvJ8CDZ3
-kIOOrYolpnycedLS17Jnv4D/IDP6OwvmT6/0XvforKDQlmAk6ioJBRAwHRDYHBZg
-lj8FXyMNUS313Un0l2FXJBhfJNBqb1ZqYwWcmJ2t+w==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Separate Certificate and CRL Keys EE Certificate Test19
-issuer=/C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
------BEGIN CERTIFICATE-----
-MIICqzCCAhSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJVNlcGFyYXRlIENl
-cnRpZmljYXRlIGFuZCBDUkwgS2V5cyBDQTEwHhcNMDEwNDE5MTQ1NzIwWhcNMTEw
-NDE5MTQ1NzIwWjBxMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZp
-Y2F0ZXMxRjBEBgNVBAMTPVZhbGlkIFNlcGFyYXRlIENlcnRpZmljYXRlIGFuZCBD
-UkwgS2V5cyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTkwgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBAKj1Dg4L1T9e6MNcWCCvYvg+vk54WuF5s2Dxaa0lfcclqzahyLfN
-KqLCp0jCJyvA23IGF2C7I+P4dvjwW9kq0XD7H0Vt7LIjyQIpVyHObshN6gciyIXz
-iZjgaBqf8O+P6XhjAqsNyYSipygh3bX0Gqs/Kjb8qHbw8kdUG3Oq6xTFAgMBAAGj
-azBpMB8GA1UdIwQYMBaAFJtcUbwiJzEiQJQJJf/Pg3mto4EZMB0GA1UdDgQWBBSu
-h3HiE1+nBL/O/8Ce2FdoNLsWhzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAM
-BgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBAFL8c81C5Av+LkiNwZqrbjHV
-HFmRSvBpcRFa0WoFd8bNntXow2oh3ygbWRWt3FucJqTq6t4tys+3aNQClu/fcUSS
-IljPUyYAlgSxOTER4P9OYePEC/QtzjAGRH/5Kms56LVZa7lrOl2UpO8dkluoOADI
-hXabE5IQYEEjA26WpmmH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Separate Certificate and CRL Keys CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8A:FD:42:29:7B:59:78:52:4A:F7:48:1C:71:B7:C4:71:8A:A6:57:DB
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:7f:8e:79:fc:1e:57:0e:34:9e:bc:05:3c:28:df:90:bb:1f:
- c7:f4:6a:a1:95:51:f1:d2:b4:1f:3a:64:41:35:b6:42:62:b7:
- e7:14:1c:bf:0b:ed:6b:ca:f6:4c:c9:a7:48:ab:42:9e:04:9e:
- 0a:b5:f1:86:99:0f:b1:7e:6e:dd:d6:a6:b3:b1:3f:fc:79:6a:
- bf:f0:39:3f:03:ac:69:15:b5:2f:5a:17:12:64:8b:e9:46:9f:
- 82:09:f2:09:91:90:b4:fd:56:a1:ab:04:79:a0:17:33:26:c6:
- 49:6a:96:d9:42:8b:44:a5:ed:ad:69:82:63:78:8e:e7:96:1d:
- 17:2d
------BEGIN X509 CRL-----
-MIIBdjCB4AIBATANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxLjAsBgNVBAMTJVNlcGFyYXRlIENlcnRpZmlj
-YXRlIGFuZCBDUkwgS2V5cyBDQTEXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowIjAgAgECFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1Ud
-IwQYMBaAFIr9Qil7WXhSSvdIHHG3xHGKplfbMAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAAV/jnn8HlcONJ68BTwo35C7H8f0aqGVUfHStB86ZEE1tkJit+cU
-HL8L7WvK9kzJp0irQp4Engq18YaZD7F+bt3WprOxP/x5ar/wOT8DrGkVtS9aFxJk
-i+lGn4IJ8gmRkLT9VqGrBHmgFzMmxklqltlCi0Sl7a1pgmN4jueWHRct
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19EE.pem
new file mode 100644
index 0000000000..fa610b23e4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSeparateCertificateandCRLKeysTest19EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: DB CD 6B E8 FD 50 E3 22 68 C0 32 BE CA F5 E8 11 AF 45 79 10
+ friendlyName: Valid Separate Certificate and CRL Keys Test19 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Separate Certificate and CRL Keys EE Certificate Test19
+issuer=/C=US/O=Test Certificates 2011/CN=Separate Certificate and CRL Keys CA1
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlU2VwYXJh
+dGUgQ2VydGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMTAeFw0xMDAxMDEwODMwMDBa
+Fw0zMDEyMzEwODMwMDBaMHYxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENl
+cnRpZmljYXRlcyAyMDExMUYwRAYDVQQDEz1WYWxpZCBTZXBhcmF0ZSBDZXJ0aWZp
+Y2F0ZSBhbmQgQ1JMIEtleXMgRUUgQ2VydGlmaWNhdGUgVGVzdDE5MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6A/taBe34m/ksKOwmzFEXaF1fuBIoQM3
+AGF9NWtZ5qH16J4v/zCqL2LJz1lSeWeHcff8ScbPAgsqrdU9miaWhmdPBRATsnMc
+Y+rg45i4a4yt+phGqrG3DeGlbRW10evsqvYp+wnRKQQVh/qwa8LQqJ9ravqDdda4
+EQIuCN611MApwKbXQEPU50zGoqpTznRlmb18QV7amVwZnU3mJ0mZRjigZo9ptB4n
++msdHllGFVfaql8rqyoJ7cRONEwVdzysDWmn+Ql0dioZqMCBWK294jfeErYsU1qw
+QdXrnff0cek4mQlledqYACJtbzgapOmpy8LRlpMA4DpgcGhv2JtomQIDAQABo2sw
+aTAfBgNVHSMEGDAWgBTwZdo/Ghda3tW2SJk7FxQQ10wUpDAdBgNVHQ4EFgQU603H
+KTKwnexXe6+XcA3kjeBBjeMwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEACphhULftasvd9sThocYbTMs1
+BzSI0B1HQZLU0FGd2kYg7IEfrwYBc896RhLrSdbWl80bbeqomdED1KmG9eUl56ql
+6+qPKT4RB0eBEa06mBI8mYuLMGJ4N9mMV4w/P14cTnDVnXyIymUD1de+6kuQQ9n+
+KVtoMO8wyuu9OMETMd7QMH7KbOJZTBiBkhgJmZw8VaF5kYmVVmtryhTJnBszo1z5
+WcEbbSjX00Z4dQpzkIV5jlow5bmYuMrfb1NU8/uD8B27c3Ga/NGb4q2FrmFtsQiq
+Pb8XoXSJG2bL85SPhKP4j7GwPrTM4/xRmzbWOcookD+7SZzPmxzQBQ5wa+KQKg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DB CD 6B E8 FD 50 E3 22 68 C0 32 BE CA F5 E8 11 AF 45 79 10
+ friendlyName: Valid Separate Certificate and CRL Keys Test19 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3959557A2AA91B03
+
+yyDCYFHN71ZDE/VtMk1lScldcqAXuESWPTDIV9jVCdmcgoKjLXh9RNx17NoAih1x
+RskbCvbUbceXQhc15g5owlAPI+O8nCsBKLOSYMZNLgHM+5hzKJOCP/as4uizSBwm
+JDVjrqZeKwKa2yzCipq3VYK4CyedDjwXytaM8k9YjFUnsroKmOyPevFlDPynm4Su
++gpnn2kHN/mmCwOslptpcCbZZHutGtqfN4I/wlsjY7vfDazsZ3VwY+QDQDqNHMoC
+myrH8ntUg1HzTAK3A/3io/xNpNDoX5OPqLJ+rofBJUMUU2iRxp97aYiU/yDEx5re
+aj+bdmmteLfWePCY8dDafo45KPCNcseiO+joYFKaqhOQMql6k1RJlTCosvF3OdSI
+5h+1ysCwgPvQ2V5NSyZwaxMjq+b7mbgE9zNsJ79eTwcfMEQA2ZbtSIr0ZOFkHMIT
+mwsdN3tz1g2YR3Nnc0Dt5n/sy7IQAVzEMZgGeRfkbuP6K/dAWnTZh/DddPSk+OOE
+03Z+8v2VtSGgnD6oP6z4Ue2+ED81jTBzK82s2qkyQjvIW8q2mMohDK8o0+IR80Ac
+WRUUL6ua5Z5NEPiY2bNfua9r8siD/x4tGvpMMHcsmPKdPvfpmpzgBxlmp5Ie1PKD
+m3ntBAVuRIs5FtxyrK/qygM9LmCspnFpttPE3VebP6QGQZmB6qIw9FyZjGDPzz8M
+dhtphJwU0/sz1DQqiK74qw8Vyfp8obLfC0Dhax1Lj9SokQCZM32Ms4C78jLB8b3n
+uT3I/bZE5UOuEowggYTAUqcj3QaL0OsNauxxYJsj0vVDpgRD+GgGG54iQDMgdKKo
+6Clav4m31pKV1D1XEOYP7pZBsJkEQPfgV8Yfj+LTR7SxrdgHoJBlly75dT+eQqQ9
+PHut2xfCjyES1dtWDS8SejXlDphuueVoyJxGXGiMeqH0QlAnSQST8cTGeGV42W15
+imlgnN88x+teNooZ8jMPnk5jHr6UO2i17UbIaIY/rIeQExSJ2KZ7MNmU/bZkrMyf
+a+Lh1Sw5GXNyRLp41hgdzI38tFaaLnQ9HvHWpJzNIUG0xuz49nJcBGJIzNR80HRh
+lBOypWLsA09M1xCqzPLT7YLv7wUGuxMl4XwQkw+buzJIZWBQwYYjUgka7PdfNtfV
+STsBaS1zx0BU0KmjacVvWoOYIgzYJJQ+WTnDcXk/dJ9VCaApxdRJKlUqBKsI8jjg
+5VvCkp1kOwYkT1gfz8dl+LwuJZJDHPLdYFM75oevECkOMJmD2gcviEdt7jXykIF5
+BNE2ZxyBJRY/mgulAEFJ9r3C8D4UArni3RRyNOwXp84Qqi4vbxta3TMAAAzoewQy
+L6Pa3JtblN+vr9zUz4DIsr4B1WXU0t7q//Vmxgu5+5Cuy0jVc5wYDMswPAHZWvbt
+Ae6txUoySmdxFfhyzpB9tatlYL8g1mzo6k86GhA+yfOJI8csRimFplk9abBoyZb/
+kh302I/4+qmrDdYJhD0+4Xyhy9BbUZA168UeW03FCx+O5PiBz+Fk4gBSJyJvjCi7
+QlHNwblChH+2rYSZp6GAV6JNwx+3RuS9kKz3EWF6eaCORRmpRTOK2yS/oCHDJ1kv
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSignaturesTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSignaturesTest1.pem
deleted file mode 100644
index de409f5895..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidSignaturesTest1.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICajCCAdOgAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGlZhbGlkIEVFIENlcnRp
-ZmljYXRlIFRlc3QxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtpKu/a6Co
-7KcKOymboEA+MmgoryXHT1dxExmQ1lO7yah2L8j8RG6ox5Tr37TV8Y21ti3MopcF
-H+iXDSX31fixsYCZkcpjMI4kbjXmjGOeFKu1vnbBmcb5JBISiUeg22tIRFoJ4zTh
-i3GLVecGijyOVReA5LiPymEKG7fAB3241wIDAQABo2swaTAfBgNVHSMEGDAWgBS3
-LqaCy8LIvKh7J0TXNTPfmhWUxzAdBgNVHQ4EFgQUOsyUZQyFqTzB4K9RMyoUSI+e
-kVswDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
-hkiG9w0BAQUFAAOBgQCkaGfCqYi0681n9Dit36lg3U/9gTZoNqPMaAaLUQV3Crzx
-x2MGInhTyKchYydbV8HD89N2jzzYq7J2KM/ZEAfjskCdsj1SiMNkbYZe3rZZOldr
-PCGFgzUGTNakQxkpxU5j7plivQic/OZ7+mMTi0fnjGRi9M+aa744VmH6FgCt1w==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7.pem
deleted file mode 100644
index c2940bb425..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7.pem
+++ /dev/null
@@ -1,146 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Two CRLs CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcTCCAdqgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMD8xCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEUMBIGA1UEAxMLVHdvIENSTHMg
-Q0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANF1dMq4ulaNZm1L3KlBM9wi
-a4eu7sCry3O20zzWCttHHqG1W9UYLqqivx3HTyKvc/acTndqBtaz9HcdrETCRreu
-UjKFAa19JAnjF88BluoZ7A7TjdhsGfsa8gcLUZCN6ZkJJok2wENNh0xdsVhVlmnV
-p9rqIgYFPbZd0tvUp44xAgMBAAGjfDB6MB8GA1UdIwQYMBaAFPts1C2Bnsonep4N
-sDzqmryH/0nqMB0GA1UdDgQWBBQwyOlKAd5DJkEjjFNTjLNHFheOyjAOBgNVHQ8B
-Af8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMB
-Af8wDQYJKoZIhvcNAQEFBQADgYEAW8JONjczN4V2xpuIs064NZkR/ZEqwuPDedoS
-bQMZtQfK7+587JhXzGM3Hv2INUge/GRWUS6Y0Ra74Z4EU0UjKIM0PfCkokiU9cMg
-APFxIwTaaIfmrFY5FOAr0tvJXX1fwvLB2EEzFoD3m3FT5dKH3fV0l07W+rAzXGXd
-Mhqyx5o=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid Two CRLs EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=Two CRLs CA
------BEGIN CERTIFICATE-----
-MIICdzCCAeCgAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFDASBgNVBAMTC1R3byBDUkxzIENB
-MB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowVzELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSwwKgYDVQQDEyNWYWxpZCBUd28g
-Q1JMcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAiWTa6oG+nNhsn3jFI0IU5eab51kPtxwKr8QO22md2ezjZi0Si3bkH+nL
-d969Tfp3AtKQbsaNJVgYIP+GLylF1YmawBW39kLy8yuACUb9k0OlG02sW8u9SsTJ
-ifK2hvRv/2dGMe6eOR0Rpknk/8CHUgPJHyU3wSewsookv22AcdsCAwEAAaNrMGkw
-HwYDVR0jBBgwFoAUMMjpSgHeQyZBI4xTU4yzRxYXjsowHQYDVR0OBBYEFBVyE7Sc
-ZE9qRg0qsIBnbUWvDEhPMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAb3ltD/JZHS9eilXbrUwx4XAfOxMl
-l62TnSCbUwvD3VvSBp6CSL9/GAcOIQvGvsbyaFCCtCfPwSDw+Ub4vONlBK5+8uGE
-ceErncuILRQcNTwK8U3olehAt6Smh7aEcGBpdeMkSSZhoBSMe0GaIzCeDKELtG5d
-3yyDUN+RlEGX0tE=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Two CRLs CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:30:C8:E9:4A:01:DE:43:26:41:23:8C:53:53:8C:B3:47:16:17:8E:CA
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- af:97:f6:38:91:3b:72:79:fe:fe:8c:3e:65:dc:61:a8:72:ef:
- 9f:73:2e:dc:16:db:92:3e:2a:dc:ba:32:f9:97:0c:6b:52:32:
- 0c:7c:8b:89:a2:82:f2:81:6f:30:10:dd:5f:e9:ec:26:c6:35:
- c1:fa:94:79:ec:4c:9a:9a:82:ab:3f:be:9d:2a:3e:af:d8:e4:
- 8e:c3:c1:c5:08:81:25:c7:11:83:98:6e:42:89:5e:6f:d6:c7:
- f8:d2:39:63:34:22:95:56:7f:f2:24:a1:62:18:b6:9e:ff:d4:
- 0e:30:e1:b7:2c:03:90:70:81:51:bf:74:13:3c:dc:a9:28:55:
- 98:d5
------BEGIN X509 CRL-----
-MIIBODCBogIBATANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFDASBgNVBAMTC1R3byBDUkxzIENBFw0wMTA0
-MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAWgBQwyOlKAd5D
-JkEjjFNTjLNHFheOyjAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQCvl/Y4
-kTtyef7+jD5l3GGocu+fcy7cFtuSPircujL5lwxrUjIMfIuJooLygW8wEN1f6ewm
-xjXB+pR57EyamoKrP76dKj6v2OSOw8HFCIElxxGDmG5CiV5v1sf40jljNCKVVn/y
-JKFiGLae/9QOMOG3LAOQcIFRv3QTPNypKFWY1Q==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Bad CRL for Two CRLs CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:30:C8:E9:4A:01:DE:43:26:41:23:8C:53:53:8C:B3:47:16:17:8E:CA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 02:fb:a8:69:0a:aa:8c:4d:f2:07:f4:6a:6b:38:ae:da:15:1a:
- b8:c0:8b:d2:23:96:1d:3a:fd:d4:82:0f:c5:de:56:ba:c2:59:
- 8f:9e:97:67:06:1a:d1:4b:d6:24:40:98:4b:b1:c2:85:3c:be:
- e3:be:28:9a:3e:56:1f:98:4c:9d:68:36:a8:eb:e6:1c:d5:52:
- de:30:49:e0:76:0b:bf:be:3e:9a:b2:18:f8:de:51:f0:f4:da:
- 59:48:c5:00:9f:47:21:32:29:d9:f0:1b:75:18:a6:6f:d1:3c:
- 56:b1:5a:e8:6f:06:ce:ce:5a:4e:97:c2:91:cf:6d:40:63:8f:
- d5:71
------BEGIN X509 CRL-----
-MIIBaDCB0gIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF0JhZCBDUkwgZm9yIFR3byBD
-UkxzIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBARcNMDEw
-NDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAfBgNVHSMEGDAWgBQwyOlKAd5D
-JkEjjFNTjLNHFheOyjAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQAC+6hp
-CqqMTfIH9GprOK7aFRq4wIvSI5YdOv3Ugg/F3la6wlmPnpdnBhrRS9YkQJhLscKF
-PL7jviiaPlYfmEydaDao6+Yc1VLeMEngdgu/vj6ashj43lHw9NpZSMUAn0chMinZ
-8Bt1GKZv0TxWsVrobwbOzlpOl8KRz21AY4/VcQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7EE.pem
new file mode 100644
index 0000000000..78ea3689e4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidTwoCRLsTest7EE.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: EF A7 9B F6 FC B6 01 A8 09 0E E1 C9 45 3F B5 81 87 4D AD E2
+ friendlyName: Valid Two CRLs Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Two CRLs EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=Two CRLs CA
+-----BEGIN CERTIFICATE-----
+MIIDhjCCAm6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEUMBIGA1UEAxMLVHdvIENS
+THMgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBcMQswCQYDVQQG
+EwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEsMCoGA1UEAxMj
+VmFsaWQgVHdvIENSTHMgRUUgQ2VydGlmaWNhdGUgVGVzdDcwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC5JuoqCjmcfSVCDJ8pt6rU7wGuVd2jgjVKPpZR
+P7KiYOnVr1ZicDHgZKNP9eXgEG2Dlf0ajdV1AI+elrtWRMwMwVJ40UoWrgMSJUQ6
+15hdMLfJn/3Faxn8pRsxA2JaVL3l5HVJhhvIfS9sIDFKrGuVZdHkiAoCyVfyzpTz
+3k1YzPzCkhvObpROsrsiWvMiiUCPwgdO7KYNHooSJIPffcndBuJ9m6eAsO0WOHV8
+Sim9InCMhos0/P2hQODI93sMhQ0j1I9lpzyX0niZwLMITNHGpsyhpziXUw7Z9ivj
+tccFv2AdqdU9IP1u/VRenLXWcOYf2cF+ptqPPNZdbEp9AzwJAgMBAAGjazBpMB8G
+A1UdIwQYMBaAFBChAdaZnYDjbf3n7ndLX/FJ2TxTMB0GA1UdDgQWBBRNPB25WV8Y
+wN3ySuDwAKYpN5htvzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQCZZ/gPznl6z2bhDPfAXbW3c8gv0H/B
+xe1FmlkVfbdnBecT5Sapg1d+MBZG7vvChdROJPf/5wpLlBb4VWiTEFD88LGppkXM
++ba1w6oWyNdW3GjLAb1mso5JJi/rdSmJHXYOURmFACXhsMfp4HQo4xkorqetqV4E
+Ei4suAY62RiEjFRFPx85JmfGWRkN28hYcgY9BH8MNXkTolNDVhs3YWiD1L3WgNfx
+mQcIleaVRmBpxGcpNsggwO3igVmwLUMAFauMZZMrygJxixpvlRS04jJWCO++XQTN
+zy0jT7le65xMrIY4JXS+yV2wdoQlfFmrxTY1cvOaZp/C8owx1paNfpKa
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EF A7 9B F6 FC B6 01 A8 09 0E E1 C9 45 3F B5 81 87 4D AD E2
+ friendlyName: Valid Two CRLs Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,859B11CA69F6FEC0
+
+sQDMkeFGX2SxHHzSZ+Gztmmzn9hP+4zMq805hqIDnMtAiqU3r6ZBHZBH8wp8YXdc
+iIs9+Zdx06ympfTpoPfXHy6zsgizfKXMp/GBwYa7FC6xEBCy/Q89sfW7XDAdFcCJ
+WhhNP3DOdVbWZ2tN/9IfDD8Q1XRmO4l5j/ZflcoC5TY+dnnezYnQoVvahMBAUZre
+vUZ6afp/fOOAQhkhEFRZXrLMRv8Gjc/Vkh4eG7ecBHM1UKUrTXqxGewrXQ8qH3uX
+gs+LKU1Z4e0BfH58mHxBFF4JzPCFkj5ILV8iNMpFU/ukrt3+KuhgULPF1gxft27R
+oll5gQKf8AvTttwuPMqgByKZxDZCAWSb1xKo50XA1BH+ktauk2n8cUp7cKy1Cxt1
+oWqp0TCganu7238KWuo9YSm1Jc5CDbc0m0JTxGUI1GepHQzdQYjgEq/oSn86LgOE
+fg9hMTnFyT7fTk1SqtUvcRumjMxvZftrmp12tUET4wMMH1NT7hdpZlpWnEyScrsR
+LOfuN73X309TIk17gKkCPYg2yJoB5yfRAkYVftcKJEb2a8rzmLabldO82bHhMzUc
+HPriigU/IaBfwl0H+SxHkr0ynAjqsfH73A/W1573BVkTm3EEi6pkKiL58n9vr/GL
+Jx8RvFZdUGhKHGC70jgQ5xmL3R4VZgjgKC48eacdNdRLzuappJSphGhf5nDdgzOV
+v5hChh49uAGzn+9zJdF0EeA3gWXrhwTbW8q43YjQeKXvZWq4+F0swAcu3BQtEmtg
+CWsl03GTkEIMFOcby+V6oLETMhNZovQR8Ri79pZdDJb7isLiphBmnZyzdEMtTsP4
+upJnBBJ6BTkGrpmXjXkAc3W0LlAyOGs3AvZmKwLzRlJ3lh6nW27CsZj2Km8282bq
+xVZsVo93gCXsONQcFhEnkxPxH663tYoMg1w14ZAGGvU/WCdih+toCACKRw0IjBY2
+4heKVA7DXTFU1iB1Z+q6fBpnfcJ2BwNNky4GafAT1sEP6w8wBPdRpZlrLy33DpmU
+2t/PsHalLTCIFqAj7LOGmqWW9CIaCghLXhMaCAYAOfyU5b+xdlmZ2wmNFWQigzG0
+6GkBw7ZmxEQ0+B+8NP0ZcUVm6nx4+ZUA4BMMpmTrXThyxO8bOqa92FgjNpxvMq/x
++VdLt9tsMxoeiWHmSvyZycxsP4cwwuA5c/V6Jo1ASHYlq4jDs+SVgujLHNCxbsXc
+hmCb6Sh1vEoXXaqluBgBV4BQO7hF+pqXs2L2d6MXl4ZrJrbiLH3No2MniDwYtGJv
+GL4e7sLXkry5B536EU2zorNM7EzbRNWbGE23WbuKah7Z7yPYue2eERs/mtKJJumI
+Z0CwpkAPRUAIjkNgRuUqAJOCB2z5XWtGCwn1M0pq67As1iIySNZGr02ccmaRZJJN
+xMBWm0WWGV+HewjPOA/yAYrGQWbLj7rsjVk7zJgYnhlwwEZtLgO9TwkwOQIBM9eM
+lP+GMyaGIM3hh1jL2JFwG6NyFv0e2sLWnK/I006/vPMejk+C9XgL+8c5zicppUSC
+FqVHPGbdK/Uaoflih5bsDlpes5BXYilbniZmz8Hyk4F8/zrbW7cvtA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34.pem
deleted file mode 100644
index b7c8ae1749..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints URI1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqDCCAhGgAwIBAgIBSDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIFVSSTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKxL9gyE
-2WbKCoEEU+RviucDsSOeDHQfoVxci7AD0RhpGDZkMaDQhM+DUHywwIo9zUpLVeGi
-xQNu1+1bQ4SzVBT6k7vcf8ZxPOUI+8WQzMNO5H2/PGz3XGpfIw/RJrRH79ICwZlC
-6QzvSbLJhOtJTQS9kFTECA4AeBzHEN3f0igTAgMBAAGjgaYwgaMwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFKwdFrpLHgtf4rxhruHZ
-ZFp5vkXWMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zAnBgNVHR4BAf8EHTAboBkwF4YVLnRlc3RjZXJ0aWZp
-Y2F0ZXMuZ292MA0GCSqGSIb3DQEBBQUAA4GBAHbVqbpvjgN0GV8abRGms01xVNHT
-PtqMarG3/zQImm9xDzqUqv81kX/8DOy9I/lo3Mvp83M9B74mEEiTTnxkYEpaSouE
-fE3/VAW8dTJb35NeZcOCNWDQv3eA7bufOVO+4KjEHERlxBfEYlPEkJGSLD98SF62
-OYmmR3Cda8cKBk6p
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid URI nameConstraints EE Certificate Test34
-issuer=/C=US/O=Test Certificates/CN=nameConstraints URI1 CA
------BEGIN CERTIFICATE-----
-MIICzzCCAjigAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBVUkkxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTgwNgYDVQQD
-Ey9WYWxpZCBVUkkgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Qz
-NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6FGlp6Xjgc5M7qIkjpaJW/ie
-OIVcl5Qn+CIdaNq7obRCyoLrqT/lyrQKTifbp29aWeS20Q9OnvNHYe0AoQulxnhx
-tId1+3BJ657gMf8FIwZ6y7C1vKus4TE6lYhBXJZtTF5lE1znoTDmaO9u+Ix2/RY4
-lH5oTdCUCHiEdcoOBvsCAwEAAaOBqjCBpzAfBgNVHSMEGDAWgBSsHRa6Sx4LX+K8
-Ya7h2WRaeb5F1jAdBgNVHQ4EFgQUnBltKBL7MT2/JrE+lLcnIG0SKgEwDgYDVR0P
-AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATA8BgNVHREENTAzhjFo
-dHRwOi8vdGVzdHNlcnZlci50ZXN0Y2VydGlmaWNhdGVzLmdvdi9pbmRleC5odG1s
-MA0GCSqGSIb3DQEBBQUAA4GBABEni3LRvD7bB0FXjsIor6I+OaDVBV6uWcVuwtmS
-gtVMwBhrnKGi/nw+7E+wJs0Sa7INnkylGFlUzOLEFV1Sa6RYjmo61i4AE32uqzlc
-lNvE/bXQh6ah0Hj/sw2u9bXRn6zgPcf+9yQRsJ+wNYuB3rP2dsxckGRMylL5bDZq
-CfQz
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints URI1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:AC:1D:16:BA:4B:1E:0B:5F:E2:BC:61:AE:E1:D9:64:5A:79:BE:45:D6
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 48:8d:62:fe:d7:4c:f3:06:9a:78:4d:e0:96:d6:4b:12:b3:93:
- 23:96:6d:00:b6:6b:7f:35:25:e3:94:20:1b:fe:c8:cb:3d:5c:
- 7b:e8:f3:cf:c3:db:96:d3:62:4e:b7:5b:93:05:11:c3:7f:41:
- 94:e8:75:d2:8a:67:bf:f3:b0:81:25:22:99:a3:4c:02:9f:1c:
- 87:1d:b1:20:a6:0f:b7:c8:f2:2b:e5:b2:4d:b4:e1:bc:c3:85:
- b7:54:29:13:e8:7e:53:ed:d2:cc:a7:95:3f:71:32:5d:3a:09:
- a1:fe:af:ba:45:14:41:1a:67:fb:8f:46:03:6a:fb:78:26:71:
- 02:1b
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBV
-UkkxIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBSsHRa6Sx4LX+K8Ya7h2WRaeb5F1jAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBIjWL+10zzBpp4TeCW1ksSs5Mjlm0Atmt/NSXjlCAb/sjLPVx76PPP
-w9uW02JOt1uTBRHDf0GU6HXSime/87CBJSKZo0wCnxyHHbEgpg+3yPIr5bJNtOG8
-w4W3VCkT6H5T7dLMp5U/cTJdOgmh/q+6RRRBGmf7j0YDavt4JnECGw==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34EE.pem
new file mode 100644
index 0000000000..83475b7d41
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest34EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 64 28 A1 C6 BB 67 6E 3E AE 4E 08 E2 AA 3E 62 53 85 52 03 F7
+ friendlyName: Valid URI nameConstraints Test34 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid URI nameConstraints EE Certificate Test34
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints URI1 CA
+-----BEGIN CERTIFICATE-----
+MIID3jCCAsagAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIFVSSTEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBoMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE4MDYGA1UEAxMvVmFsaWQgVVJJIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZp
+Y2F0ZSBUZXN0MzQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO5F/3
+wWBzxesA5Y/T/BL4plearIiSXCj2/J6WAYteqn0mrUwJ1r2apfS0ZjNREqqiKj1c
+nPIi2mIfqanPTTIYJTfvnR4fAYYpgU+b8jGCmF1qU/G7gRuvhfAV67/NqzkvmiRl
+Nq2qWN0xS+r24fotIAtBhh/kkzmRlgK9rJceRDX0gatRtUkZwNCDA8f132Ghsznb
+REzEzxlWWp1sTi6g9PgL/rvGH2h1RrhUby291O0fUQ0uplSXPgodYZxkS52o66pZ
+3pBTdqvCc7evLZfRaxz1uuFl2IYrYXUos0iOMoTqPzo5jX29Z6A4N78G6tB0Uksq
+nzGTPg6iPwrHxVNvAgMBAAGjgaowgacwHwYDVR0jBBgwFoAU+iitQRbeKmgXyA8c
+Iz8mA94CFAIwHQYDVR0OBBYEFNZ67DHSA5qsuP96390yL1+UdqlGMA4GA1UdDwEB
+/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwPAYDVR0RBDUwM4YxaHR0
+cDovL3Rlc3RzZXJ2ZXIudGVzdGNlcnRpZmljYXRlcy5nb3YvaW5kZXguaHRtbDAN
+BgkqhkiG9w0BAQsFAAOCAQEAUAfALBN64JUbbsGzkZBy5SAIDD8HJCpcxlMgJ6UU
+4RkR59QygGzwquDniZQvhDJ+ZqzgkBFY/k/UFXdpPJD6baREO1H+wTz/TPhtxMv0
+5n5Ycbno9qhlIr4JFj5gTU0DcDcYke7AztSOxyT3D7/Y0cpUOipTay0BmZA9ndB9
+yGnIIALUzQ5pDttKZso5TX4Tf8c3Y8V5VqhiN/dOQnXnsanyBSsRhn6jaPTowi9s
+SjNXIw3GgiWod26Ld9eRLMljkNgA1h2nIwkqIfStvJMzWVEd/tPUj5+lF3L2EqL8
+8E9ziMi7XGb1hpCr9oBN+9TaDQF58lRFiwZO4c92bCqmJg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 64 28 A1 C6 BB 67 6E 3E AE 4E 08 E2 AA 3E 62 53 85 52 03 F7
+ friendlyName: Valid URI nameConstraints Test34 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,50160F6A2AB4C12B
+
+kohSQm0k1WKhPHAE0UjYK6HN/4aIK2XHNrgcB/0imbi2nIsENeR2BAu3c3VTXTm8
+rNPxawXFu6SrqM4Q0QUvY5Iwntas8y8jPvXibLKWIR8PdtQBn0LV/xUTG3DWOUW/
+YoTHB8TrDYYLqNmIlzazOjlCU3GGanFuywep0UDSRSqPja7mFrLxmQfNySan1ucl
+5oKHvZISFQoiq35ujPdtSR9oXAkrApsI3g3EzLCXhf1o3OEToUleXdLsnIP3oO+j
+Sa2VrkhWhTrrJaud5RJYIBfrtZURg26OQhJuTjOI3FfThliHkfBqx8zP4PlDDmyK
+S+hE7IqDD2ANWqazKaAReG910vX2FdlFo82YsFF8ultSbt+WNwZHY1/76YNCSL/5
+OwVbbOdG+iaD+k9uWbln4HalwB3eS9HlSVgUQLieXluVbRUtsjevJQSWT4mvYI2z
+ut4SLttuxPL0+QvKoSfZ1I7cfCQgLo1Wxw3gHu7hhyIdSqey4HPr6YYTyvjngLmp
+j2AxQLCyfMRJFod7louYs20qnvOAxL+0UAgRSMtkRSj9s/sXw+At5Dy3W0LDjx/P
+qq08eXYImXTbG7D1SvWln0xwJlM7bItEIgdRbnXmnAThxLshAi9bKVC2OTLRj7HM
+b4rx8EvgQViQ6HQEZQAPLKHDEfLUhgk0US7Tg78AfPuY/IMY9MquXmvBMi3+ngkR
+RUeuUes0puPy4q3xSrc/Uf6nLpPYdfqN7hFOXWH8yfVs2vsM0/iVHqCM/XWm0zMc
+4Vf5qhZFaoR1XLSH5/D1jr4lDhB4r1Mh2N0y5Sps8SbH2hiSAKPrI9jTlrmH2nUt
+zlzu9kUp5KORPjV5/cf59rU4KeJb1S6deG1uBAB7vwtJhQdzr1HNURM2L66XybAZ
++orb4HCPxKPsHCUFMbOWPyhc/mOSHJAcjylAFosu/C0xqNl/gmoKzbbp7VxV9hZf
+SIJUgNu6NZLhrjFBcekEfiZDIyDLFYpJ1vTcAebJn5b+/9n9xkRjF0IbPfbDUX3t
+gvcrKcr2puANr8ZrgqjFGJJ0B7AEMZa1x3NCiMXioQXMVupvTtL4b8zmsWqD3ZYZ
+yeFYnRHlXC2M9cZNm9yTqIDtEOc6zB+dqYK0VThKP7YfDoACuFsei6EBGsY3A3n3
+V0csq9RMm8Svo3qrhR3ygDiWWyxWIwxrmoRIZgv/bUhScwfsccf1oahlvueRxfDA
+8ytIQw3SwXhLflmmqdd3AA1Ks0QZAU32JiUhKfpzzHxjad+xVLElrBMjWMoUvy/U
+rEjvQCasrTCOvf9cxt1pla1X23USVcr4q4mq+amFYXdpn67mDemqeI4bnJmOcSC9
+yic2OuWgBhU0zRytkn2oBAyg0r4RTx2Pr64BjPuuHCQ500EMFOiuTfJJiPvgb0F3
+IgLmJoHr3lwD4/bF1UPLldHkmLdVPYBgYU+Fc721zIUJJQvEi4AedOPcRzyJ+tlD
+v7FhWudV+Lt+sQl5kZ6oz7u8BzOVfcTApJUu+7dSfiTujbSnmip3gB07mvUE6kQa
+sntlWQbLfnOM+uxH+cpT7f1vmpXkv/CcJCIfd+fX+yoYk5B/0q8KKA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36.pem
deleted file mode 100644
index c13af8a307..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36.pem
+++ /dev/null
@@ -1,111 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=nameConstraints URI2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICqjCCAhOgAwIBAgIBSTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEgMB4GA1UEAxMXbmFtZUNvbnN0
-cmFpbnRzIFVSSTIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANCu/tVS
-XB6TUXM4bU2lQ7EKvQrGMy49TSnHlIwEVZ9UNvbSA/ChnCxPIKWiVWlqdqr0evlL
-xdLPxQe6xHuVjkvgFleY6RjA9LqD7YFFvf8AnDD6BV0kIr3itChNI2abON8Dh6IG
-+o48bCPAt9bqxCepQbrSn4mYSlcKjyn66Ev7AgMBAAGjgagwgaUwHwYDVR0jBBgw
-FoAU+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFIakVWPxjKAjp6e8y2yq
-bdBaxg9aMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
-DwYDVR0TAQH/BAUwAwEB/zApBgNVHR4BAf8EHzAdoRswGYYXaW52YWxpZGNlcnRp
-ZmljYXRlcy5nb3YwDQYJKoZIhvcNAQEFBQADgYEAXeaQUlCHmmhg1rKHYxVfKaCq
-S574GPbDh1QtQoNmVqFF+yGHse9s4hcYcv7VZB74kYKCFUShbBWl1VcmgPbJLDnc
-MDjP1B35WdH4IGAxCBLHOiuv/1AWL9EfHUdhX2ZoFpJqNty9lFkahCZ6MARJwtS2
-fBh60OItInetzMDECnE=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid URI nameConstraints EE Certificate Test36
-issuer=/C=US/O=Test Certificates/CN=nameConstraints URI2 CA
------BEGIN CERTIFICATE-----
-MIIC0jCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJh
-aW50cyBVUkkyIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowYzEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTgwNgYDVQQD
-Ey9WYWxpZCBVUkkgbmFtZUNvbnN0cmFpbnRzIEVFIENlcnRpZmljYXRlIFRlc3Qz
-NjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvE7GKi9cq2LoR4nDK2rqmEIH
-MsJ3m6EeWMUWwoRidb2gH7E45Oumq5skRGihWVu15Lokjua+3arteyn8MbuDj+lF
-KcEEP4VLE84+SFaA5KNgDJspoT7+UiBZRELwTxiTK9vPR5VQyTQnc/M9PkfC5rvV
-WbctYK/HJ/r68nmGAQ8CAwEAAaOBrTCBqjAfBgNVHSMEGDAWgBSGpFVj8YygI6en
-vMtsqm3QWsYPWjAdBgNVHQ4EFgQU2X6Y6CoZbpdRkA80xPGNWG1aeZ0wDgYDVR0P
-AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATA/BgNVHREEODA2hjRo
-dHRwOi8vdGVzdHNlcnZlci5pbnZhbGlkY2VydGlmaWNhdGVzLmdvdi9pbmRleC5o
-dG1sMA0GCSqGSIb3DQEBBQUAA4GBAG2N3tYbTsRh2FgGR/eAxNmVerY5ooWKrZE/
-MkikG9U+XWgHChNL4eR92wDJVi1h5uVvSyUIF1vEFXVfVxyqG1kz1dqWcFrZHp1I
-w3WD/3qKE0ilWL+AnW7LOOTbTUDevmIwcUAvl9/QiYpexJyeQhzWJ13gh5vwkfiG
-coWXP3GU
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=nameConstraints URI2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:86:A4:55:63:F1:8C:A0:23:A7:A7:BC:CB:6C:AA:6D:D0:5A:C6:0F:5A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 73:1d:ee:ad:1d:21:24:88:c7:70:27:82:cf:68:1d:fa:61:18:
- da:2c:a9:9e:05:0d:b4:7e:e3:ac:49:fc:82:76:d0:6c:80:1c:
- b3:b0:36:4c:44:da:e9:0e:aa:9a:df:66:1e:0a:80:f4:f0:0c:
- 84:02:2f:57:47:96:e1:f7:ae:e6:be:85:9e:53:e0:97:1e:9a:
- 68:7e:f2:32:8c:d7:89:1e:63:dd:3f:47:06:30:44:e3:42:ee:
- 30:c2:d6:ce:3a:46:4f:6c:8c:e2:43:c3:7e:5a:51:ce:5e:73:
- 7a:ed:f7:5a:04:a8:0d:f2:f0:67:af:e1:0e:b8:eb:9f:cd:2b:
- 24:62
------BEGIN X509 CRL-----
-MIIBRDCBrgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBV
-UkkyIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSME
-GDAWgBSGpFVj8YygI6envMtsqm3QWsYPWjAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBzHe6tHSEkiMdwJ4LPaB36YRjaLKmeBQ20fuOsSfyCdtBsgByzsDZM
-RNrpDqqa32YeCoD08AyEAi9XR5bh967mvoWeU+CXHppofvIyjNeJHmPdP0cGMETj
-Qu4wwtbOOkZPbIziQ8N+WlHOXnN67fdaBKgN8vBnr+EOuOufzSskYg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36EE.pem
new file mode 100644
index 0000000000..c54a940b53
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidURInameConstraintsTest36EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 90 C8 1E B2 98 13 4E 66 81 CC A0 66 8C DC 14 EA 92 3A 08 CB
+ friendlyName: Valid URI nameConstraints Test36 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid URI nameConstraints EE Certificate Test36
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints URI2 CA
+-----BEGIN CERTIFICATE-----
+MIID4TCCAsmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNv
+bnN0cmFpbnRzIFVSSTIgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBoMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTE4MDYGA1UEAxMvVmFsaWQgVVJJIG5hbWVDb25zdHJhaW50cyBFRSBDZXJ0aWZp
+Y2F0ZSBUZXN0MzYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMbB0+
+65ySk6fi6dtExfV1zX4fF6wQUg0um9bpkU7sssBLoEI3fNMzQTM1iwjpbQqILiRP
+0zqi/pEy8LTZZN0H3/Bvign4sGWhf45iMB5gIVR788WqOKz+vnTHjzjve8a3y2BG
+0obtbCGD03k3a1zu3EH6X6ZXQHN5AXFgwQgOkwWf0azdHUb7JO4fSFMH2hNEgOJx
+2ip+HuWZfzUzIa+as9ysh7OCjJYySAp6jxzvrQAsRcUQPd0XLuJKUM/tWXAzfqgy
+Rk5RsfcnLiBw/Z4fB1UzhN5RSGyBxqwiibLl5zeEQxDETmW7kVDN0V0khIpX7mD3
+frmvHfx1nzaSU4IdAgMBAAGjga0wgaowHwYDVR0jBBgwFoAUTeuJcd/wBAGy+nY6
+WLG6YN2M08MwHQYDVR0OBBYEFF3cy5MzmrQiP79DwPPCIj7VxjfFMA4GA1UdDwEB
+/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwPwYDVR0RBDgwNoY0aHR0
+cDovL3Rlc3RzZXJ2ZXIuaW52YWxpZGNlcnRpZmljYXRlcy5nb3YvaW5kZXguaHRt
+bDANBgkqhkiG9w0BAQsFAAOCAQEAXHV9C9XnmJqFiGQvsQv+Mtb3wU/lbRlv7P4+
+dVItASgqIPJwjrGAEkFjykCDUd/ozD4lIo+UxKwXAEmH53wyXLnnupluCnPYarTM
+KgWfQlBj/eO6GNEQLujg05EK7VxfFnr1jPXEaVBIacwwXNlEGVFK/j5GaOKh9kbT
+SwdMgzGI8R+k8mYoLbVcE3Q3v3zsZPjsME8OBW3d+AytEb2gWScJv/iDfCSgk3rQ
+F7NENzPMDreitDNAhxvmQL0/KGewkCStOjFHaBLQKR+ELq8TruIEuypNl8BNFQf/
+HSf5MCFAlkXUNaff+m/vEvm6j6l4WlcuY3cYA0BLG+OTnSnTCA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 90 C8 1E B2 98 13 4E 66 81 CC A0 66 8C DC 14 EA 92 3A 08 CB
+ friendlyName: Valid URI nameConstraints Test36 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,099C68B6A471A08E
+
+nyQYist/gy/S0F8Dbw3KXCcHMxzhAM2TlY8lecSS2d+Q3hrFWrqQ7tIrwZYGzznv
+ypq6Wp8Jxkq357ceY7F9yz8UA/TDK4xQdFITeM4toUknwscbkSNHgYbMAFwpaSAC
+1dd/VyVIEUC6q7gbBYoUxCXS3tEcoIzmwSO1unB/c75ks78uY1ygyrjPu6VrnOMz
+wQDrOAdRJQhwAvw8DBqHUejxThr60UMi7OMbNlzlzud9crBdlUzAluxkgTagpihe
+9KBvPUGMAtnGmchmCQEZcNoQ4mqCLAQqcylaQl9h9bUnMrAllVteiBpePHCBTO5e
+EmfSa82yQJI32NyJMI1a3soP7fZMQzitHgGKo9Kcw2g0qAMjtV4vgB+PeavW5zpV
+uNCQ/cYbkie9NbccrkHR/iiLtOggws/Sm8ZQv3WaAtamDM0TK5uLilWWthvcD/3X
+h0RPOaBkzH+APUbTk2b4sLFqMJDmKEO0C1o0yGDsvo/0AarZCUXaw7LE0VmAV4aw
+ux68ttmqIshamV7rj4UZ/V94M1KLnxRcvGui4XdNx0sKA+so01+4XgIZEXWRR0mM
+RKGwO+zlTuSRtCgo5rDwx6rATxjq65PawAMZ48QGKXZWhfvEtGwsmCweQvH/G241
+LZKBXrl0wO5jEeGHvd5LGRjZQqP5AEnlUV7fKWb19j4HidOtDixZyhWxXDt6x5k9
+BEEKrDp3K8Uhu/+cYLtziCa/ItzGMPiBUd/m5C1zYcUqrh1eMaPh9YBbRdXR/GYh
+1g6dEXcCwjyLrYsaAjIydKwES0Q8lnbwVtC9VyQwVId/X+dp9ayU+IWPBweOFZ+Z
+bHp0oAbn5fPRzx/BwjhpHUYbmqgs3knenQDYofRiPCaV9oTvEt33iU6tm+tsOOt1
+d4Jqa8kgbX05+jxDIjwjY/v2pVqaKllJzpKWFPGlXXj74aKRrVr0kEXb2pklYp/G
+3HzPbEG0OegIFAj3qBYZujbJ9P0Fys6/Qz7p0gELWRRvAsXsKntRDBE9n2QrzGzI
+iT/r9u23pjmNv1mIT8bIArzTmlckJO7QeF776Ti27hQeZcYa4wS9m8vqAljI0LWX
+g4HvChsaS1Q4SBS1Fi1WaREDOfeuJyDBaLqa+Xc+n9StuN3bJlsx7PX5Y3fIQBD+
+ixmyMZQHaopuue/LH9BICaDHvU9h0qD1jTAs4oDr7OLzaH7bILDPsooVKMmb+EOT
+NIT85QC4sbrpVTK1UR0Mnw1D5QOCRyuQyetdG6T/bpKb2V4AjWFX5BSexhp5YAdx
+qfRkib3DKF0s//evkn92phwVoZP4lTv+phVRIU4DSSxxZST7XNsr0QzlE2lUkYTT
+AOCOeB519BHdugmAT3WwCqbOEcmnqef+WHnWWH8IplTU355MWN6odfsFDhCr/Sf/
+/7XajGPw0dq7w1M7gUpEJcQC2r29s814L3UGstU55+rfnf3tevs9ar6HcuTM2Nhm
+IjP0hHeFYaD9AN9AvyPyhYwn1sEibpz9y4UUOyK2yCe9BGVzFXl0MJn5VSX+qWSX
+7cS2hhm+v0zRqGA7u+fMaqWMnMWMl3+3Pxh/8CIhC6J/ioGHtOjz/AkWR1e0Qaii
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11.pem
deleted file mode 100644
index f91b6dfd97..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=UTF8String Case Insensitive Match CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBZDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKDBFUZXN0IENlcnRpZmljYXRlczEtMCsGA1UEAwwkVVRGOFN0cmlu
-ZyBDYXNlIEluc2Vuc2l0aXZlIE1hdGNoIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCaogvEpeDhTyOkM06wjnLD1JeNedm9VZ+FpIvkkhrhGKskIHcfsNfJ
-EsrLnoSQIj5ocFyxY/76uaSgJcEhTpIj695mSBtyZThgQr07wSGTByiAmO3fR3if
-tMzWdzP9j19QXSUZjQCBNySjtuabFoqgR9OHEmVjly+67Al3yaZDEwIDAQABo3ww
-ejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUNmIV
-KXylwtCEEMdeoxYn36lEE2IwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
-YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAKnn
-dr5r22s30krLGaZ6Ava5zeA3jRRsq/ewoyaGn39VO/MYpqRxPdqlVqLO41PCjwTY
-VjndPhVSfFsQHxANRG4TUD7MBKeNsr3eclIvzCtIb8U9dwHngXeYNlih1ufYUDZ5
-z5oTq4R9mHUGu1Jz/uW9sisBRMbS+2wj+E/3yezC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid UTF8String Case Insensitive Match EE Certificate Test11
-issuer=/C=US/O= test certificates /CN=utf8string case insensitive match CA
------BEGIN CERTIFICATE-----
-MIICrzCCAhigAwIBAgIBATANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJVUzEe
-MBwGA1UECgwVICB0ZXN0IGNlcnRpZmljYXRlcyAgMS4wLAYDVQQDDCV1dGY4c3Ry
-aW5nIGNhc2UgIGluc2Vuc2l0aXZlIG1hdGNoIENBMB4XDTAxMDQxOTE0NTcyMFoX
-DTExMDQxOTE0NTcyMFowcTELMAkGA1UEBhMCVVMxGjAYBgNVBAoMEVRlc3QgQ2Vy
-dGlmaWNhdGVzMUYwRAYDVQQDDD1WYWxpZCBVVEY4U3RyaW5nIENhc2UgSW5zZW5z
-aXRpdmUgTWF0Y2ggRUUgQ2VydGlmaWNhdGUgVGVzdDExMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDsol6bNoNnlNAy2lkPsdVM02fDVB5vmtUbTN2DiXfYxICd
-NtMW9orODpZLBLuhHD9L/N+amY5njVAJUpvbdU2cjFMwgn/YfQ/eDXrCDPG2FLaJ
-WA0nRqHFrhBVz6MgJFtpJUz3e1Owsy3U03aq9SthFb/BBFFOtAH6mXnuBjYVTQID
-AQABo2swaTAfBgNVHSMEGDAWgBQ2YhUpfKXC0IQQx16jFiffqUQTYjAdBgNVHQ4E
-FgQUxMF/9KLvn9+5ABPGIN0ZEfq0S6cwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQCLnWS00RFXZcbBCM15
-7+vQE5xrZp4AH8MhcC5CCS7C5F6JkHPcXT5OnCCN+d0cmCCTgolBi+AndeXwen9O
-y/2uq63SVqP/H67rcyoxaGeqSxxZqbowZqboUMBLinSyMq/coqnGbiNjK+K7xXqR
-borsQCmKGqvst1rn2LPNKfKRCA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=UTF8String Case Insensitive Match CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:36:62:15:29:7C:A5:C2:D0:84:10:C7:5E:A3:16:27:DF:A9:44:13:62
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 32:f5:46:0f:c0:5a:10:87:86:95:df:18:69:d7:c8:99:4c:84:
- 5f:f7:1a:e8:c7:66:27:41:73:a4:72:f6:09:66:a9:f7:cd:62:
- 22:87:dd:24:94:77:c1:38:e3:9c:cc:70:64:29:b7:d9:76:94:
- 59:d7:26:43:86:35:63:6b:0b:81:a4:1d:d4:4f:7d:87:6a:b6:
- bc:68:34:9b:ad:d0:1c:34:3b:72:7c:7f:25:b2:19:03:a1:24:
- ee:ef:d3:3c:a6:21:cd:79:11:70:d4:6d:5d:c6:67:14:39:17:
- e2:23:30:76:5b:f7:b5:4e:ce:ed:3e:57:2e:58:1d:cc:ec:ed:
- b5:52
------BEGIN X509 CRL-----
-MIIBUTCBuwIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJVUzEaMBgGA1UE
-CgwRVGVzdCBDZXJ0aWZpY2F0ZXMxLTArBgNVBAMMJFVURjhTdHJpbmcgQ2FzZSBJ
-bnNlbnNpdGl2ZSBNYXRjaCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WqAvMC0wHwYDVR0jBBgwFoAUNmIVKXylwtCEEMdeoxYn36lEE2IwCgYDVR0UBAMC
-AQEwDQYJKoZIhvcNAQEFBQADgYEAMvVGD8BaEIeGld8YadfImUyEX/ca6MdmJ0Fz
-pHL2CWap981iIofdJJR3wTjjnMxwZCm32XaUWdcmQ4Y1Y2sLgaQd1E99h2q2vGg0
-m63QHDQ7cnx/JbIZA6Ek7u/TPKYhzXkRcNRtXcZnFDkX4iMwdlv3tU7O7T5XLlgd
-zOzttVI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11EE.pem
new file mode 100644
index 0000000000..55689d442b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringCaseInsensitiveMatchTest11EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: D7 D0 63 11 F3 B5 B2 43 11 C6 86 8F D5 31 5F 7E 92 4D 7B 10
+ friendlyName: Valid UTF8String Case Insensitive Match Test11 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid UTF8String Case Insensitive Match EE Certificate Test11
+issuer=/C=US/O= test certificates 2011 /CN=utf8string case insensitive match CA
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIBATANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEj
+MCEGA1UECgwaICB0ZXN0IGNlcnRpZmljYXRlcyAyMDExICAxLjAsBgNVBAMMJXV0
+ZjhzdHJpbmcgY2FzZSAgaW5zZW5zaXRpdmUgbWF0Y2ggQ0EwHhcNMTAwMTAxMDgz
+MDAwWhcNMzAxMjMxMDgzMDAwWjB2MQswCQYDVQQGEwJVUzEfMB0GA1UECgwWVGVz
+dCBDZXJ0aWZpY2F0ZXMgMjAxMTFGMEQGA1UEAww9VmFsaWQgVVRGOFN0cmluZyBD
+YXNlIEluc2Vuc2l0aXZlIE1hdGNoIEVFIENlcnRpZmljYXRlIFRlc3QxMTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN29zJK6hFJG5nAuyoIXSLM7XSRW
+O5FCiwm1id6V5ELZnaiQN5PtY7ZzOdQ5Rymo60UCnsnp2Ylg1OYh82GfvKG7gZS0
+xRwA/3Z5veLZsYhuqm/yixO3lfbmQRb1axDgfudVwUnwdQlvXjXPf4EsIB5WIAIv
+JYryutqJNIn3VX5BeI8luQX2ynlkc1StTCeUMnXYT26X2GW71m0hn5RsSlwHayo2
+HXVULIt5ojyGoatCESTbN0kmPXKJQTwV/KmER9Ual9Zb4BKvdy0Kbs/SImNzmA3a
+VITJ/YMs6BA0OshD39ZkqvDF86aCConG69VXWF9ASOmClC/asa9AyHvDAKUCAwEA
+AaNrMGkwHwYDVR0jBBgwFoAUYN8Y0cqpUJIRFyFE0nf1aq2mvngwHQYDVR0OBBYE
+FKzudXSiTCM93NKYuEBr9McOizZqMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBAEv6NJ3Kqb+fORfTmqBp
+z/UIu+rdVqUmqVOc6VEG8hrOWOUjNHxb+DQHwWSM52s4ednWj4iOrERBtqI6I9+L
+Ja1yCa1i84KLowhew/iH8fgFqLnuoqiQ6SXvY/z6hBIHgOSZ5LI0yF7Zsw7R7JKc
+S4rpOI9lrXRPHPFv51Up7Z9BUNv1QOU7dlLAIwXXKvEETuYD4rM25w2Jz6ogfdXD
+Rs/B2OAm5lKTf/ZNeLtF30oyNPHPol0DvAQO25oRtrguOShdluY++kWqDXlVMetI
+y5xJ4/n3p2W3V+S56jwwok+627UoDYUqS4ulQtix30lcWi2O+UqYgFnNWJxwa+Gj
+zp0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D7 D0 63 11 F3 B5 B2 43 11 C6 86 8F D5 31 5F 7E 92 4D 7B 10
+ friendlyName: Valid UTF8String Case Insensitive Match Test11 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,58848D19CF96577A
+
+mvFg38AyE/2G/aVUlNhvdTka5AvgOAknAWqk4lP9m4oGx4V/QH39TjFGG9HHF25k
+UXLMXj/e4qbN7uwU5T+z+A/FiPBBuhjCjcK2Bm0zH9O88yh/Qklop2XQQEM9oIXI
+AJrYXoKfin8Q+AgSvZ92CfAYqIm7j5jEdQaf3o9yih2aRQTcYiM429fGM5gSY+mv
+vS/4MNJFWyME0D5aRJrwBK2lMmiQI/zSQfmZRiNOYE7z2htmkEECeGarO074gO2z
+He5RKtGc15x09AP7GzzDZOYMX7tC9PyxE0dQ0sif28Dw7bp/mZeG31geznW7kpQt
+p3scKoZ8TKOVmxnxbrHUMhXQ1nd0hVRTAr1VGtp994Na85sYe1SKpcF3WMxCJ7pq
+ttZ0g50S0zLlgjJjOPcnybDRMoNwnzZsEW6RiQdlNZY3TRoeLkNfJgtTV93jxJ+c
+8l6TO8Us5E7GjChUnN8/Oo9U89XXVKJW7MOnbxCkqlAyHxl1prOvpBecHhuuN6or
+0e/RwMxrkObCN4MPpa4+axzhTBPLDnqGJSCkF78VoQEF55QF3ZFDWztwhusM+bWL
+U7wfFjLbIZZw3vlJOu9/7Owva9Od0es1+X8+V/RVjbMFS0VxnOTjjeLEG2q3Cqll
+byesMZ2csF2BAHoCtP9mlQ2NXalDi4hSwf1RpT47KqAnaX4y1lI0lHB8Bv12UHDy
+foKLxTrZcDpHKvpxgkQRBClR2ZIUQzwpNiOtIo5c8BCyNn6FLCmXnasdZSG2ow6M
+gXlzpLoDL8g+aTI6U3Ruo0NiRmWFTljRcJOKoCf/H24F1eOCRLQOTwJs97YUD3/h
+dK2XGkGKgS9dEOon6CnCGVti8NNKBMDpiOt/PwtLB/IZf6PCUunVKlzqnyaT4twL
+dUImUev+ybVpBGQADYxQ0qWjtpGee1kUjBPOMI+UbzYogCVbAJlutQJmqYX8gvQn
+vLmo4kh2NkoS7nHyCAQb1d7qryoMYq8ODSIW78yj9il4YblajBT0N+x7KuU+K3f4
+hWIosco1WnejXmMDBYXyhzI+mEE0B5nxzio8zSFYXOe06FNiWeY6G7j2UybfA6zk
+7OLT8tEK7xk/Q23ih4wHTndaMYzPMDepEM/hdSXgGHc7O7oXEVfprHLVxVZPy+Ju
+KcLIu1t6BEEpXbrE+Ar4gcJmYQePkMs7UtOxBdTNijcN/egmGY++6V+Pg+vDjqzn
+Evr+rjq9MxtSqMntrtZJ8fLd8Dufs7O/PCAfDAj2lISrYcjx6Zbf/wOaU/+VzCu0
+tGO+ZuxTMWLxnGj4VhFdy2Mm8maayva+qMDP4SBlYsChDMjgMdXBkq+nyXdFNQyf
+a+8owuaXhRd+wpMmPy+4WKkJ35B7rlgOw2uYcKei1IkqMS0Nvl/yH5RMPjeLWxgA
++ubuZm6zXpM75sbQ9dEgwDCHadjRYktEDfVhT1Fm1FRjVGU+12FSMa9wGv/OVWN0
+xW1g3dqvXQyHQ/MuWGRfU0OHa92bu1cJ5vUPVtPOdNXwKxx8AdFlqZyJWsCd2OCb
+ST/BEi1+SBIPeV73M6movs6zFP2/e2VKvDArHThf8dVQROqPGO9Nyg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9.pem
deleted file mode 100644
index 2857bd3c74..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=UTF8String CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICczCCAdygAwIBAgIBYjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEExCzAJBgNVBAYTAlVT
-MRowGAYDVQQKDBFUZXN0IENlcnRpZmljYXRlczEWMBQGA1UEAwwNVVRGOFN0cmlu
-ZyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwNymUjXTPLYfQm1sbyf8
-QSDxshobqw4r+yna0i1Rj3o7Lu/5vt/vqIPKH2r52EYvuFWBMNKCglyCcqidFgVx
-Z+hsUqJi79uj1DhGgqeSG1/gmyduba9sGud4J6rNhVuz1E/dX5gu81Gi8AgFQj/D
-tC+HMSrP6GKAXVbXsnWBPGkCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6
-ng2wPOqavIf/SeowHQYDVR0OBBYEFNMoQWQMXH4Okw1WMKge9ihlAMr7MA4GA1Ud
-DwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUw
-AwEB/zANBgkqhkiG9w0BAQUFAAOBgQAYI8NaUKFwf+db04baEtgElpS8AhzYiCP9
-H+4pn+6Bp7ZK+3WMdR5HVmHkn0wx3+eRrAO+4sViEZYS7+yJfJvQVqgeVgRWZeuE
-dzIXVT0OLIloElDfgpdZgkkM2Ucdg5Nn52Of3AnZagaFiaNqFRZmC+QYnKif09vj
-8jaUJTJbuw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid UTF8String Encoded Names EE Certificate Test9
-issuer=/C=US/O=Test Certificates/CN=UTF8String CA
------BEGIN CERTIFICATE-----
-MIICiTCCAfKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEa
-MBgGA1UECgwRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMMDVVURjhTdHJpbmcg
-Q0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBnMQswCQYDVQQGEwJV
-UzEaMBgGA1UECgwRVGVzdCBDZXJ0aWZpY2F0ZXMxPDA6BgNVBAMMM1ZhbGlkIFVU
-RjhTdHJpbmcgRW5jb2RlZCBOYW1lcyBFRSBDZXJ0aWZpY2F0ZSBUZXN0OTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoxNfkgSuZUKuoTrCTE46w8pIE47j18Ul
-+ZyQJGplDws8AeUtIXBGxaYs6He2jxJXV6geeAi/DlFhUnNSK1Gavbey2DUkn8Av
-3U5y2+p6S4HtU1FMypUCKcboGqHME6y3rqDQSl7YY03v3wd4PPaKPqvhZtDSG7b/
-QnejyG55zHkCAwEAAaNrMGkwHwYDVR0jBBgwFoAU0yhBZAxcfg6TDVYwqB72KGUA
-yvswHQYDVR0OBBYEFFNv7Je2o4j/89zS0tw/sI8eM4dZMA4GA1UdDwEB/wQEAwIE
-8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEAT2NW
-DkK184Mva0VGnLCXsyNVUYV9/6cBxVncmML7X/XlT3c4M7ZjSoL/J+hVyavU+1pN
-SAKfgfyZE6mVa6BOYzL5sBRcvpgJPjZMAEGZ+dwfJUsh2KQvFmEXu8xSBIss4Rgh
-o7OsvrTpSFiidbLgLQW6FeMEivGfw8AZZ2W9+s0=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=UTF8String CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D3:28:41:64:0C:5C:7E:0E:93:0D:56:30:A8:1E:F6:28:65:00:CA:FB
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 97:9a:cb:dd:e8:9a:f3:02:96:35:53:29:74:69:84:1f:c9:47:
- f5:14:71:8a:f0:32:42:64:ae:06:9a:ec:f1:2a:e1:4a:70:d7:
- 1e:11:fc:b8:f2:9b:6b:38:d6:18:37:5b:74:d7:bc:78:c7:9c:
- b1:34:c1:76:87:4f:31:43:25:ce:95:52:23:cd:d0:38:c5:f0:
- 26:b1:13:d1:ca:2b:f1:e1:df:e1:e7:3e:6a:3e:d9:51:60:5f:
- 6a:78:b2:50:03:45:39:95:40:3d:2d:39:7b:af:97:e3:32:5f:
- 14:f8:aa:70:ac:49:6d:44:1d:ac:2c:d2:fb:a4:5c:d5:f1:d7:
- 23:5f
------BEGIN X509 CRL-----
-MIIBOjCBpAIBATANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJVUzEaMBgGA1UE
-CgwRVGVzdCBDZXJ0aWZpY2F0ZXMxFjAUBgNVBAMMDVVURjhTdHJpbmcgQ0EXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1UdIwQYMBaAFNMoQWQM
-XH4Okw1WMKge9ihlAMr7MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4GBAJea
-y93omvMCljVTKXRphB/JR/UUcYrwMkJkrgaa7PEq4Upw1x4R/Ljym2s41hg3W3TX
-vHjHnLE0wXaHTzFDJc6VUiPN0DjF8CaxE9HKK/Hh3+HnPmo+2VFgX2p4slADRTmV
-QD0tOXuvl+MyXxT4qnCsSW1EHaws0vukXNXx1yNf
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9EE.pem
new file mode 100644
index 0000000000..eeb1e3371a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUTF8StringEncodedNamesTest9EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 3E CC 69 23 02 AA 68 46 BE EA 0B 63 31 0C 9F 56 C6 FC 3F 84
+ friendlyName: Valid UTF8String Encoded Names Test9 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid UTF8String Encoded Names EE Certificate Test9
+issuer=/C=US/O=Test Certificates 2011/CN=UTF8String CA
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEf
+MB0GA1UECgwWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEWMBQGA1UEAwwNVVRGOFN0
+cmluZyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGwxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKDBZUZXN0IENlcnRpZmljYXRlcyAyMDExMTwwOgYDVQQD
+DDNWYWxpZCBVVEY4U3RyaW5nIEVuY29kZWQgTmFtZXMgRUUgQ2VydGlmaWNhdGUg
+VGVzdDkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiQyHe+Qlww7JG
+F56OLnXVa6/PwDW5nMyghTVjB/9SVbOF2cOOtFS/pGw9Qbc42wajSZuKP0tEBph0
+SkZlyhpyHwcGn2UMrWolAnAGDugxr83ijb/AElL+Orzm5lxPcuVG8+D1w9EW7JOq
+I4iwhHe70XKdM5RaGRzQpQmfvGMuj6VsMUJaIv+9/5RLycevwNEZl3yiLTV6APui
+hoI8LQQc9C+YQfAzRqz+e9adZIBayMhshpAJtgZ9pdNRPiUXt/NDw4jSbHp+fABs
+3x0i5GMDGBQMI44rUVY4odIM7GcIFZ14HyLY0stkp2PsHCvmd2DBS9QbCA7rWhHu
+8gcdQ021AgMBAAGjazBpMB8GA1UdIwQYMBaAFDtnW0TyDadIfXMpjJOf1STjEmAm
+MB0GA1UdDgQWBBS4qOG97iGSGhivTSqPnNsjcsGavzAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQAeayIn
+ZVW7XoaTBtQWUmvNBO3bMOq/FsCioTns6lSZp3JeTMG0yj6HmxJGNLuDNMzcfN88
+piQ7sfvNf+lcWb0gwdB2HXWTU4TcpAHUkn83Fid9og3gZv4YDh+fIQtcaL4/Yja0
+cSDiy/OYHvV3ehEuTAnMPh8Utd5UI72eFwznL+7lFdJMp6IMTa0GD5iVjkYDSOE8
+CBFv1vyFZOpiM3US56Kuo93VQdDUSXZdbHphgddospcnlW1fQ4wvMUTZpXeqcbu0
+kDqNIM10ooUbnkpa8Zsf1aOdna1p3GcFyJTdpKiellXrtc52azNxwHgPwvchG4k9
+RqHAGNJlDwsEHMB2
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3E CC 69 23 02 AA 68 46 BE EA 0B 63 31 0C 9F 56 C6 FC 3F 84
+ friendlyName: Valid UTF8String Encoded Names Test9 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0348A1ADC6843B58
+
+CIUrRDnJzviIO4bKwrC4z7P78xkD3j0qb4EcLeCJnuPgRioje5DcQ6mc0EpsbDrB
+r9HT1B2TtIK8VjOn0Ij35TKPMCKXNWajJALwcrN/h7TwR31X9m0DGvnhxBi5oZSc
+JWdBsePDApcIxfxJ70pI69gY/yOW1I8iKUXxGtmdOJBOupTQtmEbiDw4jlPIlImc
+AJErDVFhtnLEQgczv/+/J8QeW20NyrxGxkcZjBBAQkwn9A00MuxeQ31KYYEBe+xN
+MXOmVz1JFJhQTdIooH8bEPRBOgW2PF0ZXYbL70Mj5X/QRnFnw5IL59vn7G/RylMz
+uORlOPzuldVxwnNk3eff2LK/S5KdG2f0G41T09Y3j9BmtuVCfqX50bUvneYVfVsL
+a3a5/zZc1JYGlYrSy0wqilV/5dPBR8JcEz/jXqV/BkqBOZgoySm3iBbeo8jy7Zb4
+N6uamLwmyu/ED/EFNyIqJ77ITs/AK4aOVepAcITyreRpkuxmlzJhdrKzkukfZokq
+Qy+MAXyva+gXbP7gwLeWAl1BN3GgekvhWd+DTMrAbK/9E4y3A6poNe9xS/JNUqfu
+E7bMSvzawrxk4vh1t5evsrms7SYR3JnI0nFoZfVynwifAG1ci5xafQe96Wd7XII+
+M1z+Ifm24UodrIBOB9pMzlx2hENo3f7f9DSzbLKJUHkc8voBQm+Pn+MGwNH42Aux
+TGmsNjekaboeY3kQK84KmsPzoTQ/LIKAEs51T6bss4cJxUlMK1ZqW4+lUt2hDAmz
+WXqmdaq6gRFwQxZbEH69yEul6HIYIluTVQKFR9qYZ3cipIMcjPdOq+6MZfMcNOD5
+knsGLmGa9IbLFF99ORvT/8Ul+eyCrGdJ3G0Q+4HL2Tbf9eacL56vQC2JZiN1uUR6
+R9LDOrGfy5OlCSgk+gLTm0p8BQOAiUuzRSO0uuhufa/VnP+se0Fqi+5Z/b+J+CVA
+brdbRQnadvUilAj091EjBP3meXY6OrKNmUOW3ZUfUSOLyfY6WffxxEDL3+g6zY6F
+XqprdfcL8iP18DXm+bQSCq9SCu2PWnqH1heknCvZ/rmleqty0rdtheJjzLMTaZZZ
+FEOTkaYO/enFVPJBghO0aoK1nSfIU72XKqYdI0Fs79wXGpyteZ5eedbMf5XzcJWp
+7dF3jSgfDyKAgZ9kULGBNUGRlbyQPwfZEwXxqG7BtnO0fDuu1OmAJcGvmhYaUitq
+R2bYN60a2+hWa7CLX5jLlwI6yhAKHI9B3Kav5tAma8Paj/WoOem2uCMSxMx6ZCzA
+IZ2WJSDsY9pkRLf1nCOBl0+Ym1XWIcr6k1cGFeAw8YEiUUn+N+Veek1dWrMh5bu9
+RBndLWrvlu+lWnCdaVUHHgoNt2nz+SlaHux8ODTL/TFUeLl0b/d780hVms43T+jf
+k0M78bCKpK0MYOukRkjedQfgH/WIegpFq7KK9MY+oT8iGzTjDXMLyzPqt8ha9EMK
+sm5QkYWPjrYguS70tSDxjO2rWYAvtiz0f1uTujaRSNmFxNrl8FdY0uoKh6Xtbzvb
+fnwB9bjxpPySbDK2mV8cK+8kUL4ZW+4b5dSOl+PWh7e4NCFBm4JpwQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1.pem
deleted file mode 100644
index 7d19088eda..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1.pem
+++ /dev/null
@@ -1,58 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid Unknown Not Critical Certificate Extension EE Cert Test1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpTCCAg6gAwIBAgIBXjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMHIxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczFHMEUGA1UEAxM+VmFsaWQgVW5r
-bm93biBOb3QgQ3JpdGljYWwgQ2VydGlmaWNhdGUgRXh0ZW5zaW9uIEVFIENlcnQg
-VGVzdDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKhu9MiazK4MZfZxFp8b
-EqQNtc72SyzLI8gVU6uacEHKLpo7auSD72gD77oJKNLO0wW/lJmBZrr8N6Vb10xG
-UDpyNayjEHhIQ9YGjQ0iFAzwBZdxSba417KwGoZEtWDwXDgHFcJkpdeO0cmvN/WY
-T3hTDuDubTGzkT/z3o7HLBXVAgMBAAGjfTB7MB8GA1UdIwQYMBaAFPts1C2Bnson
-ep4NsDzqmryH/0nqMB0GA1UdDgQWBBT2UVRewjWmpJzpb1mXbOTeaXT6qjAOBgNV
-HQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMBAGCWCGSAFlAgEM
-AgQDAgEAMA0GCSqGSIb3DQEBBQUAA4GBABs3aiPSbahf2RsQXVpA2945ngkKbfef
-RWOSqb+RmLmR3zburW1DXXzu3XSEOB8Ud75OdMvg9MIeKss1EqhEp3Bp4ltMa4+V
-xORBZ1hlK47mQAPiGsshFriTYp1nVfzHfByAFuwYZFLhjJnk2w/nyq5kyQ3AjfpQ
-XaezK4Qnje4K
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1EE.pem
new file mode 100644
index 0000000000..7799da859f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidUnknownNotCriticalCertificateExtensionTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: EC AE 20 8D 62 05 B1 DA 8B A5 41 80 4D EE CF 8E 2B 7D 30 BF
+ friendlyName: Valid Unknown Not Critical Certificate Extension Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid Unknown Not Critical Certificate Extension EE Cert Test1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApygAwIBAgIBXjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowdzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExRzBFBgNVBAMT
+PlZhbGlkIFVua25vd24gTm90IENyaXRpY2FsIENlcnRpZmljYXRlIEV4dGVuc2lv
+biBFRSBDZXJ0IFRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+xR67LyBnthZAMPhZkzpYoGxHaIbC/er8Fj5AlXd619zdvMCaWmXE+d6pHByEo6+R
+VZRovpOEhiapfjZX3ZYtR0zzFXFqGZXNTlP0caKIjOGgqrSP5ZVLbPOk1j38hOHW
+BVRBUigp/ADaBQ43c+EKf761jIrgHHG2MtE9zmj1HgIa4Hbq+K5ejoangiGNPZXC
+VFeTSReh9DxC3gilregD6KPR/AQzeV2/BPBse3afXlR/i+2R256tZy0HhzMLSntU
+JyEsA2I9jqw7kfRQw749ZT6uhNi/KqFWYqtj/iIqaPF82JidKkQmevqZT0WdtIfB
++MtYDIWABmwx/bBohbsfYQIDAQABo30wezAfBgNVHSMEGDAWgBTkfV/RXJWGCCwF
+rr51tmWn2V2oZjAdBgNVHQ4EFgQUTqAIoK4LHZBaMv/WHFi0k/KurlQwDgYDVR0P
+AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAQBglghkgBZQIBDAIE
+AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAEjAmvYQDnZ9h9tK0SPGVI57LiptQxKz0
+caPfRivaSLTlNQ3umZJkDSVe1+QKt9x7QchbZSK0v563XUmnGLj+9w6OWJUXsatf
+DMXgoasef6Y9HNKx8JiqUwbtJrDEXjvpqsdXE6ZMyQ4ij4C/VTAf7QD6bLpMLRmd
+lBl1NQzcr6F7fz9exV2PyWJL7E28ujxwcTauXmANKkQ9hKgrCuWuVx6o7qpqKpf/
+X1ldl9VwVLg9sO39+2J4Q+vxssFjlkggUfbz6bE78DLwMIruCIvgxbuCrMqy4cbp
+tqHqzvth5CjRBEhGBwGPqjvampYA2+ZofTyq13bMqp5Q6aCzCvjR6g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EC AE 20 8D 62 05 B1 DA 8B A5 41 80 4D EE CF 8E 2B 7D 30 BF
+ friendlyName: Valid Unknown Not Critical Certificate Extension Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4DF79075B2123655
+
+dul293n8fUdEHnuzI/oNHAfx+1qGPCJ3SDu+sZkktfOJ0FZXYtXPhc3QcA5/P8Qg
+FyitRbAWpS8+AYZxnOYyzPNyi6eT2a35VYmamkPwQMi/6ClqXpbfDsSL2ee3cihD
+h46A2/NbYYsh/SWqVR4kIBP9Nxl0ziiRiNFMdNJg859WFvi5W6GkeMxcexfFH/Dv
+ot32/PVbbA34X/al2GY7Uk79r7Gjr3o6eDVnM2u2Vst0ZcluYqWL63C6pXeA+LDP
+XpGdI9q5vTWAIaS5Z+ANeappx9yIhJ7t8MSP1gFwZ+sw3yZITVs7ojzypvn577UW
+CfqjIV7kPJ8j+85CVi2SZAoY2yf7/kjCDZJg9HV+tclMQOxY1A/eDnh6QQ4dCV/A
+c6vxAFzLGHOvSOUJHk6V+64CI/9tkCKZdXjWA4N3KK9msremwpMOl8Ruvdgm1Rwc
+gvbltkodoeztAYhGK6wXqDACbX0IaFELNbnC4H/WOr9CRrYvMCUOy6sdZtQj6dwE
+ea0x9FK7SJ/yYxWZ8TdQJhXcCKe/s0e15Pb9rUhD+xkLXfY1D7F41Csuauqvtns0
+0iQuXmJB3/v0/aYqCZvCIy8HXxga4XssLvPeZo1VQAAXOI7tB3zurunebpY1iyJN
+v11JEZbeWSIFL1kD8Faimz5k+WxoyFdVoe3Glp0yRNbINPYsy6l62qKqokRN9OEd
+kniqBTUnKbqvipyIjTiUn8Blk3M3o/0xOyIO7FmDmhnQeeRxOXX1R5cm2UFKHF5b
+WA/NTfnv61712IJDUZWLPEPqMkP+rMA9XXAcFB6LZldaIdFTi5pTB2UTWLYpdI3S
+H+N94C2FtVC4xcCZ6ZhIrw1GV0kMyrjr5V+h3bG1Kehmd4icyqQxgs5XcXuQ2JZl
+uTL3/9pEwHzW+2+Nl5LBxqNmUfwdC1ax/HXeG1iz7mT9rJEWPStzNNjHMa/+Ci1H
+K47T1Tz3xzsxPtDcpTwqep+jl00k6SL6rbxywWeyORfTUHypkqZ0iEo1CeiO3A8e
+Jjol9lW77O7S29X0P9raHNtV6lxPN5kFAOFDXf58foJ3uGBUGccD2NdCEluRSE7x
+kNM4AywtSNNKQliwuWPnGd3BoEoS/jHM97d9CwC8l5lMeMoTDIRBKeIPwiGPvxVv
+JqqgSMV9kvXhRkGhU3i+YryoaF2BdnBftZQAA5sYRdP4EorL0rO6YcmOTtgcuQ93
+VcPlK4qdv4pdl3q1Kqjwwi92kN9VNYcfY2rQTA09YScjika9sff8LM41jH60aCXR
+VoJrxcOh7mO6zBzdE55glYpvRLFChBAivY5hh5Dl9w0tyY1p0A+HpOxZUSSKPXAh
+kGpvDmjXSU/o3BzttOwoNtUPptxy5h7I/MTvvpYA4JO0hSItuxHpP5pmVYW4r+zc
+vuYZkBt3Vm9fAJzlwSZnRRLhEASGPQxepfWqlEXopcq2NX6vaRDUUrpAq9QFISDC
+eatXdD6DJ/6QhD1yf0u6cxYQU1K4yXBfgl+mq8rNCIMBvuZdJMOD52OmB5MPjK3n
+uoksn/TKZiIkZ4TNsq2IUtpkbzvpHGTrxWVpBfPNG26JLv9jAjW7OFp4qaoTtTgs
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4.pem
deleted file mode 100644
index 8a9c75ecf4..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4.pem
+++ /dev/null
@@ -1,110 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=basicConstraints Not Critical CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICgzCCAeygAwIBAgIBGTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFQxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEpMCcGA1UEAxMgYmFzaWNDb25z
-dHJhaW50cyBOb3QgQ3JpdGljYWwgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBANLhA0OA9wRfp95Q7/HTBd7PlWljTlLaWClrNNQ1jWPhuQJN3ww9dy42U/na
-HvOcy9yz2ANw44VJKqLn68rVvypadYoWUNUGPHgHSrhj37Dj/mNkFmw18BcEgpED
-4OIp2vJW00ZLeMt7ItsFh1pxpaHZl4WDHIWKh0BAuw7VBWhpAgMBAAGjeTB3MB8G
-A1UdIwQYMBaAFPts1C2Bnsonep4NsDzqmryH/0nqMB0GA1UdDgQWBBTYuN8r/BQM
-rtcTVstcPg56jM+RCDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEACqRpg4KhHWSs
-qfP23ZQX2hAOVVT/0AqaTcnNCQVLGE4sE16rMPQMZQ4qpb1WAPZIq6gs+P43deDu
-5M4evZgQVheRR7RqQm7/7ZXAiJ4uzAvJjWP5eYg23OyHqPvaK76reyPgde/gegWq
-Lj/0XhyySYlWDr4i138LYLsfUDy2rWw=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid basicConstraints Not Critical EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=basicConstraints Not Critical CA
------BEGIN CERTIFICATE-----
-MIICoTCCAgqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAMTIGJhc2ljQ29uc3Ry
-YWludHMgTm90IENyaXRpY2FsIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0
-NTcyMFowbDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVz
-MUEwPwYDVQQDEzhWYWxpZCBiYXNpY0NvbnN0cmFpbnRzIE5vdCBDcml0aWNhbCBF
-RSBDZXJ0aWZpY2F0ZSBUZXN0NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-ztwCM4KjCZAusrt0pqJODe24QkEVIKHLb4UAlOxeSbZZ4Ye5BtR5NylouUsMu8Ja
-XKoU+BxIWXmUrP7HSt2+D8HI33xczpxfXCUyYmY/ht58WkhRSur9n3XUBErcVOe1
-xoV/2CNceuS97TvupEAYDKkcK+Uv+gBZpuLyY2jF4ccCAwEAAaNrMGkwHwYDVR0j
-BBgwFoAU2LjfK/wUDK7XE1bLXD4OeozPkQgwHQYDVR0OBBYEFAL9NE678Dg8eh16
-3hZvX02XaVPoMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
-MAEwDQYJKoZIhvcNAQEFBQADgYEAxH3RpgHseEdMz+tdowijXMxxOgAvJ+bDmb4W
-VmA6BBlPljNwDeOJ5mu/qq2HaTbeYYkqxfGw/V0Nv5GoG4Ak0xnSFaVz8+dVEzDN
-Avks85QOwYREyw/sxlpU7uOjlWBOwfkglUJM8UU2ZpBMlJf6sn7bEf5W9w35ZUo8
-Vlf2alk=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=basicConstraints Not Critical CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:D8:B8:DF:2B:FC:14:0C:AE:D7:13:56:CB:5C:3E:0E:7A:8C:CF:91:08
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 9d:dc:8e:45:7e:1c:6d:56:eb:08:bd:04:5c:c7:9d:21:a0:ae:
- 69:b7:35:a2:b5:31:34:85:f0:0a:92:7d:20:36:2e:32:dc:b9:
- 8c:cb:ad:39:97:35:3a:9c:d1:68:37:f0:9a:06:ad:da:42:67:
- 92:30:82:b8:52:db:c5:d5:39:d4:2f:cd:7b:ec:18:43:56:6d:
- d7:2f:31:9c:59:48:fa:07:af:f9:fd:3a:b7:e0:b2:4b:0a:7c:
- e9:7b:04:81:75:1f:58:a2:70:bb:30:bb:e2:14:21:0e:34:74:
- ea:e3:41:e5:d0:c0:b4:7d:51:52:f6:7f:51:13:be:78:96:25:
- a5:8a
------BEGIN X509 CRL-----
-MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAMTIGJhc2ljQ29uc3RyYWludHMg
-Tm90IENyaXRpY2FsIENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8w
-LTAfBgNVHSMEGDAWgBTYuN8r/BQMrtcTVstcPg56jM+RCDAKBgNVHRQEAwIBATAN
-BgkqhkiG9w0BAQUFAAOBgQCd3I5FfhxtVusIvQRcx50hoK5ptzWitTE0hfAKkn0g
-Ni4y3LmMy605lzU6nNFoN/CaBq3aQmeSMIK4UtvF1TnUL8177BhDVm3XLzGcWUj6
-B6/5/Tq34LJLCnzpewSBdR9YonC7MLviFCEONHTq40Hl0MC0fVFS9n9RE754liWl
-ig==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4EE.pem
new file mode 100644
index 0000000000..ff5bcaa6d9
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidbasicConstraintsNotCriticalTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: A1 9B 91 68 9D 3A 8F B4 87 03 A5 A4 FA C9 28 88 91 62 36 E3
+ friendlyName: Valid basicConstraints Not Critical Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid basicConstraints Not Critical EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=basicConstraints Not Critical CA
+-----BEGIN CERTIFICATE-----
+MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEpMCcGA1UEAxMgYmFzaWND
+b25zdHJhaW50cyBOb3QgQ3JpdGljYWwgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAx
+MjMxMDgzMDAwWjBxMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZp
+Y2F0ZXMgMjAxMTFBMD8GA1UEAxM4VmFsaWQgYmFzaWNDb25zdHJhaW50cyBOb3Qg
+Q3JpdGljYWwgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC+lPXP5KQEuLh1WekcPzNwCFWuM7cmi/FG3qRPojFw+46s
+DOSAtp94IFLaSYBGyblsOrYA97PExGbctAmt1W38kUO2MIsk272mfINEJPrdGaAL
+JjgGYcpmdOK0TgMCmVGKbUpNkPxGqeAUyWvfZbg6Cdd3QDBy9Q5ad1UxNd+EDkTc
+2vwH2C2VyqssOWfn93Rr2+klQo0F3KGClsQjwSmqvOR0gOv2f9snj0ldwPsovrZ8
+U9GxQOSYTowkGrV9o2H2+1jQYATvjAxqaanPAjXgVW3vR2gcq1VoVvN1fGYJETQa
+ZMa+JgX3AVLS97p2Ff9W4DTv7DNmH/bURXjo58gNAgMBAAGjazBpMB8GA1UdIwQY
+MBaAFAqkuTBDrEPINAITz+9V6L9wn0avMB0GA1UdDgQWBBQlrmGYIdS4j+kjLBG0
+7x6UOiFEMTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA0GCSqGSIb3DQEBCwUAA4IBAQASHVtzeHQAZSeSrZIJOSNHbe2hiGUeR3vWeod1
+aXrs8PRmqYyNdQ77ZYSfh0wVLEH9AtDPZXLBWEFcHQhJzO/hmtNsn/NYK4jGyzr6
+c/bF4sDJ1zPwkYZDJws3p9lmU55jhZrRYDd/fCYqpwo8IgWg7xR/glMMaAfMUKze
+eKttcTD50JUTlXehKX8hbMk2M+HgfQRRh9YuXFJEAJLscldY61riMQJ51/CLPZIG
+62jXV1vi2zixDY4Q4vuq2fN0alQVbx5g/yAisKi2TUWPe9+H9N04m8Xyq4FE+OsT
+YZsUiT/MiWoI8zXMqRnC5TErkFSxGq8cNqx+HBj+Lad8266A
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A1 9B 91 68 9D 3A 8F B4 87 03 A5 A4 FA C9 28 88 91 62 36 E3
+ friendlyName: Valid basicConstraints Not Critical Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6D557D0EF72B7F65
+
+jRjR5uPELeAf9XrkOa1X1bMqKH8P9oZXbRrF4apOXvCzv6vd/mGaR5divIbAbY6c
+qh4ByJt6Kd7JTWTQpVm+518WqKCi0R2lHXLFRkvEnaCxkAiPZllnhyoNQ0mkq2ms
+ci03g97UpyZajB1uCbULbZv/kIHE4K4ma9jVLaR7mReJ72/kQ5A13YNTy9XCE+gh
+3O+21SoWzT+KRjzZX7otnuj8uLo5Vp/Wc4EJF5VxmG3XMb3p9e/LOiP/bUzrh1iS
+t9V73qZDXSm4r+KQbNYbxR/yIEgfkrjjyBENsXxgvXfdQKTTakEe6jRv474g8jHN
+JIlzjVvh7yD9aHZrbG5yMo9CSt7W5yyfzzHKpM11lgYvpJlPy03hp/DoBjXo1Hg6
+WuhlAwbk8FB9XhVWrCkqn21P7DXB5pqrFS66OCshWYP1ngNPKcEHr5wkn1xDs4mG
+EaVCio089f7MxOhXYG34TrPZWxDbWr+oWdt446IPkMmU16Sz5DxYxRW5gdJkwHRO
+T5be8cnaE+KmNVfOw3dH9aoxZL8kbIn3Vjz/73JS8nemtHA8ykLbB644U7cWqK4c
+xHxy8u5RIbrIp3DS6EaJkyTPxrPGPrHsYq5RqKoElkyjMswNUmq5VZKkGHGsYg2U
+7LY5LrZnDft3/9PCoAO6W1AOoqQT4/kOaRTJoH9PVs40yy3KOj2mlIVdPXmLIQB4
+pME71G/Uo01CWb6dlLIMRugwy5NBrnlIJaTIicK8jhh2rKd94t4TeMc4F+R2tbea
+rGflh/mlqQ+UYy/3oqBgQjZmAlJIOJMjEO43xBaSr9J0IqFKSkN7kzNpZH/CbcP/
+AVRwGGsoS50y//2XoQY1xO13nzBrN2wXjpenb9HijVSg+yqk4S3C+pN+rMD3UT3Z
+gFzbhuXxk+AaNVrURgwqwzi0UCXxTaNmMCCJsiRupZj8FvrBVQJaAOGi5HrPxoV7
+Uj7G48C5ykkFr9bBKhFyD6aP8xQp02wTXDx/l1wY8xmJnE5QZnNqGKgqfdoMoa05
+ufa4Ze5D5HvM7WZcediooYtc7a2CA1+R0bRuZ0BXtvU5gkHXvK2oSq5hcKQgDLkC
+6Xvq4TxhezhdCmbuKy8G+eHnpy7k/Y1j5ZAwN/F1jiKbqVoxJP/Q+3xskJBluwK1
+gjQ+SPMAKnDtLbhb9AlRPkl5stZeAo//OdooHepMFcrWmua+mUIrNIOzPy5KKcXs
+uQjdn7sw1a+QV6IDfVA1+Z/3KbQ7O2ULV+UrGqh7R3SYGjCXsDFoUQcMLLNYbfnm
+k3SnGM9KTGFthBeEpr7Q5QZWigKycZ+Q2VpQ4dcMcaHjQi+i934SKMw8ZsReZuRk
+IEMzQbHod7//jVM/aTkb/lFqRJ/V+IRhuLLFgPCAP8tZ6mJocsvxaMHX4kQv+f7t
+gBU6H0A0yPnhQGNkhl07pYiL/YDq8X8+wz6S5K3W6cqgURmkMrnuwd62n8lXEyZr
+5MFLLJKNj0cZPis/3zLJNXzTlKzZDPUWKoLOp9zsFoEESh5yA5Jv+21JKidULudn
+zs/fPzObcSFWjHoH49vk+qIca71IJ6cMOu2kzDYWgFLL3qBbW24t2u/AkbTo3AVe
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28.pem
deleted file mode 100644
index e788cc4242..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28.pem
+++ /dev/null
@@ -1,178 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA3
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0EzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCb2axnNI56WnvGeocp
-atKwDsPjuFVSHeTtyX3KVU/1U+ST/Jtv0u5WPp4iitAz/ddFiiBj4cwgr9hZYd0Y
-tUyBvGAP8UjJVp55qo1hjMDYyxFRqotx6gH4F7wyfu7s08ERFrtOoT91EwbaTFwG
-go0sbSeXio43GfBdAxDi3INGdwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlii8KaatWJ9nLsfCwZc63+6I6ygwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAM8E4GsQT3eKZHuyNOUIn/7ZFw/9gFX3
-QfyYv5/Qozv19LTpdKCuIJuZAO900NFkfI4m4kjaYB8CGf9Z2P2B3ctXzgdI9uJM
-KmRUnMfzzXGKx+jh+/xkwYi5kduJ2RECX0mqAcOS38OFX3ej7LQWTQ9y3oeqevcS
-aUfi6VDmnLr8
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA3 cRLIssuer
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA3
------BEGIN CERTIFICATE-----
-MIIC2jCCAkOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBMzAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UECxMZaW5kaXJl
-Y3RDUkwgQ0EzIGNSTElzc3VlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-mHdETkTcRztCRHzlSZJg4afLgOPz/cqZQIIoA4riJ/kHT00t3kf5mRx0Gz8/GWBH
-wYjUk5NlqDoDlmTby3SFHnZac7Ba/+rkiu4Jzdivp+BKAkiTKzIk9eM5KNv+rpUc
-cy3XKWPbz/ox5+OEvn2NhUfVWTe/RbJx1Nq0Mvybh2cCAwEAAaOB0zCB0DAfBgNV
-HSMEGDAWgBSWKLwppq1Yn2cux8LBlzrf7ojrKDAdBgNVHQ4EFgQUsQ4hS7IckqgK
-M04rBolnT6FPHZ8wDgYDVR0PAQH/BAQDAgECMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATBlBgNVHR8EXjBcMFqgWKBWpFQwUjELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTMxDTAL
-BgNVBAMTBENSTDEwDQYJKoZIhvcNAQEFBQADgYEAbIFuFqULVZjrhsyragErXnS8
-R/sgqnP5GJcPHn7p87dEkExtxEYL5N4XnDQXhWdnpc9UtAzh7qR3xnE9EvjeaU1r
-lnsdkbJNO7DxTaM5EqLxiy/Rpf+b2rBprv10A0HvPloU9JvnVNHxT/2XA6hMnCsI
-6gImM5yk9Sc/rTitZ6s=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid cRLIssuer EE Certificate Test28
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA3
------BEGIN CERTIFICATE-----
-MIIDZTCCAs6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBMzAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlVmFsaWQg
-Y1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QyODCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEAuwCMHRZqCorqgWJ/3RJzqiuHtyGbyYxGxHWcVZTbw4GSmQtI
-F07KmEPqaz7I/wyMS0+u70yDrhQkfH1Esjmx7/srC+p4oBzZMa3/LiyDo0D63NjA
-3JjOdLwf3YRWGE+4XcPbjHsd486hkCCXw4EF7ZfnscRWgNCe6FEzHy131MkCAwEA
-AaOCAVEwggFNMB8GA1UdIwQYMBaAFJYovCmmrVifZy7HwsGXOt/uiOsoMB0GA1Ud
-DgQWBBT6Yyl3V/7WremGwNkDahqsIxegJjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMIHhBgNVHR8EgdkwgdYwgdOgfqB8pHoweDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlp
-bmRpcmVjdENSTCBDQTMgY1JMSXNzdWVyMSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwg
-Zm9yIGluZGlyZWN0Q1JMIENBM6JRpE8wTTELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTMgY1JM
-SXNzdWVyMA0GCSqGSIb3DQEBBQUAA4GBAIk5myvkEmHvyOOh3ygeeWzpz2aV6o8D
-ojAK/KS84CYsP7f64D8FU/H3JFrTXBNOoRiXpqrV5bzrHcmXgodQWTwOSL2KLzi9
-inTs+pRDbTw1oevK3GAjN5BedRZlgIyJr8d05Knp0YGYoItGYQTQXd22Dlzuoz2P
-L5I8AvoFHSAL
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:96:28:BC:29:A6:AD:58:9F:67:2E:C7:C2:C1:97:3A:DF:EE:88:EB:28
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0Z.X.V.T0R1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA31 0...U....CRL1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 15:65:bb:88:f2:fd:8c:76:6d:92:ae:f5:06:d5:bf:c8:ba:bb:
- d4:98:de:83:a5:e1:7a:e9:92:96:f7:c2:ce:0c:de:7b:81:7f:
- a0:32:c8:a4:15:a6:16:e6:51:b1:b2:e5:92:62:ef:46:d3:7c:
- 5f:37:56:47:5d:3c:12:94:a6:3e:18:59:6b:2c:9e:ac:f0:90:
- 03:23:84:b1:cd:0f:49:ff:1a:8e:67:62:35:32:68:ed:24:a2:
- 76:93:5c:b2:80:5d:bc:81:26:ab:02:c0:f4:a1:de:3a:6d:0d:
- ae:02:66:fb:6e:72:49:59:fe:f1:2f:87:d2:bc:98:10:3e:33:
- 3d:d5
------BEGIN X509 CRL-----
-MIIBpzCCARACAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTMX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqggZgwgZUwHwYDVR0jBBgwFoAU
-lii8KaatWJ9nLsfCwZc63+6I6ygwCgYDVR0UBAMCAQEwZgYDVR0cAQH/BFwwWqBY
-oFakVDBSMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-GDAWBgNVBAsTD2luZGlyZWN0Q1JMIENBMzENMAsGA1UEAxMEQ1JMMTANBgkqhkiG
-9w0BAQUFAAOBgQAVZbuI8v2Mdm2SrvUG1b/IurvUmN6DpeF66ZKW98LODN57gX+g
-MsikFaYW5lGxsuWSYu9G03xfN1ZHXTwSlKY+GFlrLJ6s8JADI4SxzQ9J/xqOZ2I1
-MmjtJKJ2k1yygF28gSarAsD0od46bQ2uAmb7bnJJWf7xL4fSvJgQPjM91Q==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA3 cRLIssuer
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B1:0E:21:4B:B2:1C:92:A8:0A:33:4E:2B:06:89:67:4F:A1:4F:1D:9F
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0...~.|.z0x1.0...U....US1.0...U.
-..Test Certificates1"0 ..U....indirectCRL CA3 cRLIssuer1)0'..U... indirect CRL for indirectCRL CA3...
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 68:34:87:64:55:65:a9:87:47:54:c2:2d:14:48:91:1e:ee:59:
- f5:ed:d9:06:6d:78:b9:ff:81:8c:5c:02:f5:08:b5:22:90:75:
- 02:f2:63:62:78:25:4d:6c:2f:1f:a3:58:e2:1f:57:2b:3f:49:
- 0d:0b:bd:85:02:c5:ac:ad:9d:38:0b:13:46:2c:34:f2:9b:e5:
- 22:f5:55:cc:63:fb:c2:69:94:14:d7:e5:78:4f:17:4e:16:98:
- 65:81:cf:9d:72:20:32:78:15:0e:22:af:22:2c:21:c5:7c:db:
- 8c:31:be:ad:59:c4:81:24:e4:ec:e0:0c:40:4c:2b:95:98:dd:
- 8f:f4
------BEGIN X509 CRL-----
-MIIB3TCCAUYCAQEwDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTMg
-Y1JMSXNzdWVyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoIHEMIHBMB8G
-A1UdIwQYMBaAFLEOIUuyHJKoCjNOKwaJZ0+hTx2fMAoGA1UdFAQDAgEBMIGRBgNV
-HRwBAf8EgYYwgYOgfqB8pHoweDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3Qg
-Q2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTMgY1JMSXNzdWVy
-MSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwgZm9yIGluZGlyZWN0Q1JMIENBM4QB/zAN
-BgkqhkiG9w0BAQUFAAOBgQBoNIdkVWWph0dUwi0USJEe7ln17dkGbXi5/4GMXAL1
-CLUikHUC8mNieCVNbC8fo1jiH1crP0kNC72FAsWsrZ04CxNGLDTym+Ui9VXMY/vC
-aZQU1+V4TxdOFphlgc+dciAyeBUOIq8iLCHFfNuMMb6tWcSBJOTs4AxATCuVmN2P
-9A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28EE.pem
new file mode 100644
index 0000000000..2d774c09bb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest28EE.pem
@@ -0,0 +1,66 @@
+Bag Attributes
+ localKeyID: 95 E2 B6 92 51 B8 EE 8C BC FC 22 3A E1 9A 20 48 77 9B 53 76
+ friendlyName: Valid cRLIssuer Test28 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid cRLIssuer EE Certificate Test28
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA3
+-----BEGIN CERTIFICATE-----
+MIIEgDCCA2igAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0EzMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNV
+BAMTJVZhbGlkIGNSTElzc3VlciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjgwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAcgXZlxz1vsqbr5dbfy/fgYWOCvNO
+Zm22LtUSHyeXR1vIpqI+W9/GpT/YipI/yDJuxCklM3GwmgJrQlm7LK57UuiWY27e
+oHKVNGEabtFfyjjOKwRD+yq+0bxdXCR8eFKLr++w5vgHaoeFrTOdV87YGPpzEW/Q
+9L9/xL1fkAo+6h+lIKkWF6oXA/SQMrbE5Svlcc4jE8I5QJiZytL7Or7KH4Szs3FQ
+ZQktcin7oYKrovcKkxBzvAAfr8uxFwPrngHGFd5Ti+hDKVUZyUwRxt1MAbebWIb1
+LpWiQI5w3wx5SEBSQRhDCuW/CqS587vBOQSGuRBcwKA2lAaRJ8wi7q6XAgMBAAGj
+ggFdMIIBWTAfBgNVHSMEGDAWgBRIk1R9xG0w/y1XRXEk30wFn0oALTAdBgNVHQ4E
+FgQUg3uZU2ZksblpyuyaAZ3YIDhwGcswDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATCB7QYDVR0fBIHlMIHiMIHfoIGEoIGBpH8wfTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNV
+BAsTGWluZGlyZWN0Q1JMIENBMyBjUkxJc3N1ZXIxKTAnBgNVBAMTIGluZGlyZWN0
+IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0EzolakVDBSMQswCQYDVQQGEwJVUzEfMB0G
+A1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UECxMZaW5kaXJlY3RD
+UkwgQ0EzIGNSTElzc3VlcjANBgkqhkiG9w0BAQsFAAOCAQEAbai0gBNwrPSxSlGN
+My40YqFlMpSuj0pV0mcRc42WWUX4L4JvXkjLQQoN8kZyguCCcOBkDl/vclb86G/y
+Ar+2wWbtwa2lZQ3VHi4X9ss/g5cXUXX7eDhsNiQmD6KMIIBn+j9GDvHqdaooDSpc
+94b/EsfCCTIoT98Ayng4ScGsezzbiDBFt+kVOZrNwwZIthISbj5H8rTrhJkFcinR
+l1i2qiKugubIptFAnGeUu4mDCvxzWSEJwK3diKK0Dq0DB5siNpUhi3KQsaYkJRKa
+qkxvm1q3H+n50eYDtDTtuEWoIUEciYOS73p1Oums5dLUZL8FiRea9ODY4T+5g6XC
+3yQwXg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 95 E2 B6 92 51 B8 EE 8C BC FC 22 3A E1 9A 20 48 77 9B 53 76
+ friendlyName: Valid cRLIssuer Test28 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0AD86CD7DA0ECF30
+
+kK8ErkJFMMQTRPKQD3zzPgVZSIYadshEsxCXpYU26SadxrnWoCwG72vqjbZEv7ux
+9jgkhlzH5yLd++Qu9RuB7Dj8/leuBRhvh12KwxR+Ct63BVDk5+JdeUgdRXhXzNMo
+YBL7ym3HTrw+eD3Jv075tw8MoCEm2wL/Wle+mn9YZX1h40KoumKL5ESrUZAiAx8f
+orYmGySVqUfM8X7OOS+xk046YMso4tQLWGp10f1MDZcHt3X6RebgV3fdfhuMTPbe
+d0ywYfvjGV8N7M+vRHR2hwJxBkRfWawfqT9se6czEUzOt86htvviu4HMbCD0g9qy
+lLsq2lKe2s8Z9GXW+AjU1Je9yz5fNTmzJ93OB8fIod+iUD0FhriLW+ZalbKNWGQq
+n5yQBlXdxlhd06L6YlHyQLqZvav0dpm5zS94a4gGX/76DLfrL04VLgdhDrfeV8VB
+DWFdoFlGONubIuQCxolKMVTcldU2h7GI7+69u6uBe0kxHdGx20q91x7G1yA0STSi
+YFEeHR3rMR5bUtys0dR7ANeH82DHVIOBo7JV9fg3yRCZlmko99+Yw9zbFvxVn1GJ
+rk5rMZ1tl5fukWDKGHgxKD+BSHll3MpZ49u9laQ+owsBPEqoOQYzHccUrRfKcm9u
+YwT6fQBRteXCiBbvPt+MT5V2C6R+SI2CMtd6V3AQ/E1rjgq6gI8+kI5Ro0WaVsGt
+8ZWd+uAzhVLdDafVsPGmUT9SQGvC2bmPhaUHy1Hur8zm9RMKpsXkrELFHydjJoaZ
+IReLor1mpLE7WkGrUGF1hW+JmdpnYSI+OK24i52Fj5BqGUn596DyTxZLbfruMluX
+sX6AEQ85l2wQzMeyLYMigvJTokI+XX6MxbUP9iCWZjm8/Jjbghyizn7JsaLJP1y7
+oQBndyfq9BkPAdY7wSNCwj4vd5GscCtqBLR+NuJKdlCbcdRwQYTD0FgA9+4JQ+Dh
+6lBxf8ynffsiUKK1viuspfiZR38kTFUYvGKHjVnUV9+zes61qvZll/zV/NEz1zoj
+z0F405gUNExUGBsOAQMQ8oCE2KsK25QMmPJezHa5qHob4EnSRf53AQEQh67YZnFD
+NG7jAAuK3NPeQ2AMzZsWTiHiu9SBTeSsEBnYn0L5VfuAhMKHfsiTLmUODmuKxFOt
+oNSWrTegQQnkVMHeAfiq7xbCRiTAsmQAR5tUH8rBGGDtQVdUxe2RYxKdL+FXL6aX
+tY73dYWsSIltuQkHDAKgi8wrLVqyBkkSvCWYGAfjiNC3aoB2iCVazwwz9sjYi4oT
+vKE5W/+rwkE+CB8NgkJHfE8O5cJb1mbhCwG+AqAdoAlYdgBJUzdU+uzr8wzr9f/5
+DAZ3WzfFqvGTcXBaIjlPkJPgT9Gno1P3twfAh9/RCnwbl9AmySS3FJMZLp+JnQ+3
+DRcpiLVpxR+zyw7QVEPUbQKv82fV6wIv3XCUMqFDY6U2mD5JtoHFeE3bcaxXAVCk
+vSedEEHJPKPIOFTvLy964pLPvNfiWJSnupYO5bjI7SIj+9KZ9jF1cwbMIJKjtCZ2
+3n8JxVSn9pWaYVZZG+EjcXRKh7X6Ax2CfBRw9guMwm6FF6qu5p9kUUan7KumMCVh
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29.pem
deleted file mode 100644
index 4eba759d4e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29.pem
+++ /dev/null
@@ -1,176 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA3
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0EzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCb2axnNI56WnvGeocp
-atKwDsPjuFVSHeTtyX3KVU/1U+ST/Jtv0u5WPp4iitAz/ddFiiBj4cwgr9hZYd0Y
-tUyBvGAP8UjJVp55qo1hjMDYyxFRqotx6gH4F7wyfu7s08ERFrtOoT91EwbaTFwG
-go0sbSeXio43GfBdAxDi3INGdwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlii8KaatWJ9nLsfCwZc63+6I6ygwDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAM8E4GsQT3eKZHuyNOUIn/7ZFw/9gFX3
-QfyYv5/Qozv19LTpdKCuIJuZAO900NFkfI4m4kjaYB8CGf9Z2P2B3ctXzgdI9uJM
-KmRUnMfzzXGKx+jh+/xkwYi5kduJ2RECX0mqAcOS38OFX3ej7LQWTQ9y3oeqevcS
-aUfi6VDmnLr8
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA3 cRLIssuer
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA3
------BEGIN CERTIFICATE-----
-MIIC2jCCAkOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBMzAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UECxMZaW5kaXJl
-Y3RDUkwgQ0EzIGNSTElzc3VlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-mHdETkTcRztCRHzlSZJg4afLgOPz/cqZQIIoA4riJ/kHT00t3kf5mRx0Gz8/GWBH
-wYjUk5NlqDoDlmTby3SFHnZac7Ba/+rkiu4Jzdivp+BKAkiTKzIk9eM5KNv+rpUc
-cy3XKWPbz/ox5+OEvn2NhUfVWTe/RbJx1Nq0Mvybh2cCAwEAAaOB0zCB0DAfBgNV
-HSMEGDAWgBSWKLwppq1Yn2cux8LBlzrf7ojrKDAdBgNVHQ4EFgQUsQ4hS7IckqgK
-M04rBolnT6FPHZ8wDgYDVR0PAQH/BAQDAgECMBcGA1UdIAQQMA4wDAYKYIZIAWUD
-AgEwATBlBgNVHR8EXjBcMFqgWKBWpFQwUjELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTMxDTAL
-BgNVBAMTBENSTDEwDQYJKoZIhvcNAQEFBQADgYEAbIFuFqULVZjrhsyragErXnS8
-R/sgqnP5GJcPHn7p87dEkExtxEYL5N4XnDQXhWdnpc9UtAzh7qR3xnE9EvjeaU1r
-lnsdkbJNO7DxTaM5EqLxiy/Rpf+b2rBprv10A0HvPloU9JvnVNHxT/2XA6hMnCsI
-6gImM5yk9Sc/rTitZ6s=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid cRLIssuer EE Certificate Test29
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA3
------BEGIN CERTIFICATE-----
-MIIDEDCCAnmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBMzAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlVmFsaWQg
-Y1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QyOTCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEA3icTqNDmsima/TbMUuvjBhV59GC8zfX3Z3bbHAEH/kipg5Gu
-rREsznRezB5sZVZG9SH3vfWMkugzVFLlYsAsp5Zjon3+ZM7t/JtZJ0pg6XzqsEfZ
-/FCux1F10rMBIsaPzcLtc1At1aWoaqU4ydyam/kDzOEt7f/7WGqGY/ljZVUCAwEA
-AaOB/TCB+jAfBgNVHSMEGDAWgBSWKLwppq1Yn2cux8LBlzrf7ojrKDAdBgNVHQ4E
-FgQU3ZhtNWI1qdWfBti5WKsMkC0xclMwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATCBjgYDVR0fBIGGMIGDMIGAoCuhKTAnBgNVBAMTIGlu
-ZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0EzolGkTzBNMQswCQYDVQQGEwJV
-UzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAsTGWluZGlyZWN0
-Q1JMIENBMyBjUkxJc3N1ZXIwDQYJKoZIhvcNAQEFBQADgYEAAJ+7QrDsVr4IL5DF
-k4CE+XFTE1pd3zqHZCCUSiXp4rY5FEPlsErMT9xcEUB3CiHNFLdKRdaxMxeJ0Of4
-oJV5cnM/0QdVM0HkieFFasr9Ad5CdV7ltfgzgV3fgjDr/hsBAIfcD516l2s3oN7L
-PvlIa7CLUa5f5TGAyvyKF9d1sRo=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA3
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:96:28:BC:29:A6:AD:58:9F:67:2E:C7:C2:C1:97:3A:DF:EE:88:EB:28
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0Z.X.V.T0R1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA31 0...U....CRL1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 15:65:bb:88:f2:fd:8c:76:6d:92:ae:f5:06:d5:bf:c8:ba:bb:
- d4:98:de:83:a5:e1:7a:e9:92:96:f7:c2:ce:0c:de:7b:81:7f:
- a0:32:c8:a4:15:a6:16:e6:51:b1:b2:e5:92:62:ef:46:d3:7c:
- 5f:37:56:47:5d:3c:12:94:a6:3e:18:59:6b:2c:9e:ac:f0:90:
- 03:23:84:b1:cd:0f:49:ff:1a:8e:67:62:35:32:68:ed:24:a2:
- 76:93:5c:b2:80:5d:bc:81:26:ab:02:c0:f4:a1:de:3a:6d:0d:
- ae:02:66:fb:6e:72:49:59:fe:f1:2f:87:d2:bc:98:10:3e:33:
- 3d:d5
------BEGIN X509 CRL-----
-MIIBpzCCARACAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTMX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqggZgwgZUwHwYDVR0jBBgwFoAU
-lii8KaatWJ9nLsfCwZc63+6I6ygwCgYDVR0UBAMCAQEwZgYDVR0cAQH/BFwwWqBY
-oFakVDBSMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-GDAWBgNVBAsTD2luZGlyZWN0Q1JMIENBMzENMAsGA1UEAxMEQ1JMMTANBgkqhkiG
-9w0BAQUFAAOBgQAVZbuI8v2Mdm2SrvUG1b/IurvUmN6DpeF66ZKW98LODN57gX+g
-MsikFaYW5lGxsuWSYu9G03xfN1ZHXTwSlKY+GFlrLJ6s8JADI4SxzQ9J/xqOZ2I1
-MmjtJKJ2k1yygF28gSarAsD0od46bQ2uAmb7bnJJWf7xL4fSvJgQPjM91Q==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA3 cRLIssuer
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B1:0E:21:4B:B2:1C:92:A8:0A:33:4E:2B:06:89:67:4F:A1:4F:1D:9F
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0...~.|.z0x1.0...U....US1.0...U.
-..Test Certificates1"0 ..U....indirectCRL CA3 cRLIssuer1)0'..U... indirect CRL for indirectCRL CA3...
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 68:34:87:64:55:65:a9:87:47:54:c2:2d:14:48:91:1e:ee:59:
- f5:ed:d9:06:6d:78:b9:ff:81:8c:5c:02:f5:08:b5:22:90:75:
- 02:f2:63:62:78:25:4d:6c:2f:1f:a3:58:e2:1f:57:2b:3f:49:
- 0d:0b:bd:85:02:c5:ac:ad:9d:38:0b:13:46:2c:34:f2:9b:e5:
- 22:f5:55:cc:63:fb:c2:69:94:14:d7:e5:78:4f:17:4e:16:98:
- 65:81:cf:9d:72:20:32:78:15:0e:22:af:22:2c:21:c5:7c:db:
- 8c:31:be:ad:59:c4:81:24:e4:ec:e0:0c:40:4c:2b:95:98:dd:
- 8f:f4
------BEGIN X509 CRL-----
-MIIB3TCCAUYCAQEwDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTMg
-Y1JMSXNzdWVyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoIHEMIHBMB8G
-A1UdIwQYMBaAFLEOIUuyHJKoCjNOKwaJZ0+hTx2fMAoGA1UdFAQDAgEBMIGRBgNV
-HRwBAf8EgYYwgYOgfqB8pHoweDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3Qg
-Q2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTMgY1JMSXNzdWVy
-MSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwgZm9yIGluZGlyZWN0Q1JMIENBM4QB/zAN
-BgkqhkiG9w0BAQUFAAOBgQBoNIdkVWWph0dUwi0USJEe7ln17dkGbXi5/4GMXAL1
-CLUikHUC8mNieCVNbC8fo1jiH1crP0kNC72FAsWsrZ04CxNGLDTym+Ui9VXMY/vC
-aZQU1+V4TxdOFphlgc+dciAyeBUOIq8iLCHFfNuMMb6tWcSBJOTs4AxATCuVmN2P
-9A==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29EE.pem
new file mode 100644
index 0000000000..a361c3ee96
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest29EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 66 79 78 DF B6 14 66 FC FA 2B B1 94 E2 E6 9E 44 45 B3 13 89
+ friendlyName: Valid cRLIssuer Test29 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid cRLIssuer EE Certificate Test29
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA3
+-----BEGIN CERTIFICATE-----
+MIIEJTCCAw2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0EzMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNV
+BAMTJVZhbGlkIGNSTElzc3VlciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MjkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCr3eGR+sBYL85UTAHpOdf45y4rELYl
+wkiGSqJB0cDybDToAMVL08FJKdEfFC7fyOiTCRd18R/tV9iAopb0sLGPvcHDkeDP
+Nr6IBJq3rpnYOhA/iKb9+zwTNJqxAmAac43HTADC9FCaY6A5HxVO/OwfXux92WDg
+obFuNFj/axWUnERbzU6u4r4rl02Cn+nWtXqYRUn8WHRNIggdZjxNbl0ns1Ynygkv
+X7Uld32VzdSiS4h6xF0mf+IhgVBsP1yiiQLuY5xMqw70i2fSpj93Bm2w/xilKiL+
+odvCDINZiInokTGNzf67hxM01LkLlIZDNDZadNY9/TN50RpprPckGIajAgMBAAGj
+ggECMIH/MB8GA1UdIwQYMBaAFEiTVH3EbTD/LVdFcSTfTAWfSgAtMB0GA1UdDgQW
+BBT/vJxlImx2fXxtPpgGHfvzrNORyjAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMIGTBgNVHR8EgYswgYgwgYWgK6EpMCcGA1UEAxMgaW5k
+aXJlY3QgQ1JMIGZvciBpbmRpcmVjdENSTCBDQTOiVqRUMFIxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMSIwIAYDVQQLExlpbmRp
+cmVjdENSTCBDQTMgY1JMSXNzdWVyMA0GCSqGSIb3DQEBCwUAA4IBAQAbMog7F0ck
+BMnOTiITw0tI6o2ZuPQHvTqPIN37xQRzo2nkDAKsP3Z0bYp9l5LMhwvXB/ngYF//
+mgbfuZvM7VGhmvOAXKxRJSP/pgcMIXYmD6wxNnbd8+RSXGMV3sY3qxkgvpk4OWek
+kXrZOjJvsvEFihZpaaK+tE09+A0yjDSIws/8a9KQ8tlLRlfhOnthoUfKYuxgZVpw
+78j1wbj3hFl2q0Zbk1iIBi8gHFHiVhbpEE7a7ui1c8cNCUZmMPvm/ojEkefFRMIv
+3KX8NENvjgRlqowMz2oMQQrEtMswy7ofQ2qso0oH417rhglOY9YQPjnCKEWdYQuw
+7j1p8nTrvKa+
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 66 79 78 DF B6 14 66 FC FA 2B B1 94 E2 E6 9E 44 45 B3 13 89
+ friendlyName: Valid cRLIssuer Test29 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8EE0D1DD985FBC8A
+
+Et6YIfjyHfadq7IW2VA8RHjauA0LFzaerIAdya8gGkq2NHxRSXUaAdaQzxK2kHJE
+P1fZvyVUlrdsm/ANhWMp8aSnRhVh0+M4EjcjBvEiui/adNzTorJROOBxcuiwdoo+
+7UerJl1jqnwU5wBRzew829uxbySILsDkhymURrCMqveq4G9AT8Izekg754zVBowq
+oblsyHLin/PIMKWOiwGBJWsdGKLlpcIp1Oi3CeCq0TrIDWaId3/iL8H1g3Rytib8
+AzmRlmUATwACWrvRo945GYD+x3taUB0Bl35l6+3K3SMHddqtRlOR/iF1JRsTHDq6
+8sYZBaiI0RtuAVTleh0gLI+zLxf/kNVNX/3eWd9RcxydMlV+w/+c2og+jiS3VNpd
+3YdgghJ+QLRQ65nq4yCwLLe9pbKgxHsKYA+0fZX8nDzj2TREcsimNyOPW8ZNt7kL
+wMJPnA6AMMcDQfDDsijxZo4vQaWRoAknd+KXZP+EeYXWJP3c6UDLXfmXMC81oG7c
+QMLvXz90OzPegb+2YbBQYE0RoyVBwq3KjmUHg/SGOOnhngEIQSXqdDsf0+khGkzw
+VlRr4cstFXmlcUoa/DIoMQKyVZh51tY919k+dhbyYok01cqIzgD9WzNKpD+Me1HN
+CE1EG9Cd8iZ7if0+LXcHui2YzYrjZOTG4WsEA0ZPzTIVSiXw2jQ4X12Trwbb95EO
+1ye0eSbh7+RGs33IkK4D5nHymEghqTh9P0c0fNq6jqv4+R5A9SLpoQ2f3RfTyg8h
+1/UpfFPdJqviOYabqenbFGbSGy/md4wHvqh2m7lqRUe0gUJrJ5FrR+oSuYFOJrZk
+wVA5Ce5bAI7ZOdtgt2s4+/p93d61JJVrk+dmBqjLsDEPbA4AZqNJf/2EUpaAVV0v
++ycWwFnsnfmbZE4NakWCP19MY/ZYzTMJgQgyKOHO8iy5GRXkU0e5Y7n19f2c136H
+hxRdP6b4Vzx+lemLcKPdFjeV2dRAebhdMr8wB4FZ1go+aYxMmlWYuhH7tKE8qbDY
+D0aoRU8r6d3DyHzai9I+gXW/yKgbs0RiVWZ1fXq1pPhYMXrqecTnxcu3mONrkDGI
+Hckutom+EshGpbRPDCN7lTJoaUZQoY8uXeCyaPiXdHLSsdXZjIWAF+9LoJsQ5/9v
+L0rhVkt+P6EMjshpvnVLpM9iqOzTJdfmJMCFZscoPcAodjDdMHvD1ZvUPkWWEmRH
+TOtSRFqhbPALKYg4f/ujqKmb9oMFrOlWQtLsGr9di4KH0WiqMMZTj3Lh+S0eb4kE
+mXB9Esu28FFBUnM1kWnAJXoyALp9Ah1HTdbEGBNgTzHS4k3+MX8fSNUm0awRrbA7
+z6equPhnEnrDpljoGlcmwTfmnHqTd+BSV74yND9dUoKZldd1LBBuOzzPvrwD7UtN
+7l1m6s5cI5DyIjI1uzDYmb8kEVwL3gd2ts/upTEZ1dBH2zEsrleSYXSoWcLYM6+d
+0Wa60QHYkRQ3/Q6a2qIEBeizYpm/APEWmN0OFVVvHIi2qvj5Mp0f4YlnZFeY8Nv0
+YrkixNgPEarGTXwAzTdYqhNQlOR1VSxWDKlxU+T9L5jHkbU1oTswPt0WuJF1A/y0
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30.pem
deleted file mode 100644
index 5fa8620800..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30.pem
+++ /dev/null
@@ -1,143 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA4
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBVzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0E0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOomKt58EC5ZhZuQ5l
-1sHzwQGlV0aO6IxFJcWNzxERgALimki0sMEmrMvIg7vymvt/sQE/n4ivjA4Zmi7J
-AvHlOsvgWiM6Kv2pvPkoBbRuOLQz1jrvOXIQlapQc6bsv3Cp8tIpxtNdjHEagqpc
-+yL8WWtTTB89P2WOaDjUevZPSQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUrbJDVL6XeFCXxQvyNJPFyECwuScwDgYD
-VR0PAQH/BAQDAgIEMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFWfQvCC6bO3TFmioOAPr4LLUDYbz8Za
-z26H0RgIrFnUEmrPZF7i4/iQpq6cJmWcOb3M3wI/3IlaUmydTEOBpGGazIlk7NF6
-28v19V7KsugitbLcZJXOtaqbseyfwWgFT3LLvxV8qJqKBhNR3NUJvjdBYU6KlbeE
-rZoFX9Ru0Z0G
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA4 cRLIssuer
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA4
------BEGIN CERTIFICATE-----
-MIIDWTCCAsKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBNDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UECxMZaW5kaXJl
-Y3RDUkwgQ0E0IGNSTElzc3VlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-vVQzOttxelJEVuWmMiwdG3GTEejfYhWdQmYtsSPFQ64V3B1F/SYYykFOPCVAbkZh
-PvFOhkUY0iQCBXi95lpCsWt31O2l5oIhKuzqBU6q86Ymk32qDQBvwtaHAlHRSdfn
-nPsCxWlDQdl5El4WL4/bT60xL1SdwWePNDldrtN7hf8CAwEAAaOCAVEwggFNMB8G
-A1UdIwQYMBaAFK2yQ1S+l3hQl8UL8jSTxchAsLknMB0GA1UdDgQWBBQF35wWai5Z
-gbV2xnj1OQvb/oVaYzAOBgNVHQ8BAf8EBAMCAQIwFwYDVR0gBBAwDjAMBgpghkgB
-ZQMCATABMIHhBgNVHR8EgdkwgdYwgdOgfqB8pHoweDELMAkGA1UEBhMCVVMxGjAY
-BgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBD
-QTQgY1JMSXNzdWVyMSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwgZm9yIGluZGlyZWN0
-Q1JMIENBNKJRpE8wTTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTQgY1JMSXNzdWVyMA0GCSqG
-SIb3DQEBBQUAA4GBAFKBu5yoQtqwA+MA/6AboLUyFrryUbT8gm6n5zVA7H5ezmO3
-apxKCgdHPEshKAN+SgO2kto0eE/4s2MF++66pMA+r8TDDmCrOfYVwMHyPVOrBKGM
-n7C+rt0ozZ32wA3d7k57IIsPT/H56TdX07oV5URZKAJ0k5iaPCBBLmF9w6BE
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid cRLIssuer EE Certificate Test30
-issuer=/C=US/O=Test Certificates/OU=indirectCRL CA4
------BEGIN CERTIFICATE-----
-MIIDZTCCAs6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JM
-IENBNDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlVmFsaWQg
-Y1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QzMDCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEArCi7o+0oIpxvpPUN8G1Ys04I2kgIPVMldcU0tM/QiAGdPEXG
-j/Hcn9YQZVOGFuuPKge/kZ7wheOIpI91lKkeGqegSWssN1BzgiAJupENTtDlex3I
-FqatuDIln6nXgUp984F42mLPqLcXqSiAzCkJiPz24slUDhJiLWkEE0fWFrkCAwEA
-AaOCAVEwggFNMB8GA1UdIwQYMBaAFK2yQ1S+l3hQl8UL8jSTxchAsLknMB0GA1Ud
-DgQWBBQ4JkHeuoJrm1VjW/qWHf72m1Xm5TAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMIHhBgNVHR8EgdkwgdYwgdOgfqB8pHoweDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlp
-bmRpcmVjdENSTCBDQTQgY1JMSXNzdWVyMSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwg
-Zm9yIGluZGlyZWN0Q1JMIENBNKJRpE8wTTELMAkGA1UEBhMCVVMxGjAYBgNVBAoT
-EVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTQgY1JM
-SXNzdWVyMA0GCSqGSIb3DQEBBQUAA4GBAEGbnAJ6dpMVdHCjEMoVtyK7az1Sxcea
-28kAl/5TcdMNyP/DUgoweDRVQcm7sbJ3se3M0ac/+I9ce78YpS2e+83drRFYDRTg
-4DRD5RJUr6SS0F4tAwyncyaCsTn577sLWSmnkF3SKBiz6QNr83tetioIeXhAUcoI
-0tg5RoGSJkFD
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA4 cRLIssuer
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:05:DF:9C:16:6A:2E:59:81:B5:76:C6:78:F5:39:0B:DB:FE:85:5A:63
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0...~.|.z0x1.0...U....US1.0...U.
-..Test Certificates1"0 ..U....indirectCRL CA4 cRLIssuer1)0'..U... indirect CRL for indirectCRL CA4...
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 8f:7e:a7:21:7b:8e:70:00:d3:23:a8:d7:d5:ce:87:34:44:e0:
- ad:e2:89:f6:7e:9d:5b:2a:b7:af:57:bf:95:bf:5e:6b:f9:1c:
- 40:77:87:ea:eb:b1:ad:0c:e1:55:82:93:f0:bb:f6:e5:4c:33:
- 69:e5:41:c1:c9:6e:ae:b4:98:38:a0:1e:38:e1:20:84:d9:2d:
- 9f:2f:07:90:7e:30:7c:a1:c5:0d:c3:04:39:aa:97:b5:30:6f:
- d9:e9:dd:78:d4:f9:49:01:69:93:da:e9:30:2e:ce:5b:89:cd:
- 5b:c7:48:31:69:bc:06:9a:6a:cc:02:2f:bd:5b:78:b4:c4:ad:
- 8b:ef
------BEGIN X509 CRL-----
-MIIB3TCCAUYCAQEwDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTQg
-Y1JMSXNzdWVyFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoIHEMIHBMB8G
-A1UdIwQYMBaAFAXfnBZqLlmBtXbGePU5C9v+hVpjMAoGA1UdFAQDAgEBMIGRBgNV
-HRwBAf8EgYYwgYOgfqB8pHoweDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3Qg
-Q2VydGlmaWNhdGVzMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTQgY1JMSXNzdWVy
-MSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwgZm9yIGluZGlyZWN0Q1JMIENBNIQB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCPfqche45wANMjqNfVzoc0ROCt4on2fp1bKrevV7+V
-v15r+RxAd4fq67GtDOFVgpPwu/blTDNp5UHByW6utJg4oB444SCE2S2fLweQfjB8
-ocUNwwQ5qpe1MG/Z6d141PlJAWmT2ukwLs5bic1bx0gxabwGmmrMAi+9W3i0xK2L
-7w==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30EE.pem
new file mode 100644
index 0000000000..8a24f94274
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest30EE.pem
@@ -0,0 +1,66 @@
+Bag Attributes
+ localKeyID: 26 4C 20 BC 2B EA 8F A8 43 6D AD 2E BB 94 60 45 BD C7 20 AA
+ friendlyName: Valid cRLIssuer Test30 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid cRLIssuer EE Certificate Test30
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA4
+-----BEGIN CERTIFICATE-----
+MIIEgDCCA2igAwIBAgIBAjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0E0MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNV
+BAMTJVZhbGlkIGNSTElzc3VlciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzAwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSzooJ7m4luutdu9QJQDkbY0Il8noU
+TgbKk5RKvCLiBOKpw2OWhUQC6REPPxCUPPlt6Nesrr7HJrAMI6V7ri6BadHXO/3J
+lReya5BgAqkPlHPIUzRgf+GLV4noXkhZu7n1HuC3WIrKLlQ7DxDfOaMtCmM2uXhs
+Htou/zroTG7ed7I6git8dmcYlJb7GwerHzJWXkCN+tdamuzpP/lQjFNAkSpBUkNY
+B3NDRSppsaf3xnwKDw8IHGoprM8Jc1X4bi6Gj1RJ/kPcJZ+Wzfv7xsPvZ06Y/TE+
+vFrs3KAXFYM+F+4Mcxl0cZe97w7kU0YUXJyrG4p1dyx7y1XoMyQkc1hxAgMBAAGj
+ggFdMIIBWTAfBgNVHSMEGDAWgBQMWjLqlAEgC6iqL8kS4y5BAoLotzAdBgNVHQ4E
+FgQUpLFFtgmq4YtGXlXl0x18qEhkLMswDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATCB7QYDVR0fBIHlMIHiMIHfoIGEoIGBpH8wfTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNV
+BAsTGWluZGlyZWN0Q1JMIENBNCBjUkxJc3N1ZXIxKTAnBgNVBAMTIGluZGlyZWN0
+IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E0olakVDBSMQswCQYDVQQGEwJVUzEfMB0G
+A1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UECxMZaW5kaXJlY3RD
+UkwgQ0E0IGNSTElzc3VlcjANBgkqhkiG9w0BAQsFAAOCAQEAPkueBBT1p9JCkPfO
+5YxsM3b6bqPQ6dK4hBSqdX6+lgAkey0kGUH5kp0wyK+g7GO8GHrk+2N0S9mjSFEK
+bxdMuxho41sZp0+A12ZAw68Pwqgg0XtqY2MOSMsPOpwJSq6Fv/DC/uJVFRaD2moa
+avWgugALr2dbJ7jIsZhPmA68101nXSegz4qBeT+AZi5m4jiT75GR/qnbJV0aFDYU
+062FzWBAvrB3a7WT/0/vw8+eYmFeXi8cPouGvUttL/GHGDcVazALLK9GpRAx/2+g
+dtkvLdq5Je3HxRdIJVH8TiTZM8EHdlJ/3cDlN0qNMog9PN5q184xi2nrFzunFdhB
+4nPQoQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 26 4C 20 BC 2B EA 8F A8 43 6D AD 2E BB 94 60 45 BD C7 20 AA
+ friendlyName: Valid cRLIssuer Test30 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FE5270AE65D3B000
+
+kgUcvK3apSU+Wzb/ZnTaqVfuh2oBFN/lKVGl1LJkNNMvZXvACYqYVyriddieT00M
+WGRjmKvN1pFRM4w4WjCwr1aVZSst7AcXTjfobjVPXqoQ84e0kT3hGuqyXXkoNDei
+IgOEwRMQ9gGQpz7OrOaSm3vnRJlkkwLzN6iN3PwkDt7Bd0uVQkIcd7GhZj2nclZw
+JT0rkEn65xPhIik9djCRzWOjfQM956g7PiVUabQOWjts/HeYwkS4l9amBu3WoohD
+tEovDOM3UOg3IuX/bYoTzpOK6WHviDlDP4Qb8yqUcyxO5NUgFgCs3waU4jGn3ykD
++1pf1mmxsY+QhIAdRnnYp/UhZlxk1LDYCgy0YBvJ3U17jhGLQ8iYn6t5TigvjE+c
+I78xd8jf3RxUtzvCGy/ZJz7jeqPmHOUU0sop5VoVZrSBkVQygISMz242PLaptqja
+3Q1UqlmwPCt7xI0+PEoQXs5sjQ1eKJIlM+hWL9RXH4uu3WXECcMJKyesWBQAYW1v
+qbES8bSPAi86Po970FdbAFwgUBJGkE/U1k0bYEuZ4VIef/pxwHAzfde7zAzlUJrb
+Cm/beSNh3lFVRCj2NTpb7YToXQr90zLB9kyJGTleUzd6sX7CBlkGVrw+nje0jKxw
+IeDSEtR18FEOfzY3bKbv2aj3h9amAB9/hYEeE9I9Q5LxKFyw8b+pB75kUi0kuwx4
+u+tW/PjELoshJujhOZtXFveqenV5PYxPyE6KP88Zst/5QHWOuG1+FlTLEQy9a7Oi
+D4vq/65n9sgaH/L9miy+CpubfXXrAawvFNQJ/QDymjAp0FDsU/PxlaE0dzsAQmcH
+HV/gJEVK0EWJ85Myt/L6mdJszeOCoM0vttA8wxejia6joIs0kMX/AccEzgC1tSDu
+F6WJ6sTV0FNi6p/b7I01phRRDUY44TFa5qeiB18ZmWf5JYT3QpFcZ6Dd60OIA/+m
+Z80QDdMHZbBlMux/ZLQygD9q58QRc0uv2vP+6HXZLyEUbv9NNkz1v46hIoixT75H
+iuqOscTdsyfR9xbe7szTrDLSnjq6iN3lHL5bEtdCsBDg6GDcqt6V9iG1uE5zdzNG
+bJo+8Lvm8TBn47No6gdFyn3+DHAdrrb2HgcmxRUxGsOBScdZr6bXNkZe4iz+OvHw
+hCzAD0XCp38a2xiR2dWj8ZnyT8/TEwgOvuKLSXuY0BHZyGSJo9OCwzV+F6jgzjnE
+I9CG7O6E9vGJ54N3LPUmAEB9uHixGwuLjRTlzjyapIcHlKeW/srr/ICVnUi8c5yB
+qbU6uo+fkBEicaJC7foK3vGLye9T6qAc9S8vmOE2CTi9SeLCoSBLTaeYFURuKzSx
+EJ+c8PXcjLKkAYBgHDNKvdJf/tx/hfU2ZZIRPktvwSr/blqgyreIvdExdmCFyEwZ
+jHrrDc73mg/V+kVWbDOJmG7VG/XigY1XmyWFJG2E9eGzyhTsh0AINEGJRg84O8fM
+lGEDLJZSXAkT+LhAMF9RqK0znrnCbTH07mlf8BTDJgPlWCZVqTVqe6mRyEsAfXgX
+DEIejVs3Z9uE3uoLBSQbmBFc7G8g8BluxzeHtLgRtpXRz3FY6Z6Sl7bixHLVk+2Q
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33.pem
deleted file mode 100644
index a1d4ca6ebd..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33.pem
+++ /dev/null
@@ -1,226 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=indirectCRL CA5
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UECxMPaW5kaXJlY3RD
-UkwgQ0E1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx678FWV/yNhQZJRyI
-iaMmsrcrL1oSrYNu6oCM7kFCgk9PSYQRh+4SVNGyvyuQQ74+C4MLKd+GgMPRtHok
-km0S1dv/hLd6qZcVzhL+XHQ+ufLEbZqs1ZXSUfqTJFJpAgu4qLqMS8iZxijRGaDM
-6cQdbVcLMhxTC6sYFzuYtl78gwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUlK0S0eEOfsO7N0tBPW1ZgD9EV20wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALAhR+3HUAbz9RiSD7M2UTI/CO2tE7dn
-6zSaQvkfm/UVsDvNLmSaeXS/29C8sHeoEVpmDdGbgCPcMwB3lTNt2pKI5jhr9f7J
-7BE1W43gZMR2YFRrkMX8AhQKVRN5LVpQIKjGMm8CkTPH9ecvH8kGwYcB3qLZwD3H
-sN+wLRApTQTr
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=indirectCRL CA6
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICdTCCAd6gAwIBAgIBWTANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEMxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RD
-UkwgQ0E2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5/raWoeX0Fp14qkKY
-Ypdts+gzpB6uEBcK8SpAa5FzydBYcIJajJ7MbWLlH1o1nzd27E2YQQPaVuRvB9vS
-4Tih5plnbOXvkaUVh/iohILhb0Q49JWe4JU2yQsphppmzXgUH7C0Zygn3N/fd8JF
-MUxK0kDYmuerHsZ7DDIJsAOTpQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7K
-J3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUwhs+qhpOwTOKGqpZSQOxZqIc8H0wDgYD
-VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACMudfomzqT284TDQDAaT8SdUGpP0bH0
-ofTP/6WODMD3M2+AYgM5ES2McuNKWBx/iifIy42icqmtiP4EjbwjK5JKPJzSSyIF
-/BL1+/TdNfvGBuDBG7qoVzqALx4QeAdCh9tjM9eZQbwVuIIUiI94VPU3hT1OcJRE
-ZCkFIjgPYCPR
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid cRLIssuer EE Certificate Test33
-issuer=/C=US/O=Test Certificates/CN=indirectCRL CA6
------BEGIN CERTIFICATE-----
-MIIDUTCCArqgAwIBAgIBBzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JM
-IENBNjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UEAxMlVmFsaWQg
-Y1JMSXNzdWVyIEVFIENlcnRpZmljYXRlIFRlc3QzMzCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEA01gBYBQnJrrihQ7wxqFilR6zjimXk5ZbQs9BCX1n/zpBfmwn
-ezaal6qZo9BPsXH+zjp8eicI+kPZSXMUd5JgwwuHYH9+gL7EvKobEJc9WBuhBU5i
-GRSeBq9M0UltbXo5c6hbxl22rmTpqTaehigZ94dujqsPPl5g334rdtPU2IcCAwEA
-AaOCAT0wggE5MB8GA1UdIwQYMBaAFMIbPqoaTsEzihqqWUkDsWaiHPB9MB0GA1Ud
-DgQWBBR8QXrBPNUgzCMGCs9z7zs4nferRzAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0g
-BBAwDjAMBgpghkgBZQMCATABMIHNBgNVHR8EgcUwgcIwgb+gdKBypHAwbjELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9p
-bmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJl
-Y3RDUkwgQ0E2okekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0
-aWZpY2F0ZXMxGDAWBgNVBAsTD2luZGlyZWN0Q1JMIENBNTANBgkqhkiG9w0BAQUF
-AAOBgQCTqqePZ3xWbeWlGEO5gbYfjxlqTrTOYOFZoSMlApx3fDkAo2o89IvoGN9N
-hXQDCVtd7MS5g1v2bCGF9TjVKgPMGIJSFGp0QIRRsNdsxRi631JxUFvVz7yE3RgI
-Qjll0EqM4nEceTJaNz6SnQhSjdcOJspkqKXUA1ga7Za2rC8SSA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=indirectCRL CA5
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:94:AD:12:D1:E1:0E:7E:C3:BB:37:4B:41:3D:6D:59:80:3F:44:57:6D
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0..Y...R...N.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA6.p0n1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51)0'..U... indirect CRL for indirectCRL CA7.h0f1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA51!0...U....CRL1 for indirectCRL CA5...
-Revoked Certificates:
- Serial Number: 01
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA7
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 07
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 08
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA6
- Serial Number: 09
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0A
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- 2.5.29.29: critical
- 0G.E0C1.0...U....US1.0...U.
-..Test Certificates1.0...U....indirectCRL CA5
- Serial Number: 0B
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 05:49:47:a1:74:fb:1b:35:e7:63:c3:18:3f:ff:34:5b:ba:1c:
- d3:05:5c:a5:3f:2e:d1:1b:fe:d9:91:8b:25:a9:b1:e2:42:9c:
- f0:f9:98:c2:ae:94:da:1e:da:b8:38:51:6b:42:c1:6e:c5:9e:
- 44:bc:3a:b4:36:57:f8:56:a1:ae:4c:04:ca:b6:67:2e:da:ce:
- 51:b3:17:b7:9e:1d:12:af:54:9d:37:88:d2:58:9f:c1:a6:53:
- 79:c8:aa:90:45:b2:ff:61:63:e9:5e:2c:7b:4c:6e:a8:71:ab:
- 7b:10:11:aa:c4:bd:45:ce:9a:09:d5:f7:ac:0d:83:7c:62:3c:
- c7:af
------BEGIN X509 CRL-----
-MIIFfDCCBOUCAQEwDQYJKoZIhvcNAQEFBQAwQzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUX
-DTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowggLKMCACAQEXDTAxMDQxOTE0
-NTcyMFowDDAKBgNVHRUEAwoBATB1AgECFw0wMTA0MTkxNDU3MjBaMGEwCgYDVR0V
-BAMKAQEwUwYDVR0dAQH/BEkwR6RFMEMxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEYMBYGA1UEAxMPaW5kaXJlY3RDUkwgQ0E2MCACAQMX
-DTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBATAgAgEEFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwdQIBBRcNMDEwNDE5MTQ1NzIwWjBhMAoGA1UdFQQDCgEB
-MFMGA1UdHQEB/wRJMEekRTBDMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBD
-ZXJ0aWZpY2F0ZXMxGDAWBgNVBAMTD2luZGlyZWN0Q1JMIENBNzAgAgEGFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBxcNMDEwNDE5MTQ1NzIwWjAMMAoG
-A1UdFQQDCgEBMHUCAQgXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUEAwoBATBTBgNV
-HR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlm
-aWNhdGVzMRgwFgYDVQQDEw9pbmRpcmVjdENSTCBDQTYwIAIBCRcNMDEwNDE5MTQ1
-NzIwWjAMMAoGA1UdFQQDCgEBMHUCAQoXDTAxMDQxOTE0NTcyMFowYTAKBgNVHRUE
-AwoBATBTBgNVHR0BAf8ESTBHpEUwQzELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRl
-c3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUwIAIBCxcN
-MDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIIBnjCCAZowHwYDVR0jBBgwFoAU
-lK0S0eEOfsO7N0tBPW1ZgD9EV20wCgYDVR0UBAMCAQEwggFpBgNVHRwBAf8EggFd
-MIIBWaCCAVKgggFOpHAwbjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2Vy
-dGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGlu
-ZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E2pHAwbjELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgwFgYDVQQLEw9pbmRpcmVjdENS
-TCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E3
-pGgwZjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRgw
-FgYDVQQLEw9pbmRpcmVjdENSTCBDQTUxITAfBgNVBAMTGENSTDEgZm9yIGluZGly
-ZWN0Q1JMIENBNYQB/zANBgkqhkiG9w0BAQUFAAOBgQAFSUehdPsbNedjwxg//zRb
-uhzTBVylPy7RG/7ZkYslqbHiQpzw+ZjCrpTaHtq4OFFrQsFuxZ5EvDq0Nlf4VqGu
-TATKtmcu2s5Rsxe3nh0Sr1SdN4jSWJ/BplN5yKqQRbL/YWPpXix7TG6ocat7EBGq
-xL1FzpoJ1fesDYN8YjzHrw==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33EE.pem
new file mode 100644
index 0000000000..830d206e9e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidcRLIssuerTest33EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 0F 7D A1 ED F6 2D E3 B1 55 23 86 96 A5 E3 C4 CF 05 60 F9 7C
+ friendlyName: Valid cRLIssuer Test33 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid cRLIssuer EE Certificate Test33
+issuer=/C=US/O=Test Certificates 2011/CN=indirectCRL CA6
+-----BEGIN CERTIFICATE-----
+MIIEajCCA1KgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJl
+Y3RDUkwgQ0E2MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNV
+BAMTJVZhbGlkIGNSTElzc3VlciBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9GPPNteHIdTdRRszbD/h/b+eGaWAD
+NrTjWgzTuZeXV6/D6sW9I+f6S0jcJGSvRB6kcM50+BnXqVV9fnuMgULlmpRAaGqw
+B6NqjlySxkrbuMQPOoHqp426I42grxN4OPf+qzujMMjMGAVImdnDt9MYfM2j1Sr8
+opCYbZFI5R9HXN4pmTCPkp5fox3Vp/ATCoXNtE6tux4iLzlEi+oyK0LjWYWvUHJ9
+cAAqbtzZEN5d0y41a+DFQSkckfCdR/M4lmLG2vzomt5Sft1KyYYL8OA7zxBJVcqx
+H0DcEW0kUPgcaxrBCHNyDuHMvGqe4sl4lOaXamQN5rzzgkFxmGTxeeUrAgMBAAGj
+ggFHMIIBQzAfBgNVHSMEGDAWgBQfySCNC6NsLXdPE95C9Au23ip2MTAdBgNVHQ4E
+FgQUluhzy9F5Af6JjyGhLMUYmAjLgycwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATCB1wYDVR0fBIHPMIHMMIHJoHmgd6R1MHMxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRgwFgYDVQQL
+Ew9pbmRpcmVjdENSTCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5k
+aXJlY3RDUkwgQ0E2okykSjBIMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBD
+ZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJlY3RDUkwgQ0E1MA0GCSqG
+SIb3DQEBCwUAA4IBAQB+9q8Ik0Z2KfZHsQDFdbZDL+EZUxMrzEj59fHD0X2KsHml
+8ZEj2YOEvnsGi5Y29B4NzVSqEnIJ7JHh9oWrCguHtLhw/x6VEy9ghE4Uhw8F36it
+KqCn9a8Djhxrj0riagy9ww/QRFV50rXuV0TuhiVBR1/A9869dx3onqOZiaVljzgr
+dk+Cxtze9rcyMrmaGvgboLlpPF9/s9JLFNc6FH3tH5PY6xGcEGfWtQeEedhJCWz8
+WPRL+kUf0aT5qX0PD7PHT9UDMzP0338QgAjI5rsjhPScQs7oSRSbKV1jkgdRMLoM
+TsUpUhQRYx5XVz36f7j9x94IWsz5PfkBqD2vH+AX
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0F 7D A1 ED F6 2D E3 B1 55 23 86 96 A5 E3 C4 CF 05 60 F9 7C
+ friendlyName: Valid cRLIssuer Test33 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1CB3D75D493E7769
+
+WBhqGT+RJWLGu+ESdchE6u4yA2jPGhK2rK94zXxv2OK3ZgzRdjKJszQmWS6WHXUW
+T2BnHRp2oD2JUl6uNuUeIl+NteuHCaBVjCHJiY/zd03YbiS13x9q0TwnGJzD3YjR
+C5+zw+NJiTLikVY5etDNibaf56NykaHownrqQu+LlIfLu3yL5bY1x8nkEeWnL/cY
+zBAYa64S+Vh7Wd6Q5dXEMtbpUYmAfHFG1XkjiaBL3FDtMnJOLRRBtq7z9Td3CGxe
+Za2lTFhHFRHw6KbgDmvYz6lDnP/mdP4cNIw8jMaaB3tRUPaoAoHxYr8lY9RdxQt9
+wT4AxDkCC7KAiea+im2BhX5LhdrOCoWjcTrBNJRTp7mypXwezE3Uw4/uzD/bi5CN
+UcSJ+RwWIYfLNvJid6QkmKDg81cvEP2MlxHnL9nVycO0Wx/E7eDlnpgSq6CDdTx5
+3hvUSbTvapTXN2CM6KQlbu7hbvvfkEI+hXUpQ2lpkigJQCyR4uMRsqwuoDsKgKZJ
+92s2/0KATnCrmeUIOBR7JF3H9cvJf5Rxtr6QYi9IagyYl2HhWMzYgD93RViqJ2yw
+vkDG5I1SDvusQEO6dca6FaCb24UzJKFgu+zk7+ma8cmZaYMmZs/9FZzHAQ+PgrtU
+iXDqJqen+5mWyozancFuc6wJBxksI2vmHx/1BI3Uh6i+J7iQPXvPQ/p4Ti1IS4nW
+bm3uxohjMf7KdptHVjjr7KZxDyV+i4hmyke2Sl/oCnFfSdUo44VafBJRJmEHB9W0
+ECLt8s1D96d7uDU8ib917rM4YscmH1uB+i0K+cEVpAL6/HyABQmzSVGjFRjeyTxC
+KZ/5a/dlw9Tpgh1Hp0vDWOFFS/r2zpbPqmADOxSBle7QShRGvSFz83a1/vEs1Y40
+GNl34T/0cVGyupqpFxwTkxJCamUF2A/yqDfCNJJUeLHTMljJrMPo+YaJQhBzGMuA
+EA+jxzenFkyAjo3H5DJ/6gvYch0xHv4xp/OMEeJh2T0dv4kQN0Ia9uKgZXySgMID
++Kp//xLgxUSNt62LYJSmmoQ1i8w//1y7wX/0RfgQVKZhE0lSmZukqvndOWh/Z+tj
+HorxR6YWCLvBIaME5VDMjO+GnRULTjkzC5AHqe4oR8bBhwmD1/JqfNaGp9WEd6YM
+PSzwftuf3/WF5wwhDusTPr76sItEAOuA1fBcu3zSVYCLrFyS1XBrBdnl9Vj2rNIM
+vyXF7BvX4mALaLL64L2W4YXqmw/GG8RqKyQudQXET3hDDFqIEqIA7Yx2I3mA3LDu
+EtcSEoL4II9rx91Z9+30gnexGhNbJR6sajtOEYdMGSIpNaPifhsVk5b3OP9+E6xg
+RAKU9nyb5Ta79rg4FEyk4Mj1bYNFHWacbD9NRlhHRbKkEatoLahUjSufSwrVoioK
+d00ywK6abby9YLHyBzr4wEkJhDk5Gs4VTcrD5jK8MX+WVGqfVvgKjwlbPd2D0Mgs
+Zo9maIWsYEpnm1H9kblXfdvDBbw6TfUs32vwX+7assnr0ytiUlayZWmVGxL2QOlp
+vSTqZtfArBsdQuPSOYBQO9TV20G8f1qQ9CvpR21MbSIAs2Uir4aIlg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2.pem
deleted file mode 100644
index abd16aaee7..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2.pem
+++ /dev/null
@@ -1,190 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBWzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWAdMOZhkDHEp9KBGE+XuF
-msopQ2J+rJDtUrJ4pDANd3KgvUwmAZnDOopO+3hIw/w6tsB48EJwMCiofofFALAT
-zbGJidQOgpLF2if/SwmyWzUKqB8XirB9z5z0NLfE/0nnUhVQnAJ54W1jOz/+wMfg
-7oWdQC0ZAd1ndBLf+mtqHwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUk49NvPIc1wyuIEisujIaDdfoDc0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJhiiwAX8BQouosN8thaL0+ZHNhiuQ2gr8Mi
-xgaJCB4DVxE5teLk0eeWz+KVJBQwDdrlK4l0BO595r8cldkYkKJkJl+ZGPbNSDys
-XuVwXGbgfcUNPCeD1UIErQASVfomr3io69Nc62HwaBpTgARQO0wvfnIOFNAQSZH9
-247eEnnm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid deltaCRL EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA1
------BEGIN CERTIFICATE-----
-MIIDJjCCAo+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEsMCoGA1UEAxMjVmFsaWQgZGVs
-dGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBANRKVxWvFldCkmzvNTs41NjJct7Jt2VltlefYPwBuwPuHZveA3TbXj88
-nvKICCqBLZwlhGlAyfZTqFd4gElplVEKvfn/GSNyGGnsAHfZJOqwzyvpIPx/yg61
-ALFj1gsGSesibsgaXOhUVO0N6EVpse2azO8I7qSpXf6f6b+qpSkLAgMBAAGjggEX
-MIIBEzAfBgNVHSMEGDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAdBgNVHQ4EFgQU
-zo7j3tkIY9+L33KkkCzx7XzdaOcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
-DAYKYIZIAWUDAgEwATBTBgNVHR8ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBD
-QTEwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwgQ0ExMA0GCSqGSIb3
-DQEBBQUAA4GBABBiIdpyc6pIhhnujMn4FXCBcoJtkC5Am8NB/cgPKyhVlUTnp62b
-dbt1zoUI9KJPSlwBuJduPL/Q9hJr1vKHdcFC98iANtf3s7fzzhGF22Nel/qKtlWr
-fldw2WVkIjTSeQV9gmBf3cHAV31JP5/q1rMljeZD448J9Cd46UR05jM2
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 2
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Signature Algorithm: sha1WithRSAEncryption
- 63:e6:6b:e9:cf:44:29:c8:8b:e5:8c:ba:ab:26:57:a5:4f:a8:
- b6:e3:81:35:ff:73:8b:40:e0:79:7a:d7:69:8a:c5:a3:d9:85:
- 29:ff:ef:e4:7a:4b:f5:36:51:34:79:9a:85:01:cb:ac:03:48:
- 9e:2d:b7:b6:9e:82:57:b1:0a:b7:49:06:a8:cb:c3:71:2c:71:
- 58:7d:e1:68:22:6a:11:3d:e6:ac:2a:58:d8:1d:97:3b:46:98:
- d0:f5:f2:85:85:7f:b5:c7:57:a4:0e:e4:fc:c8:cd:7e:b0:2c:
- 1d:2d:86:30:1b:06:70:36:33:e0:69:47:60:98:5b:f5:93:35:
- 90:7a
------BEGIN X509 CRL-----
-MIIB1DCCAT0CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAz
-MDEwMTEyMDAwMFoXDTExMDQxOTE0NTcyMFowgYgwIAIBAxcNMDEwNDE5MTQ1NzIw
-WjAMMAoGA1UdFQQDCgEBMCACAQQXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoB
-CDAgAgEFFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEIoD4wPDAfBgNVHSMEGDAWgBSTj0288hzXDK4g
-SKy6MhoN1+gNzTAKBgNVHRQEAwIBAjANBgNVHRsBAf8EAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBj5mvpz0QpyIvljLqrJlelT6i244E1/3OLQOB5etdpisWj2YUp/+/k
-ekv1NlE0eZqFAcusA0ieLbe2noJXsQq3SQaoy8NxLHFYfeFoImoRPeasKljYHZc7
-RpjQ9fKFhX+1x1ekDuT8yM1+sCwdLYYwGwZwNjPgaUdgmFv1kzWQeg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 48:32:1b:da:3a:c2:71:37:ea:24:5a:90:2f:19:b8:9e:00:96:
- b3:e1:2a:6d:ed:b5:7b:eb:90:30:ac:87:c0:8a:6d:ca:24:f4:
- 73:dd:bd:b7:f8:cc:55:31:f3:d9:e2:a2:5c:7c:51:60:6d:a0:
- db:43:12:52:9c:94:fa:10:86:32:e6:a6:7e:ce:e6:c1:00:2e:
- fe:33:22:b3:5f:66:e9:d3:03:de:05:c4:94:bd:09:2b:1d:2e:
- 06:86:e8:26:f5:f4:38:39:62:7e:e8:0e:bb:cd:c8:bb:82:92:
- 71:96:8a:01:73:d7:ef:fa:a5:c2:94:53:e9:2c:34:a7:50:7d:
- eb:4e
------BEGIN X509 CRL-----
-MIIB+TCCAWICAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwIAIBBBcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEG
-MCACAQUXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBBqCBhTCBgjAfBgNVHSME
-GDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAKBgNVHRQEAwIBATBTBgNVHS4ETDBK
-MEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEASDIb
-2jrCcTfqJFqQLxm4ngCWs+Eqbe21e+uQMKyHwIptyiT0c929t/jMVTHz2eKiXHxR
-YG2g20MSUpyU+hCGMuamfs7mwQAu/jMis19m6dMD3gXElL0JKx0uBoboJvX0ODli
-fugOu83Iu4KScZaKAXPX7/qlwpRT6Sw0p1B9604=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2EE.pem
new file mode 100644
index 0000000000..6d14a5b19d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest2EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: F6 29 DB 96 07 D3 3A 5E E1 03 C0 AC 2B 81 C4 CD 0D E2 6B E8
+ friendlyName: Valid deltaCRL Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid deltaCRL EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLDAqBgNVBAMT
+I1ZhbGlkIGRlbHRhQ1JMIEVFIENlcnRpZmljYXRlIFRlc3QyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwd1BQ7/wKjBDcP9D5j5bCNy9FutJREznSiHS
+P1ZWdbmMUNZgzwgmA9oXqX9wqbQmq/KdQj1UNao69Ih3TDu6pIhWs9tZFDXQJ5Aw
+QBTS8rxdxcTzvcWYh61gG35ZS+obi85nDBtcMH6uJ3CVzLOe1S/cneeaIlvME1dR
+qEYUizVvc827K/POXYD89i+Cv56PTvkngHaX4s9acF2Nfu+wI8mgt0VCuCt+/FUq
+9WkUEzWFwWZ9l9wtYPijG+8mD5RK8UKhVYAnLLXHh1vY6a2g7fNg0nVE2yFMGMQi
+VWK+Goj0oPwfQbbWhdyLwEdoqbilnNVdVvorTqUYNDYVL2feQQIDAQABo4IBITCC
+AR0wHwYDVR0jBBgwFoAUdxgj5XaEyBSUP4LQgep0seCkLzMwHQYDVR0OBBYEFPof
+pRoOE0DZ7urfHC/l3cmHSCQLMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
+CmCGSAFlAwIBMAEwWAYDVR0fBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8w
+HQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNS
+TCBDQTEwWAYDVR0uBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+ExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEw
+DQYJKoZIhvcNAQELBQADggEBAKPvo7tsUNQ5bI0XnuZU+EZuqi0EXzLAT1ybFYVQ
+dR8uDdi9l+HdRsKioPOoQF2wzjQ5WvvfVMQ0032aXqQ2mKZP5n3NaMYon5l4ZMZD
+tmFSBsNpKmVL5TfQNhujuuiAg3/iTviwTK3tApgdUhEioZomFv8GT1P/W4DnDpjU
+Khns6ZZS1SwE+UP5ckJBFN75J3ptYyUrialBjCitoou5dH7hUmpKL6/jwr/zTmXm
+QT+jNsNg2OaKe9BZUuE3T3vMS/ecQPkgUvosTeqVbg3Q3g53Kq9noiPrDOF0RKrp
+JHoYsWHK1AkMy0o3uYUifeVdRcYxXQvaScLwwzsp/bv6FxM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F6 29 DB 96 07 D3 3A 5E E1 03 C0 AC 2B 81 C4 CD 0D E2 6B E8
+ friendlyName: Valid deltaCRL Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EE2887BC9A995025
+
+1HjPKjN/H2UbwdN8notTrNk82KvHmYTDztz6me+cZo1iMW2K/W8go5Y8xgtQ38Nh
+Jwj+xw/+lgAjUQ8kuk5PoW+KUnbCwBS9rbQyBXZPwSlApxalnCd2cLxWYBdzHT1g
+4x45pkNw86CYpxwGijOEX+Ml6M1FY2y/X3KG27GCAOH9YW7BPvAt8zTg29cq1+Qc
+O42FSJK+06qeGrV5ElvQKK4iCi/UiGFsAHpREfiDLdD+Z/YZMa9ERPYp0eTLr/A4
+AXCSv1tABz9hJg6QT/q0FtOK0ub0498V5L/ZIYSbHxZ1Y/3ACqHQNeV5kua/80DO
+YnYyhouoiXEHAFJW0BSClK1WgNQM9Uoccvag38iM+KrymnlhQH8eJnG5rM3QI2yg
+Cm6IKuyP2fFx1Kd0qCMiaoEwkh+zWysq1yITFJhvS4NMiW3QVC17jzS5zq9Cht3D
+lQChON5wDh5fxAyb/nnfrV3T4ZbI1uz9hmJwEhoCMUp1qAUZYhQfDrBsRLA5OPdq
+8xnNx/1ol2MUlhp3bN1FpsgA9WjY/5rCD9RyXGctm/k0uz3or/C7SGZHy12e3EPa
+/2pBth17y1S2dxyoTQjN37ulolA1PIixkKgEhHqqflt1d6H+7w6g3897XzApsvi5
+QfOxS9dd2mEfoycfCIkvk/A/ovkWbV8USHFvZT3tkzVyxG58RdBsbPspWXnS52Up
+EJci07kVoihq/wQAY8j8Cd2xJ8NYuH4fL5RUGJPHBMBIQwQ/W1h6HrXvhnFbDNnk
+/6OAJfnVnHKVEyHw+wG0McybPM1KWk00BSFkRbwxMQdwunACjUEmC3Mzdktrffpc
+o3moOY6aTNF3que/YZD9B7yWhu1bhmO3t3cRw04To9dMUSdO+RLqp5vS907B0fpa
+d5J/qNafSjdWTnkzBAQzMX9yHXMuAUIgPKqM+DFyZ98JBIyDjrmhccc2Lnvy00XH
+baC6d6FoGtwaGwzEeKIEJVV0UBEBxXA+V5JML7cqFsm2Fr+6sTmpTzoOb/1SnORL
+1t0tdMSEAkOGT8DTD3LvF3jaIuxdQttwWx3h7bJpH0UD4Lkc8CUUmO8MwskOvy1y
+sgU2FEFTh9WEeQhu6AftdL7PBCHIdlbDU+p2GLOidIq/UcODVLi6+uIXyJheAnNZ
+63xyQXRYF/t9JgbkNv8pMBU5VZ36jjzweHp9cXcZEi5Kr7Wrjh5luKQJhiRHyh7P
+b8nBzJmZt+Rvkn0JJmgnO+03RFgWla6tySMQwgciHpewjVOjv8UnbNs4cvhdZE0Q
+5e/swhuc7mMHOeAiui77eyzFclBeRVKzJ01gr8c+lpHNSGb9oDDL+1hVZ6ITfE6U
+wTE+PijTDNOSaAvYfS5LFc42zIxhssj4pbSaETN0G7ANSSbBLnxb5NDmNMzoj0zL
+s2Q/mRSOcnlkagZz2C9LEr6Rf68ZhGJk6PLESfUlJJXazsm2Er7JntlIi2orEpVq
+IBZB322iKfErIg1w9M/N+Iq5OUAe/xF30U+I/WXT8NBjajYD1Pasf2gr27Q1uk8p
+Zgp2+3EGgb/AS4g5tqzVY3vMmYcKjTMv+kMq5I8ssjibMZS6d4Bp2huXpx1VJ8SM
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5.pem
deleted file mode 100644
index 57390f882d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5.pem
+++ /dev/null
@@ -1,190 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBWzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWAdMOZhkDHEp9KBGE+XuF
-msopQ2J+rJDtUrJ4pDANd3KgvUwmAZnDOopO+3hIw/w6tsB48EJwMCiofofFALAT
-zbGJidQOgpLF2if/SwmyWzUKqB8XirB9z5z0NLfE/0nnUhVQnAJ54W1jOz/+wMfg
-7oWdQC0ZAd1ndBLf+mtqHwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUk49NvPIc1wyuIEisujIaDdfoDc0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJhiiwAX8BQouosN8thaL0+ZHNhiuQ2gr8Mi
-xgaJCB4DVxE5teLk0eeWz+KVJBQwDdrlK4l0BO595r8cldkYkKJkJl+ZGPbNSDys
-XuVwXGbgfcUNPCeD1UIErQASVfomr3io69Nc62HwaBpTgARQO0wvfnIOFNAQSZH9
-247eEnnm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid deltaCRL EE Certificate Test5
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA1
------BEGIN CERTIFICATE-----
-MIIDJjCCAo+gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEsMCoGA1UEAxMjVmFsaWQgZGVs
-dGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDUwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBALJoiZyA4CHBqHesCHEPO2Me3gceR6LJTUtoEOGP877OjigufADkFCsN
-m6lEz1zn0JfUOvERm70QxsfYSjpbc3OiPi8v/hbsB0whYBVGe017Qluvyf6ZV2v/
-ItpeUd3v3rw3g3Z+pXGAgLTeDBl6RhbybuoORo2hbpq1hPkhrep7AgMBAAGjggEX
-MIIBEzAfBgNVHSMEGDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAdBgNVHQ4EFgQU
-FouAPbKkYNJGEKJU0p5tKX2BhpEwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
-DAYKYIZIAWUDAgEwATBTBgNVHR8ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBD
-QTEwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwgQ0ExMA0GCSqGSIb3
-DQEBBQUAA4GBAGu61lJXt+1uZ8FoGyPdKeHvT8YKDijsbNtC8azjbqKRIz7ETsfQ
-9nax423fRWHnphLHzSUdbuIdBvWL8aDN0T9ZvNt4A+73SndqlIw7y3ULlw+r+CRs
-UBmBJJSEvo8Bh+4OJCjGoZXDzdGbQ+7TYzZn+asNvDVZE5MN8o8Tcq8r
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 2
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Signature Algorithm: sha1WithRSAEncryption
- 63:e6:6b:e9:cf:44:29:c8:8b:e5:8c:ba:ab:26:57:a5:4f:a8:
- b6:e3:81:35:ff:73:8b:40:e0:79:7a:d7:69:8a:c5:a3:d9:85:
- 29:ff:ef:e4:7a:4b:f5:36:51:34:79:9a:85:01:cb:ac:03:48:
- 9e:2d:b7:b6:9e:82:57:b1:0a:b7:49:06:a8:cb:c3:71:2c:71:
- 58:7d:e1:68:22:6a:11:3d:e6:ac:2a:58:d8:1d:97:3b:46:98:
- d0:f5:f2:85:85:7f:b5:c7:57:a4:0e:e4:fc:c8:cd:7e:b0:2c:
- 1d:2d:86:30:1b:06:70:36:33:e0:69:47:60:98:5b:f5:93:35:
- 90:7a
------BEGIN X509 CRL-----
-MIIB1DCCAT0CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAz
-MDEwMTEyMDAwMFoXDTExMDQxOTE0NTcyMFowgYgwIAIBAxcNMDEwNDE5MTQ1NzIw
-WjAMMAoGA1UdFQQDCgEBMCACAQQXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoB
-CDAgAgEFFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEIoD4wPDAfBgNVHSMEGDAWgBSTj0288hzXDK4g
-SKy6MhoN1+gNzTAKBgNVHRQEAwIBAjANBgNVHRsBAf8EAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBj5mvpz0QpyIvljLqrJlelT6i244E1/3OLQOB5etdpisWj2YUp/+/k
-ekv1NlE0eZqFAcusA0ieLbe2noJXsQq3SQaoy8NxLHFYfeFoImoRPeasKljYHZc7
-RpjQ9fKFhX+1x1ekDuT8yM1+sCwdLYYwGwZwNjPgaUdgmFv1kzWQeg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 48:32:1b:da:3a:c2:71:37:ea:24:5a:90:2f:19:b8:9e:00:96:
- b3:e1:2a:6d:ed:b5:7b:eb:90:30:ac:87:c0:8a:6d:ca:24:f4:
- 73:dd:bd:b7:f8:cc:55:31:f3:d9:e2:a2:5c:7c:51:60:6d:a0:
- db:43:12:52:9c:94:fa:10:86:32:e6:a6:7e:ce:e6:c1:00:2e:
- fe:33:22:b3:5f:66:e9:d3:03:de:05:c4:94:bd:09:2b:1d:2e:
- 06:86:e8:26:f5:f4:38:39:62:7e:e8:0e:bb:cd:c8:bb:82:92:
- 71:96:8a:01:73:d7:ef:fa:a5:c2:94:53:e9:2c:34:a7:50:7d:
- eb:4e
------BEGIN X509 CRL-----
-MIIB+TCCAWICAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwIAIBBBcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEG
-MCACAQUXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBBqCBhTCBgjAfBgNVHSME
-GDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAKBgNVHRQEAwIBATBTBgNVHS4ETDBK
-MEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEASDIb
-2jrCcTfqJFqQLxm4ngCWs+Eqbe21e+uQMKyHwIptyiT0c929t/jMVTHz2eKiXHxR
-YG2g20MSUpyU+hCGMuamfs7mwQAu/jMis19m6dMD3gXElL0JKx0uBoboJvX0ODli
-fugOu83Iu4KScZaKAXPX7/qlwpRT6Sw0p1B9604=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5EE.pem
new file mode 100644
index 0000000000..b20e3975c4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest5EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 93 22 59 7C 8F 4E E0 09 A4 B6 5F 3A 9A 85 15 F6 8A B5 FD 2B
+ friendlyName: Valid deltaCRL Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid deltaCRL EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBBDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLDAqBgNVBAMT
+I1ZhbGlkIGRlbHRhQ1JMIEVFIENlcnRpZmljYXRlIFRlc3Q1MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqJFECVVjrL4M7nLTi4W1pAi2nrpcoUfvyqYD
+PRN8qfpzIE2sdD8F+TFkPACLkiLO/ZxHg/SMlLxViLS14Psx2wsNVz8FKD3B2M4l
+7BqdRL9kb5n7AWYajmT1iBJhbiFqr6j+4wPljpRifp6mEF+Y66kqvcVOJZYo9mxK
+wtFfQ8Bfq80QXqADKzs14Zcr2WMwI6e+qxvvIEBoG9AiAXwcEaQQZaNuxBMAEWYj
+J4QKZb1ThRQvwHR+OF2WDQnFJU/igyo6r7JlC6Oole3TDeXAL+HLLc7PrAFYuKAC
+Q5V9uIAuBVsk9ZqTv3hxWlwM8UcIniTbCdaJzMk9PUnSLiIWDwIDAQABo4IBITCC
+AR0wHwYDVR0jBBgwFoAUdxgj5XaEyBSUP4LQgep0seCkLzMwHQYDVR0OBBYEFEll
++YhvWUeTjLvr+5XokIkUWsJaMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
+CmCGSAFlAwIBMAEwWAYDVR0fBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8w
+HQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNS
+TCBDQTEwWAYDVR0uBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+ExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEw
+DQYJKoZIhvcNAQELBQADggEBAHzp3LR2KfAWREjO8RVbzdP43ggy2Qi7oYZ3NsTp
+99KuQ4Z5agn0v97GgFfCq1Aym/dcoilxYT9BWD7QofsVUdHF5uUhVZ6oW63CR+rM
+6YC8WYneCzZc8MZl09I00mJCeMqWhRpQcaLGKhTLeJ5B580BSd+w+VkjiqHZr7SW
+Nft16xyOsw/jzMZQZ/bsjDcb+M/O2Gy4xUqpxp+sJNHeeY7N+/FX3OG8Z53IML3J
+SfD2Y+NUZ6UOMsTq4c7TxMFFUSmBrpg7xkiAWJl5HIwsX5dtFK33AxAbxOkXbmfC
+ESxVMsWyt1eXn/ndaiwAqyq5GXfcVyXCJJHcvdYjl8jGFrM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 93 22 59 7C 8F 4E E0 09 A4 B6 5F 3A 9A 85 15 F6 8A B5 FD 2B
+ friendlyName: Valid deltaCRL Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,517C8F7B45662A8C
+
+QdbF4c6aeSXFoCFctsIsul7/4O7/znzpz6XNcnLnqZqbKPsdiWjNhtriapJyUPs6
+1VYXFHi3y1G9ySFZ1FWIbWoFkp62As8EaE7D/o3xQMBRGC3OQpAntZWdUfLmIQBI
+ImhKFY3dhJ9pmKKQ6lbfyXb2LhURTLhEeyqyhpNllppMS5Mv/iF3s/CP0BsUENwe
+5mBc1GQVhH0UC72fbIhsP741UidXoPLQKDNWQ3G5sX9X37YlmwkvzAFqFupUsZrq
+JKRYNxx1izYCzmlhWGf+3jlxtfhR0N+ULl/1RxE+cpLelPlUn82G+ct7i0mXyW8L
+nBLqEHq3IhbKa+baEJMbWM/vrQCwnJYux4NWtdTCdjqyHFcpnOSkosM3VJSi1N5A
+LePDEUhKHMfZigarxyuKLTYyVj/V4EmD3IOWbqxNOX1KUw4sb60aPEjxiPMG11q3
+x4VgIyC1v9l+oGeJflAiY/7hVoOtuyfDXO7Af6an688S/O6m7gkQ+eOs2PQSVTCl
+Nw5+eAAbaUjt53Fpy0WSS7sWQjnAHIaL0tGYwxI5wkmvorsilGWE8SJ7UXT0uUkx
+s9Oh+QVcj5oLeVexyui7ican+0Ok/mXmtMh6svET671aAmzef9VTW2yvGEsG2A0A
+c4//cd8jnfYBVkl/kdzPyGZLkbzWgMs+Ynjbco7eoO9lSX3wj2YIlPe3FRMbPRLg
+Ue69MiIKWZdiqcdYmQGO7/mqZUg5EUcFM+c93COl4tqyjaCNO7jqAsdhr8oa35H/
+Giml77rH86J/dUFL6Aw+5u7RCJQM0nKPHN6AgIedZZbw7Qgjph01S8h22Ot9DeR+
+ZSVDSi/xPfneJu7SbcUvhifdRYi1ytbMsl0saBKCesHRt0OtimqZHbazD5bKjJR+
+ceNVT6vR1E24LMvtiFLARt2c94XpzJ9iWsmHoXZ4bimPAFlAvVSKccYa9mTXjYvK
+ognt/cXnIpekOHbLt8XPRcxl/lUDT6UUtPAph0tn4/G3CkcJvGq1iAZ5TUbyzvTZ
+pE5GwCsLrFpDd5phc8yMzbQVcuFbeTyRUA3tupMJHXE5UjNtm26Fob2R3tvbZBju
+N41tv1AHl3QZSctjWM9kivZbYliZyNTuBwEQEJiL37XIsxCuDHUUGEKsAOQRPOio
+uLui6tML/ydeKYHJfj4bV/3RWbeuIEHxS24qNV3a2Qcfax+rGQZzdk5v2ijLcGzB
+U1biH5fP6A/JnYpyP0/eeqRnJE3HqP1ntRAcHWgWAiqoRD45zYm/efDr1w46N8ZO
+XN7b3R+zmpDv66spLC417jmT4E5//azPcAs5dknlxALTpSSTY5DqtEXM42nyRn0+
+LzehGCrj7NUeZkSo+FUB1bbD4UjW5jFCsLGcC2y7vo79r5uH/AV1vgGG8ugF6Iip
+dN0r4hM2EtOVMDaN1RuP3+iyslbE46T//gICRLFm2plG3nGko8BgYpGnUsNCB3b2
+pgMnkkWjpYpxpCs0SAos08KXr/LbaZcR4RwuhMK3hWHboHPPZGd1+tapzSrxNIOe
+SA25jedrzE6hDdLfJJUDH/+CmgS3X/Sc7B1hq0bngdxuNqw2XZnbRPNnYBlQ9OLl
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7.pem
deleted file mode 100644
index 9b046d77ae..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7.pem
+++ /dev/null
@@ -1,190 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA1
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBWzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0ExMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWAdMOZhkDHEp9KBGE+XuF
-msopQ2J+rJDtUrJ4pDANd3KgvUwmAZnDOopO+3hIw/w6tsB48EJwMCiofofFALAT
-zbGJidQOgpLF2if/SwmyWzUKqB8XirB9z5z0NLfE/0nnUhVQnAJ54W1jOz/+wMfg
-7oWdQC0ZAd1ndBLf+mtqHwIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUk49NvPIc1wyuIEisujIaDdfoDc0wDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAJhiiwAX8BQouosN8thaL0+ZHNhiuQ2gr8Mi
-xgaJCB4DVxE5teLk0eeWz+KVJBQwDdrlK4l0BO595r8cldkYkKJkJl+ZGPbNSDys
-XuVwXGbgfcUNPCeD1UIErQASVfomr3io69Nc62HwaBpTgARQO0wvfnIOFNAQSZH9
-247eEnnm
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid deltaCRL EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA1
------BEGIN CERTIFICATE-----
-MIIDJjCCAo+gAwIBAgIBBjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEsMCoGA1UEAxMjVmFsaWQgZGVs
-dGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDcwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBALU8oom56GYl7ggs8WAyhZeZmMxxsN6Ikht0t6Iydxic3xNbotaUS0iz
-H0tYBYwzuCTMpM8RMBSrU4UlqIE/9V5PuY2dWiHDXVGRawMdE3i4UNzrMS0BlYDz
-zvAw77ifKwmObOm8R1CWg2VCY9xzFWqER3YRDKQTcK5LzjtxP6PZAgMBAAGjggEX
-MIIBEzAfBgNVHSMEGDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAdBgNVHQ4EFgQU
-unt4uPVRHtIAndMWGuDH66dedOcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
-DAYKYIZIAWUDAgEwATBTBgNVHR8ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBD
-QTEwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwgQ0ExMA0GCSqGSIb3
-DQEBBQUAA4GBAFwV555uqsNA+ZtS8QnVH+RRp5jhYTymacP8yc7G87Hyue8xaNzA
-yj4g3Rxfthlo52FFH0ZiuOKJP4YSvX4jr/BqZyrO5eMNs+ln4gMHn+RVxBdeh4xT
-LgXbQGX8wnks92CCGWUW1vbXUSbpBW43SaT767qDIo7yTASQVQ4jtWHJ
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 2
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 06
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Remove From CRL
- Signature Algorithm: sha1WithRSAEncryption
- 63:e6:6b:e9:cf:44:29:c8:8b:e5:8c:ba:ab:26:57:a5:4f:a8:
- b6:e3:81:35:ff:73:8b:40:e0:79:7a:d7:69:8a:c5:a3:d9:85:
- 29:ff:ef:e4:7a:4b:f5:36:51:34:79:9a:85:01:cb:ac:03:48:
- 9e:2d:b7:b6:9e:82:57:b1:0a:b7:49:06:a8:cb:c3:71:2c:71:
- 58:7d:e1:68:22:6a:11:3d:e6:ac:2a:58:d8:1d:97:3b:46:98:
- d0:f5:f2:85:85:7f:b5:c7:57:a4:0e:e4:fc:c8:cd:7e:b0:2c:
- 1d:2d:86:30:1b:06:70:36:33:e0:69:47:60:98:5b:f5:93:35:
- 90:7a
------BEGIN X509 CRL-----
-MIIB1DCCAT0CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAz
-MDEwMTEyMDAwMFoXDTExMDQxOTE0NTcyMFowgYgwIAIBAxcNMDEwNDE5MTQ1NzIw
-WjAMMAoGA1UdFQQDCgEBMCACAQQXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoB
-CDAgAgEFFw0wMTA0MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQEwIAIBBhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEIoD4wPDAfBgNVHSMEGDAWgBSTj0288hzXDK4g
-SKy6MhoN1+gNzTAKBgNVHRQEAwIBAjANBgNVHRsBAf8EAwIBATANBgkqhkiG9w0B
-AQUFAAOBgQBj5mvpz0QpyIvljLqrJlelT6i244E1/3OLQOB5etdpisWj2YUp/+/k
-ekv1NlE0eZqFAcusA0ieLbe2noJXsQq3SQaoy8NxLHFYfeFoImoRPeasKljYHZc7
-RpjQ9fKFhX+1x1ekDuT8yM1+sCwdLYYwGwZwNjPgaUdgmFv1kzWQeg==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:93:8F:4D:BC:F2:1C:D7:0C:AE:20:48:AC:BA:32:1A:0D:D7:E8:0D:CD
-
- X509v3 CRL Number:
- 1
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 04
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Serial Number: 05
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Certificate Hold
- Signature Algorithm: sha1WithRSAEncryption
- 48:32:1b:da:3a:c2:71:37:ea:24:5a:90:2f:19:b8:9e:00:96:
- b3:e1:2a:6d:ed:b5:7b:eb:90:30:ac:87:c0:8a:6d:ca:24:f4:
- 73:dd:bd:b7:f8:cc:55:31:f3:d9:e2:a2:5c:7c:51:60:6d:a0:
- db:43:12:52:9c:94:fa:10:86:32:e6:a6:7e:ce:e6:c1:00:2e:
- fe:33:22:b3:5f:66:e9:d3:03:de:05:c4:94:bd:09:2b:1d:2e:
- 06:86:e8:26:f5:f4:38:39:62:7e:e8:0e:bb:cd:c8:bb:82:92:
- 71:96:8a:01:73:d7:ef:fa:a5:c2:94:53:e9:2c:34:a7:50:7d:
- eb:4e
------BEGIN X509 CRL-----
-MIIB+TCCAWICAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowZjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQEwIAIBBBcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEG
-MCACAQUXDTAxMDQxOTE0NTcyMFowDDAKBgNVHRUEAwoBBqCBhTCBgjAfBgNVHSME
-GDAWgBSTj0288hzXDK4gSKy6MhoN1+gNzTAKBgNVHRQEAwIBATBTBgNVHS4ETDBK
-MEigRqBEpEIwQDELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNh
-dGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEwDQYJKoZIhvcNAQEFBQADgYEASDIb
-2jrCcTfqJFqQLxm4ngCWs+Eqbe21e+uQMKyHwIptyiT0c929t/jMVTHz2eKiXHxR
-YG2g20MSUpyU+hCGMuamfs7mwQAu/jMis19m6dMD3gXElL0JKx0uBoboJvX0ODli
-fugOu83Iu4KScZaKAXPX7/qlwpRT6Sw0p1B9604=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7EE.pem
new file mode 100644
index 0000000000..3d0d5a7c95
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest7EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: E1 24 61 D4 80 26 C6 06 DB E3 20 10 B4 4E 3D C1 4C A6 CC 7F
+ friendlyName: Valid deltaCRL Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid deltaCRL EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBBjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLDAqBgNVBAMT
+I1ZhbGlkIGRlbHRhQ1JMIEVFIENlcnRpZmljYXRlIFRlc3Q3MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzciKUI1wBFK9EwAbsgpdXjusVk7/1h6YVvqN
++ZUJbsgq/3yxRU4jeSZDcZjMXJPXsrR1hLXn1yRpVo6S9ZobQuaefENp/RiASNOf
+YBYATNAGQmWFZEX9QCogEJpWeb2dFF32sCRzYwNy3DQaBFeDcTEXVzsdvXyfS3YA
+hXdQi5gefeuZjX/7OKl9pRBdaVntD+uE/wAo2Ez8aHIFpPtaqQWocHVZBX9zvFFI
+9V6hrZWECE6ncTeZnE5zEhRsgvEQH9yP/aS/B2VsQ9lp/vLgmUJNlGM+GJGVHt2c
+3GuwDOnGf2X37P3MhtVikr3n5Kdesz6/uifl/hEUTUYuVWJNQQIDAQABo4IBITCC
+AR0wHwYDVR0jBBgwFoAUdxgj5XaEyBSUP4LQgep0seCkLzMwHQYDVR0OBBYEFOW2
+9kwsl3yikB+EDuhYr3oLXkCRMA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
+CmCGSAFlAwIBMAEwWAYDVR0fBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8w
+HQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNS
+TCBDQTEwWAYDVR0uBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+ExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTEw
+DQYJKoZIhvcNAQELBQADggEBAAs0oXbA8TuPF+tMxNXgkOguLJikBkt/frKilUTA
+9DmJ+F/9vjHr72Q9bpjsqKp/KHwJKctL7wYuPsAkXBEMBAXVyKksD85/1Eka6YU3
+puJJeA+Bq0bsDESrJJL8XEXD3VuOLMbOq4Ot7DA6PH7P2F6VkfYrKXJEtabhBkVV
+0KWRI5aCR94pPJKoz2up29fJawUKLXdceIVKN9rWj2+mMv2aEV8f2WX2gbNyqZUE
+35RVGyExTLdt3AIeJ0W9RvxccyIkAk3T5rdeofjhjgyI7Y9/WMBT94BhBQv3SAXN
+3hmax5SnAGqm4/Fh6jl1LZcG5Ldln7tj2DMzewoSysPbTiA=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E1 24 61 D4 80 26 C6 06 DB E3 20 10 B4 4E 3D C1 4C A6 CC 7F
+ friendlyName: Valid deltaCRL Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DEA4934DBEE6AE93
+
+fdN9TkpMM8GT1odOJXa8TnsKePIaitXGooKLqmvKooIQ84BcTzK1jnOKea5XoqGT
+MlnNHtbl8fO3/S6n0vwUQp3+4EfKw7eWvNVpv+i/L+I3ibWlOvq5YF6ke9b2JQHK
+tVpKguGDiyqVZN8nzN5TUQgz/35tSkuMnkZa9AKqIfHjq91r2ZNtk/GX3st+k1GQ
+IJLsQpjDIToC1QVdZDFzbvRxZLVezs0+jyXgedXagiCyUoKfRAVSmcP8PPibIFrH
+3QPE1D2KmLKcJbcSAR/qJ27ajGEyNjDpUJo6xDUFiKRDYgyxD5Ect26UNI5BIxa/
+/wIcxSDMB2GS5Q6rMkWQXbhjE11/s0C6kE9FDbonrA414PdQkrHCHBj1WtyrOhFt
+1taJPjc3BU0aurMQXFpFaN5NOJciQMu8JK7zR/AeCTkXAFLNyZjZac+qfk8OY+5t
+XoSH5uuhhwZBqPPjOtWh4KqHtjitAUbZ+FLJIENFQhINQiECpSIzABc+4R7tZDDv
+m+mKj6VMo4ZxSGs0ViUNm716dqJqP2bpPi4gF7Y/Ivb6c0tuPtbY2e889WlgxHbK
+2fEXPPW/DX+cFH+gHTCSLFLR06fTENm4pDJ4K6ClEhnQP4qV//udB2PQ1PKyUZ2B
+aC8T9HgvqOszDQbDQ1DQ7HgBlwKd0Y8qqjSQWrr16dsEzbTilH9odqjsOQCpdE4o
+jk9g8O2F+85LsmrBmPn+tuBmIwnbs+M/F19wYoZpLrT9Nh0ux8c8RQvvyIOZ1cPt
+HhfTBeMEmmz/ItkWtGlcAoaMh0Bmq6X+c9n/ZF49LKEztGEhcKpdQu8R0YoFX6yb
+PNqJFXBpWOj5vJrRA2/PVcobtJE55KyOExwDKbS1b188tKJNSJwZbqRG/2ZkX5NK
+z6j+OdQkdoLkq0z0FxATy3tEjlRsqNWHC3352yg6aG8ejvtvucnnf7eSrflPSt2C
+ADYY2uw1NLJjlv8T3xqJk15erT/lRu6ycCBHi8/Pi0Uo2KAoMuh1LIQYD01ZP+nS
+3Sgl15GSwb32Ldmb2ZOkq87/zgIT9/K+Dlb3LGN4v0yzJCb6dZCqPeK0zv0QBPsa
+6VrAVOB+mSszbuDXcT9Fjt7OCT+Pq4Pk4OjVs4tCaY42dfZTBHhBw6dUHmJ/aZ1i
+axmzijm+c32uxxVdt2p7kqt64qdZ58AqgCAGzglyMcIGIQzWo6uAoir8kG2/6clh
+YYPT+5J6VSPC5UdXcSvH15SLaWDfLX7/KMetUbof1KW+/CrPM+L8CNNqdpCinVJs
+iVEY8isQPIIM6WuCANSIyvV7XkjHVqxgohmcmjuDJMdPFm8ftEcZTjCfvy1kF/yQ
+JNz+XsLDjmyRGBQ1bcIQWZR7eLXeNPERe5pPAOpLbWM1IZefGZS1PiuBAOIxK9yP
+AfsbvvVf4kKYy+Ea1XUZfMwLdOeqmAgW1WyP7oB9zlQPT5thQKyMm3Tut+ad8OqK
+cXtMRhi+U827gs/lSbwluA+2pv9dacA5vebmiaku8b5fnOpzo0AH6CcQZGvWMW9x
+kv/jqMId9ppUYu5gzs31/prBo6R9dZ7pdHQrk1XT7tyklkjklXIYHg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8.pem
deleted file mode 100644
index 2db6c9c39f..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8.pem
+++ /dev/null
@@ -1,162 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=deltaCRL CA2
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICcjCCAdugAwIBAgIBXDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwg
-Q0EyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCr2MUpxzH8HIqzmAylEvng
-qJvVIxI4xzM8NSpC7P7T2R1dmFXK/19W+m5yqOagB9VxgxP9IYbI2VJ/FrbQSD/+
-afpuHA8++piSAs2e/1BoRagiln3PnQTLemPsmVy00eSLnsw6QRdC0MIZjme0/SHv
-Z6XuWPNvicDyA/Uml2pCqQIDAQABo3wwejAfBgNVHSMEGDAWgBT7bNQtgZ7KJ3qe
-DbA86pq8h/9J6jAdBgNVHQ4EFgQUo5OrV2YmbXI6bLyDZaOa/I4MQwswDgYDVR0P
-AQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBBQUAA4GBAFnKbCQCHJI6HhnaoKJkHKk3dBK/E1DNHc3a
-u9yx3wYdmqwkoG5iKJjssQDLcbLfpjuF7jU9nKbk2gcmOIa5//lgCmUaok4WZSUA
-u8bzMnpiZyzIjjoW78RyuntCMXbZzcs7umsOKfOlDXj4wwsev4E7m5nvP2Qv7hEX
-ECR/9DaG
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid deltaCRL EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=deltaCRL CA2
------BEGIN CERTIFICATE-----
-MIIDJjCCAo+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENB
-MjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEsMCoGA1UEAxMjVmFsaWQgZGVs
-dGFDUkwgRUUgQ2VydGlmaWNhdGUgVGVzdDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
-MIGJAoGBANNXQWv/s3VtlajbHeAAaJZ+taow3YYnDMLz9tXUqMSOOKnoHR59ec/A
-1XsEc02zK6rj6cC8db6LqebYOUJ1kpBl3t2oEH25mVFiBhgdYiLGeezrLNiAm2vF
-dBdoOCER9Y5PshspgHG45kPR88sRxRuN+NtvOBQ+rS3ZagNzOydDAgMBAAGjggEX
-MIIBEzAfBgNVHSMEGDAWgBSjk6tXZiZtcjpsvINlo5r8jgxDCzAdBgNVHQ4EFgQU
-rDZIHgyRpXqIY0zNvpsz15jbVrcwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4w
-DAYKYIZIAWUDAgEwATBTBgNVHR8ETDBKMEigRqBEpEIwQDELMAkGA1UEBhMCVVMx
-GjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBD
-QTIwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFU
-ZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFDUkwgQ0EyMA0GCSqGSIb3
-DQEBBQUAA4GBACi9fCMcVs6WjeEeE35GgRLIbCVWQ1PbtOFwwJiaM7f/c4i1F3Kt
-A2BcHex6T21Ea9eSra37uvPdAUSc0Dc3klZS96pU6v0oZtXl07daAhbR8mKRmoPq
-tVcto5YqOd/STL2egFKzNVhfR5UZo1wycobU3FZtmFyr9DFIEKb/mFt0
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA2
- Last Update: Jan 1 12:00:00 2003 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A3:93:AB:57:66:26:6D:72:3A:6C:BC:83:65:A3:9A:FC:8E:0C:43:0B
-
- X509v3 CRL Number:
- 3
- X509v3 Delta CRL Indicator: critical
- 1
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 25:e0:e6:a0:65:11:f0:81:2b:f1:ed:47:8c:1c:a4:dd:79:26:
- 78:05:22:84:96:35:60:de:7b:13:ec:70:ee:50:3d:ac:d4:9a:
- 22:fe:e3:9a:77:a4:fb:bb:86:98:21:80:3e:d3:20:85:57:b2:
- 0f:2e:bd:53:d4:7a:ac:96:02:3e:17:00:67:67:6d:16:01:9d:
- 93:cb:fc:b6:f1:c2:23:0b:e2:de:c2:02:5a:70:05:34:35:8a:
- 72:8c:cb:78:ad:62:96:86:50:5d:6c:ba:1a:bb:e5:b8:e8:5f:
- b6:7c:33:8f:8b:aa:c6:b1:78:a7:e4:56:12:76:09:7a:db:ae:
- f5:ff
------BEGIN X509 CRL-----
-MIIBbDCB1gIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDGRlbHRhQ1JMIENBMhcNMDMw
-MTAxMTIwMDAwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAQIXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaA+MDwwHwYDVR0jBBgwFoAUo5OrV2YmbXI6bLyDZaOa/I4M
-QwswCgYDVR0UBAMCAQMwDQYDVR0bAQH/BAMCAQEwDQYJKoZIhvcNAQEFBQADgYEA
-JeDmoGUR8IEr8e1HjByk3XkmeAUihJY1YN57E+xw7lA9rNSaIv7jmnek+7uGmCGA
-PtMghVeyDy69U9R6rJYCPhcAZ2dtFgGdk8v8tvHCIwvi3sICWnAFNDWKcozLeK1i
-loZQXWy6GrvluOhftnwzj4uqxrF4p+RWEnYJetuu9f8=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=deltaCRL CA2
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:A3:93:AB:57:66:26:6D:72:3A:6C:BC:83:65:A3:9A:FC:8E:0C:43:0B
-
- X509v3 CRL Number:
- 2
- 2.5.29.46:
-..Test Certificates1.0...U....deltaCRL CA2
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 6a:af:6c:a0:70:12:90:02:5b:70:fd:d4:b6:8d:28:9a:51:5c:
- fd:04:ed:47:e1:a0:5a:60:e7:41:83:23:ff:a3:e0:c6:b1:fc:
- 71:db:cb:8e:a7:20:0e:f6:9a:ae:e3:fd:61:33:a6:21:69:4f:
- 7f:7f:23:cc:33:47:45:23:bc:fc:a1:79:02:31:3f:8d:77:e7:
- c0:9c:8d:90:ef:6a:9d:38:fe:13:b7:03:dd:ac:36:72:b5:94:
- e5:7b:43:a8:7a:96:ce:16:bc:55:00:bd:cc:1b:a7:81:93:40:
- f7:f6:11:bf:c6:dd:7a:ab:32:e5:be:fb:88:32:e2:06:41:9f:
- 5f:d5
------BEGIN X509 CRL-----
-MIIBtTCCAR4CAQEwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTIXDTAx
-MDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0MTkxNDU3MjBa
-MAwwCgYDVR0VBAMKAQGggYUwgYIwHwYDVR0jBBgwFoAUo5OrV2YmbXI6bLyDZaOa
-/I4MQwswCgYDVR0UBAMCAQIwUwYDVR0uBEwwSjBIoEagRKRCMEAxCzAJBgNVBAYT
-AlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEVMBMGA1UEAxMMZGVsdGFD
-UkwgQ0EyMA0GCSqGSIb3DQEBBQUAA4GBAGqvbKBwEpACW3D91LaNKJpRXP0E7Ufh
-oFpg50GDI/+j4Max/HHby46nIA72mq7j/WEzpiFpT39/I8wzR0UjvPyheQIxP413
-58CcjZDvap04/hO3A92sNnK1lOV7Q6h6ls4WvFUAvcwbp4GTQPf2Eb/G3XqrMuW+
-+4gy4gZBn1/V
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8EE.pem
new file mode 100644
index 0000000000..a16e256c7f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddeltaCRLTest8EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 04 A5 97 42 73 3F 37 86 6D 23 09 D9 09 F6 C8 C8 E6 14 A2 57
+ friendlyName: Valid deltaCRL Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid deltaCRL EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=deltaCRL CA2
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFD
+UkwgQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLDAqBgNVBAMT
+I1ZhbGlkIGRlbHRhQ1JMIEVFIENlcnRpZmljYXRlIFRlc3Q4MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8cN2sWESGC6fNXCLygPwdhQv9FHYDd+cFpxm
+kheAY2g4ijWFyF6OUiiGE3pgKsWnK6ggR/TGGJywRZGNHHSXxQXFE2yb9K0H9SqV
+UTMAcnj+Bfn/EwTh/TH6MZ1qK521o2sHnLclVwMmsPcXOlvStj146Qy4bJeYxfrx
+4+ElWzjxrFdYq2Bl8Dg3ttC3VN2qHBt/cgJSOYSFV0NRq9AWahuBvaZLabpwThpd
+GdgYYJoS8xbTc1CbQ2Ae3SnzPzRoDgDIa3qq/dvsvid14x19l5iikXutlOc+vP83
+h030hWFY22BcV0KpJ6JPl1G66jE8bqr1OJpiCsMaIUqS6vk2MwIDAQABo4IBITCC
+AR0wHwYDVR0jBBgwFoAUfNj2vgNMzs+3P6EZuzOrtdeN+8QwHQYDVR0OBBYEFDVt
+isYS30aB8pp8CZs3el96Hk63MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwG
+CmCGSAFlAwIBMAEwWAYDVR0fBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8w
+HQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNS
+TCBDQTIwWAYDVR0uBFEwTzBNoEugSaRHMEUxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+ExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQDEwxkZWx0YUNSTCBDQTIw
+DQYJKoZIhvcNAQELBQADggEBAHWaKCfflZoi95Z/yp1yP6w4LEJL3H529WDI2UvD
+1Fm2gkj/+VcJhv3e8jAIppl99nAv96wQSyZ+fK3MyC0z0imcgBGWDuG2R9y8CBD0
+/eEoDNuR/ohHoZep5g6tFTdyCEOiOTfw2KlQUHC5QDrGueQYSe+paIUB3U2mi0Zx
+3wKur48JUckLnnqZM5ZsuGbGJq0jndUEPsbRIEkUTD8wPSrlmGa3FZw3/Tv/o6QJ
+Dn3TRvjVTCGiCqDhvlaB3hdhOl9cxqOgC9Q8JHitr17FUcFUnZdZ8BoiyQE5/ASK
+Pu7QbuDtqRlByongR9EinSmc8KZpZOXA2WZmweq6H2sM8JE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 04 A5 97 42 73 3F 37 86 6D 23 09 D9 09 F6 C8 C8 E6 14 A2 57
+ friendlyName: Valid deltaCRL Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C9E871E8056A9637
+
+TQBadg+aGhsk4Qn8qCDGGGWmW3z/Xfon1sWhWu/6mKFUmZt7ohtSIM0MIEOZ/Y8b
+8+y4xLYoMR4sj36VErleauBNy3dheara0dmqNeNLY7JdpTQKUBe2Sy/sR5r7bAEX
+qPVng+1RDHDyGHDgdY9wX42pwspeS3Cm5QL2mejc4lVGf59YK/zM8bD99PN4sbK6
+IugUVz14UvkTEghrW8c3jryUlcBRx6lbMyzUCHSQEQ2EJ1e9XdDSNvLiNAv0Fgao
+rvnlL0/9S8JHUie+W9hS33lhABf3/bjCQqBbH6PmH8lGoyRtA6J3/bA39I7pIlfA
+XeGgxbMIzrNRQDFMTcSCRJKbFoVLPLgn0uD/ugMAaWgAfuAJs6gPjc6tHe5fu1WK
+sw8xH3yO1p+I4jPeMmBLB1hUHJMo593iQSTRNKcovBHumP6G4aLHd7rNSiucUj7M
+C/RuTFMNP1xkU1o7eqbLFFAf5EjLPKH0LOiORMYKQfRALz+zhzKI72x1Wv6sFofQ
+RYea7MAsMua/4YIjzGOZ1DeYFkKEopb5kLS0/s5tFLRx9joOzl5MGm0MlIn3cNCu
+5iEc/bPGgA9Sx7Ch1T4x8EabbrNWTbpI3Ru58homQKAUJ/BZWtItEqDq1TuMPgQy
+gAQ7pEcKRHRE2sHGtLkJGmcH67ZIk8ArowMPhQHxslCsnqPEqXu45SwleJi0NIzC
+ceIr4jIhooCVXPtIUSdkdVKtM7/SJ2L1za3/sOB02FCqHRwj+hlTZ6cEg3hWd1Gr
+uJnyhriNrNyMhQY52kTJaPtLNW+3jT26yXIrUWAcsDNVCEHDBMqPzpKNQPVfazMw
+4w+o7e1M2znPICq5r8nbQMT4YLLG2K1JaZmdq7zqLRK2BWo5WQot9Vm0kOlPXTbD
+JTO2V3t3cCqErF2A5gcKj+DuOi/YJN7E2vqZrrw5xFJLZZuiqrVp/gZUWvL9qYMg
+xrGRNta1J/mpiksaosJ71vqnwC4OCpr/dFUkA3WVV+UxaoA0Zt2YIri8wRQPBCoy
+35HZg8rCynP7sckhFLHAqQI96x9djGmFFPzWWol62BVnLAWZ+904Soxs5UTPbQmh
+egm03rYTfU5Zp6ktLb3NdPeixu30i/sBzDG5CvNuchEfHI600kUV7lfzPacBtWZJ
+25C5TpbB1SxBX5tYR/H5kv8M+1dWV+GXOQ68yF20rYNydzzfrd0vYnRzZ+EhDPCK
+2YhzajyVjYeAUdJAJIhaIHAUabHCedlVkWEkDSdm1OzUSvMr9OqyLcEWwHnjYt26
+JXI+GWG0Q/mVJIeyBzbniEzFWVyYqDRYqTiYkKj10BpPF8CBwD7H5jzFlVUu8HpG
+lgLkXUY5iGfhPl3ufNBHhp6NUj4AugJ8X+lBZWFFqdCQ18QL6wPeNfGAhr48oWvz
+97EgBFZaihhesw2eSIUdzXcqZPMfRPt52kBt3J+/TLEE0z/CUpxSpyEDJs9olhSY
+7hoss5HAWV8jbmSwjHMxdEOX6hY5hGk3MnUH5vYKRAfrj8Sh+UAf1B4O5RY2h/tw
+wzoDhzpaggqOExQx3mTzQZKfP5oh4fBpsa9tzoFJ5oa6769qRrV3070BXl4izs57
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1.pem
deleted file mode 100644
index 4d1155f29e..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1.pem
+++ /dev/null
@@ -1,123 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoVIDlX8Ue
-jptTAccp199par4Wi+6zdvpzdmUXj6UICGge/S5OJUY6nmBMligfESDLwjhbFB9V
-wm194odW9eAiWfUenAN7i4xIyorZwf5dPqHZVOcv9M3jRBce9j/ZuO8ard6c8Dp+
-UQ7gGH0Avyz4IM9x52TNBjYLthRcxwRPywIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnh8dUFdqhW8b+OZBXut6ujB+
-uvQwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMM6gfNW7Hs8z/E7U5NW/M1Y
-eT2VxqvZaq+HqK/GnxQeJUalPUbLk66F3XU5QmU/gQ/F6wP5yEV8UZALVj7OuJ56
-Vz21USzCSPGXPazeDdBQSx0otXHbKVtamBKYMn+jFqYPuPmNxUWzu4iczvEsBZFK
-0dm+b6846EQQbmI8jNru
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid distributionPoint EE Certificate Test1
-issuer=/C=US/O=Test Certificates/OU=distributionPoint1 CA
------BEGIN CERTIFICATE-----
-MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGAxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE1MDMGA1UEAxMs
-VmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNhdGUgVGVzdDEwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAN6guztNoD71JstXwHeM6i0zxnyPdZOx
-ZTcQsR+TD2lCqIvhOECxI8GdbfxgHJlvh/2nKd7LKSelitE+3fWW/qKMZ/0YuVru
-PaJZ++CaJDZQma26yjruW5AcBQ0L+V9VYKLoFnGDjtlJrHGbvrv4XZByL19ikrKd
-nt241DXaNxsnAgMBAAGjgfMwgfAwHwYDVR0jBBgwFoAUnh8dUFdqhW8b+OZBXut6
-ujB+uvQwHQYDVR0OBBYEFGrgSYUMuxW8YuQDkUuM8pXH+fGIMA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwgYQGA1UdHwR9MHsweaB3oHWk
-czBxMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAc
-BgNVBAsTFWRpc3RyaWJ1dGlvblBvaW50MSBDQTEmMCQGA1UEAxMdQ1JMMSBvZiBk
-aXN0cmlidXRpb25Qb2ludDEgQ0EwDQYJKoZIhvcNAQEFBQADgYEAaNonr89NlCOf
-B4CPoPAy+I/+jv8FamQoB55nhirAu/W5oZunV0iWLyajzQxSVgMpmrKaIC0cgCwx
-i6XUWy7aAkam0kQMmWzHNSrGEAvMjtYU9+jQj3ZO94LFUlSKsN6Ut1dxXNheb7ML
-YFgoWyPNz0rcb+iy6fjoyxr8fpA5H9Q=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9E:1F:1D:50:57:6A:85:6F:1B:F8:E6:41:5E:EB:7A:BA:30:7E:BA:F4
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0y.w.u.s0q1.0...U....US1.0...U.
-..Test Certificates1.0...U....distributionPoint1 CA1&0$..U....CRL1 of distributionPoint1 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- bb:36:57:87:39:3f:49:50:07:42:5f:a4:2b:3e:b2:04:52:a9:
- 1b:dc:5e:8b:c1:6c:47:19:83:1d:5f:81:da:ae:bf:ba:1d:57:
- 8d:a7:f0:41:bf:d1:40:e3:f8:7f:bf:80:ac:8d:2d:97:15:88:
- 6c:91:39:87:3d:0d:45:79:a3:b8:41:a2:17:b6:a3:24:cd:a9:
- 7b:f2:f9:57:b5:98:a0:a7:07:2b:3e:5a:2a:d8:5b:84:7d:25:
- 75:25:51:9f:58:1e:6f:ea:f9:3a:62:59:e6:54:01:d7:76:91:
- 2d:0f:b9:f5:2a:ce:0c:46:e4:dd:b1:3c:23:92:a8:67:d2:39:
- 6a:49
------BEGIN X509 CRL-----
-MIIB8TCCAVoCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGggbgwgbUwHwYDVR0jBBgwFoAUnh8dUFdq
-hW8b+OZBXut6ujB+uvQwCgYDVR0UBAMCAQEwgYUGA1UdHAEB/wR7MHmgd6B1pHMw
-cTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYD
-VQQLExVkaXN0cmlidXRpb25Qb2ludDEgQ0ExJjAkBgNVBAMTHUNSTDEgb2YgZGlz
-dHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEBBQUAA4GBALs2V4c5P0lQB0Jf
-pCs+sgRSqRvcXovBbEcZgx1fgdquv7odV42n8EG/0UDj+H+/gKyNLZcViGyROYc9
-DUV5o7hBohe2oyTNqXvy+Ve1mKCnBys+WirYW4R9JXUlUZ9YHm/q+TpiWeZUAdd2
-kS0PufUqzgxG5N2xPCOSqGfSOWpJ
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1EE.pem
new file mode 100644
index 0000000000..68449061eb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest1EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: D3 79 25 D9 3C 99 E3 68 09 68 E2 8A 42 EF 15 F4 9F DF FA 09
+ friendlyName: Valid distributionPoint Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid distributionPoint EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint1 CA
+-----BEGIN CERTIFICATE-----
+MIIEKTCCAxGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NTAzBgNVBAMTLFZhbGlkIGRpc3RyaWJ1dGlvblBvaW50IEVFIENlcnRpZmljYXRl
+IFRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sPTk1SoTy03
+5AcGZcmP71y5DQKUR59LVALZKFRoNPExjKDu/1iA4xbhQF7sQPExUpOp1hmCn0Ln
+FXCS+Cal+tKFOZ2+jLs2QCWk96czfVQ2fKipq7C5CwZXMYfhiUL+RZ+cXt7KEYdH
+TTfaWbHKIBW+7DCJ/AwEqbRa7b7ozLnrprQXvjbgJTsEbWZCD3oQVHg9r+5sWgwB
+/JhcTyr3+t63ZRMT8TjXqElnu2n9cGesJgy3/KEyBJ7nV50pQQVdbVPHf/QximZd
+wCSnlnMubmC0dqCZFJQcJQhKToarEkdyNNZwaci58pJ0heZ3XDwAGhLLXrUc6MCy
+h59WPhNpkQIDAQABo4H6MIH3MB8GA1UdIwQYMBaAFBEwc72NcCiC0m/P0jftzesj
+kdvvMB0GA1UdDgQWBBSy6JFibzXDGWwqeeIz3gyphnF+vDAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIGLBgNVHR8EgYMwgYAwfqB8oHqk
+eDB2MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEeMBwGA1UECxMVZGlzdHJpYnV0aW9uUG9pbnQxIENBMSYwJAYDVQQDEx1DUkwx
+IG9mIGRpc3RyaWJ1dGlvblBvaW50MSBDQTANBgkqhkiG9w0BAQsFAAOCAQEAN4Nk
+5AglIPqk6oGm0F3kRKsgBJfkUR8Cm97MqjqzUzNHN9nWnQd4yihkGd00gKMVqHqw
+Cs/hm61VlHa+Y6l+cXprG+aKOQlTzircOjv8kzJRTglu72dnSeUtHZEw2Lb06B/0
+4dO/WUQcvyMzB7bQCeUFYA+JGZJbGhq6irtI9aXgfJK6vOQkOp0M8UNohCYJWVnD
+rJ1ve3lDEYm+TP+oOvGJPI6+eLgugaSQs7x+nCu1GGa7Ur1lmzLBkDpBU7/bb4zD
+58x+mEJzcnWFp62PxUnBIOVjxvHOC5hfvhL1pMwb2hJTCUz5Cll+9Ql0cimey6N5
+qyh2uI5l4i8HykXVSQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D3 79 25 D9 3C 99 E3 68 09 68 E2 8A 42 EF 15 F4 9F DF FA 09
+ friendlyName: Valid distributionPoint Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B1814F2B9424DBDE
+
+C7PqZvJSPgKj6ZgWexy/L4+LvKtgmY08HSfMfhnJASIcNGuzYlHeNFx0m33jLU4a
+94hkgZkGwrRyvW8yxEnIxgnEpJAH7bmMY53k5mYRp3yWae84FL1EOjFaWPYQF9T8
+8wqfLCT1Mc4CNSo8/mINq7PRXkRckBL31fMk5vbDDOD0N5/VFySu+r2D6+qIVmBV
+rIl8Pxeox6ZTc423JuBJNOlplcFNNxOVxYkez0kpiAIWQaHHnD/ib0TNRFwCqdqm
+LM2ep6qFhQLxJXdGv+b/uKxYRQneHmUfCICsZsESAI68yuV7gINUSoG5gvuemyVN
+fi2nkG5MhQ5bAu5L8T0VhhRi3E/g1ND7QLkBt8pNIOqfUrYdT7QHZODYe+7MBBQr
+HAZ3whqebuzXsK4r5ZNphZOFOql2pebB/F6EyGExbSZ6bkmjmGqVCSZIfpOgJ0n7
+1xEXo5qOZz6PPyBAszL1vi97t82TQO1aqOcq/rXzA80sjFQopaDhAXeWd/on6O/s
+DDQYz+d+QjgTmFWeUQ+UvvpNXsq1E5WxWqsyiDzNF0ebhCzdyDDxDaYFFy2kUcAO
+Y7StHphBn5KB3ja2xf84R9eV6NN6B3jaoUnZyNTpaSdqSLjxU3Yl363NJ/O+hOgn
+c4iCsEATcq7A2881DSyRr7r8hVxv9rQu9z/D7mz7y8VuRGtABesKVsBU65Zj83aH
+JBKnBthU0FGCC9XTx+IOVATk0gDiFImub6N33KEtzEGBWNKh7Nc1DypjnOI08kBp
+PNw9bWtjRlJ4caBqfB99LLju5KGQa6wJSIzkmhBqrykoJ85RB8UEb49TZxWm8Mim
+Qm/3kZ0aiTTBkWtlZM6zy8/5oHAO8oeqC8SvKrOJ+CE0lWjBAQ0Zyp0uy6TJDeAf
+ea+yjoqvsnXH/DxfUkbTkILZVJP2pKwj38/mYfpatiHyUGDg4v7V6Rxnl1NP4gw0
+Ew6yRe0HeonLkTcEmjqlBsDCqlhU98h/nplTwCcTMWfYnFUVYqGsLDXrJajXL3Nt
+Zi/TbNAWQibB6bCedurPgauHNoRaqvsRnVJZ1DTqFuc+hBL3sWPVweHBjxBbwxs3
+K2GZmE7uL8jHUUoDcvjNrieh0ESfHxDGWwEVKckokQsUKuwdPqgNuCbGeZapce2P
+BSh8dlZkWHvoITUgTwpUU2736xR5iCEcfwTpkLN4eJtFWaTaMBiPNd6/8RKXFAt9
+cs+CK+6O2i4JV3J+hZCT3hqeNAt86lumKlm4sgn2HyecH5Xkg4EuO1Sw6LYUS7El
+XfpT2Jo+vM2hfMp/ebvTsFAOOfoD7V1o4vYfzHcD/rvqnPMyLSnM3sceKZXt70E8
+s2iQ/VxZY8GXrFlXTJa5CRof+CvkWDDjfqlZo48i2amH4qn03Eylapp2ma3MIiuD
+5KhielEG5PBYkOxonpfj8erbLU7unCtNVKFiXT1hDS/o5YDWHJSuCR8A1/7bOzuh
+OYR/DcBGhe6Es7NLWBgIwSYMLTGCv1/sukMqVERVWATgvn3SbuZ2mSxesJjN2/kk
+uvceA1UtkI59duulDW5mIv+zY+0DuYlXTnZCdNR6o4VoVZDQb7vNxzBcDDn02Wzp
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4.pem
deleted file mode 100644
index b910bfa5b8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4.pem
+++ /dev/null
@@ -1,121 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoVIDlX8Ue
-jptTAccp199par4Wi+6zdvpzdmUXj6UICGge/S5OJUY6nmBMligfESDLwjhbFB9V
-wm194odW9eAiWfUenAN7i4xIyorZwf5dPqHZVOcv9M3jRBce9j/ZuO8ard6c8Dp+
-UQ7gGH0Avyz4IM9x52TNBjYLthRcxwRPywIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnh8dUFdqhW8b+OZBXut6ujB+
-uvQwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMM6gfNW7Hs8z/E7U5NW/M1Y
-eT2VxqvZaq+HqK/GnxQeJUalPUbLk66F3XU5QmU/gQ/F6wP5yEV8UZALVj7OuJ56
-Vz21USzCSPGXPazeDdBQSx0otXHbKVtamBKYMn+jFqYPuPmNxUWzu4iczvEsBZFK
-0dm+b6846EQQbmI8jNru
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid distributionPoint EE Certificate Test4
-issuer=/C=US/O=Test Certificates/OU=distributionPoint1 CA
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBBDANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MSBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGAxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE1MDMGA1UEAxMs
-VmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNhdGUgVGVzdDQwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJIkOdZRwN8UTl55iM8yHPn50dQHIq8
-HfyujAk6Jv6J99xOf9TR0MdxFPy0pQ+sqafVe30jTmqUVekQqyzewTZvJ3Q2tRoc
-POnbHancXe29FlXNO2PXHA+L7RPpFglcXQjTQTzccRCzmpv2bRO4oGEICTWg7twt
-MiPAc4q4jZbfAgMBAAGjgaMwgaAwHwYDVR0jBBgwFoAUnh8dUFdqhW8b+OZBXut6
-ujB+uvQwHQYDVR0OBBYEFNbqujjf+uaNLMffRr8p+XZZJNN/MA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwNQYDVR0fBC4wLDAqoCihJjAk
-BgNVBAMTHUNSTDEgb2YgZGlzdHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEB
-BQUAA4GBAKzWCbFK6I9YapazUsu+6hrCf5Eafd14GQqQOhxwUQNvHdD8IxcTeQoX
-7u5YapjezA6GSz14DxHIZQRtE/cAzSIjRJjDvn3rQdrlwdNXRgjFia9Jknth311/
-GXxAPrAwlxOAuTBFplNC9mG9japtT3qz2BkM/q+MdedGRWtS++30
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9E:1F:1D:50:57:6A:85:6F:1B:F8:E6:41:5E:EB:7A:BA:30:7E:BA:F4
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0y.w.u.s0q1.0...U....US1.0...U.
-..Test Certificates1.0...U....distributionPoint1 CA1&0$..U....CRL1 of distributionPoint1 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- bb:36:57:87:39:3f:49:50:07:42:5f:a4:2b:3e:b2:04:52:a9:
- 1b:dc:5e:8b:c1:6c:47:19:83:1d:5f:81:da:ae:bf:ba:1d:57:
- 8d:a7:f0:41:bf:d1:40:e3:f8:7f:bf:80:ac:8d:2d:97:15:88:
- 6c:91:39:87:3d:0d:45:79:a3:b8:41:a2:17:b6:a3:24:cd:a9:
- 7b:f2:f9:57:b5:98:a0:a7:07:2b:3e:5a:2a:d8:5b:84:7d:25:
- 75:25:51:9f:58:1e:6f:ea:f9:3a:62:59:e6:54:01:d7:76:91:
- 2d:0f:b9:f5:2a:ce:0c:46:e4:dd:b1:3c:23:92:a8:67:d2:39:
- 6a:49
------BEGIN X509 CRL-----
-MIIB8TCCAVoCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDEgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGggbgwgbUwHwYDVR0jBBgwFoAUnh8dUFdq
-hW8b+OZBXut6ujB+uvQwCgYDVR0UBAMCAQEwgYUGA1UdHAEB/wR7MHmgd6B1pHMw
-cTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYD
-VQQLExVkaXN0cmlidXRpb25Qb2ludDEgQ0ExJjAkBgNVBAMTHUNSTDEgb2YgZGlz
-dHJpYnV0aW9uUG9pbnQxIENBMA0GCSqGSIb3DQEBBQUAA4GBALs2V4c5P0lQB0Jf
-pCs+sgRSqRvcXovBbEcZgx1fgdquv7odV42n8EG/0UDj+H+/gKyNLZcViGyROYc9
-DUV5o7hBohe2oyTNqXvy+Ve1mKCnBys+WirYW4R9JXUlUZ9YHm/q+TpiWeZUAdd2
-kS0PufUqzgxG5N2xPCOSqGfSOWpJ
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4EE.pem
new file mode 100644
index 0000000000..9c24c93c57
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest4EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 0F 9E 09 91 9F 0F 27 AB AD C8 5D 0D 95 BF 42 64 0F 13 D1 F4
+ friendlyName: Valid distributionPoint Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid distributionPoint EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint1 CA
+-----BEGIN CERTIFICATE-----
+MIID0jCCArqgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NTAzBgNVBAMTLFZhbGlkIGRpc3RyaWJ1dGlvblBvaW50IEVFIENlcnRpZmljYXRl
+IFRlc3Q0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyr8rZVD36q04
+FE0+YBnLiq3ad6FjrlscY2OK0okCydYweqD0c4RT+Pzsx4zOFl+89xzFMN4JRgzz
+W7+vnHR/rjnZMytEjN2k2ogy69ngXOgM3HzQGKCdqki9avl/Nn2vyE8+9pi8GCVj
+TRfEG2HMArmx3PP3QiRjrRmelJxSY/FLlZvTVHj2gAWYAzmBiCeYCl+qR9HxSnss
+JXA/TQb5aNgMb5L339Lk7Y7YT5mxVQ8xKMutTTpVtz3GfxEHQgo6agYxgiIa8bMV
+IkE8p0fG2ZRfYwLhwYy87F9JEIj2ym+Z/0Ooepew2niiFMqxVtQIVslUVLtL/xod
+uiktM6x3vQIDAQABo4GjMIGgMB8GA1UdIwQYMBaAFBEwc72NcCiC0m/P0jftzesj
+kdvvMB0GA1UdDgQWBBStvK477w0iNyKZRRE+EwqQgnHVjjAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMDUGA1UdHwQuMCwwKqAooSYwJAYD
+VQQDEx1DUkwxIG9mIGRpc3RyaWJ1dGlvblBvaW50MSBDQTANBgkqhkiG9w0BAQsF
+AAOCAQEAlivKj2rplK0uUXRMFJD9MHMBLpL35+UHCR37N0oX9VFLiTff3cCoMfkE
+0Dt/8uJk/N6dQI8n3vIYRH9CKiOIvfHudpFNSAM6LD9rGbIsmYADib3mXE2vVhcB
++edYLI7Qcd0IWXiQYsXAmwJuZfWn/KZTwFlkUVfMDUDOwFBSDIDTmISGZwoh0EUN
+t0ZTUYFUSCliBzQcS54tJOY1gnV4P0eAr946u3Wx2sMTKbZ8wGeKNzkuMYeGYp8l
+3JNoV6p2Oa6zVi+tHf3tckTToZhykiR6LtRcpGGiOGbTIIcdcmPZaf/LUfKgIqyP
+dsaeo0Fk2JlJ6/biR2C0pYMtN/hIfg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 0F 9E 09 91 9F 0F 27 AB AD C8 5D 0D 95 BF 42 64 0F 13 D1 F4
+ friendlyName: Valid distributionPoint Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,02924E6CEF2362C8
+
+iZyvq7fQJC1gqwi+TzhvSaaAp7cahIAGNyaN3BK2qsuorwMELmLp5vci1FocVpqC
+nJcNKQYvDWGooz4PMDU6GihwexEWMlAoVDGTO+obq4aAjahK68CzqGzROPobnMxs
+SNL2E5geSuF1dU1pE89hadMY35n1sOQtvWqrgaUqmPDcwaCPWGEV1xMH09lJ9/WM
+mV6L6KZPX9be+pXDkhrsZ1E6VwIV/cHkdmDpnhzXuErGHMQlPJqg5j0nI7wXliuU
+XSPiDsladyNIaJAkNHKzjDON9+rsRcAYvQytZ1ANiBAGmY6QXyxlOiro3rHeS6vl
+JVYK8pM5+EhOLJci1BAAc0se2Tvl7OXZIJuBwecvEiTnwCZsgNkJxNvbms3jdbf6
+58GETQCcJO1QJGUdnylELNjZIf1+PP5xCkP/2dAGdYZoN44P5tPstSAAv4uk7a8Z
+NfRgQubt0vovK+EDAh7szn5sMysNgsYYw137qFctYzDy7Go7jDizdZzGV+2/3F/Z
+Pwh0FsLaMjsApxJo5JtuHDOvADf0D66hpzb2HlOOmZ1t6HIxAjbsb4TwV7ATLHc7
+kyo+YLvSXOMN5Ma+4FwBPcMIf8PFtUQDT0KO16JlDtA1GXrbMkRmhvHd2oqU/bYZ
+9Yd21RFaoDOHtaWTXdriMYNcuzdU4E4x7vryqNU7lgxsqLZzShjpHLscTv1mPDMw
+SEe7qQAXfZO8h/qDaPw3PqLInaSeC7QbrBBwtHKsS8kzwgCassuVtLHHGVlRz1ee
+WGuY2MIGMmuHi0bN3IAWffYaAcf9/SEe7y4e+huHepU9HWg8bMZVy/mJS6LuRSEk
+kP/FNlJlMXujsed6NFToB3nNrWF/OZhq+9BrAl6KTMQ3isfGvDmYqw1MfGs+NAwX
+TYsV7F485MHc6dHc1ekJKp1K9n9SrWeT6yL1FNt3radujiWysy4giIsCs33kIqyt
+gyX7oYeprTvqVI0ajwJbVAWI8s7vR/LzR1kwK5El94e8tmpFiuQafBkap3EPs0qE
+/NyMIyneB4Znkn8mAexcMwxQZJrwFd0nmySjUqOl1t0bwX688eW0+EnRuohS83fT
+w48gKgZNEgDdwsOgq3TG8Co03OZbQVwf/lKBFaeFYQ5ml2ZwwuZ+shocufSMQDEW
+DsbD97FodlJeEAdXRDTg7BoCDtrntMnzfXnDButUT94+gTCr30ymyyaGajVE4LNh
+6h/rgdE8qVrsl8JX+8WNsOnCFrOBBV7IoqoUn2+g8eFJrxrjzB//R5Bmk8Wp9NiC
+Er3eBcInY9ySEKaWfaDzUjSoTKm+PRz+q0Zlh5+7RSWZWqpJMX5pKRmXM26f1YCK
+KmGDhg8sCSrqBa4MMteFun3E2Q4PwRODHuprrHg7EzcAm14C4W9R096HDGr2vEV7
+X9LqEKkF42FHLVumGLmOOtHnfx091XDD7v+1zCSbJH7HfNcKfzZNgNXztwRRdT4W
+6i7b6+omPIDSUMaC+UDFI/DEGL9yzql2JKcaYPO/tKkD6Pl1+QOxjOi032W93CYn
+v+Rs1ewQxvnAXEhPTdLploM6w0GgelUvbJiYCYgc5LrLuAygaRUQSS6KhEg9rC5E
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5.pem
deleted file mode 100644
index ef20fec499..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCs1jD9UP9Z
-XFXO9pXlwQaq3g11cXEADTlDc+W2RuUiBJXRjOhbt9pBqMwI7EhS41KMALd8ISna
-SAp5DDvmtp2z4X95eoizwZ9O5vtIw6XA7d5EwFr2c89INmIXFw2OA0K2Xj9K7eKK
-u95rUFjJM7qfZueTDyR8/qrUEUUhq+7gtQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUOjSLBeN2WFjEhwSYfX4djKxd
-uU4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMagar2d/lP05a6g8iDgAc4i
-8GOkbbNIOguMdW9fwv9DvIJyDO/ruRnKgZJdY9osVBqR8pVP1qErhwboe+dIBgLA
-p1yRVbcPKEd/1xXrFhjoH9Wlp6CK6Al0LIJ7iQMoufcUzay6Bux5caNEH06+BnJF
-nhKgwK6jkVuYAf9HHtVh
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid distributionPoint EE Certificate Test5
-issuer=/C=US/O=Test Certificates/OU=distributionPoint2 CA
------BEGIN CERTIFICATE-----
-MIICwzCCAiygAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGAxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE1MDMGA1UEAxMs
-VmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNhdGUgVGVzdDUwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALIdJpgRzxOKTnCCaASeNoi7icWn2JXA
-bBhMylWHT4WIl7sKHk5BkXh5iSMq81bPtotaxeZ+Ws8HGeZfJkZi3Ea/lo6bRPIp
-XLWXT9bEppiXcWEsQjM1OYGfiqAsPqHLQYmx3QlNndM4/lkMpXScaPwVUH5y1dbF
-oPNUrRztB7TpAgMBAAGjgaMwgaAwHwYDVR0jBBgwFoAUOjSLBeN2WFjEhwSYfX4d
-jKxduU4wHQYDVR0OBBYEFPcg5CWLrv8FdA/4HseZ3PWB0ri3MA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwNQYDVR0fBC4wLDAqoCihJjAk
-BgNVBAMTHUNSTDEgb2YgZGlzdHJpYnV0aW9uUG9pbnQyIENBMA0GCSqGSIb3DQEB
-BQUAA4GBABOac3w495YGcjA+gy3vEom/LJkN4/GNBM/n4qqPQSBLDfO9llCa+Ocg
-MeRH/D/CyKU7r767Zx5WsPTRtu8hysZQF/B2QMg7wrt4iJxD2VLl1gDrWSgIFEYL
-gmkFWj4cnUEWa3yxc+WoAYbFMCp10pGsfIpttb0KqIUYHGBSBNdX
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3A:34:8B:05:E3:76:58:58:C4:87:04:98:7D:7E:1D:8C:AC:5D:B9:4E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0*.(.&0$..U....CRL1 of distributionPoint2 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 8c:94:d4:ed:c7:a8:0e:9d:16:d2:aa:4d:3e:d5:a4:72:af:7f:
- e7:9e:83:e9:93:a6:92:a3:0e:48:39:60:27:0c:6e:75:4f:e0:
- 1d:84:89:17:3e:09:85:f8:ac:32:b5:76:76:ab:09:64:95:4e:
- ef:01:2f:34:69:4e:3d:53:96:7b:05:5e:c9:b4:84:62:a2:06:
- bd:5f:6e:6f:c8:08:be:8e:d1:4f:33:72:5e:8c:0e:e1:2e:f3:
- fb:23:7a:3a:34:3e:69:3f:6a:44:e1:a5:fe:cc:5d:60:23:95:
- a3:48:97:bf:72:dd:2f:ab:fd:59:5c:d2:11:c1:4c:e1:f7:ad:
- d9:03
------BEGIN X509 CRL-----
-MIIBnzCCAQgCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgZzBlMB8GA1UdIwQYMBaAFDo0iwXjdlhY
-xIcEmH1+HYysXblOMAoGA1UdFAQDAgEBMDYGA1UdHAEB/wQsMCqgKKEmMCQGA1UE
-AxMdQ1JMMSBvZiBkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQAD
-gYEAjJTU7ceoDp0W0qpNPtWkcq9/556D6ZOmkqMOSDlgJwxudU/gHYSJFz4Jhfis
-MrV2dqsJZJVO7wEvNGlOPVOWewVeybSEYqIGvV9ub8gIvo7RTzNyXowO4S7z+yN6
-OjQ+aT9qROGl/sxdYCOVo0iXv3LdL6v9WVzSEcFM4fet2QM=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5EE.pem
new file mode 100644
index 0000000000..2ce99c5cbf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest5EE.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: E9 C5 29 E5 92 23 E7 76 AD F6 A8 06 0B 02 C1 A1 7D B3 D0 6E
+ friendlyName: Valid distributionPoint Test5 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid distributionPoint EE Certificate Test5
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint2 CA
+-----BEGIN CERTIFICATE-----
+MIID0jCCArqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NTAzBgNVBAMTLFZhbGlkIGRpc3RyaWJ1dGlvblBvaW50IEVFIENlcnRpZmljYXRl
+IFRlc3Q1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAocgvAWF32zRU
+CqGI+DvQpWf+IU/MzpIJw0N2yTC9n5RQqepLfHbOu+s9ZEbxs+42KxsbXktapPgO
+yd6z/2M2gxyK4lKH3a1+iAf5hoPMyiYM3/Fp+GttKrlbWyXnFMx+0l2v5U5NIFl9
+sSoS9SxpVMtCHp8n67+fwKLHmZuvqIwezeqDGs/NWsWyq169Q3IIZ+W8mXIsQr94
+1Gs7NgbQ1wItpyHsfGQlcqT93WCloAQvdLikIISCCJhH1/SGZ2sYxWw9cjxP7Qh1
+VNobUSTq45voboe/Q1ccqnpfnFCnnEdepHPSM1an91U3w5PJXSarMloiyXUFsxhq
+HZfbIcK19QIDAQABo4GjMIGgMB8GA1UdIwQYMBaAFERs7ttvf+tOSX94/s3lGKDs
+u2BrMB0GA1UdDgQWBBRKg0dQhxSRE2yTyIuHCUD6gvgVITAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMDUGA1UdHwQuMCwwKqAooSYwJAYD
+VQQDEx1DUkwxIG9mIGRpc3RyaWJ1dGlvblBvaW50MiBDQTANBgkqhkiG9w0BAQsF
+AAOCAQEAfBLVqAitbExsjyJN00xcHbpcOUeLsGlcqODdse3hqUWBCGYVSbldGMsb
+X92XvNJuxg9eIXGRFywfr7WaWMhmUE9suOOF4amhS6PySHI+3nRTjiSuSpr6Flsm
+QBy6V8E0GhicUd7gQKjnmX/bngtuLrxDmT0J3KR90K35EDUBHMWj6xtgofMVUKGK
+DtPWB0pLklYStJgEJnbKaaOjO25yE58hxHxMwLRzs+yLJORA9m4eZa4PiGQ876oc
+hWlb5rgAhkEpCva3aQL4bU7LfHWteWHlOcL8YJxPQWReBizEk9G9A1jjRoMzHNGc
++RPY8p7JErINu/F/bY8WhuulVYdYrQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E9 C5 29 E5 92 23 E7 76 AD F6 A8 06 0B 02 C1 A1 7D B3 D0 6E
+ friendlyName: Valid distributionPoint Test5 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EC0796A18C4A9208
+
+cRBX4eAQ1ocSls58fvv7ns7yXjuLx027m2P5E4VUodsjirJnMrz08Rl7NvpqP3bF
+uRNmrLEHh51rzxof2/Xz70n+gsjvH18AJEprTI2jWwdGU5CRKuFndaWreR6Utnt/
+O0yGfYeYU6n8OUllg+iatMqXignwUtssC8kwmHkr0JL9u2UVWlJtTXAN3ZQcAn1n
+c/iEd/q8CsT1D66zKiNsXa6HtAtLb9KzA3w746cJCv0867BTym65VdIU7Z0dfzyE
+V6TLeKpU9u+p3D34ukjtn2APVeOMI+L8zSgs3/nbL1/jXWG7Wig30HvnEiwf+bHk
+uvu3YFZ57+U+yV2QwUx0H0PgIR0AIgqo5jyWyHsw1Y9kVWS9JdTf9CDJcdYM3Smo
+7lCZy+hemLXYODpmDGdtmeafKiCcBnkj8MMwUyE0fQdK+HhK9S1rIWv4SpVLgRjl
+62+e24ruvNm/GWtwTitLiFkuCaInIY0PmAEXKy0COGmuK12doGfvFEnCqjhSAkF2
+xdD5u1y3iIZPoD1ffUBzO9wzrC+0HnXH7lIkefKg5tQ6a6mkJYwsbPkb3v3q1jga
+uTIG1oSCng/IHJsMIvZqB0/ZXLwqiLRaNxyr6Nvoi0pQfRaEsgK39D0MyGupTPqF
+ouRJBovbzUp/Iz7duxM3gsQ/sr/qXy7pxZbDOfP6R6k0LE1pPqN5X7CJ0PJlIVam
+w7wcFN5TVBqLsdKie4JaR6w9VFK5129ZTSH52FZIRWhCTdwFBXBPahpa30NYVlXm
+vMe4912HPlK7+/yLSrrmofYaBo0esF4VD7dXtKRotGb4pBnw/aDkbtDo/NVI6Yp0
+/LMrYIdm9JQCmC0YrzobxABVYE3rjJKScjFL7uZDpoa1eiI+AMAUmapQphWnR5Bj
+GAVeURKYBqexzeXYhULGkmbMT0uqEiRPq5ciW3NjLCoNdGZD+1hXvQfACUbCpTd2
+anXjNZCOVVsQE5LC2Tq1VntW1AQ2FcHRUrXQtR9tf59AkoR/wWkK67AbjbHfrPxI
+KxTfhjYK6ENq/UuNc2PpFT6RJbM/ByVdeQZMmpsgkJRwYR4btVrmb1yHcU2dEf1g
+xdM7fGo09GALgferFuadvfq9iyNs40yjIbPD9qpq4tfNSpcaRH9gKphwtjpWUm1L
+PCRslk/LdejYd45dW8tBu0MY4NkthyNQCe+4b3cjQyBR/9WRwanoz0hzrMX321uF
+ya0bj+8wjK0aCcavT+gJIBwN/mP1FT0+UsWy0fN1u+sA4BkPtzOHfqLya6YA/gzP
+SXYZM4PhZb+643ujmkJP1SYqw10rDUq1pADP9xdpT8pkmBkCzfi35PQENzcvUngg
+sEeIY54VMr8pFfTyTUjuMNyR3lw0tVMdxMg3eIv4DvVhJ1/R2XS4O8d4xllt5X8N
+6gQGU3f7NZDlZTyIHwCxRFjRlEnTcUCaspu6N2LRqRYAS1VquoUXWQBKZQxGLsIV
+weL/ZdGTZ8Marrw/+QW0QhJaU4wO0WtQxylftd+vkyan0VAYJ/wRDZ2RS6WIVKYP
+ojVhkaeqxbJ2S9vmbMn4SrYDvAMUxbuRUP7XjXcMqpQ7Fg3R+a9vU8xIiCPWs53r
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7.pem
deleted file mode 100644
index 47a6d35e13..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7.pem
+++ /dev/null
@@ -1,120 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=distributionPoint2 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UECxMVZGlzdHJpYnV0
-aW9uUG9pbnQyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCs1jD9UP9Z
-XFXO9pXlwQaq3g11cXEADTlDc+W2RuUiBJXRjOhbt9pBqMwI7EhS41KMALd8ISna
-SAp5DDvmtp2z4X95eoizwZ9O5vtIw6XA7d5EwFr2c89INmIXFw2OA0K2Xj9K7eKK
-u95rUFjJM7qfZueTDyR8/qrUEUUhq+7gtQIDAQABo3wwejAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUOjSLBeN2WFjEhwSYfX4djKxd
-uU4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAMagar2d/lP05a6g8iDgAc4i
-8GOkbbNIOguMdW9fwv9DvIJyDO/ruRnKgZJdY9osVBqR8pVP1qErhwboe+dIBgLA
-p1yRVbcPKEd/1xXrFhjoH9Wlp6CK6Al0LIJ7iQMoufcUzay6Bux5caNEH06+BnJF
-nhKgwK6jkVuYAf9HHtVh
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid distributionPoint EE Certificate Test7
-issuer=/C=US/O=Test Certificates/OU=distributionPoint2 CA
------BEGIN CERTIFICATE-----
-MIIDEzCCAnygAwIBAgIBAzANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
-blBvaW50MiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGAxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE1MDMGA1UEAxMs
-VmFsaWQgZGlzdHJpYnV0aW9uUG9pbnQgRUUgQ2VydGlmaWNhdGUgVGVzdDcwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALJkqBgeil9P1aDGKnKT8h4pjVxykFCh
-VM/tAU8+60Q16CRQ9Bt/7EPt0Qt/mRgxeP51SDX2Sw37dE2Y6aTbGufnxaQbYQIr
-Xt4tEbUHKCx5cTIkR+rQh14970HAccLfsu8j21u+852qqsnXm1liCdwTw20NwfO/
-avIK1efcgtyvAgMBAAGjgfMwgfAwHwYDVR0jBBgwFoAUOjSLBeN2WFjEhwSYfX4d
-jKxduU4wHQYDVR0OBBYEFJFcO0xfyRIlKoio1BzAWLtkBu01MA4GA1UdDwEB/wQE
-AwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwgYQGA1UdHwR9MHsweaB3oHWk
-czBxMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAc
-BgNVBAsTFWRpc3RyaWJ1dGlvblBvaW50MiBDQTEmMCQGA1UEAxMdQ1JMMSBvZiBk
-aXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQADgYEAOPu/fA1dLP+t
-SF2JNufkHRN+2SvhsqtuOTvh/uFByRS+H2bLFMaB2IJQwkCidQ53kf8LNb6iNRtj
-hjVosG5KpEvqx70cRcUSp15fcdMDrjz2tAgiq58Eq/8DgYa+ml+CVRBx1Y6KHsyn
-eeXXuCv+DmdYkhXefbSyXe2lUsCiuR0=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=distributionPoint2 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3A:34:8B:05:E3:76:58:58:C4:87:04:98:7D:7E:1D:8C:AC:5D:B9:4E
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0*.(.&0$..U....CRL1 of distributionPoint2 CA
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 8c:94:d4:ed:c7:a8:0e:9d:16:d2:aa:4d:3e:d5:a4:72:af:7f:
- e7:9e:83:e9:93:a6:92:a3:0e:48:39:60:27:0c:6e:75:4f:e0:
- 1d:84:89:17:3e:09:85:f8:ac:32:b5:76:76:ab:09:64:95:4e:
- ef:01:2f:34:69:4e:3d:53:96:7b:05:5e:c9:b4:84:62:a2:06:
- bd:5f:6e:6f:c8:08:be:8e:d1:4f:33:72:5e:8c:0e:e1:2e:f3:
- fb:23:7a:3a:34:3e:69:3f:6a:44:e1:a5:fe:cc:5d:60:23:95:
- a3:48:97:bf:72:dd:2f:ab:fd:59:5c:d2:11:c1:4c:e1:f7:ad:
- d9:03
------BEGIN X509 CRL-----
-MIIBnzCCAQgCAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMR4wHAYDVQQLExVkaXN0cmlidXRpb25Qb2lu
-dDIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowIjAgAgECFw0wMTA0
-MTkxNDU3MjBaMAwwCgYDVR0VBAMKAQGgZzBlMB8GA1UdIwQYMBaAFDo0iwXjdlhY
-xIcEmH1+HYysXblOMAoGA1UdFAQDAgEBMDYGA1UdHAEB/wQsMCqgKKEmMCQGA1UE
-AxMdQ1JMMSBvZiBkaXN0cmlidXRpb25Qb2ludDIgQ0EwDQYJKoZIhvcNAQEFBQAD
-gYEAjJTU7ceoDp0W0qpNPtWkcq9/556D6ZOmkqMOSDlgJwxudU/gHYSJFz4Jhfis
-MrV2dqsJZJVO7wEvNGlOPVOWewVeybSEYqIGvV9ub8gIvo7RTzNyXowO4S7z+yN6
-OjQ+aT9qROGl/sxdYCOVo0iXv3LdL6v9WVzSEcFM4fet2QM=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7EE.pem
new file mode 100644
index 0000000000..ba308d9054
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValiddistributionPointTest7EE.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 25 9F FC 85 A2 6D 0E 82 9F 26 F7 21 2E 2A 5E CC 14 A9 F8 58
+ friendlyName: Valid distributionPoint Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid distributionPoint EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/OU=distributionPoint2 CA
+-----BEGIN CERTIFICATE-----
+MIIEKTCCAxGgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UECxMVZGlzdHJp
+YnV0aW9uUG9pbnQyIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NTAzBgNVBAMTLFZhbGlkIGRpc3RyaWJ1dGlvblBvaW50IEVFIENlcnRpZmljYXRl
+IFRlc3Q3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqhy1vplMFbpz
+ccU9FYtMZkobOoPsE4uf0s8UoML/tgHDsnzk0hsZPzrgkDwd5a5U5rXrt83S0ZZB
+hfcr4a2vgc5n8xtUB3hBI4++M4t6W6pu4YuHdxNZxLJNxzD6JXXzs42t5dTH+Ryo
+wgcfIsTkrMgaIw7gYV9cEoIVxVnqd5AY7qBmM2vN/DsgTaV4uju+XRhXiPcdpf0B
+j6+nDFoP2jrwHvrC5t4BcPfMMUfz316kt1DWnxcRlYp1mec6D2FHnGvVmpBXKU4O
+JzsjSXirlBrpS945LYxHLPwdRDvblL2JahjUKgKHWEZYOGp/UCdK09s+ikIb6P+R
+iJpz0t9/EQIDAQABo4H6MIH3MB8GA1UdIwQYMBaAFERs7ttvf+tOSX94/s3lGKDs
+u2BrMB0GA1UdDgQWBBQgeJBnu2Gwake3G5H9oG+TMcj37DAOBgNVHQ8BAf8EBAMC
+BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMIGLBgNVHR8EgYMwgYAwfqB8oHqk
+eDB2MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEeMBwGA1UECxMVZGlzdHJpYnV0aW9uUG9pbnQyIENBMSYwJAYDVQQDEx1DUkwx
+IG9mIGRpc3RyaWJ1dGlvblBvaW50MiBDQTANBgkqhkiG9w0BAQsFAAOCAQEAWi8g
+5HeE4pN40JTyl1xf2WD2d0Rp+EGRPBRT6JsA0Z2ajrVWJg/Dpqj12PgQqbCY6fd6
+e3DSzJgezXAOFIdaXNRWtt6bOYVEoZT80/Uszv5inEmYBWJYoJHaHClDR+I8Jxy7
+lVsuR5qsD6QPiqJYXSQMOdQapZdAZvXA8ZH67mhY6AFP+1E79WBcEwWuqY0CxH4l
+QAPiIGH0hHYiwkU2AIAQt9X6DzpgvpFQwbgrtM1LSlQAYPftilG3KV0RMV9PEBiV
+z+ojLzhK21j7upjcgJn5HKGUUTOSQ+e1FjxLYAURF1Q8+BvOPOjpYbzQlA0b0FON
+3hjOfuXfei/6htb8bg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 25 9F FC 85 A2 6D 0E 82 9F 26 F7 21 2E 2A 5E CC 14 A9 F8 58
+ friendlyName: Valid distributionPoint Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,12D6324C6E746FA4
+
+rj3/7o3RRUBDRfJnS4bVr3DSNqpBvjuWo00w0UAAAwrs51AkZSjy31TsZ3NOclBq
+ztXMvKZfLBQ39EZFOYL0riCx+QR1/UPbS52QfypDgq2RggTPAiKIxVMgw73S3pnT
+EH6RfYv3AegwIFXpu7VCPSxe/w1t5gJZgWQD/VVZy2SYhfDniZ4d6B5IOQUd4UVi
+1Ltd9YbJfOPfBMbEmv4q8TZtTTNOgSY/K3WfAGq6M2IeyNqKTQCANUs+wuJz6+Tq
+sw/7cVt2/sm+gUrpdP+dbCdM+T21MJBHFKhIG+P0V6OPHwtq14up1k98Ls+Ax7dA
+I1o5KOXbLwDUx5PooKlI4AYYVWIoFc8CQRsMUxmOQ0b8pplIxcgDg1Fgx6s85pug
+QQ206UbqzzwewMrvD6rqEI8RaHju82b7FzyQ9xdLsXyTdxoYMwyTMNino8JLwqOI
+wrwibtbNIP7q+WPaBIFoZuPAnqrCOYBn7yf5qnmWnLM9dpVabofFvE8ZcbDfFJ+s
+gGJ1A01+rOginQSRK7qW8x/23E6DKOk/4hUASzmKK49XhLnJtt+lCt3KZ8W0NhQF
+AIuwTY/BPvAdJ3J8EB7RVC2E/8a8FuqzvDUBmDknl6iSW2clSN4QnuyRyO6hLZ+W
+zlrf8IUV04RbPPUH/QLeasnMNAjvzEgk617ShEzUZLkXTXWJD2vDLV9EYQ9IENSk
+PKjhgZ4pvlFIjVc0aR4jDG388sgMDDkw2aAEss48u3E4fatNtQHEHG0yBS6VpIPr
+GyVjuzpSkHONpGcDEjmIpcycP58kn1AFKxoPjA0PvRTPlGc/0Vfx0Kz0g39+XDTY
+bI+kbFEpwdzKKXnZ8svBmbX+y7IxYjt+iWFoiGLQBK3PsE8jXn2DfD/KNnNJECLb
+mYNnrvm/DptGtqqgMIPW1npFj3pYBlULuMPR+nXTAKkmpKMjM38X0zOuZHgGDeaU
+tWly7gfT1y1vJQRScVT0yFXGIUS+kCfI7eGN080CIbNIT/fUVZkUeVj+M8W6kdbC
+6aL3FWaxHjSQ76Il39szxq1s3EjCYltzXpEUdNTF5QHj3C4VqxM1fH+p9BmETUE0
+38NVtBPLpJ9/mKIVU5PRdsclPKTX9nVd9aijA373hWGxYY8+ZlCoLt0ICShqTGU5
+1OKfuMIenONKAl1yyMNSLWNtd5cjnUtrWUUv/MO8kN7lcvhAtF+UOGPI4Ou3+gVN
+j6hGjB0crzDtfkZvhYfnw7V31M6DAcEaJ2uIOFYCekaDQSpY9UTemAgWZroU7Ljr
+472d9hnILmAHMk5a7WQH7d7nBIoRdwaM6xV/Kek8xMR84aB8SxSe/viURAsRuAwm
+fqA4NY2ZWCzDsr8uyf3HnoGsEzU3hein3VyfCJ4JkE3XxrxQbAH08aBAuhPYezVb
+Uj0yD+X6WjxMO5HXF/MrES8Bw5ziC+Mc+SN3KyThQ7KOiBYWJsqd9UIJa/vZQAyG
+tS9jGifuG1XpbdTlrr/ZBwxrPLgEVXjm3jQaWxSm4qI+hoRGhia+pjinc4ctvyFT
+rt93DRX7l9BLKjl1XsKF1gkwR+kFRGg46gc2cA5JGVlGrrfEMjJt0wIvSzFQyWyI
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2.pem
deleted file mode 100644
index eff7ceaf28..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid inhibitAnyPolicy EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy0 CA
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kwIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowXzELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMTQwMgYDVQQDEytW
-YWxpZCBpbmhpYml0QW55UG9saWN5IEVFIENlcnRpZmljYXRlIFRlc3QyMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8K1Na64KAEx4DG90CIYdXjn9QXftZ/JmM
-hJ7HZotijcxTLAJ3Sz0718AcEoSXtaXQlkw/PDRF6WOd0BjcLM6qzWEkQTWBWyW2
-EOBRbJ8UY8XRijBsOG7ay1rZEV4bomd/6xnNG6TznXujwmBXQZDp2Voyil8OgJiv
-uf+gY0BrnQIDAQABo3MwcTAfBgNVHSMEGDAWgBSdQJhgCObI/VzR2C8L6gDsGkUG
-zzAdBgNVHQ4EFgQUutY+X7TkU+FzLalrhov3rioWEiYwDgYDVR0PAQH/BAQDAgTw
-MB8GA1UdIAQYMBYwBgYEVR0gADAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUA
-A4GBAK2mBSjdik46DSR2Cn9O53Wk3uL54jZEHmH1jLi8eD7zxOU8eE23HWch+P9w
-swVaUJ4SqZfrgpV4+IJ72AMPGXKnAEn633uoNXbe8KFErSzMe3p+fFI4iKt2tMdG
-yPprehhYqGlG4KK5IHzgqcsfYZc989GcPE+Z679GnioPK8Mk
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBOzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTAgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALXCzoaXAEbX
-pgMPDk3SCu2nzrt+I18MsI4lg/0oLjQAgPsD0np8LOGHMzo3UBtfJtpV0BXCc+E+
-+Ni+ehXFWfA4BXjFc3GdUdJmn7y3F9X7XSIauTE1GSYR2+bMW/IRbmjpMDzldmRs
-WNb40N+jWAxw1h+YN61Pv0MD7Ef2ds0NAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFJ1AmGAI5sj9XNHYLwvqAOwa
-RQbPMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEAMA0GCSqG
-SIb3DQEBBQUAA4GBALhhUDb9VolIM2bKpbpat4dNjGrkOmVT/HvGBl+FGwSXa7Mj
-cLgZ3WygZ9gil3l7X+wL7lM9zKpXljV5WNpX+58RclQ2kK7Yk4qcY0tpPEUn8R4/
-9yg64Nferl/2gn9W79ODU3BiBFF/GiAJJ4SiwvLWl/JnPDoQuJv67IS24+Oa
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:40:98:60:08:E6:C8:FD:5C:D1:D8:2F:0B:EA:00:EC:1A:45:06:CF
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 60:ab:a2:8a:e3:22:04:cb:95:4a:c5:ca:68:46:70:0a:d0:31:
- b0:98:cc:ad:4b:23:8c:3e:fc:b4:c7:7a:93:0d:6a:31:68:c4:
- ff:30:37:7b:5c:48:01:6d:e1:85:f7:d0:9b:73:53:ca:62:36:
- 00:5c:29:c8:af:a6:40:62:d5:f5:af:32:a9:4a:b6:a2:a7:0b:
- cb:bb:72:2e:3e:0b:77:64:17:8d:2d:59:2f:fc:cf:2f:1f:a6:
- 77:83:9a:7c:68:b0:15:f6:5a:63:67:74:b2:3a:fa:74:b8:d3:
- a9:70:e6:87:04:bc:4c:79:ef:c8:b4:31:70:17:ae:f3:ef:ae:
- 7a:3b
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kw
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBSdQJhgCObI/VzR2C8L6gDsGkUGzzAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQBgq6KK4yIEy5VKxcpoRnAK0DGwmMytSyOMPvy0x3qTDWoxaMT/MDd7XEgB
-beGF99Cbc1PKYjYAXCnIr6ZAYtX1rzKpSraipwvLu3IuPgt3ZBeNLVkv/M8vH6Z3
-g5p8aLAV9lpjZ3SyOvp0uNOpcOaHBLxMee/ItDFwF67z7656Ow==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2EE.pem
new file mode 100644
index 0000000000..9f14a19756
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitAnyPolicyTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: FF 5C 76 C5 E6 D7 F8 0E C8 19 F0 BA BB F8 A1 69 CC EA 4F 11
+ friendlyName: Valid inhibitAnyPolicy Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid inhibitAnyPolicy EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy0 CA
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTAgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBk
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE0
+MDIGA1UEAxMrVmFsaWQgaW5oaWJpdEFueVBvbGljeSBFRSBDZXJ0aWZpY2F0ZSBU
+ZXN0MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMvWJ2NltVcIqG8R
+Gd6aAaTkV74OHh22qqq5VisygSWOraY+e/kZzgnHexceST9oUvWxJ210DYysc8E8
+NQsMEQRhJiy0vK2Pweb2q2Uv/DPpelT9Gzx3CuEuxvUvOY7EMYqsTkWkcvCbxJ0i
+/fYxmUJgsb+tdWuggcp1DV6UR1YVZFwFuzwFR6U3NxhkSKh1Aqpeg3rvO9igxaIe
+1KWuNKXb8GsQREEKOxXdRK21wrm7TSq4uhpyTbHb2GjhtAAKb/fiOtfWjibEhANg
+Xd9kxjSYI4npbisd+yYo45gXEDoqFTtxz6YPtR7+dzgVKxOE/Xc+PtXIl/0AT60Q
+Rdqsz/MCAwEAAaNzMHEwHwYDVR0jBBgwFoAUGKCgemr/ap2FgiTNwyaF+L+KNwYw
+HQYDVR0OBBYEFM7BJgyfyIp3q6sZiSd0E+VdkSzKMA4GA1UdDwEB/wQEAwIE8DAf
+BgNVHSAEGDAWMAYGBFUdIAAwDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOC
+AQEAn87EWhrmPNMFRrFS2VTSXUb/3OPnx1eLB918Vo+KY5fwcDGO8WuhxFsszju0
+BShfZnrwj7/Hrc/UdmPbk6RrPq5BMsmpLMwiqpxjqqN7J5C81cXvK2f7V4UX8sVc
+OriHWK8Vt6dEk0CN6Rt2AkkUE+7LrOS92hhLU5Opzyue3ZW6JPLfuk0uER2hKt3r
+POm96ZMVxNH0QAmZUQK03IqzGr+UigLgQA78Kc7qOYqTVc9JGuwu0F+e25h0L83W
+xRYW+BjGWRUfL7Y0uwylS772ZWLNBRac2mrniZJZNIzzr92Bwt5R4w0ZR6cB+C/S
+qN7XKYDdE6V9nwrJt5Wum031lw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: FF 5C 76 C5 E6 D7 F8 0E C8 19 F0 BA BB F8 A1 69 CC EA 4F 11
+ friendlyName: Valid inhibitAnyPolicy Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1A41BC0974CE034B
+
+gj9OGMPqVjkXcx6+XB9wKtnrs6R0hPYfYyncPTCzWCD4Y8e6yw2TKIEg7nXNQZOB
+hJZyH/I1Dat1LY/lVcF4kauf7546QEwL9m0IW6chsfRJZVt/AQN85zeM6bjidDBX
+H9fK1a0zs+x9btpbqdTRpIsOakUOnB9W0FCAdc6uYxrQ+yyoUXuqvuIMa4H08h19
+qGc3q+3mIpVwvJNO55k9lv2mUxaqSTIyTxm51TtXesKBmTVRUQB+zwsLA4IQPybO
+lGmxFkUzDJo/Sj/1taeDD+Fi0lr5Tz/VssgLJpEQ+CQzENbqpinS7DHFM7GwTwQy
+BhW3Fc2Uof3SU5FSuluJxAdUZuCN2nHZws+sQ7yfqG1M3UndJI67SOE949hP+tg2
+RA5jCQwMYbmkZKiBm9c+fwpHPVglN3KUjkE9wquqJg//VDPkDLVLnTooleNQ5Trb
+5dfM1ZJQA8Yar+yXNUOygiqi6wXwYuxceiFNMlLdi7I8UF/qFo2KiLvUC2lAQ5uU
+YuhI6X2iuuIhZiJqdX4B9Yc6Ha+MojIyfrYHF1haeZogk1GFmVqZdcoIqw/k6cqy
+lkOsRNdTYCaBJYdd0BuJp5wkhsRaAY+TccKa5HFyr+iPG7uif3LlhUWyxEF29/2I
+OdcK9orPTeQIS8mydbdlyo3x3dLs8bF2Ve6O2sXjovXhYAa/Ls5zH2SyjffWhr8w
+OuvzTaeK4ZLVuB/mK67V1giyfRgsj6tJymdxydqMGbunepzK664KDXp04lgnnkfQ
+THZpcVC+/bQeH+tPSEYk5/sQZS5SzABF4ILWiropxdxf5hNnDuiKMu/PaHYO026n
+yIuasY6H5Cl7JG8494ZG43H1D9WEu7ZQkLgLALduCoHVmx/746e+Y93XDvpnzjcm
+BlWslVdKL6SoqRlgz4QuzvZIeH1z8E01wJAGMjzb3nN9UgJ6pJtcR5FZZJ2rDUX/
+/CwE0bPiJHYwClggxHlPMUCCL2fzIOS/UBO1GVa00KEE5e5mJQlAV08uEDIeIsVX
+y4yXsae/fwsQ+lwxf2jKWdePI6pJ60BLm3ees+wb/UidegKfa7Eb1MFDHQDw6Kl0
+zSui/xU1RKpI7fsmpoqDSP7rAyIyMdJCgi8vK+Hx7vYHZPMh4vBKyHX3d2rsMvvX
+vskZsm033TXG3Jm/9umq6nG83YwBKWojxO1d/PFWJgwjVh+zV3KnJuDI5yojsBfY
+hC7VCGBfH0dE+ICRU9lo+xmgtKGnphYp+DyOAgdld4/d5OJxxdY+dfIkUDgdSA8O
+yAfn0Y8UQ1gWIvyaDPA69FkmFDSnhefejj4IsMVNa8daYlMS2wzKqvMNBkD5eaxY
+yHphFOhHLU1nYN0d1msrPqc6nfXkvMZiPxs5G2Y46px4ZZQ3HUEg9RY+YfHtOyZC
+jYWxwNYr30YfzqSZjn3LWAEox9f2FEu6tjv/Wv2xkukNQTy2FwUPa1dxU3uk82tZ
+AdqQhR7JZ7o9AeHn6YimUMMf2XxAfJNZm9p6bASUzmddodqE40D5+tvcqb0ySg5o
+qIAg1/BbFcXPhdGaGrH2WfkH4WcToCo5D4diL4c6jDmbZnYDesWDB00omwMhwfl3
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2.pem
deleted file mode 100644
index c9e23ce0b8..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2.pem
+++ /dev/null
@@ -1,162 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid inhibitPolicyMapping EE Certificate Test2
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBjMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-ODA2BgNVBAMTL1ZhbGlkIGluaGliaXRQb2xpY3lNYXBwaW5nIEVFIENlcnRpZmlj
-YXRlIFRlc3QyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZweShwVjs1qka
-nqPGQOLGlctQ3TXgy/mxMNF5iCtHOwRF1KCW1OU9KloQ3r6+OfgzcZN+flBVpI3e
-jyjOMjfcTTb30YkOQneX5WBmDbG0hNh6eMeguoRuUhkdFGqXR/vCRpMZm54bw85o
-6PrFmUwLluXwBGGzX7qaD0h2mpzycQIDAQABo2swaTAfBgNVHSMEGDAWgBQXeoow
-BvbqXDZADa7Yn7+5vYLMUjAdBgNVHQ4EFgQUGa+XGGh0cFuvb54Rblg0NuJV0T4w
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwAzANBgkqhkiG
-9w0BAQUFAAOBgQCtpBN+M2QdihGfroUS+K93c6X4n5STm0IwsSvGEpOHX2tjLKqr
-WGurbAH8XvIJEsO4wlA6NOHbFEYmSYX1otlMNDKu3vQVTDEB7RJWA04YsUuS4BNA
-B+scXAJEWbvQdkoGh5U+aOmX8yST+HWIbW6XgKQmA3qiO4LsJgdmEDB8xw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpjCCAg+gAwIBAgIBODANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxMiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-s4T6CQeTrbqUSlSczfx8iMSRK4ip9F4liS7giqCrZeZYEuP+/XoRZKzqmT3G+io6
-zcenL7cegP9DJnTNuZ1nHEoeJTlhQZq00PD1n33OMK0zhMIirByYBpabztuw1dJ0
-MKKcRzJ1AswgccI8seh2W1FXdFo/vGkDOkcD21Se0XUCAwEAAaOBnzCBnDAfBgNV
-HSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUj3Ywg1+jhUuQ
-FB4GBHs3AQUgJmYwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUD
-AgEwATAMBgpghkgBZQMCATACMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgw
-BoABAIEBATANBgkqhkiG9w0BAQUFAAOBgQCXSeQ5mEkpmqCHstAZJbAGVSNrj3ka
-eA0k2v+n7vDeZ+9F8bByDiBBz3RMTqmdZxQ6zroOPsw66HLxv5D7oJImbhyvFrnN
-uxPGh8hvvP67N7UT9cM0RAoIQHmoI+3+o9cqOnTIJWXXPyq5q08yTrUt1lzFyrcK
-wGB7PyQXRRDWjA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
------BEGIN CERTIFICATE-----
-MIIC5zCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBTMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAm
-BgNVBAMTH2luaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgc3ViQ0EwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBAMX6LszkJcSryGVxfI4egJDv3zFztB0M+jGHKEc8
-uPkbpVlPSjM2LWqUOks/C1q34lfaC6J5O+V3/DmN7GjLpJmdjBDn7k/aqGeE7XHR
-Wns707M/rcEWxPP/ErMQNIsqSkvy92GtwuaG7wsY4a+KyB0YCdqikJr6oK2Cvhwf
-LmC1AgMBAAGjgc0wgcowHwYDVR0jBBgwFoAUj3Ywg1+jhUuQFB4GBHs3AQUgJmYw
-HQYDVR0OBBYEFBd6ijAG9upcNkANrtifv7m9gsxSMA4GA1UdDwEB/wQEAwIBBjAl
-BgNVHSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjBABgNVHSEBAf8E
-NjA0MBgGCmCGSAFlAwIBMAEGCmCGSAFlAwIBMAMwGAYKYIZIAWUDAgEwAgYKYIZI
-AWUDAgEwBDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAE3ZflJR
-6b/Pwip7bO1ZIkiym+8uTzlT5nx3CF4P5Yyhje4VKVqoAOdljbZoaL5x1Zdd733W
-MxbQk/QP+wziLjZJlnqX+lSxg4wUiSU6mGtDJ1rPwMsbiiVBld7iP5JhFAWoTg0b
-XJ0ZSTHABPtNeMg2desSHwfh2I5WtX3hpXwE
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8F:76:30:83:5F:A3:85:4B:90:14:1E:06:04:7B:37:01:05:20:26:66
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1f:20:b6:9f:f6:68:a0:22:5f:24:73:c0:ac:bc:8b:05:86:58:
- 7b:97:ad:38:8e:70:61:7c:17:9d:38:21:06:0a:72:b5:41:3c:
- b6:9a:93:77:6f:e3:15:e6:06:74:67:90:b1:95:56:f2:be:52:
- 21:6a:de:f7:bf:d9:2c:12:11:9d:dc:f9:ba:46:f9:92:24:75:
- ef:83:af:a2:8b:3a:79:da:ca:c5:72:a4:7b:19:e1:a2:f7:02:
- 18:92:eb:a6:1b:74:bc:ba:62:51:d6:9f:69:af:20:34:3d:43:
- 08:e7:15:da:75:79:b7:81:6e:ae:95:08:cb:7d:e0:3a:50:7e:
- c1:7e
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFI92MINfo4VLkBQeBgR7NwEFICZmMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAB8gtp/2aKAiXyRzwKy8iwWGWHuXrTiOcGF8F504IQYKcrVB
-PLaak3dv4xXmBnRnkLGVVvK+UiFq3ve/2SwSEZ3c+bpG+ZIkde+Dr6KLOnnaysVy
-pHsZ4aL3AhiS66YbdLy6YlHWn2mvIDQ9QwjnFdp1ebeBbq6VCMt94DpQfsF+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:17:7A:8A:30:06:F6:EA:5C:36:40:0D:AE:D8:9F:BF:B9:BD:82:CC:52
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 01:73:17:d4:24:e8:3a:79:6d:9c:a4:96:74:fd:60:fa:65:82:
- c6:0a:26:9c:64:d6:f8:c5:01:8e:ce:70:b2:a4:1a:a0:1c:41:
- df:1e:a2:36:1b:4f:2d:56:6f:ef:e2:fb:e7:84:d3:aa:0c:08:
- 04:44:67:57:88:8b:34:b1:74:8c:57:96:9b:e2:b7:dc:2e:d4:
- a3:05:41:bb:24:fa:be:2c:a4:cf:be:0a:aa:8d:64:ff:6f:ee:
- e1:24:c8:06:8e:15:fb:fd:19:fe:92:d6:55:84:ae:71:58:2c:
- 6a:65:53:34:39:20:43:1a:5b:20:41:81:00:6c:5c:10:25:b0:
- 3f:f3
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFBd6ijAG9upcNkANrtifv7m9gsxSMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBAAFzF9Qk6Dp5bZyklnT9YPplgsYKJpxk1vjFAY7OcLKk
-GqAcQd8eojYbTy1Wb+/i++eE06oMCAREZ1eIizSxdIxXlpvit9wu1KMFQbsk+r4s
-pM++CqqNZP9v7uEkyAaOFfv9Gf6S1lWErnFYLGplUzQ5IEMaWyBBgQBsXBAlsD/z
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2EE.pem
new file mode 100644
index 0000000000..e6fcd20b60
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1A 71 70 3E F1 A6 1A 85 BD 72 DC 16 16 EE 1A 80 92 61 64 36
+ friendlyName: Valid inhibitPolicyMapping Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid inhibitPolicyMapping EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subCA
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMGgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMTgwNgYDVQQDEy9WYWxpZCBpbmhpYml0UG9saWN5TWFwcGluZyBF
+RSBDZXJ0aWZpY2F0ZSBUZXN0MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAPDRNocjMpqJS8XXEn2KeY/S7iXL8tNa1sS8X1umBKBSotfKudBZlQFXSesE
+FC0og1Zs0syETNkUA1Wi+0cs+q2B0dNQS3oEzuMhMHRWjj56QtBiTFGwUs6qRliH
+JJ+AAmcwOoMjsD64MFxOPtwAo71i1LAPbDXj9fZSPmQirI9ntOafT0RrZDVQwh0g
+Sh6aCSAh/Bht8BgTaZW4MN/bi/cqv5v8bnFuV0BOgCE3O0frFuwinSG1d69ZOHHK
+qVZ/fRfKNlxflSU0XcbtybYVgsyAoRL9Wq4m3RKsbtDeyqLa5SFTKRCMRw4ZCEIx
+F1OMaeFh7etefe+7zDRW27l+2jkCAwEAAaNrMGkwHwYDVR0jBBgwFoAUqiaUHWQP
+fgW8XWCNB1f8cJVmbOcwHQYDVR0OBBYEFP9zakNg0xu0uUYWu6rUrwVyxJTZMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAMwDQYJKoZIhvcN
+AQELBQADggEBADaelkwjWQrtrmyosROq1o2cNB2pldWpI3chT/c3cn8IpAQMMNHJ
+Ch94idy6x/bzO7R2ZXlL5VCHPJlzDpClEOv8ZGebupN3+AE73Czaxqxrxj1xiOVl
+g5imlIUt7oIjJibpLDVSH7Z2PcY9YK+/A6uaX1kll4oMtCLmoF8obFVp7alj0Hzp
+uVpVfEq3I0dRLGLJCuOg0wCoyLtjV+YGp+uXXxYWBZc3CbxE1sVJ0g8D1JYLj5eq
+uyj3Nmplo6T1c6i02z4LDtl81umgQyeH1JPijLH094G12i5L50QevtqQ6ifmFHjP
+24mHZ/b0BatgDap0gy+JOYrPj0op5HrnU7A=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1A 71 70 3E F1 A6 1A 85 BD 72 DC 16 16 EE 1A 80 92 61 64 36
+ friendlyName: Valid inhibitPolicyMapping Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,345A2F34C9598F64
+
+XfvNEKO6RJq11Po3l3MB8Iv0E0gzRwfLPEJOIiKq0Dl2emB4Myp4dlFMdX6HgmSB
+Nec+QWQHsV+t2koSF2SlwNFMzMhHX8lUDjYN1pGDqodXhaqUb2lbvtmAud/O9Nth
+40jd4kXq+OGgjKmmXIOlLdjVf4DoM6k3u1TVdtL+6lEEKojO+EWxl2TWd4/0+4GU
+LS/qK802foNZk1FS+FSxMrEkoZshUWmK8qWFID5WUdM8Afi5l9LX4s1edNIzFEq4
+8f/btdMrEpYI7q/MmuMNotiH5DVDGXKd3Lj+mHeDuzjtmjC+KbDBX/SPyqJN5nav
+P+3TtTDhKvKnSdMF4+Zn1t3DzAE4gDZcHwqTOraDTAS4Pvqrc+U9AMG4STrcQ4Hs
+BCWPwX5AakSNhChcpILJOMKu/Y6MNHUXMboE/lJPCF39sM0aqUUvg/9oCjqcOHVa
+OdLhIiSJesXCjXvYszQocaSLexiIbEqszqQ/2zyjCPNFEILycRTOhQo1059+8BcH
+F2toqctHo8AdfbLFmns7xrTiV03r1tbUV1RYd5qIvqoR4IWlNobmu/xzBRyrz5A/
+otiGuTzM27FzO2Igc1IdMgN5WFM2znywlWFf2IY7vKZ+UlNCeNqHnkQ3YiokdrmH
+thKTiOTsC7CkBD67jFBFkHYBatPE0Po43K8ZFjMzLkmKcay7Pq74+N20TivWpgqW
+dxQgBWkibe/bO6UNf1va81Z2z4MtlNOkagajWaLNBTYTdRrpAUKTqgV2WejMaMti
+KULXKiEKhJ/M+74q7Med+OHkIQpQEpCuuSc7VfWsrcSIXqNj/aCxgSByci9k06c0
+K8aGxAYSFP+mr9EzoHeTo1kb79grgilaSSuwopwNoE9jfg/yMtU7oIvrnH7biqwb
+4aaLSaSqrN1HT/6ACBOIHlnmvwzQh7rSxiuWO5A+6COUDvOmyaiadifUlXMo9fcv
+M7mn6yOFzjSZ1uKXGgyh9+uATmu8Wf/zeEoJtJIrE3Fv2Ibd9FiqmRwdVyilHrYk
+8Mmdsrf1AZ5qNXYEYRSZYSX7+HRLniO9kXbbGtIrNB7bRkTdX33vQy5EQ3xKatb5
+X/6diAv0Rn56LoyNWmmj/khZnrTUbWrykzaTLvV5Hsq+ZMD+huxLCfLN/Hu8RDDk
+K2YUUGiJocv8mv2AtH5U7KNPE+tzEAB2dHTT978k+eS2Sv6wXZj+alsPOWXvKF+4
+BdWatrC8wi14KhZafV4AoRa6VMbe/e60gZ5b2DvDtJ3znYHv/UMoOOToV1OkiSDy
+n86YnswIwCNL7SEaMXlr1R9RX8Lk3GJY4Dt9btKfsFCu8esjh1FVfMQaWLaTe3fq
+9Pzmf9/Jp1/5bPby5rw2hcEmRj360Pc5J+CeloLyb5PUhjjtiEUM0/EsLBSROnVx
+AkdZRCqVvxK9vVQanxvvWeQ6ROWffSLzcPdIfyV4tP/7+Awwj8OZBgUlqPeCrTlW
+qu/3kjSo1slpe9TXGGqQKT2j4+0CvNqWtAmSUg0s807KTSq1Hn8HxPo/ETgYaMUi
+dF46SXGfZ6b/wIcroki51SDDyTKRcZujP0kwmkv2prL+TUMe/kVYHTn8h/xB5gpR
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4.pem
deleted file mode 100644
index 21d384e81c..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4.pem
+++ /dev/null
@@ -1,216 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid inhibitPolicyMapping EE Certificate Test4
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCA
------BEGIN CERTIFICATE-----
-MIICmjCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTImluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3Vic3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5
-MTQ1NzIwWjBjMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0
-ZXMxODA2BgNVBAMTL1ZhbGlkIGluaGliaXRQb2xpY3lNYXBwaW5nIEVFIENlcnRp
-ZmljYXRlIFRlc3Q0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMMwNGdAJ0
-vncWniYOninmdOvqbWTU+G3jPbZ4uJULmhWBvap0Hpq8RSJZ8wprenFgK2/epICj
-uFtJZyEtG/3A8PZ3IHYNkWv7srclGdUlotObulycoDHBn9LXI+i/CvUNGvFJldlm
-kQOxqy1Qhto5Gj7cVWa4HiEYfx+7HJPR2QIDAQABo2swaTAfBgNVHSMEGDAWgBRa
-k0vvlp6uPkMWJqQYHnmLouabITAdBgNVHQ4EFgQUFgpn09iEBzTYWYmTqi0RWeEt
-CfYwDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwBDANBgkq
-hkiG9w0BAQUFAAOBgQCCP6oScMpFs5Ak3jAfJkXhwpzciLdF1Mtq/SO8auu0mZ6a
-CfrKh6JL5kshzKbZFbRYqkIidQNW42Iv4et3yLhWZvSVoYkP+EAg0dMs9/Arw2C1
-pqRc5a2mgi1G182TWgEh9rMZDvYPdD+FrzZU55bLtSlt9L8o9y9vz6+dE2MrLQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICpjCCAg+gAwIBAgIBODANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFAxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczElMCMGA1UEAxMcaW5oaWJpdFBv
-bGljeU1hcHBpbmcxIFAxMiBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-s4T6CQeTrbqUSlSczfx8iMSRK4ip9F4liS7giqCrZeZYEuP+/XoRZKzqmT3G+io6
-zcenL7cegP9DJnTNuZ1nHEoeJTlhQZq00PD1n33OMK0zhMIirByYBpabztuw1dJ0
-MKKcRzJ1AswgccI8seh2W1FXdFo/vGkDOkcD21Se0XUCAwEAAaOBnzCBnDAfBgNV
-HSMEGDAWgBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUj3Ywg1+jhUuQ
-FB4GBHs3AQUgJmYwDgYDVR0PAQH/BAQDAgEGMCUGA1UdIAQeMBwwDAYKYIZIAWUD
-AgEwATAMBgpghkgBZQMCATACMA8GA1UdEwEB/wQFMAMBAf8wEgYDVR0kAQH/BAgw
-BoABAIEBATANBgkqhkiG9w0BAQUFAAOBgQCXSeQ5mEkpmqCHstAZJbAGVSNrj3ka
-eA0k2v+n7vDeZ+9F8bByDiBBz3RMTqmdZxQ6zroOPsw66HLxv5D7oJImbhyvFrnN
-uxPGh8hvvP67N7UT9cM0RAoIQHmoI+3+o9cqOnTIJWXXPyq5q08yTrUt1lzFyrcK
-wGB7PyQXRRDWjA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
------BEGIN CERTIFICATE-----
-MIIC0zCCAjygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH2luaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgc3ViQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1
-NzIwWjBWMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMx
-KzApBgNVBAMTImluaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgc3Vic3ViQ0EwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJiRgbTlXD7Tr33rE8bkM1fLhA/0RcC0
-n6UIcVb6xSELqRqVIpXK2C038i/3Ta6+eoiCdjT6kvQwsM9uMBJnB7uePzDzpkSE
-G3Php6MSbnAO+6LPrGFBJ0LNo6yXvsV3HQ1Uwh8iND8Yt37obPJ05PzfU6hSnMgV
-47YDMrmE5h+5AgMBAAGjgbMwgbAwHwYDVR0jBBgwFoAUF3qKMAb26lw2QA2u2J+/
-ub2CzFIwHQYDVR0OBBYEFFqTS++Wnq4+QxYmpBgeeYui5pshMA4GA1UdDwEB/wQE
-AwIBBjAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAMwDAYKYIZIAWUDAgEwBDAmBgNV
-HSEBAf8EHDAaMBgGCmCGSAFlAwIBMAMGCmCGSAFlAwIBMAUwDwYDVR0TAQH/BAUw
-AwEB/zANBgkqhkiG9w0BAQUFAAOBgQCh/ZM7m2L0OxzF6RXxeVUhY5xlTjRO0HGd
-0xOnDkOesSYfCI4gUflMo6/T9Ot67Vnb9mgzwWSEXB6g2R22/3DVR1ord/UgZFKe
-w4llbMnwRS5e3zjqLGsLeWk2ZdyjoD2vmKiFBiX+rlHvaLk+5xYcGEfOupTVqWMO
-OHuz9iinWQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
-issuer=/C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
------BEGIN CERTIFICATE-----
-MIIC5zCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xp
-Y3lNYXBwaW5nMSBQMTIgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIw
-WjBTMQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAm
-BgNVBAMTH2luaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgc3ViQ0EwgZ8wDQYJKoZI
-hvcNAQEBBQADgY0AMIGJAoGBAMX6LszkJcSryGVxfI4egJDv3zFztB0M+jGHKEc8
-uPkbpVlPSjM2LWqUOks/C1q34lfaC6J5O+V3/DmN7GjLpJmdjBDn7k/aqGeE7XHR
-Wns707M/rcEWxPP/ErMQNIsqSkvy92GtwuaG7wsY4a+KyB0YCdqikJr6oK2Cvhwf
-LmC1AgMBAAGjgc0wgcowHwYDVR0jBBgwFoAUj3Ywg1+jhUuQFB4GBHs3AQUgJmYw
-HQYDVR0OBBYEFBd6ijAG9upcNkANrtifv7m9gsxSMA4GA1UdDwEB/wQEAwIBBjAl
-BgNVHSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjBABgNVHSEBAf8E
-NjA0MBgGCmCGSAFlAwIBMAEGCmCGSAFlAwIBMAMwGAYKYIZIAWUDAgEwAgYKYIZI
-AWUDAgEwBDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAE3ZflJR
-6b/Pwip7bO1ZIkiym+8uTzlT5nx3CF4P5Yyhje4VKVqoAOdljbZoaL5x1Zdd733W
-MxbQk/QP+wziLjZJlnqX+lSxg4wUiSU6mGtDJ1rPwMsbiiVBld7iP5JhFAWoTg0b
-XJ0ZSTHABPtNeMg2desSHwfh2I5WtX3hpXwE
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:8F:76:30:83:5F:A3:85:4B:90:14:1E:06:04:7B:37:01:05:20:26:66
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 1f:20:b6:9f:f6:68:a0:22:5f:24:73:c0:ac:bc:8b:05:86:58:
- 7b:97:ad:38:8e:70:61:7c:17:9d:38:21:06:0a:72:b5:41:3c:
- b6:9a:93:77:6f:e3:15:e6:06:74:67:90:b1:95:56:f2:be:52:
- 21:6a:de:f7:bf:d9:2c:12:11:9d:dc:f9:ba:46:f9:92:24:75:
- ef:83:af:a2:8b:3a:79:da:ca:c5:72:a4:7b:19:e1:a2:f7:02:
- 18:92:eb:a6:1b:74:bc:ba:62:51:d6:9f:69:af:20:34:3d:43:
- 08:e7:15:da:75:79:b7:81:6e:ae:95:08:cb:7d:e0:3a:50:7e:
- c1:7e
------BEGIN X509 CRL-----
-MIIBSTCBswIBATANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJTAjBgNVBAMTHGluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8G
-A1UdIwQYMBaAFI92MINfo4VLkBQeBgR7NwEFICZmMAoGA1UdFAQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAB8gtp/2aKAiXyRzwKy8iwWGWHuXrTiOcGF8F504IQYKcrVB
-PLaak3dv4xXmBnRnkLGVVvK+UiFq3ve/2SwSEZ3c+bpG+ZIkde+Dr6KLOnnaysVy
-pHsZ4aL3AhiS66YbdLy6YlHWn2mvIDQ9QwjnFdp1ebeBbq6VCMt94DpQfsF+
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:17:7A:8A:30:06:F6:EA:5C:36:40:0D:AE:D8:9F:BF:B9:BD:82:CC:52
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 01:73:17:d4:24:e8:3a:79:6d:9c:a4:96:74:fd:60:fa:65:82:
- c6:0a:26:9c:64:d6:f8:c5:01:8e:ce:70:b2:a4:1a:a0:1c:41:
- df:1e:a2:36:1b:4f:2d:56:6f:ef:e2:fb:e7:84:d3:aa:0c:08:
- 04:44:67:57:88:8b:34:b1:74:8c:57:96:9b:e2:b7:dc:2e:d4:
- a3:05:41:bb:24:fa:be:2c:a4:cf:be:0a:aa:8d:64:ff:6f:ee:
- e1:24:c8:06:8e:15:fb:fd:19:fe:92:d6:55:84:ae:71:58:2c:
- 6a:65:53:34:39:20:43:1a:5b:20:41:81:00:6c:5c:10:25:b0:
- 3f:f3
------BEGIN X509 CRL-----
-MIIBTDCBtgIBATANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKDAmBgNVBAMTH2luaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAt
-MB8GA1UdIwQYMBaAFBd6ijAG9upcNkANrtifv7m9gsxSMAoGA1UdFAQDAgEBMA0G
-CSqGSIb3DQEBBQUAA4GBAAFzF9Qk6Dp5bZyklnT9YPplgsYKJpxk1vjFAY7OcLKk
-GqAcQd8eojYbTy1Wb+/i++eE06oMCAREZ1eIizSxdIxXlpvit9wu1KMFQbsk+r4s
-pM++CqqNZP9v7uEkyAaOFfv9Gf6S1lWErnFYLGplUzQ5IEMaWyBBgQBsXBAlsD/z
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitPolicyMapping1 P12 subsubCA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:5A:93:4B:EF:96:9E:AE:3E:43:16:26:A4:18:1E:79:8B:A2:E6:9B:21
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 64:90:80:33:7a:e3:e8:e4:66:09:4e:4d:1d:ae:cb:f4:f5:b2:
- ea:4d:48:24:be:04:8f:39:9e:c1:da:6c:14:fa:0a:a5:be:47:
- 84:19:27:c0:3e:15:ab:18:78:71:0e:93:e7:6e:c8:05:ea:f2:
- bd:c3:7b:fc:52:04:be:fc:b2:22:80:81:35:b3:ab:57:7b:23:
- ca:39:66:ed:47:19:cd:1f:2c:ab:14:4a:28:5d:23:ab:24:7b:
- e3:51:bb:78:79:05:20:25:ff:13:4f:c5:d1:2c:e1:67:b3:e4:
- 29:35:2b:1c:5e:aa:01:17:aa:49:bb:04:66:52:a3:1a:7c:0b:
- f5:57
------BEGIN X509 CRL-----
-MIIBTzCBuQIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKzApBgNVBAMTImluaGliaXRQb2xpY3lNYXBw
-aW5nMSBQMTIgc3Vic3ViQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqg
-LzAtMB8GA1UdIwQYMBaAFFqTS++Wnq4+QxYmpBgeeYui5pshMAoGA1UdFAQDAgEB
-MA0GCSqGSIb3DQEBBQUAA4GBAGSQgDN64+jkZglOTR2uy/T1supNSCS+BI85nsHa
-bBT6CqW+R4QZJ8A+FasYeHEOk+duyAXq8r3De/xSBL78siKAgTWzq1d7I8o5Zu1H
-Gc0fLKsUSihdI6ske+NRu3h5BSAl/xNPxdEs4Wez5Ck1KxxeqgEXqkm7BGZSoxp8
-C/VX
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4EE.pem
new file mode 100644
index 0000000000..6e38b01882
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidinhibitPolicyMappingTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 6D AB DC E6 32 A2 D1 1C CF 1D D4 69 DD AE 5C 0B 5D 14 96 94
+ friendlyName: Valid inhibitPolicyMapping Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid inhibitPolicyMapping EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqTCCApGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMiaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTgwNgYDVQQDEy9WYWxpZCBpbmhpYml0UG9saWN5TWFwcGlu
+ZyBFRSBDZXJ0aWZpY2F0ZSBUZXN0NDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKYL62yu7+fSYzmj0n3w6uGjjzv62IQV/CL9BECVjokjFNxU+tfm3Mk7
+Db7JxnHMEKR8jY4KvRmsaNSUe/3lK1VG4AFNzciYw4eDhOOLr5Kkx6EE3nbiWLiH
+eE7CDRe68kwiRf71K4sUuRtHFKzYq78O1LY2fbYQoudnVbMs7JGj02nVqBA7M9iR
+JKu6V6R/9EdSQEI7SFQEOJcnlIOkdL3Y5zYQLmXvoQ21RACpbPTrt4VFLQ9kUgdV
+IwrIdD1qunbkbNTiaIjLcy8duhKBVx1m20MFY3h1uQc7SsOedEtCX/XA6a4GUZnA
+TwBBiNePmhJUcN3P+35i8GBfin0K47kCAwEAAaNrMGkwHwYDVR0jBBgwFoAU14Bc
+E4uOQXa6CrVzceijQIB0DtEwHQYDVR0OBBYEFHcvegxzhgIyUXHqaXOrOMLRpwmi
+MA4GA1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAQwDQYJKoZI
+hvcNAQELBQADggEBALkd6aOI5LOFb4xsYP6dSJe1DNfieEU6gmjHjphXiz1VXbau
+0j1lqcxNj7GiOEThH6C9rgQ1DQmEt1DQrj4byYgnoMOa5fUwK5r3Mw+r+2SIGbyy
+wvu6Sy1zdJ3OGymchuIfVXeaXgku/Uhf/68xSn8yw0HW9SEKe8ZDVZKTCXPPqnLW
+FbD4xjBHXywSXlRlohLRuk9Rparq2Q18Qat4TOf/M1FjdxrToK+HRSfNw3e7cHQp
+gxIvCK6mshrc9ojJ0aJRxvZEiM1W4/Twn8R+1sdWxKxeSfdz0Sl0jBHBVY/CqWKc
+5Xh4d7lLxwItJ60kyVbsrsGeRJHtY1jyMQ9T+1U=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6D AB DC E6 32 A2 D1 1C CF 1D D4 69 DD AE 5C 0B 5D 14 96 94
+ friendlyName: Valid inhibitPolicyMapping Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F3E31AEC3D5768E3
+
+9UUHfnUhE5QAbpko68+WMXCmLsSpLQ9yYiXhguUwoxnoHWxtKo55PaVJnaHlod9e
+2iy8dSot3h+LNM+GZ8I/OmpzGrEa/GMCO4QhXhwRnRcyifFy3MKFPpO4MJUf6sJ/
+1+Qj2j79kQ738etkvc7qFmJlp81/cvIOybSMoAvFwGfkABqVRXBGSM12UkL5vBg5
+n//GvEP8vJj0P/luK2OS8TSVH/pNeRN2k7u7eA4cYssb7zWyD+xUKFXlNSKoiStt
+506bbXuPDv7EjBDi0VU2Xdh8oPU0guLOh3G06Y60WbfA+rrM/fbw3J+hVply8vCx
+lI5J8YHhsReSsl76dpnocfjaXMj+K9vZX3fgDDEu+1Xwo11X1ztHXPPNPVRFgb5Q
+iY+ERzFwJykapOmOSuHAK7trCnNhGwvOgmLuBe2iNl/c3nom4hQrwIP5fxavOdjC
+6fuXN0od1V6agr22OZOM2dp0YcCVlptNIicSNHxB2YyngEmaAICtB4IdwfeTmcGD
+FS3sdRQi/BdqgiSaZtrexYDu0d7//Mujk4W8MCK9m4Z2BZDyYBEYLGcr3c7lWRyV
+cvWOz++X3Kwe3ENpZEHA6dYFgXWnBEyqAajjGamfVTi1eool6WoAYQ4ngPAX54LU
+Fm9FiQueCnWgrBIWt8BJBKThikOk9fy5gvKWSx7Lz3BipsBYf2k2jvG7tCFopIdj
+HNSfq9nEiWQ/d6W7vEdImu9geJxFBbNhmL/NQS943OL/GEESKzz/UCcJ79XhSqL9
+YO5xJe1KYwnrDstkuwTsxJfXyOCQaOCTkELTwzxz3B8gP0I7gaF/I4g98NND3Ldu
+prGNzXUkbxr/OS3jbk30wn7ro7KlEWwsN5E1Eac8Xeqxrp+2g6S+8ysSCVcmnTg/
+JZoNNCJI4my6wN39Vo4070m1hyj4JTVz/V6SFGFn6ssSgkrfNPLz+6+2lGsP/k2S
+2FByK20cjGTVktsXSm54lujU5Sb4Matlomam/hWRwgMC2emrLnkApE0XpKobBHg1
+5D0S4qBccKGaz0/zcCFvt9wCyVn2bx7GhGSNZtggw8lJmjYV6bXVF/G4hm3RLl1Y
+6XD9RvjEZxLgfPHcxYbm7hTvlw1j6kE76rAqFJMXQpQvuw+Ze37PQK/ABBo418I4
+zNDQeMw7iDlxdiLg0ylWI+6vua45cRUW1Hu2JbLfWs6/7pOLMSswrYz5I5N6gZJk
+c//BtzkJwe78Bft1bYDv4M8WpbUg3x5KvzU2K4qXPmlpcVw4L/L0VS5ADQeU1Ubh
+joUHTk4sedh0ge+lYaTI8Pj3gjsL0Ynxl9WIlDvr7ggL2kxuCZbDpyHojaPDu0cH
+4Qxp1AJos6vGAYDBH5l7Pe04as+BswfEPOeCW8YykTCT6pM16UUY9mR+ZIdZMiMU
+dMt8UbeF0qB3jyjER6ALP3K5v2Jx8GPWV52GbD9oBoFkguK2scM88EWcIEWa1sAC
+2khDcVRBsA27sVWGu+QgdEYQQFEH6oPMG0/NBE42T5FSrnFXtRH5061uEt5w3ROg
+bgT42rD4G4bP6Wsa6JCNDwTNXhIWujiTVkchvSuOGXV70y8cI+E6Hw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3.pem
deleted file mode 100644
index 3183499812..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=keyUsage Not Critical CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICezCCAeSgAwIBAgIBHzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEwxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEhMB8GA1UEAxMYa2V5VXNhZ2Ug
-Tm90IENyaXRpY2FsIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYlAJy
-nnvLn2glPjCkqnWzCC/bxT/ypoeW3spfvzi+AQuwM+d/bNL1ZouAnps7JPpf4VHp
-ZvSGjeCgLpCvDjnUP6tG/hkQBm8CS9vaqg/65FoI/MpSMHXmVJ9CgUjOkjHp1g47
-2AYniw5lRztaH2tCN25WqZFzar+vdhQG2ZkJNQIDAQABo3kwdzAfBgNVHSMEGDAW
-gBT7bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUzyqhpf1C4jO8MypNmHOz
-2PtVvNgwCwYDVR0PBAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAKS4oBKhFhU5vxr4Z547N5er
-YrYR5JU75QnGUZjv7JYCXydlJVuvIhZptrzG/wevhz2VgNSbk/wp8Uw+ra3eqqlq
-QjVFQukh0F4GKMBaiFZ1HUEGILLIpeEq0Pn70Q8EE0H1RsweW1P30qaXZE9050m4
-7h+is62/EaaT31RpTb+G
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid keyUsage Not Critical EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=keyUsage Not Critical CA
------BEGIN CERTIFICATE-----
-MIICkTCCAfqgAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGtleVVzYWdlIE5v
-dCBDcml0aWNhbCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGQx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE5MDcGA1UE
-AxMwVmFsaWQga2V5VXNhZ2UgTm90IENyaXRpY2FsIEVFIENlcnRpZmljYXRlIFRl
-c3QzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQifnsA6fOmILXLNZeSJEf
-D8ON1YDI4FjDmGqG8Ob1ITgAWPfxJcWgQXqRwzn/1NXj0faYKeVA5j6VZxSCP7Dz
-D6ZCeGxjgcF1lNF2dqZh268sSsW3ZiesNQ+wG9zaF8YNWvL8iqICgMrjVqdiFbiD
-X8N15gROcCA0lPuKiqlJlwIDAQABo2swaTAfBgNVHSMEGDAWgBTPKqGl/ULiM7wz
-Kk2Yc7PY+1W82DAdBgNVHQ4EFgQUHw6xfNRi0j5jpx9vVSQlS+45UuUwDgYDVR0P
-AQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUF
-AAOBgQADtx2GVXZR3dxm4aGGrvmtdkDkj/20o+75/jzMHss7prirQQdShNtqL02F
-TL2y/PWCf6QbDQgcakwPDez60a7reZ02JKUtwKCa4VJf86gy3BDKKhm+msihYgCj
-ZzkYwS9CoF3dRup5ySq6dvAU6gVzPRJZKOf3MIM/3Vo9hUtmVg==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=keyUsage Not Critical CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:CF:2A:A1:A5:FD:42:E2:33:BC:33:2A:4D:98:73:B3:D8:FB:55:BC:D8
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 3a:4d:11:cb:3c:14:7e:17:ec:4f:14:72:47:1e:98:fe:ba:02:
- 2c:79:4d:2f:5d:e8:71:fa:35:d3:7f:26:b5:27:1b:23:c0:12:
- 8d:c5:9c:f7:e1:96:71:d5:7c:6a:e4:40:ed:7d:46:28:a1:91:
- 99:ab:75:2b:61:a5:c5:4b:d1:63:10:bb:95:bb:4c:ee:a0:8a:
- 8e:d6:65:14:3c:86:f2:11:8b:0c:4d:6a:3d:e1:a9:e6:12:28:
- 69:87:1b:eb:e4:9e:d1:45:5c:dd:2b:2f:6e:55:72:e2:69:cd:
- 88:84:b1:c5:5e:86:44:10:4f:ce:ab:a4:b3:ed:c7:03:58:84:
- 84:cc
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGtleVVzYWdlIE5vdCBDcml0
-aWNhbCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUzyqhpf1C4jO8MypNmHOz2PtVvNgwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAOk0RyzwUfhfsTxRyRx6Y/roCLHlNL13ocfo1038mtScbI8ASjcWc
-9+GWcdV8auRA7X1GKKGRmat1K2GlxUvRYxC7lbtM7qCKjtZlFDyG8hGLDE1qPeGp
-5hIoaYcb6+Se0UVc3SsvblVy4mnNiISxxV6GRBBPzquks+3HA1iEhMw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3EE.pem
new file mode 100644
index 0000000000..6a4f159be3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidkeyUsageNotCriticalTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 19 E9 F8 16 84 3B B1 8B 16 F5 45 FC D0 35 AA A6 0C 8E E4 E9
+ friendlyName: Valid keyUsage Not Critical Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid keyUsage Not Critical EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=keyUsage Not Critical CA
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYa2V5VXNh
+Z2UgTm90IENyaXRpY2FsIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowaTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExOTA3BgNVBAMTMFZhbGlkIGtleVVzYWdlIE5vdCBDcml0aWNhbCBFRSBDZXJ0
+aWZpY2F0ZSBUZXN0MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALez
+B7zAQcz+cwTNzcRbXADc2II98d2UkCim1OerlAh4XSPePFqkPmCcuijOF1vTFsxc
+eUBcnBHO3iH6Dw6LBoJF8f4slPhGVzTtmXjD/0N1/x70ypCbNHeCv1Lxfn/M6Ufi
+bYEYqZnL4D9i6pRWU6UcjRRWfoX8zEyTdShPLhxIUovvEwStmd3ISQvgJKLEbAJc
++EEPA1k/bcXJEf3VVhmx0kjNTqWXJP+X+JfG4i1AmyhwRDbXdwND2lzPOizThff+
+4gBaxJB0cdW7wHwqrnSTQmFOB4vSkgQYFHxgBplJ2Eh1t/AyokjI9imz06VmfhFk
+kyuRvGqaxBD1W6zY+bsCAwEAAaNrMGkwHwYDVR0jBBgwFoAUwZARStm0K8Vwfs6M
+O2JY5buXK3MwHQYDVR0OBBYEFJ46eWPPLst3JdrmpRlWguBUS9GrMA4GA1UdDwEB
+/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQAD
+ggEBADfZpIsEnc5hM5JwyXKi3HdQMCwHRQvGadMNqh/3A6SSIWJwU5+8WeorwD1Z
+SikyE+AXC/cOfSEksVjrCWY3ezWVF99+jaQFqgE8lcws1LlytaN6sRY7AdEoQUhQ
+r+YawAvNZgbkRRB8LvhWUWK/66N8rkVFJVahJCcfEGzQdNBryag9SQrcqYigfV+D
+Ysob5iuSOJAoGlnAtHVtOwogjfZ1ZQy//P4yJ+IbzE3u0kHMTTqUrIeB1RWqy1YQ
+QTpnFVcmuI0utFmhEDYz7w5ktTQor7cwojxc+NpA8qzvRn6hiIeqemqrYIFAzhc6
+EI38iiO0ZAhjvDBgsERMLmKUTR0=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 19 E9 F8 16 84 3B B1 8B 16 F5 45 FC D0 35 AA A6 0C 8E E4 E9
+ friendlyName: Valid keyUsage Not Critical Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5BF897CB9FF0385B
+
+P7aeEOOsC7LxvND9OuJqHbesUzf/CpLspAdxh+2XwRPZxLxbATA5FIQX7o75EyBT
+JoLMh1eBm4n7nMW9o8O0YX6u/1LpK7+T/yEl4S65xJNw/gcdXTvzYY1VSN9gCY9d
+MI2XZuLpXGNcSTnAIqE1RRGJ0aPoejR8/fIR1++qcSYUtPwKn5dzMo3JkT4NFU9J
+Ux+YuBrHLo+hk9ymZ/MBSb13Vz8sxpNJo2W/zidhrvDJRa1qmfAtSXsdu60n7O6y
+7gspxrOsFeORgJUrW9ITM5QdKBZNEgBED5IoB+fdRI0FwF5HGziEJwYujPYcldeo
+8T/1yNzo5fZ8HdINL3KJYMpFzo2EnE7ZCxhGEjtUC4UUSfPsdTi2mlNRVK2hQ+UN
+Qc30hicM57tne1Zth5ArQCYHV9wM6bOIzdERJnBD8bDlyXW2iDhTbW5BMn6wvjGi
+7zdot+zxlsed1hHdyHLkiZHxTlKHI7hoMjuwROaTNRcnARl3aiStMLYoBvk9Y9Bw
+ZFivyK/b73C+jXAs8TmBLfJYqGkgGwB/CKbSYNYpm/F1j6nP20zvwetwr5TqlNze
+v5pV2jN+ZdDlqicjmHcLspqJJrtstD/PiOOWyxT/5jUmFZsK0tgnDUysDhwdoRjO
+tdMBqf73SZ7HVFVYmY2dajBhsuieOg5aNts5vWlp9ENxkCnC+lSxPamXBQ12EDtd
+Z8QTEwPndaXoS/NZ4O+LFyuCRaB9D0V643jAaVmEb+MHii5oihPk83a/ZcH8aoLh
+GMkyn1UwVoKwERGcGvYBXZt8Tb4FtOkOwM61hVs3S0lokQ/kaLl83rygJvdsiiRu
+mah/PKWVsKujJ4P2YyXwDmDTNO7KNYZU/O5E2fRsLxFP+qAwB4GpuDDcbKuIUQyz
+gu4vFCxrWLRZC4VW8B5oYhs6JiErVhg9bwbKsToUvyC+FeoyJvxnKiE/jJ1KeH1X
+hEPhPTu54YNaE+ccHTXDp5fDJboSdz0nZ2Ktjecg3UEBVayaaw/zJzUE0oOF1fxG
+Iu01RTEH+0Qx+QPrKHfkwSiD9ZXWOY3bebstjNrWF5sm5rtHILiTU4q830dyKFxl
+KltqXgKzRHBkMFbJNVQHQ6FdZ5e56KFUw96YymDWspTklrP90xbesOPPpTKPxFeV
+XPwN44tVN5j8CZIIhf0lNVRJDGBMNuT0ffr6q7poqb48nGfkoge1g26h8Bj1L/1x
+yc0ceL2yWXiEeFoUz8XU3NEyLSJlBwTFW1lHz687CiqkwGaliNon+N7Il0wSgbRc
+iVKom2OBQAih5aJId98xVg7/jpHq2Z1I3mrwq3cTtlXy4j9eViXKSwgsDSK+G0mJ
+HPRDF4Omw3fIf65M7BcuiAs352AQnlu5wG/+10YL31l1OW3NN8TOKhor2RX8+JXP
+sMiEsJhwyBy0X3LKIlKwaQuQQwcwvvMzBY54hMocqUJtSkr0+pX5TniAIbf6/pcS
+jDdbz9dakfMNVB+TFnWd0jh6bAYLLf6jhH9034PDc2vJCThAZor6Kw04uccpktya
+3O3dOVeQpjhKfQ9nOiqVoF9XXPAHIUEuDXRFpuSAPVwbSKPr2AnOng==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsCRLTest13.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsCRLTest13.pem
deleted file mode 100644
index fc640e8409..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsCRLTest13.pem
+++ /dev/null
@@ -1,112 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=onlyContainsCACerts CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfDCCAeWgAwIBAgIBTjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEoxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEfMB0GA1UEAxMWb25seUNvbnRh
-aW5zQ0FDZXJ0cyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqP8z3Y0v
-UCVXIVXCpbr+dcdoZFi0UZQPvl77hqqVORSs9FefV5mTeuoDDfhtUYa+O6Wzh2v/
-Yzv1MzPQzePG3eho/6CLs4pzqVWZDzYTG6OXubjPvYT10WykqfaWuivcn5YxbHuA
-cRitNsBAvY1Nq/kPDtsPJz1t5+PDRVO64gsCAwEAAaN8MHowHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFPOhB0Zne+mPWavrVYaTyKzk
-VbcYMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDGkMUjQFfto4SQpRJ2fAeU
-qXp2dn4kt+s/ITPOIykUFaybQ6eaGRcWN4kTi7IufbSeI7lmaa4SC+bq14tfSf/w
-gJSpwu58pIbPHKN0IgB+9S8eRS8wmB4HcBflmNZz/NX6wJzwJt15ZC+gek+eZGUw
-Qck6L9wt5i1wMFyRwBmAHQ==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid onlyContainsCACerts EE Certificate Test13
-issuer=/C=US/O=Test Certificates/CN=onlyContainsCACerts CA
------BEGIN CERTIFICATE-----
-MIICnzCCAgigAwIBAgIBAjANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm9ubHlDb250YWlu
-c0NBQ2VydHMgQ0EwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBjMQsw
-CQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxODA2BgNVBAMT
-L1ZhbGlkIG9ubHlDb250YWluc0NBQ2VydHMgRUUgQ2VydGlmaWNhdGUgVGVzdDEz
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCleZwZx1DWjtQUI6sccnzSSv3J
-scTabLlHXVLbXj57OzT/9XuVVLkRe6ZB95/CCO8YM/bYdtmJEwtT3S7J7jaSI1XM
-NBi9E5Uc2y6RXOEZ4dL8LFJjZYIQNbRUgg2o5rtJ55N7Hp/uA5zJYKH9wtNBXAlj
-i0eULWMWi42zHc/w1wIDAQABo3wwejAfBgNVHSMEGDAWgBTzoQdGZ3vpj1mr61WG
-k8is5FW3GDAdBgNVHQ4EFgQUQrE9JN7MpRBHp0VYS792Fg2IxOMwDgYDVR0PAQH/
-BAQDAgH2MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/
-MA0GCSqGSIb3DQEBBQUAA4GBAI7d4izaGul72X3r0YD8tjwHlxMMBg7/4nO6PrJd
-+blNKJwn/eqMJdekiTWjl2E+PKS4nBCBSeFeoboUHLnQ/AHevzxnJiEUK7otOXim
-UFRLlktEMASIbfUjiJrkwmL6JxvDXlbmhJNVlXZI6bRfAxi2XXt6o+ZO0VAFlebG
-iga9
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=onlyContainsCACerts CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:F3:A1:07:46:67:7B:E9:8F:59:AB:EB:55:86:93:C8:AC:E4:55:B7:18
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0....
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 54:27:ac:fc:b5:7a:93:93:e7:f2:e9:63:f7:52:ad:20:08:4c:
- 52:08:62:e6:f6:81:71:1d:72:f4:1d:bf:db:06:52:d6:4f:8b:
- 86:68:4a:ca:01:4a:fd:b9:7e:5d:7a:df:48:67:36:9b:31:12:
- dd:13:29:b2:8e:b6:ba:c4:20:31:57:4f:7e:c6:d1:3c:0b:e5:
- 1c:a0:c2:15:c6:09:5b:77:ca:95:37:31:7d:a8:08:4d:ae:60:
- 4f:3c:b4:ef:92:9d:f1:11:5f:a1:1b:2d:ff:e6:2e:07:88:4e:
- 2c:88:54:b8:e1:be:4e:6c:22:90:0e:37:0d:b2:8d:61:21:46:
- 36:29
------BEGIN X509 CRL-----
-MIIBVDCBvgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHzAdBgNVBAMTFm9ubHlDb250YWluc0NBQ2Vy
-dHMgQ0EXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgQDA+MB8GA1UdIwQY
-MBaAFPOhB0Zne+mPWavrVYaTyKzkVbcYMAoGA1UdFAQDAgEBMA8GA1UdHAEB/wQF
-MAOCAf8wDQYJKoZIhvcNAQEFBQADgYEAVCes/LV6k5Pn8ulj91KtIAhMUghi5vaB
-cR1y9B2/2wZS1k+LhmhKygFK/bl+XXrfSGc2mzES3RMpso62usQgMVdPfsbRPAvl
-HKDCFcYJW3fKlTcxfagITa5gTzy075Kd8RFfoRst/+YuB4hOLIhUuOG+TmwikA43
-DbKNYSFGNik=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsTest13EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsTest13EE.pem
new file mode 100644
index 0000000000..30fec0a7c4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlyContainsCACertsTest13EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 9C 29 A1 97 81 CF FA AA C3 77 FB C8 F9 3F 64 D4 2C DC C1 7D
+ friendlyName: Valid onlyContainsCACerts Test13 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid onlyContainsCACerts EE Certificate Test13
+issuer=/C=US/O=Test Certificates 2011/CN=onlyContainsCACerts CA
+-----BEGIN CERTIFICATE-----
+MIIDrjCCApagAwIBAgIBAjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWb25seUNv
+bnRhaW5zQ0FDZXJ0cyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MGgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MTgwNgYDVQQDEy9WYWxpZCBvbmx5Q29udGFpbnNDQUNlcnRzIEVFIENlcnRpZmlj
+YXRlIFRlc3QxMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANX15GuX
+OGqR1Az5/3Eya+5k/mszVGRtEA4BxsovHQrt4IIP1MjoRrB6sL2Gxjps4vzA4Aw9
+S6LxUJRaw1L59qRWJcdrTMnI9Jzqc0t9WanMqb7CTvlTQN86FO9KEbmc3HO8YKnw
+OySx6uXgAA/X9+AsuJhlwXH05K0sTlqzP39PiXupl3S3pqVAPHVKpjY1hizfABQQ
+ugfMk0szqm5ZqUbtRoRsTI5pWxe12UDVN8eclHUJVPng220tUQY9vaHesjIpcrEg
+p7KBxmLsbAdnoVs3JNYGPTI4wgvAOAlFxIpTc83l8T214BD5w65oQdDYVcRo37+3
+bqRyWAuLy3qYeX8CAwEAAaN8MHowHwYDVR0jBBgwFoAUJTjDrsotdXpbTdTAA5KI
+EyLHbFQwHQYDVR0OBBYEFDtDT7cTpkfkonYlzo4kLdOETiNvMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB9jAN
+BgkqhkiG9w0BAQsFAAOCAQEAfmMUoBvJy5nZ5eICleksT7UiUJ9gyi/uxAYn1NN4
+o61FMj0lyattfHD6gyFFVHW6BrEF2vbDXKug9BWuJI+3xLOIxUsDQ+IP/0juxu9O
+iggb6f9zg1IqmX0YEC05+4MPEidRKLsZh+OYlpCtjCMj94XOFWeM8gHJIhhR17oz
+7VG68tKWMvoo8Tfo4nuYkjQ4nFwAcMKIctL641sxVzMEmDgv9x6oJs/irSqKSLSZ
+pFJrYBYiOU8/GTOL4rlOBEYL4gXW4PJs1HXft761W7Bpwd9SVJA6fogM28XuWr8c
+Gslx+k60FDk0HfYsxw3pTlSubTKp+oYiV7xQgcgtHWLkZA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9C 29 A1 97 81 CF FA AA C3 77 FB C8 F9 3F 64 D4 2C DC C1 7D
+ friendlyName: Valid onlyContainsCACerts Test13 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EEC5957D68BA54BA
+
+qrY9d5ZVIowhv+2U9J1l+oI/xmuDX1I/6K8ba3cDGtFuYRHp5CHen3LwiqNecqz5
+Q+b03EEk/cKfIFIRBv/iuH27N1yUEQO/zWc2ShxRpcjO6vynx0vBFp+e+2f3PAs4
+1Bqb9mfP3lct0ZznaU/nIXqfTSpFp1cYAQvHVYOr4syFVMFr0hGlXWeliQqaEdlr
+GamfWs9NkieMQCmS6OXJxTQBgu9CKE50K9J1OeVGy+qR9heSWfx0q10vR+Ic29K9
+LHYVWGtLAbgIS8NL9ugwQNnJrRVd7WNnnwTlR1R2+vhAvPiTo16FKIK5pjCVxdFi
+xuBplIVwUPksqoL4uzuQupGHwBpY/6L9SfulBfBmpc+JEARvhj18sSSuYOxBE/5k
+0u1AFc5ltaO3LggseB3yQJAlBGPzqn1t8AQjoXnvo/T0hocYApwlWwXfDI5NE0T+
+T7oyDMed+EyPfegs5Ld1HDS7B5MMsKsTeooxdomAvPjnJHK1tQsVIYRdJ53XsFo+
+0aX7ClDc3G8oK0m97gogQghYdCHAFD4ts1gewHozUUjpxig8SmJ7FPqHvcwXA74f
+iXkXUiPPENhVE4fuydzrfB7SQ+5Esbk6bPb88GHWFod9HnRVA0n5yVg47/pTB8DL
+9wz5DkN/sMYyyE0+3rmsvT5/z0+4GOinV0vWpnMAz6t9huMg2943kLQhEIRXszIp
+PQhA9ljwCFqjv7xl3nbQUP2l6nQeHN6YMzk/0tWAsLR8sbp4NLKvGWYBG4EVrxzQ
+/Oee5ubzznx0loO5QOvfheElAuyRZrWZPxeFajgT1h4UZNwORfTSWWZ4RYk+6GPB
++p8BV3GTpM80CF3O5syUik3zw1TxRgMvr/5mzGmw95Jlr941cGWTyf7OuJjCpL65
+jt7rv8uacSCbu7UQrh4gqBlP/dCUAs2QZaO4dW55eJBDOzDsxgnTqon8loaJlRQc
+mZj+BZ/H+s8N9hazexRF5RLhbcB+p4ef4+5YznMXRphTnhbNLmQh0HXxdliKHmTO
+D72PkEIFJMkkAKY3iONyRCUaYJCajlBo2TiRLMspRsmTszzqDYM5t1MixbHeXLBv
+tPNSdrjgR/jwqMKaFNAjI2EiSkkZpSX6yHwHpSj9WjSRcLPhVJwFpR+wmLDG2tHU
+aC++rFQCDU/blZCkasHZNwB23HEZuF5oVTj59V/L2z/JqptrzxpWzTMfx8xOOLJd
+cQud70en29/mfzXYAe0M2YpIoSokkMOliE0W3DblFcivo6U6oZEbC9nI3otIazZL
+brbcANPIgSPzCtvoQj0ibtqcyZ7QzabzGG2Uemraqmt5HjVbAcPncDm78TB3xdfb
+W0O0MQ8I1lj/o31pvO5Lzd4c4ae57V+gkIy285CTEKwk/BYzujQYbzRuPWjWQxqS
+tZKnRtEfQzqQmqgLeZWwg1yLns+Cl8Zikv5vixQ5V/R9jASohRFyU5DFyj0fR1rI
+EvBO5bRHUU/35ExppmVuY8eUsSwBNR/XG2dFQwLvy+Q29e1TTXsaw4wTmRCJOViL
++eAyUGnv4XKUTr7nKIF4G8tCulMLV9DWChagc1ZJVdFKhQTwN1sicQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18.pem
deleted file mode 100644
index 580d919aa2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UECxMTb25seVNvbWVS
-ZWFzb25zIENBNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApawx8YRMPlMQ
-024rS3sld90L6veeiaILQ6LHaLsGJq3VdzR86qrSqOOIC4riSla8gYRwgMxS4ex2
-wjXsRFQbvsG09PcFyRJKJ0NLsY8FiVdShUDwLEohR/cdfL4Z+iCgZdY4iMaILI8a
-MHiBRffd7isOjbgUd8JKQ6DM4ercJksCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFD++QPH3awL7sFnDAKRa4JdUCOkZ
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAzmsqTCqqsyknqgNHYbj4aH461
-hKTEkZRpMSUHjJwKJWFK4fzqdC8DDlCw9rfmNld7RwxcC3/o0J5v3T4KG3C4s9Rr
-eVSmm4Kwvgjmj0tsm0TQbG+B4uLqaFAAmlBTZPYl9ABodUKUP2eKcAL7f98INanN
-/veMciSwQ7N4Ku7Zjw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid onlySomeReasons EE Certificate Test19
-issuer=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
------BEGIN CERTIFICATE-----
-MIIDYjCCAsugAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAsTE29ubHlTb21lUmVh
-c29ucyBDQTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBfMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNDAyBgNVBAMTK1Zh
-bGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTkwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBANbeMMLH+IhNKpE0W5mNqU1YnGXZjAhFNF7V
-hMVHkKyGO+6oluHVdrzxL4CoonF40mpNZdCyVA39nKEW2HV1KB2OQ2cjjOpS+n6l
-1eds3MeBCa3z1kzPbsqkkTH+hdmkHnn7gsQNElk+mALZXM/UC+kIRlHIWSmR+FvK
-+gqFZw3ZAgMBAAGjggFEMIIBQDAfBgNVHSMEGDAWgBQ/vkDx92sC+7BZwwCkWuCX
-VAjpGTAdBgNVHQ4EFgQU31n0/apTtgdLpf3g030Om2i0nuswDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATCB1AYDVR0fBIHMMIHJMGKgXKBa
-pFgwVjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRww
-GgYDVQQLExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgQIFYDBj
-oFygWqRYMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czEcMBoGA1UECxMTb25seVNvbWVSZWFzb25zIENBNDENMAsGA1UEAxMEQ1JMMoED
-B5+AMA0GCSqGSIb3DQEBBQUAA4GBACKZfydulpOlfYkHfr+kYAFm8mWYkFty5+82
-g7UQ34pUUcNlmXy2LAvyOnFBy9LJGLpfyqbaZYLyspSseZrYTfdEYRdba4FWLwEp
-iCqeyzac+D1Hr7uRFVocXyd1ZUKWhdA0gfkORdmeNO4HjY3D1+y75qjNutoqK9et
-6C9d+9jH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0b.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL1...`
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 0c:c9:cf:ae:6b:51:3a:d8:ee:4f:85:3b:a7:18:30:00:6c:cd:
- 0f:1a:59:06:50:fd:75:49:44:9a:af:71:a5:74:ca:25:02:e1:
- fe:c2:0b:15:f4:db:0a:8c:7f:ca:9b:de:cd:bf:1a:2d:3e:10:
- 1a:a9:4a:9b:a9:64:75:01:1c:dc:26:b2:f6:ab:2f:d2:7b:3d:
- 01:f6:fb:64:a4:c8:53:65:b2:80:5a:1d:22:e7:3b:9c:12:92:
- 96:01:0d:74:83:d2:72:c3:a6:34:cb:54:bc:75:c4:34:12:c1:
- 4e:40:2e:e1:28:d7:ea:6d:c1:9a:4b:80:dc:2d:7c:7c:a5:a7:
- 28:75
------BEGIN X509 CRL-----
-MIIB1zCCAUACAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIGgMIGdMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG4GA1UdHAEB/wRkMGKgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgwIFYDANBgkqhkiG
-9w0BAQUFAAOBgQAMyc+ua1E62O5PhTunGDAAbM0PGlkGUP11SUSar3GldMolAuH+
-wgsV9NsKjH/Km97NvxotPhAaqUqbqWR1ARzcJrL2qy/Sez0B9vtkpMhTZbKAWh0i
-5zucEpKWAQ10g9Jyw6Y0y1S8dcQ0EsFOQC7hKNfqbcGaS4DcLXx8pacodQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0c.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL2.....
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Affiliation Changed
- Signature Algorithm: sha1WithRSAEncryption
- 3d:11:d9:b5:4a:98:2e:f6:01:84:ec:e5:d7:d5:20:45:06:18:
- 19:5e:18:1b:89:27:c3:fc:7a:ea:a7:3e:3d:bc:ff:26:f1:69:
- 90:73:a1:2f:d6:0e:82:36:1b:f7:98:7d:26:2f:07:86:05:58:
- b4:5f:ce:84:6d:ef:4a:51:e8:40:4a:51:b2:57:46:b6:76:e1:
- 8f:0e:b8:03:16:88:72:c3:88:74:74:76:38:1d:44:87:88:c2:
- a5:ce:34:cb:a9:bf:a1:6f:e9:96:e3:a7:ab:3f:be:a5:60:b2:
- 4b:e2:bb:f8:1b:84:4e:eb:69:ae:01:f2:5a:e9:78:9d:ac:38:
- 45:4d
------BEGIN X509 CRL-----
-MIIB2DCCAUECAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAxcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEDoIGhMIGeMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG8GA1UdHAEB/wRlMGOgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwygwMHn4AwDQYJKoZI
-hvcNAQEFBQADgYEAPRHZtUqYLvYBhOzl19UgRQYYGV4YG4knw/x66qc+Pbz/JvFp
-kHOhL9YOgjYb95h9Ji8HhgVYtF/OhG3vSlHoQEpRsldGtnbhjw64AxaIcsOIdHR2
-OB1Eh4jCpc40y6m/oW/pluOnqz++pWCyS+K7+BuETutprgHyWul4naw4RU0=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18EE.pem
new file mode 100644
index 0000000000..c0ee2e1cda
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest18EE.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 42 A7 D1 D9 39 66 A1 A3 50 5D 99 15 05 9A 61 3D 4C 09 43 CC
+ friendlyName: Valid onlySomeReasons Test18 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid onlySomeReasons EE Certificate Test18
+issuer=/C=US/O=Test Certificates 2011/OU=onlySomeReasons CA3
+-----BEGIN CERTIFICATE-----
+MIIEBzCCAu+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UECxMTb25seVNv
+bWVSZWFzb25zIENBMzAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGQx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTQw
+MgYDVQQDEytWYWxpZCBvbmx5U29tZVJlYXNvbnMgRUUgQ2VydGlmaWNhdGUgVGVz
+dDE4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4x8zxpPGgnBqlIWH
+sva5Yg5I7d0lcKVlJv4pTMjnEXaGboFcTOBu+ZI/ECdX1hLTA+9JLEivrZU996SW
+gWD7JCjq5ULOzD3a+fgDColZY81TP+EfcwWOP84qQHZzBj1LrNczk/nyla4s4aoA
+z3//CHmz6DEEKNlIDk80MLSagvUZo/LJ6QyKx1BecsP8pf6mDxIXpHgf9LrJ4aWz
+xRPFy+Zmoizo3BRQghRGnCTo+fWNwPOJ8nSRTEu926xMiyu2qExL75Ng2dsaMSd9
+dFlJgU86pp8oYfMsFKJal70ofB1QeqpszkAgW+FOEp6R2iabHTWxrYW5aJ7DTyjc
+0SkD4wIDAQABo4HbMIHYMB8GA1UdIwQYMBaAFC0kt5eHLO7aHL7el4Qbr6AVFr5r
+MB0GA1UdDgQWBBSCHuiLoRbi7SpBZu52PliT2MdEUTAOBgNVHQ8BAf8EBAMCBPAw
+FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMG0GA1UdHwRmMGQwYqBgoF6kXDBaMQsw
+CQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoG
+A1UECxMTb25seVNvbWVSZWFzb25zIENBMzEMMAoGA1UEAxMDQ1JMMA0GCSqGSIb3
+DQEBCwUAA4IBAQBMDyLf+YjZxO+aN7TIp70Wm8qKs5gEfZQEzKBODxprp9iImKb4
+4PYrLPt3hjUFa9dIZeH/ewoeXdqjIfLwqFZfHBWsNMWXiKOa+N7k/XcTclX1LSPT
+h5HkvbhomN2rvwpUgbnUQKD4PddOfTABJtVzJJwLvY92cgu5/qxwkreeI0FwlFx4
+bnMB6AoCV8jNGlEAVMTrL4YKGVGFYSdWthfbMRvtR6OGfQ1/SLQZeD+7Tzq6dtdV
+qAuRUb9BXemkK85LIcBhvVSHJEmcGocOjKAs+VqxBJlNVcoVUoFDX17/PwInbQmO
+C35YSeFdBh6FNwbalsWkzKl5PmjH2XJCP4Zi
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 42 A7 D1 D9 39 66 A1 A3 50 5D 99 15 05 9A 61 3D 4C 09 43 CC
+ friendlyName: Valid onlySomeReasons Test18 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DC1A964E9CB7CB53
+
+XWgNPVxoNKAvoa9qvAqymT5p8IVNC09tbQVnV3TTf4ZBX/3qa/apfmQ8u/T0Vibr
+vgYMBwt9L+j4Oujyw9+o83ziUlom9Reor7KmFSO0vYJOIgxPIkHTG5+IXiRSO8N9
+W0jhMRWuHFlpQFXF8AR4+dPAa0KVCzfBGuEwksmmHTYhVboYwN1FrQwxL5Mua89N
+PCUucOWRXrARA0LqA5tTeFGHU3Ou1SIdvaGDxRYoRQjAV2uTQuiILxIPUUOCZR0j
+qE3vZNRW781EgnHF2lVrXaTIgKJXmu0owHS0e/HNTpno4r1JLEBKOdjwgbnilZOI
+c4CWnXi+6CLmLP4rw1QaV/gV+c0uVrPjCCy/1kD2dEF/D7rOfSc/Il6aR5wD6Vsk
+sl3pMpKuhX3YxDShDg6rHp3n2YPRh7x6/bPNbGB1WuXOGFC0SptulTzY1gKW45Nn
+wFHYkjmPDadLhU+5HwpzXeXhJdMHCW+z8TsTGjNIQVRFlbX4PRxWwK8n1FPl5+k6
+1pCZZjdcFXUXNzNXqMXSxd8/7ilnVqXXi1unaoqFW8Zfp8e7FR8ltAUuJL3jOjV0
+Tw7K63B5KmtcpRn/O0J/me+d15343F0QaglJpn3iakNyutyu5zzAzZS4KvBRIXJg
+QyYfm16D9p1AkNOHq7g99N7wnA15JLxqOuE+YB26LSpcRZIker5cGsAfQDWliqOB
+vX86jMET4qPcOmApPaSuRolXlBm7kWjxv9iltr/nPJi1RJOZkfBuGHJ5V+vuNpWJ
+y87y5sgCkGakoG7NASAQQYKHhdKie+//3AWaaxWqr5H3jzUEtaZ2yyqvMmMOle/K
+ePna6WyHQ8a/CQBypPGp9adWO6oUNyDIYbNbq86bw5Eor0JvSQIBWany1Xlzt3Qg
+J6cPxBe4nEktHzv9+bM0fRb6R6mHbu21MQ7JEPoF316E++PM8gC0Mt0R37dRSEvv
+Q+Yy3FNArDeqRdP3BcVsbl93zPz1Su2uyJo8h+o+YCEao48NcttOcMkU/wkSyT0y
+OXvi2YotIsAkryR0ZvXcfWkKl1kt2qBR7qOvVedWiwgeIjyytgHi9PAPqAYw+Aia
+ZlGRPaiqCIEmwu2HiJ1A5+lrW5vK6UWtwrWM3XJKjcPSW493auFURyAKdA3jvhCu
++7PEV4m7AksM+N+rjObGFbonEIqTov1cIj+S4DqnOpOvc0LEvNumIY5iZtIZrkDT
+93JQODsyGgs4mnlV7BFhWiGaEIhOV2nSANz2VQc7mN2RyUdajg4nTgCsTK0j7OVb
++aFYXlJ9KB4484n4BRJ8LOjjGpsUegvVqt2QP56YyI02Du13YPCkzIjOUA4lMWRk
+q52k69X55d8kI+EE7Sn18Veo80Idq6vA9wlYzk16hg3cyI0uEpwtbTNF5j/PG1yf
+IsMpj+KJPDx+P9PNZC7fnb5J9ok6yxy/G/GOTvLuqHUZtoYhSW4UL3aRwzs8hgTP
+n/1Yg4GETmNRQu06tgrwOIa6iyXV6ulsFnn1J3jgZlbbAXqyP2lZR5M9lQn4oPuy
+8AdX/QtJJzqjgWD0GUYWCg7l+rJa+Hqqwr2U0kz8t6mS2HTPVtutUQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19.pem
deleted file mode 100644
index 580d919aa2..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19.pem
+++ /dev/null
@@ -1,167 +0,0 @@
-subject=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIBUzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEcxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEcMBoGA1UECxMTb25seVNvbWVS
-ZWFzb25zIENBNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApawx8YRMPlMQ
-024rS3sld90L6veeiaILQ6LHaLsGJq3VdzR86qrSqOOIC4riSla8gYRwgMxS4ex2
-wjXsRFQbvsG09PcFyRJKJ0NLsY8FiVdShUDwLEohR/cdfL4Z+iCgZdY4iMaILI8a
-MHiBRffd7isOjbgUd8JKQ6DM4ercJksCAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zU
-LYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFD++QPH3awL7sFnDAKRa4JdUCOkZ
-MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAzmsqTCqqsyknqgNHYbj4aH461
-hKTEkZRpMSUHjJwKJWFK4fzqdC8DDlCw9rfmNld7RwxcC3/o0J5v3T4KG3C4s9Rr
-eVSmm4Kwvgjmj0tsm0TQbG+B4uLqaFAAmlBTZPYl9ABodUKUP2eKcAL7f98INanN
-/veMciSwQ7N4Ku7Zjw==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid onlySomeReasons EE Certificate Test19
-issuer=/C=US/O=Test Certificates/OU=onlySomeReasons CA4
------BEGIN CERTIFICATE-----
-MIIDYjCCAsugAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHDAaBgNVBAsTE29ubHlTb21lUmVh
-c29ucyBDQTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBfMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxNDAyBgNVBAMTK1Zh
-bGlkIG9ubHlTb21lUmVhc29ucyBFRSBDZXJ0aWZpY2F0ZSBUZXN0MTkwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBANbeMMLH+IhNKpE0W5mNqU1YnGXZjAhFNF7V
-hMVHkKyGO+6oluHVdrzxL4CoonF40mpNZdCyVA39nKEW2HV1KB2OQ2cjjOpS+n6l
-1eds3MeBCa3z1kzPbsqkkTH+hdmkHnn7gsQNElk+mALZXM/UC+kIRlHIWSmR+FvK
-+gqFZw3ZAgMBAAGjggFEMIIBQDAfBgNVHSMEGDAWgBQ/vkDx92sC+7BZwwCkWuCX
-VAjpGTAdBgNVHQ4EFgQU31n0/apTtgdLpf3g030Om2i0nuswDgYDVR0PAQH/BAQD
-AgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATCB1AYDVR0fBIHMMIHJMGKgXKBa
-pFgwVjELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRww
-GgYDVQQLExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgQIFYDBj
-oFygWqRYMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czEcMBoGA1UECxMTb25seVNvbWVSZWFzb25zIENBNDENMAsGA1UEAxMEQ1JMMoED
-B5+AMA0GCSqGSIb3DQEBBQUAA4GBACKZfydulpOlfYkHfr+kYAFm8mWYkFty5+82
-g7UQ34pUUcNlmXy2LAvyOnFBy9LJGLpfyqbaZYLyspSseZrYTfdEYRdba4FWLwEp
-iCqeyzac+D1Hr7uRFVocXyd1ZUKWhdA0gfkORdmeNO4HjY3D1+y75qjNutoqK9et
-6C9d+9jH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0b.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL1...`
-Revoked Certificates:
- Serial Number: 02
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 0c:c9:cf:ae:6b:51:3a:d8:ee:4f:85:3b:a7:18:30:00:6c:cd:
- 0f:1a:59:06:50:fd:75:49:44:9a:af:71:a5:74:ca:25:02:e1:
- fe:c2:0b:15:f4:db:0a:8c:7f:ca:9b:de:cd:bf:1a:2d:3e:10:
- 1a:a9:4a:9b:a9:64:75:01:1c:dc:26:b2:f6:ab:2f:d2:7b:3d:
- 01:f6:fb:64:a4:c8:53:65:b2:80:5a:1d:22:e7:3b:9c:12:92:
- 96:01:0d:74:83:d2:72:c3:a6:34:cb:54:bc:75:c4:34:12:c1:
- 4e:40:2e:e1:28:d7:ea:6d:c1:9a:4b:80:dc:2d:7c:7c:a5:a7:
- 28:75
------BEGIN X509 CRL-----
-MIIB1zCCAUACAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAhcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoIGgMIGdMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG4GA1UdHAEB/wRkMGKgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgwIFYDANBgkqhkiG
-9w0BAQUFAAOBgQAMyc+ua1E62O5PhTunGDAAbM0PGlkGUP11SUSar3GldMolAuH+
-wgsV9NsKjH/Km97NvxotPhAaqUqbqWR1ARzcJrL2qy/Sez0B9vtkpMhTZbKAWh0i
-5zucEpKWAQ10g9Jyw6Y0y1S8dcQ0EsFOQC7hKNfqbcGaS4DcLXx8pacodQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/OU=onlySomeReasons CA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:3F:BE:40:F1:F7:6B:02:FB:B0:59:C3:00:A4:5A:E0:97:54:08:E9:19
-
- X509v3 CRL Number:
- 1
- 2.5.29.28: critical
- 0c.\.Z.X0V1.0...U....US1.0...U.
-..Test Certificates1.0...U....onlySomeReasons CA41 0...U....CRL2.....
-Revoked Certificates:
- Serial Number: 03
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Affiliation Changed
- Signature Algorithm: sha1WithRSAEncryption
- 3d:11:d9:b5:4a:98:2e:f6:01:84:ec:e5:d7:d5:20:45:06:18:
- 19:5e:18:1b:89:27:c3:fc:7a:ea:a7:3e:3d:bc:ff:26:f1:69:
- 90:73:a1:2f:d6:0e:82:36:1b:f7:98:7d:26:2f:07:86:05:58:
- b4:5f:ce:84:6d:ef:4a:51:e8:40:4a:51:b2:57:46:b6:76:e1:
- 8f:0e:b8:03:16:88:72:c3:88:74:74:76:38:1d:44:87:88:c2:
- a5:ce:34:cb:a9:bf:a1:6f:e9:96:e3:a7:ab:3f:be:a5:60:b2:
- 4b:e2:bb:f8:1b:84:4e:eb:69:ae:01:f2:5a:e9:78:9d:ac:38:
- 45:4d
------BEGIN X509 CRL-----
-MIIB2DCCAUECAQEwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCVVMxGjAYBgNV
-BAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMg
-Q0E0Fw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMCIwIAIBAxcNMDEwNDE5
-MTQ1NzIwWjAMMAoGA1UdFQQDCgEDoIGhMIGeMB8GA1UdIwQYMBaAFD++QPH3awL7
-sFnDAKRa4JdUCOkZMAoGA1UdFAQDAgEBMG8GA1UdHAEB/wRlMGOgXKBapFgwVjEL
-MAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMRwwGgYDVQQL
-ExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwygwMHn4AwDQYJKoZI
-hvcNAQEFBQADgYEAPRHZtUqYLvYBhOzl19UgRQYYGV4YG4knw/x66qc+Pbz/JvFp
-kHOhL9YOgjYb95h9Ji8HhgVYtF/OhG3vSlHoQEpRsldGtnbhjw64AxaIcsOIdHR2
-OB1Eh4jCpc40y6m/oW/pluOnqz++pWCyS+K7+BuETutprgHyWul4naw4RU0=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19EE.pem
new file mode 100644
index 0000000000..ce783f6d22
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidonlySomeReasonsTest19EE.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 23 3F AC 65 5C BD B4 11 55 FA 12 15 B8 BD F4 B7 AA 63 89 68
+ friendlyName: Valid onlySomeReasons Test19 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid onlySomeReasons EE Certificate Test19
+issuer=/C=US/O=Test Certificates 2011/OU=onlySomeReasons CA4
+-----BEGIN CERTIFICATE-----
+MIIEezCCA2OgAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UECxMTb25seVNv
+bWVSZWFzb25zIENBNDAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMGQx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMTQw
+MgYDVQQDEytWYWxpZCBvbmx5U29tZVJlYXNvbnMgRUUgQ2VydGlmaWNhdGUgVGVz
+dDE5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsYaYmevtVXzOSYqg
+VGMWu24TJ5L1gx1O3gTuPBCkQE5QZVa23vo3dDpL2m3SpMJ3kWJuPkIAA4eobyIk
+IYqZCsSO9y6zKfhCFOG/ynddUbglmcigcjzA4uZ8wNTXgV2shFYtxCcU/3Tbr8IT
+Q/bbX9/eMw+8vNtIZdM6MieX9/fwa5WkQJqhOYyPJJ9NfeJmwSnjd6WC5mkA9hBa
+0RqL34l8mhiARM9sO8p7uv2cTm7hKTQ133RhnWX5wwbiRB3H18pG/Ikw+2Fel0u2
+PuI4qXbevmzjL/83sf/unZt8++MeiyUVYSJf/V4yRuRW/kFAOPExJJyCoaZeNp1i
+SGa9pQIDAQABo4IBTjCCAUowHwYDVR0jBBgwFoAUvmbcHgwGO/bTiDSRUyaBDWgX
+bskwHQYDVR0OBBYEFORDdLxa0SqQZuQsnjKT0Gwdhm7KMA4GA1UdDwEB/wQEAwIE
+8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwgd4GA1UdHwSB1jCB0zBnoGGgX6Rd
+MFsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQDEwRDUkwxgQIF
+YDBooGGgX6RdMFsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMRwwGgYDVQQLExNvbmx5U29tZVJlYXNvbnMgQ0E0MQ0wCwYDVQQD
+EwRDUkwygQMHn4AwDQYJKoZIhvcNAQELBQADggEBAEp1pHXjSGjq1N6Oe2KCTqvs
+TW/SpD8ezjGgyAUwU15I2sTCRhIUeRMZPFVkNqSmDfSp+xNWa8WwXgTaUpcbN3/+
+SC7WefRmx82NMFGZ7lshpwd/LdcagG8oK8jyC8Lec73qpDeObhwo2VTWUs2KfcgE
+Q9QP0QL8xO5v2VbQovLHIu1H4vqqYYCgZ/dZ7ctiatxFEHo36PP57+gRbBGPkubg
+c7TC0UWF2z+m+LeBtSQBXyifUIhqcbWkXz0fqpf12/6BVrKsRnpICJhKjYBhpS9z
+mORlC3jZn479qEASq+HfY/T5aaWJvIhZbsRd50GZerNg6DhQfNj8bJvnBx77CSI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 23 3F AC 65 5C BD B4 11 55 FA 12 15 B8 BD F4 B7 AA 63 89 68
+ friendlyName: Valid onlySomeReasons Test19 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F770B6331EB6E985
+
+00hiEinPPF507CjG5k30QFMeFtpvVoaSvIV3gwKZs1fxsHhMU58Aw8ir9muU7mOI
+KoFHC2JYytoX+BQWmkvSFtqiQEuWmQNcdQmuWXz0HqbmtTSqxC7kI+rDhseetO1f
+Varfou/gU07P29NHTVArxr4cG9GxeArnsV1xT6/hChXuKFHk3Rlb1mkVDR5hojtc
+70z+t6Fpr2csBiu+s8JbI0GdUspsLTCNSJAZDhXaPbrVA2mb/F5m1+soUb8filGJ
+a7YfR6EOAL5BlO4AKJsmW9DuDz+ZUp/NbaCQMIOUUcFqhTQlez3vWp9RH6yvzbUR
+NZe7wEoj5U2JPPj8MKPJRkFVIYv/VL5BsJgjMKz1CAx/ev4SNchBjctph/WlJ/Yh
+DEhdqQv3cS6n3cwY5UVkKjBIMLT0rFDcCrPUC1PttwMv+/qj67jaLjqSkHH37m6b
+RzLgUP7iZCWT/4kzRTQ/PZ3loErNYXqgINLmk3uAQYMMGWXK2I0/O6Ib0YiAg91n
+8NbD7ii8Xi2tvBUgqmUNA4HPBxDaadeuMF9cyZgNRghgM1pFXHCMx+jY9NTFfkQz
+hEQwGmw5FlDIlJzuckUVrwKp2D+ewkThuCPl4xIEq0UG6L7ZDVhZ3dNlZzaXuhk7
+zJpcNLIbTkZEw+xaO4vYkKa7XwmGZ6L6Q0rf1DPyYscLp7P6Ym4AIlzFepb8sdjT
+NrkjDy/OpU/W9HzIT08WQv31uPtaxqthMrRyAQiqcSRqrye80/hXu3YFGjRh1QfV
+AT4gMdC/SZUrWb2YSBieE8uHW5/5PtJC8WKQFWg7Rth8noeRb/f5jU8UiqLN1YSO
+pXXPo1MA1UBNc5aXYHtsg+4uDz1osvOrKgrU3D1JRi6NNcVg6VNYwy/E4etYvDJX
+sTYvnoU1XNPMFpEFzjPNhllYZ43V7C45LgZadsdG6JMY/6/QBysiv3uvP6ckxOUq
+WHM4Q0ifWtAgAPKLLgZiol6r0R4WUihsZHawn/Dwwcj97/zxPFTroN81l393sGQJ
+oESU/RMR/ZzGBJFaV/Hn15MdNGSp2SRGCi0xaOrEfx+kOHDWJbMe9Kl9KMQMngPL
+2qLKLl0Me4fBq5xhxq4t6F21/c3a5dwpAU/mK1UKKQtQSQ0AXcZSSXlvrk0x02jf
+sOoR5+mKYCky4dxBq1DkLmpOSk/G5GxDQ6MU+UVi+6/9KQ/CEgCu/TafYtgjwGfL
+He7d7NnduXYcdLXuxFZBDRJoLNIXGzTbJWF2wIXdxLx30OV9X7HvRV4DfBSX0Yq0
+o5ohzToT3QSY60JHDnhqsvpp95FlZgfuIqdC75Nz9gK6hD5OakQ/dyGEDFrWGyuh
+5Lf3t/YC7yd8E9c6SicH/ijOnuXwdm+Xqefs5VFPNfC+PBwTjVUHFdG9peFFyjq2
+mW5T+BBCwumWvlyudUDGRWisNP/xa/ooKieP4sQgGFQADwRD+bb7V0eHP92dC4i/
+jHnRq1u8wE+ce+usn2CzZIuzOzpPdKAbG9LMJeCdGQU7L3VJ4YkEB6IqOrrfHRdD
+aO9DnZLtH6kVi0vM4UJAYt9rCw+GjQOlO//fb/rFOe/JpFBD2kPQf5VPxsNl/xIY
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13.pem
deleted file mode 100644
index b183ea4aec..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13.pem
+++ /dev/null
@@ -1,262 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQ2IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbfycd4Ehd
-RlHiRJp0MMk0H94GHYCYxpVEzfiC5V9w2M0NWJotHuHxdTvH02XZquFdQptZI0qZ
-AGeBgE3+FBJAGOK0ZxYJgSyscFWBTLGzFZu2Y09siuEwlr5W4z6iByJpFYsEK0JS
-icx7LPYOYyHmFpmDSdcUXwV59VWlaQn5HQIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnY+0pLeirrl2tR7LH2QWpXoO
-hUowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKJlZqSQSA4tpA42dNOs
-k5r0RU2BrRu2bPXhSEZHD0o46NJlNTNTfCAus4HtZ6GE1AvTIy3smHPGb1O4jth2
-9hYXVqNHIEIlejhxgSE0trBBT5L5vodq5Pu5qoTWPZ2Uu8pdqRvdmypKr7gI5inp
-Cu6s2eBv0+DeibQTg73sQuTj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA4
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50NiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQ2IHN1YkNBNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAvfifKseM6a2SLDsRFhGp/REqaFlx95O6qTUy4GtxendIFOtyadcv+Krt
-MtbMq5gpTipTi88pg9PZJgu5WNbNCBTw9a4LVmuK7vW7+qc4vKAiHMx1C36i+M/u
-xAyxABnaB/+3GuTXBVh2UaFyc0y742BlOGiJQec4j12Ympn+/D8CAwEAAaN/MH0w
-HwYDVR0jBBgwFoAUnY+0pLeirrl2tR7LH2QWpXoOhUowHQYDVR0OBBYEFEg0CFSm
-7E/ZmBQh7NRjsSNv7Xk+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBBDANBgkqhkiG9w0BAQUFAAOBgQBH
-GNn47Kmou/bb4DJqEWK0rYy18Luf89VyfaGcLrRx55hJopWTol/7VNHK/PcEcYZR
-FvrRx3+j/FmPw7KdZhr7vswlOw+Al6Izo2NpTdI71n9v0mWk0aMnagaU1/HhVCo0
-MFmjWB6hXagaUlj7PMUGxJhJDLGVxim5OsTKsDyQsA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA41
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA4
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJDQTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBR
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNV
-BAMTHXBhdGhMZW5Db25zdHJhaW50NiBzdWJzdWJDQTQxMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDEkec8+m6bpWo+4WFbIZq5Ex3/ooPS1Ag0V67MSbWUopjA
-ZSFFn1jMVuyJwvVJcWhm60beqAFCWAgdUw39yw1AH1ZjF80S0i7gOs1ecJOgcJlH
-l12ROKtYyawcnvh97Riu5uNhddo7GNP8imgxuTm+KCMgA2Yje/3+s+kkJGrmmQID
-AQABo38wfTAfBgNVHSMEGDAWgBRINAhUpuxP2ZgUIezUY7Ejb+15PjAdBgNVHQ4E
-FgQUxsXdPdf7dENAydCq5aEK1oE0ihEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAHXkSFfYx3eChLIW3r9jR5s+WkJP7zC2MDwTim6sqK9EEdF8u7jpSM7A
-injU005gD9O+daXiOhdTWtO6tHG5lU4F0pz1/gf6NabgsIZcCY5ihmO0sg9yFw2x
-m9ZtI0lrFDJVVMb2TTzSg2BCk/4WrjCu8lyZKeHb3/MPXrhVI6QI
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid pathLenConstraint EE Certificate Test13
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA41X
------BEGIN CERTIFICATE-----
-MIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJzdWJDQTQxWDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMGExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czE2MDQGA1UEAxMtVmFsaWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlmaWNh
-dGUgVGVzdDEzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt+goZGlfBA+Us
-3gYzg2H1q9xTS0jsUbdAWR+UyFhwlPTu9s29bJOQlgYCeMoZsW60iIbUbQjcq5Uz
-cVH3GuHEdnVZi+2PuExwKCPfJd5AlZLlHF2/rXEitua/1jfZeCG2APIo6Fo6MyRm
-DjXSMXVDa+34SxTNsxmRL5mRkAU14wIDAQABo2swaTAfBgNVHSMEGDAWgBQQleeK
-lnT5PPSbBqlJ88GaP85wHzAdBgNVHQ4EFgQUKiHe+m/ll4aKUr4X5q6GcSIkJkEw
-DgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG
-9w0BAQUFAAOBgQBg1xu2EY6shLYeKkVPx8VQMKHQwihQdDRH5Ehqsrgw5t3hALFO
-PjKZ7qdAOOWJA0Y8HmswJswQ9hYMEPkUdGLcE6ssQLySaRecEK5uW5/fWrs451uq
-5hyC55DEHEaJBbvzzBy4eftZcJrQv+QQTxhBH82+/LT02FkYqfjuUPIYSA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA41X
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA41
------BEGIN CERTIFICATE-----
-MIICmDCCAgGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJDQTQxMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowVTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSow
-KAYDVQQDEyFwYXRoTGVuQ29uc3RyYWludDYgc3Vic3Vic3ViQ0E0MVgwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBALlp+FnExwi/Gj0ZI91kqo4pmnqqOhGFj1B7
-BwwpwPKi9bTS4V7SoF/789+rQvetsKPMvlFqlJxAJDAucVf9IcHun+JONgiIUcLB
-o1x/hhXffJx5AKaTGK3lCSkXqT2ivI8QJNTTjDgv3gvwGg97WVPlbOeZEPbwMzlx
-i4oq4uHXAgMBAAGjfDB6MB8GA1UdIwQYMBaAFMbF3T3X+3RDQMnQquWhCtaBNIoR
-MB0GA1UdDgQWBBQQleeKlnT5PPSbBqlJ88GaP85wHzAOBgNVHQ8BAf8EBAMCAQYw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
-hvcNAQEFBQADgYEAuzFHa2SgbDIRvfbqmMe+p2l0M4gJMEc3r2caaovmKgfuVyBl
-n0JdZN2rzlYFV4jZbJ0wa89PzLIDtmptUctcO0DO/P+ofx8uAATdFhL4yMmHkK9L
-XVBrdANbZSBZ+8WXKrnvsJArX0vtQax8znEaTUskMtDe6gjzZsb957dYCCU=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:8F:B4:A4:B7:A2:AE:B9:76:B5:1E:CB:1F:64:16:A5:7A:0E:85:4A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0d:f1:3d:54:c8:22:83:d4:1c:69:d2:12:e3:82:09:7e:b6:c0:
- af:f4:41:9b:51:c5:04:d4:c5:ca:51:73:5c:c5:14:c5:d6:d0:
- 11:6c:40:ce:49:e7:80:49:a9:35:94:84:b5:bb:52:37:62:c3:
- 5e:0e:18:48:57:44:b1:cd:97:a2:44:ef:9f:75:44:16:9e:58:
- ff:db:7f:18:8e:d5:07:fc:01:64:17:c3:00:79:4d:02:af:dd:
- 08:88:37:03:be:cc:80:7a:cb:fd:e7:5c:53:03:b1:f2:17:16:
- 1a:14:25:f4:ea:50:8c:14:ff:58:e9:2f:fe:e4:75:d9:67:78:
- fa:7a
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-NiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUnY+0pLeirrl2tR7LH2QWpXoOhUowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEADfE9VMgig9QcadIS44IJfrbAr/RBm1HFBNTFylFzXMUUxdbQEWxAzknn
-gEmpNZSEtbtSN2LDXg4YSFdEsc2XokTvn3VEFp5Y/9t/GI7VB/wBZBfDAHlNAq/d
-CIg3A77MgHrL/edcUwOx8hcWGhQl9OpQjBT/WOkv/uR12Wd4+no=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subCA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:48:34:08:54:A6:EC:4F:D9:98:14:21:EC:D4:63:B1:23:6F:ED:79:3E
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 7a:5e:e4:e2:af:00:5c:48:3a:c2:36:d1:97:10:66:06:b0:04:
- 8c:37:8b:96:01:b2:c1:bc:b5:3a:8f:b5:44:05:db:84:2a:85:
- c1:7c:96:fd:b3:6c:1d:47:69:63:e6:a2:d5:6b:29:76:e2:72:
- e1:4b:6a:d4:06:22:80:cb:58:0a:39:aa:47:45:a0:84:d0:9d:
- d4:e5:00:13:71:ef:bb:3b:27:b0:e5:93:cf:b2:05:87:43:8d:
- bc:a5:7a:50:8f:22:43:48:df:9a:e7:cc:8c:3e:54:fd:16:85:
- 3e:e9:a2:47:4f:f8:ae:94:85:32:4a:88:94:b7:c4:13:62:11:
- 6c:b8
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJDQTQXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFEg0CFSm7E/ZmBQh7NRjsSNv7Xk+MAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAHpe5OKvAFxIOsI20ZcQZgawBIw3i5YBssG8tTqPtUQF24QqhcF8
-lv2zbB1HaWPmotVrKXbicuFLatQGIoDLWAo5qkdFoITQndTlABNx77s7J7Dlk8+y
-BYdDjbylelCPIkNI35rnzIw+VP0WhT7pokdP+K6UhTJKiJS3xBNiEWy4
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA41
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C6:C5:DD:3D:D7:FB:74:43:40:C9:D0:AA:E5:A1:0A:D6:81:34:8A:11
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0e:71:9b:f6:ad:39:6e:d8:be:f8:b2:87:85:75:4b:35:16:3c:
- e7:52:48:af:e3:b1:7b:6d:1f:2e:59:59:81:af:cc:88:37:3b:
- 78:f8:4d:7a:81:e6:6e:23:50:4c:80:f2:e9:d5:cf:79:ce:e8:
- 9e:f8:c4:82:2b:6f:4a:ab:29:bd:5b:34:57:5f:31:5d:3b:a6:
- b5:da:8f:57:4b:07:e2:5f:e3:f1:b0:8f:25:92:f2:c6:57:26:
- 9a:4e:36:d9:c9:6b:37:f3:0f:7d:81:b6:2d:6c:f7:c7:76:d7:
- 3e:29:67:8b:2e:01:9a:f8:90:2c:53:da:a6:c7:6c:b6:56:09:
- fb:df
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJDQTQxFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBTGxd091/t0Q0DJ0KrloQrWgTSKETAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQAOcZv2rTlu2L74soeFdUs1FjznUkiv47F7bR8uWVmBr8yI
-Nzt4+E16geZuI1BMgPLp1c95zuie+MSCK29Kqym9WzRXXzFdO6a12o9XSwfiX+Px
-sI8lkvLGVyaaTjbZyWs38w99gbYtbPfHdtc+KWeLLgGa+JAsU9qmx2y2Vgn73w==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA41X
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:10:95:E7:8A:96:74:F9:3C:F4:9B:06:A9:49:F3:C1:9A:3F:CE:70:1F
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 06:af:3f:80:68:02:24:ee:c0:3f:33:5b:62:49:01:cf:ee:87:
- f7:92:49:33:a2:b1:b0:6c:e7:23:7f:4a:8d:2a:1b:e9:31:fc:
- 04:49:76:f2:f6:92:d2:b3:32:70:50:71:9f:12:ab:03:6c:2d:
- a7:0f:81:ef:fb:01:3e:3f:09:b8:df:e8:4e:28:c9:5d:fa:a3:
- ef:64:db:b9:cb:8f:66:a2:b5:ba:17:f3:05:62:5c:8c:5b:75:
- f6:7e:54:aa:30:59:0d:50:c1:23:90:c9:91:06:49:1e:bf:23:
- de:88:c6:7a:39:0e:6e:11:cc:44:44:40:2e:08:82:65:e8:74:
- 9d:60
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJzdWJDQTQxWBcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUEJXnipZ0+Tz0mwapSfPBmj/OcB8wCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEABq8/gGgCJO7APzNbYkkBz+6H95JJM6KxsGznI39K
-jSob6TH8BEl28vaS0rMycFBxnxKrA2wtpw+B7/sBPj8JuN/oTijJXfqj72TbucuP
-ZqK1uhfzBWJcjFt19n5UqjBZDVDBI5DJkQZJHr8j3ojGejkObhHMRERALgiCZeh0
-nWA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13EE.pem
new file mode 100644
index 0000000000..79507de0d1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest13EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 2D FA 1C 30 3E E6 37 A1 12 BE 07 77 3B 17 6E F8 9F 00 3A 06
+ friendlyName: Valid pathLenConstraint Test13 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid pathLenConstraint EE Certificate Test13
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubsubCA41X
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YnN1YkNBNDFYMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowZjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExNjA0BgNVBAMTLVZhbGlkIHBhdGhMZW5Db25zdHJhaW50IEVF
+IENlcnRpZmljYXRlIFRlc3QxMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBANGvSnWvqPuuQwnBzwyPeG9cwJSQU/bvAAFK1V8D6Yb5dGmKu++FJuY3+qmG
+uzN3K1HFo1C/84fQ0UFNp/6H9r+9yUZ3RRSvr8A4JA0CUUv+mXfbd7+HzCqqyj0i
+RSreaFuiXaM4QAH56nrfg31qQGb1QC14tpEXlBp8YnGh2PRbbdJQf8JbxMOlhWB9
+A8+Dk0gwSVqUZ0nPDFy2OLQ3cEQTgjnihXBJqHztLtj4rQkwWbQCNIThrZ+XszkW
+6rcGygZ7ZACnuuHOG5UK6qxakReo8ZuW079tnFJCPSyPk54dHLlTrsz6LyyBQBKv
+2PzZAQcnzZWHJLoACwhOWUQ9dz8CAwEAAaNrMGkwHwYDVR0jBBgwFoAUoe2i8zVU
+pZ+8Y+ZHalMkbEoMciwwHQYDVR0OBBYEFLdJcbHtcyweaP/yNyrJR7L7kfqpMA4G
+A1UdDwEB/wQEAwIE8DAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcN
+AQELBQADggEBAJTElUFCT4pcCXUHleZsjeg3hPXNJIWYLr3/MACyrDpD7M4kb1J/
+v03VUo6r9wFgd2LE8Q9kghkRsQ1BvdGX9FijaPDMZ31kPpU1EelGutxkjU21mz6x
+lXLb4ql8QBCLDZ+N2mEQ8y/KCYpSkKJK2X5XHQ8LRn0b/QKK64UmF4uZFxKA5Ez8
+q1bescEhdWiAZBrFv5t+OhSHbRkRtLNB2fHkzkovVrhSgrG/qcsGInWTvF1RnV40
+iP7VcosKbEynP8p5LQMIjt7d4f+PocFcSIVwgcVfZdwx9MS+nAj29Ynu9vQENFHI
+xwRm/XT3hYzGswzrl5RhHyyjgAvjxwSaxfU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2D FA 1C 30 3E E6 37 A1 12 BE 07 77 3B 17 6E F8 9F 00 3A 06
+ friendlyName: Valid pathLenConstraint Test13 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C045A0179BFD32F2
+
+0PhVbeIHszH6dY1ZI4AbD2whyIF4mwSnK0v+/EzbQixapqiVpM5mjsogGfNjH0xA
+/LUFFI75lMUJDQSstlUiDAVLBhLadSx2K7EQe7Yh+biVi/xlqObKauYzF8IUGl76
+CNU1DNvrf3HDU4GE/7nxrYWYjBZt6upNHjaek4UoyfiJT8T3hmOhhAFYxb0lxs8Z
+SnrGzb5eFWNSvlr4gTvvbb48PLrWzKk8DeuirhV23c4n6sj7pEcY1+rNVPxNm9oU
+43sOY4IEfr+CFXxQBFUTseVkLWpLLDdkPFiIgcmVSV8vaSwnsIQ3ciBxge/wZJMU
+78OyHkkUquZV+cCKrgpgChMin1u2wn08QyPwETdpMobc+g7Ydb+eyU39kMSIPP3t
+UrFsmTTPygF11iwkSbPzToQ163O0TOmqD0BcJsWxTVjbHSTnNJ4hVie8xIAShjAa
+9U04QPBp7gb7npf4dIEIh6Yyf9AQyLqwDgSZv2VO+M9G1EMxpNflsYLU6s3V1efM
+kXk9EPA0j0piq5xMdSf+AqRLieSkIm53fFENvfz0CcauOwSQ0Trm2S6vLzIp/IYA
+ZaCqwba9QqusemG/CfKKc4oCKeF+hFk5D21d+s5XGhmWjrkaWn7PQLxNnIiuZ+5s
+CIabBUjQHWreoBPw9QOQwbJMfTJYmfldZll9KnlLlo296Qb+uWLZTbtk3/ZEQ5go
+1iJp35jEs82nI9NVazSS98CXHBUCUOlHM0caxq3irssQlLz9nbnUODlrZ3CSaW8V
+wOsYkAnN6lFImq+1LqrSVtVqtESY6aPBt8GWS9UHx2n9MfRlPBKQLUJGnOG9+ktW
+tuayerk2V86x1R8c1YEbhqU+g//l1UoAOAEOfndkb4JNAgVXAxIhU2WpJUs9EGZR
+43nYgJ+IwiHWpWmB1TMgTMU+qFo+QjVYyZkGVyO2FUY2CaD5oq1MUGS0uDkfXq34
+8yBjCCskYG+eTnktrbJ86844oAObQiour2zVcQz3oI+uivn7XJBuLP/np2RLwQow
+yyXMzJIY+WO/WkZDPmXRLNToHaK6NG9/JVP6Z5WaZSHf1qrIHzH1optKT4YVJmmQ
+ZKbkVg1vsDmvaDMEaETzw6W8UUlrEc81HIlC03qKbmWVQKj/B6vvWefhXl8HCeWA
+OIeLhLVqJL5ZSQdnMdF33uhGOvhAWkUUmCEplixC+bRWdEhFoorZLHmuoML1WQ1X
+O8P9EkAuHxNzTv/FuPl+GHC3dkQrxFi0BNBKfUXhpK3E+/UAztcDlX4FNytLv7Q7
+FLP1yJ7Em2S87yeX4dRtG2OvNR8/gRWfNoZBxd3CU4mMg1IwXCZnpk5Odz1i/obJ
+yLUdymiAjHMZ3EyAhTxofDSwmakWjP8tzcXppcMJC6ghMHDd22KtYJztt/qG691G
+k77Ygq693ub+2usd/6aBmzOQMDAzj1aqAPUzd0yM36Cm7OmgJV3ZJ5C26XBOLP00
+oAa4UklbL5erfU6qMimMMdqbmKUd4whyvx9fKSdhGhFZ0VoOrT80CyGzVnnxC3fY
+Uw7NB+13ZruVC6SYCD1R7rRUUZgu9GbYdUx0Te12rrQozXMajPFy6psTUqEFusv5
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14.pem
deleted file mode 100644
index fb615f5434..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14.pem
+++ /dev/null
@@ -1,263 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGzANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQ2IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbfycd4Ehd
-RlHiRJp0MMk0H94GHYCYxpVEzfiC5V9w2M0NWJotHuHxdTvH02XZquFdQptZI0qZ
-AGeBgE3+FBJAGOK0ZxYJgSyscFWBTLGzFZu2Y09siuEwlr5W4z6iByJpFYsEK0JS
-icx7LPYOYyHmFpmDSdcUXwV59VWlaQn5HQIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUnY+0pLeirrl2tR7LH2QWpXoO
-hUowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKJlZqSQSA4tpA42dNOs
-k5r0RU2BrRu2bPXhSEZHD0o46NJlNTNTfCAus4HtZ6GE1AvTIy3smHPGb1O4jth2
-9hYXVqNHIEIlejhxgSE0trBBT5L5vodq5Pu5qoTWPZ2Uu8pdqRvdmypKr7gI5inp
-Cu6s2eBv0+DeibQTg73sQuTj
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA4
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 CA
------BEGIN CERTIFICATE-----
-MIICizCCAfSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50NiBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaME0xCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEiMCAGA1UEAxMZ
-cGF0aExlbkNvbnN0cmFpbnQ2IHN1YkNBNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAvfifKseM6a2SLDsRFhGp/REqaFlx95O6qTUy4GtxendIFOtyadcv+Krt
-MtbMq5gpTipTi88pg9PZJgu5WNbNCBTw9a4LVmuK7vW7+qc4vKAiHMx1C36i+M/u
-xAyxABnaB/+3GuTXBVh2UaFyc0y742BlOGiJQec4j12Ympn+/D8CAwEAAaN/MH0w
-HwYDVR0jBBgwFoAUnY+0pLeirrl2tR7LH2QWpXoOhUowHQYDVR0OBBYEFEg0CFSm
-7E/ZmBQh7NRjsSNv7Xk+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
-SAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBBDANBgkqhkiG9w0BAQUFAAOBgQBH
-GNn47Kmou/bb4DJqEWK0rYy18Luf89VyfaGcLrRx55hJopWTol/7VNHK/PcEcYZR
-FvrRx3+j/FmPw7KdZhr7vswlOw+Al6Izo2NpTdI71n9v0mWk0aMnagaU1/HhVCo0
-MFmjWB6hXagaUlj7PMUGxJhJDLGVxim5OsTKsDyQsA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA41
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subCA4
------BEGIN CERTIFICATE-----
-MIICkzCCAfygAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJDQTQwHhcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBR
-MQswCQYDVQQGEwJVUzEaMBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNV
-BAMTHXBhdGhMZW5Db25zdHJhaW50NiBzdWJzdWJDQTQxMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDEkec8+m6bpWo+4WFbIZq5Ex3/ooPS1Ag0V67MSbWUopjA
-ZSFFn1jMVuyJwvVJcWhm60beqAFCWAgdUw39yw1AH1ZjF80S0i7gOs1ecJOgcJlH
-l12ROKtYyawcnvh97Riu5uNhddo7GNP8imgxuTm+KCMgA2Yje/3+s+kkJGrmmQID
-AQABo38wfTAfBgNVHSMEGDAWgBRINAhUpuxP2ZgUIezUY7Ejb+15PjAdBgNVHQ4E
-FgQUxsXdPdf7dENAydCq5aEK1oE0ihEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
-MA4wDAYKYIZIAWUDAgEwATASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEB
-BQUAA4GBAHXkSFfYx3eChLIW3r9jR5s+WkJP7zC2MDwTim6sqK9EEdF8u7jpSM7A
-injU005gD9O+daXiOhdTWtO6tHG5lU4F0pz1/gf6NabgsIZcCY5ihmO0sg9yFw2x
-m9ZtI0lrFDJVVMb2TTzSg2BCk/4WrjCu8lyZKeHb3/MPXrhVI6QI
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA41X
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA41
------BEGIN CERTIFICATE-----
-MIICmDCCAgGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJDQTQxMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcy
-MFowVTELMAkGA1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSow
-KAYDVQQDEyFwYXRoTGVuQ29uc3RyYWludDYgc3Vic3Vic3ViQ0E0MVgwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBALlp+FnExwi/Gj0ZI91kqo4pmnqqOhGFj1B7
-BwwpwPKi9bTS4V7SoF/789+rQvetsKPMvlFqlJxAJDAucVf9IcHun+JONgiIUcLB
-o1x/hhXffJx5AKaTGK3lCSkXqT2ivI8QJNTTjDgv3gvwGg97WVPlbOeZEPbwMzlx
-i4oq4uHXAgMBAAGjfDB6MB8GA1UdIwQYMBaAFMbF3T3X+3RDQMnQquWhCtaBNIoR
-MB0GA1UdDgQWBBQQleeKlnT5PPSbBqlJ88GaP85wHzAOBgNVHQ8BAf8EBAMCAQYw
-FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
-hvcNAQEFBQADgYEAuzFHa2SgbDIRvfbqmMe+p2l0M4gJMEc3r2caaovmKgfuVyBl
-n0JdZN2rzlYFV4jZbJ0wa89PzLIDtmptUctcO0DO/P+ofx8uAATdFhL4yMmHkK9L
-XVBrdANbZSBZ+8WXKrnvsJArX0vtQax8znEaTUskMtDe6gjzZsb957dYCCU=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid pathLenConstraint EE Certificate Test14
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA41X
------BEGIN CERTIFICATE-----
-MIICqDCCAhGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25z
-dHJhaW50NiBzdWJzdWJzdWJDQTQxWDAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkx
-NDU3MjBaMGExCzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRl
-czE2MDQGA1UEAxMtVmFsaWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlmaWNh
-dGUgVGVzdDE0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTcyx/sZXkB7EZ
-X9U9aJCVucbvSK3QXJ38Ej+ZM7agOIkJnMypA0BzQ43FvxbDlx67ynhH3au4nFw9
-niBIPF0hg9LKJBYQDlFhdCPd441gpnEOtT5abklFPScEoi115OUSsoA94VZwjdmz
-rxb5Scji7OZYKtBZumvQ+YxbZGKi9QIDAQABo3wwejAfBgNVHSMEGDAWgBQQleeK
-lnT5PPSbBqlJ88GaP85wHzAdBgNVHQ4EFgQUSa5vCfYgmh0xBcsnTTGEttOhtX0w
-DgYDVR0PAQH/BAQDAgH2MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMB
-Af8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABdfALk3+cW2GpEztpvr/6wgOkaJ
-ev+/WwDgW5YTiVGbLZRr+5qrxz8Log4b4Y/OYyrwh+J/gmQFP34wHEm4ReZHcfyD
-4k6Ji2dWxqLaocQVROOZ9n+vqSFC63nNE/ZDNnsUErkEQJdX7f7HMDZoDI0wryrp
-3fLY+NJlyePm6r1M
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:9D:8F:B4:A4:B7:A2:AE:B9:76:B5:1E:CB:1F:64:16:A5:7A:0E:85:4A
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0d:f1:3d:54:c8:22:83:d4:1c:69:d2:12:e3:82:09:7e:b6:c0:
- af:f4:41:9b:51:c5:04:d4:c5:ca:51:73:5c:c5:14:c5:d6:d0:
- 11:6c:40:ce:49:e7:80:49:a9:35:94:84:b5:bb:52:37:62:c3:
- 5e:0e:18:48:57:44:b1:cd:97:a2:44:ef:9f:75:44:16:9e:58:
- ff:db:7f:18:8e:d5:07:fc:01:64:17:c3:00:79:4d:02:af:dd:
- 08:88:37:03:be:cc:80:7a:cb:fd:e7:5c:53:03:b1:f2:17:16:
- 1a:14:25:f4:ea:50:8c:14:ff:58:e9:2f:fe:e4:75:d9:67:78:
- fa:7a
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-NiBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUnY+0pLeirrl2tR7LH2QWpXoOhUowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEADfE9VMgig9QcadIS44IJfrbAr/RBm1HFBNTFylFzXMUUxdbQEWxAzknn
-gEmpNZSEtbtSN2LDXg4YSFdEsc2XokTvn3VEFp5Y/9t/GI7VB/wBZBfDAHlNAq/d
-CIg3A77MgHrL/edcUwOx8hcWGhQl9OpQjBT/WOkv/uR12Wd4+no=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subCA4
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:48:34:08:54:A6:EC:4F:D9:98:14:21:EC:D4:63:B1:23:6F:ED:79:3E
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 7a:5e:e4:e2:af:00:5c:48:3a:c2:36:d1:97:10:66:06:b0:04:
- 8c:37:8b:96:01:b2:c1:bc:b5:3a:8f:b5:44:05:db:84:2a:85:
- c1:7c:96:fd:b3:6c:1d:47:69:63:e6:a2:d5:6b:29:76:e2:72:
- e1:4b:6a:d4:06:22:80:cb:58:0a:39:aa:47:45:a0:84:d0:9d:
- d4:e5:00:13:71:ef:bb:3b:27:b0:e5:93:cf:b2:05:87:43:8d:
- bc:a5:7a:50:8f:22:43:48:df:9a:e7:cc:8c:3e:54:fd:16:85:
- 3e:e9:a2:47:4f:f8:ae:94:85:32:4a:88:94:b7:c4:13:62:11:
- 6c:b8
------BEGIN X509 CRL-----
-MIIBRjCBsAIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJDQTQXDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFqgLzAtMB8GA1Ud
-IwQYMBaAFEg0CFSm7E/ZmBQh7NRjsSNv7Xk+MAoGA1UdFAQDAgEBMA0GCSqGSIb3
-DQEBBQUAA4GBAHpe5OKvAFxIOsI20ZcQZgawBIw3i5YBssG8tTqPtUQF24QqhcF8
-lv2zbB1HaWPmotVrKXbicuFLatQGIoDLWAo5qkdFoITQndTlABNx77s7J7Dlk8+y
-BYdDjbylelCPIkNI35rnzIw+VP0WhT7pokdP+K6UhTJKiJS3xBNiEWy4
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubCA41
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:C6:C5:DD:3D:D7:FB:74:43:40:C9:D0:AA:E5:A1:0A:D6:81:34:8A:11
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 0e:71:9b:f6:ad:39:6e:d8:be:f8:b2:87:85:75:4b:35:16:3c:
- e7:52:48:af:e3:b1:7b:6d:1f:2e:59:59:81:af:cc:88:37:3b:
- 78:f8:4d:7a:81:e6:6e:23:50:4c:80:f2:e9:d5:cf:79:ce:e8:
- 9e:f8:c4:82:2b:6f:4a:ab:29:bd:5b:34:57:5f:31:5d:3b:a6:
- b5:da:8f:57:4b:07:e2:5f:e3:f1:b0:8f:25:92:f2:c6:57:26:
- 9a:4e:36:d9:c9:6b:37:f3:0f:7d:81:b6:2d:6c:f7:c7:76:d7:
- 3e:29:67:8b:2e:01:9a:f8:90:2c:53:da:a6:c7:6c:b6:56:09:
- fb:df
------BEGIN X509 CRL-----
-MIIBSjCBtAIBATANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxJjAkBgNVBAMTHXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJDQTQxFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAf
-BgNVHSMEGDAWgBTGxd091/t0Q0DJ0KrloQrWgTSKETAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQAOcZv2rTlu2L74soeFdUs1FjznUkiv47F7bR8uWVmBr8yI
-Nzt4+E16geZuI1BMgPLp1c95zuie+MSCK29Kqym9WzRXXzFdO6a12o9XSwfiX+Px
-sI8lkvLGVyaaTjbZyWs38w99gbYtbPfHdtc+KWeLLgGa+JAsU9qmx2y2Vgn73w==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint6 subsubsubCA41X
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:10:95:E7:8A:96:74:F9:3C:F4:9B:06:A9:49:F3:C1:9A:3F:CE:70:1F
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 06:af:3f:80:68:02:24:ee:c0:3f:33:5b:62:49:01:cf:ee:87:
- f7:92:49:33:a2:b1:b0:6c:e7:23:7f:4a:8d:2a:1b:e9:31:fc:
- 04:49:76:f2:f6:92:d2:b3:32:70:50:71:9f:12:ab:03:6c:2d:
- a7:0f:81:ef:fb:01:3e:3f:09:b8:df:e8:4e:28:c9:5d:fa:a3:
- ef:64:db:b9:cb:8f:66:a2:b5:ba:17:f3:05:62:5c:8c:5b:75:
- f6:7e:54:aa:30:59:0d:50:c1:23:90:c9:91:06:49:1e:bf:23:
- de:88:c6:7a:39:0e:6e:11:cc:44:44:40:2e:08:82:65:e8:74:
- 9d:60
------BEGIN X509 CRL-----
-MIIBTjCBuAIBATANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxKjAoBgNVBAMTIXBhdGhMZW5Db25zdHJhaW50
-NiBzdWJzdWJzdWJDQTQxWBcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAv
-MC0wHwYDVR0jBBgwFoAUEJXnipZ0+Tz0mwapSfPBmj/OcB8wCgYDVR0UBAMCAQEw
-DQYJKoZIhvcNAQEFBQADgYEABq8/gGgCJO7APzNbYkkBz+6H95JJM6KxsGznI39K
-jSob6TH8BEl28vaS0rMycFBxnxKrA2wtpw+B7/sBPj8JuN/oTijJXfqj72TbucuP
-ZqK1uhfzBWJcjFt19n5UqjBZDVDBI5DJkQZJHr8j3ojGejkObhHMRERALgiCZeh0
-nWA=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14EE.pem
new file mode 100644
index 0000000000..7271932e27
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest14EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 04 A0 3D CB C0 33 CA B4 2C C2 0F CC CD 23 1F 52 D0 88 A6 34
+ friendlyName: Valid pathLenConstraint Test14 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid pathLenConstraint EE Certificate Test14
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubsubCA41X
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YnN1YkNBNDFYMB4XDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFowZjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExNjA0BgNVBAMTLVZhbGlkIHBhdGhMZW5Db25zdHJhaW50IEVF
+IENlcnRpZmljYXRlIFRlc3QxNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALwvb5kYb8ZGePgV8mVn9WJWyg0Wbw6tmwPBtLDhu1M+yVu5u+mZ30leAT07
+idW26yPnA75uFMjgKbbzoccKeI9e68lm5fwUFbflcVywdvcXIRszUoqwZvZJnnqp
+FO+wjw1YDVmfbqHJ68eKUUwebgNNnMz7LS1Qf6I811JYPJLGq8dLRruoN46Uxfnr
+dtWwu09ovP1N6lkvtPRE8DZFweTE4CYr6OAzcX9EnjDxCy/E0BVhXSbUCYq1zQht
+nfHihV/+K3JLyCiOU6UmYxI9sP/A8H0L1ymMKBnV5a7dj1wKWPsonUYwEMLZqUXw
+/p2VSrJyseyovwtD5sDXlor2xT8CAwEAAaN8MHowHwYDVR0jBBgwFoAUoe2i8zVU
+pZ+8Y+ZHalMkbEoMciwwHQYDVR0OBBYEFBIalgWSiLc2La4mJ6CGCUvwDtB8MBcG
+A1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIB9jANBgkqhkiG9w0BAQsFAAOCAQEAVhkHa+bENPN+3xIaFGBp9icw3gtg
+wx34h2kqls0SzTxl48bBGFoDR9YGzUH0Z/ZEfrnMPKF7Q/RMU0AnUftz3aAifsms
+P6mI7pYpDnSby4nk7nlaEohfL8qozpbr8ZGX3pPmR+7/6YmdP/hcLZusaWznnxuk
+pGpMGnVdZNaoNgzlkGzUP2+02IaDYVJ+Fb1GxuyofrZZU37b8FXgm0aaEPMJzGHD
+QCpc62yTxVU/NoWHPtx0zJnDzaeooVTlJxM+bIyjksW2fdaFfpoxGkJVkSNBxiXY
+Kntn/0GBOWHqKM349yIt+KU2fkJuG19jmKdP1tgDAPTtTlpTDaqNoXqfQg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 04 A0 3D CB C0 33 CA B4 2C C2 0F CC CD 23 1F 52 D0 88 A6 34
+ friendlyName: Valid pathLenConstraint Test14 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,606028537BDECB08
+
+PiwJB9Kp7heayAFM3DNRNa7HEyB2ZzhqLkb220AWZzf74xcebBuIeDpFvd7DM/Ch
+gq7P8pnfmlfxslJj1bG9kPz2ruZ/p0ltCYIShztmVBZ4v6v6ADZy0nmaT1vdjOar
+ElxeJ3YPn+I2oFDTWNmrDHJcwR053a86XwxFYHQWXWDEfGaianVMvm6n7YOs+BmG
+oSr2qS28ddeWnmtsifbCI1jZNjcUDr4w+6cMq/SFsOXh/m063dB23JoekdSVwDt6
+k0MdmU/5ir414ek2ZWRmP2ILe/vbCReyukabxyMweUbrROQJEHF5QDQunhJ3mbQT
+XSo0IDt8nRQJP8Fq8za2xUIXo+VZZlykSvsJOeuNLgtyY/5MYBsSgIsO0IG3TxMo
+E+8bRHGy0XJhvvIJaezSiN/F+xp3ugm9133vvM51WfY6+yHw5g91JzaiIbYHx/hP
+u1TE7MlfsbXYvB2duN3Jqx0Jja306XQv2ZX8TRWvcazreYcqfQsUuTaVQt6I9enb
+6R6weCdSdpSnNdwpemZN0y7+xT48zgpm928gsoU5ioNoxdAwzV6xiecTWtZM4dAe
+u3520Mk7hdzhTx601y2GRfMH4jAU04ENhk0u1/485u7D3oT9T/QGpncSIeKJKqG0
+iQziHiaSifEHcbopsrcBUhh5bGjtvXtdjZbPYpFqNLc49sAGsWEGDK7CikYgr6dQ
+EhFkZjIFcEpqdKLC+hBzVl3xczlQ1E/Dnjst8EIvBkX0d9Du66PYp1F85LYwP3XI
+QBqJqn0TpcWVQIHeJtbbSY5yuWgYLbVHW2DL+OyA2Rxx8jlnbtDZc1RDi0BN8LGO
+E8xTI9wwFkPp3Z6fr/gFCatAdjVEj2YNM1WyLfDQO8sKHbdGpZnwqPRYNn8uvlJ0
+lNOJW3n4FkFfMP+GJBRtF4Foy0htW/88oxG5MVl10a/6JgZa/cAwQl72wpWhJY/o
+VRCoPyPiAEK/psTmcSwxpRLUE0XRNlWsSOm2KoGvnVvUiHYJZSezN9Cs/wuyPxhr
+XJeBsqwntDIpV0dhplLoAsGDpr/F4qfYp3ba4vXxFbL+WIiMWSMVeuv6pbHs0Y30
+M8288+VnuWLLRmjuEe4jVuw+RUu76CtePvXXYUd1YGLRqx0ckMIptpu9wUvLtZbr
+7THSoKuA8ImLcbA7z6zjztuPbpaj9p89NAVU0H8CV0u1coZ0pncadTNQD5tgKmeV
+TgeDKuGyyP+tz4ML73chkdCwabJMVlFxf3n6XI3ZlKtd1apJGMllcJo6SprdSgnv
+5NnPsCoaRa8No1IZVxVGfdHxOSXydogCrRVx/D3PYWrodEXdnnU+AC2Rqk80veVS
+zEkuXPISsFP445tU0SSDnligmMwEmIGeokyYZuxSsbfdbE3e2tOv5WPtRtg2DqSl
+PVn3UwBbC9otf3jO2zQCZCrp49n8c0ZJzxFmLZ1ytZa3GEKS1RlB8mdLpy4adlB5
+uHzYy9cwfwSV6R/fS0I4M9BwhimezGLEvWSIQXrXP77pvjeHC1b2RlCKm/dj+1pL
+Dx+T8CcmVM8ox4iSBCpbzTCNw6mrUysDdIJPIWLhnvtBox9Gh1PDeg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7.pem
deleted file mode 100644
index d2ac20b505..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXXXPbNnk
-MU3wxjjwCdA/Pj+lwkDk8WSxKGdOrcPMnFnrCdUnSqEES3K6/T7JRQyv6Y13Rt6w
-LAhrQI94UBcsAAQND4SOPyJUE3PonzcolJQ+EzkSB9qq6cxJokxTvxVTx2VN7bN1
-RJ7FrWovHu/vmKnwsOy3zv41U6KBfuf04QIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUIQy1AXZ207MqrCb8qqZP8tah
-b0swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJUd83zrSjxfaGwFdTCt
-BSI1mTeztSKFxIzrWeTxD3C0JHAxt1oM1AN8DQ/Ej8ja3rxhzsFQaWzdi3ixvnGr
-NbjLZH7EPWBPSSC2rTAcvLzVs2AuPsBkv7IKxg7HTJZtLbXDOIatWT+24OuKwTzE
-6cbcSe7zaz5qdojy0B72dLHC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid pathLenConstraint EE Certificate Test7
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIICijCCAfOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGAxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE1MDMGA1UEAxMs
-VmFsaWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlmaWNhdGUgVGVzdDcwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDow4Z8Uorsifrji6RyscEE5DKo3WRY
-S01OJEDMgd8P75udI5umL9+vwJBIoObEUAx5I5UMDxkto9pDvHrRH72cNywar2n2
-4oat6X0JzKOaEzlx0N5E8Tp7LRkF7dcVCIZUGN0qVAJvfMtVQpcbRbLhK96jqOV1
-5uh5OetDHHufAgMBAAGjazBpMB8GA1UdIwQYMBaAFCEMtQF2dtOzKqwm/KqmT/LW
-oW9LMB0GA1UdDgQWBBRscpI4Rhz3vkPw7mtg+y+hic1p2DAOBgNVHQ8BAf8EBAMC
-BPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBBQUAA4GBACeo
-UDJXue1qGUe8Qxos7w6eQsbzHSXsmNI+t2Hyq+CARypTIgbueoWHfe1HyPsbOrEr
-3U2waZZ8AQzwklkyFUiL4D5Jo/+0coA9hPwmyhF6J/Wa5nOmLex1ZGg3c7J+MVAL
-1qx70Ft4WEm/EWBWCqse0wlEZXsvg5WocxF/xXKC
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:21:0C:B5:01:76:76:D3:B3:2A:AC:26:FC:AA:A6:4F:F2:D6:A1:6F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:7b:a5:e5:64:8b:31:64:fa:9f:8f:a3:25:ab:8b:c9:c2:ba:
- cb:b9:e3:5f:3d:e9:b9:f4:f4:f4:d8:00:4c:cc:9e:5a:36:b3:
- d3:53:12:aa:d5:ba:ad:94:a5:21:16:c4:9c:ac:3d:3c:e3:2f:
- 53:69:97:6c:2e:e5:82:98:31:e8:47:f9:8d:dc:ab:e2:8d:ec:
- b9:3f:b2:61:20:ad:22:24:f6:ff:90:4a:14:92:38:0e:9b:80:
- 3f:1e:11:f2:d8:7b:fd:d4:0c:90:06:82:2c:48:f8:9e:7e:91:
- 55:0c:21:e8:dd:95:ac:90:c7:d7:02:af:84:f4:23:08:bb:da:
- cd:a2
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUIQy1AXZ207MqrCb8qqZP8tahb0swCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAVnul5WSLMWT6n4+jJauLycK6y7njXz3pufT09NgATMyeWjaz01MSqtW6
-rZSlIRbEnKw9POMvU2mXbC7lgpgx6Ef5jdyr4o3suT+yYSCtIiT2/5BKFJI4DpuA
-Px4R8th7/dQMkAaCLEj4nn6RVQwh6N2VrJDH1wKvhPQjCLvazaI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7EE.pem
new file mode 100644
index 0000000000..1a2c275658
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest7EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 35 20 C7 01 33 EA 16 11 B0 87 DE 1A 48 93 90 F1 6C 92 0D E6
+ friendlyName: Valid pathLenConstraint Test7 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid pathLenConstraint EE Certificate Test7
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NTAzBgNVBAMTLFZhbGlkIHBhdGhMZW5Db25zdHJhaW50IEVFIENlcnRpZmljYXRl
+IFRlc3Q3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4Fz+73nLTNQk
+5wB39QOcOINSEMhrucw1kGkaAWyS8zQp4+EuqHs7Atb0XqZdnKldzOa4UYYbHIdv
+72IZdyL2VVo3SKrPHZNm8CTcOvYUfLDJkieF8Jq3zlubKGfAxoVg6Nxs6XUs1TXC
+zWZddqgaNi4s+NApxUFCEenTlv+LcoA4sEj4G3E1ElrqiP/iTGsMCfslVhWwXhGl
+PN7BHLICNYVW9HyKdNnDKb2kbTg3sGs0lD7BvjVBq+sXXBsjRBgNq7YlpLaVu5JE
+vnuTSUFRIUZsY/gKQr+xdS3oQegHLuej606PNbpXdngBHTQV7MYuOqf5uUGLa9/m
+VdDJsXw4nwIDAQABo2swaTAfBgNVHSMEGDAWgBSbK7JKPJDFblABySK9Y84J8Yw9
++jAdBgNVHQ4EFgQUeVtfJzYHp65HDuqh3SrnkjIrRTUwDgYDVR0PAQH/BAQDAgTw
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQsFAAOCAQEAbrtr
+dAQUuu4yakUr42oGarOU8nJ2rEwFUelHSVXUmMN+rswPb4OrmBojrunFZs++xAkn
+L5VVoGDgyuefaquBFvXYB911Dz+1O+7McLXgRCj22fJHgEDMnUFKah3I5bFuZHnP
+RX+n12Up/9oxAHsafaTIQNhylkNbTO1N9dvnB9lqFGqNoyww45G5aFOVE55IeBhi
+KZJ8U13zQ6lcxpbUcW/SSGrfDrQfJeJmWHf1nBSeQZgSKWMBlfbWTeuyscqSBBSN
+3eZSFmyW/Ks0zj3qHGRtYi0/nFc1XpUWuzReS8DXKc6+YaAshT2jhzZctY5Ctmrv
+sCRlwOfchMmn1w7FyQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 35 20 C7 01 33 EA 16 11 B0 87 DE 1A 48 93 90 F1 6C 92 0D E6
+ friendlyName: Valid pathLenConstraint Test7 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,774AD27661212217
+
+H5pQ9/Z+mDBytoFA+PeB+lBy0p5bGjQhRvzT8LOME8QpFrMm01XF8u6wHy+KNQpv
+HB9F9ggWTnNayrIj2y4ei0/hRf/Q2lqbLn7D6D9JJZToQE/j2E7F1c7MZHgR9kJv
+1Aefeohu09PYYacXVAb22ksmV4TJy24+5pHtFWSZlv+W0g2MG85dCiuYqquq3dFJ
+pOiXESa/C9JjkYN/UCmeWrNdCsXBPWFrvi1XWSyluAE+TAVxvRBMEqUbEt31aWQt
+UWyyE6Onk8tciIm+Uzrb7zg75NTo/S7SfBlHm0gE6/TroPo+igiex4S7vXe1ig0n
+0w6vO0tXZCGIfd5yglkSNeYZD9VUhpLvZuIrIunlvOi1bJECnmqa/JPlVJbFht7i
+0nIAZEMDyngToFiOo3gdMgvZC4/B4J+IIsZ7k6OlrXhl27p6pdQ4oXkK0ivvx6E+
+kW7iATMALxcygaZJkAOjv4c3vvrz5YGyAXnDIwbeY+KyxOHVZGHvIlgRt+hoahxn
+MlzdCLAXB6Nw2Z91pF6jaw0D4EbU8NSRrORvhyItKzLdZ60CkHSyNw/MFhvTvdEZ
+cGCky3pdEdZhkZHxPFIUQkR2GsiuIy3kFJHxQAO/Z/npXUYZ6u1eD3Fat3hiqFS4
+AlrNmI0/8BKkaW1s+EFt+cucQMntL0xsTsZLaGl+TUFKbSGbJJmFkt6kRbQWKv77
+97jBlChSscWwr2UNIt5guLrT337/4/afq4Fh2LvL7pvn16Q5mRz21ajawd1wzvb+
+Zu7PtH08ZgRw/RtKGVK4hIOPXyRRegWPWIJoPfwGDUY4ApuThe7JY6yNhvn/JNVe
+w+wh49nfKgJ284DmbpLqXMn53z2dhg+tLiEwkufCcItqsy0Z10r+y3IuOnHnQawq
+yaW6rF6ZALVsZVshjzRx4b3mWs3gWcbNtn/IkR6ne0vDnXbfklpmsdNvoLy7hlgs
+f+hDQ+5gAk7FwWlH86UFAQF0KPYLRnNsaTNDCkAu7fod5PpifKS3q496kgb/L07V
+8/ZWhrKOz0DCSxo4pcuOLho4Ji8DFjOvrAB/k66caNPA9C/axnPgMU9GpIlve7G1
+68+nbbmlJn08D1qq5nzIOEnfwvB4hB6hAEochf24Hpw5Fcs1b89HnX8zf21++V0M
+yNRE7sE6VTHTaOnmDUmzuN8NtmMM79fHd5lkLkW6MAo78fj/lagnu233DZydDYGS
+KoGZXxsfZNHcDeLYiYJdQ+aV1H+vFq3nMQ2t6oAbmRYljNQd8PpNbcR2AQpeYbzp
+37D74ffjVbHlWQSI3JvxNUR2PXisT9aNG7rPooUUZMENhBf8VVDQniblEE2nW7ZU
+OYF5vAsFXhWNA9YSmcOK86V+pFwj+bcqaBnlCzNZBS4tVbN1KhCQj5y6jthkSMMP
+Aje1i/Ww61wvebKmB/XqxcvR7OfLUohYxMgIuE1goXiOltGbpJWv6YorrqWDN+mG
+PgfdGj+Kj43o2ktFNY4BTtW7KbiupromJ+7b3F/rTgo63TXMCOSoQLZv/Q53AWlF
+RSDNvA0nMB9kMv80yb8vhQevQJCdtWfLv8kFPM88AX7sQ0zspHqHD6u8y8vmCO6W
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8.pem
deleted file mode 100644
index 4dc31c0a1d..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8.pem
+++ /dev/null
@@ -1,108 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICfjCCAeegAwIBAgIBGjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEkxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEeMBwGA1UEAxMVcGF0aExlbkNv
-bnN0cmFpbnQwIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXXXPbNnk
-MU3wxjjwCdA/Pj+lwkDk8WSxKGdOrcPMnFnrCdUnSqEES3K6/T7JRQyv6Y13Rt6w
-LAhrQI94UBcsAAQND4SOPyJUE3PonzcolJQ+EzkSB9qq6cxJokxTvxVTx2VN7bN1
-RJ7FrWovHu/vmKnwsOy3zv41U6KBfuf04QIDAQABo38wfTAfBgNVHSMEGDAWgBT7
-bNQtgZ7KJ3qeDbA86pq8h/9J6jAdBgNVHQ4EFgQUIQy1AXZ207MqrCb8qqZP8tah
-b0swDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATASBgNV
-HRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJUd83zrSjxfaGwFdTCt
-BSI1mTeztSKFxIzrWeTxD3C0JHAxt1oM1AN8DQ/Ej8ja3rxhzsFQaWzdi3ixvnGr
-NbjLZH7EPWBPSSC2rTAcvLzVs2AuPsBkv7IKxg7HTJZtLbXDOIatWT+24OuKwTzE
-6cbcSe7zaz5qdojy0B72dLHC
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid pathLenConstraint EE Certificate Test8
-issuer=/C=US/O=Test Certificates/CN=pathLenConstraint0 CA
------BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25z
-dHJhaW50MCBDQTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMGAxCzAJ
-BgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczE1MDMGA1UEAxMs
-VmFsaWQgcGF0aExlbkNvbnN0cmFpbnQgRUUgQ2VydGlmaWNhdGUgVGVzdDgwgZ8w
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ+d2dQ2by4x3S9c+qiAbIuZy8fID08F
-m7aovaa12yHhqJ3IzwCS1+98Gu23ZZS65gN/dW1buemmT4JpkyJ5eUPiw5HuxN2n
-2pvbRTUJWmEKu1CL4ZdhDaWZJrzu1Nh33imr4KOz+JmYCK+GoYPtgBbWVfCA92B7
-DSHq36MTczl/AgMBAAGjfDB6MB8GA1UdIwQYMBaAFCEMtQF2dtOzKqwm/KqmT/LW
-oW9LMB0GA1UdDgQWBBQOVClwok24sW5DcWf/ad9B25zw3TAOBgNVHQ8BAf8EBAMC
-AfYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEFBQADgYEAIy48NtD42z00ZliJ+YZXUEU/rjppUQ19EdKy5ECwUPNl
-/2VPgN43d5eaOB3e4YxFHG8E0PHYy8dNTZo8dlIRRUZzSswCzuJuDYpVi16vVkeO
-N6+gI9xXcd4AMBcbjpyCDuJsSlV5xyIVfgocdocT6kasvJThBiOYDfH7QOWuSfw=
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=pathLenConstraint0 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:21:0C:B5:01:76:76:D3:B3:2A:AC:26:FC:AA:A6:4F:F2:D6:A1:6F:4B
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 56:7b:a5:e5:64:8b:31:64:fa:9f:8f:a3:25:ab:8b:c9:c2:ba:
- cb:b9:e3:5f:3d:e9:b9:f4:f4:f4:d8:00:4c:cc:9e:5a:36:b3:
- d3:53:12:aa:d5:ba:ad:94:a5:21:16:c4:9c:ac:3d:3c:e3:2f:
- 53:69:97:6c:2e:e5:82:98:31:e8:47:f9:8d:dc:ab:e2:8d:ec:
- b9:3f:b2:61:20:ad:22:24:f6:ff:90:4a:14:92:38:0e:9b:80:
- 3f:1e:11:f2:d8:7b:fd:d4:0c:90:06:82:2c:48:f8:9e:7e:91:
- 55:0c:21:e8:dd:95:ac:90:c7:d7:02:af:84:f4:23:08:bb:da:
- cd:a2
------BEGIN X509 CRL-----
-MIIBQjCBrAIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50
-MCBDQRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0jBBgw
-FoAUIQy1AXZ207MqrCb8qqZP8tahb0swCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEF
-BQADgYEAVnul5WSLMWT6n4+jJauLycK6y7njXz3pufT09NgATMyeWjaz01MSqtW6
-rZSlIRbEnKw9POMvU2mXbC7lgpgx6Ef5jdyr4o3suT+yYSCtIiT2/5BKFJI4DpuA
-Px4R8th7/dQMkAaCLEj4nn6RVQwh6N2VrJDH1wKvhPQjCLvazaI=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8EE.pem
new file mode 100644
index 0000000000..def574ea90
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidpathLenConstraintTest8EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 9D B5 8D C4 AB C7 8A 47 ED 0B 8E 26 75 6B 5B 87 3E 5A C1 38
+ friendlyName: Valid pathLenConstraint Test8 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid pathLenConstraint EE Certificate Test8
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+ZTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+NTAzBgNVBAMTLFZhbGlkIHBhdGhMZW5Db25zdHJhaW50IEVFIENlcnRpZmljYXRl
+IFRlc3Q4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAveE/VqvYMxSY
+iJYipDWVtsy+LSoYmzW01w7agtChJFU8nyyGfXETdXJXUhqOSQ3KHMNvheRWUChQ
+LUApGvj+ZDYL+ABokDzyYxMpFmPs4GtaTWrVpSKNo+3e/hgYdm6/YpV4cr3whrrS
+XAXSKoohKwcnJaXZEWFp8bCsyfo6Llp68moO4pXxey396KyGyiTHdU2AnHjx8Uvw
+EsHFM2JRG4cQPGiDyEkteKtmliJcMI/q+o79TwXCEYzXNppTAiQ6imIDSySH3iZf
+RtRMLrTtF3SbEl5tfTAji9nQd3H2kHbxbnT+4r85UGhRdkeJgvfbTcbNhbpGjnA9
+WUbG+CWdPwIDAQABo3wwejAfBgNVHSMEGDAWgBSbK7JKPJDFblABySK9Y84J8Yw9
++jAdBgNVHQ4EFgQU+6vUASuM8lSGUTbsCFGmxWglc0wwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgH2MA0GCSqG
+SIb3DQEBCwUAA4IBAQDDBgsAr0bbdHP9DpawET8C9+cNstGtLgnhqosVaNxheg4m
+8xLOfbXJG9Y6l7Kuphw8TTCOgV4bto8eQM8tyZSr6lLZ7C3ER6Jwjw8GlrNNliFP
+yPyyIGPTT/NG888eO9ALyGkCFNych1QKrIgCaTTkjCnDZ4AfUmOLBB5DPA/Ryhu7
+VLxbwE/zIKLrRb+qRozC6mgZM/om459sQcvgQUQpjCrjZYD33ZLoGVhcs8Rb0TU9
+/BA/pbqF9/0qsW5iwCq7tEm6Kz7vtVkJnLqOt7zlh14HY9QP4ddfQFbZxg0okyns
+VADqsOn9RFxkZZdFSXKvYVRnndOtJplE/WBSg46l
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9D B5 8D C4 AB C7 8A 47 ED 0B 8E 26 75 6B 5B 87 3E 5A C1 38
+ friendlyName: Valid pathLenConstraint Test8 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DED4F5AFDB5C4F37
+
+hyQrmK1RuvLrLmXo6ZpzrGzbkHKLFmXnpt6NBBdQ/Sc38erd7XPw81AeUdnHMkPB
+ZcvtdKDLEaI1ppBTcbE9lA41PaT2eKS8wZ3V0KA1KkeJ209nxM/YGNoqSxxSuAMU
+rucC6iFp63VvMlGIGNBV+U+oBPpwB/0uz4yJ5pRhbG4JC70k4crOcGscUoVjBU6X
+v+iowvyV8LqkqOdVBpBgII/Z1QKXyukA0z4sq8sJOKbPlMzOKfLSs1IMGd1FHaxH
+FM+V0zV3IU+KBpspDgJH7wNAdIy4OLu8eGaAGlWYwvzZskzWvmY1EP6p3yZawv4b
+k56ctK2daF1p3NuVAyltAOGccDTjJv6L84O/szpgU0AlddwirDP0FsIKScSeZ2jo
+0sqcCgd245YchiAaDxb99W5XTB3ekld4Nz8q3iA6Wab0piyuyVg5+sn3E4JdVj0J
+/i/8WRIuXeuxx5m8oc4mFT5bnOkzVqCG0hL444R3gmrJbgkpk5O9YTtbPztdugPG
+wDBKaysIRa7gHLdhqO7Gg5u4w22Mn/DGDfPgmJUVIT/ibCWBK87IMv3MkORKVOjs
+0p33cv5pjQGw1ZIYjSZv2FegUqtApfglZXzjrSZ4hpPpaadb4xS0I67C3zhki2m3
+R8xQWgYlTGnLtQWOE7ZDZ5XwBd+VATpYDewNqaRTc3CMRb3NsE8biBaG/CXv3mBy
+HYmXOeR3zUeIxIK59VcPwKk9igZpda2Vev9+NX6w6EDTXWnqRsrEUWUtDb3U2oCW
+W4j5aqJMeB/fhNZmVHArtT14lRN18GwzyZT0gtNzGqPACiwMBwb0NGwONCvJkmdI
+SZXevRKYJT5ZEB0k1sq+Z/mr2wsZF0tUyqgSd6qJP9jhWqPsJdPQAUkgwPnn5QlN
+4dGc5WL/qsuUKpzogBrzb0eij5i9Sgv2APMah4+t7lDKEDphY2KTmBeHAvpvWtoa
+HkUoeWjoGKZ39ajPkiKZnYoV92KjZt0c6uNU+mvecBaM+vWqdzbr4vRoTJNEvrOH
+Y3HJejQ/0JWVMa7t39iuI97oLp2V+y7mvMIYYs+brarpHwSwxBjdzO1R5Hv7R6PJ
+VOR+g7hn+RaiLXcfmRqJ8A4M5sq5NAEHCf3Ceoir9SWIlMH61oh/vJynVqsLc4zV
+l1oZNrDdVp8+12yJluOCXXCDru59ItB1cPVLxPr2EB0oQbdzdmxiM0+B3TpnJIDk
+bLh1TETbKqAt7oVbbZK/Fn+FaATYsGyIbflCGFZ73Oi978eU2XsjrQ+GeH+nBTT1
+hOh475CVmQtdBGnHIggEgRGTUQnRuXLRJk5G3F1a7OgCdUT5+e8gsWbICDHKlDP7
+RAJvo5YA4nBP3ajxZeb/XZWgGyMC6WnspuzWqro9HZJ7YeIGsiitpa3xYNdMO8L2
++oMqcV02jsIthO8yviN8gdBhMRAXBlNEdx9kp5uN2hV5NlWHJG8WdT65lQMWl31q
+c969D7oFXo2I90zJix9UfpAxSZDeGzRy4FkNf+W7MSqY/MnOTUmvFyZCXhlk0QTX
+Kc9AEHwGAfwqgh8vz0rAfNm+Hy5lfkWHCqHs66G6EoeUYYSzt13B/A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3.pem
deleted file mode 100644
index 3f2ffa9bf5..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3.pem
+++ /dev/null
@@ -1,119 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Valid pre2000 UTC notBefore Date EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIIChTCCAe6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-NTAwMTAxMTIwMTAwWhcNMTEwNDE5MTQ1NzIwWjBpMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxPjA8BgNVBAMTNVZhbGlkIHByZTIwMDAg
-VVRDIG5vdEJlZm9yZSBEYXRlIEVFIENlcnRpZmljYXRlIFRlc3QzMIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQC1uwQ7EgYKGk7IBOZd3vdARgrWUKCEqjpfYUEG
-ZGlsC48omvxCrzR+eJj1q8TeHAsH3dAcpkbNNWCWRHblq9LbqkhpBaMquzvg541B
-TNerg9dj4vjwV0/QYdbvyLVcKBv9iLE0MCJeSLcaseO2vYmNXObSXMTf74BXNR4D
-k7uI9wIDAQABo2swaTAfBgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAd
-BgNVHQ4EFgQU9EsyhAynLAz6iwskm+iASoGKdMowDgYDVR0PAQH/BAQDAgTwMBcG
-A1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkqhkiG9w0BAQUFAAOBgQCTLQM+0YBT
-3vure42KCvGYSQpheOtLtv1bLa9TT4kbo18aNRVQwTOnZLtKqKa6etoxJ70rhfO5
-x2uCELzyIkUrAbjyqMYg/0nckc4HTEys4xmbHjiyWPie/lS757sA1trwNRntBn9J
-pdkDmwEqALaRBRH6YH3ybrNMZh5h2CVqFw==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3EE.pem
new file mode 100644
index 0000000000..6e9f5c98f7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/Validpre2000UTCnotBeforeDateTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: B7 DD F1 4D EF 58 4D BE 7E 18 5D 84 77 1A 83 8D 78 3C E6 26
+ friendlyName: Valid pre2000 UTC notBefore Date Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid pre2000 UTC notBefore Date EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=Good CA
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIBBDANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBD
+QTAeFw01MDAxMDExMjAxMDBaFw0zMDEyMzEwODMwMDBaMG4xCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMT4wPAYDVQQDEzVWYWxp
+ZCBwcmUyMDAwIFVUQyBub3RCZWZvcmUgRGF0ZSBFRSBDZXJ0aWZpY2F0ZSBUZXN0
+MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALOY1i2dfQm7MR3F7FEB
+eUvqhyz0RVOJ5W9ffzQpg8puuROsdevN68qfhN/GTIHMLmeQeEv56Zsl1hRIKMqB
+hDpOvSNoaAeZUGJpAaMBzEdEE0KyVlh70u2IaKk3JYDzsWhmbN4ESXFGpmDccsfZ
+8kFZo+XTapSeFEc5ETbyVIV7HHPE54zPX9Ce67kJI0e41R5hsXUKFBA7ORycbcFh
+8c8sN3mDYhFFX8m7a2qTN6oHQ6I1fReKKOCfYDs671bbiyFCQWNl+7Ok19qUVOgQ
+L/g2HyA1YNvueh8ivNNRRwfv6RTPwhuOWF5FyOXRCTzDaS309Lb3TN9d3a3kAoEf
+HdMCAwEAAaNrMGkwHwYDVR0jBBgwFoAUWAGEJBu8K1KUSj2lEHIUUfWvOskwHQYD
+VR0OBBYEFEBvkKgDjazQ6vxQ2V37VnUlYMSbMA4GA1UdDwEB/wQEAwIE8DAXBgNV
+HSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQELBQADggEBABDntMraC1zS
+kjUQmdbhI+l1j8Is7ApNjb03/Hgq8pjDxP2VNPEy9XgXYDOHaAmt7p7jDYMwBxzV
+7TSnFIvR3kYjb5k7YhCMIQXkJJgM2QvZ8m0B5c9YJI6qktAp2sxPfzLuBg7fm4Oe
+BqQ6f2NlmLorDqhXG3QSJmXWRXMxti4rWz4mJfuWuzPdZERE9bJ118ijfksQjGfu
+pjoWizxTCt8kRMP9+RSD8Hzipuxfc2JPn16fNrXMkyBtek82L7tNo1raLueyPcEg
+Z5RpwEX/C4nlsQV3JS2viDxhcdtgcmn/A/ho7Ta4QazDqWjQywXExpEpgrp7ExFn
+hiss7AFKddQ=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B7 DD F1 4D EF 58 4D BE 7E 18 5D 84 77 1A 83 8D 78 3C E6 26
+ friendlyName: Valid pre2000 UTC notBefore Date Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F9DDFF4CF96218FB
+
+sVadNk/UvBQDZbxN2NFbq9WxOo9kYW2VX4+k84wYn46Nrt7as5qaRylbQT+Bm6SY
+q0iqyirdbIHjwlAn7AxHY5fJ1aofnZntGDWZBgMWiZTIjeQ1syx1UhPu48R9kLrL
+i1fqiwMD7h+qa45uG5Z5orx2+m+fBjwIP7kAQ5z/KMqq/1e64C2yrnYIohoww9xF
+BFBPS1t+0diJ5ZqVD5p9wKMAyPI2X6fxa1J4Ra2sF7v6MVyfRWAobwOxNuyjLj+s
+miewEizU15fQRCaavhBTh1fAmo5LZjkoW+LPyOyCNp2GGLG+NmK4CVNKoiQ9NFSh
+oPKOKeDvbo6U9rLTFdSEK/NkHT0J5g62BkVLyu3JfozAViJS4vGA4hzCOtRdkvB2
+ZQpEkQTWlC8fAA3z7CeHjLi+Tedu7dzyGAU+E3WBrRC38pFkTKHATer9nuXwggxl
+myZXt6U2YoOEeH34Di0+TOaBezIyBaHDe16hg71A8zv8cqohkrHK0RUyUgz5vDqZ
+YBBKJWXNWfIPLEHwwgwjrT86VQgdywgcl4/CyxhpLntj5D04/Igwr3ITGU3mANrm
+wxU9Zo+/DaqjgcSsE2lggewkYL2/44LNpK3IT3GXpOIyljY2mIVEzFKLYFqmtXEJ
+UzKvxFptkuewmICKyguKkPbZZI85ZMpli8i/jekktjR+mHwZeuJ9XYzQ5UZF/zwD
+yMUKdUs4UVDmeLOIywmSZCK7hWnBVv2+uz9xSi8o7M//tht303QXKoIbNjDgarpv
+xp33Vnw1+cDE4mWQs6plfNtZjrSKqWGq5WqnbNgqkaVtEK+FHcxySYE2MhCyBEQL
+Hyewk31/awnzaxGWIsJnGB88S/n/K0MGsqsOJx6bokXRAVGAI0cqGOQR3Ka/ejhm
+DL0lsD2XTbGX4Yb/BU2bXdRail/CHl5+bHNdWLiiZdKWqZSgtsYk9O+sjcsAHky2
+VOuHY7qfra4koiGZraMkSJ842O+ci9Ng1kUhfFhfrnqdTgFWlss/vgNoZ2lcKAUz
+8uJO2+yQbVEENv88HcCihF8DgSv8s04MYmlzHWOQ0WKiniPd9BwjNeNiQfFaEUyv
+oWWEP84f7jh6yldRCT2UocSEpwvL+A0vnWmG0pJOWjQj+CPYym06KBSyjgI9ECez
+lYPl0oZ2yI8g9+gd9aS2yKJl6kR+Ms3sYCufXQmgJU4NV5lENA4Q6IL5Tx5KuHwm
+T2mUkLMC4qI24WqIrjzzcno/Y6jGF2PZg5W5l6bR0ZpyTzpTVntJrL02+5wCQo5V
+4pVnu3Z4ObshGRAkvVMyBBTLYo6tyFs0PwC7MiP/Y0FB4uBRxDKmTWMMhilKiH1l
+IGood9SKQnqDGf5ZmzIKzvpa9cqNXu2JzPpThjikbJFQwccakHEfV19gxwvK1Df4
+jdzRLhMd5/EUpo9Wn0iW5SMIM3PYx9fb+CSfBgM4e8S1xE7Q3tfzw6MkNFIYRTGy
+nvTcqRdsLmpmbEAq2V2foqwmAcKeMZErF9YL24LTJoXeyjkU0GtOdOA5jZQYyffw
+ZkMvxcl0LJaoensvn3IgNDaf8cqYYyBU2ABnFY43iXMtveEaazsycg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest1EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest1EE.pem
new file mode 100644
index 0000000000..f7981cae35
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest1EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 8F 26 DA BF 2E 12 89 D5 EC 6B BD EE 9F 35 1F 66 78 EA DD 3E
+ friendlyName: Valid requireExplicitPolicy Test1 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid requireExplicitPolicy EE Certificate Test1
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 subsubsubCA
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEsMCoGA1UEAxMjcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MTAgc3Vic3Vic3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcN
+MzAxMjMxMDgzMDAwWjBpMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0
+aWZpY2F0ZXMgMjAxMTE5MDcGA1UEAxMwVmFsaWQgcmVxdWlyZUV4cGxpY2l0UG9s
+aWN5IEVFIENlcnRpZmljYXRlIFRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsIqrLD1lrY+10wadJZYPQPQ2cChNLXuM+Aa4S1hCl3t3UlSsh5DF
+8w5S0pJXjCYhsbzJu9jWxg6twBoHfan8aSE8/syGc0jyA3ySWxNszCvYzL00PGkb
++r76G/q7F9M9owZYrfu9tgjJWM2RG/9YvDH5ymvz2fcTgeP2mLr8fdqkZ2FyGLvT
+GQFz2yu6P0+ZJ0PrL/jp6KPXAqMbAQUE8buAPVDliHyPN2gVQW74ox0IRLNnJZY6
+o4YamrGp+RmadFyJoPGeTXrHHBo7VBl78m6bEeadNBBP8J6l3hYpEvREuu6/cbLA
+hqKfCDwdhDzA/QzEhRNAGqiGBlRcvoM4oQIDAQABo1IwUDAfBgNVHSMEGDAWgBSW
+jHH8Fag7ztnE+MPQX2lxfOgASzAdBgNVHQ4EFgQUjAmT8zwTrGYzjB1+ZnT6CY6n
+OF0wDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBCwUAA4IBAQBHABhR2hGz0n3X
+3P5bDWSNmMpf4R9/4Rn38thteSd+mOukGv0Mw/cXccH1squBXYbBDqlHPobbhRWn
+cfxVicf16NvVWj0vxEAfhDXpZ5Tfw+ufUCRs+ECjpZA1Gocc/uxz503iTzFFXSFM
+CE7a7Qq8vDA+MnVJgdalnVegdmu6u4dQXtmNcX7sGi/FqrbGGVmolmuo6K7LCjF4
+Fgk8IgR7G+Ks7Dd5hZg1ISu+whMonRCV4zhoSX+A4tc5UQqVlRbeJN80Xtzznl9G
+XtuZuBvpeM/VSMucSwd2RRr4r803wVsYIGBTv9KoyyPy8oF6vqlxiJOe4Iwbxf9i
+la8pgfuH
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8F 26 DA BF 2E 12 89 D5 EC 6B BD EE 9F 35 1F 66 78 EA DD 3E
+ friendlyName: Valid requireExplicitPolicy Test1 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8FF5F62B80CAAC69
+
+YF4ufMIHioRNMyadtg4RaIYhMfzpnA8erLIlaL0v8PWq/t0Eow0ZT66Kn9v2TWnZ
+pVmbhn+noiiT+smgpzzhUkzzxnwrPpZgS6bax3/TwZIy1i2HwUJ2a6pE9W5Z6QIC
+kDZanGGfgF2y54apDc7odbeWEeYgXDThaAKozd9dJgIaFgeisNB0kLTViZMgZVkz
+4MXCMocaYShe1TBqfwgBvDEWyeiKRgV39e1JTtgGN5iPH+biExQqw1qG7+vQKY4t
+tfPgAfgtPPog82uwD9W0KGbGhBmX5mBmfsLhZ22bkcMCfAi2kbzy2HIvt8mPx/gN
+KWgZ/JmanFzvb9ajZ/DDsH39odBIAwqF6jOmU71ujfmWgyNTjYA3Xy2eduBKLVxR
+nWIGSA+fJLqmNcKRudq9rcwZ1V7gid1c2P2W2F/NCU1Vnt2d0cOcoTh2Dgb1Il6M
+IlT/f9Wm/xEoAHKQpoC7kIgHDpTY7H879BtKKPoXn79U1ZREH3LkbkLbmo4ALLu1
+++YnvafMIogNE6ODKkPu7T6fMfmLfIRoOuPIPKbDLec+RkJaXIl0XJU6ioWm+vQ/
+QWxmyGdEpSCCp78+iBMWSuAFi4rQFvfJirYgekwFlsiLKHxZfqaOtiV7x8bI5ztt
+E2sTeOh3NtMoIbYFBjalvaElmoG2/9MHTppJc1A8cSpPqX1Bng8Nwv605PX3oNxR
+/R0N6tx7H9/8r/gdHUhuc8iV246pTwKATpGbZFfWc7fNXoLELWUtlGf8faYlA4xP
+XgVSyFCspolQNiBtR1iQ1OlIS6z5zx3fGTd3akkSB2IV8mOLtTh+8cZ+VdC/oeB8
+XDqDAg8biM/1GYfpt0YsKNZcKeYkmpTQfes4bPrPnhUCyvYJjSNc6S6+dA/MgkYB
+y7JHZ4meQA9aje0a/iWi3lh4oGvLZio4BGpiZwCF7ll06Rttmu7jD+zvDMrlA6as
+C2NeHjMPo1/l1bj6X79SM8wIHVaUCFkur/7iiVBNQn1BMDsqNtvIkUSyCI2no20W
+hdnY98NaCg9R3Enex7POxBGPFh/vzmXUYsX47nwCO/+StaG0r/1iKGA7/XwX3ptO
+i7GR1opOcBSPYK72TSzmqE3GDMxlP2ZInewvTvBAow4foSoe82yUvGu5MX7q2qnm
+/PvklKq8OJ44zVg3pXYlzBFPkWkDZG8VeiIJn9nybVKS4+7XWlCb0U3dlDP34OhA
+y0HTdwISE7oiX8XA/ku84lJebc/sSYCtLS3Z9HHOXoGSsb0wvUkFgjhBZS1Z9eZK
+7DyRAGNVS8Sm0rdvzipQAEJ8ox16zPo+jaYaeY8wZAlUWyCec4fGl0Z+EnIqd6uD
+1Df61nlUhHlovyb71hmQ+2scGrmsaQ97yWMB8hyhycRqgcVUqVNbayZaLmsPlqlp
+uero065thgat1yOkPy9jTjH0+5kkhWZqCcWhsmvi6jlzGedtYXi45iE+RQEYFFjy
++WHcxBeHaw7LdIys8gAJ1QhcQ07dHelpn+E7QXhajMSGl9FzrkwiFaQdZoEzX4xm
+19JeNXvTzqarBBZrsixr46aYtyxgqMi9MDuUWjTH4hLNW4jbvZbAxA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest2EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest2EE.pem
new file mode 100644
index 0000000000..bd5a6f0a6b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest2EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 2B FD 3D 65 0C 9A A4 81 DA BE 36 FC 7E E3 86 9A BD E8 ED B6
+ friendlyName: Valid requireExplicitPolicy Test2 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid requireExplicitPolicy EE Certificate Test2
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 subsubsubCA
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMicmVxdWly
+ZUV4cGxpY2l0UG9saWN5NSBzdWJzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGkxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTkwNwYDVQQDEzBWYWxpZCByZXF1aXJlRXhwbGljaXRQb2xp
+Y3kgRUUgQ2VydGlmaWNhdGUgVGVzdDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDOcG4aw+WhAULnqHANEFgfOkbpQKUodW9QaY4fNaZozY/QB3qGOa1+
+W6Mv3KoV3rEmzL7n/biP6RpjhY6MMoqD7S3sz0sbAxqeQeeY7/m0ScKlhtoiTcxy
+ArrGpsOa4clVs8F7/8y+j+H3HiawKQ6nwYzh34INcUytlLd+G6kIT2y9J7B83a0p
+HvxGVXAlVFUeUIZ1Nf75n/L0IEz91jBGHsrvvN89pGzLUPWCxh94EUeQ4uIawO4A
+JMiGozWpVrF5YU3jztG77okNVxnxAPRRs8KLOhUROkmptAAF10oBR4Jw3kQNNF2q
+eXwtCKv4naFajjV9yFoPN/wZTKDA/dhvAgMBAAGjUjBQMB8GA1UdIwQYMBaAFPpi
+ur1+Xl/fH7oHvh95N4Lc/BMoMB0GA1UdDgQWBBTT/G30XBRLcdlm6LXjOmIn6MQu
+ezAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQELBQADggEBACnxWF0ZZslNWBFt
+vPGw7c4Ui3YQRuxEk85yOkTLO9HvymgskvkQezYTGQkYThzE+8T+VoW+XcGKtqzB
+aWHeVu/S6Kq7zc7MbeHqC0vtyc3ViMFXk7Wk3gve6NBxwh92rITdtJFJ3+IAlmJe
+RHgRan6mMujqLEZFns7fs/kIOiHdhB0W+Q/33X1AKieulxOlhilH8yM6dDBn5JaC
+xVckbqTMMbeWzJU00zIz4oSNx3WvYQqyqrPVzCpVjqVFYJfFMs1FxBPNuPDovb+y
+2Y8awekxYALnFyXfToV2owUFmK2BFQ62BiG9fghvsXWYjCSdcSdkaIBNTxbCITTZ
+KFfbXh4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2B FD 3D 65 0C 9A A4 81 DA BE 36 FC 7E E3 86 9A BD E8 ED B6
+ friendlyName: Valid requireExplicitPolicy Test2 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,54FD30C4F1C4B89B
+
+4K/32g+JPsQ6CsA/MdKiJTgbVFKOuI4nbS5Vtvn4wwWZmAzXmExwJVINJ726d9qU
+kiMkBuIThNg95Ze/Yb5zD6qxjDjWL3PMRpOp+wHIhs1xiJgeSJ9p+vxwHZfU7uFB
+lP8hHvxrD5KmaKVk4TSGPhpIm2FuKj6XazuHjKlJH8RO5VLkYfX665Rou8tIyZKx
++yn6zKNDCIwPnwodkZFXqF330Qj1d5nvBqUmSTu0qhcuyIiMcMrgcWa3UQkBnbdK
+2hoeZDevhfU6vqJSuVE/zVsHBcLDFCOXDsx02fk0D4ivookTptEqwTaIdfxdkpj5
+Ptx0+dmQz4SpS1PABzk9I3+bgpcH4O164v6IGLtoreDDWjDCZy0PGJjHGjpiVjYK
+qH/51GHnqXFCG2b/Ra1RXTVY2MfL/QGcg12+p+ck2tjqZwOJVR1bK3B7pU2U206/
+g3KUcZH51w8HqnDJQln+/zNMr3X5kqKYoBckPgjswW5BjCOKGHj8wCFJjTGssNPE
+++iYx97uY7dQGU3tzP+hD8ERXaUovZalz01xEbXzIGfhbvYwbeqbMdqYfvzipTpe
+862Cvulp1lilH1EHCYFPTgGT712d/WEe3CLcVAlapBODPLOhtSLBu2ogLfebjHsG
+CWl7oQF4huoWU1ux0cba+gndivUIOsvILQbJrK0vXlSWH0hOME2UBWfWtQUusy3Z
+uoq0grWfrxZw6XM9wRjVtiyG+gK9fPdm75lqp1PX6TdV1bJ95OQFu7rUbT/TdU7u
+mcmas3hEsPkxgykJRJizi1cQqGPrV7FoqGbfp7uYcrIODQZvZD+24eerB9IpZkpS
+43VNK2XZxcSzs/V5GEsI36wO2dYxuo+AvqR+hfsPuRwMn06PCpdYk5n3sc0wHuXH
+39zGbNf0CuZZzzqrU5/bD3/bLQVNCqkUpBCMoarLGJASZNPUSxV+Ii/E8NLMXP/p
+LHUMx2SKXABcUNGvTsWqJsx1snwv9s0jPTI3YG9cWaYlJtJGtFT5fF+webRmkkOE
+SUx+8nK+KL8Ee4ni0Ty2wuve0o1nIjMqADXfuMjlLZs1F5L42qONMu7buBFm2EKa
+ryMYGDbuq7NrZ2fiYUnmRtuZYOXHJf66ixwqDBLGiUPvpmPd+rj6cS8rUqQpM/oT
+FPePDPV1t1jHY3YZK+36ExG/o2U8hoL+3FVqJSC9XaFSFHpEj/B1uvV7W9XBHbSI
+CWZ8vp27oGOFaXdd/6B+5aNENLuFNcA3OtWECGXmZuY6wpXKtlPKU3jpB8ByHcH0
+DFHNYoiukWdilRAfxr+1R8M8akguJc2JwYWKJm+YzTSh96GkLANnfhvFBYXf25av
+LH78qgYOSSD54CK+HBNjrD22iNcQKeX/WjZohiJvES8ok5mgslLdHguiSUpHJQwv
+N6LCWvDutfbYfM9ctlaLBvnyz0LqZaKEMFcWUKK1ZcHlF9d8bkaRLUZS2QC3Kcda
+B+pbo14k7RTqVS0e0CaWOQYtw7LuI8/81rg/Du7NubqlMOuhybiVx1hPiz74uUyY
+g0vMrGT0qlmlhfkQhj4tIyzaLmTu1giZ0QPG4QlfkL6EyWf0vbbPr1acyf6HRSyx
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest4EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest4EE.pem
new file mode 100644
index 0000000000..e2b855de2f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/ValidrequireExplicitPolicyTest4EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 06 40 C2 10 8F 7F 28 EA F7 59 3E 00 0E 09 7E CE D3 1D 41 BC
+ friendlyName: Valid requireExplicitPolicy Test4 EE
+subject=/C=US/O=Test Certificates 2011/CN=Valid requireExplicitPolicy EE Certificate Test4
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 subsubsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMicmVxdWly
+ZUV4cGxpY2l0UG9saWN5MCBzdWJzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaMGkxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMTkwNwYDVQQDEzBWYWxpZCByZXF1aXJlRXhwbGljaXRQb2xp
+Y3kgRUUgQ2VydGlmaWNhdGUgVGVzdDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDeDxXcQyw8uZzj9sUOQ/0sZRELT3exJGteTsgMGmazqaA7z6mdqc+Z
+IN/6xj0Ub61biiNXdOfGAGwd+l3mdx94E33ik+1zylEWJqyr2Ovc+JcjR/z6IbcN
+Wv6FPdMPsDTaJgERvuPm2dPYViKpRDiV4BTQ5DsrGhstJGsT/K04UiIB6ahZKN6/
+ToL9OTp+Sj+Y4DAyxl8MdmQWgJpzmo4yeDroGyA4Ui6nTMgVcK2vPDti7o3yjZVe
+rkAqf59Qf6PUtsUXl+eprAQ6gfV87Z8/3K0d/n7QnYg6KcAIUxAnwocuJOp+TqFV
+W2+G9ArW8qdpsLmZqUtj/h+STuUj30mxAgMBAAGjazBpMB8GA1UdIwQYMBaAFLXb
+BNbIIAgvWkHHeKNEidrOLmu6MB0GA1UdDgQWBBTSKJ6JK4Bv9B3Im8QAxcOiq9ML
+DTAOBgNVHQ8BAf8EBAMCBPAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqG
+SIb3DQEBCwUAA4IBAQCTBUOuvyS5e9eevtUKsjCPLpfP/Daf+43KMxHIvLUboO4B
+8KWd/245AIioGgK0vr1AoL0cvOyyYvKuSbi/j/M9WOzCCmgrzrA3mWi9IHq3gv8X
+zWag7VWx4fVbQVQrqseyAKouMZDqWp/rl++IbittXlhcHi54qZ2LgO9gydA7pXN1
+9LOpUOi0mP0wFDfDoOpiNOGJHg5SLuwQWFtEzcXrqJsjtoNigtpXeY1S0nt9u5Dt
+FQVk5FOD7S7SKIuy9QVuCDelDxFYU7zOGNq229S2yTa9dJVym24aGsrJU++XVKle
+FM2quSZqdJ90IpQS3FMQu5XIa3iLaiMNkHUZStnL
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 06 40 C2 10 8F 7F 28 EA F7 59 3E 00 0E 09 7E CE D3 1D 41 BC
+ friendlyName: Valid requireExplicitPolicy Test4 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F3FA35040C7C371D
+
+dQsQbeCFwSq7SCUPBso/WtMmHv6wYyZZb/qav/OXAfwMY0QGT4PYagzG1wtNottx
+U7+5VJr8eXxiOWXOxQ2biq0zmOKYZ2OaTw9NbQn+ug256qLvFFvA3oMHLw8TmrNJ
+L7IvX8R/qrq4C9vAMx28gwrfSykAhpr2Aam2Q3FtwtZi1X7OaaMj41rX1aqWAtJF
+ju22hiYtY9NteCBmw+S4hlXfmX6MbRT6AWS4jV4hQ0x8O7EMOEGoltCqpmnpn+fD
+Bt9Igui0To54xBinjOM0M4Y3L02V967AUP6rxm5sgZQk3rDvYOlmSTVESfFGjCjn
+nYrK2VwH6wasc4vLuNqhjKg1A3m+QyWjdbPX5xG6YGizYQFBhn/0t7uikMSoEJpO
+GSD9r0C7pbRtOLB/GkMKYADpjeUe14Ri/HXiXmcuoinT3pFuml+eT33RtiiWpw61
+YpAbmr9TxHOewyWwdbkIZXE45RH+MxXNXDyKOzWrDd9GobaLJfuoHYo3cllVvYyz
+YetuCr7/DhQ8aLhhQ0HpF6/3ojS57XZUW0Nk/2uJXCg/6cXeq9NbsCnfpGGrwTUd
+TptQjQfkKx6I3046c+zNHgy5oJSC3av0jQ8wLfioPTdgK3ZIy+AOsPTdSDTZNGXt
+Fbg5pgSBDyemqb+JWq8BWRo1MXliYDFmNvS/LTV74MpC7VRtuadM1kLW9y3RDynb
+2TMmCqi3e9+w6D/kIrRrFWz3jUD8iXt/sV2WZdVClZ/qF8BCaLO6NiIGTFRDshaZ
+Ti/7ZIZvcWLRtLIWah/ZNrApuR5hvbiGV64dTUYs5ql7Zp3qq+Ohv5zf57c+dLM8
+X1AVRJdX+H8Hwvpv5aJsvqF5bCsqCF2mz66WDRyOiKyn95YJ6dh+NdnR/0S7cx7U
+ciPzpxRrLAnwheEDy5qItTHg88Cf/GYbtTBYJjbbl+xPIMtGeoyb2iEC5FrSHCEb
+D9wei6HYZaGferXGISiUyDDsSSr+71i5JDfL4td5DxQiDvoE848tY3ab6LTBKWdz
+HBTDGLvYoeTQhBVsGOfy0AFclLxNzlFF6kwyC8HuAhEQ90Yesd5cXJ6PWsFI/SHG
+WEbmKosAf4CBvzhLcoaiMrTpN1owztxlk3KE4QcYtvbWb5MFHuRBYFrc80Elti2y
+xsJIZjzwa9dRBIHP/RbM6V/qkYX2kSb4yUd6aUhEw0D8apK3fJxq1lZ/2K4KMtTD
+mmmRu/MFiAiZGgTpLcTcH0wi/FykdLDY/9rtAh3dpRP0IxRZrwJvXj85UzvoL2b4
+//aoEXaPz+Rq2Ts2/c9pZY0jOtTi1v6uk+nSedzb6qfwjPMVnDq32xh+Q500Ep/N
+hCtnoVTWt4tz+MfIcN9ieOkd0jjAHvWfFhiEEpuQTicjqhbUGdPrUJ8dgY83FVfH
+oLA2s9aA0caxBGZj3DhOzqi2X7SHsHnXL+FNW1JDfeTSWYNaPMgxPLJslH9mu205
+Owe1O57zF9FCJ7DKrMeEAF60IIVEpdQWmCPJDdsGoq70Ivbzuuix6XbFpLyA82uD
+uaFCcy9B9pb4NKvJDCKGcCofScSQmzpa09KC6FR5y5QlpfdyIEcnWllSBWNO0tXo
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/WrongCRLCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/WrongCRLCACert.pem
new file mode 100644
index 0000000000..3c2359e85a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/WrongCRLCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: D8 B9 FB D0 30 49 8A 19 FD C0 74 0F 90 8A 3A 60 3D 35 AD D4
+ friendlyName: Wrong CRL CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=Wrong CRL CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBCjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMT
+DFdyb25nIENSTCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALfS
+dqU+ffbeIUKH8y141HuCwtV0pFXbQWA8l4ulBKNt/V+03/OOkoFXFId5tyu9TvZr
+ouQruhiOrWW18bWOipWJnlr/S4n0JbIdIYduhMCD/i7JIoOgtW/3bN4T+PfvL12C
+B7tvyGTi4Rl7y6LoDMMXse1VaTzS6M9MJZrpmGa/yVR3WVKzLWScqK5gqMDXzcAH
+mEo0cRnGdLmp7hHzkAiWZEZ9X0bV5K/awcjUercRC1xJpnfJXzUgOaQJp740k2rQ
+D9QPGSM4eQIUC0JvqLjINz3OmuQtkyQTqLkU+79WskiRlM7yMNbKdlvpZ5E+iqRY
+BJaqLQH5jVTW7fvWwAMCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+
+dbZlp9ldqGYwHQYDVR0OBBYEFAwlRuCJelEHSq81r82QxHIOt6gGMA4GA1UdDwEB
+/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAN0iMkt88kC3W/eLpsMRtDNYwmtMUZI6TtFND
+oLdXlwhOjRjNOX0q8g6veHRiZTtdXI83P4KQYb3YYrc+L4/BpiGNV8LM3KDG4fpO
+Uqfj8zq8jxZNae+rblwXMgs1cI0DpxEdJXtFv4q74ILvWt+Wp5H2St7nJPobeOn1
+STGZoe4HGIQ62XdHfPCacLYIqejpZJD3QYBPHQlTKJKF2ifMAF0QaoWtjvOENBRQ
+r8sfmDqWlixChZpMDZMRhLHULiAS22Aoqql+yueh/G+HgVOaA/rB8iD8Csxot23M
+QM3koijndOFgzDGMhTJfwEQ96NXL+JptuocPwzKWOzLieMYYww==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D8 B9 FB D0 30 49 8A 19 FD C0 74 0F 90 8A 3A 60 3D 35 AD D4
+ friendlyName: Wrong CRL CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2EDBF1518A102CDD
+
+w2sVwSRe6zlBOSZmEUVzHezqJTV6IJt9cr6psogywNect7wLX8eae53NkOFA0aji
+iECUqiuL+ae9HCCDtegAKW6zq6dGjBbvFJdMhix353Q1vDF/UD2TAOvAaXp5phOF
+Yf12f2Za+aiohtobOAvnG55ddHe4+ClxxKThiCfrZeUlX0QaAsljXIqh92IR44B1
+5OCrFq+qvMoy+/lw3MTODERXWkPJN/PIO7xU4kWc3SBSgxmmT8vw3FnDLOFfISHZ
+O1hZDna9/fI6PeLfglNq9GxtehKiRxM9V6HhqPQztDLdqCrrv5aVCb3MKEev5BZ0
+kVrDtXP1GzhpL40opYeZNq03crBBOUpRSaHRDzVv8MC7L7dI15HmPiRErsAXkxIC
+u/SmB/PX2g5MD3oxTBVm0i9ezMXB4Zlan1bko+22XHmc2RyGd9+Afef7umWvd9Gj
+k2f1i43HU7c66BqN/XJUOgqCd+ngP6OdOE2LLeUc1mkgBmpqk0FWCe5mYmPnlm50
+8E7gE/z8Gjj9hJ3pJwhgcxRhdzgl14u3kjCqjHdYWsiK1kER0mTtYk3BPAOLVJ2M
+2uYqWnJqmblA6aels7mFAI3kxw93rEFlg3nNYtbIVyfY1Z7FGensqdanF04zxQlf
+rPkmWGUJKWlZex1m67N848ywLbbL+soxbnN7UpEszA5jpdBxswjGqwwBXxcHDjYE
+g38s0MlDaIpOGyqc6XxkcKgcoTedSh+pudR4FCdWEEhnAbZhp39ctzrMe99sohq9
+qs+l6P57qm5M3sTCOpPv6erbNQzi/TkGgNM7h5ti7Vq+k3VUBBS6kY1SM6szuoJB
+ZAgzuDanR7U7L5QmallaHCQurGLOhP1R8Hf0gb00xZSUwBrpa3palPCcMysKQe9B
+nCgnfWUE7V9AKwik7IpxUzCXN4Tcsl1f/M0uRU6/b4HL6aHicbhAueZdpmOcw+9u
+fbFhE2QWlPTqwgv9W+G9nLOhAxuIe6Xu3MEe163lwYe6M35F5h9ddyDWAi+CM0kB
+yVf+CE4KVI2HY1nIpxISsKAGebSSqoOhbFr30q+RMH3lCo8Uu660fZWbswgagzh0
+NgX8fyndBgGv7sF+8fi3LXt3/71zbGX96pzdCofGsXOGG5waDeW6ZTtybjPdMciP
+qEJ72iTsVF9ToQs9ycPAg9QDv/bTpeBlRlM1dcmaJE+RtM/7ajOCeGotJ3o/Kk05
+fNAFQ/dUwUDFCncFqQC3HC6zL+iGTG/ytdJ+c1kQSR716jjsaUQ9472k7EJLL8RD
+Y4C7le3vTsqvzpNHlMVuIjSt2tZNvIMBYGV8XipwNO/OGWiDXVCq8MUy8ZiXvAMu
+nlY2lKAEz/D0OVDjdQFyUQoNmffyHMQCaGjZM0yxnKzuIXJHfJGNbW98xjW4+w4S
+3YawDimZXFGpICsqSpk2pL3G0ipEg9bzatYHCy4ynlNE51A2TMmwOAkSsgDinQf2
+Dmsf4vRCAkhpzUC5vBtvA/FvJ1B+lNS0boW5Lq0E+9xBk1x9xQqXkhBwWKWzR8Ke
+b77ZC2KfAiDb8uyp2kkjtGLg9sRlBFPUCn59ZoI04tCEOTAwdq6H8pDIOhQbcZ/L
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/anyPolicyCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/anyPolicyCACert.pem
new file mode 100644
index 0000000000..9795ea31e3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/anyPolicyCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: E2 88 AA BB AF BC F2 89 B6 55 3A 08 28 EC 18 CA C4 6F 22 46
+ friendlyName: anyPolicy CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=anyPolicy CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDizCCAnOgAwIBAgIBJjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMT
+DGFueVBvbGljeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7o
+J91PNM3AvPFePimzLAnnv+BRwQSrqafBm/nheXXLVtOtfNSoTqBWoo5uF4rGyYHF
+MRHPORNZjZRBoxHho/SWM2J7r7hOOL+JJjMYwZhCPkxXjATXNIXIolacHxARaT9a
+XjfnPAtmAotI+91ZMaHiRup87ygHHtuD3Atpe0NNbnqbQzmpA2+bwqv8Ojou+40i
+1NHVTgVDk2mH3HQbPzh2C3p2CIrhPv8IDpxZcdkEkAaMUK+czXt3OEMnqzerKSOZ
+8UVxdjYtJoOeDg2Pq0qNqbwW3lXL6+PNH/zU63fr3Nqz5befHyTS421OlEIK8FtU
+lEQ3V2/JBQENdlugwXsCAwEAAaOBhTCBgjAfBgNVHSMEGDAWgBTkfV/RXJWGCCwF
+rr51tmWn2V2oZjAdBgNVHQ4EFgQUu8neyByV50LikKKOrgNcqyRgfoUwDgYDVR0P
+AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADARBgNVHSAE
+CjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAD11IPBOgXaljMw5AvmAXBLG
+LPx4zhX/UmT57NlW3Y/jbDb6MxglZr/YsXyUo8Nu3PkdqbO9mwfzfcmLrnuHrdSj
+ud2jlR1VEZz+7uzPDPzP89u+wjA0UYlKahHvgFTRedUZ5FhN6Y7iyP5b6Iq4Gb6A
+bhJLq59d0RXRsVOhgAWBo0xTO5s4e7vhzKHCQLHkTbD1g/HLW0ae7aFfCT30PpFP
+UhBHfwkD5tdW/8qcejbs0fpegaiVtOzwE6/Rwkuh4wDoszXQJo7yOsFyGtn7+ord
+M3PS80suV01q67BmW2M6F6oAU3agb4guzMCw/3d7F+Ow9d7Qq5CjabaW38Gb/OA=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E2 88 AA BB AF BC F2 89 B6 55 3A 08 28 EC 18 CA C4 6F 22 46
+ friendlyName: anyPolicy CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B1AD402C798B02CA
+
+q6/m5cQWmyel+SPbSfJcjN9tmEv9wASz4zF3aJ8nxVlNKWkeJK7AjsG9TgvMLS+j
+ZoeaQBKsTz2m1ieSfW4kyBLIc/moBFr1Et5iVwjX6Nz2kx+TPobRbzsKwj/bOorj
+QSZruWVnbSVO4FOpcl4IbiSfVHqI20zpCoLN8IIngZDUv0AmAK+KBgH8U5fDP7vQ
+oU3THgkh96ab7gt6LGvZ5HM/zZNCYgeEQsz84Ku+r/eWpWoTdqpKlZDIEcXHjO9M
+JyOMq/DylB120OVabGzKnau1S5p0EiuDlvBzWsr5ybpMJc8AbW+p7/Xu/9/dWNv5
+ZLGw7pS98h0b16MxVU/NpgF4BqRyPWo1p3o7jeApjqSBMJePzjrWseLLnZdQxVkA
+Y56NiEZjCFVVFHhmuLny2RDwFh/buFps68UahrlbBP/H0nDIQi9x6P5QYcrxP3Iz
+z6/MKNeX7IT6GiQIvhWd0LZkFG8qdtiH+S02e3+0XNCEKGprdph/dq9QU2l8dWfu
+Gf880UC03QzRVabHDe+AuTSqXRf0lOG8APGvqUqHwaaH53hcjnVD5Hb5soHmh7X6
+JAQ2u4a5IfP9EX90UJ7UJKTypIpVsK2G7HZDQap0vm0FmXQc7dMChb5qLaGpBILu
+8m6Hq0lU0fHSl3Mu/UHD+2RDvpo44B0q9tDorIKN7/FKbF9MwzkRjBLXPvg5HzAN
+A+G3K3ccnpOf5puT/wqPiDQt+oQelKZlNsENfB4lQB1Io5lE8imGSo6Keka0qxzK
+D4fLSVnKKSnpotpNV7A3QEzmB/f+glBFzvIUP7+l9dW01X/Oq9YXcOAGJpbTrJ+b
+OeBWmWeXgf1HyAAb6uHUFoaDCCQMHd3RXWqkfm3Taj0/SqC1Iz60FeVAtBITVjbj
+SzS9KGvOuZ+0PjIDQj3ufa7v1f2MjzNAml4JSihtqy2rlQo6pljD56+iXS3k9Yx/
+lC9VfHlAxOiSVGU6vKWZJMEtD/nWLOVGak+36SBcM0w5OUFfOV6dY2Z3YHwB4pBh
+HjN11pB9BjsP0vGKEkV2x7x9k685n1crRferq6BSjsbNQ46ZqPQNABAnPAYZ6eJ1
+Uo1LuyWU/tjtrdJMV9TudVHRgjljuxiADDPytPka8H3/oAG5IYPEHiaXmHnkM5ZR
+LJRPcvh93KAV/zfwcNX5V4pTYdDR5C6GnDQocsw7crawd/egicbJ7y48HjoKBwJe
+CeuTljhc4GTmuFFzN7Qpk/NryBuAcKBIxdKtkrPzq/bi+ekPGhn8AobLa025W5Me
+sJKSEgW5AGbYHTYOOEde0QhnuFK/nOTdL1LK+lhbxxFVXpdgjON36W0uMH50k0sj
+zHxTPYe3zbVmGDTKl70CabELn2X0bU1VGoO3J42b17GQMAEeeAwtBkdsnh+y8JLH
+bfbbAqq+K2Jq9h3PqSwFzBagcnS7fwyAvVu3qSwK4j6WRjwBUySpYHOxZOWdcJL9
+HQk/QAH+Dkt2Sia1A0nfX9Uu+JNE5m2wUCNEfg/Ikfr31AlyjCimwfIsMCTxXuqs
+9SVMX7yWaYZRJchF2mi0GXar6R85PYXmcMYSotQvCkkwzJDJkiV6RNvXC/yYbCwp
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsCriticalcAFalseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsCriticalcAFalseCACert.pem
new file mode 100644
index 0000000000..2964eb58f0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsCriticalcAFalseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 46 67 82 1C F9 18 B7 EE 5F 55 A4 59 54 20 0F EF 45 5B 86 F9
+ friendlyName: basicConstraints Critical cA False CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=basicConstraints Critical cA False CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIBFzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLjAsBgNVBAMT
+JWJhc2ljQ29uc3RyYWludHMgQ3JpdGljYWwgY0EgRmFsc2UgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDK0TuX7lUycbAgxfZnKcg+Rx2r61nSTPYw
+1lgfYLDJALaWLUioE7qIrkbpO713AYSExS2mbm+lahJiFznGgpZreL+cY6se844t
+2TG9ZU7Z/gap/UCKGu/Zllq30Mx5nuX2yQJbH9oLp8aaxIFJrE1l2bzw5oJNITf3
+h5D0ZE1s4j/cvDQ1AeIn56HSsU+FFJ+WZ9tlpOG5C8WbaRUJBDg68FEStgq63Dtd
+7zje4jykLw9FE6ecksEZ87TeoOVbxsM68jr03/wByZKDkiwM4LGgHHFyfQRgHWbd
+kMpTDhyrk0CNv7F3kQ2LOfbZP3Xt2KTXYoORYMC/kSf+rfKaAORnAgMBAAGjeTB3
+MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRw30Qv
+A5kcF3MY8jY8FDTQCdHy7TAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAEvnbglu
+cVBQ9vbuv8jUUzxvxBLqBbvwfsY6QmZGVgNKQOIkARLkguDt6PpVuB/w2uRFBRFv
+zcV1ooleAKis9t42aNamzgdDLxSQ060Z98yGeU33La7uqRX6PVzvYncwVKOPl1mu
+Hr9CEPc9EHYJF9mWYGGYXhNkrvlFpow1Jgg6zWtmWtoYfl27XoGBnuLGPqmd9Qn8
+aDWfNe4k8XgVwemq+n+r/tYGXW8P91DXk/YZCFS4x8hbx+0VvCcOXWZ2ApWGkX8j
+KHGzhl3jFqhQOSy66QljjW1qVxPjkL33l2TaGrOQXv/Ykf6r2K2bCxKGvahSAH1A
+tA53saU+pZ94JrU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 46 67 82 1C F9 18 B7 EE 5F 55 A4 59 54 20 0F EF 45 5B 86 F9
+ friendlyName: basicConstraints Critical cA False CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A907CD5776049645
+
+BlcYGd6sAmCbJz23X7IvcehLqjkzE4Z8eMNK6q0ll+nw4vD68iu7id8ErvfxwsF/
+daVJQkPCKQSQqJCq1Z98SqxxNPtxrWKhvnOd8wfHyvMX4d/8wZphEm72mZfyMylz
+uHkHMj7FpBWTgzR4S8bsEOP8asM/9gdWsAYoABXn5QnracH0aR3hbcNfyRFnFcpB
+MMpZdWL8Mk5KUVTiQWWb3ZefuZIsi2uWzJMNw77jqx+ri4MWMVCpY9GI0pFZgWRr
+Nkd3gyS/8QvKrcIszbNOliT8V8/1qbLhV9oeCdj34kuRub9JspCWhNcTe4ny9nxW
+0/0nHEzT2BAjnZbGAyzCTGkSZkJTAxpZi/mwWq+gaj4eD2aa+2UNtiazAltF7SVH
+LcZE8JjePDGMpob51RKqzxtntyP98BAgsnAS/Wsn+WRqnV2afAvFwY1bsP2tCNUB
+WP1FXwR9Ryzp8diG7VBET8kfi7npbXv9FICUYo+NMnXjApI+yXY7YXIQq6YawOhd
+tO/2bytPjHnvdnYZURPQ3dsINZWjrd5xXXI/boTXH76QUp8lgg1jx6nPBO1pjPZ8
+CELjvL3YDFLChS6DiOanOPPVTsKzDHrmlNwBkEQBG/tsCbRhQl0ZmLMd2EPdNbbQ
+EoWIqo7P4E3FlVzdwN42pug+nSD/GhPl5bzBH6F9MLMkqT3ff64RaonFu2Gi3TJv
+XMOY//4EDNrFLHnB//lALAQISmUFHgMbyU1uc48QtZ5rHPcHw9T+z71pP3I2Iy+V
+KrQwYq3BaknVpxL1YX2xUuojXSGot7vGFCbj6WS4ooeQjwDPyiFUJq6SrfFw4YmY
+HCS1pfhu5YMFtNxLmzMyn4h4CQweVkStrKtexTZHbmEKexhLZlD28YatZTZw5YdK
+qxoA+qNAx3mGISIlbl0Y1P7Vh43KkOaka36OCQFZd6tPsOK7/PCD0sk6IqScyYqz
+ZvmfDl4NrBnuYfPFtuZBdmN/fKvSlIOro30/mok8mWjhZbnsJKp6i+xqNdsSZKwX
+Q1gGXAtja33T6ZwLuZTcFkX5mb3XMfMEIiAm8xhMqYSgL+sJxDt8g/BHyryDScOm
+7Sgh62ZjlxXm6ge5YW1imS5Xroqp3pnZOQrmHZC7XJesXM1it/fSAkL3RLmShvUf
+u2jZC6ULAg6eo7PvONaidtSlHx/O8RiBMvJrOXFUcShn2CKsbc7M/u4tnRLZVVHZ
+pblGs0ID7wCUxCL3j4N3ipFaNvo3XMlfifQ8YBlInlEXp8YYlGjQX11rtC3Minf/
+vMU0qfR0ObvjgjhJ8E+jJ/kJhC1sTIVpPIdgIiVsLhoDyAauwxawz3ONlHrB491X
+5wH74clArihNz3Pj2pL6FvqRZzXtym5YbCHRcFtNs/K2HAGAyj26MiQRQ5+yPqhO
+olWZHohZTQhA7fKWh3AmhMdCiwaqmx7xRmRTwfICHKIUka6qu91Y3jQ+cMr4n7IZ
+8yrOCZjlkHww51I89agqBfCB+56v2lWwed6Sbs447Xtu4G3k7MR1PjCYt7FxccRK
+ajpKhQDxoMpig41GQ9dy6yuNTYmPCwlZSVrhpv92jMfbAE4sfh95wDGdgKu4061c
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalCACert.pem
new file mode 100644
index 0000000000..36d5718399
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 48 03 2A 70 2D 08 91 22 69 59 D8 1F DA F3 ED 06 D2 09 FF 7F
+ friendlyName: basicConstraints Not Critical CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=basicConstraints Not Critical CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIBGTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowWTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExKTAnBgNVBAMT
+IGJhc2ljQ29uc3RyYWludHMgTm90IENyaXRpY2FsIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEArsQn8oF6pcm/kFywrnN3jMacD0/pU5QPugEQTz1z
+SH4R8VN/SBlsC4kBk2ue+IDyhJDXUhhq4d3Rs4hUNVv70U9GbwUw92OEie1/JFyt
+h3E6W2AJd+akHJ269MIFZ00e7MTXdRdtX1QpESnqpBL7YuvTkZhXYLRnvgy+gZtm
+lelEmXgMT2Ww8leKWmGJr0VkhYH+sGZLZKgxmFX4FeMXVcWA0k3uHIXeQT0h8gJU
+VsrdzBC1A8pvbThtIj2ZfQ4CClmDZZW4vplTC9oJJldenl5jI1s2DYzcXrn2eIH7
+edFuiwGqeUpWv/KONSHVvzHytw/CjS+3L9Wn302y/IijGwIDAQABo3kwdzAfBgNV
+HSMEGDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUCqS5MEOsQ8g0
+AhPP71Xov3CfRq8wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
+AgEwATAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBSpmk+5lnnJCmJ
+CQ074FYF+IHNPqc/ZztWuOGGsY0O4ST3vIHfbpJwjCvvY7QC0glG3klEDvhOVRVB
+MYzkTscePuEI9xUSht4MoEsN9AIL0ONZ5Hi4OfKwdjm6AatSmvTyj9EWpmUzmxqP
+Uo5GkfcIty+84ExeTE1azxTi/XbJ5vzpvnhTQQCp2yp9T/+BSCovr73OlmahQWur
+tS332QG5XAPYV54uJpYPYxSfoouf2YoVfw8HJRA3qfQYoomKWQSfNVQtk2pklxIe
+zNVFpjHbIef/AZOGRYVAePoQAx3SqtA5faHlYHcy8fCr0uklwvQkitS4a8ghc6Xq
+o4g/ilaN
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 48 03 2A 70 2D 08 91 22 69 59 D8 1F DA F3 ED 06 D2 09 FF 7F
+ friendlyName: basicConstraints Not Critical CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2B8F6C672C9D1209
+
+UciDWxzXIHzVsJcr9SCpIsfAYutmhoJaU6oykTzH+9YgNLuvkMo3xzvFTbD/0lG7
+rRsIV9BZchKs9PjkD5AkXaR/8BfW6rNQR166Nvyhd2Yn88xy4ng/b3vWmwmIp580
+VNKfg4uwepjQaot97RYkS7dgGp/6HAoy/LvLPz8+Vv2NZr0Ocj+2kUt6KT5LlSEC
+8HZs6SR/O4lnJfAZf9B5FwFOrDqx31wUtKADMmtn9AeJwM0LpLRhyDOkUzmBP08L
+kJAiKJ0qfKvf/eJFvJKbyeckqGhmqqGSFvHO1xHHw7xUDvTB0lskAdy+MVZd8XA+
+QA3duCYZaTcpRDqm+fcNqGZB604zlbKxscY7MvZ5RVsA7Vw5ATHhLmvOMS4H4wDt
+hq3s9hBQIAM9VOeuoGIk+BP+pKss6X57R/5XvnIaVTLsSbn6VpxbJ6migsOAq9fa
+cSqT/13w6Nlf9rzo6AfskOfBzmSgxOHCrwEkR67xuSWsVepRSCu43Ctm41UsWWLZ
+peY8WGMZdsqv88cnwgGQObPfAjKW94aaVfizhoj78gppfghvC95nw8IaViDAWTE6
+QGptRf0M2zsGtKp536IRT9tUCaGIbewc1diNovY+tNB0YINGeiQcu7Lgyu5MbzHm
+evglA4U9hmHnMyt7fWaxyauw0HHz830Bhh5qocj5CsrRMNPSXma9+g2wxV9Sjz29
+P2y0Msk+ppYkNEzVeNHfz6oXW45KXXGT6IOcgpwMKNncKaMW6ZtECE84AYeFzNcP
+YYhFylF5z1qBhYXHPJcmwjIsf4GSVzU8YuM8hlrKix1YEBqqtTDYifRIM74lmdaD
+7IyJZ/wK8yqYsze8hHt0E0poCJ9WC2vkkZvmu4zZHr80L0ARpqQ8b2UX4UIMwar0
+L/q3625fUXi+OijtpGqjM+iAAZgsg0Dv5744lZwAdn1fdMUsDnkPPtyOaP8C4id+
+JUozCXlQ5QWWAVGpwltyTUI2cSw1z3GBL/ofQVbqXznsTIie3xBAiHZKBB/QpgP2
+PNLuYhV93JVYxBUO3BgZXlwy8jbgGk5NU+EZ6yTWPF+q0o7hF7wQAIb1yfz/zGQl
+6sohXVRhZAJWzbnDQIWfZMVXsPpHDXoIXMdeufmKy6MGAbO634upVxZfpbErUg3R
+zw7kzSQ0nLkW7viUYpCPz6waXtxCMP3DZynlXmVbYrr+be53PFpg9PhgCI88VQ+g
+At9CHTMdocCZELJkEem4/VV0bjYCYv22DeALTSM6SlrSmOFWU5QLXV7Z8zs6nOwd
+f5W0kom93FolMmz6iFn09FEiRnGWGVE3n4m/9IQz2jTbHgAFsust3uKuWMeTmzy8
+iAYVv02CRt8odMFCBi/ld6vzD3mxiLucxC7RfYr+b5fhkYxqJkPW6WnfHtwlUV2w
+SSEfJlhThZG7t/ZSbMNPo/kemV8Y9jByZvbl57kpSji7ft5BbJ5J0jFblnX6aJcd
+UoXJm6t1BitRzhS/bYT0gBWp7V1UISlwflZKwZwF/P0LYAdOdJM5IgYyLFl2G/Nw
+E8ElkZwApmHGyYpDCABQsudLK9hEuItlEqNKdfsE1TB+rgCZF6xoy8ci2GR5+BNm
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalcAFalseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalcAFalseCACert.pem
new file mode 100644
index 0000000000..668159e530
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/basicConstraintsNotCriticalcAFalseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 67 88 25 B9 3A 83 74 48 FC C0 EA AF 2C 59 06 A2 D8 7C B5 4D
+ friendlyName: basicConstraints Not Critical cA False CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=basicConstraints Not Critical cA False CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBGDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMjAwBgNVBAMT
+KWJhc2ljQ29uc3RyYWludHMgTm90IENyaXRpY2FsIGNBIEZhbHNlIENBMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn0EwqHs6AKdSF6fQyFQ9KzZMLoAg
+o3Vjz4MudMtI8xe5SGdgQiGK1w7acKOWzVg/xRG+7Lv8osjGB9+m6MsYgXACOVt+
+2VSmsuHQ5F9UZIoaXfsCFV8J4KJYuqWYJt84PIzUoIEKHHloghRQvI4qv8SPJUSI
+LbaeRckJAzsLhRVOTGIOCPTtj/rosKpdBdHofuzdtVkSJvMu3NcN1oL6haAaDtS+
+MYAizyLnTbNYBS/NW+6hImyNLYvmXYCh4rVq0PTTEJvm9b7SQHyHyFroN3a9vxof
+2+bQq6Lpim0QBKi4rBRDeJn+zc5EZnBkEDtZXEQ808JddIboTOi4JDkKbwIDAQAB
+o3YwdDAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQU
+OdCbt08pN77TsIp26mqeze9GvlgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQB1uT+Y
+KoMDcmuoxjk4KoBNTWPmR8eXegKa3WfyOJxYRTqlDhmDd/N+3Ifk/QzDqXitKUEI
+BWL13NTh6ngG9AIBrRGpk5XmixKTxCP5FxGjsd5dM/So079U0+K9s90xzwOwolJi
+4Fkih0eeRu2ntqwCvLsIEOSJMH7uSOISuRjYqMAnzlP4FFXYeLOGQLtUFln/lseC
+KfD0roxZZ7W8KVWLICwGAFrw5rBnZuyoNIcCJUtH9uJ4ugid0BmYrICWLFwEU3af
+W7GJZmRfegol/5TJy14XSb6vxyp2kAPmgdDZTmLiB36xaixjsS/7AIhejzDJ3gHU
+SIxm4tAlyWAjCBXh
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 67 88 25 B9 3A 83 74 48 FC C0 EA AF 2C 59 06 A2 D8 7C B5 4D
+ friendlyName: basicConstraints Not Critical cA False CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1E7A841BD9890B31
+
+7pXy++DsDBBVp7eFGwKvmWMCzl73VTqnwp2Zt+OlEshNqcbjC/t8TCWS4+zbot8J
+q4bVOdu7VieNl+MWdDK08PbZPi1rNeOY4hB0R7JftfRc7iNZJa/DPGjReFloTsxx
+Dkhdo4VBEpqQdQRq+BkCIe4IXc449f95jBIFp7blvTYixjqpUcuTDCkq90JQl/a1
+SvG73oZVLjkneF3e2km0nCQiLIrvEEwCva804ZvohyyN64C3WwRd6CXtFqKed4MO
+ju1TExPVg3sCnEF48rhHPQbqac6kSmWq100XrDyzJpvXc0idh8uq16N9zB8ESCtu
+H933fK9695cJL436LpaXBN1grXuZNL0if5wXqfUEXcTfQmrAkuD8O3abtyCxyc92
++6k3kMkzY/W5BvE4hWCboBYc5VkKd+FwxTD6hdGZ5iTN7kol1obzccxFRRRkL5tV
+0gDdWjAz84vbQYbJNrePXPSnN/xLKD+vnOl5HA1Eu11Z75XfiouiW2J4WK12HZUG
+UYI1jPKibCcoXaYZZPBI8pVyfwc2T+/CRGxp9v8gqYInh5TTbur4QB9wnhCFrNZp
+lSkUOW6I40UC/20MpNqIIipw7Jf6nKMWvN7zFojVz31bni0OySZ7np2deZfStAuM
+xXfC1plLgEXyquhXfCcnV4Od/xCbLb7e/l0NqWGGWGu3EKZnfBDrBoPmwxJ4toOB
+3ExqVP1M/gxY4TMc+YVIICYdWIhntF+hiGkmAsdGXslfLQuxXxq0E2j6xQCFfBdY
+iMehq9IyO8debl523hcP/3nAx1PMrdMXk+tRAhpbtPJmaN75YyEQlSHAJEZDA8YK
+id5jAx7pmneAzRPs2mU7XSSTysyjx5hV0g/AXIGlIHrZcjpwsvuFlwJJQZ+GEUxG
+OTLZEqFOIA+tg63Jze0rxOnegT7AZx1Nzz8YX7/WrDiGuYdM/sfHbyz8AF0cAsI6
+Uuqzydz4W2U4shwwop5/Rwh01PSiEWI6x0K9L7htFKerVvEoLzUjFldmAqmqlGIH
+GBUl2WYDLxkhMRdT7/9YZu82X1TcFoU6LsP0Iup1tRrUv6vbeqtaZDGoZ5ebHZZ7
+vSDSMInRSzbdv6nd6Yoilkd57pbEVbtqblAY2tBQ/R0Kc/FMddm6gheEh9Sd7qqv
+fbWgp0Z8gRE1R3sD8cl79DIcUBxI2XiHGideO1flAAlPogv9IGeqqH4e1DsjPewj
+s/4/9ofVx//4/TjQP/aWzFTemGzlozPWM28FfrGBtReNUQ7zUSJKzzJJ0HC0GQLN
+zhXJOklxg/wyhmD15H1xy0bqxXM38/LR7PfaJCvlIlJ5lbUaCDJqxa3LM2+2qhOm
+JKq5Bmdk8zlbQi314JuBfOy0PEyLHxpZrEn3orYqtK2MjgoOwE4IDfCWkLL2bF2+
+sYfCFZ+ApD0Ki3uL/9AhTzsPkYLAp+vH9+3FQ9NOe/hCwF99Ak4+Qo2sShSwGJQl
+IdEiKtVmN+3q+gZweTyHQeoWgSVcJY2A8BquR+Q39yYbhilgQxRt/Ivws9oeSUx8
+ga72sXk08SEIdmlkpwpvev+FIixCbk3EdmUSVOQtX3AiK06TNUTYlg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/certs.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/certs.pem
deleted file mode 100644
index de409f5895..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/certs.pem
+++ /dev/null
@@ -1,118 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=Valid EE Certificate Test1
-issuer=/C=US/O=Test Certificates/CN=Good CA
------BEGIN CERTIFICATE-----
-MIICajCCAdOgAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EwHhcN
-MDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjBOMQswCQYDVQQGEwJVUzEaMBgG
-A1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxIzAhBgNVBAMTGlZhbGlkIEVFIENlcnRp
-ZmljYXRlIFRlc3QxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtpKu/a6Co
-7KcKOymboEA+MmgoryXHT1dxExmQ1lO7yah2L8j8RG6ox5Tr37TV8Y21ti3MopcF
-H+iXDSX31fixsYCZkcpjMI4kbjXmjGOeFKu1vnbBmcb5JBISiUeg22tIRFoJ4zTh
-i3GLVecGijyOVReA5LiPymEKG7fAB3241wIDAQABo2swaTAfBgNVHSMEGDAWgBS3
-LqaCy8LIvKh7J0TXNTPfmhWUxzAdBgNVHQ4EFgQUOsyUZQyFqTzB4K9RMyoUSI+e
-kVswDgYDVR0PAQH/BAQDAgTwMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATANBgkq
-hkiG9w0BAQUFAAOBgQCkaGfCqYi0681n9Dit36lg3U/9gTZoNqPMaAaLUQV3Crzx
-x2MGInhTyKchYydbV8HD89N2jzzYq7J2KM/ZEAfjskCdsj1SiMNkbYZe3rZZOldr
-PCGFgzUGTNakQxkpxU5j7plivQic/OZ7+mMTi0fnjGRi9M+aa744VmH6FgCt1w==
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=Good CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICbTCCAdagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMDsxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEQMA4GA1UEAxMHR29vZCBDQTCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsI1lQuXKwOxSkOVRaPwlhMQtgp0
-p7HT4rKLGqojfY0twvMDc4rC9uj97wlh98kkraMx3r0wlllYSQ+Cp9mCCNu/C/Y2
-IbZCyG+io4A3Um3q/QGvbHlclmrJb0j0MQi3o88GhE8Q6Vy6SGwFXGpKDJMpLSFp
-Pxz8lh7M6J56Ex8CAwEAAaN8MHowHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqa
-vIf/SeowHQYDVR0OBBYEFLcupoLLwsi8qHsnRNc1M9+aFZTHMA4GA1UdDwEB/wQE
-AwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQUFAAOBgQCOls9+0kEUS71w+KoQhfkVLdAKANXUmGCVZHL1zsya
-cPP/Q8IsCNvwjefZpgc0cuhtnHt2uDd0/zYLRmgcvJwfx5vwOfmDN13mMB8Za+cg
-3sZ/NI8MqQseKvS3fWqXaK6FJoKLzxId0iUGntbF4c5+rPFArzqM6IE7f9cMD5Fq
-rA==
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Good CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:B7:2E:A6:82:CB:C2:C8:BC:A8:7B:27:44:D7:35:33:DF:9A:15:94:C7
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 0E
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Serial Number: 0F
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 93:c2:ec:0b:71:07:2d:9d:d7:a2:b3:f0:ed:08:4d:6e:06:90:
- 66:72:06:a9:c2:30:73:f1:18:72:bf:a7:51:13:95:c4:31:3f:
- 1d:79:41:ed:ed:ab:d0:96:11:1e:32:47:4c:c4:f7:e2:08:65:
- 6f:73:55:c1:59:09:56:f2:60:79:27:18:2e:94:40:dd:7e:b1:
- 92:bf:b8:57:e5:4c:c5:38:97:75:2a:a1:17:a2:25:0d:ec:0e:
- b7:95:40:8d:2c:df:b9:fa:10:ff:be:9e:4a:f2:37:4f:25:cb:
- 1b:c8:6d:ef:e4:09:b9:03:36:1b:c1:d9:f9:4f:00:5e:80:85:
- 92:cd
------BEGIN X509 CRL-----
-MIIBejCB5AIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxEDAOBgNVBAMTB0dvb2QgQ0EXDTAxMDQxOTE0
-NTcyMFoXDTExMDQxOTE0NTcyMFowRDAgAgEOFw0wMTA0MTkxNDU3MjBaMAwwCgYD
-VR0VBAMKAQEwIAIBDxcNMDEwNDE5MTQ1NzIwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
-BgNVHSMEGDAWgBS3LqaCy8LIvKh7J0TXNTPfmhWUxzAKBgNVHRQEAwIBATANBgkq
-hkiG9w0BAQUFAAOBgQCTwuwLcQctndeis/DtCE1uBpBmcgapwjBz8Rhyv6dRE5XE
-MT8deUHt7avQlhEeMkdMxPfiCGVvc1XBWQlW8mB5JxgulEDdfrGSv7hX5UzFOJd1
-KqEXoiUN7A63lUCNLN+5+hD/vp5K8jdPJcsbyG3v5Am5AzYbwdn5TwBegIWSzQ==
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA1Cert.pem
new file mode 100644
index 0000000000..7afdeee299
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA1Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: F0 C9 87 CA 32 71 3A 6C 01 BB 33 39 C8 4F 65 31 40 08 8E D9
+ friendlyName: deltaCRL CA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=deltaCRL CA1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBWzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMT
+DGRlbHRhQ1JMIENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM1D
+K0cQkUNtDBARI1ttcSMWbaqm4Rx+gncCY62Ilp1eHN9tBFyJXN/kxEe8mxh/nl2j
+WEundquIwtjnMKXV4hU7ynC+Vg7taRu6Mu558dvGbBzkJ9LYCEFs3DgOphyY38zh
+PYa/0o7DoRoIAYopaEmCpa/fyqfUDGWps4S6FATb8rlEAK6zQHO2zirGsp5gq9F8
+mJon67WM0iJpIPSuCIkbaTRfY4glRFyokHWXQwXV63XkgNUAxQjLGwAqH1iZIOBy
+fl3t716yIcCnnimcaVrJu69GBxYrkeYTGD8w74rzGKJIHSCEZy7hOtS10G+N1zx+
+RqCKnCh3OHyc5qTyhYkCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+
+dbZlp9ldqGYwHQYDVR0OBBYEFHcYI+V2hMgUlD+C0IHqdLHgpC8zMA4GA1UdDwEB
+/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAjgJJapgvD6p5DPB8zpQ/ol3xmi4YS0g2ephG
+7IX/vh0H1AF7wYJz7zeYBbRUVeObLVzUgBq1iN4Gk+UxTFDFZxzIg6kfPyP+MBDB
+VIcSfQoWWWl7bKEm7R/eIlxRm1ZyvnCDc+7QYMwdH50m8KNSF9UOuJOQHGIgqJpA
+gRm1t7INMr4OP0hxeVkzw77P4hShwi9Wj3O4eDD+0xVPvxweDQdoo4oo3rx1ubWB
+CvJAFv/Iz0qZaV+2RJNFD5Seg/z/G9wtBPXaOsbaushHEejw9rsQCvj7GMuzzKVH
+qWhXC94zdUfGOz7+euMLgnJUmfEYyvQY9NgZ57+7SmTit98wEg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F0 C9 87 CA 32 71 3A 6C 01 BB 33 39 C8 4F 65 31 40 08 8E D9
+ friendlyName: deltaCRL CA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,722A4E713C2A9002
+
+BguAZJfr1dO6b5dtwQQG7QdiD2cK+57DcU8qycGo/4y0ZB3iy97keTWLx9O92LhM
+lzUeL5AM34sT+m1w2ciaKdR1GiKXA2OTC3M/3kOm75eirSAMEkUptbwuPW/0iJZA
+Oc+EsaKC4FipWi0EB1aTaeTwApM7X8WNgywUYSCMz1kL+QCRedgjSTyqRcf1xUs5
+zvKcaC5q4ofVNDppkLZMAnufFWep41hQ4pHobkh6zbcVXeF8ozy3iGcyJWVgbYOv
+f2LumH8uoPoBwk2Pi8z3PKHGx0ZwKV6+huHCMATuLLlSO2N7CwCatz7c2DUPbU+e
+26IOpykXmqxvBzyo9vlrr2yvuP4zmNod1D+JnRVtHpfBdju+0K3qHZ0ihbnHnS8D
+zdOkO6TjLVHw9OvNbZEx3oTabOiHYFIFMKyAhjUIDQHEVVZ12fhdnBNvKduCnSJz
+7ckwYBPerFkfXjYKMaXKEGPfeuI85yT60FT7LInPqcjWC+LqkfTpyrgh+qciV7X1
+IfumvbfIFAUTlHPxUu7evdGVqbl1nhXCpKA8DTyjA1QO8nl4zkaRKtoijLANXZ1I
+SXj+UL4EwTmT7nzTm5/XmcioZlJpVPC4uz6ZUaACuNXHi6172FdS3WLmlp9ZtaBs
+eYjHqzQHfFWo4l1CF6JI/Z54nr8BsUZ1m9gb7PYRiM8ylrEQiJTGLf4a0ypUyG4R
+SoC72kAzihd6iEuJRKWTymHnz5IBK8PrgnkAk7TLWoKNb/PS5ifs2wtUGvBXa0os
+FzrahyPCGF5afZ0pGhw+01aJeHHaEhfVHI9ix33OUz5vy4oM5xYNDKCLtDXzhZ6Z
+Dc7c/9GiHUgW1u7eQbV5i6igRvEqwItitPah/zbfrsNwd34swv8YyyPovihYY3GL
+w6tk+8CYb4qRkyhXRg37vBUUuPa7GjElwE5cZsqUaVpB47wSjIZVFOC9g+/C4/Ps
+SI6y+A6QatTqgZ4OmQ7JKUtYHFkESnKPl7IzRFrw054oUWVQKvdvQgY8R0yhd/2E
+qbLSyk2Db0wLmcPt59NV8nyHa7twNPMVApQigXAszEhbSxJWGIFjSN1X41654WG4
+/2FO8TYl5+mn32BdbCgYGn3kFyAeCd+aHNfa1uM93coSoupCVRA/ROTxAx8gohzO
+TM3GctWfQh3uxOakDqv8I8GG5BMvJZmAoNTrMr+kUNt3hrCr9YRKGRD922J91vL3
+yBWrgkudn09y27zjxXZBmYDF0rtXmmtJqw2GebKFdw55OLj5cETy3X5HjarVrVmG
+SBF0toq03Mpc5i8AlduIaQp8ZLFmHLpHfX2mgbuyb3EMDC2RgdfzhxdKUzirVFqc
+DaVfZ+KNVQu8gyMdvljeRJN5vnf8jUEPzNZhyJtBV/CqzJxtUa+Cl3t6JRlWToOB
+U5oNF3d0BfWAlJCWzsjqcRk2C8zP9ZXBii+AErDkUtq/ifPpea7PYUKGqszLXtE3
+vEi6QoArjHCaDwpVdXi8IHpJUl363LTqOrfg7u4BrXMi+haoQPEyK5UPqilECzwC
+lShfMH9t9sHbqIN9CW/7RfO4+frEbHEYc6fm293IClTfSE9zS638Jg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA2Cert.pem
new file mode 100644
index 0000000000..8099fd391d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA2Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 76 86 80 FC 15 9B A5 CC CD 2F A4 CB 1A FD 4D C4 3D 88 A4 6F
+ friendlyName: deltaCRL CA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=deltaCRL CA2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBXDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMT
+DGRlbHRhQ1JMIENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPmG
+eyqKnZwJFXM5DgR2BT3pqqs+DhJwQrNm13bDDmo5YRZtwkP04BF+AovdaABYrzG8
+SPiAnj7XrldFqIt/UJh8j87qqMvLcUU3bHIfB08mVHs+IRA1tXR6hle1gKNTvr6s
+tBeVyre3yGYJzu95wM0dENMlUfol/gB0hswUrbzfCWL4bLf86I/k6dhHcRpAanLf
+Ns/zOgR4ZjlgWfV6LV0VEYCNzPQ3d1jzgAUtHNtME6KoHeP0cn4EooDlFpwwjRCJ
+ijNmnZfyML2BZXmjKeye+vNXZ2kSRGaAOZPG1tDmdjVy6OwcxsCkv2oOXwZ7WwRA
+HOiLygA4cXym8HDOgL8CAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+
+dbZlp9ldqGYwHQYDVR0OBBYEFHzY9r4DTM7Ptz+hGbszq7XXjfvEMA4GA1UdDwEB
+/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAnot97/Kk3staK5cRrXT3IdCNVOvFTJgMt9oM
+Ngm/cId+NkEFpjPzpJU5H0RXabe5mqpM25W4ybfTTWgYqWvuCxTzwjhDmtDfhUwg
++U7prkEz9LgaJBa2ZZioNsrBEjSj+f/mO1e4ByruCBsY+uEpwU5eGKzySoaXX2wP
+7fWC81H6fX4/QNRnOsajadNSLbyVjOmiwz/c8rSt0ocaNTxkpe3xBh9MLSQbqJEi
+gQTB08URkciHRGBsrBk6HolAjMcghra2Z/Knry1wCcEzQkknOxzgS+IME7ehF9gP
+XmkFC8jp05ZGOfZeyKInxsivefg9QvdGOAu5IXHZvCUrFV//Sw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 76 86 80 FC 15 9B A5 CC CD 2F A4 CB 1A FD 4D C4 3D 88 A4 6F
+ friendlyName: deltaCRL CA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DD8F6C30E6C01617
+
+7F8RxBk5h9wR1Ib1nxlGHOH6jj5UnG02dtUGJimXtFvAzNz+E5+LbHsol7G4hRXS
+xEa/p3LbqApBKKwskJNwh8vPD/ue7hbo6Hr57jMIE+9LQRanZwg6CMIcaw4eRD8Z
+/nKpIWZgLS5ohLAlLp868ZiSohFgLGPOvgW5IvuoS4LlDyVIn30wViwJZZDxibht
+VWmxQP5BQUaUBSDsZFjwgMJC5Nl+nNBhGcrIlerkaAPXihf1MJ5bMwudjsJfzFsa
+qQILIBy0iQzlwifR/gc5TmePwEOa36GSiLdCaQAihjbhTH2Mht0EEApEYWrr1C99
+fGzIyAcLUBKOQ9Moi2pC0VlGMcB7pT1EhQAcgYfinxBbQlZcieVB8u1dVfbRdeAQ
+ipIZvD2i8fOjDSXp117eoBjH3oiOWzTXCuy5iEyE+IDBxr+FPNCJgc48CX+MfbAM
+sgxsSfVAcClo167mYYbA8O6ORr9QvZ72KWvPJZEO/pDfVTMyZZJPhNyuJR3KxYYl
+iShZfWo/rUow4I4UCRPoobBqEitIPAL/+Uwsd/AEihN76dMXjY87zqm8rRdRsrHH
+YL3Q7g0Owrs2idJahta+2sjsgx4y+4DKX6U5ttDsnOSO/pXJhKCUzFufARoMO/Xj
+mZ7SoEPP+NxGmyHPSb0OK087TyJf/E1JZOUG2GOVXj6QN4yIn951WIfYRyntj33Q
+KUR1rVljlATKkVqwWETnsTGaoSZPmZ1c0VIwA1z/MrXEYtl7Q/cTlUrr7TxCpmw7
+7Dwes0uiiLbYfWXyJ+coGq9V0r5lkkWky9SOE5c4KL185G4DYKvjldPmmDy71hPy
+Tsdj3u7XIOLb/hbrRLFV/6ufs+bY+D6hkZWz1HI5ukuwxSTTjHSkEFGNVEUFtHLO
+E0M60YjRXR7VTE0z5hzNS0Q/9bcIH7jn1z8PRmwBAR7VcgC9oq7PFc+eTWkns6FV
+48m9a3BkAimJ2rsdaBYBXn6+qizeoDeTKhSs1sN1Z02Xu6jPcYX5aTrIsLESF2ya
+SpAVaE4QZpAP+k2jl98N3oZQIZd8L/tOEPRfxuzuVNpxfu/U05W6zQnHHE7Whce4
+miTwc1VvDCwKVlnzGyYm0x/so0Nvzl3FvKVRnDm6NueOS3+BVwnZGB5gGOKMpXt9
+2Rgr/mg77Df0SltFHJf32v0iLH91ozk85pyGIgI+LHqIcYXM6IdCRqqpRHJ7cMIc
+OoAff5sxzolmfrVt/14ba4wtLiiyKAcnS8k1YvjA06tp1201Y1hv0B8v+rSsnzBn
+LsTYErElmwCSu8H7dVLiXvskOXJrlC0mMKKaT9/F0Hw6O8aQwGer8IVGnb2jB52v
+czZoYoWjze3JGEGheKOLh70dMPM8geEDeFIBtR/Z+BFsKPxOwR7O9el7GLwp5wxg
+YpBNumQoGDEGc3v3MjJ6NuDrIDJd9E0pSMfF5wAK135tDEw/briw9qa1eR6opnqX
+8PD+8Dwa0vNfbiEHu9NZWASVBHo0XkZRkQuk9h63odb2Ce8jMvdSb04Sj5hqdxtU
+vwai+mWjeOZeNlMBRsi7QIR3/EcXZqIWr2mnx+sp6+AUeSxbZqqC7g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA3Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA3Cert.pem
new file mode 100644
index 0000000000..2b5a8de8f5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLCA3Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: D8 F3 A4 B6 51 CC 05 39 FC 58 CE 6B 1B BF 4F 01 A8 DF F9 7A
+ friendlyName: deltaCRL CA3 Cert
+subject=/C=US/O=Test Certificates 2011/CN=deltaCRL CA3
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBXTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowRTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMT
+DGRlbHRhQ1JMIENBMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANWk
+V4v0ntSi9RGfISHPgdqTaJJOhlOC/mr9w4/zI03WxMARD6dFCOiJDP+D1O43FEnG
+UoeoxVIwnTYlN1rvJEyjXXZCdrLJQGqV4FVNQ/EpllubGkfc2mvemabpkmYIEW6L
+FlF20TrhiHowPffKj+7y/aXAMMiEfX+kplSkI8nN2wDGfOmZzhHptIKClExnDdJ3
+09sYRAqU8sdK17gthqOUa7Q6YIcTKJD5KP4nN1HHfhZT0Yl5tXnoppjPDMtVun90
+pF7wst8Nr7nO7tiDenpKvlYRNdP57Sg7SKzFhJt5wDEzZVLEh0BQ7iqw/IJRDTXH
+tmz8QVU2hBF/6vQGu7UCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+
+dbZlp9ldqGYwHQYDVR0OBBYEFO9j06hOsfnfYeINwwWjmBjSk5nnMA4GA1UdDwEB
+/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAZ3Ll6ZNSuII0b61IuWxMGImVPqF9M5u7q1W7
+dZqmMMzQCull5LmgeprRJA3jSvCBC3/kmdHsA+KNh5qtln7pOkdewhvz2kyDq/GH
+8boxSNEIi7yqPGVIRLHyp6jDrwkMrbhZOnwr06K/NwUuPMTsN7eITW/wVZSm8yUH
+TR0pDDTwCjrzYiszzbGNsJ/qTtmtroYJ2LJliKXYOhN2dP+47I0AKx5clhhofDz1
+vve9wuHgkZ17fvl1r19VXVw5r2XPSL7qNQxHECGzHNXKzJnSAaYN44py9VQ0JLgA
+gxZJZBZfmW1XzWMfusb8BxGbfy6WFx+698V9G/yas36Uv9bAJQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D8 F3 A4 B6 51 CC 05 39 FC 58 CE 6B 1B BF 4F 01 A8 DF F9 7A
+ friendlyName: deltaCRL CA3 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6732CAD4054FA1E3
+
+/iiFt7tBHNGhLMtdgr1HYBP5tXrMDI4RoC++7n3PYuKnHf5+qomyoAZwZXWashAr
+AzeB7iXoMIrMLfjKK7Ka4+syXElaZTg4gcy8A4EZjzdw9uZY/8/5fxsP6CwhVRPk
+hAAK3RWdeqnjHpDpsPNQqUxRevHHwtLLPTEOnlSjn+mmLqPW230/q0MCWpGoSk3U
+6V2EX9AY2DR1pARVCUE20F99PQs6WBov71vnLRbjg/NxtN02jw3cvRHog/lX4gJ6
+LtVU8i13I201TCJftrlz8srHOW30UGdJSI+ngcK720wzqhhsB64dtKMaYn32GQGL
+EcG4esC8J1yZ3JAp4Mw5QCgcQzLrPcLQ1S5Nn5zAhyT5KRxVqbVHQW1Mq3GZJEcW
+aISGgZYIcP3g2o4Pj+hPgLCYsrzaTur9uUCgilCHWpGD03PJ/GAqh157CxKNH7aJ
+PkjbnTwXiFm9D1tBcsL1ebkXwvto0tONG58+VII7mT+8TISIw4AyAEZkdk2MBTes
+rYinh6hiyRX39Y1sqjW+j6j/oiZdSEnT903bZ3O3WjH7ocVkUKc9wXCCt8M3j+b+
+rVSEsa0KRTc5h6sosQSx11iiH6DfzhAoHG1DqPxhlwX4HkQzYWolW9NMF1wSO/b6
+3MOTBmbkdXFDLXMcJkikUvSf4DMxAV2WUEINbPq0opKjJtoHiwWiiCBrS+luSbk8
+0iwGkynIq9+d5Ntvqo2XrQbRgrXgE/RX7q3rIloNwHWhQu/F/SoFy8VTd5u4NMes
+hRoVfW8vhDMm7K/BUy8lunNHnBUaan1XOaUZmTFD8IWWR239evo7Arolhq9nbfXi
+PZO4xIRNMJXDyEntnw3eyVZvAm5OiIqzc/wU2aoM907Kes+6N6+XSqRhdCPSAgC3
+GnL43NQIu6Drl0tHFFEv3igQF7QtzVqkemzPCufFqreuYUoLh4pitHpNHTgBY5QJ
+/pnEzzna4hVFKGFqAGw+XINqOaFgnEMQ2KD34LHXUVNJ8cy8srWUYnrl91mZm12m
+9e29Q8qucA9+edRgdBcmkA4iiNamrykzPYi8qG3/SED9GyBKBgBVWcuzEyFcYeCm
+1zCqmj64l1asn4/mxV/f8jL1Jlr8Lfbzaz+rr2ECxK82WnEgrGP3HvmoMHf2GmPv
+k+6zRYbMBqaO6EF2swDqlSVkjAykezpQ8Jiela04K85m5gP7Y8rq1ps1fU6o7bJP
+rDhjI4uUnuC084mufCLxjxyR8gcyWkloc0wcD5yQK07QFg+Lao7SqLgOwFoOTNU4
+uKbH1yj4IO+2OiBiOW1rUN05ydQ7htdmVDras3NWUQsKFZRielWxKEZ8TCKgl+Vk
+t7uybtKrShyCqLNGxniDkhQHqwD4qgJ9bPxjK+I1TdLqZggR27fPx7lGSNFNPXzQ
+lAWS4rO35hldQ3Z3ieRBwvUfGHdvZKOqgft63BslryH+ugSgpU8Be8YVK3P5QH1J
+T1uv43qkwOY+dmFi+/Sn1FXcuhUgcA6XlQLbIPIgWqiSaTH20rnYA5D71oiw1CFR
+Uq7Ls+Kgw72matjq6VTgz05KlJR3uWl+n62sogheiBfB/nSUU/LKUB7oj3qgaeBI
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLIndicatorNoBaseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLIndicatorNoBaseCACert.pem
new file mode 100644
index 0000000000..2913748c22
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/deltaCRLIndicatorNoBaseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E1 81 B3 0B 3C 20 FC 64 51 F0 57 E7 B4 DE 8B 34 2D 4C 78 9F
+ friendlyName: deltaCRLIndicator No Base CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=deltaCRLIndicator No Base CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIBWjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJTAjBgNVBAMT
+HGRlbHRhQ1JMSW5kaWNhdG9yIE5vIEJhc2UgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDD2MDEBGlnaP19Dx4CgvQTIRIJi6rw8OvaAZgntS/WWFZt
+0BYKwbZnyXxJCbGO0HBbul9rFVv2dFZdRWMHd17HEIyv+Xma7/0w7L1CemeJQQ2j
+mpTjEkHef/G+p+Y1iBEn2vomiQV3WtyRoe1FVuOI0TNyg2JFR7SJoZU4P138Devf
+UW8po0fBAl7M/4gjXz61Q72QsM4V8vgeanQMvFaB0Qu43RYADtLMBTLuxkH0jA2m
+xodtfbpQzEnslEbkemYMw3fmuKkhbLPfqV22XaoRAohF4I5lKKpLj6alWTJjeTSb
+KvuQi3whU3rZYru06g8xCot4hK6daBJ4ibOPFZYFAgMBAAGjfDB6MB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBT0OHYlq6TjHMDIdYyN
+E2tjI7aKgTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACnnfaS3g5fltnq9
+bGIa6RsE9OlAFAXNxPVEdvXV4Tyj77hKexYBMwpf0NZ/pAHfsOtNJwU/5HY+vR7E
+VxPnIQsHnImP+LF/rr4I2RZCv4Y98DC/a6nSfZEqLNonxDQRlBls+jKsMbRRDxum
+YPIO7V1O6d2j6sDKW4rHal4llx/cezldhiK/6S9qEJ/+cjozQNICSA4voR0h1L5u
+ZvbGp5d+gaGQ+v6E88CcMTKDupavpvsZ6rQW6Yq6so2p5WgKU3+KdBs3MPKoDyk3
+RCCFHS4LxXLF5I4HYt3LU2SXarj26Xpo/6FhhLuzGaJ1r6jNuTGV6RUEZHSaMl4d
+anTwgW8=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E1 81 B3 0B 3C 20 FC 64 51 F0 57 E7 B4 DE 8B 34 2D 4C 78 9F
+ friendlyName: deltaCRLIndicator No Base CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8272274058A2EDF0
+
+S3vB0SvIHneL0yWIiPOHWfK97IA/z5l2nkIo42y8IMeG5QL18o2b842vEmSq7DC1
+D3mSg65aa9ShAwtQcftH3+Fnp4my8oEy1dJ7LkGsPQKRrgyfWN6b/AvsB3TUEAGJ
+wC8wuVy/ASLKk3zfQKJtrCNTG6aEVfcx0yD83mE2LvsBl8HmTO2OxldvcKd/hze8
+xlVk3nNPDcwwy6r6FyJzQmqd2NEIOHTeUOHiKJD7PHhjpvJhlDHuzfivuGoxVcOF
+FReOaT+psFm6V5lNNqvvQxLfxv+O6h2+nb3D0gZ6bxTvpCaS0k8plAsdySs3b3LC
+avPddOf2F2qEY/vZRwVrdjVafSXFRydTWufuEDRrhRgf5JhxiJFN8ALPb4DWmYLi
+fmYsgcFVR+GC7tafQYppZJbxcYbItVgPmCXOqq0ndoOrVZObPZlz0rrNk4VExMIG
+ewViu8cv3hreBQFWT0JvCwVXbVTdxDlzBXHluHFjdhD4ZK6Ya+j8k9X4dkhgo+CV
+QU3wUox95YQbGqcg6SWKVEffJ1p5mqsJl2KR2NHohpDA0idGUPsj/FZ0s4yFetmW
+qQfvlhxLCMLIt+AFoJp8WgXtrv6AICDAjMBUulidFjuZy1fhdsBmLyXI+gcOAM6U
+ouoqvOVd8aCnJNhXtaxi2lKeXybLPrq0mNj+jAr10/ZKxaYpHi0x+sRkA0EJ2lmI
+5GagmktdipkOA2CQk6kWeKpxO0DLCdW8VA9TPixxtvZ82WfGsNlgrNlbMdjx5yWj
+w+1xmtHM/rkU1ueTq7Xt3BW8Xc+pHOOKEvjbeEE5GpJCLik/oqUpQ9LfDl5a2AZN
+OnCY591HEFQ8Bqgom7YpOiWtz/kaCOu3KlbOhiZ+zLrFoblwBRMFUgqraMfLT4dr
+yFsLEF8G80fQ3BCtOO5oORbeUYpPijhpO3RyjNiFk7yDjetXZewbwRwE7Qce7Cwg
+nM5bwPCc+UD4ha6B8UOxG86bdY+rk1D8mhAZN7mMQpEVJStIKC/91XZjyWJT7ZLZ
+jWAATAMPKQkColoCJILlFO1Hah0Zh1JhVcn09BDyudQXIm2m4+SceD+Jtlak4+Iv
+6xsvTsiLBgCPKMcy5s+B8cIyeLOUwVLqSd3b+uv3TJF54ANxIjTfpY7isiT1IyLW
+YbFuV14X0NuVs19MoYq+yzpFpz3z4ERtDMlDPQUXqZTr27TeNeF4ALb6fr++o2ja
+/+EoPsr9D1QRWBIy3FxRCGjCX5Bd2iS+mMDyplCJ5d5RhxIFDZSbeYVPC9VuyHUt
+IHHq030V9N5SjIXOR+rKLbxbi9xyDOQJwq7Q0encqn688SOr9PqsevSFnM5Zr3BP
+vWBl1U0ChwQD40pEc8Thteg7BDoeomeD670iG/ik8xW4XMbBT2sMmzLt3JYeZAjR
+Ef9bvZHjXShnWCqgPMcYpmT5ayi6V645PncNj0z+7Dl1il7JYuSo5lz+xo6QRNSq
++kESksnEcvRgnxL3bFUHHLKCs2Q+BAeJbm2tRDU1UtGXny7k952ULVIF7D4voNIc
+i5dNyyQUXfIE31Kdw2GewjUjkXtFSUF/RrK/j9OBPR+VcdYKtt/siA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint1CACert.pem
new file mode 100644
index 0000000000..0317457845
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint1CACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: FE 53 4D 03 9D A4 5F 00 E8 DF CB 39 B4 6E 8A 0B 9F D1 D5 1F
+ friendlyName: distributionPoint1 CA Cert
+subject=/C=US/O=Test Certificates 2011/OU=distributionPoint1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBSjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAsT
+FWRpc3RyaWJ1dGlvblBvaW50MSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMENYynQ66E+JgY1xOwEnmlpX+QdSNkLIStriNPb9+e04Yj6oIIIDPIO
+/nrtm7JkX/INHfmkYCwATYLWuSPRljutttRqCaja62DccwRV2ihZkBNV5Ptut6Ow
+Ec4Xeokk9704E2oFyZz77RFGZj2B9IY4zgJhDsFBUoNLW5f35PFFZnw7OBYug4u/
+yUAFhJD+T+nX5ULtCEKcDNelpEMqb13w79Vq6x5ppkwu/JVTeBdMqNnIFxNvt1/9
+tiyd6P7ZCRuFDKoW+qpV3jq+NhJSnfSxLeaa9AVqsZN56Ipl6JzYl2mKCUN2yGf7
+PTSiOP7a+T5vuk1fprwWvgqE2up63q0CAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFBEwc72NcCiC0m/P0jftzesjkdvv
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAqvE2hwsQx+hGq3knMpgC7a7u
+k3Efu3rqhzjT2cWDfNagFGwSp29BEKVlOayp+CZdUVZsqs2Ciiv9/+3aNaYMvVoa
+kSX65EJ4+f5ypA3kjEVQQjRp/2caWfoAsuyO1uI9T5bqhregHFplqvPYhLU46ZXk
+Bl+WrrqkfJX8lnGK3bLN8aPd1WvD9P/We/Rq790RGm44zZ2QtKZKL+wegrSVSOdS
+0vUV9quRfvEVIu/JzzRnxkTj7f03/Gn77RKeJux1jHlm69FKz6gWtuZ+gK6gO56t
+Fi2DvQhVBGXVU7pDDBbT+tIWZptLYGLhtDU32CDB/WmuyjPxVehmtWCdIP4/NQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: FE 53 4D 03 9D A4 5F 00 E8 DF CB 39 B4 6E 8A 0B 9F D1 D5 1F
+ friendlyName: distributionPoint1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4256DD02A40FB24D
+
+551dFf1TMYbIL2bCT/LHxhp//bPnIKHjBt8FQjSq4uhPrjfEFeAxLdPFqd1WMuPc
+0kBvaKVexP0KtLd+owsMwb3bgw5BLKDt8xOm7c5auzjJ0EDRFxBl1WyoXJTnu9wK
+uSVS2NLv4XNgRAThfOvVYXKnkNCxiL8/7RCAGrGsvsPpoGTFotdv0NZ6yWkHO6GA
+FoNb5uM+xj3hcLd9rt9sljSFrXiqWc1a6ciE6eK23Ncol4zCMW/CuWTtBrppBNy1
++toc5GRfbxi3T5uKP4UyWV6n104cvGBQzk7Gn8FSa5/dvU3bXtJLiUXQujLyeVTH
+xF+Wc+NMXNe7vF225rxiI1DTHlECiH+AvzC02jCGzFKjw46I4r7vsyRzPY/SYHmg
+4XbVIdws+0Hd4wrkHAhIc08gKJ8pAZt9ZmmUAlQAP65924Vk5TkmatHtn72LDlGW
+d4PHXKq/o2cK3KW+yFFzVkUepnEU0/hsqSQMq0504ip5dAlnn5TDft1kbNA8LojO
+W0kWVXdgrzgPvXhe8zdRXD2wRzhGc1LKOUknmAkJV7EDJSJEm4dLYIX/D4iH8NEF
+1An6Mj/FM/i42c7SNsd55IT2dJS7kxT/GgKSj4RaAZVtXItKEWbpxv9YyNOpNM33
+9uGqmW7yBfH/d+xmeN8dAWifWKjJFobwK6uJW3U4FxomcN6Y7gfbXyj4qBNt5Ja2
++fcT5A/OsiVIXFCb1qpMdoUKGnYJvbDSqFnB5OE0WvD/0DcQNKnV/maid29MkJSk
+vZJUcjw6SYT9h5tIuAXFP9DFMjaI91RLW75JWVkSOApTptdzpmsRkJHOGRBaAIKb
+6ph2VPEr6wDNy+c4nA6/b8Di7JT3bbsPUHOlNnPxpV+4bGBpzZQ1hZjAl0WqNCS9
+eZJ3Wyu4py84hTbgM8Ayewi89bUFGSBS/tM5JzVRSeZYa6PbUtm4y/+YC4PC1Lfm
+pzykFji8j7w37vv8okwnAm9mXUAkHe4Yq3wzv/vx92ad9O9+OQCwmL5VpRtPUCQ4
+IkZrveFk38Jbl7Yqg9I0zd2QRCRSZcV0tKymMknBRb7zWOFIx5asd5B4/YgSG1OU
+c+zWt0gj7aLNwcY+Li5lbkLQf+juJRl9YKR8rdIEVsLZG8HzSzxd6g1nRGWjmfS7
+oLEkb1fjb5EOEMygnJ+YR8/zWoFxJrv7fhEKgkov2GSynFAK1n136/bjVOwDHJZ7
+40FL0YjWcyXngeK6CeC2yGz+FFDt5gaYhEKKqg8w7QwIOqEE2L8GEi15LYCd5wHd
+ZDjeBlR/AxF7OIZKuR36TfyWj0uY9TiqLFhLBREe40mIE782FXO98p4NizOQOM/W
+wkTHg3Vt70bTr83vzjapsyxsbPJc1lDQ9VjJ9h9Wx4OWwG/HauhfglnFXSZJ7qjO
+KhZW+LrULpX1KtsIg4oKO2NG624VzvlAEtCpklRNpmU1DV+82BHiA8vCXsKR2Yhx
+92shJ+5fOGtic1snUYvRfvTudGaixymnXA9QYYPDTogb2CiCK43cuxVdm2MhEI2P
+hDPQGNkBc+VZpHmDXQf4Z/k7SG0WMAwEGnrmWori3iRcKxq1SyssUdNi5Z2dPZ+M
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint2CACert.pem
new file mode 100644
index 0000000000..ee5c443897
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/distributionPoint2CACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 63 F7 CE 8C 7E 44 8F 60 34 BE 14 C9 CB 2C 2D 6B B1 08 30 6E
+ friendlyName: distributionPoint2 CA Cert
+subject=/C=US/O=Test Certificates 2011/OU=distributionPoint2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBSzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAsT
+FWRpc3RyaWJ1dGlvblBvaW50MiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALQ2LB7oID8p5wb57NwdfJ315YHnRlQWCCGgLmKHKDbxN15m/f0LKYgN
+kNuV3rddlwHkRwY0fsKw8o+scrykcTtFQ2bu8RKVJnkDNayoPASbNnlvFXqQKTJs
+atfy7VLN0nriHjM4GNuQ1kGsOmGi0raZK7P9VZhLEEBcKnoFamInZPX9XxyvLE6Z
+FPVKGZbUiwEdytR6TBhKkw3teOWC7NOF48pyPYT7kqmbqSiiIOziuidtwvPEiA8Z
+OtIYtrf1BC/ERRJ4Q3ar0R1Q5vamzNCCe7MKo8/vYUXD5KlJiGHWRs+ntjoQMelm
+gPjSY0piwTnvfggPhvzK4tfhmUgD0XsCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFERs7ttvf+tOSX94/s3lGKDsu2Br
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAUjZ9l+vtdY4SEDuKVEXz8N5B
+p2vDWBOSoKmPSIAiz/38OoQsX5I3NWb5VTIe9MUg9+Bov6G/7Pxi79qZkSHEnCwi
+Yk5dQDzKR7B/60ImIDydTuBjv9a9H3JUH+sxjViZeGkNBoqMEBbfeKerz5MilHRl
+fWJ2ZX/Tsg36YrCHmrFcU2BoSoTJ94q1+DXlGH/UhmtrD/OzCpS/ltCSIlp5kpUL
+KDx1MnA895+Q93XWU53JBDw7ZrPWEGWvLhHPXhr7FUX0gORQO7+gbJnmelHZdpb+
+69l2hOq3mGx/55qLnyJsyblw9w3UQ3uaBBcY/kZ9KaJsgMpNBzwNmHzD9I5gSg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 63 F7 CE 8C 7E 44 8F 60 34 BE 14 C9 CB 2C 2D 6B B1 08 30 6E
+ friendlyName: distributionPoint2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,37721919A22903DA
+
+ExdsXEgw7tph+8XnTmAsVxrgBuWl/9P80m6gO9/x4wd3DNgcLxHOHim28B3ISLOA
++oZmjuUnJyglLwFxLCndy6UB7A3+0i+lmmY1nc189NJD1khO9XLcj620RRc0hyZ8
+ozdEuqGhtpvcYUiTrBqWSDdfM0WQIPu7AjlJPXJUn16z4gsRewN6Xg3T1Wz/nHwr
+KSSBowCpz8PsBUl2nCIFhgeWezDJLeCQVpK8Pn8Sgx8JY/kQliQRnVcEi+KTQhcl
+ssxjYokbgbKWkuhYaJx5eTeRl0XfhNL9Co9fKObfPsOFmsCydZ2zgkfiPEtMVpPQ
+NyjdtAlpKQFV/JnuXIfrPGed9S4DUGh0f6zqzdLXgXzQiisF9N9e62bV/dJYRlKR
+DEeQ/swqYHLgbOff11xe46jllQwS5D2QzUX5730uLrWKd4wMC0rep2ZOc8o8R1uL
+CqgyjXuSfhDtlXnMQ++vVky05V6uqiMwugYFhy+hUI2J6snvc6Bo905mjxUNQ6Ns
+lKRDWg2s+UZDWZ9vZORnlCCuw63BQaQ2ynjAyWZHD1NpWoAk9EU3qxCrfHynBnRp
+eM17njVtmW6ostxcKwmQfGlCNWOOoNSL7BZ1z3O6/UQOr/Nc+FehcYRxobJ3+u1e
+TaiBy1Sn4u1fOWPFApz/qMDAwfytdUY2sd39alxOnPcd/Q5/yc/H8HENJ7yhLfkP
+m3iy+xX3yeJ4JA7x+3STgV5pMXutUpt/YYfAow4FfNYbSAzG7bgZLk1ZYJ3cJvH7
+4UY7cipdtkc2fCI8xv4aroLuC1Cniyrt2lwtKjLgmpUS55liZ8PW5f1QhF1G7n7z
+H1wEu1JAN62gCP4Is4d7gMrG3oHIO76iFan0SvbodV1e/PQwAH26EHG/cm0jW2xw
+bSauJiOhd9mC3sHp3fs70jarXXxS6TvbRrsJDu8AUlrNiuKj7rH8CVRZCLZKJ8xw
+gxiexhvZWFXIOVI8tAdj6KXcn1fNzMXXaBiuXvX4YJr5DqBVLAuiGhOhe9HUsxoh
+TUbKaiD3MzYALA5Kd0vSTPRJfEMQNBCCXfpDmrRCWXC/M7XyZBXPC70vLO6+wm6k
+LjoapyFSManlyoQcZxYU89TNhoTq533l4Emx25IO8CU31wjU+RrZx8waYuaL+U6r
+TBY3MFV5UTPOxRNyn8QrPoFgk76Mx3wq7urGqLbr/QZVsoSf/EsmiW6k0xEGtCO3
+HInok44uBDlxomNrQ97QXRxFxz0XRySPkfFlOtF7ANciuNw/bl2Z2VhdxcpCdyTq
+P7X9zpTZJdlC1CNmmpty0z/x9IBd5bxarhuDPAd6/Lx9q07pzRU87FrxsiapiQRi
+j4GbCRgQZXTf3hsG0LCTko/DHuICWXoPGtMHX+cL0ivJfPKFEBH532uRQDetS6ca
+dZokky+lG2abugJQuUEuNh3w4fDX2Lw1KvxYaJWAFLcohqwzdqehVxhRbWolLvaO
+KAMKGkIBFZCfi+2kLLdl/HIQPeBQK7qnhYE0ZsCJLJsjUgsO9Iglwltkk44M9lM9
+iQzzyUexzGOjjUXg4BAtNOlhRk2lCW2U9jtu3qC9kgVb6AUMCSfrfA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA1Cert.pem
new file mode 100644
index 0000000000..aab1211b54
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA1Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: B5 F5 8F 3D 5B 86 16 0C DC 95 C5 E9 12 C7 07 36 ED B5 17 39
+ friendlyName: indirectCRL CA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=indirectCRL CA1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBVDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMT
+D2luZGlyZWN0Q1JMIENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALuf5et3e5r6UGUkLBSZ8GWvlLJMbqav8v5qvzCH8/BkfrIBQkxZJzlFmXUmlBaj
+MssFOzcuaBsXQRi1rB+/A/0eBc7n9q/eZJAujc7us0ZxFSR3wM31dMop2Sj3GUcY
+X9D+CtastUIePibzwSvnyWpmhwATVakSmFQGw1dWY9+mJ61JMHvtI/0TAcCNxMF+
+pL2DffQB3t3s/jzu2wLK37/QGRVReH9CoOJ+EQc3VFPPuZDSj9lVEdIyUnSAZb5R
+1pYzyJgq81rFZyGjQRKyThZVM4dvWkFAMjhxBtTon5EwidSMVFSyCJEe9udmXHzp
+8BEUr/ZTitxRviBr1vOUE90CAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggs
+Ba6+dbZlp9ldqGYwHQYDVR0OBBYEFCX4r/yvtqkaG3lL28tkLItLsRXNMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAHLWWL8D7Drl5QC41ZedYyXBDctYlWUsr
+F9S64SNyF4DQQF+H7zBFsfpmjqGEQcQ0RRQ5MX109HqA0Xj24zp5uyPTCR/0ZU7G
+DFfYtkNbLMRf0zuMY6LnYuTa89JcHYDsX62Km52Gke2j5Uv5dhuyU4HMbgnvCYrm
+iCBtdXR8+EPyTKRIpryRwBx7fveMECFNkPYOxeOO8VOpN7s9SBJW9XlMlHJgCgWC
+t0AyKSlOXfGxZOVc+CQ8Db20+66prvugWPxNh/YhDVlCq0MiqN5VeVF9dX46TthJ
+r0/md2iiQ27rUueExcJOdfBVlH0+1h+eMh5PDKpQbhxJOL9F7ozQcg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B5 F5 8F 3D 5B 86 16 0C DC 95 C5 E9 12 C7 07 36 ED B5 17 39
+ friendlyName: indirectCRL CA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7CE6392CC967C94E
+
+mXH2KbKPjlzKd67R2q/xXneWCfc6awdN0vIHgJaeGUPx1HR3pbx1sfnCIgK9dYF8
+nf5W0MMtI0+5vB4airkiy21oE4yRiPr6ijm6/UbAc7Zbepk0Gjfhf62Cqc6mgWq4
+53U1VvNSl1fbaG5Lt/syyJ3XOo1Oi1cc8/4LSUl9o3MLPVx8rRmS26x/LqlXrArO
+COpk6++5uM7oG7g31ctPdpHrNU3CVly5xYbFyUZViexu55ret+rX8MMEWgfD+Ncx
+BobCdFAkpa+DMUbvf6xHm/a6DvmkrcBM0vZDwtfTK379qMoCZp+UrJtmaXIfBszt
+nWybwYpLIreNY1aWt3oSn1DQZkx5el/jrOMeOfScVMxbKfiyHZFvgNMDum/fy7mH
+NOIqLWQsl1CwC19qcmzqntvc7RpVVCmVfTybnrtlgbdjA2CMExDmAVD0WaES3qzw
+MhgjOsCe5KPGtnTeV9YvMJf9dVW6dR7Vb6F5STrD4pCPl25upESgDdfMB9hsKhAg
+q8uc6tlsZRuwIHreG7KdVMkhYMJPUFDTIrks2cpgLZUq8S/Zq7QrrMDUwhZ+ARAz
+hPeoQLmm6OZ2AZBfOab0/V9l5B7k1yqDw8lm2Oh9BPl0RXpcpPlrQvsZRCMQd28I
+8EH22LCNF6eB6OCRHz5Ob5y0drG5IDmG4iWWFiqcxF8BtDfN1wHgs75G9D45GUJ4
+ZCEJxl/UWOxmJtqU4NzwoZ7WTZs47TpVLKecd/a0gF0h2Jc8NFQbXuKoj8la0IGT
+DfplxWd5JVZp598/yMWP2JV7Fvx4HyqGPG3oK4hZyDCm4+BAWXcWw+jcYilwmxva
+RSScp0xtPriLecBSQaZsO+Pz0XzOrncMyPfNIZXqhOXjOY67c7fChPwDF9UV279x
+PpZififIK3R4xZHKKuOIqnxRBqKP0MxF2EI68yjdfmqDJFMZCPjgfUtEoJAC5gSI
+f9nIia/A0AWaDqtYx8XvBRS7W0OlMR2OcR/U92SLobKna8roviNhDpm4SciYRvLl
+kj5XXWFpszcrUsJ3a5sF3cvFjklJkeuyLGZIQxoMa2RQSSd3xNDKc0kn0v3w7fuP
+Cp2io3ipIEeAIQFnRg2Hszyb9cWgfXL7excsfjfIay5Mm1jRFDcopxF7xn1F5VCl
+CUnAB5wiVQtyFwtRzGfQcLkvxUmKkmrEgAVO4Co+4WE4zWhukNnVZbOxDbMAftCU
+7srkC9va6qQ7AvaRO4Q8zCi8K0k+UhSGp1qj5kutxqnZycEQ3RKGwxm0xDC35Km8
+WUX7Dx5NSEsrbaoyWxEp5RLkXnnM3oO36vIQFUpFdfzzqAV8UZYR4eHQIZmyiyXV
+nImH7N3JKJ30bcWjvqURTUEHTk//0gzjKPrCGUqVPdUPf8Sy+eXmmvWOei4gWvVH
+hlyvr1XAjHKU2LAxvCIMj41T7q/EjFVOQkBKVWAU2eciaWF2/f9M+XET1r6ijQvw
+ISORmGph2rbnydxPDolytXYn9Hjn+hqoPS2N7EvUPOPYGVn5lL5RvK668AeQRd0v
+C3zqDX64o1SQlv+5x7z+bLAkod97c9XIgBpjeZhEV25ud1gqkdkH7qT5oS9Rx1Kb
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA2Cert.pem
new file mode 100644
index 0000000000..0e958cc03a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA2Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: AC 34 1A 99 52 64 41 C6 43 25 78 27 60 BC AE E3 D4 45 34 7C
+ friendlyName: indirectCRL CA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=indirectCRL CA2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBVTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMT
+D2luZGlyZWN0Q1JMIENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALbG+vkISj7NavKshMiFDWeY8m/KGblFRI+iNIivcrXR7KoyDka+l1GySD/v8g/m
+SPVWLySa30YPq7lQzK7Z1ZiIFTK4oX//86C9A739Ix1EpE5wy6N17TcN9/84VvzQ
+4F8XgfWArHxkx6iGwaKAewjqbWXrIlJAN/AEKIVdGRDKYJ8WjBsbjqOKW3gdqeXC
+NQArz2RoVW/HPAQ9UBuHm/HA6pucChQg0Etr5rgWXwVOwBz3i6SutniOau5f3LCt
+R572MrldRdQ1PyNlWu+DvYmeHkn7x8TfRdSzfqJcdZHxiaaD0rDAHL4P/VnPqoQL
+wNAkaumLXxYAobs3/eacM0ECAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggs
+Ba6+dbZlp9ldqGYwHQYDVR0OBBYEFIgj4bOz8mz+Mam+i2GqO5KHBaSjMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwICBDANBgkqhkiG9w0BAQsFAAOCAQEAOXdtPXpoRCu4kV9TYCqJbWIdroe9/iJE
+frHjG4IB7WvGNZG7X8frDJ6jpPPa99WsVTsARpcgIwR0dgsPzbfKi60/M0UIlIVc
+qAsqFCkxomILSXzSHgcjry5Uj4K5fKWPJYxjiFtBkL+aBu4K6/xuzFOXNokj3EA9
+dehWOrXS7rqxcs+bTEQnmg29kHrChbekChIOlD1v2dCwP65VM7G1RiqVUCeUu1uF
+JgSePo2t89Q6JupwgNmsR7rmnctEX+RmA0j2wLmEcyMEyuk5NaBDViSzmA6uKwxf
+1lrs9TRq9bHA/K7Nb0sUIxE0O+dMsXwjLDZjCLCcyJvE5ykw3okgLg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: AC 34 1A 99 52 64 41 C6 43 25 78 27 60 BC AE E3 D4 45 34 7C
+ friendlyName: indirectCRL CA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D14DB604D7D17BF7
+
+hKKgFggsf49lZ9+bD89dr9Rdr59yV5eF0lBS7X1pqBL89UFMwl9FSVaQnyqcWREw
+sab3toOiYRvEHUCGM4Tu9ly121y7/KSkkEyDaDQSrW8RPrVJZ21pz+Gmr5Ryrtzp
+OfiYdCIqgxBb1mSkC9RperIEE0/42uN340sO4qDIGFZlgs8wFFq/7Ohm5XktJ7au
+iBpxEMmjG7JbAYTOdVQDnOIo/IqUzTd3DymI6YiEk/oxE9Lk3m0daHBlYWdHc8e1
+2e4rm6WUTpyuAs+XlJSi8n2x8bC432WIcH/D9w81nxqNNEsKd8glMzGUKnTb0UGD
+0+9+E9nV3i8cx+mqjgF9if+ZDGjN2Yj+u9O6mQ5BIP8BxpcpfusCGb6asv5zzK7O
+G3QvpHAK1NLF7Z73YhTjl1LHViPwrndHRtGbzK79s/d/tHFrc3i+8QaGklkwCJo1
+IijRyCqtrkTDIOzI+7iqmbZvUnecT4pL1l8JATRCOyDhV8StaimA3KU8NTEpYcJ2
+TCAOJgC5S2Q1bygCa64Rd+9+E/B+VbSMtHkaRmY9haXBbCpf1UA2Ylkxk/Wsp1zi
+k0z/W+4WeBdbEltpTBig7ofs1QpfbFAP/eItGlr8/dovLj4VRFIVFkAza+vZYbAz
+O9tikQ4ha7uxbHqFRIPo4MIy8ocwbzaNSTF8VJgo3ertjaWCM7SNkm44ERD7Ftly
+CObzXqvhltcvf1Pdeq1uISRvaekhBWe3vmEMx7mFrqucctLLkiF68YjvtzeQIszT
+Z923kYRuTE4ds/9YU7zyWAk6bTNQ0ThPZGcmnooxcCx0guNtXdXdZz+j9lmazyww
+INmSqoxtWUgnq8Yic5mgcu19pYC1aHLCgouT781T9p38Y8oBCSPBZEfV9n31xPz+
+dkv+YR9U6lR+kQAi3J2HWOaqYM/hs6SPXlGqCLCesANhlsiJoqeGvxYD9uSEqTzn
+/CvHcc/7IP2WIHZGTx7v5OPIdYB0XC41gqqBCSVadPjjwaY5ydmgPbuMgt6lVt57
+BjiGciVHJVfThITQ0rBsXZUoIWOtujqNB9rQ/Vtf9oPLjL84Tf3wPPtVlPtaLJAi
+s95rt+QkHsDil1sKky+eiq6n+dS4qI8HYvFrxDb66Dl59pWmrXxM7AMyBlKdBYB8
+Srk/LkCyRrHQYOItem/YWXAmKsvP/y3XNVAVJ4tsmrRgWomJegWizJyxlSFK7zZT
+7F76D3bPv9ss8/qZOd+z0brwWG2DIqZfofrIqPUACLIyaawDDoCoBZNHKvOTd08h
+8ANDHZbpSRG5P4U7pAGcb3fTiNYwRUq5Uui9B+VyU9Hkc3UPS0NbcDxRO7jyAeo8
+GUfuPswQDTZdCpvGfv2QfzxvEqhBMZhi6uSrxVk9cgAeW0ZIxb8Lyu4Y/wWB54iY
++nILagoiTll/ReaoMGA7ZcZriGlQi7eiUnjFtnSyKSojMuej86BNmBFjBNcbFo+N
+FFsF1MVyUN3W4AeZJvpyOpwgGylGh50F+yMDPufTfV/zeM2GcP+SncPcTN+MK1we
+lHMEzW0Qz0rgn3Aur36ZeA3O0YUl2HYG8OHXmLahNNF3FjgDdVcH2Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3Cert.pem
new file mode 100644
index 0000000000..a9fa78436f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 4B D8 D0 37 3B 66 F3 24 85 06 9B 66 77 2F 4E F4 EB 09 75 75
+ friendlyName: indirectCRL CA3 Cert
+subject=/C=US/O=Test Certificates 2011/OU=indirectCRL CA3
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBVjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAsT
+D2luZGlyZWN0Q1JMIENBMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANiNK3lOKMs7e3En7Due5lbLp0+mhgqNt/CrFwdoc29BZ3O8NyXPeTN9giRZL+xI
+0af/FZVSa9cX7aYkDIfW1xBCENAqWharbOU6ChJEVVlbyRJnrRrsUfEKOkvg5rDA
+8/7x9Ow9/oLPBmCsBimTY3FnITv9WElB0qO2vws0rlpZve1LeNlO0Iby+w/oWwPb
+yz/v65+Ih0482EHo9Dk7Hyy7SFK03cC2shMGq7YYerpZ+HQDrmQ98J0UllLgbLoW
+0J2X7fX29IKbt3HHfITzrG5qBVmGAhvPLuRvOhTgNWX2v+cu24VlS1I054vojpzY
+l2emDjSX6dAXHJECDomk6dUCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggs
+Ba6+dbZlp9ldqGYwHQYDVR0OBBYEFEiTVH3EbTD/LVdFcSTfTAWfSgAtMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABQ//a1C5EPLrPnVaIBZbc9JORtSqVNdd
+NhR2GhwFFPihKof9CvOu7F5bhBjFggPPfKzlKvHa0/V3RVMm5wpkMgNDP+sJJJbU
+CNGotpJGzxz0Qcy7oamq12rQZLLfF6+9Bhfl6v4/G+WdctDR9LBztruHFomj6WXh
+9ExtH6IVxv+byA8SDazPaVGegDHB7RB5mfScblzLYMiCE53zzA/vcaad9MsxndR+
+zPVLlvMHeCM+6+nv9u66dUqDChYO7hf6eKjbfXMLYqZkD/ODuwt1eGmNaw+JNgK7
+uR2OBjnbTpFsxlRWvr9a8LLdRv3WouHeLXPnZZNXonemz8UJxY8/bA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4B D8 D0 37 3B 66 F3 24 85 06 9B 66 77 2F 4E F4 EB 09 75 75
+ friendlyName: indirectCRL CA3 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,70DC1F7E38F226A1
+
+wcAcDokOxThmTTO/Lkg7H+uovoXaR9vgWtSdwk0HADNerrcXuXUJ2l1uP6avTDSb
+4Ecw/lWOb0WDZQj6CxaXZ1ZqxO74z2F7Ta3ho/oca7qJYoix6qxuzDdk04hlL6hl
+YiUMCPCP90O1FMoqR0iN/4j9sWaUv5cAtq3nYEqqI1UwcULeyPeASqCSA2Yuw7El
+44p2YEya+6GWfBz2jemDDNl5ofqZB6/McABgDxAQ39awXg+d3ClTb0tt+5Rvw1qh
+9jq4VOTEWOw3QtMq11/VmpxO1jur2ltlAU3L1Kww4lUwoR1TKndTGmrQW50cx0vW
+gEAgX6bLjbxTNJjNqORl62W70V9Wxc4tV43mKUq6IeYMQmJM5AdaDfZlSN8GyMIc
+VtpRcGCvUwfAjgby9VP6UCEOaTQhuRyGb8jsOitiImW9C7x/KgsTj9aOSvVjqd5M
+KMPfvcNPiO7uGPKtYFMt+iFdG3sm4FQ2oNUWd2nsnG/IEHrZZGmzXBJS8M1u0kEt
+6sHbs9b2j8yoCzv1tJfHMHWL71vxJ7zMgY84cxUyllFA2RZH2QEnwdUrR2r/aLP8
+hIstF6Aqd2dlEWfJ6/+EWPyiZngtneVDMY9GgqARb0+bOIe7CwusxtXrNGFV8Nu/
+Wjq3G1Xm85kXovPlb/2w+Jo1qgetPSIIV6nu5Jy3B+Qr0Iq04kwthBkusYqezdF5
+qE5D4ez1o5Kojy6NS9Gv98XXM41+qA3mK58v0PAkSMe+hmCwQPVjdLrejWcLKUte
++wFINCQGavl1KvVqHwrDyKr2OeH46FZYHy4kxK7gpUYaITwRuAhfxqoaJRegDW8X
+JILdphexoF5UtXuNba78j/EP4fBOCW4qLirh27mUBqPN/mjvwWcBxCnkkNl+nqy6
++bPk2uZV1vjC/g5lDTJHpXSsK2hjGhX14q92PmcTCSPJS8CU3vhYB+RfZdWiHaGm
+ro8+iESwTKleXQtQb23003kez7k/x/kaqDz2zRTM6QejbH/BCEw3lX/dCZqHXsO9
+B7PtuQ/vlXZKr+1OPmuAMDxC3uz3FK70WndWAc/Iz4u6MC5JUBLBRUbCKWt9qpiN
+1IqUCPK+duGy4t5zm3eR40F4gzNhQik4Fswtif3SLhH/+k2tZvdBlD+pW7wsHf1P
+UG9aVeF8nrRSOGxxm1QvUG29QE/CPmlr2dFIl7cJXUQlAGOkxyRqav57YKTgvTWq
+Bzsb+Rn2g9guN6h1eikF+LbvH3jDjOWCv5UQmQ2oWmeJMzCZ1BA9Zh29qbpgQhBm
+fcn5ymsh6LhLoOie+4YbAH1NgL4BN8GSty058VWpG4TuZ+HLaTi0N968zYWCE4nQ
+EYW1lOR8mHb7Nt/m7vLGoUsyJ4UcUeGRj0Ni/B1Do0EBkMkrL0aWZd/SkKS67TEU
+RNDUte2UXVTdUNG9O8cp3hosxeFxe+JkrH0jIMCokklGywPmRA6M3j7EmXB0bBx5
+1s5/ST2zSclDPWsogQ+WKhMsM1dyKuRPFHaKZZQd/4mvP/UZvgx89yORfTv/6HPO
+h/O5UkPJBEV9PQGWiTITDbZA7qwJXLoMm9T9iY/1xA9IFgPxyc00fYaa4/NQnKzw
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3cRLIssuerCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3cRLIssuerCert.pem
new file mode 100644
index 0000000000..e860a06fd5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA3cRLIssuerCert.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: D7 67 E3 9B 4F BC FC D2 0B 68 1D B3 C0 0E 0C 8E 33 B9 11 5F
+ friendlyName: indirectCRL CA3 cRLIssuer Cert
+subject=/C=US/O=Test Certificates 2011/OU=indirectCRL CA3 cRLIssuer
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA3
+-----BEGIN CERTIFICATE-----
+MIID7jCCAtagAwIBAgIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0EzMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNV
+BAsTGWluZGlyZWN0Q1JMIENBMyBjUkxJc3N1ZXIwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDEEg/m18OkpbFmgcDm2jrpdH5AIAb02lmRStIbYZZu7kJ7
+WPJGEMbGezYr9zg40ALP2a8GIygEDNuw17xm6vAr0ivCYd0mPcZxZ342EsQHLvG7
+u2zsDqw5cfb7BTyn0r7yEiIV02EnKfQYWDqpdV6BoSKnDzVGBafwos3dBk+ogr1c
+2s7iDW5oHM8cypqsOD8Aa/LbMvu5S/qaGYJUF0HvDavQTKKgSq3hg7bwcGL1iI0X
+znMWbMz75XM0ZB7G1Hj+0F4yAMB5NsFw3nfSNYTks9XU2l0O+qS5uhsn8//5odLp
+84nTd6FxGMYXLIhxOE3OTlbszkGNKE7CyXpbVVDzAgMBAAGjgdgwgdUwHwYDVR0j
+BBgwFoAUSJNUfcRtMP8tV0VxJN9MBZ9KAC0wHQYDVR0OBBYEFJHROZjJ709UZYoY
+Ui18EhIKbHeNMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAOBgNVHQ8BAf8EBAMC
+AQIwagYDVR0fBGMwYTBfoF2gW6RZMFcxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZU
+ZXN0IENlcnRpZmljYXRlcyAyMDExMRgwFgYDVQQLEw9pbmRpcmVjdENSTCBDQTMx
+DTALBgNVBAMTBENSTDEwDQYJKoZIhvcNAQELBQADggEBAD7jPyov+IMOSYaort2s
+i2Hn/Y+wxXnqcLw9sTsxCMQYSQTgvXLN9aG7wT0gCNGR8Xdg9GhsMDAqUjwiBto/
+RUcsA4a/8H94SmGpO5v/s9Ow1MNicSAZxn57nKIDhj2Mb4sHIxzEgEp8iclBKpYm
+Hi/J8IOQoSR5e2nZSDoEGZxadq+qZx9BQYlNCMIZ/w0YPU+Xj8Yhoz+RB6my11m5
+cCTmcrMThRIsq8m9NKeRokZnhjjrPFSAaopbVaIlI3d7vTfZ6xbqozxG3qs4fk0Y
+g/vMAD1kSMt+C/wj9SyzJfzqumVilpRozTvMunD/k8mb1kWbyij6/V9fm6gdL6eK
+nko=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D7 67 E3 9B 4F BC FC D2 0B 68 1D B3 C0 0E 0C 8E 33 B9 11 5F
+ friendlyName: indirectCRL CA3 cRLIssuer Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,91F8DAFD91445923
+
+y0GoU9Up1IcqCWyZ+ELfoH4ov1/IoOK0XRRgjI2kOX0+KtCS/kEZa6mFZ0hS60sv
+ArAnokuFRr9lbbyvm/R7Fik8kQBz6BmMCuSNOL/UMPqhhjErvU+lgUqDQMVbEWTQ
+l7AYQNBtXWEm17HT1No9vCy5VpBipphr7x9OCc2Nan9ZHWV6Hzx3kTxBInnyfwYd
+uBwkoLkYXDqvrwkJiPokikc/DQBl2ksKNeWjBUbskwZ55g91qAVg8oWSUAT/picV
+aP9ZXnwYEFcWheooLRLVDyaUIRGlwiRV7KfBrIDE3ClySGdMTMmjzfRWdxk7tH/5
+qCL+pzWz5RGM+Uhvnt2sf5hWYE3aCfIQT2sLhkoiqG/j2FB3MVRl23JSnH5nqwPE
+093Suiaf3qUwCZZpgP/7+ZBftOBnvi8zRZy5RdhFotSXRQ16MNGPxRvI4eKdXcDs
+9rtn0b6NMPlDym7JjscfVgQa5bCFJeaV8gh4cEWYtFIjgN6o7n7RZIJ7ZZBi2v1W
+eMVLB50Nai+EsQr4h3plJnFu2Lh48MgAxIiy3k+xLTGTQyYxJOJa+Ms+jWSnjb47
+XzQLfrZ6NTCKpTVNaUNmbPeKPZ1cDV4RPzkZbd2Hq2gohr34NfBOBp3d0oQFCd6/
+BvD1ZTWCPe088jw+tL5QClXouBPrLTuCUKwDjCfXQLj3HWJixJR37Al2meicz4jx
+seKoygO6orVJubJPzAPF0zIDGS1m2Q5f8eT07Gmgv7XlxWlcxOtzP7epjjhlbumv
+tgRu+I4qBvLVuzVihKduISI9M9Epzxy/OxQMYkNxKt2xBgZucz5htOlH7r+HTHwT
+Xs9jBO3Vc0qsjSRuOBfIP6z4oe8OMfZmIZidYDqXqtcoHai4YYMNyUaeVqSLcfku
+QnlpGGitPFpu+7/Hp32krTd+3B1NljedRB2KWRb9fB8u7uQRoP+oxt8cO87G1XS/
+c5B4j33pvB90FSk4ljvXXWkqwKojn6d4w8URgHDsWsMJRuwrBRnguItgNL657JKx
+qjcTdOPZvFBhCPeR7zYAC1Sph+ik7qqdk9CAOMbFX8BbyFfE2GGdqNxHAiTzV8PA
+4A1Tv6dP5pAzTTf9ID/QugzKglCm3Dvib1fGr5C3aCc/CSdE0X1ba6/4X58IFI9r
+0rWwyMlPShStT9cFks3JeOPIQL/a2ShdeQCjGhdj4muSSdziUEGMikKnSEaKvk+7
+qLvoyIQVmGMx/zG00xbw3lB89sJq7o4KJUXEom2hTtf/wwhO4FYaFLwmBXup37Ob
+P8tsmWERiy2X6aWAtquFawRimb11xCWxWvBmjPVf7g+aXdxwUoevj4UZNEPuKhTL
+hIePovajLDFj2jvtbo2WBU/GHyC2jBs6C7hMCZBhpb0C12I7c28jqHwTdPtB+/ld
+fxudITxmsNQXW+/g90RQp2TuqllKjltjFmtgXT8XQR7SSsivaYhSvyUq+/qGB3Xm
+5MM75YDJjV5WNuFJtTNp2IyKb4gZ5/XDLxBJnuNJT9IFatLe9WkvdldSwJRhEyUn
+PTH5mD0oCCRr5E1Q7FpMsMSavbfN1c5zNZcMXT1Zy7OtEtyH5jAPHw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4Cert.pem
new file mode 100644
index 0000000000..df33028904
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 43 DB 38 3F 81 52 93 48 5F 32 F8 14 3F C8 B5 4E A4 5F C6 33
+ friendlyName: indirectCRL CA4 Cert
+subject=/C=US/O=Test Certificates 2011/OU=indirectCRL CA4
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBVzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAsT
+D2luZGlyZWN0Q1JMIENBNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AMIccFW/U1iXfJpLneZ/qS8p7kcRZMEOAl4wEwPcQNFqcceBINzwzkHMnKOsdbXI
+h/9p2I8+uzRA1zNLL7Z5jJdCskLR6KcyeK/PatB606UOKASrJssK498OHhI2GAY0
+/htTk+Gh9mKEXzh0TwpT5RMeAQmz+0rAG+InatLWzSo0js87MhMcgiBPCm8nVMw1
+31Ju6DOhGJ17zsjWCQgq4cjvniJe0oBmiZJI70c3BjfSyETOLENCkp2iV7v1VjiG
+Aqo4K4iWBlhE2tTeK4gcRdom0I+RMsUefz2TawxslTKBT75jbT0zLc6KcKuawqQi
+UTSeJ1pId5NkBsd3I4iV76kCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggs
+Ba6+dbZlp9ldqGYwHQYDVR0OBBYEFAxaMuqUASALqKovyRLjLkECgui3MBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwICBDANBgkqhkiG9w0BAQsFAAOCAQEApuBvFvvvzaEhVXrF4iklYuwhN3XOAIYl
+iXtVgh7+eB3hLj0yI3vlIRe7FaiYQJyd4WXQgfFtXNnjqCbQsmHu+Z2La2INu1Z+
+GmKryMZPSlceyYlovW2LBATRf4XxzusrkKZ1ovW45wpad3w9x2Wmnyd/+xzcPCAv
+0E1GS/pstkszz46E7S2dtEab9mSHADwesx+rese6zbdqT1wLNgxVu7BIYylgCmfb
+TV2CyQCeatdtAziyLaHtqK1NFWBLDp6KnlRXyjOYg1kVUNX/qQVYcb2S+OaEFQQk
+M7c+30FSksP/pWcQ+MqpLoTpVT9dlwYX6fWxGGc2hqNW42A+7HkJXw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 43 DB 38 3F 81 52 93 48 5F 32 F8 14 3F C8 B5 4E A4 5F C6 33
+ friendlyName: indirectCRL CA4 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1F861942A743C6CF
+
+wK0oBQc+fOeGBEjxMYsOZfrZgHK6lfs84YIlAm62Dm68RErR/Vb8EBc/0nxjv/hv
+VAgCQGTOqLootoFYunij2AYWZj+rUWlbl4CzmupOIpF4RU58iRZ/StQM3qBGiB4B
+xywYmjCt6A4/9x2fRRpc8mAZ1eAAkPuR/GPlxvZBjwueHkbeOw+U3ff66vLN9mpR
+ut7JmvTP13clfQsTrvyo2Ru0xJEOKhEVRm7lfV8EKviFK63jyZAIuHj3b244kgvp
+9XiI7wvn9mTkl50fAV2q+lnKbxBcSqRMM/YhDQ7uRI3vP+5SRZjyOtZEJ/lcWsOk
++15ZvXHLy5N0n8NgsmL/rNpxsyEAUZnzW3jJe22UAG/VxXldm1U5+Ks060KkWw2I
+57ZbPAUQFt9Q2IvmNmYzU6jIsOsfHILJF2PfEiu03P6OQOW7c4H6BiRtj4/nTZ02
+HLg2GYKXIRFlyoSSmla7xA6c05QKgbXkARPLNrQeF7gRs6Sbm1MBznXXieGxlR2s
+Jq5+9OlaJ0TuhUqYbZxcytx7PfSVMHt0D9n1oAc65J1ik8KcBpdmSi1B7brxUH4w
+r4yQvGDuui/uCSLzfW1RNkug1jSUI/2mBRqvJOTzqFblLXi29NEb7TzDXJ6q3qe9
+sFD7ZbbrphLCl4iawJ7tmB6+Uz3+K3w+mkLa3muZPDt5UZ6Y93qLyeQNUk2NL+x0
+7FopkCh7Tp79g4oKWZ7MFcslyWb3rrd7GuPwFC5c4+W1k1PsEtLnpaAxbNLg82Z4
+tXeDnp8HqNk8G3M++193LD4syc9GUBYFc9ToP4oaDVjyHc7RYy+SjfKyh8Ij6U34
+1Ff2uctSh5x93xEhYwh0URdwnX7OrOR8Lo8OPqmTe8qnTJ4Z5uRoMVXxhZN90bp5
+IyHmaJvw/gpNFvTT/PTXzjQYawqQQvDAVXTzOyUPgijHivH107JjT20eVGKdIuLG
+Ty59T+MPf9wamIarR2/RiMLdk266QJaKlR24p1/LSZmgu5jmP5O9S5W3k5Z4VBJU
+ZSv7Z+fw9YuN7vwNWxFf3djLV2zzp/AGc+CdTWf7hUVTs56aSqO/AYmPpq77LEMl
+HjyqNK8dh0VLJHBBlECNx15LCabpmBO2WwpH93BIogC/NE39U//MmiP989+EVZK9
+tplu+EEYVPQKJiKgaeSyAOcf+PUJJGBKggAQrqjxmoWjnN6+++p5koZGwwYQyhUj
+eT8VfphlFlE44d84ZymVsqrJirNrriDOfc8C9MDi+jKrcI4utHThXFNdDMZrNmE4
+dNjibaSn1Wi+YA6fNjvTfGRUl8taHUj75F6Nj7C/ugCKp6AWnYMEAvDBlmsgUN2J
+Eyw0eIkqM7nAqQhnxf5bgikKA3IZ6EjYoDeH6MgigtPEUg/pOEbRrfF2Lnc7F5mD
+7BqdMu/aLY/z5fELT2jADaQNaexoboslnhBUHKcVx1NwYB0nAECGKUf8b7cd4I4q
+2Cvz+j5p2GW5g8hbu+rdMvdueanM8j6j42LV2eBp5tTLyTB6a0wnlLxawqKYbcc4
+Lpbe9ngqZHoz/x+cNyCx/3YX6QeHWQobACVe6fRYtW2sumwi/Wt7Pw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4cRLIssuerCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4cRLIssuerCert.pem
new file mode 100644
index 0000000000..68c5c76a27
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA4cRLIssuerCert.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: 8C CF 5B 50 6A 15 7B 2A 06 9A E0 FB 03 9D C2 ED 71 5A 7D FE
+ friendlyName: indirectCRL CA4 cRLIssuer Cert
+subject=/C=US/O=Test Certificates 2011/OU=indirectCRL CA4 cRLIssuer
+issuer=/C=US/O=Test Certificates 2011/OU=indirectCRL CA4
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJl
+Y3RDUkwgQ0E0MB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNV
+BAsTGWluZGlyZWN0Q1JMIENBNCBjUkxJc3N1ZXIwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC9xeOutJme+85JOGzcNASVfrEKrSri/RMChEdBr6Fh8V03
+G3j8wKFbvoubSRpFn14/pqk8VyWURjeqj2knSeYd/WJI4f5k7GTo9oD9ysOIDw3u
+giAY2IqQAUhwTyP6UhpQhXNPnmHpS52lUGIe7Naq5s1UXaTc9ofg/qKRSHTOFZ6O
+xO/QwPC5upcZ26ooEV46qz4Qe0tFO9vGD0XTsSgBKwguXPlxd4Jkyd1IYh7QfBqw
+5sKmJTbn7zvbPJ5cnpkJvTyQmiriu/GnmgBmYE5WgHd9LE4iSTfFuLv3ssaT41rM
+yq5OJzi1J2/xS0g++9Za2Tzxqp/0gWVYUYfM/MUbAgMBAAGjggFdMIIBWTAfBgNV
+HSMEGDAWgBQMWjLqlAEgC6iqL8kS4y5BAoLotzAdBgNVHQ4EFgQU8wjrbbnFoBCk
+2gRF/696R68RwLkwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA4GA1UdDwEB/wQE
+AwIBAjCB7QYDVR0fBIHlMIHiMIHfoIGEoIGBpH8wfTELMAkGA1UEBhMCVVMxHzAd
+BgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAsTGWluZGlyZWN0
+Q1JMIENBNCBjUkxJc3N1ZXIxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5k
+aXJlY3RDUkwgQ0E0olakVDBSMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBD
+ZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UECxMZaW5kaXJlY3RDUkwgQ0E0IGNSTElz
+c3VlcjANBgkqhkiG9w0BAQsFAAOCAQEAnk525PYwE6GN0KVKCE4B9NFybrWSSmt8
+Eh7bG1bLDfd7aBW2yjHSR0fr2KpYMW1OCB0aS7H9kOOrMYoJIW+fDWmw94oUhML/
+nvrOGmkaIuoPFKY1rI+s2NdG7taUndMw2KFGprToowQtWTs42f33NCi8PVmppXKQ
+HbAaPFl3TBJ0fk1d0dmnpqYGHJqgRSbt/qg0pUisYPhMqD4kT/4iJihkfovfeccy
+rptvHA6XoTVKREP97eCKGpK3SZ5eDoVSlT84nwlqDlRzvBgCnyRyR1eWo3lmWjox
+EmqYwJAXHfPRumgNMuC6ccAEzUMvPacD8z6fCWjR9uKUE5opGo5ffA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8C CF 5B 50 6A 15 7B 2A 06 9A E0 FB 03 9D C2 ED 71 5A 7D FE
+ friendlyName: indirectCRL CA4 cRLIssuer Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,95D33CFA36DD53E6
+
+ygCly9uXoWW4ISD+WxAepT9rBjaL7KcFLxrxD5s+xmWh5seZeVlmXsVOdebdkbdV
+AZWNWTkw8Jz+hXmRfHEkvJLZZwCUL7s05hyWgxJ9UjT0iaUQIlwJErcm6JyaFkD9
+W6g61L57oLq0rrcv1KMBjD52lwjtGN67RvesHxLeAVIndqlhl00MhbCe7cOi5oVc
+hsRjqoHQ1xVdNQkIdFzK+4nqF+Bz7Nr4oFWBk+CbjWHGL6MTf0mNtOZnrxh+O5d1
+aEomxqHtW+JyLoYLWlLtfJj9kWMJomaO/c0xX6FZ/teUk3zXRxtHcDocrCgvFiFh
+TPHkCvivcH6bTqr/WTN566pZfodJKsqZmV8/Y8BYx2ZfxWN6JxuxysELP7hPX2Jj
+1Uub5gXEw3GGpXd1OfKm42vvONd6usVbfe6gtUuH8WcBArZkNkIjGrtNA/HVUenx
+jv3HQyfOHufcBrEAUqwANXjVY11sW6ANPSBeEjnjSzFZ3BlPTdDJs0DTibbwLjAv
+IR4Jto9xra00Wo2vRNpr0yPXV168xL7pHa3opU7jlQCg0qUV+JTS/YeBfRJRzM9Z
+Le9uGl2xYZBg4IgoMLl/4czn6NmLxp1//vvC9r23e7/mqCZ2mHLtyBCcUgLkBlFl
+hkI9gR2QEI0cn7ESY9Q3cMOxb71kpXYRzbW7qKUagOkFzgQTftbxPfPQmUfLMxqP
+m9cqn5PyL5QQlDfBkm5NGsHz1Nx01bH7buBSh8HLEr912UCZ9wWfK7VMjxu2hObv
+UE/B5EMudav1PT0pj84HZBWnmEHFkbZZMGTCiC3+H5rQQIQwC5Jbk8dAGIur+yn6
+j0iNybXdtYFyzV179h+FcIYRFMVIbGhVGd5/5kBeAqDjuk3WKhwC/0rGRyTNNbki
++HdjRF51rZ5E7ZnkDCW1asgUeu/mWyyqbg/Sf/CI2SHFM2BTO4QnmBhuqUOZemgW
+1CS5Os9rKpMXh7g7xRr+H21tN6MqCUoVQi2cQfpV22VGF3OTFbayw0bMQjQO7cmO
+4ij3Q0MTG1BeAUDiFxs5ler43HmhxxMW3psyHzG4mos/IGkL2Uie54JwVjsXw9Bt
+jBIeIkeqSDCANC8s/Vs2oq8yZnFFNrHokUdO1FvJ/3ADrwpizhvzbqe1T0U84qH8
+7eJKgQbzcoZzPmlgBQmeHkb1CGsKxxTZ+Z8VoOnvOh8AgoWcan3DaShv8OJMIEaK
+++QiCN9AMVefZvWniru4ehw+hq8aFM5uCVTDIrfjsEPJ7DGmVtl64+0i+30ab06R
+LEN2O8T1dkWWmzb6Wow7srTk+seyliAvfKXWoKwpYXivK1ULls6fEXaA/stfcZ87
+ZmlokqTlqDRBYxuujuPlOMIp755FmX7AUIAVFp/HKQCS8hb72wy+ETlLhhfrO1f8
+qFi5q+DmE7WwBKm9LnSGutSrnEXYad711Dd+aFa2elXUKXBy4GSHMDDAZTMMK4vB
+f32ql1j1D/CicVB5ubg8Z+gAu3QbOe7lvTzS/9TYltb1m78zwljjQcT5W8chCuV+
+uex0J9KInh9PwHfDylm5vpNp5gdiTPpktlcGan5t7fRXaJ2qmmUSfQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA5Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA5Cert.pem
new file mode 100644
index 0000000000..b2f82c1a97
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA5Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 27 4F 1B 00 78 11 92 48 98 B9 DD 80 D3 52 B9 CE 73 4D 3A 67
+ friendlyName: indirectCRL CA5 Cert
+subject=/C=US/O=Test Certificates 2011/OU=indirectCRL CA5
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBWDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAsT
+D2luZGlyZWN0Q1JMIENBNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANCnFJyRRuG+54pazi6+E/5j7N/GM+HyV8HeSNEtF4lXdOxwaU3SnKYCmJNMM7MT
+lg+dkilaufu3TV0Xqb8jgXXP+GbTVHLk6bzTozhDhh842cF5nFfLZvpp63yEDFFa
+bAmlV7pJxK5mv+/SQHIchckJOOZCgrcxRulUDF4SZVhXiyowX2p55Ipuyb/Hxbea
+i03e+SKptH+WltSwtuRuI06SLx9sjJXDQ6xdkrZMogDNTicjz8A+dbHMLBoxqHDv
+rsCzTWTPVOR0y+AXu/5Skfc/qsBzsgSSR0s8TOBflnKFVQhXncKQnlUtzxWAE5Bu
+rjKEgo9Ubvuv3oHQhHDkh6UCAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggs
+Ba6+dbZlp9ldqGYwHQYDVR0OBBYEFIH3qr1IdVmAsM/fIxid2JNGghazMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAic63G/b+yfTHBtYeNKkZwT9RWSs30IP6
+oSNm8yx7R8kbpKGtfUxhvct0V/0Mn88yPf2vh+Q1ILHYltgyflOO4TiskFy+82Ug
++IBibEqBafQqGEF0jfzw8ziNjFxLIZbO4KKdgbCu8lpK1hE4DJZSO1Qmb2VWu1cM
+obQxILQpT70UtUThwzILRMDeOn4suF/cMLzhyry69UXwv5E7y4pe4/jJRkwFYPpW
+MOqCTs6jI9y/0fao95iwi0FQVVoAzu9T4qvAageeUcaEIM9MhI7d/lJxJhdI8UxU
+HaxFfVvarYxJ6Y566RKfhMS60QX5Y0HT1IbDPTiLNkvBJNlOMuz1rw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 27 4F 1B 00 78 11 92 48 98 B9 DD 80 D3 52 B9 CE 73 4D 3A 67
+ friendlyName: indirectCRL CA5 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DEFF90C14C4E25A8
+
+/Uq3XhQHgdnCIUFfwm0F4VHwNuiLV46nWrchtUiDA9gtGOZWuDZWBw0Qma0b/AFK
+uzQOeXDiDL44WwntmcR/tqHT7A0Np1wk1HA+XZg1MkLPap2W10fn+R8PAguzboMX
+yjGUhhpbJ5lzdGNZ8qQd70t+K1oHdY0e7CEWkqG6/6jCzRTMn4WGez4Y0tz/TAjZ
+aV13WHuhlokWL72tGkkVvWFIW3u7ecO3Lq++zc1M67e1v3zMTy+LuKjejmQDttXn
+hvel5/F919/Kd7Pxf9e0cjNJSBeymokEiHvnckgDB/CAe+sALVMM+9neDu41kskc
+8JoZ6xN3oP55/JCcOl/oUnr4zMuZ5h812BQLl7QnBpjbwiurtrNQwnD7iYmb7RB9
+lrBjYfs+OgLIQfqVYbVAKL9DxqGil0HzYDKolNX6PSewl6KNsIvvDZDI8ylpb6iD
+nche61yNB66CR2dGDUZtn3xelGo8AqKkH8itBXssYvhC/38FYV3uLtE0NucAz+IB
+WheyC6p/6EQYg1z0Oxcn3LxS2revY8W8HC2SrhClTxrSIs5B3yTTUgzKEc/fAOtI
+GYEy0YPpBjEOxBhnicBYFfSqVk1Ky4JyOOBIGfhEm67n2UVKM9lvuGmB5o9Q5/bb
+kQv8DEWCtf3L1RZN/iR1Avm5c8gVy4aggYiuJncI7ZACmhuFbZdEgVUMg/aDzKqt
+phcL8Jjms7x9ZYZr4xSQcsJOtqt4WYySPFqk0xukytvWJEH7pa0xp35ycSo4g/U/
+1EAq9jBRzSVAe/+ufsE01Yu+S/xjPwmwS9C50ArYx5sFzk6YKYnYZ93j4DST05pA
+7nCoLDFLSKqRscLMsjEppPcudv/TJhJQmceTtLfzgat0zTkfUCALNuAhfCdai7yl
+l/HN4pUQj2JXPiXHIOneybH3Z4P/MyxNCDmncI1ha6ZYuNLqcSmIZUJz7cfovr19
+Z0lWl0OHSVPkav7m+UIYvppI5f+PFHsuz7+R/im19VEZMQ4sseswvFUYAZ98YLMO
+bgtsvo2iqUPSka7ejFo/pmwQQlFyQEd1zNXCUF1wEVqDH4kejz2TjgKCtDGvNu5V
+hQ4eeh5m2XkX3IlUMJiFle8Y5W422ekk6OzPLmVl5/iPrCVjshlekcLO/sPPvSeG
+4FT2DPk/twcEmCJ/Wg0OcGk215mspNwF6Chk/5i9BPcmdsLjT6NFygeTQYtVAOrA
+3dqoNekvGdH8FmgA6pCCbBUOBboKbNzyhE2pOsAbkbKPzrrmKbMO0516cNI4nfq1
+92S0owEUqH6++ua6Rp85ngnjm4ZFMa/CCw3lnHJN3EpeQTQ2EIDwnrJ1WAroLZ0G
+u5fBXJrl4Jj7QdKZpayd8vzrxFkOnT+PzHJYTQVWhk3bHFaPWBDheRVILa3uzFEj
+DCkGKOJwTzc40QclIeexMu1UVOjPtZZu6hdrIQqI5HEMLLXPbfZqlqQ/5YCr68FI
+XEweTp5HiZGWSd6d5o6u4lmRsRVoMCuZ41AAhMCLyCUnXUBhu/cXIi1SaySdpss6
+YdQ7GkuvZ+ZceWyVh6RaCba3eIrxo8lh1ZlJIRsX4stvwH9MkSNPSw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA6Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA6Cert.pem
new file mode 100644
index 0000000000..6779e6d5cf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/indirectCRLCA6Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: DF 60 70 22 FD D8 66 5A D6 48 71 B5 FC 7D 66 DA 67 7E 5E 0F
+ friendlyName: indirectCRL CA6 Cert
+subject=/C=US/O=Test Certificates 2011/CN=indirectCRL CA6
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmygAwIBAgIBWTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowSDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMT
+D2luZGlyZWN0Q1JMIENBNjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANr4SdBfmvVoe7FX9vAiUwmvImwVjK+B8t83+7CNGq63EWeLcQztgu2PU0p8z3Y4
+txQrhxgEbAc8WvNnLVbPRwqsf4EXvugsVh8O7jVzLy9BTrmlGPRwk+dI5LFlCZzJ
+VzdkAUcK+Q7kjK4OfkYEBo6TVYDxgjm14NbXNVVKahJQwTllUTITtQ68dwd/IUTt
+Y1Tpnb2DorIwyTDtesMzGD4118RxyKmBwXICic5Da8Gh+laHXxiz66voVvzmed2w
+umTngY27j/VgoHkc4ZMV5S5wFfFnpZeqMCi72Przwjyq7KCkB1LYjJHcfkVBQLDd
+2LjbqvzP6CB9P0cyzZXtfHECAwEAAaN8MHowHwYDVR0jBBgwFoAU5H1f0VyVhggs
+Ba6+dbZlp9ldqGYwHQYDVR0OBBYEFB/JII0Lo2wtd08T3kL0C7beKnYxMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAWH/AphxOKQid6uERppifz0XnqpaHMW45
+GKgeywO560Uxfw3qZQesXDRUigcMh4XKXtysK/ILWLiRzIGhzJ3qR+uo1g5Paymv
+76azYg5TQbKRBnqTq9w0JcrS3s82kKfVqQcR5PbmADorGFMlxaGdVMFv2ImkPKO6
+8nm+S0X/xmjdLkVu8Kvbw8za8+FQ7IoCsBNlel4NVf3Pzg2wpexF/j4ZFEhbv8D+
+1VtoLohdbsQAb42KrT87x/xTTWqN8+zbj0+b8As6LGDmjZbuIeKK9NCbh90edTQC
+o89lhuALG0+Zk5sFhoYZ9aHjLyOEUjkm2kq+SD0ipCpb+/sCRyy/MQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DF 60 70 22 FD D8 66 5A D6 48 71 B5 FC 7D 66 DA 67 7E 5E 0F
+ friendlyName: indirectCRL CA6 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DADDB1A0700F3513
+
+zQhH+108kzz6dq73i5aD1o/KmXUZmMAn+7JDTpSPl2q2uOWD1PoOAqaAJFsB1BxQ
+QpqG5Cnl+9ogcC+rsMx1RctN4sIFd4nVi7pUzb+GIzOkLeiwfBEKkIfOCjKc3dBs
+slVvww7VECcTP64hMpumIP4805QfAm+YBVra4dvLTqXretUT/38tiEF1pax1lZPu
+SQBzE9nIRtCkmbHJS4cd/x3GecOMlUIVJeGwqkLhtwk9KasjbSDUEoj+TNJbtQh2
+amnAfXEu22q36bGyZy8sBr7inA2QIJHtzcXbkpbVjn6tIoyrvDQ6kYhtvFmWkqde
+NVWg/ef8c43bskiWxQ6+vmQvGNo9k6XUmjiv7fo+sVWxvmmS3aq2EhD4CUPozXMC
+7OqT4ZW8dZys4YGe4vYqIoaZXj2CupZlOAKxr7XC4eaN8P1ZBhgXeKBUvddAvCyy
+CeUxAfJ9paCLYyNw/MBlMbvzbz475wDSAj/qWr3YDgJCBWXYCZv11oTE6H9Au9om
+WBwjgjUzcZTXdFTOfxDNwo4qs8zbpCpASqgs2/ofsSIcIsshkZsmndg+oJsdJp/+
+G+rDaHGa4gfbGNyd4onmTMmIAUMi+BifyHTM1nfOj31ogJUKF79Wk1Wm3JWZ8P7W
+vN0a9FTC0RGdOhE/yv+uwzKwulYoAjUQdqoQQ/pYzRiNB8wwp1yqlVakBO9IGOWo
+xb+PHF9HPxbEgbhb3k6GQIQDCV4PkHOu8EW2L0CKO3arCvLpT3gVn7hcVp6fVq0o
+bRUcrtkZsZaVamF4+1LIJjHki8/X1XHsi5LRmuFMQn/NX12KHi1eYyvPHg6hnnR3
+HwIoYzXJolUmnMDxo9ql8B2J5Vtp0sgI2sz4b9cI11ozg+PUdwGL9/4V4s1Kv404
+L8vP98YE3tlrvTtUYP7YV7kZxlmXJ5PonSd2gvzOogLMMxnRNlhTUq/zX4lTmx60
+y9YnA034/L2MWAgk6rCg9lvC0NEtXQgHzIZV1TyrKMpdX2BsOU/li9P5JoFOkD3d
+jdaI9af/8+XMkePh+AVHTs7NVhvb7Dyoy5BPgCL0XwDt6RkmcKSLAoXNutXb6jLp
+K3ROyKtu/C4nkCDedNerxdrQvrKiS7FUO2+xwdhsU6vhaWw+87P9GFoI3Dr0jKvO
+ADmV4H0JKbk687DB7NVAqq8BibxdD1d4rUZvio5KOal06Tu2f/1CewA2a4mMVj9E
+GxqHDOrymDaNg5YLu/H3XDCWwC+qszsD1/2fzwGLGgZl3mJX9AJx8c/T6axbqyyP
+GIaLkxwrN9JtKO8+e97cCKUylt6riLa/0tiAPUG5RJizBi4ey677xr1L2ICExFqU
+lDY22m+ezGwrfZhi4yVIHS45KG9+pF+om1XYo4cqmAHg2QqEZeiEOsHgvNAbyQh7
+1uhPhSCUVsAlFqWZr4sJLt32Kih7KN2UqAZBGCxox+l/h8Vyy4DZwAvygMU+yYwp
+miEUhtB47LBHTFegYLdbGnPm5WYHppECneaIsqjgXC3TXqAXpEQEi5rCBIRtpqUz
+7rwjlNmY/k4TQhyY9ielim/ouA7FISvCPC1voCZYHtZf29EVvFFzf+C9uLzA/31n
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy0CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy0CACert.pem
new file mode 100644
index 0000000000..bc04fb9c3c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy0CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 9B CA 08 2F 8D 70 30 97 45 EC 2D 50 73 B4 8B A2 ED B2 53 11
+ friendlyName: inhibitAnyPolicy0 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy0 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIBOzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNVBAMT
+FGluaGliaXRBbnlQb2xpY3kwIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAwm7RmKNqzNVB1upuD/XDkNQZe330VuJCvAN9qtUbmOwBCQ2Imy3G22tO
+o0g0sd0FlDusckPU2bfVW59Ya5SQXlfQq3Qu7dmr4SznXyLwjEFkJex3YFi/0RiL
+dkzC/2ZK8ikQtU3HHznh8qImo5sb+STz5esh+nqtJy8+eWf+PzIRzVtGxxThnqCX
+fwCOYcgALxcvZEyfGmZpKGjyVGNTmmLXYUHPOaMN84+sTueys3R4WaidErJQihOJ
+I0D8k2zNiP44crr8QaBPDYujleFp99ZoL0p0t9rb/i91Oha1YR4AriZOkSdZ+12f
+l4oYmUVSpiSr64wKFCFYOTybXDHr+wIDAQABo4GaMIGXMB8GA1UdIwQYMBaAFOR9
+X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQYoKB6av9qnYWCJM3DJoX4v4o3
+BjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgNVHTYBAf8EAwIBADANBgkqhkiG
+9w0BAQsFAAOCAQEAYACyQ2xi2/hapopt7cI+wPFzJtn2eSzNP+lkyRkp8VbtFW6k
+35IPAUnuS+bcB92Cn0LwwSXIzMJ6Cs2su9UmKox/psMXH8UMeebjL4WtpuzqtGLX
+eFVo3Cmfdih0JICYo952u0Ugzw5LQzMMNDgtcSjlo+OP7ksOyvP9o1hKfk580cLV
+X+PiJDmqGbnP+0ERDbN4pRQvYNGNFyzBgqGpiIENgWIJwc42HTHpaG63Y/tVc30M
+3Gh3//ZomjVlWg12PLoYefV3xv2TT/uK4zb3ppeznSGso8sCYh+/p6/T6brIyqUh
+a2yA6ge9SUPKy8EVgqo96s7ofQwobF5DOJ9UBA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 9B CA 08 2F 8D 70 30 97 45 EC 2D 50 73 B4 8B A2 ED B2 53 11
+ friendlyName: inhibitAnyPolicy0 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9EFEE878D3C13B53
+
+COl6N0BIwOOAKEUyflxLC9tGHBUEeuxCMytbs6J1DBteOSWocL81iJlPHCcDsgo6
+cHS0sTXbvbxC2le816uo1q0gE1OTKZtfL6HOCOYzK0lMFKAFP1aS05rccR8r+CdF
+F5vcIJ1yyAhdiqsr6LN3m2Px4COz9SoepzKxevjGoQBkU1LsAlql1cg+xUCwVapv
+nRoq++fAzF16YOLER16QSMMJm6gRRDstuu8ugrV3h4bTy46hsHmywkDxhAdaYHft
+Ao+I39Bq6+F7VoYTKq8rogA51ML3mmva0sQd+4aLFH6nm/k2QkKwxawAimy7zoKk
+6jdu0r+kCN+jXGqFtg5lRTdM2WpuHL2Hustq1t4mGQSEOWgOqW98VIKV8O5Yb6be
+xz1HaAPEYaCOOydkCQW7Gzk8nyzRmPI4zh1453kF62p3O69IKh9TkEp/Q1Op9hdn
+iA8W3BSPm8Bm+yEjFu4PDQCS7N/FjWhH4nfb0/VCZAX6KS+lAxtYTLDf5klgS8pJ
+zhYGqAH32sycSzjuvxWHxpHRs4vL2izRQzKWMYpoLaldElFAY19eKiVWND2Xma0O
+KDjdLRF4XYXoqiWAAPR4amdPiI+5uRmHcmvE/kPm3lYwBEzTt9Hg9NCsL/oJBKld
+Tann2JtXa5vzvKXlRNRoFNlcu3CRXfxsVbwh51tiN9S1DlQOMH3VO8/odhk9Ei3b
+4t+/xhKTEpz8O4i6n61Rww23+gkevgXpMOZq6pugngJQB0gDSzaGHQ4j/P84B+m2
+WrqLaqmDOgS3d1K4jzhMmPLnYCUXtXRKKVQ3sbgMsWSp5aXsHgXd9NDLXntZ1Lpa
+359MJCWMirfV+NTOPtHzfIsxsFxmahqQjB3PrkFHnlVS0zWsYR7ATSYfaSatzY3h
+B7GiJDA2B7YAmO3TTCIECCOTpOUAugA+WhxGKIH5L8y6+/ae4fgpkk+vhWcVOPyv
+ZiWfqZL9+Z6dTYTsz9uCjeA+XizCFI91XwRpBUcdW3ldxnoXIX8QJDJ2SNApkK9h
+KPeAIztz6v81ylSkSY1fYfmy7QwWqmCw6tndo2/GuGD/jz0lYfGYSYSbJ8FAXL/+
+Sxshv5E2Oqdth84tmCb275Fut8y4KrH4t2WzW8J27WzvcWHDv8jx/OaWJr8eSdQr
+Qw1o6Bd/CgcOKtY0sSk4cRM4u7llKDZ9UDS3KrVyST9Z1cHIG2kXbeKoLLOpLm5I
+x5P6TU9/t9QDaChtwKjxTs22oWiRu2ZPSggvwHfAU8zxOyDI+PTZdIdpzESWV/7S
+pi6S8y3C0ey/8l9HC6qd7khq/4jt4dtCkIcsZpN/xcNfoe2OItCb0fwGd3xQh0cg
+d7HOEEg4ZIbM4Rw+t4qy4hXj54P/++SN0h1s7PPx8oUBJsOOTDJdmRCE+vxpeAMY
+NkFlpIQd+btxiSpIpa/21qoqHbAL+LiuBph4grHHbuTXqpFyrJl9SMkQSccufHI+
+GZl1Sax8ggS7JVRbP6DlyPAJf0T89mKMnONCtn8FcEJu67SaSd6gO0AKmER4LVmf
+Ydeb6zEwdxIbgbbFfFo8vsTF9Fp1AQnKKhbqW94kKhIPB1Zbe+f9/keNS0E8OaNv
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1CACert.pem
new file mode 100644
index 0000000000..703bf6857a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 21 4B E9 2E 8E 14 78 20 89 D8 37 06 15 99 28 E7 62 26 69 C5
+ friendlyName: inhibitAnyPolicy1 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIBPDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNVBAMT
+FGluaGliaXRBbnlQb2xpY3kxIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA6zBvGZdcVEAf/5tkGFfFnBVSmugm+C88xlCv9nv6QizfRFE9unEgMgC0
+XzUOeYBfsVDD+s8vjLW6l1oYd/8dB8nj7yPL+Zp8tjANb0Pm5Q5IH7tN+a/o81Jh
+sb2bJky9jSiKxaFNhGHZ0uKsGYZn1im5XTmqAshVWF129drcizb7//FSTeAnkjpP
+Qtb0UqQljSTeuXIdDUnWSuUvJHOzlK+wJBBBlxQQU9AFXyPSejLDLHEyVEgweQ2g
+/PrEkxBpCl84BSeXw7hOyeqy8W8DCRlNH4vbi4UESM5nydgHbpi1WJg7XayRsv4L
+YtSa424ueI3H2OG/lfY+6NlBJl1PewIDAQABo4GaMIGXMB8GA1UdIwQYMBaAFOR9
+X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBTYpp4nlxHDjtQZIdcgvJztoXvy
+0zAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgNVHTYBAf8EAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEANF4unXV7d2qUpPtdqy72XTM8e4g9dJGOS9XA1xRPjh4flZE/
+7DPh86LuhfQALvGqlwUcjTY0ZTRq47YKUqj840+y2qyii4QYq/USs3TRqlBZVWYL
+2gKOFDCGWl3MLtlFR4kgRmMpcHRxuE5fDHNdSBR/o9Ri7/9EIOjUA5UWjCYk7ccI
+oHQ3vVkKspFSObgq23zJTsahW7s+mmxbwxDFQVyQ6K4jXOnemBodAIin7KQXSaPq
+SPUOcOFTf0430xU+HZFahy8Oqe9PdAf1yrBiMMG4W59Bly0cJsFdvEgQVDu+h1S4
+gfrQDgV76wl1nblJHH8uFYRFdYG99/Z45bjIVg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 21 4B E9 2E 8E 14 78 20 89 D8 37 06 15 99 28 E7 62 26 69 C5
+ friendlyName: inhibitAnyPolicy1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DB75938147E4A4F2
+
+Z3WFBDKFyqbgqjWLohTujouVk1bgiFIZ7hzfwstNzrrsWOsP3ECfKkvGCwEDZjHD
+EJRKtsxjq1PSsfnF0N4z3xZtVSySPlVBh0sdfps2M4okn5Pbn3KRNk1WXJIbPmLo
+DAzBce+CT3GuMoWcaL+9NONZg1Y2T1vXrss3qOQLh9xrG+r3MGIv6MswlA6YHgdC
+gzSeWKE1KfH3YWSj4N5tPc0DoTiwyr99SuPzQLUm5jSe8a+vQavYWlKjubk7r8Hc
+fQ10jqTZBO5HeSTXgvJtzwSTPuuca4sDuIk1oHtIH4FDuj9IfcPnXiQXeko9PJ97
+NVZYpOVdM/t9GY2ueZcu3sa0UNcLuL5gHMvfufgE7g57kWHmmHBaHbHTB19ah1B+
+drjpT8k4pUnAKhzqnWh9RsfKBlTxhG+cWkJ2orK7dan9U5ksG7pWOv+u907+nsQs
+bzCCkz7a4QDJQMK4LXxMfXWA2cILlQW3ZgEz3i5PZOhfk49Q4SMeZAUIgWKhqRDt
+36Dr6H99S5kQ7ruDtlewCUTJIAwrxefBbs5+3S2IWQJs9U3/AP63+Cf0dkHDWO0P
+yvCE2eN9eOb9rDU/OxaZtBz2vpFmBLNsyArMdQJE/NDQVKiFgmCj7YSY5eGLgmNs
+vKfZ45bcex8XxOPhwvanfymzUqItCx/FJqwgsmllXSQGqAoQ0xl4dVZiBy7vpWCf
+6GbVAUgAqNE07utLyBhzHlB18/FcaK4Q7ruzNl6OdwwEbGaQbanA/eYD9SF9Ih8c
+zD2dFT7i3fWfcr7+7r/49neG4YN2A4b1pAv4m7owKGUSQQstETrVkXCdWL+ll2Fi
+IfSVgm2ymdIYn2bB2C7qYbisF90Jh21lIITufdZCn5iSV5W64rbU9OVZpflpBHUO
+aS7jalgKC+qx0pUskBs/2+PL97kYlYqof/VGOAS/6t8Ub7ux9/ZiAxSJIvwlv7Hs
+GXNtr5XKb7QeEPlWoAxlASXXtZC7X8Ftg/FWO0mnrMEXbiMLbEZNnjBDLIM/4+XC
+BW0d9JuXi1C8wgR5q2gv9Jqj3Gayp289UJq4/AgkoqD6Lg/jA59SomOcqDIMbw2t
+8v4ccuHLG4bswm0QewhLhWujNtHggOfAXI48T/eeL+S63lS1cu21tvt1QTWu6W8f
+T1HX0c1YCjEUTjYMYFWOanbJv8QijdlvavtTpryfj2ZTScggt3ec/R1J9XqcaWwT
+q0Ha7wvb/b1D0UThOfvTbGL7Cp3PUxEQNqx6g/4OjhDJ9Rv2WafBXYtGfns8bf92
+46J64XbcBO9dfraOa089cdTG0S0IUk5QlcJpAOH83bfcCv9ANFUOeCKxG5r2ra7W
+hAJW5f8zCooh/U6n3AC+TV+b09F97O9PZhyyXabHFWKlrHVU9/kXAPOvF75ASi0R
+nD8SZ6m9S4UIGl3TRPl3v/qY6Qp/0r5y3Nr9Q5puk45HwZNO7AWDutGEjWT8+QCx
+N/UbMSuP8jnAyuu1YMRBl7LFcGf6381RN1vN7VpyBJQrcrpg9o7iC0GKQKJ/Qn5H
+Vw7pjZC5h5OnCI2cCPYs+rME8OK1o2yqiHv9i+25IagJ0/Mq1dMz/4ASIeyTH1br
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedCACert.pem
new file mode 100644
index 0000000000..c62b540462
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 37 FF 72 28 A4 A4 54 C6 7C C4 ED 25 4E E0 46 75 40 3A 4C 2D
+ friendlyName: inhibitAnyPolicy1 Self-Issued CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 CA
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBN
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEd
+MBsGA1UEAxMUaW5oaWJpdEFueVBvbGljeTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDCFu0fJxTpvoal9t+mW/X3OsIz61KWZdMukGwyZ2qGnOVp
+JtzZowwep2J/vOZyyAS3eCLJ+DE5rtrCUFnlkYbD0aRM5Ov3LQv6/wVeASJ2peE1
+ktUPdTn+O2smk0gkTqrE0wQCB3VqkpoeU6MGkfVRi5cmuuX9yH9DrfNDqBt0v0qN
+k6RV1Qatllw9vMcmzPSFw5QtF+siYKvh0Y9ZxR4LpleoNgNu0WDEiGSObwOcWaqn
+kdtki0sDY2Rrh7l7P7AmNILg2SPd/U/999Eq4U9s0qDbWRm6JieFQk56kSTqzSFs
+VqNknWKkDddew/YGC3HgkMGDlZqGXjqCOdYNjylZAgMBAAGjfDB6MB8GA1UdIwQY
+MBaAFNimnieXEcOO1Bkh1yC8nO2he/LTMB0GA1UdDgQWBBRAqcjvsmE0lURsYYYC
+qQ/mQa5fxjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYPM2xLE6+X6y4j
+OiVLbySiZbkfMcMa+/9NQGIq0PAn88BGxaX13t5xfcGnUSkRJ5cBJN8HIEOnSXi0
+8SzRDMOIlMsBfsOLWPrrw3WAmRI6kAbqAjgwYyfvVJaAXD3UotQHsBSbuE9wOo5D
+HCZmSB7GAscnCMZwjz0ZVfu9Efpldi4PmoTC0Z6URop6n4N7w4IviZlSfadQP0O+
+CTZQHt/D0HRiGgF+DiQ/4mSWgP5wBlhhUJE0pwVLCd92PfMIqsK5cSgN+ILMjlX/
+rKeu95Jro38CL9eXpEPnkECq30jAMZcBqAigQ4GN5sAw0nT9Oly+GjV1P8Bu06zg
+hTJyzDE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 37 FF 72 28 A4 A4 54 C6 7C C4 ED 25 4E E0 46 75 40 3A 4C 2D
+ friendlyName: inhibitAnyPolicy1 Self-Issued CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,918EEB1F8B4EFAC7
+
+oGaJS8rWm37/xZ17HHrKZ5LitHkYuoxGmrHu0a+rruw02od9ZJcHZgC1BS0jV/Gl
+ne4SVHOa2rCyPiM1G4PKwXzK7rxRbXMuNoIv7cCS9lRUy4Nr8AiH0YkUL7+n5m1C
+ExgEe6DhLmtGoJx/M8ZHf/pDRmRuhPBu9HLrgyX251U8dCj44o9l0OJpsVQVGqvb
+Vz1yQrLyLbtB1NH86N1Y6+SVc7e1AeuOndKJ+Gt6R+G70IcYW2klwnnK6JECsaZU
+iy/SR3bT5oC78E748znrgYsFvO3BzJwr5W8qtpM0zkhOemdzUh9Dt2NfyLvOBft6
+n/IkGSvapYFz5eVU5nCSRfGBVO4+tHwUCYbt6wUD/JsJ2njfKaQyZaHhy7xxQTM8
+N0f79GCqKkBLhUNDrNc3VQYiyeYou5PXGiDOm7vkxVXR8mbroK2hBhbV1IxFUJ08
++g4pmfVhPjxFSakz5t4hkukjR+3ihaTRSqveSbRJlDIDBiBreHWphrJN5DVccN2S
+TU+TrHsFFCvuUSgKwhNWuTv0WDoIs6S0XmhL03bB76Dhvqi/9QOQAB+7Ybhw5D0J
+nxzul5/K3nM73TuEz8aRZ74u9+RWVyb66MF0Ou0iFcKvs8UDyz6TDAlRw+1UJ5n9
+o0kBi9e3OUtInP74xxSyhG3hN3lspXwaMvnY3rbEMh0RSHyY0GskA4IBY7+oeyBD
+Yvu0LLkiTE3KOySs/6t62rDIHxXLD+5VB3MiMIWvhwpqtEJNdgn/+Z7p5yEmkqFg
+ijdVdBXm+oiBIEowp7XEiQENQlt+iUhoumeLtDwFwENryAe4tKUG60ILtXpmrftW
+JFtpShfsm/PHaTLIBSgjNn/u+ZYZ16phL80NLOuhl9hO5qJi+dKVqsfInZ1qjtiz
+MmaimZHZMCNvhzTugAofPV/kO2LAA5vQBsqfi+uz9WVaQgYPCGPKnYpwewtc6yRH
+0L0s+0JHCaXxWG7w4wWEky4r080D3dyCwymkXDdfSOBoBL2vC2JvjAnpuZ5GAjw1
+66/vNVzWoRs/AsuPsi70iSMCTuvB4u4fsVBQjjNNQq5sAiN0XrrCOCDr45AW7MQB
+O1UiAnuJEDSYl0HophsHa99f5aTRQrAlfOUXMl6GpNK24IRY5JOW6fGsfe00DCLx
+lIeQIjG2ittUvZWxOBZtDg5x3fDZd6z6EV0sMqpzXnupikNUIRtu+COjeGqFJXTj
+4UDLE6+iYM4iZjL47Q0JbDrdE3FB640U14iznX1l01Z6W6pZP3XA4cYQTNniUZnn
+9/brVg7ACOrjmy1lCpUPiwR3/zdkEi4eF5VogIPrr1YL490WTamUajo+pOgOgBPo
+pXlMt2EJiABERHi4/RP73TNsCHqxnJ+ojTzzEL8Ykjc9tEdL5AXF88fE5NcWQAOH
+Rk4W7bAb22jXmSlRGzz36jaHGumCw8/0oUUp2qLm33Y3j9sJuSakPS/OdjYk+xcZ
++3GtDmW4QrskO97aS0rUFPUp2wxrnRVQQ2PzZK9EusTF+f6nq8u++JHYuoRd9ehG
+Ivpa7IOCQ6ZHSbN4lb3B6L033j1JAeaWHYeleS5jlfyJikt6f9R8Cg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedsubCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedsubCA2Cert.pem
new file mode 100644
index 0000000000..6eaff0ca8e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1SelfIssuedsubCA2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 4A EE B1 77 48 F2 22 52 86 52 94 58 C1 A5 3C 27 74 F7 A4 38
+ friendlyName: inhibitAnyPolicy1 Self-Issued subCA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBAzANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowUTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kxIHN1YkNBMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJJAVofrVfHs45uXKz4PgJkRHsgL1Z4e2sxf
+Y2DoqXS9SaYI6WIGl8UaUaWu2GdEw8ogTo3JUrJI3fbDBRJs+aGFvBTaTjH9QuL8
+EKXDHoMMTUpRy183wS6wbZKKHS42CxjBHR4zMmLhnCkFo7IEC2CsgxCTzUO9F8Dn
+aWQ2LuoTTjD6O8POnTLawoqcioqQzvpGY/kYItrYGq43lSA4zaxToHFWrRSqmMhT
+kjqGhAPpjemoUtPKhBfcMw5HSTP1ZWJUUZfXlH3OCuKzi7+dk//7JVzmPGSIP0RZ
+KYY1bj3XjSS0/0VlbJBG8tOhAZT2DKvzMIPpvCMDJeEW45bBNYsCAwEAAaN2MHQw
+HwYDVR0jBBgwFoAUjAXc335k22K+20tRZIxqZthco6MwHQYDVR0OBBYEFMnMP/pb
+8KHa1TcMm86YxnqJK9XrMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsFAAOCAQEA1S7dJczr1Qzl
+zL9tXuePIeWIEW+U0V7V3IAMJEy4eo1B7v5uHSdxCf+4syTypdB6rbNUmoK1cRp1
+ChDyuQ4Yeiqj15HVD/anZ1Jo3zKnfr8KklVPEgiotUTSAV78aYJ1liCaZOBPK2n8
+voSX0antIGJLILX/FxJWijpjOERnYpD+wQSWBcSifo2XYXplE/gD/HqyaVjGl1ec
+Kh2j4bf4WS6P/QsW1h95SfOK9j7atKevgqWKY0lGePS89NoIyQHfhrXY25v4nwRM
+iGB8d1zjzlpOVskFlrvlJu9TW+qQPsA3ZLiRBQZj1CEhU1n5x0e94K7LzEKL0759
+xhV1ZzxcqA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4A EE B1 77 48 F2 22 52 86 52 94 58 C1 A5 3C 27 74 F7 A4 38
+ friendlyName: inhibitAnyPolicy1 Self-Issued subCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8122364D328014CA
+
+LQtuX+3U/P3IUUgPuyr2SuBmTlllXHGcMt1y714GJXUyeyeOpyiRP9le4UcLZ5SB
+5BS4X2exCL7dFEFQ+3eE11lJe4wkXq9NVErAV0zkhBwrDt4Azs+8iyqB6b/g5HHI
+keZRFyUsCs1Iyd0hRLnlgL5klY/MznhVQTwIHA1808xOMVn4vAdM00Iz5eKXSkf0
+d9iq1l1VUHhQo0dwe125ATBRJnCrGlFJGl+gsMMYcvi2SIaH4WFtYC/CKxhNi4Fm
+gKUrie6ar7pEZm8SUbHrP8HJTWIbGxY2F3T9gkzbQGqnS0I8derDtSIHxN7hzB/u
+vZmYU6p0Z8Q/mMKby8m/yDp3i9uej19PtyGc+Ao9fpe5QnAW5CaSNluSYNxU9Ob2
+3hIIvrXtKH/Su0UyX5iwuLymKEwHAaVRUU4dTdXLp7qQ9MZJ/uazYzQb3XMxX43o
+1oWrsaksAufYgvAzIIqNyGwyYfpwQCt4ejoTL5WNcp+2m0HTXGaKmvrUmKl3gARK
+gVsOFtx9aR0LIHTaDlFZ9GFseznNahcTR5abbaMO2VaXt29Z0ZuhdVUUstw7M7PC
+OLCClRYVNYjORkML3Xot7xFcmkhYoeoodZNXU9mX7P4YcHS0HDzBFRvahDzNqc/C
+XPTS7IBgMB6qeks9+p97IzsULZcLfa2947CYnlLSRDl+MDxak16Z0b+abYoLLv9p
+qcmTZvkYZs5PjOXL1cKc8cCRcZtn6s0prCCB5vtgvFBKzr6165jjlZDF7uwUXI6W
+zmLFGepTLtUU1ew1GLjr8kdlUmGgqGMwhJzphwRVk90CXKV+yiIGe20Jq3GLhG7P
+5ABuL0GMcKD8/Wa8kcZaUAeI8KXLMHFc5QBHmlRI1lLJr+/qOgTgItijAuvuNO3G
+dBavsTIKDQxfiMuTNeLq4UUbBdSGr27DhnXl6HycBNyVuPcFNsq66ez1aX3fFKOg
+AFMGd5GTE7+eqLfRwFbM0hp2feFV49BLX3ZH4bEnRsMCF2bbZd5DQcnMvjZJjNor
+sMx9M139lg15V2SKUcXPPQu5bLP0dH8b9OyFL/UZlLtRFkftsmAlvyIxdNTnbCdH
+xwWYyY4bVyvp6pMB5jXvFeAigBdMPTSAdRp3k/yfTvsSSoucV66eJYbNI9OGrEdS
+Zff/6pvh1aC0BxOzfNn2/aR5wo85aNqgHyQ/mY0KzNikfCMXtuCCYs8+Epz/D+PS
+Jc9kUwAP5e7B9UcfL6pcE35TJrE1v3wObSEx6gVwwDhuUNg+5hHCBjHYc1T8qNaV
+B98EaeBJy0qPcLMQCidJ9E9QOq4KRj+wt2jwP2APs6befH7JIEh2udsBK9tpbE4+
+HnkdqKCvzJSgxQ2UuitYWLFJRwA+md8hvgQLDLzHShAf7k2CRAxJDkp+ZFhIhO7L
+pz7epbwqsKcU98I7DTOwBEdnnjkDByLlDnW43HruJjLmFDjnJoklSFcDXTsj6P8l
+/ydsm4wjnVXLESpWWWRwQycBoU+Y+NINIpyYvGXgPZXQd1qYdTk+9+Z4NlWrMPNV
+VnfCkJ3JMLzxH3VIN3sKYti3CxLa0ef+8l2OpoG4HPVOJcd421ggJA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA1Cert.pem
new file mode 100644
index 0000000000..fe94f13218
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA1Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E0 F0 D8 A3 FD CF D9 7E 99 72 58 2B B2 4F 3A 52 1D 75 05 AE
+ friendlyName: inhibitAnyPolicy1 subCA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA1
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 CA
+-----BEGIN CERTIFICATE-----
+MIIDjzCCAnegAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBR
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEh
+MB8GA1UEAxMYaW5oaWJpdEFueVBvbGljeTEgc3ViQ0ExMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAyVwAGmULZXHVZpOzaNmYz6rXZSAplQb+QtuN41pU
+qvxd3RpiryOIZXMfSyamdM0tvo5Vfngen/IjnrYpWfPGBh8oZtUI26TXLYpaGTGv
+9bXynCNNRcLzlmufhCFvgipDcQlCB9KFBgBFX0MXSOgf4MviSOncnVm3vIvrUR9/
+xUGRmxLMb3FJyiY7MBoGAUxbsyEVA/sjn2RquDHLBu83hCnkCX0WuSwyz1rQ1KT0
+kOauGVz0Zxj+wFwpSz4jTdazBXgDEjFwqptRoivzyXz4jwldMEB75XyjIMV5yObu
+Lvore59mbwDtqsSaOsTqjXXlqW0F17DORMSaYT/CHRugGQIDAQABo3YwdDAfBgNV
+HSMEGDAWgBTYpp4nlxHDjtQZIdcgvJztoXvy0zAdBgNVHQ4EFgQUdKDVWNkrU9Ir
+sM1dccahv0OnyBUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wEQYD
+VR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBCwUAA4IBAQBnzM+7R73vitIVn6v1
+RdMLwiGv+PRyshDNyrzeAIGRmQxSto06y93imt4X1l0WuwymoO3pkRJP34x7hqwB
+PZfufX56zLc/TndMmLNRrjUgmQZV5MdADqMQwMWM8TjxLlqhKD9CAb7Su6PlsJFx
+eosv8QTJti2dBLAGrmMoqnf8om/yqBE1Ix31rwhB8WhSvYd7LkMdlJWW5Eu3IqOj
+OGbIa4lm24r/g7mSktFTrZMa9uCjaFhdMl91qmHjuMVm/8Ze0STx18SyUse0qBre
+Hizk6JC/+JHciyBn/+ioqYagRGyfCcIlqw0hSH4ebejtEt+tZHvUWN5lmjkzSVnR
+6kIb
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E0 F0 D8 A3 FD CF D9 7E 99 72 58 2B B2 4F 3A 52 1D 75 05 AE
+ friendlyName: inhibitAnyPolicy1 subCA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E4FB2A364F203A2F
+
+95C99Fi2QIM2E8JetfoTzl+R7ZX1JIjfkd3pWbBXPzXOEySE+iocCjhW1zlHeoxP
+51diy38WCmY6n0LAOwTNMVZ+819Icx3+FsTS7hbutnDrK7KyqWWG7eYNHJwQJWi8
+/iJPPU7O4gnhNjaejdFfeMvAy27WnSjXH5289l8TsCwcOMbT2sVxo9ldkMKQQr0x
+CYjaz02SFIBUPMFkBelw5kcS6GJPBPpNaK8pbeENM7dZ9R4UCtdvlkENuFwybDjW
+XMm61NmMO5yclB4hYCOBVkXmB6rzmzUTPbGiaKJER73Pkq8RqaEr8+h7erdVF9PI
+NtHgbRldyGPmS3bqDkHydEjshMw6RQo9xTrRZNDjC1eO0lUtpHB+HzBW2NBWaHpD
+E9g/4SSjiuPpnWSdJ3ChGrurHbeYcfyy9GRLSyrdaZLTj+wIMnzadCSRrfgMvPE6
++yncM3ykAsx9i5rmyU/P9qkCOCFXg0HIHDXMqJH8aKRcW7+niFcPgy2ZK+yf0nG+
+szboU3RlNjY/SIT3RhXchH9C3lq5GlDbxB6RozdmA3ddWZ6Lqhanr69MgFS75rzP
+YrjaDGOCs5rlebCOXN9TNjRYLqQNuXidEGjkrcsSPhCdRCacybSCnYM1j9hrh5EX
+m2f+6cq3OLPMeX/NzMwd3OGWyI69EIJTVuW0cP8vQ2iSTaX+0PQKb5XIegUprxQm
+ruvlHxYC3bhy4QEHXaUGrBLFCaK7xlzbQlu8tObPeLRhNi2i8F2F8n3naAAZbHVZ
+e+ryrERooWyfpciISPHWLycZI5ClJkVmyVlX6d8SR5yYqProCQeJuTAWWKZz4nm3
+aAwPkx6QjqnXQVUUESqgdDfP3PuMfJIHwvAXS4TaGL6h3C3KWdKE7HlAg7CysmLW
+joxgx5Sc/7uvH9MO1W7Si8UilCtXuFn0mMuENtIGcqVPnjiW8lpsaNQZTcM7KDHi
+f+t/WqGQvdr+PIFxofZhG2UzWgA5G9mS7oTw9HfUbz5x7kyl0GiBJYBPBkrRxNQ+
+i8glrtJMm0yzIFiOxuib9FdQukSLQfoE64uor+y93enIUTt7mHnIE6kDxYM/aZCI
+QldpT3XkvSc+gGYvkTKANjnKryLYphAIsbo5pN1dBPktXWV5qZobJZQU4W2z1nwi
+adOcL5bFE70LQMiIbnqUrIgWtTNq/8cfRD72uNXMv2f6zeiIlZxqF4VBVax228Kn
+vPxBseT3/a/K3vJid6vTFeKEiQg72TzAG/JAWDjb2THNeHk7WttfVtr+8KI/cedr
+0hchRq862PkeHwkAD0ULP7fc5SmFvn6qWpREVaaaETl/g1UlKbNA17YGm9q8o3N9
+ZW9kRGXRFMa0cJKuflwUEKJxQO7LtHVurzpfE4Zca3dG9zBpbNBek8moTWeW7SEK
+ZeDd1JmPMjGGB+X4lhtMyIgyf3g2uKpotpkwqEJ+hR8Uvk5MbX8vRFhomoQLCa2f
+H2IahW8nWJTMKcaiLwruAXfMmLx649+P592cjN6LscUcCCLeAz8CEkkWh/3mxILG
+hE8EFhQuT02s8zXAzOfxrphDKV8z5NCzdKDUJooxx8PB4DXyKz9QjSYQxtlQ4lai
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA2Cert.pem
new file mode 100644
index 0000000000..74a91c3f79
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCA2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5B 48 A7 D1 4B 42 C2 55 95 98 67 40 A0 09 D7 6F 04 57 C4 2B
+ friendlyName: inhibitAnyPolicy1 subCA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 CA
+-----BEGIN CERTIFICATE-----
+MIIDjzCCAnegAwIBAgIBBDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBR
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEh
+MB8GA1UEAxMYaW5oaWJpdEFueVBvbGljeTEgc3ViQ0EyMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA1wKZbiE/ysToa9HAVzFhiFhUj8zx2fLR4Sx+Yk5p
+0N2lfDWP91hTtP6CamBOzUIRH8s14bRvcAJfwdepbzDw/SzH2gi9D3qlGA5H6Sba
+29u5CHN1fvHcHkBh2uaA0r1tGUgI5B9OG3/kGvzWN4kU5AY3zsZrsxASmbyzUtbb
+GPQGf+UFrzFVnTzSTo5bfhJI+J3KQOe6TpusxlnUsKbEMEAItF1IqIKl/9LskeD4
+Nb5Rr9BjPe73Q5mGqtd9wV0gZNMa2wpnN2mJtdpJc9E4c459Svdr0ud/Lx9CMm2t
+4TvBjaDnhemVQ5PnjTUtIWsX+bvLmLMyUpPSPmJJNfx0EQIDAQABo3YwdDAfBgNV
+HSMEGDAWgBRAqcjvsmE0lURsYYYCqQ/mQa5fxjAdBgNVHQ4EFgQUjAXc335k22K+
+20tRZIxqZthco6MwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wEQYD
+VR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBCwUAA4IBAQBVZuMq6323Ai0EJicg
+9wk4pPvFWNdG8kkAEr6jA6lrr/h/iKt1WbQnRRMHNMjfQa11Du0EiQpdrb+lHmb5
+PwXAcBBXJf5L6Kb59tR/bvnEbXWi4GwQeVlPMmyytl2Ry5h0GahTtCPdFL0VBD8L
+4w7GUL3KTjJp4/rOm42Dnk8/RlpYwia6Ynoup7xOKOYJR0f4ooIYmQs4eA9eMSdj
+VVVViwHZqTzshR2D9peuGRj18go3tVJj0j2rrsC4WJ1fVhlpO4UGmZZvh2MO8UJI
+U8NSOizyKZu+RvVHr0vXJJCkmShqYKTpbg4mrRGY5VjvEwSZU4wN00zZ7gNd5O/v
+vKwW
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5B 48 A7 D1 4B 42 C2 55 95 98 67 40 A0 09 D7 6F 04 57 C4 2B
+ friendlyName: inhibitAnyPolicy1 subCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2FAD26B357CA72C5
+
+cDt9ugky/xNhuX7W8o9Fila+e7LFBGDp+9fwWvyK9vQClwEXPBYh/uA54gML9jXl
+jF7pyn7UKQTts4nt3ziHRAdaihLTfYgdvYGc4++a2fiA8oKEuOpNGnzr0YRRat4Q
+eKiwR3fGdcRnf3+YF/CasA2n7wUGXWJK3r7GvQTQP5WhcehUqOd7eI/k9cTJuzN3
+WlVCoPh9aBwfa7Njtja8RuR4iBYf5mSPjHaJqWkvPEedAvi//W33npr2HJQ3n2nS
+HfWnahsyjhiBgIInAEpaIE8C8z2icXKsz6zR8HxuxEwMeg4ewKpQRYFosOSkYosD
+cLiMtoYXzZl6c6/az2fmjzeSBOBPAcYuOXaaXu7ySiirf2tbVKmADQEZFhqjx9Ag
+ZimsIp1FYYKWSJBAhn4doteyVsabVJocDBuR0feHHg6woUZ8cKlU4NzQjrc7ywQh
+nPrNCg9R+eC96ckJCAVHXYpnmcPzcdZE8ETobw1eC4yIvD8qNaUWRK164MiA3i0B
+u+vEz47ryQ0AkYdhKQ/9Kfcc5IWXsnBvK06XKsIEqXPgShrU7nGdM9FhySsofv7c
+e4yyqem6pT3h2Qq6KyAWmZeFPVTQibo0XzFkIS9zLtD2Qa+zpZNGPtoswLX8300H
+wfYGD3NnejCDMmTpV9iZgJYpVSYeXPTF+Xc0tsYTLN1HZDu1jen7L3+L4yIqEAce
+c/PILr8e4jTRRZzreFFb3tf9bPOY7+7a6iQ+MH0LLYzjHGNyegPeYEtup7y4fVDS
+VOlVRDGRR17a+m2whys0Z7m0OAFcl8/t/anxOgzSD5Cxr2a+DDcdNsh8tGzZGXao
+WXAyqHhulk2VdhN9JZKY585xAW1aEhGksDt0Y7whn1s9XUItFgjcfahYkbV1eflm
+r+tSoZhVfJTibUm3wdDLRS1UhjInD8fuhCXtU8+1x/0l4Z5yI/4d5f3y5DQwtt4B
+JjXYVjkHLFHJqUojPlwKYFHIJCom5U/LvAtsIVZTbmcRhSKtqwQ4sfRy6jrJuNsA
+U9ww9OYxuc68t1CY6d7isazh34zLFb9r3Sgn7NLE5xAykPJAXhoJHtb7QxG2Xr9I
+AmL9hPKDsiXVy7h3drX5f6ItYzgg7xeGjrPeZbaGJeiTzfII1E0z9TIHzgjg67QW
+fjnkEnaB9+/H7OE15ddmzexcA5CEEIdNfaQhqac6TsMsZjZySyW78/3t+UabqTpJ
+0r2mps+zySOE8Zt3NZHepP8hTKfnKyikW/NX1oG5Sec+vvVbxSACzyhts2b+AjHE
+bNGbC9qa4XMIFMqU3u0qNTR/8Qp+BMMs7DTy2aSCvln0nVdH/VCu2B5FSliHX2rg
+OsYIfkKoJlzcRx6SktcWOZWzLW3EmbxyYbC7XY2O++9u9BrrXQc7Ny3m8ThCR2Al
+eli3faY6lHbApqbO8luxAAyvaG1rqRFlxL6HyreAGQaEM7SJUAEldARzKBvpzfFu
++pdVy2NMzZLhGaB3Ij2zVezNAzuXw6rlp4tN9wSINwjkMAqaYpZYQaDBicVi/h7b
+7IYKM/cBJmP2j6miyioIFtwrVaKASeiXJ8k3kSkXpJaEbGY657dHaQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCAIAP5Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCAIAP5Cert.pem
new file mode 100644
index 0000000000..74681c18c7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subCAIAP5Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5D B6 24 15 CA F1 97 28 65 ED 33 7F 27 F8 44 EF FB 75 51 86
+ friendlyName: inhibitAnyPolicy1 subCAIAP5 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCAIAP5
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 CA
+-----BEGIN CERTIFICATE-----
+MIIDqTCCApGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTEgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBU
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEk
+MCIGA1UEAxMbaW5oaWJpdEFueVBvbGljeTEgc3ViQ0FJQVA1MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu10Q/7dllIbdDlDoQXjb6LbdUZq9K1NJUZUZ
+KxTwF+JnWroxFkmUtCYP/6sxI/yLWrD4uDuVWDx2bYZ1lGqdrBucimlvpUWAqJmu
+jrChxpNXfzSBs/9uSsp9S5Y9ZCU7+lSVoQ0FPM1i1qaVC23crOxcKyVDwnotJHPi
+eL4fU9zLnw2LZr3gcF5wn9cH1qXGYc4HKXm6MaL2P+RdtZORjBX4/zzbidsar91N
+z18nDm8ittPS5oMPDGA7Et3pSp+6IrDn/r6kuGaLYrJ89BZ2rV/jQ4krDZiSPtE+
+sjcZacvGu2P9WXv3ZY6tqo+125T1NzHPDNLiBcdnT/bLW24C9QIDAQABo4GMMIGJ
+MB8GA1UdIwQYMBaAFNimnieXEcOO1Bkh1yC8nO2he/LTMB0GA1UdDgQWBBSJBFR0
+BmCz9wBuoGGOFfu+UgIGJjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYDVR02AQH/BAMCAQUwDQYJKoZI
+hvcNAQELBQADggEBACLLLvFs4MAJ9pQg70MPbjrrz/lZnHWNu6ew1q6O7/Nug+wP
+UdwFdbKnSAkX4rXjLyu4tvqH4akkwsn4QKSIpOQlaghbHLK+WL8ITUHzQv+m2Iv4
+F02wWIIxaGYdD3bEIm3qMHRHoO4cfQz6GY2an4vjvik1a0sKM56es9XM8M+U6y3v
+qKVudZb7p9xbGMjNwnPaBIpXwXS2XJaT2X3YZBpTBlhXrpAFc886TwvS5LqEzdLX
+6WTi5NhJN0Y2yjoffRgrkQr5C+2Nd9pkcVHR+T5yQ9NTzJa3lgKfDY1ZJXTAQZjP
+vXG5L02klQs1z5rrMPmQwXhZqgi2HelFaleZXrI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5D B6 24 15 CA F1 97 28 65 ED 33 7F 27 F8 44 EF FB 75 51 86
+ friendlyName: inhibitAnyPolicy1 subCAIAP5 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2C62EF1BEE692234
+
+1pKDUi+tgaTyTBuYMwYHv4ZPmXS0i0HADwI3gEnNNkFu4Xi33MZ0fmWp0fZgoAMd
+7OjUMbFaDw30qxjxMR9iBwyieXWslpJ575lw0SgH1LBvOYhHXbfa5YmHyjMdKZsh
+SZLp4iEf6Wc0oaHmD7ZQjeSD7H3JWSdAntOrYcm183f8FIrjBWUPkgCEtntrZcFV
+Li053M6GgGFSndfl2a745iKlX65ioscCL8MhWB71yWlvqBm0p+56Im4TM8DI6pC1
+WpkqAc7rbWVQSy6NjCsk6u3m2E2Lc25vobTe3gMi4I3XSTA6MCVhLhZG6MnpaxFh
+yNW31iztQM6My1eJqiTmFjXrGSFHGG2T5E590eEmEzjfNfcYmc9Qvy9g4+awMPqU
+hOnZiocMOFfz4Wly66xqBqL7UwruOjSjSwU5VhTKjbxNsZ2umaiYFzGj8Zl1oLDu
+sKz9VJDI2oeOGBRF2aAc+8WTimis69EvQDdXyapoa2tg4x0QIzQm2e/Wa/egCwsX
+jQmnnKAbs+vEzRd68JtmzWQpwl9vXomAwQShIaWdEwfbJrXXGWRtwNvhM1N75cu8
+wM5EFkYa2787zNPWopK6eRn+FfddY9a+yrNGpke+yyn5lKTTLTT9LeGxRruexuuo
+Xg7izOryaFTAozdZF7PsghC8DnqJ8nqc85Qg6ynQD9noF5o9uiD6XIYGCGYTHAp5
+MpakmnEBMI4XnOTAOrOBUeBG4neAW5ZIDbh6wSdmQVomv4STunSBajlCX2RkaeaB
+1coGMdqLnjijz5o/1FRr2TdXemmmczEZkNLlj5SSBOADPENPJ2c01+nRf+HHCx8N
+avej9VfhulWHSCTIN3ZWMjnw+OwBPyAvpUybxfnDk453+ztV6+8JasGwqSGMc6gZ
+OwqNlpkA5gSY9Anf/DVhftG2AZ0PBTzXySyP/6qp2aWXQF7m/GHsY1/eApAS92cr
+FY5W84Yhb9QRNxfd6fMYJuoJz47Hyo4PyC50YoccjNd59M1i2myp7FVMrHW5cVVI
+7RY8kdKkKMvuLm/gv70O2yDn95PS4KzRR3Y0ldDW4SUuQm8b+AlnV8ypm3rCQWvK
+wRT/h1DrBL3pg796rcMrkgcf+ETYL6RNKPYnV/lzAxmSUlmjtltV510KUnsjxiG8
+4T/eSBx44DI/sr/ZfVUD/L7NZzJ5KFwr9UwfVW77ECh4j6sNjX3WzVdclGI/3GTz
+qE9qDUO2Y6RCo6LqXS0MNRDNzOBxEqCR1vZoxkYPdLZK4oggljvmhGDmzzXxewQ3
+CAd/BkRNzrjOZw/b/UQIy9cPSjvE53lHjHLfxn1z/EW3J2pFVcx0Zmp6kNQe5ppz
+3fZRtGnfSvb2boge2bhthzk83W3A9V3qoxdP7N43fKgwC9H6lG0f2OLVKcrHt3Bk
+dyCriKSVz5e05mp17hapYL8VMyhgirzvFNknnL2+1b+VbZnjNLHGyeUgCqpl+cuA
+jAHv0JnYa9vSGR/CQvl/V+fhMAtzp5Fnd6ja0i9uteMN2RYcIbczio08vVW6Jyf7
+J1xEDjHVywFltxb1zd4lz6rKJuKFaWtFbeThzgWHsFDKVkB5CBD7zlmfDgfGuSGJ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subsubCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subsubCA2Cert.pem
new file mode 100644
index 0000000000..cda31665aa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy1subsubCA2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 49 FA 41 24 8C 26 A8 F6 EC 22 DB 2C FB 19 9E FA 0A C7 E1 01
+ friendlyName: inhibitAnyPolicy1 subsubCA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subsubCA2
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA2
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0EyMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowVDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExJDAiBgNVBAMTG2luaGliaXRBbnlQb2xpY3kxIHN1YnN1YkNBMjCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALAa5di9sE6N1APDJcqBi166iOEyhdim
+UOR8WmLQQF+zANUCiwfgGLuTDU5DASaua8OodRLbdULKgYFqfOfFFaf1PXckA2OG
+sCJx2W9LiMihDPFke5F36LTsoQ3FQ0D+ivyr6MhzyeaKnMIQ5+lZnzd5KLTYm8UM
+FTMc3KeKwqj99doaZ2bkCF4YtdjacJwV88+7Qx2BHFYX/KKmM0V5ATMv2TAT7Hqh
+2zA316mUcmMBXau3bYheXZMxvZsgUYic+FB1RUgWIu+lRUqFw5l0RnpbUvJR5dBq
+78wtY39pQnROCm0q+/sOOWDGsaDxye4inrH6i5FX/kjJcgKDvX1GsHMCAwEAAaN2
+MHQwHwYDVR0jBBgwFoAUjAXc335k22K+20tRZIxqZthco6MwHQYDVR0OBBYEFBF9
+wJyKdvlJM/ekgUuOMHWVO+iIMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsFAAOCAQEAs63PsCAJ
+QfGsdCQ8SSViQpUxIIHmogbN4xTMfYk880Kjepk6FEXM2q3L89XKpi2oZiNxjfvN
+YAZDSuLSVtfli9auc7RTtF+RXz5Pjs5U4htAHFz2JAf8nrAQ4sRBc7q8wwINGjRB
+FSRHQUD275u4CYLsXf7dMy/m5Pe5FjQ8EdzuStshwoCTe2cSKv4r/YGqkBiatt4i
+lsjfcs+sQDyZcQd2G9U2hGe+/uF4VXXOYq87ARie8osBUiVfDnRSdeTfTdLq8MB3
+WYR7gQlA/OiTjvgyeKPYnM7RmKKCcYy3ZdXmsMnT9s1Zaqvw2Zh6xan4sWGbQRs0
+mBDueMYtypQa3g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 49 FA 41 24 8C 26 A8 F6 EC 22 DB 2C FB 19 9E FA 0A C7 E1 01
+ friendlyName: inhibitAnyPolicy1 subsubCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2D7D9604BF088637
+
+L5POqQ6HbRXYgvSKp7SaVLs/tX7tzoXcZjON4dq2tMZFtExF4gNdEduC7k5bRQPz
+sJKQ1iQivuSgDR9uyXODE8xpTRE0HBp2P1QahiO5XTdL/UNEsTfgsbrU0fI9yK4s
+wf79PNe/nu52sy7oiDTZGdycmqZdVfOs5i+KS/xfFHA4wkdpsQazzEK9fhINypou
+lZnhZp1hMO6bzlKhvY/XyW0YM4kj3Sr3cByeIka5NgvzLPw1u5AGpt/XxG/ApoZ5
+YLH17xVzk5tf5OhjyeFzh2fKaYeeHd4hBI8z+NvtSj6HhzMY/PUxxN60jLpgPxCi
+jxEwG+sGlWdr6oTCguXIyEbl5IFqGnRnazyLxpmZ3Y3T3jODLUqy9+qBh3THQKp3
+hUoH+XZikz/cvFTcJi4jKEj8roqUB2q2A1o/nz0Yw/nkwK1JmNedVPaRPvw6QJst
+Gg6+nNCwift+LFVTYFW97n8KOq7IfA7pPWkghW0uIhLHZNu5RoS7KLS3W2zWd+E8
+1oSfXaFwalJn+958OPxjcgdREMPVx629UhN5OqCWE2b5jIslOp0+AXV17tb0gBnW
+fjz3oDC32f9aY2Ljef0cJzEGazujrLsGlQM4ZAXmyQHflnVbJXqhld4XacCiCo7G
+lqtXirsLFLq72bK/3qXOX+6OpPmBcQOwDJbv0lLB37cbChzXVIjwixrb1w0XfqAh
+tLwxIEPAgWLi6dU/+A3QPtgVukHD1Jl22dgbFtrVEoCdK+IwyZIX14dOQUF7u2mQ
+90V7HtDrg9xx4Tk980yeWPfFCFEFt98B0HuPEDlY8hyhC4f61oZ8qnXS52Dnomjp
+2068Y06NDpoyAgSqZKt2O6+rX4+G3USWA2vjVDKZM4P45s0r7oMcKEGneFXT6rLs
+PENq2u5ATjWi7cQO9zdoEBw3gCeMHKACraX/8F2h/lXJhWrA3PmvBqgREYHqhpZ5
+7ozLfA83DRlNb1cEZEPdIKWCZ0Bmq/GSkcCYzWF3h+zs6Jc5J3t/KNTBZGeHGnSw
+WoiONiqKvDDFw2sK0djBfgYuHEmuabnB15jjjTGGH/LKZHA1XNrXuEYA+C6wZEiO
+5Ugu1/gmUD6LvjOwkPjp0OhOG0+KFZ859RDDKtw9grHWq02oxn19/INQqq/FnX2S
+gZpjkvCkmVzeqPhV7DBhaW9qTNDh12L6Wo0/rDzhPvERcnHcneesrudrUkpkguMr
+XJ/ILHvBEHbKEIliy+ZCrqtIunMGWmrVO/dkT8luyfag55oUMF4dlXbtGszhlU7T
+yZdN/t4fx1F9rJKw0lN47iwmLPqnFlqByb71sp19Yf3UILhFfQnW+INPv9TC5Of3
+QEof3kRTcGeVo5OMn9BjRbGtzCbQ3bgCJfpqIBQvx3+cYAbTqAdVxjtk/OCYFttt
+OKhQfB1ZZ2WTtmZ5LwFBvc20L6U7jyTVJGXOUq1RTgUcNzG/Tyd2jfOq0pYFPeyX
+9d0nuy80P8d2f9iDef+LabP5VKNTfLc270f5T1XoyFDVzeAe5EAwiTMufgvUg1XU
+l5NS6byh5faGxD0JdCEGG+s0AfUhZdGHOK6w/4aOqBpkOSUchCmEEw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5CACert.pem
new file mode 100644
index 0000000000..1c39167ebf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 96 DD 41 7F 4E 2D C5 8B BF 51 25 F9 03 64 06 31 E4 15 AC 7A
+ friendlyName: inhibitAnyPolicy5 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy5 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIBPTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHTAbBgNVBAMT
+FGluaGliaXRBbnlQb2xpY3k1IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA3UgNJ6YbK+6YWKAVLudNC4/A9551Bu01IOogUe+0F9LIv7bQPx7ovDiZ
+HA5j7bO3vR1i/VHFgMxrurBmyWXZIK5fYUIqZd5m5ZCZCXPeExOgIL9XrZw0rt6x
+4eZHWN2ygIALlicLJvLXNIymuypS01Pca90e0yumWg3yV4HXrK484mV4xAXvkKNb
+gD6wdSQ76tsMG+XnE7doGfAIXPZS8jwkwPhxNCcgmmUoHVl1aeWlJJmtTkPx6Dpq
+iysJMyA/pfWGb4f6PRMI8Mv6cN+2rfwV2Ec0v7W7KV/moSLJ7u1zqtHEceTE5F0V
+wbIsnv3b3kLV8Ey3yMQihZcLx795ZQIDAQABo4GaMIGXMB8GA1UdIwQYMBaAFOR9
+X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBTAJoHnadadfPC91Z2qUw5l+ZzL
+CjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgNVHTYBAf8EAwIBBTANBgkqhkiG
+9w0BAQsFAAOCAQEAhs7mMDiz1F1wTXNxIBHbOCsg3foXn4M6jK6pOzfDLo/VQG0G
+fvIexIWEJllgQ4WDg9egg+MKKbHRNjDnSZG/nDfxJzWf+uvZ/AtaU/d7CuFb6ykB
+2kYoowmyRZY8cOLFHIMgIyXlOtaelVyvrgmz5deKSBO/Tp5/ss+84UUtbwHv6RL0
+jhgau96YAShZiwvDMCDDnjszHCH0Rl+qY9SHGcuQgrAzj8wYyCcJ4PZDahDxZoxc
+gB/0yUMXG1XgLFK49LH9e18ya3aZ3St9SHa9kkm7l6zqymyR8q4EBgK5jZEXy2m/
+thrfDzQan/S/tIrqzJHovMR3/AXkI21iCTSQKQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 96 DD 41 7F 4E 2D C5 8B BF 51 25 F9 03 64 06 31 E4 15 AC 7A
+ friendlyName: inhibitAnyPolicy5 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,ECF26E92DF31CA59
+
+adpAekT6JeKZGiJqT7MeaI9XW8E1QAFJZ+vo7muRnCHc1lkZSOQeMc0hiywp7UPg
+Itof3x4CeN3ArulZk4Q2Bv2LQ2h9NMWmEF8T2F54CUPlrI6mXDukCj+o7fT3v87m
+ABnS2T7KnAtY+t/K7qYUwW3k7Q/iLsFrIgPWIKpH/dLYeqxGAk2oJn/iB3Nb0Y+W
+1+Q2LkTsVILQt/wNp/bLfLUPmGi27ec8DedAHv5cJUmWGmreIO0nd23dQmZg6kxe
+1VwHH+Y496CUbnNSo2M0vdf0q7DDOGAkzJnnG18VJ90bfsjE9q5jtYGWG75+IODe
+UEoGxW3MrCEo2ZVYY6Sr292WF9+kv8HjRSGwHxvWl2cxM8qmtlbAKQklDRctHfsS
+4CjGUrZh3dHbnRAVu9uJozMoFF0ojlUB/jsLeOsN0A+i9wjJ7PF+BsABm+ccLtuK
+8omjcxMhmRfYHKgTy125ZpXcbrXSt83ocGoj6rLK+ship/R743UIsuecLMrfY6Ml
+xpZmXP/sLdRH/j0Tswi0LPrvWrI+KKJuvgrSkDTUI8Rx9Um7pDaSulsQp9dXRXqH
++WmZjmlT7pjHzC5kronaW06nHMngNl9+zF9YDr1OqL7QmgLqDK3mKmtR5QOdSRfj
+Jjf2ITz863NU8zwm2h8eh1T6r30VD48UOzuiTHUcBrXc0SLH+UAvi0NzAydYmrYa
+jJlrm1QQC3XopPfhIoSx33dEIpI6Tfw69Z3Rjo6L0H/8sseZ/t36mE5905YMHCot
+fe8krSwaT3EbYrahnFk3zWgNb1ENS+7E0PnVrrPhLCz0bPiv6vI6KGDHHhXPIr8g
+G0Ouya09rmX9s4HmDyXuvvbL20kbAKOSTFaYTp08YQCdwdWLabARAGCSAjQiCMYp
+wcUXK9CpvyFcTvXv/ZJ6E9Mlsu430mO3bJFLA2Ot9TOw1BcrKSSsUBeV6joIorGU
+qn8D9nLTxarWNc6fztlzFAA/6KdWNC/yGRbNyjHBUYd0IvIpkLcsqZN4wN8W1g44
+yMgWDJwZgMsI5yXkuYCw7/nvAA1TTsNx1Vq0K/RX6sEve63YTOx4dcKmfC9MFwXm
+vZYfn+RZ0nmrdvf4IjYa64WlpCpZSUaIgCTNUOa64AqXDCYO1s7xTbxBQpogL2T/
+mdCErGgTIbP4Tt2xRPIJ9ayQynPE2+ntUoJ8iYfipBlRKW8plYSY3hrQh4Lsczrs
+/r8V5cjim1/Rb6ZVoTlUF+7uUTvNc0WGbkXgMyLQD3KP6u/AE3zNdYnmYN/Ia46D
+Ls+26jYEIY9+M/LnKUqPR7kxE7tIq2XZtxMbHQHhJQ12EOwfkPTn95X7dO3qdgzQ
+DXNkZgGfc/uMehlUkvCHKBJuiXvyTqZueaGIXjNwODdhcIbv/kRiSzI/UxswUPAm
+w4Xfu3X2HzE1/4g0UhdZFzPYexejSVvlf/NRQNcV2PBwZw7DVuIxSWgqcz9yuF5t
+QAndD1o31X6xhB6IYKBdAl0UCScvx9TcIFYYlbKuHCRbGLYkQiHRRUbtiVjkrWCS
+4edrTa8jNhG/N/nJsuS1wuzBTHahsEFc1gNEzz1Q1gsYVGbIsYuK6Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subCACert.pem
new file mode 100644
index 0000000000..8289750405
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 06 FA BF 4F 88 83 CF C9 20 30 63 1A 83 9D B8 58 77 2C 1F 8A
+ friendlyName: inhibitAnyPolicy5 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy5 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy5 CA
+-----BEGIN CERTIFICATE-----
+MIIDpTCCAo2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJp
+dEFueVBvbGljeTUgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBQ
+MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEg
+MB4GA1UEAxMXaW5oaWJpdEFueVBvbGljeTUgc3ViQ0EwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQC5561W3C1C2WjmuY6Gs3Vb32L4i2f87Awffxn7zLAm
+8k85fRXHKT2gR2DKwSM/mNt4q/22qcjAKAuEhv7GZ2glmOt6m4xeYUq+6Y96Qi7Q
+Vq7jwBxT+yIuo0GdCsnSVJ9ZwS4pFlLMeL0zMZQniHRYg28fcEp/DJZpjxMu55DN
+rNm7+nEwphnSxLcuNvq5WO40rKBDLKVEOOopp3Ok+bsamuVWDkucqrkTRmEis3Wq
+XXv0Jgsh64h9SCI+0bjewjlQppunKfj0upZCNTZGodWKf5qNuEcJcVQPJdT2/vfk
+m/GaTflkY7yGkc2Vr0tAJXkiS6wk1lrGKMLIzQzSbVzbAgMBAAGjgYwwgYkwHwYD
+VR0jBBgwFoAUwCaB52nWnXzwvdWdqlMOZfmcywowHQYDVR0OBBYEFGyZqbYF675w
+STZMWJoi6BSIhS/bMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFl
+AwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgNVHTYBAf8EAwIBATANBgkqhkiG9w0B
+AQsFAAOCAQEAd5CGkdrpbMYK6NXgbS03kQFxAhmgnpY6aU2j7d4RatvkkSVHp5Nf
+DzooyQ9oyz3cmfX5c73vN+Ugxqst+lc4/wjnNmiCm/bLj1pQ89wdORHKgiLU2HnL
+aTkQQOwSczl8xqhK7ATk0ZgICmMwxMxhcen90u4SJwRPp0dIGfIiBUEvnnst5Lpu
+9EaPAHYvrsXn1kYKylWEFRoGEI20TJ360COTYF6TwFR+hsfkcIYL2CewtkhqW0vc
+k83ZgqIlbI7mTScbLLjVjFbldjJ3OGspaXlWcVPAEP9T41Xj+vOKagDwBxM1gaOJ
+h8Y4uEIFS2eAY5+qzzXEnbTG4gVCEJzyTA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 06 FA BF 4F 88 83 CF C9 20 30 63 1A 83 9D B8 58 77 2C 1F 8A
+ friendlyName: inhibitAnyPolicy5 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8A5B334DBC670404
+
+rGsieRSVG2XvI7e4FiZ1Uglu4V6ZBCQnZQ6d69jIgX8yqtE9z0H5/DRcoAIQ3mQs
+ZhX3Qd3sElxByCnpqrKifmDpPu9u/rsau6Wxi/wmYuiq/BlLpiILCOfEQTxULbFt
+jsd6wtk+LIZCYKWLv5w6pDD61Hsv0K490eyS3sQF4wiLNkhtgj8QZE2YSF1zizwm
+747fqsHlwoTkQES7fFhJEtGDbZcUq9ntyw3HSupMYyiBnp+Mq7itCmXt9V5LCrOv
+CJqHam4kZwS8kkGIK/J4L5xKqKGJlMRQ6oDgpVa4XCWd7rgXknMYQzKgdKwR4cy5
+IkDU39b8kYmpJIfXooZxSAJSkjF03mIpVHQBbWlnjip/CrUhmxuSPFAP6c4TRDMz
+O+vzyjId6G/mdlLXVlSa8QiyCrDW4YyC8aT6Blxy18p47/1F2L0yDit1o+sGHxMg
+4PwOM976wSb7xZGBdooPlq4lpt44GQSyG/AZWoUjo2+5p9+VXZ6FMCeN46Btv5dS
+TMbBIkdJmRGosW0q2wVPX8TrIHFnGWNXNOA5uwkqIE2tNqCqgH02iDNaNG5hFOtP
+lNhJv5vJ/kDLc72qETEQMqviK7zAyos9VQCouioXH71vVxX79v8525DN+2hCQy5P
+hXol41S4YG2/gM8/R5pymndqo2Aig7XncRMqZUWtVam0uuUoQa0WnIYxcyfLEKGY
+nqixJwFqgFu0Iv2FdEwIaGo6zjNneQiRr56a1TTKd9MYvm/ZWXtQL1zuuTtD+QOD
+he+CHCZXnEJoTXSvNOc5Ieo/qoIbbXbaf33znX1ljph79N2MVd2O/auv3sU+o3CC
+GWcc1Sj/pZe23x6G5XZTOX072MMZZdIBO4W6V+qupnIIhK9MecYERA7soL1pGO9X
+8QM3iiH3qd5s3gfcS6MSq7IuOKDkHneJW3yQzFZnsopa+MPxe3O9/pEiksWH7bw7
+x6Qw0+DOXYeSrrVXbjYHJ4Qb/nTBE225zAZVdqqgnRiijE5+BLU8re7d+J9SR440
+t0c0/vp2UjkiNzq+W/uzrdaF+U2xwRbzH6SQqNCoSmWqdvtX8qLBf00SskYpILbV
+qgmdqiWROBWoefkYRHAdpysw/4hJUNsvfVkVwv5bMvirE18NpM75bzZqzQKlHNBK
+d2Cr+fsG6QyBGoIijoixMXOSDw9lO4jNwSHCNkqheLOUcEWkWIII7lNoUwCXib7M
+W40OtSkTUggMZTXDddYZ9fgBNsc9g0n0XtF5QBPEhoW/BJBisuRcL4gj+qLC/U0I
+DgzFM2cwGE18OcI7q2u/OwqvKzGXIIVGY6guy6S1tubL8QivHnfEBHEGZu20EQlr
+PGOqd5jClUngTjT6dVlRSgriTVXQXeEfMUbs9jtFHSCe9nFQONhdIeRD2Iu5SwZm
+jguWaeTkkLtKwMfeW+fE8uI/xqNN6YWQI6UHxmhPmkQIIHdkbWGu0d6s03BnSIux
+CwKXpBULLMSkd1dEkVgDERGq61TnMNvwjxkEJGY1YyxjM3YuAgl8CYHr4wrwDDUP
+oYjlx+6WRauSfFANwGAey7KhxJKNUqvIQyxm9ZWiJRmKuJ0x3oIwb1LTrh9A4Jq3
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subsubCACert.pem
new file mode 100644
index 0000000000..e2da15a120
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicy5subsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 80 1E 9D 41 62 69 96 11 26 7F 72 85 64 AF F5 28 1F D2 26 27
+ friendlyName: inhibitAnyPolicy5 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy5 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy5 subCA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXaW5oaWJp
+dEFueVBvbGljeTUgc3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WjBTMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEjMCEGA1UEAxMaaW5oaWJpdEFueVBvbGljeTUgc3Vic3ViQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCRGX+IdLeXlu6WOO1XhgOgGqd9vt8vGh9
+kaeJkJvY+1hpPPj5UzXz125tovx5oIsnxll0/M76mJUpNz67W/qeg+FkBHa7q+ct
+oZefLzysWBF6v1SkRZckKujdjCLHw6qoxSbuOKRC3+Y/o33dkB9wCcAjxWC1SZAh
+AK7E2PkfSh5pPE9waAUQTO3CjJuUPPwffh3WFV52ahhR18RfEMJPsIFQc9b40hEl
+kz4vuZLkT4BP/HIuFIMF5uzehcUGs4DUXQ0wxQesr+0AVCcDM5R1CR9S3WaGJURM
+uCkiQ7WWefgvk2dYkAoE0f0mwMo7nXHpj0D0LFXCFSXlNS8uV0XlAgMBAAGjfDB6
+MB8GA1UdIwQYMBaAFGyZqbYF675wSTZMWJoi6BSIhS/bMB0GA1UdDgQWBBQx4T/8
+Ym6AZc2peRAAK26JWugFwzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpg
+hkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFxP
+sWa61v5gPCuZjV4CP5aoR9c3RwnXgwb1gigoeakbWE0hKy6HdZhrcpht+pSoeHOt
+saYnIEm2lM7MOC4vzvtVMTe3vj/PTwx44yGK3IxSRYs3tWesciRAJdfJrIBxUpgO
+vabTNdI2/7gi8KckWRLCpo0aiRriU8W0TDwMD9lEEMRJ2UGgbIsmExsy8h6ylWxN
+7BAyMWoOx8EQe7Fh9b+j5t3A8XZ0Oe7LdT7NDS+UfFKFqoP21v6h7iXzusoHA3Uv
+YQjEIwuZ7dYzDIXETb7jzQvdsY2mIFIwHtqP6csVtMQVu2WugApFjwGoNV5d1DMn
+XpjK0TofQMZYNOxBEZY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 80 1E 9D 41 62 69 96 11 26 7F 72 85 64 AF F5 28 1F D2 26 27
+ friendlyName: inhibitAnyPolicy5 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,18D6086D08530D26
+
+0piNmvVEM3en9DlJy6As62VsIKsH6IaGNrjEkd256Ql5UWClirgZdydhz2bs4ctI
+49fCVejnqWU6hZXZN01zKiP/h9bJNTF8336sQQHLw3RpvLJJgO5PY2ukj3ZvpN94
+t6csUEqRdy+QuR1BTMZrvDocCCSCWqBSRZmyShV2fL2eos/2hIeY0u4BtqF4fzWe
+mY6FXjI4P36Nla6G5KFIyNMzxFxp+XVZYdelglrgB9p6VLzvSSdk+K6LZHcXtopH
+JpuHf7H91npaix4L2K0GQzze0HgSg/3Ue/8ozipnNv82rhwFEViExa/88E3ddSEh
+FkaM/LNKF2mqT9m0/jm6O+682LqhJd7uh8y3u9n9t5UuCR5UhhumRvAZidpBF71q
+uPseB/ikypJQ/oJRt4jP/lJI3aPT89Oy80CxMCKAKvaV4+e5nob4bcyc51q27Fku
+WszWcOJWMvM6os9JgaCN5BYpqt7zpa148qZx0rq+ZcqC4l/n/DTEvQxVyNQNWkpp
+cualkUiz74A7hX098eQRI2Sseo6KWrV2fEcuQLIkzo/BxnsTRziiehEJYa2khhUW
+qwapQ5ulM8vU+e6vyrfJW0z/kuEoLWFkq9o6wA34eRta7hxihoUcjSmvCbJ238/i
+mg75biBtsoB/KNJsX9eLLmxbaccPH64ETuNLH8Yj9faWeOGxotv1HCPOqTL4wrQG
+Czpd67DGSspl9PVG3TXFEW8Xf0fl0NqVqx0MM8X7Suq+3svX11VXFiqUiXiMvvhi
+g+WjtmjBQ5HWbu/LuG58PIBkSzah58vmFB+XrvWRb2HyrBT8hvZRCIgUqLzr8Ufx
+vOkHtlVn091XtWqhLZBrCjoCI/U3K+TmbbePxzAB/ju47vjF9YPQRD6IKW+Z38rb
+j05timFYKLPDyOu3gaWNI865LkOxx5JgWR2rIoSALv7pln0GfGtpAHvRPdrUGoze
+Vu2jqqPCPlddQ8Pm58BSYj+GRRKANfJi5LdPnRwTnbFceHAmk71mph/DnEgHfF5O
+mBfKXdPAUr5/Fj9sMCkpH9ihl4qylXAd19NzW1oM4puD/L22d9VhXD1wTdAWu9ew
+9kdrRiPl+Ohm/ktOkjLYkDoCol4sfxuetF8pXswRi4laqPvz+kw6KMgyp61gcGBC
+M5cbpAZhH6zfDLSnYPaC+GTQdSjBWp51LZYe2ChPocOs2HPVWZ49NLVd8VCJo48e
+xFCG32GW87sGMAV6INPAQ0CQBTAE2iWWZZRk5xrqehBmcjkl1WJBBF5DJN2UeZ1+
+6buBu5Fdtc3TM9PyIoDsBjKA1ma925bARz4OGhU39YbdgJDfSEuy6ahKxwr+JgEC
+C4xINh5BjQLpXewzA6F0O3sh4V9d5/FdMIc5jCeIGVfRkRRkQQwfZbg+gKhEg1PL
+CEy7SOPuahAHFjWSK26ZF86heHB608IO/GcljN+p1fe+I8z671fp15XxlKDOW0YS
+/hkbgwvzp5XYDz6/vkjRxUACuWd9s1emp5dv5wUBg9Ly+A1ObjFK6k9Q1judD4XS
+5BC9jrNUNdlXBGvy5iTTcoio0Kq6hHp7VrSi5ujgUVCiBTKWsWk+LYaIFLxh8OMk
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3.pem
deleted file mode 100644
index 05c743e5b5..0000000000
--- a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3.pem
+++ /dev/null
@@ -1,159 +0,0 @@
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA1
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
------BEGIN CERTIFICATE-----
-MIICgDCCAemgAwIBAgIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQ
-b2xpY3kxIENBMB4XDTAxMDQxOTE0NTcyMFoXDTExMDQxOTE0NTcyMFowTDELMAkG
-A1UEBhMCVVMxGjAYBgNVBAoTEVRlc3QgQ2VydGlmaWNhdGVzMSEwHwYDVQQDExhp
-bmhpYml0QW55UG9saWN5MSBzdWJDQTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
-AoGBAMvuM5rrG+hunxSZwR8TVsLND7teVaTAzIxbnJv0xpVvawDeQiN1A+CIdJH8
-TUXrgcfdU+E04StBCqDRBr1+DBMt/PuBDS/I2PcKqBuP6sfkSDr/lPYkbRBI8wZ9
-87H/ke7seqh7cSVORfqg4KupdEE3i2gxONHlTT/7XV0C5aOlAgMBAAGjdjB0MB8G
-A1UdIwQYMBaAFGbbtZTHBcSzPiuRud/IqNBNKzREMB0GA1UdDgQWBBQpIHiUjoSQ
-KUJLfKsOgyq+NVs8FTAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0gBAowCDAGBgRVHSAA
-MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAuKZUyh6gvU8Ab5pl
-P79yddRQcx4G1navwUD3YSS7q2rnmqY2ucmHX8H1JsOhQUqvLL81fIqAkWPANAmQ
-K4NU/ZSkkjtfTcJy5oYsVXjz0MyLKOwrt52j8MLZsUW/TIf5e57kPbORC7RQhEr+
-yMDT6AY3En8iF4h8mqMhwnQnO3U=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy EE Certificate Test3
-issuer=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA1
------BEGIN CERTIFICATE-----
-MIIChjCCAe+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQ
-b2xpY3kxIHN1YkNBMTAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMFkx
-CzAJBgNVBAYTAlVTMRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEuMCwGA1UE
-AxMlaW5oaWJpdEFueVBvbGljeSBFRSBDZXJ0aWZpY2F0ZSBUZXN0MzCBnzANBgkq
-hkiG9w0BAQEFAAOBjQAwgYkCgYEA5paTjQbj3puhDjZ2oS+VWmYpkB1j3pR42xS6
-DZJFysWv18MFWj06Gcb3VAc4DowyPEHzYQuzdaTQASCQLSX9JskU/ohcioVwGiK5
-S80dAfcGLSVJsvMROXvlapFvgkhM/qqtvyL0ft/bTTMPPkQMqayQPNiS1j1NIOaj
-nLReO+sCAwEAAaNrMGkwHwYDVR0jBBgwFoAUKSB4lI6EkClCS3yrDoMqvjVbPBUw
-HQYDVR0OBBYEFFXoqY9k25OSv29Bm8cxsKCX5ASxMA4GA1UdDwEB/wQEAwIE8DAX
-BgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDQYJKoZIhvcNAQEFBQADgYEARqFA8zrZ
-Fv0+U+IKZbMlVa9p1ILSXSsNk+KlwRjgJRk1l3UQtw6G6NfVhKkgNvqgrj7zcfg6
-zZuuMCad33y5ysIFZ4ohuBtD19Rq5TEp+UqAqMwaewF7AajpU0h+XnLg8v1uPY0j
-a6MimyCJtGwBH9LcptLn/+La3+6ap7ji+nM=
------END CERTIFICATE-----
-
-subject=/C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
-issuer=/C=US/O=Test Certificates/CN=Trust Anchor
------BEGIN CERTIFICATE-----
-MIICmTCCAgKgAwIBAgIBPDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEa
-MBgGA1UEChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hv
-cjAeFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaMEgxCzAJBgNVBAYTAlVT
-MRowGAYDVQQKExFUZXN0IENlcnRpZmljYXRlczEdMBsGA1UEAxMUaW5oaWJpdEFu
-eVBvbGljeTEgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM97WBxcmLvJ
-SCQLpyIPIhnb86f8mT4hWgvgIiFRNZDdlqrMl5D754iGLwoSRYWm6NZzneNuxpXa
-sX+q9JyoOc6/7ZQy37w/cp6Elcq77KWgALd2zRbEAbFOtdy216GpPB+3c9I7msQT
-W6bbzzGuqbTxaEEvWptSCBqXuFY6FR+XAgMBAAGjgZowgZcwHwYDVR0jBBgwFoAU
-+2zULYGeyid6ng2wPOqavIf/SeowHQYDVR0OBBYEFGbbtZTHBcSzPiuRud/IqNBN
-KzREMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
-VR0TAQH/BAUwAwEB/zAMBgNVHSQEBTADgAEAMA0GA1UdNgEB/wQDAgEBMA0GCSqG
-SIb3DQEBBQUAA4GBAJTqlrUt2/8sAjVasjqUiKDtFgaFp8ueEU93bKb/90sW+uxF
-HCyYOqmVYnjKLDGYR0rR9R9hErIFwlqIz3ff2K6cq7ND2uLm8BctGWmvP3s56y7V
-CooCKzBgRilaPqsJw12BrGGjZ4CaYx8ov4puyRW11UjrAcWn/8AIWCmIPuzH
------END CERTIFICATE-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 CA
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:66:DB:B5:94:C7:05:C4:B3:3E:2B:91:B9:DF:C8:A8:D0:4D:2B:34:44
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 03:a6:22:4b:c0:43:a0:ed:e5:8e:d1:8b:0b:d2:cc:b6:8b:9b:
- 21:e8:fc:2f:84:a1:cd:3c:a0:bf:73:be:9a:00:f2:b4:90:e5:
- 15:a0:31:87:2b:61:f0:cd:3e:ad:db:d8:2d:91:db:ba:8f:5c:
- fd:95:59:36:0c:ba:0b:f1:79:a9:68:96:a1:2e:14:cc:0b:6a:
- 43:93:0a:80:71:b7:3e:8e:3a:da:74:31:5c:1c:ec:82:b9:3c:
- 88:ff:6f:51:05:f5:f8:d8:47:c2:9f:3d:3c:5c:98:be:f0:de:
- 9d:d8:a6:56:e9:53:62:cd:09:56:91:c7:ea:c8:bb:2e:05:a6:
- 38:b5
------BEGIN X509 CRL-----
-MIIBQTCBqwIBATANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxHTAbBgNVBAMTFGluaGliaXRBbnlQb2xpY3kx
-IENBFw0wMTA0MTkxNDU3MjBaFw0xMTA0MTkxNDU3MjBaoC8wLTAfBgNVHSMEGDAW
-gBRm27WUxwXEsz4rkbnfyKjQTSs0RDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQUF
-AAOBgQADpiJLwEOg7eWO0YsL0sy2i5sh6PwvhKHNPKC/c76aAPK0kOUVoDGHK2Hw
-zT6t29gtkdu6j1z9lVk2DLoL8XmpaJahLhTMC2pDkwqAcbc+jjradDFcHOyCuTyI
-/29RBfX42EfCnz08XJi+8N6d2KZW6VNizQlWkcfqyLsuBaY4tQ==
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=inhibitAnyPolicy1 subCA1
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:29:20:78:94:8E:84:90:29:42:4B:7C:AB:0E:83:2A:BE:35:5B:3C:15
-
- X509v3 CRL Number:
- 1
-No Revoked Certificates.
- Signature Algorithm: sha1WithRSAEncryption
- 75:3b:42:7f:44:c5:fa:ab:b2:c4:63:ac:10:89:84:e0:50:32:
- 4b:96:80:48:15:1d:19:1c:b8:49:6d:42:c3:4c:b4:bd:a0:29:
- e0:14:56:1a:1d:df:92:90:19:27:a0:b7:f3:1b:7a:32:32:2d:
- cd:ee:29:38:d0:75:8e:8c:51:9d:02:7f:92:a6:af:08:ef:23:
- 8e:bc:b2:a6:47:36:d1:9c:e6:dd:4b:05:55:1c:56:47:1a:40:
- 67:4b:01:bd:b4:d0:74:12:5a:97:83:20:d5:4e:a7:d2:bb:ad:
- 52:a5:ac:13:44:fc:95:1f:d9:70:fa:a2:05:fb:73:e2:9d:15:
- 61:ac
------BEGIN X509 CRL-----
-MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGGluaGliaXRBbnlQb2xpY3kx
-IHN1YkNBMRcNMDEwNDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWqAvMC0wHwYDVR0j
-BBgwFoAUKSB4lI6EkClCS3yrDoMqvjVbPBUwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
-AQEFBQADgYEAdTtCf0TF+quyxGOsEImE4FAyS5aASBUdGRy4SW1Cw0y0vaAp4BRW
-Gh3fkpAZJ6C38xt6MjItze4pONB1joxRnQJ/kqavCO8jjryypkc20Zzm3UsFVRxW
-RxpAZ0sBvbTQdBJal4Mg1U6n0rutUqWsE0T8lR/ZcPqiBftz4p0VYaw=
------END X509 CRL-----
-
-Certificate Revocation List (CRL):
- Version 2 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: /C=US/O=Test Certificates/CN=Trust Anchor
- Last Update: Apr 19 14:57:20 2001 GMT
- Next Update: Apr 19 14:57:20 2011 GMT
- CRL extensions:
- X509v3 Authority Key Identifier:
- keyid:FB:6C:D4:2D:81:9E:CA:27:7A:9E:0D:B0:3C:EA:9A:BC:87:FF:49:EA
-
- X509v3 CRL Number:
- 1
-Revoked Certificates:
- Serial Number: 68
- Revocation Date: Apr 19 14:57:20 2001 GMT
- CRL entry extensions:
- X509v3 CRL Reason Code:
- Key Compromise
- Signature Algorithm: sha1WithRSAEncryption
- 92:12:c4:34:b4:92:ab:ba:71:6b:74:31:16:ce:ed:25:d6:4b:
- 1e:fa:f8:20:1e:9d:d7:7f:30:ed:15:f7:8b:5d:64:9b:dd:31:
- 40:e4:55:0f:0c:5f:82:69:63:00:76:a5:cf:9e:c4:5f:f2:53:
- 9b:9b:7d:f5:69:1d:74:57:38:70:e5:fb:5b:76:58:c9:ec:31:
- dc:94:1b:02:ee:9d:33:9c:38:4b:29:1d:e1:0c:29:8b:6e:c7:
- bf:a0:e8:40:34:83:cf:ff:9f:cd:b5:f7:d9:4d:a7:9f:2e:bf:
- 44:98:6b:f2:d3:fe:a8:20:31:c1:33:76:b7:1c:19:65:4d:b9:
- 14:39
------BEGIN X509 CRL-----
-MIIBXTCBxwIBATANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEaMBgGA1UE
-ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNMDEw
-NDE5MTQ1NzIwWhcNMTEwNDE5MTQ1NzIwWjAiMCACAWgXDTAxMDQxOTE0NTcyMFow
-DDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU+2zULYGeyid6ng2wPOqavIf/
-SeowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADgYEAkhLENLSSq7pxa3QxFs7t
-JdZLHvr4IB6d138w7RX3i11km90xQORVDwxfgmljAHalz57EX/JTm5t99WkddFc4
-cOX7W3ZYyewx3JQbAu6dM5w4Sykd4Qwpi27Hv6DoQDSDz/+fzbX32U2nny6/RJhr
-8tP+qCAxwTN2txwZZU25FDk=
------END X509 CRL-----
-
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3EE.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3EE.pem
new file mode 100644
index 0000000000..9f5f766248
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitAnyPolicyTest3EE.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F8 C8 CC 60 FF 6A F8 EA DA 16 34 3D 23 A3 8E FE 01 4F CA B5
+ friendlyName: inhibitAnyPolicy Test3 EE
+subject=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy EE Certificate Test3
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitAnyPolicy1 subCA1
+-----BEGIN CERTIFICATE-----
+MIIDlTCCAn2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dEFueVBvbGljeTEgc3ViQ0ExMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowXjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExLjAsBgNVBAMTJWluaGliaXRBbnlQb2xpY3kgRUUgQ2VydGlmaWNhdGUgVGVz
+dDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXXPnjv8RRkKcKkZOV
+yGORDonJuI1SMrxuX02bYLRAC/XwvLOJpDsf/xA8JLffgaFLY6qfYmBeyVrpPvTk
+wyLD5LwI3MK6sc/lTCIBidoDBodfodpzBTQIa4MJLElXJRCkwyuEVMAFNng8N4Uj
+6ZGlBUw5t0wX2dudQQaILmmKKq01ChpP0DCujvs2vcadAm/sM3mpOoVrmc5onF94
+szwB1QrNrLrPN+WlaX67dl/m/uuK4Bbvj1cWOdyAtpskVKl4uZoyTE4gyuOSRbFX
+H2jC1XMd2yhtePKFYkHjEQEITpSKy/FPeQMyw9rzFI7t2+nAqP090pB4YsLNPYgN
+cG2HAgMBAAGjazBpMB8GA1UdIwQYMBaAFHSg1VjZK1PSK7DNXXHGob9Dp8gVMB0G
+A1UdDgQWBBSgPl5tKwvtC+NPQQGd8WO1AN3BkjAOBgNVHQ8BAf8EBAMCBPAwFwYD
+VR0gBBAwDjAMBgpghkgBZQMCATABMA0GCSqGSIb3DQEBCwUAA4IBAQDFsWjMxFvi
+8SyiT+A6KlMhtL6UINksICnrb2ozC7mouE1uge+XdzRhk6ub/x3Yrc83OxZbtZzA
+f36G5OSyKn42LPAtsqW+X98xJJR4ADEsAxUTiodITJ0O7rolRFurlCrITR/AEswp
+bGyspXbSZVpCMqr87BCRlJxklpk8Vx4JevroJBrbvqtm0s7W1RsaazNzZyA30WIA
+SYISAcXhLlJhA+XTVZVMp7U/8RQ7K8lftW17ZJ1AQGc1KTSHhzOeZeoAJCYaqBLz
+BTRFRv04CGjhGq3UCBDazX2XfBQRg4TIoTo2GE2/cpv5oOMFZuxJLESCZbbev2Df
+8JFIDAsJaKox
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F8 C8 CC 60 FF 6A F8 EA DA 16 34 3D 23 A3 8E FE 01 4F CA B5
+ friendlyName: inhibitAnyPolicy Test3 EE
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BD2FB17770635FCC
+
+Q8wUO/8aCWrsdP73HdUypS9Qbr1TBRDIeN4SrhnumHAP+uWgvZsb6ijnu9i1rG5i
+N9VguWwUkR+b0evo7AzS94hJt89CRtWICxF9AfX/ruMUrLjPuI0OY4N96WdBSAEN
+612yy65jJfTATSXoZ7xX7he5ZZ69yX/qehTKjBJUZyybhHEcsGSjnlbOOtGL+cTy
+7Rp2NWsGK+EjdqB1JGeoZkTeA+P06f9KNdofSzqtq4Ku8+6SQMJ5mxKYK3Q3pZl6
+OKfTYBu13cS/JcvMZ3CiCIqgAfztt9mMufpfRI8CSw/vBdsp485n/g4Qcq1kWouj
+m4XWIE1zJ2D8D21KamP0zIHJrNkvaqvK/kxld8H5nKmPRd6i7yiqNJ0vDe/+zQN0
+Xts8qoszNXjGvKbt5ee63TkSVCHPLQW9FlSUK/n/jIDb9FLy36jT/JgYlT6Gq/kG
+AdPJM4855S6J1sfiIzSd+IMydFY7nHea6wbNvNDJu+8g9BYA9xP8YAWVTJU91d/P
+gtTfR2APC8oAFafVK9zumI81hR+6weED9MsYdNDSSpyx4/vfDMfjuTxqlEF1Jp0F
+57LMGViy97uQrnjn00zyBZ4RWIyFDrkmD2MAkhSkxKT6RDdMazF/nflbzEeleblb
+kNA/cSUsGt7yNaaWKxKPuOKAP0fVcvDaFnkIpajVIOIw/FTs9RtlHGt+9u0ClAki
+2r7YUDGef4qWC0N0OT0/vY4FGxOm5Z8iFfrEjsOeqR9ffXS91aZVjX6JLanLBz8y
+grY8p8QJNx0rG47XRscXPjqprslzUzkL1UPE1UfrbHz6SvCtNxXIDs9qNbmT1LqN
+ICLxp9B8Gz+PXNWquVFBSiJ/wCdy1EINS9Uga5SflTikoWbxCiUuivNgQbAq3f32
+qSwr/3DfyF4srZ9L+pt9XLhC3rF2pcYsg+msA/kY6GteB0b8tmF1SqBctjzG4bL7
+OIaT+H4WYTD3R9Pl80y8ZBd885x9xNa6hWPvoiMsjEDzJnl0PhS9XwkFKTUe+b3x
+F3Sw60idyYXqHcVDmBd7Q/U4epMIjrmhJJDd9tiYGM2cUNNSw1O7qDNwap3cD/tn
+Gy62+bCO1hXsDPq7M0Ae+8BaXO8L7FBEbuaItFDKcrwdGonqO1ypWnkN+518hyXh
+FA35sFzrSVQJuttG2Yn8qdaEmoo6E+c1WAOTzaX8ISKZ74kSa+4orhscAqlxB4wh
+o179/V5iK1lDKY8xr6i9NMD9nb1hfFfgUGmYKgP4jtihXOogplUdif9wOe6DAD1j
+h2hyWSiokPDOZK2oGyjzpJjXmG4SWI1MGCwu0FpH/Uqs+RSCu01bAvjrjyCpiK6T
+ykw4josSQ/E64cNJuhB6A/FTChR46nFHGv2PHLeI8FVj32N22pqiwC297bod57jE
++savZ4nVt5BjYdQM3iy1UMuZq5XPmFYpiIyvUWwAvPLa/N5ukxcRR5vWwB+q4oUZ
+PMW2qeM6Eg9GLsMwSvDwdaz5E3shK9FL6xzkdzkwiSdnnIQkrRLNVvLxm+UvE53U
+bOZ7n2G/I4mIspwxc2qES5SDzkegQdqVYHr6/d+lkUsX6eEZjScr7WHla5a51Eim
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0CACert.pem
new file mode 100644
index 0000000000..3c95cac707
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1F 48 9F 19 D8 64 D7 71 C2 59 81 7B 56 6E 72 AB 7B B2 05 E6
+ friendlyName: inhibitPolicyMapping0 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping0 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDozCCAougAwIBAgIBNzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExITAfBgNVBAMT
+GGluaGliaXRQb2xpY3lNYXBwaW5nMCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANt7nMME0N3fefF9kFthzAI8C4Y0Ul3e4aGamPxfGzSoKVgKIEXl
+yKbwGaBplcjaOjQxl6MO74pTzEcOUDHshkf1uLJh8K52pJDew36C3KrZ3cMACKrz
+LgvwigxcHTWFv7Rey0n76TupvA8HGAl663ah2QIt8I1rCqmp/7raxqQxbBJFC2Ti
+pJ8XZrHzIPnzkP/RjVgHH+2vgxypQh+/Izw9E9MOLnkXKUUE5x6rCHvbz2CHJ3L2
+QXlqaZJz7hqKIFASnaY3FPKwP+cU/bmIIImXCTjzYx5hiT0rixD/bUb+pXkcZkF5
+WTZZ0MU4VyLYTAEnBeiiX288aaDV4vUli/MCAwEAAaOBkTCBjjAfBgNVHSMEGDAW
+gBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUWDcmB5GEYKzu9kA+pSv8
+/5cdndswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
+BgNVHRMBAf8EBTADAQH/MBIGA1UdJAEB/wQIMAaAAQCBAQAwDQYJKoZIhvcNAQEL
+BQADggEBAFzEkzKG6Ig8FbZ5qGL/3Ua5qibD6Ky88jtku7s2ZG6vQ/GC/5QAcWsW
+Qtz7ajxzTqZ8ffXSFsmynLiUjmtPbpvuKmgZpklXi/8dWmy2DMxxBqObnOkASL0U
+wbpv0hMTRNQZkYaNRKd3G0mSJdLCR1ZumDQfxYtSSB5I700rLZNqxLgF+XemTNqK
+NQxcVvAFOjJ3fu6a1lRPr1ahvyPgPfUGugETMoMQ95cqM0Aj5Zo0ZRUQsXS0XCtV
+D5ZD4THlPWdUcUKaF1H2vVvidJX8dGV5eA1GkJ3VFb2yAmbEHxgzfr6YgD4jjgAc
+ksRGDC7jO4eEsZYanmTqnXdR7xBFN6w=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1F 48 9F 19 D8 64 D7 71 C2 59 81 7B 56 6E 72 AB 7B B2 05 E6
+ friendlyName: inhibitPolicyMapping0 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CBB29B0088B46234
+
+V0UB4zlADJOccBOu4p4x8UvJgQxqW0WabhdIPT0Gpi5k3ou6TTVXT4pj5mb33Ov8
+n5VrB0kDC0q+oopZtZDWI+ZxgYPxQex2Skijcc60zGxNljF0UHYV3X8xAQ4os30R
+0xEE30tYCVqTJ/EA/QMZ4jl8xQFCBoUzpIeUcUXGmcf2uK2I69di0s80fX5uzvUm
+yxTsgnWuOucKm6J9bjs5Bb3LbfFq3uUGf2lVWizQj7ZKLTAVvRCO1pnc/OOo8zdG
+5h7jYDVvfHJZOv9Q3RAS4K5h56Oe7ebmR0ucNwNN0iWw6QZvuabUppCNJooZfA9d
+4y8eZ+Ocd8PNgy2VJpmy/NMsj74a7oXO1cZrmqJuajn1HBO/xYksH0334xLemaxD
+OnZNL9aNyTmyboTnmn712skBUgIWC76kdb/M/MSwFFUjElVO+i2xI0c91T+VYP5n
+3YsfMWSS1n1386lTUCYlb3YqW6SE6dLUTjB4j9UF/kLHNKjVcYFfYK2I99aXX5yg
+Kg1Ye+hgaeMB4BUKp5f2YGhpqnfTzfG/wQjCrn3ev2sJlvEYFQvRakrHVyAaELzu
+BadiEQLVfb7yV+DcFwdK9zSZf6JnBEL8HpMSTLCvgiXgB+m+j57Cly1Xcl1qbUkn
++yvyJOar9zANlqmBOD+cn8HqmJXOb51whNi9GZJCa5E0992nR5PiTYgW4/aP3ArD
+MGz+4gF1MfWLJCNaL8RoyVTCdD4ZaexAYt8MkKqirviv2mQFLYm2i5mzDCd1ZUR1
+rGVzSBwnG5v0/zFiIWF23hi4HxzhTu3H67EU9yUNhikVCNb+7JRyD78QqwGYlqIC
+oPXCEOyU2iGr5zIe+N80C88vGkq/5C+16VAq1Pp/FBuEFrcl4HM2O0FcsWvhofWK
+aKlmAY0V2Q71MRN3Pc9OrBAvKoc6U0F7ggw60GupImNORhxGbOgnoGJpNA5BO3RB
+lerEWyuOmrRhQvmpMAMKIRGmzBTos/T9h4FvM153AmJThNRdMOsgFCvREd7WN41/
+QiAXJ4F4kP3ibx3t8NeQcYgMw6Kh6PthO1mP6GVaxQLh0EBAHtubTXPOXcKfESHJ
+HxcP/UMGmwiFgQm3RNxtl7wRqfdVDwXIWdMRFjbSDJtRx1EQaMgqRSYIu7xG+5QT
+HNcH87GUBwDiGEggK4aZ7bHS/VAbnIeTJRbe59uIfdEx/Wmc/04CQ/kOranx5ER+
+7VfSn1njQ0x4JyBwwxy4zt83eaMZYHk+XJZMnkvNaxv3bdb727Lt+SQdPX3iYtO+
+4oMMsHjVR1yJ7ty85zzE6KkxavFGj5Oxy4O76bnuvx2aU6wGE0k50um3iFOkPidy
+a+PmhwFuOcvNPP/y2OM32J5nv5K9QqY+IQ/V8fZXMK2rLLYnxF0emDrlqmBwqBeB
+VM23mKyd+fFCfl0V8u6PkyrKX3emXD3GXIX12vC3gk3LGDehJl55KJTz9CG/JDGh
+pDMxymRAWaI+hyyZ7caCQ+wY5ut1h1g0a7H5gB9uoqLTTx7N6jm0jkXcoV43r3VU
+M9GxJPDmUgPzvxFi8R+ue67sTb1PshxvzJJlBKazn0kxspaR7a4TAr1gXPYspsrT
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0subCACert.pem
new file mode 100644
index 0000000000..93ca7870f9
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping0subCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: F5 46 C6 A0 F5 9C 18 B7 19 19 29 45 97 68 C3 F9 C2 98 5A E7
+ friendlyName: inhibitPolicyMapping0 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping0 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping0 CA
+-----BEGIN CERTIFICATE-----
+MIIDxjCCAq6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dFBvbGljeU1hcHBpbmcwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowVDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBwaW5nMCBzdWJDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOxx/fK0GiaWvaebSvC+tR/65oOxtOB0
+i2rlCHg++AGW0iPfXroJpby/vqElvVGZ9/L4ZC4ESfkKlcP99E5jqxNFqxNmjXbp
+ySBDusJ7cGIK+Qqd2tkfXPkE0Ov/XqQYa2hXqvZGbwPyXTjkjtaL7k/xJ42vJ4vY
+VyB3TKHWnm7VK307P6R74SvlLeTqcbNY8UtjZ7y88mfufWAKczbDq+0BCMpjFaUz
+h2gJbp7XZXrsDq3NdQ6KSsiU4YKDk2JKtPZuLxlHXl3DELKzcdTuipGtbxvTheOB
+VUfJKo24hBDWSry7ejCKwNbxMwXGovRY9FH8iHNKjEefc7W5d443rQUCAwEAAaOB
+pTCBojAfBgNVHSMEGDAWgBRYNyYHkYRgrO72QD6lK/z/lx2d2zAdBgNVHQ4EFgQU
+/7RzYlKNXJY6WpCuGry4PHmBYx4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdIQEB/wQcMBowGAYK
+YIZIAWUDAgEwAQYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOCAQEAvmTHRMpF
+Xgn5rrscWjGbzojCzy8p6s2fH1D02ULqEJtJXFbs/UIVByZaMU+s9g1yRz6NsrBY
+YJeUKc0l4OZeOmM6rHeXVD3KUBTb1dvZbc22Y4LzzRacv8p6XF+jtiTI7hnkv+7I
+AmK1y9IOIMWB0mKT/uRwzFn5GG8kYyIQuLGt/xB446nHL5M0k6kstz/aApkA5A62
+LUZs83AcF/p+NK2bY2rGFrbfoRtxFyOKrf8bwc1GmHdj/KeQT3iwJo9ilYOECY+0
+DmL8SbReR2oE6KM3Y2FTcVu2aBh2kqiFRU/DUu3Qso9hQ69920KdysFj2I4mTRWB
+Sn0cA3GqJO54Wg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F5 46 C6 A0 F5 9C 18 B7 19 19 29 45 97 68 C3 F9 C2 98 5A E7
+ friendlyName: inhibitPolicyMapping0 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,82D2B7D8553AE8DD
+
+CT72MgD6SJk7vHWHJ2AwPkvAuujP2V/jX/2061eholo92cfOwARYretMFnqxKqBV
+1veZdKKekq5okX03iMOdOg+MJo1dKARzFeQ7e4nqUvFLRKrfjbJpd0rrga7MoRC7
+qScAxuZ5fBFkk7RpzxL/ejeaFDEII95tmS3PpoYBMRUS2NGHmDWF94onX7yzj/Qx
+ztz1v8FkGdus72gDv7ezpnED+3ENNFhLm9QXnaN56xIIxc7l2ads4QQu4M9s1nwI
+RNqn1hR0BxABF92pRoXgkrXnYMv7bLW+/5mowCb87VUddWHqM91AygUxkXtVto6Z
+jX9TXCbcTS3fv0bHdxQqNr7bna0zY6ym9z8yWRAJ/Hkf1CqNYFVFLvm05pGOtRb9
+Hk5LR+o7ZzYzK+V4e5+VfvYj5cKAARmvW51+we+p7XOO4x8iOuYGAzFHEkjrFOrI
+o8idKIfmoe2oy1JI8WCh/IddhPUM725YaGc+iOW+FtX3laAoOml1TZC0LJJZWWzT
+uP9CftRStoUxx6I+IgHUe80rTasjj4KQ23UsW42IGs5M9DlP/mHYoSlUf1nxjpGb
+rl6emEXB1SK7Dc/5DYYqn1zqWpVtZBqp3jlHTy+XpSM8HXhY9YhvCKy1BSNx0dhG
+nBzBECLJ11gvzU1r5279S+V+myOE619C83dn2CA+4bmVfddWsw+i0Y9cRIyGyyBf
+P3vzm++UOcWjiaORD65TQWGPjvUFKrE1TkZBZ0uThILEfnpUyYaH9X1l3R2Ky3yp
+p6nHQAMBGt2F7fPZDdtlB+SP2VXd/WJdvU25L8xUWmIQ/uFN7RHVemFznwJGzAYr
+ixghJ3QEG7Wj0ie6y8SVXMILUKfBYjKnMsluLi4f62jg7cePEh+u2xpdyVHBgbZT
+p8PN7Y1D1uJUb98ZekFoLq28fIKptCOSHmwyn4uM/g2DfutmONMJEWGP1HqBTcR7
+bGwlyqZYpQw2C4CJ9F/ubDHMYNhQSEZWqh6FRF2DJxveTl6fYOre3PYDAc7XCXyQ
+QZ2QIdZ2138C1PewlmP6duM7Oz2+NhxRB44B7PNc7B+F2e1oekur6mgZD25U/5pS
+y4WPdRxO55kJjFzS9LCrRWbnwMpUPE+ISqBGJ4dhjpSGAHVHEBM0JZIenpJEFVFF
+DbbWqboDKo0fvnREPbSJqKz9HQ/4SoxOPdlRxQtYGkb0wdZoygYttkVnaqaKsCIG
+Rgqh7sWlPCzIh8/HkTI2YlX9yXETINvx2QVBeMZspTwSRy22SbbuIdPgWspVMCZu
+J8z32IxMgxZvpx1prS0jcJGh69GLbnGMXg0u4jo/ruhuY0MNflWbCHX/YOVbylSW
+a9cWCplrb/SwmDDJ1HOgx/UylRGQ9HDvxnNRIW5ic+Wdehd2dSoya2SZLSGw6BXf
+5RRIBk2Cxac/ooi6rYU65S+ZC3iMBEa2L+KIPEEgjxOdBfZwJ+N6pSWZ/nZ+jzO9
+Qv6DvFZhs7sD2cI/M69TmaUBM++l0cofj3WUdMWLevgVc0AAnQL/83bZ62fpBnGt
+MDOEMDBQrCRxlCuV3yxHu7zivWx2DuUBqfQMy4dyG0ieMlKLLjx1W/K9fVcfFCJd
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12CACert.pem
new file mode 100644
index 0000000000..77eeeee458
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CE D9 A8 C3 E5 4D 04 D4 32 B4 01 5B 7B 14 D1 B1 01 05 C0 8B
+ friendlyName: inhibitPolicyMapping1 P12 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIBODANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJTAjBgNVBAMT
+HGluaGliaXRQb2xpY3lNYXBwaW5nMSBQMTIgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQD1I5zxceMZorGyjg1wIoa8bfGeT1qfHYrEVfYDrHwug5k4
+S1cwzlE+S2+1a4izALDGq9AwRgmnu3e+sD0D+D0jN2dKQN9xChH+u/IAI5Mtbw7h
+ds2yHU90cqNFbkEk5JyvBdGLvJZ4BVc/VuJaxdDIh3xUADnpk2wXjPGJSol4Sjdc
+pb7m4/YaDl0dAc+r3r5U1Wz5BNqI0A3JvezPJxTYnBQN0JvEkuSOg0TfmAUFqEqB
+o/mCz1/h9Lycz0qwqOWgyVQvvfIpD5YtZF1Bek9JISleu2pEaiRkulVCK9TP26Wh
+ZSE/vJAhnbX52Unpz/Kp3jlUwU/DDbM7KW9bRCgNAgMBAAGjgZ8wgZwwHwYDVR0j
+BBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFE1nfo3dORmv6Cbe
+DgE0eLF1ENqkMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBIGA1Ud
+JAEB/wQIMAaAAQCBAQEwJQYDVR0gBB4wHDAMBgpghkgBZQMCATABMAwGCmCGSAFl
+AwIBMAIwDQYJKoZIhvcNAQELBQADggEBACsyNZjgHZskZHR1CLfKK/Ny/xYRo8ln
+NaSzPGFEcmltgkUFAEKmjnzITOIg1kyPeOh9BVLbtjzuXVJ83+2Y1MBzqDTmrGFg
+F62PRAXKkH54QyT00xP0TbmMQ7DEIRAf4Dam+mT8tezBbJgr9zjSTQdh2R0JxeI9
+J4GgBMuASTMF7NDDtl72adRo9xzJu9FFucSKUsTkYjm2muUStfZH0ULJoDEm0MlJ
+CEZWukj49JOznvVgWtUaHv50/oRB2Cgl94NIcs9lAsctA/cw4i2pQhede94SUjFK
+pa5ZeQWQ8rV9MpXFEZ9qRhekJ+ckfqSvPWUcZIW4wve16E/hR83Fre4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CE D9 A8 C3 E5 4D 04 D4 32 B4 01 5B 7B 14 D1 B1 01 05 C0 8B
+ friendlyName: inhibitPolicyMapping1 P12 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0F886ED54A0FC007
+
+ytyfPeZDySSt3olbkPdTmNLg+X1d7aEmZGh3LYg3lVGnYCZOc9sx8F7ArZWZM8wZ
+2CEV/As9Dfkzr9+hzdc5he1sW/9X1tEQu2E66kdNLlrMwOwaOqNRBXB6NMszOuHM
+HSzmqps45w3YUZZivfQEO6QN7wNuYOSLFEs/Yl9KujHIu8V3UHwb+ZK4Sfcj/uu/
+uOyy9Nkbinue+VDnKK8u8apU5njiPFreIBz1FPII/GiQuF4SmOiSuMiuWRPacGUE
+LCvXs1AdRWUjayEeiLDRg2l8gIbtazT7Fd0zWS9rat/x/UlrwGNzAyDNmHklGguP
+oz8chgm+CVgIRbf+XXPLbvBuKDVflJFJnoTtwBu1AaqeviAej0ETGe0tqMKZJjZF
+oMM0HVZkuhbf8y4uxQIX1J+yF7DyYZWkWYADVWi1uyve1G5yXRlDaEw0hdUjUeAe
+H1UBHjrKIfIHlWdpbrwa7o848zi8Fx+eR0QKnyPLFrsawIUjXJu8K2fWmQ4RCXyG
+6+NDPOH5m8ywH7CtQoFTAK4C6tctT7FxNiqbWIP6MUM2g3GwmZy/EoVA2AHKxySf
+b5NIqZE7SoGJHRdoBZCZG7WGQtXXWK53IyQ5BuNiPy7vsylzevM8grWNmrBcDzi8
+u53mEvgPthWtkdxD5Ap4e8SFMhI9k6ypcSc3TmBj7WMj60nP86xBGQq4hApnBHZE
+kQAbNlNgzPFfw5Ap1tx1BifqJmb0r5hMnziPVkEEBpmOuuwXsDnxG7bmAomOz89K
+3DHe2WdIselXkNzJZJHV1z7z4eIGrlT915t9C4Yf7RE6xS9xi5flJ5BtBKIk8DcS
+GfHgO950E0nwQIX97cAbcNOQsi0dHUwr7Hm2958q+uBpVc1hDFAeO1mBrZdXLBpO
+uLh9/k5i+IpqHq04DSBGQUDyaXIsWbTzio+Xi1QnJ3CP612pp3XD7XcOML12WQEg
+zGm2VJbs3jQ8DQT0J2hQBKD6qFA30ERtoLE+yEGV6PzuXqaEk33sirBNPGk2qK5O
+LqfxpwBQ5+75dZxe9oGY3porG31yNiFMcTOWYbXw9Xa7+HcjEPJULSetXH3aqIcM
+P4kat+UriWyV60UuvUO+dRa/g0Nu50wISgxC46qbNn1c3M3FTLNwj8CkK+abs2YQ
+0cDmqJ07Lewrt4GtQCA3xij6dpzZOZmiASdFKP0bJqiL7cbtd+GDgg2ssLt9I7wl
+DcsIZH8AfY7M2eUc/ukF1UnJa1g00N/WbPAvlgl4kXHmtnuFUeOk8g4FHSmfphZc
+/8OI9iGk/djAhqrp210DAstsYK5K+d7Ua1sthh4kOX9vNfVsuLI7KmFvQYcabmL1
+oWPTIP1zr64UpVD3LD2lzzYoH55zRSmF9rlY99JZTkDGWxT2d4fD+yWUwQK05hXj
+XnNZW+gPyKXvR44lMYIwoAVJdOzZfDqSiIpJKfw9VbAmB9e1vNxAgigTJlvoxH+u
+UXIR2DCBN2JwDfwJyBsNkfz0OIKuqW4xUszOiT/zH0Z34Vbxecym3HR08VqdFyU0
+IXYJ7XazX37vkh0AKeD+AyhCyek2HBFKBzDfWwknofj/UtyWyUM+NVBUuf5Qp0mS
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCACert.pem
new file mode 100644
index 0000000000..ac4e8e3abb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCACert.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: C1 5C 04 71 D0 64 37 F9 10 8C 2B D4 F4 F0 91 B5 51 B9 B4 54
+ friendlyName: inhibitPolicyMapping1 P12 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 CA
+-----BEGIN CERTIFICATE-----
+MIID9jCCAt6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSgwJgYDVQQDEx9pbmhpYml0UG9saWN5TWFwcGluZzEgUDEyIHN1YkNB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7/QrlXBwBH0gps8hquY5
+TPS3Pl3nIpIi+sth4IelwQSoZHaegDK1qWdnTQjv/lJ596J3TXGnzqNuvGddznYj
+/GR71RLDV78euoXdw2VKFfE6UwC8R7qPvA+1VmkGwY4t93AvlWMvZNoevz9bnWvC
+coByRgFDino7JTHz9rqxeAumf1hU4XnwMXqbr/am/INJrbGSLqWFawaF2YZwnvCb
+4/ykemKyYf7CSaQ85WsuAMwUU2UdSVqsW2n4ATqYQWs1KUOOYFMVVHBZu4v44Q4L
+BYk8fBa15ly4LoiJeqjKpttt8oyNktCEhxN/j+5zHKgIVYKYzd0lz6u0isRrifee
+bQIDAQABo4HNMIHKMB8GA1UdIwQYMBaAFE1nfo3dORmv6CbeDgE0eLF1ENqkMB0G
+A1UdDgQWBBSqJpQdZA9+BbxdYI0HV/xwlWZs5zAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAEwDAYKYIZIAWUD
+AgEwAjBABgNVHSEBAf8ENjA0MBgGCmCGSAFlAwIBMAEGCmCGSAFlAwIBMAMwGAYK
+YIZIAWUDAgEwAgYKYIZIAWUDAgEwBDANBgkqhkiG9w0BAQsFAAOCAQEAaYLtBvHj
+nfmFJ0JXZk9449d+fjF+N+jz0xgBn+8jeIDUJwYd1KBIjhMd3/ILnnRWwt8pNwXF
+HeBs7GEoFuqFmycVd+aP+1KO6noitwU2os8h1yFzvTgJYN/MUaTYUqQRiwYIy3Ol
+ZXQhYHCf1+7qjfNkQ3yqY9YCh3rRDMliVtfACkV844ijTOyUXP/RXvpYkIzMW0jb
+rFtIo5pJ68EfpJV4DA6yA9raBAyuxTXxStnkfzwte4pTwXivLzp/5mDe+myBXAzv
+7WThsPpxuc4yL+KItZPS7HebwOSqDRuOMyGi5Cqn7zquvphTfi/poJQimamBCrfS
+DJ62v3/CviEAZA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C1 5C 04 71 D0 64 37 F9 10 8C 2B D4 F4 F0 91 B5 51 B9 B4 54
+ friendlyName: inhibitPolicyMapping1 P12 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1DB575107DC6C9D8
+
+yEB2NyCU+noUIZfPaBM7XYczCsK9oAh3RcSRXRX0Krt0Mc4MvQFKDNA+RsnAKDkf
+Nl7FdltTfIfNp3OtOLwqakOagMJBBUqIeDm1+MZtQRcP4OYHV1UKF6Z7bdl9RjfL
+21eeM+hJIJ7avSfUbuhzAFDLoGGAfBJT+n0rsDXIV72EFdeyGmPSXsispSQcHjcF
+GCn9T324r6rnbaTlP2a7tPAsbMSyeq485DTAsKA0TVn/JLXMiNOY2ihEpOFc80TF
+g5LGJhm4klLc+QQykYb5jxBXSmw6T4Z6fqqt5ry+v+JClWg3ohRJGrXpsH8mnGtt
+x5Fqmp0NI2dxHbfYMzq7L5TERirgGcMfH4/DtYUKv/ntBWECckHp+HrJWGCf6T6L
+f6dU8qv/HPRDND1X20SIRPt9kUksfGnr3tA4AtCHtRaJh18bOqYI7BFzMJBMU3Hf
+gQQkRk1xzrF6EgTsN6q6utyNJ+dkP6jLzYKDhajSYnvViJvi/UED6vx7kfPyMo/A
+AZSG7G1ptJ5sTeY/c6gBD5BQ8XhW9BII7aVIPHMJJUFt72/G/NtClpR06AhIs9pt
+z7yL9UzPf8px3KBkqCQGrvJmbTn+KFxQlguLUyUxzhz6QyVF/QRysBsL5SdkbEnm
+G6eVHRdRjIUD8hGujH4YWu6B2U8yYfbmLAmJoRY2qNyrVaSDEUJ9alo5Nx9t/lXU
+PyVXHTmHh+Fbh7+ASGUd28j29xvnFAq4GNxcJghIqI3DwJLvvDCNt9NATYQDidzR
+8uPSuVEwM1C8OHX9pry/wcmlgf8Y/LOBEkESKKlRDzhmMtQOeuhaviLL49WkC/9O
+g5LmnMim6kRd+Pzk5JmypbbYKOmwIBPEqV8IMSYvO4KhgY2Y7dYDUJEgSbToOvGl
++TLJmS+hK+PsnEVmVlWMu+2d8biw3LZBzOudw1jHj/2Xp9SASBC4vLkap5VM/2qr
+z2p8EnlziMEdLFqwfCjtRM+xd3sCwXXr3HiztyblPJqs/HlVHK3amkKkSfSSDMP/
+7KO+kNewL7TkVO7nl0UeYIMGGtxPwcjFchn6FZq34IyzT+hOB5opACFaajZRY426
+vAgP4Dkahwr3u60n0nCcazVROD5FS0ccooopyiUEZwnB4V++nRsKgToe6WyndoVv
+oWkeaJtr6wGvLb/P+mwShdDvAm52jBQ4Sp5gEH7/b/sGRXaH7uJd/BChD8dY0JAY
+2E+lVni8d+PteKCSbjItFC4vD2eOsCIaYEO1SuxOjfIRAfVAiLa7or4FMRgv084b
+FOQyF5jrh4OL0al9osB90wAdJHWYZgNImJJLw9GiWqGWNf1RKrTgnL5mEcpLJY0l
+JXpIPJh52/H1FJpC9AQ9IDsW3ewjkGQR1k/uXdNmNePRHC2bCJFIJuA6e/J5hypu
+qanrlcQe5kUyFl7C9Tb3yT3g5yJWEloKGjkaTH5zBECi4/jqT3pWWxm9Fj2g4iTS
+5iz80saAAcF8Nj1TnFjiCoW7ZegIvM1pRaB+ISpXaUp3+zxYm+1RTJ+Novqz8UqJ
+ff4QNdQ5/vtY6WEs8e5LDhbPG5zbQo2hEONTeq8tn3pvh0xlDSoBSy91m0Jd3Q6F
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCAIPM5Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCAIPM5Cert.pem
new file mode 100644
index 0000000000..012f19d8c8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subCAIPM5Cert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: F9 BE CB 0D B5 0B 0D 95 48 69 CB B0 2C 42 85 20 A1 0B 67 09
+ friendlyName: inhibitPolicyMapping1 P12 subCAIPM5 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subCAIPM5
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 CA
+-----BEGIN CERTIFICATE-----
+MIIDyTCCArGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFwxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSwwKgYDVQQDEyNpbmhpYml0UG9saWN5TWFwcGluZzEgUDEyIHN1YkNB
+SVBNNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0cg66AzOSJwdQr
+Hj5jFNh8E1lyBSK6cIPyB102DVKLKmj4C4QpzcXk8/15iEOEVks/j397JUsyqlEp
+ayfdGo1BNHq1oi/o0BfHcsybXcHmhRYieL3xUGcl4+9dNs2086nT5ZuOVR4grVlp
+S429Rmdtny6k/mpAc/alvPmsgahUsSFFh8LoOgqPriVgFV/ifGBk9ig8CQwxccWB
+JIvv8tFImPOxtaTE9a1bPV6hZbDzTIRxIz8c2FHtjPnI5eWsmhBpQ5/TFC+I7RJ+
+2nJbgS9jo1J39J6Ll04WQVWREQ5nH/XwdmorkPJbURNL7XosTV9WaDhodZOkcPbk
+Czvf0X8CAwEAAaOBnDCBmTAfBgNVHSMEGDAWgBRNZ36N3TkZr+gm3g4BNHixdRDa
+pDAdBgNVHQ4EFgQUHQTPdicHjyI7wvSCLu7m3ROAe1MwDgYDVR0PAQH/BAQDAgEG
+MA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0kAQH/BAUwA4EBBTAlBgNVHSAEHjAcMAwG
+CmCGSAFlAwIBMAEwDAYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOCAQEAPh/d
+V6FSzVZTO6s0ttZjFxM+5Yyi8gU+O74rUPUwoCo1zHQHS/ElM7nzk2SMUyW6/aoG
+W3xNGijWrYMEBb/LosEjPbB9Hqct4pt6ahT0oE62FUI1J1LBkxa0CfCouLzoN/dr
+SBLlsMtrYuDriGmr4GIF4MZAp0DgSFP9QcHuIWhfQRMJxNBmNT/nFbhJ6uxJiLoY
+qaklau2l2aeEIa63d1PSwlVeyPYOdDFivB7i705e3mPL+har6GNQxpKVoeoljJv3
+SJjAzw3TfDezPKALmsHtk7qD6O23r4+j8q/8cQqfB83/aL262oSN4Ov8vNvlHV1B
+0BXgLEcrIP1K4LpS+w==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F9 BE CB 0D B5 0B 0D 95 48 69 CB B0 2C 42 85 20 A1 0B 67 09
+ friendlyName: inhibitPolicyMapping1 P12 subCAIPM5 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7C82229E00AE2D0F
+
+3DC2eXeyxL9Jevjc7678BxcxtMRxaQS28VRbbDZm22mudJsNIiavCQ6X1qkw1S7J
+OH5t5lTKqq6mJIsiHipkHcjwJYZZzQ+ZtYCwQuXx5UB6DZ61OLCDDNXHx4y5Id4a
+Nnb5O2CtoxKAzKKft37xIBwDMmQT6ZL2X+WTjvznJVxOSAH2uMF/SnOUcDBiIpDK
+eUnlie6mfs5CY14o1J0bETX+/XTq/05P27VkGFOFp4E0Kp/fnHhRWtGmLollEmut
+JcPh8ckEwKmljdydbklYDSv47gpW3Sd9dgwYZkqqprlPizlAXJT34Fp9X9+xOr4e
+1QM1/ZLQl4vMNWEXwtMaBtXTqMk2Na61pt5AAyDwRibGCnPrCIS2bd28L8R5689O
+SlIdzdW0SqIFul6MEfNgi7Rxv3ZXyeQ8rgN2fII32N5agRws87rl0IDDqUFD6KDS
+Pz/5AG2h/ypBcdcy6AowwqzyHxVOLvMt0A0kQPMjYkF3P3DZ2SVhrThqmD4o/MZr
+XPbRF+L9syVaggRkED98il18mZCPzIoVE3ZMW9B5pAnzkju7X5qcuKDfka8p+i4a
+vOOyNnMt02Ci+bTmqWGIQ4nICHuf6YzNZmn1EtKxyyrY2xlIA9hZWL3Gn0qbqNMf
+okGXR0Xk6PyOXjyOt92do1ikS/N+MvTCghLzhz2QD+jSteQwrAoHarAcDZlC+nqu
+Owode5ybICY+n80FoSLw7TjtBsyso25K+hMgyzUiLrU+hEniDrhitPDpKK9tEQJJ
+HyISS5kWqZR7Ec/qKzhTqj2gb6upSQyx23kQWslI46/YJB3gF0Z+1GUjjgLLxwVo
+HPjbyyV71B7dMTyB93JXggaltwm3SOr0KqUg4+FFmgJfOFIANDX7oZEhcA4kyvaL
+q3Edqsq1G46Wi6U9i49iNCliAeM7N9LI3sQsDPQafTO1pjJ49UmvNdgUQxORZPD+
+ZYJt3I1w4ZDlWNl7F6xADOKtIjbz47bkJhuFNFnbyqXMQcq2JvC9qO+RaB3Hoe9U
+d8A5gtvHcFxTVqC51KzMRdhH/XV8iNh2snWrAEqHeiDrRfGQdth7wXO0FXEmaFk9
+LVXiaUYkQcWfaMV7/vI1WiTmAcbCXLqolIykhQaZXECUWzj/kqyf1nhMo2jY4plr
+G7YN8r4RFeHiyV4V490bxf95kyY72Xs70x8YDc0NPPgaO+ayPab6DJ7G32PaDsks
+A4XR/Rm/f+IwsgJk0EwsaJ48Q8nlSad/aFGmLGDGa8blbA/1bzHUAetglBtRlsN7
+5B+Cpc/J8BPU991a3OOafJ/Izknw23OSlX4yPuruH/S4h07vI52GWNXXkRYj3+x2
+qNjg6sXLbTopHeEVGhTrEzfrQnmm+E/fFLyeqCicqAHV72IKlpjwFqjiW6Rpv/Yi
+8NCN5cho7dQPAQKbUzSTj75cK++IL+4gre3U+7sXMOFQhUxNQElzZNR1g8R33Rz2
+XYnmYQk8d9sFJyQCcURZEn1lI+nfOtDXSb69z++VzYd9VpCdq8nnCmjQIRwoEtH0
+USRzbDmU5OuAnM/cL+2kCl4+NDRcHraXZeKNQG6jnXettVattRyOag==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCACert.pem
new file mode 100644
index 0000000000..cad13d9146
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: EF 94 73 18 7D A3 06 B3 51 5D F9 7E 0F 97 5A 1F 10 20 44 7A
+ friendlyName: inhibitPolicyMapping1 P12 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subCA
+-----BEGIN CERTIFICATE-----
+MIID4jCCAsqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMFsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMSswKQYDVQQDEyJpbmhpYml0UG9saWN5TWFwcGluZzEgUDEyIHN1
+YnN1YkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA41RBZsVSZtw5
+b13HlMhvwmwd6KG/vDnbeZnxFMOvUE8T75Dz/1P0SCSkix1T+G1FdanOupx+Nv2X
++qo0xHV/tdme0V1AEbx3Rbt4fFJM8OZed/YpoRiHrl/yojesRZv0hk0GO4lOBgxH
+ouKj0vXbTIOFj/3oD1q89GVUpkShTUMRQzL64NKhqiPP2hkQIP0O3heR89nqggM1
+/1oyC9Eu3ShvcUtdNLD1MVdPxIQJ3ytC9x6i5wFJVyFF/H7YuREKDzeXt4Tb0ESr
+Lq79pDFTOiU64au28ClxKNgOZMTn+vKKuKdxOdqkbQn8jQyws1YjPPoilWxoC0aB
+Ev32rnqHXQIDAQABo4GzMIGwMB8GA1UdIwQYMBaAFKomlB1kD34FvF1gjQdX/HCV
+ZmznMB0GA1UdDgQWBBTXgFwTi45BdroKtXNx6KNAgHQO0TAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHSAEHjAcMAwGCmCGSAFlAwIBMAMwDAYK
+YIZIAWUDAgEwBDAmBgNVHSEBAf8EHDAaMBgGCmCGSAFlAwIBMAMGCmCGSAFlAwIB
+MAUwDQYJKoZIhvcNAQELBQADggEBAFMmz8KB5cr40DimQ006k+qjMH3kjROwVMfG
+CFQ6dBQawNlZDTw+1QTFc8AYH7kBFGY0UpjFZOVBcraW+FmVFEekGN7a4EQ9Gqxf
+/+xgUSbQF4PpH6G7jqCPPJhmZX7i1ByEx0/FD++2QAd6aOETOGshp5o7dy5SHSvC
+BWwmb6XTcP1+gJggvVdQFpRSdt6l+7+3YveSOhhfw+z+LvLWwjqAhuBdvvON9qqc
+uWTkj7U1wszl5QqbPJcbvDRLEkIccnDnVDBRm8rY5lN5S8G2nODVQXG+58/0nytL
+6yiE26xchmmFEWVzIwWfCUbBtOM4bYtGgj2Os3O8RRBzNprZEtE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EF 94 73 18 7D A3 06 B3 51 5D F9 7E 0F 97 5A 1F 10 20 44 7A
+ friendlyName: inhibitPolicyMapping1 P12 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,17F51FE552D7C4D2
+
+0ZrGdJuzBt1+mvHSivLi3QA7Hc0rDIbrLOlqI7LmAfw/zSDEl/dB8Xa4ebaGmhqn
+t2MJoOz4sbqO5nKRJxKDgcipk6aSvWgIIjfc2yWlWCyFcSoGSdWm/uovfQiyWQg1
+uk4jOJrhM6DaaOq/x0HXxaHa1Y9Yw6DHdAZUXG/5Dh+SGIoz/yzKW3J1kRgM49Qy
+4zamlPa62lXvkyXGLCzxGV+9gPOq0TbDh9y98a3v9rGpu6GaNQv/GXvvqT3dIQJm
+VJ6KFt8IS02GR1jbOm1zdt0PITJTBqlutnXCySN6dPYrPVPAR7PR4Nh0CjTQLuam
+kwBk59Nkujau/srfVYLZW4sMM3PGAinHKysSvEKCdqp1qovpoEqTsE57Dh1bg/F0
+A8lDXHErmoPbDTKJdQTLhI6NQ3MQ3hpzUw85Qi2qz2QLtBfYk1PvYK31/SmbqW6Q
+bs6aW6eyxEJFEj/z5Drd+ctLkMeifpKXuoS2eci3BLBJkBMHCSNDTwJXBLCt6uK0
+yAcsDhzIV54iKeTI6fCSo5sGKr56x2GsQa/q9M2+2O8Vj8aUcsivezWdWo3Y7xqc
+cfUZqrqql9Wa9RqpEk6ZK+zG2M7y+sob8S6DYxqfWGsCl26gedxphYbO5gbDUko/
+fuigh+G4z2rryKAHznTYo57vcNgUeDVxMxHMbD4ZG4aumg6810ZmPNz3YQuzJ943
+CZflKcb4GTgGZMTGuv6eDPgeorGyrd1Vs8Z76m6bRzOk/ZOPISFpwG/MIC0XgGcG
+GYRoEwBVyZBnHMxvPbgfKJ2ua9u1ap6+RMOq9S4G/bjzlPkBH96PTR6oUk39RpMr
+Gk11HPtzxT9Pi1M48sb/tf/pQzNAMG5bTszzcxJPadX9tJXHKHToWJUN4nv4apea
+vNLzT+cGRIKs68ebhHGQJR06QG2KS4l73BSy+VvsaLGcBGqcFMu5ikajJ40hDCQv
+pGDrcaPUyuc2TR8jcIqTIIGpoi6/mny4r3zh2a4WeEWvzXL8WQkpe8N1TmzK/CLc
+iKGJs/Y3gfmpSsEHcthAnXsSoHRQZ1lYfFpjKsaS7aoqTDCS2zPKfiwQSFY6K4fS
++EXk6vDFxuhUzFYSw7os7PPQ5rXIjLakiE6uW1R9duQQl4amjzQy40YUzCoLD2RF
+K2UztPhZriiCmwEGW+e9V6o7x0mhnCGrlZILjb/An8XrGVBkBsgR5ZGab5vTdDuP
+40qIyUMwQZqiET28TnD4+3sv6zmbwp4+J7RSCvBuFsCfiVOmjzBqQeff/GUj4fYn
+vQVej3QET2g/xgmdU8tuRiV7dxBrNMkql4Si6ZKMhrVzphQyvzqNajj24L8IuBSr
+SiIA/U8H1V4kEzgQT0cbIFuRCIlpOWJbLTunKF22U2gHyHGTqtNdmRk9Bv+f87Bw
+0rvUQmBTkgQhbAHFc6Tlujd9Xfc+c9Lgo6iWeC35CIAPw1oL7aRiiyMt5TQk98rN
+qluKybCi6vD9GXWhiNXgRNux/k/3b2zAdS5Hdw6J0ZokLbEMwoEKo1lv30VTXI2M
+UXm91dkANflEU+NPIf6IJWVdgmjmFmYjG3RAUpfva/kAiQoi/jqGTO2Csr9WUsia
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCAIPM5Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCAIPM5Cert.pem
new file mode 100644
index 0000000000..c7f4852e9c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P12subsubCAIPM5Cert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 29 F8 58 E9 54 9C 19 A2 91 CA 1A 99 99 62 A8 45 12 30 F0 BF
+ friendlyName: inhibitPolicyMapping1 P12 subsubCAIPM5 Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subsubCAIPM5
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P12 subCAIPM5
+-----BEGIN CERTIFICATE-----
+MIID6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEsMCoGA1UEAxMjaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxMiBzdWJDQUlQTTUwHhcNMTAwMTAxMDgzMDAwWhcN
+MzAxMjMxMDgzMDAwWjBfMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0
+aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMmaW5oaWJpdFBvbGljeU1hcHBpbmcxIFAx
+MiBzdWJzdWJDQUlQTTUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM
+GmJ2x7yrfem6iySdHRgqYcT8hBb6YP7cMPaItRkU4vE1//h9uAPociee8y44Jb48
+/sLrI+JP6fMT1HkxaKMix9R7PfZyh0wGB2QAfEHcpm9nMLuMamcHLi0O7Mk7vsml
+Hxuc5mO9lt2XQ8f87NgZ8hpke8uCdGUvhydGR6q0GBfJd301D50GxUjbgxtuKAO4
+KNF24bW/sXBGEFG/ryOVZjrdkKSMl20HCID7pj8Sc1rHPjX5o9ykRW1XlhsMvQIA
+a4RzOh0BXm+zYKZbtJCtZrgCOEW6pdqEdoSU+ZybrE6jtn4Hl4FBLb68J+FjfiZa
+pRXmT/r6vGKQGx7zVMFJAgMBAAGjgbMwgbAwHwYDVR0jBBgwFoAUHQTPdicHjyI7
+wvSCLu7m3ROAe1MwHQYDVR0OBBYEFBKHGzVn8LyhoDa6FagpGe0am1twMA4GA1Ud
+DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MCUGA1UdIAQeMBwwDAYKYIZIAWUD
+AgEwATAMBgpghkgBZQMCATACMCYGA1UdIQEB/wQcMBowGAYKYIZIAWUDAgEwAQYK
+YIZIAWUDAgEwAzANBgkqhkiG9w0BAQsFAAOCAQEAJEtvIEyehDWiKJvojD656dbF
+3VkkvFiovYk9B0du4rrq1+fHr5KW5uhKO5G+0gnQAmb2s2DQMWDooC/w9UOzuagw
+kD6Y2GswGG749QOEEOoYBcuU4AgmBQjp8jZ8b5WznQHKDlk0ZtBtO61Urmd5GJ3u
+Nv690xew+zeYqXRWtR7Mjr+vOUU911TgfTF2zkUoY6UGw43qCz9krpJmoQ8Ky9Bt
+cOYXgSHBOm3EtA+KMIo/mmmiu0zxhvBJTKWhAsRpejosqargDUpmbOzj8pw2tcJC
+4K8mBvz6OFo0TEqoDx5LOZkBD4u8EGjSU3gc2Ou6RUL453iKyMN5ID0bRYFn/w==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 29 F8 58 E9 54 9C 19 A2 91 CA 1A 99 99 62 A8 45 12 30 F0 BF
+ friendlyName: inhibitPolicyMapping1 P12 subsubCAIPM5 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1E8743AD5173FBF7
+
+uGt4kG3TLNuXx7oW+Ytfnfn3K2K4Hl4GjgtqiUbrjv2v4S5/j0p3keJi7OC5O+06
+J2QGG1vrdvvPZVOEtejv2fmEIClvxmTLJWWbQMIx6VxzhI69Qp0gNDvFbMS0T4W5
+C0aPO+tDSFT6HYl0kZA5hNRcCm1+ls5peps8yScgYQVUx5IUoFEYXaPMqD/0nNBD
+4sid+aKL2AsTStQ+9Yht3BNtN38JSFe6oabPNrUU6dJ4JzU7Zu0U11FB3HmdwiO6
+GP3G+vx9YT2bXtbBZAKx2aCnHtv6JWyWQCr7XtpsId9BEmjQdurqQmUoylgzQoFY
+VA/WR4efK9SaTt44FXjLwHdnyMwGX68uf/kQNKUxh/iQhjTNY1uB57VImpCkseu3
+CIJ3+/eL3gQ3UnwvXgLe4+z7oCnvuS7fttmgn3ryCyvXx8oe9jNckUnuVOf/6+T/
+yyxyVA6N6feLux7wBcyrzkFCbEUuLAVI+6XsQ33ctHyBXjhyUZJYW8N/4kOdzX78
+PDEIHQNUtKAUFX1EPRcXeyleCvS+mO6yPQOdVaxqb66wLr2iBoIgZ2WGt+KAmA/K
+wzNZTjIWexl7A+yO/GcCIz1ZK67kwghgCUwFSwCXLzhcy05rj5NTcW5qhXiKkTac
+Q7hIaJuHm/4cQG0XeyaqAkfRjjhsJFVBR0Eto32s9qOMTf0SFRrzGR5UNQgXM4df
+T5w9qEPp/emthhgyrc7gll9asT8sY4jW2nO2kNXIXRZhkwbe3mqdfmeBOauFtH4D
+cmsw3lx88thcfLe8gpYvwHUjfnZ6dVeZTPQfuiSfdffEJkBILVR4VZGanJYpwH4z
+yBM2tsmESHBC9VcDi6SNYQXDJctSFJ6m1XokUTH7DQgFLLqDZ1+XyJZEPvSWCdkO
+QNQttez0xH72eohaq7E+q2oFtAIGEmrF29q+mzcTQwna8sTN6I5M6J7q9yE6AHgd
+y9sVbllmj+pwDZHJfqsjf8xZsKIgxB17DAwfVk7t+1emJHL1V1QWXw12hgjx752+
+4R92j2euAHCX3gt/Ua9Xzr+la5agV6axb1PnzWrMbqluYygtQ17yg8qo1g2x8ByS
+f0Rhmq7dX3ekT1jkbE7+JMYeUHejlQufss9im/SKHYJpDAJSXdH60qD5YNPIof9+
+HSEdS9qUAUmDTz/v9RrjvOjBYOrqMfyBrmDJkJ/Cj7A0jxo6thJ1Ojqequtdc+Eb
+Xui8wl6pPbPLnYRUbduzLPOh1G1drzJLkzLpHPsK6RQ7SQ1zrZ/H1GqN29q6H8bW
+Hig2GWmBxAsq1DkHS7EHmshdYPEQzV0875VBG26dtIuob1lNLrYC/UkCieDS29GS
+cpQmcSiCZpI0YsJge4dZsuHQrdSMd7n4GRxHxycpbeVeJOCvlbdmZv/A+nesjFHz
+7/5tUxFa4fAC2lXc1JFPlPHTYcnj/otz3XxfMfBb8YJfrypVGjbkolHTTRQ47kSW
+gATt+rys1HckOsgUOe1+PrvlkhHFpvTlyTppZNPo+Jt5/ofMKgttoFN87xqwf4Eq
+D+KCBH1oHeZf8/bJqIzqLpUomgyJ0jM6le1Qsgpe3TOR11ekjf6m5Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1CACert.pem
new file mode 100644
index 0000000000..01c7e6c429
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F5 3E 9F AA 0C 16 6F 7B FF 9B 61 7C EA 2E ED 6E E8 2F 01 AA
+ friendlyName: inhibitPolicyMapping1 P1 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBOjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJDAiBgNVBAMT
+G2luaGliaXRQb2xpY3lNYXBwaW5nMSBQMSBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBANNzchiVXFu3PN6VHXl37Lfl6CWd/nzabFywiheAyXJQhKpR
+ijrhHUNfWUFZpy0s9LcXQCibTwAXHTvNm7bEsIxP7bZzBIxyJXkrNMO/OAm1xGo9
+JeMfADrtJWXuLzLyLs4OZsmcjMConJwClu5OoHRu5PzFM5UPg+dLdl8P832Ug9ol
+Cmp+R1Dh2euZgbuiLkdLNdy8COfNFYDHAm8GoqueauaPUMWMH4G4GVTkKsvB6zoB
+yV5HN37kek/vaLbtm3RjCu4Wp5/kmjbHMZZqq3/8m8FGZykna9s3vVEcTPDS1A5h
+hkzKi7qaqirbvBFzU8LLtf8kgSGo+aABvGTU3OECAwEAAaOBkTCBjjAfBgNVHSME
+GDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUvradvSl/GqHZi+Gk
+gGiDKK1K8AEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
+ATAPBgNVHRMBAf8EBTADAQH/MBIGA1UdJAEB/wQIMAaAAQCBAQEwDQYJKoZIhvcN
+AQELBQADggEBABSJW2Z9XMCKoB6BKyAvE0tkrFt8XNnIHpUZDJPUKA75KgTSXXk0
+Z+/4YjCsbY3N4V2vYWIBRbQDzVt+ux0E/flUUiD7cXdutJ9/EJgzZurplxbtwX6A
+dauSywWwlpMrk/l60ICN3yTfQSauljnrsTcKe9TqYptyGgSxxrEPXXvQ/gx8mKhI
+Y3PERCuZb2WYzbYQ8cyJe7Q3HYLFuEWgTN6g2ZfCRcu4XMBsmu8sT6rNL0U4OOU6
+ZFXZC0EejThj5NvNPYzmn1ROfgZvPYrNAHJjQXcCaMBN6odbLkAKYmGaKRMkCUPQ
+BS+EhzDfuGxj2JFbH5mkVGfpoLeXvS34kfM=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F5 3E 9F AA 0C 16 6F 7B FF 9B 61 7C EA 2E ED 6E E8 2F 01 AA
+ friendlyName: inhibitPolicyMapping1 P1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,02F3C17E34F9B24E
+
+SG8hQk9fVXTK4pfHRIV1+txw6uiHgpCzu21ObNqKL+mJlQh6qDsZKRcAGMlCBZH2
+k7lZkvPLBQNU9k0DZWPVy395+vmg72Iz5J2YuPa8S6DoC41CLgcIsAtZmFEOz/4d
+/VkaE+kUWVEFCgEu1gd6+dziqEp8nVdiRxAzjDSzvxn+gS8p8XT11vQDw1izKbvg
+Q6r/qre3c0FERgJHoHz6+T6Up3+YQ+ZuDIeYXGuhSsnM2EbF7twB6zzWxZM9OOWs
+EbE7V9IgWTrpImtJfrWqZXZjVSAH/pxQ/zI/23y9cpRr9qiNhmv02yqKSUJHYIys
+oPfmG557/fas7N8/2kqrm9BSd83IeQQVgL1GEYhU8Ji1RYm9aftDed6O+HTVzree
+SDWrggUjQrFisgBasXlLanakJm4ALN4hQJiFGbixZ8eN71ZKh4+J5QzMn5QSUgkY
+8e6rW/Udjq7+vgPVcX0++UziJgQV4YZMd1Z5WCUy5SXdcqM0flK/0l2nF0VGFywz
+ShT2PJltiX/b6iZlu5HKd2hti5R2VVgl5RneL1QxENmdploSk5aPCgvd1iX/ZUOv
+l2LmFEiwFStXI8oRk95wCOmmTvvWl91PzYw6SwurMQZF2SRr4CMeIwxaZRJRPImi
+TPbYPicxkJ1p3wKWMs/Ph+rxAupWiYBkCR1qlpMt6dndc9ZT5+yj1G2KWIrkw3nq
+/LS+YpO0ZRKfZSSQlY9cwlc580Vm/aVPmhL1gc/I5puQHIcvQ6Z/1JY8SQTN+t2I
+7IjhwohoismKcp2kddPxDo/mbFakSnIJ+XC/fkPeE19Z+R1zM00i6YyjOLIHbybg
+l9qlDjRRrKSKjiMJacFo+X49HHmX6A+OX5Kr032GQDDSawpkPHGZk+Qx7Jvm5rMN
+Jjr7EgbKO8ejJOXVHNkCMEsX1QAKC2ltYjMK5pkSoAL9otXGwnuvHi/9UvzWhd6l
+yj3b4REJ+fXpNW96QbfLZAFUY2bi30Ov+yDWPLXkcR2LZaEkJrTPuliBDAMCOGk1
+w+SvnJozmiEfOf9FSD3vnjN6y2goQ9FRhA+6NyaUpp2QrOzbaWvGH2MIH4ESHkvZ
+t+5IedePPbMynKdS4CXVVBX6aT/SRwDPuF0RIxOmcEl9ZB1zLT1D86Od/24UPlRI
+HkWslMjNZEQoNfGJBczu9AZqZ+rS3zStlewxl1drwcDg4FuInySgMsdyM9CQInDI
+j2ehA/i8O//LsJPRfVBT2GwGtl2m288If04hTUg3oLHse9p6C2ZWejN+U4/8xz/r
+Sb6ckHVZ8Tl7gelC1/CRYxbvyO9ac3+LJ+IZSHvPDHfImvIa9AEcACFDWGyPxmgE
+90xK7NkZRyKRKGzfB53n0jcYL5oReezNggtHVwrhDmTUHJurR8R6cB9jAmQiTQG1
+uBxR2HoLpRGovkEy7/kNAzo+3YCUVeRx+qfeVV14SYU+957KF1PZ9hLkPN+G9MY3
+6EnaGyU+w5Z5tUc6u/eT9eGlUXz6nlvSXXZJeT8FmAsiIpwI0GR9DvbU9LCBm9+Q
+QSiKrsRG3exdQwj5NLEpdkv0tasTH5hI5euev5inA1+umbfcd2kW0A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedCACert.pem
new file mode 100644
index 0000000000..4c966d02aa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 08 C8 4E C2 6E DA D1 4E 27 3A 4F 14 21 DD 04 D6 FC A4 4E EF
+ friendlyName: inhibitPolicyMapping1 P1 Self-Issued CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 CA
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowVDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBwaW5nMSBQMSBDQTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL4hFAK6xYrGnE8mqLy4jasyD6TX
+qUwILdx9MxRmFng2VFoARl8eHjGWt48XdOqiGyALQ68aW6WIk+AZV4YAFWXlSdBy
+QWTCTE0tM0b2kJmxNIqbzNMBdzRcP4yPHaLXSPt3AYZgeHuG/zGBDSiCsOwXZiFB
+sl0o8u5wTeqzpSMEPa5Zs0cN4f77npYpcOsAo3r5WezL6r/nx+oj6BaA/qI/M90Q
+xGzA0RkG9p7uJUjemkx1g7aQaUMvsnXDyXOdpzAslQBy191evT+sQ4D5pabR8yFq
+vtIfkeQItwj49zXso9CZppXohWRC/HlNw98aq1bcVWhMwLkm28lR9Fn+KesCAwEA
+AaN8MHowHwYDVR0jBBgwFoAUvradvSl/GqHZi+GkgGiDKK1K8AEwHQYDVR0OBBYE
+FJfMQl7X+BVEi7OXUZLdbAE7IRjYMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AQEAKPe/EX44EHfBWAevfNDVzkd1uf4IuCyftrKHY18e+ikOZOw8KXzz4SzcHus9
+d/TB0z9iPL04fREfVICqExRqoH0rcMxxJ8td4eohoEKVeUc/1WrnH8KvdeOTj1vW
+npG3Fm3M0FHoLZFWQpbFKEUowu5FY5GgGPnnudUzxCP2A+6oXxDAhFVkzZVAailF
+tDrPT0BSk9O1/v5DCmfVsAlFYwzXRzddRmjiiLh5Tb6Acd2uJgi1bjQCYiNbZx5E
+gcgDjHuYzL2JBihShFLtFzdz9OtyRwOrsgMvuKR1erW7G9OvXjDpLfXXnFsXeH5r
+5D3Y/TMQa7VJlW08+WlEYc0wcg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 08 C8 4E C2 6E DA D1 4E 27 3A 4F 14 21 DD 04 D6 FC A4 4E EF
+ friendlyName: inhibitPolicyMapping1 P1 Self-Issued CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BC6242706B8E877B
+
+ln7ielJePx49yvzKHZOgOTsJd6dUPCs8qtjyKZCyuHD5sjdJOwkekNrKj1+K2Kcu
+dv1MdFeUyu9VjApXC9P3BXcnloAvMcHWauwyRxi84fD5MmxNeWUWN/JfD2EG8gw5
+Cnm3NdY0eXVOHtXfrCb+eUEoWdaJ7rulGwIxsBejZwUFabHEyqfbygk6laslXZqa
+95dWydtTC3cv1YKYG1xFP7O4B7lv9QMD0/+Xmxye2Gzok1yZFDkc64PxVZZybvvZ
+G3e7ExI3/Zwe1wqkEk8S5C/B87pijHUio1C6dQ8vGQjrXBTyO2n18g+L9lBJQKZf
+gmCt+ojycntWhSa5e8o3sAD2q6EN4brEBOLvK2SIhLmGOYzGTR4vOnBkrGqtux6w
+u/am+SPBvemRwsAcCIj3cAZeOwZUYtXhOKs/ArGsnnCAIaRgL8T79g++Ur5BwC1z
+547BEij0VSDY3RJChpuG1U2NoTqMNTOLZqa1/n6ti1qpZL2VLZgW/By4MHNPv7TZ
+6WsLQREyOkM2PNaxtBQ8sXTbPKcRg4hUJ+rO+65DeNPGtugfQh68MPHMj+uBp93+
+4MqtVbBS3XLS+XH+f+O3YIFAXkYybYUjxHxWAahARtWGBAHHE54ImgiCw+c8NOc/
+uXDGFGxXGA/LUf+2/QKUv/qtEzc4x0JzNpKbUCq1pFCcWMSm/LeK1QOs4QB8WKcS
+7ELBeywrQtM8TT/lfgN61KKCAwknjUPutrJGZxH0snTHOUCopc1lVOQeJr+w4NdU
+ahM6Md3pJCu8G904oiNN+2Xm3EHKFnfv+gR9J2FWnB20hVL8dZ3sgqexQ6WAVnc2
+1Zx8IFVEw0XO2AW6AZC/Msjyqw7JISIC8v9j73qoN9bSy4aE22gpcg/IA/WPaPOp
+XA14+xjxBL6A5UcrDFukCp1QeKYrJ4AXeNq/UvDhdQW7BlHOBrg5tWxFArqWA4DN
+DV0nnXDArggg0aZbChbLW/YGD4R+6vjqGoI14TA3rnND+r9gZmSbYB+GiNpYO8j4
+dXWNwI/SJAv4SNsir7AXlXwpjVtTjUN4o+sh2X2IhV+3K7jhwHoM+A3ygLYCaAA7
+sM8EiLkvkKzFzDftnAcnW5Mj3PPRbZ3Acsh8e1/yiqwkO9Ovz37kOFN4RHRJzs5l
+opYMn8zSk/qkJs2vzYcAgDbWKrX4LwBpAlNGjWE8MbAmxUAAgbXts3lclIVGVa3h
+1UKR0ty6x/qKZt2u7vlBU4Hf3civBxDR9+H3qU46yD546UGLg9XNNtr/IpwBaJzL
+1WxD60Hx74KUnfeyLDGSLADyF7lPsFGVrDFKJfDMolVHxn3is048VH61hrAmPLBr
+IASbeiv29ULIEEHLg3hmpctcNlWvMy/BwKFy98NUZ6Zz7w4qvh7amjnpC/A1jXi6
+KGKXIygZLt4UbVnVgrc2nfxJ6r9U8g0CsK/Ddb6v3LBfkmjbSEnBCbJlZxmLNmXF
+f23oNRN8LXmNwUnB/OlXsujC1KVsWxigE5kMAGIrHK9Y0lpGaIZpML9hyCb/2P43
+iDRxEpPct/0im+mueQCfWb5gGSmO3hlORawuAM5RKcZquHWQuptzNiR3JgJUkyRw
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedsubCACert.pem
new file mode 100644
index 0000000000..184d03f9ec
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1SelfIssuedsubCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 09 CA 0D FF 17 A8 97 A3 CE 61 0D 28 9A F7 B2 3A DC DE B0 CD
+ friendlyName: inhibitPolicyMapping1 P1 Self-Issued subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+-----BEGIN CERTIFICATE-----
+MIIDzzCCAregAwIBAgIBAzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowVzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBwaW5nMSBQMSBzdWJD
+QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu1zv/j9hUO9KsCMtIO
+6fmdTyGxvmTo1iBnDYkOMkunYTqq5hxL6QRQbAdpgTYLDF6TpPEl8WwYd4icjMH2
+jv/Ddrf1U4ep7S3cHeXJv0i40BR8f+UOGHv9XCQCZPWV9Czw3tlLsDBPq6epG1Mx
+U+/LOdd74z79dTHmNqCKLjO6fGogYqSin2H34OVAABxTSjdoWYFe+myN0RDgsO4v
+y8UZb+ciM1aPw4Q0pkPI1tBkJVQlFdVbVawrOkzSLUisQtfbJObFMTwKaFS2JYr0
+GWbBBhH1IS4dVh4vktIQLNMCpjkTLvoFVO9KH9VKnZzW4UrBcvqbW7zrkKfr2eD4
+pB0CAwEAAaOBpTCBojAfBgNVHSMEGDAWgBTzzQc/gzDTxwJi2ubKbAGlsbaAyzAd
+BgNVHQ4EFgQUWblsZOrzrpbqtlFcJY87z+31kw4wDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMCYGA1UdIQEB
+/wQcMBowGAYKYIZIAWUDAgEwAgYKYIZIAWUDAgEwAzANBgkqhkiG9w0BAQsFAAOC
+AQEATJR8hHpUS/Em9JJ75jdfOIOlmBAgjtQjqMjH0rZm/h/X0whS/3ElXS9qS/3s
+OuhFKeYAaSa+2nvKvqHVmeHRSAOAKZHz5AZ7vCSikh+KR2FxMp5WM2cqrwj7q+cq
+d6fHaRrSbZfPQDMu/rBm6j2wYLb3RvzuuMFpEkSgbbqSNFVAmZrLfBsP20yy8NLz
+HXwInqwU4lI/02ekuywzm+ZRdvDPQWt7RxomC8KWHR94tCsFtltZsM6r+20WKD94
+7+XJP6fp8KeLFQkDlSI3EEaBGjVJwGFrrJ3GH0AkB2u9iw0+G1IwGdTwn4P7tu8L
+UYwi7y/iSXXcEQaIQAdXEPHVnw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 09 CA 0D FF 17 A8 97 A3 CE 61 0D 28 9A F7 B2 3A DC DE B0 CD
+ friendlyName: inhibitPolicyMapping1 P1 Self-Issued subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4FB634241EBDE81A
+
+KKVyMfvbouesNkPhg2EiIhzc3jKkvZ+wiW8qoggxoO2k4Ec6ojnWI6KU8oIrFSqH
+tFN9d1EwQ9xe/U4JSDJNEKcABDZVITx9a0RvB8KGBy+c9Ffnk6gjbNWu8f/msB+e
+2GDqjNt4cE+Yn7Md80AJ6HVO/iHbrSJAaQvggZJMKbjuPqQSUbcX6kbWA0DylCED
+14Eoju8yYkgza0LM/TZqlW/1i2qXRfQeGWIJ2hns/9OD2diNjxRoXtzTd8P/VV+h
+2RAIdqj+ePWcZxrzSARa0aH/owkc/z3Tucw8IoUOHB9+ONrbHKGGz/8gggAP1uMS
+Mbdb+xCsESEUn5fIsSKglrzLmZTlLtn36MdIrrg4DVQOzqFgr7PeJLvsFk8LMA2k
+xWo6c5RyUlaKI/+iyVX+OIUVW5gONFQzmitQ90tKbcqiMhaXP25vjWnLZH+Y997D
+kc1myhBVNb9mQVL4E0D9MvDYMb3AqzwY6262gDDomV7QkHcVZk3cwjmCAy/zbKVF
+mWQ/VGlhX4bGTWVjBwIEmUqCh6mNfsG7rnel8VciQPM/aS6vR59X53x7feYCgXh/
+AJ2Sp7OMXEYVn073G5S+nYuyeipYka+HxjE3l+4H5G9XGs2VSVU7kW0AegzpwB6o
+XE8aZilMv5d66BGL6tLaHT00qPd97FqmmAwCaEBWIHS5RtnD9OSaOWmPxhS9DZw+
+uoDqxpmfLa8uoubZ0InqaRVS2sdYwnxyXc3dHaZgb6wvCpb/leqYKLYSUXn1unfO
+Duut4K2US/LTdaQo4Ezw9PFv7BwnllBcYJ77NsM4t7PAfyl0Swa+xwyLD4fzVr4c
+M/CVi8r4+DjIS46kbTWt0cbVB568FKaoekvixo3bhwNDx0i6RKZLy2SqNWaFM713
+xS6JgHV9BNPaSvtDszQViKglfqBDZgX5gyv18bnLgFmGbP2r9YxbiakcxZYiGrv1
+qqJx27671hc2QR5Alaysk8LImwXSYKe8NFqP4Dz39ZcvnAMrHtpeJQaby0VZpAJ4
+u0dNtO5hXv6D0aIl7cETYtDi02hp2oeIA9yfXDv64Cdw0hgS0YmPKleu1BlT+6+F
+lsTdq8Z+xCXji+45Dioz9wApozpJBrSEQ/qcrVykbNxxEml3dfVyptOsVZ7A+3xi
+kZ4zer3GR+ZZLxD1tW7UCzqrkQg40+F93Nj0kKRGT8DcixHgv64IWXtUB7U6O50W
+x5DnmkR96YMC3Vn9MQrICferdTrvpMTo+umjxDwxgXKh8+2G/2/eXbER8wTb8PZZ
+CECT9ahjVrUz4uCrl1fnZeYB4WVGlprgCkHWADw5KwQeyMbBma15jj8lV81vRnlZ
+Qk7DT/2kIURXa1R9JswyWD1UII2GlHkiE4qjLAz/koBNRpZwdwiHBbJixlwIm4t8
+C9UTC7VwFASKmmqIfLf0dm8MMg0AgswCLIf6WayS5PexHdQWlRfHYlSUnGsxkj2K
+3UfsycwJmgDHjt/8xCOBbsFoPAER4LR8A00UdTkJhvM393ziMjT0YBEkDa/7e15X
+JiEvN0KKCLya53NGtTfBQrwPRSId0dzsBu93lX1GwKvFd6VPQuiNxQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subCACert.pem
new file mode 100644
index 0000000000..13b4d54815
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 32 E2 73 0D 8C B7 F4 8B 84 42 B1 A2 EE AA F6 00 7B 9B 98 56
+ friendlyName: inhibitPolicyMapping1 P1 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 CA
+-----BEGIN CERTIFICATE-----
+MIIDzDCCArSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowVzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBwaW5nMSBQMSBzdWJDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO2x9/hMwh7GCDcxZx8y0j/4
+Ls1Qow36ywaMPWliQ8ql4neUmZciT5WfoY2u27nmkFA5HiBDGt8NMEd1dJAaEHFn
+luDroslPlbh+1dEhl744TWroaGCXETaFHFNY3jPzo3XVU/Q+Yiy2ftK0ZzSVaHz3
+Oqv52scuXm5hgFHSrt39qoJXGErlZ9S+x7t2fFnfAeO6q7evYgJQsF7yJdbNQCfs
+YnBfz2vFvnPwIXGEmf8aNrO7qgcPg1J7AlKZ6+3pYEL4bLuwUmtxcZyfT5kKKxbD
+Gwg/iHov9K/5X28xnuBHpTmuRWVoDgB3kgBxLF/ZxXXO9Y1Iv6k+e3uAsZpVLfEC
+AwEAAaOBpTCBojAfBgNVHSMEGDAWgBSXzEJe1/gVRIuzl1GS3WwBOyEY2DAdBgNV
+HQ4EFgQU880HP4Mw08cCYtrmymwBpbG2gMswDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdIQEB/wQc
+MBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsFAAOCAQEA
+WYy0yUE7kUeVqhHdNJdc55+y5LP9BKcz/sa8l3aqo7RjKOmj2cygt9B7E4DRJT2S
+uot9Gp/rHVPv0cknQ/3SDBwYtHCSKV3bB4eQp5nCiMpWaAWXamUTNqpY9qEOJImA
+Ctg7bNL/t46eGOWhixz1wUMDMGGkS+rIzf+UJqHOBAUdkEjP8ouUWBTlNsQrwFxc
+x1u1GiuxWPzIAIjOV1xtUPSLig7Sv5uQccmf0vHh2KkMtO+1dCoTbV30QLWvbVwz
+wzi1DzPMvAWqTVXwFQrYev5mUh4XJ7wMXHp5WW49qmdamQeIKImxzIsgHaVlKl2K
+eFX6REWaJ3Sv+U7KJ1eaqw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 32 E2 73 0D 8C B7 F4 8B 84 42 B1 A2 EE AA F6 00 7B 9B 98 56
+ friendlyName: inhibitPolicyMapping1 P1 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A94BA885B97FE142
+
+S1SX/VDCk4XNa9nge/MhmELKwJVJVtvawCipA0EfJ1mAgTlP8uyazqM8M2h/5WsX
+Elc/V1NoepmdEHr7xbj6SpeEZXEyVlNWeC/OZEohSDK5us4U0BxrYFWe2d6jlXTl
+8vLtT+N4PAZ7OazRk2QRZASxaLMWbVU8vLSKGSjKYbKVTuuVv6mz+6GkIj5/4Ys0
+7Vmhvx4ujwY0dwRdps9SgAPTp3E+VIn8Eu3D27A92pBCvD17wFjSTg1YosF4KVDH
+SEiqWfCfoXtcxbCXHl/6PIcK8/GTFQoeOD3uJiU0f9+2KcDT8zAV43IpodANHF5k
+FAewzywN3svc5TYfaXipQ0L8eAerQ6qRH+naWkVqNrZN5xFCWfhnpQOboKz52EWq
+lCIbQlpIiOqi6os/TotmCYbhyOrpt69VMKu0LzlWcq8Ohv8ZJdulfiTB5yCT3q+d
+1pT3wS0vZRbb8lw3Mf+hpa/L64KWX2heRX/m2mX8b6y194/oCXUX9FT9VZBFsFip
+w3sO1AyuwNmAPkivzAq7C4BhJ2lJT/cGbXi4L6DV8+JFIp/+DBUoZg+GzYk+Rdeq
+2p3x0M325ZkY4XGSuj2t9irpZ5wyh5gQKC0xqyr57QuzvEGoG+/hYVUInJGBu0BC
+YUdN0wX7HViHp2YkiF8btWLGx/6OXdVK78ZqQ+w1bGlB3ikP+bSAkDLMCBDY3GQ2
+x+rLoKmkr0ULnfYPRZ/CrvqO3bg/9Rn8rEfaeMgUpCWCX2mNfs7I2sFoKiqrw58B
+eMn3SceY9uB7ZOeH2s4nL4NoD1Od9e/oPylbceZZQUbcVRCOh6vmGbU6jCxT965a
+DEBsaIr0SnszSIEyUWU5+1W3jqeoNHwoNtiVvV7roiylebdfzoZjXUcpwpbcuiug
+/RnyAF5AVYnQrZnHEmuEoZrJWxjArUCGMxBqvVU6uk/O2DarYCheEohOB/J8FnV4
+bZoBo5+ftiP727oohqWyZQVH4rOCTy+EEeoZJ/FqeiOFAyj27/EBFvSdauG8p9+t
+mubRCfZmZ3qb0JQgKwGZNE+siGwqAP3a2vwwuSNGxoV9arF+rdlPd83zhf5fI000
+yWwtibohYrfPNzl/Zjlt3NoFJO07i0Lk/n4zp555eKHLw23NLz7WrPrA2L9Te0P2
+YQl5K5afFPek689IawcqEEpYCxhPwSukjAeUB+mdgCadkons5Ks4/bErEH6UVwGd
+S60zF4w6C3hzS2xYg3s7eJ+ek3QK5c+8AORW1T2xXi9xGzLnYbwdEZEorbElRcxr
+EbtTtf7Kf/r57Is3sr8Rgyatw2LBOjSOJKKhaYE1jMpJjqYz4xhGkwv/EG6+Xiac
+eSC+ZvfDEGgdr3hFBJfgGnWfEAUtuc2viglGMEQqkQYenV2Dk40hCrJoT5FIFcIm
+lw4LXHTj/T/eZ6c9Ki6YDLvChNTQ8hbIDe730u9tBcPk956sz1wElXFmAlpX/0tU
+ZKrsugFmJxQLSkU2aZk6kTXTI/55Yi5bmKiW64ew1h6E158AlweWSXeOaByOxYGc
+VcEmetuUsth/gAA8n3xk9mKEEGUex6tz/WFp0Ykuaiy/KZwFFcuPzg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subsubCACert.pem
new file mode 100644
index 0000000000..8f89619aad
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping1P1subsubCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: D6 93 BB E0 99 D1 0C 29 79 23 51 46 9B C8 BB DB CD 5E B0 88
+ friendlyName: inhibitPolicyMapping1 P1 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping1 P1 subCA
+-----BEGIN CERTIFICATE-----
+MIID0jCCArqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJp
+dFBvbGljeU1hcHBpbmcxIFAxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowWjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExKjAoBgNVBAMTIWluaGliaXRQb2xpY3lNYXBwaW5nMSBQMSBzdWJz
+dWJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJJrQ5z0bfU+HR+h
+7+Rok9J7y4aPRd50OEgl+SGnwBLodQ1xgyZUhJgSbIeaLCw5uYUWJedxh1TQM4Fg
+RZD5VIMFpFjIu4xg0mRXm+YomjBkF2eGCtpgjRjbO9rbjVxj01oQmtE+595P4OFb
+zXKXkb9ilbFvz2zVKJ+1aTENKJd9jB9STsNz5NTKVRUSr6WF+gn8HJofrpsQdZVO
+qQOk6GAB4FK1/0TyNmywGXWkEbM1WJeejSnHuNX1gBRjlCorwOKP5M/T5mT1KZUP
+x4Fhk826XPKMxGvC4xKNfpjlmgHGH7LpsSbLv+4UE0aGVPcKbkwx9b7W5Ot5x2c9
+urn9WnsCAwEAAaOBpTCBojAfBgNVHSMEGDAWgBTzzQc/gzDTxwJi2ubKbAGlsbaA
+yzAdBgNVHQ4EFgQUPkV0oovS8VaMRgFmeHAkxiLBA54wDgYDVR0PAQH/BAQDAgEG
+MA8GA1UdEwEB/wQFMAMBAf8wFwYDVR0gBBAwDjAMBgpghkgBZQMCATACMCYGA1Ud
+IQEB/wQcMBowGAYKYIZIAWUDAgEwAgYKYIZIAWUDAgEwAzANBgkqhkiG9w0BAQsF
+AAOCAQEAdfivFridTE3XIZBYeomP2Heqj4tX3TiDbCSCOiIs/608QnZS7a0e1/yl
+yPWexV2WMAOv9HvdaQ3HtejZpBPvc0Gmu1M45vCdjQC/4/MWbtKVl3buBecRcWZi
+z9sfajKhlZzXISyOp9GjWfH6OYtPypj1xMvqIj4NSEu+RWyavJzcVIZtVWiUBGQc
+zR3jxgTs6CzWMbXFe/dHrDzdBbtLk6Z647Co19Cg07I4OP21gQB7nombxlv/EHbb
+BajVkd+APg6NNDCV+JgSU3XXQpTGiSx0J6P+39FrRPfTJcdUIIfSUoxuTDVy4Uzj
++66fxMiAaaII4phA6fBlCj2mWvBr/g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D6 93 BB E0 99 D1 0C 29 79 23 51 46 9B C8 BB DB CD 5E B0 88
+ friendlyName: inhibitPolicyMapping1 P1 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E84DEAA45F984BE5
+
+GSWxcCybzSiHHOwi5aT1pJBsDZd0IebePQLoR+4gFHov2csP2F0zMjhrDx24Clcp
+8s/byesoyeSWgn7yr6liCI3iNzs9r6fq3soV9tQNJgomToj8wj+oUX9DHHaE5db0
+Q9hLUCTZR9PxdSCu6vgk9U1+VnsGTpv4uWSOUFWI24ldTyTn7zoGSki7LvUvZViQ
+hc1vtILHMTFjSQKri+G2ivUn9TA6igrCn314jSLJwhoO2N/7JCDEng0rqZ8ny8pp
+JqwAphYo8HMR9St6sYsL+78Yk9fb6d38XaVtxUYLTyzdeHIRAuK40ww3DqckjVB8
+5JZ9yq2d0F52QUZNO0Xdt3MCjFi4V7ihl+g324gQeopgyQVd11h6AO7TvCpadb7g
+E9/zn87b4JOwaTzLN6JGMVguuuN6k7u1MWqKzfbZXV7NKDUjK7yZFPghHuWBPieM
+n6zEVOIFHW9LyuU44Q/RTpJNoLyAjs5DNB+DG6O4zq8TZvIi4M1tikgGUDsSowXm
+5Dsm3n5+KkMFj7Y7rG2ldncLOUkr4XdNzXB3S95NC2Hp4vAfcwFnz158fO28gPHm
+jPdupJw0BqpRILLXbVmt1smeZT3Btb1QhCqVt+gZqhrNgpxf8RZZ1DCAKs8/l6MH
+jpoX8LKIrOrZowH9ToHN/8nt6ZVrGVsDG4QNP6Z6fUNV0NKz5X4w6swB5ma2Hw7v
+PADh8ZaPRDi68dmvDbvlvj1xJWanE3BD9UM2GhY4fZXGiyRgLsK32jgjWcY/nm67
+z9IYK8pkN/hQYXz6WkFD3UfxYDnVL6JJ2K3RJW1Mt1pJFfaoBGi8pnWA0cnz4Dgk
+lUypqvrp1TaXtu5F6nz5DPA9sP9OfBLr8y6A3mAJTWxyeknSmFkWeIH5BIwzMo3P
+F/Zycxtj7bGUxOyC5jn1z0BFYYxOFs7WxQusQj84slRPu+3GYhIR8EQ2nf2lGIMR
+NnkzwbsxeFTkyfGzA8cmASIsn9EqDeK9h4DbtB3l1zCQzXsTQPi7mqlsOxu3doxl
+UKbMHAM0B4TodOSIKZCyQ0UXau/jr4ruZ9Usz6fknYg0ELSOxACK0Gnhk0UmJH0N
+uUOWCz97o6e3NFdbOwMIChD++T7uGlIK5zKKi0Ti8/Tyc7KIzI9zlYmilypyuDHE
+geTgP1A4mulJBRYRjHV03Fge5RQr7wjuK9u+tUWSadiR5D+qSmHh35+slaiHEsnn
+kDKisnWI60GSHhxx18bUoRFMIUfPqLwQZOL5uD3ruMSCf33ynQYws7icAlI17IFN
+53aevB9sSuLPp48+3YOlR5kd2BD/bARvOudGKCaDVwLKhe1n7opjysG7S6xduIBe
++6DQwte1SaKp+rAjRDErEl3sg0mLXAvpf1WYqyTO6BQbrRiTUaUzepSiIgYJ0SEE
+U3de2hcTzqPM75Iw+7mhWB2TY1M/zYzIHkh0WwvcDTj+x5oT5NEtCtEUxDe6Yuz1
+1qRVcw35whQsHW22Gs0mdQ4/L+1obmfTVgRM2U+VsqHfpccklrwgHl70aTbG1ozO
+v9SXcBVZqPvBdrWmtRXq4SnFH4a2gyq1LArJw0hbUADFAa56pze1QN/fN67mtjyQ
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5CACert.pem
new file mode 100644
index 0000000000..92576c4e23
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 3B 9F D2 7B CA D1 78 89 5D A9 07 5B 66 0E 1D AC 61 F9 27 A7
+ friendlyName: inhibitPolicyMapping5 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDozCCAougAwIBAgIBOTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExITAfBgNVBAMT
+GGluaGliaXRQb2xpY3lNYXBwaW5nNSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANZnJDHPYGmDlhnjbX2Wd8iDOcwP3hJI6nYposXyUdQsXnA2DQ/c
+hTL5jI1smsPgXdS1H+s53Ii5n5PoaaaXR3uRpgyf+T82oDL2NcWlUhvPwPee/Oba
+mum7VeXYik1Itp3qDV5GJQlRLgpu8JN1Zx8v8CjvPUbgQxgcXpHh3tfSR+YEywzd
+N+CbKRqflBhroXmwZQS0YMU+lF+qbfcVna0PoNjisg+LVT/uOvrskOVibfa746r4
+HouY3g/mCBVJVb8+4YobezK7ixryFmUpiO1p9F8onRuB7a00ZBhtIHnT68+QU50v
+iPWAzoBcsLPflYLR4BTClJ69xaFlNbGh+EcCAwEAAaOBkTCBjjAfBgNVHSMEGDAW
+gBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQU24AHuWIsxcP980PiZlEl
+u9v0HM0wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
+BgNVHRMBAf8EBTADAQH/MBIGA1UdJAEB/wQIMAaAAQCBAQUwDQYJKoZIhvcNAQEL
+BQADggEBACAu1zkxR7sFDb4Yd7WMY2PuHviiAZVkYql/+rS9nTHFxSstRbaCaiUO
+NhjeAVbZVGNqlbvW58W6OU+qXtv8+5U5rzJjAAMbLMklsrJnjyyntaxXZerbdh0P
+RpIv4DP2mAmSCDH9qR6sJ43iHpvFO14CQNUofbfS1TYIw8u+NQGz3UwCfmMrQAqY
+/teK8hMdEd7D1QUwRKBSi8icsPQiAdlVB7JCzSASaqIn/sB1nCwe/sYCAUdydfmO
+AMQGyFymSavQq8WH9QnLn49/0yKnrJxgVexq2a56XDDiQnxPsVuXYr8uuNGPH5j+
+XlwnsW2fsDoZawTjXr5DCStBmx0tnQI=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3B 9F D2 7B CA D1 78 89 5D A9 07 5B 66 0E 1D AC 61 F9 27 A7
+ friendlyName: inhibitPolicyMapping5 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,681F6DA8CA9F5D21
+
+5kiDnMKFXJy+I106E5Qn3QOH9eFCaaYnlqNwRt1ijG26AfhzhTlvt8xaJhH3f+AL
+mQCKwrndrXbfFMAYkyX5sinWOtMrVEgOi4WrUu1ScKWhChe5V/GvdOA3zNmImG88
+jPat/pQ5lTHcSkX/NhQFwdt6IVBm9kL2gg9hR0aP7hC0t+XQP7s5IgZXvvTCk2q+
+CAE63hV/FwVexXoCmGxS3DBMEjAl1aUOXw3nmMvF+I4FPQShXUXTiRbtmPzdFSu8
+d8MojxGYBs1Yv3yDTTdtdA9G7YwNCwvqHCivMK0+Iuv7nHfB10ObKKQRw7IGSL04
+7A6mv9fBhWa4jarUpottoXwBe3NYjyEgqAshC3TPrbVJClnBGt1GRQ/m4B7oGh7v
+2DzLz6grkvcMjnEfTs9E4qawhwgMQBoP/NJ8YwXgqsGcBeDd4PDIWxSaNqkhtQdV
+j1NNZm2d0QoBc6mvFdDCYFWX7ch4r5NEZ6mryntZ5+pR+/Aw0YxXqiVtjIM4n6YA
+KZ5H50iikxwViZn4wnKOgoil7Xc3EwWvcJt+LBAhUGWgJB141UY/TKx14QFDh9co
+MPXrxkcpogVNCgYLXnmubicm0HPPR0ORYU3zG+dDaEPad23cWAwh6NNegModbEHS
+GFlDLHjLxQHAWY7XpLsLti90wBauyhE4zNUQzXTZc+0JrSYm5HE+pOBb9EWjjBJ5
+a0Wk2hHpRvz25Mk41g12qWg4RnmnW86u/6LjhXKy8kCbil2A3JXTRJE/JmjPWTzk
+2t5FpUq/Bcbl0WT076ROvMpk/n3SI7s1kW6tlw8olCzKBiDaN07PXcN5YtYzmZ8y
+W5ySTvj2W8O1VseYYDPt9B7V5xM3YtsqF59VZMmBQgDpoiniVb6rCxanEE5uJdMW
+aAextRiZE4wqzTbqh0Gjip94RADi7om1enxtu+X0mxfAC3JdVSYdI49+f2n57RvA
+sxzFMDEe4jSkFctAy8pjY/6fZN7m0Bpkpzy8g417rm2zFexND1bZONb/y6avXluL
+r426EEbORglcCaGjiakh9XHMQcjwlPhDPFjvI4JRLEheEu32KbNT6d8DGbYDK5K2
+934PMAkGr7Lw4C7ofdTbWGZRy6IWe8S2RjD90C/nPgNcLTPIkLAT6qVL6NvMHck5
+v3hivjsRaJp1lXUJn05+Goj9CVRwarg2JGU6jGAhkeyFrLLIMh9MWqI8rpuuP58d
+YIUCp99iSszr2gEIs+RPUavpbSJQknMI+ZtDv9vWv8cgk7ldJxNHvEFUldx8OKNO
+9e+lwy3ub0gLx7FNtcb33Do7ZN+NYLP3UwKXNmUADCuBeBmf0XBQEypzu9vPxPEx
+2CBm0Knii5ZdPS+hZ75uxkfktoQvC+z+pSuQqopYCd4Tk9ryrn7h2FdUm3nB7HYx
+bEdZpfhZiBXPkFZLAmLXuvQQbkS4eJ0Pq+y19hU6nSNOM+6plu6pcm9C6nb1HP6J
+m6KrTbH+mP5DUtsUvvdXOHu1IZ/8MRc5kvh/2VQdTPXyfJ9X5HtJHxna4YtKqBRW
+rrLEawQXeBcsuO7W1D4uYTtxGmsLWFf8OWLmMgCv0j/cLxm4tEpj8tJ20E6cyXLs
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subCACert.pem
new file mode 100644
index 0000000000..c989d48344
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 11 16 78 91 AC BD FD 5D AC 0D 8E BD 30 FE F9 C8 AB BF CA 4E
+ friendlyName: inhibitPolicyMapping5 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 CA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJp
+dFBvbGljeU1hcHBpbmc1IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowVDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExJDAiBgNVBAMTG2luaGliaXRQb2xpY3lNYXBwaW5nNSBzdWJDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALWNoV9OB/sGpzCATKUhLi110SMZVvGR
+btEnF/hkxaUlmi0foAiK1RMgUSmdHLYhKLogfjVJZhvSLut+OECEtKZTYV2RkNVm
+4igcfjs8aVhuo2z9lHZgqIkRpb/TPWkL6IgHVfLle352+zTscC6SVksC9J/o347y
+WE46efxyYYSGqUg8eXqodBd9ReFqYUKMZG/6Zrk1YbSYWOkdhTLEbvtmgN1ZsRvZ
+ImIZEAHaA2fKQKhwWeZax75qOeKRnzi0ZJCK4BFUkY5tviNclyNxbDCdOEyyrY74
+5wTjSkImxYEArgn41i++i05U/Fo6c5BAtiEQJZwoOfFPUXZ6ri5kZ+sCAwEAAaOB
+jjCBizAfBgNVHSMEGDAWgBTbgAe5YizFw/3zQ+JmUSW72/QczTAdBgNVHQ4EFgQU
+2OxtvrdvyhNjyifMnFuiaTa28mgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdJAEB/wQFMAOBAQEw
+DQYJKoZIhvcNAQELBQADggEBAEGWmRimtoryrWPMHFnL2kvI/vwMcVxQno5UzWGQ
+FnqgqRgKpgNeeNJmzTugZVPWfK36cPehUYPAZJjtcUB2zBaEEoFghvtZgQPWR/M5
+/amPSIHzt+mW3sXdJZ/lgkeA6nNanW/9AV3bWlYCfWgOdHiHym7hpKsk7UwHQYob
+ynVgkL4oxSV+KglhXYGab20YiWNW6KPC0C9PCyu3PEG21WYsrFGNi5aOOlnTTW8z
+A39i8vqZ023pgOkShxYBOvUdisg15xmSq+SzJZf5s1QyWd3kX5FRAsAOHWJzglvQ
+yqeQX3fItsth1c7iJojcVhz8A0yuXICe1knhgg72TEqj/3Q=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 11 16 78 91 AC BD FD 5D AC 0D 8E BD 30 FE F9 C8 AB BF CA 4E
+ friendlyName: inhibitPolicyMapping5 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5C3B5407440E3D9A
+
+g9QcHW7o0MyolWOLsAc2kQawYPcI/YOzbWz77ax4i2OTc7F0bA8iCDy8WLMakxzl
+b2lxhhXcKJxAcqKO8bEcZjYhUIWO5F/651/BSHtCfuq3ojyRvc1vq5f2mMDE9bhz
+odKNUFbcF14i8gpjLP8RloC4BkQDKEubAsyaZD43gu3t/2V3KCOP0ARAWcuDKhUZ
+6HXkcevegjsxpzoKg6w0Bj1+f2clJ8iE4gRdJ9Szkbg0YsgJYrR0DCk1xMMHZRPU
+RbLcehx1Gt4WjwqCl40NF/cylMlda/6OpS152ht9N44NAWRIP34MdXFJXNmQFcNr
+pIPRi+uyEbYBJ2YWXPMmv8oJyl7wnIpa9sCILNbi8aJwgCvck1ALNmo9GiDqZNC8
+L6+gedGdxB2qIwPiPTgX2KO9dgBLNDQftfa+TR4nJi2T2NUdatSnufU+HzMAvyEI
+DZFt07zfxaEHoF5pNvKsHC3P9Y1hdme5GJlKzORvy0ssH2cCuiCrKHrYlGYgvXQC
+UpSvho46u60+qsvP9Q4af0Ys3bIM1BD9/soCMGFZSkIHENXr8y8nzLUmQmwrJypB
+GEXtbJiGtpG95SATza5/rE98UaUSJdG9EbngQlxAagP7HZySNrnoMgTobGplxFAo
+fMHv1oKlBGvnk2J3vHItI3GSODuvEEJPNVDYVyw8fS9tqFk2H+fhV8KoN57W0Job
+cGqxJ3m8IKp8yF3i341gRhJSbynNK8qz5YBwVBreVw2kWz/mZuUIRDyWRxZOwZlG
+OaJ7F6xFkt/fZK0+6RUQDWW8/Vk7HiKC7Okcvq5qkBqIne9+JIXhJr+MXMF2K/wb
+aEypoO2E0Vu+F7ivu9j/iGOTj4K/U+5YaZI8rPSql84UInPdCnK2QfgsWHOEbsGj
+D0bNfejcUfcqT+LcUPiwm+jBlPwcT34dv+58+vd+/I8pOlNOsq4TEW9UVHcHPgHX
+BSW7Ntu4B2/s8nNYwxcfmpx7me0EhZhHBoaazi5+J/3dRSdC33tf604tuwjjzVOG
+FSy4SFNGEvh/lp94KA3rfsr/hBzBBNJ5FvpYSH4/Q+fCyN/MVeSo7m145yXBnwS+
+P1C85coy4cT0M2/kw8svJgeW9Z930No/RDmUbBN7UmgzLJt4bsXRv+f/WQvNp3Wo
+PVo0i8fLrKP79bv7Nf8L6GUAIf9DeQ4mPHnKPr2Qq0Uvyjxbnj+DFT6w62+o2q0t
+QUNH2ScJwxNUKWyvqvdOkEk0IxzZSjPZefPmdtfmfezZ8avOCaF1GbrZBLYrIqZq
+Tovw48Lit4f5dSrvDH1HXKyBiq3Wgmn1drUpgHYWJOlQB+yBy1E5RFa5aU1OLyeo
+3xvnZjgS+A/o5HV4O5OVDQ6HCGiAekKwiNlVkQLIJLjFWO4kXWM4nyIONPKiY6B8
+YHGdfOL05k63aHYOqomikXv+uldYKI5eqJzjqHfbn1Z7dugsFZRNV2jAtd9L+w9S
+kGc+mtS9Utt9vh/rL49gviDkXXl+mjQ+RCrFZVgGRsNY/O78bBei3sfGdnMc7sUj
+hEsxMy8tQZIeJAnHn3tFd+QXbqdhIoaJ8aH0rvZajVKXLRS6u4JTfD6gQgHccyTp
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubCACert.pem
new file mode 100644
index 0000000000..2e129523c4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5E 5D 55 A4 B6 8E A0 01 78 DF EA 47 3A 67 B4 15 B6 6D 37 76
+ friendlyName: inhibitPolicyMapping5 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 subCA
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJp
+dFBvbGljeU1hcHBpbmc1IHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFowVzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVz
+IDIwMTExJzAlBgNVBAMTHmluaGliaXRQb2xpY3lNYXBwaW5nNSBzdWJzdWJDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAORACl2TAi2vRGNZ0z25HHDq
+63G0jwwUOBpMU1tGZM3EA6E6CZ1Od8tAsWfeW9sUj8K2m+t5ncmshD0xjUeLl9JV
+CkJ7XsYI384YKQPdN96Wh+eNlbWRGi/DfmSiKwebVWOKVio7zMfv4rLdFEDYSUO2
+62AJ9tOBc8lUEfqZiN+VD/AAfKXWfoyW2J8pJ0AhX77P9DAuzMiZKvE63yI0lodh
+u9RKMVUPzLXq7FBY9xHexBFYGvGAtmuVfCfqNMR9Fu+loYqwb6KAAXnXh/DRq2TA
+VveMGaMxuoCk4TPlkrraHiFitJgXnFuIsD19YQ1iyX28c6W3pfFjca1/MQUOAGsC
+AwEAAaN8MHowHwYDVR0jBBgwFoAU2OxtvrdvyhNjyifMnFuiaTa28mgwHQYDVR0O
+BBYEFDWn1OFLdE5VqHG0Qn8y/gQayQG4MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAE
+EDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF
+AAOCAQEArfD53rmonDxsB7VLzP6pscDyvmqoQGKb8BgjxfuNC5AJflfBbbtlCeMP
+cBIfFtyc0nECkfaO/tS6ZbzHyU7Oe69+jVOufQ0gdPJBITLCD3uhGXUgmTQdckXd
+a2YU7ua8NZI040Vr7inevt8DjgBwfXEtUlObMCGO4OYtUBOXhQ9yW5KRkOBoYMks
+PSwthYFiw92gkagk/jHwfB16VNIs9u/n0/848m4BzF7wNp7S5iG7yq/+fFT0WfoJ
+rI/TZJTmIyWTJfhGwaV59ira0PrzzJuji4w62TpBAC/iKbeUqtLdRHBFgur8ccBK
+VzdvksHDozhB+yWvQZNwqjIGoKb6Ow==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5E 5D 55 A4 B6 8E A0 01 78 DF EA 47 3A 67 B4 15 B6 6D 37 76
+ friendlyName: inhibitPolicyMapping5 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4FF971D4AA6603EF
+
+he4gc1l86KKIErt8Ps3L1JurH41LCz1bBIPjK+eCvpCAD0ClyHveZ6Xt2kWFaBX3
+dMLH7sFDO/MMLqpn70L6BopBF5fD3edX/Uc3/L4BR79x9LGT0QE1WS9V4djt8Bqk
+INPEZaESnQTdckGsg9riICTuF9vujUTmrGieaUzxJLIdrAhmtU/VjjcduSzb7vMq
+DVl2aPtY+/iWDhO5HtGIAPMvB8zZnEsU8UbMvW+ST4CafjudAw28fYT+bMUzr+Y0
+3evVK+Lya3dc3Pd82LNDo+Vp3KSEGwsX9H077nBBR1LWz4HvYblTojYyd0U9Hz1w
+ReIbjJ6GzRH1Ro+FmWnMQPbRfUqmfbNwLY5keRzDHijiUmBTIyFepY8LfCfviaHz
+W0morw8u3s0HmsH8apVXsye8l4to30O0pwscGXT6G1pzdbB6EplYSZHP3VRuRVHq
+0rfAnmnbG1pNKc3ooLPoEFqfHVxzIazbe0D8a4q6iGvQGRUjFz9rlWefbazNeyPr
+caA27WSVy3bzqNB1MfIQo4BQcAEo1mOyBZW7vZCQ/GTPzEaDi56F4PatLskaX8vq
+nfCF+JUJj78+mTddZnV6Dc6AnW78ISJvS37i9FEkCg+PqTyUMlCwjkSh0fmi1vWm
+MYV0TOz31juOhowNZo67IDpVJJhsX08zFUdSbz/xDC8WUMmOANPYJGP2kAbQU7XV
+lC26rtO9XBPEc2TR6qpiU6HdUNmnT4tBdN5rvYy5QhQvwzcYhVGeAy8gsKhpbzJ8
+OdMz5e5c+V+dvkVlEWOniXmTZKKqXF2MBnTw/lI+uGijgwfTkHX+YlGpgU8cKNIC
+KOnilFBINIfa2+AmwntSBgUqmYsPQCJGvt/AS8tBezDewkzOneDtP9qfh1nbNNJM
+Mj5UGgVnWSqff7kf78lQZJbltM89KZI4Xi5ffHwMTqi//NKUFTyNx0GjMp0P0iIC
+XJGT8TX/QtL0lsRubvghNfYF/HJRxl8QchpK37bVqUs8v6fB3i7gzwkUdDRiK6Ai
+1nUXpH0I2KAhRkfw25uh+r7AQF2JTxnihbSkkxUqM1DkPBvVUa4QpciurGGp76ZX
+9Cg81hYcUPyv0PnIKfJaLIULMStvcFZ2qCgPn0LL+Nfbi+hxI2qFTLmZCCXXTM3g
+ZC1m/jkhocea3U/EHVtCBM3FtsmaoZ1jwbG8lg7sMYelGDo1hLHVxSg27v32yGim
+ULM4bVqYf3LTIrJ/iC3E19F+5aGuzyhqL95Yl0nA9s6oeG/SY7dB/Obb/ImvYE8H
+GiQ89sYM2Ykp6UzUH9cKjNnJZnfbYlhwBMwEFKNLSYNmob0iPBax5yFTiNukjRpu
+nZxb+840bYvogExlP4eUM1j3O2gvGlPUpH5lAf1015gY4SbJexkXGBW4hEDLxt/8
+DK/usv88NUYbuJMDn6QPslJWk6cv1knMRyLpM8m8bBqs3nUAkUtdiINU+eMqQknl
+GEMkCY57d9DY0OQuOQjH9ATvu4+e2Dbnr9EsBWxqgJK7EVWD6MRck28H9YybOZCx
+7Rh9EsJU72T7x+bWSMcXBqu+EMTlqlkIv0lP3jNxSYiX8OnoF6lLJhsRC8QxPaWj
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubsubCACert.pem
new file mode 100644
index 0000000000..68ca7de65b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/inhibitPolicyMapping5subsubsubCACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: B5 80 27 32 7A 83 85 E2 00 12 C2 75 75 1E 49 05 85 C4 A6 F1
+ friendlyName: inhibitPolicyMapping5 subsubsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 subsubsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=inhibitPolicyMapping5 subsubCA
+-----BEGIN CERTIFICATE-----
+MIID0jCCArqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJp
+dFBvbGljeU1hcHBpbmc1IHN1YnN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFowWjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNh
+dGVzIDIwMTExKjAoBgNVBAMTIWluaGliaXRQb2xpY3lNYXBwaW5nNSBzdWJzdWJz
+dWJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMOUe51QDDF4LIT8
+dNI7U7D9/Co97Ayr2DWC3r1XLTRuFPRFy87WgdMLZKMwQFFyUlExeXtmH3k3hiBf
+xQxkMe/RpmMzJsg2tR5ATvPvatP2yPAp9mdMCqn4KyWkMM7t7hKubm8n3V2FV+eZ
+VCM6Q+wCrxjzLpx/BnALMkk/+tNg0mCF5xQoTi20AKZZVapwN/jUM8bEn4LDP9bg
+jfvpZcP/J/IWRvQSRDBN7+62JT5DsnjJaXOD2a3ZgI/7shdoCOJJSBI1qJrSPkca
+IwozCjheu1icHr+34/uLXkYFuIAs0my0IJx7y43RrWNA0JTJ/WNYB+humZHP30eR
+bguXAbECAwEAAaOBpTCBojAfBgNVHSMEGDAWgBQ1p9ThS3ROVahxtEJ/Mv4EGskB
+uDAdBgNVHQ4EFgQUrmPL1+LDceP0zm78NfSb0k0+3BcwDgYDVR0PAQH/BAQDAgEG
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MCYGA1Ud
+IQEB/wQcMBowGAYKYIZIAWUDAgEwAQYKYIZIAWUDAgEwAjANBgkqhkiG9w0BAQsF
+AAOCAQEAhxkEhZca1jstqu4SQv4NukDbw8Z3DdN15kwxZzgNfij8622UR4YqHu6/
+dv+c0ANrgLR99MpRbvjimg4SnYj1Dlok4QJZN04jvvv0q6N3Tyvwf+S4LmaOyrXr
+N542+uqYrOAS5UNAPF4ZxkT5L9OdxKQ5qqRNN5GxyxbPszvVA89/rFy3fHC+2OHz
+eLgaSl/i0MIUhx+iCop1C+Svvt11DE3pBqRQly6A+MEtL9NjHVuJ/I6RxySHpbj2
+46+yJv6k/OuWjVrAlhiDuUjwFHPVVnvHk1plcXLv77EnhxL8Yb2tNF7tM/0aG7s8
+w5Idxl3AuA/XWMrmoLvQFlcYLm42Zg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: B5 80 27 32 7A 83 85 E2 00 12 C2 75 75 1E 49 05 85 C4 A6 F1
+ friendlyName: inhibitPolicyMapping5 subsubsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,218DC09D15ADE49B
+
+WuH8KvV+CZLuBDAte4hOz4eQwjEmyt40Lb0OrP3fCY9E8TC/BzMl/nkg9VgqHnH4
+n1Xa+DGyGHZVLoW41u/Z9WB0AEC3+4pcvKnBt13uKMBRgBS/X3PGLTA3alTxxxqm
+6fZ0EQrEiz1idvhNfsYzRDXbtMYGK7Lmqltpm9i4tl3elakClIPPNEQqFyB8sfdj
+rx3ahk3nf9cUhXS4Ch3mnPfJyj20WCUboXqToX7OmsozE+hlhmIwSrpCj57MaDGc
+bcKUgMG0xzPnCiouFuqD8G2I0PxE1/5xx5DKcfqDJ3QFmBYBCXpv4AfFLDWtTOmh
+ZdNNU7irbB2e2/NL439unk2DfrTjcQtEXKOgs8JhOQtaKWBU8HsI4HcCWr69l0NP
+3O/7muG0o/Kr/4YAUaPkHce7BFMYnPQEqTTWxOpjQxGbVHYdjaYxEBfRC9iebU7/
+XLNUoKZMWDk69i1qPnT0GEDgZD1y4wGoKebJ77jRQQ7INtB3h/jQW8Ps9mLzHm3x
+u396hVNxrJ0C2chftRQ7HgmiEJqdI0hz5o0WAm9ojSDMeTLRiRk4a1Zmx6NsmoSF
+gfbcrMnOLr3oIeehD4Zq+HKy3sRsF45u9qvMtyh8tT6bNiml76ocKP3bvDgBwCMy
+PG1m4j1XesyuxkGsCC50zJDEdxRq6uFikuH/yJBRK1EX+qtkuavKQKnP1bWebhaU
+wsPvhfsa9h+rwNhOZ1ec8P6TfEXCqufoMIYWGhmFbzsHOpTyMZ+BQRorJkFkQ8Y0
+gJU3Lv8fCow/nJVlcV6oZKXoFhbPcETa5fVYmEFkX3sMcK9i+a0TpSorE7MnMAd1
+f/bGlcDy2tgOg7yqPK8OL3G4oNyzZWyPgRo6OsKU3Fnq8s0GI/JMMovcYt+mU6Qc
+bkIKNo4NbDQKGhujSTSjl6JpcTkC3mzCW0l5yLp/ke0Qoc55co+i2cPDBCOCQx2p
+0CcwsOAgfy9sgRA111zSiH2aTjH/S4hYiK5jshs3DAg60fTjg6l4zkB4fK0kS4F5
+dqr0xrXbGnL+ILSBuCwU3IABFc6gkD6qPzKB9nrFv0dEzXtcXYLOs2sNREGwgxre
+BfQhVA7msHQ+2YaiaQnE9HlvqWRntkJzBi0cND6slN5gnVEqX0vV5lQz6orTwtdM
+vv/CQCIXhbKj6P3RQmIP0s3/foTLXOQBmJoQE4Yo2Nynzb5gXMJCpInAA7lOMOqT
+ZGmMVKqB3n17VaBcrRyb48UobibzXUCWhharDCLznN6cYQuryh05Go5ugMMadxbS
+5I8TKpaivEbhNjUkbU/4HF0RgGdquxVEJSHMGSpyPnNTXqnG4U/tceRGkemsm+Dd
+oFmk2HHH2esUFuMWFXAcevGZznOtgzCz9utLr6Xb6RWZMEHf0aHItCZfkTtVEfVm
+YlyZG+xBL57cKbXZDXIlBNxldTEoKjUdQ8ICCusW64bLe4fHRKoJfOm9NSv2fZDh
+YpUKEkhaYuU3nhOJBil8wMPS8PgyoG7nDXxR7YHwNdePzUMXD5TJX9rRISuww/KT
+kGRVn8hewI/ihNvvtxVfFDGuKFfRz491jWbM78ZjT4r7hXlfVBC9u16zIbp+8+Sq
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalcRLSignFalseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalcRLSignFalseCACert.pem
new file mode 100644
index 0000000000..dc15ee8ff0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalcRLSignFalseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C0 3D 50 4D 1A 36 70 FC C3 00 C9 60 6E DF 9E CA ED 35 E4 08
+ friendlyName: keyUsage Critical cRLSign False CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=keyUsage Critical cRLSign False CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIBIDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowWzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExKzApBgNVBAMT
+ImtleVVzYWdlIENyaXRpY2FsIGNSTFNpZ24gRmFsc2UgQ0EwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDVXFpJZrrfE3RhnognaEW5+Af+QIHZD5UHsNHJ
+5+52dskADZ27OVATF0lxfJFCsvqg+xF0CwUnPGAAvicTqbn5s6VfivsitBKgJtYv
+7mQHmnA/atFcsstwIM4a0ElZktPr3uBoVxfxJPve11Pkzn54JOO7iWMMqvbCnUM2
+rL+CDR+0mVStkYCxLbUDYIBHvjBua2K2h6zffk+UDf1cBiOJjBKLdQN3gJDKvgBz
+P4icVr3SOKy7CeZssY9qDvfs1VIXbFdHDNqAQJqIDrmdYFaWQ9Frg9SYdJ4nCNyN
+7eQs78izC8jF9EjR7NAIHD9l+PeznskhJ8hfHOQ/gIiccfPrAgMBAAGjfDB6MB8G
+A1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBTCymn1tK8T
+LfSc8hFVyyows9JaSTAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBADmfRFtG
+DU7X1eSxvzMRLpmjMY7rtbEUvSMJXB4kTt9/QsKPucJhG90897xCca8i8R2nBjl6
+Wt9YorVQIXg1usooaLj0d1/MWgRl51Tf6rWRlpbaG3sYuU9lfu/b1TPHLdh+iihD
+OrJRrv2VhNyurI61IbwgOUfnc/185PdIhWMyFMiIg+S7k+U6MM0b0m8tfAwQMS7W
+qVKV/DZdutJFDNPqWUNW9KsVPQreAs0BHfeH1U3Sj5y3678pOOW/oWeQECv3hptF
+xIeE8gCSz8ckM75AJnqa3bI4Qfc8Z7h2KYbqg4uh5Lvy5sjT6EmzOFhZfxPkkYuZ
+v7kVKEHrXEIv20Q=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C0 3D 50 4D 1A 36 70 FC C3 00 C9 60 6E DF 9E CA ED 35 E4 08
+ friendlyName: keyUsage Critical cRLSign False CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,68D6DA85EB17E2DD
+
+jED0gB+zQ9Xhyoqoj23i4u/lRZGmWxP1UhmzX2uP0dW4TknSr1V4SlNrAR+WSiTl
+7sHP5JUNIt/l8GM+xXQ7fbOdoOLsbkpOauHh0ftQKbVmEJvRojwTlBrlvfVESYIP
+iWhfAbI1Dsz35dzX6czqFq8K8OReA8BGpd95Ix/FGBWKcoAnjKISQy2N1hMea6RF
+zGXFUWtccI2jfB5QIuIwrHIsWCqPKT1iwEw1TzMt4zhppRGv4svN+176Lx81g40o
+M6Dg8qNpLx+OfKzY962zMB7kCXAxHbnZITKlx8U1cF+60QujGwBg6arROgEwOKSU
+PU2m112MuHckdEhI+7VbcQKjwskggYgP9UsqOrBt4WJxGNWm9uMFM1XkEyxmU3ut
+NiyCX4mjPUpqfY4Z2JkOlVu0TgrP+f041a1V5MxCD8UtdN62hV9V2fYjKRNaGt8E
+wZpc6/GRv9ZK6pVPDML8B3OrrCCMLjg84L7OCfuduxV1oK1YXok/Z3nralfIVdNu
+O6ORaXhXPCwNx3mj+MbNCCzMQmmLPBX/g/p6z5kVC+67HVzAp/tMiQ9p8RiLqPoS
+W1fEBnpDMgtqzwlSnGtCMKCIkto8jHi7zdk3eCjwX+dt/eaq6oYzQYHjEv5LatZM
+UD/UUtKG8MYyuVt3niiV7C4LFO861gPgydr9R7ZffnLKKre2mTzFOcpD95b2jbvz
+GrjrU5MNvZIBnet6kYVFyElB34eEO33emV/2z8L5pp3QpFtx7WldhhAH03cUUZsJ
+B8t3Jhz9KabKDl9mcFH0x98VgNN8ZPNsIMYtz1tQ+J3J1JAbh5X3R88bXJRonYiW
++itRoTtrJ8xDWgV79LzhJTo5AqE8h2C/AvIsFynUhiJk9eMioX4BHaqj+RroS8x7
+VrqyQHQf0fOg33f3xy+xWPDablqGohj/e/YMwHXZmovp1Wbwrg0J0sfsyDPwGeVS
+5Jy38ohdFLawlXm4WT5a9VVKEJkRVrAfDbFpYOMwLnJJHNp9b1WyWHDlfP751yYa
++wFC6idLnYy2r4STVOiawg+HaDH0syWvatcfRj7LRi1rG+eUBY1jALjRoSCKIDxX
+yQhjCBRIXk7Cuq72a07fwRj3WJ24E+nzp8L3E+YkuraMUmTsgI5+NIpYItNv9gNd
+Bcgu7L13BR/jyG/WdZwg2JIgkOnyHAVNPXC7oYmsSpuCOGFrYpG7jI/NtZB4NL/o
+IEmbHrw62lbE6vPxcwf3KPkzOLJurxyZ5IuFhzKX3A2HjoOrlYuKXUs6qhioSzly
+B4QSdUNuUbhOBGRNqaneWLjQBGSoijLpGNdzWjz0EOjDqSrTSvCc6Q4OoFByiK9O
+YSLjgOOhJ2lHj3TIEYkvVlN28Dna9L25VVsE0i+Yq8xvZG8wzlqg6QqWnLZnE6OY
+zrYX1CCGUnMSSpkqPVvWhqtMJQWcNBxeHIfQ7ixjMwmJn5f/mJ/mQ3Pjm6sjHNig
+nwmD4dWSGVbZxmturc3Q81oLt/f3M6os2/9Ds9oAHGrLslubcfbVnicLGwdRAAj0
+hH3oG5sFsR1E5z/F6YQUun0czkaQb5caUYiVIskia5ibA0WRkg72dmj827xrVtLy
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalkeyCertSignFalseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalkeyCertSignFalseCACert.pem
new file mode 100644
index 0000000000..e98f314654
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageCriticalkeyCertSignFalseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 54 DD F3 A2 70 30 02 61 F3 F7 32 AA 21 08 32 1D A2 C4 14 F5
+ friendlyName: keyUsage Critical keyCertSign False CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=keyUsage Critical keyCertSign False CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmzCCAoOgAwIBAgIBHTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLzAtBgNVBAMT
+JmtleVVzYWdlIENyaXRpY2FsIGtleUNlcnRTaWduIEZhbHNlIENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAshkDAkc1NgsehY25cyVzSEjWwYU6t95G
+/bdkWf9DwvSkBxz42UAB0DfeBaHlbsgyVPjecL2N2bBpu4Jn9T03xEaMfcZXsyI+
+Be6psiAHVoVI9yTqESpjDgwWC6qE+g6PcQq1pYxsGzWlcBm+nxxpb0biMg0pTgcD
+KUtkK3UeoUJ15K3nDEekwLkLFwuBBFGzfOFCp9PImJh432RT/zzy47GGF9GNNDPa
+7iAZDmKadTAQ2RFy91qvUWsMxTdQ5wR7mzYRQwjzJG/3QBUKaSl5jEX+U7wzI20b
+OAHMdiEfsDNKXlvbIWloxcmVHLrVnzyFXgoB4ZYUydsAZoqW4RUaIQIDAQABo3ww
+ejAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUNFUL
+Z/wcsdzCcgoU8GPp1JvwY/kwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgECMA0GCSqGSIb3DQEBCwUAA4IBAQBe
+d4ZoblyGZ2/KmDlPWpOb1UDgc8l4fTwKDuDOch2en3qqX22Lbfpc3XWB+cOvcneu
+TvU3GCC2udrSk867vxd6LsiUPdfieO58b0au8+myabu+ICeOeWtug/++HvHiZYPg
+dJI39eSmMC5iaiSUkcdyNdH6IwkB3WTlfFwQo62T+zC044ajD/1nH1F8yNx6bJPb
+nCcphNbufW7lN/3B7bpiz4EKajIkvBk5ZP8b6amkDO4fGQvEgbZGhNo2TwDPJh+i
+97WnDFkCgOETr6GTgfXj+BfABCKduqpl4H/cUG0zt4QI4SMsuUvqTVoHTUc+XNMW
+kaLapuUYQMDC/P0XLwPk
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 54 DD F3 A2 70 30 02 61 F3 F7 32 AA 21 08 32 1D A2 C4 14 F5
+ friendlyName: keyUsage Critical keyCertSign False CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D4AC773554F54CB8
+
+wx/O0W+iaLKhCpmZrFqQGu1feMI1jBRW6etpY9miXcSUorYfyiSYplNgTKNmcBF4
+MQTC7zLeAx+0HUWrPKETjYxPz8m0W0wBHBr64+CPo+DU/xxalgxpb4v0faz+Imuj
+Mm4gIHKikWHIHdonnFWpAAYAibIKg2suXJ8xDrMzHERzRKX5BdyJIHcpt6c7CLaQ
+6VgPQ/07N+ooNHis5ZrXtOink7DAAFS4EvY2fb7Fqm09eBRVe/vVtQQYSINpruWq
+W7SO6GJihr+hVtKo0PoHYvlsrlxZgYegxtiI+UjmJssLWj0p0fGvmgnQlf8UtuLL
+lV5kMSxGBqcJREWNWfYnrz6rACYoxmnG0DkUpGFTVeNfgF12WRZr1AQxSXo+xPeQ
+99zwXTYQ4hr6mB3ur6o+wAQXIRhuahfMNdVUvCL6Lnuaon70opw/8u0CffAwxCsC
+dFRXIe1Kmp2Ms637fLimoQCuOJ9OHM/wNf5MUyPBA9V9K7tidvqH4kCrgdm7P1vy
++ZLtvJ96V0uWqniKBRdqekzCN46v07Ss6GFL6fBDnbGCCCHPZo/nMtHWnXc0TM0h
+3AzYtsFtpaaEUBXmY/fuVOLEm8JELkByV0+08U4lktu+PcAg0rWDn+x/dNrSYcNz
+HWHpet/Jbsxk3JV6p9Be45wug4IEiouGHVUVE+q0wv/jbEebQlYk8qNATCvl8oo1
+xgpluvYW8+mrDTVskuuewb5Mj1AiwINUdLS4ZCDO1zwi6qyCGPvGSovUylBLI1m+
+wlD1yCBBfgwJUi7DpKh1K3ut0/bmU0CWRq76U/eWdLP76hsLIyuSZoMpeezaplwA
+AjoLme7da8yYjwzvXN5D5p4JigIhau+yOydpB+1EZyQAf//ROiHQ4mn3sofFPryp
+WPOY9B1j7vEQQcCowH7t33BbVMnacoYApYs3fJJrKBdfdcjFK2nkVbEUDg1BuWtw
+qfFpvS1ElW7C75lEOxx/r5ZJVI9v/r5sDB8zgszyhj9DEcpSbq5EApDW9AWJiH9y
+JKNBgh7KhotLPi3ADnp3Gzd4vA+h+ylCyGxZMEaY4gt5QrXViw3ndXe7BIzffT+g
+wOLyYY0hFIl4XPdD2iuho8iUov2MwX95SoWo+WZMH5NcPvbG9Z5Qf4/DMvcpQILZ
+hW1H5rDikiZ9kBLpIfXrWktDyvgP1p4Ng8LbZshK4Jw6rtLF6Bo1bB27gF98+lCo
+cORPVMi5eSL6IF8ZkkxS7Qos4CC9SpFS+8DIHbM1PibOwD1C6A2KoIS55c/kYUye
+XZwjqmHO1g7DBP6/qVRaSw4Dkcr0NqDbt1cp8+w+yKQnmqzgf2zKx09fbufdjnDL
+/hU+FAm10YKGozDbWA5oTZ57sy9K8rA38p9ECrz4OeEVnaG/MeCnqfpsWUyvpHUo
+XA9/mzjaUAfktQP+wGgRdv6Ir2stOIEgkkYo57T54sCDnELyzECo+6FadHUxqNL0
+pQ8zSuIH+Wb8PdVlkFtKXE0cL0laahBzMFSZQVj27UQCnVNBdFFy/Kv4aoCyWL+K
+FVRMY3kJ40sTh8SWeFwO0aLd8ycV28AapkWqyKJau3zbNQNWQkR43A8KeTsNf28Z
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalCACert.pem
new file mode 100644
index 0000000000..b2b35d95ba
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: FD 63 0E 7B 2B E9 83 FA A2 27 54 7A B1 AB 67 0F C4 76 56 D6
+ friendlyName: keyUsage Not Critical CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=keyUsage Not Critical CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnKgAwIBAgIBHzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExITAfBgNVBAMT
+GGtleVVzYWdlIE5vdCBDcml0aWNhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAK/akbKDSU+jyQyKaVyIOSz1eF/8IBeTVffB6t4DDAzrnRLvfKPO
+QaKZb2v5iqF1M2bBoKaIdSfcI5At/JXFHJD7H4EGHkT9sWMV3Qyhw9peIr7We90R
+S30KHCOsXU4UYx0Cqgg9A1coxkMo+lopBwaQMXdxSRSLshfGuNKrjCcttOxF/GXm
+hpz8kMPBLUKj9OFFudTylI2DD46FxcwgJ0JnBPOll+fpLPYVhBAM9Y5uHjcanl6x
+5U3Vu2ENZ+v8wAXqFFkl/ySMO8oXidy+2ifYjxPJsvAC/A7BID2NG7y6F90+tHOS
+7I4pUA2dwp3ju6p5yj3o4zSX/cQDvuHj99ECAwEAAaN5MHcwHwYDVR0jBBgwFoAU
+5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFMGQEUrZtCvFcH7OjDtiWOW7
+lytzMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MAsG
+A1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAHJthW7o9tlSkPicbKxW3xOHN
+vcod5xj4RNcMFpz3AZe1KDPm8vSO0P20uzUo94BcwKGOhf1Ecp+8r9Y7O/dpyIz0
+FZRa5JKW4NA0LlAuhsD5f4gLpRbY4Nr0SS0w3k8ycSU3uxpPCiD92tvih3GAPne+
+d79uPxmFSOVwgiPa6uLz0nnlAwgbMl9NiLpdzsLnbIi1saapuoEwMNWF4VXd4DDO
+MfOh1tHOwbyfmJuQF7rl7dGkhQN0e6AHJUsNigI3i4wHf1GvfnpXrzUoz8QzmUWf
+QQCza3OcdC2UUN905ztpH/+1bgtUJE/alfclVJZEHaWIhIPg+5//Op74d3oK4Q==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: FD 63 0E 7B 2B E9 83 FA A2 27 54 7A B1 AB 67 0F C4 76 56 D6
+ friendlyName: keyUsage Not Critical CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D9768CAB2007E4A2
+
+1izcemhgrYgp7NpmBfYrToOfortvPJIK3wSduRy+LeP1g3o4vgRXKzX4i4k9LBbL
+2OFdtFGAvON/btC4oSlTeNVIdDHv8/Oakf66HHUlw9tu1LhFwWcFXDQ9Jyf/Pb9K
+H9vk53fBoDl7PZUNPDsGigMAI2cfo7GClbAEMzIFhaCbvjApDW4YhtoMDPy4P7gI
+hOsymmIvP7TttV5vfO6raFHPLzem3M6+XubToouHRUlc1m1nX3DMiotXRMEO4ioW
+uX1QqNb9xEngnKA4ADTrYvM7R6QoQ9claXHqieLzgc8iNzpMj5vSkVbOCOCVMxoj
+Sk5oJMGI/jE4jsX1VHKFbBfEMntF6aeuoCrGsuZWPidopuxZ9nBGgLQVCzs9QOaq
+z6f06Udjg0C/nM5/iE9DfL3RAylTrRrXV+tL/N6AZde/7KxJByUo8SndvcqIgrIh
++1NZsVdFhp/xybqfalUXz2WxzDkrj9B4+GRZn7/Ci+cVRRXBuifnZwm6FlLBMsKq
+rz1EgMSkX/0JmE9C2qe7ls/Gpx3W/ahNLbDLiiqhUXFIvTUqpnww9Ozrwwq0OcIx
+5qjT2LyZvxZ6BP8hm2ux/CQtteyyAvLlMF6b4GqEyjJWXav46oDcmmvobe97Wa3V
+JHVw+TCpLWypYZlUPHyW661s33ewWs167lIlCWlFkKCUtzW4Bp/E1xZ1Et+/xzdm
+PhVqWWyoWVIQXwi3K/OWojc9ZGyIFHybROl+sqeWIpUXnsN0pa3vCigWMTxqeA7V
+EHyQ28rC5EF+IreW3RE6vI0ZGtmSeKxf7UonX2HBiOYPHxfgHFRpcIqJmE/p2Mi+
+IIx3q/q3+N1mGtLrk2QBzJNUyGWD118Y3XrWv8gsj9GF+9J9NBTBfNgyxaxrdPcH
+6tmSrOF6Buz34jlQdxsn7wN/kjTtNVwBxHtaVc6KzrP1e6IY+5m9FfpLY6z0kLtY
+ZczKMr/fjubH3RoC/dR9H0v7vFyd8syzfIXLW92SMqdwh+LLRBfHUZa6tfe8cVf9
+E9dybAbTVS+Gctq5mS5pYHSWyZDq5t7JrvBVBjh2Dt6D/0BnQhIqnQRwNpbSoeNc
+dgcKs+HhptRG8Mtr8VA4JgZTTYf7h2rVJHp5ilYvvIj9K29ftgRHj+iAKlKCpdzJ
+K82kWNI++/nT/xX9lbtSEp9Z2slB7j5FPseHNvaDoFh/dIDGbuYsteVu/pBnPX/O
+jtcOd6Tu9lzjrHSx9AANpxDui+VQRfdGJBg/nCof6RQ6JJI0KD73gOJFYEPcrU+i
+zoZR/3m8Rb6maz8xL8qwJerOefYaMGvBidqcBPxl4TVs17JzEfyCyLwUM9gOXuBb
+VNiI1tFxs/Sai4U3dhv5y/DrMSJ52/viPzz5UHh/38Og1b3pQWc4xCJgAesSvbCi
+McxKCksGErozuzopNPJXv59s3wxkHcGY7SQ8S7HqUz+nR715Ho92mWuvDitPm09g
+DEUFgD1ZHB1CYjJ6jOiq4hEGFKBUyP56Zwz1060/JHsEjnYMhUJ9FQkhZJOaPEa6
+7DNbXkish0R+ClDkI1CIWfe/t/m+Po4c3WJASPs5F1ivDGvCXDN5/g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalcRLSignFalseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalcRLSignFalseCACert.pem
new file mode 100644
index 0000000000..59924e049e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalcRLSignFalseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: FA 8E E9 9B FF 45 C8 61 CF 71 C0 90 04 96 CE 07 1A 60 C0 ED
+ friendlyName: keyUsage Not Critical cRLSign False CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=keyUsage Not Critical cRLSign False CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIBITANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowXzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLzAtBgNVBAMT
+JmtleVVzYWdlIE5vdCBDcml0aWNhbCBjUkxTaWduIEZhbHNlIENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4ajkrGWOSxFEG9vuWGeWpRVcosWQyfZP
+JV13VfTNb+3Q6Ke5L218dww1FtrmP99ZBbbX8VTaLT9Hl36zdCNhXfNDjpj92N4F
+rM93HPFrMLewZnfq1d3zWvtPN6UYNKyRozFsys72YmIswHZb83uAltVNKZNaoIhx
+9oDLf6BudU9MYynVUnOskvWbJbbi2SqjNW7dHP7boiDi5Uy+IdyiKvkyTHnaH3OC
+gjmQ3lWXpg+2unulTZabYaR4twj1hFh2XgZF946GAg2sy8ux4g9lKR7+HL1BNC5Z
+PBzKHqMPZu8+RCUA+gHUeh5xwRFBg7wq1Gs5FXY0BB86bDdjJrDrLQIDAQABo3kw
+dzAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQU+X5S
+oHlmBAhECGV5EA7dkOZD8dgwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBCwUAA4IBAQBXNr7R
+CtJ7NH6ne9HBNzkCWsG3bwfaR3tD9hQNR5w5fyX0LKwBhnX8oH6dAHe+YHZ5oRlF
+yOeAZ5tjD3XR1WGFJCEHWQ3VmHOVtHLoc5YNgUZcn9xO7KLWiLsRPm6Nyd7AETZd
+/2EQUcHecRR6tnTKZJLeZzddzGnb9ThWvdYO8VaY7ipNp/fL+odZx98P8yiwni9f
+gspeW+GDi8xD6U16qXGYLJ76y1gkSYs4IZCx1Pqn/MJTsx42cHfrRLaomVzOGraa
+tjeiql/jUOb6IWX84tabge5xp3nMD1xfCFaGTaLMPiWtEhgFqZEzONP8R7d+15gr
+tWm1TYtrpHu3POhY
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: FA 8E E9 9B FF 45 C8 61 CF 71 C0 90 04 96 CE 07 1A 60 C0 ED
+ friendlyName: keyUsage Not Critical cRLSign False CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,275F2E3AD2EEA049
+
+7YvBHx8+E+Vhw/nPOVU0cqQG86t08FlQJoYzqbih+EMvmOnuARkLo85UqgsMhPLR
+KFIgv3WiVIUc+DYSaP0PbC85Zkq3Lctl0hNDyUbtozMh8bCXVqNnVLIdPlmN4FDx
+JofVamca1/TAAhZrVymSk9XRCQg3tt+7LwgRS2fCtTmFIPkyVMrgo1vV64x2Y+1y
+hBJyXfSvXI/v0aAZbqz+Fho4TlaxPtuBpT8HiBhcIEIk6Abx1Jsgl5/PD2fsnrK1
+zzTKw7vMLKsvfUpt7aapVmjv3CpZEEgJtYlGxYyTGD1HbBSR0XXdU9YTSQAGXDL1
+sc2pXRuMKS/mMAP8CtLYyBQTmCk6w6ySceiIDx01QYrOWANwX2upsnyR65NBDSj2
+EQH2Z9Os+Uslbd/MMLZT67VgCLXkrNBKWSklrt63YdRivCUNtMM8N92+7boSxExx
+vo/ngvhO1vULPN6y231dS7X/wqMgJyyBBVCjtlaVSqD1pDiF9u1KUJze+olqvEdQ
+9alOna/FisedtjE8HuntfIiH0TGujtcC6bbVLYs6Lhuk/tiq3ud4j47UuArGovD0
+qV5JqIcxMxyh9cI7CGx3TWUTMrllCfKT8DuxFlWV6eOER1gtk8AFOhwNgCX12iUt
+ZXleKaBgi6ckVip/lvkBQjg8UZuy2aYK7MFCn0jKo1anaSOZ/VcT9nnv62z6jzZn
+heG8IUUKvLotuTEO8+2fgb/Gw2v/ZYCviqAmI+GLuVCHd3b+g8j4wylNV0jFq1Gq
+sLswif5RHUgAW+UaYm+UJkWA4uKGEWf2LEsMk1qJ+Gbiv3nWB0r8e+qYqWZtdJvd
+5U3wOjgH76BQgQewqRPRQ44WXXY+Mz+RntPmq2i3oBfoFCRAP3mSjQJK1z6e+xl2
+h91yAn0vhp9QdwUb5f01kYH7Wz12IuhCxVApMRal1PKq7afNxHUMaG67XyfTsvCr
+GhBFmO5uFV6s2S+cAve8vdG9f11Iq4X2zX8GwPY2rtjjg013gsnyhcQcfDbGIf3D
+21l9Wln1aqQa6ryUM5Q7cjrOJTB0S2xb9ItP/Ma7bufNmeiqo36U5pe2m55XHTG0
+KvQVjW3y9LiEFlISWsKjLIwYOHFcWRhBJlzFHhf4iuHolufqZMmg696MqauCEF6q
+RtKDFAbkT6pDE8OuuvYh6vPjwDsse5nYBGezjXGWHHI9cSXQE8RGI8QAAwHidpUK
+mIp7xCpmMcCOKEp89eErF+5DW41fqg1QVnZ0Y6AJcQcpkO6iAgb/ci8dfD+t0s6N
+GycmWKe/SiWPlfBwFNuzw7A6HxsUS48Mxq7CEYfYv990SAQrLWwIgUxELcEd8ftT
+YOtdwnji3VgbGEvMmtNVr0Ve3+ilK4h/AjidZ+YzAuFEdwYjtAHuVr0fREoX4q2T
+gj79ZlaEnNXWaDcVX8LiqTAlWBCd9nFDv/EEgheptEkfY2/M7jvlMSokRXWibZZ1
+48xPg4duUcChEGssmnzebdzNrTvLPgjNeRfQfc5XcgSzJecCrBBpLobMGyjrMeH7
+oV7vV96ll3wpvAqvP/GGkcgBX0TNRTntH1L0u0AQMiCvXL7jMxNr35c3la8elJfc
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalkeyCertSignFalseCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalkeyCertSignFalseCACert.pem
new file mode 100644
index 0000000000..7ebcb97e2b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/keyUsageNotCriticalkeyCertSignFalseCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 27 CC 92 74 D5 0F 97 23 CA 48 E6 84 97 53 DF 65 EF 38 B1 CF
+ friendlyName: keyUsage Not Critical keyCertSign False CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=keyUsage Not Critical keyCertSign False CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoSgAwIBAgIBHjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowYzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExMzAxBgNVBAMT
+KmtleVVzYWdlIE5vdCBDcml0aWNhbCBrZXlDZXJ0U2lnbiBGYWxzZSBDQTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALuW25Rdl1a11hIRQCfJWGwgZNpJ
+8Bxjnvmd+5HmQB2uTgWTPpIs9xfWCuOqqCD/jVSS97nyBQQtp6I3dQvU7Ssmkz80
+7y25FvrdcklcYjFKeKra/Di2suavIb3nlf5H1hRIzIejKqFxIDjT4QOi+kNdArr/
+cJM1nrZEhnNErXJ8qDpcb8k4fzbmodDbV/g1zvqY/vmh4iYv5qiw3PFRR94e613H
+gatzeOgFdu7EpTGAbNp0cGnsjvSuFb/XjY9EAtQoQiRmiiXbBnmoDIqOM7lktYJ4
+6Aly5kGXqXS3ZkkWERHRepN4B9rA8C2bppjGxQ13TKHFqeQfOgkvpGi7rVECAwEA
+AaN5MHcwHwYDVR0jBBgwFoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYE
+FLIl0igw0FVobky1wkjzypsV8kBFMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
+BgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBAjANBgkqhkiG9w0BAQsFAAOCAQEA
+LFhwyCZWomHkwIVAZ8k+3AqH8bVC/JcN/8St1fY/0BCt6pLeFOWLLXpflPlvvNA5
+SZbJLDfE3VOOYrYqwJEnmy979I1527wPGcj5O+jcDg2AWBpMt1qPPafftSGQxx7t
+UEWw8ZQvsEAab3Cof4p1/DXCJKOpx4zsXrz/OFBkSx+Gq6v7n+Pb+4g+IojVaxnx
+UO8xUAaQzjxv4yVfQQw3fzfrY6a99UBUOwuIPcQ+AKv80uU3aqgtvkoOWqs7R96h
+rnEWe9qZj2hCg9Fpwz1hyg2cXpkBfL5Kki5zUTaNhad+6iv6p+tXxx7W8qs7Fti7
+ziEwUI8u1HYLbCGCGFsuhw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 27 CC 92 74 D5 0F 97 23 CA 48 E6 84 97 53 DF 65 EF 38 B1 CF
+ friendlyName: keyUsage Not Critical keyCertSign False CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E1F05EEEC619010F
+
+74pwj8kKEJA3mS8C+eIEtuVZs2lGNc9hKvK/LXlUSnQuYgtfmOIch2rXgNZMtQE8
+LhPfxUrNGG+30b0kkrhdwTBiM2+I/OsoPG9qXZMEHtDhqpGAZhnj+FKRB7VQnt5m
+jP81Y/dgWTHct4TsJPdSIRVOm5rbParIijUmnQ5nAH8HUEExbbd3fzLEEnZVZDus
+rulTbJaSiUhKHBU+oQtZ9AGl1uCzr+uU4o5ihltA31vMjRfqxdnpET7+31WI/1M+
+8hUjXCb3kE/zxexffXiIlujiQBrPomd61L48rZiEvN+kKHbp0DJvaxyNvupzbFii
+wNCkOxfQzRUTvGDKuvFsLjAnwoKkBDX3Mn2qbUELK0l6q0598srvnO03NEZoLm5a
+Saz/qvF0M3jAChxzjd8qqmJ8JffWmO9DLCPpYDVT2NG68QSu5hbREle/VZtwVMqD
+IYw4iqyfTwwP6HN/20VsQPxId0Dy+Pjo46bmF9NUHDtSIYIQngkE3EHyzfLI5Fm1
+YHQy5uZNclrhu5mQaYgqfQLmeTpx6BqcIq+pmw92hHzxFslHIv/wFSeEd0zkTPPv
+DL8LIp7kairNy4TBO0/LjLZJOutBZ3afiKWD3HjU0MwDhvgiFUtmdA3Ok5t0c+Og
+vF3y1pM3oMEF3QJg28eiyX6ZtoMYh+fKjSNN2PjKfQ2H3z67FcsgaAg5Suxa8SCi
+Px0d8O130D5uBlwsRkq8kBY/bohC2d/2rjVRedGyGsNAJqER8Kyez+3OmnOnOBV0
+l67hw1rbzOO2MEz8dh6yfrqo7rHSuJFD5yl8G/u91ljkH3STgJaZSx0XzS9mdIpw
+z03lIgymSCRJEOiTeAVgHpBqJtCT6/efKbU0jkeJHozXgCD0QY7xK1MRgTr69ojW
+Tpb0OibL6NyDm5gMq6Hwq/ISjsi0FsGHBg2q0yBY+tepErZH+XMxav7Hb9hcuYU9
+YzhzCTK9HHwk6xGZWvXcpTpxyeSkDjw3+IPV9Zc6bfOHNJg/znebpoEosbrnHQAt
+k1xHvqTfnA4MJZWqhaM9okrP3LK+9V3fJKPQ161aFjBbM9suO25unR+cuBfWV/R4
+FV/fyrA2zpXZcG5gC3HP/Y8Nt2DbIkZ7aTcSKTky3p2puMlxDiBkD6fgHgjj808t
+SYepDYGqaVmJKX8dxGKHyjKfYsdwYuspSKLNl9oFSYmgdUfygeeDGXmqOuGmSovD
+q6iONPyKOH6p+oSazEJ2ZuP6nIAcSoaz6ueGlTATdDYm075K/fmNhEvqNds3CE7A
+XOn2wDlrxv4VMdDFpTazNpTGEo8O9rYUtgVTy5LPWmENFtCvI8CL63qcjAQon2jM
+yFcTgT9YqJpcabBFb87HunyG16Zbb/30PWh2c5UECDLzEkKSZVTg1D2cEcuD7IDV
+8Fu0GZPotOFDM84x/4dQPD4+wjHxqfPXmUNXIpt5sWSj/55uyS1uhEik6pznotoc
+ge+Yps3psIFb6AVr+vTBFx5FvRvILIb4iCyL/kgAs5bfSnlMdmSFN39wLUBZOaR+
+JLprx8Bo9qH25Wc6mmNPQjReGTgQOVIdsIkBaTpqqXEfZj6O+KJXIQ0gTGmAs/sv
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1CACert.pem
new file mode 100644
index 0000000000..433445f937
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1CACert.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 2D 55 C2 E9 01 A6 15 D3 50 78 02 A6 EE F4 DC C3 F6 64 CE 86
+ friendlyName: nameConstraints DN1 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID7TCCAtWgAwIBAgIBPjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+Fm5hbWVDb25zdHJhaW50cyBETjEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDIFZChS4W10eHwp3smMrXyTluiMJTrq0f8LEx4D63qlvrjNngGxCHt
+BOlFbIH3uKwK24yKHywpFK38bHLyDf+2LoaEYox32sfyeqneYurTGJ4sZ1T/fsZk
+lG/n5fkMlvIU0iu4eOkshyEEtvUGpvdSEg4a7TiadjmsAZkJkgBHV0h9VYaRYvgY
+BnDsTd8MrzKo0bNnpMgiUGtGJB9lB0DmhO51IelaxiyaJUVIsKUZfpA1NPjSboLi
+NLgKhP8El/AlBY3BG190xJ3a5xDIhDq5SRTJ16554PIIwzfE7nvY+9TpwfkYvVKL
+zCOTyrA6VnFwTLKc8sLYKFfmKNEboLafAgMBAAGjgd0wgdowHwYDVR0jBBgwFoAU
+5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFEF4QkbNTqiC5+E53/epFsAK
+/O+GMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
+VR0TAQH/BAUwAwEB/zBeBgNVHR4BAf8EVDBSoFAwTqRMMEoxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJt
+aXR0ZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQsFAAOCAQEAaRFMK70B7a7bqMhucX7K
+3AnChP1D8T/CFQUnOWeC/yKAcHbplQf3uWzL52ZJIoKLJaT7dnCuLxx9St/m5aCI
+MKZuIda+85I2WisV4brJJWyZlgLauA0WLZuEswqB0viCZG0vgtWTm9uN6O8Lqua3
+fnM/0WQtcmMMNs3NWN+FTX6SHIu5Z/DuUZWSF0H76jjheSJG2wXn0TJk8RRJ7mn5
+dnDEoDFUpePO0qaOjl1KGov28zz2QGIr7Nq+S0Z3Gk1Z2O3DlgYMeYtqkiMPKZ4Y
+sPDZIABuaSYI1o0ZoFnpLgiWVWbBJDO3w5x6eIS/CueS8hKfX0h7+dIcgQhABleo
+2w==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2D 55 C2 E9 01 A6 15 D3 50 78 02 A6 EE F4 DC C3 F6 64 CE 86
+ friendlyName: nameConstraints DN1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,898DAD8985686C96
+
+QaviycojHWt2k7YjmdYJV70orCk2E8JuW1arD99JAJ5AsLFVi4NjaOuB6HVp9NmV
+ye44weLxzeeU5ngFz6cyJKSeEP5nGdAbcA0ROYPHBcj9oEfXOiVV7cf7LeGyDtaT
+hrl9+fOgepJm0CyQy0cuV8UqYwrd1ebjSNtq+Em2HWs6e0mYxhNJw04xR0zlPNAU
+XYHLzKQuad8bdQsylfk1/+bYVHHtPh3gdXhz9g+lvpJ7zl5Zo9i0kS9X1ov2EriH
+BwrF7owBLgf5J3LJ0xxoIiYFmartTg3JncO6V72hBtDWLQv1sDdsOmBW6kM+x2Xh
+TgRHjvFk5LgHEpRoz8ureAGMOCELGMmYYF4qdnvgq9YM69LEooX1YMmSpLBpa91+
+ZaZJbHrJqLFUU6kBV6aKyEmhSnP19zQCJln3b6R/+PZFRVuagoO0Ybk1byBPegF7
+mxZXhnD+mO9d/H4+YEnuOZC5npuHo5UnLcm6h8eyKvs8c/dceF1fsVZQfm8n7Drj
+/Oid1cjLVPvkN+absGqPkFzWQybVuNOpA1BjBVUUx/jc7EBmEPs8FDqGNJi7hMqT
+Gj1rDU8m+JvkBskfVmEFJeIa38jzooKkcGONl/HeTldgpN0Hn598kvwAqgT5tOaJ
+L/sm1L67ETCtw3SXWO3XJdT7EnQZ4E3Te/Khq9Hu25eTX1pgKt4hRnTZGmuNY3PM
+oS7hwJY7YuLJtDX6R4f5+6E9v9pYGXPZpcMA0UKpXwcMtCHm7UYE92UyOlzkNxUs
+bLzmUbqkoX+/hYvoIZlmXeCZSaL9rO75anyjFZ5AZqj7lUCZGD04NHcJUlmmRzfV
+PozdDQLb/8xwrnCamRFAgJ4G4l4RqlAr7oBxuJOAqOn/aTz+5pzQG8BlSf5NYL9s
+8wRIFNY/YDw533+ZJMb+62j+BXzRM4uSiwZiAM5Wgea6E/wJhDu7vjmrZZOw5QXg
+pdab6gfFiZ6T5DKGDHVkJRsjqwIo3aINelzPT4PROAWft+UNH2jMiyMc4vk69JC4
+Gx0fX6DcXeSLZUEo+h3Df8GgJM8sUMu5uQllRhagjEgbjj9kZefhbf8HCM9msfd0
+ytju6wODE2laIjDYPaYnSqOoqJVDKhdxBrHTfQTUJ3yWUoxEByr1X3UrfAJqxd2U
+CZhe1vnA6QzNN1TfxgpU8zqsPZtblyCbhw4QOHjVhbfzljwHV2usgEdqyw9gH8Y6
+z0v0cg8SqVBJo9uE2uPsZzdAS2OrHyf6EPAjSCi5cjzihb5zzSeD56nhaTzFbs5f
+qXD5LEVAJzkjntNLBarTa5pEaOw75jrGn0YOBnYhlTEGNXzFxayidG70axn259lx
+Fz9KGBStShdoybnnW2++OOmX/SbafNQJYKrLtndQK6uaR7r2EWsORkP+HHJOPTE6
+m+h2BIuk8ow4BfjgtQ9/nrgOB73kdE0ajMwu6W+eaq99AkZLb5ms3B8HU/mjZiuS
+3RMdcqrG7GDUy91iYAFjKgh9yNxkx/imLFm329cQbRPaf2wV90784fKkAOYD27UA
+DZzx+qKCCiN6qB5h4ZVzqg7YxJyfOyVkDeKCeDkncZpqyaG59I4PopolUAaNABGi
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1SelfIssuedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1SelfIssuedCACert.pem
new file mode 100644
index 0000000000..a7940386f2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1SelfIssuedCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CB 29 94 11 6F 10 9A A5 D1 7E 8D 1A EB 0A C6 82 D6 C3 B9 DE
+ friendlyName: nameConstraints DN1 Self-Issued CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIDlTCCAn2gAwIBAgIBBzANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+ME8xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MR8wHQYDVQQDExZuYW1lQ29uc3RyYWludHMgRE4xIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAyiKAFzYtdvEdciQ58kyp4foxdHez0Ho0jlCiy8aV
+7EdOkOe6I+BAIve44XQywvh4JqZ2xEkYhAFuVhZTpe419Fojtut1pS5p1MiP87y2
+eJ8jRJFMJ/O+UwCRwgt4G0whBAO10BT8ETwD7wkl5XbF5Q9cj3oB3ESyQC4klN5y
+L5lcnyMUqZ8e/fmiJD/M4siYIAUqJzfYpPgExDfxCc8Y5GolybvhVlngHn3mqa/l
+qjfkIjqVbB9qSEbS+vyrZp4+HFKeTxCNMri1UeRYIhm30XIEFVD/c8Z/e8FqykQH
+ZyBeEpwb5caoS8+sPcQ9DN2afMEHfVCZfXyL4P3Gj3MANQIDAQABo3wwejAfBgNV
+HSMEGDAWgBRBeEJGzU6ogufhOd/3qRbACvzvhjAdBgNVHQ4EFgQURZ0b7sX/48TH
+MDhMW8ddVJlywLgwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUD
+AgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQC0BCN3q3RD
+IGoq2eKsryXDduFqAJca6+jKE4re+Kmy7PK4f0C57r6za/KQTw3fDgAKPi6DctN7
+BoXiEL4nDtNE29OuuMPMQmpyZZ5MF7H8ZgRrzYW3OMbu48lzwcBIZ3eCPY4rL6uM
+OaBRw7TXMmFVnxsusN+SB0o/FXIslyKijV5ZACP1Bf0OotzZnsiWEkGKP2H/iDxs
++rxLVYTyowtKi4EmA7M2a+2LmGvndpB7u0KghWDL+sKjVa4PK2r/9AiulLL+FJbY
+x0Tal47siI1yC2P4XXj/8z5o8jrYqJFY8QNAl7PO2vNzo6CqXF1QypNAVeDYYCcG
+ysMMqgXsj7XQ
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CB 29 94 11 6F 10 9A A5 D1 7E 8D 1A EB 0A C6 82 D6 C3 B9 DE
+ friendlyName: nameConstraints DN1 Self-Issued CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7CD8C7B701770883
+
+8mw1OmIgu9bYNpdKlNOkfCqyRaTWDwE8zFYM2nzVrvKLVDEnmbQCCQdPWHa0Ny4d
+6DLcYN6Pu4TGFYUN8Xfql/BfagEfKlMD9zen3AAMhRO+hfP/CP1GoadjI0pG0Qnc
+whn6th06VS6PR1mlKhsR915J07m6+IjJUdA2KsmK6yxC3iY/liZiIZaeosOsYR8h
+ROrJ8kGOBPUVhhPbMC2t4QHO5xM6bon3T1Ng+b7UUCH/N7tkvI89wXyrR9nJmkU9
+T5Xb53cf1XC+WU5OmnjuZXGBmnlPTHu55zUNBsFVuiD2F1QLBLUNelGox/MS5BQt
+Nh9ca7140ntp4cU7NFl7CI2hjqRPyMCmwCgpcoCZmqo6G3hXk/3uF7H+/nYEK+bV
+0+lhRuitBdktjwhY82GXnSu4SUUtjsQv+6gXaT5qu2jaJ+i6MNbJie9myqh1Yqid
+bZ4pbO5VEyIcd2eVpAvTohbXYT4iBO656nOhQwzNxvEPAkILFGSwQlETReJlI1eL
+QEBb7xld6v0e/EMH7U7eLQaf3YXK7c3dtAwlEanE6whS7CQVajZD1BeecQ+rQI5n
+UNcm8TZnNm8koJiplSVC7GvTUEJHPV2L9AkIvnG8zEtvuLlUWlCRZnaxGfkwsreP
+U8BS5y9CBSlBtAdYMaLV3kWtDXIx+pXdY3m38T29F0A0+kSCc2vEakZ/XTPWVkQt
+hPz0EU6OAdvEppwsgmQGzAOiz/tLeNg38MBvhZI+gOIKa7tMV42egmm+nlK2xeWU
+j0OmcIBaws1u+x5DT/8NhuoycWJFxH6zjCBupa29HBc34+irHXzs4rYYK8eUZbrJ
+vdUiPMOvmXEfsEyOU6tDeJvpWRjmUAcqmdlx1ccZu/7i9vRxbq0v+X00T/W8iujJ
+yGNbhbPeGoB4cKUSdXpnQznjnajyUSI4GUNkT4He9Fzt2PpgJQn4jLj5r9crlp2i
+f/U+ldZ3vWuqVhZf9XDTPyG+0/xuWq3LcoPxvOkn5kx9N4KXoiGciJiDuaJSdKLu
+sv2Z+qGOyMydYlOr4O47jX9/rKdO2MyayMLg1WbPi1/d8dFDDfmEJEu2b9AeAm+N
+ONudAw8ZJdgfTVGvTiu/O629V95UgJ3iMZu0hNetai/Ned6og/ixxoh/AILDyVSk
+EMEGHcanWMbQ4YlYbsabhnBZaKJMkoTp2DomzN4n/DiP3QMiAnKfUtcytSQngW04
+IT5S9mupP5UVsv7Kg/AWVUXnBdCWJLl48GUnCCPUH4IlMyoz34AOne8K1TvEZ4SM
+qB6FdY+ixm4jfevDEzj6ldu9tpWlxBL49w8l5Tbnzh0IjakdZG9K24nDYf+2uhWc
+6h/3XS+xs+Hf/8bXO0cb2jVldf7178j/cx6MwA86/cBU6N4YTjc9WnPPixceiDG1
+SXbqEavWw9LUo99hb8FeLg1yYOQ0ElVJMCQO73Z2Jfx9QOwjQoepNvQ3CGHpUmym
+NpRPfQ/uFhvfuGWktgAtz9f++LKqCadSGKYw9QDGYyysXfFcSw6GLF+GLoVOQGpU
+F9H+/6jMZrKik1zd6Lq3YVTXpM1to0tUzV2mZj+aAg2A6trIGkiNFEWbkrAAQ6Qi
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA1Cert.pem
new file mode 100644
index 0000000000..fe77c2244b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA1Cert.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: C6 87 C7 50 18 D4 BB 30 CF 04 B7 F6 50 45 7B 61 30 41 E4 B3
+ friendlyName: nameConstraints DN1 subCA1 Cert
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA1
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIBBTANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MG8xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0cmVlMTEjMCEGA1UEAxMabmFtZUNvbnN0
+cmFpbnRzIEROMSBzdWJDQTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCnk6DcIUFQfwdRiYfWRy4EZs8bttqWQv2K4Jtx+hcVARrTeyf3hXCnRZBclltV
+x7k2TZQcO6kekgMsxEZJikWB22yP4V+DPt/84pZJa9w+KIcunpXz1ssAfAGav2V8
+XgJHzxhd7UPLi3TAhlRR7n6WfeALE3al9cITYH8FPUDYOREbhLGMKpedvZN6sZPd
+gPVHztiKu9uOODKJAC/uuaz6/arV+3i/tBTEIDCSUWT55Hru7lbuWURShmLgzwCn
+rhnnH/j/5JzPX2/TQtIJFAPVJW6zf2AAPLBf2KgwfHRb6f6FqVDjH2KZUa1Vxt6b
+TUq2xWzJ+sZIqqNU67w5RirpAgMBAAGjgfkwgfYwHwYDVR0jBBgwFoAUQXhCRs1O
+qILn4Tnf96kWwAr874YwHQYDVR0OBBYEFOE4DhQYFENczudLYscawZL2ZoLqMA4G
+A1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/
+BAUwAwEB/zB6BgNVHR4BAf8EcDBuoGwwaqRoMGYxCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJtaXR0ZWRT
+dWJ0cmVlMTEaMBgGA1UECxMRcGVybWl0dGVkU3VidHJlZTIwDQYJKoZIhvcNAQEL
+BQADggEBABBmPe0Z8HrHPHka4JG5rGDs26rfKj2lIb74k3MJsuytdIUeqbFdCrH7
+dEjwAs+UvRgDDRFVWpWpHG32lk4hacMLHTV1zcl6gcdsOubVXfgodDLaZnTMtV93
+NV+cGJohowpkmbERLZDtM0/LXJWFbl+BAALPuJ91QwKdEKkImTBY63U1A4BKbmTd
+WtHnLgJjYC0Z53N761u7cwfpvxL2IQDKmFNHQI6dMkdTxSv5TOzPrN8A0jr63hg4
+D/QBm1Am0fddg+SNx34qbGpGgBorp5pPzowDCQWTJU3qbaJ7wTYmcWIE9uoDmaJq
+TaS/SCkPfhwzOPyKNt7KnKIn/acNHOw=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C6 87 C7 50 18 D4 BB 30 CF 04 B7 F6 50 45 7B 61 30 41 E4 B3
+ friendlyName: nameConstraints DN1 subCA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,878F62637E80B8C2
+
+SV/ST1+kWuzYixZC8kPSiVyzK1EkiPKBCf2L4QZfVVwIKTyP28lr9axgdCAwe6Kj
+R3HvZNoXePm8ksVi+Y/PyiU7cqwROMw7AW5RBdw+ujh4m/5OD1ZS1OyR3JpbnR8j
+ggYzIvwuTXr3tiVS/4ZroMYCMoBqrm1ODkm+qdXap22HZLpK3MBsCHTJ034iRdlU
+ZJK/p3aDS7ZrMJfn8u/PEYd9UiH2JuOx3hlrsJ+8yWayQ14X7FrC8bbPQ22OK5k1
+lYh4WHqyBe4aYu+cicgLax3Q+yLgWe6k3L1i2gfjQE0YVy2rU7YfXDIQNd6E32pE
+zVqeTIiQc1wmGrcCx8kTJTWKw5nIOyDDTq8BxDd6tLZwVEgczhtxF6l2y1Rck8QF
+KLlysLKd3DD9sIf8b25wxQ23QJlf5xKlP5qpkQYFqr6ygh95TFvs5MAVegA/Vh3m
+siRB1KwzaZnwnQKAmh9Nyti/Aa1xzFEqAge2JH4F/XukFiUfsGPsOBaH2DjsU1I2
+Ovc0brxyYfTxMrNjC2D2r7ukkvpryGAxRMgt0Jk9Hc1VFoqhpxvHc7Tf3KK5h7K1
+pG4u4T6lrAIpJKqLW+NgVXTeDNrWUs6ut2yoYang6wPSunudN/nAKwFJTNBnE1Oa
+pfzmmqsuYUowLY3NPfLBW1mltbE8WrL3M7SbugD3/Z6z9dwuICljwRcZlRKlzf8G
+swX6ZlVB2DJ6JSf+Uyr33tofCewgAGF8g/nFK/tDG2r1PdPavDGf7lA9BWUUD0MA
+WujLOa9+xn5IF+xu/9SNz1mAyptLRWmeimPzYvx0v7Yq14VcfFxNV2roH1hLH89l
+y0AFkZdKZzIzQ8Hgz3xzRAJKJCyeUVH0PRm76Uijxcw/7ZwjRTuEkuISmz+BlNEc
+sIgHnuAi4zZFp5blGglMpxCzx7dSngvXV4bcoA+iP3sCADo/no4/wG5ZNbBpRqd8
+BmQwpaQgpcFceV0EIvkG7p1zUZg/AD42Acu8lCSY16V06yiaGUMLNIYfdicCr1/K
+7jm9yhpsIvMQEmUmKA980rR0PjoQ35KKf2BUYDU5cBTNwWiZe/1CG3IRXkzDNwN0
+nPyj2/LW0bGhnzTvUGmcy5VfXIbDMKLr9FeKaEJ6696hkq7meEzbVHcN/SqdbaZ/
+dpXc5f6pP+Zu96c7hMt2w1P1J0tEqI1qa5nhFXJm04h6RlNSOesQEbSGIklnRSfx
+/z1jeUjVD9QKqaHQ8qKJcnj5i2GSOmmgZenxd4cjfG3sNwUU/W+6XUhmZBZKSg9e
+G0u9jeAeHGcuno3z+dayE5A1p0w7RpEloDp+401lTtDmbmqTqCQYuc4fhMjrfsqJ
+anro3XJC3G5R9mAcTxqVE4E6po0/JSYmoielNfmygL3pRa1BUtvjIkFubDnt/XAh
+9qExwWUiRZMaTYhoaSksrvIV+C87ZMwDr2XQwb8LU/CrwNsfOrAKdpQxVb+IxFRd
+7NGKnaGcW6UkbKzW75UeeK2AvDyF4eDWWbVsQxfll4AgzWKXVWeVY7O4GXaBgo4s
+Xby/2ufPFX9DBac+g9uSLHlKlba67C3ZVtfblRy99wcYOXjcR/lUcjlZ5ON24S4a
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA2Cert.pem
new file mode 100644
index 0000000000..64ebdc93dd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA2Cert.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 1A 1A 6D 42 92 3A B9 8C 84 27 B9 AD F9 B3 53 39 28 3C 4E 3A
+ friendlyName: nameConstraints DN1 subCA2 Cert
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIIEFzCCAv+gAwIBAgIBBjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MG8xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0cmVlMTEjMCEGA1UEAxMabmFtZUNvbnN0
+cmFpbnRzIEROMSBzdWJDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDYfm94+1UckIWrnwOecmHcjFD/KNLTJI62cn3LBu7L+B1RsbKRqB/a8NDKnSjd
+8LaqxYztPgbS9ll+67sq/Y9DTSGTep0wFJwJS2n+wBTu88BhOMwMX6JjyCFSM9a6
+1nzfk7X+mRGpcSyeqVABl173PxPFfyV2HSagyqLtwc/8uouKrdhcTFgTzsyqOBzp
+f4+OTB7XuXt8hYdgCfNlPbX2g8kH2Db4Lx7OcrJgP9Ybb2pQZQ7TiBRiK0EJa/WH
+hA96xmvR9Sq7lXnsk09f3lnP3KPeoPfd1wN2rRJ3aMl63dAbfBEdzX7T7Z3RJz6N
+bdndTYyo4SKwmO8kknp28pfFAgMBAAGjgd0wgdowHwYDVR0jBBgwFoAUQXhCRs1O
+qILn4Tnf96kWwAr874YwHQYDVR0OBBYEFKIvWINbTJWXt+72h7SXDuB/4JcVMA4G
+A1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/
+BAUwAwEB/zBeBgNVHR4BAf8EVDBSoFAwTqRMMEoxCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJtaXR0ZWRT
+dWJ0cmVlMjANBgkqhkiG9w0BAQsFAAOCAQEAwEwa9JZVYlDzDjZFQxuAlxD/pw1x
+by1ylmOBJnq4eUoS2fwEm75O7lQKQmgvLnWtvy3vnrocTKFTv4jSYldVGqT/Un5N
+aopCuIiH44Lr7z/daBQuSPsWPvtRK04DrNXG7BRj6bubn+DdjTsNT+V7HaFwBm9O
+8QFm7V2T7NmeElnxcasfNrk96eHgqMyOt/nEuvklmA5pJbcmqOootaIkaPfLlvlC
+eE4BlzmDApxSsQzHGHX7W3l8Ulow9BjylZtRRPZ2uM91kGattzhMF6t2dZr+ey2C
+BHze/rS2PoFqCFYyRyTWchqXnifv5dqV775zO8AadT36bE3vsRzKogXLfQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1A 1A 6D 42 92 3A B9 8C 84 27 B9 AD F9 B3 53 39 28 3C 4E 3A
+ friendlyName: nameConstraints DN1 subCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4269A2ECDCE2090C
+
++Qhp38Vagkg2P/lTyPzuTW/h59JEkrNByCVkqduIDtNYw4buUpCfJFM5HE51KH5J
+VeznQs/fFq8CHfCwNCNWuNzxORfdChC3B/yzAZ8/orcc64FCFu3+b2FTmnylZmL9
+aDSITryOjY65OC2g50LsZDmFIGEIDgh+z8s66/1wa1MtIJNHHPZK2ZQeXLsHbG4D
+n5ppN895s7tpvnSTiAB9UacY1lVw0Lni1COPWJo0I+83r+T48bCZ0S0Fl1nGyiiW
+/RveZURedIGL9j0bmsFeS/Ytj8begiSOCCvch2ASkWiH8FCPWoU8mWSYG8AzhVJs
+wqApVKZlLywEXrBzdMKY+8VCYXluvLV574I+sQXe9+C2Lz/MsL3i+4mNzKld/NFq
+SZCKFBiLAGcc10sN1j488eIWubUokR1FyYnRRnh2R6XYzrfHNOiO+EVvPHIVISJi
+MmytIIR0H6gQwgm9BcWTORI7P1ZFUawghBcyuD+/YnwZw+zt8iaoITvJH668d8o7
+r1v9VmJMB9UqKkiG/CmtMtV3mn68QzuTR/DEEBmDM/OI99Cc+2o3h36fvJe+szsX
+LPknnU1vaE/5KA+skvdHL36gFZ7b8nM//UZGtcMSkPxa6utv1azrLBgYjuc6wOtu
+nDr2tzovOIDVNj0zdl8+OvSy6yNXnRiq4cQMZQwMT2X8nmeBAUPmapZYW+4nhyc/
+SZr8G4dV8YBySbM8a4KIpLC8ziyDL7LGdOdCteUudB2RmFRSy9FL0ZJZgqWfDYxR
+CbZ3DMk3QI7vl09iAiOJKhwCvk+iycBI5Oa59UNs/YlQWI1I0U58Mgp3NQa6Ug++
+9+GgTM34nFn/VBBdH3VkHh4UL3QFhjGvMgTFmgt5f5tDsXV0oFbOEjBUS7hozXvZ
+sTMKJgcrxxKT8vRvBkjlaF2ypP5jiZwkx/7mrbe2trlJb1et0Azg55/B9wxcsYXD
+RKgADxISTvWykWIr28PMdWaDCGLfqx+RXNc+vEPXZiIKMWL5VGJ7m4gWXtoNOXFO
+nGGos3gbk0wNWhEENsSia9Gs6MQVngjz+6O8wirpVGBWm2oWazDf9M/nTZ10cfIB
+SVgMJpt9IUWVZHHyXwrp/vV5cyv9xoScWifMrAuVhhUYjEpuJhUgJeZwlfk/BULs
+iPCxdonnsT0GndyE/BvPNrIxzKOoLH0SIyjnw1shomGVtaf6yNMwSXJ9vCoSos8F
+X1zkIFPCCTW09lJZaa649XE5oDyWyhNh5qb3PQXkFGLy041lWhdMI7yHPcIL4qfv
+GuKbUsfv6u+PQ/PN94dHh4zO/V4WJCsEul1BpGlWPWQCcFE+e1k4j2pLhH38N+QH
+o9nUmSR6oM+Xy9erc/VXzwdwa595q4EgrUhBdcAsUzIS9NeyT6r+VrJgs+ZHFpT1
+QxTZXtizI12BJ+rsMgvVTEnp52/ve2R89NEFQ5arJWd8oOlG2LY9WO12QrmMqB+U
+odRqoXsHqBMJzd9rONGNgqYKnDWAKH6yjMWgYBlR6o4/8g2LaECt8F+tptPjTogu
+smXuFPCz9LAawfCVdJQojHp0ZkFwYZ8g9MgInrwQ1DPXKe6yeXS0ztYepn4Slgf4
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA3Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA3Cert.pem
new file mode 100644
index 0000000000..7e7e3070f1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN1subCA3Cert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: EA 66 BC 04 84 6C 50 5E 6E 12 E6 29 D7 74 24 BD CB AB F9 41
+ friendlyName: nameConstraints DN1 subCA3 Cert
+subject=/C=US/O=Test Certificates 2011/OU=permittedSubtree1/CN=nameConstraints DN1 subCA3
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN1 CA
+-----BEGIN CERTIFICATE-----
+MIID3zCCAsegAwIBAgIBCjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MG8xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0cmVlMTEjMCEGA1UEAxMabmFtZUNvbnN0
+cmFpbnRzIEROMSBzdWJDQTMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDELVS/5i1Vg6yF6gHTSfiiT9ULjd1sFFXz2fXI53H0P6d4KAs6CS1swI52BA/X
+H2sg3RRnFq6bkwYtkGdUBBLEoIjduP2ntNzeUH5Z+Wma9XiGXSmpG4W9rkpxYB80
+6B0H6sJ0wkSqWjcCLxsAO0E3xDlkSZIxLkSTeXv0KuHwKC/iqQk1yrjIrw05qhWQ
+JcCQRWHyovQsIomY3TXKrCzZGdlVzX0wBiu/p4uzgo41Fg5OCElt0ic6D7Ds8dsN
+DHANWBy8Soo6OMdgtH37U35HS7r/YQRKuxqRrmrv5yRuVnEYHz2oBA2Qdzemb8or
+KeV89jjvkZOqhw4RYQBDlKyXAgMBAAGjgaUwgaIwHwYDVR0jBBgwFoAUQXhCRs1O
+qILn4Tnf96kWwAr874YwHQYDVR0OBBYEFCdJ5ATZRfpsmJRs/O0NwyRSbVVEMA4G
+A1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYDVR0TAQH/
+BAUwAwEB/zAmBgNVHR4BAf8EHDAaoBgwFoEUdGVzdGNlcnRpZmljYXRlcy5nb3Yw
+DQYJKoZIhvcNAQELBQADggEBABeREf5wmcEhE5n7e3p8axLkSf8m+dzgp4ibNJz3
+L/AHhHQOSWVpz6w/4qerFs+ZpQPkt6SdPYmsyGSQaw3hEYZ4mKP1wYIRoBNN9iy2
+TaZsjZKMPdqoDUoQnBBXdYOOaLgOFfYaCD2AJRGbZlOqTwPZHHFrATZJrOfaXfqf
+Op+6XMfwflnRs9wt+2E6URRam/o9/i95MCysxE8FIUcFAzxr81UzOyWXysKCN2aw
+QxbWkWOlrjnA4+oTghMtR3ajzL8F9ryk5PYwDxpXinoGuTNbAfA/y2At09Y8v773
+CwAw83sKoZfejzc0m/+7+fNhJuaG4J4C02v2XlafWYAvY3k=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EA 66 BC 04 84 6C 50 5E 6E 12 E6 29 D7 74 24 BD CB AB F9 41
+ friendlyName: nameConstraints DN1 subCA3 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F8DB07284B0B15D9
+
+cX38pViubeCOwGjRlyZQuL7cMJNmDlNuxonZF0Em1JtKZI8u6wHOBd1fU9Auo4vt
+vfdQ2H0Nzn9zOt5bQ9ZNlAGyYKbyZStriCo/Zf7gxL1mvXQyOZoGHKYSG86HxAuC
+qtQPYyeAvwzOlXgAtHF3x4drhFJto0Zk5jwvYmT/Oe6wOQ/UCFhxBomFnHNz75tR
+yOky54EhM9dX0JFcnECnkJhzJDUmVfAA5fHKtYFgbBXMeTIXe2KScTofsWuPGn5m
+MfAOaOpb0L+mUlFnRQEKFtawADyAjEAu7hvS/8twCF7vofBwfrl3+l2BB1f1NNde
+XTWEFLSpMCGMUaHat9tVQumyjEzh6THPq+Th1NJ0ZfsH2JY511aRcXrJH9GMD9QS
+iHlc54H9Zp7gqYSbC56Zj1kV5Fq4DeSMNbDlYAOFjQriRq6j6gv63jlim/taMA4f
+pamugPEn13SW3TtN8UkFO41jZ4G8LUKDnsA1PJOVe3uzTd/4HVNBurXuqU6667C+
+E/+4OqonJGggY1W8FC1Y/P5qw4KcrlVFKZ+tnhoAJ7zMXFUvZkru+Es6/zsIIuHZ
+BTW/Ki5sBLG0BjgxBGfFiYvXOHyA12GFSEKnZJ79dLsianlQW6PXLdaMRMoAQtUl
+ojO/WUXzTfwfcT9X+HmBByKVXVbgFDQOLmI0kCO8jQ5p9KRDnKAQwaYGFnza0/Kl
+J7SGMMXruPzjkuAFt6GJY3Bght8Oft/sAM1mRxu6hpNVlonoKMxR6h3/vLqlQ98I
+HsglCKhJsUUwoKNSFfeYmUBDoHKD+n73V/WZAwIBC4uOdKy5RqRKmmddK2boEu4a
+7l0z5DEgpsKQiM9d78h1juE/obZAc/VKetGmE9aYTuWXLVwHbsmarkC7osY0Kft5
+Kk4BZoJWzf35yd+vlMKOaRrI1+XyHMXKpPDlOTwXwkLQ/mLPKbLfJZ/UjSiQv+aK
+dfMgcb+Gf06RjZxG8WM9mLApTF8xgna/G7UlZ2o/oggl2FFmDgtiwvK6pcNfbR5C
+hOKnDLFsFM36RhIow7jWE2OaJ6BF086O/o8iuhY5t7+Bdle35TrviqE3P726r3+C
+Q83JWKpNT2rP/BlPqyi8mBF7BuLttCgJ/xU4s5EW6a8hfB0M2kQMhFkSqw0oOeZa
+fJgdWL2jGS4O0+sK2Mb1/s26AC7ZFYKEpjzkeRl71/iNXB+vNlPoZoLvcYs7g4EP
+0ruDraCADs1+3rgmXeTzUPj3KAIUQwMk64YEosnj+oAF8ub7BNV0wtg0lUj1LIIf
+wc134En4br1fZkB6OsOWUgHwiwTajkUs1oA4ZnnJo1xqpnx20145L5val9CMluus
+stJlbZPZEAWVZezN6nKYeCD2EelGPMd9TYTy7DA/yH9qtEUb4z+FrMZVH8kPBSzV
+b5wyq1UDxDugGwUASVtueVUwnRB32gWoNAYLtO5sSdD0IPh/769yDKLQh3dw4wt/
+vufSZ6+dfaCsBGwir06luI0wA9DJRqSML4Sd5p0RKtxsZWzFo9uFPmLjQ0/w0AFk
+wIBOx9lcG+9MYWrz4T1Pizk5oMkr4xeD9W1iqL54NGJcohEEOPHvr2ng4UF81t9Z
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN2CACert.pem
new file mode 100644
index 0000000000..4cfd25d98e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN2CACert.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: 19 EF D6 CB D3 A7 5E 0C 9F 01 8D 1F 2F 91 09 CF 97 82 BC A0
+ friendlyName: nameConstraints DN2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBPzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+Fm5hbWVDb25zdHJhaW50cyBETjIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQC+uNFCmZxvCnJAo+o7l2d8518z7l5vjF/XBRG+Tdve0kCfVGy5A60A
+SlhV9UvADeYGeYaUdz3Rz9XFRYWClMFY320x0AFalq4154wBCqF4TkQnYBjyNqa0
+vLgVgSDidP2GaO8m/sNLn1fGgEjXJ4Dia+MzTgYPJJrD9nuAbEJdrfaQhGutvPAi
+MY8kOGUxQuVipV2OoY0N1mcdrJSHDD6nLeDF+U7Sac+dGFv5ip6Di8n5cLliSXjF
+cBlLx9LepOF0qYI7iUsHyjql/Zk1SQ6tQziobs/So3sXQOAI4tOfQFfNCoo3XVjh
+GU8ya1aLaJ2m1nWIw2bLXcMigGGF4EUxAgMBAAGjggEyMIIBLjAfBgNVHSMEGDAW
+gBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUo1fZW10Rs2D2AGuJUSuC
+wwlzqHswDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
+BgNVHRMBAf8EBTADAQH/MIGxBgNVHR4BAf8EgaYwgaOggaAwTqRMMEoxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQL
+ExFwZXJtaXR0ZWRTdWJ0cmVlMTBOpEwwSjELMAkGA1UEBhMCVVMxHzAdBgNVBAoT
+FlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGjAYBgNVBAsTEXBlcm1pdHRlZFN1YnRy
+ZWUyMA0GCSqGSIb3DQEBCwUAA4IBAQCXLrE60g7rdRWgaKYMWCgs6s0i25R+9SIl
+U4UNeepOEONu8pSbj6uUrtGdqPNTZ7HIXzYQ1mPAvz2gGM/KIfumIcZn+A6ZEwEi
+9UdHPF29GwEv4hU3BZ/QTxORGe5JxgJY5be7PCVyIr5vMf7RQFKX0W72Se+SK2MI
+vPosq6Iufv9L0rdURTq5QKfPXwq8WbnDlDzwar0puc4yYrqsmxvBfDN+9Z/z7gM2
+5uoL6hd0D1U/Vo07NNky2i7giYKrUkOBEW/kVXWIgM86ydsQAOsyiIepJTW3b1Hm
+gxUGkn20eEftf/QXo6gFD/o0l5dRXSu72Kh8UdkcJO4alD93qB04
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 19 EF D6 CB D3 A7 5E 0C 9F 01 8D 1F 2F 91 09 CF 97 82 BC A0
+ friendlyName: nameConstraints DN2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,16772D615E954514
+
+JOX8UzOOHGy8yxYErM12TGYDaSXLNt5LzZ6s2avjGWygxrEFG0ffQIwpLFpUy0iN
+ytHlkT9b95kizmN8egDUFKPfnkNJgbZ+8x9bfSWMp2MWnIypcxRdeijPj4Sfhcdt
++oHEQ4XPxlRgvh97yu8mNg48BMvPC5nSsd8oasjIxKra5y/U5B65H6knfKqqkCjn
+ylOoagitE2XZE4ScZ6EoXHsGTgPwHjQT/k76WDibP72i+0I2lcBUHZkyBU71iqRR
+q3KLydGQKKl72J7ATCY/jPVCojhRjaW6Mlg/UGJZCJWQC8NI5CRUWt+8y4d7i+rp
+98yJVogfVlVqIC7DIdst3w9MjNVMGIcEn4T2grg19NrHZs2LaespWP0IsB4Z/BZ6
+4GHFg6wRkEBY1b79wZX9ykO34CbPr0jIfHC21p8/Iyy1NuGHIhS0EhkBffDl8qgj
+HJch+e+XolU62jZmo1cwUSkZjGEH3v+Ev6dxw+sVug16x1H7bccE0bREqEIrB3nR
+r5UDUu9GQNI4Yr1C7yJ1WLYetUOga4n4Vbky1pk+31xgjzOgT2xztgfNMN+WMMMG
+rbsFXxLLGblgd4YEaqpSyCJnkjdWjFLL5tOVa8BxWMyKCl/ulum+SZjHWH1zZtSP
+q8A9l9nuJ9xhDfrvbQiX8MJOkvMhaAFCqeULZszpIk9pe6ym5ULGKBCVycFcsByX
++wWrsOt49fOrs2SrwMCh4R+5tNJmBwrOZCqQKCtv2BL0T+14dJ7BIwCgFlx5y5n7
+gC7IyHS6olm+MSsFFtv9q70CmeUC6FEnoNxjD/HW19XPsYUAMJ57a+DMrZDQfo/w
+0zC6DgzNk9saC8rauIxA9o7pII+ap44tkwrrT1nJ3GCYBsjmB8kvWCwwBmWpVc1J
+kjbu4xP2JBFv8Eb1OFL0tz3unduddqDHVUC3QFEBZGxAjGDdspnSUA5/FUo0or9v
+f4QeDyuQ6npppqmkA0N6d/cKkR0EmACo7siD7JSxOJ/XwIqrKurDf32MOxlOZUlj
+EuXx3PJGH9CrUQGaAAIeRBxNePsUr+lu5Hdg4eFWLU1JFy59OGLplzZo/mwd+2Tp
+gJ7LYFAyTUQd2XDGtVt+1eKWHVNTs5RUx9bysVu7A9d7lrKlk5AnklryQoLrsrKW
+RN8ne3JL/ZAE+CZE63QuRr7bigx58msb9qcoqnJHlEl6tdygHn5k9iOBLelO0Pur
+uNwYl+oUeyGaXOPck8ijIJ+arTZDVcVJ18/ArcmE8EMyh3wzZswxDem+XY744we8
+8MquD8vzL8c9HUidDlCD2rhefmkorLf9S0hH7xOu2ESfUNFJ6ubEeSeQ14L8/YfA
+omNkTlALanYMird55b5/RnEPRYsTFSqh1+rJBdEFUCSDKnlq2GoIR+UcoKzy1X87
+CLc9rKYCXHAQ1WiHKa2/56fq2ltge9VA6PRAqCtJ0tI2tRtfu8FLzNos+OK+plAf
+ZxPkqYd2FzZNqeff2nkNm8FHPRVDqKeRmsMpitFUV80L/yv4n749uiSjgJylDliL
+v7ANl0pAvWzifi5f9qwm6GiQi4m9CM2Mwiy9d8NKiIkvqStHm/nJYCfiYLY40tqV
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3CACert.pem
new file mode 100644
index 0000000000..c6f95236a1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3CACert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 18 16 77 27 41 21 D7 CA 9D 33 9F BF A6 19 A4 01 81 35 09 B4
+ friendlyName: nameConstraints DN3 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIID7DCCAtSgAwIBAgIBQDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+Fm5hbWVDb25zdHJhaW50cyBETjMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDGcxuyIPM2Ih2s0FbK8O1gDt0zWIuExMS6mU7Sy+BgUCD9qstR/BNv
+8YYUtepUZyztqonXiNY1STW4FjumzN3+izaIH+9Ji6sLrc3F7U+G/N0mzungENbI
+HzE8xMOzNiChVZOXQuU8S6OhYn9gQBRm/xCJlwPSaymBQz2b6j/hwQJjzQG/pwWb
+hYhDU64Lf4kDJ0MENkc8wlcyUj2dHEfc9jq49W/5FcG7Gyhb8XUGQAasV8mnc+Aj
+hKwliqg8HA6Um8yXpRuKBv1pSvq5ZwnE0oWSntnHKjcQHvRkn8JCIE0JYaLwwx7Y
+ZSCWux3o/bGAEE7uZdS354a4MUzK6PqbAgMBAAGjgdwwgdkwHwYDVR0jBBgwFoAU
+5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFAbcW77HEjdZpIpAdHwJnUU8
+SqHbMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
+VR0TAQH/BAUwAwEB/zBdBgNVHR4BAf8EUzBRoU8wTaRLMEkxCzAJBgNVBAYTAlVT
+MR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRkwFwYDVQQLExBleGNs
+dWRlZFN1YnRyZWUxMA0GCSqGSIb3DQEBCwUAA4IBAQCATlxJGDbeYJueWqOhiixA
+PfOIc2ZXmtoWkeJv2l8Eyoy3LubjUgrpZA62jOvj+0irrrC+Vd32gO8pQ7NYBwpm
+gBqRgbCKhPH7U1Igblj2twEZozkMC0BO8YLfzXngKOIb7BJuuhG8KCMVPVtu9/Xd
+Abov5aS8tJh0cKfi3d/eu8XpYsPtPQkwodpKSHHXFZTJlYocJkVGdDIO7cb/WfPj
+pVDkpZdRiX37Rlk7CBH+YddypFZhEnGm9e1bgKmF2xgB0MXMfWndev7XSO7m+KkP
+h4yxFJk8XE+erQQQGxWc1RMEsXTppijRrrpqirF5vDFseW9U8C+VE0VtFxFkxlqn
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 18 16 77 27 41 21 D7 CA 9D 33 9F BF A6 19 A4 01 81 35 09 B4
+ friendlyName: nameConstraints DN3 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6542BAA527CA1F84
+
+VnqjOjWVB6/8sl4/GjdA4vPe5EjTlxeppx2VkllUZHklNGNqpKbgrKSKKceNOngj
+GotRlpezuNh7kC2LlJgxf7pHimRGAMBEvbk5v/BkYjINVzHN82CUYfxswJclu8uY
+Sqw+5qBWEkfpHYfXLM9SK5DIgIcWzXGWs1ZHeriBF7LzqDUbcNC+V2OmN+tTGTt1
+1W1rPHhVsPqKn9iAHMhzqPAOtZafOKNZKcT6wNXjMhstmNARsv/z8o1kFTTjJdVI
+hnM2ve0XYcZVGW0oaoKGcv0IFsYTtay/2KMA4pr2deC8L5d8pPgXbihw6DWzSnD4
++VT2ehJ2vGAdZp0wfZyjFhoIeaeM1QMuoFdcHqzNJZHm34PSzHsuV4D7xiPZ789M
+ArnY1lVuNrwSRvSb4vnbc32Me/MqzCoYCcvt88uZC3Pymr9TbhcvbJRCGUsrA/EC
+nJjTJaVOhtnurdA6peIPN4yyXVBlG4sq8r/tdDPOMODmTT5UWo8lI0fuI1RtSnT6
+OfFGGgMlwMgn0jMhxN7M2rjX+14ieVlNI+fI7wqoPMpP9x1clj8fZxL0RZZSToZ+
+0RKIFGPh6LqC0P6rUwImPAas3GAKiSH1WibfQELcht41qapYQrlcWtwVbe6c72A2
+9L6vINSHTkeRjSLa2M4u2rm6CJOzCCtz6t6v3AQpkdFa5MlmpFTyDN7hn5VmAXMX
+HTiq4Wp9uhQ3Y6w3XEX9ubVriEzBQEch/gx1gYcOkHGF2KB/uyu1rwk62KaxUNcZ
+fx9/uD2scPQq3qseo7XM3+9LMXsUxxnEeoWnLKHWO+fBbloVYduhHNZEi/r9QZ+U
+1HX6cd3LeiCrS5gVZ/GJZ7g7qJzKoEk9C7qt5Yon6+AXsE1l1GETlfg45Jg70lyN
+lJXGuAjFmRTdW4ijf/CPmqZQe9WWUe+3VowhwmBL1Yv5xiph8kfvy3KxpIdN6qOM
+05bQ+hSOSVQad9SWXr9fYi3o0JXMfAyptrydnG6W5KHitvHNx3rnY5PW+G+3qPdF
+fCiaPOioPwfVSKTs+pcrUqq98C/7wL7m8PJ5I+MmNegajlo43j7n9CKLlbl1NdnH
+RlNUI18+J4bVH0xX839jo9hil6ZIJjvs8BEElLzy3yxLN3+vBNdX9zuvu4TL5+7h
+zU9HNceug4VDq+25AoqTWFHbD4Mi56EAD4JIt+ShGvVoJAo25vZo14pasRmbINzt
+Pm0HvxYQcoDNdtif0sSxNZTQbUdCaojyve207XgRVGFkOyJeOsJbwxCWehOxN77f
+aPJgTDeB4sqEX8//12AGRlAUTHG1VsXzvHgmLJjQsZFAZD3mlqB3BnYzwRmH1x0/
+K48OtW2N6W+Nh3UhIy/FMXngLBbZk65wBFmXqoSwjC/Jk/Jyok9EVRkoaqTb/zgR
+ev2llY82U9J+hcmUoMN2Adylt7Ts4b3m1XJiO+vW432L8s1jjPaHLWnw+OolqAel
+iGRQ5rBJaD9Y4W02P1erYIRgOeIBvKaii212yGKMMTTwU35c0o/cKaXrr93tHgph
+YL1BEknREHg3KkmRSd8U8YKe8eAOzHHidQ9G4pmUSbo1hgds+t+yMgVMWzcXKvVP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA1Cert.pem
new file mode 100644
index 0000000000..ecb84d4733
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA1Cert.pem
@@ -0,0 +1,63 @@
+Bag Attributes
+ localKeyID: 75 A5 AD 55 D0 4F DA A7 4F BE 76 2D EC 06 C0 2B 78 4C 04 91
+ friendlyName: nameConstraints DN3 subCA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 subCA1
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 CA
+-----BEGIN CERTIFICATE-----
+MIID+jCCAuKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MFMxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4zIHN1YkNBMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAPnsQIGHFaqj7j4q4DsZNAUSd/1bjxVoJE+G
+wqa4MeAzBStBHuQAiUJ5PzxiTWtiUklQWrTqssx5qEAjUh3xE/muB4b3N/+v/A++
+oeolkUcbaCGqRUr8pQA6aYQNZJr3XON/6VOrLVwkKiOMAO6Ur8BZ2S08I2r+38aG
+b23AUyGQB3sFkn4TmC5eMSsY6SXBvr9bqsXJiT2DuORbB9sk8Cy07nOI37rO13el
+/51naQOf6/3S7HYYBemL6pIVynu8fdhmzZ9l6CHy787KDMOs+QJINoa1qW754QwB
+wLIINtubz1wMrgs/DWpx4BwSidD+L1bGOmTaFrT63lHb25NswAsCAwEAAaOB3DCB
+2TAfBgNVHSMEGDAWgBQG3Fu+xxI3WaSKQHR8CZ1FPEqh2zAdBgNVHQ4EFgQUgLzH
+LveOGn/xOHv0Nevd6VjGPFAwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MF0GA1UdHgEB/wRTMFGhTzBNpEsw
+STELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+GTAXBgNVBAsTEGV4Y2x1ZGVkU3VidHJlZTIwDQYJKoZIhvcNAQELBQADggEBAHCI
+IAnj/BU0M/5JGSoDrSkxi44+RGnAKP/18kgU9hGMgm7GBqJ8rb1azbS8l6u6GW3d
+qPyisyXvr2ZBL3L08mgkHEJgRh81KQ4pGID6RGghB/DYWfpyxetMuGjQnkD4eHJQ
+RriILKNU1JIUEdF/uQSucYCnR9tF2SKvRhSMvQipNKTpHfQ+utig7wIYvFkmc9Rn
+4kyoAxjoj6IwdqiFBtMoePG5R9xk3nQZsjTP5WFS+OyNc/xYLMXh/eQ15C+BC4og
+1FGFlcLSCI7tvgKYXk/kpWwv4F2pxsvjBLgZq6IsNbCTBNxxNp+QOID61Xkb1U73
+cjSJjvAqxW/yqlz97bY=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 75 A5 AD 55 D0 4F DA A7 4F BE 76 2D EC 06 C0 2B 78 4C 04 91
+ friendlyName: nameConstraints DN3 subCA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E34ADD6471D8898A
+
+7sPFSxXBOmlBeDtJ1BQOCt+i8p/KMgAfLm2Tc5EFeRYNfZgZ2xZ64v2rb43aa/BG
+4HQgzPhHcnfrTb3nS+HAzq4Kl6Mczsp6HKlH5i3MFncAjBIbQbaRBaSOhSX+lw3L
+AV0t0CV9vsUlolls4ahGQbwx6JrsQI16+2O6WZnjnerWx3oOdVoNVudc79LJvj9U
+n6t3+1LO2VBwg0sO7tTzO22h9ugLtDccdtF1XGog80mrUXxGQH+ccMwE61h4By8q
+5+XBnZ7h8trq1hmgp2c/QHuGGzbk0m6txz9B1gtO+X/hCI67uYB/P7meg3OTyeRQ
+ppCrbRiU9xUb0r/umlCFGOwKP7YN/V8LAMNDuOYb06z2SSypkoD9op4twtQhXkur
+1BIbSdmfmSJmBQljEVZop9XMMfwIeZMwRL4C3qUH8iO71rFTotbhdapqTc+4htPZ
+0M2ebzFCF67H/PXtTkk2g6tb4o5qmnc7oaYGtuKgds75kJlxvgxJtzvMiy5xu5iE
+zKzM5qmLb3kScb7gdte6mOuyrFW5Hm5KHmCsD1mpkoEJckxM+TEmPspcfn4n26es
+uIj6FAVL7qxNTgunjbl6amWv0V4fFyL+d7Fc9uQTJ6nms2pKxzSIym1R2aZnCZ0x
+EfkMDlmp3ebv8gnWG5svqtt1BT5laTuQEFK3CXtizWwJLHGbTAdZqngR/EmamnP2
+d6XXEbNp1ZmgHDFv+2aWhv2djy0dqZkLAQnwseYR8SD/LF9A5NfhRePExqwDBWPL
+De/Lm8U5PjgjfAWlYnIA9Wnt4p6Sc85/q+agl6UKYvMdcgvfPr8R5fVJNStleMd+
+2IOwbc4nqpgATB5jziwhryxqiZ58DjlnLVc+0sZeJq4ptGTVIEzF65UHF7zU84yZ
+NSMyaa5NJkAW4Uzwv5a6VrQvigBIlBg1BYfSxqhFdLrbaHADFmcqMJQ7mvIME+qh
+sWHLrreFAZCs/IbuWl6WtdBfVl9AAu0z4mtZQAvg2v0XesPKuqN9KWFTnK02qa/8
+gs7j1ojjrSvPTyzYXPJmZk8HP+wbYBrTmDFJtPqLEJVv7GUg39rgiP2mnvwptmBy
+Wk85arNyHpqR4H/Q7X7kC5KB2APuUwQOGXr2TR4vgHzYf6O8pQt9bEMlwshEYm2S
+LXYKPodDQQtMvK0oarZS/FgnFGr4p87u/+ojhd7oB1WsEjVR33hQnC4W3QWSbDSC
+d+ftoHr18A16f0VFdPWfIZbT8cA/CM9u0a03FGL96tNKFPs3irhuLDxmld73Ai45
+5Xvs5xQxF17471ipPc0fW3esbEatNECqAZr8RkoGzmsWNR4w25LNR3D7KhGRYJ7h
+DA18eKlK8jtxhKc1+kb59DgbaN2LpRS+lpNS2BqrAWKCkQT1RMGlPl0ODJZYHut5
+fiDXY5LCEHBE31I5LbqlrRsyRJ31cW2r/O6GlX1XPnaiOZCRi/WtOyRfzkOnjdm9
+Zf3IZV8t5IMSp9x7cYHSzh62pveR0XF8RV31VylB7QXhcwtGRHlgYncryXZs/2yi
+oXxYDTCQcN4OIhX03OpzINOW3VKkT5XXhwxYCfgALCNid3+Q0qPjVmlMUQFNvxyB
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA2Cert.pem
new file mode 100644
index 0000000000..89021b4c0b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN3subCA2Cert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: 39 9B 1B 2E 69 1E D8 FD 4E 2F 56 36 CC 48 46 B9 A9 28 E2 45
+ friendlyName: nameConstraints DN3 subCA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=nameConstraints DN3 CA
+-----BEGIN CERTIFICATE-----
+MIID3zCCAsegAwIBAgIBBDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNv
+bnN0cmFpbnRzIEROMyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MFMxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDEx
+MSMwIQYDVQQDExpuYW1lQ29uc3RyYWludHMgRE4zIHN1YkNBMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMTpZN/9lfu5qnSxBzxNYREzs0oW+EkQC6dV
+6lTASGBtvdK2rJyFeuhlKeGsmRrF/f/oLbGHodn8POv/vhGA5MFUty6gyOQ86oEh
+p/J5XbjMtVd/MGk+oc+d0gvrvN/SdqLpSE1u0hTkavMfEd44PlnNVmnT5ksN1Lcz
+yA8QLBuG6hsxEQygs5m8lFLgftMdFRUI0/OKOVp0MVwCB+LqWqUKRsv3jgH5DAcP
+ZyQ5Auf6gkH74uxQKDsSTIuz0PRmeNDTaNExT7DXysaafv3Xat8/dvARlcqlICdb
+UrCgJ8ccpEqlcdelfwEqts7i1oWDOj2F2qct28YSpmi+4eWmacMCAwEAAaOBwTCB
+vjAfBgNVHSMEGDAWgBQG3Fu+xxI3WaSKQHR8CZ1FPEqh2zAdBgNVHQ4EFgQUzATt
+aigdft5k6gCIKux1Eb+lLmcwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MEIGA1UdHgEB/wQ4MDagNDAypDAw
+LjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEw
+DQYJKoZIhvcNAQELBQADggEBAJLF4j1s6nKBt1jK6gDyUmQurPyPtSxoGKv4Ji2G
+ChM5qgFvkqj14oEhcGA0I3mjl0uCmGbUkMtrzDbTwmTAzs1CE0NmpMkAbsde/6Vk
+L5biHGP0HlnZwJ+79ol5ljpCLKnRETUnrh/t6Wwmkxar4K5bfDFG55jF8WFEG05y
+k1B69jPLilyHaepHYd1rw+eqE9x1me2ESMJ40bv2mX5Yx0QgSaeKsr1RbuqiNwhs
+LQ0HrQkQ9TsUfVL4g4KmAd+HaSV3lupWX8v9lhUJkajtVwf/cjRmQCOCb8vUHhoH
+6KvWIoq7MiyydVHykCp4rL8NRhwCFoHGdGIMdRQhvXlMtR4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 39 9B 1B 2E 69 1E D8 FD 4E 2F 56 36 CC 48 46 B9 A9 28 E2 45
+ friendlyName: nameConstraints DN3 subCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C709F657F16DDFAE
+
+18YCCI5fJ4xN2TQNJMyjsBslG2Dsx7ImeNdQ0STmo4wuz0KwnLuVUrmUNayFm18H
+GJHdq3CP32bfubTBz6rYYNd3bFOQCzrOZAOI10GkgXnJ6nBw/VtL3yt2bDew0nV+
+FBxnkcUIH+ur2IAGhvqNO6P/QOyKkmkBksGGWIHNM304AimG1Xf03zoQNUVjX09F
+syvCqPNGncJ9rWHkk1ayOF8MzW/hNbAyJq6Ny5yssx7coJHluVsqm7763++d8UwN
+AmdmUJKSQvr23vUMd6yG/Es7T88VmE6DP7a2cL1yPpT8tHWmWAot+cxKMYXWMkof
+cZCirDHo4z6r5DLBrnPjxJ46JT+wc5i4fFMyV4eFJEOZVJRxgvrIrb6wjV3BvQVw
+lXml2H7j1p+NG5GeVw2IW9VNkQOY4yjuwaC0wNuujWBZ5LHqZqyOm4Cg6i3tROfE
+1j58h7Xau4X0FIkWaVpsVhmrrs8wL9ukLbib81QbQDqggNGh2p9/oNdm++8egH2W
+odPLm7BPVX4Ch3ZqZycrE0DfLbOrSj6w+xywziRfEspk62fsWW6TtobGP6Kgp4zK
+uZvCOqwOcWe7qN6tgPcTIb3lroFyD4TqliSHWYdSE7y6S54T4qQ9YYs674Mxxgwt
+sY0FATKPv/gCeTnc+UoYjLNFVGlXrRVGNvTGRl/G8j9TKc/YaA0IQnuynxPB23b+
+Nq+exmYLJcQefdSgZufN7BXPRT5J1TDzeGIyFGx3MpflrXaisMMGwpR1gtq8lz8U
+ve+LQzcZgYjjUIv4gHnttzBkujWb8YVIs+fz7+nyTZee7dWgfizng8atdyRK1MvC
+aRf2cWczBsljeFuJ9MXqjFMxr3tVsSXhvC1K71gAu61VY3IcUSje5nqIyiOV/Ltk
+so/+fEjuz0AW0Ooz9+a01LtfYJ1cZXmZg/c/MPYB/iAatOpBzwXLMw219hsKDWRn
+FOzC52TixrBwAI4OIL8PIFUm4LgaT2yTyaUWmiVLqRckRP9CCjdvldzLb+4MpOdN
+Id80/uRUqti6+BsYUO3YM1rqDU6mJqB57iOCD7wLOwm7nhIufEIxxsbpTIVt2cn2
+8gqEol3HdbEDV+F8aAH20LmMwLVDAabG2CfwuP11zr34QrfrmgvIGNGC1nA5gVt6
+0NGJ27WNFRdalQIsNomS9tcSZMaibxGavpIL+IGzprB0b9sTbKnQv5vF86OzZcZ/
+yN196/A+8lC5/BY5Tg4L0VPj1skcUDKCWEBBvmeCtJHRaI0dsvYHsQTSz1upS6qG
+aE13waI3Zy4fWXYSw3bTSKSDFYBsn+g6l4d6lwipP1/fIzzj5sRM1sGF3/g4kVld
+AvR8eUB6cgB1a31Kg8wSfXoYEtw17+vO3rM8ilfcUWwjkJ2gs52Fzt0Dpv5/rwpx
+IlsjRiDYDfiMTwq+svo07GHTrkkehM5YkXplbfNeCPDdLQAAH8SWnki3TsjXkgGq
+Zz/lVyOUwOGQDJ65LTuGrq29LiRBlvSjbTGRGruM+Mzp04Z3lIeJ26CJHW4YSopM
+oGye70jk6SeM1SrMAR5CIjwq/6Eh0lYAiowu+/couAvE4tscUvhEpp/lm9ODzYEj
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN4CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN4CACert.pem
new file mode 100644
index 0000000000..ff079ae27c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN4CACert.pem
@@ -0,0 +1,64 @@
+Bag Attributes
+ localKeyID: DC C8 39 E9 6C 68 80 7D B3 B1 0E 2F DC 53 7F 33 42 1F 94 2A
+ friendlyName: nameConstraints DN4 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN4 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIEQTCCAymgAwIBAgIBQTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+Fm5hbWVDb25zdHJhaW50cyBETjQgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDErlH+siiNuSte+3eQGs7cT2LBjfndbDv/SSKvazHDGHl3jg/m8OF5
+650gFQ/vi4HVN8IXfICMNpWL7XKTvpwyFydsPi5DiabbrdL5lQqugKDxVt4o0AJ0
+IcEzji7w0syAaJoCXmX8inM4NVwDKuwk+3PYFBygOPn3C690tVHVq6Y8eesqsPam
+d33HZNpq26KLEkIFvGQPHO7q2jPGgvXH6X2njhewKzy1iorJgH8fYA3b6XtdqLZF
+OstCkz8l/iNTBab+jQSB4bdwuaA03QaCaUp6VB8nvZT1Bleh+4I1j86wGw74W132
+A5iGpedSFqOV1vFhVKg3bCz9ZkJZVtorAgMBAAGjggEwMIIBLDAfBgNVHSMEGDAW
+gBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUbEk2rS5YiRI2UUE7VFIm
+JADTynUwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
+BgNVHRMBAf8EBTADAQH/MIGvBgNVHR4BAf8EgaQwgaGhgZ4wTaRLMEkxCzAJBgNV
+BAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRkwFwYDVQQL
+ExBleGNsdWRlZFN1YnRyZWUxME2kSzBJMQswCQYDVQQGEwJVUzEfMB0GA1UEChMW
+VGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVl
+MjANBgkqhkiG9w0BAQsFAAOCAQEAbbKErwqLymnsshF9fWoJ7Q34GSpXkfvnqLsM
+pak8iy/VCfntv9pPMFhpvAT6F4wuoGN4wXhyQed2ZuSNZlu18fSIiU9aymr0eyJR
+XuNHHGjVe+5NDfNkHWVX6sQoH+fLUTQy7SmXK5zFrXynE4GJRTzq3oFTTdnI8HGS
+f3YE3wpv0miYrKV/YUz/Sn3v/FV9jqhUU+uMqeOE6o03FX+6wXuZ4FWD6vhbLBpg
+2GG3bjZ+ZQAShn10yvZmkWFyvwGinzcqKwI2aotX4eKGTfE1Mx8eFoRVO/1Iiu53
+HvrXVQtKgyQkEqYm8py+fJbg7PZ2z+2bn4b+5F0TPI2sJJ2ihw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: DC C8 39 E9 6C 68 80 7D B3 B1 0E 2F DC 53 7F 33 42 1F 94 2A
+ friendlyName: nameConstraints DN4 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3A4F6CA0E0C61E15
+
+cAWOiLGDU9eGOBuNBTTGZfIHH0FPppsWGrGXqNdf3z8RmbG0+Rl+gBsravN5abeI
+q/zaRtr0juFIexQinQKNtTQepVgwOiphhpwq/J7qFnssszz2ozZCZlDmz6nT5msz
+upbgor44Kby6RgUlIul7ZTAX5vlxT+yCtkA0ojB9UCpAct6Vx5afTTdRdfeoeuEX
+d2//Pv+UvM2GVRU/Ov8O6yofSkVCM2cE9VR+LKj24aA7D9l9qD1BeA0t//S/Kt+k
+u2VxH5db4e+Ayld8tC/LapNmS/Aucw1SrJ715Z8HHlA0hgFqZnRSJEk/e6x03EJn
+Qud1lnVJcp3S1EOZ164zftcairA6224YseKhXZ2Hk/iuczFgMMIxbTJ5gqLSaLmv
+yx7JbX6HjLZ0NtfG0//KKdFnKpBPhs3HrdYPROBp73gkXnNn5Cl0YQEILeSVUpLf
+xc9GNY9OikSITV9ELWPgAmlbS+6/HI/9ep/CmlL9b96wcCjLHM2UUwYzqSnUnn1J
+wNpNWIKBWZepHpIJTLLKVmv0B5SMgdkVyvpG3YL7OetDG0GiAlbZae134jfvRq7p
+yj0i8nboCeKVLVxwvSKku47zQWi25cO1gaAyfnCJ3ODPuVXndrnfT9rb6g94qPF5
+7jCfffTOAEL9qPKUrqXI0B7WU39SwYsYaH9GJpuMVsl98JVxbxyX3AlDmoECHYrI
+TbbmePE7iojxNj9JpJhuJSJwdK3HhGlA9mVQt8alx6M+G474f+cmdcxtu6AmV3en
+cKlYFke4/be5BgTq1zga0o4N/pom1b8nBhX1tvMqhaEA4hAf+GzYJ6gFJ3SbMbgQ
+mCEvjtzx8zmjBtiaJX2xXfMYJ2lyWUrdv04EUQmU/hEoAFLE9tUt/YrDD4DLAOE5
+1L9QlWi5Su/2HwHbA5sSstDsbn/WSvuGYTpFU1pa3ugoWiG47+lzc4DZTsUC3yBY
++A+v1yxRKmtb8B4+vE4Du1umzPmLdEVtVFs1csjT4dHTLt2ky/bRmRCD/YReJKSf
+s656ZBMF9cqViVeCNIiMICorENMMw0nSb78m6kOt+pVhaHJ2Eq5VIY4emRIsIgpM
+FbBDEl1NXY32de3rki1tbLTwcsZK/ffLcyWB5pHFRSahQYVbcVYG1jeLX+Ecyo3/
+lNgFOY3xp9as81NfGztiCG0bs90LxJNIF6r4MxWmjLZb1SQvtv8YIuC9Yt08EjO0
+S7EwT5EzHqnmSnWeYZS8jKUbEmC3qHSDTqVWG6++2FA0M9ZQ4GKvKglwZde9MhEN
+6W8B8Y7PZeNKaY51l8zAAvqQJuQVVnAOx4NTsPMS55oRd20tNOgOy0DrEpC4eqVH
+gwKU4WWftri/ys9C9gLZNxA7GFNTmJn7X1R8EANO79PLi9wteal+surNbHpeofQ9
+4tr+04p019LjZLeuEwRq9BvVoIOZ30X0lkURts3azLpyOQx83DJqFb3chS8OV0d7
+SsahxX1+dngcrtaS1kyP5X9AQ8qYLRAKP4ObMeBV7+5X0IVxnUjpQIvuEPiXibFT
+pm4AVXB5qxnuXiJ4fUXAOW1tmJTYwwthygNQvE4nVEDVfafT8fyauQLWhK+tQvNu
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN5CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN5CACert.pem
new file mode 100644
index 0000000000..7e1053a5dd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDN5CACert.pem
@@ -0,0 +1,65 @@
+Bag Attributes
+ localKeyID: C1 C8 31 03 AE BC F1 B4 A9 00 C7 99 75 9F 42 89 9F 96 C9 2A
+ friendlyName: nameConstraints DN5 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DN5 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIEXzCCA0egAwIBAgIBQjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+Fm5hbWVDb25zdHJhaW50cyBETjUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDuAvtcHk5Gye8SvdckoKSvZLwTjNb95iDOOSpUaijVx5NcCubuosIX
+n6Hcxc4FI+z3vjoMQr0SdSiATv2QUFvYDkvAXKuZGrWE80oB693w6ljI1iVsT9BK
+O8VBdSRFtUaH5fZWUds8Ed6G8TEcybyp/Fi301rGBtcS3Ci4s2eooruWt1EbZUjx
+XhxebXGD6xeGgifVtVvZTUySNJNMLxlBAKw4zYX4ZbB0SO0sSMB1fq/OaDvRvBZu
+mxJOBCzC7TUl4rhfi8PWaC9gdrsAgIl3pMt0A9nLVE76HL1L5kJnoZDfwFav+/ix
+3Rc/PIQ7hqTe+LK4MJ/QW0lZRYesXHrdAgMBAAGjggFOMIIBSjAfBgNVHSMEGDAW
+gBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUup8JypA5nE53Wuv7EJWs
+06dKXScwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAP
+BgNVHRMBAf8EBTADAQH/MIHNBgNVHR4BAf8EgcIwgb+gUDBOpEwwSjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGjAYBgNVBAsT
+EXBlcm1pdHRlZFN1YnRyZWUxoWswaaRnMGUxCzAJBgNVBAYTAlVTMR8wHQYDVQQK
+ExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRowGAYDVQQLExFwZXJtaXR0ZWRTdWJ0
+cmVlMTEZMBcGA1UECxMQZXhjbHVkZWRTdWJ0cmVlMTANBgkqhkiG9w0BAQsFAAOC
+AQEAAPGe7Q+EIK4mWtMfDbJlcdLNvAPB8lvaDyM5Tb8cnsDALQfDywVfxhFgNcP9
+yPE/NPEo6icOToJKE5wv6/jA3eEs1CPK1HdadnKLMzp2xwcUo6ztMHiPeyGe0amO
+HbqUj5dfo8CeNkFsbOcSaCgN9FQl8cQ8/nld3pvX+/tacajBrKWBvLocVTnVSGWx
+1TGsB9JkuQtm2Tvr45+7FwzViuu8roIBtFpNMoWLSDU+SG5BB+BaKPT1bA+N79sk
+EPGld961zpkq4+53ZsUaaC+WVoXSRaafXitou4cFojEglrhqW5MkmaPDpmBVZ+ke
+w786OZvGQ3aNK/RAKRQ7fl4y6w==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C1 C8 31 03 AE BC F1 B4 A9 00 C7 99 75 9F 42 89 9F 96 C9 2A
+ friendlyName: nameConstraints DN5 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5ED7185F5A78AF01
+
+CmjYjyReYVctbc3Ag8DVeaTnHIWk/GAWikjYoyNjtSwt/4mya32qr7nsjoQbXORG
+ETInKRBRp8XI/i6laLA9pjBHrRCdnLQK074TNqaaOahvIe5NtjutwMpwO15W1FJn
+2oUqyoIqAOcljLz69S1VijEVIOB6e0Jh8ocY8DKBWwYgscmLlGXaHS4VeAGpRpZs
+XRjv14N5OpzctaUoJKNyCvbbXrQYf4hBfxxDfYmIoiau4jigS9oPKfvtge82TmpS
+kphZMEGJ6NtRvQS50ug69y1thWhwHGZZw4gBqyspvgwiYIpg/ABWFqUBzoybBqm4
+EoV/3vJf9Ivig8yarlUCIc0Wf5PYq/T/NdYIk2LRdsL3Cw9coMi23rqwDp1AYjUB
+POzs2+LJXduckqb4yRwICMSrGkIc0R0DhjlLKRru8ca7DdA+qOw0vMCw1F+zYJBb
+6Nggy00egJWwnkvBEvPZfQSsD7kyElrDchsAkgzLsVI0Lbr72z0b+zuNmpyTTynB
+II3oV2u5Wlo4MiCGzqeEZLTWv/HYtuD5603r+EgAgBm+sjkKKVahkBYlmX4BiPoD
+VWet31kqCpgfrriN4I64OD6fqFoxooc7JbYVwNeZY6+OQZBuL3o3jC4bOFXpjEJe
+VaOGQNd2yHq3K6MaiJemmcuQtUt59RNCxWEav0yhHYvltXkyjtSdWhCy2g73MJ6H
+y20lbiRlykliQbxFqtXDUBauHVddNblIByjdNziHCVbQskaX6nUv5nMHCBzc0REo
+/Y1F3gPernpRUYPI1SbUa8oTwU1qpAq86TZtAL8/ceQfyZfytUya1uUtDoSlbo9T
+BnjgA5H+aG3/BaPw/eacTFr7KPmxM81wDhkTzbxnRWLxKPDWuR/ofoeJIt2pCME3
+oACdANURd5uJy3sxUrEe14n7uJ5DN1O93m47vaVSCXaYfhpW/H6GvBaUbu5ghHqp
+zfbmTm7kNbWuL/lag9PjU56MazmJAx9XozsCZKDQgHvYAkYZmc7sU9xDcokfRtNp
+EAKfwMIQt36DYXzkgho75DpIggKYIKCqPgCYwWsEBVO3ci8iwW8/3OkFM5k493FA
+KRtEX2go9oZW0uBWLmVjhVOPJ2ZxGzoy0rzPFt4znyPKa4aSIrGhCf+xequgXeV0
+1G5TGcEV/MurHCItd2WNXIo5NvRq0vDqH9Ufgxjj6lzhLY77Ld7L2HSTudjgC2jA
+iKauatpfcdwKz9wAZFLDsL1TY6nFPh36fR5wgEfvpeM3q+Y682gtLCYKsmhSSMo2
+s3j61X0Q4rOBE6u+0k5dXmNyHI/BbuDf46Li3tahW/tcyZFx9y4JCgzB4+1uN6DJ
+qndgMC/wtakkDHv35mYtNnoWSOKxryvOA7ElJMtXX1ucUDHetBEvqN5I3cH9q2HA
+SbB3Bqw+40qcTbj3p7nfhYZs1kJQohcd0IPanyhuNVobaUFAePk1JjyFtZ7OLVL2
+7e9pH5jNrZypp/BIMJcGE+edSu2yQxdLAn3iZ0qWXz5y2zXwcm6V2rw3W57427oS
+LsyEiN2L3H8iuQWJMVBcSpYv3050ezySpPoqqkmpGE/EmqI7vjm0wA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS1CACert.pem
new file mode 100644
index 0000000000..7497d63215
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS1CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 8C 78 65 B4 6C 7F 97 CF B2 14 61 5B BC D6 BD 30 33 90 B5 0E
+ friendlyName: nameConstraints DNS1 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIBRjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIDAeBgNVBAMT
+F25hbWVDb25zdHJhaW50cyBETlMxIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxyZIOtzAZ9n+6Fp6UAqnUpZYqyvCKSvTt0W1Ww2idbDJFczQcqX9
+lQDy/v+NoGkpQbjqZdrATmomnujiL4AQVpl01V1XJPLySeVOqToqhbzifoy+RBYq
+sXewuEDBpy2FGMaFz3JIK8mbK/qQOBFOG8fzzv9gNIH02AQpdC+J6Df3TB0utyiK
+PjHHGFWifSswFqCHGG7geXeE+Ep+iqIm4MKKtRIG5DeHiqugcHii+HpaXFASVkIr
+Eo1FmWLDE6Ww8m62Si8WQSkPfkcEMGn8s9MXI8L0DT5OlkIVvSs6Fdd24gJJlPC4
+lrF5g4P6/UPHFvyphDptCkqpbkBKQEBXUQIDAQABo4GlMIGiMB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBSxqhfw48/M0qeJpoMH3f9u
+2gfjSTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wJgYDVR0eAQH/BBwwGqAYMBaCFHRlc3RjZXJ0aWZpY2F0
+ZXMuZ292MA0GCSqGSIb3DQEBCwUAA4IBAQA2cwKSvsy7ORVz5Al8eYcC1Y81FdYA
+ioDGnr+x+6/I+pskqBFox+5QHN/ccd/xOeFjK1tQCq7WTaEiFWme4DmatuFAMtcD
+LG3Xng+yfEeXswsT2L+e79o/Cg1G1D86V+YArRRTGBvIpzNu0owpW8AhJ3us9P31
+e6ZRcL3kwuyx/nKODVoTupVE+YJwzLqtMKtF7EOfp9zQK+jSfTUbrmq0y2gqfv5V
+5wVjI3Wj/7N1T5cKfPTnRyAoSZRSmZTVVRZgz7wEZSalMLlrCKv9UrTP00WX2n/J
+33mL/1KX/Tf0EwaOMfjWj2otCksNZTU5QoMmtVxBhYd01nTV/bKejbUE
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8C 78 65 B4 6C 7F 97 CF B2 14 61 5B BC D6 BD 30 33 90 B5 0E
+ friendlyName: nameConstraints DNS1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DEAB6091DBB1685F
+
+tFtb22ury3hDBFcRIRlEJcVLvemmfIIoQqRMmVNJnlYUFMFi+Nl+PEPpr01S8BGc
+1qLYMgpFBp83bTkr1qsGbBG2O1G0vHAdqMWdxXJDsXGRIq5pi438eEknryrOQRjC
+D+81ZHY6H0seg9JzrBFoQZtGZfjZ3icTQRR7sXC88DNPr9YLiDdRUQB/NICr+UP/
+e2xlabFAEi2NmdoosbV2qKrd2DBlz+Ko1DCnEl/H0/lwZhP5AkYDcCYpnAM4PPu7
+XbT8rNwx/ioD/WaM4zdFTs7eFaSOY6nvWGNvE3B05ChQ1GGUd/poZUwty44kVvKA
+puUpNpuxLDH5TvhTQyHuwo8cLix41g2EDWMkMJCZGXP4yufk0SFpRwmZb0HZasyB
+hwAq9lF0bphdE51InIbxFjhFhsBLfR5x1eOjr0hFXbZ6mSywHcriyDs2FhYVi9Kj
+taTM9Z/z6JbgX3lAQ3JKvx19URBQatcwrHxCRYt2M5jxHgLx2FCF1NmVjIuNSYMJ
+c8aZX4j3yL+/ccNT26+7W02XFTrgCSp9I6tOlMmVlwEhdmlYh7zhxiqB0p4SMQNY
+yrGBjEm/24m+rxw0usJwuvRGSBNXEIPAB2Zj2ndiIdUuht1u4+vEJ+juaFigxISb
+wKPbPEdZ8dG65FFSBbRLVilFpnfk8uhCZ4LsV7HZBWQHryuLqj+XuEbZVc8skv5a
+yvHzN1anzLC6ucHBCtW449Hh8N8wL34VY0BJrtoTr5Zf09MToYZsdoDT8l66Y0/a
+ahoW0pWYNiksntlh2pyme4FNMtr06bmaVjRavphtkWygi3y+yCpJS3D0yrqcDymn
+mljhP/9oxAqNhOzgPV905XSqVCkJ9jIbQy9Cix5smdhGs4h9xajUC81XtfOZcXF/
+WFFe0Wf1Hh+HgHTQzcILui27NeN+PBzHmcOyYpvTzQQgLtAuhXLQDGp07sTzKzvm
+u2Rl9wNBw14V96hkuCUGtiZxrYzQra7Jxyvry0yJ7iCe4awCbnw6G83EPmvEJzg+
+HjjTJYhxnvJLNnYEte3bXLiDlU+8I6Q5MsDEenfueAj5bpHCbGGA686r0n8ds0in
+9IQ58pwKnjTjZGh2M2QtUcH/Azz7rQL/drYAazISbnRhTB54/MDomxwmnTiLg9p7
+de+VU6bu8m9GXgQV2pfkdpIOO0j5dmHcRHL6G0v7vAkiSa0lD8jMc21MmloVhTrH
+w9KdTLCq2Bf3xehjxQAJaVzwZf1B4/TOnMa6cakBSMxoEyFekgfIld3wbrNRxbo3
+1jfzMkFKMM+SGpjjLZJUDtXzCzTcOurMl1R9APZXT20Udegm4obiBs7+TIDc0PyB
+e3MqdfqAEtinY6dzPodB9t3mFzjY4rV5Grks+twpWBA0GSe8P6qe+TEwW/Sbh3rx
+QD/mTnLWpol/CxLYxs/ibHudO5W0WTY3yRZj53OMM/5ZRlODbRBjUEIbgy4Nz6sY
+7sjTDRNexYfr2OhsvEDQi8/9AbSpttbQM4ATrd7ZvRNQiBpkSUtGpQPYVE2HAw6d
+tgZ6oV/HYpkkw5Re0wRc6pdJWWa1p9TpxHoGkW546C0eUIEGy+ZvLQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS2CACert.pem
new file mode 100644
index 0000000000..fd19a35879
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsDNS2CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 6B D4 F0 64 35 65 71 B0 A8 FE 96 51 2C 71 66 B1 4A A0 60 4B
+ friendlyName: nameConstraints DNS2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints DNS2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBRzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIDAeBgNVBAMT
+F25hbWVDb25zdHJhaW50cyBETlMyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAvfi8NX1OP0jd2b3bSoIyMixV6E+/kY/Uax1VRBts6UW2lx2CYk5e
+aF9/9jR3lx24bit3RHNHk7LcaX5Wkr1YE5ROpyxEwhEOGWnK7GcM1MlFvpO9Bj6n
+39wr3aB9MOHSOS1ihfY99mY7UINyWNoXzkUD//ivf3Guwuf7lVfvjXwotgcs1ig5
+2wSTK0sFONYdCtZMcrslFgBOhm9qZ8fGlOSVAoxKq5Fhpx0omn3DYInXNjHPHwJc
+wj7D+8FBY71FHDG7oaeyhaU/kYiQTMAxoUd7XDibLf7KUQ38EiVpLshCNNFTZb9A
+56l+03RieJzxNd3OmIULd6AFLNZ1aMOjVQIDAQABo4GoMIGlMB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRGSJxCCY5dU3DYFh7gwckY
+FTUKBjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wKQYDVR0eAQH/BB8wHaEbMBmCF2ludmFsaWRjZXJ0aWZp
+Y2F0ZXMuZ292MA0GCSqGSIb3DQEBCwUAA4IBAQCGjj236wEfbWpLjM5irGBHsc0w
+RdmtOLh4Wht2TlaaJOErYwY4HWankOeTjQdJh2fxlOwWewcjplngI24XuY1i52GC
+HL3H3CbiXJJKiyNZQyTfUtWaaP9Avp9psb4J9WcqfKBMMl+j3M3Fw2vLFXSRvC7u
+bXnaLNAnsMdJoLYdqcuqfG36aGOlouxf5+ATj8nS/EoOjIDS1LjPCCLVMSSURNYP
+2royVDt7AH2TzxOT5c0+5nvrx5bs2GOO/77oiLXqu0FJfXsJSOSOrFZ0EvwTOPg6
+5jH4zO0aOlP/p1bkpYpVyHh3syyeKTxqdn+TTZl/SoiSLpk5CxK+eFBlQ7ad
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6B D4 F0 64 35 65 71 B0 A8 FE 96 51 2C 71 66 B1 4A A0 60 4B
+ friendlyName: nameConstraints DNS2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A15577E096374231
+
+jIAioNMYij8iqXwg0fQl2sfAXBkwiLnCOc8mh2szeTBwkaF0EQku5ZKkBUu3dTAH
+yZ0LyB3/t1ZwZ4qUsOfatq5neI86FXw10Khf9JfFl3XI9Cynp6PdJjYIgZaP2S9G
+n0kVB8q7nXhBIsRWvH/0mvKWUSAaQYAkiPYNtlvo4LXjb9Y2m5QdaIY4Vo6WtD4d
+nwn6HNhR4TGhEMkI2MpeHq+tqhKx7PTjvFqKmon5x9i9lDI2XxvaHvQ6j9WNq4Yf
+Kjtn0UVxmkNEadQ0mfXChYY7cxK8mWNk1yj4OvxZNX8vHhtWxJlXKOL2E+xaVXfm
+N3lrSAH2n8u1biTjVqlpaMEgc1yBLc7wYYlmZv3n0y1lnb/HBTAoudJn4q2kVZtG
+5h9/aEuY1F/b0eJGu4E2zqAY2UMUX5Trjn6pKHbKfSrwxrIGGEbgy0COeJ2R6zfa
+WH5hQLk70p+8Xb8fkVc0oiAu3Vk0M9INVPF1ICirsPJGpRoz3XmNRhbqKxaSwAxd
+4lM8yiHcM3m4Mkymek5D+xPiOuq6JjJ3+WZS/TidXfDkoa7AILgj3N8Ns0KOba1L
+D2woUPRJVDXvYcXsT+KWQdr02JJilJajEB+8RzPZFVAzUDqbwmyDDu0oNrhBqeou
+ej/Q1O5q8AkIF9cqFJLDdI/7DqFVehb+4mAsTOg24CF78K6g6QUUHZDnDYUBx6fy
+GMJX2eXXp3MzvDH1cYpXqOPwbL+dOTzCyRrNMjWbuMozdG0fErjyk78abozUYe2v
+SUMnoUKyPCwYia7dFl0/mJggrbbe/pnhLt3wOSYPcQMD7yt2TKSjIgMlP4zAfZZd
+iJZymqxvBJm3Ce55EuKapWKxtFZbk/uehT8NelmpJZrnIQOSfXLjG+bcRM0BZ1s5
+spb8HK9ZdyjR/3C8lSYbho/uufPntlpcVAYGyn1onvV2+NH9fHMgakynyJJpCFwl
+KQhkkAkpJil0TBPdfUHuFIUBdfjbD53CWoUxiHIfcKR+GcWF4sArJmviHfhyxGxI
+sM5Lu7e5xzfJkrpgHj5raRsi/b1y9PAOXwRv7HM7lP50VA1ZuCaP8NU8gyarvF2V
+DDGkiO4CnUBFY6xFs2VdFRj1dm+chKQW96iRCwuC/WiUTVX0FTtkmldvSOJ1k4/i
+kvjpqNSwFDs1jDkn/jyk11gAEr8Mg1VQS960NJmDB6P/viJBuAFcGJVgF9F/AESz
+xGLisvRZ/OJsng8j7qrTecYcwTRj5/7/QMoBy2Cj31GvzxsUC/dHUXFzjfWeqdAz
+Xw7teLHqzrPYU7VD76rGWTD5HJPuaiCaioSslewcrfx3wC+aEBfywvr4zQkPHPIh
+tplHJPdJoxme7FwUTXu3LgpkPp7EiggpqS31vecKy7YmnLq3smpNtBpHGjQC0XeQ
+x55nuXEz5RWmLql7nfYq/D7zWNk7OFa1iZ33cWNTB72HoLKR6FSPZvKOfX03GbwL
+QwOQQRIJqDwgTH8pC8gqJdfxrvSd1E6UsvUeXU0bhP6zbtFDBdOA+ZEDqg0VXtWX
+9eDgZ6zFwQz7l0PZtUABd2FmPFtEXonDvg/QVOBXs6vdXefi/vAnLAKL5TjuyyPI
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA1Cert.pem
new file mode 100644
index 0000000000..ae4b69b5da
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA1Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1B F5 F5 63 8A A0 64 77 D3 A3 99 D9 D7 4B 03 39 AA 14 80 E1
+ friendlyName: nameConstraints RFC822 CA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIBQzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAMT
+Gm5hbWVDb25zdHJhaW50cyBSRkM4MjIgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAq9vbr9mMpG3/bg2XQGmxlZSEqeJpOnQUuEoS4cicFxpCaKMK
+OrGLlpwTrGhR/NGHOEzUO7qLWyTaA2wthe0ohZIsxjvGKK3yMvmnFNriMBt+md8i
+PAR0ysFhBmMyIpwdJs1N2jBnOANPW0KFOtrFgncHnEOajo8l0jpGBaLA3ryhdwB6
+h/L/A8bNbqJL4E3foEk2AsOzdt1LoRUaA9gcXCo9EqQ29a+598f7NvRME09teL9n
+iJEzHy9Dwxy//II6FnlmjnvGdUmm/2Z71UbzkpiqjD0w0/jBXcDAlwTF9EfL71rF
+wDCRfZppGRUKLqMNTohHKYI4ilkD/oP75a1EKwIDAQABo4GmMIGjMB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBTIao6xD0uqpYi4p4+R
+2+ozSujV4jAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wJwYDVR0eAQH/BB0wG6AZMBeBFS50ZXN0Y2VydGlm
+aWNhdGVzLmdvdjANBgkqhkiG9w0BAQsFAAOCAQEAcAR6YeKZpZPVB0ICn2GTD2Q1
+FlSS7paAINYzC59z6h8ynJFGp40/67SrFz7IBzBp5E2InzQ35dBXINNsxcG+xzgE
+2PmPZXzInzI5MCJS4XpX6bY94yUTslpoAiVJxwISZ4Gbfd9M73evvcxymSVNAPEO
+AX/6eO2ilazokSR9D3zQVOe5lxPshorlX/WlF9LvCOrS0UcEhHoDrfAM6KhojUN9
+K5l6Fv1NXwb/8cAbFyC2BMmwmec6OL2oBDJCxoLrAWVaPh7+YZadnLw/w930IIdT
+U4C90QPUgdFJWZv13TePZ2WEMtxsev82AU4PjeUS+l7c2FLW0zavMoaPhjPnaQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1B F5 F5 63 8A A0 64 77 D3 A3 99 D9 D7 4B 03 39 AA 14 80 E1
+ friendlyName: nameConstraints RFC822 CA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4562102D253EBFD9
+
+j6TVJONwSX4g9azgAS6muR8BK+257UC91asDs9mFLvVUlCLTQH1ZTwDuyPXTdIHz
+/3tPysrfI/1Bq/IwNkFHEEbDEVSmK32PfrXN4E9dEjaI+jgmSap4ZPTXnVyzpO1x
+LyKAglqacYYv5HX0S38mnCHAKKeTvJ00POvwTqrPb+lxQAFf3LcBpopL8BtD5Wma
+qmJO1EcqCVFU9ceo1FoOhWNsPDrpf2qZPpfQ6v6fkpqZWedQUC6mfDdIhThjQTD/
+tOIKuo1s6zHz2ZLKmpYKDAYJ6zeeIsrn+j1/3KyMfW/DTuPmdDDeCmGwOuQdja5e
+sSL2Ij+Qk5IlgLX0OkkXJizuYdIqs13Isk8rK9oZqPhqWeoIvBcXYt9GpYo5CnJ7
+1Vov39567Ycc2xKtdv9d+VayHUWhwtvRT6Cmm0HQj+ktcQJsAM4H978ptMhlxV4c
+FoyAn5q01CMg1uRMZRPiXGHSLwy7bOYUamwIpomzhmRzeUl1GTRI98atsIMvhGPc
+SEt5mmTvYfaTQXcFBF0MWc3h5MUOGRYs8O1jjeLd6rg/pZUFWDZUqzmElq9Kc9TG
+m/0r0DqFI4FxvyTI+1830DUt0H7BzbjOO/lJS8lu4XUoVcz9sSoAc3U1n8yyXzMV
+vHNHcHSGNsabfE7ouRwWn0ttjOseicZDsu5RVAcw/1XehRScdfZxNNyVhU7BGrgS
+UqEnPxqQYPb0fqpiiRVn+RqD6wDdaaroirU54HPPq0OAxhosGlE5PVc9ZIYcBrFI
+fO0anVuQYwK4HnWVDbp0+0jfv6GHKiskFRmQ31MWZ7CrIEfyAoG7+JusdttDTf6o
+BBDR1EVfBGGRX2J30hMqbRXwvuJ4TpWDsGiH3dnkdjA3txhnYTV1C0p6dIbiBRdN
+3ncwNaLRbjjnv03+taiZuFrY/JYetsrpht4woE/W/s0fQ0uBUq+xeCNqqNlrcvNg
+j22o6JKyitDWbCAeu4SnULN5RHAZPALYITeAhU4o7SLWNzFlzIen+JpbzKzOnRBw
+cXa1DuJxkj9BXMapjGoFkFrIkfgLPjO8I37wFgk4REWpBMlMfZ2PYPJZkl3v/uLZ
+nLOWoEWqclPMjuA6Dtb4rti09+pMGN11j7oKRC5W15LcIjrSdj1NKl8mJIivlEHg
+646IoS4yPsNI2kthdx3YaMfRUYXqGOxom0KYXcj8hlVVofN7/3kGN/xhC0+QA58/
+CQ3XahUOpemqcMTEUbDA/8S56MruzlhD0Nq/oxYR3Pm9J8NnJ6jH0b6RZ2zmDp9s
+YZuOIoiTRBfkdljrsK5Nw7ixnsTVuNi94wBnxWjHsSjzpx9sIZhhi7NUheVN4WaJ
+CyK0j3qqOIZgbp0y4cLyZCKBZ2fTvDuqQznnyiPIT7Nf4zeD91i0b0J0gcq/y8Ff
+Vo/HkyQOIkwGdkE80G/eu8dYJ8IOnO8ty2DwLzihfQHYHZHLFcbJkUBcNsE1jcTj
+vYw496/wQjpsW635mUKmKkXMQakO7oJ1L5AaoyCLbs7Qn1NqELqsehbhtrv6vPhd
+AGNWK+KPBuC75HyAczdAiEkiUlofaNSHzzENaeaix9L74/oLJseU3A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA2Cert.pem
new file mode 100644
index 0000000000..23e4ec0233
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 79 01 06 78 95 60 C3 39 42 82 32 7F 03 4F 38 6E 44 48 BE 0E
+ friendlyName: nameConstraints RFC822 CA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBRDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAMT
+Gm5hbWVDb25zdHJhaW50cyBSRkM4MjIgQ0EyMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA5WbcU+FNFY3n/eJc1k45UKjs2clgZI0HMujImijlExY8DG9c
+FZQuOX7g1eCaHXFeS7HSVMrfKLO9tOSUfYUCido4TA7xhl7Y5l5BrKkn1ZgEgGFf
+Z6lZqqb5C6+qd3cUzNPbOXd1HzZJNcV47uZ1NusoqMyXKEpRQUW3t+V6dp3E8JFz
+VCLmRPXtqY5JpZemmJD5VWe5tj89OnPk6S/HLKUeNcYiA7rcpZR83TJHmO6tjF47
+Bb/hgxLNRYToTn+Z69e9VJ3WZM/t9fJxRUWwEgyBGW48kQjYmGvBNzrlMdCq1ncy
+Z6JoBk7UY6qky21uhaO5sknZajTFPTj+M4YNeQIDAQABo4GlMIGiMB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRRgM36SXJIPO0OTgvO
+zh9AZRJwoDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wJgYDVR0eAQH/BBwwGqAYMBaBFHRlc3RjZXJ0aWZp
+Y2F0ZXMuZ292MA0GCSqGSIb3DQEBCwUAA4IBAQAk9GOd+egKHy41DnTObsmqsc3w
+KSvj1SVn17Hda1gq3tLXUcNqp0g7kP/YNXRx8XXxU9heUCOTR7JLVO5AMVS32Qid
+J5u3q2D7dBgHN5Nyv7YsUOI+AcVysLMTlUu6iGnwCSsdtL5aJtSq8gAKZE+HJZwl
+iR73kSPGr4J1MKBiZvcVa6L5LKg88FQiSdOPJwyPurvn4t/K27u9jW0/SYg1qeM2
+/iKSyzsf9bM97aYqqE3P7DPHRZeXTZKLCaMNKAmZ2iWtsyc3aNTn2RyXg6RBUoY3
+d8um+8xE71cKdDjNwdJrsPwFhbripzJ+eE7bWV8v5e5E1dN3AzJU31wG1+vn
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 79 01 06 78 95 60 C3 39 42 82 32 7F 03 4F 38 6E 44 48 BE 0E
+ friendlyName: nameConstraints RFC822 CA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1EE3FCFC2932F1DA
+
+Nwl6UqvLB41/40EviSaPBJ8mdUgi923wEyqY3hmfKVBnM7M8gt7ULVKOj59+TAe7
+dTZh0Wx9JUIWJ3fEVInkvMWWFMteB/B+KkwjmVWL81Gfe8CqqyssYk61GJI7M7kR
+gCD3DLKia6VlbuB5UM040fpuNMsgqe4oLnonRFY0i5ruqOjrDkctRpweZGT99RSn
+PIeu4/qnAwkcxsBwGh/GjahmUfAA6neemCeb0hxVTrpYQSGkyAwxuI9/D49ok7DB
+5QoW0ZzJhS3EUv4sbILLNOZsY5b+7RRVzMUeXXWRbgyNo4BeYK9by53hbZhtVUZi
+i3+NHdMBJLlP/nujcycu1ETsgwU6BUoZncguhUdymtdErQgw/8AUKQ+K6TsrbBco
+47nHuDRF6mEwHbI/r/BPW+CxvtjG39TG8jMgO2BQYChP4jYklchfd0zU1fTIEzvh
+YmUxIyEB9uY1xYgtrn+lgTQY6+5fs5L+Rp7HBu/bITW/QQ0XFdn+z7Q4BTm9hXUy
+23yPH9XofEcsj3UlFI+PCeSTqu4lRf28iip9xf+AsOq6U8fzrj1LNI6x+VpRmYpc
+WxKoIEvNUwNFRgsVxxW/d7La+URmF7cwLcgoUDH8Xc/Ytc0TsL0fcWJFKW/NJYTI
+YZqnDLY/pe3q6tw1ZM+x+y+L3dHuF8Fs14VxEklzhJabP+M9/p28F+N7Nh2dl9h6
+X6mES3LU9g3T72Fr9MEuD3+SVMz85kFAgiVsmulZ0NPrL0MG6QMxGoy2BOCAqzb1
+WpRmLeC4A5jWKPZT2Eu7spKMgQTQytItn4EwByZcUx3RkGIkUf659Mz6ABALWLN+
+Fppu9S9yZtaBY3C02eVO6idMvYoGVYo/spKFMYErRllXSlyoMPMPNbwginUcrAyX
+tSiWSRCFopdzfFsyO7C2rKb7PU+KauCERlEVGY9tq24w+zckElTWJuZhN57dlaRd
+6zPu6wC+OgHdYvYqeWOsh0gipFV4lpPQz96IfQuVIGfOoBlYfxQTCkwh/W8GFvoi
+L6kwGEj9zgHTMy6JQstvdFHjEKppFfaE9gkSrB+Q0oQsUX9UQJ40CVKvDKV0Di0/
+CHiZ6G5C3Y3Kq6I2na9GdYxVWXSIDY9CWtq7Sh8i3x9wllG2dzQYHx+C87+WkL1S
+Xyrsq8dF0UO8dJbdocZ9udbEYdUatoz8Zz07xLKY/DInK12YRIKW1r6/5xjlIndI
+FMvHhG+pRTAtc3Pt777aSF5JVGvci0nlZU1EzEF/LEl+Osvr8zMk+SXXJXnr0DHW
+cc58wbVttJQm6sXbTiqDeDif9JUdNKMpGosSt+8NB8Hw0YUoaQo35jNgcdG4/0IH
+kbS1wQCRhrxa0388ksok9HwwSIKKWikE/p7Rfu4abWM1pmVNh5OP7y6pW7hxKmxE
+rQcrlJYWssNkYX43xOvjM4vfPmY8cEftUukIgj/kltDSh5n8gh//dETcaAEPmOG9
+o/uO0cOnOxcOm8f3mciYra6EhI+3Rd4a4tvnw60ahf60a0QAxKGIjzuU3XNCZDfO
+GwmAxEYS0jGyWgHGUusS24mpOnF+Czzk5vJohVV2ask4E3gjwnhLeA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA3Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA3Cert.pem
new file mode 100644
index 0000000000..9f11d4a80f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsRFC822CA3Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 1E 15 21 B2 0B A6 60 0A EC AA 86 B2 28 08 08 72 A3 5E 03 C7
+ friendlyName: nameConstraints RFC822 CA3 Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints RFC822 CA3
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBRTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAMT
+Gm5hbWVDb25zdHJhaW50cyBSRkM4MjIgQ0EzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEArHS+/nwL4IEPwwXe4efteEWKpq1uL3iDHm61D3Jb/GQKFWoJ
+lNz1VElMoVCqYG++hdGHbQB7teD/59MXxojFdcisSIAA3pTBBDj8c0GFzucAzagw
+1IPN3NDjoHJcY1eRg+bKpwrROXxWHsIPnkULSJ++BkMarinmfuN1TjdtKT+Bv6yH
+vaCgPxck63Uz+lVHuVyA5feLp6NEn9ocaATeo9JanbiZEPLm3NVYMqt2yzSMy2UR
+MJ4dyD14P2L8dTgjaDD22BwpjiLc7gSCrLgTOut25JtYIqreqMn0HWQTbkg3MAg0
+S6UTRnFVUR1vfHRleGrqMU1BU4VQRFan8T7HHQIDAQABo4GlMIGiMB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBSaujlN2iF1r+pBwzxs
+UdioRal/ozAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wJgYDVR0eAQH/BBwwGqEYMBaBFHRlc3RjZXJ0aWZp
+Y2F0ZXMuZ292MA0GCSqGSIb3DQEBCwUAA4IBAQBhd8WP6gnAMqbdGdka9QLQ9t2x
+Xx9zp6vdHGl4oJVmDw2opfpAXwhRc3mQ2MsY7KDfmCNvw3ry6EFEndGdinzfWNE3
+4arjKO+uVFiZCD5O4smVklvpI4xFUZOOxClcJFa/tqicdLNF6tA+reP46djPfuUB
+W9c2XDBNipVjX4w3f1i4LKTH+imhmF0L3hoHfvwyM26RW/j503HvUHPmX6MeSBjP
+HqPfDUgwxtaKbcG/FC7IgCnaKQmcawjIgkWVVz77aue9UW01mJum1dW+7vuZ1gE7
+S3waoAlURTU97IgWymX6FtYnHrX/MiQhexsapFHxXxs06l/up/7k/2m89vKX
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 1E 15 21 B2 0B A6 60 0A EC AA 86 B2 28 08 08 72 A3 5E 03 C7
+ friendlyName: nameConstraints RFC822 CA3 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DF5454DFFEE3D139
+
+fgaLOif4JvdvfGzmaGKV+JlZcgSGCD3R3Mbif9uhcUdACJmocBGRAviF8aafiPIZ
+D9eLMdv7OQ5VgoYLrEmVYakElfHySpthi3bvC+W8rKRSJO3rxA6pGDfrotjm/Uor
+0Rghx/0jlsl/MmELEQd8Oj2RFPezRqLN60Tu9Dp/WfMCcdZOjZ0QEb7TUUmpsInr
+vtrVoD5hZjL6ViG70pz5r7sRcuTVJiRMgF2d5E3xD1tl3tfJEYXrX7btJ1pbVolY
+/YxCOm0nCLPe2eoqIhI+n3Rw+6hz6n6Onhfql99C4vHGh+uVeim4xh46GjQAEDIw
+/GLHXOz6r6qmOOnH+ekNteSi63e+VB8w6KqcwW1Zm58OC5jMGbr7tVxQ6CmaUxkH
+Oh2RVfE02+1PbCGYFFv5fZK6WfTuAofsCmLd4ii4iLsBWw8V/ZOV/UFj1e43v8hY
+VJq1RXOolElBKhsBW98D0pfLhdOJgNeVY5NcpA7Rx9+KkEZbXzcxQk1pCOSKp84L
+g+T71aH3IPgLWy8ZiZPwObns6YuA+hj/JXFAQFF1c3KGp1rZYh/vqml/EI+M9BLp
+BT4nuVzVPSRsBakAo2fYy74W6doXTvGYRpBYliwPTkQaL/0Ldowi9oV6R/+jGNc3
+fZEdmn53dEvtieeDstrhH3TJFJdNTAgN54gJB/vpsHX+rKqqS+iY7YH+C5S376PR
+NvqI+nkSrFsKpNkY71zYPKEkOOgUHCuKOzRAIo3kabJQ72lJm+v4e9kQLoK8J3zb
+D70snDXeDJpep4pxD56DylV1lZrk9lI3KXaERTFfrbkUfpwo1+Ksicgw14kYRTwu
+WrEUzDNAJ/O8laWnyhIremZEyCbRsyx3MsMmsI3hxat4/CT09lZGTshGGjrw7wXc
+PW0Nnb1XyS/lHyEm9ajL/wpe+wjdWky4FDG4qCJRFZebdX+l3aqRvVF9t0Wo0eL0
+cFk4fmhh19hxVnrmwma5sXFjmP/vIMziESzh1ZIjTPYBj6DxRdYcsWBTzUf+d0iQ
+eLy7n8UDTHHdHJxzz3mKMDYz+ZlA5ypnxFauCPVJUqYepg8iZFRNq+TzFXs05DTf
+zx3rJpoK2xlZVjG3LTb29kltjur+eBUSfaj9UTKV176VPxBTkczV3X/37y2Tbomh
+JLcsNhKGQaBRm7SnRC4yj65TLenqUM9/CbQi4VM1zGBrFl87tVzEkutklqFdSthM
+RyttFYevmLni624DUPemwad/r1K3O4QiJt130SC1gyb9egQZvrnlpqD4cdPjUU6G
+ExMkZ/SfU0m0k9U6ry62OFwbysdXAQE+BtQAgkd1ud34jtFg4faWTD0N34zs9H2H
+88pVFq+xt/fTy7eOGd2PgtwsJMdAMoipLvXTj4823bxu+TXVpFQGmhC9WxTNzk6L
+K+9M5GlEgVU7D9A9k7etFm+DDb5+1KXl/bzoZ+Rofm9q3JpH8L0oljhC8iFupWcw
+y0vT9Pj3D3HtaQbTj8B+mYygbXtpWyIdmN5M6JOuau6QzY8KrPq4qwP850Uvr8rL
+DN1srseTKVJp/5OveRKvJB90KS9kO9A4pXibLwzZvz2Uo5LFbCa1ZQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI1CACert.pem
new file mode 100644
index 0000000000..7e45b075d6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI1CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 8C 4C 2D 13 2B 41 D1 D9 6B 6B 8F 83 97 64 93 DA 30 BC 1F 39
+ friendlyName: nameConstraints URI1 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints URI1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIBSDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIDAeBgNVBAMT
+F25hbWVDb25zdHJhaW50cyBVUkkxIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAp+cs3as6ObnbAg5IEkmXsD/XLGICGl6qVcEKB6eMA0ILAsGdMHRq
+ybgY25GUQ+o6RfvTHdD40N6Cqjk5vu9+7aAVjrJ0pdUyqHmK6u6TVcRt+xjonlEp
+o8bpkqqgV4i7m51qfLP6+KEh2SKUDBwOZ8/jlYIZeKzVXqk2GZx8+VmWWncDz/D7
+v262km2IiYoZM+1VAUixGhoi6ImPeDBE1u7qoxvvBEDKJJ4sj/5+i4yAgr+JNIUL
+vr8DaT17SkwRZquWT18yu2qP2KycneKysWm30A6AmAALhFBNX1ljDeLT5U1wBCST
+DRP5U4zH+XvAUUEeMyDYMc92a0hjYwE4swIDAQABo4GmMIGjMB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBT6KK1BFt4qaBfIDxwjPyYD
+3gIUAjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wJwYDVR0eAQH/BB0wG6AZMBeGFS50ZXN0Y2VydGlmaWNh
+dGVzLmdvdjANBgkqhkiG9w0BAQsFAAOCAQEAW+m6tH95z9aBJUxdo/dsjRTdVgxP
+LGVODxeqpW8IvEEjoYBWgHT5M+g4WYnzeSjiPvrq1NerYU0DOI2/hb7aoBBq+7MJ
+2q6BK06ddUTawRhLh4Rfnc36epefkZLKtQuFBKA7xaqWLlRQa/jMoZ27hKI5b1qr
+aKR+iP1rKPd1epIL4nwqQgAd6z1bJrV8c2V8py7TWE7/b6wuZVR4aKtFMp2fIN0e
+o8U1K35YVtmuVw3TJsTlFn/DuZ4R4Tl6GqkdUUvlKXNuY/nMobgfruTG6nvmaLyy
+FHtDoamjegjbIx/N1dibXZLf5n32iBXyHHDk7L3ubrarUrutmaHgEEiFZg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 8C 4C 2D 13 2B 41 D1 D9 6B 6B 8F 83 97 64 93 DA 30 BC 1F 39
+ friendlyName: nameConstraints URI1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EAA221B768070C24
+
+AcR2xSZpFUEn4OVUqagNlFl1w3gYszI5vzBwRIlRqUGD3fXehH3TJMOky0qQvTiG
+g4Yh2hWxJsTSRs59w8UIXbZo2Qv7bYpbqudtuSmF+L2c4uip4M2Rliquol9ydIp1
+ulueKTatotnG25t8Tc1Nu9+udbR8znKvCwzBhrPx6hQ7CO/QXrvYML31UZvBNVkh
+Sj24mTYe2f+glY+1YZAM5LANA14qu0CLXGm00ImKKGs8FspriRENtfQRglxdZ5kk
+7cigX3lNPJOKVnjiAxwGC6FUTDkvTAYxkKaMVbF6bKpnPG5jiTpys41shKi5+oXl
+3VXpSYVRwAiKHikmkEPC9dCKkHAh3PBw/SQeAtY7TZgkH2+yoIiqDkXIA8k4fsBe
+fRZGJyty4RgtfQ0E880klW6H2j/E9g/Gv/aS1PVluassyZwP3UoWXBsAe1DsRP/O
+6XrTvWvpGkrinsYFZVGzw/778gkF4stMUcefHqt0HF9FDbHrtZI8fnAqTHiCxfHq
+9cpfj2WXTxYqIIB+il6r69fJX2RWzJsJ3Nny5mK1h5rx7qib7ReicWV4VZh8Sn+r
+FErwsp9yoPoPj3PUaP00kh+BcP2k0er52cwrTTRV6jiyMdXqGl9uT+HV1feE7o6O
+utZxwYaMo4a1nGDpVtszihym0p3aBEqlYoucUDpzpbV6x1dYrE2irmizIn9z1iEx
+JZbB5Sxl2s8BGic6GkvjsmC4EJbI1pxO2kPqL61zdFAsmPtdwt0fcM9ZJCStpWBP
+cb2j5JCDjgIJbwHd9dafXq/iavGJ2bE/rXr8ivY6Zp9OdbZUoXh28/2CX+dIBHaO
++F68q+PjhEdqBEC6488+xBv2c99cUjIslAfq1iZVJw8wBMo3OcxVZSRcSjCASjIA
+YlmMl1PAOgYCHQxv43oQqwp8ibN8UrvV/2QPS5PEUOG+sBaNrMnV34zGqH0DvCvS
+V/ILflsKx1e3sRgI94Sj79OMtYPJeyhZjKI09zoNNU4qV94LFrpixo58KXpUESl+
+rsmiIY8Xp2tL95t05mXxG7AZWkvlkwkiPrDnxp0N0cBSGItb0YeZT1LuYzjhVh7f
+en8XoBJYbDmCuRfQzQIsXJ39Z2VYdRBO+mVdooPJIsFMCAaIEHKmRlsTjvIEMHDE
+mmT+KY4CKilnbiyrMxPuL/ayV0xDAzpQgR+uGboo0baN3ly5RF9VgckVCX3k8r3B
+/F7/zPCOSF8t+MsL/loq5n+g6BQp3csU6kySXcOlg2JQMkR91lsBXlm5npurd4Hx
+e9cfwlqYFYdTxZvh8Mnft+o1djE+76hAeGzos3H7qtalbxYgEK/Xm2i/U4hjg0uM
+Gx2VfPlEjqs+Pk5oicOy+GoB4sWz+f/bjQaSsscWPGfolIL9ZFKw5/nU50rJeUYp
+8APSX7qc/1JfIz/sZMOGCBwv6R3MgAG4JU7E7Wrbgyt1ha/8BTsGDZvYcKA87Ap/
+w7Z6S8KgVGtYbGkr2o0okRmv0XTmjbG6+hs5ki8GAtv4BMLIBNZWgeNWG34f5cov
+ZCJuJD5DzRWbijW+2k88nCqNd4hLaadtBxdMmha4PxNx7uREdyaG9Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI2CACert.pem
new file mode 100644
index 0000000000..9551a095cc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/nameConstraintsURI2CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 34 6A 77 38 F8 A9 89 7D 1E 91 15 51 CE F5 FD 08 26 79 5F 2C
+ friendlyName: nameConstraints URI2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=nameConstraints URI2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqGgAwIBAgIBSTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIDAeBgNVBAMT
+F25hbWVDb25zdHJhaW50cyBVUkkyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAvl+AJxWs1WMO+mjRtv79nQQIKiD4ZerSA3/ELaH8hFiF7zjMQ5iE
+LbNmILHWH5vqaHVmiDRbxuoe5fcWO5B0YB1A/dFY88kGTjB/TSgt+CBGdF7Lmy+O
++JwL5EGiIerDfte2+OpsUDXmwvSa5pP69kS88il7WuZcbJZgcAJ2dH7s4c0oQ4RZ
+pKZitazyeruYlq8ISw0tMyWUhQyIBtnpaRn4FGRpZhwdn3MzpBsMXEBfETqDaIT/
+Js/NHI9p0BldLlXxjTci5DO3JD+5eEwzjmXepIER/xKNuTEgK2ZpULY8JyJxG8Ep
+lenySFLq129D/VbDVJjp5PAj1wJKLL6OLwIDAQABo4GoMIGlMB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRN64lx3/AEAbL6djpYsbpg
+3YzTwzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wKQYDVR0eAQH/BB8wHaEbMBmGF2ludmFsaWRjZXJ0aWZp
+Y2F0ZXMuZ292MA0GCSqGSIb3DQEBCwUAA4IBAQBmrQhlvkrzTPT4BYr4agHBUoLL
+n444+NPFOwy4rQOIOY0k++Fpvn+jjpIzrHMor9afu2rMHJDhlcNia+a03Ov1cLwe
+9fmf3gR1V5AuSjTJiLEN7IWADuIVcAPbAgg34e9Qb27pfVOnZ2JmPHkxiVMlGtA4
+1AZXwDD70gZU3iaIQKVPmMbLyBZHv8c3XtMkZ0JstPgr1WJ/Vl/Xu2fmQgJOc5tC
+z5fPPQteE5Uas/6COzeAL/VRAqfysO9jh7T7xfs62bbqxGcQise6bLxqKnpd5KWW
+BX1dDMZrBsEziR4j6wczx0fhfEPH0VPileMDN1o/V9YO9RFo1Y4+0YUi8C6P
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 34 6A 77 38 F8 A9 89 7D 1E 91 15 51 CE F5 FD 08 26 79 5F 2C
+ friendlyName: nameConstraints URI2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,25879DBF4FEEFEB1
+
+eHanMm5BAI/xfO6HNob2KxFkcHyofBJ6fc7p8IsUbs8SEG9DYxT08dnwASuTWdlf
+gwukEKujaIY5O6nyx1zQOLsg/0XT4HMCvkpGJ80DfJWg69q2mYnwOaC9IiQgsA/q
+nxwuoN8rrfFpaOlUEFStuUAnc/FynEPZ92IHYuBxMebGhQgrkTtygMiRuqln3QhV
+a3HrpSsUkNxSi3olwAZqGBX176AhCkPt8ufE2PwV2uwgDUrfgouAq6HOeXqjNLBg
+Nz5TJ5EC+tAD0wRf4xVW0D34BOZaH3YkIcTXhmkMTl8uNnug8fkw7SqIM1FyI3hf
+NAXSluu7uOCnmMEeKOop0DFE0j/Bx7yBOYIdYVE6b2ZHEs44NIknMlkadhUogZfi
+7m/K2gqDXhfSYI93PTvJnRsz2C2v/F60V+KFRjo0eGEPEQ3n1al2q8Uk2k+vNOb1
+MVNb9NhIhTnkDnOBLtdvJso0qPCqAiWqhTlDYaVdyfI/j0wTArlLwKth/UPCTY9J
+PbOrErNib4k9q8fCj108AvfBIMrjdzGKsY8xR2CMLZTcqIwa4ISliEIH40RXix/K
+UFuA4O7RIVlCdRpVEBsTRebvTIzFfCQEj15VETu0eEI6A6g4i9AIm7chM1FXuf4n
+VBQWM5ftK5DOWBORtib2mFnLEfma7nYwsWRJXvkVdr7p5WXUZ9fYyleCu4Zxt003
+rTLWKA2o3Lud1WDsy3VabIjrLgyU/RxqlRkAG/QHfIud1D4Y9Ed14GWe12gr5+oU
+/2PwwDMgNp3NG4+9SgJeD0RBu6fcjui2GBc/AdTw7Ax6wnNzG2kmlFPwU/cPrQb3
+f6zWJeYIXM2ST1kq2VGnBglNZ/cAxMRfLGwTzECW/16FLCI7ej2R1+CDYzd+jTNb
+9NJcSJ3om0ojHnbQgeqOl4UQI3uJsOs+Vy/aL5kqISCibg5RrWGXZ8bAoijDVFk9
+jskfgzIQpM6RnH5KnUUlh6mXC/Yn2ju9lTKpfFqp0yIWM24U5dpCXJVmIrN8PMaH
+bZ4z1boHN/rB9GU0A7qdF6D/oj4XttRYpytDiGPPi+6lLXgu2MYy9kFrvxUp3xZY
+QfQ8d4ScJA6PXGOC3mA1PWoeF9SWedJgIsEwXYakbVaEOjahcoosTKFYoy0SFErG
+E7N4iJ20PvwTzKP3otMT3KtTem3hQlBxJxoZ4+w1dL7u4wgtSiGC//7C8QYipxK2
+Ch+HT6yvjkBdrH6L4xY/wOTsxRHUO0NuEsWruLHv/UjJHyaYbBRnBHiUC2jtDzlg
+hRWHI2NQNb/l508z8OO8bTqrKoGJnl/rUUAzCVCdv4tP4yRaIRUwmmYRJnDETaBW
+03XP1os4JfMuGr4nHzHePKSbd+FFa/QntVyYcRO26x97k+QCaQrzTB6ae7LHtfvU
+Kbtlme3iCkp3yccsKWwKTcYoZr6QvfCotfGeu4pjZ5vMGUq+bFR4xBCBb9twv2UI
+FN9qAKHEllpeo8OVyn7fFamswkHbVhPOSkUyDe6QKfFeP1u5omjiO+tUmQTVsM0x
+eMXJnxNAy5cUQNYBHOlmmSgVq79/itkUXdgaTDgnDkVt5f7OCw2a4w==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsAttributeCertsCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsAttributeCertsCACert.pem
new file mode 100644
index 0000000000..e388968e95
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsAttributeCertsCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C7 C7 6E 53 32 81 C8 66 3A 1B 7C F5 61 20 4D 39 22 A0 57 6C
+ friendlyName: onlyContainsAttributeCerts CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=onlyContainsAttributeCerts CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIBTzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowVjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJjAkBgNVBAMT
+HW9ubHlDb250YWluc0F0dHJpYnV0ZUNlcnRzIENBMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA2E6R2OJ/GnvIKN2P902pDmSDe39PiEWDdyTU0wZaUg7f
+3B+NWwz6zfuPP1VS+w3ZIpzMQN+KfsTQUUKvK98jvHRRUAZbwoM8RToVFkjoAsG8
+vpdnzPS9rSTKOkeaJRg2XqR5Yvh21aqfxi0EPszcBn2B80UugX32bLv3znE9Asoh
+jbP6HSonsmWBlAAz7XNlb1C/Q2Zp54fCeXyAbCy436TudkQ6z5gcUOlvqYvt3QUW
+xX1SKU08YDM4dkQD1w59iGiI9T4PUyiDxAVoJrGlv81nUYchOdClRuCjV8a8/aSr
+dnrEnxUxX0jZ3trXidjsPhzo9rYIPe/lZ9HUQzJwcQIDAQABo3wwejAfBgNVHSME
+GDAWgBTkfV/RXJWGCCwFrr51tmWn2V2oZjAdBgNVHQ4EFgQUTQf+9i28tRkaUE3f
+mQR6bTNwkE4wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEw
+ATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAXvMeOuZFCENp0
+hdymDJLOWK5FAjdilDU8h8K8Eu6kDQ/rKGEZKd39i8hDmz0/utfFge7VHSwh4LVt
+VAM1tJrdAQDu1aApKTkIZyb+ShFX427DjFcDMBZjZ0Rvz9/qiGdFd59moGIqao/c
+P7wKwLp9DCZBAa3ydLzYe71cX+7u11vbzvKNFfjy4PQ7VkjE9Hu9w4O2d18mD4Av
+KwEotwc7loNCrE6JEjTURcmrvJhuOgEIsLzVzMEuwaWeqiIPeIYHl/q1TMixRfkc
+UWDab7wLgb2TPZMtnVGFCp+cClK7R76iEXIMoofiuQb/uR/Qpm2ODQTlbQQFH+xf
+y7cXNz+M
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C7 C7 6E 53 32 81 C8 66 3A 1B 7C F5 61 20 4D 39 22 A0 57 6C
+ friendlyName: onlyContainsAttributeCerts CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,18B964FED0F9EE04
+
+r/nlBrK0lqS6TYiBdSIkthWXfj14ZE+eh/2ojzM5aopppXI0SjeuiKX47dyNNCR4
+cVGE+4wYkptAhQb855I5JIin0I+VTSYAcFev5b5HH/3P9HxMxyAWBemVzpTQ9ZUU
+0icFn/0baLg168yZXLMlEBzC7RmqHzlsY23VyrTdr6LsQBlyx4G+gf3tql4i9nn7
+rgnc/5O03VkwCzWLkBAKlb6vsWD4tdQ4umAGSvW1bWXixjWH/6rh4kA27bMBc3bZ
+Sd6nDnDUgfBkNsU35GcjUu+7XB/YkD94mIkWvfjOyY0IYduoiA++dW1PcJwvk9pA
+JgGf13uQGpsMEl96T2LajrN2HraghZBJ1kUmpJrSUjYrpRBhAqbBq73FQD+zLqy/
+sT4sHeiRldz1ciCAb2i6znTNIlcNXPmYHVD/bQCi6HbQgY7Cus/kEjim/UCoTwZe
+wmU1ZwfAL0d4AHTIwsa2cysBQ8bh2VUOestRkO+O6Nd7bArJC0VRJTm+D7gQ3M9w
+9WqRgDYnxxN+ADYTmuMjf9Va9J3G1Fw0NF7RDh2VoF9rIy3evex9noqVCJ3JDRf6
+fYNryHfxlunIPTyiwA15tMU8Aoe7JNwEw+kwIDLQWJIz/7rHK1FvrgYBQZpwY/9n
+ytzEa56G0jwmYu2away2R/mulTbg35jlbY+NEj6FhmtJEGvm9doItm1XM3ON8wAI
+FGParpoLWYEye0GrSDP+odREDQs4QhOyexzeV8A2H97gnA4iqWaFSPBty5wrxGBc
+f3W9xT4Q7ljpSMjSZDS6mW+XLwqJEaBx+T51ktY9d9sRG44aaWNsV33L4yNBty84
+H8XpJ8NAizP0nh/lBroXT1TgYCSnB1v5glZI3cN+jcj6mBG5n8wF+pjmQRx1ionJ
+lkI2Qojo/VOJc2tBmxzKKK9URB/h3xX6t89t8NXP+NEJg45iD9i/ydp3Ir7UIuIN
+HEt88tlPEDTUSTDI/eKGmPzx1OYTOea0Bd1CbhB8buoPk4bRB6hnpyQgCNNOSoDP
+NEWQoOpb5qS83RGH6iYjxIK5IMrNL+Bny5gH3D6cAaxNv4vR3kB3UAgInMYO9CHs
+acSwr09cpj3nezQeOE3eGBpNyfjD/mQ9Qnhc9Z8uL4gm1QewWEe4C3TqkH3wQvTr
+A/OjOMNSjLYuf10fXFoLM030T5K9kZMv5gAz8lw6GDrt06plRwmWGzrSKbEj+tg0
+o/B+H/83wtqJeMCqozcHzfuW6lbhkq9DsSgIYIhRf2bI4Ez5j3zQyyF4RWkyKkwn
+BcXbu0aEE09Eh2fU+cGqJ9GhhEMa1gSyiu+g12SF2ptQQE3pw67UCoe9ebQcjcfC
+jggwIwqHJHOBpnnkBoekFxgOtOhfcHf/hxHCk478t6mEEgMa4BIFTgy1MgwKhxYC
+Ohi4SDbnQze4jGwj57DYRklS137TgpE5yQUg0IfW2aQWzvGsPA90bD6QtcDE7MoX
+QLUf9fwQ1ldHLG2VPdvxQpGvwH7fAb+I69WrW+j7pWhGwe7yQM1zsS9ybK3URE6a
+yNjOhaKokZlqKdTpavZL/0G4Ot/plQXQORse/9eFBHRjdz0UwswvWj0dtMi+HuWV
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsCACertsCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsCACertsCACert.pem
new file mode 100644
index 0000000000..db908bd78b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsCACertsCACert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 4D 54 91 D4 15 C9 D3 01 C0 7E BF A5 79 11 88 F6 DD AE AC 35
+ friendlyName: onlyContainsCACerts CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=onlyContainsCACerts CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDizCCAnOgAwIBAgIBTjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHzAdBgNVBAMT
+Fm9ubHlDb250YWluc0NBQ2VydHMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDIrJf/IZIHMiENvbg/xopK+2CNAY1l42W2B4uRzfJzk31C8sQYmVG5
+RFSJ70xt6k7QeuJ63lAO5vVdtAZkZ5W0WfXQHUPtS+TjWYphpRKbuiFUGg2sDgrm
+Ij8ZbID4BS0vogcN6pGMnbgm8wScYcPbp4MPs5cDWGVjAFfLt3Vn30WfjEofHkjF
+1duATD/nlruAO9OpFJngrA11/YmrAnKd92qj4cDkKBeyUGBkOXVEgNTcJEMz179v
+MzNjyZv/piWMwImQ0BscPG91lEx5tCPaUiXx0zO1EEaCiHNK1MQVx2rhUKiA+pQ3
+XS+M5GNRe8S+P0CnQT1SxQHRRidk7B7fAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9
+X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQlOMOuyi11eltN1MADkogTIsds
+VDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEIiy9eAyhl49VpASQAeX4i4
++gNwgDWHolSxkb6bovr2YBxB/PTLWE4c3zMadsxC4REO3ojaE3bP7dfwvnXXFPUG
+UBZef9rieo3ie0z6SqZxEUieJb2PgKAF6vya3aAnx2WLx2TmMb7iACmLZOFXdDp5
+V+WC+vaNDPtRSu+MX2ttvELFXgLBNoeTmRhWc1kcbR5biO7UB8e+IddvBTiUVy/4
+v6N8QxK9AmqV1apq6Gsx7qeyp5I3biO44ikMMvA+xjz4iFwikphlYEupmauD8mjF
+Pc5rK2DtI+n/lI891EoeW7eyq1pO1vmHTZxkOxwy+E226Yz4FB884EQpsb6cf9k=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4D 54 91 D4 15 C9 D3 01 C0 7E BF A5 79 11 88 F6 DD AE AC 35
+ friendlyName: onlyContainsCACerts CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CD4982F558369A72
+
+yZvCqPFld3fSUveakYCsMgQXmpcS/+wqjWD5GQTtpyjSPLIQHFbd4Pig6eo+5JwK
+l4M01evK1t4ho4OlmtnnKfdcv7GCZFW/89DbrGBa4t5EiFKiPC1RGUt+Jp5R9HOT
+a2JjT4tB/10OFDm3zHbVRCzmrPJDWmuz/QkWrHOSSUx15tAPFiADpcIudYd+Hp9z
+T+o/Ee0LeyjF5f7tEkkcOcuwPV2IZoTCPbOHbf1K9YChDg5ZymFK3Ow/KOeraUCZ
+Jgiw9a58DsGqH+Bf/HTwBXkI56iQOD7Ttsld0dle3BhKNhpP5UxP7bS5LTlpDuwN
+0Jt7G2CtxG9rJaegKWtjh/0LWLrfQ0wiFk8Xcj4WX8nBk4ROeBAhUguTxGJhGR6R
+U6ILFw6ugCGuVqNY4hrLZ78qi75M0v30B3f3k0V+Zz8VtnxrbjCsHL8DAIrl5myM
+AnnfazkHAG90QGgMjVtb2A7g7GM/ZfTHjlXrFJlV/dx8JD5++3qzY7Tm9Xs/vnOC
+RUYy9OalBv8j6fUe5Q20w/HThw0TmoWVBHZ8TQE8uOA6lKbR7R9i/VNjLdZg018R
+7mejo4izqlvYDDH9o8h4Td1mBz+2eqS0aZ/RXAl1KpWPy8vkuDyxOJYYqbbJFhWl
++sCa5Z+v2A+tTGilDZx8qvEEq7ydcn7spOiKe7PNxMtH8YgWGIn5Y4Vi5sLQCQwy
+7h40dDz1GFxLXB4fRJ1GNSMl4TqdJs40esGBqR7xtXLjUFqni3JqFPLCzST532F3
+MkcshUQDPh7ZrfGkwj7MFCTrzXVzAVU5e/Rc4lHdw1xkIiNQkmTOv6aqzAqKMiOa
+sevdM1s594nF9kFp9Pkj7yWTFMosjWtQ2LlUL1X5d4NEeazn1d3sTz9fX5y5R6Ro
+07igIvPu3HnB4M/4KV6hNb630meufYFCD/pL1BZsFF3GkJakMMgtTYVH8ORkUZIj
+fk70vIt+T5u56QVcvMacamdjgFOyQ/UslEMa/1mjTZtDbxNQLMnLBGkIvCYUyPaM
+c/SSpGQ5+aGqpNzoj73whUW5TW6s2SmBuanVOHTuF0UJYb6A+h5zUuqT1U2OH80U
+8Q5a3Iwquz0f68zCFAedD+rymuTk6TKaew4SY3HFHcynifJlv0HJEtbIWgMF6ziR
+1DcQE1KMGywLvUfl6NAKmtXas/JBB1LyGVmZTfRVvBQ56Yvx5+EesUtBGN2sz6y+
+NsWXoJ76jTi+2xdapEevLG40OE/vW5P1kJuWhMJOftA8qCcpYVa68RkmLXIyONJK
+IKbaIKMJUmkx2GJt22UFvMz95Xi9GTq98p2Q2jcW+vRpWx9LiuA0CSQFauJ5J9CA
+P9Mg5b+PpZXm5v0cPlVhKH4b6oHgbwxPW7Z6wPsMwk73gkGupNSXcYrZvUOuKFHA
+yeWGSeh/oHv6X4XdFhn0GGNzwAWVfg1efRx1l3NNFucOTLz1Oyxnz81UQXs/O+I7
+FFfXpuj6vUXfC1KV/fm7KeIERLzOl2T8J3+iG+KIFzOUBajk0N2Hnor9pKBSNCPh
+fO8CjSwvQfARkk8DyuP2pTKIXS+p9+1cvtwvEPxb4WoO5G725mjbTg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsUserCertsCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsUserCertsCACert.pem
new file mode 100644
index 0000000000..d85ce17b3b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlyContainsUserCertsCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 5B EC 82 0D F3 65 F7 4C 10 0A B7 E2 2D 35 79 98 E0 75 52 C4
+ friendlyName: onlyContainsUserCerts CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=onlyContainsUserCerts CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBTTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUTELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExITAfBgNVBAMT
+GG9ubHlDb250YWluc1VzZXJDZXJ0cyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKlNvTBCtZzuTltV3uYU3mQnxuNHBt+V6caK4kDpfW55LCuWYynT
+DuRhO3QyFs07Kwmp9x7wPJKscsFPWMdskNhF35bGpe+rofIo2vmNEGzC+uFXKEnf
+D/1Uz2c02Q7TKua9YwP56F7b9kOAYHB74K9RfWZZ41HdFRNLrY+uS3imHnkKHqNN
+Ad7V7eAUB06hNgpDpt1AMyAfJ/T8u9r1Rnq0NY4myhHOWFJ/Igl6aSzHDQPE8zeM
+5piM3am2Je4sO96a3SsDL7kgMICtt6DOjXCnewKgzt/k8YUMS6//SsDg3px/8XqX
+SN/qA0dFmrRI4iwn20sg3bKAQbNKQroHguUCAwEAAaN8MHowHwYDVR0jBBgwFoAU
+5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFJ28AKncAc3+HZaIfbWeT5ne
+JNIFMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPJByrONlwIFohW4Gmj2
+QZqLaHtT7vUb6sW4pd04EXBy4/8OmAz6giT3NEyMlnSaTlqSRHRLEXZb7RyuNBRy
+ixm1bvDI4nnHpVFhC2CU+5yORzXkXlfDiDl6KAK31CLxxuBeguHbelZJ8u8ERtpA
+9qn/FKm343FlUHVIje/7a2uo8KV3EZT+4V1oPVi3CpkyDIpMypnY6UmQPyuqstxn
+BVgfijZAx68HFb09yMAlL/cOONQfWHFp1igINJEiqE6j8fIlJBiqo1tZpmh6UHEx
+Zky3pmHgczfIlBlaQetjITOxignJAEbU1Wd3mBFgiJIAbNeJtqZNNNKM88zokJoj
+Gw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 5B EC 82 0D F3 65 F7 4C 10 0A B7 E2 2D 35 79 98 E0 75 52 C4
+ friendlyName: onlyContainsUserCerts CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,05240ECEEDFAB262
+
+CIcl1VuzngTwNxm/PxWb+EnUj6m6zKj4SDkKR31SKSRPg8GY+uG82CKI9TqyZoNg
+pcAkXBt/hTOs1WyoqXrH8F+DsL4HVayMtT4qvXOz9x/8Dl2/phiNcBo9a1eMHHiL
+d3XV/pD0lDhp4OKrfovaQyINBZnjSTBIka4zMaEaiBIuiZJwrDK8m7K1Wy9qy/xM
+lHRWyTzuoMqoF8NERwDYSlK9P4/Kn4FmwjV+mcsGcXvivhOkCMmKxyOo8ryt+bSv
+gy/4USC3InOKCj7REA1MTAudUkPaG746f8irStL2BTLqJx7mjy3uNQ1l5QNcIHQo
+49jkxBr8E38Pwe982OcziEUAjuiRA2dzp+qz7P935G/pkvaf2htqCPj9ZoZj5Cce
+tL75XITV63gsklIJABxEzednnaa3qMTd4hZWrx+LW+c2+h8vj/w+ScxYsGLDFEvU
+Yw3lZixspWZfnqCltUX+p4/ZcK1RgD8jvQWLhGUGAuzxg3c3mGa5vyh4ZM6YP2Nt
+cuaClNBSuqU2utEFwf875GlEJnOIFbUZDg3dchZAsF9DjhC7x5jp7XfRjRsLZjPu
+tYqtJD5GCsmevLCL6VNO4fGYc/AH724QU8LeYsvFcqupAIs34cLa6JRRDn+tU+j2
+SBICRzfF36+jLPUTPEckXnfXrkTNheEfOscB3UisoR9h9LH5AjpAkMZofGPt+rO4
+0OhfeVUNTQVu8qLbInIehWbi68uOGvEDSFqqDwvpYG8a93o3ovXLFwzpbb9fFnaN
+2M1R6TN1h1ApFPNqcNApm0Mo3QTXhpkMoIM6Ik4FU9/4qQZ2rEMjB1yom3VImp13
+UPpxDo1OKcI/oyRwV1+MYUhpV5tXnVw/REUY9aQ/9+Xgm2wQ9xA9iqUh3nLt59HQ
+2Iu6TYzs8EFC5pmMPXhZ+K9vRNq9aeXVnhZp1Y0t3BkWE25Axu3vNiyLKkLIIwwr
+882S6qHcEsqYhvzR6FFmu0f7Hn1B/IkZ2ytIWNilRhtHgyHRIoucr5Lj1l2u/NO1
+jdlb1Xqyq6V4APCtL8h84DmMUv20aLTnYVjGWRsnNwpKs2GAiDyEr3DeiNg2fPyk
+XDDZcLOEKmXLLoAJoPPyH3eK52IrDeqV1NT/SR384+ri2r7NM+wMmI9QZbVBO4cS
+iQjU0IUrjlnxmmPRQB1eccbtZnnzzujmc0JHEfmWK7VUmd4VSjsN5EJyGxN3G8rc
+ccOYYasV9XeDxOf4yAHsSIXWeIIgz0gqj+CrPcOwj0er8pSl6ya+V/ajBRPZ5XKb
+Q7gBTwoktm4fKo8MRT+BNnAcOf0llh2Wtyu3Etji32hU3DsoNN0i7TaQo+nwhAY5
+UGUp6V/bAGmiyC6ZL2d6jfJJtQIXEN0RPfKXxm6Wog+/IepJh8NSZY+6DHTrXJOC
+aGM8WYdnWskbw1xWCf+jRRqpwPzitlcqB7yG9Ut6Pu45WUAUsRsgKnX/QzAzRXa+
+8VhCsYppYDmGjD4o9T37IiNOKyKQ1Nazy80yBmhqMPCCvxSGd9/grNnTzUkcMYHH
+X6QdSRCa2SOTyUl7Vwg3eCJPqugZWgoLG+k05bNWKZfljjbit95ZFQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA1Cert.pem
new file mode 100644
index 0000000000..acc2db9ec7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA1Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 21 E8 8C AC 8D F8 F3 96 78 B3 9B 03 AD 1A B9 BC C4 27 68 AB
+ friendlyName: onlySomeReasons CA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=onlySomeReasons CA1
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIBUDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAMT
+E29ubHlTb21lUmVhc29ucyBDQTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDNCh+UU1u7RaINmvHQNlENRQ4u0my6Kk5jTprQKZym5xXcNnnlCdv/1h+J
+1ZRhcgkRl70/RucD7c7q+WLV1N7sDTOk7a6d6ICoXLak9piG4OBC5y+IR+L5vO/k
+qCewR3ORPup7RrjsrEPuqlJa9yi1H55BhzLRRqPvcsumsIzHdXN6BwT7a0eCHqCM
+5a2mh0NT6CKEbQrMMEtDiKdItUYDPsIPcquxIrP5uoF2uuERI3U1p5UXE3owxecC
+kvQz+dMGz7QQACKT2cNYhZiuZVtYfUrAvdQ/E6LOhlV3eRqdPYsFZHU5ijz75blc
+VYMUBFPpqp5o9tddcGPFs5YS2oyXAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9Fc
+lYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRQaNEJQSeH5wpOt3hW+xeO7gQHcTAO
+BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAqealoCILXGegRsrAUZ+zTqnaVC
+6DXA11OnQhUkpMvCWG3HLfNjEUxMUohu73U4akR8ByHKgZlY79YaZEpViC4ipDFu
+w/Xs+NW3L6g5p6sCCaqAa3YODnZLET6SOWjxxgBhmoydDr9V1J/DfQyBV3NNypS0
+UN0njf9GXMrkJ05eA7F1JXpAbnhHxWL9iqmj32jaXj/WEbiRriOq/puGvLDnLYw5
+1/DwmKYrIfXI1erTIjVvMz8XOrqvsfbTdaHtbQjGRoL8dT56/2OX7cfp6lP+Yeup
+Nwt/eHp3sUXspAWHgJWy7faNJPYyNJriNuYDqJ7Hwa3mT29ymBK5nPOBmNQ=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 21 E8 8C AC 8D F8 F3 96 78 B3 9B 03 AD 1A B9 BC C4 27 68 AB
+ friendlyName: onlySomeReasons CA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3304EF028C8F37CF
+
+NHfxWzbgnnGAfj7B+tA4sHmQz1GYEAMeQGti7fyiIKAfQnihapXoQGld0qD6J7YI
+ASbY2A8j4z15TEtlYgNoqdPOOfsTqIJofXuYTnmWkKHhALUbMR3tnN6jNXNwEgen
+t12yv4tVjG7Qv2LVH0FZgAAMpa72HsvnK1keiO1e4th/QUIeLAnm2zyABfgRTSnt
+HumfEfeuMquGvSG8zQjAnLLqhrTngeMxm2so0eVn+WcohUb45HTGa/dhPsUJmFWS
+fyGyXiQ2faOb0AMkC3IYZGHymBiJU7ZVkvim2uft92ZDwl5NylpOGVbbbgSZ4rmy
+g+ABrIvOpr27QyxXMx9bBCGff1VyHTZt0B32pNuUjpnxpbq5SYJrUqPgvCYk+OYu
+YQlnzlrQyDTrYsvdWukZvEGNFrxsqlwJecdj5OOYkmNvOnu24xfFLjh26PYdUrJc
+/LM0S/qFLaffF2koWN2vv7Bt1Mhl8xnCMd+vjMR7NYO6VYcBH5Fr52P+KViiQXuj
+iz7ej0OyR6MsKEDqFokSS9r3k9VI2fHNFvAGie3paEaMFcZrZc5gIraOcZHcAsei
+pjf4IDFAs3cfzo3QJ4AxPYKdp3CwlizAgvAferGd1JmihtgJenJwsw6ODd2wat7X
+a5ae+Ax8mS5M7r5GZYFMtq1gc5sLG2zOkuSBMCxrmUdr+Bn8vDR2o8YaGE7TsBg3
+K/CpiTV6JThEWLaZOwUoE2njT68IgcS3FhkHWL0hMBhTROuAB+xwzg7paBtMbpya
+4UjP71tiAGnpKI+ICr+h1ZDCd/nxnlCVlYR8Iw3wIHzpUB64v+8vN7WifK21sJXV
+sh78kbAPYHatOAOhApEY83Zg9jWfwLmOIF87uLA6CLZ13DC5F5i01pELEqNaIDkk
+kgXOOCaDXzakDiedJa4PXc35cRLD7svTCY2S7F2e6sd9zdM2cvqNp2t9coS/v3LR
+nxcC4YFkinvH6kxhy+gClucw5DIKp/YZAiz6nxqqzyww8tFITAYew2BQMxLkfThS
+1qcONAvcNffr5v9vpz8eSDNEfsBnBnUZmTJgcFEOimeixkclEQsJmSSpHYN1242K
++8fLfTY4WwkmwAMVAW/rY0AdIZvUgjimQlX81qOxn5lqc7UdaxkcBwkT7SxuZzMg
+X0ee+Je3+Jewh0zlrmz9fkQPfEzzb6AEiw6VSQHRDwDz5HTH/YaaEdor9WkCE6eA
+uwjeu3KVMOY/AiLLoBrCacpYUVpi6ZeQwFENHY5JBs2GQ+aTT/Xp8CoChx6K3eyS
+QbVJA1dL2CzAZyO65hU3KRqYQli+XScj7RSNoI2OrmP7v7Eaxvp+6dK6g2e7C8XS
+HR9Z/hyWPBTKs58rHKU/jxOM+hn2XQGgbvzg4msuh8IaI3K30WDcKyg6FIS6pDw7
+HjWeh2AcnaoMosYTdrNA+czzk/LrMbRZl1Mc5PMPKgAGhy9jvH/7iM4nisQEQ9pP
+BTklbVQAycz5xJb5fPowoHgi2uba1PwxT3ITdoAOxebqHyqa4RFjSZ3q/71oCv/e
+sn819PGt3yVT5etC0lcoXDhQ0cUCpoZypLuHBm1aY4ePwMUKWKDh1w==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA2Cert.pem
new file mode 100644
index 0000000000..75bdd78cde
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA2Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 62 D0 F0 21 17 A2 D8 EA 5D 5C 7C 5A FC 05 E1 98 F1 2C E2 4E
+ friendlyName: onlySomeReasons CA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=onlySomeReasons CA2
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIBUTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAMT
+E29ubHlTb21lUmVhc29ucyBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDGAUE6VKx4EWe/9m53te/ZpcBa1Ipmkzzo7oqB0EQo+XV2rtBbKo+aCclV
+3Wz9fZ174ydCxbIuOWkIOHfy09Xn9mBOy8u5xehgFRv58p28VIaHjsLqW1rKimdj
+4VYIlXggNjWaRv+RU8fthz2N08yC/0qEYKGl/n4JGax7/T/EGBIUXGWMLhJsNuBA
+77fpt6kzo/CIbm3Ad4y1P7CvKIQpDRERlgz46qtBi0vI7X2pu2L0URYArkUYXwkH
+pmszmcovcpgZYEkszrk1qwoF3Mr2ETJoTQpyeYVDV5hj/5KcN1D5z5tN0pCabJS2
+NH0W+WDo9j7eVthnD6mTeWY3fQEFAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9Fc
+lYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBRgY9/SI6Qp1kGkrMqGeZimZQFIrjAO
+BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHGDsZYn3ZAIZ2H7xe+cnSisch5E
+jFuol+JqPT9CW/cTbC/HKcUBN5KEq7gIvTm/r7+Rc7kK+9I1dxxf9ZLxSBgfuNfw
+xUj1sn1h2/HLiQj/4kFB8wtFCTWhur28AELLqiNuMKyGKtJUXqKy6LGcfKaiUVEZ
+g1MH+DfVpST2FBGyoI/vdPyTt9wUABwUkPH20j7ff+u17V3BR3TwCs1tAkY89PNO
+YAcc51fMDEDl/9smo38DoiCl/SKWxYaDXuDvTdDcDsitsOKrolL+9dIToBes5l7B
+vl+soT0Xw+IQ+xptAUfchKxsuGL1DkWOsluGdSDdGhTOA7Hfm+szyR6HlS4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 62 D0 F0 21 17 A2 D8 EA 5D 5C 7C 5A FC 05 E1 98 F1 2C E2 4E
+ friendlyName: onlySomeReasons CA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FDA79368BE51B572
+
+oKekLSBkqx6Uyjl8yElaf4zGCrOxoudKNxYh06k0k/lA1UWK9sAxF7/3oZidtS3h
+yS7UK8LOo4YPKkX1v4huKryx18H/TynyMP9fzVxtekkVrunzT2L922LhLvvxdXPg
+QgNUHyjZp/SYijbJCOgBRRwnuBonMfFQOgrOKTyVvW6h1Grd6kvgEVAYl6F6AQxG
+lEbDT0i0GwPO50qUciJJYTz+rGq0KsRW1b3PmOz7t38jOlRGXWZynSJ/SeHWKDDz
+oAAn3Xb+ct7aUXgA5saSTiCrfhbx9L96t6d6oARtHu7ewfq4vWbPlArir1iqwCkG
+p5xmPrduODLyYLEyN4+uHs++xGXkigRObRsVRPgH2H94h4Fhqg87qqOMD6+Q+yN6
+caU0fWywK9Ac5A5wuxJ7IdtGx05L6RmVGSIE5o5PMRLz4380+5cyJcAmKnTmjZbo
+7iRIz2Lkp+Axq0WyOt5sDraXEvgbs2BH3sA72JClj6YVC0IPJVFaTgwT7WLwSrSS
+KeXREsTm3mLOM++egUA8GNBGDDWvtsuHTYcmNH8m4kodWWocycvRm6mGU/Y7rq+S
+23n4hvMcxqpLk/yratJe76ij86rua1a05bxNJ92ITBpLAPVS4WBMEmv0UmllURDZ
+zShSIbQBbcEcWJ6AFkJ3E+oIIns1Ml17X4u+TzM/nCF56zGgVLz2zKRCtyTfMQ65
+Fv8xzHZ5h1Nu829er53WGSR27FIB+nFFghiZ7eQvm7tb7ggUrw8JxZoUXi2oRSWk
+btc6jC7iOA+8AMi/yR8p0HN8KliCL7PrKbyJOuspotxC7jIhzwcGRlKqfZ+RtaPs
+HXH1kM8vI0kCByL++HCNw5DQZZcwscQN0RsDxmN4AY7tnOTBwhTEGRjtG0eYw2Nm
+6Q6qveTg2pQeIlRcpqj5Gsp6T+OJ0OXO0qPM9YmOI3/934OizU0ZZfLQ6/2JM8Pg
+nEDuOyxI6vrIVjP1nxm22mC6dHU0Dc50bpw72omR/oMmLV/GzhSl/0quLqEvwG1u
+BgHLstIv820Cu2PCD3UGxiiczZeIYB9ERKDtRAywlBnqnqze1+6ZMPhGcYFyaW2w
+VI3e6XshIfztVX8vIyqxDKlahMFuBvplwPQuhnE+ELZi6maO3s6/wgoLdSQ+IiAP
+6xk6Iuk3K6SMG2kW/hs3RBumT2VrYBssiVwQIO0zcF5cExlt43iAu+duels7sgek
+AilygrSHgIb+ieEvsbwJrRkG5insPtcLF9R84KX0AZwLx3T8j/yeSupJ+3LaDHrZ
+bMCKr2sa02MWcpS6aa8YZOkQkGNn1Cm98/5ImFLSZ/DxYH20Ul/k1FqC/wMfGe/Q
+lNXpIS56L1owxpSsEPFrHJ3N4ihdGMkxO/kZeJvwyNehKa1pLvAtlChveYz6uqiH
+pZ5iy2frX2bAOT2U2fNEn0Wn1Lioa7My+OMawFlxWk2SQRmLxOs+I3jaXeMymzV7
+/ihD1ara71iekkG+NI/zpcQYmrDT+3DZcqG5m+r4gQ0wjf2blVuzBIx2JIO8abYu
++drPop9nCT9WkSjoGSMIrUYxxDQrMCp35T3EidPy4agVNBgP5xRb1g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA3Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA3Cert.pem
new file mode 100644
index 0000000000..a5308f022e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA3Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 05 95 13 A5 8C 32 3F 73 16 26 CF B6 25 46 FA 14 26 76 29 AE
+ friendlyName: onlySomeReasons CA3 Cert
+subject=/C=US/O=Test Certificates 2011/OU=onlySomeReasons CA3
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIBUjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAsT
+E29ubHlTb21lUmVhc29ucyBDQTMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDW7KN86+AxdC+M9zUVhx3zrIzYb14p5bROLn0oVLrX2CrAzM0BJwy9Eyfs
+Kjz+C+hNSom6zZauHScCcW7Dq2pwYodhJYGccs+iFTppwtqOodXhiDEs7XiLM2tz
+Y4HTqJMH1XRgDZQemCedZaeQvqjj5kwycktkiVKfyHVsGIKYbt8Fz9QGNebCGhvx
+iwQ6pvMfOynEhCObgwyCU6FQxEn2ZHo3uZooJbxYnMiThFjdKzUyvBfsXaeawmDc
+vXwCBHYy7VFs8NikWYcek78Jt+6uoQ726NA0QgXz2PXL8Tsh3TJ6JqLXU27rxJOR
+Ih4lDtnYuZAuiWGi6T8hB3f8+DFNAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9Fc
+lYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQtJLeXhyzu2hy+3peEG6+gFRa+azAO
+BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFZ01abRiJllD1coQl+tPkFpIrX2
+/6vIvljOU6K15UFRovO3Hct4Z3hGszZxUtyI4ipGq/aLVHbjvW6Jd/CgCnZ76kSD
+px55iLVFepfaxksJjWWbE1Oe72foLiHztJ6tOzXT9E0NxXPxrZFlhP9gCN8tUak8
+wS7URFOorHCxznZMxZ+ADM6g77D3zBf5BxH5iNdxD6Caaz7ez6yPaA6APMY9tsiA
+jF7pW6F9ETMZVug9be6PpzNHxsWBjE6wkpl7qSCF13o2zvcsXzs5TkCjPQWk16sq
+f9Uvt+oEl/4OoyIQ3kS47aedWc3mL855YqCz5S7fwRWyhKSTIC0mFCaWyeA=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 05 95 13 A5 8C 32 3F 73 16 26 CF B6 25 46 FA 14 26 76 29 AE
+ friendlyName: onlySomeReasons CA3 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B40F3C8577730807
+
+eISBvf614CKAGf9IwjMT68YoFuH4XXc2DV6P0M8yFhaKfZMZpIE0aEt15buADWk3
+PSTOMOiJ/V8Zi1EKHDl4XOnua4WfDwVX+Tia75uSwOjka5UxE0bqLOqekCw0hUXt
+HTV7YRuOd+uln1wnSxuGeRxyhOjPJ5rcdBrULgtPNqAJU/LGrGXIc7S9Cb+i4/tk
+oVPRjNl3NWr3RKMSRebw0P4Fw6q/kVUqLAfPg1aC0kAvLCkV6NjpiSD7xuaHuWOm
+qIvfezo4PtAZciNs6Fco0OEv0PTrfKrLV2l+tP6tDYitbxneaqWRKEzxFaX02jIQ
+q5sTF4if2ybg3cOAus89G9ihAZUIpQLWe5GLIMmw6TeaDUlUSRejhOmuetww9IGM
+vkgbtogQ4FylYt7RJyj5WeGH/7Q0GqTDxBzAlOLJTkq8jknN/HU2gW0PZS+CMzyd
+e7vgOhF2jNRw20JzLyuDAIWh0crmCKohhmeHbJ5MxvURiTLFEZaHCVCgdSYfaOvs
+lSmehPn2YVsHi03o1ERkcCkkNVI9R1WueGJnbbRCgcNdViWfxcqw+kle9Hq8AcHF
+gkuG2DzK7nPCFFUyQfJkjXSdkjnWTt/dG1U644/aslAubENl+zS3QabYmYpfQPc8
+9IIRW/+n2Mo43HNk0erF56Jsg/Av42gCaYeMIJhf4j6HEimjI4jaZvzSObkK+FAH
+kkt4XAvUaS76qNXpHFvtW3NiiVQDrfOIhyYcMFHjVtlMPDp8ttKozAMrc9tdVUZj
+gB4Pj+cO1T4QYGNIwyRwwOGm4XWsBD0qFVcxtgx+JyCsSPRXTYlw8GisaXqK8J9u
+TWDKYm1RBydNp4weVnJAPjLF4c2D2VXxnqXkwkhL37iehj3ZHFKKhiCL+w3ennjD
+sqr333ak/So853kAk+VV8EazMzxIB3bdr8Ok3lDy3mXBOkPhOR2nc7oDPPV2K4m4
+ECebBMUN/4FZu1zLU2nWizLVcIP7sfV85zCqWh5EzmB03w+4+zg2e0zXk7wKo+wr
+/Fwm1cO152aRe++B2VQaPdRL8bAFy+zqguwwJFJqDkK99xdL6NQAe71F+3r3MM6C
+RdV6b8GS1axdHgQz8FrnaUDhBeMjq2fTqaM+xHwaprmdGN9nYbnCYNFi0zdxoGSE
+7OtVGwT/ZczfUKiiWxBL8dXbdL9erFpEJanlIA/4oYXurB99wsjvrXArTfgYJc9v
+lF9DI/z/JYjM60MCLhaFYH/3WxQFD84/wQam1QHgOpZN5IZj1jOH8AXunJejYWnM
+6DCmfsWr4yODxjSg47+TAr3DnWHPjl29bQ52/DAM4qoVQKzLr8OWIlKo2djTMXr4
+IZOqFPb63gHo5zGKav5cRrSwT42k7OZf/UuBJNiqN/eJPrIC0wqWrH26TAr/8sw/
+leI1tGWFUH44CBhtOeRz8fcnXqAWJdPjtYsCXf713HirRs4W2WpNgraV+WL3aIg9
+zx20bPGaqd8zPE4rJ0vWqXyio9lVJrNcVB+93RD6Znyi+0VGZZKA25lmY+VdvW+/
+JpB2t/8kBzWFnyIR1XJ6A72PSZh4YrUm4QLYvHYenVbNH4aHCstJMnKHWJ7MzwLh
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA4Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA4Cert.pem
new file mode 100644
index 0000000000..c9936c65e3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/onlySomeReasonsCA4Cert.pem
@@ -0,0 +1,60 @@
+Bag Attributes
+ localKeyID: 64 DB F5 91 85 C6 DB AC 2F DA D8 B6 1C 80 69 1B E3 95 A0 9E
+ friendlyName: onlySomeReasons CA4 Cert
+subject=/C=US/O=Test Certificates 2011/OU=onlySomeReasons CA4
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTDELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAsT
+E29ubHlTb21lUmVhc29ucyBDQTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCcUg1THz/u9oqguGuyVJRqpN2fztvDrzvEDldGjzRN+M27cnJSU+AkGwYI
+/orIzQOrI585VB/WEuofYlKna3bw2ARokg+swgs/hK9w030zgx2idKC3mNghUgJG
+EjBfzLDS4j46eFJX2pTginCtrriiga0tvuLDrJG0+deeAT6eBEbxEYNEsc2cPE39
+1yUhT6Q3kX/kF480jStykRMxKlms4y3SlyBKkbQ/DVYyY9/TLyDc4l1QpUQ+f22L
+R+dYJ9SRQoO/xFG9Vukpo2Yl6D13di9JgdKdNj1LPc6yG0zwneOgVwliS515MUQ/
+BKOwnnh4/0oboM6wXw/TtxoVy3uNAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9Fc
+lYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBS+ZtweDAY79tOINJFTJoENaBduyTAO
+BgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAuptMQ+7SNcCu0O5GBSXdrWUsKH
+lRusRE/IVoNjuhfjJthO4WLtAs9HEzz1OOqcksxTEm1XNG4CqTAoubmFQJ3eNm1n
+jAZTPqO1GZtrkd7CTtdJqDcM9OYF9Qp1HYTXxcz4Sm/ySPiJV9tj19ZKG/phx1Ib
+bLxtrN7i+Sn2Ym3yI+G4JeJoaVCcuhLawEaxj8oCoqNPpt0/gNvizwEmt/5yssmX
+qguxcvQvSW73Cs3nrTG7/vqRQz1gKMwBwGfZh8gR8ce+2gZguwAvykE2E4b/AL3G
+5nrfM4sMmlnxIVTbuyvO4MdefvBM/Q5wARuwkSXg64eWfefbvhQgx0TBQ+4=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 64 DB F5 91 85 C6 DB AC 2F DA D8 B6 1C 80 69 1B E3 95 A0 9E
+ friendlyName: onlySomeReasons CA4 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3877C7AFF63F6D80
+
+y2SpiSz0QuZ0CzWgn9UD/m2tAiQ4UYh29P/VdmsLrL7zy8bbG6CaTDbbzV7e51ny
+xVPqSNKD9hrRv2Lsv6FFTHuU7IWxzSuz2alDWDUnXP1KFrgS85+PvBkLaJKTb39p
+KavK3TaQWCIYqYXU1APK7nLhpeem9nIeEv5GoToyD7v0FZR6JuLAPXtk9aJfTy0m
+cChwCRw2CzjHu2h4IqACpO8Kkhk+zH2pOd23OhERiTXOqMYhVmbmU4B2cpOjHIf4
+3HjGhIQjz3UWTBX3Jq++5VOkZJT2RrFaTwVGwd5nl8LlgkDEeKQyfGWzRykfvTn/
+oOAjANYNDur3ONBmy9o6sMsfOt/76n8gLbkXshhf/obSoD6hw4thSs5++fPANaf9
+/q+FDfx8eOsP0nVvV6mEDOFL6DYf40BnSkegdnfnbs5VRZGm0wb8y+JPWCy9Zs/4
+eEhJbRQZ1BncIIfSDcUchxdGaJMxh9zETjhLHvIQKdFgm8s/UNZv8wExng0DOV3W
+m+Ptv4ZvBqtjj4l56wAf669HQHpZEUNhgC4mQjfvWsYU66NRYPYlZNFs4Ys7QAwq
+/a5rCbpv0Gcjxum4wo2CFmuroFEXYecWndmoeV8EK5q28xS6pfFW3XSbAJXRsu3n
+IKdnmvywoyKZ/RQGpDffSLGXvTbwdiogHQ3PWtQQfkruJJKuBKw3U5Oh+6hkEdU8
+kJpXDAZRYU3gYEpCkIDPfR8VTZfiaHaw0yToba28gZhhM2h3BQqE7Nhh3c5kH5Xl
+ZzKmL3JfGMjrYwQ+iUpNdgBCrSIdQUAta38g38payjra8YbGX3DqPDi5CSkHXG3H
+zFvWS/MN3oGJoNKXQmUrAcWg3Nu2xzZN29gCPkx/+2eK+KZIZ6CzGuOul151k3hs
+2Fps7jDPfZejwpKKKLV3mhRp6lnSAqL7rTS1Z5y0mnzJpkqwLeGtytm24cgd37Y2
+6vtxFOKsqA3YHc6rNgk+sZlupT0f5/oyxE3Hy1qbnK4THXsCEEmOQFNY5lD5A6vc
+Jyl6g8Tlf22NAGL5QU9/aIrWIIV55FBVDBnk162gS2XFExLurgolcG0R9dEa82sF
+urX86Nio4m/QGELxIEqDReJ6QeCidE+yFQnm/gGDAjnT73aaN0oxTX+zA75MECqE
+iOYBdC87jBIJE/33LwxuOLDIOk7IPL/JJsQg6ZWJ6rTAlPYiqGldn97/+zFXOqC/
+H7HS/aWMnU4kWDbClKTWB4THUfNdrfuBhf64sAEvQpqW2d0AgeZyHFS1Esc3m276
+n3wDmJdQLSoiUEtlQ008n7uREl1aJhS1Yp3DxzqFrcqFytINvaXPgt8RU16HPyqB
+huYY9K4t83QQJ41GaEYLCOYfgdMTjWEavTWozlak3GF+APWK3e+hWf7+5NmIO5rr
+E2hic8Mjc8rODbhCddsbPdWZXPnE0h+LpSgG1Km4flT3Z8bNPbd2TWaGKCrYtGwo
+8PiC/86+aVLVaviT1lDegnNmUMVAhXI6tDAfJiUnqYToelS3KnNYRt/itRBp2EQl
+iaACuUMPxYH7u/VLVDp9kenwPJNWQCvl13a9vUKjEp959xGBTB7PeA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0CACert.pem
new file mode 100644
index 0000000000..9ad542d1a6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 03 50 A1 43 9B A2 1C D2 AC 84 CC 7B BF D3 C5 45 18 93 E7 68
+ friendlyName: pathLenConstraint0 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBGjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAMT
+FXBhdGhMZW5Db25zdHJhaW50MCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMi803q1skF3rlRLLe9UJy2uHFEYjwqmpOnvDT+3GAFrYFYjS4u7307M
+pOxI7vPwlpRMURsQY4k8IGlNmXgHJLTphFdARhmPWskpfAfC/7mnNrYqvOCixnG4
+1EYhnCrKN7Uhni/l6AHT0cLp3HmnNXFq0YSWVpWOZ5yx7KpUld75+MqUQixEieXc
+PunjGC6MjHJQFrko5igrcGu/PcETu9ao2CQZdqnYb17ftxSiSPRUtwilTLEikINo
+tzklWM6HEO+aQyXi+Ib5UVfmYuUYZCEA5xZk5c1Q8oYd3EAvbP2EHQL1cPo+etR8
+K5IZ3zpu7rt1sD8Lw4JSFVNejDoZrl0CAwEAAaN/MH0wHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFJsrsko8kMVuUAHJIr1jzgnxjD36
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwEgYDVR0T
+AQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsFAAOCAQEAQMor5mePNE4lGLLT0vop
+fvEOCEJSav9+ufqqnH7BrMWQ7QzXH1pHdA/IgPAXXTRVWv2U83srUxERw6aAyuSW
+DJ2g9iW1ti3fqLM0X+jDLrCkjIpyeG+9R+uvEG48FTVEYrWr0yeI73K235XmZh+0
+vht6STnnrNNX+ZUS12wEPOes/TskflyZXcOcodC97gr+veazS8ghL5RPXKyIkBLn
+jRsarcwDyN8KQbSlsUtvv9nowqVzptishiTXHZRnKMWMr91gqVnRkhjoXPsRGsq1
+ytueK4tqUCRnBwrBp+nfg3UyWHfh+Nj6XG+VYkjAXUVytqZdX2rMFTh7qwGMH/zz
+jA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 03 50 A1 43 9B A2 1C D2 AC 84 CC 7B BF D3 C5 45 18 93 E7 68
+ friendlyName: pathLenConstraint0 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7CD6E26377E7D236
+
+aqLPrf3wLKBxZiScg0dbhdX3K6sZ0ydp8rKlEonxU1efiG7eVWAmvgUTbXGt7yuU
+eqd2XvnN/voC3vAxlZbo/RrYRvpWG00MYaYBn7Saus+huZpmozXzjnMuVFwSYARf
+ZmYRsHuNANm6fzulndJZuPwu80p0H/bjKd5jKOrluHd2cap1LuiqYqpnjvcjxZaC
+Vpqnc4jrvprb46ygz0w+9Tpgc3XodIYjpG+DFNN7IDuh/cMZ5d0tz7NaYqWDIDzr
+b08A6+vR6Z23LNV6LNUhjQCefR7VVMjMDt6MxW57KZ8BWMIXikJ0ThmM2eL2nDd6
+a9ARzkATU7/nOiJoux2cRSjJ1H/faTVrMvhwhbVYCwTVSpRt41UO7Xxh0njzgxH/
+BMpCzSlsGFRivgCS/ok4udMWOPJwO71RW6ORCtdt7ZePw7hQS4dq0OYER9EHD1++
+wR1VVdHXu4FIyB96tPp0WLlSIA1uFkffGpOWp17b6NFR9X8KxPyf8G/mdAy3dp5s
+7dFEsbPFPw11eJliOSmasASxI1HpFN9Aw++lVaG+fl+hzBMRYhsYPpheysQz6IY6
+nMy3B8C25dw76ax2wcWM76BvhAw+ty1WbnjPKly2ScS8j8WFwWVNC1jEDDAJCV8x
+XDK4ci/1ijJ3QmxHQaqbi1vWhB8q+6lrM2OOr4eVgei1CKfSmoo2BAYeh6aw7MdN
+JiMTaI8xrp43urbKWwIwXxf+YkL2x8LElutZ9lPONmmtGPjYLUvpM8AIkLnCdQEc
+4hbhtuApw9K5idWxkD4Sn+wYlJubRrPluFLFkXhhnqPYn5ieHGbca+LrZeyjoaad
+HJ7KNjzqJnD2fqiLnIziu9oOYTUULZxHhoiXRvGo0r0S+46qLoKjxDuNzy0XL/tB
+uVr0yPQk5AGBSHa4HdOov881kzgyyTdYDd4JTHXnfOCwmdhqxkd2hx5F67yPEZb4
+nCOrUrU09MVwnlYpuPzgSSCefv0eGZP2ZXLA5j+OnRAODBxxRQe0rneowRInAIQ2
+a809IvmOX/4+vGSQ9jaOhogvRi6Mlpm2acrPlsZqizDlnGH2DAtk/OED36Hpo1xW
+gBE8gynqzEVXkc+23R/wF1ks0vgVkye2qtA7yBPCLDdYMKvjpWE8XEOtTLss5YX4
+mBQPdpJ38lCTRTojk63MtX3sQCaD2M5Kvr6bCgauEErIcxif40e5Qr7Re02eoWtb
+DnfsxNObcshEOzDoJQFcdYwQFiwPOZAZyeVUtxTauKWcR/vJ3kDr/GImixfqpaMG
+oCJEGN3dWY5L2tCb4D5QI7OdPQEDd+TfTcMGa1k+jYMv4c60TY15EQSk9m/0WXlz
+/s5TG2ZfVRUbUaBFEMQFJxgGRiYVEdoxVmUWSjNfLNFQd9x2rJ/gmxuTgaXed5U1
+tQcF+YygxikpPcoz9Ou5Ghkq2YxIkNVGW6nsySdEC2BXk/iZTlss59xrCJ72UkoV
+fMkex7R6Tv7vLJhwNdqIy+N6p8MU3TOQcsHAQRFR8/hdNznIGPlJWKtAjpWfbNso
+HiMygoAYBZ08af/78SJWzw/9Kv70oAWj+uXR5G32Uv+59g1jeorU+cYZzXNaXVDa
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0SelfIssuedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0SelfIssuedCACert.pem
new file mode 100644
index 0000000000..0f11d26320
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0SelfIssuedCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E8 FA A1 FD BB D0 38 25 D5 CE 7E 25 2F 1A 24 FA EA 0E 44 1C
+ friendlyName: pathLenConstraint0 Self-Issued CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBBDANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+TjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+HjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50MCBDQTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAK6/MMP+APou9dhuFL2cxOt7900Egk7KHnsv5qHiDiRd
+yxJk39iF3O2SK7dy1ChKhZtlI7sMznTFD6NrnR9/wAdj8sabFleXM7RMXGCNbKD9
+q0fDqn2pTxJ7oCk7BLjcdvR/coWmAWZo+oC6F/cdZuHAvNI5HILlOF/EbAw1UeNo
+XXfeay8Mjf54mnKGbZLeAMqwpy1Dq0KwnLhMpd54eAPaWeipqPhlAQ/Uc43sVlLK
+xAR+DD1dGh64vr84GTqtF5vWJ2vW3dC8bMiXqVsOyXHJQyFRNBO1f4QedlYiBby+
+MpxTjvjnRZle19hecvhW3ZxBKspQoOc2NveKAdKEPNkCAwEAAaN8MHowHwYDVR0j
+BBgwFoAUmyuySjyQxW5QAckivWPOCfGMPfowHQYDVR0OBBYEFIDrc75NmZ6UvRdL
+WvfPV3d0w193MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
+MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAFT0uTP1wQtXV
+2vfQ7uNjYgTZOtIy6yAKUZKbDssGtwZodj4sAMOqIK4Cc0unzCifaPFPfPS1qDUW
+d7PGUrKDp81rISzOr2XqNZGaMXrdskfDzghTXdwPfpFtxmEPg+ewamuI8zcRTfOj
+sxUB/afnqSBUqkRu5BB7iBE6Vd8Ig97SScxXpudBB/jsm2zf9Hhr4U+cUUQGJpUM
+tVi+MpRRhF5F5Ak9gf/FG6u9D5tawpY7y8nekPGbJqpFV0xJnCp/C0qaJbbTwU/L
+lL5QLVBpLCfdEevwI/CTEUXmLJC46mLDhN3mcCBK0fL1Vjj3k9NRpS67i3/m9ZzT
+ggRxSu4nuA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E8 FA A1 FD BB D0 38 25 D5 CE 7E 25 2F 1A 24 FA EA 0E 44 1C
+ friendlyName: pathLenConstraint0 Self-Issued CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1421CCDA5CA29971
+
+VWBNKnl2soYLiPxDTW4GmlkAyLjZvpqYCq7grCWlVY0xPUiwuZVuQ2xArH1S01pA
+a1IY4ehUoUPrDxWxHo5MkdwyJqzmzpepR4/PebL1+/ZjwKZiyTATToIxylMxkl8/
+SWqdVOdfu7H7BriS6M2+nkpgJzndq9/LqHFj6DATy6jjg3Q+D4uaShLYTP6vXSA2
+j8eHHdLeT9E22ELwyVG3uXvS9T1Foyh6Kzgd2QIYhoQ/XCzcyuKH5kRrWNGWgWcA
+EgDFnZJu1ZrnNmC6vziAUqteNbo7FbUQi65G/X3JcHVBcCdGP3co1rD1uTOAKfBk
+R2bu78wlfOe1W0JripVuT8DdcPuyYZs/qrLep3NzpQUI//4Cdroc7pAlDRp9e9Ib
+D5+Y5BeJQ4TA9ViElixpfn6UIgsx8Lo/0P1sWEysEKQLHIQk3NuhZbhfcZ9ZmVq+
+/fQzbZUp18n7IhbmLRMet6LMb6ogBC4fh61xETxJtk7yIz0incApyD9yixB8KIAY
+dCcCdtqMdbnJRQ7IX4SsGBXkEuCLcpSg6zvrXQ4SQTlWgFETh6d1gziPo9YvYjDd
+Cp6lxtsmDCUV5PzgZTPZ+9O+FmJVhhgRENwFKr+Yh/ieS7YG6yuq0KmZbODthK/e
+guFNm+0UGOdPHhpe/V512JozwZcWBP3hQaXXlWW0QBms8rYUsxyNLUrAM03PlcOA
+KuF0S/6HpIpMvljeEdbPXcGRXY/d9yxZnUtJrc8IBdUVX9BnDOpLGpc8Qpx0stQa
+hvdOH1zOjQdmexDdDcWt7rpyW5Z89cRzHX4gMeeMKPuw+EjaMwUHFH+9m9CSytDD
+oG9xpo3Z8K+TGOIdYpGelGvceP/sUVVKOlfDCoNbBbdFXWLl87ZXP0a4iUmrUqz2
+4UOpFcN0Th2awG09f4Wwbzh0vNs0JK7SBWuTfBcphb2j0FZQ5S9WdUK6qzu76GIP
+XzLCymwCN9a1XyqGrESgiPpRHHLGaMBmMmSVaY2TKoQnsziiuxgh3dlWl53teXFC
+2fY3VI9CyK8zxfUs+0+INdwl52SXzoEyv5CmCDEH0EDoJKxiGVI/qp3sdRknpkxf
+MEsQazANA9sO1rfQbFQnHZuTGyiQunpXlZc+t4hjExdsgWF/RX6122je9BjGoy4Z
+O9s6gx8iJWvqoFaah+04s8b1cYjlCrHHInoXBJzH2wNDZ8HQpqz5XVHTJ9TAkHrm
+6Ocrl5QqKQf7KCuDmQWUMvkt3EioY03Rbbls8hLrF4N23YZqEWpBbPKeAM/TqdeM
+PhUraFZ2aBFxqrA62rEwWFEDBk9f4TuGMRFHPMP4JbL864ZsbyFDhXKJ5I+AIjva
+PWOwohY1PTs2POcNHrmY60MyhqSf1dpU5WCw6YSdiv//MNo57Tzbb7NBQsE6pwAQ
+HjOsNVDz2mz+xtZ1XFv92JjJwJ/f2BwuVQUs3tp8h2LoXxBlr4h6o13/e2rQ8P/j
+yF058yj/1hZp/KrgCEXtdGozT9yTP6Nnn2yXiyZHq5hq5pB8lNbLe2tBIj38bu72
+5Fi3nOks0UiE5o62V5lsZfwa3rMZT8ycm4Cvsd3qnk6iL/bXefNkQC0pAgHwSV/G
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCA2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCA2Cert.pem
new file mode 100644
index 0000000000..72edd2a808
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCA2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 44 1A 7D C3 32 FD A5 01 4A DA 78 67 8F 3F CA 59 F1 0A 63 4C
+ friendlyName: pathLenConstraint0 subCA2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 subCA2
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIBBjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+UjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+IjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50MCBzdWJDQTIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDDwju2MX5clm28dBSlbJqozQEyqSyU2XEBKhVc
+YhHCnnW4Mhqtx3HEFzG72XX5tAuLhjtpQjwYhoz1Q/vHdZrzG5/rtbthbeWrVbFa
+pr+NS1CJqJWMFYfCITCOkWn4BoAzga7reEAsMGZzOsczR3RhtckeYQTfFj21H+pe
+zCcJ0DESZpBW8QAPvRm9fryCl81O3aYAV+bhz5ssnL3hhNtn5Ll1ZDVALkOXtOqC
+sJEkDQNJTaXROuRqUCs4dr/uLHVlOVbhlv+oND5n2ASTcgeyOra4PO24ZqKnmGUJ
+8QSDeMVZ+pauI6mF3MRWouEGQfQVdvXE4jJFueTa/EvvOsG5AgMBAAGjfDB6MB8G
+A1UdIwQYMBaAFIDrc75NmZ6UvRdLWvfPV3d0w193MB0GA1UdDgQWBBTGCSob+7jp
+PmhgeseXzrNYUXt23jAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJZghcKY
+Ek73C7WdWGwfUEVjvhM0L/R5LGNzvHur2Oo3Z3Yw3/J68QNKqtge2W9gMl3xQ3iv
+T2wu8Llxq3rDtMAuVKM29n9UK+rxL6GTb9/n5tgdE9UVQhzKaNvvR1pzTGmqne3V
+xHMi7bf3aC/1GVs051DMqPi99tFUCe761r+gvwQShcDVXRHKtK0bidx7BSKdiG3n
+1b+EbF6w0/xmPpIpP5L1XFJBfnpclNr57zopBNjsr5yuZ8FM17L7jynSlvbJozlS
+EXMUORtLZr9e49iI0vRU8+FqwMEpMsFdHY8fTnBkO1x/01O3x5RRBeYf3Jekmoq7
+q0KsUdvxjpd/KeE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 44 1A 7D C3 32 FD A5 01 4A DA 78 67 8F 3F CA 59 F1 0A 63 4C
+ friendlyName: pathLenConstraint0 subCA2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,87AF19A419801435
+
+sHg4lcYFIK6ljU4K8tQmlG33G88gpy57yfEjbmWdg5SuiM/1LzjaQHHxHsFxBRP/
+8U6tYoAIGKaMLFRbu09YozlQDaqBNilJe3cqcdgM6Hk64vNQqoqnHqC+fEmSxTMh
+SYKPOXHbLOrNg21kBtZQih49UN4NbwJUtrEEvhI7nT1VCyFER5d+eYuDuEzg/n83
+3FTeasFmgSDQ5bBq/oajGi6RY8UCRKs1M3Dtz1mcy+vrM0drj3KCAvHcuAU3iHEp
+eqSC0ZREJc2U7Cx/jChkjLaqggLCXjlYTkB3Ejpgb1wa1syEfraQNwbp8Ru2RnL1
+rR9MTzme0mZouDfs2AVRvqjWTMIcled98P3CZ6m0+r8n4YHfYWY4BZxKmKqVERua
+4eO6bP8cQKX008B5AKl6REnODiWSeXFmZNpenvjriZoAncCozwjXbDWg4x7GFO5H
+UFT6aGLat/pX+BhdjzRFFWikAMRjL+cuYCfhkWCCKRW3hbgeT0K/W6+e3h9IRONi
+bJ5gp2hyW3T+OgzBsldZgnVSMfDoc7dOVzH7Sdo5S/MMb5RCe6EX/oVcUwO4E5eA
+b2s24kOech8QpvDSgVVqt889RqyYeALlzjHKKshSMs+ydSx0ukv1rG3Oisjgfqj+
+liDZCfwaDZy1V1FZvBdqZsQEs1cWxb39JwzoShC+W1DQwLOoQyesXz4xFbgSMK9J
+vYue3oj1wMxiGyUhf8KYIu3UYCKuOqnFBoLCxOmhI8GABloGfa5/aLMjd5JWBIn7
+JB4l+NbD+Umj0ZGISH4/et4P1x/j6wpljzAzIb6QaDHjqMOe09owdH5m1hZ4/ybQ
+T84P1qsUKKw2GDR/+e5CVcoYioSkJsmQDYNT9Q2s+gGBQg55G4JgK7CCEYsBCrNr
+sFYg3dJJIOqqRucwB9Ghf2UijPbj0O1SH0z7tpCuw2QQmjk3UMkWxslJQE7oi1Nf
+ApEhiNhGxNbr6TRYXBd8Ao8O4ZZcbgWnHVRWW9IXNYBX4VWsJMDjRnC9rWnyLakd
+xSoH2Au0/F14hrTm9uELPOwm4sshm/tpoGj1UfK/eG9WPFN6aHOJMqNmmOyH9Oj+
+YziswpuHRa6s3fAsawCjBfAZ8K51QLIXWmjMMWLpoYjaiP2kSwJmvvidRb50DKUN
+gMH9ssDZTLSNf2gKFgt7AClZv/u509VX7DBrC9aXecLzfOekLJraFpxw4tUioszG
+Xp5+ePIvD0PCw/poO9e0IJmzncvvBYmFIJM2m0GsD3QitwPF4aqWnViLiMfFE4Sw
+UP7vY9gOD/mv0qnpfUx5aBl5ZXlMsOJjOq0MKpp22OtpEAO+2UtKPHdhHAm6e1mm
+jy9fvzyFUtOwHL2T6m1bcAMKJ8cpow+y3S8/tyl3rFSE0H2NTdb4NIVqbqsVoHxS
+J7VS/6QY6Pw/8sEcuAXa6U23LFeJKNgVlzXU+46gs1DEOJBhtxmOjTSoAugmhWk1
+q58AUccS401V5a+LkjE/+ZguKw+v4YkfuNPh5upXVC1CEwTlEWRY7COIClftb3mU
+qci5/P5LSl9lI5hY8SZzUD+Oiur8QfYKTGdhqnwHVVz2ZWOSNh1YyQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCACert.pem
new file mode 100644
index 0000000000..af09d14be4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint0subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 6D 4C B5 58 FC DB 0B 9C 62 4A B0 DE 51 50 5B AF B5 3D 69 46
+ friendlyName: pathLenConstraint0 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint0 CA
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQwIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+UTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+ITAfBgNVBAMTGHBhdGhMZW5Db25zdHJhaW50MCBzdWJDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAK30/E10HSTUTxTe/EMYjXq+P+oyGA3ZxAEz6OhM
+uPKZnp0OGu7/kIPVhWkfbEa9J4wKrbbMmk3gqx/fvbo6/ZhWDkFq/fjLvjkCC8F7
+CFwXrLxGAoGd4EvdGIUyZ5zUeIRZYWYjlC8J32dDAQvbGx9/8j9lOG/3Vm0cHXz7
+kF6B9mHp7OHEm4URyAKM1Bn2QCbsRCqkOFxWLh6XbREdKFYWFRExN9dL9rwOZ3u1
+psGCpvAjXq9dw7vvmrSqJAPku2N+qx9NUysonIUNKLf3q3ynLLK91S5C8KeXoGWS
+ujGRF1gnvTNlPcEf8ESRg53XokYZ7FIrxPCmhtNwnAAV0a0CAwEAAaN8MHowHwYD
+VR0jBBgwFoAUmyuySjyQxW5QAckivWPOCfGMPfowHQYDVR0OBBYEFBRiZxB90jfF
+cgbQ3n+1Fh3Ko3NeMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFl
+AwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEALpjmzN+R
+TIzv5jQAMokgflELINf1b8eTeG3Fz9CvOZ68dGJIMr0Qigr2epEQ4/KW9mHXUgGn
+8GwXvnraoLiq6/LyFEW6PE9yl4lpotlxLmMnoEDDno5rfLWgKC2uygKXJrwCMAxE
+6pNO66V6Qi4nWwXpHBwnbeAVp137LuKp+Fw+SwmcqSFFIScifwSCS5kFokqPUM9l
+sYJZg2bUDj8cMGKYx/erl/LEZOT56lIcZBg0v5ablxB8XrDA1nx3QDONqd6qBjzU
+FFUqgJpu2CwiZLZ77VRfjuF889mp8SHnwi5tPglVZFBJ4t+72LfjXgM32a7rCwrE
+O1uFD6QiGDQAQw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6D 4C B5 58 FC DB 0B 9C 62 4A B0 DE 51 50 5B AF B5 3D 69 46
+ friendlyName: pathLenConstraint0 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,15EE4B43B0C84AC2
+
+nTud/GUep/vRr505cfJlU526WLJu6J37DfIdlQF8X6jpVWfjSxLh9GHtQtgSRFHQ
+hKqyI9CLiDVCZnJc26doAWBtbH3ZD43gp9vXb1cUzapt+fUQqUD1FyLweerMZlvJ
+1bMNQRMMPIw3YExnGgVFPMiFMzjZVs1frihsma9VrdOtx6F5VV+77RQjVM3Aqrjm
+TBAPpnPV+P9DsSkgb35dlqAePDnyRnQqHXnldoNdHFkTUVdlCp/uDtz4pKGgxlLu
+6H96vTu5yVgKGZBB7/kpqWNo7r9D1xVIo/V1RUzmf2KlIlSu8NYAb3r0Yw+A+CvI
+svrCYbs042YrN43tjx6/MnCarsERrExDlyeHTi2+0KAT8mrFlMIzsQ4IUGiWm9aa
+tbhgc3QUEMbfgxwQk4t7pGd5fi8+ylAsklnw9d3o7hlsCMEfhTEThB+6o6ICO0OI
+yOEQyvB+hDgs5eOekGx4xB21qzbGUc6JmjauWeQ4KOMO/YUceE57jNakoqCRkNZ3
++KCghHuNeUAkM8Z4DKpO5Xkh3PtJ8sg6Cy5qRUq6iMuhcjrqpRAsuI8QuNmSmgW/
+lSQZTqfR80iA6HJTtEYsQnTe1HVSAKvv6WYBAzU96ubCuD2MqZYP7kN+ObeoCbbD
+Peoz7yM3TKoM1KRUW13QslczXjIkecVgZlzWBRdTZMBdttMzvTsIp8TTRHEjc3zu
+qqwyMcWkkmHXko86NpStuSbiZV85/urDaAAOL/chWf9XLCo9CSo6XHsVtLC8W8js
+dFxURzelKqFg3pXYvhTE+6oHd1oTVPDy5DJyfkhf4thMrF+egAq+efdPTTRB17dQ
+eQiO7gxWeKLuKwg8jUQH1hTTKxHnjraAW8hhi9Qg3wM/5EbzFoVKjTvOoI2rlhyt
+FbJaZPD+gnr8uDjYouVxb+3lBnh3wiBlFmWtElG33kWup0MLJc/j1bgGsjOQkZY2
+smfzEJh0m9i5zrZXe6xX3copT6ZfeTB0Q3rHt8MEwMqTWO45i9HQVpmm/t2u7tcN
++hsyncQgWKN6N8r8De0wZD6PK3BDmau8nhoRnJS5MKsVZasFWK8+uRxYZiLtr+jS
+H8NNnahUEzovQtJzRh7B7XzvRrsbnH8UxmJmilHosg6L8hIouu3/Sb8X2zKmdsVQ
+hVq9+Hu8KsNQtJde5GccM07oJhRlkT1a/fJLgh+pV6eFLHCqt1Gww7VFoIVShpoF
+rGVIohlWG/CDlAWZZ8MNmjjr0K/T9P2Ya91PdL8Xvj5rctW0/qMsNJa4jlazn0cm
+Cg2DMccqrpJiQ9wirQBAiCouA7KugS7zNoXVKkKnCNEuJoRQqNjU9yOcaczk35sd
+lsh8IqeJ5BHVyyrpK/th0KQJMeNGMBLz4N5H/dXlsIe8nRcKWPUPmKL5Cf0saomI
+CKn8V3Q1nl12y0dV9RvHSnmu8BEWPEJYNZ0oGXeJgi4sA8iCRuxv/wpbFUiRQPuO
+kWrpmmN9HpoX2kl2eNaf6kotG0AWxefGf7y9xLSyC1UTBJa43D3zeC6fghmj+sAm
+//PCJ5yIJUgDHRoElFOXwq1B6gDuuzNODQCqBmiMSDycW42xyUsWWQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1CACert.pem
new file mode 100644
index 0000000000..a64bf26029
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C7 30 CB A8 FA DC B7 67 60 53 20 1F 28 36 2B E7 04 95 C3 6D
+ friendlyName: pathLenConstraint1 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBHDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAMT
+FXBhdGhMZW5Db25zdHJhaW50MSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMPMeBPiR7BFGHpvlxWNf9ogcUB61rzOlXR3ZzeDZsb+hslxASASvWVB
+nCbMGwoQyYVuCOLiWkTaZRxg+Xf7ZrdZUqu1MBNISS6xpjNsgk8SoDwRJtN/TZFo
+E2LpE90VAJRv0KBFrwT0CTAD24xCLF3y2zBLPX+lcjySi5HPshDckNHnARdxZ1B9
+m05bm4mDIqicBxFLqz33UZv9zNQ9E7UPike4HEdJ4vcio5eUtx0WPdeLXVw/zXfG
+qgDdRpSsEZPrSC7WkWigblGL+/5v3XpjuUL52ecX4egBKY18lL/Mi/7IGOrWE1/q
+4ucPM5lj2DVmGJ2PC8vWXyMdqjy27lMCAwEAAaN/MH0wHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFPPkcWD/FxTejSaFM34c/MFHZ/rB
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwEgYDVR0T
+AQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsFAAOCAQEANk4qiCIoQEqCO3v/6FaO
+StfIEVgimKiuVHCxSdRdvU/53ullYEWRonqoGRGh4LLj+oJO+JgWYmstphMNPgQ6
+edML21rMH8HYOsj/VuT1akNeyuXT9vwIusPP1UMSkmYu2YehIFzJijxZ0jitX8Xh
+qfkip9xpgQi/R9e8Ad1prvQyhZvFvxkNTXwU/V2oZvvAcBZhsH3dZteTLc5dl18K
+4wRO2kcU6NBww3W6JtvHIFHKvwihyUpZckc5CrmvAkNopP6DCF3nUW8V3OBrN0gr
+7g8Vrt7Tx0OkWNUyJ/uInPrpCYh4IrXAyd94UT5L3H1lj+tNYY+NdWeOhkYafjSr
+2A==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C7 30 CB A8 FA DC B7 67 60 53 20 1F 28 36 2B E7 04 95 C3 6D
+ friendlyName: pathLenConstraint1 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D09272A74C47A74F
+
+DU7n1+ZEMoTsX/iwSlvxElwPwswXLovRkKzF4XsqmkL7bIsFrDARDmCHOUhV6dJ4
+xl1hG0q4szx5kMnuJclVJNvwkBQxUwGMknNZM7oQxWkEj5xCeet8zhgdU0xuWQ6S
+rIfJ1H6QeNoLNSkEucwT+GCrhXrDtghzb5SZ5t7u6ozjJlUP+h+bKGGCA2J9Qr1S
+AfOqreZRFKxacvxoX4WFtLl4TGYdEi4Gb1Ou1BhT/OCEf8spfABJGZ+fmJq75TA6
+Gb97t204J5zdNOIxCVX+61K2l5YLyTLsj3yqehVoIkGd4CAAYy6Ua7wKARFdSIrR
+r/J0/32wQMG01/u/bz65CSiXWXWGLW0o8EPxZs18dYT7jk3KuLKkD5qDLYFnfL+e
+cnMDLt769aLZY8W/3sZkmuLLpE28ZN43+mtXKNl7APFkeIjsAmUt26zXKPTPGc1Y
+bAU85TKL5okI5opfNWAB4B36RkBBvB5RXv95KfkhTNj56w+su25l65vUwMouzOud
+Rw1csly0gLtOhovlo8r6Wd+qumhPFPDjTycttLKPsn5fJLtepKBOKe0XjS21AKjH
+8R2RMnSXyLSqlNr2UZaz3yPrtAmpW5L6o45Z2fRb/UKvez520EiH1+WEn/coLtdv
+70/+2npE4FDQBrYzSfjAYMTxfOJNV0BVLIl3TIKq4jeoyQC/ie9iFw8WKsvj325X
+cbl+4/W/K4KkqAYwt1BYcWL8UQiAZH33Ku0vxRNFKHodnx6ftby3p70IHB82fR9w
+wWvtaqYC5um+yrZsgFoGn+bqEGWuPuZAKkpITjKz270iPRLf4/HK1josL7fvuj3L
+3sP+SUrrLWcW+ZIFiISEz9i0SzAoRGefpom9XOEdssRNktq7nJj2fD1iTlOFGjF5
+AgaODEOFGFVD7DeIcdwqWo1axy3OMdjFl1gqzh6tZQIf4/0XyvHyrVHRSRJ3yTFP
+C1VyuunQOHaoYD60/ywFs65hTE1J46+/0RptUhyja8d4z8noquN0RCMX0gruFy0j
+tvB+FhWRAOiNLc0R3pwP3cDdc+mF3qIaJuRBIHIOirMrUGms44pDs7qAbeJ3QTiI
+o5v+vHbJbUFj0XoJIyuz9EhCs62j3NLz596XRQGUuX+lwM1duYxyz5ZA1/rrbHqs
+PF7OonEbFXeLwv3rr21iIEtA+jBYFoArDHtLolVamKDiHjJAP0HyzZ4ic+yqOLLy
+Yp2YfGRA619qm24MV5dwqxw17aVufAI144prkxo4Mxzr9Xluv+OLwQqfJ11weOh5
+Jm+IzH631NcSfiLNbrNTs8hr03p3fY6idAAM7fFha3zrfu6Pwx2OKOjn++G4uEM2
+zDjHsqx4pLoY1qYnPLyu2S0cTmXijsx8ce7T543EuPv3dify0aiN10Wm0FRB3wiV
+/m78qUydrkm6HQ4pp9OwxiAE0Z6xS7I9dxHhrkfpofyyqQWzvfjW96CMHXWHCJb2
+ME9TrGw4iYdvs6V9bfeA73nZfrGT1mY677wfBx7oKDjXD/pDu6zxfVpz87+UJQDm
+Y3I5KEi+6dnvq6CqbJ1F2S8w9JrWlmnSghv+T2oIIquvc9vBEuQBemYA8Wqwe2+M
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedCACert.pem
new file mode 100644
index 0000000000..fbda7aaa06
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 82 3B 7A 08 18 4D A2 78 C9 62 2B A1 FC D8 D9 6E 6D D1 F5 2C
+ friendlyName: pathLenConstraint1 Self-Issued CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 CA
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 CA
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+TjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+HjAcBgNVBAMTFXBhdGhMZW5Db25zdHJhaW50MSBDQTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBALt/+8RsBtPmiqfzvoksZfA2tnzXWqaI9We0vP+zCNAn
+g3iq7xtccZB1wczjSs90P07TGNAo0kgzvRW4Cr1H66e8lpd7pj4TJtkW1lnaKQAF
+DGvF3fhGFgfDUPhTeHfEpaeJ2IPB8WfuDfaCvUkmSXkLo18Q0CTzW6GHr6Cc35iH
+3njaGcppyCgxRI4Dxn8I3civKNhjV0I/x5A/KXBh+Zz6eDRZaQABZqHaPwo8Y6hm
+KaXyAp8HhiEphaGS709jloFQAbS82FZEtUVD9Arrd3a2+cSXfhCgBV79sOX0tTYK
+Wzmk9kRWiRD9TZFSepIKlwsployk2rD+V48YyQ2wg1ECAwEAAaN8MHowHwYDVR0j
+BBgwFoAU8+RxYP8XFN6NJoUzfhz8wUdn+sEwHQYDVR0OBBYEFDS9ZOOfjm6YJQDb
+ZTauNAiV650HMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIB
+MAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEATw49Gv/qJNHn
+DrsMkLN8NPb3Yk99ATawO+03jybiYqsrr2w+r2aJdRHC2dRoAZEpkQRceaSI1LpX
+gESU9z5kNpVYCC/kRtqmWPPGd7/zYfzRG5shGVtPkqDjyhc7J0PJdTqWKafDosVq
+rOhNJmpRr/u7wrD/oQHxHcjqXpcKW1BoZdJyCd74jQG/89gG7PoUcz1WYFSwnOh5
+uU2zMFbp5w1b7eXBRBZ5604dFrbCATLbdqSXDTYvCuoRGknWHbM2eSFcwlddEvKu
+Q26ZnAEbSmtoGCZhC1tQ9ymT0IxgFr/kEA+TbE8PwPbeVExckBmYVYSZ0YbOaDbv
+KzHycDsvVQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 82 3B 7A 08 18 4D A2 78 C9 62 2B A1 FC D8 D9 6E 6D D1 F5 2C
+ friendlyName: pathLenConstraint1 Self-Issued CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,CDF89CDD9EF4A5FC
+
+OVoq/PNs0UiHCs9KO5YOv3dquxzP6vCfMGDWmwAjvSIIOqmFipriTd4TNwPzr0m5
+GpxIOAGwWCrehvOfURdf+54joX8MnEeBWT4RgR4qvX/whNU4Z1NRm8+lNd/YIy81
+IqKDgdIW3r3x0HqIY+edk/90zvGo8a11T525oefzpcKnvm3D0KJYfXhAms7PAfPt
+zPQ1tZoNTMVX7oee+k+MSmISCKY/ohumJafQ0TjFzH0bq8nZx1YdncyS5mpY7TOp
+By1zh7VaVpAXXGRLK5Sl0YLcOTgobr/dR1G9Mqqma5e7rauZxq928ZDWJ7rsoDr/
+Q63vB3YQBio8sODpBXo18Kehk7lmhUlCeLIOQAefar9gxY+sV/ZD9HeLzdb45RVJ
+qxu5F83LGbdn0Vq/vrxMbEB7C13qT3GShUrxUz7VsVfVeNevMlb11Q93+5mnfv70
+gHH9Q8OfmvRBqLuiWdxtDKJoOIZ2sM7sCoFRf6kisNybNChZDP/vNGdM+L+ErJHD
+ftMCiQTy87xDdP11C8lQN27Bu6rRAZG9qUFbmhyUhiE7CUftjmsXGquCGnSHD38p
+yPrazytt43xF4sq8JMZBYspY0rkbzagaM52p1eOWFDHK1vOpC8ZuQJKHQG0ev/PQ
+f5fYa5BqRLPm9KbZfYKFUYEmHtMUTe7Pki8SKxjX8YVw5atl5aoudYmd03Egkr0a
+7BflAySllNviGoR5qn6lKNRdvNwL+TlKAh7UjQBmHMOBsllsSJETdqLQ03v1T619
++Fv5qMjqiNTEktG3jNYwgXKg4asuu6xHYSQJQHmIHb1qJhhgnelFFg9+cAEA6JxC
+7cv8Odybhol0gOV8oQjGY2yLeuYLHPYkPDXXyj9MUC/iAHxJk8cvUwZDQ1dK416+
+sN1kwnX5Hcxge+EWyTgCt3Da0+VIJo9bI2t2UB0T/Q5Z46ZR5y4dMnMYErZkTdGo
+MXUPL6BOY3SdhF/ppkZkteExWytpSOnHSugi1GspgaJMX+23v/hqMJLT3IBlITRT
+1atH1NEqFFvctTqKsOgK8gG7VDVlDnmoE3GElL/qeoGFYB5SOltprQpoH08P/jw/
+1dUxoEEzr5jzRONL5uGf1bVnckCdouTyf+auaZ+ugZOXG75xHfHn15PspuTG4DuU
+Qz9jRVoZt0BIfpdlcANVNZr+eiTToAsfkfrfc/hF7JSnMAtU7kwRVIGPaS7p0Yb+
+PPTroeukMU0jvY6Xxcwhb3QKIlOq4HCIb+awL7A32fCxT9D4t6+fpM3dUbPKV/PI
+o9PoKPMX/UC/xCNQ+1AeSEXVQBGdMMJReDW+bpmZX4Lcpd3DZ6ejtOTND1KH7AYn
+lGx265A6sPN+nTAtfcJVhNiTv+6VyO/j3vePvANhY4wImCHVxeLS44UYvO63lpsw
+l54B/OlU6ip/gz25ZtYI22IEyDWKPBMIhytC+cnKQ2VSGi4QAR1+0D/G58WTU9qt
+SD/GkJQY2LzntMTdDyfKpx3FzlInI2yb6fjV/pvDOetza+lrD1CaDMOh3DBBMrZv
+Hvm3dC1znnwalxZsjArQrvFEcFVMif/NLtwVcJ2xOCRSay2U3gv6Y3qUgogVMXZx
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedsubCACert.pem
new file mode 100644
index 0000000000..1e7b38fc27
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1SelfIssuedsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: A3 3E 09 15 BB 01 BE 01 A8 8C 89 EC 20 3F E6 4A 66 E1 D4 82
+ friendlyName: pathLenConstraint1 Self-Issued subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 subCA
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYcGF0aExl
+bkNvbnN0cmFpbnQxIHN1YkNBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFowUTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExITAfBgNVBAMTGHBhdGhMZW5Db25zdHJhaW50MSBzdWJDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKZG3pTPn+SJPMjCLTMtG2fYzkP+dDAXVAVI
+l3fw5wsUeCwNjyYOa0sWOGp2q6QrBgGhVUMi/IAw0y7YzE1BWOyf0zAxVKSjTNvi
+zm2sYeC7eH5J+Yf7c179F0SLa3GwuDf9z18z8gSa/mtqszclsDK7SqRQ+wC3cer/
+XHZ0KfiAhON7XLkhuFoInS1SlvYmy+KCSJ6898kqWLhx4KG5kty77HvnB4uUeCCK
+zhaIaTTK91r/R1LCGpeU6L6TB7O4wi+SI+tkmyIqy6MUOG7wEEgza8ACGOT6cEVF
+GcJyX7dzo0BJ9J+WcSdsK/Ugh9WIqyCSNA20sHFVOYq+qOWuanECAwEAAaN8MHow
+HwYDVR0jBBgwFoAU5ZmWtcd9VUKtgY7HJfYYzaydkHkwHQYDVR0OBBYEFHkDh1Mp
+Oh6+6NQY5QQ0gyudEcfWMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCG
+SAFlAwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEACZ+k
+jPBCnY1vtT62m30fHrzOBlIhF7BxGFRLElq+cz1caazoP1UwvI2U/NKzjtdjYIQU
+5KI1G99HmxQE1P3Lao0GK7SMi7PrfZke+ULWCa1/NviZgj1wZIecK+o930xlXemo
+xLYT5kyDEQTaKXLEmwWVZA4YZZybcrDrGYzjcYmhVVRId10zAHqos+Md2E8OHa1Y
+q1i0lpS/3DjkHhWmOOv99c4Bs5TwmW6IRNjYYdnPpL69XyeIaVheU2KXIxVxrdhp
+hLn4CRDQ6SeZl4zb3WzrBKLWcLJm4JM/OTGRb0LsV6Qba0StWp0995lGi+tqySuU
+slTcCndmiCcZady6vw==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A3 3E 09 15 BB 01 BE 01 A8 8C 89 EC 20 3F E6 4A 66 E1 D4 82
+ friendlyName: pathLenConstraint1 Self-Issued subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,50330B0885B8FD2D
+
+8Np7zgICHrdZR90w/givtroizFxRrkLepi5D6HGrPNhkl4sqTmwLLhgl0pQO7Y8P
+3XboKQhlKzmKT43bjxoVtY9IxDRgJvMvAc0Tt4Uw/16iYK2mv5M//8VxiKbwRbqy
+NeVYYPG7O8pGWO6FRAmjZ/J1pLxfRHzFbNZipFyl/Kt2/MhNL9JTrPETodC30/Nx
+Lxx7Hz1gBGXfOBXEUVq1ON7kBoIHeAEgG8jVrfgF1sH7APB9SLwNDEO7TMtGM33B
+0D3s3umJN4fWoSE73bQp+9o2L3wkPYGRjxInWEYrrkClWINvRwIiLsueIuzbdn8Y
+TqSsllbJyZ+VbjoVOiwrG4Ax0p00HLfYhibuXJqWAlV3WvCBTe3zTiuLiMqnf62u
+QeJhrRQ+3enJA0lTeFMX6fUm8T5nkvFcSulBhFAm3Q7JjYbg0fDmA7uXpDKQIIZv
+XDBxzX3QMH5KGHm2uAHx+1eLEpOJ5Tj5vCB3h91s0mMFpOyCAkBatiaKYgDo3AVr
+F2e78b2N9NQoDxMZUSN2310Pd2tIiCQJFdWwBZRS/LBv5sbgtsU45YYITRKH5Wxk
+sY5WqiCmijHHtVZq9rmbJJNbst9TV452bMsUKk9gbDvPOX/OeycXrlrDzEz/wlTi
+Y1t2X5ZbZTbfofMm+bw660Hrl/f3QvH2QLcL7FAu9bLcw8ToeSRcuNK/1HTKbmuP
+BW+gWRdiAlVUFUH3DnjMw2KvUVMDSqx5Z2i2YuoG7uLxY9E1PLMhA1eM8bzvFKCz
+elwyJg6/EsGioURgxdRg34PGTADUEIUxgtEbr0P8LjCQzYOxNtFV/8VbhbIJAqqy
+I5eKqkfIeRisoP7D/zCpcr5zUtzaMBr3XwrgNVzwgiedX4ytMidAJau2DGtDcqFK
+8khO235lVEf/1E0g35it+o/cVo1JCpAFQXvTjaGfN+9OCkSh9CIlF4X3Kq9njydv
+5Gt5uHkIOxnJ5v4n0HILLVmriO5hP7IG3LuhL+T3CRc7FhIfi24aZSj//kIUQxcO
+DDE0fyaGsaemmH85kkIkhVZx+TDBT3cROKG7CPc+tyzqhrZdga/O0+9hSKczs+K8
+KqAcbSTsp5PNCvxHEqWyBqUOnGdsZHb2qbnfOULa0908SKyBT7Kus76qATNY7DcA
+M5G5/dOQkD2oMkl0kHOl5LO+ByTZbOGikkyKvn4/B8GEOmj+5NIr4fs8T8e/8VH8
+Tker6YzzpLNoNvaok3WTkeQR8CnO1mzhqh3kgejOttaa1Tfv9+Ho28veIIXxJOYM
+WPdRbYVWUuZCuncl1wcn0ZZN2N+a1T9a+0d+OTZ/Fw+g5pED0YgZk/9NP6Lek3WZ
+y+HWHrrLBOPPUI6jddMQfUgk4j0OmIhgf0edgRkiTze/ZlRsi7a9JzYug/Q3BD8S
+jlyb1SzItMP1JVnqFFuBxChbUGgWFvEB0Bljq3o0n62ADNkk3VEYzmV57O1h6iFO
+SS5veeD/e5/IUq5v7VeLRa70MJ3HxygAQAvzWtimWlBiyR0navwXrdJsDNP8+To6
+CnYiJxqPh20m2lO18bES+b555yUPzgO2xvyZ9ZIjynvYelFg0CxXmjyHoidVV96v
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1subCACert.pem
new file mode 100644
index 0000000000..8c4fee3e5e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint1subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 45 C2 92 B2 42 06 35 4F A2 74 24 F4 E2 ED ED 1C 35 42 2B AD
+ friendlyName: pathLenConstraint1 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint1 CA
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQxIENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+UTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+ITAfBgNVBAMTGHBhdGhMZW5Db25zdHJhaW50MSBzdWJDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAL4T7DpvoO/ymsui7e6SJaKtxNET+dImelMFK7Ao
+PzGGaXiDHKbPPV82MQVEICaeDZ+CWe8+tCRGEttlf3xFplzOg7glM0itFpGWhe88
+OtUwj4hLG6TBqu1W2dJU3B+JghpHO67brDoO+AQxt2juJIknR2AwYwgr0MoylA8h
+TjSVd6aLsQfaRLdjGLEzbev7Ktj1LkRbykGx0FeoGiEbj/fW1Nl3RJGS9aeiQnPL
+FoxjNAQ9vDOMB+xEzLEVYZAHvXVvtYGxAHywrPYZbAvrmm2fty3sLN0g//uJvbOZ
+2EbL601Qu1MAp7yFhDFl7YcsQxQORkfx3gO/noeud5np1KsCAwEAAaN8MHowHwYD
+VR0jBBgwFoAUNL1k45+ObpglANtlNq40CJXrnQcwHQYDVR0OBBYEFOWZlrXHfVVC
+rYGOxyX2GM2snZB5MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFl
+AwIBMAEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAS0A82n0i
+4CFz8P1KHyyPaO4QK8v834S0An0Nx2G/zEcQM2SVYDjVKbls7mNN3KxtaMmv1fS0
+kfdPzYAvu7asEHTRaM2854OI+zBIOZw0l90/4cCxdf2eUCphmgKehy9CZ3BHEqVE
+iPJM3+/XAxlU2WuGWblNiHOFHKl5rXlkGSBscu4OV5NHay75q5nC/LVaMdugWSAe
+xOOHiLnV+H3Z+rx95aa5/uMn1TL+N+QY++cC/ug/vxlfOEeFhCWc8VhuqzGNtFlW
+Z1FR01Q6Rxs8xRnyOzZs57dTdSA1bDu1TnZYelrn7N5x+RlYixJA6M9fM/kweeDa
+WlQQJJGrznvK8g==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 45 C2 92 B2 42 06 35 4F A2 74 24 F4 E2 ED ED 1C 35 42 2B AD
+ friendlyName: pathLenConstraint1 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,720A13E00C693308
+
+iDD+bcmeaPqbuEEMzH04sORtTsOUqI+Khjd33vJEZxmP9yClJfYf9nmM1dOuUNCm
+Xtb854TzIsssbKbWdGfE6OrRjS+ivHRH6c+5SOYL1lVwbT9Nr30NNf1fUJYF6Ogq
+c+yeE5utte7a2xB3mhy0/VqsNogsiLqDte7auh0MIGFg0dACe7227UEDqLqKUPGW
+oLfc02cCdMDxuo7m5AxyDQIokcNRE7wiaX9cR1ReeyyY9oy7F5qWUYqA6jkhQNJZ
+sW3mscZWkWWtCuhiVY+r/tKqIGf0T/+s1PdBUlcK7cTVgECJygoC+LrYYSQuJ+Lp
+A4vtaXegDxgzNtXX2wCMESRIipTdXHhUJboKT/Z5O3y7WsLCb4YL8RZ/61y1qNAa
+a/177gG+iz/Cb3jOxYHZt16O4qvhQu1RVs1N7oexIcF9TIkZs5Z5IotwLRQb5aLH
+23lZ6TUkHBgyOLNvkGwmJBJQfFWL/dfST92ak02jnKTtkXm5ypEpg/Gn+ZpNSauP
+IIzBPoUgyWn3RCq4F9zYl7yU9tkOh8+JVq2pJSJ75RMd3hhoH2ivSS1zDsc5cPBg
+IFbq1Dg2T1BlzWQ1VhVePsEf8Al49lVcRTMa5TzrTH9wzpWZypxrmjr9PM9vKWvL
+9ukZrz/KgBGo9uLvo/sDMD9GdRjAJ4t8ACUHGdtC0ZGvnZjKAGNxyxNkEt5BqgQr
+3MkltlVZyQDIvr8XFMwlmbFzQI7H7XW8QQljkdRhYOHrcsbxlvo1o+PrSkb4XeUJ
+Mbu9NnS7ale2a2+YYDQfhoGuaaw1IrtQnsiW7Y1i2Pm8vDEtyRWFg9QvUD8mzLkR
+STL3thk5P2+q1/NlBI524aJ0A6vqpSCYFy677gbSkDaD+golnd8PZJe6s4bY8NnI
+wggSN71/7hWoAIvb+IW+zHQQ/i7KEg7NZ6y2DZfVTqCK81QJn5a2CNesGqEsxyD/
+6KkQ2mbZFoN92eAqwaqL40oNbrkp4BRqFKYhE0mEJHgjhlDQbglSrm8r4+HC2Cla
+oSQqlzGWSEvNHdY1lmhCd5qwcFB0T0dAbw0c3kr7tGwrnG53rdbvV9KrkpHfn+VO
+T+GpllfqWqlgsVSxv912c80rmGtTi4kTbQmF31hEgmIjVhtT+0Af1Ajf8vi5zrA1
+rWUAEfxmCPEgCkzBZKM5hZdOybAT1vMiLR7jft3MUxVPNmjnVOxBhFX0vo4t4bq0
+hXLRPdOVh84NfjXMu+hRf3XX81ltQHPBPNxoOtDWcPJwvGpyxucQYIYVbEpNW7AI
+MMR5AeMZkRzk9U0JYt9H8GMJhXSK3N3+Ijwul0cqS6b8nuWKpUjMWOiJkC7MiOdf
+UTJVN32LRfIz/LvYC7iI4lzSdBzSRWa3Tlxf2IGGEYWTPEnyAcH7/2E2nM0c80UT
+ElvBbX/KFyPow8yVG2JP6uS7P+hSWE6NRBlbet7x7+uG34mI/jIdNK7gYhKOAt7o
+XMNh7YizvwwKTYNs6cYZnUSYEvGySAm1NUZCTD6tc6N9UGIvF5QhsGYEmzacNqdw
+NMMf/Kbeko+TJUG0K+a8UJRGDOo7XhOq/fQTOqbYqKB9roxDBfp1GA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6CACert.pem
new file mode 100644
index 0000000000..e5e01a2385
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C3 6D BC BC AA 5F C1 9C E6 3E 47 A9 CD E7 BF 45 52 1E 95 35
+ friendlyName: pathLenConstraint6 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBGzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowTjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAMT
+FXBhdGhMZW5Db25zdHJhaW50NiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMhrG5ilLNK2JnW0V+GiT392lCKM4vUjPjAOxrg0mdIfK2AI1D9pgYUN
+h5jXFarP18NT65fkskd/NPPSbEePcEzi0ZjOBqnaUFS+tA425QiWkqdld/q+r4H/
+1ZF/f6Cz6CrguSUDNPT1a0cmv1t7dlLnae1UTP9HiVBLNCTfabBaTN95vzM3dyVR
+mcGYkT+ahiEgXDLYXuoWjqHjkz5Y8yd3+3TQ2IsyrmSN0NJCj4P/fC5sdpzFRDoB
+FYCXsCL0gXVUsvfzn/ds1BUqxcHw6O4UUadhBj+Khuleq0forX+77bxFhUnZkGo5
+iO+EZhvr6t32d7IG/MKfXt5nb25jypMCAwEAAaN/MH0wHwYDVR0jBBgwFoAU5H1f
+0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFK+8ha7+TK7hjZcjiMilsWALuk7Y
+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEwEgYDVR0T
+AQH/BAgwBgEB/wIBBjANBgkqhkiG9w0BAQsFAAOCAQEAMJCr70MBeik9uEqE4f27
+dR2O/kNaoqIOtzn+Y4PIzJGRspeGRjhkl4E+wafiPgHeyYCWIlO/R2E4BmI/ZNeD
+xQCHbIVzPDHeSI7DD6F9N/atZ/b3L3J4VnfU8gFdNq1wsGqf1hxHcvdpLXLTU0LX
+2j+th4jY/ogHv4kz3SHT7un1ktxQk2Rhb1u4PSBbQ6lI9oP4Jnda0jtakb1ZqhdZ
+8N/sJvsfEQuqxss/jp+j70dmIGH/bDJfxU1oG0xdyi1xP2qjqdrWHI/mEVlygfXi
+oxJ8JTfEcEHVsTffYR9fDUn0NylqCLdqFaDwLKqWl+C2inODNMpNusqleDAViw6B
+CA==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C3 6D BC BC AA 5F C1 9C E6 3E 47 A9 CD E7 BF 45 52 1E 95 35
+ friendlyName: pathLenConstraint6 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EB5F15F1B77A7EC6
+
+7I6S5ZvKPebxjsls94StH/51kmz2SIlFmdbnTSupmGJW+PpIWv6zZ7+TOXNp10+h
+YJsKVf8w33aezcZpoK48S96gL79Ws9rrk/dvbOIYOJedyVOrXNoAtKUO9SUH3wvo
+OVxNVVCMNoEtQRbv3IGGR+gM4zD6RCiIrYmjOAdI/yGh21iF8Ztd7TC0kG7vGdU/
+86H0rySvmouByxGiOY2ri5D6DZh+oU0KPVgc//efbA6ntDSQuhCTeTSYB9frRz6q
+H97ZEUNCcQdXMETx7KTpbrd6+OaQo1CpMOkfm7ve5ILSyAjIqmq3QBBTyyCKIlQy
+OAb7DCLF3X8zg3tv8wlmtogAEswE90KsSTXJTNSnkjH0X6/5jG0IJnqh9SMSWubo
+AKzuJq/xuW1hBupwdsPZG7sGTIYLWSDST7IGkDwV3mKFr0LzwB3ytTfl3M1fmu+n
+VxWv9WqojPhC2qHcV4R1Wbr/ZymlG/rtocfQWOsLEmp3kJizyWsFtNClym4lpi1k
+t7PKSWTrOFnhCjM1KLIkmH5uUl9mompsBL0ex7ztfgFSad6M0rQDNuaM7MEcDLd0
+eCM5qPoTcLwVJ0Mz65v4bntjv+NjTJIkCjxJiGJ5qjDikcEdqe/Ii9dy7EvCS1na
+juXXU/WmVr9+XFWKaUrV6yq1ZvuQSbNhttyXB4Y4ywZNUTaXVoeNseg2RHc2M/h7
+tmHxyrAZNCd7hP1OFZ8wGVUfCa6r6206Ifa281NMaaGKcjma3x1GYBubuhujrXFC
+Gn9PRDRlYDfkGQ47j2SxDQMoFHuq34vs46HpvITyg1v7WO9N0rRj1iWlk7fUr6jQ
+VCxO1x7HkfrEBcea8eRiwkxHnb0uPawemuDjei6axlkQkbefNgzSBeJR69XmiY6h
+vDeMHzsfCwL8wUVPowXOHCTsZ1l2GrJxClBWDMperBclmFS6GSnumamG6cSCV68f
+Fq6PR3jIRjeaZ6DsSTrMNawnWSFYgfiPbPaEmLJWjwiI+w3m9xUAlCquswVGcmbp
+L0vxByLO7onm8ZgzlsYtGI6zttmbOo1okiMrCQbNrcf6gJ+ujrh9phpOHezrhs7t
+Qut5bWCWlwMXvXhtGfZAZP0r53CVEtjVvRocOc5vQFbQlQgtyd89zpvKFmYfSsgC
+XPb0KTIBJuR/Y5ZcK1I7AVXmtomg5Zls36V+eUylWG0DPGqysYABKxfl6XP8qG+B
+jZ28rpEt2NF26wcN/fBpSK0fPQaPZwU95C531jsXxPbrF+eqt742aaXQFG/Vk7O+
+iHdm/wo1uK4tm6JlOMU7qv0UtuqBzTKnr9TBVcaBwSQiPI9xIOlKmmarfbdZ7uFE
+4E4r0qhVH5Q8tNBmUN2O+0zUlfj0jyz4AWYOF5JjLPecBMWJOq4dAAnm8xBBx8ED
+6b9vIgl7t0T1zQplTUO0r9VyUZQuIT0bP4mPu6cnbkaVUP+LgaaemK/3cj0fFf+W
+i8G5CgcRLzGk4B6VF92veMYk3Fhci+ASUjQaT4yAOSx+heSUQeiYBfG0vCa/f/E8
+IUfkTdYNY/todp9wNRzaDh4Wn1F3CiJR9CMzLiccNSe9uZ5TPszMcg+pFMQXVyIt
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA0Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA0Cert.pem
new file mode 100644
index 0000000000..5c2b861a06
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA0Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: C0 70 34 C0 9A 8D 1D 2E 2D D7 48 F4 47 47 6E 89 FC 22 A0 28
+ friendlyName: pathLenConstraint6 subCA0 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subCA0
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQ2IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+UjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+IjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50NiBzdWJDQTAwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDpgGQKv6ZtxqisbQnblDFKz1kj4LQRZTaRi6ly
+jkFMlb1h8OE3Q2m2uQd/HnayH57gKKvjvo5mdYe9AxjZtQKlnfvLvnEckt/2jx8f
+PnD1owh9WnFxPfKk5KXFe07v2S6PnDJB9KeD5gGrGGDBPFtnN81rJ6CgFuDmO1TY
+WPJVlZm+xK1OCPP5iPUT5DiyE6ouVLlHO6IONz4XgeMfjEa9J4Y3n5V2J0w4pUzV
+P/YZ+afXQY8r/Gh3Vyx0oKqdlYjDd60Ui8iw0SMd8DDyTaa9wW4LGDolYOjB7yna
+gW//Sxd/MZVwmcKmq03ZAlEIs4ew/+fBPYqMox4SFI7AWwzXAgMBAAGjfzB9MB8G
+A1UdIwQYMBaAFK+8ha7+TK7hjZcjiMilsWALuk7YMB0GA1UdDgQWBBTPdnaDc5Ak
+x42jbWd861LA1NTtSDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMBIGA1UdEwEB/wQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAEB/
+WsEKvQHARpddOd3k4ozzpgZ882UmNgb+9ILrMLhXnJUn6JWfSj2jSSmhDmiNqu3b
+lmzVVDBvVQqufpSIUK7/GB35AELTgoeOtepDANoRA1LJDJWc0gUbtKvgtfvAPPVu
+19CzmZrYLalyS+DMF6MWB8WfSrhtqdCKH7ndwNqBhW47mwO8OHAmpnGfCcvAbvMi
+UzrW7IoONO8dyPmUyLiscuiYzceI5S/ht3LbS/xHQeqFPslESirnsMrLKIFewqVv
+TG7ODfcxBGAT40Sa02WABO3qPzcVnDPqBuzWHXM7Z02JXOkzZqcjH9bYpmRhz1vU
+ZmqzIuGDS7/JLvKJekw=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: C0 70 34 C0 9A 8D 1D 2E 2D D7 48 F4 47 47 6E 89 FC 22 A0 28
+ friendlyName: pathLenConstraint6 subCA0 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FCFFF93C60567CEF
+
+jrP4Qz7OJDNU/aoROu+niRWYXpZyOPiye9vSxV8i4mTdagBX+O5ZG8Q+R24W3zkJ
+yKL1JVawZfxBbc0XgUhgan4TkI8664PxUIknFLvN86GT3O29USdOBHzCcrHVY8p+
+rzmc7gcZP5+jiSbQVHUhFfU9iqR2V/yN3xOX/mbTEsKT7/6lxgpdSiVaPxy3uWpU
+Sbj8FBGNPrgIotykbO0/itKLiJXiJchX6pFwzBXteqaouSqJ889u684/eW7rT2fC
+Z7r0ELGAVrc8TjbxPBzrH0eE8uXB3tNwYUz5ClLjJNJikyuZ6ZOKHaSSGCcGoVsA
+aghgsi9xiOMHjd/+jsOF+ZUvqLMfRc628e8ZGN8d6xuI6DwtKrXwTM2URZG4dFPJ
+Iy/2es+y3GaLFZZq006h1U7Ch7qmXdadNZXyrM/UzWDk0ZjfkfeBSswbpdjQkTnO
+pUFaWTRo29/BBZdyPk51OsGorv2P1AJxSwieMHUDbV7lV9gfwQtZWWQL2Axx+1TX
+CSYa8/fCdiODwt1lZZO7SW6nOvz/izTfTNixBhdiePNZcUPh0YwedBZ4A8Pt1LML
+WdPplOFc+IIzEhywJ2E3qJDfPEpX6URdzho4fultjyF/pDCIOO3KMSNVwQ8JOSsj
+AHRenjepoKMoHtCiIt5y4Uy01FbAHOMc8y7SGjhb76rEhv0Tnkm7NamnV7n7jG77
+Pl+2DDMpVLBIvMEddUTtZOihP1HJ1m3cWiy4fbM7M/t1sUO4sM58bz2iHVXnPRCc
+V93UP8A6XnTgB06SMeih+nYBkXZ5xoOYwH5u5dznr5+nOiAPXE6y6Cd4kOFKVSW/
+74jQTurdT1locsjLHbiEEDziy+0ECZXHeOv776bnffDVSREa2xtywhV/fXDQFdxr
+QxXMlx9OSz0MqDeXEwXXRbaWTWnYbhygPWHoAx/dTHJVOWEpj1SkjBAZXcZRC42i
+/AMLDjTw2/o1BssojTvEiedCdNx/Nw8lCQlog+NM4cu76ROgkZMN5od5KzIZMIr0
+TJQFvcNuLmW+Io2b3t0pzhtarMtfR76ThPILyec98ngWy4ckqydDVaKq1eeidh9Y
+UjYw9ZMJGghKQ0Y8xxOKR74pVOcmiiYM8lrsfLE3S2xCIpy49tL4W2S0JxaE6YUa
+Bt1OZLwZleQtA0Ppj2Zw2P2NR7LAyhGE0wAUxI6mGxhllpHaRfG8zX35g4a4TotO
+PeFoD1pAwjkIMSl/3365Uj7+imYRAmkliWtDfpQr6kd2RIjyA+rGire3AswsS0Z9
+a5fDpAPUtRwnrGa25b6cl/FejkBzD6/61bxoKzaiKWjKJmcgIGw8pqaW/AqHSxNI
+cHQk3pyTrmRJFnaIgX7oYIOd3N6fehNtX63uGNGK+n8Dnftht6ap+SbEzx3pWAz4
+c4tHllQiE1AH9IWKgq1VHn4/vtzjZldBqHq3MPb4XOQotK1ukhnX1aacPQaOYVHH
+x+Xle3A3Pa+TgSjav/jxJ/EqWt08AGU6/R/gKoUS51gwVY5KM3/1xMCHJBU6tGqn
+gwfrIMYybRxJQCTZpsRbMQLS2SXYS4eHF+g37wOBao5lBqQxfBs9pYK3bzhP40PT
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA1Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA1Cert.pem
new file mode 100644
index 0000000000..07cb933bfa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA1Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 46 BC E8 E1 06 A9 4F FD C8 F5 F2 A0 EC E7 60 57 02 F9 A1 07
+ friendlyName: pathLenConstraint6 subCA1 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subCA1
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQ2IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+UjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+IjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50NiBzdWJDQTEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDbl//xWkNw59SbDnUPP4oLjGtR0lPZ9ro0Y6WB
++VU5bQttT1STRTs4rE0dsO7uxCe4rgElYiE3RWkOX3NpjDoCjhAsZQw+qTR+RYBq
+rXSoNY80g6yKD+hw8Og99RL00sf0/vYlP0VYG38+cMILpZerHyIjyn04miEb3KA/
+VDh3iacw0W38bDi4vWkKM+vyzTu1bmwTK3e74GaeDQKoZFEP5dGFleHaEjf3TobK
+mXvEVAl2OmJcm64caInLsn5ZorVxYYizcsnwtIaAVP03UFq00tHIRzthDUe/Q+qP
+FXYesalAOV+65HnlVk3xVuhxc1/MtoUtMuaK13E0nl2h0CeBAgMBAAGjfzB9MB8G
+A1UdIwQYMBaAFK+8ha7+TK7hjZcjiMilsWALuk7YMB0GA1UdDgQWBBQ8mpWek15W
+YulbOJBsmjpuktv3CzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMBIGA1UdEwEB/wQIMAYBAf8CAQEwDQYJKoZIhvcNAQELBQADggEBAAEB
+tPnuRM2E44XP0QrA5YQhDrvV7pzhdEmo+7ZeaAlb4I6r5jAHpCcBjuI39tihVxqF
+ERPPrK1ZLjIt3q9ZIeih02rmWde/qqDgIGQJATl9pY2VpWX6kTu6vuZKw8eA9in2
+PB6y5lHGnMcb8oSyvAA2gH81HxQtS0SmILOPDr8LFJ+cmw3Wv6E8T8lDYCQyb/oN
+KCHGIY+Je3W9e+BPVyRLk9B7SbQC8dFC0zC/tkL6EImHXCP4vH5B0B2WysD7Yjav
+6KKJgWLa7l15/ZxcxuX17E5GZG3Vl9fIZf0qfaR6nZAMXPNLOQTSR2tS8ponmk3K
+7xxdRXaFL4msvMY7iP8=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 46 BC E8 E1 06 A9 4F FD C8 F5 F2 A0 EC E7 60 57 02 F9 A1 07
+ friendlyName: pathLenConstraint6 subCA1 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E3277D8DC8428604
+
+1KOZwzQYMSXVc4ZjSJQMkMqAYHNDlWmkrbChYpOwoiTKHo656wCmfUmj21fJVylW
+ntsQic7srUpTZ8JJEmZBwEnBsZs/bSITXjlzXCFR+nkxwlXi5FXiF+ujDLzRZqhk
+udKZZZskmo7v47u6Su1qDyYHM6SK5+jbxr92fUL+PngbUSpmQn5wYzn/Hwoc4CKF
+2DBXUBNUDN/xxsV/PhvArgEXNGpEnjIs0hC02OiElTHdvG+Fix59RM2Z8qQhTCYg
+HgaVBNhlASh2PFMMiwTzuREoXJgq6GA/kUtU+1cf4jUyENoXRzObx++3ON+BQQ+w
+iNMOcFnVQ+LjwDZKzPDGaq7bGzVFPZT8c1hiqFQ0MutWUqkcxeQp+L4wUF4ysVZA
+4Yx/f2M3fr+4K33qW6w3Y/PKMxPU+32m9bJLKaV/d1a2gixNys7pCKj7kx+STFO7
+J7E/Qptcmth90p1tTZtJ+DId7Hl+SMJDsKRR073Cv4qsu/gQsBeHicOpb13k/1Sa
+pPZLcswriUEG2apABluHBWiOQiU4eWcyqshSTd8XkZs2GyBDXHJrjpFG9KuGQo9/
+n3lmp93p7wWuJjW3JZhvL9bTDsMXFvdV+80OeL+5cKvX8BHmSmeJC4nwV3P5mJeM
+tO8jxYb/6dnq5SKikWK05UzvYvgoYWex/IWfucY5qTEjBkDYWKjbQjJC1mc6iyXO
+L/UUQ+v4A+ukxSjpcZ9oX5j+z3YPm1E/7Fy3gvljRM+QRNuYkfZeqZpxBkx1GDKZ
+lSBkRBG2seXugWyyX0mpuqA1piN4dNik5IoXk2I7RzwrE/b8RBlSWsREtQbNON3Z
+Ab2X/qc+TRpHYLcTHaeQxlCoIXx+3JFcuhug/XViWTN+EG9qfFwy3Fn2wtuhYdqT
+GJO+1Ffuv5FxBFJovHSCHw6nB0qDAYYNEEgm+12IY6zptZ0QA6WhKsLIkbvwAwJV
+wJ0MJ2AWxh+AOg/E8Vqktowo+s/mAmuZHW+CR1OWT/HTJqPXhm5UI07lOmlErjaD
+sr79iX4aPdF5rNAO54FWXt5MHXKzI5shefZc2Av2qJUsVBs/yLES7LS9zwtiEeBn
+7d8pr1GaU8zEWOUJpr5IobmkXU/gNOutBpAhgxrfdyn67WMsaNvXazBMQB1QPkzx
+hME5TOzSNHoqaJXH1PdbrR4a+1Cu47SBn9/orFjhV1YK+R3A7psN0McyaSFO6AgP
+1TOsJ8m0p9VxO0Ld5Io0e6FaG5pZKf2mnJqiC3n6F3fIyX7vjSab4D7eV4q6SGZx
+6AvhXzmhk9y38QqI+EwVXvF9L7qWOKmiCFaUnLa4PrXb4gvTml+I3mljB8y1frUI
+82D0hHwXxmcgV/PWkKUv4HnP5vXE1wpCjkSruHgBius9/ukXARUW1UgPsjMEMpHB
+0Hr6mcJ8KYtNvvnGEIwkNRepTEINuS9ZkUdE9d7Y9C5lgPSQ+hrnZ0WzpUmKKSuc
+QDRpPpGGSTOnvsuaDrJJVlSkvuo0gIkqLABF828UBwiWkQyRR7QuhvHgaK0qNTeZ
+Z8t6jxxaL1cX+Y2mDOC/3yioad+tHhCKczHNCMox2QB4/fgtzFaqZ9YqP1Dc7uju
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA4Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA4Cert.pem
new file mode 100644
index 0000000000..eca3bf0452
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subCA4Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 20 3F 1E 27 F5 D5 D8 B2 21 57 38 DA 36 07 E2 57 F8 6F 10 1F
+ friendlyName: pathLenConstraint6 subCA4 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subCA4
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 CA
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExl
+bkNvbnN0cmFpbnQ2IENBMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFow
+UjELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTEx
+IjAgBgNVBAMTGXBhdGhMZW5Db25zdHJhaW50NiBzdWJDQTQwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDRaciiXPE9CRnZszi4MJScusSJJBpnJRox4Dpn
+VJKE86q6HuEUtOzhllVlfQtaSGxhyWD8q8HpeGW7F2lqcblT0VbPyTPDF2DiPt6B
+yGYw2J9IMmkmdJ3RiXxouq336e1FTJoPCsgwHiK1bne2i4d6L5TFen8p6IFL2XR/
+lQyug93gOPysThsY14A2JJTNAISkJFtfEiHABPlsMtzST5OkazCJiIkGZw7+pId+
+jkWMoOc1C4nVTUEJJbyUVYTLEetaJVxU+3tVDr1vmTHXdYu4v6rWpX3IcmEMTM9m
+4HOqO1c92SWna0WvJLsPRm1y2/H+hhaGgvp83VrdXh/fdHrDAgMBAAGjfzB9MB8G
+A1UdIwQYMBaAFK+8ha7+TK7hjZcjiMilsWALuk7YMB0GA1UdDgQWBBRJhdtL+xFj
+2ZkCKLQLep4TF1oVdzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgB
+ZQMCATABMBIGA1UdEwEB/wQIMAYBAf8CAQQwDQYJKoZIhvcNAQELBQADggEBAJBm
+SQWFZgiXsoHVxU/Di8Vz/JG2sTHLr58iyp38gcp+7oM/SrRqdtFe3KoaRb1LBHhK
+Kwssx+5ukA/ZYIrKRTwv7IFUgdeQgsQDbNtAyxMkKwv2QFrtx1zaS0397wqZRGL2
+c4ph2EI7F0IzOmzuXuj3leZTiAA1z7m+WopfmN7RxPmFT/8ZouNCUnMxryjqEzm0
+k2vUuGzd7MLEGHlW2UVR4R/hfSOUTUBcUgC/F/aB07nCJ3Gon8ztvzRIAo7IQ1Vt
+okYWRHbFapAq5NsEn/Z/AxDGh9kJuSIx8/mz4hcdiKvfbQTztUPBVrq1RmF++rHR
+fwzHkZ48GGyTH5QbV8Y=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 20 3F 1E 27 F5 D5 D8 B2 21 57 38 DA 36 07 E2 57 F8 6F 10 1F
+ friendlyName: pathLenConstraint6 subCA4 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C5B1DBE38CC5F027
+
+xmAK7t4VqSNBgcZrMibK2lTme0BW6e65ASOjylAXAH4yMvgJGjEHRxj62gMZHHCp
+Cn/w4/PE2MfyZg4Ac9d0W+t3+8o0fJsa5rjfdSHWjZvK0hjx/0PgUplV9hqMYQ1K
+pOEZzAFPDiLb8t383RTUCKhsE0EyIxjcKdqFackk0s3RulEN5O9ehj/70IYbO9XA
+726FgHA3S1dZsxekTkrpTmC1T6Nxw4tWYWR+2x5Vx2BesQIsBvQF41nB55y+l0MG
+tYA4lFJ/qSlMqT0nYBEOghRHt7hyT4Rz4DOC5AZXwlZ5JUsjgzAHEr3FE0cT/4kT
+rISxP7L7pL8L9Vusnm39bxrCiKNLFcqGrBhEi/lLzHQ9WMXc/i1GQicaqDLKlLkA
+gDZ4rBUMFuJThvfAteSLLPsYVWcGN4NMq/CRXj6+EgaGGuUy22rt9H4/n7O/xPsU
+kTleCyIGrgJozT01/OqSCisOXb362Ho+BcC4cxXI5mL9y2qzhlsO6KBjl76v6QK1
+Q2KH9qzvNwWXAWlQ93MLwAZ92W+z9vXr27qc/EPzrFObPrIjHVLJFs94FsgVXCSv
++Gf/vXQRWURnH95hmhIibseKJ5l/yyhIeUB9zyB+cg0ZZdkKJnNavNeSGWHm6TP3
+jnT4761Pg1DjyJN2Ce5Gh86P1KyaGhmxP3+RwZqGo1vRMqk9qEebAfmC5WqDBMVn
+pbQ2XT6dQUXmr7vsW8XCBi8ojlf4pS41Oq2ZMY/l+6FYYFw5KSz3IW7Rcjyj+FmE
+P0lOCIskE6UrcXrX/AtvJKWjgfDu9NUVENDV0ZXJ9xKqrWRD9PRIDEUeXc5YiZjJ
+v/i3iWcHeFK5Y35daW9T7QkTOivTmEsuE/ncR8ZrM76nYhcvb/Euo+CZ1kW42sUT
+c6Q+cVBm0BY2I8VTvxEAWTbytTvIV39xPg9eOqqNWomvDkocvZ5D9pe16YRMYhy/
+XIl+jdJ9qnmzGmLmVP1xWzN6CJx9i61JSBTdm6HZqr1EaTcVY0xz/6R1PsBJ/veP
+3vDMimT2Z0UkcmwrlWFsIzc/2JNNrmAgzLqUz8aED8EI5DsH2ixoWBxIyu8OY5I6
+o5Xk+AtaGFH79ktdVmCk9Bx8JlH3ngi3QvkV3pnLsFt7xm5NL8f983eMIEcW3xTG
+3MFpLXRMfIrX9IZJFeEEBiJQufxgkbeIblulY6Il8YFKvUyBK2rTjF/RV2NWL89X
+zx0pBV7IMk+eav0T4dIKHyCEn719lRawJujBdqfHIFR9XqQeriLNmvl1fwIAq9aV
+E4xKR9BlvkXd4MyFQWWGomI8aIHyHfb0DDQtlD8DTL3EZx11P1ihAiXWgtHjJv2t
+WQqxSsJrT7K4ZsuzZxvC3RBzCx1+w7rzoBjr+shgoKQa+DgQCIvYqx9yHenTfLJU
+b0mLn/NCc6V+NRvA8ismPZbXOFGi5edxmBRm9/AlLJwPrYv3nL+F5k74qWkhLDrG
+863JD1YNIvue1voJGK+RRXetZHPTK2BQW+N5dTn1ZQIGPM/pGMCXYiLjwABv4riQ
+Q+ayr702yMuJiDGDywb4PsNkpeiEvZWdEefGwbRj56EHzIhwqd/GB4goGWo+v0ve
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA00Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA00Cert.pem
new file mode 100644
index 0000000000..062578b2b8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA00Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 2F BE 8A 79 66 E8 F2 34 7F 81 93 45 80 67 28 47 99 3C 8D 41
+ friendlyName: pathLenConstraint6 subsubCA00 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA00
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subCA0
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YkNBMDAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFYxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSYwJAYDVQQDEx1wYXRoTGVuQ29uc3RyYWludDYgc3Vic3ViQ0EwMDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPzK+3Yt88gKSZVYm3rqWATIKudK
+erzo6+8OfKXCeLhqdyl7YQSXA49uFUCP3j41d6D51ntK6ngrxNY0HzGIO76aGbqB
+u1XCDdNUQGdL6j2IKBL1b3wWfbkFP7jQ4t57SKbtRVrJQUclQnPngCglKy9VSVME
+xpO9FfmPMJi9UV+zZ2VXD/6wfe6WG+bwkGDh935dJXi/pRJEYcT9ldL38He+fTmu
+pFatw7Z/qroGStY03BhsbNs5hGPk84ttMgf+HUcNWEKPrLmRzY0nmfAL3oRtfjNY
++V8N5BhcBHIXoiReaSUi68mkt7K//FzIOMa5F4tsyuiiElFMYebEV5M1pGcCAwEA
+AaN/MH0wHwYDVR0jBBgwFoAUz3Z2g3OQJMeNo21nfOtSwNTU7UgwHQYDVR0OBBYE
+FLq54oj31FkliuMp30+gBjjdcXSCMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsF
+AAOCAQEAQoo7imYucTJXFumY1aMqG9EQSloP/zLPTdL6XFi1tUFCebI/pNhDIHOO
+svVDSnenCEL2pf5V7obvFKBCb+IyaOQLC1JqV66Cti25xcyyVDKm0Bewd+ZydXYS
+YxhGkPEzqPCPJ0z3Z46vI2ObJU/+s37+u6EUSfX+V7uKcrQhR+9DwfL+x/5b+TKg
+l1kKIxaAw8hZGwOaAUdUTayCHPaxpGUFXqgfR52D2+fqIDFd59CwksvCUXx76qqW
+5JOBQu7UMyTMZsv+ZWg++JcSjKd9/FMBGtmPRnu+HB4+XQ+I5f6lSi62FUQQQ3JX
+MWTHU+R74FntihrR4lAAl5Qwh3N9pg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2F BE 8A 79 66 E8 F2 34 7F 81 93 45 80 67 28 47 99 3C 8D 41
+ friendlyName: pathLenConstraint6 subsubCA00 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4CF27B968169FE88
+
+1iw0oCkMr96HSqViN8KaY6SHsCNqFr/nlf7hWf9vRZ8pZPvxPaNyadQ9WPvJPFXa
+06rCaV9RV2cMMpejdkMYL+E8odYSBjYHE3u310YQWJdJLt72AO16TxTyjV/ZsFxD
+aCxGh5vW/kWIa1BD6mgWAUXPJQWihGmxqWitxXvNYb4RlltH5nCoSHHWR6lqD347
+aRANohrFqFp4488o7NbvzupGF6bPTK0CrRSFTpShq/Jmd3exwXOcJ9u9hL3/CPvt
+ybShcNvvSLO0m5uoP6j6ijP8AeQKivIdxt119AksjByDr9mclOdJM+B9Gia35iDN
+H7GcCbOeNYCacDDRJuSdJn22M+TXXVbpeexKV8hFUqLEpXmd+7kX7c/6zXqzIPLV
+T8Ko5nvxQ90POPWoIcNWGHq8CJEtA5ty8jiUorFze4hghtomdEPyG5HaLWEchLnV
+/FS8n8z8EABqpnXbDEp4Q2hMY+Nco9L6L+5cxI/pcylsMG5c5wpquf81Ff6IKEo8
+syTkdj07zsvih3gwxvDzlGff3s3cUi1L1BlBvl6n9mdhjbVH9P/TVJNhgXxTmjAH
+8eTi9rzVzzzGUOttMhjwsSinwd+qHIklT66tamIFlWqFPJLUUjw42uz5MxnpJkOS
+1AuJKVQo7XTljpVK4BnA4h/xIaoWH0gM0f+qhHLaqSe9rbU2dNNCciyDDi20AUBQ
+Y4Otk4mq45R77A2zYwZdsljahxeaRp6xZHboQ5W+sosHecAZ2+UDe19slmddn9rC
+eQLJt9Jf7uGLhimWep+X1Bn4vCdvdZeRZW8dKhu9NvlWOj79OzQjbxNLOQ3CiRZz
+fMtDnnKreXe2bYe42zop8FR9Kfri4dQVsTkkVtK+vtz3PVWHctJHQP59otqhDCK0
+pDp5XGKMcyDQ5pTXGJ6H6DAO5RqO6v/ZK0YD56cr6W1XGZHfibF5UI1AgXO6dfIj
+c9Al6gWaoLXdxDXjT36e/EJQydMyNBKRlFJ8uC87F8binvPwYkOzu8PxQ3DSMZ/V
+e45x7II+wmxyAvthLXPWBwbTZUUK1pnPxR8VKWdjuzvxqvZSfchsXTjyxhBwANtr
+gRIMiQofwbQFPosUu+3MGYJ3tjdH923RXY51/OJClnirerCk8LVX8aECWFbMtc82
+E7I4KrqZmex1ja3xzwfTn5bHoy5RssAQDCzvk0M7ia+C3IObK1j8WbXlJBwj0BL0
+lpWZOnYcvLQWXkvxg2D3DuQYUQKDGon79rrsOyXgWuaDSIXDzjE2BiM0VRXskHst
+vpGm9JwEpVpe/0kRvxiLpeG4cHwSWtA4U8cHkuucWuxrxZ85OMu5fnIJ+v29KcmK
+AGn1hEas0hBDIevBLEPtT+Z7NsCwUQn4sgE7foPwrcPHSWu6NlsSarAxAJReJZhi
+ktVGbV7QtSCm9QQeql0BpoCaWHaP5yeljfcIqQNX5ndzVOf4f2eMtl2G3lZXR5Wb
+v+OoxHZZxYwiSkBlmCffXgYTEeuzM2sDdEIuz4YtDyAN8SVc2ZpF7jwGFzY3uKQW
+Eobo7WjIsJ8RUKHp2nUNbi4pWgPmawaPIZW+KXsEKl5b2yATVZ1vWhRaOdqXyvOa
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA11Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA11Cert.pem
new file mode 100644
index 0000000000..c0453fc232
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA11Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D8 2E E7 D9 03 4B 28 64 6A 5F 09 89 7D E4 9B 4D F6 2C E9 4C
+ friendlyName: pathLenConstraint6 subsubCA11 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA11
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subCA1
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YkNBMTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFYxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSYwJAYDVQQDEx1wYXRoTGVuQ29uc3RyYWludDYgc3Vic3ViQ0ExMTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALuN/uaJp/PshJKQyBN2TWolI/yk
+GtUvS8cQoBUZUR7ahtG31S8sD48vf3s5ggkb3JfkLOQuwxwzfiYRZxVLxHyNbQEY
+TUrZIoPj0+SqdDb9JCXkuCU94akI1d0xqf7M7MO0CHVZ3fcOp9qNTwm/gBdnep+x
+pMh+g6nn73ufozCGzrnLaQp3wzWK/D4V6WjuDQMgnEjlAhxs2euUsg13HbElCSqf
+r8Mx8bbhHdvzV5yMPVTH8mXYt/xv8YCN/ek78q+i1VI4yUw2AdB1IMwvXDnYNQJb
+fi5ucRIthUmBwPlf7zaEHjAsNieSQL8+SdI6vOA4WUH2tNHIIvTHn5GqItECAwEA
+AaN/MH0wHwYDVR0jBBgwFoAUPJqVnpNeVmLpWziQbJo6bpLb9wswHQYDVR0OBBYE
+FNOmRV4CnWcWfZSAD3O5hMZbtTG+MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsF
+AAOCAQEAT4bn1Lcr9UM45OpPECn9R4qREuYB4mAdo/NHNvnXQWoe/g3ao5y1R0OZ
+t5aAw5Ri3ghemIraBIadgiWEpbYR1MVoR6Vx+yTLH1nq5yGKoLJ+fsEPmNwTc94O
+Lhdu94B/gB/sy1vfq+/lnmScXMqWjE5+0kEE6BhNEJm5ep4r31/nv0oijTwLEWXn
+VnAF/NmOWgm7+hOMVkzXTqJVY/Ep1r7QJHa65hB2+UhkzuNryOK/57CBZQbO8+qM
+GVEymCQ858dkmH8JSpScryYdXQZb74Owx0z+zB/yiy2arubmocOwtBJIVpAv9DeV
+HyK/COG7N0jwe98VneVl/KstdYTrDQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D8 2E E7 D9 03 4B 28 64 6A 5F 09 89 7D E4 9B 4D F6 2C E9 4C
+ friendlyName: pathLenConstraint6 subsubCA11 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5DA38B49F7680467
+
+vCNi7mFrSPZxDYmL8Qfjvy7bxyx0TkWqZO0nWdNAxKnSDjsXS5+D8awQ/ZNmj74N
++SLBFJE2pB7fp6uT4Z2WXHIbG61bARd3qmkXkXBtMhFU1nOy7rJ4iALsvJAqbKJg
+VBosdvZDMlHT64eOqfucVJVpPtJoKKGim3d496c8iUgWsYQVLpu5h+ifTfuRO+/l
+ARIbpprGsjjhKkUiAe44AuG3z7WZqe4jy7iVTqew2GBULUUkkYOAtYGRnDf5/SjY
+dfxTHAh/uvNSg82aacIqD8JO6eKX3c0uFSyAA4Oty/4Hr39R4F5cfXQMgnPmhAQg
+UdMBIlsa79eWU/2D6AxlkgmfmnF0VgGJRSkfiBvQ7nJX+AlQ8amZ+oCt7mGRyOEk
+BjwzwLufkj6xof6V/o/ZM1McqOTGhLNL9zz9+Qq6WNJhIznniNEUKNOxCJZnHk9D
++k3eoIACfXXCjMVSxndpjZ3l+xM+nY3ei8jXdLp7vYoaWs1UtXT7U+L6qyE+LVhx
+mh7DyCkkX9IfKQqcZWgTN4Bm6KHN8OLu8l8hv4McTfylwK2JB7S3YZrrx9Kc0R0y
+itw+l1zwAUvck9aZ4AOO2vqA+HErBQBKtpNBoB7DMjrwc/22tJd5HmKDPAqqtuqb
+NZhkYD2dnFvb07fV3t7DfpIs4cdewtoebvikGX8oHJTx0tv40BkAPRPtf3VcnShh
+gRRatGDcRrs+TFVHdY7r0JFh+TWkHStVrv4UyzlGAwQ7lVnt0r6zaGRZSB2CZ3jA
+u30RVtvnu2aEMg824rdHpEtfW+dKgE8l0L0jjRMEb8UYsUjYxKT+10C52RN2FpwW
+PjSI8VZeJHK2LlFNbtDO7cUNK4hrRY1Ic3qU3jkm+bBVutrbe+SQjswH0F2435j/
+slO8LTxRqY8VZ4ueEa8Ofp3TdWLG7CTq0NF2UlEqBldB+Hg5GP5JzAX3IjSoTgyn
+aUO+rcygsfWKh4cBaHo8Le7aJjFlLLcvXMIsOqGvnIzG3tMlmvK58qDIlo/2ilLR
+3DwC/nXBKTfelDyO4wgNiQvc4gCsLQ6a1CizT2ulTmBmQUbFk5m6mYJF0tkyZAX9
+mMMxKrCYjU6PvY+OEiAN1W4UpVJE8Pr6MFBD11Z/H7NCGATJS71xWqYR8LVuaF1g
+YZvf9vZL3YleBNmrlLxr68v2Z/Inco0lrMpyFws4JDYOHjuD1TJQKpjAmxxQXj/W
+MtjeDffrEKHudhA5jRrOP8ZB8hdWlox/iuu087mnJW8yWtIRvyNEusE2wvNtiMYk
+QBUuqaHSIagr3QtkQ+o3EesfzkDFl5oz8Z7ZWZ9n2vF510HwJKmqb40lgsEyywjT
+qbaVyHhySxHikPcO8cxHlpQKiBCHHdAZprq32qnk46q/n9rb3p+nMjZSWIF9/YwS
+QD38G1NyFgm0q269P9oQ2BGbILhCpblwYAflavrDqDdE4KvZGKaR00RJpC6diDeM
+h1xCBBz5Fwp6NOZ/e0jGHns71pZ/NboGSHkieQle30nw2o06brwrDTTXW5shIKaR
+jcmzH0wgsMNVORkM4p3Taq42UVugMjkTuXCMI3AygOYNn8a9Ib8sXLpivkLW8UCF
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA41Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA41Cert.pem
new file mode 100644
index 0000000000..dee3db33b0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubCA41Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 2A 6A 29 59 4D 9D 4D C2 33 FD DB 17 CD 49 47 F8 72 2C 92 CC
+ friendlyName: pathLenConstraint6 subsubCA41 Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA41
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subCA4
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YkNBNDAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFYxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSYwJAYDVQQDEx1wYXRoTGVuQ29uc3RyYWludDYgc3Vic3ViQ0E0MTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANhwD2w1qEqflNfYtpGLRSNwCAoE
+N7//EbgaFJKP4OGaerEZ41IHT4G8x0QOsx2RMRd6gXL9zNMmKhjoCL4Nv2mXksGt
+crt9dSJE2MaUIQFj/cdJv+WNwoQW8amBjeMSNL7BgB8y71fnO8srWabp6vkIgDr9
+tY0qmHZ1CLxB848d8C14NbaNGMeWJzI8ri2rXD/0sC/0LtWgg624DjmZWgxb7B8J
+w1ERSKznjFQ4vv9imV7vJ1GZ2r5V6nBPFnmtK2r2yqAeNReHE3U2syb9lpFyOsjh
+qTjVQdKUk5N+NAZpCipVuymCdvWcJY3C8FVmjxefqv/cJBu3Kxi7Bf6f1iMCAwEA
+AaN/MH0wHwYDVR0jBBgwFoAUSYXbS/sRY9mZAii0C3qeExdaFXcwHQYDVR0OBBYE
+FERapgfP9vPIx0bvZKH1W8E/grxXMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAO
+MAwGCmCGSAFlAwIBMAEwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsF
+AAOCAQEAtz+rkTNDpvnMjCDzmvVltiLfHURT3X/GipGokbedY89ANtS1dRmNFyDS
+I1Dh17v8HsW2GR40FCIP4ImbxvPrUAQIASOVUR7iLKwSj99RwK8+Tfd9cUBx5cdA
+nXm+KGqJ04sBKilEM6kGhA+vxZU8OJ7hck3rFVxNiIvGTZmYPlSLLQqv0X3LcWG9
+XArnZEKfNH6Ph0LCOzlPsLI3iQ5rHluq3liWMD21LBEftUdpJ0DqzEiWEFHL8PuD
+AtiGA+cOA0DTakpwjLnd2q1wM0S7HLVaYGSv6HErM594IUZQfWAyyyTpl3CERtH+
+mlou5h4IgFeitqocNlVfoAX5CzZsvQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 2A 6A 29 59 4D 9D 4D C2 33 FD DB 17 CD 49 47 F8 72 2C 92 CC
+ friendlyName: pathLenConstraint6 subsubCA41 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3E4218EFB3A645FB
+
+SlNl29wyvuhel9ar2aDtOEG+incCnQscatPX8whutk0o0/uhViDsxZqw1VrZPGYU
+VuYuplolpGLts9Ac42qpFO9C6TAMzBuuqvfkVVESrHrULSDooUaMmahSu2aptfEC
+7d1QFSh57X8UsnHmhpcyGHdVeu3ZU3gbRwg0ThIpMPTeA0Z/yjmXrBbe15o3d5hP
+y16cbMPfMQJ25lfmmLoe/belsqWBEVRcfcW1ZlUxEYcvocNgrN4sEI6XfWZw5CYc
+5005r3onPF01xPYDqhmGvDShwIpI1b2Xxd5RbAkTCS0e/QrDUDUt+jlYfWZN/osd
+QdMj6lFRGGoJkEhMjAOGza+ixuGjf4WlqjtWPItCrqtz8f0rixqQWFsU/xuqaqRR
++q0Bgw6H2sSGennKeyPuv6ONnKWbPZgOEdqNMmLp3rWY23g3RhHonHeB267YVCOX
+8FoPOJlBq2EpTefwUe9pwm94awWRMPhGeDDhpKubVkVPe0E9ghFkf264X1pkxAsy
+0LTatlTsXh4Hv8MexaaNZ87EQDat8Ehw6Z/LMNQVkrmQNyYa/LE9mEBMs7PEIvBp
+mGjlCo3aLzS7JSUB7QJwYS4KlkxyTIA36AS+YYEsTEvclYvdEVY8r/4NNHOV0Y+q
+eZLfm+KdseMBdfphUOjUj4dOM7vnqsgprwbLOD4lLQn104GCHt3FebphJ6Sd0PqV
+czd6ZPETM6U1/TFkxqqe1dhsHUA03hKCGFyKg8/mUjJyPajUtJmAOG0BYgJB58ZS
+QMNiQu+3qIJyimlGoUAKStS8zlfV4u1ZXx9Qd7eds1SGNX7ekgeL9XqN57lV9g93
+YKYx+s1izCMltq/IgLiBCow1PTcEcQhgqHADKaL44603I5cDKFp7DEeQ9Csq/4K8
+Vd57EAV8a/UEKLGpKnYTTBtG4StCbtpfZM1Z9YFrsXwLNslkPDIpeizkE/Es8IR3
+komhXk1qp0rH+0sZyohArLmdNrONyDAGOT1N3EVzeMKylKDsLZ3MSIneWx2CUQm1
+nB3yU0JFuiCrszmvP3ToBQLn6b8w0Hz7OIvgmRVUj/KiRoiS3QdgR696ijHjrVxA
+03HJER2tkGfxPG09va/cAzEGnotBOf7njyagxtMLho9UcNKRphHB8IXZE4KjO1Ci
+a1WKU0DVO0BxB0xyvaxBTa7DZe4nUNcABUB1NiHBda7V+44gpQ6QNjciCtEAaVPR
+YL4txJHYkQW3QoV5HY5B1O6XDODW9TNg+D5NLio326JU9rpOZuHQSgvHnrHKSN+q
+iAuE3Kv4TZL5uq35Z0HnhZSNaps12iGmtNJggCPe6cXvak5G+Gbww74L6/Pbx/RF
+Tzyo+q5Q6C4lrAZPwxc0uFFR40HdAvG8FI3eSP2AvDMjb9BjNKFGV6POnErNZjwP
+2IO8hmiEPZqD5X2W39KZmf9p9BT/mby4VtMTNHXCa2lDLVbQStaTTAS7JvTZK9sj
+h60ij3HmDnrn/oNb+Tj27RPP6WwfRwEG9Q6ckQUR4IxcTQtZJueY2NhAYzZECVsP
+fkqROcAMAgsglc+qIhmK+GRcXT8SH1RVC1MMOiIzYiamZI+I82Fonw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA11XCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA11XCert.pem
new file mode 100644
index 0000000000..d03f8732ea
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA11XCert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 88 94 18 7E AC 6F 72 8F FA 6B 91 D7 BB 94 C4 27 3B 68 12 30
+ friendlyName: pathLenConstraint6 subsubsubCA11X Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubsubCA11X
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA11
+-----BEGIN CERTIFICATE-----
+MIIDpzCCAo+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YkNBMTEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjBaMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExlbkNvbnN0cmFpbnQ2IHN1YnN1YnN1YkNB
+MTFYMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzo0UoNFGT352ywLD
+aKdwbykOrdmbb2i9KA1jFcqybAsbFggHUWmqEbSwqgepPtbWwmQBcMXHr5jGwgpl
+WL+3XK+e37NR3CwhhHu+ab/wQ+YQhzx2X9OmDiUqEd8trpLst7xhB2MbBDmh6F8P
+uKqc5bYgweh2rG9btTF3pNZCpAoB++xBfmWFgZ4smWnNh56Q8StmJRUbNyxSb48V
+NT+HD0WolgMTJiGy95UzAJreX7+vD93LtqgV7qQfB5IEo7QUe0L6bKBDnl0mKubv
+wFWMBjMBvkj8Vn+MBPpPbmt5K2xQcNNBoCCwziXkutnpt1bpOiBX3vfxaNQj5M0S
+rkdlwQIDAQABo3wwejAfBgNVHSMEGDAWgBTTpkVeAp1nFn2UgA9zuYTGW7UxvjAd
+BgNVHQ4EFgQUg9q4tcadyIsIfIs/7RpyJeKvG+owDgYDVR0PAQH/BAQDAgEGMBcG
+A1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBNi63ktdmqOjJ86RiHJKt46kPz3m6rDrPF3cVUh+gYeW6bYTKa
+2PbBbdPF90ENIZosUsg3dD1J7C+HR9oKqnG1YnghfKwhMej9z/PH+/GfepK+RADi
+b6Op6J1+zC1JCP2oLLMPcD/KKqptle5URd4u0tWM+tKodVijSkeKq6CfHtHErBcX
+uh0L8Q8PR3SWWmvYqfqDr0LGzl1D8hQp6EPUaQdxYFyNgiwcOz8p5pF70+ExnPMO
+Zw7nlBHN7QqtIegieCdwl/DJQCtfvxXYVGs2CW4af9p0ttM5lIDNXuoMRUd1rWTR
+vE63/I9pL52qh/9aX8GhBGuj4kP4E8OxgFo6
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 88 94 18 7E AC 6F 72 8F FA 6B 91 D7 BB 94 C4 27 3B 68 12 30
+ friendlyName: pathLenConstraint6 subsubsubCA11X Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,29E796E9158D0510
+
+rDtlnUNJqhCzyBZzrrQewQV/EZsv1x+tz86nXJDeXXBd3S2RqS2q9geIgsYerXZZ
+tWoMBgt5AKVOpkfFmfbTmVxYz6IlFDsi/hnjgwgucKwFCmc7V5M6endSuPO856/Y
+xA09QeKqcEAzgopW7mnavPoScfIpk4NYOpeiRDTvHTX2nMQbA69WMBka+FGqYV2l
+nW2bhEGSggl5A35R+iAj2AXXsDBy6x52ySYZ5VehnRq6T4lNxd4Wzk7TeHyYCpsr
+EpA6Ao451LawmLhbQS//H0D4L7b3Pn7XsA/d15UlMfqkvhuMLTcd7k3xH0MOxGZm
+0d9toet8DwrQ/v2WzIwsX++/e6jfKlZGa2RPZXvr5icF5JI/LSl3lNtI/GPQQNpy
+ZMOw5G21n9+2jUoOxDH+jA215JUDIwdRWf3KxsGMsMz1ROWG3QZWFYO/F7xb5FH1
+w4V7oqoJP0N6K84mShIzi3mm8e39BUGjLPGMoRGTeD37RRuQCmHv7avZ8SEKJh2R
+btaJhe0wD++34DTHFbz3Ea4qu2jgdf0VQF5TV/cIAVIlEbzBVvTWBBxdo7luypBe
+yTt0BG9+tE7A/UAy/Q7IXnobwZ4PfR52RVWLOTy/EpRSfbxC2TmXWFfrEs91Evb1
+b1rHIxWKRfK0wvdte0C6Wsy9WcFlqxDhwsYXMfAs0/Wa6/P3yLloRxUL/eus8N8W
+2pvF4hHTjq2VlytC6JW3heKY4SFtu87HgWw/5tnP28jRQPmpuvYsukoFFOjsq30I
+z9lmP5iRKHhMSnXOzBxW+XkW4J0gUeJ67zWJQK4QK4w4fgRm4DmO/GNGvltg9870
+HzkHrHx7j1EqUG3mxKB0A7cH55YfE/MO+4mTANnFjajTKoOBT8soI/9UZ9zy2C2C
+66c5a/L8nY1/D7rqSGLmAFaXiY5V6JrhqNG7Dslmj1gtS3TKian9JJ9OS5dvNrxF
+9Of1YAbea5dagQAfbAfG/FbStcdJiy0H1UEdQGynQLbLWOVFIoTztvehgLrOqssY
+vr4lds/EQK1rW5yaj7hIgDiFAAs0vmXC0kXmf4KtFHrESsEcKHh1dQOwpA70FsaC
+fa4eAKt+Uk6SP+WrbAuZNF101tmI++kbp9oYKR3xRjnMaSQEoAUv5xgtZmyIRHoK
+UtbBeoMhQRyuwmr52lv8f0Ztp6OKJBnk+lc+BZ+w/ydYm/s2UyAUMHdjQiAa4l6D
+ga0E1I634UvkrV3MpLvGt6Q2N8wffbAunMtlzZ8Mlp0mOlR1r0Nywplostseph/l
+QXp2GvZ3yvvPJ3wXbseXr9IGQiZEVi2j6qLECT1IJKMB/IUBAApLdbYA/wTRkVL1
+uV2PATkHIp7rVllX8mUtl5SO3tvqe9hzLZpI8Q8fUzOPRXGpNzYqW/HBPMLuEyhw
+fgZb1/wkchOd0d20CL9iQVkEyuJvNhjO6gbsm7dB0marreyQHP7Ho0TXMedBtByf
+oJRe7Did6d17H8d0/RYfm++nCeqlNMvS2nt+4T3trCC5T3m8jTrNGSamp3MgH7qc
+5L0OFqoDnBOYvZMnUFkPkjPy0XPRH9qXTxwEHSzaVMXmychMr5odvq1dQDBnKMub
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA41XCert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA41XCert.pem
new file mode 100644
index 0000000000..2e2402c8bc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pathLenConstraint6subsubsubCA41XCert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 84 F0 F2 97 13 11 CE 64 6E 27 A4 E0 AD A4 7C 01 48 5C CC 1C
+ friendlyName: pathLenConstraint6 subsubsubCA41X Cert
+subject=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubsubCA41X
+issuer=/C=US/O=Test Certificates 2011/CN=pathLenConstraint6 subsubCA41
+-----BEGIN CERTIFICATE-----
+MIIDpzCCAo+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExl
+bkNvbnN0cmFpbnQ2IHN1YnN1YkNBNDEwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjBaMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExlbkNvbnN0cmFpbnQ2IHN1YnN1YnN1YkNB
+NDFYMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6hM3qC08TT0qiiB1
+AXVRGB8La1zcPFASpIZ0T1pRmbvQVay8/l8gAcVytv6KVDgpjXjXXMjjJMuAZQm6
+ilT+eC3WrLSzBWUQDzAXTARzERVE3u4woJnBdpcyo4ZlTRGijwzYfbVlrdTNRnX1
+ET0R9BLIK4qxRYdJvlDXoCQQFb1/58RMs9jK7lxHetuVt1ieeWF/fLRPZ2Qbf/qm
+MpepaATXRf4Nue57jA3FyUAbvgVg2XnhRRdAEnsM90YRZHOD+XbB4Lhz2Pk6hNDM
+xfl70rGpDXIOh9UmIYZZ2yegRx/rKDI+3wFAtcGYek4trQGg/1HoTbaKszhIgb1s
+uJ0EUQIDAQABo3wwejAfBgNVHSMEGDAWgBREWqYHz/bzyMdG72Sh9VvBP4K8VzAd
+BgNVHQ4EFgQUoe2i8zVUpZ+8Y+ZHalMkbEoMciwwDgYDVR0PAQH/BAQDAgEGMBcG
+A1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBM/xztTxc6ooWAmhUfwjeTeHYxZFBCB81yMwM/agD4C3gTf+vl
+P1CnTaXFV2aoOYDiXCkA3oL4DViFQKHcuIh6ag5pKlxB38KCH5l87W+xb4NuuyhC
+/sYzP6PsQr43jiWtzbGRgQ8SFwN/+jX4MQnJE660ab09hgm3LmIkWCa3202nbwvR
+rL0ILpgkzQs+IgbJY9EAE2cGiapoZ8mjKBq4EwZG6xqjqp8LO2Al8Koa1ofFwnoz
+sYCgl+oyiP2lTkdMpg9p3gmmqWRnv0qWvfjwxnpH470rFWxL1u5nG1MM/Y2GLi5o
++poL/laW4KNTZOgEnijxlvBJiLfhb/mymaMZ
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 84 F0 F2 97 13 11 CE 64 6E 27 A4 E0 AD A4 7C 01 48 5C CC 1C
+ friendlyName: pathLenConstraint6 subsubsubCA41X Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2FE4FAA573336C14
+
+GLa99+FOa9l+sPDWoFbyBrbX/TtHNYIleUwj/cWNxb7jQU07+yk7mBUld0Bz5Rsf
+VuANrtMFAKMVIP6G4U7lDO33F89oDESmpm/NBcXorVklfaRoYAEpGmpFmPpYinUH
+L4zhMODI04VO6RbDLAUIKDrnjObW3Kz+u4It+0qE6cPWF6a2C0w2Qtnl+TX9yd4g
+vHrQUcXbNJ7FJIxPCVM6oVtEFA/YCaTxp2YIjls+6mM8raJAAeXr7mgTSRcMf0xl
+GHhq94Srx2LEN4U7x4vAzeGVcgt4Fc6Wl7S3GejQCJVCSlaqh1n5LObFL24hHW+W
+MNo4BF4Ie5+GvT8bNryXTfz6WS1/I5WpRBjncoJglKXLhKFkOyS+l+4hmh+RRN4H
+4GEgBQ0UjlNxRmycU9kS63A4rs2EJCpeaQkZbubrOyWQ21NmBmeGPAno+J8TfSUb
+UsHvS0DIbsQVc629/ROE+Mp+qkzNIITzgogT/GXbJMLj/ECJM6gZ46SXbUpoH/Zn
+F8QoqMm/nzY8jiF8HS/CmVi0fwd2zyqH5I8Igz5JN1i2Toq1AKJ1dhpJTij5vm2C
+m3EpwATFkjPD2WDrDlcCfvVwlGY2GJG3VHTvlF6E3+bkpZoqQ/LY4+xBj2DvxuQ6
+bQiSL0rcw7xvibsjdxTj0VRg1RBkGnZoUqEpA1uAbehFTLI1EkttvIDPWjtflfwY
+5d6c9HsAo4Ikcwwb897sPQ7SMK9OaXjg7v3D4QFMIMQVCN81xA149l8++SS2Az9T
+nxMswJ+pZp/+Gvs0D9bfAbN9dICVCkAlE4PUAPbvwt3Tb49hG7prCgs7pwedBa3b
+20f7PMEJ99WaOvZ+Dc0aFttyuS7hc2vuYdlG2Ah0QK8INk6cJI385ghp8mthdl7N
+nwGmMKux5y1rmB0JTRiKjYbVILiL0LwvU+leK2kiJSwjdBgmg1ucDDL69D+4/P76
+T+pmxcyyNqfqy2no1p5aELuOU1XMbeC5AnISqsBa9Gjuw6ApaapHZ0Q/KEXxPeRY
+lgJ307CUK9EGQOviLnFB5htGLMVYBbqPT8kp5m4gmTTD20baM4bjnHoR0vdTfzv4
+IgkMPGgsdEtyEcvAcEKK5uH6gWHcAe9DeOtBe6w2FMRNdsTytqa3oABb9wVK8/ZG
+wpP4EHh3NDm3NPHt5K2DSD8aUrXYnt0Yvt4KTSrytZ4ayFLz14WNXnKIGD1WqSJC
+8/3Gs5vs1m86sKo6qLyybI5Jxm04DZ4KiNxj4t9XN102D6wnJVEzDWXPLUqc3bio
+Ln2pncIaCX+5ACS/ETYiTHoxNzGXM1QdyCkBBeDKk31x1A2HF1KehYzAXltxvkzt
+1BzTEYx/lXSu+UJpoNw0l9c1dO+qQrEdCqVEEGc1MCmgY/aQgtX6Z0EguFvz8VwR
+UyWkXxwvndy/iFMhSSDc9ZbsBKGpXE5wdn6VcnSfhziOOB7/vtSgzaXSoWM7UZED
+xfbAp0/k0Sqwwk65cN4E2PUXKNuKtaMfh94QXnrhn/eYRjFmzZhfkiDkuBLN7f56
+MdevaFdEL6rFfOlFGI5LIISK1Nv+rWC/x1rZwVvRjcftRiKjD0tAdQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pre2000CRLnextUpdateCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pre2000CRLnextUpdateCACert.pem
new file mode 100644
index 0000000000..71c924fa42
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/pre2000CRLnextUpdateCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 6C D5 39 2E C2 D9 A8 61 5A 18 1A 13 BD D1 E2 C2 E7 60 8F 88
+ friendlyName: pre2000 CRL nextUpdate CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=pre2000 CRL nextUpdate CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIBDzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GXByZTIwMDAgQ1JMIG5leHRVcGRhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDJaKW914d9ICbgb9i5WTu9xNEgITtuLfHFOh1uuDHXbo48416O
+1x7Bcws68LzNGyZiWIvs9kokWB0vVNdKt76kJvMTOMZcPFH0o4dfYo5JUaBeSU8Y
++Nfjxlql6PKOYiTruu4reYLgxf1BaGCtH+GjYqYOYC3He8gqiD0xuAEFb2a2Fdo8
+m5eryPTYEHC81LjmDZPDRksJmsUXsCa63AKQaqEvnrXxT9MLGflkFilXCL66yFhJ
+19k0lucJo8oZQt4PIMS7TF3fPFYdk58c5eQc3TUwjm93ZYgvSNEOeISC6EE7avb7
+0DASh70CX1iy+uNX+gcGp6aoZ799UaqAFv0hAgMBAAGjfDB6MB8GA1UdIwQYMBaA
+FOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQeqEecYYBoKLFCmimM5igD
+KZIDzDAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJCSqna4iaOkoMr5x0YW
+TxgORJXV2/YMYG+loli/0m7bCp2A5WLp6YGifWXvdcxjcNwVnXZsT6RYJ3eGp7RJ
+oKiRncTMjrAhAVsVjgdy5U7uP7lEfAQfZ2nzMOzT8TVk7sjGmWXmm8OaiWxLoQll
+4eOdKsBLIJLweWdV7AZ0cpGCPwnXRq8mh4mabsAEl0cB85ZGydb3D+q9zv92HIHi
+LJm/mVEbn6EQV6f+XW7JKYjTJJ0nFeZb5j/0JFPy5+4lo+KXHXV+DkEIdMMPG66U
+99Co7Xtye7IkjOzXFLbRYbQJ+lALkq0BqAPCC2RCbZz8ZLaVoIjJU0XyuQ3O0YMY
+5Qo=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 6C D5 39 2E C2 D9 A8 61 5A 18 1A 13 BD D1 E2 C2 E7 60 8F 88
+ friendlyName: pre2000 CRL nextUpdate CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,48E785EC915176B0
+
+DvAWSul3RAjkEh00T/mI2uZoXGmFZ8KMSIpciqidBfizZNHtVCWpelmHH2bdq5c3
+LAyWePUZzeWglaag/cWzykPwgH0sPgeXPLwr/BtoAOPRgITVr1k1vHhShI7gjWuk
+Ya+3bMVvOF67fyeYNz19YjoSQ+fGMMCo/KyxYNPfth/w6F/kVoqqXrSt1k3na6AP
+HM7sELceaQzGl6JYZs4Q+1IRsA4sXpMO1FvxSem08vfjsrpHBhQvjcXPBP2GQpy4
+TANNZVVeed7uimomklEdJrsjqRtmvjGB4maaARVBBvLywouZqWPQXqjUr71kDTM0
+z6OfunsRH11DabCjwFaOkb1n5WYaVGETz+8BygIdHbhzzlkdtxIkKc9fUUlvcK+p
+YBxPbfn6u4tuOkhzauUTMMCzJXe3FWn0Q+3Ff7WAfnK44xD1eImGr39zjfDA1KVA
+YVpg6geqCZCX3pHRiygMWRVRiTu14fnlbvw2Tx25Irx6cJd/XvFVMOtAJzhKCEr4
+mPKENqhW734k45qISYegeeuL12sJGLyemHHPSrRLZxD1sbrFwJ6jO6rP2ph4At9b
+DmDaVPRZpHJUxW/XHN0UOIsbycDVdsxWz+QGYDaBbwNGyWBGj3Fe5CkeeQdIn4VK
+IJ5pixAvnBz8paPcN17u0jLf8gw4VkVxV9dQxKREFg+1A51M1ywWoPoj+FcLnx5X
+5LlCpw7r4j00dsEP/86VjhAffMP7j+DiIofRsrHiJKoHjY/tw+5JAzeD/mkiFEcy
+klr0N5nMdqq1EeoczljpNcS67eUx1s0VlVca4PSdkFI4Y/6AH0sHY3q8Alsnm7II
+zNqur3/XuwZgKcI6pYJrKrr076bU5GjSrjFDjkRcZODpTwfHMoWScOsof+15eLz2
+WbecSJE2l3pbB12x2UY/p9w73TAs+DO8DbHe9ARZ3P8TijFqm7M1olrbXwjmTMRY
+m2QLJ39muPsRNP3GpiXCuuCmb+tiq1zuhdUwVmckRf5uJCxqKIriKnqtPxL6qCS7
+1XGxSC98NthFXkQFxIiZHEs/TzrCqzhxE3kPR0k2A6AfgvHAcSOGGxGN87dtQbW9
+BnIJTwpmiT9CNJMeNGMFTKdEP3paZL21EFiwtu45TFWrlsOf1WVd4KoWmBmiIstp
+sb6KhWUx2konms1RoC0wtWv/JxXSptymCmqDyB7NhHe9YHz3YpCrfsqKw4JrOatO
+nkFVr2oyK0nC/2mbsugRJ2TjEv2ctXEKmPJ0tCVH3ZlK/qxsd8wu+AKdpThZtb7/
+deHf+LSgfimjzBk9/MnUYU61Y4InMv/cChfQwQdooJPT/sxPLcQYl5SEolNzaK4z
+rDa/HpTk0bbaK13RiZ1OR0tP2KfgKrIxKWdsH3WGSarxF7HTKsDQzdgZusIVuJDi
+NtQPhrOLIr1N181jF8Wj/dLr5FY8fGWwomQCgkIF0OAfnN/bzWHufifdb6nc0F+u
+UH/ah86lrkgoUxFiQjbyK1QKyW2gNJFmV0Uuk5aQWvnlK8Yn0Gg8cJ/EFTzl89pS
+LrofVKQT1YJJaH45PapT1E+DP9z42TZscvIivLwxjIJLZXdZJxMqat1mMYzXaIqU
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0CACert.pem
new file mode 100644
index 0000000000..4aaf206169
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 27 CD 61 20 C9 48 37 C4 8E 4B 48 31 C5 51 74 67 43 00 1E D3
+ friendlyName: requireExplicitPolicy0 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBLTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GXJlcXVpcmVFeHBsaWNpdFBvbGljeTAgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC9H7tvssdc/wduqx16T+W82qMWJRF190U8Ojp8YtO11D+dXuos
+YwW1s2g6HC9GuoMCVkS7H3VOx4D0T+oY/Gdt2vVKWFALPXlPkXYvcetrZeBucc+8
+oQHdgUeMKpFwagazoOeBZRbEKuz32amMQajto6RsdOKn8G/tCfvPWSiu+e9Wpr1A
+F8/F49mxKRrHo/8sLnHZEBYA4NIVy/KuXThzkYmfU1nfVejYjNPDC8rV67MtDvJX
+Q4KkbASnlX9zzaQuJbT8AeUeDMnYKbss9VcWTuukIk45PMAJvF9tnK3vlzPZcoI1
+wL8Xznd7XpwGDCjt9sjcfFG+P9gnnpe+oH3RAgMBAAGjgY4wgYswHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFLns37pSIri4vmr3ohLV
+JyDWZwQ1MA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgAEAMA0GCSqGSIb3DQEBCwUA
+A4IBAQBW5W0it/x9piqf4Ontkmv47v7kAheDZ3zVTavuaSyTR3X8zZjq2MRZ/GP1
+ukAIbYmtVA8ButPfrz98zK+JvgWhijro0lulYoB1weRwEVCCskRw1puGCwLcO5HH
+esqtSf25opakP+8orfdJ5oz3MNgIbV2eLrV8UBoIwqUlh9nJur1dLYY0EVWaLtl0
+vG3ZCzoJUdoQfidcBukQ1vs94fSeo86PUSmc3ly9R7e9bqmlYx3W8+UWWnNzj45c
+7kho7OxSoyZhcIP30Brq567uvhWftpHTThNdgsXLEMZ0sAtYz3RRTwJR926fij54
+sXrppFJp8OTTFV9u++k/u3qmGQJq
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 27 CD 61 20 C9 48 37 C4 8E 4B 48 31 C5 51 74 67 43 00 1E D3
+ friendlyName: requireExplicitPolicy0 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B129C23003C7DEB1
+
+DLhdq7VdbAjB0rZaaal3iA/ic6EcNiB3hXhnWinigTmeRLec8mtYZqiOkTDs3kSP
+g81WHfr+06hC8T3112FjVg4XhMjQIL6TnyP8WExWOZlbfNgaQtn1O/6/uPVPywi9
+gx0hipVnTLhfiTjD2HdvKs7nNxvwcGvHSMp1DQIZj4JVPA39RNVW5KncOCybA5tu
+1Up7+3lPfpO6it0+i/eib1QOU5hIIN+O0zPy7eiyxMWKFv0brqGKWeExB5gIc2BH
+Zlad8DWnYscxGOMUqM0OELBIDqH5Mgpsml689VzUae5AqfGLTHW60H0HY6owpiKF
+Kq2e8SfKWuGf+4hwnaMlHH31JQwO1vIJrF3tLdpcgZSicCC4sTKl45oc1lZXgYHA
+WdH8LhsHIZdcA68eEDJxHFxtD3Jvh2mtOyWwxTCv1PK6X69q+orzf6qjhbX1k1sl
+gNYudB3rJZLgQOkOX8jlyrFf88VFUgrE4Ti6Lr5JBG/nbrs3mpEkvgx4/cq6RVJP
+pi7gFY8+E+HXa0vn9qMSTgMq1uIWixHxRhTs4PPH2cn8D6qCnz5a1WFmlCWlznw9
+2wsGyhgjsUcUjjJEhXNBvdPDaqu3pon5wyT5wPng5UdX9eDhwi5ZMSjIeSbybdWh
+MXPPla0lsYS5/edG+rU8A/LS0dRuAM55b4qZ2uKMXA5H4pzMuIp9i70BPHiTtlTo
+QMzaK3xpfHWZOfbONyWN70tdyhDJI4YrtO1mpknBOJuHjxMhe67NYaxpS3FMwXuK
+sXfPmbCy5N5NxKuJG0rwFaHmqUDu/u1UQlr+6OQggZQ4mwKUENGGR72c1onFa6j9
+X90NTKsx1XnH9ho7wXLPp8q5I+wyfRkcGTREw6t0X7ZNE6wtUv983lZ+KK7I+8XF
+ggQkh/wZphlm01qx4XTnOSvjexgxDHHfFDO0APaonZsZ99pnfLadMhO5GN9YKMcY
+4jTQ8B9pty58CvJuSXxNRwnOwDpJSxQA6Z+SS5rn5GZELvXFea1h6dzVy6LNcYnn
+DqQayNbw94GF2YLTchYKCM50/BiT90wcR2qRJYgwKshWK2YrVyxgn4PDme5CST5p
+CfUiKfGlL77pojauzjeAttytFYhwocN9Ubc/X9FVVycrqUQjsviC4pZigGt5eeQq
+us7QaBsdcUStGa+rJnhAZ3uu3cWflYi5X/i3Rct/BlJBcTWTYLzKznZphStEn4OI
+Z5kObIqCLZEq52TZ7Bho90dX7c6efB+J81GyVY56D8LKJqI1IDcXAnrdHLrgv+eH
+BmyOBx9iS7XdNqUUfW//zvDd7OkbPclOntmU162JEBWXVPhODjg2uI9tAAnd+Fd6
+zIPqXFA4iD4yfawNGvucY5R9xuGiwV263GfDZg6ZYomSjfRXhyix/n9y5tDSIyeY
+IcyhHqK3ceu6LK0c1p/ChE+O3tyV/l9zLKjKC8/rD9ISbsGoMYm5dmHwsxRFi8aG
+ZxhXrMVzJuB5yqHLyLoVZ+JV0vXmQwh0amT//fpY13ymo9QUNl3aWVdV921QsI3J
+0dO1LjL4NVhysOaGu+IwJqk6EbDGMg9OAHlM1ZbNAunJfNKOEQCnbTd34p0ot8fp
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subCACert.pem
new file mode 100644
index 0000000000..5758443d07
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 98 9F E7 16 BC 53 67 43 9F 00 66 8E 0C 12 67 DC D8 B6 BC 91
+ friendlyName: requireExplicitPolicy0 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 CA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MCBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSUwIwYDVQQDExxyZXF1aXJlRXhwbGljaXRQb2xpY3kwIHN1YkNBMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1kJr6U09z+r8aR+1RvhIAo+D0AF2
+do7gCMyAhzT3z+LRHAdHqeOwpsUaTBcREVV2MsCoWAk2gsG6mkXzrpKWWboFM+0x
+V2HmWjDSb44HNYEwcnSQ8uW2eIZ/B2ZUEdnkODBvIToPEbvfubccCBz+zerRuShN
+yB/m6m/Hgx65/ZmLLlja62OdP8/Txk+q+NudnkgkWIFaoqF6PxPyZDf5rS6wFybi
+B2E3xETVhRSAVuKqJXiTIl+xQnc68/HaF00Oj6Ul2v3Xmy8pLdA+z+BMBLEgso88
+4CQCCw9DKWExeWOGTOGcsXGF2Ccxo+HjIpDtuy+NiyKBrCySjJWTMebUAwIDAQAB
+o3wwejAfBgNVHSMEGDAWgBS57N+6UiK4uL5q96IS1Scg1mcENTAdBgNVHQ4EFgQU
+vmJ4/Tu9bpwLM/I7MqpBCPPliVowDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
+AQC1SY78Ivlxwfun6e4Ru6ZfZbq41Jdn9WDMSO2BpepubxaXSDmGv0lGuvTDKAJK
+qNLUZ5GfGJP6inTx6iOxSPsn94vVT3YnlQNB3m2BW80MAL4G1Y+2IGid+DziABjl
+uuihKKe9gSbu5alh39RolvCP/PuUmXX53SJvn6rcM2ImnP80F73lccJno+on/zX8
+SvLqoGBA7jUO6XUJRN9ZweY7jpjQmJkRbArIHf8XUaEHDzFnn9job0siFYBfSbyE
+zDGOqpesAx/2enD3AHGdCQAfN6j68bojseeY+o2R/qKAyW6Q3tgloj33bo9xq4ku
+qNvqfPmXIIdT6aO4zpTrjJgy
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 98 9F E7 16 BC 53 67 43 9F 00 66 8E 0C 12 67 DC D8 B6 BC 91
+ friendlyName: requireExplicitPolicy0 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E7F5CD2A1E296188
+
+KCkDHzpCNib6KzyDil7+gKgxF4KnWDa3lOxEe+4gG5IFZ/Fl/agCSqAKg0efdIM8
+kCJrR5968l03QXhdk/WHMymOgpwVTope+eYpx9093fXQRfy4p15q5YDxH2Sufwbg
+kIbE5HR0RlWnOjHHG413ihmEMSxPM9uQK3UhrTHAss4Z3mDDgRMYjip04o9fCmiG
+ib9bJmp9uqCHraygD//Hnk2juKOI+/mjWLaEmOu8L6CCCjNdrk3bfwBxtgfgZOa2
+MBumLB7uSSA1tirzo5yulo/l6n2sCtdrL5AqYAhxIgPITGKTNwp31fcUScWYP6uO
+cbDYKzIbU0Z2GhVhCeQ4bP72uUYxPHDEVzwLKCUTL7QhddT4tmf1ZWqz9PGvjX48
+1C+9Hr7tdeqevewhbwn2nj/i7WhCBFFQCAcQJhMufro3PbM8SOxilCnl7ggp0WPH
+W3KJ+u55+mO8m0GsfaYmwpJW5bPliTlWhY+4XLDdYtK7bF5NfOng0sPmi/IjFo+0
+QauvRVgK7mZWGXjSVzsy0x6AYQqC7PfST6auoA3llSx6iteqwHnJBAgaJ6m4GyGW
+p1KMiyo41WCPS8EftRdD5sOQLNY3j7hGXZQV6XQRRBUeonpjwYdm8dtRlE9GNT8A
+B/Hjlm+qOdPRahMKT/vgRggFEXKwxRPYVrE5fJZvNxZ0pDTDJqIAN1yizduYrVbA
+PUUvAQzuYeAkZuYpTs4iZkfOy/fO4ZQLIWIs/OS9AW9EZU3y5qR0sK8hEimwgTPu
+karhYKs7PGy9Ni4n9Q2yFio/+RGgPGauH7FZZQiveuWG3tXLSMczNjEdOqgs+LPR
+ATwbbLuqA+btrqLt3Zru9ZPMsDEEUz88x6kvJ26IoArVelPOGBKeJoIIZZrDVdJv
+UUhJeXyRWhdD9duRY4z1JPKVYte2zsU8OQZZ7U60L3zVNXJict3BKtljSnzotqRc
+27ICOQWdrs0KVox3seJJte98xuzJ3KqBYFS9d9wO5oA2mcJYG4iG7v23XQvtnBnz
+EFNa8RdjsIzKqimqECedUfOAnU2EfYFx0YgGUTC9XnPkv++tAPuOgEql6cgleg4S
+qzaQYzEuaXp6PBjHkFfd/b9xMrXD/JeLBLlPY/qaxtJIZsIC1BFpeT0qz1uy8wBQ
+XwrerC/xM8pMJ0J+EOmf0B8XXeWZdM+3LMzlxRG79LXFjlCQEQak75ViWx6wXftK
+ZpCaG9q9oQq0Qnd7f7k40wT4Qou8B2QSVqwYKdxra/PVAUdR4xBnZ9jD0LYNpcAM
+9EN1Uo8G4tQl2nn0u/s2Sk4QpeCKgtz7R9q3pxRFNsQYgQTtVim+Eq0AhIjRz7Pe
+g2R30Kb0Yl3PhDS4Gpn8dlQZ0CP6nq4YDYb9APLbAK6vU7McsQbXDIr3MfuPReMc
+Ayfov+WSeGWy+XnMrLmWRpyuoJB7+89U79crqfMdC6T4alanOyB6Rqxprg9tuGUF
+cyHh+FOgRlRbXfdiAhPeBOVAdHAb22hC28PNMQKh6RBZhW3ygijuUQA0d7iEpwuQ
+woZOLc9S3/8B3kkc+wOxkWYNGVwSLzTu3VgbUm1LBG2LQSu5w5c70SBQee5Rbpd9
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubCACert.pem
new file mode 100644
index 0000000000..29620a143b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 86 5E 78 BF 57 E4 3C A7 B5 99 E0 8E 3F E6 8C 6F AC B8 55 E9
+ friendlyName: requireExplicitPolicy0 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 subCA
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWly
+ZUV4cGxpY2l0UG9saWN5MCBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSgwJgYDVQQDEx9yZXF1aXJlRXhwbGljaXRQb2xpY3kwIHN1YnN1YkNB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu2JoTDyKgPYRFw7WI1x0
+qDLxFwPdMWrqDNPO3IXgWvoxaJs9TTJ0Du0yU4WBqNRR6waqPeRLtXi95RVg60CG
+EEbY4j8nTVNGj0VUnDfF/ey1ZrIPpLh2HWE0UGAfYPX26sZ2Z+gN4A9KE7kRBgf0
+GfwwebdVRJq4yCncvmMqAevllCUonA45cn3W+wC9n5Ono4ooD4PJFJ8KRALImUXc
+xHFtvL4GEsCEHHXFrEGle18aQiApb1aFVl1USk59ILLs/IuFdf1J/pztbA9HGEsa
+w0yrlN2fXK/ZPZhyD/Bs5Wy8uH85iduCRgmRa/XENqccN7AxVp1NeE8OxW3rjEQ6
+VQIDAQABo3wwejAfBgNVHSMEGDAWgBS+Ynj9O71unAsz8jsyqkEI8+WJWjAdBgNV
+HQ4EFgQU69iXen96IzUZ5M+XJCcizGenVkkwDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQCVCnP34O7DI0X1maCMTT7+hJ1cLO2LvC5MlQK8q/V/BjKFc6G8VcCy
+SMRFEwgoMIctfF9lWLqFFGlAJPB1U6T1w80eFb3GCB9vLILx5rAZ0Zib963MzFZB
+/hxhpnmwAQLc08zmjtHQQKNiTOWKCriBfPvAMGbdWNej/rwnDSj9YpBBEYE9Z4AV
+EFUS6DTBCj4QHP4Sej0y3V/MJot1F18U7Q3UCGicrrTnQrtP9g+r2dfRruaNeoxc
+T6YmhEvBrdCwoAlBFpBZr0HAI4+iTMB4Qt007Tc9WG/zH3cdkKH5YsqRGIr37Ruq
+DG/m3mjqG+3WkRuj1ExY0LYkxxiMdCVR
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 86 5E 78 BF 57 E4 3C A7 B5 99 E0 8E 3F E6 8C 6F AC B8 55 E9
+ friendlyName: requireExplicitPolicy0 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,88080B693CA4CBCB
+
+eWTD85vvMoWI33pUfTY+58uSpi+fs7jkDxVrKD7mOW3rzPCep8h/lVv0neP0RNoh
+5lvzFkT/2V4HTzDneJfmE1ZUqThAQaqtZxWqkpPgzrVbD+bZvcCzzOb81ib3ERo2
+Zb79MoEPcvzNhSnX4K3A49/4qivghfBbp9NB8OGHJ/FKbjsWYPkQiqYU4JmxYL0d
+OrpfwAdWX1S5r/monH0E1Uv6ip5NHpr0kHzwfQxsD+pgubqnH200+wY3bRyrnDhv
+J4R5IjqzEup5xXGTBhN9rYoVF95cLn94YRkHxfE8kSmLew84IkG9REL8fiqbwr/S
+LD9+SK1DJpp5CBYVevA6lVQrW7bvFclbvOPQhJjxTTNBnOoUbaX96JMDNTH4mB3c
+C8blqAIqo5En//ZRD/PsjhTqQ4eUj437h9z5ePO7Itvqh+7HY80zHb4ShlhQxc0l
+PSxGk1aGtD8WscSfV+8EaEHiDF0DHyYVC5ZW8iBgmXHVuuVk40//ha7VSbH9SlJM
+lb4ZrhwHjAOvbiuNxp2O1iX7n1IVP2NycgUcO0YM33tQ4/ejsZd1QEjxeliTIUhC
+V+7bdXggH0KzJdvpDPyleKSELSwZMpd0fz1bNq4abDmwDlKlpoaBrO7+03VsVv+a
+HZYe96W7MNK/AnQm5ylm1wAP4NHkJjWARWENDS/24lGvUbVzYcdxttnxf0SLUiAO
+nvMCv8cnibQ4wXeY+CLivELdvtsusIKZ++d2MgWp4aNJgIdJygpNZQW69/xqQLre
+ldlkxQio8hYtTCY1MUifMag4uBUzxW9iiJuV2PD7Gu1TVV4xd/bGChZVMa9P+nHo
+u2eiY4pVtNhe9wr5I7nM+SwF6ivtBEH5KwC8H4tDT3nX5fH0+AuvlsfbWeRg7W1k
+cxs6ZMOR9bd9B2J7zUHptQNGP1suly0tMb/KbhM6igjSgnovVGBcdzpK6i6JrLzc
+TlQKg61SQMinRXZgkNYazV+vnkUIYv/rLUoQDlFMAlaijIyN6w5ksaE7KfonjAmx
+OHh2vonCSy2W4gErFY7zNeBVH/fE+JddAWJeoAr1+EzS580V4PhZ9R4LydRfv9o5
+eihAWj1aLUCeCdBNB1MazghBFNt38PbOy+hpzvFC6bG+PGPQAnxisHplO6q+P6co
+xknLYNqA6iFw7mUeCii9hHtj+FAF/cNmNClrK7SAmgA0W8TehLeoOKGoo0dA6/Xu
+DXZV0TDlbt2A8avuYP65daX+b9ghys8m2ETU6x+avlmuPZ5YSq269+y3/ePSwpQ7
+jBfVBRN5+aEM3cR7W4Mn/20PVVpt4gAIYrEAIPiz7sISsWZSLSu8IzCK8jcY8DlY
+L5O/QPZ2LFBJ1EliR32EXl7ubtwqa4VnEf9uoWnyooznyO7qydjPHJU1vTh1wz4T
+gUd4RNCGd7FW/pxS/F8RlItZvvQk5uVKvX6LjrxuHese3dW9JGSe9EUqxozhKRz1
+yudyxVG1rynKxPndL8bSkDikAfPrB/7tg5bzOrF2sAwxS61mkKc3Zd8TBoeOt34F
+L7GgwbWU9mWs/bw8l53HDVuAn2Fsf85xrPdyBRLXzNpMRfAmqs/zgutKLupZJtUP
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubsubCACert.pem
new file mode 100644
index 0000000000..9360d1dc11
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy0subsubsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: D2 01 8C 12 28 A9 C4 AC A2 4B A9 B5 EF DE C4 07 DC AB 48 2F
+ friendlyName: requireExplicitPolicy0 subsubsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 subsubsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy0 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MCBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMFsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMSswKQYDVQQDEyJyZXF1aXJlRXhwbGljaXRQb2xpY3kwIHN1YnN1
+YnN1YkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4d8UvN3QmBtB
+KQJSFClF134Wrv+NsPbS8dsXxeWIPKizD+8yDP53Rwdwr8k7q+Q2f3jZdXWovp/Z
+RILL+woH9SRbSNRpyDPtbrukl3hPaUO9UCtpeCqPETb5/zfJuw8JIqSG9Ab+atqa
+97bG7XzBTThsSNkfckHoDAc8i0U1HngPuLx9elndglmKtlfgKGqTagXLaWJbo0WM
+phT8BOBrmBohhIr7K+t08MyC72vCLZXD4dTkV/+fFuhHdKOP7XHNejLOdy8QVbC7
+kuSTPuCjI7a5EjtpSVwpXvpaooHdFIeOCiPjJg4xBP1NNJuqKG9Bkc+P+dMjdz+i
+JH4ybXFsIwIDAQABo3wwejAfBgNVHSMEGDAWgBTr2Jd6f3ojNRnkz5ckJyLMZ6dW
+STAdBgNVHQ4EFgQUtdsE1sggCC9aQcd4o0SJ2s4ua7owDgYDVR0PAQH/BAQDAgEG
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4IBAQA7RXTh5JOGumpqPXnJxJTJ0T99+mGke4EtCkyzmb1KvyKD
+gId0UwrUjENlGX20Jqt7/PhBcYS4xgx1kpQcRf/WJ8pzQbSH7SD7EFxySJ4d4zaj
+Zu9ITjJCEWw8qlWRP9lbQ5Hucs+X+W1kFSlWM3GgV3qcysDnNlcBoJfpNC6wehFy
+aSIBDY+SgT51bDZp/ANdKUSIjX1HUV6uRzCPQZYKkNAD4hS3X6as37Ap5WerP8Lf
+rZKkEtbFFB5TSJif31LTsxb5sYc2AtBjOBKvemBGzdmtjOs6MNRXvRdi/wwK3wJ5
+Y/y6tuaxlJtlUngvx7HLQxlZOvySQrq84uKZ3F7C
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: D2 01 8C 12 28 A9 C4 AC A2 4B A9 B5 EF DE C4 07 DC AB 48 2F
+ friendlyName: requireExplicitPolicy0 subsubsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F15CFEF31278A507
+
+aSZOe2dyS84zymKL3agADP47XYRnv5CrbiUhwyzE3k/blUEkzTp0VTOwulg8G6pK
+m6Ol1rgp8BpvnIcfvo9u+YhKYd2ziHhNjnOSzaGTAPRq+6s1cdRiH4dhrtzZpOR2
+AKcbk7XiH/uWSR4GLZUjWqGPU6nAd5OvrfVrBF9OiBpz1j/qx1Fy9O6J77DIy6/x
+jeJiH57KLV/RMJzyFELfLF/y1PfjPfxq2ojSAimn1XZKR44McELtn+KBdFEJo/5Q
+K5bPJy2lPdFfLyArqGmvOMyKUpirb04hTEEt20yoTJpIZhBcstyWNszwkiF9vso6
+Zxz6eTchgsiqaIHfKe0ezRDMX8cW1pdB5+2pW9QxUsUn3izIbIq5+KEl5oj+qZcV
+wNN2aX1NKs8eoT1lr4bOTAUaikJyoU4Z0wnUH7AjvW8ynA8jXvi2BC7921JM+6d/
+yzh3nblCQSKsuz6iJv6oWI0CHycc/69bjhsKt1aBdC2t5WFLwWdvhaPlUEBmJm22
+b1Ftez4eQ4w8531g/JA4oWK+Jgyb+Ys8ZJKJHe3NpjjOmCj95oWr7L7ZyUjrIh/I
+Q0Mq9NNrHb5XQSB/by82gNjaE4pBiOOxWBy+CaHgvh8THkZ1UGrPMTUKyY/BPNCT
+tlxj8E88z3kkQzfxqf95JE7JocUEmVou2x3RGKmooOg6KydAxqQFquGeFeb0eigY
+q7Asce2+XB+ilUTOaa8gQXXHDWyzhcDdfWlgmaAC9kZ/uzhEqonuoG0nyfE8V3ZL
+Zzn3j0cc2/LUA0CO4y+01zXxoakIAWBfsI514BH0Atg9l7CDFCPgy5moZmpopDD0
+6EKlAUF15KZiW4x4kLyVm7U8Yjkg+Q86HBqCb2rgas6YJiRbDMv2aQQl/33j/4cS
+TWPaDMmdmHMc4jZjGqmEVlkXQUgBdRoeC0SUVX+fIWrnKpZURJZfb9V7i8Q6VeFF
+TJfaAYz2ML5vQ782ZIKA3HfckgAxX7KaesfH05Q6VlahDv1mpJFNN4ZOmiZ7+0vw
+g+8AYmENCKS7MVuX+YFpIbZXDvYFpX7gYIpNa4ADE8VZLtngQyfOtIzBdgPOXUoJ
+M3JXJDkxWVHEfOLjnOklQK8HrfHOQFxU9Hd+KvYDRbIzsph/LPhYf9LcQ7cj8Mq0
+05nyb0DyNG+ZHe8wHBjiuevUxlG+LMJgqF37XucZmtocixcsl18aHq7Gifqto1iY
+dLPnmDezdlmVvz+Hoasj6qodEmN/A39fa2uDeG+9jTDddpbc+Cjz5ZNLLFQKEKAU
+LW08Ya0ZNV8njHdlB+3MmDzfDwBG4lBEj3Jm3Q9OMV9zoH2HNaUqnTOEXGz1EMGP
+4lGIVt+CKaX0SydSN2jVONPeLOq4R1F4DB8W7mcydJC2EvgUxdtd5m8yst+f8D1/
+46031OVwuLWP0KgIPX0Kmz2Jmm/V69grXG9J4OkZQYv/KfsWjdczalw1IzWU2nae
+Yqdl2fgz1jb7mJaeE7PtG8Oc50ewlzMbCQS0dCXqKv00mntEcc3pjIiYmIl+oVBq
+t+uzCkILkO35WQIEX9oebIQYS4CYyPZrx2IVr+VDVGUBFAF+fyT5tA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10CACert.pem
new file mode 100644
index 0000000000..20f0472cb5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: CD 39 F6 C7 73 B2 91 15 EA 44 84 98 D5 1B 56 9F 77 1F 34 73
+ friendlyName: requireExplicitPolicy10 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIBKjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUzELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAMT
+GnJlcXVpcmVFeHBsaWNpdFBvbGljeTEwIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA89pNhXn+jUxGpeJ1/h+iAlDoB5GdV8Do9wWsj8xwV6wx8QAi
+7MLPxjS9/zzCmmdvv9sa/tPZFYObbUaY8VDtQoksQKtW57OZgyAJTbUj1vV6VPDB
+U55xFOWaI/pesiO1+q1Xzxs5mZKVqChXQMIxzEYbN1opf+48tvsK4cOPLx/QQuEL
+E0q8nnoL8ePohm+8rTEtsWevzHz+PEywncSG+xu3SXC62gBm0Ij6v4178/CyTOho
+m2wXU7KAowokvvRx8ZqI2WS9Arir278fHzCsdjYeBCnybJyES+ldKZ5tvANLh8am
+C8loUhtoBW/HvAWFzOyEgucWqMmH0dUSiDLe1QIDAQABo4GOMIGLMB8GA1UdIwQY
+MBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBQZ80wE0V/VgEfz+DQs
+EYHkmM9rnzAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATAB
+MA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0kAQH/BAUwA4ABCjANBgkqhkiG9w0BAQsF
+AAOCAQEAi0krrdtrtcdh6y64lMi0WeCP4QILh7uXhceEtxyafJAKi0D/t2vQ55oN
+rAP+ZnIT0jOBBOE0cE6kyIcSa82rvNvjLR6fPqEhyXtE2i5dZbJBw847jP91UyBZ
+4QaA4jzJh/cz41U0GRv1dPf0SF/9WcsWKZnqumbZZ/NG7Zu1QJrF1+GU17rOWFUy
+CndBlxka3QVJSTzLxhXwbw52YiXvLJQm7mwF9OTuDU2ffZ5WKuOSA7rXumKNUAqD
+d/U6lvBwChFlr8sAqbXHcxh4ZqboOaTDxvBQ9rLrjKtcuA9N7udGFjZr/nEwqH+t
+vJgmuFX0Tkh9gH9AZax/zOWZivL0nQ==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: CD 39 F6 C7 73 B2 91 15 EA 44 84 98 D5 1B 56 9F 77 1F 34 73
+ friendlyName: requireExplicitPolicy10 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,64795C6B19211323
+
+27uUJ0FOOfIALApWq8b2aNDRoTK8tCfjZSpwRDwoeHpZZNFUw7ckVRtatn09aXu+
+oGWnIkC+WmCIlJH8CxN4VID99OVp95xVk8o2sutEfMO5chpNlaIZ+G0RBltQWWzQ
+sB3up5YEQMBMNYyqD5IdtakFjfa6MSB1LW0tGDmIPu15TBP9ZhxFxDLSfUzvCBco
+Mx4WKP6Cp+sTS5Vw914guOWQTl3nFVAmkv0QbGPjuhw0sR3mXAQw2H9iqf7nlW/l
+D0UTo/vRyIyqy6ri9gkLPGEFIVuOtT3gzZNv1n1mUX3JKtgBan3bvpiCuATbDke3
++p6ZSkkX219fNW6AtezPSBn+YNs796XGLOR7Z4ZwgqigekjBiNZ0T46NOqUr8XsE
++dHW9I67PnaJasb33muOfS7wNIB/RfPTkoCHgUaXqkp3BvQFivadNcOz2oNRGddo
+voRlDfrKrkbcsZTtvStn1nXz7211X31DiQr/Cct2RDeziy6m1DGMH0m6vF9TYmCV
+vH1Fvb3xbViLR1khQeJPiWUrAQG5nHPcm66RKwL1IdKdtTq8WzJyhu+FFGLncn/z
+yIm29dDg6XsLhyEAQMLj6GyVBsR6obMsSovYHP06uNGIpmIeBr/qlO7RZXZTJpn4
+kHJc2/aESWLzqJPQtV1RSgRlp1XJl8+8s9n8VuvcNBpVIoAGXf39mL3ysYQZGjuu
+Tk4I+WhI3XgcHm9mFf1D6ySjjT3TdDtRZucKAUv7RjpyINaJ2y8Qu6rOEuczx+ql
+hdW2cC06zlM/OmFgQaLxcrTyOLetZMLqPVbuf/ZXAKMRsjaIm9NUUA5+QQIYIu+Q
+MgRQ4l78Z9xWSdDiU1+FNsgzwCxSsZYe3mbLXQSxdGUG4WcElpMXL2w9m1DZNSp2
++3cl83yhI34OxzHgKLzP4vh2NliN7TBKGa7rCEgZbR6pjayZ4GCibDReqn/48Upg
+WR0amOzV7ZO4YemHgkL2LDLcNKW031F7DsOHubXql7j/G4gUcbRYrA+k6oX/rLa/
+YOv50xHKzFE9l7nqsbZXCt9jOmTudlTtDda64XSUN1J8dudgOcuQMa0QbVAoQVIY
+9P1wChyUXmcZNpyioRN0/Rk6JsCaCkFapokbG1b1ICy+y817rRlXOqJ3veNlwOmC
+axVUv0smGvxmTlLirfju3/sFFzdqNE44FNwU2pTFcZdekLLeuIXGvtg1gm8kXwIo
+UElpPiUSNDpGYLWW/P7qPYLIejh/sOtPbczL90+lf2YIZcD2QiYdCNWNc5xdFczi
+4ymcYtDrGT9kNjE+Um3vB8Km0aiEAQ6YTRli30dBSNJY/6TUh/EoZyA2rKFkRfuL
+XoKGpkG4PXs1byNppR7QkbTJ8VDCI63pfNBclvmjLQGqcdMkXXTJPJxWxGovMqDI
+fBncN2+x1q2HdmyqdP10PjOdA/C6Eps8c7nNzTxFON8gBNOKIDaFVFyQlfPIim0/
+dI9Xic5lC39LhCtobtUZsmx52O7guVGTLKwUL/NBE09lF0Sn3DEfiok9xFbuDpU7
+sFGe9FVHjxb4Bn/nv7S3HruEVVormpsDvAU12Z42Co0ubvVlWaDxyEl7G5+0WzCA
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subCACert.pem
new file mode 100644
index 0000000000..e8ff4b5f51
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 7F 03 2F 98 50 19 5C A8 C7 F2 F2 19 50 D2 16 FE DF E0 33 E2
+ friendlyName: requireExplicitPolicy10 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 CA
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMacmVxdWly
+ZUV4cGxpY2l0UG9saWN5MTAgQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWjBWMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMg
+MjAxMTEmMCQGA1UEAxMdcmVxdWlyZUV4cGxpY2l0UG9saWN5MTAgc3ViQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVX0CKln4yztxPjF30FSL1KXKy
+G+0mCyGvYaITtuY6wIxSEY5/gx5llypjWstkFJK6Y5K+2aeHzPzcrsxd2jg3mG54
+WOEpdDgnOyx9CPA8BjWVmZxcnzLzikSF66IoniwImkpBSpK+vzouO/aiC2kEDvLH
+5ywmwtHhW5fYUT8maw7pzJEbE1ZcQivDNxrXL0feO6neRGhNds53tC8WDFSgtZNK
+kNsPT+S6FLMzs0dfLFbg21WHjJ9MaG2kjH1yuKI0KmXJ+RbM3/vngJPmIzILx8pL
++o4mRCSmIYDW24WREsYahWvismJ+Yn+xYxUSjYrAqw8XTTWFy+pBDJooCFYpAgMB
+AAGjfDB6MB8GA1UdIwQYMBaAFBnzTATRX9WAR/P4NCwRgeSYz2ufMB0GA1UdDgQW
+BBRuGKZhJA9o2y4GEZYmN6/JeClWBjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAw
+DjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBAOkcAeSy758gjhUGHr83+uAMg7509xvYFSmyTvic9b4TEjUTddYplwZ4zHK+
+jRSLsOzh83ZD76uVcGn12a3FbFj7GmYC3o3409ciWWefaSZ0zxFsNmvHB4Y3kt8e
+Emjzkck/LLNri5SGKVlPdYEBWQiCvxdK/jN6YAWpbIASPSbNNiSDUYLXNFWhaRVs
+8+RgaEHwyYW71IHOZ+qWhnjmtYQUL6uglCLcIGmMzkxXIgUo70utC5DbTtUYVDZ6
+glLca7VUQnES1G0oA85/nokRVd1TxbKOeBJoyxRf5IjRbW6OIgLxUYjFmxF5MB0p
+7LHjIkT/5vZy/lERobzh44QI0/s=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 7F 03 2F 98 50 19 5C A8 C7 F2 F2 19 50 D2 16 FE DF E0 33 E2
+ friendlyName: requireExplicitPolicy10 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,FF976BA627CFB6F9
+
+0UQf1na5hpAkAVpjFPiBq2fUfi5cEFRrrVtGslQSCfbP6S71v5rxbS3cuwXqIdM9
++au606Cs3NweNOeHIBe3npnk5kXrkP8NBDb9AaC3k5H+aHZ9GKYPFY1EaNya9LnO
+VHko7h7pgn4QaGrHC3BmqjyJIKFaTesLWzNhb9G9MUlIIZs++PufrnHNPB9mWhI6
+Fvs1l5vrZhVdi0sWSplqoE34Hth5Vng3ArDAaQKOa94WNI5F95eEokq7SUQIF+s+
+udHW/VsS4WEnPAVyPhsUdpb9+ofSh6FND7Lr0+vbd7tFzxHuksWZazbK57n1x9oA
+BrC1CN/1XfN+pliNCLF2jEE+gBktUaEBVjCNHpCv6K9fRySCKVrPTKhMr4/fMYEJ
+Pm2HuLtq9umiqJ/Y/ix/OeEllCDrmRlg6l+nniWnC1RlUb433hnpP1l/wBf6zPPj
+qbMYZBzK3mRDhZlcAtOhm23OyUN4WiSslBGIn/auSe+Z1K5J+zYfVyZ9/yMzS2US
+unCOxCMHCQ92vAakzpZmNTNn/8S/orXuHottrHhSHMv9zMoP0hieJZHy9AkoFEeJ
+WGH/CioyY3NImdO3RxiOhIkM0zQpVUXYpgrzl32cJOGkINIs9GxRApqDo3pGH4R7
+gW+5/kfxX9EPDKfZYHOoeV7+tqiatzjPrMJ8ZsGk9OL3xtU+cQ2EbQtIJCoMXc/g
+m4pRPmjiD64FOfcE1UHnSh/Sfvq9Wb13mn1Y/niC1q9SSnwWw9glJVLpJNPlC8SE
+OOAkhnoOzlHqbChpWtiFzls6ExJFmFdZuZdrICJp1812lgwcxlvLO/9MLrV5edE0
+vB3SRDfh8W9DR4yZ98ZFd/QpRI/Yb2QzORKzpoSXQ+U/n/uFuL+OhRBiyW9TZ2vg
+dnJ+9wy6JnITNdFTuL7m5iv7tXRV650bJ/sMXsIzyhz7WAoNL5BxpJO5g1Vdwoft
+A4vBPRlvkFurspLWwEcyLrIM7Foj3hXV1eQbp4W7fKGDSFlvESVF5tLtURoVWN05
+HHXX1tbwJel7zNmCrjNIxw0QIZsG8SyFGtOHgTzK+oeR8KJ3B5hTBgnOd10RVJZE
+M8Uj1IU43RwaTnpQttw4DP/rMeQe/yXTTw6SdvrQW50YDMO6MGGK1C92OqiTBPRV
+qtvlsROpUEITUCbNP22QeYQw145t5pYu96JE7S7EHvFpr+m+KmAO17lpbUIBX40u
+Pkh9sOdKBWkm5skIQi36qx5lPDLkcYvBosadJs0z83qNlfnEJtEm6g0MYmU1rcwy
+X8UJMBmQZAOIAaX7y0EX3eBFAqs77FE7dnIiJDKXAxVbErzC+4JEHTYvdw4VIMor
+yMJDtVDJuVk9MG5lWkIX+942TVWJc297USYQpr9fxvgEPlgrOzeOyCOIfx1hJ7JV
+HJmlHSqxat+2WQPBQPh4sMX8OcndsJjkejKgY2Igdix5K48TFlD683lZPVeIOgAD
+ILaJbcO0/9j+q0EjjT8MItt4tQiN3pHvfqAy8nGXaXeolZyo4TANVfAUXswLSO0Q
+9YY1BO1wAI5LT5mWtF8+4u/oyYlqSnIo09hgVjBfdN0JedACD3l16Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubCACert.pem
new file mode 100644
index 0000000000..33f695db43
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 90 84 34 25 35 EA 8F 80 07 75 7D 36 0E 18 D0 93 C2 5B 9C 12
+ friendlyName: requireExplicitPolicy10 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 subCA
+-----BEGIN CERTIFICATE-----
+MIIDpjCCAo6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MTAgc3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjBZMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0
+ZXMgMjAxMTEpMCcGA1UEAxMgcmVxdWlyZUV4cGxpY2l0UG9saWN5MTAgc3Vic3Vi
+Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3Q6OlKYYO7GHk++9w
+xG8Uaa1vROnO94XkBCXxGvbcoEk9vLTPMrU5LDNeb2b5jsqFUnyr2VspNrqVjsft
+SWn35sbByY9KvOvxtVe9CKKbQsnr/xdn8eAbWz160y1yzfTgKgug36awApr+Br3v
+LKAr4+pRyFoFA/rOODTgCvAAw7kWqSo1u41x3tr2trxhX5LysQQu4ZAmuUgK0FW/
+GVElVC3XqkJEj7f87CAJ1UJvJbkmX3fwg2ZLbH2v4UihwVj1rwOmRUz5mrxVM6Qv
+CkcBmP+gxXStOpWpb+xJbrB8ja6XEZ9E1mZvn7z0tVd/MMp2j/FvPAvIX5eK0jE/
+rVixAgMBAAGjfDB6MB8GA1UdIwQYMBaAFG4YpmEkD2jbLgYRliY3r8l4KVYGMB0G
+A1UdDgQWBBRYUE8O8v5yJKTQdz+glix3tSToITAOBgNVHQ8BAf8EBAMCAQYwFwYD
+VR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
+AQELBQADggEBAM5UH8wRhIjUneCRQvs9o+G2dyjZ2vTOe2Fh7KyY48tnVB0WBn+l
+Z+oSat2PcoEqGLeHb0xeiOdTStG+CIMBsKtEURm+6wm/O9McFDyu/zWAENdgqZfY
+wQa91xLPw/mZ+p73SGqrRpFiOcmStaIax7ip6yB9smU9eIWvqJnRvWN69UvhIhjy
+xarGYM3vUNC4uuhoZuzerUoZ+X4S1l84a0erkbGmH3bLLG/6xtS9jyIrfTN0kkPu
+631e1/HICHgVyGzFxhzKU2wDlkLtWqGk71ZqxJB/hZ0GS9BaFk2k5LS/Jc/r1vjo
+UBK1VkO0Un06qiXfa0JDsXFrWiMtycqBFzE=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 90 84 34 25 35 EA 8F 80 07 75 7D 36 0E 18 D0 93 C2 5B 9C 12
+ friendlyName: requireExplicitPolicy10 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6C56B0A995D09FC8
+
+kNCwDBBX24zs8XyFyKqns0+HqPKcmOUOwb5Eckka6gqCUpI5q1bp+STZaPYBahb+
+q+H9DChmRG9O4eV+T3pmCfY8lSFqv/5X0tBm1KG/7UQHCeK93PJ/+OudrI+9xqsJ
+L46yjdnNHPxRJUflnUmxSf6RAVoxcZ5B8aCW0arXcJpbKPG7vg8noBAGLL9L+Dz3
+RoxF7h/6Uie28oH5sk5KAueItE6lF1kHfBo6gE5G3Y2UDapYbSmXU2Af2lFnZ7zN
+GIlTyapnH0arnWUzMB1QgVWof5sbi4cmt+std8kSpR1olfFEV9+BopVNvspHwDhI
+GdUhN78Oxd3FjHI+RK0oo3rVwfvfN5Zz5/wsL8P6QmCzSS4BWTbL5nMRqUT1ZxhW
+kGRmSn7K43ybGuViWrzZRHxdkx4Uf3/u235dOz9cZqL7UbE6Uz30TWBtDlJNUhkY
+t9iZnlmoz+uQPJVcXoFGQycV49MRddF3dFCQ15Mr4C8xSbU66HBSF8CcO5p8ne30
+k78BPgCTeLeUkO9P0j2W6rYxrAwt4Dcse5bfPlaYZsPsdj2TdludOMJedbLm9ppb
+27UgLmu/IGety7KVbn9zFQKjzoN0acsA0ENdP9wdfpyplhfZ3F0J22RJV/pmrYug
+mmUqPqkmKmN6KWl4N+ZBdOsfwMmMdou+YJ9+kZBOk1uC/3cL9LwL/X33ILanM5pn
+nvJr8cy/lMhcadLM3wiHqtiroKf+Ui+nHrZQ6v7ZAtqQEvTOvLC8G7tYPTdUz1yE
+jKsqs6JrwKHq/cQruumxXj8+xipJ+IncB0AxrAtI1zMcbXosT+tuyXmK76SLX42j
+MDsLysr3N1mkfVm/kiaRVmcRijyaUf9lHM/tLHVhbO0GIuPyYsAKjTJmUIXnx20H
+Zqe/T22MV51ptzZZcr5CRjihJITQpVUjAw8pQKijktT7OEIPSvbvq/fnZX/foruL
+9rXVrACb4LSf8sdJTn7eP3xZVElfbCBosJpm1etjLwKdiIzmcPfuVXsnsfKiuyS1
+PchTcVE7duodcQnUAOhWkpZtlrX+4ZuPFUCWrsebNWgBavEuhKhfdjKsfjXS6Pr6
+u+qTgPa3xVPAhKW1cxiW+smBBnJNPApZ1bqmN5u5dfrUOhoL/sjuuc3bUVA0BkTg
+H6uatshkBRXXaRtx6AvnJ8aECOBvbK90Wl1EbszszVpAEsU2MNhbX3eQiRz1TBtE
+shKnGphVNCbtbS7Ll6xwL74gwxDSOIIGs7ggdpPNmMKfo9SmQPWw137Q4EjpNyAV
+NZXTMmF8P4PJ3K8OCNZ7v9PqnEQ3rJjp7TADD4j2KX63Mnv8fIlE/okm1Wt5Tdvo
+zX6uCkLCb79M3atbpVRZocR1SddJmpLQ8hKKPrPK3lq8MLzTpp6xjnWVK17Hsgub
+UGvsfca+VlDbYmqKvdj1lyIroSaBxN7WLh5QzMILt+IeAF4ihl4Q1xEeRE1NVdN+
+CGB4pC6J+aWpZC20c6lG7O7OcOQGAM6HK/aiAgaaSmxLhu/NjGle4uKhTfGuodgH
+8ytggkks3SzupnDRSWCmaQ0rSFWPSL2rPJbBwoWjRIMTurgQRmFkNg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubsubCACert.pem
new file mode 100644
index 0000000000..21160f2bac
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy10subsubsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 3D B0 50 D7 39 16 46 7D 10 06 9A 1A A0 D1 28 D0 03 48 F2 CD
+ friendlyName: requireExplicitPolicy10 subsubsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 subsubsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy10 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDrDCCApSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEpMCcGA1UEAxMgcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MTAgc3Vic3ViQ0EwHhcNMTAwMTAxMDgzMDAwWhcNMzAx
+MjMxMDgzMDAwWjBcMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZp
+Y2F0ZXMgMjAxMTEsMCoGA1UEAxMjcmVxdWlyZUV4cGxpY2l0UG9saWN5MTAgc3Vi
+c3Vic3ViQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2DO8cedU6
+MF/8P1YnCcHKe47mA/BD/ZjRJFTpgEelXmhIk/9qcx5i+jYsQFPOIWPo/V1WacZA
+4Z3WIdP57sw21CZTPX1JfaoygAlcaueoi2UPH2LlvnHGpOGfZpqtI/6y1Kfs77Rc
+bsIMkW8zRPXY2DOhRaYEOzf7ueXiNFx9SDLolxyZPEJiGeFX3+WrDXjZVH5wnCgV
+6t3l+88ZsLQ0WRgbi1gocOBxOtrR50JkNHoOFwUNlqPibJvBkLYrlIOvJiPlqXXj
+y5lgxMCyeSH79AJ9Q/UdMbJdC8HNmXgWxXuK+vInnaOJkjmQFY9MVMq35jIdSaZD
+69D5hOWuBO0RAgMBAAGjfDB6MB8GA1UdIwQYMBaAFFhQTw7y/nIkpNB3P6CWLHe1
+JOghMB0GA1UdDgQWBBSWjHH8Fag7ztnE+MPQX2lxfOgASzAOBgNVHQ8BAf8EBAMC
+AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggEBACl0/KFW/P2mCzjLyGB/zUARmsAFdR0zvWjnKfdDAjg9
+5Tf6At3kqcgTWt7qiKf58NK1S4BqcOQvYnYP3YeSmBEirMgtgJQ0FGR7R0FgoYhy
+DY3tWak94nuM+tuucWqtQuyB6zGOh8Stc7uYkspb2tCCyQQ+pc/V2S6ggC0QuAE0
++yfuJEGlCyoR83ASr3aImoGcZdZ61aqK7bz0+DTDGJdbteBbSJ6WJsH6z8AFQ+yA
+vmEXwQisnsufWYDtwuskwxoAGL+iTVYj1gtveU9O4zzh03hqOT6owGdjryX6VH9L
+dJFtQ7bn8rR5fuuT9Oui1EgnwoKAtDEIpVQGvCEtLuU=
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 3D B0 50 D7 39 16 46 7D 10 06 9A 1A A0 D1 28 D0 03 48 F2 CD
+ friendlyName: requireExplicitPolicy10 subsubsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2693B4FF0C23B6DC
+
+oT4nC1SPE3hkJ36qls3FUIwwT4t8CIQm+If2oVjwqUWPk0nOCtoDdsI/0D4bwA5p
+oqeE8cm2qpBSeM+1LLxMvSKgDPavwnaIQ0slnQTIWlFZQcviUAby/wbvZf56UkeM
+AqoFsa3rk2KEhxlmlJ9yp/hi2OFz0yIWEeaH5AAKkoTxDAu68+xVI1ofZb81umY5
+7RMogXmKSN1/Ztl1lCtfhP1HYyJo07SluO4EiK0H7zfJR6Tj40npOzAhFWMI7ZN1
+7QlshDkoMBha6nLUuLlgapwIfzW1aaBohAVPrbT8e5+5KbZYa7jyU95YXbWjEDkS
+j5KSUsOCUw0Pfr5c8hCTzYTrpiQQdQsp5+kIUYIAfGM4M7h7gmYL5qbmS45ND/mr
+zivlJs64hRZpuiHrdoW7IC7SVSh13DOM8QW/j9Mod321fV8TMZLTRDUfDmFJcPA0
+bXc6Y+i3izPA6DtDfHuKhv/uVIUjNOkY3OtenVi382qY6svpiDk8zFZfffdFao0F
+edB16GPNI1UpxD9UgE723g9KNA5239HUJhf+vAXEZcUHog7FYkjGPVgAVObinrjP
+iVuk4lBN44K2bhK+adDjn7SkmxpmlzmY3E+4ZBLQl1w4yZqjsKGQeBE4FfIu5g3H
+Doo57oUAX8l/5UGETFpSXdrXdxfwRb6B802ApcDqs/mbgTXfdK2B+kM61mUbquBf
+wO5gbf4YR1MTpRJg2mnwSPRDUlnZzl5BmzjzlZEy+37NOXI8VnD0SROLbOGh8XoK
+9Aq3QTaLJVAzR93Mav08oFVH/FszP+hoec44YAOHZnyq0sbUzeOwi8+T2A75BHYV
+QZRYxb2PNU0J52IjTygI0RRFiY4/0qZF2t3OMJJt8+Vhk0oVQ357YpqrNZBam+iW
+AXjis54A65AsZYwP8oqi0yYhrmqIYUcJYm4fFbW2gB/QAzUu0tifgqQCE+xruBc0
+cYj7BJUJy2i4Sv6paN0/vvj5U5GnyGEBCsIOBsThOsVKRdeyOZZX988AtjUWR+Xr
+4qty4xwpd/AcJFadTILLMLujigIoeW72qvlkl8DxgJi7mJc9C+0yLvMsRQNFAlAK
+NBYyDUm6wE+BrjA1nTmTYYQJxVuGdo7ESUQx836jMnptXIPpuuPQCyHi+T691msU
+IjrEq1Dn6VT3oMnNLuT/Lfq2QRatrSDWAPPjfp9hDH5FvbqyJD+GoVc5r8M2/MF4
+WV/vhSiaQpwZD1ZgG/XNRhutHb1LSGIGPYbQFbDqZ+1tpa3UXzU1zPJDAirumFZs
+/CsyXmpnXJgdgd5E1CxqCq3yfYpz8a/YgRlGNMDtf9cMQI6qLhiKDarVpdlhhVjI
+lbHINMEakBsgO3+L2CyJRhpDYvoq+BuFYtTL01hcHeoBDGTLQF4eM571FE5Eoxc2
+KJwBtzUIU/tIfEBVO5qxBbK2vad+s7fz0/lLWX8mkkg9SNHuaNYImt2uoBBQVJ31
++agpG+th4eB9t5uL6h54Ivbgishld/zc7mKrzwX4cYYYWkBZZtFTBKCPF4AKzvY8
+in+tAV3EKlz5mXB1ztJ/ezbR6ALAOdyDSO9EhTdaOmpTuT6NjCtFTzF3QYwnRDMz
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2CACert.pem
new file mode 100644
index 0000000000..c49f2da69f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 35 D9 76 B0 0C BF 65 C0 63 6B 78 35 10 9A 4F 3E DF E4 75 7A
+ friendlyName: requireExplicitPolicy2 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBLzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GXJlcXVpcmVFeHBsaWNpdFBvbGljeTIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCzxfi584eF82tOhWkMbV/3OVpGrWH1czuMyaq0z0aPeRgBRrIB
+EIvQpq+7Bn9NttfyrXjsyJOt47rtyV0yBGkEyBt/UmCehaLuEROLemMB4uzcKLLS
+fo/dcHd8MZV4MUn6ESPWny0PJADb4akSbhWS6H5LA9j6qeMc211nfgy5LBjJiqNL
+6pEdyFfiW59UjL3E180/pm5ktxiUbQAjqs39vr5TEUrcnXIGEwD1wNyia7HovdoL
+2dvSb7CbOw26Gv5EKLPKfBTBGM79JUnMFG7kWXLUAhGbosCI0bLsZO4ox7q0hy3M
+NMOkxv/4yOqu4g4lg4ldmfxj5xSV4QooFSrzAgMBAAGjgY4wgYswHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFDap2fuqOC+g90w72YWd
+mhWjLanHMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgAECMA0GCSqGSIb3DQEBCwUA
+A4IBAQAe0P0wi2luJkXyOChUK4ruG45cD6IIep+GwGXYtnsq2fAXIWe1c8XCQTyi
+1TrQBK+AiM/AREdH2ZVSA+V44zgmPIXIiVa1teBPXbuvM7GQzOaUU5Dv8SMCjRzH
+ThsV5bkvTw5V29Pk8vbIFNMzSFeWfoatv4RB0a5ahW153q4CgDOUyJoMOcRGRi9L
+xDToUwTICmz4eNcMA04n0U94wnqZiNhcLEdfyX95ZspOAs3E2YGBr/Wi0slN9+6Y
+CpdaYY6UzK9azt1q4t9p4PTfbYDxi6hPksgMEoFfUtskikrdD5dPYcG42IzCTOks
+Jx1qxicm25mJ7TuNhtQKBeQ3FeXT
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 35 D9 76 B0 0C BF 65 C0 63 6B 78 35 10 9A 4F 3E DF E4 75 7A
+ friendlyName: requireExplicitPolicy2 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E86F4CFC334DAFA5
+
+V9wxv4XRXhnFgR/nCrVP+HQGB2ZpnxDLDRCCi1wCGQT4HevR1zx1lhmckqN1q5SK
+en/+8HITNNLpC60zczhO2l3aAnR4WzIGn+VSPAP1kAx03DvconRyX/ZTenSs5Vti
+1CApBPJZb8+bQdbX7GEtLxVeZ7OCKPdHBYfXFVB/0jcQgUJSxhO60/YJk/q+/WO0
+gjq5geu7h+gUi1XcVN1YaHkwhDndtlDfRSoYp7ZhnfUfODqnfzapw7zEmmcXLZt7
+xii7UpeERZ5BE73mEn0yEEyLsnDVOvfokVAwu0zkTsKrJMqLZ5k2spHYSU8LJi3s
+Jw/Jfrw9GiCQm8GSqD46SsBdl9DqBjucBqhKDZv9sUUANc8a+y/e2kNINAtezwrV
+dCVaXptVYiaAfl9oJKtAiBDQRJ1Mp/4aFpguEttX847RyXjusUpQXrjtnph6byvp
+33QDP2Dgvg2juft4/qxYm2dDN9jXUxAMy0Ym0ZjG/Uv0Z9EUx0BAzF3j9u9ztAcJ
+TA4bNSvI6xA3hgoQsd9rGZQUFgP5nNAXLQUCSPaFUY1OdZUNsnzFMvQvKG22uOyd
+DhMSAlXfpaxQ8KmqX9ekgzYSBWwlCLCMHUTCAKQFybg5bFvsQQNjTkqAAgRt9lLF
+zlb5Z0+bsSjlNyHNQ2QumI4gnL29b2Ep60/tPH2hWBuiFXOnnJUfvCDrrZl+2JLi
+mVtz7qucLGiEtLdX8wXoJDKh+AgidbyhQ9H+G98sDx6GN2z6bUKZbeIIXOSoiWbY
+iOMusN8/rTjpW1p7tNMZd/NZ7iJWcVlz8HAEkxGmqZVePkZe4diWsGy4mx7WDDZG
+5XPuDHVu+4jwFBU8OFqc9qhQzox7OdCEFfNxzo8TCjJ6zLePS98esVwbKjJy8F6y
+Znm2bilT7PVNN53N6gHeV4jZ213/KxuD6r2IamqOo0itst16DSvGxZ+nf0kJzJuL
+I7c9rME0OvBr8KgFP00ad4ZIO65ss0SEJH3+qSGgMsAdWemZ592uF09GeE2/WqcK
+n/tza3e5Yckeudopu5U9Icl+wvFwC6Wy2cgrXLdb/PB/txLGqlLShGocSTtNPRJ5
+Bi/MmYET9kJoKyyKuD/vW6C71KyXRj6KpD3f8wiVQUGRU5TPkLn+8m4AwcRldM8v
+4pKw4Lr44jJum/jg1ELHzaK8vCYr2E6JSgPOWxar7+KOPqi8VnfaoTdsEhpbpcJn
+yhWQ3z3vanG0dmJ5ROVde6X93bJVPMmvFIyW05fxpUSA/7/de19UZ/HoAEkq4wik
+VRwaJ8JOgTpp2Z8W9Ma1lbPEXtaHvbA/MH/83blD7Y87BLJhxgTcMPdU2edRX/HG
+W27yIRsJ3F8YFeb8iKTmO8BKgx9vfT8MlY7aPJr2pE1FrVdT6tnj6c+BU9hogXlD
+Gg8V5wNq7baQuVsHbIlv8QRTlDf+mxajj/BJO0P/HmM6VHezcYfpXtC1ozvOZ82b
+bsbpA+5t/BWgxOXgV66GX4Nf40K2u+kIUQapdDJgG1VdB5KfLKzu3GAlJBbdXK2o
+YQR+srJaV3OSpcEeam5JJ3ydZcZt21IqO3J8tPF9EnOcrA4pHfIn8Q==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedCACert.pem
new file mode 100644
index 0000000000..e0a2b37a9e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 50 09 24 5A 39 5F AF 37 8A E1 C8 59 95 20 B7 99 FA 59 1A 2F
+ friendlyName: requireExplicitPolicy2 Self-Issued CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 CA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 CA
+-----BEGIN CERTIFICATE-----
+MIIDmzCCAoOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MiBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFIxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSIwIAYDVQQDExlyZXF1aXJlRXhwbGljaXRQb2xpY3kyIENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5ByQjiOjxE+oZnilZmG+qagOo289Fp+X
+R9raC3r0WvOV/DiAIO2m+PMkq71mXXR3jc/gIL8QqIzS75W0XToccyVOnY6uQSlN
+avFElfBmhxMnYNC/kcP/cpne4iABELM3csuIRUz06nFXTsSkQSHa9sfc3jin75dB
+5JFHF+WzVBbZLa0mUMweVJ0g6ukWYoyEqrRSME19jw3X+VKkQxqOBR4BEiKLLVHZ
+0DWzomRmvC/YOa6QxlHGlXO6myPBCVt6xqpzBNsBLhjKb9aTsxgRir8Wyo46FGpi
+OBGfB8ebefFEQuwx/Y3TLZEUyaAvd7MO85ftuvp8weAVUIw0Ks+d2wIDAQABo3ww
+ejAfBgNVHSMEGDAWgBQ2qdn7qjgvoPdMO9mFnZoVoy2pxzAdBgNVHQ4EFgQU76va
+2OGAMadDFu7Edg2v7G3yYKEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYK
+YIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAM
+H2gKVmtNkx9bL0dvtkEPs+89dAzNW36hrK3NTIIDfe1JjA/u5W2mMHORYJIDgvWS
+viva+NsPYDNsLiF/okUX/B+d+zUYBweRDG2t1QQzQGuwArb/y07eKTm2VZfHuvR8
+UJhP/BeqW8ftZ4NU2P1nGwvTRaENGvih7aPxJWZAyqlcQrE0Je0iFM8V3tJfC9DH
+9xRDUTADrgsaWMajbEea+cFAhcY7E4YuZM94DKEvXIVjIMM5ifOGm9ySnf5LAsVd
+3ER6jg90zfW1wjqC68nPWpHOfglWoJ7QzCxp6IqGkVE3tFoVIJKz8d34bKBoyh9R
+xPdQHkHs3XLydaxFC8kf
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 50 09 24 5A 39 5F AF 37 8A E1 C8 59 95 20 B7 99 FA 59 1A 2F
+ friendlyName: requireExplicitPolicy2 Self-Issued CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5F6F0A015308F197
+
+R+0cQyPBxUuYCKNFCmE/mdgtm8g2QoIr2dFN5WwmwjVkmrL5IG9BLMzedJ21/O5/
+KiMwKshJ3o39CmU0KSC7rMgmrCB1jV0CYz04i9/j4Zn9o3cvZxgILOLEvRY25JUB
+Ak/lcb1hWTuBP0Jlpq33KYjupkR6Ss13kgOc893SFFWJPRvMjyjulwzY+wC+fsHW
+OrK1SeMioG9SpxQayF8Y3o3KitoBfomozW1PTGZn+xtoFvIUSpToiPu7/3rKdAMc
+OmNjbAaPOmEyhJmPvwTb1SIP5UHrNwkzeN/WknZWUjPbGonvsu49dlvLwWhvsRM+
+rEadTY8XTxMQ123QJMmd8CkYzyvAbkTTySDrlH+7px0rxZ359e5FqBqMG1KtfWXo
+HshiEf3ok1DxDdTdbTyfKxc/7DpFjmC83+3aL7Yba1PwgNvpeJCEmGkSaNN/mBlV
+0K+zBva/l25ftLpdm4FJbU5heB3l8Js11sxhiik9XKQUrLEdVQznG8a8t+yaZpHI
+XHqia2c3GsFcilESXgcKhRunyuutzRh6VASgLO82u3oaMhdPXqAuUHO9ZjNTlS5i
+IQJJBU4QmhB8rtu4lsSgB9Y1OhK7Ijza+fvJJ6/KMcBP19IMuK7uhMtdk+1q0qRW
+HAhCx5iiVB3JKikPOzQHeJFbdIa+0YOBVWh+ttxpQZD34KZxIdqJe5NOQPuVRZyn
+HBN8U2ibEsbKgI62a1nI6hOC/OFOsxiXqc2BO+p4ySw1KO4hoGNupvYMe3lmVSki
+ki1pDo5esrf+XzXYQeAQ047Ml6wnzddmeG24FMoOhZsVKhpKezds3Jclf1LbemS8
+hR8b92HL6UncI7NmSIOFV/HlVTxjxAP9ZdEGImUoDTuF5eT0V6Wf0uMqVGPdiFLH
+NJ8929bAaFL2m4rbkkjjEPZPotvjsSYj6T41m4VwFqhwIHbKCVWf2Zxd4/pTjVAD
+xSsrfQnNVvfn+Prixkn8qZmLNeK6CS0fkBVSYikHm+m4eqOeWXsMw5KTHsUW3XVq
+R9pbFpQXKqxFjCsToQFMKdYjRAFxsQ2JHs99dyeB4GstmAsDgOY+QCViRgT3IQEJ
+jgbRTr7DuDPbBa6nkGuEsSV5D0MSG1DehbT0GrCL4UrrE3B6BJKB3uLTEpg4i+1M
+g2et4bSkuzCgT31IRpm9iNGhjqWospJJ7o7DYsRD/b49vax3J3Mv7CsdWWnrSt4m
+AQbWmZg6TJkG0yJ2dt3AFdY4stAiL4MKRBMsVETTI2cyIuNMZlo9zX4T/yv6xFeR
+rzqddvh7NY6AQQcqn1aRSA3OJqs6cD+CV07QJEjoi9g3XQ9f1gkGMivdTz5I470U
+LW8R9LR9dbeCYuTHHGweKvecz5+Tj9EOXXOw2uRedZrbxgh6jA68PGzzP3E3ZgZT
+XiLtOSwa9xSWCDE39OUX1DJ9RqBjW6Q0SxZ53fYhvAiWGin2U3WZZyqh8kH+Ef+0
+KU9/YcQ2EpexC0wXe41CUVSugVf1vwlz6RJtWjL9+f/V2TH/v5K9NtgVn3BPiEB0
+z+xeDbM+yGS0Z9X1AuTdDgFw2R2L2iq2S+DgImr+eruI+stbSIJONQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedsubCACert.pem
new file mode 100644
index 0000000000..fec9b57fa7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2SelfIssuedsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 30 5D 56 DB 11 7A D6 A5 0F F5 EB 7B 4E DA 45 A6 4C C7 57 B9
+ friendlyName: requireExplicitPolicy2 Self-Issued subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 subCA
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWly
+ZUV4cGxpY2l0UG9saWN5MiBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSUwIwYDVQQDExxyZXF1aXJlRXhwbGljaXRQb2xpY3kyIHN1YkNBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwnzSUphT/R8NNpeCrM75XZbe
+zrzFry7FcZWWHSFkNKZPyzKJiHyA4uWR2tIz4HaoNR31abyitlqnK8raWcRobhY/
+v1YcatsWBl84DXeUijt7Lo8FsgFYgJtXdQMTTZM09lrY3YA1daUUxjEVWxogoFVK
+mfAz1lLiAlMEeyzWCGpKS/RGY3f0AKZNLFFqcaK7bvWOcg8MJezmWGd++937utjZ
+tQDLzQ6m4I9pkrOQgwyIL0BTetwyLG3wMZRP7nhU4p4BRoSDfMiVQ8Q+wWKWIl1+
+EvRdNnM9L8TJYtBYvFDxPNIHlqi2OKi8burXeGaHD8MkuQ3/XvaCCoFLz465LQID
+AQABo3wwejAfBgNVHSMEGDAWgBQgd/5MMI3is1Edj7D3HH8dg5gORzAdBgNVHQ4E
+FgQUSQpnYVZHjdJZl68iZjBRd1Cq3KIwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQ
+MA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
+A4IBAQB0287v2B91j3aqGz6VvjWX9dV1aXfrJ/agTXML2eCFfDpdZHSJBfF1eEWp
+EyRV5B4drAJJUOFQk2A576yH2wY26c2CatdTtepyvfiNa9j5KlxF0eJDuU7RjIpS
+X9aV0yLZVWj+zDxNZcWnTZiw5UmEURQWm1UvNe4n/DZqP+Pl90VhHmQujpDNRzsb
+zKmGbTwGtJ1T9oEIsP++cRW+cp3MXY+31gYghwsEgIL974tnuHSSL/NTM1lEu6VF
+A/45TkZKj1ZlQPYZmG1AoT1JeAoXoWDEoqYpXNZoQAD5fveEtunwPb3Ndy9GRvuV
+r2lfVmqh7AmOZMnyQvkxHohQ3cY3
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 30 5D 56 DB 11 7A D6 A5 0F F5 EB 7B 4E DA 45 A6 4C C7 57 B9
+ friendlyName: requireExplicitPolicy2 Self-Issued subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9583C403C5D25EFD
+
+EREj7CrK6SseZexovZgTkHUnzLQSOpZDOFjRjEpWDDHiyVUM/qimEuynGfTKWJHA
+EfcKL8nYgOeaIbGijpyf/B4DDPxiKSiizgqLLLpxxNN+uFfLixDmRkAw8wI480MM
+kZWYLgFdBAl1DOzrUVu2IfGpNnt/mX+je+Ku7iYpK5rNwuZnISr0rAHW/PNu+YOS
+wPrRb5l/eZ4E18cx+UhLBjnMq4qbFAEFXz3PEchTswPCeC/tyojmFo84Y9/zCRxa
+NRfgTmIsehRy25/L3bmlaES6z4ijIbXDfiv4dLIFN1tMGY/0b9HLS6RCyZcKHCA0
+DHqY3RySA5JJCXdrD+jKBYv5sfiqUg/26VtpbXUlluZltBeDKGx2/vmf5oHow1cg
+QgazwqAINUKVLeuLEslShbJCHWnnNnbBpSwG2sOaZYx4v6GiJR8WhMW4CM/oiEye
+Z7DF92bAEvNtOIGsn8TzoSBRZecsPverv72i8eVq0HWYJ0kLR9VNqCuqOuHQL87Z
+e6SlNBf7LqiN2dQeszSWKOb5szPwk3U4nzo5X1vAt+v3ebQV9uFyQ4uTNSGe5hno
+0vn8LXbaFOLakBDUmMNdCqhyWFq7vioApSI6TDCToNgByaf4v/biljb/l+L6af7u
+MU3CVc8De43gpM9G/g1czfNDG1glXLYhXjfNmuXnPsBDWvjq1XEBIAsjbq8hyHk9
+AQNej5fRipr0hRbojxc2AO0dGNdZ9jtzsYI6MeIAaSsE6I6jP/7tNYTpjCAtfnGL
+BH1AZseIpID0D97ZCbZK+p14a8LyhW8ncoYgB6zWrVP30mJ2Vbn+ACUCRRgAKQ3w
+t0u9suM0CuJeYnUKhyIGZVXzuxgafDdXn4j6gscyz+JVlxjbuRD49xX2Ser3DKex
+D2xcH9UG2gLxZKWPsuSuXTbIh54dWEYpNBauamKKXhE6vKCwzn6Kr11lQwbmnpmB
+1ZV4McCg9NVg+5kQEL0iVdYX42KivG6PZxlyVm6dAmcPG/QgZzBA+ujQpJ6QnSR2
+oP6URm6GE4NKqf9tbV69tY4mrmnemwCS2sugNe4ZFM3O7FwiMnWG0XcKYwIHKdjx
+iLLCboJo6gObaDLEqU73PSalhzcjzxRjG8p0vDwLNfX7nUy6rqzqxzMxhkksv7tH
+d+4O3R70DxBpHGJnHnRyRfOKoKr2Rvm3gCNizRr5TP+zbnJ13nZrVcTg4V6K0jhC
+BSnlwcpKgHwnvnKBnPYOsBNBSWKrID2yPMercwtnwGvpWQutCpg+TXlmeXZY9iON
+W05GHDuSekNpiI033MYdXVP6WvH56mdQ35B2FemcDiBevmsQkfwT3r1BF3fWx3/h
+0sddZe/mDm7Z/HZF5QLe5iqg49hRH2Z2MypjDMdjb//o7VqbcvFuwS0VL+s3m4Vd
+lV/iUWiBXheIMLkavxBRk5I80C/DZzKc6prYPXE0GW0bNLnAbTxAd8zPd1k9xF9q
+iLn9LZ/o7b0U7+HjzB/vs2SwAstYWsD48S53XixyJXUwfwOtb5ozct8sFt1L/G2W
+jAiQjrCDiwmxGHiiEU97A/tFn1x/u/bpE7Z+5ThE35r9qN0js5HNKw==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2subCACert.pem
new file mode 100644
index 0000000000..a1e3a855d4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy2subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: EC 05 DA CE C4 05 55 DA 18 AF ED 65 5B AD 27 AD F3 70 32 48
+ friendlyName: requireExplicitPolicy2 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy2 CA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBAzANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5MiBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSUwIwYDVQQDExxyZXF1aXJlRXhwbGljaXRQb2xpY3kyIHN1YkNBMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsi+sFt/pVAsHLB0tfOfQJAKTDdVo
+krxRAE9Ykhw2mJympAhm/yEB/Yokq/oDim+KjRlJ9LQpem0qOjCTM+ApZ4ClsvcC
+apqvHDKpU2kBXlLyAFPRz0WaKGUlvNUheBkiQOJEUMulXF4VtsNFZloCc5fTKLOK
+62UIdnPMWPEsU0/T6Wp03yT4mKF4mV7cxcBRDwYOhb73wCwP9sE/5DshU4uaX0vr
+Zv7MKr5DLkq+TxCDrOGi4nRdplw1TOog46OIc7XuE2nd/Oez4tgbE44tACRfvdZz
+oQToxX6mw09d50dlIy7Sg+5U8U1M3T74tQ91LPH9WUQ3qfR/0BGVXMOAXQIDAQAB
+o3wwejAfBgNVHSMEGDAWgBTvq9rY4YAxp0MW7sR2Da/sbfJgoTAdBgNVHQ4EFgQU
+IHf+TDCN4rNRHY+w9xx/HYOYDkcwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
+AQCqda8jpBRM00PZxYoWbSe1nLb62jNqZ1D2b/wMEKgBqueQhV/AsqCsqSKoGpKy
+9J1ZYcUfRH941kdMAf9zRq/jtuECva0ZkblFq33mx3a+5/7PNesOU9YglAtEL0lJ
+mXtpzaO3tPO4gyODSU2eWdjBgbmndDugp/m/t51SdcR8fhiRkaLIERnybXt4S/FH
+7CdzrJjoLGmVZzigQa1de/6MIyumAXxJfxPmlqxomS+uDzGys+CGMVJf/hJnZJ4m
+QH1THJUNfJFyx2VvNqQqj6bllO79tcWwAIwizPr46qO7ZmwRAVs2HhQgEQn9uIti
+fR/NRcbd6E2c2L+TYxNYfZ9r
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: EC 05 DA CE C4 05 55 DA 18 AF ED 65 5B AD 27 AD F3 70 32 48
+ friendlyName: requireExplicitPolicy2 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1130C927FC646156
+
+XqOtLmXfDRiiFtiBAzARvlaAekMHrJTlP+xc/AhfhYcnvfF4SC3fhVH0L7XKWojM
+NOxsPM02iSFHL6mB9uP4QuWjuSvlMnfXyN3REcvo4XyFEhsqwaiAfR3dGQP7f+cK
+vBKC7ZG2MxIB8oekMmW0j5nuthru1W1PeqMSiGY5OMx/FT8JA8GOZop0+PZM3IgH
+aUpScMbAocXHRRjXFyhGPWLQ9eQlOucaF+QRXS6ULRej38Jxfo97dxQiQPQ2ZjYQ
+NL1XMwA50fQOo6UTHFSNNcnP3tr70hyIUtzXCHiIyLPhUxp93v3dYYgUgZCgZgfk
+NcM8xdI3NPsACYstUa9Mezp6cfpsr6yYS/7Pwvo8F9Rf1yHiTRiMjQDfEQgNatl5
+xm2lSiiLaVdGRAv7Gwt4Ie2R5X50cUJfnNL4ILWgPCVEMQGMLp8FTiBEIgngMY32
++VOfCV0f+ObQTOQDyvVr7R4zk9PMg+N1I9d7JqGWjEJpghpelXstPWkDzwqADI/9
+V4UUQf5e6oBuVTxlANgHU5lRJzgNyr9lAc0FQrGFm+3bGMQKHUWXHUcx/BpYpLYB
+99YhlZz2nUyuHxOOikHJN/1FpPx7Gz1REAAtDItjjKqrrDKE7Q03srN3w14BuIFf
+uTv6uO7sGzNpUPNrTUt7OBaRFColXu1d4HPNG0Js14uB3zttiUumt1ENC8OHC8JL
+O6+shmmKQkzRTiIq0r3gf9GL+MyHAb+fMiphiZKBai/OyT14ACy6wUD2fsKciP5a
+mscAYUVBp8w1ZR4dSDfEkAhlQmHWGzD/KtN3ZrqqzOGmThkg/Spoou7PtaWhROI9
+mxk7R5JJ18LvDoTsttzmPQf62t3BPR05ZBb0YtSG50vvDVqPyg9vM+Z77CvjO2ux
+pC2QhAxWLrjuX3I5V52Pp83ZDi18XU7FDlmRYzNTyADrk2fXlD//IT3xhTyXnxKg
+UgP7JqJemHR1rc+aB27bmDq/NmpOX+J/C1WfSaxTS8OgN5RXSFGqoNyFLZLEFooJ
+Er99nQma8rAbVNfFQdoJ1XVJNlyZNczGpYeB8OqShNvu3xkSKW6LgaB335fSKeq1
+W83us0s43j37HrcwDgCgZgTvEoJb2l/Y8fp7lLFxDMbUIPSKTRCeshhzGq0abN59
+iPRtzZk3MmIC3gJoEhPwlstA3hsWCrkZ+lAgNCMONW5eWOpiRV9pWU813u+B10b7
+7XSwIdAwCa3jVcSm67KlaRvYT9DMfEMvA865+piw7S96yrcibfuBg9LhSAThvNkX
+TBpBwqLmNiPW1oxYDTGBpAcX7Vf6ddbF6MXAkQaxdls4LaU9C315MYCfg3eBG3P4
+poU4hO1ID1821jm5Br4f/rD8n7bhMDak87cicVj5aEaSpSQJl1Tgn1EUcxuyxLRA
+XArZCO/StfNYWfkfoFx5p8sJatVYJd7DepYfnxfscjzgvLPe+3+d4o6dHDgGjCoC
+aGGea+4EG5WTpFCTf1MyAtCIp0uJXuM82M2ngKoTzKI/GfpEHlvhIRRNGSZ2aD1q
+hrEb68K4WIUNAwirrSi4lD9VV58HRzWkRTiumlCOl/nObKnHKKxkGg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4CACert.pem
new file mode 100644
index 0000000000..205fccc01b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 76 13 15 FE 85 60 E8 F3 40 70 45 EE 9F 1B D3 30 EE AE D0 B6
+ friendlyName: requireExplicitPolicy4 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBLDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GXJlcXVpcmVFeHBsaWNpdFBvbGljeTQgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDa+CVdJxQ/ByNBR6ZlsIM3/EsZlaS2iCQA2SxIP6w0Tc+v/+Ug
+BcDBblSufESFEfbhmqzWITxUx4mourvl8nTWSvcUBXZITg/+9RKUNUAVvzCEEY6L
+Yk1bCGInOwFe1QRA6q9bGfufN6mwbvwAYML1I6Cp9El/zpNWO5F3XTaIpJ6hWyXo
+/FZ09MLMHhrAZKi5diInbH6pm8PYPtbAxA1GqjFmFQkp/idJ11sz0yL3Owbt3NRC
+UwvYXdwGnpBkuXuDUEx6ImGT66AI9gSgVqXm1+hc78sElrlFR7JTNaaeulEAcIrO
+XaijURKvc95snwvOI6Fcm3rMPq++hBB/P8uvAgMBAAGjgY4wgYswHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFM3R3MzUMWMHLF02sQ+N
+nnW+S15jMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgAEEMA0GCSqGSIb3DQEBCwUA
+A4IBAQAZdX7f0d/4NVR4jF1aslqeBmT4OLiV8GNLZjho/mBmhHqP97LU2aRMaAgs
+xwbdMyffJY5yEGe/x+LEOD/+j1Zf5FOqwKXO3AesQqcrOVf94oAxc9qkMnbU5T3Y
+S8DFSbvUqcPncCQ09UmdL+kcFg4t42WYige5MybEf6rI8bYaQuCn3R/Bj9QyKtvI
+UOKYgJZS3aIEnwnU46I6Fi6c48r0KsFswpq1XLs2g9qnGYAQ0QTy3bZRoJHGUEWm
+q3IlUK4FjgTfMWhicKyfm9HHc5mlM1TCLLAndyzhI7NSOS4SfRGUiSgrGydwkC9s
+4MNoiNImgrIYopZynkesWA5z8HPy
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 76 13 15 FE 85 60 E8 F3 40 70 45 EE 9F 1B D3 30 EE AE D0 B6
+ friendlyName: requireExplicitPolicy4 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0C15598C80817A5F
+
+NpAhMhqmAOIWvRGz2mYGfKhdfOFuVqXgkySM4ZqcgB2OqmWm6JrWtZck4xAeATHj
+h2zxjtFKP4cMtNN/nVR3vFhZmNjUl0rvG3FJHgj7tl2RIKM8SlzLzu8zqO6/pViy
+n/qPBR4aLI0zJGfGy3JEvBhlFFFCE1tFnGBMJ88gEH2L/YxTwM2UVoYmhMpvDLb9
+c1NluB64jzipvAAQqiN+kIcMf8wizkHeomOCqRXnlcxnjvkg1121ShQrNaSYMLDv
+BRiXEJGu0PjuUO7F1zse3YDQQV4D72tcse3PCIyno/WEzbbtWzKvkfUSqSiv+Iu7
+ixeCjkP4zVa88k0dK8NwtqykyP19HYmX+e5hZpRT/reAv+1F49NcA8fhpCpfBje/
+7f+VyRdDKJBjy+OirubY0qUtrrelDLm+AAAsv8d1GUcmxKXOwb7Jua4UoS/L4Ke9
+LUTQpLm2NVrTSwmu3FGsJn8vI2fDtNXcecjXrPLzJzb1kZjkpCbOeYt9JkVCKDpS
+VKLexAd26B3PHVZZEOnxO+uSiUW+WbTx/RNSXB0AmUnMlMfCZeE+S6utLawi5eZ1
+uxMQ3T0cTuVajpX0d4bGbp68XaAJEd4Nf5vFyR1H8lLQX+Yu4KUKHG9EVxLFdOK9
+ivJQocoUDN2M2y9HkYe8hhEwHHYkNTw9/SfvCCaTQdhTt8gA3IhvtSsOQkdS4eYw
+dW3gqeIPIPlto+J61ytQCXRXc8AdUibQttBRLuHZ96T3sy8/6H+gCtAMvsRgnOgz
+Zs5XeryV/Ytvicpg8L4KwV4tQh6nqGdr+NlvgICU76I89Hb3O9T/cuSdxrclUEM2
+G1ZOIBENj/N1CKxy4VorUJk7VKz8NPimX+/8q+BIz+I7c+GQQGh5tXRXpSBp9TeZ
+erWCMMyiT7vEkhhD55UHqyM1ixHbGTgWJ4lW2X8Do7hhAkl6/HRF9/VnjGp4V4yP
+N/qHw5V6FvQuiXnfD6nj+QbdjcE2WiShELa97qlgcEC3X8d6OAkOhDxI3hKrg8EW
+s943TTEZ0nig82W0BQQZHyN8vm6JXT3wr3aiyyRAHHxsBftsVl3rnHK1lGPHr8du
+r95hDIKZVBSpCoYLXmESKhZLtSRo4c8LwHIPOS5rpqylCU2K1tODTAeZiu2bORr9
+430oyeaXepYO2KyMxopc4PUnGbJPFVagwzAIFw9myCKspEWqajgK5kzAwSwZnRGZ
+P4S+vTRuPdnDLFfjDI0hgcFrmRvY6eziE0gZSCTpVzxejkhTskxbJ5mj//v7zU5f
+pLPId7bF1MzG8PiKJD+24SWB3+fNxKXiydrFwg/tE9cGnz1zfnPl8vtuZrzs3icW
+q79e35TAMjCaO+ESabG6jO+ij3flbAL/8Sfe4WnwOSEGA1qaMWvxg/BZy/beq9tv
+XhMEPZ41Mf7YEQ05znBzmQbfAweahZvVDOgX2g2Fdaeh3XN67rUdbTY3my8IM9u5
+klEpRpIlezBI4hr+Dz9pbCAjdhge/2TlGwEFgDW6GhYsVuxIAxqW9Pa6tMyrDSMP
+Squ9KjE5fwCB3SWAZ3fT/aHBS5bRqSvmBxVRQ9R0jbwtze3arZQlXsti4uEI6QdC
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subCACert.pem
new file mode 100644
index 0000000000..c2b269e675
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 4E 1F 7B 4B BA AE 8B 49 80 2C 39 93 E1 8F 5B AF 2D 62 FF 72
+ friendlyName: requireExplicitPolicy4 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 CA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NCBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSUwIwYDVQQDExxyZXF1aXJlRXhwbGljaXRQb2xpY3k0IHN1YkNBMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjxAmVGJK/Tf1KXchcBFfOGvTNaC
+PIrRtPoMudTQVaWVULbVkDlQlNs7U0HIhB5ojybvUweKYpmqMExSMVei4/KJwiYO
+kvtLLlKL35LF0+lgv33qbmlhhE7GDg6XGc1edcu+Lfnn53F2/bpldSSwv040roH7
+82NN5xqk8hP2iyChsb9eKFJolXo1opl/J7123xcUEgOQ1DEDTe1EKRGpcwguMk9w
+OWz5X3fkZ7fd0WccqjaxX/e6mkNhTnnjHil7N/33FSOpO8gWeLBdy3hbidPWuBVj
+Z6zQ3R4M308V8my5PpPjhkLuPoU6hRgqPXEQZa5CZTXWCnEvAGYmJsV4ewIDAQAB
+o3wwejAfBgNVHSMEGDAWgBTN0dzM1DFjByxdNrEPjZ51vkteYzAdBgNVHQ4EFgQU
+fe8OlBe79qeX5tgiSENIrLPuuo0wDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
+AQBo1F5VotF+zBRk3lISLB+TwDbHkOnTeZP1CANWsThk/l5sx48F8cdhp4oqyzKc
+aP/SjDt8a46clnd+jHN+WpaQComRwFNZFjytb4HRciU2QgC9ic4+L/xMG95pOQk2
+ZAdzpa7SF5Nf8aR07Th3Z6gfSrMsN3KRurRTMWozjLaGXiOrrKEKARVf/AbytnKG
+SVjB06e95i4k4/ge9lGKGPH1VajbpyZ96ujzVk3AB/hAY6q93nlOiSNATWa1HV6m
+j29A6upj7f5E+SVd86Ms9TRT63Br/a6595avK+At2T57FaiuSHoPC+hMfq8hkLfQ
+a3itQvRuWRzIOtSe6ei7vY7Q
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 4E 1F 7B 4B BA AE 8B 49 80 2C 39 93 E1 8F 5B AF 2D 62 FF 72
+ friendlyName: requireExplicitPolicy4 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,441A86E99DA66C24
+
+3DOENkQtTbWRVz0EvGti2L5itNsvLfjAHh0FVmh7w24U+QHFre1aIagAGa3ciN1+
+yUgTyvtYRZ9haynn+o2vPLLD2I67PNDHpdODhOEP6+PN6PhN8oCy64ENyr8wEukf
+vBKOFLWKoe/3Dg1aR0po1dtbCFTZ2QajMfac8D+VJdkpXNS/5SOlkDFHVe9HKXXt
+t51zqKrIUHEsaUtq9dPjlddSQ7KWoPQhhhiMeRmP4u3mxPOs/287nQawKtFRdOcd
+mH+CuPTEnaCMcEQU/xBXEt4jpVk8mpuA9o8xs3aq2K47EqRiQ1ZYNfqVkIkxcFDz
+1rhtSuHobTo3vjn+poduD/e0kKBv+SBvUxS8s3Kr12+5P1Ye+Z5FtODxERxQDml5
+e9/IbtX/YRWZLqBpWwx6VNrvumXOC0YMf8lnCPSOegh2R2mhLXlMMVcYIbZplB+Q
+581eClEcNEurPEXgsK8NVtgfRsIBOxvZsE7xBpvnFP3MkuLpuUaHIHAoKrrlXxJE
+Th5AbnI4Ql7+ElRmtk0UTWp7aeH2y+4c50g7Pd4E7eKMxjg68bW+02WWxo1I9kEc
+6ZXgZPmZqKe/2pTmiFTSbCLIa1xiOXvpo4/abNi3o5QegdJadQ1v+GBIZ/cn+cIV
+gDiLpvKn8WzMQ5qircV7ZxPs76fZ8ABP55iNLkKolczemKG9ZuTJ4/uPiNfis82J
+geMdvEUPSd9atxb3pLb3UgU3ugCr46v/7lS4qpHpDwe9NVQbiHSG7sEttvnsjbb6
+r6J54tb7IbbErin8nqwjBTGq0YH02iFBUGViobE7m/F2aFhaQe6DsNXC661lkuda
+G1EG4zOEbFICnyAIXC7fkRakWIO5pzEjI+ycEciCGb2WDWYX4amjJBuoM+0lEVRt
+hcc0zIigiUiKpqQvn98WtiolKqhsLzny3qx/+jMF20Hf9cDXwSDA6y+MNzq961C9
+ivBuLHTIYM7c+qZQRbH6FZfG4qmqu4/ezl1eEFmyJ2rRZYFKJaC/zWYOb0o7K4Mn
+EfzmUsgLgrZ1NRLDyvdEkVdUtoR2Gbc/tUN44M25c0EzkHwWZ7DelSYlgvOcG2vP
+p2mvmp4F9Pdj4q4pdylGrf0cMIKPSVzaenk5dOeAQvADN2zfs9lPW7ilGTe/Cj8g
+b6g/88A2KDl/M2N3Zyre/IYkd3n4KHNMto9vJa1DHMKd8Mm6QaQohuWrCGPe/tMr
+nNivL6F48dZeVspGfUS07005Gl9T6OEmcysYpOGvRPSNNWjz7t2jr1xmfmvaP5xo
+zX8Hu0n6QmJswj8Z9B4Ziu1k4CEhK9rzHT5b4pdYs2vatB9dwM6WeF9uLQkdrrHt
++sJ1YY4nZVLGrxgWkyayNrqRwX5m1WHSQnFIoEy0vcFHOU6O+awtgVGNGAy3G1dK
+7jJTAEGZL4wnTDD/TujFbBxQlR7wP/wG6fGzNLpioXlvuYtgNvYFJjZnk4Ra+zUT
+it5GeAEZFPq75wILOf4kPw5ZUyYDfpqGZwc02OIDm5l/Y6dY/XNmc3MW8fjvZBEk
+ydvxuIPdLSifOFrp2wptM2ylb+qAiWXTT/SJErwlQoH/ioEloZdG5erkes9gjWxf
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubCACert.pem
new file mode 100644
index 0000000000..2c73cf5845
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 12 49 30 42 4B 01 FF B3 CB E8 D7 13 77 9B 35 75 9B DD E4 63
+ friendlyName: requireExplicitPolicy4 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 subCA
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWly
+ZUV4cGxpY2l0UG9saWN5NCBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSgwJgYDVQQDEx9yZXF1aXJlRXhwbGljaXRQb2xpY3k0IHN1YnN1YkNB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAym9lfJRPXHcjzvJ5Yn3L
+WJQBzdL3kReoVmfz0fUk92PgyUtnYRyQZhOA4M3yd2/gui4ZSN/OdmhrCCmIzxE7
+lqjxZk9wSZhdrNCC1dJRuZ8b/nu4Mu/zKUyj4OtbvsB2kxHLgDDVvD610+rqgpRX
+INlRP03qpClgCRku72wF/cuxMYqtW8Ev5KJB5SV6PTCMe3IWkHb0H9Lc3Ux/fVgG
+HW91o6bUrLbrqLkECrlz0l2pZ7DOuZgVQA2YRovfkajqmHJRzJpDa2dqgtXmIugL
+lMdyeLG+Tv2mefGxnCotgiJoFJRg0rcooSt8sWYDOvyaFTZY/EIh4QbT+5i3bg78
+JwIDAQABo3wwejAfBgNVHSMEGDAWgBR97w6UF7v2p5fm2CJIQ0iss+66jTAdBgNV
+HQ4EFgQUqerm056wCZev5/4eLhAyoRBnTIYwDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQCqlr/tZaeY+Dfdr/JgHFg18fXEloYEoGqI8wbh5Uft00CMiLHIzQGl
+sfDKHup2ZXSTC9IIbEHIw7ZVdztkvHEuuPBSny9GQv4KaB0adliyVaa3q8oYmqBJ
+lgBoNi9Jz236otqmfuIuB/hjogNOnJJMzn+HYYgGdIWKiJj4pJ8CSesb/yx17Vf7
+XgnyPxMeD9IZeoPfdGn/7tBM4Mp8TgnEFlaOujydYEj04+EjO9wQ5jompT+Z4xlJ
+X5/mFZ1qhkxNzG2i4+aaRW13RW52bOzn29mYVBQ0YA8KIsWPZKqbTFDG9jEmdHZN
+as/9IXJP7bOcwuGUljRq8n9O/M11poPx
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 12 49 30 42 4B 01 FF B3 CB E8 D7 13 77 9B 35 75 9B DD E4 63
+ friendlyName: requireExplicitPolicy4 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,97027569E6B790BD
+
+Bq+FJaPlWoIvgpF9FW8QuzakNqq7a6RN4MNuGrH18o0kF4ZCx4kDaWnb9ipdwGYc
+R/nq6JpfJoOApizstVbizEax4XO0tAXiVtcLF5t0oCpXM0d36Z7RYuaCsl1am+MM
+eH/wvc052q6w3hembPUrjRXjSsXg2WLlObiand85Ej4VMro1es1Som5ZYpKNfmqB
+oBHcaLu/OsKu0bbQUdB1xCt8D3PyaMvkrYsHhyUvZwZY0xveQ2iu/QD43clI6xWI
+wXR1PnNswoEEyeyg8b0IewcWOwlwicTijJDvg4HWXaVrNQbkipu/H6BDiBvVYD/+
+9E7+vX4O8NDlw8KensBBPkcquIJSgKntiZW7BUaChCPi9EarHqXx0xV+6FTdzEVI
+35OGJLGPpQuXRqoldgBIG4aq9VckX9FX9qIJ31UibLxqqiNUrw5CPY5MrXalVF4n
+Yn2jpoi+OfIZhyuq23yAXF0br3d9nRsmEyo+8RdyravS8O13JIC+LlHSsRWfTYCi
+JKVWRJdpFtyiz79IpjYihZydMp10YWKH1HzqFsBXH6GZnK8LDtl/tdaHehrEZ73T
+1xiF3xgiMiobcHneavULTMqcCN3PJnVPyikVUO1esr7QSgM5DzwboX1ZlXTkEto/
+wE2XyeoUH2ASAouc/13v1q+7VzMYCvEGs5I/tZo6zH1YXh8nhpQzEBNpik0tnbub
+SGRmg4OVs/JyRXpXCW0ssklgGzn8iZOxxH8L/MO49q8i0ldtGN80i0UM1H5zgSTh
+nJmHCOf81gbZ+W9imu3fiDeNlIjp4XNRg87og/tR2ayOQv0C+j9GIcettK+oIjQC
+4BTRwLZ90+eqnpNUwMVilVqfmlXziqzeu5R0JUMG5bxg9SEjWA4nKa/7c5L9vXL/
+oSIWjc1xYR3TYT7hOg66RUYXsY1kM5jci0qoJc4doavOZlsxO9M25a1GcNuydqXd
+D7I3fxd6mqXvjhCrNFayMTjueTY0MP5ofqHEhqjBfjbE/jAyLj4u7zZGcK4o5BD0
+ML5VuEhnEQZeQBGH3HupNNj3RxXscVgPbqxpQ4o/c4NBRSpsZGFcKEwVREdvSeQM
+2MaEzuIkXOwv411Z1XlMoPetcvVxJS/JM2qqo85TVi4ysT9zKp/oj2mapZI+Ub/C
+B6l10Pjfg/eJExdqQiJoGK3imaim7hmQ0fLP7D9EM9e2pA1pltKTUBygltrOR4ju
+u5jHhwE3AINBfqeeKXCzyFWIH6j84a+51FhTVbHOe4KDoWZ0NdrcqNwHAQ5J1JvI
+ngDjBP16mVC5DsRBTJakywmAscfmWDvtiIXEzRv+ECB5MbX2fIaOhT9Is5HMkdM5
+NcurxeEmrENZaqfOGJRvsKu8UkAyATTA6TPUadlWgr/k37LffqBaUCfmAzlme+aE
+I4E5e50aWRzDdLY2de59aDTKVEGPh0IExSC8yIPVkkS39AwIzh4wrF7PNsBPvIh9
+W2RjUT0vjeKz3ZTMK6/zN7mVYbJbRUkE44qcxcxzqywnDfxybSxL93YFa25BXpPf
+/3IiBBCJOaRhK8IPodjWFqYvgDc+zGnIKdHN2ghJsXJa4iDpJt7vUA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubsubCACert.pem
new file mode 100644
index 0000000000..c550e7b521
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy4subsubsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 60 B7 89 A6 42 4A 53 8A 9A 48 EB 64 61 75 5A E3 F8 A9 C3 C6
+ friendlyName: requireExplicitPolicy4 subsubsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 subsubsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy4 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NCBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMFsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMSswKQYDVQQDEyJyZXF1aXJlRXhwbGljaXRQb2xpY3k0IHN1YnN1
+YnN1YkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2QXTxL+owEKq
+PE3XYLeNLP6gbjf+741GuoCI9gb39kj0UpkLpXi1lrJ7gupEhUX7E9eo7HCCJ8ox
+xuxAa/SgsU3DMLy4pEo1H4PuuhItPyqBzJxmj2urreCjMmU1WI3HiAjIIW1wrj19
+Po50djXz6fMFhOZhohpg5EPK6XP8KqjEkKQS+bcXM49z/LtTQabfZTOYiwtZn7fc
+dUjyGtLSCM+jnYqRgFRLjlDJw5SnVDc6X32DdskN53VPZDwEZEZZ+48gFr7kbj2A
+TZ9Z32MGBt2iLEWCsxuZ5cntdFlECaCtgUiyibp5FpjJv+WyXsudJrDMP5ef0duP
+tLn2sVw0awIDAQABo3wwejAfBgNVHSMEGDAWgBSp6ubTnrAJl6/n/h4uEDKhEGdM
+hjAdBgNVHQ4EFgQUFLvRJvSegTyLDhLP2XsVsizcoyEwDgYDVR0PAQH/BAQDAgEG
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4IBAQB4TRzPo/4HW8xacmWqsKY1hsa0yI99p9BoMHCdomXGM1Cf
+6lU+wBWpRbwS2Vldrk6CqHpSUQ0iw1q/+WB4dc3qpTL46HzxhpahZ6t34fWUFB6g
+04fL2oaRc8MNj0+dYG9FXo3X9ViBPJAP1A9o2XbuvBGAFjIIIL6TUxp66wfKv3c3
+DxF6IThaOB0Xi/eHNGwKnyYAvdoJvx382YwOJP+0vADzr1a2kcCJdqh5fmYbyKUW
+a57SRGJU2eAmHcoZbF4d6ypMuT6J/wzDyJ+0bB6AAugoffI/bsTcBbQwLaYMXbPz
+Dhd0Xl7qLcwA8aVcrK2oBmacpLhjThEizNRm7y0s
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 60 B7 89 A6 42 4A 53 8A 9A 48 EB 64 61 75 5A E3 F8 A9 C3 C6
+ friendlyName: requireExplicitPolicy4 subsubsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,315A515BD08456D9
+
+vRPKQr7EMWKvcFnl6KxRsQ3CX70buoRNpRxqnMmKucStq/cB0XJV3ECd81C5bIuR
+d80Pt0aL7b2vFzfRI9F2chU28l7Vazb0DGvdObiIII6RZ88oachBgu/bvoaxnp7a
+SBDf2uQyC/dTb31hDBwWDHTKcMVzUeBmfAwUvbV+pgrspcF5mCl3Lxo8QjkD7pcL
+h9GrQIizDmdfjzVlBG80lpBy4Km1K6F2CfrwnsLJRnthn2Eu0BlBrfnvgcp8FayU
+ThiLrGwh/dYiA1KQ+Z+YeuQdSx/Y6VbEFVENSBINfFKHkfshGvAMhHPo/9LqNOKX
+n8GNm4kexNoLW5H2g1zdUrJiROBWsja5Cn04Huxs4qlS5w+f1XD+GlyC5yxIEz7A
+H6WGhr2lh/dSXWFdf20FMzsPPCis7WXzf9H9gFnCmBuUC+WNOAQBNQgyuvJvqT5H
+ets4FchES3/L//5rXTJIdfZVKYukDzQ1HJmRfwXAML3gbiLZ1iWlFrbJ9BbTWen2
+ePhcsA/SAJd9V23lELjNNvGF+EFGX4ZOXutpCSnL1kQHu22qvuk3v4/gCMxsFhhU
+7rY1UnYMNarRIy+xFMGZFy1MLZVa0Hp4oTh52QWX1SJFeqO/nPafDxVgWRy03FNp
+3G4eu+zlNCR/TvasfjvN/OS/+Tj/d0DszkXU+Ts4Y4bG23s2tB16zFheuGc4NZFq
+u9V7h5xJjnsV6QG5Q6yFKIEFuQPTejtuA5S4R34Qb9AnWNwOnSW70+edcBtuu+um
+FT0Sd756TzcjNu9MducD9wH/85K66JvVtAlk1K4+lwgrLefh58W0P6wBxRCqZYgk
+y91a25Qbm0CNK75HD9Mzyobh/qKtI6G1ndalDkV/Ywt97NOpM11w1glTaDndxKzI
+2ztnDilVNuU3XNqvyQy5LR8i9MY9LXMvykrX/OBaBUMDcZgvl2IUoLInp72Q0UXj
+sEN7mYJUHo1oHtn23PTHyxkxvBeM6YXK2/MS+XwFtYMy/q9Aa1G7tnI+rzg0l2V9
+kSo0uYcY10ouVtJ/K4aXieXHBZAsIMvaWAJcUyPuiu4HOLlOGV5ts2T1TfLJtae6
+A6TRr88tz2NSNxY56gmGRFsA03Ohsur4c4oIULGAqlXVxdJOQ9bK5j1AsptBIgma
+QTEcEa8bU/92PFLrvJJR395QJUNWHPftJv5qRUNZKfAxFztnOeES2CIIg3XKaGFB
+6Xl5fblxAG1rxyempFXsMG2hqPLGLDDYdhQl9+VeMw/60rktW0xAq3Npj9RGLyF9
+PxWs+8u0KleoPwOJ2RHW1DH5L4pdctxJjWbgZbmKGs90IFVJgo3Uq21BG3wJrDG2
+174ao+cRB49X14E1EOvn8hP0g40issb5RtSGXQc72EMEGBHSoXEIv2Yr+F2kPNoa
+KY2aPjx+7IexAVrzzFxQf+kJdEact2M5WvAUJS+MOqFy7AMrh370R/nbXLvQPhi+
+qRpkrDrPsbumucq2KL3KgHJiCkN/aidtxXsHIzPA94R6PZtZBYYkJn6/tLPYJCT7
+WSy1Gi3yucjVQ6bU9VdomKOdpUsSkqmEwruZCXLxJnGgXDug9SYOktrKjsgh6xCX
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5CACert.pem
new file mode 100644
index 0000000000..d88c3d3458
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 72 C1 9A 00 CA 10 4A 11 5E BB 32 35 93 46 DC FD 06 0D 91 2D
+ friendlyName: requireExplicitPolicy5 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBKzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GXJlcXVpcmVFeHBsaWNpdFBvbGljeTUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDX64Yh0H261J0Gvd60y3m9dHEszgHONN7g8YYFETXH88aiScj9
+G2p07n7WfwfAh0Mziuz0j0fibq4vSjAgGbxS9G3WY0+oxJAAIo4wfIAkP8BTG94A
+qU1vFvGtl+Njol97tA3gxaaryyxwzzGIucLSCpH1pJwrVSuvh9FxxfCi8FMJ2P1E
+cQHZoXTXuZQCzmY/uKODbDN2uDzokbG1eIitBuAx0936wxKzz6Yjd6IaVnR94AJR
+gyL+QDk5Qly1I5blX99HL9svBtNRmUgeNZxMjnLfuXBkIKnSqrj9yJnKisQR0ci7
+ZxDtbJ3FEXfuDo9vehdmevDyAmG/qWJ63MkFAgMBAAGjgY4wgYswHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFLuRg6uurt5c2ODykDxc
++p8u4TloMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgAEFMA0GCSqGSIb3DQEBCwUA
+A4IBAQB4lgz3iN00AQ0XVL/Erti7xs7ENs/mzyiw3GLJgLVXpmVIgJe1hVSFNuEU
+QV5WpTfTn+pxLW2ydjkj/mkbgyoVGpAMZlGYGgN2WzE2vcDBJVOlayZK95245k9p
+ZZhdRhraZtaOS12+T3k+JVCxqGrKgLbVwl7Njs/WkXv01ApW0zzNi31sgnxHBNH4
+i/uB0OYmf47PwuUAv3DJQbVZhetCgbZ5xZ0cSCqh6IKjvAJw//A3/r01kurrYVdP
+aXRe6FAlZdZ+gWeWofmS1kL770TveBE34vKyFI6CIz2nC8gbEmisNmelNJz77/Tm
+v33K8gJxQbwn+0htOdqICEIfMz7p
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 72 C1 9A 00 CA 10 4A 11 5E BB 32 35 93 46 DC FD 06 0D 91 2D
+ friendlyName: requireExplicitPolicy5 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0A16FBB865455B80
+
+3tq2f75lU9TDEotyu0EMMvOmSPwb3vh70ZmqjMsfbXTfVovU3Bdz6IvTy1prmfKj
+moQ1akOTCg/hhxXf6XN+4Ik7rG9KJrH+40AfbGBCE01MHHaDplbepCp/iWq8Lo/j
+PlsJgoEmS5x/WUfae20Rh89WCCk2MFK4q4rEkimwo3sywuqsVuW/OEsAr5S/XVFO
+bJs8sUoOR89jl69wp0ZS7gI7G0kzYGpgi7UDPG5yziAfZLM8+vya2QTXFBK0QXDB
+SmPSRI2xlPE6L612YfXAADFQ/FQQfyB5FySzyCTVv3tFv+YMPrH7pEB5ZJdVQSIk
+fZSf13f9kXA0Nr4iESTW6BzdSeF7QzjPHOGtE7tye5YfPgV429BlU2iJgGzjmD+O
+E7j3987Ds0IuIcMbyMxbKZuSIa9E85G6NRZvBmUzhG9JxXz417/bBA4ULSyHzXUh
+j+hIvpIM9hX5MT00kaUcYpy+3W9ENw38ydK+Qy1AxQFHwoPDnBOaGkt44F1PXEPE
+RVFZAqRxtP6NNP961lDy5CHSh5WzO/PtMIxVYqHL+/OqpqBbz84Y5gPET6XMRhPc
+h8tCiMv6aoWiO2sWxzHMLx7sLx6nnNTBHSSKfJGkIyfiCUZKAayz8q/OAgYKZnI9
+dnQjC/PkXsqspamFkjsXClSjGuntQbQ4UpnKS8bxBIJG2b0qwu2rTVlqvXNLbyZg
+5tcJDJHazc1IycFZPYNr0IttDfKxFgyHZhdEQS+l6svlOTrj44NXrJWl0RuavoaC
++Gs3uffcsbflwd9w9cxeHSuYBNhO2LLIk9cBf0DAlM5pUNqJysFy8tCGSjqSHwIo
+oPRjltHsOUy8sGPQl84SU/Rd26ANbpWHox/y+3ZuUpm620BVmuGbS4c+PT2F15K2
+xZr3POVB4Trt3zPYeY6NQRiXnqcYzzOj0Br1XWwb34P/O9toyAh8CM46pjE3Blaj
+UvGxINMRy2YjJ6X+1i2DOeKUZZWILk1MPVYli7u8WNzQV8CJYHxH1s+Zg/L10sAf
+y7fMQ4a9V1FRY1xLM7H3JwchrZivzI9IZIhcybG948BLSN45nBFH4SskK38KKW1j
+qj2r1feNLcI04OyhAU2OxGIPkooszQfKZyu20u+OJY7YaqMKwQ33BjkIjBMq7YL5
+1wA+pRjGqr3jEzVhWbCQdhnhk5YQkL2FAG0SGfMh2XzVHj0Nt9OKEI/a4Ufrq85D
+ssR4Q3VyRAvw/0bhnEsBLqeEieXB17EkuNB43g2kanjwRWDYA2dBu1YDeQ5svvJQ
+fpId9pzXY5Zg+5upmRW+uRwtLRIdHkjdHGJUYzyceligAiXPHk/lWykiV+/yf93c
+PecHKjBVdDuPJROaZmazkag5amv1PP6/0MYpmVdwfMfSuHieToY2/csEpkkN1qX9
+xVFtL+2VZw36GLugmCY2uah8SYS94E5BbeBOqRbMsrgyT1sA3fGLgH8kF9b/B3E+
+G8caclyITJV/1Bu7y7ZpM6Se0RpJjl2EMBvriUhz9XjrxVnUcYSVFz9w6GIeE+z6
+fil5fwP716grZagpEa6Aby2AniEoezd40crCPkcaaD3T+6XrgaOxahsZJ/BQoCM/
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subCACert.pem
new file mode 100644
index 0000000000..eadabaf0e4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: A0 0E 9B 7F 7D 52 91 00 EA B2 0F CB 6A 42 50 0B 6B 0E 30 A0
+ friendlyName: requireExplicitPolicy5 subCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 subCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 CA
+-----BEGIN CERTIFICATE-----
+MIIDnjCCAoagAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NSBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFUxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSUwIwYDVQQDExxyZXF1aXJlRXhwbGljaXRQb2xpY3k1IHN1YkNBMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0yRFiPxcDa4VcjEIMjPxx2RaYWn2
+HDOXqGxX6L5+pD8PLaXGLExhaTdwWNy+/yDaUUHij4pdFl/SQsmwtpEvfBD1vXis
+2MZIsIGy4DWYqni8J6H2M7ofoafKyS4J5xkBh/Z9eBH85BmlPfJBSVVrR4zjlDQ1
+B74tQTVWvznfpaZQomyr4Z4pzITkLANvEGvunIXckuIerkxjsjx0XzXt4W7h5aIt
+b9Ow3W5wDh3qRwWgPgA9JkUQR+F5ZAZaqeZESGe72rTPir748IOqRKaoZPPh3IpH
+IZLbh3hdAknoGNUg39s1EzAG6CR6S4rOFYqJIBmpnreR0AIm7XmziOwu7QIDAQAB
+o3wwejAfBgNVHSMEGDAWgBS7kYOrrq7eXNjg8pA8XPqfLuE5aDAdBgNVHQ4EFgQU
+N9O/3txQx6/IiuiSsMRIYfA6BAEwDgYDVR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4w
+DAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
+AQDGFqeMi0qNekHCj90wnNUgVkw3kwGyufgAbqV4VvFswdL8UwRZ+FAD32d4Hvqc
+UYvrjN5TeoL3zW8p7czvq2bB8gDVgxxGT41v+OXd0uT+T34kArsJbi1nxA8GiZ9n
+xU+XLWNp3up5wZB92F2I9J1W6psSxdPH4aBNrW/mgpckhimz5gWAOHIXiU2pB9R7
+JsnRJ0VxcAtCXRWqeHqgcpeDl5cA0ImOVupvLOiF4o7JJ/+KfAlMD11Wvp8dcebi
+S+1+mH9eod7daIN/fB39tMi+aTELILUvN8rmOz1COjN+lyVpZCbmSCo8wncNcT0B
+NEdgddMknERZ9SRajlmnbyTv
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: A0 0E 9B 7F 7D 52 91 00 EA B2 0F CB 6A 42 50 0B 6B 0E 30 A0
+ friendlyName: requireExplicitPolicy5 subCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4386478E7A1A6DF0
+
+w8wdVsuYUFkdjd3NS19wckCjlmHS4FtkNbzN8g54ryAPmjtE65HMDb7bIWV97L2A
+iYlIUIAjKQBb1Bya6cqzOkNUNWtxzvWEjlzM0m4ErAW1rCLTZmqguuqk4Hf0N1yl
+veR8mqfHk9EN/LN+j+68N2oXz5E7kcdiylkwGKImbNaZCGLJPiK+SWK/akBkl7HA
+QblxnSpuxSJ2iAr8Y/nYfplPOJBGM7APYjh3aCD0YcNyO6t1F5BDHP1DXsKmdkRJ
+y7PpMMy+qYIk+4XosI/TSl1ikTuQvU1cnAfyQgrYiKAyFXO6M3e5dzBVuq/dz9MQ
+CDQCvHM70D8QB7GrUdj7XsHQwPGWUGN1kFpUyHmwlqAxArX/sOode1DJnX/qOFTt
+rltOQ7bAJIly2EvMGmiSie2Xhm0sBeatu+jyPZ+HfFRi6CwO4mkL5cjzXX2esfFU
+/LXmXNcCNxby4jpqlJRdhwN2dpLueqj4md1y7UM/pPTH7sXz3cKM5lDkVRpRuqm3
+zPN3ttgJ2R3hzjbASdzk2HECSmhTCbwjw4qUFEM2O6XOmVLvwtsHB7u3IFYQE6S7
+5F9K9tBiyU/J6FMncJERJOtfkT7fZa1LUUSJWUqAYGY8KONsWs7tE6LZ6CX6dxjq
+oXr/B64pMHnEPGhk/44bK5qDv1zi4r2vP3YOyV/owN3hEZNCUU9PRK21MIBXs1hb
++XynsWhRWUU8W1CF60fyWl4ZNvmJTocdKsPNOIM/KDUfzfFRFF9FgyPi9BsuxB1L
+2VRLcwhPVm9+SfDOarPgu4Uhfb7MdqH1cIitrUve4EHZHBZbQzwfuOhiMa8ADStU
+uaijfAVczRjp9ZOJIK295Rc191SzNifbaFsIrDIKG+z3B8JVmgM3jVZR4ypZXYe+
+znvMNSOTCDKvnHUztUXX6/ZSY3fBYQZrBhblQ8Y8wT15vFs/M7+Bqv1v5YNT+rit
+nd9wZvyx+6fIdAPd/ejpBNzdDLSuLRBs79CIpLxOtxUn2WBtN/FsQPIqLUNdYWJZ
+vNgJvpFJx1aMlEzV8OIjt8acWDSdcy/nAVGuLX9Pw3BP9wuyIfo6c0RcYMWKBI4h
+ANIrEFEg7FVhxzNJOuJWrJEM772gpPp+SOdvDMd5czWpyx9ENozb1KpRiL+9oqKf
+IoSOHEfGzcrpFSY/RhkqGgaNVVcurDtHjAJmxiYxOCqW9jj//54HlQKNkJBN1y/w
+1ZCBPPGF0jDagJduq/4QnCRPAfQwowPd5DrKLnNphyQAd76115WLQxjRyk0IA58+
+i+6Cg676+kuwAJNmafijoho0cx2Q8jq6H0jFKJHX8aijQp8htE84YwnJKPWGz9kz
+go2LOkRzQ4YtVBAGJPFbAm59PKMBAMoqPXcUVFX7fcYiuikUOzksMLSfA1OMQuad
+385aOMHWLRZYu0GhBoxffzJo5nXWiYJuK+FO47ArP25bC8bx2Qp6nhgCtc9hXHlB
+WOvJO4RdFzOivlHCs4jcsNpK9l10D3INCGTFVLFokV53S3QtEGqCrwBoEJwiE9zd
+8kvwplXC1h1zgGlqZ2bzu0/ttMaZjJrfI+AyWi50viVJIaTbHKkn1F7m4WF9fC2T
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubCACert.pem
new file mode 100644
index 0000000000..6446c7c306
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: F8 F5 E6 7A C7 14 1F EC 35 0F 9E 6D 11 C4 79 E0 67 E7 CB 2C
+ friendlyName: requireExplicitPolicy5 subsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 subsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 subCA
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWly
+ZUV4cGxpY2l0UG9saWN5NSBzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMFgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRl
+cyAyMDExMSgwJgYDVQQDEx9yZXF1aXJlRXhwbGljaXRQb2xpY3k1IHN1YnN1YkNB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5osj0pPsQd7VtPH2r3xk
+y+cCCrZpVCpWv79iVHsYL+FvNRoJcoAp4YRn5TVxL0tcaQ9GVUEG+mh8JPyr222D
+PGnPiPKTNYyurrIouh70B1C6uCdQ5tYQiE9HS7WEvu9mPti4qVWcIurhfKHsvYAu
+qzY+4UNrno9Qz9kjr4tYr+RXxHcby2TLXlvEKzgG79XmtvDW70tfiQhkQBEHSw04
+j+dnUlhPRBtyYrXoAkDETKYK+CIso8/0PyDlZNqu8fJib6P1UVlCnsQ556r7cY4L
+bjU4T49L36Y24wb6/5gKFBQxhvt9gsGUtNM6IUPtSh8MbiRXgHXmZFf/1niMiVXW
+VQIDAQABo3wwejAfBgNVHSMEGDAWgBQ307/e3FDHr8iK6JKwxEhh8DoEATAdBgNV
+HQ4EFgQU+IIvef+0fggC21uvMp3kNWG1bBswDgYDVR0PAQH/BAQDAgEGMBcGA1Ud
+IAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQA3toFMuFLrY/uxv2tTf2qtmCp5JJPfPdZYDmGVMEYlRJqX4IUSq4Ua
+/YxDTGvdP74edOEmxgi4cDDY6Y1l0lgPT5qZ4J/uXhuVAull3UPnZYe+TIFf+VEA
+ZKoC3JOf8A8+gFE+/0Fso7eLvI7C3YlL8BIQjWkfVylfXcf6wTk136XlMv9tKt23
+lrVqqs3WHBu7jBHYw6+hUF8iv+1DRbLD3zVmrr3MJb2+Cm32DFvxujt6vAVuo0wP
+bYUV3vF0QIGBgGbUmB4inAgmHYSiUmYzvkg7g8MF2pAthk20eK9lvLPo7PS468l2
+kguCoyCmqySucoSul6rNQ/qiDhOu9ucf
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: F8 F5 E6 7A C7 14 1F EC 35 0F 9E 6D 11 C4 79 E0 67 E7 CB 2C
+ friendlyName: requireExplicitPolicy5 subsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C03C65F9F917F617
+
+BhZR+T0kYvoZX7Vc6PetT5t9L+RQuJhBBIBR8DNT1nLfR9kO8QewffwyLukoUaPP
+PQzf2BS+V9k0NHHDq8j68uLg7S89+hgwULvRsmAFIgjWAHDwheF7chbbjY/BQzjW
+S1SH9zcJ9TnvlCrfROFxGuRCuiVsr6WIVQ27r6U0egm9FcIh1pR2NEtVG0vFahch
+UIAgNW/0hS2Jp0XfTtGrmduQCPGlVtp13XcR6mM1MVl3j2nczRtjnR7xZFwnEO4J
+J1QvXcyL15Y+MmUuUSLTylWMH8oijZvf0iN6mlhYcG2LiKt1c3PMHziaRlwQuyhM
+lj+iT7ujeGfDgsslklCKRjlWtC5a+5Wb5FM0NAeg7gCzC8eUUwULv9N75IzNJ5CU
+fc9tQ0aZh0BI0BeqPiCm6llxAgtPzEPSunx5atvPm3zG+2V71ic3MdGSKExutPqn
+jLzTdchCXff5lVcq/GeV8P8z3d0YUHQwZk4bpPkJlalHf+85TV0Ta/pdBNPng4b6
+MmLVdhVz2I3nurmt3Ogq7r36fqDoZxA9F3eacCePu52xtcQEizK322HJ9H/gP9zM
+qr25/idjWnrMJ+UP+BI44/AsXa9ohQ6Uv2+nenfsn2Eqyneb3nEHe67AED8dj/Lr
+lKdjV2Tz26Goe6aGuJueybGzSy6v1nt03vpHQmnQituCcZOQHiKYXDu5xfTQA29S
++G5BFjRCtlK/YWUredYe2rJRA3xPMAoFYZHB2VF+8rkDA9VyFCJ5yJVPaqtD/5gl
+Dk0OQ9dUEkuNQcs0PlmMc9ioB5jGjedgmfKxOt82RVhrui2qR888hrilpG+hTqBF
+YwcUqXBAmuJF8uOHTSYq5OUOGJwXpjjnpKDAHNFzC+MROTqqMb2azY4Nbgts3b1p
+xaXEIhBkZGlxwJBPrgQA0LBTDUL15s4bVBchwzvLxCQzoGlRrrR1AoV1VjLV95XO
+L8ADI9pShQuMbLj8LlK8X9edhgqzz41GgICXFodOlhbRs7kO6uHgPRwfIE8jEtgW
+B0sxXp0jUwgou8X3OOUcRw1T1oIbYemPLPRYR2lEE5OF0k8Auep3HUVOKcXBj1Sg
+AC9kUhoAtToU8l+MyrLGTVvC3sZzLUGJXl34PJ4SeKdddZGu3TmoOwZxk3u4jAT4
+dmz/bR/airM8W/zt2pkfBvRuA9Gfmi6+FzvatKSF8TlpxfuH3lcq9fLMZnJwvhMv
+kYFP25oWIZYQ9zcCUtjXKVdNRmc99cG4y6htXthVZayLfqDEg7I2MeS9s+JLIYtt
+uzzQRerb2O8sGcYPJxpprNLlU/WGH6ia0qhycB7vop62OyL/DhGiX4nA58bTyS5V
+GSzMAN1AUapVZVG0Ew2nhUlV45kN8iINKJl3o0PE7bcdBw3uyiOei0E6PLesu9ps
+G/bzx+5by8J+RppS2ZmEGFhBQNi2Ck41Rgf4W0dOdQMCy3m5euiq5v54XLaE4r0M
++vR3WSrMEgqo+8kTa8Jp8V+cru5s6meMc5v0M7OXG5iFy7aGgsomUlgUqeic3M8s
+0OLyeR7Q/NKfDrR8fOfd9t40SjPGbZIYjikT22gVa7WRXJsXqzICB2gX8b5qvx/+
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubsubCACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubsubCACert.pem
new file mode 100644
index 0000000000..fb8f1310a8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy5subsubsubCACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 61 DC 13 73 F6 5F 7B DB 78 16 A5 9C 55 36 83 A9 75 58 01 C9
+ friendlyName: requireExplicitPolicy5 subsubsubCA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 subsubsubCA
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy5 subsubCA
+-----BEGIN CERTIFICATE-----
+MIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NSBzdWJzdWJDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMFsxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMSswKQYDVQQDEyJyZXF1aXJlRXhwbGljaXRQb2xpY3k1IHN1YnN1
+YnN1YkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlTf1ewQJZhIh
+4PmJ+VD3TwcCt2e4mPpSH4n3WMFIhLPk4cLQr67l4TjzZChg5ok1rhb8RrOXjf6L
+bL21MMx9nppk2WFfysWeYCz0qvuYH0UAUi2xze716rwNDotvndDSV9bykKjGOws4
+PTDvwBNKdIcPwqFxPdbqtGOSVNxOMwvQ0HIjIekLxizD549oZnT0SX7YX7aeagCb
+DJQ2U8MPbUltLSdyu/efhftZcE9PwhG9ubvu1Vo8J9kJkzN1BxXW7Ea9OLvYl9Ce
+157zMYPTgetX3HBUUyrKmhoymSOoSeq9rRBZaORbO2Xhaf8txOk6yQuBatNMfdNv
+R9umR8B+MwIDAQABo3wwejAfBgNVHSMEGDAWgBT4gi95/7R+CALbW68yneQ1YbVs
+GzAdBgNVHQ4EFgQU+mK6vX5eX98fuge+H3k3gtz8EygwDgYDVR0PAQH/BAQDAgEG
+MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4IBAQCPwnR8ERgKeZGYVBAdVSA3u8LTaxB1TTGBFNoTM2IzFMI5
+xxmGkXSBnQUPLiGNAOSYuiz4TqzSZYkQvOYQVCowClplOKfi7jZfIBsU+EJOaX6u
+ofcsrBmdY3hkA3MohlkWTwJY6J9O4OloQqBKwdFDTGnbeCk+ec8NVpBR2He9Nn97
+XT3XrmDvRJUYH4Fi5mM27HIIo434Ncjm27KkEy8t4Ks+SXSMHBOtS4BgKivdgSBM
+TWJbYv8vHbWBnQhFGbz6WD9yenm5ho4ejZFcIYGq9fJugU7j1NNo1CB7KIfCZW/E
+Xog1n/lLdDgziJj3sYx6l2zR95MtzcdRRKlnyE3j
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 61 DC 13 73 F6 5F 7B DB 78 16 A5 9C 55 36 83 A9 75 58 01 C9
+ friendlyName: requireExplicitPolicy5 subsubsubCA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DA968D2A17EE20BF
+
+D0KUSvUxhPDCKA4G4wCv6FeOhZkwjMrxzYFpszxFEAlst7NmouwjIN3OPfHmt0IV
+G9e8/urZwBffHkHTVT/VYDur2dGoq5UF0/qbAcBq62p0RsSkyIOcGBf9TZfO6aRR
+VtVYdt1wyBTxLOLoqZxH2oP6KilW2dI8+Ca1DCQRJ1taeISCyvwIOG3eKf+DvNmp
+c5/jc+gq/lVQxGBLoeJrttJ6mydwmjOeMzG2f6OOpTwWladjkZaIdoFFnOGPk4Ms
+jyWtDa5GFhIOAqBqtg38Uy719NEZKDDuJXC1IXFwPBRg7+gXY27GLgAdqgw5yunG
+Jsl/zPYkxUFECVaQ/ZbHbw1DzVTMUqRuwPrFMeSu4/ejHefLNbNdH56e4coovolw
+vE/92QRYa3VDILfNpLYMFeLW2LwmM5AtUNAfnc0MJetpbtWaqDR8gkZ6RXQMLUlg
+t9js5ByTtYnjVK4jEdYWDTKlZEfK3wzhet5jSxJ0vpN4N4xoQtedeEyUvLTf9WX3
+O7p55GM4hlt+9istCVR8b1MGrEYD/89y8cG0Vw7+RYet3THk4yukiffkmL0ymsWp
+EAnXiDtJf4dCVUe9j0DL7Vr3blk4oefrkgaEb0V3TiptJQDKtZqOGwOtEozcxMkX
+x8ep5Sx7xBVCOSqX0bo+5J8MbSib1UmMC9d4ifi/BN4PuJSQ548nSPzlXQDaxKl/
+QoJakS0ZrVyzz9YNQ+LCorAx7V9JqqjhDDYIAZF66lGB1AYy5gMTGmpw/hM2Bzsy
+DUt61k30JTnWS4KeWCES+w/BawXVlk/1EK0D7iWVjnqd9NZBtdjKrHLxm8o84QFK
+Z2xkJ6o8hunJ5JaF8wuSmacCb4757W92vt0Qoo9ShTYAIAq3Oj1LCF4zNl0lQOzl
+yCX+3uv7B/VU66S7HAd9JgyiGXBgNCyFVCP3TerpOZjX1ErhkYlE46NAWzhTyYed
+E99Oka4lN5yJuq7uTiZR2dh18HkseQMmj1mnXYEIQSrDmKDmJI3Yfim3XFmj6sZC
+3i754W+LJLkBEqUSxLtRix/FWR+N5/MkQtTl7VP/Q6tPOj1MYhpV6I/v7glwKQjh
+hbkVPA+BdkVbiDWO856JPXmOAyXns2ZYbhZD3JPGrXP0+dLB59Qz4fYr7aO6cHm/
+jJOFOMkccee18HVyvJp2JUy9ji/VneV3Co40mjAfQcrFfb/4nBgKhaX8igZCpFtj
+q61bpizO560T8++zdAwUY6jdvdF6XT+t7dLHF4NB37RsfwfBxTSNQucJDrcysYxD
+svZn54Bhm0ictsuKMvXNj3hzfUWDlhI7kN/bInbeml3Q+wEwvcUvLjA8bWsS8W7G
+rmBnqj37zelEDUPf3ir3U321nOfNxNoyGTvuRbIlstno7kARlq42hnOaSVHOpynX
+/u1cxQhj8aChKf67nF2dVORVjNduTq+wy+dpT3nEp+CFtOrHpRKm6s41g6Fgkg0d
+9Ssanah1cxfEB3u1eUGQ1/fOiv7EJYTHNP84ukKlbHGMC9MU5hjD14zfrl2cs1Lz
+4E6CUePJvHXC2AF6aqfereUuzPyNFZG7crpMZqvv8QEL+817TPHCCg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7CACert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7CACert.pem
new file mode 100644
index 0000000000..fbc3e78c67
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7CACert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: E3 D0 9E DA 0A 42 63 D5 D0 EE D9 43 E9 1B 60 4B F0 4C B4 C4
+ friendlyName: requireExplicitPolicy7 CA Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 CA
+issuer=/C=US/O=Test Certificates 2011/CN=Trust Anchor
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgIBLjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowUjELMAkGA1UE
+BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAMT
+GXJlcXVpcmVFeHBsaWNpdFBvbGljeTcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCpVKpHFxYwg5kq0aETF4qFIYC1k132i1tnGPJFaE8s4vgtocrS
+wVS8gZ+IUAcAobfNjTFJqLkg+Dir5O+DrUmbd6+DIrw0EJL/O57bC94jTI01Cl6w
+O1sVnY9ni5yFDZGQiE9iMBaJQ3UBrGMSu3pT4lgV0FzEet70qnE2T8irAWid+7+W
+9cK/RatZKF7F/QjgfYO1giZs0S0bFt+j4jK7ZQPbYbnLR93hZziy0di4qnr9U2vs
+ekYlvwNcsjL7H1SqtCo6bwxL7jXn0GTpZz2O5Pv7J5xe69nW+9uULcCmYgASUJ2u
+exqWd2b15Eb/6qnnoPYPojIwmyuCjG6hVhj3AgMBAAGjgY4wgYswHwYDVR0jBBgw
+FoAU5H1f0VyVhggsBa6+dbZlp9ldqGYwHQYDVR0OBBYEFGwxlwE1IN7bNeUKaVhZ
+iGTMIc5KMA4GA1UdDwEB/wQEAwIBBjAXBgNVHSAEEDAOMAwGCmCGSAFlAwIBMAEw
+DwYDVR0TAQH/BAUwAwEB/zAPBgNVHSQBAf8EBTADgAEHMA0GCSqGSIb3DQEBCwUA
+A4IBAQB0FCmLk1xVqT7ECIhn+PfIXXQ312OWKRKqZurBCs8fMa8zq67GVBFi2HEo
++TwXaN0u3G5q3esDk+20ontt7cxaTx416Lnd1i+6+daK3ieIbvsX2yE/f6zxmRwg
+J4B5UTFm9yrhJHHn8JSyNKNFe33fFHWcUM0MuRfRNK5O7tawg6HlILr/hbPvO0Ls
+FbbJZyAzCHBqL0x9GS7pyFNJub3Y6BjYMLIvUNKbSaciw/rYLWEuV1uVyD3mC++4
+a2MeiCdQfFDki/xaHElme7qkiQeEDaUXCjCQ5m2Bhl3SMo5g/8SVDs1l/012UfsH
+uT4wf2kqJcmh8a5OSvuczLgsCqFm
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E3 D0 9E DA 0A 42 63 D5 D0 EE D9 43 E9 1B 60 4B F0 4C B4 C4
+ friendlyName: requireExplicitPolicy7 CA Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8DCB8DA039F9C4A8
+
+5gssmzUJAH5iKUaEWRw5pmlzaGZcN8Y3QLoTNDmiylmnRI5djN+PTc7R4vULMK0u
+9apffAlkJYqJPaAHeBcn6KkhJs/GYzT8GKn6tvMIKdLoC44Rs5YLz97wy6QGwnqK
+ws9rg6m9qvOHi2VQjVD9c+fox/9loZBaNBXF81XyvPeQ/rghSNrQTM7OXEeL1bto
+7EKBeX9CR7Q5X/DGq3+JGLpX4sFXdZBuIko7jli8eXGfl3nms1P9O62Wm/1bW28y
+f8Ku4MHm4a5yQg+foK3lKiuYQOCleyGu/0KC8f7h00jv7vGKRQKD2/vtBMbCCDmR
+tXKU6dE29q9gZxCsw/EUOJWDk4wsn3UOV9OMBwTa0zd7JtDDiLUyMyo05u8rSzHL
+FdVQr2URgCHZpoWdLx6Fiyw9OY5LKyuGunlC5PJBuzHKzCTgBTArfvpckoJRx5Ly
+fXhpL5I3wiURk6han4kiezf0oih9quxwK1hxy3jESuH8dpOXzzrH0uMbnn/BL7Rp
+hqgbuyFYluRHcLcaz0q3pzrkp/FFzDUXhqx8om7pny85U/U7JFU+kYAWWKb0LA+z
+or60GZ7YRl/P5cxkC4x18w9ltpbmweggKZmtc9oqTz9DvtTPjDhHvNYubdqJ8uZt
+NBqxLPciXzBZDfaw0zFCzZgShbqPQfTtUHSZ7ab6v/V5eFCzajGqQ9YE1MsMGZQX
+fIOt2XtllXuBkbMhwtYDNIo2quKpD63rhlXcmH+XBuMJdCa965lYaB4BxCFmpTmu
+tfF4RK/PCuuJYZIuZ0/gxH3PMQAF6agDdsT7r6eXb4IXgTJlVzb93Lt2/hR65ivg
+aliJOsyMkMZb2lbgGuGp/kZFMSdE1dpzeIDG3LiJjZ3GdFfCZA1rQ4HmppCQg/UK
+Z5j00OjagCElQnmVf3h4NDO5ipacVGBr1F0V4qegVbd76fi2i7vtCrMbK+bvrE9a
+FvzJMN7Gts+pWpHv395nk4lZYu0Uok09B6P0xe7ep777T9ckJCzg8KCkDPNCkgBZ
+1+WEVg9eKaPsM4tzWJ6h3cZOpuIMOqznyp/TzthKI3RqLmacEQiEr3PeAWRHemck
+0S6TvoT046ePKDdcmb5EEc4FrDsGG99+LquEzKZtumhxhB2mUHANl9YIf6iuqWpC
+eb5JJKJIz29cz1pPc3hpZ0XjQJsraqewbli0z7M4WOnDBktvGDz3x74qs+n5nOpq
+CQ1I/T6OQ6wj1h+31C4bUQfIuWH3oYQELGGNjLT4nZ5RXL4Ym2LSsSoKclYYatl8
+9wGTJFRxcotR9RK4yDfYfEwLECYgapPIrvX6NfZb0D2e78lV4/kyBi9xn93Qvr8v
+gOpEDiZOiA3legMirlfGVaVCtDu1jZ/bwPXjV89r4akjjV01IL2ysqDpHW1WvKph
+beOg2R+2OlsNas9+9b1nKWrcsvwHFsmuvD93C6BAjIc8Tn/St4DVLd4O1fRZ5b4x
+NiE96G2cJUm1lRwIQjNENV1U9BoxZji1sPDlyKKykuhkoL/c73M8bhl66foyNkWB
+TLrtUA+9pCsRt+8hpx5DtNCKWege6jzV10Iimbi53UmptUBuauqJWg==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subCARE2Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subCARE2Cert.pem
new file mode 100644
index 0000000000..5e563a8c22
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subCARE2Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 88 72 F0 52 A1 91 20 D4 08 52 B6 2D 98 EF F0 34 51 2B 4C 33
+ friendlyName: requireExplicitPolicy7 subCARE2 Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 subCARE2
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 CA
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApygAwIBAgIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NyBDQTAeFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaMFgxCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAy
+MDExMSgwJgYDVQQDEx9yZXF1aXJlRXhwbGljaXRQb2xpY3k3IHN1YkNBUkUyMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArNCCh87bZLO+YSdMLvfXHSR9
+pno7RfOAsEKaiPo2ievBaYHZUI1eXBOi10V3Klm+WZ7kGRKXr3ZjCxBJ0eAbUav9
+htXPdQprkjHS6+PfehpUiZvoe8JM1SaEIk6ZJ6hZbWQ9fL7xsCy7M2t1mPnFuN2i
+23TbHRIOmkxCD9NJgDqejNCN9O3lqjr+na978Irf3ZrSK9GZ9LnopXBcg70DcTMg
+TcuCHfPuvRyciClvMAFUaUvMH8POVFa6yDriD/ArHXfc4FLTFaLMN57lah8ft0uN
++Ec1tvqnSg7mDcHN8jdyj8Tu3sjh23QHCyvlKJUjk2FwLzmaDvhn8KIS9pPVBwID
+AQABo4GOMIGLMB8GA1UdIwQYMBaAFGwxlwE1IN7bNeUKaVhZiGTMIc5KMB0GA1Ud
+DgQWBBTnXCWOfqpMd4N7w+pp1seiNOE0WTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0g
+BBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0kAQH/BAUw
+A4ABAjANBgkqhkiG9w0BAQsFAAOCAQEAohBJ68sra6KMs8u+uyx1e8HRXv4rsIM9
+vc4H+OfqE3OxVBT/xX9QFx3QtBAKr6x0BKRZAxQwYi4bCZilSUDbuE/WF/fv21k4
+fVF4R2W9uvo8pKwizRr5/cPEq/N7tWtv1YhilcD1ET/k2RoEIUtgsOres7iQ1DLo
+O1t3u69jgi0UCEymRrzr/JPW9nLSkNYvr+M3noFfsYxeNb81l2Ma89tOdZ4dixNc
+tsYCgQ7DP6IEDdCpUxY9iEjnZHYGW84jIvGNQ+ASlx9R3WNuQm8QThxbdkAJhDLG
+PhoYnJE7zsZXFhvQGh8KWxPCN5F04yl6mEAGE09OU9fv3qOqzLlgQg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 88 72 F0 52 A1 91 20 D4 08 52 B6 2D 98 EF F0 34 51 2B 4C 33
+ friendlyName: requireExplicitPolicy7 subCARE2 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F19325DAABEC41E8
+
+92uaRXF4JM9Xmi4dnmlD1QuJMcjLvnIm8xAtEko1OhxzgQ6VL0gwSSr/iMPXBlai
+4+TQdxxeFdIuuqpQMLbgn5VRUDwdN6SzkOHUniprKg+y6w5y0bRewWt/X3uUGIOa
++snj54weqp4mBHG1xAA+2+gtMUvflPwdeY65oDDk1meMYQosY1hM5P9CdgAI59RC
+Hgnc7DuC9PLmaYRQiRTx9BczFmNGXgXfMS5p0rRHD6S/U1S+T1IgRZ6nTo7rt1b4
+JqJefEGntINg4nAClAkf1HtBRVU0diZeJr7DbPfqesLtjSDJRBujd8E07W7DQkZ3
+ZcYOqcchArUpvW6zZsu4hdQbe/jdn8GqIZsdhVL2/Gx0q7VJvtkE6yzlq0/LqBj3
+bJ/0zqG4Kplbkt2p6Sc+QrzjtLU+qOtC0fvSPJF4L2Vjoxw0MNPR9Xa+BgC9T7oY
+2VH8NYnAKpUe5Jqnr1tGi+9IxXs5kBKIi2IdOzfAgiG9BwdMi/PMkk2ciyvGqxaZ
+w1lrGyKWI1hHUWPz6dnEUIoJdTyykqAgVtiMzy6bn0lUID0Y/bOySjz1D5sTBUd4
+sW/MHiu6rX108EDv2Aeu+vOGWWzIehu6t0CWLu35C2AsXnCF+Eswyz18hL7PGo55
+NmO60l8GcWW/ToKyPqaD9O5sOt8KO6yPnOWC3JMFzac44xfAHOD5YXJaW57y0QsT
+59wGEsSnYUEROmRgTGPHfjVpqiQTS6BWcaI8a0SRZedGl4sSLv9np9iTP7KeC6hc
+hhNnnZj2RHK2miYbn0RX6ent/F1k32F5Fqk4vVIBeECaiesh5O+K965H5ai0eGzg
+E5kj3j7J7vi+42eJeib8eKMtvrwl/FUeH6H6g9rTWfeuCHoj1s8khxDGHKBeek53
+cTS+uKdeE1MagCJMYWINu3DKGDHBqqjKZUW9SdqmpXag+xUlG5Jr/Ka1mQJZw6Zq
+Al6tczN3uKzEtEd+yKCAvdxco+kwzcM6mlfIgmidlb0Yzm9kYPhNGCYjr7+daeUm
+fzkBmTsVOsRUqBiZf6NCI944cFsXw04r6i3zXVmv8qtYLaWN3kc3FvjxPne3AGeO
+E2fHK8HFHBvtaChebJ1SoW2gIlxY7goRJdLz9Cq2LoYt/eMNZhlCv7ma/vG1/Ri6
+WdLo/rO8Sw45b2yblskNzVJM9Qkk1IYhPLa4rT+l/DYDpxteAiU9SaruXRdNT6An
+/xipbwF75qscet72Z3c0QA0wGZC7kEz8zCVqtVHSlj9LTyZPWcEIjbQ2ExYYffIo
+jrkBXk3w8ip4aX6iPti5RTIk0CdTQLxbizL/UWtqv58LzChwh5Ee5jPh4CUkkRGm
+feWL6E1dOTpSAbG/tcPczfDg/TQWpsvPi58IwXHIYhTeEDOmuhJBTwtZTfxcRYDg
+AfYH0lAdtF+pYITwueyZyGKFYUQs6qocX9tLcLl+LL4XvJcXibYjytCE1lqJewCT
+f2IfCzfv3h6QxwDKLs/vgjT1tceU6S1Awu6gS7agHekhU44yfF4+LUT8uVE9nFp4
+VUnVMnoe2x/Ps0skruwXaBusvPkZCUQDmzIJFV3NlnxVZ8vHbFkWeQ==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubCARE2RE4Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubCARE2RE4Cert.pem
new file mode 100644
index 0000000000..107aa9cf80
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubCARE2RE4Cert.pem
@@ -0,0 +1,62 @@
+Bag Attributes
+ localKeyID: E2 B0 02 FB 6C B9 1C 13 89 78 2F 51 A9 ED 16 BE A4 B3 6A 0E
+ friendlyName: requireExplicitPolicy7 subsubCARE2RE4 Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 subsubCARE2RE4
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 subCARE2
+-----BEGIN CERTIFICATE-----
+MIIDwDCCAqigAwIBAgIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NyBzdWJDQVJFMjAeFw0xMDAxMDEwODMwMDBaFw0zMDEy
+MzEwODMwMDBaMF4xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmlj
+YXRlcyAyMDExMS4wLAYDVQQDEyVyZXF1aXJlRXhwbGljaXRQb2xpY3k3IHN1YnN1
+YkNBUkUyUkU0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsKLzquG1
+Wxpg7dOJrrPXsuwroWJcJ9q4XcofFyo8PWBu3Yt4H4H8rEtQATDnOcorYd93IcJx
+ycuxyZwa+PQEGZOBZYAtxyicombbYGR70wJ1Njxsa1oHKe7wFGd6YdMB1xbFjNqx
+w1umyI4zvGR8WpfA0sEUilIF/sZCcErVTk7fDNi/KT3BLyyDmQ8sHFhQqxL9i9FA
+tHLHaZ4zyH0HgXGgUEqblgw+wsWWRQVP5AW12UaALGLn4ZijThUihW5H4Khx7pcv
+Xq8oZsLjbWa8wR1NNfeZxyd5qAyEYKf69/53vKjDlcDCaZSuM+Av3r1x56+VpuTo
+37CuXylUcS/vewIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFOdcJY5+qkx3g3vD6mnW
+x6I04TRZMB0GA1UdDgQWBBRu/40Ii2b+m6V7+2QzZeoDlUiUmDAOBgNVHQ8BAf8E
+BAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8w
+DwYDVR0kAQH/BAUwA4ABBDANBgkqhkiG9w0BAQsFAAOCAQEABhL0Q/1K3/hsd6Od
+6TGkaumY47BYBh86RHtxAoGKXecsotYO1kdJXLQsQOkEpLp/g5Tj0WL2YqX5tgS1
+r8fkcfAL1+Mm7vq6UEBd0S/wLZndMJ/Xjvzpal/o6iujqIEkWZZa70hYRcN+Q/OQ
+azhPsDKAm4I48xaRKOorCVq0PAjBwRia8MucOcoymmiQW8/wQWS3fMRj1gh3DERE
+Y/6TLeib5pyH1KYXE7W7dA76K9SzX7TlDOFd3xybch1UxTrz2I9cqbjQdDjJMEYU
+W8tFdCcIk1/dr2faOuWvKkOw+AQRKciVrPTRcb/GKKlnNhc+YRx3KBBs6D2kjM/O
+hsObrg==
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: E2 B0 02 FB 6C B9 1C 13 89 78 2F 51 A9 ED 16 BE A4 B3 6A 0E
+ friendlyName: requireExplicitPolicy7 subsubCARE2RE4 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7F1D317ACFCCFD84
+
+ys8urfxzgQMfQRVnSzGp7480kJ6DI5PMZTdtIKUnX7l6KG2KUmRfvoAfSI1sMA49
+bPqMSxaS9OrC2BTRsVGsi8oQxbnFm32v9IeaTNQCYQ4ntMoMV/xbGYhIEH4H3Hg4
+9Krnc0upc0ktHWMyaRct6RGzvn3hwXdkb+yaw6mB7hHy5/6uMNgs65ZWhiXY+gHR
+UAQjYv6tgvjwHXR0TlzOWM30Veh5Zz2BY4xBT+wFxFBCSfy+6tZLOa0dnxkPhbMS
+QYFfUq7JemrCQiDpMsNRrTBJFsUb4YN7JVPtvPhi/mHFHiA1g6kEnsvaTRoHkuoQ
+9TQeVyUVuK1JU0aHO2Wur2KatczZOqcSfDQQz57/i4OHNGEfZGqGEZ6YXZlrQSEd
+iMGP+vKPBOgJiYZQH6CItZ2ziFtJYNjAZJszaa+1asNWZCQJrBWdZ5ZQ9Gm9gnV6
+22tSZfqkRKFXCsknjWl6NOywldf4cRwq+zqr4EeVlj4eNm3NoIJvjpCKHGYYJ8mi
+HJl49utHBBrZtSWAFYjV4Xfl6/kCH1Nkl87ijBwHFiqNdJYxj9y2Q5edJBJ5U6dZ
+K2zBdZY0vF5OJeWo451ztXVi4JmX9/LlDiekY/28XlQd1gIANweYYrDciIeODFdJ
+yASNxZD6yOSIegmQ3c8xJxzHKivG9VPJCYSsKGhAxZcwHR2fw/UnDZA5lkRfLyDA
+iMurrYmZhvcpBpZS8fHVqGFzSV7RTnf/bU6M2Z+9Nv65tSwwyTJ/P2QP3hrYKqje
+w6qSLeqoZvExnHvaLIvGLii/Sq46euX8bcVFi4d8KDv8iKzKGIl/uPp0ktgjWLuR
+zdGpEn6PcNeoUOqTpiepyYd3sIZSn4GKDSccJ/xNUlpEjim9+5Lg8dHdCadDAzGJ
+QrCzXFlWg+rNWe4kdM3P4SA1OjF3+kISDcSRRZjTBaNQm6p/pcxKnueMiGegpfAH
+8JGGkT8MVodWO6I/fh18QgtJO+aVfPFFWLz8i6PHsqO+9sZUhSur8wrWtN2xbyC4
+cUWn6RUkhtg0U8Ys5fyxnOUpSFuBxkOU3F5HWzE1kaId8E/6ry4V6oaOMdQLmduM
+Ms5XIZ8r4/jQH+vN+4BTIkSQqR01tPTQm7pWv6t1c4hMWLP68GOVywFqtuSFXJKj
+i7AFnk91X72fSa5qxp7ZsgvuDIXeOxnw+QviC8/5Ha3r2GQhAjew3+6VEa4yZqmM
+yHu+qleFKw/6pARSNBl9+QZusN9R+cTZgYr9Bg5F4dEhlsfAoyVlzq3Ev/euGNOW
+XdI1vwv6Bi4ocH5+3i//kOUXjxke2WpA3Z/svjvWfIJwkEFoF8cxK3iKmuqXawyG
+MgM86gwVX1YohPVda2vAzAe54W4hpypDhDCkjdjLjXSJvhX/ysEiW1hjSK6ZJ6+o
+HAKkCTrF1R336WbmUvwYw7bglaYP7qyw3F8m9l2kQJYmr8TFYZOmN8NyKbofu+AN
+Xl4tVZbN5uLSDaFWQzTpzWv+QCxGAscGMCRH1TpcS+BI8OLX1pj425CFVD80tX3D
+zMSkgX+FyT/weVFd0KGvPYflZJBzayq9RvCrOj5cMYkNoKUNnlP5TA==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubsubCARE2RE4Cert.pem b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubsubCARE2RE4Cert.pem
new file mode 100644
index 0000000000..3066bd2314
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/smime-pem/requireExplicitPolicy7subsubsubCARE2RE4Cert.pem
@@ -0,0 +1,61 @@
+Bag Attributes
+ localKeyID: 76 13 A6 B2 AF 61 63 68 21 A1 77 C6 7D D8 5F 8A ED C7 E4 2E
+ friendlyName: requireExplicitPolicy7 subsubsubCARE2RE4 Cert
+subject=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 subsubsubCARE2RE4
+issuer=/C=US/O=Test Certificates 2011/CN=requireExplicitPolicy7 subsubCARE2RE4
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEf
+MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlcmVxdWly
+ZUV4cGxpY2l0UG9saWN5NyBzdWJzdWJDQVJFMlJFNDAeFw0xMDAxMDEwODMwMDBa
+Fw0zMDEyMzEwODMwMDBaMGExCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENl
+cnRpZmljYXRlcyAyMDExMTEwLwYDVQQDEyhyZXF1aXJlRXhwbGljaXRQb2xpY3k3
+IHN1YnN1YnN1YkNBUkUyUkU0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAu6hakMgtlNCA+rCJWAL8vGJ9le47WEg+7fAOpHBMAZvLGYiufTGL9z082H6l
+XMYJZl9vt/04HghPEbFeWfF/S8ahz6A7kpuSB/i4trfzkyCYqi+5YDozDw3+JzVS
+C9h77p59euEO4LVxlJwxLeDIXh2idbYmMs6hBqyktdRv4qZbqgtAyascshbclgs7
+5YJWYtkDp59/MWooX/Af8VNTnCUGrgCtk7dagQd1eGilyo0NpM6XDQ6eYdkqQJhI
+zyvGo5SWSAmkIrX0fRoyocwD3ibn+OUN5pVDZplzYA/PPL4kq0BBFt8C8RddSZIs
+1YM+hnhSdB8mRfs/Yl/xWpIwhwIDAQABo3wwejAfBgNVHSMEGDAWgBRu/40Ii2b+
+m6V7+2QzZeoDlUiUmDAdBgNVHQ4EFgQUeyxRYTEVrawsa6m+OzsYGpKqf0QwDgYD
+VR0PAQH/BAQDAgEGMBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAPBgNVHRMBAf8E
+BTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCcmQxvc23zsZ5WsaG6itcxVmsRDeKF
+WjkeTATCwuac7OTFciIJ2ts2sMDnT5yupQFxNn03VhBejR+caA2RlIKkV31tQDu+
+34kvGxD6fLcjAf9tfUbzjfEyZEPAfrlSiXVDLVPa0BFw/mO3gjCNNlLs8/RoFhsZ
+alMVnfklprdGkaGldVuqDDHPbiX2xy2WE4XoWKSqD/PXBifml/K8Ktfz6FezN8fH
+DIz0zc7JXnu8mI3TeWFSvcK+lIBVfmm3sarVDGVR83/RY+ev2kPP2PzKL2vJpBqD
+cRKPCxQiGmMw7IaDw8o/mGzapGd+W+zIgL0G/cvtbIKayoe7fwk9iHOm
+-----END CERTIFICATE-----
+Bag Attributes
+ localKeyID: 76 13 A6 B2 AF 61 63 68 21 A1 77 C6 7D D8 5F 8A ED C7 E4 2E
+ friendlyName: requireExplicitPolicy7 subsubsubCARE2RE4 Cert
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1735F91368816CAC
+
+0mzm+tlczyDGO8QkYpl3YWMMMLYz4/Om3I+rNNgb4u4g/M67gew0RaNd6+jIXQ+d
+MFRV3Vd2pRjH8IsHXIO0Y9pS2A2cBqOEPOlNX/vAk4HO+bHIHbx757gznY1S8op1
+hmMx9RE+5yAOra1naPr2vrH+/b25qRFYvgClGbD2xSct9+N3nltNLvMxkS/mh0Mj
+nxb23GRGXuD2tldzeJ2ufqPj0OqJzjpqzx+LJikLwsjHDTzZ9TTX5x071eIWr9TO
+HNC4Rj72OaLoYSsODONoTzX++lB+RFiqccyzl4sFlh2a6v4LDV1FCpGLoYzm+OxH
+zUu0z3B6nOSXoVWSIpHKrTE7f/ffeVPfjQRy6SNb9KRh6OXqjundOJAY9RQ850LN
+u2LcJQzyxvAkkhTPQUcRHqib+xwoxZSc2PZGpdBG6+UmXCjHcTpYS1FzHM5WnN2W
+JrMsOworZjAAvyopPIdv9ByM2AS9oMSTglv6jcujXkUpeDFnfs9Knt0ATMXaHhpi
+EXKP4b6I7JeSdTGk9suH60FUY2y13DjZFFT16tcQ7SIHilh8pQMxLrSToOGCfsAa
+R/dlyj3gQYMgf8qyvGSdpchiGdAuNtg6akhoFKnXmzEupoq5kY0ZKLZwulofDLfx
+IwQVwDz5RXBhDJUmr/TLZrhyLUIkC7E1ZoCocQDlmojrw2Q0mfOCJkenxja8YA3I
+IVvnakET52T8oXwDl94bhLN85/1Dtvj9CJkIrUKF37Eyidy3/SoCsL+ufI6e7Fnk
+jeaupw4oTsYlr1CtHUVAHRnfncc9BIducVqG1QomACmschc1Ivkd+8Ok61lIxXRt
+/7xiPV3+HeUKSZs7R4kDrRWa6LiLfXfXC9Vf/FxBzPVMnPOd9e1L634SZ8OcHIbS
+Q7JAaX+jXBs1+Rf1n0LKTYKVFKsWgAtkB0dug7mpEz7lqqKQi4LYEr9KMXZIbSif
+NEtdDs3eXUtZjLLnMQgioEqWCZLE5YHkZD1KJj9XQ6g6XRHWYVMpZWy3/480YTsH
+Vaw7UPJ3s0yCF7OUVxgjOdBQr4J90G+WOncTEPXknQDjS9/5FYYE5kOpeIpOsm05
+D73aLiHei+MWDO2WWOU9w1jzwusPEDU+wL3E9nmz1zS3io0esp3daVW8G1sBQiCm
+F7aodgrb6EWIzmWOEPP42pWsJoZtogNbjo2u41H2mCfoeVpRj6YOvc1OiG/gVS9B
+1GmJmZGkGh/y7Hos0bSab+ZZNx16NDEHE5j3JI8ziFzo1zBELHPMYEZK8tRTFS3z
+gHWm8s5ib94xykonXG6jDU1fRLi8ZZHPpLg7yfiFHs9yBLlecfCnh9f9mmEKRpgj
+PHFnWdbZZZfRZC+TSQDIDhCvjbBj+jB3We3nLluSjEUmWrAJN/sGRcJ6+rK55ErA
+jMq4ApfYmx6z6Gw8vONatiwDqZE7BKxlR5k69BazG+aB54vugMusggdAeBO2het1
+orUaD36pfIf3jCXgzn9ycVuQaTq4KECZStGqhfOhj1DB33/1Tnmf9ZX3m0mwx3VW
+79QavvERR/m4iHiudSeJgP7IDZCO2VLtPQH6aKDfyaIfmWYkE9bp6g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index b11e4d092a..6a879867e1 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server_line.hrl").
+%%-include_lib("common_test/include/ct.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include_lib("public_key/include/public_key.hrl").
@@ -107,7 +107,7 @@ all() ->
{group, ssh_public_key_decode_encode},
encrypt_decrypt,
{group, sign_verify},
- pkix, pkix_path_validation, deprecated].
+ pkix, pkix_countryname, pkix_path_validation].
groups() ->
[{pem_decode_encode, [], [dsa_pem, rsa_pem, encrypted_pem,
@@ -626,6 +626,34 @@ pkix(Config) when is_list(Config) ->
VerifyStr = public_key:pkix_normalize_name(TestStr),
ok.
+
+%%--------------------------------------------------------------------
+pkix_countryname(doc) ->
+ "Test workaround for certs that code x509countryname as utf8";
+pkix_countryname(suite) ->
+ [];
+pkix_countryname(Config) when is_list(Config) ->
+ Cert = incorrect_pkix_cert(),
+ OTPCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCert = OTPCert#'OTPCertificate'.tbsCertificate,
+ Issuer = TBSCert#'OTPTBSCertificate'.issuer,
+ Subj = TBSCert#'OTPTBSCertificate'.subject,
+ check_countryname(Issuer),
+ check_countryname(Subj).
+
+check_countryname({rdnSequence,DirName}) ->
+ do_check_countryname(DirName).
+do_check_countryname([]) ->
+ ok;
+do_check_countryname([#'AttributeTypeAndValue'{type = ?'id-at-countryName',
+ value = "US"}|_]) ->
+ ok;
+do_check_countryname([#'AttributeTypeAndValue'{type = ?'id-at-countryName',
+ value = Value}|_]) ->
+ test_server:fail({incorrect_cuntry_name, Value});
+do_check_countryname([_| Rest]) ->
+ do_check_countryname(Rest).
+
%%--------------------------------------------------------------------
pkix_path_validation(doc) ->
"Misc pkix tests not covered elsewhere";
@@ -699,27 +727,6 @@ pkix_path_validation(Config) when is_list(Config) ->
VerifyFunAndState1}]),
ok.
-%%--------------------------------------------------------------------
-deprecated(doc) ->
- ["Check deprecated functions."];
-deprecated(suite) ->
- [];
-deprecated(Config) when is_list(Config) ->
- Datadir = ?config(data_dir, Config),
- {ok, [DsaKey = {'DSAPrivateKey', _DsaKey, _}]} =
- public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- {ok, [RsaKey = {'RSAPrivateKey', _RsaKey,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
- {ok, [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}]} =
- public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
-
- {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey),
- {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey, "abcd1234"),
- ok.
-
-%%--------------------------------------------------------------------
-
check_entry_type(#'DSAPrivateKey'{}, 'DSAPrivateKey') ->
true;
check_entry_type(#'RSAPrivateKey'{}, 'RSAPrivateKey') ->
@@ -737,3 +744,6 @@ check_entry_type(_,_) ->
strip_ending_newlines(Bin) ->
string:strip(binary_to_list(Bin), right, 10).
+
+incorrect_pkix_cert() ->
+ <<48,130,5,186,48,130,4,162,160,3,2,1,2,2,7,7,250,61,63,6,140,137,48,13,6,9,42, 134,72,134,247,13,1,1,5,5,0,48,129,220,49,11,48,9,6,3,85,4,6,19,2,85,83,49, 16,48,14,6,3,85,4,8,19,7,65,114,105,122,111,110,97,49,19,48,17,6,3,85,4,7,19, 10,83,99,111,116,116,115,100,97,108,101,49,37,48,35,6,3,85,4,10,19,28,83,116, 97,114,102,105,101,108,100,32,84,101,99,104,110,111,108,111,103,105,101,115, 44,32,73,110,99,46,49,57,48,55,6,3,85,4,11,19,48,104,116,116,112,58,47,47,99, 101,114,116,105,102,105,99,97,116,101,115,46,115,116,97,114,102,105,101,108, 100,116,101,99,104,46,99,111,109,47,114,101,112,111,115,105,116,111,114,121, 49,49,48,47,6,3,85,4,3,19,40,83,116,97,114,102,105,101,108,100,32,83,101,99, 117,114,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117, 116,104,111,114,105,116,121,49,17,48,15,6,3,85,4,5,19,8,49,48,54,56,56,52,51, 53,48,30,23,13,49,48,49,48,50,51,48,49,51,50,48,53,90,23,13,49,50,49,48,50, 51,48,49,51,50,48,53,90,48,122,49,11,48,9,6,3,85,4,6,12,2,85,83,49,11,48,9,6, 3,85,4,8,12,2,65,90,49,19,48,17,6,3,85,4,7,12,10,83,99,111,116,116,115,100, 97,108,101,49,38,48,36,6,3,85,4,10,12,29,83,112,101,99,105,97,108,32,68,111, 109,97,105,110,32,83,101,114,118,105,99,101,115,44,32,73,110,99,46,49,33,48, 31,6,3,85,4,3,12,24,42,46,108,111,103,105,110,46,115,101,99,117,114,101,115, 101,114,118,101,114,46,110,101,116,48,130,1,34,48,13,6,9,42,134,72,134,247, 13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,185,136,240,80,141,36,124, 245,182,130,73,19,188,74,166,117,72,228,185,209,43,129,244,40,44,193,231,11, 209,12,234,88,43,142,1,162,48,122,17,95,230,105,171,131,12,147,46,204,36,80, 250,171,33,253,35,62,83,22,71,212,186,141,14,198,89,89,121,204,224,122,246, 127,110,188,229,162,67,95,6,74,231,127,99,131,7,240,85,102,203,251,50,58,58, 104,245,103,181,183,134,32,203,121,232,54,32,188,139,136,112,166,126,14,91, 223,153,172,164,14,61,38,163,208,215,186,210,136,213,143,70,147,173,109,217, 250,169,108,31,211,104,238,103,93,182,59,165,43,196,189,218,241,30,148,240, 109,90,69,176,194,52,116,173,151,135,239,10,209,179,129,192,102,75,11,25,168, 223,32,174,84,223,134,70,167,55,172,143,27,130,123,226,226,7,34,142,166,39, 48,246,96,231,150,84,220,106,133,193,55,95,159,227,24,249,64,36,1,142,171,16, 202,55,126,7,156,15,194,22,116,53,113,174,104,239,203,120,45,131,57,87,84, 163,184,27,83,57,199,91,200,34,43,98,61,180,144,76,65,170,177,2,3,1,0,1,163, 130,1,224,48,130,1,220,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,0,48,29,6,3, 85,29,37,4,22,48,20,6,8,43,6,1,5,5,7,3,1,6,8,43,6,1,5,5,7,3,2,48,14,6,3,85, 29,15,1,1,255,4,4,3,2,5,160,48,56,6,3,85,29,31,4,49,48,47,48,45,160,43,160, 41,134,39,104,116,116,112,58,47,47,99,114,108,46,115,116,97,114,102,105,101, 108,100,116,101,99,104,46,99,111,109,47,115,102,115,50,45,48,46,99,114,108, 48,83,6,3,85,29,32,4,76,48,74,48,72,6,11,96,134,72,1,134,253,110,1,7,23,2,48, 57,48,55,6,8,43,6,1,5,5,7,2,1,22,43,104,116,116,112,115,58,47,47,99,101,114, 116,115,46,115,116,97,114,102,105,101,108,100,116,101,99,104,46,99,111,109, 47,114,101,112,111,115,105,116,111,114,121,47,48,129,141,6,8,43,6,1,5,5,7,1, 1,4,129,128,48,126,48,42,6,8,43,6,1,5,5,7,48,1,134,30,104,116,116,112,58,47, 47,111,99,115,112,46,115,116,97,114,102,105,101,108,100,116,101,99,104,46,99, 111,109,47,48,80,6,8,43,6,1,5,5,7,48,2,134,68,104,116,116,112,58,47,47,99, 101,114,116,105,102,105,99,97,116,101,115,46,115,116,97,114,102,105,101,108, 100,116,101,99,104,46,99,111,109,47,114,101,112,111,115,105,116,111,114,121, 47,115,102,95,105,110,116,101,114,109,101,100,105,97,116,101,46,99,114,116, 48,31,6,3,85,29,35,4,24,48,22,128,20,73,75,82,39,209,27,188,242,161,33,106, 98,123,81,66,122,138,215,213,86,48,59,6,3,85,29,17,4,52,48,50,130,24,42,46, 108,111,103,105,110,46,115,101,99,117,114,101,115,101,114,118,101,114,46,110, 101,116,130,22,108,111,103,105,110,46,115,101,99,117,114,101,115,101,114,118, 101,114,46,110,101,116,48,29,6,3,85,29,14,4,22,4,20,138,233,191,208,157,203, 249,85,242,239,20,195,48,10,148,49,144,101,255,116,48,13,6,9,42,134,72,134, 247,13,1,1,5,5,0,3,130,1,1,0,82,31,121,162,49,50,143,26,167,202,143,61,71, 189,201,199,57,81,122,116,90,192,88,24,102,194,174,48,157,74,27,87,210,223, 253,93,3,91,150,109,120,1,110,27,11,200,198,141,222,246,14,200,71,105,41,138, 13,114,122,106,63,17,197,181,234,121,61,89,74,65,41,231,248,219,129,83,176, 219,55,107,55,211,112,98,38,49,69,77,96,221,108,123,152,12,210,159,157,141, 43,226,55,187,129,3,82,49,136,66,81,196,91,234,196,10,82,48,6,80,163,83,71, 127,102,177,93,209,129,26,104,2,84,24,255,248,161,3,244,169,234,92,122,110, 43,4,17,113,185,235,108,219,210,236,132,216,177,227,17,169,58,162,159,182, 162,93,160,229,200,9,163,229,110,121,240,168,232,14,91,214,188,196,109,210, 164,222,0,109,139,132,113,91,16,118,173,178,176,80,132,34,41,199,51,206,250, 224,132,60,115,192,94,107,163,219,212,226,225,65,169,148,108,213,46,174,173, 103,110,189,229,166,149,254,31,51,44,144,108,187,182,11,251,201,206,86,138, 208,59,51,86,132,235,81,225,88,34,190,8,184>>.
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 66ac78a65d..c8165fa247 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.13
+PUBLIC_KEY_VSN = 0.16
diff --git a/lib/reltool/doc/src/Makefile b/lib/reltool/doc/src/Makefile
index 8bc1488f77..0b85b7e02c 100644
--- a/lib/reltool/doc/src/Makefile
+++ b/lib/reltool/doc/src/Makefile
@@ -97,13 +97,13 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(HTMLDIR)/* $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(HTMLDIR)/* "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/reltool/doc/src/make.dep b/lib/reltool/doc/src/make.dep
deleted file mode 100644
index 59e77e8162..0000000000
--- a/lib/reltool/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex reltool.tex \
- reltool_examples.tex reltool_intro.tex reltool_usage.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 5304b996a4..0aae128c2b 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -37,7 +37,165 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.5.7</title>
+ <section><title>Reltool 0.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Miscellaneous corrections: <list> <item> Start of reltool
+ GUI would sometimes crash with a badmatch in
+ reltool_sys_win:do_init. This has been corrected. </item>
+ <item> Minor corrections of documentation and type
+ specifications of app() and mod() are done. </item>
+ <item> If a module name is duplicated in an app file
+ reltool would return an error. This is now changed to a
+ warning. </item> <item> Reltool would earlier not
+ necessarily keep the order of applications as listed in
+ the rel specification in the configuration. This has been
+ corrected. </item> <item> Reltool would earlier set the
+ default for included applications to an empty list if it
+ was not set in the rel specification in the
+ configuration. This was correct according to
+ sasl/systools documentation, but not according to
+ sasl/systools implementation. We decided to change the
+ documentation and reltool to use the value of
+ included_applications from the .app file as default
+ instead of the empty list, since this seems more
+ intuitive and since systools always has done the same.
+ </item> <item> The value of included applications in the
+ rel specification in the configuration did not overwrite
+ included_applications in the .app file if it was set to
+ an empty list. This has been corrected. </item> <item>
+ Reltool would earlier add load instructions in the
+ script/boot files for ALL modules in the ebin directory
+ of an application even if mod_cond was set to app
+ (include only modules listed in the .app file). This has
+ been corrected. </item> <item> Reltool would earlier add
+ start instructions in the script/boot file for included
+ applications. This has been corrected - included
+ applications shall only be loaded since the including
+ application is responsible for starting them. </item>
+ <item> Status bar now indicates that reltool is working
+ (Processing libraries...) for all configuration changes,
+ and when generating target system. </item> <item> Title
+ of dependecies column in app and mod window is changed
+ from "Modules used by others" to "Modules using this".
+ </item> </list></p>
+ <p>
+ Own Id: OTP-9792</p>
+ </item>
+ <item>
+ <p>
+ Configuration changes via the GUI had a few bugs related
+ to error handling, rollback and undo. A major re-write of
+ the reltool_server has been done in order to align the
+ way reltool_server updates and uses its state and tables
+ for all different kinds of configuration change. </p>
+ <p>
+ All configuration changes (except undo) now cause a
+ re-read of the file system, meaning that if something has
+ changed in the file system it will be reflected in the
+ result of the configuration change.</p>
+ <p>
+ When loading a new configuration file via the GUI, the
+ old configuration is now completely scratched, and only
+ the new is valid.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9794</p>
+ </item>
+ <item>
+ <p>
+ Some bug fixes related to the handling of escripts:
+ <list> <item> Reltool could not handle escripts with
+ inlined applications. This has been corrected. Inlined
+ applications will be visible in the GUI, but not possible
+ to include/exclude separately. </item> <item> Loading a
+ config which contains an escript via the GUI menu did not
+ produce the same result as when using the same
+ configuration at reltool start. Paths, version and label
+ could differ. This has been corrected. </item> <item>
+ Loading config with same escript (source) twice caused
+ reltool to add same module twice. This has been
+ corrected. </item> <item> Loading config with same
+ escript (inlined beam) twice caused reltool to fail
+ saying module is included by two different applications.
+ This has been corrected. </item> <item> Loading config
+ which in addition to an existing escript also adds
+ another escript, for which the name sorts before the
+ existing one, would cause reltool to fail saying
+ "Application name clash". This has been corrected.
+ </item> </list></p>
+ <p>
+ Own Id: OTP-9968</p>
+ </item>
+ <item>
+ <p>
+ Reltool would sometimes generate a .app file containing
+ <c>{start_phases,undefined}</c>, which would cause an
+ exception in systools at parse time. This has been
+ corrected so reltool now omits the <c>start_phases</c>
+ entry if the value is <c>undefined</c>. (Thanks to Juan
+ Jose Comellas)</p>
+ <p>
+ In order to align with reltool, sasl will also omit
+ <c>start_phases</c> entries with value <c>undefined</c>
+ in .script files.</p>
+ <p>
+ Own Id: OTP-10003</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A warning list is added to the sys window of the reltool
+ GUI. This list will continuously show all warnings
+ produced by the current configuration.</p>
+ <p>
+ Own Id: OTP-9967</p>
+ </item>
+ <item>
+ <p>
+ As a way of specifying one specific version of an
+ application, the following configuration parameter is
+ added on application level:</p>
+ <p>
+ {lib_dir,Dir}, Dir = string()</p>
+ <p>
+ This can be useful if the parent directory of the
+ application directory is not suitable to use as a lib dir
+ on system level.</p>
+ <p>
+ Own Id: OTP-9977</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.5.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added recommendation about <c>RootDir</c> parameter to
+ <c>reltool:eval_target_spec/3</c>.</p>
+ <p>
+ Own Id: OTP-9742</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.5.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 31e15e34e7..9b43640d83 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -221,6 +221,52 @@
system.</p>
</item>
+ <tag><c>excl_lib</c></tag>
+ <item>
+ <warning><p>This option is experimental.</p></warning>
+ <p>If the <c>excl_lib</c> option is set to <c>otp_root</c>
+ then reltool will not copy anything from the Erlang/OTP
+ installation ($OTP_ROOT) into the target structure. The goal
+ is to create a "slim" release which can be used together with
+ an existing Erlang/OTP installation. The target structure will
+ therefore only contain a <c>lib</c> directory with the
+ applications that were found outside of $OTP_ROOT (typically
+ your own applications), and a <c>releases</c> directory with
+ the generated <c>.rel,</c> <c>.script</c> and <c>.boot</c>
+ files.</p>
+
+ <p>When starting this release, three things must be specified:</p>
+ <taglist>
+ <tag><b>Which <c>releases</c> directory to use</b></tag>
+ <item>Tell the release handler to use the <c>releases</c>
+ directory in our target structure instead of
+ <c>$OTP_ROOT/releases</c>. This is done by setting the SASL
+ environment variable <c>releases_dir</c>, either from the
+ command line (<c>-sasl releases_dir
+ &lt;target-dir&gt;/releases</c>) or in
+ <c>sys.config</c>.</item>
+
+ <tag><b>Which boot file to use</b></tag>
+ <item>The default boot file is <c>$OTP_ROOT/bin/start</c>,
+ but in this case we need to specify a boot file from our
+ target structure, typically
+ <c>&lt;target-dir&gt;/releases/&lt;vsn&gt;/&lt;RelName&gt;</c>. This
+ is done with the <c>-boot</c> command line option to
+ <c>erl</c></item>
+
+ <tag><b>The location of our applications</b></tag>
+ <item>The generated .script (and .boot) file uses the
+ environment variable <c>$RELTOOL_EXT_LIB</c> as prefix for
+ the paths to all applications. The <c>-boot_var</c> option
+ to <c>erl</c> can be used for specifying the value of this
+ variable, typically <c>-boot_var RELTOOL_EXT_LIB
+ &lt;target-dir&gt;/lib</c>.</item>
+ </taglist>
+
+ <p>Example:</p>
+ <p><code>erl -sasl releases_dir \"mytarget/releases\" -boot mytarget/releases/1.0/myrel -boot_var RELTOOL_EXT_LIB mytarget/lib</code></p>
+ </item>
+
<tag><c>incl_sys_filters</c></tag>
<item>
<p>This parameter normally contains a list of regular
@@ -322,8 +368,21 @@
<item>
<p>The version of the application. In an installed system there may
exist several versions of an application. The <c>vsn</c> parameter
- controls which version of the application will be chosen. If it
- is omitted, the latest version will be chosen.</p>
+ controls which version of the application will be chosen.</p>
+ <p>This parameter is mutual exclusive with <c>lib_dir</c>. If
+ <c>vsn</c> and <c>lib_dir</c> are both omitted, the latest version
+ will be chosen.</p>
+ </item>
+ <tag><c>lib_dir</c></tag>
+ <item>
+ <p>The directory to read the application from. This parameter
+ can be used to point out a specific location to fetch the
+ application from. This is useful for instance if the parent
+ directory for some reason is no good as a library directory on
+ system level.</p>
+ <p>This parameter is mutual exclusive with <c>vsn</c>. If
+ <c>vsn</c> and <c>lib_dir</c> are both omitted, the latest version
+ will be chosen.</p>
</item>
<tag><c>mod</c></tag>
<item>
@@ -433,11 +492,13 @@ sys() = {root_dir, root_dir()}
| {excl_archive_filters, excl_archive_filters()}
| {archive_opts, [archive_opt()]}
app() = {vsn, app_vsn()}
- | {mod, mod_name(), mod()}
+ | {lib_dir, lib_dir()}
+ | {mod, mod_name(), [mod()]}
| {mod_cond, mod_cond()}
| {incl_cond, incl_cond()}
| {debug_info, debug_info()}
| {app_file, app_file()}
+ | {excl_lib, excl_lib()}
| {incl_sys_filters, incl_sys_filters()}
| {excl_sys_filters, excl_sys_filters()}
| {incl_app_filters, incl_app_filters()}
@@ -445,8 +506,7 @@ app() = {vsn, app_vsn()}
| {incl_archive_filters, incl_archive_filters()}
| {excl_archive_filters, excl_archive_filters()}
| {archive_opts, [archive_opt()]}
-mod() = {vsn, app_vsn()}
- | {incl_cond, incl_cond()}
+mod() = {incl_cond, incl_cond()}
| {debug_info, debug_info()}
rel_app() = app_name()
| {app_name(), app_type()}
@@ -464,6 +524,7 @@ escript() = {incl_cond, incl_cond()}
escript_file() = file()
excl_app_filters() = regexps()
excl_archive_filters() = regexps()
+excl_lib() = otp_root
excl_sys_filters() = regexps()
file() = string()
incl_app() = app_name()
@@ -558,7 +619,17 @@ target_spec() = [target_spec()]
<c>true</c> there is no need to install the target system with
<c>reltool:install/2</c> before it can be started. In that case
the file tree containing the target system can be moved without
- re-installation.</p></desc>
+ re-installation.</p>
+
+ <p>In most cases, the <c>RootDir</c> parameter should be set to
+ the same as the <c>root_dir</c> configuration parameter used in
+ the call to <c>reltool:get_target_spec/1</c>
+ (or <c>code:root_dir()</c> if the configuration parameter is not
+ set). In some cases it might be useful to evaluate the same
+ target specification towards different root directories. This
+ should, however, be used with great care as it requires
+ equivalent file structures under all roots.</p>
+ </desc>
</func>
<func>
@@ -640,7 +711,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_target_spec(Server) -> {ok, targetSpec} | {error, Reason}</name>
+ <name>get_target_spec(Server) -> {ok, TargetSpec} | {error, Reason}</name>
<fsummary>Return a specification of the target system</fsummary>
<type>
<v>Server = server()</v>
@@ -654,10 +725,10 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>install(Server, TargetDir) -> ok | {error, Reason}</name>
+ <name>install(RelName, TargetDir) -> ok | {error, Reason}</name>
<fsummary>Install a target system</fsummary>
<type>
- <v>Server = server()</v>
+ <v>RelName = rel_name()</v>
<v>TargetDir = target_dir()</v>
<v>Reason = reason()</v>
</type>
diff --git a/lib/reltool/examples/Makefile b/lib/reltool/examples/Makefile
index dacfd4e7d4..afc47e1d12 100644
--- a/lib/reltool/examples/Makefile
+++ b/lib/reltool/examples/Makefile
@@ -72,8 +72,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(ERL_FILES) $(DATA_FILES) $(HRL_FILES) "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/reltool/src/Makefile b/lib/reltool/src/Makefile
index 4e6a112b7e..4730b4acff 100644
--- a/lib/reltool/src/Makefile
+++ b/lib/reltool/src/Makefile
@@ -97,11 +97,11 @@ $(TARGET_FILES): $(HRL_FILES) $(INTERNAL_HRL_FILES)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/reltool/src/reltool.erl b/lib/reltool/src/reltool.erl
index 54eb1ca9e1..2bdf222aa0 100644
--- a/lib/reltool/src/reltool.erl
+++ b/lib/reltool/src/reltool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,7 @@ start_link(Options) when is_list(Options) ->
{ok, _WinPid} = OK ->
OK;
{error, Reason} ->
- {error, lists:flatten(io_lib:format("~p", [Reason]))}
+ {error, Reason}
end.
%% Start server process with options
@@ -69,7 +69,7 @@ start_server(Options) ->
{ok, ServerPid, _Common, _Sys} ->
{ok, ServerPid};
{error, Reason} ->
- {error, lists:flatten(io_lib:format("~p", [Reason]))}
+ {error, Reason}
end.
%% Start server process with options
diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl
index 93f47f6381..f0d8b38519 100644
--- a/lib/reltool/src/reltool.hrl
+++ b/lib/reltool/src/reltool.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,7 @@
-type profile() :: development | embedded | standalone.
-type relocatable() :: boolean().
-type escript_file() :: file().
+-type escript_app_name() :: app_name().
-type mod_name() :: atom().
-type app_name() :: atom().
-type app_vsn() :: string(). % e.g. "4.7"
@@ -62,7 +63,8 @@
-type mod() :: {incl_cond, incl_cond()}
| {debug_info, debug_info()}.
-type app() :: {vsn, app_vsn()}
- | {mod, mod_name(), mod()}
+ | {lib_dir, lib_dir()}
+ | {mod, mod_name(), [mod()]}
| {mod_cond, mod_cond()}
| {incl_cond, incl_cond()}
| {app_file, app_file()}
@@ -77,6 +79,7 @@
| {debug_info, debug_info()}
| {app_file, app_file()}
| {profile, profile()}
+ | {excl_lib, excl_lib()}
| {incl_sys_filters, incl_sys_filters()}
| {excl_sys_filters, excl_sys_filters()}
| {incl_app_filters, incl_app_filters()}
@@ -121,32 +124,31 @@
-type incl_defaults() :: boolean().
-type incl_derived() :: boolean().
-type status() :: missing | ok.
+-type excl_lib() :: otp_root.
-record(common,
{
sys_debug :: term(),
wx_debug :: term(),
- trap_exit :: boolean(),
- app_tab :: ets:tab(),
- mod_tab :: ets:tab(),
- mod_used_by_tab :: ets:tab()
+ trap_exit :: boolean()
}).
+%% Types '$1','$2' and '_' are needed for match specs to ets:select
-record(mod,
{ %% Static
- name :: mod_name(),
- app_name :: app_name(),
- incl_cond :: incl_cond() | undefined,
- debug_info :: debug_info() | undefined,
- is_app_mod :: boolean(),
- is_ebin_mod :: boolean(),
- uses_mods :: [mod_name()],
- exists :: boolean(),
+ name :: '$1' | mod_name(),
+ app_name :: '_' | app_name(),
+ incl_cond :: '_' | incl_cond() | undefined,
+ debug_info :: '_' | debug_info() | undefined,
+ is_app_mod :: '_' | boolean(),
+ is_ebin_mod :: '_' | boolean(),
+ uses_mods :: '$2' | [mod_name()],
+ exists :: '_' | boolean(),
%% Dynamic
- status :: status(),
- used_by_mods :: [mod_name()],
- is_pre_included :: boolean() | undefined,
- is_included :: boolean() | undefined
+ status :: '_' | status(),
+ used_by_mods :: '_' | [mod_name()],
+ is_pre_included :: '_' | boolean() | undefined,
+ is_included :: '_' | boolean() | undefined
}).
-record(app_info,
@@ -167,48 +169,49 @@
-record(regexp, {source, compiled}).
+%% Types '$1','$2' and '_' are needed for match specs to ets:select
-record(app,
{ %% Static info
- name :: app_name(),
- is_escript :: boolean(),
- use_selected_vsn :: boolean() | undefined,
- active_dir :: dir(),
- sorted_dirs :: [dir()],
- vsn :: app_vsn(),
- label :: app_label(),
- info :: #app_info{} | undefined,
- mods :: [#mod{}],
+ name :: '_' | app_name(),
+ is_escript :: '_' | boolean() | {inlined, escript_app_name()},
+ use_selected_vsn :: '_' | vsn | dir | undefined,
+ active_dir :: '_' | dir(),
+ sorted_dirs :: '_' | [dir()],
+ vsn :: '_' | app_vsn(),
+ label :: '_' | app_label(),
+ info :: '_' | #app_info{} | undefined,
+ mods :: '_' | [#mod{}],
%% Static source cond
- mod_cond :: mod_cond() | undefined,
- incl_cond :: incl_cond() | undefined,
+ mod_cond :: '_' | mod_cond() | undefined,
+ incl_cond :: '_' | incl_cond() | undefined,
%% Static target cond
- debug_info :: debug_info() | undefined,
- app_file :: app_file() | undefined,
- app_type :: app_type() | undefined,
- incl_app_filters :: [#regexp{}],
- excl_app_filters :: [#regexp{}],
- incl_archive_filters :: [#regexp{}],
- excl_archive_filters :: [#regexp{}],
- archive_opts :: [archive_opt()],
+ debug_info :: '_' | debug_info() | undefined,
+ app_file :: '_' | app_file() | undefined,
+ app_type :: '_' | app_type() | undefined,
+ incl_app_filters :: '_' | [#regexp{}],
+ excl_app_filters :: '_' | [#regexp{}],
+ incl_archive_filters :: '_' | [#regexp{}],
+ excl_archive_filters :: '_' | [#regexp{}],
+ archive_opts :: '_' | [archive_opt()],
%% Dynamic
- status :: status(),
- uses_mods :: [mod_name()],
- used_by_mods :: [mod_name()],
- uses_apps :: [app_name()],
- used_by_apps :: [app_name()],
- is_pre_included :: boolean(),
- is_included :: boolean(),
- rels :: [rel_name()]
+ status :: '_' | status(),
+ uses_mods :: '_' | [mod_name()],
+ used_by_mods :: '_' | [mod_name()],
+ uses_apps :: '_' | [app_name()],
+ used_by_apps :: '_' | [app_name()],
+ is_pre_included :: '_' | '$2' | boolean() | undefined,
+ is_included :: '_' | '$1' | boolean() | undefined,
+ rels :: '_' | [rel_name()]
}).
-record(rel_app,
{
name :: app_name(),
app_type :: app_type() | undefined,
- incl_apps = [] :: [incl_app()]
+ incl_apps :: [incl_app()] | undefined
}).
-record(rel,
@@ -225,13 +228,14 @@
escripts :: [file()],
mod_cond :: mod_cond(),
incl_cond :: incl_cond(),
- apps :: [#app{}],
+ apps :: [#app{}] | undefined,
%% Target cond
boot_rel :: boot_rel(),
rels :: [#rel{}],
emu_name :: emu_name(),
profile :: profile(),
+ excl_lib :: excl_lib(),
incl_sys_filters :: [#regexp{}],
excl_sys_filters :: [#regexp{}],
incl_app_filters :: [#regexp{}],
diff --git a/lib/reltool/src/reltool_app_win.erl b/lib/reltool/src/reltool_app_win.erl
index 70bd72b258..6cd0d2f90b 100644
--- a/lib/reltool/src/reltool_app_win.erl
+++ b/lib/reltool/src/reltool_app_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -271,8 +271,8 @@ create_apps_list_ctrl(Panel, Sizer, Text) ->
ListItem = wxListItem:new(),
wxListItem:setAlign(ListItem, ?wxLIST_FORMAT_LEFT),
wxListItem:setText(ListItem, Text),
+ wxListItem:setWidth(ListItem, reltool_utils:get_column_width(ListCtrl)),
wxListCtrl:insertColumn(ListCtrl, ?APPS_APP_COL, ListItem),
- %% wxListCtrl:setColumnWidth(ListCtrl, ?APPS_APP_COL, ?APPS_APP_COL_WIDTH),
wxListItem:destroy(ListItem),
wxSizer:add(Sizer, ListCtrl,
@@ -292,7 +292,7 @@ create_deps_page(S, Derived) ->
UsedByCtrl = create_mods_list_ctrl(Panel,
Main,
- "Modules used by others",
+ "Modules using this",
" and their applications",
undefined,
undefined),
@@ -611,7 +611,7 @@ handle_event(#state{sys = Sys, app = App} = S, Wx) ->
redraw_window(S2);
#wx{userData = use_selected_vsn} ->
%% Use selected version
- App2 = App#app{use_selected_vsn = true},
+ App2 = App#app{use_selected_vsn = dir},
{ok, App3} = reltool_sys_win:set_app(S#state.parent_pid, App2),
S2 = S#state{app = App3},
redraw_window(S2);
@@ -619,7 +619,8 @@ handle_event(#state{sys = Sys, app = App} = S, Wx) ->
event = #wxCommand{type = command_radiobox_selected,
cmdString = ActiveDir}} ->
%% Change app source
- S2 = change_version(S, App, ActiveDir),
+ App2 = App#app{use_selected_vsn = dir},
+ S2 = change_version(S, App2, ActiveDir),
redraw_window(S2);
#wx{userData = {mod_button, Action, ListCtrl},
event = #wxCommand{type = command_button_clicked}} ->
@@ -942,11 +943,11 @@ redraw_config(#state{sys = #sys{incl_cond = GlobalIncl,
LatestRadio,
SelectedRadio,
SourceBox,
- fun(true) ->
+ fun(false) ->
+ 0;
+ (_) ->
reltool_utils:elem_to_index(ActiveDir,
- SortedDirs) - 1;
- (false) ->
- 0
+ SortedDirs) - 1
end).
redraw_double_box(Global, Local, GlobalRadio, LocalRadio, LocalBox, GetChoice) ->
diff --git a/lib/reltool/src/reltool_mod_win.erl b/lib/reltool/src/reltool_mod_win.erl
index e1c2fa5100..899423bb6d 100644
--- a/lib/reltool/src/reltool_mod_win.erl
+++ b/lib/reltool/src/reltool_mod_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -215,7 +215,7 @@ create_deps_page(S) ->
UsedByCtrl = create_mods_list_ctrl(Panel,
Main,
- "Modules used by others",
+ "Modules using this",
" and their applications"),
wxSizer:add(Main,
wxStaticLine:new(Panel, [{style, ?wxLI_VERTICAL}]),
@@ -314,8 +314,8 @@ do_create_code_page(#state{xref_pid = Xref, mod = M} = S, PageName) ->
{ok, App} = reltool_server:get_app(Xref, M#mod.app_name),
ErlBin =
case App#app.is_escript of
- true -> find_escript_bin(App, M);
- false -> find_regular_bin(App, M)
+ false -> find_regular_bin(App, M);
+ _ -> find_escript_bin(App, M)
end,
load_code(Editor, ErlBin),
diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl
index 692baea0a4..3d1d7e54bf 100644
--- a/lib/reltool/src/reltool_server.erl
+++ b/lib/reltool/src/reltool_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,7 +51,12 @@
sys,
old_sys,
status,
- old_status}).
+ old_status,
+ app_tab,
+ old_app_tab,
+ mod_tab,
+ old_mod_tab,
+ mod_used_by_tab}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Client
@@ -123,174 +128,165 @@ gen_spec(Pid) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Server
-init(Options) ->
+init([{parent,Parent}|_] = Options) ->
try
do_init(Options)
catch
+ throw:{error,Reason} ->
+ proc_lib:init_ack(Parent,{error,Reason});
error:Reason ->
exit({Reason, erlang:get_stacktrace()})
end.
do_init(Options) ->
- {S, Status} = parse_options(Options),
- #state{parent_pid = ParentPid, common = C, sys = Sys} = S,
-
- %% process_flag(trap_exit, (S#state.common)#common.trap_exit),
- proc_lib:init_ack(ParentPid,
- {ok, self(), C, Sys#sys{apps = undefined}}),
- {S2, Status2} = refresh(S, true, Status),
- {S3, Status3} =
- analyse(S2#state{old_sys = S2#state.sys}, Status2),
- case Status3 of
- {ok, _Warnings} -> % BUGBUG: handle warnings
- loop(S3#state{status = Status3, old_status = {ok, []}});
- {error, Reason} ->
- exit(Reason)
- end.
-
-parse_options(Opts) ->
- AppTab = ets:new(reltool_apps, [public, ordered_set, {keypos, #app.name}]),
- ModTab = ets:new(reltool_mods, [public, ordered_set, {keypos, #mod.name}]),
+ AppTab = ets:new(reltool_apps1, [public, ordered_set, {keypos,#app.name}]),
+ OldAppTab = ets:new(reltool_apps2, [public, ordered_set, {keypos,#app.name}]),
+ ModTab = ets:new(reltool_mods1, [public, ordered_set, {keypos,#mod.name}]),
+ OldModTab = ets:new(reltool_mods2, [public, ordered_set, {keypos,#mod.name}]),
ModUsesTab = ets:new(reltool_mod_uses, [public, bag, {keypos, 1}]),
- Sys = #sys{root_dir = reltool_utils:root_dir(),
- lib_dirs = reltool_utils:erl_libs(),
- escripts = [],
- incl_cond = ?DEFAULT_INCL_COND,
- mod_cond = ?DEFAULT_MOD_COND,
- apps = ?DEFAULT_APPS,
- boot_rel = ?DEFAULT_REL_NAME,
- rels = reltool_utils:default_rels(),
- emu_name = ?DEFAULT_EMU_NAME,
- profile = ?DEFAULT_PROFILE,
- incl_sys_filters = dec_re(incl_sys_filters,
- ?DEFAULT_INCL_SYS_FILTERS,
- []),
- excl_sys_filters = dec_re(excl_sys_filters,
- ?DEFAULT_EXCL_SYS_FILTERS,
- []),
- incl_app_filters = dec_re(incl_app_filters,
- ?DEFAULT_INCL_APP_FILTERS,
- []),
- excl_app_filters = dec_re(excl_app_filters,
- ?DEFAULT_EXCL_APP_FILTERS,
- []),
- relocatable = ?DEFAULT_RELOCATABLE,
- rel_app_type = ?DEFAULT_REL_APP_TYPE,
- embedded_app_type = ?DEFAULT_EMBEDDED_APP_TYPE,
- app_file = ?DEFAULT_APP_FILE,
- incl_archive_filters = dec_re(incl_archive_filters,
- ?DEFAULT_INCL_ARCHIVE_FILTERS,
- []),
- excl_archive_filters = dec_re(excl_archive_filters,
- ?DEFAULT_EXCL_ARCHIVE_FILTERS,
- []),
- archive_opts = ?DEFAULT_ARCHIVE_OPTS,
- debug_info = ?DEFAULT_DEBUG_INFO},
- C2 = #common{sys_debug = [],
- wx_debug = 0,
- trap_exit = true,
- app_tab = AppTab,
- mod_tab = ModTab,
- mod_used_by_tab = ModUsesTab},
- S = #state{options = Opts},
- parse_options(Opts, S, C2, Sys, {ok, []}).
+ S = #state{options = Options,
+ app_tab = AppTab,
+ old_app_tab = OldAppTab,
+ mod_tab = ModTab,
+ old_mod_tab = OldModTab,
+ mod_used_by_tab = ModUsesTab},
+
+ S2 = parse_options(S),
+ {S3, Apps, Status2} = refresh(S2),
+ Status3 = analyse(S3, Apps, Status2),
+ %% Set old_xxx equal to xxx to allow undo=nop
+ FakeBackup = {ets:tab2list(S3#state.app_tab),ets:tab2list(S3#state.mod_tab)},
+ S4 = save_old(S3, S3, FakeBackup, Status3),
+ #state{parent_pid = Parent, sys=Sys, common=C} = S4,
+ proc_lib:init_ack(Parent, {ok, self(), C, Sys#sys{apps=undefined}}),
+ loop(S4).
+
+parse_options(S) ->
+ Sys = default_sys(),
+ C = #common{sys_debug = [],
+ wx_debug = 0,
+ trap_exit = true},
+ parse_options(S#state.options, S, C, Sys).
+
+default_sys() ->
+ #sys{root_dir = reltool_utils:root_dir(),
+ lib_dirs = reltool_utils:erl_libs(),
+ escripts = [],
+ incl_cond = ?DEFAULT_INCL_COND,
+ mod_cond = ?DEFAULT_MOD_COND,
+ apps = ?DEFAULT_APPS,
+ boot_rel = ?DEFAULT_REL_NAME,
+ rels = reltool_utils:default_rels(),
+ emu_name = ?DEFAULT_EMU_NAME,
+ profile = ?DEFAULT_PROFILE,
+ incl_sys_filters = dec_re(incl_sys_filters,
+ ?DEFAULT_INCL_SYS_FILTERS,
+ []),
+ excl_sys_filters = dec_re(excl_sys_filters,
+ ?DEFAULT_EXCL_SYS_FILTERS,
+ []),
+ incl_app_filters = dec_re(incl_app_filters,
+ ?DEFAULT_INCL_APP_FILTERS,
+ []),
+ excl_app_filters = dec_re(excl_app_filters,
+ ?DEFAULT_EXCL_APP_FILTERS,
+ []),
+ relocatable = ?DEFAULT_RELOCATABLE,
+ rel_app_type = ?DEFAULT_REL_APP_TYPE,
+ embedded_app_type = ?DEFAULT_EMBEDDED_APP_TYPE,
+ app_file = ?DEFAULT_APP_FILE,
+ incl_archive_filters = dec_re(incl_archive_filters,
+ ?DEFAULT_INCL_ARCHIVE_FILTERS,
+ []),
+ excl_archive_filters = dec_re(excl_archive_filters,
+ ?DEFAULT_EXCL_ARCHIVE_FILTERS,
+ []),
+ archive_opts = ?DEFAULT_ARCHIVE_OPTS,
+ debug_info = ?DEFAULT_DEBUG_INFO}.
dec_re(Key, Regexps, Old) ->
reltool_utils:decode_regexps(Key, Regexps, Old).
-parse_options([{Key, Val} | KeyVals], S, C, Sys, Status) ->
+parse_options([{Key, Val} | KeyVals], S, C, Sys) ->
case Key of
parent ->
- parse_options(KeyVals, S#state{parent_pid = Val}, C, Sys, Status);
+ parse_options(KeyVals, S#state{parent_pid = Val}, C, Sys);
sys_debug ->
- parse_options(KeyVals, S, C#common{sys_debug = Val}, Sys, Status);
+ parse_options(KeyVals, S, C#common{sys_debug = Val}, Sys);
wx_debug ->
- parse_options(KeyVals, S, C#common{wx_debug = Val}, Sys, Status);
+ parse_options(KeyVals, S, C#common{wx_debug = Val}, Sys);
trap_exit ->
- parse_options(KeyVals, S, C#common{trap_exit = Val}, Sys, Status);
+ parse_options(KeyVals, S, C#common{trap_exit = Val}, Sys);
config ->
- {Sys2, Status2} = read_config(Sys, Val, Status),
- parse_options(KeyVals, S, C, Sys2, Status2);
+ Sys2 = read_config(Sys, Val),
+ parse_options(KeyVals, S, C, Sys2);
sys ->
- {Sys2, Status2} = read_config(Sys, {sys, Val}, Status),
- parse_options(KeyVals, S, C, Sys2, Status2);
+ Sys2 = read_config(Sys, {sys, Val}),
+ parse_options(KeyVals, S, C, Sys2);
_ ->
- Text = lists:flatten(io_lib:format("~p", [{Key, Val}])),
- Status2 =
- reltool_utils:return_first_error(Status,
- "Illegal option: " ++ Text),
- parse_options(KeyVals, S, C, Sys, Status2)
+ reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
end;
-parse_options([], S, C, Sys, Status) ->
- {S#state{common = C, sys = Sys}, Status};
-parse_options(KeyVals, S, C, Sys, Status) ->
- Text = lists:flatten(io_lib:format("~p", [KeyVals])),
- Status2 = reltool_utils:return_first_error(Status,
- "Illegal options: " ++ Text),
- {S#state{common = C, sys = Sys}, Status2}.
-
-loop(#state{common = C, sys = Sys} = S) ->
+parse_options([], S, C, Sys) ->
+ S#state{common = C, sys = Sys};
+parse_options(KeyVals, _S, _C, _Sys) ->
+ reltool_utils:throw_error("Illegal option: ~p", [KeyVals]).
+
+loop(#state{sys = Sys} = S) ->
receive
{system, From, Msg} ->
sys:handle_system_msg(Msg,
From,
S#state.parent_pid,
?MODULE,
- C#common.sys_debug,
+ (S#state.common)#common.sys_debug,
S);
{call, ReplyTo, Ref, {get_config, InclDef, InclDeriv}} ->
Reply = do_get_config(S, InclDef, InclDeriv),
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
{call, ReplyTo, Ref, {load_config, SysConfig}} ->
- {S2, Reply} = do_load_config(S, SysConfig),
- reltool_utils:reply(ReplyTo, Ref, Reply),
- ?MODULE:loop(S2);
+ Fun = fun() -> do_load_config(S, SysConfig) end,
+ {S3, Status2} = config_and_refresh(S, Fun),
+ reltool_utils:reply(ReplyTo, Ref, Status2),
+ ?MODULE:loop(S3);
{call, ReplyTo, Ref, {save_config, Filename, InclDef, InclDeriv}} ->
Reply = do_save_config(S, Filename, InclDef, InclDeriv),
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
{call, ReplyTo, Ref, reset_config} ->
- {S2, Status} = parse_options(S#state.options),
- S3 = shrink_sys(S2),
- {S4, Status2} = refresh(S3, true, Status),
- {S5, Status3} = analyse(S4#state{old_sys = S4#state.sys}, Status2),
- S6 =
- case Status3 of
- {ok, _Warnings} ->
- S5#state{status = Status3, old_status = S#state.status};
- {error, _} ->
- %% Keep old state
- S
- end,
- reltool_utils:reply(ReplyTo, Ref, Status3),
- ?MODULE:loop(S6);
+ Fun = fun() -> parse_options(S) end,
+ {S3, Status2} = config_and_refresh(S, Fun),
+ reltool_utils:reply(ReplyTo, Ref, Status2),
+ ?MODULE:loop(S3);
{call, ReplyTo, Ref, undo_config} ->
- reltool_utils:reply(ReplyTo, Ref, ok),
S2 = S#state{sys = S#state.old_sys,
- old_sys = S#state.sys,
- status = S#state.old_status,
- old_status = S#state.status},
+ old_sys = Sys,
+ status = S#state.old_status,
+ old_status = S#state.status,
+ app_tab = S#state.old_app_tab,
+ old_app_tab = S#state.app_tab,
+ mod_tab = S#state.old_mod_tab,
+ old_mod_tab = S#state.mod_tab},
+ reltool_utils:reply(ReplyTo, Ref, ok),
?MODULE:loop(S2);
{call, ReplyTo, Ref, {get_rel, RelName}} ->
- Sys = S#state.sys,
Reply =
case lists:keysearch(RelName, #rel.name, Sys#sys.rels) of
{value, Rel} ->
- reltool_target:gen_rel(Rel, Sys);
+ reltool_target:gen_rel(Rel, sys_all_apps(S));
false ->
{error, "No such release: " ++ RelName}
end,
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
{call, ReplyTo, Ref, {get_script, RelName}} ->
- Sys = S#state.sys,
Reply =
case lists:keysearch(RelName, #rel.name, Sys#sys.rels) of
{value, Rel} ->
PathFlag = true,
Vars = [],
- reltool_target:gen_script(Rel, Sys, PathFlag, Vars);
+ reltool_target:gen_script(Rel, sys_all_apps(S),
+ PathFlag, Vars);
false ->
{error, "No such release: " ++ RelName}
end,
@@ -298,7 +294,7 @@ loop(#state{common = C, sys = Sys} = S) ->
?MODULE:loop(S);
{call, ReplyTo, Ref, {get_mod, ModName}} ->
Reply =
- case ets:lookup(C#common.mod_tab, ModName) of
+ case ets:lookup(S#state.mod_tab, ModName) of
[M] ->
{ok, M};
[] ->
@@ -308,92 +304,83 @@ loop(#state{common = C, sys = Sys} = S) ->
?MODULE:loop(S);
{call, ReplyTo, Ref, {get_app, AppName}} when is_atom(AppName) ->
Reply =
- case lists:keysearch(AppName, #app.name, Sys#sys.apps) of
- {value, App} ->
+ case ets:lookup(S#state.app_tab,AppName) of
+ [App] ->
{ok, App};
- false ->
+ [] ->
{error, "No such application: " ++
atom_to_list(AppName)}
end,
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
{call, ReplyTo, Ref, {set_app, App}} ->
- {S2, Status} = do_set_app(S, App, {ok, []}),
- {S3, Status2} = analyse(S2, Status),
- case Status2 of
- {ok, Warnings} ->
- App2 = ?KEYSEARCH(App#app.name,
- #app.name,
- (S3#state.sys)#sys.apps),
- reltool_utils:reply(ReplyTo, Ref, {ok, App2, Warnings}),
- ?MODULE:loop(S3);
- {error, Reason} ->
- %% Keep old state
- reltool_utils:reply(ReplyTo, Ref, {error, Reason}),
- ?MODULE:loop(S)
- end;
+ Fun = fun() -> do_set_apps(S, [App]) end,
+ {S3, Status2} = config_and_refresh(S, Fun),
+ Reply =
+ case Status2 of
+ {ok, Warnings} ->
+ [App2] = ets:lookup(S3#state.app_tab,App#app.name),
+ {ok, App2, Warnings};
+ {error, _} ->
+ Status2
+ end,
+ reltool_utils:reply(ReplyTo, Ref, Reply),
+ ?MODULE:loop(S3);
{call, ReplyTo, Ref, {get_apps, Kind}} ->
AppNames =
case Kind of
whitelist ->
- [A ||
- A <- Sys#sys.apps,
- A#app.is_pre_included =:= true];
- blacklist ->
- [A ||
- A <- Sys#sys.apps,
- A#app.is_pre_included =:= false];
- source ->
- [A ||
- A <- Sys#sys.apps,
- A#app.is_included =/= true,
- A#app.is_pre_included =/= false];
+ %% Pre-included
+ ets:select(S#state.app_tab,
+ [{#app{is_pre_included=true,_='_'},
+ [],
+ ['$_']}]);
+ blacklist ->
+ %% Pre-excluded
+ ets:select(S#state.app_tab,
+ [{#app{is_pre_included=false,_='_'},
+ [],
+ ['$_']}]);
+ source ->
+ %% Not included and not pre-excluded
+ ets:select(S#state.app_tab,
+ [{#app{is_included='$1',
+ is_pre_included='$2',
+ _='_'},
+ [{'=/=','$1',true},
+ {'=/=','$2',false}],
+ ['$_']}]);
derived ->
- [A ||
- A <- Sys#sys.apps,
- A#app.is_included =:= true,
- A#app.is_pre_included =/= true]
+ %% Included, but not pre-included
+ ets:select(S#state.app_tab,
+ [{#app{is_included='$1',
+ is_pre_included='$2',
+ _='_'},
+ [{'=:=','$1',true},
+ {'=/=','$2',true}],
+ ['$_']}])
end,
reltool_utils:reply(ReplyTo, Ref, {ok, AppNames}),
?MODULE:loop(S);
{call, ReplyTo, Ref, {set_apps, Apps}} ->
- {S2, Status} =
- lists:foldl(fun(A, {X, Y}) -> do_set_app(X, A, Y) end,
- {S, {ok, []}},
- Apps),
- {S3, Status2} = analyse(S2, Status),
+ Fun = fun() -> do_set_apps(S, Apps) end,
+ {S3, Status2} = config_and_refresh(S, Fun),
reltool_utils:reply(ReplyTo, Ref, Status2),
- ?MODULE:loop(S3);
+ ?MODULE:loop(S3);
{call, ReplyTo, Ref, get_sys} ->
reltool_utils:reply(ReplyTo, Ref, {ok, Sys#sys{apps = undefined}}),
?MODULE:loop(S);
{call, ReplyTo, Ref, {set_sys, Sys2}} ->
- S2 = S#state{sys = Sys2#sys{apps = Sys#sys.apps}},
- Force =
- (Sys2#sys.root_dir =/= Sys#sys.root_dir) orelse
- (Sys2#sys.lib_dirs =/= Sys#sys.lib_dirs) orelse
- (Sys2#sys.escripts =/= Sys#sys.escripts),
- {S3, Status} = refresh(S2, Force, {ok, []}),
- {S4, Status2} =
- analyse(S3#state{old_sys = S#state.sys}, Status),
- {S5, Status3} =
- case Status2 of
- {ok, _Warnings} -> % BUGBUG: handle warnings
- {S4#state{status = Status2,
- old_status = S#state.status},
- Status2};
- {error, _} ->
- %% Keep old state
- {S, Status2}
- end,
- reltool_utils:reply(ReplyTo, Ref, Status3),
- ?MODULE:loop(S5);
+ Fun = fun() -> S#state{sys = Sys2#sys{apps = Sys#sys.apps}} end,
+ {S3, Status} = config_and_refresh(S, Fun),
+ reltool_utils:reply(ReplyTo, Ref, Status),
+ ?MODULE:loop(S3);
{call, ReplyTo, Ref, get_status} ->
reltool_utils:reply(ReplyTo, Ref, S#state.status),
?MODULE:loop(S);
{call, ReplyTo, Ref, {gen_rel_files, Dir}} ->
Status =
- case reltool_target:gen_rel_files(S#state.sys, Dir) of
+ case reltool_target:gen_rel_files(sys_all_apps(S), Dir) of
ok ->
{ok, []};
{error, Reason} ->
@@ -402,11 +389,11 @@ loop(#state{common = C, sys = Sys} = S) ->
reltool_utils:reply(ReplyTo, Ref, Status),
?MODULE:loop(S);
{call, ReplyTo, Ref, {gen_target, Dir}} ->
- Reply = reltool_target:gen_target(S#state.sys, Dir),
+ Reply = reltool_target:gen_target(sys_all_apps(S), Dir),
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
{call, ReplyTo, Ref, gen_spec} ->
- Reply = reltool_target:gen_spec(S#state.sys),
+ Reply = reltool_target:gen_spec(sys_all_apps(S)),
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
{'EXIT', Pid, Reason} when Pid =:= S#state.parent_pid ->
@@ -422,101 +409,215 @@ loop(#state{common = C, sys = Sys} = S) ->
?MODULE:loop(S)
end.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-do_set_app(#state{sys = Sys} = S, App, Status) ->
- AppName = App#app.name,
- {App2, Status2} = refresh_app(App, false, Status),
- Apps = Sys#sys.apps,
- Apps2 = lists:keystore(AppName, #app.name, Apps, App2),
- Escripts = [A#app.active_dir || A <- Apps2, A#app.is_escript],
- Sys2 = Sys#sys{apps = Apps2, escripts = Escripts},
- {S#state{sys = Sys2}, Status2}.
-
-analyse(#state{common = C,
- sys = #sys{apps = Apps0, rels = Rels} = Sys} = S,
- Status) ->
- Apps = lists:keydelete(?MISSING_APP_NAME, #app.name, Apps0),
- ets:delete_all_objects(C#common.app_tab),
- ets:delete_all_objects(C#common.mod_tab),
- ets:delete_all_objects(C#common.mod_used_by_tab),
- MissingApp = default_app(?MISSING_APP_NAME, "missing"),
- ets:insert(C#common.app_tab, MissingApp),
-
- {RevRelApps, Status2} = apps_in_rels(Rels, Apps, Status),
- RelApps2 = lists:reverse(RevRelApps),
- {Apps2, Status3} =
- lists:mapfoldl(fun(App, Acc) ->
- app_init_is_included(C, Sys, App, RelApps2, Acc)
- end,
- Status2,
- Apps),
- Apps3 =
- case app_propagate_is_included(C, Sys, Apps2, []) of
- [] ->
- Apps2;
- MissingMods ->
- %% io:format("Missing mods: ~p\n", [MissingMods]),
- MissingApp2 = MissingApp#app{label = ?MISSING_APP_TEXT,
- info = missing_app_info(""),
- mods = MissingMods,
- status = missing,
- uses_mods = []},
- [MissingApp2 | Apps2]
- end,
- app_propagate_is_used_by(C, 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, Status4) of
- {ok, _Warnings} = Status5 ->
- {S#state{sys = Sys2}, Status5};
- {error, _} = Status5 ->
- {S, Status5}
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+do_set_apps(#state{sys = Sys} = S, ChangedApps) ->
+ %% Create new list of configured applications
+ SysApps = app_update_config(ChangedApps, Sys#sys.apps),
+ S#state{sys = Sys#sys{apps = SysApps}}.
+
+%% Re-create the #sys.apps list by
+%% 1) taking configurable fields from the changed #app records and
+%% create new default records
+%% 2) removing #app records if no configurable fields are set
+%% 3) keeping #app records that are not changed
+app_update_config([#app{name=Name,is_escript={inlined,Escript}}|_],_SysApps) ->
+ reltool_utils:throw_error("Application ~p is inlined in ~p. Can not change "
+ "configuration for an inlined application.",
+ [Name,Escript]);
+app_update_config([Config|Configs],SysApps) ->
+ NewSysApps =
+ case app_set_config_only(Config) of
+ {delete,Name} ->
+ lists:keydelete(Name,#app.name,SysApps);
+ New ->
+ lists:ukeymerge(#app.name,[New],SysApps)
+ end,
+ app_update_config(Configs,NewSysApps);
+app_update_config([],SysApps) ->
+ SysApps.
+
+app_set_config_only(#app{mods=ConfigMods} = Config) ->
+ app_set_config_only(mod_set_config_only(ConfigMods),Config).
+
+app_set_config_only([],#app{name = Name,
+ incl_cond = undefined,
+ mod_cond = undefined,
+ use_selected_vsn = undefined,
+ debug_info = undefined,
+ app_file = undefined,
+ app_type = undefined,
+ incl_app_filters = undefined,
+ excl_app_filters = undefined,
+ incl_archive_filters = undefined,
+ excl_archive_filters = undefined,
+ archive_opts = undefined,
+ is_escript = false})->
+ {delete,Name};
+app_set_config_only(Mods,#app{name = Name,
+ incl_cond = InclCond,
+ mod_cond = ModCond,
+ use_selected_vsn = UseSelectedVsn,
+ debug_info = DebugInfo,
+ app_file = AppFile,
+ app_type = AppType,
+ incl_app_filters = InclAppFilters,
+ excl_app_filters = ExclAppFilters,
+ incl_archive_filters = InclArchiveFilters,
+ excl_archive_filters = ExclArchiveFilters,
+ archive_opts = ArchiveOpts,
+ vsn = Vsn,
+ is_escript = IsEscript,
+ label = Label,
+ info = Info,
+ active_dir = ActiveDir,
+ sorted_dirs = SortedDirs}) ->
+ App = (default_app(Name))#app{incl_cond = InclCond,
+ mod_cond = ModCond,
+ use_selected_vsn = UseSelectedVsn,
+ debug_info = DebugInfo,
+ app_file = AppFile,
+ app_type = AppType,
+ incl_app_filters = InclAppFilters,
+ excl_app_filters = ExclAppFilters,
+ incl_archive_filters = InclArchiveFilters,
+ excl_archive_filters = ExclArchiveFilters,
+ archive_opts = ArchiveOpts,
+ vsn = Vsn,
+ mods = Mods},
+
+ if IsEscript ->
+ %% Some fields shall only be set if it is an escript, e.g. label
+ %% must never be set for any other applications since that will
+ %% prevent refreshing.
+ App#app{is_escript = IsEscript,
+ active_dir = ActiveDir,
+ sorted_dirs = SortedDirs,
+ label = Label,
+ info = Info};
+ UseSelectedVsn =:= dir ->
+ %% Must not loose active_dir if it is configured to be used
+ App#app{active_dir = ActiveDir,
+ sorted_dirs = [ActiveDir]};
+ true ->
+ App
end.
-apps_in_rels(Rels, Apps, Status) ->
- lists:foldl(fun(Rel, {RelApps, S}) ->
- {MoreRelApps, S2} = apps_in_rel(Rel, Apps, S),
- {MoreRelApps ++ RelApps, S2}
- end,
- {[], Status},
- Rels).
+mod_set_config_only(ConfigMods) ->
+ [#mod{name = Name,
+ incl_cond = InclCond,
+ debug_info = DebugInfo} ||
+ #mod{name = Name,
+ incl_cond = InclCond,
+ debug_info = DebugInfo} <- ConfigMods,
+ (InclCond =/= undefined) orelse (DebugInfo =/= undefined)].
-apps_in_rel(#rel{name = RelName, rel_apps = RelApps}, Apps, Status) ->
- Mandatory = [{RelName, kernel}, {RelName, stdlib}],
- Other = [{RelName, AppName} ||
- RA <- RelApps,
- AppName <- [RA#rel_app.name | RA#rel_app.incl_apps],
- not lists:keymember(AppName, 2, Mandatory)],
- more_apps_in_rels(Mandatory ++ Other, Apps, [], Status).
-more_apps_in_rels([{RelName, AppName} = RA | RelApps], Apps, Acc, Status) ->
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+analyse(#state{sys=Sys} = S, Apps, Status) ->
+ %% Create a list of {RelName,AppName}, one element for each
+ %% AppName that needs to be included for the given release.
+ RelApps = apps_in_rels(Sys#sys.rels, Apps),
+
+ %% Initiate is_pre_included and is_included for all applications
+ %% based on #sys.incl_cond, #app.incl_cond and if the application
+ %% is included in a release (rel spec - see apps_in_rels above).
+ %% Then initiate the same for each module, and check that there
+ %% are no duplicated module names (in different applications)
+ %% where we can not decide which one to use.
+ %% Write all #app to app_tab and all #mod to mod_tab.
+ Status2 = apps_init_is_included(S, Apps, RelApps, Status),
+
+ %% For each module that has #mod.is_included==true, propagate
+ %% is_included to the modules it uses.
+ propagate_is_included(S),
+
+ %% Insert reverse dependencies - i.e. for each
+ %% #mod{name=Mod, uses_mods=[UsedMod]},
+ %% insert an entry {UsedMod,Mod} in mod_used_by_tab.
+ propagate_is_used_by(S),
+
+ %% Set the above reverse dependencies in #mod records
+ %% (used_by_mods) and accumulate in #app records.
+ %% Make sure #app.is_included is always true if some
+ %% #mod.is_included==true for at least one module in the app.
+ %% Set status=missing|ok for #app and #mod - indicates if module
+ %% (.beam file) is missing in file system.
+ app_recap_dependencies(S),
+
+ %% Check that the boot_rel exists.
+ %% Check that all applications that are listed in a 'rel' spec are
+ %% also really included in the target release.
+ %% Check that all mandatory applications are included in all rels.
+ verify_config(S, RelApps, Status2).
+
+apps_in_rels(Rels, Apps) ->
+ AllRelApps =
+ lists:foldl(fun(Rel, RelApps) ->
+ MoreRelApps = apps_in_rel(Rel, Apps),
+ MoreRelApps ++ RelApps
+ end,
+ [],
+ Rels),
+ lists:reverse(AllRelApps).
+
+apps_in_rel(#rel{name = RelName, rel_apps = RelApps}, Apps) ->
+ Mandatory = [{RelName, kernel}, {RelName, stdlib}],
+ Other =
+ [{RelName, AppName} ||
+ RA <- RelApps,
+ AppName <- [RA#rel_app.name |
+ %% Included applications in rel shall overwrite included
+ %% applications in .app. I.e. included applications in
+ %% .app shall only be used if it is not defined in rel.
+ case RA#rel_app.incl_apps of
+ undefined ->
+ case lists:keyfind(RA#rel_app.name,
+ #app.name,
+ Apps) of
+ #app{info = #app_info{incl_apps = IA}} ->
+ IA;
+ false ->
+ reltool_utils:throw_error(
+ "Release ~p uses non existing "
+ "application ~p",
+ [RelName,RA#rel_app.name])
+ end;
+ IA ->
+ IA
+ end],
+ not lists:keymember(AppName, 2, Mandatory)],
+ more_apps_in_rels(Mandatory ++ Other, Apps, []).
+
+more_apps_in_rels([{RelName, AppName} = RA | RelApps], Apps, Acc) ->
case lists:member(RA, Acc) of
true ->
- more_apps_in_rels(RelApps, Apps, Acc, Status);
+ more_apps_in_rels(RelApps, Apps, Acc);
false ->
case lists:keyfind(AppName, #app.name, Apps) of
#app{info = #app_info{applications = InfoApps}} ->
Extra = [{RelName, N} || N <- InfoApps],
- {Acc2, Status2} =
- more_apps_in_rels(Extra, Apps, [RA | Acc], Status),
- more_apps_in_rels(RelApps, Apps, Acc2, Status2);
+ Acc2 = more_apps_in_rels(Extra, Apps, [RA | Acc]),
+ more_apps_in_rels(RelApps, Apps, Acc2);
false ->
- Text = lists:concat(["Release ", RelName,
- " uses non existing application ",
- AppName]),
- Status2 = reltool_utils:return_first_error(Status, Text),
- more_apps_in_rels(RelApps, Apps, Acc, Status2)
+ reltool_utils:throw_error(
+ "Release ~p uses non existing application ~p",
+ [RelName,AppName])
end
end;
-more_apps_in_rels([], _Apps, Acc, Status) ->
- {Acc, Status}.
+more_apps_in_rels([], _Apps, Acc) ->
+ Acc.
-app_init_is_included(C,
- Sys,
+
+apps_init_is_included(S, Apps, RelApps, Status) ->
+ lists:foldl(fun(App, AccStatus) ->
+ app_init_is_included(S, App, RelApps, AccStatus)
+ end,
+ Status,
+ Apps).
+
+app_init_is_included(#state{app_tab = AppTab, mod_tab = ModTab, sys=Sys},
#app{name = AppName, mods = Mods} = A,
RelApps,
Status) ->
@@ -538,18 +639,16 @@ app_init_is_included(C,
{exclude, []} ->
{undefined, false, false, Status};
{exclude, [RelName | _]} -> % App is included in at least one rel
- Text = lists:concat(["Application ", AppName, " is used "
- "in release ", RelName, " and cannot "
- "be excluded"]),
- TmpStatus = reltool_utils:return_first_error(Status, Text),
- {undefined, false, false, TmpStatus};
+ reltool_utils:throw_error(
+ "Application ~p is used in release ~p and cannot be excluded",
+ [AppName,RelName]);
{derived, []} ->
{undefined, undefined, undefined, Status};
{derived, [_ | _]} -> % App is included in at least one rel
{true, undefined, true, Status}
end,
{Mods2,Status3} = lists:mapfoldl(fun(Mod,Acc) ->
- mod_init_is_included(C,
+ mod_init_is_included(ModTab,
Mod,
ModCond,
AppCond,
@@ -562,10 +661,10 @@ app_init_is_included(C,
is_pre_included = IsPreIncl,
is_included = IsIncl,
rels = Rels},
- ets:insert(C#common.app_tab, A2),
- {A2, Status3}.
+ ets:insert(AppTab, A2),
+ Status3.
-mod_init_is_included(C, M, ModCond, AppCond, Default, Status) ->
+mod_init_is_included(ModTab, M, ModCond, AppCond, Default, Status) ->
%% print(M#mod.name, hipe, "incl_cond -> ~p\n", [AppCond]),
IsIncl =
case AppCond of
@@ -602,43 +701,33 @@ mod_init_is_included(C, M, ModCond, AppCond, Default, Status) ->
M2 = M#mod{is_pre_included = IsIncl, is_included = IsIncl},
Status2 =
- case ets:lookup(C#common.mod_tab,M#mod.name) of
+ case ets:lookup(ModTab,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);
+ ets:insert(ModTab, M2),
+ reltool_utils:add_warning(
+ "Module ~p exists in applications ~p and ~p. "
+ "Using module from application ~p.",
+ [M#mod.name, Existing#mod.app_name,
+ M#mod.app_name, M#mod.app_name],
+ Status);
{_,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);
+ %% Don't insert in ModTab - using Existing
+ reltool_utils:add_warning(
+ "Module ~p exists in applications ~p and ~p. "
+ "Using module from application ~p.",
+ [M#mod.name, Existing#mod.app_name,
+ M#mod.app_name,Existing#mod.app_name],
+ Status);
{_,_} ->
- 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)
+ reltool_utils:throw_error(
+ "Module ~p potentially included by two different "
+ "applications: ~p and ~p.",
+ [M#mod.name,Existing#mod.app_name,M#mod.app_name])
end;
[] ->
- ets:insert(C#common.mod_tab, M2),
+ ets:insert(ModTab, M2),
Status
end,
@@ -651,55 +740,43 @@ false_to_undefined(Bool) ->
_ -> Bool
end.
-app_propagate_is_included(C, Sys, [#app{mods = Mods} = A | Apps], Acc) ->
- Acc2 = mod_propagate_is_included(C, Sys, A, Mods, Acc),
- app_propagate_is_included(C, Sys, Apps, Acc2);
-app_propagate_is_included(_C, _Sys, [], Acc) ->
- Acc.
-
-mod_propagate_is_included(C, Sys, A, [#mod{name = ModName} | Mods], Acc) ->
- Acc2 =
- 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.
+%% Return the list for {ModName, UsesModNames} for all modules where
+%% #mod.is_included==true.
+get_all_mods_and_dependencies(S) ->
+ ets:select(S#state.mod_tab, [{#mod{name='$1',
+ uses_mods='$2',
+ is_included=true,
+ _='_'},
+ [],
+ [{{'$1','$2'}}]}]).
+
+propagate_is_included(S) ->
+ case lists:flatmap(
+ fun({ModName,UsesModNames}) ->
+ mod_mark_is_included(S,ModName,UsesModNames,[])
+ end,
+ get_all_mods_and_dependencies(S)) of
+ [] ->
+ ok;
+ MissingMods ->
+ MissingApp = default_app(?MISSING_APP_NAME, "missing"),
+ MissingApp2 = MissingApp#app{label = ?MISSING_APP_TEXT,
+ info = missing_app_info(""),
+ mods = MissingMods,
+ status = missing,
+ uses_mods = []},
+ ets:insert(S#state.app_tab, MissingApp2),
+ ok
+ end.
-mod_mark_is_included(C, Sys, UsedByName, [ModName | ModNames], Acc) ->
+mod_mark_is_included(#state{app_tab=AppTab, mod_tab=ModTab, sys=Sys} = S,
+ UsedByName, [ModName | ModNames], Acc) ->
Acc3 =
- case ets:lookup(C#common.mod_tab, ModName) of
+ case ets:lookup(ModTab, ModName) of
[M] ->
- %% print(UsedByName, file, "Maybe Mark ~p -> ~p\n",
- %% [M, M#mod.is_included]),
- %% print(UsedByName, filename, "Maybe Mark ~p -> ~p\n",
- %% [M, M#mod.is_included]),
case M#mod.is_included of
- true ->
- %% Already marked
- Acc;
- false ->
- %% Already marked
- Acc;
undefined ->
- %% Mark and propagate
+ %% Not yet marked => mark and propagate
M2 =
case M#mod.incl_cond of
include ->
@@ -711,16 +788,10 @@ mod_mark_is_included(C, Sys, UsedByName, [ModName | ModNames], Acc) ->
undefined ->
M#mod{is_included = true}
end,
- ets:insert(C#common.mod_tab, M2),
- %% io:format("Propagate mod: ~p -> ~p (~p)\n",
- %% [UsedByName, ModName, M#mod.incl_cond]),
- [A] = ets:lookup(C#common.app_tab, M2#mod.app_name),
+ ets:insert(ModTab, M2),
+ [A] = ets:lookup(AppTab, M2#mod.app_name),
Acc2 =
case A#app.is_included of
- true ->
- Acc;
- false ->
- Acc;
undefined ->
ModCond =
case A#app.mod_cond of
@@ -738,63 +809,50 @@ mod_mark_is_included(C, Sys, UsedByName, [ModName | ModNames], Acc) ->
end
end,
Mods = lists:filter(Filter, A#app.mods),
- %% io:format("Propagate app: ~p ~p -> ~p\n",
- %% [UsedByName, A#app.name,
- %% [M3#mod.name || M3 <- Mods]]),
A2 = A#app{is_included = true},
- ets:insert(C#common.app_tab, A2),
- mod_mark_is_included(C,
- Sys,
+ ets:insert(AppTab, A2),
+ mod_mark_is_included(S,
ModName,
[M3#mod.name ||
M3 <- Mods],
- Acc)
+ Acc);
+ _ ->
+ %% Already marked true or false
+ Acc
end,
- mod_mark_is_included(C,
- Sys,
- ModName,
- M2#mod.uses_mods,
- Acc2)
+ mod_mark_is_included(S, ModName, M2#mod.uses_mods, Acc2);
+ _ ->
+ %% Already marked true or false
+ Acc
end;
[] ->
M = missing_mod(ModName, ?MISSING_APP_NAME),
M2 = M#mod{is_included = true},
- ets:insert(C#common.mod_tab, M2),
- ets:insert(C#common.mod_used_by_tab, {UsedByName, ModName}),
+ ets:insert(ModTab, M2),
[M2 | Acc]
end,
- mod_mark_is_included(C, Sys, UsedByName, ModNames, Acc3);
-mod_mark_is_included(_C, _Sys, _UsedByName, [], Acc) ->
+ mod_mark_is_included(S, UsedByName, ModNames, Acc3);
+mod_mark_is_included(_S, _UsedByName, [], Acc) ->
Acc.
-app_propagate_is_used_by(C, [#app{mods = Mods, name = Name} | Apps]) ->
- case Name =:= ?MISSING_APP_NAME of
- true -> ok;
- false -> ok
- end,
- mod_propagate_is_used_by(C, Mods),
- app_propagate_is_used_by(C, Apps);
-app_propagate_is_used_by(_C, []) ->
- ok.
+propagate_is_used_by(S) ->
+ lists:foreach(
+ fun({Mod,UsesMods}) ->
+ lists:foreach(
+ fun(UsedMod) ->
+ ets:insert(S#state.mod_used_by_tab,{UsedMod,Mod})
+ end,
+ UsesMods)
+ end,
+ get_all_mods_and_dependencies(S)).
-mod_propagate_is_used_by(C, [#mod{name = ModName} | Mods]) ->
- [M] = ets:lookup(C#common.mod_tab, ModName),
- case M#mod.is_included of
- true ->
- [ets:insert(C#common.mod_used_by_tab, {UsedModName, ModName}) ||
- UsedModName <- M#mod.uses_mods];
- false ->
- ignore;
- undefined ->
- ignore
- end,
- mod_propagate_is_used_by(C, Mods);
-mod_propagate_is_used_by(_C, []) ->
- ok.
-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),
+app_recap_dependencies(S) ->
+ ets:foldl(fun(App,_) -> app_recap_dependencies(S,App) end,
+ ok, S#state.app_tab).
+
+app_recap_dependencies(S, #app{mods = Mods, is_included = IsIncl} = A) ->
+ {Mods2, IsIncl2} = mod_recap_dependencies(S, A, Mods, [], IsIncl),
AppStatus =
case lists:keymember(missing, #mod.status, Mods2) of
true -> missing;
@@ -803,12 +861,12 @@ app_recap_dependencies(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Ap
UsesMods = [M#mod.uses_mods || M <- Mods2, M#mod.is_included =:= true],
UsesMods2 = lists:usort(lists:flatten(UsesMods)),
UsesApps = [M#mod.app_name || ModName <- UsesMods2,
- M <- ets:lookup(C#common.mod_tab, ModName)],
+ M <- ets:lookup(S#state.mod_tab, ModName)],
UsesApps2 = lists:usort(UsesApps),
UsedByMods = [M#mod.used_by_mods || M <- Mods2, M#mod.is_included =:= true],
UsedByMods2 = lists:usort(lists:flatten(UsedByMods)),
UsedByApps = [M#mod.app_name || ModName <- UsedByMods2,
- M <- ets:lookup(C#common.mod_tab, ModName)],
+ M <- ets:lookup(S#state.mod_tab, ModName)],
UsedByApps2 = lists:usort(UsedByApps),
A2 = A#app{mods = Mods2,
@@ -818,13 +876,11 @@ app_recap_dependencies(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Ap
uses_apps = UsesApps2,
used_by_apps = UsedByApps2,
is_included = IsIncl2},
- 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}.
+ ets:insert(S#state.app_tab,A2),
+ ok.
-mod_recap_dependencies(C, Sys, A, [#mod{name = ModName}=M1 | Mods], Acc, IsIncl, Status) ->
- case ets:lookup(C#common.mod_tab, ModName) of
+mod_recap_dependencies(S, A, [#mod{name = ModName}=M1 | Mods], Acc, IsIncl) ->
+ case ets:lookup(S#state.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]),
@@ -832,32 +888,28 @@ mod_recap_dependencies(C, Sys, A, [#mod{name = ModName}=M1 | Mods], Acc, IsIncl,
case M2#mod.is_included of
true ->
UsedByMods =
- [N || {_, N} <- ets:lookup(C#common.mod_used_by_tab,
+ [N || {_, N} <- ets:lookup(S#state.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);
+ ets:insert(S#state.mod_tab, M3),
+ mod_recap_dependencies(S, A, Mods, [M3 | Acc], IsIncl2);
[_] 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);
+ mod_recap_dependencies(S, A, Mods, [M1 | Acc], IsIncl);
[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)
+ reltool_utils:throw_error(
+ "Module ~p potentially included by two different applications: "
+ "~p and ~p", [ModName,A#app.name, " and ", M2#mod.app_name, "."])
end;
-mod_recap_dependencies(_C, _Sys, _A, [], Acc, IsIncl, Status) ->
- {lists:reverse(Acc), IsIncl, Status}.
+mod_recap_dependencies(_S, _A, [], Acc, IsIncl) ->
+ {lists:reverse(Acc), IsIncl}.
do_get_status(M) ->
if
@@ -867,48 +919,49 @@ do_get_status(M) ->
ok
end.
-shrink_sys(#state{sys = #sys{apps = Apps} = Sys} = S) ->
- Apps2 = lists:zf(fun filter_app/1, Apps),
- S#state{sys = Sys#sys{apps = Apps2}}.
-
-filter_app(A) ->
- Mods = [M#mod{is_app_mod = undefined,
- is_ebin_mod = undefined,
- uses_mods = undefined,
- exists = false} ||
- M <- A#app.mods,
- M#mod.incl_cond =/= undefined],
- if
- A#app.is_escript ->
- {true, A#app{vsn = undefined,
- label = undefined,
- info = undefined,
- mods = [],
- uses_mods = undefined}};
- Mods =:= [],
- A#app.mod_cond =:= undefined,
- A#app.incl_cond =:= undefined,
- A#app.use_selected_vsn =:= undefined ->
- false;
+verify_config(#state{app_tab=AppTab, sys=#sys{boot_rel = BootRel, rels = Rels}},
+ RelApps, Status) ->
+ case lists:keymember(BootRel, #rel.name, Rels) of
true ->
- {Dir, Dirs, OptVsn} =
- case A#app.use_selected_vsn of
- undefined ->
- {shrinked, [], undefined};
- false ->
- {shrinked, [], undefined};
- true ->
- {A#app.active_dir, [A#app.active_dir], A#app.vsn}
- end,
- {true, A#app{active_dir = Dir,
- sorted_dirs = Dirs,
- vsn = OptVsn,
- label = undefined,
- info = undefined,
- mods = Mods,
- uses_mods = undefined}}
+ Status2 = lists:foldl(fun(RA, Acc) ->
+ check_app(AppTab, RA, Acc) end,
+ Status,
+ RelApps),
+ lists:foldl(fun(#rel{name = RelName}, Acc)->
+ check_rel(RelName, RelApps, Acc)
+ end,
+ Status2,
+ Rels);
+ false ->
+ reltool_utils:throw_error(
+ "Release ~p is mandatory (used as boot_rel)",[BootRel])
+ end.
+
+check_app(AppTab, {RelName, AppName}, Status) ->
+ case ets:lookup(AppTab, AppName) of
+ [#app{is_pre_included=IsPreIncl, is_included=IsIncl}]
+ when IsPreIncl; IsIncl ->
+ Status;
+ _ ->
+ reltool_utils:throw_error(
+ "Release ~p uses non included application ~p",[RelName,AppName])
end.
+check_rel(RelName, RelApps, Status) ->
+ EnsureApp =
+ fun(AppName, Acc) ->
+ case lists:member({RelName, AppName}, RelApps) of
+ true ->
+ Acc;
+ false ->
+ reltool_utils:throw_error(
+ "Mandatory application ~p is not included in "
+ "release ~p", [AppName,RelName])
+ end
+ end,
+ Mandatory = [kernel, stdlib],
+ lists:foldl(EnsureApp, Status, Mandatory).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
refresh_app(#app{name = AppName,
@@ -937,30 +990,57 @@ refresh_app(#app{name = AppName,
AppName,
DefaultVsn,
Status),
+
+ %% And read all modules from ebin and create
+ %% #mod record with dependencies (uses_mods).
{AI, read_ebin_mods(Ebin, AppName), Status2};
- true ->
+ _ ->
{App#app.info, Mods, Status}
end,
- %% Add non-existing modules
- AppInfoMods = AppInfo#app_info.modules,
- AppModNames =
- case AppInfo#app_info.mod of
- {StartModName, _} ->
- case lists:member(StartModName, AppInfoMods) of
- true -> AppInfoMods;
- false -> [StartModName | AppInfoMods]
- end;
- undefined ->
- AppInfoMods
- end,
- MissingMods = add_missing_mods(AppName, EbinMods, AppModNames),
+ %% Add non-existing modules - i.e. create default #mod
+ %% records for all modules that are listed in .app file
+ %% but do not exist in ebin.
+ AppInfoMods = lists:usort(AppInfo#app_info.modules),
+ Status4 =
+ case AppInfo#app_info.modules -- AppInfoMods of
+ [] ->
+ Status3;
+ DuplicatedMods ->
+ lists:foldl(
+ fun(M,S) ->
+ reltool_utils:add_warning(
+ "Module ~p duplicated in app file for "
+ "application ~p.", [M, AppName], S)
+ end,
+ Status3,
+ DuplicatedMods)
+ end,
+ AppModNames =
+ case AppInfo#app_info.mod of
+ {StartModName, _} ->
+ case lists:member(StartModName, AppInfoMods) of
+ true -> AppInfoMods;
+ false -> [StartModName | AppInfoMods]
+ end;
+ undefined ->
+ AppInfoMods
+ end,
+ MissingMods = add_missing_mods(AppName, EbinMods, AppModNames),
- %% Add optional user config for each module
+ %% Add optional user config for each module.
+ %% The #mod records that are already in the #app record at
+ %% this point do only contain user defined configuration
+ %% (set by parse_options/4). So here we merge with the
+ %% default records from above.
Mods2 = add_mod_config(MissingMods ++ EbinMods, Mods),
- %% Set app flag for each module in app file
+ %% Set app flag for each module in app file, i.e. the flag
+ %% which indicates if the module is listed in the .app
+ %% file or not. The start module also get the flag set to true.
Mods3 = set_mod_flags(Mods2, AppModNames),
+
+ %% Finally, set label and update the #app record
AppVsn = AppInfo#app_info.vsn,
AppLabel =
case AppVsn of
@@ -971,7 +1051,7 @@ refresh_app(#app{name = AppName,
label = AppLabel,
info = AppInfo,
mods = lists:keysort(#mod.name, Mods3)},
- {App2, Status3};
+ {App2, Status4};
true ->
{App, Status}
end.
@@ -988,22 +1068,21 @@ read_app_info(AppFileOrBin, AppFile, AppName, DefaultVsn, Status) ->
AI = #app_info{vsn = DefaultVsn},
parse_app_info(AppFile, Info, AI, Status);
{ok, _BadApp} ->
- Text = lists:concat([AppName,
- ": Illegal contents in app file ", AppFile,
- ", application tuple with arity 3 expected."]),
{missing_app_info(DefaultVsn),
- reltool_utils:add_warning(Status, Text)};
+ reltool_utils:add_warning("~p: Illegal contents in app file ~p, "
+ "application tuple with arity 3 expected.",
+ [AppName,AppFile],
+ Status)};
{error, Text} when Text =:= EnoentText ->
- Text2 = lists:concat([AppName,
- ": Missing app file ", AppFile, "."]),
{missing_app_info(DefaultVsn),
- reltool_utils:add_warning(Status, Text2)};
+ reltool_utils:add_warning("~p: Missing app file ~p.",
+ [AppName,AppFile],
+ Status)};
{error, Text} ->
- Text2 = lists:concat([AppName,
- ": Cannot parse app file ",
- AppFile, " (", Text, ")."]),
{missing_app_info(DefaultVsn),
- reltool_utils:add_warning(Status, Text2)}
+ reltool_utils:add_warning("~p: Cannot parse app file ~p (~p).",
+ [AppName,AppFile,Text],
+ Status)}
end.
parse_app_info(File, [{Key, Val} | KeyVals], AI, Status) ->
@@ -1037,10 +1116,11 @@ parse_app_info(File, [{Key, Val} | KeyVals], AI, Status) ->
parse_app_info(File, KeyVals, AI#app_info{start_phases = Val},
Status);
_ ->
- String = lists:concat(["Unexpected item ",
- Key, "in app file ", File]),
- parse_app_info(File, KeyVals, AI,
- reltool_utils:add_warning(Status, String))
+ Status2 =
+ reltool_utils:add_warning("Unexpected item ~p in app file ~p.",
+ [Key,File],
+ Status),
+ parse_app_info(File, KeyVals, AI, Status2)
end;
parse_app_info(_, [], AI, Status) ->
{AI, Status}.
@@ -1171,12 +1251,54 @@ set_mod_flags(Mods, AppModNames) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
do_get_config(S, InclDef, InclDeriv) ->
- S2 =
+ AppTab = S#state.app_tab,
+ Sys =
case InclDeriv of
- false -> shrink_sys(S);
- true -> S
+ false ->
+ %% Only the apps that exist in #sys.apps shall be
+ %% included,and they shall be minimized
+ Apps = [shrink_app(App) ||
+ #app{name=Name} <- (S#state.sys)#sys.apps,
+ App <- ets:lookup(AppTab,Name)],
+ (S#state.sys)#sys{apps=Apps};
+ true ->
+ sys_all_apps(S)
end,
- reltool_target:gen_config(S2#state.sys, InclDef).
+ reltool_target:gen_config(Sys, InclDef).
+
+shrink_app(A) ->
+ Mods = [M#mod{is_app_mod = undefined,
+ is_ebin_mod = undefined,
+ uses_mods = undefined,
+ exists = false} ||
+ M <- A#app.mods,
+ M#mod.incl_cond =/= undefined],
+ if
+ A#app.is_escript ->
+ A#app{vsn = undefined,
+ label = undefined,
+ info = undefined,
+ mods = [],
+ uses_mods = undefined};
+ true ->
+ {Dir, Dirs, OptVsn} =
+ case A#app.use_selected_vsn of
+ undefined ->
+ {undefined, [], undefined};
+ vsn ->
+ {undefined, [], A#app.vsn};
+ dir ->
+ {A#app.active_dir, [A#app.active_dir], undefined}
+ end,
+ A#app{active_dir = Dir,
+ sorted_dirs = Dirs,
+ vsn = OptVsn,
+ label = undefined,
+ info = undefined,
+ mods = Mods,
+ uses_mods = undefined}
+ end.
+
do_save_config(S, Filename, InclDef, InclDeriv) ->
{ok, Config} = do_get_config(S, InclDef, InclDeriv),
@@ -1187,132 +1309,83 @@ do_save_config(S, Filename, InclDef, InclDeriv) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
do_load_config(S, SysConfig) ->
- OldSys = S#state.sys,
- S2 = shrink_sys(S),
- ShrinkedSys = S2#state.sys,
- {NewSys, Status} =
- read_config(ShrinkedSys#sys{apps = []}, SysConfig, {ok, []}),
- case Status of
- {ok, _Warnings} ->
- Force = false,
- {MergedSys, Status2} = merge_config(OldSys, NewSys, Force, Status),
- {S3, Status3} =
- analyse(S2#state{sys = MergedSys, old_sys = OldSys}, Status2),
- S4 =
- case Status3 of
- {ok, _Warnings2} ->
- S3#state{status = Status3, old_status = S#state.status};
- {error, _} ->
- %% Keep old state
- S
- end,
- {S4, Status3};
- {error, _} ->
- %% Keep old state
- {S, Status}
- end.
+ S#state{sys = read_config(default_sys(), SysConfig)}.
-read_config(OldSys, Filename, Status) when is_list(Filename) ->
+read_config(OldSys, Filename) when is_list(Filename) ->
case file:consult(Filename) of
{ok, [SysConfig | _]} ->
- read_config(OldSys, SysConfig, Status);
+ read_config(OldSys, SysConfig);
{ok, Content} ->
- Text = lists:flatten(io_lib:format("~p", [Content])),
- {OldSys,
- reltool_utils:return_first_error(Status,
- "Illegal file content: " ++
- Text)};
+ reltool_utils:throw_error("Illegal file content: ~p",[Content]);
{error, Reason} ->
- Text = file:format_error(Reason),
- {OldSys,
- reltool_utils:return_first_error(Status,
- "Illegal config file " ++
- Filename ++ ": " ++ Text)}
+ reltool_utils:throw_error("Illegal config file ~p: ~s",
+ [Filename,file:format_error(Reason)])
end;
-read_config(OldSys, {sys, KeyVals}, Status) ->
- {NewSys, Status2} =
- decode(OldSys#sys{apps = [], rels = []}, KeyVals, Status),
- case Status2 of
- {ok, _Warnings} -> % BUGBUG: handle warnings
- Apps = [A#app{mods = lists:sort(A#app.mods)} ||
- A <- NewSys#sys.apps],
- case NewSys#sys.rels of
- [] -> Rels = reltool_utils:default_rels();
- Rels -> ok
- end,
- NewSys2 = NewSys#sys{apps = lists:sort(Apps),
- rels = lists:sort(Rels)},
- case lists:keymember(NewSys2#sys.boot_rel,
- #rel.name,
- NewSys2#sys.rels) of
- true ->
- {NewSys2, Status2};
- false ->
- Text2 = lists:concat(["Release " ++ NewSys2#sys.boot_rel,
- " is mandatory (used as boot_rel)"]),
- {OldSys, reltool_utils:return_first_error(Status2, Text2)}
- end;
- {error, _} ->
- %% Keep old state
- {OldSys, Status2}
+read_config(OldSys, {sys, KeyVals}) ->
+ NewSys = decode(OldSys#sys{apps = [], rels = []}, KeyVals),
+ Apps = [A#app{mods = lists:sort(A#app.mods)} || A <- NewSys#sys.apps],
+ Rels =
+ case NewSys#sys.rels of
+ [] -> reltool_utils:default_rels();
+ Rs -> Rs
+ end,
+ NewSys2 = NewSys#sys{apps = lists:sort(Apps),
+ rels = lists:sort(Rels)},
+ case lists:keymember(NewSys2#sys.boot_rel, #rel.name, NewSys2#sys.rels) of
+ true ->
+ NewSys2;
+ false ->
+ reltool_utils:throw_error(
+ "Release ~p is mandatory (used as boot_rel)",
+ [NewSys2#sys.boot_rel])
end;
-read_config(OldSys, BadConfig, Status) ->
- Text = lists:flatten(io_lib:format("~p", [BadConfig])),
- {OldSys,
- reltool_utils:return_first_error(Status, "Illegal content: " ++ Text)}.
+read_config(_OldSys, BadConfig) ->
+ reltool_utils:throw_error("Illegal content: ~p", [BadConfig]).
-decode(#sys{apps = Apps} = Sys, [{erts = Name, AppKeyVals} | SysKeyVals],
- Status)
+decode(#sys{apps = Apps} = Sys, [{erts = Name, AppKeyVals} | SysKeyVals])
when is_atom(Name), is_list(AppKeyVals) ->
App = default_app(Name),
- {App2, Status2} = decode(App, AppKeyVals, Status),
- decode(Sys#sys{apps = [App2 | Apps]}, SysKeyVals, Status2);
-decode(#sys{apps = Apps} = Sys, [{app, Name, AppKeyVals} | SysKeyVals], Status)
+ App2= decode(App, AppKeyVals),
+ decode(Sys#sys{apps = [App2 | Apps]}, SysKeyVals);
+decode(#sys{apps = Apps} = Sys, [{app, Name, AppKeyVals} | SysKeyVals])
when is_atom(Name), is_list(AppKeyVals) ->
App = default_app(Name),
- {App2, Status2} = decode(App, AppKeyVals, Status),
- decode(Sys#sys{apps = [App2 | Apps]}, SysKeyVals, Status2);
+ App2 = decode(App, AppKeyVals),
+ decode(Sys#sys{apps = [App2 | Apps]}, SysKeyVals);
decode(#sys{apps = Apps, escripts = Escripts} = Sys,
- [{escript, File, AppKeyVals} | SysKeyVals], Status)
- when is_list(File), is_list(AppKeyVals) ->
- {Name, Label} = split_escript_name(File),
- App = default_app(Name, File),
- App2 = App#app{is_escript = true,
- label = Label,
- info = missing_app_info(""),
- active_dir = File,
- sorted_dirs = [File]},
- {App3, Status2} = decode(App2, AppKeyVals, Status),
- decode(Sys#sys{apps = [App3 | Apps], escripts = [File | Escripts]},
- SysKeyVals,
- Status2);
-decode(#sys{rels = Rels} = Sys, [{rel, Name, Vsn, RelApps} | SysKeyVals],
- Status)
+ [{escript, File0, AppKeyVals} | SysKeyVals])
+ when is_list(File0), is_list(AppKeyVals) ->
+ File = filename:absname(File0),
+ App = default_escript_app(File),
+ App2 = decode(App, AppKeyVals),
+ decode(Sys#sys{apps = [App2 | Apps], escripts = [File | Escripts]},
+ SysKeyVals);
+decode(#sys{rels = Rels} = Sys, [{rel, Name, Vsn, RelApps} | SysKeyVals])
when is_list(Name), is_list(Vsn), is_list(RelApps) ->
Rel = #rel{name = Name, vsn = Vsn, rel_apps = []},
- {Rel2, Status2} = decode(Rel, RelApps, Status),
- decode(Sys#sys{rels = [Rel2 | Rels]}, SysKeyVals, Status2);
-decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) ->
- {Sys3, Status3} =
+ Rel2 = decode(Rel, RelApps),
+ decode(Sys#sys{rels = [Rel2 | Rels]}, SysKeyVals);
+decode(#sys{} = Sys, [{Key, Val} | KeyVals]) ->
+ Sys3 =
case Key of
root_dir when is_list(Val) ->
- {Sys#sys{root_dir = Val}, Status};
+ Sys#sys{root_dir = Val};
lib_dirs when is_list(Val) ->
- {Sys#sys{lib_dirs = Val}, Status};
+ Sys#sys{lib_dirs = Val};
mod_cond when Val =:= all;
Val =:= app;
Val =:= ebin;
Val =:= derived;
Val =:= none ->
- {Sys#sys{mod_cond = Val}, Status};
+ Sys#sys{mod_cond = Val};
incl_cond when Val =:= include;
Val =:= exclude;
Val =:= derived ->
- {Sys#sys{incl_cond = Val}, Status};
+ Sys#sys{incl_cond = Val};
boot_rel when is_list(Val) ->
- {Sys#sys{boot_rel = Val}, Status};
+ Sys#sys{boot_rel = Val};
emu_name when is_list(Val) ->
- {Sys#sys{emu_name = Val}, Status};
+ Sys#sys{emu_name = Val};
profile when Val =:= development;
Val =:= embedded;
Val =:= standalone ->
@@ -1321,198 +1394,169 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) ->
InclApp = reltool_utils:choose_default(incl_app_filters, Val, false),
ExclApp = reltool_utils:choose_default(excl_app_filters, Val, false),
AppType = reltool_utils:choose_default(embedded_app_type, Val, false),
- {Sys#sys{profile = Val,
- incl_sys_filters = dec_re(incl_sys_filters,
- InclSys,
- Sys#sys.incl_sys_filters),
- excl_sys_filters = dec_re(excl_sys_filters,
- ExclSys,
- Sys#sys.excl_sys_filters),
- incl_app_filters = dec_re(incl_app_filters,
- InclApp,
- Sys#sys.incl_app_filters),
- excl_app_filters = dec_re(excl_app_filters,
- ExclApp,
- Sys#sys.excl_app_filters),
- embedded_app_type = AppType},
- Status};
+ Sys#sys{profile = Val,
+ incl_sys_filters = dec_re(incl_sys_filters,
+ InclSys,
+ Sys#sys.incl_sys_filters),
+ excl_sys_filters = dec_re(excl_sys_filters,
+ ExclSys,
+ Sys#sys.excl_sys_filters),
+ incl_app_filters = dec_re(incl_app_filters,
+ InclApp,
+ Sys#sys.incl_app_filters),
+ excl_app_filters = dec_re(excl_app_filters,
+ ExclApp,
+ Sys#sys.excl_app_filters),
+ embedded_app_type = AppType};
+ excl_lib when Val =:= otp_root ->
+ Sys#sys{excl_lib=Val};
incl_sys_filters ->
- {Sys#sys{incl_sys_filters =
- dec_re(Key,
- Val,
- Sys#sys.incl_sys_filters)},
- Status};
+ Sys#sys{incl_sys_filters =
+ dec_re(Key, Val, Sys#sys.incl_sys_filters)};
excl_sys_filters ->
- {Sys#sys{excl_sys_filters =
- dec_re(Key,
- Val,
- Sys#sys.excl_sys_filters)},
- Status};
+ Sys#sys{excl_sys_filters =
+ dec_re(Key, Val, Sys#sys.excl_sys_filters)};
incl_app_filters ->
- {Sys#sys{incl_app_filters =
- dec_re(Key,
- Val,
- Sys#sys.incl_app_filters)},
- Status};
+ Sys#sys{incl_app_filters =
+ dec_re(Key, Val, Sys#sys.incl_app_filters)};
excl_app_filters ->
- {Sys#sys{excl_app_filters =
- dec_re(Key,
- Val,
- Sys#sys.excl_app_filters)},
- Status};
+ Sys#sys{excl_app_filters =
+ dec_re(Key, Val, Sys#sys.excl_app_filters)};
incl_archive_filters ->
- {Sys#sys{incl_archive_filters =
- dec_re(Key,
- Val,
- Sys#sys.incl_archive_filters)},
- Status};
+ Sys#sys{incl_archive_filters =
+ dec_re(Key, Val, Sys#sys.incl_archive_filters)};
excl_archive_filters ->
- {Sys#sys{excl_archive_filters =
- dec_re(Key,
- Val,
- Sys#sys.excl_archive_filters)},
- Status};
+ Sys#sys{excl_archive_filters =
+ dec_re(Key, Val, Sys#sys.excl_archive_filters)};
archive_opts when is_list(Val) ->
- {Sys#sys{archive_opts = Val}, Status};
+ Sys#sys{archive_opts = Val};
relocatable when Val =:= true; Val =:= false ->
- {Sys#sys{relocatable = Val}, Status};
+ Sys#sys{relocatable = Val};
rel_app_type when Val =:= permanent;
Val =:= transient;
Val =:= temporary;
Val =:= load;
Val =:= none ->
- {Sys#sys{rel_app_type = Val}, Status};
+ Sys#sys{rel_app_type = Val};
embedded_app_type when Val =:= permanent;
Val =:= transient;
Val =:= temporary;
Val =:= load;
Val =:= none;
Val =:= undefined ->
- {Sys#sys{embedded_app_type = Val}, Status};
+ Sys#sys{embedded_app_type = Val};
app_file when Val =:= keep; Val =:= strip; Val =:= all ->
- {Sys#sys{app_file = Val}, Status};
+ Sys#sys{app_file = Val};
debug_info when Val =:= keep; Val =:= strip ->
- {Sys#sys{debug_info = Val}, Status};
+ Sys#sys{debug_info = Val};
_ ->
- Text = lists:flatten(io_lib:format("~p", [{Key, Val}])),
- {Sys, reltool_utils:return_first_error(Status,
- "Illegal option: " ++
- Text)}
+ reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
end,
- decode(Sys3, KeyVals, Status3);
-decode(#app{} = App, [{Key, Val} | KeyVals], Status) ->
- {App2, Status2} =
+ decode(Sys3, KeyVals);
+decode(#app{} = App, [{Key, Val} | KeyVals]) ->
+ App2 =
case Key of
mod_cond when Val =:= all;
Val =:= app;
Val =:= ebin;
Val =:= derived;
Val =:= none ->
- {App#app{mod_cond = Val}, Status};
+ App#app{mod_cond = Val};
incl_cond when Val =:= include;
Val =:= exclude;
Val =:= derived ->
- {App#app{incl_cond = Val}, Status};
+ App#app{incl_cond = Val};
debug_info when Val =:= keep;
Val =:= strip ->
- {App#app{debug_info = Val}, Status};
+ App#app{debug_info = Val};
app_file when Val =:= keep;
Val =:= strip;
Val =:= all ->
- {App#app{app_file = Val}, Status};
+ App#app{app_file = Val};
app_type when Val =:= permanent;
Val =:= transient;
Val =:= temporary;
Val =:= load;
Val =:= none;
Val =:= undefined ->
- {App#app{app_type = Val}, Status};
+ App#app{app_type = Val};
incl_app_filters ->
- {App#app{incl_app_filters =
- dec_re(Key,
- Val,
- App#app.incl_app_filters)},
- Status};
+ App#app{incl_app_filters =
+ dec_re(Key, Val, App#app.incl_app_filters)};
excl_app_filters ->
- {App#app{excl_app_filters =
- dec_re(Key,
- Val,
- App#app.excl_app_filters)},
- Status};
+ App#app{excl_app_filters =
+ dec_re(Key, Val, App#app.excl_app_filters)};
incl_archive_filters ->
- {App#app{incl_archive_filters =
- dec_re(Key,
- Val,
- App#app.incl_archive_filters)},
- Status};
+ App#app{incl_archive_filters =
+ dec_re(Key, Val, App#app.incl_archive_filters)};
excl_archive_filters ->
- {App#app{excl_archive_filters =
- dec_re(Key,
- Val,
- App#app.excl_archive_filters)},
- Status};
+ App#app{excl_archive_filters =
+ dec_re(Key, Val, App#app.excl_archive_filters)};
archive_opts when is_list(Val) ->
- {App#app{archive_opts = Val}, Status};
- vsn when is_list(Val) ->
- {App#app{use_selected_vsn = true, vsn = Val}, Status};
+ App#app{archive_opts = Val};
+ vsn when is_list(Val), App#app.use_selected_vsn=:=undefined ->
+ App#app{use_selected_vsn = vsn, vsn = Val};
+ lib_dir when is_list(Val), App#app.use_selected_vsn=:=undefined ->
+ case filelib:is_dir(Val) of
+ true ->
+ Dir = reltool_utils:normalize_dir(Val),
+ App#app{use_selected_vsn = dir,
+ active_dir = Dir,
+ sorted_dirs = [Dir]};
+ false ->
+ reltool_utils:throw_error("Illegal lib dir for ~p: ~p",
+ [App#app.name, Val])
+ end;
+ SelectVsn when SelectVsn=:=vsn; SelectVsn=:=lib_dir ->
+ reltool_utils:throw_error("Mutual exclusive options "
+ "'vsn' and 'lib_dir'",[]);
_ ->
- Text = lists:flatten(io_lib:format("~p", [{Key, Val}])),
- {App, reltool_utils:return_first_error(Status,
- "Illegal option: " ++ Text)}
+ reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
end,
- decode(App2, KeyVals, Status2);
-decode(#app{mods = Mods} = App, [{mod, Name, ModKeyVals} | AppKeyVals],
- Status) ->
- {Mod, Status2} = decode(#mod{name = Name}, ModKeyVals, Status),
- decode(App#app{mods = [Mod | Mods]}, AppKeyVals, Status2);
-decode(#mod{} = Mod, [{Key, Val} | KeyVals], Status) ->
- {Mod2, Status2} =
+ decode(App2, KeyVals);
+decode(#app{mods = Mods} = App, [{mod, Name, ModKeyVals} | AppKeyVals]) ->
+ Mod = decode(#mod{name = Name}, ModKeyVals),
+ decode(App#app{mods = [Mod | Mods]}, AppKeyVals);
+decode(#mod{} = Mod, [{Key, Val} | KeyVals]) ->
+ Mod2 =
case Key of
incl_cond when Val =:= include; Val =:= exclude; Val =:= derived ->
- {Mod#mod{incl_cond = Val}, Status};
+ Mod#mod{incl_cond = Val};
debug_info when Val =:= keep; Val =:= strip ->
- {Mod#mod{debug_info = Val}, Status};
+ Mod#mod{debug_info = Val};
_ ->
- Text = lists:flatten(io_lib:format("~p", [{Key, Val}])),
- {Mod,
- reltool_utils:return_first_error(Status,
- "Illegal option: " ++ Text)}
+ reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
end,
- decode(Mod2, KeyVals, Status2);
-decode(#rel{rel_apps = RelApps} = Rel, [RelApp | KeyVals], Status) ->
+ decode(Mod2, KeyVals);
+decode(#rel{rel_apps = RelApps} = Rel, [RelApp | KeyVals]) ->
{ValidTypesAssigned, RA} =
case RelApp of
Name when is_atom(Name) ->
{true, #rel_app{name = Name}};
- {Name, Type} when is_atom(Name) ->
- {is_type(Type), #rel_app{name = Name, app_type = Type}};
{Name, InclApps} when is_atom(Name), is_list(InclApps) ->
VI = lists:all(fun erlang:is_atom/1, InclApps),
{VI, #rel_app{name = Name, incl_apps = InclApps}};
+ {Name, Type} when is_atom(Name) ->
+ {is_type(Type), #rel_app{name = Name, app_type = Type}};
{Name, Type, InclApps} when is_atom(Name), is_list(InclApps) ->
VT = is_type(Type),
VI = lists:all(fun erlang:is_atom/1, InclApps),
{VT andalso VI,
#rel_app{name = Name, app_type = Type, incl_apps = InclApps}};
_ ->
- {false, #rel_app{incl_apps = []}}
+ {false, #rel_app{}}
end,
case ValidTypesAssigned of
true ->
- decode(Rel#rel{rel_apps = RelApps ++ [RA]}, KeyVals, Status);
+ decode(Rel#rel{rel_apps = RelApps ++ [RA]}, KeyVals);
false ->
- Text = lists:flatten(io_lib:format("~p", [RelApp])),
- Status2 =
- reltool_utils:return_first_error(Status,
- "Illegal option: " ++ Text),
- decode(Rel, KeyVals, Status2)
+ reltool_utils:throw_error("Illegal option: ~p", [RelApp])
end;
-decode(Acc, [], Status) ->
- {Acc, Status};
-decode(Acc, KeyVal, Status) ->
- Text = lists:flatten(io_lib:format("~p", [KeyVal])),
- {Acc, reltool_utils:return_first_error(Status, "Illegal option: " ++ Text)}.
+decode(Acc, []) ->
+ Acc;
+decode(_Acc, KeyVal) ->
+ reltool_utils:throw_error("Illegal option: ~p", [KeyVal]).
is_type(Type) ->
case Type of
@@ -1529,79 +1573,50 @@ split_escript_name(File) when is_list(File) ->
Label = filename:basename(File, ".escript"),
{list_to_atom("*escript* " ++ Label), Label}.
+default_escript_app(File) ->
+ {Name, Label} = split_escript_name(File),
+ App = default_app(Name, File),
+ App#app{is_escript = true,
+ label = Label,
+ info = missing_app_info("")}.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-refresh(#state{sys = Sys} = S, Force, Status) ->
- {Sys2, Status2} = merge_config(Sys, Sys#sys{apps = []}, Force, Status),
- {S#state{sys = Sys2}, Status2}.
-
-merge_config(OldSys, NewSys, Force, Status) ->
- RootDir = filename:absname(NewSys#sys.root_dir),
- LibDirs = [filename:absname(D) || D <- NewSys#sys.lib_dirs],
- Escripts = [filename:absname(E) || E <- NewSys#sys.escripts],
- {SourceDirs, Status2} =
- libs_to_dirs(RootDir, LibDirs, Status),
- MergedApps = merge_app_dirs(SourceDirs, NewSys#sys.apps, OldSys#sys.apps),
- {AllApps, Status3} =
- escripts_to_apps(Escripts, MergedApps, OldSys#sys.apps, Status2),
- {RefreshedApps, Status4} =
- refresh_apps(OldSys#sys.apps, AllApps, [], Force, Status3),
- {PatchedApps, Status5} =
- patch_erts_version(RootDir, RefreshedApps, Status4),
- Escripts2 = [A#app.active_dir || A <- PatchedApps, A#app.is_escript],
- NewSys2 = NewSys#sys{root_dir = RootDir,
- lib_dirs = LibDirs,
- escripts = Escripts2,
- apps = PatchedApps},
- {NewSys2, Status5}.
+%% Apps is a list of #app records - sorted on #app.name - containing
+%% only the apps that have specific configuration (e.g. in the config
+%% file)
+refresh(#state{sys=Sys} = S) ->
+ RootDir = filename:absname(Sys#sys.root_dir),
+ LibDirs = [filename:absname(D) || D <- Sys#sys.lib_dirs],
+ Escripts = [filename:absname(E) || E <- Sys#sys.escripts],
-verify_config(RelApps, #sys{boot_rel = BootRel, rels = Rels, apps = Apps}, Status) ->
- case lists:keymember(BootRel, #rel.name, Rels) of
- true ->
- Status2 = lists:foldl(fun(RA, Acc) ->
- check_app(RA, Apps, Acc) end,
- Status,
- RelApps),
- lists:foldl(fun(#rel{name = RelName}, Acc)->
- check_rel(RelName, RelApps, Acc)
- end,
- Status2,
- Rels);
- false ->
- Text = lists:concat(["Release ", BootRel,
- " is mandatory (used as boot_rel)"]),
- reltool_utils:return_first_error(Status, Text)
- end.
+ %% Read all lib dirs and return sorted [{AppName,Dir}]
+ SourceDirs = libs_to_dirs(RootDir, LibDirs),
-check_app({RelName, AppName}, Apps, Status) ->
- case lists:keysearch(AppName, #app.name, Apps) of
- {value, App} when App#app.is_pre_included ->
- Status;
- {value, App} when App#app.is_included ->
- Status;
- _ ->
- Text = lists:concat(["Release ", RelName,
- " uses non included application ",
- AppName]),
- reltool_utils:return_first_error(Status, Text)
- end.
+ %% Create #app records for all apps in SourceDirs, and merge with
+ %% list of apps from config.
+ MergedApps = merge_app_dirs(SourceDirs, Sys#sys.apps),
-check_rel(RelName, RelApps, Status) ->
- EnsureApp =
- fun(AppName, Acc) ->
- case lists:member({RelName, AppName}, RelApps) of
- true ->
- Acc;
- false ->
- Text = lists:concat(["Mandatory application ",
- AppName,
- " is not included in release ",
- RelName]),
- reltool_utils:return_first_error(Acc, Text)
- end
- end,
- Mandatory = [kernel, stdlib],
- lists:foldl(EnsureApp, Status, Mandatory).
+ %% For each escript, find all related files and convert to #app
+ %% and #mod records
+ {AllApps, Status2} = escripts_to_apps(Escripts, MergedApps, {ok,[]}),
+
+ %% Make sure correct version of each application is used according
+ %% to the user configuration.
+ %% Then find all modules and their dependencies and set user
+ %% configuration per module if it exists.
+ {RefreshedApps, Status3} = refresh_apps(Sys#sys.apps, AllApps, [],
+ true, Status2),
+
+ %% Make sure erts exists in app list and has a version (or warn)
+ {PatchedApps, Status4} = patch_erts_version(RootDir, RefreshedApps, Status3),
+
+ %% Update #sys and return
+ Escripts2 = [A#app.active_dir || A <- PatchedApps, A#app.is_escript],
+ Sys2 = Sys#sys{root_dir = RootDir,
+ lib_dirs = LibDirs,
+ escripts = Escripts2},
+ {S#state{sys=Sys2}, PatchedApps, Status4}.
patch_erts_version(RootDir, Apps, Status) ->
AppName = erts,
@@ -1615,18 +1630,17 @@ patch_erts_version(RootDir, Apps, Status) ->
Apps2 = lists:keystore(AppName, #app.name, Apps, Erts2),
{Apps2, Status};
Vsn =:= "" ->
- {Apps, reltool_utils:add_warning(Status,
- "erts has no version")};
+ {Apps, reltool_utils:add_warning("erts has no version",[],
+ Status)};
true ->
{Apps, Status}
end;
false ->
- Text = "erts cannot be found in the root directory " ++ RootDir,
- Status2 = reltool_utils:return_first_error(Status, Text),
- {Apps, Status2}
+ reltool_utils:throw_error(
+ "erts cannot be found in the root directory ~p", [RootDir])
end.
-libs_to_dirs(RootDir, LibDirs, Status) ->
+libs_to_dirs(RootDir, LibDirs) ->
case file:list_dir(RootDir) of
{ok, RootFiles} ->
RootLibDir = filename:join([RootDir, "lib"]),
@@ -1648,21 +1662,16 @@ libs_to_dirs(RootDir, LibDirs, Status) ->
end,
ErtsFiles = [{erts, Fun(F)} || F <- RootFiles,
lists:prefix("erts", F)],
- app_dirs2(AllLibDirs, [ErtsFiles], Status);
+ app_dirs2(AllLibDirs, [ErtsFiles]);
[Duplicate | _] ->
- {[],
- reltool_utils:return_first_error(Status,
- "Duplicate library: " ++
- Duplicate)}
+ reltool_utils:throw_error("Duplicate library: ~p",[Duplicate])
end;
{error, Reason} ->
- Text = file:format_error(Reason),
- {[], reltool_utils:return_first_error(Status,
- "Missing root library " ++
- RootDir ++ ": " ++ Text)}
+ reltool_utils:throw_error("Missing root library ~p: ~s",
+ [RootDir,file:format_error(Reason)])
end.
-app_dirs2([Lib | Libs], Acc, Status) ->
+app_dirs2([Lib | Libs], Acc) ->
case file:list_dir(Lib) of
{ok, Files} ->
Filter =
@@ -1682,17 +1691,15 @@ app_dirs2([Lib | Libs], Acc, Status) ->
end
end,
Files2 = lists:zf(Filter, Files),
- app_dirs2(Libs, [Files2 | Acc], Status);
+ app_dirs2(Libs, [Files2 | Acc]);
{error, Reason} ->
- Text = file:format_error(Reason),
- {[], reltool_utils:return_first_error(Status,
- "Illegal library " ++
- Lib ++ ": " ++ Text)}
+ reltool_utils:throw_error("Illegal library ~p: ~s",
+ [Lib, file:format_error(Reason)])
end;
-app_dirs2([], Acc, Status) ->
- {lists:sort(lists:append(Acc)), Status}.
+app_dirs2([], Acc) ->
+ lists:sort(lists:append(Acc)).
-escripts_to_apps([Escript | Escripts], Apps, OldApps, Status) ->
+escripts_to_apps([Escript | Escripts], Apps, Status) ->
{EscriptAppName, _Label} = split_escript_name(Escript),
Ext = code:objfile_extension(),
Fun = fun(FullName, _GetInfo, GetBin, {FileAcc, StatusAcc}) ->
@@ -1755,156 +1762,114 @@ escripts_to_apps([Escript | Escripts], Apps, OldApps, Status) ->
end,
case reltool_utils:escript_foldl(Fun, {[], Status}, Escript) of
{ok, {Files, Status2}} ->
+ EscriptApp =
+ case lists:keyfind(EscriptAppName,#app.name,Apps) of
+ false -> default_escript_app(Escript);
+ EA -> EA
+ end,
{Apps2, Status3} =
- files_to_apps(Escript,
- lists:sort(Files),
- Apps,
- Apps,
- OldApps,
- Status2),
- escripts_to_apps(Escripts, Apps2, OldApps, Status3);
+ escript_files_to_apps(EscriptAppName,
+ lists:sort(Files),
+ [EscriptApp],
+ Apps,
+ Status2),
+ escripts_to_apps(Escripts, Apps2, Status3);
{error, Reason} ->
- Text = lists:flatten(io_lib:format("~p", [Reason])),
- {[], reltool_utils:return_first_error(Status,
- "Illegal escript " ++
- Escript ++ ": " ++ Text)}
+ reltool_utils:throw_error("Illegal escript ~p: ~p", [Escript,Reason])
end;
-escripts_to_apps([], Apps, _OldApps, Status) ->
+escripts_to_apps([], Apps, Status) ->
{Apps, Status}.
%% Assume that all files for an app are in consecutive order
%% Assume the app info is before the mods
-files_to_apps(Escript,
- [{AppName, Type, Dir, ModOrInfo} | Files] = AllFiles,
- Acc,
- Apps,
- OldApps,
- Status) ->
- case Type of
- mod ->
- case Acc of
- [] ->
- Info = missing_app_info(""),
- {NewApp, Status2} =
- merge_escript_app(AppName,
- Dir,
- Info,
- [ModOrInfo],
- Apps,
- OldApps,
- Status),
- files_to_apps(Escript,
- AllFiles,
- [NewApp | Acc],
- Apps,
- OldApps, Status2);
- [App | Acc2] when App#app.name =:= ModOrInfo#mod.app_name ->
- App2 = App#app{mods = [ModOrInfo | App#app.mods]},
- files_to_apps(Escript,
- Files,
- [App2 | Acc2],
- Apps,
- OldApps,
- Status);
- [App | Acc2] ->
- PrevApp = App#app{mods = lists:keysort(#mod.name,
- App#app.mods)},
- Info = missing_app_info(""),
- {NewApp, Status2} =
- merge_escript_app(AppName,
- Dir,
- Info,
- [ModOrInfo],
- Apps,
- OldApps,
- Status),
- files_to_apps(Escript,
- Files,
- [NewApp, PrevApp | Acc2],
- Apps,
- OldApps,
- Status2)
- end;
- app ->
- {App, Status2} =
- merge_escript_app(AppName, Dir, ModOrInfo, [], Apps, OldApps,
- Status),
- files_to_apps(Escript, Files, [App | Acc], Apps, OldApps, Status2)
- end;
-files_to_apps(_Escript, [], Acc, _Apps, _OldApps, Status) ->
- {lists:keysort(#app.name, Acc), Status}.
-
-merge_escript_app(AppName, Dir, Info, Mods, Apps, OldApps, Status) ->
- App1 = case lists:keyfind(AppName, #app.name, OldApps) of
- #app{} = App ->
- App;
- false ->
- default_app(AppName, Dir)
- end,
- App2 = App1#app{is_escript = true,
+escript_files_to_apps(EscriptAppName,
+ [{AppName, Type, Dir, ModOrInfo} | Files],
+ Acc,
+ Apps,
+ Status) ->
+ {NewAcc,Status3} =
+ case Type of
+ mod ->
+ case Acc of
+ [App | Acc2] when App#app.name =:= ModOrInfo#mod.app_name ->
+ Mods = lists:ukeymerge(#mod.name,
+ [ModOrInfo],
+ App#app.mods),
+ {[App#app{mods = Mods} | Acc2], Status};
+ Acc ->
+ {NewApp, Status2} = init_escript_app(AppName,
+ EscriptAppName,
+ Dir,
+ missing_app_info(""),
+ [ModOrInfo],
+ Apps,
+ Status),
+ {[NewApp | Acc], Status2}
+ end;
+ app ->
+ {App, Status2} = init_escript_app(AppName,
+ EscriptAppName,
+ Dir,
+ ModOrInfo,
+ [],
+ Apps,
+ Status),
+ {[App | Acc], Status2}
+ end,
+ escript_files_to_apps(EscriptAppName, Files, NewAcc, Apps, Status3);
+escript_files_to_apps(_EscriptAppName, [], Acc, Apps, Status) ->
+ {lists:ukeymerge(#app.name, lists:reverse(Acc), Apps), Status}.
+
+init_escript_app(AppName, EscriptAppName, Dir, Info, Mods, Apps, Status) ->
+ App1 = default_app(AppName, Dir),
+ IsEscript =
+ if AppName=:=EscriptAppName -> true;
+ true -> {inlined, EscriptAppName}
+ end,
+ InclCond = (lists:keyfind(EscriptAppName,#app.name,Apps))#app.incl_cond,
+ App2 = App1#app{is_escript = IsEscript,
label = filename:basename(Dir, ".escript"),
info = Info,
mods = Mods,
active_dir = Dir,
- sorted_dirs = [Dir]},
+ sorted_dirs = [Dir],
+ incl_cond = InclCond},% inlined apps inherit incl from escript
case lists:keymember(AppName, #app.name, Apps) of
true ->
- Error = lists:concat([AppName, ": Application name clash. ",
- "Escript ", Dir," contains application ",
- AppName, "."]),
- {App2, reltool_utils:return_first_error(Status, Error)};
+ reltool_utils:throw_error(
+ "~p: Application name clash. Escript ~p contains application ~p.",
+ [AppName,Dir,AppName]);
false ->
{App2, Status}
end.
-merge_app_dirs([{Name, Dir} | Rest], [App | Apps], OldApps)
- when App#app.name =:= Name ->
- %% Add new dir to app
- App2 = App#app{sorted_dirs = [Dir | App#app.sorted_dirs]},
- merge_app_dirs(Rest, [App2 | Apps], OldApps);
-merge_app_dirs([{Name, Dir} | Rest], Apps, OldApps) ->
- %% Initate app
- Apps2 = sort_app_dirs(Apps),
- Apps4 =
+merge_app_dirs([{Name, Dir} | Rest], Apps) ->
+ App =
case lists:keyfind(Name, #app.name, Apps) of
false ->
- case lists:keyfind(Name, #app.name, OldApps) of
- false ->
- App = default_app(Name, Dir),
- [App | Apps2];
- #app{active_dir = Dir} = OldApp ->
- [OldApp | Apps2];
- OldApp ->
- App =
- case filter_app(OldApp) of
- {true, NewApp} ->
- NewApp#app{active_dir = Dir,
- sorted_dirs = [Dir]};
- false ->
- default_app(Name, Dir)
- end,
- [App | Apps2]
- end;
+ default_app(Name, Dir);
OldApp ->
- Apps3 = lists:keydelete(Name, #app.name, Apps2),
- App = OldApp#app{sorted_dirs = [Dir | OldApp#app.sorted_dirs]},
- [App | Apps3]
+ SortedDirs = lists:umerge(fun reltool_utils:app_dir_test/2,
+ [Dir], OldApp#app.sorted_dirs),
+ OldApp#app{sorted_dirs = SortedDirs}
end,
- merge_app_dirs(Rest, Apps4, OldApps);
-merge_app_dirs([], Apps, _OldApps) ->
- Apps2 = sort_app_dirs(Apps),
- lists:reverse(Apps2).
-
-sort_app_dirs([#app{sorted_dirs = Dirs} = App | Acc]) ->
- SortedDirs = lists:sort(fun reltool_utils:app_dir_test/2, Dirs),
- case SortedDirs of
- [ActiveDir | _] -> ok;
- [] -> ActiveDir = undefined
- end,
- [App#app{active_dir = ActiveDir, sorted_dirs = SortedDirs} | Acc];
-sort_app_dirs([]) ->
+ Apps2 = lists:ukeymerge(#app.name, [App], Apps),
+ merge_app_dirs(Rest, Apps2);
+merge_app_dirs([], Apps) ->
+ set_active_dirs(Apps).
+
+%% First dir, i.e. the one with highest version, is set to active dir,
+%% unless a specific dir is given in config
+set_active_dirs([#app{use_selected_vsn = dir} = App | Apps]) ->
+ [App | set_active_dirs(Apps)];
+set_active_dirs([#app{sorted_dirs = [ActiveDir|_]} = App | Apps]) ->
+ [App#app{active_dir = ActiveDir} | set_active_dirs(Apps)];
+set_active_dirs([#app{sorted_dirs = []} = App | Apps]) ->
+ [App#app{active_dir = undefined} | set_active_dirs(Apps)];
+set_active_dirs([]) ->
[].
+
default_app(Name, Dir) ->
App = default_app(Name),
App#app{active_dir = Dir,
@@ -1913,91 +1878,55 @@ default_app(Name, Dir) ->
default_app(Name) ->
#app{name = Name,
is_escript = false,
- use_selected_vsn = undefined,
- active_dir = undefined,
sorted_dirs = [],
- vsn = undefined,
- label = undefined,
- info = undefined,
mods = [],
-
- mod_cond = undefined,
- incl_cond = undefined,
-
- status = missing,
- uses_mods = undefined,
- is_pre_included = undefined,
- is_included = undefined,
- rels = undefined}.
-
-%% Assume that the application are sorted
-refresh_apps([Old | OldApps], [New | NewApps], Acc, Force, Status)
- when New#app.name =:= Old#app.name ->
- {Info, ActiveDir, Status2} = ensure_app_info(New, Status),
- OptLabel =
- case Info#app_info.vsn =:= New#app.vsn of
- true -> New#app.label;
- false -> undefined % Cause refresh
- end,
- {Refreshed, Status3} =
- refresh_app(New#app{label = OptLabel,
- active_dir = ActiveDir,
- vsn = Info#app_info.vsn,
- info = Info},
- Force,
- Status2),
- refresh_apps(OldApps, NewApps, [Refreshed | Acc], Force, Status3);
-refresh_apps([Old | OldApps], [New | NewApps], Acc, Force, Status)
- when New#app.name < Old#app.name ->
- %% No old app version exists. Use new as is.
- %% BUGBUG: Issue warning if the active_dir is not defined
- {New2, Status2} = refresh_app(New, Force, Status),
- refresh_apps([Old | OldApps], NewApps, [New2 | Acc], Force, Status2);
-refresh_apps([Old | OldApps], [New | NewApps], Acc, Force, Status)
- when New#app.name > Old#app.name ->
- %% No new version. Remove the old.
- Status2 =
- case Old#app.name =:= ?MISSING_APP_NAME of
- true ->
- Status;
- false ->
- Warning =
- lists:concat([Old#app.name,
- ": The source dirs does not ",
- "contain the application anymore."]),
- reltool_utils:add_warning(Status, Warning)
- end,
- refresh_apps(OldApps, [New | NewApps], Acc, Force, Status2);
-refresh_apps([], [New | NewApps], Acc, Force, Status) ->
- %% No old app version exists. Use new as is.
- {New2, Status2} = refresh_app(New, Force, Status),
- refresh_apps([], NewApps, [New2 | Acc], Force, Status2);
-refresh_apps([Old | OldApps], [], Acc, Force, Status) ->
- %% No new version. Remove the old.
- Status2 =
- case Old#app.name =:= ?MISSING_APP_NAME of
- true ->
- Status;
- false ->
- Warning =
- lists:concat([Old#app.name,
- ": The source dirs does not "
- "contain the application anymore."]),
- reltool_utils:add_warning(Status, Warning)
- end,
- refresh_apps(OldApps, [], Acc, Force, Status2);
-refresh_apps([], [], Acc, _Force, Status) ->
+ status = missing}.
+
+
+
+refresh_apps(ConfigApps, [New | NewApps], Acc, Force, Status) ->
+ {New2, Status3} =
+ case lists:keymember(New#app.name,#app.name,ConfigApps) of
+ true ->
+ %% There is user defined config for this application, make
+ %% sure that the application exists and that correct
+ %% version is used. Set active directory.
+ {Info, ActiveDir, Status2} = ensure_app_info(New, Status),
+ OptLabel =
+ case Info#app_info.vsn =:= New#app.vsn of
+ true -> New#app.label;
+ false -> undefined % Cause refresh
+ end,
+ refresh_app(New#app{label = OptLabel,
+ active_dir = ActiveDir,
+ vsn = Info#app_info.vsn,
+ info = Info},
+ Force,
+ Status2);
+ false ->
+ %% There is no user defined config for this
+ %% application. This means that the app is found in the
+ %% lib dirs, and that the highest version shall be
+ %% used. I.e. the active_dir and vsn are already correct
+ %% from merge_app_dirs.
+ refresh_app(New, Force, Status)
+ end,
+ refresh_apps(ConfigApps, NewApps, [New2 | Acc], Force, Status3);
+refresh_apps(_ConfigApps, [], Acc, _Force, Status) ->
{lists:reverse(Acc), Status}.
-ensure_app_info(#app{is_escript = true, active_dir = Dir, info = Info},
- Status) ->
+
+ensure_app_info(#app{is_escript = IsEscript, active_dir = Dir, info = Info},
+ Status)
+ when IsEscript=/=false ->
+ %% Escript or application which is inlined in an escript
{Info, Dir, Status};
-ensure_app_info(#app{name = Name, sorted_dirs = []}, Status) ->
- Error = lists:concat([Name, ": Missing application directory."]),
- Status2 = reltool_utils:return_first_error(Status, Error),
- {missing_app_info(""), undefined, Status2};
+ensure_app_info(#app{name = Name, sorted_dirs = []}, _Status) ->
+ reltool_utils:throw_error("~p: : Missing application directory.",[Name]);
ensure_app_info(#app{name = Name,
vsn = Vsn,
+ use_selected_vsn = UseSelectedVsn,
+ active_dir = ActiveDir,
sorted_dirs = Dirs,
info = undefined},
Status) ->
@@ -2017,32 +1946,36 @@ ensure_app_info(#app{name = Name,
%% No redundant info
Status2;
[BadVsn | _] ->
- Error2 =
- lists:concat([Name, ": Application version clash. ",
- "Multiple directories contains version \"",
- BadVsn, "\"."]),
- reltool_utils:return_first_error(Status2, Error2)
+ reltool_utils:throw_error(
+ "~p: Application version clash. "
+ "Multiple directories contains version ~p.",
+ [Name,BadVsn])
end,
FirstInfo = hd(AllInfo),
FirstDir = hd(Dirs),
if
- Vsn =:= undefined ->
- {FirstInfo, FirstDir, Status3};
- Vsn =:= FirstInfo#app_info.vsn ->
- {FirstInfo, FirstDir, Status3};
- true ->
- case find_vsn(Vsn, AllInfo, Dirs) of
- {Info, VsnDir} ->
- {Info, VsnDir, Status3};
- false ->
- Error3 =
- lists:concat([Name,
- ": No application directory contains ",
- "selected version \"",
- Vsn, "\"."]),
- Status4 = reltool_utils:return_first_error(Status3, Error3),
- {FirstInfo, FirstDir, Status4}
- end
+ UseSelectedVsn =:= dir ->
+ if ActiveDir =:= FirstDir ->
+ {FirstInfo, FirstDir, Status3};
+ true ->
+ Info = find_dir(ActiveDir, AllInfo, Dirs),
+ {Info, ActiveDir, Status3}
+ end;
+ UseSelectedVsn =:= vsn ->
+ if Vsn =:= FirstInfo#app_info.vsn ->
+ {FirstInfo, FirstDir, Status3};
+ true ->
+ case find_vsn(Vsn, AllInfo, Dirs) of
+ {Info, VsnDir} ->
+ {Info, VsnDir, Status3};
+ false ->
+ reltool_utils:throw_error(
+ "~p: No application directory contains "
+ "selected version ~p", [Name,Vsn])
+ end
+ end;
+ true ->
+ {FirstInfo, FirstDir, Status3}
end;
ensure_app_info(#app{active_dir = Dir, info = Info}, Status) ->
{Info, Dir, Status}.
@@ -2054,6 +1987,11 @@ find_vsn(Vsn, [_ | MoreInfo], [_ | MoreDirs]) ->
find_vsn(_, [], []) ->
false.
+find_dir(Dir, [Info | _], [Dir | _]) ->
+ Info;
+find_dir(Dir, [_ | MoreInfo], [_ | MoreDirs]) ->
+ find_dir(Dir, MoreInfo, MoreDirs).
+
get_base(Name, Dir) ->
case Name of
erts ->
@@ -2067,6 +2005,54 @@ get_base(Name, Dir) ->
filename:basename(Dir)
end.
+sys_all_apps(#state{app_tab=AppTab, sys=Sys}) ->
+ Sys#sys{apps = ets:match_object(AppTab,'_')}.
+
+config_and_refresh(OldS, Fun) ->
+ try
+ S = Fun(),
+ {S2, Apps, Status2} = refresh(S),
+ %% Analyse will write to app_tab and mod_tab, so we first
+ %% backup these tables and clear them
+ Backup = backup(OldS),
+ try
+ Status3 = analyse(S2, Apps, Status2),
+ S3 = save_old(OldS, S2, Backup, Status3),
+ {S3, Status3}
+ catch throw:{error,_} = Error1 ->
+ restore(Backup,OldS),
+ throw(Error1)
+ end
+ catch throw:{error,_} = Error2 ->
+ {OldS, Error2}
+ end.
+
+
+backup(S) ->
+ Apps = ets:tab2list(S#state.app_tab),
+ Mods = ets:tab2list(S#state.mod_tab),
+ ets:delete_all_objects(S#state.app_tab),
+ ets:delete_all_objects(S#state.mod_tab),
+ ets:delete_all_objects(S#state.mod_used_by_tab), %tmp tab, no backup needed
+ {Apps,Mods}.
+
+restore({Apps,Mods}, S) ->
+ insert_all(S#state.app_tab,Apps),
+ insert_all(S#state.mod_tab,Mods).
+
+save_old(#state{status=OldStatus,sys=OldSys},NewS,{OldApps,OldMods},NewStatus) ->
+ ets:delete_all_objects(NewS#state.old_app_tab),
+ ets:delete_all_objects(NewS#state.old_mod_tab),
+ insert_all(NewS#state.old_app_tab,OldApps),
+ insert_all(NewS#state.old_mod_tab,OldMods),
+ NewS#state{old_sys=OldSys,
+ old_status=OldStatus,
+ status=NewStatus}.
+
+insert_all(Tab,Items) ->
+ lists:foreach(fun(Item) -> ets:insert(Tab,Item) end, Items).
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sys callbacks
diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl
index 8b0f64eb45..0c0b295db1 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,7 +56,9 @@
derived,
fgraph_wins,
app_box,
- mod_box
+ mod_box,
+ warning_list,
+ warning_wins
}).
-define(WIN_WIDTH, 800).
@@ -88,6 +90,10 @@
-define(blacklist, "Excluded").
-define(derived, "Derived").
+-define(WARNING_COL, 0).
+-define(DEFAULT_WARNING_TIP, "Warnings are listed in this window").
+-define(WARNING_POPUP_SIZE, {400,150}).
+
-define(safe_config,{sys,[{incl_cond,exclude},
{app,kernel,[{incl_cond,include}]},
{app,stdlib,[{incl_cond,include}]},
@@ -141,48 +147,44 @@ do_init([{safe_config, Safe}, {parent, Parent} | Options]) ->
wx:debug(C#common.wx_debug),
%% wx_misc:beginBusyCursor(),
- case reltool_server:get_status(ServerPid) of
- {ok, Warnings} ->
- exit_dialog(Warnings),
- {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(S2#state.frame,
- Title),
- %% wxFrame:setMinSize(Frame,
- %% {?WIN_WIDTH, ?WIN_HEIGHT}),
- wxStatusBar:setStatusText(
- S2#state.status_bar,
- "Done."),
- 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} ->
- restart_server_safe_config(Safe,Parent,Reason)
- end;
+ {ok, Warnings} = reltool_server:get_status(ServerPid),
+ exit_dialog(Warnings),
+ 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 = [],
+ warning_wins = []},
+ S2 = create_window(S),
+ S5 = wx:batch(fun() ->
+ Title = atom_to_list(?APPLICATION),
+ wxFrame:setTitle(S2#state.frame,
+ Title),
+ %% wxFrame:setMinSize(Frame,
+ %% {?WIN_WIDTH, ?WIN_HEIGHT}),
+ wxStatusBar:setStatusText(
+ S2#state.status_bar,
+ "Done."),
+ 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.
-restart_server_safe_config(true,_Parent,Reason) ->
+restart_server_safe_config(true,Parent,Reason) ->
io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
- exit(Reason);
+ proc_lib:init_ack(Parent, {error,Reason});
restart_server_safe_config(false,Parent,Reason) ->
+ wx:new(),
Strings =
[{?wxBLACK,"Could not start reltool server:\n\n"},
{?wxRED,Reason++"\n\n"},
@@ -197,7 +199,7 @@ restart_server_safe_config(false,Parent,Reason) ->
do_init([{safe_config,true},{parent,Parent},?safe_config]);
?wxID_CANCEL ->
io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
- exit(Reason)
+ proc_lib:init_ack(Parent,{error,Reason})
end.
exit_dialog([]) ->
@@ -240,10 +242,18 @@ loop(S) ->
lists:keydelete(ObjRef, #fgraph_win.frame, FWs),
?MODULE:loop(S#state{fgraph_wins = FWs2});
false ->
- error_logger:format("~p~p got unexpected "
- "message:\n\t~p\n",
- [?MODULE, self(), Msg]),
- ?MODULE:loop(S)
+ WWs = S#state.warning_wins,
+ case lists:member(ObjRef, WWs) of
+ true ->
+ wxFrame:destroy(ObjRef),
+ WWs2 = lists:delete(ObjRef, WWs),
+ ?MODULE:loop(S#state{warning_wins = WWs2});
+ false ->
+ error_logger:format("~p~p got unexpected "
+ "message:\n\t~p\n",
+ [?MODULE, self(), Msg]),
+ ?MODULE:loop(S)
+ end
end
end;
#wx{id = ?CLOSE_ITEM,
@@ -297,8 +307,8 @@ handle_child_exit({'EXIT', Pid, _Reason} = Exit, FWs, AWs) ->
msg_warning(Exit, application_window),
{FWs, lists:keydelete(Pid, #app_win.pid, AWs)};
false ->
- msg_warning(Exit, unknown),
- {FWs, AWs}
+ msg_warning(Exit, unknown),
+ {FWs, AWs}
end
end.
@@ -340,8 +350,12 @@ create_window(S) ->
fun create_main_release_page/1,
fun create_config_page/1
]),
+
+ S4 = create_warning_list(S3),
+
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, Book, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(Sizer, S4#state.warning_list, [{flag, ?wxEXPAND}]),
wxPanel:setSizer(Panel, Sizer),
wxSizer:fit(Sizer, Frame),
@@ -349,7 +363,7 @@ create_window(S) ->
wxFrame:connect(Frame, close_window),
wxFrame:show(Frame),
- S3.
+ S4.
create_menubar(Frame) ->
MenuBar = wxMenuBar:new(),
@@ -444,6 +458,7 @@ create_app_list_ctrl(Panel, OuterSz, Title, Tick, Cross) ->
ListItem = wxListItem:new(),
wxListItem:setAlign(ListItem, ?wxLIST_FORMAT_LEFT),
wxListItem:setText(ListItem, Title),
+ wxListItem:setWidth(ListItem, reltool_utils:get_column_width(ListCtrl)),
wxListCtrl:insertColumn(ListCtrl, ?APPS_APP_COL, ListItem),
wxListItem:destroy(ListItem),
@@ -642,6 +657,49 @@ redraw_config_page(#state{sys = Sys, app_box = AppBox, mod_box = ModBox} = S) ->
wxRadioBox:setSelection(ModBox, ModChoice),
S.
+create_warning_list(#state{panel = Panel} = S) ->
+ ListCtrl = wxListCtrl:new(Panel,
+ [{style,
+ ?wxLC_REPORT bor
+ ?wxLC_HRULES bor
+ ?wxVSCROLL},
+ {size, {?WIN_WIDTH,80}}]),
+ reltool_utils:assign_image_list(ListCtrl),
+ wxListCtrl:insertColumn(ListCtrl, ?WARNING_COL, "Warnings",
+ [{format,?wxLIST_FORMAT_LEFT},
+ {width,reltool_utils:get_column_width(ListCtrl)}]),
+ wxListCtrl:setToolTip(ListCtrl, ?DEFAULT_WARNING_TIP),
+ wxEvtHandler:connect(ListCtrl, size,
+ [{skip, true}, {userData, warnings}]),
+ wxEvtHandler:connect(ListCtrl, command_list_item_activated,
+ [{userData, warnings}]),
+ wxEvtHandler:connect(ListCtrl, motion, [{userData, warnings}]),
+ wxEvtHandler:connect(ListCtrl, enter_window),
+ S#state{warning_list=ListCtrl}.
+
+redraw_warnings(S) ->
+ {ok,Warnings} = reltool_server:get_status(S#state.server_pid),
+ redraw_warnings(S#state.warning_list,Warnings),
+ length(Warnings).
+
+redraw_warnings(ListCtrl, []) ->
+ wxListCtrl:deleteAllItems(ListCtrl),
+ ok;
+redraw_warnings(ListCtrl, Warnings) ->
+ wxListCtrl:deleteAllItems(ListCtrl),
+ Show = fun(Warning, Row) ->
+ wxListCtrl:insertItem(ListCtrl, Row, ""),
+ wxListCtrl:setItem(ListCtrl,
+ Row,
+ ?WARNING_COL,
+ Warning,
+ [{imageId, ?WARN_IMAGE}]),
+ Row + 1
+ end,
+ wx:foldl(Show, 0, Warnings),
+ ok.
+
+
create_main_release_page(#state{book = Book} = S) ->
Panel = wxPanel:new(Book, []),
RelBook = wxNotebook:new(Panel, ?wxID_ANY, []),
@@ -783,6 +841,9 @@ escript_popup(S, File, Tree, Item) ->
handle_event(S, #wx{id = Id, obj= ObjRef, userData = UserData, event = Event} = _Wx) ->
%% io:format("wx: ~p\n", [Wx]),
case Event of
+ _ when UserData =:= warnings;
+ is_tuple(UserData), element(1,UserData)=:=warning ->
+ handle_warning_event(S, ObjRef, UserData, Event);
#wxSize{type = size, size = {W, _H}} when UserData =:= app_list_ctrl ->
wxListCtrl:setColumnWidth(ObjRef, ?APPS_APP_COL, W),
S;
@@ -848,7 +909,9 @@ handle_event(S, #wx{id = Id, obj= ObjRef, userData = UserData, event = Event} =
when S#state.popup_menu =/= undefined ->
handle_popup_event(S, Type, Id, ObjRef, UserData, Str);
#wxMouse{type = enter_window} ->
- wxWindow:setFocus(ObjRef),
+ %% The following is commented out because it raises the
+ %% main system window on top of popup windows.
+ %% wxWindow:setFocus(ObjRef),
S;
_ ->
case wxNotebook:getPageText(S#state.book,
@@ -860,6 +923,110 @@ handle_event(S, #wx{id = Id, obj= ObjRef, userData = UserData, event = Event} =
end
end.
+handle_warning_event(S, ObjRef, _, #wxSize{type = size}) ->
+ ColumnWidth = reltool_utils:get_column_width(ObjRef),
+ wxListCtrl:setColumnWidth(ObjRef, ?WARNING_COL, ColumnWidth),
+ S;
+handle_warning_event(S, ObjRef, _, #wxMouse{type = motion, x=X, y=Y}) ->
+ Pos = reltool_utils:wait_for_stop_motion(ObjRef, {X,Y}),
+ warning_list_set_tool_tip(os:type(),ObjRef,Pos),
+ S;
+handle_warning_event(S, ObjRef, _, #wxList{type = command_list_item_activated,
+ itemIndex = Pos}) ->
+ Text = wxListCtrl:getItemText(ObjRef, Pos),
+ S#state{warning_wins = [display_warning(S,Text) | S#state.warning_wins]};
+handle_warning_event(S, _ObjRef, {warning,Frame},
+ #wxCommand{type = command_button_clicked}) ->
+ wxFrame:destroy(Frame),
+ S#state{warning_wins = lists:delete(Frame,S#state.warning_wins)}.
+
+warning_list_set_tool_tip({win32,_},ListCtrl,{_X,Y}) ->
+ case win_find_item(ListCtrl,Y,0) of
+ -1 ->
+ wxListCtrl:setToolTip(ListCtrl,?DEFAULT_WARNING_TIP);
+ _Index ->
+ %% The following is commented out because there seems to
+ %% be an utomatic tooltip under Windows that shows the
+ %% expanded list item in case it is truncated because it
+ %% is too long for column width.
+ %% Tip =
+ %% case wxListCtrl:getItemText(ListCtrl,Index) of
+ %% "" ->
+ %% ?DEFAULT_WARNING_TIP;
+ %% Text ->
+ %% "WARNING:\n" ++ Text
+ %% end,
+ %% wxListCtrl:setToolTip(ListCtrl,Tip),
+ ok
+ end;
+warning_list_set_tool_tip(_,ListCtrl,Pos) ->
+ case wxListCtrl:findItem(ListCtrl,-1,Pos,0) of
+ Index when Index >= 0 ->
+ Tip =
+ case wxListCtrl:getItemText(ListCtrl,Index) of
+ "" ->
+ ?DEFAULT_WARNING_TIP;
+ Text ->
+ "WARNING:\n" ++ Text
+ end,
+ wxListCtrl:setToolTip(ListCtrl, Tip);
+ _ ->
+ ok
+ end.
+
+win_find_item(ListCtrl,YPos,Index) ->
+ case wxListCtrl:getItemRect(ListCtrl,Index) of
+ {true,{_,Y,_,H}} when YPos>=Y, YPos=<Y+H ->
+ Index;
+ {true,_} ->
+ win_find_item(ListCtrl,YPos,Index+1);
+ {false,_} ->
+ -1
+ end.
+
+display_warning(S,Warning) ->
+ Pos = warning_popup_position(S,?WARNING_POPUP_SIZE),
+ Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Warning",[{pos,Pos}]),
+ Panel = wxPanel:new(Frame, []),
+ TextStyle = ?wxTE_READONLY bor ?wxTE_WORDWRAP bor ?wxTE_MULTILINE,
+ Text = wxTextCtrl:new(Panel, ?wxID_ANY, [{value, Warning},
+ {style, TextStyle},
+ {size, ?WARNING_POPUP_SIZE}]),
+ Attr = wxTextAttr:new(),
+ wxTextAttr:setLeftIndent(Attr,10),
+ wxTextAttr:setRightIndent(Attr,10),
+ true = wxTextCtrl:setDefaultStyle(Text, Attr),
+ wxTextAttr:destroy(Attr),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, Text, [{border, 2},
+ {flag, ?wxEXPAND bor ?wxALL},
+ {proportion, 1}]),
+
+ Close = wxButton:new(Panel, ?wxID_ANY, [{label, "Close"}]),
+ wxButton:setToolTip(Close, "Close window."),
+ wxButton:connect(Close, command_button_clicked, [{userData,{warning,Frame}}]),
+ wxSizer:add(Sizer, Close, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+
+ wxPanel:setSizer(Panel, Sizer),
+ wxSizer:fit(Sizer, Frame),
+ wxSizer:setSizeHints(Sizer, Frame),
+ wxFrame:connect(Frame, close_window),
+
+ wxFrame:show(Frame),
+ Frame.
+
+warning_popup_position(#state{frame=MF,warning_list=WL},{WFW,WFH}) ->
+ {MFX,MFY} = wxWindow:getPosition(MF),
+ {MFW,MFH} = wxWindow:getSize(MF),
+ {_WLW,WLH} = wxWindow:getSize(WL),
+
+ %% Position the popup in the middle of the main frame, above the
+ %% warning list, and with a small offset from the exact middle...
+ Offset = 50,
+ X = MFX + (MFW-WFW) div 2 - Offset,
+ Y = MFY + (MFH-WLH-WFH) div 2 - Offset,
+ {X,Y}.
+
handle_popup_event(S, _Type, 0, _ObjRef, _UserData, _Str) ->
S#state{popup_menu = undefined};
handle_popup_event(#state{popup_menu = #root_popup{dir = OldDir,
@@ -1079,16 +1246,16 @@ handle_app_event(S, Event, ObjRef, UserData) ->
[?MODULE, self(), ObjRef, UserData, Event]),
S.
-handle_app_button(#state{server_pid = ServerPid, app_wins = AppWins} = S,
+handle_app_button(#state{server_pid = ServerPid,
+ status_bar = Bar,
+ app_wins = AppWins} = S,
Items,
Action) ->
+ wxStatusBar:setStatusText(Bar, "Processing libraries..."),
NewApps = [move_app(S, Item, Action) || Item <- Items],
case reltool_server:set_apps(ServerPid, NewApps) of
- {ok, []} ->
+ {ok, _Warnings} ->
ok;
- {ok, Warnings} ->
- Msg = lists:flatten([[W, $\n] || W <- Warnings]),
- display_message(Msg, ?wxICON_WARNING);
{error, Reason} ->
display_message(Reason, ?wxICON_ERROR)
end,
@@ -1125,23 +1292,22 @@ move_app(S, {_ItemNo, AppBase}, Action) ->
end,
OldApp#app{incl_cond = AppCond}.
-do_set_app(#state{server_pid = ServerPid, app_wins = AppWins} = S, NewApp) ->
+do_set_app(#state{server_pid = ServerPid,
+ status_bar = Bar,
+ app_wins = AppWins} = S, NewApp) ->
+ wxStatusBar:setStatusText(Bar, "Processing libraries..."),
Result = reltool_server:set_app(ServerPid, NewApp),
- [ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- AppWins],
- S2 = redraw_apps(S),
ReturnApp =
case Result of
- {ok, AnalysedApp, []} ->
- AnalysedApp;
- {ok, AnalysedApp, Warnings} ->
- Msg = lists:flatten([[W, $\n] || W <- Warnings]),
- display_message(Msg, ?wxICON_WARNING),
+ {ok, AnalysedApp, _Warnings} ->
AnalysedApp;
{error, Reason} ->
display_message(Reason, ?wxICON_ERROR),
{ok,OldApp} = reltool_server:get_app(ServerPid, NewApp#app.name),
OldApp
end,
+ [ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- AppWins],
+ S2 = redraw_apps(S),
{ok, ReturnApp, S2}.
redraw_apps(#state{server_pid = ServerPid,
@@ -1164,8 +1330,14 @@ redraw_apps(#state{server_pid = ServerPid,
WhiteN = redraw_apps(WhiteApps, WhiteCtrl, ?TICK_IMAGE, ?ERR_IMAGE),
redraw_apps(BlackApps2, BlackCtrl, ?CROSS_IMAGE, ?WARN_IMAGE),
DerivedN = redraw_apps(DerivedApps, DerivedCtrl, ?TICK_IMAGE, ?ERR_IMAGE),
+
+ WarningsN = redraw_warnings(S),
+ WarningText = if WarningsN==1 -> "warning";
+ true -> "warnings"
+ end,
Status = lists:concat([WhiteN, " whitelisted modules and ",
- DerivedN, " derived modules."]),
+ DerivedN, " derived modules, ",
+ WarningsN, " ", WarningText, "."]),
wxStatusBar:setStatusText(S#state.status_bar, Status),
S.
@@ -1323,26 +1495,28 @@ save_config(#state{config_file = OldFile} = S, InclDefaults, InclDerivates) ->
S
end.
-gen_rel_files(#state{target_dir = OldDir} = S) ->
+gen_rel_files(#state{status_bar = Bar, target_dir = OldDir} = S) ->
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
case select_dir(S#state.frame,
"Select a directory to generate rel, script and boot files to",
OldDir,
Style) of
{ok, NewDir} ->
+ wxStatusBar:setStatusText(Bar, "Processing libraries..."),
Status = reltool_server:gen_rel_files(S#state.server_pid, NewDir),
check_and_refresh(S, Status);
cancel ->
S
end.
-gen_target(#state{target_dir = OldDir} = S) ->
+gen_target(#state{status_bar = Bar, target_dir = OldDir} = S) ->
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
case select_dir(S#state.frame,
"Select a directory to generate a target system to",
OldDir,
Style) of
{ok, NewDir} ->
+ wxStatusBar:setStatusText(Bar, "Processing libraries..."),
Status = reltool_server:gen_target(S#state.server_pid, NewDir),
check_and_refresh(S#state{target_dir = NewDir}, Status);
cancel ->
@@ -1380,8 +1554,8 @@ check_and_refresh(S, Status) ->
case Status of
ok ->
true;
- {ok, Warnings} ->
- undo_dialog(S, Warnings);
+ {ok, _Warnings} ->
+ true;
{error, Reason} when is_list(Reason) ->
display_message(Reason, ?wxICON_ERROR),
false;
@@ -1435,19 +1609,6 @@ question_dialog(Question, Details) ->
wxDialog:destroy(Dialog),
Answer.
-undo_dialog(_S, []) ->
- true;
-undo_dialog(S, Warnings) ->
- Question = "Do you want to perform the update despite these warnings?",
- Details = lists:flatten([[W, $\n] || W <- Warnings]),
- case question_dialog(Question, Details) of
- ?wxID_OK ->
- true;
- ?wxID_CANCEL ->
- reltool_server:undo_config(S#state.server_pid),
- false
- end.
-
display_message(Message, Icon) ->
Dialog = wxMessageDialog:new(wx:null(),
Message,
@@ -1491,8 +1652,6 @@ add_text(_,_,[]) ->
ok.
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sys callbacks
diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl
index 0fcf89a360..c39ed0ecd5 100644
--- a/lib/reltool/src/reltool_target.erl
+++ b/lib/reltool/src/reltool_target.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -101,7 +101,7 @@ do_gen_config(#sys{root_dir = RootDir,
|| A <- Apps,
A#app.name =/= ?MISSING_APP_NAME,
A#app.name =/= erts,
- not A#app.is_escript],
+ A#app.is_escript =/= true],
EscriptItems = [{escript,
A#app.active_dir,
emit(incl_cond, A#app.incl_cond, undefined, InclDefs)}
@@ -155,6 +155,7 @@ do_gen_config(#app{name = Name,
archive_opts = ArchiveOpts,
use_selected_vsn = UseSelected,
vsn = Vsn,
+ active_dir = ActiveDir,
mods = Mods,
is_included = IsIncl},
InclDefs) ->
@@ -170,9 +171,10 @@ do_gen_config(#app{name = Name,
emit(excl_archive_filters, ExclArchiveDirs, undefined, InclDefs),
emit(archive_opts, ArchiveOpts, undefined, InclDefs),
if
- IsIncl, InclDefs -> [{vsn, Vsn}];
- UseSelected -> [{vsn, Vsn}];
- true -> []
+ IsIncl, InclDefs -> [{vsn, Vsn}, {lib_dir, ActiveDir}];
+ UseSelected =:= vsn -> [{vsn, Vsn}];
+ UseSelected =:= dir -> [{lib_dir, ActiveDir}];
+ true -> []
end,
[do_gen_config(M, InclDefs) || M <- Mods]
],
@@ -208,10 +210,10 @@ do_gen_config(#rel_app{name = Name,
incl_apps = InclApps},
_InclDefs) ->
case {Type, InclApps} of
- {undefined, []} -> Name;
- {undefined, _} -> {Name, InclApps};
- {_, []} -> {Name, Type};
- {_, _} -> {Name, Type, InclApps}
+ {undefined, undefined} -> Name;
+ {undefined, _} -> {Name, InclApps};
+ {_, undefined} -> {Name, Type};
+ {_, _} -> {Name, Type, InclApps}
end;
do_gen_config({Tag, Val}, InclDefs) ->
emit(Tag, Val, undefined, InclDefs);
@@ -247,10 +249,15 @@ gen_app(#app{name = Name,
env = Env,
mod = StartMod,
start_phases = StartPhases}}) ->
- StartMod2 =
- case StartMod =:= undefined of
- true -> [];
- false -> [{mod, StartMod}]
+ StartPhases2 =
+ case StartPhases of
+ undefined -> [];
+ _ -> [{start_phases, StartPhases}]
+ end,
+ Tail =
+ case StartMod of
+ undefined -> StartPhases2;
+ _ -> [{mod, StartMod} | StartPhases2]
end,
{application, Name,
[{description, Desc},
@@ -261,10 +268,9 @@ gen_app(#app{name = Name,
{applications, ReqApps},
{included_applications, InclApps},
{env, Env},
- {start_phases, StartPhases},
{maxT, MaxT},
{maxP, MaxP} |
- StartMod2]}.
+ Tail]}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate the contents of a rel file
@@ -279,7 +285,7 @@ gen_rel(Rel, Sys) ->
{error, Text}
end.
-do_gen_rel(#rel{name = RelName, vsn = RelVsn},
+do_gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps},
#sys{apps = Apps},
MergedApps) ->
ErtsName = erts,
@@ -288,7 +294,7 @@ do_gen_rel(#rel{name = RelName, vsn = RelVsn},
{release,
{RelName, RelVsn},
{ErtsName, Erts#app.vsn},
- [strip_rel_info(App) || App <- MergedApps]};
+ [strip_rel_info(App, RelApps) || App <- MergedApps]};
false ->
reltool_utils:throw_error("Mandatory application ~p is "
"not included",
@@ -298,13 +304,17 @@ do_gen_rel(#rel{name = RelName, vsn = RelVsn},
strip_rel_info(#app{name = Name,
vsn = Vsn,
app_type = Type,
- info = #app_info{incl_apps = InclApps}})
- when Type =/= undefined ->
- case {Type, InclApps} of
- {permanent, []} -> {Name, Vsn};
- {permanent, _} -> {Name, Vsn, InclApps};
- {_, []} -> {Name, Vsn, Type};
- {_, _} -> {Name, Vsn, Type, InclApps}
+ info = #app_info{incl_apps = AppInclApps}},
+ RelApps) when Type =/= undefined ->
+ RelInclApps = case lists:keyfind(Name,#rel_app.name,RelApps) of
+ #rel_app{incl_apps = RIA} when RIA =/= undefined -> RIA;
+ _ -> undefined
+ end,
+ case {Type, RelInclApps} of
+ {permanent, undefined} -> {Name, Vsn};
+ {permanent, _} -> {Name, Vsn, AppInclApps};
+ {_, undefined} -> {Name, Vsn, Type};
+ {_, _} -> {Name, Vsn, Type, AppInclApps}
end.
merge_apps(#rel{name = RelName,
@@ -323,7 +333,7 @@ merge_apps(#rel{name = RelName,
A#app.name =/= ?MISSING_APP_NAME,
not lists:keymember(A#app.name, #app.name, MergedApps2)],
MergedApps3 = do_merge_apps(RelName, Embedded, Apps, EmbAppType, MergedApps2),
- sort_apps(MergedApps3).
+ sort_apps(lists:reverse(MergedApps3)).
do_merge_apps(RelName, [#rel_app{name = Name} = RA | RelApps], Apps, RelAppType, Acc) ->
case is_already_merged(Name, RelApps, Acc) of
@@ -341,25 +351,18 @@ do_merge_apps(RelName, [Name | RelApps], Apps, RelAppType, Acc) ->
true ->
do_merge_apps(RelName, RelApps, Apps, RelAppType, Acc);
false ->
- RelApp = init_rel_app(Name, Apps),
+ RelApp = #rel_app{name = Name},
do_merge_apps(RelName, [RelApp | RelApps], Apps, RelAppType, Acc)
end;
do_merge_apps(_RelName, [], _Apps, _RelAppType, Acc) ->
- lists:reverse(Acc).
-
-init_rel_app(Name, Apps) ->
- {value, App} = lists:keysearch(Name, #app.name, Apps),
- Info = App#app.info,
- #rel_app{name = Name,
- app_type = undefined,
- incl_apps = Info#app_info.incl_apps}.
+ Acc.
merge_app(RelName,
- #rel_app{name = Name,
- app_type = Type,
- incl_apps = InclApps},
- RelAppType,
- App) ->
+ #rel_app{name = Name,
+ app_type = Type,
+ incl_apps = InclApps0},
+ RelAppType,
+ App) ->
Type2 =
case {Type, App#app.app_type} of
{undefined, undefined} -> RelAppType;
@@ -367,6 +370,11 @@ merge_app(RelName,
{_, _} -> Type
end,
Info = App#app.info,
+ InclApps =
+ case InclApps0 of
+ undefined -> Info#app_info.incl_apps;
+ _ -> InclApps0
+ end,
case InclApps -- Info#app_info.incl_apps of
[] ->
App#app{app_type = Type2, info = Info#app_info{incl_apps = InclApps}};
@@ -421,7 +429,10 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn},
Mandatory = mandatory_modules(),
Early = Mandatory ++ Preloaded,
{value, KernelApp} = lists:keysearch(kernel, #app.name, MergedApps),
- InclApps = [I || #app{info = #app_info{incl_apps = I}} <- MergedApps],
+ InclApps = lists:flatmap(fun(#app{info = #app_info{incl_apps = I}}) ->
+ I
+ end,
+ MergedApps),
%% Create the script
DeepList =
@@ -471,7 +482,7 @@ load_app_mods(#app{mods = Mods} = App, Mand, PathFlag, Variables) ->
Path = cr_path(App, PathFlag, Variables),
PartNames =
lists:sort([{packages:split(M),M} ||
- #mod{name = M} <- Mods,
+ #mod{name = M, is_included=true} <- Mods,
not lists:member(M, Mand)]),
SplitMods =
lists:foldl(
@@ -513,7 +524,12 @@ sort_apps([#app{name = Name, info = Info} = App | Apps],
Circular,
Visited) ->
{Uses, Apps1, NotFnd1} =
- find_all(Name, Info#app_info.applications, Apps, Visited, [], []),
+ find_all(Name,
+ lists:reverse(Info#app_info.applications),
+ Apps,
+ Visited,
+ [],
+ []),
{Incs, Apps2, NotFnd2} =
find_all(Name,
lists:reverse(Info#app_info.incl_apps),
@@ -671,6 +687,8 @@ strip_name_ebin(Dir, Name, Vsn) ->
case lists:reverse(Dir) of
["ebin", Name | D] -> {ok, lists:reverse(D)};
["ebin", FullName | D] -> {ok, lists:reverse(D)};
+ [Name | D] -> {ok, lists:reverse(D)};
+ [FullName | D] -> {ok, lists:reverse(D)};
_ -> false
end.
@@ -717,8 +735,20 @@ do_spec_rel_files(#rel{name = RelName} = Rel, Sys) ->
BootFile = RelName ++ ".boot",
MergedApps = merge_apps(Rel, Sys),
GenRel = do_gen_rel(Rel, Sys, MergedApps),
+ Variables =
+ case Sys#sys.excl_lib of
+ otp_root ->
+ %% All applications that are fetched from somewhere
+ %% other than $OTP_ROOT/lib will get $RELTOOL_EXT_LIB
+ %% as path prefix in the .script file.
+ [{"RELTOOL_EXT_LIB",LibDir} || LibDir <- Sys#sys.lib_dirs] ++
+ [{"RELTOOL_EXT_LIB",filename:dirname(AppLibDir)} ||
+ #app{active_dir=AppLibDir,use_selected_vsn=dir}
+ <- MergedApps];
+ _ ->
+ []
+ end,
PathFlag = true,
- Variables = [],
{ok, Script} = do_gen_script(Rel, Sys, MergedApps, PathFlag, Variables),
{ok, BootBin} = gen_boot(Script),
Date = date(),
@@ -755,29 +785,34 @@ gen_spec(Sys) ->
end.
do_gen_spec(#sys{root_dir = RootDir,
+ excl_lib = ExclLib,
incl_sys_filters = InclRegexps,
excl_sys_filters = ExclRegexps,
relocatable = Relocatable,
apps = Apps} = Sys) ->
- {create_dir, _, SysFiles} = spec_dir(RootDir),
- {ExclRegexps2, SysFiles2} =
- strip_sys_files(Relocatable, SysFiles, Apps, ExclRegexps),
RelFiles = spec_rel_files(Sys),
- {InclRegexps2, BinFiles} =
- spec_bin_files(Sys, SysFiles, SysFiles2, RelFiles, InclRegexps),
+ {SysFiles, InclRegexps2, ExclRegexps2, Mandatory} =
+ case ExclLib of
+ otp_root ->
+ {[],InclRegexps,ExclRegexps,["lib"]};
+ _ ->
+ {create_dir, _, SF} = spec_dir(RootDir),
+ {ER2, SF2} = strip_sys_files(Relocatable, SF, Apps, ExclRegexps),
+ {IR2, BinFiles} =
+ spec_bin_files(Sys, SF, SF2, RelFiles, InclRegexps),
+ SF3 = [{create_dir, "bin", BinFiles}] ++ SF2,
+ {SF3,IR2,ER2,["bin","erts","lib"]}
+ end,
LibFiles = spec_lib_files(Sys),
{BootVsn, StartFile} = spec_start_file(Sys),
- SysFiles3 =
- [
- {create_dir, "releases",
+ SysFiles2 =
+ [{create_dir, "releases",
[StartFile,
- {create_dir,BootVsn, RelFiles}]},
- {create_dir, "bin", BinFiles}
- ] ++ SysFiles2,
- SysFiles4 = filter_spec(SysFiles3, InclRegexps2, ExclRegexps2),
- SysFiles5 = SysFiles4 ++ [{create_dir, "lib", LibFiles}],
- check_sys(["bin", "erts", "lib"], SysFiles5),
- SysFiles5.
+ {create_dir,BootVsn, RelFiles}]}] ++ SysFiles,
+ SysFiles3 = filter_spec(SysFiles2, InclRegexps2, ExclRegexps2),
+ SysFiles4 = SysFiles3 ++ [{create_dir, "lib", LibFiles}],
+ check_sys(Mandatory, SysFiles4),
+ SysFiles4.
strip_sys_files(Relocatable, SysFiles, Apps, ExclRegexps) ->
ExclRegexps2 =
@@ -895,7 +930,7 @@ spec_escripts(#sys{apps = Apps}, ErtsBin, BinFiles) ->
if
Name =:= ?MISSING_APP_NAME ->
false;
- not IsEscript ->
+ IsEscript =/= true ->
false;
IsIncl; IsPre ->
{true, do_spec_escript(File, ErtsBin, BinFiles)};
@@ -951,22 +986,35 @@ safe_lookup_spec(Prefix, Specs) ->
%% Specify applications
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec_lib_files(#sys{apps = Apps} = Sys) ->
+spec_lib_files(#sys{root_dir = RootDir,
+ apps = Apps,
+ excl_lib = ExclLib} = Sys) ->
Filter = fun(#app{is_escript = IsEscript, is_included = IsIncl,
- is_pre_included = IsPre, name = Name}) ->
+ is_pre_included = IsPre, name = Name,
+ active_dir = ActiveDir}) ->
if
Name =:= ?MISSING_APP_NAME ->
false;
- IsEscript ->
+ IsEscript =/= false ->
false;
IsIncl; IsPre ->
- true;
+ case ExclLib of
+ otp_root ->
+ not lists:prefix(RootDir,ActiveDir);
+ _ ->
+ true
+ end;
true ->
false
end
end,
SelectedApps = lists:filter(Filter, Apps),
- check_apps([kernel, stdlib], SelectedApps),
+ case ExclLib of
+ otp_root ->
+ ok;
+ _ ->
+ check_apps([kernel, stdlib], SelectedApps)
+ end,
lists:flatten([spec_app(App, Sys) || App <- SelectedApps]).
check_apps([Mandatory | Names], Apps) ->
diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl
index 39d057d994..6149d6ef06 100644
--- a/lib/reltool/src/reltool_utils.erl
+++ b/lib/reltool/src/reltool_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,17 @@
-export([root_dir/0, erl_libs/0, lib_dirs/1,
split_app_name/1, prim_consult/1,
default_rels/0, choose_default/3,
+ normalize_dir/1,
- assign_image_list/1, get_latest_resize/1,
+ assign_image_list/1, get_latest_resize/1, wait_for_stop_motion/2,
mod_conds/0, list_to_mod_cond/1, mod_cond_to_index/1,
incl_conds/0, list_to_incl_cond/1, incl_cond_to_index/1, elem_to_index/2,
app_dir_test/2, split_app_dir/1,
get_item/1, get_items/1, get_selected_items/3,
select_items/3, select_item/2,
+ get_column_width/1,
- safe_keysearch/5, print/4, return_first_error/2, add_warning/2,
+ safe_keysearch/5, print/4, add_warning/3,
create_dir/1, list_dir/1, read_file_info/1,
write_file_info/2, read_file/1, write_file/2,
@@ -86,6 +88,21 @@ split_app_name(Name) ->
{list_to_atom(Name), ""}
end.
+
+normalize_dir(RelDir) ->
+ Tokens = filename:split(filename:absname(RelDir)),
+ filename:join(lists:reverse(normalize_dir(Tokens, []))).
+
+normalize_dir([".."|Dirs], [_Dir|Path]) ->
+ normalize_dir(Dirs, Path);
+normalize_dir(["."|Dirs], Path) ->
+ normalize_dir(Dirs, Path);
+normalize_dir([Dir|Dirs], Path) ->
+ normalize_dir(Dirs, [Dir|Path]);
+normalize_dir([], Path) ->
+ Path.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
prim_consult(Bin) when is_binary(Bin) ->
@@ -126,18 +143,14 @@ prim_parse(Tokens, Acc) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
default_rels() ->
- %%Kernel = #rel_app{name = kernel, incl_apps = []},
- %%Stdlib = #rel_app{name = stdlib, incl_apps = []},
- Sasl = #rel_app{name = sasl, incl_apps = []},
+ %% kernel and stdlib are added automatically in every release
[
#rel{name = ?DEFAULT_REL_NAME,
vsn = "1.0",
rel_apps = []},
- %%rel_apps = [Kernel, Stdlib]},
#rel{name = "start_sasl",
vsn = "1.0",
- rel_apps = [Sasl]}
- %%rel_apps = [Kernel, Sasl, Stdlib]}
+ rel_apps = [#rel_app{name = sasl}]}
].
choose_default(Tag, Profile, InclDefs)
@@ -191,6 +204,16 @@ get_latest_resize(#wx{obj = ObjRef, event = #wxSize{}} = Wx) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+wait_for_stop_motion(ObjRef, {_,_}=Pos) ->
+ receive
+ #wx{obj = ObjRef, event = #wxMouse{type = motion, x=X, y=Y}} ->
+ wait_for_stop_motion(ObjRef, {X,Y})
+ after 100 ->
+ Pos
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
mod_conds() ->
["all (ebin + app file)", "ebin + derived", "app file + derived", "derived", "none"].
@@ -249,7 +272,7 @@ app_dir_test(Dir1, Dir2) ->
Name1 > Name2 -> false;
Vsn1 < Vsn2 -> false;
Vsn1 > Vsn2 -> true;
- Parent1 < Parent2 -> true;
+ Parent1 =< Parent2 -> true;
true -> false
end.
@@ -377,6 +400,26 @@ select_item(ListCtrl, [{ItemNo, Text} | Items]) ->
select_item(_ListCtrl, []) ->
ok.
+get_column_width(ListCtrl) ->
+ wx:batch(fun() ->
+ {Total, _} = wxWindow:getClientSize(ListCtrl),
+ Total - scroll_size(ListCtrl)
+ end).
+
+scroll_size(ObjRef) ->
+ case os:type() of
+ {win32, nt} -> 0;
+ {unix, darwin} ->
+ %% I can't figure out is there is a visible scrollbar
+ %% Always make room for it
+ wxSystemSettings:getMetric(?wxSYS_VSCROLL_X);
+ _ ->
+ case wxWindow:hasScrollbar(ObjRef, ?wxVERTICAL) of
+ true -> wxSystemSettings:getMetric(?wxSYS_VSCROLL_X);
+ false -> 0
+ end
+ end.
+
safe_keysearch(Key, Pos, List, Mod, Line) ->
case lists:keysearch(Key, Pos, List) of
false ->
@@ -392,31 +435,13 @@ print(X, X, Format, Args) ->
print(_, _, _, _) ->
ok.
-%% -define(SAFE(M,F,A), safe(M, F, A, ?MODULE, ?LINE)).
-%%
-%% safe(M, F, A, Mod, Line) ->
-%% case catch apply(M, F, A) of
-%% {'EXIT', Reason} ->
-%% io:format("~p(~p): ~p:~p~p -> ~p\n", [Mod, Line, M, F, A, Reason]),
-%% timer:sleep(infinity);
-%% Res ->
-%% Res
-%% end.
-
-return_first_error(Status, NewError) when is_list(NewError) ->
- case Status of
- {ok, _Warnings} ->
- {error, NewError};
- {error, OldError} ->
- {error, OldError}
- end.
-
-add_warning(Status, Warning) ->
- case Status of
- {ok, Warnings} ->
- {ok, [Warning | Warnings]};
- {error, Error} ->
- {error, Error}
+add_warning(Format, Args, {ok,Warnings}) ->
+ Warning = lists:flatten(io_lib:format(Format,Args)),
+ case lists:member(Warning,Warnings) of
+ true ->
+ {ok,Warnings};
+ false ->
+ {ok,[Warning|Warnings]}
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile
index 767454b66a..52cdef44da 100644
--- a/lib/reltool/test/Makefile
+++ b/lib/reltool/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2011. All Rights Reserved.
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,7 @@ MODULES= \
reltool_app_SUITE \
reltool_wx_SUITE \
reltool_server_SUITE \
+ reltool_manual_gui_SUITE \
reltool_test_lib
@@ -48,7 +49,7 @@ RELSYSDIR = $(RELEASE_PATH)/reltool_test
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-#ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS += -pa $(ERL_TOP)/lib/reltool/ebin/
EBIN = .
@@ -72,12 +73,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) reltool.spec reltool.cover $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_SCRIPT) rtt $(INSTALL_PROGS) $(RELSYSDIR)
- $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) reltool.spec reltool.cover $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_SCRIPT) rtt $(INSTALL_PROGS) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(INSTALL_PROGS) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/reltool/test/reltool.spec b/lib/reltool/test/reltool.spec
index 2995720105..2501a7a203 100644
--- a/lib/reltool/test/reltool.spec
+++ b/lib/reltool/test/reltool.spec
@@ -1 +1,2 @@
{suites,"../reltool_test",all}.
+{skip_suites,"../reltool_test",[reltool_manual_gui_SUITE],"Manual only"}.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE.erl b/lib/reltool/test/reltool_manual_gui_SUITE.erl
new file mode 100644
index 0000000000..0dcc5cbf15
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE.erl
@@ -0,0 +1,266 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(reltool_manual_gui_SUITE).
+
+-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).
+
+-include_lib("common_test/include/ct.hrl").
+-include("reltool_test_lib.hrl").
+
+%% Initialization functions.
+init_per_suite(Config) ->
+ reltool_test_lib:wx_init_per_suite(Config).
+
+end_per_suite(Config) ->
+ reltool_test_lib:wx_end_per_suite(Config).
+
+init_per_testcase(Func,Config) ->
+ reltool_test_lib:init_per_testcase(Func,Config).
+end_per_testcase(Func,Config) ->
+ reltool_test_lib:end_per_testcase(Func,Config).
+
+%% SUITE specification
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [config, depgraphs].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% The test cases
+
+%% Semi-automatic walkthrough of the GUI
+config(Config) ->
+ DataDir = ?config(data_dir,Config),
+ PrivDir = ?config(priv_dir,Config),
+ {ok, SysPid} = ?msym({ok, _}, reltool:start([])),
+ link(SysPid),
+
+ SimpleConfigFile = create_simple_config(PrivDir),
+ WarningConfigFile = create_warning_config(PrivDir,DataDir),
+
+ break("there are no modules in the 'Included' and 'Excluded' columns, "
+ "and now warnings are displayed",
+ {"load configuration ~p",[SimpleConfigFile]}),
+ break("kernel, stdlib and sasl are included and all other are excluded",
+ "undo"),
+ break("we are back to default - no included and no excluded applications",
+ "undo again"),
+ break("kernel, stdlib and sasl are included and all other are excluded",
+ {"load configuration ~p",
+ [WarningConfigFile]}),
+ break("a warning is displayed in the warning list",
+ "undo"),
+ break("no warning is displayed in the warning list",
+ "load same configuration again"),
+ break("application a is added in the 'Included' column and "
+ "one warning is displayed",
+ "reset configuration"),
+ break("we are back to default - no included and no excluded applications, "
+ "and no warnings",
+ "undo"),
+ break("a, kernel, stdlib and sasl are included and all other are excluded. "
+ "One warning should now exist through the rest of this test case",
+ "double click the warning"),
+ break("a popup window occurs displaying the warning text",
+ "close it with the 'Close' button"),
+ break("it disappears",
+ "open it again"),
+ break("the warning text can be marked, copied and pasted",
+ "close the popup with the close box on the top frame"),
+ break("it disappears",
+ "select application a from 'Included' column and click 'cross'-button "
+ "with to exclude it"),
+ break("application a is moved to 'Excluded' column",
+ "select application tools from 'Excluded' column and click "
+ "'tick'-button to include it"),
+ break("application tools is moved to 'Included' column",
+ "select application runtime_tools from 'Excluded' column and click "
+ "'tick'-button to include it"),
+ break("application runtime_tools is moved to 'Included' column",
+ "undo"),
+
+ ExplicitConfig = filename:join(PrivDir,"explicit.config"),
+ break("application runtime_tools is moved back to 'Excluded' column",
+ {"save configuration as 'explicit' to ~p",[ExplicitConfig]}),
+ ExpectedExplicitConfig =
+ {sys,[{lib_dirs,[filename:join(DataDir,"faulty_app_file")]},
+ {incl_cond,exclude},
+ {app,a,[{incl_cond,exclude}]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ check_config(ExpectedExplicitConfig,ExplicitConfig),
+
+ break("The saved configuration file is checked and is ok.\n"
+ "Now go to the 'Libraries' tab and change the root directory to "
+ "some invalid directory."),
+ break("an error dialog occurs saying that there is no lib dir",
+ {"add library directory ~p",
+ [filename:join(DataDir,"dependencies")]}),
+ break("applications x, y and z are added to the 'Excluded' column in "
+ "'Applications' tab",
+ "go to the 'System settings' tab and set application inclusion policy "
+ "to 'derived'"),
+ break("a is excluded, kernel, stdlib, sasl and tools are included and "
+ "x, y and z are available in the 'Applications' tab",
+ "undo"),
+ break("all non included application are moved to the 'Excluded' column "
+ "and that 'Application inclusion policy' under 'System settings' "
+ "tab is set back to 'exclude'",
+ "undo again"),
+ break("applications x, y and z are in the 'Available' column",
+ "open application x, go to the 'Application settings' tab and set "
+ "'Application inclusion policy' to 'Use application specific config' "
+ "and 'include'. Close the window"),
+ break("application x is moved to the 'Included' column and z and y are moved "
+ "to the 'Derived' column in the system window",
+ "open application y"),
+ break("modules y1, y2 and y3 are in the 'Derived' column",
+ "go to 'Application dependencies' tab"),
+ break("application y is used by x, requires kernel and stdlib, and uses z",
+ "go to 'Module dependencies' tab"),
+ break("y is used by x2 and x3, and uses z1",
+ "got to 'Application settings' tab and select "
+ "'Source selection policy' 'Use selected version'"),
+ break("'Directories' frame becomes enabled (clickable)",
+ "select 'Module inclusion policy' 'Use application specific config' "
+ "and select 'app file + derived'"),
+ break("module y3 is moved to the 'Available' column in the 'Modules' tab",
+ "open module y1"),
+ break("module y1 is used by x2 and uses z1",
+ "go to the 'Code' tab and double click the line with call to z1:f()"),
+ break("new tab is opened with module z1",
+ "find something"),
+ break("it is found",
+ "goto some line"),
+ break("the cursor is moved to that line",
+ "click the 'Back' button"),
+ break("the cursor is moved back to the line of your previous 'find'",
+ "terminate the application window (but keep the module window)."),
+
+ {ok,ServerPid} = reltool:get_server(SysPid),
+ unlink(SysPid),
+ break("the system window is still alive",
+ "terminate reltool by hitting 'Ctrl-q' (linux) or clicking the "
+ "close box on the top fram when system window is active"),
+ false = erlang:is_process_alive(SysPid),
+ false = erlang:is_process_alive(ServerPid),
+
+ break("Check that both module window and system window are terminated"),
+
+ ok.
+
+
+depgraphs(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ SimpleConfigFile = create_simple_config(PrivDir),
+ {ok, SysPid} = ?msym({ok, _}, reltool:start([{config,SimpleConfigFile}])),
+ link(SysPid),
+
+ break("Open the application dependency graph and \n\n"
+ "*move the complete graph by left clicking somewhere over it and drag\n"
+ "*move one node left clicking the node and drag\n"
+ "*lock node to position by holding down shift while releasing\n"
+ "*select several nodes with ctrl and left mouse button\n"
+ "*lock/unlock selected nodes with suitable buttons\n"
+ "*freeze\n"
+ "*reset\n"
+ "*left slider: push nodes apart\n"
+ "*right slider: pull nodes together\n"
+ "*middle slider: adjust length of links\n"
+ "*select node and delete\n"),
+ break("Open the module dependency graph and meditate over it... "),
+
+ unlink(SysPid),
+ break("Terminate reltool from the file menu in the system window"),
+ false = erlang:is_process_alive(SysPid),
+
+ break("Check that system window and graphs are terminated"),
+
+ ok.
+
+
+
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+break(CheckStr,DoStr) when is_list(CheckStr), is_list(DoStr) ->
+ Str = io_lib:format("Check that ~s.~n~nThen ~s.",[CheckStr,DoStr]),
+ break(Str);
+break(Check,Do) ->
+ CheckStr =
+ case Check of
+ {CheckFormat,CheckArgs} -> io_lib:format(CheckFormat,CheckArgs);
+ _ -> Check
+ end,
+ DoStr =
+ case Do of
+ {DoFormat,DoArgs} -> io_lib:format(DoFormat,DoArgs);
+ _ -> Do
+ end,
+ break(CheckStr,DoStr).
+
+break(Str) ->
+ Count =
+ case get(count) of
+ undefined -> 1;
+ C -> C
+ end,
+ put(count,Count+1),
+ test_server:break("Step " ++ integer_to_list(Count) ++ ":\n" ++ Str).
+
+check_config(Expected,File) ->
+ {ok,[Config]} = file:consult(File),
+ ?m(Expected,Config).
+
+create_simple_config(PrivDir) ->
+ SimpleConfigFile = filename:join(PrivDir,"simple.config"),
+ SimpleConfig = {sys,[{incl_cond,exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]}]},
+ ok=file:write_file(SimpleConfigFile,io_lib:format("~p.~n",[SimpleConfig])),
+ SimpleConfigFile.
+
+create_warning_config(PrivDir,DataDir) ->
+ WarningConfigFile = filename:join(PrivDir,"warning.config"),
+ FaultyAppFileDir = filename:join(DataDir,"faulty_app_file"),
+ WarningConfig = {sys,[{lib_dirs,[FaultyAppFileDir]},
+ {incl_cond,exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,a,[{incl_cond,include}]}
+ ]},
+ ok=file:write_file(WarningConfigFile,io_lib:format("~p.~n",[WarningConfig])),
+ WarningConfigFile.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/Makefile.src b/lib/reltool/test/reltool_manual_gui_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..9a340274ad
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/Makefile.src
@@ -0,0 +1,28 @@
+EFLAGS=+debug_info
+
+DEPENDENCIES= \
+ dependencies/x-1.0/ebin/x1.@EMULATOR@ \
+ dependencies/x-1.0/ebin/x2.@EMULATOR@ \
+ dependencies/x-1.0/ebin/x3.@EMULATOR@ \
+ dependencies/y-1.0/ebin/y1.@EMULATOR@ \
+ dependencies/y-1.0/ebin/y2.@EMULATOR@ \
+ dependencies/y-1.0/ebin/y3.@EMULATOR@ \
+ dependencies/z-1.0/ebin/z1.@EMULATOR@
+
+
+all: $(DEPENDENCIES)
+
+dependencies/x-1.0/ebin/x1.@EMULATOR@: dependencies/x-1.0/src/x1.erl
+ erlc $(EFLAGS) -odependencies/x-1.0/ebin dependencies/x-1.0/src/x1.erl
+dependencies/x-1.0/ebin/x2.@EMULATOR@: dependencies/x-1.0/src/x2.erl
+ erlc $(EFLAGS) -odependencies/x-1.0/ebin dependencies/x-1.0/src/x2.erl
+dependencies/x-1.0/ebin/x3.@EMULATOR@: dependencies/x-1.0/src/x3.erl
+ erlc $(EFLAGS) -odependencies/x-1.0/ebin dependencies/x-1.0/src/x3.erl
+dependencies/y-1.0/ebin/y1.@EMULATOR@: dependencies/y-1.0/src/y1.erl
+ erlc $(EFLAGS) -odependencies/y-1.0/ebin dependencies/y-1.0/src/y1.erl
+dependencies/y-1.0/ebin/y2.@EMULATOR@: dependencies/y-1.0/src/y2.erl
+ erlc $(EFLAGS) -odependencies/y-1.0/ebin dependencies/y-1.0/src/y2.erl
+dependencies/y-1.0/ebin/y3.@EMULATOR@: dependencies/y-1.0/src/y3.erl
+ erlc $(EFLAGS) -odependencies/y-1.0/ebin dependencies/y-1.0/src/y3.erl
+dependencies/z-1.0/ebin/z1.@EMULATOR@: dependencies/z-1.0/src/z1.erl
+ erlc $(EFLAGS) -odependencies/z-1.0/ebin dependencies/z-1.0/src/z1.erl
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/ebin/x.app b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/ebin/x.app
new file mode 100644
index 0000000000..ccaab8a8c7
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/ebin/x.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, x,
+ [{description, "Main application in reltool dependency test"},
+ {vsn, "1.0"},
+ {modules, [x1,x2,x3]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x1.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x1.erl
new file mode 100644
index 0000000000..bf1e7f9279
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x1.erl
@@ -0,0 +1,5 @@
+-module(x1).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x2.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x2.erl
new file mode 100644
index 0000000000..82191ba278
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x2.erl
@@ -0,0 +1,5 @@
+-module(x2).
+-compile(export_all).
+
+f() ->
+ y1:f().
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x3.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x3.erl
new file mode 100644
index 0000000000..618c75c9a7
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/x-1.0/src/x3.erl
@@ -0,0 +1,5 @@
+-module(x3).
+-compile(export_all).
+
+f() ->
+ y2:f().
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/ebin/y.app b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/ebin/y.app
new file mode 100644
index 0000000000..4f9b610b69
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/ebin/y.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, y,
+ [{description, "Library application in reltool dependency test"},
+ {vsn, "1.0"},
+ {modules, [y1,y2]}, % y3 is skipped on purpose - to test module inclusion policy
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y1.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y1.erl
new file mode 100644
index 0000000000..dd21b33292
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y1.erl
@@ -0,0 +1,5 @@
+-module(y1).
+-compile(export_all).
+
+f() ->
+ z1:f().
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y2.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y2.erl
new file mode 100644
index 0000000000..bf8ddf6080
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y2.erl
@@ -0,0 +1,5 @@
+-module(y2).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y3.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y3.erl
new file mode 100644
index 0000000000..915d64d5b9
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/y-1.0/src/y3.erl
@@ -0,0 +1,5 @@
+-module(y3).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/ebin/z.app b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/ebin/z.app
new file mode 100644
index 0000000000..437a0968e9
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/ebin/z.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, z,
+ [{description, "Library application in reltool dependency test"},
+ {vsn, "1.0"},
+ {modules, [z1]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/src/z1.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/src/z1.erl
new file mode 100644
index 0000000000..97ef90b87f
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/dependencies/z-1.0/src/z1.erl
@@ -0,0 +1,5 @@
+-module(z1).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/ebin/a.app b/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/ebin/a.app
new file mode 100644
index 0000000000..ea77103598
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/ebin/a.app
@@ -0,0 +1 @@
+faulty app file
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/src/a.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/src/a.erl
new file mode 100644
index 0000000000..bb500bed69
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/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/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/src/a_sup.erl b/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/a-1.0/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/reltool/test/reltool_manual_gui_SUITE_data/faulty_app_file/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/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index 9ed79e8c95..f29f6049a5 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,7 @@
-compile(export_all).
+-include_lib("reltool/src/reltool.hrl").
-include("reltool_test_lib.hrl").
-include_lib("common_test/include/ct.hrl").
@@ -51,10 +52,46 @@ end_per_testcase(Func,Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [start_server, set_config, create_release,
- create_script, create_target, create_embedded,
- create_standalone, create_old_target,
- otp_9135, otp_9229_exclude_app, otp_9229_exclude_mod].
+ [start_server,
+ set_config,
+ get_config,
+ create_release,
+ create_release_sort,
+ create_script,
+ create_script_sort,
+ create_target,
+ create_embedded,
+ create_standalone,
+ create_standalone_beam,
+ create_standalone_app,
+ create_standalone_app_clash,
+ create_multiple_standalone,
+ create_old_target,
+ create_slim,
+ eval_target_spec,
+ otp_9135,
+ otp_9229_dupl_mod_exclude_app,
+ otp_9229_dupl_mod_exclude_mod,
+ dupl_mod_in_app_file,
+ get_apps,
+ get_mod,
+ get_sys,
+ set_app_and_undo,
+ set_apps_and_undo,
+ set_apps_inlined,
+ set_sys_and_undo,
+ load_config_and_undo,
+ load_config_fail,
+ load_config_escript_path,
+ load_config_same_escript_source,
+ load_config_same_escript_beam,
+ load_config_add_escript,
+ reset_config_and_undo,
+ gen_rel_files,
+ save_config,
+ dependencies,
+ use_selected_vsn,
+ use_selected_vsn_relative_path].
groups() ->
[].
@@ -71,8 +108,6 @@ end_per_group(_GroupName, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Start a server process and check that it does not crash
-start_server(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
start_server(_Config) ->
{ok, Pid} = ?msym({ok, _}, reltool:start_server([])),
Libs = lists:sort(erl_libs()),
@@ -88,8 +123,6 @@ start_server(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Start a server process and check that it does not crash
-set_config(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
set_config(_Config) ->
Libs = lists:sort(erl_libs()),
Default =
@@ -112,10 +145,102 @@ set_config(_Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Check that get_config returns the expected derivates and defaults
+%% as specified
+get_config(_Config) ->
+
+ KVsn = latest(kernel),
+ StdVsn = latest(stdlib),
+ SaslVsn = latest(sasl),
+
+ LibDir = code:lib_dir(),
+ KLibDir = filename:join(LibDir,"kernel-"++KVsn),
+ StdLibDir = filename:join(LibDir,"stdlib-"++StdVsn),
+ SaslLibDir = filename:join(LibDir,"sasl-"++SaslVsn),
+
+ Sys = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include},{vsn,SaslVsn}]},
+ {app,stdlib,[{incl_cond,include},{lib_dir,StdLibDir}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+ ?m({ok, Sys}, reltool:get_config(Pid)),
+ ?m({ok, Sys}, reltool:get_config(Pid,false,false)),
+
+ %% Include derived info
+ ?msym({ok,{sys,[{incl_cond, exclude},
+ {erts,[]},
+ {app,kernel,[{incl_cond,include},{mod,_,[]}|_]},
+ {app,sasl,[{incl_cond,include},{vsn,SaslVsn},{mod,_,[]}|_]},
+ {app,stdlib,[{incl_cond,include},{lib_dir,StdLibDir},
+ {mod,_,[]}|_]}]}},
+ reltool:get_config(Pid,false,true)),
+
+ %% Include defaults
+ ?msym({ok,{sys,[{root_dir,_},
+ {lib_dirs,_},
+ {mod_cond,all},
+ {incl_cond,exclude},
+ {app,kernel,[{incl_cond,include},{vsn,undefined},
+ {lib_dir,undefined}]},
+ {app,sasl,[{incl_cond,include},{vsn,SaslVsn},
+ {lib_dir,undefined}]},
+ {app,stdlib,[{incl_cond,include},{vsn,undefined},
+ {lib_dir,StdLibDir}]},
+ {boot_rel,"start_clean"},
+ {rel,"start_clean","1.0",[]},
+ {rel,"start_sasl","1.0",[sasl]},
+ {emu_name,"beam"},
+ {relocatable,true},
+ {profile,development},
+ {incl_sys_filters,[".*"]},
+ {excl_sys_filters,[]},
+ {incl_app_filters,[".*"]},
+ {excl_app_filters,[]},
+ {incl_archive_filters,[".*"]},
+ {excl_archive_filters,["^include$","^priv$"]},
+ {archive_opts,[]},
+ {rel_app_type,permanent},
+ {app_file,keep},
+ {debug_info,keep}]}},
+ reltool:get_config(Pid,true,false)),
+
+ %% Include both defaults and derived info
+ ?msym({ok,{sys,[{root_dir,_},
+ {lib_dirs,_},
+ {mod_cond,all},
+ {incl_cond,exclude},
+ {erts,[]},
+ {app,kernel,[{incl_cond,include},{vsn,KVsn},
+ {lib_dir,KLibDir},{mod,_,[]}|_]},
+ {app,sasl,[{incl_cond,include},{vsn,SaslVsn},
+ {lib_dir,SaslLibDir},{mod,_,[]}|_]},
+ {app,stdlib,[{incl_cond,include},{vsn,StdVsn},
+ {lib_dir,StdLibDir},{mod,_,[]}|_]},
+ {boot_rel,"start_clean"},
+ {rel,"start_clean","1.0",[]},
+ {rel,"start_sasl","1.0",[sasl]},
+ {emu_name,"beam"},
+ {relocatable,true},
+ {profile,development},
+ {incl_sys_filters,[".*"]},
+ {excl_sys_filters,[]},
+ {incl_app_filters,[".*"]},
+ {excl_app_filters,[]},
+ {incl_archive_filters,[".*"]},
+ {excl_archive_filters,["^include$","^priv$"]},
+ {archive_opts,[]},
+ {rel_app_type,permanent},
+ {app_file,keep},
+ {debug_info,keep}]}},
+ reltool:get_config(Pid,true,true)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% OTP-9135, test that app_file option can be set to all | keep | strip
-otp_9135(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
otp_9135(_Config) ->
Libs = lists:sort(erl_libs()),
StrippedDefaultSys =
@@ -145,8 +270,6 @@ otp_9135(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate releases
-create_release(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
create_release(_Config) ->
%% Configure the server
RelName = "Just testing...",
@@ -170,10 +293,135 @@ create_release(_Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate releases and make sure order of applications specified in
+%% 'rel' parameter is preserved and that included applications are
+%% started before the including application.
+%% Circular dependencies shall also be detected and cause error.
+
+create_release_sort(_Config) -> {skip, "Two bugs related to sorting"};
+create_release_sort(Config) ->
+ DataDir = ?config(data_dir,Config),
+ %% Configure the server
+ RelName1 = "MnesiaFirst",
+ RelName2 = "SaslFirst",
+ RelName3 = "Include-both",
+ RelName4 = "Include-only-app",
+ RelName5 = "Include-only-rel",
+ RelName6 = "Include-missing-app",
+ RelName7 = "Circular",
+ RelName8 = "Include-both-missing-app",
+ RelName9 = "Include-overwrite",
+ RelName10= "Uses-order-as-rel",
+ RelVsn = "1.0",
+ %% Application z (.app file):
+ %% includes [tools, mnesia]
+ %% uses [kernel, stdlib, sasl, inets]
+ Sys =
+ {sys,
+ [
+ {lib_dirs, [filename:join(DataDir,"sort_apps")]},
+ {boot_rel, RelName1},
+ {rel, RelName1, RelVsn, [stdlib, kernel, mnesia, sasl]},
+ {rel, RelName2, RelVsn, [stdlib, kernel, sasl, mnesia]},
+ {rel, RelName3, RelVsn, [stdlib, kernel, {z,[tools]}, tools, mnesia]},
+ {rel, RelName4, RelVsn, [stdlib, kernel, z, mnesia, tools]},
+ {rel, RelName5, RelVsn, [stdlib, kernel, {sasl,[tools]}]},
+ {rel, RelName6, RelVsn, [stdlib, kernel, z]},
+ {rel, RelName7, RelVsn, [stdlib, kernel, mnesia, y, sasl, x]},
+ {rel, RelName8, RelVsn, [stdlib, kernel, {z,[tools]}]},
+ {rel, RelName9, RelVsn, [stdlib, kernel, {z,[]}]},
+ {rel, RelName10, RelVsn, [stdlib, kernel, {z,[]}, inets, sasl]},
+ {incl_cond,exclude},
+ {mod_cond,app},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,mnesia,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,inets,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include}]},
+ {app,y,[{incl_cond,include}]},
+ {app,z,[{incl_cond,include}]},
+ {app,tools,[{mod_cond,app},{incl_cond,include}]}
+ ]},
+ %% Generate release
+
+ ?msym({ok, {release, {RelName1, RelVsn},
+ {erts, _},
+ [{kernel, _},
+ {stdlib, _},
+ {mnesia, _},
+ {sasl, _}]}},
+ reltool:get_rel([{config, Sys}], RelName1)),
+
+ ?msym({ok, {release, {RelName2, RelVsn},
+ {erts, _},
+ [{kernel, _},
+ {stdlib, _},
+ {sasl, _},
+ {mnesia, _}]}},
+ reltool:get_rel([{config, Sys}], RelName2)),
+
+ ?msym({ok, {release, {RelName3, RelVsn},
+ {erts, _},
+ [{kernel, _},
+ {stdlib, _},
+ {sasl, _},
+ {inets, _},
+ {tools, _},
+ {z, _, [tools]},
+ {mnesia, _}]}},
+ reltool:get_rel([{config, Sys}], RelName3)),
+
+ %%! BUG: same as OTP-4121, but for reltool???? Or revert tools and mnesia
+ ?msym({ok, {release, {RelName4, RelVsn},
+ {erts, _},
+ [{kernel, _},
+ {stdlib, _},
+ {sasl, _},
+ {inets, _},
+ {mnesia, _},
+ {tools, _},
+ {z, _}]}},
+ reltool:get_rel([{config, Sys}], RelName4)),
+
+ ?m({error,"sasl: These applications are used by release "
+ "Include-only-rel but are missing as included_applications "
+ "in the app file: [tools]"},
+ reltool:get_rel([{config, Sys}], RelName5)),
+
+ ?m({error, "Undefined applications: [tools,mnesia]"},
+ reltool:get_rel([{config, Sys}], RelName6)),
+
+ ?m({error,"Circular dependencies: [x,y]"},
+ reltool:get_rel([{config, Sys}], RelName7)),
+
+ ?m({error,"Undefined applications: [tools]"},
+ reltool:get_rel([{config, Sys}], RelName8)),
+
+ ?msym({ok,{release,{RelName9,RelVsn},
+ {erts,_},
+ [{kernel,_},
+ {stdlib,_},
+ {sasl, _},
+ {inets, _},
+ {z,_,[]}]}},
+ reltool:get_rel([{config, Sys}], RelName9)),
+
+ %%! BUG: same as OTP-9984, but for reltool???? Or revert inets and sasl?
+ ?msym({ok,{release,{RelName10,RelVsn},
+ {erts,_},
+ [{kernel,_},
+ {stdlib,_},
+ {inets, _},
+ {sasl, _},
+ {z,_,[]}]}},
+ reltool:get_rel([{config, Sys}], RelName10)),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate boot scripts
-create_script(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
create_script(_Config) ->
%% Configure the server
RelName = "Just testing",
@@ -218,10 +466,197 @@ create_script(_Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test creation of .script with different sorting of applications and
+%% included applications.
+%% Test that result is equal to what systools produces
+create_script_sort(Config) ->
+ DataDir = ?config(data_dir,Config),
+ %% Configure the server
+ RelName1 = "MnesiaFirst",
+ RelName2 = "SaslFirst",
+ RelName3 = "Include-both",
+ RelName4 = "Include-only-app",
+ RelName5 = "Include-only-rel",
+ RelName6 = "Include-missing-app",
+ RelName7 = "Circular",
+ RelName8 = "Include-both-missing-app",
+ RelName9 = "Include-overwrite",
+ RelVsn = "1.0",
+ LibDir = filename:join(DataDir,"sort_apps"),
+ Sys =
+ {sys,
+ [
+ {lib_dirs, [LibDir]},
+ {boot_rel, RelName1},
+ {rel, RelName1, RelVsn, [stdlib, kernel, mnesia, sasl]},
+ {rel, RelName2, RelVsn, [stdlib, kernel, sasl, mnesia]},
+ {rel, RelName3, RelVsn, [stdlib, kernel, {z,[tools]}, tools, mnesia]},
+ {rel, RelName4, RelVsn, [stdlib, kernel, z, mnesia, tools]},
+ {rel, RelName5, RelVsn, [stdlib, kernel, {sasl,[tools]}]},
+ {rel, RelName6, RelVsn, [stdlib, kernel, z]},
+ {rel, RelName7, RelVsn, [stdlib, kernel, mnesia, y, sasl, x]},
+ {rel, RelName8, RelVsn, [stdlib, kernel, {z,[tools]}]},
+ {rel, RelName9, RelVsn, [stdlib, kernel, {z,[]}]},
+ {incl_cond,exclude},
+ {mod_cond,app},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,mnesia,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,inets,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include}]},
+ {app,y,[{incl_cond,include}]},
+ {app,z,[{incl_cond,include}]},
+ {app,tools,[{mod_cond,app},{incl_cond,include}]}
+ ]},
+
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ %% Generate release files
+ application:load(sasl),
+ application:load(inets),
+ application:load(mnesia),
+ application:load(tools),
+ {ok,KernelVsn} = application:get_key(kernel,vsn),
+ {ok,StdlibVsn} = application:get_key(stdlib,vsn),
+ {ok,SaslVsn} = application:get_key(sasl,vsn),
+ {ok,InetsVsn} = application:get_key(inets,vsn),
+ {ok,MnesiaVsn} = application:get_key(mnesia,vsn),
+ {ok,ToolsVsn} = application:get_key(tools,vsn),
+ ErtsVsn = erlang:system_info(version),
+
+ Rel1 = {release, {RelName1,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {mnesia,MnesiaVsn},
+ {sasl,SaslVsn}]},
+ FullName1 = filename:join(?WORK_DIR,RelName1),
+ ?m(ok, file:write_file(FullName1 ++ ".rel", io_lib:format("~p.\n", [Rel1]))),
+ Rel2 = {release, {RelName2,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {sasl,SaslVsn},
+ {mnesia,MnesiaVsn}]},
+ FullName2 = filename:join(?WORK_DIR,RelName2),
+ ?m(ok, file:write_file(FullName2 ++ ".rel", io_lib:format("~p.\n", [Rel2]))),
+ Rel3 = {release, {RelName3,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {z,"1.0",[tools]},
+ {tools,ToolsVsn},
+ {mnesia,MnesiaVsn},
+ {sasl,SaslVsn},
+ {inets,InetsVsn}]},
+ FullName3 = filename:join(?WORK_DIR,RelName3),
+ ?m(ok, file:write_file(FullName3 ++ ".rel", io_lib:format("~p.\n", [Rel3]))),
+ Rel4 = {release, {RelName4,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {z,"1.0"},
+ {tools,ToolsVsn},
+ {mnesia,MnesiaVsn},
+ {sasl,SaslVsn},
+ {inets,InetsVsn}]},
+ FullName4 = filename:join(?WORK_DIR,RelName4),
+ ?m(ok, file:write_file(FullName4 ++ ".rel", io_lib:format("~p.\n", [Rel4]))),
+ Rel5 = {release, {RelName5,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {sasl,SaslVsn,[tools]},
+ {tools,ToolsVsn}]},
+ FullName5 = filename:join(?WORK_DIR,RelName5),
+ ?m(ok, file:write_file(FullName5 ++ ".rel", io_lib:format("~p.\n", [Rel5]))),
+ Rel6 = {release, {RelName6,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {z,"1.0"}]},
+ FullName6 = filename:join(?WORK_DIR,RelName6),
+ ?m(ok, file:write_file(FullName6 ++ ".rel", io_lib:format("~p.\n", [Rel6]))),
+ Rel7 = {release, {RelName7,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {mnesia,MnesiaVsn},
+ {y,"1.0"},
+ {sasl,SaslVsn},
+ {x,"1.0"}]},
+ FullName7 = filename:join(?WORK_DIR,RelName7),
+ ?m(ok, file:write_file(FullName7 ++ ".rel", io_lib:format("~p.\n", [Rel7]))),
+ Rel8 = {release, {RelName8,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {z,"1.0",[tools]}]},
+ FullName8 = filename:join(?WORK_DIR,RelName8),
+ ?m(ok, file:write_file(FullName8 ++ ".rel", io_lib:format("~p.\n", [Rel8]))),
+ Rel9 = {release, {RelName9,RelVsn}, {erts,ErtsVsn},
+ [{kernel,KernelVsn},
+ {stdlib,StdlibVsn},
+ {z,"1.0",[]},
+ {sasl,SaslVsn},
+ {inets,InetsVsn}]},
+ FullName9 = filename:join(?WORK_DIR,RelName9),
+ ?m(ok, file:write_file(FullName9 ++ ".rel", io_lib:format("~p.\n", [Rel9]))),
+
+ %% Generate script files with systools and reltool and compare
+ ZPath = filename:join([LibDir,"*",ebin]),
+
+ ?msym({ok,_,_}, systools_make_script(FullName1,ZPath)),
+ {ok, [SystoolsScript1]} = ?msym({ok,[_]}, file:consult(FullName1++".script")),
+ {ok, Script1} = ?msym({ok, _}, reltool:get_script(Pid, RelName1)),
+ ?m(equal, diff_script(SystoolsScript1, Script1)),
+
+ ?msym({ok,_,_}, systools_make_script(FullName2,ZPath)),
+ {ok, [SystoolsScript2]} = ?msym({ok,[_]}, file:consult(FullName2++".script")),
+ {ok, Script2} = ?msym({ok, _}, reltool:get_script(Pid, RelName2)),
+ ?m(equal, diff_script(SystoolsScript2, Script2)),
+
+ ?msym({ok,_,_}, systools_make_script(FullName3,ZPath)),
+ {ok, [SystoolsScript3]} = ?msym({ok,[_]}, file:consult(FullName3++".script")),
+ {ok, Script3} = ?msym({ok, _}, reltool:get_script(Pid, RelName3)),
+ ?m(equal, diff_script(SystoolsScript3, Script3)),
+
+ ?msym({ok,_,_}, systools_make_script(FullName4,ZPath)),
+ {ok, [SystoolsScript4]} = ?msym({ok,[_]}, file:consult(FullName4++".script")),
+ {ok, Script4} = ?msym({ok, _}, reltool:get_script(Pid, RelName4)),
+ ?m(equal, diff_script(SystoolsScript4, Script4)),
+
+ ?msym({error,_,[{error_reading,{sasl,{override_include,_}}}]},
+ systools_make_script(FullName5,ZPath)),
+ ?m({error,"sasl: These applications are used by release "
+ "Include-only-rel but are missing as included_applications "
+ "in the app file: [tools]"},
+ reltool:get_script(Pid, RelName5)),
+
+ ?msym({error,_,{undefined_applications,_}},
+ systools_make_script(FullName6,ZPath)),
+ ?m({error, "Undefined applications: [tools,mnesia]"},
+ reltool:get_script(Pid, RelName6)),
+
+ ?msym({error,_,{circular_dependencies,_}},
+ systools_make_script(FullName7,ZPath)),
+ ?m({error,"Circular dependencies: [x,y]"},
+ reltool:get_script(Pid, RelName7)),
+
+ ?msym({error,_,{undefined_applications,_}},
+ systools_make_script(FullName8,ZPath)),
+ ?m({error, "Undefined applications: [tools]"},
+ reltool:get_script(Pid, RelName8)),
+
+ ?msym({ok,_,_}, systools_make_script(FullName9,ZPath)),
+ {ok, [SystoolsScript9]} = ?msym({ok,[_]}, file:consult(FullName9++".script")),
+ {ok, Script9} = ?msym({ok, _}, reltool:get_script(Pid, RelName9)),
+ ?m(equal, diff_script(SystoolsScript9, Script9)),
+
+ %% Stop server
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+systools_make_script(Name,Path) ->
+ systools:make_script(Name,[{path,[Path]},{outdir,?WORK_DIR},silent]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate target system
-create_target(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
create_target(_Config) ->
%% Configure the server
RelName1 = "Just testing",
@@ -243,7 +678,7 @@ create_target(_Config) ->
?m(ok, reltool_utils:recursive_delete(TargetDir)),
?m(ok, file:make_dir(TargetDir)),
?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Config}])]),
- ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
Erl = filename:join([TargetDir, "bin", "erl"]),
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
@@ -254,8 +689,6 @@ create_target(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate embedded target system
-create_embedded(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
create_embedded(_Config) ->
%% Configure the server
RelName1 = "Just testing",
@@ -276,7 +709,7 @@ create_embedded(_Config) ->
TargetDir = filename:join([?WORK_DIR, "target_embedded"]),
?m(ok, reltool_utils:recursive_delete(TargetDir)),
?m(ok, file:make_dir(TargetDir)),
- ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
Erl = filename:join([TargetDir, "bin", "erl"]),
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
@@ -287,8 +720,6 @@ create_embedded(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate standalone system
-create_standalone(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
create_standalone(_Config) ->
%% Configure the server
ExDir = code:lib_dir(reltool, examples),
@@ -306,30 +737,223 @@ create_standalone(_Config) ->
TargetDir = filename:join([?WORK_DIR, "target_standalone"]),
?m(ok, reltool_utils:recursive_delete(TargetDir)),
?m(ok, file:make_dir(TargetDir)),
- ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
+ %% Start the target system and fetch root dir
BinDir = filename:join([TargetDir, "bin"]),
Erl = filename:join([BinDir, "erl"]),
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
RootDir = ?ignore(rpc:call(Node, code, root_dir, [])),
?msym(ok, stop_node(Node)),
+ %% Execute escript
Expected = iolist_to_binary(["Root dir: ", RootDir, "\n"
"Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n",
"Smp: false\n",
"ExitCode:0"]),
io:format("Expected: ~s\n", [Expected]),
- ?m(Expected, run(BinDir, EscriptName ++ " -arg1 arg2 arg3")),
+ ?m(Expected, run(BinDir, EscriptName, "-arg1 arg2 arg3")),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate standalone system with inlined beam file
+
+create_standalone_beam(Config) ->
+ %% Read beam file
+ DataDir = ?config(data_dir,Config),
+ BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]),
+ {ok,BeamBin} = file:read_file(BeamFile),
+
+ %% Create the escript
+ EscriptName = "mymod.escript",
+ Escript = filename:join(?WORK_DIR,EscriptName),
+ ok = escript:create(Escript,[shebang,{beam,BeamBin}]),
+ ok = file:change_mode(Escript,8#00744),
+
+ %% Configure the server
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ %% Generate target file
+ TargetDir = filename:join([?WORK_DIR, "target_standalone_beam"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)),
+
+ %% Start the target system and fetch root dir
+ BinDir = filename:join([TargetDir, "bin"]),
+ Erl = filename:join([BinDir, "erl"]),
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
+ RootDir = ?ignore(rpc:call(Node, code, root_dir, [])),
+ ?msym(ok, stop_node(Node)),
+
+ %% Execute escript
+ Expected = iolist_to_binary(["Root dir: ", RootDir, "\n"
+ "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n",
+ "ExitCode:0"]),
+ io:format("Expected: ~s\n", [Expected]),
+ ?m(Expected, run(BinDir, EscriptName, "-arg1 arg2 arg3")),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate standalone system with inlined archived application
+
+create_standalone_app(Config) ->
+ %% Create archive
+ DataDir = ?config(data_dir,Config),
+ EscriptDir = filename:join(DataDir,escript),
+ {ok,{_Archive,Bin}} = zip:create("someapp-1.0.ez",["someapp-1.0"],
+ [memory,
+ {cwd,EscriptDir},
+ {compress,all},
+ {uncompress,[".beam",".app"]}]),
+
+ %% Create the escript
+ EscriptName = "someapp.escript",
+ Escript = filename:join(?WORK_DIR,EscriptName),
+ ok = escript:create(Escript,[shebang,
+ {emu_args,"-escript main mymod"},
+ {archive,Bin}]),
+ ok = file:change_mode(Escript,8#00744),
+
+ %% Configure the server
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ %% Generate target file
+ TargetDir = filename:join([?WORK_DIR, "target_standalone_app"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)),
+
+ %% Start the target system and fetch root dir
+ BinDir = filename:join([TargetDir, "bin"]),
+ Erl = filename:join([BinDir, "erl"]),
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
+ RootDir = ?ignore(rpc:call(Node, code, root_dir, [])),
+ ?msym(ok, stop_node(Node)),
+
+ %% Execute escript
+ Expected = iolist_to_binary(["Root dir: ", RootDir, "\n"
+ "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n",
+ "ExitCode:0"]),
+ io:format("Expected: ~s\n", [Expected]),
+ ?m(Expected, run(BinDir, EscriptName, "-arg1 arg2 arg3")),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate standalone system with inlined archived application
+%% Check that the inlined app can not be explicitly configured
+
+create_standalone_app_clash(Config) ->
+ %% Create archive
+ DataDir = ?config(data_dir,Config),
+ EscriptDir = filename:join(DataDir,escript),
+ {ok,{_Archive,Bin}} = zip:create("someapp-1.0.ez",["someapp-1.0"],
+ [memory,
+ {cwd,EscriptDir},
+ {compress,all},
+ {uncompress,[".beam",".app"]}]),
+
+ %% Create the escript
+ EscriptName = "someapp.escript",
+ Escript = filename:join(?WORK_DIR,EscriptName),
+ ok = escript:create(Escript,[shebang,
+ {emu_args,"-escript main mymod"},
+ {archive,Bin}]),
+ ok = file:change_mode(Escript,8#00744),
+
+ %% Configure the server
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript, [{incl_cond, include}]},
+ {profile, standalone},
+ {app, someapp, [{incl_cond,include}]}
+ ]},
+
+ ?msym({error,"someapp: Application name clash. Escript "++_},
+ reltool:start_server([{config,Sys}])),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate standalone system with multiple escripts
+
+create_multiple_standalone(Config) ->
+ %% First escript
+ ExDir = code:lib_dir(reltool, examples),
+ EscriptName1 = "display_args",
+ Escript1 = filename:join([ExDir, EscriptName1]),
+
+ %% Second escript
+ DataDir = ?config(data_dir,Config),
+ BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]),
+ {ok,BeamBin} = file:read_file(BeamFile),
+ EscriptName2 = "mymod.escript",
+ Escript2 = filename:join(?WORK_DIR,EscriptName2),
+ ok = escript:create(Escript2,[shebang,{beam,BeamBin}]),
+ ok = file:change_mode(Escript2,8#00744),
+
+ %% Configure server
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript1, [{incl_cond, include}]},
+ {escript, Escript2, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ %% Generate target system
+ TargetDir = filename:join([?WORK_DIR, "target_multiple_standalone"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config,Sys}], TargetDir)),
+
+ %% Start the target system and fetch root dir
+ BinDir = filename:join([TargetDir, "bin"]),
+ Erl = filename:join([BinDir, "erl"]),
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
+ RootDir = ?ignore(rpc:call(Node, code, root_dir, [])),
+ ?msym(ok, stop_node(Node)),
+
+ %% Execute escript1
+ Expected1 = iolist_to_binary(["Root dir: ", RootDir, "\n"
+ "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n",
+ "Smp: false\n",
+ "ExitCode:0"]),
+ io:format("Expected1: ~s\n", [Expected1]),
+ ?m(Expected1, run(BinDir, EscriptName1, "-arg1 arg2 arg3")),
+
+
+ %% Execute escript2
+ Expected2 = iolist_to_binary(["Root dir: ", RootDir, "\n"
+ "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n",
+ "ExitCode:0"]),
+ io:format("Expected2: ~s\n", [Expected2]),
+ ?m(Expected2, run(BinDir, EscriptName2, "-arg1 arg2 arg3")),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate old type of target system
-create_old_target(TestInfo) when is_atom(TestInfo) ->
- reltool_test_lib:tc_info(TestInfo);
+create_old_target(_Config) -> {skip, "Old style of target"};
create_old_target(_Config) ->
- ?skip("Old style of target", []),
%% Configure the server
RelName1 = "Just testing",
@@ -350,10 +974,10 @@ create_old_target(_Config) ->
TargetDir = filename:join([?WORK_DIR, "target_old_style"]),
?m(ok, reltool_utils:recursive_delete(TargetDir)),
?m(ok, file:make_dir(TargetDir)),
- ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
+ ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)),
%% io:format("Will fail on Windows (should patch erl.ini)\n", []),
- ?m(ok, reltool:install(RelName2, TargetDir)),
+ ok = ?m(ok, reltool:install(RelName2, TargetDir)),
Erl = filename:join([TargetDir, "bin", "erl"]),
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
@@ -362,11 +986,93 @@ create_old_target(_Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate target system
+
+create_slim(Config) ->
+ %% Configure the server
+ RelName = "slim",
+ RelVsn = "1.0",
+
+ DataDir = ?config(data_dir,Config),
+ LibDir = filename:join(DataDir,"slim"),
+
+ Sys =
+ {sys,
+ [
+ {root_dir, code:root_dir()},
+ {lib_dirs, []},
+ {boot_rel, RelName},
+ {rel, RelName, RelVsn, [sasl, stdlib, kernel, a]},
+ {app, sasl, [{incl_cond, include}]},
+ {app, a, [{incl_cond, include},
+ {lib_dir,filename:join(LibDir,"a-1.0")}]},
+ {excl_lib,otp_root}
+ ]},
+
+ %% Generate target file
+ TargetDir = filename:absname(filename:join([?WORK_DIR, "target_slim"])),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]),
+ ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)),
+
+ TargetLibDir = filename:join(TargetDir,"lib"),
+ TargetRelDir = filename:join(TargetDir,"releases"),
+ TargetRelVsnDir = filename:join(TargetRelDir,RelVsn),
+
+ {ok,["a-1.0.ez"]} = file:list_dir(TargetLibDir),
+
+ RootDir = code:root_dir(),
+ Erl = filename:join([RootDir, "bin", "erl"]),
+ Args = "-boot_var RELTOOL_EXT_LIB " ++ TargetLibDir ++
+ " -boot " ++ filename:join(TargetRelVsnDir,RelName) ++
+ " -sasl releases_dir \\\"" ++ TargetRelDir ++ "\\\"",
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl, Args)),
+ ?msym(RootDir, rpc:call(Node, code, root_dir, [])),
+ ?msym([{RelName,RelVsn,_,permanent}],
+ rpc:call(Node,release_handler,which_releases,[])),
+ ?msym(ok, stop_node(Node)),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Generate target system with eval_target_spec/3
+
+eval_target_spec(_Config) ->
+ %% Configure the server
+ RelName1 = "Just testing",
+ RelName2 = "Just testing with SASL",
+ RelVsn = "1.0",
+ Config =
+ {sys,
+ [
+ {root_dir, code:root_dir()},
+ {lib_dirs, []},
+ {boot_rel, RelName2},
+ {rel, RelName1, RelVsn, [stdlib, kernel]},
+ {rel, RelName2, RelVsn, [sasl, stdlib, kernel]},
+ {app, sasl, [{incl_cond, include}]}
+ ]},
+
+ %% Generate target file
+ TargetDir = filename:join([?WORK_DIR, "eval_target_spec"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ {ok, Spec} = ?msym({ok,_}, reltool:get_target_spec([{config, Config}])),
+ ok = ?m(ok, reltool:eval_target_spec(Spec, code:root_dir(), TargetDir)),
+
+ Erl = filename:join([TargetDir, "bin", "erl"]),
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
+ ?msym(ok, stop_node(Node)),
+
+ 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) ->
+otp_9229_dupl_mod_exclude_app(Config) ->
DataDir = ?config(data_dir,Config),
LibDir = filename:join(DataDir,"otp_9229"),
@@ -389,8 +1095,8 @@ otp_9229_exclude_app(Config) ->
?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)),
+ ?m({ok,["Module mylib exists in applications x and y. Using module from application x."]}, reltool:get_status([{config, ExclApp}])),
+ ok = ?m(ok, reltool:create_target([{config, ExclApp}], TargetDir)),
Erl = filename:join([TargetDir, "bin", "erl"]),
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
@@ -413,7 +1119,7 @@ otp_9229_exclude_app(Config) ->
ok.
%% Include both apps, but exclude common module from one app
-otp_9229_exclude_mod(Config) ->
+otp_9229_dupl_mod_exclude_mod(Config) ->
DataDir = ?config(data_dir,Config),
LibDir = filename:join(DataDir,"otp_9229"),
@@ -436,8 +1142,8 @@ otp_9229_exclude_mod(Config) ->
?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)),
+ ?m({ok,["Module mylib exists in applications x and y. Using module from application x."]}, reltool:get_status([{config, ExclMod}])),
+ ok = ?m(ok, reltool:create_target([{config, ExclMod}], TargetDir)),
Erl = filename:join([TargetDir, "bin", "erl"]),
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
@@ -466,6 +1172,1029 @@ otp_9229_exclude_mod(Config) ->
ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test that if a module is duplicated in a .app file, then a warning
+%% is produced, but target can still be created.
+dupl_mod_in_app_file(Config) ->
+ DataDir = ?config(data_dir,Config),
+ LibDir = filename:join(DataDir,"dupl_mod"),
+
+ %% Configure the server
+ Sys =
+ {sys,
+ [
+ {lib_dirs, [LibDir]},
+ {incl_cond,exclude},
+ {app,a,[{incl_cond,include}]},
+ {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_in_app_file"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]),
+ ?m({ok,["Module a duplicated in app file for application a."]},
+ reltool:get_status([{config, Sys}])),
+
+ %%! test that only one module installed (in spec)
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test the interface used by the GUI:
+%% get_app
+%% get_apps
+%% set_app
+%% set_apps
+%% load_config
+%% reset_config
+%%
+%% Also, for each operation which manipulates the config, test
+%% get_status and undo_config.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+get_apps(_Config) ->
+ Sys = {sys,[{app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,derived}]},
+ {app,runtime_tools,[{incl_cond,exclude}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ {ok,Sasl} = ?msym({ok,#app{name=sasl}}, reltool_server:get_app(Pid,sasl)),
+ {ok,[#app{name=kernel},
+ #app{name=sasl}=Sasl,
+ #app{name=stdlib}] = White} =
+ ?msym({ok,_}, reltool_server:get_apps(Pid,whitelist)),
+ {ok,[#app{name=runtime_tools}] = Black} =
+ ?msym({ok,_}, reltool_server:get_apps(Pid,blacklist)),
+
+ {ok,Derived} = ?msym({ok,_}, reltool_server:get_apps(Pid,derived)),
+ true = lists:keymember(tools,#app.name,Derived),
+
+ {ok,Source} = ?msym({ok,_}, reltool_server:get_apps(Pid,source)),
+ true = lists:keymember(common_test,#app.name,Source),
+
+ %% Check that the four lists are disjoint
+ Number = length(White) + length(Black) + length(Derived) + length(Source),
+ WN = lists:usort([N || #app{name=N} <- White]),
+ BN = lists:usort([N || #app{name=N} <- Black]),
+ DN = lists:usort([N || #app{name=N} <- Derived]),
+ SN = lists:usort([N || #app{name=N} <- Source]),
+ AllN = lists:umerge([WN,BN,DN,SN]),
+ ?m(Number,length(AllN)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+get_mod(_Config) ->
+ Sys = {sys,[{app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,derived}]},
+ {app,runtime_tools,[{incl_cond,exclude}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ %% Read app and get a module from the #app record
+ {ok,Tools} = ?msym({ok,#app{name=tools}}, reltool_server:get_app(Pid,tools)),
+ Cover = lists:keyfind(cover,#mod.name,Tools#app.mods),
+
+ %% get_mod - and check that it is equal to the one in #app.mods
+ ?m({ok,Cover}, reltool_server:get_mod(Pid,cover)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+get_sys(_Config) ->
+ Sys = {sys,[{app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,derived}]},
+ {app,runtime_tools,[{incl_cond,exclude}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ RootDir = code:root_dir(),
+ ?msym({ok,#sys{root_dir=RootDir,apps=undefined}},reltool_server:get_sys(Pid)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+set_app_and_undo(Config) ->
+ Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]},
+ {incl_cond, exclude},
+ {app,a,[{incl_cond,include}]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+ ?m({ok, Sys}, reltool:get_config(Pid)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Get app and mod
+ {ok,Tools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ {ok,Cover} = ?msym({ok,#mod{name=cover, is_included=true}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Exclude one module with set_app
+ ExclCover = Cover#mod{incl_cond=exclude},
+ Mods = Tools#app.mods,
+ Tools1 = Tools#app{mods = lists:keyreplace(cover,#mod.name,Mods,ExclCover)},
+ {ok,ToolsNoCover,["a: Cannot parse app file"++_|_]} =
+ ?msym({ok,_,["a: Cannot parse app file"++_|_]},
+ reltool_server:set_app(Pid,Tools1)),
+ ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)),
+
+ %% Check that the module is no longer included
+ ?m({ok,ToolsNoCover}, reltool_server:get_app(Pid,tools)),
+ {ok,NoIncludeCover} = ?msym({ok,#mod{name=cover, is_included=false}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Undo
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,Tools}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)),
+
+ %% Undo again, to check that it toggles
+ ?msym(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,ToolsNoCover}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,NoIncludeCover}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+set_apps_and_undo(Config) ->
+ Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+ ?m({ok, Sys}, reltool:get_config(Pid)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Get app and mod
+ {ok,Tools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ ?m(true, Tools#app.is_pre_included),
+ ?m(true, Tools#app.is_included),
+ {ok,Cover} = ?msym({ok,#mod{name=cover, is_included=true}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Exclude one application with set_apps
+ ExclTools = Tools#app{incl_cond=exclude},
+ ?msym({ok,["a: Cannot parse app file"++_]},
+ reltool_server:set_apps(Pid,[ExclTools])),
+ ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)),
+
+ %% Check that the app and its modules (one of them) are no longer included
+ {ok,NoTools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ ?m(false, NoTools#app.is_pre_included),
+ ?m(false, NoTools#app.is_included),
+ {ok,NoIncludeCover} = ?msym({ok,#mod{name=cover, is_included=false}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Undo
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,Tools}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Undo again, to check that it toggles
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,NoTools}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,NoIncludeCover}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test that escript can be configured, but not its inlined applications
+set_apps_inlined(Config) ->
+ %% Create archive
+ DataDir = ?config(data_dir,Config),
+ EscriptDir = filename:join(DataDir,escript),
+ {ok,{_Archive,Bin}} = zip:create("someapp-1.0.ez",["someapp-1.0"],
+ [memory,
+ {cwd,EscriptDir},
+ {compress,all},
+ {uncompress,[".beam",".app"]}]),
+
+ %% Create the escript
+ EscriptName = "someapp.escript",
+ Escript = filename:join(?WORK_DIR,EscriptName),
+ ok = escript:create(Escript,[shebang,
+ {emu_args,"-escript main mymod"},
+ {archive,Bin}]),
+ ok = file:change_mode(Escript,8#00744),
+
+ %% Configure the server
+ Sys = {sys,[{incl_cond, exclude},
+ {escript,Escript,[]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+ ?msym({ok,[]},reltool_server:get_status(Pid)),
+
+ %% Get app and mod
+ {ok,EApp} = ?msym({ok,_}, reltool_server:get_app(Pid,'*escript* someapp')),
+ {ok,Someapp} = ?msym({ok,_}, reltool_server:get_app(Pid,someapp)),
+ ?m(undefined, EApp#app.incl_cond),
+ ?m(undefined, Someapp#app.incl_cond),
+ ?m(false, Someapp#app.is_included),
+ ?m(false, Someapp#app.is_pre_included),
+
+ %% Include escript
+ EApp1 = EApp#app{incl_cond=include},
+ ?m({ok,[]}, reltool_server:set_apps(Pid,[EApp1])),
+ ExpectedEApp = EApp1#app{is_included=true,is_pre_included=true},
+ ?m({ok,ExpectedEApp}, reltool_server:get_app(Pid,'*escript* someapp')),
+ {ok,Someapp1} = ?msym({ok,_}, reltool_server:get_app(Pid,someapp)),
+ ?m(include, Someapp1#app.incl_cond),
+ ?m(true, Someapp1#app.is_included),
+ ?m(true, Someapp1#app.is_pre_included),
+
+ %% Check that inlined app can not be configured
+ Someapp2 = Someapp1#app{incl_cond=exclude},
+ ?msym({error,
+ "Application someapp is inlined in '*escript* someapp'. "
+ "Can not change configuration for an inlined application."},
+ reltool_server:set_apps(Pid,[Someapp2])),
+ ?m({ok,Someapp1}, reltool_server:get_app(Pid,someapp)),
+
+ %% Exclude escript
+ {ok,EApp2} = ?msym({ok,_}, reltool_server:get_app(Pid,'*escript* someapp')),
+ EApp3 = EApp2#app{incl_cond=exclude},
+ ?m({ok,[]}, reltool_server:set_apps(Pid,[EApp3])),
+ ExpectedEApp3 = EApp3#app{is_included=false,is_pre_included=false},
+ ?m({ok,ExpectedEApp3}, reltool_server:get_app(Pid,'*escript* someapp')),
+ {ok,Someapp3} = ?msym({ok,_}, reltool_server:get_app(Pid,someapp)),
+ ?m(exclude, Someapp3#app.incl_cond),
+ ?m(false, Someapp3#app.is_included),
+ ?m(false, Someapp3#app.is_pre_included),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+set_sys_and_undo(Config) ->
+ Sys1 = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Read sys record
+ {ok, SysRec} = reltool_server:get_sys(Pid),
+
+ %% Set lib dirs by call to set_sys
+ NewLib = filename:join(datadir(Config),"faulty_app_file"),
+ NewLibDirs = [NewLib | SysRec#sys.lib_dirs],
+ NewSysRec = SysRec#sys{lib_dirs=NewLibDirs},
+ ?msym({ok,["a: Cannot parse app file"++_]},
+ reltool_server:set_sys(Pid, NewSysRec)),
+ ?m({ok,NewSysRec}, reltool_server:get_sys(Pid)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Undo
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,SysRec}, reltool_server:get_sys(Pid)),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Undo again, to check that it toggles
+ ?m(ok,reltool_server:undo_config(Pid)),
+ ?m({ok,NewSysRec}, reltool_server:get_sys(Pid)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+load_config_and_undo(Config) ->
+ Sys1 = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])),
+ ?m({ok, Sys1}, reltool:get_config(Pid)),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Get app and mod
+ {ok,Tools1} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ ?m(true, Tools1#app.is_pre_included),
+ ?m(true, Tools1#app.is_included),
+ {ok,Cover1} = ?msym({ok,#mod{name=cover,
+ is_included=true,
+ is_pre_included=true}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Change tools from include to derived by loading new config
+ Sys2 = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]},
+ {app,a,[{incl_cond,include}]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,derived}]}]},
+ ?msym({ok,["a: Cannot parse app file"++_]},
+ reltool_server:load_config(Pid,Sys2)),
+%%% OTP-0702, 15) ?m({ok, Sys2}, reltool:get_config(Pid)),
+%%% Note that {incl_cond,exclude} is removed compared to Sys1 -
+%%% config is merged, not overwritten - is this correct???
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Check that tools is included (since it is used by sasl) but not
+ %% pre-included (neither included or excluded => undefined)
+ {ok,Tools2} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ ?m(undefined, Tools2#app.is_pre_included),
+ ?m(true, Tools2#app.is_included),
+ {ok,Cover2} = ?msym({ok,#mod{name=cover,
+ is_included=true,
+ is_pre_included=undefined}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Undo
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,Tools1}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover1}, reltool_server:get_mod(Pid,cover)),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Undo again, to check that it toggles
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,Tools2}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover2}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test that load_config is properly rolled back if it fails
+load_config_fail(_Config) ->
+ Sys1 = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])),
+ ?m({ok, Sys1}, reltool:get_config(Pid)),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Get app and mod
+ {ok,Tools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+
+ %% Try to load a config with a faulty rel statement (includes a
+ %% non-existing application)
+ Sys2 = {sys,[{incl_cond, exclude},
+ {boot_rel, "faulty_rel"},
+ {rel, "faulty_rel", "1.0", [kernel, sasl, stdlib, xxx]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]}]},
+ ?msym({error,"Release \"faulty_rel\" uses non existing application xxx"},
+ reltool_server:load_config(Pid,Sys2)),
+
+ %% Check that a rollback is done to the old configuration
+ ?m({ok, Sys1}, reltool:get_config(Pid,false,false)),
+
+ %% and that tools is not changed (i.e. that the new configuration
+ %% is not applied)
+ ?m({ok,Tools}, reltool_server:get_app(Pid,tools)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load config with escript
+
+load_config_escript_path(Config) ->
+ %% Create escript
+ DataDir = ?config(data_dir,Config),
+ BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]),
+ {ok,BeamBin} = file:read_file(BeamFile),
+ EscriptName = "mymod.escript",
+ Escript = filename:join(?WORK_DIR,EscriptName),
+ ok = escript:create(Escript,[shebang,{beam,BeamBin}]),
+ ok = file:change_mode(Escript,8#00744),
+
+ %% Start reltool_server with one escript in configuration
+ EscriptSys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, EscriptSys}])),
+ {ok,[#app{name='*escript* mymod'}=A]} =
+ ?msym({ok,[_]}, reltool_server:get_apps(Pid1,whitelist)),
+ ?m(ok, reltool:stop(Pid1)),
+
+
+ %% Do same again, but now start reltool first with simple config,
+ %% then add escript by loading new configuration and check that
+ %% #app is the same
+ SimpleSys =
+ {sys,
+ [
+ {lib_dirs, []}
+ ]},
+
+ {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, SimpleSys}])),
+ ?m({ok,[]}, reltool_server:get_apps(Pid2,whitelist)),
+ ?m({ok,[]}, reltool_server:load_config(Pid2,EscriptSys)),
+ ?m({ok,[A]}, reltool_server:get_apps(Pid2,whitelist)),
+
+ ?m(ok, reltool:stop(Pid2)),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load config with same (source) escript twice and check that the
+%% application information is not changed.
+
+load_config_same_escript_source(_Config) ->
+ %% Create escript
+ ExDir = code:lib_dir(reltool, examples),
+ EscriptName = "display_args",
+ Escript = filename:join([ExDir, EscriptName]),
+
+ %% Start reltool_server with one escript in configuration
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+% {ok,[#app{name='*escript* display_args'}]} =
+ ?msym({ok,[#app{name='*escript* display_args',mods=[_]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+
+ %% Load the same config again, then check that app is not changed
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys)),
+ ?msym({ok,[#app{name='*escript* display_args',mods=[_]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+
+ ?m(ok, reltool:stop(Pid)),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load config with same (beam) escript twice and check that the
+%% application information is not changed.
+
+load_config_same_escript_beam(Config) ->
+ %% Create escript
+ DataDir = ?config(data_dir,Config),
+ BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]),
+ {ok,BeamBin} = file:read_file(BeamFile),
+ EscriptName = "mymod.escript",
+ Escript = filename:join(?WORK_DIR,EscriptName),
+ ok = escript:create(Escript,[shebang,{beam,BeamBin}]),
+ ok = file:change_mode(Escript,8#00744),
+
+ %% Start reltool_server with one escript in configuration
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+ {ok,[#app{name='*escript* mymod'}=A]} =
+ ?msym({ok,[_]}, reltool_server:get_apps(Pid,whitelist)),
+
+ %% Load the same config again, then check that app is not changed
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys)),
+ ?m({ok,[A]}, reltool_server:get_apps(Pid,whitelist)),
+
+ ?m(ok, reltool:stop(Pid)),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load config with escript
+
+load_config_add_escript(Config) ->
+ %% First escript
+ ExDir = code:lib_dir(reltool, examples),
+ EscriptName1 = "display_args",
+ Escript1 = filename:join([ExDir, EscriptName1]),
+
+ %% Second escript
+ DataDir = ?config(data_dir,Config),
+ BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]),
+ {ok,BeamBin} = file:read_file(BeamFile),
+ EscriptName2 = "mymod.escript",
+ Escript2 = filename:join(?WORK_DIR,EscriptName2),
+ ok = escript:create(Escript2,[shebang,{beam,BeamBin}]),
+ ok = file:change_mode(Escript2,8#00744),
+
+ %% Start reltool_server with one escript in configuration
+ Sys1 =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript2, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])),
+
+ %% Add second escript by loading new configuration
+ Sys2 =
+ {sys,
+ [
+ {lib_dirs, []},
+ {escript, Escript1, [{incl_cond, include}]},
+ {escript, Escript2, [{incl_cond, include}]},
+ {profile, standalone}
+ ]},
+
+ {ok,[]} = ?m({ok,[]}, reltool_server:load_config(Pid,Sys2)),
+ {ok,[#app{name='*escript* display_args'},
+ #app{name='*escript* mymod'}]} =
+ ?msym({ok,[_,_]}, reltool_server:get_apps(Pid,whitelist)),
+
+ ?m(ok, reltool:stop(Pid)),
+
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+reset_config_and_undo(Config) ->
+ Sys1 = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]},
+ {incl_cond, exclude},
+ {app,a,[{incl_cond,include}]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])),
+ ?m({ok, Sys1}, reltool:get_config(Pid)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Get app and mod
+ {ok,Tools1} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ ?m(true, Tools1#app.is_pre_included),
+ ?m(true, Tools1#app.is_included),
+ {ok,Cover1} = ?msym({ok,#mod{name=cover,
+ is_included=true,
+ is_pre_included=true}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Exclude tools by loading new config
+ Sys2 = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,tools,[{incl_cond,exclude}]}]},
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys2)),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Check that tools is excluded
+ {ok,Tools2} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)),
+ ?m(false, Tools2#app.is_pre_included),
+ ?m(false, Tools2#app.is_included),
+ {ok,Cover2} = ?msym({ok,#mod{name=cover,
+ is_included=false,
+ is_pre_included=false}},
+ reltool_server:get_mod(Pid,cover)),
+
+ %% Reset
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:reset_config(Pid)),
+ ?m({ok,Tools1}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover1}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ %% Undo
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,Tools2}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover2}, reltool_server:get_mod(Pid,cover)),
+ ?m({ok,[]}, reltool_server:get_status(Pid)),
+
+ %% Undo again, to check that it toggles
+ ?m(ok, reltool_server:undo_config(Pid)),
+ ?m({ok,Tools1}, reltool_server:get_app(Pid,tools)),
+ ?m({ok,Cover1}, reltool_server:get_mod(Pid,cover)),
+ ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+gen_rel_files(_Config) ->
+ %% Configure the server
+ RelName = "gen_fel_files_test",
+ RelVsn = "1.0",
+ Sys =
+ {sys,
+ [
+ {lib_dirs, []},
+ {boot_rel, RelName},
+ {rel, RelName, RelVsn, [kernel, stdlib]}
+ ]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ %% Generate .rel, .script and .boot
+ Dir = filename:join(?WORK_DIR,"gen_rel_files"),
+ ok = file:make_dir(Dir),
+ ?m({ok,[]}, reltool_server:gen_rel_files(Pid,Dir)),
+
+ Script = RelName ++ ".script",
+ Rel = RelName ++ ".rel",
+ Boot = RelName ++ ".boot",
+ {ok,Files} = ?msym({ok,_}, file:list_dir(Dir)),
+ [Boot,Rel,Script] = lists:sort(Files),
+
+ %% Check that contents is reasonable
+ {ok,[S]} = ?msym({ok,[{script,_,_}]},file:consult(filename:join(Dir,Script))),
+ ?msym({ok,[{release,_,_,_}]}, file:consult(filename:join(Dir,Rel))),
+ {ok,Bin} = ?msym({ok,_}, file:read_file(filename:join(Dir,Boot))),
+ ?m(S,binary_to_term(Bin)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+save_config(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Sys = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+ ?m({ok, Sys}, reltool:get_config(Pid)),
+
+ Simple = filename:join(PrivDir,"save_simple.reltool"),
+ ?m(ok, reltool_server:save_config(Pid,Simple,false,false)),
+ ?m({ok,[Sys]}, file:consult(Simple)),
+
+ Derivates = filename:join(PrivDir,"save_derivates.reltool"),
+ ?m(ok, reltool_server:save_config(Pid,Derivates,false,true)),
+ ?msym({ok,[{sys,[{incl_cond, exclude},
+ {erts,[]},
+ {app,kernel,[{incl_cond,include},{mod,_,[]}|_]},
+ {app,sasl,[{incl_cond,include},{mod,_,[]}|_]},
+ {app,stdlib,[{incl_cond,include},{mod,_,[]}|_]}]}]},
+ file:consult(Derivates)),
+
+ Defaults = filename:join(PrivDir,"save_defaults.reltool"),
+ ?m(ok, reltool_server:save_config(Pid,Defaults,true,false)),
+ ?msym({ok,[{sys,[{root_dir,_},
+ {lib_dirs,_},
+ {mod_cond,all},
+ {incl_cond,exclude},
+ {app,kernel,[{incl_cond,include},{vsn,undefined},
+ {lib_dir,undefined}]},
+ {app,sasl,[{incl_cond,include},{vsn,undefined},
+ {lib_dir,undefined}]},
+ {app,stdlib,[{incl_cond,include},{vsn,undefined},
+ {lib_dir,undefined}]},
+ {boot_rel,"start_clean"},
+ {rel,"start_clean","1.0",[]},
+ {rel,"start_sasl","1.0",[sasl]},
+ {emu_name,"beam"},
+ {relocatable,true},
+ {profile,development},
+ {incl_sys_filters,[".*"]},
+ {excl_sys_filters,[]},
+ {incl_app_filters,[".*"]},
+ {excl_app_filters,[]},
+ {incl_archive_filters,[".*"]},
+ {excl_archive_filters,["^include$","^priv$"]},
+ {archive_opts,[]},
+ {rel_app_type,permanent},
+ {app_file,keep},
+ {debug_info,keep}]}]},
+ file:consult(Defaults)),
+
+ KVsn = latest(kernel),
+ StdVsn = latest(stdlib),
+ SaslVsn = latest(sasl),
+
+ LibDir = code:lib_dir(),
+ KLibDir = filename:join(LibDir,"kernel-"++KVsn),
+ StdLibDir = filename:join(LibDir,"stdlib-"++StdVsn),
+ SaslLibDir = filename:join(LibDir,"sasl-"++SaslVsn),
+
+ All = filename:join(PrivDir,"save_all.reltool"),
+ ?m(ok, reltool_server:save_config(Pid,All,true,true)),
+ ?msym({ok,[{sys,[{root_dir,_},
+ {lib_dirs,_},
+ {mod_cond,all},
+ {incl_cond,exclude},
+ {erts,[]},
+ {app,kernel,[{incl_cond,include},{vsn,KVsn},
+ {lib_dir,KLibDir},{mod,_,[]}|_]},
+ {app,sasl,[{incl_cond,include},{vsn,SaslVsn},
+ {lib_dir,SaslLibDir},{mod,_,[]}|_]},
+ {app,stdlib,[{incl_cond,include},{vsn,StdVsn},
+ {lib_dir,StdLibDir},{mod,_,[]}|_]},
+ {boot_rel,"start_clean"},
+ {rel,"start_clean","1.0",[]},
+ {rel,"start_sasl","1.0",[sasl]},
+ {emu_name,"beam"},
+ {relocatable,true},
+ {profile,development},
+ {incl_sys_filters,[".*"]},
+ {excl_sys_filters,[]},
+ {incl_app_filters,[".*"]},
+ {excl_app_filters,[]},
+ {incl_archive_filters,[".*"]},
+ {excl_archive_filters,["^include$","^priv$"]},
+ {archive_opts,[]},
+ {rel_app_type,permanent},
+ {app_file,keep},
+ {debug_info,keep}]}]},
+ file:consult(All)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test calculation of dependencies
+%% The following test applications are used
+%%
+%% x-1.0: x1.erl x2.erl x3.erl
+%% \ / (x2 calls y1, x3 calls y2)
+%% y-1.0: y1.erl y2.erl
+%% \ (y1 calls z1)
+%% z-1.0 z1.erl
+%%
+%% Test includes x and derives y and z.
+%%
+dependencies(Config) ->
+ %% Default: all modules included => y and z are included (derived)
+ Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include}]},
+ {app,y,[{incl_cond,derived}]},
+ {app,z,[{incl_cond,derived}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ ?msym({ok,[#app{name=kernel},
+ #app{name=sasl},
+ #app{name=stdlib},
+ #app{name=x,uses_apps=[y]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+ {ok, Der} = ?msym({ok,_},
+ reltool_server:get_apps(Pid,derived)),
+ ?msym([#app{name=y,uses_apps=[z]},
+ #app{name=z}],
+ rm_missing_app(Der)),
+ ?msym({ok,[]},
+ reltool_server:get_apps(Pid,source)),
+
+ %% Excluding x2 => y still included since y2 is used by x3
+ %% z still included since z1 is used by y1
+ Sys2 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include},{mod,x2,[{incl_cond,exclude}]}]},
+ {app,y,[{incl_cond,derived}]},
+ {app,z,[{incl_cond,derived}]}]},
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys2)),
+ ?msym({ok,[#app{name=kernel},
+ #app{name=sasl},
+ #app{name=stdlib},
+ #app{name=x,uses_apps=[y]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+ {ok, Der2} = ?msym({ok,_},
+ reltool_server:get_apps(Pid,derived)),
+ ?msym([#app{name=y,uses_apps=[z]},
+ #app{name=z}],
+ rm_missing_app(Der2)),
+ ?msym({ok,[]},
+ reltool_server:get_apps(Pid,source)),
+
+ %% Excluding x3 => y still included since y1 is used by x2
+ %% z still included since z1 is used by y1
+ Sys3 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include},{mod,x3,[{incl_cond,exclude}]}]},
+ {app,y,[{incl_cond,derived}]},
+ {app,z,[{incl_cond,derived}]}]},
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys3)),
+ ?msym({ok,[#app{name=kernel},
+ #app{name=sasl},
+ #app{name=stdlib},
+ #app{name=x,uses_apps=[y]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+ {ok, Der3} = ?msym({ok,_},
+ reltool_server:get_apps(Pid,derived)),
+ ?msym([#app{name=y,uses_apps=[z]},
+ #app{name=z}],
+ rm_missing_app(Der3)),
+ ?msym({ok,[]},
+ reltool_server:get_apps(Pid,source)),
+
+ %% Excluding x2 and x3 => y and z excluded
+ Sys4 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include},
+ {mod,x2,[{incl_cond,exclude}]},
+ {mod,x3,[{incl_cond,exclude}]}]},
+ {app,y,[{incl_cond,derived}]},
+ {app,z,[{incl_cond,derived}]}]},
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys4)),
+ ?msym({ok,[#app{name=kernel},
+ #app{name=sasl},
+ #app{name=stdlib},
+ #app{name=x,uses_apps=[]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+ {ok, Der4} = ?msym({ok,_},
+ reltool_server:get_apps(Pid,derived)),
+ ?msym([], rm_missing_app(Der4)),
+ ?msym({ok,[#app{name=y},
+ #app{name=z}]},
+ reltool_server:get_apps(Pid,source)),
+
+ %% Excluding y1 => y still included since y2 is used by x3
+ %% z excluded since not used by any other than y1
+ Sys5 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,x,[{incl_cond,include}]},
+ {app,y,[{incl_cond,derived},
+ {mod,y1,[{incl_cond,exclude}]}]},
+ {app,z,[{incl_cond,derived}]}]},
+ ?m({ok,[]}, reltool_server:load_config(Pid,Sys5)),
+ ?msym({ok,[#app{name=kernel},
+ #app{name=sasl},
+ #app{name=stdlib},
+ #app{name=x,uses_apps=[y]}]},
+ reltool_server:get_apps(Pid,whitelist)),
+ {ok, Der5} = ?msym({ok,_},
+ reltool_server:get_apps(Pid,derived)),
+ ?msym([#app{name=y,uses_apps=[]}], rm_missing_app(Der5)),
+ ?msym({ok,[#app{name=z}]},
+ reltool_server:get_apps(Pid,source)),
+
+ ?m(ok, reltool:stop(Pid)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+use_selected_vsn(Config) ->
+ LibDir1 = filename:join(datadir(Config),"use_selected_vsn"),
+ B1Dir = filename:join(LibDir1,"b-1.0"),
+ B3Dir = filename:join(LibDir1,"b-3.0"),
+
+ LibDir2 = filename:join(LibDir1,"lib2"),
+ B2Dir = filename:join(LibDir2,"b-2.0"),
+
+ %%-----------------------------------------------------------------
+ %% Pre-selected vsn of app b
+ Sys1 = {sys,[{lib_dirs,[LibDir1]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,b,[{incl_cond,include},{vsn,"1.0"}]}]},
+ {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])),
+ {ok,B11} = ?msym({ok,#app{vsn="1.0",active_dir=B1Dir}},
+ reltool_server:get_app(Pid1,b)),
+
+ %% Change from a pre-selected vsn to use a specific dir
+ ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []},
+ reltool_server:set_app(Pid1,
+ B11#app{active_dir = B3Dir,
+ use_selected_vsn = dir,
+ label = undefined,
+ vsn = undefined,
+ info = undefined})),
+ ?m(ok, reltool:stop(Pid1)),
+
+
+ %%-----------------------------------------------------------------
+ %% Pre-selected vsn of app b
+ Sys2 = {sys,[{lib_dirs,[LibDir1]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,b,[{incl_cond,include},{vsn,"1.0"}]}]},
+ {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, Sys2}])),
+ {ok,B21} = ?msym({ok,#app{vsn="1.0",active_dir=B1Dir}},
+ reltool_server:get_app(Pid2,b)),
+
+ %% Change from a pre-selected vsn to use latest
+ ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []},
+ reltool_server:set_app(Pid2,
+ B21#app{use_selected_vsn=undefined,
+ label = undefined,
+ vsn = undefined,
+ info = undefined})),
+ ?m(ok, reltool:stop(Pid2)),
+
+
+ %%-----------------------------------------------------------------
+ %% Pre-selected directory for app b
+ Sys3 = {sys,[{lib_dirs,[LibDir1]},
+ {incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,b,[{incl_cond,include},{lib_dir,B2Dir}]}]},
+ {ok, Pid3} = ?msym({ok, _}, reltool:start_server([{config, Sys3}])),
+% test_server:break("Pid3 = list_to_pid(\""++pid_to_list(Pid3)++"\")."),
+ {ok,B31} = ?msym({ok,#app{vsn="2.0",active_dir=B2Dir}},
+ reltool_server:get_app(Pid3,b)),
+ %% Change from a pre-selected dir to use latest
+ {ok,B32,_} = ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []},
+ reltool_server:set_app(Pid3,
+ B31#app{use_selected_vsn=undefined,
+ label = undefined,
+ vsn = undefined,
+ info = undefined})),
+ %% Change back to use selected dir
+ {ok,B33,_} = ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []},
+ reltool_server:set_app(Pid3,
+ B32#app{use_selected_vsn = dir})),
+ %% use dir 1
+ {ok,B34,_} = ?msym({ok, #app{vsn ="1.0", active_dir = B1Dir}, []},
+ reltool_server:set_app(Pid3,
+ B33#app{active_dir = B1Dir,
+ label = undefined,
+ vsn = undefined,
+ info = undefined})),
+ %% use dir 2
+ {ok,B35,_} = ?msym({ok, #app{vsn ="2.0", active_dir = B2Dir}, []},
+ reltool_server:set_app(Pid3,
+ B34#app{active_dir = B2Dir,
+ label = undefined,
+ vsn = undefined,
+ info = undefined})),
+ %% use dir 3
+ ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []},
+ reltool_server:set_app(Pid3,
+ B35#app{active_dir = B3Dir,
+ label = undefined,
+ vsn = undefined,
+ info = undefined})),
+ ?m(ok, reltool:stop(Pid3)),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+use_selected_vsn_relative_path(Config) ->
+ LibDir = filename:join([datadir(Config),"use_selected_vsn","b-1.0"]),
+ RelDir = filename:join(LibDir,"rel"),
+
+ {ok,Cwd} = file:get_cwd(),
+ ok = file:set_cwd(RelDir),
+
+ Sys = {sys,[{incl_cond, exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,b,[{incl_cond,include},{lib_dir,".."}]}]},
+ {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])),
+
+ ?msym({ok,#app{vsn="1.0",active_dir=LibDir}},reltool_server:get_app(Pid,b)),
+
+ ?m(ok, reltool:stop(Pid)),
+
+ ok = file:set_cwd(Cwd),
+ ok.
@@ -478,6 +2207,20 @@ erl_libs() ->
LibStr -> string:tokens(LibStr, ":;")
end.
+datadir(Config) ->
+ %% Removes the trailing slash...
+ filename:nativename(?config(data_dir,Config)).
+
+latest(App) ->
+ AppStr = atom_to_list(App),
+ AppDirs = filelib:wildcard(filename:join(code:lib_dir(),AppStr++"-*")),
+ [LatestAppDir|_] = lists:reverse(AppDirs),
+ [_,Vsn] = string:tokens(filename:basename(LatestAppDir),"-"),
+ Vsn.
+
+rm_missing_app(Apps) ->
+ lists:keydelete(?MISSING_APP_NAME,#app.name,Apps).
+
diff_script(Script, Script) ->
equal;
diff_script({script, Rel, Commands1}, {script, Rel, Commands2}) ->
@@ -534,8 +2277,10 @@ mod_path(Node,Mod) ->
%% Node handling
start_node(Name, ErlPath) ->
+ start_node(Name, ErlPath, []).
+start_node(Name, ErlPath, Args) ->
FullName = full_node_name(Name),
- CmdLine = mk_node_cmdline(Name, ErlPath),
+ CmdLine = mk_node_cmdline(Name, ErlPath, Args),
io:format("Starting node ~p: ~s~n", [FullName, CmdLine]),
case open_port({spawn, CmdLine}, []) of
Port when is_port(Port) ->
@@ -554,14 +2299,7 @@ stop_node(Node) ->
spawn(Node, fun () -> halt() end),
receive {nodedown, Node} -> ok end.
-mk_node_cmdline(Name) ->
- Prog = case catch init:get_argument(progname) of
- {ok,[[P]]} -> P;
- _ -> exit(no_progname_argument_found)
- end,
- mk_node_cmdline(Name, Prog).
-
-mk_node_cmdline(Name, Prog) ->
+mk_node_cmdline(Name, Prog, Args) ->
Static = "-detached -noinput",
Pa = filename:dirname(code:which(?MODULE)),
NameSw = case net_kernel:longnames() of
@@ -576,7 +2314,8 @@ mk_node_cmdline(Name, Prog) ->
++ NameSw ++ " " ++ NameStr ++ " "
++ "-pa " ++ Pa ++ " "
++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr ++ " "
- ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
+ ++ "-setcookie " ++ atom_to_list(erlang:get_cookie())
+ ++ " " ++ Args.
full_node_name(PreName) ->
HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end,
@@ -610,14 +2349,16 @@ wait_for_process(Node, Name, N) when is_integer(N), N > 0 ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Run escript
-run(Dir, Cmd0) ->
+run(Dir, Script, Args) ->
+ Cmd0 = filename:rootname(Script) ++ " " ++ Args,
Cmd = case os:type() of
{win32,_} -> filename:nativename(Dir) ++ "\\" ++ Cmd0;
_ -> Cmd0
end,
do_run(Dir, Cmd).
-run(Dir, Opts, Cmd0) ->
+run(Dir, Opts, Script, Args) ->
+ Cmd0 = filename:rootname(Script) ++ " " ++ Args,
Cmd = case os:type() of
{win32,_} -> Opts ++ " " ++ filename:nativename(Dir) ++ "\\" ++ Cmd0;
_ -> Opts ++ " " ++ Dir ++ "/" ++ Cmd0
@@ -626,7 +2367,9 @@ run(Dir, Opts, Cmd0) ->
do_run(Dir, Cmd) ->
io:format("Run: ~p\n", [Cmd]),
- Env = [{"PATH",Dir++":"++os:getenv("PATH")}],
+ Env = [{"PATH",Dir++":"++os:getenv("PATH")},
+ {"ERL_FLAGS",""}, % Make sure no flags are set that can override
+ {"ERL_ZFLAGS",""}], % any of the flags set in the escript.
Port = open_port({spawn,Cmd}, [exit_status,eof,in,{env,Env}]),
Res = get_data(Port, []),
receive
diff --git a/lib/reltool/test/reltool_server_SUITE_data/Makefile.src b/lib/reltool/test/reltool_server_SUITE_data/Makefile.src
index 049e8dd6cc..02846f42b6 100644
--- a/lib/reltool/test/reltool_server_SUITE_data/Makefile.src
+++ b/lib/reltool/test/reltool_server_SUITE_data/Makefile.src
@@ -6,8 +6,27 @@ OTP9229= \
otp_9229/y-1.0/ebin/y.@EMULATOR@ \
otp_9229/y-1.0/ebin/mylib.@EMULATOR@
+DEPENDENCIES= \
+ dependencies/x-1.0/ebin/x1.@EMULATOR@ \
+ dependencies/x-1.0/ebin/x2.@EMULATOR@ \
+ dependencies/x-1.0/ebin/x3.@EMULATOR@ \
+ dependencies/y-1.0/ebin/y1.@EMULATOR@ \
+ dependencies/y-1.0/ebin/y2.@EMULATOR@ \
+ dependencies/z-1.0/ebin/z1.@EMULATOR@
-all: $(OTP9229)
+ESCRIPT= \
+ escript/someapp-1.0/ebin/mymod.@EMULATOR@
+
+SEL_VSN= \
+ use_selected_vsn/b-1.0/ebin/b.@EMULATOR@ \
+ use_selected_vsn/b-3.0/ebin/b.@EMULATOR@ \
+ use_selected_vsn/lib2/b-2.0/ebin/b.@EMULATOR@
+
+SLIM= \
+ slim/a-1.0/ebin/a_sup.@EMULATOR@ \
+ slim/a-1.0/ebin/a.@EMULATOR@
+
+all: $(OTP9229) $(DEPENDENCIES) $(ESCRIPT) $(SEL_VSN) $(SLIM)
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
@@ -17,3 +36,31 @@ 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
+
+dependencies/x-1.0/ebin/x1.@EMULATOR@: dependencies/x-1.0/src/x1.erl
+ erlc $(EFLAGS) -odependencies/x-1.0/ebin dependencies/x-1.0/src/x1.erl
+dependencies/x-1.0/ebin/x2.@EMULATOR@: dependencies/x-1.0/src/x2.erl
+ erlc $(EFLAGS) -odependencies/x-1.0/ebin dependencies/x-1.0/src/x2.erl
+dependencies/x-1.0/ebin/x3.@EMULATOR@: dependencies/x-1.0/src/x3.erl
+ erlc $(EFLAGS) -odependencies/x-1.0/ebin dependencies/x-1.0/src/x3.erl
+dependencies/y-1.0/ebin/y1.@EMULATOR@: dependencies/y-1.0/src/y1.erl
+ erlc $(EFLAGS) -odependencies/y-1.0/ebin dependencies/y-1.0/src/y1.erl
+dependencies/y-1.0/ebin/y2.@EMULATOR@: dependencies/y-1.0/src/y2.erl
+ erlc $(EFLAGS) -odependencies/y-1.0/ebin dependencies/y-1.0/src/y2.erl
+dependencies/z-1.0/ebin/z1.@EMULATOR@: dependencies/z-1.0/src/z1.erl
+ erlc $(EFLAGS) -odependencies/z-1.0/ebin dependencies/z-1.0/src/z1.erl
+
+escript/someapp-1.0/ebin/mymod.@EMULATOR@: escript/someapp-1.0/src/mymod.erl
+ erlc $(EFLAGS) -oescript/someapp-1.0/ebin escript/someapp-1.0/src/mymod.erl
+
+use_selected_vsn/b-1.0/ebin/b.@EMULATOR@: use_selected_vsn/b-1.0/src/b.erl
+ erlc $(EFLAGS) -ouse_selected_vsn/b-1.0/ebin use_selected_vsn/b-1.0/src/b.erl
+use_selected_vsn/b-3.0/ebin/b.@EMULATOR@: use_selected_vsn/b-3.0/src/b.erl
+ erlc $(EFLAGS) -ouse_selected_vsn/b-3.0/ebin use_selected_vsn/b-3.0/src/b.erl
+use_selected_vsn/lib2/b-2.0/ebin/b.@EMULATOR@: use_selected_vsn/lib2/b-2.0/src/b.erl
+ erlc $(EFLAGS) -ouse_selected_vsn/lib2/b-2.0/ebin use_selected_vsn/lib2/b-2.0/src/b.erl
+
+slim/a-1.0/ebin/a_sup.@EMULATOR@: slim/a-1.0/src/a_sup.erl
+ erlc $(EFLAGS) -oslim/a-1.0/ebin slim/a-1.0/src/a_sup.erl
+slim/a-1.0/ebin/a.@EMULATOR@: slim/a-1.0/src/a.erl
+ erlc $(EFLAGS) -oslim/a-1.0/ebin slim/a-1.0/src/a.erl
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/ebin/x.app b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/ebin/x.app
new file mode 100644
index 0000000000..ccaab8a8c7
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/ebin/x.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, x,
+ [{description, "Main application in reltool dependency test"},
+ {vsn, "1.0"},
+ {modules, [x1,x2,x3]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x1.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x1.erl
new file mode 100644
index 0000000000..bf1e7f9279
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x1.erl
@@ -0,0 +1,5 @@
+-module(x1).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x2.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x2.erl
new file mode 100644
index 0000000000..82191ba278
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x2.erl
@@ -0,0 +1,5 @@
+-module(x2).
+-compile(export_all).
+
+f() ->
+ y1:f().
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x3.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x3.erl
new file mode 100644
index 0000000000..618c75c9a7
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/x-1.0/src/x3.erl
@@ -0,0 +1,5 @@
+-module(x3).
+-compile(export_all).
+
+f() ->
+ y2:f().
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app
new file mode 100644
index 0000000000..d9dac371d7
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, y,
+ [{description, "Library application in reltool dependency test"},
+ {vsn, "1.0"},
+ {modules, [y1,y2]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y1.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y1.erl
new file mode 100644
index 0000000000..dd21b33292
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y1.erl
@@ -0,0 +1,5 @@
+-module(y1).
+-compile(export_all).
+
+f() ->
+ z1:f().
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y2.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y2.erl
new file mode 100644
index 0000000000..bf8ddf6080
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y2.erl
@@ -0,0 +1,5 @@
+-module(y2).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/ebin/z.app b/lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/ebin/z.app
new file mode 100644
index 0000000000..437a0968e9
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/ebin/z.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, z,
+ [{description, "Library application in reltool dependency test"},
+ {vsn, "1.0"},
+ {modules, [z1]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/src/z1.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/src/z1.erl
new file mode 100644
index 0000000000..97ef90b87f
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/z-1.0/src/z1.erl
@@ -0,0 +1,5 @@
+-module(z1).
+-compile(export_all).
+
+f() ->
+ ok.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/dupl_mod/a-1.0/ebin/a.app b/lib/reltool/test/reltool_server_SUITE_data/dupl_mod/a-1.0/ebin/a.app
new file mode 100644
index 0000000000..fada34847a
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/dupl_mod/a-1.0/ebin/a.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, a,
+ [{description, "Application with duplicated module name in .app file"},
+ {vsn, "1.0"},
+ {modules, [a,a]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/ebin/someapp.app b/lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/ebin/someapp.app
new file mode 100644
index 0000000000..ea2209941e
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/ebin/someapp.app
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{application, someapp,
+ [{description, "Some app for reltool test including archives in escripts"},
+ {vsn, "1.0"},
+ {modules, [someapp]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/src/mymod.erl b/lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/src/mymod.erl
new file mode 100644
index 0000000000..b6c71c666d
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/escript/someapp-1.0/src/mymod.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(mymod).
+
+-export([main/1]).
+
+%%%-----------------------------------------------------------------
+%%% escript main function
+main(Args) ->
+ io:format("Root dir: ~s\n", [code:root_dir()]),
+ io:format("Script args: ~p\n", [Args]).
diff --git a/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/ebin/a.app b/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/ebin/a.app
new file mode 100644
index 0000000000..ea77103598
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/ebin/a.app
@@ -0,0 +1 @@
+faulty app file
diff --git a/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/src/a.erl b/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/src/a.erl
new file mode 100644
index 0000000000..bb500bed69
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/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/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/src/a_sup.erl b/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/a-1.0/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/faulty_app_file/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/reltool/test/reltool_server_SUITE_data/slim/a-1.0/ebin/a.app b/lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/ebin/a.app
new file mode 100644
index 0000000000..3160e00da7
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/ebin/a.app
@@ -0,0 +1,7 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [a, a_sup]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/src/a.erl b/lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/src/a.erl
new file mode 100644
index 0000000000..bb500bed69
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/slim/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/reltool/test/reltool_server_SUITE_data/slim/a-1.0/src/a_sup.erl b/lib/reltool/test/reltool_server_SUITE_data/slim/a-1.0/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/slim/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/reltool/test/reltool_server_SUITE_data/sort_apps/x-1.0/ebin/x.app b/lib/reltool/test/reltool_server_SUITE_data/sort_apps/x-1.0/ebin/x.app
new file mode 100644
index 0000000000..5fa2a92969
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/sort_apps/x-1.0/ebin/x.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, x,
+ [{description, "Application in reltool sort app test - circular dependency"},
+ {vsn, "1.0"},
+ {modules,[]},
+ {registered, []},
+ {applications, [kernel, stdlib, y]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/sort_apps/y-1.0/ebin/y.app b/lib/reltool/test/reltool_server_SUITE_data/sort_apps/y-1.0/ebin/y.app
new file mode 100644
index 0000000000..c4bc62f55f
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/sort_apps/y-1.0/ebin/y.app
@@ -0,0 +1,7 @@
+% -*-erlang-*-
+{application, y,
+ [{description, "Application in reltool sort app test - circular dependency"},
+ {vsn, "1.0"},
+ {modules,[]},
+ {registered, []},
+ {applications, [kernel, stdlib, x]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/sort_apps/z-1.0/ebin/z.app b/lib/reltool/test/reltool_server_SUITE_data/sort_apps/z-1.0/ebin/z.app
new file mode 100644
index 0000000000..8608bc554b
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/sort_apps/z-1.0/ebin/z.app
@@ -0,0 +1,8 @@
+% -*-erlang-*-
+{application, z,
+ [{description, "Application in reltool sort app test - included applications"},
+ {vsn, "1.0"},
+ {modules,[]},
+ {registered, []},
+ {applications, [kernel, stdlib, sasl, inets]},
+ {included_applications, [tools, mnesia]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/ebin/b.app b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/ebin/b.app
new file mode 100644
index 0000000000..c511dcc8f1
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/ebin/b.app
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "Reltool test app for using selected version of app"},
+ {vsn, "1.0"},
+ {modules, [b]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/rel/.gitignore b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/rel/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/rel/.gitignore
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/src/b.erl b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/src/b.erl
new file mode 100644
index 0000000000..a6b4ff1c05
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-1.0/src/b.erl
@@ -0,0 +1,4 @@
+-module(b).
+-compile(export_all).
+
+foo() -> ok.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/ebin/b.app b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/ebin/b.app
new file mode 100644
index 0000000000..9ed7695a40
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/ebin/b.app
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "Reltool test app for using selected version of app"},
+ {vsn, "3.0"},
+ {modules, [b]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/src/b.erl b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/src/b.erl
new file mode 100644
index 0000000000..a6b4ff1c05
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/b-3.0/src/b.erl
@@ -0,0 +1,4 @@
+-module(b).
+-compile(export_all).
+
+foo() -> ok.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/ebin/b.app b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/ebin/b.app
new file mode 100644
index 0000000000..33c633d635
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/ebin/b.app
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "Reltool test app for using selected version of app"},
+ {vsn, "2.0"},
+ {modules, [b]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/src/b.erl b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/src/b.erl
new file mode 100644
index 0000000000..a6b4ff1c05
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/use_selected_vsn/lib2/b-2.0/src/b.erl
@@ -0,0 +1,4 @@
+-module(b).
+-compile(export_all).
+
+foo() -> ok.
diff --git a/lib/reltool/test/reltool_test_lib.erl b/lib/reltool/test/reltool_test_lib.erl
index b8bcbcd009..61f783190c 100644
--- a/lib/reltool/test/reltool_test_lib.erl
+++ b/lib/reltool/test/reltool_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -138,10 +138,6 @@ end_per_testcase(_Func, Config) when is_list(Config) ->
reset_kill_timer(Config),
Config.
-%% Backwards compatible with test_server
-tc_info(suite) -> [];
-tc_info(doc) -> "".
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Use ?log(Format, Args) as wrapper
diff --git a/lib/reltool/test/reltool_test_lib.hrl b/lib/reltool/test/reltool_test_lib.hrl
index b592ebb2f0..0dfc08b81c 100644
--- a/lib/reltool/test/reltool_test_lib.hrl
+++ b/lib/reltool/test/reltool_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,20 +18,10 @@
-include_lib("wx/include/wx.hrl").
--define(flat_format(Format,Args), lists:flatten(io_lib:format(Format,Args))).
-define(log(Format,Args), reltool_test_lib:log(Format,Args,?FILE,?LINE)).
--define(warning(Format,Args), ?log("<WARNING>\n " ++ Format,Args)).
-define(error(Format,Args), reltool_test_lib:error(Format,Args,?FILE,?LINE)).
-define(verbose(Format,Args), reltool_test_lib:verbose(Format,Args,?FILE,?LINE)).
--define(fatal(Format,Args),
- ?error(Format, Args),
- exit({test_case_fatal, Format, Args, ?FILE, ?LINE})).
-
--define(skip(Format,Args),
- ?warning(Format, Args),
- exit({skipped, ?flat_format(Format, Args)})).
-
-define(ignore(Expr),
fun() ->
AcTuAlReS = (catch (Expr)),
@@ -68,25 +58,3 @@
AcTuAlReS
end
end()).
-
--define(m_receive(ExpectedMsg),
- ?m(ExpectedMsg,reltool_test_lib:pick_msg())).
-
--define(m_multi_receive(ExpectedMsgs),
- fun() ->
- TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs),
- AcTuAlReS =
- lists:sort(lists:map(fun(_) ->
- reltool_test_lib:pick_msg()
- end, TmPeXpCtEdMsGs)),
- case AcTuAlReS of
- TmPeXpCtEdMsGs ->
- ?verbose("ok: ~p\n",[AcTuAlReS]),
- AcTuAlReS;
- _ ->
- reltool_test_lib:error("Not matching actual result was:\n ~p \nExpected ~p\n",
- [AcTuAlReS, ExpectedMsgs],
- ?FILE, ?LINE),
- AcTuAlReS
- end
- end()).
diff --git a/lib/reltool/test/reltool_wx_SUITE.erl b/lib/reltool/test/reltool_wx_SUITE.erl
index 424bc7d189..13d71f4fd6 100644
--- a/lib/reltool/test/reltool_wx_SUITE.erl
+++ b/lib/reltool/test/reltool_wx_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,9 +61,46 @@ start_all_windows(TestInfo) when is_atom(TestInfo) ->
reltool_test_lib:tc_info(TestInfo);
start_all_windows(_Config) ->
{ok, SysPid} = ?msym({ok, _}, reltool:start([{trap_exit, false}])),
+ erlang:monitor(process,SysPid),
{ok, AppPid} = ?msym({ok, _}, reltool_sys_win:open_app(SysPid, stdlib)),
- ?msym({ok, _}, reltool_app_win:open_mod(AppPid, escript)),
+ erlang:monitor(process,AppPid),
+ {ok, ModPid} = ?msym({ok, _}, reltool_app_win:open_mod(AppPid, escript)),
+ erlang:monitor(process,ModPid),
+
+ %% Let all windows get started
timer:sleep(timer:seconds(10)),
+
+ %% Test that server pid can be fetched, and that server is alive
+ {ok, Server} = ?msym({ok,_}, reltool:get_server(SysPid)),
+ ?m(true, erlang:is_process_alive(Server)),
+ ?m({ok,{sys,[]}}, reltool:get_config(Server)),
+
+ %% Terminate
+ check_no_win_crash(),
?m(ok, reltool:stop(SysPid)),
-
+ wait_terminate([{sys,SysPid},{app,AppPid},{mod,ModPid}]),
+
ok.
+
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+check_no_win_crash() ->
+ receive {'DOWN',_,_,_,_} = Down ->
+ ct:log("Unexpected termination of window:~n~p",[Down]),
+ ct:fail("window crashed")
+ after 0 ->
+ ok
+ end.
+
+wait_terminate([]) ->
+ ok;
+wait_terminate([{Win,P}|Rest]) ->
+ receive
+ {'DOWN',_,process,P,shutdown} ->
+ wait_terminate(Rest);
+ {'DOWN',_,process,P,Reason} ->
+ ct:log("~p window terminated with unexpected reason:~n~p",
+ [Win,Reason]),
+ ct:fail("unexpected exit reason from window")
+ end.
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index 751f9bb6db..3811d897c7 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.5.7
+RELTOOL_VSN = 0.6
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index 73ab6cdc11..754e6ccd78 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,11 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
# ----------------------------------------------------
+# Items from top-level configure
+# ----------------------------------------------------
+DTRACE_ENABLED=@DTRACE_ENABLED@
+DTRACE_ENABLED_2STEP=@DTRACE_ENABLED_2STEP@
+# ----------------------------------------------------
# Application version
# ----------------------------------------------------
include ../vsn.mk
@@ -38,6 +43,8 @@ SHELL = /bin/sh
LIBS = $(DED_LIBS)
LDFLAGS += $(DED_LDFLAGS)
+DTRACE_LIBNAME = dyntrace
+
SYSINCLUDE = $(DED_SYS_INCLUDE)
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
SYSINCLUDE += -I$(ERL_TOP)/erts/etc/vxworks
@@ -45,15 +52,20 @@ endif
TRACE_DRV_INCLUDES = $(SYSINCLUDE)
-ALL_CFLAGS = $(CFLAGS) @DEFS@ $(TYPE_FLAGS) $(TRACE_DRV_INCLUDES)
-
+ALL_CFLAGS = $(CFLAGS) @DEFS@ $(TYPE_FLAGS) $(TRACE_DRV_INCLUDES) \
+ -I$(OBJDIR) -I$(ERL_TOP)/erts/emulator/$(TARGET)
ifeq ($(TYPE),debug)
TYPEMARKER = .debug
-TYPE_FLAGS = -g -DDEBUG @DEBUG_FLAGS@
+TYPE_FLAGS = $(subst -O3,,$(subst -O2,,$(CFLAGS))) -DDEBUG @DEBUG_FLAGS@
+else
+ifeq ($(TYPE),valgrind)
+TYPEMARKER = .valgrind
+TYPE_FLAGS = $(subst -O3,,$(subst -O2,,$(CFLAGS))) -DVALGRIND
else
TYPEMARKER =
-TYPE_FLAGS = -O2
+TYPE_FLAGS = $(CFLAGS)
+endif
endif
ROOTDIR = $(ERL_TOP)/lib
@@ -69,6 +81,16 @@ RELSYSDIR = $(RELEASE_PATH)/lib/runtime_tools-$(VSN)
# ----------------------------------------------------
# Misc Macros
# ----------------------------------------------------
+before_DTrace_OBJS = $(OBJDIR)/dyntrace$(TYPEMARKER).o
+## NIF_MAKEFILE = $(PRIVDIR)/Makefile
+
+# Higher-level makefiles says that we can only compile on UNIX flavors
+NIF_LIB = $(LIBDIR)/dyntrace$(TYPEMARKER).@DED_EXT@
+
+ifeq ($(HOST_OS),)
+HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
+endif
+
TRACE_IP_DRV_OBJS = \
$(OBJDIR)/trace_ip_drv.o
@@ -91,7 +113,44 @@ endif
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-debug opt: $(SOLIBS)
+debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB)
+
+ifdef DTRACE_ENABLED
+DTRACE_USER_HEADER=$(OBJDIR)/dtrace_user.h
+$(OBJDIR)/dtrace_user.h: ./dtrace_user.d
+ dtrace -h -C $(INCLUDES) \
+ -s ./dtrace_user.d \
+ -o ./dtrace_user.tmp
+ sed -e '/^#define[ ]*ERLANG_[A-Z0-9_]*(.*)/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' ./dtrace_user.tmp > $@
+ rm ./dtrace_user.tmp
+else
+DTRACE_USER_HEADER=
+endif
+
+DTRACE_OBJS =
+ifdef DTRACE_ENABLED_2STEP
+DTRACE_OBJS += $(OBJDIR)/dtrace_user.o
+$(OBJDIR)/dtrace_user.o: $(before_DTrace_OBJS) $(OBJDIR)/dtrace_user.h
+ dtrace -G -C \
+ -s ./dtrace_user.d \
+ -o $@ $(before_DTrace_OBJS)
+endif
+
+DYNTRACE_OBJS = $(before_DTrace_OBJS) $(DTRACE_OBJS)
+
+$(OBJDIR):
+ -@mkdir -p $(OBJDIR)
+
+$(LIBDIR):
+ -@mkdir -p $(LIBDIR)
+
+$(OBJDIR)/dyntrace$(TYPEMARKER).o: dyntrace.c $(DTRACE_USER_HEADER)
+ $(INSTALL_DIR) $(OBJDIR)
+ $(CC) -c -o $@ $(ALL_CFLAGS) $<
+
+$(NIF_LIB): $(DYNTRACE_OBJS)
+ $(INSTALL_DIR) $(LIBDIR)
+ $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(OBJDIR)/%.o: %.c
$(CC) -c -o $@ $(ALL_CFLAGS) $<
@@ -118,6 +177,12 @@ $(LIBDIR)/trace_file_drv.eld: $(TRACE_FILE_DRV_OBJS)
clean:
rm -f $(SOLIBS) $(TRACE_IP_DRV_OBJS) $(TRACE_FILE_DRV_OBJS)
+ rm -f $(LIBDIR)/dyntrace.@DED_EXT@
+ rm -f $(LIBDIR)/dyntrace.debug.@DED_EXT@
+ rm -f $(LIBDIR)/dyntrace.valgrind.@DED_EXT@
+ rm -f $(OBJDIR)/dyntrace.o
+ rm -f $(OBJDIR)/dyntrace.debug.o
+ rm -f $(OBJDIR)/dyntrace.valgrind.o
rm -f core *~
docs:
@@ -128,8 +193,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_PROGRAM) $(SOLIBS) $(RELSYSDIR)/priv/lib
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib"
release_docs_spec:
diff --git a/lib/runtime_tools/c_src/dtrace_user.d b/lib/runtime_tools/c_src/dtrace_user.d
new file mode 100644
index 0000000000..9e180a3cb2
--- /dev/null
+++ b/lib/runtime_tools/c_src/dtrace_user.d
@@ -0,0 +1,33 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012.
+ * All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+provider erlang {
+ /*
+ * The set of probes for use by Erlang code ... moved from here to
+ * erts/emulator/beam/erlang_dtrace.d until a more portable solution is
+ * found; see erlang_dtrace.d for details.
+ */
+};
+
+#pragma D attributes Evolving/Evolving/Common provider erlang provider
+#pragma D attributes Private/Private/Common provider erlang module
+#pragma D attributes Private/Private/Common provider erlang function
+#pragma D attributes Evolving/Evolving/Common provider erlang name
+#pragma D attributes Evolving/Evolving/Common provider erlang args
diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c
new file mode 100644
index 0000000000..eef03afd1c
--- /dev/null
+++ b/lib/runtime_tools/c_src/dyntrace.c
@@ -0,0 +1,127 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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: Dynamically loadable NIF library for DTrace
+ */
+
+
+
+#include "erl_nif.h"
+#include "config.h"
+#include "sys.h"
+#include "dtrace-wrapper.h"
+#if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP))
+#define HAVE_USE_DTRACE 1
+#endif
+#ifdef HAVE_USE_DTRACE
+#include "dtrace_user.h"
+#endif
+
+void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf);
+void get_string_maybe(ErlNifEnv *env, const ERL_NIF_TERM term, char **ptr, char *buf, int bufsiz);
+#ifdef HAVE_USE_DTRACE
+ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+#endif
+
+#ifdef VALGRIND
+ # include <valgrind/memcheck.h>
+#endif
+
+#ifdef __GNUC__
+ # define INLINE __inline__
+#else
+ # define INLINE
+#endif
+
+#define MESSAGE_BUFSIZ 1024
+
+/* NIF interface declarations */
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
+
+/* The NIFs: */
+static ERL_NIF_TERM available(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static ErlNifFunc nif_funcs[] = {
+ {"available", 0, available},
+ {"user_trace_s1", 1, user_trace_s1},
+ {"user_trace_i4s4", 9, user_trace_i4s4},
+ {"user_trace_n", 10, user_trace_n}
+};
+
+ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL)
+
+static ERL_NIF_TERM atom_true;
+static ERL_NIF_TERM atom_false;
+static ERL_NIF_TERM atom_error;
+static ERL_NIF_TERM atom_not_available;
+static ERL_NIF_TERM atom_badarg;
+static ERL_NIF_TERM atom_ok;
+
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ atom_true = enif_make_atom(env,"true");
+ atom_false = enif_make_atom(env,"false");
+ atom_error = enif_make_atom(env,"error");
+ atom_not_available = enif_make_atom(env,"not_available");
+ atom_badarg = enif_make_atom(env,"badarg");
+ atom_ok = enif_make_atom(env,"ok");
+
+ return 0;
+}
+
+static ERL_NIF_TERM available(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef HAVE_USE_DTRACE
+ return atom_true;
+#else
+ return atom_false;
+#endif
+}
+
+static ERL_NIF_TERM user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef HAVE_USE_DTRACE
+ return erl_nif_user_trace_s1(env, argc, argv);
+#else
+ return atom_error;
+#endif
+}
+
+static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef HAVE_USE_DTRACE
+ return erl_nif_user_trace_i4s4(env, argc, argv);
+#else
+ return atom_error;
+#endif
+}
+
+static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef HAVE_USE_DTRACE
+ return erl_nif_user_trace_n(env, argc, argv);
+#else
+ return atom_error;
+#endif
+}
diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c
index 668f6f4af3..08bace80ef 100644
--- a/lib/runtime_tools/c_src/trace_file_drv.c
+++ b/lib/runtime_tools/c_src/trace_file_drv.c
@@ -21,6 +21,9 @@
* Purpose: Send trace messages to a file.
*/
+#ifdef __WIN32__
+#include <windows.h>
+#endif
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -31,7 +34,6 @@
#ifdef __WIN32__
# include <io.h>
# define write _write
-# define open _open
# define close _close
# define unlink _unlink
#else
@@ -40,11 +42,6 @@
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
-#ifdef VXWORKS
-# include "reclaim.h"
-#endif
-
-
/*
* Deduce MAXPATHLEN, which is the one to use in this file,
@@ -176,11 +173,13 @@ static TraceFileData *first_data;
*/
static ErlDrvData trace_file_start(ErlDrvPort port, char *buff);
static void trace_file_stop(ErlDrvData handle);
-static void trace_file_output(ErlDrvData handle, char *buff, int bufflen);
+static void trace_file_output(ErlDrvData handle, char *buff,
+ ErlDrvSizeT bufflen);
static void trace_file_finish(void);
-static int trace_file_control(ErlDrvData handle, unsigned int command,
- char* buff, int count,
- char** res, int res_size);
+static ErlDrvSSizeT trace_file_control(ErlDrvData handle,
+ unsigned int command,
+ char* buff, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size);
static void trace_file_timeout(ErlDrvData handle);
/*
@@ -194,6 +193,12 @@ static int my_flush(TraceFileData *data);
static void put_be(unsigned n, unsigned char *s);
static void close_unlink_port(TraceFileData *data);
static int wrap_file(TraceFileData *data);
+#ifdef __WIN32__
+static int win_open(char *path, int flags, int mask);
+#define open win_open
+#else
+ErlDrvEntry *driver_init(void);
+#endif
/*
** The driver struct
@@ -212,7 +217,18 @@ ErlDrvEntry trace_file_driver_entry = {
NULL, /* void * that is not used (BC) */
trace_file_control, /* F_PTR control, port_control callback */
trace_file_timeout, /* F_PTR timeout, driver_set_timer callback */
- NULL /* F_PTR outputv, reserved */
+ NULL, /* F_PTR outputv, reserved */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
/*
@@ -241,6 +257,7 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff)
int n, w;
static const char name[] = "trace_file_drv";
+
#ifdef HARDDEBUG
fprintf(stderr,"hello (%s)\r\n", buff);
#endif
@@ -347,17 +364,18 @@ static void trace_file_stop(ErlDrvData handle)
/*
** Data sent from erlang to port.
*/
-static void trace_file_output(ErlDrvData handle, char *buff, int bufflen)
+static void trace_file_output(ErlDrvData handle, char *buff,
+ ErlDrvSizeT bufflen)
{
int heavy = 0;
TraceFileData *data = (TraceFileData *) handle;
unsigned char b[5] = "";
put_be((unsigned) bufflen, b + 1);
- switch (my_write(data, b, sizeof(b))) {
+ switch (my_write(data, (unsigned char *) b, sizeof(b))) {
case 1:
heavy = !0;
case 0:
- switch (my_write(data, buff, bufflen)) {
+ switch (my_write(data, (unsigned char *) buff, bufflen)) {
case 1:
heavy = !0;
case 0:
@@ -391,9 +409,10 @@ static void trace_file_output(ErlDrvData handle, char *buff, int bufflen)
/*
** Control message from erlang, we handle $f, which is flush.
*/
-static int trace_file_control(ErlDrvData handle, unsigned int command,
- char* buff, int count,
- char** res, int res_size)
+static ErlDrvSSizeT trace_file_control(ErlDrvData handle,
+ unsigned int command,
+ char* buff, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size)
{
if (command == 'f') {
TraceFileData *data = (TraceFileData *) handle;
@@ -636,3 +655,40 @@ static int wrap_file(TraceFileData *data) {
return 0;
}
+#ifdef __WIN32__
+static int win_open(char *path, int flags, int mask)
+{
+ DWORD access = 0;
+ DWORD creation = 0;
+ HANDLE fd;
+ int ret;
+ if (flags & O_WRONLY) {
+ access = GENERIC_WRITE;
+ } else if (flags & O_RDONLY) {
+ access = GENERIC_READ;
+ } else {
+ access = (GENERIC_READ | GENERIC_WRITE);
+ }
+
+ if (flags & O_CREAT) {
+ creation |= CREATE_ALWAYS;
+ } else {
+ creation |= OPEN_ALWAYS;
+ }
+
+ fd = CreateFileA(path, access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fd == INVALID_HANDLE_VALUE) {
+
+ return -1;
+ }
+
+ if ((ret = _open_osfhandle((intptr_t)fd, (flags & O_RDONLY) ? O_RDONLY : 0))
+ < 0) {
+ CloseHandle(fd);
+ }
+
+ return ret;
+}
+#endif
diff --git a/lib/runtime_tools/c_src/trace_ip_drv.c b/lib/runtime_tools/c_src/trace_ip_drv.c
index d2ed1a294b..6b77128761 100644
--- a/lib/runtime_tools/c_src/trace_ip_drv.c
+++ b/lib/runtime_tools/c_src/trace_ip_drv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -185,7 +185,8 @@ static TraceIpData *first_data;
*/
static ErlDrvData trace_ip_start(ErlDrvPort port, char *buff);
static void trace_ip_stop(ErlDrvData handle);
-static void trace_ip_output(ErlDrvData handle, char *buff, int bufflen);
+static void trace_ip_output(ErlDrvData handle, char *buff,
+ ErlDrvSizeT bufflen);
#ifdef __WIN32__
static void trace_ip_event(ErlDrvData handle, ErlDrvEvent event);
#endif
@@ -193,9 +194,10 @@ static void trace_ip_ready_input(ErlDrvData handle, ErlDrvEvent fd);
static void trace_ip_ready_output(ErlDrvData handle, ErlDrvEvent fd);
static void trace_ip_finish(void); /* No arguments, despite what might be stated
in any documentation */
-static int trace_ip_control(ErlDrvData handle, unsigned int command,
- char* buff, int count,
- char** res, int res_size);
+static ErlDrvSSizeT trace_ip_control(ErlDrvData handle,
+ unsigned int command,
+ char* buff, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size);
/*
** Internal routines
@@ -210,11 +212,11 @@ static TraceIpData *lookup_data_by_port(int portno);
static int set_nonblocking(SOCKET sock);
static TraceIpMessage *make_buffer(int datasiz, unsigned char op,
unsigned number);
-static void enque_message(TraceIpData *data, unsigned char *buff, int bufflen,
+static void enque_message(TraceIpData *data, char *buff, int bufflen,
int byteswritten);
static void clean_que(TraceIpData *data);
static void close_client(TraceIpData *data);
-static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen);
+static int trywrite(TraceIpData *data, char *buff, int bufflen);
static SOCKET my_accept(SOCKET sock);
static void close_unlink_port(TraceIpData *data);
enum MySelectOp { SELECT_ON, SELECT_OFF, SELECT_CLOSE };
@@ -382,7 +384,7 @@ static void trace_ip_stop(ErlDrvData handle)
/*
** Data sent from erlang to port.
*/
-static void trace_ip_output(ErlDrvData handle, char *buff, int bufflen)
+static void trace_ip_output(ErlDrvData handle, char *buff, ErlDrvSizeT bufflen)
{
TraceIpData *data = (TraceIpData *) handle;
if (data->flags & FLAG_LISTEN_PORT) {
@@ -516,7 +518,7 @@ static void trace_ip_ready_output(ErlDrvData handle, ErlDrvEvent fd)
tim = data->que[data->questart];
towrite = tim->siz - tim->written;
while((res = write_until_done(data->fd,
- tim->bin + tim->written, towrite))
+ (char *)tim->bin + tim->written, towrite))
== towrite) {
driver_free(tim);
data->que[data->questart] = NULL;
@@ -548,9 +550,10 @@ static void trace_ip_ready_output(ErlDrvData handle, ErlDrvEvent fd)
/*
** Control message from erlang, we handle $p, which is get_listen_port.
*/
-static int trace_ip_control(ErlDrvData handle, unsigned int command,
- char* buff, int count,
- char** res, int res_size)
+static ErlDrvSSizeT trace_ip_control(ErlDrvData handle,
+ unsigned int command,
+ char* buff, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size)
{
register void *void_ptr; /* Soft type cast */
@@ -558,7 +561,7 @@ static int trace_ip_control(ErlDrvData handle, unsigned int command,
TraceIpData *data = (TraceIpData *) handle;
ErlDrvBinary *b = my_alloc_binary(3);
b->orig_bytes[0] = '\0'; /* OK */
- put_be16(data->listen_portno, &(b->orig_bytes[1]));
+ put_be16(data->listen_portno, (unsigned char *)&(b->orig_bytes[1]));
*res = void_ptr = b;
return 0;
}
@@ -587,8 +590,8 @@ static void *my_alloc(size_t size)
void *ret;
if ((ret = driver_alloc(size)) == NULL) {
/* May or may not work... */
- fprintf(stderr, "Could not allocate %d bytes of memory in %s.",
- (int) size, __FILE__);
+ fprintf(stderr, "Could not allocate %lu bytes of memory in %s.",
+ (unsigned long) size, __FILE__);
exit(1);
}
return ret;
@@ -602,8 +605,8 @@ static ErlDrvBinary *my_alloc_binary(int size)
ErlDrvBinary *ret;
if ((ret = driver_alloc_binary(size)) == NULL) {
/* May or may not work... */
- fprintf(stderr, "Could not allocate a binary of %d bytes in %s.",
- (int) size, __FILE__);
+ fprintf(stderr, "Could not allocate a binary of %lu bytes in %s.",
+ (unsigned long) size, __FILE__);
exit(1);
}
return ret;
@@ -693,7 +696,7 @@ static TraceIpMessage *make_buffer(int datasiz, unsigned char op,
** Add message to que, discarding in a politically correct way...
** The FLAG_DROP_OLDEST is currently ingored...
*/
-static void enque_message(TraceIpData *data, unsigned char *buff, int bufflen,
+static void enque_message(TraceIpData *data, char *buff, int bufflen,
int byteswritten)
{
int diff = data->questop - data->questart;
@@ -760,13 +763,13 @@ static void close_client(TraceIpData *data)
** Try to write a message from erlang directly (only called when que is empty
** and client is connected)
*/
-static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen)
+static int trywrite(TraceIpData *data, char *buff, int bufflen)
{
- unsigned char op[5];
+ char op[5];
int res;
op[0] = OP_BINARY;
- put_be32(bufflen, op + 1);
+ put_be32(bufflen, (unsigned char *)op + 1);
if ((res = write_until_done(data->fd, op, 5)) < 0) {
close_client(data);
@@ -790,7 +793,11 @@ static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen)
static SOCKET my_accept(SOCKET sock)
{
struct sockaddr_in sin;
- int sin_size = sizeof(sin);
+#ifdef HAVE_SOCKLEN_T
+ socklen_t sin_size = sizeof(sin);
+#else
+ int sin_size = (int) sizeof(sin);
+#endif
return accept(sock, (struct sockaddr *) &sin, &sin_size);
}
diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile
index dbbae81cfe..d240b287c3 100644
--- a/lib/runtime_tools/doc/src/Makefile
+++ b/lib/runtime_tools/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
+# Copyright Ericsson AB 1999-2012. All Rights Reserved.
#
# The 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 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = dbg.xml erts_alloc_config.xml
+XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml
XML_REF6_FILES = runtime_tools_app.xml
XML_PART_FILES = part_notes.xml part_notes_history.xml
@@ -108,16 +108,16 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/runtime_tools/doc/src/dyntrace.xml b/lib/runtime_tools/doc/src/dyntrace.xml
new file mode 100644
index 0000000000..5fc5530f25
--- /dev/null
+++ b/lib/runtime_tools/doc/src/dyntrace.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>1996</year><year>2012</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>dyntrace</title>
+ <prepared>Patrik Nyblom</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved>ETX/B/SFP (Kenneth Lundin)</approved>
+ <checked></checked>
+ <date>12-03-20</date>
+ <rev>A</rev>
+ <file>dyntrace.xml</file>
+ </header>
+ <module>dyntrace</module>
+ <modulesummary>Interface to dynamic tracing</modulesummary>
+ <description>
+ <p>This module implements interfaces to dynamic tracing, should such be compiled into the virtual machine. For a standard and/or commercial build, no dynamic tracing is available, in which case none of the functions in this module is usable or give any effect.</p>
+ <p>Should dynamic tracing be enabled in the current build, either by configuring with <c>./configure --with-dynamic-trace=dtrace</c> or with <c>./configure --with-dynamic-trace=systemtap</c>, the module can be used for two things:</p>
+ <list type="bulleted">
+ <item>Trigger the user-probe <c>user_trace_i4s4</c> in the NIF library <c>dyntrace.so</c> by calling <c>dyntrace:p/{1,2,3,4,5,6,7,8}</c>.</item>
+ <item>Set a user specified tag that will be present in the trace messages of both the <c>efile_drv</c> and the user-probe mentioned above.</item>
+ </list>
+ <p>Both building with dynamic trace probes and using them is experimental and unsupported by Erlang/OTP. It is included as an option for the developer to trace and debug performance issues in their systems.</p>
+ <p>The original implementation is mostly done by Scott Lystiger Fritchie as an Open Source Contribution and it should be viewed as such even though the source for dynamic tracing as well as this module is included in the main distribution. However, the ability to use dynamic tracing of the virtual machine is a very valuable contribution which OTP has every intention to maintain as a tool for the developer.</p>
+ <p>How to write <c>d</c> programs or <c>systemtap</c> scripts can be learned from books and from a lot of pages on the Internet. This manual page does not include any documentation about using the dynamic trace tools of respective platform. The <c>examples</c> directory of the <c>runtime_tools</c> application however contains comprehensive examples of both <c>d</c> and <c>systemtap</c> programs that will help you get started. Another source of information is the <c>README.dtrace(.md)</c> and <c>README.systemtap(.md)</c> files in the Erlang source top directory.</p>
+ </description>
+ <funcs>
+ <func>
+ <name>available() -> boolean()</name>
+ <fsummary>Check if dynamic tracing is available</fsummary>
+ <desc>
+ <p>This function uses the NIF library to determine if dynamic
+ tracing is available. Usually calling <seealso
+ marker="erts:erlang#system_info/1">erlang:system_info/1</seealso>
+ is a better indicator of the availability of dynamic
+ tracing.</p>
+ <p>The function will throw an exception if the <c>dyntrace</c> NIF library could not be loaded by the on_load function of this module.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p() -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message only containing the user tag and zeroes/empty strings in all other fields.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer() | string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer or string parameter in the first integer/string field.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer() | string(), integer() | string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters. I.e. <c>p(1,"Hello")</c> is ok, as is <c>p(1,1)</c> and <c>p("Hello","Again")</c>, but not <c>p("Hello",1)</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer() | string(), integer() | string(), integer() | string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer() | string(), integer() | string(), integer() | string(), integer() | string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer(), integer() | string(), integer() | string(), integer() | string(), string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
+ <p>There can be no more than four parameters of any type (integer() or string()), so the first parameter has to be an integer() and the last a string().</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer(), integer(), integer() | string(), integer() | string(), string(), string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
+ <p>There can be no more than four parameters of any type (integer() or string()), so the first two parameters has to be integer()'s and the last two string()'s.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer(), integer(), integer(), integer() | string(), string(), string(), string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
+ <p>There can be no more than four parameters of any type (integer() or string()), so the first three parameters has to be integer()'s and the last three string()'s.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(integer(), integer(), integer(), integer(), string(), string(), string(), string()) -> true | false | error | badarg</name>
+ <fsummary>Trigger the user trace probe.</fsummary>
+ <desc>
+ <p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing all the integer()'s and string()'s provided, as well as any user tag set in the current process.</p>
+ </desc>
+ </func>
+ <func>
+ <name>get_tag() -> binary() | undefined</name>
+ <fsummary>Get the user tag set in the process.</fsummary>
+ <desc>
+ <p>This function returns the user tag set in the current
+ process. If no tag is set or dynamic tracing is not available,
+ it returns <c>undefined</c></p>
+ </desc>
+ </func>
+ <func>
+ <name>get_tag() -> binary() | undefined</name>
+ <fsummary>Get the user tag set in the process or sent to the process.</fsummary>
+ <desc>
+ <p>This function returns the user tag set in the current
+ process or, if no user tag is present, the last user tag sent
+ to the process together with a message (in the same way as
+ <seealso marker="kernel:seq_trace">sequential trace
+ tokens</seealso> are spread to other processes together with
+ messages. For an explanation of how user tags can be spread
+ together with messages, see <seealso
+ marker="#spread_tag/1">spread_tag/1</seealso>. If no tag is
+ found or dynamic tracing is not available, it returns
+ <c>undefined</c></p>
+ </desc>
+ </func>
+
+ <func>
+ <name>put_tag(Item) -> binary() | undefined </name>
+ <fsummary>Set the user tag of the current process.</fsummary>
+ <type>
+ <v>Item = iodata()</v>
+ </type>
+ <desc>
+ <p>This function sets the user tag of the current process. The user tag is a binary(), but can be specified as any iodata(), which is automatically converted to a binary by this function.</p>
+ <p>The user tag is provided to the user probes triggered by calls top <c>dyntrace:p/{1,2,3,4,5,6,7,8}</c> as well as probes in the efile_driver. In the future, user tags might be added to more probes.</p>
+ <p>The old user tag (if any) is returned, or <c>undefined</c> if no user tag was present or dynamic tracing is not enabled.</p>
+ </desc>
+ </func>
+ <func>
+ <name>spread_tag(boolean()) -> TagData</name>
+ <fsummary>Start or stop spreading dynamic trace user tags with the next message.</fsummary>
+ <type>
+ <v>TagData = opaque data that can be used as parameter to <seealso marker="#restore_tag/1">restore_tag/1</seealso></v>
+ </type>
+ <desc>
+ <p>This function controls if user tags are to be spread to other processes with the next message. Spreading of user tags work like spreading of sequential trace tokens, so that a received user tag will be active in the process until the next message arrives (if that message does not also contain the user tag.</p>
+ <p>This functionality is used when a client process communicates with a file i/o-server to spread the user tag to the I/O-server and then down to the efile_drv driver. By using <c>spread_tag/1</c> and <c>restore_tag/1</c>, one can enable or disable spreading of user tags to other processes and then restore the previous state of the user tag. The TagData returned from this call contains all previous information so the state (including any previously spread user tags) will be completely restored by a later call to <c>restore_tag/1</c>.</p>
+ <p>The <seealso marker="kernel:file">file</seealso> module already spread's tags, so there is noo need to manually call these function to get user tags spread to the efile driver through that module.</p>
+ <p>The most use of this function would be if one for example uses the <seealso marker="stdlib:io">io</seealso> module to communicate with an I/O-server for a regular file, like in the following example:</p>
+<pre>
+f() ->
+ {ok, F} = file:open("test.tst",[write]),
+ Saved = dyntrace:spread_tag(true),
+ io:format(F,"Hello world!",[]),
+ dyntrace:restore_tag(Saved),
+ file:close(F).
+</pre>
+ <p>In this example, any user tag set in the calling process will be spread to the I/O-server when the io:format call is done.</p>
+ </desc>
+ </func>
+ <func>
+ <name>restore_tag(TagData) -> true</name>
+ <fsummary>Restore to a previous state of user tag spreading.</fsummary>
+ <type>
+ <v>TagData = opaque data returned by <seealso marker="#spread_tag/1">spread_tag/1</seealso></v>
+ </type>
+ <desc>
+ <p>Restores the previous state of user tags and their spreading as it was before a call to <seealso marker="#spread_tag/1">spread_tag/1</seealso>. Note that the restoring is not limited to the same process, one can utilize this to turn off spreding in one process and restore it in a newly created, the one that actually is going to send messages:</p>
+<pre>
+f() ->
+ TagData=dyntrace:spread_tag(false),
+ spawn(fun() ->
+ dyntrace:restore_tag(TagData),
+ do_something()
+ end),
+ do_something_else(),
+ dyntrace:restore_tag(TagData).
+</pre>
+ <p>Correctly handling user tags and their spreading might take some effort, as Erlang programs tend to send and receive messages so that sometimes the user tag gets lost due to various things, like double receives or communication with a port (ports do not handle user tags, in the same way as they do not handle regular sequential trace tokens).</p>
+ </desc>
+ </func>
+ </funcs>
+ </erlref>
+
diff --git a/lib/runtime_tools/doc/src/make.dep b/lib/runtime_tools/doc/src/make.dep
deleted file mode 100644
index 85eae88adf..0000000000
--- a/lib/runtime_tools/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex dbg.tex erts_alloc_config.tex refman.tex \
- runtime_tools_app.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: refman.xml
-
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 0bb76e1ea4..2d4a206e1c 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -31,6 +31,78 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.8.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The DTrace source patch from Scott Lystig Fritchie is
+ integrated in the source tree. Using an emulator with
+ dtrace probe is still not supported for production use,
+ but may be a valuable debugging tool. Configure with
+ --with-dynamic-trace=dtrace (or
+ --with-dynamic-trace=systemtap) to create a build with
+ dtrace probes enabled. See runtime_tools for
+ documentation and examples.</p>
+ <p>
+ Own Id: OTP-10017</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.8.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Earlier dbg:stop only did erlang:trace_delivered and did
+ not flush the trace file driver. Therefore there could
+ still be trace messages that were delivered to the driver
+ (guaranteed by erlang:trace_delivered) but not yet
+ written to the file when dbg:stop returned. Flushing is
+ now added on each node before the dbg process terminates.</p>
+ <p>
+ Own Id: OTP-9651</p>
+ </item>
+ <item>
+ <p>
+ File handles created by the trace_file_drv driver was
+ inherited to child processes. This is now corrected.</p>
+ <p>
+ Own Id: OTP-9658</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <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.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/doc/src/ref_man.xml b/lib/runtime_tools/doc/src/ref_man.xml
index 579efcd969..df3446cd17 100644
--- a/lib/runtime_tools/doc/src/ref_man.xml
+++ b/lib/runtime_tools/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1999</year><year>2009</year>
+ <year>1999</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,7 @@
</description>
<xi:include href="runtime_tools_app.xml"/>
<xi:include href="dbg.xml"/>
+ <xi:include href="dyntrace.xml"/>
<xi:include href="erts_alloc_config.xml"/>
</application>
diff --git a/lib/runtime_tools/examples/dist.d b/lib/runtime_tools/examples/dist.d
new file mode 100644
index 0000000000..7e2d7f0e35
--- /dev/null
+++ b/lib/runtime_tools/examples/dist.d
@@ -0,0 +1,62 @@
+/* example usage: dtrace -q -s /path/to/dist.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::dist-monitor
+{
+ printf("monitor: pid %d, who %s, what %s, node %s, type %s, reason %s\n",
+ pid,
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3),
+ copyinstr(arg4));
+}
+
+erlang*:::dist-port_busy
+{
+ printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
+ /*
+ * For variable use advice, see:
+ * http://dtrace.org/blogs/brendan/2011/11/25/dtrace-variable-types/
+ *
+ * Howevever, it's quite possible for the blocked events to span
+ * threads, so we'll use globals.
+ */
+ blocked_procs[copyinstr(arg3)] = timestamp;
+}
+
+erlang*:::dist-output
+{
+ printf("dist output: node %s, port %s, remote_node %s bytes %d\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+
+erlang*:::dist-outputv
+{
+ printf("port outputv: node %s, port %s, remote_node %s bytes %d\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+
+erlang*:::process-scheduled
+/blocked_procs[copyinstr(arg0)]/
+{
+ pidstr = copyinstr(arg0);
+ printf("blocked pid %s scheduled now, waited %d microseconds\n",
+ pidstr, (timestamp - blocked_procs[pidstr]) / 1000);
+ blocked_procs[pidstr] = 0;
+}
diff --git a/lib/runtime_tools/examples/dist.systemtap b/lib/runtime_tools/examples/dist.systemtap
new file mode 100644
index 0000000000..8935e19e28
--- /dev/null
+++ b/lib/runtime_tools/examples/dist.systemtap
@@ -0,0 +1,76 @@
+/* example usage: stap /path/to/dist.systemtap -x <pid> */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("dist-monitor")
+{
+ printf("monitor: pid %d, who %s, what %s, node %s, type %s, reason %s\n",
+ pid(),
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4),
+ user_string($arg5));
+}
+
+probe process("beam").mark("dist-port_busy")
+{
+ printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
+ blocked_procs[user_string($arg4)] = timestamp;
+}
+
+probe process("beam").mark("dist-port_busy")
+{
+ printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
+ blocked_procs[user_string($arg4)] = timestamp;
+}
+
+probe process("beam").mark("dist-output")
+{
+ printf("dist output: node %s, port %s, remote_node %s bytes %d\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
+}
+
+probe process("beam").mark("dist-outputv")
+{
+ printf("port outputv: node %s, port %s, remote_node %s bytes %d\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
+}
+
+probe process("beam").mark("process-scheduled")
+{
+ pidstr = user_string($arg1);
+ if (pidstr in blocked_procs) {
+ printf("blocked pid %s scheduled now, waited %d microseconds\n",
+ pidstr, (timestamp - blocked_procs[pidstr]) / 1000);
+ delete blocked_procs[pidstr];
+ }
+}
+
+global blocked_procs;
diff --git a/lib/runtime_tools/examples/driver1.d b/lib/runtime_tools/examples/driver1.d
new file mode 100644
index 0000000000..4871a8ee69
--- /dev/null
+++ b/lib/runtime_tools/examples/driver1.d
@@ -0,0 +1,114 @@
+/* example usage: dtrace -q -s /path/to/driver1.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::driver-init
+{
+ printf("driver init name %s major %d minor %d flags %d\n",
+ copyinstr(arg0), arg1, arg2, arg3);
+}
+
+erlang*:::driver-start
+{
+ printf("driver start pid %s driver name %s port %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-stop
+{
+ printf("driver stop pid %s driver name %s port %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-finish
+{
+ printf("driver finish driver name %s port %s\n",
+ copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::driver-flush
+{
+ printf("driver flush pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-output
+{
+ printf("driver output pid %s port %s port name %s bytes %d\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+
+erlang*:::driver-outputv
+{
+ printf("driver outputv pid %s port %s port name %s bytes %d\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+
+erlang*:::driver-control
+{
+ printf("driver control pid %s port %s port name %s command %d bytes %d\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3, arg4);
+}
+
+erlang*:::driver-call
+{
+ printf("driver call pid %s port %s port name %s command %d bytes %d\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3, arg4);
+}
+
+erlang*:::driver-event
+{
+ printf("driver event pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-ready_input
+{
+ printf("driver ready_input pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-ready_output
+{
+ printf("driver ready_output pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-timeout
+{
+ printf("driver timeout pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-ready_async
+{
+ printf("driver ready_async pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-process_exit
+{
+ printf("driver process_exit pid %s port %s port name %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::driver-stop_select
+{
+ printf("driver stop_select driver name %s\n", copyinstr(arg0));
+}
diff --git a/lib/runtime_tools/examples/driver1.systemtap b/lib/runtime_tools/examples/driver1.systemtap
new file mode 100644
index 0000000000..deae82f8fb
--- /dev/null
+++ b/lib/runtime_tools/examples/driver1.systemtap
@@ -0,0 +1,125 @@
+/* example usage: stap /path/to/driver1.systemtap -x <pid> */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("driver-init")
+{
+ printf("driver init name %s major %d minor %d flags %d\n",
+ user_string($arg1), $arg2, $arg3, $arg4);
+}
+
+probe process("beam").mark("driver-start")
+{
+ printf("driver start pid %s driver name %s port %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-stop")
+{
+ printf("driver stop pid %s driver name %s port %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-finish")
+{
+ printf("driver finish driver name %s\n",
+ user_string($arg1));
+}
+
+probe process("beam").mark("driver-flush")
+{
+ printf("driver flush pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-output")
+{
+ printf("driver output pid %s port %s port name %s bytes %d\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
+}
+
+probe process("beam").mark("driver-outputv")
+{
+ printf("driver outputv pid %s port %s port name %s bytes %d\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
+}
+
+probe process("beam").mark("driver-control")
+{
+ printf("driver control pid %s port %s port name %s command %d bytes %d\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4, $arg5);
+}
+
+probe process("beam").mark("driver-call")
+{
+ printf("driver call pid %s port %s port name %s command %d bytes %d\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4, $arg5);
+}
+
+probe process("beam").mark("driver-event")
+{
+ printf("driver event pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-ready_input")
+{
+ printf("driver ready_input pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-ready_output")
+{
+ printf("driver ready_output pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-timeout")
+{
+ printf("driver timeout pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-ready_async")
+{
+ printf("driver ready_async pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-process_exit")
+{
+ printf("driver process_exit pid %s port %s port name %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("driver-stop_select")
+{
+ printf("driver stop_select driver name %s\n", user_string($arg1));
+}
diff --git a/lib/runtime_tools/examples/efile_drv.d b/lib/runtime_tools/examples/efile_drv.d
new file mode 100644
index 0000000000..2442222552
--- /dev/null
+++ b/lib/runtime_tools/examples/efile_drv.d
@@ -0,0 +1,104 @@
+/* example usage: dtrace -q -s /path/to/efile_drv.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+BEGIN
+{
+ op_map[1] = "OPEN";
+ op_map[2] = "READ";
+ op_map[3] = "LSEEK";
+ op_map[4] = "WRITE";
+ op_map[5] = "FSTAT";
+ op_map[6] = "PWD";
+ op_map[7] = "READDIR";
+ op_map[8] = "CHDIR";
+ op_map[9] = "FSYNC";
+ op_map[10] = "MKDIR";
+ op_map[11] = "DELETE";
+ op_map[12] = "RENAME";
+ op_map[13] = "RMDIR";
+ op_map[14] = "TRUNCATE";
+ op_map[15] = "READ_FILE";
+ op_map[16] = "WRITE_INFO";
+ op_map[19] = "LSTAT";
+ op_map[20] = "READLINK";
+ op_map[21] = "LINK";
+ op_map[22] = "SYMLINK";
+ op_map[23] = "CLOSE";
+ op_map[24] = "PWRITEV";
+ op_map[25] = "PREADV";
+ op_map[26] = "SETOPT";
+ op_map[27] = "IPREAD";
+ op_map[28] = "ALTNAME";
+ op_map[29] = "READ_LINE";
+ op_map[30] = "FDATASYNC";
+ op_map[31] = "FADVISE";
+}
+
+erlang*:::aio_pool-add
+{
+ printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
+}
+
+erlang*:::aio_pool-get
+{
+ printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
+}
+
+erlang*:::efile_drv-entry
+{
+ printf("efile_drv enter tag={%d,%d} %s%s | %s (%d) | args: %s %s , %d %d (port %s)\n",
+ arg0, arg1,
+ arg2 == NULL ? "" : "user tag ",
+ arg2 == NULL ? "" : copyinstr(arg2),
+ op_map[arg3], arg3,
+ arg4 == NULL ? "" : copyinstr(arg4),
+ arg5 == NULL ? "" : copyinstr(arg5), arg6, arg7,
+ /* NOTE: port name in args[10] is experimental */
+ (args[10] == NULL) ?
+ "?" : copyinstr((user_addr_t) args[10]));
+}
+
+erlang*:::efile_drv-int*
+{
+ printf("async I/O worker tag={%d,%d} | %s (%d) | %s\n",
+ arg0, arg1, op_map[arg2], arg2, probename);
+}
+
+/* efile_drv-return error case */
+erlang*:::efile_drv-return
+/arg4 == 0/
+{
+ printf("efile_drv return tag={%d,%d} %s%s | %s (%d) | errno %d\n",
+ arg0, arg1,
+ arg2 == NULL ? "" : "user tag ",
+ arg2 == NULL ? "" : copyinstr(arg2),
+ op_map[arg3], arg3,
+ arg5);
+}
+
+/* efile_drv-return success case */
+erlang*:::efile_drv-return
+/arg4 != 0/
+{
+ printf("efile_drv return tag={%d,%d} %s | %s (%d) ok\n",
+ arg0, arg1,
+ arg2 == NULL ? "" : copyinstr(arg2),
+ op_map[arg3], arg3);
+}
diff --git a/lib/runtime_tools/examples/efile_drv.systemtap b/lib/runtime_tools/examples/efile_drv.systemtap
new file mode 100644
index 0000000000..4b92e67048
--- /dev/null
+++ b/lib/runtime_tools/examples/efile_drv.systemtap
@@ -0,0 +1,112 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe begin
+{
+ op_map[1] = "OPEN";
+ op_map[2] = "READ";
+ op_map[3] = "LSEEK";
+ op_map[4] = "WRITE";
+ op_map[5] = "FSTAT";
+ op_map[6] = "PWD";
+ op_map[7] = "READDIR";
+ op_map[8] = "CHDIR";
+ op_map[9] = "FSYNC";
+ op_map[10] = "MKDIR";
+ op_map[11] = "DELETE";
+ op_map[12] = "RENAME";
+ op_map[13] = "RMDIR";
+ op_map[14] = "TRUNCATE";
+ op_map[15] = "READ_FILE";
+ op_map[16] = "WRITE_INFO";
+ op_map[19] = "LSTAT";
+ op_map[20] = "READLINK";
+ op_map[21] = "LINK";
+ op_map[22] = "SYMLINK";
+ op_map[23] = "CLOSE";
+ op_map[24] = "PWRITEV";
+ op_map[25] = "PREADV";
+ op_map[26] = "SETOPT";
+ op_map[27] = "IPREAD";
+ op_map[28] = "ALTNAME";
+ op_map[29] = "READ_LINE";
+ op_map[30] = "FDATASYNC";
+ op_map[31] = "FADVISE";
+}
+
+probe process("beam").mark("aio_pool-add")
+{
+ printf("async I/O pool port %s queue len %d\n", user_string($arg1), $arg2);
+}
+
+probe process("beam").mark("aio_pool-get")
+{
+ printf("async I/O pool port %s queue len %d\n", user_string($arg1), $arg2);
+}
+
+probe process("beam").mark("efile_drv-entry")
+{
+ printf("efile_drv enter tag={%d,%d} %s%s | %s (%d) | args: %s %s , %d %d (port %s)\n",
+ $arg1, $arg2,
+ $arg3 == NULL ? "" : "user tag ",
+ $arg3 == NULL ? "" : user_string($arg3),
+ op_map[$arg4], $arg4,
+ $arg5 == NULL ? "" : user_string($arg5),
+ $arg6 == NULL ? "" : user_string($arg6), $arg7, $arg8,
+ /* NOTE: port name in $arg[11] is experimental */
+ user_string($arg11))
+}
+
+probe process("beam").mark("efile_drv-int*")
+{
+ printf("async I/O worker tag={%d,%d} | %s (%d) | %s\n",
+ $arg1, $arg2, op_map[$arg3], $arg3, probefunc());
+}
+
+probe process("beam").mark("efile_drv-return")
+{
+ if ($arg5 == 0) {
+ /* efile_drv-return error case */
+ printf("efile_drv return tag={%d,%d} %s%s | %s (%d) | errno %d\n",
+ $arg1, $arg2,
+ $arg3 == NULL ? "" : "user tag ",
+ $arg3 == NULL ? "" : user_string($arg3),
+ op_map[$arg4], $arg4,
+ $arg6);
+ } else {
+ /* efile_drv-return success case */
+ printf("efile_drv return tag={%d,%d} %s | %s (%d) ok\n",
+ $arg1, $arg2,
+ $arg3 == NULL ? "" : user_string($arg3),
+ op_map[$arg4], $arg4);
+ }
+}
+
+global op_map;
diff --git a/lib/runtime_tools/examples/function-calls.d b/lib/runtime_tools/examples/function-calls.d
new file mode 100644
index 0000000000..ec6090553e
--- /dev/null
+++ b/lib/runtime_tools/examples/function-calls.d
@@ -0,0 +1,57 @@
+/* example usage: dtrace -q -s /path/to/function-calls.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::local-function-entry
+{
+ printf("pid %s enter (local) %s depth %d\n",
+ copyinstr(arg0), copyinstr(arg1), arg2);
+}
+
+erlang*:::global-function-entry
+{
+ printf("pid %s enter (global) %s depth %d\n",
+ copyinstr(arg0), copyinstr(arg1), arg2);
+}
+
+erlang*:::function-return
+{
+ printf("pid %s return %s depth %d\n",
+ copyinstr(arg0), copyinstr(arg1), arg2);
+}
+
+erlang*:::bif-entry
+{
+ printf("pid %s BIF entry mfa %s\n", copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::bif-return
+{
+ printf("pid %s BIF return mfa %s\n", copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::nif-entry
+{
+ printf("pid %s NIF entry mfa %s\n", copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::nif-return
+{
+ printf("pid %s NIF return mfa %s\n", copyinstr(arg0), copyinstr(arg1));
+}
diff --git a/lib/runtime_tools/examples/function-calls.systemtap b/lib/runtime_tools/examples/function-calls.systemtap
new file mode 100644
index 0000000000..4de54cfb5a
--- /dev/null
+++ b/lib/runtime_tools/examples/function-calls.systemtap
@@ -0,0 +1,67 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("local-function-entry")
+{
+ printf("pid %s enter (local) %s depth %d\n",
+ user_string($arg1), user_string($arg2), $arg3);
+}
+
+probe process("beam").mark("global-function-entry")
+{
+ printf("pid %s enter (global) %s depth %d\n",
+ user_string($arg1), user_string($arg2), $arg3);
+}
+
+probe process("beam").mark("function-return")
+{
+ printf("pid %s return %s depth %d\n",
+ user_string($arg1), user_string($arg2), $arg3);
+}
+
+probe process("beam").mark("bif-entry")
+{
+ printf("pid %s BIF entry mfa %s\n", user_string($arg1), user_string($arg2));
+}
+
+probe process("beam").mark("bif-return")
+{
+ printf("pid %s BIF return mfa %s\n", user_string($arg1), user_string($arg2));
+}
+
+probe process("beam").mark("nif-entry")
+{
+ printf("pid %s NIF entry mfa %s\n", user_string($arg1), user_string($arg2));
+}
+
+probe process("beam").mark("nif-return")
+{
+ printf("pid %s NIF return mfa %s\n", user_string($arg1), user_string($arg2));
+}
diff --git a/lib/runtime_tools/examples/garbage-collection.d b/lib/runtime_tools/examples/garbage-collection.d
new file mode 100644
index 0000000000..ebc40a19ec
--- /dev/null
+++ b/lib/runtime_tools/examples/garbage-collection.d
@@ -0,0 +1,39 @@
+/* example usage: dtrace -q -s /path/to/garbage-collection.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::gc_major-start
+{
+ printf("GC major start pid %s need %d words\n", copyinstr(arg0), arg1);
+}
+
+erlang*:::gc_minor-start
+{
+ printf("GC minor start pid %s need %d words\n", copyinstr(arg0), arg1);
+}
+
+erlang*:::gc_major-end
+{
+ printf("GC major end pid %s reclaimed %d words\n", copyinstr(arg0), arg1);
+}
+
+erlang*:::gc_minor-start
+{
+ printf("GC minor end pid %s reclaimed %d words\n", copyinstr(arg0), arg1);
+}
diff --git a/lib/runtime_tools/examples/garbage-collection.systemtap b/lib/runtime_tools/examples/garbage-collection.systemtap
new file mode 100644
index 0000000000..81e9d38196
--- /dev/null
+++ b/lib/runtime_tools/examples/garbage-collection.systemtap
@@ -0,0 +1,49 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("gc_major-start")
+{
+ printf("GC major start pid %s need %d words\n", user_string($arg1), $arg2);
+}
+
+probe process("beam").mark("gc_minor-start")
+{
+ printf("GC minor start pid %s need %d words\n", user_string($arg1), $arg2);
+}
+
+probe process("beam").mark("gc_major-end")
+{
+ printf("GC major end pid %s reclaimed %d words\n", user_string($arg1), $arg2);
+}
+
+probe process("beam").mark("gc_minor-start")
+{
+ printf("GC minor end pid %s reclaimed %d words\n", user_string($arg1), $arg2);
+}
diff --git a/lib/runtime_tools/examples/memory1.d b/lib/runtime_tools/examples/memory1.d
new file mode 100644
index 0000000000..b222aeae62
--- /dev/null
+++ b/lib/runtime_tools/examples/memory1.d
@@ -0,0 +1,41 @@
+/* example usage: dtrace -q -s /path/to/memory1.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::copy-struct
+{
+ printf("copy_struct %d bytes\n", arg0);
+}
+
+erlang*:::copy-object
+{
+ printf("copy_object pid %s %d bytes\n", copyinstr(arg0), arg1);
+}
+
+erlang*:::process-heap_grow
+{
+ printf("proc heap grow pid %s %d -> %d bytes\n", copyinstr(arg0),
+ arg1, arg2);
+}
+
+erlang*:::process-heap_shrink
+{
+ printf("proc heap shrink pid %s %d -> %d bytes\n", copyinstr(arg0),
+ arg1, arg2);
+}
diff --git a/lib/runtime_tools/examples/memory1.systemtap b/lib/runtime_tools/examples/memory1.systemtap
new file mode 100644
index 0000000000..9374b97d18
--- /dev/null
+++ b/lib/runtime_tools/examples/memory1.systemtap
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("copy-struct")
+{
+ printf("copy_struct %d bytes\n", $arg1);
+}
+
+probe process("beam").mark("copy-object")
+{
+ printf("copy_object pid %s %d bytes\n", user_string($arg1), $arg2);
+}
+
+probe process("beam").mark("process-heap_grow")
+{
+ printf("proc heap grow pid %s %d -> %d bytes\n", user_string($arg1),
+ $arg2, $arg3);
+}
+
+probe process("beam").mark("process-heap_shrink")
+{
+ printf("proc heap shrink pid %s %d -> %d bytes\n", user_string($arg1),
+ $arg2, $arg3);
+}
diff --git a/lib/runtime_tools/examples/messages.d b/lib/runtime_tools/examples/messages.d
new file mode 100644
index 0000000000..08cf52f3d2
--- /dev/null
+++ b/lib/runtime_tools/examples/messages.d
@@ -0,0 +1,94 @@
+/* example usage: dtrace -q -s /path/to/messages.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+BEGIN
+{
+ printf("\n");
+ printf("NOTE: message-queue message size 4294967295 means an external\n");
+ printf(" message that the code isn't smart enough to determine\n");
+ printf(" the actual size.\n");
+ printf("\n");
+}
+
+erlang*:::message-send
+/arg3 == 0 && arg4 == 0 && arg5 == 0/
+{
+ printf("send: %s -> %s: %d words\n",
+ copyinstr(arg0), copyinstr(arg1), arg2);
+}
+
+erlang*:::message-send
+/arg3 != 0 || arg4 != 0 || arg5 != 0/
+{
+ printf("send: %s label %d token {%d,%d} -> %s: %d words\n",
+ copyinstr(arg0),
+ arg3, arg4, arg5,
+ copyinstr(arg1), arg2);
+}
+
+/*
+ * TODO:
+ * Weird, on my OS X box, beam says arg6 = 0 but this script says 4294967296.
+ */
+
+erlang*:::message-send-remote
+/arg4 == 0 && arg5 == 0 && (arg6 == 0 || arg6 >= 4294967296)/
+{
+ printf("send : %s -> %s %s: %d words\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+
+erlang*:::message-send-remote
+/arg4 != 0 || arg5 != 0 || arg6 < 4294967296/
+{
+ printf("send : %s label %d token {%d,%d} -> %s %s: %d words\n",
+ copyinstr(arg0),
+ arg4, arg5, arg6,
+ copyinstr(arg1), copyinstr(arg2), arg3);
+}
+
+erlang*:::message-queued
+/arg3 == 0 && arg4 == 0 && arg5 == 0/
+{
+ printf("queued: %s: %d words, queue len %d\n", copyinstr(arg0), arg1, arg2);
+}
+
+erlang*:::message-queued
+/arg3 != 0 || arg4 != 0 || arg5 != 0/
+{
+ printf("queued: %s label %d token {%d,%d}: %d words, queue len %d\n",
+ copyinstr(arg0), arg3, arg4, arg5,
+ arg1, arg2);
+}
+
+erlang*:::message-receive
+/arg3 == 0 && arg4 == 0 && arg5 == 0/
+{
+ printf("receive: %s: %d words, queue len %d\n",
+ copyinstr(arg0), arg1, arg2);
+}
+
+erlang*:::message-receive
+/arg3 != 0 || arg4 != 0 || arg5 != 0/
+{
+ printf("receive: %s label %d token {%d,%d}: %d words, queue len %d\n",
+ copyinstr(arg0), arg3, arg4, arg5,
+ arg1, arg2);
+}
diff --git a/lib/runtime_tools/examples/messages.systemtap b/lib/runtime_tools/examples/messages.systemtap
new file mode 100644
index 0000000000..c58e1168f9
--- /dev/null
+++ b/lib/runtime_tools/examples/messages.systemtap
@@ -0,0 +1,87 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe begin
+{
+ printf("\n");
+ printf("NOTE: message-queue message size 4294967295 means an external\n");
+ printf(" message that the code isn't smart enough to determine\n");
+ printf(" the actual size.\n");
+ printf("\n");
+}
+
+probe process("beam").mark("message-send")
+{
+ if ($arg4 == 0 && $arg5 == 0 && $arg6 == 0) {
+ printf("send: %s -> %s: %d words\n",
+ user_string($arg1), user_string($arg2), $arg3);
+ } else {
+ printf("send: %s label %d token {%d,%d} -> %s: %d words\n",
+ user_string($arg1),
+ $arg4, $arg5, $arg6,
+ user_string($arg2), $arg3);
+ }
+}
+
+probe process("beam").mark("message-send-remote")
+{
+ if ($arg5 == 0 && $arg6 == 0 && $arg7 == 0) {
+ printf("send : %s -> %s %s: %d words\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
+ } else {
+ printf("send : %s label %d token {%d,%d} -> %s %s: %d words\n",
+ user_string($arg1),
+ $arg5, $arg6, $arg7,
+ user_string($arg2), user_string($arg3), $arg4);
+ }
+}
+
+probe process("beam").mark("message-queued")
+{
+ if ($arg4 == 0 && $arg5 == 0 && $arg6 == 0) {
+ printf("queued: %s: %d words, queue len %d\n", user_string($arg1), $arg2, $arg3);
+ } else {
+ printf("queued: %s label %d token {%d,%d}: %d words, queue len %d\n",
+ user_string($arg1), $arg4, $arg5, $arg6,
+ $arg2, $arg3);
+ }
+}
+
+probe process("beam").mark("message-receive")
+{
+ if ($arg4 == 0 && $arg5 == 0 && $arg6 == 0) {
+ printf("receive: %s: %d words, queue len %d\n",
+ user_string($arg1), $arg2, $arg3);
+ } else {
+ printf("receive: %s label %d token {%d,%d}: %d words, queue len %d\n",
+ user_string($arg1), $arg4, $arg5, $arg6,
+ $arg2, $arg3);
+ }
+}
diff --git a/lib/runtime_tools/examples/port1.d b/lib/runtime_tools/examples/port1.d
new file mode 100644
index 0000000000..1e3bd3d8a9
--- /dev/null
+++ b/lib/runtime_tools/examples/port1.d
@@ -0,0 +1,142 @@
+/* example usage: dtrace -q -s /path/to/port1.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+BEGIN
+{
+ driver_map["tcp_inet", 1] = "OPEN";
+ driver_map["tcp_inet", 2] = "CLOSE";
+ driver_map["tcp_inet", 3] = "CONNECT";
+ driver_map["tcp_inet", 4] = "PEER";
+ driver_map["tcp_inet", 5] = "NAME";
+ driver_map["tcp_inet", 6] = "BIND";
+ driver_map["tcp_inet", 7] = "SETOPTS";
+ driver_map["tcp_inet", 8] = "GETOPTS";
+ driver_map["tcp_inet", 11] = "GETSTAT";
+ driver_map["tcp_inet", 12] = "GETHOSTNAME";
+ driver_map["tcp_inet", 13] = "FDOPEN";
+ driver_map["tcp_inet", 14] = "GETFD";
+ driver_map["tcp_inet", 15] = "GETTYPE";
+ driver_map["tcp_inet", 16] = "GETSTATUS";
+ driver_map["tcp_inet", 17] = "GETSERVBYNAME";
+ driver_map["tcp_inet", 18] = "GETSERVBYPORT";
+ driver_map["tcp_inet", 19] = "SETNAME";
+ driver_map["tcp_inet", 20] = "SETPEER";
+ driver_map["tcp_inet", 21] = "GETIFLIST";
+ driver_map["tcp_inet", 22] = "IFGET";
+ driver_map["tcp_inet", 23] = "IFSET";
+ driver_map["tcp_inet", 24] = "SUBSCRIBE";
+ driver_map["tcp_inet", 25] = "GETIFADDRS";
+ driver_map["tcp_inet", 40] = "ACCEPT";
+ driver_map["tcp_inet", 41] = "LISTEN";
+ driver_map["tcp_inet", 42] = "RECV";
+ driver_map["tcp_inet", 43] = "UNRECV";
+ driver_map["tcp_inet", 44] = "SHUTDOWN";
+ driver_map["tcp_inet", 60] = "RECV";
+ driver_map["tcp_inet", 61] = "LISTEN";
+ driver_map["tcp_inet", 62] = "BINDX";
+ /* No looping constructs, so repeat for udp_inet */
+ driver_map["udp_inet", 1] = "OPEN";
+ driver_map["udp_inet", 2] = "CLOSE";
+ driver_map["udp_inet", 3] = "CONNECT";
+ driver_map["udp_inet", 4] = "PEER";
+ driver_map["udp_inet", 5] = "NAME";
+ driver_map["udp_inet", 6] = "BIND";
+ driver_map["udp_inet", 7] = "SETOPTS";
+ driver_map["udp_inet", 8] = "GETOPTS";
+ driver_map["udp_inet", 11] = "GETSTAT";
+ driver_map["udp_inet", 12] = "GETHOSTNAME";
+ driver_map["udp_inet", 13] = "FDOPEN";
+ driver_map["udp_inet", 14] = "GETFD";
+ driver_map["udp_inet", 15] = "GETTYPE";
+ driver_map["udp_inet", 16] = "GETSTATUS";
+ driver_map["udp_inet", 17] = "GETSERVBYNAME";
+ driver_map["udp_inet", 18] = "GETSERVBYPORT";
+ driver_map["udp_inet", 19] = "SETNAME";
+ driver_map["udp_inet", 20] = "SETPEER";
+ driver_map["udp_inet", 21] = "GETIFLIST";
+ driver_map["udp_inet", 22] = "IFGET";
+ driver_map["udp_inet", 23] = "IFSET";
+ driver_map["udp_inet", 24] = "SUBSCRIBE";
+ driver_map["udp_inet", 25] = "GETIFADDRS";
+ driver_map["udp_inet", 40] = "ACCEPT";
+ driver_map["udp_inet", 41] = "LISTEN";
+ driver_map["udp_inet", 42] = "RECV";
+ driver_map["udp_inet", 43] = "UNRECV";
+ driver_map["udp_inet", 44] = "SHUTDOWN";
+ driver_map["udp_inet", 60] = "RECV";
+ driver_map["udp_inet", 61] = "LISTEN";
+ driver_map["udp_inet", 62] = "BINDX";
+}
+
+erlang*:::port-open
+{
+ printf("port open pid %s port name %s port %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::port-command
+{
+ printf("port command pid %s port %s port name %s command type %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
+}
+
+erlang*:::port-control
+{
+ /* http://dtrace.org/blogs/brendan/2011/11/25/dtrace-variable-types/ */
+ this->cmd = driver_map[copyinstr(arg2), arg3];
+ this->cmd_str = (this->cmd == 0) ? "unknown" : this->cmd;
+ printf("port control pid %s port %s port name %s command %d %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3,
+ this->cmd_str);
+}
+
+/* port-exit is fired as a result of port_close() or exit signal */
+
+erlang*:::port-exit
+{
+ printf("port exit pid %s port %s port name %s reason %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
+}
+
+erlang*:::port-connect
+{
+ printf("port connect pid %s port %s port name %s new pid %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
+}
+
+erlang*:::port-busy
+{
+ printf("port busy %s\n", copyinstr(arg0));
+}
+
+erlang*:::port-not_busy
+{
+ printf("port not busy %s\n", copyinstr(arg0));
+}
+
+erlang*:::aio_pool-add
+{
+ printf("async I/O pool add thread %d queue len %d\n", arg0, arg1);
+}
+
+erlang*:::aio_pool-get
+{
+ printf("async I/O pool get thread %d queue len %d\n", arg0, arg1);
+}
diff --git a/lib/runtime_tools/examples/port1.systemtap b/lib/runtime_tools/examples/port1.systemtap
new file mode 100644
index 0000000000..c8af240d85
--- /dev/null
+++ b/lib/runtime_tools/examples/port1.systemtap
@@ -0,0 +1,152 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe begin
+{
+ driver_map["tcp_inet", 1] = "OPEN";
+ driver_map["tcp_inet", 2] = "CLOSE";
+ driver_map["tcp_inet", 3] = "CONNECT";
+ driver_map["tcp_inet", 4] = "PEER";
+ driver_map["tcp_inet", 5] = "NAME";
+ driver_map["tcp_inet", 6] = "BIND";
+ driver_map["tcp_inet", 7] = "SETOPTS";
+ driver_map["tcp_inet", 8] = "GETOPTS";
+ driver_map["tcp_inet", 11] = "GETSTAT";
+ driver_map["tcp_inet", 12] = "GETHOSTNAME";
+ driver_map["tcp_inet", 13] = "FDOPEN";
+ driver_map["tcp_inet", 14] = "GETFD";
+ driver_map["tcp_inet", 15] = "GETTYPE";
+ driver_map["tcp_inet", 16] = "GETSTATUS";
+ driver_map["tcp_inet", 17] = "GETSERVBYNAME";
+ driver_map["tcp_inet", 18] = "GETSERVBYPORT";
+ driver_map["tcp_inet", 19] = "SETNAME";
+ driver_map["tcp_inet", 20] = "SETPEER";
+ driver_map["tcp_inet", 21] = "GETIFLIST";
+ driver_map["tcp_inet", 22] = "IFGET";
+ driver_map["tcp_inet", 23] = "IFSET";
+ driver_map["tcp_inet", 24] = "SUBSCRIBE";
+ driver_map["tcp_inet", 25] = "GETIFADDRS";
+ driver_map["tcp_inet", 40] = "ACCEPT";
+ driver_map["tcp_inet", 41] = "LISTEN";
+ driver_map["tcp_inet", 42] = "RECV";
+ driver_map["tcp_inet", 43] = "UNRECV";
+ driver_map["tcp_inet", 44] = "SHUTDOWN";
+ driver_map["tcp_inet", 60] = "RECV";
+ driver_map["tcp_inet", 61] = "LISTEN";
+ driver_map["tcp_inet", 62] = "BINDX";
+ /* No looping constructs, so repeat for udp_inet */
+ driver_map["udp_inet", 1] = "OPEN";
+ driver_map["udp_inet", 2] = "CLOSE";
+ driver_map["udp_inet", 3] = "CONNECT";
+ driver_map["udp_inet", 4] = "PEER";
+ driver_map["udp_inet", 5] = "NAME";
+ driver_map["udp_inet", 6] = "BIND";
+ driver_map["udp_inet", 7] = "SETOPTS";
+ driver_map["udp_inet", 8] = "GETOPTS";
+ driver_map["udp_inet", 11] = "GETSTAT";
+ driver_map["udp_inet", 12] = "GETHOSTNAME";
+ driver_map["udp_inet", 13] = "FDOPEN";
+ driver_map["udp_inet", 14] = "GETFD";
+ driver_map["udp_inet", 15] = "GETTYPE";
+ driver_map["udp_inet", 16] = "GETSTATUS";
+ driver_map["udp_inet", 17] = "GETSERVBYNAME";
+ driver_map["udp_inet", 18] = "GETSERVBYPORT";
+ driver_map["udp_inet", 19] = "SETNAME";
+ driver_map["udp_inet", 20] = "SETPEER";
+ driver_map["udp_inet", 21] = "GETIFLIST";
+ driver_map["udp_inet", 22] = "IFGET";
+ driver_map["udp_inet", 23] = "IFSET";
+ driver_map["udp_inet", 24] = "SUBSCRIBE";
+ driver_map["udp_inet", 25] = "GETIFADDRS";
+ driver_map["udp_inet", 40] = "ACCEPT";
+ driver_map["udp_inet", 41] = "LISTEN";
+ driver_map["udp_inet", 42] = "RECV";
+ driver_map["udp_inet", 43] = "UNRECV";
+ driver_map["udp_inet", 44] = "SHUTDOWN";
+ driver_map["udp_inet", 60] = "RECV";
+ driver_map["udp_inet", 61] = "LISTEN";
+ driver_map["udp_inet", 62] = "BINDX";
+}
+
+probe process("beam").mark("port-open")
+{
+ printf("port open pid %s port name %s port %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("port-command")
+{
+ printf("port command pid %s port %s port name %s command type %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
+}
+
+probe process("beam").mark("port-control")
+{
+ cmd = driver_map[user_string($arg3), $arg4];
+ cmd_str = (cmd == "") ? "unknown" : cmd;
+ printf("port control pid %s port %s port name %s command %d %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), $arg4, cmd_str);
+}
+
+/* port-exit is fired as a result of port_close() or exit signal */
+
+probe process("beam").mark("port-exit")
+{
+ printf("port exit pid %s port %s port name %s reason %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
+}
+
+probe process("beam").mark("port-connect")
+{
+ printf("port connect pid %s port %s port name %s new pid %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
+}
+
+probe process("beam").mark("port-busy")
+{
+ printf("port busy %s\n", user_string($arg1));
+}
+
+probe process("beam").mark("port-not_busy")
+{
+ printf("port not busy %s\n", user_string($arg1));
+}
+
+probe process("beam").mark("aio_pool-add")
+{
+ printf("async I/O pool add thread %d queue len %d\n", $arg1, $arg2);
+}
+
+probe process("beam").mark("aio_pool-get")
+{
+ printf("async I/O pool get thread %d queue len %d\n", $arg1, $arg2);
+}
+
+global driver_map; \ No newline at end of file
diff --git a/lib/runtime_tools/examples/process-scheduling.d b/lib/runtime_tools/examples/process-scheduling.d
new file mode 100644
index 0000000000..6408d7d5f2
--- /dev/null
+++ b/lib/runtime_tools/examples/process-scheduling.d
@@ -0,0 +1,35 @@
+/* example usage: dtrace -q -s /path/to/process-scheduling.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::process-scheduled
+{
+ printf(" Schedule pid %s mfa %s\n", copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::process-unscheduled
+{
+ printf("Unschedule pid %s\n", copyinstr(arg0));
+}
+
+erlang*:::process-hibernate
+{
+ printf(" Hibernate pid %s resume mfa %s\n",
+ copyinstr(arg0), copyinstr(arg1));
+}
diff --git a/lib/runtime_tools/examples/process-scheduling.systemtap b/lib/runtime_tools/examples/process-scheduling.systemtap
new file mode 100644
index 0000000000..4cc3ef555c
--- /dev/null
+++ b/lib/runtime_tools/examples/process-scheduling.systemtap
@@ -0,0 +1,45 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("process-scheduled")
+{
+ printf(" Schedule pid %s mfa %s\n", user_string($arg1), user_string($arg2));
+}
+
+probe process("beam").mark("process-unscheduled")
+{
+ printf("Unschedule pid %s\n", user_string($arg1));
+}
+
+probe process("beam").mark("process-hibernate")
+{
+ printf(" Hibernate pid %s resume mfa %s\n",
+ user_string($arg1), user_string($arg2));
+}
diff --git a/lib/runtime_tools/examples/spawn-exit.d b/lib/runtime_tools/examples/spawn-exit.d
new file mode 100644
index 0000000000..ae690b819a
--- /dev/null
+++ b/lib/runtime_tools/examples/spawn-exit.d
@@ -0,0 +1,41 @@
+/* example usage: dtrace -q -s /path/to/spawn-exit.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::process-spawn
+{
+ printf("pid %s mfa %s\n", copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::process-exit
+{
+ printf("pid %s reason %s\n", copyinstr(arg0), copyinstr(arg1));
+}
+
+erlang*:::process-exit_signal
+{
+ printf("sender %s -> pid %s reason %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2));
+}
+
+erlang*:::process-exit_signal-remote
+{
+ printf("sender %s -> node %s pid %s reason %s\n",
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
+}
diff --git a/lib/runtime_tools/examples/spawn-exit.systemtap b/lib/runtime_tools/examples/spawn-exit.systemtap
new file mode 100644
index 0000000000..4b69e4aea6
--- /dev/null
+++ b/lib/runtime_tools/examples/spawn-exit.systemtap
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("process-spawn")
+{
+ printf("pid %s mfa %s\n", user_string($arg1), user_string($arg2));
+}
+
+probe process("beam").mark("process-exit")
+{
+ printf("pid %s reason %s\n", user_string($arg1), user_string($arg2));
+}
+
+probe process("beam").mark("process-exit_signal")
+{
+ printf("sender %s -> pid %s reason %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3));
+}
+
+probe process("beam").mark("process-exit_signal-remote")
+{
+ printf("sender %s -> node %s pid %s reason %s\n",
+ user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
+}
diff --git a/lib/runtime_tools/examples/user-probe-n.d b/lib/runtime_tools/examples/user-probe-n.d
new file mode 100644
index 0000000000..06a3e5c9b9
--- /dev/null
+++ b/lib/runtime_tools/examples/user-probe-n.d
@@ -0,0 +1,44 @@
+/* example usage: dtrace -q -s /path/to/user-probe.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::user_trace-n0
+{
+ printf("probe n0: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
+ copyinstr(arg0),
+ arg1 == NULL ? "" : copyinstr(arg1),
+ arg2, arg3, arg4, arg5,
+ arg6 == NULL ? "" : copyinstr(arg6),
+ arg7 == NULL ? "" : copyinstr(arg7),
+ arg8 == NULL ? "" : copyinstr(arg8),
+ arg9 == NULL ? "" : copyinstr(arg9));
+}
+
+erlang*:::user_trace-n1
+{
+ printf("probe n1: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
+ copyinstr(arg0),
+ arg1 == NULL ? "" : copyinstr(arg1),
+ arg2, arg3, arg4, arg5,
+ arg6 == NULL ? "" : copyinstr(arg6),
+ arg7 == NULL ? "" : copyinstr(arg7),
+ arg8 == NULL ? "" : copyinstr(arg8),
+ arg9 == NULL ? "" : copyinstr(arg9));
+}
+
diff --git a/lib/runtime_tools/examples/user-probe-n.systemtap b/lib/runtime_tools/examples/user-probe-n.systemtap
new file mode 100644
index 0000000000..6aa415bb67
--- /dev/null
+++ b/lib/runtime_tools/examples/user-probe-n.systemtap
@@ -0,0 +1,53 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("user_trace-n0")
+{
+ printf("probe n0: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
+ user_string($arg1),
+ $arg2 == NULL ? "" : user_string($arg2),
+ $arg3, $arg4, $arg5, $arg6,
+ $arg7 == NULL ? "" : user_string($arg7),
+ $arg8 == NULL ? "" : user_string($arg8),
+ $arg9 == NULL ? "" : user_string($arg9),
+ $arg9 == NULL ? "" : user_string($arg9));
+}
+
+probe process("beam").mark("user_trace-n1")
+{
+ printf("probe n1: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
+ user_string($arg1),
+ $arg2 == NULL ? "" : user_string($arg2),
+ $arg3, $arg4, $arg5, $arg6,
+ $arg7 == NULL ? "" : user_string($arg7),
+ $arg8 == NULL ? "" : user_string($arg8),
+ $arg9 == NULL ? "" : user_string($arg9),
+ $arg9 == NULL ? "" : user_string($arg9));
+}
diff --git a/lib/runtime_tools/examples/user-probe.d b/lib/runtime_tools/examples/user-probe.d
new file mode 100644
index 0000000000..5cb5d61a76
--- /dev/null
+++ b/lib/runtime_tools/examples/user-probe.d
@@ -0,0 +1,36 @@
+/* example usage: dtrace -q -s /path/to/user-probe.d */
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+erlang*:::user_trace-s1
+{
+ printf("%s\n", copyinstr(arg0));
+}
+
+erlang*:::user_trace-i4s4
+{
+ printf("%s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
+ copyinstr(arg0),
+ arg1 == NULL ? "" : copyinstr(arg1),
+ arg2, arg3, arg4, arg5,
+ arg6 == NULL ? "" : copyinstr(arg6),
+ arg7 == NULL ? "" : copyinstr(arg7),
+ arg8 == NULL ? "" : copyinstr(arg8),
+ arg9 == NULL ? "" : copyinstr(arg9));
+}
diff --git a/lib/runtime_tools/examples/user-probe.systemtap b/lib/runtime_tools/examples/user-probe.systemtap
new file mode 100644
index 0000000000..0482235324
--- /dev/null
+++ b/lib/runtime_tools/examples/user-probe.systemtap
@@ -0,0 +1,46 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Note: This file assumes that you're using the non-SMP-enabled Erlang
+ * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note that other variations of the virtual machine also have
+ * different names, e.g. the debug build of the SMP-enabled VM
+ * is "beam.debug.smp".
+ *
+ * To use a different virtual machine, replace each instance of
+ * "beam" with "beam.smp" or the VM name appropriate to your
+ * environment.
+ */
+
+probe process("beam").mark("user_trace-s1")
+{
+ printf("%s\n", user_string($arg1));
+}
+
+probe process("beam").mark("user_trace-i4s4")
+{
+ printf("%s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
+ user_string($arg1),
+ $arg2 == NULL ? "" : user_string($arg2),
+ $arg3, $arg4, $arg5, $arg6,
+ $arg7 == NULL ? "" : user_string($arg7),
+ $arg8 == NULL ? "" : user_string($arg8),
+ $arg9 == NULL ? "" : user_string($arg9),
+ $arg9 == NULL ? "" : user_string($arg9));
+}
diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile
index 46b570210a..810e3e8741 100644
--- a/lib/runtime_tools/src/Makefile
+++ b/lib/runtime_tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
+# Copyright Ericsson AB 1999-2012. All Rights Reserved.
#
# The 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,7 @@ MODULES= \
runtime_tools \
runtime_tools_sup \
dbg \
+ dyntrace \
percept_profile \
observer_backend \
ttb_autostart
@@ -64,10 +65,15 @@ APPUP_FILE= runtime_tools.appup
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+EXAMPLE_FILES= \
+ ../examples/*
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -I../include
+ERL_COMPILE_FLAGS += \
+ -I../include \
+ -I ../../et/include \
+ -I ../../../libraries/et/include
# ----------------------------------------------------
# Targets
@@ -93,12 +99,14 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(EXAMPLE_FILES) "$(RELSYSDIR)/examples"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index 446de63064..385047ee73 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.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
@@ -32,7 +32,7 @@
-export([fun2ms/1]).
%% Local exports
--export([erlang_trace/3,get_info/0]).
+-export([erlang_trace/3,get_info/0,deliver_and_flush/1]).
%% Debug exports
-export([wrap_presort/2, wrap_sort/2, wrap_postsort/1, wrap_sortfix/2,
@@ -348,17 +348,16 @@ trace_port_control(Operation) ->
trace_port_control(node(), Operation).
trace_port_control(Node, flush) ->
- Ref = erlang:trace_delivered(all),
- receive
- {trace_delivered,all,Ref} -> ok
- end,
- case trace_port_control(Node, $f, "") of
- {ok, [0]} ->
- ok;
- {ok, _} ->
- {error, not_supported_by_trace_driver};
- Other ->
- Other
+ case get_tracer(Node) of
+ {ok, Port} when is_port(Port) ->
+ case catch rpc:call(Node,?MODULE,deliver_and_flush,[Port]) of
+ [0] ->
+ ok;
+ _ ->
+ {error, not_supported_by_trace_driver}
+ end;
+ _ ->
+ {error, no_trace_driver}
end;
trace_port_control(Node,get_listen_port) ->
case trace_port_control(Node,$p, "") of
@@ -378,7 +377,14 @@ trace_port_control(Node, Command, Arg) ->
{error, no_trace_driver}
end.
-
+%% A bit more than just flush - it also makes sure all trace messages
+%% are delivered first, before flushing the driver.
+deliver_and_flush(Port) ->
+ Ref = erlang:trace_delivered(all),
+ receive
+ {trace_delivered,all,Ref} -> ok
+ end,
+ erlang:port_control(Port, $f, "").
trace_port(file, {Filename, wrap, Tail}) ->
@@ -684,18 +690,12 @@ loop({C,T}=SurviveLinks, Table) ->
%% tracing on the node it removes from the list of active trace nodes,
%% we will call erlang:trace_delivered/1 on ALL nodes that we have
%% connections to.
- Delivered = fun() ->
- Ref = erlang:trace_delivered(all),
- receive
- {trace_delivered,all,Ref} -> ok
- end
- end,
- catch rpc:multicall(nodes(), erlang, apply, [Delivered,[]]),
- Ref = erlang:trace_delivered(all),
- receive
- {trace_delivered,all,Ref} ->
- exit(done)
- end;
+ %% If it is a file trace driver, we will also flush the port.
+ lists:foreach(fun({Node,{_Relay,Port}}) ->
+ rpc:call(Node,?MODULE,deliver_and_flush,[Port])
+ end,
+ get()),
+ exit(done);
{From, {link_to, Pid}} ->
case (catch link(Pid)) of
{'EXIT', Reason} ->
diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl
new file mode 100644
index 0000000000..b4579fd5ce
--- /dev/null
+++ b/lib/runtime_tools/src/dyntrace.erl
@@ -0,0 +1,352 @@
+-module(dyntrace).
+
+%%% @doc The Dynamic tracing interface module
+%%%
+%%% This Dynamic tracing interface module, with the corresponding NIFs, should
+%%% work on any operating system platform where user-space DTrace/Systemtap
+%%% (and in the future LttNG UST) probes are supported.
+%%%
+%%% It is recommended that you use the `dyntrace:p()' function to add
+%%% Dynamic trace probes to your Erlang code. This function can accept up to
+%%% four integer arguments and four string arguments; the integer
+%%% argument(s) must come before any string argument.
+%%%
+%%% If using DTrace, enable the dynamic trace probe using the 'dtrace'
+%%% command, for example:
+%%%
+%%% dtrace -s /your/path/to/lib/runtime_tools-1.8.7/examples/user-probe.d
+%%%
+%%% Then, back at the Erlang shell, try this example:
+%%% ```
+%%% 1> dyntrace:put_tag("GGOOOAAALL!!!!!").
+%%% true
+%%%
+%%% 2> dyntrace:p(7, 8, 9, "one", "four").
+%%% true
+%%% '''
+%%%
+%%% Output from the example D script `user-probe.d' looks like:
+%%% ```
+%%% <0.34.0> GGOOOAAALL!!!!! 7 8 9 0 'one' 'four' '' ''
+%%% '''
+%%%
+%%% If the expected type of variable is not present, e.g. integer when
+%%% integer() is expected, or an I/O list when iolist() is expected,
+%%% then the driver will ignore the user's input and use a default
+%%% value of 0 or NULL, respectively.
+
+-export([available/0,
+ user_trace_s1/1, % TODO: unify with pid & tag args like user_trace_i4s4
+ p/0, p/1, p/2, p/3, p/4, p/5, p/6, p/7, p/8,
+ pn/1, pn/2, pn/3, pn/4, pn/5, pn/6, pn/7, pn/8, pn/9]).
+-export([put_tag/1, get_tag/0, get_tag_data/0, spread_tag/1, restore_tag/1]).
+
+-export([user_trace_i4s4/9]). % Know what you're doing!
+-on_load(on_load/0).
+
+-type probe_arg() :: integer() | iolist().
+-type int_p_arg() :: integer() | iolist() | undef.
+-type n_probe_label() :: 0..1023.
+
+%% The *_maybe() types use atom() instead of a stricter 'undef'
+%% because user_trace_i4s4/9 is exposed to the outside world, and
+%% because the driver will allow any atom to be used as a "not
+%% present" indication, we'll allow any atom in the types.
+
+-type integer_maybe() :: integer() | atom().
+-type iolist_maybe() :: iolist() | atom().
+
+on_load() ->
+ PrivDir = code:priv_dir(runtime_tools),
+ LibName = "dyntrace",
+ Lib = filename:join([PrivDir, "lib", LibName]),
+ Status = case erlang:load_nif(Lib, 0) 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, 0)
+ end;
+ Error1 -> Error1
+ end,
+ case Status of
+ ok -> ok;
+ {error, {E, Str}} ->
+ case erlang:system_info(dynamic_trace) of
+ none ->
+ ok;
+ _ ->
+ error_logger:error_msg("Unable to load dyntrace library. Failed with error:~n
+\"~p, ~s\"~n"
+ "Dynamic tracing is enabled but the driver is not built correctly~n",[
+ E,Str]),
+ Status
+ end
+ end.
+
+%%%
+%%% NIF placeholders
+%%%
+
+-spec available() -> true | false.
+
+available() ->
+ erlang:nif_error(nif_not_loaded).
+
+-spec user_trace_s1(iolist()) -> true | false | error | badarg.
+
+user_trace_s1(_Message) ->
+ erlang:nif_error(nif_not_loaded).
+
+-spec user_trace_i4s4(iolist(),
+ integer_maybe(), integer_maybe(),
+ integer_maybe(), integer_maybe(),
+ iolist_maybe(), iolist_maybe(),
+ iolist_maybe(), iolist_maybe()) ->
+ true | false | error | badarg.
+
+user_trace_i4s4(_, _, _, _, _, _, _, _, _) ->
+ erlang:nif_error(nif_not_loaded).
+
+-spec user_trace_n(n_probe_label(), iolist(),
+ integer_maybe(), integer_maybe(),
+ integer_maybe(), integer_maybe(),
+ iolist_maybe(), iolist_maybe(),
+ iolist_maybe(), iolist_maybe()) ->
+ true | false | error | badarg.
+
+user_trace_n(_, _, _, _, _, _, _, _, _, _) ->
+ erlang:nif_error(nif_not_loaded).
+
+%%%
+%%% Erlang support functions
+%%%
+
+-spec p() -> true | false | error | badarg.
+
+p() ->
+ user_trace_int(undef, undef, undef, undef, undef, undef, undef, undef).
+
+-spec p(probe_arg()) -> true | false | error | badarg.
+
+p(I1) when is_integer(I1) ->
+ user_trace_int(I1, undef, undef, undef, undef, undef, undef, undef);
+p(S1) ->
+ user_trace_int(undef, undef, undef, undef, S1, undef, undef, undef).
+
+-spec p(probe_arg(), probe_arg()) -> true | false | error | badarg.
+
+p(I1, I2) when is_integer(I1), is_integer(I2) ->
+ user_trace_int(I1, I2, undef, undef, undef, undef, undef, undef);
+p(I1, S1) when is_integer(I1) ->
+ user_trace_int(I1, undef, undef, undef, S1, undef, undef, undef);
+p(S1, S2) ->
+ user_trace_int(undef, undef, undef, undef, S1, S2, undef, undef).
+
+-spec p(probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
+
+p(I1, I2, I3) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_int(I1, I2, I3, undef, undef, undef, undef, undef);
+p(I1, I2, S1) when is_integer(I1), is_integer(I2) ->
+ user_trace_int(I1, I2, undef, undef, S1, undef, undef, undef);
+p(I1, S1, S2) when is_integer(I1) ->
+ user_trace_int(I1, undef, undef, undef, S1, S2, undef, undef);
+p(S1, S2, S3) ->
+ user_trace_int(undef, undef, undef, undef, S1, S2, S3, undef).
+
+-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+p(I1, I2, I3, I4) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_int(I1, I2, I3, I4, undef, undef, undef, undef);
+p(I1, I2, I3, S1) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_int(I1, I2, I3, undef, S1, undef, undef, undef);
+p(I1, I2, S1, S2) when is_integer(I1), is_integer(I2) ->
+ user_trace_int(I1, I2, undef, undef, S1, S2, undef, undef);
+p(I1, S1, S2, S3) when is_integer(I1) ->
+ user_trace_int(I1, undef, undef, undef, S1, S2, S3, undef);
+p(S1, S2, S3, S4) ->
+ user_trace_int(undef, undef, undef, undef, S1, S2, S3, S4).
+
+-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg()) ->
+ true | false | error | badarg.
+
+p(I1, I2, I3, I4, S1) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_int(I1, I2, I3, I4, S1, undef, undef, undef);
+p(I1, I2, I3, S1, S2) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_int(I1, I2, I3, undef, S1, S2, undef, undef);
+p(I1, I2, S1, S2, S3) when is_integer(I1), is_integer(I2) ->
+ user_trace_int(I1, I2, undef, undef, S1, S2, S3, undef);
+p(I1, S1, S2, S3, S4) when is_integer(I1) ->
+ user_trace_int(I1, undef, undef, undef, S1, S2, S3, S4).
+
+-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+p(I1, I2, I3, I4, S1, S2) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_int(I1, I2, I3, I4, S1, S2, undef, undef);
+p(I1, I2, I3, S1, S2, S3) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_int(I1, I2, I3, undef, S1, S2, S3, undef);
+p(I1, I2, S1, S2, S3, S4) when is_integer(I1), is_integer(I2) ->
+ user_trace_int(I1, I2, undef, undef, S1, S2, S3, S4).
+
+-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg(), probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+p(I1, I2, I3, I4, S1, S2, S3) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_int(I1, I2, I3, I4, S1, S2, S3, undef);
+p(I1, I2, I3, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_int(I1, I2, I3, undef, S1, S2, S3, S4).
+
+-spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+p(I1, I2, I3, I4, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_int(I1, I2, I3, I4, S1, S2, S3, S4).
+
+-spec user_trace_int(int_p_arg(), int_p_arg(), int_p_arg(), int_p_arg(),
+ int_p_arg(), int_p_arg(), int_p_arg(), int_p_arg()) ->
+ true | false | error | badarg.
+
+user_trace_int(I1, I2, I3, I4, S1, S2, S3, S4) ->
+ UTag = get_tag(),
+ try
+ user_trace_i4s4(UTag, I1, I2, I3, I4, S1, S2, S3, S4)
+ catch
+ error:nif_not_loaded ->
+ false
+ end.
+
+-spec pn(n_probe_label()) -> true | false | error | badarg.
+
+pn(ProbeLabel) ->
+ user_trace_n_int(ProbeLabel, undef, undef, undef, undef, undef, undef, undef, undef).
+
+-spec pn(n_probe_label(), probe_arg()) -> true | false | error | badarg.
+
+pn(ProbeLabel, I1) when is_integer(I1) ->
+ user_trace_n_int(ProbeLabel, I1, undef, undef, undef, undef, undef, undef, undef);
+pn(ProbeLabel, S1) ->
+ user_trace_n_int(ProbeLabel, undef, undef, undef, undef, S1, undef, undef, undef).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg()) -> true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2) when is_integer(I1), is_integer(I2) ->
+ user_trace_n_int(ProbeLabel, I1, I2, undef, undef, undef, undef, undef, undef);
+pn(ProbeLabel, I1, S1) when is_integer(I1) ->
+ user_trace_n_int(ProbeLabel, I1, undef, undef, undef, S1, undef, undef, undef);
+pn(ProbeLabel, S1, S2) ->
+ user_trace_n_int(ProbeLabel, undef, undef, undef, undef, S1, S2, undef, undef).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2, I3) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, undef, undef, undef, undef, undef);
+pn(ProbeLabel, I1, I2, S1) when is_integer(I1), is_integer(I2) ->
+ user_trace_n_int(ProbeLabel, I1, I2, undef, undef, S1, undef, undef, undef);
+pn(ProbeLabel, I1, S1, S2) when is_integer(I1) ->
+ user_trace_n_int(ProbeLabel, I1, undef, undef, undef, S1, S2, undef, undef);
+pn(ProbeLabel, S1, S2, S3) ->
+ user_trace_n_int(ProbeLabel, undef, undef, undef, undef, S1, S2, S3, undef).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2, I3, I4) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, I4, undef, undef, undef, undef);
+pn(ProbeLabel, I1, I2, I3, S1) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, undef, S1, undef, undef, undef);
+pn(ProbeLabel, I1, I2, S1, S2) when is_integer(I1), is_integer(I2) ->
+ user_trace_n_int(ProbeLabel, I1, I2, undef, undef, S1, S2, undef, undef);
+pn(ProbeLabel, I1, S1, S2, S3) when is_integer(I1) ->
+ user_trace_n_int(ProbeLabel, I1, undef, undef, undef, S1, S2, S3, undef);
+pn(ProbeLabel, S1, S2, S3, S4) ->
+ user_trace_n_int(ProbeLabel, undef, undef, undef, undef, S1, S2, S3, S4).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg()) ->
+ true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2, I3, I4, S1) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, I4, S1, undef, undef, undef);
+pn(ProbeLabel, I1, I2, I3, S1, S2) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, undef, S1, S2, undef, undef);
+pn(ProbeLabel, I1, I2, S1, S2, S3) when is_integer(I1), is_integer(I2) ->
+ user_trace_n_int(ProbeLabel, I1, I2, undef, undef, S1, S2, S3, undef);
+pn(ProbeLabel, I1, S1, S2, S3, S4) when is_integer(I1) ->
+ user_trace_n_int(ProbeLabel, I1, undef, undef, undef, S1, S2, S3, S4).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2, I3, I4, S1, S2) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, I4, S1, S2, undef, undef);
+pn(ProbeLabel, I1, I2, I3, S1, S2, S3) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, undef, S1, S2, S3, undef);
+pn(ProbeLabel, I1, I2, S1, S2, S3, S4) when is_integer(I1), is_integer(I2) ->
+ user_trace_n_int(ProbeLabel, I1, I2, undef, undef, S1, S2, S3, S4).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg(), probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2, I3, I4, S1, S2, S3) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, I4, S1, S2, S3, undef);
+pn(ProbeLabel, I1, I2, I3, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_integer(I3) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, undef, S1, S2, S3, S4).
+
+-spec pn(n_probe_label(), probe_arg(), probe_arg(), probe_arg(), probe_arg(),
+ probe_arg(), probe_arg(), probe_arg(), probe_arg()) ->
+ true | false | error | badarg.
+
+pn(ProbeLabel, I1, I2, I3, I4, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) ->
+ user_trace_n_int(ProbeLabel, I1, I2, I3, I4, S1, S2, S3, S4).
+
+-spec user_trace_n_int(n_probe_label(),
+ int_p_arg(), int_p_arg(), int_p_arg(), int_p_arg(),
+ int_p_arg(), int_p_arg(), int_p_arg(), int_p_arg()) ->
+ true | false | error | badarg.
+
+user_trace_n_int(ProbeLabel, I1, I2, I3, I4, S1, S2, S3, S4) ->
+ UTag = get_tag(),
+ try
+ user_trace_n(ProbeLabel, UTag, I1, I2, I3, I4, S1, S2, S3, S4)
+ catch
+ error:nif_not_loaded ->
+ false
+ end.
+
+-spec put_tag(undefined | iodata()) -> binary() | undefined.
+put_tag(Data) ->
+ erlang:dt_put_tag(unicode:characters_to_binary(Data)).
+
+-spec get_tag() -> binary() | undefined.
+get_tag() ->
+ erlang:dt_get_tag().
+
+-spec get_tag_data() -> binary() | undefined.
+%% Gets tag if set, otherwise the spread tag data from last incoming message
+get_tag_data() ->
+ erlang:dt_get_tag_data().
+
+-spec spread_tag(boolean()) -> true | {non_neg_integer(), binary() | []}.
+%% Makes the tag behave as a sequential trace token, will spread with
+%% messages to be picked up by someone using get_tag_data
+spread_tag(B) ->
+ erlang:dt_spread_tag(B).
+
+-spec restore_tag(true | {non_neg_integer(), binary() | []}) -> true.
+restore_tag(T) ->
+ erlang:dt_restore_tag(T).
diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl
index 0bcb202fd8..284e88d4a7 100644
--- a/lib/runtime_tools/src/erts_alloc_config.erl
+++ b/lib/runtime_tools/src/erts_alloc_config.erl
@@ -1,6 +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
@@ -16,6 +17,7 @@
%% The Initial Developer of the Original Code is Ericsson AB.
%%
%% %CopyrightEnd%
+%%
%%%-------------------------------------------------------------------
%%% File : erts_alloc_config.erl
@@ -71,6 +73,7 @@
A == binary_alloc;
A == std_alloc;
A == ets_alloc;
+ A == fix_alloc;
A == eheap_alloc;
A == ll_alloc;
A == sl_alloc;
@@ -94,6 +97,7 @@
[{binary_alloc, 131072},
{std_alloc, 131072},
{ets_alloc, 131072},
+ {fix_alloc, 131072},
{eheap_alloc, 524288},
{ll_alloc, 2097152},
{sl_alloc, 131072},
@@ -104,6 +108,7 @@
[{binary_alloc, 10},
{std_alloc, 10},
{ets_alloc, 10},
+ {fix_alloc, 10},
{eheap_alloc, 10},
{ll_alloc, 0},
{sl_alloc, 10},
@@ -438,9 +443,6 @@ conf_alloc(#conf{format_to = FTO} = Conf, #alloc{name = A} = Alc) ->
chk_xnote(Conf, Alc).
chk_xnote(#conf{format_to = FTO},
- #alloc{name = fix_alloc}) ->
- fcp(FTO, "Cannot be configured.");
-chk_xnote(#conf{format_to = FTO},
#alloc{name = sys_alloc}) ->
fcp(FTO, "Cannot be configured. Default malloc implementation used.");
chk_xnote(#conf{format_to = FTO},
@@ -470,7 +472,7 @@ au_conf_alloc(#conf{format_to = FTO} = Conf,
_ ->
fc(FTO, "~p instances used.",
[Insts]),
- format(FTO, " +M~ct ~p~n", [alloc_char(A), Insts])
+ format(FTO, " +M~ct true~n", [alloc_char(A)])
end,
mmbcs(Conf, Alc),
smbcs_lmbcs_mmmbc(Conf, Alc),
diff --git a/lib/runtime_tools/src/inviso_rt.erl b/lib/runtime_tools/src/inviso_rt.erl
index ac7ac2a584..b162f5b045 100644
--- a/lib/runtime_tools/src/inviso_rt.erl
+++ b/lib/runtime_tools/src/inviso_rt.erl
@@ -2359,8 +2359,8 @@ list_wrapset(Prefix,Suffix) ->
list_wrapset_2([File|Rest],RegExp) ->
Length=length(File),
- case regexp:first_match(File,RegExp) of
- {match,1,Length} -> % This is a member of the set.
+ case re:run(File,RegExp) of
+ {match,[{0,Length}]} -> % This is a member of the set.
[File|list_wrapset_2(Rest,RegExp)];
_ ->
list_wrapset_2(Rest,RegExp)
diff --git a/lib/runtime_tools/src/inviso_rt_lib.erl b/lib/runtime_tools/src/inviso_rt_lib.erl
index 2c6964e53e..5dfe14068a 100644
--- a/lib/runtime_tools/src/inviso_rt_lib.erl
+++ b/lib/runtime_tools/src/inviso_rt_lib.erl
@@ -1,7 +1,7 @@
%%
%% %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
@@ -197,15 +197,15 @@ match_modules(RegExpDir,RegExpMod,Actions) ->
handle_expand_regexp_2([{Mod,Path}|Rest],RegExpDir,RegExpMod,Result) ->
ModStr=atom_to_list(Mod),
ModLen=length(ModStr),
- case regexp:first_match(ModStr,RegExpMod) of
- {match,1,ModLen} -> % Ok, The regexp matches the module.
+ case re:run(ModStr,RegExpMod) of
+ {match,[{0,ModLen}]} -> % Ok, The regexp matches the module.
if
is_list(RegExpDir),is_atom(Path) -> % Preloaded or covercompiled...
handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result);
is_list(RegExpDir),is_list(Path) -> % Dir reg-exp is used!
PathOnly=filename:dirname(Path), % Must remove beam-file name.
- case regexp:first_match(PathOnly,RegExpDir) of
- {match,_,_} -> % Did find a match, that is enough!
+ case re:run(PathOnly,RegExpDir,[{capture,none}]) of
+ match -> % Did find a match, that is enough!
handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,[Mod|Result]);
_ -> % Either error or nomatch.
handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result)
@@ -233,8 +233,8 @@ handle_expand_regexp_3([Path|Rest],RegExpDir,RegExpMod,AllLoaded,Result) ->
volumerelative -> % Only on Windows!?
filename:absname(Path)
end,
- case regexp:first_match(AbsPath,RegExpDir) of
- {match,_,_} -> % Ok, the directory is allowed.
+ case re:run(AbsPath,RegExpDir,[{capture,none}]) of
+ match -> % Ok, the directory is allowed.
NewResult=handle_expand_regexp_3_1(Path,RegExpMod,AllLoaded,Result),
handle_expand_regexp_3(Rest,RegExpDir,RegExpMod,AllLoaded,NewResult);
_ -> % This directory does not qualify.
@@ -262,8 +262,8 @@ handle_expand_regexp_3_2([File|Rest],RegExpMod,AllLoaded,Result) ->
case {lists:keysearch(Mod,1,AllLoaded),lists:member(Mod,Result)} of
{false,false} -> % This module is not tried before.
ModLen=length(ModStr),
- case regexp:first_match(ModStr,RegExpMod) of
- {match,1,ModLen} -> % This module satisfies the regexp.
+ case re:run(ModStr,RegExpMod) of
+ {match,[{0,ModLen}]} -> % This module satisfies the regexp.
handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,[Mod|Result]);
_ -> % Error or not perfect match.
handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,Result)
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index 9c1f9da5b1..01e99f3f5e 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,9 @@
%% General
-export([vsn/0]).
+%% observer stuff
+-export([sys_info/0, get_table/3, get_table_list/2, fetch_stats/2]).
+
%% etop stuff
-export([etop_collect/1]).
-include("observer_backend.hrl").
@@ -42,8 +45,175 @@ vsn() ->
Error -> Error
end.
+%%
+%% observer backend
+%%
+sys_info() ->
+ {{_,Input},{_,Output}} = erlang:statistics(io),
+ [{process_count, erlang:system_info(process_count)},
+ {process_limit, erlang:system_info(process_limit)},
+ {uptime, element(1, erlang:statistics(wall_clock))},
+ {run_queue, erlang:statistics(run_queue)},
+ {io_input, Input},
+ {io_output, Output},
+ {logical_processors, erlang:system_info(logical_processors)},
+ {logical_processors_available, erlang:system_info(logical_processors_available)},
+ {logical_processors_online, erlang:system_info(logical_processors_online)},
+
+ {otp_release, erlang:system_info(otp_release)},
+ {version, erlang:system_info(version)},
+ {system_architecture, erlang:system_info(system_architecture)},
+ {kernel_poll, erlang:system_info(kernel_poll)},
+ {smp_support, erlang:system_info(smp_support)},
+ {threads, erlang:system_info(threads)},
+ {thread_pool_size, erlang:system_info(thread_pool_size)},
+ {wordsize_internal, erlang:system_info({wordsize, internal})},
+ {wordsize_external, erlang:system_info({wordsize, external})} |
+ erlang:memory()
+ ].
+
+get_table(Parent, Table, Module) ->
+ spawn(fun() ->
+ link(Parent),
+ get_table2(Parent, Table, Module)
+ end).
+
+get_table2(Parent, Table, Type) ->
+ Size = case Type of
+ ets -> ets:info(Table, size);
+ mnesia -> mnesia:table_info(Table, size)
+ end,
+ case Size > 0 of
+ false ->
+ Parent ! {self(), '$end_of_table'},
+ normal;
+ true when Type =:= ets ->
+ Mem = ets:info(Table, memory),
+ Average = Mem div Size,
+ NoElements = max(10, 20000 div Average),
+ get_ets_loop(Parent, ets:match(Table, '$1', NoElements));
+ true ->
+ Mem = mnesia:table_info(Table, memory),
+ Average = Mem div Size,
+ NoElements = max(10, 20000 div Average),
+ Ms = [{'$1', [], ['$1']}],
+ Get = fun() ->
+ get_mnesia_loop(Parent, mnesia:select(Table, Ms, NoElements, read))
+ end,
+ %% Not a transaction, we don't want to grab locks when inspecting the table
+ mnesia:async_dirty(Get)
+ end.
-
+get_ets_loop(Parent, '$end_of_table') ->
+ Parent ! {self(), '$end_of_table'};
+get_ets_loop(Parent, {Match, Cont}) ->
+ Parent ! {self(), Match},
+ get_ets_loop(Parent, ets:match(Cont)).
+
+get_mnesia_loop(Parent, '$end_of_table') ->
+ Parent ! {self(), '$end_of_table'};
+get_mnesia_loop(Parent, {Match, Cont}) ->
+ Parent ! {self(), Match},
+ get_mnesia_loop(Parent, mnesia:select(Cont)).
+
+get_table_list(ets, Opts) ->
+ HideUnread = proplists:get_value(unread_hidden, Opts, true),
+ HideSys = proplists:get_value(sys_hidden, Opts, true),
+ Info = fun(Id, Acc) ->
+ try
+ TabId = case ets:info(Id, named_table) of
+ true -> ignore;
+ false -> Id
+ end,
+ Name = ets:info(Id, name),
+ Protection = ets:info(Id, protection),
+ ignore(HideUnread andalso Protection == private, unreadable),
+ Owner = ets:info(Id, owner),
+ RegName = case catch process_info(Owner, registered_name) of
+ [] -> ignore;
+ {registered_name, ProcName} -> ProcName
+ end,
+ ignore(HideSys andalso ordsets:is_element(RegName, sys_processes()), system_tab),
+ ignore(HideSys andalso ordsets:is_element(Name, sys_tables()), system_tab),
+ ignore((RegName == mnesia_monitor)
+ andalso Name /= schema
+ andalso is_atom((catch mnesia:table_info(Name, where_to_read))), mnesia_tab),
+ Memory = ets:info(Id, memory) * erlang:system_info(wordsize),
+ Tab = [{name,Name},
+ {id,TabId},
+ {protection,Protection},
+ {owner,Owner},
+ {size,ets:info(Id, size)},
+ {reg_name,RegName},
+ {type,ets:info(Id, type)},
+ {keypos,ets:info(Id, keypos)},
+ {heir,ets:info(Id, heir)},
+ {memory,Memory},
+ {compressed,ets:info(Id, compressed)},
+ {fixed,ets:info(Id, fixed)}
+ ],
+ [Tab|Acc]
+ catch _:_What ->
+ %% io:format("Skipped ~p: ~p ~n",[Id, _What]),
+ Acc
+ end
+ end,
+ lists:foldl(Info, [], ets:all());
+
+get_table_list(mnesia, Opts) ->
+ HideSys = proplists:get_value(sys_hidden, Opts, true),
+ Owner = ets:info(schema, owner),
+ Owner /= undefined orelse
+ throw({error, "Mnesia is not running on: " ++ atom_to_list(node())}),
+ {registered_name, RegName} = process_info(Owner, registered_name),
+ Info = fun(Id, Acc) ->
+ try
+ Name = Id,
+ ignore(HideSys andalso ordsets:is_element(Name, mnesia_tables()), system_tab),
+ ignore(Name =:= schema, mnesia_tab),
+ Storage = mnesia:table_info(Id, storage_type),
+ Tab0 = [{name,Name},
+ {owner,Owner},
+ {size,mnesia:table_info(Id, size)},
+ {reg_name,RegName},
+ {type,mnesia:table_info(Id, type)},
+ {keypos,2},
+ {memory,mnesia:table_info(Id, memory) * erlang:system_info(wordsize)},
+ {storage,Storage},
+ {index,mnesia:table_info(Id, index)}
+ ],
+ Tab = if Storage == disc_only_copies ->
+ [{fixed, dets:info(Id, safe_fixed)}|Tab0];
+ (Storage == ram_copies) orelse
+ (Storage == disc_copies) ->
+ [{fixed, ets:info(Id, fixed)},
+ {compressed, ets:info(Id, compressed)}|Tab0];
+ true -> Tab0
+ end,
+ [Tab|Acc]
+ catch _:_What ->
+ %% io:format("Skipped ~p: ~p ~p ~n",[Id, _What, erlang:get_stacktrace()]),
+ Acc
+ end
+ end,
+ lists:foldl(Info, [], mnesia:system_info(tables)).
+
+fetch_stats(Parent, Time) ->
+ erlang:system_flag(scheduler_wall_time, true),
+ process_flag(trap_exit, true),
+ fetch_stats_loop(Parent, Time),
+ erlang:system_flag(scheduler_wall_time, false).
+
+fetch_stats_loop(Parent, Time) ->
+ receive
+ _Msg -> normal
+ after Time ->
+ _M = Parent ! {stats, 1,
+ erlang:statistics(scheduler_wall_time),
+ erlang:statistics(io),
+ erlang:memory()},
+ fetch_stats(Parent, Time)
+ end.
%%
%% etop backend
%%
@@ -395,3 +565,62 @@ match_filenames(Dir,MetaFile,[H|T],Files) ->
end;
match_filenames(_Dir,_MetaFile,[],Files) ->
Files.
+
+
+%%%%%%%%%%%%%%%%%
+
+sys_tables() ->
+ [ac_tab, asn1,
+ cdv_dump_index_table, cdv_menu_table, cdv_decode_heap_table,
+ cell_id, cell_pos, clist,
+ cover_internal_data_table, cover_collected_remote_data_table, cover_binary_code_table,
+ code, code_names, cookies,
+ corba_policy, corba_policy_associations,
+ dets, dets_owners, dets_registry,
+ disk_log_names, disk_log_pids,
+ eprof, erl_atom_cache, erl_epmd_nodes,
+ etop_accum_tab, etop_tr,
+ ets_coverage_data,
+ file_io_servers,
+ gs_mapping, gs_names, gstk_db,
+ gstk_grid_cellid, gstk_grid_cellpos, gstk_grid_id,
+ httpd,
+ id,
+ ign_req_index, ign_requests,
+ index,
+ inet_cache, inet_db, inet_hosts,
+ 'InitialReferences',
+ int_db,
+ interpreter_includedirs_macros,
+ ir_WstringDef,
+ lmcounter, locks,
+ % mnesia_decision,
+ mnesia_gvar, mnesia_stats,
+ % mnesia_transient_decision,
+ pg2_table,
+ queue,
+ schema,
+ shell_records,
+ snmp_agent_table, snmp_local_db2, snmp_mib_data, snmp_note_store, snmp_symbolic_ets,
+ tkFun, tkLink, tkPriv,
+ ttb, ttb_history_table,
+ udp_fds, udp_pids
+ ].
+
+sys_processes() ->
+ [auth, code_server, global_name_server, inet_db,
+ mnesia_recover, net_kernel, timer_server, wxe_master].
+
+mnesia_tables() ->
+ [ir_AliasDef, ir_ArrayDef, ir_AttributeDef, ir_ConstantDef,
+ ir_Contained, ir_Container, ir_EnumDef, ir_ExceptionDef,
+ ir_IDLType, ir_IRObject, ir_InterfaceDef, ir_ModuleDef,
+ ir_ORB, ir_OperationDef, ir_PrimitiveDef, ir_Repository,
+ ir_SequenceDef, ir_StringDef, ir_StructDef, ir_TypedefDef,
+ ir_UnionDef, logTable, logTransferTable, mesh_meas,
+ mesh_type, mnesia_clist, orber_CosNaming,
+ orber_objkeys, user
+ ].
+
+ignore(true, Reason) -> throw(Reason);
+ignore(_,_ ) -> ok.
diff --git a/lib/runtime_tools/src/runtime_tools.app.src b/lib/runtime_tools/src/runtime_tools.app.src
index 095567b165..1152f7259d 100644
--- a/lib/runtime_tools/src/runtime_tools.app.src
+++ b/lib/runtime_tools/src/runtime_tools.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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 @@
inviso_rt,inviso_rt_lib,inviso_rt_meta,
inviso_as_lib,inviso_autostart,inviso_autostart_server,
runtime_tools,runtime_tools_sup,erts_alloc_config,
- ttb_autostart]},
+ ttb_autostart,dyntrace]},
{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 4fcb2292d0..913719c449 100644
--- a/lib/runtime_tools/src/runtime_tools_sup.erl
+++ b/lib/runtime_tools/src/runtime_tools_sup.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
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile
index cfaf420d65..4979b9c7b1 100644
--- a/lib/runtime_tools/test/Makefile
+++ b/lib/runtime_tools/test/Makefile
@@ -3,6 +3,7 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES = \
+ dyntrace_SUITE \
runtime_tools_SUITE \
inviso_testmodule1_foo \
inviso_SUITE \
@@ -56,10 +57,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
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 -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) runtime_tools.spec runtime_tools.cover $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EMAKEFILE) runtime_tools.cover "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/runtime_tools/test/dyntrace_SUITE.erl b/lib/runtime_tools/test/dyntrace_SUITE.erl
new file mode 100644
index 0000000000..0e4f369ed0
--- /dev/null
+++ b/lib/runtime_tools/test/dyntrace_SUITE.erl
@@ -0,0 +1,224 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(dyntrace_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([init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([smoke/1,process/1]).
+
+%% Default timetrap timeout (set in init_per_testcase)
+-define(default_timeout, ?t:minutes(1)).
+
+init_per_testcase(_Case, Config) ->
+ Dog = test_server:timetrap(?default_timeout),
+ [{watchdog,Dog}|Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ case erlang:system_info(dynamic_trace) of
+ none ->
+ {skip,"No dynamic trace in this run-time system"};
+ dtrace ->
+ [{group,smoke}];
+ systemtap ->
+ {skip,"SystemTap tests currently not supported"}
+ end.
+
+groups() ->
+ [{smoke,[sequence],[smoke,{group,rest}]},
+ {rest,[],
+ [process]}].
+
+init_per_suite(Config) ->
+ N = "beam" ++
+ case erlang:system_info(debug_compiled) of
+ false -> "";
+ true -> ".debug"
+ end ++
+ case erlang:system_info(smp_support) of
+ false -> "";
+ true -> ".smp"
+ end,
+ [{emu_name,N}|Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+smoke(Config) ->
+ Emu = ?t:lookup_config(emu_name, Config),
+ BinEmu = list_to_binary(Emu),
+ case erlang:system_info(dynamic_trace) of
+ dtrace ->
+ Probes = os:cmd("sudo /usr/sbin/dtrace -l -m" ++ Emu),
+ io:put_chars(Probes),
+ [_|Lines] = re:split(Probes, "\n", [trim]),
+ [{_,_} = binary:match(L, BinEmu) || L <- Lines],
+ ok
+ end,
+
+ %% Test that the framework for running dtrace/systemtap works
+ %% by executing an empty script.
+ {ok,[]} = dyntrace("", fun() -> ok end),
+ ok.
+
+
+process(_Config) ->
+ Script = [{probe,"process-spawn"},
+ {action,[{printf,["spawn %s %s\n",{arg,0},{arg,1}]}]},
+ {probe,"process-scheduled"},
+ {action,[{printf,["in %s\n",{arg,0}]}]},
+ {probe,"process-unscheduled"},
+ {action,[{printf,["out %s\n",{arg,0}]}]},
+ {probe,"process-hibernate"},
+ {action,[{printf,["hibernate %s %s\n",{arg,0},{arg,1}]}]},
+ {probe,"process-exit"},
+ {action,[{printf,["exit %s %s\n",{arg,0},{arg,1}]}]}
+ ],
+ F = fun() ->
+ {Pid,Ref} = spawn_monitor(fun my_process/0),
+ Pid ! hibernate,
+ Pid ! quit,
+ receive
+ {'DOWN',Ref,process,Pid,{terminated,Pid}} ->
+ ok
+ end,
+ Pid
+ end,
+ {Pid,Output0} = dyntrace(Script, F),
+ Output1 = [termify_line(L) || L <- Output0],
+ PidStr = pid_to_list(Pid),
+ Output = [L || L <- Output1, element(2, L) =:= PidStr],
+ Reason = "{terminated,"++PidStr++"}",
+ io:format("~p\n", [Output]),
+ [{spawn,PidStr,"erlang:apply/2"},
+ {in,PidStr},
+ {hibernate,PidStr,"erlang:apply/2"},
+ {out,PidStr},
+ {in,PidStr},
+ {exit,PidStr,Reason},
+ {out,PidStr}] = Output,
+ ok.
+
+termify_line(L) ->
+ [H|T] = re:split(L, " ", [{return,list}]),
+ list_to_tuple([list_to_atom(H)|T]).
+
+my_process() ->
+ receive
+ hibernate ->
+ erlang:hibernate(erlang, apply, [fun my_process/0,[]]);
+ quit ->
+ exit({terminated,self()})
+ end.
+
+%%%
+%%% Utility functions.
+%%%
+
+dyntrace(Script0, Action) ->
+ Sudo = os:find_executable(sudo),
+ {Termination,Pid} = termination_probe(),
+ Script1 = Script0++Termination,
+ Script = translate_script(Script1),
+ io:format("~s\n", [Script]),
+ SrcFile = "test-dyntrace.d",
+ ok = file:write_file(SrcFile, Script),
+ Args = ["/usr/sbin/dtrace", "-q","-s",SrcFile],
+ Port = open_port({spawn_executable,Sudo},
+ [{args,Args},stream,in,stderr_to_stdout,eof]),
+ receive
+ {Port,{data,Sofar}} ->
+ Res = Action(),
+ Pid ! quit,
+ {Res,get_data(Port, Sofar)}
+ end.
+
+get_data(Port, Sofar) ->
+ receive
+ {Port,{data,Bytes}} ->
+ get_data(Port, [Sofar|Bytes]);
+ {Port,eof} ->
+ port_close(Port),
+ [$\n|T] = lists:flatten(Sofar),
+ re:split(T, "\n", [{return,list},trim])
+ end.
+
+termination_probe() ->
+ Pid = spawn(fun() ->
+ receive
+ _ ->
+ exit(done)
+ end
+ end),
+ S = [{'BEGIN',[{printf,["\n"]}]},
+ {probe,"process-exit"},
+ {pred,{'==',{arg,0},Pid}},
+ {action,[{exit,[0]}]}],
+ {S,Pid}.
+
+translate_script(Script) ->
+ [dtrace_op(Op) || Op <- Script].
+
+dtrace_op({probe,Function}) ->
+ OsPid = os:getpid(),
+ ["erlang",OsPid,":::",Function,$\n];
+dtrace_op({pred,Pred}) ->
+ ["/",dtrace_op(Pred),"/\n"];
+dtrace_op({action,List}) ->
+ ["{ ",action_list(List)," }\n\n"];
+dtrace_op({'BEGIN',List}) ->
+ ["BEGIN { ",action_list(List)," }\n\n"];
+dtrace_op({'==',Op1,Op2}) ->
+ [dtrace_op(Op1)," == ",dtrace_op(Op2)];
+dtrace_op({arg,N}) ->
+ ["copyinstr(arg",integer_to_list(N),")"];
+dtrace_op({Func,List}) when is_atom(Func), is_list(List) ->
+ [atom_to_list(Func),"(",comma_sep_ops(List),")"];
+dtrace_op(Pid) when is_pid(Pid) ->
+ ["\"",pid_to_list(Pid),"\""];
+dtrace_op(Str) when is_integer(hd(Str)) ->
+ io_lib:format("~p", [Str]);
+dtrace_op(Int) when is_integer(Int) ->
+ integer_to_list(Int).
+
+comma_sep_ops([A,B|T]) ->
+ [dtrace_op(A),","|comma_sep_ops([B|T])];
+comma_sep_ops([H]) ->
+ dtrace_op(H);
+comma_sep_ops([]) -> [].
+
+action_list([H|T]) ->
+ [dtrace_op(H),";"|action_list(T)];
+action_list([]) -> [].
diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl
index 3ae8d34dd6..c64c40b945 100644
--- a/lib/runtime_tools/test/inviso_SUITE.erl
+++ b/lib/runtime_tools/test/inviso_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The 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,13 +66,18 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) ->
- %% No never know who skrewed up this node before this suite! :-)
- erlang:trace_pattern({'_','_','_'},[],[local]),
- erlang:trace_pattern({'_','_','_'},[],[global]),
- erlang:trace(all,false,[all]),
+ case test_server:is_native(lists) of
+ true ->
+ {skip,"Native libs -- tracing doesn't work"};
+ false ->
+ %% We never know who messed up this node before this suite! :-)
+ erlang:trace_pattern({'_','_','_'},[],[local]),
+ erlang:trace_pattern({'_','_','_'},[],[global]),
+ erlang:trace(all,false,[all]),
- ?l ok=application:start(runtime_tools),
- Config.
+ ok=application:start(runtime_tools),
+ Config
+ end.
end_per_suite(_Config) ->
?l ok=application:stop(runtime_tools).
@@ -1380,9 +1385,10 @@ fetch_log_dist_trace_2(Config) ->
io:format("~p~n",[NodeResults]),
CheckFun=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) ->
Fun2=fun({ok,File}) ->
- {match,1,_}=
- regexp:first_match(File,
- "^"++"p1"++Name++atom_to_list(N)),
+ match=
+ re:run(File,
+ "^"++"p1"++Name++atom_to_list(N),
+ [{capture,none}]),
true;
(_) ->
false
@@ -1425,8 +1431,8 @@ fetch_log_dist_trace_3(Config) ->
CheckFun=fun({N,{ok,[{trace_log,PrivDir2,[F1,F2]},{ti_log,PrivDir2,[F3]}]}})->
PrivDir2=PrivDir,
RegExp="^"++Name++atom_to_list(N)++"[0-9]+"++"\.log",
- {match,1,_}=regexp:first_match(F1,RegExp),
- {match,1,_}=regexp:first_match(F2,RegExp),
+ match=re:run(F1,RegExp,[{capture,none}]),
+ match=re:run(F2,RegExp,[{capture,none}]),
F3=Name++"_ti_"++atom_to_list(N)++".ti",
true;
(_) ->
@@ -1439,9 +1445,10 @@ fetch_log_dist_trace_3(Config) ->
io:format("~p~n",[NodeResults2]),
CheckFun2=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) ->
Fun2=fun({ok,File}) ->
- {match,1,_}=
- regexp:first_match(File,
- "^"++"p1"++Name++atom_to_list(N)),
+ match=
+ re:run(File,
+ "^"++"p1"++Name++atom_to_list(N),
+ [{capture,none}]),
true;
(_) ->
false
@@ -2649,8 +2656,8 @@ check_on_nodes([],_,_,_,_) ->
how_many_files_regexp([],_,N) ->
{ok,N};
how_many_files_regexp([FName|Rest],RegExp,N) ->
- case regexp:first_match(FName,RegExp) of
- {match,1,_} ->
+ case re:run(FName,RegExp,[{capture,none}]) of
+ match ->
how_many_files_regexp(Rest,RegExp,N+1);
nomatch ->
how_many_files_regexp(Rest,RegExp,N);
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 0bcd261861..c9b5cc1a41 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.8.6
+RUNTIME_TOOLS_VSN = 1.8.8
diff --git a/lib/sasl/doc/src/Makefile b/lib/sasl/doc/src/Makefile
index eb880ccb78..b0ec671adc 100644
--- a/lib/sasl/doc/src/Makefile
+++ b/lib/sasl/doc/src/Makefile
@@ -116,18 +116,18 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man4
- $(INSTALL_DATA) $(MAN4_FILES) $(RELEASE_PATH)/man/man4
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man4"
+ $(INSTALL_DATA) $(MAN4_FILES) "$(RELEASE_PATH)/man/man4"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml
index 89bcf23b5e..bacfaa76ef 100644
--- a/lib/sasl/doc/src/appup.xml
+++ b/lib/sasl/doc/src/appup.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,12 +56,20 @@
the application.</p>
</item>
<item>
- <p><c>UpFromVsn = string()</c> is an earlier version of
- the application to upgrade from.</p>
+ <p><c>UpFromVsn = string() | binary()</c> is an earlier
+ version of the application to upgrade from. If it is a
+ string, it will be interpreted as a specific version
+ number. If it is a binary, it will be interpreted as a
+ regular expression which can match multiple version
+ numbers.</p>
</item>
<item>
- <p><c>DownToVsn = string()</c> is an earlier version of
- the application to downgrade to.</p>
+ <p><c>DownToVsn = string() | binary()</c> is an earlier
+ version of the application to downgrade to. If it is a
+ string, it will be interpreted as a specific version
+ number. If it is a binary, it will be interpreted as a
+ regular expression which can match multiple version
+ numbers.</p>
</item>
<item>
<p><c>Instructions</c> is a list of <em>release upgrade instructions</em>, see below. It is recommended to use
@@ -70,6 +78,12 @@
creating the <c>relup</c> file.</p>
</item>
</list>
+ <p>In order to avoid duplication of upgrade instructions it is
+ allowed to use regular expressions to specify the <c>UpFromVsn</c>
+ and <c>DownToVsn</c>. To be considered a regular expression, the
+ version identifier must be specified as a binary, e.g.</p>
+ <code type="none">&lt;&lt;"2\\.1\\.[0-9]+">></code>
+ <p>will match all versions <c>2.1.x</c>, where x is any number.</p>
</section>
<section>
@@ -319,12 +333,37 @@ point_of_no_return
<pre>
restart_new_emulator
</pre>
- <p>Shuts down the current emulator and starts a ne one. All
- processes are terminated gracefully. The new release must still
- be made permanent when the new emulator is up and running.
- Otherwise, the old emulator is started in case of a emulator
- restart. This instruction should be used when a new emulator is
- introduced, or if a complete reboot of the system should be done.</p>
+ <p>This instruction is used when erts, kernel, stdlib or sasl is
+ upgraded. It shuts down the current emulator and starts a new
+ one. All processes are terminated gracefully, and the new
+ version of erts, kernel, stdlib and sasl are used when the
+ emulator restarts. Only one <c>restart_new_emulator</c>
+ instruction is allowed in the relup, and it shall be placed
+ first. <seealso marker="systools#make_relup/3">systools:make_relup3,4</seealso>
+ will ensure this when the relup is generated. The rest of the
+ relup script is executed after the restart as a part of the boot
+ script.</p>
+ <p>An info report will be written when the upgrade is
+ completed. To programatically find out if the upgrade is
+ complete,
+ call <seealso marker="release_handler#which_releases/0">
+ release_handler:which_releases</seealso> and check if the
+ expected release has status <c>current</c>.</p>
+ <p>The new release must still be made permanent after the upgrade
+ is completed. Otherwise, the old emulator is started in case of
+ an emulator restart.</p>
+ <pre>
+restart_emulator
+ </pre>
+ <p>This instruction is similar to <c>restart_new_emulator</c>,
+ except it shall be placed at the end of the relup script. It is
+ not related to an upgrade of the emulator or the core
+ applications, but can be used by any application when a complete
+ reboot of the system is reqiured. When generating the
+ relup, <seealso marker="systools#make_relup/3">systools:make_relup/3,4</seealso>
+ ensures that there is only one <c>restart_emulator</c>
+ instruction and that it is the last instruction of the
+ relup.</p>
</section>
<section>
diff --git a/lib/sasl/doc/src/make.dep b/lib/sasl/doc/src/make.dep
deleted file mode 100644
index 4843b7934a..0000000000
--- a/lib/sasl/doc/src/make.dep
+++ /dev/null
@@ -1,22 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: alarm_handler.tex appup.tex book.tex error_logging.tex \
- overload.tex part.tex rb.tex ref_man.tex rel.tex \
- release_handler.tex relup.tex sasl_app.tex \
- sasl_intro.tex script.tex systools.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index 01cdc4b29e..e4a2c98db7 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -30,6 +30,167 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If sys.config existed, but was not readable or parseable,
+ this would not be detected until after the upgrade and at
+ the next node restart. The possibility for this to happen
+ is now reduced by adding a check to systools:make_tar
+ which fails the creation of the tar file if sys.config or
+ relup does not have reasonable contents. Note that there
+ are no detailed checks, only parsing and erlang term
+ format check.</p>
+ <p>
+ Own Id: OTP-9539</p>
+ </item>
+ <item>
+ <p>
+ systools:make_script would allow {kernel,Vsn,load} in the
+ .rel file, causing a .boot file which only loaded kernel
+ and did not start it. This has been corrected. Only start
+ type 'permanent', which is the default, is now allowed
+ for kernel and stdlib.</p>
+ <p>
+ Own Id: OTP-9652</p>
+ </item>
+ <item>
+ <p>
+ release_handler:remove_release/1 now handles symlinked
+ files properly</p>
+ <p>
+ Own Id: OTP-9864</p>
+ </item>
+ <item>
+ <p>
+ If stdlib was stated with a start type different from
+ <c>permanent</c> in a .rel file, systools would
+ incorrectly say that sasl had faulty start type. This has
+ been corrected.</p>
+ <p>
+ Own Id: OTP-9888</p>
+ </item>
+ <item>
+ <p>
+ Sasl documentation earlier said that the InclApps
+ parameters in a .rel file defaults to the empty list.
+ This is not correct. It defaults to the same value as
+ specified in the .app file. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9980</p>
+ </item>
+ <item>
+ <p>
+ Applications that are listed in
+ <c>{applications,Apps}</c> in the .app file were not
+ sorted correctly by <c>systools:make_script/1,2</c>. They
+ got the reverse order of how they were listed in the .app
+ file. This is corrected so they are now sorted
+ (internally between each other) in the same order as they
+ are listed in the .rel file (i.e. the order they are
+ listed in the .app file does no longer matter).</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9984</p>
+ </item>
+ <item>
+ <p>
+ Documentation of .appup files now also states that
+ <c>UpFromVsn</c> and <c>DownToVsn</c> can be specified as
+ regular expressions in order to avoid duplicated upgrade
+ instructions.</p>
+ <p>
+ Own Id: OTP-10001</p>
+ </item>
+ <item>
+ <p>
+ Reltool would sometimes generate a .app file containing
+ <c>{start_phases,undefined}</c>, which would cause an
+ exception in systools at parse time. This has been
+ corrected so reltool now omits the <c>start_phases</c>
+ entry if the value is <c>undefined</c>. (Thanks to Juan
+ Jose Comellas)</p>
+ <p>
+ In order to align with reltool, sasl will also omit
+ <c>start_phases</c> entries with value <c>undefined</c>
+ in .script files.</p>
+ <p>
+ Own Id: OTP-10003</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the mechanism for upgrading emulator.</p>
+ <p>
+ The appup files for kernel, stdlib and sasl do now
+ recognize two major releases back and include a
+ 'restart_new_emulator' instruction. </p>
+ <p>
+ Appup files can include regular expressions for matching
+ earlier releases.</p>
+ <p>
+ The mechanism for upgrading the emulator is changed so
+ 'restart_new_emulator' will be the first instruction
+ executed. The rest of the upgrade instruction will be
+ executed after the emulator restart.</p>
+ <p>
+ A new upgrade instruction 'restart_emulator' is added for
+ the case where the emulator shall be restarted after all
+ other upgrade instructions.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9438</p>
+ </item>
+ <item>
+ <p>
+ Add release_handler:which_releases/1</p>
+ <p>
+ This is an extension to which_releases that allows a user
+ to specify the status of the releases they wish to be
+ returned. For instance it allows for quickly determining
+ which release is 'permanent' without the need of parsing
+ the entire release list. (Thanks to Joe Williams)</p>
+ <p>
+ Own Id: OTP-9717</p>
+ </item>
+ <item>
+ <p>
+ Add copy of rel file in releases/Vsn in release tar file</p>
+ <p>
+ systool:make_tar stores the rel file in the releases
+ directory. When unpacking with
+ release_handler:unpack_release, the file is automatically
+ moved to releases/Vsn/. If, however, the tar file is
+ unpacked manually, the rel file might not be moved, and
+ the next release unpacked might overwrite the rel file.
+ To overcome this, systools:make_tar now stores a copy of
+ the rel file in releases/Vsn/ directly and it is not
+ longer necessary to move the file after unpacking.</p>
+ <p>
+ The reason for keeping the file in the releases directory
+ also is that is needs to be extracted separately before
+ the release version (Vsn) is known.</p>
+ <p>
+ Own Id: OTP-9746</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 2.1.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index f35ceb5777..3da825878e 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.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>
@@ -123,7 +123,9 @@
<fsummary>List all reports</fsummary>
<type>
<v>Type = type()</v>
- <v>type() = crash_report | supervisor_report | error | progress</v>
+ <v>type() = error | error_report | info_msg | info_report |
+ warning_msg | warning_report | crash_report |
+ supervisor_report | progress</v>
</type>
<desc>
<p>This function lists all reports loaded in the
diff --git a/lib/sasl/doc/src/rel.xml b/lib/sasl/doc/src/rel.xml
index 470adf3c03..68ef90330f 100644
--- a/lib/sasl/doc/src/rel.xml
+++ b/lib/sasl/doc/src/rel.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1997</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -88,7 +88,7 @@
<p>The list must be a subset of the included applications
specified in the application resource file
(<c>Application.app</c>) and overrides this value. Defaults
- to the empty list.</p>
+ to the same value as in the application resource file.</p>
</item>
</list>
<note>
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 5ac0dc1acc..e3438ede41 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -64,10 +64,10 @@
downgraded to the specified version by evaluating the instructions
in <c>relup</c>. An installed release can be made
<em>permanent</em>. There can only be one permanent release in
- the system, and this is the release that is used if the system is
- restarted. An installed release, except the permanent one, can be
- <em>removed</em>. When a release is removed, all files that
- belong to that release only are deleted.</p>
+ the system, and this is the release that is used if the system
+ is restarted. An installed release, except the permanent one,
+ can be <em>removed</em>. When a release is removed, all files
+ that belong to that release only are deleted.</p>
<p>Each version of the release has a status. The status can be
<c>unpacked</c>, <c>current</c>, <c>permanent</c>, or <c>old</c>.
There is always one latest release which either has status
@@ -107,16 +107,17 @@ old reboot_old permanent
restarted. This is taken care of automatically if Erlang is
started as an embedded system. Read about this in <em>Embedded System</em>. In this case, the system configuration file
<c>sys.config</c> is mandatory.</p>
- <p>A new release may restart the system. Which program to use is
- specified by the SASL configuration parameter <c>start_prg</c>
- which defaults to <c>$ROOT/bin/start</c>.</p>
+ <p>The installation of a new release may restart the system. Which
+ program to use is specified by the SASL configuration
+ parameter <c>start_prg</c> which defaults
+ to <c>$ROOT/bin/start</c>.</p>
<p>The emulator restart on Windows NT expects that the system is
started using the <c>erlsrv</c> program (as a service).
Furthermore the release handler expects that the service is named
<em>NodeName</em>_<em>Release</em>, where <em>NodeName</em> is
the first part of the Erlang nodename (up to, but not including
- the "@") and <em>Release</em> is the current release of
- the application. The release handler furthermore expects that a
+ the "@") and <em>Release</em> is the current version of
+ the release. The release handler furthermore expects that a
program like <c>start_erl.exe</c> is specified as "machine" to
<c>erlsrv</c>. During upgrading with restart, a new service will
be registered and started. The new service will be set to
@@ -238,7 +239,7 @@ old reboot_old permanent
</func>
<func>
<name>install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
- <name>install_release(Vsn, [Opt]) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
+ <name>install_release(Vsn, [Opt]) -> {ok, OtherVsn, Descr} | {continue_after_restart, OtherVsn, Descr} | {error, Reason}</name>
<fsummary>Install a release in the system.</fsummary>
<type>
<v>Vsn = OtherVsn = string()</v>
@@ -248,7 +249,8 @@ old reboot_old permanent
<v>&nbsp;Timeout = default | infinity | int()>0</v>
<v>&nbsp;Bool = boolean()</v>
<v>Descr = term()</v>
- <v>Reason = {illegal_option, Opt} | {already_installed, Vsn} | {change_appl_data, term()} | term()</v>
+ <v>Reason = {illegal_option, Opt} | {already_installed, Vsn} | {change_appl_data, term()} | {missing_base_app, OtherVsn, App} | {could_not_create_hybrid_boot, term()} | term()</v>
+ <v>App = atom()</v>
</type>
<desc>
<p>Installs the specified version <c>Vsn</c> of the release.
@@ -268,6 +270,15 @@ old reboot_old permanent
<c>OtherVsn</c> and <c>Descr</c> are the version
(<c>UpFromVsn</c> or <c>Vsn</c>) and description
(<c>Descr1</c> or <c>Descr2</c>) as specified in the script.</p>
+ <p>If <c>{continue_after_restart,OtherVsn,Descr}</c> is
+ returned, it means that the emulator will be restarted
+ before the upgrade instructions are executed. This will
+ happen if the emulator or any of the applications kernel,
+ stdlib or sasl are updated. The new version of the emulator
+ and these core applications will execute after the restart,
+ but for all other applications the old versions will be
+ started and the upgrade will be performed as normal by
+ executing the upgrade instructions.</p>
<p>If a recoverable error occurs, the function returns
<c>{error,Reason}</c> and the original application
specifications are restored. If a non-recoverable error
@@ -325,6 +336,18 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
upgrade, but it will allow checks and purge to be executed
in the background before the real upgrade is started.</p>
</note>
+ <note>
+ <p>When upgrading the emulator from a version older than OTP
+ R15, there will be an attempt to load new application beam
+ code into the old emulator. In some cases, the new beam
+ format can not be read by the old emulator, and so the code
+ loading will fail and terminate the complete upgrade. To
+ overcome this problem, the new application code should be
+ compiled with the old emulator. See <seealso
+ marker="doc/design_principles:appup_cookbook">Design
+ Principles</seealso> for more information about emulator
+ upgrade from pre OTP R15 versions.</p>
+ </note>
</desc>
</func>
<func>
@@ -431,6 +454,18 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<p>Returns all releases known to the release handler.</p>
</desc>
</func>
+ <func>
+ <name>which_releases(Status) -> [{Name, Vsn, Apps, Status}]</name>
+ <fsummary>Return all known releases of a specific status</fsummary>
+ <type>
+ <v>Name = Vsn = string()</v>
+ <v>Apps = ["App-Vsn"]</v>
+ <v>Status = unpacked | current | permanent | old</v>
+ </type>
+ <desc>
+ <p>Returns all releases known to the release handler of a specific status.</p>
+ </desc>
+ </func>
</funcs>
<section>
@@ -442,7 +477,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
and evaluated exactly in the same way as <c>release_handler</c>
does.</p>
<warning>
- <p>These function is primarily intended for simplified testing of
+ <p>These functions are primarily intended for simplified testing
of <c>.appup</c> files. They are not run within the context of
the <c>release_handler</c> process. They must therefore
<em>not</em> be used together with calls to
@@ -450,7 +485,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<c>release_handler</c> to end up in an inconsistent state.</p>
<p>No persistent information is updated, why these functions can
be used on any Erlang node, embedded or not. Also, using these
- functions does not effect which code will be loaded in case of
+ functions does not affect which code will be loaded in case of
a reboot.</p>
<p>If the upgrade or downgrade fails, the application may end up
in an inconsistent state.</p>
@@ -458,7 +493,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</section>
<funcs>
<func>
- <name>upgrade_app(App, Dir) -> {ok, Unpurged} | restart_new_emulator | {error, Reason}</name>
+ <name>upgrade_app(App, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
<fsummary>Upgrade to a new application version</fsummary>
<type>
<v>App = atom()</v>
@@ -487,14 +522,21 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
does.</p>
<p>Returns <c>{ok, Unpurged}</c> if evaluating the script is
successful, where <c>Unpurged</c> is a list of unpurged
- modules, or <c>restart_new_emulator</c> if this instruction is
+ modules, or <c>restart_emulator</c> if this instruction is
encountered in the script, or <c>{error, Reason}</c> if
an error occurred when finding or evaluating the script.</p>
+ <p>If the <c>restart_new_emulator</c> instruction is found in
+ the script, <c>upgrade_app/2</c> will return
+ <c>{error,restart_new_emulator}</c>. The reason for this is
+ that this instruction requires that a new version of the
+ emulator is started before the rest of the upgrade
+ instructions can be executed, and this can only be done by
+ <c>install_release/1,2</c>.</p>
</desc>
</func>
<func>
<name>downgrade_app(App, Dir) -></name>
- <name>downgrade_app(App, OldVsn, Dir) -> {ok, Unpurged} | restart_new_emulator | {error, Reason}</name>
+ <name>downgrade_app(App, OldVsn, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
<fsummary>Downgrade to a previous application version</fsummary>
<type>
<v>App = atom()</v>
@@ -528,7 +570,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
does.</p>
<p>Returns <c>{ok, Unpurged}</c> if evaluating the script is
successful, where <c>Unpurged</c> is a list of unpurged
- modules, or <c>restart_new_emulator</c> if this instruction is
+ modules, or <c>restart_emulator</c> if this instruction is
encountered in the script, or <c>{error, Reason}</c> if
an error occurred when finding or evaluating the script.</p>
</desc>
@@ -604,7 +646,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</desc>
</func>
<func>
- <name>eval_appup_script(App, ToVsn, ToDir, Script) -> {ok, Unpurged} | restart_new_emulator | {error, Reason}</name>
+ <name>eval_appup_script(App, ToVsn, ToDir, Script) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
<fsummary>Evaluate an application upgrade or downgrade script</fsummary>
<type>
<v>App = atom()</v>
@@ -617,8 +659,8 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<desc>
<p>Evaluates an application upgrade or downgrade script
<c>Script</c>, the result from calling
- <seealso marker="#upgrade_app/2">upgrade_app/2</seealso> or
- <seealso marker="#downgrade_app/3">downgrade_app/2,3</seealso>,
+ <seealso marker="#upgrade_app/2">upgrade_script/2</seealso> or
+ <seealso marker="#downgrade_app/3">downgrade_script/3</seealso>,
exactly in the same way as
<seealso marker="#install_release/1">install_release/1,2</seealso>
does.</p>
@@ -629,9 +671,16 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<c>.appup</c> files should be located under <c>Dir/ebin</c>.</p>
<p>Returns <c>{ok, Unpurged}</c> if evaluating the script is
successful, where <c>Unpurged</c> is a list of unpurged
- modules, or <c>restart_new_emulator</c> if this instruction is
+ modules, or <c>restart_emulator</c> if this instruction is
encountered in the script, or <c>{error, Reason}</c> if
an error occurred when evaluating the script.</p>
+ <p>If the <c>restart_new_emulator</c> instruction is found in
+ the script, <c>eval_appup_script/4</c> will return
+ <c>{error,restart_new_emulator}</c>. The reason for this is
+ that this instruction requires that a new version of the
+ emulator is started before the rest of the upgrade
+ instructions can be executed, and this can only be done by
+ <c>install_release/1,2</c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 8c1c327d74..84fed0a25f 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -111,6 +111,11 @@
low-level instruction to restart the emulator is appended to
the relup scripts. This ensures that a complete reboot of
the system is done when the system is upgraded or downgraded.</p>
+ <p>If an upgrade includes a change from an emulator earlier
+ than OTP R15 to OTP R15 or later, the warning
+ <c>pre_R15_emulator_upgrade</c> is issued. See <seealso
+ marker="doc/design_principles:appup_cookbook">Design
+ Principles</seealso> for more information about this.</p>
<p>By default, errors and warnings are printed to tty and
the function returns <c>ok</c> or <c>error</c>. If the option
<c>silent</c> is provided, the function instead returns
@@ -133,8 +138,9 @@
<fsummary>Generate a boot script <c>.script/.boot</c>.</fsummary>
<type>
<v>Name = string()</v>
- <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}]
- | silent | {outdir,Dir} | warnings_as_errors</v>
+ <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref |
+ {exref,[App]}] | silent | {outdir,Dir} | no_warn_sasl |
+ warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>&nbsp;Var = {VarName,Prefix}</v>
<v>&nbsp;&nbsp;VarName = Prefix = string()</v>
@@ -190,6 +196,14 @@
<p>The applications are sorted according to the dependencies
between the applications. Where there are no dependencies,
the order in the <c>.rel</c> file is kept.</p>
+ <p>The function will fail if the mandatory
+ applications <c>kernel</c> and <c>stdlib</c> are not
+ included in the <c>.rel</c> file and have start
+ type <c>permanent</c> (default).</p>
+ <p>If <c>sasl</c> is not included as an application in
+ the <c>.rel</c> file, a warning is emitted because such a
+ release can not be used in an upgrade. To turn off this
+ warning, add the option <c>no_warn_sasl</c>.</p>
<p>All files are searched for in the current path. It is
assumed that the <c>.app</c> and <c>.beam</c> files for an
application is located in the same directory. The <c>.erl</c>
@@ -220,7 +234,7 @@
<p>Example: If the option <c>{variables,[{"TEST","lib"}]}</c> is
supplied, and <c>myapp.app</c> is found in
<c>lib/myapp/ebin</c>, then the path to this application in
- the boot script will be <c>$TEST/myapp-1/ebin"</c>. If
+ the boot script will be <c>"$TEST/myapp-1/ebin"</c>. If
<c>myapp.app</c> is found in <c>lib/test</c>, then the path
will be <c>$TEST/test/myapp-1/ebin</c>.</p>
<p>The checks performed before the boot script is generated can
diff --git a/lib/sasl/examples/src/Makefile b/lib/sasl/examples/src/Makefile
index 9cf0d4c25d..47c8626205 100644
--- a/lib/sasl/examples/src/Makefile
+++ b/lib/sasl/examples/src/Makefile
@@ -63,10 +63,10 @@ docs:
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
+ $(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
index 0e1e0b2324..ffc0fcf443 100644
--- a/lib/sasl/examples/src/target_system.erl
+++ b/lib/sasl/examples/src/target_system.erl
@@ -16,6 +16,7 @@
%%
%% %CopyrightEnd%
%%
+%module
-module(target_system).
-export([create/1, create/2, install/2]).
@@ -130,14 +131,14 @@ install(RelFileName, RootDir) ->
[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"
+ io:fwrite("Substituting in erl.src, start.src and start_erl.src to "
"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])).
+ create_RELEASES(RootDir, filename:join([RootDir, "releases",
+ filename:basename(RelFileName)])).
%% LOCALS
@@ -257,3 +258,4 @@ remove_all_files(Dir, Files) ->
file:delete(FilePath)
end
end, Files).
+%module
diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile
index 9a5d1e42d9..cae8146ebc 100644
--- a/lib/sasl/src/Makefile
+++ b/lib/sasl/src/Makefile
@@ -91,10 +91,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index bc08f94dff..5efd932c92 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,9 @@
create_RELEASES/1, create_RELEASES/2, create_RELEASES/4,
unpack_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,
+ install_release/1, install_release/2, new_emulator_upgrade/2,
+ remove_release/1, which_releases/0, which_releases/1,
+ 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,
upgrade_script/2, downgrade_script/3,
@@ -40,7 +41,7 @@
%% Internal exports, a client release_handler may call this functions.
-export([do_write_release/3, do_copy_file/2, do_copy_files/2,
do_copy_files/1, do_rename_files/1, do_remove_files/1,
- do_write_file/2, do_ensure_RELEASES/1]).
+ remove_file/1, do_write_file/2, do_ensure_RELEASES/1]).
-record(state, {unpurged = [],
root,
@@ -61,10 +62,11 @@
%% remove -
%% current make_permanent permanent
%% install other old
+%% restart node unpacked
%% remove -
%% permanent make other permanent old
%% install permanent
-%% old reboot permanen
+%% old reboot_old permanent
%% install current
%% remove -
%%-----------------------------------------------------------------
@@ -74,6 +76,14 @@
-define(timeout, 10000).
%%-----------------------------------------------------------------
+%% The version set on the temporary release that will be used when the
+%% emulator is upgraded.
+-define(tmp_vsn(__BaseVsn__), "__new_emulator__"++__BaseVsn__).
+
+
+
+
+%%-----------------------------------------------------------------
%% Assumes the following file structure:
%% root --- lib --- Appl-Vsn1 --- <src>
%% | | |- ebin
@@ -183,11 +193,15 @@ check_check_install_options([],Purge) ->
%%-----------------------------------------------------------------
%% Purpose: Executes the relup script for the specified version.
%% The release must be unpacked.
-%% Returns: {ok, FromVsn, Descr} | {error, Reason}
+%% Returns: {ok, FromVsn, Descr} |
+%% {continue_after_restart, FromVsn, Descr} |
+%% {error, Reason}
%% Reason = {already_installed, Vsn} |
%% {bad_relup_file, RelFile} |
%% {no_such_release, Vsn} |
%% {no_such_from_vsn, Vsn} |
+%% {could_not_create_hybrid_boot,Why} |
+%% {missing_base_app,Vsn,App} |
%% {illegal_option, Opt}} |
%% exit_reason()
%%-----------------------------------------------------------------
@@ -230,6 +244,21 @@ check_timeout(Int) when is_integer(Int), Int > 0 -> true;
check_timeout(_Else) -> false.
%%-----------------------------------------------------------------
+%% Purpose: Called by boot script after emulator is restarted due to
+%% new erts version.
+%% Returns: Same as install_release/2
+%% If this crashes, the emulator restart will fail
+%% (since the function is called from the boot script)
+%% and there will be a rollback.
+%%-----------------------------------------------------------------
+new_emulator_upgrade(Vsn, Opts) ->
+ Result = call({install_release, Vsn, reboot, Opts}),
+ error_logger:info_msg(
+ "~p:install_release(~p,~p) completed after node restart "
+ "with new emulator version~nResult: ~p~n",[?MODULE,Vsn,Opts,Result]),
+ Result.
+
+%%-----------------------------------------------------------------
%% Purpose: Makes the specified release version be the one that is
%% used when the system starts (or restarts).
%% The release must be installed (not unpacked).
@@ -305,6 +334,14 @@ which_releases() ->
call(which_releases).
%%-----------------------------------------------------------------
+%% Returns: [{Name, Vsn, [LibName], Status}]
+%% Status = unpacked | current | permanent | old
+%%-----------------------------------------------------------------
+which_releases(Status) ->
+ Releases = which_releases(),
+ get_releases_with_status(Releases, Status, []).
+
+%%-----------------------------------------------------------------
%% check_script(Script, LibDirs) -> ok | {error, Reason}
%%-----------------------------------------------------------------
check_script(Script, LibDirs) ->
@@ -313,7 +350,7 @@ check_script(Script, LibDirs) ->
%%-----------------------------------------------------------------
%% eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
%% {ok, UnPurged} |
-%% restart_new_emulator |
+%% restart_emulator |
%% {error, Error}
%% {'EXIT', Reason}
%% If sync_nodes is present, the calling process must have called
@@ -350,7 +387,7 @@ create_RELEASES(Root, RelDir, RelFile, LibDirs) ->
%%-----------------------------------------------------------------
%% Func: upgrade_app(App, Dir) -> {ok, Unpurged}
-%% | restart_new_emulator
+%% | restart_emulator
%% | {error, Error}
%% Types:
%% App = atom()
@@ -370,7 +407,7 @@ upgrade_app(App, NewDir) ->
%%-----------------------------------------------------------------
%% Func: downgrade_app(App, Dir)
%% downgrade_app(App, Vsn, Dir) -> {ok, Unpurged}
-%% | restart_new_emulator
+%% | restart_emulator
%% | {error, Error}
%% Types:
%% App = atom()
@@ -578,7 +615,7 @@ handle_call({check_install_release, Vsn, Purge}, _From, S) ->
handle_call({install_release, Vsn, ErrorAction, Opts}, From, S) ->
NS = resend_sync_nodes(S),
case catch do_install_release(S, Vsn, Opts) of
- {ok, NewReleases, CurrentVsn, Descr} ->
+ {ok, NewReleases, [], CurrentVsn, Descr} ->
{reply, {ok, CurrentVsn, Descr}, NS#state{releases=NewReleases}};
{ok, NewReleases, Unpurged, CurrentVsn, Descr} ->
Timer =
@@ -593,10 +630,14 @@ handle_call({install_release, Vsn, ErrorAction, Opts}, From, S) ->
{reply, {ok, CurrentVsn, Descr}, NewS};
{error, Reason} ->
{reply, {error, Reason}, NS};
- {restart_new_emulator, CurrentVsn, Descr} ->
+ {restart_emulator, CurrentVsn, Descr} ->
gen_server:reply(From, {ok, CurrentVsn, Descr}),
init:reboot(),
{noreply, NS};
+ {restart_new_emulator, CurrentVsn, Descr} ->
+ gen_server:reply(From, {continue_after_restart, CurrentVsn, Descr}),
+ init:reboot(),
+ {noreply, NS};
{'EXIT', Reason} ->
io:format("release_handler:"
"install_release(Vsn=~p Opts=~p) failed, "
@@ -801,8 +842,13 @@ do_unpack_release(Root, RelDir, ReleaseName, Releases) ->
extract_tar(Root, Tar),
NewReleases = [Release#release{status = unpacked} | Releases],
write_releases(RelDir, NewReleases, false),
+
+ %% Keeping this for backwards compatibility reasons with older
+ %% systools:make_tar, where there is no copy of the .rel file in
+ %% the releases/<vsn> dir. See OTP-9746.
Dir = filename:join([RelDir, Vsn]),
copy_file(RelFile, Dir, false),
+
{ok, NewReleases, Vsn}.
%% Note that this function is not executed by a client
@@ -941,7 +987,38 @@ do_install_release(#state{start_prg = StartPrg,
{value, Release} ->
LatestRelease = get_latest_release(Releases),
case get_rh_script(LatestRelease, Release, RelDir, Masters) of
+ {ok, {_CurrentVsn, _Descr, [restart_new_emulator|_Script]}}
+ when Static == true ->
+ throw(static_emulator);
+ {ok, {CurrentVsn, Descr, [restart_new_emulator|_Script]}} ->
+ %% This will only happen if the upgrade includes
+ %% an emulator upgrade (and it is not a downgrade)
+ %% - then the new emulator must be started before
+ %% new code can be loaded.
+ %% Create a temporary release which includes new
+ %% emulator, kernel, stdlib and sasl - and old
+ %% versions of other applications.
+ {TmpVsn,TmpRelease} =
+ new_emulator_make_tmp_release(LatestRelease,Release,
+ RelDir,Opts,Masters),
+ NReleases = [TmpRelease|Releases],
+
+ %% Then uppgrade to the temporary release.
+ %% The rest of the upgrade will continue after the restart
+ prepare_restart_new_emulator(StartPrg, RootDir,
+ RelDir, TmpVsn, TmpRelease,
+ NReleases, Masters),
+ {restart_new_emulator, CurrentVsn, Descr};
{ok, {CurrentVsn, Descr, Script}} ->
+ %% In case there has been an emulator upgrade,
+ %% remove the temporary release
+ NReleases =
+ new_emulator_rm_tmp_release(
+ LatestRelease#release.vsn,
+ LatestRelease#release.erts_vsn,
+ Vsn,RelDir,Releases,Masters),
+
+ %% Then execute the relup script
mon_nodes(true),
EnvBefore = application_controller:prep_config_change(),
Apps = change_appl_data(RelDir, Release, Masters),
@@ -949,31 +1026,19 @@ do_install_release(#state{start_prg = StartPrg,
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),
- NewReleases = set_status(Vsn, current, Releases),
- {ok, NewReleases, CurrentVsn, Descr};
{ok, Unpurged} ->
application_controller:config_change(EnvBefore),
mon_nodes(false),
- NewReleases = set_status(Vsn, current, Releases),
- {ok, NewReleases, Unpurged, CurrentVsn, Descr};
- restart_new_emulator when Static == true ->
+ NReleases1 = set_status(Vsn, current, NReleases),
+ {ok, NReleases1, Unpurged, CurrentVsn, Descr};
+ restart_emulator when Static == true ->
throw(static_emulator);
- restart_new_emulator ->
+ restart_emulator ->
mon_nodes(false),
- {value, PermanentRelease} =
- lists:keysearch(permanent, #release.status,
- Releases),
- NReleases = set_status(Vsn, current, Releases),
- NReleases2 = set_status(Vsn,tmp_current,NReleases),
- write_releases(RelDir, NReleases2, Masters),
prepare_restart_new_emulator(StartPrg, RootDir,
- RelDir, Release,
- PermanentRelease,
- Masters),
- {restart_new_emulator, CurrentVsn, Descr};
+ RelDir, Vsn, Release,
+ NReleases, Masters),
+ {restart_emulator, CurrentVsn, Descr};
Else ->
application_controller:config_change(EnvBefore),
mon_nodes(false),
@@ -986,6 +1051,158 @@ do_install_release(#state{start_prg = StartPrg,
{error, {no_such_release, Vsn}}
end.
+new_emulator_make_tmp_release(CurrentRelease,ToRelease,RelDir,Opts,Masters) ->
+ CurrentVsn = CurrentRelease#release.vsn,
+ ToVsn = ToRelease#release.vsn,
+ TmpVsn = ?tmp_vsn(CurrentVsn),
+ case get_base_libs(ToRelease#release.libs) of
+ {ok,{Kernel,Stdlib,Sasl}=BaseLibs,_} ->
+ case get_base_libs(ToRelease#release.libs) of
+ {ok,_,RestLibs} ->
+ TmpErtsVsn = ToRelease#release.erts_vsn,
+ TmpLibs = [Kernel,Stdlib,Sasl|RestLibs],
+ TmpRelease = CurrentRelease#release{vsn=TmpVsn,
+ erts_vsn=TmpErtsVsn,
+ libs = TmpLibs,
+ status = unpacked},
+ new_emulator_make_hybrid_boot(CurrentVsn,ToVsn,TmpVsn,
+ BaseLibs,RelDir,Opts,Masters),
+ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,
+ RelDir,Masters),
+ {TmpVsn,TmpRelease};
+ {error,{missing,Missing}} ->
+ throw({error,{missing_base_app,CurrentVsn,Missing}})
+ end;
+ {error,{missing,Missing}} ->
+ throw({error,{missing_base_app,ToVsn,Missing}})
+ end.
+
+%% Get kernel, stdlib and sasl libs,
+%% and also return the rest of the libs as a list.
+%% Return error if any of kernel, stdlib or sasl does not exist.
+get_base_libs(Libs) ->
+ get_base_libs(Libs,undefined,undefined,undefined,[]).
+get_base_libs([{kernel,_,_}=Kernel|Libs],undefined,Stdlib,Sasl,Rest) ->
+ get_base_libs(Libs,Kernel,Stdlib,Sasl,Rest);
+get_base_libs([{stdlib,_,_}=Stdlib|Libs],Kernel,undefined,Sasl,Rest) ->
+ get_base_libs(Libs,Kernel,Stdlib,Sasl,Rest);
+get_base_libs([{sasl,_,_}=Sasl|Libs],Kernel,Stdlib,undefined,Rest) ->
+ get_base_libs(Libs,Kernel,Stdlib,Sasl,Rest);
+get_base_libs([Lib|Libs],Kernel,Stdlib,Sasl,Rest) ->
+ get_base_libs(Libs,Kernel,Stdlib,Sasl,[Lib|Rest]);
+get_base_libs([],undefined,_Stdlib,_Sasl,_Rest) ->
+ {error,{missing,kernel}};
+get_base_libs([],_Kernel,undefined,_Sasl,_Rest) ->
+ {error,{missing,stdlib}};
+get_base_libs([],_Kernel,_Stdlib,undefined,_Rest) ->
+ {error,{missing,sasl}};
+get_base_libs([],Kernel,Stdlib,Sasl,Rest) ->
+ {ok,{Kernel,Stdlib,Sasl},lists:reverse(Rest)}.
+
+new_emulator_make_hybrid_boot(CurrentVsn,ToVsn,TmpVsn,BaseLibs,RelDir,Opts,Masters) ->
+ FromBootFile = filename:join([RelDir,CurrentVsn,"start.boot"]),
+ ToBootFile = filename:join([RelDir,ToVsn,"start.boot"]),
+ TmpBootFile = filename:join([RelDir,TmpVsn,"start.boot"]),
+ ensure_dir(TmpBootFile,Masters),
+ Args = [ToVsn,Opts],
+ {ok,FromBoot} = read_file(FromBootFile,Masters),
+ {ok,ToBoot} = read_file(ToBootFile,Masters),
+ {{_,_,KernelPath},{_,_,SaslPath},{_,_,StdlibPath}} = BaseLibs,
+ Paths = {filename:join(KernelPath,"ebin"),
+ filename:join(StdlibPath,"ebin"),
+ filename:join(SaslPath,"ebin")},
+ case systools_make:make_hybrid_boot(TmpVsn,FromBoot,ToBoot,Paths,Args) of
+ {ok,TmpBoot} ->
+ write_file(TmpBootFile,TmpBoot,Masters);
+ {error,Reason} ->
+ throw({error,{could_not_create_hybrid_boot,Reason}})
+ end.
+
+new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
+ FromFile = filename:join([RelDir,CurrentVsn,"sys.config"]),
+ ToFile = filename:join([RelDir,ToVsn,"sys.config"]),
+ TmpFile = filename:join([RelDir,TmpVsn,"sys.config"]),
+
+ FromConfig =
+ case consult(FromFile,Masters) of
+ {ok,[FC]} ->
+ FC;
+ {error,Error1} ->
+ io:format("Warning: ~p can not read ~p: ~p~n",
+ [?MODULE,FromFile,Error1]),
+ []
+ end,
+
+ [Kernel,Stdlib,Sasl] =
+ case consult(ToFile,Masters) of
+ {ok,[ToConfig]} ->
+ [lists:keyfind(App,1,ToConfig) || App <- [kernel,stdlib,sasl]];
+ {error,Error2} ->
+ io:format("Warning: ~p can not read ~p: ~p~n",
+ [?MODULE,ToFile,Error2]),
+ [false,false,false]
+ end,
+
+ Config1 = replace_config(kernel,FromConfig,Kernel),
+ Config2 = replace_config(stdlib,Config1,Stdlib),
+ Config3 = replace_config(sasl,Config2,Sasl),
+
+ ConfigStr = io_lib:format("~p.~n",[Config3]),
+ write_file(TmpFile,ConfigStr,Masters).
+
+%% Take the configuration for application App from the new config and
+%% insert in the old config.
+%% If no entry exists in the new config, then delete the entry (if it exists)
+%% from the old config.
+%% If entry exists in the new config, but not in the old config, then
+%% add the entry.
+replace_config(App,Config,false) ->
+ lists:keydelete(App,1,Config);
+replace_config(App,Config,AppConfig) ->
+ lists:keystore(App,1,Config,AppConfig).
+
+%% Remove all files related to the temporary release
+new_emulator_rm_tmp_release(?tmp_vsn(_)=TmpVsn,EVsn,NewVsn,
+ RelDir,Releases,Masters) ->
+ case os:type() of
+ {win32, nt} ->
+ rename_tmp_service(EVsn,TmpVsn,NewVsn);
+ _ ->
+ ok
+ end,
+ remove_dir(filename:join(RelDir,TmpVsn),Masters),
+ lists:keydelete(TmpVsn,#release.vsn,Releases);
+new_emulator_rm_tmp_release(_,_,_,_,Releases,_) ->
+ Releases.
+
+%% Rename the tempoarary service (for erts ugprade) to the real ToVsn
+rename_tmp_service(EVsn,TmpVsn,NewVsn) ->
+ FromName = hd(string:tokens(atom_to_list(node()),"@")) ++ "_" ++ TmpVsn,
+ ToName = hd(string:tokens(atom_to_list(node()),"@")) ++ "_" ++ NewVsn,
+ case erlsrv:get_service(EVsn,ToName) of
+ {error, _Error} ->
+ ok;
+ _Data ->
+ erlsrv:remove_service(ToName)
+ end,
+ rename_service(EVsn,FromName,ToName).
+
+
+%% Rename a service and check that it succeeded
+rename_service(EVsn,FromName,ToName) ->
+ case erlsrv:rename_service(EVsn,FromName,ToName) of
+ {ok,_} ->
+ case erlsrv:get_service(EVsn,ToName) of
+ {error,Error1} ->
+ throw({error,Error1});
+ _Data2 ->
+ ok
+ end;
+ Error2 ->
+ throw({error,{service_rename_failed, Error2}})
+ end.
+
+
%%% This code chunk updates the services in one of two ways,
%%% Either the emulator is restarted, in which case the old service
%%% is to be removed and the new enabled, or the emulator is NOT restarted
@@ -1002,26 +1219,16 @@ do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) ->
%% rename.
case os:getenv("ERLSRV_SERVICE_NAME") == PermName of
true ->
- case erlsrv:rename_service(EVsn,PermName,Name) of
- {ok,_} ->
- case erlsrv:get_service(EVsn,Name) of
- {error,Error2} ->
- throw({error,Error2});
- _Data2 ->
- %% The interfaces for doing this are
- %% NOT published and may be subject to
- %% change. Do NOT do this anywhere else!
-
- os:putenv("ERLSRV_SERVICE_NAME", Name),
-
- %% Restart heart port program, this
- %% function is only to be used here.
- heart:cycle(),
- ok
- end;
- Error3 ->
- throw({error,{service_rename_failed, Error3}})
- end;
+ rename_service(EVsn,PermName,Name),
+ %% The interfaces for doing this are
+ %% NOT published and may be subject to
+ %% change. Do NOT do this anywhere else!
+
+ os:putenv("ERLSRV_SERVICE_NAME", Name),
+
+ %% Restart heart port program, this
+ %% function is only to be used here.
+ heart:cycle();
false ->
throw({error,service_name_missmatch})
end;
@@ -1260,21 +1467,31 @@ do_set_removed(RelDir, Vsn, Releases, Masters) ->
%% corresponding relup instructions, we check if it's possible to
%% downgrade from CurrentVsn to ToVsn.
%%-----------------------------------------------------------------
+get_rh_script(#release{vsn = ?tmp_vsn(CurrentVsn)},
+ #release{vsn = ToVsn},
+ RelDir,
+ Masters) ->
+ {ok,{Vsn,Descr,[restart_new_emulator|Script]}} =
+ do_get_rh_script(CurrentVsn,ToVsn,RelDir,Masters),
+ {ok,{Vsn,Descr,Script}};
get_rh_script(#release{vsn = CurrentVsn},
- #release{vsn = Vsn},
+ #release{vsn = ToVsn},
RelDir,
Masters) ->
- Relup = filename:join([RelDir, Vsn, "relup"]),
- case try_upgrade(Vsn, CurrentVsn, Relup, Masters) of
+ do_get_rh_script(CurrentVsn,ToVsn,RelDir,Masters).
+
+do_get_rh_script(CurrentVsn, ToVsn, RelDir, Masters) ->
+ Relup = filename:join([RelDir, ToVsn, "relup"]),
+ case try_upgrade(ToVsn, CurrentVsn, Relup, Masters) of
{ok, RhScript} ->
{ok, RhScript};
_ ->
Relup2 = filename:join([RelDir, CurrentVsn,"relup"]),
- case try_downgrade(Vsn, CurrentVsn, Relup2, Masters) of
+ case try_downgrade(ToVsn, CurrentVsn, Relup2, Masters) of
{ok, RhScript} ->
{ok, RhScript};
_ ->
- throw({error, {no_matching_relup, Vsn, CurrentVsn}})
+ throw({error, {no_matching_relup, ToVsn, CurrentVsn}})
end
end.
@@ -1355,7 +1572,7 @@ memlib(_Lib, []) -> false.
%% recursively remove file or directory
remove_file(File) ->
- case file:read_file_info(File) of
+ case file:read_link_info(File) of
{ok, Info} when Info#file_info.type==directory ->
case file:list_dir(File) of
{ok, Files} ->
@@ -1487,6 +1704,15 @@ prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
%% restart is performed by calling init:reboot() higher up.
%%-----------------------------------------------------------------
prepare_restart_new_emulator(StartPrg, RootDir, RelDir,
+ Vsn, Release, Releases, Masters) ->
+ {value, PRelease} = lists:keysearch(permanent, #release.status,Releases),
+ NReleases1 = set_status(Vsn, current, Releases),
+ NReleases2 = set_status(Vsn,tmp_current,NReleases1),
+ write_releases(RelDir, NReleases2, Masters),
+ prepare_restart_new_emulator(StartPrg, RootDir, RelDir,
+ Release, PRelease, Masters).
+
+prepare_restart_new_emulator(StartPrg, RootDir, RelDir,
Release, PRelease, Masters) ->
#release{erts_vsn = EVsn, vsn = Vsn} = Release,
Data = EVsn ++ " " ++ Vsn,
@@ -1512,19 +1738,10 @@ check_start_prg({do_check, StartPrg}, Masters) ->
check_start_prg({_, StartPrg}, _) ->
StartPrg.
-write_new_start_erl(Data, RelDir, false) ->
- DataFile = filename:join([RelDir, "new_start_erl.data"]),
- case do_write_file(DataFile, Data) of
- ok -> DataFile;
- Error -> throw(Error)
- end;
write_new_start_erl(Data, RelDir, Masters) ->
DataFile = filename:join([RelDir, "new_start_erl.data"]),
- case at_all_masters(Masters, ?MODULE, do_write_file,
- [DataFile, Data]) of
- ok -> DataFile;
- Error -> throw(Error)
- end.
+ write_file(DataFile, Data, Masters),
+ DataFile.
%%-----------------------------------------------------------------
%% When a new emulator shall be restarted, the current release
@@ -1538,27 +1755,41 @@ write_new_start_erl(Data, RelDir, Masters) ->
%% If the release is made permanent, this is written to disk.
%%-----------------------------------------------------------------
transform_release(ReleaseDir, Releases, Masters) ->
- F = fun(Release) when Release#release.status == tmp_current ->
- Release#release{status = unpacked};
- (Release) -> Release
- end,
- case lists:map(F, Releases) of
- Releases ->
- Releases;
- DReleases ->
+ case init:script_id() of
+ {Name, ?tmp_vsn(_)=TmpVsn} ->
+ %% This is was a reboot due to a new emulator version. The
+ %% current release is a temporary internal release, which
+ %% must be removed. It is the "real new release" that is
+ %% set to unpacked on disk and current in memory.
+ DReleases = lists:keydelete(TmpVsn,#release.vsn,Releases),
write_releases(ReleaseDir, DReleases, Masters),
- F1 = fun(Release) when Release#release.status == tmp_current ->
- case init:script_id() of
- {_Name, Vsn} when Release#release.vsn == Vsn ->
- Release#release{status = current};
- _ ->
- Release#release{status = unpacked}
- end;
- (Release) -> Release
- end,
- lists:map(F1, Releases)
+ set_current({Name,TmpVsn},Releases);
+ ScriptId ->
+ F = fun(Release) when Release#release.status == tmp_current ->
+ Release#release{status = unpacked};
+ (Release) -> Release
+ end,
+ case lists:map(F, Releases) of
+ Releases ->
+ Releases;
+ DReleases ->
+ write_releases(ReleaseDir, DReleases, Masters),
+ set_current(ScriptId, Releases)
+ end
end.
+set_current(ScriptId, Releases) ->
+ F1 = fun(Release) when Release#release.status == tmp_current ->
+ case ScriptId of
+ {_Name,Vsn} when Release#release.vsn == Vsn ->
+ Release#release{status = current};
+ _ ->
+ Release#release{status = unpacked}
+ end;
+ (Release) -> Release
+ end,
+ lists:map(F1, Releases).
+
%%-----------------------------------------------------------------
%% Functions handling files, RELEASES, start_erl.data etc.
%% This functions consider if the release_handler is a client and
@@ -1617,12 +1848,25 @@ extract_tar(Root, Tar) ->
throw({error, {cannot_extract_file, Name, Reason}})
end.
-write_releases(Dir, NewReleases, false) ->
+write_releases(Dir, Releases, Masters) ->
+ %% We must never write 'current' to disk, since this will confuse
+ %% us after a node restart - since we would then have a permanent
+ %% release running, but state set to current for a non-running
+ %% release.
+ NewReleases = lists:zf(fun(Release) when Release#release.status == current ->
+ {true, Release#release{status = unpacked}};
+ (_) ->
+ true
+ end, Releases),
+ write_releases_1(Dir, NewReleases, Masters).
+
+
+write_releases_1(Dir, NewReleases, false) ->
case do_write_release(Dir, "RELEASES", NewReleases) of
ok -> ok;
Error -> throw(Error)
end;
-write_releases(Dir, NewReleases, Masters) ->
+write_releases_1(Dir, NewReleases, Masters) ->
all_masters(Masters),
write_releases_m(Dir, NewReleases, Masters).
@@ -1844,6 +2088,37 @@ read_file(File, false) ->
read_file(File, Masters) ->
read_master(Masters, File).
+write_file(File, Data, false) ->
+ case file:write_file(File, Data) of
+ ok -> ok;
+ Error -> throw(Error)
+ end;
+write_file(File, Data, Masters) ->
+ case at_all_masters(Masters, file, write_file, [File, Data]) of
+ ok -> ok;
+ Error -> throw(Error)
+ end.
+
+ensure_dir(File, false) ->
+ case filelib:ensure_dir(File) of
+ ok -> ok;
+ Error -> throw(Error)
+ end;
+ensure_dir(File, Masters) ->
+ case at_all_masters(Masters,filelib,ensure_dir,[File]) of
+ ok -> ok;
+ Error -> throw(Error)
+ end.
+
+remove_dir(Dir, false) ->
+ remove_file(Dir);
+remove_dir(Dir, Masters) ->
+ case at_all_masters(Masters,?MODULE,remove_file,[Dir]) of
+ ok -> ok;
+ Error -> throw(Error)
+ end.
+
+
%% Ignore status of each delete !
remove_files(Master, Files, Masters) ->
takewhile(Master, Masters, ?MODULE, do_remove_files, [Files]).
@@ -2010,3 +2285,14 @@ get_new_libs([{App,Vsn,_LibDir}|CurrentLibs], NewLibs) ->
end;
get_new_libs([],_) ->
[].
+
+%%-----------------------------------------------------------------
+%% Return a list of releases witch a specific status
+%%-----------------------------------------------------------------
+get_releases_with_status([], _, Acc) ->
+ Acc;
+get_releases_with_status([ {_, _, _, ReleaseStatus } = Head | Tail],
+ Status, Acc) when ReleaseStatus == Status ->
+ get_releases_with_status(Tail, Status, [Head | Acc]);
+get_releases_with_status([_ | Tail], Status, Acc) ->
+ get_releases_with_status(Tail, Status, Acc).
diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl
index 8d0baf3ab1..93d12cf609 100644
--- a/lib/sasl/src/release_handler_1.erl
+++ b/lib/sasl/src/release_handler_1.erl
@@ -47,26 +47,38 @@
%%%-----------------------------------------------------------------
%%% This is a low-level release handler.
%%%-----------------------------------------------------------------
+check_script([restart_new_emulator|Script], LibDirs) ->
+ %% There is no need to check for old processes, since the node
+ %% will be restarted before anything else happens.
+ do_check_script(Script, LibDirs, []);
check_script(Script, LibDirs) ->
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,PurgeMods};
- {error, Error} ->
- {error, Error};
- Other ->
- {error, Other}
- end;
+ do_check_script(Script, LibDirs, PurgeMods);
{error, Mod} ->
{error, {old_processes, Mod}}
end.
+do_check_script(Script, LibDirs, 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) ->
+ case catch syntax_check_script(After) of
+ ok ->
+ {ok,PurgeMods};
+ Other ->
+ {error,Other}
+ end;
+ {error, Error} ->
+ {error, Error};
+ Other ->
+ {error, Other}
+ end.
+
%% eval_script/1 - For testing only - no apps added, just testing instructions
eval_script(Script) ->
eval_script(Script, [], [], [], []).
@@ -83,22 +95,30 @@ eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
newlibs = NewLibs,
opts = Opts},
Before) of
- EvalState2 when is_record(EvalState2, eval_state) ->
- case catch lists:foldl(fun(Instruction, EvalState3) ->
- eval(Instruction, EvalState3)
- end,
- EvalState2,
- After) of
- EvalState4 when is_record(EvalState4, eval_state) ->
- {ok, EvalState4#eval_state.unpurged};
- restart_new_emulator ->
- restart_new_emulator;
- Error ->
- {'EXIT', Error}
- end;
- {error, Error} -> {error, Error};
- Other -> {error, Other}
- end;
+ EvalState2 when is_record(EvalState2, eval_state) ->
+ case catch syntax_check_script(After) of
+ ok ->
+ case catch lists:foldl(
+ fun(Instruction, EvalState3) ->
+ eval(Instruction,
+ EvalState3)
+ end,
+ EvalState2,
+ After) of
+ EvalState4
+ when is_record(EvalState4, eval_state) ->
+ {ok, EvalState4#eval_state.unpurged};
+ restart_emulator ->
+ restart_emulator;
+ Error ->
+ {'EXIT', Error}
+ end;
+ Other ->
+ {error,Other}
+ end;
+ {error, Error} -> {error, Error};
+ Other -> {error, Other}
+ end;
{error, Mod} ->
{error, {old_processes, Mod}}
end.
@@ -174,6 +194,42 @@ do_check_old_code(Mod,Procs) ->
[Mod].
+%% Check the last part of the script, i.e. the part after point_of_no_return.
+%% More or less a syntax check in case the script was handwritten.
+syntax_check_script([point_of_no_return | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{load, {_,_,_}} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{remove, {_,_,_}} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{purge, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{suspend, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{resume, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{code_change, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{code_change, _, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{stop, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{start, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{sync_nodes, _, {_,_,_}} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{sync_nodes, _, _} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([{apply, {_,_,_}} | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([restart_emulator | Script]) ->
+ syntax_check_script(Script);
+syntax_check_script([Illegal | _Script]) ->
+ throw({illegal_instruction_after_point_of_no_return,Illegal});
+syntax_check_script([]) ->
+ ok.
+
+
%%-----------------------------------------------------------------
%% An unpurged module is a module for which there exist an old
%% version of the code. This should only be the case if there are
@@ -243,7 +299,7 @@ do_check_old_code(Mod,Procs) ->
%% must also exectue the same line. Waits for all these nodes to get
%% to this line.
%% point_of_no_return
-%% restart_new_emulator
+%% restart_emulator
%% {stop_application, Appl} - Impl with apply
%% {unload_application, Appl} - Impl with {remove..}
%% {load_application, Appl} - Impl with {load..}
@@ -402,6 +458,8 @@ eval({sync_nodes, Id, Nodes}, EvalState) ->
eval({apply, {M, F, A}}, EvalState) ->
apply(M, F, A),
EvalState;
+eval(restart_emulator, _EvalState) ->
+ throw(restart_emulator);
eval(restart_new_emulator, _EvalState) ->
throw(restart_new_emulator).
@@ -447,15 +505,20 @@ resume(Pids) ->
change_code(Pids, Mod, Vsn, Extra, Timeout) ->
Fun = fun(Pid) ->
- case Timeout of
- default ->
- ok = sys:change_code(Pid, Mod, Vsn, Extra);
- _Else ->
- ok = sys:change_code(Pid, Mod, Vsn, Extra, Timeout)
+ case sys_change_code(Pid, Mod, Vsn, Extra, Timeout) of
+ ok ->
+ ok;
+ {error,Reason} ->
+ throw({code_change_failed,Pid,Mod,Vsn,Reason})
end
end,
lists:foreach(Fun, Pids).
+sys_change_code(Pid, Mod, Vsn, Extra, default) ->
+ sys:change_code(Pid, Mod, Vsn, Extra);
+sys_change_code(Pid, Mod, Vsn, Extra, Timeout) ->
+ sys:change_code(Pid, Mod, Vsn, Extra, Timeout).
+
stop(Mod, Procs) ->
lists:zf(fun({undefined, _Name, _Pid, _Mods}) ->
false;
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index 64c653a4e5..ce4aa1f8f8 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -1,25 +1,27 @@
-%%
+%% -*- erlang -*-
%% %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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, 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%
{"%VSN%",
- [{"2.1.4", [{load_module, release_handler},
- {load_module, systools_relup}]}],
- [{"2.1.4", [{load_module, release_handler},
- {load_module, systools_relup}]}]
+ %% Up from - max two major revisions back
+ [{<<"2\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"2\\.1\\.10(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14B04 (and later?)
+ {<<"2\\.1\\.[6-9](\\.[0-9]+)*">>,[restart_new_emulator]}],%% R13B-R14B03
+ %% Down to - max two major revisions back
+ [{<<"2\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"2\\.1\\.10(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14B04 (and later?)
+ {<<"2\\.1\\.[6-9](\\.[0-9]+)*">>,[restart_new_emulator]}] %% R13B-R14B03
}.
diff --git a/lib/sasl/src/systools.hrl b/lib/sasl/src/systools.hrl
index 9a3e98221c..da531dbee5 100644
--- a/lib/sasl/src/systools.hrl
+++ b/lib/sasl/src/systools.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% integer() | infinity.
mod = [], %% [] | {Mod, StartArgs}, Mod= atom(),
%% StartArgs = list().
- start_phases = [], %% [] | {Phase, PhaseArgs}, Phase = atom(),
+ start_phases, %% [{Phase, PhaseArgs}] | undefined,
+ %% Phase = atom(),
%% PhaseArgs = list().
dir = "" %% The directory where the .app file was
%% found (internal use).
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 7f400f5cce..61e660e918 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,6 +31,8 @@
-export([read_application/4]).
+-export([make_hybrid_boot/5]).
+
-import(lists, [filter/2, keysort/2, keysearch/3, map/2, reverse/1,
append/1, foldl/3, member/2, foreach/2]).
@@ -56,6 +58,7 @@
%% {variables,[{Name,AbsString}]}
%% {machine, jam | beam | vee}
%% exref | {exref, [AppName]}
+%% no_warn_sasl
%%-----------------------------------------------------------------
make_script(RelName) when is_list(RelName) ->
@@ -86,7 +89,8 @@ make_script(RelName, Output, Flags) when is_list(RelName),
Path = make_set(Path1 ++ code:get_path()),
ModTestP = {member(src_tests, Flags),xref_p(Flags)},
case get_release(RelName, Path, ModTestP, machine(Flags)) of
- {ok, Release, Appls, Warnings} ->
+ {ok, Release, Appls, Warnings0} ->
+ Warnings = wsasl(Flags, Warnings0),
case systools_lib:werror(Flags, Warnings) of
true ->
return(ok,Warnings,Flags);
@@ -110,7 +114,13 @@ make_script(RelName, _Output, Flags) when is_list(Flags) ->
make_script(RelName, _Output, Flags) ->
badarg(Flags,[RelName, Flags]).
-%% Inlined.
+
+wsasl(Options, Warnings) ->
+ case lists:member(no_warn_sasl,Options) of
+ true -> lists:delete({warning,missing_sasl},Warnings);
+ false -> Warnings
+ end.
+
badarg(BadArg, Args) ->
erlang:error({badarg,BadArg}, Args).
@@ -162,6 +172,118 @@ return({error,Mod,Error},_,Flags) ->
error
end.
+
+%%-----------------------------------------------------------------
+%% Make hybrid boot file for upgrading emulator. The resulting boot
+%% file is a combination of the two input files, where kernel, stdlib
+%% and sasl versions are taken from the second file (the boot file of
+%% the new release), and all other application versions from the first
+%% file (the boot file of the old release).
+%%
+%% The most important thing that can fail here is that the input boot
+%% files do not contain all three base applications - kernel, stdlib
+%% and sasl.
+%%
+%% TmpVsn = string(),
+%% Paths = {KernelPath,StdlibPath,SaslPath}
+%% Returns {ok,Boot} | {error,Reason}
+%% Boot1 = Boot2 = Boot = binary()
+%% Reason = {app_not_found,App} | {app_not_replaced,App}
+%% App = kernel | stdlib | sasl
+make_hybrid_boot(TmpVsn, Boot1, Boot2, Paths, Args) ->
+ catch do_make_hybrid_boot(TmpVsn, Boot1, Boot2, Paths, Args).
+do_make_hybrid_boot(TmpVsn, Boot1, Boot2, Paths, Args) ->
+ {script,{_RelName1,_RelVsn1},Script1} = binary_to_term(Boot1),
+ {script,{RelName2,_RelVsn2},Script2} = binary_to_term(Boot2),
+ MatchPaths = get_regexp_path(Paths),
+ NewScript1 = replace_paths(Script1,MatchPaths),
+ {Kernel,Stdlib,Sasl} = get_apps(Script2,undefined,undefined,undefined),
+ NewScript2 = replace_apps(NewScript1,Kernel,Stdlib,Sasl),
+ NewScript3 = add_apply_upgrade(NewScript2,Args),
+ Boot = term_to_binary({script,{RelName2,TmpVsn},NewScript3}),
+ {ok,Boot}.
+
+%% For each app, compile a regexp that can be used for finding its path
+get_regexp_path({KernelPath,StdlibPath,SaslPath}) ->
+ {ok,KernelMP} = re:compile("kernel-[0-9\.]+",[unicode]),
+ {ok,StdlibMP} = re:compile("stdlib-[0-9\.]+",[unicode]),
+ {ok,SaslMP} = re:compile("sasl-[0-9\.]+",[unicode]),
+ [{KernelMP,KernelPath},{StdlibMP,StdlibPath},{SaslMP,SaslPath}].
+
+%% For each path in the script, check if it matches any of the MPs
+%% found above, and if so replace it with the correct new path.
+replace_paths([{path,Path}|Script],MatchPaths) ->
+ [{path,replace_path(Path,MatchPaths)}|replace_paths(Script,MatchPaths)];
+replace_paths([Stuff|Script],MatchPaths) ->
+ [Stuff|replace_paths(Script,MatchPaths)];
+replace_paths([],_) ->
+ [].
+
+replace_path([Path|Paths],MatchPaths) ->
+ [do_replace_path(Path,MatchPaths)|replace_path(Paths,MatchPaths)];
+replace_path([],_) ->
+ [].
+
+do_replace_path(Path,[{MP,ReplacePath}|MatchPaths]) ->
+ case re:run(Path,MP,[{capture,none}]) of
+ nomatch -> do_replace_path(Path,MatchPaths);
+ match -> ReplacePath
+ end;
+do_replace_path(Path,[]) ->
+ Path.
+
+%% Return the entries for loading the three base applications
+get_apps([{kernelProcess,application_controller,
+ {application_controller,start,[{application,kernel,_}]}}=Kernel|
+ Script],_,Stdlib,Sasl) ->
+ get_apps(Script,Kernel,Stdlib,Sasl);
+get_apps([{apply,{application,load,[{application,stdlib,_}]}}=Stdlib|Script],
+ Kernel,_,Sasl) ->
+ get_apps(Script,Kernel,Stdlib,Sasl);
+get_apps([{apply,{application,load,[{application,sasl,_}]}}=Sasl|_Script],
+ Kernel,Stdlib,_) ->
+ {Kernel,Stdlib,Sasl};
+get_apps([_|Script],Kernel,Stdlib,Sasl) ->
+ get_apps(Script,Kernel,Stdlib,Sasl);
+get_apps([],undefined,_,_) ->
+ throw({error,{app_not_found,kernel}});
+get_apps([],_,undefined,_) ->
+ throw({error,{app_not_found,stdlib}});
+get_apps([],_,_,undefined) ->
+ throw({error,{app_not_found,sasl}}).
+
+
+%% Replace the entries for loading the base applications
+replace_apps([{kernelProcess,application_controller,
+ {application_controller,start,[{application,kernel,_}]}}|
+ Script],Kernel,Stdlib,Sasl) ->
+ [Kernel|replace_apps(Script,undefined,Stdlib,Sasl)];
+replace_apps([{apply,{application,load,[{application,stdlib,_}]}}|Script],
+ Kernel,Stdlib,Sasl) ->
+ [Stdlib|replace_apps(Script,Kernel,undefined,Sasl)];
+replace_apps([{apply,{application,load,[{application,sasl,_}]}}|Script],
+ _Kernel,_Stdlib,Sasl) ->
+ [Sasl|Script];
+replace_apps([Stuff|Script],Kernel,Stdlib,Sasl) ->
+ [Stuff|replace_apps(Script,Kernel,Stdlib,Sasl)];
+replace_apps([],undefined,undefined,_) ->
+ throw({error,{app_not_replaced,sasl}});
+replace_apps([],undefined,_,_) ->
+ throw({error,{app_not_replaced,stdlib}});
+replace_apps([],_,_,_) ->
+ throw({error,{app_not_replaced,kernel}}).
+
+
+%% Finally add an apply of release_handler:new_emulator_upgrade - which will
+%% complete the execution of the upgrade script (relup).
+add_apply_upgrade(Script,Args) ->
+ [{progress, started} | RevScript] = lists:reverse(Script),
+ lists:reverse([{progress,started},
+ {apply,{release_handler,new_emulator_upgrade,Args}} |
+ RevScript]).
+
+
+
%%-----------------------------------------------------------------
%% Create a release package from a release file.
%% Options is a list of {path, Path} | silent |
@@ -250,13 +372,13 @@ get_release(File, Path, ModTestP, Machine) ->
end.
get_release1(File, Path, ModTestP, Machine) ->
- {ok, Release} = read_release(File, Path),
+ {ok, Release, Warnings1} = read_release(File, Path),
{ok, Appls0} = collect_applications(Release, Path),
{ok, Appls1} = check_applications(Appls0),
- {ok, Appls2} = sort_included_applications(Appls1, Release), % OTP-4121
- {ok, Warnings} = check_modules(Appls2, Path, ModTestP, Machine),
+ {ok, Appls2} = sort_used_and_incl_appls(Appls1, Release), % OTP-4121, OTP-9984
+ {ok, Warnings2} = check_modules(Appls2, Path, ModTestP, Machine),
{ok, Appls} = sort_appls(Appls2),
- {ok, Release, Appls, Warnings}.
+ {ok, Release, Appls, Warnings1 ++ Warnings2}.
%%______________________________________________________________________
%% read_release(File, Path) -> {ok, #release} | throw({error, What})
@@ -271,11 +393,12 @@ read_release(File, Path) ->
check_rel(Release) ->
case catch check_rel1(Release) of
- {ok, {Name,Vsn,Evsn,Appl,Incl}} ->
+ {ok, {Name,Vsn,Evsn,Appl,Incl}, Ws} ->
{ok, #release{name=Name, vsn=Vsn,
erts_vsn=Evsn,
applications=Appl,
- incl_apps=Incl}};
+ incl_apps=Incl},
+ Ws};
{error, Error} ->
throw({error,?MODULE,Error});
Error ->
@@ -286,8 +409,8 @@ check_rel1({release,{Name,Vsn},{erts,EVsn},Appl}) when is_list(Appl) ->
check_name(Name),
check_vsn(Vsn),
check_evsn(EVsn),
- {Appls,Incls} = check_appl(Appl),
- {ok, {Name,Vsn,EVsn,Appls,Incls}};
+ {{Appls,Incls},Ws} = check_appl(Appl),
+ {ok, {Name,Vsn,EVsn,Appls,Incls},Ws};
check_rel1(_) ->
{error, badly_formatted_release}.
@@ -340,25 +463,35 @@ check_appl(Appl) ->
end,
Appl) of
[] ->
- mandatory_applications(Appl),
- split_app_incl(Appl);
+ {ApplsNoIncls,Incls} = split_app_incl(Appl),
+ {ok,Ws} = mandatory_applications(ApplsNoIncls,undefined,
+ undefined,undefined),
+ {{ApplsNoIncls,Incls},Ws};
Illegal ->
throw({error, {illegal_applications,Illegal}})
end.
-mandatory_applications(Appl) ->
- AppNames = map(fun(AppT) -> element(1, AppT) end,
- Appl),
- Mand = mandatory_applications(),
- case filter(fun(X) -> member(X, AppNames) end, Mand) of
- Mand ->
- ok;
- _ ->
- throw({error, {missing_mandatory_app, Mand}})
- end.
-
-mandatory_applications() ->
- [kernel, stdlib].
+mandatory_applications([{kernel,_,Type}|Apps],undefined,Stdlib,Sasl) ->
+ mandatory_applications(Apps,Type,Stdlib,Sasl);
+mandatory_applications([{stdlib,_,Type}|Apps],Kernel,undefined,Sasl) ->
+ mandatory_applications(Apps,Kernel,Type,Sasl);
+mandatory_applications([{sasl,_,Type}|Apps],Kernel,Stdlib,undefined) ->
+ mandatory_applications(Apps,Kernel,Stdlib,Type);
+mandatory_applications([_|Apps],Kernel,Stdlib,Sasl) ->
+ mandatory_applications(Apps,Kernel,Stdlib,Sasl);
+mandatory_applications([],Type,_,_) when Type=/=permanent ->
+ error_mandatory_application(kernel,Type);
+mandatory_applications([],_,Type,_) when Type=/=permanent ->
+ error_mandatory_application(stdlib,Type);
+mandatory_applications([],_,_,undefined) ->
+ {ok, [{warning,missing_sasl}]};
+mandatory_applications([],_,_,_) ->
+ {ok,[]}.
+
+error_mandatory_application(App,undefined) ->
+ throw({error, {missing_mandatory_app, App}});
+error_mandatory_application(App,Type) ->
+ throw({error, {mandatory_app, App, Type}}).
split_app_incl(Appl) -> split_app_incl(Appl, [], []).
@@ -709,34 +842,45 @@ undefined_applications(Appls) ->
filter(fun(X) -> not member(X, Defined) end, Uses).
%%______________________________________________________________________
-%% sort_included_applications(Applications, Release) -> Applications
+%% sort_used_and_incl_appls(Applications, Release) -> Applications
%% Applications = [{{Name,Vsn},#application}]
%% Release = #release{}
%%
-%% Check that included applications are given in the same order as in
-%% the release resource file (.rel). Otherwise load instructions in
-%% the boot script, and consequently release upgrade instructions in
-%% relup, may end up in the wrong order.
+%% OTP-4121, OTP-9984
+%% Check that used and included applications are given in the same
+%% order as in the release resource file (.rel). Otherwise load and
+%% start instructions in the boot script, and consequently release
+%% upgrade instructions in relup, may end up in the wrong order.
-sort_included_applications(Applications, Release) when is_tuple(Release) ->
+sort_used_and_incl_appls(Applications, Release) when is_tuple(Release) ->
{ok,
- sort_included_applications(Applications, Release#release.applications)};
-
-sort_included_applications([{Tuple,Appl}|Appls], OrderedAppls) ->
- case Appl#application.includes of
- Incls when length(Incls)>1 ->
- IndexedIncls = find_pos(Incls, OrderedAppls),
- SortedIndexedIncls = lists:keysort(1, IndexedIncls),
- Incls2 = lists:map(fun({_Index,Name}) -> Name end,
- SortedIndexedIncls),
- Appl2 = Appl#application{includes=Incls2},
- [{Tuple,Appl2}|sort_included_applications(Appls, OrderedAppls)];
- _Incls ->
- [{Tuple,Appl}|sort_included_applications(Appls, OrderedAppls)]
- end;
-sort_included_applications([], _OrderedAppls) ->
+ sort_used_and_incl_appls(Applications, Release#release.applications)};
+
+sort_used_and_incl_appls([{Tuple,Appl}|Appls], OrderedAppls) ->
+ Incls2 =
+ case Appl#application.includes of
+ Incls when length(Incls)>1 ->
+ sort_appl_list(Incls, OrderedAppls);
+ Incls ->
+ Incls
+ end,
+ Uses2 =
+ case Appl#application.uses of
+ Uses when length(Uses)>1 ->
+ sort_appl_list(Uses, OrderedAppls);
+ Uses ->
+ Uses
+ end,
+ Appl2 = Appl#application{includes=Incls2, uses=Uses2},
+ [{Tuple,Appl2}|sort_used_and_incl_appls(Appls, OrderedAppls)];
+sort_used_and_incl_appls([], _OrderedAppls) ->
[].
+sort_appl_list(List, Order) ->
+ IndexedList = find_pos(List, Order),
+ SortedIndexedList = lists:keysort(1, IndexedList),
+ lists:map(fun({_Index,Name}) -> Name end, SortedIndexedList).
+
find_pos([Name|Incs], OrderedAppls) ->
[find_pos(1, Name, OrderedAppls)|find_pos(Incs, OrderedAppls)];
find_pos([], _OrderedAppls) ->
@@ -1120,7 +1264,8 @@ sort_appls(Appls) -> {ok, sort_appls(Appls, [], [], [])}.
sort_appls([{N, A}|T], Missing, Circular, Visited) ->
{Name,_Vsn} = N,
- {Uses, T1, NotFnd1} = find_all(Name, A#application.uses, T, Visited, [], []),
+ {Uses, T1, NotFnd1} = find_all(Name, lists:reverse(A#application.uses),
+ T, Visited, [], []),
{Incs, T2, NotFnd2} = find_all(Name, lists:reverse(A#application.includes),
T1, Visited, [], []),
Missing1 = NotFnd1 ++ NotFnd2 ++ Missing,
@@ -1323,15 +1468,18 @@ pack_app(#application{name=Name,vsn=V,id=Id,description=D,modules=M,
{applications, App},
{included_applications, Incs},
{env, Env},
- {start_phases, SF},
{maxT, MaxT},
{maxP, MaxP} |
- behave(Mod)]}.
-
+ behave([{start_phases,SF},{mod,Mod}])]}.
+
+behave([{mod,[]}|T]) ->
+ behave(T);
+behave([{start_phases,undefined}|T]) ->
+ behave(T);
+behave([H|T]) ->
+ [H|behave(T)];
behave([]) ->
- [];
-behave(Mod) ->
- [{mod, Mod}].
+ [].
%%______________________________________________________________________
%% mandatory modules; this modules must be loaded before processes
@@ -1510,8 +1658,19 @@ add_system_files(Tar, RelName, Release, Path1) ->
SVsn = Release#release.vsn,
RelName0 = filename:basename(RelName),
+ RelVsnDir = filename:join("releases", SVsn),
+
+ %% OTP-9746: store rel file in releases/<vsn>
+ %% Adding rel file to
+ %% 1) releases directory - so it can be easily extracted
+ %% separately (see release_handler:unpack_release)
+ %% 2) releases/<vsn> - so the file must not be explicitly moved
+ %% after unpack.
add_to_tar(Tar, RelName ++ ".rel",
filename:join("releases", RelName0 ++ ".rel")),
+ add_to_tar(Tar, RelName ++ ".rel",
+ filename:join(RelVsnDir, RelName0 ++ ".rel")),
+
%% OTP-6226 Look for the system files not only in cwd
%% --
@@ -1527,26 +1686,27 @@ add_system_files(Tar, RelName, Release, Path1) ->
[RelDir, "."|Path1]
end,
- ToDir = filename:join("releases", SVsn),
case lookup_file(RelName0 ++ ".boot", Path) of
false ->
throw({error, {tar_error,{add, RelName0++".boot",enoent}}});
Boot ->
- add_to_tar(Tar, Boot, filename:join(ToDir, "start.boot"))
+ add_to_tar(Tar, Boot, filename:join(RelVsnDir, "start.boot"))
end,
case lookup_file("relup", Path) of
false ->
ignore;
Relup ->
- add_to_tar(Tar, Relup, filename:join(ToDir, "relup"))
+ check_relup(Relup),
+ add_to_tar(Tar, Relup, filename:join(RelVsnDir, "relup"))
end,
case lookup_file("sys.config", Path) of
false ->
ignore;
Sys ->
- add_to_tar(Tar, Sys, filename:join(ToDir, "sys.config"))
+ check_sys_config(Sys),
+ add_to_tar(Tar, Sys, filename:join(RelVsnDir, "sys.config"))
end,
ok.
@@ -1562,6 +1722,44 @@ lookup_file(Name, [Dir|Path]) ->
lookup_file(_Name, []) ->
false.
+%% Check that relup can be parsed and has expected format
+check_relup(File) ->
+ case file:consult(File) of
+ {ok,[{Vsn,UpFrom,DownTo}]} when is_list(Vsn), is_integer(hd(Vsn)),
+ is_list(UpFrom), is_list(DownTo) ->
+ ok;
+ {ok,_} ->
+ throw({error,{tar_error,{add,"relup",[invalid_format]}}});
+ Other ->
+ throw({error,{tar_error,{add,"relup",[Other]}}})
+ end.
+
+%% Check that sys.config can be parsed and has expected format
+check_sys_config(File) ->
+ case file:consult(File) of
+ {ok,[SysConfig]} ->
+ case lists:all(fun({App,KeyVals}) when is_atom(App),
+ is_list(KeyVals)->
+ true;
+ (OtherConfig) when is_list(OtherConfig),
+ is_integer(hd(OtherConfig)) ->
+ true;
+ (_) ->
+ false
+ end,
+ SysConfig) of
+ true ->
+ ok;
+ false ->
+ throw({error,{tar_error,
+ {add,"sys.config",[invalid_format]}}})
+ end;
+ {ok,_} ->
+ throw({error,{tar_error,{add,"sys.config",[invalid_format]}}});
+ Other ->
+ throw({error,{tar_error,{add,"sys.config",[Other]}}})
+ end.
+
%%______________________________________________________________________
%% Add either a application located under a variable dir or all other
%% applications to a tar file.
@@ -1850,90 +2048,67 @@ get_flag(_,_) -> false.
%% Check Options for make_script
check_args_script(Args) ->
- cas(Args,
- {undef, undef, undef, undef, undef, undef, undef, undef,
- undef, []}).
+ cas(Args, []).
-cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps,_Werror, X}) ->
+cas([], X) ->
X;
%%% path ---------------------------------------------------------------
-cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
- XrefApps, Werror, X}) when is_list(P) ->
+cas([{path, P} | Args], X) when is_list(P) ->
case check_path(P) of
ok ->
- cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- Werror, X});
+ cas(Args, X);
error ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- Werror, X++[{path,P}]})
+ cas(Args, X++[{path,P}])
end;
%%% silent -------------------------------------------------------------
-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});
+cas([silent | Args], X) ->
+ cas(Args, X);
%%% local --------------------------------------------------------------
-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});
+cas([local | Args], X) ->
+ cas(Args, X);
%%% src_tests -------------------------------------------------------
-cas([src_tests | Args], {Path, Sil, Loc, _Test, Var, Mach, Xref,
- XrefApps, Werror, X}) ->
- cas(Args,
- {Path, Sil, Loc, src_tests, Var, Mach, Xref, Werror, XrefApps,X});
+cas([src_tests | Args], X) ->
+ cas(Args, X);
%%% variables ----------------------------------------------------------
-cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
- XrefApps, Werror, X}) when is_list(V) ->
+cas([{variables, V} | Args], X) when is_list(V) ->
case check_vars(V) of
ok ->
- cas(Args,
- {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, Werror, X});
+ cas(Args, X);
error ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- Werror, X++[{variables, V}]})
+ cas(Args, X++[{variables, V}])
end;
%%% machine ------------------------------------------------------------
-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});
+cas([{machine, M} | Args], X) when is_atom(M) ->
+ cas(Args, X);
%%% exref --------------------------------------------------------------
-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});
+cas([exref | Args], X) ->
+ cas(Args, X);
%%% exref Apps ---------------------------------------------------------
-cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
- XrefApps, Werror, X}) when is_list(Apps) ->
+cas([{exref, Apps} | Args], X) when is_list(Apps) ->
case check_apps(Apps) of
ok ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, Apps, Werror, X});
+ cas(Args, X);
error ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, Werror, X++[{exref, Apps}]})
+ cas(Args, X++[{exref, Apps}])
end;
%%% outdir Dir ---------------------------------------------------------
-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});
+cas([{outdir, Dir} | Args], X) when is_list(Dir) ->
+ cas(Args, X);
%%% otp_build (secret, not documented) ---------------------------------
-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});
+cas([otp_build | Args], X) ->
+ cas(Args, X);
+%%% warnings_as_errors -------------------------------------------------
+cas([warnings_as_errors | Args], X) ->
+ cas(Args, X);
+%%% no_warn_sasl -------------------------------------------------------
+cas([no_warn_sasl | Args], X) ->
+ cas(Args, 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});
+cas([no_module_tests | Args], X) ->
+ cas(Args, X);
%%% ERROR --------------------------------------------------------------
-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]}).
+cas([Y | Args], X) ->
+ cas(Args, X++[Y]).
@@ -2072,9 +2247,12 @@ format_error({missing_parameter,Par}) ->
format_error({illegal_applications,Names}) ->
io_lib:format("Illegal applications in the release file: ~p~n",
[Names]);
-format_error({missing_mandatory_app,Names}) ->
- io_lib:format("Mandatory applications (~p) must be specified in the release file~n",
- [Names]);
+format_error({missing_mandatory_app,Name}) ->
+ io_lib:format("Mandatory application ~p must be specified in the release file~n",
+ [Name]);
+format_error({mandatory_app,Name,Type}) ->
+ io_lib:format("Mandatory application ~p must be of type 'permanent' in the release file. Is '~p'.~n",
+ [Name,Type]);
format_error({duplicate_register,Dups}) ->
io_lib:format("Duplicated register names: ~n~s",
[map(fun({{Reg,App1,_,_},{Reg,App2,_,_}}) ->
@@ -2198,5 +2376,9 @@ form_warn(Prefix, {exref_undef, Undef}) ->
[Prefix,M,F,A])
end,
map(F, Undef);
+form_warn(Prefix, missing_sasl) ->
+ io_lib:format("~s: Missing application sasl. "
+ "Can not upgrade with this release~n",
+ [Prefix]);
form_warn(Prefix, What) ->
io_lib:format("~s ~p~n", [Prefix,What]).
diff --git a/lib/sasl/src/systools_rc.erl b/lib/sasl/src/systools_rc.erl
index daadb79967..c16f6aa845 100644
--- a/lib/sasl/src/systools_rc.erl
+++ b/lib/sasl/src/systools_rc.erl
@@ -54,6 +54,7 @@
%% {sync_nodes, Id, Nodes}
%% {apply, {M, F, A}}
%% restart_new_emulator
+%% restart_emulator
%%-----------------------------------------------------------------
%% High-level instructions that contain dependencies
@@ -144,7 +145,10 @@ translate_merged_script(Mode, Script, Appls, PreAppls) ->
{Before2, After2} = translate_dependent_instrs(Mode, Before1, After1,
Appls),
Before3 = merge_load_object_code(Before2),
- NewScript = Before3 ++ [point_of_no_return | After2],
+
+ {Before4,After4} = sort_emulator_restart(Mode,Before3,After2),
+ NewScript = Before4 ++ [point_of_no_return | After4],
+
check_syntax(NewScript),
{ok, NewScript}.
@@ -699,6 +703,39 @@ mlo([{load_object_code, {Lib, LibVsn, Mods}} | T]) ->
mlo([]) -> [].
%%-----------------------------------------------------------------
+%% RESTART EMULATOR
+%% -----------------------------------------------------------------
+%% -----------------------------------------------------------------
+%% Check if there are any 'restart_new_emulator' instructions (i.e. if
+%% the emulator or core application version is changed). If so, this
+%% must be done first for upgrade and last for downgrade.
+%% Check if there are any 'restart_emulator' instructions, if so
+%% remove all and place one the end.
+%% -----------------------------------------------------------------
+sort_emulator_restart(Mode,Before,After) ->
+ {Before1,After1} =
+ case filter_out(restart_new_emulator, After) of
+ After ->
+ {Before,After};
+ A1 when Mode==up ->
+ {[restart_new_emulator|Before],A1};
+ A1 when Mode==dn ->
+ {Before,A1++[restart_emulator]}
+ end,
+ After2 =
+ case filter_out(restart_emulator, After1) of
+ After1 ->
+ After1;
+ A2 ->
+ A2++[restart_emulator]
+ end,
+ {Before1,After2}.
+
+
+filter_out(What,List) ->
+ lists:filter(fun(X) when X=:=What -> false; (_) -> true end, List).
+
+%%-----------------------------------------------------------------
%% SYNTAX CHECK
%%-----------------------------------------------------------------
%%-----------------------------------------------------------------
@@ -817,6 +854,7 @@ check_op({apply, {M, F, A}}) ->
check_func(F),
check_args(A);
check_op(restart_new_emulator) -> ok;
+check_op(restart_emulator) -> ok;
check_op(X) -> throw({error, {bad_instruction, X}}).
check_mod(Mod) when is_atom(Mod) -> ok;
diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl
index 6d9e922900..7fb623bb85 100644
--- a/lib/sasl/src/systools_relup.erl
+++ b/lib/sasl/src/systools_relup.erl
@@ -112,6 +112,11 @@
-export([mk_relup/3, mk_relup/4, format_error/1, format_warning/1]).
-include("systools.hrl").
+-define(R15_SASL_VSN,"2.2").
+
+%% For test purposes only - used by kernel, stdlib and sasl tests
+-export([appup_search_for_version/2]).
+
%%-----------------------------------------------------------------
%% mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs)
%% mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Opts) -> Ret
@@ -200,7 +205,13 @@ do_mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Path, Opts) ->
%% TopRel = #release
%% NameVsnApps = [{{Name, Vsn}, #application}]
{ok, TopRel, NameVsnApps, Ws0} ->
- %%
+ case lists:member({warning,missing_sasl},Ws0) of
+ true ->
+ throw({error,?MODULE,{missing_sasl,TopRel}});
+ false ->
+ ok
+ end,
+
%% TopApps = [#application]
TopApps = lists:map(fun({_, App}) -> App end, NameVsnApps),
@@ -247,7 +258,21 @@ foreach_baserel_up(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts,
Ws, Acc) ->
BaseRelFile = extract_filename(BaseRelDc),
- {ok, BaseRel} = systools_make:read_release(BaseRelFile, Path),
+ {BaseRel, {BaseNameVsns, BaseApps}, Ws0} =
+ case systools_make:get_release(BaseRelFile, Path) of
+ {ok, BR, NameVsnApps, Warns} ->
+ case lists:member({warning,missing_sasl},Warns) of
+ true ->
+ throw({error,?MODULE,{missing_sasl,BR}});
+ false ->
+ %% NameVsnApps = [{{Name,Vsn},#application}]
+ %% Gives two lists - [{Name,Vsn}] and [#application]
+ {BR,lists:unzip(NameVsnApps),Warns}
+ end;
+ Other1 ->
+ throw(Other1)
+ end,
+
%%
%% BaseRel = #release
@@ -257,29 +282,23 @@ foreach_baserel_up(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts,
%% application, one for each added applications, and one for
%% each removed applications.
%%
- {RUs1, Ws1} = collect_appup_scripts(up, TopApps, BaseRel, Ws, []),
+ {RUs1, Ws1} = collect_appup_scripts(up, TopApps, BaseRel, Ws0++Ws, []),
{RUs2, Ws2} = create_add_app_scripts(BaseRel, TopRel, RUs1, Ws1),
{RUs3, Ws3} = create_remove_app_scripts(BaseRel, TopRel, RUs2, Ws2),
- {RUs4, Ws4} =
- check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
-
- BaseApps =
- case systools_make:get_release(BaseRelFile, Path) of
- {ok, _, NameVsnApps, _Warns} ->
- lists:map(fun({_,App}) -> App end, NameVsnApps);
- Other1 ->
- throw(Other1)
- end,
+ {RUs4, Ws4} = check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
case systools_rc:translate_scripts(up, RUs4, TopApps, BaseApps) of
- {ok, RUs} ->
+ {ok, RUs5} ->
+
+ {RUs, Ws5} = fix_r15_sasl_upgrade(RUs5,Ws4,BaseNameVsns),
+
VDR = {BaseRel#release.vsn,
extract_description(BaseRelDc), RUs},
foreach_baserel_up(TopRel, TopApps, BaseRelDcs, Path,
- Opts, Ws4, [VDR| Acc]);
+ Opts, Ws5, [VDR| Acc]);
XXX ->
throw(XXX)
end;
@@ -294,42 +313,41 @@ foreach_baserel_dn(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts,
Ws, Acc) ->
BaseRelFile = extract_filename(BaseRelDc),
- {ok, BaseRel} = systools_make:read_release(BaseRelFile, Path),
-
- %% BaseRel = #release
-
- %% RUs = (release upgrade scripts)
- %%
- {RUs1, Ws1} = collect_appup_scripts(dn, TopApps, BaseRel, Ws, []),
-
- {BaseApps, Ws2} =
+ {BaseRel, BaseApps, Ws0} =
case systools_make:get_release(BaseRelFile, Path) of
%%
%% NameVsnApps = [{{Name, Vsn}, #application}]
- {ok, _, NameVsnApps, Warns} ->
- %%
- %% NApps = [#application]
- NApps = lists:map(fun({_,App}) -> App end, NameVsnApps),
- {NApps, Warns ++ Ws1};
+ {ok, BR, NameVsnApps, Warns} ->
+ case lists:member({warning,missing_sasl},Warns) of
+ true ->
+ throw({error,?MODULE,{missing_sasl,BR}});
+ false ->
+ %% NApps = [#application]
+ NApps = lists:map(fun({_,App}) -> App end, NameVsnApps),
+ {BR, NApps, Warns}
+ end;
Other ->
throw(Other)
end,
- RUs2 = RUs1,
+ %% BaseRel = #release
+
+ %% RUs = (release upgrade scripts)
+ %%
+ {RUs1, Ws1} = collect_appup_scripts(dn, TopApps, BaseRel, Ws0++Ws, []),
- {RUs3, Ws3} = create_add_app_scripts(TopRel, BaseRel, RUs2, Ws2),
+ {RUs2, Ws2} = create_add_app_scripts(TopRel, BaseRel, RUs1, Ws1),
- {RUs4, Ws4} = create_remove_app_scripts(TopRel, BaseRel, RUs3, Ws3),
+ {RUs3, Ws3} = create_remove_app_scripts(TopRel, BaseRel, RUs2, Ws2),
- {RUs5, Ws5} = check_for_emulator_restart(TopRel, BaseRel,
- RUs4, Ws4, Opts),
+ {RUs4, Ws4} = check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
- case systools_rc:translate_scripts(dn, RUs5, BaseApps, TopApps) of
+ case systools_rc:translate_scripts(dn, RUs4, BaseApps, TopApps) of
{ok, RUs} ->
VDR = {BaseRel#release.vsn,
extract_description(BaseRelDc), RUs},
foreach_baserel_dn(TopRel, TopApps, BaseRelDcs, Path,
- Opts, Ws5, [VDR| Acc]);
+ Opts, Ws4, [VDR| Acc]);
XXX ->
throw(XXX)
end;
@@ -343,14 +361,42 @@ foreach_baserel_dn( _, _, [], _, _, Ws, Acc) ->
%%
check_for_emulator_restart(#release{erts_vsn = Vsn1, name = N1},
#release{erts_vsn = Vsn2, name = N2}, RUs, Ws,
- _Opts) when Vsn1 /= Vsn2 ->
- {RUs++[[restart_new_emulator]], [{erts_vsn_changed, {N1, N2}} | Ws]};
+ Opts) when Vsn1 /= Vsn2 ->
+ %% Automatically insert a restart_new_emulator instruction when
+ %% erts version is changed. Also allow extra restart at the end of
+ %% the upgrade if restart_emulator option is given.
+ NewRUs = [[restart_new_emulator]|RUs],
+ NewWs = [{erts_vsn_changed, {{N1,Vsn1}, {N2,Vsn2}}} | Ws],
+ check_for_restart_emulator_opt(NewRUs, NewWs, Opts);
check_for_emulator_restart(_, _, RUs, Ws, Opts) ->
+ check_for_restart_emulator_opt(RUs, Ws, Opts).
+
+check_for_restart_emulator_opt(RUs, Ws, Opts) ->
case get_opt(restart_emulator, Opts) of
- true -> {RUs++[[restart_new_emulator]], Ws};
+ true -> {RUs++[[restart_emulator]], Ws};
_ -> {RUs, Ws}
end.
+
+%% Special handling of the upgrade from pre R15 to post R15. In R15,
+%% upgrade of the emulator was improved by moving the restart of the
+%% emulator before the rest of the upgrade instructions. However, it
+%% can only work if the release_handler is already upgraded to a post
+%% R15 version. If not, the upgrade instructions must be backwards
+%% compatible - i.e. restart_new_emulator will be the last
+%% instruction, executed after all code loading, code_change etc.
+fix_r15_sasl_upgrade([restart_new_emulator | RestRUs]=RUs, Ws, BaseApps) ->
+ case lists:keyfind(sasl,1,BaseApps) of
+ {sasl,Vsn} when Vsn < ?R15_SASL_VSN ->
+ {lists:delete(restart_emulator,RestRUs) ++ [restart_new_emulator],
+ [pre_R15_emulator_upgrade|Ws]};
+ _ ->
+ {RUs,Ws}
+ end;
+fix_r15_sasl_upgrade(RUs, Ws, _BaseApps) ->
+ {RUs,Ws}.
+
+
%% collect_appup_scripts(Mode, TopApps, BaseRel, Ws, RUs) -> {NRUs, NWs}
%% Mode = up | dn
%% TopApps = [#application]
@@ -440,13 +486,32 @@ get_script_from_appup(Mode, TopApp, BaseVsn, Ws, RUs) ->
%% XXX Why is this a warning only?
[{bad_vsn, {TopVsn, TopApp#application.vsn}}| Ws]
end,
- case lists:keysearch(BaseVsn, 1, VsnRUs) of
- {value, {_, RU}} ->
+ case appup_search_for_version(BaseVsn, VsnRUs) of
+ {ok, RU} ->
{RUs ++ [RU], Ws1};
- _ ->
+ error ->
throw({error, ?MODULE, {no_relup, FName, TopApp, BaseVsn}})
end.
+appup_search_for_version(BaseVsn, VsnRUs) ->
+ appup_search_for_version(BaseVsn, length(BaseVsn), VsnRUs).
+
+appup_search_for_version(BaseVsn,_,[{BaseVsn,RU}|_]) ->
+ {ok,RU};
+appup_search_for_version(BaseVsn,Size,[{Vsn,RU}|VsnRUs]) when is_binary(Vsn) ->
+ case re:run(BaseVsn,Vsn,[unicode,{capture,first,index}]) of
+ {match,[{0,Size}]} ->
+ {ok, RU};
+ _ ->
+ appup_search_for_version(BaseVsn,Size,VsnRUs)
+ end;
+appup_search_for_version(BaseVsn,Size,[_|VsnRUs]) ->
+ appup_search_for_version(BaseVsn,Size,VsnRUs);
+appup_search_for_version(_,_,[]) ->
+ error.
+
+
+
%% Primitives for the "lists of release names" that we upgrade from
%% and to.
@@ -543,7 +608,9 @@ format_error({no_relup, File, App, Vsn}) ->
"in file ~p~n",
[App#application.name, App#application.vsn,
App#application.name, Vsn, File]);
-
+format_error({missing_sasl,Release}) ->
+ io_lib:format("No sasl application in release ~p, ~p. Can not be upgraded.",
+ [Release#release.name, Release#release.vsn]);
format_error(Error) ->
io:format("~p~n", [Error]).
diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile
index 65be134462..bb3f82f411 100644
--- a/lib/sasl/test/Makefile
+++ b/lib/sasl/test/Makefile
@@ -36,6 +36,8 @@ MODULES= \
ERL_FILES= $(MODULES:%=%.erl)
+HRL_FILES= test_lib.hrl
+
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
INSTALL_PROGS= $(TARGET_FILES)
@@ -83,10 +85,10 @@ 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 -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_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
index a98e8c9c67..a4064ef27a 100644
--- a/lib/sasl/test/alarm_handler_SUITE.erl
+++ b/lib/sasl/test/alarm_handler_SUITE.erl
@@ -18,7 +18,7 @@
%%
-module(alarm_handler_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%-----------------------------------------------------------------
%% We will add an own alarm handler in order to verify that the
@@ -56,34 +56,32 @@ end_per_group(_GroupName, Config) ->
%%-----------------------------------------------------------------
-set_alarm(suite) -> [];
set_alarm(Config) when is_list(Config) ->
- ?line gen_event:add_handler(alarm_handler, ?MODULE, self()),
+ 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),
+ ok = alarm_handler:set_alarm(Alarm1),
reported(set_alarm, Alarm1),
- ?line ok = alarm_handler:set_alarm(Alarm2),
+ ok = alarm_handler:set_alarm(Alarm2),
reported(set_alarm, Alarm2),
- ?line ok = alarm_handler:set_alarm(Alarm3),
+ ok = alarm_handler:set_alarm(Alarm3),
reported(set_alarm, Alarm3),
- ?line [Alarm3,Alarm2,Alarm1] = alarm_handler:get_alarms(),
+ [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(),
+ [] = alarm_handler:get_alarms(),
test_server:messages_get(),
- ?line my_yes = gen_event:delete_handler(alarm_handler, ?MODULE, []),
+ 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()),
+ 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"}},
@@ -92,44 +90,42 @@ clear_alarm(Config) when is_list(Config) ->
alarm_handler:set_alarm(Alarm3),
test_server:messages_get(),
- ?line ok = alarm_handler:clear_alarm(alarm1),
+ ok = alarm_handler:clear_alarm(alarm1),
reported(clear_alarm, alarm1),
- ?line ok = alarm_handler:clear_alarm("alarm2"),
+ ok = alarm_handler:clear_alarm("alarm2"),
reported(clear_alarm, "alarm2"),
- ?line ok = alarm_handler:clear_alarm({alarm3}),
+ ok = alarm_handler:clear_alarm({alarm3}),
reported(clear_alarm, {alarm3}),
- ?line [] = alarm_handler:get_alarms(),
+ [] = alarm_handler:get_alarms(),
- ?line my_yes = gen_event:delete_handler(alarm_handler, ?MODULE, []),
+ 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,
+ 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),
+
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),
+ ok = gen_event:swap_handler(alarm_handler,
+ {alarm_handler, swap},
+ {?MODULE, self()}),
+ [?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(),
+ {error, _} = alarm_handler:get_alarms(),
- ?line my_yes = gen_event:delete_handler(alarm_handler,
- ?MODULE, []),
- ?line gen_event:add_handler(alarm_handler, alarm_handler, []),
+ my_yes = gen_event:delete_handler(alarm_handler,
+ ?MODULE, []),
+ gen_event:add_handler(alarm_handler, alarm_handler, []),
ok;
_ ->
alarm_handler:clear_alarm(alarm1),
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl
index f5ceab0dc4..634218e3fb 100644
--- a/lib/sasl/test/installer.erl
+++ b/lib/sasl/test/installer.erl
@@ -19,20 +19,33 @@
-module(installer).
+-include("test_lib.hrl").
+
%%-compile(export_all).
-export([install_1/2]).
-export([install_2/1]).
-export([install_3/2]).
--export([install_3a/1]).
+-export([install_6a/1]).
-export([install_4/1]).
-export([install_5/1]).
-export([install_5a/1]).
-export([install_6/1]).
-export([install_7/1]).
+-export([install_7a/1]).
-export([install_8/1]).
+-export([install_8a/1]).
-export([install_9/1]).
-export([install_10/1]).
-export([install_11/1]).
+-export([install_12/1]).
+-export([install_13/1]).
+-export([install_14/1]).
+-export([upgrade_restart_1/2]).
+-export([upgrade_restart_1a/1]).
+-export([upgrade_restart_2/1]).
+-export([upgrade_restart_2a/1]).
+-export([upgrade_restart_2b/1]).
+-export([upgrade_restart_3/1]).
-export([client1_1/4]).
-export([client2/3]).
-export([stop/1]).
@@ -46,28 +59,35 @@
-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_release_states(States),
+ check_release_states(TestNode,node(),States,?LINE)).
+-define(check_release_states_client(Node,States),
+ check_release_states(TestNode,Node,States,?LINE)).
+
+-define(check_release_lib(Vsn,Apps),
+ check_release_lib(TestNode,node(),Vsn,Apps,?LINE)).
+-define(check_release_lib_client(Node,Vsn,Apps),
+ check_release_lib(TestNode,Node,Vsn,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)).
+-define(check_disallowed_calls,check_disallowed_calls(TestNode,?LINE)).
+
install_1(TestNode,PrivDir) ->
?print([TestNode]),
?print(["install_1 start"]),
+ ?check_release_states([permanent]),
% Unpack and install P1H
{ok, "P1H"} = unpack_release(PrivDir,"rel1"),
- ?print(["unpack_release P1H ok"]),
- ?check_release("P1H",unpacked,["a-1.0"]),
+ ?check_release_states([permanent,unpacked]),
+ ?check_release_lib("P1H",["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_release_states([permanent,current]),
?check_running_app(a,"1.0"),
X = a:a(),
?print(["X", X]),
@@ -81,173 +101,351 @@ 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"]),
+ ?check_release_states([permanent,unpacked]),
{ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
?print(["install_2 install_release ok"]),
- ?check_release("P1H",current,["a-1.0"]),
+ ?check_release_states([permanent,current]),
+ ?check_running_app(a,"1.0"),
+ ok = release_handler:make_permanent("P1H"),
+ ?print(["install_2 make permanent P1H ok"]),
+ ?check_release_states([old,permanent]),
?check_running_app(a,"1.0"),
- ok = release_handler:make_permanent("P1H").
+ ok.
% 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"]),
+ ?check_release_states([old,permanent]),
+ ?check_running_app(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"]),
+ ?check_release_states([old,permanent,unpacked]),
+ ?check_release_lib("P1I",["a-1.1"]),
{ok,"P1H",[{extra, gott}]} = release_handler:check_install_release("P1I"),
+ ?print(["install_3 check_install_release P1I ok"]),
{error,_} = release_handler:check_install_release("P1J"),
+ ?print(["install_3 check_install_release P1J fails - ok"]),
{ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
- ?print(["install_3 install_release P1I ok"]),
- ?check_release("P1I",current,["a-1.1"]),
+ ?check_release_states([old,permanent,current]),
?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(),
+ ?print(["install_3 env ok"]),
- % Unpack and install P2A
+ % Unpack P2A
{ok, "P2A"} = unpack_release(PrivDir,"rel3"),
- ?print(["install_3 unpack_release P2A ok"]),
- ?check_release("P2A",unpacked,["a-1.1"]),
+ ?check_release_states([old,permanent,current,unpacked]),
+ ?check_release_lib("P2A",["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.
+ % release_handler_SUITE will reboot this node now!
+
+install_4(TestNode) ->
+ ?print(["install_4 start"]),
-install_3a(TestNode) ->
- {ok, "P1I", [new_emu]} = release_handler:install_release("P2A"),
+ %% Check that P1H is the one that is used
+ ?check_release_states([old,permanent,unpacked,unpacked]),
+ ?check_running_app(a,"1.0"),
+
+ %% Install P2A
+ {continue_after_restart, "P1H", [new_emu,new_appl]} =
+ 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"]),
+ ?print(["install_4 P2A installed"]),
ok.
+install_5(TestNode) ->
+ ?print(["install_5 start"]),
-install_4(TestNode) ->
- ?print(["install_4 start"]),
+ %% Check that the upgrade was done via a temporary release due to
+ %% new emulator version.
+ {"SASL-test","__new_emulator__P1H"} = init:script_id(),
+
+ %% Check that P2A is in use.
+ ?check_release_states([old,permanent,unpacked,current]),
+ ?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(),
+ ?print(["install_5 check env ok"]),
+ ok.
+
+install_5a(TestNode) ->
+ ?print(["install_5a start"]),
+
+ %% Install P1I (this will be a downgrade)
+ {ok, "P1I", [old_emu]} = release_handler:install_release("P1I"),
+ %% 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_5a P1I installed"]),
+ ok.
+
+install_6(TestNode) ->
+ ?print(["install_6 start"]),
+
+ %% Check that P1I is used
+ ?check_release_states([old,permanent,current,old]),
+ ?check_running_app(a,"1.1"),
+
+ %% Make P1I permanent
+ ok = release_handler:make_permanent("P1I"),
+ ?check_release_states([old,old,permanent,old]),
+ ?check_running_app(a,"1.1"),
+ ok.
+
+install_6a(TestNode) ->
+ %% Install P2A
+ {continue_after_restart, "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_6a P2A installed"]),
+ ok.
+
+install_7(TestNode) ->
+ ?print(["install_7 start"]),
+
+ %% Check that the upgrade was done via a temporary release due to
+ %% new emulator version.
+ {"SASL-test","__new_emulator__P1I"} = init:script_id(),
% Check that P2A is in use.
- ?check_release("P2A",current,["a-1.1"]),
+ ?check_release_states([old,old,permanent,current]),
?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(),
+ ?print(["install_7 check env ok"]),
ok.
- % release_handler_SUITE will reboot this node now!
-install_5(TestNode) ->
- ?print(["install_5 start"]),
+install_7a(TestNode) ->
+ %% Install P1H (this will be a downgrade)
+ {ok, "P1H", [old_emu,old_appl]} = release_handler:install_release("P1H"),
+ %% 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_7a P1H installed"]),
+ ok.
- % Check that P1I is used
- {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"),
+install_8(TestNode) ->
+ ?print(["install_8 start"]),
+
+ %% Check that P1H is used
+ ?check_release_states([old,current,permanent,old]),
+ ?check_running_app(a,"1.0"),
+ {ok,"P1H",[new_emu,new_appl]} = release_handler:check_install_release("P2A"),
+ ?print(["install_8 check_install_release P2A ok"]),
+
+ %% Install P1I and check that it is permanent
+ {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
+ ?check_release_states([old,old,permanent,old]),
+ ?check_running_app(a,"1.1"),
ok.
-install_5a(TestNode) ->
+install_8a(TestNode) ->
% Install P2A again
- {ok, "P1I", [new_emu]} = release_handler:install_release("P2A"),
+ {continue_after_restart, "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"]),
+ ?print(["install_8a P2A installed"]),
ok.
-install_6(TestNode) ->
- ?print(["install_6 start"]),
+install_9(TestNode) ->
+ ?print(["install_9 start"]),
+
+ %% Check that the upgrade was done via a temporary release due to
+ %% new emulator version.
+ {"SASL-test","__new_emulator__P1I"} = init:script_id(),
% Check that P2A is used
- ?check_release("P2A",current,["a-1.1"]),
+ ?check_release_states([old,old,permanent,current]),
?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").
+ ?print(["install_9 check env ok"]),
+ ok = release_handler:make_permanent("P2A"),
+ ?check_release_states([old,old,old,permanent]),
+ ?check_running_app(a,"1.1"),
+ ok.
% release_handler_SUITE will reboot this node now!
-install_7(TestNode) ->
- ?print(["install_7 start"]),
+install_10(TestNode) ->
+ ?print(["install_10 start"]),
% Check that P2A is used
- ?check_release("P2A",permanent,["a-1.1"]),
+ ?check_release_states([old,old,old,permanent]),
+ ?check_running_app(a,"1.1"),
% Install old P1H
ok = release_handler:reboot_old_release("P1H"),
+ ?print(["install_10 reboot_old ok"]),
ok.
-install_8(TestNode) ->
- ?print(["install_8 start"]),
+
+install_11(TestNode) ->
+ ?print(["install_11 start"]),
% Check that P1H is permanent
- ?check_release("P1H",permanent,["a-1.0"]),
+ ?check_release_states([old,permanent,old,old]),
+ ?check_running_app(a,"1.0"),
X = a:a(),
{key2, val2} = lists:keyfind(key2, 1, X),
{key1, val1} = lists:keyfind(key1, 1, X),
+ ?print(["install_11 check env ok"]),
%% Remove P1I and P2A and check that a-1.1 and erts-<latest> are removed
ok = release_handler:remove_release("P2A"),
+ ?check_release_states([old,permanent,old]),
ok = release_handler:remove_release("P1I"),
+ ?check_release_states([old,permanent]),
{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),
+ ErtsDir = "erts-"++?ertsvsn,
+ [ErtsDir] = lists:filter(fun(Dir) -> lists:prefix("erts-",Dir) end, Dirs),
+ ?print(["install_11 file checks ok"]),
ok.
% release_handler_SUITE will reboot this node now!
-install_9(TestNode) ->
- ?print(["install_9 start"]),
+install_12(TestNode) ->
+ ?print(["install_12 start"]),
% Check that P1H is permanent
- ?check_release("P1H",permanent,["a-1.0"]),
+ ?check_release_states([old,permanent]),
+ ?check_running_app(a,"1.0"),
X = a:a(),
{key2, val2} = lists:keyfind(key2, 1, X),
{key1, val1} = lists:keyfind(key1, 1, X),
+ ?print(["install_12 check env ok"]),
% Install old P1G
ok = release_handler:reboot_old_release("P1G"),
+ ?print(["install_12 reboot_old ok"]),
ok.
-install_10(TestNode) ->
- ?print(["install_10 start"]),
+install_13(TestNode) ->
+ ?print(["install_13 start"]),
% Check that P1G is permanent
- ?check_release("P1G",permanent,[]),
- ?check_release("P1H",old,["a-1.0"]),
+ ?check_release_states([permanent,old]),
+ false = lists:keysearch(a,1,application:loaded_applications()),
+ ?print(["install_13 no a application found - ok"]),
%% Remove P1H and check that both versions of application a is removed
ok = release_handler:remove_release("P1H"),
+ ?check_release_states([permanent]),
{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),
+ ?print(["install_13 file checks ok"]),
ok.
% release_handler_SUITE will reboot this node now!
-install_11(TestNode) ->
- ?print(["install_11 start"]),
+install_14(TestNode) ->
+ ?print(["install_14 start"]),
% Check that P1G is permanent
- ?check_release("P1G",permanent,[]),
+ ?check_release_states([permanent]),
+ false = lists:keysearch(a,1,application:loaded_applications()),
+ ?print(["install_13 no a application found - ok"]),
ok.
+%%%-----------------------------------------------------------------
+%%% Ths test checks that an upgrade which both upgrades to a new
+%%% emulator version, and had a restart_emulator option to
+%%% systools:make_relup will be restarted twice on upgrade.
+%%% (On downgrade it will happen only once.)
+upgrade_restart_1(TestNode,PrivDir) ->
+ ?print([TestNode]),
+ ?print(["upgrade_restart_1 start"]),
+ ?check_release_states([permanent]),
+
+ {ok, "P2B"} = unpack_release(PrivDir,"rel4"),
+ ?check_release_states([permanent,unpacked]),
+ ?check_release_lib("P2B",["a-1.1"]),
+ ok.
+
+upgrade_restart_1a(TestNode) ->
+ ?print(["upgrade_restart_1a start"]),
+
+ {continue_after_restart,"P1G",[new_emu,add_appl]} =
+ release_handler:install_release("P2B"),
+ ?print(["upgrade_restart_1a P2B installed"]),
+ ok.
+
+upgrade_restart_2(TestNode) ->
+ ?print(["upgrade_restart_2 start"]),
+
+ %% Check that the node has been restarted once more after the tmp release
+ case init:script_id() of
+ {"SASL-test","P2B"} ->
+ upgrade_restart_2a(TestNode);
+ {"SASL-test","__new_emulator__P1G"} ->
+ %% catched the node too early - give it another try
+ {wait,whereis(init)}
+ end.
+
+upgrade_restart_2a(TestNode) ->
+ ?print(["upgrade_restart_2a start"]),
+
+ %% This time we must be there, else something is definitely wrong
+ {"SASL-test","P2B"} = init:script_id(),
+
+ ?check_release_states([permanent,current]),
+ ?check_running_app(a,"1.1"),
+
+ ok = release_handler:make_permanent("P2B"),
+ ?check_release_states([old,permanent]),
+
+ ok.
+
+upgrade_restart_2b(TestNode) ->
+ ?print(["upgrade_restart_2b start"]),
+
+ {ok,"P1G",[old_emu,rm_appl]} = release_handler:install_release("P1G"),
+ ?print(["upgrade_restart_2b P1G installed"]),
+ ok.
+
+upgrade_restart_3(TestNode) ->
+ ?print(["upgrade_restart_3 start"]),
+
+ %% Ideally we should test that the node has only been restarted
+ %% once... but that's not so easy. Let's just check that P1G is running.
+ ?check_release_states([current,permanent]),
+ false = lists:keysearch(a,1,application:loaded_applications()),
+ ?print(["upgrade_restart_3 no a application found - ok"]),
+
+ ok.
+
+
+
%%-----------------------------------------------------------------
%% This test starts a client node which uses this node as master
@@ -272,6 +470,8 @@ client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
Node = start_client(TestNode,client1,ClientSname),
trace_disallowed_calls(Node),
+ ?check_release_states_client(Node,[permanent]),
+
%% Check env var for SASL on client node
SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
?print([{client1_1,sasl_env},SaslEnv]),
@@ -300,13 +500,14 @@ client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
%% 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.
+ %% trace_disallowed_calls/1 and check_disallowed_calls/2 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"]),
+ ?check_release_states_client(Node,[permanent,unpacked]),
+ ?check_release_lib_client(Node,"P1H",["a-1.0"]),
ok = rpc:call(Node, release_handler, install_file,
["P1H", filename:join(P1HDir, "start.boot")]),
@@ -323,13 +524,16 @@ client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
{ok,"P1G",[new_appl]} =
rpc:call(Node, release_handler, install_release, ["P1H"]),
+ ?check_release_states_client(Node,[permanent,current]),
+ ?check_running_app_client(Node,a,"1.0"),
+
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(),
+ ?check_disallowed_calls,
reboot(TestNode,Node),
trace_disallowed_calls(Node),
@@ -339,17 +543,17 @@ 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"]),
+ ?check_release_states_client(Node,[permanent,unpacked]),
{ok,"P1G",[new_appl]} =
rpc:call(Node, release_handler, install_release, ["P1H"]),
- ?check_release_client(Node,"P1H",current,["a-1.0"]),
+ ?check_release_states_client(Node,[permanent,current]),
?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_release_states_client(Node,[old,permanent]),
- check_disallowed_calls(),
+ ?check_disallowed_calls,
reboot(TestNode,Node),
trace_disallowed_calls(Node),
@@ -359,10 +563,8 @@ 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),
+ ?check_release_states_client(Node,[old,permanent]),
+ ?check_running_app_client(Node,a,"1.0"),
%% Unpack P1I on master
{ok, "P1I"} = unpack_release(PrivDir,"rel2"),
@@ -374,7 +576,8 @@ client1_3(TestNode,PrivDir,Node) ->
{ok, "P1I"} = rpc:call(Node, release_handler, set_unpacked,
[filename:join(P1IDir, "rel2.rel"),[]]),
- ?check_release_client(Node,"P1I",unpacked,["a-1.1"]),
+ ?check_release_states_client(Node,[old,permanent,unpacked]),
+ ?check_release_lib_client(Node,"P1I",["a-1.1"]),
ok = rpc:call(Node, release_handler, install_file,
["P1I", filename:join(P1IDir, "start.boot")]),
@@ -389,6 +592,7 @@ client1_3(TestNode,PrivDir,Node) ->
{ok,"P1H",[{extra, gott}]} =
rpc:call(Node, release_handler, install_release, ["P1I"]),
+ ?check_release_states_client(Node,[old,permanent,current]),
?check_running_app_client(Node,a,"1.1"),
X2 = rpc:call(Node, a, a, []),
{key2, newval2} = lists:keyfind(key2, 1, X2),
@@ -404,6 +608,9 @@ client1_3(TestNode,PrivDir,Node) ->
rpc:call(Node, release_handler, set_unpacked,
[filename:join(P2ADir, "rel3.rel"),[]]),
+ ?check_release_states_client(Node,[old,permanent,current,unpacked]),
+ ?check_release_lib_client(Node,"P2A",["a-1.1"]),
+
ok = rpc:call(Node, release_handler, install_file,
["P2A", filename:join(P2ADir, "start.boot")]),
ok = rpc:call(Node, release_handler, install_file,
@@ -413,66 +620,136 @@ client1_3(TestNode,PrivDir,Node) ->
{ok, "P1I", [new_emu]} =
rpc:call(Node, release_handler, check_install_release, ["P2A"]),
+
+ %% Reboot from P1H
+ ?check_disallowed_calls,
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_4(TestNode,Node).
+
+client1_4(TestNode,Node) ->
+ ?print(["client1_4 start"]),
+
+ %% check that P1H is used
+ ?check_release_states_client(Node,[old,permanent,unpacked,unpacked]),
+
+ %% since the install_release below reboot the node...
+ ?check_disallowed_calls,
+ cover_client(TestNode,Node,stop_cover),
+
+ {continue_after_restart, "P1H", [new_emu,new_appl]} =
+ rpc:call(Node, release_handler, install_release, ["P2A"]),
+ %% Reboots the client !
+
+ check_reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_5(TestNode,Node).
+
+client1_5(TestNode,Node) ->
+ ?print(["client1_5 start"]),
+
+ %% Check that P2A is in use.
+ ?check_release_states_client(Node,[old,permanent,unpacked,current]),
+ ?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, []),
+
+ %% since the install_release below reboot the node...
+ ?check_disallowed_calls,
+ cover_client(TestNode,Node,stop_cover),
+
+ {ok,"P1I",[old_emu]} =
+ rpc:call(Node, release_handler, install_release, ["P1I"]),
+
+ check_reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_6(TestNode,Node).
+
+client1_6(TestNode,Node) ->
+ ?print(["client1_6 start"]),
+
+ ?check_release_states_client(Node,[old,permanent,current,old]),
+ ?check_running_app_client(Node,a,"1.1"),
+
ok = rpc:call(Node, release_handler, make_permanent, ["P1I"]),
- ?check_release_client(Node,"P1I",permanent,["a-1.1"]),
+ ?check_release_states_client(Node,[old,old,permanent,old]),
%% since the install_release below reboot the node...
- check_disallowed_calls(),
+ ?check_disallowed_calls,
cover_client(TestNode,Node,stop_cover),
- {ok, "P1I", [new_emu]} =
+ {continue_after_restart, "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_7(TestNode,Node).
-client1_4(TestNode,Node) ->
- ?print(["client1_4 start"]),
+client1_7(TestNode,Node) ->
+ ?print(["client1_7 start"]),
%% Check that P2A is in use.
- ?check_release_client(Node,"P2A",current,["a-1.1"]),
+ ?check_release_states_client(Node,[old,old,permanent,current]),
?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),
+ %% since the install_release below reboot the node...
+ ?check_disallowed_calls,
+ cover_client(TestNode,Node,stop_cover),
+
+ {ok,"P1H",[old_emu,old_appl]} =
+ rpc:call(Node, release_handler, install_release, ["P1H"]),
+
+ check_reboot(TestNode,Node),
trace_disallowed_calls(Node),
- client1_5(TestNode,Node).
+ client1_8(TestNode,Node).
-client1_5(TestNode,Node) ->
- ?print(["client1_5 start"]),
+client1_8(TestNode,Node) ->
+ ?print(["client1_8 start"]),
- %% Check that P1I is used
- {ok, "P1I", [new_emu]} =
+ %% Check that P1H is used
+ ?check_release_states_client(Node,[old,current,permanent,old]),
+ ?check_running_app_client(Node,a,"1.0"),
+ {ok, "P1H", [new_emu,new_appl]} =
rpc:call(Node, release_handler, check_install_release, ["P2A"]),
+
+ {ok,"P1H",[{extra, gott}]} =
+ rpc:call(Node, release_handler, install_release, ["P1I"]),
+ ?check_release_states_client(Node,[old,old,permanent,old]),
+ ?check_running_app_client(Node,a,"1.1"),
+
+
%% since the install_release below will reboot the node...
- check_disallowed_calls(),
+ ?check_disallowed_calls,
cover_client(TestNode,Node,stop_cover),
%% Install P2A again
- {ok, "P1I", [new_emu]} =
+ {continue_after_restart, "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_9(TestNode,Node).
-client1_6(TestNode,Node) ->
- ?print(["client1_6 start"]),
+client1_9(TestNode,Node) ->
+ ?print(["client1_9 start"]),
%% Check that P2A is used
- ?check_release_client(Node,"P2A",current,["a-1.1"]),
+ ?check_release_states_client(Node,[old,old,permanent,current]),
?check_running_app_client(Node,a,"1.1"),
X = rpc:call(Node, a, a, []),
{key2, newval2} = lists:keyfind(key2, 1, X),
@@ -481,22 +758,23 @@ client1_6(TestNode,Node) ->
%% Make P2A permanent
ok = rpc:call(Node, release_handler, make_permanent, ["P2A"]),
+ ?check_release_states_client(Node,[old,old,old,permanent]),
%% Reboot from P2A
- check_disallowed_calls(),
+ ?check_disallowed_calls,
reboot(TestNode,Node),
trace_disallowed_calls(Node),
- client1_7(TestNode,Node).
+ client1_10(TestNode,Node).
-client1_7(TestNode,Node) ->
- ?print(["client1_7 start"]),
+client1_10(TestNode,Node) ->
+ ?print(["client1_10 start"]),
%% Check that P2A is used
- ?check_release_client(Node,"P2A",permanent,["a-1.1"]),
+ ?check_release_states_client(Node,[old,old,old,permanent]),
%% since the reboot_old_release below will reboot the node
- check_disallowed_calls(),
+ ?check_disallowed_calls,
cover_client(TestNode,Node,stop_cover),
%% Install old P1H
@@ -505,41 +783,45 @@ client1_7(TestNode,Node) ->
check_reboot(TestNode,Node),
trace_disallowed_calls(Node),
- client1_8(TestNode,Node).
+ client1_11(TestNode,Node).
-client1_8(TestNode,Node) ->
- ?print(["client1_8 start"]),
+client1_11(TestNode,Node) ->
+ ?print(["client1_11 start"]),
%% Check that P1H is permanent
- ?check_release_client(Node,"P1H",permanent,["a-1.0"]),
+ ?check_release_states_client(Node,[old,permanent,old,old]),
+ ?check_running_app_client(Node,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
+ %% Remove P1I and P2A from client
ok = rpc:call(Node, release_handler, set_removed, ["P2A"]),
+ ?check_release_states_client(Node,[old,permanent,old]),
ok = rpc:call(Node, release_handler, set_removed, ["P1I"]),
+ ?check_release_states_client(Node,[old,permanent]),
- 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.
+ %% Check that P2A and P1I does not exists
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),
+ ?check_disallowed_calls,
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_12(TestNode,Node).
+
+client1_12(TestNode,Node) ->
+ ?print(["client1_12 start"]),
+
+ ?check_release_states_client(Node,[old,permanent]),
+
%% since the reboot_old_release below will reboot the node
- check_disallowed_calls(),
+ ?check_disallowed_calls,
cover_client(TestNode,Node,stop_cover),
%% Install old P1G
@@ -548,33 +830,34 @@ client1_9(TestNode,Node) ->
check_reboot(TestNode,Node),
trace_disallowed_calls(Node),
- client1_10(TestNode,Node).
+ client1_13(TestNode,Node).
-client1_10(TestNode,Node) ->
- ?print(["client1_10 start"]),
+client1_13(TestNode,Node) ->
+ ?print(["client1_13 start"]),
%% Check that P1G is permanent
- ?check_release_client(Node,"P1G",permanent,[]),
- ?check_release_client(Node,"P1H",old,["a-1.0"]),
+ ?check_release_states_client(Node,[permanent,old]),
{error,client_node} = rpc:call(Node,release_handler,remove_release,["P1H"]),
ok = rpc:call(Node, release_handler, set_removed, ["P1H"]),
+ ?check_release_states_client(Node,[permanent]),
- check_disallowed_calls(),
+ ?check_disallowed_calls,
reboot(TestNode,Node),
trace_disallowed_calls(Node),
- client1_11(TestNode,Node).
+ client1_14(TestNode,Node).
-client1_11(TestNode,Node) ->
- ?print(["client1_11 start"]),
+client1_14(TestNode,Node) ->
+ ?print(["client1_14 start"]),
%% Check that P1G is permanent
- ?check_release_client(Node,"P1G",permanent,[]),
+ ?check_release_states_client(Node,[permanent]),
- check_disallowed_calls(),
+ ?check_disallowed_calls,
stop_client(TestNode,Node), %% TEST IS OK !!
net_kernel:monitor_nodes(false),
+ %% Remove releases from master
ok = release_handler:remove_release("P2A"),
ok = release_handler:remove_release("P1I"),
ok = release_handler:remove_release("P1H"),
@@ -593,11 +876,14 @@ 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}}]}]]).
+ rpc:call(Node,dbg,tp,[file,[{'_',[],[{message,{caller}}]}]]),
+ %% File:native_name_encoding/0 is a BIF and OK to use
+ rpc:call(Node,dbg,ctp,[file,native_name_encoding,0]).
-check_disallowed_calls() ->
+check_disallowed_calls(TestNode,Line) ->
receive
Trace when element(1,Trace)==trace ->
+ ?print_line(Line,["Disallowed function called",Trace]),
exit({disallowed_function_call,Trace})
after 0 ->
ok
@@ -628,7 +914,7 @@ start_client_unix(TestNode,Sname,Node) ->
start_client_win32(TestNode,Client,ClientSname) ->
Name = atom_to_list(ClientSname) ++ "_P1G",
RootDir = code:root_dir(),
- ErtsBinDir = filename:join(RootDir,"erts-4.4/bin"),
+ ErtsBinDir = filename:join([RootDir,"erts-"++?ertsvsn,"bin"]),
{ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname,
RootDir),
@@ -729,8 +1015,10 @@ client2(TestNode,PrivDir,ClientSname) ->
ok
end,
+ %% Unpack P1H on master
{ok, "P1H"} = unpack_release(PrivDir,"rel1"),
+ %% Try to set P1H unpacked on client
Root = code:root_dir(),
{error,{bad_masters,[Master2]}} =
rpc:call(Node, release_handler, set_unpacked,
@@ -755,15 +1043,17 @@ stop(Now) ->
unpack_p1h(TestNode,PrivDir) ->
{ok, "P1H"} = unpack_release(PrivDir,"rel1"),
- ?check_release("P1H",unpacked,["a-1.0"]),
+ ?check_release_states([permanent,unpacked]),
+ ?check_release_lib("P1H",["a-1.0"]),
ok.
permanent_p1h(TestNode) ->
- ?check_release("P1H",unpacked,["a-1.0"]),
+ ?check_release_states([permanent,unpacked]),
+ ?check_release_lib("P1H",["a-1.0"]),
{ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
- ?check_release("P1H",current,["a-1.0"]),
+ ?check_release_states([permanent,current]),
ok = release_handler:make_permanent("P1H"),
- ?check_release("P1H",permanent,["a-1.0"]),
+ ?check_release_states([old,permanent]),
ok.
@@ -779,24 +1069,38 @@ registered_loop(_Name) ->
exit(killed)
end.
-check_release(TestNode,Node,Vsn,Status,Apps,Line) ->
+%% Checks that the list of states for all releases (sorted on vsn)
+%% equals the input States
+check_release_states(TestNode,Node,States,Line) ->
+ case rpc:call(Node,release_handler,which_releases,[]) of
+ {badrpc,_}=Error ->
+ ?fail_line(Line,{check_release_states,Node,States,Error});
+ Rels ->
+ ?print_line(Line,["check_release_states:", Rels]),
+ States = [Status || {_,_,_,Status} <- lists:keysort(2,Rels)],
+ ok
+ end.
+
+%% Check that the given release (Vsn) sees the correct vsn of App.
+check_release_lib(TestNode,Node,Vsn,Apps,Line) ->
case rpc:call(Node,release_handler,which_releases,[]) of
{badrpc,_}=Error ->
- ?fail_line(Line,{check_release,Node,Vsn,Status,Error});
+ ?fail_line(Line,{check_release_lib,Node,Vsn,Apps,Error});
Rels ->
- ?print_line(Line,["check_release:", Rels]),
- {"SASL-test", Vsn, Libs, Status} = lists:keyfind(Vsn, 2, Rels),
+ ?print_line(Line,["check_release_lib:", 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 that the given Vsn of App is executed
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),
+ {App, _, Vsn} = lists:keyfind(App, 1, Apps),
ok
end.
diff --git a/lib/sasl/test/overload_SUITE.erl b/lib/sasl/test/overload_SUITE.erl
index 92b1aaed6e..e7f180b2ea 100644
--- a/lib/sasl/test/overload_SUITE.erl
+++ b/lib/sasl/test/overload_SUITE.erl
@@ -18,14 +18,13 @@
%%
-module(overload_SUITE).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() -> [info, set_config_data, set_env_vars, request, timeout].
-all(suite) -> all().
init_per_testcase(_Case,Config) ->
restart_sasl(),
@@ -38,37 +37,34 @@ end_per_testcase(Case,Config) ->
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.
+ Info = overload:get_overload_info(),
+ [{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),
+ InfoDefault = overload:get_overload_info(),
+ ok = check_info(0.8,0.1,InfoDefault),
+ ok = overload:set_config_data(0.5,0.4),
+ Info1 = overload:get_overload_info(),
+ 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),
+ InfoDefault = overload:get_overload_info(),
+ ok = check_info(0.8,0.1,InfoDefault),
+ ok = application:set_env(sasl,overload_max_intensity,0.5),
+ ok = application:set_env(sasl,overload_weight,0.4),
+ ok = application:stop(sasl),
+ ok = application:start(sasl),
+ Info1 = overload:get_overload_info(),
+ ok = check_info(0.5,0.4,Info1),
ok.
set_env_vars(cleanup,_Config) ->
application:unset_env(sasl,overload_max_intensity),
@@ -76,63 +72,61 @@ set_env_vars(cleanup,_Config) ->
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]),
-
+ overload:set_config_data(0.8, 0.1),
+ NDefault = do_many_requests(0),
+ restart_sasl(),
+ ?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,
+ overload:set_config_data(2, 0.1),
+ NLargeMI = do_many_requests(0),
+ restart_sasl(),
+ ?t:format("NLargeMI: ~p",[NLargeMI]),
+ 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,
+ overload:set_config_data(0.8, 1),
+ NLargeWeight = do_many_requests(0),
+ restart_sasl(),
+ ?t:format("NLargeWeight: ~p",[NLargeWeight]),
+ 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,
+ overload:set_config_data(0.8, 1),
+ NLargeTime = do_many_requests(500),
+ restart_sasl(),
+ ?t:format("NLargeTime: ~p",[NLargeTime]),
+ true = NLargeTime > NLargeWeight,
ok.
%%%-----------------------------------------------------------------
-timeout(suite) -> [];
timeout(_Config) ->
- ?line overload:set_config_data(0.8, 1),
- ?line _N = do_many_requests(0),
-
+ overload:set_config_data(0.8, 1),
+ _N = do_many_requests(0),
+
%% Check that the overload alarm is raised
- ?line [{overload,_}] = alarm_handler:get_alarms(),
+ [{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(),
+ overload ! timeout,
+ timer:sleep(1000),
+ [{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(),
+ overload ! timeout,
+ timer:sleep(1000),
+ [] = alarm_handler:get_alarms(),
ok.
@@ -171,5 +165,3 @@ check_info(MI,W,Info) ->
{{_,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
index b53c382609..35a4eb7e7b 100644
--- a/lib/sasl/test/rb_SUITE.erl
+++ b/lib/sasl/test/rb_SUITE.erl
@@ -18,7 +18,8 @@
%%
-module(rb_SUITE).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
+
-compile(export_all).
@@ -45,19 +46,10 @@ groups() ->
]}].
-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),
+ PrivDir = ?config(priv_dir,Config),
+ RbDir = filename:join(PrivDir,rb),
+ ok = file:make_dir(RbDir),
NewConfig = [{rb_dir,RbDir}|Config],
reset_sasl(NewConfig),
NewConfig.
@@ -66,10 +58,18 @@ end_per_suite(_Config) ->
ok.
init_per_group(running_error_logger,Config) ->
- install_mf_h(Config).
+ %% Install log_mf_h
+ RbDir = ?config(rb_dir,Config),
+ ok = application:set_env(sasl,error_logger_mf_dir,RbDir),
+ ok = application:set_env(sasl,error_logger_mf_maxbytes,5000),
+ ok = application:set_env(sasl,error_logger_mf_maxfiles,2),
+ restart_sasl(),
+ Config.
end_per_group(running_error_logger,Config) ->
- remove_mf_h(Config).
+ %% Remove log_mf_h???
+ ok.
+
init_per_testcase(_Case,Config) ->
case whereis(?SUP) of
@@ -92,187 +92,152 @@ end_per_testcase(Case,Config) ->
%%%-----------------------------------------------------------------
+%%% Test cases
-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),
+ Help = capture(fun() -> rb:h() end),
+ "Report Browser Tool - usage" = hd(Help),
+ "rb:stop - stop the rb_server" = lists:last(Help),
ok.
-
-start_error_stop() -> start_error_stop(suite).
-start_error_stop(suite) -> [];
+%% Test that all three sasl env vars must be set for a successful start of rb
+%% Then stop rb.
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.
+ RbDir = ?config(rb_dir,Config),
+ {error,{"cannot locate report directory",_}} = rb:start(),
-%% 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.
+ ok = application:set_env(sasl,error_logger_mf_dir,"invaliddir"),
+ ok = application:set_env(sasl,error_logger_mf_maxbytes,1000),
+ ok = application:set_env(sasl,error_logger_mf_maxfiles,2),
+ restart_sasl(),
+ {error,{"cannot read the index file",_}} = rb:start(),
+ ok = application:set_env(sasl,error_logger_mf_dir,RbDir),
+ restart_sasl(),
+ {ok,_} = rb:start(),
-remove_mf_h(_Config) ->
+ ok = rb:stop(),
ok.
-
-
-show() -> show(suite).
-show(suite) -> [];
show(Config) ->
- ?line PrivDir = ?config(priv_dir,Config),
- ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
-
+ PrivDir = ?config(priv_dir,Config),
+ 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),
+ ok = start_rb(OutFile),
%% Show all reports
- ?line All = check_report(fun() -> rb:show() end,OutFile),
+ 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),
+ [{_,First}] = check_report(fun() -> rb:show(1) end,OutFile),
+ {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}"),
+ [{_,CR}] = check_report(fun() -> rb:show(crash_report) end,OutFile),
+ true = contains(CR,"rb_test_crash"),
+ [{_,EC},{_,EM}] = check_report(fun() -> rb:show(error) end,OutFile),
+ true = contains(EC,"rb_test_crash"),
+ true = contains(EM,"rb_test_error_msg"),
+ [{_,ER}] = check_report(fun() -> rb:show(error_report) end,OutFile),
+ true = contains(ER,"rb_test_error"),
+ [{_,IR}] = check_report(fun() -> rb:show(info_report) end,OutFile),
+ true = contains(IR,"rb_test_info"),
+ [{_,IM}] = check_report(fun() -> rb:show(info_msg) end,OutFile),
+ true = contains(IM,"rb_test_info_msg"),
+ [_|_] = check_report(fun() -> rb:show(progress) end,OutFile),
+ [{_,SR}] = check_report(fun() -> rb:show(supervisor_report) end,
+ OutFile),
+ true = contains(SR,"child_terminated"),
+ 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"),
+ PrivDir = ?config(priv_dir,Config),
+ 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}] =
+ ok = start_rb(OutFile),
+
+ All = capture(fun() -> rb:list() end),
+ [{crash_report,[_]=CR},
+ {error,[_,_]=EM},
+ {error_report,[_]=ER},
+ {info_msg,[_]=IM},
+ {info_report,[_]=IR},
+ {progress,[_|_]=P},
+ {supervisor_report,[_]=SR}] = sort_list(All),
+
+ [{crash_report,CR}] =
sort_list(capture(fun() -> rb:list(crash_report) end)),
- ?line [{error,EM}] =
+ [{error,EM}] =
sort_list(capture(fun() -> rb:list(error) end)),
- ?line [{error_report,ER}] =
+ [{error_report,ER}] =
sort_list(capture(fun() -> rb:list(error_report) end)),
- ?line [{info_msg,IM}] =
+ [{info_msg,IM}] =
sort_list(capture(fun() -> rb:list(info_msg) end)),
- ?line [{info_report,IR}] =
+ [{info_report,IR}] =
sort_list(capture(fun() -> rb:list(info_report) end)),
- ?line [{progress,P}] =
+ [{progress,P}] =
sort_list(capture(fun() -> rb:list(progress) end)),
- ?line [{supervisor_report,SR}] =
+ [{supervisor_report,SR}] =
sort_list(capture(fun() -> rb:list(supervisor_report) end)),
-
- ok.
+ ok.
-grep() -> grep(suite).
-grep(suite) -> [];
grep(Config) ->
- ?line PrivDir = ?config(priv_dir,Config),
- ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+ PrivDir = ?config(priv_dir,Config),
+ 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 = start_rb(OutFile),
+
+ [{_,S},
+ {_,CR},
+ {_,EC},
+ {_,IM},
+ {_,IR},
+ {_,EM},
+ {_,ER}]= check_report(fun() -> rb:grep("rb_test_") end,OutFile),
+ true = contains(S, "rb_test_crash"),
+ true = contains(CR, "rb_test_crash"),
+ true = contains(EC, "rb_test_crash"),
+ true = contains(IM, "rb_test_info_msg"),
+ true = contains(IR, "rb_test_info"),
+ true = contains(EM, "rb_test_error_msg"),
+ 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"),
+ PrivDir = ?config(priv_dir,Config),
+ 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),
+ ok = start_rb(OutFile),
- ?line All = check_report(fun() -> rb:show() end,OutFile),
+ 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),
+ ER = [_] = rb_filter([{rb_SUITE,rb_test_error}],OutFile),
+ [] = rb_filter([{rb_SUITE,rb_test}],OutFile),
+ _E = [_,_] = rb_filter([{rb_SUITE,"rb_test",re}],OutFile),
+ 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,
+ 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"),
+ PrivDir = ?config(priv_dir,Config),
+ OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
%% Insert some reports in the error log and start rb
@@ -280,35 +245,33 @@ filter_date(Config) ->
Between1 = calendar:local_time(),
timer:sleep(1000),
Between2 = calendar:local_time(),
- ?line ok = start_rb(OutFile),
+ ok = start_rb(OutFile),
- ?line All = check_report(fun() -> rb:show() end,OutFile),
+ All = check_report(fun() -> rb:show() end,OutFile),
Before = calendar:gregorian_seconds_to_datetime(
- calendar:datetime_to_gregorian_seconds(calendar:local_time()) - 10),
+ 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),
+ All = rb_filter([],{Before,from},OutFile),
+ All = rb_filter([],{After,to},OutFile),
+ [] = rb_filter([],{Before,to},OutFile),
+ [] = rb_filter([],{After,from},OutFile),
+ 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),
+ AllButLast = [{N-1,R} || {N,R} <- tl(All)],
+ AllButLast = rb_filter([],{Before,Between1},OutFile),
- ?line Last = hd(All),
- ?line [Last] = rb_filter([],{Between2,After},OutFile),
+ Last = hd(All),
+ [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"),
+ PrivDir = ?config(priv_dir,Config),
+ OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
%% Insert some reports in the error log and start rb
@@ -316,102 +279,96 @@ filter_filter_and_date(Config) ->
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),
+ error_logger:error_report([{rb_SUITE,rb_test_filter}]),
+ ok = start_rb(OutFile),
Before = calendar:gregorian_seconds_to_datetime(
- calendar:datetime_to_gregorian_seconds(calendar:local_time()) - 10),
+ 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),
+ All = check_report(fun() -> rb:show() end,OutFile),
+ 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"),
+ [_,_,_] = rb_filter([{rb_SUITE,"rb_test",re}],{Before,After},OutFile),
+ [_,_] = rb_filter([{rb_SUITE,"rb_test",re}],{Before,Between1},OutFile),
+ [_] = rb_filter([{rb_SUITE,"rb_test",re}],{Between2,After},OutFile),
+ [_] = rb_filter([{rb_SUITE,rb_test_filter}],{Before,After},OutFile),
+ [] = rb_filter([{rb_SUITE,rb_test_filter}],{Before,Between1},OutFile),
+ [Last] = rb_filter([{rb_SUITE,rb_test_filter,no}],{Between2,After},OutFile),
+ {_,Str} = Last,
+ 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"),
+ PrivDir = ?config(priv_dir,Config),
+ 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),
+ ok = start_rb(OutFile),
- ?line All = check_report(fun() -> rb:show() end,OutFile),
+ 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),
+ E = [_,_] = rb_filter([{rb_SUITE,"rb_test",re}],OutFile),
+ 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,
+ 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"),
-
+ PrivDir = ?config(priv_dir,Config),
+ OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
%% Start rb
- ?line ok = start_rb(OutFile),
+ 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),
+ AllBefore = capture(fun() -> rb:list() end),
+ error_logger:error_report([{rb_SUITE,rb_test_rescan}]),
+ ok = rb:rescan(),
+ AllAfter = capture(fun() -> rb:list() end),
+ Diff = length(AllAfter) - length(AllBefore),
+ 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,[]),
+ PrivDir = ?config(priv_dir,Config),
+ OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+ 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),
-
+ ok = start_rb(),
+ StdioResult = [_|_] = capture(fun() -> rb:show(1) end),
+ {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 =/= <<>>),
+ ok = rb:start_log(OutFile),
+ [] = capture(fun() -> rb:show(1) end),
+ {ok,Bin} = file:read_file(OutFile),
+ 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),
+ ok = rb:stop_log(),
+ ok = file:write_file(OutFile,[]),
+ StdioResult = capture(fun() -> rb:show(1) end),
+ {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 = rb:start_log(filename:join(nonexistingdir,"newfile.txt")),
+ StdioResult = capture(fun() -> rb:show(1) end),
+ {ok,<<>>} = file:read_file(OutFile),
ok.
@@ -435,7 +392,7 @@ empty_error_logs(Config) ->
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) ->
@@ -448,7 +405,7 @@ wait_for_sasl(N) ->
timer:sleep(100),
wait_for_sasl(N-1)
end.
-
+
start_rb(OutFile) ->
do_start_rb([{start_log,OutFile}]).
start_rb() ->
@@ -482,20 +439,20 @@ delete_content(Dir) ->
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(),
+ error_logger:error_report([{rb_SUITE,rb_test_error}]),
+ error_logger:error_msg("rb_test_error_msg"),
+ error_logger:info_report([{rb_SUITE,rb_test_info}]),
+ error_logger:info_msg("rb_test_info_msg"),
+ _Pid = start(),
+ Ref = erlang:monitor(process,?MODULE),
+ gen_server:cast(?MODULE,crash),
+ 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,
+ erlang:demonitor(Ref),
+ wait_for_server(),
ok.
wait_for_server() ->
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index af2183bfff..a8e3cc3d88 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,7 @@
-module(release_handler_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include("test_lib.hrl").
-compile(export_all).
@@ -30,6 +31,7 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
init_per_suite(Config) ->
+ init_priv_dir(Config),
application:start(sasl),
Config.
@@ -58,7 +60,10 @@ 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].
+ instructions, eval_appup, eval_appup_with_restart,
+ supervisor_which_children_timeout,
+ release_handler_which_releases, install_release_syntax_check,
+ upgrade_supervisor, upgrade_supervisor_fail, otp_9864].
groups() ->
[{release,[],
@@ -69,6 +74,7 @@ groups() ->
{release_single,[],
[
upgrade,
+ upgrade_restart,
client1,
client2
]},
@@ -82,7 +88,7 @@ groups() ->
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_p1g(Config,P1gInstall),
ok = create_p1h(Config),
?t:timetrap_cancel(Dog);
@@ -95,6 +101,7 @@ init_per_group(release_single, Config) ->
%% Create some more releases to upgrade to
ok = create_p1i(Config),
ok = create_p2a(Config),
+ ok = create_p2b(Config),
?t:timetrap_cancel(Dog);
@@ -155,7 +162,7 @@ end_per_group(release, Config) ->
{win32,_} -> delete_all_services();
_ -> ok
end,
- delete_release(Config),
+ clean_priv_dir(Config,true),
?t:timetrap_cancel(Dog),
Config;
end_per_group(_GroupName, Config) ->
@@ -191,7 +198,10 @@ end_per_testcase(Case, Config) ->
FailDir = filename:join(SaveDir,lists:concat(["failed-",Case])),
ok = filelib:ensure_dir(filename:join(FailDir,"*")),
- LogDirs = filelib:wildcard(filename:join([PrivDir,"*",log])),
+ LogDirs =
+ filelib:wildcard(filename:join([PrivDir,"*",log])) ++
+ filelib:wildcard(filename:join([PrivDir,"*",clients,
+ type1,"*",log])),
lists:foreach(
fun(LogDir) ->
@@ -236,7 +246,7 @@ break(Config) ->
?t:break(priv_dir(Config)),
ok.
-%% Test upgrade and downgrade of erts
+%% Test upgrade and downgrade of erts and other apps on embedded node
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]),
@@ -259,54 +269,75 @@ upgrade(Conf) when is_list(Conf) ->
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]),
+ %% check that P1H is permanent, unpack and install P1I, unpack P2A
ok = rpc_inst(TestNode, install_3, [PrivDir]),
stop_cover(TestNode),
- ok = rpc_inst(TestNode, install_3a, []),
- wait_nodes_up([{TestNode,TestNodeInit1}],"install_3",[a]),
+ reboot_and_wait(TestNode,"install_3",[a]),
- %% check that P2A is used, reboot from P1I
- ok = rpc_inst(TestNode, install_4, []),
+ %% check that P1H is used, install P2A
+ TestNodeInit1 = rpc:call(TestNode,erlang,whereis,[init]),
stop_cover(TestNode),
- reboot_and_wait(TestNode,"install_4",[a]),
+ ok = rpc_inst(TestNode, install_4, []),
+ wait_nodes_up([{TestNode,TestNodeInit1}],"install_4",[a]),
- %% check that P1I, reinstall P2A
+ %% check that P2A is used, then downgrade to P1I
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
+ %% Check that P1I is used, then make P1I permanent and install P2A
+ TestNodeInit3 = rpc:call(TestNode,erlang,whereis,[init]),
ok = rpc_inst(TestNode, install_6, []),
stop_cover(TestNode),
- reboot_and_wait(TestNode,"install_6",[a]),
+ ok = rpc_inst(TestNode, install_6a, []),
+ wait_nodes_up([{TestNode,TestNodeInit3}],"install_6",[a]),
- %% check that P2A is permanent, install old P1H
- TestNodeInit3 = rpc:call(TestNode,erlang,whereis,[init]),
- stop_cover(TestNode),
+ %% check that P2A is used, then downgrade to P1H
+ TestNodeInit4 = rpc:call(TestNode,erlang,whereis,[init]),
ok = rpc_inst(TestNode, install_7, []),
- wait_nodes_up([{TestNode,TestNodeInit3}],"install_7",[a]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, install_7a, []),
+ wait_nodes_up([{TestNode,TestNodeInit4}],"install_7",[a]),
- %% check that P1H is permanent, remove P1I and P2A
+ %% check that P1H is used, then install P1I and check that it is permanent
+ %% then reinstall P2A
+ TestNodeInit5 = rpc:call(TestNode,erlang,whereis,[init]),
ok = rpc_inst(TestNode, install_8, []),
stop_cover(TestNode),
- reboot_and_wait(TestNode,"install_8",[a]),
+ ok = rpc_inst(TestNode, install_8a, []),
+ wait_nodes_up([{TestNode,TestNodeInit5}],"install_8",[a]),
+
+ %% check that P2A is used, make P2A permanent
+ ok = rpc_inst(TestNode, install_9, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_9",[a]),
+
+ %% check that P2A is permanent, reboot to old P1H
+ TestNodeInit6 = rpc:call(TestNode,erlang,whereis,[init]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, install_10, []),
+ wait_nodes_up([{TestNode,TestNodeInit6}],"install_10",[a]),
+
+ %% check that P1H is permanent, remove P1I and P2A
+ ok = rpc_inst(TestNode, install_11, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_11",[a]),
%% check that P1H is permanent, reboot old P1G
- TestNodeInit4 = rpc:call(TestNode,erlang,whereis,[init]),
+ TestNodeInit7 = rpc:call(TestNode,erlang,whereis,[init]),
stop_cover(TestNode),
- ok = rpc_inst(TestNode, install_9, []),
- wait_nodes_up([{TestNode,TestNodeInit4}],"install_9"),
+ ok = rpc_inst(TestNode, install_12, []),
+ wait_nodes_up([{TestNode,TestNodeInit7}],"install_12"),
%% check that P1G is permanent, remove P1H
- ok = rpc_inst(TestNode, install_10, []),
+ ok = rpc_inst(TestNode, install_13, []),
stop_cover(TestNode),
- reboot_and_wait(TestNode,"install_10"),
+ reboot_and_wait(TestNode,"install_13"),
%% check that P1G is permanent
- ok = rpc_inst(TestNode, install_11, []),
+ ok = rpc_inst(TestNode, install_14, []),
ok.
@@ -323,6 +354,54 @@ reboot_and_wait(Node,Tag,Apps) ->
wait_nodes_up([{Node,InitPid}],Tag,Apps).
+%% Test upgrade and downgrade of erts in combination with the
+%% restart_emulator option to systools:make_relup. For upgrade, this
+%% should cause one restart before the upgrade code, and one
+%% after. For downgrade, there will be one restart only - at the end.
+upgrade_restart(Conf) when is_list(Conf) ->
+ reg_print_proc(), %% starts a printer process on test_server node
+ ?t:format("upgrade_restart ~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_restart start"),
+
+ %% unpack and install P2B
+ TestNodeInit1 = rpc:call(TestNode,erlang,whereis,[init]),
+ ok = rpc_inst(TestNode, upgrade_restart_1, [PrivDir]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, upgrade_restart_1a, []),
+ wait_nodes_up([{TestNode,TestNodeInit1}],"upgrade_restart_1",[a]),
+
+ %% install P1G
+ case rpc_inst(TestNode, upgrade_restart_2, []) of
+ ok ->
+ ok;
+ {wait,TestNodeInit2a} ->
+ %% We catched the node too early - it was supposed to
+ %% restart twice, so let's wait for one more restart.
+ wait_nodes_up([{TestNode,TestNodeInit2a}],"upgrade_restart_2a",[]),
+ ok = rpc_inst(TestNode, upgrade_restart_2a, [])
+ end,
+ TestNodeInit2 = rpc:call(TestNode,erlang,whereis,[init]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, upgrade_restart_2b, []),
+ wait_nodes_up([{TestNode,TestNodeInit2}],"upgrade_restart_2b",[]),
+
+ %% Check that P1G is going again
+ ok = rpc_inst(TestNode, upgrade_restart_3, []),
+
+ ok.
+
+upgrade_restart(cleanup,Config) ->
+ TestNode = tc_full_node_name(Config),
+ ok = stop_nodes([TestNode]).
+
+
%% Test upgrade and downgrade of erts, diskless
client1(Conf) when is_list(Conf) ->
reg_print_proc(), %% starts a printer process on test_server node
@@ -542,9 +621,51 @@ supervisor_which_children_timeout(Conf) ->
ok.
-supervisor_which_children_timeout(cleanup, Conf) ->
+supervisor_which_children_timeout(cleanup, _Conf) ->
stop_node(node_name(supervisor_which_children_timeout)).
+
+%% Test that check_install_release will fail for illegal relup
+%% instructions, even after point of no return.
+install_release_syntax_check(Conf) when is_list(Conf) ->
+
+ S1 = [point_of_no_return, illegal_instruction],
+ {error,{illegal_instruction_after_point_of_no_return,illegal_instruction}} =
+ release_handler_1:check_script(S1,[]),
+
+ S2 = [point_of_no_return,restart_new_emulator],
+ {error,{illegal_instruction_after_point_of_no_return,restart_new_emulator}} =
+ release_handler_1:check_script(S2,[]),
+
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% release_handler:which_releases/0 and 1 test
+%%-----------------------------------------------------------------
+release_handler_which_releases(Conf) ->
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"release_handler_which_releases"),
+ 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(release_handler_which_releases, Rel1, []),
+ Releases0 = rpc:call(Node, release_handler, which_releases, []),
+ Releases1 = rpc:call(Node, release_handler, which_releases, [permanent]),
+ Releases2 = rpc:call(Node, release_handler, which_releases, [old]),
+
+ 1 = length(Releases0),
+ 1 = length(Releases1),
+ 0 = length(Releases2),
+
+ ?t:format("release_handler:which_releases/0: ~p~n", [Releases0]),
+ ?t:format("release_handler:which_releases/1: ~p~n", [Releases1]),
+ ?t:format("release_handler:which_releases/1: ~p~n", [Releases2]),
+
+ ok.
+
%%-----------------------------------------------------------------
%% Ticket: OTP-2740
%% Slogan: vsn not numeric doesn't work so good in release_handling
@@ -1084,6 +1205,163 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
otp_9395_rm_many_mods(cleanup,_Conf) ->
stop_node(node_name(otp_9395_rm_many_mods)).
+otp_9864(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9864"),
+ 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_9864, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% 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]),
+
+ %% Install RelVsn1 again
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn1]),
+
+ TempRel2Dir = filename:join(Dir,"releases/2"),
+ file:make_symlink(TempRel2Dir, filename:join(TempRel2Dir, "foo_symlink_dir")),
+
+ %% This will fail if symlinks are not handled
+ ok = rpc:call(Node, release_handler, remove_release, [RelVsn2]),
+
+ ok.
+
+
+upgrade_supervisor(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"upgrade_supervisor"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Lib1 = [{a,"1.0",LibDir}],
+ Lib2 = [{a,"9.0",LibDir}],
+ Rel1 = create_and_install_fake_first_release(Dir,Lib1),
+ Rel2 = create_fake_upgrade_release(Dir,"2",Lib2,{[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(upgrade_supervisor, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Check path
+ Dir1 = filename:join([LibDir, "a-1.0"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [a]),
+ ASupBeam1 = filename:join([Dir1,ebin,"a_sup.beam"]),
+ ASupBeam1 = rpc:call(Node, code, which, [a_sup]),
+
+ %% Install second release, with no changed modules
+ {ok, RelVsn2} = rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", Lib2]),
+ 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 libdir is changed
+ Dir2 = filename:join([LibDir, "a-9.0"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [a]),
+ ASupBeam2 = filename:join([Dir2,ebin,"a_sup.beam"]),
+ ASupBeam2 = rpc:call(Node, code, which, [a_sup]),
+
+ %% Check that the restart strategy and child spec is updated
+ {status, _, {module, _}, [_, _, _, _, [_,_,{data,[{"State",State}]}]]} =
+ rpc:call(Node,sys,get_status,[a_sup]),
+ {state,_,RestartStrategy,[Child],_,_,_,_,_,_} = State,
+ one_for_all = RestartStrategy, % changed from one_for_one
+ {child,_,_,_,_,brutal_kill,_,_} = Child, % changed from timeout 2000
+
+ ok.
+
+%% Check that if the supervisor fails, then the upgrade is rolled back
+%% and an ok error message is returned
+upgrade_supervisor_fail(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"upgrade_supervisor_fail"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Lib1 = [{a,"1.0",LibDir}],
+ Lib2 = [{a,"9.1",LibDir}],
+ Rel1 = create_and_install_fake_first_release(Dir,Lib1),
+ Rel2 = create_fake_upgrade_release(Dir,"2",Lib2,{[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(upgrade_supervisor_fail, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Check path
+ Dir1 = filename:join([LibDir, "a-1.0"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [a]),
+ ASupBeam1 = filename:join([Dir1,ebin,"a_sup.beam"]),
+ ASupBeam1 = rpc:call(Node, code, which, [a_sup]),
+
+ %% Install second release, with no changed modules
+ {ok, RelVsn2} = rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", Lib2]),
+ 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 = net_kernel:monitor_nodes(true),
+
+ {error,{code_change_failed,_Pid,a_sup,_Vsn,
+ {error,{invalid_shutdown,brutal_kil}}}} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Check that the upgrade is terminated - normally this would mean
+ %% rollback, but since this testcase is very simplified the node
+ %% is not started with heart supervision and will therefore not be
+ %% restarted. So we just check that the node goes down.
+ receive {nodedown,Node} -> ok
+ after 10000 -> ct:fail(failed_upgrade_never_restarted_node)
+ end,
+
+ ok.
%% Test upgrade and downgrade of applications
@@ -1107,6 +1385,12 @@ eval_appup(Conf) when is_list(Conf) ->
App11Dir = code:lib_dir(app1),
ok = gen_server:call(harry, error),
+ %% Read appup script
+ {ok,"2.0",UpScript} = release_handler:upgrade_script(app1,App12Dir),
+ [{load_object_code,_},
+ point_of_no_return,
+ {load,_}] = UpScript,
+
%% Upgrade to app1-2.0
{ok, []} = release_handler:upgrade_app(app1, App12Dir),
App12Dir = code:lib_dir(app1),
@@ -1117,6 +1401,12 @@ eval_appup(Conf) when is_list(Conf) ->
%% (see myrel/lib2/app1-2.0/ebin/app1.app)
[{var,val2}] = ets:lookup(otp_6162, var),
+ %% Read appup script
+ {ok,DnScript} = release_handler:downgrade_script(app1,"1.0",App11Dir),
+ [{load_object_code,_},
+ point_of_no_return,
+ {load,_}] = DnScript,
+
%% Downgrade to app1-1.0
{ok, []} = release_handler:downgrade_app(app1,"1.0",App11Dir),
App11Dir = code:lib_dir(app1),
@@ -1134,6 +1424,85 @@ eval_appup(Conf) when is_list(Conf) ->
ok.
+%% Test upgrade and downgrade of applications when appup contains
+%% restart_emulator and restart_new_emulator instructions
+eval_appup_with_restart(Conf) when is_list(Conf) ->
+
+ %% Set some paths
+ RelDir = filename:join(?config(data_dir, Conf), "app1_app2"),
+ App11Dir = filename:join([RelDir, "lib1", "app1-1.0"]),
+ App13Dir = filename:join([RelDir, "lib3", "app1-3.0"]), %restart_emulator
+ App14Dir = filename:join([RelDir, "lib4", "app1-4.0"]), %restart_new_emulator
+ EbinDir1 = filename:join(App11Dir, "ebin"),
+ EbinDir3 = filename:join(App13Dir, "ebin"),
+ EbinDir4 = filename:join(App14Dir, "ebin"),
+
+ %% Start app1-1.0
+ code:add_patha(EbinDir1),
+ ok = application:start(app1),
+ App11Dir = code:lib_dir(app1),
+
+ %% Read appup script
+ {ok,"3.0",UpScript3} = release_handler:upgrade_script(app1,App13Dir),
+ [{load_object_code,_},
+ point_of_no_return,
+ {load,_},
+ restart_emulator] = UpScript3,
+
+ %% Upgrade to app1-3.0 - restart_emulator
+ restart_emulator = release_handler:upgrade_app(app1, App13Dir),
+ App13Dir = code:lib_dir(app1),
+
+ %% Fake full upgrade to 3.0
+ {ok,AppSpec} = file:consult(filename:join([App13Dir,"ebin","app1.app"])),
+ application_controller:change_application_data(AppSpec,[]),
+
+ %% Read appup script
+ {ok,"4.0",UpScript4} = release_handler:upgrade_script(app1,App14Dir),
+ [restart_new_emulator,point_of_no_return] = UpScript4,
+
+ %% Try pgrade to app1-4.0 - restart_new_emulator
+ {error,restart_new_emulator} = release_handler:upgrade_app(app1, App14Dir),
+ App13Dir = code:lib_dir(app1),
+
+ %% Read appup script
+ {ok,DnScript1} = release_handler:downgrade_script(app1,"1.0",App11Dir),
+ [{load_object_code,_},
+ point_of_no_return,
+ {load,_},
+ restart_emulator] = DnScript1,
+
+ %% Still running 3.0 - downgrade to app1-1.0 - restart_emulator
+ restart_emulator = release_handler:downgrade_app(app1,"1.0",App11Dir),
+ App11Dir = code:lib_dir(app1),
+
+ ok = application:stop(app1),
+ ok = application:unload(app1),
+ true = code:del_path(EbinDir1),
+
+ %% Start again as version 4.0
+ code:add_patha(EbinDir4),
+ ok = application:start(app1),
+ App14Dir = code:lib_dir(app1),
+
+ %% Read appup script
+ {ok,DnScript3} = release_handler:downgrade_script(app1,"3.0",App13Dir),
+ [point_of_no_return,restart_emulator] = DnScript3,
+
+ %% Downgrade to app1-3.0 - restart_new_emulator
+ restart_emulator = release_handler:downgrade_app(app1,"3.0",App13Dir),
+ App13Dir = code:lib_dir(app1),
+
+ ok = application:stop(app1),
+ ok = application:unload(app1),
+
+ true = code:del_path(EbinDir3),
+ false = code:del_path(EbinDir1),
+ false = code:del_path(EbinDir4),
+
+ ok.
+
+
%% Test the example/target_system.erl module
target_system(Conf) when is_list(Conf) ->
PrivDir = priv_dir(Conf),
@@ -1147,11 +1516,10 @@ target_system(Conf) when is_list(Conf) ->
%% 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"}]),
+ create_rel_file(RelFile,RelName,RelVsn,current,[{a, "1.0"}]),
%% Build the target_system module
ExamplesEbin = filename:join([code:lib_dir(sasl),examples,ebin]),
@@ -1179,11 +1547,13 @@ target_system(Conf) when is_list(Conf) ->
code:del_path(TSPath),
%% Check that all files exist in installation
- true = filelib:is_dir(filename:join(TargetInstallDir,"erts-"++ErtsVsn)),
+ ErtsDir = app_dir(erts,current),
+ true = filelib:is_dir(filename:join(TargetInstallDir,ErtsDir)),
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),
+ KernelVsn = vsn(kernel,current),
+ StdlibVsn = vsn(stdlib,current),
+ SaslVsn = vsn(sasl,current),
+ RelFileBasename = filename:basename(RelFile),
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)),
@@ -1191,10 +1561,10 @@ target_system(Conf) when is_list(Conf) ->
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_regular(filename:join(RelDir,RelFileBasename)),
true = filelib:is_dir(filename:join(RelDir,RelVsn)),
true = filelib:is_regular(filename:join([RelDir,RelVsn,"start.boot"])),
+ true = filelib:is_regular(filename:join([RelDir,RelVsn,RelFileBasename])),
BinDir = filename:join(TargetInstallDir,bin),
true = filelib:is_regular(filename:join(BinDir,"start.boot")),
true = filelib:is_regular(filename:join(BinDir,erl)),
@@ -1205,6 +1575,7 @@ target_system(Conf) when is_list(Conf) ->
true = filelib:is_regular(filename:join(BinDir,to_erl)),
%% Check content of files
+ ErtsVsn = vsn(erts,current),
{ok,SED} = file:read_file(filename:join(RelDir,"start_erl.data")),
[ErtsVsn,RelVsn] = string:tokens(binary_to_list(SED),"\s\n"),
ok.
@@ -1456,7 +1827,7 @@ copy_client(Conf,Master,Sname,Client) ->
ok.
-delete_release(Conf) ->
+clean_priv_dir(Conf,Save) ->
PrivDir = priv_dir(Conf),
{ok, OrigWd} = file:get_cwd(),
@@ -1466,7 +1837,7 @@ delete_release(Conf) ->
{ok, Dirs} = file:list_dir(PrivDir),
?t:format("======== deleting ~p~n",[Dirs]),
- ok = delete_release_os(Dirs--["save"]),
+ ok = clean_dirs_os(Dirs,Save),
{ok,Remaining} = file:list_dir(PrivDir),
?t:format("======== remaining ~p~n",[Remaining]),
@@ -1474,7 +1845,7 @@ delete_release(Conf) ->
[] ->
ok;
_ ->
- delete_release_os(Remaining),
+ clean_dirs_os(Remaining,Save),
Remaining2 = file:list_dir(PrivDir),
?t:format("======== remaining after second try ~p~n",[Remaining2])
end,
@@ -1483,22 +1854,22 @@ delete_release(Conf) ->
ok.
-delete_release_os(Dirs) ->
+clean_dirs_os(Dirs,Save) ->
case os:type() of
{unix, _} ->
- delete_release_unix(Dirs);
+ clean_dirs_unix(Dirs,Save);
{win32, _} ->
- delete_release_win32(Dirs);
+ clean_dirs_win32(Dirs,Save);
Os ->
test_server:fail({error, {not_yet_implemented_os, Os}})
end.
-delete_release_unix([]) ->
+clean_dirs_unix([],_) ->
ok;
-delete_release_unix(["save"|Dirs]) ->
- delete_release_unix(Dirs);
-delete_release_unix([Dir|Dirs]) ->
+clean_dirs_unix(["save"|Dirs],Save) when Save ->
+ clean_dirs_unix(Dirs,Save);
+clean_dirs_unix([Dir|Dirs],Save) ->
Rm = string:concat("rm -rf ", Dir),
?t:format("============== COMMAND ~p~n",[Rm]),
case file:list_dir(Dir) of
@@ -1515,13 +1886,13 @@ delete_release_unix([Dir|Dirs]) ->
?t:format("------- ls -al ~p~n",[os:cmd("ls -al " ++ Dir)])
end,
- delete_release_unix(Dirs).
+ clean_dirs_unix(Dirs,Save).
-delete_release_win32([]) ->
+clean_dirs_win32([],_) ->
ok;
-delete_release_win32(["save"|Dirs]) ->
- delete_release_win32(Dirs);
-delete_release_win32([Dir|Dirs]) ->
+clean_dirs_win32(["save"|Dirs],Save) when Save ->
+ clean_dirs_win32(Dirs,Save);
+clean_dirs_win32([Dir|Dirs],Save) ->
Rm =
case filelib:is_dir(Dir) of
true ->
@@ -1531,7 +1902,7 @@ delete_release_win32([Dir|Dirs]) ->
end,
?t:format("============== COMMAND ~p~n",[Rm]),
[] = os:cmd(Rm),
- delete_release_win32(Dirs).
+ clean_dirs_win32(Dirs,Save).
node_name(Sname) when is_atom(Sname) ->
@@ -1657,9 +2028,17 @@ 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
+ filename:absname(filename:join(?config(data_dir, Conf),priv_dir)).
+
+init_priv_dir(Conf) ->
Dir = filename:absname(filename:join(?config(data_dir, Conf),priv_dir)),
- filelib:ensure_dir(filename:join(Dir,"*")),
- Dir.
+ case filelib:is_dir(Dir) of
+ true ->
+ clean_priv_dir(Conf,false);
+ false ->
+ ok
+ end,
+ filelib:ensure_dir(filename:join(Dir,"*")).
latest_version(Dir) ->
List = filelib:wildcard(Dir ++ "*"),
@@ -1694,14 +2073,22 @@ stop_print_proc() ->
%% 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),
+create_p1g(Conf,TargetDir) ->
DataDir = ?config(data_dir,Conf),
- ErtsVsn = "4.4",
- ErtsDir = "erts-"++ErtsVsn,
+ PrivDir = priv_dir(Conf),
+ ErtsDir = app_dir(erts,old),
+ KernelDir = app_dir(kernel,old),
+ StdlibDir = app_dir(stdlib,old),
+
+ %% Fake earlier version of kernel and stdlib
+ SystemLib = system_lib(PrivDir),
+ ok = filelib:ensure_dir(filename:join(SystemLib,"*")),
+ KernelLib = code:lib_dir(kernel),
+ StdlibLib = code:lib_dir(stdlib),
+ ok = copy_tree(Conf,KernelLib,KernelDir,SystemLib),
+ ok = copy_tree(Conf,StdlibLib,StdlibDir,SystemLib),
+ fix_version(SystemLib,kernel),
+ fix_version(SystemLib,stdlib),
%% Create dirs
BinDir = filename:join(TargetDir,bin),
@@ -1745,17 +2132,15 @@ do_create_p1g(Conf,TargetDir) ->
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, [], [], [], []),
+ TarFile = create_basic_release(Conf,RelFile,RelVsn,{old,false}),
%% 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]),
+ StartErlData = io_lib:fwrite("~s ~s~n", [vsn(erts,old), RelVsn]),
ok = file:write_file(StartErlDataFile, StartErlData),
%% Create RELEASES
@@ -1763,60 +2148,98 @@ do_create_p1g(Conf,TargetDir) ->
ok.
+fix_version(SystemLib,App) ->
+ FromVsn = vsn(App,current),
+ ToVsn = vsn(App,old),
+ Rootname = filename:join([SystemLib,app_dir(App,old),ebin,atom_to_list(App)]),
+
+ AppFile = Rootname ++ ".app",
+ {ok,OrigApp} = file:read_file(AppFile),
+ ok = file:write_file(AppFile,re:replace(OrigApp,FromVsn,ToVsn,
+ [{return,binary}])),
+ AppupFile = Rootname ++ ".appup",
+ {ok,OrigAppup} = file:read_file(AppupFile),
+ ok = file:write_file(AppupFile,re:replace(OrigAppup,FromVsn,ToVsn,
+ [{return,binary}])).
+
+
%% 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_upgrade_release(Conf,"rel1","P1H",{old,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"}],
+ create_upgrade_release(Conf,"rel2","P1I",{old,false},[{a,"1.1"}],
[{a,[{key2,newval2}]}],
- {"rel1",[{extra,gott}]}).
+ [{"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()},
+ create_upgrade_release(Conf,"rel3","P2A",{current,code:root_dir()},
+ [{a,"1.1"}],[{a,[{key2,newval2}]}],
+ [{"rel1",[new_emu,new_appl]},{"rel2",[new_emu]}],
+ [{"rel1",[old_emu,old_appl]},{"rel2",[old_emu]}]).
+
+%% Create version P2B - which is P2A, but with relup containing an
+%% extra reboot.
+%% Can be upgraded to from P1G - so must have run create_p1g first!!
+create_p2b(Conf) ->
+ create_upgrade_release(Conf,"rel4","P2B",{current,code:root_dir()},
[{a,"1.1"}],[{a,[{key2,newval2}]}],
- {"rel2",[new_emu]}).
+ [{"rel0",[new_emu,add_appl]}],
+ [{"rel0",[old_emu,rm_appl]}],
+ [restart_emulator]).
%% Create a release tar package which can be installed on top of P1G
-create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,{UpFromName,Descr}) ->
+create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,UpFrom) ->
+ create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,UpFrom,[]).
+create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,UpFrom,DownTo) ->
+ create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,UpFrom,DownTo,[]).
+create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,UpFrom0,DownTo0,RelupOpts) ->
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}],
+ UpFrom = [{filename:join([PrivDir,UpFromName,UpFromName]),Descr} ||
+ {UpFromName,Descr} <- UpFrom0],
+ DownTo = [{filename:join([PrivDir,DownToName,DownToName]),Descr} ||
+ {DownToName,Descr} <- DownTo0],
- create_basic_release(Conf, RelFile, RelVsn, Erts, LibPath,
- Apps, Config, UpFrom, []),
+ create_basic_release(Conf,RelFile,RelVsn,Erts,Apps,Config,
+ UpFrom,DownTo,RelupOpts),
ok.
%% Create .rel, .script, .boot, sys.config and tar
-create_basic_release(Conf, RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Config,UpFrom,DownTo) ->
+create_basic_release(Conf,RelFile,RelVsn,{Erts,ErtsDir}) ->
+ create_basic_release(Conf, RelFile,RelVsn,{Erts,ErtsDir},[],[],[],[],[]).
+create_basic_release(Conf,RelFile,RelVsn,{Erts,ErtsDir},ExtraApps,Config,UpFrom,DownTo,RelupOpts) ->
+ DataDir = ?config(data_dir,Conf),
+ PrivDir = priv_dir(Conf),
+ SystemLib = system_lib(PrivDir),
+ LibPath = [filename:join([SystemLib,"*",ebin]),
+ filename:join([DataDir,lib,"*",ebin])],
+
RelDir = filename:dirname(RelFile),
RelFileName = filename:rootname(RelFile),
%% Create .rel file
- create_installer_rel_file(RelFile,RelVsn,ErtsVsn,ExtraApps),
+ create_installer_rel_file(RelFile,RelVsn,Erts,ExtraApps),
%% Generate .script and .boot
ok = systools:make_script(RelFileName,
- [{path,[LibPath]},
+ [{path,LibPath},
{outdir,RelDir}]),
%% Generate relup
- ok = systools:make_relup(RelFileName,UpFrom,DownTo,[{path,[LibPath]},
- {outdir,RelDir}]),
+ ok = systools:make_relup(RelFileName,UpFrom,DownTo,[{path,LibPath},
+ {outdir,RelDir} |
+ RelupOpts]),
%% Create sys.config
ok = write_term_file(filename:join(RelDir,"sys.config"),Config),
@@ -1824,7 +2247,7 @@ create_basic_release(Conf, RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Co
%% Create tar file (i.e. collect all lib/app-*/* and system files)
ok = systools:make_tar(RelFileName,
- [{path,[LibPath]},
+ [{path,LibPath},
{outdir,RelDir} |
case ErtsDir of
false -> [];
@@ -1841,18 +2264,19 @@ create_basic_release(Conf, RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Co
TarFileName.
%% Create a .rel file
-create_installer_rel_file(RelFile,RelVsn,ErtsVsn,ExtraApps) ->
- create_rel_file(RelFile,"SASL-test",RelVsn,ErtsVsn,
+create_installer_rel_file(RelFile,RelVsn,Erts,ExtraApps) ->
+ create_rel_file(RelFile,"SASL-test",RelVsn,Erts,
[{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),
+create_rel_file(RelFile,RelName,RelVsn,Erts,ExtraApps) ->
+ ErtsVsn = vsn(erts,Erts),
+ KernelVsn = vsn(kernel,Erts),
+ StdlibVsn = vsn(stdlib,Erts),
+ SaslVsn = vsn(sasl,current),
application:load(tools),
- {ok,ToolsVsn} = application:get_key(tools,vsn),
+ ToolsVsn = vsn(tools,current),
application:load(runtime_tools),
- {ok,RuntimeToolsVsn} = application:get_key(runtime_tools,vsn),
+ RuntimeToolsVsn = vsn(runtime_tools,current),
RelFileContent = {release,
{RelName, RelVsn},
@@ -2033,7 +2457,7 @@ start_node_unix(Sname,NodeDir) ->
start_node_win32(Sname,NodeDir) ->
Name = atom_to_list(Sname) ++ "_P1G",
- ErtsBinDir = filename:join(NodeDir,"erts-4.4/bin"),
+ ErtsBinDir = filename:join([NodeDir,app_dir(erts,old),"bin"]),
StartErlArgs = rh_test_lib:get_start_erl_args(NodeDir),
ServiceArgs = rh_test_lib:get_service_args(NodeDir, Sname, StartErlArgs),
@@ -2158,7 +2582,6 @@ create_fake_release(Dir,RelName,RelVsn,AppDirs) ->
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}) ->
@@ -2168,7 +2591,7 @@ create_fake_release(Dir,RelName,RelVsn,AppDirs) ->
{[],[]},
AppDirs),
- create_rel_file(Rel++".rel",RelName,RelVsn,ErtsVsn,Apps),
+ create_rel_file(Rel++".rel",RelName,RelVsn,current,Apps),
%% Generate boot scripts
ok = systools:make_script(Rel,[local,
@@ -2217,3 +2640,16 @@ modify_tar_win32(Conf, TarFileName) ->
[ok = erl_tar:add(T,filename:join(TmpDir,F),F,[]) || F <- Fs],
ok = erl_tar:close(T),
ok.
+
+app_dir(App,Vsn) ->
+ atom_to_list(App) ++ "-" ++ vsn(App,Vsn).
+vsn(erts,old) -> ?ertsvsn;
+vsn(kernel,old) -> ?kernelvsn;
+vsn(stdlib,old) -> ?stdlibvsn;
+vsn(erts,current) -> erlang:system_info(version);
+vsn(App,current) ->
+ {ok,Vsn} = application:get_key(App,vsn),
+ Vsn.
+
+system_lib(PrivDir) ->
+ filename:join(PrivDir,"system_lib").
diff --git a/lib/sasl/test/release_handler_SUITE_data/Makefile.src b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
index edb446413d..55d20aa8b6 100644
--- a/lib/sasl/test/release_handler_SUITE_data/Makefile.src
+++ b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
@@ -5,6 +5,10 @@ P2B= \
P2B/a-2.0/ebin/a_sup.@EMULATOR@
LIB= \
+ lib/a-9.1/ebin/a.@EMULATOR@ \
+ lib/a-9.1/ebin/a_sup.@EMULATOR@ \
+ lib/a-9.0/ebin/a.@EMULATOR@ \
+ lib/a-9.0/ebin/a_sup.@EMULATOR@ \
lib/a-1.2/ebin/a.@EMULATOR@ \
lib/a-1.2/ebin/a_sup.@EMULATOR@ \
lib/a-1.1/ebin/a.@EMULATOR@ \
@@ -50,7 +54,13 @@ APP= \
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@
+ app1_app2/lib2/app2-1.0/ebin/app2.@EMULATOR@ \
+ app1_app2/lib3/app1-3.0/ebin/app1_sup.@EMULATOR@ \
+ app1_app2/lib3/app1-3.0/ebin/app1_server.@EMULATOR@ \
+ app1_app2/lib3/app1-3.0/ebin/app1.@EMULATOR@ \
+ app1_app2/lib4/app1-4.0/ebin/app1_sup.@EMULATOR@ \
+ app1_app2/lib4/app1-4.0/ebin/app1_server.@EMULATOR@ \
+ app1_app2/lib4/app1-4.0/ebin/app1.@EMULATOR@
OTP2740= \
otp_2740/vsn_atom.@EMULATOR@ \
@@ -95,6 +105,17 @@ lib/a-1.2/ebin/a.@EMULATOR@: 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/a-9.0/ebin/a.@EMULATOR@: lib/a-9.0/src/a.erl
+ erlc $(EFLAGS) -olib/a-9.0/ebin lib/a-9.0/src/a.erl
+lib/a-9.0/ebin/a_sup.@EMULATOR@: lib/a-9.0/src/a_sup.erl
+ erlc $(EFLAGS) -olib/a-9.0/ebin lib/a-9.0/src/a_sup.erl
+
+lib/a-9.1/ebin/a.@EMULATOR@: lib/a-9.1/src/a.erl
+ erlc $(EFLAGS) -olib/a-9.1/ebin lib/a-9.1/src/a.erl
+lib/a-9.1/ebin/a_sup.@EMULATOR@: lib/a-9.1/src/a_sup.erl
+ erlc $(EFLAGS) -olib/a-9.1/ebin lib/a-9.1/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
@@ -183,6 +204,22 @@ app1_app2/lib2/app2-1.0/ebin/app2.@EMULATOR@: app1_app2/lib2/app2-1.0/src/app2.e
erlc $(EFLAGS) -oapp1_app2/lib2/app2-1.0/ebin app1_app2/lib2/app2-1.0/src/app2.erl
+app1_app2/lib3/app1-3.0/ebin/app1_sup.@EMULATOR@: app1_app2/lib3/app1-3.0/src/app1_sup.erl
+ erlc $(EFLAGS) -oapp1_app2/lib3/app1-3.0/ebin app1_app2/lib3/app1-3.0/src/app1_sup.erl
+app1_app2/lib3/app1-3.0/ebin/app1_server.@EMULATOR@: app1_app2/lib3/app1-3.0/src/app1_server.erl
+ erlc $(EFLAGS) -oapp1_app2/lib3/app1-3.0/ebin app1_app2/lib3/app1-3.0/src/app1_server.erl
+app1_app2/lib3/app1-3.0/ebin/app1.@EMULATOR@: app1_app2/lib3/app1-3.0/src/app1.erl
+ erlc $(EFLAGS) -oapp1_app2/lib3/app1-3.0/ebin app1_app2/lib3/app1-3.0/src/app1.erl
+
+
+app1_app2/lib4/app1-4.0/ebin/app1_sup.@EMULATOR@: app1_app2/lib4/app1-4.0/src/app1_sup.erl
+ erlc $(EFLAGS) -oapp1_app2/lib4/app1-4.0/ebin app1_app2/lib4/app1-4.0/src/app1_sup.erl
+app1_app2/lib4/app1-4.0/ebin/app1_server.@EMULATOR@: app1_app2/lib4/app1-4.0/src/app1_server.erl
+ erlc $(EFLAGS) -oapp1_app2/lib4/app1-4.0/ebin app1_app2/lib4/app1-4.0/src/app1_server.erl
+app1_app2/lib4/app1-4.0/ebin/app1.@EMULATOR@: app1_app2/lib4/app1-4.0/src/app1.erl
+ erlc $(EFLAGS) -oapp1_app2/lib4/app1-4.0/ebin app1_app2/lib4/app1-4.0/src/app1.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
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.app b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.app
new file mode 100644
index 0000000000..4adc0540c4
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.app
@@ -0,0 +1,9 @@
+{application, app1,
+ [{description, "very simple example application"},
+ {id, "app1"},
+ {vsn, "3.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/lib3/app1-3.0/ebin/app1.appup b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.appup
new file mode 100644
index 0000000000..a5cdfe9fcc
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/ebin/app1.appup
@@ -0,0 +1,4 @@
+{"3.0",
+ [{"1.0", [{load_module, app1_server},restart_emulator]}],
+ [{"1.0", [{load_module, app1_server},restart_emulator]}]
+}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1.erl
new file mode 100644
index 0000000000..f123c8f470
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.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/lib3/app1-3.0/src/app1_server.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1_server.erl
new file mode 100644
index 0000000000..660d095ebf
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.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/lib3/app1-3.0/src/app1_sup.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.0/src/app1_sup.erl
new file mode 100644
index 0000000000..e6ad9b6967
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib3/app1-3.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/lib4/app1-4.0/ebin/app1.app b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/ebin/app1.app
new file mode 100644
index 0000000000..243bc21f02
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/ebin/app1.app
@@ -0,0 +1,9 @@
+{application, app1,
+ [{description, "very simple example application"},
+ {id, "app1"},
+ {vsn, "4.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/lib4/app1-4.0/ebin/app1.appup b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/ebin/app1.appup
new file mode 100644
index 0000000000..72535c8b34
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/ebin/app1.appup
@@ -0,0 +1,4 @@
+{"4.0",
+ [{"3.0", [restart_new_emulator]}],
+ [{"3.0", [restart_new_emulator]}]
+}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1.erl
new file mode 100644
index 0000000000..f123c8f470
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.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/lib4/app1-4.0/src/app1_server.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1_server.erl
new file mode 100644
index 0000000000..660d095ebf
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.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/lib4/app1-4.0/src/app1_sup.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.0/src/app1_sup.erl
new file mode 100644
index 0000000000..e6ad9b6967
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib4/app1-4.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/heart_restart.bat b/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
index ede1ad4ff3..ede1ad4ff3 100755..100644
--- a/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
+++ b/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/README b/lib/sasl/test/release_handler_SUITE_data/lib/README
index 639a4ca0fb..ffb8c5120b 100644
--- a/lib/sasl/test/release_handler_SUITE_data/lib/README
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/README
@@ -8,6 +8,14 @@ a-1.2:
can be upgraded to from a-1.1.
No module have changed, but priv dir is added including one 'file'
+a-9.0:
+can be upgrade to from a-1.0
+Changes a_sup correctly - to test successful upgrade of supervisor
+
+a-9.1:
+can be upgrade to from a-1.0
+Changes a_sup faulty - to test failing upgrade of supervisor
+
b-1.0:
start version, includes b_lib and b_server
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
index 05db4cb541..6ef67b869e 100644
--- 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
@@ -1,3 +1,3 @@
{"1.1",
[{"1.0",[{update,a,{advanced,extra_par}}]}],
- []}.
+ [{"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
index c082ad5339..1050e53f35 100644
--- 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
@@ -51,4 +51,6 @@ terminate(_Reason, _State) ->
ok.
code_change(1, Extra, State) ->
- {ok, {state, bval}}.
+ {ok, {state, bval}};
+code_change({down,1},Extra,State) ->
+ {ok, state}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.app b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.app
new file mode 100644
index 0000000000..aa436d3e8c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.app
@@ -0,0 +1,8 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "9.0"},
+ {modules, [a, a_sup]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.appup b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.appup
new file mode 100644
index 0000000000..c4071d57a3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/ebin/a.appup
@@ -0,0 +1,3 @@
+{"9.0",
+ [{"1.0",[{update,a_sup,{advanced,update_supervisor}}]}],
+ [{"1.0",[{update,a_sup,{advanced,update_supervisor}}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a.erl
new file mode 100644
index 0000000000..1050e53f35
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a.erl
@@ -0,0 +1,56 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The 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}};
+code_change({down,1},Extra,State) ->
+ {ok, state}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a_sup.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.0/src/a_sup.erl
new file mode 100644
index 0000000000..ae1d080f58
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.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_all, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, brutal_kill, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.app b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.app
new file mode 100644
index 0000000000..5b467ec4e8
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.app
@@ -0,0 +1,8 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "9.1"},
+ {modules, [a, a_sup]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.appup b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.appup
new file mode 100644
index 0000000000..efeb7f1fe3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/ebin/a.appup
@@ -0,0 +1,3 @@
+{"9.1",
+ [{"1.0",[{update,a_sup,{advanced,update_supervisor}}]}],
+ [{"1.0",[{update,a_sup,{advanced,update_supervisor}}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a.erl
new file mode 100644
index 0000000000..1050e53f35
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a.erl
@@ -0,0 +1,56 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The 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}};
+code_change({down,1},Extra,State) ->
+ {ok, state}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a_sup.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.1/src/a_sup.erl
new file mode 100644
index 0000000000..b0597dc5c3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-9.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_all, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, brutal_kil, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/sasl_SUITE.erl b/lib/sasl/test/sasl_SUITE.erl
index 454095db6a..b6eaf41323 100644
--- a/lib/sasl/test/sasl_SUITE.erl
+++ b/lib/sasl/test/sasl_SUITE.erl
@@ -20,20 +20,21 @@
-include_lib("common_test/include/ct.hrl").
-% Default timetrap timeout (set in init_per_testcase).
+%% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
-define(application, sasl).
-% Test server specific exports
+%% 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.
+%% Test cases must be exported.
-export([app_test/1,
+ appup_test/1,
log_mf_h_env/1]).
all() ->
- [app_test, log_mf_h_env].
+ [app_test, appup_test, log_mf_h_env].
groups() ->
[].
@@ -46,7 +47,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
+ Dog=test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
end_per_testcase(_Case, Config) ->
Dog=?config(watchdog, Config),
@@ -54,9 +55,105 @@ end_per_testcase(_Case, Config) ->
ok.
app_test(Config) when is_list(Config) ->
- ?line ?t:app_test(sasl, allow),
+ ?t:app_test(sasl, allow),
ok.
+%% Test that appup allows upgrade from/downgrade to a maximum of two
+%% major releases back.
+appup_test(_Config) ->
+ application:load(sasl),
+ {sasl,_,SaslVsn} = lists:keyfind(sasl,1,application:loaded_applications()),
+ Ebin = filename:join(code:lib_dir(sasl),ebin),
+ {ok,[{SaslVsn,UpFrom,DownTo}=Appup]} =
+ file:consult(filename:join(Ebin,"sasl.appup")),
+ ct:log("~p~n",[Appup]),
+ {OkVsns,NokVsns} = create_test_vsns(SaslVsn),
+ check_appup(OkVsns,UpFrom,{ok,[restart_new_emulator]}),
+ check_appup(OkVsns,DownTo,{ok,[restart_new_emulator]}),
+ check_appup(NokVsns,UpFrom,error),
+ check_appup(NokVsns,DownTo,error),
+ ok.
+
+
+%% For sasl, the versions up to R14B03 were not according to the rule
+%% used for other core applications - i.e. to change the second number
+%% at major releases, the third at maintenance releases and the fourth
+%% for patches - therefore test versions up to and including R16 are
+%% hardcoded.
+%% (All versions below are not necessarily existing.)
+-define(r12_vsns,["2.1.5"]).
+-define(r13_vsns,["2.1.6","2.1.7.1","2.1.9","2.1.9.1.2"]).
+-define(r14_vsns,["2.1.9.2","2.1.9.2.20","2.1.9.4","2.1.10"]).
+-define(r15_major,"2.2").
+-define(r16_major,"2.3").
+-define(r17_major,"2.4").
+create_test_vsns(?r15_major ++ Rest) ->
+ R15Vsns =
+ case string:tokens(Rest,".") of
+ [] -> [];
+ ["1"] -> [?r15_major];
+ _ -> [?r15_major,?r15_major++".1"]
+ end,
+ OkVsns = ?r13_vsns ++ ?r14_vsns ++ R15Vsns,
+ NokVsns = ?r12_vsns ++ [?r15_major++",1", ?r16_major],
+ {OkVsns,NokVsns};
+create_test_vsns(?r16_major ++ Rest) ->
+ R16Vsns =
+ case string:tokens(Rest,".") of
+ [] -> [];
+ ["1"] -> [?r16_major];
+ _ -> [?r16_major,?r16_major++".1"]
+ end,
+ OkVsns = ?r14_vsns ++ [?r15_major, ?r15_major ++ ".1.4"] ++ R16Vsns,
+ NokVsns = ?r13_vsns ++ [?r16_major++",1", ?r17_major],
+ {OkVsns,NokVsns};
+%% Normal erts case - i.e. for versions that comply to the erts standard
+create_test_vsns(Current) ->
+ [XStr,YStr|Rest] = string:tokens(Current,"."),
+ X = list_to_integer(XStr),
+ Y = list_to_integer(YStr),
+ SecondMajor = vsn(X,Y-2),
+ SecondMinor = SecondMajor ++ ".1.3",
+ FirstMajor = vsn(X,Y-1),
+ FirstMinor = FirstMajor ++ ".57",
+ ThisMajor = vsn(X,Y),
+ This =
+ case Rest of
+ [] ->
+ [];
+ ["1"] ->
+ [ThisMajor];
+ _ ->
+ ThisMinor = ThisMajor ++ ".1",
+ [ThisMajor,ThisMinor]
+ end,
+ OkVsns = This ++ [FirstMajor, FirstMinor, SecondMajor, SecondMinor],
+
+ ThirdMajor = vsn(X,Y-3),
+ ThirdMinor = ThirdMajor ++ ".10.12",
+ Illegal = ThisMajor ++ ",1",
+ Newer1Major = vsn(X,Y+1),
+ Newer1Minor = Newer1Major ++ ".1",
+ Newer2Major = ThisMajor ++ "1",
+ NokVsns = [ThirdMajor,ThirdMinor,
+ Illegal,
+ Newer1Major,Newer1Minor,
+ Newer2Major],
+ {OkVsns,NokVsns}.
+
+vsn(X,Y) ->
+ integer_to_list(X) ++ "." ++ integer_to_list(Y).
+
+check_appup([Vsn|Vsns],Instrs,Expected) ->
+ case systools_relup:appup_search_for_version(Vsn, Instrs) of
+ Expected -> check_appup(Vsns,Instrs,Expected);
+ Other -> ct:fail({unexpected_result_for_vsn,Vsn,Other})
+ end;
+check_appup([],_,_) ->
+ ok.
+
+
+
%% OTP-9185 - fail sasl start if some but not all log_mf_h env vars
%% are given.
log_mf_h_env(Config) ->
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index e352247d44..878d582e6b 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2012. All Rights Reserved.
%%
%% The 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,9 @@
-module(systools_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
-define(datadir, ?config(data_dir, Config)).
-define(privdir, ?config(priv_dir, Config)).
@@ -40,19 +40,22 @@
-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([script_options/1, normal_script/1, no_mod_vsn_script/1,
+ wildcard_script/1, variable_script/1, no_sasl_script/1,
+ abnormal_script/1, src_tests_script/1, crazy_script/1,
+ included_script/1, included_override_script/1,
+ included_fail_script/1, included_bug_script/1, exref_script/1,
+ otp_3065_circular_dependenies/1, included_and_used_sort_script/1]).
+-export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, system_files_tar/1,
+ system_files_tar/2, invalid_system_files_tar/1,
+ invalid_system_files_tar/2, variable_tar/1,
+ src_tests_tar/1, var_tar/1, exref_tar/1, link_tar/1,
+ otp_9507_path_ebin/1]).
+-export([normal_relup/1, restart_relup/1, abnormal_relup/1, no_sasl_relup/1,
+ no_appup_relup/1, bad_appup_relup/1, app_start_type_relup/1,
+ regexp_relup/1]).
+-export([normal_hybrid/1,hybrid_no_old_sasl/1,hybrid_no_new_sasl/1]).
+-export([otp_6226_outdir/1]).
-export([init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
@@ -67,25 +70,27 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
- [{group, script}, {group, tar}, {group, relup},
- {group, tickets}].
+ [{group, script}, {group, tar}, {group, relup}, {group, hybrid},
+ {group, options}].
groups() ->
[{script, [],
[script_options, normal_script, no_mod_vsn_script,
wildcard_script, variable_script, abnormal_script,
- src_tests_script, crazy_script, warn_shadow_script,
+ no_sasl_script, src_tests_script, crazy_script,
included_script, included_override_script,
included_fail_script, included_bug_script, exref_script,
- otp_3065]},
+ otp_3065_circular_dependenies, included_and_used_sort_script]},
{tar, [],
- [tar_options, normal_tar, no_mod_vsn_tar, variable_tar,
- src_tests_tar, shadow_tar, var_tar,
- exref_tar, link_tar, otp_9507]},
+ [tar_options, normal_tar, no_mod_vsn_tar, system_files_tar,
+ invalid_system_files_tar, variable_tar,
+ src_tests_tar, var_tar, exref_tar, link_tar, otp_9507_path_ebin]},
{relup, [],
- [normal_relup, abnormal_relup, no_appup_relup,
- bad_appup_relup, app_start_type_relup]},
- {tickets, [], [otp_6226]}].
+ [normal_relup, restart_relup, abnormal_relup, no_sasl_relup,
+ no_appup_relup, bad_appup_relup, app_start_type_relup, regexp_relup
+ ]},
+ {hybrid, [], [normal_hybrid,hybrid_no_old_sasl,hybrid_no_new_sasl]},
+ {options, [], [otp_6226_outdir]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -100,17 +105,17 @@ 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),
+ CopyDir = fname(PrivDir, "datacopy"),
+ TarFile = fname(PrivDir, "datacopy.tgz"),
+ {ok, Tar} = erl_tar:open(TarFile, [write, compressed]),
+ ok = erl_tar:add(Tar, DataDir, CopyDir, [compressed]),
+ ok = erl_tar:close(Tar),
+ ok = erl_tar:extract(TarFile, [compressed]),
+ 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),
+ Sources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*.erl'])),
+ lists:foreach(fun compile_source/1, Sources),
%% To use in end_per_testcase
Path = code:get_path(),
@@ -141,10 +146,13 @@ init_per_testcase(link_tar, Config) ->
{win32, _} -> {skip, "Skip on windows"}
end;
init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(?default_timeout),
+ Dog = test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
Dog=?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
case {?config(path,Config),?config(cwd,Config)} of
@@ -172,502 +180,502 @@ end_per_testcase(_Case, Config) ->
%%
-%% make_script
-%%
-script_options(suite) -> [];
-script_options(doc) ->
- ["Check illegal script options."];
+%% make_script: 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]}, _}} =
+ {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
+ (catch systools:make_script("release", [{path,["Path",12,"Another"]}])),
+ {'EXIT',{{badarg,[sillent]}, _}} =
(catch systools:make_script("release",
[{path,["Path","Another"]},sillent])),
- ?line {'EXIT',{{badarg,[locall]}, _}} =
+ {'EXIT',{{badarg,[locall]}, _}} =
(catch systools:make_script("release",
[{path,["Path","Another"]},locall])),
- ?line {'EXIT',{{badarg,[src_testsxx]}, _}} =
+ {'EXIT',{{badarg,[src_testsxx]}, _}} =
(catch systools:make_script("release",
[{path,["Path"]},src_testsxx])),
- ?line {'EXIT',{{badarg,[{variables, {"TEST", "/home/lib"}}]}, _}} =
+ {'EXIT',{{badarg,[{variables, {"TEST", "/home/lib"}}]}, _}} =
(catch systools:make_script("release",
[{variables, {"TEST", "/home/lib"}}])),
- ?line {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
+ {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
(catch systools:make_script("release",
[{variables, [{a, b}, {"a", "b"}]}])),
- ?line {'EXIT',{{badarg,[exreff]}, _}} =
+ {'EXIT',{{badarg,[exreff]}, _}} =
(catch systools:make_script("release",
[{path,["Path","Another"]},exreff])),
- ?line {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
+ {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
(catch systools:make_script("release", [{exref,["appl"]}])),
- ?line {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
+ {'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."];
+%% make_script: Check that normal case
normal_script(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line PSAVE = code:get_path(), % Save path
+ {ok, OldDir} = file:get_cwd(),
+ PSAVE = code:get_path(), % Save path
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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]),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P1 = fname([LibDir, 'db-2.1', ebin]),
+ P2 = fname([LibDir, 'fe-3.1', ebin]),
- ?line true = code:add_patha(P1),
- ?line true = code:add_patha(P2),
+ true = code:add_patha(P1),
+ true = code:add_patha(P2),
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line ok = systools:make_script(filename:basename(LatestName)),
- ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+ ok = systools:make_script(filename:basename(LatestName)),
+ {ok, _} = read_script_file(LatestName), % Check readabillity
%% Check the same but w. silent flag
- ?line {ok, _, []} = systools:make_script(LatestName, [silent]),
+ {ok, _, []} = systools:make_script(LatestName, [silent]),
%% Use the local option
- ?line ok = systools:make_script(LatestName, [local]),
- ?line ok = check_script_path(LatestName),
+ ok = systools:make_script(LatestName, [local]),
+ ok = check_script_path(LatestName),
%% use the path option
- ?line code:set_path(PSAVE), % Restore path
+ 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])),
+ true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
+ 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]}]),
+ error = systools:make_script(LatestName), %should fail
+ ok = systools:make_script(LatestName,[{path, [P1, P2]}]),
- ?line ok = file:set_cwd(OldDir),
- ?line code:set_path(PSAVE), % Restore path
+ ok = file:set_cwd(OldDir),
+ 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."];
+%% make_script:
+%% 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
+ {ok, OldDir} = file:get_cwd(),
+ PSAVE = code:get_path(), % Save path
- ?line {LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
+ {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]),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P1 = fname([LibDir, 'db-3.1', ebin]),
+ P2 = fname([LibDir, 'fe-3.1', ebin]),
- ?line true = code:add_patha(P1),
- ?line true = code:add_patha(P2),
+ true = code:add_patha(P1),
+ true = code:add_patha(P2),
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line ok = systools:make_script(filename:basename(LatestName)),
- ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+ ok = systools:make_script(filename:basename(LatestName)),
+ {ok, _} = read_script_file(LatestName), % Check readabillity
%% Check the same but w. silent flag
- ?line {ok, _, []} = systools:make_script(LatestName, [silent]),
+ {ok, _, []} = systools:make_script(LatestName, [silent]),
%% Use the local option
- ?line ok = systools:make_script(LatestName, [local]),
- ?line ok = check_script_path(LatestName),
+ ok = systools:make_script(LatestName, [local]),
+ ok = check_script_path(LatestName),
%% use the path option
- ?line code:set_path(PSAVE), % Restore path
+ 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])),
+ true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
+ 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]}]),
+ error = systools:make_script(LatestName), %should fail
+ ok = systools:make_script(LatestName,
+ [{path, [P1, P2]}]),
- ?line ok = file:set_cwd(OldDir),
- ?line code:set_path(PSAVE), % Restore path
+ ok = file:set_cwd(OldDir),
+ code:set_path(PSAVE), % Restore path
ok.
-%% make_script
-%%
-wildcard_script(suite) -> [];
-wildcard_script(doc) ->
- ["Check that make_script handles wildcards in path."];
+%% make_script: Check that make_script handles wildcards in path.
wildcard_script(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {LatestDir, LatestName} = create_script(latest,Config),
- ?line DataDir = filename:absname(?copydir),
- ?line LibDir = fname([DataDir, d_normal, lib]),
- ?line WildDir = fname([LibDir, '*', ebin]),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ WildDir = fname([LibDir, '*', ebin]),
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line error = systools:make_script(filename:basename(LatestName)),
+ error = systools:make_script(filename:basename(LatestName)),
- ?line ok = systools:make_script(LatestName,
- [{path, [WildDir]}]),
+ ok = systools:make_script(LatestName,
+ [{path, [WildDir]}]),
- ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+ {ok, _} = read_script_file(LatestName), % Check readabillity
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
-%% make_script
-%%
-variable_script(suite) -> [];
-variable_script(doc) ->
- ["Add own installation dependent variable in script."];
+%% make_script: Add own installation dependent variable in script.
variable_script(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line ok = systools:make_script(LatestName,
- [{path, P},
- {variables, [{"TEST", LibDir}]}]),
+ 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),
+ 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 = file:set_cwd(OldDir),
ok.
-%% make_script
-%%
-abnormal_script(suite) -> [];
-abnormal_script(doc) ->
- ["Abnormal cases."];
+%% make_script: Abnormal cases.
abnormal_script(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {LatestDir, LatestName} = create_script(latest,Config),
- ?line DataDir = filename:absname(?copydir),
+ 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])],
+ ok = file:set_cwd(LatestDir),
+ LibDir = fname([DataDir, d_bad_app_vsn, lib]),
+ 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"}}}}}]} =
+ error = systools:make_script(LatestName, [{path, P}]),
+ {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 = 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."];
+%% make_script: Create script without sasl appl. Check warning.
+no_sasl_script(Config) when is_list(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest1_no_sasl,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ {ok, _ , [{warning,missing_sasl}]} =
+ systools:make_script(LatestName,[{path, P},silent]),
+
+ {ok, _ , []} =
+ systools:make_script(LatestName,[{path, P},silent, no_warn_sasl]),
+
+ ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_script: 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
+ {ok, OldDir} = file:get_cwd(),
+ PSAVE = code:get_path(), % Save path
- ?line {LatestDir, LatestName} = create_script(latest,Config),
- ?line BootFile = LatestName ++ ".boot",
+ {LatestDir, LatestName} = create_script(latest,Config),
+ 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]),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_missing_src, lib]),
+ P1 = fname([LibDir, 'db-2.1', ebin]),
+ P2 = fname([LibDir, 'fe-3.1', ebin]),
N = [P1, P2],
- ?line ok = file:set_cwd(LatestDir),
+ 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}}),
+ 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),
+ Erl2 = filename:join([P1,"..","src","db2.erl"]),
+ file:delete(Erl2),
%% Then make script
%% .boot file should not exist
- ?line ok = file:delete(BootFile),
- ?line false = filelib:is_regular(BootFile),
+ ok = file:delete(BootFile),
+ false = filelib:is_regular(BootFile),
%% With warnings_as_errors and src_tests option, an error should be issued
- ?line error =
+ error =
systools:make_script(LatestName, [silent, {path, N}, src_tests,
warnings_as_errors]),
- ?line error =
+ 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),
+ 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,_}}]} =
+ {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),
+ true = filelib:is_regular(BootFile),
%% Without the src_tests option, no warning should be issued
- ?line {ok, _, []} =
+ {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,_}}]} =
+ {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 = file:set_cwd(OldDir),
+ 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."];
+%% make_script: Do the crazy cases.
crazy_script(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest, Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
%% Run with bad path
- ?line error = systools:make_script(LatestName),
- ?line {error, _, [{error_reading, _}, {error_reading, _}]} =
+ error = systools:make_script(LatestName),
+ {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),
+ {LatestDir2, LatestName2} = create_script(latest_nokernel, Config),
+ ok = file:set_cwd(LatestDir2),
- ?line error = systools:make_script(LatestName2),
- ?line {error, _, {missing_mandatory_app,[kernel,stdlib]}} =
+ error = systools:make_script(LatestName2),
+ {error, _, {missing_mandatory_app,kernel}} =
systools:make_script(LatestName2, [silent,{path,P}]),
- ?line ok = file:set_cwd(OldDir),
+ %% Run with .rel file with non-permanent kernel
+ {LatestDir3, LatestName3} = create_script(latest_kernel_start_type, Config),
+ ok = file:set_cwd(LatestDir3),
+
+ error = systools:make_script(LatestName3),
+ {error, _, {mandatory_app,kernel,load}} =
+ systools:make_script(LatestName3, [silent,{path,P}]),
+
+ %% Run with .rel file with non-permanent stdlib
+ {LatestDir4, LatestName4} = create_script(latest_stdlib_start_type, Config),
+ ok = file:set_cwd(LatestDir4),
+
+ error = systools:make_script(LatestName4),
+ {error, _, {mandatory_app,stdlib,load}} =
+ systools:make_script(LatestName4, [silent,{path,P}]),
+
+ %% Run with .rel file lacking stdlib
+ {LatestDir5, LatestName5} = create_script(latest_no_stdlib, Config),
+ ok = file:set_cwd(LatestDir5),
+
+ error = systools:make_script(LatestName5),
+ {error, _, {missing_mandatory_app,stdlib}} =
+ systools:make_script(LatestName5, [silent,{path,P}]),
+
+ 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."];
+%% make_script: 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, OldDir} = file:get_cwd(),
+ {LatestDir, LatestName} = create_include_files(inc1, Config),
+ ok = file:set_cwd(LatestDir),
+ ok = systools:make_script(LatestName),
+ ok = check_include_script(LatestName,
+ [t1, t2, t3, t5, t4, t6],
+ [t1, t3, t6]),
+ 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."];
+%% make_script: 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, OldDir} = file:get_cwd(),
+ {LatestDir, LatestName} = create_include_files(inc2, Config),
+ ok = file:set_cwd(LatestDir),
+ ok = systools:make_script(LatestName),
+ ok = check_include_script(LatestName,
+ [t1, t2, t3, t4, t6, t5],
+ [t1, t3, t6, t5]),
+
+ {_, LatestName1} = create_include_files(inc3, Config),
+ ok = systools:make_script(LatestName1),
+ ok = check_include_script(LatestName1,
+ [t3, t5, t4, t6, t1, t2],
+ [t3, t6, t1, t2]),
+
+ {_, LatestName2} = create_include_files(inc4, Config),
+ ok = systools:make_script(LatestName2),
+ ok = check_include_script(LatestName2,
+ [t3, t4, t6, t5, t1, t2],
+ [t3, t6, t5, t1, t2]),
+
+ {_, LatestName3} = create_include_files(inc5, Config),
+ ok = systools:make_script(LatestName3),
+ ok = check_include_script(LatestName3,
+ [t3, t4, t6, t1, t2],
+ [t3, t6, t1, t2]),
+
+ 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."];
+%% make_script: 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]}} =
+ {ok, OldDir} = file:get_cwd(),
+ {LatestDir, LatestName} = create_include_files(inc6, Config),
+ ok = file:set_cwd(LatestDir),
+ {error, _, {undefined_applications,[t2]}} =
systools:make_script(LatestName, [silent]),
- ?line {_, LatestName1} = create_include_files(inc7, Config),
- ?line {error, _, {duplicate_include,[{{t5,t7,_,_},{t5,t6,_,_}}]}} =
+ {_, LatestName1} = create_include_files(inc7, Config),
+ {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,_}]}} =
+ {_, LatestName3} = create_include_files(inc9, Config),
+ {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]}}}]} =
+ {_, LatestName4} = create_include_files(inc10, Config),
+ {error, _, [{error_reading,{t9,{override_include,[t7]}}}]} =
systools:make_script(LatestName4, [silent]),
- ?line ok = file:set_cwd(OldDir),
+ 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."];
+%% make_script: 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, OldDir} = file:get_cwd(),
+ {LatestDir, LatestName} = create_include_files(inc11, Config),
+ ok = file:set_cwd(LatestDir),
+ ok = systools:make_script(LatestName),
+ ok = check_include_script(LatestName,
+ [t13, t11, t12],
+ [t11, t12]),
+ 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),
+%% make_script: Circular dependencies in systools:make_script().
+otp_3065_circular_dependenies(Config) when is_list(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+ {LatestDir, LatestName} =
+ create_include_files(otp_3065_circular_dependenies, Config),
+ ok = file:set_cwd(LatestDir),
+ ok = systools:make_script(LatestName),
+ ok = check_include_script(LatestName,
+ [aa12, chAts, chTraffic],
+ [chTraffic]),
+ ok = file:set_cwd(OldDir),
ok.
+%% Test sorting of included applications and used applications
+included_and_used_sort_script(Config) when is_list(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+ {LatestDir1, LatestName1} = create_include_files(sort_apps, Config),
+ ok = file:set_cwd(LatestDir1),
+ ok = systools:make_script(LatestName1),
+ ok = check_include_script(LatestName1,
+ [t20,t19,t18,t17,t16,t15,t14],[t20,t19,t18,t14]),
+
+ {LatestDir2, LatestName2} = create_include_files(sort_apps_rev, Config),
+ ok = file:set_cwd(LatestDir2),
+ ok = systools:make_script(LatestName2),
+ ok = check_include_script(LatestName2,
+ [t18,t19,t20,t15,t16,t17,t14],[t18,t19,t20,t14]),
+
+ ok = file:set_cwd(OldDir),
+ ok.
-%% make_script
-%%
-exref_script(suite) -> [];
-exref_script(doc) ->
- ["Check that make_script exref option works."];
+
+%% make_script: 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
+ {ok, OldDir} = file:get_cwd(),
+ PSAVE = code:get_path(), % Save path
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line {ok, _, _} = systools:make_script(LatestName, [{path,P}, silent]),
+ {ok, _, _} = systools:make_script(LatestName, [{path,P}, silent]),
%% Complete exref
- ?line {ok, _, W1} =
+ {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
+ check_exref_warnings(with_db1, W1),
+ {ok, _} = read_script_file(LatestName), % Check readabillity
%% Only exref the db application.
- ?line {ok, _, W2} =
+ {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
+ check_exref_warnings(with_db1, W2),
+ {ok, _} = read_script_file(LatestName), % Check readabillity
%% Only exref the fe application.
- ?line {ok, _, W3} =
+ {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
+ check_exref_warnings(without_db1, W3),
+ {ok, _} = read_script_file(LatestName), % Check readabillity
%% exref the db and stdlib applications.
- ?line {ok, _, W4} =
+ {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
+ check_exref_warnings(with_db1, W4),
+ {ok, _} = read_script_file(LatestName), % Check readabillity
+ ok = file:set_cwd(OldDir),
+ code:set_path(PSAVE), % Restore path
ok.
check_exref_warnings(with_db1, W) ->
@@ -697,11 +705,11 @@ filter({ok, W}) ->
{ok, filter(W)};
filter(L) ->
lists:filter(fun%({hipe_consttab,_,_}) -> false;
- ({int,_,_}) -> false;
- ({i,_,_}) -> false;
- ({crypto,_,_}) -> false;
- (_) -> true
- end,
+ ({int,_,_}) -> false;
+ ({i,_,_}) -> false;
+ ({crypto,_,_}) -> false;
+ (_) -> true
+ end,
L).
get_exref1(T, [{warning, {T, Value}}|_]) -> {ok, Value};
@@ -721,197 +729,268 @@ no_hipe({ok, Value}) ->
{ok, Value}
end.
-%% tar_options
-%%
-tar_options(suite) -> [];
-tar_options(doc) ->
- ["Check illegal tar options."];
+%% tar_options: Check illegal tar options.
tar_options(Config) when is_list(Config) ->
- ?line {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
+ {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
(catch systools:make_tar("release", [{path,["Path",12,"Another"]}])),
- ?line {'EXIT',{{badarg,[sillent]}, _}} =
+ {'EXIT',{{badarg,[sillent]}, _}} =
(catch systools:make_tar("release",
[{path,["Path","Another"]},sillent])),
- ?line {'EXIT',{{badarg,[{dirs,["dirs"]}]}, _}} =
+ {'EXIT',{{badarg,[{dirs,["dirs"]}]}, _}} =
(catch systools:make_tar("release", [{dirs, ["dirs"]}])),
- ?line {'EXIT',{{badarg,[{erts, illegal}]}, _}} =
+ {'EXIT',{{badarg,[{erts, illegal}]}, _}} =
(catch systools:make_tar("release", [{erts, illegal}])),
- ?line {'EXIT',{{badarg,[src_testsxx]}, _}} =
+ {'EXIT',{{badarg,[src_testsxx]}, _}} =
(catch systools:make_tar("release",
[{path,["Path"]},src_testsxx])),
- ?line {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
+ {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
(catch systools:make_tar("release",
[{variables, [{a, b}, {"a", "b"}]}])),
- ?line {'EXIT',{{badarg,[{var_tar, illegal}]}, _}} =
+ {'EXIT',{{badarg,[{var_tar, illegal}]}, _}} =
(catch systools:make_tar("release", [{var_tar, illegal}])),
- ?line {'EXIT',{{badarg,[exreff]}, _}} =
+ {'EXIT',{{badarg,[exreff]}, _}} =
(catch systools:make_tar("release",
[{path,["Path","Another"]},exreff])),
- ?line {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
+ {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
(catch systools:make_tar("release", [{exref,["appl"]}])),
- ?line {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
+ {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
(catch systools:make_tar("release", [{machine,"appl"}])),
ok.
-%% normal_tar
-%%
-normal_tar(suite) -> [];
-normal_tar(doc) ->
- ["Check normal case"];
+%% make_tar: Check normal case
normal_tar(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ 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),
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ok = systools:make_tar(LatestName, [{path, P}]),
+ ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
+ {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
- ?line ok = file:set_cwd(OldDir),
+ 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."];
+%% make_tar: 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(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-3.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ 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),
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ok = systools:make_tar(LatestName, [{path, P}]),
+ ok = check_tar(fname([lib,'db-3.1',ebin,'db.app']), LatestName),
+ {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
-%% variable_tar
-%%
-variable_tar(suite) -> [];
-variable_tar(doc) ->
- ["Use variable and create separate tar (included in generated tar)."];
+
+%% make_tar: Check that relup or sys.config are included if they exist
+system_files_tar(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ %% Add dummy relup and sys.config
+ ok = file:write_file("sys.config","[].\n"),
+ ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
+
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ok = systools:make_tar(LatestName, [{path, P}]),
+ ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
+ ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
+ {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
+ ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
+
+ ok = file:set_cwd(OldDir),
+
+ ok.
+
+system_files_tar(cleanup,Config) ->
+ Dir = ?privdir,
+ file:delete(filename:join(Dir,"sys.config")),
+ file:delete(filename:join(Dir,"relup")),
+ ok.
+
+
+%% make_tar: Check that make_tar fails if relup or sys.config exist
+%% but do not have valid content
+invalid_system_files_tar(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+
+ %% Add dummy relup and sys.config - faulty sys.config
+ ok = file:write_file("sys.config","[]\n"), %!!! syntax error - missing '.'
+ ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"sys.config",[{error,_}]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ %% Add dummy relup and sys.config - faulty sys.config
+ ok = file:write_file("sys.config","[x,y].\n"), %!!! faulty format
+ ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"sys.config",[invalid_format]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ %% Add dummy relup and sys.config - faulty relup
+ ok = file:write_file("sys.config","[]\n"),
+ ok = file:write_file("relup","{\"LATEST\"\n"), %!!! syntax error - truncated
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"relup",[{error,_}]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ %% Add dummy relup and sys.config - faulty relup
+ ok = file:write_file("sys.config","[]\n"),
+ ok = file:write_file("relup","[].\n"), %!!! faulty format
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"relup",[invalid_format]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ ok = file:set_cwd(OldDir),
+
+ ok.
+
+invalid_system_files_tar(cleanup,Config) ->
+ Dir = ?privdir,
+ file:delete(filename:join(Dir,"sys.config")),
+ file:delete(filename:join(Dir,"relup")),
+ ok.
+
+
+%% make_tar: Use variable and create separate tar (included in generated tar).
variable_tar(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line {ok, _, _} = systools:make_script(LatestName,
- [silent,
- {path, P},
- {variables,[{"TEST", LibDir}]}]),
+ {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),
+ ok = systools:make_tar(LatestName, [{path, P},
+ {variables,[{"TEST", LibDir}]}]),
+ 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),
+ {ok, _, _} = systools:make_tar(LatestName,
+ [{path, P}, silent,
+ {variables,[{"TEST", LibDir}]}]),
+ ok = check_var_tar("TEST", LatestName),
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
-%% link_tar
-%%
-link_tar(suite) -> [];
-link_tar(doc) ->
- ["Check that symlinks in applications are handled correctly"];
+%% make_tar: Check that symlinks in applications are handled correctly.
link_tar(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_links, lib]),
+ 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),
-
+ Db1Erl = fname(['db-2.1',src,'db1.erl']),
+ NormalDb1Erl = fname([DataDir,d_normal,lib,Db1Erl]),
+ LinkDb1Erl = fname([LibDir, Db1Erl]),
+ ok = file:make_symlink(NormalDb1Erl, LinkDb1Erl),
+ Db1Beam = fname(['db-2.1',ebin,'db1.beam']),
+ NormalDb1Beam = fname([DataDir,d_normal,lib,Db1Beam]),
+ LinkDb1Beam = fname([LibDir, Db1Beam]),
+ ok = file:make_symlink(NormalDb1Beam, LinkDb1Beam),
+ FeApp = fname(['fe-3.1',ebin,'fe.app']),
+ NormalFeApp = fname([DataDir,d_normal,lib,FeApp]),
+ LinkFeApp = fname([LibDir, FeApp]),
+ 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 = file:set_cwd(LatestDir),
+
+ {ok,_,[]} = systools:make_script(LatestName, [{path, P},silent]),
+
+ {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ok = check_tar_regular(?privdir,
+ [fname([lib,FeApp]),
+ fname([lib,Db1Beam])],
+ LatestName),
+
+ {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]}]),
+ ok = check_tar_regular(?privdir,
+ [fname([lib,FeApp]),
+ fname([lib,Db1Beam]),
+ fname([lib,Db1Erl])],
+ LatestName),
+
+ 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."];
+%% make_tar: 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(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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]),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_missing_src, lib]),
+ P1 = fname([LibDir, 'db-2.1', ebin]),
+ P2 = fname([LibDir, 'fe-3.1', ebin]),
P = [P1, P2],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
%% Manipulate the modification date of a beam file so it seems
%% older than the .erl file
@@ -921,282 +1000,308 @@ src_tests_tar(Config) when is_list(Config) ->
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),
+ Erl2 = filename:join([P1,"..","src","db2.erl"]),
+ file:delete(Erl2),
- ?line ok = systools:make_script(LatestName, [{path, P}]),
+ 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,_}}]} =
+ {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),
+ 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),
+ {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]}]),
+ 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,_}}]} =
+ {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.
+ ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
-%% 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 = file:set_cwd(OldDir),
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."];
+%% make_tar: 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} optio.
var_tar(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line PSAVE = code:get_path(), % Save path
+ {ok, OldDir} = file:get_cwd(),
+ PSAVE = code:get_path(), % Save path
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line {ok, _, _} = systools:make_script(LatestName,
- [silent,
- {path, P},
- {variables,[{"TEST", LibDir}]}]),
+ {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}]}]),
+ 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),
+ true = exists_tar_file("TEST"), %% Also removes the file !
+ {error, {not_generated, _}} = check_var_tar("TEST", LatestName),
- ?line ok = systools:make_tar(LatestName, [{path, P},
- {var_tar, omit},
- {variables,[{"TEST", LibDir}]}]),
+ 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"),
+ {error, {not_generated, _}} = check_var_tar("TEST", LatestName),
+ false = exists_tar_file("TEST"),
- ?line ok = systools:make_tar(LatestName, [{path, P},
- {var_tar, include},
- {variables,[{"TEST", LibDir}]}]),
+ 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"),
+ ok = check_var_tar("TEST", LatestName),
+ false = exists_tar_file("TEST"),
- ?line ok = file:set_cwd(OldDir),
- ?line code:set_path(PSAVE),
+ ok = file:set_cwd(OldDir),
+ code:set_path(PSAVE),
ok.
-%% exref_tar
-%%
-exref_tar(suite) -> [];
-exref_tar(doc) ->
- ["Check exref option."];
+%% make_tar: Check exref option.
exref_tar(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest,Config),
+ {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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
- ?line {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
%% Complete exref
- ?line {ok, _, W1} =
+ {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),
+ check_exref_warnings(with_db1, W1),
+ ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
%% Only exref the db application.
- ?line {ok, _, W2} =
+ {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),
+ check_exref_warnings(with_db1, W2),
+ ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
%% Only exref the fe application.
- ?line {ok, _, W3} =
+ {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),
+ check_exref_warnings(without_db1, W3),
+ ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
%% exref the db and stdlib applications.
- ?line {ok, _, W4} =
+ {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),
+ check_exref_warnings(with_db1, W4),
+ ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
- ?line ok = file:set_cwd(OldDir),
+ 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(),
+%% make_tar: OTP-9507 - make_tar failed when path given as just 'ebin'.
+otp_9507_path_ebin(Config) when is_list(Config) ->
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName} = create_script(latest_small,Config),
+ {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']),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ FeDir = fname([LibDir, 'fe-3.1']),
- ?line ok = file:set_cwd(FeDir),
+ 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),
+ P1 = ["./ebin",
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+ {ok, _, _} = systools:make_script(RelName, [silent, {path, P1}]),
+ ok = systools:make_tar(RelName, [{path, P1}]),
+ Content1 = tar_contents(RelName),
- ?line P2 = ["ebin",
- fname([DataDir, lib, kernel, ebin]),
- fname([DataDir, lib, stdlib, ebin])],
+ P2 = ["ebin",
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, 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),
+ ok = systools:make_tar(RelName, [{path, P2}]),
+ Content2 = tar_contents(RelName),
true = (Content1 == Content2),
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
-%% The relup stuff.
-%%
-%%
-
-
-%% make_relup
-%%
-normal_relup(suite) -> [];
-normal_relup(doc) ->
- ["Check normal case"];
+%% make_relup: Check normal case
normal_relup(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {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),
+ {LatestDir,LatestName} = create_script(latest0,Config),
+ {_LatestDir1,LatestName1} = create_script(latest1,Config),
+ {_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])],
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, 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(),
+ ok = file:set_cwd(LatestDir),
%% 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, _, _, []} =
+ ok = systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P}]),
+ ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ {ok, _, _, []} =
systools:make_relup(LatestName, [LatestName1], [LatestName1],
[{path, P}, silent]),
- ?line ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ 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"),
+ ok = file:delete("relup"),
%% Check that warnings are treated as errors
- ?line error =
+ error =
systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}, warnings_as_errors]),
- ?line error =
+ error =
systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}, silent, warnings_as_errors]),
%% relup file should not exist
- ?line false = filelib:is_regular("relup"),
+ 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, _}]} =
+ ok = systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}]),
+ ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
+ {ok, _, _, [pre_R15_emulator_upgrade,{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"}]),
+ ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
%% relup file should exist now
- ?line true = filelib:is_regular("relup"),
+ true = filelib:is_regular("relup"),
+
+ ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_relup: Test relup which includes emulator restart.
+restart_relup(Config) when is_list(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir,LatestName} = create_script(latest0,Config),
+ {_LatestDir1,LatestName1} = create_script(latest1,Config),
+ {_LatestDir0CurrErts,LatestName0CurrErts} =
+ create_script(latest0_current_erts,Config),
+ {_CurrentAllDir,CurrentAllName} = create_script(current_all,Config),
+ {_CurrentAllFutErtsDir,CurrentAllFutErtsName} =
+ create_script(current_all_future_erts,Config),
+ {_CurrentAllFutSaslDir,CurrentAllFutSaslName} =
+ create_script(current_all_future_sasl,Config),
- ?line ok = file:set_cwd(OldDir),
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin]),
+ fname([DataDir, lib, 'sasl-9.9', ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ %% OTP-2561: Check that the option 'restart_emulator' generates a
+ %% "restart_emulator" instruction.
+ {ok, _ , _, []} =
+ systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P},restart_emulator,silent]),
+ ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ ok = check_restart_emulator(),
+
+
+ %% Pre-R15 to Post-R15 upgrade
+ {ok, _ , _, Ws} =
+ systools:make_relup(LatestName0CurrErts,
+ [LatestName1],
+ [LatestName1],
+ [{path, P},silent]),
+ ok = check_relup([{db,"2.1"}], [{db, "1.0"}]),
+ ok = check_pre_to_post_r15_restart_emulator(),
+ ok = check_pre_to_post_r15_warnings(Ws),
+
+
+ %% Check that new sasl version generates a restart_new_emulator
+ %% instruction
+ {ok, _ , _, []} =
+ systools:make_relup(CurrentAllFutSaslName,
+ [CurrentAllName],
+ [CurrentAllName],
+ [{path, P},silent]),
+ ok = check_relup([{fe, "3.1"}], []),
+ ok = check_restart_emulator_diff_coreapp(),
+
+
+ %% Check that new erts version generates a restart_new_emulator
+ %% instruction, if FromSaslVsn >= R15SaslVsn
+ %% (One erts_vsn_changed warning for upgrade and one for downgrade)
+ {ok, _ , _, [{erts_vsn_changed,_},{erts_vsn_changed,_}]} =
+ systools:make_relup(CurrentAllFutErtsName,
+ [CurrentAllName],
+ [CurrentAllName],
+ [{path, P},silent]),
+ ok = check_relup([{fe, "3.1"}], []),
+ ok = check_restart_emulator_diff_coreapp(),
+
+
+ %% Check that new erts version generates a restart_new_emulator
+ %% instruction, and can be combined with restart_emulator opt.
+ %% (One erts_vsn_changed warning for upgrade and one for downgrade)
+ {ok, _ , _, [{erts_vsn_changed,_},{erts_vsn_changed,_}]} =
+ systools:make_relup(CurrentAllFutErtsName,
+ [CurrentAllName],
+ [CurrentAllName],
+ [{path, P},restart_emulator,silent]),
+ ok = check_relup([{fe, "3.1"}], []),
+ ok = check_restart_emulator(),
+ ok = check_restart_emulator_diff_coreapp(),
+
+ ok = file:set_cwd(OldDir),
ok.
@@ -1216,295 +1321,558 @@ check_relup(UpVsnL, DnVsnL) ->
[{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Dn]),
ok.
+check_relup_up_only(UpVsnL) ->
+ {ok, [{_V1, [{_, _, Up}], []}]} = 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]),
+ ok.
+
check_restart_emulator() ->
{ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
+ restart_emulator = lists:last(Up),
+ restart_emulator = lists:last(Dn),
+ ok.
+
+check_restart_emulator_up_only() ->
+ {ok, [{_V1, [{_, _, Up}], []}]} = file:consult(relup),
+ restart_emulator = lists:last(Up),
+ ok.
+
+check_restart_emulator_diff_coreapp() ->
+ {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
+ [restart_new_emulator|_] = Up,
+ restart_emulator = lists:last(Dn),
+ ok.
+
+check_pre_to_post_r15_restart_emulator() ->
+ {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
restart_new_emulator = lists:last(Up),
- restart_new_emulator = lists:last(Dn),
+ restart_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."];
+check_pre_to_post_r15_warnings(Ws) ->
+ true = lists:member(pre_R15_emulator_upgrade,Ws),
+ ok.
+
+%% make_relup: 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(),
+ {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),
+ {LatestDir,LatestName} = create_script(latest_small,Config),
+ {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
+ {_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])],
+ DataDir = filename:absname(?copydir),
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
%% Check that appup might be missing
- ?line ok =
+ P1 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+ ok =
systools:make_relup(LatestName, [LatestName], [], [{path, P1}]),
- ?line {ok,_, _, []} =
+ {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,_,_}}}}} =
+ P2 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
+ fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+ error =
+ systools:make_relup(LatestName, [LatestName0], [], [{path, P2}]),
+ {error,_,{file_problem, {_,{error,{open,_,_}}}}} =
systools:make_relup(LatestName, [], [LatestName0],
- [silent, {path, P1}]),
+ [silent, {path, P2}]),
%% 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, _, _, _}} =
+ P3 = [fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
+ fname([DataDir, d_no_appup, lib, 'fe-500.18.7', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ error =
+ systools:make_relup(LatestName0, [LatestName1], [], [{path, P3}]),
+ {error,_,{no_relup, _, _, _}} =
systools:make_relup(LatestName0, [], [LatestName1],
- [silent, {path, P2}]),
+ [silent, {path, P3}]),
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
-%% make_relup
-%%
-bad_appup_relup(suite) -> [];
-bad_appup_relup(doc) ->
- ["Check that badly written appup files are detected"];
+%% make_relup: Check that badly written appup files are detected.
bad_appup_relup(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir,LatestName} = create_script(latest_small,Config),
- ?line {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
+ {LatestDir,LatestName} = create_script(latest_small,Config),
+ {_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])],
+ DataDir = filename:absname(?copydir),
+ N2 = [fname([DataDir, d_bad_appup, lib, 'fe-3.1', ebin]),
+ fname([DataDir, d_bad_appup, lib, 'fe-2.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
- ?line ok = file:set_cwd(LatestDir),
+ ok = file:set_cwd(LatestDir),
%% Check that bad appup is trapped
- ?line error =
+ error =
systools:make_relup(LatestName, [LatestName0], [], [{path, N2}]),
- ?line {error,_,{file_problem, {_, {error, {parse,_, _}}}}} =
+ {error,_,{file_problem, {_, {error, {parse,_, _}}}}} =
systools:make_relup(LatestName, [], [LatestName0],
[silent, {path, N2}]),
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
-%% make_relup
-%%
-abnormal_relup(suite) -> [];
-abnormal_relup(doc) ->
- ["Check some abnormal cases"];
+%% make_relup: Check some abnormal cases.
abnormal_relup(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir,LatestName} = create_script(latest0,Config),
- ?line {_LatestDir1,LatestName1} = create_script(latest1,Config),
+ {LatestDir,LatestName} = create_script(latest0,Config),
+ {_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),
+ DataDir = filename:absname(?copydir),
+ 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]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ error = systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P}]),
+ R0 = systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [silent, {path, P}]),
+ {error,systools_make,
+ [{error_reading,{db,{no_valid_version,
+ {{"should be","2.1"},
+ {"found file", _, "2.0"}}}}}]} = R0,
+ 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"];
+%% make_relup: Check relup can not be created is sasl is not in rel file.
+no_sasl_relup(Config) when is_list(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+ {Dir1,Name1} = create_script(latest1_no_sasl,Config),
+ {_Dir2,Name2} = create_script(latest1,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(Dir1),
+
+ error = systools:make_relup(Name2, [Name1], [Name1], [{path, P}]),
+ R1 = systools:make_relup(Name2, [Name1], [Name1],[silent, {path, P}]),
+ {error,systools_relup,{missing_sasl,_}} = R1,
+
+ error = systools:make_relup(Name1, [Name2], [Name2], [{path, P}]),
+ R2 = systools:make_relup(Name1, [Name2], [Name2],[silent, {path, P}]),
+ {error,systools_relup,{missing_sasl,_}} = R2,
+
+ ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_relup: Check that application start type is used in relup
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,
+ PrivDir = ?config(priv_dir, Config),
+ {Dir1,Name1} = create_script(latest_app_start_type1,Config),
+ {Dir2,Name2} = create_script(latest_app_start_type2,Config),
+ Release1 = filename:join(Dir1,Name1),
+ Release2 = filename:join(Dir2,Name2),
+
+ {ok, Release2Relup, systools_relup, []} = systools:make_relup(Release2, [Release1], [Release1], [{outdir, PrivDir}, silent]),
+ {"LATEST_APP_START_TYPE2",
+ [{"LATEST_APP_START_TYPE1",[], UpInstructions}],
+ [{"LATEST_APP_START_TYPE1",[], 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),
+ [{load_object_code, {mnesia, _, _}},
+ {load_object_code, {runtime_tools, _, _}},
+ {load_object_code, {webtool, _, _}},
+ {load_object_code, {snmp, _, _}},
+ {load_object_code, {xmerl, _, _}},
+ point_of_no_return
+ | UpInstructionsT] = UpInstructions,
+ true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT),
+ true = lists:member({apply,{application,start,[runtime_tools,transient]}}, UpInstructionsT),
+ true = lists:member({apply,{application,start,[webtool,temporary]}}, UpInstructionsT),
+ true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT),
+ false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT),
+ [point_of_no_return | DownInstructionsT] = DownInstructions,
+ true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT),
+ true = lists:member({apply,{application,stop,[runtime_tools]}}, DownInstructionsT),
+ true = lists:member({apply,{application,stop,[webtool]}}, DownInstructionsT),
+ true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT),
+ true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT),
+ true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT),
+ true = lists:member({apply,{application,unload,[runtime_tools]}}, DownInstructionsT),
+ true = lists:member({apply,{application,unload,[webtool]}}, DownInstructionsT),
+ true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT),
+ true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT),
+ ok.
+
+
+%% make_relup: Check that regexp can be used in .appup for UpFromVsn
+%% and DownToVsn.
+regexp_relup(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir,LatestName} = create_script(latest_small,Config),
+ {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
+ {_LatestDir1,LatestName1} = create_script(latest_small2,Config),
+
+ DataDir = filename:absname(?copydir),
+ P = [fname([DataDir, d_regexp_appup, lib, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ %% Upgrade fe 2.1 -> 3.1, and downgrade 2.1 -> 3.1
+ %% Shall match the first entry if fe-3.1 appup.
+ {ok, _, _, []} =
+ systools:make_relup(LatestName, [LatestName0], [LatestName0],
+ [{path, P}, silent]),
+ ok = check_relup([{fe, "3.1"}], [{fe, "2.1"}]),
+
+ %% Upgrade fe 2.1.1 -> 3.1
+ %% Shall match the second entry in fe-3.1 appup. Have added a
+ %% restart_emulator instruction there to distinguish it from
+ %% the first entry...
+ {ok, _, _, []} =
+ systools:make_relup(LatestName, [LatestName1], [], [{path, P}, silent]),
+ ok = check_relup_up_only([{fe, "3.1"}]),
+ ok = check_restart_emulator_up_only(),
+
+ %% Attempt downgrade fe 3.1 -> 2.1.1
+ %% Shall not match any entry!!
+ {error,systools_relup,{no_relup,_,_,_}} =
+ systools:make_relup(LatestName, [], [LatestName1], [{path, P}, silent]),
+
+ ok = file:set_cwd(OldDir),
+
+ ok.
+
+
+%% make_hybrid_boot: Normal case.
+%% For upgrade of erts - create a boot file which is a hybrid between
+%% old and new release - i.e. starts erts, kernel, stdlib, sasl from
+%% new release, all other apps from old release.
+normal_hybrid(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+ {Dir1,Name1} = create_script(latest1,Config),
+ {_Dir2,Name2} = create_script(current_all,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(Dir1),
+
+ {ok, _ , []} = systools:make_script(Name1,[{path, P},silent]),
+ {ok, _ , []} = systools:make_script(Name2,[{path, P},silent]),
+ {ok,Boot1} = file:read_file(Name1 ++ ".boot"),
+ {ok,Boot2} = file:read_file(Name2 ++ ".boot"),
+
+ ok = file:set_cwd(OldDir),
+
+ BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
+ {ok,Hybrid} = systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
+ BasePaths, [dummy,args]),
+
+ {script,{"Test release","tmp_vsn"},Script} = binary_to_term(Hybrid),
+ ct:log("~p.~n",[Script]),
+
+ %% Check that all paths to base apps are replaced by paths from BaseLib
+ Boot1Str = io_lib:format("~p~n",[binary_to_term(Boot1)]),
+ HybridStr = io_lib:format("~p~n",[binary_to_term(Hybrid)]),
+ ReOpts = [global,{capture,first,list},unicode],
+ {match,OldKernelMatch} = re:run(Boot1Str,"kernel-[0-9\.]+",ReOpts),
+ {match,OldStdlibMatch} = re:run(Boot1Str,"stdlib-[0-9\.]+",ReOpts),
+ {match,OldSaslMatch} = re:run(Boot1Str,"sasl-[0-9\.]+",ReOpts),
+
+ nomatch = re:run(HybridStr,"kernel-[0-9\.]+",ReOpts),
+ nomatch = re:run(HybridStr,"stdlib-[0-9\.]+",ReOpts),
+ nomatch = re:run(HybridStr,"sasl-[0-9\.]+",ReOpts),
+ {match,NewKernelMatch} = re:run(HybridStr,"testkernelpath",ReOpts),
+ {match,NewStdlibMatch} = re:run(HybridStr,"teststdlibpath",ReOpts),
+ {match,NewSaslMatch} = re:run(HybridStr,"testsaslpath",ReOpts),
+
+ NewKernelN = length(NewKernelMatch),
+ NewKernelN = length(OldKernelMatch),
+ NewStdlibN = length(NewStdlibMatch),
+ NewStdlibN = length(OldStdlibMatch),
+ NewSaslN = length(NewSaslMatch),
+ NewSaslN = length(OldSaslMatch),
+
+ %% Check that application load instruction has correct versions
+ Apps = application:loaded_applications(),
+ {_,_,KernelVsn} = lists:keyfind(kernel,1,Apps),
+ {_,_,StdlibVsn} = lists:keyfind(stdlib,1,Apps),
+ {_,_,SaslVsn} = lists:keyfind(sasl,1,Apps),
+
+ [KernelInfo] = [I || {kernelProcess,application_controller,
+ {application_controller,start,
+ [{application,kernel,I}]}} <- Script],
+ [StdlibInfo] = [I || {apply,
+ {application,load,
+ [{application,stdlib,I}]}} <- Script],
+ [SaslInfo] = [I || {apply,
+ {application,load,
+ [{application,sasl,I}]}} <- Script],
+
+ {vsn,KernelVsn} = lists:keyfind(vsn,1,KernelInfo),
+ {vsn,StdlibVsn} = lists:keyfind(vsn,1,StdlibInfo),
+ {vsn,SaslVsn} = lists:keyfind(vsn,1,SaslInfo),
+
+ %% Check that new_emulator_upgrade call is added
+ [_,{apply,{release_handler,new_emulator_upgrade,[dummy,args]}}|_] =
+ lists:reverse(Script),
+
+ %% Check that db-1.0 and fe-3.1 are used (i.e. vsns from old release)
+ %% And that fe is in there (it exists in old rel but not in new)
+ {match,DbMatch} = re:run(HybridStr,"db-[0-9\.]+",ReOpts),
+ {match,[_|_]=FeMatch} = re:run(HybridStr,"fe-[0-9\.]+",ReOpts),
+ true = lists:all(fun(["db-1.0"]) -> true;
+ (_) -> false
+ end,
+ DbMatch),
+ true = lists:all(fun(["fe-3.1"]) -> true;
+ (_) -> false
+ end,
+ FeMatch),
+
+ %% Check that script has same length as old script, plus one (the
+ %% new_emulator_upgrade apply)
+ {_,_,Old} = binary_to_term(Boot1),
+ OldLength = length(Old),
+ NewLength = length(Script),
+ NewLength = OldLength + 1,
+
+ ok.
+
+%% make_hybrid_boot: No sasl in from-release.
+%% Check that systools_make:make_hybrid_boot fails with a meaningful
+%% error message if the FromBoot does not include the sasl
+%% application.
+hybrid_no_old_sasl(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+ {Dir1,Name1} = create_script(latest1_no_sasl,Config),
+ {_Dir2,Name2} = create_script(current_all,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(Dir1),
+
+ {ok, _ , [{warning,missing_sasl}]} =
+ systools:make_script(Name1,[{path, P},silent]),
+ {ok, _ , []} = systools:make_script(Name2,[{path, P},silent]),
+ {ok,Boot1} = file:read_file(Name1 ++ ".boot"),
+ {ok,Boot2} = file:read_file(Name2 ++ ".boot"),
+
+ BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
+ {error,{app_not_replaced,sasl}} =
+ systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
+ BasePaths,[dummy,args]),
+
+ ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_hybrid_boot: No sasl in to-release.
+%% Check that systools_make:make_hybrid_boot fails with a meaningful
+%% error message if the ToBoot does not include the sasl
+%% application.
+hybrid_no_new_sasl(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+ {Dir1,Name1} = create_script(latest1,Config),
+ {_Dir2,Name2} = create_script(current_all_no_sasl,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = [fname([DataDir, d_normal, lib])],
+ P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin]),
+ fname([DataDir, lib, sasl, ebin])],
+
+ ok = file:set_cwd(Dir1),
+
+ {ok, _ , []} = systools:make_script(Name1,[{path, P},silent]),
+ {ok, _ , [{warning,missing_sasl}]} =
+ systools:make_script(Name2,[{path, P},silent]),
+ {ok,Boot1} = file:read_file(Name1 ++ ".boot"),
+ {ok,Boot2} = file:read_file(Name2 ++ ".boot"),
+
+ BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
+ {error,{app_not_found,sasl}} =
+ systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
+ BasePaths,[dummy,args]),
+
+ ok = file:set_cwd(OldDir),
ok.
-otp_6226(suite) ->
- [];
-otp_6226(doc) ->
- ["{outdir,Dir} option for systools:make_script()"];
-otp_6226(Config) when is_list(Config) ->
+
+%% options: {outdir,Dir} option
+otp_6226_outdir(Config) when is_list(Config) ->
PrivDir = ?privdir,
- ?line {ok, OldDir} = file:get_cwd(),
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest0,Config),
+ {_LatestDir, LatestName1} = create_script(latest1,Config),
- ?line {LatestDir, LatestName} = create_script(latest0,Config),
- ?line {_LatestDir, LatestName1} = create_script(latest1,Config),
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ 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]),
+ fname([DataDir, lib, sasl, ebin])],
- ?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])],
+ ok = file:set_cwd(LatestDir),
- ?line ok = file:set_cwd(LatestDir),
-
%% Create an outdir1 directory
- ?line ok = file:make_dir("outdir1"),
+ ok = file:make_dir("outdir1"),
%% ==== Now test systools:make_script ====
%% a) badarg
- ?line {'EXIT', {{badarg,[{outdir,outdir1}]}, _}} =
+ {'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),
+ {ok,_,[]} = systools:make_script(LatestName, [{outdir,Outdir1},
+ {path,P},silent]),
+ Script1 = filename:join(Outdir1, LatestName ++ ".script"),
+ Boot1 = filename:join(Outdir1, LatestName ++ ".boot"),
+ true = filelib:is_file(Script1),
+ true = filelib:is_file(Boot1),
+ ok = file:delete(Script1),
+ 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),
+ {ok,_,[]} = systools:make_script(LatestName, [{outdir,"./outdir1"},
+ {path,P},silent]),
+ true = filelib:is_file(Script1),
+ true = filelib:is_file(Boot1),
+ ok = file:delete(Script1),
+ 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,_}} =
+ Outdir2 = filename:join(PrivDir, "outdir2"),
+ Script2 = filename:join(Outdir2, LatestName ++ ".script"),
+ {error,_,{open,Script2,_}} =
systools:make_script(LatestName, [{outdir,Outdir2},{path,P},silent]),
%% e) relative but incorrect path
- ?line {error,_,{open,_,_}} =
+ {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),
+ ok = file:set_cwd(Outdir1),
+ {ok,_,[]} = systools:make_script(filename:join(PrivDir, LatestName),
+ [{outdir,"."},{path,P},silent]),
+ true = filelib:is_file(LatestName ++ ".script"),
+ true = filelib:is_file(LatestName ++ ".boot"),
+ ok = file:delete(LatestName ++ ".script"),
+ ok = file:delete(LatestName ++ ".boot"),
+ ok = file:set_cwd(LatestDir),
%% ==== Now test systools:make_tar =====
- ?line {ok,_,[]} = systools:make_script(LatestName, [{path,P},silent]),
+ {ok,_,[]} = systools:make_script(LatestName, [{path,P},silent]),
%% a) badarg
- ?line {'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
+ {'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),
+ {ok,_,[]} = systools:make_tar(LatestName, [{outdir,Outdir1},
+ {path,P},silent]),
+ Tar1 = filename:join(Outdir1,LatestName++".tar.gz"),
+ true = filelib:is_file(Tar1),
+ 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),
+ {ok,_,[]} = systools:make_tar(LatestName, [{outdir,"./outdir1"},
+ {path,P},silent]),
+ true = filelib:is_file(Tar1),
+ 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}}}} =
+ Tar2 = filename:join(Outdir2,LatestName++".tar.gz"),
+ {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]),
+ {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),
+ ok = file:set_cwd(Outdir1),
+ {ok,_,[]} = systools:make_tar(filename:join(PrivDir, LatestName),
+ [{outdir,"."},{path,P},silent]),
+ true = filelib:is_file(Tar1),
+ ok = file:set_cwd(LatestDir),
%% ===== Now test systools:make_relup =====
%% a) badarg
- ?line {'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
+ {'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),
-
+ {ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,Outdir1},
+ {path,P},silent]),
+ true = filelib:is_file(Relup),
+ 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),
-
+ {ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,"./outdir1"},
+ {path,P},silent]),
+ true = filelib:is_file(Relup),
+ ok = file:delete(Relup),
+
%% d) absolute but incorrect path
- ?line {error,_,{file_problem,{"relup",enoent}}} =
+ {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}}} =
+ {error,_,{file_problem,{"relup",enoent}}} =
systools:make_relup(LatestName,[LatestName1],[LatestName1],
[{outdir,"./outdir2"},{path,P},silent]),
@@ -1513,7 +1881,7 @@ otp_6226(Config) when is_list(Config) ->
%% cwd, not in the same directory as the .rel file --
%% Change back to previous working directory
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(OldDir),
ok.
@@ -1536,7 +1904,7 @@ check_var_script_file(VarDirs, NoExistDirs, RelName) ->
AllPaths = lists:append(lists:map(fun({path, P}) -> P;
(_) -> []
end,
- ListOfThings)),
+ ListOfThings)),
case lists:filter(fun(VarDir) -> lists:member(VarDir, AllPaths) end,
VarDirs) of
VarDirs ->
@@ -1561,7 +1929,7 @@ check_include_script(RelName, ExpectedLoad, ExpectedStart) ->
[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,
@@ -1636,7 +2004,7 @@ check_tar_regular(PrivDir, Files, RelName) ->
NotThere ->
{error,{erroneous_tar_file,tar_name(RelName),NotThere}}
end.
-
+
delete_tree(Dir) ->
case filelib:is_dir(Dir) of
true ->
@@ -1656,534 +2024,582 @@ 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)};
+ Apps = core_apps(current) ++ [{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest,Config,"4.4",Apps);
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)};
+ Apps = core_apps(current) ++ [{db,"3.1"},{fe,"3.1"}],
+ do_create_script(latest_no_mod_vsn,Config,"4.4",Apps);
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)};
+ Apps = core_apps("1.0") ++ [{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest0,Config,"4.4",Apps);
+create_script(latest0_current_erts,Config) ->
+ Apps = core_apps("1.0") ++ [{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest0_current_erts,Config,current,Apps);
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)};
+ Apps = core_apps("1.0") ++ [{db,"1.0"},{fe,"3.1"}],
+ do_create_script(latest1,Config,"4.4",Apps);
+create_script(latest1_no_sasl,Config) ->
+ Apps = [{kernel,"1.0"},{stdlib,"1.0"},{db,"1.0"},{fe,"3.1"}],
+ do_create_script(latest1_no_sasl,Config,"4.4",Apps);
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)};
+ Apps = core_apps("1.0") ++ [{db,"1.0"},{fe,"2.1"}],
+ do_create_script(latest2,Config,"4.3",Apps);
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)};
+ Apps = core_apps("1.0") ++ [{fe,"3.1"}],
+ do_create_script(latest_small,Config,"4.4",Apps);
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)};
+ Apps = core_apps("1.0") ++ [{fe,"2.1"}],
+ do_create_script(latest_small0,Config,"4.4",Apps);
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)};
+ Apps = core_apps("1.0") ++ [{fe,"500.18.7"}],
+ do_create_script(latest_small1,Config,"4.4",Apps);
+create_script(latest_small2,Config) ->
+ Apps = core_apps("1.0") ++ [{fe,"2.1.1"}],
+ do_create_script(latest_small2,Config,"4.4",Apps);
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)};
+ Apps = [{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest_nokernel,Config,"4.4",Apps);
+create_script(latest_kernel_start_type,Config) ->
+ Apps = [{kernel,"1.0",load},{stdlib,"1.0"},{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest_kernel_start_type,Config,"4.4",Apps);
+create_script(latest_stdlib_start_type,Config) ->
+ Apps = [{kernel,"1.0"},{stdlib,"1.0",load},{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest_stdlib_start_type,Config,"4.4",Apps);
+create_script(latest_no_stdlib,Config) ->
+ Apps = [{kernel,"1.0"},{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest_no_stdlib,Config,"4.4",Apps);
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)};
+ Apps = core_apps(current),
+ do_create_script(latest_app_start_type1,Config,current,Apps);
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),
+ OtherApps = [{mnesia,current,permanent},
+ {runtime_tools,current,transient},
+ {webtool,current,temporary},
+ {snmp,current,load},
+ {xmerl,current,none}],
+ Apps = core_apps(current) ++ OtherApps,
+ do_create_script(latest_app_start_type2,Config,current,Apps);
+create_script(current_all_no_sasl,Config) ->
+ Apps = [{kernel,current},{stdlib,current},{db,"2.1"},{fe,"3.1"}],
+ do_create_script(current_all_no_sasl,Config,current,Apps);
+create_script(current_all,Config) ->
+ Apps = core_apps(current) ++ [{db,"2.1"}],
+ do_create_script(current_all,Config,current,Apps);
+create_script(current_all_future_erts,Config) ->
+ Apps = core_apps(current) ++ [{db,"2.1"},{fe,"3.1"}],
+ do_create_script(current_all_future_erts,Config,"99.99",Apps);
+create_script(current_all_future_sasl,Config) ->
+ Apps = [{kernel,current},{stdlib,current},{sasl,"9.9"},{db,"2.1"},{fe,"3.1"}],
+ do_create_script(current_all_future_sasl,Config,current,Apps).
+
+
+do_create_script(Id,Config,ErtsVsn,AppVsns) ->
+ PrivDir = ?privdir,
+ Name = fname(PrivDir, Id),
+ {ok,Fd} = file:open(Name++".rel",write),
+ RelfileContent =
+ {release,{"Test release", string:to_upper(atom_to_list(Id))},
+ {erts,erts_vsn(ErtsVsn)},
+ app_vsns(AppVsns)},
+ io:format(Fd,"~p.~n",[RelfileContent]),
+ ok = file:close(Fd),
{filename:dirname(Name), filename:basename(Name)}.
+core_apps(Vsn) ->
+ [{App,Vsn} || App <- [kernel,stdlib,sasl]].
+
+app_vsns(AppVsns) ->
+ [{App,app_vsn(App,Vsn)} || {App,Vsn} <- AppVsns] ++
+ [{App,app_vsn(App,Vsn),Type} || {App,Vsn,Type} <- AppVsns].
+app_vsn(App,current) ->
+ application:load(App),
+ {ok,Vsn} = application:get_key(App,vsn),
+ Vsn;
+app_vsn(_App,Vsn) ->
+ Vsn.
+
+erts_vsn(current) -> erlang:system_info(version);
+erts_vsn(Vsn) -> Vsn.
+
+
create_include_files(inc1, Config) ->
- ?line PrivDir = ?privdir,
- ?line Name = fname(PrivDir, inc1),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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),
+ PrivDir = ?privdir,
+ 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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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_include_files(otp_3065_circular_dependenies, Config) ->
+ PrivDir = ?privdir,
+ Name = fname(PrivDir, otp_3065_circular_dependenies),
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),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {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",
+ " [{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_include_files(sort_apps, Config) ->
+ PrivDir = ?privdir,
+ Name = fname(PrivDir, sort_apps),
+ create_sort_apps(PrivDir),
+
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t14, \"1.0\"}, \n"
+ " {t20, \"1.0\"}, \n"
+ " {t19, \"1.0\"}, \n"
+ " {t18, \"1.0\"}, \n"
+ " {t17, \"1.0\"}, \n"
+ " {t16, \"1.0\"}, \n"
+ " {t15, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(sort_apps_rev, Config) ->
+ PrivDir = ?privdir,
+ Name = fname(PrivDir, sort_apps_rev),
+ create_sort_apps(PrivDir),
+
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t14, \"1.0\"}, \n"
+ " {t18, \"1.0\"}, \n"
+ " {t19, \"1.0\"}, \n"
+ " {t20, \"1.0\"}, \n"
+ " {t15, \"1.0\"}, \n"
+ " {t16, \"1.0\"}, \n"
+ " {t17, \"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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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",
+ " [{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)).
+create_sort_apps(Dir) ->
+ T14 = "{application, t14,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t18,t20,t19]},\n"
+ " {included_applications, [t15,t17,t16]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't14.app'), list_to_binary(T14)),
+
+ T15 = "{application, t15,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't15.app'), list_to_binary(T15)),
+
+ T16 = "{application, t16,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't16.app'), list_to_binary(T16)),
+
+ T17 = "{application, t17,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't17.app'), list_to_binary(T17)),
+
+ T18 = "{application, t18,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't18.app'), list_to_binary(T18)),
+
+ T19 = "{application, t19,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't19.app'), list_to_binary(T19)),
+
+ T20 = "{application, t20,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't20.app'), list_to_binary(T20)).
+
fname(N) ->
filename:join(N).
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-2.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-2.1/ebin/fe.app
new file mode 100644
index 0000000000..3cb0b0c2cf
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-2.1/ebin/fe.app
@@ -0,0 +1,7 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "2.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_no_appup/lib/fe-500.18.7/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-500.18.7/ebin/fe.app
new file mode 100644
index 0000000000..3a5c0ddd9b
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-500.18.7/ebin/fe.app
@@ -0,0 +1,7 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "500.18.7"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {mod, {fe1, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-2.1.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_regexp_appup/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_regexp_appup/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_regexp_appup/lib/fe-2.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_regexp_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_regexp_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_regexp_appup/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_regexp_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_regexp_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_regexp_appup/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..6b99c47e53
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_regexp_appup/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,28 @@
+%% -*- erlang -*-
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+ %% Upgrade from:
+ [
+ {<<"2\\.[0-9]+">>, % matches 2.X in full length and 2.X.Y... only partly
+ [{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(\\.[0-9]+)+">>, % matches 2.X.Y... in full length
+ [{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]},
+ restart_emulator]}
+ ],
+
+ %% Downgrade to:
+ [
+ {<<"2\\.[0-9]+">>, % matches 2.X in full length and 2.X.Y... only partly
+ [{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/lib/sasl-9.9/ebin/sasl.app b/lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.app
new file mode 100644
index 0000000000..3bcc1a4619
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.app
@@ -0,0 +1,6 @@
+{application, sasl,
+ [{description, "FAKE FUTURE SASL"},
+ {vsn, "9.9"},
+ {modules, []},
+ {registered, []},
+ {applications, []}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.appup b/lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.appup
new file mode 100644
index 0000000000..cff0c69b6e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/sasl-9.9/ebin/sasl.appup
@@ -0,0 +1,12 @@
+%%
+%% Fake release upgrade script for sasl
+%%
+
+{
+ "9.9",
+ [{<<".+">>,[restart_new_emulator]}
+ ],
+
+ [{<<".+">>,[restart_new_emulator]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.app b/lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.app
new file mode 100644
index 0000000000..aaeb37fa4d
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.app
@@ -0,0 +1,6 @@
+{application, sasl,
+ [{description, "FAKE SASL"},
+ {vsn, "1.0"},
+ {modules, []},
+ {registered, []},
+ {applications, []}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.appup b/lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.appup
new file mode 100644
index 0000000000..796a1e7368
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/sasl/ebin/sasl.appup
@@ -0,0 +1,12 @@
+%%
+%% Fake release upgrade script for sasl
+%%
+
+{
+ "1.0",
+ [
+ ],
+
+ [
+ ]
+}.
diff --git a/lib/sasl/test/systools_rc_SUITE.erl b/lib/sasl/test/systools_rc_SUITE.erl
index bb93f38fa7..bd4aa9e7a7 100644
--- a/lib/sasl/test/systools_rc_SUITE.erl
+++ b/lib/sasl/test/systools_rc_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
@@ -18,17 +18,18 @@
%%
-module(systools_rc_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.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]).
+ syntax_check/1, translate/1, translate_app/1,
+ translate_emulator_restarts/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].
+ [syntax_check, translate, translate_app, translate_emulator_restarts].
groups() ->
[].
@@ -40,7 +41,6 @@ end_per_group(_GroupName, Config) ->
Config.
-syntax_check(suite) -> [];
syntax_check(Config) when is_list(Config) ->
PreApps =
[#application{name = test,
@@ -68,8 +68,8 @@ syntax_check(Config) when is_list(Config) ->
{update, baz, 5000, soft, brutal_purge, brutal_purge, []},
{add_module, new_mod},
{remove_application, snmp}
- ],
- ?line {ok, _} = systools_rc:translate_scripts([S1], Apps, PreApps),
+ ],
+ {ok, _} = systools_rc:translate_scripts([S1], Apps, PreApps),
S2 = [
{apply, {m, f, [a]}},
{load_object_code, {tst, "1.0", [new_mod]}},
@@ -87,42 +87,42 @@ syntax_check(Config) when is_list(Config) ->
{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, []),
+ restart_new_emulator,
+ restart_emulator
+ ],
+ {ok, _} = systools_rc:translate_scripts([S2], Apps, []),
S3 = [{apply, {m, f, a}}],
- ?line {error, _, _} = systools_rc:translate_scripts([S3], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S3], Apps, []),
S3_1 = [{apply, {m, 3, a}}],
- ?line {error, _, _} = systools_rc:translate_scripts([S3_1], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S3_1], Apps, []),
S4 = [{apply, {m, f}}],
- ?line {error, _, _} = systools_rc:translate_scripts([S4], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S4], Apps, []),
S5 = [{load_object_code, hej}],
- ?line {error, _, _} = systools_rc:translate_scripts([S5], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S5], Apps, []),
S6 = [{load_object_code, {342, "1.0", [foo]}}],
- ?line {error, _, _} = systools_rc:translate_scripts([S6], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S6], Apps, []),
S7 = [{load_object_code, {tets, "1.0", foo}}],
- ?line {error, _, _} = systools_rc:translate_scripts([S7], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S7], Apps, []),
S8 = [{suspend, [m1]}, point_of_no_return],
- ?line {error, _, _} = systools_rc:translate_scripts([S8], Apps, []),
+ {error, _, _} = systools_rc:translate_scripts([S8], Apps, []),
S9 = [{update, ba, {advanced, extra}, brutal_purge, brutal_purge, []}],
- ?line {error, _, _} = systools_rc:translate_scripts([S9], Apps, []),
+ {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, []),
+ {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, []),
+ {error, _, _} = systools_rc:translate_scripts([S11], Apps, []),
S12 = [{update, bar, advanced, brutal_purge, brutal_purge, []}],
- ?line {error, _, _} = systools_rc:translate_scripts([S12], Apps, []),
+ {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, []),
+ {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, []),
+ {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, []),
+ {error, _, _} = systools_rc:translate_scripts([S15], Apps, []),
S16 = [{code_change, [module]}],
- ?line {error, _, _} = systools_rc:translate_scripts([S16], Apps, []),
- ?line ok.
+ {error, _, _} = systools_rc:translate_scripts([S16], Apps, []),
+ ok.
-translate(suite) -> [];
translate(Config) when is_list(Config) ->
Apps =
[#application{name = test,
@@ -134,170 +134,170 @@ translate(Config) when is_list(Config) ->
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,
+ {ok, X1} = systools_rc:translate_scripts([Up1], Apps, []),
+ [{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,
+ {ok, X2} = systools_rc:translate_scripts([Up2], Apps, []),
+ [{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,
+
+ {ok, X22} = systools_rc:translate_scripts(dn,[Up2], Apps, []),
+ [{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,
+ {ok, X2a} = systools_rc:translate_scripts([Up2a], Apps, []),
+ [{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,
+
+ {ok, X22a} = systools_rc:translate_scripts(dn,[Up2a], Apps, []),
+ [{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,
+ {ok, X31} = systools_rc:translate_scripts([Up3], Apps, []),
+ [{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,
+ {ok, X32} = systools_rc:translate_scripts(dn,[Up3], Apps, []),
+ [{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,
+ {ok, X3a1} = systools_rc:translate_scripts([Up3a], Apps, []),
+ [{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,
+ {ok, X3a2} = systools_rc:translate_scripts(dn,[Up3a], Apps, []),
+ [{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,
+ {ok, X4} = systools_rc:translate_scripts(up,[Up4], Apps, []),
+ [{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,
+
+ {ok, X42} = systools_rc:translate_scripts(dn,[Up4], Apps, []),
+ [{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,
+ {ok, X4a} = systools_rc:translate_scripts(up,[Up4a], Apps, []),
+ [{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,
+
+ {ok, X42a} = systools_rc:translate_scripts(dn,[Up4a], Apps, []),
+ [{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,
+ {ok, X4b} = systools_rc:translate_scripts(up,[Up4b], Apps, []),
+ [{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,
+
+ {ok, X42b} = systools_rc:translate_scripts(dn,[Up4b], Apps, []),
+ [{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,
+ {ok, X5} = systools_rc:translate_scripts([Up5], Apps, []),
+ [{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,
+
+ {ok, X52} = systools_rc:translate_scripts(dn,[Up5], Apps, []),
+ [{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]},
@@ -305,26 +305,26 @@ translate(Config) when is_list(Config) ->
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,
+ {ok, X5a} = systools_rc:translate_scripts([Up5a], Apps, []),
+ [{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,
+
+ {ok, X52a} = systools_rc:translate_scripts(dn,[Up5a], Apps, []),
+ [{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]},
@@ -332,65 +332,65 @@ translate(Config) when is_list(Config) ->
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,
+ {ok, X5b} = systools_rc:translate_scripts([Up5b], Apps, []),
+ [{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,
+
+ {ok, X52b} = systools_rc:translate_scripts(dn,[Up5b], Apps, []),
+ [{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,
+ {ok, X61} = systools_rc:translate_scripts([Up6], Apps, []),
+ [{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,
+ {ok, X62} = systools_rc:translate_scripts(dn,[Up6], Apps, []),
+ [{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,
+ {ok, X71} = systools_rc:translate_scripts([Up7], Apps, []),
+ [{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,
+ {ok, X72} = systools_rc:translate_scripts(dn,[Up7], Apps, []),
+ [{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
%%
@@ -400,20 +400,20 @@ translate(Config) when is_list(Config) ->
{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,
+ {ok, X8} = systools_rc:translate_scripts([Up8], Apps, []),
+ {value, {suspend, Order}} = lists:keysearch(suspend, 1, X8),
+ Rest = case lists:reverse(Order) of
+ [bar, baz | R] -> R;
+ [baz, bar | R] -> R
+ end,
+ 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]},
@@ -428,13 +428,12 @@ translate(Config) when is_list(Config) ->
{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, []),
+ {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.
+ [1,2,3,4,5,6] = lists:sort(Other2),
+ ok.
-translate_app(suite) -> [];
translate_app(Config) when is_list(Config) ->
PreApps =
[#application{name = test,
@@ -459,30 +458,112 @@ translate_app(Config) when is_list(Config) ->
%% 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,
+ {ok, X1} = systools_rc:translate_scripts([Up1], Apps, []),
+ [{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,
+ {ok, X2} = systools_rc:translate_scripts([Up2], Apps, []),
+ io:format("X2=~p~n", [X2]),
+ [{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.
+ {ok, X3} = systools_rc:translate_scripts([Up3], Apps, PreApps),
+ [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,
+ ok.
+
+
+translate_emulator_restarts(_Config) ->
+ Apps =
+ [#application{name = test,
+ description = "TEST",
+ vsn = "1.0",
+ modules = [{foo,1},{bar,1},{baz,1}],
+ regs = [],
+ mod = {sasl, []}},
+ #application{name = test,
+ description = "TEST2",
+ vsn = "1.0",
+ modules = [{x,1},{y,1},{z,1}],
+ regs = [],
+ mod = {sasl, []}}],
+ %% restart_new_emulator
+ Up1 = [{update, foo, soft, soft_purge, soft_purge, []},restart_new_emulator],
+ {ok, X1} = systools_rc:translate_scripts([Up1], Apps, []),
+ [restart_new_emulator,
+ {load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[foo]}] = X1,
+
+ %% restart_emulator
+ Up2 = [{update, foo, soft, soft_purge, soft_purge, []},restart_emulator],
+ {ok, X2} = systools_rc:translate_scripts([Up2], Apps, []),
+ [{load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[foo]},
+ restart_emulator] = X2,
+
+ %% restart_emulator + restart_new_emulator
+ Up3 = [{update, foo, soft, soft_purge, soft_purge, []},
+ restart_emulator,
+ restart_new_emulator],
+ {ok, X3} = systools_rc:translate_scripts([Up3], Apps, []),
+ [restart_new_emulator,
+ {load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[foo]},
+ restart_emulator] = X3,
+
+ %% restart_emulator + restart_new_emulator
+ Up4a = [{update, foo, soft, soft_purge, soft_purge, []},
+ restart_emulator,
+ restart_new_emulator],
+ Up4b = [restart_new_emulator,
+ {update, x, soft, soft_purge, soft_purge, []},
+ restart_emulator,
+ restart_emulator],
+ {ok, X4} = systools_rc:translate_scripts([Up4a,Up4b], Apps, []),
+ [restart_new_emulator,
+ {load_object_code, {test,"1.0",[foo,x]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[foo]},
+ {suspend,[x]},
+ {load,{x,soft_purge,soft_purge}},
+ {resume,[x]},
+ restart_emulator] = X4,
+
+ %% only restart_new_emulator
+ Up5 = [restart_new_emulator],
+ {ok, X5} = systools_rc:translate_scripts([Up5], Apps, []),
+ [restart_new_emulator,
+ point_of_no_return] = X5,
+
+ %% only restart_emulator
+ Up6 = [restart_emulator],
+ {ok, X6} = systools_rc:translate_scripts([Up6], Apps, []),
+ [point_of_no_return,
+ restart_emulator] = X6,
+
+ ok.
diff --git a/lib/sasl/test/test_lib.hrl b/lib/sasl/test/test_lib.hrl
new file mode 100644
index 0000000000..eeef721647
--- /dev/null
+++ b/lib/sasl/test/test_lib.hrl
@@ -0,0 +1,3 @@
+-define(ertsvsn,"4.4").
+-define(kernelvsn,"2.14.3").
+-define(stdlibvsn,"1.17.3").
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 2db134af48..6e9e2c9ff8 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 2.1.10
+SASL_VSN = 2.2.1
diff --git a/lib/snmp/Makefile b/lib/snmp/Makefile
index 4264531112..ff6fad8ddc 100644
--- a/lib/snmp/Makefile
+++ b/lib/snmp/Makefile
@@ -54,6 +54,9 @@ else
endif
+DIA_PLT = ./priv/plt/$(APPLICATION).plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+
# ----------------------------------------------------
# Default Subdir Targets
# ----------------------------------------------------
@@ -75,6 +78,11 @@ info:
@echo ""
@echo "SNMP_VSN: $(SNMP_VSN)"
@echo "APP_VSN: $(APP_VSN)"
+ @echo ""
+ @echo "DIA_PLT: $(DIA_PLT)"
+ @echo "DIA_ANALYSIS: $(DIA_ANALYSIS)"
+ @echo ""
+
gclean:
git clean -fXd
@@ -120,3 +128,23 @@ tar: $(APP_TAR_FILE)
$(APP_TAR_FILE): $(APP_DIR)
(cd $(APP_RELEASE_DIR); gtar zcf $(APP_TAR_FILE) $(DIR_NAME))
+
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT):
+ @echo "Building $(APPLICATION) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ -r ../$(APPLICATION)/ebin \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on $(APPLICATION)"
+ @dialyzer --plt $< \
+ ../$(APPLICATION)/ebin \
+ --verbose \ No newline at end of file
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index aa9431477c..6c58ae994a 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -28,14 +28,6 @@ VSN = $(SNMP_VSN)
APPLICATION=snmp
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -88,40 +80,10 @@ MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
MAN7_FILES = $(MIB_FILES:$(MIBSDIR)/%.mib=$(MAN7DIR)/%.7)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = \
- $(XML_REF1_FILES:%.xml=%.tex) \
- $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_REF6_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_PART_FILES = $(XML_PART_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = snmp-$(VSN).pdf
-TOP_PS_FILE = snmp-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- @echo "building $(TOP_PDF_FILE)"
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- @echo "building $(TOP_PS_FILE)"
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-TOP_HTML_FILES = $(INDEX_TARGET)
-
-endif
-
INDEX_FILE = index.html
INDEX_SRC = $(INDEX_FILE).src
INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
@@ -141,8 +103,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif # Copy them to ../html
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
ldocs: local_docs $(INDEX_TARGET)
@@ -157,47 +117,6 @@ html2: html $(INDEX_TARGET)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) $(TOP_HTML_FILES) gifs
-
-html2: gifs $(TOP_HTML_FILES) $(HTML_FILES) $(HTML_REF1_FILES) $(HTML_REF3_FILES) $(HTML_REF6_FILES) $(HTML_CHAP_FILES)
-
-clean: clean_tex clean_html clean_man clean_docs
-
-
-clean_tex:
- @echo "cleaning tex:"
- rm -f $(TEX_FILES_USERS_GUIDE)
- rm -f $(TEX_FILES_REF_MAN)
- rm -f $(TEX_PART_FILES)
- rm -f $(TEX_FILES_BOOK)
-
-clean_docs:
- @echo "cleaning docs:"
- rm -f $(TOP_PDF_FILE)
- rm -f $(TOP_PS_FILE)
- rm -f core $(LATEX_CLEAN)
-
-
-$(HTML_PART_FILES): notes.xml
-
-endif
-
$(INDEX_TARGET): $(INDEX_SRC) ../../vsn.mk # Create top make file
sed -e 's;%VSN%;$(VSN);' $< > $@ # inserting version number
@@ -246,77 +165,33 @@ $(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
$(MAN1DIR)/snmpc.1: snmpc_cmd.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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1DIR)/* $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6DIR)/* $(RELEASE_PATH)/man/man6
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man7
- $(INSTALL_DATA) $(MAN7DIR)/* $(RELEASE_PATH)/man/man7
-
-else
-
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man7
- $(INSTALL_DATA) $(MAN7_FILES) $(RELEASE_PATH)/man/man7
- $(INSTALL_DATA) $(TOP_HTML_FILES) \
- $(RELSYSDIR)/doc
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DATA) $(MAN1DIR)/* "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man7"
+ $(INSTALL_DATA) $(MAN7DIR)/* "$(RELEASE_PATH)/man/man7"
release_spec:
-ifdef DOCSUPPORT
info: info_xml info_man info_html
@echo "MAN1DIR: $(MAN1DIR)"
@echo "MAN3DIR: $(MAN3DIR)"
@echo "MAN6DIR: $(MAN6DIR)"
@echo "MAN7DIR: $(MAN7DIR)"
-else
-info: info_xml info_man info_html info_tex
- @echo "DVI2PS = $(DVI2PS)"
- @echo "DVIPS_FLAGS = $(DVIPS_FLAGS)"
- @echo ""
- @echo "DISTILL = $(DISTILL)"
- @echo "DISTILL_FLAGS = $(DISTILL_FLAGS)"
-endif
info_man:
@echo "man files:"
@@ -362,14 +237,3 @@ info_html:
@echo "HTML_REF3_FILES = $(HTML_REF3_FILES)"
@echo "HTML_REF6_FILES = $(HTML_REF6_FILES)"
@echo "HTML_CHAP_FILES = $(HTML_CHAP_FILES)"
-
-info_tex:
- @echo "tex files:"
- @echo "TEX_FILES_USERS_GUIDE = $(TEX_FILES_USERS_GUIDE)"
- @echo "TEX_FILES_REF_MAN = $(TEX_FILES_REF_MAN)"
- @echo "TEX_PART_FILES = $(TEX_PART_FILES)"
- @echo "TEX_FILES_BOOK = $(TEX_FILES_BOOK)"
-
-ifndef DOCSUPPORT
-include depend.mk
-endif
diff --git a/lib/snmp/doc/src/depend.mk b/lib/snmp/doc/src/depend.mk
deleted file mode 100644
index 20a523dd8c..0000000000
--- a/lib/snmp/doc/src/depend.mk
+++ /dev/null
@@ -1,83 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %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%
-
-$(HTMLDIR)/part_notes.html: \
- part_notes_history.xml \
- part_notes.xml \
- notes_history.xml \
- notes.xml
-
-$(HTMLDIR)/part.html: \
- part.xml \
- snmp_intro.xml \
- snmp_agent_funct_descr.xml \
- snmp_manager_funct_descr.xml \
- snmp_mib_compiler.xml \
- snmp_config.xml \
- snmp_agent_config_files.xml \
- snmp_manager_config_files.xml \
- snmp_impl_example_agent.xml \
- snmp_impl_example_manager.xml \
- snmp_instr_functions.xml \
- snmp_def_instr_functions.xml \
- snmp_agent_netif.xml \
- snmp_manager_netif.xml \
- snmp_audit_trail_log.xml \
- snmp_advanced_agent.xml \
- snmp_app_a.xml \
- snmp_app_b.xml
-
-$(HTMLDIR)/ref_man.html: \
- ref_man.xml \
- snmp_app.xml \
- snmp.xml \
- snmpc.xml \
- snmpc_cmd.xml \
- snmpa.xml \
- snmpa_conf.xml \
- snmpa_discovery_handler.xml \
- snmpa_error_report.xml \
- snmpa_error.xml \
- snmpa_error_io.xml \
- snmpa_error_logger.xml \
- snmpa_local_db.xml \
- snmpa_mpd.xml \
- snmpa_network_interface.xml \
- snmpa_network_interface_filter.xml \
- snmpa_notification_delivery_info_receiver.xml \
- snmpa_notification_filter.xml \
- snmpa_supervisor.xml \
- snmp_community_mib.xml \
- snmp_framework_mib.xml \
- snmp_generic.xml \
- snmp_index.xml \
- snmp_notification_mib.xml \
- snmp_pdus.xml \
- snmp_standard_mib.xml \
- snmp_target_mib.xml \
- snmp_user_based_sm_mib.xml \
- snmp_view_based_acm_mib.xml \
- snmpm.xml \
- snmpm_conf.xml \
- snmpm_mpd.xml \
- snmpm_network_interface.xml \
- snmpm_network_interface_filter.xml \
- snmpm_user.xml
-
-
diff --git a/lib/snmp/doc/src/make.dep b/lib/snmp/doc/src/make.dep
deleted file mode 100644
index 223e197f25..0000000000
--- a/lib/snmp/doc/src/make.dep
+++ /dev/null
@@ -1,77 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-
-# %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%
-
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex snmp.tex snmp_advanced_agent.tex \
- snmp_agent_config_files.tex snmp_agent_funct_descr.tex \
- snmp_agent_netif.tex snmp_app.tex snmp_app_a.tex \
- snmp_app_b.tex snmp_audit_trail_log.tex \
- snmp_community_mib.tex \
- snmp_config.tex snmp_def_instr_functions.tex \
- snmp_framework_mib.tex snmp_generic.tex \
- snmp_impl_example_agent.tex \
- snmp_impl_example_manager.tex snmp_index.tex \
- snmp_instr_functions.tex snmp_intro.tex \
- snmp_manager_config_files.tex \
- snmp_manager_funct_descr.tex snmp_manager_netif.tex \
- snmp_mib_compiler.tex snmp_notification_mib.tex \
- snmp_pdus.tex snmp_standard_mib.tex snmp_target_mib.tex \
- snmp_user_based_sm_mib.tex snmp_view_based_acm_mib.tex \
- snmpa.tex snmpa_conf.tex snmpa_error.tex snmpa_error_io.tex \
- snmpa_error_logger.tex snmpa_error_report.tex \
- snmpa_local_db.tex snmpa_mpd.tex \
- snmpa_discovery_handler.tex \
- snmpa_network_interface.tex \
- snmpa_network_interface_filter.tex \
- snmpa_notification_delivery_info_receiver.tex \
- snmpa_notification_filter.tex \
- snmpa_supervisor.tex \
- snmpc.tex snmpc_cmd.tex snmpm.tex snmpm_conf.tex snmpm_mpd.tex \
- snmpm_network_interface.tex snmpm_network_interface_filter.tex \
- snmpm_user.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: MIB_mechanism.ps snmp-um-1-image-1.ps snmp-um-1-image-2.ps \
- snmp-um-1-image-3.ps
-
-book.dvi: snmp_agent_netif_1.ps
-
-book.dvi: getnext1.ps getnext2.ps getnext3.ps getnext4.ps
-
-book.dvi: snmp_manager_netif_1.ps
-
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 9e1a060dee..442837d57d 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,32 +32,50 @@
<file>notes.xml</file>
</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>
+ <title>SNMP Development Toolkit 4.22.1</title>
+ <p>Version 4.22.1 supports code replacement in runtime from/to
+ version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and
+ 4.21. </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>
+ <p>[agent] Sematic fixes to SNMP-USER-BASED-SM-MIB.
+ The semantics allow the <c>usmUserAuthKeyChange</c> and
+ <c>usmUserPrivKeyChange</c> objects to be written to in the
+ same set requests that also creates and clones the user.
+ This was not possible beforehand, causing test tools checking
+ semantic SNMPv3 behaviour to fail on a lot of test cases. </p>
+ <p>Furthermore, once the user has been cloned by writing to an
+ instance of <c>usmUserCloneFrom</c>, further set-operations to
+ the same object will not return an error, but be no-ops.
+ Especially, it must be avoided to copy security parameters
+ again (possibly even from a different user). </p>
+ <p>Stefan Zegenhagen</p>
+ <p>Own Id: OTP-10166</p>
</item>
<item>
- <p>[agent] Some very minor debugging improvements. </p>
- <p>Own Id: OTP-9446</p>
+ <p>[agent] Errors in <c>vacmAccessTable</c> RowStatus handling.
+ There are problems with the handling of vacmAccessTableStatus
+ that cause some SNMP test suites to report errors.
+ Most notably, erroneous set operations frequently cause "genErr"
+ errors to be returned. These "genErr" errors are usually caused
+ by badmatch exceptions coming from
+ <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c>
+ if the row does not exist. </p>
+ <p>The semantics of the RowStatus handling in that table has
+ been adjusted to be compliant with the RowStatus
+ textual description of SNPMv2-TC MIB. </p>
+ <p>Stefan Zegenhagen</p>
+ <p>Own Id: OTP-10164</p>
</item>
</list>
@@ -65,448 +83,211 @@
<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>
+ <p>[agent] Fix walk over vacmAccessTable.
+ Fix the get_next implementation of vacmAccessTable to
+ return all table entries. </p>
+ <p>The get_next implementation of vacmAccessTable did not return
+ all available table data. Instead, it only returned the first
+ column for each row, and all columns for the last row available. </p>
+ <p>Stefan Zegenhagen</p>
+ <p>Own Id: OTP-10165</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>
+ <p>[manager]
+ <seealso marker="snmpm#log_to_io">snmpm:log_to_io/6</seealso>
+ did not use the LogName argument. </p>
+ <p>Own Id: OTP-10066</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>
+ <p>Incorrect TimeTicks decode. Also bad handling of
+ invalid encode (value outside of value range) for both
+ <c>TimeTicks</c> and <c>Unsigned32</c>. </p>
+ <p>Own Id: OTP-10132</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>
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.20.1 -->
+ </section> <!-- 4.22.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>
+ <title>SNMP Development Toolkit 4.22</title>
+ <p>Version 4.22 supports code replacement in runtime from/to
+ version 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </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>
-
+ <list type="bulleted">
<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>
+ <p>[compiler] The table information the MIB compiler provides with
+ augmented tables has been extended with <c>nbr_of_cols</c>,
+ <c>first_accessible</c> and <c>not_accessible</c>. </p>
+ <p>Own Id: OTP-9969</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>
+ <p>Added the <c>log_to_io</c> audit-trail-log converter function
+ to the api modules of both the
+ <seealso marker="snmpm#log_to_io">manager</seealso>
+ and
+ <seealso marker="snmpa#log_to_io">agent</seealso>. </p>
+ <p>Own Id: OTP-9940</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>
+ <p>[manager] Introduced a new transport module,
+ <c>snmpm_net_if_mt</c>,
+ which handles all incomming and outgoing
+ traffic in newly created processes. The message/request is
+ processed and then the process exits. </p>
+ <p>Own Id: OTP-9876</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>
+ <p>[agent] Documenting previously existing but undocumented function,
+ <seealso marker="snmp_generic#get_table_info">snmp_generic:get_table_info/2</seealso>. </p>
+ <p>Own Id: OTP-9942</p>
</item>
<item>
- <p>Added type specs for functions that do not return. </p>
- <p>Kostis Sagonas</p>
- <p>Own Id: OTP-9208</p>
+ <p>[agent] Improve error handling while reading agent config files.
+ Some files contain mandatory information and is therefor themself
+ mandatory. </p>
+ <p>Own Id: OTP-9943</p>
</item>
</list>
+
</section>
<section>
<title>Fixed Bugs and Malfunctions</title>
-<!--
- <p>-</p>
--->
+ <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>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ calls can interfere.
+ The master agent did not check if a backup was already in
+ progress when a backup request was accepted. </p>
+ <p>Own Id: OTP-9884</p>
+ <p>Aux Id: Seq 11995</p>
+ </item>
</list>
- </section>
+ -->
+ </section>
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.20 -->
+ </section> <!-- 4.22 -->
<section>
- <title>SNMP Development Toolkit 4.19</title>
- <p>Version 4.19 supports code replacement in runtime from/to
- version 4.18.</p>
+ <title>SNMP Development Toolkit 4.21.7</title>
+ <p>Version 4.21.7 supports code replacement in runtime from/to
+ version 4.21.6, 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
+ 4.20. </p>
<section>
<title>Improvements and new features</title>
-<!--
<p>-</p>
--->
- <list type="bulleted">
- <item>
- <p>[compiler] Added support for textual convention
- <c>AGENT-CAPABILITIES</c> and "full" support for textual
- convention MODULE-COMPLIANCE, both defined by the SNMPv2-CONF
- mib.</p>
- <p>The <c>reference</c> and <c>modules</c> part(s) are
- stored in the <c>assocList</c> of the mib-entry (<c>me</c>)
- record.
- Only handled <em>if</em> the option(s) <c>agent_capabilities</c>
- and <c>module_compliance</c> (respectively) are provided to the
- compiler. </p>
- <p>See <seealso marker="snmpc#compile">compile/2</seealso>
- for more info. </p>
- <p>For backward compatibillity, the MIBs provided with
- this application are <em>not</em> compiled with these
- options. </p>
- <p>Own Id: OTP-8966</p>
- </item>
- <item>
- <p>[agent] Added a "complete" set of (snmp) table and variable
- print functions, for each mib handled by the SNMP (agent)
- application. This will be usefull when debugging a running agent.</p>
- <p>See
- <seealso marker="snmpa#print_mib_info">print_mib_info/0</seealso>,
- <seealso marker="snmpa#print_mib_tables">print_mib_tables/0</seealso>
- and
- <seealso marker="snmpa#print_mib_variables">print_mib_variables/0</seealso>
- for more info. </p>
- <p>Own Id: OTP-8977</p>
- </item>
-
- <item>
- <p>[compiler] Added a MIB compiler (frontend) escript,
- <c>snmpc</c>. </p>
- <p>Own Id: OTP-9004</p>
- </item>
-
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
-<!--
- <p>-</p>
--->
+ <!--
<list type="bulleted">
<item>
- <p>[agent] For the table vacmAccessTable,
- when performing the is_set_ok and set operation(s),
- all values of the vacmAccessSecurityModel column was
- incorrectly translated to <c>any</c>. </p>
-<!--
-that is when calling:
-snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
--->
- <p>Own Id: OTP-8980</p>
- </item>
-
- <item>
- <p>[agent] When calling
- <seealso marker="snmp_view_based_acm_mib#reconfigure">snmp_view_based_acm_mib:reconfigure/1</seealso>
- on a running node, the table <c>vacmAccessTable</c> was not properly
- cleaned.
- This meant that if some entries in the vacm.conf file was removed
- (compared to the <c>current</c> config),
- while others where modified and/or added, the removed entrie(s)
- would still exist in the <c>vacmAccessTable</c> table. </p>
- <p>Own Id: OTP-8981</p>
- <p>Aux Id: Seq 11750</p>
+ <p>[agent] DoS attack using GET-BULK with large value of
+ MaxRepetitions.
+ A preventive method has been implementing by simply
+ limit the number of varbinds that can be included in
+ a Get-BULK response message. This is specified by the
+ new config option,
+ <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
+ </p>
+ <p>Own Id: OTP-9700</p>
</item>
</list>
- </section>
+ -->
+ </section>
<section>
- <title>Incompatibilities</title>
+ <title>Fixed Bugs and Malfunctions</title>
+ <!--
<p>-</p>
- </section>
-
- </section> <!-- 4.19 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.18</title>
- <p>Version 4.18 supports code replacement in runtime from/to
- version 4.17.1 and 4.17.</p>
+ -->
- <section>
- <title>Improvements and new features</title>
<list type="bulleted">
<item>
- <p>Prepared for R14B release.</p>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ calls can interfere.
+ The master agent did not check if a backup was already in
+ progress when a backup request was accepted. </p>
+ <p>Own Id: OTP-9884</p>
+ <p>Aux Id: Seq 11995</p>
</item>
- </list>
- </section>
- <section><title>Fixed Bugs and Malfunctions</title>
- <p>-</p>
-<!--
- <list type="bulleted">
- <item>
- <p>[agent] When the function FilterMod:accept_recv/2 returned false
- the SNMP agent stopped collecting messages from UDP.</p>
- <p>Own Id: OTP-8761</p>
- </item>
</list>
--->
- </section>
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.18 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.17.1</title>
- <p>Version 4.17.1 supports code replacement in runtime from/to
- version 4.17, 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
-
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>When the function FilterMod:accept_recv/2
- returned false the SNMP agent stopped collecting
- messages from UDP.</p>
- <p>Own Id: OTP-8761</p>
- </item>
- </list>
</section>
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.17.1 -->
+
+ </section> <!-- 4.21.7 -->
<section>
- <title>SNMP Development Toolkit 4.17</title>
- <p>Version 4.17 supports code replacement in runtime from/to
- version 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
+ <title>SNMP Development Toolkit 4.21.6</title>
+ <p>Version 4.21.6 supports code replacement in runtime from/to
+ version 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
+ 4.20. </p>
<section>
<title>Improvements and new features</title>
- <!--
- <p>-</p>
+ <!--
+ <p>-</p>
-->
+
<list type="bulleted">
<item>
- <p>[agent] Added very basic support for multiple SNMPv3
- EngineIDs in a single agent. See
- <seealso marker="snmpa#send_notification">send_notification/7</seealso>,
- <seealso marker="snmpa_mpd#process_packet">process_packet/7</seealso>,
- <seealso marker="snmpa_mpd#generate_response_msg">generate_response_msg/6</seealso> or
- <seealso marker="snmpa_mpd#generate_msg">generate_msg/6</seealso>
- for more info. </p>
-
- <p>Own Id: OTP-8478</p>
+ <p>[agent] DoS attack using GET-BULK with large value of
+ MaxRepetitions.
+ A preventive method has been implementing by simply
+ limit the number of varbinds that can be included in
+ a Get-BULK response message. This is specified by the
+ new config option,
+ <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
+ </p>
+ <p>Own Id: OTP-9700</p>
</item>
</list>
@@ -514,23 +295,24 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
</section>
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
+ <title>Fixed Bugs and Malfunctions</title>
+ <!--
<p>-</p>
+ -->
- <!--
<list type="bulleted">
<item>
- <p>The config utility
- (<seealso marker="snmp#config">snmp:config/0</seealso>)
- generated a default notify.conf
- 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>
+ <p>[agent] Mib server cache gclimit update function incorrectly calls
+ age update function.
+ The gclimit update function,
+ <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>,
+ <em>incorrectly</em> called the age update function,
+ <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/2</seealso>. </p>
+ <p>Johan Claesson</p>
+ <p>Own Id: OTP-9868</p>
</item>
</list>
- -->
</section>
@@ -538,73 +320,25 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.17 -->
+
+ </section> <!-- 4.21.6 -->
<section>
- <title>SNMP Development Toolkit 4.16.2</title>
- <p>Version 4.16.2 supports code replacement in runtime from/to
- version 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
+ <title>SNMP Development Toolkit 4.21.5</title>
+ <p>Version 4.21.5 supports code replacement in runtime from/to
+ version 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and 4.20. </p>
<section>
<title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[compiler] The SMI specifies that a table row OID should be
- named: { &lt;tableIdentifier&gt; "1" }. </p>
- <p>A new option has been introduced,
- <seealso marker="snmpc#compiler_opts">relaxed_row_name_assign_check</seealso>,
- that allows for a more liberal numbering scheme</p>
- <p>Own Id: OTP-8574</p>
- </item>
-
- <item>
- <p>[agent|manager] Changes to make snmp (forward) compatible with
- the new version of the crypto application (released in R14).
- As of R14, crypto is implemented using NIFs. Also,
- the API is more strict. </p>
- <p>Own Id: OTP-8594</p>
- </item>
-
- <item>
- <p>Auto [agent] Changed default value for the MIB server cache.
- GC is now on by default. </p>
- <p>Own Id: OTP-8648</p>
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
+<!--
<p>-</p>
- -->
+-->
<list type="bulleted">
<item>
- <p>Encode/decode of Counter64 values larger than
- 16#7fffffffffffffff (9223372036854775807) failed. </p>
- <p>Own Id: OTP-8563</p>
- </item>
-
- <item>
- <p>[compiler] Fails to compile non-contiguous BITS. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-8595</p>
- </item>
-
- <item>
- <p>[manager] Raise condition causing the manager server process to
- crash. Unregistering an agent while traffic (set/get-operations)
- is ongoing could cause a crash in the manager server process
- (raise condition). </p>
- <p>Own Id: OTP-8646</p>
- <p>Aux Id: Seq 11585</p>
+ <p>[agent] Removed (more) use of old style tuple funs. </p>
+ <p>Own Id: OTP-9783</p>
</item>
</list>
@@ -612,1120 +346,654 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
</section>
<section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.16.2 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.16.1</title>
- <p>Version 4.16.1 supports code replacement in runtime from/to
- version 4.16, 4.15, 4.14 and 4.13.5.</p>
-
- <section>
- <title>Improvements and new features</title>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
<p>-</p>
- <!--
+-->
+
<list type="bulleted">
<item>
- <p>[agent|manager] Entries in the audit trail log can now be
- augmented by a sequence number. </p>
- <p>This is enabled by the <c>seqno</c> option, which is part of the
- <seealso marker="snmp_config#audit_trail_log">Audit Trail Log</seealso>
- config option. </p>
- <p>See the
- <seealso marker="snmp_app#configuration_params">reference manual</seealso>
- or the
- <seealso marker="snmp_config#configuration_params">Configuring the application</seealso>
- chapter of the User's Guide for further info. </p>
-
- <p>Own Id: OTP-8395</p>
+ <p>[agent] Repeated vacm table dumping fails due to file name
+ conflict. When dumping the vacm table to disk, a temoporary
+ file with a fixed name was used. If the table dumping
+ (snmpa_vacm:dump_table/0) was initiated from several different
+ processes in rapid succesion, the dumping could fail because the
+ different processes was simultaniously trying to write to the
+ same file. This problem has been eliminated by creating a unique
+ name for the temporary file. </p>
+ <p>Own Id: OTP-9851</p>
+ <p>Aux Id: Seq 11980</p>
</item>
</list>
- -->
-
</section>
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
+ <title>Incompatibilities</title>
<p>-</p>
- -->
+<!--
<list type="bulleted">
<item>
- <p>[manager] Fixed an upgrade/downgrade problem. </p>
- <p>Upgrade/downgrade from/to 4.13.5 did not work for the net-if
- process. This has now been fixed. </p>
- <p>Own Id: OTP-8481</p>
- </item>
-
- <item>
- <p>[agent] A minor mnesia related performance improvement. </p>
- <p>Own Id: OTP-8480</p>
+ <p>foo. </p>
+ <p>Own Id: OTP-9718</p>
</item>
</list>
+-->
</section>
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.16.1 -->
+ </section> <!-- 4.21.5 -->
<section>
- <title>SNMP Development Toolkit 4.16</title>
- <p>Version 4.16 supports code replacement in runtime from/to
- version 4.15, 4.14 and 4.13.5.</p>
+ <title>SNMP Development Toolkit 4.21.4</title>
+ <p>This version has never been released for R14B.</p>
+ <p>Version 4.21.4 supports code replacement in runtime from/to
+ version 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1, 4.20 and 4.19. </p>
<section>
<title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
+ <p>-</p>
+
+<!--
<list type="bulleted">
<item>
- <p>[agent|manager] Entries in the audit trail log can now be
- augmented by a sequence number. </p>
- <p>This is enabled by the <c>seqno</c> option, which is part of the
- <seealso marker="snmp_config#audit_trail_log">Audit Trail Log</seealso>
- config option. </p>
- <p>See the
- <seealso marker="snmp_app#configuration_params">reference manual</seealso>
- or the
- <seealso marker="snmp_config#configuration_params">Configuring the application</seealso>
- chapter of the User's Guide for further info. </p>
-
- <p>Own Id: OTP-8395</p>
+ <p>[compiler] Improved version info printout from the
+ <seealso marker="snmpc(command)#">MIB compiler frontend escript</seealso>. </p>
+ <p>Own Id: OTP-9618</p>
</item>
</list>
+-->
</section>
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
<list type="bulleted">
<item>
- <p>[manager] Registration of agents using the config file,
- <seealso marker="snmp_manager_config_files#agents">agents.conf</seealso>,
- does not work. This has now been corrected. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-8442</p>
- </item>
-
- <item>
- <p>The config utility
- (<seealso marker="snmp#config">snmp:config/0</seealso>)
- generated a default notify.conf
- 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>
+ <p>[agent] Removed use of old style tuple funs. </p>
+ <p>Own Id: OTP-9779</p>
</item>
</list>
-
</section>
<section>
<title>Incompatibilities</title>
<p>-</p>
- </section>
- </section> <!-- 4.16 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.15</title>
-
- <p>Version 4.15 supports code replacement in runtime from/to
- version 4.14 and 4.13.5.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
+<!--
<list type="bulleted">
<item>
- <p>The documentation is now built with open source tools
- (<em>xsltproc</em> and <em>fop</em>) that exists on most
- platforms. One visible change is that the frames are removed.</p>
- <p>Own Id: OTP-8249</p>
+ <p>foo. </p>
+ <p>Own Id: OTP-9718</p>
</item>
</list>
+-->
</section>
+ </section> <!-- 4.21.4 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.21.3</title>
+ <p>Version 4.21.3 supports code replacement in runtime from/to
+ version 4.21.2, 4.21.1, 4.21, 4.20.1, 4.20 and 4.19. </p>
+
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
+ <title>Improvements and new features</title>
+<!--
<p>-</p>
- -->
+-->
+
<list type="bulleted">
<item>
- <p>[manager] When information from an unknown agent is received,
- it was previously delivered to the default user via calls to all
- the functions of the callback API depending on the info type
- (<c>pdu</c>, <c>trap</c>, <c>report</c> or <c>inform</c>).
- The problem was that the <c>TargetName</c> argument was useless
- in this case (only an already known agent has a known/valid
- <c>TargetName</c>, but the <c>TargetName</c> used in these calls
- was generated "on the fly"). </p>
- <p>This has now been changed so that when a message is received
- from an unknown agent, then only
- <seealso marker="snmpm_user#handle_agent">handle_agent</seealso>
- (for the default user) is called, but now this call also has a
- <c>Type</c> argument, which is
- <c>pdu | trap | report | inform</c>, depending on what kind of
- message was actually received, thus making it possible for the
- user to properly analyze the data received. </p>
- <p>To handle this, the
- <seealso marker="snmpm_user">snmpm_user</seealso> behaviour has
- been updated. </p>
- <p>*** POTENTIAL INCOMPATIBILITY ***</p>
- <p>Own Id: OTP-8229</p>
- <!-- <p>Aux Id: Seq 11312</p> -->
+ <p>[compiler] Improved version info printout from the
+ <seealso marker="snmpc(command)#">MIB compiler frontend escript</seealso>. </p>
+ <p>Own Id: OTP-9618</p>
</item>
</list>
</section>
- </section> <!-- 4.15 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.14</title>
-
- <p>Version 4.14 supports code replacement in runtime from/to
- version 4.13.5, 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
-
<section>
- <title>Improvements and new features</title>
- <!--
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
<p>-</p>
- -->
+-->
<list type="bulleted">
<item>
- <p>[compiler] Include object- and notification groups in the
- compiled mib.
- This will make it possible to import groups from other mibs. </p>
- <p>Also the SNMPv2-MIB-file has been updated to a more
- up-to-date version. </p>
- <p>Own Id: OTP-8223</p>
- <!-- <p>Aux Id: Seq 11383</p> -->
+ <p>[agent] Version 4.20 introduced a change that broke trap
+ sending from subagents. Due to a bug in the test code,
+ this was not discovered, until that bug was fixed. </p>
+ <p>Own Id: OTP-9745</p>
</item>
<item>
- <p>[manager] Added support for message filtering in the
- network interface module provided with the application.
- The component that actually make the filter decisions
- is the network interface filter module. This module
- must implement the
- <seealso marker="snmpm_network_interface_filter">network interface filter behaviour</seealso>
- for message filtering.
- See also the Configuring chapter of
- the User's Guide to see how to configure this feature. </p>
- <p>See the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the filter options.</p>
- <p>Own Id: OTP-8228</p>
- <p>Aux Id: Seq 11411</p>
+ <p>[agent] When sending an error message (reply) regarding
+ <c>snmpUnknownPDUHandlers</c>, the agent used the wrong OID. </p>
+ <p>Own Id: OTP-9747</p>
</item>
<item>
- <p>The MIBs delivered as part of the application is now
- also available as man pages, section 7. </p>
- <p>Own Id: OTP-8237</p>
- <!-- <p>Aux Id: Seq 11383</p> -->
+ <p>[compiler] Fix the <c>--warnings/--W</c> option parsing in the
+ <seealso marker="snmpc(command)#option_warnings">snmpc</seealso>
+ wrapper (e)script.
+ The short warning option was incorrectly <c>--w</c>, instead
+ of as documented <c>--W</c>. This has now been corrected. </p>
+ <p>*** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>Tuncer Ayaz</p>
+ <p>Own Id: OTP-9718</p>
</item>
</list>
-
</section>
+
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
+ <title>Incompatibilities</title>
+<!--
<p>-</p>
+-->
- <!--
<list type="bulleted">
<item>
- <p>[agent] The main agent type header file contained some miss-information
- regarding the type of the entrytype field of the me-record, causing
- unneccessary confusion.</p>
- <p>Own Id: OTP-8116</p>
- <p>Aux Id: Seq 11312</p>
+ <p>[compiler] The short warning option has been changed from
+ <c>--w</c> to <c>--W</c> to comply with the documentation. </p>
+ <p>Tuncer Ayaz</p>
+ <p>Own Id: OTP-9718</p>
</item>
</list>
- -->
-
</section>
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.14 -->
+ </section> <!-- 4.21.3 -->
<section>
- <title>SNMP Development Toolkit 4.13.5</title>
-
- <p>Version 4.13.5 supports code replacement in runtime from/to
- version 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+ <title>SNMP Development Toolkit 4.21.2</title>
+ <p>Version 4.21.2 supports code replacement in runtime from/to
+ version 4.21.1, 4.21, 4.20.1, 4.20 and 4.19. </p>
<section>
<title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
+ <p>-</p>
+<!--
<list type="bulleted">
<item>
- <p>[agent] Improved the cache handling of the mib server. </p>
- <p>A number of new functions and config options for the mib server
- cache has been added. </p>
- <p>See
- <seealso marker="snmpa#invalidate_mibs_cache">invalidate_mibs_cache/0,1</seealso>,
- <seealso marker="snmpa#enable_mibs_cache">enable_mibs_cache/0,1</seealso>,
- <seealso marker="snmpa#disable_mibs_cache">disable_mibs_cache/0,1</seealso>,
- <seealso marker="snmpa#gc_mibs_cache">gc_mibs_cache/0,1,2,3</seealso>,
- <seealso marker="snmpa#enable_mibs_cache_autogc">enable_mibs_cache_autogc/0,1</seealso>,
- <seealso marker="snmpa#disable_mibs_cache_autogc">disable_mibs_cache_autogc/0,1</seealso>,
- <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/1,2</seealso> and
- <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1,2</seealso> for more info. </p>
- <p>See also the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the mib server cache options.</p>
- <p>Own Id: OTP-8182</p>
- <p>Aux Id: Seq 11383</p>
- </item>
-
- <item>
- <p>[agent] A manager could no longer use the SNMPv3 user "initial"
- as this was interpretated as the first step of the discovery. </p>
- <p>Introduced a new terminating option, <c>trigger_username</c> to
- make it possible to configure the username the agent reacts to.
- Default is <c>""</c>. </p>
- <p>See the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the discovery options.</p>
- <p>Own Id: OTP-8120</p>
- <p>Aux Id: Seq 11361</p>
+ <p>Bad note store GC timer deactivation.
+ Wrong field in the state record was set (timeout instead active). </p>
+ <p>Stefan Grundmann</p>
+ <p>Own Id: OTP-9690</p>
</item>
</list>
+-->
</section>
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
<list type="bulleted">
<item>
- <p>[agent] The main agent type header file contained some miss-information
- regarding the type of the entrytype field of the me-record, causing
- unneccessary confusion.</p>
- <p>Own Id: OTP-8116</p>
- <p>Aux Id: Seq 11312</p>
+ <p>Bad note store GC timer deactivation.
+ Wrong field in the state record was set (timeout instead active). </p>
+ <p>Stefan Grundmann</p>
+ <p>Own Id: OTP-9690</p>
</item>
</list>
-
</section>
+
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.13.5 -->
+ </section> <!-- 4.21.2 -->
- <section>
- <title>SNMP Development Toolkit 4.13.4</title>
- <p>Version 4.13.4 supports code replacement in runtime from/to
- version 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+ <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>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
+<!--
<p>-</p>
- -->
+-->
<list type="bulleted">
<item>
- <p>[agent] Originating discovery problems. </p>
- <p>Invalid state variable update during second stage of
- discovery causes master agent crash. </p>
- <p>Also the net_if process failed to activate socket
- ({active, once}) after first discovery response was sent. </p>
- <p>Own Id: OTP-8044</p>
- <p>Aux Id: Seq 11295</p>
- </item>
-
- <item>
- <p>[agent] Terminating discovery problem. </p>
- <p>The reply to the second stage request should include a
- varbind with <c>usmStatsNotInTimeWindows</c>.</p>
- <p>Own Id: OTP-8062</p>
- <p>Aux Id: Seq 11318</p>
+ <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] Originating discovery improvement. </p>
- <p>Added the ExtraInfo argument to the
- <seealso marker="snmpa#discovery">discovery</seealso> function.
- This argument will be passed on to the stage1_finish callback
- function. Also, the
- <seealso marker="snmpa#discovery">discovery</seealso> function
- will now always return <c>{ok, ManagerEngineID}</c> on successful
- discovery. </p>
- <p>The <seealso marker="snmpa_discovery_handler">discovery handler</seealso>
- behaviour updated accordingly. </p>
- <p>Own Id: OTP-8098</p>
- <p>Aux Id: Seq 11346</p>
+ <p>[agent] Some very minor debugging improvements. </p>
+ <p>Own Id: OTP-9446</p>
</item>
-
</list>
</section>
<section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.4 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.13.3</title>
-
- <p>Version 4.13.3 supports code replacement in runtime from/to
- version 4.13.2, 4.13.1 and 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
+ <title>Fixed Bugs and Malfunctions</title>
<p>-</p>
- <!--
+<!--
<list type="bulleted">
<item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </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>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] A request for an oid of type BITS was actually
- returned as OCTET STRING. </p>
- <p>Values of type BITS are encoded as OCTET STRING,
- which makes it impossible for the decoder to know that
- they should really be of type BITS.
- Instead, this has to be done higher up in the stack, where
- there is knowledge of the MIB (assuming that the mib has
- been loaded, there is info about the type of the mibentry). </p>
- <p>This problem has now been fixed, but requires that the MIB
- defining this mib-entry is loaded! </p>
- <p>The utility function
- <seealso marker="snmpm#oid_to_type">oid_to_type</seealso>
- has been added, for debug purpose. </p>
- <p>The utility function(s)
- <seealso marker="snmp#octet_string_to_bits">octet_string_to_bits</seealso>
- and
- <seealso marker="snmp#bits_to_octet_string">bits_to_octet_string</seealso>
- has also been added. These can be used if the user prefers to
- handle the conversion on their own. </p>
- <p>Own Id: OTP-8015</p>
- <p>Aux Id: Seq 11285</p>
- </item>
-
- <item>
- <p>[agent] Fixed some issues with the discovery handling. </p>
- <p>Changed the API of the
- <seealso marker="snmpa#discovery">discovery</seealso>
- function to solve some
- of these problems. </p>
- <p>Introduced various options for controlling the discovery
- process. See the
- <seealso marker="snmp_app#configuration_params">configuration</seealso>
- chapter for more info about the discovery options.</p>
- <p>Own Id: OTP-8020</p>
- <p>Aux Id: Seq 11295</p>
- </item>
-
- </list>
-
- </section>
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.13.3 -->
+ </section> <!-- 4.21.1 -->
- <section>
- <title>SNMP Development Toolkit 4.13.2</title>
- <p>Version 4.13.2 supports code replacement in runtime from/to
- version 4.13.1 and 4.13.</p>
+ <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>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
+<!--
<p>-</p>
- -->
+-->
<list type="bulleted">
<item>
- <p>[manager] Failure during downed user cleanup.
- As part of the cleanup after a crashed user,
- the manager attempts to unregister the agents
- registered by this user. This however failed,
- causing a server crash. </p>
- <p>Own Id: OTP-7961</p>
- <p>Aux Id: Seq 11275</p>
- </item>
-
- <item>
- <p>[manager] Incorrectly documented value type for
- IpAddress (ip). The value type for IpAddress is
- documented as ip but is actually ia. The value type
- ip has been added. The old (not documented) value
- type ia still works. </p>
- <p>Own Id: OTP-7977</p>
- <p>Aux Id: Seq 11279</p>
- </item>
-
- <item>
- <p>[manager] EngineId lookup fails when using version-3. </p>
- <p>Own Id: OTP-7983</p>
- <p>Aux Id: Seq 11275</p>
+ <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>[agent] As of version 4.13 the possible return values
- of the function
- <seealso marker="snmpa_mpd#process_packet">snmpa_mpd:process_packet/4</seealso>
- changed, but this was not documented. </p>
- <p>Own Id: OTP-7989</p>
- <p>Aux Id: Seq 11275</p>
+ <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>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.13.2 -->
-
- <section>
- <title>SNMP Development Toolkit 4.13.1</title>
-
- <p>Version 4.13.1 supports code replacement in runtime from/to
- version 4.13.</p>
-
- <section>
- <title>Improvements and new features</title>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
<p>-</p>
+-->
- <!--
<list type="bulleted">
<item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
- </item>
-
- </list>
- -->
+ <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>
- </section>
+ <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>
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
<item>
- <p>[manager] Registration of users had some issues. </p>
- <p>Not all of the registration functions where actually exported
- (<seealso marker="snmpm#register_user">register_user/4</seealso>
- and
- <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>).
- This has now been fixed. </p>
- <p>Also, the registration did not succeed unless
- user implemented the *new* behaviour. This has now
- also been fixed (registration succeeds if the user
- implements either the new (i.e. updated
- <seealso marker="snmpm_user">snmpm_user</seealso>)
- or the old user behaviour (<c>snmpm_user_old</c>)). </p>
- <p>Own Id: OTP-7902</p>
- <p>Aux Id: Seq 11240</p>
- </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.13.1 -->
+
+ </section> <!-- 4.21 -->
+
<section>
- <title>SNMP Development Toolkit 4.13</title>
-<!--
- <p>Version 4.13 supports code replacement in runtime from/to
- version 4.12.1.</p>
--->
+ <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>
- -->
+ <p>-</p>
+<!--
<list type="bulleted">
<item>
- <p>[agent] Support for the discovery process. </p>
- <p>The agent can both initiate discovery itself (see the
- <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
- for more info) and respond to discovery initiated by a manager.</p>
- <p>Own Id: OTP-7571</p>
- <p>Aux Id: Seq 11053</p>
+ <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>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
<list type="bulleted">
<item>
- <p>[agent] Unnecessary use of math:pow/2 could cause problems
- on systems without floating point support. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7735</p>
- <!-- <p>Aux Id: Seq 10966</p> -->
- </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>[manager] A major flaw was discovered with the agent handling. </p>
- <p>First, <c>TargetName</c> was never used as intended, as a unique
- identifier for the target (agent in this case). </p>
- <p>Second, <c>TargetName</c> had a <em>default value</em>, which meant
- that several agents could have the same <c>TargetName</c>, causing
- unpredictable behaviour in the manager. </p>
- <p>Third, <c>EngineID</c> was not a mandatory config option and had
- furthermore also a <em>default value</em>. </p>
-
- <p>These problems has been solved in the following way: </p>
- <p>First, a new set of api functions has been introduced (and documented):
- <seealso marker="snmpm#register_user">register_user/4</seealso>,
- <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>,
- <seealso marker="snmpm#register_agent">register_agent/3</seealso>,
- <seealso marker="snmpm#unregister_agent">unregister_agent/2</seealso>,
- <seealso marker="snmpm#agent_info">agent_info/2</seealso>,
- <seealso marker="snmpm#update_agent_info">update_agent_info/4</seealso>,
- <seealso marker="snmpm#sync_get">sync_get/3,4,5,6</seealso>,
- <seealso marker="snmpm#async_get">async_get/3,4,5,6</seealso>,
- <seealso marker="snmpm#sync_get_next">sync_get_next/3,4,5,6</seealso>,
- <seealso marker="snmpm#async_get_next">async_get_next/3,4,5,6</seealso>,
- <seealso marker="snmpm#sync_set">sync_set/3,4,5,6</seealso>,
- <seealso marker="snmpm#async_set">async_set/3,4,5,6</seealso>,
- <seealso marker="snmpm#sync_get_bulk">sync_get_bulk/5,6,7,8</seealso> and
- <seealso marker="snmpm#async_get_bulk">async_get_bulk/5,6,7,8</seealso>
- that all use <c>TargetName</c> (and not, as previously, <c>Addr</c>
- and <c>Port</c>) to identify the agent (also the return value of
- <seealso marker="snmpm#which_agents">which_agents</seealso> has
- been changed). </p>
- <p>Second, for backward compatibility, the old functions still
- exist, but are no longer documented and are now wrappers for the
- new functions, including erroneous default value for EngineID and
- all. The TargetName is however generated from the provided
- <c>Addr</c>, <c>Port</c> and <c>Version</c> config options. </p>
- <p>Third, the behaviour of the
- <seealso marker="snmpm_user">SNMP manager user</seealso> has
- been changed to reflect this, i.e.
- <seealso marker="snmpm_user#handle_pdu">handle_pdu/4</seealso>,
- <seealso marker="snmpm_user#handle_trap">handle_trap/3</seealso>,
- <seealso marker="snmpm_user#handle_inform">handle_inform/3</seealso>,
- <seealso marker="snmpm_user#handle_report">handle_report/3</seealso>
- and the return-value of
- <seealso marker="snmpm_user#handle_agent">handle_agent/4</seealso>.
- The old (non-documented) callback-functions (using Addr and Port)
- will still be called if the agent was registered using the old
- registration functions. </p>
-
- <p>Own Id: OTP-7836</p>
- <!-- <p>Aux Id: Seq 10966</p> -->
- </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.13 -->
-
- <section>
- <title>SNMP Development Toolkit 4.12.2</title>
- <p>Version 4.12.2 supports code replacement in runtime from/to
- version 4.12.1, 4.12, 4.11.2, 4.11.1 and 4.11.</p>
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
- <!--
- <list type="bulleted">
- <item>
- <item>
- <p>[agent] Improvement of the inform reporting.
- It was previously not certain how many acks an
- application received, 0, 1 or 2. This has now been
- fixed, so that only 1 (one) ack is issued. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7525</p>
- </item>
+ </section> <!-- 4.20.1 -->
- </list>
- -->
- </section>
+ <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>Reported Fixed Bugs and Malfunctions</title>
- <!--
+ <title>Improvements and new features</title>
+<!--
<p>-</p>
- -->
+-->
<list type="bulleted">
<item>
- <p>[agent] Bad session cache (usm+camv-info) invalidation
- could cause user crash, through call(s) to (a number of)
- MIB API function(s) (undefined function). </p>
- <p>Own Id: OTP-7868</p>
- <!-- <p>Aux Id: Seq 11124</p> -->
- </item>
-
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.12.2 -->
+ <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>
- <section>
- <title>SNMP Development Toolkit 4.12.1</title>
- <p>Version 4.12.1 supports code replacement in runtime from/to
- version 4.12, 4.11.2, 4.11.1 and 4.11.</p>
- <section>
- <title>Improvements and new features</title>
- <p>-</p>
- <!--
- <list type="bulleted">
- <item>
<item>
- <p>[agent] Improvement of the inform reporting.
- It was previously not certain how many acks an
- application received, 0, 1 or 2. This has now been
- fixed, so that only 1 (one) ack is issued. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7525</p>
+ <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>
- </list>
- -->
-
- </section>
-
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
<item>
- <p>Logging of messages with the GetBulk-request PDU
- incorrectly produced an erroneous entry in the
- log: "An error occurred". </p>
- <p>The reason for this was that the PDU-fields
- error_status and error_index is re-used for
- Non-repeaters and Max-repetitions for
- GetBulk-request PDUs, but this was not handled
- by the logging code. </p>
- <p>Own Id: OTP-7695</p>
- <p>Aux Id: Seq 11124</p>
+ <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>[agent] An attempt to set the row status to active for an
- notReady table row, could result in an "inconsistentValue"
- error. </p>
- <p>The same problem existed when attempting to set row status
- to notInService for a row in notReady. </p>
- <p>Serge Aleynikov</p>
- <p>Own Id: OTP-7698</p>
- <!-- <p>Aux Id: Seq 10966</p> -->
+ <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>
- </list>
-
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.12.1 -->
-
- <section>
- <title>SNMP Development Toolkit 4.12</title>
- <p>Version 4.12 supports code replacement in runtime from/to
- version 4.11.2, 4.11.1 and 4.11.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
<item>
- <p>[agent] A simple lookup cache has been added to improve
- the mib server lookup performance. </p>
- <p>This can be disabled with the mib_server
- <seealso marker="snmp_app">cache</seealso> option. </p>
- <p>Own Id: OTP-7346</p>
+ <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>[agent] Improvement of the inform reporting.
- It was previously not certain how many acks an
- application received, 0, 1 or 2. This has now been
- fixed, so that only 1 (one) ack is issued. </p>
- <p>Per Hedeland</p>
- <p>Own Id: OTP-7525</p>
+ <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>Reported Fixed Bugs and Malfunctions</title>
- <p>-</p>
- <!--
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
<list type="bulleted">
<item>
- <p>[manager] Encryption error when attempting to send
- version 3 inform-requests. </p>
- <p>Own Id: OTP-7432</p>
- <p>Aux Id: Seq 10966</p>
- </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.12 -->
+
+ </section> <!-- 4.20 -->
+
<section>
- <title>SNMP Development Toolkit 4.11.2</title>
- <p>Version 4.11.2 supports code replacement in runtime from/to
- version 4.11.1 and 4.11. </p>
+ <title>SNMP Development Toolkit 4.19</title>
+ <p>Version 4.19 supports code replacement in runtime from/to
+ version 4.18.</p>
<section>
<title>Improvements and new features</title>
- <p>-</p>
- <!--
+<!--
+ <p>-</p>
+-->
<list type="bulleted">
<item>
- <p>Added utility functions for transforming DateAndTime
- as [int()] to strings;
- <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
- and
- <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
- <p>Also added new validation function
- <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
- <p>Own Id: OTP-7412</p>
- <p>Aux Id: Seq 10987</p>
+ <p>[compiler] Added support for textual convention
+ <c>AGENT-CAPABILITIES</c> and "full" support for textual
+ convention MODULE-COMPLIANCE, both defined by the SNMPv2-CONF
+ mib.</p>
+ <p>The <c>reference</c> and <c>modules</c> part(s) are
+ stored in the <c>assocList</c> of the mib-entry (<c>me</c>)
+ record.
+ Only handled <em>if</em> the option(s) <c>agent_capabilities</c>
+ and <c>module_compliance</c> (respectively) are provided to the
+ compiler. </p>
+ <p>See <seealso marker="snmpc#compile">compile/2</seealso>
+ for more info. </p>
+ <p>For backward compatibillity, the MIBs provided with
+ this application are <em>not</em> compiled with these
+ options. </p>
+ <p>Own Id: OTP-8966</p>
</item>
- </list>
- -->
- </section>
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
<item>
- <p>[manager] Erroneous engine-id check when receiving version 3
- informs. </p>
- <p>Own Id: OTP-7570</p>
- <p>Aux Id: Seq 11060</p>
+ <p>[agent] Added a "complete" set of (snmp) table and variable
+ print functions, for each mib handled by the SNMP (agent)
+ application. This will be usefull when debugging a running agent.</p>
+ <p>See
+ <seealso marker="snmpa#print_mib_info">print_mib_info/0</seealso>,
+ <seealso marker="snmpa#print_mib_tables">print_mib_tables/0</seealso>
+ and
+ <seealso marker="snmpa#print_mib_variables">print_mib_variables/0</seealso>
+ for more info. </p>
+ <p>Own Id: OTP-8977</p>
</item>
<item>
- <p>Receiving an snmp message with a very large version
- number could cause the erlang node to run out of
- memory and consequently crash. </p>
- <p>The standard specifies the snmp version as an
- (unlimited) INTEGER, but today only
- 0 (version 1), 1 (version 2) and 3 (version 3) is
- actually used. So, when decoding a message, a limit
- has been put on the snmp version integer in order
- to not allow this kind of a problem. </p>
- <p>Own Id: OTP-7575</p>
- <p>Aux Id: Seq 11064</p>
+ <p>[compiler] Added a MIB compiler (frontend) escript,
+ <c>snmpc</c>. </p>
+ <p>Own Id: OTP-9004</p>
</item>
</list>
</section>
<section>
- <title>Incompatibilities</title>
- <p>-</p>
- </section>
- </section> <!-- 4.11.2 -->
-
-
- <section>
- <title>SNMP Development Toolkit 4.11.1</title>
- <p>Version 4.11.1 supports code replacement in runtime from/to
- version 4.11.</p>
-
- <section>
- <title>Improvements and new features</title>
- <!--
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
<p>-</p>
- -->
+-->
<list type="bulleted">
<item>
- <p>[compiler] The MIB compiler did not retrieve the REFERENCE part
- of a SNMP MIB definition. </p>
- <p>This problem has been partly solved. For SNMP tables,
- the assocList field of the tables mib-entry record now contains
- this info (as <c>{reference, string()}</c>), <em>if</em> the
- MIB was compiled with the compiler option <em>+reference</em>. </p>
- <p>This solution is temporary, until such time as a permanent
- solution (and probably not backward compatible) is devised, which
- retrieves and stores all REFERENCE part(s) of a MIB. </p>
- <p>See the
- <seealso marker="snmpc#compiler_opts">compiler options</seealso>
- for more info. </p>
-
- <p>Serge Aleynikov</p>
- <p>Own Id: OTP-7426</p>
+ <p>[agent] For the table vacmAccessTable,
+ when performing the is_set_ok and set operation(s),
+ all values of the vacmAccessSecurityModel column was
+ incorrectly translated to <c>any</c>. </p>
+<!--
+that is when calling:
+snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
+-->
+ <p>Own Id: OTP-8980</p>
</item>
<item>
- <p>Added utility functions for transforming DateAndTime
- as [int()] to strings;
- <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
- and
- <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
- <p>Also added new validation function
- <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
- <p>Own Id: OTP-7412</p>
- <p>Aux Id: Seq 10987</p>
+ <p>[agent] When calling
+ <seealso marker="snmp_view_based_acm_mib#reconfigure">snmp_view_based_acm_mib:reconfigure/1</seealso>
+ on a running node, the table <c>vacmAccessTable</c> was not properly
+ cleaned.
+ This meant that if some entries in the vacm.conf file was removed
+ (compared to the <c>current</c> config),
+ while others where modified and/or added, the removed entrie(s)
+ would still exist in the <c>vacmAccessTable</c> table. </p>
+ <p>Own Id: OTP-8981</p>
+ <p>Aux Id: Seq 11750</p>
</item>
</list>
-
</section>
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
- <p>-</p>
- -->
- <list type="bulleted">
- <item>
- <p>[manager] Encryption error when attempting to send
- version 3 inform-requests. </p>
- <p>Own Id: OTP-7432</p>
- <p>Aux Id: Seq 10966</p>
- </item>
-
- </list>
- </section>
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.11.1 -->
+
+ </section> <!-- 4.19 -->
+
<section>
- <title>SNMP Development Toolkit 4.11</title>
- <p>Version 4.11 supports code replacement in runtime from/to
- version 4.10.3, 4.10.2, 4.10.1 and 4.10.</p>
+ <title>SNMP Development Toolkit 4.18</title>
+ <p>Version 4.18 supports code replacement in runtime from/to
+ version 4.17.1 and 4.17.</p>
<section>
<title>Improvements and new features</title>
- <!--
- <p>-</p>
- -->
<list type="bulleted">
<item>
- <p>[agent] Performance improvements in the case when an SNMP
- manager performs an snmpwalk. </p>
- <p>Martin Bj&ouml;rklund</p>
- <p>Own Id: OTP-7201</p>
- </item>
-
- <item>
- <p>The API for sending inform(s) has been improved. Also
- the documentation has been corrected and updated. See
- <seealso marker="snmpa#send_notification">snmpa:send_notification</seealso> and
- <seealso marker="snmpa_notification_delivery_info_receiver">snmpa_notification_delivery_info_receiver</seealso>
- for more info.</p>
- <p>Own Id: OTP-7287</p>
- <p>Aux Id: Seq 10926</p>
- </item>
-
- <item>
- <p>[agent] Performance of the internal database (local-db)
- has been improved.</p>
- <p>Own Id: OTP-7319</p>
- <p>Aux Id: Seq 10942</p>
- </item>
-
- <item>
- <p>[agent] Added utility functions,
- <seealso marker="snmpa#restart_worker">snmpa:restart_worker/0,1</seealso> and
- <seealso marker="snmpa#restart_set_worker">snmpa:restart_set_worker/0,1</seealso>,
- for restarting the agent worker processes (in case the agent is
- multi-threaded).</p>
- <p>Own Id: OTP-7369</p>
- </item>
-
- <item>
- <p>Add utility function to
- <seealso marker="snmp#read_mib">read</seealso>
- a compiled mib. </p>
- <p>Own Id: OTP-7371</p>
+ <p>Prepared for R14B release.</p>
</item>
-
</list>
</section>
- <section>
- <title>Reported Fixed Bugs and Malfunctions</title>
- <!--
+ <section><title>Fixed Bugs and Malfunctions</title>
<p>-</p>
- -->
+<!--
<list type="bulleted">
<item>
- <p>[manager] Encryption error when attempting to send
- version 3 inform-requests. </p>
- <p>Own Id: OTP-7377</p>
- <p>Aux Id: Seq 10966</p>
+ <p>[agent] When the function FilterMod:accept_recv/2 returned false
+ the SNMP agent stopped collecting messages from UDP.</p>
+ <p>Own Id: OTP-8761</p>
</item>
-
</list>
+-->
</section>
<section>
<title>Incompatibilities</title>
<p>-</p>
</section>
- </section> <!-- 4.11 -->
+ </section> <!-- 4.18 -->
+
<!-- section>
<title>Release notes history</title>
diff --git a/lib/snmp/doc/src/notes_history.xml b/lib/snmp/doc/src/notes_history.xml
index 934df87866..023717cd7c 100644
--- a/lib/snmp/doc/src/notes_history.xml
+++ b/lib/snmp/doc/src/notes_history.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>2004</year><year>2010</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,1277 @@
</header>
<section>
+ <title>SNMP Development Toolkit 4.17.1</title>
+ <p>Version 4.17.1 supports code replacement in runtime from/to
+ version 4.17, 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>When the function FilterMod:accept_recv/2
+ returned false the SNMP agent stopped collecting
+ messages from UDP.</p>
+ <p>Own Id: OTP-8761</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.17.1 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.17</title>
+ <p>Version 4.17 supports code replacement in runtime from/to
+ version 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Added very basic support for multiple SNMPv3
+ EngineIDs in a single agent. See
+ <seealso marker="snmpa#send_notification">send_notification/7</seealso>,
+ <seealso marker="snmpa_mpd#process_packet">process_packet/7</seealso>,
+ <seealso marker="snmpa_mpd#generate_response_msg">generate_response_msg/6</seealso> or
+ <seealso marker="snmpa_mpd#generate_msg">generate_msg/6</seealso>
+ for more info. </p>
+
+ <p>Own Id: OTP-8478</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>The config utility
+ (<seealso marker="snmp#config">snmp:config/0</seealso>)
+ generated a default notify.conf
+ 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>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.17 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.16.2</title>
+ <p>Version 4.16.2 supports code replacement in runtime from/to
+ version 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[compiler] The SMI specifies that a table row OID should be
+ named: { &lt;tableIdentifier&gt; "1" }. </p>
+ <p>A new option has been introduced,
+ <seealso marker="snmpc#compiler_opts">relaxed_row_name_assign_check</seealso>,
+ that allows for a more liberal numbering scheme</p>
+ <p>Own Id: OTP-8574</p>
+ </item>
+
+ <item>
+ <p>[agent|manager] Changes to make snmp (forward) compatible with
+ the new version of the crypto application (released in R14).
+ As of R14, crypto is implemented using NIFs. Also,
+ the API is more strict. </p>
+ <p>Own Id: OTP-8594</p>
+ </item>
+
+ <item>
+ <p>Auto [agent] Changed default value for the MIB server cache.
+ GC is now on by default. </p>
+ <p>Own Id: OTP-8648</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>Encode/decode of Counter64 values larger than
+ 16#7fffffffffffffff (9223372036854775807) failed. </p>
+ <p>Own Id: OTP-8563</p>
+ </item>
+
+ <item>
+ <p>[compiler] Fails to compile non-contiguous BITS. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-8595</p>
+ </item>
+
+ <item>
+ <p>[manager] Raise condition causing the manager server process to
+ crash. Unregistering an agent while traffic (set/get-operations)
+ is ongoing could cause a crash in the manager server process
+ (raise condition). </p>
+ <p>Own Id: OTP-8646</p>
+ <p>Aux Id: Seq 11585</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.16.2 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.16.1</title>
+ <p>Version 4.16.1 supports code replacement in runtime from/to
+ version 4.16, 4.15, 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent|manager] Entries in the audit trail log can now be
+ augmented by a sequence number. </p>
+ <p>This is enabled by the <c>seqno</c> option, which is part of the
+ <seealso marker="snmp_config#audit_trail_log">Audit Trail Log</seealso>
+ config option. </p>
+ <p>See the
+ <seealso marker="snmp_app#configuration_params">reference manual</seealso>
+ or the
+ <seealso marker="snmp_config#configuration_params">Configuring the application</seealso>
+ chapter of the User's Guide for further info. </p>
+
+ <p>Own Id: OTP-8395</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>[manager] Fixed an upgrade/downgrade problem. </p>
+ <p>Upgrade/downgrade from/to 4.13.5 did not work for the net-if
+ process. This has now been fixed. </p>
+ <p>Own Id: OTP-8481</p>
+ </item>
+
+ <item>
+ <p>[agent] A minor mnesia related performance improvement. </p>
+ <p>Own Id: OTP-8480</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.16.1 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.16</title>
+ <p>Version 4.16 supports code replacement in runtime from/to
+ version 4.15, 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent|manager] Entries in the audit trail log can now be
+ augmented by a sequence number. </p>
+ <p>This is enabled by the <c>seqno</c> option, which is part of the
+ <seealso marker="snmp_config#audit_trail_log">Audit Trail Log</seealso>
+ config option. </p>
+ <p>See the
+ <seealso marker="snmp_app#configuration_params">reference manual</seealso>
+ or the
+ <seealso marker="snmp_config#configuration_params">Configuring the application</seealso>
+ chapter of the User's Guide for further info. </p>
+
+ <p>Own Id: OTP-8395</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>[manager] Registration of agents using the config file,
+ <seealso marker="snmp_manager_config_files#agents">agents.conf</seealso>,
+ does not work. This has now been corrected. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-8442</p>
+ </item>
+
+ <item>
+ <p>The config utility
+ (<seealso marker="snmp#config">snmp:config/0</seealso>)
+ generated a default notify.conf
+ 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>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.16 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.15</title>
+
+ <p>Version 4.15 supports code replacement in runtime from/to
+ version 4.14 and 4.13.5.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>The documentation is now built with open source tools
+ (<em>xsltproc</em> and <em>fop</em>) that exists on most
+ platforms. One visible change is that the frames are removed.</p>
+ <p>Own Id: OTP-8249</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] When information from an unknown agent is received,
+ it was previously delivered to the default user via calls to all
+ the functions of the callback API depending on the info type
+ (<c>pdu</c>, <c>trap</c>, <c>report</c> or <c>inform</c>).
+ The problem was that the <c>TargetName</c> argument was useless
+ in this case (only an already known agent has a known/valid
+ <c>TargetName</c>, but the <c>TargetName</c> used in these calls
+ was generated "on the fly"). </p>
+ <p>This has now been changed so that when a message is received
+ from an unknown agent, then only
+ <seealso marker="snmpm_user#handle_agent">handle_agent</seealso>
+ (for the default user) is called, but now this call also has a
+ <c>Type</c> argument, which is
+ <c>pdu | trap | report | inform</c>, depending on what kind of
+ message was actually received, thus making it possible for the
+ user to properly analyze the data received. </p>
+ <p>To handle this, the
+ <seealso marker="snmpm_user">snmpm_user</seealso> behaviour has
+ been updated. </p>
+ <p>*** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>Own Id: OTP-8229</p>
+ <!-- <p>Aux Id: Seq 11312</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ </section> <!-- 4.15 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.14</title>
+
+ <p>Version 4.14 supports code replacement in runtime from/to
+ version 4.13.5, 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Include object- and notification groups in the
+ compiled mib.
+ This will make it possible to import groups from other mibs. </p>
+ <p>Also the SNMPv2-MIB-file has been updated to a more
+ up-to-date version. </p>
+ <p>Own Id: OTP-8223</p>
+ <!-- <p>Aux Id: Seq 11383</p> -->
+ </item>
+
+ <item>
+ <p>[manager] Added support for message filtering in the
+ network interface module provided with the application.
+ The component that actually make the filter decisions
+ is the network interface filter module. This module
+ must implement the
+ <seealso marker="snmpm_network_interface_filter">network interface filter behaviour</seealso>
+ for message filtering.
+ See also the Configuring chapter of
+ the User's Guide to see how to configure this feature. </p>
+ <p>See the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the filter options.</p>
+ <p>Own Id: OTP-8228</p>
+ <p>Aux Id: Seq 11411</p>
+ </item>
+
+ <item>
+ <p>The MIBs delivered as part of the application is now
+ also available as man pages, section 7. </p>
+ <p>Own Id: OTP-8237</p>
+ <!-- <p>Aux Id: Seq 11383</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] The main agent type header file contained some miss-information
+ regarding the type of the entrytype field of the me-record, causing
+ unneccessary confusion.</p>
+ <p>Own Id: OTP-8116</p>
+ <p>Aux Id: Seq 11312</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.14 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.5</title>
+
+ <p>Version 4.13.5 supports code replacement in runtime from/to
+ version 4.13.4, 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+
+ <list type="bulleted">
+ <item>
+ <p>[agent] Improved the cache handling of the mib server. </p>
+ <p>A number of new functions and config options for the mib server
+ cache has been added. </p>
+ <p>See
+ <seealso marker="snmpa#invalidate_mibs_cache">invalidate_mibs_cache/0,1</seealso>,
+ <seealso marker="snmpa#enable_mibs_cache">enable_mibs_cache/0,1</seealso>,
+ <seealso marker="snmpa#disable_mibs_cache">disable_mibs_cache/0,1</seealso>,
+ <seealso marker="snmpa#gc_mibs_cache">gc_mibs_cache/0,1,2,3</seealso>,
+ <seealso marker="snmpa#enable_mibs_cache_autogc">enable_mibs_cache_autogc/0,1</seealso>,
+ <seealso marker="snmpa#disable_mibs_cache_autogc">disable_mibs_cache_autogc/0,1</seealso>,
+ <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/1,2</seealso> and
+ <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1,2</seealso> for more info. </p>
+ <p>See also the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the mib server cache options.</p>
+ <p>Own Id: OTP-8182</p>
+ <p>Aux Id: Seq 11383</p>
+ </item>
+
+ <item>
+ <p>[agent] A manager could no longer use the SNMPv3 user "initial"
+ as this was interpretated as the first step of the discovery. </p>
+ <p>Introduced a new terminating option, <c>trigger_username</c> to
+ make it possible to configure the username the agent reacts to.
+ Default is <c>""</c>. </p>
+ <p>See the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the discovery options.</p>
+ <p>Own Id: OTP-8120</p>
+ <p>Aux Id: Seq 11361</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] The main agent type header file contained some miss-information
+ regarding the type of the entrytype field of the me-record, causing
+ unneccessary confusion.</p>
+ <p>Own Id: OTP-8116</p>
+ <p>Aux Id: Seq 11312</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.5 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.4</title>
+
+ <p>Version 4.13.4 supports code replacement in runtime from/to
+ version 4.13.3, 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Originating discovery problems. </p>
+ <p>Invalid state variable update during second stage of
+ discovery causes master agent crash. </p>
+ <p>Also the net_if process failed to activate socket
+ ({active, once}) after first discovery response was sent. </p>
+ <p>Own Id: OTP-8044</p>
+ <p>Aux Id: Seq 11295</p>
+ </item>
+
+ <item>
+ <p>[agent] Terminating discovery problem. </p>
+ <p>The reply to the second stage request should include a
+ varbind with <c>usmStatsNotInTimeWindows</c>.</p>
+ <p>Own Id: OTP-8062</p>
+ <p>Aux Id: Seq 11318</p>
+ </item>
+
+ <item>
+ <p>[agent] Originating discovery improvement. </p>
+ <p>Added the ExtraInfo argument to the
+ <seealso marker="snmpa#discovery">discovery</seealso> function.
+ This argument will be passed on to the stage1_finish callback
+ function. Also, the
+ <seealso marker="snmpa#discovery">discovery</seealso> function
+ will now always return <c>{ok, ManagerEngineID}</c> on successful
+ discovery. </p>
+ <p>The <seealso marker="snmpa_discovery_handler">discovery handler</seealso>
+ behaviour updated accordingly. </p>
+ <p>Own Id: OTP-8098</p>
+ <p>Aux Id: Seq 11346</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.4 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.3</title>
+
+ <p>Version 4.13.3 supports code replacement in runtime from/to
+ version 4.13.2, 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] A request for an oid of type BITS was actually
+ returned as OCTET STRING. </p>
+ <p>Values of type BITS are encoded as OCTET STRING,
+ which makes it impossible for the decoder to know that
+ they should really be of type BITS.
+ Instead, this has to be done higher up in the stack, where
+ there is knowledge of the MIB (assuming that the mib has
+ been loaded, there is info about the type of the mibentry). </p>
+ <p>This problem has now been fixed, but requires that the MIB
+ defining this mib-entry is loaded! </p>
+ <p>The utility function
+ <seealso marker="snmpm#oid_to_type">oid_to_type</seealso>
+ has been added, for debug purpose. </p>
+ <p>The utility function(s)
+ <seealso marker="snmp#octet_string_to_bits">octet_string_to_bits</seealso>
+ and
+ <seealso marker="snmp#bits_to_octet_string">bits_to_octet_string</seealso>
+ has also been added. These can be used if the user prefers to
+ handle the conversion on their own. </p>
+ <p>Own Id: OTP-8015</p>
+ <p>Aux Id: Seq 11285</p>
+ </item>
+
+ <item>
+ <p>[agent] Fixed some issues with the discovery handling. </p>
+ <p>Changed the API of the
+ <seealso marker="snmpa#discovery">discovery</seealso>
+ function to solve some
+ of these problems. </p>
+ <p>Introduced various options for controlling the discovery
+ process. See the
+ <seealso marker="snmp_app#configuration_params">configuration</seealso>
+ chapter for more info about the discovery options.</p>
+ <p>Own Id: OTP-8020</p>
+ <p>Aux Id: Seq 11295</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.3 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.2</title>
+
+ <p>Version 4.13.2 supports code replacement in runtime from/to
+ version 4.13.1 and 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Failure during downed user cleanup.
+ As part of the cleanup after a crashed user,
+ the manager attempts to unregister the agents
+ registered by this user. This however failed,
+ causing a server crash. </p>
+ <p>Own Id: OTP-7961</p>
+ <p>Aux Id: Seq 11275</p>
+ </item>
+
+ <item>
+ <p>[manager] Incorrectly documented value type for
+ IpAddress (ip). The value type for IpAddress is
+ documented as ip but is actually ia. The value type
+ ip has been added. The old (not documented) value
+ type ia still works. </p>
+ <p>Own Id: OTP-7977</p>
+ <p>Aux Id: Seq 11279</p>
+ </item>
+
+ <item>
+ <p>[manager] EngineId lookup fails when using version-3. </p>
+ <p>Own Id: OTP-7983</p>
+ <p>Aux Id: Seq 11275</p>
+ </item>
+
+ <item>
+ <p>[agent] As of version 4.13 the possible return values
+ of the function
+ <seealso marker="snmpa_mpd#process_packet">snmpa_mpd:process_packet/4</seealso>
+ changed, but this was not documented. </p>
+ <p>Own Id: OTP-7989</p>
+ <p>Aux Id: Seq 11275</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.2 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.13.1</title>
+
+ <p>Version 4.13.1 supports code replacement in runtime from/to
+ version 4.13.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Registration of users had some issues. </p>
+ <p>Not all of the registration functions where actually exported
+ (<seealso marker="snmpm#register_user">register_user/4</seealso>
+ and
+ <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>).
+ This has now been fixed. </p>
+ <p>Also, the registration did not succeed unless
+ user implemented the *new* behaviour. This has now
+ also been fixed (registration succeeds if the user
+ implements either the new (i.e. updated
+ <seealso marker="snmpm_user">snmpm_user</seealso>)
+ or the old user behaviour (<c>snmpm_user_old</c>)). </p>
+ <p>Own Id: OTP-7902</p>
+ <p>Aux Id: Seq 11240</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13.1 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.13</title>
+<!--
+ <p>Version 4.13 supports code replacement in runtime from/to
+ version 4.12.1.</p>
+-->
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Support for the discovery process. </p>
+ <p>The agent can both initiate discovery itself (see the
+ <seealso marker="snmp_agent_funct_descr#discovery">discovery</seealso> chapter
+ for more info) and respond to discovery initiated by a manager.</p>
+ <p>Own Id: OTP-7571</p>
+ <p>Aux Id: Seq 11053</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Unnecessary use of math:pow/2 could cause problems
+ on systems without floating point support. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7735</p>
+ <!-- <p>Aux Id: Seq 10966</p> -->
+ </item>
+
+ <item>
+ <p>[manager] A major flaw was discovered with the agent handling. </p>
+ <p>First, <c>TargetName</c> was never used as intended, as a unique
+ identifier for the target (agent in this case). </p>
+ <p>Second, <c>TargetName</c> had a <em>default value</em>, which meant
+ that several agents could have the same <c>TargetName</c>, causing
+ unpredictable behaviour in the manager. </p>
+ <p>Third, <c>EngineID</c> was not a mandatory config option and had
+ furthermore also a <em>default value</em>. </p>
+
+ <p>These problems has been solved in the following way: </p>
+ <p>First, a new set of api functions has been introduced (and documented):
+ <seealso marker="snmpm#register_user">register_user/4</seealso>,
+ <seealso marker="snmpm#register_user_monitor">register_user_monitor/4</seealso>,
+ <seealso marker="snmpm#register_agent">register_agent/3</seealso>,
+ <seealso marker="snmpm#unregister_agent">unregister_agent/2</seealso>,
+ <seealso marker="snmpm#agent_info">agent_info/2</seealso>,
+ <seealso marker="snmpm#update_agent_info">update_agent_info/4</seealso>,
+ <seealso marker="snmpm#sync_get">sync_get/3,4,5,6</seealso>,
+ <seealso marker="snmpm#async_get">async_get/3,4,5,6</seealso>,
+ <seealso marker="snmpm#sync_get_next">sync_get_next/3,4,5,6</seealso>,
+ <seealso marker="snmpm#async_get_next">async_get_next/3,4,5,6</seealso>,
+ <seealso marker="snmpm#sync_set">sync_set/3,4,5,6</seealso>,
+ <seealso marker="snmpm#async_set">async_set/3,4,5,6</seealso>,
+ <seealso marker="snmpm#sync_get_bulk">sync_get_bulk/5,6,7,8</seealso> and
+ <seealso marker="snmpm#async_get_bulk">async_get_bulk/5,6,7,8</seealso>
+ that all use <c>TargetName</c> (and not, as previously, <c>Addr</c>
+ and <c>Port</c>) to identify the agent (also the return value of
+ <seealso marker="snmpm#which_agents">which_agents</seealso> has
+ been changed). </p>
+ <p>Second, for backward compatibility, the old functions still
+ exist, but are no longer documented and are now wrappers for the
+ new functions, including erroneous default value for EngineID and
+ all. The TargetName is however generated from the provided
+ <c>Addr</c>, <c>Port</c> and <c>Version</c> config options. </p>
+ <p>Third, the behaviour of the
+ <seealso marker="snmpm_user">SNMP manager user</seealso> has
+ been changed to reflect this, i.e.
+ <seealso marker="snmpm_user#handle_pdu">handle_pdu/4</seealso>,
+ <seealso marker="snmpm_user#handle_trap">handle_trap/3</seealso>,
+ <seealso marker="snmpm_user#handle_inform">handle_inform/3</seealso>,
+ <seealso marker="snmpm_user#handle_report">handle_report/3</seealso>
+ and the return-value of
+ <seealso marker="snmpm_user#handle_agent">handle_agent/4</seealso>.
+ The old (non-documented) callback-functions (using Addr and Port)
+ will still be called if the agent was registered using the old
+ registration functions. </p>
+
+ <p>Own Id: OTP-7836</p>
+ <!-- <p>Aux Id: Seq 10966</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.13 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.12.2</title>
+ <p>Version 4.12.2 supports code replacement in runtime from/to
+ version 4.12.1, 4.12, 4.11.2, 4.11.1 and 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <item>
+ <p>[agent] Improvement of the inform reporting.
+ It was previously not certain how many acks an
+ application received, 0, 1 or 2. This has now been
+ fixed, so that only 1 (one) ack is issued. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7525</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Bad session cache (usm+camv-info) invalidation
+ could cause user crash, through call(s) to (a number of)
+ MIB API function(s) (undefined function). </p>
+ <p>Own Id: OTP-7868</p>
+ <!-- <p>Aux Id: Seq 11124</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.12.2 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.12.1</title>
+ <p>Version 4.12.1 supports code replacement in runtime from/to
+ version 4.12, 4.11.2, 4.11.1 and 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <item>
+ <p>[agent] Improvement of the inform reporting.
+ It was previously not certain how many acks an
+ application received, 0, 1 or 2. This has now been
+ fixed, so that only 1 (one) ack is issued. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7525</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>Logging of messages with the GetBulk-request PDU
+ incorrectly produced an erroneous entry in the
+ log: "An error occurred". </p>
+ <p>The reason for this was that the PDU-fields
+ error_status and error_index is re-used for
+ Non-repeaters and Max-repetitions for
+ GetBulk-request PDUs, but this was not handled
+ by the logging code. </p>
+ <p>Own Id: OTP-7695</p>
+ <p>Aux Id: Seq 11124</p>
+ </item>
+
+ <item>
+ <p>[agent] An attempt to set the row status to active for an
+ notReady table row, could result in an "inconsistentValue"
+ error. </p>
+ <p>The same problem existed when attempting to set row status
+ to notInService for a row in notReady. </p>
+ <p>Serge Aleynikov</p>
+ <p>Own Id: OTP-7698</p>
+ <!-- <p>Aux Id: Seq 10966</p> -->
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.12.1 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.12</title>
+ <p>Version 4.12 supports code replacement in runtime from/to
+ version 4.11.2, 4.11.1 and 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] A simple lookup cache has been added to improve
+ the mib server lookup performance. </p>
+ <p>This can be disabled with the mib_server
+ <seealso marker="snmp_app">cache</seealso> option. </p>
+ <p>Own Id: OTP-7346</p>
+ </item>
+
+ <item>
+ <p>[agent] Improvement of the inform reporting.
+ It was previously not certain how many acks an
+ application received, 0, 1 or 2. This has now been
+ fixed, so that only 1 (one) ack is issued. </p>
+ <p>Per Hedeland</p>
+ <p>Own Id: OTP-7525</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[manager] Encryption error when attempting to send
+ version 3 inform-requests. </p>
+ <p>Own Id: OTP-7432</p>
+ <p>Aux Id: Seq 10966</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.12 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.11.2</title>
+ <p>Version 4.11.2 supports code replacement in runtime from/to
+ version 4.11.1 and 4.11. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>Added utility functions for transforming DateAndTime
+ as [int()] to strings;
+ <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
+ and
+ <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
+ <p>Also added new validation function
+ <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
+ <p>Own Id: OTP-7412</p>
+ <p>Aux Id: Seq 10987</p>
+ </item>
+ </list>
+ -->
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Erroneous engine-id check when receiving version 3
+ informs. </p>
+ <p>Own Id: OTP-7570</p>
+ <p>Aux Id: Seq 11060</p>
+ </item>
+
+ <item>
+ <p>Receiving an snmp message with a very large version
+ number could cause the erlang node to run out of
+ memory and consequently crash. </p>
+ <p>The standard specifies the snmp version as an
+ (unlimited) INTEGER, but today only
+ 0 (version 1), 1 (version 2) and 3 (version 3) is
+ actually used. So, when decoding a message, a limit
+ has been put on the snmp version integer in order
+ to not allow this kind of a problem. </p>
+ <p>Own Id: OTP-7575</p>
+ <p>Aux Id: Seq 11064</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.11.2 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.11.1</title>
+ <p>Version 4.11.1 supports code replacement in runtime from/to
+ version 4.11.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[compiler] The MIB compiler did not retrieve the REFERENCE part
+ of a SNMP MIB definition. </p>
+ <p>This problem has been partly solved. For SNMP tables,
+ the assocList field of the tables mib-entry record now contains
+ this info (as <c>{reference, string()}</c>), <em>if</em> the
+ MIB was compiled with the compiler option <em>+reference</em>. </p>
+ <p>This solution is temporary, until such time as a permanent
+ solution (and probably not backward compatible) is devised, which
+ retrieves and stores all REFERENCE part(s) of a MIB. </p>
+ <p>See the
+ <seealso marker="snmpc#compiler_opts">compiler options</seealso>
+ for more info. </p>
+
+ <p>Serge Aleynikov</p>
+ <p>Own Id: OTP-7426</p>
+ </item>
+
+ <item>
+ <p>Added utility functions for transforming DateAndTime
+ as [int()] to strings;
+ <seealso marker="snmp#dat2s">date_and_time_to_string/2</seealso>
+ and
+ <seealso marker="snmp#dat2s2">date_and_time_to_string2/1</seealso>. </p>
+ <p>Also added new validation function
+ <seealso marker="snmp#vdat">validate_date_and_time/2</seealso>. </p>
+ <p>Own Id: OTP-7412</p>
+ <p>Aux Id: Seq 10987</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Encryption error when attempting to send
+ version 3 inform-requests. </p>
+ <p>Own Id: OTP-7432</p>
+ <p>Aux Id: Seq 10966</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.11.1 -->
+
+ <section>
+ <title>SNMP Development Toolkit 4.11</title>
+ <p>Version 4.11 supports code replacement in runtime from/to
+ version 4.10.3, 4.10.2, 4.10.1 and 4.10.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Performance improvements in the case when an SNMP
+ manager performs an snmpwalk. </p>
+ <p>Martin Bj&ouml;rklund</p>
+ <p>Own Id: OTP-7201</p>
+ </item>
+
+ <item>
+ <p>The API for sending inform(s) has been improved. Also
+ the documentation has been corrected and updated. See
+ <seealso marker="snmpa#send_notification">snmpa:send_notification</seealso> and
+ <seealso marker="snmpa_notification_delivery_info_receiver">snmpa_notification_delivery_info_receiver</seealso>
+ for more info.</p>
+ <p>Own Id: OTP-7287</p>
+ <p>Aux Id: Seq 10926</p>
+ </item>
+
+ <item>
+ <p>[agent] Performance of the internal database (local-db)
+ has been improved.</p>
+ <p>Own Id: OTP-7319</p>
+ <p>Aux Id: Seq 10942</p>
+ </item>
+
+ <item>
+ <p>[agent] Added utility functions,
+ <seealso marker="snmpa#restart_worker">snmpa:restart_worker/0,1</seealso> and
+ <seealso marker="snmpa#restart_set_worker">snmpa:restart_set_worker/0,1</seealso>,
+ for restarting the agent worker processes (in case the agent is
+ multi-threaded).</p>
+ <p>Own Id: OTP-7369</p>
+ </item>
+
+ <item>
+ <p>Add utility function to
+ <seealso marker="snmp#read_mib">read</seealso>
+ a compiled mib. </p>
+ <p>Own Id: OTP-7371</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <!--
+ <p>-</p>
+ -->
+ <list type="bulleted">
+ <item>
+ <p>[manager] Encryption error when attempting to send
+ version 3 inform-requests. </p>
+ <p>Own Id: OTP-7377</p>
+ <p>Aux Id: Seq 10966</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+ </section> <!-- 4.11 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.10.3</title>
<p>Version 4.10.3 supports code replacement in runtime from/to
version 4.10.2, 4.10.1 and 4.10.</p>
diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml
index af0833f005..3e6610891f 100644
--- a/lib/snmp/doc/src/snmp.xml
+++ b/lib/snmp/doc/src/snmp.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>1996</year><year>2009</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -391,6 +391,30 @@
version of the protocol data unit. There is a new line
between <c>Vsn</c> and <c>PDU</c>.</p>
+ <marker id="log_to_io"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
+ <fsummary>Convert an Audit Trail Log to text format</fsummary>
+ <type>
+ <v>LogDir = string()</v>
+ <v>Mibs = [MibName]</v>
+ <v>MibName = string()</v>
+ <v>LogName = string()</v>
+ <v>LogFile = string()</v>
+ <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Converts an Audit Trail Log to a readable format and
+ prints it on stdio. See
+ <seealso marker="snmp#log_to_txt">log_to_txt</seealso>
+ above for more info.</p>
+
<marker id="change_log_size"></marker>
</desc>
</func>
diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml
index 694e619da1..62dfa515d1 100644
--- a/lib/snmp/doc/src/snmp_app.xml
+++ b/lib/snmp/doc/src/snmp_app.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE appref SYSTEM "appref.dtd">
<appref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,8 +35,8 @@
<appsummary>The SNMP Application</appsummary>
<description>
<p>This chapter describes the <c>snmp</c>
- application in OTP. The SNMP application provides the following
- services:</p>
+ application in OTP. The SNMP application provides the following
+ services:</p>
<list type="bulleted">
<item>
<p>a multilingual extensible SNMP agent</p>
@@ -78,7 +78,15 @@
].
</pre>
- <!-- The info below is also found in the snmp_config.xml file -->
+
+ <!--
+ ********************************************************
+
+ The info below is also found in the snmp_config.xml file
+
+ ********************************************************
+ -->
+
<p>Each snmp component has its own set of configuration parameters,
even though some of the types are common to both components. </p>
@@ -92,6 +100,7 @@
{agent_verbosity, verbosity()} |
{discovery, agent_discovery()} |
{versions, versions()} |
+ {gb_max_vbs, gb_max_vbs()} |
{priority, priority()} |
{multi_threaded, multi_threaded()} |
{db_dir, db_dir()} |
@@ -122,8 +131,10 @@
{def_user_data, def_user_data()}
</pre>
+ <marker id="agent_opts_and_types"></marker>
<p>Agent specific config options and types:</p>
<taglist>
+ <marker id="agent_type"></marker>
<tag><c><![CDATA[agent_type() = master | sub <optional>]]></c></tag>
<item>
<p>If <c>master</c>, one master agent is
@@ -131,6 +142,7 @@
<p>Default is <c>master</c>.</p>
</item>
+ <marker id="agent_disco"></marker>
<tag><c><![CDATA[agent_discovery() = [agent_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_discovery_opt() =
@@ -143,6 +155,7 @@
<p>For defaults see the options in <c>agent_discovery_opt()</c>.</p>
</item>
+ <marker id="agent_term_disco_opts"></marker>
<tag><c><![CDATA[agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_terminating_discovery_opt() =
@@ -160,6 +173,7 @@
</list>
</item>
+ <marker id="agent_orig_disco_opts"></marker>
<tag><c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_originating_discovery_opt() =
@@ -173,6 +187,7 @@
</list>
</item>
+ <marker id="agent_mt"></marker>
<tag><c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, the agent is multi-threaded, with one
@@ -180,11 +195,21 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="agent_data_dir"></marker>
<tag><c><![CDATA[db_dir() = string() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent internal db files are stored.</p>
</item>
+ <marker id="agent_gb_max_vbs"></marker>
+ <tag><c><![CDATA[gb_max_vbs() = pos_integer() | infinity <optional>]]></c></tag>
+ <item>
+ <p>Defines the maximum number of varbinds allowed
+ in a Get-BULK response.</p>
+ <p>Default is <c>1000</c>.</p>
+ </item>
+
+ <marker id="agent_local_db"></marker>
<tag><c><![CDATA[local_db() = [local_db_opt()] <optional>]]></c></tag>
<item>
<p><c>local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}</c></p>
@@ -192,6 +217,7 @@
<p>For defaults see the options in <c>local_db_opt()</c>.</p>
</item>
+ <marker id="agent_ldb_repair"></marker>
<tag><c><![CDATA[agent_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>When starting snmpa_local_db it always tries to open an
@@ -202,6 +228,7 @@
<p>Default is <c>true</c>.</p>
</item>
+ <marker id="agent_ldb_auto_save"></marker>
<tag><c><![CDATA[agent_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
@@ -209,6 +236,7 @@
<p>Default is <c>5000</c>.</p>
</item>
+ <marker id="agent_net_if"></marker>
<tag><c><![CDATA[agent_net_if() = [agent_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_opt() = {module, agent_net_if_module()} | {verbosity, verbosity()} | {options, agent_net_if_options()}</c></p>
@@ -217,6 +245,7 @@
<p>For defaults see the options in <c>agent_net_if_opt()</c>.</p>
</item>
+ <marker id="agent_ni_module"></marker>
<tag><c><![CDATA[agent_net_if_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface part for the
@@ -225,6 +254,7 @@
<p>Default is <c>snmpa_net_if</c>.</p>
</item>
+ <marker id="agent_ni_opts"></marker>
<tag><c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() = {bind_to, bind_to()} |
@@ -239,12 +269,14 @@
<p>For defaults see the options in <c>agent_net_if_option()</c>.</p>
</item>
+ <marker id="agent_ni_req_limit"></marker>
<tag><c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
<item>
<p>Max number of simultaneous requests handled by the agent.</p>
<p>Default is <c>infinity</c>.</p>
</item>
+ <marker id="agent_ni_filter_opts"></marker>
<tag><c><![CDATA[agent_net_if_filter_options() = [agent_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_filter_option() = {module, agent_net_if_filter_module()}</c></p>
@@ -255,6 +287,7 @@
<c>agent_net_if_filter_option()</c>.</p>
</item>
+ <marker id="agent_ni_filter_module"></marker>
<tag><c><![CDATA[agent_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
@@ -263,6 +296,7 @@
<p>Default is <c>snmpa_net_if_filter</c>.</p>
</item>
+ <marker id="agent_mibs"></marker>
<tag><c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) that defines which MIBs
@@ -277,6 +311,7 @@
<p>Default is <c>[]</c>.</p>
</item>
+ <marker id="agent_mib_storage"></marker>
<tag><c><![CDATA[mib_storage() = ets | {ets, Dir} | {ets, Dir, Action} | dets | {dets, Dir} | {dets, Dir, Action} | mnesia | {mnesia, Nodes} | {mnesia, Nodes, Action} <optional>]]></c></tag>
<item>
<p>Specifies how info retrieved from the mibs will be stored.</p>
@@ -302,6 +337,7 @@
mnesia/dets table already exist.</p>
</item>
+ <marker id="agent_mib_server"></marker>
<tag><c><![CDATA[mib_server() = [mib_server_opt()] <optional>]]></c></tag>
<item>
<p><c>mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()}</c></p>
@@ -309,6 +345,7 @@
<p>For defaults see the options in <c>mib_server_opt()</c>.</p>
</item>
+ <marker id="agent_ms_meo"></marker>
<tag><c><![CDATA[mibentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each mib-
@@ -318,6 +355,7 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="agent_ms_teo"></marker>
<tag><c><![CDATA[trapentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each trap
@@ -327,6 +365,7 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="agent_ms_cache"></marker>
<tag><c><![CDATA[mibs_cache() = bool() | mibs_cache_opts() <optional>]]></c></tag>
<item>
<p>Shall the agent utilize the mib server lookup cache or not.</p>
@@ -334,6 +373,7 @@
default values apply).</p>
</item>
+ <marker id="agent_ms_cache_opts"></marker>
<tag><c><![CDATA[mibs_cache_opts() = [mibs_cache_opt()] <optional>]]></c></tag>
<item>
<p><c>mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}</c></p>
@@ -341,6 +381,7 @@
<p>For defaults see the options in <c>mibs_cache_opt()</c>.</p>
</item>
+ <marker id="agent_ms_cache_autogc"></marker>
<tag><c><![CDATA[mibs_cache_autogc() = bool() <optional>]]></c></tag>
<item>
<p>Defines if the mib server shall perform cache gc automatically or
@@ -349,6 +390,7 @@
<p>Default is <c>true</c>.</p>
</item>
+ <marker id="agent_ms_cache_age"></marker>
<tag><c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag>
<item>
<p>Defines how old the entries in the cache will be allowed before
@@ -358,6 +400,7 @@
<p>Default is <c>10 timutes</c>.</p>
</item>
+ <marker id="agent_ms_cache_gclimit"></marker>
<tag><c><![CDATA[mibs_cache_gclimit() = integer() > 0 | infinity <optional>]]></c></tag>
<item>
<p>When performing a GC, this is the max number of cache entries
@@ -368,6 +411,7 @@
<p>Default is <c>100</c>.</p>
</item>
+ <marker id="agent_error_report_mod"></marker>
<tag><c><![CDATA[error_report_mod() = atom() <optional>]]></c></tag>
<item>
<p>Defines an error report module, implementing the
@@ -377,6 +421,7 @@
<p>Default is <c>snmpa_error_logger</c>.</p>
</item>
+ <marker id="agent_symbolic_store"></marker>
<tag><c>symbolic_store() = [symbolic_store_opt()]</c></tag>
<item>
<p><c>symbolic_store_opt() = {verbosity, verbosity()}</c></p>
@@ -384,23 +429,29 @@
<p>For defaults see the options in <c>symbolic_store_opt()</c>.</p>
</item>
+ <marker id="agent_target_cache"></marker>
<tag><c>target_cache() = [target_cache_opt()]</c></tag>
<item>
<p><c>target_cache_opt() = {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent target cache. </p>
<p>For defaults see the options in <c>target_cache_opt()</c>.</p>
</item>
+
+ <marker id="agent_config"></marker>
<tag><c><![CDATA[agent_config() = [agent_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}</c></p>
<p>Defines specific config related options for the SNMP agent. </p>
<p>For defaults see the options in <c>agent_config_opt()</c>.</p>
</item>
+
+ <marker id="agent_config_dir"></marker>
<tag><c><![CDATA[agent_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent configuration files are stored.</p>
</item>
+ <marker id="agent_force_load"></marker>
<tag><c><![CDATA[force_load() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c> the configuration files are re-read
@@ -412,14 +463,18 @@
</item>
</taglist>
+ <marker id="manager_opts_and_types"></marker>
<p>Manager specific config options and types:</p>
<taglist>
+ <marker id="manager_server"></marker>
<tag><c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
<item>
<p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the options for the manager server process.</p>
<p>Default is <c>silence</c>.</p>
</item>
+
+ <marker id="manager_server_timeout"></marker>
<tag><c><![CDATA[server_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Asynchroneous request cleanup time. For every requests,
@@ -440,6 +495,7 @@
<p>Default is <c>30000</c>.</p>
</item>
+ <marker id="manager_config"></marker>
<tag><c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}</c></p>
@@ -447,16 +503,19 @@
<p>For defaults see the options in <c>manager_config_opt()</c>.</p>
</item>
+ <marker id="manager_config_dir"></marker>
<tag><c><![CDATA[manager_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager configuration files are stored.</p>
</item>
+ <marker id="manager_config_db_dir"></marker>
<tag><c><![CDATA[manager_db_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager store persistent data.</p>
</item>
+ <marker id="manager_config_repair"></marker>
<tag><c><![CDATA[manager_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>Defines the repair option for the persistent database (if
@@ -464,6 +523,7 @@
<p>Default is <c>true</c>.</p>
</item>
+ <marker id="manager_config_auto_save"></marker>
<tag><c><![CDATA[manager_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
@@ -471,6 +531,7 @@
<p>Default is <c>5000</c>.</p>
</item>
+ <marker id="manager_irb"></marker>
<tag><c><![CDATA[manager_irb() = auto | user | {user, integer()} <optional>]]></c></tag>
<item>
<p>This option defines how the manager will handle the sending of
@@ -500,6 +561,7 @@
<p>Default is <c>auto</c>.</p>
</item>
+ <marker id="manager_mibs"></marker>
<tag><c><![CDATA[manager_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) and defines which MIBs
@@ -507,6 +569,7 @@
<p>Default is <c>[]</c>.</p>
</item>
+ <marker id="manager_net_if"></marker>
<tag><c><![CDATA[manager_net_if() = [manager_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_opt() = {module, manager_net_if_module()} |
@@ -517,6 +580,7 @@
<p>For defaults see the options in <c>manager_net_if_opt()</c>.</p>
</item>
+ <marker id="manager_ni_opts"></marker>
<tag><c><![CDATA[manager_net_if_options() = [manager_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_option() = {bind_to, bind_to()} |
@@ -525,19 +589,21 @@
{no_reuse, no_reuse()} |
{filter, manager_net_if_filter_options()} </c></p>
<p>These options are actually specific to the used module.
- The ones shown here are applicable to the default
- <c>manager_net_if_module()</c>.</p>
+ The ones shown here are applicable to the default
+ <c>manager_net_if_module()</c>.</p>
<p>For defaults see the options in <c>manager_net_if_option()</c>.</p>
</item>
+ <marker id="manager_ni_module"></marker>
<tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
<item>
- <p>Module which handles the network interface part for the
- SNMP manager. Must implement the
+ <p>The module which handles the network interface part for the
+ SNMP manager. It must implement the
<seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour.</p>
<p>Default is <c>snmpm_net_if</c>.</p>
</item>
+ <marker id="manager_ni_filter_opts"></marker>
<tag><c><![CDATA[manager_net_if_filter_options() = [manager_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_filter_option() = {module, manager_net_if_filter_module()}</c></p>
@@ -548,6 +614,7 @@
<c>manager_net_if_filter_option()</c>.</p>
</item>
+ <marker id="manager_ni_filter_module"></marker>
<tag><c><![CDATA[manager_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
@@ -556,6 +623,7 @@
<p>Default is <c>snmpm_net_if_filter</c>.</p>
</item>
+ <marker id="manager_def_user_module"></marker>
<tag><c><![CDATA[def_user_module() = atom() <optional>]]></c></tag>
<item>
<p>The module implementing the default user. See the
@@ -563,6 +631,7 @@
<p>Default is <c>snmpm_user_default</c>.</p>
</item>
+ <marker id="manager_def_user_data"></marker>
<tag><c><![CDATA[def_user_data() = term() <optional>]]></c></tag>
<item>
<p>Data for the default user. Passed to the user module when
@@ -571,8 +640,10 @@
</item>
</taglist>
+ <marker id="common_types"></marker>
<p>Common config types:</p>
<taglist>
+ <marker id="restart_type"></marker>
<tag><c>restart_type() = permanent | transient | temporary</c></tag>
<item>
<p>See <seealso marker="stdlib:supervisor#child_spec">supervisor</seealso>
@@ -580,6 +651,8 @@
<p>Default is <c>permanent</c> for the agent and <c>transient</c>
for the manager.</p>
</item>
+
+ <marker id="db_init_error"></marker>
<tag><c>db_init_error() = terminate | create</c></tag>
<item>
<p>Defines what to do if the agent or manager is unable to open an
@@ -588,23 +661,31 @@
agent/manager will remove the faulty file(s) and create new ones.</p>
<p>Default is <c>terminate</c>.</p>
</item>
+
+ <marker id="prio"></marker>
<tag><c><![CDATA[priority() = atom() <optional>]]></c></tag>
<item>
<p>Defines the Erlang priority for all SNMP processes.</p>
<p>Default is <c>normal</c>.</p>
</item>
+
+ <marker id="versions"></marker>
<tag><c><![CDATA[versions() = [version()] <optional>]]></c></tag>
<item>
<p><c>version() = v1 | v2 | v3</c></p>
<p>Which SNMP versions shall be accepted/used.</p>
<p>Default is <c>[v1,v2,v3]</c>.</p>
</item>
+
+ <marker id="verbosity"></marker>
<tag><c><![CDATA[verbosity() = silence | info | log | debug | trace <optional>]]></c></tag>
<item>
<p>Verbosity for a SNMP process. This specifies now much debug info
is printed.</p>
<p>Default is <c>silence</c>.</p>
</item>
+
+ <marker id="bind_to"></marker>
<tag><c><![CDATA[bind_to() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if binds to the IP address.
@@ -612,6 +693,8 @@
where it is running. </p>
<p>Default is <c>false</c>.</p>
</item>
+
+ <marker id="no_reuse"></marker>
<tag><c><![CDATA[no_reuse() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if does not specify that the IP
@@ -619,22 +702,30 @@
the address is set to reusable. </p>
<p>Default is <c>false</c>.</p>
</item>
+
+ <marker id="recbuf"></marker>
<tag><c><![CDATA[recbuf() = integer() <optional>]]></c></tag>
<item>
<p>Receive buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
+
+ <marker id="sndbuf"></marker>
<tag><c><![CDATA[sndbuf() = integer() <optional>]]></c></tag>
<item>
<p>Send buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
+
+ <marker id="note_store"></marker>
<tag><c><![CDATA[note_store() = [note_store_opt()] <optional>]]></c></tag>
<item>
<p><c>note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the start-up verbosity for the SNMP note store.</p>
<p>For defaults see the options in <c>note_store_opt()</c>.</p>
</item>
+
+ <marker id="ns_timeout"></marker>
<tag><c><![CDATA[note_store_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Note cleanup time. When storing a note in the note store,
@@ -643,9 +734,9 @@
milli-seconds.</p>
<p>Default is <c>30000</c>.</p>
- <marker id="audit_trail_log"></marker>
</item>
+ <marker id="audit_trail_log"></marker>
<tag><c><![CDATA[audit_trail_log() = [audit_trail_log_opt()] <optional>]]></c></tag>
<item>
<p><c>audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}</c></p>
@@ -655,6 +746,8 @@
<c>size</c> options are mandatory.</p>
<p>If not present, audit trail logging is not used.</p>
</item>
+
+ <marker id="atl_type"></marker>
<tag><c><![CDATA[atl_type() = read | write | read_write <optional>]]></c></tag>
<item>
<p>Specifies what type of an audit trail log should be used.
@@ -675,12 +768,16 @@
</list>
<p>Default is <c>read_write</c>.</p>
</item>
+
+ <marker id="atl_dir"></marker>
<tag><c><![CDATA[atl_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Specifies where the audit trail log should be stored.</p>
<p>If <c>audit_trail_log</c> specifies that logging should take
place, this parameter <em>must</em> be defined.</p>
</item>
+
+ <marker id="atl_size"></marker>
<tag><c><![CDATA[atl_size() = {integer(), integer()} <mandatory>]]></c></tag>
<item>
<p>Specifies the size of the audit
@@ -688,6 +785,8 @@
<p>If <c>audit_trail_log</c> specifies that logging should
take place, this parameter <em>must</em> be defined.</p>
</item>
+
+ <marker id="atl_repair"></marker>
<tag><c><![CDATA[atl_repair() = true | false | truncate | snmp_repair <optional>]]></c></tag>
<item>
<p>Specifies if and how the audit trail log shall be repaired
@@ -699,6 +798,8 @@
analysis.</p>
<p>Default is <c>true</c>.</p>
</item>
+
+ <marker id="atl_seqno"></marker>
<tag><c><![CDATA[atl_seqno() = true | false <optional>]]></c></tag>
<item>
<p>Specifies if the audit trail log entries will be (sequence)
diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml
index fc8562b638..eec53162a1 100644
--- a/lib/snmp/doc/src/snmp_config.xml
+++ b/lib/snmp/doc/src/snmp_config.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,6 +40,7 @@
<item>starting the application (agent and/or manager)</item>
<item>debugging the application (agent and/or manager)</item>
</list>
+
<p>Refer also to the chapter(s)
<seealso marker="snmp_agent_config_files">Definition of Agent Configuration Files</seealso> and
<seealso marker="snmp_manager_config_files">Definition of Manager Configuration Files</seealso> which contains more detailed information
@@ -73,7 +74,14 @@
</item>
</list>
- <!-- The info below is also found in the snmp_app.xml file -->
+
+ <!--
+ *****************************************************
+
+ The info below is also found in the snmp_app.xml file
+
+ *****************************************************
+ -->
<p>The agent and manager uses (application) configuration parameters to
find out where these directories are located. The parameters should be
@@ -87,6 +95,7 @@
{agent_verbosity, verbosity()} |
{versions, versions()} |
{discovery, agent_discovery()} |
+ {gb_max_vbs, gb_max_vbs()} |
{priority, priority()} |
{multi_threaded, multi_threaded()} |
{db_dir, db_dir()} |
@@ -117,8 +126,10 @@
{def_user_data, def_user_data()}
</pre>
+ <marker id="agent_opts_and_types"></marker>
<p>Agent specific config options and types:</p>
<taglist>
+ <marker id="agent_type"></marker>
<tag><c><![CDATA[agent_type() = master | sub <optional>]]></c></tag>
<item>
<p>If <c>master</c>, one master agent is
@@ -126,6 +137,7 @@
<p>Default is <c>master</c>.</p>
</item>
+ <marker id="agent_disco"></marker>
<tag><c><![CDATA[agent_discovery() = [agent_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_discovery_opt() =
@@ -138,6 +150,7 @@
<p>For defaults see the options in <c>agent_discovery_opt()</c>.</p>
</item>
+ <marker id="agent_term_disco_opts"></marker>
<tag><c><![CDATA[agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_terminating_discovery_opt() =
@@ -155,6 +168,7 @@
</list>
</item>
+ <marker id="agent_orig_disco_opts"></marker>
<tag><c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_originating_discovery_opt() =
@@ -168,6 +182,7 @@
</list>
</item>
+ <marker id="agent_mt"></marker>
<tag><c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, the agent is multi-threaded, with one
@@ -175,11 +190,21 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="agent_data_dir"></marker>
<tag><c><![CDATA[db_dir() = string() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent internal db files are stored.</p>
</item>
+ <marker id="agent_gb_max_vbs"></marker>
+ <tag><c><![CDATA[gb_max_vbs() = pos_integer() | infinity <optional>]]></c></tag>
+ <item>
+ <p>Defines the maximum number of varbinds allowed
+ in a Get-BULK response.</p>
+ <p>Default is <c>1000</c>.</p>
+ </item>
+
+ <marker id="agent_local_db"></marker>
<tag><c><![CDATA[local_db() = [local_db_opt()] <optional>]]></c></tag>
<item>
<p><c>local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}</c></p>
@@ -187,6 +212,7 @@
<p>For defaults see the options in <c>local_db_opt()</c>.</p>
</item>
+ <marker id="agent_ldb_repair"></marker>
<tag><c><![CDATA[agent_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>When starting snmpa_local_db it always tries to open an
@@ -197,6 +223,7 @@
<p>Default is <c>true</c>.</p>
</item>
+ <marker id="agent_ldb_auto_save"></marker>
<tag><c><![CDATA[agent_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
@@ -204,6 +231,7 @@
<p>Default is <c>5000</c>.</p>
</item>
+ <marker id="agent_net_if"></marker>
<tag><c><![CDATA[agent_net_if() = [agent_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() = {module, agent_net_if_module()} |
@@ -214,6 +242,7 @@
<p>For defaults see the options in <c>agent_net_if_opt()</c>.</p>
</item>
+ <marker id="agent_ni_module"></marker>
<tag><c><![CDATA[agent_net_if_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface part for the
@@ -222,6 +251,7 @@
<p>Default is <c>snmpa_net_if</c>.</p>
</item>
+ <marker id="agent_ni_opts"></marker>
<tag><c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() = {bind_to, bind_to()} |
@@ -236,6 +266,14 @@
<p>For defaults see the options in <c>agent_net_if_option()</c>.</p>
</item>
+ <marker id="agent_ni_req_limit"></marker>
+ <tag><c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
+ <item>
+ <p>Max number of simultaneous requests handled by the agent.</p>
+ <p>Default is <c>infinity</c>.</p>
+ </item>
+
+ <marker id="agent_ni_filter_opts"></marker>
<tag><c><![CDATA[agent_net_if_filter_options() = [agent_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c><![CDATA[agent_net_if_filter_option() = {module, agent_net_if_filter_module()}]]></c></p>
@@ -245,6 +283,7 @@
<p>For defaults see the options in <c>agent_net_if_filter_option()</c>.</p>
</item>
+ <marker id="agent_ni_filter_module"></marker>
<tag><c><![CDATA[agent_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
@@ -254,12 +293,7 @@
<p>Default is <c>snmpa_net_if_filter</c>.</p>
</item>
- <tag><c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
- <item>
- <p>Max number of simultaneous requests handled by the agent.</p>
- <p>Default is <c>infinity</c>.</p>
- </item>
-
+ <marker id="agent_mibs"></marker>
<tag><c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) that defines which MIBs
@@ -274,6 +308,7 @@
<p>Default is <c>[]</c>.</p>
</item>
+ <marker id="agent_mib_storage"></marker>
<tag><c><![CDATA[mib_storage() = ets | {ets, Dir} | {ets, Dir, Action} | dets | {dets, Dir} | {dets, Dir, Action} | mnesia | {mnesia, Nodes} | {mnesia, Nodes, Action} <optional>]]></c></tag>
<item>
<p>Specifies how info retrieved from the mibs will be stored.</p>
@@ -299,6 +334,7 @@
mnesia/dets table already exist.</p>
</item>
+ <marker id="agent_mib_server"></marker>
<tag><c><![CDATA[mib_server() = [mib_server_opt()] <optional>]]></c></tag>
<item>
<p><c>mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()}</c></p>
@@ -306,6 +342,7 @@
<p>For defaults see the options in <c>mib_server_opt()</c>.</p>
</item>
+ <marker id="agent_ms_meo"></marker>
<tag><c><![CDATA[mibentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each mib-
@@ -315,6 +352,7 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="agent_ms_teo"></marker>
<tag><c><![CDATA[trapentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each trap
@@ -324,6 +362,7 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="agent_ms_cache"></marker>
<tag><c><![CDATA[mibs_cache() = bool() | mibs_cache_opts() <optional>]]></c></tag>
<item>
<p>Shall the agent utilize the mib server lookup cache or not.</p>
@@ -331,6 +370,7 @@
default values apply).</p>
</item>
+ <marker id="agent_ms_cache_opts"></marker>
<tag><c><![CDATA[mibs_cache_opts() = [mibs_cache_opt()] <optional>]]></c></tag>
<item>
<p><c>mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}</c></p>
@@ -338,6 +378,7 @@
<p>For defaults see the options in <c>mibs_cache_opt()</c>.</p>
</item>
+ <marker id="agent_ms_cache_autogc"></marker>
<tag><c><![CDATA[mibs_cache_autogc() = bool() <optional>]]></c></tag>
<item>
<p>Defines if the mib server shall perform cache gc automatically or
@@ -346,6 +387,7 @@
<p>Default is <c>true</c>.</p>
</item>
+ <marker id="agent_ms_cache_age"></marker>
<tag><c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag>
<item>
<p>Defines how old the entries in the cache will be allowed before
@@ -355,6 +397,7 @@
<p>Default is <c>10 timutes</c>.</p>
</item>
+ <marker id="agent_ms_cache_gclimit"></marker>
<tag><c><![CDATA[mibs_cache_gclimit() = integer() > 0 | infinity <optional>]]></c></tag>
<item>
<p>When performing a GC, this is the max number of cache entries
@@ -365,6 +408,7 @@
<p>Default is <c>100</c>.</p>
</item>
+ <marker id="agent_error_report_mod"></marker>
<tag><c><![CDATA[error_report_mod() = atom() <optional>]]></c></tag>
<item>
<p>Defines an error report module, implementing the
@@ -374,6 +418,7 @@
<p>Default is <c>snmpa_error_logger</c>.</p>
</item>
+ <marker id="agent_symbolic_store"></marker>
<tag><c>symbolic_store() = [symbolic_store_opt()]</c></tag>
<item>
<p><c>symbolic_store_opt() = {verbosity, verbosity()}</c></p>
@@ -381,12 +426,15 @@
<p>For defaults see the options in <c>symbolic_store_opt()</c>.</p>
</item>
+ <marker id="agent_target_cache"></marker>
<tag><c>target_cache() = [target_cache_opt()]</c></tag>
<item>
<p><c>target_cache_opt() = {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent target cache. </p>
<p>For defaults see the options in <c>target_cache_opt()</c>.</p>
</item>
+
+ <marker id="agent_config"></marker>
<tag><c><![CDATA[agent_config() = [agent_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}</c></p>
@@ -394,11 +442,13 @@
<p>For defaults see the options in <c>agent_config_opt()</c>.</p>
</item>
+ <marker id="agent_config_dir"></marker>
<tag><c><![CDATA[agent_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent configuration files are stored.</p>
</item>
+ <marker id="agent_force_load"></marker>
<tag><c><![CDATA[force_load() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c> the configuration files are re-read
@@ -410,14 +460,18 @@
</item>
</taglist>
+ <marker id="manager_opts_and_types"></marker>
<p>Manager specific config options and types:</p>
<taglist>
+ <marker id="manager_server"></marker>
<tag><c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
<item>
<p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the options for the manager server process.</p>
<p>Default is <c>silence</c>.</p>
</item>
+
+ <marker id="manager_server_timeout"></marker>
<tag><c><![CDATA[server_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Asynchroneous request cleanup time. For every requests,
@@ -438,6 +492,7 @@
<p>Default is <c>30000</c>.</p>
</item>
+ <marker id="manager_config"></marker>
<tag><c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}</c></p>
@@ -445,16 +500,19 @@
<p>For defaults see the options in <c>manager_config_opt()</c>.</p>
</item>
+ <marker id="manager_config_dir"></marker>
<tag><c><![CDATA[manager_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager configuration files are stored.</p>
</item>
+ <marker id="manager_config_db_dir"></marker>
<tag><c><![CDATA[manager_db_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager store persistent data.</p>
</item>
+ <marker id="manager_config_repair"></marker>
<tag><c><![CDATA[manager_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>Defines the repair option for the persistent database (if
@@ -462,6 +520,7 @@
<p>Default is <c>true</c>.</p>
</item>
+ <marker id="manager_config_auto_save"></marker>
<tag><c><![CDATA[manager_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
@@ -469,6 +528,7 @@
<p>Default is <c>5000</c>.</p>
</item>
+ <marker id="manager_irb"></marker>
<tag><c><![CDATA[manager_irb() = auto | user | {user, integer()} <optional>]]></c></tag>
<item>
<p>This option defines how the manager will handle the sending of
@@ -498,6 +558,7 @@
<p>Default is <c>auto</c>.</p>
</item>
+ <marker id="manager_mibs"></marker>
<tag><c><![CDATA[manager_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) and defines which MIBs
@@ -505,6 +566,7 @@
<p>Default is <c>[]</c>.</p>
</item>
+ <marker id="manager_net_if"></marker>
<tag><c><![CDATA[manager_net_if() = [manager_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_opt() = {module, manager_net_if_module()} |
@@ -515,6 +577,7 @@
<p>For defaults see the options in <c>manager_net_if_opt()</c>.</p>
</item>
+ <marker id="manager_ni_opts"></marker>
<tag><c><![CDATA[manager_net_if_options() = [manager_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_option() = {bind_to, bind_to()} |
@@ -523,19 +586,21 @@
{no_reuse, no_reuse()} |
{filter, manager_net_if_filter_options()}</c></p>
<p>These options are actually specific to the used module.
- The ones shown here are applicable to the default
- <c>manager_net_if_module()</c>.</p>
+ The ones shown here are applicable to the default
+ <c>manager_net_if_module()</c>. </p>
<p>For defaults see the options in <c>manager_net_if_option()</c>.</p>
</item>
+ <marker id="manager_ni_module"></marker>
<tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
<item>
- <p>Module which handles the network interface part for the
- SNMP manager. Must implement the
- <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour.</p>
- <p>Default is <c>snmpm_net_if</c>.</p>
+ <p>The module which handles the network interface part for the
+ SNMP manager. It must implement the
+ <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour. </p>
+ <p>Default is <c>snmpm_net_if</c>. </p>
</item>
+ <marker id="manager_ni_filter_opts"></marker>
<tag><c><![CDATA[manager_net_if_filter_options() = [manager_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_filter_option() = {module, manager_net_if_filter_module()}</c></p>
@@ -546,6 +611,7 @@
<c>manager_net_if_filter_option()</c>.</p>
</item>
+ <marker id="manager_ni_filter_module"></marker>
<tag><c><![CDATA[manager_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
@@ -554,6 +620,7 @@
<p>Default is <c>snmpm_net_if_filter</c>.</p>
</item>
+ <marker id="manager_def_user_module"></marker>
<tag><c><![CDATA[def_user_module() = atom() <optional>]]></c></tag>
<item>
<p>The module implementing the default user. See the
@@ -561,6 +628,7 @@
<p>Default is <c>snmpm_user_default</c>.</p>
</item>
+ <marker id="manager_def_user_data"></marker>
<tag><c><![CDATA[def_user_data() = term() <optional>]]></c></tag>
<item>
<p>Data for the default user. Passed to the user when calling
@@ -569,8 +637,10 @@
</item>
</taglist>
+ <marker id="common_types"></marker>
<p>Common config types:</p>
<taglist>
+ <marker id="restart_type"></marker>
<tag><c>restart_type() = permanent | transient | temporary</c></tag>
<item>
<p>See <seealso marker="stdlib:supervisor#child_spec">supervisor</seealso>
@@ -579,6 +649,7 @@
for the manager.</p>
</item>
+ <marker id="db_init_error"></marker>
<tag><c>db_init_error() = terminate | create</c></tag>
<item>
<p>Defines what to do if the agent is unable to open an
@@ -588,12 +659,14 @@
<p>Default is <c>terminate</c>.</p>
</item>
+ <marker id="prio"></marker>
<tag><c><![CDATA[priority() = atom() <optional>]]></c></tag>
<item>
<p>Defines the Erlang priority for all SNMP processes.</p>
<p>Default is <c>normal</c>.</p>
</item>
+ <marker id="versions"></marker>
<tag><c><![CDATA[versions() = [version()] <optional>]]></c></tag>
<item>
<p><c>version() = v1 | v2 | v3</c></p>
@@ -601,6 +674,7 @@
<p>Default is <c>[v1,v2,v3]</c>.</p>
</item>
+ <marker id="verbosity"></marker>
<tag><c><![CDATA[verbosity() = silence | info | log | debug | trace <optional>]]></c></tag>
<item>
<p>Verbosity for a SNMP process. This specifies now much debug info
@@ -608,6 +682,7 @@
<p>Default is <c>silence</c>.</p>
</item>
+ <marker id="bind_to"></marker>
<tag><c><![CDATA[bind_to() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if binds to the IP address.
@@ -616,6 +691,7 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="no_reuse"></marker>
<tag><c><![CDATA[no_reuse() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if does not specify that the IP
@@ -624,17 +700,21 @@
<p>Default is <c>false</c>.</p>
</item>
+ <marker id="recbuf"></marker>
<tag><c><![CDATA[recbuf() = integer() <optional>]]></c></tag>
<item>
<p>Receive buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
+
+ <marker id="sndbuf"></marker>
<tag><c><![CDATA[sndbuf() = integer() <optional>]]></c></tag>
<item>
<p>Send buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
+ <marker id="note_store"></marker>
<tag><c><![CDATA[note_store() = [note_store_opt()] <optional>]]></c></tag>
<item>
<p><c>note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}</c></p>
@@ -642,6 +722,7 @@
<p>For defaults see the options in <c>note_store_opt()</c>.</p>
</item>
+ <marker id="ns_timeout"></marker>
<tag><c><![CDATA[note_store_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Note cleanup time. When storing a note in the note store,
@@ -649,10 +730,9 @@
process performs a GC to remove the expired note's. Time in
milli-seconds.</p>
<p>Default is <c>30000</c>.</p>
-
- <marker id="audit_trail_log"></marker>
</item>
+ <marker id="audit_trail_log"></marker>
<tag><c><![CDATA[audit_trail_log() [audit_trail_log_opt()] <optional>]]></c></tag>
<item>
<p><c>audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}</c></p>
@@ -663,6 +743,7 @@
<p>If not present, audit trail logging is not used.</p>
</item>
+ <marker id="atl_type"></marker>
<tag><c><![CDATA[atl_type() = read | write | read_write <optional>]]></c></tag>
<item>
<p>Specifies what type of an audit trail log should be used.
@@ -684,6 +765,7 @@
<p>Default is <c>read_write</c>.</p>
</item>
+ <marker id="atl_dir"></marker>
<tag><c><![CDATA[atl_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Specifies where the audit trail log should be stored.</p>
@@ -691,6 +773,7 @@
place, this parameter <em>must</em> be defined.</p>
</item>
+ <marker id="atl_size"></marker>
<tag><c><![CDATA[atl_size() = {integer(), integer()} <mandatory>]]></c></tag>
<item>
<p>Specifies the size of the audit
@@ -699,6 +782,7 @@
take place, this parameter <em>must</em> be defined.</p>
</item>
+ <marker id="atl_repair"></marker>
<tag><c><![CDATA[atl_repair() = true | false | truncate | snmp_repair <optional>]]></c></tag>
<item>
<p>Specifies if and how the audit trail log shall be repaired
@@ -710,6 +794,8 @@
analysis.</p>
<p>Default is <c>true</c>.</p>
</item>
+
+ <marker id="atl_seqno"></marker>
<tag><c><![CDATA[atl_seqno() = true | false <optional>]]></c></tag>
<item>
<p>Specifies if the audit trail log entries will be (sequence)
@@ -877,7 +963,8 @@ Manager snmp config:
7b. User name? hobbes
7c. Security name? [hobbes]
7d. Authentication protocol (no/sha/md5)? [no] sha
-7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
+7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
+ 17,18,19,20]
7d. Priv protocol (no/des/aes)? [no] des
7f Priv [des] key (length 0 or 16)? [""] 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
7. Configure an usm user handled by this manager (y/n)? [y] n
diff --git a/lib/snmp/doc/src/snmp_generic.xml b/lib/snmp/doc/src/snmp_generic.xml
index 77f3cefaa2..79a22323d9 100644
--- a/lib/snmp/doc/src/snmp_generic.xml
+++ b/lib/snmp/doc/src/snmp_generic.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>1996</year><year>2009</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,15 +34,16 @@
<module>snmp_generic</module>
<modulesummary>Generic Functions for Implementing SNMP Objects in a Database</modulesummary>
<description>
- <p>The module <c>snmp_generic</c> contains generic functions for implementing tables
- (and variables) using the SNMP built-in database or Mnesia. These
- default functions are used if no instrumentation function is
- provided for a managed object in a MIB. Sometimes, it might be
- necessary to customize the behaviour of the default functions. For
- example, in some situations a trap should be sent if a row is
- deleted or modified, or some hardware is to be informed, when
- information is changed.
- </p>
+ <marker id="description"></marker>
+ <p>The module <c>snmp_generic</c> contains generic functions for
+ implementing tables (and variables) using the SNMP built-in database
+ or Mnesia. These default functions are used if no instrumentation
+ function is provided for a managed object in a MIB. Sometimes,
+ it might be necessary to customize the behaviour of the default
+ functions. For example, in some situations a trap should be sent
+ if a row is deleted or modified, or some hardware is to be informed,
+ when information is changed. </p>
+
<p>The overall structure is shown in the following figure:</p>
<pre>
+---------------+
@@ -93,6 +94,7 @@
</description>
<section>
+ <marker id="data_types"></marker>
<title>DATA TYPES</title>
<p>In the functions defined below, the following types are used:</p>
<code type="none">
@@ -118,7 +120,10 @@ value() = term()
case of a <c>set</c> operation. </p>
</item>
</taglist>
+
+ <marker id="get_status_col2"></marker>
</section>
+
<funcs>
<func>
<name>get_status_col(Name, Cols)</name>
@@ -136,8 +141,11 @@ value() = term()
<p>This function can be used in instrumentation functions for
<c>is_set_ok</c>, <c>undo</c> or <c>set</c> to check if the
status column of a table is modified.</p>
+
+ <marker id="get_index_types"></marker>
</desc>
</func>
+
<func>
<name>get_index_types(Name)</name>
<fsummary>Get the index types of <c>Name</c></fsummary>
@@ -147,9 +155,36 @@ value() = term()
<desc>
<p>Gets the index types of <c>Name</c></p>
<p>This function can be used in instrumentation functions to
- retrieve the index types part of the table info.</p>
+ retrieve the index types part of the table info.</p>
+
+ <marker id="get_table_info"></marker>
</desc>
</func>
+
+ <func>
+ <name>get_table_info(Name, Item) -> table_info_result()</name>
+ <fsummary>Get table info item of MIB table <c>Name</c></fsummary>
+ <type>
+ <v>Name = name()</v>
+ <v>Item = table_item() | all</v>
+ <v>table_item() = nbr_of_cols | defvals | status_col | not_accessible |
+ index_types | first_accessible | first_own_index</v>
+ <v>table_info_result() = Value | [{table_item(), Value}]</v>
+ <v>Value = term()</v>
+ </type>
+ <desc>
+ <p>Get a specific table info item or, if <c>Item</c> has the
+ value <c>all</c>, a two tuple list (property list) is instead
+ returned with all the items and their respctive values of the
+ given table. </p>
+
+ <p>This function can be used in instrumentation functions to
+ retrieve a given part of the table info.</p>
+
+ <marker id="table_func"></marker>
+ </desc>
+ </func>
+
<func>
<name>table_func(Op1, NameDb)</name>
<name>table_func(Op2, RowIndex, Cols, NameDb) -> Ret</name>
@@ -190,8 +225,11 @@ value() = term()
<p>The function returns according to the specification of an
instrumentation function.
</p>
+
+ <marker id="table_get_elements"></marker>
</desc>
</func>
+
<func>
<name>table_get_elements(NameDb, RowIndex, Cols) -> Values</name>
<fsummary>Get elements in a table row</fsummary>
@@ -204,8 +242,11 @@ value() = term()
<desc>
<p>Returns a list with values for all columns in <c>Cols</c>.
If a column is undefined, its value is <c>noinit</c>.</p>
+
+ <marker id="table_next"></marker>
</desc>
</func>
+
<func>
<name>table_next(NameDb, RestOid) -> RowIndex | endOfTable</name>
<fsummary>Find the next row in the table</fsummary>
@@ -217,8 +258,11 @@ value() = term()
<desc>
<p>Finds the indices of the next row in the table. <c>RestOid</c>
does not have to specify an existing row.</p>
+
+ <marker id="table_row_exists"></marker>
</desc>
</func>
+
<func>
<name>table_row_exists(NameDb, RowIndex) -> bool()</name>
<fsummary>Check if a row in a table exists</fsummary>
@@ -228,8 +272,11 @@ value() = term()
</type>
<desc>
<p>Checks if a row in a table exists.</p>
+
+ <marker id="table_set_elements"></marker>
</desc>
</func>
+
<func>
<name>table_set_elements(NameDb, RowIndex, Cols) -> bool()</name>
<fsummary>Set elements in a table row</fsummary>
@@ -246,8 +293,11 @@ value() = term()
<c>mnesia:write</c> to store the values. This means that
this function must be called from within a transaction
(<c>mnesia:transaction/1</c> or <c>mnesia:dirty/1</c>).</p>
+
+ <marker id="variable_func"></marker>
</desc>
</func>
+
<func>
<name>variable_func(Op1, NameDb)</name>
<name>variable_func(Op2, Val, NameDb) -> Ret</name>
@@ -268,8 +318,11 @@ value() = term()
the database. </p>
<p>The function returns according to the specification of an
instrumentation function. </p>
+
+ <marker id="variable_get"></marker>
</desc>
</func>
+
<func>
<name>variable_get(NameDb) -> {value, Value} | undefined</name>
<fsummary>Get the value of a variable</fsummary>
@@ -279,8 +332,11 @@ value() = term()
</type>
<desc>
<p>Gets the value of a variable.</p>
+
+ <marker id="variable_set"></marker>
</desc>
</func>
+
<func>
<name>variable_set(NameDb, NewVal) -> true | false</name>
<fsummary>Set a value for a variable</fsummary>
@@ -299,6 +355,7 @@ value() = term()
</funcs>
<section>
+ <marker id="example"></marker>
<title>Example</title>
<p>The following example shows an implementation of a table which is
stored in Mnesia, but with some checks performed at set-request
diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml
index 2738ca76c1..169e20d10b 100644
--- a/lib/snmp/doc/src/snmp_manager_netif.xml
+++ b/lib/snmp/doc/src/snmp_manager_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>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,31 +35,34 @@
<image file="snmp_manager_netif_1.gif">
<icaption>The Purpose of Manager Net if</icaption>
</image>
+
<p>The Network Interface (Net if) process delivers SNMP PDUs to the
- manager server, and receives SNMP PDUs from the manager server.
- The most common behaviour of a Net if process is that is receives
- request PDU from the manager server, encodes the PDU into bytes
- and transmits the bytes onto the network to an agent. When the
- reply from the agent is received by the Net if process, which it
- decodes into an SNMP PDU, which it sends to the manager server.
- </p>
+ manager server, and receives SNMP PDUs from the manager server.
+ The most common behaviour of a Net if process is that is receives
+ request PDU from the manager server, encodes the PDU into bytes
+ and transmits the bytes onto the network to an agent. When the
+ reply from the agent is received by the Net if process, which it
+ decodes into an SNMP PDU, which it sends to the manager server. </p>
+
<p>However, that simple behaviour can be modified in numerous
- ways. For example, the Net if process can apply some kind of
- encrypting/decrypting scheme on the bytes.
- </p>
- <p>It is also possible to write your own Net if process. The default
- Net if process is implemented in the module <c>snmpm_net_if</c> and
- it uses UDP as the transport protocol.
- </p>
- <p>This section describes how to write a Net if process.
- </p>
+ ways. For example, the Net if process can apply some kind of
+ encrypting/decrypting scheme on the bytes. </p>
+
+ <p>The snmp application provides two different modules,
+ <c>snmpm_net_if</c> (the default) and <c>snmpm_net_if_mt</c>,
+ both uses the UDP as the transport protocol. The difference
+ between the two modules is that the latter is "multi-threaded",
+ i.e. for each message/request a new process is created that
+ process the message/request and then exits. </p>
+
+ <p>It is also possible to write your own Net if process,
+ this section describes how to write a Net if processdo that.</p>
<section>
<marker id="mandatory_functions"></marker>
<title>Mandatory Functions</title>
<p>A Net if process must implement the SNMP manager
- <seealso marker="snmpm_network_interface">network interface behaviour</seealso>.
- </p>
+ <seealso marker="snmpm_network_interface">network interface behaviour</seealso>. </p>
</section>
<section>
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index 27d89ea4e3..86fde03205 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2011</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -198,12 +198,18 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<type>
<v>BackupDir = string()</v>
<v>Agent = pid() | atom()</v>
+ <v>Reason = backup_in_progress | term()</v>
</type>
<desc>
<p>Backup persistent/permanent data handled by the agent
(such as local-db, mib-data and vacm). </p>
<p>Data stored by mnesia is not handled. </p>
<p>BackupDir cannot be identical to DbDir. </p>
+ <p>Simultaneous backup calls are <em>not</em> allowed.
+ That is, two different processes cannot simultaneously
+ successfully call this function. One of them will be first,
+ and succeed. The second will fail with the error reason
+ <c>backup_in_progress</c>. </p>
<marker id="info"></marker>
</desc>
@@ -217,13 +223,13 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</type>
<desc>
<p>Returns a list (a dictionary) containing information about
- the agent. Information includes loaded MIBs, registered
- sub-agents, some information about the memory allocation. </p>
- <p>As of version 4.4 the format of the info has been changed.
- To convert the info to the old format, call the
- <seealso marker="#old_info_format">old_info_format</seealso>
- function. </p>
-
+ the agent. Information includes loaded MIBs, registered
+ sub-agents, some information about the memory allocation. </p>
+ <p>As of version 4.4 the format of the info has been changed.
+ To convert the info to the old format, call the
+ <seealso marker="#old_info_format">old_info_format</seealso>
+ function. </p>
+
<marker id="old_info_format"></marker>
</desc>
</func>
@@ -495,6 +501,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
+ <name>log_to_txt(LogDir)</name>
<name>log_to_txt(LogDir, Mibs)</name>
<name>log_to_txt(LogDir, Mibs, OutFile) -> ok | {error, Reason}</name>
<name>log_to_txt(LogDir, Mibs, OutFile, LogName) -> ok | {error, Reason}</name>
@@ -522,6 +529,37 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso>
for more info.</p>
+ <marker id="log_to_io"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
+ <fsummary>Convert an Audit Trail Log to text format</fsummary>
+ <type>
+ <v>LogDir = string()</v>
+ <v>Mibs = [MibName]</v>
+ <v>MibName = string()</v>
+ <v>LogName = string()</v>
+ <v>LogFile = string()</v>
+ <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Reason = disk_log_open_error() | file_open_error() | term()</v>
+ <v>disk_log_open_error() = {LogName, term()}</v>
+ <v>file_open_error() = {OutFile, term()}</v>
+ </type>
+ <desc>
+ <p>Converts an Audit Trail Log to a readable format and
+ prints it on stdio.
+ <c>LogName</c> defaults to "snmpa_log".
+ <c>LogFile</c> defaults to "snmpa.log".
+ See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
+ for more info.</p>
+
<marker id="change_log_size"></marker>
</desc>
</func>
diff --git a/lib/snmp/doc/src/snmpa_network_interface_filter.xml b/lib/snmp/doc/src/snmpa_network_interface_filter.xml
index 10419517dd..84953c5270 100644
--- a/lib/snmp/doc/src/snmpa_network_interface_filter.xml
+++ b/lib/snmp/doc/src/snmpa_network_interface_filter.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -84,7 +84,9 @@
<title>DATA TYPES</title>
<code type="none">
port() = integer() > 0
-pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report
+pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
+ 'set-request' | trap | 'get-bulk-request' | 'inform-request' |
+ report
</code>
<marker id="accept_recv"></marker>
</section>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index c36a1b2a24..8ab3be8e18 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2011</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -173,16 +173,16 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
</type>
<desc>
<p>Register the manager entity (=user) responsible for specific
- agent(s). </p>
+ agent(s). </p>
<p><c>Module</c> is the callback module (snmpm_user behaviour) which
- will be called whenever something happens (detected
- agent, incoming reply or incoming trap/notification).
- Note that this could have already been done as a
- consequence of the node config. (see users.conf).</p>
+ will be called whenever something happens (detected
+ agent, incoming reply or incoming trap/notification).
+ Note that this could have already been done as a
+ consequence of the node config. (see users.conf).</p>
- <p>The argument <c>DefaultAgentConfig</c> is used as default values when
- this user register agents.</p>
+ <p>The argument <c>DefaultAgentConfig</c> is used as default
+ values when this user register agents.</p>
<p>The type of <c>Val</c> depends on <c>Item</c>: </p>
<code type="none"><![CDATA[
@@ -1237,6 +1237,38 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso>
for more info.</p>
+ <marker id="log_to_io"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
+ <fsummary>Convert an Audit Trail Log to text format</fsummary>
+ <type>
+ <v>LogDir = string()</v>
+ <v>Mibs = [MibName]</v>
+ <v>MibName = string()</v>
+ <v>LogName = string()</v>
+ <v>LogFile = string()</v>
+ <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Reason = disk_log_open_error() | file_open_error() | term()</v>
+ <v>disk_log_open_error() = {LogName, term()}</v>
+ <v>file_open_error() = {OutFile, term()}</v>
+ </type>
+ <desc>
+ <p>Converts an Audit Trail Log to a readable format and
+ prints it on stdio.
+ <c>LogName</c> defaults to "snmpm_log".
+ <c>LogFile</c> defaults to "snmpm.log".
+ See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
+ for more info.</p>
+
<marker id="change_log_size"></marker>
</desc>
</func>
diff --git a/lib/snmp/doc/src/snmpm_network_interface_filter.xml b/lib/snmp/doc/src/snmpm_network_interface_filter.xml
index ea1e183848..4dc133dd71 100644
--- a/lib/snmp/doc/src/snmpm_network_interface_filter.xml
+++ b/lib/snmp/doc/src/snmpm_network_interface_filter.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>2009</year>
+ <year>2007</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -72,16 +72,19 @@
</list>
<p>Note that the network interface filter is something which is used
by the network interface implementation provided by the application
- (<c>snmpm_net_if</c>). The default filter accepts all messages.</p>
+ (<c>snmpm_net_if</c> and <c>snmpm_net_if_mt</c>).
+ The default filter accepts all messages.</p>
<p>A network interface filter can e.g. be used during testing or for load
- regulation. </p>
+ regulation. </p>
</description>
<section>
<title>DATA TYPES</title>
<code type="none">
port() = integer() > 0
-pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report | trappdu
+pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
+ 'set-request' | trap | 'get-bulk-request' | 'inform-request' |
+ report | trappdu
</code>
<marker id="accept_recv"></marker>
</section>
diff --git a/lib/snmp/examples/ex1/Makefile b/lib/snmp/examples/ex1/Makefile
index 1a55ba0470..996b686e0e 100644
--- a/lib/snmp/examples/ex1/Makefile
+++ b/lib/snmp/examples/ex1/Makefile
@@ -46,7 +46,7 @@ ERL_COMPILE_FLAGS += -I../include \
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN)
-EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
+EXAMPLE_RELSYSDIR = "$(RELSYSDIR)/examples"
EX1_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/ex1
# ----------------------------------------------------
diff --git a/lib/snmp/examples/ex2/Makefile b/lib/snmp/examples/ex2/Makefile
index 7fbd7f530b..090b9274d4 100644
--- a/lib/snmp/examples/ex2/Makefile
+++ b/lib/snmp/examples/ex2/Makefile
@@ -47,7 +47,7 @@ ERL_COMPILE_FLAGS += -I../include \
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN)
-EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
+EXAMPLE_RELSYSDIR = "$(RELSYSDIR)/examples"
EX2_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/ex2
# ----------------------------------------------------
diff --git a/lib/snmp/examples/ex2/snmp_ex2_manager.erl b/lib/snmp/examples/ex2/snmp_ex2_manager.erl
index ff873327bc..1b247d713d 100644
--- a/lib/snmp/examples/ex2/snmp_ex2_manager.erl
+++ b/lib/snmp/examples/ex2/snmp_ex2_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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 @@
%% Manager callback API:
-export([handle_error/3,
- handle_agent/4,
+ handle_agent/5,
handle_pdu/4,
handle_trap/3,
handle_inform/3,
@@ -265,16 +265,17 @@ handle_snmp_callback(handle_error, {ReqId, Reason}) ->
"~n Reason: ~p"
"~n", [ReqId, Reason]),
ok;
-handle_snmp_callback(handle_agent, {Addr, Port, SnmpInfo}) ->
+handle_snmp_callback(handle_agent, {Addr, Port, Type, SnmpInfo}) ->
{ES, EI, VBs} = SnmpInfo,
io:format("*** UNKNOWN AGENT ***"
"~n Address: ~p"
"~n Port: ~p"
+ "~n Type: ~p"
"~n SNMP Info: "
"~n Error Status: ~w"
"~n Error Index: ~w"
"~n Varbinds: ~p"
- "~n", [Addr, Port, ES, EI, VBs]),
+ "~n", [Addr, Port, Type, ES, EI, VBs]),
ok;
handle_snmp_callback(handle_pdu, {TargetName, ReqId, SnmpResponse}) ->
{ES, EI, VBs} = SnmpResponse,
@@ -382,8 +383,8 @@ handle_error(ReqId, Reason, Server) when is_pid(Server) ->
ignore.
-handle_agent(Addr, Port, SnmpInfo, Server) when is_pid(Server) ->
- report_callback(Server, handle_agent, {Addr, Port, SnmpInfo}),
+handle_agent(Addr, Port, Type, SnmpInfo, Server) when is_pid(Server) ->
+ report_callback(Server, handle_agent, {Addr, Port, Type, SnmpInfo}),
ignore.
diff --git a/lib/snmp/include/snmp_types.hrl b/lib/snmp/include/snmp_types.hrl
index 4adb24361c..399379a49b 100644
--- a/lib/snmp/include/snmp_types.hrl
+++ b/lib/snmp/include/snmp_types.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,23 +78,36 @@
%%-----------------------------------------------------------------
%% TableInfo - stored in snmp_symbolic_store for use by the
-%% generic table functions.
+%% generic table functions. For an ordinary table, the
+%% types will be the following:
%% nbr_of_cols is an integer
+%% pos_integer()
%% defvals is a list of {Col, Defval}, ordered by column
%% number
+%% [{Col :: integer(), Defval :: term()}]
%% status_col is an integer
+%% pos_integer()
%% not_accessible a sorted list of columns (> first_accessible)
%% that are 'not-accessible'
-%% indextypes is a list of #asn1_type for the index-columns,
-%% ordered by column number
-%% first_accessible is an integer, the first non-accessible
-%% column
+%% [pos_integer()]
+%% index_types is a list of #asn1_type for the index-columns,
+%% ordered by column number or an "augment"-tuple
+%% [asn1_type()]
+%% first_accessible is an integer, the first accessible column
+%% pos_integer()
%% first_own_index is an integer. 0 if there is no such index for
%% this table.
%% This is not the same as the last integer in the oid!
%% Example: If a table has one own index (oid.1), one
%% column (oid.2) and one imported index then
%% first_own_index will be 2.
+%% non_neg_integer()
+%% For a augmented table, it will instead look like this:
+%% index_types {augments, {atom(), asn1_type()}}
+%% nbr_of_cols pos_integer()
+%% not_accessible [pos_integer()]
+%% first_accessible pos_integer()
+%%
%%-----------------------------------------------------------------
-record(table_info,
@@ -192,7 +205,7 @@
%%----------------------------------------------------------------------
-record(mib,
{misc = [],
- mib_format_version = "3.2",
+ mib_format_version = "3.3",
name = "",
module_identity, %% Not in SMIv1, and only with +module_identity
mes = [],
diff --git a/lib/snmp/mibs/Makefile.in b/lib/snmp/mibs/Makefile.in
index 993a67c6f2..c74c0b2ac4 100644
--- a/lib/snmp/mibs/Makefile.in
+++ b/lib/snmp/mibs/Makefile.in
@@ -211,7 +211,7 @@ info:
@echo ""
@echo "SNMP_VSN = $(SNMP_VSN)"
@echo "VSN = $(VSN)"
- @echo "RELSYSDIR = $(RELSYSDIR)"
+ @echo "RELSYSDIR = "$(RELSYSDIR)""
v1/%.mib.v1: %.mib $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1
$(ERL_TOP)/lib/snmp/bin/snmp-v2tov1 -o $@ $<
@@ -223,17 +223,17 @@ v1/%.mib.v1: %.mib $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/mibs
- $(INSTALL_DIR) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DATA) $(MIB_FILES) $(RELSYSDIR)/mibs
- $(INSTALL_DATA) $(STD_v2_MIB_FILES) $(RELSYSDIR)/mibs
- $(INSTALL_DATA) $(FUNCS_FILES) $(RELSYSDIR)/mibs
- $(INSTALL_DATA) $(STD_v1_MIB_FILES) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DATA) $(V1_MIB_FILES) $(RELSYSDIR)/mibs/v1
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/priv/mibs
- $(INSTALL_DATA) $(BIN_TARGETS) $(RELSYSDIR)/priv/mibs
+ $(INSTALL_DIR) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DIR) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DATA) $(MIB_FILES) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DATA) $(STD_v2_MIB_FILES) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DATA) $(FUNCS_FILES) "$(RELSYSDIR)/mibs"
+ $(INSTALL_DATA) $(STD_v1_MIB_FILES) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DATA) $(V1_MIB_FILES) "$(RELSYSDIR)/mibs/v1"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/mibs"
+ $(INSTALL_DATA) $(BIN_TARGETS) "$(RELSYSDIR)/priv/mibs"
release_docs_spec:
diff --git a/lib/snmp/priv/conf/agent/Makefile b/lib/snmp/priv/conf/agent/Makefile
index ee3a915c2b..c7921bacc2 100644
--- a/lib/snmp/priv/conf/agent/Makefile
+++ b/lib/snmp/priv/conf/agent/Makefile
@@ -55,9 +55,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/conf
- $(INSTALL_DIR) $(RELSYSDIR)/priv/conf/agent
- $(INSTALL_DATA) $(CONF_FILES) $(RELSYSDIR)/priv/conf/agent
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/conf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/conf/agent"
+ $(INSTALL_DATA) $(CONF_FILES) "$(RELSYSDIR)/priv/conf/agent"
release_docs_spec:
diff --git a/lib/snmp/priv/conf/manager/Makefile b/lib/snmp/priv/conf/manager/Makefile
index 16355f0ff3..ba5a74c3fe 100644
--- a/lib/snmp/priv/conf/manager/Makefile
+++ b/lib/snmp/priv/conf/manager/Makefile
@@ -55,9 +55,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/conf
- $(INSTALL_DIR) $(RELSYSDIR)/priv/conf/manager
- $(INSTALL_DATA) $(CONF_FILES) $(RELSYSDIR)/priv/conf/manager
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/conf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/conf/manager"
+ $(INSTALL_DATA) $(CONF_FILES) "$(RELSYSDIR)/priv/conf/manager"
release_docs_spec:
diff --git a/lib/snmp/priv/plt/.gitignore b/lib/snmp/priv/plt/.gitignore
new file mode 100644
index 0000000000..174481f561
--- /dev/null
+++ b/lib/snmp/priv/plt/.gitignore
@@ -0,0 +1,3 @@
+/*.plt
+/*.dialyzer_analysis
+
diff --git a/lib/snmp/src/agent/Makefile b/lib/snmp/src/agent/Makefile
index a67fe4d17c..9a982edf91 100644
--- a/lib/snmp/src/agent/Makefile
+++ b/lib/snmp/src/agent/Makefile
@@ -128,14 +128,14 @@ info:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/agent
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/agent
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/agent"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src/agent"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
- $(RELSYSDIR)/ebin
-# $(INSTALL_DIR) $(RELSYSDIR)/include
-# $(INSTALL_DATA) $(EXT_HRL_FILES) $(RELSYSDIR)/include
+ "$(RELSYSDIR)/ebin"
+# $(INSTALL_DIR) "$(RELSYSDIR)/include"
+# $(INSTALL_DATA) $(EXT_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/snmp/src/agent/depend.mk b/lib/snmp/src/agent/depend.mk
index bc39e1fa35..ea9261e266 100644
--- a/lib/snmp/src/agent/depend.mk
+++ b/lib/snmp/src/agent/depend.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The 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 @@ $(EBIN)/snmpa_acm.$(EMULATOR): \
$(EBIN)/snmpa_agent.$(EMULATOR): \
snmpa_agent.erl \
+ snmpa_internal.hrl \
../misc/snmp_debug.hrl \
../misc/snmp_verbosity.hrl \
../../include/snmp_types.hrl
@@ -136,6 +137,7 @@ $(EBIN)/snmpa_set_lib.$(EMULATOR): \
$(EBIN)/snmpa_supervisor.$(EMULATOR): \
snmpa_supervisor.erl \
+ snmpa_internal.hrl \
../misc/snmp_debug.hrl \
../misc/snmp_verbosity.hrl
diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl
index 77307aa7ad..7bdd500727 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,7 @@
-export([add_community/5, add_community/6, delete_community/1]).
-export([check_community/1]).
+-include("snmpa_internal.hrl").
-include("SNMP-COMMUNITY-MIB.hrl").
-include("SNMP-TARGET-MIB.hrl").
-include("SNMPv2-TC.hrl").
@@ -120,10 +121,17 @@ init_tabs(Comms) ->
read_community_config_files(Dir) ->
?vdebug("read community config file",[]),
- Gen = fun(_) -> ok end,
- Filter = fun(Comms) -> Comms end,
- Check = fun(Entry) -> check_community(Entry) end,
- [Comms] =
+ FileName = "community.conf",
+ Gen = fun(D, Reason) ->
+ warning_msg("failed reading config file ~s"
+ "~n Config Dir: ~s"
+ "~n Reason: ~p",
+ [FileName, D, Reason]),
+ ok
+ end,
+ Filter = fun(Comms) -> Comms end,
+ Check = fun(Entry) -> check_community(Entry) end,
+ [Comms] =
snmp_conf:read_files(Dir, [{Gen, Filter, Check, "community.conf"}]),
Comms.
@@ -601,5 +609,8 @@ set_sname(_) -> %% Keep it, if already set.
error(Reason) ->
throw({error, Reason}).
+warning_msg(F, A) ->
+ ?snmpa_warning("[COMMUNITY-MIB]: " ++ F, A).
+
config_err(F, A) ->
snmpa_error:config_err("[COMMUNITY-MIB]: " ++ F, A).
diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl
index 0d7866d94d..cc191bd956 100644
--- a/lib/snmp/src/agent/snmp_framework_mib.erl
+++ b/lib/snmp/src/agent/snmp_framework_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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 @@ do_configure(Dir) ->
read_internal_config_files(Dir) ->
?vdebug("read context config file",[]),
- Gen = fun(D) -> convert_context(D) end,
+ Gen = fun(D, Reason) ->
+ convert_context(D, Reason)
+ end,
Filter = fun(Contexts) -> Contexts end,
Check = fun(Entry) -> check_context(Entry) end,
[Ctxs] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "context.conf"}]),
@@ -123,10 +125,17 @@ read_internal_config_files(Dir) ->
read_agent(Dir) ->
- ?vdebug("read agent config file",[]),
- Check = fun(Entry) -> check_agent(Entry) end,
- File = filename:join(Dir, "agent.conf"),
- Agent = snmp_conf:read(File, Check),
+ ?vdebug("read agent config file", []),
+ FileName = "agent.conf",
+ Check = fun(Entry) -> check_agent(Entry) end,
+ File = filename:join(Dir, FileName),
+ Agent =
+ try
+ snmp_conf:read(File, Check)
+ catch
+ throw:{error, Reason} ->
+ error({failed_reading_config_file, Dir, FileName, Reason})
+ end,
sort_agent(Agent).
@@ -146,9 +155,9 @@ sort_agent(L) ->
%%-----------------------------------------------------------------
%% Generate a context.conf file.
%%-----------------------------------------------------------------
-convert_context(Dir) ->
+convert_context(Dir, _Reason) ->
config_err("missing context.conf file => generating a default file", []),
- File = filename:join(Dir,"context.conf"),
+ File = filename:join(Dir, "context.conf"),
case file:open(File, [write]) of
{ok, Fid} ->
ok = io:format(Fid, "~s\n", [context_header()]),
@@ -165,7 +174,7 @@ context_header() ->
io_lib:format("%% This file was automatically generated by "
"snmp_config v~s ~w-~2.2.0w-~2.2.0w "
"~2.2.0w:~2.2.0w:~2.2.0w\n",
- [?version,Y,Mo,D,H,Mi,S]).
+ [?version, Y, Mo, D, H, Mi, S]).
%%-----------------------------------------------------------------
diff --git a/lib/snmp/src/agent/snmp_generic_mnesia.erl b/lib/snmp/src/agent/snmp_generic_mnesia.erl
index a73aad5b33..7fd6501977 100644
--- a/lib/snmp/src/agent/snmp_generic_mnesia.erl
+++ b/lib/snmp/src/agent/snmp_generic_mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -121,7 +121,7 @@ table_func(set, RowIndex, Cols, Name) ->
fun() ->
snmp_generic:table_set_row(
{Name, mnesia}, nofunc,
- {snmp_generic_mnesia, table_try_make_consistent},
+ fun table_try_make_consistent/2,
RowIndex, Cols)
end) of
{atomic, Value} ->
@@ -368,7 +368,8 @@ table_set_elements(Name, RowIndex, Cols) ->
_ -> false
end.
table_set_elements(Name, RowIndex, Cols, ConsFunc) ->
- #table_info{index_types = Indexes, first_own_index = FirstOwnIndex} =
+ #table_info{index_types = Indexes,
+ first_own_index = FirstOwnIndex} =
snmp_generic:table_info(Name),
AddCol = if
FirstOwnIndex == 0 -> 2;
diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl
index 720ac749b8..37e09f5d3e 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -27,6 +27,7 @@
-export([add_notify/3, delete_notify/1]).
-export([check_notify/1]).
+-include("snmpa_internal.hrl").
-include("SNMP-NOTIFICATION-MIB.hrl").
-include("SNMPv2-TC.hrl").
-include("snmp_tables.hrl").
@@ -104,7 +105,14 @@ do_reconfigure(Dir) ->
read_notify_config_files(Dir) ->
?vdebug("read notify config file",[]),
- Gen = fun(_) -> ok end,
+ FileName = "notify.conf",
+ Gen = fun(D, Reason) ->
+ info_msg("failed reading config file ~s"
+ "~n Config Dir: ~s"
+ "~n Reason: ~p",
+ [FileName, D, Reason]),
+ ok
+ end,
Filter = fun(Notifs) -> Notifs end,
Check = fun(Entry) -> check_notify(Entry) end,
[Notifs] =
@@ -112,7 +120,7 @@ read_notify_config_files(Dir) ->
Notifs.
check_notify({Name, Tag, Type}) ->
- snmp_conf:check_string(Name,{gt,0}),
+ snmp_conf:check_string(Name, {gt, 0}),
snmp_conf:check_string(Tag),
{ok, Val} = snmp_conf:check_atom(Type, [{trap, 1}, {inform, 2}]),
Notify = {Name, Tag, Val,
@@ -451,12 +459,15 @@ set_sname() ->
set_sname(get(sname)).
set_sname(undefined) ->
- put(sname,conf);
+ put(sname, conf);
set_sname(_) -> %% Keep it, if already set.
ok.
error(Reason) ->
throw({error, Reason}).
+info_msg(F, A) ->
+ ?snmpa_info("[NOTIFICATION-MIB]: " ++ F, A).
+
config_err(F, A) ->
snmpa_error:config_err("[NOTIFICATION-MIB]: " ++ F, A).
diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl
index b6834d278c..766b75022b 100644
--- a/lib/snmp/src/agent/snmp_standard_mib.erl
+++ b/lib/snmp/src/agent/snmp_standard_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -143,20 +143,35 @@ do_reconfigure(Dir) ->
%% Func: read_standard/1
%% Args: Dir is the directory with trailing dir_separator where
%% the configuration files can be found.
-%% Purpose: Reads th standard configuration file.
+%% Purpose: Reads the standard configuration file.
%% Returns: A list of standard variables
%% Fails: If an error occurs, the process will die with Reason
%% configuration_error.
+%% This file is mandatory, as it contains mandatory
+%% config options for which there are no default values.
%%-----------------------------------------------------------------
read_standard(Dir) ->
?vdebug("check standard config file",[]),
- Gen = fun(_) -> ok end,
- Filter = fun(Standard) -> sort_standard(Standard) end,
- Check = fun(Entry) -> check_standard(Entry) end,
+ FileName = "standard.conf",
+ Gen = fun(D, Reason) ->
+ throw({error, {failed_reading_config_file,
+ D, FileName,
+ list_dir(Dir), Reason}})
+ end,
+ Filter = fun(Standard) -> sort_standard(Standard) end,
+ Check = fun(Entry) -> check_standard(Entry) end,
[Standard] =
- snmp_conf:read_files(Dir, [{Gen, Filter, Check, "standard.conf"}]),
+ snmp_conf:read_files(Dir, [{Gen, Filter, Check, FileName}]),
Standard.
+list_dir(Dir) ->
+ case file:list_dir(Dir) of
+ {ok, Files} ->
+ Files;
+ Error ->
+ Error
+ end.
+
%%-----------------------------------------------------------------
%% Make sure that each mandatory standard attribute is present, and
@@ -548,6 +563,7 @@ snmp_set_serial_no(set, NewVal) ->
snmp_generic:variable_func(set, (NewVal + 1) rem 2147483648,
{snmpSetSerialNo, volatile}).
+
%%-----------------------------------------------------------------
%% This is the instrumentation function for sysOrTable
%%-----------------------------------------------------------------
@@ -588,4 +604,4 @@ error(Reason) ->
throw({error, Reason}).
config_err(F, A) ->
- snmpa_error:config_err("[STANDARD-MIB]: " ++ F, A).
+ snmpa_error:config_err("[STANDARD-MIB] " ++ F, A).
diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl
index 60bd3e0912..b01d536caa 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -46,8 +46,14 @@
%% Column not accessible via SNMP - needed when the agent sends informs
-define(snmpTargetAddrEngineId, 10).
%% Extra comlumns for the augmented table snmpTargetAddrExtTable
--define(snmpTargetAddrTMask, 11).
--define(snmpTargetAddrMMS, 12).
+-define(snmpTargetAddrTMask, 11).
+-define(snmpTargetAddrMMS, 12).
+
+-ifdef(snmp_extended_verbosity).
+-define(vt(F,A), ?vtrace(F, A)).
+-else.
+-define(vt(_F, _A), ok).
+-endif.
%%-----------------------------------------------------------------
@@ -126,12 +132,12 @@ do_reconfigure(Dir) ->
read_target_config_files(Dir) ->
- ?vdebug("check target address config file",[]),
- TAGen = fun(_D) -> ok end,
+ ?vdebug("check target address and parameter config file(s)",[]),
+ TAGen = fun(_D, _Reason) -> ok end,
TAFilter = fun(Addr) -> Addr end,
TACheck = fun(Entry) -> check_target_addr(Entry) end,
- TPGen = fun(_D) -> ok end,
+ TPGen = fun(_D, _Reason) -> ok end,
TPFilter = fun(Params) -> Params end,
TPCheck = fun(Entry) -> check_target_params(Entry) end,
@@ -459,10 +465,16 @@ get_target_addrs() ->
get_target_addrs(Key, {Tab, _} = TabDb, Acc) ->
+ ?vt("get_target_addrs -> entry with"
+ "~n Key: ~p", [Key]),
case table_next(Tab, Key) of
endOfTable ->
+ ?vt("get_target_addrs -> endOfTable when"
+ "~n Acc: ~p", [Acc]),
Acc;
NextKey ->
+ ?vt("get_target_addrs -> next ok: "
+ "~n NextKey: ~p", [NextKey]),
case get_target_addr(TabDb, NextKey) of
{ok, Targ} ->
get_target_addrs(NextKey, TabDb, [Targ| Acc]);
diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
index 69cebc858b..3c4ba1af66 100644
--- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
+++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,7 @@
%% Columns not accessible via SNMP
-define(usmUserAuthKey, 14).
-define(usmUserPrivKey, 15).
+-define(is_cloning, 16).
%%%-----------------------------------------------------------------
@@ -136,7 +137,7 @@ do_reconfigure(Dir) ->
read_usm_config_files(Dir) ->
?vdebug("read usm config file",[]),
- Gen = fun(D) -> generate_usm(D) end,
+ Gen = fun(D, Reason) -> generate_usm(D, Reason) end,
Filter = fun(Usms) -> Usms end,
Check = fun(Entry) -> check_usm(Entry) end,
[Usms] =
@@ -144,7 +145,7 @@ read_usm_config_files(Dir) ->
Usms.
-generate_usm(Dir) ->
+generate_usm(Dir, _Reason) ->
info_msg("Incomplete configuration. Generating empty usm.conf.", []),
USMFile = filename:join(Dir, "usm.conf"),
ok = file:write_file(USMFile, list_to_binary([])).
@@ -564,7 +565,9 @@ usmUserTable(set, RowIndex, Cols0) ->
{ok, Cols} ->
?vtrace("usmUserTable(set) -> verified"
"~n Cols: ~p", [Cols]),
- NCols = pre_set(RowIndex, Cols),
+ % check whether we're cloning. if so, get cloned params and add a few
+ % defaults that might be needed.
+ NCols = pre_set(RowIndex, validate_clone_from(RowIndex, Cols)),
?vtrace("usmUserTable(set) -> pre-set: "
"~n NCols: ~p", [NCols]),
%% NOTE: The NCols parameter is sent to snmp_generic, but not to
@@ -730,30 +733,40 @@ validate_is_set_ok(Error, _RowIndex, _Cols) ->
Error.
do_validate_is_set_ok(RowIndex, Cols) ->
- validate_clone_from(RowIndex, Cols),
- validate_auth_protocol(RowIndex, Cols),
- validate_auth_key_change(RowIndex, Cols),
- validate_own_auth_key_change(RowIndex, Cols),
- validate_priv_protocol(RowIndex, Cols),
- validate_priv_key_change(RowIndex, Cols),
- validate_own_priv_key_change(RowIndex, Cols),
+ NCols = validate_clone_from(RowIndex, Cols),
+ validate_auth_protocol(RowIndex, NCols),
+ validate_auth_key_change(RowIndex, NCols),
+ validate_own_auth_key_change(RowIndex, NCols),
+ validate_priv_protocol(RowIndex, NCols),
+ validate_priv_key_change(RowIndex, NCols),
+ validate_own_priv_key_change(RowIndex, NCols),
ok.
pre_set(RowIndex, Cols) ->
+ %% Remove the ?is_cloning member again; it must no longer be
+ %% present.
+ Cols0 = key1delete(?is_cloning, Cols),
%% Possibly initialize the usmUserSecurityName and privacy keys
case snmp_generic:table_row_exists(db(usmUserTable), RowIndex) of
- true -> Cols;
+ true -> Cols0;
false ->
SecName = get_user_name(RowIndex),
- [{?usmUserSecurityName, SecName} | Cols] ++
- [{?usmUserAuthKey, ""},
- {?usmUserPrivKey, ""}]
+ Cols1 = [{?usmUserSecurityName, SecName} | Cols0],
+ case proplists:get_value(?is_cloning, Cols) of
+ true ->
+ % the row is just being cloned. the cloned user's
+ % passwords are already present in Cols and must
+ % not be overwritten.
+ Cols1;
+ _ ->
+ Cols1 ++ [{?usmUserAuthKey, ""},
+ {?usmUserPrivKey, ""}]
+ end
end.
validate_set({noError, 0}, RowIndex, Cols) ->
%% Now, all is_set_ok validation steps have been executed. So
%% everything is ready for the set.
- set_clone_from(RowIndex, Cols),
set_auth_key_change(RowIndex, Cols),
set_own_auth_key_change(RowIndex, Cols),
set_priv_key_change(RowIndex, Cols),
@@ -769,7 +782,7 @@ validate_set(Error, _RowIndex, _Cols) ->
%% no further checks.
%%-----------------------------------------------------------------
validate_clone_from(RowIndex, Cols) ->
- case lists:keysearch(?usmUserCloneFrom, 1, Cols) of
+ case key1search(?usmUserCloneFrom, Cols) of
{value, {_Col, RowPointer}} ->
RowIndex2 = extract_row(RowPointer),
OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
@@ -778,35 +791,63 @@ validate_clone_from(RowIndex, Cols) ->
case OldCloneFrom of
{value, Val} when Val /= noinit ->
%% This means that the cloning is already done...
- ok;
+ no_cloning(Cols);
_ ->
- %% Otherwise, we must check the CloneFrom value
- case snmp_generic:table_get_element(db(usmUserTable),
- RowIndex2,
- ?usmUserStatus) of
- {value, ?'RowStatus_active'} -> ok;
- _ -> inconsistentName(?usmUserCloneFrom)
- end
+ %% Otherwise, we must check the CloneFrom value. It
+ %% must relate to a usmUserEntry that exists and is active.
+ case snmp_generic:table_get_row(db(usmUserTable), RowIndex2) of
+ CloneFromRow when is_tuple(CloneFromRow) ->
+ case element(?usmUserStatus, CloneFromRow) of
+ ?'RowStatus_active' ->
+ get_cloned_cols(CloneFromRow, Cols);
+ _ ->
+ inconsistentName(?usmUserCloneFrom)
+ end;
+ undefined ->
+ inconsistentName(?usmUserCloneFrom)
+ end
end;
false ->
- ok
+ % no ?usmUserCloneFrom specified, don't modify columns
+ no_cloning(Cols)
end.
+get_cloned_cols(CloneFromRow, Cols) ->
+ % initialize cloned columns with data from CloneFromRow
+ % and overwrite that again with data found in Cols
+ AuthP = element(?usmUserAuthProtocol, CloneFromRow),
+ PrivP = element(?usmUserPrivProtocol, CloneFromRow),
+ AuthK = element(?usmUserAuthKey, CloneFromRow),
+ PrivK = element(?usmUserPrivKey, CloneFromRow),
+ ClonedCols = [{?usmUserAuthProtocol, AuthP},
+ {?usmUserPrivProtocol, PrivP},
+ {?usmUserAuthKey, AuthK},
+ {?usmUserPrivKey, PrivK},
+ {?is_cloning, true}
+ ],
+ Func = fun({Col, _} = Item, NCols) ->
+ key1store(Col, NCols, Item)
+ end,
+ Cols1 = lists:foldl(Func, ClonedCols, Cols),
+ key1sort(Cols1).
+
+no_cloning(Cols0) ->
+ Cols1 = key1delete(?usmUserCloneFrom, Cols0),
+ key1delete(?is_cloning, Cols1).
+
validate_auth_protocol(RowIndex, Cols) ->
- case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of
+ case key1search(?usmUserAuthProtocol, Cols) of
{value, {_Col, AuthProtocol}} ->
- %% Check if the row has been cloned; we can't check the
+ %% Check if the row is being cloned; we can't check the
%% old value of authProtocol, because if the row was
%% createAndWaited, the default value would have been
%% written (usmNoAuthProtocol).
- OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
- RowIndex,
- ?usmUserCloneFrom),
- case OldCloneFrom of
- {value, Val} when Val /= noinit ->
- %% This means that the cloning is already done; set is ok
- %% if new protocol is usmNoAuthProtocol
+ IsCloning = proplists:get_value(?is_cloning, Cols, false),
+ if
+ not IsCloning ->
+ %% This means that the row is not being cloned right
+ %% now; set is ok if new protocol is usmNoAuthProtocol
case AuthProtocol of
?usmNoAuthProtocol ->
%% Check that the Priv protocl is noPriv
@@ -821,7 +862,7 @@ validate_auth_protocol(RowIndex, Cols) ->
_ ->
wrongValue(?usmUserAuthProtocol)
end;
- _ ->
+ true ->
%% Otherwise, check that the new protocol is known,
%% and that the system we're running supports the
%% hash function.
@@ -867,7 +908,7 @@ validate_own_priv_key_change(RowIndex, Cols) ->
%% Check that the requesting user is the same as the modified user
validate_requester(RowIndex, Cols, KeyChangeCol) ->
- case lists:keysearch(KeyChangeCol, 1, Cols) of
+ case key1search(KeyChangeCol, Cols) of
{value, _} ->
case get(sec_model) of % Check the securityModel in the request
?SEC_USM -> ok;
@@ -890,17 +931,14 @@ validate_requester(RowIndex, Cols, KeyChangeCol) ->
end.
validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
- case lists:keysearch(KeyChangeCol, 1, Cols) of
+ case key1search(KeyChangeCol, Cols) of
{value, {_Col, KeyC}} ->
%% Check if the row has been cloned; or if it is cloned in
%% this set-operation.
OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
RowIndex,
?usmUserCloneFrom),
- IsClonePresent = case lists:keysearch(?usmUserCloneFrom, 1, Cols) of
- {value, _} -> true;
- false -> false
- end,
+ IsClonePresent = proplists:get_value(?is_cloning, Cols, false),
%% Set is ok if 1) the user already is created, 2) this is
%% a new user, which has been cloned, or is about to be
%% cloned.
@@ -912,7 +950,7 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
%% The user is cloned in this operation
ok;
_ ->
- %% The user doen't exist, or hasn't been cloned,
+ %% The user doesn't exist, or hasn't been cloned,
%% and is not cloned in this operation.
inconsistentName(KeyChangeCol)
end,
@@ -939,17 +977,15 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
end.
validate_priv_protocol(RowIndex, Cols) ->
- case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of
+ case key1search(?usmUserPrivProtocol, Cols) of
{value, {_Col, PrivProtocol}} ->
%% Check if the row has been cloned; we can't check the
%% old value of privhProtocol, because if the row was
%% createAndWaited, the default value would have been
%% written (usmNoPrivProtocol).
- OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
- RowIndex,
- ?usmUserCloneFrom),
- case OldCloneFrom of
- {value, Val} when Val /= noinit ->
+ IsCloning = proplists:get_value(?is_cloning, Cols, false),
+ if
+ not IsCloning ->
%% This means that the cloning is already done; set is ok
%% if new protocol is usmNoPrivProtocol
case PrivProtocol of
@@ -962,7 +998,7 @@ validate_priv_protocol(RowIndex, Cols) ->
_ ->
wrongValue(?usmUserPrivProtocol)
end;
- _ ->
+ true ->
%% Otherwise, check that the new protocol is known,
%% and that the system we're running supports the
%% crypto function.
@@ -1005,31 +1041,6 @@ validate_priv_protocol(RowIndex, Cols) ->
end.
-set_clone_from(RowIndex, Cols) ->
- %% If CloneFrom is modified, do the cloning.
- case lists:keysearch(?usmUserCloneFrom, 1, Cols) of
- {value, {_Col, RowPointer}} ->
- RowIndex2 = extract_row(RowPointer), % won't fail
- CloneRow = snmp_generic:table_get_row(db(usmUserTable), RowIndex2,
- foi(usmUserTable)),
- AuthP = element(?usmUserAuthProtocol, CloneRow),
- PrivP = element(?usmUserPrivProtocol, CloneRow),
- AuthK = element(?usmUserAuthKey, CloneRow),
- PrivK = element(?usmUserPrivKey, CloneRow),
- SCols = [{?usmUserAuthProtocol, AuthP},
- {?usmUserPrivProtocol, PrivP},
- {?usmUserAuthKey, AuthK},
- {?usmUserPrivKey, PrivK}],
- case snmp_generic:table_set_elements(db(usmUserTable),
- RowIndex,
- SCols) of
- true -> ok;
- false -> {commitFailed, ?usmUserCloneFrom}
- end;
- false ->
- ok
- end.
-
set_auth_key_change(RowIndex, Cols) ->
set_key_change(RowIndex, Cols, ?usmUserAuthKeyChange, auth).
@@ -1043,7 +1054,7 @@ set_own_priv_key_change(RowIndex, Cols) ->
set_key_change(RowIndex, Cols, ?usmUserOwnPrivKeyChange, priv).
set_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
- case lists:keysearch(KeyChangeCol, 1, Cols) of
+ case key1search(KeyChangeCol, Cols) of
{value, {_Col, KeyChange}} ->
KeyCol = case Type of
auth -> ?usmUserAuthKey;
@@ -1071,11 +1082,11 @@ extract_row([H | T], [H | T2]) -> extract_row(T, T2);
extract_row([], [?usmUserSecurityName | T]) -> T;
extract_row(_, _) -> wrongValue(?usmUserCloneFrom).
-%% Pre: the user exixt
+%% Pre: the user exists or is being cloned in this operation
get_auth_proto(RowIndex, Cols) ->
- %% The protocol can be chanegd by the request too, otherwise,
+ %% The protocol can be changed by the request too, otherwise,
%% check the stored protocol.
- case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of
+ case key1search(?usmUserAuthProtocol, Cols) of
{value, {_, Protocol}} ->
Protocol;
false ->
@@ -1090,11 +1101,11 @@ get_auth_proto(RowIndex, Cols) ->
end
end.
-%% Pre: the user exixt
+%% Pre: the user exists or is being cloned in this operation
get_priv_proto(RowIndex, Cols) ->
- %% The protocol can be chanegd by the request too, otherwise,
+ %% The protocol can be changed by the request too, otherwise,
%% check the stored protocol.
- case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of
+ case key1search(?usmUserPrivProtocol, Cols) of
{value, {_, Protocol}} ->
Protocol;
false ->
@@ -1232,6 +1243,27 @@ set_sname(_) -> %% Keep it, if already set.
error(Reason) ->
throw({error, Reason}).
+
+%%-----------------------------------------------------------------
+%% lists key-function(s) wrappers
+
+-compile({inline,key1delete/2}).
+key1delete(Key, List) ->
+ lists:keydelete(Key, 1, List).
+
+-compile({inline,key1search/2}).
+key1search(Key, List) ->
+ lists:keysearch(Key, 1, List).
+
+-compile({inline,key1store/3}).
+key1store(Key, List, Elem) ->
+ lists:keystore(Key, 1, List, Elem).
+
+-compile({inline,key1sort/1}).
+key1sort(List) ->
+ lists:keysort(1, List).
+
+
%%-----------------------------------------------------------------
info_msg(F, A) ->
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 37f6dd3f26..436f15eb9c 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,7 @@ do_reconfigure(Dir) ->
read_vacm_config_files(Dir) ->
?vdebug("read vacm config file",[]),
- Gen = fun(_) -> ok end,
+ Gen = fun(_D, _Reason) -> ok end,
Filter = fun(Vacms) ->
Sec2Group = [X || {vacmSecurityToGroup, X} <- Vacms],
Access = [X || {vacmAccess, X} <- Vacms],
@@ -203,18 +203,16 @@ init_sec2group_table([Row | T]) ->
init_sec2group_table(T);
init_sec2group_table([]) -> true.
-init_access_table([{GN, Prefix, Model, Level, Row} | T]) ->
-%% ?vtrace("init access table: "
-%% "~n GN: ~p"
-%% "~n Prefix: ~p"
-%% "~n Model: ~p"
-%% "~n Level: ~p"
-%% "~n Row: ~p",[GN, Prefix, Model, Level, Row]),
- Key = [length(GN) | GN] ++ [length(Prefix) | Prefix] ++ [Model, Level],
- snmpa_vacm:insert([{Key, Row}], false),
- init_access_table(T);
-init_access_table([]) ->
- snmpa_vacm:dump_table().
+make_access_key(GN, Prefix, Model, Level) ->
+ [length(GN) | GN] ++ [length(Prefix) | Prefix] ++ [Model, Level].
+
+make_access_entry({GN, Prefix, Model, Level, Row}) ->
+ Key = make_access_key(GN, Prefix, Model, Level),
+ {Key, Row}.
+
+init_access_table(TableData) ->
+ TableData2 = [make_access_entry(E) || E <- TableData],
+ snmpa_vacm:insert(TableData2, true).
init_view_table([Row | T]) ->
%% ?vtrace("init view table: "
@@ -276,10 +274,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) ->
Match, RV, WV, NV},
case (catch check_vacm(Access)) of
{ok, {vacmAccess, {GN, Pref, SM, SL, Row}}} ->
- Key1 = [length(GN) | GN],
- Key2 = [length(Pref) | Pref],
- Key3 = [SM, SL],
- Key = Key1 ++ Key2 ++ Key3,
+ Key = make_access_key(GN, Pref, SM, SL),
snmpa_vacm:insert([{Key, Row}], false),
snmpa_agent:invalidate_ca_cache(),
{ok, Key};
@@ -570,45 +565,85 @@ vacmAccessTable(is_set_ok, RowIndex, Cols0) ->
case (catch verify_vacmAccessTable_cols(Cols0, [])) of
{ok, Cols} ->
IsValidKey = is_valid_key(RowIndex),
- case lists:keysearch(?vacmAccessStatus, 1, Cols) of
- %% Ok, if contextMatch is init
- {value, {Col, ?'RowStatus_active'}} ->
- {ok, Row} = snmpa_vacm:get_row(RowIndex),
- case element(?vacmAContextMatch, Row) of
- noinit -> {inconsistentValue, Col};
- _ -> {noError, 0}
+ StatusCol = lists:keyfind(?vacmAccessStatus, 1, Cols),
+ MaybeRow = snmpa_vacm:get_row(RowIndex),
+ case {StatusCol, MaybeRow} of
+ {{Col, ?'RowStatus_active'}, false} ->
+ %% row does not yet exist => inconsistentValue
+ %% (see SNMPv2-TC.mib, RowStatus textual convention)
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_active'}, {ok, Row}} ->
+ %% Ok, if contextMatch is init
+ case element(?vacmAContextMatch, Row) of
+ noinit ->
+ %% check whether ContextMatch is being set in
+ %% the same operation
+ case proplists:get_value(?vacmAccessContextMatch,
+ Cols) of
+ undefined ->
+ %% no, we can't make this row active yet
+ {inconsistentValue, Col};
+ _ ->
+ %% ok, activate the row
+ {noError, 0}
+ end;
+ _ ->
+ {noError, 0}
end;
- {value, {Col, ?'RowStatus_notInService'}} -> % Ok, if not notReady
- {ok, Row} = snmpa_vacm:get_row(RowIndex),
+ {{Col, ?'RowStatus_notInService'}, false} ->
+ %% row does not yet exist => inconsistentValue
+ %% (see SNMPv2-TC.mib, RowStatus textual convention)
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_notInService'}, {ok, Row}} ->
+ %% Ok, if not notReady
case element(?vacmAStatus, Row) of
- ?'RowStatus_notReady' -> {inconsistentValue, Col};
- _ -> {noError, 0}
+ ?'RowStatus_notReady' ->
+ {inconsistentValue, Col};
+ _ ->
+ {noError, 0}
end;
- {value, {Col, ?'RowStatus_notReady'}} -> % never ok!
+ {{Col, ?'RowStatus_notReady'}, _} ->
+ %% never ok!
{inconsistentValue, Col};
- {value, {Col, ?'RowStatus_createAndGo'}} -> % ok, if it doesn't exist
+ {{Col, ?'RowStatus_createAndGo'}, false} ->
+ %% ok, if it doesn't exist
Res = lists:keysearch(?vacmAccessContextMatch, 1, Cols),
- case snmpa_vacm:get_row(RowIndex) of
- false when (IsValidKey =:= true) andalso
- is_tuple(Res) -> {noError, 0};
- false -> {noCreation, Col}; % Bad RowIndex
- _ -> {inconsistentValue, Col}
+ if
+ IsValidKey =/= true ->
+ %% bad RowIndex => noCreation
+ {noCreation, Col};
+ is_tuple(Res) ->
+ %% required field is present => noError
+ {noError, 0};
+ true ->
+ %% required field is missing => inconsistentValue
+ {inconsistentValue, Col}
end;
- {value, {Col, ?'RowStatus_createAndWait'}} -> % ok, if it doesn't exist
- case snmpa_vacm:get_row(RowIndex) of
- false when (IsValidKey =:= true) -> {noError, 0};
- false -> {noCreation, Col}; % Bad RowIndex
- _ -> {inconsistentValue, Col}
+ {{Col, ?'RowStatus_createAndGo'}, _} ->
+ %% row already exists => inconsistentValue
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_createAndWait'}, false} ->
+ %% ok, if it doesn't exist
+ if
+ IsValidKey =:= true ->
+ %% RowIndex is valid => noError
+ {noError, 0};
+ true ->
+ {noCreation, Col}
end;
- {value, {_Col, ?'RowStatus_destroy'}} -> % always ok!
+ {{Col, ?'RowStatus_createAndWait'}, _} ->
+ %% Row already exists => inconsistentValue
+ {inconsistentValue, Col};
+ {value, {_Col, ?'RowStatus_destroy'}} ->
+ %% always ok!
{noError, 0};
- _ -> % otherwise, it's a change; it must exist
- case snmpa_vacm:get_row(RowIndex) of
- {ok, _} ->
- {noError, 0};
- false ->
- {inconsistentName, element(1, hd(Cols))}
- end
+ {_, false} ->
+ %% otherwise, it's a row change;
+ %% row does not exist => inconsistentName
+ {inconsistentName, element(1, hd(Cols))};
+ _ ->
+ %% row change and row exists => noError
+ {noError, 0}
end;
Error ->
Error
@@ -739,10 +774,15 @@ do_vacmAccessTable_set(RowIndex, Cols) ->
%% Cols are sorted, and all columns are > 3.
+do_get_next(_RowIndex, []) ->
+ % Cols can be empty because we're called for each
+ % output of split_cols(); and one of that may well
+ % be empty.
+ [];
do_get_next(RowIndex, Cols) ->
case snmpa_vacm:get_next_row(RowIndex) of
{NextIndex, Row} ->
- F1 = fun(Col) when Col < ?vacmAccessStatus ->
+ F1 = fun(Col) when Col =< ?vacmAccessStatus ->
{[Col | NextIndex], element(Col-3, Row)};
(_) ->
endOfTable
@@ -750,9 +790,9 @@ do_get_next(RowIndex, Cols) ->
lists:map(F1, Cols);
false ->
case snmpa_vacm:get_next_row([]) of
- {_NextIndex, Row} ->
+ {NextIndex2, Row} ->
F2 = fun(Col) when Col < ?vacmAccessStatus ->
- {[Col+1 | RowIndex], element(Col-2, Row)};
+ {[Col+1 | NextIndex2], element(Col-2, Row)};
(_) ->
endOfTable
end,
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl
index 50b169e4e7..b45a47ec6b 100644
--- a/lib/snmp/src/agent/snmpa.erl
+++ b/lib/snmp/src/agent/snmpa.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,8 +83,11 @@
-export([add_agent_caps/2, del_agent_caps/1, get_agent_caps/0]).
%% Audit Trail Log functions
--export([log_to_txt/2, log_to_txt/3, log_to_txt/4,
+-export([log_to_txt/1,
+ log_to_txt/2, log_to_txt/3, log_to_txt/4,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
+ log_to_io/1, log_to_io/2, log_to_io/3,
+ log_to_io/4, log_to_io/5, log_to_io/6,
log_info/0,
change_log_size/1,
get_log_type/0, get_log_type/1,
@@ -547,7 +550,7 @@ update_mibs_cache_age(Agent, Age) ->
update_mibs_cache_gclimit(GcLimit) ->
- update_mibs_cache_age(snmp_master_agent, GcLimit).
+ update_mibs_cache_gclimit(snmp_master_agent, GcLimit).
update_mibs_cache_gclimit(Agent, GcLimit) ->
snmpa_agent:update_mibs_cache_gclimit(Agent, GcLimit).
@@ -780,6 +783,8 @@ get_agent_caps() ->
%%% Audit Trail Log functions
%%%-----------------------------------------------------------------
+log_to_txt(LogDir) ->
+ log_to_txt(LogDir, []).
log_to_txt(LogDir, Mibs) ->
OutFile = "snmpa_log.txt",
LogName = ?audit_trail_log_name,
@@ -800,6 +805,23 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) ->
snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop).
+log_to_io(LogDir) ->
+ log_to_io(LogDir, []).
+log_to_io(LogDir, Mibs) ->
+ LogName = ?audit_trail_log_name,
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName) ->
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop).
+
+
log_info() ->
LogName = ?audit_trail_log_name,
snmp_log:info(LogName).
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index 6322f0f21d..9d30e332f1 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,8 +68,11 @@
%% 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,
+ handle_pdu/8, worker/2, worker_loop/1,
do_send_trap/7, do_send_trap/8]).
+%% <BACKWARD-COMPAT>
+-export([handle_pdu/7]).
+%% </BACKWARD-COMPAT>
-include("snmpa_internal.hrl").
@@ -87,7 +90,6 @@
-define(DISCO_TERMINATING_TRIGGER_USERNAME, "").
-
-ifdef(snmp_debug).
-define(GS_START_LINK3(Prio, Parent, Ref, Opts),
gen_server:start_link(?MODULE, [Prio, Parent, Ref, Opts],
@@ -103,13 +105,49 @@
gen_server:start_link({local, Name}, ?MODULE,
[Prio, Parent, Ref, Opts],[])).
-endif.
-
+
+%% Increment this whenever a change is made to the worker interface
+-define(WORKER_INTERFACE_VERSION, 1).
+
+%% -- Utility macros for creating worker commands --
+-define(mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra),
+ #wrequest{cmd = handle_pdu,
+ info = [{vsn, Vsn},
+ {pdu, Pdu},
+ {pdu_ms, PduMS},
+ {acm_data, ACMData},
+ {addr, Address},
+ {gb_max_vbs, GbMaxVBs},
+ {extra, Extra}]}).
+-define(mk_send_trap_wreq(TrapRec, NotifyName, ContextName,
+ Recv, Vbs, LocalEngineID, Extra),
+ #wrequest{cmd = send_trap,
+ info = [{trap_rec, TrapRec},
+ {notify_name, NotifyName},
+ {context_name, ContextName},
+ {receiver, Recv},
+ {varbinds, Vbs},
+ {local_engine_id, LocalEngineID},
+ {extra, Extra}]}).
+-define(mk_terminate_wreq(), #wrequest{cmd = terminate, info = []}).
+-define(mk_verbosity_wreq(V), #wrequest{cmd = verbosity,
+ info = [{verbosity, V}]}).
+
-record(notification_filter, {id, mod, data}).
-record(disco,
{from, rec, sender, target, engine_id,
sec_level, ctx, ivbs, stage, handler, extra}).
+%% This record is used when sending requests to the worker processes
+-record(wrequest,
+ {
+ version = ?WORKER_INTERFACE_VERSION,
+ cmd,
+ info
+ }
+ ).
+
%%-----------------------------------------------------------------
%% The agent is multi-threaded, i.e. each request is handled
@@ -142,7 +180,8 @@
net_if_mod,
backup,
disco,
- mibs_cache_request}).
+ mibs_cache_request,
+ gb_max_vbs}).
%%%-----------------------------------------------------------------
@@ -330,6 +369,8 @@ do_init(Prio, Parent, Ref, Options) ->
MultiT = get_multi_threaded(Options),
Vsns = get_versions(Options),
+ GbMaxVbs = get_gb_max_vbs(Options),
+
NS = start_note_store(Prio, Ref, Options),
{Type, NetIfPid, NetIfMod} =
start_net_if(Parent, Prio, Ref, Vsns, NS, Options),
@@ -348,7 +389,8 @@ do_init(Prio, Parent, Ref, Options) ->
ref = Ref,
vsns = Vsns,
note_store = NS,
- net_if_mod = NetIfMod}}.
+ net_if_mod = NetIfMod,
+ gb_max_vbs = GbMaxVbs}}.
start_note_store(Prio, Ref, Options) ->
@@ -410,7 +452,8 @@ start_net_if(Parent, _Prio, _Ref, _Vsns, _NoteStore, _Options)
start_mib_server(Prio, Ref, Mibs, Options) ->
?vdebug("start_mib_server -> with Prio: ~p", [Prio]),
MibStorage = get_mib_storage(Options),
- MibsOpts = [{mib_storage, MibStorage}|get_option(mib_server, Options, [])],
+ MibsOpts = [{mib_storage, MibStorage} |
+ get_option(mib_server, Options, [])],
?vtrace("start_mib_server -> "
"~n Mibs: ~p"
@@ -558,25 +601,6 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) ->
],
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"
"~n self(): ~p"
@@ -599,27 +623,6 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, 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>
@@ -709,11 +712,6 @@ wis(Atom) when is_atom(Atom) ->
whereis(Atom).
-forward_trap(Agent, 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,
@@ -796,7 +794,8 @@ handle_info({snmp_pdu, Vsn, Pdu, PduMS, ACMData, Address, Extra}, S) ->
?vdebug("handle_info(snmp_pdu) -> entry with"
"~n Vsn: ~p"
"~n Pdu: ~p"
- "~n Address: ~p", [Vsn, Pdu, Address]),
+ "~n Address: ~p"
+ "~n Extra: ~p", [Vsn, Pdu, Address, Extra]),
NewS = handle_snmp_pdu(is_valid_pdu_type(Pdu#pdu.type),
Vsn, Pdu, PduMS, ACMData, Address, Extra, S),
@@ -808,11 +807,11 @@ handle_info(worker_available, S) ->
{noreply, S#state{worker_state = ready}};
handle_info({send_notif, Notification, SendOpts}, S) ->
- ?vlog("[handle_info] send trap request:"
+ ?vlog("[handle_info] send notif request:"
"~n Notification: ~p"
"~n SendOpts: ~p",
[Notification, SendOpts]),
- case (catch handle_send_trap(cast, S, Notification, SendOpts)) of
+ case (catch handle_send_trap(S, Notification, SendOpts)) of
{ok, NewS} ->
{noreply, NewS};
{'EXIT', R} ->
@@ -832,7 +831,7 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) ->
"~n Varbinds: ~p",
[Trap, NotifyName, ContextName, Recv, Varbinds]),
ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
- LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
+ LocalEngineID = local_engine_id(S),
case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
@@ -979,6 +978,7 @@ handle_info({'EXIT', Pid, Reason}, S) ->
end,
{noreply, S}
end;
+
handle_info({'DOWN', Ref, process, Pid, {mibs_cache_reply, Reply}},
#state{mibs_cache_request = {Pid, Ref, From}} = S) ->
?vlog("reply from the mibs cache request handler (~p): ~n~p",
@@ -1014,11 +1014,11 @@ handle_call(restart_set_worker, _From, #state{set_worker = Pid} = S) ->
{reply, ok, S};
handle_call({send_notif, Notification, SendOpts}, _From, S) ->
- ?vlog("[handle_info] send trap request:"
+ ?vlog("[handle_call] send notif request:"
"~n Notification: ~p"
"~n SendOpts: ~p",
[Notification, SendOpts]),
- case (catch handle_send_trap(call, S, Notification, SendOpts)) of
+ case (catch handle_send_trap(S, Notification, SendOpts)) of
{ok, NewS} ->
{reply, ok, NewS};
{'EXIT', Reason} ->
@@ -1039,18 +1039,8 @@ 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 now, eventually the trap send
- %% request will reach the master-agent and then it
- %% will look up the proper engine id.
- ignore
- end,
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ LocalEngineID = local_engine_id(S),
case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
@@ -1130,7 +1120,7 @@ handle_call({subagent_get_next, MibView, Varbinds, PduData}, _From, S) ->
"~n PduData: ~p",
[MibView,Varbinds,PduData]),
put_pdu_data(PduData),
- {reply, do_get_next(MibView, Varbinds), S};
+ {reply, do_get_next(MibView, Varbinds, infinity), S};
handle_call({subagent_set, Arguments, PduData}, _From, S) ->
?vlog("[handle_call] subagent set:"
"~n Arguments: ~p"
@@ -1171,7 +1161,7 @@ handle_call({get_next, Vars, Context}, _From, S) ->
?vdebug("Varbinds: ~p",[Varbinds]),
MibView = snmpa_acm:get_root_mib_view(),
Reply =
- case do_get_next(MibView, Varbinds) of
+ case do_get_next(MibView, Varbinds, infinity) of
{noError, 0, NewVarbinds} ->
Vbs = lists:keysort(#varbind.org_index, NewVarbinds),
[{Oid,Val} || #varbind{oid = Oid, value = Val} <- Vbs];
@@ -1272,7 +1262,8 @@ handle_call(info, _From, S) ->
handle_call(get_net_if, _From, S) ->
{reply, get(net_if), S};
-handle_call({backup, BackupDir}, From, S) ->
+%% Only accept a backup request if there is none already in progress
+handle_call({backup, BackupDir}, From, #state{backup = undefined} = S) ->
?vlog("backup: ~p", [BackupDir]),
Pid = self(),
V = get(verbosity),
@@ -1289,7 +1280,11 @@ handle_call({backup, BackupDir}, From, S) ->
end),
?vtrace("backup server: ~p", [BackupServer]),
{noreply, S#state{backup = {BackupServer, From}}};
-
+
+handle_call({backup, _BackupDir}, _From, #state{backup = Backup} = S) ->
+ ?vinfo("backup already in progress: ~p", [Backup]),
+ {reply, {error, backup_in_progress}, S};
+
handle_call(dump_mibs, _From, S) ->
Reply = snmpa_mib:dump(get(mibserver)),
{reply, Reply, S};
@@ -1338,27 +1333,27 @@ handle_call({me_of, Oid}, _From, S) ->
{reply, Reply, S};
handle_call(get_log_type, _From, S) ->
- ?vlog("get_log_type", []),
+ ?vlog("handle_call(get_log_type) -> entry with", []),
Reply = handle_get_log_type(S),
{reply, Reply, S};
handle_call({set_log_type, NewType}, _From, S) ->
- ?vlog("set_log_type -> "
+ ?vlog("handle_call(set_log_type) -> entry with"
"~n NewType: ~p", [NewType]),
Reply = handle_set_log_type(S, NewType),
{reply, Reply, S};
handle_call(get_request_limit, _From, S) ->
- ?vlog("get_request_limit", []),
+ ?vlog("handle_call(get_request_limit) -> entry with", []),
Reply = handle_get_request_limit(S),
{reply, Reply, S};
handle_call({set_request_limit, NewLimit}, _From, S) ->
- ?vlog("set_request_limit -> "
+ ?vlog("handle_call(set_request_limit) -> entry with"
"~n NewLimit: ~p", [NewLimit]),
Reply = handle_set_request_limit(S, NewLimit),
{reply, Reply, S};
-
+
handle_call(stop, _From, S) ->
{stop, normal, ok, S};
@@ -1367,15 +1362,15 @@ handle_call(Req, _From, S) ->
Reply = {error, {unknown, Req}},
{reply, Reply, S}.
-handle_cast({verbosity,Verbosity}, S) ->
- ?vlog("verbosity: ~p -> ~p",[get(verbosity),Verbosity]),
+handle_cast({verbosity, Verbosity}, S) ->
+ ?vlog("verbosity: ~p -> ~p",[get(verbosity), Verbosity]),
put(verbosity,snmp_verbosity:validate(Verbosity)),
case S#state.worker of
- Pid when is_pid(Pid) -> Pid ! {verbosity,Verbosity};
+ Pid when is_pid(Pid) -> Pid ! ?mk_verbosity_wreq(Verbosity);
_ -> ok
end,
case S#state.set_worker of
- Pid2 when is_pid(Pid2) -> Pid2 ! {verbosity,Verbosity};
+ Pid2 when is_pid(Pid2) -> Pid2 ! ?mk_verbosity_wreq(Verbosity);
_ -> ok
end,
{noreply, S};
@@ -1462,13 +1457,80 @@ handle_mibs_cache_request(MibServer, Req) ->
%% Downgrade
%%
-%% code_change({down, _Vsn}, S, downgrade_to_pre_4_13) ->
-%% {ok, S2};
+code_change({down, _Vsn}, S1, downgrade_to_pre_4_17_3) ->
+ #state{type = Type,
+ parent = Parent,
+ worker = Worker,
+ worker_state = WorkerState,
+ set_worker = SetWorker,
+ multi_threaded = MT,
+ ref = Ref,
+ vsns = Vsns,
+ nfilters = NF,
+ note_store = NoteStore,
+ mib_server = MS,
+ net_if = NetIf,
+ net_if_mod = NetIfMod,
+ backup = Backup,
+ disco = Disco,
+ mibs_cache_request = MCR} = S1,
+ S2 = {state,
+ type = Type,
+ parent = Parent,
+ worker = Worker,
+ worker_state = WorkerState,
+ set_worker = SetWorker,
+ multi_threaded = MT,
+ ref = Ref,
+ vsns = Vsns,
+ nfilters = NF,
+ note_store = NoteStore,
+ mib_server = MS,
+ net_if = NetIf,
+ net_if_mod = NetIfMod,
+ backup = Backup,
+ disco = Disco,
+ mibs_cache_request = MCR},
+ {ok, S2};
%% Upgrade
%%
-%% code_change(_Vsn, S, upgrade_from_pre_4_13) ->
-%% {ok, S2};
+code_change(_Vsn, S1, upgrade_from_pre_4_17_3) ->
+ {state,
+ type = Type,
+ parent = Parent,
+ worker = Worker,
+ worker_state = WorkerState,
+ set_worker = SetWorker,
+ multi_threaded = MT,
+ ref = Ref,
+ vsns = Vsns,
+ nfilters = NF,
+ note_store = NoteStore,
+ mib_server = MS,
+ net_if = NetIf,
+ net_if_mod = NetIfMod,
+ backup = Backup,
+ disco = Disco,
+ mibs_cache_request = MCR} = S1,
+ S2 = #state{type = Type,
+ parent = Parent,
+ worker = Worker,
+ worker_state = WorkerState,
+ set_worker = SetWorker,
+ multi_threaded = MT,
+ ref = Ref,
+ vsns = Vsns,
+ nfilters = NF,
+ note_store = NoteStore,
+ mib_server = MS,
+ net_if = NetIf,
+ net_if_mod = NetIfMod,
+ backup = Backup,
+ disco = Disco,
+ mibs_cache_request = MCR,
+ gb_max_vbs = ?DEFAULT_GB_MAX_VBS},
+ {ok, S2};
code_change(_Vsn, S, _Extra) ->
{ok, S}.
@@ -1508,7 +1570,7 @@ worker_start(Dict) ->
%% worker_stop(Pid, infinity).
worker_stop(Pid, Timeout) when is_pid(Pid) ->
- Pid ! terminate,
+ Pid ! ?mk_terminate_wreq(),
receive
{'EXIT', Pid, normal} ->
ok
@@ -1595,7 +1657,7 @@ handle_backup_res([{Who, Crap}|Results], Acc) ->
%% because we (for some reason) support the function
%% snmpa:current_community().
%%-----------------------------------------------------------------
-cheat({community, SecModel, Community, _TAddress}, Address, ContextName) ->
+cheat({community, _SecModel, Community, _TAddress}, Address, ContextName) ->
{Community, Address, ContextName};
cheat({community, _SecModel, Community, _TDomain, _TAddress},
Address, ContextName) ->
@@ -1645,9 +1707,11 @@ invalidate_ca_cache() ->
%%
%%-----------------------------------------------------------------
-spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, Extra) ->
+%% This functions spawns a temporary worker process,
+%% that evaluates one request and then silently exits.
+spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) ->
Dict = get(),
- Args = [Vsn, Pdu, PduMS, ACMData, Address, Extra, Dict],
+ Args = [Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra, Dict],
proc_lib:spawn_link(?MODULE, handle_pdu, Args).
spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs,
@@ -1665,7 +1729,7 @@ do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
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))),
+ put(sname, trap_sender_short_name(get(sname))),
?vlog("starting",[]),
snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
LocalEngineID, ExtraInfo, get(net_if)).
@@ -1677,58 +1741,122 @@ worker(Master, Dict) ->
worker_loop(Master).
worker_loop(Master) ->
- receive
- {Vsn, Pdu, PduMS, ACMData, Address, Extra} ->
- ?vtrace("worker_loop -> received request", []),
- handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra),
- Master ! worker_available;
-
- %% 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,
- ?DEFAULT_NOTIF_EXTRA_INFO,
- get(net_if)),
- Master ! worker_available;
-
- %% 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, ?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;
-
- {verbosity, Verbosity} ->
- put(verbosity,snmp_verbosity:validate(Verbosity));
-
- terminate ->
- exit(normal);
-
- _X ->
- %% ignore
- ok
-
- after 30000 ->
- %% This is to assure that the worker process leaves a
- %% possibly old version of this module.
- ok
- end,
+ Res =
+ receive
+ #wrequest{cmd = handle_pdu,
+ info = Info} = Req ->
+ ?vtrace("worker_loop -> received handle_pdu request with"
+ "~n Info: ~p", [Info]),
+ Vsn = proplists:get_value(vsn, Info),
+ Pdu = proplists:get_value(pdu, Info),
+ PduMS = proplists:get_value(pdu_ms, Info),
+ ACMData = proplists:get_value(acm_data, Info),
+ Address = proplists:get_value(addr, Info),
+ GbMaxVBs = proplists:get_value(gb_max_vbs, Info),
+ Extra = proplists:get_value(extra, Info),
+ HandlePduRes =
+ try
+ begin
+ handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address,
+ GbMaxVBs, Extra)
+ end
+ catch
+ T:E ->
+ exit({worker_crash, Req, T, E,
+ erlang:get_stacktrace()})
+ end,
+ Master ! worker_available,
+ HandlePduRes; % For debugging...
+
+
+ #wrequest{cmd = send_trap,
+ info = Info} = Req ->
+ ?vtrace("worker_loop -> received send_trap request with"
+ "~n Info: ~p", [Info]),
+ TrapRec = proplists:get_value(trap_rec, Info),
+ NotifyName = proplists:get_value(notify_name, Info),
+ ContextName = proplists:get_value(context_name, Info),
+ Recv = proplists:get_value(receiver, Info),
+ Vbs = proplists:get_value(varbinds, Info),
+ LocalEngineID = proplists:get_value(local_engine_id, Info),
+ Extra = proplists:get_value(extra, Info),
+ SendTrapRes =
+ try
+ begin
+ snmpa_trap:send_trap(TrapRec, NotifyName,
+ ContextName, Recv, Vbs,
+ LocalEngineID, Extra,
+ get(net_if))
+ end
+ catch
+ T:E ->
+ exit({worker_crash, Req, T, E,
+ erlang:get_stacktrace()})
+ end,
+ Master ! worker_available,
+ SendTrapRes; % For debugging...
+
+
+ #wrequest{cmd = verbosity,
+ info = Info} ->
+ Verbosity = proplists:get_value(verbosity, Info),
+ put(verbosity, snmp_verbosity:validate(Verbosity));
+
+
+ #wrequest{cmd = terminate} ->
+ ?vtrace("worker_loop -> received terminate request", []),
+ exit(normal);
+
+
+ %% *************************************************************
+ %%
+ %% Kept for backward compatibillity reasons
+ %%
+ %% *************************************************************
+
+ {Vsn, Pdu, PduMS, ACMData, Address, Extra} ->
+ ?vtrace("worker_loop -> received request", []),
+ handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address,
+ ?DEFAULT_GB_MAX_VBS, Extra),
+ Master ! worker_available;
+
+ %% 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)),
+ Master ! worker_available;
+
+ %% We don't trap exits!
+ {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;
+
+ {verbosity, Verbosity} ->
+ put(verbosity, snmp_verbosity:validate(Verbosity));
+
+ terminate ->
+ exit(normal);
+
+ _X ->
+ %% ignore
+ ignore_unknown
+
+ after 30000 ->
+ %% This is to assure that the worker process leaves a
+ %% possibly old version of this module.
+ ok
+ end,
+ ?vtrace("worker_loop -> wrap with"
+ "~n ~p", [Res]),
?MODULE:worker_loop(Master).
@@ -1736,42 +1864,52 @@ worker_loop(Master) ->
%%-----------------------------------------------------------------
handle_snmp_pdu(true, Vsn, Pdu, PduMS, ACMData, Address, Extra,
- #state{multi_threaded = false} = S) ->
+ #state{multi_threaded = false,
+ gb_max_vbs = GbMaxVBs} = S) ->
?vtrace("handle_snmp_pdu -> single-thread agent",[]),
- handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra),
+ handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra),
S;
handle_snmp_pdu(true, Vsn, #pdu{type = 'set-request'} = Pdu, PduMS,
ACMData, Address, Extra,
#state{set_worker = Worker} = S) ->
?vtrace("handle_snmp_pdu -> multi-thread agent: "
"send set-request to main worker",[]),
- Worker ! {Vsn, Pdu, PduMS, ACMData, Address, Extra},
+ WRequest = ?mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, infinity, Extra),
+ Worker ! WRequest,
S#state{worker_state = busy};
handle_snmp_pdu(true, Vsn, Pdu, PduMS,
ACMData, Address, Extra,
- #state{worker_state = busy} = S) ->
+ #state{worker_state = busy,
+ gb_max_vbs = GbMaxVBs} = S) ->
?vtrace("handle_snmp_pdu -> multi-thread agent: "
"main worker busy - create new worker",[]),
- spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, Extra),
+ spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra),
S;
handle_snmp_pdu(true, Vsn, Pdu, PduMS, ACMData, Address, Extra,
- #state{worker = Worker} = S) ->
+ #state{worker = Worker,
+ gb_max_vbs = GbMaxVBs} = S) ->
?vtrace("handle_snmp_pdu -> multi-thread agent: "
"send to main worker",[]),
- Worker ! {Vsn, Pdu, PduMS, ACMData, Address, Extra},
+ WRequest = ?mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra),
+ Worker ! WRequest,
S#state{worker_state = busy};
handle_snmp_pdu(_, _Vsn, _Pdu, _PduMS, _ACMData, _Address, _Extra, S) ->
S.
%% Called via the spawn_thread function
+%% <BACKWARD-COMPAT>
handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra, Dict) ->
+ handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, ?DEFAULT_GB_MAX_VBS, Extra,
+ Dict).
+%% </BACKWARD-COMPAT>
+handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra, Dict) ->
lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict),
put(sname, pdu_handler_short_name(get(sname))),
?vlog("new worker starting",[]),
- handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra).
+ handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra).
-handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra) ->
+handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) ->
%% OTP-3324
AuthMod = get(auth_module),
case AuthMod:init_check_access(Pdu, ACMData) of
@@ -1780,7 +1918,8 @@ handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra) ->
"~n MibView: ~p"
"~n ContextName: ~p", [MibView, ContextName]),
AgentData = cheat(ACMData, Address, ContextName),
- do_handle_pdu(MibView, Vsn, Pdu, PduMS, ACMData, AgentData, Extra);
+ do_handle_pdu(MibView, Vsn, Pdu, PduMS, ACMData, AgentData,
+ GbMaxVBs, Extra);
{error, Reason} ->
?vlog("handle_pdu -> error:"
"~n Reason: ~p", [Reason]),
@@ -1794,16 +1933,19 @@ handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra) ->
end.
do_handle_pdu(MibView, Vsn, Pdu, PduMS,
- ACMData, {Community, Address, ContextName}, Extra) ->
+ ACMData, {Community, Address, ContextName},
+ GbMaxVBs, Extra) ->
put(net_if_data, Extra),
+
RePdu = process_msg(MibView, Vsn, Pdu, PduMS, Community,
- Address, ContextName),
+ Address, ContextName, GbMaxVBs),
?vtrace("do_handle_pdu -> processed:"
"~n RePdu: ~p", [RePdu]),
- get(net_if) ! {snmp_response, Vsn, RePdu,
- RePdu#pdu.type, ACMData, Address, Extra}.
+ NetIf = get(net_if),
+ NetIf ! {snmp_response, Vsn, RePdu,
+ RePdu#pdu.type, ACMData, Address, Extra}.
handle_acm_error(Vsn, Reason, Pdu, ACMData, Address, Extra) ->
@@ -1859,7 +2001,7 @@ handle_acm_error(Vsn, Reason, Pdu, ACMData, Address, Extra) ->
ok
end.
-get_opt(Key, Default, SendOpts) ->
+get_send_opt(Key, Default, SendOpts) ->
case lists:keysearch(Key, 1, SendOpts) of
{value, {Key, Value}} ->
Value;
@@ -1867,40 +2009,19 @@ get_opt(Key, Default, SendOpts) ->
Default
end.
-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),
+ NotifyName = get_send_opt(name, "", SendOpts),
+ ContextName = get_send_opt(context, "", SendOpts),
+ Recv = get_send_opt(receiver, no_receiver, SendOpts),
+ Varbinds = get_send_opt(varbinds, [], SendOpts),
+ ExtraInfo = get_send_opt(extra, ?DEFAULT_NOTIF_EXTRA_INFO, SendOpts),
LocalEngineID =
- get_opt(local_engine_id, ?DEFAULT_LOCAL_ENGINE_ID, SendOpts),
+ case lists:keysearch(local_engine_id, 1, SendOpts) of
+ {value, {local_engine_id, Value}} ->
+ Value;
+ false ->
+ local_engine_id(S)
+ end,
handle_send_trap(S, Notification, NotifyName, ContextName, Recv, Varbinds,
LocalEngineID, ExtraInfo).
@@ -1908,11 +2029,11 @@ handle_send_trap(#state{type = Type} = S,
Notification, NotifyName, ContextName, Recv, Varbinds,
LocalEngineID, ExtraInfo) ->
?vtrace("handle_send_trap -> entry with"
- "~n Agent type: ~p"
- "~n TrapName: ~p"
- "~n NotifyName: ~p"
- "~n ContextName: ~p"
- "~n LocalEngineID: ~p",
+ "~n Agent type: ~p"
+ "~n TrapName: ~p"
+ "~n NotifyName: ~p"
+ "~n ContextName: ~p"
+ "~n LocalEngineID: ~p",
[Type, Notification, NotifyName, ContextName, LocalEngineID]),
case snmpa_trap:construct_trap(Notification, Varbinds) of
{ok, TrapRecord, VarList} ->
@@ -2025,9 +2146,9 @@ do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds,
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, ExtraInfo},
+ S#state.worker ! ?mk_send_trap_wreq(TrapRec, NotifyName,
+ ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo),
{ok, S#state{worker_state = busy}}
end.
@@ -2367,17 +2488,18 @@ handle_mib_of(MibServer, Oid) ->
%% Func: process_msg/7
%% Returns: RePdu
%%-----------------------------------------------------------------
-process_msg(MibView, Vsn, Pdu, PduMS, Community, {Ip, Udp}, ContextName) ->
+process_msg(MibView, Vsn, Pdu, PduMS, Community, {Ip, Udp}, ContextName,
+ GbMaxVBs) ->
#pdu{request_id = ReqId} = Pdu,
put(snmp_address, {tuple_to_list(Ip), Udp}),
put(snmp_request_id, ReqId),
put(snmp_community, Community),
put(snmp_context, ContextName),
?vtrace("process ~p",[Pdu#pdu.type]),
- process_pdu(Pdu, PduMS, Vsn, MibView).
+ process_pdu(Pdu, PduMS, Vsn, MibView, GbMaxVBs).
process_pdu(#pdu{type='get-request', request_id = ReqId, varbinds=Vbs},
- _PduMS, Vsn, MibView) ->
+ _PduMS, Vsn, MibView, _GbMaxVBs) ->
?vtrace("get ~p",[ReqId]),
Res = get_err(do_get(MibView, Vbs, false)),
?vtrace("get result: "
@@ -2398,12 +2520,12 @@ process_pdu(#pdu{type='get-request', request_id = ReqId, varbinds=Vbs},
make_response_pdu(ReqId, ErrStatus, ErrIndex, Vbs, ResponseVarbinds);
process_pdu(#pdu{type = 'get-next-request', request_id = ReqId, varbinds = Vbs},
- _PduMS, Vsn, MibView) ->
+ _PduMS, Vsn, MibView, _GbMaxVBs) ->
?vtrace("process get-next-request -> entry with"
"~n ReqId: ~p"
"~n Vbs: ~p"
"~n MibView: ~p",[ReqId, Vbs, MibView]),
- Res = get_err(do_get_next(MibView, Vbs)),
+ Res = get_err(do_get_next(MibView, Vbs, infinity)),
?vtrace("get-next result: "
"~n ~p",[Res]),
{ErrStatus, ErrIndex, ResVarbinds} =
@@ -2420,11 +2542,15 @@ process_pdu(#pdu{type = 'get-next-request', request_id = ReqId, varbinds = Vbs},
"~n ~p",[ResponseVarbinds]),
make_response_pdu(ReqId, ErrStatus, ErrIndex, Vbs, ResponseVarbinds);
-process_pdu(#pdu{type = 'get-bulk-request',request_id = ReqId,varbinds = Vbs,
- error_status = NonRepeaters, error_index = MaxRepetitions},
- PduMS, _Vsn, MibView)->
+process_pdu(#pdu{type = 'get-bulk-request',
+ request_id = ReqId,
+ varbinds = Vbs,
+ error_status = NonRepeaters,
+ error_index = MaxRepetitions},
+ PduMS, _Vsn, MibView, GbMaxVBs) ->
{ErrStatus, ErrIndex, ResponseVarbinds} =
- get_err(do_get_bulk(MibView,NonRepeaters,MaxRepetitions,PduMS,Vbs)),
+ get_err(do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Vbs,
+ GbMaxVBs)),
?vtrace("get-bulk final result: "
"~n Error status: ~p"
"~n Error index: ~p"
@@ -2433,7 +2559,7 @@ process_pdu(#pdu{type = 'get-bulk-request',request_id = ReqId,varbinds = Vbs,
make_response_pdu(ReqId, ErrStatus, ErrIndex, Vbs, ResponseVarbinds);
process_pdu(#pdu{type = 'set-request', request_id = ReqId, varbinds = Vbs},
- _PduMS, Vsn, MibView)->
+ _PduMS, Vsn, MibView, _GbMaxVbs)->
Res = do_set(MibView, Vbs),
?vtrace("set result: "
"~n ~p",[Res]),
@@ -2490,7 +2616,8 @@ validate_next_v1_2([Vb | _Vbs], _MibView, _Res)
{noSuchName, Vb#varbind.org_index};
validate_next_v1_2([Vb | Vbs], MibView, Res)
when Vb#varbind.variabletype =:= 'Counter64' ->
- case validate_next_v1(do_get_next(MibView, [mk_next_oid(Vb)]), MibView) of
+ case validate_next_v1(
+ do_get_next(MibView, [mk_next_oid(Vb)], infinity), MibView) of
{noError, 0, [NVb]} ->
validate_next_v1_2(Vbs, MibView, [NVb | Res]);
{Error, Index, _OrgVb} ->
@@ -2963,59 +3090,97 @@ validate_tab_res(_TooMany, [], Mfa, _Res, I) ->
%% that this really matters, since many nexts across the same
%% subagent must be considered to be very rare.
%%-----------------------------------------------------------------
-do_get_next(MibView, UnsortedVarbinds) ->
- SortedVarbinds = oid_sort_varbindlist(UnsortedVarbinds),
- next_loop_varbinds([], SortedVarbinds, MibView, [], []).
-oid_sort_varbindlist(Vbs) ->
+%% It may be a bit agressive to check this already,
+%% but since it is a security measure, it makes sense.
+do_get_next(_MibView, UnsortedVarbinds, GbMaxVBs)
+ when (is_integer(GbMaxVBs) andalso (length(UnsortedVarbinds) > GbMaxVBs)) ->
+ {tooBig, 0, []}; % What is the correct index in this case?
+do_get_next(MibView, UnsortedVBs, GbMaxVBs) ->
+ ?vt("do_get_next -> entry when"
+ "~n MibView: ~p"
+ "~n UnsortedVBs: ~p", [MibView, UnsortedVBs]),
+ SortedVBs = oid_sort_vbs(UnsortedVBs),
+ ?vt("do_get_next -> "
+ "~n SortedVBs: ~p", [SortedVBs]),
+ next_loop_varbinds([], SortedVBs, MibView, [], [], GbMaxVBs).
+
+oid_sort_vbs(Vbs) ->
lists:keysort(#varbind.oid, Vbs).
+next_loop_varbinds(_, Vbs, _MibView, Res, _LAVb, GbMaxVBs)
+ when (is_integer(GbMaxVBs) andalso
+ ((length(Vbs) + length(Res)) > GbMaxVBs)) ->
+ {tooBig, 0, []}; % What is the correct index in this case?
+
%% LAVb is Last Accessible Vb
-next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) ->
+next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb, GbMaxVBs) ->
?vt("next_loop_varbinds -> entry when"
"~n Vb: ~p"
"~n MibView: ~p", [Vb, MibView]),
case varbind_next(Vb, MibView) of
endOfMibView ->
+ ?vt("next_loop_varbind -> endOfMibView", []),
RVb = if LAVb =:= [] -> Vb;
true -> LAVb
end,
NewVb = RVb#varbind{variabletype = 'NULL', value = endOfMibView},
- next_loop_varbinds([], Vbs, MibView, [NewVb | Res], []);
+ next_loop_varbinds([], Vbs, MibView, [NewVb | Res], [], GbMaxVBs);
+
{variable, ME, VarOid} when ((ME#me.access =/= 'not-accessible') andalso
(ME#me.access =/= 'write-only') andalso
(ME#me.access =/= 'accessible-for-notify')) ->
+ ?vt("next_loop_varbind -> variable: "
+ "~n ME: ~p"
+ "~n VarOid: ~p", [ME, VarOid]),
case try_get_instance(Vb, ME) of
{value, noValue, _NoSuchSomething} ->
+ ?vt("next_loop_varbind -> noValue", []),
%% Try next one
- NewVb = Vb#varbind{oid = VarOid, value = 'NULL'},
- next_loop_varbinds([], [NewVb | Vbs], MibView, Res, []);
+ NewVb = Vb#varbind{oid = VarOid,
+ value = 'NULL'},
+ next_loop_varbinds([], [NewVb | Vbs], MibView, Res, [],
+ GbMaxVBs);
{value, Type, Value} ->
- NewVb = Vb#varbind{oid = VarOid, variabletype = Type,
- value = Value},
- next_loop_varbinds([], Vbs, MibView, [NewVb | Res], []);
+ ?vt("next_loop_varbind -> value"
+ "~n Type: ~p"
+ "~n Value: ~p", [Type, Value]),
+ NewVb = Vb#varbind{oid = VarOid,
+ variabletype = Type,
+ value = Value},
+ next_loop_varbinds([], Vbs, MibView, [NewVb | Res], [],
+ GbMaxVBs);
{error, ErrorStatus} ->
?vdebug("next loop varbinds:"
"~n ErrorStatus: ~p",[ErrorStatus]),
{ErrorStatus, Vb#varbind.org_index, []}
end;
{variable, _ME, VarOid} ->
+ ?vt("next_loop_varbind -> variable: "
+ "~n VarOid: ~p", [VarOid]),
RVb = if LAVb =:= [] -> Vb;
true -> LAVb
end,
NewVb = Vb#varbind{oid = VarOid, value = 'NULL'},
- next_loop_varbinds([], [NewVb | Vbs], MibView, Res, RVb);
+ next_loop_varbinds([], [NewVb | Vbs], MibView, Res, RVb, GbMaxVBs);
{table, TableOid, TableRestOid, ME} ->
+ ?vt("next_loop_varbind -> table: "
+ "~n TableOid: ~p"
+ "~n TableRestOid: ~p"
+ "~n ME: ~p", [TableOid, TableRestOid, ME]),
next_loop_varbinds({table, TableOid, ME,
[{tab_oid(TableRestOid), Vb}]},
- Vbs, MibView, Res, []);
+ Vbs, MibView, Res, [], GbMaxVBs);
{subagent, SubAgentPid, SAOid} ->
+ ?vt("next_loop_varbind -> subagent: "
+ "~n SubAgentPid: ~p"
+ "~n SAOid: ~p", [SubAgentPid, SAOid]),
NewVb = Vb#varbind{variabletype = 'NULL', value = 'NULL'},
next_loop_varbinds({subagent, SubAgentPid, SAOid, [NewVb]},
- Vbs, MibView, Res, [])
+ Vbs, MibView, Res, [], GbMaxVBs)
end;
next_loop_varbinds({table, TableOid, ME, TabOids},
- [Vb | Vbs], MibView, Res, _LAVb) ->
+ [Vb | Vbs], MibView, Res, _LAVb, GbMaxVBs) ->
?vt("next_loop_varbinds(table) -> entry with"
"~n TableOid: ~p"
"~n Vb: ~p", [TableOid, Vb]),
@@ -3023,13 +3188,14 @@ next_loop_varbinds({table, TableOid, ME, TabOids},
{table, TableOid, TableRestOid, _ME} ->
next_loop_varbinds({table, TableOid, ME,
[{tab_oid(TableRestOid), Vb} | TabOids]},
- Vbs, MibView, Res, []);
+ Vbs, MibView, Res, [], GbMaxVBs);
_ ->
case get_next_table(ME, TableOid, TabOids, MibView) of
{ok, TabRes, TabEndOfTabVbs} ->
NewVbs = lists:append(TabEndOfTabVbs, [Vb | Vbs]),
NewRes = lists:append(TabRes, Res),
- next_loop_varbinds([], NewVbs, MibView, NewRes, []);
+ next_loop_varbinds([], NewVbs, MibView, NewRes, [],
+ GbMaxVBs);
{ErrorStatus, OrgIndex} ->
?vdebug("next loop varbinds: next varbind"
"~n ErrorStatus: ~p"
@@ -3039,7 +3205,7 @@ next_loop_varbinds({table, TableOid, ME, TabOids},
end
end;
next_loop_varbinds({table, TableOid, ME, TabOids},
- [], MibView, Res, _LAVb) ->
+ [], MibView, Res, _LAVb, GbMaxVBs) ->
?vt("next_loop_varbinds(table) -> entry with"
"~n TableOid: ~p", [TableOid]),
case get_next_table(ME, TableOid, TabOids, MibView) of
@@ -3048,7 +3214,8 @@ next_loop_varbinds({table, TableOid, ME, TabOids},
"~n TabRes: ~p"
"~n TabEndOfTabVbs: ~p", [TabRes, TabEndOfTabVbs]),
NewRes = lists:append(TabRes, Res),
- next_loop_varbinds([], TabEndOfTabVbs, MibView, NewRes, []);
+ next_loop_varbinds([], TabEndOfTabVbs, MibView, NewRes, [],
+ GbMaxVBs);
{ErrorStatus, OrgIndex} ->
?vdebug("next loop varbinds: next table"
"~n ErrorStatus: ~p"
@@ -3057,7 +3224,7 @@ next_loop_varbinds({table, TableOid, ME, TabOids},
{ErrorStatus, OrgIndex, []}
end;
next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
- [Vb | Vbs], MibView, Res, _LAVb) ->
+ [Vb | Vbs], MibView, Res, _LAVb, GbMaxVBs) ->
?vt("next_loop_varbinds(subagent) -> entry with"
"~n SAPid: ~p"
"~n SAOid: ~p"
@@ -3066,13 +3233,14 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
{subagent, _SubAgentPid, SAOid} ->
next_loop_varbinds({subagent, SAPid, SAOid,
[Vb | SAVbs]},
- Vbs, MibView, Res, []);
+ Vbs, MibView, Res, [], GbMaxVBs);
_ ->
case get_next_sa(SAPid, SAOid, SAVbs, MibView) of
{ok, SARes, SAEndOfMibViewVbs} ->
NewVbs = lists:append(SAEndOfMibViewVbs, [Vb | Vbs]),
NewRes = lists:append(SARes, Res),
- next_loop_varbinds([], NewVbs, MibView, NewRes, []);
+ next_loop_varbinds([], NewVbs, MibView, NewRes, [],
+ GbMaxVBs);
{noSuchName, OrgIndex} ->
%% v1 reply, treat this Vb as endOfMibView, and try again
%% for the others.
@@ -3085,12 +3253,14 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
case lists:delete(EVb, SAVbs) of
[] ->
next_loop_varbinds([], [EndOfVb, Vb | Vbs],
- MibView, Res, []);
+ MibView, Res, [],
+ GbMaxVBs);
TryAgainVbs ->
next_loop_varbinds({subagent, SAPid, SAOid,
TryAgainVbs},
[EndOfVb, Vb | Vbs],
- MibView, Res, [])
+ MibView, Res, [],
+ GbMaxVBs)
end;
false ->
%% bad index from subagent
@@ -3106,14 +3276,15 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
end
end;
next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
- [], MibView, Res, _LAVb) ->
+ [], MibView, Res, _LAVb, GbMaxVBs) ->
?vt("next_loop_varbinds(subagent) -> entry with"
"~n SAPid: ~p"
"~n SAOid: ~p", [SAPid, SAOid]),
case get_next_sa(SAPid, SAOid, SAVbs, MibView) of
{ok, SARes, SAEndOfMibViewVbs} ->
NewRes = lists:append(SARes, Res),
- next_loop_varbinds([], SAEndOfMibViewVbs, MibView, NewRes, []);
+ next_loop_varbinds([], SAEndOfMibViewVbs, MibView, NewRes, [],
+ GbMaxVBs);
{noSuchName, OrgIndex} ->
%% v1 reply, treat this Vb as endOfMibView, and try again for
%% the others.
@@ -3124,11 +3295,13 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
value = {endOfMibView, NextOid}},
case lists:delete(EVb, SAVbs) of
[] ->
- next_loop_varbinds([], [EndOfVb], MibView, Res, []);
+ next_loop_varbinds([], [EndOfVb], MibView, Res, [],
+ GbMaxVBs);
TryAgainVbs ->
next_loop_varbinds({subagent, SAPid, SAOid,
TryAgainVbs},
- [EndOfVb], MibView, Res, [])
+ [EndOfVb], MibView, Res, [],
+ GbMaxVBs)
end;
false ->
%% bad index from subagent
@@ -3141,12 +3314,15 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs},
[ErrorStatus,OrgIndex]),
{ErrorStatus, OrgIndex, []}
end;
-next_loop_varbinds([], [], _MibView, Res, _LAVb) ->
+next_loop_varbinds([], [], _MibView, Res, _LAVb, _GbMaxVBs) ->
?vt("next_loop_varbinds -> entry when done", []),
{noError, 0, Res}.
try_get_instance(_Vb, #me{mfa = {M, F, A}, asn1_type = ASN1Type}) ->
- ?vtrace("try get instance from <~p,~p,~p>",[M,F,A]),
+ ?vtrace("try_get_instance -> entry with"
+ "~n M: ~p"
+ "~n F: ~p"
+ "~n A: ~p", [M,F,A]),
Result = (catch dbg_apply(M, F, [get | A])),
% mib shall return {value, <a-nice-value-within-range>} |
% {noValue, noSuchName} (v1) |
@@ -3157,6 +3333,7 @@ try_get_instance(_Vb, #me{mfa = {M, F, A}, asn1_type = ASN1Type}) ->
tab_oid([]) -> [0];
tab_oid(X) -> X.
+
%%-----------------------------------------------------------------
%% Perform a next, using the varbinds Oid if value is simple
%% value. If value is {endOf<something>, NextOid}, use NextOid.
@@ -3403,22 +3580,30 @@ next_oid(Oid) ->
%%%-----------------------------------------------------------------
%%% 5. GET-BULK REQUEST
+%%%
+%%% In order to prevent excesses in reply sizes there are two
+%%% preventive methods in place. One is to check that the encode
+%%% size does not exceed Max PDU size (this is mentioned in the
+%%% standard). The other is a simple VBs limit. That is, the
+%%% resulting response cannot contain more then this number of VBs.
%%%-----------------------------------------------------------------
-do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) ->
- ?vtrace("do get bulk: start with"
+
+do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds, GbMaxVBs) ->
+ ?vtrace("do_get_bulk -> entry with"
"~n MibView: ~p"
"~n NonRepeaters: ~p"
"~n MaxRepetitions: ~p"
"~n PduMS: ~p"
- "~n Varbinds: ~p",
- [MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds]),
+ "~n Varbinds: ~p"
+ "~n GbMaxVBs: ~p",
+ [MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds, GbMaxVBs]),
{NonRepVbs, RestVbs} = split_vbs(NonRepeaters, Varbinds, []),
- ?vt("do get bulk -> split: "
+ ?vt("do_get_bulk -> split: "
"~n NonRepVbs: ~p"
"~n RestVbs: ~p", [NonRepVbs, RestVbs]),
- case do_get_next(MibView, NonRepVbs) of
- {noError, 0, UResNonRepVbs} ->
- ?vt("do get bulk -> next: "
+ case do_get_next(MibView, NonRepVbs, GbMaxVBs) of
+ {noError, 0, UResNonRepVbs} ->
+ ?vt("do_get_bulk -> next noError: "
"~n UResNonRepVbs: ~p", [UResNonRepVbs]),
ResNonRepVbs = lists:keysort(#varbind.org_index, UResNonRepVbs),
%% Decode the first varbinds, produce a reversed list of
@@ -3428,11 +3613,12 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) ->
user_err("failed encoding varbind ~w:~n~p", [Idx, Reason]),
{genErr, Idx, []};
{SizeLeft, Res} when is_integer(SizeLeft) and is_list(Res) ->
- ?vtrace("do get bulk -> encoded: "
+ ?vtrace("do_get_bulk -> encoded: "
"~n SizeLeft: ~p"
"~n Res: ~w", [SizeLeft, Res]),
case (catch do_get_rep(SizeLeft, MibView, MaxRepetitions,
- RestVbs, Res)) of
+ RestVbs, Res,
+ length(UResNonRepVbs), GbMaxVBs)) of
{error, Idx, Reason} ->
user_err("failed encoding varbind ~w:~n~p",
[Idx, Reason]),
@@ -3441,6 +3627,10 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) ->
?vtrace("do get bulk -> Res: "
"~n ~w", [Res]),
{noError, 0, conv_res(Res)};
+ {noError, 0, Data} = OK ->
+ ?vtrace("do get bulk -> OK: "
+ "~n length(Data): ~w", [length(Data)]),
+ OK;
Else ->
?vtrace("do get bulk -> Else: "
"~n ~w", [Else]),
@@ -3449,6 +3639,7 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) ->
Res when is_list(Res) ->
{noError, 0, conv_res(Res)}
end;
+
{ErrorStatus, Index, _} ->
?vdebug("do get bulk: "
"~n ErrorStatus: ~p"
@@ -3498,11 +3689,12 @@ enc_vbs(SizeLeft, Vbs) ->
end,
lists:foldl(Fun, {SizeLeft, []}, Vbs).
-do_get_rep(Sz, MibView, MaxRepetitions, Varbinds, Res)
+do_get_rep(Sz, MibView, MaxRepetitions, Varbinds, Res, GbNumVBs, GbMaxVBs)
when MaxRepetitions >= 0 ->
- do_get_rep(Sz, MibView, 0, MaxRepetitions, Varbinds, Res);
-do_get_rep(Sz, MibView, _MaxRepetitions, Varbinds, Res) ->
- do_get_rep(Sz, MibView, 0, 0, Varbinds, Res).
+ do_get_rep(Sz, MibView, 0, MaxRepetitions, Varbinds, Res,
+ GbNumVBs, GbMaxVBs);
+do_get_rep(Sz, MibView, _MaxRepetitions, Varbinds, Res, GbNumVBs, GbMaxVBs) ->
+ do_get_rep(Sz, MibView, 0, 0, Varbinds, Res, GbNumVBs, GbMaxVBs).
conv_res(ResVarbinds) ->
conv_res(ResVarbinds, []).
@@ -3511,22 +3703,30 @@ conv_res([VbListOfBytes | T], Bytes) ->
conv_res([], Bytes) ->
Bytes.
-do_get_rep(_Sz, _MibView, Max, Max, _, Res) ->
+%% The only other value, then a positive integer, is infinity.
+do_get_rep(_Sz, _MibView, Count, Max, _, _Res, GbNumVBs, GbMaxVBs)
+ when (is_integer(GbMaxVBs) andalso (GbNumVBs > GbMaxVBs)) ->
+ ?vinfo("Max Get-BULK VBs limit (~w) exceeded (~w) when:"
+ "~n Count: ~p"
+ "~n Max: ~p", [GbMaxVBs, GbNumVBs, Count, Max]),
+ {tooBig, 0, []};
+do_get_rep(_Sz, _MibView, Max, Max, _, Res, _GbNumVBs, _GbMaxVBs) ->
?vt("do_get_rep -> done when: "
"~n Res: ~p", [Res]),
{noError, 0, conv_res(Res)};
-do_get_rep(Sz, MibView, Count, Max, Varbinds, Res) ->
+do_get_rep(Sz, MibView, Count, Max, Varbinds, Res, GbNumVBs, GbMaxVBs) ->
?vt("do_get_rep -> entry when: "
"~n Sz: ~p"
"~n Count: ~p"
"~n Res: ~w", [Sz, Count, Res]),
- case try_get_bulk(Sz, MibView, Varbinds) of
+ case try_get_bulk(Sz, MibView, Varbinds, GbMaxVBs) of
{noError, NextVarbinds, SizeLeft, Res2} ->
?vt("do_get_rep -> noError: "
"~n SizeLeft: ~p"
"~n Res2: ~p", [SizeLeft, Res2]),
do_get_rep(SizeLeft, MibView, Count+1, Max, NextVarbinds,
- Res2 ++ Res);
+ Res2 ++ Res,
+ GbNumVBs + length(Varbinds), GbMaxVBs);
{endOfMibView, _NextVarbinds, _SizeLeft, Res2} ->
?vt("do_get_rep -> endOfMibView: "
"~n Res2: ~p", [Res2]),
@@ -3538,22 +3738,29 @@ do_get_rep(Sz, MibView, Count, Max, Varbinds, Res) ->
{ErrorStatus, Index, []}
end.
-try_get_bulk(Sz, MibView, Varbinds) ->
+org_index_sort_vbs(Vbs) ->
+ lists:keysort(#varbind.org_index, Vbs).
+
+try_get_bulk(Sz, MibView, Varbinds, GbMaxVBs) ->
?vt("try_get_bulk -> entry with"
- "~n Sz: ~w", [Sz]),
- case do_get_next(MibView, Varbinds) of
+ "~n Sz: ~w"
+ "~n MibView: ~w"
+ "~n Varbinds: ~w", [Sz, MibView, Varbinds]),
+ case do_get_next(MibView, Varbinds, GbMaxVBs) of
{noError, 0, UNextVarbinds} ->
- ?vt("try_get_bulk -> noError", []),
- NextVarbinds = lists:keysort(#varbind.org_index, UNextVarbinds),
+ ?vt("try_get_bulk -> noError: "
+ "~n UNextVarbinds: ~p", [UNextVarbinds]),
+ NextVarbinds = org_index_sort_vbs(UNextVarbinds),
case (catch enc_vbs(Sz, NextVarbinds)) of
{error, Idx, Reason} ->
user_err("failed encoding varbind ~w:~n~p", [Idx, Reason]),
- ?vtrace("try_get_bulk -> error: "
+ ?vtrace("try_get_bulk -> encode error: "
"~n Idx: ~p"
"~n Reason: ~p", [Idx, Reason]),
{genErr, Idx};
- {SizeLeft, Res} when is_integer(SizeLeft) andalso is_list(Res) ->
- ?vt("try get bulk -> "
+ {SizeLeft, Res} when is_integer(SizeLeft) andalso
+ is_list(Res) ->
+ ?vt("try get bulk -> encode ok: "
"~n SizeLeft: ~w"
"~n Res: ~w", [SizeLeft, Res]),
{check_end_of_mibview(NextVarbinds),
@@ -3564,9 +3771,9 @@ try_get_bulk(Sz, MibView, Varbinds) ->
{endOfMibView, [], 0, Res}
end;
{ErrorStatus, Index, _} ->
- ?vt("try get bulk: "
+ ?vt("try_get_bulk -> error: "
"~n ErrorStatus: ~p"
- "~n Index: ~p",[ErrorStatus, Index]),
+ "~n Index: ~p", [ErrorStatus, Index]),
{ErrorStatus, Index}
end.
@@ -3707,9 +3914,8 @@ get_err({ErrC, ErrI, Vbs}) ->
{get_err_i(ErrC), ErrI, Vbs}.
get_err_i(noError) -> noError;
-get_err_i(S) ->
- ?vtrace("convert '~p' to 'genErr'",[S]),
- genErr.
+get_err_i(tooBig) -> tooBig; % OTP-9700
+get_err_i(ES) -> ?vtrace("convert ErrorStatus '~p' to 'genErr'", [ES]), genErr.
v2err_to_v1err(noError) -> noError;
v2err_to_v1err(noAccess) -> noSuchName;
@@ -3935,6 +4141,7 @@ mapfoldl(F, Eas, Accu0, [Hd|Tail]) ->
{Accu2,[R|Rs]};
mapfoldl(_F, _Eas, Accu, []) -> {Accu,[]}.
+
%%-----------------------------------------------------------------
%% Runtime debugging of the agent.
%%-----------------------------------------------------------------
@@ -4001,6 +4208,18 @@ subagents_verbosity(_,_V) ->
%% ---------------------------------------------------------------------
+local_engine_id(#state{type = master_agent}) ->
+ ?DEFAULT_LOCAL_ENGINE_ID;
+local_engine_id(_) ->
+ %% 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.
+ ignore.
+
+
+%% ---------------------------------------------------------------------
+
handle_get_log_type(#state{net_if_mod = Mod})
when Mod =/= undefined ->
case (catch Mod:get_log_type(get(net_if))) of
@@ -4047,7 +4266,7 @@ handle_set_request_limit(_, _) ->
{error, not_supported}.
-agent_info(#state{worker = W, set_worker = SW}) ->
+agent_info(#state{worker = W, set_worker = SW}) ->
case (catch get_agent_info(W, SW)) of
Info when is_list(Info) ->
Info;
@@ -4206,6 +4425,9 @@ get_multi_threaded(Opts) ->
get_versions(Opts) ->
get_option(versions, Opts, [v1,v2,v3]).
+get_gb_max_vbs(Opts) ->
+ get_option(gb_max_vbs, Opts, infinity).
+
get_note_store_opt(Opts) ->
get_option(note_store, Opts, []).
diff --git a/lib/snmp/src/agent/snmpa_internal.hrl b/lib/snmp/src/agent/snmpa_internal.hrl
index a490a78f84..6537562d44 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,9 +22,19 @@
-include_lib("snmp/src/app/snmp_internal.hrl").
--define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()).
+%% The DEFAULT_LOCAL_ENGINE_ID macro can only be used by the master_agent!!
+-define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()).
-define(DEFAULT_NOTIF_EXTRA_INFO, {snmpa_default_notification_extra_info}).
+%% -- Max number of VBs in a Get-BULK response --
+%% (( The default value, 1000, is *way* more ))
+%% (( then there is room for in a normal pdu ))
+%% (( (unless the max pdu size has been ))
+%% (( cranked way up), so this value should ))
+%% (( suffice as "infinity" without actually ))
+%% (( causing memory issues for the VM ... ))
+-define(DEFAULT_GB_MAX_VBS, 1000).
+
-define(snmpa_info(F, A), ?snmp_info("agent", F, A)).
-define(snmpa_warning(F, A), ?snmp_warning("agent", F, A)).
-define(snmpa_error(F, A), ?snmp_error("agent", F, A)).
diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl
index d9d6e633de..2c0cad807a 100644
--- a/lib/snmp/src/agent/snmpa_local_db.erl
+++ b/lib/snmp/src/agent/snmpa_local_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -486,7 +486,11 @@ handle_call({match, Name, Db, Pattern}, _From, State) ->
L1 = match(Db, Name, Pattern, State),
{reply, lists:delete([undef], L1), State};
-handle_call({backup, BackupDir}, From, #state{dets = Dets} = State) ->
+%% This check (that there is no backup already in progress) is also
+%% done in the master agent process, but just in case a user issues
+%% a backup call to this process directly, we add a similar check here.
+handle_call({backup, BackupDir}, From,
+ #state{backup = undefined, dets = Dets} = State) ->
?vlog("backup: ~p",[BackupDir]),
Pid = self(),
V = get(verbosity),
@@ -511,6 +515,10 @@ handle_call({backup, BackupDir}, From, #state{dets = Dets} = State) ->
{reply, Error, State}
end;
+handle_call({backup, _BackupDir}, _From, #state{backup = Backup} = S) ->
+ ?vinfo("backup already in progress: ~p", [Backup]),
+ {reply, {error, backup_in_progress}, S};
+
handle_call(dump, _From, #state{dets = Dets} = State) ->
?vlog("dump",[]),
dets_sync(Dets),
@@ -1110,7 +1118,7 @@ table_func(is_set_ok, RowIndex, Cols, NameDb) ->
table_func(set, RowIndex, Cols, NameDb) ->
snmp_generic:table_set_row(NameDb,
nofunc,
- {snmp_generic, table_try_make_consistent},
+ fun snmp_generic:table_try_make_consistent/3,
RowIndex,
Cols);
diff --git a/lib/snmp/src/agent/snmpa_mib.erl b/lib/snmp/src/agent/snmpa_mib.erl
index ce90db18b3..575a018c0c 100644
--- a/lib/snmp/src/agent/snmpa_mib.erl
+++ b/lib/snmp/src/agent/snmpa_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -552,8 +552,12 @@ handle_call({dump, File}, _From, #state{data = Data} = State) ->
Reply = snmpa_mib_data:dump(Data, File),
{reply, Reply, State};
-handle_call({backup, BackupDir}, From, #state{data = Data} = State) ->
- ?vlog("backup to ~s",[BackupDir]),
+%% This check (that there is no backup already in progress) is also
+%% done in the master agent process, but just in case a user issues
+%% a backup call to this process directly, we add a similar check here.
+handle_call({backup, BackupDir}, From,
+ #state{backup = undefined, data = Data} = State) ->
+ ?vlog("backup to ~s", [BackupDir]),
Pid = self(),
V = get(verbosity),
case file:read_file_info(BackupDir) of
@@ -576,6 +580,10 @@ handle_call({backup, BackupDir}, From, #state{data = Data} = State) ->
{reply, Error, State}
end;
+handle_call({backup, _BackupDir}, _From, #state{backup = Backup} = S) ->
+ ?vinfo("backup already in progress: ~p", [Backup]),
+ {reply, {error, backup_in_progress}, S};
+
handle_call(stop, _From, State) ->
?vlog("stop",[]),
{stop, normal, ok, State};
diff --git a/lib/snmp/src/agent/snmpa_mib_lib.erl b/lib/snmp/src/agent/snmpa_mib_lib.erl
index 078e681945..529a65a1f1 100644
--- a/lib/snmp/src/agent/snmpa_mib_lib.erl
+++ b/lib/snmp/src/agent/snmpa_mib_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,23 +61,23 @@ table_del_row({Tab, Db} = TabDb, Key) ->
get_table(NameDb, FOI) ->
(catch get_table(NameDb, FOI, [], [])).
-get_table(NameDb, FOI, Oid, Acc) ->
- case table_next(NameDb, Oid) of
+get_table(NameDb, FOI, Key, Acc) ->
+ case table_next(NameDb, Key) of
endOfTable ->
?vdebug("end of table",[]),
{ok, lists:reverse(Acc)};
- Oid ->
+ Key ->
%% Crap, circular ref
- ?vinfo("cyclic reference: ~w -> ~w", [Oid,Oid]),
- throw({error, {cyclic_db_reference, Oid, Acc}});
- NextOid ->
- ?vtrace("get row for oid ~w", [NextOid]),
- case table_get_row(NameDb, NextOid, FOI) of
+ ?vinfo("cyclic reference: ~w -> ~w", [Key, Key]),
+ throw({error, {cyclic_db_reference, Key, Acc}});
+ NextKey ->
+ ?vtrace("get row for key ~w", [NextKey]),
+ case table_get_row(NameDb, NextKey, FOI) of
undefined ->
- throw({error, {invalid_rowindex, NextOid, Acc}});
+ throw({error, {invalid_rowindex, NextKey, Acc}});
Row ->
?vtrace("row: ~w", [Row]),
- get_table(NameDb, FOI, NextOid, [{NextOid, Row}|Acc])
+ get_table(NameDb, FOI, NextKey, [{NextKey, Row}|Acc])
end
end.
diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl
index 4f50b1a674..2d37ea56f0 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -468,15 +468,10 @@ v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log) ->
_ ->
%% 4.2.2.1.2
NIsReportable = snmp_misc:is_reportable_pdu(Type),
- Val = inc(snmpUnknownPDUHandlers),
ErrorInfo =
- {#varbind{oid = ?snmpUnknownPDUHandlers,
- variabletype = 'Counter32',
- value = Val},
- SecName,
- [{securityLevel, SecLevel},
- {contextEngineID, ContextEngineID},
- {contextName, ContextName}]},
+ snmpUnknownPDUHandlers_ei(SecName, SecLevel,
+ ContextEngineID,
+ ContextName),
case generate_v3_report_msg(MsgID,
MsgSecurityModel,
Data, LocalEngineID,
@@ -507,6 +502,21 @@ v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log) ->
end
end.
+make_error_info(Variable, Oid, SecName, Opts) ->
+ Val = inc(Variable),
+ VB = #varbind{oid = Oid,
+ variabletype = 'Counter32',
+ value = Val},
+ {VB, SecName, Opts}.
+
+snmpUnknownPDUHandlers_ei(SecName, SecLevel,
+ ContextEngineID, ContextName) ->
+ Opts = [{securityLevel, SecLevel},
+ {contextEngineID, ContextEngineID},
+ {contextName, ContextName}],
+ make_error_info(snmpUnknownPDUHandlers,
+ ?snmpUnknownPDUHandlers_instance,
+ SecName, Opts).
get_security_module(?SEC_USM) ->
snmpa_usm;
diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl
index 00c77a0cdb..f5218d5409 100644
--- a/lib/snmp/src/agent/snmpa_set_lib.erl
+++ b/lib/snmp/src/agent/snmpa_set_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
@@ -143,8 +143,8 @@ consistency_check(Varbinds) ->
consistency_check(Varbinds, []).
consistency_check([{TableOid, TableVbs} | Varbinds], Done) ->
?vtrace("consistency_check -> entry with"
- "~n TableOid: ~p"
- "~n TableVbs: ~p",[TableOid,TableVbs]),
+ "~n TableOid: ~p"
+ "~n TableVbs: ~p", [TableOid, TableVbs]),
TableOpsWithShortOids = deletePrefixes(TableOid, TableVbs),
[#ivarbind{mibentry = MibEntry}|_] = TableVbs,
case is_set_ok_table(MibEntry, TableOpsWithShortOids) of
@@ -158,7 +158,7 @@ consistency_check([{TableOid, TableVbs} | Varbinds], Done) ->
end;
consistency_check([IVarbind | Varbinds], Done) ->
?vtrace("consistency_check -> entry with"
- "~n IVarbind: ~p",[IVarbind]),
+ "~n IVarbind: ~p", [IVarbind]),
#ivarbind{varbind = Varbind, mibentry = MibEntry} = IVarbind,
#varbind{value = Value, org_index = OrgIndex} = Varbind,
case is_set_ok_variable(MibEntry, Value) of
@@ -358,38 +358,54 @@ make_value_a_correct_value(Value, ASN1Type, Mfa) ->
%% Runtime debug support
%%-----------------------------------------------------------------
-% XXX: This function match on the exakt return codes from EXIT
-% messages. As of this writing it was not decided if this is
-% the right way so don't blindly do things this way.
-%
-% We fake a real EXIT signal as the return value because the
-% result is passed to the function snmpa_agent:validate_err()
-% that expect it.
+%% XYZ: This function match on the exakt return codes from EXIT
+%% messages. As of this writing it was not decided if this is
+%% the right way so don't blindly do things this way.
+%%
+%% We fake a real EXIT signal as the return value because the
+%% result is passed to the function snmpa_agent:validate_err()
+%% that expect it.
dbg_apply(M,F,A) ->
- Result =
- case get(verbosity) of
- false ->
- (catch apply(M,F,A));
- _ ->
- ?vlog("~n apply: ~w,~w,~p~n", [M,F,A]),
- Res = (catch apply(M,F,A)),
- ?vlog("~n returned: ~p", [Res]),
- Res
- end,
- case Result of
- {'EXIT', {undef, [{M, F, A, _} | _]}} ->
- {'EXIT', {hook_undef, {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', {hook_undef, {M, F, A}}};
- {'EXIT', {function_clause, {M, F, A, _}}} ->
- {'EXIT', {hook_function_clause, {M, F, A}}};
-
- Result ->
- Result
+ case maybe_verbose_apply(M, F, A) of
+ %% <Future proofing>
+ %% As of R15 we get extra info containing,
+ %% among other things, line numbers.
+ {'EXIT', {undef, [{M, F, A, _} | _]}} ->
+ {'EXIT', {hook_undef, {M, F, A}}};
+ {'EXIT', {function_clause, [{M, F, A, _} | _]}} ->
+ {'EXIT', {hook_function_clause, {M, F, A}}};
+
+ %% This is really overkill, but just to be on the safe side...
+ {'EXIT', {undef, {M, F, A, _}}} ->
+ {'EXIT', {hook_undef, {M, F, A}}};
+ {'EXIT', {function_clause, {M, F, A, _}}} ->
+ {'EXIT', {hook_function_clause, {M, F, A}}};
+ %% </Future proofing>
+
+ %% Old format format for compatibility
+ {'EXIT', {undef, [{M, F, A} | _]}} ->
+ {'EXIT', {hook_undef, {M, F, A}}};
+ {'EXIT', {function_clause, [{M, F, A} | _]}} ->
+ {'EXIT', {hook_function_clause, {M, F, A}}};
+
+ % XYZ: Older format for compatibility
+ {'EXIT', {undef, {M, F, A}}} ->
+ {'EXIT', {hook_undef, {M, F, A}}};
+ {'EXIT', {function_clause, {M, F, A}}} ->
+ {'EXIT', {hook_function_clause, {M, F, A}}};
+
+ Result ->
+ Result
end.
+maybe_verbose_apply(M, F, A) ->
+ case get(verbosity) of
+ false ->
+ (catch apply(M,F,A));
+ _ ->
+ ?vlog("~n apply: ~w,~w,~p~n", [M,F,A]),
+ Res = (catch apply(M,F,A)),
+ ?vlog("~n returned: ~p", [Res]),
+ Res
+ end.
diff --git a/lib/snmp/src/agent/snmpa_supervisor.erl b/lib/snmp/src/agent/snmpa_supervisor.erl
index 5ef5914e18..886fd074bc 100644
--- a/lib/snmp/src/agent/snmpa_supervisor.erl
+++ b/lib/snmp/src/agent/snmpa_supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,8 +176,8 @@ init([AgentType, Opts]) ->
"~n AgentType: ~p"
"~n Opts: ~p", [AgentType, Opts]),
- put(sname, asup),
- put(verbosity,get_verbosity(Opts)),
+ put(sname, asup),
+ put(verbosity, get_verbosity(Opts)),
?vlog("starting",[]),
@@ -203,7 +203,12 @@ init([AgentType, Opts]) ->
Vsns = get_opt(versions, Opts, [v1,v2,v3]),
?vdebug("[agent table] store versions: ~p",[Vsns]),
ets:insert(snmp_agent_table, {versions, Vsns}),
-
+
+ %% -- Max number of VBs in a Get-BULK response --
+ GbMaxVBs = get_gb_max_vbs(Opts),
+ ?vdebug("[agent table] Get-BULK max VBs: ~p", [GbMaxVBs]),
+ ets:insert(snmp_agent_table, {gb_max_vbs, GbMaxVBs}),
+
%% -- DB-directory --
DbDir = get_opt(db_dir, Opts),
?vdebug("[agent table] store db_dir: ~n ~p",[DbDir]),
@@ -377,7 +382,8 @@ init([AgentType, Opts]) ->
{versions, Vsns},
{net_if, NiOpts},
{mib_server, MibsOpts},
- {note_store, NsOpts}|
+ {note_store, NsOpts},
+ {gb_max_vbs, GbMaxVBs} |
get_opt(master_agent_options, Opts, [])],
AgentSpec =
@@ -542,6 +548,32 @@ get_verbosity(Opts) ->
get_agent_type(Opts) ->
get_opt(agent_type, Opts, master).
+
+%% We validate this option! This should really be done for all
+%% options, but it is beyond the scope of this ticket, OTP-9700.
+
+get_gb_max_vbs(Opts) ->
+ Validate =
+ fun(GbMaxVBs)
+ when ((is_integer(GbMaxVBs) andalso (GbMaxVBs > 0)) orelse
+ (GbMaxVBs =:= infinity)) ->
+ ok;
+ (_) ->
+ error
+ end,
+ get_option(gb_max_vbs, ?DEFAULT_GB_MAX_VBS, Validate, Opts).
+
+get_option(Key, Default, Validate, Opts)
+ when is_list(Opts) andalso is_function(Validate) ->
+ Value = get_opt(Key, Opts, Default),
+ case Validate(Value) of
+ ok ->
+ Value;
+ error ->
+ exit({bad_option, Key, Value})
+ end.
+
+
get_opt(Key, Opts) ->
snmp_misc:get_option(Key, Opts).
diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl
index 567de020c0..b9a2496341 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -352,11 +352,26 @@ send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, ExtraInfo, NetIf) ->
send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
LocalEngineID, ExtraInfo, NetIf).
+%% The agent normally does not care about the result,
+%% but since it can be usefull when debugging, add
+%% some info when we fail to send the trap(s).
send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID,
ExtraInfo, NetIf) ->
- (catch do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID, ExtraInfo, NetIf)).
-
+ try
+ begin
+ do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo, NetIf)
+ end
+ catch
+ T:E ->
+ Info = [{args, [TrapRec, NotifyName, ContextName,
+ Recv, Vbs, LocalEngineID, ExtraInfo, NetIf]},
+ {tag, T},
+ {err, E},
+ {stacktrace, erlang:get_stacktrace()}],
+ {error, {failed_sending_trap, Info}}
+ end.
+
do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
LocalEngineID, ExtraInfo, NetIf) ->
VarbindList = make_varbind_list(Vbs),
@@ -379,8 +394,13 @@ send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo) ->
get_values(VariablesWithType) ->
{Order, Varbinds} = extract_order(VariablesWithType, 1),
+ ?vtrace("get_values -> "
+ "~n Order: ~p"
+ "~n Varbinds: ~p", [Order, Varbinds]),
case snmpa_agent:do_get(snmpa_acm:get_root_mib_view(), Varbinds, true) of
{noError, _, NewVarbinds} ->
+ ?vtrace("get_values -> values retrieved"
+ "~n NewVarbinds: ~p", [NewVarbinds]),
%% NewVarbinds is the result of:
%% first a reverse, then a sort on the oid field and finally
%% a reverse during the get-processing so we need to re-sort
diff --git a/lib/snmp/src/agent/snmpa_vacm.erl b/lib/snmp/src/agent/snmpa_vacm.erl
index 892dc265f1..dadcf32543 100644
--- a/lib/snmp/src/agent/snmpa_vacm.erl
+++ b/lib/snmp/src/agent/snmpa_vacm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,13 @@ get_mib_view(ViewType, SecModel, SecName, SecLevel, ContextName) ->
%% Follows the procedure in rfc2275
auth(ViewType, SecModel, SecName, SecLevel, ContextName) ->
+ ?vtrace("auth -> entry with"
+ "~n ViewType: ~p"
+ "~n SecModel: ~p"
+ "~n SecName: ~p"
+ "~n SecLevel: ~p"
+ "~n ContextName: ~p",
+ [ViewType, SecModel, SecName, SecLevel, ContextName]),
% 3.2.1 - Check that the context is known to us
?vdebug("check that the context (~p) is known to us",[ContextName]),
case snmp_view_based_acm_mib:vacmContextTable(get, ContextName,
@@ -74,7 +81,7 @@ auth(ViewType, SecModel, SecName, SecLevel, ContextName) ->
end,
% 3.2.2 - Check that the SecModel and SecName is valid
?vdebug("check that SecModel (~p) and SecName (~p) is valid",
- [SecModel,SecName]),
+ [SecModel, SecName]),
GroupName =
case snmp_view_based_acm_mib:get(vacmSecurityToGroupTable,
[SecModel, length(SecName) | SecName],
@@ -111,6 +118,8 @@ check_auth(Res) -> {ok, Res}.
%% key in the table >= ViewIndex.
%%-----------------------------------------------------------------
get_mib_view(ViewName) ->
+ ?vtrace("get_mib_view -> entry with"
+ "~n ViewName: ~p", [ViewName]),
ViewKey = [length(ViewName) | ViewName],
case snmp_view_based_acm_mib:table_next(vacmViewTreeFamilyTable,
ViewKey) of
@@ -202,6 +211,13 @@ backup(BackupDir) ->
%% Ret: {ok, ViewName} | {error, Reason}
get_view_name(ViewType, GroupName, ContextName, SecModel, SecLevel) ->
+ ?vtrace("get_view_name -> entry with"
+ "~n ViewType: ~p"
+ "~n GroupName: ~p"
+ "~n ContextName: ~p"
+ "~n SecModel: ~p"
+ "~n SecLevel: ~p",
+ [ViewType, GroupName, ContextName, SecModel, SecLevel]),
GroupKey = [length(GroupName) | GroupName],
case get_access_row(GroupKey, ContextName, SecModel, SecLevel) of
undefined ->
@@ -266,9 +282,10 @@ dump_table(true) ->
dump_table(_) ->
ok.
+
dump_table() ->
[{_, FName}] = ets:lookup(snmp_agent_table, snmpa_vacm_file),
- TmpName = FName ++ ".tmp",
+ TmpName = unique_table_name(FName),
case ets:tab2file(snmpa_vacm, TmpName) of
ok ->
case file:rename(TmpName, FName) of
@@ -283,6 +300,35 @@ dump_table() ->
[FName, Reason])
end.
+%% This little thing is an attempt to create a "unique" filename
+%% in order to minimize the risk of two processes at the same
+%% time dumping the table.
+unique_table_name(Pre) ->
+ %% We want something that is guaranteed to be unique,
+ %% therefor we use erlang:now() instead of os:timestamp()
+ unique_table_name(Pre, erlang:now()).
+
+unique_table_name(Pre, {_A, _B, C} = 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_~w",
+ [YYYY, MM, DD, Hour, Min, Sec, round(C/1000)]),
+ unique_table_name2(Pre, FormatDate).
+
+unique_table_name2(Pre, FormatedDate) ->
+ PidPart = unique_table_name_pid(),
+ lists:flatten(io_lib:format("~s.~s~s.tmp", [Pre, PidPart, FormatedDate])).
+
+unique_table_name_pid() ->
+ case string:tokens(pid_to_list(self()), [$<,$.,$>]) of
+ [A, B, C] ->
+ A ++ B ++ C ++ ".";
+ _ ->
+ ""
+ end.
+
%%-----------------------------------------------------------------
%% Alg.
diff --git a/lib/snmp/src/app/Makefile b/lib/snmp/src/app/Makefile
index d89eb4e723..7a16d42c30 100644
--- a/lib/snmp/src/app/Makefile
+++ b/lib/snmp/src/app/Makefile
@@ -127,14 +127,14 @@ $(APPUP_TARGET): $(APPUP_SRC) ../../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/app
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/app
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/app"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src/app"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
- $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXT_HRL_FILES) $(RELSYSDIR)/include
+ "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXT_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/snmp/src/app/snmp.app.src b/lib/snmp/src/app/snmp.app.src
index a880a14696..b11c1ef934 100644
--- a/lib/snmp/src/app/snmp.app.src
+++ b/lib/snmp/src/app/snmp.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,6 +91,7 @@
snmpm_mpd,
snmpm_net_if,
snmpm_net_if_filter,
+ snmpm_net_if_mt,
snmpm_network_interface,
snmpm_network_interface_filter,
snmpm_server,
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 0b6ea93231..593ddd82bd 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,92 +22,289 @@
%% ----- U p g r a d e -------------------------------------------------------
[
- {"4.21",
+ {"4.22",
[
- {load_module, snmp_target_mib, soft_purge, soft_purge, []}
+ {load_module, snmpm, soft_purge, soft_purge, []},
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []}
]
},
- {"4.20.1",
+ {"4.21.7",
[
- {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]}
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
- {"4.20",
+ {"4.21.6",
[
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
{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]}
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
+ ]
+ },
+ {"4.21.5",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
+ ]
+ },
+ {"4.21.4",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
- {"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, []},
+ {"4.21.3",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
+ ]
+ },
+ {"4.21.2",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{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]}
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge, []},
+ {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
+ ]
+ },
+ {"4.21.1",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge, []},
+ {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
+ ]
+ },
+ {"4.21",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge, []},
+ {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
}
],
@@ -115,92 +312,290 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
- {"4.21",
+ {"4.22",
[
- {load_module, snmp_target_mib, soft_purge, soft_purge, []}
+ {load_module, snmpm, soft_purge, soft_purge, []},
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []}
]
},
- {"4.20.1",
+ {"4.21.7",
[
- {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]}
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
- {"4.20",
+ {"4.21.6",
[
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
{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]}
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
+ ]
+ },
+ {"4.21.5",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
+ ]
+ },
+ {"4.21.4",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
- {"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, []},
+ {"4.21.3",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
+ ]
+ },
+ {"4.21.2",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{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]}
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge, []},
+ {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
+ ]
+ },
+ {"4.21.1",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge, []},
+ {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
+ ]
+ },
+ {"4.21",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]},
+
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
+ {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {load_module, snmpa_vacm, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge, []},
+ {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
+ {load_module, snmpa_trap, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mib_lib]},
+ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
+ {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
+ {update, snmpa_mib, soft, soft_purge, soft_purge, []},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
}
]
diff --git a/lib/snmp/src/app/snmp.erl b/lib/snmp/src/app/snmp.erl
index 3e0f05e604..cd3e3a0055 100644
--- a/lib/snmp/src/app/snmp.erl
+++ b/lib/snmp/src/app/snmp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,6 +50,7 @@
read_mib/1,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
+ log_to_io/4, log_to_io/5, log_to_io/6,
change_log_size/2,
octet_string_to_bits/1, bits_to_octet_string/1,
@@ -843,6 +844,12 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start) ->
log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) ->
snmp_log:log_to_txt(LogName, LogFile, LogDir, Mibs, OutFile, Start, Stop).
+log_to_io(LogDir, Mibs, LogName, LogFile) ->
+ snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start) ->
+ snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs, Start).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) ->
+ snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs, Start, Stop).
change_log_size(LogName, NewSize) ->
snmp_log:change_size(LogName, NewSize).
diff --git a/lib/snmp/src/compile/Makefile b/lib/snmp/src/compile/Makefile
index 627af6f185..9658ee0005 100644
--- a/lib/snmp/src/compile/Makefile
+++ b/lib/snmp/src/compile/Makefile
@@ -120,13 +120,13 @@ $(GENERATED_PARSER): $(PARSER_SRC)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(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) $(EBIN_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/bin
- $(INSTALL_SCRIPT) $(ESCRIPT_BIN) $(RELSYSDIR)/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(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) $(EBIN_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/bin"
+ $(INSTALL_SCRIPT) $(ESCRIPT_BIN) "$(RELSYSDIR)/bin"
release_docs_spec:
diff --git a/lib/snmp/src/compile/depend.mk b/lib/snmp/src/compile/depend.mk
index f7084f8bcd..3ee8dc4bec 100644
--- a/lib/snmp/src/compile/depend.mk
+++ b/lib/snmp/src/compile/depend.mk
@@ -44,6 +44,6 @@ $(EBIN)/snmpc_mib_gram.$(EMULATOR): \
../../include/snmp_types.hrl \
snmpc_mib_gram.erl
-$(BIN)/snmpc: snmpc.src
+$(BIN)/snmpc: snmpc.src ../../vsn.mk
$(PERL) -p -e 's?%VSN%?$(VSN)? ' < $< > $@
chmod 755 $@
diff --git a/lib/snmp/src/compile/snmpc.src b/lib/snmp/src/compile/snmpc.src
index f993335b89..6eb95be35e 100644
--- a/lib/snmp/src/compile/snmpc.src
+++ b/lib/snmp/src/compile/snmpc.src
@@ -74,7 +74,7 @@
%% --rrnac
%% --version
%% --verbosity V
-%% --warnings
+%% --warnings | --W
%% --Werror | --wae | --warnings_as_errors
main(Args) when is_list(Args) ->
case (catch process_args(Args)) of
@@ -221,7 +221,10 @@ process_args([], #state{verbosity = Verbosity0, file = MIB} = State) ->
process_args(["--help"|_Args], _State) ->
ok;
process_args(["--version"|_Args], #state{version = Version, mfv = MFV} = _State) ->
- {ok, lists:flatten(io_lib:format("snmpc ~s (~s)", [Version, MFV]))};
+ OtpVersion = otp_release(),
+ {ok, lists:flatten(
+ io_lib:format("snmpc ~s [Mib format version ~s] (OTP ~s)",
+ [Version, MFV, OtpVersion]))};
process_args(["--verbosity", Verbosity0|Args], #state{verbosity = V} = State)
when (V =:= undefined) ->
Verbosity = list_to_atom(Verbosity0),
@@ -234,7 +237,7 @@ 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(["--W"|Args], State) ->
process_args(Args, State#state{warnings = true});
process_args(["--warnings"|Args], State) ->
process_args(Args, State#state{warnings = true});
@@ -398,3 +401,15 @@ usage() ->
e(Reason) ->
throw({error, Reason}).
+otp_release() ->
+ system_info(otp_release, string).
+
+system_info(Tag, Type) ->
+ case (catch erlang:system_info(Tag)) of
+ {'EXIT', _} ->
+ "-";
+ Info when is_list(Info) andalso (Type =:= string) ->
+ Info;
+ Info ->
+ lists:flatten(io_lib:format("~w", [Info]))
+ end.
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index 38bb8f3ac6..c7eae307e8 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -704,23 +704,29 @@ check_trap_name(EnterpriseName, Line, MEs) ->
%% This information is needed to be able to create default instrumentation
%% functions for tables.
%%----------------------------------------------------------------------
-make_table_info(Line, _TableName, {augments,SrcTableEntry}, ColumnMEs) ->
+make_table_info(Line, TableName, {augments, SrcTableEntry}, ColumnMEs) ->
ColMEs = lists:keysort(#me.oid, ColumnMEs),
- %% Nbr_of_Cols = length(ColMEs),
+ Nbr_of_Cols = length(ColMEs),
MEs = ColMEs ++ (get(cdata))#cdata.mes,
- Aug = case lookup(SrcTableEntry,MEs) of
+ Aug = case lookup(SrcTableEntry, MEs) of
false ->
print_error("Cannot AUGMENT the non-existing table entry ~p",
- [SrcTableEntry],Line),
+ [SrcTableEntry], Line),
{augments, error};
- {value,ME} ->
- {augments, {SrcTableEntry,translate_type(ME#me.asn1_type)}}
+ {value, ME} ->
+ {augments, {SrcTableEntry, translate_type(ME#me.asn1_type)}}
end,
- #table_info{index_types = Aug};
-make_table_info(Line, TableName, {indexes,[]}, _ColumnMEs) ->
+ FirstNonIdxCol = augments_first_non_index_column(ColMEs),
+ NoAccs = list_not_accessible(FirstNonIdxCol, ColMEs),
+ FirstAcc = first_accessible(TableName, ColMEs),
+ #table_info{nbr_of_cols = Nbr_of_Cols,
+ first_accessible = FirstAcc,
+ not_accessible = NoAccs,
+ index_types = Aug};
+make_table_info(Line, TableName, {indexes, []}, _ColumnMEs) ->
print_error("Table ~w lacks indexes.", [TableName],Line),
#table_info{};
-make_table_info(Line, TableName, {indexes,Indexes}, ColumnMEs) ->
+make_table_info(Line, TableName, {indexes, Indexes}, ColumnMEs) ->
ColMEs = lists:keysort(#me.oid, ColumnMEs),
NonImpliedIndexes = lists:map(fun non_implied_name/1, Indexes),
test_read_create_access(ColMEs, Line, dummy),
@@ -860,11 +866,17 @@ get_asn1_type(ColumnName, MEs, Line) ->
end.
test_index_positions(Line, Indexes, ColMEs) ->
- TLI = lists:filter(fun (IndexName) ->
- is_table_local_index(IndexName,ColMEs) end,
- Indexes),
+ IsTLI = fun(IndexName) -> is_table_local_index(IndexName, ColMEs) end,
+ TLI = lists:filter(IsTLI, Indexes),
test_index_positions_impl(Line, TLI, ColMEs).
+%% An table that augments another cannot conatin any index,
+%% so the first non-index column is always the first column.
+augments_first_non_index_column([]) ->
+ none;
+augments_first_non_index_column([#me{oid=Col}|_ColMEs]) ->
+ Col.
+
%% Returns the first non-index column | none
test_index_positions_impl(_Line, [], []) -> none;
test_index_positions_impl(_Line, [], [#me{oid=Col}|_ColMEs]) ->
diff --git a/lib/snmp/src/manager/Makefile b/lib/snmp/src/manager/Makefile
index c1d5703300..1f30669f02 100644
--- a/lib/snmp/src/manager/Makefile
+++ b/lib/snmp/src/manager/Makefile
@@ -111,13 +111,13 @@ info:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/manager
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/manager
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
-# $(INSTALL_DIR) $(RELSYSDIR)/include
-# $(INSTALL_DATA) $(EXT_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/manager"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src/manager"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+# $(INSTALL_DIR) "$(RELSYSDIR)/include"
+# $(INSTALL_DATA) $(EXT_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/snmp/src/manager/depend.mk b/lib/snmp/src/manager/depend.mk
index 0e7e9e3df7..2e7783c8ed 100644
--- a/lib/snmp/src/manager/depend.mk
+++ b/lib/snmp/src/manager/depend.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -49,6 +49,13 @@ $(EBIN)/snmpm_net_if.$(EMULATOR): \
snmpm_net_if.erl \
snmpm_network_interface.erl
+$(EBIN)/snmpm_net_if_mt.$(EMULATOR): \
+ ../../include/snmp_types.hrl \
+ ../misc/snmp_debug.hrl \
+ ../misc/snmp_verbosity.hrl \
+ snmpm_net_if_mt.erl \
+ snmpm_network_interface.erl
+
$(EBIN)/snmpm_server.$(EMULATOR): \
../../include/snmp_types.hrl \
../../include/STANDARD-MIB.hrl \
diff --git a/lib/snmp/src/manager/modules.mk b/lib/snmp/src/manager/modules.mk
index 79f3dd65d9..d46545ea3f 100644
--- a/lib/snmp/src/manager/modules.mk
+++ b/lib/snmp/src/manager/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The 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,6 +31,7 @@ MODULES = \
snmpm_mpd \
snmpm_misc_sup \
snmpm_net_if \
+ snmpm_net_if_mt \
snmpm_net_if_filter \
snmpm_server \
snmpm_server_sup \
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index 6d2ac8d747..f590892c66 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,8 +75,11 @@
%%
%% Logging
+ log_to_txt/1,
log_to_txt/2, log_to_txt/3, log_to_txt/4,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
+ log_to_io/1, log_to_io/2, log_to_io/3,
+ log_to_io/4, log_to_io/5, log_to_io/6,
change_log_size/1,
get_log_type/0,
set_log_type/1,
@@ -1371,6 +1374,9 @@ cancel_async_request(UserId, ReqId) ->
%%%-----------------------------------------------------------------
%%% Audit Trail Log functions (for backward compatibility)
%%%-----------------------------------------------------------------
+
+log_to_txt(LogDir) ->
+ log_to_txt(LogDir, []).
log_to_txt(LogDir, Mibs) ->
OutFile = "snmpm_log.txt",
LogName = ?audit_trail_log_name,
@@ -1391,6 +1397,23 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) ->
snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop).
+log_to_io(LogDir) ->
+ log_to_io(LogDir, []).
+log_to_io(LogDir, Mibs) ->
+ LogName = ?audit_trail_log_name,
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName) ->
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop).
+
+
change_log_size(NewSize) ->
LogName = ?audit_trail_log_name,
snmp:change_log_size(LogName, NewSize).
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index c2e57abddb..5bbf9e5542 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index 103c87d32b..d7148bb4a4 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -110,9 +110,9 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) ->
#message{version = 'version-2', vsn_hdr = Community, data = Data}
when State#state.v2c =:= true ->
HS = ?empty_msg_size + length(Community),
- (catch process_v1_v2c_msg('version-2', NoteStore, Msg,
- Domain, Addr, Port,
- Community, Data, HS, Logger));
+ 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}
diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl
new file mode 100644
index 0000000000..3e87f6a7fb
--- /dev/null
+++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl
@@ -0,0 +1,1259 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmpm_net_if_mt).
+
+-behaviour(gen_server).
+-behaviour(snmpm_network_interface).
+
+
+%% Network Interface callback functions
+-export([
+ start_link/2,
+ stop/1,
+ send_pdu/6, % Backward compatibillity
+ send_pdu/7, % Backward compatibillity
+ send_pdu/8,
+
+ inform_response/4,
+
+ note_store/2,
+
+ info/1,
+ verbosity/2,
+ %% system_info_updated/2,
+ get_log_type/1, set_log_type/2,
+ filter_reset/1
+ ]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ code_change/3, terminate/2]).
+
+-define(SNMP_USE_V3, true).
+-include("snmp_types.hrl").
+-include("snmpm_internal.hrl").
+-include("snmpm_atl.hrl").
+-include("snmp_debug.hrl").
+
+%% -define(VMODULE,"NET_IF").
+-include("snmp_verbosity.hrl").
+
+-record(state,
+ {
+ server,
+ note_store,
+ sock,
+ mpd_state,
+ log,
+ irb = auto, % auto | {user, integer()}
+ irgc,
+ filter
+ }).
+
+
+-define(DEFAULT_FILTER_MODULE, snmpm_net_if_filter).
+-define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]).
+
+-ifdef(snmp_debug).
+-define(GS_START_LINK(Args),
+ gen_server:start_link(?MODULE, Args, [{debug,[trace]}])).
+-else.
+-define(GS_START_LINK(Args),
+ gen_server:start_link(?MODULE, Args, [])).
+-endif.
+
+
+-define(IRGC_TIMEOUT, timer:minutes(5)).
+
+-define(ATL_SEQNO_INITIAL, 1).
+-define(ATL_SEQNO_MAX, 2147483647).
+
+
+%%%-------------------------------------------------------------------
+%%% API
+%%%-------------------------------------------------------------------
+start_link(Server, NoteStore) ->
+ ?d("start_link -> entry with"
+ "~n Server: ~p"
+ "~n NoteStore: ~p", [Server, NoteStore]),
+ Args = [Server, NoteStore],
+ ?GS_START_LINK(Args).
+
+stop(Pid) ->
+ call(Pid, stop).
+
+send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) ->
+ send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO).
+
+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, Domain, Addr, Port]),
+ cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}).
+
+note_store(Pid, NoteStore) ->
+ call(Pid, {note_store, NoteStore}).
+
+inform_response(Pid, Ref, Addr, Port) ->
+ cast(Pid, {inform_response, Ref, Addr, Port}).
+
+info(Pid) ->
+ call(Pid, info).
+
+verbosity(Pid, V) ->
+ call(Pid, {verbosity, V}).
+
+%% system_info_updated(Pid, What) ->
+%% call(Pid, {system_info_updated, What}).
+
+get_log_type(Pid) ->
+ call(Pid, get_log_type).
+
+set_log_type(Pid, NewType) ->
+ call(Pid, {set_log_type, NewType}).
+
+filter_reset(Pid) ->
+ cast(Pid, filter_reset).
+
+
+%%%-------------------------------------------------------------------
+%%% Callback functions from gen_server
+%%%-------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%%--------------------------------------------------------------------
+init([Server, NoteStore]) ->
+ ?d("init -> entry with"
+ "~n Server: ~p"
+ "~n NoteStore: ~p", [Server, NoteStore]),
+ case (catch do_init(Server, NoteStore)) of
+ {error, Reason} ->
+ {stop, Reason};
+ {ok, State} ->
+ {ok, State}
+ end.
+
+do_init(Server, NoteStore) ->
+ process_flag(trap_exit, true),
+
+ %% -- Prio --
+ {ok, Prio} = snmpm_config:system_info(prio),
+ process_flag(priority, Prio),
+
+ %% -- Create inform request table --
+ %% This should really be protected, but it also needs to
+ %% be writable for the worker processes, so...
+ ets:new(snmpm_inform_request_table,
+ [set, public, named_table, {keypos, 1}]),
+
+ %% -- Verbosity --
+ {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity),
+ put(sname, mnif),
+ put(verbosity, Verbosity),
+ ?vlog("starting", []),
+
+ %% -- MPD --
+ {ok, Vsns} = snmpm_config:system_info(versions),
+ MpdState = snmpm_mpd:init(Vsns),
+ ?vdebug("MpdState: ~w", [MpdState]),
+
+ %% -- Module dependent options --
+ {ok, Opts} = snmpm_config:system_info(net_if_options),
+
+ %% -- Inform response behaviour --
+ {ok, IRB} = snmpm_config:system_info(net_if_irb),
+ IrGcRef = irgc_start(IRB),
+
+ %% -- Socket --
+ SndBuf = get_opt(Opts, sndbuf, default),
+ RecBuf = get_opt(Opts, recbuf, default),
+ BindTo = get_opt(Opts, bind_to, false),
+ NoReuse = get_opt(Opts, no_reuse, false),
+ {ok, Port} = snmpm_config:system_info(port),
+ {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, BindTo, NoReuse),
+
+ %% Flow control --
+ FilterOpts = get_opt(Opts, filter, []),
+ FilterMod = create_filter(FilterOpts),
+ ?vdebug("FilterMod: ~w", [FilterMod]),
+
+ %% -- Audit trail log ---
+ {ok, ATL} = snmpm_config:system_info(audit_trail_log),
+ Log = do_init_log(ATL),
+ ?vdebug("Log: ~w", [Log]),
+
+ %% -- Initiate counters ---
+ init_counters(),
+
+ %% -- We are done ---
+ State = #state{server = Server,
+ note_store = NoteStore,
+ mpd_state = MpdState,
+ sock = Sock,
+ log = Log,
+ irb = IRB,
+ irgc = IrGcRef,
+ filter = FilterMod},
+ ?vdebug("started", []),
+ {ok, State}.
+
+
+%% Open port
+do_open_port(Port, SendSz, RecvSz, BindTo, NoReuse) ->
+ ?vtrace("do_open_port -> entry with"
+ "~n Port: ~p"
+ "~n SendSz: ~p"
+ "~n RecvSz: ~p"
+ "~n BindTo: ~p"
+ "~n NoReuse: ~p", [Port, SendSz, RecvSz, BindTo, NoReuse]),
+ IpOpts1 = bind_to(BindTo),
+ IpOpts2 = no_reuse(NoReuse),
+ IpOpts3 = recbuf(RecvSz),
+ IpOpts4 = sndbuf(SendSz),
+ IpOpts = [binary | IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4],
+ OpenRes =
+ case init:get_argument(snmpm_fd) of
+ {ok, [[FdStr]]} ->
+ Fd = list_to_integer(FdStr),
+ gen_udp:open(0, [{fd, Fd}|IpOpts]);
+ error ->
+ gen_udp:open(Port, IpOpts)
+ end,
+ case OpenRes of
+ {error, _} = Error ->
+ throw(Error);
+ OK ->
+ OK
+ end.
+
+bind_to(true) ->
+ case snmpm_config:system_info(address) of
+ {ok, Addr} when is_list(Addr) ->
+ [{ip, list_to_tuple(Addr)}];
+ {ok, Addr} ->
+ [{ip, Addr}];
+ _ ->
+ []
+ end;
+bind_to(_) ->
+ [].
+
+no_reuse(false) ->
+ [{reuseaddr, true}];
+no_reuse(_) ->
+ [].
+
+recbuf(default) ->
+ [];
+recbuf(Sz) ->
+ [{recbuf, Sz}].
+
+sndbuf(default) ->
+ [];
+sndbuf(Sz) ->
+ [{sndbuf, Sz}].
+
+
+create_filter(Opts) when is_list(Opts) ->
+ case get_opt(Opts, module, ?DEFAULT_FILTER_MODULE) of
+ ?DEFAULT_FILTER_MODULE = Mod ->
+ Mod;
+ Module ->
+ snmpm_network_interface_filter:verify(Module),
+ Module
+ end;
+create_filter(BadOpts) ->
+ throw({error, {bad_filter_opts, BadOpts}}).
+
+
+%% ----------------------------------------------------------------------
+%% Audit Trail Logger
+%% ----------------------------------------------------------------------
+
+%% Open log
+do_init_log(false) ->
+ ?vtrace("do_init_log(false) -> entry", []),
+ undefined;
+do_init_log(true) ->
+ ?vtrace("do_init_log(true) -> entry", []),
+ {ok, Type} = snmpm_config:system_info(audit_trail_log_type),
+ {ok, Dir} = snmpm_config:system_info(audit_trail_log_dir),
+ {ok, Size} = snmpm_config:system_info(audit_trail_log_size),
+ {ok, Repair} = snmpm_config:system_info(audit_trail_log_repair),
+ Name = ?audit_trail_log_name,
+ File = filename:absname(?audit_trail_log_file, Dir),
+ case snmpm_config:system_info(audit_trail_log_seqno) of
+ {ok, true} ->
+ Initial = ?ATL_SEQNO_INITIAL,
+ Max = ?ATL_SEQNO_MAX,
+ Module = snmpm_config,
+ Function = increment_counter,
+ Args = [atl_seqno, Initial, Max],
+ SeqNoGen = {Module, Function, Args},
+ case snmp_log:create(Name, File, SeqNoGen, Size, Repair, true) of
+ {ok, Log} ->
+ ?vdebug("log created: ~w", [Log]),
+ {Name, Log, Type};
+ {error, Reason} ->
+ throw({error, {failed_create_audit_log, Reason}})
+ end;
+ _ ->
+ case snmp_log:create(Name, File, Size, Repair, true) of
+ {ok, Log} ->
+ ?vdebug("log created: ~w", [Log]),
+ {Name, Log, Type};
+ {error, Reason} ->
+ throw({error, {failed_create_audit_log, Reason}})
+ end
+ end.
+
+
+%% ----------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Func: handle_call/3
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_call({verbosity, Verbosity}, _From, State) ->
+ ?vlog("received verbosity request", []),
+ put(verbosity, Verbosity),
+ {reply, ok, State};
+
+%% handle_call({system_info_updated, What}, _From, State) ->
+%% ?vlog("received system_info_updated request with What = ~p", [What]),
+%% {NewState, Reply} = handle_system_info_updated(State, What),
+%% {reply, Reply, NewState};
+
+handle_call(get_log_type, _From, State) ->
+ ?vlog("received get-log-type request", []),
+ Reply = (catch handle_get_log_type(State)),
+ {reply, Reply, State};
+
+handle_call({set_log_type, NewType}, _From, State) ->
+ ?vlog("received set-log-type request with NewType = ~p", [NewType]),
+ {NewState, Reply} = (catch handle_set_log_type(State, NewType)),
+ {reply, Reply, NewState};
+
+handle_call({note_store, Pid}, _From, State) ->
+ ?vlog("received new note_store: ~w", [Pid]),
+ {reply, ok, State#state{note_store = Pid}};
+
+handle_call(stop, _From, State) ->
+ ?vlog("received stop request", []),
+ Reply = ok,
+ {stop, normal, Reply, State};
+
+handle_call(info, _From, State) ->
+ ?vlog("received info request", []),
+ Reply = get_info(State),
+ {reply, Reply, State};
+
+handle_call(Req, From, State) ->
+ warning_msg("received unknown request (from ~p): ~n~p", [Req, From]),
+ {reply, {error, {invalid_request, Req}}, State}.
+
+
+%%--------------------------------------------------------------------
+%% Func: handle_cast/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+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, Domain, Addr, Port]),
+ maybe_process_extra_info(ExtraInfo),
+ handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State),
+ {noreply, State};
+
+handle_cast({inform_response, Ref, Addr, Port}, State) ->
+ ?vlog("received inform_response message with"
+ "~n Ref: ~p"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Ref, Addr, Port]),
+ handle_inform_response(Ref, Addr, Port, State),
+ {noreply, State};
+
+handle_cast(filter_reset, State) ->
+ ?vlog("received filter_reset message", []),
+ reset_counters(),
+ {noreply, State};
+
+handle_cast(Msg, State) ->
+ warning_msg("received unknown message: ~n~p", [Msg]),
+ {noreply, State}.
+
+
+%%--------------------------------------------------------------------
+%% Func: handle_info/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_info({udp, Sock, Ip, Port, Bytes}, #state{sock = Sock} = State) ->
+ ?vlog("received ~w bytes from ~p:~p", [size(Bytes), Ip, Port]),
+ handle_udp(Ip, Port, Bytes, State),
+ {noreply, State};
+
+handle_info(inform_response_gc, State) ->
+ ?vlog("received inform_response_gc message", []),
+ State2 = handle_inform_response_gc(State),
+ {noreply, State2};
+
+handle_info({disk_log, _Node, Log, Info}, State) ->
+ ?vlog("received disk_log message: "
+ "~n Info: ~p", [Info]),
+ State2 = handle_disk_log(Log, Info, State),
+ {noreply, State2};
+
+handle_info({'DOWN', _MRef, process, Pid, {net_if_worker, ExitStatus}},
+ State) ->
+ ?vdebug("received DOWN message from net_if-worker: "
+ "~n ExitStatus: ~p", [ExitStatus]),
+ handle_worker_exit(Pid, ExitStatus),
+ {noreply, State};
+
+handle_info(Info, State) ->
+ warning_msg("received unknown info: ~n~p", [Info]),
+ {noreply, State}.
+
+
+%%--------------------------------------------------------------------
+%% Func: terminate/2
+%% Purpose: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%--------------------------------------------------------------------
+terminate(Reason, #state{log = Log, irgc = IrGcRef}) ->
+ ?vdebug("terminate: ~p", [Reason]),
+ irgc_stop(IrGcRef),
+ %% Close logs
+ do_close_log(Log),
+ ok.
+
+
+do_close_log({Log, _Type}) ->
+ (catch snmp_log:sync(Log)),
+ (catch snmp_log:close(Log)),
+ ok;
+do_close_log(_) ->
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Convert process state when code is changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+
+code_change(_Vsn, State, _Extra) ->
+ ?d("code_change -> entry with"
+ "~n Vsn: ~p"
+ "~n State: ~p"
+ "~n Extra: ~p", [_Vsn, State, _Extra]),
+ {ok, State}.
+
+
+%%%-------------------------------------------------------------------
+%%% Internal functions
+%%%-------------------------------------------------------------------
+
+handle_udp(Addr, Port, Bytes, State) ->
+ Verbosity = get(verbosity),
+ spawn_opt(fun() ->
+ Log = worker_init(State, Verbosity),
+ Res = (catch maybe_handle_recv_msg(
+ Addr, Port, Bytes,
+ State#state{log = Log})),
+ worker_exit(udp, {Addr, Port}, Res)
+ end,
+ [monitor]).
+
+
+maybe_handle_recv_msg(Addr, Port, Bytes, #state{filter = FilterMod} = State) ->
+ case (catch FilterMod:accept_recv(Addr, Port)) of
+ false ->
+ %% Drop the received packet
+ inc(netIfMsgInDrops),
+ ok;
+ _ ->
+ handle_recv_msg(Addr, Port, Bytes, State)
+ end.
+
+
+handle_recv_msg(Addr, Port, Bytes, #state{server = Pid})
+ when is_binary(Bytes) andalso (size(Bytes) =:= 0) ->
+ Pid ! {snmp_error, {empty_message, Addr, Port}, Addr, Port},
+ ok;
+
+handle_recv_msg(Addr, Port, Bytes,
+ #state{server = Pid,
+ note_store = NoteStore,
+ 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, Domain, Addr, Port,
+ MpdState, NoteStore, Logger)) of
+
+ {ok, Vsn, Pdu, MS, ACM} ->
+ maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, MS, ACM,
+ Logger, State);
+
+ {discarded, Reason, Report} ->
+ ?vdebug("discarded: ~p", [Reason]),
+ ErrorInfo = {failed_processing_message, Reason},
+ Pid ! {snmp_error, ErrorInfo, Addr, Port},
+ maybe_udp_send(State#state.filter, Sock, Addr, Port, Report),
+ ok;
+
+ {discarded, Reason} ->
+ ?vdebug("discarded: ~p", [Reason]),
+ ErrorInfo = {failed_processing_message, Reason},
+ Pid ! {snmp_error, ErrorInfo, Addr, Port},
+ ok;
+
+ Error ->
+ error_msg("processing of received message failed: "
+ "~n ~p", [Error]),
+ ok
+ end.
+
+
+maybe_handle_recv_pdu(Addr, Port,
+ Vsn, #pdu{type = Type} = Pdu, PduMS, ACM,
+ Logger,
+ #state{filter = FilterMod} = State) ->
+ case (catch FilterMod:accept_recv_pdu(Addr, Port, Type)) of
+ false ->
+ inc(netIfPduInDrops),
+ ok;
+ _ ->
+ handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State)
+ end;
+maybe_handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger,
+ #state{filter = FilterMod} = State)
+ when is_record(Trap, trappdu) ->
+ case (catch FilterMod:accept_recv_pdu(Addr, Port, trappdu)) of
+ false ->
+ inc(netIfPduInDrops),
+ ok;
+ _ ->
+ handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, State)
+ end;
+maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) ->
+ handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State).
+
+
+handle_recv_pdu(Addr, Port,
+ Vsn, #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM,
+ Logger, #state{server = Pid, irb = IRB} = State) ->
+ handle_inform_request(IRB, Pid, Vsn, Pdu, ACM,
+ Addr, Port, Logger, State);
+handle_recv_pdu(Addr, Port,
+ _Vsn, #pdu{type = report} = Pdu, _PduMS, ok,
+ _Logger,
+ #state{server = Pid} = _State) ->
+ ?vtrace("received report - ok", []),
+ Pid ! {snmp_report, {ok, Pdu}, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, #pdu{type = report} = Pdu, _PduMS,
+ {error, ReqId, Reason},
+ _Logger,
+ #state{server = Pid} = _State) ->
+ ?vtrace("received report - error", []),
+ Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM,
+ _Logger,
+ #state{server = Pid} = _State) ->
+ ?vtrace("received snmpv2-trap", []),
+ Pid ! {snmp_trap, Pdu, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, Trap, _PduMS, _ACM,
+ _Logger,
+ #state{server = Pid} = _State) when is_record(Trap, trappdu) ->
+ ?vtrace("received trappdu", []),
+ Pid ! {snmp_trap, Trap, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, Pdu, _PduMS, _ACM,
+ _Logger,
+ #state{server = Pid} = _State) when is_record(Pdu, pdu) ->
+ ?vtrace("received pdu", []),
+ Pid ! {snmp_pdu, Pdu, Addr, Port},
+ ok;
+handle_recv_pdu(_Addr, _Port, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) ->
+ ?vlog("received unexpected pdu: "
+ "~n Pdu: ~p"
+ "~n ACM: ~p", [Pdu, ACM]),
+ ok.
+
+
+handle_inform_request(auto, Pid, Vsn, Pdu, ACM, Addr, Port, Logger, State) ->
+ ?vtrace("received inform-request (true)", []),
+ Pid ! {snmp_inform, ignore, Pdu, Addr, Port},
+ RePdu = make_response_pdu(Pdu),
+ maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, State);
+handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu,
+ ACM, Addr, Port, _Logger, _State) ->
+ ?vtrace("received inform-request (false)", []),
+
+ Pid ! {snmp_inform, ReqId, Pdu, Addr, Port},
+
+ %% Before we go any further, we need to check that we have not
+ %% already received this message (possible resend).
+
+ Key = {ReqId, Addr, Port},
+ case ets:lookup(snmpm_inform_request_table, Key) of
+ [_] ->
+ %% OK, we already know about this. We assume this
+ %% is a resend. Either the agent is really eager or
+ %% the user has not answered yet. Bad user!
+ ok;
+ [] ->
+ RePdu = make_response_pdu(Pdu),
+ Expire = t() + To,
+ Rec = {Key, Expire, {Vsn, ACM, RePdu}},
+ ets:insert(snmpm_inform_request_table, Rec)
+ end,
+ ok.
+
+handle_inform_response(Ref, Addr, Port, State) ->
+ Verbosity = get(verbosity),
+ spawn_opt(fun() ->
+ Log = worker_init(State, Verbosity),
+ Res = (catch do_handle_inform_response(
+ Ref,
+ Addr, Port,
+ State#state{log = Log})),
+ worker_exit(inform_reponse, {Addr, Port}, Res)
+ end,
+ [monitor]).
+
+
+
+do_handle_inform_response(Ref, Addr, Port, State) ->
+ Key = {Ref, Addr, Port},
+ case ets:lookup(snmpm_inform_request_table, Key) of
+ [{Key, _, {Vsn, ACM, RePdu}}] ->
+ Logger = logger(State#state.log, read, Addr, Port),
+ ets:delete(snmpm_inform_request_table, Key),
+ maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port,
+ Logger, State);
+ [] ->
+ %% Already acknowledged, or the user was to slow to reply...
+ ok
+ end,
+ ok.
+
+maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger,
+ #state{server = Pid,
+ sock = Sock,
+ filter = FilterMod}) ->
+ case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(RePdu))) of
+ false ->
+ inc(netIfPduOutDrops),
+ ok;
+ _ ->
+ case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of
+ {ok, Msg} ->
+ maybe_udp_send(FilterMod, Sock, Addr, Port, Msg);
+ {discarded, Reason} ->
+ ?vlog("failed generating response message:"
+ "~n Reason: ~p", [Reason]),
+ ReqId = RePdu#pdu.request_id,
+ ErrorInfo = {failed_generating_response, {RePdu, Reason}},
+ Pid ! {snmp_error, ReqId, ErrorInfo, Addr, Port},
+ ok
+ end
+ end.
+
+handle_inform_response_gc(#state{irb = IRB} = State) ->
+ ets:safe_fixtable(snmpm_inform_request_table, true),
+ do_irgc(ets:first(snmpm_inform_request_table), t()),
+ ets:safe_fixtable(snmpm_inform_request_table, false),
+ State#state{irgc = irgc_start(IRB)}.
+
+%% We are deleting at the same time as we are traversing the table!!!
+do_irgc('$end_of_table', _) ->
+ ok;
+do_irgc(Key, Now) ->
+ Next = ets:next(snmpm_inform_request_table, Key),
+ case ets:lookup(snmpm_inform_request_table, Key) of
+ [{Key, BestBefore, _}] when BestBefore < Now ->
+ ets:delete(snmpm_inform_request_table, Key);
+ _ ->
+ ok
+ end,
+ do_irgc(Next, Now).
+
+irgc_start(auto) ->
+ undefined;
+irgc_start(_) ->
+ erlang:send_after(?IRGC_TIMEOUT, self(), inform_response_gc).
+
+irgc_stop(undefined) ->
+ ok;
+irgc_stop(Ref) ->
+ (catch erlang:cancel_timer(Ref)).
+
+
+handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) ->
+ Verbosity = get(verbosity),
+ spawn_opt(fun() ->
+ Log = worker_init(State, Verbosity),
+ Res = (catch maybe_handle_send_pdu(
+ Pdu, Vsn, MsgData,
+ Domain, Addr, Port,
+ State#state{log = Log})),
+ worker_exit(send_pdu, {Domain, Addr, Port}, Res)
+ end,
+ [monitor]).
+
+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;
+ _ ->
+ do_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State)
+ end.
+
+do_handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port,
+ #state{server = Pid,
+ note_store = NoteStore,
+ sock = Sock,
+ log = Log,
+ filter = FilterMod}) ->
+ Logger = logger(Log, write, Addr, Port),
+ case (catch snmpm_mpd:generate_msg(Vsn, NoteStore,
+ Pdu, MsgData, Logger)) of
+ {ok, Msg} ->
+ ?vtrace("do_handle_send_pdu -> message generated", []),
+ maybe_udp_send(FilterMod, Sock, Addr, Port, Msg);
+ {discarded, Reason} ->
+ ?vlog("PDU not sent: "
+ "~n PDU: ~p"
+ "~n Reason: ~p", [Pdu, Reason]),
+ Pid ! {snmp_error, Pdu, Reason},
+ ok
+ end.
+
+
+maybe_udp_send(FilterMod, Sock, Addr, Port, Msg) ->
+ case (catch FilterMod:accept_send(Addr, Port)) of
+ false ->
+ inc(netIfMsgOutDrops),
+ ok;
+ _ ->
+ udp_send(Sock, Addr, Port, Msg)
+ end.
+
+
+udp_send(Sock, Addr, Port, Msg) ->
+ case (catch gen_udp:send(Sock, Addr, Port, Msg)) of
+ ok ->
+ ?vdebug("sent ~w bytes to ~w:~w [~w]",
+ [sz(Msg), Addr, Port, Sock]),
+ ok;
+ {error, Reason} ->
+ error_msg("failed sending message to ~p:~p: "
+ "~n ~p",[Addr, Port, Reason]),
+ ok;
+ Error ->
+ error_msg("failed sending message to ~p:~p: "
+ "~n ~p",[Addr, Port, Error]),
+ ok
+ end.
+
+sz(B) when is_binary(B) ->
+ size(B);
+sz(L) when is_list(L) ->
+ length(L);
+sz(_) ->
+ undefined.
+
+
+handle_disk_log(_Log, {wrap, NoLostItems}, State) ->
+ ?vlog("Audit Trail Log - wrapped: ~w previously logged items where lost",
+ [NoLostItems]),
+ State;
+handle_disk_log(_Log, {truncated, NoLostItems}, State) ->
+ ?vlog("Audit Trail Log - truncated: ~w items where lost when truncating",
+ [NoLostItems]),
+ State;
+handle_disk_log(_Log, full, State) ->
+ error_msg("Failed to write to Audit Trail Log (full)", []),
+ State;
+handle_disk_log(_Log, {error_status, ok}, State) ->
+ State;
+handle_disk_log(_Log, {error_status, {error, Reason}}, State) ->
+ error_msg("Error status received from Audit Trail Log: "
+ "~n~p", [Reason]),
+ State;
+handle_disk_log(_Log, _Info, State) ->
+ State.
+
+
+%% mk_discovery_msg('version-3', Pdu, _VsnHdr, UserName) ->
+%% ScopedPDU = #scopedPdu{contextEngineID = "",
+%% contextName = "",
+%% data = Pdu},
+%% Bytes = snmp_pdus:enc_scoped_pdu(ScopedPDU),
+%% MsgID = get(msg_id),
+%% put(msg_id,MsgID+1),
+%% UsmSecParams =
+%% #usmSecurityParameters{msgAuthoritativeEngineID = "",
+%% msgAuthoritativeEngineBoots = 0,
+%% msgAuthoritativeEngineTime = 0,
+%% msgUserName = UserName,
+%% msgPrivacyParameters = "",
+%% msgAuthenticationParameters = ""},
+%% SecBytes = snmp_pdus:enc_usm_security_parameters(UsmSecParams),
+%% PduType = Pdu#pdu.type,
+%% Hdr = #v3_hdr{msgID = MsgID,
+%% msgMaxSize = 1000,
+%% msgFlags = snmp_misc:mk_msg_flags(PduType, 0),
+%% msgSecurityModel = ?SEC_USM,
+%% msgSecurityParameters = SecBytes},
+%% Msg = #message{version = 'version-3', vsn_hdr = Hdr, data = Bytes},
+%% case (catch snmp_pdus:enc_message_only(Msg)) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% L when list(L) ->
+%% {Msg, L}
+%% end;
+%% mk_discovery_msg(Version, Pdu, {Com, _, _, _, _}, UserName) ->
+%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu},
+%% case catch snmp_pdus:enc_message(Msg) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% L when list(L) ->
+%% {Msg, L}
+%% end.
+
+
+%% mk_msg('version-3', Pdu, {Context, User, EngineID, CtxEngineId, SecLevel},
+%% MsgData) ->
+%% %% Code copied from snmp_mpd.erl
+%% {MsgId, SecName, SecData} =
+%% if
+%% tuple(MsgData), Pdu#pdu.type == 'get-response' ->
+%% MsgData;
+%% true ->
+%% Md = get(msg_id),
+%% put(msg_id, Md + 1),
+%% {Md, User, []}
+%% end,
+%% ScopedPDU = #scopedPdu{contextEngineID = CtxEngineId,
+%% contextName = Context,
+%% data = Pdu},
+%% ScopedPDUBytes = snmp_pdus:enc_scoped_pdu(ScopedPDU),
+
+%% PduType = Pdu#pdu.type,
+%% V3Hdr = #v3_hdr{msgID = MsgId,
+%% msgMaxSize = 1000,
+%% msgFlags = snmp_misc:mk_msg_flags(PduType, SecLevel),
+%% msgSecurityModel = ?SEC_USM},
+%% Message = #message{version = 'version-3', vsn_hdr = V3Hdr,
+%% data = ScopedPDUBytes},
+%% SecEngineID = case PduType of
+%% 'get-response' -> snmp_framework_mib:get_engine_id();
+%% _ -> EngineID
+%% end,
+%% case catch snmp_usm:generate_outgoing_msg(Message, SecEngineID,
+%% SecName, SecData, SecLevel) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% {error, Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% Packet ->
+%% Packet
+%% end;
+%% mk_msg(Version, Pdu, {Com, _User, _EngineID, _Ctx, _SecLevel}, _SecData) ->
+%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu},
+%% case catch snmp_pdus:enc_message(Msg) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% B when list(B) ->
+%% B
+%% end.
+
+
+%% handle_system_info_updated(#state{log = {Log, _OldType}} = State,
+%% audit_trail_log_type = _What) ->
+%% %% Just to make sure, check that ATL is actually enabled
+%% case snmpm_config:system_info(audit_trail_log) of
+%% {ok, true} ->
+%% {ok, Type} = snmpm_config:system_info(audit_trail_log_type),
+%% NewState = State#state{log = {Log, Type}},
+%% {NewState, ok};
+%% _ ->
+%% {State, {error, {adt_not_enabled}}}
+%% end;
+%% handle_system_info_updated(_State, _What) ->
+%% ok.
+
+handle_get_log_type(#state{log = {_Log, Value}} = State) ->
+ %% Just to make sure, check that ATL is actually enabled
+ case snmpm_config:system_info(audit_trail_log) of
+ {ok, true} ->
+ Type =
+ case {lists:member(read, Value), lists:member(write, Value)} of
+ {true, true} ->
+ read_write;
+ {true, false} ->
+ read;
+ {false, true} ->
+ write;
+ {false, false} ->
+ throw({State, {error, {bad_atl_type, Value}}})
+ end,
+ {ok, Type};
+ _ ->
+ {error, not_enabled}
+ end;
+handle_get_log_type(_State) ->
+ {error, not_enabled}.
+
+handle_set_log_type(#state{log = {Log, OldValue}} = State, NewType) ->
+ %% Just to make sure, check that ATL is actually enabled
+ case snmpm_config:system_info(audit_trail_log) of
+ {ok, true} ->
+ NewValue =
+ case NewType of
+ read ->
+ [read];
+ write ->
+ [write];
+ read_write ->
+ [read,write];
+ _ ->
+ throw({State, {error, {bad_atl_type, NewType}}})
+ end,
+ NewState = State#state{log = {Log, NewValue}},
+ OldType =
+ case {lists:member(read, OldValue),
+ lists:member(write, OldValue)} of
+ {true, true} ->
+ read_write;
+ {true, false} ->
+ read;
+ {false, true} ->
+ write;
+ {false, false} ->
+ throw({State, {error, {bad_atl_type, OldValue}}})
+ end,
+ {NewState, {ok, OldType}};
+ _ ->
+ {State, {error, not_enabled}}
+ end;
+handle_set_log_type(State, _NewType) ->
+ {State, {error, not_enabled}}.
+
+
+%% -------------------------------------------------------------------
+
+worker_init(#state{log = undefined = Log}, Verbosity) ->
+ worker_init2(Log, Verbosity);
+worker_init(#state{log = {Name, Log, Type}}, Verbosity) ->
+ case snmp_log:open(Name, Log) of
+ {ok, NewLog} ->
+ worker_init2({Name, NewLog, Type}, Verbosity);
+ {error, Reason} ->
+ warning_msg("NetIf worker ~p failed opening ATL: "
+ "~n ~p", [self(), Reason]),
+ NewLog = undefined,
+ worker_init2({Name, NewLog, Type}, Verbosity)
+ end;
+worker_init(State, Verbosity) ->
+ ?vinfo("worker_init -> entry with invalid data: "
+ "~n State: ~p"
+ "~n Verbosity: ~p", [State, Verbosity]),
+ exit({worker_init, State, Verbosity}).
+
+worker_init2(Log, Verbosity) ->
+ put(sname, mnifw),
+ put(verbosity, Verbosity),
+ Log.
+
+
+worker_exit(Tag, Info, Result) ->
+ exit({net_if_worker, {Tag, Info, Result}}).
+
+handle_worker_exit(_, {_, _, ok}) ->
+ ok;
+handle_worker_exit(Pid, {udp, {Addr, Port}, ExitStatus}) ->
+ warning_msg("Worker process (~p) terminated "
+ "while processing (incomming) message from ~w:~w: "
+ "~n~p", [Pid, Addr, Port, ExitStatus]),
+ ok;
+handle_worker_exit(Pid, {send_pdu, {Domain, Addr, Port}, ExitStatus}) ->
+ warning_msg("Worker process (~p) terminated "
+ "while processing (outgoing) pdu for [~w] ~w:~w: "
+ "~n~p", [Pid, Domain, Addr, Port, ExitStatus]),
+ ok;
+handle_worker_exit(Pid, {inform_response, {Addr, Port}, ExitStatus}) ->
+ warning_msg("Worker process (~p) terminated "
+ "while processing (outgoing) inform response for ~w:~w: "
+ "~n~p", [Pid, Addr, Port, ExitStatus]),
+ ok;
+handle_worker_exit(_, _) ->
+ ok.
+
+
+%% -------------------------------------------------------------------
+
+make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) ->
+ #pdu{type = 'get-response',
+ request_id = ReqId,
+ error_status = noError,
+ error_index = 0,
+ varbinds = Vbs}.
+
+
+%% ----------------------------------------------------------------
+
+pdu_type_of(#pdu{type = Type}) ->
+ Type;
+pdu_type_of(TrapPdu) when is_record(TrapPdu, trappdu) ->
+ trap.
+
+
+%% -------------------------------------------------------------------
+
+%% 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).
+
+
+%% -------------------------------------------------------------------
+
+logger(undefined, _Type, _Addr, _Port) ->
+ fun(_) ->
+ ok
+ end;
+logger({_Name, Log, Types}, Type, Addr, Port) ->
+ case lists:member(Type, Types) of
+ true ->
+ fun(Msg) ->
+ snmp_log:log(Log, Msg, Addr, Port)
+ end;
+ false ->
+ fun(_) ->
+ ok
+ end
+ end.
+
+
+%% -------------------------------------------------------------------
+
+%% info_msg(F, A) ->
+%% ?snmpm_info("NET-IF server: " ++ F, A).
+
+warning_msg(F, A) ->
+ ?snmpm_warning("NET-IF server: " ++ F, A).
+
+error_msg(F, A) ->
+ ?snmpm_error("NET-IF server: " ++ F, A).
+
+
+
+%%%-------------------------------------------------------------------
+
+% get_opt(Key, Opts) ->
+% ?vtrace("get option ~w", [Key]),
+% snmp_misc:get_option(Key, Opts).
+
+get_opt(Opts, Key, Def) ->
+ ?vtrace("get option ~w with default ~p", [Key, Def]),
+ snmp_misc:get_option(Key, Opts, Def).
+
+
+%% -------------------------------------------------------------------
+
+get_info(#state{sock = Id}) ->
+ ProcSize = proc_mem(self()),
+ PortInfo = get_port_info(Id),
+ [{process_memory, ProcSize}, {port_info, PortInfo}].
+
+proc_mem(P) when is_pid(P) ->
+ case (catch erlang:process_info(P, memory)) of
+ {memory, Sz} when is_integer(Sz) ->
+ Sz;
+ _ ->
+ undefined
+ end.
+%% proc_mem(_) ->
+%% undefined.
+
+
+get_port_info(Id) ->
+ PortInfo =
+ case (catch erlang:port_info(Id)) of
+ PI when is_list(PI) ->
+ [{port_info, PI}];
+ _ ->
+ []
+ end,
+ PortStatus =
+ case (catch prim_inet:getstatus(Id)) of
+ {ok, PS} ->
+ [{port_status, PS}];
+ _ ->
+ []
+ end,
+ PortAct =
+ case (catch inet:getopts(Id, [active])) of
+ {ok, PA} ->
+ [{port_act, PA}];
+ _ ->
+ []
+ end,
+ PortStats =
+ case (catch inet:getstat(Id)) of
+ {ok, Stat} ->
+ [{port_stats, Stat}];
+ _ ->
+ []
+ end,
+ IfList =
+ case (catch inet:getif(Id)) of
+ {ok, IFs} ->
+ [{interfaces, IFs}];
+ _ ->
+ []
+ end,
+ BufSz =
+ case (catch inet:getopts(Id, [recbuf, sndbuf, buffer])) of
+ {ok, Sz} ->
+ [{buffer_size, Sz}];
+ _ ->
+ []
+ end,
+ [{socket, Id}] ++
+ IfList ++
+ PortStats ++
+ PortInfo ++
+ PortStatus ++
+ PortAct ++
+ BufSz.
+
+
+%%-----------------------------------------------------------------
+%% Counter functions
+%%-----------------------------------------------------------------
+init_counters() ->
+ F = fun(Counter) -> maybe_create_counter(Counter) end,
+ lists:map(F, counters()).
+
+reset_counters() ->
+ F = fun(Counter) -> snmpm_config:reset_stats_counter(Counter) end,
+ lists:map(F, counters()).
+
+maybe_create_counter(Counter) ->
+ snmpm_config:maybe_cre_stats_counter(Counter, 0).
+
+counters() ->
+ [
+ netIfMsgOutDrops,
+ netIfMsgInDrops,
+ netIfPduOutDrops,
+ netIfPduInDrops
+ ].
+
+inc(Name) -> inc(Name, 1).
+inc(Name, N) -> snmpm_config:incr_stats_counter(Name, N).
+
+%% get_counters() ->
+%% Counters = counters(),
+%% get_counters(Counters, []).
+
+%% get_counters([], Acc) ->
+%% lists:reverse(Acc);
+%% get_counters([Counter|Counters], Acc) ->
+%% case snmpm_config:get_stats_counter(Counter) of
+%% {ok, CounterVal} ->
+%% get_counters(Counters, [{Counter, CounterVal}|Acc]);
+%% _ ->
+%% get_counters(Counters, Acc)
+%% end.
+
+
+%% ----------------------------------------------------------------
+
+call(Pid, Req) ->
+ call(Pid, Req, infinity).
+
+call(Pid, Req, Timeout) ->
+ gen_server:call(Pid, Req, Timeout).
+
+cast(Pid, Msg) ->
+ gen_server:cast(Pid, Msg).
+
diff --git a/lib/snmp/src/misc/Makefile b/lib/snmp/src/misc/Makefile
index 48d76bdbed..c6a5064d89 100644
--- a/lib/snmp/src/misc/Makefile
+++ b/lib/snmp/src/misc/Makefile
@@ -109,13 +109,13 @@ info:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/src/misc
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/misc
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
-# $(INSTALL_DIR) $(RELSYSDIR)/include
-# $(INSTALL_DATA) $(EXT_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/misc"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src/misc"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+# $(INSTALL_DIR) "$(RELSYSDIR)/include"
+# $(INSTALL_DATA) $(EXT_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl
index 7249def24e..e1e7fab57b 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -71,6 +71,18 @@
%%-----------------------------------------------------------------
+%% read_files(Dir, Files) -> Configs
+%% Dir - string() - Full path to the config dir.
+%% Files - [{Gen, Filter, Check, FileName}]
+%% Gen - function/2 - In case of failure when reading the config file,
+%% this function is called to either generate a
+%% default file or issue the error.
+%% Filter - function/1 - Filters all the config entries read from the file
+%% Check - function/1 - Check each entry as they are read from the file.
+%% FileName - string() - Name of the config file.
+%% Configs - [config_entry()]
+%% config_entry() - term()
+
read_files(Dir, Files) when is_list(Dir) andalso is_list(Files) ->
read_files(Dir, Files, []).
@@ -90,7 +102,7 @@ read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res)
{error, R} ->
?vlog("failed reading file info for ~s: "
"~n ~p", [FileName, R]),
- Gen(Dir),
+ Gen(Dir, R),
read_files(Dir, Files, [Filter([])|Res])
end.
@@ -99,6 +111,7 @@ read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res)
read(File, Check) when is_function(Check) ->
?vdebug("read -> entry with"
"~n File: ~p", [File]),
+
Fd = open_file(File),
case loop(Fd, [], Check, 1, File) of
diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl
index 6ab20e3e48..0bed097b62 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,6 +90,17 @@
]).
+-export_type([void/0,
+ verify_config_entry_function/0,
+ verify_config_function/0,
+ write_config_function/0]).
+
+
+%%----------------------------------------------------------------------
+
+-type void() :: term(). % Any value - ignored
+
+
%%----------------------------------------------------------------------
%% Handy SNMP configuration
%%----------------------------------------------------------------------
@@ -2356,53 +2367,109 @@ write_sys_config_file_manager_atl_opt(Fid, {seqno, SeqNo}) ->
header() ->
- {Y,Mo,D} = date(),
- {H,Mi,S} = time(),
+ {Y, Mo, D} = date(),
+ {H, Mi, S} = time(),
io_lib:format("%% This file was generated by "
- "snmp_config (version-~s) ~w-~2.2.0w-~2.2.0w "
+ "~w (version-~s) ~w-~2.2.0w-~2.2.0w "
"~2.2.0w:~2.2.0w:~2.2.0w\n",
- [?version,Y,Mo,D,H,Mi,S]).
+ [?MODULE, ?version, Y, Mo, D, H, Mi, S]).
+
+%% *If* these functions are successfull, they successfully return anything
+%% (which is ignored), but they fail with either a throw or an exit or
+%% something similar.
+
+%% Verification of one config entry read from a file
+-type(verify_config_entry_function() ::
+ fun((Entry :: term()) -> ok | {error, Reason :: term()})).
+
+%% Verification of config to be written
+-type(verify_config_function() ::
+ fun(() -> void())).
+
+%% Write config to file (as defined by Fd)
+-type(write_config_function() ::
+ fun((Fd :: file:io_device()) -> void())).
+
+-spec write_config_file(Dir :: string(),
+ FileName :: string(),
+ Verify :: verify_config_function(),
+ Write :: write_config_function()) ->
+ ok | {error, Reason :: term()}.
write_config_file(Dir, FileName, Verify, Write)
when (is_list(Dir) andalso
is_list(FileName) andalso
is_function(Verify) andalso
is_function(Write)) ->
- (catch do_write_config_file(Dir, FileName, Verify, Write)).
+ try
+ begin
+ do_write_config_file(Dir, FileName, Verify, Write)
+ end
+ catch
+ throw:Error ->
+ Error;
+ T:E ->
+ {error, {failed_write, Dir, FileName, T, E}}
+ end.
+
do_write_config_file(Dir, FileName, Verify, Write) ->
Verify(),
case file:open(filename:join(Dir, FileName), [write]) of
{ok, Fd} ->
- (catch Write(Fd)),
- file:close(Fd),
- ok;
+ file_write_and_close(Write, Fd, Dir, FileName);
Error ->
Error
end.
-
append_config_file(Dir, FileName, Verify, Write)
when (is_list(Dir) andalso
is_list(FileName) andalso
is_function(Verify) andalso
is_function(Write)) ->
- (catch do_append_config_file(Dir, FileName, Verify, Write)).
+ try
+ begin
+ do_append_config_file(Dir, FileName, Verify, Write)
+ end
+ catch
+ throw:Error ->
+ Error;
+ T:E ->
+ {error, {failed_append, Dir, FileName, T, E}}
+ end.
do_append_config_file(Dir, FileName, Verify, Write) ->
Verify(),
case file:open(filename:join(Dir, FileName), [read, write]) of
{ok, Fd} ->
file:position(Fd, eof),
- (catch Write(Fd)),
- file:close(Fd),
- ok;
+ file_write_and_close(Write, Fd, Dir, FileName);
Error ->
Error
end.
+file_write_and_close(Write, Fd, Dir, FileName) ->
+ ok = Write(Fd),
+ case file:sync(Fd) of
+ ok ->
+ case file:close(Fd) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ {error, {failed_closing, Dir, FileName, Reason}}
+ end;
+ {error, Reason} ->
+ {error, {failed_syncing, Dir, FileName, Reason}}
+ end.
+
+
+-spec read_config_file(Dir :: string(),
+ FileName :: string(),
+ Verify :: verify_config_entry_function()) ->
+ {ok, Config :: list()} | {error, Reason :: term()}.
+
read_config_file(Dir, FileName, Verify)
when is_list(Dir) andalso is_list(FileName) andalso is_function(Verify) ->
(catch do_read_config_file(Dir, FileName, Verify)).
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index 2c781810ef..a8c5df0b64 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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 @@
-export([
- create/4, create/5, create/6,
+ create/4, create/5, create/6, open/1, open/2,
change_size/2, close/1, sync/1, info/1,
log/4,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
@@ -109,6 +109,24 @@ create(Name, File, SeqNoGen, Size, Repair, Notify) ->
{error, {bad_args, Name, File, SeqNoGen, Size, Repair, Notify}}.
+%% -- open ---
+
+%% Open an already existing ( = open ) log
+
+open(Name) ->
+ open(Name, #snmp_log{seqno = disabled}).
+open(Name, #snmp_log{seqno = SeqNoGen} = _OldLog) ->
+ %% We include mode in the opts just to be on the safe side
+ case disk_log:open([{name, Name}, {mode, read_write}]) of
+ {ok, Log} ->
+ %% SeqNo must be proprly initiated also
+ {ok, #snmp_log{id = Log, seqno = SeqNoGen}};
+ {repaired, Log, _RecBytes, _BadBytes} ->
+ {ok, #snmp_log{id = Log, seqno = SeqNoGen}};
+ ERROR ->
+ ERROR
+ end.
+
%% -- close ---
@@ -394,6 +412,14 @@ log_to_io(Log, FileName, Dir, Mibs, Start) ->
log_to_io(Log, FileName, Dir, Mibs, Start, Stop)
when is_list(Mibs) ->
+ ?vtrace("log_to_io -> entry with"
+ "~n Log: ~p"
+ "~n FileName: ~p"
+ "~n Dir: ~p"
+ "~n Mibs: ~p"
+ "~n Start: ~p"
+ "~n Stop: ~p",
+ [Log, FileName, Dir, Mibs, Start, Stop]),
File = filename:join(Dir, FileName),
Converter = fun(L) ->
do_log_to_io(L, Mibs, Start, Stop)
@@ -401,28 +427,10 @@ log_to_io(Log, FileName, Dir, Mibs, Start, Stop)
log_convert(Log, File, Converter).
-%% -- log_to_plain ---
-
-%% log_to_plain(Log, FileName, Dir) ->
-%% log_to_plain(Log, FileName, Dir, null, null).
-
-%% log_to_plain(Log, FileName, Dir, Start) ->
-%% log_to_plain(Log, FileName, Dir, Start, null).
-
-%% log_to_plain(Log, FileName, Dir, Start, Stop)
-%% when is_list(Mibs) ->
-%% File = filename:join(Dir, FileName),
-%% Converter = fun(L) ->
-%% do_log_to_plain(L, Start, Stop)
-%% end,
-%% log_convert(Log, File, Converter).
-
-
%% --------------------------------------------------------------------
%% Internal functions
%% --------------------------------------------------------------------
-
%% -- log_convert ---
log_convert(#snmp_log{id = Log}, File, Converter) ->
@@ -431,6 +439,26 @@ log_convert(Log, File, Converter) ->
do_log_convert(Log, File, Converter).
do_log_convert(Log, File, Converter) ->
+ %% ?vtrace("do_log_converter -> entry with"
+ %% "~n Log: ~p"
+ %% "~n File: ~p"
+ %% "~n disk_log:info(Log): ~p", [Log, File, disk_log:info(Log)]),
+ {Pid, Ref} =
+ erlang:spawn_monitor(
+ fun() ->
+ Result = do_log_convert2(Log, File, Converter),
+ exit(Result)
+ end),
+ receive
+ {'DOWN', Ref, process, Pid, Result} ->
+ %% ?vtrace("do_log_converter -> received result"
+ %% "~n Result: ~p"
+ %% "~n disk_log:info(Log): ~p",
+ %% [Result, disk_log:info(Log)]),
+ Result
+ end.
+
+do_log_convert2(Log, File, Converter) ->
%% First check if the caller process has already opened the
%% log, because if we close an already open log we will cause
%% a runtime error.
@@ -439,29 +467,18 @@ do_log_convert(Log, File, Converter) ->
Converter(Log);
false ->
%% Not yet member of the ruling party, apply for membership...
- %% If a log is opened as read_write it is not possible to
- %% open it as read_only. So, to get around this we open
- %% it under a different name...
- Log2 = convert_name(Log),
- case log_open(Log2, File) of
+ case log_open(Log, File) of
{ok, _} ->
- Res = Converter(Log2),
- disk_log:close(Log2),
+ Res = Converter(Log),
+ disk_log:close(Log),
Res;
{error, {name_already_open, _}} ->
- Converter(Log2);
+ Converter(Log);
{error, Reason} ->
{error, {Log, Reason}}
end
end.
-convert_name(Name) when is_list(Name) ->
- Name ++ "_tmp";
-convert_name(Name) when is_atom(Name) ->
- list_to_atom(atom_to_list(Name) ++ "_tmp");
-convert_name(Name) ->
- lists:flatten(io_lib:format("~w_tmp", [Name])).
-
%% -- do_log_to_text ---
@@ -705,21 +722,21 @@ tsf_ge(_Local,Universal,{universal_time,DateTime}) ->
tsf_ge(Local,_Universal,DateTime) ->
tsf_ge(Local,DateTime).
-tsf_ge(TimeStamp,DateTime) ->
+tsf_ge(TimeStamp, DateTime) ->
T1 = calendar:datetime_to_gregorian_seconds(TimeStamp),
T2 = calendar:datetime_to_gregorian_seconds(DateTime),
T1 >= T2.
-tsf_le(_Local,_Universal,null) ->
+tsf_le(_Local, _Universal, null) ->
true;
-tsf_le(Local,_Universal,{local_time,DateTime}) ->
- tsf_le(Local,DateTime);
-tsf_le(_Local,Universal,{universal_time,DateTime}) ->
- tsf_le(Universal,DateTime);
-tsf_le(Local,_Universal,DateTime) ->
+tsf_le(Local, _Universal, {local_time, DateTime}) ->
+ tsf_le(Local, DateTime);
+tsf_le(_Local, Universal, {universal_time, DateTime}) ->
+ tsf_le(Universal, DateTime);
+tsf_le(Local, _Universal, DateTime) ->
tsf_le(Local,DateTime).
-tsf_le(TimeStamp,DateTime) ->
+tsf_le(TimeStamp, DateTime) ->
T1 = calendar:datetime_to_gregorian_seconds(TimeStamp),
T2 = calendar:datetime_to_gregorian_seconds(DateTime),
T1 =< T2.
@@ -864,11 +881,8 @@ do_std_log_open(Name, File, Size, Repair, Notify) ->
log_open(Name, File) ->
- Opts = [{name, Name},
- {file, File},
- {type, ?LOG_TYPE},
- {format, ?LOG_FORMAT},
- {mode, read_only}],
+ Opts = [{name, Name},
+ {file, File}],
case disk_log:open(Opts) of
{error, {badarg, size}} ->
{error, no_such_log};
diff --git a/lib/snmp/src/misc/snmp_note_store.erl b/lib/snmp/src/misc/snmp_note_store.erl
index a21a6209f1..608fdcd9ca 100644
--- a/lib/snmp/src/misc/snmp_note_store.erl
+++ b/lib/snmp/src/misc/snmp_note_store.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
@@ -258,10 +258,17 @@ code_change({down, _Vsn}, State, _Extra) ->
{ok, NState};
% upgrade
-code_change(_Vsn, State, _Extra) ->
+code_change(_Vsn, State0, _Extra) ->
process_flag(trap_exit, true),
- NState = restart_timer(State),
- {ok, NState}.
+ State1 =
+ case State0 of
+ #state{timeout = false} ->
+ State0#state{timeout = ?timeout};
+ _ ->
+ State0
+ end,
+ State2 = restart_timer(State1),
+ {ok, State2}.
%%----------------------------------------------------------
@@ -282,7 +289,7 @@ deactivate_timer(#state{timer = Pid, active = true} = State) ->
receive
deactivated -> ok
end,
- State#state{timeout = false};
+ State#state{active = false};
deactivate_timer(State) ->
State.
diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl
index 0788d86b2d..5b8be90a71 100644
--- a/lib/snmp/src/misc/snmp_pdus.erl
+++ b/lib/snmp/src/misc/snmp_pdus.erl
@@ -254,68 +254,95 @@ strip(0, _Tail) ->
%%----------------------------------------------------------------------
%% Returns:{Type, Value}
%%----------------------------------------------------------------------
+
+%% OBJECT IDENTIFIER
dec_value([6 | Bytes]) ->
{Value, Rest} = dec_oid_notag(Bytes),
{{'OBJECT IDENTIFIER', Value}, Rest};
dec_value([5,0 | T]) ->
{{'NULL', 'NULL'}, T};
+
+%% INTEGER
dec_value([2 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
{{'INTEGER', Value}, Rest};
+
+%% OCTET STRING
dec_value([4 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'OCTET STRING', Value}, Rest};
+
+%% IpAddress
dec_value([64 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'IpAddress', Value}, Rest};
+
+%% Counter32
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),
Value2 =
- if
+ 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};
+
+%% Unsigned32
+dec_value([66 | Bytes]) ->
+ {Value, Rest} = dec_integer_notag(Bytes),
+ 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}})
+ exit({error, {bad_unsigned32, Value}})
end,
- {{'Counter32', Value2}, Rest};
-dec_value([66 | Bytes]) ->
- {Value, Rest} = dec_integer_notag(Bytes),
- if
- (Value >= 0) andalso (Value =< 4294967295) ->
- {{'Unsigned32', Value}, Rest};
- true ->
- exit({error, {bad_unsigned32, Value}})
- end;
+ {{'Unsigned32', Value2}, Rest};
+
+%% TimeTicks
dec_value([67 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
- if
- (Value >= 0) andalso (Value =< 4294967295) ->
- {{'TimeTicks', Value}, Rest};
+ Value2 =
+ if
+ (Value >= 0) andalso (Value =< 16#ffffffff) ->
+ Value;
+ (Value < 0) ->
+ 16#ffffffff + Value + 1;
true ->
exit({error, {bad_timeticks, Value}})
- end;
+ end,
+ {{'TimeTicks', Value2}, Rest};
+
+%% Opaque
dec_value([68 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'Opaque', Value}, Rest};
+
+%% Counter64
dec_value([70 | Bytes]) ->
%% Counter64 is an unsigned 64 but is actually encoded as
%% a signed integer 64.
{Value, Rest} = dec_integer_notag(Bytes),
Value2 =
- if
- (Value >= 0) andalso (Value < 16#8000000000000000) ->
- Value;
- (Value < 0) ->
- 18446744073709551615 + Value + 1;
- true ->
- exit({error, {bad_counter64, Value}}) end,
+ if
+ (Value >= 0) andalso (Value < 16#8000000000000000) ->
+ Value;
+ (Value < 0) ->
+ 16#ffffffffffffffff + Value + 1;
+ true ->
+ exit({error, {bad_counter64, Value}}) end,
{{'Counter64', Value2}, Rest};
+
dec_value([128,0|T]) ->
{{'NULL', noSuchObject}, T};
dec_value([129,0|T]) ->
@@ -629,7 +656,7 @@ enc_VarBind_attributes(#varbind{oid = Oid, variabletype = Type,value = Val}) ->
ValueBytes = enc_value(Type, Val),
lists:append(OidBytes, ValueBytes).
-enc_value('INTEGER',Val) ->
+enc_value('INTEGER', Val) ->
enc_integer_tag(Val);
enc_value('OCTET STRING', Val) ->
enc_oct_str_tag(Val);
@@ -637,7 +664,7 @@ enc_value('BITS', Val) ->
enc_oct_str_tag(bits_to_str(Val));
enc_value('OBJECT IDENTIFIER', Val) ->
enc_oid_tag(Val);
-enc_value('IpAddress',Val) ->
+enc_value('IpAddress', Val) ->
Bytes2 = enc_oct_str_notag(Val),
Len2 = elength(length(Bytes2)),
lists:append([64 | Len2],Bytes2);
@@ -668,6 +695,24 @@ enc_value('Counter32', Val) ->
Bytes2 = enc_integer_notag(Val2),
Len2 = elength(length(Bytes2)),
lists:append([65 | Len2],Bytes2);
+enc_value('Unsigned32', Val) ->
+ if
+ (Val >= 0) andalso (Val =< 4294967295) ->
+ Bytes2 = enc_integer_notag(Val),
+ Len2 = elength(length(Bytes2)),
+ lists:append([66 | Len2], Bytes2);
+ true ->
+ exit({error, {bad_counter32, Val}})
+ end;
+enc_value('TimeTicks', Val) ->
+ if
+ (Val >= 0) andalso (Val =< 4294967295) ->
+ Bytes2 = enc_integer_notag(Val),
+ Len2 = elength(length(Bytes2)),
+ lists:append([67 | Len2], Bytes2);
+ true ->
+ exit({error, {bad_timeticks, Val}})
+ end;
enc_value('Counter64', Val) ->
Val2 =
if
@@ -682,18 +727,7 @@ enc_value('Counter64', Val) ->
end,
Bytes2 = enc_integer_notag(Val2),
Len2 = elength(length(Bytes2)),
- lists:append([70 | Len2],Bytes2);
-enc_value(Type, Val) ->
- Bytes2 = enc_integer_notag(Val),
- Len2 = elength(length(Bytes2)),
- lists:append([enc_val_tag(Type,Val) | Len2],Bytes2).
-
-enc_val_tag('Counter32',Val) when (Val >= 0) andalso (Val =< 4294967295) ->
- 65;
-enc_val_tag('Unsigned32', Val) when (Val >= 0) andalso (Val =< 4294967295) ->
- 66;
-enc_val_tag('TimeTicks', Val) when (Val >= 0) andalso (Val =< 4294967295) ->
- 67.
+ lists:append([70 | Len2],Bytes2).
%%----------------------------------------------------------------------
diff --git a/lib/snmp/src/misc/snmp_verbosity.erl b/lib/snmp/src/misc/snmp_verbosity.erl
index 85037ba2ae..df5986b7bc 100644
--- a/lib/snmp/src/misc/snmp_verbosity.erl
+++ b/lib/snmp/src/misc/snmp_verbosity.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The 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,7 +76,7 @@ format_timestamp({_N1, _N2, N3} = 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",
+ io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w ~w",
[YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
lists:flatten(FormatDate).
@@ -144,6 +144,8 @@ image_of_sname(mse) -> "M-SERVER";
image_of_sname(msew) -> io_lib:format("M-SERVER-worker(~p)", [self()]);
image_of_sname(mns) -> "M-NOTE-STORE";
image_of_sname(mnif) -> "M-NET-IF";
+image_of_sname(mnifl) -> "M-NET-IF-LOGGER";
+image_of_sname(mnifw) -> io_lib:format("M-NET-IF-worker(~p)", [self()]);
image_of_sname(mconf) -> "M-CONF";
image_of_sname(mgr) -> "MGR";
diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile
index 78ffb1c255..546d46a002 100644
--- a/lib/snmp/test/Makefile
+++ b/lib/snmp/test/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The 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,7 +79,7 @@ COVER_SPEC_FILE = snmp.cover
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/snmp_test
+RELSYSDIR = $(RELEASE_PATH)/snmp_test
# ----------------------------------------------------
@@ -224,6 +224,9 @@ $(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
+$(SNMP_BIN_TARGET_DIR)/Test3.bin: $(SNMP_BIN_TARGET_DIR)/Test2.bin
+
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -232,10 +235,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(RELTEST_FILES) $(COVER_SPEC_FILE) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- tar cf - snmp_test_data | (cd $(RELSYSDIR); tar xf -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(RELTEST_FILES) $(COVER_SPEC_FILE) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ tar cf - snmp_test_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
@@ -251,7 +254,7 @@ info:
@echo ""
@echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
@echo ""
- @echo "RELSYSDIR = $(RELSYSDIR)"
+ @echo "RELSYSDIR = "$(RELSYSDIR)""
@echo ""
@echo "SOURCE = $(SOURCE)"
@echo ""
diff --git a/lib/snmp/test/exp/.gitignore b/lib/snmp/test/exp/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/snmp/test/exp/.gitignore
diff --git a/lib/snmp/test/exp/snmp_agent_bl_test.erl b/lib/snmp/test/exp/snmp_agent_bl_test.erl
new file mode 100644
index 0000000000..a5a6e8260b
--- /dev/null
+++ b/lib/snmp/test/exp/snmp_agent_bl_test.erl
@@ -0,0 +1,5654 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmp_agent_bl_test).
+
+%% TODO
+%% * Test fault-tolerance (kill master etc)
+%%
+
+% -include_lib("kernel/include/file.hrl").
+% -include("test_server.hrl").
+% -include("snmp_test_lib.hrl").
+% -define(SNMP_USE_V3, true).
+% -include_lib("snmp/include/snmp_types.hrl").
+
+%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
+
+
+% -define(klas1, [1,3,6,1,2,1,7]).
+% -define(klas2, [1,3,6,1,2,1,9]).
+% -define(klas3, [1,3,6,1,2,1,8,1]).
+% -define(klas4, [1,3,6,1,2,1,8,4]).
+% -define(sa, [1,3,6,1,4,1,193,2]).
+% -define(system, [1,3,6,1,2,1,1]).
+% -define(snmp, [1,3,6,1,2,1,11]).
+% -define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
+% -define(ericsson, [1,3,6,1,4,1,193]).
+% -define(testTrap, [1,3,6,1,2,1,15,0]).
+% -define(xDescr, [1,3,6,1,2,1,17,1]).
+% -define(xDescr2, [1,3,6,1,2,1,17,2]).
+
+% -define(active, 1).
+% -define(notInService, 2).
+% -define(notReady, 3).
+% -define(createAndGo, 4).
+% -define(createAndWait, 5).
+% -define(destroy, 6).
+
+% -define(TRAP_UDP, 5000).
+
+% -define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
+
+-define(str(X), snmp_pdus:bits_to_str(X)).
+
+-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
+ [?LINE, self()]),
+ receive cont -> ok end
+ end).
+
+
+-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
+-define(v1_2(V1,V2),
+ case get(vsn) of
+ v1 -> V1;
+ _ -> V2
+ end).
+
+-define(v1_2_3(V1,V2,V3),
+ case get(vsn) of
+ v1 -> V1;
+ v2 -> V2;
+ _ -> V3
+ end).
+
+all(suite) -> {req,
+ [mnesia, distribution,
+ {local_slave_nodes, 2}, {time, 360}],
+ [{conf, init_all, cases(), finish_all}]}.
+
+init_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+cases() ->
+ case ?OSTYPE() of
+ vxworks ->
+ %% No crypto app, so skip v3 testcases
+ [
+ app_info,
+ test_v1, test_v2, test_v1_v2,
+ test_multi_threaded,
+ mib_storage,
+ tickets];
+ _Else ->
+ [
+ app_info,
+ test_v1, test_v2, test_v1_v2, test_v3,
+ test_multi_threaded,
+ mib_storage,
+ tickets
+ ]
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% The test case structure is as follows:
+%%%
+%%% init_all - starts mnesia,
+%%%
+%%% init_v1 - starts agent
+%%% simple
+%%% big - e.g. starts/stops subagent, load/unloads mibs
+%%% init_mul
+%%% mul_get
+%%% mul_set
+%%% <etc>
+%%% finish_mul
+%%% <etc>
+%%% finish_v1
+%%%
+%%% init_v2 - starts agent
+%%% finish_v2
+%%%
+%%% init_bilingual - starts agent
+%%% finish_bilingual
+%%%
+%%% finish_all
+%%%
+%%% There is still one problem with these testsuites. If one test
+%%% fails, it may not be possible to run some other cases, as it
+%%% may have e.g. created some row or loaded some table, that it
+%%% didn't undo (since it failed).
+%%%-----------------------------------------------------------------
+
+init_all(Config0) when list(Config0) ->
+ ?LOG("init_all -> entry with"
+ "~n Config0: ~p",[Config0]),
+
+ %% --
+ %% Fix config:
+ %%
+
+ DataDir0 = ?config(data_dir, Config0),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config0),
+ Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+
+ %% --
+ %% Start nodes
+ %%
+
+ ?line {ok, SaNode} = start_node(snmp_sa),
+ ?line {ok, MgrNode} = start_node(snmp_mgr),
+
+
+ %% --
+ %% Create necessary files
+ %%
+
+ Dir = ?config(priv_dir, Config),
+ ?DBG("init_all -> Dir ~p", [Dir]),
+
+ DataDir = ?config(data_dir, Config),
+ ?DBG("init_all -> DataDir ~p", [DataDir]),
+
+ file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+
+ file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+
+ file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
+ ?DBG("init_all -> SaDir ~p", [SaDir]),
+
+
+ %% --
+ %% Start and initiate mnesia
+ %%
+
+ ?DBG("init_all -> load application mnesia", []),
+ ?line ok = application:load(mnesia),
+
+ ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
+ ?line ok = rpc:call(SaNode, application, load, [mnesia]),
+
+ ?DBG("init_all -> application mnesia: set_env dir",[]),
+ ?line application_controller:set_env(mnesia, dir,
+ filename:join(Dir, "Mnesia1")),
+
+ ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(Dir, "Mnesia2")]),
+
+ ?DBG("init_all -> create mnesia schema",[]),
+ ?line ok = mnesia:create_schema([SaNode, node()]),
+
+ ?DBG("init_all -> start application mnesia",[]),
+ ?line ok = application:start(mnesia),
+
+ ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
+ ?line ok = rpc:call(SaNode, application, start, [mnesia]),
+ Ip = ?LOCALHOST(),
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {agent_dir, AgentDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {mib_dir, DataDir},
+ {ip, Ip} |
+ Config].
+
+finish_all(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ stop_node(SaNode),
+ stop_node(MgrNode),
+ application:stop(mnesia).
+
+start_v1_agent(Config) when list(Config) ->
+ start_agent(Config, [v1]).
+
+start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
+ start_agent(Config, [v1], Opts).
+
+start_v2_agent(Config) when list(Config) ->
+ start_agent(Config, [v2]).
+
+start_v3_agent(Config) when list(Config) ->
+ start_agent(Config, [v3]).
+
+start_bilingual_agent(Config) when list(Config) ->
+ start_agent(Config, [v1,v2]).
+
+start_multi_threaded_agent(Config) when list(Config) ->
+ start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
+
+stop_agent(Config) when list(Config) ->
+ ?LOG("stop_agent -> entry with"
+ "~n Config: ~p",[Config]),
+
+ {Sup, Par} = ?config(snmp_sup, Config),
+ ?DBG("stop_agent -> attempt to stop (sup) ~p"
+ "~n Sup: ~p"
+ "~n Par: ~p",
+ [Sup,
+ (catch process_info(Sup)),
+ (catch process_info(Par))]),
+ stop_sup(Sup, Par),
+
+ {Sup2, Par2} = ?config(snmp_sub, Config),
+ ?DBG("stop_agent -> attempt to stop (sub) ~p"
+ "~n Sup2: ~p"
+ "~n Par2: ~p",
+ [Sup2,
+ (catch process_info(Sup2)),
+ (catch process_info(Par2))]),
+ stop_sup(Sup2, Par2),
+
+ ?DBG("stop_agent -> done - now cleanup config", []),
+ C1 = lists:keydelete(snmp_sup, 1, Config),
+ lists:keydelete(snmp_sub, 1, C1).
+
+
+stop_sup(Pid, _) when node(Pid) == node() ->
+ case (catch process_info(Pid)) of
+ PI when list(PI) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ exit(Pid, kill),
+ await_stopped(Pid, Ref);
+ {'EXIT', _Reason} ->
+ ?LOG("stop_sup -> ~p not running", [Pid]),
+ ok
+ end;
+stop_sup(Pid, _) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ ?LOG("stop_sup -> Ref: ~p", [Ref]),
+ %% Pid ! {'EXIT', Parent, shutdown}, % usch
+ exit(Pid, kill),
+ await_stopped(Pid, Ref).
+
+await_stopped(Pid, Ref) ->
+ receive
+ {'DOWN', Ref, process, Pid, _Reason} ->
+ ?DBG("received down message for ~p", [Pid]),
+ ok
+ after 10000 ->
+ ?INF("await_stopped -> timeout for ~p",[Pid]),
+ erlang:demonitor(Ref),
+ ?FAIL({failed_stop,Pid})
+ end.
+
+
+start_agent(Config, Vsn) ->
+ start_agent(Config, Vsn, []).
+start_agent(Config, Vsn, Opts) ->
+ ?LOG("start_agent -> entry (~p) with"
+ "~n Config: ~p"
+ "~n Vsn: ~p"
+ "~n Opts: ~p",[node(), Config, Vsn, Opts]),
+
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
+ snmp_app_env_init(vsn_init(Vsn) ++
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentDir},
+ {snmp_db_dir, AgentDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, trace},
+ {snmp_symbolic_store_verbosity, trace},
+ {snmp_note_store_verbosity, trace},
+ {snmp_net_if_verbosity, trace}],
+ Opts),
+
+
+ process_flag(trap_exit,true),
+
+ {ok, AppSup} = snmp_app_sup:start_link(),
+ unlink(AppSup),
+ ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
+
+ ?DBG("start_agent -> start master agent (old style)",[]),
+ Sup = case (catch snmpa_app:start(normal)) of
+ {ok, S} ->
+ ?DBG("start_agent -> started, Sup: ~p",[S]),
+ S;
+
+ Else ->
+ ?DBG("start_agent -> unknown result: ~n~p",[Else]),
+ %% Get info about the apps we depend on
+ MnesiaInfo = mnesia_running(),
+ ?FAIL({start_failed,Else,MnesiaInfo})
+ end,
+
+ ?DBG("start_agent -> unlink from supervisor",[]),
+ ?line unlink(Sup),
+ ?line SaDir = ?config(sa_dir, Config),
+ ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
+ ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
+ ?DBG("start_agent -> done",[]),
+ ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
+
+
+vsn_init(Vsn) ->
+ vsn_init([v1,v2,v3], Vsn, []).
+
+vsn_init([], _Vsn, Acc) ->
+ Acc;
+vsn_init([V|Vsns], Vsn, Acc) ->
+ case lists:member(V, Vsn) of
+ true ->
+ vsn_init(Vsns, Vsn, [{V, true}|Acc]);
+ false ->
+ vsn_init(Vsns, Vsn, [{V, false}|Acc])
+ end.
+
+snmp_app_env_init(Env0, Opts) ->
+ ?DBG("snmp_app_env_init -> unload snmp",[]),
+ ?line application:unload(snmp),
+ ?DBG("snmp_app_env_init -> load snmp",[]),
+ ?line application:load(snmp),
+ ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
+ F1 = fun({Key,Val} = New, Acc0) ->
+ ?DBG("snmp_app_env_init -> "
+ "updating setting ~p to ~p", [Key, Val]),
+ case lists:keyreplace(Key, 1, Acc0, New) of
+ Acc0 ->
+ [New|Acc0];
+ Acc ->
+ Acc
+ end
+ end,
+ Env = lists:foldr(F1, Env0, Opts),
+ ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
+ F2 = fun({Key,Val}) ->
+ ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
+ application_controller:set_env(snmp, Key, Val)
+ end,
+ lists:foreach(F2, Env).
+
+
+
+
+%% Test if application is running
+mnesia_running() -> ?IS_MNESIA_RUNNING().
+crypto_running() -> ?IS_CRYPTO_RUNNING().
+
+
+start_sub(Dir) ->
+ ?DBG("start_sub -> entry",[]),
+ Opts = [{db_dir, Dir},
+ {supervisor, [{verbosity, trace}]}],
+ %% BMK BMK
+% {ok, P} = snmp_supervisor:start_sub(Dir),
+ {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
+ unlink(P),
+ {ok, {P, self()}}.
+
+create_tables(SaNode) ->
+ ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
+ {attributes, [a1,a2]}]).
+
+delete_tables() ->
+ mnesia:delete_table(friendsTable2),
+ mnesia:delete_table(kompissTable2),
+ mnesia:delete_table(snmp_variables).
+
+%% Creation is done in runtime!
+delete_mib_storage_mnesia_tables() ->
+ mnesia:delete_table(snmpa_mib_data),
+ mnesia:delete_table(snmpa_mib_tree),
+ mnesia:delete_table(snmpa_symbolic_store).
+
+%%-----------------------------------------------------------------
+%% A test case is always one of:
+%% - v1 specific case
+%% - v2 specific case
+%% - v1 and v2 case
+%% All v1 specific cases are prefixed with v1_, and all v2 with
+%% v2_. E.g. v1_trap/v2_trap.
+%%
+%% All other cases are shared. However, the testserver uses the name
+%% of the case to generate a file for that case. The same case cannot
+%% be used in different configurations in the same suite. Therefore
+%% all these functions exists in two variants, the base function
+%% <base>, and a second version <base>_2. There may be several
+%% versions as well, <base>_N.
+%%-----------------------------------------------------------------
+mib_storage(suite) -> [
+ mib_storage_ets,
+ mib_storage_dets,
+ mib_storage_mnesia,
+ mib_storage_size_check_ets,
+ mib_storage_size_check_dets,
+ mib_storage_size_check_mnesia,
+ mib_storage_varm_dets,
+ mib_storage_varm_mnesia
+ ].
+
+mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets,
+ mib_storage_ets_cases(),
+ finish_mib_storage_ets}}.
+
+mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets,
+ mib_storage_dets_cases(),
+ finish_mib_storage_dets}}.
+
+mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia,
+ mib_storage_mnesia_cases(),
+ finish_mib_storage_mnesia}}.
+
+mib_storage_size_check_ets(suite) ->
+ {req, [], {conf,
+ init_size_check_mse,
+ mse_size_check_cases(),
+ finish_size_check_mse}}.
+
+mib_storage_size_check_dets(suite) ->
+ {req, [], {conf,
+ init_size_check_msd,
+ msd_size_check_cases(),
+ finish_size_check_msd}}.
+
+mib_storage_size_check_mnesia(suite) ->
+ {req, [], {conf,
+ init_size_check_msm,
+ msm_size_check_cases(),
+ finish_size_check_msm}}.
+
+mib_storage_varm_dets(suite) ->
+ {req, [], {conf,
+ init_varm_mib_storage_dets,
+ varm_mib_storage_dets_cases(),
+ finish_varm_mib_storage_dets}}.
+
+mib_storage_varm_mnesia(suite) ->
+ {req, [], {conf,
+ init_varm_mib_storage_mnesia,
+ varm_mib_storage_mnesia_cases(),
+ finish_varm_mib_storage_mnesia}}.
+
+mib_storage_ets_cases() ->
+ [
+ mse_simple,
+ mse_v1_processing,
+ mse_big,
+ mse_big2,
+ mse_loop_mib,
+ mse_api,
+ mse_sa_register,
+ mse_v1_trap,
+ mse_sa_error,
+ mse_next_across_sa,
+ mse_undo,
+ mse_standard_mib,
+ mse_community_mib,
+ mse_framework_mib,
+ mse_target_mib,
+ mse_notification_mib,
+ mse_view_based_acm_mib,
+ mse_sparse_table,
+ mse_me_of,
+ mse_mib_of].
+
+mib_storage_dets_cases() ->
+ [
+ msd_simple,
+ msd_v1_processing,
+ msd_big,
+ msd_big2,
+ msd_loop_mib,
+ msd_api,
+ msd_sa_register,
+ msd_v1_trap,
+ msd_sa_error,
+ msd_next_across_sa,
+ msd_undo,
+ msd_standard_mib,
+ msd_community_mib,
+ msd_framework_mib,
+ msd_target_mib,
+ msd_notification_mib,
+ msd_view_based_acm_mib,
+ msd_sparse_table,
+ msd_me_of,
+ msd_mib_of
+ ].
+
+mib_storage_mnesia_cases() ->
+ [
+ msm_simple,
+ msm_v1_processing,
+ msm_big,
+ msm_big2,
+ msm_loop_mib,
+ msm_api,
+ msm_sa_register,
+ msm_v1_trap,
+ msm_sa_error,
+ msm_next_across_sa,
+ msm_undo,
+ msm_standard_mib,
+ msm_community_mib,
+ msm_framework_mib,
+ msm_target_mib,
+ msm_notification_mib,
+ msm_view_based_acm_mib,
+ msm_sparse_table,
+ msm_me_of,
+ msm_mib_of
+ ].
+
+mse_size_check_cases() ->
+ [mse_size_check].
+
+msd_size_check_cases() ->
+ [msd_size_check].
+
+msm_size_check_cases() ->
+ [msm_size_check].
+
+varm_mib_storage_dets_cases() ->
+ [msd_varm_mib_start].
+
+varm_mib_storage_mnesia_cases() ->
+ [msm_varm_mib_start].
+
+init_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,ets},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ init_ms(Config, [MibStorage]).
+
+init_ms(Config, Opts) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
+ [{vsn, v1} | start_v1_agent(Config,Opts1)].
+
+init_size_check_mse(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, ets},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msd(Config) when list(Config) ->
+ AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDir}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msm(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, {mnesia,[]}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_ms(Config, Opts) when list(Config) ->
+ SaNode = ?GCONF(snmp_sa, Config),
+ %% We are using v3 here, so crypto must be supported or else...
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end,
+ create_tables(SaNode),
+ AgentDir = ?GCONF(agent_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ ?line ok =
+ config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_agent(Config, [v3], Opts)].
+
+init_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_dets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+init_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_mnesia -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+finish_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_ets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_dets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_dets -> entry", []),
+ delete_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_size_check_mse(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msd(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msm(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_ms(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%% These are just interface functions to fool the test server
+mse_simple(X) -> simple(X).
+mse_v1_processing(X) -> v1_processing(X).
+mse_big(X) -> big(X).
+mse_big2(X) -> big2(X).
+mse_loop_mib(X) -> loop_mib(X).
+mse_api(X) -> api(X).
+mse_sa_register(X) -> sa_register(X).
+mse_v1_trap(X) -> v1_trap(X).
+mse_sa_error(X) -> sa_error(X).
+mse_next_across_sa(X) -> next_across_sa(X).
+mse_undo(X) -> undo(X).
+mse_standard_mib(X) -> snmp_standard_mib(X).
+mse_community_mib(X) -> snmp_community_mib(X).
+mse_framework_mib(X) -> snmp_framework_mib(X).
+mse_target_mib(X) -> snmp_target_mib(X).
+mse_notification_mib(X) -> snmp_notification_mib(X).
+mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+mse_sparse_table(X) -> sparse_table(X).
+mse_me_of(X) -> ms_me_of(X).
+mse_mib_of(X) -> ms_mib_of(X).
+
+msd_simple(X) -> simple(X).
+msd_v1_processing(X) -> v1_processing(X).
+msd_big(X) -> big(X).
+msd_big2(X) -> big2(X).
+msd_loop_mib(X) -> loop_mib(X).
+msd_api(X) -> api(X).
+msd_sa_register(X) -> sa_register(X).
+msd_v1_trap(X) -> v1_trap(X).
+msd_sa_error(X) -> sa_error(X).
+msd_next_across_sa(X) -> next_across_sa(X).
+msd_undo(X) -> undo(X).
+msd_standard_mib(X) -> snmp_standard_mib(X).
+msd_community_mib(X) -> snmp_community_mib(X).
+msd_framework_mib(X) -> snmp_framework_mib(X).
+msd_target_mib(X) -> snmp_target_mib(X).
+msd_notification_mib(X) -> snmp_notification_mib(X).
+msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msd_sparse_table(X) -> sparse_table(X).
+msd_me_of(X) -> ms_me_of(X).
+msd_mib_of(X) -> ms_mib_of(X).
+
+msm_simple(X) -> simple(X).
+msm_v1_processing(X) -> v1_processing(X).
+msm_big(X) -> big(X).
+msm_big2(X) -> big2(X).
+msm_loop_mib(X) -> loop_mib(X).
+msm_api(X) -> api(X).
+msm_sa_register(X) -> sa_register(X).
+msm_v1_trap(X) -> v1_trap(X).
+msm_sa_error(X) -> sa_error(X).
+msm_next_across_sa(X) -> next_across_sa(X).
+msm_undo(X) -> undo(X).
+msm_standard_mib(X) -> snmp_standard_mib(X).
+msm_community_mib(X) -> snmp_community_mib(X).
+msm_framework_mib(X) -> snmp_framework_mib(X).
+msm_target_mib(X) -> snmp_target_mib(X).
+msm_notification_mib(X) -> snmp_notification_mib(X).
+msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msm_sparse_table(X) -> sparse_table(X).
+msm_me_of(X) -> ms_me_of(X).
+msm_mib_of(X) -> ms_mib_of(X).
+
+
+mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
+msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
+msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
+
+msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
+msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
+
+ms_size_check(suite) -> [];
+ms_size_check(Config) when list(Config) ->
+ p("ms_size_check..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?LOG("mib server size check...", []),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMPv2-MIB"),
+ ?line load_master_std("SNMPv2-TM"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMPv2-MIB"),
+ ?line unload_master("SNMPv2-TM"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+
+varm_mib_start(suite) -> [];
+varm_mib_start(Config) when list(Config) ->
+ p("varm_mib_start..."),
+ ?LOG("varm_mib_start -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ %% Start the agent
+ Opts = ?GCONF(agent_opts, Config),
+ Config1 = start_v1_agent(Config, Opts),
+
+ %% Sleep some in order for the agent to start properly
+ ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
+ ?SLEEP(5000),
+
+ %% Load all the mibs
+ HardwiredMibs = loaded_mibs(),
+ ?DBG("varm_mib_start -> load all mibs", []),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+
+ %% Unload the hardwired mibs
+ ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
+ ?SLEEP(1000),
+ ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
+ ?line unload_mibs(HardwiredMibs), %% unload hardwired
+
+ ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
+ ?SLEEP(1000),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ Config2 = stop_agent(Config1),
+
+ %% Sleep some in order for the agent to stop properly
+ ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
+ ?SLEEP(5000),
+
+ %% Start the agent (again)
+ ?DBG("varm_mib_start -> start the agent", []),
+ Config3 = start_v1_agent(Config2, Opts),
+
+ ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
+ ?SLEEP(5000),
+
+ %% Perform the test(s)
+ ?DBG("varm_mib_start -> perform the tests", []),
+ try_test(snmp_community_mib),
+ try_test(snmp_framework_mib),
+ try_test(snmp_target_mib),
+ try_test(snmp_notification_mib),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ stop_agent(Config3),
+ ok.
+
+
+-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
+-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
+-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+ms_me_of(suite) -> [];
+ms_me_of(Config) when list(Config) ->
+ p("ms_me_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = me_of(?snmpTrapCommunity_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = me_of(?vacmViewSpinLock_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+me_of(Oid) ->
+ case snmpa:me_of(Oid) of
+ {ok, #me{oid = Oid}} ->
+ ok;
+ {ok, #me{oid = OtherOid}} ->
+ case lists:reverse(Oid) of
+ [0|Rest] ->
+ case lists:reverse(Rest) of
+ OtherOid ->
+ ok;
+ AnotherOid ->
+ {error, {invalid_oid, Oid, AnotherOid}}
+ end;
+ _ ->
+ {error, {invalid_oid, Oid, OtherOid}}
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ {error, Else}
+ end.
+
+
+ms_mib_of(suite) -> [];
+ms_mib_of(Config) when list(Config) ->
+ p("ms_mib_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
+ 'SNMP-USER-BASED-SM-MIB'),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+mib_of(Oid, ExpectedMibName) ->
+ ?DBG("mib_of -> entry with"
+ "~n Oid: ~p"
+ "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
+ %% case snmpa:mib_of(Oid) of
+ MibOf = snmpa:mib_of(Oid),
+ ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
+ case MibOf of
+ {ok, ExpectedMibName} ->
+ ok;
+ {ok, OtherMibName} ->
+ {error, {invalid_mib, ExpectedMibName, OtherMibName}};
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ ?DBG("mib_of -> Else: ~n~p", [Else]),
+ {error, Else}
+ end.
+
+
+app_info(suite) -> [];
+app_info(Config) when list(Config) ->
+ SnmpDir = app_dir(snmp),
+ SslDir = app_dir(ssl),
+ CryptoDir = app_dir(crypto),
+ Attr = snmp:module_info(attributes),
+ AppVsn =
+ case lists:keysearch(app_vsn, 1, Attr) of
+ {value, {app_vsn, V}} ->
+ V;
+ false ->
+ "undefined"
+ end,
+ io:format("Root dir: ~s~n"
+ "SNMP: Application dir: ~s~n"
+ " Application ver: ~s~n"
+ "SSL: Application dir: ~s~n"
+ "CRYPTO: Application dir: ~s~n",
+ [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
+ ok.
+
+app_dir(App) ->
+ case code:lib_dir(App) of
+ D when list(D) ->
+ filename:basename(D);
+ {error, _Reason} ->
+ "undefined"
+ end.
+
+
+test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}.
+
+%v1_cases() -> [loop_mib];
+v1_cases() ->
+ [simple,
+ db_notify_client,
+ v1_processing, big, big2, loop_mib,
+ api, subagent, mnesia, multiple_reqs,
+ sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs,
+ standard_mibs, sparse_table, cnt_64,
+ opaque,
+ % opaque].
+
+ change_target_addr_config].
+
+init_v1(Config) when list(Config) ->
+ ?line SaNode = ?config(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v1} | start_v1_agent(Config)].
+
+finish_v1(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}.
+
+%v2_cases() -> [loop_mib_2];
+v2_cases() ->
+ [simple_2, v2_processing, big_2, big2_2, loop_mib_2,
+ api_2, subagent_2, mnesia_2,
+ multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2,
+ next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2,
+ v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps].
+
+init_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_v2_agent(Config)].
+
+finish_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}.
+
+v1_v2_cases() ->
+ [simple_bi].
+
+init_v1_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, bilingual} | start_bilingual_agent(Config)].
+
+finish_v1_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}.
+
+%v3_cases() -> [loop_mib_3];
+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, reported_bugs_3, standard_mibs_3,
+ v3_security,
+ v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3].
+
+init_v3(Config) when list(Config) ->
+ %% Make sure crypto works, otherwise start_agent will fail
+ %% and we will be stuck with a bunch of mnesia tables for
+ %% the rest of this suite...
+ ?DBG("start_agent -> start crypto app",[]),
+ case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end
+ end,
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v3], MgrDir, AgentDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_v3_agent(Config)].
+
+finish_v3(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}.
+
+mt_cases() ->
+ [multi_threaded, mt_trap].
+
+init_mt(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_multi_threaded_agent(Config)].
+
+finish_mt(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+%% This one *must* be run first in each case.
+init_case(Config) when list(Config) ->
+ ?DBG("init_case -> entry with"
+ "~n Config: ~p", [Config]),
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = node(),
+
+ SaHost = ?HOSTNAME(SaNode),
+ MgrHost = ?HOSTNAME(MgrNode),
+ MasterHost = ?HOSTNAME(MasterNode),
+ {ok, MasterIP} = snmp_misc:ip(MasterHost),
+ {ok, MIP} = snmp_misc:ip(MgrHost),
+ {ok, SIP} = snmp_misc:ip(SaHost),
+
+
+ put(mgr_node, MgrNode),
+ put(sa_node, SaNode),
+ put(master_node, MasterNode),
+ put(sa_host, SaHost),
+ put(mgr_host, MgrHost),
+ put(master_host, MasterHost),
+ put(mip, tuple_to_list(MIP)),
+ put(masterip , tuple_to_list(MasterIP)),
+ put(sip, tuple_to_list(SIP)),
+
+ MibDir = ?config(mib_dir, Config),
+ put(mib_dir, MibDir),
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ put(std_mib_dir, StdM),
+
+ MgrDir = ?config(mgr_dir, Config),
+ put(mgr_dir, MgrDir),
+
+ put(vsn, ?config(vsn, Config)),
+ ?DBG("init_case -> exit with"
+ "~n MasterNode: ~p"
+ "~n SaNode: ~p"
+ "~n MgrNode: ~p"
+ "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
+ {SaNode, MgrNode, MibDir}.
+
+load_master(Mib) ->
+ ?DBG("load_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+
+load_master_std(Mib) ->
+ ?DBG("load_master_std -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+
+unload_master(Mib) ->
+ ?DBG("unload_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+
+loaded_mibs() ->
+ ?DBG("loaded_mibs -> entry",[]),
+ Info = snmpa:info(snmp_master_agent),
+ {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
+ [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
+
+unload_mibs(Mibs) ->
+ ?DBG("unload_mibs -> entry with"
+ "~n Mibs: ~p", [Mibs]),
+ ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
+
+start_subagent(SaNode, RegTree, Mib) ->
+ ?DBG("start_subagent -> entry with"
+ "~n SaNode: ~p"
+ "~n RegTree: ~p"
+ "~n Mib: ~p", [SaNode, RegTree, Mib]),
+ MA = whereis(snmp_master_agent),
+ ?DBG("start_subagent -> MA: ~p", [MA]),
+ MibDir = get(mib_dir),
+ Mib1 = join(MibDir,Mib),
+ %% BMK BMK
+% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
+ case rpc:call(SaNode, snmpa_supervisor,
+ start_sub_agent, [MA, RegTree, [Mib1]]) of
+ {ok, SA} ->
+ ?DBG("start_subagent -> SA: ~p", [SA]),
+ {ok, SA};
+ Error ->
+ ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
+ end.
+
+stop_subagent(SA) ->
+ ?DBG("stop_subagent -> entry with"
+ "~n SA: ~p", [SA]),
+ %% BNK BMK
+ %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
+ rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
+
+%%-----------------------------------------------------------------
+%% This function takes care of the old OTP-SNMPEA-MIB.
+%% Unfortunately, the testcases were written to use the data in the
+%% internal tables, and these table are now obsolete and not used
+%% by the agent. Therefore, we emulate them by using
+%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
+%%
+%% These two rows must exist in intCommunityTable
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+%% (But with the manager's IP address)
+%%
+%%-----------------------------------------------------------------
+init_old() ->
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [6 | "public"],
+ {get(mip), "public", 2, 2}),
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [13 | "standard trap"],
+ {get(mip), "standard trap", 2, 1}),
+ snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
+
+
+
+simple(suite) -> [];
+simple(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(simple_standard_test).
+
+simple_2(X) -> simple(X).
+
+simple_bi(suite) -> [];
+simple_bi(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(vsn, v1), % First, try v1 manager
+ try_test(simple_standard_test),
+
+ put(vsn, v2), % Then, try v2 manager
+ try_test(simple_standard_test).
+
+simple_3(X) ->
+ simple(X).
+
+big(suite) -> [];
+big(Config) when list(Config) ->
+ ?DBG("big -> entry", []),
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?DBG("big -> SA: ~p", [SA]),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+big_2(X) -> big(X).
+
+big_3(X) -> big(X).
+
+
+big2(suite) -> [];
+big2(Config) when list(Config) ->
+ %% This is exactly the same tests as 'big', but with the
+ %% v2 equivalent of the mibs.
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
+ ?line load_master("OLD-SNMPEA-MIB-v2"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB-v2").
+
+big2_2(X) -> big2(X).
+
+big2_3(X) -> big2(X).
+
+
+multi_threaded(suite) -> [];
+multi_threaded(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(multi_threaded_test),
+ ?line unload_master("Test1").
+
+mt_trap(suite) -> [];
+mt_trap(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ ?line load_master("TestTrapv2"),
+ try_test(mt_trap_test, [MA]),
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("Test1").
+
+v2_types(suite) -> [];
+v2_types(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(types_v2_test),
+ ?line unload_master("Test1").
+
+v2_types_3(X) -> v2_types(X).
+
+
+implied(suite) -> [];
+implied(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(implied_test,[MA]),
+ ?line unload_master("Test1").
+
+implied_3(X) -> implied(X).
+
+
+sparse_table(suite) -> [];
+sparse_table(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(sparse_table_test),
+ ?line unload_master("Test1").
+
+sparse_table_2(X) -> sparse_table(X).
+
+sparse_table_3(X) -> sparse_table(X).
+
+cnt_64(suite) -> [];
+cnt_64(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(cnt_64_test, [MA]),
+ ?line unload_master("Test1").
+
+cnt_64_2(X) -> cnt_64(X).
+
+cnt_64_3(X) -> cnt_64(X).
+
+opaque(suite) -> [];
+opaque(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(opaque_test),
+ ?line unload_master("Test1").
+
+opaque_2(X) -> opaque(X).
+
+opaque_3(X) -> opaque(X).
+
+
+change_target_addr_config(suite) -> [];
+change_target_addr_config(Config) when list(Config) ->
+ p("Testing changing target address config..."),
+ ?LOG("change_target_addr_config -> entry",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(sname,snmp_suite),
+ put(verbosity,trace),
+
+ MA = whereis(snmp_master_agent),
+
+ ?LOG("change_target_addr_config -> load TestTrap",[]),
+ ?line load_master("TestTrap"),
+
+ ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,trace),
+
+ %% First send some traps that will arive att the original manager
+ ?LOG("change_target_addr_config -> send trap",[]),
+ try_test(ma_trap1, [MA]),
+
+ ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,silence),
+
+ %% Start new dummy listener
+ ?LOG("change_target_addr_config -> start dummy manager",[]),
+ ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+
+ %% Reconfigure
+ ?LOG("change_target_addr_config -> reconfigure",[]),
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_addr_conf(AgentDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ %% Send the trap again
+ ?LOG("change_target_addr_config -> send trap again",[]),
+ catch dummy_manager_send_trap2(Pid),
+
+ ?LOG("change_target_addr_config -> await trap ack",[]),
+ catch dummy_manager_await_trap2_ack(),
+
+ ?LOG("change_target_addr_config -> stop dummy manager",[]),
+ ?line ok = dummy_manager_stop(Pid),
+
+ ?LOG("change_target_addr_config -> reset target address config",[]),
+ ?line reset_target_addr_conf(AgentDir),
+
+ ?LOG("change_target_addr_config -> unload TestTrap",[]),
+ ?line unload_master("TestTrap").
+
+
+dummy_manager_start(MA) ->
+ ?DBG("dummy_manager_start -> entry",[]),
+ Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
+ ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
+ await_dummy_manager_started(Pid).
+
+await_dummy_manager_started(Pid) ->
+ receive
+ {dummy_manager_started,Pid,Port} ->
+ ?DBG("dummy_manager_start -> acknowledge received with"
+ "~n Port: ~p",[Port]),
+ {ok,Pid,Port};
+ {'EXIT', Pid, Reason} ->
+ {error, Pid, Reason};
+ O ->
+ ?LOG("dummy_manager_start -> received unknown message:"
+ "~n ~p",[O]),
+ await_dummy_manager_started(Pid)
+ end.
+
+dummy_manager_stop(Pid) ->
+ ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
+ Pid ! stop,
+ receive
+ {dummy_manager_stopping, Pid} ->
+ ?DBG("dummy_manager_stop -> acknowledge received",[]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_stop -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_send_trap2(Pid) ->
+ ?DBG("dummy_manager_send_trap2 -> entry",[]),
+ Pid ! {send_trap,testTrap2}.
+
+dummy_manager_await_trap2_ack() ->
+ ?DBG("dummy_manager_await_trap2 -> entry",[]),
+ receive
+ {received_trap,Trap} ->
+ ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
+ %% Note:
+ %% Without this sleep the v2_inform_i testcase failes! There
+ %% is no relation between these two test cases as far as I
+ %% able to figure out...
+ sleep(60000),
+ ok;
+ O ->
+ ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_await_trap2 -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_init(Parent,MA) ->
+ ?DBG("dummy_manager_init -> entry with"
+ "~n Parent: ~p"
+ "~n MA: ~p",[Parent,MA]),
+ {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
+ ?DBG("dummy_manager_init -> S: ~p",[S]),
+ {ok,Port} = inet:port(S),
+ ?DBG("dummy_manager_init -> Port: ~p",[Port]),
+ Parent ! {dummy_manager_started,self(),Port},
+ dummy_manager_loop(Parent,S,MA).
+
+dummy_manager_loop(P,S,MA) ->
+ ?LOG("dummy_manager_loop -> ready for receive",[]),
+ receive
+ {send_trap,Trap} ->
+ ?LOG("dummy_manager_loop -> received trap send request"
+ "~n Trap: ~p",[Trap]),
+ snmpa:send_trap(MA, Trap, "standard trap"),
+ dummy_manager_loop(P,S,MA);
+ {udp, _UdpId, Ip, UdpPort, Bytes} ->
+ ?LOG("dummy_manager_loop -> received upd message"
+ "~n from: ~p:~p"
+ "~n size: ~p",
+ [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
+ R = dummy_manager_handle_message(Bytes),
+ ?DBG("dummy_manager_loop -> R: ~p",[R]),
+ P ! R,
+ dummy_manager_loop(P,S,MA);
+ stop ->
+ ?DBG("dummy_manager_loop -> received stop request",[]),
+ P ! {dummy_manager_stopping, self()},
+ gen_udp:close(S),
+ exit(normal);
+ O ->
+ ?LOG("dummy_manager_loop -> received unknown message:"
+ "~n ~p",[O]),
+ dummy_manager_loop(P,S,MA)
+ end.
+
+dummy_manager_message_sz(B) when binary(B) ->
+ size(B);
+dummy_manager_message_sz(L) when list(L) ->
+ length(L);
+dummy_manager_message_sz(_) ->
+ undefined.
+
+dummy_manager_handle_message(Bytes) ->
+ case (catch snmp_pdus:dec_message(Bytes)) of
+ {'EXIT',Reason} ->
+ ?ERR("dummy_manager_handle_message -> "
+ "failed decoding message only:~n ~p",[Reason]),
+ {error,Reason};
+ M ->
+ ?DBG("dummy_manager_handle_message -> decoded message:"
+ "~n ~p",[M]),
+ {received_trap,M}
+ end.
+
+
+api(suite) -> [];
+api(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(api_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+api_2(X) -> api(X).
+
+api_3(X) -> api(X).
+
+
+subagent(suite) -> [];
+subagent(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ try_test(load_test_sa),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+
+ p("Loading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(load_test),
+
+ p("Unloading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(unreg_test),
+ p("Testing register subagent..."),
+ rpc:call(SaNode, snmp, register_subagent,
+ [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ ?line stop_subagent(SA),
+ try_test(unreg_test).
+
+subagent_2(X) -> subagent(X).
+
+subagent_3(X) -> subagent(X).
+
+
+mnesia(suite) -> [];
+mnesia(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent with mnesia impl..."),
+ {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ try_test(big_test_2),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA).
+
+mnesia_2(X) -> mnesia(X).
+
+mnesia_3(X) -> mnesia(X).
+
+
+multiple_reqs(suite) ->
+ {req, [], {conf, init_mul, mul_cases(), finish_mul}}.
+
+mul_cases() ->
+ [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err].
+
+multiple_reqs_2(suite) ->
+ {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}.
+
+multiple_reqs_3(_X) ->
+ {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
+
+
+mul_cases_2() ->
+ [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2].
+
+
+mul_cases_3() ->
+ [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
+
+
+init_mul(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ [{mul_sub, SA} | Config].
+
+finish_mul(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ SA = ?config(mul_sub, Config),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA),
+ lists:keydelete(mul_sub, 1, Config).
+
+mul_get(suite) -> [];
+mul_get(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get..."),
+ try_test(do_mul_get).
+
+mul_get_2(X) -> mul_get(X).
+
+mul_get_3(X) -> mul_get(X).
+
+
+mul_get_err(suite) -> [];
+mul_get_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get with error..."),
+ try_test(do_mul_get_err).
+
+mul_get_err_2(X) -> mul_get_err(X).
+
+mul_get_err_3(X) -> mul_get_err(X).
+
+
+mul_next(suite) -> [];
+mul_next(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next).
+
+mul_next_2(X) -> mul_next(X).
+
+mul_next_3(X) -> mul_next(X).
+
+
+mul_next_err(suite) -> [];
+mul_next_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next_err).
+
+mul_next_err_2(X) -> mul_next_err(X).
+
+mul_next_err_3(X) -> mul_next_err(X).
+
+
+mul_set(suite) -> [];
+mul_set(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set..."),
+ try_test(do_mul_set).
+
+mul_set_2(X) -> mul_set(X).
+
+mul_set_3(X) -> mul_set(X).
+
+
+mul_set_err(suite) -> [];
+mul_set_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set with error..."),
+ try_test(do_mul_set_err).
+
+mul_set_err_2(X) -> mul_set_err(X).
+
+mul_set_err_3(X) -> mul_set_err(X).
+
+
+sa_register(suite) -> [];
+sa_register(Config) when list(Config) ->
+ ?DBG("sa_register -> entry", []),
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?DBG("sa_register -> start subagent", []),
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+
+ ?DBG("sa_register -> unregister subagent", []),
+ p("Testing unregister subagent (2)..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Loading SA-MIB..."),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ ?DBG("sa_register -> register subagent", []),
+ rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
+ try_test(sa_mib),
+
+ ?DBG("sa_register -> stop subagent", []),
+ ?line stop_subagent(SA).
+
+sa_register_2(X) -> sa_register(X).
+
+sa_register_3(X) -> sa_register(X).
+
+
+v1_trap(suite) -> [];
+v1_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_trap1, [MA]),
+ try_test(ma_trap2, [MA]),
+ try_test(ma_v2_2_v1_trap, [MA]),
+ try_test(ma_v2_2_v1_trap2, [MA]),
+
+ p("Testing trap sending from subagent..."),
+ try_test(sa_trap1, [SA]),
+ try_test(sa_trap2, [SA]),
+ try_test(sa_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v2_trap(suite) -> [];
+v2_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+
+ try_test(ma_v2_trap1, [MA]),
+ try_test(ma_v2_trap2, [MA]),
+ try_test(ma_v1_2_v2_trap, [MA]),
+ try_test(ma_v1_2_v2_trap2, [MA]),
+
+ try_test(sa_mib),
+ p("Testing trap sending from subagent..."),
+ try_test(sa_v1_2_v2_trap1, [SA]),
+ try_test(sa_v1_2_v2_trap2, [SA]),
+ try_test(sa_v1_2_v2_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v3_trap(X) ->
+ v2_trap(X).
+
+v2_inform(suite) ->
+ {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}.
+
+v3_inform(_X) ->
+ %% v2_inform(X).
+ {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
+
+init_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+init_v3_inform(X) ->
+ init_v2_inform(X).
+
+finish_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+finish_v3_inform(X) ->
+ finish_v2_inform(X).
+
+
+
+v2_inform_i(suite) -> [];
+v2_inform_i(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing inform sending from master agent... NOTE! This test\ntakes a "
+ "few minutes (5) to complete."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_v2_inform1, [MA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2").
+
+v3_inform_i(X) -> v2_inform_i(X).
+
+
+sa_error(suite) -> [];
+sa_error(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing sa bad value (is_set_ok)..."),
+ try_test(sa_errs_bad_value),
+
+ p("Testing sa gen err (set)..."),
+ try_test(sa_errs_gen_err),
+
+ p("Testing too big..."),
+ try_test(sa_too_big),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
+
+sa_error_2(X) -> sa_error(X).
+
+sa_error_3(X) -> sa_error(X).
+
+
+next_across_sa(suite) -> [];
+next_across_sa(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Loading another subagent mib..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+
+ rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ p("Testing next across subagent (endOfMibView from SA)..."),
+ try_test(next_across_sa),
+
+ p("Unloading mib"),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Starting another subagent"),
+ ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ p("Testing next across subagent (wrong prefix from SA)..."),
+ try_test(next_across_sa),
+
+ stop_subagent(SA),
+ stop_subagent(SA2).
+
+next_across_sa_2(X) -> next_across_sa(X).
+
+next_across_sa_3(X) -> next_across_sa(X).
+
+
+undo(suite) -> [];
+undo(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing undo phase at master agent..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ try_test(undo_test),
+ try_test(api_test2),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+
+ p("Testing bad return values from instrum. funcs..."),
+ try_test(bad_return),
+
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+
+ p("Testing undo phase at subagent..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ try_test(undo_test),
+ try_test(api_test3),
+
+ p("Testing undo phase across master/subagents..."),
+ try_test(undo_test),
+ try_test(api_test3),
+ stop_subagent(SA).
+
+undo_2(X) -> undo(X).
+
+undo_3(X) -> undo(X).
+
+%% Req. Test2
+v1_processing(suite) -> [];
+v1_processing(Config) when list(Config) ->
+ ?DBG("v1_processing -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v1_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v2_processing(suite) -> [];
+v2_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v3_processing(suite) -> [];
+v3_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc), % same as v2!
+ ?line unload_master("Test2").
+
+
+%% We'll try get/set/trap and inform for all the auth & priv protocols.
+%% For informs, the mgr is auth-engine. The agent has to sync. This is
+%% accomplished by the first inform sent. That one will generate a
+%% report, which makes it in sync. The notification-generating
+%% application times out, and send again. This time it'll work.
+v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv].
+
+v3_crypto_basic(suite) -> [];
+v3_crypto_basic(_Config) ->
+ EID = [0,0,0,0,0,0,0,0,0,0,0,2],
+ %% From rfc2274 appendix A.3.1
+ ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
+ ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
+ 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
+ KMd5_1,
+ %% From rfc2274 appendix A.3.2
+ ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
+ ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
+ 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
+ KSHA_1,
+ %% From rfc2274, appendix A.5.1
+ ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
+ 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ %% From rfc2274, appendix A.5.2
+ ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
+ 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
+ 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ KSHA_1t = lists:sublist(KSHA_1, 16),
+ KSHA_2t = lists:sublist(KSHA_2, 16),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
+ 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+
+ %% Try with correct random
+ ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
+ ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
+ ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
+ ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
+ ok.
+
+
+
+v3_md5_auth(suite) -> [];
+v3_md5_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing MD5 authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_sha_auth(suite) -> [];
+v3_sha_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing SHA authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_des_priv(suite) -> [];
+v3_des_priv(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing DES encryption...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+%% Make sure mgr is in sync with agent
+v3_sync(Funcs) ->
+ ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
+ g([[sysDescr, 0]]),
+ expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
+ g([[sysDescr, 0]]),
+ expect(433, [{[sysDescr,0], any}]),
+ lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
+
+v3_inform_sync(MA) ->
+ ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
+ "standard inform", []),
+ %% Make sure agent is in sync with mgr...
+ ?DBG("v3_sync -> wait some time: ",[]),
+ sleep(20000), % more than 1500*10 in target_addr.conf
+ ?DBG("v3_sync -> await response",[]),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]).
+
+
+v2_caps(suite) -> [];
+v2_caps(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(v2_caps_i, [node()]).
+
+v2_caps_3(X) -> v2_caps(X).
+
+
+v2_caps_i(Node) ->
+ ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
+ g([[sysORID, Idx], [sysORDescr, Idx]]),
+ ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
+ {[sysORDescr, Idx], "test cap"}]),
+ ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
+ g([[sysORID, Idx]]),
+ ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
+
+
+%% Req. Test2
+v1_proc() ->
+ ?DBG("v1_proc -> entry", []),
+ %% According to RFC1157.
+ %% Template: <Section>:<list no>
+ v1_get_p(),
+ v1_get_next_p(),
+ v1_set_p().
+
+
+v1_get_p() ->
+ %% 4.1.2:1
+ g([[test2]]),
+ ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
+ g([[tDescr]]),
+ ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
+ g([[tDescr2,0]]),
+ ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ g([[tDescr3,0]]),
+ ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ g([[tDescr4,0]]),
+ ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ {[tDescr,0], 'NULL'}]),
+ g([[sysDescr,3]]),
+ ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+
+ %% 4.1.2:2
+ g([[tTable]]),
+ ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
+ g([[tEntry]]),
+ ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
+
+ %% 4.1.2:3
+ g([[tTooBig, 0]]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.2:4
+ g([[tGenErr1, 0]]),
+ ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]).
+
+
+v1_get_next_p() ->
+ %% 4.1.3:1
+ gn([[1,3,7,1]]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+ gn([[tDescr2]]),
+ ?line expect(11, tooBig, 0, any),
+
+ %% 4.1.3:2
+ gn([[tTooBig]]),
+ io:format("We currently don't handle tooBig correct!!!\n"),
+% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
+ ?line expect(20, tooBig, 0, any),
+
+ %% 4.1.3:3
+ gn([[tGenErr1]]),
+% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?line expect(40, genErr, 1, any),
+ gn([[tGenErr2]]),
+% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?line expect(41, genErr, 1, any),
+ gn([[sysDescr], [tGenErr3]]),
+% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
+% {[tGenErr3], 'NULL'}]).
+ ?line expect(42, genErr, 2, any).
+
+v1_set_p() ->
+ %% 4.1.5:1
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+ s([{[tDescr3], s, "noSuchObject"}]),
+ ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+ s([{[tDescr3,1], s, "noSuchInstance"}]),
+ ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+ s([{[tDescr2,0], s, "inconsistentName"}]),
+ ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+
+ %% 4.1.5:2
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.1.5:3
+ %% The standard is quite incorrect here. The resp pdu was too big. In
+ %% the resp pdu, we have the original vbs. In the tooBig pdu we still
+ %% have to original vbs => the tooBig pdu is too big as well!!! It
+ %% may not get it to the manager, unless the agent uses 'NULL' instead
+ %% of the std-like original value.
+ s([{[tTooBig, 0], s, ?tooBigStr}]),
+ %% according to std:
+% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.5:4
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+ s([{[tDescr2, 0], s, "commit_fail"}]),
+ ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+
+%% Req. Test2
+v2_proc() ->
+ %% According to RFC1905.
+ %% Template: <Section>:<list no>
+ ?DBG("v2_proc -> entry",[]),
+ v2_get_p(),
+ v2_get_next_p(),
+ v2_get_bulk_p(),
+ v2_set_p().
+
+v2_get_p() ->
+ %% 4.2.1:2
+ ?DBG("v2_get_p -> entry",[]),
+ g([[test2]]),
+ ?line expect(10, [{[test2], noSuchObject}]),
+ g([[tDescr]]),
+ ?line expect(11, [{[tDescr], noSuchObject}]),
+ g([[tDescr4,0]]),
+ ?line expect(12, [{[tDescr4,0], noSuchObject}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[tDescr,0], noSuchObject}]),
+ g([[tTable]]),
+ ?line expect(14, [{[tTable], noSuchObject}]),
+ g([[tEntry]]),
+ ?line expect(15, [{[tEntry], noSuchObject}]),
+
+ %% 4.2.1:3
+ g([[tDescr2,0]]), %% instrum ret noSuchName!!!
+ ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
+ g([[tDescr3,0]]),
+ ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
+ g([[sysDescr,3]]),
+ ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
+ g([[tIndex,1]]),
+ ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
+
+ %% 4.2.1 - any other error: genErr
+ g([[tGenErr1, 0]]),
+ ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]),
+
+ %% 4.2.1 - tooBig
+ g([[tTooBig, 0]]),
+ ?line expect(40, tooBig, 0, []).
+
+
+v2_get_next_p() ->
+ %% 4.2.2:2
+ ?DBG("v2_get_next_p -> entry",[]),
+ gn([[1,3,7,1]]),
+ ?line expect(10, [{[1,3,7,1], endOfMibView}]),
+ gn([[sysDescr], [1,3,7,1]]),
+ ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gn([[tCnt2, 1]]),
+ ?line expect(12, [{[tCnt2,2], 100}]),
+ gn([[tCnt2, 2]]),
+ ?line expect(12, [{[tCnt2,2], endOfMibView}]),
+
+ %% 4.2.2 - any other error: genErr
+ gn([[tGenErr1]]),
+ ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ gn([[tGenErr2]]),
+ ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ gn([[sysDescr], [tGenErr3]]),
+ ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
+ {[tGenErr3], 'NULL'}]),
+
+ %% 4.2.2 - tooBig
+ gn([[tTooBig]]),
+ ?line expect(20, tooBig, 0, []).
+
+v2_get_bulk_p() ->
+ %% 4.2.3
+ ?DBG("v2_get_bulk_p -> entry",[]),
+ gb(1, 1, []),
+ ?line expect(10, []),
+ gb(-1, 1, []),
+ ?line expect(11, []),
+ gb(-1, -1, []),
+ ?line expect(12, []),
+ gb(-1, -1, []),
+ ?line expect(13, []),
+ gb(2, 0, [[sysDescr], [1,3,7,1]]),
+ ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(1, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(0, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
+ ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
+ ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[sysDescr, 0], "Erlang SNMP agent"}]),
+
+ gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
+ ?line expect(19, []),
+
+ gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
+ ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
+ {[sysObjectID], 'NULL'},
+ {[tGenErr1], 'NULL'},
+ {[sysDescr], 'NULL'}]),
+ gb(0, 2, [[tCnt2, 1]]),
+ ?line expect(21, [{[tCnt2,2], 100},
+ {[tCnt2,2], endOfMibView}]).
+
+
+v2_set_p() ->
+ %% 4.2.5:1
+ ?DBG("v2_set_p -> entry",[]),
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
+
+ %% 4.2.5:2
+ s([{[1,3,6,1,0], s, "noSuchObject"}]),
+ ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
+
+ %% 4.2.5:3
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.2.5:4
+ s([{[tStr, 0], s, ""}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
+ s([{[tStr, 0], s, "12345"}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
+
+ %% 4.2.5:5 - N/A
+
+ %% 4.2.5:6
+ s([{[tInt1, 0], i, 0}]),
+ ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
+ s([{[tInt1, 0], i, 5}]),
+ ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
+ s([{[tInt2, 0], i, 0}]),
+ ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
+ s([{[tInt2, 0], i, 5}]),
+ ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
+ s([{[tInt3, 0], i, 5}]),
+ ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
+
+ %% 4.2.5:7
+ s([{[tDescrX, 1, 1], s, "noCreation"}]),
+ ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
+
+ %% 4.2.5:8
+ s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
+ ?line expect(80, inconsistentName, 1,
+ [{[tDescrX, 1, 2], "inconsistentName"}]),
+
+ %% 4.2.5:9
+ s([{[tCnt, 1, 2], i, 5}]),
+ ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
+
+ %% 4.2.5:10
+ s([{[tDescr2,0], s, "inconsistentValue"}]),
+ ?line expect(100, inconsistentValue, 1,
+ [{[tDescr2,0], "inconsistentValue"}]),
+
+ %% 4.2.5:11
+ s([{[tDescr2,0], s, "resourceUnavailable"}]),
+ ?line expect(110, resourceUnavailable, 1,
+ [{[tDescr2,0],"resourceUnavailable"}]),
+
+ %% 4.2.5:12
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
+
+ %% commitFailed and undoFailed is tested by the 'undo' case.
+
+
+%% Req. OLD-SNMPEA-MIB
+table_test() ->
+ io:format("Testing simple get, next and set on communityTable...~n"),
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+ Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
+ Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
+ Key1c4 = [intCommunityAccess,get(mip),is("public")],
+ EndKey = [intCommunityEntry,[9],get(mip),is("public")],
+ gn([[intCommunityEntry]]),
+ ?line expect(7, [{Key1c3, 2}]),
+ gn([[intCommunityTable]]),
+ ?line expect(71, [{Key1c3, 2}]),
+ gn([[community]]),
+ ?line expect(72, [{Key1c3, 2}]),
+ gn([[otpSnmpeaMIB]]),
+ ?line expect(73, [{Key1c3, 2}]),
+ gn([[ericsson]]),
+ ?line expect(74, [{Key1c3, 2}]),
+ gn([Key1c3]),
+ ?line expect(8, [{Key2c3, 2}]),
+ gn([Key2c3]),
+ ?line expect(9, [{Key1c4, 2}]),
+ gn([EndKey]),
+ AgentIp = [intAgentIpAddress,0],
+ ?line expect(10, [{AgentIp, any}]),
+ g([Key1c3]),
+ ?line expect(11, [{Key1c3, 2}]),
+ g([EndKey]),
+ ?line ?v1_2(expect(12, noSuchName, 1, any),
+ expect(12, [{EndKey, noSuchObject}])),
+
+ io:format("Testing row creation/deletion on communityTable...~n"),
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+ s([{NewKeyc5, ?createAndGo}]),
+ ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
+ s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
+ ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
+ g([NewKeyc4]),
+ ?line expect(16, [{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(17, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?createAndWait}]),
+ ?line expect(19, [{NewKeyc5, ?createAndWait}]),
+ g([NewKeyc5]),
+ ?line expect(20, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(21, [{NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(22, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc3, 2}]),
+ ?line expect(23, [{NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(24, [{NewKeyc5, ?notInService}]),
+ s([{NewKeyc5, ?active}]),
+ ?line expect(25, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(26, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc3, 3}]),
+ ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
+ otp_1128().
+
+%% Req. system group
+simple_standard_test() ->
+ ?DBG("simple_standard_test -> entry",[]),
+ gn([[1,1]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3]]),
+ ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6]]),
+ ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1]]),
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2]]),
+ ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1]]),
+ ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1,1]]),
+ ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[sysDescr]]),
+ ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr,0]]),
+ ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr]]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{[sysDescr], noSuchObject}])),
+ g([[1,6,7,0]]),
+ ?line ?v1_2(expect(41, noSuchName, 1, any),
+ expect(3, [{[1,6,7,0], noSuchObject}])),
+ gn([[1,13]]),
+ ?line ?v1_2(expect(4, noSuchName,1, any),
+ expect(4, [{[1,13], endOfMibView}])),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+ g([[sysLocation, 0]]),
+ ?line expect(6, [{[sysLocation, 0], "new_value"}]),
+ io:format("Testing noSuchName and badValue...~n"),
+ s([{[sysServices,0], 3}]),
+ ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
+ s([{[sysLocation, 0], i, 3}]),
+ ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
+ ?DBG("simple_standard_test -> done",[]),
+ ok.
+
+%% This is run in the agent node
+db_notify_client(suite) -> [];
+db_notify_client(Config) when list(Config) ->
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
+ [SaNode,MgrNode,MibDir]),
+ snmpa_local_db:register_notify_client(self(),?MODULE),
+
+ %% This call (the manager) will issue to set operations, so
+ %% we expect to receive to notify(insert) calls.
+ try_test(db_notify_client_test),
+
+ ?DBG("await first notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
+ end,
+
+ ?DBG("await second notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
+ end,
+
+ snmpa_local_db:unregister_notify_client(self()).
+
+
+%% This is run in the manager node
+db_notify_client_test() ->
+ ?DBG("set first new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?DBG("set second new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]).
+
+notify(Pid,What) ->
+ ?DBG("notify(~p,~p) -> called",[Pid,What]),
+ Pid ! {db_notify_test_reply,What}.
+
+
+%% Req: system group, OLD-SNMPEA-MIB, Klas1
+big_test() ->
+ ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
+ simple_standard_test(),
+
+ ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
+ gn([[klas1]]),
+ ?line expect(1, [{[fname,0], ""}]),
+ g([[fname,0]]),
+ ?line expect(2, [{[fname,0], ""}]),
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[fname,0]]),
+ ?line expect(4, [{[fname,0], "test set"}]),
+
+ ?DBG("big_test -> "
+ "testing next from last instance in master to subagent...",[]),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname,0], "test set"}]),
+ s([{[fname,0], s, ""}]),
+ ?line expect(52, [{[fname,0], ""}]),
+
+ table_test(),
+
+ ?DBG("big_test -> adding one row in subagent table",[]),
+ _FTab = [friendsEntry],
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {[friendsEntry, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ s([{[friendsEntry, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
+
+ otp_1131(),
+
+ ?DBG("big_test -> adding two rows in subagent table with special INDEX",
+ []),
+ s([{[kompissEntry, [1, 3]], s, "kompis3"},
+ {[kompissEntry, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry, [1, 3]],
+ [kompissEntry, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ gn([[kompissEntry, [1]],
+ [kompissEntry, [2]]]),
+ ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ s([{[kompissEntry, [1, 2]], s, "kompis3"},
+ {[kompissEntry, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry, [1, 1]],
+ [kompissEntry, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?active}]),
+ s([{[kompissEntry, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
+ s([{[kompissEntry, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
+ ?DBG("big_test -> done",[]),
+ ok.
+
+%% Req. system group, Klas2, OLD-SNMPEA-MIB
+big_test_2() ->
+ p("Testing simple next/get/set @ master agent (2)..."),
+ simple_standard_test(),
+
+ p("Testing simple next/get/set @ subagent (2)..."),
+ gn([[klas2]]),
+ ?line expect(1, [{[fname2,0], ""}]),
+ g([[fname2,0]]),
+ ?line expect(2, [{[fname2,0], ""}]),
+ s([{[fname2,0], s, "test set"}]),
+ ?line expect(3, [{[fname2,0], "test set"}]),
+ g([[fname2,0]]),
+ ?line expect(4, [{[fname2,0], "test set"}]),
+
+ otp_1298(),
+
+ p("Testing next from last object in master to subagent (2)..."),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname2,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname2,0], "test set"}]),
+
+ table_test(),
+
+ p("Adding one row in subagent table (2)"),
+ _FTab = [friendsEntry2],
+ s([{[friendsEntry2, [2, 3]], s, "kompis3"},
+ {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry2, [2, 3]],
+ [friendsEntry2, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?active}]),
+ s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
+
+ p("Adding two rows in subagent table with special INDEX (2)"),
+ s([{[kompissEntry2, [1, 3]], s, "kompis3"},
+ {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry2, [1, 3]],
+ [kompissEntry2, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ gn([[kompissEntry2, [1]],
+ [kompissEntry2, [2]]]),
+ ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ s([{[kompissEntry2, [1, 2]], s, "kompis3"},
+ {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry2, [1, 1]],
+ [kompissEntry2, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?active}]),
+ s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
+ s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
+ ok.
+
+%% Req. Test1
+multi_threaded_test() ->
+ p("Testing multi threaded agent..."),
+ g([[multiStr,0]]),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(1, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "pelle"}]),
+ ?line expect(2, [{[sysLocation, 0], "pelle"}]),
+ Pid ! continue,
+ ?line expect(3, [{[multiStr,0], "ok"}]),
+
+ s([{[multiStr, 0], s, "block"}]),
+ Pid2 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(4, [{[sysUpTime,0], any}]),
+ g([[multiStr,0]]),
+ Pid3 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(5, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "kalle"}]),
+ Pid3 ! continue,
+ ?line expect(6, [{[multiStr,0], "ok"}]),
+ Pid2 ! continue,
+ ?line expect(7, [{[multiStr,0], "block"}]),
+ ?line expect(8, [{[sysLocation,0], "kalle"}]).
+
+%% Req. Test1, TestTrapv2
+mt_trap_test(MA) ->
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ snmpa:send_trap(MA, mtTrap, "standard trap"),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(2, [{[sysUpTime,0], any}]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ Pid ! continue,
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [2]},
+ {[multiStr,0], "ok"}]).
+
+
+get_multi_pid() ->
+ get_multi_pid(10).
+get_multi_pid(0) ->
+ ?line ?FAIL(no_global_name);
+get_multi_pid(N) ->
+ sleep(1000),
+ case global:whereis_name(snmp_multi_tester) of
+ Pid when pid(Pid) -> Pid;
+ _ -> get_multi_pid(N-1)
+ end.
+
+%% Req. Test1
+types_v2_test() ->
+ p("Testing v2 types..."),
+
+ s([{[bits1,0], 2#10}]),
+ ?line expect(1, [{[bits1,0], ?str(2#10)}]),
+ g([[bits1,0]]),
+ ?line expect(2, [{[bits1,0], ?str(2#101)}]),
+
+ s([{[bits2,0], 2#11000000110}]),
+ ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
+ g([[bits2,0]]),
+ ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
+
+ g([[bits3,0]]),
+ ?line expect(50, genErr, 1, any),
+
+ g([[bits4,0]]),
+ ?line expect(51, genErr, 1, any),
+
+ s([{[bits1,0], s, [2#10]}]),
+ ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
+
+ s([{[bits2,0], 2#11001001101010011}]),
+ ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%% Req. Test1
+implied_test(MA) ->
+ ?LOG("implied_test -> start",[]),
+ p("Testing IMPLIED..."),
+
+ snmpa:verbosity(MA,trace),
+ snmpa:verbosity(MA,trace),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = "apa",
+ Idx2 = "qq",
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
+ ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
+ {[testDescr, Idx1], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
+ ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
+ {[testDescr, Idx2], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr)",[]),
+ gn([[testDescr]]),
+ ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
+ gn([[testDescr,Idx1]]),
+ ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?destroy}]),
+ ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?destroy}]),
+ ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
+
+ %% Try the same in other table
+ Idx3 = [1, "apa"],
+ Idx4 = [1, "qq"],
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
+ ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
+ {[testDescr2, Idx3], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
+ ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
+ {[testDescr2, Idx4], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr2)",[]),
+ gn([[testDescr2]]),
+ ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
+ gn([[testDescr2,Idx3]]),
+ ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?destroy}]),
+ ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?destroy}]),
+ ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
+
+ snmpa:verbosity(MA,log),
+
+ ?LOG("implied_test -> done",[]).
+
+
+
+%% Req. Test1
+sparse_table_test() ->
+ p("Testing sparse table..."),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ s([{[sparseStatus, Idx1], i, ?createAndGo},
+ {[sparseDescr, Idx1], s, "row 1"}]),
+ ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
+ {[sparseDescr, Idx1], "row 1"}]),
+ s([{[sparseStatus, Idx2], i, ?createAndGo},
+ {[sparseDescr, Idx2], s, "row 2"}]),
+ ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
+ {[sparseDescr, Idx2], "row 2"}]),
+ ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
+ [sparseStatus,Idx1], [sparseStatus,Idx2]]),
+ gb(0,5,[[sparseIndex]])),
+ ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
+ {[sparseDescr,Idx2], "row 2"},
+ {[sparseStatus,Idx1], ?active},
+ {[sparseStatus,Idx2], ?active},
+ {[sparseStr,0], "slut"}]),
+ % Delete the rows
+ s([{[sparseStatus, Idx1], i, ?destroy}]),
+ ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
+ s([{[sparseStatus, Idx2], i, ?destroy}]),
+ ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
+
+
+%% Req. Test1
+cnt_64_test(MA) ->
+ ?LOG("start cnt64 test (~p)",[MA]),
+ snmpa:verbosity(MA,trace),
+ ?LOG("start cnt64 test",[]),
+ p("Testing Counter64, and at the same time, RowStatus is not last column"),
+
+ ?DBG("get cnt64",[]),
+ g([[cnt64,0]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(1, noSuchName, 1, any),
+ expect(1, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("get-next cnt64",[]),
+ gn([[cnt64]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
+ expect(2, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("send cntTrap",[]),
+ snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
+ {cnt64, 10},
+ {sysLocation, "here"}]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ {[sysLocation,0], "here"}]),
+ expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [1]},
+ {[sysContact,0], "pelle"},
+ {[cnt64,0], 10},
+ {[sysLocation,0], "here"}])),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ ?DBG("create row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
+ ?DBG("create row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
+
+ ?DBG("get-next (cntIndex)",[]),
+ gn([[cntIndex]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
+ expect(3, [{[cntCnt,Idx1], 0}])),
+ % Delete the rows
+ ?DBG("delete row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
+ ?DBG("delete row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
+ catch snmpa:verbosity(MA,log),
+ ?DBG("done",[]),
+ ok.
+
+%% Req. Test1
+opaque_test() ->
+ p("Testing Opaque datatype..."),
+ g([[opaqueObj,0]]),
+ ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
+
+%% Req. OLD-SNMPEA-MIB
+api_test(MaNode) ->
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [intAgentIpAddress]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
+ oid_to_name, [OID]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [[1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp,
+ int_to_enum, ['RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
+ ?line case snmp:date_and_time() of
+ List when list(List), length(List) == 8 -> ok;
+ List when list(List), length(List) == 11 -> ok
+ end.
+
+%% Req. Klas3
+api_test2() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]),
+ g([[fname4,0]]),
+ ?line expect(2, [{[fname4,0], 1}]).
+
+api_test3() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]).
+
+
+unreg_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[snmpInPkts, 0], any}]).
+
+load_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[fname,0], ""}]).
+
+%% Req. Klas1
+load_test_sa() ->
+ gn([[?v1_2(sysServices,sysORLastChange), 0]]),
+ ?line expect(1, [{[fname,0], any}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_get() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
+ [sysName,0]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,0], "test"}]),
+ g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
+ ?line ?v1_2(expect(2, noSuchName, [1,4], any),
+ expect(2, [{[1,3,7,1], noSuchObject},
+ {Key1c4, 2},
+ {[sysDescr,0], "Erlang SNMP agent"},
+ {[1,3,7,2], noSuchObject},
+ {Key1c3, 2},
+ {[sysDescr,0], "Erlang SNMP agent"}])).
+
+%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
+do_mul_get_err() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
+ ?line ?v1_2(expect(1, noSuchName, 5, any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,2], noSuchInstance}])),
+ g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname3,0], noSuchObject},
+ {Key1c3, 2},
+ {[sysName,1], noSuchInstance}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2}, {[fname,0], "test set"},
+ {Key1c3, 2}, {[sysName,0], "test"}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next_err() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[1,3,6,999], endOfMibView},
+ {[fname,0], "test set"},
+ {[1,3,90], endOfMibView},
+ {Key1c3, 2},
+ {[sysName,0], "test"}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set() ->
+ p("Adding one row in subagent table, and one in master table"),
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [sysLocation,0],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[sysLocation,0], "new_value"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ g([NewKeyc4]),
+ ?line expect(3, [{NewKeyc4, 2}]),
+ s([{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]),
+ ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ p("Adding one row in subagent table, and one in master table"),
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {NewKeyc3, 2},
+ {[sysUpTime,0], 45}, % sysUpTime (readOnly)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
+ g([[friendsEntry, [2, 3]]]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB
+sa_mib() ->
+ g([[sa, [2,0]]]),
+ ?line expect(1, [{[sa, [2,0]], 3}]),
+ s([{[sa, [1,0]], s, "sa_test"}]),
+ ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+
+ma_trap1(MA) ->
+ snmpa:send_trap(MA, testTrap2, "standard trap"),
+ ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ snmpa:send_trap(MA, testTrap1, "standard trap"),
+ ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]).
+
+ma_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap2(MA) ->
+ snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
+ {ifAdminStatus, [1], 1},
+ {ifOperStatus, [1], 2}]),
+ ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]).
+
+sa_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "pelle"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]).
+
+ma_v2_trap1(MA) ->
+ ?DBG("ma_v2_traps -> entry with MA = ~p => "
+ "send standard trap: testTrapv22",[MA]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
+ snmpa:send_trap(MA, testTrapv21, "standard trap"),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmp ++ [1]}]).
+
+ma_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"}]).
+
+%% Note: This test case takes a while... actually a couple of minutes.
+ma_v2_inform1(MA) ->
+ ?DBG("ma_v2_inform -> entry with MA = ~p => "
+ "send notification: testTrapv22",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag1, self()},
+ "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag1, [_]} ->
+ ok;
+ {snmp_targets, tag1, Addrs1} ->
+ ?line ?FAIL({bad_addrs, Addrs1})
+ after
+ 5000 ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag1, {got_response, _}} ->
+ ok;
+ {snmp_notification, tag1, {no_response, _}} ->
+ ?line ?FAIL(no_response)
+ after
+ 20000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+
+ %%
+ %% -- The rest is possibly erroneous...
+ %%
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag2, self()},
+ "standard inform", []),
+ ?line expect(2, {inform, false},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag2, [_]} ->
+ ok;
+ {snmp_targets, tag2, Addrs2} ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
+ ?line ?FAIL({bad_addrs, Addrs2})
+ after
+ 5000 ->
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag2, {got_response, _}} ->
+ ?line ?FAIL(got_response);
+ {snmp_notification, tag2, {no_response, _}} ->
+ ok
+ after
+ 240000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag2) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end.
+
+
+ma_v1_2_v2_trap(MA) ->
+ snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
+ {[ifIndex, 1], 1},
+ {[snmpTrapEnterprise, 0], [1,2,3]}]).
+
+
+ma_v1_2_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"},
+ {[snmpTrapEnterprise, 0], ?system}]).
+
+
+sa_v1_2_v2_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+sa_v1_2_v2_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+sa_v1_2_v2_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_bad_value() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 5}, % badValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, badValue, 2, any),
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_gen_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},{NewKeyc4, 2},
+ {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
+ ?line expect(1, genErr, 4, any),
+% The row might have been added; we don't know.
+% (as a matter of fact we do - it is added, because the agent
+% first sets its own vars, and then th SAs. Lets destroy it.
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(2, [{NewKeyc5, ?destroy}]).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_too_big() ->
+ g([[sa, [4,0]]]),
+ ?line expect(1, tooBig).
+
+%% Req. Klas1, system group, snmp group (v1/v2)
+next_across_sa() ->
+ gn([[sysDescr],[klas1,5]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[snmpInPkts, 0], any}]).
+
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
+%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
+%% Req. Klas3, Klas4
+undo_test() ->
+ s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
+ s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
+ ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
+% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+% it depends on which order the agent traverses the varbind list.
+% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
+% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
+ ?line expect(6, genErr, 2, any).
+
+%% Req. Klas3, Klas4
+bad_return() ->
+ g([[fStatus4,4],
+ [fName4,4]]),
+ ?line expect(4, genErr, 2, any),
+ g([[fStatus4,5],
+ [fName4,5]]),
+ ?line expect(5, genErr, 1, any),
+ g([[fStatus4,6],
+ [fName4,6]]),
+ ?line expect(6, genErr, 2, any),
+ gn([[fStatus4,7],
+ [fName4,7]]),
+ ?line expect(7, genErr, 2, any),
+ gn([[fStatus4,8],
+ [fName4,8]]),
+ ?line expect(8, genErr, 1, any),
+ gn([[fStatus4,9],
+ [fName4,9]]),
+ ?line expect(9, genErr, 2, any).
+
+
+%%%-----------------------------------------------------------------
+%%% Test the implementation of standard mibs.
+%%% We should *at least* try to GET all variables, just to make
+%%% sure the instrumentation functions work.
+%%% Note that many of the functions in the standard mib is
+%%% already tested by the normal tests.
+%%%-----------------------------------------------------------------
+standard_mibs(suite) ->
+ [snmp_standard_mib, snmp_community_mib,
+ snmp_framework_mib,
+ snmp_target_mib, snmp_notification_mib,
+ snmp_view_based_acm_mib].
+
+standard_mibs_2(suite) ->
+ [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(suite) ->
+ [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].
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v1.
+%% o Test the counters and control objects in SNMP-STANDARD-MIB
+%%-----------------------------------------------------------------
+snmp_standard_mib(suite) -> [];
+snmp_standard_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?DBG("snmp_standard_mib -> std_mib_init", []),
+ try_test(std_mib_init),
+
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v2),
+ ?DBG("snmp_standard_mib -> std_mib_read", []),
+ try_test(std_mib_read),
+ put(vsn, v1),
+
+ ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+ ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+ ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
+ try_test(std_mib_write, [], [{community, "public"}]),
+ ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
+ try_test(std_mib_asn_err),
+ ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
+ try_test(std_mib_c, [Bad]),
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ try_test(standard_mib_a),
+
+ ?DBG("snmp_standard_mib -> std_mib_finish", []),
+ try_test(std_mib_finish),
+ ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
+ try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_a() ->
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ ?line OutPkts2 = OutPkts + 1,
+ %% There are some more counters we could test here, but it's not that
+ %% important, since they are removed from SNMPv2-MIB.
+ ok.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_init() ->
+ %% disable authentication failure traps. (otherwise w'd get many of
+ %% them - this is also a test to see that it works).
+ s([{[snmpEnableAuthenTraps,0], 2}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_finish() ->
+ %% enable again
+ s([{[snmpEnableAuthenTraps,0], 1}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_test_finish() ->
+ %% force a authenticationFailure
+ std_mib_write(),
+ %% check that we got a trap
+ ?line expect(2, trap, [1,2,3], 4, 0, []).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_read() ->
+ ?DBG("std_mib_read -> entry", []),
+ g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
+ ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
+ ?line expect(1, timeout). % make sure we don't get a trap!
+
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_write() ->
+ ?DBG("std_mib_write -> entry", []),
+ s([{[sysLocation, 0], "new_value"}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_asn_err() ->
+ snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v2 and v3.
+%% o Test the counters and control objects in SNMPv2-MIB
+%%-----------------------------------------------------------------
+snmpv2_mib_2(suite) -> [];
+snmpv2_mib_2(Config) when list(Config) ->
+ ?LOG("snmpv2_mib_2 -> start",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?DBG("snmpv2_mib_2 -> standard mib init",[]),
+ try_test(std_mib_init),
+
+ ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
+ InBadVsns = try_test(std_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
+ put(vsn, v1),
+ try_test(std_mib_read),
+
+ ?DBG("snmpv2_mib_2 -> bad version read",[]),
+ put(vsn, v2),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+
+ ?DBG("snmpv2_mib_2 -> read with bad community",[]),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+
+ ?DBG("snmpv2_mib_2 -> write with public community",[]),
+ try_test(std_mib_write, [], [{community, "public"}]),
+
+ ?DBG("snmpv2_mib_2 -> asn err",[]),
+ try_test(std_mib_asn_err),
+
+ ?DBG("snmpv2_mib_2 -> check counters",[]),
+ try_test(std_mib_c, [Bad]),
+
+ ?DBG("snmpv2_mib_2 -> get som counters",[]),
+ try_test(snmpv2_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
+ try_test(std_mib_finish),
+
+ ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
+ "then disable auth traps",[]),
+ try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
+
+ ?LOG("snmpv2_mib_2 -> done",[]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_3(suite) -> [];
+snmpv2_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v1),
+ try_test(std_mib_read),
+ put(vsn, v3),
+ _Bad = try_test(std_mib_b, [InBadVsns]),
+ try_test(snmpv2_mib_a),
+
+ try_test(std_mib_finish).
+
+-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_test_finish() ->
+ %% force a authenticationFailure
+ ?DBG("ma_v2_inform -> write to std mib",[]),
+ std_mib_write(),
+
+ %% check that we got a trap
+ ?DBG("ma_v2_inform -> await trap",[]),
+ ?line expect(2, v2trap, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0], ?authenticationFailure}]),
+
+ %% and the the inform
+ ?DBG("ma_v2_inform -> await inform",[]),
+ ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0],?authenticationFailure}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_a() ->
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+
+ ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ InBadVsns.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_b(InBadVsns) ->
+ ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ ?line InBadVsns2 = InBadVsns + 1,
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+ ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
+ get_req(4, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
+ ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ get_req(1, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ ?line InBadCommunityNames2 = InBadCommunityNames + 1,
+ ?line InBadCommunityUses2 = InBadCommunityUses + 1,
+ ?line InASNErrs2 = InASNErrs + 1.
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_a() ->
+ ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
+ s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
+ ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
+ {[sysLocation, 0], "val2"}]),
+ s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
+ ?line expect(4, inconsistentValue, 2,
+ [{[sysLocation, 0], "val3"},
+ {[snmpSetSerialNo,0], SetSerial}]),
+ ?line ["val2"] = get_req(5, [[sysLocation,0]]).
+
+
+%%-----------------------------------------------------------------
+%% o Bad community uses/name is tested already
+%% in SNMPv2-MIB and STANDARD-MIB.
+%% o Test add/deletion of rows.
+%%-----------------------------------------------------------------
+snmp_community_mib(suite) -> [];
+snmp_community_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ try_test(snmp_community_mib),
+ ?line unload_master("SNMP-COMMUNITY-MIB").
+
+snmp_community_mib_2(X) -> snmp_community_mib(X).
+
+%% Req. SNMP-COMMUNITY-MIB
+snmp_community_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o Test engine boots / time
+%%-----------------------------------------------------------------
+snmp_framework_mib(suite) -> [];
+snmp_framework_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ try_test(snmp_framework_mib),
+ ?line unload_master("SNMP-FRAMEWORK-MIB").
+
+snmp_framework_mib_2(X) -> snmp_framework_mib(X).
+
+snmp_framework_mib_3(suite) -> [];
+snmp_framework_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(snmp_framework_mib).
+
+
+%% Req. SNMP-FRAMEWORK-MIB
+snmp_framework_mib() ->
+ ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ sleep(5000),
+ ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ if
+ EngineTime+7 < EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ EngineTime+4 > EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ true -> ok
+ end,
+ ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ [Boots] when integer(Boots) -> ok;
+ Else -> ?FAIL(Else)
+ end,
+ ok.
+
+%%-----------------------------------------------------------------
+%% o Test the counters
+%%-----------------------------------------------------------------
+snmp_mpd_mib_3(suite) -> [];
+snmp_mpd_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ UnknownPDUHs = try_test(snmp_mpd_mib_a),
+ try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
+ try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
+
+
+%% Req. SNMP-MPD-MIB
+snmp_mpd_mib_a() ->
+ ?line [UnknownSecs, InvalidMsgs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0]]),
+ Pdu = #pdu{type = 'get-request',
+ request_id = 23,
+ error_status = noError,
+ error_index = 0,
+ varbinds = []},
+ SPdu = #scopedPdu{contextEngineID = "agentEngine",
+ contextName = "",
+ data = Pdu},
+ ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
+ V3Hdr1 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [7],
+ msgSecurityModel = 23, % bad sec model
+ msgSecurityParameters = []},
+ V3Hdr2 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [6], % bad flag combination
+ msgSecurityModel = 3,
+ msgSecurityParameters = []},
+ Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
+ data = SPDUBytes},
+ Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
+ data = SPDUBytes},
+ ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
+ ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
+ snmp_test_mgr:send_bytes(MsgBytes1),
+ snmp_test_mgr:send_bytes(MsgBytes2),
+
+ ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0],
+ [snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownSecs2 = UnknownSecs + 1,
+ ?line InvalidMsgs2 = InvalidMsgs + 1,
+ UnknownPDUHs.
+
+-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
+snmp_mpd_mib_b() ->
+ g([[sysUpTime,0]]),
+ ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
+
+
+snmp_mpd_mib_c(UnknownPDUHs) ->
+ ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownPDUHs2 = UnknownPDUHs + 1.
+
+
+snmp_target_mib(suite) -> [];
+snmp_target_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ try_test(snmp_target_mib),
+ ?line unload_master("SNMP-TARGET-MIB").
+
+snmp_target_mib_2(X) -> snmp_target_mib(X).
+
+snmp_target_mib_3(X) -> snmp_target_mib(X).
+
+snmp_target_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+snmp_notification_mib(suite) -> [];
+snmp_notification_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ try_test(snmp_notification_mib),
+ ?line unload_master("SNMP-NOTIFICATION-MIB").
+
+snmp_notification_mib_2(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib_3(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o add/delete views and try them
+%% o try boundaries
+%%-----------------------------------------------------------------
+snmp_view_based_acm_mib(suite) -> [];
+snmp_view_based_acm_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master("Test2"),
+ snmp_view_based_acm_mib(),
+ ?line unload_master("Test2"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib() ->
+ snmpa:verbosity(net_if,trace),
+ snmpa:verbosity(master_agent,trace),
+ ?LOG("start snmp_view_based_acm_mib test",[]),
+ %% The user "no-rights" is present in USM, and is mapped to security
+ %% name 'no-rights", which is not present in VACM.
+ %% So, we'll add rights for it, try them and delete them.
+ %% We'll give "no-rights" write access to tDescr.0 and read access
+ %% to tDescr2.0
+ %% These are the options we'll use to the mgr
+ Opts = [{user, "no-rights"}, {community, "no-rights"}],
+ %% Find the valid secmodel, and one invalid secmodel.
+ {SecMod, InvSecMod} =
+ case get(vsn) of
+ v1 -> {?SEC_V1, ?SEC_V2C};
+ v2 -> {?SEC_V2C, ?SEC_USM};
+ v3 -> {?SEC_USM, ?SEC_V1}
+ end,
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Now, add a mapping from "no-rights" -> "no-rights-group"
+ GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
+ GRow1 =
+ [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
+ {GRow1Status, ?createAndGo}],
+ ?DBG("set '~p'",[GRow1]),
+ ?line try_test(do_set, [GRow1]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create a mapping for another sec model, and make sure it dosn't
+ %% give us access
+ GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
+ GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
+ {GRow2Status, ?createAndGo}],
+
+ ?DBG("set '~p'",[GRow2]),
+ ?line try_test(do_set, [GRow2]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [GRow2Status]),
+
+ RVName = "rv_name",
+ WVName = "wv_name",
+
+ %% Access row
+ ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
+ ARow1Status = [vacmAccessStatus, ARow1Idx],
+ ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
+ {[vacmAccessReadViewName, ARow1Idx], RVName},
+ {[vacmAccessWriteViewName, ARow1Idx], WVName},
+ {ARow1Status, ?createAndGo}],
+
+ %% This access row would give acces, if InvSecMod was valid.
+ ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
+ ARow2Status = [vacmAccessStatus, ARow2Idx],
+ ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
+ {[vacmAccessReadViewName, ARow2Idx], "internet"},
+ {[vacmAccessWriteViewName, ARow2Idx], "internet"},
+ {ARow2Status, ?createAndGo}],
+
+ ?line try_test(do_set, [ARow2]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [ARow2Status]),
+
+
+ %% Add valid row
+ ?line try_test(do_set, [ARow1]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create the view family
+ VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
+ VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
+ VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
+ VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
+ VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
+ VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
+ VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
+ VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
+
+ ?line try_test(add_row, [VRow1Status]),
+ ?line try_test(add_row, [VRow2Status]),
+ ?line try_test(add_row, [VRow3Status]),
+
+ %% We're supposed to have access now...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Change Row3 to Row4
+ ?line try_test(del_row, [VRow3Status]),
+ ?line try_test(add_row, [VRow4Status]),
+
+ %% We should still have access...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Delete rows
+ ?line try_test(del_row, [GRow1Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete rest of rows
+ ?line try_test(del_row, [ARow1Status]),
+ ?line try_test(del_row, [VRow1Status]),
+ ?line try_test(del_row, [VRow2Status]),
+ ?line try_test(del_row, [VRow4Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+ snmpa:verbosity(master_agent,log).
+
+do_set(Row) ->
+ s(Row),
+ expect(1, Row).
+
+add_row(RowStatus) ->
+ s([{RowStatus, ?createAndGo}]),
+ expect(1, [{RowStatus, ?createAndGo}]).
+
+del_row(RowStatus) ->
+ s([{RowStatus, ?destroy}]),
+ expect(1, [{RowStatus, ?destroy}]).
+
+
+
+use_no_rights() ->
+ g([[xDescr,0]]),
+ ?v1_2_3(expect(11, noSuchName, 1, any),
+ expect(12, [{[xDescr,0], noSuchObject}]),
+ expect(13, authorizationError, 1, any)),
+ g([[xDescr2,0]]),
+ ?v1_2_3(expect(21, noSuchName, 1, any),
+ expect(22, [{[xDescr2,0], noSuchObject}]),
+ expect(23, authorizationError, 1, any)),
+ gn([[xDescr]]),
+ ?v1_2_3(expect(31, noSuchName, 1, any),
+ expect(32, [{[xDescr], endOfMibView}]),
+ expect(33, authorizationError, 1, any)),
+ s([{[xDescr,0], "tryit"}]),
+ ?v1_2_3(expect(41, noSuchName, 1, any),
+ expect(42, noAccess, 1, any),
+ expect(43, authorizationError, 1, any)).
+
+
+use_rights() ->
+ g([[xDescr,0]]),
+ expect(1, [{[xDescr,0], any}]),
+ g([[xDescr2,0]]),
+ expect(2, [{[xDescr2,0], any}]),
+ s([{[xDescr,0], "tryit"}]),
+ expect(3, noError, 0, any),
+ g([[xDescr,0]]),
+ expect(4, [{[xDescr,0], "tryit"}]).
+
+mk_ln(X) ->
+ [length(X) | X].
+
+%%-----------------------------------------------------------------
+%% o add/delete users and try them
+%% o test all secLevels
+%% o test all combinations of protocols
+%% o try bad ops; check counters
+%%-----------------------------------------------------------------
+snmp_user_based_sm_mib_3(suite) -> [];
+snmp_user_based_sm_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ _AgentDir = ?config(agent_dir, Config),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+
+ %% The newUser used here already has VACM access.
+
+ %% Add a new user in the simplest way; just createAndGo
+ try_test(v3_sync, [[{usm_add_user1, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new user
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
+ DesKey1 = lists:sublist(ShaKey1, 16),
+
+ %% Change the new user's keys - 1
+ try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ MgrDir = ?config(mgr_dir, Config),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
+ DesKey2 = lists:sublist(ShaKey2, 16),
+
+ %% Change the new user's keys - 2
+ ?line try_test(v3_sync,
+ [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ reset_usm_mgr(MgrDir),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
+ ?line load_master("Test2"),
+ ?line try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Change the new user's keys - 3
+ ?line try_test(v3_sync,
+ [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new keys
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Try some read requests
+ ?line try_test(v3_sync, [[{usm_read, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Delete the new user
+ ?line try_test(v3_sync, [[{usm_del_user, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try some bad requests
+ ?line try_test(v3_sync, [[{usm_bad, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("SNMP-USER-BASED-SM-MIB").
+
+-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
+
+usm_add_user1() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+usm_use_user() ->
+ v2_proc().
+
+
+%% Change own public keys
+usm_key_change1(ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_shaxxxxxxxxxx",
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_desxxxxxx",
+ DesKey),
+ Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change own private keys
+usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change other's public keys
+usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
+ s(Vbs1),
+ ?line expect(1, noAccess, 1, any),
+ Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs2),
+ ?line expect(2, noAccess, 1, any),
+
+
+ Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs3),
+ ?line expect(1, Vbs3).
+
+usm_read() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ?line g([[usmUserSecurityName, NewRowIndex],
+ [usmUserCloneFrom, NewRowIndex],
+ [usmUserAuthKeyChange, NewRowIndex],
+ [usmUserOwnAuthKeyChange, NewRowIndex],
+ [usmUserPrivKeyChange, NewRowIndex],
+ [usmUserOwnPrivKeyChange, NewRowIndex]]),
+ ?line expect(1,
+ [{[usmUserSecurityName, NewRowIndex], "newUser"},
+ {[usmUserCloneFrom, NewRowIndex], [0,0]},
+ {[usmUserAuthKeyChange, NewRowIndex], ""},
+ {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
+ {[usmUserPrivKeyChange, NewRowIndex], ""},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
+ ok.
+
+
+
+usm_del_user() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
+
+-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
+
+-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
+
+-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
+
+-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
+
+-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
+
+usm_bad() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, inconsistentName, 1, any),
+
+ RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs2),
+ ?line expect(2, wrongValue, 1, any),
+
+ RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs3),
+ ?line expect(3, Vbs3),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
+ ?line expect(4, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
+ ?line expect(5, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
+ ?line expect(6, wrongValue, 1, any),
+ ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
+ ?line expect(7, wrongValue, 1, any),
+
+ Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs4),
+ ?line expect(1, Vbs4),
+
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Loop through entire MIB, to make sure that all instrum. funcs
+%% works.
+%% Load all std mibs that are not loaded by default.
+%%-----------------------------------------------------------------
+loop_mib(suite) -> [];
+loop_mib(Config) when list(Config) ->
+ ?LOG("loop_mib -> initiate case",[]),
+ %% snmpa:verbosity(master_agent,debug),
+ %% snmpa:verbosity(mib_server,info),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?DBG("loop_mib -> try",[]),
+ try_test(loop_mib_1),
+ ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ %% snmpa:verbosity(master_agent,log),
+ %% snmpa:verbosity(mib_server,silence),
+ ?LOG("loop_mib -> done",[]).
+
+
+loop_mib_2(suite) -> [];
+loop_mib_2(Config) when list(Config) ->
+ ?LOG("loop_mib_2 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_2 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_2 -> load mibs",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_2 -> unload mibs",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?LOG("loop_mib_2 -> done",[]).
+
+
+loop_mib_3(suite) -> [];
+loop_mib_3(Config) when list(Config) ->
+ ?LOG("loop_mib_3 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_3 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_3 -> load mibs",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_3 -> unload mibs",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?LOG("loop_mib_3 -> done",[]).
+
+
+%% Req. As many mibs all possible
+loop_mib_1() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_1([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_1(Oid, N) ->
+ ?DBG("loop_it_1 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_1 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_1 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_1(NOid, N+1);
+ #pdu{type='get-response', error_status=noSuchName, error_index=1,
+ varbinds=[_]} ->
+ ?DBG("loop_it_1 -> done",[]),
+ N;
+
+ #pdu{type = Type, error_status = Err, error_index = Idx,
+ varbinds = Vbs} ->
+ exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
+ end.
+
+%% Req. As many mibs all possible
+loop_mib_2() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_2([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_2(Oid, N) ->
+ ?DBG("loop_it_2 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p",[NOid]),
+ N;
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_2 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_2(NOid, N+1)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+reported_bugs(suite) ->
+ [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(suite) ->
+ [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(suite) ->
+ [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].
+
+
+%% These are (ticket) test cases where the initiation has to be done
+%% individually.
+tickets(suite) ->
+ [otp_4394].
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1128
+%% Slogan: Bug in handling of createAndWait set-requests.
+%%-----------------------------------------------------------------
+otp_1128(suite) -> [];
+otp_1128(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1128),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1128_2(X) -> otp_1128(X).
+
+otp_1128_3(X) -> otp_1128(X).
+
+otp_1128() ->
+ io:format("Testing bug reported in ticket OTP-1128...~n"),
+
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+
+ s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(29, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(31, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(32, [{NewKeyc5, ?destroy}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1129, OTP-1169
+%% Slogan: snmpa:int_to_enum crashes on bad oids
+%%-----------------------------------------------------------------
+otp_1129(suite) -> [];
+otp_1129(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ try_test(otp_1129_i, [node()]),
+ ?line unload_master("Klas3").
+
+otp_1129_2(X) -> otp_1129(X).
+
+otp_1129_3(X) -> otp_1129(X).
+
+otp_1129_i(MaNode) ->
+ io:format("Testing bug reported in ticket OTP-1129...~n"),
+ false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
+ false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1131
+%% Slogan: Agent crashes / erlang node halts if RowIndex in a
+%% setrequest is of bad type, e.g. an INDEX {INTEGER},
+%% and RowIdenx [3,2].
+%%-----------------------------------------------------------------
+otp_1131(suite) -> [];
+otp_1131(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas1"),
+ try_test(otp_1131),
+ ?line unload_master("Klas1").
+
+otp_1131_2(X) -> otp_1131(X).
+
+otp_1131_3(X) -> otp_1131(X).
+
+otp_1131() ->
+ io:format("Testing bug reported in ticket OTP-1131...~n"),
+ s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
+ {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1162
+%% Slogan: snmp_agent can't handle wrongValue from instrum.func
+%%-----------------------------------------------------------------
+otp_1162(suite) -> [];
+otp_1162(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ try_test(otp_1162),
+ stop_subagent(SA).
+
+otp_1162_2(X) -> otp_1162(X).
+
+otp_1162_3(X) -> otp_1162(X).
+
+otp_1162() ->
+ s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
+ ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1222
+%% Slogan: snmp agent crash if faulty index is returned from instrum
+%%-----------------------------------------------------------------
+otp_1222(suite) -> [];
+otp_1222(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ ?line load_master("Klas4"),
+ try_test(otp_1222),
+ ?line unload_master("Klas3"),
+ ?line unload_master("Klas4").
+
+otp_1222_2(X) -> otp_1222(X).
+
+otp_1222_3(X) -> otp_1222(X).
+
+otp_1222() ->
+ io:format("Testing bug reported in ticket OTP-1222...~n"),
+ s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
+ ?line expect(1, genErr, 0, any),
+ s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
+ ?line expect(2, genErr, 0, any).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1298
+%% Slogan: Negative INTEGER values are treated as positive.
+%%-----------------------------------------------------------------
+otp_1298(suite) -> [];
+otp_1298(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1298),
+ ?line unload_master("Klas2").
+
+otp_1298_2(X) -> otp_1298(X).
+
+otp_1298_3(X) -> otp_1298(X).
+
+otp_1298() ->
+ io:format("Testing bug reported in ticket OTP-1298...~n"),
+ s([{[fint,0], -1}]),
+ ?line expect(1298, [{[fint,0], -1}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1331
+%% Slogan: snmp_generic should return noError when deleting non-ex row
+%%-----------------------------------------------------------------
+otp_1331(suite) -> [];
+otp_1331(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1331),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1331_2(X) -> otp_1331(X).
+
+otp_1331_3(X) -> otp_1331(X).
+
+otp_1331() ->
+ NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(1, [{NewKeyc5, ?destroy}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1338
+%% Slogan: snmp bug in initialisation of default values for mnesia tabs
+%%-----------------------------------------------------------------
+otp_1338(suite) -> [];
+otp_1338(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1338),
+ ?line unload_master("Klas2").
+
+otp_1338_2(X) -> otp_1338(X).
+
+otp_1338_3(X) -> otp_1338(X).
+
+otp_1338() ->
+ s([{[kStatus2, 7], i, ?createAndGo}]),
+ ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
+ g([[kName2, 7]]),
+ ?line expect(2, [{[kName2, 7], "JJJ"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1342
+%% Slogan: default impl of snmp table can't handle bad index access,
+%% Set when INDEX is read-write gets into an infinite loop!
+%%-----------------------------------------------------------------
+otp_1342(suite) -> [];
+otp_1342(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas4"),
+ try_test(otp_1342),
+ ?line unload_master("Klas4").
+
+otp_1342_2(X) -> otp_1342(X).
+
+otp_1342_3(X) -> otp_1342(X).
+
+otp_1342() ->
+ s([{[fIndex5, 1], i, 1},
+ {[fName5, 1], i, 3},
+ {[fStatus5, 1], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1366
+%% Slogan: snmp traps not sent to all managers
+%% Note: NYI! We need a way to tell the test server that we need
+%% mgrs on two different machines.
+%%-----------------------------------------------------------------
+otp_1366(suite) -> [];
+otp_1366(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1366),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1366_2(X) -> otp_1366(X).
+
+otp_1366_3(X) -> otp_1366(X).
+
+otp_1366() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ 'NYI'.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2776
+%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
+%%-----------------------------------------------------------------
+otp_2776(suite) -> [];
+otp_2776(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_2776).
+
+otp_2776_2(X) -> otp_2776(X).
+
+otp_2776_3(X) -> otp_2776(X).
+
+otp_2776() ->
+ io:format("Testing bug reported in ticket OTP-2776...~n"),
+
+ Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
+ Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
+ Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
+ Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
+ Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
+ Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
+ Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
+ Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
+ Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
+ Dt10_invalid = [],
+ Dt11_invalid = [kalle,hobbe],
+ L = [{ 1, true, Dt01_valid},
+ { 2, true, Dt02_valid},
+ { 3, true, Dt03_valid},
+ { 4, false, Dt04_invalid},
+ { 5, true, Dt05_valid},
+ { 6, true, Dt06_valid},
+ { 7, false, Dt07_invalid},
+ { 8, true, Dt08_valid},
+ { 9, false, Dt09_invalid},
+ {10, false, Dt10_invalid},
+ {11, false, Dt11_invalid}],
+
+ ?line ok = validate_dat(L).
+
+
+validate_dat(L) -> validate_dat(L,[]).
+
+validate_dat([],V) ->
+ Fun = fun({_,X}) -> case X of
+ ok -> false;
+ _ -> true
+ end
+ end,
+ validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
+validate_dat([{Id,E,Dat}|T],V) ->
+ validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
+
+validate_dat1([]) -> ok;
+validate_dat1(L) -> {error,L}.
+
+validate_dat2(Id, E, Dat) ->
+ Res = case {E,snmp:validate_date_and_time(Dat)} of
+ {E,E} -> ok;
+ {E,A} -> {E,A}
+ end,
+ {Id, Res}.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2979
+%% Slogan: get-next on more than 1 column in an empty table
+%% returns bad response.
+%%-----------------------------------------------------------------
+otp_2979(suite) -> [];
+otp_2979(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Test1"),
+ ?line init_old(),
+ try_test(otp_2979),
+ ?line unload_master("Test1").
+
+otp_2979_2(X) -> otp_2979(X).
+
+otp_2979_3(X) -> otp_2979(X).
+
+otp_2979() ->
+ gn([[sparseDescr], [sparseStatus]]),
+ ?line expect(1, [{[sparseStr,0], "slut"},
+ {[sparseStr,0], "slut"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3187
+%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% endOfTable - should return value.
+%%-----------------------------------------------------------------
+otp_3187(suite) -> [];
+otp_3187(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ otp_3187(),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+otp_3187_2(X) -> otp_3187(X).
+
+otp_3187_3(X) -> otp_3187(X).
+
+otp_3187() ->
+ ?line Elements =
+ snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
+ lists:foreach(fun(E) ->
+ ?line if E == endOfTable ->
+ ?FAIL(endOfTable);
+ true -> ok
+ end
+ end, Elements).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3542
+%% Slogan:
+%%-----------------------------------------------------------------
+otp_3542(suite) -> [];
+otp_3542(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_3542).
+
+otp_3542() ->
+ io:format("SNMP v3 discovery...~n"),
+ ?line Res = snmp_test_mgr:d(),
+ io:format("SNMP v3 discovery result: ~p~n",[Res]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3725
+%% Slogan: Slow response time on snmpa:int_to_enum
+%%-----------------------------------------------------------------
+otp_3725(suite) -> [];
+otp_3725(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_3725_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+otp_3725_test(MaNode) ->
+ io:format("Testing feature requested in ticket OTP-3725...~n"),
+ ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
+ ?DBG("otp_3725_test -> Db = ~p",[Db]),
+
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [Db, intAgentIpAddress]),
+ ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
+ [Db,OID]),
+ ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [Db, [1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, 'RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-4394
+%% Slogan: Target mib tag list check invalid
+%%-----------------------------------------------------------------
+
+
+otp_4394(suite) -> {req, [], {conf,
+ init_otp_4394,
+ [otp_4394_test],
+ finish_otp_4394}}.
+
+init_otp_4394(Config) when list(Config) ->
+ ?DBG("init_otp_4394 -> entry with"
+ "~n Config: ~p", [Config]),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ MasterAgentVerbosity = {master_agent_verbosity, trace},
+ NetIfVerbosity = {net_if_verbosity, trace},
+ Opts = [MasterAgentVerbosity,NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config,Opts)].
+
+otp_4394_config(AgentDir, MgrDir, Ip0) ->
+ ?DBG("otp_4394_config -> entry with"
+ "~n AgentDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ Vsn = [v1],
+ Ip = tuple_to_list(Ip0),
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?TRAP_UDP, Ip, 4000,
+ "OTP-4394 test"),
+ ?line case update_usm(Vsn, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsn, MgrDir);
+ false ->
+ ?line ok
+ end,
+ C1 = {"a", "all-rights", "initial", "", "pc"},
+ C2 = {"c", "secret", "secret_name", "", "secret_tag"},
+ ?line write_community_conf(AgentDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentDir),
+ Ta1 = {"shelob v1",
+ [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ "pc1",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [],
+ 2048},
+ Ta2 = {"bifur v1",
+ [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ "pc2",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [], 2048},
+ ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentDir, Vsn),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+
+
+finish_otp_4394(Config) when list(Config) ->
+ ?DBG("finish_otp_4394 -> entry", []),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ erase(mgr_node),
+ lists:keydelete(vsn, 1, C1).
+
+otp_4394_test(suite) -> [];
+otp_4394_test(Config) ->
+ ?DBG("otp_4394_test -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_4394_test1),
+ ?DBG("otp_4394_test -> done", []),
+ ok.
+
+otp_4394_test1() ->
+ ?DBG("otp_4394_test1 -> entry", []),
+ gn([[1,1]]),
+ Res =
+ case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
+ %% {error, 1, {"?",[]}, {"~w",[timeout]}}
+ {error, 1, _, {_, [timeout]}} ->
+ ?DBG("otp_4394_test1 -> expected result: timeout", []),
+ ok;
+ Else ->
+ Else
+ end,
+ ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
+ Res.
+
+
+%%%--------------------------------------------------
+%%% Used to test the standard mib with our
+%%% configuration.
+%%%--------------------------------------------------
+run(F, A, Opts) ->
+ M = get(mib_dir),
+ Dir = get(mgr_dir),
+ User = snmp_misc:get_option(user, Opts, "all-rights"),
+ SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
+ EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
+ CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
+ Community = snmp_misc:get_option(community, Opts, "all-rights"),
+ ?DBG("run -> start crypto app",[]),
+ Crypto = case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ ?CRYPTO_START()
+ end,
+ ?DBG("run -> Crypto: ~p",[Crypto]),
+ catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ ?DBG("run -> config:~n"
+ "\tM: ~p~n"
+ "\tDir: ~p~n"
+ "\tUser: ~p~n"
+ "\tSecLevel: ~p~n"
+ "\tEngineID: ~p~n"
+ "\tCtxEngineID: ~p~n"
+ "\tCommunity: ~p~n"
+ "\tStdM: ~p",
+ [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
+ case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
+ {packet_server_debug,true},
+ {debug,true},
+ {agent, get(master_host)},
+ {agent_udp, 4000},
+ {trap_udp, 5000},
+ {recbuf,65535},
+ quiet,
+ get(vsn),
+ {community, Community},
+ {user, User},
+ {sec_level, SecLevel},
+ {engine_id, EngineID},
+ {context_engine_id, CtxEngineID},
+ {dir, Dir},
+ {mibs, mibs(StdM, M)}]) of
+ {ok, _Pid} ->
+ Res = apply(?MODULE, F, A),
+ catch snmp_test_mgr:stop(),
+ Res;
+ Err ->
+ io:format("Error starting manager: ~p\n", [Err]),
+ catch snmp_test_mgr:stop(),
+ ?line exit({mgr_start, Err})
+ end.
+
+
+mibs(StdMibDir,MibDir) ->
+ [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
+ join(MibDir, "OLD-SNMPEA-MIB.bin"),
+ join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
+ join(StdMibDir, "SNMP-MPD-MIB"),
+ join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
+ join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
+ join(StdMibDir, "SNMP-TARGET-MIB"),
+ join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
+ join(MibDir, "Klas1.bin"),
+ join(MibDir, "Klas2.bin"),
+ join(MibDir, "Klas3.bin"),
+ join(MibDir, "Klas4.bin"),
+ join(MibDir, "SA-MIB.bin"),
+ join(MibDir, "TestTrap.bin"),
+ join(MibDir, "Test1.bin"),
+ join(MibDir, "Test2.bin"),
+ join(MibDir, "TestTrapv2.bin")].
+
+join(D,F) ->
+ filename:join(D,F).
+
+%% string used in index
+is(S) -> [length(S) | S].
+
+try_test(Func) ->
+ call(get(mgr_node), ?MODULE, run, [Func, [], []]).
+
+try_test(Func, A) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, []]).
+
+try_test(Func, A, Opts) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
+
+call(N,M,F,A) ->
+ ?DBG("call -> entry with~n"
+ " N: ~p~n"
+ " M: ~p~n"
+ " F: ~p~n"
+ " A: ~p~n"
+ " when~n"
+ " get(): ~p",
+ [N,M,F,A,get()]),
+ spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
+ receive
+ {done, {'EXIT', Rn}, Loc} ->
+ ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
+ put(test_server_loc, Loc),
+ exit(Rn);
+ {done, Ret, Zed} ->
+ ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
+ Ret
+ end.
+
+wait(From, Env, M, F, A) ->
+ ?DBG("wait -> entry with ~n"
+ "\tFrom: ~p~n"
+ "\tEnv: ~p",[From,Env]),
+ lists:foreach(fun({K,V}) -> put(K,V) end, Env),
+ Rn = (catch apply(M, F, A)),
+ ?DBG("wait -> Rn: ~n~p", [Rn]),
+ From ! {done, Rn, get(test_server_loc)},
+ exit(Rn).
+
+expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
+expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
+expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
+expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
+
+get_req(Id, Vars) ->
+ ?DBG("get_req -> entry with~n"
+ "\tId: ~p~n"
+ "\tVars: ~p",[Id,Vars]),
+ g(Vars),
+ ?DBG("get_req -> await response",[]),
+ {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
+ ?DBG("get_req -> response: ~p",[Val]),
+ Val.
+
+get_next_req(Vars) ->
+ ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
+ gn(Vars),
+ ?DBG("get_next_req -> await response",[]),
+ Response = snmp_test_mgr:receive_response(),
+ ?DBG("get_next_req -> response: ~p",[Response]),
+ Response.
+
+
+
+start_node(Name) ->
+ ?LOG("start_node -> entry with Name: ~p",[Name]),
+ M = list_to_atom(?HOSTNAME(node())),
+ ?DBG("start_node -> M: ~p",[M]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ ?DBG("start_node -> Pa: ~p",[Pa]),
+
+ Args = case init:get_argument('CC_TEST') of
+ {ok, [[]]} ->
+ " -pa /clearcase/otp/libraries/snmp/ebin ";
+ {ok, [[Path]]} ->
+ " -pa " ++ Path;
+ error ->
+ ""
+ end,
+ %% Do not use start_link!!! (the proc that calls this one is tmp)
+ ?DBG("start_node -> Args: ~p~n",[Args]),
+ A = Args ++ " -pa " ++ Pa,
+ case (catch ?START_NODE(Name, A)) of
+ {ok, Node} ->
+ %% Tell the test_server to not clean up things it never started.
+ ?DBG("start_node -> Node: ~p",[Node]),
+ {ok, Node};
+ Else ->
+ ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
+ ?line ?FAIL(Else)
+ end.
+
+
+stop_node(Node) ->
+ ?LOG("stop_node -> Node: ~p",[Node]),
+ rpc:cast(Node, erlang, halt, []).
+
+p(X) ->
+ io:format(user, X++"\n", []).
+
+sleep(X) ->
+ receive
+ after
+ X -> ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Configuration
+%%%-----------------------------------------------------------------
+config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
+ ?TRAP_UDP, AIp, 4000,
+ "test"),
+ ?line case update_usm(Vsns, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsns, MgrDir);
+ false ->
+ ?line ok
+ end,
+ ?line update_community(Vsns, AgentDir),
+ ?line update_vacm(Vsns, AgentDir),
+ ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentDir, Vsns),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+delete_files(Config) ->
+ Dir = ?config(agent_dir, Config),
+ {ok, List} = file:list_dir(Dir),
+ lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
+ List).
+
+update_usm(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+update_usm_mgr(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.conf"),
+ filename:join(Dir,"usm.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ file:close(Fid).
+
+reset_usm_mgr(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.old"),
+ filename:join(Dir,"usm.conf")).
+
+
+update_community([v3], _Dir) -> ok;
+update_community(_, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
+ []),
+ file:close(Fid).
+
+
+-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
+update_vacm(_Vsn, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
+ ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
+ "~w, excluded, null}.\n", [?tDescr_instance]),
+ file:close(Fid).
+
+
+vacm_ver(v1) -> v1;
+vacm_ver(v2) -> v2c;
+vacm_ver(v3) -> usm.
+
+
+write_community_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
+ ok = write_community_conf1(Fid, Confs),
+ file:close(Fid).
+
+write_community_conf1(_, []) ->
+ ok;
+write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
+ [ComIdx, ComName, SecName, CtxName, TransTag]),
+ write_community_conf1(Fid, Confs).
+
+
+write_target_addr_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ ok = write_target_addr_conf1(Fid, Confs),
+ file:close(Fid).
+
+
+write_target_addr_conf1(_, []) ->
+ ok;
+write_target_addr_conf1(Fid,
+ [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
+ [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz]),
+ write_target_addr_conf1(Fid, Confs).
+
+write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ ok = io:format(Fid,
+ "{\"~s\", ~w, ~w, 1500, 3, "
+ "\"std_trap\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP, mk_param(Vsn)]),
+ case Vsn of
+ v1 -> ok;
+ v2 ->
+ ok = io:format(Fid,
+ "{\"~s.2\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)]);
+ v3 ->
+ ok = io:format(Fid,
+ "{\"~s.3\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\", "
+ "\"mgrEngine\", [], 1024}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)])
+ end
+ end,
+ Vsns),
+ file:close(Fid).
+
+mk_param(v1) -> "target_v1";
+mk_param(v2) -> "target_v2";
+mk_param(v3) -> "target_v3".
+
+mk_ip([A,B,C,D], Vsn) ->
+ io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
+
+
+rewrite_target_addr_conf(Dir,NewPort) ->
+ TAFile = filename:join(Dir, "target_addr.conf"),
+ ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
+ case file:read_file_info(TAFile) of
+ {ok, _} -> ok;
+ {error, R} -> ?ERR("failure reading file info of "
+ "target address config file: ~p",[R]),
+ ok
+ end,
+
+ ?line [TrapAddr|Addrs] =
+ snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
+
+ ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
+
+ NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
+
+ ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
+
+ ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
+ filename:join(Dir,"target_addr.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+
+ ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
+
+ file:close(Fid).
+
+rewrite_target_addr_conf1(O) ->
+ {ok,O}.
+
+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) ->
+ ?LOG("rewrite_target_addr_conf2 -> entry with "
+ "~n O: ~p",[O]),
+ O.
+
+
+rewrite_target_addr_conf3(_,[]) -> ok;
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
+ ParamName,EngineId}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % ParamsName
+ "\"~s\"}.", % EngineId
+ [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
+ rewrite_target_addr_conf3(Fid,T);
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
+ ParamName,EngineId,TMask,MMS}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % TagList
+ "\"~s\", " % ParamsName
+ "\"~s\"," % EngineId
+ "~p, " % TMask
+ "~p}.", % MMS
+ [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
+ EngineId,TMask,MMS]),
+ rewrite_target_addr_conf3(Fid,T).
+
+reset_target_addr_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
+ filename:join(Dir,"target_addr.conf")).
+
+write_target_params_conf(Dir, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ MP = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> v3
+ end,
+ SM = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> usm
+ end,
+ ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
+ "\"all-rights\", noAuthNoPriv}.~n",
+ [Vsn, MP, SM])
+ end,
+ Vsns),
+ file:close(Fid).
+
+rewrite_target_params_conf(Dir, SecName, SecLevel) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
+ filename:join(Dir,"target_params.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
+ [SecName, SecLevel]),
+ file:close(Fid).
+
+reset_target_params_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.old"),
+ filename:join(Dir,"target_params.conf")).
+
+write_notify_conf(Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
+ ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
+ ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
+ file:close(Fid).
+
+ver_to_trap_str([v1]) -> "v1";
+ver_to_trap_str([v2]) -> "v2";
+% default is to use the latest snmp version
+ver_to_trap_str([v1,v2]) -> "v2".
+
+
+
+write_view_conf(Dir) ->
+ {ok, Fid} = file:open(a(Dir,"view.conf"),write),
+ ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
+ ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
+ file:close(Fid).
+
+a(A,B) -> lists:append(A,B).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+copy_file(From, To) ->
+ {ok, Bin} = file:read_file(From),
+ ok = file:write_file(To, Bin).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+display_memory_usage() ->
+ Info = snmpa:info(snmp_master_agent),
+ TreeSize = lists_key1search(tree_size_bytes, Info),
+ ProcMem = lists_key1search(process_memory, Info),
+ MibDbSize = lists_key1search([db_memory,mib], Info),
+ NodeDbSize = lists_key1search([db_memory,node], Info),
+ TreeDbSize = lists_key1search([db_memory,tree], Info),
+ ?INF("Memory usage: "
+ "~n Tree size: ~p"
+ "~n Process memory size: ~p"
+ "~n Mib db size: ~p"
+ "~n Node db size: ~p"
+ "~n Tree db size: ~p",
+ [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
+
+lists_key1search([], Res) ->
+ Res;
+lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ lists_key1search(Keys, Val);
+ false ->
+ undefined
+ end;
+lists_key1search(Key, List) when atom(Key) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ Val;
+ false ->
+ undefined
+ end.
+
+
+regs() ->
+ lists:sort(registered()).
diff --git a/lib/snmp/test/exp/snmp_agent_ms_test.erl b/lib/snmp/test/exp/snmp_agent_ms_test.erl
new file mode 100644
index 0000000000..d5eaea55fa
--- /dev/null
+++ b/lib/snmp/test/exp/snmp_agent_ms_test.erl
@@ -0,0 +1,5649 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmp_agent_ms_test).
+
+%% TODO
+%% * Test fault-tolerance (kill master etc)
+%%
+
+-compile(export_all).
+
+-define(application, snmp).
+
+-include_lib("kernel/include/file.hrl").
+-include_lib("test_server/include/test_server.hrl").
+-include("snmp_test_lib.hrl").
+-define(SNMP_USE_V3, true).
+-include_lib("snmp/include/snmp_types.hrl").
+%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
+
+
+-define(klas1, [1,3,6,1,2,1,7]).
+-define(klas2, [1,3,6,1,2,1,9]).
+-define(klas3, [1,3,6,1,2,1,8,1]).
+-define(klas4, [1,3,6,1,2,1,8,4]).
+-define(sa, [1,3,6,1,4,1,193,2]).
+-define(system, [1,3,6,1,2,1,1]).
+-define(snmp, [1,3,6,1,2,1,11]).
+-define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
+-define(ericsson, [1,3,6,1,4,1,193]).
+-define(testTrap, [1,3,6,1,2,1,15,0]).
+-define(xDescr, [1,3,6,1,2,1,17,1]).
+-define(xDescr2, [1,3,6,1,2,1,17,2]).
+
+-define(active, 1).
+-define(notInService, 2).
+-define(notReady, 3).
+-define(createAndGo, 4).
+-define(createAndWait, 5).
+-define(destroy, 6).
+
+-define(TRAP_UDP, 5000).
+
+-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
+
+-define(str(X), snmp_pdus:bits_to_str(X)).
+
+-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
+ [?LINE, self()]),
+ receive cont -> ok end
+ end).
+
+
+-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
+-define(v1_2(V1,V2),
+ case get(vsn) of
+ v1 -> V1;
+ _ -> V2
+ end).
+
+-define(v1_2_3(V1,V2,V3),
+ case get(vsn) of
+ v1 -> V1;
+ v2 -> V2;
+ _ -> V3
+ end).
+
+all() ->
+[cases()].
+
+groups() ->
+ [{mib_storage, [],
+ [{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()},
+ {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]},
+ {standard_mibs, [],
+ [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]},
+ {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]},
+ {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]},
+ {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]},
+ {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]},
+ {tickets, [], [{group, otp_4394}]},
+ {otp_4394, [], [otp_4394_test]}].
+
+init_per_group(otp_4394, Config) ->
+ init_otp_4394(Config);
+init_per_group(v2_inform, Config) ->
+ init_v2_inform(Config);
+init_per_group(multiple_reqs_2, Config) ->
+ init_mul(Config);
+init_per_group(multiple_reqs, Config) ->
+ init_mul(Config);
+init_per_group(test_multi_threaded, Config) ->
+ init_mt(Config);
+init_per_group(test_v3, Config) ->
+ init_v3(Config);
+init_per_group(test_v1_v2, Config) ->
+ init_v1_v2(Config);
+init_per_group(test_v2, Config) ->
+ init_v2(Config);
+init_per_group(test_v1, Config) ->
+ init_v1(Config);
+init_per_group(mib_storage_varm_mnesia, Config) ->
+ init_varm_mib_storage_mnesia(Config);
+init_per_group(mib_storage_varm_dets, Config) ->
+ init_varm_mib_storage_dets(Config);
+init_per_group(mib_storage_size_check_mnesia, Config) ->
+ init_size_check_msm(Config);
+init_per_group(mib_storage_size_check_dets, Config) ->
+ init_size_check_msd(Config);
+init_per_group(mib_storage_size_check_ets, Config) ->
+ init_size_check_mse(Config);
+init_per_group(mib_storage_mnesia, Config) ->
+ init_mib_storage_mnesia(Config);
+init_per_group(mib_storage_dets, Config) ->
+ init_mib_storage_dets(Config);
+init_per_group(mib_storage_ets, Config) ->
+ init_mib_storage_ets(Config);
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(otp_4394, Config) ->
+ finish_otp_4394(Config);
+end_per_group(v2_inform, Config) ->
+ finish_v2_inform(Config);
+end_per_group(multiple_reqs_2, Config) ->
+ finish_mul(Config);
+end_per_group(multiple_reqs, Config) ->
+ finish_mul(Config);
+end_per_group(test_multi_threaded, Config) ->
+ finish_mt(Config);
+end_per_group(test_v3, Config) ->
+ finish_v3(Config);
+end_per_group(test_v1_v2, Config) ->
+ finish_v1_v2(Config);
+end_per_group(test_v2, Config) ->
+ finish_v2(Config);
+end_per_group(test_v1, Config) ->
+ finish_v1(Config);
+end_per_group(mib_storage_varm_mnesia, Config) ->
+ finish_varm_mib_storage_mnesia(Config);
+end_per_group(mib_storage_varm_dets, Config) ->
+ finish_varm_mib_storage_dets(Config);
+end_per_group(mib_storage_size_check_mnesia, Config) ->
+ finish_size_check_msm(Config);
+end_per_group(mib_storage_size_check_dets, Config) ->
+ finish_size_check_msd(Config);
+end_per_group(mib_storage_size_check_ets, Config) ->
+ finish_size_check_mse(Config);
+end_per_group(mib_storage_mnesia, Config) ->
+ finish_mib_storage_mnesia(Config);
+end_per_group(mib_storage_dets, Config) ->
+ finish_mib_storage_dets(Config);
+end_per_group(mib_storage_ets, Config) ->
+ finish_mib_storage_ets(Config);
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+cases() ->
+case ?OSTYPE() of
+ vxworks ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_multi_threaded},
+ {group, mib_storage}, {group, tickets}];
+ _Else ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_v3},
+ {group, test_multi_threaded}, {group, mib_storage},
+ {group, tickets}]
+end.
+
+
+%%%-----------------------------------------------------------------
+%%% The test case structure is as follows:
+%%%
+%%% init_all - starts mnesia,
+%%%
+%%% init_v1 - starts agent
+%%% simple
+%%% big - e.g. starts/stops subagent, load/unloads mibs
+%%% init_mul
+%%% mul_get
+%%% mul_set
+%%% <etc>
+%%% finish_mul
+%%% <etc>
+%%% finish_v1
+%%%
+%%% init_v2 - starts agent
+%%% finish_v2
+%%%
+%%% init_bilingual - starts agent
+%%% finish_bilingual
+%%%
+%%% finish_all
+%%%
+%%% There is still one problem with these testsuites. If one test
+%%% fails, it may not be possible to run some other cases, as it
+%%% may have e.g. created some row or loaded some table, that it
+%%% didn't undo (since it failed).
+%%%-----------------------------------------------------------------
+
+init_all(Config0) when list(Config0) ->
+ ?LOG("init_all -> entry with"
+ "~n Config0: ~p",[Config0]),
+
+ %% --
+ %% Fix config:
+ %%
+
+ DataDir0 = ?config(data_dir, Config0),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config0),
+ Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+
+ %% --
+ %% Start nodes
+ %%
+
+ ?line {ok, SaNode} = start_node(snmp_sa),
+ ?line {ok, MgrNode} = start_node(snmp_mgr),
+
+
+ %% --
+ %% Create necessary files
+ %%
+
+ Dir = ?config(priv_dir, Config),
+ ?DBG("init_all -> Dir ~p", [Dir]),
+
+ DataDir = ?config(data_dir, Config),
+ ?DBG("init_all -> DataDir ~p", [DataDir]),
+
+ file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+
+ file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+
+ file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
+ ?DBG("init_all -> SaDir ~p", [SaDir]),
+
+
+ %% --
+ %% Start and initiate mnesia
+ %%
+
+ ?DBG("init_all -> load application mnesia", []),
+ ?line ok = application:load(mnesia),
+
+ ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
+ ?line ok = rpc:call(SaNode, application, load, [mnesia]),
+
+ ?DBG("init_all -> application mnesia: set_env dir",[]),
+ ?line application_controller:set_env(mnesia, dir,
+ filename:join(Dir, "Mnesia1")),
+
+ ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(Dir, "Mnesia2")]),
+
+ ?DBG("init_all -> create mnesia schema",[]),
+ ?line ok = mnesia:create_schema([SaNode, node()]),
+
+ ?DBG("init_all -> start application mnesia",[]),
+ ?line ok = application:start(mnesia),
+
+ ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
+ ?line ok = rpc:call(SaNode, application, start, [mnesia]),
+ Ip = ?LOCALHOST(),
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {agent_dir, AgentDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {mib_dir, DataDir},
+ {ip, Ip} |
+ Config].
+
+finish_all(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ stop_node(SaNode),
+ stop_node(MgrNode),
+ application:stop(mnesia).
+
+start_v1_agent(Config) when list(Config) ->
+ start_agent(Config, [v1]).
+
+start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
+ start_agent(Config, [v1], Opts).
+
+start_v2_agent(Config) when list(Config) ->
+ start_agent(Config, [v2]).
+
+start_v3_agent(Config) when list(Config) ->
+ start_agent(Config, [v3]).
+
+start_bilingual_agent(Config) when list(Config) ->
+ start_agent(Config, [v1,v2]).
+
+start_multi_threaded_agent(Config) when list(Config) ->
+ start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
+
+stop_agent(Config) when list(Config) ->
+ ?LOG("stop_agent -> entry with"
+ "~n Config: ~p",[Config]),
+
+ {Sup, Par} = ?config(snmp_sup, Config),
+ ?DBG("stop_agent -> attempt to stop (sup) ~p"
+ "~n Sup: ~p"
+ "~n Par: ~p",
+ [Sup,
+ (catch process_info(Sup)),
+ (catch process_info(Par))]),
+ stop_sup(Sup, Par),
+
+ {Sup2, Par2} = ?config(snmp_sub, Config),
+ ?DBG("stop_agent -> attempt to stop (sub) ~p"
+ "~n Sup2: ~p"
+ "~n Par2: ~p",
+ [Sup2,
+ (catch process_info(Sup2)),
+ (catch process_info(Par2))]),
+ stop_sup(Sup2, Par2),
+
+ ?DBG("stop_agent -> done - now cleanup config", []),
+ C1 = lists:keydelete(snmp_sup, 1, Config),
+ lists:keydelete(snmp_sub, 1, C1).
+
+
+stop_sup(Pid, _) when node(Pid) == node() ->
+ case (catch process_info(Pid)) of
+ PI when list(PI) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ exit(Pid, kill),
+ await_stopped(Pid, Ref);
+ {'EXIT', _Reason} ->
+ ?LOG("stop_sup -> ~p not running", [Pid]),
+ ok
+ end;
+stop_sup(Pid, _) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ ?LOG("stop_sup -> Ref: ~p", [Ref]),
+ %% Pid ! {'EXIT', Parent, shutdown}, % usch
+ exit(Pid, kill),
+ await_stopped(Pid, Ref).
+
+await_stopped(Pid, Ref) ->
+ receive
+ {'DOWN', Ref, process, Pid, _Reason} ->
+ ?DBG("received down message for ~p", [Pid]),
+ ok
+ after 10000 ->
+ ?INF("await_stopped -> timeout for ~p",[Pid]),
+ erlang:demonitor(Ref),
+ ?FAIL({failed_stop,Pid})
+ end.
+
+
+start_agent(Config, Vsn) ->
+ start_agent(Config, Vsn, []).
+start_agent(Config, Vsn, Opts) ->
+ ?LOG("start_agent -> entry (~p) with"
+ "~n Config: ~p"
+ "~n Vsn: ~p"
+ "~n Opts: ~p",[node(), Config, Vsn, Opts]),
+
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
+ snmp_app_env_init(vsn_init(Vsn) ++
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentDir},
+ {snmp_db_dir, AgentDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, trace},
+ {snmp_symbolic_store_verbosity, trace},
+ {snmp_note_store_verbosity, trace},
+ {snmp_net_if_verbosity, trace}],
+ Opts),
+
+
+ process_flag(trap_exit,true),
+
+ {ok, AppSup} = snmp_app_sup:start_link(),
+ unlink(AppSup),
+ ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
+
+ ?DBG("start_agent -> start master agent (old style)",[]),
+ Sup = case (catch snmpa_app:start(normal)) of
+ {ok, S} ->
+ ?DBG("start_agent -> started, Sup: ~p",[S]),
+ S;
+
+ Else ->
+ ?DBG("start_agent -> unknown result: ~n~p",[Else]),
+ %% Get info about the apps we depend on
+ MnesiaInfo = mnesia_running(),
+ ?FAIL({start_failed,Else,MnesiaInfo})
+ end,
+
+ ?DBG("start_agent -> unlink from supervisor",[]),
+ ?line unlink(Sup),
+ ?line SaDir = ?config(sa_dir, Config),
+ ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
+ ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
+ ?DBG("start_agent -> done",[]),
+ ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
+
+
+vsn_init(Vsn) ->
+ vsn_init([v1,v2,v3], Vsn, []).
+
+vsn_init([], _Vsn, Acc) ->
+ Acc;
+vsn_init([V|Vsns], Vsn, Acc) ->
+ case lists:member(V, Vsn) of
+ true ->
+ vsn_init(Vsns, Vsn, [{V, true}|Acc]);
+ false ->
+ vsn_init(Vsns, Vsn, [{V, false}|Acc])
+ end.
+
+snmp_app_env_init(Env0, Opts) ->
+ ?DBG("snmp_app_env_init -> unload snmp",[]),
+ ?line application:unload(snmp),
+ ?DBG("snmp_app_env_init -> load snmp",[]),
+ ?line application:load(snmp),
+ ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
+ F1 = fun({Key,Val} = New, Acc0) ->
+ ?DBG("snmp_app_env_init -> "
+ "updating setting ~p to ~p", [Key, Val]),
+ case lists:keyreplace(Key, 1, Acc0, New) of
+ Acc0 ->
+ [New|Acc0];
+ Acc ->
+ Acc
+ end
+ end,
+ Env = lists:foldr(F1, Env0, Opts),
+ ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
+ F2 = fun({Key,Val}) ->
+ ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
+ application_controller:set_env(snmp, Key, Val)
+ end,
+ lists:foreach(F2, Env).
+
+
+
+
+%% Test if application is running
+mnesia_running() -> ?IS_MNESIA_RUNNING().
+crypto_running() -> ?IS_CRYPTO_RUNNING().
+
+
+start_sub(Dir) ->
+ ?DBG("start_sub -> entry",[]),
+ Opts = [{db_dir, Dir},
+ {supervisor, [{verbosity, trace}]}],
+ %% BMK BMK
+% {ok, P} = snmp_supervisor:start_sub(Dir),
+ {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
+ unlink(P),
+ {ok, {P, self()}}.
+
+create_tables(SaNode) ->
+ ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
+ {attributes, [a1,a2]}]).
+
+delete_tables() ->
+ mnesia:delete_table(friendsTable2),
+ mnesia:delete_table(kompissTable2),
+ mnesia:delete_table(snmp_variables).
+
+%% Creation is done in runtime!
+delete_mib_storage_mnesia_tables() ->
+ mnesia:delete_table(snmpa_mib_data),
+ mnesia:delete_table(snmpa_mib_tree),
+ mnesia:delete_table(snmpa_symbolic_store).
+
+%%-----------------------------------------------------------------
+%% A test case is always one of:
+%% - v1 specific case
+%% - v2 specific case
+%% - v1 and v2 case
+%% All v1 specific cases are prefixed with v1_, and all v2 with
+%% v2_. E.g. v1_trap/v2_trap.
+%%
+%% All other cases are shared. However, the testserver uses the name
+%% of the case to generate a file for that case. The same case cannot
+%% be used in different configurations in the same suite. Therefore
+%% all these functions exists in two variants, the base function
+%% <base>, and a second version <base>_2. There may be several
+%% versions as well, <base>_N.
+%%-----------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+mib_storage_ets_cases() ->
+[mse_simple, mse_v1_processing, mse_big, mse_big2,
+ mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
+ mse_sa_error, mse_next_across_sa, mse_undo,
+ mse_standard_mib, mse_community_mib, mse_framework_mib,
+ mse_target_mib, mse_notification_mib,
+ mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
+ mse_mib_of].
+
+mib_storage_dets_cases() ->
+[msd_simple, msd_v1_processing, msd_big, msd_big2,
+ msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
+ msd_sa_error, msd_next_across_sa, msd_undo,
+ msd_standard_mib, msd_community_mib, msd_framework_mib,
+ msd_target_mib, msd_notification_mib,
+ msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
+ msd_mib_of].
+
+mib_storage_mnesia_cases() ->
+[msm_simple, msm_v1_processing, msm_big, msm_big2,
+ msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
+ msm_sa_error, msm_next_across_sa, msm_undo,
+ msm_standard_mib, msm_community_mib, msm_framework_mib,
+ msm_target_mib, msm_notification_mib,
+ msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
+ msm_mib_of].
+
+mse_size_check_cases() ->
+[mse_size_check].
+
+msd_size_check_cases() ->
+[msd_size_check].
+
+msm_size_check_cases() ->
+[msm_size_check].
+
+varm_mib_storage_dets_cases() ->
+[msd_varm_mib_start].
+
+varm_mib_storage_mnesia_cases() ->
+[msm_varm_mib_start].
+
+init_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,ets},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ init_ms(Config, [MibStorage]).
+
+init_ms(Config, Opts) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
+ [{vsn, v1} | start_v1_agent(Config,Opts1)].
+
+init_size_check_mse(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, ets},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msd(Config) when list(Config) ->
+ AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDir}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msm(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, {mnesia,[]}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_ms(Config, Opts) when list(Config) ->
+ SaNode = ?GCONF(snmp_sa, Config),
+ %% We are using v3 here, so crypto must be supported or else...
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end,
+ create_tables(SaNode),
+ AgentDir = ?GCONF(agent_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ ?line ok =
+ config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_agent(Config, [v3], Opts)].
+
+init_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_dets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+init_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_mnesia -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+finish_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_ets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_dets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_dets -> entry", []),
+ delete_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_size_check_mse(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msd(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msm(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_ms(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%% These are just interface functions to fool the test server
+mse_simple(X) -> simple(X).
+mse_v1_processing(X) -> v1_processing(X).
+mse_big(X) -> big(X).
+mse_big2(X) -> big2(X).
+mse_loop_mib(X) -> loop_mib(X).
+mse_api(X) -> api(X).
+mse_sa_register(X) -> sa_register(X).
+mse_v1_trap(X) -> v1_trap(X).
+mse_sa_error(X) -> sa_error(X).
+mse_next_across_sa(X) -> next_across_sa(X).
+mse_undo(X) -> undo(X).
+mse_standard_mib(X) -> snmp_standard_mib(X).
+mse_community_mib(X) -> snmp_community_mib(X).
+mse_framework_mib(X) -> snmp_framework_mib(X).
+mse_target_mib(X) -> snmp_target_mib(X).
+mse_notification_mib(X) -> snmp_notification_mib(X).
+mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+mse_sparse_table(X) -> sparse_table(X).
+mse_me_of(X) -> ms_me_of(X).
+mse_mib_of(X) -> ms_mib_of(X).
+
+msd_simple(X) -> simple(X).
+msd_v1_processing(X) -> v1_processing(X).
+msd_big(X) -> big(X).
+msd_big2(X) -> big2(X).
+msd_loop_mib(X) -> loop_mib(X).
+msd_api(X) -> api(X).
+msd_sa_register(X) -> sa_register(X).
+msd_v1_trap(X) -> v1_trap(X).
+msd_sa_error(X) -> sa_error(X).
+msd_next_across_sa(X) -> next_across_sa(X).
+msd_undo(X) -> undo(X).
+msd_standard_mib(X) -> snmp_standard_mib(X).
+msd_community_mib(X) -> snmp_community_mib(X).
+msd_framework_mib(X) -> snmp_framework_mib(X).
+msd_target_mib(X) -> snmp_target_mib(X).
+msd_notification_mib(X) -> snmp_notification_mib(X).
+msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msd_sparse_table(X) -> sparse_table(X).
+msd_me_of(X) -> ms_me_of(X).
+msd_mib_of(X) -> ms_mib_of(X).
+
+msm_simple(X) -> simple(X).
+msm_v1_processing(X) -> v1_processing(X).
+msm_big(X) -> big(X).
+msm_big2(X) -> big2(X).
+msm_loop_mib(X) -> loop_mib(X).
+msm_api(X) -> api(X).
+msm_sa_register(X) -> sa_register(X).
+msm_v1_trap(X) -> v1_trap(X).
+msm_sa_error(X) -> sa_error(X).
+msm_next_across_sa(X) -> next_across_sa(X).
+msm_undo(X) -> undo(X).
+msm_standard_mib(X) -> snmp_standard_mib(X).
+msm_community_mib(X) -> snmp_community_mib(X).
+msm_framework_mib(X) -> snmp_framework_mib(X).
+msm_target_mib(X) -> snmp_target_mib(X).
+msm_notification_mib(X) -> snmp_notification_mib(X).
+msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msm_sparse_table(X) -> sparse_table(X).
+msm_me_of(X) -> ms_me_of(X).
+msm_mib_of(X) -> ms_mib_of(X).
+
+
+mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
+msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
+msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
+
+msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
+msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
+
+ms_size_check(suite) -> [];
+ms_size_check(Config) when list(Config) ->
+ p("ms_size_check..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?LOG("mib server size check...", []),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMPv2-MIB"),
+ ?line load_master_std("SNMPv2-TM"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMPv2-MIB"),
+ ?line unload_master("SNMPv2-TM"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+
+varm_mib_start(suite) -> [];
+varm_mib_start(Config) when list(Config) ->
+ p("varm_mib_start..."),
+ ?LOG("varm_mib_start -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ %% Start the agent
+ Opts = ?GCONF(agent_opts, Config),
+ Config1 = start_v1_agent(Config, Opts),
+
+ %% Sleep some in order for the agent to start properly
+ ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
+ ?SLEEP(5000),
+
+ %% Load all the mibs
+ HardwiredMibs = loaded_mibs(),
+ ?DBG("varm_mib_start -> load all mibs", []),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+
+ %% Unload the hardwired mibs
+ ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
+ ?SLEEP(1000),
+ ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
+ ?line unload_mibs(HardwiredMibs), %% unload hardwired
+
+ ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
+ ?SLEEP(1000),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ Config2 = stop_agent(Config1),
+
+ %% Sleep some in order for the agent to stop properly
+ ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
+ ?SLEEP(5000),
+
+ %% Start the agent (again)
+ ?DBG("varm_mib_start -> start the agent", []),
+ Config3 = start_v1_agent(Config2, Opts),
+
+ ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
+ ?SLEEP(5000),
+
+ %% Perform the test(s)
+ ?DBG("varm_mib_start -> perform the tests", []),
+ try_test(snmp_community_mib),
+ try_test(snmp_framework_mib),
+ try_test(snmp_target_mib),
+ try_test(snmp_notification_mib),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ stop_agent(Config3),
+ ok.
+
+
+-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
+-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
+-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+ms_me_of(suite) -> [];
+ms_me_of(Config) when list(Config) ->
+ p("ms_me_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = me_of(?snmpTrapCommunity_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = me_of(?vacmViewSpinLock_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+me_of(Oid) ->
+ case snmpa:me_of(Oid) of
+ {ok, #me{oid = Oid}} ->
+ ok;
+ {ok, #me{oid = OtherOid}} ->
+ case lists:reverse(Oid) of
+ [0|Rest] ->
+ case lists:reverse(Rest) of
+ OtherOid ->
+ ok;
+ AnotherOid ->
+ {error, {invalid_oid, Oid, AnotherOid}}
+ end;
+ _ ->
+ {error, {invalid_oid, Oid, OtherOid}}
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ {error, Else}
+ end.
+
+
+ms_mib_of(suite) -> [];
+ms_mib_of(Config) when list(Config) ->
+ p("ms_mib_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
+ 'SNMP-USER-BASED-SM-MIB'),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+mib_of(Oid, ExpectedMibName) ->
+ ?DBG("mib_of -> entry with"
+ "~n Oid: ~p"
+ "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
+ %% case snmpa:mib_of(Oid) of
+ MibOf = snmpa:mib_of(Oid),
+ ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
+ case MibOf of
+ {ok, ExpectedMibName} ->
+ ok;
+ {ok, OtherMibName} ->
+ {error, {invalid_mib, ExpectedMibName, OtherMibName}};
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ ?DBG("mib_of -> Else: ~n~p", [Else]),
+ {error, Else}
+ end.
+
+
+app_info(suite) -> [];
+app_info(Config) when list(Config) ->
+ SnmpDir = app_dir(snmp),
+ SslDir = app_dir(ssl),
+ CryptoDir = app_dir(crypto),
+ Attr = snmp:module_info(attributes),
+ AppVsn =
+ case lists:keysearch(app_vsn, 1, Attr) of
+ {value, {app_vsn, V}} ->
+ V;
+ false ->
+ "undefined"
+ end,
+ io:format("Root dir: ~s~n"
+ "SNMP: Application dir: ~s~n"
+ " Application ver: ~s~n"
+ "SSL: Application dir: ~s~n"
+ "CRYPTO: Application dir: ~s~n",
+ [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
+ ok.
+
+app_dir(App) ->
+ case code:lib_dir(App) of
+ D when list(D) ->
+ filename:basename(D);
+ {error, _Reason} ->
+ "undefined"
+ end.
+
+
+
+%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].
+
+init_v1(Config) when list(Config) ->
+ ?line SaNode = ?config(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v1} | start_v1_agent(Config)].
+
+finish_v1(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v2_cases() -> [loop_mib_2];
+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].
+
+init_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_v2_agent(Config)].
+
+finish_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+v1_v2_cases() ->
+[simple_bi].
+
+init_v1_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, bilingual} | start_bilingual_agent(Config)].
+
+finish_v1_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v3_cases() -> [loop_mib_3];
+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].
+
+init_v3(Config) when list(Config) ->
+ %% Make sure crypto works, otherwise start_agent will fail
+ %% and we will be stuck with a bunch of mnesia tables for
+ %% the rest of this suite...
+ ?DBG("start_agent -> start crypto app",[]),
+ case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end
+ end,
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v3], MgrDir, AgentDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_v3_agent(Config)].
+
+finish_v3(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+mt_cases() ->
+[multi_threaded, mt_trap].
+
+init_mt(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_multi_threaded_agent(Config)].
+
+finish_mt(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+%% This one *must* be run first in each case.
+init_case(Config) when list(Config) ->
+ ?DBG("init_case -> entry with"
+ "~n Config: ~p", [Config]),
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = node(),
+
+ SaHost = ?HOSTNAME(SaNode),
+ MgrHost = ?HOSTNAME(MgrNode),
+ MasterHost = ?HOSTNAME(MasterNode),
+ {ok, MasterIP} = snmp_misc:ip(MasterHost),
+ {ok, MIP} = snmp_misc:ip(MgrHost),
+ {ok, SIP} = snmp_misc:ip(SaHost),
+
+
+ put(mgr_node, MgrNode),
+ put(sa_node, SaNode),
+ put(master_node, MasterNode),
+ put(sa_host, SaHost),
+ put(mgr_host, MgrHost),
+ put(master_host, MasterHost),
+ put(mip, tuple_to_list(MIP)),
+ put(masterip , tuple_to_list(MasterIP)),
+ put(sip, tuple_to_list(SIP)),
+
+ MibDir = ?config(mib_dir, Config),
+ put(mib_dir, MibDir),
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ put(std_mib_dir, StdM),
+
+ MgrDir = ?config(mgr_dir, Config),
+ put(mgr_dir, MgrDir),
+
+ put(vsn, ?config(vsn, Config)),
+ ?DBG("init_case -> exit with"
+ "~n MasterNode: ~p"
+ "~n SaNode: ~p"
+ "~n MgrNode: ~p"
+ "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
+ {SaNode, MgrNode, MibDir}.
+
+load_master(Mib) ->
+ ?DBG("load_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+
+load_master_std(Mib) ->
+ ?DBG("load_master_std -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+
+unload_master(Mib) ->
+ ?DBG("unload_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+
+loaded_mibs() ->
+ ?DBG("loaded_mibs -> entry",[]),
+ Info = snmpa:info(snmp_master_agent),
+ {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
+ [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
+
+unload_mibs(Mibs) ->
+ ?DBG("unload_mibs -> entry with"
+ "~n Mibs: ~p", [Mibs]),
+ ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
+
+start_subagent(SaNode, RegTree, Mib) ->
+ ?DBG("start_subagent -> entry with"
+ "~n SaNode: ~p"
+ "~n RegTree: ~p"
+ "~n Mib: ~p", [SaNode, RegTree, Mib]),
+ MA = whereis(snmp_master_agent),
+ ?DBG("start_subagent -> MA: ~p", [MA]),
+ MibDir = get(mib_dir),
+ Mib1 = join(MibDir,Mib),
+ %% BMK BMK
+% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
+ case rpc:call(SaNode, snmpa_supervisor,
+ start_sub_agent, [MA, RegTree, [Mib1]]) of
+ {ok, SA} ->
+ ?DBG("start_subagent -> SA: ~p", [SA]),
+ {ok, SA};
+ Error ->
+ ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
+ end.
+
+stop_subagent(SA) ->
+ ?DBG("stop_subagent -> entry with"
+ "~n SA: ~p", [SA]),
+ %% BNK BMK
+ %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
+ rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
+
+%%-----------------------------------------------------------------
+%% This function takes care of the old OTP-SNMPEA-MIB.
+%% Unfortunately, the testcases were written to use the data in the
+%% internal tables, and these table are now obsolete and not used
+%% by the agent. Therefore, we emulate them by using
+%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
+%%
+%% These two rows must exist in intCommunityTable
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+%% (But with the manager's IP address)
+%%
+%%-----------------------------------------------------------------
+init_old() ->
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [6 | "public"],
+ {get(mip), "public", 2, 2}),
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [13 | "standard trap"],
+ {get(mip), "standard trap", 2, 1}),
+ snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
+
+
+
+simple(suite) -> [];
+simple(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(simple_standard_test).
+
+simple_2(X) -> simple(X).
+
+simple_bi(suite) -> [];
+simple_bi(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(vsn, v1), % First, try v1 manager
+ try_test(simple_standard_test),
+
+ put(vsn, v2), % Then, try v2 manager
+ try_test(simple_standard_test).
+
+simple_3(X) ->
+ simple(X).
+
+big(suite) -> [];
+big(Config) when list(Config) ->
+ ?DBG("big -> entry", []),
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?DBG("big -> SA: ~p", [SA]),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+big_2(X) -> big(X).
+
+big_3(X) -> big(X).
+
+
+big2(suite) -> [];
+big2(Config) when list(Config) ->
+ %% This is exactly the same tests as 'big', but with the
+ %% v2 equivalent of the mibs.
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
+ ?line load_master("OLD-SNMPEA-MIB-v2"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB-v2").
+
+big2_2(X) -> big2(X).
+
+big2_3(X) -> big2(X).
+
+
+multi_threaded(suite) -> [];
+multi_threaded(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(multi_threaded_test),
+ ?line unload_master("Test1").
+
+mt_trap(suite) -> [];
+mt_trap(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ ?line load_master("TestTrapv2"),
+ try_test(mt_trap_test, [MA]),
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("Test1").
+
+v2_types(suite) -> [];
+v2_types(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(types_v2_test),
+ ?line unload_master("Test1").
+
+v2_types_3(X) -> v2_types(X).
+
+
+implied(suite) -> [];
+implied(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(implied_test,[MA]),
+ ?line unload_master("Test1").
+
+implied_3(X) -> implied(X).
+
+
+sparse_table(suite) -> [];
+sparse_table(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(sparse_table_test),
+ ?line unload_master("Test1").
+
+sparse_table_2(X) -> sparse_table(X).
+
+sparse_table_3(X) -> sparse_table(X).
+
+cnt_64(suite) -> [];
+cnt_64(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(cnt_64_test, [MA]),
+ ?line unload_master("Test1").
+
+cnt_64_2(X) -> cnt_64(X).
+
+cnt_64_3(X) -> cnt_64(X).
+
+opaque(suite) -> [];
+opaque(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(opaque_test),
+ ?line unload_master("Test1").
+
+opaque_2(X) -> opaque(X).
+
+opaque_3(X) -> opaque(X).
+
+
+change_target_addr_config(suite) -> [];
+change_target_addr_config(Config) when list(Config) ->
+ p("Testing changing target address config..."),
+ ?LOG("change_target_addr_config -> entry",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(sname,snmp_suite),
+ put(verbosity,trace),
+
+ MA = whereis(snmp_master_agent),
+
+ ?LOG("change_target_addr_config -> load TestTrap",[]),
+ ?line load_master("TestTrap"),
+
+ ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,trace),
+
+ %% First send some traps that will arive att the original manager
+ ?LOG("change_target_addr_config -> send trap",[]),
+ try_test(ma_trap1, [MA]),
+
+ ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,silence),
+
+ %% Start new dummy listener
+ ?LOG("change_target_addr_config -> start dummy manager",[]),
+ ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+
+ %% Reconfigure
+ ?LOG("change_target_addr_config -> reconfigure",[]),
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_addr_conf(AgentDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ %% Send the trap again
+ ?LOG("change_target_addr_config -> send trap again",[]),
+ catch dummy_manager_send_trap2(Pid),
+
+ ?LOG("change_target_addr_config -> await trap ack",[]),
+ catch dummy_manager_await_trap2_ack(),
+
+ ?LOG("change_target_addr_config -> stop dummy manager",[]),
+ ?line ok = dummy_manager_stop(Pid),
+
+ ?LOG("change_target_addr_config -> reset target address config",[]),
+ ?line reset_target_addr_conf(AgentDir),
+
+ ?LOG("change_target_addr_config -> unload TestTrap",[]),
+ ?line unload_master("TestTrap").
+
+
+dummy_manager_start(MA) ->
+ ?DBG("dummy_manager_start -> entry",[]),
+ Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
+ ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
+ await_dummy_manager_started(Pid).
+
+await_dummy_manager_started(Pid) ->
+ receive
+ {dummy_manager_started,Pid,Port} ->
+ ?DBG("dummy_manager_start -> acknowledge received with"
+ "~n Port: ~p",[Port]),
+ {ok,Pid,Port};
+ {'EXIT', Pid, Reason} ->
+ {error, Pid, Reason};
+ O ->
+ ?LOG("dummy_manager_start -> received unknown message:"
+ "~n ~p",[O]),
+ await_dummy_manager_started(Pid)
+ end.
+
+dummy_manager_stop(Pid) ->
+ ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
+ Pid ! stop,
+ receive
+ {dummy_manager_stopping, Pid} ->
+ ?DBG("dummy_manager_stop -> acknowledge received",[]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_stop -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_send_trap2(Pid) ->
+ ?DBG("dummy_manager_send_trap2 -> entry",[]),
+ Pid ! {send_trap,testTrap2}.
+
+dummy_manager_await_trap2_ack() ->
+ ?DBG("dummy_manager_await_trap2 -> entry",[]),
+ receive
+ {received_trap,Trap} ->
+ ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
+ %% Note:
+ %% Without this sleep the v2_inform_i testcase failes! There
+ %% is no relation between these two test cases as far as I
+ %% able to figure out...
+ sleep(60000),
+ ok;
+ O ->
+ ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_await_trap2 -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_init(Parent,MA) ->
+ ?DBG("dummy_manager_init -> entry with"
+ "~n Parent: ~p"
+ "~n MA: ~p",[Parent,MA]),
+ {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
+ ?DBG("dummy_manager_init -> S: ~p",[S]),
+ {ok,Port} = inet:port(S),
+ ?DBG("dummy_manager_init -> Port: ~p",[Port]),
+ Parent ! {dummy_manager_started,self(),Port},
+ dummy_manager_loop(Parent,S,MA).
+
+dummy_manager_loop(P,S,MA) ->
+ ?LOG("dummy_manager_loop -> ready for receive",[]),
+ receive
+ {send_trap,Trap} ->
+ ?LOG("dummy_manager_loop -> received trap send request"
+ "~n Trap: ~p",[Trap]),
+ snmpa:send_trap(MA, Trap, "standard trap"),
+ dummy_manager_loop(P,S,MA);
+ {udp, _UdpId, Ip, UdpPort, Bytes} ->
+ ?LOG("dummy_manager_loop -> received upd message"
+ "~n from: ~p:~p"
+ "~n size: ~p",
+ [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
+ R = dummy_manager_handle_message(Bytes),
+ ?DBG("dummy_manager_loop -> R: ~p",[R]),
+ P ! R,
+ dummy_manager_loop(P,S,MA);
+ stop ->
+ ?DBG("dummy_manager_loop -> received stop request",[]),
+ P ! {dummy_manager_stopping, self()},
+ gen_udp:close(S),
+ exit(normal);
+ O ->
+ ?LOG("dummy_manager_loop -> received unknown message:"
+ "~n ~p",[O]),
+ dummy_manager_loop(P,S,MA)
+ end.
+
+dummy_manager_message_sz(B) when binary(B) ->
+ size(B);
+dummy_manager_message_sz(L) when list(L) ->
+ length(L);
+dummy_manager_message_sz(_) ->
+ undefined.
+
+dummy_manager_handle_message(Bytes) ->
+ case (catch snmp_pdus:dec_message(Bytes)) of
+ {'EXIT',Reason} ->
+ ?ERR("dummy_manager_handle_message -> "
+ "failed decoding message only:~n ~p",[Reason]),
+ {error,Reason};
+ M ->
+ ?DBG("dummy_manager_handle_message -> decoded message:"
+ "~n ~p",[M]),
+ {received_trap,M}
+ end.
+
+
+api(suite) -> [];
+api(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(api_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+api_2(X) -> api(X).
+
+api_3(X) -> api(X).
+
+
+subagent(suite) -> [];
+subagent(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ try_test(load_test_sa),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+
+ p("Loading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(load_test),
+
+ p("Unloading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(unreg_test),
+ p("Testing register subagent..."),
+ rpc:call(SaNode, snmp, register_subagent,
+ [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ ?line stop_subagent(SA),
+ try_test(unreg_test).
+
+subagent_2(X) -> subagent(X).
+
+subagent_3(X) -> subagent(X).
+
+
+mnesia(suite) -> [];
+mnesia(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent with mnesia impl..."),
+ {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ try_test(big_test_2),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA).
+
+mnesia_2(X) -> mnesia(X).
+
+mnesia_3(X) -> mnesia(X).
+
+
+
+mul_cases() ->
+[mul_get, mul_get_err, mul_next, mul_next_err,
+ mul_set_err].
+
+
+multiple_reqs_3(_X) ->
+ {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
+
+
+mul_cases_2() ->
+[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
+ mul_set_err_2].
+
+
+mul_cases_3() ->
+ [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
+
+
+init_mul(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ [{mul_sub, SA} | Config].
+
+finish_mul(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ SA = ?config(mul_sub, Config),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA),
+ lists:keydelete(mul_sub, 1, Config).
+
+mul_get(suite) -> [];
+mul_get(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get..."),
+ try_test(do_mul_get).
+
+mul_get_2(X) -> mul_get(X).
+
+mul_get_3(X) -> mul_get(X).
+
+
+mul_get_err(suite) -> [];
+mul_get_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get with error..."),
+ try_test(do_mul_get_err).
+
+mul_get_err_2(X) -> mul_get_err(X).
+
+mul_get_err_3(X) -> mul_get_err(X).
+
+
+mul_next(suite) -> [];
+mul_next(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next).
+
+mul_next_2(X) -> mul_next(X).
+
+mul_next_3(X) -> mul_next(X).
+
+
+mul_next_err(suite) -> [];
+mul_next_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next_err).
+
+mul_next_err_2(X) -> mul_next_err(X).
+
+mul_next_err_3(X) -> mul_next_err(X).
+
+
+mul_set(suite) -> [];
+mul_set(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set..."),
+ try_test(do_mul_set).
+
+mul_set_2(X) -> mul_set(X).
+
+mul_set_3(X) -> mul_set(X).
+
+
+mul_set_err(suite) -> [];
+mul_set_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set with error..."),
+ try_test(do_mul_set_err).
+
+mul_set_err_2(X) -> mul_set_err(X).
+
+mul_set_err_3(X) -> mul_set_err(X).
+
+
+sa_register(suite) -> [];
+sa_register(Config) when list(Config) ->
+ ?DBG("sa_register -> entry", []),
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?DBG("sa_register -> start subagent", []),
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+
+ ?DBG("sa_register -> unregister subagent", []),
+ p("Testing unregister subagent (2)..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Loading SA-MIB..."),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ ?DBG("sa_register -> register subagent", []),
+ rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
+ try_test(sa_mib),
+
+ ?DBG("sa_register -> stop subagent", []),
+ ?line stop_subagent(SA).
+
+sa_register_2(X) -> sa_register(X).
+
+sa_register_3(X) -> sa_register(X).
+
+
+v1_trap(suite) -> [];
+v1_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_trap1, [MA]),
+ try_test(ma_trap2, [MA]),
+ try_test(ma_v2_2_v1_trap, [MA]),
+ try_test(ma_v2_2_v1_trap2, [MA]),
+
+ p("Testing trap sending from subagent..."),
+ try_test(sa_trap1, [SA]),
+ try_test(sa_trap2, [SA]),
+ try_test(sa_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v2_trap(suite) -> [];
+v2_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+
+ try_test(ma_v2_trap1, [MA]),
+ try_test(ma_v2_trap2, [MA]),
+ try_test(ma_v1_2_v2_trap, [MA]),
+ try_test(ma_v1_2_v2_trap2, [MA]),
+
+ try_test(sa_mib),
+ p("Testing trap sending from subagent..."),
+ try_test(sa_v1_2_v2_trap1, [SA]),
+ try_test(sa_v1_2_v2_trap2, [SA]),
+ try_test(sa_v1_2_v2_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v3_trap(X) ->
+ v2_trap(X).
+
+
+v3_inform(_X) ->
+ %% v2_inform(X).
+ {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
+
+init_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+init_v3_inform(X) ->
+ init_v2_inform(X).
+
+finish_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+finish_v3_inform(X) ->
+ finish_v2_inform(X).
+
+
+
+v2_inform_i(suite) -> [];
+v2_inform_i(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing inform sending from master agent... NOTE! This test\ntakes a "
+ "few minutes (5) to complete."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_v2_inform1, [MA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2").
+
+v3_inform_i(X) -> v2_inform_i(X).
+
+
+sa_error(suite) -> [];
+sa_error(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing sa bad value (is_set_ok)..."),
+ try_test(sa_errs_bad_value),
+
+ p("Testing sa gen err (set)..."),
+ try_test(sa_errs_gen_err),
+
+ p("Testing too big..."),
+ try_test(sa_too_big),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
+
+sa_error_2(X) -> sa_error(X).
+
+sa_error_3(X) -> sa_error(X).
+
+
+next_across_sa(suite) -> [];
+next_across_sa(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Loading another subagent mib..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+
+ rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ p("Testing next across subagent (endOfMibView from SA)..."),
+ try_test(next_across_sa),
+
+ p("Unloading mib"),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Starting another subagent"),
+ ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ p("Testing next across subagent (wrong prefix from SA)..."),
+ try_test(next_across_sa),
+
+ stop_subagent(SA),
+ stop_subagent(SA2).
+
+next_across_sa_2(X) -> next_across_sa(X).
+
+next_across_sa_3(X) -> next_across_sa(X).
+
+
+undo(suite) -> [];
+undo(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing undo phase at master agent..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ try_test(undo_test),
+ try_test(api_test2),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+
+ p("Testing bad return values from instrum. funcs..."),
+ try_test(bad_return),
+
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+
+ p("Testing undo phase at subagent..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ try_test(undo_test),
+ try_test(api_test3),
+
+ p("Testing undo phase across master/subagents..."),
+ try_test(undo_test),
+ try_test(api_test3),
+ stop_subagent(SA).
+
+undo_2(X) -> undo(X).
+
+undo_3(X) -> undo(X).
+
+%% Req. Test2
+v1_processing(suite) -> [];
+v1_processing(Config) when list(Config) ->
+ ?DBG("v1_processing -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v1_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v2_processing(suite) -> [];
+v2_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v3_processing(suite) -> [];
+v3_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc), % same as v2!
+ ?line unload_master("Test2").
+
+
+%% We'll try get/set/trap and inform for all the auth & priv protocols.
+%% For informs, the mgr is auth-engine. The agent has to sync. This is
+%% accomplished by the first inform sent. That one will generate a
+%% report, which makes it in sync. The notification-generating
+%% application times out, and send again. This time it'll work.
+
+v3_crypto_basic(suite) -> [];
+v3_crypto_basic(_Config) ->
+ EID = [0,0,0,0,0,0,0,0,0,0,0,2],
+ %% From rfc2274 appendix A.3.1
+ ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
+ ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
+ 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
+ KMd5_1,
+ %% From rfc2274 appendix A.3.2
+ ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
+ ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
+ 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
+ KSHA_1,
+ %% From rfc2274, appendix A.5.1
+ ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
+ 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ %% From rfc2274, appendix A.5.2
+ ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
+ 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
+ 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ KSHA_1t = lists:sublist(KSHA_1, 16),
+ KSHA_2t = lists:sublist(KSHA_2, 16),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
+ 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+
+ %% Try with correct random
+ ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
+ ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
+ ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
+ ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
+ ok.
+
+
+
+v3_md5_auth(suite) -> [];
+v3_md5_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing MD5 authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_sha_auth(suite) -> [];
+v3_sha_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing SHA authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_des_priv(suite) -> [];
+v3_des_priv(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing DES encryption...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+%% Make sure mgr is in sync with agent
+v3_sync(Funcs) ->
+ ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
+ g([[sysDescr, 0]]),
+ expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
+ g([[sysDescr, 0]]),
+ expect(433, [{[sysDescr,0], any}]),
+ lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
+
+v3_inform_sync(MA) ->
+ ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
+ "standard inform", []),
+ %% Make sure agent is in sync with mgr...
+ ?DBG("v3_sync -> wait some time: ",[]),
+ sleep(20000), % more than 1500*10 in target_addr.conf
+ ?DBG("v3_sync -> await response",[]),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]).
+
+
+v2_caps(suite) -> [];
+v2_caps(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(v2_caps_i, [node()]).
+
+v2_caps_3(X) -> v2_caps(X).
+
+
+v2_caps_i(Node) ->
+ ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
+ g([[sysORID, Idx], [sysORDescr, Idx]]),
+ ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
+ {[sysORDescr, Idx], "test cap"}]),
+ ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
+ g([[sysORID, Idx]]),
+ ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
+
+
+%% Req. Test2
+v1_proc() ->
+ ?DBG("v1_proc -> entry", []),
+ %% According to RFC1157.
+ %% Template: <Section>:<list no>
+ v1_get_p(),
+ v1_get_next_p(),
+ v1_set_p().
+
+
+v1_get_p() ->
+ %% 4.1.2:1
+ g([[test2]]),
+ ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
+ g([[tDescr]]),
+ ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
+ g([[tDescr2,0]]),
+ ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ g([[tDescr3,0]]),
+ ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ g([[tDescr4,0]]),
+ ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ {[tDescr,0], 'NULL'}]),
+ g([[sysDescr,3]]),
+ ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+
+ %% 4.1.2:2
+ g([[tTable]]),
+ ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
+ g([[tEntry]]),
+ ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
+
+ %% 4.1.2:3
+ g([[tTooBig, 0]]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.2:4
+ g([[tGenErr1, 0]]),
+ ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]).
+
+
+v1_get_next_p() ->
+ %% 4.1.3:1
+ gn([[1,3,7,1]]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+ gn([[tDescr2]]),
+ ?line expect(11, tooBig, 0, any),
+
+ %% 4.1.3:2
+ gn([[tTooBig]]),
+ io:format("We currently don't handle tooBig correct!!!\n"),
+% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
+ ?line expect(20, tooBig, 0, any),
+
+ %% 4.1.3:3
+ gn([[tGenErr1]]),
+% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?line expect(40, genErr, 1, any),
+ gn([[tGenErr2]]),
+% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?line expect(41, genErr, 1, any),
+ gn([[sysDescr], [tGenErr3]]),
+% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
+% {[tGenErr3], 'NULL'}]).
+ ?line expect(42, genErr, 2, any).
+
+v1_set_p() ->
+ %% 4.1.5:1
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+ s([{[tDescr3], s, "noSuchObject"}]),
+ ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+ s([{[tDescr3,1], s, "noSuchInstance"}]),
+ ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+ s([{[tDescr2,0], s, "inconsistentName"}]),
+ ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+
+ %% 4.1.5:2
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.1.5:3
+ %% The standard is quite incorrect here. The resp pdu was too big. In
+ %% the resp pdu, we have the original vbs. In the tooBig pdu we still
+ %% have to original vbs => the tooBig pdu is too big as well!!! It
+ %% may not get it to the manager, unless the agent uses 'NULL' instead
+ %% of the std-like original value.
+ s([{[tTooBig, 0], s, ?tooBigStr}]),
+ %% according to std:
+% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.5:4
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+ s([{[tDescr2, 0], s, "commit_fail"}]),
+ ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+
+%% Req. Test2
+v2_proc() ->
+ %% According to RFC1905.
+ %% Template: <Section>:<list no>
+ ?DBG("v2_proc -> entry",[]),
+ v2_get_p(),
+ v2_get_next_p(),
+ v2_get_bulk_p(),
+ v2_set_p().
+
+v2_get_p() ->
+ %% 4.2.1:2
+ ?DBG("v2_get_p -> entry",[]),
+ g([[test2]]),
+ ?line expect(10, [{[test2], noSuchObject}]),
+ g([[tDescr]]),
+ ?line expect(11, [{[tDescr], noSuchObject}]),
+ g([[tDescr4,0]]),
+ ?line expect(12, [{[tDescr4,0], noSuchObject}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[tDescr,0], noSuchObject}]),
+ g([[tTable]]),
+ ?line expect(14, [{[tTable], noSuchObject}]),
+ g([[tEntry]]),
+ ?line expect(15, [{[tEntry], noSuchObject}]),
+
+ %% 4.2.1:3
+ g([[tDescr2,0]]), %% instrum ret noSuchName!!!
+ ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
+ g([[tDescr3,0]]),
+ ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
+ g([[sysDescr,3]]),
+ ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
+ g([[tIndex,1]]),
+ ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
+
+ %% 4.2.1 - any other error: genErr
+ g([[tGenErr1, 0]]),
+ ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]),
+
+ %% 4.2.1 - tooBig
+ g([[tTooBig, 0]]),
+ ?line expect(40, tooBig, 0, []).
+
+
+v2_get_next_p() ->
+ %% 4.2.2:2
+ ?DBG("v2_get_next_p -> entry",[]),
+ gn([[1,3,7,1]]),
+ ?line expect(10, [{[1,3,7,1], endOfMibView}]),
+ gn([[sysDescr], [1,3,7,1]]),
+ ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gn([[tCnt2, 1]]),
+ ?line expect(12, [{[tCnt2,2], 100}]),
+ gn([[tCnt2, 2]]),
+ ?line expect(12, [{[tCnt2,2], endOfMibView}]),
+
+ %% 4.2.2 - any other error: genErr
+ gn([[tGenErr1]]),
+ ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ gn([[tGenErr2]]),
+ ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ gn([[sysDescr], [tGenErr3]]),
+ ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
+ {[tGenErr3], 'NULL'}]),
+
+ %% 4.2.2 - tooBig
+ gn([[tTooBig]]),
+ ?line expect(20, tooBig, 0, []).
+
+v2_get_bulk_p() ->
+ %% 4.2.3
+ ?DBG("v2_get_bulk_p -> entry",[]),
+ gb(1, 1, []),
+ ?line expect(10, []),
+ gb(-1, 1, []),
+ ?line expect(11, []),
+ gb(-1, -1, []),
+ ?line expect(12, []),
+ gb(-1, -1, []),
+ ?line expect(13, []),
+ gb(2, 0, [[sysDescr], [1,3,7,1]]),
+ ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(1, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(0, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
+ ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
+ ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[sysDescr, 0], "Erlang SNMP agent"}]),
+
+ gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
+ ?line expect(19, []),
+
+ gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
+ ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
+ {[sysObjectID], 'NULL'},
+ {[tGenErr1], 'NULL'},
+ {[sysDescr], 'NULL'}]),
+ gb(0, 2, [[tCnt2, 1]]),
+ ?line expect(21, [{[tCnt2,2], 100},
+ {[tCnt2,2], endOfMibView}]).
+
+
+v2_set_p() ->
+ %% 4.2.5:1
+ ?DBG("v2_set_p -> entry",[]),
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
+
+ %% 4.2.5:2
+ s([{[1,3,6,1,0], s, "noSuchObject"}]),
+ ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
+
+ %% 4.2.5:3
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.2.5:4
+ s([{[tStr, 0], s, ""}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
+ s([{[tStr, 0], s, "12345"}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
+
+ %% 4.2.5:5 - N/A
+
+ %% 4.2.5:6
+ s([{[tInt1, 0], i, 0}]),
+ ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
+ s([{[tInt1, 0], i, 5}]),
+ ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
+ s([{[tInt2, 0], i, 0}]),
+ ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
+ s([{[tInt2, 0], i, 5}]),
+ ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
+ s([{[tInt3, 0], i, 5}]),
+ ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
+
+ %% 4.2.5:7
+ s([{[tDescrX, 1, 1], s, "noCreation"}]),
+ ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
+
+ %% 4.2.5:8
+ s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
+ ?line expect(80, inconsistentName, 1,
+ [{[tDescrX, 1, 2], "inconsistentName"}]),
+
+ %% 4.2.5:9
+ s([{[tCnt, 1, 2], i, 5}]),
+ ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
+
+ %% 4.2.5:10
+ s([{[tDescr2,0], s, "inconsistentValue"}]),
+ ?line expect(100, inconsistentValue, 1,
+ [{[tDescr2,0], "inconsistentValue"}]),
+
+ %% 4.2.5:11
+ s([{[tDescr2,0], s, "resourceUnavailable"}]),
+ ?line expect(110, resourceUnavailable, 1,
+ [{[tDescr2,0],"resourceUnavailable"}]),
+
+ %% 4.2.5:12
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
+
+ %% commitFailed and undoFailed is tested by the 'undo' case.
+
+
+%% Req. OLD-SNMPEA-MIB
+table_test() ->
+ io:format("Testing simple get, next and set on communityTable...~n"),
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+ Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
+ Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
+ Key1c4 = [intCommunityAccess,get(mip),is("public")],
+ EndKey = [intCommunityEntry,[9],get(mip),is("public")],
+ gn([[intCommunityEntry]]),
+ ?line expect(7, [{Key1c3, 2}]),
+ gn([[intCommunityTable]]),
+ ?line expect(71, [{Key1c3, 2}]),
+ gn([[community]]),
+ ?line expect(72, [{Key1c3, 2}]),
+ gn([[otpSnmpeaMIB]]),
+ ?line expect(73, [{Key1c3, 2}]),
+ gn([[ericsson]]),
+ ?line expect(74, [{Key1c3, 2}]),
+ gn([Key1c3]),
+ ?line expect(8, [{Key2c3, 2}]),
+ gn([Key2c3]),
+ ?line expect(9, [{Key1c4, 2}]),
+ gn([EndKey]),
+ AgentIp = [intAgentIpAddress,0],
+ ?line expect(10, [{AgentIp, any}]),
+ g([Key1c3]),
+ ?line expect(11, [{Key1c3, 2}]),
+ g([EndKey]),
+ ?line ?v1_2(expect(12, noSuchName, 1, any),
+ expect(12, [{EndKey, noSuchObject}])),
+
+ io:format("Testing row creation/deletion on communityTable...~n"),
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+ s([{NewKeyc5, ?createAndGo}]),
+ ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
+ s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
+ ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
+ g([NewKeyc4]),
+ ?line expect(16, [{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(17, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?createAndWait}]),
+ ?line expect(19, [{NewKeyc5, ?createAndWait}]),
+ g([NewKeyc5]),
+ ?line expect(20, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(21, [{NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(22, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc3, 2}]),
+ ?line expect(23, [{NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(24, [{NewKeyc5, ?notInService}]),
+ s([{NewKeyc5, ?active}]),
+ ?line expect(25, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(26, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc3, 3}]),
+ ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
+ otp_1128().
+
+%% Req. system group
+simple_standard_test() ->
+ ?DBG("simple_standard_test -> entry",[]),
+ gn([[1,1]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3]]),
+ ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6]]),
+ ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1]]),
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2]]),
+ ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1]]),
+ ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1,1]]),
+ ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[sysDescr]]),
+ ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr,0]]),
+ ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr]]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{[sysDescr], noSuchObject}])),
+ g([[1,6,7,0]]),
+ ?line ?v1_2(expect(41, noSuchName, 1, any),
+ expect(3, [{[1,6,7,0], noSuchObject}])),
+ gn([[1,13]]),
+ ?line ?v1_2(expect(4, noSuchName,1, any),
+ expect(4, [{[1,13], endOfMibView}])),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+ g([[sysLocation, 0]]),
+ ?line expect(6, [{[sysLocation, 0], "new_value"}]),
+ io:format("Testing noSuchName and badValue...~n"),
+ s([{[sysServices,0], 3}]),
+ ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
+ s([{[sysLocation, 0], i, 3}]),
+ ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
+ ?DBG("simple_standard_test -> done",[]),
+ ok.
+
+%% This is run in the agent node
+db_notify_client(suite) -> [];
+db_notify_client(Config) when list(Config) ->
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
+ [SaNode,MgrNode,MibDir]),
+ snmpa_local_db:register_notify_client(self(),?MODULE),
+
+ %% This call (the manager) will issue to set operations, so
+ %% we expect to receive to notify(insert) calls.
+ try_test(db_notify_client_test),
+
+ ?DBG("await first notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
+ end,
+
+ ?DBG("await second notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
+ end,
+
+ snmpa_local_db:unregister_notify_client(self()).
+
+
+%% This is run in the manager node
+db_notify_client_test() ->
+ ?DBG("set first new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?DBG("set second new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]).
+
+notify(Pid,What) ->
+ ?DBG("notify(~p,~p) -> called",[Pid,What]),
+ Pid ! {db_notify_test_reply,What}.
+
+
+%% Req: system group, OLD-SNMPEA-MIB, Klas1
+big_test() ->
+ ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
+ simple_standard_test(),
+
+ ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
+ gn([[klas1]]),
+ ?line expect(1, [{[fname,0], ""}]),
+ g([[fname,0]]),
+ ?line expect(2, [{[fname,0], ""}]),
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[fname,0]]),
+ ?line expect(4, [{[fname,0], "test set"}]),
+
+ ?DBG("big_test -> "
+ "testing next from last instance in master to subagent...",[]),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname,0], "test set"}]),
+ s([{[fname,0], s, ""}]),
+ ?line expect(52, [{[fname,0], ""}]),
+
+ table_test(),
+
+ ?DBG("big_test -> adding one row in subagent table",[]),
+ _FTab = [friendsEntry],
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {[friendsEntry, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ s([{[friendsEntry, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
+
+ otp_1131(),
+
+ ?DBG("big_test -> adding two rows in subagent table with special INDEX",
+ []),
+ s([{[kompissEntry, [1, 3]], s, "kompis3"},
+ {[kompissEntry, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry, [1, 3]],
+ [kompissEntry, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ gn([[kompissEntry, [1]],
+ [kompissEntry, [2]]]),
+ ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ s([{[kompissEntry, [1, 2]], s, "kompis3"},
+ {[kompissEntry, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry, [1, 1]],
+ [kompissEntry, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?active}]),
+ s([{[kompissEntry, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
+ s([{[kompissEntry, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
+ ?DBG("big_test -> done",[]),
+ ok.
+
+%% Req. system group, Klas2, OLD-SNMPEA-MIB
+big_test_2() ->
+ p("Testing simple next/get/set @ master agent (2)..."),
+ simple_standard_test(),
+
+ p("Testing simple next/get/set @ subagent (2)..."),
+ gn([[klas2]]),
+ ?line expect(1, [{[fname2,0], ""}]),
+ g([[fname2,0]]),
+ ?line expect(2, [{[fname2,0], ""}]),
+ s([{[fname2,0], s, "test set"}]),
+ ?line expect(3, [{[fname2,0], "test set"}]),
+ g([[fname2,0]]),
+ ?line expect(4, [{[fname2,0], "test set"}]),
+
+ otp_1298(),
+
+ p("Testing next from last object in master to subagent (2)..."),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname2,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname2,0], "test set"}]),
+
+ table_test(),
+
+ p("Adding one row in subagent table (2)"),
+ _FTab = [friendsEntry2],
+ s([{[friendsEntry2, [2, 3]], s, "kompis3"},
+ {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry2, [2, 3]],
+ [friendsEntry2, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?active}]),
+ s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
+
+ p("Adding two rows in subagent table with special INDEX (2)"),
+ s([{[kompissEntry2, [1, 3]], s, "kompis3"},
+ {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry2, [1, 3]],
+ [kompissEntry2, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ gn([[kompissEntry2, [1]],
+ [kompissEntry2, [2]]]),
+ ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ s([{[kompissEntry2, [1, 2]], s, "kompis3"},
+ {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry2, [1, 1]],
+ [kompissEntry2, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?active}]),
+ s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
+ s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
+ ok.
+
+%% Req. Test1
+multi_threaded_test() ->
+ p("Testing multi threaded agent..."),
+ g([[multiStr,0]]),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(1, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "pelle"}]),
+ ?line expect(2, [{[sysLocation, 0], "pelle"}]),
+ Pid ! continue,
+ ?line expect(3, [{[multiStr,0], "ok"}]),
+
+ s([{[multiStr, 0], s, "block"}]),
+ Pid2 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(4, [{[sysUpTime,0], any}]),
+ g([[multiStr,0]]),
+ Pid3 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(5, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "kalle"}]),
+ Pid3 ! continue,
+ ?line expect(6, [{[multiStr,0], "ok"}]),
+ Pid2 ! continue,
+ ?line expect(7, [{[multiStr,0], "block"}]),
+ ?line expect(8, [{[sysLocation,0], "kalle"}]).
+
+%% Req. Test1, TestTrapv2
+mt_trap_test(MA) ->
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ snmpa:send_trap(MA, mtTrap, "standard trap"),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(2, [{[sysUpTime,0], any}]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ Pid ! continue,
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [2]},
+ {[multiStr,0], "ok"}]).
+
+
+get_multi_pid() ->
+ get_multi_pid(10).
+get_multi_pid(0) ->
+ ?line ?FAIL(no_global_name);
+get_multi_pid(N) ->
+ sleep(1000),
+ case global:whereis_name(snmp_multi_tester) of
+ Pid when pid(Pid) -> Pid;
+ _ -> get_multi_pid(N-1)
+ end.
+
+%% Req. Test1
+types_v2_test() ->
+ p("Testing v2 types..."),
+
+ s([{[bits1,0], 2#10}]),
+ ?line expect(1, [{[bits1,0], ?str(2#10)}]),
+ g([[bits1,0]]),
+ ?line expect(2, [{[bits1,0], ?str(2#101)}]),
+
+ s([{[bits2,0], 2#11000000110}]),
+ ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
+ g([[bits2,0]]),
+ ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
+
+ g([[bits3,0]]),
+ ?line expect(50, genErr, 1, any),
+
+ g([[bits4,0]]),
+ ?line expect(51, genErr, 1, any),
+
+ s([{[bits1,0], s, [2#10]}]),
+ ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
+
+ s([{[bits2,0], 2#11001001101010011}]),
+ ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%% Req. Test1
+implied_test(MA) ->
+ ?LOG("implied_test -> start",[]),
+ p("Testing IMPLIED..."),
+
+ snmpa:verbosity(MA,trace),
+ snmpa:verbosity(MA,trace),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = "apa",
+ Idx2 = "qq",
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
+ ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
+ {[testDescr, Idx1], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
+ ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
+ {[testDescr, Idx2], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr)",[]),
+ gn([[testDescr]]),
+ ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
+ gn([[testDescr,Idx1]]),
+ ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?destroy}]),
+ ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?destroy}]),
+ ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
+
+ %% Try the same in other table
+ Idx3 = [1, "apa"],
+ Idx4 = [1, "qq"],
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
+ ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
+ {[testDescr2, Idx3], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
+ ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
+ {[testDescr2, Idx4], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr2)",[]),
+ gn([[testDescr2]]),
+ ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
+ gn([[testDescr2,Idx3]]),
+ ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?destroy}]),
+ ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?destroy}]),
+ ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
+
+ snmpa:verbosity(MA,log),
+
+ ?LOG("implied_test -> done",[]).
+
+
+
+%% Req. Test1
+sparse_table_test() ->
+ p("Testing sparse table..."),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ s([{[sparseStatus, Idx1], i, ?createAndGo},
+ {[sparseDescr, Idx1], s, "row 1"}]),
+ ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
+ {[sparseDescr, Idx1], "row 1"}]),
+ s([{[sparseStatus, Idx2], i, ?createAndGo},
+ {[sparseDescr, Idx2], s, "row 2"}]),
+ ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
+ {[sparseDescr, Idx2], "row 2"}]),
+ ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
+ [sparseStatus,Idx1], [sparseStatus,Idx2]]),
+ gb(0,5,[[sparseIndex]])),
+ ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
+ {[sparseDescr,Idx2], "row 2"},
+ {[sparseStatus,Idx1], ?active},
+ {[sparseStatus,Idx2], ?active},
+ {[sparseStr,0], "slut"}]),
+ % Delete the rows
+ s([{[sparseStatus, Idx1], i, ?destroy}]),
+ ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
+ s([{[sparseStatus, Idx2], i, ?destroy}]),
+ ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
+
+
+%% Req. Test1
+cnt_64_test(MA) ->
+ ?LOG("start cnt64 test (~p)",[MA]),
+ snmpa:verbosity(MA,trace),
+ ?LOG("start cnt64 test",[]),
+ p("Testing Counter64, and at the same time, RowStatus is not last column"),
+
+ ?DBG("get cnt64",[]),
+ g([[cnt64,0]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(1, noSuchName, 1, any),
+ expect(1, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("get-next cnt64",[]),
+ gn([[cnt64]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
+ expect(2, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("send cntTrap",[]),
+ snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
+ {cnt64, 10},
+ {sysLocation, "here"}]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ {[sysLocation,0], "here"}]),
+ expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [1]},
+ {[sysContact,0], "pelle"},
+ {[cnt64,0], 10},
+ {[sysLocation,0], "here"}])),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ ?DBG("create row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
+ ?DBG("create row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
+
+ ?DBG("get-next (cntIndex)",[]),
+ gn([[cntIndex]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
+ expect(3, [{[cntCnt,Idx1], 0}])),
+ % Delete the rows
+ ?DBG("delete row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
+ ?DBG("delete row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
+ catch snmpa:verbosity(MA,log),
+ ?DBG("done",[]),
+ ok.
+
+%% Req. Test1
+opaque_test() ->
+ p("Testing Opaque datatype..."),
+ g([[opaqueObj,0]]),
+ ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
+
+%% Req. OLD-SNMPEA-MIB
+api_test(MaNode) ->
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [intAgentIpAddress]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
+ oid_to_name, [OID]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [[1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp,
+ int_to_enum, ['RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
+ ?line case snmp:date_and_time() of
+ List when list(List), length(List) == 8 -> ok;
+ List when list(List), length(List) == 11 -> ok
+ end.
+
+%% Req. Klas3
+api_test2() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]),
+ g([[fname4,0]]),
+ ?line expect(2, [{[fname4,0], 1}]).
+
+api_test3() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]).
+
+
+unreg_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[snmpInPkts, 0], any}]).
+
+load_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[fname,0], ""}]).
+
+%% Req. Klas1
+load_test_sa() ->
+ gn([[?v1_2(sysServices,sysORLastChange), 0]]),
+ ?line expect(1, [{[fname,0], any}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_get() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
+ [sysName,0]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,0], "test"}]),
+ g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
+ ?line ?v1_2(expect(2, noSuchName, [1,4], any),
+ expect(2, [{[1,3,7,1], noSuchObject},
+ {Key1c4, 2},
+ {[sysDescr,0], "Erlang SNMP agent"},
+ {[1,3,7,2], noSuchObject},
+ {Key1c3, 2},
+ {[sysDescr,0], "Erlang SNMP agent"}])).
+
+%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
+do_mul_get_err() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
+ ?line ?v1_2(expect(1, noSuchName, 5, any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,2], noSuchInstance}])),
+ g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname3,0], noSuchObject},
+ {Key1c3, 2},
+ {[sysName,1], noSuchInstance}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2}, {[fname,0], "test set"},
+ {Key1c3, 2}, {[sysName,0], "test"}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next_err() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[1,3,6,999], endOfMibView},
+ {[fname,0], "test set"},
+ {[1,3,90], endOfMibView},
+ {Key1c3, 2},
+ {[sysName,0], "test"}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set() ->
+ p("Adding one row in subagent table, and one in master table"),
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [sysLocation,0],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[sysLocation,0], "new_value"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ g([NewKeyc4]),
+ ?line expect(3, [{NewKeyc4, 2}]),
+ s([{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]),
+ ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ p("Adding one row in subagent table, and one in master table"),
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {NewKeyc3, 2},
+ {[sysUpTime,0], 45}, % sysUpTime (readOnly)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
+ g([[friendsEntry, [2, 3]]]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB
+sa_mib() ->
+ g([[sa, [2,0]]]),
+ ?line expect(1, [{[sa, [2,0]], 3}]),
+ s([{[sa, [1,0]], s, "sa_test"}]),
+ ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+
+ma_trap1(MA) ->
+ snmpa:send_trap(MA, testTrap2, "standard trap"),
+ ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ snmpa:send_trap(MA, testTrap1, "standard trap"),
+ ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]).
+
+ma_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap2(MA) ->
+ snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
+ {ifAdminStatus, [1], 1},
+ {ifOperStatus, [1], 2}]),
+ ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]).
+
+sa_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "pelle"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]).
+
+ma_v2_trap1(MA) ->
+ ?DBG("ma_v2_traps -> entry with MA = ~p => "
+ "send standard trap: testTrapv22",[MA]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
+ snmpa:send_trap(MA, testTrapv21, "standard trap"),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmp ++ [1]}]).
+
+ma_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"}]).
+
+%% Note: This test case takes a while... actually a couple of minutes.
+ma_v2_inform1(MA) ->
+ ?DBG("ma_v2_inform -> entry with MA = ~p => "
+ "send notification: testTrapv22",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag1, self()},
+ "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag1, [_]} ->
+ ok;
+ {snmp_targets, tag1, Addrs1} ->
+ ?line ?FAIL({bad_addrs, Addrs1})
+ after
+ 5000 ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag1, {got_response, _}} ->
+ ok;
+ {snmp_notification, tag1, {no_response, _}} ->
+ ?line ?FAIL(no_response)
+ after
+ 20000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+
+ %%
+ %% -- The rest is possibly erroneous...
+ %%
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag2, self()},
+ "standard inform", []),
+ ?line expect(2, {inform, false},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag2, [_]} ->
+ ok;
+ {snmp_targets, tag2, Addrs2} ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
+ ?line ?FAIL({bad_addrs, Addrs2})
+ after
+ 5000 ->
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag2, {got_response, _}} ->
+ ?line ?FAIL(got_response);
+ {snmp_notification, tag2, {no_response, _}} ->
+ ok
+ after
+ 240000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag2) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end.
+
+
+ma_v1_2_v2_trap(MA) ->
+ snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
+ {[ifIndex, 1], 1},
+ {[snmpTrapEnterprise, 0], [1,2,3]}]).
+
+
+ma_v1_2_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"},
+ {[snmpTrapEnterprise, 0], ?system}]).
+
+
+sa_v1_2_v2_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+sa_v1_2_v2_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+sa_v1_2_v2_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_bad_value() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 5}, % badValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, badValue, 2, any),
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_gen_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},{NewKeyc4, 2},
+ {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
+ ?line expect(1, genErr, 4, any),
+% The row might have been added; we don't know.
+% (as a matter of fact we do - it is added, because the agent
+% first sets its own vars, and then th SAs. Lets destroy it.
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(2, [{NewKeyc5, ?destroy}]).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_too_big() ->
+ g([[sa, [4,0]]]),
+ ?line expect(1, tooBig).
+
+%% Req. Klas1, system group, snmp group (v1/v2)
+next_across_sa() ->
+ gn([[sysDescr],[klas1,5]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[snmpInPkts, 0], any}]).
+
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
+%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
+%% Req. Klas3, Klas4
+undo_test() ->
+ s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
+ s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
+ ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
+% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+% it depends on which order the agent traverses the varbind list.
+% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
+% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
+ ?line expect(6, genErr, 2, any).
+
+%% Req. Klas3, Klas4
+bad_return() ->
+ g([[fStatus4,4],
+ [fName4,4]]),
+ ?line expect(4, genErr, 2, any),
+ g([[fStatus4,5],
+ [fName4,5]]),
+ ?line expect(5, genErr, 1, any),
+ g([[fStatus4,6],
+ [fName4,6]]),
+ ?line expect(6, genErr, 2, any),
+ gn([[fStatus4,7],
+ [fName4,7]]),
+ ?line expect(7, genErr, 2, any),
+ gn([[fStatus4,8],
+ [fName4,8]]),
+ ?line expect(8, genErr, 1, any),
+ gn([[fStatus4,9],
+ [fName4,9]]),
+ ?line expect(9, genErr, 2, any).
+
+
+%%%-----------------------------------------------------------------
+%%% Test the implementation of standard mibs.
+%%% We should *at least* try to GET all variables, just to make
+%%% sure the instrumentation functions work.
+%%% Note that many of the functions in the standard mib is
+%%% already tested by the normal tests.
+%%%-----------------------------------------------------------------
+
+
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v1.
+%% o Test the counters and control objects in SNMP-STANDARD-MIB
+%%-----------------------------------------------------------------
+snmp_standard_mib(suite) -> [];
+snmp_standard_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?DBG("snmp_standard_mib -> std_mib_init", []),
+ try_test(std_mib_init),
+
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v2),
+ ?DBG("snmp_standard_mib -> std_mib_read", []),
+ try_test(std_mib_read),
+ put(vsn, v1),
+
+ ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+ ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+ ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
+ try_test(std_mib_write, [], [{community, "public"}]),
+ ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
+ try_test(std_mib_asn_err),
+ ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
+ try_test(std_mib_c, [Bad]),
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ try_test(standard_mib_a),
+
+ ?DBG("snmp_standard_mib -> std_mib_finish", []),
+ try_test(std_mib_finish),
+ ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
+ try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_a() ->
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ ?line OutPkts2 = OutPkts + 1,
+ %% There are some more counters we could test here, but it's not that
+ %% important, since they are removed from SNMPv2-MIB.
+ ok.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_init() ->
+ %% disable authentication failure traps. (otherwise w'd get many of
+ %% them - this is also a test to see that it works).
+ s([{[snmpEnableAuthenTraps,0], 2}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_finish() ->
+ %% enable again
+ s([{[snmpEnableAuthenTraps,0], 1}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_test_finish() ->
+ %% force a authenticationFailure
+ std_mib_write(),
+ %% check that we got a trap
+ ?line expect(2, trap, [1,2,3], 4, 0, []).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_read() ->
+ ?DBG("std_mib_read -> entry", []),
+ g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
+ ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
+ ?line expect(1, timeout). % make sure we don't get a trap!
+
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_write() ->
+ ?DBG("std_mib_write -> entry", []),
+ s([{[sysLocation, 0], "new_value"}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_asn_err() ->
+ snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v2 and v3.
+%% o Test the counters and control objects in SNMPv2-MIB
+%%-----------------------------------------------------------------
+snmpv2_mib_2(suite) -> [];
+snmpv2_mib_2(Config) when list(Config) ->
+ ?LOG("snmpv2_mib_2 -> start",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?DBG("snmpv2_mib_2 -> standard mib init",[]),
+ try_test(std_mib_init),
+
+ ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
+ InBadVsns = try_test(std_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
+ put(vsn, v1),
+ try_test(std_mib_read),
+
+ ?DBG("snmpv2_mib_2 -> bad version read",[]),
+ put(vsn, v2),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+
+ ?DBG("snmpv2_mib_2 -> read with bad community",[]),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+
+ ?DBG("snmpv2_mib_2 -> write with public community",[]),
+ try_test(std_mib_write, [], [{community, "public"}]),
+
+ ?DBG("snmpv2_mib_2 -> asn err",[]),
+ try_test(std_mib_asn_err),
+
+ ?DBG("snmpv2_mib_2 -> check counters",[]),
+ try_test(std_mib_c, [Bad]),
+
+ ?DBG("snmpv2_mib_2 -> get som counters",[]),
+ try_test(snmpv2_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
+ try_test(std_mib_finish),
+
+ ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
+ "then disable auth traps",[]),
+ try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
+
+ ?LOG("snmpv2_mib_2 -> done",[]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_3(suite) -> [];
+snmpv2_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v1),
+ try_test(std_mib_read),
+ put(vsn, v3),
+ _Bad = try_test(std_mib_b, [InBadVsns]),
+ try_test(snmpv2_mib_a),
+
+ try_test(std_mib_finish).
+
+-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_test_finish() ->
+ %% force a authenticationFailure
+ ?DBG("ma_v2_inform -> write to std mib",[]),
+ std_mib_write(),
+
+ %% check that we got a trap
+ ?DBG("ma_v2_inform -> await trap",[]),
+ ?line expect(2, v2trap, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0], ?authenticationFailure}]),
+
+ %% and the the inform
+ ?DBG("ma_v2_inform -> await inform",[]),
+ ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0],?authenticationFailure}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_a() ->
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+
+ ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ InBadVsns.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_b(InBadVsns) ->
+ ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ ?line InBadVsns2 = InBadVsns + 1,
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+ ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
+ get_req(4, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
+ ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ get_req(1, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ ?line InBadCommunityNames2 = InBadCommunityNames + 1,
+ ?line InBadCommunityUses2 = InBadCommunityUses + 1,
+ ?line InASNErrs2 = InASNErrs + 1.
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_a() ->
+ ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
+ s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
+ ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
+ {[sysLocation, 0], "val2"}]),
+ s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
+ ?line expect(4, inconsistentValue, 2,
+ [{[sysLocation, 0], "val3"},
+ {[snmpSetSerialNo,0], SetSerial}]),
+ ?line ["val2"] = get_req(5, [[sysLocation,0]]).
+
+
+%%-----------------------------------------------------------------
+%% o Bad community uses/name is tested already
+%% in SNMPv2-MIB and STANDARD-MIB.
+%% o Test add/deletion of rows.
+%%-----------------------------------------------------------------
+snmp_community_mib(suite) -> [];
+snmp_community_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ try_test(snmp_community_mib),
+ ?line unload_master("SNMP-COMMUNITY-MIB").
+
+snmp_community_mib_2(X) -> snmp_community_mib(X).
+
+%% Req. SNMP-COMMUNITY-MIB
+snmp_community_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o Test engine boots / time
+%%-----------------------------------------------------------------
+snmp_framework_mib(suite) -> [];
+snmp_framework_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ try_test(snmp_framework_mib),
+ ?line unload_master("SNMP-FRAMEWORK-MIB").
+
+snmp_framework_mib_2(X) -> snmp_framework_mib(X).
+
+snmp_framework_mib_3(suite) -> [];
+snmp_framework_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(snmp_framework_mib).
+
+
+%% Req. SNMP-FRAMEWORK-MIB
+snmp_framework_mib() ->
+ ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ sleep(5000),
+ ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ if
+ EngineTime+7 < EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ EngineTime+4 > EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ true -> ok
+ end,
+ ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ [Boots] when integer(Boots) -> ok;
+ Else -> ?FAIL(Else)
+ end,
+ ok.
+
+%%-----------------------------------------------------------------
+%% o Test the counters
+%%-----------------------------------------------------------------
+snmp_mpd_mib_3(suite) -> [];
+snmp_mpd_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ UnknownPDUHs = try_test(snmp_mpd_mib_a),
+ try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
+ try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
+
+
+%% Req. SNMP-MPD-MIB
+snmp_mpd_mib_a() ->
+ ?line [UnknownSecs, InvalidMsgs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0]]),
+ Pdu = #pdu{type = 'get-request',
+ request_id = 23,
+ error_status = noError,
+ error_index = 0,
+ varbinds = []},
+ SPdu = #scopedPdu{contextEngineID = "agentEngine",
+ contextName = "",
+ data = Pdu},
+ ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
+ V3Hdr1 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [7],
+ msgSecurityModel = 23, % bad sec model
+ msgSecurityParameters = []},
+ V3Hdr2 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [6], % bad flag combination
+ msgSecurityModel = 3,
+ msgSecurityParameters = []},
+ Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
+ data = SPDUBytes},
+ Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
+ data = SPDUBytes},
+ ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
+ ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
+ snmp_test_mgr:send_bytes(MsgBytes1),
+ snmp_test_mgr:send_bytes(MsgBytes2),
+
+ ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0],
+ [snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownSecs2 = UnknownSecs + 1,
+ ?line InvalidMsgs2 = InvalidMsgs + 1,
+ UnknownPDUHs.
+
+-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
+snmp_mpd_mib_b() ->
+ g([[sysUpTime,0]]),
+ ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
+
+
+snmp_mpd_mib_c(UnknownPDUHs) ->
+ ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownPDUHs2 = UnknownPDUHs + 1.
+
+
+snmp_target_mib(suite) -> [];
+snmp_target_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ try_test(snmp_target_mib),
+ ?line unload_master("SNMP-TARGET-MIB").
+
+snmp_target_mib_2(X) -> snmp_target_mib(X).
+
+snmp_target_mib_3(X) -> snmp_target_mib(X).
+
+snmp_target_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+snmp_notification_mib(suite) -> [];
+snmp_notification_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ try_test(snmp_notification_mib),
+ ?line unload_master("SNMP-NOTIFICATION-MIB").
+
+snmp_notification_mib_2(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib_3(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o add/delete views and try them
+%% o try boundaries
+%%-----------------------------------------------------------------
+snmp_view_based_acm_mib(suite) -> [];
+snmp_view_based_acm_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master("Test2"),
+ snmp_view_based_acm_mib(),
+ ?line unload_master("Test2"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib() ->
+ snmpa:verbosity(net_if,trace),
+ snmpa:verbosity(master_agent,trace),
+ ?LOG("start snmp_view_based_acm_mib test",[]),
+ %% The user "no-rights" is present in USM, and is mapped to security
+ %% name 'no-rights", which is not present in VACM.
+ %% So, we'll add rights for it, try them and delete them.
+ %% We'll give "no-rights" write access to tDescr.0 and read access
+ %% to tDescr2.0
+ %% These are the options we'll use to the mgr
+ Opts = [{user, "no-rights"}, {community, "no-rights"}],
+ %% Find the valid secmodel, and one invalid secmodel.
+ {SecMod, InvSecMod} =
+ case get(vsn) of
+ v1 -> {?SEC_V1, ?SEC_V2C};
+ v2 -> {?SEC_V2C, ?SEC_USM};
+ v3 -> {?SEC_USM, ?SEC_V1}
+ end,
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Now, add a mapping from "no-rights" -> "no-rights-group"
+ GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
+ GRow1 =
+ [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
+ {GRow1Status, ?createAndGo}],
+ ?DBG("set '~p'",[GRow1]),
+ ?line try_test(do_set, [GRow1]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create a mapping for another sec model, and make sure it dosn't
+ %% give us access
+ GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
+ GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
+ {GRow2Status, ?createAndGo}],
+
+ ?DBG("set '~p'",[GRow2]),
+ ?line try_test(do_set, [GRow2]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [GRow2Status]),
+
+ RVName = "rv_name",
+ WVName = "wv_name",
+
+ %% Access row
+ ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
+ ARow1Status = [vacmAccessStatus, ARow1Idx],
+ ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
+ {[vacmAccessReadViewName, ARow1Idx], RVName},
+ {[vacmAccessWriteViewName, ARow1Idx], WVName},
+ {ARow1Status, ?createAndGo}],
+
+ %% This access row would give acces, if InvSecMod was valid.
+ ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
+ ARow2Status = [vacmAccessStatus, ARow2Idx],
+ ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
+ {[vacmAccessReadViewName, ARow2Idx], "internet"},
+ {[vacmAccessWriteViewName, ARow2Idx], "internet"},
+ {ARow2Status, ?createAndGo}],
+
+ ?line try_test(do_set, [ARow2]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [ARow2Status]),
+
+
+ %% Add valid row
+ ?line try_test(do_set, [ARow1]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create the view family
+ VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
+ VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
+ VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
+ VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
+ VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
+ VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
+ VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
+ VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
+
+ ?line try_test(add_row, [VRow1Status]),
+ ?line try_test(add_row, [VRow2Status]),
+ ?line try_test(add_row, [VRow3Status]),
+
+ %% We're supposed to have access now...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Change Row3 to Row4
+ ?line try_test(del_row, [VRow3Status]),
+ ?line try_test(add_row, [VRow4Status]),
+
+ %% We should still have access...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Delete rows
+ ?line try_test(del_row, [GRow1Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete rest of rows
+ ?line try_test(del_row, [ARow1Status]),
+ ?line try_test(del_row, [VRow1Status]),
+ ?line try_test(del_row, [VRow2Status]),
+ ?line try_test(del_row, [VRow4Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+ snmpa:verbosity(master_agent,log).
+
+do_set(Row) ->
+ s(Row),
+ expect(1, Row).
+
+add_row(RowStatus) ->
+ s([{RowStatus, ?createAndGo}]),
+ expect(1, [{RowStatus, ?createAndGo}]).
+
+del_row(RowStatus) ->
+ s([{RowStatus, ?destroy}]),
+ expect(1, [{RowStatus, ?destroy}]).
+
+
+
+use_no_rights() ->
+ g([[xDescr,0]]),
+ ?v1_2_3(expect(11, noSuchName, 1, any),
+ expect(12, [{[xDescr,0], noSuchObject}]),
+ expect(13, authorizationError, 1, any)),
+ g([[xDescr2,0]]),
+ ?v1_2_3(expect(21, noSuchName, 1, any),
+ expect(22, [{[xDescr2,0], noSuchObject}]),
+ expect(23, authorizationError, 1, any)),
+ gn([[xDescr]]),
+ ?v1_2_3(expect(31, noSuchName, 1, any),
+ expect(32, [{[xDescr], endOfMibView}]),
+ expect(33, authorizationError, 1, any)),
+ s([{[xDescr,0], "tryit"}]),
+ ?v1_2_3(expect(41, noSuchName, 1, any),
+ expect(42, noAccess, 1, any),
+ expect(43, authorizationError, 1, any)).
+
+
+use_rights() ->
+ g([[xDescr,0]]),
+ expect(1, [{[xDescr,0], any}]),
+ g([[xDescr2,0]]),
+ expect(2, [{[xDescr2,0], any}]),
+ s([{[xDescr,0], "tryit"}]),
+ expect(3, noError, 0, any),
+ g([[xDescr,0]]),
+ expect(4, [{[xDescr,0], "tryit"}]).
+
+mk_ln(X) ->
+ [length(X) | X].
+
+%%-----------------------------------------------------------------
+%% o add/delete users and try them
+%% o test all secLevels
+%% o test all combinations of protocols
+%% o try bad ops; check counters
+%%-----------------------------------------------------------------
+snmp_user_based_sm_mib_3(suite) -> [];
+snmp_user_based_sm_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ _AgentDir = ?config(agent_dir, Config),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+
+ %% The newUser used here already has VACM access.
+
+ %% Add a new user in the simplest way; just createAndGo
+ try_test(v3_sync, [[{usm_add_user1, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new user
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
+ DesKey1 = lists:sublist(ShaKey1, 16),
+
+ %% Change the new user's keys - 1
+ try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ MgrDir = ?config(mgr_dir, Config),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
+ DesKey2 = lists:sublist(ShaKey2, 16),
+
+ %% Change the new user's keys - 2
+ ?line try_test(v3_sync,
+ [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ reset_usm_mgr(MgrDir),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
+ ?line load_master("Test2"),
+ ?line try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Change the new user's keys - 3
+ ?line try_test(v3_sync,
+ [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new keys
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Try some read requests
+ ?line try_test(v3_sync, [[{usm_read, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Delete the new user
+ ?line try_test(v3_sync, [[{usm_del_user, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try some bad requests
+ ?line try_test(v3_sync, [[{usm_bad, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("SNMP-USER-BASED-SM-MIB").
+
+-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
+
+usm_add_user1() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+usm_use_user() ->
+ v2_proc().
+
+
+%% Change own public keys
+usm_key_change1(ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_shaxxxxxxxxxx",
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_desxxxxxx",
+ DesKey),
+ Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change own private keys
+usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change other's public keys
+usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
+ s(Vbs1),
+ ?line expect(1, noAccess, 1, any),
+ Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs2),
+ ?line expect(2, noAccess, 1, any),
+
+
+ Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs3),
+ ?line expect(1, Vbs3).
+
+usm_read() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ?line g([[usmUserSecurityName, NewRowIndex],
+ [usmUserCloneFrom, NewRowIndex],
+ [usmUserAuthKeyChange, NewRowIndex],
+ [usmUserOwnAuthKeyChange, NewRowIndex],
+ [usmUserPrivKeyChange, NewRowIndex],
+ [usmUserOwnPrivKeyChange, NewRowIndex]]),
+ ?line expect(1,
+ [{[usmUserSecurityName, NewRowIndex], "newUser"},
+ {[usmUserCloneFrom, NewRowIndex], [0,0]},
+ {[usmUserAuthKeyChange, NewRowIndex], ""},
+ {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
+ {[usmUserPrivKeyChange, NewRowIndex], ""},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
+ ok.
+
+
+
+usm_del_user() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
+
+-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
+
+-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
+
+-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
+
+-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
+
+-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
+
+usm_bad() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, inconsistentName, 1, any),
+
+ RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs2),
+ ?line expect(2, wrongValue, 1, any),
+
+ RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs3),
+ ?line expect(3, Vbs3),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
+ ?line expect(4, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
+ ?line expect(5, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
+ ?line expect(6, wrongValue, 1, any),
+ ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
+ ?line expect(7, wrongValue, 1, any),
+
+ Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs4),
+ ?line expect(1, Vbs4),
+
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Loop through entire MIB, to make sure that all instrum. funcs
+%% works.
+%% Load all std mibs that are not loaded by default.
+%%-----------------------------------------------------------------
+loop_mib(suite) -> [];
+loop_mib(Config) when list(Config) ->
+ ?LOG("loop_mib -> initiate case",[]),
+ %% snmpa:verbosity(master_agent,debug),
+ %% snmpa:verbosity(mib_server,info),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?DBG("loop_mib -> try",[]),
+ try_test(loop_mib_1),
+ ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ %% snmpa:verbosity(master_agent,log),
+ %% snmpa:verbosity(mib_server,silence),
+ ?LOG("loop_mib -> done",[]).
+
+
+loop_mib_2(suite) -> [];
+loop_mib_2(Config) when list(Config) ->
+ ?LOG("loop_mib_2 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_2 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_2 -> load mibs",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_2 -> unload mibs",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?LOG("loop_mib_2 -> done",[]).
+
+
+loop_mib_3(suite) -> [];
+loop_mib_3(Config) when list(Config) ->
+ ?LOG("loop_mib_3 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_3 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_3 -> load mibs",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_3 -> unload mibs",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?LOG("loop_mib_3 -> done",[]).
+
+
+%% Req. As many mibs all possible
+loop_mib_1() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_1([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_1(Oid, N) ->
+ ?DBG("loop_it_1 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_1 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_1 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_1(NOid, N+1);
+ #pdu{type='get-response', error_status=noSuchName, error_index=1,
+ varbinds=[_]} ->
+ ?DBG("loop_it_1 -> done",[]),
+ N;
+
+ #pdu{type = Type, error_status = Err, error_index = Idx,
+ varbinds = Vbs} ->
+ exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
+ end.
+
+%% Req. As many mibs all possible
+loop_mib_2() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_2([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_2(Oid, N) ->
+ ?DBG("loop_it_2 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p",[NOid]),
+ N;
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_2 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_2(NOid, N+1)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+
+
+
+
+%% These are (ticket) test cases where the initiation has to be done
+%% individually.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1128
+%% Slogan: Bug in handling of createAndWait set-requests.
+%%-----------------------------------------------------------------
+otp_1128(suite) -> [];
+otp_1128(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1128),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1128_2(X) -> otp_1128(X).
+
+otp_1128_3(X) -> otp_1128(X).
+
+otp_1128() ->
+ io:format("Testing bug reported in ticket OTP-1128...~n"),
+
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+
+ s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(29, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(31, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(32, [{NewKeyc5, ?destroy}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1129, OTP-1169
+%% Slogan: snmpa:int_to_enum crashes on bad oids
+%%-----------------------------------------------------------------
+otp_1129(suite) -> [];
+otp_1129(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ try_test(otp_1129_i, [node()]),
+ ?line unload_master("Klas3").
+
+otp_1129_2(X) -> otp_1129(X).
+
+otp_1129_3(X) -> otp_1129(X).
+
+otp_1129_i(MaNode) ->
+ io:format("Testing bug reported in ticket OTP-1129...~n"),
+ false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
+ false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1131
+%% Slogan: Agent crashes / erlang node halts if RowIndex in a
+%% setrequest is of bad type, e.g. an INDEX {INTEGER},
+%% and RowIdenx [3,2].
+%%-----------------------------------------------------------------
+otp_1131(suite) -> [];
+otp_1131(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas1"),
+ try_test(otp_1131),
+ ?line unload_master("Klas1").
+
+otp_1131_2(X) -> otp_1131(X).
+
+otp_1131_3(X) -> otp_1131(X).
+
+otp_1131() ->
+ io:format("Testing bug reported in ticket OTP-1131...~n"),
+ s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
+ {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1162
+%% Slogan: snmp_agent can't handle wrongValue from instrum.func
+%%-----------------------------------------------------------------
+otp_1162(suite) -> [];
+otp_1162(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ try_test(otp_1162),
+ stop_subagent(SA).
+
+otp_1162_2(X) -> otp_1162(X).
+
+otp_1162_3(X) -> otp_1162(X).
+
+otp_1162() ->
+ s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
+ ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1222
+%% Slogan: snmp agent crash if faulty index is returned from instrum
+%%-----------------------------------------------------------------
+otp_1222(suite) -> [];
+otp_1222(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ ?line load_master("Klas4"),
+ try_test(otp_1222),
+ ?line unload_master("Klas3"),
+ ?line unload_master("Klas4").
+
+otp_1222_2(X) -> otp_1222(X).
+
+otp_1222_3(X) -> otp_1222(X).
+
+otp_1222() ->
+ io:format("Testing bug reported in ticket OTP-1222...~n"),
+ s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
+ ?line expect(1, genErr, 0, any),
+ s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
+ ?line expect(2, genErr, 0, any).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1298
+%% Slogan: Negative INTEGER values are treated as positive.
+%%-----------------------------------------------------------------
+otp_1298(suite) -> [];
+otp_1298(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1298),
+ ?line unload_master("Klas2").
+
+otp_1298_2(X) -> otp_1298(X).
+
+otp_1298_3(X) -> otp_1298(X).
+
+otp_1298() ->
+ io:format("Testing bug reported in ticket OTP-1298...~n"),
+ s([{[fint,0], -1}]),
+ ?line expect(1298, [{[fint,0], -1}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1331
+%% Slogan: snmp_generic should return noError when deleting non-ex row
+%%-----------------------------------------------------------------
+otp_1331(suite) -> [];
+otp_1331(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1331),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1331_2(X) -> otp_1331(X).
+
+otp_1331_3(X) -> otp_1331(X).
+
+otp_1331() ->
+ NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(1, [{NewKeyc5, ?destroy}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1338
+%% Slogan: snmp bug in initialisation of default values for mnesia tabs
+%%-----------------------------------------------------------------
+otp_1338(suite) -> [];
+otp_1338(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1338),
+ ?line unload_master("Klas2").
+
+otp_1338_2(X) -> otp_1338(X).
+
+otp_1338_3(X) -> otp_1338(X).
+
+otp_1338() ->
+ s([{[kStatus2, 7], i, ?createAndGo}]),
+ ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
+ g([[kName2, 7]]),
+ ?line expect(2, [{[kName2, 7], "JJJ"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1342
+%% Slogan: default impl of snmp table can't handle bad index access,
+%% Set when INDEX is read-write gets into an infinite loop!
+%%-----------------------------------------------------------------
+otp_1342(suite) -> [];
+otp_1342(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas4"),
+ try_test(otp_1342),
+ ?line unload_master("Klas4").
+
+otp_1342_2(X) -> otp_1342(X).
+
+otp_1342_3(X) -> otp_1342(X).
+
+otp_1342() ->
+ s([{[fIndex5, 1], i, 1},
+ {[fName5, 1], i, 3},
+ {[fStatus5, 1], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1366
+%% Slogan: snmp traps not sent to all managers
+%% Note: NYI! We need a way to tell the test server that we need
+%% mgrs on two different machines.
+%%-----------------------------------------------------------------
+otp_1366(suite) -> [];
+otp_1366(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1366),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1366_2(X) -> otp_1366(X).
+
+otp_1366_3(X) -> otp_1366(X).
+
+otp_1366() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ 'NYI'.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2776
+%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
+%%-----------------------------------------------------------------
+otp_2776(suite) -> [];
+otp_2776(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_2776).
+
+otp_2776_2(X) -> otp_2776(X).
+
+otp_2776_3(X) -> otp_2776(X).
+
+otp_2776() ->
+ io:format("Testing bug reported in ticket OTP-2776...~n"),
+
+ Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
+ Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
+ Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
+ Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
+ Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
+ Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
+ Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
+ Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
+ Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
+ Dt10_invalid = [],
+ Dt11_invalid = [kalle,hobbe],
+ L = [{ 1, true, Dt01_valid},
+ { 2, true, Dt02_valid},
+ { 3, true, Dt03_valid},
+ { 4, false, Dt04_invalid},
+ { 5, true, Dt05_valid},
+ { 6, true, Dt06_valid},
+ { 7, false, Dt07_invalid},
+ { 8, true, Dt08_valid},
+ { 9, false, Dt09_invalid},
+ {10, false, Dt10_invalid},
+ {11, false, Dt11_invalid}],
+
+ ?line ok = validate_dat(L).
+
+
+validate_dat(L) -> validate_dat(L,[]).
+
+validate_dat([],V) ->
+ Fun = fun({_,X}) -> case X of
+ ok -> false;
+ _ -> true
+ end
+ end,
+ validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
+validate_dat([{Id,E,Dat}|T],V) ->
+ validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
+
+validate_dat1([]) -> ok;
+validate_dat1(L) -> {error,L}.
+
+validate_dat2(Id, E, Dat) ->
+ Res = case {E,snmp:validate_date_and_time(Dat)} of
+ {E,E} -> ok;
+ {E,A} -> {E,A}
+ end,
+ {Id, Res}.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2979
+%% Slogan: get-next on more than 1 column in an empty table
+%% returns bad response.
+%%-----------------------------------------------------------------
+otp_2979(suite) -> [];
+otp_2979(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Test1"),
+ ?line init_old(),
+ try_test(otp_2979),
+ ?line unload_master("Test1").
+
+otp_2979_2(X) -> otp_2979(X).
+
+otp_2979_3(X) -> otp_2979(X).
+
+otp_2979() ->
+ gn([[sparseDescr], [sparseStatus]]),
+ ?line expect(1, [{[sparseStr,0], "slut"},
+ {[sparseStr,0], "slut"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3187
+%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% endOfTable - should return value.
+%%-----------------------------------------------------------------
+otp_3187(suite) -> [];
+otp_3187(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ otp_3187(),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+otp_3187_2(X) -> otp_3187(X).
+
+otp_3187_3(X) -> otp_3187(X).
+
+otp_3187() ->
+ ?line Elements =
+ snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
+ lists:foreach(fun(E) ->
+ ?line if E == endOfTable ->
+ ?FAIL(endOfTable);
+ true -> ok
+ end
+ end, Elements).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3542
+%% Slogan:
+%%-----------------------------------------------------------------
+otp_3542(suite) -> [];
+otp_3542(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_3542).
+
+otp_3542() ->
+ io:format("SNMP v3 discovery...~n"),
+ ?line Res = snmp_test_mgr:d(),
+ io:format("SNMP v3 discovery result: ~p~n",[Res]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3725
+%% Slogan: Slow response time on snmpa:int_to_enum
+%%-----------------------------------------------------------------
+otp_3725(suite) -> [];
+otp_3725(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_3725_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+otp_3725_test(MaNode) ->
+ io:format("Testing feature requested in ticket OTP-3725...~n"),
+ ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
+ ?DBG("otp_3725_test -> Db = ~p",[Db]),
+
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [Db, intAgentIpAddress]),
+ ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
+ [Db,OID]),
+ ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [Db, [1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, 'RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-4394
+%% Slogan: Target mib tag list check invalid
+%%-----------------------------------------------------------------
+
+
+
+init_otp_4394(Config) when list(Config) ->
+ ?DBG("init_otp_4394 -> entry with"
+ "~n Config: ~p", [Config]),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ MasterAgentVerbosity = {master_agent_verbosity, trace},
+ NetIfVerbosity = {net_if_verbosity, trace},
+ Opts = [MasterAgentVerbosity,NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config,Opts)].
+
+otp_4394_config(AgentDir, MgrDir, Ip0) ->
+ ?DBG("otp_4394_config -> entry with"
+ "~n AgentDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ Vsn = [v1],
+ Ip = tuple_to_list(Ip0),
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?TRAP_UDP, Ip, 4000,
+ "OTP-4394 test"),
+ ?line case update_usm(Vsn, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsn, MgrDir);
+ false ->
+ ?line ok
+ end,
+ C1 = {"a", "all-rights", "initial", "", "pc"},
+ C2 = {"c", "secret", "secret_name", "", "secret_tag"},
+ ?line write_community_conf(AgentDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentDir),
+ Ta1 = {"shelob v1",
+ [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ "pc1",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [],
+ 2048},
+ Ta2 = {"bifur v1",
+ [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ "pc2",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [], 2048},
+ ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentDir, Vsn),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+
+
+finish_otp_4394(Config) when list(Config) ->
+ ?DBG("finish_otp_4394 -> entry", []),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ erase(mgr_node),
+ lists:keydelete(vsn, 1, C1).
+
+otp_4394_test(suite) -> [];
+otp_4394_test(Config) ->
+ ?DBG("otp_4394_test -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_4394_test1),
+ ?DBG("otp_4394_test -> done", []),
+ ok.
+
+otp_4394_test1() ->
+ ?DBG("otp_4394_test1 -> entry", []),
+ gn([[1,1]]),
+ Res =
+ case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
+ %% {error, 1, {"?",[]}, {"~w",[timeout]}}
+ {error, 1, _, {_, [timeout]}} ->
+ ?DBG("otp_4394_test1 -> expected result: timeout", []),
+ ok;
+ Else ->
+ Else
+ end,
+ ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
+ Res.
+
+
+%%%--------------------------------------------------
+%%% Used to test the standard mib with our
+%%% configuration.
+%%%--------------------------------------------------
+run(F, A, Opts) ->
+ M = get(mib_dir),
+ Dir = get(mgr_dir),
+ User = snmp_misc:get_option(user, Opts, "all-rights"),
+ SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
+ EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
+ CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
+ Community = snmp_misc:get_option(community, Opts, "all-rights"),
+ ?DBG("run -> start crypto app",[]),
+ Crypto = case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ ?CRYPTO_START()
+ end,
+ ?DBG("run -> Crypto: ~p",[Crypto]),
+ catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ ?DBG("run -> config:~n"
+ "\tM: ~p~n"
+ "\tDir: ~p~n"
+ "\tUser: ~p~n"
+ "\tSecLevel: ~p~n"
+ "\tEngineID: ~p~n"
+ "\tCtxEngineID: ~p~n"
+ "\tCommunity: ~p~n"
+ "\tStdM: ~p",
+ [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
+ case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
+ {packet_server_debug,true},
+ {debug,true},
+ {agent, get(master_host)},
+ {agent_udp, 4000},
+ {trap_udp, 5000},
+ {recbuf,65535},
+ quiet,
+ get(vsn),
+ {community, Community},
+ {user, User},
+ {sec_level, SecLevel},
+ {engine_id, EngineID},
+ {context_engine_id, CtxEngineID},
+ {dir, Dir},
+ {mibs, mibs(StdM, M)}]) of
+ {ok, _Pid} ->
+ Res = apply(?MODULE, F, A),
+ catch snmp_test_mgr:stop(),
+ Res;
+ Err ->
+ io:format("Error starting manager: ~p\n", [Err]),
+ catch snmp_test_mgr:stop(),
+ ?line exit({mgr_start, Err})
+ end.
+
+
+mibs(StdMibDir,MibDir) ->
+ [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
+ join(MibDir, "OLD-SNMPEA-MIB.bin"),
+ join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
+ join(StdMibDir, "SNMP-MPD-MIB"),
+ join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
+ join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
+ join(StdMibDir, "SNMP-TARGET-MIB"),
+ join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
+ join(MibDir, "Klas1.bin"),
+ join(MibDir, "Klas2.bin"),
+ join(MibDir, "Klas3.bin"),
+ join(MibDir, "Klas4.bin"),
+ join(MibDir, "SA-MIB.bin"),
+ join(MibDir, "TestTrap.bin"),
+ join(MibDir, "Test1.bin"),
+ join(MibDir, "Test2.bin"),
+ join(MibDir, "TestTrapv2.bin")].
+
+join(D,F) ->
+ filename:join(D,F).
+
+%% string used in index
+is(S) -> [length(S) | S].
+
+try_test(Func) ->
+ call(get(mgr_node), ?MODULE, run, [Func, [], []]).
+
+try_test(Func, A) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, []]).
+
+try_test(Func, A, Opts) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
+
+call(N,M,F,A) ->
+ ?DBG("call -> entry with~n"
+ " N: ~p~n"
+ " M: ~p~n"
+ " F: ~p~n"
+ " A: ~p~n"
+ " when~n"
+ " get(): ~p",
+ [N,M,F,A,get()]),
+ spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
+ receive
+ {done, {'EXIT', Rn}, Loc} ->
+ ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
+ put(test_server_loc, Loc),
+ exit(Rn);
+ {done, Ret, Zed} ->
+ ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
+ Ret
+ end.
+
+wait(From, Env, M, F, A) ->
+ ?DBG("wait -> entry with ~n"
+ "\tFrom: ~p~n"
+ "\tEnv: ~p",[From,Env]),
+ lists:foreach(fun({K,V}) -> put(K,V) end, Env),
+ Rn = (catch apply(M, F, A)),
+ ?DBG("wait -> Rn: ~n~p", [Rn]),
+ From ! {done, Rn, get(test_server_loc)},
+ exit(Rn).
+
+expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
+expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
+expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
+expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
+
+get_req(Id, Vars) ->
+ ?DBG("get_req -> entry with~n"
+ "\tId: ~p~n"
+ "\tVars: ~p",[Id,Vars]),
+ g(Vars),
+ ?DBG("get_req -> await response",[]),
+ {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
+ ?DBG("get_req -> response: ~p",[Val]),
+ Val.
+
+get_next_req(Vars) ->
+ ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
+ gn(Vars),
+ ?DBG("get_next_req -> await response",[]),
+ Response = snmp_test_mgr:receive_response(),
+ ?DBG("get_next_req -> response: ~p",[Response]),
+ Response.
+
+
+
+start_node(Name) ->
+ ?LOG("start_node -> entry with Name: ~p",[Name]),
+ M = list_to_atom(?HOSTNAME(node())),
+ ?DBG("start_node -> M: ~p",[M]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ ?DBG("start_node -> Pa: ~p",[Pa]),
+
+ Args = case init:get_argument('CC_TEST') of
+ {ok, [[]]} ->
+ " -pa /clearcase/otp/libraries/snmp/ebin ";
+ {ok, [[Path]]} ->
+ " -pa " ++ Path;
+ error ->
+ ""
+ end,
+ %% Do not use start_link!!! (the proc that calls this one is tmp)
+ ?DBG("start_node -> Args: ~p~n",[Args]),
+ A = Args ++ " -pa " ++ Pa,
+ case (catch ?START_NODE(Name, A)) of
+ {ok, Node} ->
+ %% Tell the test_server to not clean up things it never started.
+ ?DBG("start_node -> Node: ~p",[Node]),
+ {ok, Node};
+ Else ->
+ ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
+ ?line ?FAIL(Else)
+ end.
+
+
+stop_node(Node) ->
+ ?LOG("stop_node -> Node: ~p",[Node]),
+ rpc:cast(Node, erlang, halt, []).
+
+p(X) ->
+ io:format(user, X++"\n", []).
+
+sleep(X) ->
+ receive
+ after
+ X -> ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Configuration
+%%%-----------------------------------------------------------------
+config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
+ ?TRAP_UDP, AIp, 4000,
+ "test"),
+ ?line case update_usm(Vsns, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsns, MgrDir);
+ false ->
+ ?line ok
+ end,
+ ?line update_community(Vsns, AgentDir),
+ ?line update_vacm(Vsns, AgentDir),
+ ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentDir, Vsns),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+delete_files(Config) ->
+ Dir = ?config(agent_dir, Config),
+ {ok, List} = file:list_dir(Dir),
+ lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
+ List).
+
+update_usm(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+update_usm_mgr(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.conf"),
+ filename:join(Dir,"usm.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ file:close(Fid).
+
+reset_usm_mgr(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.old"),
+ filename:join(Dir,"usm.conf")).
+
+
+update_community([v3], _Dir) -> ok;
+update_community(_, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
+ []),
+ file:close(Fid).
+
+
+-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
+update_vacm(_Vsn, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
+ ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
+ "~w, excluded, null}.\n", [?tDescr_instance]),
+ file:close(Fid).
+
+
+vacm_ver(v1) -> v1;
+vacm_ver(v2) -> v2c;
+vacm_ver(v3) -> usm.
+
+
+write_community_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
+ ok = write_community_conf1(Fid, Confs),
+ file:close(Fid).
+
+write_community_conf1(_, []) ->
+ ok;
+write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
+ [ComIdx, ComName, SecName, CtxName, TransTag]),
+ write_community_conf1(Fid, Confs).
+
+
+write_target_addr_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ ok = write_target_addr_conf1(Fid, Confs),
+ file:close(Fid).
+
+
+write_target_addr_conf1(_, []) ->
+ ok;
+write_target_addr_conf1(Fid,
+ [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
+ [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz]),
+ write_target_addr_conf1(Fid, Confs).
+
+write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ ok = io:format(Fid,
+ "{\"~s\", ~w, ~w, 1500, 3, "
+ "\"std_trap\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP, mk_param(Vsn)]),
+ case Vsn of
+ v1 -> ok;
+ v2 ->
+ ok = io:format(Fid,
+ "{\"~s.2\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)]);
+ v3 ->
+ ok = io:format(Fid,
+ "{\"~s.3\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\", "
+ "\"mgrEngine\", [], 1024}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)])
+ end
+ end,
+ Vsns),
+ file:close(Fid).
+
+mk_param(v1) -> "target_v1";
+mk_param(v2) -> "target_v2";
+mk_param(v3) -> "target_v3".
+
+mk_ip([A,B,C,D], Vsn) ->
+ io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
+
+
+rewrite_target_addr_conf(Dir,NewPort) ->
+ TAFile = filename:join(Dir, "target_addr.conf"),
+ ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
+ case file:read_file_info(TAFile) of
+ {ok, _} -> ok;
+ {error, R} -> ?ERR("failure reading file info of "
+ "target address config file: ~p",[R]),
+ ok
+ end,
+
+ ?line [TrapAddr|Addrs] =
+ snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
+
+ ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
+
+ NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
+
+ ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
+
+ ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
+ filename:join(Dir,"target_addr.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+
+ ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
+
+ file:close(Fid).
+
+rewrite_target_addr_conf1(O) ->
+ {ok,O}.
+
+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) ->
+ ?LOG("rewrite_target_addr_conf2 -> entry with "
+ "~n O: ~p",[O]),
+ O.
+
+
+rewrite_target_addr_conf3(_,[]) -> ok;
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
+ ParamName,EngineId}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % ParamsName
+ "\"~s\"}.", % EngineId
+ [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
+ rewrite_target_addr_conf3(Fid,T);
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
+ ParamName,EngineId,TMask,MMS}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % TagList
+ "\"~s\", " % ParamsName
+ "\"~s\"," % EngineId
+ "~p, " % TMask
+ "~p}.", % MMS
+ [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
+ EngineId,TMask,MMS]),
+ rewrite_target_addr_conf3(Fid,T).
+
+reset_target_addr_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
+ filename:join(Dir,"target_addr.conf")).
+
+write_target_params_conf(Dir, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ MP = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> v3
+ end,
+ SM = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> usm
+ end,
+ ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
+ "\"all-rights\", noAuthNoPriv}.~n",
+ [Vsn, MP, SM])
+ end,
+ Vsns),
+ file:close(Fid).
+
+rewrite_target_params_conf(Dir, SecName, SecLevel) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
+ filename:join(Dir,"target_params.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
+ [SecName, SecLevel]),
+ file:close(Fid).
+
+reset_target_params_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.old"),
+ filename:join(Dir,"target_params.conf")).
+
+write_notify_conf(Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
+ ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
+ ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
+ file:close(Fid).
+
+ver_to_trap_str([v1]) -> "v1";
+ver_to_trap_str([v2]) -> "v2";
+% default is to use the latest snmp version
+ver_to_trap_str([v1,v2]) -> "v2".
+
+
+
+write_view_conf(Dir) ->
+ {ok, Fid} = file:open(a(Dir,"view.conf"),write),
+ ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
+ ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
+ file:close(Fid).
+
+a(A,B) -> lists:append(A,B).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+copy_file(From, To) ->
+ {ok, Bin} = file:read_file(From),
+ ok = file:write_file(To, Bin).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+display_memory_usage() ->
+ Info = snmpa:info(snmp_master_agent),
+ TreeSize = lists_key1search(tree_size_bytes, Info),
+ ProcMem = lists_key1search(process_memory, Info),
+ MibDbSize = lists_key1search([db_memory,mib], Info),
+ NodeDbSize = lists_key1search([db_memory,node], Info),
+ TreeDbSize = lists_key1search([db_memory,tree], Info),
+ ?INF("Memory usage: "
+ "~n Tree size: ~p"
+ "~n Process memory size: ~p"
+ "~n Mib db size: ~p"
+ "~n Node db size: ~p"
+ "~n Tree db size: ~p",
+ [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
+
+lists_key1search([], Res) ->
+ Res;
+lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ lists_key1search(Keys, Val);
+ false ->
+ undefined
+ end;
+lists_key1search(Key, List) when atom(Key) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ Val;
+ false ->
+ undefined
+ end.
+
+
+regs() ->
+ lists:sort(registered()).
diff --git a/lib/snmp/test/exp/snmp_agent_mt_test.erl b/lib/snmp/test/exp/snmp_agent_mt_test.erl
new file mode 100644
index 0000000000..d62bc6c2e7
--- /dev/null
+++ b/lib/snmp/test/exp/snmp_agent_mt_test.erl
@@ -0,0 +1,5649 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmp_agent_mt_test).
+
+%% TODO
+%% * Test fault-tolerance (kill master etc)
+%%
+
+-compile(export_all).
+
+-define(application, snmp).
+
+-include_lib("kernel/include/file.hrl").
+-include_lib("test_server/include/test_server.hrl").
+-include("snmp_test_lib.hrl").
+-define(SNMP_USE_V3, true).
+-include_lib("snmp/include/snmp_types.hrl").
+%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
+
+
+-define(klas1, [1,3,6,1,2,1,7]).
+-define(klas2, [1,3,6,1,2,1,9]).
+-define(klas3, [1,3,6,1,2,1,8,1]).
+-define(klas4, [1,3,6,1,2,1,8,4]).
+-define(sa, [1,3,6,1,4,1,193,2]).
+-define(system, [1,3,6,1,2,1,1]).
+-define(snmp, [1,3,6,1,2,1,11]).
+-define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
+-define(ericsson, [1,3,6,1,4,1,193]).
+-define(testTrap, [1,3,6,1,2,1,15,0]).
+-define(xDescr, [1,3,6,1,2,1,17,1]).
+-define(xDescr2, [1,3,6,1,2,1,17,2]).
+
+-define(active, 1).
+-define(notInService, 2).
+-define(notReady, 3).
+-define(createAndGo, 4).
+-define(createAndWait, 5).
+-define(destroy, 6).
+
+-define(TRAP_UDP, 5000).
+
+-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
+
+-define(str(X), snmp_pdus:bits_to_str(X)).
+
+-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
+ [?LINE, self()]),
+ receive cont -> ok end
+ end).
+
+
+-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
+-define(v1_2(V1,V2),
+ case get(vsn) of
+ v1 -> V1;
+ _ -> V2
+ end).
+
+-define(v1_2_3(V1,V2,V3),
+ case get(vsn) of
+ v1 -> V1;
+ v2 -> V2;
+ _ -> V3
+ end).
+
+all() ->
+[cases()].
+
+groups() ->
+ [{mib_storage, [],
+ [{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()},
+ {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]},
+ {standard_mibs, [],
+ [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]},
+ {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]},
+ {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]},
+ {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]},
+ {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]},
+ {tickets, [], [{group, otp_4394}]},
+ {otp_4394, [], [otp_4394_test]}].
+
+init_per_group(otp_4394, Config) ->
+ init_otp_4394(Config);
+init_per_group(v2_inform, Config) ->
+ init_v2_inform(Config);
+init_per_group(multiple_reqs_2, Config) ->
+ init_mul(Config);
+init_per_group(multiple_reqs, Config) ->
+ init_mul(Config);
+init_per_group(test_multi_threaded, Config) ->
+ init_mt(Config);
+init_per_group(test_v3, Config) ->
+ init_v3(Config);
+init_per_group(test_v1_v2, Config) ->
+ init_v1_v2(Config);
+init_per_group(test_v2, Config) ->
+ init_v2(Config);
+init_per_group(test_v1, Config) ->
+ init_v1(Config);
+init_per_group(mib_storage_varm_mnesia, Config) ->
+ init_varm_mib_storage_mnesia(Config);
+init_per_group(mib_storage_varm_dets, Config) ->
+ init_varm_mib_storage_dets(Config);
+init_per_group(mib_storage_size_check_mnesia, Config) ->
+ init_size_check_msm(Config);
+init_per_group(mib_storage_size_check_dets, Config) ->
+ init_size_check_msd(Config);
+init_per_group(mib_storage_size_check_ets, Config) ->
+ init_size_check_mse(Config);
+init_per_group(mib_storage_mnesia, Config) ->
+ init_mib_storage_mnesia(Config);
+init_per_group(mib_storage_dets, Config) ->
+ init_mib_storage_dets(Config);
+init_per_group(mib_storage_ets, Config) ->
+ init_mib_storage_ets(Config);
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(otp_4394, Config) ->
+ finish_otp_4394(Config);
+end_per_group(v2_inform, Config) ->
+ finish_v2_inform(Config);
+end_per_group(multiple_reqs_2, Config) ->
+ finish_mul(Config);
+end_per_group(multiple_reqs, Config) ->
+ finish_mul(Config);
+end_per_group(test_multi_threaded, Config) ->
+ finish_mt(Config);
+end_per_group(test_v3, Config) ->
+ finish_v3(Config);
+end_per_group(test_v1_v2, Config) ->
+ finish_v1_v2(Config);
+end_per_group(test_v2, Config) ->
+ finish_v2(Config);
+end_per_group(test_v1, Config) ->
+ finish_v1(Config);
+end_per_group(mib_storage_varm_mnesia, Config) ->
+ finish_varm_mib_storage_mnesia(Config);
+end_per_group(mib_storage_varm_dets, Config) ->
+ finish_varm_mib_storage_dets(Config);
+end_per_group(mib_storage_size_check_mnesia, Config) ->
+ finish_size_check_msm(Config);
+end_per_group(mib_storage_size_check_dets, Config) ->
+ finish_size_check_msd(Config);
+end_per_group(mib_storage_size_check_ets, Config) ->
+ finish_size_check_mse(Config);
+end_per_group(mib_storage_mnesia, Config) ->
+ finish_mib_storage_mnesia(Config);
+end_per_group(mib_storage_dets, Config) ->
+ finish_mib_storage_dets(Config);
+end_per_group(mib_storage_ets, Config) ->
+ finish_mib_storage_ets(Config);
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+cases() ->
+case ?OSTYPE() of
+ vxworks ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_multi_threaded},
+ {group, mib_storage}, {group, tickets}];
+ _Else ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_v3},
+ {group, test_multi_threaded}, {group, mib_storage},
+ {group, tickets}]
+end.
+
+
+%%%-----------------------------------------------------------------
+%%% The test case structure is as follows:
+%%%
+%%% init_all - starts mnesia,
+%%%
+%%% init_v1 - starts agent
+%%% simple
+%%% big - e.g. starts/stops subagent, load/unloads mibs
+%%% init_mul
+%%% mul_get
+%%% mul_set
+%%% <etc>
+%%% finish_mul
+%%% <etc>
+%%% finish_v1
+%%%
+%%% init_v2 - starts agent
+%%% finish_v2
+%%%
+%%% init_bilingual - starts agent
+%%% finish_bilingual
+%%%
+%%% finish_all
+%%%
+%%% There is still one problem with these testsuites. If one test
+%%% fails, it may not be possible to run some other cases, as it
+%%% may have e.g. created some row or loaded some table, that it
+%%% didn't undo (since it failed).
+%%%-----------------------------------------------------------------
+
+init_all(Config0) when list(Config0) ->
+ ?LOG("init_all -> entry with"
+ "~n Config0: ~p",[Config0]),
+
+ %% --
+ %% Fix config:
+ %%
+
+ DataDir0 = ?config(data_dir, Config0),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config0),
+ Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+
+ %% --
+ %% Start nodes
+ %%
+
+ ?line {ok, SaNode} = start_node(snmp_sa),
+ ?line {ok, MgrNode} = start_node(snmp_mgr),
+
+
+ %% --
+ %% Create necessary files
+ %%
+
+ Dir = ?config(priv_dir, Config),
+ ?DBG("init_all -> Dir ~p", [Dir]),
+
+ DataDir = ?config(data_dir, Config),
+ ?DBG("init_all -> DataDir ~p", [DataDir]),
+
+ file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+
+ file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+
+ file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
+ ?DBG("init_all -> SaDir ~p", [SaDir]),
+
+
+ %% --
+ %% Start and initiate mnesia
+ %%
+
+ ?DBG("init_all -> load application mnesia", []),
+ ?line ok = application:load(mnesia),
+
+ ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
+ ?line ok = rpc:call(SaNode, application, load, [mnesia]),
+
+ ?DBG("init_all -> application mnesia: set_env dir",[]),
+ ?line application_controller:set_env(mnesia, dir,
+ filename:join(Dir, "Mnesia1")),
+
+ ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(Dir, "Mnesia2")]),
+
+ ?DBG("init_all -> create mnesia schema",[]),
+ ?line ok = mnesia:create_schema([SaNode, node()]),
+
+ ?DBG("init_all -> start application mnesia",[]),
+ ?line ok = application:start(mnesia),
+
+ ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
+ ?line ok = rpc:call(SaNode, application, start, [mnesia]),
+ Ip = ?LOCALHOST(),
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {agent_dir, AgentDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {mib_dir, DataDir},
+ {ip, Ip} |
+ Config].
+
+finish_all(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ stop_node(SaNode),
+ stop_node(MgrNode),
+ application:stop(mnesia).
+
+start_v1_agent(Config) when list(Config) ->
+ start_agent(Config, [v1]).
+
+start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
+ start_agent(Config, [v1], Opts).
+
+start_v2_agent(Config) when list(Config) ->
+ start_agent(Config, [v2]).
+
+start_v3_agent(Config) when list(Config) ->
+ start_agent(Config, [v3]).
+
+start_bilingual_agent(Config) when list(Config) ->
+ start_agent(Config, [v1,v2]).
+
+start_multi_threaded_agent(Config) when list(Config) ->
+ start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
+
+stop_agent(Config) when list(Config) ->
+ ?LOG("stop_agent -> entry with"
+ "~n Config: ~p",[Config]),
+
+ {Sup, Par} = ?config(snmp_sup, Config),
+ ?DBG("stop_agent -> attempt to stop (sup) ~p"
+ "~n Sup: ~p"
+ "~n Par: ~p",
+ [Sup,
+ (catch process_info(Sup)),
+ (catch process_info(Par))]),
+ stop_sup(Sup, Par),
+
+ {Sup2, Par2} = ?config(snmp_sub, Config),
+ ?DBG("stop_agent -> attempt to stop (sub) ~p"
+ "~n Sup2: ~p"
+ "~n Par2: ~p",
+ [Sup2,
+ (catch process_info(Sup2)),
+ (catch process_info(Par2))]),
+ stop_sup(Sup2, Par2),
+
+ ?DBG("stop_agent -> done - now cleanup config", []),
+ C1 = lists:keydelete(snmp_sup, 1, Config),
+ lists:keydelete(snmp_sub, 1, C1).
+
+
+stop_sup(Pid, _) when node(Pid) == node() ->
+ case (catch process_info(Pid)) of
+ PI when list(PI) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ exit(Pid, kill),
+ await_stopped(Pid, Ref);
+ {'EXIT', _Reason} ->
+ ?LOG("stop_sup -> ~p not running", [Pid]),
+ ok
+ end;
+stop_sup(Pid, _) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ ?LOG("stop_sup -> Ref: ~p", [Ref]),
+ %% Pid ! {'EXIT', Parent, shutdown}, % usch
+ exit(Pid, kill),
+ await_stopped(Pid, Ref).
+
+await_stopped(Pid, Ref) ->
+ receive
+ {'DOWN', Ref, process, Pid, _Reason} ->
+ ?DBG("received down message for ~p", [Pid]),
+ ok
+ after 10000 ->
+ ?INF("await_stopped -> timeout for ~p",[Pid]),
+ erlang:demonitor(Ref),
+ ?FAIL({failed_stop,Pid})
+ end.
+
+
+start_agent(Config, Vsn) ->
+ start_agent(Config, Vsn, []).
+start_agent(Config, Vsn, Opts) ->
+ ?LOG("start_agent -> entry (~p) with"
+ "~n Config: ~p"
+ "~n Vsn: ~p"
+ "~n Opts: ~p",[node(), Config, Vsn, Opts]),
+
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
+ snmp_app_env_init(vsn_init(Vsn) ++
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentDir},
+ {snmp_db_dir, AgentDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, trace},
+ {snmp_symbolic_store_verbosity, trace},
+ {snmp_note_store_verbosity, trace},
+ {snmp_net_if_verbosity, trace}],
+ Opts),
+
+
+ process_flag(trap_exit,true),
+
+ {ok, AppSup} = snmp_app_sup:start_link(),
+ unlink(AppSup),
+ ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
+
+ ?DBG("start_agent -> start master agent (old style)",[]),
+ Sup = case (catch snmpa_app:start(normal)) of
+ {ok, S} ->
+ ?DBG("start_agent -> started, Sup: ~p",[S]),
+ S;
+
+ Else ->
+ ?DBG("start_agent -> unknown result: ~n~p",[Else]),
+ %% Get info about the apps we depend on
+ MnesiaInfo = mnesia_running(),
+ ?FAIL({start_failed,Else,MnesiaInfo})
+ end,
+
+ ?DBG("start_agent -> unlink from supervisor",[]),
+ ?line unlink(Sup),
+ ?line SaDir = ?config(sa_dir, Config),
+ ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
+ ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
+ ?DBG("start_agent -> done",[]),
+ ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
+
+
+vsn_init(Vsn) ->
+ vsn_init([v1,v2,v3], Vsn, []).
+
+vsn_init([], _Vsn, Acc) ->
+ Acc;
+vsn_init([V|Vsns], Vsn, Acc) ->
+ case lists:member(V, Vsn) of
+ true ->
+ vsn_init(Vsns, Vsn, [{V, true}|Acc]);
+ false ->
+ vsn_init(Vsns, Vsn, [{V, false}|Acc])
+ end.
+
+snmp_app_env_init(Env0, Opts) ->
+ ?DBG("snmp_app_env_init -> unload snmp",[]),
+ ?line application:unload(snmp),
+ ?DBG("snmp_app_env_init -> load snmp",[]),
+ ?line application:load(snmp),
+ ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
+ F1 = fun({Key,Val} = New, Acc0) ->
+ ?DBG("snmp_app_env_init -> "
+ "updating setting ~p to ~p", [Key, Val]),
+ case lists:keyreplace(Key, 1, Acc0, New) of
+ Acc0 ->
+ [New|Acc0];
+ Acc ->
+ Acc
+ end
+ end,
+ Env = lists:foldr(F1, Env0, Opts),
+ ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
+ F2 = fun({Key,Val}) ->
+ ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
+ application_controller:set_env(snmp, Key, Val)
+ end,
+ lists:foreach(F2, Env).
+
+
+
+
+%% Test if application is running
+mnesia_running() -> ?IS_MNESIA_RUNNING().
+crypto_running() -> ?IS_CRYPTO_RUNNING().
+
+
+start_sub(Dir) ->
+ ?DBG("start_sub -> entry",[]),
+ Opts = [{db_dir, Dir},
+ {supervisor, [{verbosity, trace}]}],
+ %% BMK BMK
+% {ok, P} = snmp_supervisor:start_sub(Dir),
+ {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
+ unlink(P),
+ {ok, {P, self()}}.
+
+create_tables(SaNode) ->
+ ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
+ {attributes, [a1,a2]}]).
+
+delete_tables() ->
+ mnesia:delete_table(friendsTable2),
+ mnesia:delete_table(kompissTable2),
+ mnesia:delete_table(snmp_variables).
+
+%% Creation is done in runtime!
+delete_mib_storage_mnesia_tables() ->
+ mnesia:delete_table(snmpa_mib_data),
+ mnesia:delete_table(snmpa_mib_tree),
+ mnesia:delete_table(snmpa_symbolic_store).
+
+%%-----------------------------------------------------------------
+%% A test case is always one of:
+%% - v1 specific case
+%% - v2 specific case
+%% - v1 and v2 case
+%% All v1 specific cases are prefixed with v1_, and all v2 with
+%% v2_. E.g. v1_trap/v2_trap.
+%%
+%% All other cases are shared. However, the testserver uses the name
+%% of the case to generate a file for that case. The same case cannot
+%% be used in different configurations in the same suite. Therefore
+%% all these functions exists in two variants, the base function
+%% <base>, and a second version <base>_2. There may be several
+%% versions as well, <base>_N.
+%%-----------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+mib_storage_ets_cases() ->
+[mse_simple, mse_v1_processing, mse_big, mse_big2,
+ mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
+ mse_sa_error, mse_next_across_sa, mse_undo,
+ mse_standard_mib, mse_community_mib, mse_framework_mib,
+ mse_target_mib, mse_notification_mib,
+ mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
+ mse_mib_of].
+
+mib_storage_dets_cases() ->
+[msd_simple, msd_v1_processing, msd_big, msd_big2,
+ msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
+ msd_sa_error, msd_next_across_sa, msd_undo,
+ msd_standard_mib, msd_community_mib, msd_framework_mib,
+ msd_target_mib, msd_notification_mib,
+ msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
+ msd_mib_of].
+
+mib_storage_mnesia_cases() ->
+[msm_simple, msm_v1_processing, msm_big, msm_big2,
+ msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
+ msm_sa_error, msm_next_across_sa, msm_undo,
+ msm_standard_mib, msm_community_mib, msm_framework_mib,
+ msm_target_mib, msm_notification_mib,
+ msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
+ msm_mib_of].
+
+mse_size_check_cases() ->
+[mse_size_check].
+
+msd_size_check_cases() ->
+[msd_size_check].
+
+msm_size_check_cases() ->
+[msm_size_check].
+
+varm_mib_storage_dets_cases() ->
+[msd_varm_mib_start].
+
+varm_mib_storage_mnesia_cases() ->
+[msm_varm_mib_start].
+
+init_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,ets},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ init_ms(Config, [MibStorage]).
+
+init_ms(Config, Opts) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
+ [{vsn, v1} | start_v1_agent(Config,Opts1)].
+
+init_size_check_mse(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, ets},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msd(Config) when list(Config) ->
+ AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDir}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msm(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, {mnesia,[]}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_ms(Config, Opts) when list(Config) ->
+ SaNode = ?GCONF(snmp_sa, Config),
+ %% We are using v3 here, so crypto must be supported or else...
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end,
+ create_tables(SaNode),
+ AgentDir = ?GCONF(agent_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ ?line ok =
+ config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_agent(Config, [v3], Opts)].
+
+init_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_dets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+init_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_mnesia -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+finish_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_ets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_dets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_dets -> entry", []),
+ delete_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_size_check_mse(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msd(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msm(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_ms(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%% These are just interface functions to fool the test server
+mse_simple(X) -> simple(X).
+mse_v1_processing(X) -> v1_processing(X).
+mse_big(X) -> big(X).
+mse_big2(X) -> big2(X).
+mse_loop_mib(X) -> loop_mib(X).
+mse_api(X) -> api(X).
+mse_sa_register(X) -> sa_register(X).
+mse_v1_trap(X) -> v1_trap(X).
+mse_sa_error(X) -> sa_error(X).
+mse_next_across_sa(X) -> next_across_sa(X).
+mse_undo(X) -> undo(X).
+mse_standard_mib(X) -> snmp_standard_mib(X).
+mse_community_mib(X) -> snmp_community_mib(X).
+mse_framework_mib(X) -> snmp_framework_mib(X).
+mse_target_mib(X) -> snmp_target_mib(X).
+mse_notification_mib(X) -> snmp_notification_mib(X).
+mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+mse_sparse_table(X) -> sparse_table(X).
+mse_me_of(X) -> ms_me_of(X).
+mse_mib_of(X) -> ms_mib_of(X).
+
+msd_simple(X) -> simple(X).
+msd_v1_processing(X) -> v1_processing(X).
+msd_big(X) -> big(X).
+msd_big2(X) -> big2(X).
+msd_loop_mib(X) -> loop_mib(X).
+msd_api(X) -> api(X).
+msd_sa_register(X) -> sa_register(X).
+msd_v1_trap(X) -> v1_trap(X).
+msd_sa_error(X) -> sa_error(X).
+msd_next_across_sa(X) -> next_across_sa(X).
+msd_undo(X) -> undo(X).
+msd_standard_mib(X) -> snmp_standard_mib(X).
+msd_community_mib(X) -> snmp_community_mib(X).
+msd_framework_mib(X) -> snmp_framework_mib(X).
+msd_target_mib(X) -> snmp_target_mib(X).
+msd_notification_mib(X) -> snmp_notification_mib(X).
+msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msd_sparse_table(X) -> sparse_table(X).
+msd_me_of(X) -> ms_me_of(X).
+msd_mib_of(X) -> ms_mib_of(X).
+
+msm_simple(X) -> simple(X).
+msm_v1_processing(X) -> v1_processing(X).
+msm_big(X) -> big(X).
+msm_big2(X) -> big2(X).
+msm_loop_mib(X) -> loop_mib(X).
+msm_api(X) -> api(X).
+msm_sa_register(X) -> sa_register(X).
+msm_v1_trap(X) -> v1_trap(X).
+msm_sa_error(X) -> sa_error(X).
+msm_next_across_sa(X) -> next_across_sa(X).
+msm_undo(X) -> undo(X).
+msm_standard_mib(X) -> snmp_standard_mib(X).
+msm_community_mib(X) -> snmp_community_mib(X).
+msm_framework_mib(X) -> snmp_framework_mib(X).
+msm_target_mib(X) -> snmp_target_mib(X).
+msm_notification_mib(X) -> snmp_notification_mib(X).
+msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msm_sparse_table(X) -> sparse_table(X).
+msm_me_of(X) -> ms_me_of(X).
+msm_mib_of(X) -> ms_mib_of(X).
+
+
+mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
+msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
+msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
+
+msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
+msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
+
+ms_size_check(suite) -> [];
+ms_size_check(Config) when list(Config) ->
+ p("ms_size_check..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?LOG("mib server size check...", []),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMPv2-MIB"),
+ ?line load_master_std("SNMPv2-TM"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMPv2-MIB"),
+ ?line unload_master("SNMPv2-TM"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+
+varm_mib_start(suite) -> [];
+varm_mib_start(Config) when list(Config) ->
+ p("varm_mib_start..."),
+ ?LOG("varm_mib_start -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ %% Start the agent
+ Opts = ?GCONF(agent_opts, Config),
+ Config1 = start_v1_agent(Config, Opts),
+
+ %% Sleep some in order for the agent to start properly
+ ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
+ ?SLEEP(5000),
+
+ %% Load all the mibs
+ HardwiredMibs = loaded_mibs(),
+ ?DBG("varm_mib_start -> load all mibs", []),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+
+ %% Unload the hardwired mibs
+ ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
+ ?SLEEP(1000),
+ ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
+ ?line unload_mibs(HardwiredMibs), %% unload hardwired
+
+ ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
+ ?SLEEP(1000),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ Config2 = stop_agent(Config1),
+
+ %% Sleep some in order for the agent to stop properly
+ ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
+ ?SLEEP(5000),
+
+ %% Start the agent (again)
+ ?DBG("varm_mib_start -> start the agent", []),
+ Config3 = start_v1_agent(Config2, Opts),
+
+ ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
+ ?SLEEP(5000),
+
+ %% Perform the test(s)
+ ?DBG("varm_mib_start -> perform the tests", []),
+ try_test(snmp_community_mib),
+ try_test(snmp_framework_mib),
+ try_test(snmp_target_mib),
+ try_test(snmp_notification_mib),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ stop_agent(Config3),
+ ok.
+
+
+-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
+-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
+-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+ms_me_of(suite) -> [];
+ms_me_of(Config) when list(Config) ->
+ p("ms_me_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = me_of(?snmpTrapCommunity_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = me_of(?vacmViewSpinLock_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+me_of(Oid) ->
+ case snmpa:me_of(Oid) of
+ {ok, #me{oid = Oid}} ->
+ ok;
+ {ok, #me{oid = OtherOid}} ->
+ case lists:reverse(Oid) of
+ [0|Rest] ->
+ case lists:reverse(Rest) of
+ OtherOid ->
+ ok;
+ AnotherOid ->
+ {error, {invalid_oid, Oid, AnotherOid}}
+ end;
+ _ ->
+ {error, {invalid_oid, Oid, OtherOid}}
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ {error, Else}
+ end.
+
+
+ms_mib_of(suite) -> [];
+ms_mib_of(Config) when list(Config) ->
+ p("ms_mib_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
+ 'SNMP-USER-BASED-SM-MIB'),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+mib_of(Oid, ExpectedMibName) ->
+ ?DBG("mib_of -> entry with"
+ "~n Oid: ~p"
+ "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
+ %% case snmpa:mib_of(Oid) of
+ MibOf = snmpa:mib_of(Oid),
+ ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
+ case MibOf of
+ {ok, ExpectedMibName} ->
+ ok;
+ {ok, OtherMibName} ->
+ {error, {invalid_mib, ExpectedMibName, OtherMibName}};
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ ?DBG("mib_of -> Else: ~n~p", [Else]),
+ {error, Else}
+ end.
+
+
+app_info(suite) -> [];
+app_info(Config) when list(Config) ->
+ SnmpDir = app_dir(snmp),
+ SslDir = app_dir(ssl),
+ CryptoDir = app_dir(crypto),
+ Attr = snmp:module_info(attributes),
+ AppVsn =
+ case lists:keysearch(app_vsn, 1, Attr) of
+ {value, {app_vsn, V}} ->
+ V;
+ false ->
+ "undefined"
+ end,
+ io:format("Root dir: ~s~n"
+ "SNMP: Application dir: ~s~n"
+ " Application ver: ~s~n"
+ "SSL: Application dir: ~s~n"
+ "CRYPTO: Application dir: ~s~n",
+ [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
+ ok.
+
+app_dir(App) ->
+ case code:lib_dir(App) of
+ D when list(D) ->
+ filename:basename(D);
+ {error, _Reason} ->
+ "undefined"
+ end.
+
+
+
+%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].
+
+init_v1(Config) when list(Config) ->
+ ?line SaNode = ?config(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v1} | start_v1_agent(Config)].
+
+finish_v1(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v2_cases() -> [loop_mib_2];
+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].
+
+init_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_v2_agent(Config)].
+
+finish_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+v1_v2_cases() ->
+[simple_bi].
+
+init_v1_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, bilingual} | start_bilingual_agent(Config)].
+
+finish_v1_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v3_cases() -> [loop_mib_3];
+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].
+
+init_v3(Config) when list(Config) ->
+ %% Make sure crypto works, otherwise start_agent will fail
+ %% and we will be stuck with a bunch of mnesia tables for
+ %% the rest of this suite...
+ ?DBG("start_agent -> start crypto app",[]),
+ case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end
+ end,
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v3], MgrDir, AgentDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_v3_agent(Config)].
+
+finish_v3(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+mt_cases() ->
+[multi_threaded, mt_trap].
+
+init_mt(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_multi_threaded_agent(Config)].
+
+finish_mt(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+%% This one *must* be run first in each case.
+init_case(Config) when list(Config) ->
+ ?DBG("init_case -> entry with"
+ "~n Config: ~p", [Config]),
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = node(),
+
+ SaHost = ?HOSTNAME(SaNode),
+ MgrHost = ?HOSTNAME(MgrNode),
+ MasterHost = ?HOSTNAME(MasterNode),
+ {ok, MasterIP} = snmp_misc:ip(MasterHost),
+ {ok, MIP} = snmp_misc:ip(MgrHost),
+ {ok, SIP} = snmp_misc:ip(SaHost),
+
+
+ put(mgr_node, MgrNode),
+ put(sa_node, SaNode),
+ put(master_node, MasterNode),
+ put(sa_host, SaHost),
+ put(mgr_host, MgrHost),
+ put(master_host, MasterHost),
+ put(mip, tuple_to_list(MIP)),
+ put(masterip , tuple_to_list(MasterIP)),
+ put(sip, tuple_to_list(SIP)),
+
+ MibDir = ?config(mib_dir, Config),
+ put(mib_dir, MibDir),
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ put(std_mib_dir, StdM),
+
+ MgrDir = ?config(mgr_dir, Config),
+ put(mgr_dir, MgrDir),
+
+ put(vsn, ?config(vsn, Config)),
+ ?DBG("init_case -> exit with"
+ "~n MasterNode: ~p"
+ "~n SaNode: ~p"
+ "~n MgrNode: ~p"
+ "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
+ {SaNode, MgrNode, MibDir}.
+
+load_master(Mib) ->
+ ?DBG("load_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+
+load_master_std(Mib) ->
+ ?DBG("load_master_std -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+
+unload_master(Mib) ->
+ ?DBG("unload_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+
+loaded_mibs() ->
+ ?DBG("loaded_mibs -> entry",[]),
+ Info = snmpa:info(snmp_master_agent),
+ {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
+ [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
+
+unload_mibs(Mibs) ->
+ ?DBG("unload_mibs -> entry with"
+ "~n Mibs: ~p", [Mibs]),
+ ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
+
+start_subagent(SaNode, RegTree, Mib) ->
+ ?DBG("start_subagent -> entry with"
+ "~n SaNode: ~p"
+ "~n RegTree: ~p"
+ "~n Mib: ~p", [SaNode, RegTree, Mib]),
+ MA = whereis(snmp_master_agent),
+ ?DBG("start_subagent -> MA: ~p", [MA]),
+ MibDir = get(mib_dir),
+ Mib1 = join(MibDir,Mib),
+ %% BMK BMK
+% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
+ case rpc:call(SaNode, snmpa_supervisor,
+ start_sub_agent, [MA, RegTree, [Mib1]]) of
+ {ok, SA} ->
+ ?DBG("start_subagent -> SA: ~p", [SA]),
+ {ok, SA};
+ Error ->
+ ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
+ end.
+
+stop_subagent(SA) ->
+ ?DBG("stop_subagent -> entry with"
+ "~n SA: ~p", [SA]),
+ %% BNK BMK
+ %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
+ rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
+
+%%-----------------------------------------------------------------
+%% This function takes care of the old OTP-SNMPEA-MIB.
+%% Unfortunately, the testcases were written to use the data in the
+%% internal tables, and these table are now obsolete and not used
+%% by the agent. Therefore, we emulate them by using
+%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
+%%
+%% These two rows must exist in intCommunityTable
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+%% (But with the manager's IP address)
+%%
+%%-----------------------------------------------------------------
+init_old() ->
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [6 | "public"],
+ {get(mip), "public", 2, 2}),
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [13 | "standard trap"],
+ {get(mip), "standard trap", 2, 1}),
+ snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
+
+
+
+simple(suite) -> [];
+simple(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(simple_standard_test).
+
+simple_2(X) -> simple(X).
+
+simple_bi(suite) -> [];
+simple_bi(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(vsn, v1), % First, try v1 manager
+ try_test(simple_standard_test),
+
+ put(vsn, v2), % Then, try v2 manager
+ try_test(simple_standard_test).
+
+simple_3(X) ->
+ simple(X).
+
+big(suite) -> [];
+big(Config) when list(Config) ->
+ ?DBG("big -> entry", []),
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?DBG("big -> SA: ~p", [SA]),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+big_2(X) -> big(X).
+
+big_3(X) -> big(X).
+
+
+big2(suite) -> [];
+big2(Config) when list(Config) ->
+ %% This is exactly the same tests as 'big', but with the
+ %% v2 equivalent of the mibs.
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
+ ?line load_master("OLD-SNMPEA-MIB-v2"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB-v2").
+
+big2_2(X) -> big2(X).
+
+big2_3(X) -> big2(X).
+
+
+multi_threaded(suite) -> [];
+multi_threaded(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(multi_threaded_test),
+ ?line unload_master("Test1").
+
+mt_trap(suite) -> [];
+mt_trap(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ ?line load_master("TestTrapv2"),
+ try_test(mt_trap_test, [MA]),
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("Test1").
+
+v2_types(suite) -> [];
+v2_types(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(types_v2_test),
+ ?line unload_master("Test1").
+
+v2_types_3(X) -> v2_types(X).
+
+
+implied(suite) -> [];
+implied(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(implied_test,[MA]),
+ ?line unload_master("Test1").
+
+implied_3(X) -> implied(X).
+
+
+sparse_table(suite) -> [];
+sparse_table(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(sparse_table_test),
+ ?line unload_master("Test1").
+
+sparse_table_2(X) -> sparse_table(X).
+
+sparse_table_3(X) -> sparse_table(X).
+
+cnt_64(suite) -> [];
+cnt_64(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(cnt_64_test, [MA]),
+ ?line unload_master("Test1").
+
+cnt_64_2(X) -> cnt_64(X).
+
+cnt_64_3(X) -> cnt_64(X).
+
+opaque(suite) -> [];
+opaque(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(opaque_test),
+ ?line unload_master("Test1").
+
+opaque_2(X) -> opaque(X).
+
+opaque_3(X) -> opaque(X).
+
+
+change_target_addr_config(suite) -> [];
+change_target_addr_config(Config) when list(Config) ->
+ p("Testing changing target address config..."),
+ ?LOG("change_target_addr_config -> entry",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(sname,snmp_suite),
+ put(verbosity,trace),
+
+ MA = whereis(snmp_master_agent),
+
+ ?LOG("change_target_addr_config -> load TestTrap",[]),
+ ?line load_master("TestTrap"),
+
+ ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,trace),
+
+ %% First send some traps that will arive att the original manager
+ ?LOG("change_target_addr_config -> send trap",[]),
+ try_test(ma_trap1, [MA]),
+
+ ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,silence),
+
+ %% Start new dummy listener
+ ?LOG("change_target_addr_config -> start dummy manager",[]),
+ ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+
+ %% Reconfigure
+ ?LOG("change_target_addr_config -> reconfigure",[]),
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_addr_conf(AgentDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ %% Send the trap again
+ ?LOG("change_target_addr_config -> send trap again",[]),
+ catch dummy_manager_send_trap2(Pid),
+
+ ?LOG("change_target_addr_config -> await trap ack",[]),
+ catch dummy_manager_await_trap2_ack(),
+
+ ?LOG("change_target_addr_config -> stop dummy manager",[]),
+ ?line ok = dummy_manager_stop(Pid),
+
+ ?LOG("change_target_addr_config -> reset target address config",[]),
+ ?line reset_target_addr_conf(AgentDir),
+
+ ?LOG("change_target_addr_config -> unload TestTrap",[]),
+ ?line unload_master("TestTrap").
+
+
+dummy_manager_start(MA) ->
+ ?DBG("dummy_manager_start -> entry",[]),
+ Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
+ ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
+ await_dummy_manager_started(Pid).
+
+await_dummy_manager_started(Pid) ->
+ receive
+ {dummy_manager_started,Pid,Port} ->
+ ?DBG("dummy_manager_start -> acknowledge received with"
+ "~n Port: ~p",[Port]),
+ {ok,Pid,Port};
+ {'EXIT', Pid, Reason} ->
+ {error, Pid, Reason};
+ O ->
+ ?LOG("dummy_manager_start -> received unknown message:"
+ "~n ~p",[O]),
+ await_dummy_manager_started(Pid)
+ end.
+
+dummy_manager_stop(Pid) ->
+ ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
+ Pid ! stop,
+ receive
+ {dummy_manager_stopping, Pid} ->
+ ?DBG("dummy_manager_stop -> acknowledge received",[]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_stop -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_send_trap2(Pid) ->
+ ?DBG("dummy_manager_send_trap2 -> entry",[]),
+ Pid ! {send_trap,testTrap2}.
+
+dummy_manager_await_trap2_ack() ->
+ ?DBG("dummy_manager_await_trap2 -> entry",[]),
+ receive
+ {received_trap,Trap} ->
+ ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
+ %% Note:
+ %% Without this sleep the v2_inform_i testcase failes! There
+ %% is no relation between these two test cases as far as I
+ %% able to figure out...
+ sleep(60000),
+ ok;
+ O ->
+ ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_await_trap2 -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_init(Parent,MA) ->
+ ?DBG("dummy_manager_init -> entry with"
+ "~n Parent: ~p"
+ "~n MA: ~p",[Parent,MA]),
+ {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
+ ?DBG("dummy_manager_init -> S: ~p",[S]),
+ {ok,Port} = inet:port(S),
+ ?DBG("dummy_manager_init -> Port: ~p",[Port]),
+ Parent ! {dummy_manager_started,self(),Port},
+ dummy_manager_loop(Parent,S,MA).
+
+dummy_manager_loop(P,S,MA) ->
+ ?LOG("dummy_manager_loop -> ready for receive",[]),
+ receive
+ {send_trap,Trap} ->
+ ?LOG("dummy_manager_loop -> received trap send request"
+ "~n Trap: ~p",[Trap]),
+ snmpa:send_trap(MA, Trap, "standard trap"),
+ dummy_manager_loop(P,S,MA);
+ {udp, _UdpId, Ip, UdpPort, Bytes} ->
+ ?LOG("dummy_manager_loop -> received upd message"
+ "~n from: ~p:~p"
+ "~n size: ~p",
+ [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
+ R = dummy_manager_handle_message(Bytes),
+ ?DBG("dummy_manager_loop -> R: ~p",[R]),
+ P ! R,
+ dummy_manager_loop(P,S,MA);
+ stop ->
+ ?DBG("dummy_manager_loop -> received stop request",[]),
+ P ! {dummy_manager_stopping, self()},
+ gen_udp:close(S),
+ exit(normal);
+ O ->
+ ?LOG("dummy_manager_loop -> received unknown message:"
+ "~n ~p",[O]),
+ dummy_manager_loop(P,S,MA)
+ end.
+
+dummy_manager_message_sz(B) when binary(B) ->
+ size(B);
+dummy_manager_message_sz(L) when list(L) ->
+ length(L);
+dummy_manager_message_sz(_) ->
+ undefined.
+
+dummy_manager_handle_message(Bytes) ->
+ case (catch snmp_pdus:dec_message(Bytes)) of
+ {'EXIT',Reason} ->
+ ?ERR("dummy_manager_handle_message -> "
+ "failed decoding message only:~n ~p",[Reason]),
+ {error,Reason};
+ M ->
+ ?DBG("dummy_manager_handle_message -> decoded message:"
+ "~n ~p",[M]),
+ {received_trap,M}
+ end.
+
+
+api(suite) -> [];
+api(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(api_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+api_2(X) -> api(X).
+
+api_3(X) -> api(X).
+
+
+subagent(suite) -> [];
+subagent(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ try_test(load_test_sa),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+
+ p("Loading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(load_test),
+
+ p("Unloading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(unreg_test),
+ p("Testing register subagent..."),
+ rpc:call(SaNode, snmp, register_subagent,
+ [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ ?line stop_subagent(SA),
+ try_test(unreg_test).
+
+subagent_2(X) -> subagent(X).
+
+subagent_3(X) -> subagent(X).
+
+
+mnesia(suite) -> [];
+mnesia(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent with mnesia impl..."),
+ {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ try_test(big_test_2),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA).
+
+mnesia_2(X) -> mnesia(X).
+
+mnesia_3(X) -> mnesia(X).
+
+
+
+mul_cases() ->
+[mul_get, mul_get_err, mul_next, mul_next_err,
+ mul_set_err].
+
+
+multiple_reqs_3(_X) ->
+ {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
+
+
+mul_cases_2() ->
+[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
+ mul_set_err_2].
+
+
+mul_cases_3() ->
+ [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
+
+
+init_mul(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ [{mul_sub, SA} | Config].
+
+finish_mul(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ SA = ?config(mul_sub, Config),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA),
+ lists:keydelete(mul_sub, 1, Config).
+
+mul_get(suite) -> [];
+mul_get(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get..."),
+ try_test(do_mul_get).
+
+mul_get_2(X) -> mul_get(X).
+
+mul_get_3(X) -> mul_get(X).
+
+
+mul_get_err(suite) -> [];
+mul_get_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get with error..."),
+ try_test(do_mul_get_err).
+
+mul_get_err_2(X) -> mul_get_err(X).
+
+mul_get_err_3(X) -> mul_get_err(X).
+
+
+mul_next(suite) -> [];
+mul_next(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next).
+
+mul_next_2(X) -> mul_next(X).
+
+mul_next_3(X) -> mul_next(X).
+
+
+mul_next_err(suite) -> [];
+mul_next_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next_err).
+
+mul_next_err_2(X) -> mul_next_err(X).
+
+mul_next_err_3(X) -> mul_next_err(X).
+
+
+mul_set(suite) -> [];
+mul_set(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set..."),
+ try_test(do_mul_set).
+
+mul_set_2(X) -> mul_set(X).
+
+mul_set_3(X) -> mul_set(X).
+
+
+mul_set_err(suite) -> [];
+mul_set_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set with error..."),
+ try_test(do_mul_set_err).
+
+mul_set_err_2(X) -> mul_set_err(X).
+
+mul_set_err_3(X) -> mul_set_err(X).
+
+
+sa_register(suite) -> [];
+sa_register(Config) when list(Config) ->
+ ?DBG("sa_register -> entry", []),
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?DBG("sa_register -> start subagent", []),
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+
+ ?DBG("sa_register -> unregister subagent", []),
+ p("Testing unregister subagent (2)..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Loading SA-MIB..."),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ ?DBG("sa_register -> register subagent", []),
+ rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
+ try_test(sa_mib),
+
+ ?DBG("sa_register -> stop subagent", []),
+ ?line stop_subagent(SA).
+
+sa_register_2(X) -> sa_register(X).
+
+sa_register_3(X) -> sa_register(X).
+
+
+v1_trap(suite) -> [];
+v1_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_trap1, [MA]),
+ try_test(ma_trap2, [MA]),
+ try_test(ma_v2_2_v1_trap, [MA]),
+ try_test(ma_v2_2_v1_trap2, [MA]),
+
+ p("Testing trap sending from subagent..."),
+ try_test(sa_trap1, [SA]),
+ try_test(sa_trap2, [SA]),
+ try_test(sa_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v2_trap(suite) -> [];
+v2_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+
+ try_test(ma_v2_trap1, [MA]),
+ try_test(ma_v2_trap2, [MA]),
+ try_test(ma_v1_2_v2_trap, [MA]),
+ try_test(ma_v1_2_v2_trap2, [MA]),
+
+ try_test(sa_mib),
+ p("Testing trap sending from subagent..."),
+ try_test(sa_v1_2_v2_trap1, [SA]),
+ try_test(sa_v1_2_v2_trap2, [SA]),
+ try_test(sa_v1_2_v2_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v3_trap(X) ->
+ v2_trap(X).
+
+
+v3_inform(_X) ->
+ %% v2_inform(X).
+ {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
+
+init_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+init_v3_inform(X) ->
+ init_v2_inform(X).
+
+finish_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+finish_v3_inform(X) ->
+ finish_v2_inform(X).
+
+
+
+v2_inform_i(suite) -> [];
+v2_inform_i(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing inform sending from master agent... NOTE! This test\ntakes a "
+ "few minutes (5) to complete."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_v2_inform1, [MA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2").
+
+v3_inform_i(X) -> v2_inform_i(X).
+
+
+sa_error(suite) -> [];
+sa_error(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing sa bad value (is_set_ok)..."),
+ try_test(sa_errs_bad_value),
+
+ p("Testing sa gen err (set)..."),
+ try_test(sa_errs_gen_err),
+
+ p("Testing too big..."),
+ try_test(sa_too_big),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
+
+sa_error_2(X) -> sa_error(X).
+
+sa_error_3(X) -> sa_error(X).
+
+
+next_across_sa(suite) -> [];
+next_across_sa(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Loading another subagent mib..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+
+ rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ p("Testing next across subagent (endOfMibView from SA)..."),
+ try_test(next_across_sa),
+
+ p("Unloading mib"),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Starting another subagent"),
+ ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ p("Testing next across subagent (wrong prefix from SA)..."),
+ try_test(next_across_sa),
+
+ stop_subagent(SA),
+ stop_subagent(SA2).
+
+next_across_sa_2(X) -> next_across_sa(X).
+
+next_across_sa_3(X) -> next_across_sa(X).
+
+
+undo(suite) -> [];
+undo(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing undo phase at master agent..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ try_test(undo_test),
+ try_test(api_test2),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+
+ p("Testing bad return values from instrum. funcs..."),
+ try_test(bad_return),
+
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+
+ p("Testing undo phase at subagent..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ try_test(undo_test),
+ try_test(api_test3),
+
+ p("Testing undo phase across master/subagents..."),
+ try_test(undo_test),
+ try_test(api_test3),
+ stop_subagent(SA).
+
+undo_2(X) -> undo(X).
+
+undo_3(X) -> undo(X).
+
+%% Req. Test2
+v1_processing(suite) -> [];
+v1_processing(Config) when list(Config) ->
+ ?DBG("v1_processing -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v1_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v2_processing(suite) -> [];
+v2_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v3_processing(suite) -> [];
+v3_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc), % same as v2!
+ ?line unload_master("Test2").
+
+
+%% We'll try get/set/trap and inform for all the auth & priv protocols.
+%% For informs, the mgr is auth-engine. The agent has to sync. This is
+%% accomplished by the first inform sent. That one will generate a
+%% report, which makes it in sync. The notification-generating
+%% application times out, and send again. This time it'll work.
+
+v3_crypto_basic(suite) -> [];
+v3_crypto_basic(_Config) ->
+ EID = [0,0,0,0,0,0,0,0,0,0,0,2],
+ %% From rfc2274 appendix A.3.1
+ ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
+ ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
+ 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
+ KMd5_1,
+ %% From rfc2274 appendix A.3.2
+ ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
+ ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
+ 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
+ KSHA_1,
+ %% From rfc2274, appendix A.5.1
+ ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
+ 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ %% From rfc2274, appendix A.5.2
+ ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
+ 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
+ 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ KSHA_1t = lists:sublist(KSHA_1, 16),
+ KSHA_2t = lists:sublist(KSHA_2, 16),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
+ 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+
+ %% Try with correct random
+ ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
+ ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
+ ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
+ ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
+ ok.
+
+
+
+v3_md5_auth(suite) -> [];
+v3_md5_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing MD5 authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_sha_auth(suite) -> [];
+v3_sha_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing SHA authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_des_priv(suite) -> [];
+v3_des_priv(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing DES encryption...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+%% Make sure mgr is in sync with agent
+v3_sync(Funcs) ->
+ ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
+ g([[sysDescr, 0]]),
+ expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
+ g([[sysDescr, 0]]),
+ expect(433, [{[sysDescr,0], any}]),
+ lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
+
+v3_inform_sync(MA) ->
+ ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
+ "standard inform", []),
+ %% Make sure agent is in sync with mgr...
+ ?DBG("v3_sync -> wait some time: ",[]),
+ sleep(20000), % more than 1500*10 in target_addr.conf
+ ?DBG("v3_sync -> await response",[]),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]).
+
+
+v2_caps(suite) -> [];
+v2_caps(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(v2_caps_i, [node()]).
+
+v2_caps_3(X) -> v2_caps(X).
+
+
+v2_caps_i(Node) ->
+ ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
+ g([[sysORID, Idx], [sysORDescr, Idx]]),
+ ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
+ {[sysORDescr, Idx], "test cap"}]),
+ ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
+ g([[sysORID, Idx]]),
+ ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
+
+
+%% Req. Test2
+v1_proc() ->
+ ?DBG("v1_proc -> entry", []),
+ %% According to RFC1157.
+ %% Template: <Section>:<list no>
+ v1_get_p(),
+ v1_get_next_p(),
+ v1_set_p().
+
+
+v1_get_p() ->
+ %% 4.1.2:1
+ g([[test2]]),
+ ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
+ g([[tDescr]]),
+ ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
+ g([[tDescr2,0]]),
+ ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ g([[tDescr3,0]]),
+ ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ g([[tDescr4,0]]),
+ ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ {[tDescr,0], 'NULL'}]),
+ g([[sysDescr,3]]),
+ ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+
+ %% 4.1.2:2
+ g([[tTable]]),
+ ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
+ g([[tEntry]]),
+ ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
+
+ %% 4.1.2:3
+ g([[tTooBig, 0]]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.2:4
+ g([[tGenErr1, 0]]),
+ ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]).
+
+
+v1_get_next_p() ->
+ %% 4.1.3:1
+ gn([[1,3,7,1]]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+ gn([[tDescr2]]),
+ ?line expect(11, tooBig, 0, any),
+
+ %% 4.1.3:2
+ gn([[tTooBig]]),
+ io:format("We currently don't handle tooBig correct!!!\n"),
+% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
+ ?line expect(20, tooBig, 0, any),
+
+ %% 4.1.3:3
+ gn([[tGenErr1]]),
+% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?line expect(40, genErr, 1, any),
+ gn([[tGenErr2]]),
+% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?line expect(41, genErr, 1, any),
+ gn([[sysDescr], [tGenErr3]]),
+% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
+% {[tGenErr3], 'NULL'}]).
+ ?line expect(42, genErr, 2, any).
+
+v1_set_p() ->
+ %% 4.1.5:1
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+ s([{[tDescr3], s, "noSuchObject"}]),
+ ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+ s([{[tDescr3,1], s, "noSuchInstance"}]),
+ ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+ s([{[tDescr2,0], s, "inconsistentName"}]),
+ ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+
+ %% 4.1.5:2
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.1.5:3
+ %% The standard is quite incorrect here. The resp pdu was too big. In
+ %% the resp pdu, we have the original vbs. In the tooBig pdu we still
+ %% have to original vbs => the tooBig pdu is too big as well!!! It
+ %% may not get it to the manager, unless the agent uses 'NULL' instead
+ %% of the std-like original value.
+ s([{[tTooBig, 0], s, ?tooBigStr}]),
+ %% according to std:
+% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.5:4
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+ s([{[tDescr2, 0], s, "commit_fail"}]),
+ ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+
+%% Req. Test2
+v2_proc() ->
+ %% According to RFC1905.
+ %% Template: <Section>:<list no>
+ ?DBG("v2_proc -> entry",[]),
+ v2_get_p(),
+ v2_get_next_p(),
+ v2_get_bulk_p(),
+ v2_set_p().
+
+v2_get_p() ->
+ %% 4.2.1:2
+ ?DBG("v2_get_p -> entry",[]),
+ g([[test2]]),
+ ?line expect(10, [{[test2], noSuchObject}]),
+ g([[tDescr]]),
+ ?line expect(11, [{[tDescr], noSuchObject}]),
+ g([[tDescr4,0]]),
+ ?line expect(12, [{[tDescr4,0], noSuchObject}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[tDescr,0], noSuchObject}]),
+ g([[tTable]]),
+ ?line expect(14, [{[tTable], noSuchObject}]),
+ g([[tEntry]]),
+ ?line expect(15, [{[tEntry], noSuchObject}]),
+
+ %% 4.2.1:3
+ g([[tDescr2,0]]), %% instrum ret noSuchName!!!
+ ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
+ g([[tDescr3,0]]),
+ ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
+ g([[sysDescr,3]]),
+ ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
+ g([[tIndex,1]]),
+ ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
+
+ %% 4.2.1 - any other error: genErr
+ g([[tGenErr1, 0]]),
+ ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]),
+
+ %% 4.2.1 - tooBig
+ g([[tTooBig, 0]]),
+ ?line expect(40, tooBig, 0, []).
+
+
+v2_get_next_p() ->
+ %% 4.2.2:2
+ ?DBG("v2_get_next_p -> entry",[]),
+ gn([[1,3,7,1]]),
+ ?line expect(10, [{[1,3,7,1], endOfMibView}]),
+ gn([[sysDescr], [1,3,7,1]]),
+ ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gn([[tCnt2, 1]]),
+ ?line expect(12, [{[tCnt2,2], 100}]),
+ gn([[tCnt2, 2]]),
+ ?line expect(12, [{[tCnt2,2], endOfMibView}]),
+
+ %% 4.2.2 - any other error: genErr
+ gn([[tGenErr1]]),
+ ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ gn([[tGenErr2]]),
+ ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ gn([[sysDescr], [tGenErr3]]),
+ ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
+ {[tGenErr3], 'NULL'}]),
+
+ %% 4.2.2 - tooBig
+ gn([[tTooBig]]),
+ ?line expect(20, tooBig, 0, []).
+
+v2_get_bulk_p() ->
+ %% 4.2.3
+ ?DBG("v2_get_bulk_p -> entry",[]),
+ gb(1, 1, []),
+ ?line expect(10, []),
+ gb(-1, 1, []),
+ ?line expect(11, []),
+ gb(-1, -1, []),
+ ?line expect(12, []),
+ gb(-1, -1, []),
+ ?line expect(13, []),
+ gb(2, 0, [[sysDescr], [1,3,7,1]]),
+ ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(1, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(0, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
+ ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
+ ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[sysDescr, 0], "Erlang SNMP agent"}]),
+
+ gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
+ ?line expect(19, []),
+
+ gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
+ ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
+ {[sysObjectID], 'NULL'},
+ {[tGenErr1], 'NULL'},
+ {[sysDescr], 'NULL'}]),
+ gb(0, 2, [[tCnt2, 1]]),
+ ?line expect(21, [{[tCnt2,2], 100},
+ {[tCnt2,2], endOfMibView}]).
+
+
+v2_set_p() ->
+ %% 4.2.5:1
+ ?DBG("v2_set_p -> entry",[]),
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
+
+ %% 4.2.5:2
+ s([{[1,3,6,1,0], s, "noSuchObject"}]),
+ ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
+
+ %% 4.2.5:3
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.2.5:4
+ s([{[tStr, 0], s, ""}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
+ s([{[tStr, 0], s, "12345"}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
+
+ %% 4.2.5:5 - N/A
+
+ %% 4.2.5:6
+ s([{[tInt1, 0], i, 0}]),
+ ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
+ s([{[tInt1, 0], i, 5}]),
+ ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
+ s([{[tInt2, 0], i, 0}]),
+ ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
+ s([{[tInt2, 0], i, 5}]),
+ ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
+ s([{[tInt3, 0], i, 5}]),
+ ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
+
+ %% 4.2.5:7
+ s([{[tDescrX, 1, 1], s, "noCreation"}]),
+ ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
+
+ %% 4.2.5:8
+ s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
+ ?line expect(80, inconsistentName, 1,
+ [{[tDescrX, 1, 2], "inconsistentName"}]),
+
+ %% 4.2.5:9
+ s([{[tCnt, 1, 2], i, 5}]),
+ ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
+
+ %% 4.2.5:10
+ s([{[tDescr2,0], s, "inconsistentValue"}]),
+ ?line expect(100, inconsistentValue, 1,
+ [{[tDescr2,0], "inconsistentValue"}]),
+
+ %% 4.2.5:11
+ s([{[tDescr2,0], s, "resourceUnavailable"}]),
+ ?line expect(110, resourceUnavailable, 1,
+ [{[tDescr2,0],"resourceUnavailable"}]),
+
+ %% 4.2.5:12
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
+
+ %% commitFailed and undoFailed is tested by the 'undo' case.
+
+
+%% Req. OLD-SNMPEA-MIB
+table_test() ->
+ io:format("Testing simple get, next and set on communityTable...~n"),
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+ Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
+ Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
+ Key1c4 = [intCommunityAccess,get(mip),is("public")],
+ EndKey = [intCommunityEntry,[9],get(mip),is("public")],
+ gn([[intCommunityEntry]]),
+ ?line expect(7, [{Key1c3, 2}]),
+ gn([[intCommunityTable]]),
+ ?line expect(71, [{Key1c3, 2}]),
+ gn([[community]]),
+ ?line expect(72, [{Key1c3, 2}]),
+ gn([[otpSnmpeaMIB]]),
+ ?line expect(73, [{Key1c3, 2}]),
+ gn([[ericsson]]),
+ ?line expect(74, [{Key1c3, 2}]),
+ gn([Key1c3]),
+ ?line expect(8, [{Key2c3, 2}]),
+ gn([Key2c3]),
+ ?line expect(9, [{Key1c4, 2}]),
+ gn([EndKey]),
+ AgentIp = [intAgentIpAddress,0],
+ ?line expect(10, [{AgentIp, any}]),
+ g([Key1c3]),
+ ?line expect(11, [{Key1c3, 2}]),
+ g([EndKey]),
+ ?line ?v1_2(expect(12, noSuchName, 1, any),
+ expect(12, [{EndKey, noSuchObject}])),
+
+ io:format("Testing row creation/deletion on communityTable...~n"),
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+ s([{NewKeyc5, ?createAndGo}]),
+ ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
+ s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
+ ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
+ g([NewKeyc4]),
+ ?line expect(16, [{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(17, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?createAndWait}]),
+ ?line expect(19, [{NewKeyc5, ?createAndWait}]),
+ g([NewKeyc5]),
+ ?line expect(20, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(21, [{NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(22, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc3, 2}]),
+ ?line expect(23, [{NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(24, [{NewKeyc5, ?notInService}]),
+ s([{NewKeyc5, ?active}]),
+ ?line expect(25, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(26, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc3, 3}]),
+ ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
+ otp_1128().
+
+%% Req. system group
+simple_standard_test() ->
+ ?DBG("simple_standard_test -> entry",[]),
+ gn([[1,1]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3]]),
+ ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6]]),
+ ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1]]),
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2]]),
+ ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1]]),
+ ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1,1]]),
+ ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[sysDescr]]),
+ ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr,0]]),
+ ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr]]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{[sysDescr], noSuchObject}])),
+ g([[1,6,7,0]]),
+ ?line ?v1_2(expect(41, noSuchName, 1, any),
+ expect(3, [{[1,6,7,0], noSuchObject}])),
+ gn([[1,13]]),
+ ?line ?v1_2(expect(4, noSuchName,1, any),
+ expect(4, [{[1,13], endOfMibView}])),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+ g([[sysLocation, 0]]),
+ ?line expect(6, [{[sysLocation, 0], "new_value"}]),
+ io:format("Testing noSuchName and badValue...~n"),
+ s([{[sysServices,0], 3}]),
+ ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
+ s([{[sysLocation, 0], i, 3}]),
+ ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
+ ?DBG("simple_standard_test -> done",[]),
+ ok.
+
+%% This is run in the agent node
+db_notify_client(suite) -> [];
+db_notify_client(Config) when list(Config) ->
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
+ [SaNode,MgrNode,MibDir]),
+ snmpa_local_db:register_notify_client(self(),?MODULE),
+
+ %% This call (the manager) will issue to set operations, so
+ %% we expect to receive to notify(insert) calls.
+ try_test(db_notify_client_test),
+
+ ?DBG("await first notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
+ end,
+
+ ?DBG("await second notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
+ end,
+
+ snmpa_local_db:unregister_notify_client(self()).
+
+
+%% This is run in the manager node
+db_notify_client_test() ->
+ ?DBG("set first new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?DBG("set second new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]).
+
+notify(Pid,What) ->
+ ?DBG("notify(~p,~p) -> called",[Pid,What]),
+ Pid ! {db_notify_test_reply,What}.
+
+
+%% Req: system group, OLD-SNMPEA-MIB, Klas1
+big_test() ->
+ ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
+ simple_standard_test(),
+
+ ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
+ gn([[klas1]]),
+ ?line expect(1, [{[fname,0], ""}]),
+ g([[fname,0]]),
+ ?line expect(2, [{[fname,0], ""}]),
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[fname,0]]),
+ ?line expect(4, [{[fname,0], "test set"}]),
+
+ ?DBG("big_test -> "
+ "testing next from last instance in master to subagent...",[]),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname,0], "test set"}]),
+ s([{[fname,0], s, ""}]),
+ ?line expect(52, [{[fname,0], ""}]),
+
+ table_test(),
+
+ ?DBG("big_test -> adding one row in subagent table",[]),
+ _FTab = [friendsEntry],
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {[friendsEntry, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ s([{[friendsEntry, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
+
+ otp_1131(),
+
+ ?DBG("big_test -> adding two rows in subagent table with special INDEX",
+ []),
+ s([{[kompissEntry, [1, 3]], s, "kompis3"},
+ {[kompissEntry, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry, [1, 3]],
+ [kompissEntry, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ gn([[kompissEntry, [1]],
+ [kompissEntry, [2]]]),
+ ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ s([{[kompissEntry, [1, 2]], s, "kompis3"},
+ {[kompissEntry, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry, [1, 1]],
+ [kompissEntry, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?active}]),
+ s([{[kompissEntry, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
+ s([{[kompissEntry, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
+ ?DBG("big_test -> done",[]),
+ ok.
+
+%% Req. system group, Klas2, OLD-SNMPEA-MIB
+big_test_2() ->
+ p("Testing simple next/get/set @ master agent (2)..."),
+ simple_standard_test(),
+
+ p("Testing simple next/get/set @ subagent (2)..."),
+ gn([[klas2]]),
+ ?line expect(1, [{[fname2,0], ""}]),
+ g([[fname2,0]]),
+ ?line expect(2, [{[fname2,0], ""}]),
+ s([{[fname2,0], s, "test set"}]),
+ ?line expect(3, [{[fname2,0], "test set"}]),
+ g([[fname2,0]]),
+ ?line expect(4, [{[fname2,0], "test set"}]),
+
+ otp_1298(),
+
+ p("Testing next from last object in master to subagent (2)..."),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname2,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname2,0], "test set"}]),
+
+ table_test(),
+
+ p("Adding one row in subagent table (2)"),
+ _FTab = [friendsEntry2],
+ s([{[friendsEntry2, [2, 3]], s, "kompis3"},
+ {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry2, [2, 3]],
+ [friendsEntry2, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?active}]),
+ s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
+
+ p("Adding two rows in subagent table with special INDEX (2)"),
+ s([{[kompissEntry2, [1, 3]], s, "kompis3"},
+ {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry2, [1, 3]],
+ [kompissEntry2, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ gn([[kompissEntry2, [1]],
+ [kompissEntry2, [2]]]),
+ ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ s([{[kompissEntry2, [1, 2]], s, "kompis3"},
+ {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry2, [1, 1]],
+ [kompissEntry2, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?active}]),
+ s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
+ s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
+ ok.
+
+%% Req. Test1
+multi_threaded_test() ->
+ p("Testing multi threaded agent..."),
+ g([[multiStr,0]]),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(1, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "pelle"}]),
+ ?line expect(2, [{[sysLocation, 0], "pelle"}]),
+ Pid ! continue,
+ ?line expect(3, [{[multiStr,0], "ok"}]),
+
+ s([{[multiStr, 0], s, "block"}]),
+ Pid2 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(4, [{[sysUpTime,0], any}]),
+ g([[multiStr,0]]),
+ Pid3 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(5, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "kalle"}]),
+ Pid3 ! continue,
+ ?line expect(6, [{[multiStr,0], "ok"}]),
+ Pid2 ! continue,
+ ?line expect(7, [{[multiStr,0], "block"}]),
+ ?line expect(8, [{[sysLocation,0], "kalle"}]).
+
+%% Req. Test1, TestTrapv2
+mt_trap_test(MA) ->
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ snmpa:send_trap(MA, mtTrap, "standard trap"),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(2, [{[sysUpTime,0], any}]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ Pid ! continue,
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [2]},
+ {[multiStr,0], "ok"}]).
+
+
+get_multi_pid() ->
+ get_multi_pid(10).
+get_multi_pid(0) ->
+ ?line ?FAIL(no_global_name);
+get_multi_pid(N) ->
+ sleep(1000),
+ case global:whereis_name(snmp_multi_tester) of
+ Pid when pid(Pid) -> Pid;
+ _ -> get_multi_pid(N-1)
+ end.
+
+%% Req. Test1
+types_v2_test() ->
+ p("Testing v2 types..."),
+
+ s([{[bits1,0], 2#10}]),
+ ?line expect(1, [{[bits1,0], ?str(2#10)}]),
+ g([[bits1,0]]),
+ ?line expect(2, [{[bits1,0], ?str(2#101)}]),
+
+ s([{[bits2,0], 2#11000000110}]),
+ ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
+ g([[bits2,0]]),
+ ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
+
+ g([[bits3,0]]),
+ ?line expect(50, genErr, 1, any),
+
+ g([[bits4,0]]),
+ ?line expect(51, genErr, 1, any),
+
+ s([{[bits1,0], s, [2#10]}]),
+ ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
+
+ s([{[bits2,0], 2#11001001101010011}]),
+ ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%% Req. Test1
+implied_test(MA) ->
+ ?LOG("implied_test -> start",[]),
+ p("Testing IMPLIED..."),
+
+ snmpa:verbosity(MA,trace),
+ snmpa:verbosity(MA,trace),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = "apa",
+ Idx2 = "qq",
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
+ ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
+ {[testDescr, Idx1], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
+ ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
+ {[testDescr, Idx2], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr)",[]),
+ gn([[testDescr]]),
+ ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
+ gn([[testDescr,Idx1]]),
+ ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?destroy}]),
+ ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?destroy}]),
+ ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
+
+ %% Try the same in other table
+ Idx3 = [1, "apa"],
+ Idx4 = [1, "qq"],
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
+ ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
+ {[testDescr2, Idx3], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
+ ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
+ {[testDescr2, Idx4], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr2)",[]),
+ gn([[testDescr2]]),
+ ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
+ gn([[testDescr2,Idx3]]),
+ ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?destroy}]),
+ ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?destroy}]),
+ ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
+
+ snmpa:verbosity(MA,log),
+
+ ?LOG("implied_test -> done",[]).
+
+
+
+%% Req. Test1
+sparse_table_test() ->
+ p("Testing sparse table..."),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ s([{[sparseStatus, Idx1], i, ?createAndGo},
+ {[sparseDescr, Idx1], s, "row 1"}]),
+ ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
+ {[sparseDescr, Idx1], "row 1"}]),
+ s([{[sparseStatus, Idx2], i, ?createAndGo},
+ {[sparseDescr, Idx2], s, "row 2"}]),
+ ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
+ {[sparseDescr, Idx2], "row 2"}]),
+ ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
+ [sparseStatus,Idx1], [sparseStatus,Idx2]]),
+ gb(0,5,[[sparseIndex]])),
+ ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
+ {[sparseDescr,Idx2], "row 2"},
+ {[sparseStatus,Idx1], ?active},
+ {[sparseStatus,Idx2], ?active},
+ {[sparseStr,0], "slut"}]),
+ % Delete the rows
+ s([{[sparseStatus, Idx1], i, ?destroy}]),
+ ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
+ s([{[sparseStatus, Idx2], i, ?destroy}]),
+ ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
+
+
+%% Req. Test1
+cnt_64_test(MA) ->
+ ?LOG("start cnt64 test (~p)",[MA]),
+ snmpa:verbosity(MA,trace),
+ ?LOG("start cnt64 test",[]),
+ p("Testing Counter64, and at the same time, RowStatus is not last column"),
+
+ ?DBG("get cnt64",[]),
+ g([[cnt64,0]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(1, noSuchName, 1, any),
+ expect(1, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("get-next cnt64",[]),
+ gn([[cnt64]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
+ expect(2, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("send cntTrap",[]),
+ snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
+ {cnt64, 10},
+ {sysLocation, "here"}]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ {[sysLocation,0], "here"}]),
+ expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [1]},
+ {[sysContact,0], "pelle"},
+ {[cnt64,0], 10},
+ {[sysLocation,0], "here"}])),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ ?DBG("create row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
+ ?DBG("create row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
+
+ ?DBG("get-next (cntIndex)",[]),
+ gn([[cntIndex]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
+ expect(3, [{[cntCnt,Idx1], 0}])),
+ % Delete the rows
+ ?DBG("delete row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
+ ?DBG("delete row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
+ catch snmpa:verbosity(MA,log),
+ ?DBG("done",[]),
+ ok.
+
+%% Req. Test1
+opaque_test() ->
+ p("Testing Opaque datatype..."),
+ g([[opaqueObj,0]]),
+ ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
+
+%% Req. OLD-SNMPEA-MIB
+api_test(MaNode) ->
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [intAgentIpAddress]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
+ oid_to_name, [OID]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [[1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp,
+ int_to_enum, ['RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
+ ?line case snmp:date_and_time() of
+ List when list(List), length(List) == 8 -> ok;
+ List when list(List), length(List) == 11 -> ok
+ end.
+
+%% Req. Klas3
+api_test2() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]),
+ g([[fname4,0]]),
+ ?line expect(2, [{[fname4,0], 1}]).
+
+api_test3() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]).
+
+
+unreg_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[snmpInPkts, 0], any}]).
+
+load_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[fname,0], ""}]).
+
+%% Req. Klas1
+load_test_sa() ->
+ gn([[?v1_2(sysServices,sysORLastChange), 0]]),
+ ?line expect(1, [{[fname,0], any}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_get() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
+ [sysName,0]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,0], "test"}]),
+ g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
+ ?line ?v1_2(expect(2, noSuchName, [1,4], any),
+ expect(2, [{[1,3,7,1], noSuchObject},
+ {Key1c4, 2},
+ {[sysDescr,0], "Erlang SNMP agent"},
+ {[1,3,7,2], noSuchObject},
+ {Key1c3, 2},
+ {[sysDescr,0], "Erlang SNMP agent"}])).
+
+%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
+do_mul_get_err() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
+ ?line ?v1_2(expect(1, noSuchName, 5, any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,2], noSuchInstance}])),
+ g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname3,0], noSuchObject},
+ {Key1c3, 2},
+ {[sysName,1], noSuchInstance}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2}, {[fname,0], "test set"},
+ {Key1c3, 2}, {[sysName,0], "test"}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next_err() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[1,3,6,999], endOfMibView},
+ {[fname,0], "test set"},
+ {[1,3,90], endOfMibView},
+ {Key1c3, 2},
+ {[sysName,0], "test"}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set() ->
+ p("Adding one row in subagent table, and one in master table"),
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [sysLocation,0],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[sysLocation,0], "new_value"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ g([NewKeyc4]),
+ ?line expect(3, [{NewKeyc4, 2}]),
+ s([{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]),
+ ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ p("Adding one row in subagent table, and one in master table"),
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {NewKeyc3, 2},
+ {[sysUpTime,0], 45}, % sysUpTime (readOnly)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
+ g([[friendsEntry, [2, 3]]]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB
+sa_mib() ->
+ g([[sa, [2,0]]]),
+ ?line expect(1, [{[sa, [2,0]], 3}]),
+ s([{[sa, [1,0]], s, "sa_test"}]),
+ ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+
+ma_trap1(MA) ->
+ snmpa:send_trap(MA, testTrap2, "standard trap"),
+ ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ snmpa:send_trap(MA, testTrap1, "standard trap"),
+ ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]).
+
+ma_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap2(MA) ->
+ snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
+ {ifAdminStatus, [1], 1},
+ {ifOperStatus, [1], 2}]),
+ ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]).
+
+sa_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "pelle"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]).
+
+ma_v2_trap1(MA) ->
+ ?DBG("ma_v2_traps -> entry with MA = ~p => "
+ "send standard trap: testTrapv22",[MA]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
+ snmpa:send_trap(MA, testTrapv21, "standard trap"),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmp ++ [1]}]).
+
+ma_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"}]).
+
+%% Note: This test case takes a while... actually a couple of minutes.
+ma_v2_inform1(MA) ->
+ ?DBG("ma_v2_inform -> entry with MA = ~p => "
+ "send notification: testTrapv22",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag1, self()},
+ "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag1, [_]} ->
+ ok;
+ {snmp_targets, tag1, Addrs1} ->
+ ?line ?FAIL({bad_addrs, Addrs1})
+ after
+ 5000 ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag1, {got_response, _}} ->
+ ok;
+ {snmp_notification, tag1, {no_response, _}} ->
+ ?line ?FAIL(no_response)
+ after
+ 20000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+
+ %%
+ %% -- The rest is possibly erroneous...
+ %%
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag2, self()},
+ "standard inform", []),
+ ?line expect(2, {inform, false},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag2, [_]} ->
+ ok;
+ {snmp_targets, tag2, Addrs2} ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
+ ?line ?FAIL({bad_addrs, Addrs2})
+ after
+ 5000 ->
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag2, {got_response, _}} ->
+ ?line ?FAIL(got_response);
+ {snmp_notification, tag2, {no_response, _}} ->
+ ok
+ after
+ 240000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag2) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end.
+
+
+ma_v1_2_v2_trap(MA) ->
+ snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
+ {[ifIndex, 1], 1},
+ {[snmpTrapEnterprise, 0], [1,2,3]}]).
+
+
+ma_v1_2_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"},
+ {[snmpTrapEnterprise, 0], ?system}]).
+
+
+sa_v1_2_v2_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+sa_v1_2_v2_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+sa_v1_2_v2_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_bad_value() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 5}, % badValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, badValue, 2, any),
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_gen_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},{NewKeyc4, 2},
+ {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
+ ?line expect(1, genErr, 4, any),
+% The row might have been added; we don't know.
+% (as a matter of fact we do - it is added, because the agent
+% first sets its own vars, and then th SAs. Lets destroy it.
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(2, [{NewKeyc5, ?destroy}]).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_too_big() ->
+ g([[sa, [4,0]]]),
+ ?line expect(1, tooBig).
+
+%% Req. Klas1, system group, snmp group (v1/v2)
+next_across_sa() ->
+ gn([[sysDescr],[klas1,5]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[snmpInPkts, 0], any}]).
+
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
+%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
+%% Req. Klas3, Klas4
+undo_test() ->
+ s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
+ s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
+ ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
+% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+% it depends on which order the agent traverses the varbind list.
+% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
+% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
+ ?line expect(6, genErr, 2, any).
+
+%% Req. Klas3, Klas4
+bad_return() ->
+ g([[fStatus4,4],
+ [fName4,4]]),
+ ?line expect(4, genErr, 2, any),
+ g([[fStatus4,5],
+ [fName4,5]]),
+ ?line expect(5, genErr, 1, any),
+ g([[fStatus4,6],
+ [fName4,6]]),
+ ?line expect(6, genErr, 2, any),
+ gn([[fStatus4,7],
+ [fName4,7]]),
+ ?line expect(7, genErr, 2, any),
+ gn([[fStatus4,8],
+ [fName4,8]]),
+ ?line expect(8, genErr, 1, any),
+ gn([[fStatus4,9],
+ [fName4,9]]),
+ ?line expect(9, genErr, 2, any).
+
+
+%%%-----------------------------------------------------------------
+%%% Test the implementation of standard mibs.
+%%% We should *at least* try to GET all variables, just to make
+%%% sure the instrumentation functions work.
+%%% Note that many of the functions in the standard mib is
+%%% already tested by the normal tests.
+%%%-----------------------------------------------------------------
+
+
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v1.
+%% o Test the counters and control objects in SNMP-STANDARD-MIB
+%%-----------------------------------------------------------------
+snmp_standard_mib(suite) -> [];
+snmp_standard_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?DBG("snmp_standard_mib -> std_mib_init", []),
+ try_test(std_mib_init),
+
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v2),
+ ?DBG("snmp_standard_mib -> std_mib_read", []),
+ try_test(std_mib_read),
+ put(vsn, v1),
+
+ ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+ ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+ ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
+ try_test(std_mib_write, [], [{community, "public"}]),
+ ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
+ try_test(std_mib_asn_err),
+ ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
+ try_test(std_mib_c, [Bad]),
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ try_test(standard_mib_a),
+
+ ?DBG("snmp_standard_mib -> std_mib_finish", []),
+ try_test(std_mib_finish),
+ ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
+ try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_a() ->
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ ?line OutPkts2 = OutPkts + 1,
+ %% There are some more counters we could test here, but it's not that
+ %% important, since they are removed from SNMPv2-MIB.
+ ok.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_init() ->
+ %% disable authentication failure traps. (otherwise w'd get many of
+ %% them - this is also a test to see that it works).
+ s([{[snmpEnableAuthenTraps,0], 2}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_finish() ->
+ %% enable again
+ s([{[snmpEnableAuthenTraps,0], 1}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_test_finish() ->
+ %% force a authenticationFailure
+ std_mib_write(),
+ %% check that we got a trap
+ ?line expect(2, trap, [1,2,3], 4, 0, []).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_read() ->
+ ?DBG("std_mib_read -> entry", []),
+ g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
+ ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
+ ?line expect(1, timeout). % make sure we don't get a trap!
+
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_write() ->
+ ?DBG("std_mib_write -> entry", []),
+ s([{[sysLocation, 0], "new_value"}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_asn_err() ->
+ snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v2 and v3.
+%% o Test the counters and control objects in SNMPv2-MIB
+%%-----------------------------------------------------------------
+snmpv2_mib_2(suite) -> [];
+snmpv2_mib_2(Config) when list(Config) ->
+ ?LOG("snmpv2_mib_2 -> start",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?DBG("snmpv2_mib_2 -> standard mib init",[]),
+ try_test(std_mib_init),
+
+ ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
+ InBadVsns = try_test(std_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
+ put(vsn, v1),
+ try_test(std_mib_read),
+
+ ?DBG("snmpv2_mib_2 -> bad version read",[]),
+ put(vsn, v2),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+
+ ?DBG("snmpv2_mib_2 -> read with bad community",[]),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+
+ ?DBG("snmpv2_mib_2 -> write with public community",[]),
+ try_test(std_mib_write, [], [{community, "public"}]),
+
+ ?DBG("snmpv2_mib_2 -> asn err",[]),
+ try_test(std_mib_asn_err),
+
+ ?DBG("snmpv2_mib_2 -> check counters",[]),
+ try_test(std_mib_c, [Bad]),
+
+ ?DBG("snmpv2_mib_2 -> get som counters",[]),
+ try_test(snmpv2_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
+ try_test(std_mib_finish),
+
+ ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
+ "then disable auth traps",[]),
+ try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
+
+ ?LOG("snmpv2_mib_2 -> done",[]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_3(suite) -> [];
+snmpv2_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v1),
+ try_test(std_mib_read),
+ put(vsn, v3),
+ _Bad = try_test(std_mib_b, [InBadVsns]),
+ try_test(snmpv2_mib_a),
+
+ try_test(std_mib_finish).
+
+-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_test_finish() ->
+ %% force a authenticationFailure
+ ?DBG("ma_v2_inform -> write to std mib",[]),
+ std_mib_write(),
+
+ %% check that we got a trap
+ ?DBG("ma_v2_inform -> await trap",[]),
+ ?line expect(2, v2trap, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0], ?authenticationFailure}]),
+
+ %% and the the inform
+ ?DBG("ma_v2_inform -> await inform",[]),
+ ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0],?authenticationFailure}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_a() ->
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+
+ ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ InBadVsns.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_b(InBadVsns) ->
+ ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ ?line InBadVsns2 = InBadVsns + 1,
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+ ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
+ get_req(4, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
+ ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ get_req(1, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ ?line InBadCommunityNames2 = InBadCommunityNames + 1,
+ ?line InBadCommunityUses2 = InBadCommunityUses + 1,
+ ?line InASNErrs2 = InASNErrs + 1.
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_a() ->
+ ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
+ s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
+ ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
+ {[sysLocation, 0], "val2"}]),
+ s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
+ ?line expect(4, inconsistentValue, 2,
+ [{[sysLocation, 0], "val3"},
+ {[snmpSetSerialNo,0], SetSerial}]),
+ ?line ["val2"] = get_req(5, [[sysLocation,0]]).
+
+
+%%-----------------------------------------------------------------
+%% o Bad community uses/name is tested already
+%% in SNMPv2-MIB and STANDARD-MIB.
+%% o Test add/deletion of rows.
+%%-----------------------------------------------------------------
+snmp_community_mib(suite) -> [];
+snmp_community_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ try_test(snmp_community_mib),
+ ?line unload_master("SNMP-COMMUNITY-MIB").
+
+snmp_community_mib_2(X) -> snmp_community_mib(X).
+
+%% Req. SNMP-COMMUNITY-MIB
+snmp_community_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o Test engine boots / time
+%%-----------------------------------------------------------------
+snmp_framework_mib(suite) -> [];
+snmp_framework_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ try_test(snmp_framework_mib),
+ ?line unload_master("SNMP-FRAMEWORK-MIB").
+
+snmp_framework_mib_2(X) -> snmp_framework_mib(X).
+
+snmp_framework_mib_3(suite) -> [];
+snmp_framework_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(snmp_framework_mib).
+
+
+%% Req. SNMP-FRAMEWORK-MIB
+snmp_framework_mib() ->
+ ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ sleep(5000),
+ ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ if
+ EngineTime+7 < EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ EngineTime+4 > EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ true -> ok
+ end,
+ ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ [Boots] when integer(Boots) -> ok;
+ Else -> ?FAIL(Else)
+ end,
+ ok.
+
+%%-----------------------------------------------------------------
+%% o Test the counters
+%%-----------------------------------------------------------------
+snmp_mpd_mib_3(suite) -> [];
+snmp_mpd_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ UnknownPDUHs = try_test(snmp_mpd_mib_a),
+ try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
+ try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
+
+
+%% Req. SNMP-MPD-MIB
+snmp_mpd_mib_a() ->
+ ?line [UnknownSecs, InvalidMsgs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0]]),
+ Pdu = #pdu{type = 'get-request',
+ request_id = 23,
+ error_status = noError,
+ error_index = 0,
+ varbinds = []},
+ SPdu = #scopedPdu{contextEngineID = "agentEngine",
+ contextName = "",
+ data = Pdu},
+ ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
+ V3Hdr1 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [7],
+ msgSecurityModel = 23, % bad sec model
+ msgSecurityParameters = []},
+ V3Hdr2 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [6], % bad flag combination
+ msgSecurityModel = 3,
+ msgSecurityParameters = []},
+ Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
+ data = SPDUBytes},
+ Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
+ data = SPDUBytes},
+ ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
+ ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
+ snmp_test_mgr:send_bytes(MsgBytes1),
+ snmp_test_mgr:send_bytes(MsgBytes2),
+
+ ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0],
+ [snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownSecs2 = UnknownSecs + 1,
+ ?line InvalidMsgs2 = InvalidMsgs + 1,
+ UnknownPDUHs.
+
+-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
+snmp_mpd_mib_b() ->
+ g([[sysUpTime,0]]),
+ ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
+
+
+snmp_mpd_mib_c(UnknownPDUHs) ->
+ ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownPDUHs2 = UnknownPDUHs + 1.
+
+
+snmp_target_mib(suite) -> [];
+snmp_target_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ try_test(snmp_target_mib),
+ ?line unload_master("SNMP-TARGET-MIB").
+
+snmp_target_mib_2(X) -> snmp_target_mib(X).
+
+snmp_target_mib_3(X) -> snmp_target_mib(X).
+
+snmp_target_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+snmp_notification_mib(suite) -> [];
+snmp_notification_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ try_test(snmp_notification_mib),
+ ?line unload_master("SNMP-NOTIFICATION-MIB").
+
+snmp_notification_mib_2(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib_3(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o add/delete views and try them
+%% o try boundaries
+%%-----------------------------------------------------------------
+snmp_view_based_acm_mib(suite) -> [];
+snmp_view_based_acm_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master("Test2"),
+ snmp_view_based_acm_mib(),
+ ?line unload_master("Test2"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib() ->
+ snmpa:verbosity(net_if,trace),
+ snmpa:verbosity(master_agent,trace),
+ ?LOG("start snmp_view_based_acm_mib test",[]),
+ %% The user "no-rights" is present in USM, and is mapped to security
+ %% name 'no-rights", which is not present in VACM.
+ %% So, we'll add rights for it, try them and delete them.
+ %% We'll give "no-rights" write access to tDescr.0 and read access
+ %% to tDescr2.0
+ %% These are the options we'll use to the mgr
+ Opts = [{user, "no-rights"}, {community, "no-rights"}],
+ %% Find the valid secmodel, and one invalid secmodel.
+ {SecMod, InvSecMod} =
+ case get(vsn) of
+ v1 -> {?SEC_V1, ?SEC_V2C};
+ v2 -> {?SEC_V2C, ?SEC_USM};
+ v3 -> {?SEC_USM, ?SEC_V1}
+ end,
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Now, add a mapping from "no-rights" -> "no-rights-group"
+ GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
+ GRow1 =
+ [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
+ {GRow1Status, ?createAndGo}],
+ ?DBG("set '~p'",[GRow1]),
+ ?line try_test(do_set, [GRow1]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create a mapping for another sec model, and make sure it dosn't
+ %% give us access
+ GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
+ GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
+ {GRow2Status, ?createAndGo}],
+
+ ?DBG("set '~p'",[GRow2]),
+ ?line try_test(do_set, [GRow2]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [GRow2Status]),
+
+ RVName = "rv_name",
+ WVName = "wv_name",
+
+ %% Access row
+ ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
+ ARow1Status = [vacmAccessStatus, ARow1Idx],
+ ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
+ {[vacmAccessReadViewName, ARow1Idx], RVName},
+ {[vacmAccessWriteViewName, ARow1Idx], WVName},
+ {ARow1Status, ?createAndGo}],
+
+ %% This access row would give acces, if InvSecMod was valid.
+ ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
+ ARow2Status = [vacmAccessStatus, ARow2Idx],
+ ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
+ {[vacmAccessReadViewName, ARow2Idx], "internet"},
+ {[vacmAccessWriteViewName, ARow2Idx], "internet"},
+ {ARow2Status, ?createAndGo}],
+
+ ?line try_test(do_set, [ARow2]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [ARow2Status]),
+
+
+ %% Add valid row
+ ?line try_test(do_set, [ARow1]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create the view family
+ VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
+ VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
+ VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
+ VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
+ VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
+ VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
+ VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
+ VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
+
+ ?line try_test(add_row, [VRow1Status]),
+ ?line try_test(add_row, [VRow2Status]),
+ ?line try_test(add_row, [VRow3Status]),
+
+ %% We're supposed to have access now...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Change Row3 to Row4
+ ?line try_test(del_row, [VRow3Status]),
+ ?line try_test(add_row, [VRow4Status]),
+
+ %% We should still have access...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Delete rows
+ ?line try_test(del_row, [GRow1Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete rest of rows
+ ?line try_test(del_row, [ARow1Status]),
+ ?line try_test(del_row, [VRow1Status]),
+ ?line try_test(del_row, [VRow2Status]),
+ ?line try_test(del_row, [VRow4Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+ snmpa:verbosity(master_agent,log).
+
+do_set(Row) ->
+ s(Row),
+ expect(1, Row).
+
+add_row(RowStatus) ->
+ s([{RowStatus, ?createAndGo}]),
+ expect(1, [{RowStatus, ?createAndGo}]).
+
+del_row(RowStatus) ->
+ s([{RowStatus, ?destroy}]),
+ expect(1, [{RowStatus, ?destroy}]).
+
+
+
+use_no_rights() ->
+ g([[xDescr,0]]),
+ ?v1_2_3(expect(11, noSuchName, 1, any),
+ expect(12, [{[xDescr,0], noSuchObject}]),
+ expect(13, authorizationError, 1, any)),
+ g([[xDescr2,0]]),
+ ?v1_2_3(expect(21, noSuchName, 1, any),
+ expect(22, [{[xDescr2,0], noSuchObject}]),
+ expect(23, authorizationError, 1, any)),
+ gn([[xDescr]]),
+ ?v1_2_3(expect(31, noSuchName, 1, any),
+ expect(32, [{[xDescr], endOfMibView}]),
+ expect(33, authorizationError, 1, any)),
+ s([{[xDescr,0], "tryit"}]),
+ ?v1_2_3(expect(41, noSuchName, 1, any),
+ expect(42, noAccess, 1, any),
+ expect(43, authorizationError, 1, any)).
+
+
+use_rights() ->
+ g([[xDescr,0]]),
+ expect(1, [{[xDescr,0], any}]),
+ g([[xDescr2,0]]),
+ expect(2, [{[xDescr2,0], any}]),
+ s([{[xDescr,0], "tryit"}]),
+ expect(3, noError, 0, any),
+ g([[xDescr,0]]),
+ expect(4, [{[xDescr,0], "tryit"}]).
+
+mk_ln(X) ->
+ [length(X) | X].
+
+%%-----------------------------------------------------------------
+%% o add/delete users and try them
+%% o test all secLevels
+%% o test all combinations of protocols
+%% o try bad ops; check counters
+%%-----------------------------------------------------------------
+snmp_user_based_sm_mib_3(suite) -> [];
+snmp_user_based_sm_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ _AgentDir = ?config(agent_dir, Config),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+
+ %% The newUser used here already has VACM access.
+
+ %% Add a new user in the simplest way; just createAndGo
+ try_test(v3_sync, [[{usm_add_user1, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new user
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
+ DesKey1 = lists:sublist(ShaKey1, 16),
+
+ %% Change the new user's keys - 1
+ try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ MgrDir = ?config(mgr_dir, Config),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
+ DesKey2 = lists:sublist(ShaKey2, 16),
+
+ %% Change the new user's keys - 2
+ ?line try_test(v3_sync,
+ [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ reset_usm_mgr(MgrDir),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
+ ?line load_master("Test2"),
+ ?line try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Change the new user's keys - 3
+ ?line try_test(v3_sync,
+ [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new keys
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Try some read requests
+ ?line try_test(v3_sync, [[{usm_read, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Delete the new user
+ ?line try_test(v3_sync, [[{usm_del_user, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try some bad requests
+ ?line try_test(v3_sync, [[{usm_bad, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("SNMP-USER-BASED-SM-MIB").
+
+-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
+
+usm_add_user1() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+usm_use_user() ->
+ v2_proc().
+
+
+%% Change own public keys
+usm_key_change1(ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_shaxxxxxxxxxx",
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_desxxxxxx",
+ DesKey),
+ Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change own private keys
+usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change other's public keys
+usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
+ s(Vbs1),
+ ?line expect(1, noAccess, 1, any),
+ Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs2),
+ ?line expect(2, noAccess, 1, any),
+
+
+ Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs3),
+ ?line expect(1, Vbs3).
+
+usm_read() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ?line g([[usmUserSecurityName, NewRowIndex],
+ [usmUserCloneFrom, NewRowIndex],
+ [usmUserAuthKeyChange, NewRowIndex],
+ [usmUserOwnAuthKeyChange, NewRowIndex],
+ [usmUserPrivKeyChange, NewRowIndex],
+ [usmUserOwnPrivKeyChange, NewRowIndex]]),
+ ?line expect(1,
+ [{[usmUserSecurityName, NewRowIndex], "newUser"},
+ {[usmUserCloneFrom, NewRowIndex], [0,0]},
+ {[usmUserAuthKeyChange, NewRowIndex], ""},
+ {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
+ {[usmUserPrivKeyChange, NewRowIndex], ""},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
+ ok.
+
+
+
+usm_del_user() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
+
+-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
+
+-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
+
+-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
+
+-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
+
+-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
+
+usm_bad() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, inconsistentName, 1, any),
+
+ RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs2),
+ ?line expect(2, wrongValue, 1, any),
+
+ RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs3),
+ ?line expect(3, Vbs3),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
+ ?line expect(4, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
+ ?line expect(5, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
+ ?line expect(6, wrongValue, 1, any),
+ ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
+ ?line expect(7, wrongValue, 1, any),
+
+ Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs4),
+ ?line expect(1, Vbs4),
+
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Loop through entire MIB, to make sure that all instrum. funcs
+%% works.
+%% Load all std mibs that are not loaded by default.
+%%-----------------------------------------------------------------
+loop_mib(suite) -> [];
+loop_mib(Config) when list(Config) ->
+ ?LOG("loop_mib -> initiate case",[]),
+ %% snmpa:verbosity(master_agent,debug),
+ %% snmpa:verbosity(mib_server,info),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?DBG("loop_mib -> try",[]),
+ try_test(loop_mib_1),
+ ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ %% snmpa:verbosity(master_agent,log),
+ %% snmpa:verbosity(mib_server,silence),
+ ?LOG("loop_mib -> done",[]).
+
+
+loop_mib_2(suite) -> [];
+loop_mib_2(Config) when list(Config) ->
+ ?LOG("loop_mib_2 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_2 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_2 -> load mibs",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_2 -> unload mibs",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?LOG("loop_mib_2 -> done",[]).
+
+
+loop_mib_3(suite) -> [];
+loop_mib_3(Config) when list(Config) ->
+ ?LOG("loop_mib_3 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_3 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_3 -> load mibs",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_3 -> unload mibs",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?LOG("loop_mib_3 -> done",[]).
+
+
+%% Req. As many mibs all possible
+loop_mib_1() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_1([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_1(Oid, N) ->
+ ?DBG("loop_it_1 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_1 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_1 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_1(NOid, N+1);
+ #pdu{type='get-response', error_status=noSuchName, error_index=1,
+ varbinds=[_]} ->
+ ?DBG("loop_it_1 -> done",[]),
+ N;
+
+ #pdu{type = Type, error_status = Err, error_index = Idx,
+ varbinds = Vbs} ->
+ exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
+ end.
+
+%% Req. As many mibs all possible
+loop_mib_2() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_2([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_2(Oid, N) ->
+ ?DBG("loop_it_2 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p",[NOid]),
+ N;
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_2 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_2(NOid, N+1)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+
+
+
+
+%% These are (ticket) test cases where the initiation has to be done
+%% individually.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1128
+%% Slogan: Bug in handling of createAndWait set-requests.
+%%-----------------------------------------------------------------
+otp_1128(suite) -> [];
+otp_1128(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1128),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1128_2(X) -> otp_1128(X).
+
+otp_1128_3(X) -> otp_1128(X).
+
+otp_1128() ->
+ io:format("Testing bug reported in ticket OTP-1128...~n"),
+
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+
+ s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(29, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(31, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(32, [{NewKeyc5, ?destroy}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1129, OTP-1169
+%% Slogan: snmpa:int_to_enum crashes on bad oids
+%%-----------------------------------------------------------------
+otp_1129(suite) -> [];
+otp_1129(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ try_test(otp_1129_i, [node()]),
+ ?line unload_master("Klas3").
+
+otp_1129_2(X) -> otp_1129(X).
+
+otp_1129_3(X) -> otp_1129(X).
+
+otp_1129_i(MaNode) ->
+ io:format("Testing bug reported in ticket OTP-1129...~n"),
+ false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
+ false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1131
+%% Slogan: Agent crashes / erlang node halts if RowIndex in a
+%% setrequest is of bad type, e.g. an INDEX {INTEGER},
+%% and RowIdenx [3,2].
+%%-----------------------------------------------------------------
+otp_1131(suite) -> [];
+otp_1131(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas1"),
+ try_test(otp_1131),
+ ?line unload_master("Klas1").
+
+otp_1131_2(X) -> otp_1131(X).
+
+otp_1131_3(X) -> otp_1131(X).
+
+otp_1131() ->
+ io:format("Testing bug reported in ticket OTP-1131...~n"),
+ s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
+ {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1162
+%% Slogan: snmp_agent can't handle wrongValue from instrum.func
+%%-----------------------------------------------------------------
+otp_1162(suite) -> [];
+otp_1162(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ try_test(otp_1162),
+ stop_subagent(SA).
+
+otp_1162_2(X) -> otp_1162(X).
+
+otp_1162_3(X) -> otp_1162(X).
+
+otp_1162() ->
+ s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
+ ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1222
+%% Slogan: snmp agent crash if faulty index is returned from instrum
+%%-----------------------------------------------------------------
+otp_1222(suite) -> [];
+otp_1222(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ ?line load_master("Klas4"),
+ try_test(otp_1222),
+ ?line unload_master("Klas3"),
+ ?line unload_master("Klas4").
+
+otp_1222_2(X) -> otp_1222(X).
+
+otp_1222_3(X) -> otp_1222(X).
+
+otp_1222() ->
+ io:format("Testing bug reported in ticket OTP-1222...~n"),
+ s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
+ ?line expect(1, genErr, 0, any),
+ s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
+ ?line expect(2, genErr, 0, any).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1298
+%% Slogan: Negative INTEGER values are treated as positive.
+%%-----------------------------------------------------------------
+otp_1298(suite) -> [];
+otp_1298(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1298),
+ ?line unload_master("Klas2").
+
+otp_1298_2(X) -> otp_1298(X).
+
+otp_1298_3(X) -> otp_1298(X).
+
+otp_1298() ->
+ io:format("Testing bug reported in ticket OTP-1298...~n"),
+ s([{[fint,0], -1}]),
+ ?line expect(1298, [{[fint,0], -1}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1331
+%% Slogan: snmp_generic should return noError when deleting non-ex row
+%%-----------------------------------------------------------------
+otp_1331(suite) -> [];
+otp_1331(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1331),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1331_2(X) -> otp_1331(X).
+
+otp_1331_3(X) -> otp_1331(X).
+
+otp_1331() ->
+ NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(1, [{NewKeyc5, ?destroy}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1338
+%% Slogan: snmp bug in initialisation of default values for mnesia tabs
+%%-----------------------------------------------------------------
+otp_1338(suite) -> [];
+otp_1338(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1338),
+ ?line unload_master("Klas2").
+
+otp_1338_2(X) -> otp_1338(X).
+
+otp_1338_3(X) -> otp_1338(X).
+
+otp_1338() ->
+ s([{[kStatus2, 7], i, ?createAndGo}]),
+ ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
+ g([[kName2, 7]]),
+ ?line expect(2, [{[kName2, 7], "JJJ"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1342
+%% Slogan: default impl of snmp table can't handle bad index access,
+%% Set when INDEX is read-write gets into an infinite loop!
+%%-----------------------------------------------------------------
+otp_1342(suite) -> [];
+otp_1342(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas4"),
+ try_test(otp_1342),
+ ?line unload_master("Klas4").
+
+otp_1342_2(X) -> otp_1342(X).
+
+otp_1342_3(X) -> otp_1342(X).
+
+otp_1342() ->
+ s([{[fIndex5, 1], i, 1},
+ {[fName5, 1], i, 3},
+ {[fStatus5, 1], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1366
+%% Slogan: snmp traps not sent to all managers
+%% Note: NYI! We need a way to tell the test server that we need
+%% mgrs on two different machines.
+%%-----------------------------------------------------------------
+otp_1366(suite) -> [];
+otp_1366(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1366),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1366_2(X) -> otp_1366(X).
+
+otp_1366_3(X) -> otp_1366(X).
+
+otp_1366() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ 'NYI'.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2776
+%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
+%%-----------------------------------------------------------------
+otp_2776(suite) -> [];
+otp_2776(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_2776).
+
+otp_2776_2(X) -> otp_2776(X).
+
+otp_2776_3(X) -> otp_2776(X).
+
+otp_2776() ->
+ io:format("Testing bug reported in ticket OTP-2776...~n"),
+
+ Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
+ Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
+ Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
+ Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
+ Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
+ Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
+ Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
+ Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
+ Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
+ Dt10_invalid = [],
+ Dt11_invalid = [kalle,hobbe],
+ L = [{ 1, true, Dt01_valid},
+ { 2, true, Dt02_valid},
+ { 3, true, Dt03_valid},
+ { 4, false, Dt04_invalid},
+ { 5, true, Dt05_valid},
+ { 6, true, Dt06_valid},
+ { 7, false, Dt07_invalid},
+ { 8, true, Dt08_valid},
+ { 9, false, Dt09_invalid},
+ {10, false, Dt10_invalid},
+ {11, false, Dt11_invalid}],
+
+ ?line ok = validate_dat(L).
+
+
+validate_dat(L) -> validate_dat(L,[]).
+
+validate_dat([],V) ->
+ Fun = fun({_,X}) -> case X of
+ ok -> false;
+ _ -> true
+ end
+ end,
+ validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
+validate_dat([{Id,E,Dat}|T],V) ->
+ validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
+
+validate_dat1([]) -> ok;
+validate_dat1(L) -> {error,L}.
+
+validate_dat2(Id, E, Dat) ->
+ Res = case {E,snmp:validate_date_and_time(Dat)} of
+ {E,E} -> ok;
+ {E,A} -> {E,A}
+ end,
+ {Id, Res}.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2979
+%% Slogan: get-next on more than 1 column in an empty table
+%% returns bad response.
+%%-----------------------------------------------------------------
+otp_2979(suite) -> [];
+otp_2979(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Test1"),
+ ?line init_old(),
+ try_test(otp_2979),
+ ?line unload_master("Test1").
+
+otp_2979_2(X) -> otp_2979(X).
+
+otp_2979_3(X) -> otp_2979(X).
+
+otp_2979() ->
+ gn([[sparseDescr], [sparseStatus]]),
+ ?line expect(1, [{[sparseStr,0], "slut"},
+ {[sparseStr,0], "slut"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3187
+%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% endOfTable - should return value.
+%%-----------------------------------------------------------------
+otp_3187(suite) -> [];
+otp_3187(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ otp_3187(),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+otp_3187_2(X) -> otp_3187(X).
+
+otp_3187_3(X) -> otp_3187(X).
+
+otp_3187() ->
+ ?line Elements =
+ snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
+ lists:foreach(fun(E) ->
+ ?line if E == endOfTable ->
+ ?FAIL(endOfTable);
+ true -> ok
+ end
+ end, Elements).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3542
+%% Slogan:
+%%-----------------------------------------------------------------
+otp_3542(suite) -> [];
+otp_3542(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_3542).
+
+otp_3542() ->
+ io:format("SNMP v3 discovery...~n"),
+ ?line Res = snmp_test_mgr:d(),
+ io:format("SNMP v3 discovery result: ~p~n",[Res]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3725
+%% Slogan: Slow response time on snmpa:int_to_enum
+%%-----------------------------------------------------------------
+otp_3725(suite) -> [];
+otp_3725(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_3725_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+otp_3725_test(MaNode) ->
+ io:format("Testing feature requested in ticket OTP-3725...~n"),
+ ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
+ ?DBG("otp_3725_test -> Db = ~p",[Db]),
+
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [Db, intAgentIpAddress]),
+ ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
+ [Db,OID]),
+ ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [Db, [1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, 'RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-4394
+%% Slogan: Target mib tag list check invalid
+%%-----------------------------------------------------------------
+
+
+
+init_otp_4394(Config) when list(Config) ->
+ ?DBG("init_otp_4394 -> entry with"
+ "~n Config: ~p", [Config]),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ MasterAgentVerbosity = {master_agent_verbosity, trace},
+ NetIfVerbosity = {net_if_verbosity, trace},
+ Opts = [MasterAgentVerbosity,NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config,Opts)].
+
+otp_4394_config(AgentDir, MgrDir, Ip0) ->
+ ?DBG("otp_4394_config -> entry with"
+ "~n AgentDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ Vsn = [v1],
+ Ip = tuple_to_list(Ip0),
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?TRAP_UDP, Ip, 4000,
+ "OTP-4394 test"),
+ ?line case update_usm(Vsn, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsn, MgrDir);
+ false ->
+ ?line ok
+ end,
+ C1 = {"a", "all-rights", "initial", "", "pc"},
+ C2 = {"c", "secret", "secret_name", "", "secret_tag"},
+ ?line write_community_conf(AgentDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentDir),
+ Ta1 = {"shelob v1",
+ [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ "pc1",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [],
+ 2048},
+ Ta2 = {"bifur v1",
+ [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ "pc2",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [], 2048},
+ ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentDir, Vsn),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+
+
+finish_otp_4394(Config) when list(Config) ->
+ ?DBG("finish_otp_4394 -> entry", []),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ erase(mgr_node),
+ lists:keydelete(vsn, 1, C1).
+
+otp_4394_test(suite) -> [];
+otp_4394_test(Config) ->
+ ?DBG("otp_4394_test -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_4394_test1),
+ ?DBG("otp_4394_test -> done", []),
+ ok.
+
+otp_4394_test1() ->
+ ?DBG("otp_4394_test1 -> entry", []),
+ gn([[1,1]]),
+ Res =
+ case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
+ %% {error, 1, {"?",[]}, {"~w",[timeout]}}
+ {error, 1, _, {_, [timeout]}} ->
+ ?DBG("otp_4394_test1 -> expected result: timeout", []),
+ ok;
+ Else ->
+ Else
+ end,
+ ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
+ Res.
+
+
+%%%--------------------------------------------------
+%%% Used to test the standard mib with our
+%%% configuration.
+%%%--------------------------------------------------
+run(F, A, Opts) ->
+ M = get(mib_dir),
+ Dir = get(mgr_dir),
+ User = snmp_misc:get_option(user, Opts, "all-rights"),
+ SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
+ EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
+ CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
+ Community = snmp_misc:get_option(community, Opts, "all-rights"),
+ ?DBG("run -> start crypto app",[]),
+ Crypto = case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ ?CRYPTO_START()
+ end,
+ ?DBG("run -> Crypto: ~p",[Crypto]),
+ catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ ?DBG("run -> config:~n"
+ "\tM: ~p~n"
+ "\tDir: ~p~n"
+ "\tUser: ~p~n"
+ "\tSecLevel: ~p~n"
+ "\tEngineID: ~p~n"
+ "\tCtxEngineID: ~p~n"
+ "\tCommunity: ~p~n"
+ "\tStdM: ~p",
+ [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
+ case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
+ {packet_server_debug,true},
+ {debug,true},
+ {agent, get(master_host)},
+ {agent_udp, 4000},
+ {trap_udp, 5000},
+ {recbuf,65535},
+ quiet,
+ get(vsn),
+ {community, Community},
+ {user, User},
+ {sec_level, SecLevel},
+ {engine_id, EngineID},
+ {context_engine_id, CtxEngineID},
+ {dir, Dir},
+ {mibs, mibs(StdM, M)}]) of
+ {ok, _Pid} ->
+ Res = apply(?MODULE, F, A),
+ catch snmp_test_mgr:stop(),
+ Res;
+ Err ->
+ io:format("Error starting manager: ~p\n", [Err]),
+ catch snmp_test_mgr:stop(),
+ ?line exit({mgr_start, Err})
+ end.
+
+
+mibs(StdMibDir,MibDir) ->
+ [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
+ join(MibDir, "OLD-SNMPEA-MIB.bin"),
+ join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
+ join(StdMibDir, "SNMP-MPD-MIB"),
+ join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
+ join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
+ join(StdMibDir, "SNMP-TARGET-MIB"),
+ join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
+ join(MibDir, "Klas1.bin"),
+ join(MibDir, "Klas2.bin"),
+ join(MibDir, "Klas3.bin"),
+ join(MibDir, "Klas4.bin"),
+ join(MibDir, "SA-MIB.bin"),
+ join(MibDir, "TestTrap.bin"),
+ join(MibDir, "Test1.bin"),
+ join(MibDir, "Test2.bin"),
+ join(MibDir, "TestTrapv2.bin")].
+
+join(D,F) ->
+ filename:join(D,F).
+
+%% string used in index
+is(S) -> [length(S) | S].
+
+try_test(Func) ->
+ call(get(mgr_node), ?MODULE, run, [Func, [], []]).
+
+try_test(Func, A) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, []]).
+
+try_test(Func, A, Opts) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
+
+call(N,M,F,A) ->
+ ?DBG("call -> entry with~n"
+ " N: ~p~n"
+ " M: ~p~n"
+ " F: ~p~n"
+ " A: ~p~n"
+ " when~n"
+ " get(): ~p",
+ [N,M,F,A,get()]),
+ spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
+ receive
+ {done, {'EXIT', Rn}, Loc} ->
+ ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
+ put(test_server_loc, Loc),
+ exit(Rn);
+ {done, Ret, Zed} ->
+ ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
+ Ret
+ end.
+
+wait(From, Env, M, F, A) ->
+ ?DBG("wait -> entry with ~n"
+ "\tFrom: ~p~n"
+ "\tEnv: ~p",[From,Env]),
+ lists:foreach(fun({K,V}) -> put(K,V) end, Env),
+ Rn = (catch apply(M, F, A)),
+ ?DBG("wait -> Rn: ~n~p", [Rn]),
+ From ! {done, Rn, get(test_server_loc)},
+ exit(Rn).
+
+expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
+expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
+expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
+expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
+
+get_req(Id, Vars) ->
+ ?DBG("get_req -> entry with~n"
+ "\tId: ~p~n"
+ "\tVars: ~p",[Id,Vars]),
+ g(Vars),
+ ?DBG("get_req -> await response",[]),
+ {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
+ ?DBG("get_req -> response: ~p",[Val]),
+ Val.
+
+get_next_req(Vars) ->
+ ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
+ gn(Vars),
+ ?DBG("get_next_req -> await response",[]),
+ Response = snmp_test_mgr:receive_response(),
+ ?DBG("get_next_req -> response: ~p",[Response]),
+ Response.
+
+
+
+start_node(Name) ->
+ ?LOG("start_node -> entry with Name: ~p",[Name]),
+ M = list_to_atom(?HOSTNAME(node())),
+ ?DBG("start_node -> M: ~p",[M]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ ?DBG("start_node -> Pa: ~p",[Pa]),
+
+ Args = case init:get_argument('CC_TEST') of
+ {ok, [[]]} ->
+ " -pa /clearcase/otp/libraries/snmp/ebin ";
+ {ok, [[Path]]} ->
+ " -pa " ++ Path;
+ error ->
+ ""
+ end,
+ %% Do not use start_link!!! (the proc that calls this one is tmp)
+ ?DBG("start_node -> Args: ~p~n",[Args]),
+ A = Args ++ " -pa " ++ Pa,
+ case (catch ?START_NODE(Name, A)) of
+ {ok, Node} ->
+ %% Tell the test_server to not clean up things it never started.
+ ?DBG("start_node -> Node: ~p",[Node]),
+ {ok, Node};
+ Else ->
+ ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
+ ?line ?FAIL(Else)
+ end.
+
+
+stop_node(Node) ->
+ ?LOG("stop_node -> Node: ~p",[Node]),
+ rpc:cast(Node, erlang, halt, []).
+
+p(X) ->
+ io:format(user, X++"\n", []).
+
+sleep(X) ->
+ receive
+ after
+ X -> ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Configuration
+%%%-----------------------------------------------------------------
+config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
+ ?TRAP_UDP, AIp, 4000,
+ "test"),
+ ?line case update_usm(Vsns, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsns, MgrDir);
+ false ->
+ ?line ok
+ end,
+ ?line update_community(Vsns, AgentDir),
+ ?line update_vacm(Vsns, AgentDir),
+ ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentDir, Vsns),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+delete_files(Config) ->
+ Dir = ?config(agent_dir, Config),
+ {ok, List} = file:list_dir(Dir),
+ lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
+ List).
+
+update_usm(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+update_usm_mgr(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.conf"),
+ filename:join(Dir,"usm.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ file:close(Fid).
+
+reset_usm_mgr(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.old"),
+ filename:join(Dir,"usm.conf")).
+
+
+update_community([v3], _Dir) -> ok;
+update_community(_, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
+ []),
+ file:close(Fid).
+
+
+-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
+update_vacm(_Vsn, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
+ ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
+ "~w, excluded, null}.\n", [?tDescr_instance]),
+ file:close(Fid).
+
+
+vacm_ver(v1) -> v1;
+vacm_ver(v2) -> v2c;
+vacm_ver(v3) -> usm.
+
+
+write_community_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
+ ok = write_community_conf1(Fid, Confs),
+ file:close(Fid).
+
+write_community_conf1(_, []) ->
+ ok;
+write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
+ [ComIdx, ComName, SecName, CtxName, TransTag]),
+ write_community_conf1(Fid, Confs).
+
+
+write_target_addr_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ ok = write_target_addr_conf1(Fid, Confs),
+ file:close(Fid).
+
+
+write_target_addr_conf1(_, []) ->
+ ok;
+write_target_addr_conf1(Fid,
+ [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
+ [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz]),
+ write_target_addr_conf1(Fid, Confs).
+
+write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ ok = io:format(Fid,
+ "{\"~s\", ~w, ~w, 1500, 3, "
+ "\"std_trap\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP, mk_param(Vsn)]),
+ case Vsn of
+ v1 -> ok;
+ v2 ->
+ ok = io:format(Fid,
+ "{\"~s.2\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)]);
+ v3 ->
+ ok = io:format(Fid,
+ "{\"~s.3\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\", "
+ "\"mgrEngine\", [], 1024}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)])
+ end
+ end,
+ Vsns),
+ file:close(Fid).
+
+mk_param(v1) -> "target_v1";
+mk_param(v2) -> "target_v2";
+mk_param(v3) -> "target_v3".
+
+mk_ip([A,B,C,D], Vsn) ->
+ io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
+
+
+rewrite_target_addr_conf(Dir,NewPort) ->
+ TAFile = filename:join(Dir, "target_addr.conf"),
+ ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
+ case file:read_file_info(TAFile) of
+ {ok, _} -> ok;
+ {error, R} -> ?ERR("failure reading file info of "
+ "target address config file: ~p",[R]),
+ ok
+ end,
+
+ ?line [TrapAddr|Addrs] =
+ snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
+
+ ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
+
+ NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
+
+ ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
+
+ ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
+ filename:join(Dir,"target_addr.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+
+ ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
+
+ file:close(Fid).
+
+rewrite_target_addr_conf1(O) ->
+ {ok,O}.
+
+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) ->
+ ?LOG("rewrite_target_addr_conf2 -> entry with "
+ "~n O: ~p",[O]),
+ O.
+
+
+rewrite_target_addr_conf3(_,[]) -> ok;
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
+ ParamName,EngineId}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % ParamsName
+ "\"~s\"}.", % EngineId
+ [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
+ rewrite_target_addr_conf3(Fid,T);
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
+ ParamName,EngineId,TMask,MMS}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % TagList
+ "\"~s\", " % ParamsName
+ "\"~s\"," % EngineId
+ "~p, " % TMask
+ "~p}.", % MMS
+ [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
+ EngineId,TMask,MMS]),
+ rewrite_target_addr_conf3(Fid,T).
+
+reset_target_addr_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
+ filename:join(Dir,"target_addr.conf")).
+
+write_target_params_conf(Dir, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ MP = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> v3
+ end,
+ SM = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> usm
+ end,
+ ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
+ "\"all-rights\", noAuthNoPriv}.~n",
+ [Vsn, MP, SM])
+ end,
+ Vsns),
+ file:close(Fid).
+
+rewrite_target_params_conf(Dir, SecName, SecLevel) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
+ filename:join(Dir,"target_params.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
+ [SecName, SecLevel]),
+ file:close(Fid).
+
+reset_target_params_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.old"),
+ filename:join(Dir,"target_params.conf")).
+
+write_notify_conf(Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
+ ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
+ ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
+ file:close(Fid).
+
+ver_to_trap_str([v1]) -> "v1";
+ver_to_trap_str([v2]) -> "v2";
+% default is to use the latest snmp version
+ver_to_trap_str([v1,v2]) -> "v2".
+
+
+
+write_view_conf(Dir) ->
+ {ok, Fid} = file:open(a(Dir,"view.conf"),write),
+ ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
+ ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
+ file:close(Fid).
+
+a(A,B) -> lists:append(A,B).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+copy_file(From, To) ->
+ {ok, Bin} = file:read_file(From),
+ ok = file:write_file(To, Bin).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+display_memory_usage() ->
+ Info = snmpa:info(snmp_master_agent),
+ TreeSize = lists_key1search(tree_size_bytes, Info),
+ ProcMem = lists_key1search(process_memory, Info),
+ MibDbSize = lists_key1search([db_memory,mib], Info),
+ NodeDbSize = lists_key1search([db_memory,node], Info),
+ TreeDbSize = lists_key1search([db_memory,tree], Info),
+ ?INF("Memory usage: "
+ "~n Tree size: ~p"
+ "~n Process memory size: ~p"
+ "~n Mib db size: ~p"
+ "~n Node db size: ~p"
+ "~n Tree db size: ~p",
+ [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
+
+lists_key1search([], Res) ->
+ Res;
+lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ lists_key1search(Keys, Val);
+ false ->
+ undefined
+ end;
+lists_key1search(Key, List) when atom(Key) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ Val;
+ false ->
+ undefined
+ end.
+
+
+regs() ->
+ lists:sort(registered()).
diff --git a/lib/snmp/test/exp/snmp_agent_v1_test.erl b/lib/snmp/test/exp/snmp_agent_v1_test.erl
new file mode 100644
index 0000000000..5379d6d8cf
--- /dev/null
+++ b/lib/snmp/test/exp/snmp_agent_v1_test.erl
@@ -0,0 +1,2673 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmp_agent_v1_test).
+
+%% TODO
+%% * Test fault-tolerance (kill master etc)
+%%
+
+-export([]).
+
+-define(application, snmp).
+
+-include_lib("kernel/include/file.hrl").
+-include("test_server.hrl").
+-include("snmp_test_lib.hrl").
+-define(SNMP_USE_V3, true).
+-include_lib("snmp/include/snmp_types.hrl").
+
+
+-define(klas1, [1,3,6,1,2,1,7]).
+-define(klas2, [1,3,6,1,2,1,9]).
+-define(klas3, [1,3,6,1,2,1,8,1]).
+-define(klas4, [1,3,6,1,2,1,8,4]).
+-define(sa, [1,3,6,1,4,1,193,2]).
+-define(system, [1,3,6,1,2,1,1]).
+-define(snmp, [1,3,6,1,2,1,11]).
+-define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
+-define(ericsson, [1,3,6,1,4,1,193]).
+-define(testTrap, [1,3,6,1,2,1,15,0]).
+-define(xDescr, [1,3,6,1,2,1,17,1]).
+-define(xDescr2, [1,3,6,1,2,1,17,2]).
+
+-define(active, 1).
+-define(notInService, 2).
+-define(notReady, 3).
+-define(createAndGo, 4).
+-define(createAndWait, 5).
+-define(destroy, 6).
+
+-define(TRAP_UDP, 5000).
+
+-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
+
+
+%% -- test manager defines --
+-define(MGR, snmp_test_mgr).
+-define(GN(X), ?MGR:gn(X)).
+-define(G(X), ?MGR:g(X)).
+-define(S(X), ?MGR:s(X)).
+-define(GB(X), ?MGR:gb(X)).
+-define(SEND_BYTES(X), ?MGR:send_bytes(X)).
+
+%% -- agent test lib defines --
+-define(LIB, snmp_agent_test_lib).
+-define(INIT_CASE(X), ?LIB:init_case(X)).
+-define(TRY_TEST1(A), ?LIB:try_test(A)).
+-define(TRY_TEST2(A, B), ?LIB:try_test(A, B)).
+-define(TRY_TEST3(A, B, C), ?LIB:try_test(A, B, C)).
+-define(START_SA(A, B, C), ?LIB:start_subagent(A, B, C)).
+-define(STOP_SA(A), ?LIB:stop_subagent(A)).
+-define(P1(C), ?LIB:p(C)).
+-define(P2(F), ?LIB:p(F,[])).
+-define(P3(F,A), ?LIB:p(F,A)).
+-define(RPC(N, F, A), ?LIB:rpc(N, F, A)).
+
+
+-define(v1_2(V1,V2),
+ case get(vsn) of
+ v1 -> V1;
+ _ -> V2
+ end).
+
+-define(v1_2_3(V1,V2,V3),
+ case get(vsn) of
+ v1 -> V1;
+ v2 -> V2;
+ _ -> V3
+ end).
+
+all(suite) -> {req,
+ [mnesia, distribution,
+ {local_slave_nodes, 2}, {time, 360}],
+ [{conf, init, cases(), finish}]}.
+
+init_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+cases() ->
+ [simple,
+ db_notify_client,
+ processing,
+ big,
+ big2,
+ %% implied,
+ loop_mib,
+ api,
+ subagent,
+ mnesia,
+ multiple_reqs,
+ sa_register,
+ v1_trap,
+ sa_error,
+ next_across_sa,
+ undo,
+ standard_mibs,
+ sparse_table,
+ cnt_64,
+ opaque,
+ %% opaque].
+
+ change_target_addr_config,
+
+ reported_bugs,
+ tickets
+ ].
+
+
+init(Config) ->
+ init_all(Config),
+ init_v1(Config).
+
+finish(Config) ->
+ finish_v1(Config),
+ finish_all(Config).
+
+init_v1(Config) when list(Config) ->
+ ?line SaNode = ?config(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v1} | start_v1_agent(Config)].
+
+finish_v1(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%%-----------------------------------------------------------------
+%% This function takes care of the old OTP-SNMPEA-MIB.
+%% Unfortunately, the testcases were written to use the data in the
+%% internal tables, and these table are now obsolete and not used
+%% by the agent. Therefore, we emulate them by using
+%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
+%%
+%% These two rows must exist in intCommunityTable
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+%% (But with the manager's IP address)
+%%
+%%-----------------------------------------------------------------
+init_old() ->
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [6 | "public"],
+ {get(mip), "public", 2, 2}),
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [13 | "standard trap"],
+ {get(mip), "standard trap", 2, 1}),
+ snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
+
+
+%% =========================================================================
+%%
+%% C A S E S
+%%
+%% =========================================================================
+
+%% -- simple --
+
+simple(suite) -> [];
+simple(Config) when list(Config) ->
+ ?P1(simple),
+ ?INIT_CASE(Config),
+
+ ?TRY_TEST1(simple_standard_test).
+
+simple_standard_test() ->
+ ?DBG("simple_standard_test -> entry",[]),
+ ?GN([[1,1]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[1,3]]),
+ ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[1,3,6]]),
+ ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[1,3,6,1]]),
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[1,3,6,1,2]]),
+ ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[1,3,6,1,2,1]]),
+ ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[1,3,6,1,2,1,1]]),
+ ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?GN([[sysDescr]]),
+ ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?G([[sysDescr,0]]),
+ ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
+
+ ?G([[sysDescr]]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{[sysDescr], noSuchObject}])),
+
+ ?G([[1,6,7,0]]),
+ ?line ?v1_2(expect(41, noSuchName, 1, any),
+ expect(3, [{[1,6,7,0], noSuchObject}])),
+
+ ?GN([[1,13]]),
+ ?line ?v1_2(expect(4, noSuchName,1, any),
+ expect(4, [{[1,13], endOfMibView}])),
+
+ ?S([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?G([[sysLocation, 0]]),
+ ?line expect(6, [{[sysLocation, 0], "new_value"}]),
+
+ io:format("Testing noSuchName and badValue...~n"),
+ ?S([{[sysServices,0], 3}]),
+ ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
+
+ ?S([{[sysLocation, 0], i, 3}]),
+ ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
+ ?DBG("simple_standard_test -> done",[]),
+ ok.
+
+
+%% -- db_notify_client --
+
+%% This is run in the agent node
+db_notify_client(suite) -> [];
+db_notify_client(Config) when list(Config) ->
+ ?P1(db_notify_client),
+ {SaNode, MgrNode, MibDir} = ?INIT_CASE(Config),
+ ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
+ [SaNode,MgrNode,MibDir]),
+ snmpa_local_db:register_notify_client(self(),?MODULE),
+
+ %% This call (the manager) will issue to set operations, so
+ %% we expect to receive to notify(insert) calls.
+ ?TRY_TEST1(db_notify_client_test),
+
+ ?DBG("await first notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
+ end,
+
+ ?DBG("await second notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
+ end,
+
+ snmpa_local_db:unregister_notify_client(self()).
+
+
+%% This is run in the manager node
+db_notify_client_test() ->
+ ?DBG("set first new sysLocation",[]),
+ ?S([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?DBG("set second new sysLocation",[]),
+ ?S([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]).
+
+notify(Pid,What) ->
+ ?DBG("notify(~p,~p) -> called",[Pid,What]),
+ Pid ! {db_notify_test_reply,What}.
+
+
+%% -- processing --
+
+%% Req. Test2
+processing(suite) -> [];
+processing(Config) when list(Config) ->
+ ?P1(processing),
+ ?INIT_CASE(Config),
+
+ ?line load_master("Test2"),
+ ?TRY_TEST1(v1_proc),
+ ?line unload_master("Test2").
+
+v1_proc() ->
+ ?DBG("v1_proc -> entry", []),
+ %% According to RFC1157.
+ %% Template: <Section>:<list no>
+ v1_get_p(),
+ v1_get_next_p(),
+ v1_set_p().
+
+v1_get_p() ->
+ %% 4.1.2:1
+ ?G([[test2]]),
+ ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
+ ?G([[tDescr]]),
+ ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
+ ?G([[tDescr2,0]]),
+ ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ ?G([[tDescr3,0]]),
+ ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ ?G([[tDescr4,0]]),
+ ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ ?G([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ {[tDescr,0], 'NULL'}]),
+ ?G([[sysDescr,3]]),
+ ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+
+ %% 4.1.2:2
+ ?G([[tTable]]),
+ ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
+ ?G([[tEntry]]),
+ ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
+
+ %% 4.1.2:3
+ ?G([[tTooBig, 0]]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.2:4
+ ?G([[tGenErr1, 0]]),
+ ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ ?G([[tGenErr2, 0]]),
+ ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ ?G([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]).
+
+v1_get_next_p() ->
+ %% 4.1.3:1
+ ?GN([[1,3,7,1]]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+
+ ?GN([[tDescr2]]),
+ ?line expect(11, tooBig, 0, any),
+
+ %% 4.1.3:2
+ ?GN([[tTooBig]]),
+ io:format("We currently don't handle tooBig correct!!!\n"),
+ %% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
+ ?line expect(20, tooBig, 0, any),
+
+ %% 4.1.3:3
+ ?GN([[tGenErr1]]),
+ %% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?line expect(40, genErr, 1, any),
+
+ ?GN([[tGenErr2]]),
+ %% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?line expect(41, genErr, 1, any),
+
+ ?GN([[sysDescr], [tGenErr3]]),
+ %% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
+ %% {[tGenErr3], 'NULL'}]).
+ ?line expect(42, genErr, 2, any).
+
+v1_set_p() ->
+ %% 4.1.5:1
+ ?S([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
+
+ ?S([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+
+ ?S([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+
+ ?S([{[tDescr3], s, "noSuchObject"}]),
+ ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+
+ ?S([{[tDescr3,1], s, "noSuchInstance"}]),
+ ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+
+ ?S([{[tDescr2,0], s, "inconsistentName"}]),
+ ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+
+ %% 4.1.5:2
+ ?S([{[tDescr2, 0], i, 4}]),
+ ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
+
+ ?S([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.1.5:3
+ %% The standard is quite incorrect here. The resp pdu was too big. In
+ %% the resp pdu, we have the original vbs. In the tooBig pdu we still
+ %% have to original vbs => the tooBig pdu is too big as well!!! It
+ %% may not get it to the manager, unless the agent uses 'NULL' instead
+ %% of the std-like original value.
+ ?S([{[tTooBig, 0], s, ?tooBigStr}]),
+ %% according to std:
+ %% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.5:4
+ ?S([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+
+ ?S([{[tDescr2, 0], s, "commit_fail"}]),
+ ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+
+
+%% -- big --
+
+big(suite) -> [];
+big(Config) when list(Config) ->
+ ?P1(big),
+ {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1"),
+ ?DBG("big -> SA: ~p", [SA]),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ ?TRY_TEST1(big_test),
+
+ ?line ?STOP_SA(SA),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req: system group, OLD-SNMPEA-MIB, Klas1
+big_test() ->
+ ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
+ simple_standard_test(),
+
+ ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
+ ?GN([[klas1]]),
+ ?line expect(1, [{[fname,0], ""}]),
+
+ ?G([[fname,0]]),
+ ?line expect(2, [{[fname,0], ""}]),
+
+ ?S([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+
+ ?G([[fname,0]]),
+ ?line expect(4, [{[fname,0], "test set"}]),
+
+ ?DBG("big_test -> "
+ "testing next from last instance in master to subagent...",[]),
+ ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname,0], "test set"}]),
+
+ ?GN([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname,0], "test set"}]),
+ ?S([{[fname,0], s, ""}]),
+ ?line expect(52, [{[fname,0], ""}]),
+
+ table_test(),
+
+ ?DBG("big_test -> adding one row in subagent table",[]),
+ _FTab = [friendsEntry],
+ ?S([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {[friendsEntry, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+
+ ?G([[friendsEntry, [2, 3]],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?active}]),
+
+ ?S([{[friendsEntry, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
+
+ otp_1131(),
+
+ ?DBG("big_test -> adding two rows in subagent table with special INDEX",
+ []),
+ ?S([{[kompissEntry, [1, 3]], s, "kompis3"},
+ {[kompissEntry, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?createAndGo}]),
+
+ ?G([[kompissEntry, [1, 3]],
+ [kompissEntry, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+
+ ?GN([[kompissEntry, [1]],
+ [kompissEntry, [2]]]),
+ ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+
+ ?S([{[kompissEntry, [1, 2]], s, "kompis3"},
+ {[kompissEntry, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?createAndGo}]),
+
+ ?GN([[kompissEntry, [1, 1]],
+ [kompissEntry, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?active}]),
+
+ ?S([{[kompissEntry, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
+
+ ?S([{[kompissEntry, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
+ ?DBG("big_test -> done",[]),
+ ok.
+
+
+%% Req. system group, Klas2, OLD-SNMPEA-MIB
+big_test_2() ->
+ ?P1(big_test_2),
+
+ ?P2("Testing simple next/get/set @ master agent (2)..."),
+ simple_standard_test(),
+
+ p("Testing simple next/get/set @ subagent (2)..."),
+ ?GN([[klas2]]),
+ ?line expect(1, [{[fname2,0], ""}]),
+
+ ?G([[fname2,0]]),
+ ?line expect(2, [{[fname2,0], ""}]),
+
+ ?S([{[fname2,0], s, "test set"}]),
+ ?line expect(3, [{[fname2,0], "test set"}]),
+
+ ?G([[fname2,0]]),
+ ?line expect(4, [{[fname2,0], "test set"}]),
+
+ otp_1298(),
+
+ ?P2("Testing next from last object in master to subagent (2)..."),
+ ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname2,0], "test set"}]),
+
+ ?GN([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname2,0], "test set"}]),
+
+ table_test(),
+
+ ?P2("Adding one row in subagent table (2)"),
+ ?S([{[friendsEntry2, [2, 3]], s, "kompis3"},
+ {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?createAndGo}]),
+
+ ?G([[friendsEntry2, [2, 3]],
+ [friendsEntry2, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?active}]),
+
+ ?S([{[friendsEntry2, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
+
+ ?P2("Adding two rows in subagent table with special INDEX (2)"),
+ ?S([{[kompissEntry2, [1, 3]], s, "kompis3"},
+ {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?createAndGo}]),
+ ?G([[kompissEntry2, [1, 3]],
+ [kompissEntry2, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ ?GN([[kompissEntry2, [1]],
+ [kompissEntry2, [2]]]),
+ ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+
+ ?S([{[kompissEntry2, [1, 2]], s, "kompis3"},
+ {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?createAndGo}]),
+
+ ?GN([[kompissEntry2, [1, 1]],
+ [kompissEntry2, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?active}]),
+
+ ?S([{[kompissEntry2, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
+
+ ?S([{[kompissEntry2, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
+ ok.
+
+
+%% -- bug2 --
+
+big2(suite) -> [];
+big2(Config) when list(Config) ->
+ ?P1(big2),
+ %% This is exactly the same tests as 'big', but with the
+ %% v2 equivalent of the mibs.
+ {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
+
+ ?P2("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1-v2"),
+ ?line load_master("OLD-SNMPEA-MIB-v2"),
+ ?line init_old(),
+
+ ?TRY_TEST1(big_test),
+
+ ?line ?STOP_SUBAGENT(SA),
+ ?line unload_master("OLD-SNMPEA-MIB-v2").
+
+
+implied(suite) -> [];
+implied(Config) when list(Config) ->
+ ?P1(implied),
+ ?INIT_CASE(Config),
+
+ ?line load_master("Test1"),
+
+ ?TRY_TEST2(implied_test,[whereis(snmp_master_agent)]),
+
+ ?line unload_master("Test1").
+
+%% Req. Test1
+implied_test(MA) ->
+ ?LOG("implied_test -> start",[]),
+
+ snmpa:verbosity(MA,trace),
+ snmpa:verbosity(MA,trace),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = "apa",
+ Idx2 = "qq",
+
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
+ ?S([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
+ ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
+ {[testDescr, Idx1], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
+
+ ?S([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
+ ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
+ {[testDescr, Idx2], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr)",[]),
+
+ ?GN([[testDescr]]),
+ ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
+
+ ?GN([[testDescr,Idx1]]),
+ ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
+ ?S([{[testStatus, Idx1], i, ?destroy}]),
+ ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
+
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
+ ?S([{[testStatus, Idx2], i, ?destroy}]),
+ ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
+
+ %% Try the same in other table
+ Idx3 = [1, "apa"],
+ Idx4 = [1, "qq"],
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
+ ?S([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
+ ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
+ {[testDescr2, Idx3], "row 1"}]),
+
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
+ ?S([{[testStatus2, Idx4], i, ?createAndGo},
+ {[testDescr2,Idx4],s,"row 2"}]),
+ ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
+ {[testDescr2, Idx4], "row 2"}]),
+
+ ?DBG("implied_test -> get-next(testDescr2)",[]),
+ ?GN([[testDescr2]]),
+ ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
+
+ ?GN([[testDescr2,Idx3]]),
+ ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
+ ?S([{[testStatus2, Idx3], i, ?destroy}]),
+ ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
+
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
+ ?S([{[testStatus2, Idx4], i, ?destroy}]),
+ ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
+
+ snmpa:verbosity(MA,log),
+
+ ?LOG("implied_test -> done",[]).
+
+
+%% -- loop_mib --
+
+%%-----------------------------------------------------------------
+%% Loop through entire MIB, to make sure that all instrum. funcs
+%% works.
+%% Load all std mibs that are not loaded by default.
+%%-----------------------------------------------------------------
+loop_mib(suite) -> [];
+loop_mib(Config) when list(Config) ->
+ ?P1(loop_mib),
+ %% snmpa:verbosity(master_agent,debug),
+ %% snmpa:verbosity(mib_server,info),
+ {SaNode, MgrNode, MibDir} = ?INIT_CASE(Config),
+ ?DBG("loop_mib -> "
+ "~n SaNode: ~p"
+ "~n MgrNode: ~p"
+ "~n MibDir: ~p", [SaNode, MgrNode, MibDir]),
+
+ ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?DBG("loop_mib -> try",[]),
+
+ ?TRY_TEST1(loop_mib),
+
+ ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ %% snmpa:verbosity(master_agent,log),
+ %% snmpa:verbosity(mib_server,silence),
+ ?LOG("loop_mib -> done",[]).
+
+%% Req. As many mibs all possible
+loop_mib() ->
+ ?DBG("loop_mib -> entry",[]),
+ N = loop_it([1,1], 0),
+ ?P3("found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+loop_it(Oid, N) ->
+ ?DBG("loop_it -> entry with"
+ "~n Oid: ~p"
+ "~n N: ~p", [Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it -> "
+ "~n NOid: ~p"
+ "~n Value: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_1 -> "
+ "~n Value2: ~p",[Value2]),
+ loop_it(NOid, N+1);
+
+ #pdu{type='get-response', error_status=noSuchName, error_index=1,
+ varbinds=[_]} ->
+ ?DBG("loop_it -> done",[]),
+ N;
+
+ #pdu{type = Type, error_status = Err, error_index = Idx,
+ varbinds = Vbs} ->
+ exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
+
+ end.
+
+
+%% -- api --
+
+api(suite) -> [];
+api(Config) when list(Config) ->
+ ?P1(api),
+ ?INIY_CASE(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ ?TRY_TEST2(api_test, [node()]),
+
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+api_test(MaNode) ->
+ ?line {value, OID} = ?RPC(MaNode, name_to_oid, [intAgentIpAddress]),
+ ?line {value, intAgentIpAddress} = ?RPC(MaNode, oid_to_name, [OID]),
+ ?line false = ?RPC(MaNode, name_to_oid, [intAgentIpAddres]),
+ ?line false = ?RPC(MaNode, oid_to_name, [[1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = ?RPC(MaNode, enum_to_int, [intViewType, excluded]),
+ ?line {value, excluded} = ?RPC(MaNode, int_to_enum, [intViewType, 2]),
+ ?line false = ?RPC(MaNode, enum_to_int, [intViewType, exclude]),
+ ?line false = ?RPC(MaNode, enum_to_int, [intAgentIpAddress, exclude]),
+ ?line false = ?RPC(MaNode, enum_to_int, [intAgentIpAddre, exclude]),
+ ?line false = ?RPC(MaNode, int_to_enum, [intViewType, 3]),
+ ?line false = ?RPC(MaNode, int_to_enum, [intAgentIpAddress, 2]),
+ ?line false = ?RPC(MaNode, int_to_enum, [intAgentIpAddre, 2]),
+ ?line {value, active} = ?RPC(MaNode, int_to_enum, ['RowStatus', ?active]),
+ ?line {value, ?destroy} =
+ ?RPC(MaNode, enum_to_int, ['RowStatus', destroy]),
+ ?line false = ?RPC(MaNode, enum_to_int, ['RowStatus', xxxdestroy]),
+ ?line false = ?RPC(MaNode, enum_to_int, ['xxRowStatus', destroy]),
+ ?line false = ?RPC(MaNode, int_to_enum, ['RowStatus', 25]),
+ ?line false = ?RPC(MaNode, int_to_enum, ['xxRowStatus', 1]),
+ ?line case snmp:date_and_time() of
+ List when list(List), length(List) == 8 -> ok;
+ List when list(List), length(List) == 11 -> ok
+ end.
+
+
+%% -- subagent --
+
+subagent(suite) -> [];
+subagent(Config) when list(Config) ->
+ ?P1(subagent),
+ {SaNode, _MgrNode, MibDir} = ?INIT_CASE(Config),
+
+ ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1"),
+
+ ?TRY_TEST1(load_test_sa),
+
+ ?P2("Testing unregister subagent [~w]...", [SA]),
+ MA = whereis(snmp_master_agent),
+ ?RPC(SaNode, unregister_subagent, [MA, SA]),
+ ?TRY_TEST1(unreg_test),
+
+ ?P2("Loading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ ?TRY_TEST1(load_test),
+
+ ?P2("Unloading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+
+ ?TRY_TEST1(unreg_test),
+
+ ?P2("Testing register subagent..."),
+ ?RPC(SaNode, register_subagent, [MA, ?klas1, SA]),
+ ?TRY_TEST1(load_test_sa),
+
+ ?line ?STOP_SA(SA),
+ ?TRY_TEST1(unreg_test).
+
+%% Req. Klas1
+load_test_sa() ->
+ ?GN([[?v1_2(sysServices,sysORLastChange), 0]]),
+ ?line expect(1, [{[fname,0], any}]).
+
+unreg_test() ->
+ ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[snmpInPkts, 0], any}]).
+
+load_test() ->
+ ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[fname,0], ""}]).
+
+
+%% -- mnesia --
+
+mnesia(suite) -> [];
+mnesia(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent with mnesia impl..."),
+ {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ ?TRY_TEST1(big_test_2),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ ?TRY_TEST1(unreg_test),
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA).
+
+
+%% -- multiple_reqs --
+
+multiple_reqs(suite) ->
+ {req, [], {conf, init_mul, mul_cases(), finish_mul}}.
+
+mul_cases() ->
+ [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err].
+
+init_mul(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ [{mul_sub, SA} | Config].
+
+finish_mul(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ SA = ?config(mul_sub, Config),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA),
+ lists:keydelete(mul_sub, 1, Config).
+
+
+%% -- mul_get --
+
+mul_get(suite) -> [];
+mul_get(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get..."),
+ ?TRY_TEST1(do_mul_get).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_get() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
+ [sysName,0]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,0], "test"}]),
+ g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
+ ?line ?v1_2(expect(2, noSuchName, [1,4], any),
+ expect(2, [{[1,3,7,1], noSuchObject},
+ {Key1c4, 2},
+ {[sysDescr,0], "Erlang SNMP agent"},
+ {[1,3,7,2], noSuchObject},
+ {Key1c3, 2},
+ {[sysDescr,0], "Erlang SNMP agent"}])).
+
+
+%% -- mul_get_err --
+
+mul_get_err(suite) -> [];
+mul_get_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get with error..."),
+ ?TRY_TEST1(do_mul_get_err).
+
+%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
+do_mul_get_err() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
+ ?line ?v1_2(expect(1, noSuchName, 5, any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,2], noSuchInstance}])),
+ g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname3,0], noSuchObject},
+ {Key1c3, 2},
+ {[sysName,1], noSuchInstance}])).
+
+
+%% -- mul_next --
+
+mul_next(suite) -> [];
+mul_next(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ ?TRY_TEST1(do_mul_next).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2}, {[fname,0], "test set"},
+ {Key1c3, 2}, {[sysName,0], "test"}]).
+
+
+%% -- mul_next_err --
+
+mul_next_err(suite) -> [];
+mul_next_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ ?TRY_TEST1(do_mul_next_err).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next_err() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[1,3,6,999], endOfMibView},
+ {[fname,0], "test set"},
+ {[1,3,90], endOfMibView},
+ {Key1c3, 2},
+ {[sysName,0], "test"}])).
+
+
+%% -- mul_set --
+
+mul_set(suite) -> [];
+mul_set(Config) when list(Config) ->
+ ?P(mul_set),
+ ?INIT_CASE(Config),
+
+ ?TRY_TEST1(do_mul_set).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set() ->
+ p("Adding one row in subagent table, and one in master table"),
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [sysLocation,0],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[sysLocation,0], "new_value"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ g([NewKeyc4]),
+ ?line expect(3, [{NewKeyc4, 2}]),
+ s([{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]),
+ ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]).
+
+
+%% -- mul_set_err --
+
+mul_set_err(suite) -> [];
+mul_set_err(Config) when list(Config) ->
+ ?P(mul_set_err),
+ ?INIT_CASE(Config),
+
+ ?TRY_TEST1(do_mul_set_err).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ p("Adding one row in subagent table, and one in master table"),
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {NewKeyc3, 2},
+ {[sysUpTime,0], 45}, % sysUpTime (readOnly)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
+ g([[friendsEntry, [2, 3]]]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{NewKeyc4, noSuchInstance}])).
+
+
+%% -- sa_register --
+
+sa_register(suite) -> [];
+sa_register(Config) when list(Config) ->
+ ?P1(sa_register),
+ {SaNode, _MgrNode, MibDir} = ?INIT_CASE(Config),
+
+ ?DBG("sa_register -> start subagent", []),
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+
+ ?DBG("sa_register -> unregister subagent", []),
+ ?P2("Testing unregister subagent (2)..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ ?TRY_TEST1(unreg_test),
+
+ ?P2("Loading SA-MIB..."),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ ?DBG("sa_register -> register subagent", []),
+ rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
+ ?TRY_TEST1(sa_mib),
+
+ ?DBG("sa_register -> stop subagent", []),
+ ?line stop_subagent(SA).
+
+%% Req. SA-MIB
+sa_mib() ->
+ g([[sa, [2,0]]]),
+ ?line expect(1, [{[sa, [2,0]], 3}]),
+ s([{[sa, [1,0]], s, "sa_test"}]),
+ ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+
+
+%% -- v1_trap --
+
+v1_trap(suite) -> [];
+v1_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ ?TRY_TEST2(ma_trap1, [MA]),
+ ?TRY_TEST2(ma_trap2, [MA]),
+ ?TRY_TEST2(ma_v2_2_v1_trap, [MA]),
+ ?TRY_TEST2(ma_v2_2_v1_trap2, [MA]),
+
+ p("Testing trap sending from subagent..."),
+ ?TRY_TEST2(sa_trap1, [SA]),
+ ?TRY_TEST2(sa_trap2, [SA]),
+ ?TRY_TEST2(sa_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+ma_trap1(MA) ->
+ snmpa:send_trap(MA, testTrap2, "standard trap"),
+ ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ snmpa:send_trap(MA, testTrap1, "standard trap"),
+ ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]).
+
+ma_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap2(MA) ->
+ snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
+ {ifAdminStatus, [1], 1},
+ {ifOperStatus, [1], 2}]),
+ ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]).
+
+sa_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "pelle"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]).
+
+ma_v2_trap1(MA) ->
+ ?DBG("ma_v2_traps -> entry with MA = ~p => "
+ "send standard trap: testTrapv22",[MA]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
+ snmpa:send_trap(MA, testTrapv21, "standard trap"),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmp ++ [1]}]).
+
+ma_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"}]).
+
+ma_v1_2_v2_trap(MA) ->
+ snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
+ {[ifIndex, 1], 1},
+ {[snmpTrapEnterprise, 0], [1,2,3]}]).
+
+
+ma_v1_2_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"},
+ {[snmpTrapEnterprise, 0], ?system}]).
+
+
+sa_v1_2_v2_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+sa_v1_2_v2_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+sa_v1_2_v2_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+%% -- sa_error --
+
+sa_error(suite) -> [];
+sa_error(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing sa bad value (is_set_ok)..."),
+ ?TRY_TEST1(sa_errs_bad_value),
+
+ p("Testing sa gen err (set)..."),
+ ?TRY_TEST1(sa_errs_gen_err),
+
+ p("Testing too big..."),
+ ?TRY_TEST1(sa_too_big),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_bad_value() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 5}, % badValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, badValue, 2, any),
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_gen_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},{NewKeyc4, 2},
+ {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
+ ?line expect(1, genErr, 4, any),
+% The row might have been added; we don't know.
+% (as a matter of fact we do - it is added, because the agent
+% first sets its own vars, and then th SAs. Lets destroy it.
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(2, [{NewKeyc5, ?destroy}]).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_too_big() ->
+ g([[sa, [4,0]]]),
+ ?line expect(1, tooBig).
+
+
+%% -- next_across_sa --
+
+next_across_sa(suite) -> [];
+next_across_sa(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Loading another subagent mib..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+
+ rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
+ ?TRY_TEST1(load_test_sa),
+
+ p("Testing next across subagent (endOfMibView from SA)..."),
+ ?TRY_TEST1(next_across_sa),
+
+ p("Unloading mib"),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ ?TRY_TEST1(unreg_test),
+
+ p("Starting another subagent"),
+ ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ p("Testing next across subagent (wrong prefix from SA)..."),
+ ?TRY_TEST1(next_across_sa),
+
+ stop_subagent(SA),
+ stop_subagent(SA2).
+
+%% Req. Klas1, system group, snmp group (v1/v2)
+next_across_sa() ->
+ gn([[sysDescr],[klas1,5]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[snmpInPkts, 0], any}]).
+
+
+%% -- undo --
+
+undo(suite) -> [];
+undo(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing undo phase at master agent..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ ?TRY_TEST1(undo_test),
+ ?TRY_TEST1(api_test2),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+
+ p("Testing bad return values from instrum. funcs..."),
+ ?TRY_TEST1(bad_return),
+
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+
+ p("Testing undo phase at subagent..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ ?TRY_TEST1(undo_test),
+ ?TRY_TEST1(api_test3),
+
+ p("Testing undo phase across master/subagents..."),
+ ?TRY_TEST1(undo_test),
+ ?TRY_TEST1(api_test3),
+ stop_subagent(SA).
+
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
+%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
+%% Req. Klas3, Klas4
+undo_test() ->
+ s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
+ s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
+ ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
+ %% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+ %% it depends on which order the agent traverses the varbind list.
+ %% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
+ %% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
+ ?line expect(6, genErr, 2, any).
+
+%% Req. Klas3, Klas4
+bad_return() ->
+ g([[fStatus4,4],
+ [fName4,4]]),
+ ?line expect(4, genErr, 2, any),
+ g([[fStatus4,5],
+ [fName4,5]]),
+ ?line expect(5, genErr, 1, any),
+ g([[fStatus4,6],
+ [fName4,6]]),
+ ?line expect(6, genErr, 2, any),
+ gn([[fStatus4,7],
+ [fName4,7]]),
+ ?line expect(7, genErr, 2, any),
+ gn([[fStatus4,8],
+ [fName4,8]]),
+ ?line expect(8, genErr, 1, any),
+ gn([[fStatus4,9],
+ [fName4,9]]),
+ ?line expect(9, genErr, 2, any).
+
+
+%% -- standard_mibs --
+
+%%%-----------------------------------------------------------------
+%%% Test the implementation of standard mibs.
+%%% We should *at least* try to GET all variables, just to make
+%%% sure the instrumentation functions work.
+%%% Note that many of the functions in the standard mib is
+%%% already tested by the normal tests.
+%%%-----------------------------------------------------------------
+standard_mibs(suite) ->
+ [snmp_standard_mib,
+ snmp_community_mib,
+ snmp_framework_mib,
+ snmp_target_mib,
+ snmp_notification_mib,
+ snmp_view_based_acm_mib].
+
+
+%% -- snmp_standard_mib --
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v1.
+%% o Test the counters and control objects in SNMP-STANDARD-MIB
+%%-----------------------------------------------------------------
+snmp_standard_mib(suite) -> [];
+snmp_standard_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?DBG("snmp_standard_mib -> std_mib_init", []),
+ ?TRY_TEST1(std_mib_init),
+
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ InBadVsns = ?TRY_TEST1(std_mib_a),
+ put(vsn, v2),
+ ?DBG("snmp_standard_mib -> std_mib_read", []),
+ ?TRY_TEST1(std_mib_read),
+ put(vsn, v1),
+
+ ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
+ Bad = ?TRY_TEST2(std_mib_b, [InBadVsns]),
+ ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
+ ?TRY_TEST3(std_mib_read, [], [{community, "bad community"}]),
+ ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
+ ?TRY_TEST3(std_mib_write, [], [{community, "public"}]),
+ ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
+ ?TRY_TEST1(std_mib_asn_err),
+ ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
+ ?TRY_TEST2(std_mib_c, [Bad]),
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ ?TRY_TEST1(standard_mib_a),
+
+ ?DBG("snmp_standard_mib -> std_mib_finish", []),
+ ?TRY_TEST1(std_mib_finish),
+ ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
+ ?TRY_TEST3(standard_mib_test_finish, [], [{community, "bad community"}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_a() ->
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ ?line OutPkts2 = OutPkts + 1,
+ %% There are some more counters we could test here, but it's not that
+ %% important, since they are removed from SNMPv2-MIB.
+ ok.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_init() ->
+ %% disable authentication failure traps. (otherwise w'd get many of
+ %% them - this is also a test to see that it works).
+ s([{[snmpEnableAuthenTraps,0], 2}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_finish() ->
+ %% enable again
+ s([{[snmpEnableAuthenTraps,0], 1}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_test_finish() ->
+ %% force a authenticationFailure
+ std_mib_write(),
+ %% check that we got a trap
+ ?line expect(2, trap, [1,2,3], 4, 0, []).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_read() ->
+ ?DBG("std_mib_read -> entry", []),
+ g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
+ ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
+ ?line expect(1, timeout). % make sure we don't get a trap!
+
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_write() ->
+ ?DBG("std_mib_write -> entry", []),
+ s([{[sysLocation, 0], "new_value"}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_asn_err() ->
+ ?SEND_BYTES([48,99,67,12,0,0,0,0,0,0,5]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_a() ->
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+
+ ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ InBadVsns.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_b(InBadVsns) ->
+ ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ ?line InBadVsns2 = InBadVsns + 1,
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+ ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
+ get_req(4, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
+ ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ get_req(1, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ ?line InBadCommunityNames2 = InBadCommunityNames + 1,
+ ?line InBadCommunityUses2 = InBadCommunityUses + 1,
+ ?line InASNErrs2 = InASNErrs + 1.
+
+
+%% -- snmp_community_mib --
+
+%%-----------------------------------------------------------------
+%% o Bad community uses/name is tested already
+%% in SNMPv2-MIB and STANDARD-MIB.
+%% o Test add/deletion of rows.
+%%-----------------------------------------------------------------
+snmp_community_mib(suite) -> [];
+snmp_community_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?TRY_TEST1(snmp_community_mib),
+ ?line unload_master("SNMP-COMMUNITY-MIB").
+
+snmp_community_mib_2(X) -> snmp_community_mib(X).
+
+%% Req. SNMP-COMMUNITY-MIB
+snmp_community_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+
+%% -- snmp_framework_mib --
+
+%%-----------------------------------------------------------------
+%% o Test engine boots / time
+%%-----------------------------------------------------------------
+snmp_framework_mib(suite) -> [];
+snmp_framework_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?TRY_TEST1(snmp_framework_mib),
+ ?line unload_master("SNMP-FRAMEWORK-MIB").
+
+%% Req. SNMP-FRAMEWORK-MIB
+snmp_framework_mib() ->
+ ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ sleep(5000),
+ ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ if
+ EngineTime+7 < EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ EngineTime+4 > EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ true -> ok
+ end,
+ ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ [Boots] when integer(Boots) -> ok;
+ Else -> ?FAIL(Else)
+ end,
+ ok.
+
+
+%% -- snmp_target_mib --
+
+snmp_target_mib(suite) -> [];
+snmp_target_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?TRY_TEST1(snmp_target_mib),
+ ?line unload_master("SNMP-TARGET-MIB").
+
+snmp_target_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+
+%% -- snmp_notification_mib --
+
+snmp_notification_mib(suite) -> [];
+snmp_notification_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?TRY_TEST1(snmp_notification_mib),
+ ?line unload_master("SNMP-NOTIFICATION-MIB").
+
+snmp_notification_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+
+%% -- snmp_view_based_acm_mib --
+
+%%-----------------------------------------------------------------
+%% o add/delete views and try them
+%% o try boundaries
+%%-----------------------------------------------------------------
+snmp_view_based_acm_mib(suite) -> [];
+snmp_view_based_acm_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master("Test2"),
+ snmp_view_based_acm_mib(),
+ ?line unload_master("Test2"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+snmp_view_based_acm_mib() ->
+ snmpa:verbosity(net_if,trace),
+ snmpa:verbosity(master_agent,trace),
+ ?LOG("start snmp_view_based_acm_mib test",[]),
+ %% The user "no-rights" is present in USM, and is mapped to security
+ %% name 'no-rights", which is not present in VACM.
+ %% So, we'll add rights for it, try them and delete them.
+ %% We'll give "no-rights" write access to tDescr.0 and read access
+ %% to tDescr2.0
+ %% These are the options we'll use to the mgr
+ Opts = [{user, "no-rights"}, {community, "no-rights"}],
+ %% Find the valid secmodel, and one invalid secmodel.
+ {SecMod, InvSecMod} =
+ case get(vsn) of
+ v1 -> {?SEC_V1, ?SEC_V2C};
+ v2 -> {?SEC_V2C, ?SEC_USM};
+ v3 -> {?SEC_USM, ?SEC_V1}
+ end,
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+
+ %% Now, add a mapping from "no-rights" -> "no-rights-group"
+ GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
+ GRow1 =
+ [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
+ {GRow1Status, ?createAndGo}],
+ ?DBG("set '~p'",[GRow1]),
+ ?line ?TRY_TEST2(do_set, [GRow1]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+
+ %% Create a mapping for another sec model, and make sure it dosn't
+ %% give us access
+ GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
+ GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
+ {GRow2Status, ?createAndGo}],
+
+ ?DBG("set '~p'",[GRow2]),
+ ?line ?TRY_TEST2(do_set, [GRow2]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line ?TRY_TEST2(del_row, [GRow2Status]),
+
+ RVName = "rv_name",
+ WVName = "wv_name",
+
+ %% Access row
+ ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
+ ARow1Status = [vacmAccessStatus, ARow1Idx],
+ ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
+ {[vacmAccessReadViewName, ARow1Idx], RVName},
+ {[vacmAccessWriteViewName, ARow1Idx], WVName},
+ {ARow1Status, ?createAndGo}],
+
+ %% This access row would give acces, if InvSecMod was valid.
+ ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
+ ARow2Status = [vacmAccessStatus, ARow2Idx],
+ ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
+ {[vacmAccessReadViewName, ARow2Idx], "internet"},
+ {[vacmAccessWriteViewName, ARow2Idx], "internet"},
+ {ARow2Status, ?createAndGo}],
+
+ ?line ?TRY_TEST2(do_set, [ARow2]),
+
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line ?TRY_TEST2(del_row, [ARow2Status]),
+
+
+ %% Add valid row
+ ?line ?TRY_TEST2(do_set, [ARow1]),
+
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+
+ %% Create the view family
+ VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
+ VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
+ VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
+ VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
+ VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
+ VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
+ VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
+ VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
+
+ ?line ?TRY_TEST2(add_row, [VRow1Status]),
+ ?line ?TRY_TEST2(add_row, [VRow2Status]),
+ ?line ?TRY_TEST2(add_row, [VRow3Status]),
+
+ %% We're supposed to have access now...
+ ?line ?TRY_TEST3(use_rights, [], Opts),
+
+ %% Change Row3 to Row4
+ ?line ?TRY_TEST2(del_row, [VRow3Status]),
+ ?line ?TRY_TEST2(add_row, [VRow4Status]),
+
+ %% We should still have access...
+ ?line ?TRY_TEST3(use_rights, [], Opts),
+
+ %% Delete rows
+ ?line ?TRY_TEST2(del_row, [GRow1Status]),
+
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+
+ %% Delete rest of rows
+ ?line ?TRY_TEST2(del_row, [ARow1Status]),
+ ?line ?TRY_TEST2(del_row, [VRow1Status]),
+ ?line ?TRY_TEST2(del_row, [VRow2Status]),
+ ?line ?TRY_TEST2(del_row, [VRow4Status]),
+
+ ?line ?TRY_TEST3(use_no_rights, [], Opts),
+ snmpa:verbosity(master_agent,log).
+
+do_set(Row) ->
+ s(Row),
+ expect(1, Row).
+
+add_row(RowStatus) ->
+ s([{RowStatus, ?createAndGo}]),
+ expect(1, [{RowStatus, ?createAndGo}]).
+
+del_row(RowStatus) ->
+ s([{RowStatus, ?destroy}]),
+ expect(1, [{RowStatus, ?destroy}]).
+
+
+
+use_no_rights() ->
+ g([[xDescr,0]]),
+ ?v1_2_3(expect(11, noSuchName, 1, any),
+ expect(12, [{[xDescr,0], noSuchObject}]),
+ expect(13, authorizationError, 1, any)),
+ g([[xDescr2,0]]),
+ ?v1_2_3(expect(21, noSuchName, 1, any),
+ expect(22, [{[xDescr2,0], noSuchObject}]),
+ expect(23, authorizationError, 1, any)),
+ gn([[xDescr]]),
+ ?v1_2_3(expect(31, noSuchName, 1, any),
+ expect(32, [{[xDescr], endOfMibView}]),
+ expect(33, authorizationError, 1, any)),
+ s([{[xDescr,0], "tryit"}]),
+ ?v1_2_3(expect(41, noSuchName, 1, any),
+ expect(42, noAccess, 1, any),
+ expect(43, authorizationError, 1, any)).
+
+
+use_rights() ->
+ g([[xDescr,0]]),
+ expect(1, [{[xDescr,0], any}]),
+ g([[xDescr2,0]]),
+ expect(2, [{[xDescr2,0], any}]),
+ s([{[xDescr,0], "tryit"}]),
+ expect(3, noError, 0, any),
+ g([[xDescr,0]]),
+ expect(4, [{[xDescr,0], "tryit"}]).
+
+
+%% -- sparse_table --
+
+sparse_table(suite) -> [];
+sparse_table(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
+
+ ?line load_master("Test1"),
+ ?TRY_TEST1(sparse_table_test),
+ ?line unload_master("Test1").
+
+%% Req. Test1
+sparse_table_test() ->
+ p("Testing sparse table..."),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ s([{[sparseStatus, Idx1], i, ?createAndGo},
+ {[sparseDescr, Idx1], s, "row 1"}]),
+ ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
+ {[sparseDescr, Idx1], "row 1"}]),
+ s([{[sparseStatus, Idx2], i, ?createAndGo},
+ {[sparseDescr, Idx2], s, "row 2"}]),
+ ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
+ {[sparseDescr, Idx2], "row 2"}]),
+ ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
+ [sparseStatus,Idx1], [sparseStatus,Idx2]]),
+ gb(0,5,[[sparseIndex]])),
+ ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
+ {[sparseDescr,Idx2], "row 2"},
+ {[sparseStatus,Idx1], ?active},
+ {[sparseStatus,Idx2], ?active},
+ {[sparseStr,0], "slut"}]),
+ % Delete the rows
+ s([{[sparseStatus, Idx1], i, ?destroy}]),
+ ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
+ s([{[sparseStatus, Idx2], i, ?destroy}]),
+ ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
+
+
+%% -- cnt_64 --
+
+cnt_64(suite) -> [];
+cnt_64(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ ?TRY_TEST2(cnt_64_test, [MA]),
+ ?line unload_master("Test1").
+
+%% Req. Test1
+cnt_64_test(MA) ->
+ ?LOG("start cnt64 test (~p)",[MA]),
+ snmpa:verbosity(MA,trace),
+ ?LOG("start cnt64 test",[]),
+ p("Testing Counter64, and at the same time, RowStatus is not last column"),
+
+ ?DBG("get cnt64",[]),
+ g([[cnt64,0]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(1, noSuchName, 1, any),
+ expect(1, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("get-next cnt64",[]),
+ gn([[cnt64]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
+ expect(2, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("send cntTrap",[]),
+ snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
+ {cnt64, 10},
+ {sysLocation, "here"}]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ {[sysLocation,0], "here"}]),
+ expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [1]},
+ {[sysContact,0], "pelle"},
+ {[cnt64,0], 10},
+ {[sysLocation,0], "here"}])),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ ?DBG("create row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
+ ?DBG("create row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
+
+ ?DBG("get-next (cntIndex)",[]),
+ gn([[cntIndex]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
+ expect(3, [{[cntCnt,Idx1], 0}])),
+ % Delete the rows
+ ?DBG("delete row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
+ ?DBG("delete row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
+ catch snmpa:verbosity(MA,log),
+ ?DBG("done",[]),
+ ok.
+
+
+%% -- opaque --
+
+opaque(suite) -> [];
+opaque(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
+
+ ?line load_master("Test1"),
+ ?TRY_TEST1(opaque_test),
+ ?line unload_master("Test1").
+
+%% Req. Test1
+opaque_test() ->
+ p("Testing Opaque datatype..."),
+ g([[opaqueObj,0]]),
+ ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
+
+
+%% -- change_target_addr_config --
+
+change_target_addr_config(suite) -> [];
+change_target_addr_config(Config) when list(Config) ->
+ p("Testing changing target address config..."),
+ ?LOG("change_target_addr_config -> entry",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(sname,snmp_suite),
+ put(verbosity,trace),
+
+ MA = whereis(snmp_master_agent),
+
+ ?LOG("change_target_addr_config -> load TestTrap",[]),
+ ?line load_master("TestTrap"),
+
+ ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,trace),
+
+ %% First send some traps that will arive att the original manager
+ ?LOG("change_target_addr_config -> send trap",[]),
+ ?TRY_TEST2(ma_trap1, [MA]),
+
+ ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,silence),
+
+ %% Start new dummy listener
+ ?LOG("change_target_addr_config -> start dummy manager",[]),
+ ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+
+ %% Reconfigure
+ ?LOG("change_target_addr_config -> reconfigure",[]),
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_addr_conf(AgentDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ %% Send the trap again
+ ?LOG("change_target_addr_config -> send trap again",[]),
+ catch dummy_manager_send_trap2(Pid),
+
+ ?LOG("change_target_addr_config -> await trap ack",[]),
+ catch dummy_manager_await_trap2_ack(),
+
+ ?LOG("change_target_addr_config -> stop dummy manager",[]),
+ ?line ok = dummy_manager_stop(Pid),
+
+ ?LOG("change_target_addr_config -> reset target address config",[]),
+ ?line reset_target_addr_conf(AgentDir),
+
+ ?LOG("change_target_addr_config -> unload TestTrap",[]),
+ ?line unload_master("TestTrap").
+
+
+dummy_manager_start(MA) ->
+ ?DBG("dummy_manager_start -> entry",[]),
+ Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
+ ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
+ await_dummy_manager_started(Pid).
+
+await_dummy_manager_started(Pid) ->
+ receive
+ {dummy_manager_started,Pid,Port} ->
+ ?DBG("dummy_manager_start -> acknowledge received with"
+ "~n Port: ~p",[Port]),
+ {ok,Pid,Port};
+ {'EXIT', Pid, Reason} ->
+ {error, Pid, Reason};
+ O ->
+ ?LOG("dummy_manager_start -> received unknown message:"
+ "~n ~p",[O]),
+ await_dummy_manager_started(Pid)
+ end.
+
+dummy_manager_stop(Pid) ->
+ ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
+ Pid ! stop,
+ receive
+ {dummy_manager_stopping, Pid} ->
+ ?DBG("dummy_manager_stop -> acknowledge received",[]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_stop -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_send_trap2(Pid) ->
+ ?DBG("dummy_manager_send_trap2 -> entry",[]),
+ Pid ! {send_trap,testTrap2}.
+
+dummy_manager_await_trap2_ack() ->
+ ?DBG("dummy_manager_await_trap2 -> entry",[]),
+ receive
+ {received_trap,Trap} ->
+ ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
+ %% Note:
+ %% Without this sleep the v2_inform_i testcase failes! There
+ %% is no relation between these two test cases as far as I
+ %% able to figure out...
+ sleep(60000),
+ ok;
+ O ->
+ ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_await_trap2 -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_init(Parent,MA) ->
+ ?DBG("dummy_manager_init -> entry with"
+ "~n Parent: ~p"
+ "~n MA: ~p",[Parent,MA]),
+ {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
+ ?DBG("dummy_manager_init -> S: ~p",[S]),
+ {ok,Port} = inet:port(S),
+ ?DBG("dummy_manager_init -> Port: ~p",[Port]),
+ Parent ! {dummy_manager_started,self(),Port},
+ dummy_manager_loop(Parent,S,MA).
+
+dummy_manager_loop(P,S,MA) ->
+ ?LOG("dummy_manager_loop -> ready for receive",[]),
+ receive
+ {send_trap,Trap} ->
+ ?LOG("dummy_manager_loop -> received trap send request"
+ "~n Trap: ~p",[Trap]),
+ snmpa:send_trap(MA, Trap, "standard trap"),
+ dummy_manager_loop(P,S,MA);
+ {udp, _UdpId, Ip, UdpPort, Bytes} ->
+ ?LOG("dummy_manager_loop -> received upd message"
+ "~n from: ~p:~p"
+ "~n size: ~p",
+ [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
+ R = dummy_manager_handle_message(Bytes),
+ ?DBG("dummy_manager_loop -> R: ~p",[R]),
+ P ! R,
+ dummy_manager_loop(P,S,MA);
+ stop ->
+ ?DBG("dummy_manager_loop -> received stop request",[]),
+ P ! {dummy_manager_stopping, self()},
+ gen_udp:close(S),
+ exit(normal);
+ O ->
+ ?LOG("dummy_manager_loop -> received unknown message:"
+ "~n ~p",[O]),
+ dummy_manager_loop(P,S,MA)
+ end.
+
+dummy_manager_message_sz(B) when binary(B) ->
+ size(B);
+dummy_manager_message_sz(L) when list(L) ->
+ length(L);
+dummy_manager_message_sz(_) ->
+ undefined.
+
+dummy_manager_handle_message(Bytes) ->
+ case (catch snmp_pdus:dec_message(Bytes)) of
+ {'EXIT',Reason} ->
+ ?ERR("dummy_manager_handle_message -> "
+ "failed decoding message only:~n ~p",[Reason]),
+ {error,Reason};
+ M ->
+ ?DBG("dummy_manager_handle_message -> decoded message:"
+ "~n ~p",[M]),
+ {received_trap,M}
+ end.
+
+
+%% -- reported_bugs --
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+reported_bugs(suite) ->
+ [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].
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1128
+%% Slogan: Bug in handling of createAndWait set-requests.
+%%-----------------------------------------------------------------
+otp_1128(suite) -> [];
+otp_1128(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?TRY_TEST1(otp_1128),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1128() ->
+ io:format("Testing bug reported in ticket OTP-1128...~n"),
+
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+
+ s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(29, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(31, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(32, [{NewKeyc5, ?destroy}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1129, OTP-1169
+%% Slogan: snmpa:int_to_enum crashes on bad oids
+%%-----------------------------------------------------------------
+otp_1129(suite) -> [];
+otp_1129(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ ?TRY_TEST2(otp_1129_i, [node()]),
+ ?line unload_master("Klas3").
+
+otp_1129_i(MaNode) ->
+ io:format("Testing bug reported in ticket OTP-1129...~n"),
+ false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
+ false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1131
+%% Slogan: Agent crashes / erlang node halts if RowIndex in a
+%% setrequest is of bad type, e.g. an INDEX {INTEGER},
+%% and RowIdenx [3,2].
+%%-----------------------------------------------------------------
+otp_1131(suite) -> [];
+otp_1131(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas1"),
+ ?TRY_TEST1(otp_1131),
+ ?line unload_master("Klas1").
+
+otp_1131() ->
+ io:format("Testing bug reported in ticket OTP-1131...~n"),
+ s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
+ {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1162
+%% Slogan: snmp_agent can't handle wrongValue from instrum.func
+%%-----------------------------------------------------------------
+otp_1162(suite) -> [];
+otp_1162(Config) when list(Config) ->
+ ?P1(otp_1162),
+ {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
+ ?line {ok, SA} = ?START_SA(SaNode, ?sa, "SA-MIB"),
+ ?TRY_TEST1(otp_1162),
+ ?STOP_SA(SA).
+
+otp_1162() ->
+ s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
+ ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1222
+%% Slogan: snmp agent crash if faulty index is returned from instrum
+%%-----------------------------------------------------------------
+otp_1222(suite) -> [];
+otp_1222(Config) when list(Config) ->
+ ?P1(otp_1222),
+ ?INIT_CASE(Config),
+ ?line load_master("Klas3"),
+ ?line load_master("Klas4"),
+ ?TRY_TEST1(otp_1222),
+ ?line unload_master("Klas3"),
+ ?line unload_master("Klas4").
+
+otp_1222() ->
+ io:format("Testing bug reported in ticket OTP-1222...~n"),
+ s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
+ ?line expect(1, genErr, 0, any),
+ s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
+ ?line expect(2, genErr, 0, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1298
+%% Slogan: Negative INTEGER values are treated as positive.
+%%-----------------------------------------------------------------
+otp_1298(suite) -> [];
+otp_1298(Config) when list(Config) ->
+ ?P1(otp_1298),
+ ?INIT_CASE(Config),
+ ?line load_master("Klas2"),
+ ?TRY_TEST1(otp_1298),
+ ?line unload_master("Klas2").
+
+otp_1298() ->
+ io:format("Testing bug reported in ticket OTP-1298...~n"),
+ s([{[fint,0], -1}]),
+ ?line expect(1298, [{[fint,0], -1}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1331
+%% Slogan: snmp_generic should return noError when deleting non-ex row
+%%-----------------------------------------------------------------
+otp_1331(suite) -> [];
+otp_1331(Config) when list(Config) ->
+ ?P1(otp_1331),
+ ?INIT_CASE(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?TRY_TEST1(otp_1331),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1331() ->
+ NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(1, [{NewKeyc5, ?destroy}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1338
+%% Slogan: snmp bug in initialisation of default values for mnesia tabs
+%%-----------------------------------------------------------------
+otp_1338(suite) -> [];
+otp_1338(Config) when list(Config) ->
+ ?P1(otp_1338),
+ ?INIT_CASE(Config),
+ ?line load_master("Klas2"),
+ ?TRY_TEST1(otp_1338),
+ ?line unload_master("Klas2").
+
+otp_1338() ->
+ s([{[kStatus2, 7], i, ?createAndGo}]),
+ ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
+ g([[kName2, 7]]),
+ ?line expect(2, [{[kName2, 7], "JJJ"}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1342
+%% Slogan: default impl of snmp table can't handle bad index access,
+%% Set when INDEX is read-write gets into an infinite loop!
+%%-----------------------------------------------------------------
+otp_1342(suite) -> [];
+otp_1342(Config) when list(Config) ->
+ ?P1(otp_1342),
+ ?INIT_CASE(Config),
+ ?line load_master("Klas4"),
+ ?TRY_TEST1(otp_1342),
+ ?line unload_master("Klas4").
+
+otp_1342() ->
+ s([{[fIndex5, 1], i, 1},
+ {[fName5, 1], i, 3},
+ {[fStatus5, 1], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1366
+%% Slogan: snmp traps not sent to all managers
+%% Note: NYI! We need a way to tell the test server that we need
+%% mgrs on two different machines.
+%%-----------------------------------------------------------------
+otp_1366(suite) -> [];
+otp_1366(Config) when list(Config) ->
+ ?P1(otp_1366),
+ ?INIT_CASE(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?TRY_TEST1(otp_1366),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1366() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ 'NYI'.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2776
+%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
+%%-----------------------------------------------------------------
+otp_2776(suite) -> [];
+otp_2776(Config) when list(Config) ->
+ ?P1(otp_2776),
+ ?INIT_CASE(Config),
+ ?TRY_TEST1(otp_2776).
+
+otp_2776() ->
+ io:format("Testing bug reported in ticket OTP-2776...~n"),
+
+ Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
+ Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
+ Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
+ Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
+ Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
+ Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
+ Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
+ Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
+ Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
+ Dt10_invalid = [],
+ Dt11_invalid = [kalle,hobbe],
+ L = [{ 1, true, Dt01_valid},
+ { 2, true, Dt02_valid},
+ { 3, true, Dt03_valid},
+ { 4, false, Dt04_invalid},
+ { 5, true, Dt05_valid},
+ { 6, true, Dt06_valid},
+ { 7, false, Dt07_invalid},
+ { 8, true, Dt08_valid},
+ { 9, false, Dt09_invalid},
+ {10, false, Dt10_invalid},
+ {11, false, Dt11_invalid}],
+
+ ?line ok = validate_dat(L).
+
+
+validate_dat(L) -> validate_dat(L,[]).
+
+validate_dat([],V) ->
+ Fun = fun({_,X}) -> case X of
+ ok -> false;
+ _ -> true
+ end
+ end,
+ validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
+validate_dat([{Id,E,Dat}|T],V) ->
+ validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
+
+validate_dat1([]) -> ok;
+validate_dat1(L) -> {error,L}.
+
+validate_dat2(Id, E, Dat) ->
+ Res = case {E,snmp:validate_date_and_time(Dat)} of
+ {E,E} -> ok;
+ {E,A} -> {E,A}
+ end,
+ {Id, Res}.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2979
+%% Slogan: get-next on more than 1 column in an empty table
+%% returns bad response.
+%%-----------------------------------------------------------------
+otp_2979(suite) -> [];
+otp_2979(Config) when list(Config) ->
+ ?P1(otp_2979),
+ ?INIT_CASE(Config),
+ ?line load_master("Test1"),
+ ?line init_old(),
+ ?TRY_TEST1(otp_2979),
+ ?line unload_master("Test1").
+
+otp_2979() ->
+ gn([[sparseDescr], [sparseStatus]]),
+ ?line expect(1, [{[sparseStr,0], "slut"},
+ {[sparseStr,0], "slut"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3187
+%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% endOfTable - should return value.
+%%-----------------------------------------------------------------
+otp_3187(suite) -> [];
+otp_3187(Config) when list(Config) ->
+ ?P1(otp_3187),
+ ?INIT_CASE(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ otp_3187(),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+otp_3187() ->
+ ?line Elements =
+ snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
+ lists:foreach(fun(E) ->
+ ?line if E == endOfTable ->
+ ?FAIL(endOfTable);
+ true -> ok
+ end
+ end, Elements).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3542
+%% Slogan:
+%%-----------------------------------------------------------------
+otp_3542(suite) -> [];
+otp_3542(Config) when list(Config) ->
+ ?P1(otp_3542),
+ ?INIT_CASE(Config),
+ ?TRY_TEST1(otp_3542).
+
+otp_3542() ->
+ io:format("SNMP v3 discovery...~n"),
+ ?line Res = snmp_test_mgr:d(),
+ io:format("SNMP v3 discovery result: ~p~n",[Res]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3725
+%% Slogan: Slow response time on snmpa:int_to_enum
+%%-----------------------------------------------------------------
+otp_3725(suite) -> [];
+otp_3725(Config) when list(Config) ->
+ ?P1(otp_3725),
+ ?INIT_CASE(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?TRY_TEST2(otp_3725_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+otp_3725_test(MaNode) ->
+ io:format("Testing feature requested in ticket OTP-3725...~n"),
+ ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
+ ?DBG("otp_3725_test -> Db = ~p",[Db]),
+
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [Db, intAgentIpAddress]),
+ ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
+ [Db,OID]),
+ ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [Db, [1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, 'RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
+ ok.
+
+
+%% -- tickets --
+
+%% These are (ticket) test cases where the initiation has to be done
+%% individually.
+tickets(suite) ->
+ [otp_4394].
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-4394
+%% Slogan: Target mib tag list check invalid
+%%-----------------------------------------------------------------
+
+otp_4394(suite) -> {req, [], {conf,
+ init_otp_4394,
+ [otp_4394_test],
+ finish_otp_4394}}.
+
+init_otp_4394(Config) when list(Config) ->
+ ?DBG("init_otp_4394 -> entry with"
+ "~n Config: ~p", [Config]),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ MasterAgentVerbosity = {master_agent_verbosity, trace},
+ NetIfVerbosity = {net_if_verbosity, trace},
+ Opts = [MasterAgentVerbosity,NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config,Opts)].
+
+otp_4394_config(AgentDir, MgrDir, Ip0) ->
+ ?DBG("otp_4394_config -> entry with"
+ "~n AgentDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ Vsn = [v1],
+ Ip = tuple_to_list(Ip0),
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?TRAP_UDP, Ip, 4000,
+ "OTP-4394 test"),
+ ?line case update_usm(Vsn, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsn, MgrDir);
+ false ->
+ ?line ok
+ end,
+ C1 = {"a", "all-rights", "initial", "", "pc"},
+ C2 = {"c", "secret", "secret_name", "", "secret_tag"},
+ ?line write_community_conf(AgentDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentDir),
+ Ta1 = {"shelob v1",
+ [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ "pc1",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [],
+ 2048},
+ Ta2 = {"bifur v1",
+ [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ "pc2",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [], 2048},
+ ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentDir, Vsn),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+finish_otp_4394(Config) when list(Config) ->
+ ?DBG("finish_otp_4394 -> entry", []),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ erase(mgr_node),
+ lists:keydelete(vsn, 1, C1).
+
+otp_4394_test(suite) -> [];
+otp_4394_test(Config) ->
+ ?P1(otp_4394_test),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?TRY_TEST1(otp_4394_test1),
+ ?DBG("otp_4394_test -> done", []),
+ ok.
+
+otp_4394_test1() ->
+ ?DBG("otp_4394_test1 -> entry", []),
+ gn([[1,1]]),
+ Res =
+ case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
+ %% {error, 1, {"?",[]}, {"~w",[timeout]}}
+ {error, 1, _, {_, [timeout]}} ->
+ ?DBG("otp_4394_test1 -> expected result: timeout", []),
+ ok;
+ Else ->
+ Else
+ end,
+ ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
+ Res.
+
+
+mk_ln(X) ->
+ [length(X) | X].
+
+
+
+%% string used in index
+is(S) -> [length(S) | S].
+
+expect(A,B) -> ok = ?MGR:expect(A,B).
+expect(A,B,C) -> ok = ?MGR:expect(A,B,C).
+expect(A,B,C,D) -> ok = ?MGR:expect(A,B,C,D).
+expect(A,B,C,D,E,F) -> ok = ?MGR:expect(A,B,C,D,E,F).
+
diff --git a/lib/snmp/test/exp/snmp_agent_v2_test.erl b/lib/snmp/test/exp/snmp_agent_v2_test.erl
new file mode 100644
index 0000000000..a86449ca72
--- /dev/null
+++ b/lib/snmp/test/exp/snmp_agent_v2_test.erl
@@ -0,0 +1,5649 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmp_agent_v2_test).
+
+%% TODO
+%% * Test fault-tolerance (kill master etc)
+%%
+
+-compile(export_all).
+
+-define(application, snmp).
+
+-include_lib("kernel/include/file.hrl").
+-include_lib("test_server/include/test_server.hrl").
+-include("snmp_test_lib.hrl").
+-define(SNMP_USE_V3, true).
+-include_lib("snmp/include/snmp_types.hrl").
+%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
+
+
+-define(klas1, [1,3,6,1,2,1,7]).
+-define(klas2, [1,3,6,1,2,1,9]).
+-define(klas3, [1,3,6,1,2,1,8,1]).
+-define(klas4, [1,3,6,1,2,1,8,4]).
+-define(sa, [1,3,6,1,4,1,193,2]).
+-define(system, [1,3,6,1,2,1,1]).
+-define(snmp, [1,3,6,1,2,1,11]).
+-define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
+-define(ericsson, [1,3,6,1,4,1,193]).
+-define(testTrap, [1,3,6,1,2,1,15,0]).
+-define(xDescr, [1,3,6,1,2,1,17,1]).
+-define(xDescr2, [1,3,6,1,2,1,17,2]).
+
+-define(active, 1).
+-define(notInService, 2).
+-define(notReady, 3).
+-define(createAndGo, 4).
+-define(createAndWait, 5).
+-define(destroy, 6).
+
+-define(TRAP_UDP, 5000).
+
+-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
+
+-define(str(X), snmp_pdus:bits_to_str(X)).
+
+-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
+ [?LINE, self()]),
+ receive cont -> ok end
+ end).
+
+
+-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
+-define(v1_2(V1,V2),
+ case get(vsn) of
+ v1 -> V1;
+ _ -> V2
+ end).
+
+-define(v1_2_3(V1,V2,V3),
+ case get(vsn) of
+ v1 -> V1;
+ v2 -> V2;
+ _ -> V3
+ end).
+
+all() ->
+[cases()].
+
+groups() ->
+ [{mib_storage, [],
+ [{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()},
+ {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]},
+ {standard_mibs, [],
+ [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]},
+ {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]},
+ {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]},
+ {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]},
+ {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]},
+ {tickets, [], [{group, otp_4394}]},
+ {otp_4394, [], [otp_4394_test]}].
+
+init_per_group(otp_4394, Config) ->
+ init_otp_4394(Config);
+init_per_group(v2_inform, Config) ->
+ init_v2_inform(Config);
+init_per_group(multiple_reqs_2, Config) ->
+ init_mul(Config);
+init_per_group(multiple_reqs, Config) ->
+ init_mul(Config);
+init_per_group(test_multi_threaded, Config) ->
+ init_mt(Config);
+init_per_group(test_v3, Config) ->
+ init_v3(Config);
+init_per_group(test_v1_v2, Config) ->
+ init_v1_v2(Config);
+init_per_group(test_v2, Config) ->
+ init_v2(Config);
+init_per_group(test_v1, Config) ->
+ init_v1(Config);
+init_per_group(mib_storage_varm_mnesia, Config) ->
+ init_varm_mib_storage_mnesia(Config);
+init_per_group(mib_storage_varm_dets, Config) ->
+ init_varm_mib_storage_dets(Config);
+init_per_group(mib_storage_size_check_mnesia, Config) ->
+ init_size_check_msm(Config);
+init_per_group(mib_storage_size_check_dets, Config) ->
+ init_size_check_msd(Config);
+init_per_group(mib_storage_size_check_ets, Config) ->
+ init_size_check_mse(Config);
+init_per_group(mib_storage_mnesia, Config) ->
+ init_mib_storage_mnesia(Config);
+init_per_group(mib_storage_dets, Config) ->
+ init_mib_storage_dets(Config);
+init_per_group(mib_storage_ets, Config) ->
+ init_mib_storage_ets(Config);
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(otp_4394, Config) ->
+ finish_otp_4394(Config);
+end_per_group(v2_inform, Config) ->
+ finish_v2_inform(Config);
+end_per_group(multiple_reqs_2, Config) ->
+ finish_mul(Config);
+end_per_group(multiple_reqs, Config) ->
+ finish_mul(Config);
+end_per_group(test_multi_threaded, Config) ->
+ finish_mt(Config);
+end_per_group(test_v3, Config) ->
+ finish_v3(Config);
+end_per_group(test_v1_v2, Config) ->
+ finish_v1_v2(Config);
+end_per_group(test_v2, Config) ->
+ finish_v2(Config);
+end_per_group(test_v1, Config) ->
+ finish_v1(Config);
+end_per_group(mib_storage_varm_mnesia, Config) ->
+ finish_varm_mib_storage_mnesia(Config);
+end_per_group(mib_storage_varm_dets, Config) ->
+ finish_varm_mib_storage_dets(Config);
+end_per_group(mib_storage_size_check_mnesia, Config) ->
+ finish_size_check_msm(Config);
+end_per_group(mib_storage_size_check_dets, Config) ->
+ finish_size_check_msd(Config);
+end_per_group(mib_storage_size_check_ets, Config) ->
+ finish_size_check_mse(Config);
+end_per_group(mib_storage_mnesia, Config) ->
+ finish_mib_storage_mnesia(Config);
+end_per_group(mib_storage_dets, Config) ->
+ finish_mib_storage_dets(Config);
+end_per_group(mib_storage_ets, Config) ->
+ finish_mib_storage_ets(Config);
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+cases() ->
+case ?OSTYPE() of
+ vxworks ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_multi_threaded},
+ {group, mib_storage}, {group, tickets}];
+ _Else ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_v3},
+ {group, test_multi_threaded}, {group, mib_storage},
+ {group, tickets}]
+end.
+
+
+%%%-----------------------------------------------------------------
+%%% The test case structure is as follows:
+%%%
+%%% init_all - starts mnesia,
+%%%
+%%% init_v1 - starts agent
+%%% simple
+%%% big - e.g. starts/stops subagent, load/unloads mibs
+%%% init_mul
+%%% mul_get
+%%% mul_set
+%%% <etc>
+%%% finish_mul
+%%% <etc>
+%%% finish_v1
+%%%
+%%% init_v2 - starts agent
+%%% finish_v2
+%%%
+%%% init_bilingual - starts agent
+%%% finish_bilingual
+%%%
+%%% finish_all
+%%%
+%%% There is still one problem with these testsuites. If one test
+%%% fails, it may not be possible to run some other cases, as it
+%%% may have e.g. created some row or loaded some table, that it
+%%% didn't undo (since it failed).
+%%%-----------------------------------------------------------------
+
+init_all(Config0) when list(Config0) ->
+ ?LOG("init_all -> entry with"
+ "~n Config0: ~p",[Config0]),
+
+ %% --
+ %% Fix config:
+ %%
+
+ DataDir0 = ?config(data_dir, Config0),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config0),
+ Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+
+ %% --
+ %% Start nodes
+ %%
+
+ ?line {ok, SaNode} = start_node(snmp_sa),
+ ?line {ok, MgrNode} = start_node(snmp_mgr),
+
+
+ %% --
+ %% Create necessary files
+ %%
+
+ Dir = ?config(priv_dir, Config),
+ ?DBG("init_all -> Dir ~p", [Dir]),
+
+ DataDir = ?config(data_dir, Config),
+ ?DBG("init_all -> DataDir ~p", [DataDir]),
+
+ file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+
+ file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+
+ file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
+ ?DBG("init_all -> SaDir ~p", [SaDir]),
+
+
+ %% --
+ %% Start and initiate mnesia
+ %%
+
+ ?DBG("init_all -> load application mnesia", []),
+ ?line ok = application:load(mnesia),
+
+ ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
+ ?line ok = rpc:call(SaNode, application, load, [mnesia]),
+
+ ?DBG("init_all -> application mnesia: set_env dir",[]),
+ ?line application_controller:set_env(mnesia, dir,
+ filename:join(Dir, "Mnesia1")),
+
+ ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(Dir, "Mnesia2")]),
+
+ ?DBG("init_all -> create mnesia schema",[]),
+ ?line ok = mnesia:create_schema([SaNode, node()]),
+
+ ?DBG("init_all -> start application mnesia",[]),
+ ?line ok = application:start(mnesia),
+
+ ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
+ ?line ok = rpc:call(SaNode, application, start, [mnesia]),
+ Ip = ?LOCALHOST(),
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {agent_dir, AgentDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {mib_dir, DataDir},
+ {ip, Ip} |
+ Config].
+
+finish_all(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ stop_node(SaNode),
+ stop_node(MgrNode),
+ application:stop(mnesia).
+
+start_v1_agent(Config) when list(Config) ->
+ start_agent(Config, [v1]).
+
+start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
+ start_agent(Config, [v1], Opts).
+
+start_v2_agent(Config) when list(Config) ->
+ start_agent(Config, [v2]).
+
+start_v3_agent(Config) when list(Config) ->
+ start_agent(Config, [v3]).
+
+start_bilingual_agent(Config) when list(Config) ->
+ start_agent(Config, [v1,v2]).
+
+start_multi_threaded_agent(Config) when list(Config) ->
+ start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
+
+stop_agent(Config) when list(Config) ->
+ ?LOG("stop_agent -> entry with"
+ "~n Config: ~p",[Config]),
+
+ {Sup, Par} = ?config(snmp_sup, Config),
+ ?DBG("stop_agent -> attempt to stop (sup) ~p"
+ "~n Sup: ~p"
+ "~n Par: ~p",
+ [Sup,
+ (catch process_info(Sup)),
+ (catch process_info(Par))]),
+ stop_sup(Sup, Par),
+
+ {Sup2, Par2} = ?config(snmp_sub, Config),
+ ?DBG("stop_agent -> attempt to stop (sub) ~p"
+ "~n Sup2: ~p"
+ "~n Par2: ~p",
+ [Sup2,
+ (catch process_info(Sup2)),
+ (catch process_info(Par2))]),
+ stop_sup(Sup2, Par2),
+
+ ?DBG("stop_agent -> done - now cleanup config", []),
+ C1 = lists:keydelete(snmp_sup, 1, Config),
+ lists:keydelete(snmp_sub, 1, C1).
+
+
+stop_sup(Pid, _) when node(Pid) == node() ->
+ case (catch process_info(Pid)) of
+ PI when list(PI) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ exit(Pid, kill),
+ await_stopped(Pid, Ref);
+ {'EXIT', _Reason} ->
+ ?LOG("stop_sup -> ~p not running", [Pid]),
+ ok
+ end;
+stop_sup(Pid, _) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ ?LOG("stop_sup -> Ref: ~p", [Ref]),
+ %% Pid ! {'EXIT', Parent, shutdown}, % usch
+ exit(Pid, kill),
+ await_stopped(Pid, Ref).
+
+await_stopped(Pid, Ref) ->
+ receive
+ {'DOWN', Ref, process, Pid, _Reason} ->
+ ?DBG("received down message for ~p", [Pid]),
+ ok
+ after 10000 ->
+ ?INF("await_stopped -> timeout for ~p",[Pid]),
+ erlang:demonitor(Ref),
+ ?FAIL({failed_stop,Pid})
+ end.
+
+
+start_agent(Config, Vsn) ->
+ start_agent(Config, Vsn, []).
+start_agent(Config, Vsn, Opts) ->
+ ?LOG("start_agent -> entry (~p) with"
+ "~n Config: ~p"
+ "~n Vsn: ~p"
+ "~n Opts: ~p",[node(), Config, Vsn, Opts]),
+
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
+ snmp_app_env_init(vsn_init(Vsn) ++
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentDir},
+ {snmp_db_dir, AgentDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, trace},
+ {snmp_symbolic_store_verbosity, trace},
+ {snmp_note_store_verbosity, trace},
+ {snmp_net_if_verbosity, trace}],
+ Opts),
+
+
+ process_flag(trap_exit,true),
+
+ {ok, AppSup} = snmp_app_sup:start_link(),
+ unlink(AppSup),
+ ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
+
+ ?DBG("start_agent -> start master agent (old style)",[]),
+ Sup = case (catch snmpa_app:start(normal)) of
+ {ok, S} ->
+ ?DBG("start_agent -> started, Sup: ~p",[S]),
+ S;
+
+ Else ->
+ ?DBG("start_agent -> unknown result: ~n~p",[Else]),
+ %% Get info about the apps we depend on
+ MnesiaInfo = mnesia_running(),
+ ?FAIL({start_failed,Else,MnesiaInfo})
+ end,
+
+ ?DBG("start_agent -> unlink from supervisor",[]),
+ ?line unlink(Sup),
+ ?line SaDir = ?config(sa_dir, Config),
+ ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
+ ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
+ ?DBG("start_agent -> done",[]),
+ ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
+
+
+vsn_init(Vsn) ->
+ vsn_init([v1,v2,v3], Vsn, []).
+
+vsn_init([], _Vsn, Acc) ->
+ Acc;
+vsn_init([V|Vsns], Vsn, Acc) ->
+ case lists:member(V, Vsn) of
+ true ->
+ vsn_init(Vsns, Vsn, [{V, true}|Acc]);
+ false ->
+ vsn_init(Vsns, Vsn, [{V, false}|Acc])
+ end.
+
+snmp_app_env_init(Env0, Opts) ->
+ ?DBG("snmp_app_env_init -> unload snmp",[]),
+ ?line application:unload(snmp),
+ ?DBG("snmp_app_env_init -> load snmp",[]),
+ ?line application:load(snmp),
+ ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
+ F1 = fun({Key,Val} = New, Acc0) ->
+ ?DBG("snmp_app_env_init -> "
+ "updating setting ~p to ~p", [Key, Val]),
+ case lists:keyreplace(Key, 1, Acc0, New) of
+ Acc0 ->
+ [New|Acc0];
+ Acc ->
+ Acc
+ end
+ end,
+ Env = lists:foldr(F1, Env0, Opts),
+ ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
+ F2 = fun({Key,Val}) ->
+ ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
+ application_controller:set_env(snmp, Key, Val)
+ end,
+ lists:foreach(F2, Env).
+
+
+
+
+%% Test if application is running
+mnesia_running() -> ?IS_MNESIA_RUNNING().
+crypto_running() -> ?IS_CRYPTO_RUNNING().
+
+
+start_sub(Dir) ->
+ ?DBG("start_sub -> entry",[]),
+ Opts = [{db_dir, Dir},
+ {supervisor, [{verbosity, trace}]}],
+ %% BMK BMK
+% {ok, P} = snmp_supervisor:start_sub(Dir),
+ {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
+ unlink(P),
+ {ok, {P, self()}}.
+
+create_tables(SaNode) ->
+ ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
+ {attributes, [a1,a2]}]).
+
+delete_tables() ->
+ mnesia:delete_table(friendsTable2),
+ mnesia:delete_table(kompissTable2),
+ mnesia:delete_table(snmp_variables).
+
+%% Creation is done in runtime!
+delete_mib_storage_mnesia_tables() ->
+ mnesia:delete_table(snmpa_mib_data),
+ mnesia:delete_table(snmpa_mib_tree),
+ mnesia:delete_table(snmpa_symbolic_store).
+
+%%-----------------------------------------------------------------
+%% A test case is always one of:
+%% - v1 specific case
+%% - v2 specific case
+%% - v1 and v2 case
+%% All v1 specific cases are prefixed with v1_, and all v2 with
+%% v2_. E.g. v1_trap/v2_trap.
+%%
+%% All other cases are shared. However, the testserver uses the name
+%% of the case to generate a file for that case. The same case cannot
+%% be used in different configurations in the same suite. Therefore
+%% all these functions exists in two variants, the base function
+%% <base>, and a second version <base>_2. There may be several
+%% versions as well, <base>_N.
+%%-----------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+mib_storage_ets_cases() ->
+[mse_simple, mse_v1_processing, mse_big, mse_big2,
+ mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
+ mse_sa_error, mse_next_across_sa, mse_undo,
+ mse_standard_mib, mse_community_mib, mse_framework_mib,
+ mse_target_mib, mse_notification_mib,
+ mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
+ mse_mib_of].
+
+mib_storage_dets_cases() ->
+[msd_simple, msd_v1_processing, msd_big, msd_big2,
+ msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
+ msd_sa_error, msd_next_across_sa, msd_undo,
+ msd_standard_mib, msd_community_mib, msd_framework_mib,
+ msd_target_mib, msd_notification_mib,
+ msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
+ msd_mib_of].
+
+mib_storage_mnesia_cases() ->
+[msm_simple, msm_v1_processing, msm_big, msm_big2,
+ msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
+ msm_sa_error, msm_next_across_sa, msm_undo,
+ msm_standard_mib, msm_community_mib, msm_framework_mib,
+ msm_target_mib, msm_notification_mib,
+ msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
+ msm_mib_of].
+
+mse_size_check_cases() ->
+[mse_size_check].
+
+msd_size_check_cases() ->
+[msd_size_check].
+
+msm_size_check_cases() ->
+[msm_size_check].
+
+varm_mib_storage_dets_cases() ->
+[msd_varm_mib_start].
+
+varm_mib_storage_mnesia_cases() ->
+[msm_varm_mib_start].
+
+init_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,ets},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ init_ms(Config, [MibStorage]).
+
+init_ms(Config, Opts) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
+ [{vsn, v1} | start_v1_agent(Config,Opts1)].
+
+init_size_check_mse(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, ets},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msd(Config) when list(Config) ->
+ AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDir}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msm(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, {mnesia,[]}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_ms(Config, Opts) when list(Config) ->
+ SaNode = ?GCONF(snmp_sa, Config),
+ %% We are using v3 here, so crypto must be supported or else...
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end,
+ create_tables(SaNode),
+ AgentDir = ?GCONF(agent_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ ?line ok =
+ config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_agent(Config, [v3], Opts)].
+
+init_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_dets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+init_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_mnesia -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+finish_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_ets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_dets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_dets -> entry", []),
+ delete_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_size_check_mse(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msd(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msm(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_ms(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%% These are just interface functions to fool the test server
+mse_simple(X) -> simple(X).
+mse_v1_processing(X) -> v1_processing(X).
+mse_big(X) -> big(X).
+mse_big2(X) -> big2(X).
+mse_loop_mib(X) -> loop_mib(X).
+mse_api(X) -> api(X).
+mse_sa_register(X) -> sa_register(X).
+mse_v1_trap(X) -> v1_trap(X).
+mse_sa_error(X) -> sa_error(X).
+mse_next_across_sa(X) -> next_across_sa(X).
+mse_undo(X) -> undo(X).
+mse_standard_mib(X) -> snmp_standard_mib(X).
+mse_community_mib(X) -> snmp_community_mib(X).
+mse_framework_mib(X) -> snmp_framework_mib(X).
+mse_target_mib(X) -> snmp_target_mib(X).
+mse_notification_mib(X) -> snmp_notification_mib(X).
+mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+mse_sparse_table(X) -> sparse_table(X).
+mse_me_of(X) -> ms_me_of(X).
+mse_mib_of(X) -> ms_mib_of(X).
+
+msd_simple(X) -> simple(X).
+msd_v1_processing(X) -> v1_processing(X).
+msd_big(X) -> big(X).
+msd_big2(X) -> big2(X).
+msd_loop_mib(X) -> loop_mib(X).
+msd_api(X) -> api(X).
+msd_sa_register(X) -> sa_register(X).
+msd_v1_trap(X) -> v1_trap(X).
+msd_sa_error(X) -> sa_error(X).
+msd_next_across_sa(X) -> next_across_sa(X).
+msd_undo(X) -> undo(X).
+msd_standard_mib(X) -> snmp_standard_mib(X).
+msd_community_mib(X) -> snmp_community_mib(X).
+msd_framework_mib(X) -> snmp_framework_mib(X).
+msd_target_mib(X) -> snmp_target_mib(X).
+msd_notification_mib(X) -> snmp_notification_mib(X).
+msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msd_sparse_table(X) -> sparse_table(X).
+msd_me_of(X) -> ms_me_of(X).
+msd_mib_of(X) -> ms_mib_of(X).
+
+msm_simple(X) -> simple(X).
+msm_v1_processing(X) -> v1_processing(X).
+msm_big(X) -> big(X).
+msm_big2(X) -> big2(X).
+msm_loop_mib(X) -> loop_mib(X).
+msm_api(X) -> api(X).
+msm_sa_register(X) -> sa_register(X).
+msm_v1_trap(X) -> v1_trap(X).
+msm_sa_error(X) -> sa_error(X).
+msm_next_across_sa(X) -> next_across_sa(X).
+msm_undo(X) -> undo(X).
+msm_standard_mib(X) -> snmp_standard_mib(X).
+msm_community_mib(X) -> snmp_community_mib(X).
+msm_framework_mib(X) -> snmp_framework_mib(X).
+msm_target_mib(X) -> snmp_target_mib(X).
+msm_notification_mib(X) -> snmp_notification_mib(X).
+msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msm_sparse_table(X) -> sparse_table(X).
+msm_me_of(X) -> ms_me_of(X).
+msm_mib_of(X) -> ms_mib_of(X).
+
+
+mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
+msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
+msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
+
+msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
+msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
+
+ms_size_check(suite) -> [];
+ms_size_check(Config) when list(Config) ->
+ p("ms_size_check..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?LOG("mib server size check...", []),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMPv2-MIB"),
+ ?line load_master_std("SNMPv2-TM"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMPv2-MIB"),
+ ?line unload_master("SNMPv2-TM"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+
+varm_mib_start(suite) -> [];
+varm_mib_start(Config) when list(Config) ->
+ p("varm_mib_start..."),
+ ?LOG("varm_mib_start -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ %% Start the agent
+ Opts = ?GCONF(agent_opts, Config),
+ Config1 = start_v1_agent(Config, Opts),
+
+ %% Sleep some in order for the agent to start properly
+ ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
+ ?SLEEP(5000),
+
+ %% Load all the mibs
+ HardwiredMibs = loaded_mibs(),
+ ?DBG("varm_mib_start -> load all mibs", []),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+
+ %% Unload the hardwired mibs
+ ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
+ ?SLEEP(1000),
+ ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
+ ?line unload_mibs(HardwiredMibs), %% unload hardwired
+
+ ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
+ ?SLEEP(1000),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ Config2 = stop_agent(Config1),
+
+ %% Sleep some in order for the agent to stop properly
+ ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
+ ?SLEEP(5000),
+
+ %% Start the agent (again)
+ ?DBG("varm_mib_start -> start the agent", []),
+ Config3 = start_v1_agent(Config2, Opts),
+
+ ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
+ ?SLEEP(5000),
+
+ %% Perform the test(s)
+ ?DBG("varm_mib_start -> perform the tests", []),
+ try_test(snmp_community_mib),
+ try_test(snmp_framework_mib),
+ try_test(snmp_target_mib),
+ try_test(snmp_notification_mib),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ stop_agent(Config3),
+ ok.
+
+
+-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
+-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
+-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+ms_me_of(suite) -> [];
+ms_me_of(Config) when list(Config) ->
+ p("ms_me_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = me_of(?snmpTrapCommunity_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = me_of(?vacmViewSpinLock_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+me_of(Oid) ->
+ case snmpa:me_of(Oid) of
+ {ok, #me{oid = Oid}} ->
+ ok;
+ {ok, #me{oid = OtherOid}} ->
+ case lists:reverse(Oid) of
+ [0|Rest] ->
+ case lists:reverse(Rest) of
+ OtherOid ->
+ ok;
+ AnotherOid ->
+ {error, {invalid_oid, Oid, AnotherOid}}
+ end;
+ _ ->
+ {error, {invalid_oid, Oid, OtherOid}}
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ {error, Else}
+ end.
+
+
+ms_mib_of(suite) -> [];
+ms_mib_of(Config) when list(Config) ->
+ p("ms_mib_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
+ 'SNMP-USER-BASED-SM-MIB'),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+mib_of(Oid, ExpectedMibName) ->
+ ?DBG("mib_of -> entry with"
+ "~n Oid: ~p"
+ "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
+ %% case snmpa:mib_of(Oid) of
+ MibOf = snmpa:mib_of(Oid),
+ ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
+ case MibOf of
+ {ok, ExpectedMibName} ->
+ ok;
+ {ok, OtherMibName} ->
+ {error, {invalid_mib, ExpectedMibName, OtherMibName}};
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ ?DBG("mib_of -> Else: ~n~p", [Else]),
+ {error, Else}
+ end.
+
+
+app_info(suite) -> [];
+app_info(Config) when list(Config) ->
+ SnmpDir = app_dir(snmp),
+ SslDir = app_dir(ssl),
+ CryptoDir = app_dir(crypto),
+ Attr = snmp:module_info(attributes),
+ AppVsn =
+ case lists:keysearch(app_vsn, 1, Attr) of
+ {value, {app_vsn, V}} ->
+ V;
+ false ->
+ "undefined"
+ end,
+ io:format("Root dir: ~s~n"
+ "SNMP: Application dir: ~s~n"
+ " Application ver: ~s~n"
+ "SSL: Application dir: ~s~n"
+ "CRYPTO: Application dir: ~s~n",
+ [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
+ ok.
+
+app_dir(App) ->
+ case code:lib_dir(App) of
+ D when list(D) ->
+ filename:basename(D);
+ {error, _Reason} ->
+ "undefined"
+ end.
+
+
+
+%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].
+
+init_v1(Config) when list(Config) ->
+ ?line SaNode = ?config(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v1} | start_v1_agent(Config)].
+
+finish_v1(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v2_cases() -> [loop_mib_2];
+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].
+
+init_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_v2_agent(Config)].
+
+finish_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+v1_v2_cases() ->
+[simple_bi].
+
+init_v1_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, bilingual} | start_bilingual_agent(Config)].
+
+finish_v1_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v3_cases() -> [loop_mib_3];
+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].
+
+init_v3(Config) when list(Config) ->
+ %% Make sure crypto works, otherwise start_agent will fail
+ %% and we will be stuck with a bunch of mnesia tables for
+ %% the rest of this suite...
+ ?DBG("start_agent -> start crypto app",[]),
+ case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end
+ end,
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v3], MgrDir, AgentDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_v3_agent(Config)].
+
+finish_v3(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+mt_cases() ->
+[multi_threaded, mt_trap].
+
+init_mt(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_multi_threaded_agent(Config)].
+
+finish_mt(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+%% This one *must* be run first in each case.
+init_case(Config) when list(Config) ->
+ ?DBG("init_case -> entry with"
+ "~n Config: ~p", [Config]),
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = node(),
+
+ SaHost = ?HOSTNAME(SaNode),
+ MgrHost = ?HOSTNAME(MgrNode),
+ MasterHost = ?HOSTNAME(MasterNode),
+ {ok, MasterIP} = snmp_misc:ip(MasterHost),
+ {ok, MIP} = snmp_misc:ip(MgrHost),
+ {ok, SIP} = snmp_misc:ip(SaHost),
+
+
+ put(mgr_node, MgrNode),
+ put(sa_node, SaNode),
+ put(master_node, MasterNode),
+ put(sa_host, SaHost),
+ put(mgr_host, MgrHost),
+ put(master_host, MasterHost),
+ put(mip, tuple_to_list(MIP)),
+ put(masterip , tuple_to_list(MasterIP)),
+ put(sip, tuple_to_list(SIP)),
+
+ MibDir = ?config(mib_dir, Config),
+ put(mib_dir, MibDir),
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ put(std_mib_dir, StdM),
+
+ MgrDir = ?config(mgr_dir, Config),
+ put(mgr_dir, MgrDir),
+
+ put(vsn, ?config(vsn, Config)),
+ ?DBG("init_case -> exit with"
+ "~n MasterNode: ~p"
+ "~n SaNode: ~p"
+ "~n MgrNode: ~p"
+ "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
+ {SaNode, MgrNode, MibDir}.
+
+load_master(Mib) ->
+ ?DBG("load_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+
+load_master_std(Mib) ->
+ ?DBG("load_master_std -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+
+unload_master(Mib) ->
+ ?DBG("unload_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+
+loaded_mibs() ->
+ ?DBG("loaded_mibs -> entry",[]),
+ Info = snmpa:info(snmp_master_agent),
+ {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
+ [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
+
+unload_mibs(Mibs) ->
+ ?DBG("unload_mibs -> entry with"
+ "~n Mibs: ~p", [Mibs]),
+ ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
+
+start_subagent(SaNode, RegTree, Mib) ->
+ ?DBG("start_subagent -> entry with"
+ "~n SaNode: ~p"
+ "~n RegTree: ~p"
+ "~n Mib: ~p", [SaNode, RegTree, Mib]),
+ MA = whereis(snmp_master_agent),
+ ?DBG("start_subagent -> MA: ~p", [MA]),
+ MibDir = get(mib_dir),
+ Mib1 = join(MibDir,Mib),
+ %% BMK BMK
+% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
+ case rpc:call(SaNode, snmpa_supervisor,
+ start_sub_agent, [MA, RegTree, [Mib1]]) of
+ {ok, SA} ->
+ ?DBG("start_subagent -> SA: ~p", [SA]),
+ {ok, SA};
+ Error ->
+ ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
+ end.
+
+stop_subagent(SA) ->
+ ?DBG("stop_subagent -> entry with"
+ "~n SA: ~p", [SA]),
+ %% BNK BMK
+ %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
+ rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
+
+%%-----------------------------------------------------------------
+%% This function takes care of the old OTP-SNMPEA-MIB.
+%% Unfortunately, the testcases were written to use the data in the
+%% internal tables, and these table are now obsolete and not used
+%% by the agent. Therefore, we emulate them by using
+%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
+%%
+%% These two rows must exist in intCommunityTable
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+%% (But with the manager's IP address)
+%%
+%%-----------------------------------------------------------------
+init_old() ->
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [6 | "public"],
+ {get(mip), "public", 2, 2}),
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [13 | "standard trap"],
+ {get(mip), "standard trap", 2, 1}),
+ snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
+
+
+
+simple(suite) -> [];
+simple(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(simple_standard_test).
+
+simple_2(X) -> simple(X).
+
+simple_bi(suite) -> [];
+simple_bi(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(vsn, v1), % First, try v1 manager
+ try_test(simple_standard_test),
+
+ put(vsn, v2), % Then, try v2 manager
+ try_test(simple_standard_test).
+
+simple_3(X) ->
+ simple(X).
+
+big(suite) -> [];
+big(Config) when list(Config) ->
+ ?DBG("big -> entry", []),
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?DBG("big -> SA: ~p", [SA]),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+big_2(X) -> big(X).
+
+big_3(X) -> big(X).
+
+
+big2(suite) -> [];
+big2(Config) when list(Config) ->
+ %% This is exactly the same tests as 'big', but with the
+ %% v2 equivalent of the mibs.
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
+ ?line load_master("OLD-SNMPEA-MIB-v2"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB-v2").
+
+big2_2(X) -> big2(X).
+
+big2_3(X) -> big2(X).
+
+
+multi_threaded(suite) -> [];
+multi_threaded(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(multi_threaded_test),
+ ?line unload_master("Test1").
+
+mt_trap(suite) -> [];
+mt_trap(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ ?line load_master("TestTrapv2"),
+ try_test(mt_trap_test, [MA]),
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("Test1").
+
+v2_types(suite) -> [];
+v2_types(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(types_v2_test),
+ ?line unload_master("Test1").
+
+v2_types_3(X) -> v2_types(X).
+
+
+implied(suite) -> [];
+implied(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(implied_test,[MA]),
+ ?line unload_master("Test1").
+
+implied_3(X) -> implied(X).
+
+
+sparse_table(suite) -> [];
+sparse_table(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(sparse_table_test),
+ ?line unload_master("Test1").
+
+sparse_table_2(X) -> sparse_table(X).
+
+sparse_table_3(X) -> sparse_table(X).
+
+cnt_64(suite) -> [];
+cnt_64(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(cnt_64_test, [MA]),
+ ?line unload_master("Test1").
+
+cnt_64_2(X) -> cnt_64(X).
+
+cnt_64_3(X) -> cnt_64(X).
+
+opaque(suite) -> [];
+opaque(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(opaque_test),
+ ?line unload_master("Test1").
+
+opaque_2(X) -> opaque(X).
+
+opaque_3(X) -> opaque(X).
+
+
+change_target_addr_config(suite) -> [];
+change_target_addr_config(Config) when list(Config) ->
+ p("Testing changing target address config..."),
+ ?LOG("change_target_addr_config -> entry",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(sname,snmp_suite),
+ put(verbosity,trace),
+
+ MA = whereis(snmp_master_agent),
+
+ ?LOG("change_target_addr_config -> load TestTrap",[]),
+ ?line load_master("TestTrap"),
+
+ ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,trace),
+
+ %% First send some traps that will arive att the original manager
+ ?LOG("change_target_addr_config -> send trap",[]),
+ try_test(ma_trap1, [MA]),
+
+ ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,silence),
+
+ %% Start new dummy listener
+ ?LOG("change_target_addr_config -> start dummy manager",[]),
+ ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+
+ %% Reconfigure
+ ?LOG("change_target_addr_config -> reconfigure",[]),
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_addr_conf(AgentDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ %% Send the trap again
+ ?LOG("change_target_addr_config -> send trap again",[]),
+ catch dummy_manager_send_trap2(Pid),
+
+ ?LOG("change_target_addr_config -> await trap ack",[]),
+ catch dummy_manager_await_trap2_ack(),
+
+ ?LOG("change_target_addr_config -> stop dummy manager",[]),
+ ?line ok = dummy_manager_stop(Pid),
+
+ ?LOG("change_target_addr_config -> reset target address config",[]),
+ ?line reset_target_addr_conf(AgentDir),
+
+ ?LOG("change_target_addr_config -> unload TestTrap",[]),
+ ?line unload_master("TestTrap").
+
+
+dummy_manager_start(MA) ->
+ ?DBG("dummy_manager_start -> entry",[]),
+ Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
+ ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
+ await_dummy_manager_started(Pid).
+
+await_dummy_manager_started(Pid) ->
+ receive
+ {dummy_manager_started,Pid,Port} ->
+ ?DBG("dummy_manager_start -> acknowledge received with"
+ "~n Port: ~p",[Port]),
+ {ok,Pid,Port};
+ {'EXIT', Pid, Reason} ->
+ {error, Pid, Reason};
+ O ->
+ ?LOG("dummy_manager_start -> received unknown message:"
+ "~n ~p",[O]),
+ await_dummy_manager_started(Pid)
+ end.
+
+dummy_manager_stop(Pid) ->
+ ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
+ Pid ! stop,
+ receive
+ {dummy_manager_stopping, Pid} ->
+ ?DBG("dummy_manager_stop -> acknowledge received",[]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_stop -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_send_trap2(Pid) ->
+ ?DBG("dummy_manager_send_trap2 -> entry",[]),
+ Pid ! {send_trap,testTrap2}.
+
+dummy_manager_await_trap2_ack() ->
+ ?DBG("dummy_manager_await_trap2 -> entry",[]),
+ receive
+ {received_trap,Trap} ->
+ ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
+ %% Note:
+ %% Without this sleep the v2_inform_i testcase failes! There
+ %% is no relation between these two test cases as far as I
+ %% able to figure out...
+ sleep(60000),
+ ok;
+ O ->
+ ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_await_trap2 -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_init(Parent,MA) ->
+ ?DBG("dummy_manager_init -> entry with"
+ "~n Parent: ~p"
+ "~n MA: ~p",[Parent,MA]),
+ {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
+ ?DBG("dummy_manager_init -> S: ~p",[S]),
+ {ok,Port} = inet:port(S),
+ ?DBG("dummy_manager_init -> Port: ~p",[Port]),
+ Parent ! {dummy_manager_started,self(),Port},
+ dummy_manager_loop(Parent,S,MA).
+
+dummy_manager_loop(P,S,MA) ->
+ ?LOG("dummy_manager_loop -> ready for receive",[]),
+ receive
+ {send_trap,Trap} ->
+ ?LOG("dummy_manager_loop -> received trap send request"
+ "~n Trap: ~p",[Trap]),
+ snmpa:send_trap(MA, Trap, "standard trap"),
+ dummy_manager_loop(P,S,MA);
+ {udp, _UdpId, Ip, UdpPort, Bytes} ->
+ ?LOG("dummy_manager_loop -> received upd message"
+ "~n from: ~p:~p"
+ "~n size: ~p",
+ [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
+ R = dummy_manager_handle_message(Bytes),
+ ?DBG("dummy_manager_loop -> R: ~p",[R]),
+ P ! R,
+ dummy_manager_loop(P,S,MA);
+ stop ->
+ ?DBG("dummy_manager_loop -> received stop request",[]),
+ P ! {dummy_manager_stopping, self()},
+ gen_udp:close(S),
+ exit(normal);
+ O ->
+ ?LOG("dummy_manager_loop -> received unknown message:"
+ "~n ~p",[O]),
+ dummy_manager_loop(P,S,MA)
+ end.
+
+dummy_manager_message_sz(B) when binary(B) ->
+ size(B);
+dummy_manager_message_sz(L) when list(L) ->
+ length(L);
+dummy_manager_message_sz(_) ->
+ undefined.
+
+dummy_manager_handle_message(Bytes) ->
+ case (catch snmp_pdus:dec_message(Bytes)) of
+ {'EXIT',Reason} ->
+ ?ERR("dummy_manager_handle_message -> "
+ "failed decoding message only:~n ~p",[Reason]),
+ {error,Reason};
+ M ->
+ ?DBG("dummy_manager_handle_message -> decoded message:"
+ "~n ~p",[M]),
+ {received_trap,M}
+ end.
+
+
+api(suite) -> [];
+api(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(api_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+api_2(X) -> api(X).
+
+api_3(X) -> api(X).
+
+
+subagent(suite) -> [];
+subagent(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ try_test(load_test_sa),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+
+ p("Loading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(load_test),
+
+ p("Unloading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(unreg_test),
+ p("Testing register subagent..."),
+ rpc:call(SaNode, snmp, register_subagent,
+ [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ ?line stop_subagent(SA),
+ try_test(unreg_test).
+
+subagent_2(X) -> subagent(X).
+
+subagent_3(X) -> subagent(X).
+
+
+mnesia(suite) -> [];
+mnesia(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent with mnesia impl..."),
+ {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ try_test(big_test_2),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA).
+
+mnesia_2(X) -> mnesia(X).
+
+mnesia_3(X) -> mnesia(X).
+
+
+
+mul_cases() ->
+[mul_get, mul_get_err, mul_next, mul_next_err,
+ mul_set_err].
+
+
+multiple_reqs_3(_X) ->
+ {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
+
+
+mul_cases_2() ->
+[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
+ mul_set_err_2].
+
+
+mul_cases_3() ->
+ [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
+
+
+init_mul(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ [{mul_sub, SA} | Config].
+
+finish_mul(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ SA = ?config(mul_sub, Config),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA),
+ lists:keydelete(mul_sub, 1, Config).
+
+mul_get(suite) -> [];
+mul_get(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get..."),
+ try_test(do_mul_get).
+
+mul_get_2(X) -> mul_get(X).
+
+mul_get_3(X) -> mul_get(X).
+
+
+mul_get_err(suite) -> [];
+mul_get_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get with error..."),
+ try_test(do_mul_get_err).
+
+mul_get_err_2(X) -> mul_get_err(X).
+
+mul_get_err_3(X) -> mul_get_err(X).
+
+
+mul_next(suite) -> [];
+mul_next(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next).
+
+mul_next_2(X) -> mul_next(X).
+
+mul_next_3(X) -> mul_next(X).
+
+
+mul_next_err(suite) -> [];
+mul_next_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next_err).
+
+mul_next_err_2(X) -> mul_next_err(X).
+
+mul_next_err_3(X) -> mul_next_err(X).
+
+
+mul_set(suite) -> [];
+mul_set(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set..."),
+ try_test(do_mul_set).
+
+mul_set_2(X) -> mul_set(X).
+
+mul_set_3(X) -> mul_set(X).
+
+
+mul_set_err(suite) -> [];
+mul_set_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set with error..."),
+ try_test(do_mul_set_err).
+
+mul_set_err_2(X) -> mul_set_err(X).
+
+mul_set_err_3(X) -> mul_set_err(X).
+
+
+sa_register(suite) -> [];
+sa_register(Config) when list(Config) ->
+ ?DBG("sa_register -> entry", []),
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?DBG("sa_register -> start subagent", []),
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+
+ ?DBG("sa_register -> unregister subagent", []),
+ p("Testing unregister subagent (2)..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Loading SA-MIB..."),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ ?DBG("sa_register -> register subagent", []),
+ rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
+ try_test(sa_mib),
+
+ ?DBG("sa_register -> stop subagent", []),
+ ?line stop_subagent(SA).
+
+sa_register_2(X) -> sa_register(X).
+
+sa_register_3(X) -> sa_register(X).
+
+
+v1_trap(suite) -> [];
+v1_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_trap1, [MA]),
+ try_test(ma_trap2, [MA]),
+ try_test(ma_v2_2_v1_trap, [MA]),
+ try_test(ma_v2_2_v1_trap2, [MA]),
+
+ p("Testing trap sending from subagent..."),
+ try_test(sa_trap1, [SA]),
+ try_test(sa_trap2, [SA]),
+ try_test(sa_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v2_trap(suite) -> [];
+v2_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+
+ try_test(ma_v2_trap1, [MA]),
+ try_test(ma_v2_trap2, [MA]),
+ try_test(ma_v1_2_v2_trap, [MA]),
+ try_test(ma_v1_2_v2_trap2, [MA]),
+
+ try_test(sa_mib),
+ p("Testing trap sending from subagent..."),
+ try_test(sa_v1_2_v2_trap1, [SA]),
+ try_test(sa_v1_2_v2_trap2, [SA]),
+ try_test(sa_v1_2_v2_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v3_trap(X) ->
+ v2_trap(X).
+
+
+v3_inform(_X) ->
+ %% v2_inform(X).
+ {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
+
+init_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+init_v3_inform(X) ->
+ init_v2_inform(X).
+
+finish_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+finish_v3_inform(X) ->
+ finish_v2_inform(X).
+
+
+
+v2_inform_i(suite) -> [];
+v2_inform_i(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing inform sending from master agent... NOTE! This test\ntakes a "
+ "few minutes (5) to complete."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_v2_inform1, [MA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2").
+
+v3_inform_i(X) -> v2_inform_i(X).
+
+
+sa_error(suite) -> [];
+sa_error(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing sa bad value (is_set_ok)..."),
+ try_test(sa_errs_bad_value),
+
+ p("Testing sa gen err (set)..."),
+ try_test(sa_errs_gen_err),
+
+ p("Testing too big..."),
+ try_test(sa_too_big),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
+
+sa_error_2(X) -> sa_error(X).
+
+sa_error_3(X) -> sa_error(X).
+
+
+next_across_sa(suite) -> [];
+next_across_sa(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Loading another subagent mib..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+
+ rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ p("Testing next across subagent (endOfMibView from SA)..."),
+ try_test(next_across_sa),
+
+ p("Unloading mib"),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Starting another subagent"),
+ ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ p("Testing next across subagent (wrong prefix from SA)..."),
+ try_test(next_across_sa),
+
+ stop_subagent(SA),
+ stop_subagent(SA2).
+
+next_across_sa_2(X) -> next_across_sa(X).
+
+next_across_sa_3(X) -> next_across_sa(X).
+
+
+undo(suite) -> [];
+undo(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing undo phase at master agent..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ try_test(undo_test),
+ try_test(api_test2),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+
+ p("Testing bad return values from instrum. funcs..."),
+ try_test(bad_return),
+
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+
+ p("Testing undo phase at subagent..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ try_test(undo_test),
+ try_test(api_test3),
+
+ p("Testing undo phase across master/subagents..."),
+ try_test(undo_test),
+ try_test(api_test3),
+ stop_subagent(SA).
+
+undo_2(X) -> undo(X).
+
+undo_3(X) -> undo(X).
+
+%% Req. Test2
+v1_processing(suite) -> [];
+v1_processing(Config) when list(Config) ->
+ ?DBG("v1_processing -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v1_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v2_processing(suite) -> [];
+v2_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v3_processing(suite) -> [];
+v3_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc), % same as v2!
+ ?line unload_master("Test2").
+
+
+%% We'll try get/set/trap and inform for all the auth & priv protocols.
+%% For informs, the mgr is auth-engine. The agent has to sync. This is
+%% accomplished by the first inform sent. That one will generate a
+%% report, which makes it in sync. The notification-generating
+%% application times out, and send again. This time it'll work.
+
+v3_crypto_basic(suite) -> [];
+v3_crypto_basic(_Config) ->
+ EID = [0,0,0,0,0,0,0,0,0,0,0,2],
+ %% From rfc2274 appendix A.3.1
+ ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
+ ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
+ 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
+ KMd5_1,
+ %% From rfc2274 appendix A.3.2
+ ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
+ ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
+ 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
+ KSHA_1,
+ %% From rfc2274, appendix A.5.1
+ ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
+ 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ %% From rfc2274, appendix A.5.2
+ ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
+ 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
+ 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ KSHA_1t = lists:sublist(KSHA_1, 16),
+ KSHA_2t = lists:sublist(KSHA_2, 16),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
+ 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+
+ %% Try with correct random
+ ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
+ ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
+ ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
+ ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
+ ok.
+
+
+
+v3_md5_auth(suite) -> [];
+v3_md5_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing MD5 authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_sha_auth(suite) -> [];
+v3_sha_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing SHA authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_des_priv(suite) -> [];
+v3_des_priv(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing DES encryption...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+%% Make sure mgr is in sync with agent
+v3_sync(Funcs) ->
+ ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
+ g([[sysDescr, 0]]),
+ expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
+ g([[sysDescr, 0]]),
+ expect(433, [{[sysDescr,0], any}]),
+ lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
+
+v3_inform_sync(MA) ->
+ ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
+ "standard inform", []),
+ %% Make sure agent is in sync with mgr...
+ ?DBG("v3_sync -> wait some time: ",[]),
+ sleep(20000), % more than 1500*10 in target_addr.conf
+ ?DBG("v3_sync -> await response",[]),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]).
+
+
+v2_caps(suite) -> [];
+v2_caps(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(v2_caps_i, [node()]).
+
+v2_caps_3(X) -> v2_caps(X).
+
+
+v2_caps_i(Node) ->
+ ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
+ g([[sysORID, Idx], [sysORDescr, Idx]]),
+ ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
+ {[sysORDescr, Idx], "test cap"}]),
+ ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
+ g([[sysORID, Idx]]),
+ ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
+
+
+%% Req. Test2
+v1_proc() ->
+ ?DBG("v1_proc -> entry", []),
+ %% According to RFC1157.
+ %% Template: <Section>:<list no>
+ v1_get_p(),
+ v1_get_next_p(),
+ v1_set_p().
+
+
+v1_get_p() ->
+ %% 4.1.2:1
+ g([[test2]]),
+ ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
+ g([[tDescr]]),
+ ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
+ g([[tDescr2,0]]),
+ ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ g([[tDescr3,0]]),
+ ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ g([[tDescr4,0]]),
+ ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ {[tDescr,0], 'NULL'}]),
+ g([[sysDescr,3]]),
+ ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+
+ %% 4.1.2:2
+ g([[tTable]]),
+ ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
+ g([[tEntry]]),
+ ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
+
+ %% 4.1.2:3
+ g([[tTooBig, 0]]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.2:4
+ g([[tGenErr1, 0]]),
+ ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]).
+
+
+v1_get_next_p() ->
+ %% 4.1.3:1
+ gn([[1,3,7,1]]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+ gn([[tDescr2]]),
+ ?line expect(11, tooBig, 0, any),
+
+ %% 4.1.3:2
+ gn([[tTooBig]]),
+ io:format("We currently don't handle tooBig correct!!!\n"),
+% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
+ ?line expect(20, tooBig, 0, any),
+
+ %% 4.1.3:3
+ gn([[tGenErr1]]),
+% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?line expect(40, genErr, 1, any),
+ gn([[tGenErr2]]),
+% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?line expect(41, genErr, 1, any),
+ gn([[sysDescr], [tGenErr3]]),
+% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
+% {[tGenErr3], 'NULL'}]).
+ ?line expect(42, genErr, 2, any).
+
+v1_set_p() ->
+ %% 4.1.5:1
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+ s([{[tDescr3], s, "noSuchObject"}]),
+ ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+ s([{[tDescr3,1], s, "noSuchInstance"}]),
+ ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+ s([{[tDescr2,0], s, "inconsistentName"}]),
+ ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+
+ %% 4.1.5:2
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.1.5:3
+ %% The standard is quite incorrect here. The resp pdu was too big. In
+ %% the resp pdu, we have the original vbs. In the tooBig pdu we still
+ %% have to original vbs => the tooBig pdu is too big as well!!! It
+ %% may not get it to the manager, unless the agent uses 'NULL' instead
+ %% of the std-like original value.
+ s([{[tTooBig, 0], s, ?tooBigStr}]),
+ %% according to std:
+% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.5:4
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+ s([{[tDescr2, 0], s, "commit_fail"}]),
+ ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+
+%% Req. Test2
+v2_proc() ->
+ %% According to RFC1905.
+ %% Template: <Section>:<list no>
+ ?DBG("v2_proc -> entry",[]),
+ v2_get_p(),
+ v2_get_next_p(),
+ v2_get_bulk_p(),
+ v2_set_p().
+
+v2_get_p() ->
+ %% 4.2.1:2
+ ?DBG("v2_get_p -> entry",[]),
+ g([[test2]]),
+ ?line expect(10, [{[test2], noSuchObject}]),
+ g([[tDescr]]),
+ ?line expect(11, [{[tDescr], noSuchObject}]),
+ g([[tDescr4,0]]),
+ ?line expect(12, [{[tDescr4,0], noSuchObject}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[tDescr,0], noSuchObject}]),
+ g([[tTable]]),
+ ?line expect(14, [{[tTable], noSuchObject}]),
+ g([[tEntry]]),
+ ?line expect(15, [{[tEntry], noSuchObject}]),
+
+ %% 4.2.1:3
+ g([[tDescr2,0]]), %% instrum ret noSuchName!!!
+ ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
+ g([[tDescr3,0]]),
+ ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
+ g([[sysDescr,3]]),
+ ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
+ g([[tIndex,1]]),
+ ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
+
+ %% 4.2.1 - any other error: genErr
+ g([[tGenErr1, 0]]),
+ ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]),
+
+ %% 4.2.1 - tooBig
+ g([[tTooBig, 0]]),
+ ?line expect(40, tooBig, 0, []).
+
+
+v2_get_next_p() ->
+ %% 4.2.2:2
+ ?DBG("v2_get_next_p -> entry",[]),
+ gn([[1,3,7,1]]),
+ ?line expect(10, [{[1,3,7,1], endOfMibView}]),
+ gn([[sysDescr], [1,3,7,1]]),
+ ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gn([[tCnt2, 1]]),
+ ?line expect(12, [{[tCnt2,2], 100}]),
+ gn([[tCnt2, 2]]),
+ ?line expect(12, [{[tCnt2,2], endOfMibView}]),
+
+ %% 4.2.2 - any other error: genErr
+ gn([[tGenErr1]]),
+ ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ gn([[tGenErr2]]),
+ ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ gn([[sysDescr], [tGenErr3]]),
+ ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
+ {[tGenErr3], 'NULL'}]),
+
+ %% 4.2.2 - tooBig
+ gn([[tTooBig]]),
+ ?line expect(20, tooBig, 0, []).
+
+v2_get_bulk_p() ->
+ %% 4.2.3
+ ?DBG("v2_get_bulk_p -> entry",[]),
+ gb(1, 1, []),
+ ?line expect(10, []),
+ gb(-1, 1, []),
+ ?line expect(11, []),
+ gb(-1, -1, []),
+ ?line expect(12, []),
+ gb(-1, -1, []),
+ ?line expect(13, []),
+ gb(2, 0, [[sysDescr], [1,3,7,1]]),
+ ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(1, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(0, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
+ ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
+ ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[sysDescr, 0], "Erlang SNMP agent"}]),
+
+ gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
+ ?line expect(19, []),
+
+ gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
+ ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
+ {[sysObjectID], 'NULL'},
+ {[tGenErr1], 'NULL'},
+ {[sysDescr], 'NULL'}]),
+ gb(0, 2, [[tCnt2, 1]]),
+ ?line expect(21, [{[tCnt2,2], 100},
+ {[tCnt2,2], endOfMibView}]).
+
+
+v2_set_p() ->
+ %% 4.2.5:1
+ ?DBG("v2_set_p -> entry",[]),
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
+
+ %% 4.2.5:2
+ s([{[1,3,6,1,0], s, "noSuchObject"}]),
+ ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
+
+ %% 4.2.5:3
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.2.5:4
+ s([{[tStr, 0], s, ""}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
+ s([{[tStr, 0], s, "12345"}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
+
+ %% 4.2.5:5 - N/A
+
+ %% 4.2.5:6
+ s([{[tInt1, 0], i, 0}]),
+ ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
+ s([{[tInt1, 0], i, 5}]),
+ ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
+ s([{[tInt2, 0], i, 0}]),
+ ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
+ s([{[tInt2, 0], i, 5}]),
+ ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
+ s([{[tInt3, 0], i, 5}]),
+ ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
+
+ %% 4.2.5:7
+ s([{[tDescrX, 1, 1], s, "noCreation"}]),
+ ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
+
+ %% 4.2.5:8
+ s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
+ ?line expect(80, inconsistentName, 1,
+ [{[tDescrX, 1, 2], "inconsistentName"}]),
+
+ %% 4.2.5:9
+ s([{[tCnt, 1, 2], i, 5}]),
+ ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
+
+ %% 4.2.5:10
+ s([{[tDescr2,0], s, "inconsistentValue"}]),
+ ?line expect(100, inconsistentValue, 1,
+ [{[tDescr2,0], "inconsistentValue"}]),
+
+ %% 4.2.5:11
+ s([{[tDescr2,0], s, "resourceUnavailable"}]),
+ ?line expect(110, resourceUnavailable, 1,
+ [{[tDescr2,0],"resourceUnavailable"}]),
+
+ %% 4.2.5:12
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
+
+ %% commitFailed and undoFailed is tested by the 'undo' case.
+
+
+%% Req. OLD-SNMPEA-MIB
+table_test() ->
+ io:format("Testing simple get, next and set on communityTable...~n"),
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+ Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
+ Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
+ Key1c4 = [intCommunityAccess,get(mip),is("public")],
+ EndKey = [intCommunityEntry,[9],get(mip),is("public")],
+ gn([[intCommunityEntry]]),
+ ?line expect(7, [{Key1c3, 2}]),
+ gn([[intCommunityTable]]),
+ ?line expect(71, [{Key1c3, 2}]),
+ gn([[community]]),
+ ?line expect(72, [{Key1c3, 2}]),
+ gn([[otpSnmpeaMIB]]),
+ ?line expect(73, [{Key1c3, 2}]),
+ gn([[ericsson]]),
+ ?line expect(74, [{Key1c3, 2}]),
+ gn([Key1c3]),
+ ?line expect(8, [{Key2c3, 2}]),
+ gn([Key2c3]),
+ ?line expect(9, [{Key1c4, 2}]),
+ gn([EndKey]),
+ AgentIp = [intAgentIpAddress,0],
+ ?line expect(10, [{AgentIp, any}]),
+ g([Key1c3]),
+ ?line expect(11, [{Key1c3, 2}]),
+ g([EndKey]),
+ ?line ?v1_2(expect(12, noSuchName, 1, any),
+ expect(12, [{EndKey, noSuchObject}])),
+
+ io:format("Testing row creation/deletion on communityTable...~n"),
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+ s([{NewKeyc5, ?createAndGo}]),
+ ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
+ s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
+ ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
+ g([NewKeyc4]),
+ ?line expect(16, [{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(17, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?createAndWait}]),
+ ?line expect(19, [{NewKeyc5, ?createAndWait}]),
+ g([NewKeyc5]),
+ ?line expect(20, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(21, [{NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(22, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc3, 2}]),
+ ?line expect(23, [{NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(24, [{NewKeyc5, ?notInService}]),
+ s([{NewKeyc5, ?active}]),
+ ?line expect(25, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(26, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc3, 3}]),
+ ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
+ otp_1128().
+
+%% Req. system group
+simple_standard_test() ->
+ ?DBG("simple_standard_test -> entry",[]),
+ gn([[1,1]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3]]),
+ ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6]]),
+ ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1]]),
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2]]),
+ ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1]]),
+ ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1,1]]),
+ ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[sysDescr]]),
+ ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr,0]]),
+ ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr]]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{[sysDescr], noSuchObject}])),
+ g([[1,6,7,0]]),
+ ?line ?v1_2(expect(41, noSuchName, 1, any),
+ expect(3, [{[1,6,7,0], noSuchObject}])),
+ gn([[1,13]]),
+ ?line ?v1_2(expect(4, noSuchName,1, any),
+ expect(4, [{[1,13], endOfMibView}])),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+ g([[sysLocation, 0]]),
+ ?line expect(6, [{[sysLocation, 0], "new_value"}]),
+ io:format("Testing noSuchName and badValue...~n"),
+ s([{[sysServices,0], 3}]),
+ ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
+ s([{[sysLocation, 0], i, 3}]),
+ ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
+ ?DBG("simple_standard_test -> done",[]),
+ ok.
+
+%% This is run in the agent node
+db_notify_client(suite) -> [];
+db_notify_client(Config) when list(Config) ->
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
+ [SaNode,MgrNode,MibDir]),
+ snmpa_local_db:register_notify_client(self(),?MODULE),
+
+ %% This call (the manager) will issue to set operations, so
+ %% we expect to receive to notify(insert) calls.
+ try_test(db_notify_client_test),
+
+ ?DBG("await first notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
+ end,
+
+ ?DBG("await second notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
+ end,
+
+ snmpa_local_db:unregister_notify_client(self()).
+
+
+%% This is run in the manager node
+db_notify_client_test() ->
+ ?DBG("set first new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?DBG("set second new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]).
+
+notify(Pid,What) ->
+ ?DBG("notify(~p,~p) -> called",[Pid,What]),
+ Pid ! {db_notify_test_reply,What}.
+
+
+%% Req: system group, OLD-SNMPEA-MIB, Klas1
+big_test() ->
+ ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
+ simple_standard_test(),
+
+ ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
+ gn([[klas1]]),
+ ?line expect(1, [{[fname,0], ""}]),
+ g([[fname,0]]),
+ ?line expect(2, [{[fname,0], ""}]),
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[fname,0]]),
+ ?line expect(4, [{[fname,0], "test set"}]),
+
+ ?DBG("big_test -> "
+ "testing next from last instance in master to subagent...",[]),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname,0], "test set"}]),
+ s([{[fname,0], s, ""}]),
+ ?line expect(52, [{[fname,0], ""}]),
+
+ table_test(),
+
+ ?DBG("big_test -> adding one row in subagent table",[]),
+ _FTab = [friendsEntry],
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {[friendsEntry, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ s([{[friendsEntry, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
+
+ otp_1131(),
+
+ ?DBG("big_test -> adding two rows in subagent table with special INDEX",
+ []),
+ s([{[kompissEntry, [1, 3]], s, "kompis3"},
+ {[kompissEntry, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry, [1, 3]],
+ [kompissEntry, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ gn([[kompissEntry, [1]],
+ [kompissEntry, [2]]]),
+ ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ s([{[kompissEntry, [1, 2]], s, "kompis3"},
+ {[kompissEntry, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry, [1, 1]],
+ [kompissEntry, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?active}]),
+ s([{[kompissEntry, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
+ s([{[kompissEntry, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
+ ?DBG("big_test -> done",[]),
+ ok.
+
+%% Req. system group, Klas2, OLD-SNMPEA-MIB
+big_test_2() ->
+ p("Testing simple next/get/set @ master agent (2)..."),
+ simple_standard_test(),
+
+ p("Testing simple next/get/set @ subagent (2)..."),
+ gn([[klas2]]),
+ ?line expect(1, [{[fname2,0], ""}]),
+ g([[fname2,0]]),
+ ?line expect(2, [{[fname2,0], ""}]),
+ s([{[fname2,0], s, "test set"}]),
+ ?line expect(3, [{[fname2,0], "test set"}]),
+ g([[fname2,0]]),
+ ?line expect(4, [{[fname2,0], "test set"}]),
+
+ otp_1298(),
+
+ p("Testing next from last object in master to subagent (2)..."),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname2,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname2,0], "test set"}]),
+
+ table_test(),
+
+ p("Adding one row in subagent table (2)"),
+ _FTab = [friendsEntry2],
+ s([{[friendsEntry2, [2, 3]], s, "kompis3"},
+ {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry2, [2, 3]],
+ [friendsEntry2, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?active}]),
+ s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
+
+ p("Adding two rows in subagent table with special INDEX (2)"),
+ s([{[kompissEntry2, [1, 3]], s, "kompis3"},
+ {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry2, [1, 3]],
+ [kompissEntry2, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ gn([[kompissEntry2, [1]],
+ [kompissEntry2, [2]]]),
+ ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ s([{[kompissEntry2, [1, 2]], s, "kompis3"},
+ {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry2, [1, 1]],
+ [kompissEntry2, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?active}]),
+ s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
+ s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
+ ok.
+
+%% Req. Test1
+multi_threaded_test() ->
+ p("Testing multi threaded agent..."),
+ g([[multiStr,0]]),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(1, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "pelle"}]),
+ ?line expect(2, [{[sysLocation, 0], "pelle"}]),
+ Pid ! continue,
+ ?line expect(3, [{[multiStr,0], "ok"}]),
+
+ s([{[multiStr, 0], s, "block"}]),
+ Pid2 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(4, [{[sysUpTime,0], any}]),
+ g([[multiStr,0]]),
+ Pid3 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(5, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "kalle"}]),
+ Pid3 ! continue,
+ ?line expect(6, [{[multiStr,0], "ok"}]),
+ Pid2 ! continue,
+ ?line expect(7, [{[multiStr,0], "block"}]),
+ ?line expect(8, [{[sysLocation,0], "kalle"}]).
+
+%% Req. Test1, TestTrapv2
+mt_trap_test(MA) ->
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ snmpa:send_trap(MA, mtTrap, "standard trap"),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(2, [{[sysUpTime,0], any}]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ Pid ! continue,
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [2]},
+ {[multiStr,0], "ok"}]).
+
+
+get_multi_pid() ->
+ get_multi_pid(10).
+get_multi_pid(0) ->
+ ?line ?FAIL(no_global_name);
+get_multi_pid(N) ->
+ sleep(1000),
+ case global:whereis_name(snmp_multi_tester) of
+ Pid when pid(Pid) -> Pid;
+ _ -> get_multi_pid(N-1)
+ end.
+
+%% Req. Test1
+types_v2_test() ->
+ p("Testing v2 types..."),
+
+ s([{[bits1,0], 2#10}]),
+ ?line expect(1, [{[bits1,0], ?str(2#10)}]),
+ g([[bits1,0]]),
+ ?line expect(2, [{[bits1,0], ?str(2#101)}]),
+
+ s([{[bits2,0], 2#11000000110}]),
+ ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
+ g([[bits2,0]]),
+ ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
+
+ g([[bits3,0]]),
+ ?line expect(50, genErr, 1, any),
+
+ g([[bits4,0]]),
+ ?line expect(51, genErr, 1, any),
+
+ s([{[bits1,0], s, [2#10]}]),
+ ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
+
+ s([{[bits2,0], 2#11001001101010011}]),
+ ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%% Req. Test1
+implied_test(MA) ->
+ ?LOG("implied_test -> start",[]),
+ p("Testing IMPLIED..."),
+
+ snmpa:verbosity(MA,trace),
+ snmpa:verbosity(MA,trace),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = "apa",
+ Idx2 = "qq",
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
+ ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
+ {[testDescr, Idx1], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
+ ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
+ {[testDescr, Idx2], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr)",[]),
+ gn([[testDescr]]),
+ ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
+ gn([[testDescr,Idx1]]),
+ ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?destroy}]),
+ ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?destroy}]),
+ ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
+
+ %% Try the same in other table
+ Idx3 = [1, "apa"],
+ Idx4 = [1, "qq"],
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
+ ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
+ {[testDescr2, Idx3], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
+ ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
+ {[testDescr2, Idx4], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr2)",[]),
+ gn([[testDescr2]]),
+ ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
+ gn([[testDescr2,Idx3]]),
+ ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?destroy}]),
+ ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?destroy}]),
+ ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
+
+ snmpa:verbosity(MA,log),
+
+ ?LOG("implied_test -> done",[]).
+
+
+
+%% Req. Test1
+sparse_table_test() ->
+ p("Testing sparse table..."),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ s([{[sparseStatus, Idx1], i, ?createAndGo},
+ {[sparseDescr, Idx1], s, "row 1"}]),
+ ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
+ {[sparseDescr, Idx1], "row 1"}]),
+ s([{[sparseStatus, Idx2], i, ?createAndGo},
+ {[sparseDescr, Idx2], s, "row 2"}]),
+ ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
+ {[sparseDescr, Idx2], "row 2"}]),
+ ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
+ [sparseStatus,Idx1], [sparseStatus,Idx2]]),
+ gb(0,5,[[sparseIndex]])),
+ ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
+ {[sparseDescr,Idx2], "row 2"},
+ {[sparseStatus,Idx1], ?active},
+ {[sparseStatus,Idx2], ?active},
+ {[sparseStr,0], "slut"}]),
+ % Delete the rows
+ s([{[sparseStatus, Idx1], i, ?destroy}]),
+ ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
+ s([{[sparseStatus, Idx2], i, ?destroy}]),
+ ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
+
+
+%% Req. Test1
+cnt_64_test(MA) ->
+ ?LOG("start cnt64 test (~p)",[MA]),
+ snmpa:verbosity(MA,trace),
+ ?LOG("start cnt64 test",[]),
+ p("Testing Counter64, and at the same time, RowStatus is not last column"),
+
+ ?DBG("get cnt64",[]),
+ g([[cnt64,0]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(1, noSuchName, 1, any),
+ expect(1, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("get-next cnt64",[]),
+ gn([[cnt64]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
+ expect(2, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("send cntTrap",[]),
+ snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
+ {cnt64, 10},
+ {sysLocation, "here"}]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ {[sysLocation,0], "here"}]),
+ expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [1]},
+ {[sysContact,0], "pelle"},
+ {[cnt64,0], 10},
+ {[sysLocation,0], "here"}])),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ ?DBG("create row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
+ ?DBG("create row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
+
+ ?DBG("get-next (cntIndex)",[]),
+ gn([[cntIndex]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
+ expect(3, [{[cntCnt,Idx1], 0}])),
+ % Delete the rows
+ ?DBG("delete row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
+ ?DBG("delete row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
+ catch snmpa:verbosity(MA,log),
+ ?DBG("done",[]),
+ ok.
+
+%% Req. Test1
+opaque_test() ->
+ p("Testing Opaque datatype..."),
+ g([[opaqueObj,0]]),
+ ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
+
+%% Req. OLD-SNMPEA-MIB
+api_test(MaNode) ->
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [intAgentIpAddress]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
+ oid_to_name, [OID]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [[1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp,
+ int_to_enum, ['RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
+ ?line case snmp:date_and_time() of
+ List when list(List), length(List) == 8 -> ok;
+ List when list(List), length(List) == 11 -> ok
+ end.
+
+%% Req. Klas3
+api_test2() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]),
+ g([[fname4,0]]),
+ ?line expect(2, [{[fname4,0], 1}]).
+
+api_test3() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]).
+
+
+unreg_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[snmpInPkts, 0], any}]).
+
+load_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[fname,0], ""}]).
+
+%% Req. Klas1
+load_test_sa() ->
+ gn([[?v1_2(sysServices,sysORLastChange), 0]]),
+ ?line expect(1, [{[fname,0], any}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_get() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
+ [sysName,0]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,0], "test"}]),
+ g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
+ ?line ?v1_2(expect(2, noSuchName, [1,4], any),
+ expect(2, [{[1,3,7,1], noSuchObject},
+ {Key1c4, 2},
+ {[sysDescr,0], "Erlang SNMP agent"},
+ {[1,3,7,2], noSuchObject},
+ {Key1c3, 2},
+ {[sysDescr,0], "Erlang SNMP agent"}])).
+
+%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
+do_mul_get_err() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
+ ?line ?v1_2(expect(1, noSuchName, 5, any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,2], noSuchInstance}])),
+ g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname3,0], noSuchObject},
+ {Key1c3, 2},
+ {[sysName,1], noSuchInstance}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2}, {[fname,0], "test set"},
+ {Key1c3, 2}, {[sysName,0], "test"}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next_err() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[1,3,6,999], endOfMibView},
+ {[fname,0], "test set"},
+ {[1,3,90], endOfMibView},
+ {Key1c3, 2},
+ {[sysName,0], "test"}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set() ->
+ p("Adding one row in subagent table, and one in master table"),
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [sysLocation,0],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[sysLocation,0], "new_value"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ g([NewKeyc4]),
+ ?line expect(3, [{NewKeyc4, 2}]),
+ s([{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]),
+ ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ p("Adding one row in subagent table, and one in master table"),
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {NewKeyc3, 2},
+ {[sysUpTime,0], 45}, % sysUpTime (readOnly)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
+ g([[friendsEntry, [2, 3]]]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB
+sa_mib() ->
+ g([[sa, [2,0]]]),
+ ?line expect(1, [{[sa, [2,0]], 3}]),
+ s([{[sa, [1,0]], s, "sa_test"}]),
+ ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+
+ma_trap1(MA) ->
+ snmpa:send_trap(MA, testTrap2, "standard trap"),
+ ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ snmpa:send_trap(MA, testTrap1, "standard trap"),
+ ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]).
+
+ma_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap2(MA) ->
+ snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
+ {ifAdminStatus, [1], 1},
+ {ifOperStatus, [1], 2}]),
+ ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]).
+
+sa_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "pelle"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]).
+
+ma_v2_trap1(MA) ->
+ ?DBG("ma_v2_traps -> entry with MA = ~p => "
+ "send standard trap: testTrapv22",[MA]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
+ snmpa:send_trap(MA, testTrapv21, "standard trap"),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmp ++ [1]}]).
+
+ma_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"}]).
+
+%% Note: This test case takes a while... actually a couple of minutes.
+ma_v2_inform1(MA) ->
+ ?DBG("ma_v2_inform -> entry with MA = ~p => "
+ "send notification: testTrapv22",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag1, self()},
+ "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag1, [_]} ->
+ ok;
+ {snmp_targets, tag1, Addrs1} ->
+ ?line ?FAIL({bad_addrs, Addrs1})
+ after
+ 5000 ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag1, {got_response, _}} ->
+ ok;
+ {snmp_notification, tag1, {no_response, _}} ->
+ ?line ?FAIL(no_response)
+ after
+ 20000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+
+ %%
+ %% -- The rest is possibly erroneous...
+ %%
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag2, self()},
+ "standard inform", []),
+ ?line expect(2, {inform, false},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag2, [_]} ->
+ ok;
+ {snmp_targets, tag2, Addrs2} ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
+ ?line ?FAIL({bad_addrs, Addrs2})
+ after
+ 5000 ->
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag2, {got_response, _}} ->
+ ?line ?FAIL(got_response);
+ {snmp_notification, tag2, {no_response, _}} ->
+ ok
+ after
+ 240000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag2) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end.
+
+
+ma_v1_2_v2_trap(MA) ->
+ snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
+ {[ifIndex, 1], 1},
+ {[snmpTrapEnterprise, 0], [1,2,3]}]).
+
+
+ma_v1_2_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"},
+ {[snmpTrapEnterprise, 0], ?system}]).
+
+
+sa_v1_2_v2_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+sa_v1_2_v2_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+sa_v1_2_v2_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_bad_value() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 5}, % badValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, badValue, 2, any),
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_gen_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},{NewKeyc4, 2},
+ {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
+ ?line expect(1, genErr, 4, any),
+% The row might have been added; we don't know.
+% (as a matter of fact we do - it is added, because the agent
+% first sets its own vars, and then th SAs. Lets destroy it.
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(2, [{NewKeyc5, ?destroy}]).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_too_big() ->
+ g([[sa, [4,0]]]),
+ ?line expect(1, tooBig).
+
+%% Req. Klas1, system group, snmp group (v1/v2)
+next_across_sa() ->
+ gn([[sysDescr],[klas1,5]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[snmpInPkts, 0], any}]).
+
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
+%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
+%% Req. Klas3, Klas4
+undo_test() ->
+ s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
+ s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
+ ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
+% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+% it depends on which order the agent traverses the varbind list.
+% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
+% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
+ ?line expect(6, genErr, 2, any).
+
+%% Req. Klas3, Klas4
+bad_return() ->
+ g([[fStatus4,4],
+ [fName4,4]]),
+ ?line expect(4, genErr, 2, any),
+ g([[fStatus4,5],
+ [fName4,5]]),
+ ?line expect(5, genErr, 1, any),
+ g([[fStatus4,6],
+ [fName4,6]]),
+ ?line expect(6, genErr, 2, any),
+ gn([[fStatus4,7],
+ [fName4,7]]),
+ ?line expect(7, genErr, 2, any),
+ gn([[fStatus4,8],
+ [fName4,8]]),
+ ?line expect(8, genErr, 1, any),
+ gn([[fStatus4,9],
+ [fName4,9]]),
+ ?line expect(9, genErr, 2, any).
+
+
+%%%-----------------------------------------------------------------
+%%% Test the implementation of standard mibs.
+%%% We should *at least* try to GET all variables, just to make
+%%% sure the instrumentation functions work.
+%%% Note that many of the functions in the standard mib is
+%%% already tested by the normal tests.
+%%%-----------------------------------------------------------------
+
+
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v1.
+%% o Test the counters and control objects in SNMP-STANDARD-MIB
+%%-----------------------------------------------------------------
+snmp_standard_mib(suite) -> [];
+snmp_standard_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?DBG("snmp_standard_mib -> std_mib_init", []),
+ try_test(std_mib_init),
+
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v2),
+ ?DBG("snmp_standard_mib -> std_mib_read", []),
+ try_test(std_mib_read),
+ put(vsn, v1),
+
+ ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+ ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+ ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
+ try_test(std_mib_write, [], [{community, "public"}]),
+ ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
+ try_test(std_mib_asn_err),
+ ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
+ try_test(std_mib_c, [Bad]),
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ try_test(standard_mib_a),
+
+ ?DBG("snmp_standard_mib -> std_mib_finish", []),
+ try_test(std_mib_finish),
+ ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
+ try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_a() ->
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ ?line OutPkts2 = OutPkts + 1,
+ %% There are some more counters we could test here, but it's not that
+ %% important, since they are removed from SNMPv2-MIB.
+ ok.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_init() ->
+ %% disable authentication failure traps. (otherwise w'd get many of
+ %% them - this is also a test to see that it works).
+ s([{[snmpEnableAuthenTraps,0], 2}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_finish() ->
+ %% enable again
+ s([{[snmpEnableAuthenTraps,0], 1}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_test_finish() ->
+ %% force a authenticationFailure
+ std_mib_write(),
+ %% check that we got a trap
+ ?line expect(2, trap, [1,2,3], 4, 0, []).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_read() ->
+ ?DBG("std_mib_read -> entry", []),
+ g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
+ ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
+ ?line expect(1, timeout). % make sure we don't get a trap!
+
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_write() ->
+ ?DBG("std_mib_write -> entry", []),
+ s([{[sysLocation, 0], "new_value"}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_asn_err() ->
+ snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v2 and v3.
+%% o Test the counters and control objects in SNMPv2-MIB
+%%-----------------------------------------------------------------
+snmpv2_mib_2(suite) -> [];
+snmpv2_mib_2(Config) when list(Config) ->
+ ?LOG("snmpv2_mib_2 -> start",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?DBG("snmpv2_mib_2 -> standard mib init",[]),
+ try_test(std_mib_init),
+
+ ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
+ InBadVsns = try_test(std_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
+ put(vsn, v1),
+ try_test(std_mib_read),
+
+ ?DBG("snmpv2_mib_2 -> bad version read",[]),
+ put(vsn, v2),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+
+ ?DBG("snmpv2_mib_2 -> read with bad community",[]),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+
+ ?DBG("snmpv2_mib_2 -> write with public community",[]),
+ try_test(std_mib_write, [], [{community, "public"}]),
+
+ ?DBG("snmpv2_mib_2 -> asn err",[]),
+ try_test(std_mib_asn_err),
+
+ ?DBG("snmpv2_mib_2 -> check counters",[]),
+ try_test(std_mib_c, [Bad]),
+
+ ?DBG("snmpv2_mib_2 -> get som counters",[]),
+ try_test(snmpv2_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
+ try_test(std_mib_finish),
+
+ ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
+ "then disable auth traps",[]),
+ try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
+
+ ?LOG("snmpv2_mib_2 -> done",[]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_3(suite) -> [];
+snmpv2_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v1),
+ try_test(std_mib_read),
+ put(vsn, v3),
+ _Bad = try_test(std_mib_b, [InBadVsns]),
+ try_test(snmpv2_mib_a),
+
+ try_test(std_mib_finish).
+
+-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_test_finish() ->
+ %% force a authenticationFailure
+ ?DBG("ma_v2_inform -> write to std mib",[]),
+ std_mib_write(),
+
+ %% check that we got a trap
+ ?DBG("ma_v2_inform -> await trap",[]),
+ ?line expect(2, v2trap, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0], ?authenticationFailure}]),
+
+ %% and the the inform
+ ?DBG("ma_v2_inform -> await inform",[]),
+ ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0],?authenticationFailure}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_a() ->
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+
+ ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ InBadVsns.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_b(InBadVsns) ->
+ ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ ?line InBadVsns2 = InBadVsns + 1,
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+ ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
+ get_req(4, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
+ ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ get_req(1, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ ?line InBadCommunityNames2 = InBadCommunityNames + 1,
+ ?line InBadCommunityUses2 = InBadCommunityUses + 1,
+ ?line InASNErrs2 = InASNErrs + 1.
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_a() ->
+ ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
+ s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
+ ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
+ {[sysLocation, 0], "val2"}]),
+ s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
+ ?line expect(4, inconsistentValue, 2,
+ [{[sysLocation, 0], "val3"},
+ {[snmpSetSerialNo,0], SetSerial}]),
+ ?line ["val2"] = get_req(5, [[sysLocation,0]]).
+
+
+%%-----------------------------------------------------------------
+%% o Bad community uses/name is tested already
+%% in SNMPv2-MIB and STANDARD-MIB.
+%% o Test add/deletion of rows.
+%%-----------------------------------------------------------------
+snmp_community_mib(suite) -> [];
+snmp_community_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ try_test(snmp_community_mib),
+ ?line unload_master("SNMP-COMMUNITY-MIB").
+
+snmp_community_mib_2(X) -> snmp_community_mib(X).
+
+%% Req. SNMP-COMMUNITY-MIB
+snmp_community_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o Test engine boots / time
+%%-----------------------------------------------------------------
+snmp_framework_mib(suite) -> [];
+snmp_framework_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ try_test(snmp_framework_mib),
+ ?line unload_master("SNMP-FRAMEWORK-MIB").
+
+snmp_framework_mib_2(X) -> snmp_framework_mib(X).
+
+snmp_framework_mib_3(suite) -> [];
+snmp_framework_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(snmp_framework_mib).
+
+
+%% Req. SNMP-FRAMEWORK-MIB
+snmp_framework_mib() ->
+ ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ sleep(5000),
+ ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ if
+ EngineTime+7 < EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ EngineTime+4 > EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ true -> ok
+ end,
+ ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ [Boots] when integer(Boots) -> ok;
+ Else -> ?FAIL(Else)
+ end,
+ ok.
+
+%%-----------------------------------------------------------------
+%% o Test the counters
+%%-----------------------------------------------------------------
+snmp_mpd_mib_3(suite) -> [];
+snmp_mpd_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ UnknownPDUHs = try_test(snmp_mpd_mib_a),
+ try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
+ try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
+
+
+%% Req. SNMP-MPD-MIB
+snmp_mpd_mib_a() ->
+ ?line [UnknownSecs, InvalidMsgs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0]]),
+ Pdu = #pdu{type = 'get-request',
+ request_id = 23,
+ error_status = noError,
+ error_index = 0,
+ varbinds = []},
+ SPdu = #scopedPdu{contextEngineID = "agentEngine",
+ contextName = "",
+ data = Pdu},
+ ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
+ V3Hdr1 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [7],
+ msgSecurityModel = 23, % bad sec model
+ msgSecurityParameters = []},
+ V3Hdr2 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [6], % bad flag combination
+ msgSecurityModel = 3,
+ msgSecurityParameters = []},
+ Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
+ data = SPDUBytes},
+ Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
+ data = SPDUBytes},
+ ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
+ ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
+ snmp_test_mgr:send_bytes(MsgBytes1),
+ snmp_test_mgr:send_bytes(MsgBytes2),
+
+ ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0],
+ [snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownSecs2 = UnknownSecs + 1,
+ ?line InvalidMsgs2 = InvalidMsgs + 1,
+ UnknownPDUHs.
+
+-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
+snmp_mpd_mib_b() ->
+ g([[sysUpTime,0]]),
+ ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
+
+
+snmp_mpd_mib_c(UnknownPDUHs) ->
+ ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownPDUHs2 = UnknownPDUHs + 1.
+
+
+snmp_target_mib(suite) -> [];
+snmp_target_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ try_test(snmp_target_mib),
+ ?line unload_master("SNMP-TARGET-MIB").
+
+snmp_target_mib_2(X) -> snmp_target_mib(X).
+
+snmp_target_mib_3(X) -> snmp_target_mib(X).
+
+snmp_target_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+snmp_notification_mib(suite) -> [];
+snmp_notification_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ try_test(snmp_notification_mib),
+ ?line unload_master("SNMP-NOTIFICATION-MIB").
+
+snmp_notification_mib_2(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib_3(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o add/delete views and try them
+%% o try boundaries
+%%-----------------------------------------------------------------
+snmp_view_based_acm_mib(suite) -> [];
+snmp_view_based_acm_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master("Test2"),
+ snmp_view_based_acm_mib(),
+ ?line unload_master("Test2"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib() ->
+ snmpa:verbosity(net_if,trace),
+ snmpa:verbosity(master_agent,trace),
+ ?LOG("start snmp_view_based_acm_mib test",[]),
+ %% The user "no-rights" is present in USM, and is mapped to security
+ %% name 'no-rights", which is not present in VACM.
+ %% So, we'll add rights for it, try them and delete them.
+ %% We'll give "no-rights" write access to tDescr.0 and read access
+ %% to tDescr2.0
+ %% These are the options we'll use to the mgr
+ Opts = [{user, "no-rights"}, {community, "no-rights"}],
+ %% Find the valid secmodel, and one invalid secmodel.
+ {SecMod, InvSecMod} =
+ case get(vsn) of
+ v1 -> {?SEC_V1, ?SEC_V2C};
+ v2 -> {?SEC_V2C, ?SEC_USM};
+ v3 -> {?SEC_USM, ?SEC_V1}
+ end,
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Now, add a mapping from "no-rights" -> "no-rights-group"
+ GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
+ GRow1 =
+ [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
+ {GRow1Status, ?createAndGo}],
+ ?DBG("set '~p'",[GRow1]),
+ ?line try_test(do_set, [GRow1]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create a mapping for another sec model, and make sure it dosn't
+ %% give us access
+ GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
+ GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
+ {GRow2Status, ?createAndGo}],
+
+ ?DBG("set '~p'",[GRow2]),
+ ?line try_test(do_set, [GRow2]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [GRow2Status]),
+
+ RVName = "rv_name",
+ WVName = "wv_name",
+
+ %% Access row
+ ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
+ ARow1Status = [vacmAccessStatus, ARow1Idx],
+ ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
+ {[vacmAccessReadViewName, ARow1Idx], RVName},
+ {[vacmAccessWriteViewName, ARow1Idx], WVName},
+ {ARow1Status, ?createAndGo}],
+
+ %% This access row would give acces, if InvSecMod was valid.
+ ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
+ ARow2Status = [vacmAccessStatus, ARow2Idx],
+ ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
+ {[vacmAccessReadViewName, ARow2Idx], "internet"},
+ {[vacmAccessWriteViewName, ARow2Idx], "internet"},
+ {ARow2Status, ?createAndGo}],
+
+ ?line try_test(do_set, [ARow2]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [ARow2Status]),
+
+
+ %% Add valid row
+ ?line try_test(do_set, [ARow1]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create the view family
+ VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
+ VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
+ VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
+ VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
+ VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
+ VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
+ VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
+ VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
+
+ ?line try_test(add_row, [VRow1Status]),
+ ?line try_test(add_row, [VRow2Status]),
+ ?line try_test(add_row, [VRow3Status]),
+
+ %% We're supposed to have access now...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Change Row3 to Row4
+ ?line try_test(del_row, [VRow3Status]),
+ ?line try_test(add_row, [VRow4Status]),
+
+ %% We should still have access...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Delete rows
+ ?line try_test(del_row, [GRow1Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete rest of rows
+ ?line try_test(del_row, [ARow1Status]),
+ ?line try_test(del_row, [VRow1Status]),
+ ?line try_test(del_row, [VRow2Status]),
+ ?line try_test(del_row, [VRow4Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+ snmpa:verbosity(master_agent,log).
+
+do_set(Row) ->
+ s(Row),
+ expect(1, Row).
+
+add_row(RowStatus) ->
+ s([{RowStatus, ?createAndGo}]),
+ expect(1, [{RowStatus, ?createAndGo}]).
+
+del_row(RowStatus) ->
+ s([{RowStatus, ?destroy}]),
+ expect(1, [{RowStatus, ?destroy}]).
+
+
+
+use_no_rights() ->
+ g([[xDescr,0]]),
+ ?v1_2_3(expect(11, noSuchName, 1, any),
+ expect(12, [{[xDescr,0], noSuchObject}]),
+ expect(13, authorizationError, 1, any)),
+ g([[xDescr2,0]]),
+ ?v1_2_3(expect(21, noSuchName, 1, any),
+ expect(22, [{[xDescr2,0], noSuchObject}]),
+ expect(23, authorizationError, 1, any)),
+ gn([[xDescr]]),
+ ?v1_2_3(expect(31, noSuchName, 1, any),
+ expect(32, [{[xDescr], endOfMibView}]),
+ expect(33, authorizationError, 1, any)),
+ s([{[xDescr,0], "tryit"}]),
+ ?v1_2_3(expect(41, noSuchName, 1, any),
+ expect(42, noAccess, 1, any),
+ expect(43, authorizationError, 1, any)).
+
+
+use_rights() ->
+ g([[xDescr,0]]),
+ expect(1, [{[xDescr,0], any}]),
+ g([[xDescr2,0]]),
+ expect(2, [{[xDescr2,0], any}]),
+ s([{[xDescr,0], "tryit"}]),
+ expect(3, noError, 0, any),
+ g([[xDescr,0]]),
+ expect(4, [{[xDescr,0], "tryit"}]).
+
+mk_ln(X) ->
+ [length(X) | X].
+
+%%-----------------------------------------------------------------
+%% o add/delete users and try them
+%% o test all secLevels
+%% o test all combinations of protocols
+%% o try bad ops; check counters
+%%-----------------------------------------------------------------
+snmp_user_based_sm_mib_3(suite) -> [];
+snmp_user_based_sm_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ _AgentDir = ?config(agent_dir, Config),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+
+ %% The newUser used here already has VACM access.
+
+ %% Add a new user in the simplest way; just createAndGo
+ try_test(v3_sync, [[{usm_add_user1, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new user
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
+ DesKey1 = lists:sublist(ShaKey1, 16),
+
+ %% Change the new user's keys - 1
+ try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ MgrDir = ?config(mgr_dir, Config),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
+ DesKey2 = lists:sublist(ShaKey2, 16),
+
+ %% Change the new user's keys - 2
+ ?line try_test(v3_sync,
+ [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ reset_usm_mgr(MgrDir),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
+ ?line load_master("Test2"),
+ ?line try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Change the new user's keys - 3
+ ?line try_test(v3_sync,
+ [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new keys
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Try some read requests
+ ?line try_test(v3_sync, [[{usm_read, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Delete the new user
+ ?line try_test(v3_sync, [[{usm_del_user, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try some bad requests
+ ?line try_test(v3_sync, [[{usm_bad, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("SNMP-USER-BASED-SM-MIB").
+
+-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
+
+usm_add_user1() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+usm_use_user() ->
+ v2_proc().
+
+
+%% Change own public keys
+usm_key_change1(ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_shaxxxxxxxxxx",
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_desxxxxxx",
+ DesKey),
+ Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change own private keys
+usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change other's public keys
+usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
+ s(Vbs1),
+ ?line expect(1, noAccess, 1, any),
+ Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs2),
+ ?line expect(2, noAccess, 1, any),
+
+
+ Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs3),
+ ?line expect(1, Vbs3).
+
+usm_read() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ?line g([[usmUserSecurityName, NewRowIndex],
+ [usmUserCloneFrom, NewRowIndex],
+ [usmUserAuthKeyChange, NewRowIndex],
+ [usmUserOwnAuthKeyChange, NewRowIndex],
+ [usmUserPrivKeyChange, NewRowIndex],
+ [usmUserOwnPrivKeyChange, NewRowIndex]]),
+ ?line expect(1,
+ [{[usmUserSecurityName, NewRowIndex], "newUser"},
+ {[usmUserCloneFrom, NewRowIndex], [0,0]},
+ {[usmUserAuthKeyChange, NewRowIndex], ""},
+ {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
+ {[usmUserPrivKeyChange, NewRowIndex], ""},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
+ ok.
+
+
+
+usm_del_user() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
+
+-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
+
+-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
+
+-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
+
+-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
+
+-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
+
+usm_bad() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, inconsistentName, 1, any),
+
+ RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs2),
+ ?line expect(2, wrongValue, 1, any),
+
+ RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs3),
+ ?line expect(3, Vbs3),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
+ ?line expect(4, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
+ ?line expect(5, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
+ ?line expect(6, wrongValue, 1, any),
+ ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
+ ?line expect(7, wrongValue, 1, any),
+
+ Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs4),
+ ?line expect(1, Vbs4),
+
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Loop through entire MIB, to make sure that all instrum. funcs
+%% works.
+%% Load all std mibs that are not loaded by default.
+%%-----------------------------------------------------------------
+loop_mib(suite) -> [];
+loop_mib(Config) when list(Config) ->
+ ?LOG("loop_mib -> initiate case",[]),
+ %% snmpa:verbosity(master_agent,debug),
+ %% snmpa:verbosity(mib_server,info),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?DBG("loop_mib -> try",[]),
+ try_test(loop_mib_1),
+ ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ %% snmpa:verbosity(master_agent,log),
+ %% snmpa:verbosity(mib_server,silence),
+ ?LOG("loop_mib -> done",[]).
+
+
+loop_mib_2(suite) -> [];
+loop_mib_2(Config) when list(Config) ->
+ ?LOG("loop_mib_2 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_2 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_2 -> load mibs",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_2 -> unload mibs",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?LOG("loop_mib_2 -> done",[]).
+
+
+loop_mib_3(suite) -> [];
+loop_mib_3(Config) when list(Config) ->
+ ?LOG("loop_mib_3 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_3 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_3 -> load mibs",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_3 -> unload mibs",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?LOG("loop_mib_3 -> done",[]).
+
+
+%% Req. As many mibs all possible
+loop_mib_1() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_1([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_1(Oid, N) ->
+ ?DBG("loop_it_1 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_1 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_1 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_1(NOid, N+1);
+ #pdu{type='get-response', error_status=noSuchName, error_index=1,
+ varbinds=[_]} ->
+ ?DBG("loop_it_1 -> done",[]),
+ N;
+
+ #pdu{type = Type, error_status = Err, error_index = Idx,
+ varbinds = Vbs} ->
+ exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
+ end.
+
+%% Req. As many mibs all possible
+loop_mib_2() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_2([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_2(Oid, N) ->
+ ?DBG("loop_it_2 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p",[NOid]),
+ N;
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_2 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_2(NOid, N+1)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+
+
+
+
+%% These are (ticket) test cases where the initiation has to be done
+%% individually.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1128
+%% Slogan: Bug in handling of createAndWait set-requests.
+%%-----------------------------------------------------------------
+otp_1128(suite) -> [];
+otp_1128(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1128),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1128_2(X) -> otp_1128(X).
+
+otp_1128_3(X) -> otp_1128(X).
+
+otp_1128() ->
+ io:format("Testing bug reported in ticket OTP-1128...~n"),
+
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+
+ s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(29, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(31, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(32, [{NewKeyc5, ?destroy}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1129, OTP-1169
+%% Slogan: snmpa:int_to_enum crashes on bad oids
+%%-----------------------------------------------------------------
+otp_1129(suite) -> [];
+otp_1129(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ try_test(otp_1129_i, [node()]),
+ ?line unload_master("Klas3").
+
+otp_1129_2(X) -> otp_1129(X).
+
+otp_1129_3(X) -> otp_1129(X).
+
+otp_1129_i(MaNode) ->
+ io:format("Testing bug reported in ticket OTP-1129...~n"),
+ false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
+ false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1131
+%% Slogan: Agent crashes / erlang node halts if RowIndex in a
+%% setrequest is of bad type, e.g. an INDEX {INTEGER},
+%% and RowIdenx [3,2].
+%%-----------------------------------------------------------------
+otp_1131(suite) -> [];
+otp_1131(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas1"),
+ try_test(otp_1131),
+ ?line unload_master("Klas1").
+
+otp_1131_2(X) -> otp_1131(X).
+
+otp_1131_3(X) -> otp_1131(X).
+
+otp_1131() ->
+ io:format("Testing bug reported in ticket OTP-1131...~n"),
+ s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
+ {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1162
+%% Slogan: snmp_agent can't handle wrongValue from instrum.func
+%%-----------------------------------------------------------------
+otp_1162(suite) -> [];
+otp_1162(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ try_test(otp_1162),
+ stop_subagent(SA).
+
+otp_1162_2(X) -> otp_1162(X).
+
+otp_1162_3(X) -> otp_1162(X).
+
+otp_1162() ->
+ s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
+ ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1222
+%% Slogan: snmp agent crash if faulty index is returned from instrum
+%%-----------------------------------------------------------------
+otp_1222(suite) -> [];
+otp_1222(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ ?line load_master("Klas4"),
+ try_test(otp_1222),
+ ?line unload_master("Klas3"),
+ ?line unload_master("Klas4").
+
+otp_1222_2(X) -> otp_1222(X).
+
+otp_1222_3(X) -> otp_1222(X).
+
+otp_1222() ->
+ io:format("Testing bug reported in ticket OTP-1222...~n"),
+ s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
+ ?line expect(1, genErr, 0, any),
+ s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
+ ?line expect(2, genErr, 0, any).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1298
+%% Slogan: Negative INTEGER values are treated as positive.
+%%-----------------------------------------------------------------
+otp_1298(suite) -> [];
+otp_1298(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1298),
+ ?line unload_master("Klas2").
+
+otp_1298_2(X) -> otp_1298(X).
+
+otp_1298_3(X) -> otp_1298(X).
+
+otp_1298() ->
+ io:format("Testing bug reported in ticket OTP-1298...~n"),
+ s([{[fint,0], -1}]),
+ ?line expect(1298, [{[fint,0], -1}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1331
+%% Slogan: snmp_generic should return noError when deleting non-ex row
+%%-----------------------------------------------------------------
+otp_1331(suite) -> [];
+otp_1331(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1331),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1331_2(X) -> otp_1331(X).
+
+otp_1331_3(X) -> otp_1331(X).
+
+otp_1331() ->
+ NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(1, [{NewKeyc5, ?destroy}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1338
+%% Slogan: snmp bug in initialisation of default values for mnesia tabs
+%%-----------------------------------------------------------------
+otp_1338(suite) -> [];
+otp_1338(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1338),
+ ?line unload_master("Klas2").
+
+otp_1338_2(X) -> otp_1338(X).
+
+otp_1338_3(X) -> otp_1338(X).
+
+otp_1338() ->
+ s([{[kStatus2, 7], i, ?createAndGo}]),
+ ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
+ g([[kName2, 7]]),
+ ?line expect(2, [{[kName2, 7], "JJJ"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1342
+%% Slogan: default impl of snmp table can't handle bad index access,
+%% Set when INDEX is read-write gets into an infinite loop!
+%%-----------------------------------------------------------------
+otp_1342(suite) -> [];
+otp_1342(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas4"),
+ try_test(otp_1342),
+ ?line unload_master("Klas4").
+
+otp_1342_2(X) -> otp_1342(X).
+
+otp_1342_3(X) -> otp_1342(X).
+
+otp_1342() ->
+ s([{[fIndex5, 1], i, 1},
+ {[fName5, 1], i, 3},
+ {[fStatus5, 1], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1366
+%% Slogan: snmp traps not sent to all managers
+%% Note: NYI! We need a way to tell the test server that we need
+%% mgrs on two different machines.
+%%-----------------------------------------------------------------
+otp_1366(suite) -> [];
+otp_1366(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1366),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1366_2(X) -> otp_1366(X).
+
+otp_1366_3(X) -> otp_1366(X).
+
+otp_1366() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ 'NYI'.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2776
+%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
+%%-----------------------------------------------------------------
+otp_2776(suite) -> [];
+otp_2776(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_2776).
+
+otp_2776_2(X) -> otp_2776(X).
+
+otp_2776_3(X) -> otp_2776(X).
+
+otp_2776() ->
+ io:format("Testing bug reported in ticket OTP-2776...~n"),
+
+ Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
+ Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
+ Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
+ Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
+ Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
+ Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
+ Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
+ Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
+ Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
+ Dt10_invalid = [],
+ Dt11_invalid = [kalle,hobbe],
+ L = [{ 1, true, Dt01_valid},
+ { 2, true, Dt02_valid},
+ { 3, true, Dt03_valid},
+ { 4, false, Dt04_invalid},
+ { 5, true, Dt05_valid},
+ { 6, true, Dt06_valid},
+ { 7, false, Dt07_invalid},
+ { 8, true, Dt08_valid},
+ { 9, false, Dt09_invalid},
+ {10, false, Dt10_invalid},
+ {11, false, Dt11_invalid}],
+
+ ?line ok = validate_dat(L).
+
+
+validate_dat(L) -> validate_dat(L,[]).
+
+validate_dat([],V) ->
+ Fun = fun({_,X}) -> case X of
+ ok -> false;
+ _ -> true
+ end
+ end,
+ validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
+validate_dat([{Id,E,Dat}|T],V) ->
+ validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
+
+validate_dat1([]) -> ok;
+validate_dat1(L) -> {error,L}.
+
+validate_dat2(Id, E, Dat) ->
+ Res = case {E,snmp:validate_date_and_time(Dat)} of
+ {E,E} -> ok;
+ {E,A} -> {E,A}
+ end,
+ {Id, Res}.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2979
+%% Slogan: get-next on more than 1 column in an empty table
+%% returns bad response.
+%%-----------------------------------------------------------------
+otp_2979(suite) -> [];
+otp_2979(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Test1"),
+ ?line init_old(),
+ try_test(otp_2979),
+ ?line unload_master("Test1").
+
+otp_2979_2(X) -> otp_2979(X).
+
+otp_2979_3(X) -> otp_2979(X).
+
+otp_2979() ->
+ gn([[sparseDescr], [sparseStatus]]),
+ ?line expect(1, [{[sparseStr,0], "slut"},
+ {[sparseStr,0], "slut"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3187
+%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% endOfTable - should return value.
+%%-----------------------------------------------------------------
+otp_3187(suite) -> [];
+otp_3187(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ otp_3187(),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+otp_3187_2(X) -> otp_3187(X).
+
+otp_3187_3(X) -> otp_3187(X).
+
+otp_3187() ->
+ ?line Elements =
+ snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
+ lists:foreach(fun(E) ->
+ ?line if E == endOfTable ->
+ ?FAIL(endOfTable);
+ true -> ok
+ end
+ end, Elements).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3542
+%% Slogan:
+%%-----------------------------------------------------------------
+otp_3542(suite) -> [];
+otp_3542(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_3542).
+
+otp_3542() ->
+ io:format("SNMP v3 discovery...~n"),
+ ?line Res = snmp_test_mgr:d(),
+ io:format("SNMP v3 discovery result: ~p~n",[Res]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3725
+%% Slogan: Slow response time on snmpa:int_to_enum
+%%-----------------------------------------------------------------
+otp_3725(suite) -> [];
+otp_3725(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_3725_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+otp_3725_test(MaNode) ->
+ io:format("Testing feature requested in ticket OTP-3725...~n"),
+ ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
+ ?DBG("otp_3725_test -> Db = ~p",[Db]),
+
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [Db, intAgentIpAddress]),
+ ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
+ [Db,OID]),
+ ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [Db, [1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, 'RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-4394
+%% Slogan: Target mib tag list check invalid
+%%-----------------------------------------------------------------
+
+
+
+init_otp_4394(Config) when list(Config) ->
+ ?DBG("init_otp_4394 -> entry with"
+ "~n Config: ~p", [Config]),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ MasterAgentVerbosity = {master_agent_verbosity, trace},
+ NetIfVerbosity = {net_if_verbosity, trace},
+ Opts = [MasterAgentVerbosity,NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config,Opts)].
+
+otp_4394_config(AgentDir, MgrDir, Ip0) ->
+ ?DBG("otp_4394_config -> entry with"
+ "~n AgentDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ Vsn = [v1],
+ Ip = tuple_to_list(Ip0),
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?TRAP_UDP, Ip, 4000,
+ "OTP-4394 test"),
+ ?line case update_usm(Vsn, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsn, MgrDir);
+ false ->
+ ?line ok
+ end,
+ C1 = {"a", "all-rights", "initial", "", "pc"},
+ C2 = {"c", "secret", "secret_name", "", "secret_tag"},
+ ?line write_community_conf(AgentDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentDir),
+ Ta1 = {"shelob v1",
+ [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ "pc1",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [],
+ 2048},
+ Ta2 = {"bifur v1",
+ [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ "pc2",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [], 2048},
+ ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentDir, Vsn),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+
+
+finish_otp_4394(Config) when list(Config) ->
+ ?DBG("finish_otp_4394 -> entry", []),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ erase(mgr_node),
+ lists:keydelete(vsn, 1, C1).
+
+otp_4394_test(suite) -> [];
+otp_4394_test(Config) ->
+ ?DBG("otp_4394_test -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_4394_test1),
+ ?DBG("otp_4394_test -> done", []),
+ ok.
+
+otp_4394_test1() ->
+ ?DBG("otp_4394_test1 -> entry", []),
+ gn([[1,1]]),
+ Res =
+ case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
+ %% {error, 1, {"?",[]}, {"~w",[timeout]}}
+ {error, 1, _, {_, [timeout]}} ->
+ ?DBG("otp_4394_test1 -> expected result: timeout", []),
+ ok;
+ Else ->
+ Else
+ end,
+ ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
+ Res.
+
+
+%%%--------------------------------------------------
+%%% Used to test the standard mib with our
+%%% configuration.
+%%%--------------------------------------------------
+run(F, A, Opts) ->
+ M = get(mib_dir),
+ Dir = get(mgr_dir),
+ User = snmp_misc:get_option(user, Opts, "all-rights"),
+ SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
+ EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
+ CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
+ Community = snmp_misc:get_option(community, Opts, "all-rights"),
+ ?DBG("run -> start crypto app",[]),
+ Crypto = case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ ?CRYPTO_START()
+ end,
+ ?DBG("run -> Crypto: ~p",[Crypto]),
+ catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ ?DBG("run -> config:~n"
+ "\tM: ~p~n"
+ "\tDir: ~p~n"
+ "\tUser: ~p~n"
+ "\tSecLevel: ~p~n"
+ "\tEngineID: ~p~n"
+ "\tCtxEngineID: ~p~n"
+ "\tCommunity: ~p~n"
+ "\tStdM: ~p",
+ [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
+ case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
+ {packet_server_debug,true},
+ {debug,true},
+ {agent, get(master_host)},
+ {agent_udp, 4000},
+ {trap_udp, 5000},
+ {recbuf,65535},
+ quiet,
+ get(vsn),
+ {community, Community},
+ {user, User},
+ {sec_level, SecLevel},
+ {engine_id, EngineID},
+ {context_engine_id, CtxEngineID},
+ {dir, Dir},
+ {mibs, mibs(StdM, M)}]) of
+ {ok, _Pid} ->
+ Res = apply(?MODULE, F, A),
+ catch snmp_test_mgr:stop(),
+ Res;
+ Err ->
+ io:format("Error starting manager: ~p\n", [Err]),
+ catch snmp_test_mgr:stop(),
+ ?line exit({mgr_start, Err})
+ end.
+
+
+mibs(StdMibDir,MibDir) ->
+ [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
+ join(MibDir, "OLD-SNMPEA-MIB.bin"),
+ join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
+ join(StdMibDir, "SNMP-MPD-MIB"),
+ join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
+ join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
+ join(StdMibDir, "SNMP-TARGET-MIB"),
+ join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
+ join(MibDir, "Klas1.bin"),
+ join(MibDir, "Klas2.bin"),
+ join(MibDir, "Klas3.bin"),
+ join(MibDir, "Klas4.bin"),
+ join(MibDir, "SA-MIB.bin"),
+ join(MibDir, "TestTrap.bin"),
+ join(MibDir, "Test1.bin"),
+ join(MibDir, "Test2.bin"),
+ join(MibDir, "TestTrapv2.bin")].
+
+join(D,F) ->
+ filename:join(D,F).
+
+%% string used in index
+is(S) -> [length(S) | S].
+
+try_test(Func) ->
+ call(get(mgr_node), ?MODULE, run, [Func, [], []]).
+
+try_test(Func, A) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, []]).
+
+try_test(Func, A, Opts) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
+
+call(N,M,F,A) ->
+ ?DBG("call -> entry with~n"
+ " N: ~p~n"
+ " M: ~p~n"
+ " F: ~p~n"
+ " A: ~p~n"
+ " when~n"
+ " get(): ~p",
+ [N,M,F,A,get()]),
+ spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
+ receive
+ {done, {'EXIT', Rn}, Loc} ->
+ ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
+ put(test_server_loc, Loc),
+ exit(Rn);
+ {done, Ret, Zed} ->
+ ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
+ Ret
+ end.
+
+wait(From, Env, M, F, A) ->
+ ?DBG("wait -> entry with ~n"
+ "\tFrom: ~p~n"
+ "\tEnv: ~p",[From,Env]),
+ lists:foreach(fun({K,V}) -> put(K,V) end, Env),
+ Rn = (catch apply(M, F, A)),
+ ?DBG("wait -> Rn: ~n~p", [Rn]),
+ From ! {done, Rn, get(test_server_loc)},
+ exit(Rn).
+
+expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
+expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
+expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
+expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
+
+get_req(Id, Vars) ->
+ ?DBG("get_req -> entry with~n"
+ "\tId: ~p~n"
+ "\tVars: ~p",[Id,Vars]),
+ g(Vars),
+ ?DBG("get_req -> await response",[]),
+ {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
+ ?DBG("get_req -> response: ~p",[Val]),
+ Val.
+
+get_next_req(Vars) ->
+ ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
+ gn(Vars),
+ ?DBG("get_next_req -> await response",[]),
+ Response = snmp_test_mgr:receive_response(),
+ ?DBG("get_next_req -> response: ~p",[Response]),
+ Response.
+
+
+
+start_node(Name) ->
+ ?LOG("start_node -> entry with Name: ~p",[Name]),
+ M = list_to_atom(?HOSTNAME(node())),
+ ?DBG("start_node -> M: ~p",[M]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ ?DBG("start_node -> Pa: ~p",[Pa]),
+
+ Args = case init:get_argument('CC_TEST') of
+ {ok, [[]]} ->
+ " -pa /clearcase/otp/libraries/snmp/ebin ";
+ {ok, [[Path]]} ->
+ " -pa " ++ Path;
+ error ->
+ ""
+ end,
+ %% Do not use start_link!!! (the proc that calls this one is tmp)
+ ?DBG("start_node -> Args: ~p~n",[Args]),
+ A = Args ++ " -pa " ++ Pa,
+ case (catch ?START_NODE(Name, A)) of
+ {ok, Node} ->
+ %% Tell the test_server to not clean up things it never started.
+ ?DBG("start_node -> Node: ~p",[Node]),
+ {ok, Node};
+ Else ->
+ ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
+ ?line ?FAIL(Else)
+ end.
+
+
+stop_node(Node) ->
+ ?LOG("stop_node -> Node: ~p",[Node]),
+ rpc:cast(Node, erlang, halt, []).
+
+p(X) ->
+ io:format(user, X++"\n", []).
+
+sleep(X) ->
+ receive
+ after
+ X -> ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Configuration
+%%%-----------------------------------------------------------------
+config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
+ ?TRAP_UDP, AIp, 4000,
+ "test"),
+ ?line case update_usm(Vsns, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsns, MgrDir);
+ false ->
+ ?line ok
+ end,
+ ?line update_community(Vsns, AgentDir),
+ ?line update_vacm(Vsns, AgentDir),
+ ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentDir, Vsns),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+delete_files(Config) ->
+ Dir = ?config(agent_dir, Config),
+ {ok, List} = file:list_dir(Dir),
+ lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
+ List).
+
+update_usm(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+update_usm_mgr(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.conf"),
+ filename:join(Dir,"usm.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ file:close(Fid).
+
+reset_usm_mgr(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.old"),
+ filename:join(Dir,"usm.conf")).
+
+
+update_community([v3], _Dir) -> ok;
+update_community(_, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
+ []),
+ file:close(Fid).
+
+
+-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
+update_vacm(_Vsn, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
+ ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
+ "~w, excluded, null}.\n", [?tDescr_instance]),
+ file:close(Fid).
+
+
+vacm_ver(v1) -> v1;
+vacm_ver(v2) -> v2c;
+vacm_ver(v3) -> usm.
+
+
+write_community_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
+ ok = write_community_conf1(Fid, Confs),
+ file:close(Fid).
+
+write_community_conf1(_, []) ->
+ ok;
+write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
+ [ComIdx, ComName, SecName, CtxName, TransTag]),
+ write_community_conf1(Fid, Confs).
+
+
+write_target_addr_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ ok = write_target_addr_conf1(Fid, Confs),
+ file:close(Fid).
+
+
+write_target_addr_conf1(_, []) ->
+ ok;
+write_target_addr_conf1(Fid,
+ [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
+ [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz]),
+ write_target_addr_conf1(Fid, Confs).
+
+write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ ok = io:format(Fid,
+ "{\"~s\", ~w, ~w, 1500, 3, "
+ "\"std_trap\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP, mk_param(Vsn)]),
+ case Vsn of
+ v1 -> ok;
+ v2 ->
+ ok = io:format(Fid,
+ "{\"~s.2\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)]);
+ v3 ->
+ ok = io:format(Fid,
+ "{\"~s.3\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\", "
+ "\"mgrEngine\", [], 1024}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)])
+ end
+ end,
+ Vsns),
+ file:close(Fid).
+
+mk_param(v1) -> "target_v1";
+mk_param(v2) -> "target_v2";
+mk_param(v3) -> "target_v3".
+
+mk_ip([A,B,C,D], Vsn) ->
+ io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
+
+
+rewrite_target_addr_conf(Dir,NewPort) ->
+ TAFile = filename:join(Dir, "target_addr.conf"),
+ ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
+ case file:read_file_info(TAFile) of
+ {ok, _} -> ok;
+ {error, R} -> ?ERR("failure reading file info of "
+ "target address config file: ~p",[R]),
+ ok
+ end,
+
+ ?line [TrapAddr|Addrs] =
+ snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
+
+ ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
+
+ NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
+
+ ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
+
+ ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
+ filename:join(Dir,"target_addr.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+
+ ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
+
+ file:close(Fid).
+
+rewrite_target_addr_conf1(O) ->
+ {ok,O}.
+
+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) ->
+ ?LOG("rewrite_target_addr_conf2 -> entry with "
+ "~n O: ~p",[O]),
+ O.
+
+
+rewrite_target_addr_conf3(_,[]) -> ok;
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
+ ParamName,EngineId}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % ParamsName
+ "\"~s\"}.", % EngineId
+ [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
+ rewrite_target_addr_conf3(Fid,T);
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
+ ParamName,EngineId,TMask,MMS}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % TagList
+ "\"~s\", " % ParamsName
+ "\"~s\"," % EngineId
+ "~p, " % TMask
+ "~p}.", % MMS
+ [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
+ EngineId,TMask,MMS]),
+ rewrite_target_addr_conf3(Fid,T).
+
+reset_target_addr_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
+ filename:join(Dir,"target_addr.conf")).
+
+write_target_params_conf(Dir, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ MP = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> v3
+ end,
+ SM = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> usm
+ end,
+ ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
+ "\"all-rights\", noAuthNoPriv}.~n",
+ [Vsn, MP, SM])
+ end,
+ Vsns),
+ file:close(Fid).
+
+rewrite_target_params_conf(Dir, SecName, SecLevel) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
+ filename:join(Dir,"target_params.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
+ [SecName, SecLevel]),
+ file:close(Fid).
+
+reset_target_params_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.old"),
+ filename:join(Dir,"target_params.conf")).
+
+write_notify_conf(Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
+ ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
+ ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
+ file:close(Fid).
+
+ver_to_trap_str([v1]) -> "v1";
+ver_to_trap_str([v2]) -> "v2";
+% default is to use the latest snmp version
+ver_to_trap_str([v1,v2]) -> "v2".
+
+
+
+write_view_conf(Dir) ->
+ {ok, Fid} = file:open(a(Dir,"view.conf"),write),
+ ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
+ ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
+ file:close(Fid).
+
+a(A,B) -> lists:append(A,B).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+copy_file(From, To) ->
+ {ok, Bin} = file:read_file(From),
+ ok = file:write_file(To, Bin).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+display_memory_usage() ->
+ Info = snmpa:info(snmp_master_agent),
+ TreeSize = lists_key1search(tree_size_bytes, Info),
+ ProcMem = lists_key1search(process_memory, Info),
+ MibDbSize = lists_key1search([db_memory,mib], Info),
+ NodeDbSize = lists_key1search([db_memory,node], Info),
+ TreeDbSize = lists_key1search([db_memory,tree], Info),
+ ?INF("Memory usage: "
+ "~n Tree size: ~p"
+ "~n Process memory size: ~p"
+ "~n Mib db size: ~p"
+ "~n Node db size: ~p"
+ "~n Tree db size: ~p",
+ [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
+
+lists_key1search([], Res) ->
+ Res;
+lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ lists_key1search(Keys, Val);
+ false ->
+ undefined
+ end;
+lists_key1search(Key, List) when atom(Key) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ Val;
+ false ->
+ undefined
+ end.
+
+
+regs() ->
+ lists:sort(registered()).
diff --git a/lib/snmp/test/exp/snmp_agent_v3_test.erl b/lib/snmp/test/exp/snmp_agent_v3_test.erl
new file mode 100644
index 0000000000..c72d845bf2
--- /dev/null
+++ b/lib/snmp/test/exp/snmp_agent_v3_test.erl
@@ -0,0 +1,5649 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(snmp_agent_v3_test).
+
+%% TODO
+%% * Test fault-tolerance (kill master etc)
+%%
+
+-compile(export_all).
+
+-define(application, snmp).
+
+-include_lib("kernel/include/file.hrl").
+-include_lib("test_server/include/test_server.hrl").
+-include("snmp_test_lib.hrl").
+-define(SNMP_USE_V3, true).
+-include_lib("snmp/include/snmp_types.hrl").
+%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
+%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
+
+
+-define(klas1, [1,3,6,1,2,1,7]).
+-define(klas2, [1,3,6,1,2,1,9]).
+-define(klas3, [1,3,6,1,2,1,8,1]).
+-define(klas4, [1,3,6,1,2,1,8,4]).
+-define(sa, [1,3,6,1,4,1,193,2]).
+-define(system, [1,3,6,1,2,1,1]).
+-define(snmp, [1,3,6,1,2,1,11]).
+-define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
+-define(ericsson, [1,3,6,1,4,1,193]).
+-define(testTrap, [1,3,6,1,2,1,15,0]).
+-define(xDescr, [1,3,6,1,2,1,17,1]).
+-define(xDescr2, [1,3,6,1,2,1,17,2]).
+
+-define(active, 1).
+-define(notInService, 2).
+-define(notReady, 3).
+-define(createAndGo, 4).
+-define(createAndWait, 5).
+-define(destroy, 6).
+
+-define(TRAP_UDP, 5000).
+
+-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
+
+-define(str(X), snmp_pdus:bits_to_str(X)).
+
+-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
+ [?LINE, self()]),
+ receive cont -> ok end
+ end).
+
+
+-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
+-define(v1_2(V1,V2),
+ case get(vsn) of
+ v1 -> V1;
+ _ -> V2
+ end).
+
+-define(v1_2_3(V1,V2,V3),
+ case get(vsn) of
+ v1 -> V1;
+ v2 -> V2;
+ _ -> V3
+ end).
+
+all() ->
+[cases()].
+
+groups() ->
+ [{mib_storage, [],
+ [{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()},
+ {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]},
+ {standard_mibs, [],
+ [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]},
+ {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]},
+ {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]},
+ {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]},
+ {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]},
+ {tickets, [], [{group, otp_4394}]},
+ {otp_4394, [], [otp_4394_test]}].
+
+init_per_group(otp_4394, Config) ->
+ init_otp_4394(Config);
+init_per_group(v2_inform, Config) ->
+ init_v2_inform(Config);
+init_per_group(multiple_reqs_2, Config) ->
+ init_mul(Config);
+init_per_group(multiple_reqs, Config) ->
+ init_mul(Config);
+init_per_group(test_multi_threaded, Config) ->
+ init_mt(Config);
+init_per_group(test_v3, Config) ->
+ init_v3(Config);
+init_per_group(test_v1_v2, Config) ->
+ init_v1_v2(Config);
+init_per_group(test_v2, Config) ->
+ init_v2(Config);
+init_per_group(test_v1, Config) ->
+ init_v1(Config);
+init_per_group(mib_storage_varm_mnesia, Config) ->
+ init_varm_mib_storage_mnesia(Config);
+init_per_group(mib_storage_varm_dets, Config) ->
+ init_varm_mib_storage_dets(Config);
+init_per_group(mib_storage_size_check_mnesia, Config) ->
+ init_size_check_msm(Config);
+init_per_group(mib_storage_size_check_dets, Config) ->
+ init_size_check_msd(Config);
+init_per_group(mib_storage_size_check_ets, Config) ->
+ init_size_check_mse(Config);
+init_per_group(mib_storage_mnesia, Config) ->
+ init_mib_storage_mnesia(Config);
+init_per_group(mib_storage_dets, Config) ->
+ init_mib_storage_dets(Config);
+init_per_group(mib_storage_ets, Config) ->
+ init_mib_storage_ets(Config);
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(otp_4394, Config) ->
+ finish_otp_4394(Config);
+end_per_group(v2_inform, Config) ->
+ finish_v2_inform(Config);
+end_per_group(multiple_reqs_2, Config) ->
+ finish_mul(Config);
+end_per_group(multiple_reqs, Config) ->
+ finish_mul(Config);
+end_per_group(test_multi_threaded, Config) ->
+ finish_mt(Config);
+end_per_group(test_v3, Config) ->
+ finish_v3(Config);
+end_per_group(test_v1_v2, Config) ->
+ finish_v1_v2(Config);
+end_per_group(test_v2, Config) ->
+ finish_v2(Config);
+end_per_group(test_v1, Config) ->
+ finish_v1(Config);
+end_per_group(mib_storage_varm_mnesia, Config) ->
+ finish_varm_mib_storage_mnesia(Config);
+end_per_group(mib_storage_varm_dets, Config) ->
+ finish_varm_mib_storage_dets(Config);
+end_per_group(mib_storage_size_check_mnesia, Config) ->
+ finish_size_check_msm(Config);
+end_per_group(mib_storage_size_check_dets, Config) ->
+ finish_size_check_msd(Config);
+end_per_group(mib_storage_size_check_ets, Config) ->
+ finish_size_check_mse(Config);
+end_per_group(mib_storage_mnesia, Config) ->
+ finish_mib_storage_mnesia(Config);
+end_per_group(mib_storage_dets, Config) ->
+ finish_mib_storage_dets(Config);
+end_per_group(mib_storage_ets, Config) ->
+ finish_mib_storage_ets(Config);
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(6)),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) when list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ Config.
+
+cases() ->
+case ?OSTYPE() of
+ vxworks ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_multi_threaded},
+ {group, mib_storage}, {group, tickets}];
+ _Else ->
+ [app_info, {group, test_v1}, {group, test_v2},
+ {group, test_v1_v2}, {group, test_v3},
+ {group, test_multi_threaded}, {group, mib_storage},
+ {group, tickets}]
+end.
+
+
+%%%-----------------------------------------------------------------
+%%% The test case structure is as follows:
+%%%
+%%% init_all - starts mnesia,
+%%%
+%%% init_v1 - starts agent
+%%% simple
+%%% big - e.g. starts/stops subagent, load/unloads mibs
+%%% init_mul
+%%% mul_get
+%%% mul_set
+%%% <etc>
+%%% finish_mul
+%%% <etc>
+%%% finish_v1
+%%%
+%%% init_v2 - starts agent
+%%% finish_v2
+%%%
+%%% init_bilingual - starts agent
+%%% finish_bilingual
+%%%
+%%% finish_all
+%%%
+%%% There is still one problem with these testsuites. If one test
+%%% fails, it may not be possible to run some other cases, as it
+%%% may have e.g. created some row or loaded some table, that it
+%%% didn't undo (since it failed).
+%%%-----------------------------------------------------------------
+
+init_all(Config0) when list(Config0) ->
+ ?LOG("init_all -> entry with"
+ "~n Config0: ~p",[Config0]),
+
+ %% --
+ %% Fix config:
+ %%
+
+ DataDir0 = ?config(data_dir, Config0),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config0),
+ Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+
+ %% --
+ %% Start nodes
+ %%
+
+ ?line {ok, SaNode} = start_node(snmp_sa),
+ ?line {ok, MgrNode} = start_node(snmp_mgr),
+
+
+ %% --
+ %% Create necessary files
+ %%
+
+ Dir = ?config(priv_dir, Config),
+ ?DBG("init_all -> Dir ~p", [Dir]),
+
+ DataDir = ?config(data_dir, Config),
+ ?DBG("init_all -> DataDir ~p", [DataDir]),
+
+ file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+
+ file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+
+ file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
+ ?DBG("init_all -> SaDir ~p", [SaDir]),
+
+
+ %% --
+ %% Start and initiate mnesia
+ %%
+
+ ?DBG("init_all -> load application mnesia", []),
+ ?line ok = application:load(mnesia),
+
+ ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
+ ?line ok = rpc:call(SaNode, application, load, [mnesia]),
+
+ ?DBG("init_all -> application mnesia: set_env dir",[]),
+ ?line application_controller:set_env(mnesia, dir,
+ filename:join(Dir, "Mnesia1")),
+
+ ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(Dir, "Mnesia2")]),
+
+ ?DBG("init_all -> create mnesia schema",[]),
+ ?line ok = mnesia:create_schema([SaNode, node()]),
+
+ ?DBG("init_all -> start application mnesia",[]),
+ ?line ok = application:start(mnesia),
+
+ ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
+ ?line ok = rpc:call(SaNode, application, start, [mnesia]),
+ Ip = ?LOCALHOST(),
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {agent_dir, AgentDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {mib_dir, DataDir},
+ {ip, Ip} |
+ Config].
+
+finish_all(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ stop_node(SaNode),
+ stop_node(MgrNode),
+ application:stop(mnesia).
+
+start_v1_agent(Config) when list(Config) ->
+ start_agent(Config, [v1]).
+
+start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
+ start_agent(Config, [v1], Opts).
+
+start_v2_agent(Config) when list(Config) ->
+ start_agent(Config, [v2]).
+
+start_v3_agent(Config) when list(Config) ->
+ start_agent(Config, [v3]).
+
+start_bilingual_agent(Config) when list(Config) ->
+ start_agent(Config, [v1,v2]).
+
+start_multi_threaded_agent(Config) when list(Config) ->
+ start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
+
+stop_agent(Config) when list(Config) ->
+ ?LOG("stop_agent -> entry with"
+ "~n Config: ~p",[Config]),
+
+ {Sup, Par} = ?config(snmp_sup, Config),
+ ?DBG("stop_agent -> attempt to stop (sup) ~p"
+ "~n Sup: ~p"
+ "~n Par: ~p",
+ [Sup,
+ (catch process_info(Sup)),
+ (catch process_info(Par))]),
+ stop_sup(Sup, Par),
+
+ {Sup2, Par2} = ?config(snmp_sub, Config),
+ ?DBG("stop_agent -> attempt to stop (sub) ~p"
+ "~n Sup2: ~p"
+ "~n Par2: ~p",
+ [Sup2,
+ (catch process_info(Sup2)),
+ (catch process_info(Par2))]),
+ stop_sup(Sup2, Par2),
+
+ ?DBG("stop_agent -> done - now cleanup config", []),
+ C1 = lists:keydelete(snmp_sup, 1, Config),
+ lists:keydelete(snmp_sub, 1, C1).
+
+
+stop_sup(Pid, _) when node(Pid) == node() ->
+ case (catch process_info(Pid)) of
+ PI when list(PI) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ exit(Pid, kill),
+ await_stopped(Pid, Ref);
+ {'EXIT', _Reason} ->
+ ?LOG("stop_sup -> ~p not running", [Pid]),
+ ok
+ end;
+stop_sup(Pid, _) ->
+ ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
+ Ref = erlang:monitor(process, Pid),
+ ?LOG("stop_sup -> Ref: ~p", [Ref]),
+ %% Pid ! {'EXIT', Parent, shutdown}, % usch
+ exit(Pid, kill),
+ await_stopped(Pid, Ref).
+
+await_stopped(Pid, Ref) ->
+ receive
+ {'DOWN', Ref, process, Pid, _Reason} ->
+ ?DBG("received down message for ~p", [Pid]),
+ ok
+ after 10000 ->
+ ?INF("await_stopped -> timeout for ~p",[Pid]),
+ erlang:demonitor(Ref),
+ ?FAIL({failed_stop,Pid})
+ end.
+
+
+start_agent(Config, Vsn) ->
+ start_agent(Config, Vsn, []).
+start_agent(Config, Vsn, Opts) ->
+ ?LOG("start_agent -> entry (~p) with"
+ "~n Config: ~p"
+ "~n Vsn: ~p"
+ "~n Opts: ~p",[node(), Config, Vsn, Opts]),
+
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
+ snmp_app_env_init(vsn_init(Vsn) ++
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentDir},
+ {snmp_db_dir, AgentDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, trace},
+ {snmp_symbolic_store_verbosity, trace},
+ {snmp_note_store_verbosity, trace},
+ {snmp_net_if_verbosity, trace}],
+ Opts),
+
+
+ process_flag(trap_exit,true),
+
+ {ok, AppSup} = snmp_app_sup:start_link(),
+ unlink(AppSup),
+ ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
+
+ ?DBG("start_agent -> start master agent (old style)",[]),
+ Sup = case (catch snmpa_app:start(normal)) of
+ {ok, S} ->
+ ?DBG("start_agent -> started, Sup: ~p",[S]),
+ S;
+
+ Else ->
+ ?DBG("start_agent -> unknown result: ~n~p",[Else]),
+ %% Get info about the apps we depend on
+ MnesiaInfo = mnesia_running(),
+ ?FAIL({start_failed,Else,MnesiaInfo})
+ end,
+
+ ?DBG("start_agent -> unlink from supervisor",[]),
+ ?line unlink(Sup),
+ ?line SaDir = ?config(sa_dir, Config),
+ ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
+ ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
+ ?DBG("start_agent -> done",[]),
+ ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
+
+
+vsn_init(Vsn) ->
+ vsn_init([v1,v2,v3], Vsn, []).
+
+vsn_init([], _Vsn, Acc) ->
+ Acc;
+vsn_init([V|Vsns], Vsn, Acc) ->
+ case lists:member(V, Vsn) of
+ true ->
+ vsn_init(Vsns, Vsn, [{V, true}|Acc]);
+ false ->
+ vsn_init(Vsns, Vsn, [{V, false}|Acc])
+ end.
+
+snmp_app_env_init(Env0, Opts) ->
+ ?DBG("snmp_app_env_init -> unload snmp",[]),
+ ?line application:unload(snmp),
+ ?DBG("snmp_app_env_init -> load snmp",[]),
+ ?line application:load(snmp),
+ ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
+ F1 = fun({Key,Val} = New, Acc0) ->
+ ?DBG("snmp_app_env_init -> "
+ "updating setting ~p to ~p", [Key, Val]),
+ case lists:keyreplace(Key, 1, Acc0, New) of
+ Acc0 ->
+ [New|Acc0];
+ Acc ->
+ Acc
+ end
+ end,
+ Env = lists:foldr(F1, Env0, Opts),
+ ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
+ F2 = fun({Key,Val}) ->
+ ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
+ application_controller:set_env(snmp, Key, Val)
+ end,
+ lists:foreach(F2, Env).
+
+
+
+
+%% Test if application is running
+mnesia_running() -> ?IS_MNESIA_RUNNING().
+crypto_running() -> ?IS_CRYPTO_RUNNING().
+
+
+start_sub(Dir) ->
+ ?DBG("start_sub -> entry",[]),
+ Opts = [{db_dir, Dir},
+ {supervisor, [{verbosity, trace}]}],
+ %% BMK BMK
+% {ok, P} = snmp_supervisor:start_sub(Dir),
+ {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
+ unlink(P),
+ {ok, {P, self()}}.
+
+create_tables(SaNode) ->
+ ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
+ {ram_copies, [SaNode]},
+ {snmp, [{key, integer}]},
+ {attributes, [a1,a2,a3]}]),
+ ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
+ {attributes, [a1,a2]}]).
+
+delete_tables() ->
+ mnesia:delete_table(friendsTable2),
+ mnesia:delete_table(kompissTable2),
+ mnesia:delete_table(snmp_variables).
+
+%% Creation is done in runtime!
+delete_mib_storage_mnesia_tables() ->
+ mnesia:delete_table(snmpa_mib_data),
+ mnesia:delete_table(snmpa_mib_tree),
+ mnesia:delete_table(snmpa_symbolic_store).
+
+%%-----------------------------------------------------------------
+%% A test case is always one of:
+%% - v1 specific case
+%% - v2 specific case
+%% - v1 and v2 case
+%% All v1 specific cases are prefixed with v1_, and all v2 with
+%% v2_. E.g. v1_trap/v2_trap.
+%%
+%% All other cases are shared. However, the testserver uses the name
+%% of the case to generate a file for that case. The same case cannot
+%% be used in different configurations in the same suite. Therefore
+%% all these functions exists in two variants, the base function
+%% <base>, and a second version <base>_2. There may be several
+%% versions as well, <base>_N.
+%%-----------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+mib_storage_ets_cases() ->
+[mse_simple, mse_v1_processing, mse_big, mse_big2,
+ mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
+ mse_sa_error, mse_next_across_sa, mse_undo,
+ mse_standard_mib, mse_community_mib, mse_framework_mib,
+ mse_target_mib, mse_notification_mib,
+ mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
+ mse_mib_of].
+
+mib_storage_dets_cases() ->
+[msd_simple, msd_v1_processing, msd_big, msd_big2,
+ msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
+ msd_sa_error, msd_next_across_sa, msd_undo,
+ msd_standard_mib, msd_community_mib, msd_framework_mib,
+ msd_target_mib, msd_notification_mib,
+ msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
+ msd_mib_of].
+
+mib_storage_mnesia_cases() ->
+[msm_simple, msm_v1_processing, msm_big, msm_big2,
+ msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
+ msm_sa_error, msm_next_across_sa, msm_undo,
+ msm_standard_mib, msm_community_mib, msm_framework_mib,
+ msm_target_mib, msm_notification_mib,
+ msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
+ msm_mib_of].
+
+mse_size_check_cases() ->
+[mse_size_check].
+
+msd_size_check_cases() ->
+[msd_size_check].
+
+msm_size_check_cases() ->
+[msm_size_check].
+
+varm_mib_storage_dets_cases() ->
+[msd_varm_mib_start].
+
+varm_mib_storage_mnesia_cases() ->
+[msm_varm_mib_start].
+
+init_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,ets},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ init_ms(Config, [MibStorage]).
+
+init_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ init_ms(Config, [MibStorage]).
+
+init_ms(Config, Opts) when list(Config) ->
+ ?LOG("init_mib_storage_ets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
+ [{vsn, v1} | start_v1_agent(Config,Opts1)].
+
+init_size_check_mse(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, ets},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msd(Config) when list(Config) ->
+ AgentDir = ?GCONF(agent_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDir}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_msm(Config) when list(Config) ->
+ MibStorage = {snmp_mib_storage, {mnesia,[]}},
+ init_size_check_ms(Config, [MibStorage]).
+
+init_size_check_ms(Config, Opts) when list(Config) ->
+ SaNode = ?GCONF(snmp_sa, Config),
+ %% We are using v3 here, so crypto must be supported or else...
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end,
+ create_tables(SaNode),
+ AgentDir = ?GCONF(agent_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ ?line ok =
+ config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_agent(Config, [v3], Opts)].
+
+init_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_dets -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+init_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("init_varm_mib_storage_mnesia -> entry", []),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?GCONF(agent_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
+ MibsVerbosity = {snmp_mibserver_verbosity, trace},
+ SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
+ Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
+ [{vsn, v1}, {agent_opts,Opts} | Config].
+
+finish_mib_storage_ets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_ets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_dets -> entry", []),
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ C2 = lists:keydelete(vsn, 1, C1),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_dets(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_dets -> entry", []),
+ delete_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_varm_mib_storage_mnesia(Config) when list(Config) ->
+ ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
+ delete_tables(),
+ delete_mib_storage_mnesia_tables(),
+ %% C1 = stop_agent(Config), % In case something went wrong...
+ delete_files(Config),
+ C2 = lists:keydelete(vsn, 1, Config),
+ lists:keydelete(agent_opts, 1, C2).
+
+finish_size_check_mse(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msd(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_msm(Config) when list(Config) ->
+ finish_size_check_ms(Config).
+
+finish_size_check_ms(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%% These are just interface functions to fool the test server
+mse_simple(X) -> simple(X).
+mse_v1_processing(X) -> v1_processing(X).
+mse_big(X) -> big(X).
+mse_big2(X) -> big2(X).
+mse_loop_mib(X) -> loop_mib(X).
+mse_api(X) -> api(X).
+mse_sa_register(X) -> sa_register(X).
+mse_v1_trap(X) -> v1_trap(X).
+mse_sa_error(X) -> sa_error(X).
+mse_next_across_sa(X) -> next_across_sa(X).
+mse_undo(X) -> undo(X).
+mse_standard_mib(X) -> snmp_standard_mib(X).
+mse_community_mib(X) -> snmp_community_mib(X).
+mse_framework_mib(X) -> snmp_framework_mib(X).
+mse_target_mib(X) -> snmp_target_mib(X).
+mse_notification_mib(X) -> snmp_notification_mib(X).
+mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+mse_sparse_table(X) -> sparse_table(X).
+mse_me_of(X) -> ms_me_of(X).
+mse_mib_of(X) -> ms_mib_of(X).
+
+msd_simple(X) -> simple(X).
+msd_v1_processing(X) -> v1_processing(X).
+msd_big(X) -> big(X).
+msd_big2(X) -> big2(X).
+msd_loop_mib(X) -> loop_mib(X).
+msd_api(X) -> api(X).
+msd_sa_register(X) -> sa_register(X).
+msd_v1_trap(X) -> v1_trap(X).
+msd_sa_error(X) -> sa_error(X).
+msd_next_across_sa(X) -> next_across_sa(X).
+msd_undo(X) -> undo(X).
+msd_standard_mib(X) -> snmp_standard_mib(X).
+msd_community_mib(X) -> snmp_community_mib(X).
+msd_framework_mib(X) -> snmp_framework_mib(X).
+msd_target_mib(X) -> snmp_target_mib(X).
+msd_notification_mib(X) -> snmp_notification_mib(X).
+msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msd_sparse_table(X) -> sparse_table(X).
+msd_me_of(X) -> ms_me_of(X).
+msd_mib_of(X) -> ms_mib_of(X).
+
+msm_simple(X) -> simple(X).
+msm_v1_processing(X) -> v1_processing(X).
+msm_big(X) -> big(X).
+msm_big2(X) -> big2(X).
+msm_loop_mib(X) -> loop_mib(X).
+msm_api(X) -> api(X).
+msm_sa_register(X) -> sa_register(X).
+msm_v1_trap(X) -> v1_trap(X).
+msm_sa_error(X) -> sa_error(X).
+msm_next_across_sa(X) -> next_across_sa(X).
+msm_undo(X) -> undo(X).
+msm_standard_mib(X) -> snmp_standard_mib(X).
+msm_community_mib(X) -> snmp_community_mib(X).
+msm_framework_mib(X) -> snmp_framework_mib(X).
+msm_target_mib(X) -> snmp_target_mib(X).
+msm_notification_mib(X) -> snmp_notification_mib(X).
+msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
+msm_sparse_table(X) -> sparse_table(X).
+msm_me_of(X) -> ms_me_of(X).
+msm_mib_of(X) -> ms_mib_of(X).
+
+
+mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
+msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
+msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
+
+msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
+msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
+
+ms_size_check(suite) -> [];
+ms_size_check(Config) when list(Config) ->
+ p("ms_size_check..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?LOG("mib server size check...", []),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMPv2-MIB"),
+ ?line load_master_std("SNMPv2-TM"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMPv2-MIB"),
+ ?line unload_master("SNMPv2-TM"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+
+varm_mib_start(suite) -> [];
+varm_mib_start(Config) when list(Config) ->
+ p("varm_mib_start..."),
+ ?LOG("varm_mib_start -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ %% Start the agent
+ Opts = ?GCONF(agent_opts, Config),
+ Config1 = start_v1_agent(Config, Opts),
+
+ %% Sleep some in order for the agent to start properly
+ ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
+ ?SLEEP(5000),
+
+ %% Load all the mibs
+ HardwiredMibs = loaded_mibs(),
+ ?DBG("varm_mib_start -> load all mibs", []),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+
+ %% Unload the hardwired mibs
+ ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
+ ?SLEEP(1000),
+ ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
+ ?line unload_mibs(HardwiredMibs), %% unload hardwired
+
+ ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
+ ?SLEEP(1000),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ Config2 = stop_agent(Config1),
+
+ %% Sleep some in order for the agent to stop properly
+ ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
+ ?SLEEP(5000),
+
+ %% Start the agent (again)
+ ?DBG("varm_mib_start -> start the agent", []),
+ Config3 = start_v1_agent(Config2, Opts),
+
+ ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
+ ?SLEEP(5000),
+
+ %% Perform the test(s)
+ ?DBG("varm_mib_start -> perform the tests", []),
+ try_test(snmp_community_mib),
+ try_test(snmp_framework_mib),
+ try_test(snmp_target_mib),
+ try_test(snmp_notification_mib),
+
+ %% Stop the agent (without deleting the stored files)
+ ?DBG("varm_mib_start -> stop the agent", []),
+ stop_agent(Config3),
+ ok.
+
+
+-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
+-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
+-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+ms_me_of(suite) -> [];
+ms_me_of(Config) when list(Config) ->
+ p("ms_me_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = me_of(?snmpTrapCommunity_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = me_of(?vacmViewSpinLock_instance),
+
+ ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+me_of(Oid) ->
+ case snmpa:me_of(Oid) of
+ {ok, #me{oid = Oid}} ->
+ ok;
+ {ok, #me{oid = OtherOid}} ->
+ case lists:reverse(Oid) of
+ [0|Rest] ->
+ case lists:reverse(Rest) of
+ OtherOid ->
+ ok;
+ AnotherOid ->
+ {error, {invalid_oid, Oid, AnotherOid}}
+ end;
+ _ ->
+ {error, {invalid_oid, Oid, OtherOid}}
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ {error, Else}
+ end.
+
+
+ms_mib_of(suite) -> [];
+ms_mib_of(Config) when list(Config) ->
+ p("ms_mib_of..."),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+ ?line load_master_std("OTP-SNMPEA-MIB"),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?SLEEP(2000),
+
+ ?line display_memory_usage(),
+
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
+ [?snmpTrapCommunity_instance]),
+ ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
+ [?vacmViewSpinLock_instance]),
+ ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
+
+ ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
+ [?usmStatsNotInTimeWindows_instance]),
+ ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
+ 'SNMP-USER-BASED-SM-MIB'),
+
+
+ ?line unload_master("OTP-SNMPEA-MIB"),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+
+ ok.
+
+mib_of(Oid, ExpectedMibName) ->
+ ?DBG("mib_of -> entry with"
+ "~n Oid: ~p"
+ "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
+ %% case snmpa:mib_of(Oid) of
+ MibOf = snmpa:mib_of(Oid),
+ ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
+ case MibOf of
+ {ok, ExpectedMibName} ->
+ ok;
+ {ok, OtherMibName} ->
+ {error, {invalid_mib, ExpectedMibName, OtherMibName}};
+ {error, Reason} ->
+ {error, Reason};
+ Else ->
+ ?DBG("mib_of -> Else: ~n~p", [Else]),
+ {error, Else}
+ end.
+
+
+app_info(suite) -> [];
+app_info(Config) when list(Config) ->
+ SnmpDir = app_dir(snmp),
+ SslDir = app_dir(ssl),
+ CryptoDir = app_dir(crypto),
+ Attr = snmp:module_info(attributes),
+ AppVsn =
+ case lists:keysearch(app_vsn, 1, Attr) of
+ {value, {app_vsn, V}} ->
+ V;
+ false ->
+ "undefined"
+ end,
+ io:format("Root dir: ~s~n"
+ "SNMP: Application dir: ~s~n"
+ " Application ver: ~s~n"
+ "SSL: Application dir: ~s~n"
+ "CRYPTO: Application dir: ~s~n",
+ [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
+ ok.
+
+app_dir(App) ->
+ case code:lib_dir(App) of
+ D when list(D) ->
+ filename:basename(D);
+ {error, _Reason} ->
+ "undefined"
+ end.
+
+
+
+%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].
+
+init_v1(Config) when list(Config) ->
+ ?line SaNode = ?config(snmp_sa, Config),
+ ?line create_tables(SaNode),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v1} | start_v1_agent(Config)].
+
+finish_v1(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v2_cases() -> [loop_mib_2];
+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].
+
+init_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_v2_agent(Config)].
+
+finish_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+v1_v2_cases() ->
+[simple_bi].
+
+init_v1_v2(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, bilingual} | start_bilingual_agent(Config)].
+
+finish_v1_v2(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+%v3_cases() -> [loop_mib_3];
+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].
+
+init_v3(Config) when list(Config) ->
+ %% Make sure crypto works, otherwise start_agent will fail
+ %% and we will be stuck with a bunch of mnesia tables for
+ %% the rest of this suite...
+ ?DBG("start_agent -> start crypto app",[]),
+ case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ case ?CRYPTO_START() of
+ ok ->
+ case ?CRYPTO_SUPPORT() of
+ {no, Reason} ->
+ ?SKIP({unsupported_encryption, Reason});
+ yes ->
+ ok
+ end;
+ {error, Reason} ->
+ ?SKIP({failed_starting_crypto, Reason})
+ end
+ end,
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v3], MgrDir, AgentDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v3} | start_v3_agent(Config)].
+
+finish_v3(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+
+mt_cases() ->
+[multi_threaded, mt_trap].
+
+init_mt(Config) when list(Config) ->
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDir = ?config(agent_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ [{vsn, v2} | start_multi_threaded_agent(Config)].
+
+finish_mt(Config) when list(Config) ->
+ delete_tables(),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ lists:keydelete(vsn, 1, C1).
+
+%% This one *must* be run first in each case.
+init_case(Config) when list(Config) ->
+ ?DBG("init_case -> entry with"
+ "~n Config: ~p", [Config]),
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = node(),
+
+ SaHost = ?HOSTNAME(SaNode),
+ MgrHost = ?HOSTNAME(MgrNode),
+ MasterHost = ?HOSTNAME(MasterNode),
+ {ok, MasterIP} = snmp_misc:ip(MasterHost),
+ {ok, MIP} = snmp_misc:ip(MgrHost),
+ {ok, SIP} = snmp_misc:ip(SaHost),
+
+
+ put(mgr_node, MgrNode),
+ put(sa_node, SaNode),
+ put(master_node, MasterNode),
+ put(sa_host, SaHost),
+ put(mgr_host, MgrHost),
+ put(master_host, MasterHost),
+ put(mip, tuple_to_list(MIP)),
+ put(masterip , tuple_to_list(MasterIP)),
+ put(sip, tuple_to_list(SIP)),
+
+ MibDir = ?config(mib_dir, Config),
+ put(mib_dir, MibDir),
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ put(std_mib_dir, StdM),
+
+ MgrDir = ?config(mgr_dir, Config),
+ put(mgr_dir, MgrDir),
+
+ put(vsn, ?config(vsn, Config)),
+ ?DBG("init_case -> exit with"
+ "~n MasterNode: ~p"
+ "~n SaNode: ~p"
+ "~n MgrNode: ~p"
+ "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
+ {SaNode, MgrNode, MibDir}.
+
+load_master(Mib) ->
+ ?DBG("load_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
+
+load_master_std(Mib) ->
+ ?DBG("load_master_std -> entry with"
+ "~n Mib: ~p", [Mib]),
+ snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
+ ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
+
+unload_master(Mib) ->
+ ?DBG("unload_master -> entry with"
+ "~n Mib: ~p", [Mib]),
+ ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
+
+loaded_mibs() ->
+ ?DBG("loaded_mibs -> entry",[]),
+ Info = snmpa:info(snmp_master_agent),
+ {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
+ [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
+
+unload_mibs(Mibs) ->
+ ?DBG("unload_mibs -> entry with"
+ "~n Mibs: ~p", [Mibs]),
+ ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
+
+start_subagent(SaNode, RegTree, Mib) ->
+ ?DBG("start_subagent -> entry with"
+ "~n SaNode: ~p"
+ "~n RegTree: ~p"
+ "~n Mib: ~p", [SaNode, RegTree, Mib]),
+ MA = whereis(snmp_master_agent),
+ ?DBG("start_subagent -> MA: ~p", [MA]),
+ MibDir = get(mib_dir),
+ Mib1 = join(MibDir,Mib),
+ %% BMK BMK
+% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
+ case rpc:call(SaNode, snmpa_supervisor,
+ start_sub_agent, [MA, RegTree, [Mib1]]) of
+ {ok, SA} ->
+ ?DBG("start_subagent -> SA: ~p", [SA]),
+ {ok, SA};
+ Error ->
+ ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
+ end.
+
+stop_subagent(SA) ->
+ ?DBG("stop_subagent -> entry with"
+ "~n SA: ~p", [SA]),
+ %% BNK BMK
+ %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
+ rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
+
+%%-----------------------------------------------------------------
+%% This function takes care of the old OTP-SNMPEA-MIB.
+%% Unfortunately, the testcases were written to use the data in the
+%% internal tables, and these table are now obsolete and not used
+%% by the agent. Therefore, we emulate them by using
+%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
+%%
+%% These two rows must exist in intCommunityTable
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+%% (But with the manager's IP address)
+%%
+%%-----------------------------------------------------------------
+init_old() ->
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [6 | "public"],
+ {get(mip), "public", 2, 2}),
+ snmpa_local_db:table_create_row(intCommunityTable,
+ get(mip) ++ [13 | "standard trap"],
+ {get(mip), "standard trap", 2, 1}),
+ snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
+
+
+
+simple(suite) -> [];
+simple(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(simple_standard_test).
+
+simple_2(X) -> simple(X).
+
+simple_bi(suite) -> [];
+simple_bi(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(vsn, v1), % First, try v1 manager
+ try_test(simple_standard_test),
+
+ put(vsn, v2), % Then, try v2 manager
+ try_test(simple_standard_test).
+
+simple_3(X) ->
+ simple(X).
+
+big(suite) -> [];
+big(Config) when list(Config) ->
+ ?DBG("big -> entry", []),
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?DBG("big -> SA: ~p", [SA]),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+big_2(X) -> big(X).
+
+big_3(X) -> big(X).
+
+
+big2(suite) -> [];
+big2(Config) when list(Config) ->
+ %% This is exactly the same tests as 'big', but with the
+ %% v2 equivalent of the mibs.
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent..."),
+ ?line pong = net_adm:ping(SaNode),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
+ ?line load_master("OLD-SNMPEA-MIB-v2"),
+ ?line init_old(),
+ try_test(big_test),
+ ?line stop_subagent(SA),
+ ?line unload_master("OLD-SNMPEA-MIB-v2").
+
+big2_2(X) -> big2(X).
+
+big2_3(X) -> big2(X).
+
+
+multi_threaded(suite) -> [];
+multi_threaded(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(multi_threaded_test),
+ ?line unload_master("Test1").
+
+mt_trap(suite) -> [];
+mt_trap(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ ?line load_master("TestTrapv2"),
+ try_test(mt_trap_test, [MA]),
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("Test1").
+
+v2_types(suite) -> [];
+v2_types(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(types_v2_test),
+ ?line unload_master("Test1").
+
+v2_types_3(X) -> v2_types(X).
+
+
+implied(suite) -> [];
+implied(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(implied_test,[MA]),
+ ?line unload_master("Test1").
+
+implied_3(X) -> implied(X).
+
+
+sparse_table(suite) -> [];
+sparse_table(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(sparse_table_test),
+ ?line unload_master("Test1").
+
+sparse_table_2(X) -> sparse_table(X).
+
+sparse_table_3(X) -> sparse_table(X).
+
+cnt_64(suite) -> [];
+cnt_64(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test1"),
+ try_test(cnt_64_test, [MA]),
+ ?line unload_master("Test1").
+
+cnt_64_2(X) -> cnt_64(X).
+
+cnt_64_3(X) -> cnt_64(X).
+
+opaque(suite) -> [];
+opaque(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test1"),
+ try_test(opaque_test),
+ ?line unload_master("Test1").
+
+opaque_2(X) -> opaque(X).
+
+opaque_3(X) -> opaque(X).
+
+
+change_target_addr_config(suite) -> [];
+change_target_addr_config(Config) when list(Config) ->
+ p("Testing changing target address config..."),
+ ?LOG("change_target_addr_config -> entry",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ put(sname,snmp_suite),
+ put(verbosity,trace),
+
+ MA = whereis(snmp_master_agent),
+
+ ?LOG("change_target_addr_config -> load TestTrap",[]),
+ ?line load_master("TestTrap"),
+
+ ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,trace),
+
+ %% First send some traps that will arive att the original manager
+ ?LOG("change_target_addr_config -> send trap",[]),
+ try_test(ma_trap1, [MA]),
+
+ ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
+ ?line snmpa:verbosity(local_db,silence),
+
+ %% Start new dummy listener
+ ?LOG("change_target_addr_config -> start dummy manager",[]),
+ ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+
+ %% Reconfigure
+ ?LOG("change_target_addr_config -> reconfigure",[]),
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_addr_conf(AgentDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ %% Send the trap again
+ ?LOG("change_target_addr_config -> send trap again",[]),
+ catch dummy_manager_send_trap2(Pid),
+
+ ?LOG("change_target_addr_config -> await trap ack",[]),
+ catch dummy_manager_await_trap2_ack(),
+
+ ?LOG("change_target_addr_config -> stop dummy manager",[]),
+ ?line ok = dummy_manager_stop(Pid),
+
+ ?LOG("change_target_addr_config -> reset target address config",[]),
+ ?line reset_target_addr_conf(AgentDir),
+
+ ?LOG("change_target_addr_config -> unload TestTrap",[]),
+ ?line unload_master("TestTrap").
+
+
+dummy_manager_start(MA) ->
+ ?DBG("dummy_manager_start -> entry",[]),
+ Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
+ ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
+ await_dummy_manager_started(Pid).
+
+await_dummy_manager_started(Pid) ->
+ receive
+ {dummy_manager_started,Pid,Port} ->
+ ?DBG("dummy_manager_start -> acknowledge received with"
+ "~n Port: ~p",[Port]),
+ {ok,Pid,Port};
+ {'EXIT', Pid, Reason} ->
+ {error, Pid, Reason};
+ O ->
+ ?LOG("dummy_manager_start -> received unknown message:"
+ "~n ~p",[O]),
+ await_dummy_manager_started(Pid)
+ end.
+
+dummy_manager_stop(Pid) ->
+ ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
+ Pid ! stop,
+ receive
+ {dummy_manager_stopping, Pid} ->
+ ?DBG("dummy_manager_stop -> acknowledge received",[]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_stop -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_send_trap2(Pid) ->
+ ?DBG("dummy_manager_send_trap2 -> entry",[]),
+ Pid ! {send_trap,testTrap2}.
+
+dummy_manager_await_trap2_ack() ->
+ ?DBG("dummy_manager_await_trap2 -> entry",[]),
+ receive
+ {received_trap,Trap} ->
+ ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
+ %% Note:
+ %% Without this sleep the v2_inform_i testcase failes! There
+ %% is no relation between these two test cases as far as I
+ %% able to figure out...
+ sleep(60000),
+ ok;
+ O ->
+ ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
+ ok
+ after 10000 ->
+ ?ERR("dummy_manager_await_trap2 -> timeout",[]),
+ timeout
+ end.
+
+dummy_manager_init(Parent,MA) ->
+ ?DBG("dummy_manager_init -> entry with"
+ "~n Parent: ~p"
+ "~n MA: ~p",[Parent,MA]),
+ {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
+ ?DBG("dummy_manager_init -> S: ~p",[S]),
+ {ok,Port} = inet:port(S),
+ ?DBG("dummy_manager_init -> Port: ~p",[Port]),
+ Parent ! {dummy_manager_started,self(),Port},
+ dummy_manager_loop(Parent,S,MA).
+
+dummy_manager_loop(P,S,MA) ->
+ ?LOG("dummy_manager_loop -> ready for receive",[]),
+ receive
+ {send_trap,Trap} ->
+ ?LOG("dummy_manager_loop -> received trap send request"
+ "~n Trap: ~p",[Trap]),
+ snmpa:send_trap(MA, Trap, "standard trap"),
+ dummy_manager_loop(P,S,MA);
+ {udp, _UdpId, Ip, UdpPort, Bytes} ->
+ ?LOG("dummy_manager_loop -> received upd message"
+ "~n from: ~p:~p"
+ "~n size: ~p",
+ [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
+ R = dummy_manager_handle_message(Bytes),
+ ?DBG("dummy_manager_loop -> R: ~p",[R]),
+ P ! R,
+ dummy_manager_loop(P,S,MA);
+ stop ->
+ ?DBG("dummy_manager_loop -> received stop request",[]),
+ P ! {dummy_manager_stopping, self()},
+ gen_udp:close(S),
+ exit(normal);
+ O ->
+ ?LOG("dummy_manager_loop -> received unknown message:"
+ "~n ~p",[O]),
+ dummy_manager_loop(P,S,MA)
+ end.
+
+dummy_manager_message_sz(B) when binary(B) ->
+ size(B);
+dummy_manager_message_sz(L) when list(L) ->
+ length(L);
+dummy_manager_message_sz(_) ->
+ undefined.
+
+dummy_manager_handle_message(Bytes) ->
+ case (catch snmp_pdus:dec_message(Bytes)) of
+ {'EXIT',Reason} ->
+ ?ERR("dummy_manager_handle_message -> "
+ "failed decoding message only:~n ~p",[Reason]),
+ {error,Reason};
+ M ->
+ ?DBG("dummy_manager_handle_message -> decoded message:"
+ "~n ~p",[M]),
+ {received_trap,M}
+ end.
+
+
+api(suite) -> [];
+api(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(api_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+api_2(X) -> api(X).
+
+api_3(X) -> api(X).
+
+
+subagent(suite) -> [];
+subagent(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ try_test(load_test_sa),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+
+ p("Loading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(load_test),
+
+ p("Unloading previous subagent mib in master and testing..."),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
+ try_test(unreg_test),
+ p("Testing register subagent..."),
+ rpc:call(SaNode, snmp, register_subagent,
+ [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ ?line stop_subagent(SA),
+ try_test(unreg_test).
+
+subagent_2(X) -> subagent(X).
+
+subagent_3(X) -> subagent(X).
+
+
+mnesia(suite) -> [];
+mnesia(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Starting subagent with mnesia impl..."),
+ {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+
+ try_test(big_test_2),
+
+ p("Testing unregister subagent..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
+ try_test(unreg_test),
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA).
+
+mnesia_2(X) -> mnesia(X).
+
+mnesia_3(X) -> mnesia(X).
+
+
+
+mul_cases() ->
+[mul_get, mul_get_err, mul_next, mul_next_err,
+ mul_set_err].
+
+
+multiple_reqs_3(_X) ->
+ {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
+
+
+mul_cases_2() ->
+[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
+ mul_set_err_2].
+
+
+mul_cases_3() ->
+ [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
+
+
+init_mul(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ [{mul_sub, SA} | Config].
+
+finish_mul(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ SA = ?config(mul_sub, Config),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ ?line stop_subagent(SA),
+ lists:keydelete(mul_sub, 1, Config).
+
+mul_get(suite) -> [];
+mul_get(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get..."),
+ try_test(do_mul_get).
+
+mul_get_2(X) -> mul_get(X).
+
+mul_get_3(X) -> mul_get(X).
+
+
+mul_get_err(suite) -> [];
+mul_get_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple get with error..."),
+ try_test(do_mul_get_err).
+
+mul_get_err_2(X) -> mul_get_err(X).
+
+mul_get_err_3(X) -> mul_get_err(X).
+
+
+mul_next(suite) -> [];
+mul_next(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next).
+
+mul_next_2(X) -> mul_next(X).
+
+mul_next_3(X) -> mul_next(X).
+
+
+mul_next_err(suite) -> [];
+mul_next_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple next..."),
+ try_test(do_mul_next_err).
+
+mul_next_err_2(X) -> mul_next_err(X).
+
+mul_next_err_3(X) -> mul_next_err(X).
+
+
+mul_set(suite) -> [];
+mul_set(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set..."),
+ try_test(do_mul_set).
+
+mul_set_2(X) -> mul_set(X).
+
+mul_set_3(X) -> mul_set(X).
+
+
+mul_set_err(suite) -> [];
+mul_set_err(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing multiple set with error..."),
+ try_test(do_mul_set_err).
+
+mul_set_err_2(X) -> mul_set_err(X).
+
+mul_set_err_3(X) -> mul_set_err(X).
+
+
+sa_register(suite) -> [];
+sa_register(Config) when list(Config) ->
+ ?DBG("sa_register -> entry", []),
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+
+ ?DBG("sa_register -> start subagent", []),
+ ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+
+ ?DBG("sa_register -> unregister subagent", []),
+ p("Testing unregister subagent (2)..."),
+ MA = whereis(snmp_master_agent),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Loading SA-MIB..."),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ ?DBG("sa_register -> unload mibs", []),
+ snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
+ ?DBG("sa_register -> register subagent", []),
+ rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
+ try_test(sa_mib),
+
+ ?DBG("sa_register -> stop subagent", []),
+ ?line stop_subagent(SA).
+
+sa_register_2(X) -> sa_register(X).
+
+sa_register_3(X) -> sa_register(X).
+
+
+v1_trap(suite) -> [];
+v1_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_trap1, [MA]),
+ try_test(ma_trap2, [MA]),
+ try_test(ma_v2_2_v1_trap, [MA]),
+ try_test(ma_v2_2_v1_trap2, [MA]),
+
+ p("Testing trap sending from subagent..."),
+ try_test(sa_trap1, [SA]),
+ try_test(sa_trap2, [SA]),
+ try_test(sa_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v2_trap(suite) -> [];
+v2_trap(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing trap sending from master agent..."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+
+ try_test(ma_v2_trap1, [MA]),
+ try_test(ma_v2_trap2, [MA]),
+ try_test(ma_v1_2_v2_trap, [MA]),
+ try_test(ma_v1_2_v2_trap2, [MA]),
+
+ try_test(sa_mib),
+ p("Testing trap sending from subagent..."),
+ try_test(sa_v1_2_v2_trap1, [SA]),
+ try_test(sa_v1_2_v2_trap2, [SA]),
+ try_test(sa_v1_2_v2_trap3, [SA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2"),
+
+ ?line stop_subagent(SA).
+
+v3_trap(X) ->
+ v2_trap(X).
+
+
+v3_inform(_X) ->
+ %% v2_inform(X).
+ {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
+
+init_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+init_v3_inform(X) ->
+ init_v2_inform(X).
+
+finish_v2_inform(Config) when list(Config) ->
+ _Dir = ?config(agent_dir, Config),
+% snmp_internal_mib:configure(Dir),
+ Config.
+
+finish_v3_inform(X) ->
+ finish_v2_inform(X).
+
+
+
+v2_inform_i(suite) -> [];
+v2_inform_i(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ p("Testing inform sending from master agent... NOTE! This test\ntakes a "
+ "few minutes (5) to complete."),
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(ma_v2_inform1, [MA]),
+
+ ?line unload_master("TestTrap"),
+ ?line unload_master("TestTrapv2").
+
+v3_inform_i(X) -> v2_inform_i(X).
+
+
+sa_error(suite) -> [];
+sa_error(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing sa bad value (is_set_ok)..."),
+ try_test(sa_errs_bad_value),
+
+ p("Testing sa gen err (set)..."),
+ try_test(sa_errs_gen_err),
+
+ p("Testing too big..."),
+ try_test(sa_too_big),
+
+ ?line unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
+
+sa_error_2(X) -> sa_error(X).
+
+sa_error_3(X) -> sa_error(X).
+
+
+next_across_sa(suite) -> [];
+next_across_sa(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Loading another subagent mib..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
+
+ rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
+ try_test(load_test_sa),
+
+ p("Testing next across subagent (endOfMibView from SA)..."),
+ try_test(next_across_sa),
+
+ p("Unloading mib"),
+ snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
+ rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
+ try_test(unreg_test),
+
+ p("Starting another subagent"),
+ ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ p("Testing next across subagent (wrong prefix from SA)..."),
+ try_test(next_across_sa),
+
+ stop_subagent(SA),
+ stop_subagent(SA2).
+
+next_across_sa_2(X) -> next_across_sa(X).
+
+next_across_sa_3(X) -> next_across_sa(X).
+
+
+undo(suite) -> [];
+undo(Config) when list(Config) ->
+ {SaNode, _MgrNode, MibDir} = init_case(Config),
+ MA = whereis(snmp_master_agent),
+
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+
+ p("Testing undo phase at master agent..."),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
+ try_test(undo_test),
+ try_test(api_test2),
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
+
+ p("Testing bad return values from instrum. funcs..."),
+ try_test(bad_return),
+
+ ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
+
+ p("Testing undo phase at subagent..."),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
+ ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
+ ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ try_test(undo_test),
+ try_test(api_test3),
+
+ p("Testing undo phase across master/subagents..."),
+ try_test(undo_test),
+ try_test(api_test3),
+ stop_subagent(SA).
+
+undo_2(X) -> undo(X).
+
+undo_3(X) -> undo(X).
+
+%% Req. Test2
+v1_processing(suite) -> [];
+v1_processing(Config) when list(Config) ->
+ ?DBG("v1_processing -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v1_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v2_processing(suite) -> [];
+v2_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc),
+ ?line unload_master("Test2").
+
+%% Req. Test2
+v3_processing(suite) -> [];
+v3_processing(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("Test2"),
+ try_test(v2_proc), % same as v2!
+ ?line unload_master("Test2").
+
+
+%% We'll try get/set/trap and inform for all the auth & priv protocols.
+%% For informs, the mgr is auth-engine. The agent has to sync. This is
+%% accomplished by the first inform sent. That one will generate a
+%% report, which makes it in sync. The notification-generating
+%% application times out, and send again. This time it'll work.
+
+v3_crypto_basic(suite) -> [];
+v3_crypto_basic(_Config) ->
+ EID = [0,0,0,0,0,0,0,0,0,0,0,2],
+ %% From rfc2274 appendix A.3.1
+ ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
+ ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
+ 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
+ KMd5_1,
+ %% From rfc2274 appendix A.3.2
+ ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
+ ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
+ 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
+ KSHA_1,
+ %% From rfc2274, appendix A.5.1
+ ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
+ 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ %% From rfc2274, appendix A.5.2
+ ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
+ 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
+ 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+ KSHA_1t = lists:sublist(KSHA_1, 16),
+ KSHA_2t = lists:sublist(KSHA_2, 16),
+ ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+ 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
+ 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
+ snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+
+ %% Try with correct random
+ ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
+ ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
+ ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
+ ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
+ ok.
+
+
+
+v3_md5_auth(suite) -> [];
+v3_md5_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing MD5 authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_sha_auth(suite) -> [];
+v3_sha_auth(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing SHA authentication...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+v3_des_priv(suite) -> [];
+v3_des_priv(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ p("Testing DES encryption...takes a few seconds..."),
+
+ AgentDir = ?config(agent_dir, Config),
+ ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentDir),
+
+ MA = whereis(snmp_master_agent),
+
+ ?line load_master("Test2"),
+ ?line load_master("TestTrap"),
+ ?line load_master("TestTrapv2"),
+
+ try_test(v3_sync, [[{v2_proc, []},
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("TestTrapv2"),
+ ?line unload_master("TestTrap"),
+ ?line unload_master("Test2"),
+ ?line reset_target_params_conf(AgentDir).
+
+%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
+
+%% Make sure mgr is in sync with agent
+v3_sync(Funcs) ->
+ ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
+ g([[sysDescr, 0]]),
+ expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
+ g([[sysDescr, 0]]),
+ expect(433, [{[sysDescr,0], any}]),
+ lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
+
+v3_inform_sync(MA) ->
+ ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
+ "standard inform", []),
+ %% Make sure agent is in sync with mgr...
+ ?DBG("v3_sync -> wait some time: ",[]),
+ sleep(20000), % more than 1500*10 in target_addr.conf
+ ?DBG("v3_sync -> await response",[]),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]).
+
+
+v2_caps(suite) -> [];
+v2_caps(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ try_test(v2_caps_i, [node()]).
+
+v2_caps_3(X) -> v2_caps(X).
+
+
+v2_caps_i(Node) ->
+ ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
+ g([[sysORID, Idx], [sysORDescr, Idx]]),
+ ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
+ {[sysORDescr, Idx], "test cap"}]),
+ ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
+ g([[sysORID, Idx]]),
+ ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
+
+
+%% Req. Test2
+v1_proc() ->
+ ?DBG("v1_proc -> entry", []),
+ %% According to RFC1157.
+ %% Template: <Section>:<list no>
+ v1_get_p(),
+ v1_get_next_p(),
+ v1_set_p().
+
+
+v1_get_p() ->
+ %% 4.1.2:1
+ g([[test2]]),
+ ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
+ g([[tDescr]]),
+ ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
+ g([[tDescr2,0]]),
+ ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ g([[tDescr3,0]]),
+ ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ g([[tDescr4,0]]),
+ ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ {[tDescr,0], 'NULL'}]),
+ g([[sysDescr,3]]),
+ ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+
+ %% 4.1.2:2
+ g([[tTable]]),
+ ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
+ g([[tEntry]]),
+ ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
+
+ %% 4.1.2:3
+ g([[tTooBig, 0]]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.2:4
+ g([[tGenErr1, 0]]),
+ ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]).
+
+
+v1_get_next_p() ->
+ %% 4.1.3:1
+ gn([[1,3,7,1]]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+ gn([[tDescr2]]),
+ ?line expect(11, tooBig, 0, any),
+
+ %% 4.1.3:2
+ gn([[tTooBig]]),
+ io:format("We currently don't handle tooBig correct!!!\n"),
+% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
+ ?line expect(20, tooBig, 0, any),
+
+ %% 4.1.3:3
+ gn([[tGenErr1]]),
+% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?line expect(40, genErr, 1, any),
+ gn([[tGenErr2]]),
+% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?line expect(41, genErr, 1, any),
+ gn([[sysDescr], [tGenErr3]]),
+% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
+% {[tGenErr3], 'NULL'}]).
+ ?line expect(42, genErr, 2, any).
+
+v1_set_p() ->
+ %% 4.1.5:1
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+ s([{[tDescr3], s, "noSuchObject"}]),
+ ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+ s([{[tDescr3,1], s, "noSuchInstance"}]),
+ ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+ s([{[tDescr2,0], s, "inconsistentName"}]),
+ ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+
+ %% 4.1.5:2
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.1.5:3
+ %% The standard is quite incorrect here. The resp pdu was too big. In
+ %% the resp pdu, we have the original vbs. In the tooBig pdu we still
+ %% have to original vbs => the tooBig pdu is too big as well!!! It
+ %% may not get it to the manager, unless the agent uses 'NULL' instead
+ %% of the std-like original value.
+ s([{[tTooBig, 0], s, ?tooBigStr}]),
+ %% according to std:
+% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+
+ %% 4.1.5:4
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+ s([{[tDescr2, 0], s, "commit_fail"}]),
+ ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+
+%% Req. Test2
+v2_proc() ->
+ %% According to RFC1905.
+ %% Template: <Section>:<list no>
+ ?DBG("v2_proc -> entry",[]),
+ v2_get_p(),
+ v2_get_next_p(),
+ v2_get_bulk_p(),
+ v2_set_p().
+
+v2_get_p() ->
+ %% 4.2.1:2
+ ?DBG("v2_get_p -> entry",[]),
+ g([[test2]]),
+ ?line expect(10, [{[test2], noSuchObject}]),
+ g([[tDescr]]),
+ ?line expect(11, [{[tDescr], noSuchObject}]),
+ g([[tDescr4,0]]),
+ ?line expect(12, [{[tDescr4,0], noSuchObject}]),
+ g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[tDescr,0], noSuchObject}]),
+ g([[tTable]]),
+ ?line expect(14, [{[tTable], noSuchObject}]),
+ g([[tEntry]]),
+ ?line expect(15, [{[tEntry], noSuchObject}]),
+
+ %% 4.2.1:3
+ g([[tDescr2,0]]), %% instrum ret noSuchName!!!
+ ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
+ g([[tDescr3,0]]),
+ ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
+ g([[sysDescr,3]]),
+ ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
+ g([[tIndex,1]]),
+ ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
+
+ %% 4.2.1 - any other error: genErr
+ g([[tGenErr1, 0]]),
+ ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ g([[tGenErr2, 0]]),
+ ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ g([[sysDescr, 0], [tGenErr3, 0]]),
+ ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
+ {[tGenErr3, 0], 'NULL'}]),
+
+ %% 4.2.1 - tooBig
+ g([[tTooBig, 0]]),
+ ?line expect(40, tooBig, 0, []).
+
+
+v2_get_next_p() ->
+ %% 4.2.2:2
+ ?DBG("v2_get_next_p -> entry",[]),
+ gn([[1,3,7,1]]),
+ ?line expect(10, [{[1,3,7,1], endOfMibView}]),
+ gn([[sysDescr], [1,3,7,1]]),
+ ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gn([[tCnt2, 1]]),
+ ?line expect(12, [{[tCnt2,2], 100}]),
+ gn([[tCnt2, 2]]),
+ ?line expect(12, [{[tCnt2,2], endOfMibView}]),
+
+ %% 4.2.2 - any other error: genErr
+ gn([[tGenErr1]]),
+ ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
+ gn([[tGenErr2]]),
+ ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
+ gn([[sysDescr], [tGenErr3]]),
+ ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
+ {[tGenErr3], 'NULL'}]),
+
+ %% 4.2.2 - tooBig
+ gn([[tTooBig]]),
+ ?line expect(20, tooBig, 0, []).
+
+v2_get_bulk_p() ->
+ %% 4.2.3
+ ?DBG("v2_get_bulk_p -> entry",[]),
+ gb(1, 1, []),
+ ?line expect(10, []),
+ gb(-1, 1, []),
+ ?line expect(11, []),
+ gb(-1, -1, []),
+ ?line expect(12, []),
+ gb(-1, -1, []),
+ ?line expect(13, []),
+ gb(2, 0, [[sysDescr], [1,3,7,1]]),
+ ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(1, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView}]),
+ gb(0, 2, [[sysDescr], [1,3,7,1]]),
+ ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
+ ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysDescr, 0], "Erlang SNMP agent"},
+ {[1,3,7,1], endOfMibView},
+ {[sysObjectID, 0], [1,2,3]},
+ {[1,3,7,1], endOfMibView}]),
+
+ gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
+ ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
+ {[sysDescr, 0], "Erlang SNMP agent"}]),
+
+ gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
+ ?line expect(19, []),
+
+ gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
+ ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
+ {[sysObjectID], 'NULL'},
+ {[tGenErr1], 'NULL'},
+ {[sysDescr], 'NULL'}]),
+ gb(0, 2, [[tCnt2, 1]]),
+ ?line expect(21, [{[tCnt2,2], 100},
+ {[tCnt2,2], endOfMibView}]).
+
+
+v2_set_p() ->
+ %% 4.2.5:1
+ ?DBG("v2_set_p -> entry",[]),
+ s([{[1,3,7,0], i, 4}]),
+ ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
+ s([{[tDescr,0], s, "outside mibview"}]),
+ ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
+
+ %% 4.2.5:2
+ s([{[1,3,6,1,0], s, "noSuchObject"}]),
+ ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
+
+ %% 4.2.5:3
+ s([{[tDescr2, 0], i, 4}]),
+ ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
+ s([{[tDescr2, 0], s, "badValue"}]),
+ ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
+
+ %% 4.2.5:4
+ s([{[tStr, 0], s, ""}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
+ s([{[tStr, 0], s, "12345"}]),
+ ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
+
+ %% 4.2.5:5 - N/A
+
+ %% 4.2.5:6
+ s([{[tInt1, 0], i, 0}]),
+ ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
+ s([{[tInt1, 0], i, 5}]),
+ ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
+ s([{[tInt2, 0], i, 0}]),
+ ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
+ s([{[tInt2, 0], i, 5}]),
+ ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
+ s([{[tInt3, 0], i, 5}]),
+ ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
+
+ %% 4.2.5:7
+ s([{[tDescrX, 1, 1], s, "noCreation"}]),
+ ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
+
+ %% 4.2.5:8
+ s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
+ ?line expect(80, inconsistentName, 1,
+ [{[tDescrX, 1, 2], "inconsistentName"}]),
+
+ %% 4.2.5:9
+ s([{[tCnt, 1, 2], i, 5}]),
+ ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
+ s([{[tDescr3,0], s, "read-only"}]),
+ ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
+
+ %% 4.2.5:10
+ s([{[tDescr2,0], s, "inconsistentValue"}]),
+ ?line expect(100, inconsistentValue, 1,
+ [{[tDescr2,0], "inconsistentValue"}]),
+
+ %% 4.2.5:11
+ s([{[tDescr2,0], s, "resourceUnavailable"}]),
+ ?line expect(110, resourceUnavailable, 1,
+ [{[tDescr2,0],"resourceUnavailable"}]),
+
+ %% 4.2.5:12
+ s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
+ ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
+
+ %% commitFailed and undoFailed is tested by the 'undo' case.
+
+
+%% Req. OLD-SNMPEA-MIB
+table_test() ->
+ io:format("Testing simple get, next and set on communityTable...~n"),
+%% {[147,214,36,45], "public", 2, readWrite}.
+%% {[147,214,36,45], "standard trap", 2, read}.
+ Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
+ Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
+ Key1c4 = [intCommunityAccess,get(mip),is("public")],
+ EndKey = [intCommunityEntry,[9],get(mip),is("public")],
+ gn([[intCommunityEntry]]),
+ ?line expect(7, [{Key1c3, 2}]),
+ gn([[intCommunityTable]]),
+ ?line expect(71, [{Key1c3, 2}]),
+ gn([[community]]),
+ ?line expect(72, [{Key1c3, 2}]),
+ gn([[otpSnmpeaMIB]]),
+ ?line expect(73, [{Key1c3, 2}]),
+ gn([[ericsson]]),
+ ?line expect(74, [{Key1c3, 2}]),
+ gn([Key1c3]),
+ ?line expect(8, [{Key2c3, 2}]),
+ gn([Key2c3]),
+ ?line expect(9, [{Key1c4, 2}]),
+ gn([EndKey]),
+ AgentIp = [intAgentIpAddress,0],
+ ?line expect(10, [{AgentIp, any}]),
+ g([Key1c3]),
+ ?line expect(11, [{Key1c3, 2}]),
+ g([EndKey]),
+ ?line ?v1_2(expect(12, noSuchName, 1, any),
+ expect(12, [{EndKey, noSuchObject}])),
+
+ io:format("Testing row creation/deletion on communityTable...~n"),
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+ s([{NewKeyc5, ?createAndGo}]),
+ ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
+ s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
+ ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
+ g([NewKeyc4]),
+ ?line expect(16, [{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(17, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
+ s([{NewKeyc5, ?createAndWait}]),
+ ?line expect(19, [{NewKeyc5, ?createAndWait}]),
+ g([NewKeyc5]),
+ ?line expect(20, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc4, 2}]),
+ ?line expect(21, [{NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(22, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc3, 2}]),
+ ?line expect(23, [{NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(24, [{NewKeyc5, ?notInService}]),
+ s([{NewKeyc5, ?active}]),
+ ?line expect(25, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(26, [{NewKeyc5, ?destroy}]),
+ s([{NewKeyc3, 3}]),
+ ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
+ otp_1128().
+
+%% Req. system group
+simple_standard_test() ->
+ ?DBG("simple_standard_test -> entry",[]),
+ gn([[1,1]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3]]),
+ ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6]]),
+ ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1]]),
+ ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2]]),
+ ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1]]),
+ ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[1,3,6,1,2,1,1]]),
+ ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ gn([[sysDescr]]),
+ ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr,0]]),
+ ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
+ g([[sysDescr]]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{[sysDescr], noSuchObject}])),
+ g([[1,6,7,0]]),
+ ?line ?v1_2(expect(41, noSuchName, 1, any),
+ expect(3, [{[1,6,7,0], noSuchObject}])),
+ gn([[1,13]]),
+ ?line ?v1_2(expect(4, noSuchName,1, any),
+ expect(4, [{[1,13], endOfMibView}])),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+ g([[sysLocation, 0]]),
+ ?line expect(6, [{[sysLocation, 0], "new_value"}]),
+ io:format("Testing noSuchName and badValue...~n"),
+ s([{[sysServices,0], 3}]),
+ ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
+ s([{[sysLocation, 0], i, 3}]),
+ ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
+ ?DBG("simple_standard_test -> done",[]),
+ ok.
+
+%% This is run in the agent node
+db_notify_client(suite) -> [];
+db_notify_client(Config) when list(Config) ->
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
+ [SaNode,MgrNode,MibDir]),
+ snmpa_local_db:register_notify_client(self(),?MODULE),
+
+ %% This call (the manager) will issue to set operations, so
+ %% we expect to receive to notify(insert) calls.
+ try_test(db_notify_client_test),
+
+ ?DBG("await first notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
+ end,
+
+ ?DBG("await second notify",[]),
+ receive
+ {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
+ end,
+
+ snmpa_local_db:unregister_notify_client(self()).
+
+
+%% This is run in the manager node
+db_notify_client_test() ->
+ ?DBG("set first new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]),
+
+ ?DBG("set second new sysLocation",[]),
+ s([{[sysLocation, 0], "new_value"}]),
+ ?line expect(5, [{[sysLocation, 0], "new_value"}]).
+
+notify(Pid,What) ->
+ ?DBG("notify(~p,~p) -> called",[Pid,What]),
+ Pid ! {db_notify_test_reply,What}.
+
+
+%% Req: system group, OLD-SNMPEA-MIB, Klas1
+big_test() ->
+ ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
+ simple_standard_test(),
+
+ ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
+ gn([[klas1]]),
+ ?line expect(1, [{[fname,0], ""}]),
+ g([[fname,0]]),
+ ?line expect(2, [{[fname,0], ""}]),
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[fname,0]]),
+ ?line expect(4, [{[fname,0], "test set"}]),
+
+ ?DBG("big_test -> "
+ "testing next from last instance in master to subagent...",[]),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname,0], "test set"}]),
+ s([{[fname,0], s, ""}]),
+ ?line expect(52, [{[fname,0], ""}]),
+
+ table_test(),
+
+ ?DBG("big_test -> adding one row in subagent table",[]),
+ _FTab = [friendsEntry],
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {[friendsEntry, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ s([{[friendsEntry, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
+
+ otp_1131(),
+
+ ?DBG("big_test -> adding two rows in subagent table with special INDEX",
+ []),
+ s([{[kompissEntry, [1, 3]], s, "kompis3"},
+ {[kompissEntry, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry, [1, 3]],
+ [kompissEntry, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ gn([[kompissEntry, [1]],
+ [kompissEntry, [2]]]),
+ ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
+ {[kompissEntry, [2, 3]], ?active}]),
+ s([{[kompissEntry, [1, 2]], s, "kompis3"},
+ {[kompissEntry, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry, [1, 1]],
+ [kompissEntry, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
+ {[kompissEntry, [2, 2]], ?active}]),
+ s([{[kompissEntry, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
+ s([{[kompissEntry, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
+ ?DBG("big_test -> done",[]),
+ ok.
+
+%% Req. system group, Klas2, OLD-SNMPEA-MIB
+big_test_2() ->
+ p("Testing simple next/get/set @ master agent (2)..."),
+ simple_standard_test(),
+
+ p("Testing simple next/get/set @ subagent (2)..."),
+ gn([[klas2]]),
+ ?line expect(1, [{[fname2,0], ""}]),
+ g([[fname2,0]]),
+ ?line expect(2, [{[fname2,0], ""}]),
+ s([{[fname2,0], s, "test set"}]),
+ ?line expect(3, [{[fname2,0], "test set"}]),
+ g([[fname2,0]]),
+ ?line expect(4, [{[fname2,0], "test set"}]),
+
+ otp_1298(),
+
+ p("Testing next from last object in master to subagent (2)..."),
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(5, [{[fname2,0], "test set"}]),
+ gn([[1,1],
+ [?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[fname2,0], "test set"}]),
+
+ table_test(),
+
+ p("Adding one row in subagent table (2)"),
+ _FTab = [friendsEntry2],
+ s([{[friendsEntry2, [2, 3]], s, "kompis3"},
+ {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
+ ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry2, [2, 3]],
+ [friendsEntry2, [3, 3]]]),
+ ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
+ {[friendsEntry2, [3, 3]], ?active}]),
+ s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
+ ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
+
+ p("Adding two rows in subagent table with special INDEX (2)"),
+ s([{[kompissEntry2, [1, 3]], s, "kompis3"},
+ {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
+ ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?createAndGo}]),
+ g([[kompissEntry2, [1, 3]],
+ [kompissEntry2, [2, 3]]]),
+ ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ gn([[kompissEntry2, [1]],
+ [kompissEntry2, [2]]]),
+ ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
+ {[kompissEntry2, [2, 3]], ?active}]),
+ s([{[kompissEntry2, [1, 2]], s, "kompis3"},
+ {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
+ ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?createAndGo}]),
+ gn([[kompissEntry2, [1, 1]],
+ [kompissEntry2, [2, 1]]]),
+ ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
+ {[kompissEntry2, [2, 2]], ?active}]),
+ s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
+ ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
+ s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
+ ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
+ ok.
+
+%% Req. Test1
+multi_threaded_test() ->
+ p("Testing multi threaded agent..."),
+ g([[multiStr,0]]),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(1, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "pelle"}]),
+ ?line expect(2, [{[sysLocation, 0], "pelle"}]),
+ Pid ! continue,
+ ?line expect(3, [{[multiStr,0], "ok"}]),
+
+ s([{[multiStr, 0], s, "block"}]),
+ Pid2 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(4, [{[sysUpTime,0], any}]),
+ g([[multiStr,0]]),
+ Pid3 = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(5, [{[sysUpTime,0], any}]),
+ s([{[sysLocation, 0], s, "kalle"}]),
+ Pid3 ! continue,
+ ?line expect(6, [{[multiStr,0], "ok"}]),
+ Pid2 ! continue,
+ ?line expect(7, [{[multiStr,0], "block"}]),
+ ?line expect(8, [{[sysLocation,0], "kalle"}]).
+
+%% Req. Test1, TestTrapv2
+mt_trap_test(MA) ->
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ snmpa:send_trap(MA, mtTrap, "standard trap"),
+ Pid = get_multi_pid(),
+ g([[sysUpTime,0]]),
+ ?line expect(2, [{[sysUpTime,0], any}]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ Pid ! continue,
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [2]},
+ {[multiStr,0], "ok"}]).
+
+
+get_multi_pid() ->
+ get_multi_pid(10).
+get_multi_pid(0) ->
+ ?line ?FAIL(no_global_name);
+get_multi_pid(N) ->
+ sleep(1000),
+ case global:whereis_name(snmp_multi_tester) of
+ Pid when pid(Pid) -> Pid;
+ _ -> get_multi_pid(N-1)
+ end.
+
+%% Req. Test1
+types_v2_test() ->
+ p("Testing v2 types..."),
+
+ s([{[bits1,0], 2#10}]),
+ ?line expect(1, [{[bits1,0], ?str(2#10)}]),
+ g([[bits1,0]]),
+ ?line expect(2, [{[bits1,0], ?str(2#101)}]),
+
+ s([{[bits2,0], 2#11000000110}]),
+ ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
+ g([[bits2,0]]),
+ ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
+
+ g([[bits3,0]]),
+ ?line expect(50, genErr, 1, any),
+
+ g([[bits4,0]]),
+ ?line expect(51, genErr, 1, any),
+
+ s([{[bits1,0], s, [2#10]}]),
+ ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
+
+ s([{[bits2,0], 2#11001001101010011}]),
+ ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%% Req. Test1
+implied_test(MA) ->
+ ?LOG("implied_test -> start",[]),
+ p("Testing IMPLIED..."),
+
+ snmpa:verbosity(MA,trace),
+ snmpa:verbosity(MA,trace),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = "apa",
+ Idx2 = "qq",
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
+ ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
+ {[testDescr, Idx1], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
+ ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
+ {[testDescr, Idx2], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr)",[]),
+ gn([[testDescr]]),
+ ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
+ gn([[testDescr,Idx1]]),
+ ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
+ s([{[testStatus, Idx1], i, ?destroy}]),
+ ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
+ s([{[testStatus, Idx2], i, ?destroy}]),
+ ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
+
+ %% Try the same in other table
+ Idx3 = [1, "apa"],
+ Idx4 = [1, "qq"],
+ ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
+ ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
+ {[testDescr2, Idx3], "row 1"}]),
+ ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
+ ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
+ {[testDescr2, Idx4], "row 2"}]),
+ ?DBG("implied_test -> get-next(testDescr2)",[]),
+ gn([[testDescr2]]),
+ ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
+ ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
+ gn([[testDescr2,Idx3]]),
+ ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
+
+ % Delete the rows
+ ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
+ s([{[testStatus2, Idx3], i, ?destroy}]),
+ ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
+ ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
+ s([{[testStatus2, Idx4], i, ?destroy}]),
+ ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
+
+ snmpa:verbosity(MA,log),
+
+ ?LOG("implied_test -> done",[]).
+
+
+
+%% Req. Test1
+sparse_table_test() ->
+ p("Testing sparse table..."),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ s([{[sparseStatus, Idx1], i, ?createAndGo},
+ {[sparseDescr, Idx1], s, "row 1"}]),
+ ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
+ {[sparseDescr, Idx1], "row 1"}]),
+ s([{[sparseStatus, Idx2], i, ?createAndGo},
+ {[sparseDescr, Idx2], s, "row 2"}]),
+ ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
+ {[sparseDescr, Idx2], "row 2"}]),
+ ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
+ [sparseStatus,Idx1], [sparseStatus,Idx2]]),
+ gb(0,5,[[sparseIndex]])),
+ ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
+ {[sparseDescr,Idx2], "row 2"},
+ {[sparseStatus,Idx1], ?active},
+ {[sparseStatus,Idx2], ?active},
+ {[sparseStr,0], "slut"}]),
+ % Delete the rows
+ s([{[sparseStatus, Idx1], i, ?destroy}]),
+ ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
+ s([{[sparseStatus, Idx2], i, ?destroy}]),
+ ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
+
+
+%% Req. Test1
+cnt_64_test(MA) ->
+ ?LOG("start cnt64 test (~p)",[MA]),
+ snmpa:verbosity(MA,trace),
+ ?LOG("start cnt64 test",[]),
+ p("Testing Counter64, and at the same time, RowStatus is not last column"),
+
+ ?DBG("get cnt64",[]),
+ g([[cnt64,0]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(1, noSuchName, 1, any),
+ expect(1, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("get-next cnt64",[]),
+ gn([[cnt64]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
+ expect(2, [{[cnt64,0],18446744073709551615}])),
+ ?DBG("send cntTrap",[]),
+ snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
+ {cnt64, 10},
+ {sysLocation, "here"}]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ {[sysLocation,0], "here"}]),
+ expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [1]},
+ {[sysContact,0], "pelle"},
+ {[cnt64,0], 10},
+ {[sysLocation,0], "here"}])),
+
+ %% Create two rows, check that they are get-nexted in correct order.
+ Idx1 = 1,
+ Idx2 = 2,
+ ?DBG("create row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
+ ?DBG("create row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?createAndGo}]),
+ ?DBG("await response",[]),
+ ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
+
+ ?DBG("get-next (cntIndex)",[]),
+ gn([[cntIndex]]),
+ ?DBG("await response",[]),
+ ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
+ expect(3, [{[cntCnt,Idx1], 0}])),
+ % Delete the rows
+ ?DBG("delete row (cntStatus): ~p",[Idx1]),
+ s([{[cntStatus, Idx1], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
+ ?DBG("delete row (cntStatus): ~p",[Idx2]),
+ s([{[cntStatus, Idx2], i, ?destroy}]),
+ ?DBG("await response",[]),
+ ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
+ catch snmpa:verbosity(MA,log),
+ ?DBG("done",[]),
+ ok.
+
+%% Req. Test1
+opaque_test() ->
+ p("Testing Opaque datatype..."),
+ g([[opaqueObj,0]]),
+ ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
+
+%% Req. OLD-SNMPEA-MIB
+api_test(MaNode) ->
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [intAgentIpAddress]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
+ oid_to_name, [OID]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [[1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp,
+ int_to_enum, ['RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp,
+ enum_to_int, ['xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
+ ?line case snmp:date_and_time() of
+ List when list(List), length(List) == 8 -> ok;
+ List when list(List), length(List) == 11 -> ok
+ end.
+
+%% Req. Klas3
+api_test2() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]),
+ g([[fname4,0]]),
+ ?line expect(2, [{[fname4,0], 1}]).
+
+api_test3() ->
+ g([[fname3,0]]),
+ ?line expect(1, [{[fname3,0], "ok"}]).
+
+
+unreg_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[snmpInPkts, 0], any}]).
+
+load_test() ->
+ gn([[?v1_2(sysServices, sysORLastChange),0]]),
+ ?line expect(1, [{[fname,0], ""}]).
+
+%% Req. Klas1
+load_test_sa() ->
+ gn([[?v1_2(sysServices,sysORLastChange), 0]]),
+ ?line expect(1, [{[fname,0], any}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_get() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
+ [sysName,0]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,0], "test"}]),
+ g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
+ ?line ?v1_2(expect(2, noSuchName, [1,4], any),
+ expect(2, [{[1,3,7,1], noSuchObject},
+ {Key1c4, 2},
+ {[sysDescr,0], "Erlang SNMP agent"},
+ {[1,3,7,2], noSuchObject},
+ {Key1c3, 2},
+ {[sysDescr,0], "Erlang SNMP agent"}])).
+
+%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
+do_mul_get_err() ->
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
+ ?line ?v1_2(expect(1, noSuchName, 5, any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname,0], "test set"},
+ {Key1c3, 2},
+ {[sysName,2], noSuchInstance}])),
+ g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[fname3,0], noSuchObject},
+ {Key1c3, 2},
+ {[sysName,1], noSuchInstance}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2}, {[fname,0], "test set"},
+ {Key1c3, 2}, {[sysName,0], "test"}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_next_err() ->
+ Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
+ Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
+ Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
+ Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
+ s([{[fname,0], s, "test set"}]),
+ ?line expect(3, [{[fname,0], "test set"}]),
+ gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
+ ?line ?v1_2(expect(1, noSuchName, [3,5], any),
+ expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {Key1c4, 2},
+ {[1,3,6,999], endOfMibView},
+ {[fname,0], "test set"},
+ {[1,3,90], endOfMibView},
+ {Key1c3, 2},
+ {[sysName,0], "test"}])).
+
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set() ->
+ p("Adding one row in subagent table, and one in master table"),
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
+ {NewKeyc3, 2},
+ {[sysLocation,0], "new_value"},
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ g([[friendsEntry, [2, 3]],
+ [sysLocation,0],
+ [friendsEntry, [3, 3]]]),
+ ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
+ {[sysLocation,0], "new_value"},
+ {[friendsEntry, [3, 3]], ?active}]),
+ g([NewKeyc4]),
+ ?line expect(3, [{NewKeyc4, 2}]),
+ s([{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]),
+ ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
+ {NewKeyc5, ?destroy}]).
+
+%% Req. system group, Klas1, OLD-SNMPEA-MIB
+do_mul_set_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ p("Adding one row in subagent table, and one in master table"),
+ s([{[friendsEntry, [2, 3]], s, "kompis3"},
+ {NewKeyc3, 2},
+ {[sysUpTime,0], 45}, % sysUpTime (readOnly)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2},
+ {[friendsEntry, [3, 3]], ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
+ g([[friendsEntry, [2, 3]]]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(3, noSuchName, 1, any),
+ expect(3, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB
+sa_mib() ->
+ g([[sa, [2,0]]]),
+ ?line expect(1, [{[sa, [2,0]], 3}]),
+ s([{[sa, [1,0]], s, "sa_test"}]),
+ ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+
+ma_trap1(MA) ->
+ snmpa:send_trap(MA, testTrap2, "standard trap"),
+ ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ snmpa:send_trap(MA, testTrap1, "standard trap"),
+ ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]).
+
+ma_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+
+ma_v2_2_v1_trap2(MA) ->
+ snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
+ {ifAdminStatus, [1], 1},
+ {ifOperStatus, [1], 2}]),
+ ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]).
+
+sa_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "pelle"},
+ {[sa, [1,0]], "sa_test"}]).
+
+sa_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]).
+
+ma_v2_trap1(MA) ->
+ ?DBG("ma_v2_traps -> entry with MA = ~p => "
+ "send standard trap: testTrapv22",[MA]),
+ snmpa:send_trap(MA, testTrapv22, "standard trap"),
+ ?line expect(1, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
+ snmpa:send_trap(MA, testTrapv21, "standard trap"),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmp ++ [1]}]).
+
+ma_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"}]).
+
+%% Note: This test case takes a while... actually a couple of minutes.
+ma_v2_inform1(MA) ->
+ ?DBG("ma_v2_inform -> entry with MA = ~p => "
+ "send notification: testTrapv22",[MA]),
+ ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag1, self()},
+ "standard inform", []),
+ ?line expect(1, {inform, true},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag1, [_]} ->
+ ok;
+ {snmp_targets, tag1, Addrs1} ->
+ ?line ?FAIL({bad_addrs, Addrs1})
+ after
+ 5000 ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag1, {got_response, _}} ->
+ ok;
+ {snmp_notification, tag1, {no_response, _}} ->
+ ?line ?FAIL(no_response)
+ after
+ 20000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag1) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end,
+
+ %%
+ %% -- The rest is possibly erroneous...
+ %%
+
+ ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
+ snmpa:send_notification(MA, testTrapv22, {tag2, self()},
+ "standard inform", []),
+ ?line expect(2, {inform, false},
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?DBG("ma_v2_inform -> await targets",[]),
+ receive
+ {snmp_targets, tag2, [_]} ->
+ ok;
+ {snmp_targets, tag2, Addrs2} ->
+ ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
+ ?line ?FAIL({bad_addrs, Addrs2})
+ after
+ 5000 ->
+ ?line ?FAIL(nothing_at_all)
+ end,
+ ?DBG("ma_v2_inform -> await notification",[]),
+ receive
+ {snmp_notification, tag2, {got_response, _}} ->
+ ?line ?FAIL(got_response);
+ {snmp_notification, tag2, {no_response, _}} ->
+ ok
+ after
+ 240000 ->
+ ?ERR("ma_v2_inform1 -> "
+ "awaiting snmp_notification(tag2) timeout",[]),
+ ?line ?FAIL(nothing_at_all)
+ end.
+
+
+ma_v1_2_v2_trap(MA) ->
+ snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
+ ?line expect(2, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
+ {[ifIndex, 1], 1},
+ {[snmpTrapEnterprise, 0], [1,2,3]}]).
+
+
+ma_v1_2_v2_trap2(MA) ->
+ snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
+ ?line expect(3, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]},
+ {[system, [4,0]], "pelle"},
+ {[snmpTrapEnterprise, 0], ?system}]).
+
+
+sa_v1_2_v2_trap1(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap"),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+sa_v1_2_v2_trap2(SA) ->
+ snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+sa_v1_2_v2_trap3(SA) ->
+ snmpa:send_trap(SA, saTrap2, "standard trap",
+ [{intViewSubtree, [4], [1,2,3,4]}]),
+ ?line expect(4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]).
+
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_bad_value() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 5}, % badValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, badValue, 2, any),
+ s([{NewKeyc3, 2},
+ {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
+ {NewKeyc5, ?createAndGo},
+ {NewKeyc4, 2}]),
+ ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
+ g([NewKeyc4]),
+ ?line ?v1_2(expect(2, noSuchName, 1, any),
+ expect(2, [{NewKeyc4, noSuchInstance}])).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_errs_gen_err() ->
+ NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
+ NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
+ NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
+ s([{NewKeyc3, 2},{NewKeyc4, 2},
+ {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
+ ?line expect(1, genErr, 4, any),
+% The row might have been added; we don't know.
+% (as a matter of fact we do - it is added, because the agent
+% first sets its own vars, and then th SAs. Lets destroy it.
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(2, [{NewKeyc5, ?destroy}]).
+
+%% Req. SA-MIB, OLD-SNMPEA-MIB
+sa_too_big() ->
+ g([[sa, [4,0]]]),
+ ?line expect(1, tooBig).
+
+%% Req. Klas1, system group, snmp group (v1/v2)
+next_across_sa() ->
+ gn([[sysDescr],[klas1,5]]),
+ ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
+ {[snmpInPkts, 0], any}]).
+
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
+%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
+%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
+%% Req. Klas3, Klas4
+undo_test() ->
+ s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
+ s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
+ ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
+ ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
+% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+% it depends on which order the agent traverses the varbind list.
+% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
+% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
+ s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
+ ?line expect(6, genErr, 2, any).
+
+%% Req. Klas3, Klas4
+bad_return() ->
+ g([[fStatus4,4],
+ [fName4,4]]),
+ ?line expect(4, genErr, 2, any),
+ g([[fStatus4,5],
+ [fName4,5]]),
+ ?line expect(5, genErr, 1, any),
+ g([[fStatus4,6],
+ [fName4,6]]),
+ ?line expect(6, genErr, 2, any),
+ gn([[fStatus4,7],
+ [fName4,7]]),
+ ?line expect(7, genErr, 2, any),
+ gn([[fStatus4,8],
+ [fName4,8]]),
+ ?line expect(8, genErr, 1, any),
+ gn([[fStatus4,9],
+ [fName4,9]]),
+ ?line expect(9, genErr, 2, any).
+
+
+%%%-----------------------------------------------------------------
+%%% Test the implementation of standard mibs.
+%%% We should *at least* try to GET all variables, just to make
+%%% sure the instrumentation functions work.
+%%% Note that many of the functions in the standard mib is
+%%% already tested by the normal tests.
+%%%-----------------------------------------------------------------
+
+
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v1.
+%% o Test the counters and control objects in SNMP-STANDARD-MIB
+%%-----------------------------------------------------------------
+snmp_standard_mib(suite) -> [];
+snmp_standard_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?DBG("snmp_standard_mib -> std_mib_init", []),
+ try_test(std_mib_init),
+
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v2),
+ ?DBG("snmp_standard_mib -> std_mib_read", []),
+ try_test(std_mib_read),
+ put(vsn, v1),
+
+ ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+ ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+ ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
+ try_test(std_mib_write, [], [{community, "public"}]),
+ ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
+ try_test(std_mib_asn_err),
+ ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
+ try_test(std_mib_c, [Bad]),
+ ?DBG("snmp_standard_mib -> std_mib_a", []),
+ try_test(standard_mib_a),
+
+ ?DBG("snmp_standard_mib -> std_mib_finish", []),
+ try_test(std_mib_finish),
+ ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
+ try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_a() ->
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ ?line OutPkts2 = OutPkts + 1,
+ %% There are some more counters we could test here, but it's not that
+ %% important, since they are removed from SNMPv2-MIB.
+ ok.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_init() ->
+ %% disable authentication failure traps. (otherwise w'd get many of
+ %% them - this is also a test to see that it works).
+ s([{[snmpEnableAuthenTraps,0], 2}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_finish() ->
+ %% enable again
+ s([{[snmpEnableAuthenTraps,0], 1}]),
+ ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+
+%% Req. SNMP-STANDARD-MIB
+standard_mib_test_finish() ->
+ %% force a authenticationFailure
+ std_mib_write(),
+ %% check that we got a trap
+ ?line expect(2, trap, [1,2,3], 4, 0, []).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_read() ->
+ ?DBG("std_mib_read -> entry", []),
+ g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
+ ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
+ ?line expect(1, timeout). % make sure we don't get a trap!
+
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_write() ->
+ ?DBG("std_mib_write -> entry", []),
+ s([{[sysLocation, 0], "new_value"}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_asn_err() ->
+ snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
+
+%%-----------------------------------------------------------------
+%% For this test, the agent is configured for v2 and v3.
+%% o Test the counters and control objects in SNMPv2-MIB
+%%-----------------------------------------------------------------
+snmpv2_mib_2(suite) -> [];
+snmpv2_mib_2(Config) when list(Config) ->
+ ?LOG("snmpv2_mib_2 -> start",[]),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?DBG("snmpv2_mib_2 -> standard mib init",[]),
+ try_test(std_mib_init),
+
+ ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
+ InBadVsns = try_test(std_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
+ put(vsn, v1),
+ try_test(std_mib_read),
+
+ ?DBG("snmpv2_mib_2 -> bad version read",[]),
+ put(vsn, v2),
+ Bad = try_test(std_mib_b, [InBadVsns]),
+
+ ?DBG("snmpv2_mib_2 -> read with bad community",[]),
+ try_test(std_mib_read, [], [{community, "bad community"}]),
+
+ ?DBG("snmpv2_mib_2 -> write with public community",[]),
+ try_test(std_mib_write, [], [{community, "public"}]),
+
+ ?DBG("snmpv2_mib_2 -> asn err",[]),
+ try_test(std_mib_asn_err),
+
+ ?DBG("snmpv2_mib_2 -> check counters",[]),
+ try_test(std_mib_c, [Bad]),
+
+ ?DBG("snmpv2_mib_2 -> get som counters",[]),
+ try_test(snmpv2_mib_a),
+
+ ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
+ try_test(std_mib_finish),
+
+ ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
+ "then disable auth traps",[]),
+ try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
+
+ ?LOG("snmpv2_mib_2 -> done",[]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_3(suite) -> [];
+snmpv2_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ InBadVsns = try_test(std_mib_a),
+ put(vsn, v1),
+ try_test(std_mib_read),
+ put(vsn, v3),
+ _Bad = try_test(std_mib_b, [InBadVsns]),
+ try_test(snmpv2_mib_a),
+
+ try_test(std_mib_finish).
+
+-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_test_finish() ->
+ %% force a authenticationFailure
+ ?DBG("ma_v2_inform -> write to std mib",[]),
+ std_mib_write(),
+
+ %% check that we got a trap
+ ?DBG("ma_v2_inform -> await trap",[]),
+ ?line expect(2, v2trap, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0], ?authenticationFailure}]),
+
+ %% and the the inform
+ ?DBG("ma_v2_inform -> await inform",[]),
+ ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
+ {[snmpTrapOID,0],?authenticationFailure}]).
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_a() ->
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+
+ ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ InBadVsns.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_b(InBadVsns) ->
+ ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ ?line InBadVsns2 = InBadVsns + 1,
+ ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ ?line InPkts2 = InPkts + 1,
+ ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
+ get_req(4, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
+
+%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
+std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
+ ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ get_req(1, [[snmpInBadCommunityNames,0],
+ [snmpInBadCommunityUses,0],
+ [snmpInASNParseErrs, 0]]),
+ ?line InBadCommunityNames2 = InBadCommunityNames + 1,
+ ?line InBadCommunityUses2 = InBadCommunityUses + 1,
+ ?line InASNErrs2 = InASNErrs + 1.
+
+%% Req. SNMPv2-MIB
+snmpv2_mib_a() ->
+ ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
+ s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
+ ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
+ {[sysLocation, 0], "val2"}]),
+ s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
+ ?line expect(4, inconsistentValue, 2,
+ [{[sysLocation, 0], "val3"},
+ {[snmpSetSerialNo,0], SetSerial}]),
+ ?line ["val2"] = get_req(5, [[sysLocation,0]]).
+
+
+%%-----------------------------------------------------------------
+%% o Bad community uses/name is tested already
+%% in SNMPv2-MIB and STANDARD-MIB.
+%% o Test add/deletion of rows.
+%%-----------------------------------------------------------------
+snmp_community_mib(suite) -> [];
+snmp_community_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ try_test(snmp_community_mib),
+ ?line unload_master("SNMP-COMMUNITY-MIB").
+
+snmp_community_mib_2(X) -> snmp_community_mib(X).
+
+%% Req. SNMP-COMMUNITY-MIB
+snmp_community_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o Test engine boots / time
+%%-----------------------------------------------------------------
+snmp_framework_mib(suite) -> [];
+snmp_framework_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ try_test(snmp_framework_mib),
+ ?line unload_master("SNMP-FRAMEWORK-MIB").
+
+snmp_framework_mib_2(X) -> snmp_framework_mib(X).
+
+snmp_framework_mib_3(suite) -> [];
+snmp_framework_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(snmp_framework_mib).
+
+
+%% Req. SNMP-FRAMEWORK-MIB
+snmp_framework_mib() ->
+ ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ sleep(5000),
+ ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ if
+ EngineTime+7 < EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ EngineTime+4 > EngineTime2 ->
+ ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ true -> ok
+ end,
+ ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ [Boots] when integer(Boots) -> ok;
+ Else -> ?FAIL(Else)
+ end,
+ ok.
+
+%%-----------------------------------------------------------------
+%% o Test the counters
+%%-----------------------------------------------------------------
+snmp_mpd_mib_3(suite) -> [];
+snmp_mpd_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ UnknownPDUHs = try_test(snmp_mpd_mib_a),
+ try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
+ try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
+
+
+%% Req. SNMP-MPD-MIB
+snmp_mpd_mib_a() ->
+ ?line [UnknownSecs, InvalidMsgs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0]]),
+ Pdu = #pdu{type = 'get-request',
+ request_id = 23,
+ error_status = noError,
+ error_index = 0,
+ varbinds = []},
+ SPdu = #scopedPdu{contextEngineID = "agentEngine",
+ contextName = "",
+ data = Pdu},
+ ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
+ V3Hdr1 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [7],
+ msgSecurityModel = 23, % bad sec model
+ msgSecurityParameters = []},
+ V3Hdr2 = #v3_hdr{msgID = 21,
+ msgMaxSize = 484,
+ msgFlags = [6], % bad flag combination
+ msgSecurityModel = 3,
+ msgSecurityParameters = []},
+ Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
+ data = SPDUBytes},
+ Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
+ data = SPDUBytes},
+ ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
+ ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
+ snmp_test_mgr:send_bytes(MsgBytes1),
+ snmp_test_mgr:send_bytes(MsgBytes2),
+
+ ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
+ get_req(1, [[snmpUnknownSecurityModels,0],
+ [snmpInvalidMsgs,0],
+ [snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownSecs2 = UnknownSecs + 1,
+ ?line InvalidMsgs2 = InvalidMsgs + 1,
+ UnknownPDUHs.
+
+-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
+snmp_mpd_mib_b() ->
+ g([[sysUpTime,0]]),
+ ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
+
+
+snmp_mpd_mib_c(UnknownPDUHs) ->
+ ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
+ ?line UnknownPDUHs2 = UnknownPDUHs + 1.
+
+
+snmp_target_mib(suite) -> [];
+snmp_target_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ try_test(snmp_target_mib),
+ ?line unload_master("SNMP-TARGET-MIB").
+
+snmp_target_mib_2(X) -> snmp_target_mib(X).
+
+snmp_target_mib_3(X) -> snmp_target_mib(X).
+
+snmp_target_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+snmp_notification_mib(suite) -> [];
+snmp_notification_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ try_test(snmp_notification_mib),
+ ?line unload_master("SNMP-NOTIFICATION-MIB").
+
+snmp_notification_mib_2(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib_3(X) -> snmp_notification_mib(X).
+
+snmp_notification_mib() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ nyi.
+
+%%-----------------------------------------------------------------
+%% o add/delete views and try them
+%% o try boundaries
+%%-----------------------------------------------------------------
+snmp_view_based_acm_mib(suite) -> [];
+snmp_view_based_acm_mib(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master("Test2"),
+ snmp_view_based_acm_mib(),
+ ?line unload_master("Test2"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
+
+snmp_view_based_acm_mib() ->
+ snmpa:verbosity(net_if,trace),
+ snmpa:verbosity(master_agent,trace),
+ ?LOG("start snmp_view_based_acm_mib test",[]),
+ %% The user "no-rights" is present in USM, and is mapped to security
+ %% name 'no-rights", which is not present in VACM.
+ %% So, we'll add rights for it, try them and delete them.
+ %% We'll give "no-rights" write access to tDescr.0 and read access
+ %% to tDescr2.0
+ %% These are the options we'll use to the mgr
+ Opts = [{user, "no-rights"}, {community, "no-rights"}],
+ %% Find the valid secmodel, and one invalid secmodel.
+ {SecMod, InvSecMod} =
+ case get(vsn) of
+ v1 -> {?SEC_V1, ?SEC_V2C};
+ v2 -> {?SEC_V2C, ?SEC_USM};
+ v3 -> {?SEC_USM, ?SEC_V1}
+ end,
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Now, add a mapping from "no-rights" -> "no-rights-group"
+ GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
+ GRow1 =
+ [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
+ {GRow1Status, ?createAndGo}],
+ ?DBG("set '~p'",[GRow1]),
+ ?line try_test(do_set, [GRow1]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create a mapping for another sec model, and make sure it dosn't
+ %% give us access
+ GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
+ GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
+ {GRow2Status, ?createAndGo}],
+
+ ?DBG("set '~p'",[GRow2]),
+ ?line try_test(do_set, [GRow2]),
+
+ ?DBG("assign rights for 'no-rights'",[]),
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [GRow2Status]),
+
+ RVName = "rv_name",
+ WVName = "wv_name",
+
+ %% Access row
+ ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
+ ARow1Status = [vacmAccessStatus, ARow1Idx],
+ ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
+ {[vacmAccessReadViewName, ARow1Idx], RVName},
+ {[vacmAccessWriteViewName, ARow1Idx], WVName},
+ {ARow1Status, ?createAndGo}],
+
+ %% This access row would give acces, if InvSecMod was valid.
+ ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
+ ARow2Status = [vacmAccessStatus, ARow2Idx],
+ ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
+ {[vacmAccessReadViewName, ARow2Idx], "internet"},
+ {[vacmAccessWriteViewName, ARow2Idx], "internet"},
+ {ARow2Status, ?createAndGo}],
+
+ ?line try_test(do_set, [ARow2]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete that row
+ ?line try_test(del_row, [ARow2Status]),
+
+
+ %% Add valid row
+ ?line try_test(do_set, [ARow1]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Create the view family
+ VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
+ VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
+ VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
+ VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
+ VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
+ VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
+ VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
+ VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
+
+ ?line try_test(add_row, [VRow1Status]),
+ ?line try_test(add_row, [VRow2Status]),
+ ?line try_test(add_row, [VRow3Status]),
+
+ %% We're supposed to have access now...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Change Row3 to Row4
+ ?line try_test(del_row, [VRow3Status]),
+ ?line try_test(add_row, [VRow4Status]),
+
+ %% We should still have access...
+ ?line try_test(use_rights, [], Opts),
+
+ %% Delete rows
+ ?line try_test(del_row, [GRow1Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+
+ %% Delete rest of rows
+ ?line try_test(del_row, [ARow1Status]),
+ ?line try_test(del_row, [VRow1Status]),
+ ?line try_test(del_row, [VRow2Status]),
+ ?line try_test(del_row, [VRow4Status]),
+
+ ?line try_test(use_no_rights, [], Opts),
+ snmpa:verbosity(master_agent,log).
+
+do_set(Row) ->
+ s(Row),
+ expect(1, Row).
+
+add_row(RowStatus) ->
+ s([{RowStatus, ?createAndGo}]),
+ expect(1, [{RowStatus, ?createAndGo}]).
+
+del_row(RowStatus) ->
+ s([{RowStatus, ?destroy}]),
+ expect(1, [{RowStatus, ?destroy}]).
+
+
+
+use_no_rights() ->
+ g([[xDescr,0]]),
+ ?v1_2_3(expect(11, noSuchName, 1, any),
+ expect(12, [{[xDescr,0], noSuchObject}]),
+ expect(13, authorizationError, 1, any)),
+ g([[xDescr2,0]]),
+ ?v1_2_3(expect(21, noSuchName, 1, any),
+ expect(22, [{[xDescr2,0], noSuchObject}]),
+ expect(23, authorizationError, 1, any)),
+ gn([[xDescr]]),
+ ?v1_2_3(expect(31, noSuchName, 1, any),
+ expect(32, [{[xDescr], endOfMibView}]),
+ expect(33, authorizationError, 1, any)),
+ s([{[xDescr,0], "tryit"}]),
+ ?v1_2_3(expect(41, noSuchName, 1, any),
+ expect(42, noAccess, 1, any),
+ expect(43, authorizationError, 1, any)).
+
+
+use_rights() ->
+ g([[xDescr,0]]),
+ expect(1, [{[xDescr,0], any}]),
+ g([[xDescr2,0]]),
+ expect(2, [{[xDescr2,0], any}]),
+ s([{[xDescr,0], "tryit"}]),
+ expect(3, noError, 0, any),
+ g([[xDescr,0]]),
+ expect(4, [{[xDescr,0], "tryit"}]).
+
+mk_ln(X) ->
+ [length(X) | X].
+
+%%-----------------------------------------------------------------
+%% o add/delete users and try them
+%% o test all secLevels
+%% o test all combinations of protocols
+%% o try bad ops; check counters
+%%-----------------------------------------------------------------
+snmp_user_based_sm_mib_3(suite) -> [];
+snmp_user_based_sm_mib_3(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ _AgentDir = ?config(agent_dir, Config),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+
+ %% The newUser used here already has VACM access.
+
+ %% Add a new user in the simplest way; just createAndGo
+ try_test(v3_sync, [[{usm_add_user1, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new user
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
+ DesKey1 = lists:sublist(ShaKey1, 16),
+
+ %% Change the new user's keys - 1
+ try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ MgrDir = ?config(mgr_dir, Config),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+
+ ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
+ DesKey2 = lists:sublist(ShaKey2, 16),
+
+ %% Change the new user's keys - 2
+ ?line try_test(v3_sync,
+ [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+
+ %% Try to use the new keys
+ reset_usm_mgr(MgrDir),
+ ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
+ ?line load_master("Test2"),
+ ?line try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Change the new user's keys - 3
+ ?line try_test(v3_sync,
+ [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try to use the new keys
+ ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ ?line load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
+ [{sec_level, authPriv}, {user, "newUser"}]),
+ ?line unload_master("Test2"),
+ reset_usm_mgr(MgrDir),
+
+ %% Try some read requests
+ ?line try_test(v3_sync, [[{usm_read, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Delete the new user
+ ?line try_test(v3_sync, [[{usm_del_user, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ %% Try some bad requests
+ ?line try_test(v3_sync, [[{usm_bad, []}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
+
+ ?line unload_master("SNMP-USER-BASED-SM-MIB").
+
+-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
+
+usm_add_user1() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+usm_use_user() ->
+ v2_proc().
+
+
+%% Change own public keys
+usm_key_change1(ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_shaxxxxxxxxxx",
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ "passwd_desxxxxxx",
+ DesKey),
+ Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change own private keys
+usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs1),
+ ?line expect(1, Vbs1).
+
+%% Change other's public keys
+usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldShaKey,
+ ShaKey),
+ DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
+ OldDesKey,
+ DesKey),
+ Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
+ s(Vbs1),
+ ?line expect(1, noAccess, 1, any),
+ Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs2),
+ ?line expect(2, noAccess, 1, any),
+
+
+ Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
+ {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
+ s(Vbs3),
+ ?line expect(1, Vbs3).
+
+usm_read() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ ?line g([[usmUserSecurityName, NewRowIndex],
+ [usmUserCloneFrom, NewRowIndex],
+ [usmUserAuthKeyChange, NewRowIndex],
+ [usmUserOwnAuthKeyChange, NewRowIndex],
+ [usmUserPrivKeyChange, NewRowIndex],
+ [usmUserOwnPrivKeyChange, NewRowIndex]]),
+ ?line expect(1,
+ [{[usmUserSecurityName, NewRowIndex], "newUser"},
+ {[usmUserCloneFrom, NewRowIndex], [0,0]},
+ {[usmUserAuthKeyChange, NewRowIndex], ""},
+ {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
+ {[usmUserPrivKeyChange, NewRowIndex], ""},
+ {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
+ ok.
+
+
+
+usm_del_user() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs1),
+ ?line expect(1, Vbs1),
+ ok.
+
+-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
+
+-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
+
+-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
+
+-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
+
+-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
+
+-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
+
+usm_bad() ->
+ NewRowIndex = [11,"agentEngine", 7, "newUser"],
+ RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
+ Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs1),
+ ?line expect(1, inconsistentName, 1, any),
+
+ RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs2),
+ ?line expect(2, wrongValue, 1, any),
+
+ RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
+ Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
+ {[usmUserStatus, NewRowIndex], ?createAndGo}],
+ ?line s(Vbs3),
+ ?line expect(3, Vbs3),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
+ ?line expect(4, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
+ ?line expect(5, inconsistentValue, 1, any),
+ ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
+ ?line expect(6, wrongValue, 1, any),
+ ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
+ ?line expect(7, wrongValue, 1, any),
+
+ Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
+ ?line s(Vbs4),
+ ?line expect(1, Vbs4),
+
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Loop through entire MIB, to make sure that all instrum. funcs
+%% works.
+%% Load all std mibs that are not loaded by default.
+%%-----------------------------------------------------------------
+loop_mib(suite) -> [];
+loop_mib(Config) when list(Config) ->
+ ?LOG("loop_mib -> initiate case",[]),
+ %% snmpa:verbosity(master_agent,debug),
+ %% snmpa:verbosity(mib_server,info),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?DBG("loop_mib -> try",[]),
+ try_test(loop_mib_1),
+ ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ %% snmpa:verbosity(master_agent,log),
+ %% snmpa:verbosity(mib_server,silence),
+ ?LOG("loop_mib -> done",[]).
+
+
+loop_mib_2(suite) -> [];
+loop_mib_2(Config) when list(Config) ->
+ ?LOG("loop_mib_2 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_2 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_2 -> load mibs",[]),
+ ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ ?line load_master_std("SNMP-MPD-MIB"),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_2 -> unload mibs",[]),
+ ?line unload_master("SNMP-COMMUNITY-MIB"),
+ ?line unload_master("SNMP-MPD-MIB"),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?LOG("loop_mib_2 -> done",[]).
+
+
+loop_mib_3(suite) -> [];
+loop_mib_3(Config) when list(Config) ->
+ ?LOG("loop_mib_3 -> initiate case",[]),
+ {SaNode, MgrNode, MibDir} = init_case(Config),
+ ?DBG("loop_mib_3 -> ~n"
+ "\tSaNode: ~p~n"
+ "\tMgrNode: ~p~n"
+ "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
+ ?DBG("loop_mib_3 -> load mibs",[]),
+ ?line load_master_std("SNMP-TARGET-MIB"),
+ ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ try_test(loop_mib_2),
+ ?DBG("loop_mib_3 -> unload mibs",[]),
+ ?line unload_master("SNMP-TARGET-MIB"),
+ ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ ?line unload_master("SNMP-USER-BASED-SM-MIB"),
+ ?LOG("loop_mib_3 -> done",[]).
+
+
+%% Req. As many mibs all possible
+loop_mib_1() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_1([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_1(Oid, N) ->
+ ?DBG("loop_it_1 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_1 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_1 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_1(NOid, N+1);
+ #pdu{type='get-response', error_status=noSuchName, error_index=1,
+ varbinds=[_]} ->
+ ?DBG("loop_it_1 -> done",[]),
+ N;
+
+ #pdu{type = Type, error_status = Err, error_index = Idx,
+ varbinds = Vbs} ->
+ exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
+ end.
+
+%% Req. As many mibs all possible
+loop_mib_2() ->
+ ?DBG("loop_mib_1 -> entry",[]),
+ N = loop_it_2([1,1], 0),
+ io:format(user, "found ~w varibles\n", [N]),
+ ?line N = if N < 100 -> 100;
+ true -> N
+ end.
+
+
+loop_it_2(Oid, N) ->
+ ?DBG("loop_it_2 -> entry with~n"
+ "\tOid: ~p~n"
+ "\tN: ~p",[Oid,N]),
+ case get_next_req([Oid]) of
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p",[NOid]),
+ N;
+ #pdu{type='get-response', error_status=noError, error_index=0,
+ varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
+ ?DBG("loop_it_2 -> ~n"
+ "\tNOid: ~p~n"
+ "\tValue: ~p",[NOid,Value]),
+ ?line [Value2] = get_req(1, [NOid]), % must not be same
+ ?DBG("loop_it_2 -> ~n"
+ "\tValue2: ~p",[Value2]),
+ loop_it_2(NOid, N+1)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+
+
+
+
+%% These are (ticket) test cases where the initiation has to be done
+%% individually.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1128
+%% Slogan: Bug in handling of createAndWait set-requests.
+%%-----------------------------------------------------------------
+otp_1128(suite) -> [];
+otp_1128(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1128),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1128_2(X) -> otp_1128(X).
+
+otp_1128_3(X) -> otp_1128(X).
+
+otp_1128() ->
+ io:format("Testing bug reported in ticket OTP-1128...~n"),
+
+ NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
+ NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
+ NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
+
+ s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ g([NewKeyc5]),
+ ?line expect(29, [{NewKeyc5, ?notReady}]),
+ s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ g([NewKeyc5]),
+ ?line expect(31, [{NewKeyc5, ?active}]),
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(32, [{NewKeyc5, ?destroy}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1129, OTP-1169
+%% Slogan: snmpa:int_to_enum crashes on bad oids
+%%-----------------------------------------------------------------
+otp_1129(suite) -> [];
+otp_1129(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ try_test(otp_1129_i, [node()]),
+ ?line unload_master("Klas3").
+
+otp_1129_2(X) -> otp_1129(X).
+
+otp_1129_3(X) -> otp_1129(X).
+
+otp_1129_i(MaNode) ->
+ io:format("Testing bug reported in ticket OTP-1129...~n"),
+ false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
+ false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1131
+%% Slogan: Agent crashes / erlang node halts if RowIndex in a
+%% setrequest is of bad type, e.g. an INDEX {INTEGER},
+%% and RowIdenx [3,2].
+%%-----------------------------------------------------------------
+otp_1131(suite) -> [];
+otp_1131(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas1"),
+ try_test(otp_1131),
+ ?line unload_master("Klas1").
+
+otp_1131_2(X) -> otp_1131(X).
+
+otp_1131_3(X) -> otp_1131(X).
+
+otp_1131() ->
+ io:format("Testing bug reported in ticket OTP-1131...~n"),
+ s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
+ {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1162
+%% Slogan: snmp_agent can't handle wrongValue from instrum.func
+%%-----------------------------------------------------------------
+otp_1162(suite) -> [];
+otp_1162(Config) when list(Config) ->
+ {SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ try_test(otp_1162),
+ stop_subagent(SA).
+
+otp_1162_2(X) -> otp_1162(X).
+
+otp_1162_3(X) -> otp_1162(X).
+
+otp_1162() ->
+ s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
+ ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1222
+%% Slogan: snmp agent crash if faulty index is returned from instrum
+%%-----------------------------------------------------------------
+otp_1222(suite) -> [];
+otp_1222(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas3"),
+ ?line load_master("Klas4"),
+ try_test(otp_1222),
+ ?line unload_master("Klas3"),
+ ?line unload_master("Klas4").
+
+otp_1222_2(X) -> otp_1222(X).
+
+otp_1222_3(X) -> otp_1222(X).
+
+otp_1222() ->
+ io:format("Testing bug reported in ticket OTP-1222...~n"),
+ s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
+ ?line expect(1, genErr, 0, any),
+ s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
+ ?line expect(2, genErr, 0, any).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1298
+%% Slogan: Negative INTEGER values are treated as positive.
+%%-----------------------------------------------------------------
+otp_1298(suite) -> [];
+otp_1298(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1298),
+ ?line unload_master("Klas2").
+
+otp_1298_2(X) -> otp_1298(X).
+
+otp_1298_3(X) -> otp_1298(X).
+
+otp_1298() ->
+ io:format("Testing bug reported in ticket OTP-1298...~n"),
+ s([{[fint,0], -1}]),
+ ?line expect(1298, [{[fint,0], -1}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1331
+%% Slogan: snmp_generic should return noError when deleting non-ex row
+%%-----------------------------------------------------------------
+otp_1331(suite) -> [];
+otp_1331(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1331),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1331_2(X) -> otp_1331(X).
+
+otp_1331_3(X) -> otp_1331(X).
+
+otp_1331() ->
+ NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
+ s([{NewKeyc5, ?destroy}]),
+ ?line expect(1, [{NewKeyc5, ?destroy}]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1338
+%% Slogan: snmp bug in initialisation of default values for mnesia tabs
+%%-----------------------------------------------------------------
+otp_1338(suite) -> [];
+otp_1338(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas2"),
+ try_test(otp_1338),
+ ?line unload_master("Klas2").
+
+otp_1338_2(X) -> otp_1338(X).
+
+otp_1338_3(X) -> otp_1338(X).
+
+otp_1338() ->
+ s([{[kStatus2, 7], i, ?createAndGo}]),
+ ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
+ g([[kName2, 7]]),
+ ?line expect(2, [{[kName2, 7], "JJJ"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1342
+%% Slogan: default impl of snmp table can't handle bad index access,
+%% Set when INDEX is read-write gets into an infinite loop!
+%%-----------------------------------------------------------------
+otp_1342(suite) -> [];
+otp_1342(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Klas4"),
+ try_test(otp_1342),
+ ?line unload_master("Klas4").
+
+otp_1342_2(X) -> otp_1342(X).
+
+otp_1342_3(X) -> otp_1342(X).
+
+otp_1342() ->
+ s([{[fIndex5, 1], i, 1},
+ {[fName5, 1], i, 3},
+ {[fStatus5, 1], i, ?createAndGo}]),
+ ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-1366
+%% Slogan: snmp traps not sent to all managers
+%% Note: NYI! We need a way to tell the test server that we need
+%% mgrs on two different machines.
+%%-----------------------------------------------------------------
+otp_1366(suite) -> [];
+otp_1366(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_1366),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+otp_1366_2(X) -> otp_1366(X).
+
+otp_1366_3(X) -> otp_1366(X).
+
+otp_1366() ->
+ ?INF("NOT YET IMPLEMENTED", []),
+ 'NYI'.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2776
+%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
+%%-----------------------------------------------------------------
+otp_2776(suite) -> [];
+otp_2776(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_2776).
+
+otp_2776_2(X) -> otp_2776(X).
+
+otp_2776_3(X) -> otp_2776(X).
+
+otp_2776() ->
+ io:format("Testing bug reported in ticket OTP-2776...~n"),
+
+ Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
+ Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
+ Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
+ Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
+ Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
+ Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
+ Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
+ Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
+ Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
+ Dt10_invalid = [],
+ Dt11_invalid = [kalle,hobbe],
+ L = [{ 1, true, Dt01_valid},
+ { 2, true, Dt02_valid},
+ { 3, true, Dt03_valid},
+ { 4, false, Dt04_invalid},
+ { 5, true, Dt05_valid},
+ { 6, true, Dt06_valid},
+ { 7, false, Dt07_invalid},
+ { 8, true, Dt08_valid},
+ { 9, false, Dt09_invalid},
+ {10, false, Dt10_invalid},
+ {11, false, Dt11_invalid}],
+
+ ?line ok = validate_dat(L).
+
+
+validate_dat(L) -> validate_dat(L,[]).
+
+validate_dat([],V) ->
+ Fun = fun({_,X}) -> case X of
+ ok -> false;
+ _ -> true
+ end
+ end,
+ validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
+validate_dat([{Id,E,Dat}|T],V) ->
+ validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
+
+validate_dat1([]) -> ok;
+validate_dat1(L) -> {error,L}.
+
+validate_dat2(Id, E, Dat) ->
+ Res = case {E,snmp:validate_date_and_time(Dat)} of
+ {E,E} -> ok;
+ {E,A} -> {E,A}
+ end,
+ {Id, Res}.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2979
+%% Slogan: get-next on more than 1 column in an empty table
+%% returns bad response.
+%%-----------------------------------------------------------------
+otp_2979(suite) -> [];
+otp_2979(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master("Test1"),
+ ?line init_old(),
+ try_test(otp_2979),
+ ?line unload_master("Test1").
+
+otp_2979_2(X) -> otp_2979(X).
+
+otp_2979_3(X) -> otp_2979(X).
+
+otp_2979() ->
+ gn([[sparseDescr], [sparseStatus]]),
+ ?line expect(1, [{[sparseStr,0], "slut"},
+ {[sparseStr,0], "slut"}]).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3187
+%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% endOfTable - should return value.
+%%-----------------------------------------------------------------
+otp_3187(suite) -> [];
+otp_3187(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ otp_3187(),
+ ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+
+otp_3187_2(X) -> otp_3187(X).
+
+otp_3187_3(X) -> otp_3187(X).
+
+otp_3187() ->
+ ?line Elements =
+ snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
+ lists:foreach(fun(E) ->
+ ?line if E == endOfTable ->
+ ?FAIL(endOfTable);
+ true -> ok
+ end
+ end, Elements).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3542
+%% Slogan:
+%%-----------------------------------------------------------------
+otp_3542(suite) -> [];
+otp_3542(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_3542).
+
+otp_3542() ->
+ io:format("SNMP v3 discovery...~n"),
+ ?line Res = snmp_test_mgr:d(),
+ io:format("SNMP v3 discovery result: ~p~n",[Res]).
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-3725
+%% Slogan: Slow response time on snmpa:int_to_enum
+%%-----------------------------------------------------------------
+otp_3725(suite) -> [];
+otp_3725(Config) when list(Config) ->
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+
+ ?line load_master("OLD-SNMPEA-MIB"),
+ ?line init_old(),
+ try_test(otp_3725_test, [node()]),
+ ?line unload_master("OLD-SNMPEA-MIB").
+
+%% Req. OLD-SNMPEA-MIB
+otp_3725_test(MaNode) ->
+ io:format("Testing feature requested in ticket OTP-3725...~n"),
+ ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
+ ?DBG("otp_3725_test -> Db = ~p",[Db]),
+
+ ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
+ [Db, intAgentIpAddress]),
+ ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
+ ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
+ [Db,OID]),
+ ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
+ ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
+ ?line false = rpc:call(MaNode, snmp, oid_to_name,
+ [Db, [1,5,32,3,54,3,3,34,4]]),
+ ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, excluded]),
+ ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intViewType, 2]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intViewType, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddress, exclude]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, intAgentIpAddre, exclude]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddress, 2]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, intAgentIpAddre, 2]),
+ ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
+ [Db, 'RowStatus', ?active]),
+ ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'RowStatus', xxxdestroy]),
+ ?line false = rpc:call(MaNode, snmp, enum_to_int,
+ [Db, 'xxRowStatus', destroy]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
+ ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-4394
+%% Slogan: Target mib tag list check invalid
+%%-----------------------------------------------------------------
+
+
+
+init_otp_4394(Config) when list(Config) ->
+ ?DBG("init_otp_4394 -> entry with"
+ "~n Config: ~p", [Config]),
+ ?line AgentDir = ?config(agent_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ MasterAgentVerbosity = {master_agent_verbosity, trace},
+ NetIfVerbosity = {net_if_verbosity, trace},
+ Opts = [MasterAgentVerbosity,NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config,Opts)].
+
+otp_4394_config(AgentDir, MgrDir, Ip0) ->
+ ?DBG("otp_4394_config -> entry with"
+ "~n AgentDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ Vsn = [v1],
+ Ip = tuple_to_list(Ip0),
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?TRAP_UDP, Ip, 4000,
+ "OTP-4394 test"),
+ ?line case update_usm(Vsn, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsn, MgrDir);
+ false ->
+ ?line ok
+ end,
+ C1 = {"a", "all-rights", "initial", "", "pc"},
+ C2 = {"c", "secret", "secret_name", "", "secret_tag"},
+ ?line write_community_conf(AgentDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentDir),
+ Ta1 = {"shelob v1",
+ [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ "pc1",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [],
+ 2048},
+ Ta2 = {"bifur v1",
+ [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ "pc2",
+ "target_v1", "",
+ %% [255,255,255,255,0,0],
+ [], 2048},
+ ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentDir, Vsn),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+
+
+finish_otp_4394(Config) when list(Config) ->
+ ?DBG("finish_otp_4394 -> entry", []),
+ C1 = stop_agent(Config),
+ delete_files(C1),
+ erase(mgr_node),
+ lists:keydelete(vsn, 1, C1).
+
+otp_4394_test(suite) -> [];
+otp_4394_test(Config) ->
+ ?DBG("otp_4394_test -> entry", []),
+ {_SaNode, _MgrNode, _MibDir} = init_case(Config),
+ try_test(otp_4394_test1),
+ ?DBG("otp_4394_test -> done", []),
+ ok.
+
+otp_4394_test1() ->
+ ?DBG("otp_4394_test1 -> entry", []),
+ gn([[1,1]]),
+ Res =
+ case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
+ %% {error, 1, {"?",[]}, {"~w",[timeout]}}
+ {error, 1, _, {_, [timeout]}} ->
+ ?DBG("otp_4394_test1 -> expected result: timeout", []),
+ ok;
+ Else ->
+ Else
+ end,
+ ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
+ Res.
+
+
+%%%--------------------------------------------------
+%%% Used to test the standard mib with our
+%%% configuration.
+%%%--------------------------------------------------
+run(F, A, Opts) ->
+ M = get(mib_dir),
+ Dir = get(mgr_dir),
+ User = snmp_misc:get_option(user, Opts, "all-rights"),
+ SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
+ EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
+ CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
+ Community = snmp_misc:get_option(community, Opts, "all-rights"),
+ ?DBG("run -> start crypto app",[]),
+ Crypto = case os:type() of
+ vxworks ->
+ no_crypto;
+ _ ->
+ ?CRYPTO_START()
+ end,
+ ?DBG("run -> Crypto: ~p",[Crypto]),
+ catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
+ StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
+ ?DBG("run -> config:~n"
+ "\tM: ~p~n"
+ "\tDir: ~p~n"
+ "\tUser: ~p~n"
+ "\tSecLevel: ~p~n"
+ "\tEngineID: ~p~n"
+ "\tCtxEngineID: ~p~n"
+ "\tCommunity: ~p~n"
+ "\tStdM: ~p",
+ [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
+ case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
+ {packet_server_debug,true},
+ {debug,true},
+ {agent, get(master_host)},
+ {agent_udp, 4000},
+ {trap_udp, 5000},
+ {recbuf,65535},
+ quiet,
+ get(vsn),
+ {community, Community},
+ {user, User},
+ {sec_level, SecLevel},
+ {engine_id, EngineID},
+ {context_engine_id, CtxEngineID},
+ {dir, Dir},
+ {mibs, mibs(StdM, M)}]) of
+ {ok, _Pid} ->
+ Res = apply(?MODULE, F, A),
+ catch snmp_test_mgr:stop(),
+ Res;
+ Err ->
+ io:format("Error starting manager: ~p\n", [Err]),
+ catch snmp_test_mgr:stop(),
+ ?line exit({mgr_start, Err})
+ end.
+
+
+mibs(StdMibDir,MibDir) ->
+ [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
+ join(MibDir, "OLD-SNMPEA-MIB.bin"),
+ join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
+ join(StdMibDir, "SNMP-MPD-MIB"),
+ join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
+ join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
+ join(StdMibDir, "SNMP-TARGET-MIB"),
+ join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
+ join(MibDir, "Klas1.bin"),
+ join(MibDir, "Klas2.bin"),
+ join(MibDir, "Klas3.bin"),
+ join(MibDir, "Klas4.bin"),
+ join(MibDir, "SA-MIB.bin"),
+ join(MibDir, "TestTrap.bin"),
+ join(MibDir, "Test1.bin"),
+ join(MibDir, "Test2.bin"),
+ join(MibDir, "TestTrapv2.bin")].
+
+join(D,F) ->
+ filename:join(D,F).
+
+%% string used in index
+is(S) -> [length(S) | S].
+
+try_test(Func) ->
+ call(get(mgr_node), ?MODULE, run, [Func, [], []]).
+
+try_test(Func, A) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, []]).
+
+try_test(Func, A, Opts) ->
+ call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
+
+call(N,M,F,A) ->
+ ?DBG("call -> entry with~n"
+ " N: ~p~n"
+ " M: ~p~n"
+ " F: ~p~n"
+ " A: ~p~n"
+ " when~n"
+ " get(): ~p",
+ [N,M,F,A,get()]),
+ spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
+ receive
+ {done, {'EXIT', Rn}, Loc} ->
+ ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
+ put(test_server_loc, Loc),
+ exit(Rn);
+ {done, Ret, Zed} ->
+ ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
+ Ret
+ end.
+
+wait(From, Env, M, F, A) ->
+ ?DBG("wait -> entry with ~n"
+ "\tFrom: ~p~n"
+ "\tEnv: ~p",[From,Env]),
+ lists:foreach(fun({K,V}) -> put(K,V) end, Env),
+ Rn = (catch apply(M, F, A)),
+ ?DBG("wait -> Rn: ~n~p", [Rn]),
+ From ! {done, Rn, get(test_server_loc)},
+ exit(Rn).
+
+expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
+expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
+expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
+expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
+
+get_req(Id, Vars) ->
+ ?DBG("get_req -> entry with~n"
+ "\tId: ~p~n"
+ "\tVars: ~p",[Id,Vars]),
+ g(Vars),
+ ?DBG("get_req -> await response",[]),
+ {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
+ ?DBG("get_req -> response: ~p",[Val]),
+ Val.
+
+get_next_req(Vars) ->
+ ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
+ gn(Vars),
+ ?DBG("get_next_req -> await response",[]),
+ Response = snmp_test_mgr:receive_response(),
+ ?DBG("get_next_req -> response: ~p",[Response]),
+ Response.
+
+
+
+start_node(Name) ->
+ ?LOG("start_node -> entry with Name: ~p",[Name]),
+ M = list_to_atom(?HOSTNAME(node())),
+ ?DBG("start_node -> M: ~p",[M]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ ?DBG("start_node -> Pa: ~p",[Pa]),
+
+ Args = case init:get_argument('CC_TEST') of
+ {ok, [[]]} ->
+ " -pa /clearcase/otp/libraries/snmp/ebin ";
+ {ok, [[Path]]} ->
+ " -pa " ++ Path;
+ error ->
+ ""
+ end,
+ %% Do not use start_link!!! (the proc that calls this one is tmp)
+ ?DBG("start_node -> Args: ~p~n",[Args]),
+ A = Args ++ " -pa " ++ Pa,
+ case (catch ?START_NODE(Name, A)) of
+ {ok, Node} ->
+ %% Tell the test_server to not clean up things it never started.
+ ?DBG("start_node -> Node: ~p",[Node]),
+ {ok, Node};
+ Else ->
+ ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
+ ?line ?FAIL(Else)
+ end.
+
+
+stop_node(Node) ->
+ ?LOG("stop_node -> Node: ~p",[Node]),
+ rpc:cast(Node, erlang, halt, []).
+
+p(X) ->
+ io:format(user, X++"\n", []).
+
+sleep(X) ->
+ receive
+ after
+ X -> ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Configuration
+%%%-----------------------------------------------------------------
+config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
+ ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
+ ?TRAP_UDP, AIp, 4000,
+ "test"),
+ ?line case update_usm(Vsns, AgentDir) of
+ true ->
+ ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ filename:join(MgrDir, "usm.conf")),
+ ?line update_usm_mgr(Vsns, MgrDir);
+ false ->
+ ?line ok
+ end,
+ ?line update_community(Vsns, AgentDir),
+ ?line update_vacm(Vsns, AgentDir),
+ ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentDir, Vsns),
+ ?line write_notify_conf(AgentDir),
+ ok.
+
+delete_files(Config) ->
+ Dir = ?config(agent_dir, Config),
+ {ok, List} = file:list_dir(Dir),
+ lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
+ List).
+
+update_usm(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
+ "\"all-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
+ "\"no-rights\", zeroDotZero, "
+ "usmNoAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
+ "\"authMD5\", zeroDotZero, "
+ "usmHMACMD5AuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_md5xxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
+ "\"authSHA\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmNoPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
+ "\"privDES\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+update_usm_mgr(Vsns, Dir) ->
+ case lists:member(v3, Vsns) of
+ true ->
+ {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
+ []),
+ file:close(Fid),
+ true;
+ false ->
+ false
+ end.
+
+rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.conf"),
+ filename:join(Dir,"usm.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
+ ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
+ "\"newUser\", zeroDotZero, "
+ "usmHMACSHAAuthProtocol, \"\", \"\", "
+ "usmDESPrivProtocol, \"\", \"\", \"\", "
+ "\"~s\", \"~s\"}.\n",
+ [ShaKey, DesKey]),
+ file:close(Fid).
+
+reset_usm_mgr(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"usm.old"),
+ filename:join(Dir,"usm.conf")).
+
+
+update_community([v3], _Dir) -> ok;
+update_community(_, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
+ []),
+ file:close(Fid).
+
+
+-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
+update_vacm(_Vsn, Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
+ file:position(Fid, eof),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
+ ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
+ ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
+ "~w, excluded, null}.\n", [?tDescr_instance]),
+ file:close(Fid).
+
+
+vacm_ver(v1) -> v1;
+vacm_ver(v2) -> v2c;
+vacm_ver(v3) -> usm.
+
+
+write_community_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
+ ok = write_community_conf1(Fid, Confs),
+ file:close(Fid).
+
+write_community_conf1(_, []) ->
+ ok;
+write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
+ [ComIdx, ComName, SecName, CtxName, TransTag]),
+ write_community_conf1(Fid, Confs).
+
+
+write_target_addr_conf(Dir, Confs) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ ok = write_target_addr_conf1(Fid, Confs),
+ file:close(Fid).
+
+
+write_target_addr_conf1(_, []) ->
+ ok;
+write_target_addr_conf1(Fid,
+ [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz}|Confs]) ->
+ ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
+ [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
+ EngineId, TMask, MaxMsgSz]),
+ write_target_addr_conf1(Fid, Confs).
+
+write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ ok = io:format(Fid,
+ "{\"~s\", ~w, ~w, 1500, 3, "
+ "\"std_trap\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP, mk_param(Vsn)]),
+ case Vsn of
+ v1 -> ok;
+ v2 ->
+ ok = io:format(Fid,
+ "{\"~s.2\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\"}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)]);
+ v3 ->
+ ok = io:format(Fid,
+ "{\"~s.3\",~w,~w,1500,3, "
+ "\"std_inform\", \"~s\", "
+ "\"mgrEngine\", [], 1024}.~n",
+ [mk_ip(ManagerIp, Vsn),
+ ManagerIp, UDP,
+ mk_param(Vsn)])
+ end
+ end,
+ Vsns),
+ file:close(Fid).
+
+mk_param(v1) -> "target_v1";
+mk_param(v2) -> "target_v2";
+mk_param(v3) -> "target_v3".
+
+mk_ip([A,B,C,D], Vsn) ->
+ io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
+
+
+rewrite_target_addr_conf(Dir,NewPort) ->
+ TAFile = filename:join(Dir, "target_addr.conf"),
+ ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
+ case file:read_file_info(TAFile) of
+ {ok, _} -> ok;
+ {error, R} -> ?ERR("failure reading file info of "
+ "target address config file: ~p",[R]),
+ ok
+ end,
+
+ ?line [TrapAddr|Addrs] =
+ snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
+
+ ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
+
+ NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
+
+ ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
+
+ ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
+ filename:join(Dir,"target_addr.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
+
+ ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
+
+ file:close(Fid).
+
+rewrite_target_addr_conf1(O) ->
+ {ok,O}.
+
+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) ->
+ ?LOG("rewrite_target_addr_conf2 -> entry with "
+ "~n O: ~p",[O]),
+ O.
+
+
+rewrite_target_addr_conf3(_,[]) -> ok;
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
+ ParamName,EngineId}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % ParamsName
+ "\"~s\"}.", % EngineId
+ [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
+ rewrite_target_addr_conf3(Fid,T);
+rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
+ ParamName,EngineId,TMask,MMS}|T]) ->
+ ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
+ io:format(Fid,
+ "{\"~s\", " % Name
+ "~p, " % Ip
+ "~p, " % Port
+ "~p, " % Timeout
+ "~p, " % Retry
+ "\"~s\", " % TagList
+ "\"~s\", " % ParamsName
+ "\"~s\"," % EngineId
+ "~p, " % TMask
+ "~p}.", % MMS
+ [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
+ EngineId,TMask,MMS]),
+ rewrite_target_addr_conf3(Fid,T).
+
+reset_target_addr_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
+ filename:join(Dir,"target_addr.conf")).
+
+write_target_params_conf(Dir, Vsns) ->
+ {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ lists:foreach(fun(Vsn) ->
+ MP = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> v3
+ end,
+ SM = if Vsn == v1 -> v1;
+ Vsn == v2 -> v2c;
+ Vsn == v3 -> usm
+ end,
+ ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
+ "\"all-rights\", noAuthNoPriv}.~n",
+ [Vsn, MP, SM])
+ end,
+ Vsns),
+ file:close(Fid).
+
+rewrite_target_params_conf(Dir, SecName, SecLevel) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
+ filename:join(Dir,"target_params.old")),
+ ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
+ ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
+ [SecName, SecLevel]),
+ file:close(Fid).
+
+reset_target_params_conf(Dir) ->
+ ?line ok = file:rename(filename:join(Dir,"target_params.old"),
+ filename:join(Dir,"target_params.conf")).
+
+write_notify_conf(Dir) ->
+ {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
+ ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
+ ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
+ file:close(Fid).
+
+ver_to_trap_str([v1]) -> "v1";
+ver_to_trap_str([v2]) -> "v2";
+% default is to use the latest snmp version
+ver_to_trap_str([v1,v2]) -> "v2".
+
+
+
+write_view_conf(Dir) ->
+ {ok, Fid} = file:open(a(Dir,"view.conf"),write),
+ ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
+ ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
+ file:close(Fid).
+
+a(A,B) -> lists:append(A,B).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+copy_file(From, To) ->
+ {ok, Bin} = file:read_file(From),
+ ok = file:write_file(To, Bin).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+display_memory_usage() ->
+ Info = snmpa:info(snmp_master_agent),
+ TreeSize = lists_key1search(tree_size_bytes, Info),
+ ProcMem = lists_key1search(process_memory, Info),
+ MibDbSize = lists_key1search([db_memory,mib], Info),
+ NodeDbSize = lists_key1search([db_memory,node], Info),
+ TreeDbSize = lists_key1search([db_memory,tree], Info),
+ ?INF("Memory usage: "
+ "~n Tree size: ~p"
+ "~n Process memory size: ~p"
+ "~n Mib db size: ~p"
+ "~n Node db size: ~p"
+ "~n Tree db size: ~p",
+ [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
+
+lists_key1search([], Res) ->
+ Res;
+lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ lists_key1search(Keys, Val);
+ false ->
+ undefined
+ end;
+lists_key1search(Key, List) when atom(Key) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {Key, Val}} ->
+ Val;
+ false ->
+ undefined
+ end.
+
+
+regs() ->
+ lists:sort(registered()).
diff --git a/lib/snmp/test/modules.mk b/lib/snmp/test/modules.mk
index eacc749b53..a444cab6d6 100644
--- a/lib/snmp/test/modules.mk
+++ b/lib/snmp/test/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The 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,7 +76,8 @@ MIB_FILES = \
TestTrap.mib \
TestTrapv2.mib \
Test1.mib \
- Test2.mib
+ Test2.mib \
+ Test3.mib
SPECS = snmp.spec snmp.spec.vxworks
diff --git a/lib/snmp/test/snmp_SUITE.erl b/lib/snmp/test/snmp_SUITE.erl
index b6d72da2fa..22b9c64588 100644
--- a/lib/snmp/test/snmp_SUITE.erl
+++ b/lib/snmp/test/snmp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
-module(snmp_SUITE).
+-include("snmp_test_lib.hrl").
+
-export([all/0,
suite/0,
groups/0,
@@ -39,6 +41,21 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
Config.
+init_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Top test case
@@ -53,7 +70,8 @@ all() ->
{group, manager}].
groups() ->
- [{app, [], [{group, app_test},
+ [
+ {app, [], [{group, app_test},
{group, appup_test}]},
{compiler, [], [{group, compiler_test}]},
{misc, [], [{group, conf_test},
@@ -66,6 +84,7 @@ groups() ->
{manager, [], [{group, manager_config_test},
{group, manager_user_test},
{group, manager_test}]},
+
{app_test, [], [{snmp_app_test, all}]},
{appup_test, [], [{snmp_appup_test, all}]},
{compiler_test, [], [{snmp_compiler_test, all}]},
@@ -78,17 +97,25 @@ groups() ->
{agent_test, [], [{snmp_agent_test, all}]},
{manager_config_test, [], [{snmp_manager_config_test, all}]},
{manager_user_test, [], [{snmp_manager_user_test, all}]},
- {manager_test, [], [{snmp_manager_test, all}]}].
+ {manager_test, [], [{snmp_manager_test, all}]}
+ ].
-init_per_suite(Config) ->
- Config.
-end_per_suite(_Config) ->
- ok.
+init_per_group(GroupName, Config0) ->
-init_per_group(_GroupName, Config) ->
- Config.
+ ?DBG("init_per_group -> entry with"
+ "~n GroupName: ~p"
+ "~n Config0: ~p", [GroupName, Config0]),
+
+ %% Group name is not really the suite name
+ %% (but it is a good enough approximation),
+ %% but it does not matter since we only need
+ %% it to be unique.
+ snmp_test_lib:init_suite_top_dir(GroupName, Config0).
+
end_per_group(_GroupName, Config) ->
- Config.
+ lists:keydelete(snmp_suite_top_dir, 1, Config).
+
+
diff --git a/lib/snmp/test/snmp_agent_bl_test.erl b/lib/snmp/test/snmp_agent_bl_test.erl
deleted file mode 100644
index b17489a755..0000000000
--- a/lib/snmp/test/snmp_agent_bl_test.erl
+++ /dev/null
@@ -1,5654 +0,0 @@
-%%
-%% %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%
-%%
-
--module(snmp_agent_bl_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
-% -include_lib("kernel/include/file.hrl").
-% -include("test_server.hrl").
-% -include("snmp_test_lib.hrl").
-% -define(SNMP_USE_V3, true).
-% -include_lib("snmp/include/snmp_types.hrl").
-
-%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
-
-
-% -define(klas1, [1,3,6,1,2,1,7]).
-% -define(klas2, [1,3,6,1,2,1,9]).
-% -define(klas3, [1,3,6,1,2,1,8,1]).
-% -define(klas4, [1,3,6,1,2,1,8,4]).
-% -define(sa, [1,3,6,1,4,1,193,2]).
-% -define(system, [1,3,6,1,2,1,1]).
-% -define(snmp, [1,3,6,1,2,1,11]).
-% -define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
-% -define(ericsson, [1,3,6,1,4,1,193]).
-% -define(testTrap, [1,3,6,1,2,1,15,0]).
-% -define(xDescr, [1,3,6,1,2,1,17,1]).
-% -define(xDescr2, [1,3,6,1,2,1,17,2]).
-
-% -define(active, 1).
-% -define(notInService, 2).
-% -define(notReady, 3).
-% -define(createAndGo, 4).
-% -define(createAndWait, 5).
-% -define(destroy, 6).
-
-% -define(TRAP_UDP, 5000).
-
-% -define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
-
--define(str(X), snmp_pdus:bits_to_str(X)).
-
--define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
- [?LINE, self()]),
- receive cont -> ok end
- end).
-
-
--import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
--define(v1_2(V1,V2),
- case get(vsn) of
- v1 -> V1;
- _ -> V2
- end).
-
--define(v1_2_3(V1,V2,V3),
- case get(vsn) of
- v1 -> V1;
- v2 -> V2;
- _ -> V3
- end).
-
-all(suite) -> {req,
- [mnesia, distribution,
- {local_slave_nodes, 2}, {time, 360}],
- [{conf, init_all, cases(), finish_all}]}.
-
-init_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- case ?OSTYPE() of
- vxworks ->
- %% No crypto app, so skip v3 testcases
- [
- app_info,
- test_v1, test_v2, test_v1_v2,
- test_multi_threaded,
- mib_storage,
- tickets];
- _Else ->
- [
- app_info,
- test_v1, test_v2, test_v1_v2, test_v3,
- test_multi_threaded,
- mib_storage,
- tickets
- ]
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% The test case structure is as follows:
-%%%
-%%% init_all - starts mnesia,
-%%%
-%%% init_v1 - starts agent
-%%% simple
-%%% big - e.g. starts/stops subagent, load/unloads mibs
-%%% init_mul
-%%% mul_get
-%%% mul_set
-%%% <etc>
-%%% finish_mul
-%%% <etc>
-%%% finish_v1
-%%%
-%%% init_v2 - starts agent
-%%% finish_v2
-%%%
-%%% init_bilingual - starts agent
-%%% finish_bilingual
-%%%
-%%% finish_all
-%%%
-%%% There is still one problem with these testsuites. If one test
-%%% fails, it may not be possible to run some other cases, as it
-%%% may have e.g. created some row or loaded some table, that it
-%%% didn't undo (since it failed).
-%%%-----------------------------------------------------------------
-
-init_all(Config0) when list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
-
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
-
- %% --
- %% Start nodes
- %%
-
- ?line {ok, SaNode} = start_node(snmp_sa),
- ?line {ok, MgrNode} = start_node(snmp_mgr),
-
-
- %% --
- %% Create necessary files
- %%
-
- Dir = ?config(priv_dir, Config),
- ?DBG("init_all -> Dir ~p", [Dir]),
-
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
-
- file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
-
- file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
-
- file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
- ?DBG("init_all -> SaDir ~p", [SaDir]),
-
-
- %% --
- %% Start and initiate mnesia
- %%
-
- ?DBG("init_all -> load application mnesia", []),
- ?line ok = application:load(mnesia),
-
- ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, load, [mnesia]),
-
- ?DBG("init_all -> application mnesia: set_env dir",[]),
- ?line application_controller:set_env(mnesia, dir,
- filename:join(Dir, "Mnesia1")),
-
- ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(Dir, "Mnesia2")]),
-
- ?DBG("init_all -> create mnesia schema",[]),
- ?line ok = mnesia:create_schema([SaNode, node()]),
-
- ?DBG("init_all -> start application mnesia",[]),
- ?line ok = application:start(mnesia),
-
- ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
- ?line ok = rpc:call(SaNode, application, start, [mnesia]),
- Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
- Config].
-
-finish_all(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- stop_node(SaNode),
- stop_node(MgrNode),
- application:stop(mnesia).
-
-start_v1_agent(Config) when list(Config) ->
- start_agent(Config, [v1]).
-
-start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
- start_agent(Config, [v1], Opts).
-
-start_v2_agent(Config) when list(Config) ->
- start_agent(Config, [v2]).
-
-start_v3_agent(Config) when list(Config) ->
- start_agent(Config, [v3]).
-
-start_bilingual_agent(Config) when list(Config) ->
- start_agent(Config, [v1,v2]).
-
-start_multi_threaded_agent(Config) when list(Config) ->
- start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
-
-stop_agent(Config) when list(Config) ->
- ?LOG("stop_agent -> entry with"
- "~n Config: ~p",[Config]),
-
- {Sup, Par} = ?config(snmp_sup, Config),
- ?DBG("stop_agent -> attempt to stop (sup) ~p"
- "~n Sup: ~p"
- "~n Par: ~p",
- [Sup,
- (catch process_info(Sup)),
- (catch process_info(Par))]),
- stop_sup(Sup, Par),
-
- {Sup2, Par2} = ?config(snmp_sub, Config),
- ?DBG("stop_agent -> attempt to stop (sub) ~p"
- "~n Sup2: ~p"
- "~n Par2: ~p",
- [Sup2,
- (catch process_info(Sup2)),
- (catch process_info(Par2))]),
- stop_sup(Sup2, Par2),
-
- ?DBG("stop_agent -> done - now cleanup config", []),
- C1 = lists:keydelete(snmp_sup, 1, Config),
- lists:keydelete(snmp_sub, 1, C1).
-
-
-stop_sup(Pid, _) when node(Pid) == node() ->
- case (catch process_info(Pid)) of
- PI when list(PI) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- exit(Pid, kill),
- await_stopped(Pid, Ref);
- {'EXIT', _Reason} ->
- ?LOG("stop_sup -> ~p not running", [Pid]),
- ok
- end;
-stop_sup(Pid, _) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- ?LOG("stop_sup -> Ref: ~p", [Ref]),
- %% Pid ! {'EXIT', Parent, shutdown}, % usch
- exit(Pid, kill),
- await_stopped(Pid, Ref).
-
-await_stopped(Pid, Ref) ->
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ?DBG("received down message for ~p", [Pid]),
- ok
- after 10000 ->
- ?INF("await_stopped -> timeout for ~p",[Pid]),
- erlang:demonitor(Ref),
- ?FAIL({failed_stop,Pid})
- end.
-
-
-start_agent(Config, Vsn) ->
- start_agent(Config, Vsn, []).
-start_agent(Config, Vsn, Opts) ->
- ?LOG("start_agent -> entry (~p) with"
- "~n Config: ~p"
- "~n Vsn: ~p"
- "~n Opts: ~p",[node(), Config, Vsn, Opts]),
-
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
- snmp_app_env_init(vsn_init(Vsn) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, trace},
- {snmp_symbolic_store_verbosity, trace},
- {snmp_note_store_verbosity, trace},
- {snmp_net_if_verbosity, trace}],
- Opts),
-
-
- process_flag(trap_exit,true),
-
- {ok, AppSup} = snmp_app_sup:start_link(),
- unlink(AppSup),
- ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
-
- ?DBG("start_agent -> start master agent (old style)",[]),
- Sup = case (catch snmpa_app:start(normal)) of
- {ok, S} ->
- ?DBG("start_agent -> started, Sup: ~p",[S]),
- S;
-
- Else ->
- ?DBG("start_agent -> unknown result: ~n~p",[Else]),
- %% Get info about the apps we depend on
- MnesiaInfo = mnesia_running(),
- ?FAIL({start_failed,Else,MnesiaInfo})
- end,
-
- ?DBG("start_agent -> unlink from supervisor",[]),
- ?line unlink(Sup),
- ?line SaDir = ?config(sa_dir, Config),
- ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
- ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
- ?DBG("start_agent -> done",[]),
- ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
-
-
-vsn_init(Vsn) ->
- vsn_init([v1,v2,v3], Vsn, []).
-
-vsn_init([], _Vsn, Acc) ->
- Acc;
-vsn_init([V|Vsns], Vsn, Acc) ->
- case lists:member(V, Vsn) of
- true ->
- vsn_init(Vsns, Vsn, [{V, true}|Acc]);
- false ->
- vsn_init(Vsns, Vsn, [{V, false}|Acc])
- end.
-
-snmp_app_env_init(Env0, Opts) ->
- ?DBG("snmp_app_env_init -> unload snmp",[]),
- ?line application:unload(snmp),
- ?DBG("snmp_app_env_init -> load snmp",[]),
- ?line application:load(snmp),
- ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
- F1 = fun({Key,Val} = New, Acc0) ->
- ?DBG("snmp_app_env_init -> "
- "updating setting ~p to ~p", [Key, Val]),
- case lists:keyreplace(Key, 1, Acc0, New) of
- Acc0 ->
- [New|Acc0];
- Acc ->
- Acc
- end
- end,
- Env = lists:foldr(F1, Env0, Opts),
- ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
- F2 = fun({Key,Val}) ->
- ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
- application_controller:set_env(snmp, Key, Val)
- end,
- lists:foreach(F2, Env).
-
-
-
-
-%% Test if application is running
-mnesia_running() -> ?IS_MNESIA_RUNNING().
-crypto_running() -> ?IS_CRYPTO_RUNNING().
-
-
-start_sub(Dir) ->
- ?DBG("start_sub -> entry",[]),
- Opts = [{db_dir, Dir},
- {supervisor, [{verbosity, trace}]}],
- %% BMK BMK
-% {ok, P} = snmp_supervisor:start_sub(Dir),
- {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
- unlink(P),
- {ok, {P, self()}}.
-
-create_tables(SaNode) ->
- ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
- {attributes, [a1,a2]}]).
-
-delete_tables() ->
- mnesia:delete_table(friendsTable2),
- mnesia:delete_table(kompissTable2),
- mnesia:delete_table(snmp_variables).
-
-%% Creation is done in runtime!
-delete_mib_storage_mnesia_tables() ->
- mnesia:delete_table(snmpa_mib_data),
- mnesia:delete_table(snmpa_mib_tree),
- mnesia:delete_table(snmpa_symbolic_store).
-
-%%-----------------------------------------------------------------
-%% A test case is always one of:
-%% - v1 specific case
-%% - v2 specific case
-%% - v1 and v2 case
-%% All v1 specific cases are prefixed with v1_, and all v2 with
-%% v2_. E.g. v1_trap/v2_trap.
-%%
-%% All other cases are shared. However, the testserver uses the name
-%% of the case to generate a file for that case. The same case cannot
-%% be used in different configurations in the same suite. Therefore
-%% all these functions exists in two variants, the base function
-%% <base>, and a second version <base>_2. There may be several
-%% versions as well, <base>_N.
-%%-----------------------------------------------------------------
-mib_storage(suite) -> [
- mib_storage_ets,
- mib_storage_dets,
- mib_storage_mnesia,
- mib_storage_size_check_ets,
- mib_storage_size_check_dets,
- mib_storage_size_check_mnesia,
- mib_storage_varm_dets,
- mib_storage_varm_mnesia
- ].
-
-mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets,
- mib_storage_ets_cases(),
- finish_mib_storage_ets}}.
-
-mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets,
- mib_storage_dets_cases(),
- finish_mib_storage_dets}}.
-
-mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia,
- mib_storage_mnesia_cases(),
- finish_mib_storage_mnesia}}.
-
-mib_storage_size_check_ets(suite) ->
- {req, [], {conf,
- init_size_check_mse,
- mse_size_check_cases(),
- finish_size_check_mse}}.
-
-mib_storage_size_check_dets(suite) ->
- {req, [], {conf,
- init_size_check_msd,
- msd_size_check_cases(),
- finish_size_check_msd}}.
-
-mib_storage_size_check_mnesia(suite) ->
- {req, [], {conf,
- init_size_check_msm,
- msm_size_check_cases(),
- finish_size_check_msm}}.
-
-mib_storage_varm_dets(suite) ->
- {req, [], {conf,
- init_varm_mib_storage_dets,
- varm_mib_storage_dets_cases(),
- finish_varm_mib_storage_dets}}.
-
-mib_storage_varm_mnesia(suite) ->
- {req, [], {conf,
- init_varm_mib_storage_mnesia,
- varm_mib_storage_mnesia_cases(),
- finish_varm_mib_storage_mnesia}}.
-
-mib_storage_ets_cases() ->
- [
- mse_simple,
- mse_v1_processing,
- mse_big,
- mse_big2,
- mse_loop_mib,
- mse_api,
- mse_sa_register,
- mse_v1_trap,
- mse_sa_error,
- mse_next_across_sa,
- mse_undo,
- mse_standard_mib,
- mse_community_mib,
- mse_framework_mib,
- mse_target_mib,
- mse_notification_mib,
- mse_view_based_acm_mib,
- mse_sparse_table,
- mse_me_of,
- mse_mib_of].
-
-mib_storage_dets_cases() ->
- [
- msd_simple,
- msd_v1_processing,
- msd_big,
- msd_big2,
- msd_loop_mib,
- msd_api,
- msd_sa_register,
- msd_v1_trap,
- msd_sa_error,
- msd_next_across_sa,
- msd_undo,
- msd_standard_mib,
- msd_community_mib,
- msd_framework_mib,
- msd_target_mib,
- msd_notification_mib,
- msd_view_based_acm_mib,
- msd_sparse_table,
- msd_me_of,
- msd_mib_of
- ].
-
-mib_storage_mnesia_cases() ->
- [
- msm_simple,
- msm_v1_processing,
- msm_big,
- msm_big2,
- msm_loop_mib,
- msm_api,
- msm_sa_register,
- msm_v1_trap,
- msm_sa_error,
- msm_next_across_sa,
- msm_undo,
- msm_standard_mib,
- msm_community_mib,
- msm_framework_mib,
- msm_target_mib,
- msm_notification_mib,
- msm_view_based_acm_mib,
- msm_sparse_table,
- msm_me_of,
- msm_mib_of
- ].
-
-mse_size_check_cases() ->
- [mse_size_check].
-
-msd_size_check_cases() ->
- [msd_size_check].
-
-msm_size_check_cases() ->
- [msm_size_check].
-
-varm_mib_storage_dets_cases() ->
- [msd_varm_mib_start].
-
-varm_mib_storage_mnesia_cases() ->
- [msm_varm_mib_start].
-
-init_mib_storage_ets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,ets},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- init_ms(Config, [MibStorage]).
-
-init_ms(Config, Opts) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
-
-init_size_check_mse(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, ets},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msd(Config) when list(Config) ->
- AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage, {dets, AgentDir}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msm(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, {mnesia,[]}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_ms(Config, Opts) when list(Config) ->
- SaNode = ?GCONF(snmp_sa, Config),
- %% We are using v3 here, so crypto must be supported or else...
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end,
- create_tables(SaNode),
- AgentDir = ?GCONF(agent_dir, Config),
- MgrDir = ?GCONF(mgr_dir, Config),
- Ip = ?GCONF(ip, Config),
- ?line ok =
- config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_agent(Config, [v3], Opts)].
-
-init_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_dets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-init_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_mnesia -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-finish_mib_storage_ets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_ets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_dets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_dets -> entry", []),
- delete_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_size_check_mse(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msd(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msm(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_ms(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%% These are just interface functions to fool the test server
-mse_simple(X) -> simple(X).
-mse_v1_processing(X) -> v1_processing(X).
-mse_big(X) -> big(X).
-mse_big2(X) -> big2(X).
-mse_loop_mib(X) -> loop_mib(X).
-mse_api(X) -> api(X).
-mse_sa_register(X) -> sa_register(X).
-mse_v1_trap(X) -> v1_trap(X).
-mse_sa_error(X) -> sa_error(X).
-mse_next_across_sa(X) -> next_across_sa(X).
-mse_undo(X) -> undo(X).
-mse_standard_mib(X) -> snmp_standard_mib(X).
-mse_community_mib(X) -> snmp_community_mib(X).
-mse_framework_mib(X) -> snmp_framework_mib(X).
-mse_target_mib(X) -> snmp_target_mib(X).
-mse_notification_mib(X) -> snmp_notification_mib(X).
-mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-mse_sparse_table(X) -> sparse_table(X).
-mse_me_of(X) -> ms_me_of(X).
-mse_mib_of(X) -> ms_mib_of(X).
-
-msd_simple(X) -> simple(X).
-msd_v1_processing(X) -> v1_processing(X).
-msd_big(X) -> big(X).
-msd_big2(X) -> big2(X).
-msd_loop_mib(X) -> loop_mib(X).
-msd_api(X) -> api(X).
-msd_sa_register(X) -> sa_register(X).
-msd_v1_trap(X) -> v1_trap(X).
-msd_sa_error(X) -> sa_error(X).
-msd_next_across_sa(X) -> next_across_sa(X).
-msd_undo(X) -> undo(X).
-msd_standard_mib(X) -> snmp_standard_mib(X).
-msd_community_mib(X) -> snmp_community_mib(X).
-msd_framework_mib(X) -> snmp_framework_mib(X).
-msd_target_mib(X) -> snmp_target_mib(X).
-msd_notification_mib(X) -> snmp_notification_mib(X).
-msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msd_sparse_table(X) -> sparse_table(X).
-msd_me_of(X) -> ms_me_of(X).
-msd_mib_of(X) -> ms_mib_of(X).
-
-msm_simple(X) -> simple(X).
-msm_v1_processing(X) -> v1_processing(X).
-msm_big(X) -> big(X).
-msm_big2(X) -> big2(X).
-msm_loop_mib(X) -> loop_mib(X).
-msm_api(X) -> api(X).
-msm_sa_register(X) -> sa_register(X).
-msm_v1_trap(X) -> v1_trap(X).
-msm_sa_error(X) -> sa_error(X).
-msm_next_across_sa(X) -> next_across_sa(X).
-msm_undo(X) -> undo(X).
-msm_standard_mib(X) -> snmp_standard_mib(X).
-msm_community_mib(X) -> snmp_community_mib(X).
-msm_framework_mib(X) -> snmp_framework_mib(X).
-msm_target_mib(X) -> snmp_target_mib(X).
-msm_notification_mib(X) -> snmp_notification_mib(X).
-msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msm_sparse_table(X) -> sparse_table(X).
-msm_me_of(X) -> ms_me_of(X).
-msm_mib_of(X) -> ms_mib_of(X).
-
-
-mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
-msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
-msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
-
-msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
-msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
-
-ms_size_check(suite) -> [];
-ms_size_check(Config) when list(Config) ->
- p("ms_size_check..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?LOG("mib server size check...", []),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMPv2-MIB"),
- ?line load_master_std("SNMPv2-TM"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMPv2-MIB"),
- ?line unload_master("SNMPv2-TM"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-
-varm_mib_start(suite) -> [];
-varm_mib_start(Config) when list(Config) ->
- p("varm_mib_start..."),
- ?LOG("varm_mib_start -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- %% Start the agent
- Opts = ?GCONF(agent_opts, Config),
- Config1 = start_v1_agent(Config, Opts),
-
- %% Sleep some in order for the agent to start properly
- ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
- ?SLEEP(5000),
-
- %% Load all the mibs
- HardwiredMibs = loaded_mibs(),
- ?DBG("varm_mib_start -> load all mibs", []),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
-
- %% Unload the hardwired mibs
- ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
- ?SLEEP(1000),
- ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
- ?line unload_mibs(HardwiredMibs), %% unload hardwired
-
- ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
- ?SLEEP(1000),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- Config2 = stop_agent(Config1),
-
- %% Sleep some in order for the agent to stop properly
- ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
- ?SLEEP(5000),
-
- %% Start the agent (again)
- ?DBG("varm_mib_start -> start the agent", []),
- Config3 = start_v1_agent(Config2, Opts),
-
- ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
- ?SLEEP(5000),
-
- %% Perform the test(s)
- ?DBG("varm_mib_start -> perform the tests", []),
- try_test(snmp_community_mib),
- try_test(snmp_framework_mib),
- try_test(snmp_target_mib),
- try_test(snmp_notification_mib),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- stop_agent(Config3),
- ok.
-
-
--define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
--define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
--define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-ms_me_of(suite) -> [];
-ms_me_of(Config) when list(Config) ->
- p("ms_me_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = me_of(?snmpTrapCommunity_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = me_of(?vacmViewSpinLock_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-me_of(Oid) ->
- case snmpa:me_of(Oid) of
- {ok, #me{oid = Oid}} ->
- ok;
- {ok, #me{oid = OtherOid}} ->
- case lists:reverse(Oid) of
- [0|Rest] ->
- case lists:reverse(Rest) of
- OtherOid ->
- ok;
- AnotherOid ->
- {error, {invalid_oid, Oid, AnotherOid}}
- end;
- _ ->
- {error, {invalid_oid, Oid, OtherOid}}
- end;
- {error, Reason} ->
- {error, Reason};
- Else ->
- {error, Else}
- end.
-
-
-ms_mib_of(suite) -> [];
-ms_mib_of(Config) when list(Config) ->
- p("ms_mib_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
- 'SNMP-USER-BASED-SM-MIB'),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-mib_of(Oid, ExpectedMibName) ->
- ?DBG("mib_of -> entry with"
- "~n Oid: ~p"
- "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
- %% case snmpa:mib_of(Oid) of
- MibOf = snmpa:mib_of(Oid),
- ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
- case MibOf of
- {ok, ExpectedMibName} ->
- ok;
- {ok, OtherMibName} ->
- {error, {invalid_mib, ExpectedMibName, OtherMibName}};
- {error, Reason} ->
- {error, Reason};
- Else ->
- ?DBG("mib_of -> Else: ~n~p", [Else]),
- {error, Else}
- end.
-
-
-app_info(suite) -> [];
-app_info(Config) when list(Config) ->
- SnmpDir = app_dir(snmp),
- SslDir = app_dir(ssl),
- CryptoDir = app_dir(crypto),
- Attr = snmp:module_info(attributes),
- AppVsn =
- case lists:keysearch(app_vsn, 1, Attr) of
- {value, {app_vsn, V}} ->
- V;
- false ->
- "undefined"
- end,
- io:format("Root dir: ~s~n"
- "SNMP: Application dir: ~s~n"
- " Application ver: ~s~n"
- "SSL: Application dir: ~s~n"
- "CRYPTO: Application dir: ~s~n",
- [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
- ok.
-
-app_dir(App) ->
- case code:lib_dir(App) of
- D when list(D) ->
- filename:basename(D);
- {error, _Reason} ->
- "undefined"
- end.
-
-
-test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}.
-
-%v1_cases() -> [loop_mib];
-v1_cases() ->
- [simple,
- db_notify_client,
- v1_processing, big, big2, loop_mib,
- api, subagent, mnesia, multiple_reqs,
- sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs,
- standard_mibs, sparse_table, cnt_64,
- opaque,
- % opaque].
-
- change_target_addr_config].
-
-init_v1(Config) when list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v1} | start_v1_agent(Config)].
-
-finish_v1(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}.
-
-%v2_cases() -> [loop_mib_2];
-v2_cases() ->
- [simple_2, v2_processing, big_2, big2_2, loop_mib_2,
- api_2, subagent_2, mnesia_2,
- multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2,
- next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2,
- v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps].
-
-init_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_v2_agent(Config)].
-
-finish_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}.
-
-v1_v2_cases() ->
- [simple_bi].
-
-init_v1_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, bilingual} | start_bilingual_agent(Config)].
-
-finish_v1_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}.
-
-%v3_cases() -> [loop_mib_3];
-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, reported_bugs_3, standard_mibs_3,
- v3_security,
- v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3].
-
-init_v3(Config) when list(Config) ->
- %% Make sure crypto works, otherwise start_agent will fail
- %% and we will be stuck with a bunch of mnesia tables for
- %% the rest of this suite...
- ?DBG("start_agent -> start crypto app",[]),
- case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end
- end,
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
- tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_v3_agent(Config)].
-
-finish_v3(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}.
-
-mt_cases() ->
- [multi_threaded, mt_trap].
-
-init_mt(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_multi_threaded_agent(Config)].
-
-finish_mt(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-%% This one *must* be run first in each case.
-init_case(Config) when list(Config) ->
- ?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
-
- SaHost = ?HOSTNAME(SaNode),
- MgrHost = ?HOSTNAME(MgrNode),
- MasterHost = ?HOSTNAME(MasterNode),
- {ok, MasterIP} = snmp_misc:ip(MasterHost),
- {ok, MIP} = snmp_misc:ip(MgrHost),
- {ok, SIP} = snmp_misc:ip(SaHost),
-
-
- put(mgr_node, MgrNode),
- put(sa_node, SaNode),
- put(master_node, MasterNode),
- put(sa_host, SaHost),
- put(mgr_host, MgrHost),
- put(master_host, MasterHost),
- put(mip, tuple_to_list(MIP)),
- put(masterip , tuple_to_list(MasterIP)),
- put(sip, tuple_to_list(SIP)),
-
- MibDir = ?config(mib_dir, Config),
- put(mib_dir, MibDir),
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- put(std_mib_dir, StdM),
-
- MgrDir = ?config(mgr_dir, Config),
- put(mgr_dir, MgrDir),
-
- put(vsn, ?config(vsn, Config)),
- ?DBG("init_case -> exit with"
- "~n MasterNode: ~p"
- "~n SaNode: ~p"
- "~n MgrNode: ~p"
- "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
- {SaNode, MgrNode, MibDir}.
-
-load_master(Mib) ->
- ?DBG("load_master -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
-
-load_master_std(Mib) ->
- ?DBG("load_master_std -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
-
-unload_master(Mib) ->
- ?DBG("unload_master -> entry with"
- "~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
-
-loaded_mibs() ->
- ?DBG("loaded_mibs -> entry",[]),
- Info = snmpa:info(snmp_master_agent),
- {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
- [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
-
-unload_mibs(Mibs) ->
- ?DBG("unload_mibs -> entry with"
- "~n Mibs: ~p", [Mibs]),
- ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
-
-start_subagent(SaNode, RegTree, Mib) ->
- ?DBG("start_subagent -> entry with"
- "~n SaNode: ~p"
- "~n RegTree: ~p"
- "~n Mib: ~p", [SaNode, RegTree, Mib]),
- MA = whereis(snmp_master_agent),
- ?DBG("start_subagent -> MA: ~p", [MA]),
- MibDir = get(mib_dir),
- Mib1 = join(MibDir,Mib),
- %% BMK BMK
-% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
- case rpc:call(SaNode, snmpa_supervisor,
- start_sub_agent, [MA, RegTree, [Mib1]]) of
- {ok, SA} ->
- ?DBG("start_subagent -> SA: ~p", [SA]),
- {ok, SA};
- Error ->
- ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
- end.
-
-stop_subagent(SA) ->
- ?DBG("stop_subagent -> entry with"
- "~n SA: ~p", [SA]),
- %% BNK BMK
- %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
- rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
-
-%%-----------------------------------------------------------------
-%% This function takes care of the old OTP-SNMPEA-MIB.
-%% Unfortunately, the testcases were written to use the data in the
-%% internal tables, and these table are now obsolete and not used
-%% by the agent. Therefore, we emulate them by using
-%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
-%%
-%% These two rows must exist in intCommunityTable
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
-%% (But with the manager's IP address)
-%%
-%%-----------------------------------------------------------------
-init_old() ->
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [6 | "public"],
- {get(mip), "public", 2, 2}),
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [13 | "standard trap"],
- {get(mip), "standard trap", 2, 1}),
- snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
-
-
-
-simple(suite) -> [];
-simple(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(simple_standard_test).
-
-simple_2(X) -> simple(X).
-
-simple_bi(suite) -> [];
-simple_bi(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(vsn, v1), % First, try v1 manager
- try_test(simple_standard_test),
-
- put(vsn, v2), % Then, try v2 manager
- try_test(simple_standard_test).
-
-simple_3(X) ->
- simple(X).
-
-big(suite) -> [];
-big(Config) when list(Config) ->
- ?DBG("big -> entry", []),
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-big_2(X) -> big(X).
-
-big_3(X) -> big(X).
-
-
-big2(suite) -> [];
-big2(Config) when list(Config) ->
- %% This is exactly the same tests as 'big', but with the
- %% v2 equivalent of the mibs.
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
-
-big2_2(X) -> big2(X).
-
-big2_3(X) -> big2(X).
-
-
-multi_threaded(suite) -> [];
-multi_threaded(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(multi_threaded_test),
- ?line unload_master("Test1").
-
-mt_trap(suite) -> [];
-mt_trap(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- ?line load_master("TestTrapv2"),
- try_test(mt_trap_test, [MA]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("Test1").
-
-v2_types(suite) -> [];
-v2_types(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(types_v2_test),
- ?line unload_master("Test1").
-
-v2_types_3(X) -> v2_types(X).
-
-
-implied(suite) -> [];
-implied(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(implied_test,[MA]),
- ?line unload_master("Test1").
-
-implied_3(X) -> implied(X).
-
-
-sparse_table(suite) -> [];
-sparse_table(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(sparse_table_test),
- ?line unload_master("Test1").
-
-sparse_table_2(X) -> sparse_table(X).
-
-sparse_table_3(X) -> sparse_table(X).
-
-cnt_64(suite) -> [];
-cnt_64(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(cnt_64_test, [MA]),
- ?line unload_master("Test1").
-
-cnt_64_2(X) -> cnt_64(X).
-
-cnt_64_3(X) -> cnt_64(X).
-
-opaque(suite) -> [];
-opaque(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(opaque_test),
- ?line unload_master("Test1").
-
-opaque_2(X) -> opaque(X).
-
-opaque_3(X) -> opaque(X).
-
-
-change_target_addr_config(suite) -> [];
-change_target_addr_config(Config) when list(Config) ->
- p("Testing changing target address config..."),
- ?LOG("change_target_addr_config -> entry",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(sname,snmp_suite),
- put(verbosity,trace),
-
- MA = whereis(snmp_master_agent),
-
- ?LOG("change_target_addr_config -> load TestTrap",[]),
- ?line load_master("TestTrap"),
-
- ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,trace),
-
- %% First send some traps that will arive att the original manager
- ?LOG("change_target_addr_config -> send trap",[]),
- try_test(ma_trap1, [MA]),
-
- ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
-
- %% Start new dummy listener
- ?LOG("change_target_addr_config -> start dummy manager",[]),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
-
- %% Reconfigure
- ?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- %% Send the trap again
- ?LOG("change_target_addr_config -> send trap again",[]),
- catch dummy_manager_send_trap2(Pid),
-
- ?LOG("change_target_addr_config -> await trap ack",[]),
- catch dummy_manager_await_trap2_ack(),
-
- ?LOG("change_target_addr_config -> stop dummy manager",[]),
- ?line ok = dummy_manager_stop(Pid),
-
- ?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
-
- ?LOG("change_target_addr_config -> unload TestTrap",[]),
- ?line unload_master("TestTrap").
-
-
-dummy_manager_start(MA) ->
- ?DBG("dummy_manager_start -> entry",[]),
- Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
- ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
- await_dummy_manager_started(Pid).
-
-await_dummy_manager_started(Pid) ->
- receive
- {dummy_manager_started,Pid,Port} ->
- ?DBG("dummy_manager_start -> acknowledge received with"
- "~n Port: ~p",[Port]),
- {ok,Pid,Port};
- {'EXIT', Pid, Reason} ->
- {error, Pid, Reason};
- O ->
- ?LOG("dummy_manager_start -> received unknown message:"
- "~n ~p",[O]),
- await_dummy_manager_started(Pid)
- end.
-
-dummy_manager_stop(Pid) ->
- ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
- Pid ! stop,
- receive
- {dummy_manager_stopping, Pid} ->
- ?DBG("dummy_manager_stop -> acknowledge received",[]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_stop -> timeout",[]),
- timeout
- end.
-
-dummy_manager_send_trap2(Pid) ->
- ?DBG("dummy_manager_send_trap2 -> entry",[]),
- Pid ! {send_trap,testTrap2}.
-
-dummy_manager_await_trap2_ack() ->
- ?DBG("dummy_manager_await_trap2 -> entry",[]),
- receive
- {received_trap,Trap} ->
- ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
- %% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
- %% is no relation between these two test cases as far as I
- %% able to figure out...
- sleep(60000),
- ok;
- O ->
- ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_await_trap2 -> timeout",[]),
- timeout
- end.
-
-dummy_manager_init(Parent,MA) ->
- ?DBG("dummy_manager_init -> entry with"
- "~n Parent: ~p"
- "~n MA: ~p",[Parent,MA]),
- {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
- ?DBG("dummy_manager_init -> S: ~p",[S]),
- {ok,Port} = inet:port(S),
- ?DBG("dummy_manager_init -> Port: ~p",[Port]),
- Parent ! {dummy_manager_started,self(),Port},
- dummy_manager_loop(Parent,S,MA).
-
-dummy_manager_loop(P,S,MA) ->
- ?LOG("dummy_manager_loop -> ready for receive",[]),
- receive
- {send_trap,Trap} ->
- ?LOG("dummy_manager_loop -> received trap send request"
- "~n Trap: ~p",[Trap]),
- snmpa:send_trap(MA, Trap, "standard trap"),
- dummy_manager_loop(P,S,MA);
- {udp, _UdpId, Ip, UdpPort, Bytes} ->
- ?LOG("dummy_manager_loop -> received upd message"
- "~n from: ~p:~p"
- "~n size: ~p",
- [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
- R = dummy_manager_handle_message(Bytes),
- ?DBG("dummy_manager_loop -> R: ~p",[R]),
- P ! R,
- dummy_manager_loop(P,S,MA);
- stop ->
- ?DBG("dummy_manager_loop -> received stop request",[]),
- P ! {dummy_manager_stopping, self()},
- gen_udp:close(S),
- exit(normal);
- O ->
- ?LOG("dummy_manager_loop -> received unknown message:"
- "~n ~p",[O]),
- dummy_manager_loop(P,S,MA)
- end.
-
-dummy_manager_message_sz(B) when binary(B) ->
- size(B);
-dummy_manager_message_sz(L) when list(L) ->
- length(L);
-dummy_manager_message_sz(_) ->
- undefined.
-
-dummy_manager_handle_message(Bytes) ->
- case (catch snmp_pdus:dec_message(Bytes)) of
- {'EXIT',Reason} ->
- ?ERR("dummy_manager_handle_message -> "
- "failed decoding message only:~n ~p",[Reason]),
- {error,Reason};
- M ->
- ?DBG("dummy_manager_handle_message -> decoded message:"
- "~n ~p",[M]),
- {received_trap,M}
- end.
-
-
-api(suite) -> [];
-api(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(api_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-api_2(X) -> api(X).
-
-api_3(X) -> api(X).
-
-
-subagent(suite) -> [];
-subagent(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- try_test(load_test_sa),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
-
- p("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(load_test),
-
- p("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(unreg_test),
- p("Testing register subagent..."),
- rpc:call(SaNode, snmp, register_subagent,
- [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- ?line stop_subagent(SA),
- try_test(unreg_test).
-
-subagent_2(X) -> subagent(X).
-
-subagent_3(X) -> subagent(X).
-
-
-mnesia(suite) -> [];
-mnesia(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent with mnesia impl..."),
- {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- try_test(big_test_2),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
-
-mnesia_2(X) -> mnesia(X).
-
-mnesia_3(X) -> mnesia(X).
-
-
-multiple_reqs(suite) ->
- {req, [], {conf, init_mul, mul_cases(), finish_mul}}.
-
-mul_cases() ->
- [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err].
-
-multiple_reqs_2(suite) ->
- {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}.
-
-multiple_reqs_3(_X) ->
- {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
-
-
-mul_cases_2() ->
- [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2].
-
-
-mul_cases_3() ->
- [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
-
-
-init_mul(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- [{mul_sub, SA} | Config].
-
-finish_mul(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- SA = ?config(mul_sub, Config),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
- lists:keydelete(mul_sub, 1, Config).
-
-mul_get(suite) -> [];
-mul_get(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get..."),
- try_test(do_mul_get).
-
-mul_get_2(X) -> mul_get(X).
-
-mul_get_3(X) -> mul_get(X).
-
-
-mul_get_err(suite) -> [];
-mul_get_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get with error..."),
- try_test(do_mul_get_err).
-
-mul_get_err_2(X) -> mul_get_err(X).
-
-mul_get_err_3(X) -> mul_get_err(X).
-
-
-mul_next(suite) -> [];
-mul_next(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next).
-
-mul_next_2(X) -> mul_next(X).
-
-mul_next_3(X) -> mul_next(X).
-
-
-mul_next_err(suite) -> [];
-mul_next_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next_err).
-
-mul_next_err_2(X) -> mul_next_err(X).
-
-mul_next_err_3(X) -> mul_next_err(X).
-
-
-mul_set(suite) -> [];
-mul_set(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set..."),
- try_test(do_mul_set).
-
-mul_set_2(X) -> mul_set(X).
-
-mul_set_3(X) -> mul_set(X).
-
-
-mul_set_err(suite) -> [];
-mul_set_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set with error..."),
- try_test(do_mul_set_err).
-
-mul_set_err_2(X) -> mul_set_err(X).
-
-mul_set_err_3(X) -> mul_set_err(X).
-
-
-sa_register(suite) -> [];
-sa_register(Config) when list(Config) ->
- ?DBG("sa_register -> entry", []),
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?DBG("sa_register -> start subagent", []),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
-
- ?DBG("sa_register -> unregister subagent", []),
- p("Testing unregister subagent (2)..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Loading SA-MIB..."),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
- ?DBG("sa_register -> register subagent", []),
- rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
- try_test(sa_mib),
-
- ?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
-
-sa_register_2(X) -> sa_register(X).
-
-sa_register_3(X) -> sa_register(X).
-
-
-v1_trap(suite) -> [];
-v1_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_trap1, [MA]),
- try_test(ma_trap2, [MA]),
- try_test(ma_v2_2_v1_trap, [MA]),
- try_test(ma_v2_2_v1_trap2, [MA]),
-
- p("Testing trap sending from subagent..."),
- try_test(sa_trap1, [SA]),
- try_test(sa_trap2, [SA]),
- try_test(sa_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v2_trap(suite) -> [];
-v2_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
-
- try_test(ma_v2_trap1, [MA]),
- try_test(ma_v2_trap2, [MA]),
- try_test(ma_v1_2_v2_trap, [MA]),
- try_test(ma_v1_2_v2_trap2, [MA]),
-
- try_test(sa_mib),
- p("Testing trap sending from subagent..."),
- try_test(sa_v1_2_v2_trap1, [SA]),
- try_test(sa_v1_2_v2_trap2, [SA]),
- try_test(sa_v1_2_v2_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v3_trap(X) ->
- v2_trap(X).
-
-v2_inform(suite) ->
- {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}.
-
-v3_inform(_X) ->
- %% v2_inform(X).
- {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
-
-init_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-init_v3_inform(X) ->
- init_v2_inform(X).
-
-finish_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-finish_v3_inform(X) ->
- finish_v2_inform(X).
-
-
-
-v2_inform_i(suite) -> [];
-v2_inform_i(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing inform sending from master agent... NOTE! This test\ntakes a "
- "few minutes (5) to complete."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_v2_inform1, [MA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2").
-
-v3_inform_i(X) -> v2_inform_i(X).
-
-
-sa_error(suite) -> [];
-sa_error(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing sa bad value (is_set_ok)..."),
- try_test(sa_errs_bad_value),
-
- p("Testing sa gen err (set)..."),
- try_test(sa_errs_gen_err),
-
- p("Testing too big..."),
- try_test(sa_too_big),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- stop_subagent(SA).
-
-sa_error_2(X) -> sa_error(X).
-
-sa_error_3(X) -> sa_error(X).
-
-
-next_across_sa(suite) -> [];
-next_across_sa(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Loading another subagent mib..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
-
- rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- p("Testing next across subagent (endOfMibView from SA)..."),
- try_test(next_across_sa),
-
- p("Unloading mib"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Starting another subagent"),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
- p("Testing next across subagent (wrong prefix from SA)..."),
- try_test(next_across_sa),
-
- stop_subagent(SA),
- stop_subagent(SA2).
-
-next_across_sa_2(X) -> next_across_sa(X).
-
-next_across_sa_3(X) -> next_across_sa(X).
-
-
-undo(suite) -> [];
-undo(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing undo phase at master agent..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
- try_test(undo_test),
- try_test(api_test2),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
-
- p("Testing bad return values from instrum. funcs..."),
- try_test(bad_return),
-
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
-
- p("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
- try_test(undo_test),
- try_test(api_test3),
-
- p("Testing undo phase across master/subagents..."),
- try_test(undo_test),
- try_test(api_test3),
- stop_subagent(SA).
-
-undo_2(X) -> undo(X).
-
-undo_3(X) -> undo(X).
-
-%% Req. Test2
-v1_processing(suite) -> [];
-v1_processing(Config) when list(Config) ->
- ?DBG("v1_processing -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v1_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v2_processing(suite) -> [];
-v2_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v3_processing(suite) -> [];
-v3_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc), % same as v2!
- ?line unload_master("Test2").
-
-
-%% We'll try get/set/trap and inform for all the auth & priv protocols.
-%% For informs, the mgr is auth-engine. The agent has to sync. This is
-%% accomplished by the first inform sent. That one will generate a
-%% report, which makes it in sync. The notification-generating
-%% application times out, and send again. This time it'll work.
-v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv].
-
-v3_crypto_basic(suite) -> [];
-v3_crypto_basic(_Config) ->
- EID = [0,0,0,0,0,0,0,0,0,0,0,2],
- %% From rfc2274 appendix A.3.1
- ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
- ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
- 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
- KMd5_1,
- %% From rfc2274 appendix A.3.2
- ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
- ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
- 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
- KSHA_1,
- %% From rfc2274, appendix A.5.1
- ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
- 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
- snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- %% From rfc2274, appendix A.5.2
- ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
- 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
- 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- KSHA_1t = lists:sublist(KSHA_1, 16),
- KSHA_2t = lists:sublist(KSHA_2, 16),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
- 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
-
- %% Try with correct random
- ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
- ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
- ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
- ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
- ok.
-
-
-
-v3_md5_auth(suite) -> [];
-v3_md5_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing MD5 authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_sha_auth(suite) -> [];
-v3_sha_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing SHA authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_des_priv(suite) -> [];
-v3_des_priv(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing DES encryption...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-%% Make sure mgr is in sync with agent
-v3_sync(Funcs) ->
- ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
- g([[sysDescr, 0]]),
- expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
- g([[sysDescr, 0]]),
- expect(433, [{[sysDescr,0], any}]),
- lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
-
-v3_inform_sync(MA) ->
- ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
- "standard inform", []),
- %% Make sure agent is in sync with mgr...
- ?DBG("v3_sync -> wait some time: ",[]),
- sleep(20000), % more than 1500*10 in target_addr.conf
- ?DBG("v3_sync -> await response",[]),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]).
-
-
-v2_caps(suite) -> [];
-v2_caps(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(v2_caps_i, [node()]).
-
-v2_caps_3(X) -> v2_caps(X).
-
-
-v2_caps_i(Node) ->
- ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
- g([[sysORID, Idx], [sysORDescr, Idx]]),
- ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
- {[sysORDescr, Idx], "test cap"}]),
- ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
- g([[sysORID, Idx]]),
- ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
-
-
-%% Req. Test2
-v1_proc() ->
- ?DBG("v1_proc -> entry", []),
- %% According to RFC1157.
- %% Template: <Section>:<list no>
- v1_get_p(),
- v1_get_next_p(),
- v1_set_p().
-
-
-v1_get_p() ->
- %% 4.1.2:1
- g([[test2]]),
- ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
- g([[tDescr]]),
- ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
- g([[tDescr2,0]]),
- ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
- g([[tDescr3,0]]),
- ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
- g([[tDescr4,0]]),
- ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
- {[tDescr,0], 'NULL'}]),
- g([[sysDescr,3]]),
- ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
-
- %% 4.1.2:2
- g([[tTable]]),
- ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
- g([[tEntry]]),
- ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
-
- %% 4.1.2:3
- g([[tTooBig, 0]]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.2:4
- g([[tGenErr1, 0]]),
- ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]).
-
-
-v1_get_next_p() ->
- %% 4.1.3:1
- gn([[1,3,7,1]]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
- gn([[tDescr2]]),
- ?line expect(11, tooBig, 0, any),
-
- %% 4.1.3:2
- gn([[tTooBig]]),
- io:format("We currently don't handle tooBig correct!!!\n"),
-% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
- ?line expect(20, tooBig, 0, any),
-
- %% 4.1.3:3
- gn([[tGenErr1]]),
-% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
- ?line expect(40, genErr, 1, any),
- gn([[tGenErr2]]),
-% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
- ?line expect(41, genErr, 1, any),
- gn([[sysDescr], [tGenErr3]]),
-% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
-% {[tGenErr3], 'NULL'}]).
- ?line expect(42, genErr, 2, any).
-
-v1_set_p() ->
- %% 4.1.5:1
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
- s([{[tDescr3], s, "noSuchObject"}]),
- ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
- s([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
- s([{[tDescr2,0], s, "inconsistentName"}]),
- ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
-
- %% 4.1.5:2
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.1.5:3
- %% The standard is quite incorrect here. The resp pdu was too big. In
- %% the resp pdu, we have the original vbs. In the tooBig pdu we still
- %% have to original vbs => the tooBig pdu is too big as well!!! It
- %% may not get it to the manager, unless the agent uses 'NULL' instead
- %% of the std-like original value.
- s([{[tTooBig, 0], s, ?tooBigStr}]),
- %% according to std:
-% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.5:4
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
- s([{[tDescr2, 0], s, "commit_fail"}]),
- ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
-
-%% Req. Test2
-v2_proc() ->
- %% According to RFC1905.
- %% Template: <Section>:<list no>
- ?DBG("v2_proc -> entry",[]),
- v2_get_p(),
- v2_get_next_p(),
- v2_get_bulk_p(),
- v2_set_p().
-
-v2_get_p() ->
- %% 4.2.1:2
- ?DBG("v2_get_p -> entry",[]),
- g([[test2]]),
- ?line expect(10, [{[test2], noSuchObject}]),
- g([[tDescr]]),
- ?line expect(11, [{[tDescr], noSuchObject}]),
- g([[tDescr4,0]]),
- ?line expect(12, [{[tDescr4,0], noSuchObject}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
- {[tDescr,0], noSuchObject}]),
- g([[tTable]]),
- ?line expect(14, [{[tTable], noSuchObject}]),
- g([[tEntry]]),
- ?line expect(15, [{[tEntry], noSuchObject}]),
-
- %% 4.2.1:3
- g([[tDescr2,0]]), %% instrum ret noSuchName!!!
- ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
- g([[tDescr3,0]]),
- ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
- g([[sysDescr,3]]),
- ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
- g([[tIndex,1]]),
- ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
-
- %% 4.2.1 - any other error: genErr
- g([[tGenErr1, 0]]),
- ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]),
-
- %% 4.2.1 - tooBig
- g([[tTooBig, 0]]),
- ?line expect(40, tooBig, 0, []).
-
-
-v2_get_next_p() ->
- %% 4.2.2:2
- ?DBG("v2_get_next_p -> entry",[]),
- gn([[1,3,7,1]]),
- ?line expect(10, [{[1,3,7,1], endOfMibView}]),
- gn([[sysDescr], [1,3,7,1]]),
- ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gn([[tCnt2, 1]]),
- ?line expect(12, [{[tCnt2,2], 100}]),
- gn([[tCnt2, 2]]),
- ?line expect(12, [{[tCnt2,2], endOfMibView}]),
-
- %% 4.2.2 - any other error: genErr
- gn([[tGenErr1]]),
- ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
- gn([[tGenErr2]]),
- ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
- gn([[sysDescr], [tGenErr3]]),
- ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
- {[tGenErr3], 'NULL'}]),
-
- %% 4.2.2 - tooBig
- gn([[tTooBig]]),
- ?line expect(20, tooBig, 0, []).
-
-v2_get_bulk_p() ->
- %% 4.2.3
- ?DBG("v2_get_bulk_p -> entry",[]),
- gb(1, 1, []),
- ?line expect(10, []),
- gb(-1, 1, []),
- ?line expect(11, []),
- gb(-1, -1, []),
- ?line expect(12, []),
- gb(-1, -1, []),
- ?line expect(13, []),
- gb(2, 0, [[sysDescr], [1,3,7,1]]),
- ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(1, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(0, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
- ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
- ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[sysDescr, 0], "Erlang SNMP agent"}]),
-
- gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
- ?line expect(19, []),
-
- gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
- ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
- {[sysObjectID], 'NULL'},
- {[tGenErr1], 'NULL'},
- {[sysDescr], 'NULL'}]),
- gb(0, 2, [[tCnt2, 1]]),
- ?line expect(21, [{[tCnt2,2], 100},
- {[tCnt2,2], endOfMibView}]).
-
-
-v2_set_p() ->
- %% 4.2.5:1
- ?DBG("v2_set_p -> entry",[]),
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
-
- %% 4.2.5:2
- s([{[1,3,6,1,0], s, "noSuchObject"}]),
- ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
-
- %% 4.2.5:3
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.2.5:4
- s([{[tStr, 0], s, ""}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
- s([{[tStr, 0], s, "12345"}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
-
- %% 4.2.5:5 - N/A
-
- %% 4.2.5:6
- s([{[tInt1, 0], i, 0}]),
- ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
- s([{[tInt1, 0], i, 5}]),
- ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
- s([{[tInt2, 0], i, 0}]),
- ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
- s([{[tInt2, 0], i, 5}]),
- ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
- s([{[tInt3, 0], i, 5}]),
- ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
-
- %% 4.2.5:7
- s([{[tDescrX, 1, 1], s, "noCreation"}]),
- ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
-
- %% 4.2.5:8
- s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
- ?line expect(80, inconsistentName, 1,
- [{[tDescrX, 1, 2], "inconsistentName"}]),
-
- %% 4.2.5:9
- s([{[tCnt, 1, 2], i, 5}]),
- ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
-
- %% 4.2.5:10
- s([{[tDescr2,0], s, "inconsistentValue"}]),
- ?line expect(100, inconsistentValue, 1,
- [{[tDescr2,0], "inconsistentValue"}]),
-
- %% 4.2.5:11
- s([{[tDescr2,0], s, "resourceUnavailable"}]),
- ?line expect(110, resourceUnavailable, 1,
- [{[tDescr2,0],"resourceUnavailable"}]),
-
- %% 4.2.5:12
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
-
- %% commitFailed and undoFailed is tested by the 'undo' case.
-
-
-%% Req. OLD-SNMPEA-MIB
-table_test() ->
- io:format("Testing simple get, next and set on communityTable...~n"),
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
- Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
- Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
- Key1c4 = [intCommunityAccess,get(mip),is("public")],
- EndKey = [intCommunityEntry,[9],get(mip),is("public")],
- gn([[intCommunityEntry]]),
- ?line expect(7, [{Key1c3, 2}]),
- gn([[intCommunityTable]]),
- ?line expect(71, [{Key1c3, 2}]),
- gn([[community]]),
- ?line expect(72, [{Key1c3, 2}]),
- gn([[otpSnmpeaMIB]]),
- ?line expect(73, [{Key1c3, 2}]),
- gn([[ericsson]]),
- ?line expect(74, [{Key1c3, 2}]),
- gn([Key1c3]),
- ?line expect(8, [{Key2c3, 2}]),
- gn([Key2c3]),
- ?line expect(9, [{Key1c4, 2}]),
- gn([EndKey]),
- AgentIp = [intAgentIpAddress,0],
- ?line expect(10, [{AgentIp, any}]),
- g([Key1c3]),
- ?line expect(11, [{Key1c3, 2}]),
- g([EndKey]),
- ?line ?v1_2(expect(12, noSuchName, 1, any),
- expect(12, [{EndKey, noSuchObject}])),
-
- io:format("Testing row creation/deletion on communityTable...~n"),
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
- s([{NewKeyc5, ?createAndGo}]),
- ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
- s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
- ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
- g([NewKeyc4]),
- ?line expect(16, [{NewKeyc4, 2}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(17, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc4, 2}]),
- ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
- s([{NewKeyc5, ?createAndWait}]),
- ?line expect(19, [{NewKeyc5, ?createAndWait}]),
- g([NewKeyc5]),
- ?line expect(20, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc4, 2}]),
- ?line expect(21, [{NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(22, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc3, 2}]),
- ?line expect(23, [{NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(24, [{NewKeyc5, ?notInService}]),
- s([{NewKeyc5, ?active}]),
- ?line expect(25, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(26, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc3, 3}]),
- ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
- otp_1128().
-
-%% Req. system group
-simple_standard_test() ->
- ?DBG("simple_standard_test -> entry",[]),
- gn([[1,1]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3]]),
- ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6]]),
- ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1]]),
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2]]),
- ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1]]),
- ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1,1]]),
- ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[sysDescr]]),
- ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr,0]]),
- ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr]]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{[sysDescr], noSuchObject}])),
- g([[1,6,7,0]]),
- ?line ?v1_2(expect(41, noSuchName, 1, any),
- expect(3, [{[1,6,7,0], noSuchObject}])),
- gn([[1,13]]),
- ?line ?v1_2(expect(4, noSuchName,1, any),
- expect(4, [{[1,13], endOfMibView}])),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
- g([[sysLocation, 0]]),
- ?line expect(6, [{[sysLocation, 0], "new_value"}]),
- io:format("Testing noSuchName and badValue...~n"),
- s([{[sysServices,0], 3}]),
- ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
- s([{[sysLocation, 0], i, 3}]),
- ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
- ?DBG("simple_standard_test -> done",[]),
- ok.
-
-%% This is run in the agent node
-db_notify_client(suite) -> [];
-db_notify_client(Config) when list(Config) ->
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
- [SaNode,MgrNode,MibDir]),
- snmpa_local_db:register_notify_client(self(),?MODULE),
-
- %% This call (the manager) will issue to set operations, so
- %% we expect to receive to notify(insert) calls.
- try_test(db_notify_client_test),
-
- ?DBG("await first notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
- end,
-
- ?DBG("await second notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
- end,
-
- snmpa_local_db:unregister_notify_client(self()).
-
-
-%% This is run in the manager node
-db_notify_client_test() ->
- ?DBG("set first new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?DBG("set second new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]).
-
-notify(Pid,What) ->
- ?DBG("notify(~p,~p) -> called",[Pid,What]),
- Pid ! {db_notify_test_reply,What}.
-
-
-%% Req: system group, OLD-SNMPEA-MIB, Klas1
-big_test() ->
- ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
- simple_standard_test(),
-
- ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
- gn([[klas1]]),
- ?line expect(1, [{[fname,0], ""}]),
- g([[fname,0]]),
- ?line expect(2, [{[fname,0], ""}]),
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[fname,0]]),
- ?line expect(4, [{[fname,0], "test set"}]),
-
- ?DBG("big_test -> "
- "testing next from last instance in master to subagent...",[]),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname,0], "test set"}]),
- s([{[fname,0], s, ""}]),
- ?line expect(52, [{[fname,0], ""}]),
-
- table_test(),
-
- ?DBG("big_test -> adding one row in subagent table",[]),
- _FTab = [friendsEntry],
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [friendsEntry, [3, 3]]]),
- ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?active}]),
- s([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
-
- otp_1131(),
-
- ?DBG("big_test -> adding two rows in subagent table with special INDEX",
- []),
- s([{[kompissEntry, [1, 3]], s, "kompis3"},
- {[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?createAndGo}]),
- g([[kompissEntry, [1, 3]],
- [kompissEntry, [2, 3]]]),
- ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- gn([[kompissEntry, [1]],
- [kompissEntry, [2]]]),
- ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- s([{[kompissEntry, [1, 2]], s, "kompis3"},
- {[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry, [1, 1]],
- [kompissEntry, [2, 1]]]),
- ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?active}]),
- s([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
- s([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
- ?DBG("big_test -> done",[]),
- ok.
-
-%% Req. system group, Klas2, OLD-SNMPEA-MIB
-big_test_2() ->
- p("Testing simple next/get/set @ master agent (2)..."),
- simple_standard_test(),
-
- p("Testing simple next/get/set @ subagent (2)..."),
- gn([[klas2]]),
- ?line expect(1, [{[fname2,0], ""}]),
- g([[fname2,0]]),
- ?line expect(2, [{[fname2,0], ""}]),
- s([{[fname2,0], s, "test set"}]),
- ?line expect(3, [{[fname2,0], "test set"}]),
- g([[fname2,0]]),
- ?line expect(4, [{[fname2,0], "test set"}]),
-
- otp_1298(),
-
- p("Testing next from last object in master to subagent (2)..."),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname2,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname2,0], "test set"}]),
-
- table_test(),
-
- p("Adding one row in subagent table (2)"),
- _FTab = [friendsEntry2],
- s([{[friendsEntry2, [2, 3]], s, "kompis3"},
- {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?createAndGo}]),
- g([[friendsEntry2, [2, 3]],
- [friendsEntry2, [3, 3]]]),
- ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?active}]),
- s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
-
- p("Adding two rows in subagent table with special INDEX (2)"),
- s([{[kompissEntry2, [1, 3]], s, "kompis3"},
- {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?createAndGo}]),
- g([[kompissEntry2, [1, 3]],
- [kompissEntry2, [2, 3]]]),
- ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- gn([[kompissEntry2, [1]],
- [kompissEntry2, [2]]]),
- ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- s([{[kompissEntry2, [1, 2]], s, "kompis3"},
- {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry2, [1, 1]],
- [kompissEntry2, [2, 1]]]),
- ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?active}]),
- s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
- s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
- ok.
-
-%% Req. Test1
-multi_threaded_test() ->
- p("Testing multi threaded agent..."),
- g([[multiStr,0]]),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(1, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "pelle"}]),
- ?line expect(2, [{[sysLocation, 0], "pelle"}]),
- Pid ! continue,
- ?line expect(3, [{[multiStr,0], "ok"}]),
-
- s([{[multiStr, 0], s, "block"}]),
- Pid2 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(4, [{[sysUpTime,0], any}]),
- g([[multiStr,0]]),
- Pid3 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(5, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "kalle"}]),
- Pid3 ! continue,
- ?line expect(6, [{[multiStr,0], "ok"}]),
- Pid2 ! continue,
- ?line expect(7, [{[multiStr,0], "block"}]),
- ?line expect(8, [{[sysLocation,0], "kalle"}]).
-
-%% Req. Test1, TestTrapv2
-mt_trap_test(MA) ->
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- snmpa:send_trap(MA, mtTrap, "standard trap"),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(2, [{[sysUpTime,0], any}]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- Pid ! continue,
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [2]},
- {[multiStr,0], "ok"}]).
-
-
-get_multi_pid() ->
- get_multi_pid(10).
-get_multi_pid(0) ->
- ?line ?FAIL(no_global_name);
-get_multi_pid(N) ->
- sleep(1000),
- case global:whereis_name(snmp_multi_tester) of
- Pid when pid(Pid) -> Pid;
- _ -> get_multi_pid(N-1)
- end.
-
-%% Req. Test1
-types_v2_test() ->
- p("Testing v2 types..."),
-
- s([{[bits1,0], 2#10}]),
- ?line expect(1, [{[bits1,0], ?str(2#10)}]),
- g([[bits1,0]]),
- ?line expect(2, [{[bits1,0], ?str(2#101)}]),
-
- s([{[bits2,0], 2#11000000110}]),
- ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
- g([[bits2,0]]),
- ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
-
- g([[bits3,0]]),
- ?line expect(50, genErr, 1, any),
-
- g([[bits4,0]]),
- ?line expect(51, genErr, 1, any),
-
- s([{[bits1,0], s, [2#10]}]),
- ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
-
- s([{[bits2,0], 2#11001001101010011}]),
- ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%% Req. Test1
-implied_test(MA) ->
- ?LOG("implied_test -> start",[]),
- p("Testing IMPLIED..."),
-
- snmpa:verbosity(MA,trace),
- snmpa:verbosity(MA,trace),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = "apa",
- Idx2 = "qq",
- ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
- ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
- {[testDescr, Idx1], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
- ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
- {[testDescr, Idx2], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr)",[]),
- gn([[testDescr]]),
- ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
- gn([[testDescr,Idx1]]),
- ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?destroy}]),
- ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?destroy}]),
- ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
-
- %% Try the same in other table
- Idx3 = [1, "apa"],
- Idx4 = [1, "qq"],
- ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
- ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
- {[testDescr2, Idx3], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
- ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
- {[testDescr2, Idx4], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr2)",[]),
- gn([[testDescr2]]),
- ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
- gn([[testDescr2,Idx3]]),
- ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?destroy}]),
- ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?destroy}]),
- ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
-
- snmpa:verbosity(MA,log),
-
- ?LOG("implied_test -> done",[]).
-
-
-
-%% Req. Test1
-sparse_table_test() ->
- p("Testing sparse table..."),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- s([{[sparseStatus, Idx1], i, ?createAndGo},
- {[sparseDescr, Idx1], s, "row 1"}]),
- ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
- {[sparseDescr, Idx1], "row 1"}]),
- s([{[sparseStatus, Idx2], i, ?createAndGo},
- {[sparseDescr, Idx2], s, "row 2"}]),
- ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
- {[sparseDescr, Idx2], "row 2"}]),
- ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
- [sparseStatus,Idx1], [sparseStatus,Idx2]]),
- gb(0,5,[[sparseIndex]])),
- ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
- {[sparseDescr,Idx2], "row 2"},
- {[sparseStatus,Idx1], ?active},
- {[sparseStatus,Idx2], ?active},
- {[sparseStr,0], "slut"}]),
- % Delete the rows
- s([{[sparseStatus, Idx1], i, ?destroy}]),
- ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
- s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
-
-
-%% Req. Test1
-cnt_64_test(MA) ->
- ?LOG("start cnt64 test (~p)",[MA]),
- snmpa:verbosity(MA,trace),
- ?LOG("start cnt64 test",[]),
- p("Testing Counter64, and at the same time, RowStatus is not last column"),
-
- ?DBG("get cnt64",[]),
- g([[cnt64,0]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(1, noSuchName, 1, any),
- expect(1, [{[cnt64,0],18446744073709551615}])),
- ?DBG("get-next cnt64",[]),
- gn([[cnt64]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
- expect(2, [{[cnt64,0],18446744073709551615}])),
- ?DBG("send cntTrap",[]),
- snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
- {cnt64, 10},
- {sysLocation, "here"}]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
- {[sysLocation,0], "here"}]),
- expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [1]},
- {[sysContact,0], "pelle"},
- {[cnt64,0], 10},
- {[sysLocation,0], "here"}])),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- ?DBG("create row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
- ?DBG("create row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
-
- ?DBG("get-next (cntIndex)",[]),
- gn([[cntIndex]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
- expect(3, [{[cntCnt,Idx1], 0}])),
- % Delete the rows
- ?DBG("delete row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
- ?DBG("delete row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
- catch snmpa:verbosity(MA,log),
- ?DBG("done",[]),
- ok.
-
-%% Req. Test1
-opaque_test() ->
- p("Testing Opaque datatype..."),
- g([[opaqueObj,0]]),
- ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
-
-%% Req. OLD-SNMPEA-MIB
-api_test(MaNode) ->
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
- oid_to_name, [OID]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp,
- int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
- List when list(List), length(List) == 8 -> ok;
- List when list(List), length(List) == 11 -> ok
- end.
-
-%% Req. Klas3
-api_test2() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]),
- g([[fname4,0]]),
- ?line expect(2, [{[fname4,0], 1}]).
-
-api_test3() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]).
-
-
-unreg_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[snmpInPkts, 0], any}]).
-
-load_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[fname,0], ""}]).
-
-%% Req. Klas1
-load_test_sa() ->
- gn([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line expect(1, [{[fname,0], any}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_get() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
- [sysName,0]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,0], "test"}]),
- g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
- ?line ?v1_2(expect(2, noSuchName, [1,4], any),
- expect(2, [{[1,3,7,1], noSuchObject},
- {Key1c4, 2},
- {[sysDescr,0], "Erlang SNMP agent"},
- {[1,3,7,2], noSuchObject},
- {Key1c3, 2},
- {[sysDescr,0], "Erlang SNMP agent"}])).
-
-%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
-do_mul_get_err() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(expect(1, noSuchName, 5, any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,2], noSuchInstance}])),
- g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname3,0], noSuchObject},
- {Key1c3, 2},
- {[sysName,1], noSuchInstance}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2}, {[fname,0], "test set"},
- {Key1c3, 2}, {[sysName,0], "test"}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next_err() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[1,3,6,999], endOfMibView},
- {[fname,0], "test set"},
- {[1,3,90], endOfMibView},
- {Key1c3, 2},
- {[sysName,0], "test"}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set() ->
- p("Adding one row in subagent table, and one in master table"),
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [sysLocation,0],
- [friendsEntry, [3, 3]]]),
- ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
- {[sysLocation,0], "new_value"},
- {[friendsEntry, [3, 3]], ?active}]),
- g([NewKeyc4]),
- ?line expect(3, [{NewKeyc4, 2}]),
- s([{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]),
- ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- p("Adding one row in subagent table, and one in master table"),
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {NewKeyc3, 2},
- {[sysUpTime,0], 45}, % sysUpTime (readOnly)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
- g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
- g([NewKeyc4]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB
-sa_mib() ->
- g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
- s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
-
-ma_trap1(MA) ->
- snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
- snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
-
-ma_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap2(MA) ->
- snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
- {ifAdminStatus, [1], 1},
- {ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
-
-sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
-
-ma_v2_trap1(MA) ->
- ?DBG("ma_v2_traps -> entry with MA = ~p => "
- "send standard trap: testTrapv22",[MA]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
- snmpa:send_trap(MA, testTrapv21, "standard trap"),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmp ++ [1]}]).
-
-ma_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
-
-%% Note: This test case takes a while... actually a couple of minutes.
-ma_v2_inform1(MA) ->
- ?DBG("ma_v2_inform -> entry with MA = ~p => "
- "send notification: testTrapv22",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag1, self()},
- "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag1, [_]} ->
- ok;
- {snmp_targets, tag1, Addrs1} ->
- ?line ?FAIL({bad_addrs, Addrs1})
- after
- 5000 ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag1, {got_response, _}} ->
- ok;
- {snmp_notification, tag1, {no_response, _}} ->
- ?line ?FAIL(no_response)
- after
- 20000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
-
- %%
- %% -- The rest is possibly erroneous...
- %%
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag2, self()},
- "standard inform", []),
- ?line expect(2, {inform, false},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag2, [_]} ->
- ok;
- {snmp_targets, tag2, Addrs2} ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
- ?line ?FAIL({bad_addrs, Addrs2})
- after
- 5000 ->
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag2, {got_response, _}} ->
- ?line ?FAIL(got_response);
- {snmp_notification, tag2, {no_response, _}} ->
- ok
- after
- 240000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag2) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end.
-
-
-ma_v1_2_v2_trap(MA) ->
- snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
- {[ifIndex, 1], 1},
- {[snmpTrapEnterprise, 0], [1,2,3]}]).
-
-
-ma_v1_2_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"},
- {[snmpTrapEnterprise, 0], ?system}]).
-
-
-sa_v1_2_v2_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-sa_v1_2_v2_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-sa_v1_2_v2_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_bad_value() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 5}, % badValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, badValue, 2, any),
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
- g([NewKeyc4]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_gen_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},{NewKeyc4, 2},
- {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line expect(1, genErr, 4, any),
-% The row might have been added; we don't know.
-% (as a matter of fact we do - it is added, because the agent
-% first sets its own vars, and then th SAs. Lets destroy it.
- s([{NewKeyc5, ?destroy}]),
- ?line expect(2, [{NewKeyc5, ?destroy}]).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_too_big() ->
- g([[sa, [4,0]]]),
- ?line expect(1, tooBig).
-
-%% Req. Klas1, system group, snmp group (v1/v2)
-next_across_sa() ->
- gn([[sysDescr],[klas1,5]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {[snmpInPkts, 0], any}]).
-
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
-%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
-%% Req. Klas3, Klas4
-undo_test() ->
- s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
- s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
-% unfortunatly we don't know if we'll get undoFailed or commitFailed.
-% it depends on which order the agent traverses the varbind list.
-% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
-% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line expect(6, genErr, 2, any).
-
-%% Req. Klas3, Klas4
-bad_return() ->
- g([[fStatus4,4],
- [fName4,4]]),
- ?line expect(4, genErr, 2, any),
- g([[fStatus4,5],
- [fName4,5]]),
- ?line expect(5, genErr, 1, any),
- g([[fStatus4,6],
- [fName4,6]]),
- ?line expect(6, genErr, 2, any),
- gn([[fStatus4,7],
- [fName4,7]]),
- ?line expect(7, genErr, 2, any),
- gn([[fStatus4,8],
- [fName4,8]]),
- ?line expect(8, genErr, 1, any),
- gn([[fStatus4,9],
- [fName4,9]]),
- ?line expect(9, genErr, 2, any).
-
-
-%%%-----------------------------------------------------------------
-%%% Test the implementation of standard mibs.
-%%% We should *at least* try to GET all variables, just to make
-%%% sure the instrumentation functions work.
-%%% Note that many of the functions in the standard mib is
-%%% already tested by the normal tests.
-%%%-----------------------------------------------------------------
-standard_mibs(suite) ->
- [snmp_standard_mib, snmp_community_mib,
- snmp_framework_mib,
- snmp_target_mib, snmp_notification_mib,
- snmp_view_based_acm_mib].
-
-standard_mibs_2(suite) ->
- [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(suite) ->
- [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].
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v1.
-%% o Test the counters and control objects in SNMP-STANDARD-MIB
-%%-----------------------------------------------------------------
-snmp_standard_mib(suite) -> [];
-snmp_standard_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?DBG("snmp_standard_mib -> std_mib_init", []),
- try_test(std_mib_init),
-
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- InBadVsns = try_test(std_mib_a),
- put(vsn, v2),
- ?DBG("snmp_standard_mib -> std_mib_read", []),
- try_test(std_mib_read),
- put(vsn, v1),
-
- ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
- Bad = try_test(std_mib_b, [InBadVsns]),
- ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
- try_test(std_mib_read, [], [{community, "bad community"}]),
- ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
- try_test(std_mib_write, [], [{community, "public"}]),
- ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
- try_test(std_mib_asn_err),
- ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
- try_test(std_mib_c, [Bad]),
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- try_test(standard_mib_a),
-
- ?DBG("snmp_standard_mib -> std_mib_finish", []),
- try_test(std_mib_finish),
- ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
- try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
- ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
- %% There are some more counters we could test here, but it's not that
- %% important, since they are removed from SNMPv2-MIB.
- ok.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_init() ->
- %% disable authentication failure traps. (otherwise w'd get many of
- %% them - this is also a test to see that it works).
- s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_finish() ->
- %% enable again
- s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_test_finish() ->
- %% force a authenticationFailure
- std_mib_write(),
- %% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_read() ->
- ?DBG("std_mib_read -> entry", []),
- g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
- ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
-
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_write() ->
- ?DBG("std_mib_write -> entry", []),
- s([{[sysLocation, 0], "new_value"}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_asn_err() ->
- snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v2 and v3.
-%% o Test the counters and control objects in SNMPv2-MIB
-%%-----------------------------------------------------------------
-snmpv2_mib_2(suite) -> [];
-snmpv2_mib_2(Config) when list(Config) ->
- ?LOG("snmpv2_mib_2 -> start",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?DBG("snmpv2_mib_2 -> standard mib init",[]),
- try_test(std_mib_init),
-
- ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
- InBadVsns = try_test(std_mib_a),
-
- ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
- put(vsn, v1),
- try_test(std_mib_read),
-
- ?DBG("snmpv2_mib_2 -> bad version read",[]),
- put(vsn, v2),
- Bad = try_test(std_mib_b, [InBadVsns]),
-
- ?DBG("snmpv2_mib_2 -> read with bad community",[]),
- try_test(std_mib_read, [], [{community, "bad community"}]),
-
- ?DBG("snmpv2_mib_2 -> write with public community",[]),
- try_test(std_mib_write, [], [{community, "public"}]),
-
- ?DBG("snmpv2_mib_2 -> asn err",[]),
- try_test(std_mib_asn_err),
-
- ?DBG("snmpv2_mib_2 -> check counters",[]),
- try_test(std_mib_c, [Bad]),
-
- ?DBG("snmpv2_mib_2 -> get som counters",[]),
- try_test(snmpv2_mib_a),
-
- ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
- try_test(std_mib_finish),
-
- ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
- "then disable auth traps",[]),
- try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
-
- ?LOG("snmpv2_mib_2 -> done",[]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_3(suite) -> [];
-snmpv2_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- InBadVsns = try_test(std_mib_a),
- put(vsn, v1),
- try_test(std_mib_read),
- put(vsn, v3),
- _Bad = try_test(std_mib_b, [InBadVsns]),
- try_test(snmpv2_mib_a),
-
- try_test(std_mib_finish).
-
--define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_test_finish() ->
- %% force a authenticationFailure
- ?DBG("ma_v2_inform -> write to std mib",[]),
- std_mib_write(),
-
- %% check that we got a trap
- ?DBG("ma_v2_inform -> await trap",[]),
- ?line expect(2, v2trap, [{[sysUpTime,0], any},
- {[snmpTrapOID,0], ?authenticationFailure}]),
-
- %% and the the inform
- ?DBG("ma_v2_inform -> await inform",[]),
- ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
- {[snmpTrapOID,0],?authenticationFailure}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_a() ->
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
-
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
- InBadVsns.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_b(InBadVsns) ->
- ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
- ?line InBadVsns2 = InBadVsns + 1,
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
- ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
- get_req(4, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
- get_req(1, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_a() ->
- ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
- s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
- {[sysLocation, 0], "val2"}]),
- s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line expect(4, inconsistentValue, 2,
- [{[sysLocation, 0], "val3"},
- {[snmpSetSerialNo,0], SetSerial}]),
- ?line ["val2"] = get_req(5, [[sysLocation,0]]).
-
-
-%%-----------------------------------------------------------------
-%% o Bad community uses/name is tested already
-%% in SNMPv2-MIB and STANDARD-MIB.
-%% o Test add/deletion of rows.
-%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
-snmp_community_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- try_test(snmp_community_mib),
- ?line unload_master("SNMP-COMMUNITY-MIB").
-
-snmp_community_mib_2(X) -> snmp_community_mib(X).
-
-%% Req. SNMP-COMMUNITY-MIB
-snmp_community_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o Test engine boots / time
-%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
-snmp_framework_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- try_test(snmp_framework_mib),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
-
-snmp_framework_mib_2(X) -> snmp_framework_mib(X).
-
-snmp_framework_mib_3(suite) -> [];
-snmp_framework_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(snmp_framework_mib).
-
-
-%% Req. SNMP-FRAMEWORK-MIB
-snmp_framework_mib() ->
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
- sleep(5000),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
- if
- EngineTime+7 < EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- EngineTime+4 > EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- true -> ok
- end,
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
- [Boots] when integer(Boots) -> ok;
- Else -> ?FAIL(Else)
- end,
- ok.
-
-%%-----------------------------------------------------------------
-%% o Test the counters
-%%-----------------------------------------------------------------
-snmp_mpd_mib_3(suite) -> [];
-snmp_mpd_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- UnknownPDUHs = try_test(snmp_mpd_mib_a),
- try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
- try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
-
-
-%% Req. SNMP-MPD-MIB
-snmp_mpd_mib_a() ->
- ?line [UnknownSecs, InvalidMsgs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0]]),
- Pdu = #pdu{type = 'get-request',
- request_id = 23,
- error_status = noError,
- error_index = 0,
- varbinds = []},
- SPdu = #scopedPdu{contextEngineID = "agentEngine",
- contextName = "",
- data = Pdu},
- ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
- V3Hdr1 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [7],
- msgSecurityModel = 23, % bad sec model
- msgSecurityParameters = []},
- V3Hdr2 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [6], % bad flag combination
- msgSecurityModel = 3,
- msgSecurityParameters = []},
- Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
- data = SPDUBytes},
- Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
- data = SPDUBytes},
- ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
- ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
- snmp_test_mgr:send_bytes(MsgBytes1),
- snmp_test_mgr:send_bytes(MsgBytes2),
-
- ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0],
- [snmpUnknownPDUHandlers, 0]]),
- ?line UnknownSecs2 = UnknownSecs + 1,
- ?line InvalidMsgs2 = InvalidMsgs + 1,
- UnknownPDUHs.
-
--define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
-snmp_mpd_mib_b() ->
- g([[sysUpTime,0]]),
- ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
-
-
-snmp_mpd_mib_c(UnknownPDUHs) ->
- ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownPDUHs2 = UnknownPDUHs + 1.
-
-
-snmp_target_mib(suite) -> [];
-snmp_target_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
- try_test(snmp_target_mib),
- ?line unload_master("SNMP-TARGET-MIB").
-
-snmp_target_mib_2(X) -> snmp_target_mib(X).
-
-snmp_target_mib_3(X) -> snmp_target_mib(X).
-
-snmp_target_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-snmp_notification_mib(suite) -> [];
-snmp_notification_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- try_test(snmp_notification_mib),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
-
-snmp_notification_mib_2(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib_3(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o add/delete views and try them
-%% o try boundaries
-%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
-snmp_view_based_acm_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
- snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib() ->
- snmpa:verbosity(net_if,trace),
- snmpa:verbosity(master_agent,trace),
- ?LOG("start snmp_view_based_acm_mib test",[]),
- %% The user "no-rights" is present in USM, and is mapped to security
- %% name 'no-rights", which is not present in VACM.
- %% So, we'll add rights for it, try them and delete them.
- %% We'll give "no-rights" write access to tDescr.0 and read access
- %% to tDescr2.0
- %% These are the options we'll use to the mgr
- Opts = [{user, "no-rights"}, {community, "no-rights"}],
- %% Find the valid secmodel, and one invalid secmodel.
- {SecMod, InvSecMod} =
- case get(vsn) of
- v1 -> {?SEC_V1, ?SEC_V2C};
- v2 -> {?SEC_V2C, ?SEC_USM};
- v3 -> {?SEC_USM, ?SEC_V1}
- end,
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Now, add a mapping from "no-rights" -> "no-rights-group"
- GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
- GRow1 =
- [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
- {GRow1Status, ?createAndGo}],
- ?DBG("set '~p'",[GRow1]),
- ?line try_test(do_set, [GRow1]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create a mapping for another sec model, and make sure it dosn't
- %% give us access
- GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
- GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
- {GRow2Status, ?createAndGo}],
-
- ?DBG("set '~p'",[GRow2]),
- ?line try_test(do_set, [GRow2]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [GRow2Status]),
-
- RVName = "rv_name",
- WVName = "wv_name",
-
- %% Access row
- ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
- ARow1Status = [vacmAccessStatus, ARow1Idx],
- ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
- {[vacmAccessReadViewName, ARow1Idx], RVName},
- {[vacmAccessWriteViewName, ARow1Idx], WVName},
- {ARow1Status, ?createAndGo}],
-
- %% This access row would give acces, if InvSecMod was valid.
- ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
- ARow2Status = [vacmAccessStatus, ARow2Idx],
- ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
- {[vacmAccessReadViewName, ARow2Idx], "internet"},
- {[vacmAccessWriteViewName, ARow2Idx], "internet"},
- {ARow2Status, ?createAndGo}],
-
- ?line try_test(do_set, [ARow2]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [ARow2Status]),
-
-
- %% Add valid row
- ?line try_test(do_set, [ARow1]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create the view family
- VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
- VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
- VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
- VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
- VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
- VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
- VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
- VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
-
- ?line try_test(add_row, [VRow1Status]),
- ?line try_test(add_row, [VRow2Status]),
- ?line try_test(add_row, [VRow3Status]),
-
- %% We're supposed to have access now...
- ?line try_test(use_rights, [], Opts),
-
- %% Change Row3 to Row4
- ?line try_test(del_row, [VRow3Status]),
- ?line try_test(add_row, [VRow4Status]),
-
- %% We should still have access...
- ?line try_test(use_rights, [], Opts),
-
- %% Delete rows
- ?line try_test(del_row, [GRow1Status]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete rest of rows
- ?line try_test(del_row, [ARow1Status]),
- ?line try_test(del_row, [VRow1Status]),
- ?line try_test(del_row, [VRow2Status]),
- ?line try_test(del_row, [VRow4Status]),
-
- ?line try_test(use_no_rights, [], Opts),
- snmpa:verbosity(master_agent,log).
-
-do_set(Row) ->
- s(Row),
- expect(1, Row).
-
-add_row(RowStatus) ->
- s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
-
-del_row(RowStatus) ->
- s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
-
-
-
-use_no_rights() ->
- g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
- g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
- gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
- s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
-
-
-use_rights() ->
- g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
- g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
- s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
- g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
-
-mk_ln(X) ->
- [length(X) | X].
-
-%%-----------------------------------------------------------------
-%% o add/delete users and try them
-%% o test all secLevels
-%% o test all combinations of protocols
-%% o try bad ops; check counters
-%%-----------------------------------------------------------------
-snmp_user_based_sm_mib_3(suite) -> [];
-snmp_user_based_sm_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
-
- %% The newUser used here already has VACM access.
-
- %% Add a new user in the simplest way; just createAndGo
- try_test(v3_sync, [[{usm_add_user1, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new user
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
- DesKey1 = lists:sublist(ShaKey1, 16),
-
- %% Change the new user's keys - 1
- try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- MgrDir = ?config(mgr_dir, Config),
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
- DesKey2 = lists:sublist(ShaKey2, 16),
-
- %% Change the new user's keys - 2
- ?line try_test(v3_sync,
- [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- reset_usm_mgr(MgrDir),
- ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
- ?line load_master("Test2"),
- ?line try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Change the new user's keys - 3
- ?line try_test(v3_sync,
- [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new keys
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Try some read requests
- ?line try_test(v3_sync, [[{usm_read, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Delete the new user
- ?line try_test(v3_sync, [[{usm_del_user, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try some bad requests
- ?line try_test(v3_sync, [[{usm_bad, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("SNMP-USER-BASED-SM-MIB").
-
--define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
-
-usm_add_user1() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
-usm_use_user() ->
- v2_proc().
-
-
-%% Change own public keys
-usm_key_change1(ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_shaxxxxxxxxxx",
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_desxxxxxx",
- DesKey),
- Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change own private keys
-usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change other's public keys
-usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
- s(Vbs1),
- ?line expect(1, noAccess, 1, any),
- Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs2),
- ?line expect(2, noAccess, 1, any),
-
-
- Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs3),
- ?line expect(1, Vbs3).
-
-usm_read() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ?line g([[usmUserSecurityName, NewRowIndex],
- [usmUserCloneFrom, NewRowIndex],
- [usmUserAuthKeyChange, NewRowIndex],
- [usmUserOwnAuthKeyChange, NewRowIndex],
- [usmUserPrivKeyChange, NewRowIndex],
- [usmUserOwnPrivKeyChange, NewRowIndex]]),
- ?line expect(1,
- [{[usmUserSecurityName, NewRowIndex], "newUser"},
- {[usmUserCloneFrom, NewRowIndex], [0,0]},
- {[usmUserAuthKeyChange, NewRowIndex], ""},
- {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
- {[usmUserPrivKeyChange, NewRowIndex], ""},
- {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
- ok.
-
-
-
-usm_del_user() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
--define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
-
--define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
-
--define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
-
--define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
-
--define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
-
--define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
-
-usm_bad() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, inconsistentName, 1, any),
-
- RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs2),
- ?line expect(2, wrongValue, 1, any),
-
- RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs3),
- ?line expect(3, Vbs3),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
- ?line expect(4, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
- ?line expect(5, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
- ?line expect(6, wrongValue, 1, any),
- ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
- ?line expect(7, wrongValue, 1, any),
-
- Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs4),
- ?line expect(1, Vbs4),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Loop through entire MIB, to make sure that all instrum. funcs
-%% works.
-%% Load all std mibs that are not loaded by default.
-%%-----------------------------------------------------------------
-loop_mib(suite) -> [];
-loop_mib(Config) when list(Config) ->
- ?LOG("loop_mib -> initiate case",[]),
- %% snmpa:verbosity(master_agent,debug),
- %% snmpa:verbosity(mib_server,info),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?DBG("loop_mib -> try",[]),
- try_test(loop_mib_1),
- ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- %% snmpa:verbosity(master_agent,log),
- %% snmpa:verbosity(mib_server,silence),
- ?LOG("loop_mib -> done",[]).
-
-
-loop_mib_2(suite) -> [];
-loop_mib_2(Config) when list(Config) ->
- ?LOG("loop_mib_2 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_2 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_2 -> load mibs",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_2 -> unload mibs",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?LOG("loop_mib_2 -> done",[]).
-
-
-loop_mib_3(suite) -> [];
-loop_mib_3(Config) when list(Config) ->
- ?LOG("loop_mib_3 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_3 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_3 -> load mibs",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_3 -> unload mibs",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?LOG("loop_mib_3 -> done",[]).
-
-
-%% Req. As many mibs all possible
-loop_mib_1() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_1([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_1(Oid, N) ->
- ?DBG("loop_it_1 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_1 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_1 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_1(NOid, N+1);
- #pdu{type='get-response', error_status=noSuchName, error_index=1,
- varbinds=[_]} ->
- ?DBG("loop_it_1 -> done",[]),
- N;
-
- #pdu{type = Type, error_status = Err, error_index = Idx,
- varbinds = Vbs} ->
- exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
- end.
-
-%% Req. As many mibs all possible
-loop_mib_2() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_2([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_2(Oid, N) ->
- ?DBG("loop_it_2 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p",[NOid]),
- N;
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_2 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_2(NOid, N+1)
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% Testing of reported bugs and other tickets.
-%%%-----------------------------------------------------------------
-
-reported_bugs(suite) ->
- [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(suite) ->
- [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(suite) ->
- [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].
-
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-tickets(suite) ->
- [otp_4394].
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1128
-%% Slogan: Bug in handling of createAndWait set-requests.
-%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
-otp_1128(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1128),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1128_2(X) -> otp_1128(X).
-
-otp_1128_3(X) -> otp_1128(X).
-
-otp_1128() ->
- io:format("Testing bug reported in ticket OTP-1128...~n"),
-
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
-
- s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(29, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(31, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(32, [{NewKeyc5, ?destroy}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1129, OTP-1169
-%% Slogan: snmpa:int_to_enum crashes on bad oids
-%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
-otp_1129(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- try_test(otp_1129_i, [node()]),
- ?line unload_master("Klas3").
-
-otp_1129_2(X) -> otp_1129(X).
-
-otp_1129_3(X) -> otp_1129(X).
-
-otp_1129_i(MaNode) ->
- io:format("Testing bug reported in ticket OTP-1129...~n"),
- false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
- false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1131
-%% Slogan: Agent crashes / erlang node halts if RowIndex in a
-%% setrequest is of bad type, e.g. an INDEX {INTEGER},
-%% and RowIdenx [3,2].
-%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
-otp_1131(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas1"),
- try_test(otp_1131),
- ?line unload_master("Klas1").
-
-otp_1131_2(X) -> otp_1131(X).
-
-otp_1131_3(X) -> otp_1131(X).
-
-otp_1131() ->
- io:format("Testing bug reported in ticket OTP-1131...~n"),
- s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
- {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1162
-%% Slogan: snmp_agent can't handle wrongValue from instrum.func
-%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
-otp_1162(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
- try_test(otp_1162),
- stop_subagent(SA).
-
-otp_1162_2(X) -> otp_1162(X).
-
-otp_1162_3(X) -> otp_1162(X).
-
-otp_1162() ->
- s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1222
-%% Slogan: snmp agent crash if faulty index is returned from instrum
-%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
-otp_1222(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
- try_test(otp_1222),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4").
-
-otp_1222_2(X) -> otp_1222(X).
-
-otp_1222_3(X) -> otp_1222(X).
-
-otp_1222() ->
- io:format("Testing bug reported in ticket OTP-1222...~n"),
- s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line expect(1, genErr, 0, any),
- s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line expect(2, genErr, 0, any).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1298
-%% Slogan: Negative INTEGER values are treated as positive.
-%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
-otp_1298(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1298),
- ?line unload_master("Klas2").
-
-otp_1298_2(X) -> otp_1298(X).
-
-otp_1298_3(X) -> otp_1298(X).
-
-otp_1298() ->
- io:format("Testing bug reported in ticket OTP-1298...~n"),
- s([{[fint,0], -1}]),
- ?line expect(1298, [{[fint,0], -1}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1331
-%% Slogan: snmp_generic should return noError when deleting non-ex row
-%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
-otp_1331(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1331),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1331_2(X) -> otp_1331(X).
-
-otp_1331_3(X) -> otp_1331(X).
-
-otp_1331() ->
- NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
- s([{NewKeyc5, ?destroy}]),
- ?line expect(1, [{NewKeyc5, ?destroy}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1338
-%% Slogan: snmp bug in initialisation of default values for mnesia tabs
-%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
-otp_1338(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1338),
- ?line unload_master("Klas2").
-
-otp_1338_2(X) -> otp_1338(X).
-
-otp_1338_3(X) -> otp_1338(X).
-
-otp_1338() ->
- s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
- g([[kName2, 7]]),
- ?line expect(2, [{[kName2, 7], "JJJ"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1342
-%% Slogan: default impl of snmp table can't handle bad index access,
-%% Set when INDEX is read-write gets into an infinite loop!
-%%-----------------------------------------------------------------
-otp_1342(suite) -> [];
-otp_1342(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas4"),
- try_test(otp_1342),
- ?line unload_master("Klas4").
-
-otp_1342_2(X) -> otp_1342(X).
-
-otp_1342_3(X) -> otp_1342(X).
-
-otp_1342() ->
- s([{[fIndex5, 1], i, 1},
- {[fName5, 1], i, 3},
- {[fStatus5, 1], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1366
-%% Slogan: snmp traps not sent to all managers
-%% Note: NYI! We need a way to tell the test server that we need
-%% mgrs on two different machines.
-%%-----------------------------------------------------------------
-otp_1366(suite) -> [];
-otp_1366(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1366),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1366_2(X) -> otp_1366(X).
-
-otp_1366_3(X) -> otp_1366(X).
-
-otp_1366() ->
- ?INF("NOT YET IMPLEMENTED", []),
- 'NYI'.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2776
-%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
-%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
-otp_2776(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_2776).
-
-otp_2776_2(X) -> otp_2776(X).
-
-otp_2776_3(X) -> otp_2776(X).
-
-otp_2776() ->
- io:format("Testing bug reported in ticket OTP-2776...~n"),
-
- Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
- Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
- Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
- Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
- Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
- Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
- Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
- Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
- Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
- Dt10_invalid = [],
- Dt11_invalid = [kalle,hobbe],
- L = [{ 1, true, Dt01_valid},
- { 2, true, Dt02_valid},
- { 3, true, Dt03_valid},
- { 4, false, Dt04_invalid},
- { 5, true, Dt05_valid},
- { 6, true, Dt06_valid},
- { 7, false, Dt07_invalid},
- { 8, true, Dt08_valid},
- { 9, false, Dt09_invalid},
- {10, false, Dt10_invalid},
- {11, false, Dt11_invalid}],
-
- ?line ok = validate_dat(L).
-
-
-validate_dat(L) -> validate_dat(L,[]).
-
-validate_dat([],V) ->
- Fun = fun({_,X}) -> case X of
- ok -> false;
- _ -> true
- end
- end,
- validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
-validate_dat([{Id,E,Dat}|T],V) ->
- validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
-
-validate_dat1([]) -> ok;
-validate_dat1(L) -> {error,L}.
-
-validate_dat2(Id, E, Dat) ->
- Res = case {E,snmp:validate_date_and_time(Dat)} of
- {E,E} -> ok;
- {E,A} -> {E,A}
- end,
- {Id, Res}.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2979
-%% Slogan: get-next on more than 1 column in an empty table
-%% returns bad response.
-%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
-otp_2979(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Test1"),
- ?line init_old(),
- try_test(otp_2979),
- ?line unload_master("Test1").
-
-otp_2979_2(X) -> otp_2979(X).
-
-otp_2979_3(X) -> otp_2979(X).
-
-otp_2979() ->
- gn([[sparseDescr], [sparseStatus]]),
- ?line expect(1, [{[sparseStr,0], "slut"},
- {[sparseStr,0], "slut"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
-%% endOfTable - should return value.
-%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
-otp_3187(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- otp_3187(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-otp_3187_2(X) -> otp_3187(X).
-
-otp_3187_3(X) -> otp_3187(X).
-
-otp_3187() ->
- ?line Elements =
- snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
- lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
- ?FAIL(endOfTable);
- true -> ok
- end
- end, Elements).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3542
-%% Slogan:
-%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
-otp_3542(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_3542).
-
-otp_3542() ->
- io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
- io:format("SNMP v3 discovery result: ~p~n",[Res]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3725
-%% Slogan: Slow response time on snmpa:int_to_enum
-%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
-otp_3725(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-otp_3725_test(MaNode) ->
- io:format("Testing feature requested in ticket OTP-3725...~n"),
- ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
- ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
- ?DBG("otp_3725_test -> Db = ~p",[Db]),
-
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [Db, intAgentIpAddress]),
- ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
- [Db,OID]),
- ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-4394
-%% Slogan: Target mib tag list check invalid
-%%-----------------------------------------------------------------
-
-
-otp_4394(suite) -> {req, [], {conf,
- init_otp_4394,
- [otp_4394_test],
- finish_otp_4394}}.
-
-init_otp_4394(Config) when list(Config) ->
- ?DBG("init_otp_4394 -> entry with"
- "~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
- MasterAgentVerbosity = {master_agent_verbosity, trace},
- NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
-
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
- ?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
- Vsn = [v1],
- Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
- ?TRAP_UDP, Ip, 4000,
- "OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
- false ->
- ?line ok
- end,
- C1 = {"a", "all-rights", "initial", "", "pc"},
- C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
- Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
- "pc1",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [],
- 2048},
- Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
- "pc2",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
- ok.
-
-
-
-finish_otp_4394(Config) when list(Config) ->
- ?DBG("finish_otp_4394 -> entry", []),
- C1 = stop_agent(Config),
- delete_files(C1),
- erase(mgr_node),
- lists:keydelete(vsn, 1, C1).
-
-otp_4394_test(suite) -> [];
-otp_4394_test(Config) ->
- ?DBG("otp_4394_test -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_4394_test1),
- ?DBG("otp_4394_test -> done", []),
- ok.
-
-otp_4394_test1() ->
- ?DBG("otp_4394_test1 -> entry", []),
- gn([[1,1]]),
- Res =
- case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
- %% {error, 1, {"?",[]}, {"~w",[timeout]}}
- {error, 1, _, {_, [timeout]}} ->
- ?DBG("otp_4394_test1 -> expected result: timeout", []),
- ok;
- Else ->
- Else
- end,
- ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
- Res.
-
-
-%%%--------------------------------------------------
-%%% Used to test the standard mib with our
-%%% configuration.
-%%%--------------------------------------------------
-run(F, A, Opts) ->
- M = get(mib_dir),
- Dir = get(mgr_dir),
- User = snmp_misc:get_option(user, Opts, "all-rights"),
- SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
- EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
- CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
- Community = snmp_misc:get_option(community, Opts, "all-rights"),
- ?DBG("run -> start crypto app",[]),
- Crypto = case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- ?CRYPTO_START()
- end,
- ?DBG("run -> Crypto: ~p",[Crypto]),
- catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- ?DBG("run -> config:~n"
- "\tM: ~p~n"
- "\tDir: ~p~n"
- "\tUser: ~p~n"
- "\tSecLevel: ~p~n"
- "\tEngineID: ~p~n"
- "\tCtxEngineID: ~p~n"
- "\tCommunity: ~p~n"
- "\tStdM: ~p",
- [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
- case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
- {packet_server_debug,true},
- {debug,true},
- {agent, get(master_host)},
- {agent_udp, 4000},
- {trap_udp, 5000},
- {recbuf,65535},
- quiet,
- get(vsn),
- {community, Community},
- {user, User},
- {sec_level, SecLevel},
- {engine_id, EngineID},
- {context_engine_id, CtxEngineID},
- {dir, Dir},
- {mibs, mibs(StdM, M)}]) of
- {ok, _Pid} ->
- Res = apply(?MODULE, F, A),
- catch snmp_test_mgr:stop(),
- Res;
- Err ->
- io:format("Error starting manager: ~p\n", [Err]),
- catch snmp_test_mgr:stop(),
- ?line exit({mgr_start, Err})
- end.
-
-
-mibs(StdMibDir,MibDir) ->
- [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
- join(MibDir, "OLD-SNMPEA-MIB.bin"),
- join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
- join(StdMibDir, "SNMP-MPD-MIB"),
- join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
- join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
- join(StdMibDir, "SNMP-TARGET-MIB"),
- join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
- join(MibDir, "Klas1.bin"),
- join(MibDir, "Klas2.bin"),
- join(MibDir, "Klas3.bin"),
- join(MibDir, "Klas4.bin"),
- join(MibDir, "SA-MIB.bin"),
- join(MibDir, "TestTrap.bin"),
- join(MibDir, "Test1.bin"),
- join(MibDir, "Test2.bin"),
- join(MibDir, "TestTrapv2.bin")].
-
-join(D,F) ->
- filename:join(D,F).
-
-%% string used in index
-is(S) -> [length(S) | S].
-
-try_test(Func) ->
- call(get(mgr_node), ?MODULE, run, [Func, [], []]).
-
-try_test(Func, A) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, []]).
-
-try_test(Func, A, Opts) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
-
-call(N,M,F,A) ->
- ?DBG("call -> entry with~n"
- " N: ~p~n"
- " M: ~p~n"
- " F: ~p~n"
- " A: ~p~n"
- " when~n"
- " get(): ~p",
- [N,M,F,A,get()]),
- spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
- receive
- {done, {'EXIT', Rn}, Loc} ->
- ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
- put(test_server_loc, Loc),
- exit(Rn);
- {done, Ret, Zed} ->
- ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
- Ret
- end.
-
-wait(From, Env, M, F, A) ->
- ?DBG("wait -> entry with ~n"
- "\tFrom: ~p~n"
- "\tEnv: ~p",[From,Env]),
- lists:foreach(fun({K,V}) -> put(K,V) end, Env),
- Rn = (catch apply(M, F, A)),
- ?DBG("wait -> Rn: ~n~p", [Rn]),
- From ! {done, Rn, get(test_server_loc)},
- exit(Rn).
-
-expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
-expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
-expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
-expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
-
-get_req(Id, Vars) ->
- ?DBG("get_req -> entry with~n"
- "\tId: ~p~n"
- "\tVars: ~p",[Id,Vars]),
- g(Vars),
- ?DBG("get_req -> await response",[]),
- {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
- ?DBG("get_req -> response: ~p",[Val]),
- Val.
-
-get_next_req(Vars) ->
- ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
- gn(Vars),
- ?DBG("get_next_req -> await response",[]),
- Response = snmp_test_mgr:receive_response(),
- ?DBG("get_next_req -> response: ~p",[Response]),
- Response.
-
-
-
-start_node(Name) ->
- ?LOG("start_node -> entry with Name: ~p",[Name]),
- M = list_to_atom(?HOSTNAME(node())),
- ?DBG("start_node -> M: ~p",[M]),
- Pa = filename:dirname(code:which(?MODULE)),
- ?DBG("start_node -> Pa: ~p",[Pa]),
-
- Args = case init:get_argument('CC_TEST') of
- {ok, [[]]} ->
- " -pa /clearcase/otp/libraries/snmp/ebin ";
- {ok, [[Path]]} ->
- " -pa " ++ Path;
- error ->
- ""
- end,
- %% Do not use start_link!!! (the proc that calls this one is tmp)
- ?DBG("start_node -> Args: ~p~n",[Args]),
- A = Args ++ " -pa " ++ Pa,
- case (catch ?START_NODE(Name, A)) of
- {ok, Node} ->
- %% Tell the test_server to not clean up things it never started.
- ?DBG("start_node -> Node: ~p",[Node]),
- {ok, Node};
- Else ->
- ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
- ?line ?FAIL(Else)
- end.
-
-
-stop_node(Node) ->
- ?LOG("stop_node -> Node: ~p",[Node]),
- rpc:cast(Node, erlang, halt, []).
-
-p(X) ->
- io:format(user, X++"\n", []).
-
-sleep(X) ->
- receive
- after
- X -> ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Configuration
-%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
- "test"),
- ?line case update_usm(Vsns, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsns, MgrDir);
- false ->
- ?line ok
- end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
- ok.
-
-delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
- lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
-
-update_usm(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-update_usm_mgr(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(filename:join(Dir,"usm.conf"),
- filename:join(Dir,"usm.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- file:close(Fid).
-
-reset_usm_mgr(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"usm.old"),
- filename:join(Dir,"usm.conf")).
-
-
-update_community([v3], _Dir) -> ok;
-update_community(_, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
- []),
- file:close(Fid).
-
-
--define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
-update_vacm(_Vsn, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
- ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
- "~w, excluded, null}.\n", [?tDescr_instance]),
- file:close(Fid).
-
-
-vacm_ver(v1) -> v1;
-vacm_ver(v2) -> v2c;
-vacm_ver(v3) -> usm.
-
-
-write_community_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
- ok = write_community_conf1(Fid, Confs),
- file:close(Fid).
-
-write_community_conf1(_, []) ->
- ok;
-write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
- [ComIdx, ComName, SecName, CtxName, TransTag]),
- write_community_conf1(Fid, Confs).
-
-
-write_target_addr_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- ok = write_target_addr_conf1(Fid, Confs),
- file:close(Fid).
-
-
-write_target_addr_conf1(_, []) ->
- ok;
-write_target_addr_conf1(Fid,
- [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
- [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz]),
- write_target_addr_conf1(Fid, Confs).
-
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- lists:foreach(fun(Vsn) ->
- ok = io:format(Fid,
- "{\"~s\", ~w, ~w, 1500, 3, "
- "\"std_trap\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP, mk_param(Vsn)]),
- case Vsn of
- v1 -> ok;
- v2 ->
- ok = io:format(Fid,
- "{\"~s.2\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)]);
- v3 ->
- ok = io:format(Fid,
- "{\"~s.3\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\", "
- "\"mgrEngine\", [], 1024}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)])
- end
- end,
- Vsns),
- file:close(Fid).
-
-mk_param(v1) -> "target_v1";
-mk_param(v2) -> "target_v2";
-mk_param(v3) -> "target_v3".
-
-mk_ip([A,B,C,D], Vsn) ->
- io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
-
-
-rewrite_target_addr_conf(Dir,NewPort) ->
- TAFile = filename:join(Dir, "target_addr.conf"),
- ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
- case file:read_file_info(TAFile) of
- {ok, _} -> ok;
- {error, R} -> ?ERR("failure reading file info of "
- "target address config file: ~p",[R]),
- ok
- end,
-
- ?line [TrapAddr|Addrs] =
- snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
-
- ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
-
- NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
-
- ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
-
- ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
- filename:join(Dir,"target_addr.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
-
- ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
-
- file:close(Fid).
-
-rewrite_target_addr_conf1(O) ->
- {ok,O}.
-
-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) ->
- ?LOG("rewrite_target_addr_conf2 -> entry with "
- "~n O: ~p",[O]),
- O.
-
-
-rewrite_target_addr_conf3(_,[]) -> ok;
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
- ParamName,EngineId}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % ParamsName
- "\"~s\"}.", % EngineId
- [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
- rewrite_target_addr_conf3(Fid,T);
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
- ParamName,EngineId,TMask,MMS}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % TagList
- "\"~s\", " % ParamsName
- "\"~s\"," % EngineId
- "~p, " % TMask
- "~p}.", % MMS
- [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
- EngineId,TMask,MMS]),
- rewrite_target_addr_conf3(Fid,T).
-
-reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
-
-write_target_params_conf(Dir, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- lists:foreach(fun(Vsn) ->
- MP = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> v3
- end,
- SM = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> usm
- end,
- ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
- "\"all-rights\", noAuthNoPriv}.~n",
- [Vsn, MP, SM])
- end,
- Vsns),
- file:close(Fid).
-
-rewrite_target_params_conf(Dir, SecName, SecLevel) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
- filename:join(Dir,"target_params.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
- [SecName, SecLevel]),
- file:close(Fid).
-
-reset_target_params_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.old"),
- filename:join(Dir,"target_params.conf")).
-
-write_notify_conf(Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
- ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
- ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
- file:close(Fid).
-
-ver_to_trap_str([v1]) -> "v1";
-ver_to_trap_str([v2]) -> "v2";
-% default is to use the latest snmp version
-ver_to_trap_str([v1,v2]) -> "v2".
-
-
-
-write_view_conf(Dir) ->
- {ok, Fid} = file:open(a(Dir,"view.conf"),write),
- ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
- ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
- file:close(Fid).
-
-a(A,B) -> lists:append(A,B).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-copy_file(From, To) ->
- {ok, Bin} = file:read_file(From),
- ok = file:write_file(To, Bin).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-display_memory_usage() ->
- Info = snmpa:info(snmp_master_agent),
- TreeSize = lists_key1search(tree_size_bytes, Info),
- ProcMem = lists_key1search(process_memory, Info),
- MibDbSize = lists_key1search([db_memory,mib], Info),
- NodeDbSize = lists_key1search([db_memory,node], Info),
- TreeDbSize = lists_key1search([db_memory,tree], Info),
- ?INF("Memory usage: "
- "~n Tree size: ~p"
- "~n Process memory size: ~p"
- "~n Mib db size: ~p"
- "~n Node db size: ~p"
- "~n Tree db size: ~p",
- [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
-
-lists_key1search([], Res) ->
- Res;
-lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- lists_key1search(Keys, Val);
- false ->
- undefined
- end;
-lists_key1search(Key, List) when atom(Key) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- Val;
- false ->
- undefined
- end.
-
-
-regs() ->
- lists:sort(registered()).
diff --git a/lib/snmp/test/snmp_agent_ms_test.erl b/lib/snmp/test/snmp_agent_ms_test.erl
deleted file mode 100644
index 1f34f1c8d1..0000000000
--- a/lib/snmp/test/snmp_agent_ms_test.erl
+++ /dev/null
@@ -1,5649 +0,0 @@
-%%
-%% %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%
-%%
-
--module(snmp_agent_ms_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
--compile(export_all).
-
--define(application, snmp).
-
--include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
--include("snmp_test_lib.hrl").
--define(SNMP_USE_V3, true).
--include_lib("snmp/include/snmp_types.hrl").
-%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
-
-
--define(klas1, [1,3,6,1,2,1,7]).
--define(klas2, [1,3,6,1,2,1,9]).
--define(klas3, [1,3,6,1,2,1,8,1]).
--define(klas4, [1,3,6,1,2,1,8,4]).
--define(sa, [1,3,6,1,4,1,193,2]).
--define(system, [1,3,6,1,2,1,1]).
--define(snmp, [1,3,6,1,2,1,11]).
--define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
--define(ericsson, [1,3,6,1,4,1,193]).
--define(testTrap, [1,3,6,1,2,1,15,0]).
--define(xDescr, [1,3,6,1,2,1,17,1]).
--define(xDescr2, [1,3,6,1,2,1,17,2]).
-
--define(active, 1).
--define(notInService, 2).
--define(notReady, 3).
--define(createAndGo, 4).
--define(createAndWait, 5).
--define(destroy, 6).
-
--define(TRAP_UDP, 5000).
-
--define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
-
--define(str(X), snmp_pdus:bits_to_str(X)).
-
--define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
- [?LINE, self()]),
- receive cont -> ok end
- end).
-
-
--import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
--define(v1_2(V1,V2),
- case get(vsn) of
- v1 -> V1;
- _ -> V2
- end).
-
--define(v1_2_3(V1,V2,V3),
- case get(vsn) of
- v1 -> V1;
- v2 -> V2;
- _ -> V3
- end).
-
-all() ->
-[cases()].
-
-groups() ->
- [{mib_storage, [],
- [{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()},
- {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]},
- {standard_mibs, [],
- [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]},
- {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]},
- {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]},
- {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]},
- {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]},
- {tickets, [], [{group, otp_4394}]},
- {otp_4394, [], [otp_4394_test]}].
-
-init_per_group(otp_4394, Config) ->
- init_otp_4394(Config);
-init_per_group(v2_inform, Config) ->
- init_v2_inform(Config);
-init_per_group(multiple_reqs_2, Config) ->
- init_mul(Config);
-init_per_group(multiple_reqs, Config) ->
- init_mul(Config);
-init_per_group(test_multi_threaded, Config) ->
- init_mt(Config);
-init_per_group(test_v3, Config) ->
- init_v3(Config);
-init_per_group(test_v1_v2, Config) ->
- init_v1_v2(Config);
-init_per_group(test_v2, Config) ->
- init_v2(Config);
-init_per_group(test_v1, Config) ->
- init_v1(Config);
-init_per_group(mib_storage_varm_mnesia, Config) ->
- init_varm_mib_storage_mnesia(Config);
-init_per_group(mib_storage_varm_dets, Config) ->
- init_varm_mib_storage_dets(Config);
-init_per_group(mib_storage_size_check_mnesia, Config) ->
- init_size_check_msm(Config);
-init_per_group(mib_storage_size_check_dets, Config) ->
- init_size_check_msd(Config);
-init_per_group(mib_storage_size_check_ets, Config) ->
- init_size_check_mse(Config);
-init_per_group(mib_storage_mnesia, Config) ->
- init_mib_storage_mnesia(Config);
-init_per_group(mib_storage_dets, Config) ->
- init_mib_storage_dets(Config);
-init_per_group(mib_storage_ets, Config) ->
- init_mib_storage_ets(Config);
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(otp_4394, Config) ->
- finish_otp_4394(Config);
-end_per_group(v2_inform, Config) ->
- finish_v2_inform(Config);
-end_per_group(multiple_reqs_2, Config) ->
- finish_mul(Config);
-end_per_group(multiple_reqs, Config) ->
- finish_mul(Config);
-end_per_group(test_multi_threaded, Config) ->
- finish_mt(Config);
-end_per_group(test_v3, Config) ->
- finish_v3(Config);
-end_per_group(test_v1_v2, Config) ->
- finish_v1_v2(Config);
-end_per_group(test_v2, Config) ->
- finish_v2(Config);
-end_per_group(test_v1, Config) ->
- finish_v1(Config);
-end_per_group(mib_storage_varm_mnesia, Config) ->
- finish_varm_mib_storage_mnesia(Config);
-end_per_group(mib_storage_varm_dets, Config) ->
- finish_varm_mib_storage_dets(Config);
-end_per_group(mib_storage_size_check_mnesia, Config) ->
- finish_size_check_msm(Config);
-end_per_group(mib_storage_size_check_dets, Config) ->
- finish_size_check_msd(Config);
-end_per_group(mib_storage_size_check_ets, Config) ->
- finish_size_check_mse(Config);
-end_per_group(mib_storage_mnesia, Config) ->
- finish_mib_storage_mnesia(Config);
-end_per_group(mib_storage_dets, Config) ->
- finish_mib_storage_dets(Config);
-end_per_group(mib_storage_ets, Config) ->
- finish_mib_storage_ets(Config);
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- Config.
-
-cases() ->
-case ?OSTYPE() of
- vxworks ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_multi_threaded},
- {group, mib_storage}, {group, tickets}];
- _Else ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}]
-end.
-
-
-%%%-----------------------------------------------------------------
-%%% The test case structure is as follows:
-%%%
-%%% init_all - starts mnesia,
-%%%
-%%% init_v1 - starts agent
-%%% simple
-%%% big - e.g. starts/stops subagent, load/unloads mibs
-%%% init_mul
-%%% mul_get
-%%% mul_set
-%%% <etc>
-%%% finish_mul
-%%% <etc>
-%%% finish_v1
-%%%
-%%% init_v2 - starts agent
-%%% finish_v2
-%%%
-%%% init_bilingual - starts agent
-%%% finish_bilingual
-%%%
-%%% finish_all
-%%%
-%%% There is still one problem with these testsuites. If one test
-%%% fails, it may not be possible to run some other cases, as it
-%%% may have e.g. created some row or loaded some table, that it
-%%% didn't undo (since it failed).
-%%%-----------------------------------------------------------------
-
-init_all(Config0) when list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
-
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
-
- %% --
- %% Start nodes
- %%
-
- ?line {ok, SaNode} = start_node(snmp_sa),
- ?line {ok, MgrNode} = start_node(snmp_mgr),
-
-
- %% --
- %% Create necessary files
- %%
-
- Dir = ?config(priv_dir, Config),
- ?DBG("init_all -> Dir ~p", [Dir]),
-
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
-
- file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
-
- file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
-
- file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
- ?DBG("init_all -> SaDir ~p", [SaDir]),
-
-
- %% --
- %% Start and initiate mnesia
- %%
-
- ?DBG("init_all -> load application mnesia", []),
- ?line ok = application:load(mnesia),
-
- ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, load, [mnesia]),
-
- ?DBG("init_all -> application mnesia: set_env dir",[]),
- ?line application_controller:set_env(mnesia, dir,
- filename:join(Dir, "Mnesia1")),
-
- ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(Dir, "Mnesia2")]),
-
- ?DBG("init_all -> create mnesia schema",[]),
- ?line ok = mnesia:create_schema([SaNode, node()]),
-
- ?DBG("init_all -> start application mnesia",[]),
- ?line ok = application:start(mnesia),
-
- ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
- ?line ok = rpc:call(SaNode, application, start, [mnesia]),
- Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
- Config].
-
-finish_all(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- stop_node(SaNode),
- stop_node(MgrNode),
- application:stop(mnesia).
-
-start_v1_agent(Config) when list(Config) ->
- start_agent(Config, [v1]).
-
-start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
- start_agent(Config, [v1], Opts).
-
-start_v2_agent(Config) when list(Config) ->
- start_agent(Config, [v2]).
-
-start_v3_agent(Config) when list(Config) ->
- start_agent(Config, [v3]).
-
-start_bilingual_agent(Config) when list(Config) ->
- start_agent(Config, [v1,v2]).
-
-start_multi_threaded_agent(Config) when list(Config) ->
- start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
-
-stop_agent(Config) when list(Config) ->
- ?LOG("stop_agent -> entry with"
- "~n Config: ~p",[Config]),
-
- {Sup, Par} = ?config(snmp_sup, Config),
- ?DBG("stop_agent -> attempt to stop (sup) ~p"
- "~n Sup: ~p"
- "~n Par: ~p",
- [Sup,
- (catch process_info(Sup)),
- (catch process_info(Par))]),
- stop_sup(Sup, Par),
-
- {Sup2, Par2} = ?config(snmp_sub, Config),
- ?DBG("stop_agent -> attempt to stop (sub) ~p"
- "~n Sup2: ~p"
- "~n Par2: ~p",
- [Sup2,
- (catch process_info(Sup2)),
- (catch process_info(Par2))]),
- stop_sup(Sup2, Par2),
-
- ?DBG("stop_agent -> done - now cleanup config", []),
- C1 = lists:keydelete(snmp_sup, 1, Config),
- lists:keydelete(snmp_sub, 1, C1).
-
-
-stop_sup(Pid, _) when node(Pid) == node() ->
- case (catch process_info(Pid)) of
- PI when list(PI) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- exit(Pid, kill),
- await_stopped(Pid, Ref);
- {'EXIT', _Reason} ->
- ?LOG("stop_sup -> ~p not running", [Pid]),
- ok
- end;
-stop_sup(Pid, _) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- ?LOG("stop_sup -> Ref: ~p", [Ref]),
- %% Pid ! {'EXIT', Parent, shutdown}, % usch
- exit(Pid, kill),
- await_stopped(Pid, Ref).
-
-await_stopped(Pid, Ref) ->
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ?DBG("received down message for ~p", [Pid]),
- ok
- after 10000 ->
- ?INF("await_stopped -> timeout for ~p",[Pid]),
- erlang:demonitor(Ref),
- ?FAIL({failed_stop,Pid})
- end.
-
-
-start_agent(Config, Vsn) ->
- start_agent(Config, Vsn, []).
-start_agent(Config, Vsn, Opts) ->
- ?LOG("start_agent -> entry (~p) with"
- "~n Config: ~p"
- "~n Vsn: ~p"
- "~n Opts: ~p",[node(), Config, Vsn, Opts]),
-
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
- snmp_app_env_init(vsn_init(Vsn) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, trace},
- {snmp_symbolic_store_verbosity, trace},
- {snmp_note_store_verbosity, trace},
- {snmp_net_if_verbosity, trace}],
- Opts),
-
-
- process_flag(trap_exit,true),
-
- {ok, AppSup} = snmp_app_sup:start_link(),
- unlink(AppSup),
- ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
-
- ?DBG("start_agent -> start master agent (old style)",[]),
- Sup = case (catch snmpa_app:start(normal)) of
- {ok, S} ->
- ?DBG("start_agent -> started, Sup: ~p",[S]),
- S;
-
- Else ->
- ?DBG("start_agent -> unknown result: ~n~p",[Else]),
- %% Get info about the apps we depend on
- MnesiaInfo = mnesia_running(),
- ?FAIL({start_failed,Else,MnesiaInfo})
- end,
-
- ?DBG("start_agent -> unlink from supervisor",[]),
- ?line unlink(Sup),
- ?line SaDir = ?config(sa_dir, Config),
- ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
- ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
- ?DBG("start_agent -> done",[]),
- ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
-
-
-vsn_init(Vsn) ->
- vsn_init([v1,v2,v3], Vsn, []).
-
-vsn_init([], _Vsn, Acc) ->
- Acc;
-vsn_init([V|Vsns], Vsn, Acc) ->
- case lists:member(V, Vsn) of
- true ->
- vsn_init(Vsns, Vsn, [{V, true}|Acc]);
- false ->
- vsn_init(Vsns, Vsn, [{V, false}|Acc])
- end.
-
-snmp_app_env_init(Env0, Opts) ->
- ?DBG("snmp_app_env_init -> unload snmp",[]),
- ?line application:unload(snmp),
- ?DBG("snmp_app_env_init -> load snmp",[]),
- ?line application:load(snmp),
- ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
- F1 = fun({Key,Val} = New, Acc0) ->
- ?DBG("snmp_app_env_init -> "
- "updating setting ~p to ~p", [Key, Val]),
- case lists:keyreplace(Key, 1, Acc0, New) of
- Acc0 ->
- [New|Acc0];
- Acc ->
- Acc
- end
- end,
- Env = lists:foldr(F1, Env0, Opts),
- ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
- F2 = fun({Key,Val}) ->
- ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
- application_controller:set_env(snmp, Key, Val)
- end,
- lists:foreach(F2, Env).
-
-
-
-
-%% Test if application is running
-mnesia_running() -> ?IS_MNESIA_RUNNING().
-crypto_running() -> ?IS_CRYPTO_RUNNING().
-
-
-start_sub(Dir) ->
- ?DBG("start_sub -> entry",[]),
- Opts = [{db_dir, Dir},
- {supervisor, [{verbosity, trace}]}],
- %% BMK BMK
-% {ok, P} = snmp_supervisor:start_sub(Dir),
- {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
- unlink(P),
- {ok, {P, self()}}.
-
-create_tables(SaNode) ->
- ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
- {attributes, [a1,a2]}]).
-
-delete_tables() ->
- mnesia:delete_table(friendsTable2),
- mnesia:delete_table(kompissTable2),
- mnesia:delete_table(snmp_variables).
-
-%% Creation is done in runtime!
-delete_mib_storage_mnesia_tables() ->
- mnesia:delete_table(snmpa_mib_data),
- mnesia:delete_table(snmpa_mib_tree),
- mnesia:delete_table(snmpa_symbolic_store).
-
-%%-----------------------------------------------------------------
-%% A test case is always one of:
-%% - v1 specific case
-%% - v2 specific case
-%% - v1 and v2 case
-%% All v1 specific cases are prefixed with v1_, and all v2 with
-%% v2_. E.g. v1_trap/v2_trap.
-%%
-%% All other cases are shared. However, the testserver uses the name
-%% of the case to generate a file for that case. The same case cannot
-%% be used in different configurations in the same suite. Therefore
-%% all these functions exists in two variants, the base function
-%% <base>, and a second version <base>_2. There may be several
-%% versions as well, <base>_N.
-%%-----------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-mib_storage_ets_cases() ->
-[mse_simple, mse_v1_processing, mse_big, mse_big2,
- mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
- mse_sa_error, mse_next_across_sa, mse_undo,
- mse_standard_mib, mse_community_mib, mse_framework_mib,
- mse_target_mib, mse_notification_mib,
- mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
- mse_mib_of].
-
-mib_storage_dets_cases() ->
-[msd_simple, msd_v1_processing, msd_big, msd_big2,
- msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
- msd_sa_error, msd_next_across_sa, msd_undo,
- msd_standard_mib, msd_community_mib, msd_framework_mib,
- msd_target_mib, msd_notification_mib,
- msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
- msd_mib_of].
-
-mib_storage_mnesia_cases() ->
-[msm_simple, msm_v1_processing, msm_big, msm_big2,
- msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
- msm_sa_error, msm_next_across_sa, msm_undo,
- msm_standard_mib, msm_community_mib, msm_framework_mib,
- msm_target_mib, msm_notification_mib,
- msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
- msm_mib_of].
-
-mse_size_check_cases() ->
-[mse_size_check].
-
-msd_size_check_cases() ->
-[msd_size_check].
-
-msm_size_check_cases() ->
-[msm_size_check].
-
-varm_mib_storage_dets_cases() ->
-[msd_varm_mib_start].
-
-varm_mib_storage_mnesia_cases() ->
-[msm_varm_mib_start].
-
-init_mib_storage_ets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,ets},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- init_ms(Config, [MibStorage]).
-
-init_ms(Config, Opts) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
-
-init_size_check_mse(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, ets},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msd(Config) when list(Config) ->
- AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage, {dets, AgentDir}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msm(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, {mnesia,[]}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_ms(Config, Opts) when list(Config) ->
- SaNode = ?GCONF(snmp_sa, Config),
- %% We are using v3 here, so crypto must be supported or else...
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end,
- create_tables(SaNode),
- AgentDir = ?GCONF(agent_dir, Config),
- MgrDir = ?GCONF(mgr_dir, Config),
- Ip = ?GCONF(ip, Config),
- ?line ok =
- config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_agent(Config, [v3], Opts)].
-
-init_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_dets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-init_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_mnesia -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-finish_mib_storage_ets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_ets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_dets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_dets -> entry", []),
- delete_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_size_check_mse(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msd(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msm(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_ms(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%% These are just interface functions to fool the test server
-mse_simple(X) -> simple(X).
-mse_v1_processing(X) -> v1_processing(X).
-mse_big(X) -> big(X).
-mse_big2(X) -> big2(X).
-mse_loop_mib(X) -> loop_mib(X).
-mse_api(X) -> api(X).
-mse_sa_register(X) -> sa_register(X).
-mse_v1_trap(X) -> v1_trap(X).
-mse_sa_error(X) -> sa_error(X).
-mse_next_across_sa(X) -> next_across_sa(X).
-mse_undo(X) -> undo(X).
-mse_standard_mib(X) -> snmp_standard_mib(X).
-mse_community_mib(X) -> snmp_community_mib(X).
-mse_framework_mib(X) -> snmp_framework_mib(X).
-mse_target_mib(X) -> snmp_target_mib(X).
-mse_notification_mib(X) -> snmp_notification_mib(X).
-mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-mse_sparse_table(X) -> sparse_table(X).
-mse_me_of(X) -> ms_me_of(X).
-mse_mib_of(X) -> ms_mib_of(X).
-
-msd_simple(X) -> simple(X).
-msd_v1_processing(X) -> v1_processing(X).
-msd_big(X) -> big(X).
-msd_big2(X) -> big2(X).
-msd_loop_mib(X) -> loop_mib(X).
-msd_api(X) -> api(X).
-msd_sa_register(X) -> sa_register(X).
-msd_v1_trap(X) -> v1_trap(X).
-msd_sa_error(X) -> sa_error(X).
-msd_next_across_sa(X) -> next_across_sa(X).
-msd_undo(X) -> undo(X).
-msd_standard_mib(X) -> snmp_standard_mib(X).
-msd_community_mib(X) -> snmp_community_mib(X).
-msd_framework_mib(X) -> snmp_framework_mib(X).
-msd_target_mib(X) -> snmp_target_mib(X).
-msd_notification_mib(X) -> snmp_notification_mib(X).
-msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msd_sparse_table(X) -> sparse_table(X).
-msd_me_of(X) -> ms_me_of(X).
-msd_mib_of(X) -> ms_mib_of(X).
-
-msm_simple(X) -> simple(X).
-msm_v1_processing(X) -> v1_processing(X).
-msm_big(X) -> big(X).
-msm_big2(X) -> big2(X).
-msm_loop_mib(X) -> loop_mib(X).
-msm_api(X) -> api(X).
-msm_sa_register(X) -> sa_register(X).
-msm_v1_trap(X) -> v1_trap(X).
-msm_sa_error(X) -> sa_error(X).
-msm_next_across_sa(X) -> next_across_sa(X).
-msm_undo(X) -> undo(X).
-msm_standard_mib(X) -> snmp_standard_mib(X).
-msm_community_mib(X) -> snmp_community_mib(X).
-msm_framework_mib(X) -> snmp_framework_mib(X).
-msm_target_mib(X) -> snmp_target_mib(X).
-msm_notification_mib(X) -> snmp_notification_mib(X).
-msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msm_sparse_table(X) -> sparse_table(X).
-msm_me_of(X) -> ms_me_of(X).
-msm_mib_of(X) -> ms_mib_of(X).
-
-
-mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
-msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
-msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
-
-msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
-msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
-
-ms_size_check(suite) -> [];
-ms_size_check(Config) when list(Config) ->
- p("ms_size_check..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?LOG("mib server size check...", []),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMPv2-MIB"),
- ?line load_master_std("SNMPv2-TM"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMPv2-MIB"),
- ?line unload_master("SNMPv2-TM"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-
-varm_mib_start(suite) -> [];
-varm_mib_start(Config) when list(Config) ->
- p("varm_mib_start..."),
- ?LOG("varm_mib_start -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- %% Start the agent
- Opts = ?GCONF(agent_opts, Config),
- Config1 = start_v1_agent(Config, Opts),
-
- %% Sleep some in order for the agent to start properly
- ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
- ?SLEEP(5000),
-
- %% Load all the mibs
- HardwiredMibs = loaded_mibs(),
- ?DBG("varm_mib_start -> load all mibs", []),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
-
- %% Unload the hardwired mibs
- ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
- ?SLEEP(1000),
- ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
- ?line unload_mibs(HardwiredMibs), %% unload hardwired
-
- ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
- ?SLEEP(1000),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- Config2 = stop_agent(Config1),
-
- %% Sleep some in order for the agent to stop properly
- ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
- ?SLEEP(5000),
-
- %% Start the agent (again)
- ?DBG("varm_mib_start -> start the agent", []),
- Config3 = start_v1_agent(Config2, Opts),
-
- ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
- ?SLEEP(5000),
-
- %% Perform the test(s)
- ?DBG("varm_mib_start -> perform the tests", []),
- try_test(snmp_community_mib),
- try_test(snmp_framework_mib),
- try_test(snmp_target_mib),
- try_test(snmp_notification_mib),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- stop_agent(Config3),
- ok.
-
-
--define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
--define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
--define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-ms_me_of(suite) -> [];
-ms_me_of(Config) when list(Config) ->
- p("ms_me_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = me_of(?snmpTrapCommunity_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = me_of(?vacmViewSpinLock_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-me_of(Oid) ->
- case snmpa:me_of(Oid) of
- {ok, #me{oid = Oid}} ->
- ok;
- {ok, #me{oid = OtherOid}} ->
- case lists:reverse(Oid) of
- [0|Rest] ->
- case lists:reverse(Rest) of
- OtherOid ->
- ok;
- AnotherOid ->
- {error, {invalid_oid, Oid, AnotherOid}}
- end;
- _ ->
- {error, {invalid_oid, Oid, OtherOid}}
- end;
- {error, Reason} ->
- {error, Reason};
- Else ->
- {error, Else}
- end.
-
-
-ms_mib_of(suite) -> [];
-ms_mib_of(Config) when list(Config) ->
- p("ms_mib_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
- 'SNMP-USER-BASED-SM-MIB'),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-mib_of(Oid, ExpectedMibName) ->
- ?DBG("mib_of -> entry with"
- "~n Oid: ~p"
- "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
- %% case snmpa:mib_of(Oid) of
- MibOf = snmpa:mib_of(Oid),
- ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
- case MibOf of
- {ok, ExpectedMibName} ->
- ok;
- {ok, OtherMibName} ->
- {error, {invalid_mib, ExpectedMibName, OtherMibName}};
- {error, Reason} ->
- {error, Reason};
- Else ->
- ?DBG("mib_of -> Else: ~n~p", [Else]),
- {error, Else}
- end.
-
-
-app_info(suite) -> [];
-app_info(Config) when list(Config) ->
- SnmpDir = app_dir(snmp),
- SslDir = app_dir(ssl),
- CryptoDir = app_dir(crypto),
- Attr = snmp:module_info(attributes),
- AppVsn =
- case lists:keysearch(app_vsn, 1, Attr) of
- {value, {app_vsn, V}} ->
- V;
- false ->
- "undefined"
- end,
- io:format("Root dir: ~s~n"
- "SNMP: Application dir: ~s~n"
- " Application ver: ~s~n"
- "SSL: Application dir: ~s~n"
- "CRYPTO: Application dir: ~s~n",
- [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
- ok.
-
-app_dir(App) ->
- case code:lib_dir(App) of
- D when list(D) ->
- filename:basename(D);
- {error, _Reason} ->
- "undefined"
- end.
-
-
-
-%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].
-
-init_v1(Config) when list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v1} | start_v1_agent(Config)].
-
-finish_v1(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v2_cases() -> [loop_mib_2];
-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].
-
-init_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_v2_agent(Config)].
-
-finish_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-v1_v2_cases() ->
-[simple_bi].
-
-init_v1_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, bilingual} | start_bilingual_agent(Config)].
-
-finish_v1_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v3_cases() -> [loop_mib_3];
-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].
-
-init_v3(Config) when list(Config) ->
- %% Make sure crypto works, otherwise start_agent will fail
- %% and we will be stuck with a bunch of mnesia tables for
- %% the rest of this suite...
- ?DBG("start_agent -> start crypto app",[]),
- case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end
- end,
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
- tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_v3_agent(Config)].
-
-finish_v3(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-mt_cases() ->
-[multi_threaded, mt_trap].
-
-init_mt(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_multi_threaded_agent(Config)].
-
-finish_mt(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-%% This one *must* be run first in each case.
-init_case(Config) when list(Config) ->
- ?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
-
- SaHost = ?HOSTNAME(SaNode),
- MgrHost = ?HOSTNAME(MgrNode),
- MasterHost = ?HOSTNAME(MasterNode),
- {ok, MasterIP} = snmp_misc:ip(MasterHost),
- {ok, MIP} = snmp_misc:ip(MgrHost),
- {ok, SIP} = snmp_misc:ip(SaHost),
-
-
- put(mgr_node, MgrNode),
- put(sa_node, SaNode),
- put(master_node, MasterNode),
- put(sa_host, SaHost),
- put(mgr_host, MgrHost),
- put(master_host, MasterHost),
- put(mip, tuple_to_list(MIP)),
- put(masterip , tuple_to_list(MasterIP)),
- put(sip, tuple_to_list(SIP)),
-
- MibDir = ?config(mib_dir, Config),
- put(mib_dir, MibDir),
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- put(std_mib_dir, StdM),
-
- MgrDir = ?config(mgr_dir, Config),
- put(mgr_dir, MgrDir),
-
- put(vsn, ?config(vsn, Config)),
- ?DBG("init_case -> exit with"
- "~n MasterNode: ~p"
- "~n SaNode: ~p"
- "~n MgrNode: ~p"
- "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
- {SaNode, MgrNode, MibDir}.
-
-load_master(Mib) ->
- ?DBG("load_master -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
-
-load_master_std(Mib) ->
- ?DBG("load_master_std -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
-
-unload_master(Mib) ->
- ?DBG("unload_master -> entry with"
- "~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
-
-loaded_mibs() ->
- ?DBG("loaded_mibs -> entry",[]),
- Info = snmpa:info(snmp_master_agent),
- {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
- [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
-
-unload_mibs(Mibs) ->
- ?DBG("unload_mibs -> entry with"
- "~n Mibs: ~p", [Mibs]),
- ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
-
-start_subagent(SaNode, RegTree, Mib) ->
- ?DBG("start_subagent -> entry with"
- "~n SaNode: ~p"
- "~n RegTree: ~p"
- "~n Mib: ~p", [SaNode, RegTree, Mib]),
- MA = whereis(snmp_master_agent),
- ?DBG("start_subagent -> MA: ~p", [MA]),
- MibDir = get(mib_dir),
- Mib1 = join(MibDir,Mib),
- %% BMK BMK
-% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
- case rpc:call(SaNode, snmpa_supervisor,
- start_sub_agent, [MA, RegTree, [Mib1]]) of
- {ok, SA} ->
- ?DBG("start_subagent -> SA: ~p", [SA]),
- {ok, SA};
- Error ->
- ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
- end.
-
-stop_subagent(SA) ->
- ?DBG("stop_subagent -> entry with"
- "~n SA: ~p", [SA]),
- %% BNK BMK
- %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
- rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
-
-%%-----------------------------------------------------------------
-%% This function takes care of the old OTP-SNMPEA-MIB.
-%% Unfortunately, the testcases were written to use the data in the
-%% internal tables, and these table are now obsolete and not used
-%% by the agent. Therefore, we emulate them by using
-%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
-%%
-%% These two rows must exist in intCommunityTable
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
-%% (But with the manager's IP address)
-%%
-%%-----------------------------------------------------------------
-init_old() ->
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [6 | "public"],
- {get(mip), "public", 2, 2}),
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [13 | "standard trap"],
- {get(mip), "standard trap", 2, 1}),
- snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
-
-
-
-simple(suite) -> [];
-simple(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(simple_standard_test).
-
-simple_2(X) -> simple(X).
-
-simple_bi(suite) -> [];
-simple_bi(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(vsn, v1), % First, try v1 manager
- try_test(simple_standard_test),
-
- put(vsn, v2), % Then, try v2 manager
- try_test(simple_standard_test).
-
-simple_3(X) ->
- simple(X).
-
-big(suite) -> [];
-big(Config) when list(Config) ->
- ?DBG("big -> entry", []),
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-big_2(X) -> big(X).
-
-big_3(X) -> big(X).
-
-
-big2(suite) -> [];
-big2(Config) when list(Config) ->
- %% This is exactly the same tests as 'big', but with the
- %% v2 equivalent of the mibs.
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
-
-big2_2(X) -> big2(X).
-
-big2_3(X) -> big2(X).
-
-
-multi_threaded(suite) -> [];
-multi_threaded(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(multi_threaded_test),
- ?line unload_master("Test1").
-
-mt_trap(suite) -> [];
-mt_trap(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- ?line load_master("TestTrapv2"),
- try_test(mt_trap_test, [MA]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("Test1").
-
-v2_types(suite) -> [];
-v2_types(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(types_v2_test),
- ?line unload_master("Test1").
-
-v2_types_3(X) -> v2_types(X).
-
-
-implied(suite) -> [];
-implied(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(implied_test,[MA]),
- ?line unload_master("Test1").
-
-implied_3(X) -> implied(X).
-
-
-sparse_table(suite) -> [];
-sparse_table(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(sparse_table_test),
- ?line unload_master("Test1").
-
-sparse_table_2(X) -> sparse_table(X).
-
-sparse_table_3(X) -> sparse_table(X).
-
-cnt_64(suite) -> [];
-cnt_64(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(cnt_64_test, [MA]),
- ?line unload_master("Test1").
-
-cnt_64_2(X) -> cnt_64(X).
-
-cnt_64_3(X) -> cnt_64(X).
-
-opaque(suite) -> [];
-opaque(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(opaque_test),
- ?line unload_master("Test1").
-
-opaque_2(X) -> opaque(X).
-
-opaque_3(X) -> opaque(X).
-
-
-change_target_addr_config(suite) -> [];
-change_target_addr_config(Config) when list(Config) ->
- p("Testing changing target address config..."),
- ?LOG("change_target_addr_config -> entry",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(sname,snmp_suite),
- put(verbosity,trace),
-
- MA = whereis(snmp_master_agent),
-
- ?LOG("change_target_addr_config -> load TestTrap",[]),
- ?line load_master("TestTrap"),
-
- ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,trace),
-
- %% First send some traps that will arive att the original manager
- ?LOG("change_target_addr_config -> send trap",[]),
- try_test(ma_trap1, [MA]),
-
- ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
-
- %% Start new dummy listener
- ?LOG("change_target_addr_config -> start dummy manager",[]),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
-
- %% Reconfigure
- ?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- %% Send the trap again
- ?LOG("change_target_addr_config -> send trap again",[]),
- catch dummy_manager_send_trap2(Pid),
-
- ?LOG("change_target_addr_config -> await trap ack",[]),
- catch dummy_manager_await_trap2_ack(),
-
- ?LOG("change_target_addr_config -> stop dummy manager",[]),
- ?line ok = dummy_manager_stop(Pid),
-
- ?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
-
- ?LOG("change_target_addr_config -> unload TestTrap",[]),
- ?line unload_master("TestTrap").
-
-
-dummy_manager_start(MA) ->
- ?DBG("dummy_manager_start -> entry",[]),
- Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
- ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
- await_dummy_manager_started(Pid).
-
-await_dummy_manager_started(Pid) ->
- receive
- {dummy_manager_started,Pid,Port} ->
- ?DBG("dummy_manager_start -> acknowledge received with"
- "~n Port: ~p",[Port]),
- {ok,Pid,Port};
- {'EXIT', Pid, Reason} ->
- {error, Pid, Reason};
- O ->
- ?LOG("dummy_manager_start -> received unknown message:"
- "~n ~p",[O]),
- await_dummy_manager_started(Pid)
- end.
-
-dummy_manager_stop(Pid) ->
- ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
- Pid ! stop,
- receive
- {dummy_manager_stopping, Pid} ->
- ?DBG("dummy_manager_stop -> acknowledge received",[]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_stop -> timeout",[]),
- timeout
- end.
-
-dummy_manager_send_trap2(Pid) ->
- ?DBG("dummy_manager_send_trap2 -> entry",[]),
- Pid ! {send_trap,testTrap2}.
-
-dummy_manager_await_trap2_ack() ->
- ?DBG("dummy_manager_await_trap2 -> entry",[]),
- receive
- {received_trap,Trap} ->
- ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
- %% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
- %% is no relation between these two test cases as far as I
- %% able to figure out...
- sleep(60000),
- ok;
- O ->
- ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_await_trap2 -> timeout",[]),
- timeout
- end.
-
-dummy_manager_init(Parent,MA) ->
- ?DBG("dummy_manager_init -> entry with"
- "~n Parent: ~p"
- "~n MA: ~p",[Parent,MA]),
- {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
- ?DBG("dummy_manager_init -> S: ~p",[S]),
- {ok,Port} = inet:port(S),
- ?DBG("dummy_manager_init -> Port: ~p",[Port]),
- Parent ! {dummy_manager_started,self(),Port},
- dummy_manager_loop(Parent,S,MA).
-
-dummy_manager_loop(P,S,MA) ->
- ?LOG("dummy_manager_loop -> ready for receive",[]),
- receive
- {send_trap,Trap} ->
- ?LOG("dummy_manager_loop -> received trap send request"
- "~n Trap: ~p",[Trap]),
- snmpa:send_trap(MA, Trap, "standard trap"),
- dummy_manager_loop(P,S,MA);
- {udp, _UdpId, Ip, UdpPort, Bytes} ->
- ?LOG("dummy_manager_loop -> received upd message"
- "~n from: ~p:~p"
- "~n size: ~p",
- [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
- R = dummy_manager_handle_message(Bytes),
- ?DBG("dummy_manager_loop -> R: ~p",[R]),
- P ! R,
- dummy_manager_loop(P,S,MA);
- stop ->
- ?DBG("dummy_manager_loop -> received stop request",[]),
- P ! {dummy_manager_stopping, self()},
- gen_udp:close(S),
- exit(normal);
- O ->
- ?LOG("dummy_manager_loop -> received unknown message:"
- "~n ~p",[O]),
- dummy_manager_loop(P,S,MA)
- end.
-
-dummy_manager_message_sz(B) when binary(B) ->
- size(B);
-dummy_manager_message_sz(L) when list(L) ->
- length(L);
-dummy_manager_message_sz(_) ->
- undefined.
-
-dummy_manager_handle_message(Bytes) ->
- case (catch snmp_pdus:dec_message(Bytes)) of
- {'EXIT',Reason} ->
- ?ERR("dummy_manager_handle_message -> "
- "failed decoding message only:~n ~p",[Reason]),
- {error,Reason};
- M ->
- ?DBG("dummy_manager_handle_message -> decoded message:"
- "~n ~p",[M]),
- {received_trap,M}
- end.
-
-
-api(suite) -> [];
-api(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(api_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-api_2(X) -> api(X).
-
-api_3(X) -> api(X).
-
-
-subagent(suite) -> [];
-subagent(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- try_test(load_test_sa),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
-
- p("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(load_test),
-
- p("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(unreg_test),
- p("Testing register subagent..."),
- rpc:call(SaNode, snmp, register_subagent,
- [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- ?line stop_subagent(SA),
- try_test(unreg_test).
-
-subagent_2(X) -> subagent(X).
-
-subagent_3(X) -> subagent(X).
-
-
-mnesia(suite) -> [];
-mnesia(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent with mnesia impl..."),
- {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- try_test(big_test_2),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
-
-mnesia_2(X) -> mnesia(X).
-
-mnesia_3(X) -> mnesia(X).
-
-
-
-mul_cases() ->
-[mul_get, mul_get_err, mul_next, mul_next_err,
- mul_set_err].
-
-
-multiple_reqs_3(_X) ->
- {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
-
-
-mul_cases_2() ->
-[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
- mul_set_err_2].
-
-
-mul_cases_3() ->
- [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
-
-
-init_mul(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- [{mul_sub, SA} | Config].
-
-finish_mul(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- SA = ?config(mul_sub, Config),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
- lists:keydelete(mul_sub, 1, Config).
-
-mul_get(suite) -> [];
-mul_get(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get..."),
- try_test(do_mul_get).
-
-mul_get_2(X) -> mul_get(X).
-
-mul_get_3(X) -> mul_get(X).
-
-
-mul_get_err(suite) -> [];
-mul_get_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get with error..."),
- try_test(do_mul_get_err).
-
-mul_get_err_2(X) -> mul_get_err(X).
-
-mul_get_err_3(X) -> mul_get_err(X).
-
-
-mul_next(suite) -> [];
-mul_next(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next).
-
-mul_next_2(X) -> mul_next(X).
-
-mul_next_3(X) -> mul_next(X).
-
-
-mul_next_err(suite) -> [];
-mul_next_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next_err).
-
-mul_next_err_2(X) -> mul_next_err(X).
-
-mul_next_err_3(X) -> mul_next_err(X).
-
-
-mul_set(suite) -> [];
-mul_set(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set..."),
- try_test(do_mul_set).
-
-mul_set_2(X) -> mul_set(X).
-
-mul_set_3(X) -> mul_set(X).
-
-
-mul_set_err(suite) -> [];
-mul_set_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set with error..."),
- try_test(do_mul_set_err).
-
-mul_set_err_2(X) -> mul_set_err(X).
-
-mul_set_err_3(X) -> mul_set_err(X).
-
-
-sa_register(suite) -> [];
-sa_register(Config) when list(Config) ->
- ?DBG("sa_register -> entry", []),
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?DBG("sa_register -> start subagent", []),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
-
- ?DBG("sa_register -> unregister subagent", []),
- p("Testing unregister subagent (2)..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Loading SA-MIB..."),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
- ?DBG("sa_register -> register subagent", []),
- rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
- try_test(sa_mib),
-
- ?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
-
-sa_register_2(X) -> sa_register(X).
-
-sa_register_3(X) -> sa_register(X).
-
-
-v1_trap(suite) -> [];
-v1_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_trap1, [MA]),
- try_test(ma_trap2, [MA]),
- try_test(ma_v2_2_v1_trap, [MA]),
- try_test(ma_v2_2_v1_trap2, [MA]),
-
- p("Testing trap sending from subagent..."),
- try_test(sa_trap1, [SA]),
- try_test(sa_trap2, [SA]),
- try_test(sa_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v2_trap(suite) -> [];
-v2_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
-
- try_test(ma_v2_trap1, [MA]),
- try_test(ma_v2_trap2, [MA]),
- try_test(ma_v1_2_v2_trap, [MA]),
- try_test(ma_v1_2_v2_trap2, [MA]),
-
- try_test(sa_mib),
- p("Testing trap sending from subagent..."),
- try_test(sa_v1_2_v2_trap1, [SA]),
- try_test(sa_v1_2_v2_trap2, [SA]),
- try_test(sa_v1_2_v2_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v3_trap(X) ->
- v2_trap(X).
-
-
-v3_inform(_X) ->
- %% v2_inform(X).
- {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
-
-init_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-init_v3_inform(X) ->
- init_v2_inform(X).
-
-finish_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-finish_v3_inform(X) ->
- finish_v2_inform(X).
-
-
-
-v2_inform_i(suite) -> [];
-v2_inform_i(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing inform sending from master agent... NOTE! This test\ntakes a "
- "few minutes (5) to complete."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_v2_inform1, [MA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2").
-
-v3_inform_i(X) -> v2_inform_i(X).
-
-
-sa_error(suite) -> [];
-sa_error(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing sa bad value (is_set_ok)..."),
- try_test(sa_errs_bad_value),
-
- p("Testing sa gen err (set)..."),
- try_test(sa_errs_gen_err),
-
- p("Testing too big..."),
- try_test(sa_too_big),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- stop_subagent(SA).
-
-sa_error_2(X) -> sa_error(X).
-
-sa_error_3(X) -> sa_error(X).
-
-
-next_across_sa(suite) -> [];
-next_across_sa(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Loading another subagent mib..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
-
- rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- p("Testing next across subagent (endOfMibView from SA)..."),
- try_test(next_across_sa),
-
- p("Unloading mib"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Starting another subagent"),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
- p("Testing next across subagent (wrong prefix from SA)..."),
- try_test(next_across_sa),
-
- stop_subagent(SA),
- stop_subagent(SA2).
-
-next_across_sa_2(X) -> next_across_sa(X).
-
-next_across_sa_3(X) -> next_across_sa(X).
-
-
-undo(suite) -> [];
-undo(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing undo phase at master agent..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
- try_test(undo_test),
- try_test(api_test2),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
-
- p("Testing bad return values from instrum. funcs..."),
- try_test(bad_return),
-
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
-
- p("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
- try_test(undo_test),
- try_test(api_test3),
-
- p("Testing undo phase across master/subagents..."),
- try_test(undo_test),
- try_test(api_test3),
- stop_subagent(SA).
-
-undo_2(X) -> undo(X).
-
-undo_3(X) -> undo(X).
-
-%% Req. Test2
-v1_processing(suite) -> [];
-v1_processing(Config) when list(Config) ->
- ?DBG("v1_processing -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v1_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v2_processing(suite) -> [];
-v2_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v3_processing(suite) -> [];
-v3_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc), % same as v2!
- ?line unload_master("Test2").
-
-
-%% We'll try get/set/trap and inform for all the auth & priv protocols.
-%% For informs, the mgr is auth-engine. The agent has to sync. This is
-%% accomplished by the first inform sent. That one will generate a
-%% report, which makes it in sync. The notification-generating
-%% application times out, and send again. This time it'll work.
-
-v3_crypto_basic(suite) -> [];
-v3_crypto_basic(_Config) ->
- EID = [0,0,0,0,0,0,0,0,0,0,0,2],
- %% From rfc2274 appendix A.3.1
- ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
- ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
- 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
- KMd5_1,
- %% From rfc2274 appendix A.3.2
- ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
- ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
- 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
- KSHA_1,
- %% From rfc2274, appendix A.5.1
- ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
- 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
- snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- %% From rfc2274, appendix A.5.2
- ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
- 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
- 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- KSHA_1t = lists:sublist(KSHA_1, 16),
- KSHA_2t = lists:sublist(KSHA_2, 16),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
- 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
-
- %% Try with correct random
- ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
- ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
- ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
- ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
- ok.
-
-
-
-v3_md5_auth(suite) -> [];
-v3_md5_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing MD5 authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_sha_auth(suite) -> [];
-v3_sha_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing SHA authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_des_priv(suite) -> [];
-v3_des_priv(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing DES encryption...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-%% Make sure mgr is in sync with agent
-v3_sync(Funcs) ->
- ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
- g([[sysDescr, 0]]),
- expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
- g([[sysDescr, 0]]),
- expect(433, [{[sysDescr,0], any}]),
- lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
-
-v3_inform_sync(MA) ->
- ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
- "standard inform", []),
- %% Make sure agent is in sync with mgr...
- ?DBG("v3_sync -> wait some time: ",[]),
- sleep(20000), % more than 1500*10 in target_addr.conf
- ?DBG("v3_sync -> await response",[]),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]).
-
-
-v2_caps(suite) -> [];
-v2_caps(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(v2_caps_i, [node()]).
-
-v2_caps_3(X) -> v2_caps(X).
-
-
-v2_caps_i(Node) ->
- ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
- g([[sysORID, Idx], [sysORDescr, Idx]]),
- ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
- {[sysORDescr, Idx], "test cap"}]),
- ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
- g([[sysORID, Idx]]),
- ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
-
-
-%% Req. Test2
-v1_proc() ->
- ?DBG("v1_proc -> entry", []),
- %% According to RFC1157.
- %% Template: <Section>:<list no>
- v1_get_p(),
- v1_get_next_p(),
- v1_set_p().
-
-
-v1_get_p() ->
- %% 4.1.2:1
- g([[test2]]),
- ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
- g([[tDescr]]),
- ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
- g([[tDescr2,0]]),
- ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
- g([[tDescr3,0]]),
- ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
- g([[tDescr4,0]]),
- ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
- {[tDescr,0], 'NULL'}]),
- g([[sysDescr,3]]),
- ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
-
- %% 4.1.2:2
- g([[tTable]]),
- ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
- g([[tEntry]]),
- ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
-
- %% 4.1.2:3
- g([[tTooBig, 0]]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.2:4
- g([[tGenErr1, 0]]),
- ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]).
-
-
-v1_get_next_p() ->
- %% 4.1.3:1
- gn([[1,3,7,1]]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
- gn([[tDescr2]]),
- ?line expect(11, tooBig, 0, any),
-
- %% 4.1.3:2
- gn([[tTooBig]]),
- io:format("We currently don't handle tooBig correct!!!\n"),
-% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
- ?line expect(20, tooBig, 0, any),
-
- %% 4.1.3:3
- gn([[tGenErr1]]),
-% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
- ?line expect(40, genErr, 1, any),
- gn([[tGenErr2]]),
-% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
- ?line expect(41, genErr, 1, any),
- gn([[sysDescr], [tGenErr3]]),
-% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
-% {[tGenErr3], 'NULL'}]).
- ?line expect(42, genErr, 2, any).
-
-v1_set_p() ->
- %% 4.1.5:1
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
- s([{[tDescr3], s, "noSuchObject"}]),
- ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
- s([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
- s([{[tDescr2,0], s, "inconsistentName"}]),
- ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
-
- %% 4.1.5:2
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.1.5:3
- %% The standard is quite incorrect here. The resp pdu was too big. In
- %% the resp pdu, we have the original vbs. In the tooBig pdu we still
- %% have to original vbs => the tooBig pdu is too big as well!!! It
- %% may not get it to the manager, unless the agent uses 'NULL' instead
- %% of the std-like original value.
- s([{[tTooBig, 0], s, ?tooBigStr}]),
- %% according to std:
-% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.5:4
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
- s([{[tDescr2, 0], s, "commit_fail"}]),
- ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
-
-%% Req. Test2
-v2_proc() ->
- %% According to RFC1905.
- %% Template: <Section>:<list no>
- ?DBG("v2_proc -> entry",[]),
- v2_get_p(),
- v2_get_next_p(),
- v2_get_bulk_p(),
- v2_set_p().
-
-v2_get_p() ->
- %% 4.2.1:2
- ?DBG("v2_get_p -> entry",[]),
- g([[test2]]),
- ?line expect(10, [{[test2], noSuchObject}]),
- g([[tDescr]]),
- ?line expect(11, [{[tDescr], noSuchObject}]),
- g([[tDescr4,0]]),
- ?line expect(12, [{[tDescr4,0], noSuchObject}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
- {[tDescr,0], noSuchObject}]),
- g([[tTable]]),
- ?line expect(14, [{[tTable], noSuchObject}]),
- g([[tEntry]]),
- ?line expect(15, [{[tEntry], noSuchObject}]),
-
- %% 4.2.1:3
- g([[tDescr2,0]]), %% instrum ret noSuchName!!!
- ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
- g([[tDescr3,0]]),
- ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
- g([[sysDescr,3]]),
- ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
- g([[tIndex,1]]),
- ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
-
- %% 4.2.1 - any other error: genErr
- g([[tGenErr1, 0]]),
- ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]),
-
- %% 4.2.1 - tooBig
- g([[tTooBig, 0]]),
- ?line expect(40, tooBig, 0, []).
-
-
-v2_get_next_p() ->
- %% 4.2.2:2
- ?DBG("v2_get_next_p -> entry",[]),
- gn([[1,3,7,1]]),
- ?line expect(10, [{[1,3,7,1], endOfMibView}]),
- gn([[sysDescr], [1,3,7,1]]),
- ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gn([[tCnt2, 1]]),
- ?line expect(12, [{[tCnt2,2], 100}]),
- gn([[tCnt2, 2]]),
- ?line expect(12, [{[tCnt2,2], endOfMibView}]),
-
- %% 4.2.2 - any other error: genErr
- gn([[tGenErr1]]),
- ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
- gn([[tGenErr2]]),
- ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
- gn([[sysDescr], [tGenErr3]]),
- ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
- {[tGenErr3], 'NULL'}]),
-
- %% 4.2.2 - tooBig
- gn([[tTooBig]]),
- ?line expect(20, tooBig, 0, []).
-
-v2_get_bulk_p() ->
- %% 4.2.3
- ?DBG("v2_get_bulk_p -> entry",[]),
- gb(1, 1, []),
- ?line expect(10, []),
- gb(-1, 1, []),
- ?line expect(11, []),
- gb(-1, -1, []),
- ?line expect(12, []),
- gb(-1, -1, []),
- ?line expect(13, []),
- gb(2, 0, [[sysDescr], [1,3,7,1]]),
- ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(1, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(0, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
- ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
- ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[sysDescr, 0], "Erlang SNMP agent"}]),
-
- gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
- ?line expect(19, []),
-
- gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
- ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
- {[sysObjectID], 'NULL'},
- {[tGenErr1], 'NULL'},
- {[sysDescr], 'NULL'}]),
- gb(0, 2, [[tCnt2, 1]]),
- ?line expect(21, [{[tCnt2,2], 100},
- {[tCnt2,2], endOfMibView}]).
-
-
-v2_set_p() ->
- %% 4.2.5:1
- ?DBG("v2_set_p -> entry",[]),
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
-
- %% 4.2.5:2
- s([{[1,3,6,1,0], s, "noSuchObject"}]),
- ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
-
- %% 4.2.5:3
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.2.5:4
- s([{[tStr, 0], s, ""}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
- s([{[tStr, 0], s, "12345"}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
-
- %% 4.2.5:5 - N/A
-
- %% 4.2.5:6
- s([{[tInt1, 0], i, 0}]),
- ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
- s([{[tInt1, 0], i, 5}]),
- ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
- s([{[tInt2, 0], i, 0}]),
- ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
- s([{[tInt2, 0], i, 5}]),
- ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
- s([{[tInt3, 0], i, 5}]),
- ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
-
- %% 4.2.5:7
- s([{[tDescrX, 1, 1], s, "noCreation"}]),
- ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
-
- %% 4.2.5:8
- s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
- ?line expect(80, inconsistentName, 1,
- [{[tDescrX, 1, 2], "inconsistentName"}]),
-
- %% 4.2.5:9
- s([{[tCnt, 1, 2], i, 5}]),
- ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
-
- %% 4.2.5:10
- s([{[tDescr2,0], s, "inconsistentValue"}]),
- ?line expect(100, inconsistentValue, 1,
- [{[tDescr2,0], "inconsistentValue"}]),
-
- %% 4.2.5:11
- s([{[tDescr2,0], s, "resourceUnavailable"}]),
- ?line expect(110, resourceUnavailable, 1,
- [{[tDescr2,0],"resourceUnavailable"}]),
-
- %% 4.2.5:12
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
-
- %% commitFailed and undoFailed is tested by the 'undo' case.
-
-
-%% Req. OLD-SNMPEA-MIB
-table_test() ->
- io:format("Testing simple get, next and set on communityTable...~n"),
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
- Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
- Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
- Key1c4 = [intCommunityAccess,get(mip),is("public")],
- EndKey = [intCommunityEntry,[9],get(mip),is("public")],
- gn([[intCommunityEntry]]),
- ?line expect(7, [{Key1c3, 2}]),
- gn([[intCommunityTable]]),
- ?line expect(71, [{Key1c3, 2}]),
- gn([[community]]),
- ?line expect(72, [{Key1c3, 2}]),
- gn([[otpSnmpeaMIB]]),
- ?line expect(73, [{Key1c3, 2}]),
- gn([[ericsson]]),
- ?line expect(74, [{Key1c3, 2}]),
- gn([Key1c3]),
- ?line expect(8, [{Key2c3, 2}]),
- gn([Key2c3]),
- ?line expect(9, [{Key1c4, 2}]),
- gn([EndKey]),
- AgentIp = [intAgentIpAddress,0],
- ?line expect(10, [{AgentIp, any}]),
- g([Key1c3]),
- ?line expect(11, [{Key1c3, 2}]),
- g([EndKey]),
- ?line ?v1_2(expect(12, noSuchName, 1, any),
- expect(12, [{EndKey, noSuchObject}])),
-
- io:format("Testing row creation/deletion on communityTable...~n"),
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
- s([{NewKeyc5, ?createAndGo}]),
- ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
- s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
- ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
- g([NewKeyc4]),
- ?line expect(16, [{NewKeyc4, 2}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(17, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc4, 2}]),
- ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
- s([{NewKeyc5, ?createAndWait}]),
- ?line expect(19, [{NewKeyc5, ?createAndWait}]),
- g([NewKeyc5]),
- ?line expect(20, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc4, 2}]),
- ?line expect(21, [{NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(22, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc3, 2}]),
- ?line expect(23, [{NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(24, [{NewKeyc5, ?notInService}]),
- s([{NewKeyc5, ?active}]),
- ?line expect(25, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(26, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc3, 3}]),
- ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
- otp_1128().
-
-%% Req. system group
-simple_standard_test() ->
- ?DBG("simple_standard_test -> entry",[]),
- gn([[1,1]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3]]),
- ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6]]),
- ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1]]),
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2]]),
- ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1]]),
- ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1,1]]),
- ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[sysDescr]]),
- ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr,0]]),
- ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr]]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{[sysDescr], noSuchObject}])),
- g([[1,6,7,0]]),
- ?line ?v1_2(expect(41, noSuchName, 1, any),
- expect(3, [{[1,6,7,0], noSuchObject}])),
- gn([[1,13]]),
- ?line ?v1_2(expect(4, noSuchName,1, any),
- expect(4, [{[1,13], endOfMibView}])),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
- g([[sysLocation, 0]]),
- ?line expect(6, [{[sysLocation, 0], "new_value"}]),
- io:format("Testing noSuchName and badValue...~n"),
- s([{[sysServices,0], 3}]),
- ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
- s([{[sysLocation, 0], i, 3}]),
- ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
- ?DBG("simple_standard_test -> done",[]),
- ok.
-
-%% This is run in the agent node
-db_notify_client(suite) -> [];
-db_notify_client(Config) when list(Config) ->
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
- [SaNode,MgrNode,MibDir]),
- snmpa_local_db:register_notify_client(self(),?MODULE),
-
- %% This call (the manager) will issue to set operations, so
- %% we expect to receive to notify(insert) calls.
- try_test(db_notify_client_test),
-
- ?DBG("await first notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
- end,
-
- ?DBG("await second notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
- end,
-
- snmpa_local_db:unregister_notify_client(self()).
-
-
-%% This is run in the manager node
-db_notify_client_test() ->
- ?DBG("set first new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?DBG("set second new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]).
-
-notify(Pid,What) ->
- ?DBG("notify(~p,~p) -> called",[Pid,What]),
- Pid ! {db_notify_test_reply,What}.
-
-
-%% Req: system group, OLD-SNMPEA-MIB, Klas1
-big_test() ->
- ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
- simple_standard_test(),
-
- ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
- gn([[klas1]]),
- ?line expect(1, [{[fname,0], ""}]),
- g([[fname,0]]),
- ?line expect(2, [{[fname,0], ""}]),
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[fname,0]]),
- ?line expect(4, [{[fname,0], "test set"}]),
-
- ?DBG("big_test -> "
- "testing next from last instance in master to subagent...",[]),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname,0], "test set"}]),
- s([{[fname,0], s, ""}]),
- ?line expect(52, [{[fname,0], ""}]),
-
- table_test(),
-
- ?DBG("big_test -> adding one row in subagent table",[]),
- _FTab = [friendsEntry],
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [friendsEntry, [3, 3]]]),
- ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?active}]),
- s([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
-
- otp_1131(),
-
- ?DBG("big_test -> adding two rows in subagent table with special INDEX",
- []),
- s([{[kompissEntry, [1, 3]], s, "kompis3"},
- {[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?createAndGo}]),
- g([[kompissEntry, [1, 3]],
- [kompissEntry, [2, 3]]]),
- ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- gn([[kompissEntry, [1]],
- [kompissEntry, [2]]]),
- ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- s([{[kompissEntry, [1, 2]], s, "kompis3"},
- {[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry, [1, 1]],
- [kompissEntry, [2, 1]]]),
- ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?active}]),
- s([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
- s([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
- ?DBG("big_test -> done",[]),
- ok.
-
-%% Req. system group, Klas2, OLD-SNMPEA-MIB
-big_test_2() ->
- p("Testing simple next/get/set @ master agent (2)..."),
- simple_standard_test(),
-
- p("Testing simple next/get/set @ subagent (2)..."),
- gn([[klas2]]),
- ?line expect(1, [{[fname2,0], ""}]),
- g([[fname2,0]]),
- ?line expect(2, [{[fname2,0], ""}]),
- s([{[fname2,0], s, "test set"}]),
- ?line expect(3, [{[fname2,0], "test set"}]),
- g([[fname2,0]]),
- ?line expect(4, [{[fname2,0], "test set"}]),
-
- otp_1298(),
-
- p("Testing next from last object in master to subagent (2)..."),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname2,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname2,0], "test set"}]),
-
- table_test(),
-
- p("Adding one row in subagent table (2)"),
- _FTab = [friendsEntry2],
- s([{[friendsEntry2, [2, 3]], s, "kompis3"},
- {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?createAndGo}]),
- g([[friendsEntry2, [2, 3]],
- [friendsEntry2, [3, 3]]]),
- ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?active}]),
- s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
-
- p("Adding two rows in subagent table with special INDEX (2)"),
- s([{[kompissEntry2, [1, 3]], s, "kompis3"},
- {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?createAndGo}]),
- g([[kompissEntry2, [1, 3]],
- [kompissEntry2, [2, 3]]]),
- ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- gn([[kompissEntry2, [1]],
- [kompissEntry2, [2]]]),
- ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- s([{[kompissEntry2, [1, 2]], s, "kompis3"},
- {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry2, [1, 1]],
- [kompissEntry2, [2, 1]]]),
- ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?active}]),
- s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
- s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
- ok.
-
-%% Req. Test1
-multi_threaded_test() ->
- p("Testing multi threaded agent..."),
- g([[multiStr,0]]),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(1, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "pelle"}]),
- ?line expect(2, [{[sysLocation, 0], "pelle"}]),
- Pid ! continue,
- ?line expect(3, [{[multiStr,0], "ok"}]),
-
- s([{[multiStr, 0], s, "block"}]),
- Pid2 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(4, [{[sysUpTime,0], any}]),
- g([[multiStr,0]]),
- Pid3 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(5, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "kalle"}]),
- Pid3 ! continue,
- ?line expect(6, [{[multiStr,0], "ok"}]),
- Pid2 ! continue,
- ?line expect(7, [{[multiStr,0], "block"}]),
- ?line expect(8, [{[sysLocation,0], "kalle"}]).
-
-%% Req. Test1, TestTrapv2
-mt_trap_test(MA) ->
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- snmpa:send_trap(MA, mtTrap, "standard trap"),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(2, [{[sysUpTime,0], any}]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- Pid ! continue,
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [2]},
- {[multiStr,0], "ok"}]).
-
-
-get_multi_pid() ->
- get_multi_pid(10).
-get_multi_pid(0) ->
- ?line ?FAIL(no_global_name);
-get_multi_pid(N) ->
- sleep(1000),
- case global:whereis_name(snmp_multi_tester) of
- Pid when pid(Pid) -> Pid;
- _ -> get_multi_pid(N-1)
- end.
-
-%% Req. Test1
-types_v2_test() ->
- p("Testing v2 types..."),
-
- s([{[bits1,0], 2#10}]),
- ?line expect(1, [{[bits1,0], ?str(2#10)}]),
- g([[bits1,0]]),
- ?line expect(2, [{[bits1,0], ?str(2#101)}]),
-
- s([{[bits2,0], 2#11000000110}]),
- ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
- g([[bits2,0]]),
- ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
-
- g([[bits3,0]]),
- ?line expect(50, genErr, 1, any),
-
- g([[bits4,0]]),
- ?line expect(51, genErr, 1, any),
-
- s([{[bits1,0], s, [2#10]}]),
- ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
-
- s([{[bits2,0], 2#11001001101010011}]),
- ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%% Req. Test1
-implied_test(MA) ->
- ?LOG("implied_test -> start",[]),
- p("Testing IMPLIED..."),
-
- snmpa:verbosity(MA,trace),
- snmpa:verbosity(MA,trace),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = "apa",
- Idx2 = "qq",
- ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
- ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
- {[testDescr, Idx1], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
- ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
- {[testDescr, Idx2], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr)",[]),
- gn([[testDescr]]),
- ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
- gn([[testDescr,Idx1]]),
- ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?destroy}]),
- ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?destroy}]),
- ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
-
- %% Try the same in other table
- Idx3 = [1, "apa"],
- Idx4 = [1, "qq"],
- ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
- ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
- {[testDescr2, Idx3], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
- ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
- {[testDescr2, Idx4], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr2)",[]),
- gn([[testDescr2]]),
- ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
- gn([[testDescr2,Idx3]]),
- ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?destroy}]),
- ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?destroy}]),
- ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
-
- snmpa:verbosity(MA,log),
-
- ?LOG("implied_test -> done",[]).
-
-
-
-%% Req. Test1
-sparse_table_test() ->
- p("Testing sparse table..."),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- s([{[sparseStatus, Idx1], i, ?createAndGo},
- {[sparseDescr, Idx1], s, "row 1"}]),
- ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
- {[sparseDescr, Idx1], "row 1"}]),
- s([{[sparseStatus, Idx2], i, ?createAndGo},
- {[sparseDescr, Idx2], s, "row 2"}]),
- ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
- {[sparseDescr, Idx2], "row 2"}]),
- ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
- [sparseStatus,Idx1], [sparseStatus,Idx2]]),
- gb(0,5,[[sparseIndex]])),
- ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
- {[sparseDescr,Idx2], "row 2"},
- {[sparseStatus,Idx1], ?active},
- {[sparseStatus,Idx2], ?active},
- {[sparseStr,0], "slut"}]),
- % Delete the rows
- s([{[sparseStatus, Idx1], i, ?destroy}]),
- ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
- s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
-
-
-%% Req. Test1
-cnt_64_test(MA) ->
- ?LOG("start cnt64 test (~p)",[MA]),
- snmpa:verbosity(MA,trace),
- ?LOG("start cnt64 test",[]),
- p("Testing Counter64, and at the same time, RowStatus is not last column"),
-
- ?DBG("get cnt64",[]),
- g([[cnt64,0]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(1, noSuchName, 1, any),
- expect(1, [{[cnt64,0],18446744073709551615}])),
- ?DBG("get-next cnt64",[]),
- gn([[cnt64]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
- expect(2, [{[cnt64,0],18446744073709551615}])),
- ?DBG("send cntTrap",[]),
- snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
- {cnt64, 10},
- {sysLocation, "here"}]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
- {[sysLocation,0], "here"}]),
- expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [1]},
- {[sysContact,0], "pelle"},
- {[cnt64,0], 10},
- {[sysLocation,0], "here"}])),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- ?DBG("create row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
- ?DBG("create row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
-
- ?DBG("get-next (cntIndex)",[]),
- gn([[cntIndex]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
- expect(3, [{[cntCnt,Idx1], 0}])),
- % Delete the rows
- ?DBG("delete row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
- ?DBG("delete row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
- catch snmpa:verbosity(MA,log),
- ?DBG("done",[]),
- ok.
-
-%% Req. Test1
-opaque_test() ->
- p("Testing Opaque datatype..."),
- g([[opaqueObj,0]]),
- ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
-
-%% Req. OLD-SNMPEA-MIB
-api_test(MaNode) ->
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
- oid_to_name, [OID]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp,
- int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
- List when list(List), length(List) == 8 -> ok;
- List when list(List), length(List) == 11 -> ok
- end.
-
-%% Req. Klas3
-api_test2() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]),
- g([[fname4,0]]),
- ?line expect(2, [{[fname4,0], 1}]).
-
-api_test3() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]).
-
-
-unreg_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[snmpInPkts, 0], any}]).
-
-load_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[fname,0], ""}]).
-
-%% Req. Klas1
-load_test_sa() ->
- gn([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line expect(1, [{[fname,0], any}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_get() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
- [sysName,0]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,0], "test"}]),
- g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
- ?line ?v1_2(expect(2, noSuchName, [1,4], any),
- expect(2, [{[1,3,7,1], noSuchObject},
- {Key1c4, 2},
- {[sysDescr,0], "Erlang SNMP agent"},
- {[1,3,7,2], noSuchObject},
- {Key1c3, 2},
- {[sysDescr,0], "Erlang SNMP agent"}])).
-
-%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
-do_mul_get_err() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(expect(1, noSuchName, 5, any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,2], noSuchInstance}])),
- g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname3,0], noSuchObject},
- {Key1c3, 2},
- {[sysName,1], noSuchInstance}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2}, {[fname,0], "test set"},
- {Key1c3, 2}, {[sysName,0], "test"}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next_err() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[1,3,6,999], endOfMibView},
- {[fname,0], "test set"},
- {[1,3,90], endOfMibView},
- {Key1c3, 2},
- {[sysName,0], "test"}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set() ->
- p("Adding one row in subagent table, and one in master table"),
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [sysLocation,0],
- [friendsEntry, [3, 3]]]),
- ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
- {[sysLocation,0], "new_value"},
- {[friendsEntry, [3, 3]], ?active}]),
- g([NewKeyc4]),
- ?line expect(3, [{NewKeyc4, 2}]),
- s([{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]),
- ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- p("Adding one row in subagent table, and one in master table"),
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {NewKeyc3, 2},
- {[sysUpTime,0], 45}, % sysUpTime (readOnly)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
- g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
- g([NewKeyc4]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB
-sa_mib() ->
- g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
- s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
-
-ma_trap1(MA) ->
- snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
- snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
-
-ma_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap2(MA) ->
- snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
- {ifAdminStatus, [1], 1},
- {ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
-
-sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
-
-ma_v2_trap1(MA) ->
- ?DBG("ma_v2_traps -> entry with MA = ~p => "
- "send standard trap: testTrapv22",[MA]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
- snmpa:send_trap(MA, testTrapv21, "standard trap"),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmp ++ [1]}]).
-
-ma_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
-
-%% Note: This test case takes a while... actually a couple of minutes.
-ma_v2_inform1(MA) ->
- ?DBG("ma_v2_inform -> entry with MA = ~p => "
- "send notification: testTrapv22",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag1, self()},
- "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag1, [_]} ->
- ok;
- {snmp_targets, tag1, Addrs1} ->
- ?line ?FAIL({bad_addrs, Addrs1})
- after
- 5000 ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag1, {got_response, _}} ->
- ok;
- {snmp_notification, tag1, {no_response, _}} ->
- ?line ?FAIL(no_response)
- after
- 20000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
-
- %%
- %% -- The rest is possibly erroneous...
- %%
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag2, self()},
- "standard inform", []),
- ?line expect(2, {inform, false},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag2, [_]} ->
- ok;
- {snmp_targets, tag2, Addrs2} ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
- ?line ?FAIL({bad_addrs, Addrs2})
- after
- 5000 ->
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag2, {got_response, _}} ->
- ?line ?FAIL(got_response);
- {snmp_notification, tag2, {no_response, _}} ->
- ok
- after
- 240000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag2) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end.
-
-
-ma_v1_2_v2_trap(MA) ->
- snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
- {[ifIndex, 1], 1},
- {[snmpTrapEnterprise, 0], [1,2,3]}]).
-
-
-ma_v1_2_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"},
- {[snmpTrapEnterprise, 0], ?system}]).
-
-
-sa_v1_2_v2_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-sa_v1_2_v2_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-sa_v1_2_v2_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_bad_value() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 5}, % badValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, badValue, 2, any),
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
- g([NewKeyc4]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_gen_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},{NewKeyc4, 2},
- {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line expect(1, genErr, 4, any),
-% The row might have been added; we don't know.
-% (as a matter of fact we do - it is added, because the agent
-% first sets its own vars, and then th SAs. Lets destroy it.
- s([{NewKeyc5, ?destroy}]),
- ?line expect(2, [{NewKeyc5, ?destroy}]).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_too_big() ->
- g([[sa, [4,0]]]),
- ?line expect(1, tooBig).
-
-%% Req. Klas1, system group, snmp group (v1/v2)
-next_across_sa() ->
- gn([[sysDescr],[klas1,5]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {[snmpInPkts, 0], any}]).
-
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
-%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
-%% Req. Klas3, Klas4
-undo_test() ->
- s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
- s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
-% unfortunatly we don't know if we'll get undoFailed or commitFailed.
-% it depends on which order the agent traverses the varbind list.
-% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
-% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line expect(6, genErr, 2, any).
-
-%% Req. Klas3, Klas4
-bad_return() ->
- g([[fStatus4,4],
- [fName4,4]]),
- ?line expect(4, genErr, 2, any),
- g([[fStatus4,5],
- [fName4,5]]),
- ?line expect(5, genErr, 1, any),
- g([[fStatus4,6],
- [fName4,6]]),
- ?line expect(6, genErr, 2, any),
- gn([[fStatus4,7],
- [fName4,7]]),
- ?line expect(7, genErr, 2, any),
- gn([[fStatus4,8],
- [fName4,8]]),
- ?line expect(8, genErr, 1, any),
- gn([[fStatus4,9],
- [fName4,9]]),
- ?line expect(9, genErr, 2, any).
-
-
-%%%-----------------------------------------------------------------
-%%% Test the implementation of standard mibs.
-%%% We should *at least* try to GET all variables, just to make
-%%% sure the instrumentation functions work.
-%%% Note that many of the functions in the standard mib is
-%%% already tested by the normal tests.
-%%%-----------------------------------------------------------------
-
-
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v1.
-%% o Test the counters and control objects in SNMP-STANDARD-MIB
-%%-----------------------------------------------------------------
-snmp_standard_mib(suite) -> [];
-snmp_standard_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?DBG("snmp_standard_mib -> std_mib_init", []),
- try_test(std_mib_init),
-
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- InBadVsns = try_test(std_mib_a),
- put(vsn, v2),
- ?DBG("snmp_standard_mib -> std_mib_read", []),
- try_test(std_mib_read),
- put(vsn, v1),
-
- ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
- Bad = try_test(std_mib_b, [InBadVsns]),
- ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
- try_test(std_mib_read, [], [{community, "bad community"}]),
- ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
- try_test(std_mib_write, [], [{community, "public"}]),
- ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
- try_test(std_mib_asn_err),
- ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
- try_test(std_mib_c, [Bad]),
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- try_test(standard_mib_a),
-
- ?DBG("snmp_standard_mib -> std_mib_finish", []),
- try_test(std_mib_finish),
- ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
- try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
- ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
- %% There are some more counters we could test here, but it's not that
- %% important, since they are removed from SNMPv2-MIB.
- ok.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_init() ->
- %% disable authentication failure traps. (otherwise w'd get many of
- %% them - this is also a test to see that it works).
- s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_finish() ->
- %% enable again
- s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_test_finish() ->
- %% force a authenticationFailure
- std_mib_write(),
- %% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_read() ->
- ?DBG("std_mib_read -> entry", []),
- g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
- ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
-
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_write() ->
- ?DBG("std_mib_write -> entry", []),
- s([{[sysLocation, 0], "new_value"}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_asn_err() ->
- snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v2 and v3.
-%% o Test the counters and control objects in SNMPv2-MIB
-%%-----------------------------------------------------------------
-snmpv2_mib_2(suite) -> [];
-snmpv2_mib_2(Config) when list(Config) ->
- ?LOG("snmpv2_mib_2 -> start",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?DBG("snmpv2_mib_2 -> standard mib init",[]),
- try_test(std_mib_init),
-
- ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
- InBadVsns = try_test(std_mib_a),
-
- ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
- put(vsn, v1),
- try_test(std_mib_read),
-
- ?DBG("snmpv2_mib_2 -> bad version read",[]),
- put(vsn, v2),
- Bad = try_test(std_mib_b, [InBadVsns]),
-
- ?DBG("snmpv2_mib_2 -> read with bad community",[]),
- try_test(std_mib_read, [], [{community, "bad community"}]),
-
- ?DBG("snmpv2_mib_2 -> write with public community",[]),
- try_test(std_mib_write, [], [{community, "public"}]),
-
- ?DBG("snmpv2_mib_2 -> asn err",[]),
- try_test(std_mib_asn_err),
-
- ?DBG("snmpv2_mib_2 -> check counters",[]),
- try_test(std_mib_c, [Bad]),
-
- ?DBG("snmpv2_mib_2 -> get som counters",[]),
- try_test(snmpv2_mib_a),
-
- ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
- try_test(std_mib_finish),
-
- ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
- "then disable auth traps",[]),
- try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
-
- ?LOG("snmpv2_mib_2 -> done",[]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_3(suite) -> [];
-snmpv2_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- InBadVsns = try_test(std_mib_a),
- put(vsn, v1),
- try_test(std_mib_read),
- put(vsn, v3),
- _Bad = try_test(std_mib_b, [InBadVsns]),
- try_test(snmpv2_mib_a),
-
- try_test(std_mib_finish).
-
--define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_test_finish() ->
- %% force a authenticationFailure
- ?DBG("ma_v2_inform -> write to std mib",[]),
- std_mib_write(),
-
- %% check that we got a trap
- ?DBG("ma_v2_inform -> await trap",[]),
- ?line expect(2, v2trap, [{[sysUpTime,0], any},
- {[snmpTrapOID,0], ?authenticationFailure}]),
-
- %% and the the inform
- ?DBG("ma_v2_inform -> await inform",[]),
- ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
- {[snmpTrapOID,0],?authenticationFailure}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_a() ->
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
-
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
- InBadVsns.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_b(InBadVsns) ->
- ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
- ?line InBadVsns2 = InBadVsns + 1,
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
- ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
- get_req(4, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
- get_req(1, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_a() ->
- ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
- s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
- {[sysLocation, 0], "val2"}]),
- s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line expect(4, inconsistentValue, 2,
- [{[sysLocation, 0], "val3"},
- {[snmpSetSerialNo,0], SetSerial}]),
- ?line ["val2"] = get_req(5, [[sysLocation,0]]).
-
-
-%%-----------------------------------------------------------------
-%% o Bad community uses/name is tested already
-%% in SNMPv2-MIB and STANDARD-MIB.
-%% o Test add/deletion of rows.
-%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
-snmp_community_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- try_test(snmp_community_mib),
- ?line unload_master("SNMP-COMMUNITY-MIB").
-
-snmp_community_mib_2(X) -> snmp_community_mib(X).
-
-%% Req. SNMP-COMMUNITY-MIB
-snmp_community_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o Test engine boots / time
-%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
-snmp_framework_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- try_test(snmp_framework_mib),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
-
-snmp_framework_mib_2(X) -> snmp_framework_mib(X).
-
-snmp_framework_mib_3(suite) -> [];
-snmp_framework_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(snmp_framework_mib).
-
-
-%% Req. SNMP-FRAMEWORK-MIB
-snmp_framework_mib() ->
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
- sleep(5000),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
- if
- EngineTime+7 < EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- EngineTime+4 > EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- true -> ok
- end,
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
- [Boots] when integer(Boots) -> ok;
- Else -> ?FAIL(Else)
- end,
- ok.
-
-%%-----------------------------------------------------------------
-%% o Test the counters
-%%-----------------------------------------------------------------
-snmp_mpd_mib_3(suite) -> [];
-snmp_mpd_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- UnknownPDUHs = try_test(snmp_mpd_mib_a),
- try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
- try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
-
-
-%% Req. SNMP-MPD-MIB
-snmp_mpd_mib_a() ->
- ?line [UnknownSecs, InvalidMsgs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0]]),
- Pdu = #pdu{type = 'get-request',
- request_id = 23,
- error_status = noError,
- error_index = 0,
- varbinds = []},
- SPdu = #scopedPdu{contextEngineID = "agentEngine",
- contextName = "",
- data = Pdu},
- ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
- V3Hdr1 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [7],
- msgSecurityModel = 23, % bad sec model
- msgSecurityParameters = []},
- V3Hdr2 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [6], % bad flag combination
- msgSecurityModel = 3,
- msgSecurityParameters = []},
- Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
- data = SPDUBytes},
- Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
- data = SPDUBytes},
- ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
- ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
- snmp_test_mgr:send_bytes(MsgBytes1),
- snmp_test_mgr:send_bytes(MsgBytes2),
-
- ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0],
- [snmpUnknownPDUHandlers, 0]]),
- ?line UnknownSecs2 = UnknownSecs + 1,
- ?line InvalidMsgs2 = InvalidMsgs + 1,
- UnknownPDUHs.
-
--define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
-snmp_mpd_mib_b() ->
- g([[sysUpTime,0]]),
- ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
-
-
-snmp_mpd_mib_c(UnknownPDUHs) ->
- ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownPDUHs2 = UnknownPDUHs + 1.
-
-
-snmp_target_mib(suite) -> [];
-snmp_target_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
- try_test(snmp_target_mib),
- ?line unload_master("SNMP-TARGET-MIB").
-
-snmp_target_mib_2(X) -> snmp_target_mib(X).
-
-snmp_target_mib_3(X) -> snmp_target_mib(X).
-
-snmp_target_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-snmp_notification_mib(suite) -> [];
-snmp_notification_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- try_test(snmp_notification_mib),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
-
-snmp_notification_mib_2(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib_3(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o add/delete views and try them
-%% o try boundaries
-%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
-snmp_view_based_acm_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
- snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib() ->
- snmpa:verbosity(net_if,trace),
- snmpa:verbosity(master_agent,trace),
- ?LOG("start snmp_view_based_acm_mib test",[]),
- %% The user "no-rights" is present in USM, and is mapped to security
- %% name 'no-rights", which is not present in VACM.
- %% So, we'll add rights for it, try them and delete them.
- %% We'll give "no-rights" write access to tDescr.0 and read access
- %% to tDescr2.0
- %% These are the options we'll use to the mgr
- Opts = [{user, "no-rights"}, {community, "no-rights"}],
- %% Find the valid secmodel, and one invalid secmodel.
- {SecMod, InvSecMod} =
- case get(vsn) of
- v1 -> {?SEC_V1, ?SEC_V2C};
- v2 -> {?SEC_V2C, ?SEC_USM};
- v3 -> {?SEC_USM, ?SEC_V1}
- end,
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Now, add a mapping from "no-rights" -> "no-rights-group"
- GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
- GRow1 =
- [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
- {GRow1Status, ?createAndGo}],
- ?DBG("set '~p'",[GRow1]),
- ?line try_test(do_set, [GRow1]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create a mapping for another sec model, and make sure it dosn't
- %% give us access
- GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
- GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
- {GRow2Status, ?createAndGo}],
-
- ?DBG("set '~p'",[GRow2]),
- ?line try_test(do_set, [GRow2]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [GRow2Status]),
-
- RVName = "rv_name",
- WVName = "wv_name",
-
- %% Access row
- ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
- ARow1Status = [vacmAccessStatus, ARow1Idx],
- ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
- {[vacmAccessReadViewName, ARow1Idx], RVName},
- {[vacmAccessWriteViewName, ARow1Idx], WVName},
- {ARow1Status, ?createAndGo}],
-
- %% This access row would give acces, if InvSecMod was valid.
- ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
- ARow2Status = [vacmAccessStatus, ARow2Idx],
- ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
- {[vacmAccessReadViewName, ARow2Idx], "internet"},
- {[vacmAccessWriteViewName, ARow2Idx], "internet"},
- {ARow2Status, ?createAndGo}],
-
- ?line try_test(do_set, [ARow2]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [ARow2Status]),
-
-
- %% Add valid row
- ?line try_test(do_set, [ARow1]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create the view family
- VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
- VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
- VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
- VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
- VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
- VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
- VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
- VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
-
- ?line try_test(add_row, [VRow1Status]),
- ?line try_test(add_row, [VRow2Status]),
- ?line try_test(add_row, [VRow3Status]),
-
- %% We're supposed to have access now...
- ?line try_test(use_rights, [], Opts),
-
- %% Change Row3 to Row4
- ?line try_test(del_row, [VRow3Status]),
- ?line try_test(add_row, [VRow4Status]),
-
- %% We should still have access...
- ?line try_test(use_rights, [], Opts),
-
- %% Delete rows
- ?line try_test(del_row, [GRow1Status]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete rest of rows
- ?line try_test(del_row, [ARow1Status]),
- ?line try_test(del_row, [VRow1Status]),
- ?line try_test(del_row, [VRow2Status]),
- ?line try_test(del_row, [VRow4Status]),
-
- ?line try_test(use_no_rights, [], Opts),
- snmpa:verbosity(master_agent,log).
-
-do_set(Row) ->
- s(Row),
- expect(1, Row).
-
-add_row(RowStatus) ->
- s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
-
-del_row(RowStatus) ->
- s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
-
-
-
-use_no_rights() ->
- g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
- g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
- gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
- s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
-
-
-use_rights() ->
- g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
- g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
- s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
- g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
-
-mk_ln(X) ->
- [length(X) | X].
-
-%%-----------------------------------------------------------------
-%% o add/delete users and try them
-%% o test all secLevels
-%% o test all combinations of protocols
-%% o try bad ops; check counters
-%%-----------------------------------------------------------------
-snmp_user_based_sm_mib_3(suite) -> [];
-snmp_user_based_sm_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
-
- %% The newUser used here already has VACM access.
-
- %% Add a new user in the simplest way; just createAndGo
- try_test(v3_sync, [[{usm_add_user1, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new user
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
- DesKey1 = lists:sublist(ShaKey1, 16),
-
- %% Change the new user's keys - 1
- try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- MgrDir = ?config(mgr_dir, Config),
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
- DesKey2 = lists:sublist(ShaKey2, 16),
-
- %% Change the new user's keys - 2
- ?line try_test(v3_sync,
- [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- reset_usm_mgr(MgrDir),
- ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
- ?line load_master("Test2"),
- ?line try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Change the new user's keys - 3
- ?line try_test(v3_sync,
- [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new keys
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Try some read requests
- ?line try_test(v3_sync, [[{usm_read, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Delete the new user
- ?line try_test(v3_sync, [[{usm_del_user, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try some bad requests
- ?line try_test(v3_sync, [[{usm_bad, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("SNMP-USER-BASED-SM-MIB").
-
--define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
-
-usm_add_user1() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
-usm_use_user() ->
- v2_proc().
-
-
-%% Change own public keys
-usm_key_change1(ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_shaxxxxxxxxxx",
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_desxxxxxx",
- DesKey),
- Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change own private keys
-usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change other's public keys
-usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
- s(Vbs1),
- ?line expect(1, noAccess, 1, any),
- Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs2),
- ?line expect(2, noAccess, 1, any),
-
-
- Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs3),
- ?line expect(1, Vbs3).
-
-usm_read() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ?line g([[usmUserSecurityName, NewRowIndex],
- [usmUserCloneFrom, NewRowIndex],
- [usmUserAuthKeyChange, NewRowIndex],
- [usmUserOwnAuthKeyChange, NewRowIndex],
- [usmUserPrivKeyChange, NewRowIndex],
- [usmUserOwnPrivKeyChange, NewRowIndex]]),
- ?line expect(1,
- [{[usmUserSecurityName, NewRowIndex], "newUser"},
- {[usmUserCloneFrom, NewRowIndex], [0,0]},
- {[usmUserAuthKeyChange, NewRowIndex], ""},
- {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
- {[usmUserPrivKeyChange, NewRowIndex], ""},
- {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
- ok.
-
-
-
-usm_del_user() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
--define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
-
--define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
-
--define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
-
--define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
-
--define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
-
--define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
-
-usm_bad() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, inconsistentName, 1, any),
-
- RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs2),
- ?line expect(2, wrongValue, 1, any),
-
- RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs3),
- ?line expect(3, Vbs3),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
- ?line expect(4, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
- ?line expect(5, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
- ?line expect(6, wrongValue, 1, any),
- ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
- ?line expect(7, wrongValue, 1, any),
-
- Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs4),
- ?line expect(1, Vbs4),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Loop through entire MIB, to make sure that all instrum. funcs
-%% works.
-%% Load all std mibs that are not loaded by default.
-%%-----------------------------------------------------------------
-loop_mib(suite) -> [];
-loop_mib(Config) when list(Config) ->
- ?LOG("loop_mib -> initiate case",[]),
- %% snmpa:verbosity(master_agent,debug),
- %% snmpa:verbosity(mib_server,info),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?DBG("loop_mib -> try",[]),
- try_test(loop_mib_1),
- ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- %% snmpa:verbosity(master_agent,log),
- %% snmpa:verbosity(mib_server,silence),
- ?LOG("loop_mib -> done",[]).
-
-
-loop_mib_2(suite) -> [];
-loop_mib_2(Config) when list(Config) ->
- ?LOG("loop_mib_2 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_2 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_2 -> load mibs",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_2 -> unload mibs",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?LOG("loop_mib_2 -> done",[]).
-
-
-loop_mib_3(suite) -> [];
-loop_mib_3(Config) when list(Config) ->
- ?LOG("loop_mib_3 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_3 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_3 -> load mibs",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_3 -> unload mibs",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?LOG("loop_mib_3 -> done",[]).
-
-
-%% Req. As many mibs all possible
-loop_mib_1() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_1([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_1(Oid, N) ->
- ?DBG("loop_it_1 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_1 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_1 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_1(NOid, N+1);
- #pdu{type='get-response', error_status=noSuchName, error_index=1,
- varbinds=[_]} ->
- ?DBG("loop_it_1 -> done",[]),
- N;
-
- #pdu{type = Type, error_status = Err, error_index = Idx,
- varbinds = Vbs} ->
- exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
- end.
-
-%% Req. As many mibs all possible
-loop_mib_2() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_2([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_2(Oid, N) ->
- ?DBG("loop_it_2 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p",[NOid]),
- N;
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_2 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_2(NOid, N+1)
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% Testing of reported bugs and other tickets.
-%%%-----------------------------------------------------------------
-
-
-
-
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1128
-%% Slogan: Bug in handling of createAndWait set-requests.
-%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
-otp_1128(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1128),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1128_2(X) -> otp_1128(X).
-
-otp_1128_3(X) -> otp_1128(X).
-
-otp_1128() ->
- io:format("Testing bug reported in ticket OTP-1128...~n"),
-
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
-
- s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(29, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(31, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(32, [{NewKeyc5, ?destroy}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1129, OTP-1169
-%% Slogan: snmpa:int_to_enum crashes on bad oids
-%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
-otp_1129(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- try_test(otp_1129_i, [node()]),
- ?line unload_master("Klas3").
-
-otp_1129_2(X) -> otp_1129(X).
-
-otp_1129_3(X) -> otp_1129(X).
-
-otp_1129_i(MaNode) ->
- io:format("Testing bug reported in ticket OTP-1129...~n"),
- false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
- false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1131
-%% Slogan: Agent crashes / erlang node halts if RowIndex in a
-%% setrequest is of bad type, e.g. an INDEX {INTEGER},
-%% and RowIdenx [3,2].
-%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
-otp_1131(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas1"),
- try_test(otp_1131),
- ?line unload_master("Klas1").
-
-otp_1131_2(X) -> otp_1131(X).
-
-otp_1131_3(X) -> otp_1131(X).
-
-otp_1131() ->
- io:format("Testing bug reported in ticket OTP-1131...~n"),
- s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
- {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1162
-%% Slogan: snmp_agent can't handle wrongValue from instrum.func
-%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
-otp_1162(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
- try_test(otp_1162),
- stop_subagent(SA).
-
-otp_1162_2(X) -> otp_1162(X).
-
-otp_1162_3(X) -> otp_1162(X).
-
-otp_1162() ->
- s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1222
-%% Slogan: snmp agent crash if faulty index is returned from instrum
-%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
-otp_1222(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
- try_test(otp_1222),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4").
-
-otp_1222_2(X) -> otp_1222(X).
-
-otp_1222_3(X) -> otp_1222(X).
-
-otp_1222() ->
- io:format("Testing bug reported in ticket OTP-1222...~n"),
- s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line expect(1, genErr, 0, any),
- s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line expect(2, genErr, 0, any).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1298
-%% Slogan: Negative INTEGER values are treated as positive.
-%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
-otp_1298(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1298),
- ?line unload_master("Klas2").
-
-otp_1298_2(X) -> otp_1298(X).
-
-otp_1298_3(X) -> otp_1298(X).
-
-otp_1298() ->
- io:format("Testing bug reported in ticket OTP-1298...~n"),
- s([{[fint,0], -1}]),
- ?line expect(1298, [{[fint,0], -1}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1331
-%% Slogan: snmp_generic should return noError when deleting non-ex row
-%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
-otp_1331(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1331),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1331_2(X) -> otp_1331(X).
-
-otp_1331_3(X) -> otp_1331(X).
-
-otp_1331() ->
- NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
- s([{NewKeyc5, ?destroy}]),
- ?line expect(1, [{NewKeyc5, ?destroy}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1338
-%% Slogan: snmp bug in initialisation of default values for mnesia tabs
-%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
-otp_1338(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1338),
- ?line unload_master("Klas2").
-
-otp_1338_2(X) -> otp_1338(X).
-
-otp_1338_3(X) -> otp_1338(X).
-
-otp_1338() ->
- s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
- g([[kName2, 7]]),
- ?line expect(2, [{[kName2, 7], "JJJ"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1342
-%% Slogan: default impl of snmp table can't handle bad index access,
-%% Set when INDEX is read-write gets into an infinite loop!
-%%-----------------------------------------------------------------
-otp_1342(suite) -> [];
-otp_1342(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas4"),
- try_test(otp_1342),
- ?line unload_master("Klas4").
-
-otp_1342_2(X) -> otp_1342(X).
-
-otp_1342_3(X) -> otp_1342(X).
-
-otp_1342() ->
- s([{[fIndex5, 1], i, 1},
- {[fName5, 1], i, 3},
- {[fStatus5, 1], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1366
-%% Slogan: snmp traps not sent to all managers
-%% Note: NYI! We need a way to tell the test server that we need
-%% mgrs on two different machines.
-%%-----------------------------------------------------------------
-otp_1366(suite) -> [];
-otp_1366(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1366),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1366_2(X) -> otp_1366(X).
-
-otp_1366_3(X) -> otp_1366(X).
-
-otp_1366() ->
- ?INF("NOT YET IMPLEMENTED", []),
- 'NYI'.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2776
-%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
-%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
-otp_2776(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_2776).
-
-otp_2776_2(X) -> otp_2776(X).
-
-otp_2776_3(X) -> otp_2776(X).
-
-otp_2776() ->
- io:format("Testing bug reported in ticket OTP-2776...~n"),
-
- Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
- Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
- Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
- Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
- Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
- Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
- Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
- Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
- Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
- Dt10_invalid = [],
- Dt11_invalid = [kalle,hobbe],
- L = [{ 1, true, Dt01_valid},
- { 2, true, Dt02_valid},
- { 3, true, Dt03_valid},
- { 4, false, Dt04_invalid},
- { 5, true, Dt05_valid},
- { 6, true, Dt06_valid},
- { 7, false, Dt07_invalid},
- { 8, true, Dt08_valid},
- { 9, false, Dt09_invalid},
- {10, false, Dt10_invalid},
- {11, false, Dt11_invalid}],
-
- ?line ok = validate_dat(L).
-
-
-validate_dat(L) -> validate_dat(L,[]).
-
-validate_dat([],V) ->
- Fun = fun({_,X}) -> case X of
- ok -> false;
- _ -> true
- end
- end,
- validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
-validate_dat([{Id,E,Dat}|T],V) ->
- validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
-
-validate_dat1([]) -> ok;
-validate_dat1(L) -> {error,L}.
-
-validate_dat2(Id, E, Dat) ->
- Res = case {E,snmp:validate_date_and_time(Dat)} of
- {E,E} -> ok;
- {E,A} -> {E,A}
- end,
- {Id, Res}.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2979
-%% Slogan: get-next on more than 1 column in an empty table
-%% returns bad response.
-%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
-otp_2979(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Test1"),
- ?line init_old(),
- try_test(otp_2979),
- ?line unload_master("Test1").
-
-otp_2979_2(X) -> otp_2979(X).
-
-otp_2979_3(X) -> otp_2979(X).
-
-otp_2979() ->
- gn([[sparseDescr], [sparseStatus]]),
- ?line expect(1, [{[sparseStr,0], "slut"},
- {[sparseStr,0], "slut"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
-%% endOfTable - should return value.
-%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
-otp_3187(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- otp_3187(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-otp_3187_2(X) -> otp_3187(X).
-
-otp_3187_3(X) -> otp_3187(X).
-
-otp_3187() ->
- ?line Elements =
- snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
- lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
- ?FAIL(endOfTable);
- true -> ok
- end
- end, Elements).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3542
-%% Slogan:
-%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
-otp_3542(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_3542).
-
-otp_3542() ->
- io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
- io:format("SNMP v3 discovery result: ~p~n",[Res]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3725
-%% Slogan: Slow response time on snmpa:int_to_enum
-%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
-otp_3725(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-otp_3725_test(MaNode) ->
- io:format("Testing feature requested in ticket OTP-3725...~n"),
- ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
- ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
- ?DBG("otp_3725_test -> Db = ~p",[Db]),
-
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [Db, intAgentIpAddress]),
- ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
- [Db,OID]),
- ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-4394
-%% Slogan: Target mib tag list check invalid
-%%-----------------------------------------------------------------
-
-
-
-init_otp_4394(Config) when list(Config) ->
- ?DBG("init_otp_4394 -> entry with"
- "~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
- MasterAgentVerbosity = {master_agent_verbosity, trace},
- NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
-
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
- ?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
- Vsn = [v1],
- Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
- ?TRAP_UDP, Ip, 4000,
- "OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
- false ->
- ?line ok
- end,
- C1 = {"a", "all-rights", "initial", "", "pc"},
- C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
- Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
- "pc1",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [],
- 2048},
- Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
- "pc2",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
- ok.
-
-
-
-finish_otp_4394(Config) when list(Config) ->
- ?DBG("finish_otp_4394 -> entry", []),
- C1 = stop_agent(Config),
- delete_files(C1),
- erase(mgr_node),
- lists:keydelete(vsn, 1, C1).
-
-otp_4394_test(suite) -> [];
-otp_4394_test(Config) ->
- ?DBG("otp_4394_test -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_4394_test1),
- ?DBG("otp_4394_test -> done", []),
- ok.
-
-otp_4394_test1() ->
- ?DBG("otp_4394_test1 -> entry", []),
- gn([[1,1]]),
- Res =
- case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
- %% {error, 1, {"?",[]}, {"~w",[timeout]}}
- {error, 1, _, {_, [timeout]}} ->
- ?DBG("otp_4394_test1 -> expected result: timeout", []),
- ok;
- Else ->
- Else
- end,
- ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
- Res.
-
-
-%%%--------------------------------------------------
-%%% Used to test the standard mib with our
-%%% configuration.
-%%%--------------------------------------------------
-run(F, A, Opts) ->
- M = get(mib_dir),
- Dir = get(mgr_dir),
- User = snmp_misc:get_option(user, Opts, "all-rights"),
- SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
- EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
- CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
- Community = snmp_misc:get_option(community, Opts, "all-rights"),
- ?DBG("run -> start crypto app",[]),
- Crypto = case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- ?CRYPTO_START()
- end,
- ?DBG("run -> Crypto: ~p",[Crypto]),
- catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- ?DBG("run -> config:~n"
- "\tM: ~p~n"
- "\tDir: ~p~n"
- "\tUser: ~p~n"
- "\tSecLevel: ~p~n"
- "\tEngineID: ~p~n"
- "\tCtxEngineID: ~p~n"
- "\tCommunity: ~p~n"
- "\tStdM: ~p",
- [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
- case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
- {packet_server_debug,true},
- {debug,true},
- {agent, get(master_host)},
- {agent_udp, 4000},
- {trap_udp, 5000},
- {recbuf,65535},
- quiet,
- get(vsn),
- {community, Community},
- {user, User},
- {sec_level, SecLevel},
- {engine_id, EngineID},
- {context_engine_id, CtxEngineID},
- {dir, Dir},
- {mibs, mibs(StdM, M)}]) of
- {ok, _Pid} ->
- Res = apply(?MODULE, F, A),
- catch snmp_test_mgr:stop(),
- Res;
- Err ->
- io:format("Error starting manager: ~p\n", [Err]),
- catch snmp_test_mgr:stop(),
- ?line exit({mgr_start, Err})
- end.
-
-
-mibs(StdMibDir,MibDir) ->
- [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
- join(MibDir, "OLD-SNMPEA-MIB.bin"),
- join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
- join(StdMibDir, "SNMP-MPD-MIB"),
- join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
- join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
- join(StdMibDir, "SNMP-TARGET-MIB"),
- join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
- join(MibDir, "Klas1.bin"),
- join(MibDir, "Klas2.bin"),
- join(MibDir, "Klas3.bin"),
- join(MibDir, "Klas4.bin"),
- join(MibDir, "SA-MIB.bin"),
- join(MibDir, "TestTrap.bin"),
- join(MibDir, "Test1.bin"),
- join(MibDir, "Test2.bin"),
- join(MibDir, "TestTrapv2.bin")].
-
-join(D,F) ->
- filename:join(D,F).
-
-%% string used in index
-is(S) -> [length(S) | S].
-
-try_test(Func) ->
- call(get(mgr_node), ?MODULE, run, [Func, [], []]).
-
-try_test(Func, A) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, []]).
-
-try_test(Func, A, Opts) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
-
-call(N,M,F,A) ->
- ?DBG("call -> entry with~n"
- " N: ~p~n"
- " M: ~p~n"
- " F: ~p~n"
- " A: ~p~n"
- " when~n"
- " get(): ~p",
- [N,M,F,A,get()]),
- spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
- receive
- {done, {'EXIT', Rn}, Loc} ->
- ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
- put(test_server_loc, Loc),
- exit(Rn);
- {done, Ret, Zed} ->
- ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
- Ret
- end.
-
-wait(From, Env, M, F, A) ->
- ?DBG("wait -> entry with ~n"
- "\tFrom: ~p~n"
- "\tEnv: ~p",[From,Env]),
- lists:foreach(fun({K,V}) -> put(K,V) end, Env),
- Rn = (catch apply(M, F, A)),
- ?DBG("wait -> Rn: ~n~p", [Rn]),
- From ! {done, Rn, get(test_server_loc)},
- exit(Rn).
-
-expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
-expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
-expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
-expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
-
-get_req(Id, Vars) ->
- ?DBG("get_req -> entry with~n"
- "\tId: ~p~n"
- "\tVars: ~p",[Id,Vars]),
- g(Vars),
- ?DBG("get_req -> await response",[]),
- {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
- ?DBG("get_req -> response: ~p",[Val]),
- Val.
-
-get_next_req(Vars) ->
- ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
- gn(Vars),
- ?DBG("get_next_req -> await response",[]),
- Response = snmp_test_mgr:receive_response(),
- ?DBG("get_next_req -> response: ~p",[Response]),
- Response.
-
-
-
-start_node(Name) ->
- ?LOG("start_node -> entry with Name: ~p",[Name]),
- M = list_to_atom(?HOSTNAME(node())),
- ?DBG("start_node -> M: ~p",[M]),
- Pa = filename:dirname(code:which(?MODULE)),
- ?DBG("start_node -> Pa: ~p",[Pa]),
-
- Args = case init:get_argument('CC_TEST') of
- {ok, [[]]} ->
- " -pa /clearcase/otp/libraries/snmp/ebin ";
- {ok, [[Path]]} ->
- " -pa " ++ Path;
- error ->
- ""
- end,
- %% Do not use start_link!!! (the proc that calls this one is tmp)
- ?DBG("start_node -> Args: ~p~n",[Args]),
- A = Args ++ " -pa " ++ Pa,
- case (catch ?START_NODE(Name, A)) of
- {ok, Node} ->
- %% Tell the test_server to not clean up things it never started.
- ?DBG("start_node -> Node: ~p",[Node]),
- {ok, Node};
- Else ->
- ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
- ?line ?FAIL(Else)
- end.
-
-
-stop_node(Node) ->
- ?LOG("stop_node -> Node: ~p",[Node]),
- rpc:cast(Node, erlang, halt, []).
-
-p(X) ->
- io:format(user, X++"\n", []).
-
-sleep(X) ->
- receive
- after
- X -> ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Configuration
-%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
- "test"),
- ?line case update_usm(Vsns, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsns, MgrDir);
- false ->
- ?line ok
- end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
- ok.
-
-delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
- lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
-
-update_usm(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-update_usm_mgr(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(filename:join(Dir,"usm.conf"),
- filename:join(Dir,"usm.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- file:close(Fid).
-
-reset_usm_mgr(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"usm.old"),
- filename:join(Dir,"usm.conf")).
-
-
-update_community([v3], _Dir) -> ok;
-update_community(_, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
- []),
- file:close(Fid).
-
-
--define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
-update_vacm(_Vsn, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
- ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
- "~w, excluded, null}.\n", [?tDescr_instance]),
- file:close(Fid).
-
-
-vacm_ver(v1) -> v1;
-vacm_ver(v2) -> v2c;
-vacm_ver(v3) -> usm.
-
-
-write_community_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
- ok = write_community_conf1(Fid, Confs),
- file:close(Fid).
-
-write_community_conf1(_, []) ->
- ok;
-write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
- [ComIdx, ComName, SecName, CtxName, TransTag]),
- write_community_conf1(Fid, Confs).
-
-
-write_target_addr_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- ok = write_target_addr_conf1(Fid, Confs),
- file:close(Fid).
-
-
-write_target_addr_conf1(_, []) ->
- ok;
-write_target_addr_conf1(Fid,
- [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
- [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz]),
- write_target_addr_conf1(Fid, Confs).
-
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- lists:foreach(fun(Vsn) ->
- ok = io:format(Fid,
- "{\"~s\", ~w, ~w, 1500, 3, "
- "\"std_trap\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP, mk_param(Vsn)]),
- case Vsn of
- v1 -> ok;
- v2 ->
- ok = io:format(Fid,
- "{\"~s.2\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)]);
- v3 ->
- ok = io:format(Fid,
- "{\"~s.3\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\", "
- "\"mgrEngine\", [], 1024}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)])
- end
- end,
- Vsns),
- file:close(Fid).
-
-mk_param(v1) -> "target_v1";
-mk_param(v2) -> "target_v2";
-mk_param(v3) -> "target_v3".
-
-mk_ip([A,B,C,D], Vsn) ->
- io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
-
-
-rewrite_target_addr_conf(Dir,NewPort) ->
- TAFile = filename:join(Dir, "target_addr.conf"),
- ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
- case file:read_file_info(TAFile) of
- {ok, _} -> ok;
- {error, R} -> ?ERR("failure reading file info of "
- "target address config file: ~p",[R]),
- ok
- end,
-
- ?line [TrapAddr|Addrs] =
- snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
-
- ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
-
- NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
-
- ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
-
- ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
- filename:join(Dir,"target_addr.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
-
- ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
-
- file:close(Fid).
-
-rewrite_target_addr_conf1(O) ->
- {ok,O}.
-
-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) ->
- ?LOG("rewrite_target_addr_conf2 -> entry with "
- "~n O: ~p",[O]),
- O.
-
-
-rewrite_target_addr_conf3(_,[]) -> ok;
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
- ParamName,EngineId}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % ParamsName
- "\"~s\"}.", % EngineId
- [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
- rewrite_target_addr_conf3(Fid,T);
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
- ParamName,EngineId,TMask,MMS}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % TagList
- "\"~s\", " % ParamsName
- "\"~s\"," % EngineId
- "~p, " % TMask
- "~p}.", % MMS
- [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
- EngineId,TMask,MMS]),
- rewrite_target_addr_conf3(Fid,T).
-
-reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
-
-write_target_params_conf(Dir, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- lists:foreach(fun(Vsn) ->
- MP = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> v3
- end,
- SM = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> usm
- end,
- ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
- "\"all-rights\", noAuthNoPriv}.~n",
- [Vsn, MP, SM])
- end,
- Vsns),
- file:close(Fid).
-
-rewrite_target_params_conf(Dir, SecName, SecLevel) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
- filename:join(Dir,"target_params.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
- [SecName, SecLevel]),
- file:close(Fid).
-
-reset_target_params_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.old"),
- filename:join(Dir,"target_params.conf")).
-
-write_notify_conf(Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
- ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
- ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
- file:close(Fid).
-
-ver_to_trap_str([v1]) -> "v1";
-ver_to_trap_str([v2]) -> "v2";
-% default is to use the latest snmp version
-ver_to_trap_str([v1,v2]) -> "v2".
-
-
-
-write_view_conf(Dir) ->
- {ok, Fid} = file:open(a(Dir,"view.conf"),write),
- ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
- ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
- file:close(Fid).
-
-a(A,B) -> lists:append(A,B).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-copy_file(From, To) ->
- {ok, Bin} = file:read_file(From),
- ok = file:write_file(To, Bin).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-display_memory_usage() ->
- Info = snmpa:info(snmp_master_agent),
- TreeSize = lists_key1search(tree_size_bytes, Info),
- ProcMem = lists_key1search(process_memory, Info),
- MibDbSize = lists_key1search([db_memory,mib], Info),
- NodeDbSize = lists_key1search([db_memory,node], Info),
- TreeDbSize = lists_key1search([db_memory,tree], Info),
- ?INF("Memory usage: "
- "~n Tree size: ~p"
- "~n Process memory size: ~p"
- "~n Mib db size: ~p"
- "~n Node db size: ~p"
- "~n Tree db size: ~p",
- [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
-
-lists_key1search([], Res) ->
- Res;
-lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- lists_key1search(Keys, Val);
- false ->
- undefined
- end;
-lists_key1search(Key, List) when atom(Key) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- Val;
- false ->
- undefined
- end.
-
-
-regs() ->
- lists:sort(registered()).
diff --git a/lib/snmp/test/snmp_agent_mt_test.erl b/lib/snmp/test/snmp_agent_mt_test.erl
deleted file mode 100644
index 4f125c0017..0000000000
--- a/lib/snmp/test/snmp_agent_mt_test.erl
+++ /dev/null
@@ -1,5649 +0,0 @@
-%%
-%% %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%
-%%
-
--module(snmp_agent_mt_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
--compile(export_all).
-
--define(application, snmp).
-
--include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
--include("snmp_test_lib.hrl").
--define(SNMP_USE_V3, true).
--include_lib("snmp/include/snmp_types.hrl").
-%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
-
-
--define(klas1, [1,3,6,1,2,1,7]).
--define(klas2, [1,3,6,1,2,1,9]).
--define(klas3, [1,3,6,1,2,1,8,1]).
--define(klas4, [1,3,6,1,2,1,8,4]).
--define(sa, [1,3,6,1,4,1,193,2]).
--define(system, [1,3,6,1,2,1,1]).
--define(snmp, [1,3,6,1,2,1,11]).
--define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
--define(ericsson, [1,3,6,1,4,1,193]).
--define(testTrap, [1,3,6,1,2,1,15,0]).
--define(xDescr, [1,3,6,1,2,1,17,1]).
--define(xDescr2, [1,3,6,1,2,1,17,2]).
-
--define(active, 1).
--define(notInService, 2).
--define(notReady, 3).
--define(createAndGo, 4).
--define(createAndWait, 5).
--define(destroy, 6).
-
--define(TRAP_UDP, 5000).
-
--define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
-
--define(str(X), snmp_pdus:bits_to_str(X)).
-
--define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
- [?LINE, self()]),
- receive cont -> ok end
- end).
-
-
--import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
--define(v1_2(V1,V2),
- case get(vsn) of
- v1 -> V1;
- _ -> V2
- end).
-
--define(v1_2_3(V1,V2,V3),
- case get(vsn) of
- v1 -> V1;
- v2 -> V2;
- _ -> V3
- end).
-
-all() ->
-[cases()].
-
-groups() ->
- [{mib_storage, [],
- [{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()},
- {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]},
- {standard_mibs, [],
- [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]},
- {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]},
- {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]},
- {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]},
- {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]},
- {tickets, [], [{group, otp_4394}]},
- {otp_4394, [], [otp_4394_test]}].
-
-init_per_group(otp_4394, Config) ->
- init_otp_4394(Config);
-init_per_group(v2_inform, Config) ->
- init_v2_inform(Config);
-init_per_group(multiple_reqs_2, Config) ->
- init_mul(Config);
-init_per_group(multiple_reqs, Config) ->
- init_mul(Config);
-init_per_group(test_multi_threaded, Config) ->
- init_mt(Config);
-init_per_group(test_v3, Config) ->
- init_v3(Config);
-init_per_group(test_v1_v2, Config) ->
- init_v1_v2(Config);
-init_per_group(test_v2, Config) ->
- init_v2(Config);
-init_per_group(test_v1, Config) ->
- init_v1(Config);
-init_per_group(mib_storage_varm_mnesia, Config) ->
- init_varm_mib_storage_mnesia(Config);
-init_per_group(mib_storage_varm_dets, Config) ->
- init_varm_mib_storage_dets(Config);
-init_per_group(mib_storage_size_check_mnesia, Config) ->
- init_size_check_msm(Config);
-init_per_group(mib_storage_size_check_dets, Config) ->
- init_size_check_msd(Config);
-init_per_group(mib_storage_size_check_ets, Config) ->
- init_size_check_mse(Config);
-init_per_group(mib_storage_mnesia, Config) ->
- init_mib_storage_mnesia(Config);
-init_per_group(mib_storage_dets, Config) ->
- init_mib_storage_dets(Config);
-init_per_group(mib_storage_ets, Config) ->
- init_mib_storage_ets(Config);
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(otp_4394, Config) ->
- finish_otp_4394(Config);
-end_per_group(v2_inform, Config) ->
- finish_v2_inform(Config);
-end_per_group(multiple_reqs_2, Config) ->
- finish_mul(Config);
-end_per_group(multiple_reqs, Config) ->
- finish_mul(Config);
-end_per_group(test_multi_threaded, Config) ->
- finish_mt(Config);
-end_per_group(test_v3, Config) ->
- finish_v3(Config);
-end_per_group(test_v1_v2, Config) ->
- finish_v1_v2(Config);
-end_per_group(test_v2, Config) ->
- finish_v2(Config);
-end_per_group(test_v1, Config) ->
- finish_v1(Config);
-end_per_group(mib_storage_varm_mnesia, Config) ->
- finish_varm_mib_storage_mnesia(Config);
-end_per_group(mib_storage_varm_dets, Config) ->
- finish_varm_mib_storage_dets(Config);
-end_per_group(mib_storage_size_check_mnesia, Config) ->
- finish_size_check_msm(Config);
-end_per_group(mib_storage_size_check_dets, Config) ->
- finish_size_check_msd(Config);
-end_per_group(mib_storage_size_check_ets, Config) ->
- finish_size_check_mse(Config);
-end_per_group(mib_storage_mnesia, Config) ->
- finish_mib_storage_mnesia(Config);
-end_per_group(mib_storage_dets, Config) ->
- finish_mib_storage_dets(Config);
-end_per_group(mib_storage_ets, Config) ->
- finish_mib_storage_ets(Config);
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- Config.
-
-cases() ->
-case ?OSTYPE() of
- vxworks ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_multi_threaded},
- {group, mib_storage}, {group, tickets}];
- _Else ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}]
-end.
-
-
-%%%-----------------------------------------------------------------
-%%% The test case structure is as follows:
-%%%
-%%% init_all - starts mnesia,
-%%%
-%%% init_v1 - starts agent
-%%% simple
-%%% big - e.g. starts/stops subagent, load/unloads mibs
-%%% init_mul
-%%% mul_get
-%%% mul_set
-%%% <etc>
-%%% finish_mul
-%%% <etc>
-%%% finish_v1
-%%%
-%%% init_v2 - starts agent
-%%% finish_v2
-%%%
-%%% init_bilingual - starts agent
-%%% finish_bilingual
-%%%
-%%% finish_all
-%%%
-%%% There is still one problem with these testsuites. If one test
-%%% fails, it may not be possible to run some other cases, as it
-%%% may have e.g. created some row or loaded some table, that it
-%%% didn't undo (since it failed).
-%%%-----------------------------------------------------------------
-
-init_all(Config0) when list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
-
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
-
- %% --
- %% Start nodes
- %%
-
- ?line {ok, SaNode} = start_node(snmp_sa),
- ?line {ok, MgrNode} = start_node(snmp_mgr),
-
-
- %% --
- %% Create necessary files
- %%
-
- Dir = ?config(priv_dir, Config),
- ?DBG("init_all -> Dir ~p", [Dir]),
-
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
-
- file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
-
- file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
-
- file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
- ?DBG("init_all -> SaDir ~p", [SaDir]),
-
-
- %% --
- %% Start and initiate mnesia
- %%
-
- ?DBG("init_all -> load application mnesia", []),
- ?line ok = application:load(mnesia),
-
- ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, load, [mnesia]),
-
- ?DBG("init_all -> application mnesia: set_env dir",[]),
- ?line application_controller:set_env(mnesia, dir,
- filename:join(Dir, "Mnesia1")),
-
- ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(Dir, "Mnesia2")]),
-
- ?DBG("init_all -> create mnesia schema",[]),
- ?line ok = mnesia:create_schema([SaNode, node()]),
-
- ?DBG("init_all -> start application mnesia",[]),
- ?line ok = application:start(mnesia),
-
- ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
- ?line ok = rpc:call(SaNode, application, start, [mnesia]),
- Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
- Config].
-
-finish_all(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- stop_node(SaNode),
- stop_node(MgrNode),
- application:stop(mnesia).
-
-start_v1_agent(Config) when list(Config) ->
- start_agent(Config, [v1]).
-
-start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
- start_agent(Config, [v1], Opts).
-
-start_v2_agent(Config) when list(Config) ->
- start_agent(Config, [v2]).
-
-start_v3_agent(Config) when list(Config) ->
- start_agent(Config, [v3]).
-
-start_bilingual_agent(Config) when list(Config) ->
- start_agent(Config, [v1,v2]).
-
-start_multi_threaded_agent(Config) when list(Config) ->
- start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
-
-stop_agent(Config) when list(Config) ->
- ?LOG("stop_agent -> entry with"
- "~n Config: ~p",[Config]),
-
- {Sup, Par} = ?config(snmp_sup, Config),
- ?DBG("stop_agent -> attempt to stop (sup) ~p"
- "~n Sup: ~p"
- "~n Par: ~p",
- [Sup,
- (catch process_info(Sup)),
- (catch process_info(Par))]),
- stop_sup(Sup, Par),
-
- {Sup2, Par2} = ?config(snmp_sub, Config),
- ?DBG("stop_agent -> attempt to stop (sub) ~p"
- "~n Sup2: ~p"
- "~n Par2: ~p",
- [Sup2,
- (catch process_info(Sup2)),
- (catch process_info(Par2))]),
- stop_sup(Sup2, Par2),
-
- ?DBG("stop_agent -> done - now cleanup config", []),
- C1 = lists:keydelete(snmp_sup, 1, Config),
- lists:keydelete(snmp_sub, 1, C1).
-
-
-stop_sup(Pid, _) when node(Pid) == node() ->
- case (catch process_info(Pid)) of
- PI when list(PI) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- exit(Pid, kill),
- await_stopped(Pid, Ref);
- {'EXIT', _Reason} ->
- ?LOG("stop_sup -> ~p not running", [Pid]),
- ok
- end;
-stop_sup(Pid, _) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- ?LOG("stop_sup -> Ref: ~p", [Ref]),
- %% Pid ! {'EXIT', Parent, shutdown}, % usch
- exit(Pid, kill),
- await_stopped(Pid, Ref).
-
-await_stopped(Pid, Ref) ->
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ?DBG("received down message for ~p", [Pid]),
- ok
- after 10000 ->
- ?INF("await_stopped -> timeout for ~p",[Pid]),
- erlang:demonitor(Ref),
- ?FAIL({failed_stop,Pid})
- end.
-
-
-start_agent(Config, Vsn) ->
- start_agent(Config, Vsn, []).
-start_agent(Config, Vsn, Opts) ->
- ?LOG("start_agent -> entry (~p) with"
- "~n Config: ~p"
- "~n Vsn: ~p"
- "~n Opts: ~p",[node(), Config, Vsn, Opts]),
-
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
- snmp_app_env_init(vsn_init(Vsn) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, trace},
- {snmp_symbolic_store_verbosity, trace},
- {snmp_note_store_verbosity, trace},
- {snmp_net_if_verbosity, trace}],
- Opts),
-
-
- process_flag(trap_exit,true),
-
- {ok, AppSup} = snmp_app_sup:start_link(),
- unlink(AppSup),
- ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
-
- ?DBG("start_agent -> start master agent (old style)",[]),
- Sup = case (catch snmpa_app:start(normal)) of
- {ok, S} ->
- ?DBG("start_agent -> started, Sup: ~p",[S]),
- S;
-
- Else ->
- ?DBG("start_agent -> unknown result: ~n~p",[Else]),
- %% Get info about the apps we depend on
- MnesiaInfo = mnesia_running(),
- ?FAIL({start_failed,Else,MnesiaInfo})
- end,
-
- ?DBG("start_agent -> unlink from supervisor",[]),
- ?line unlink(Sup),
- ?line SaDir = ?config(sa_dir, Config),
- ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
- ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
- ?DBG("start_agent -> done",[]),
- ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
-
-
-vsn_init(Vsn) ->
- vsn_init([v1,v2,v3], Vsn, []).
-
-vsn_init([], _Vsn, Acc) ->
- Acc;
-vsn_init([V|Vsns], Vsn, Acc) ->
- case lists:member(V, Vsn) of
- true ->
- vsn_init(Vsns, Vsn, [{V, true}|Acc]);
- false ->
- vsn_init(Vsns, Vsn, [{V, false}|Acc])
- end.
-
-snmp_app_env_init(Env0, Opts) ->
- ?DBG("snmp_app_env_init -> unload snmp",[]),
- ?line application:unload(snmp),
- ?DBG("snmp_app_env_init -> load snmp",[]),
- ?line application:load(snmp),
- ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
- F1 = fun({Key,Val} = New, Acc0) ->
- ?DBG("snmp_app_env_init -> "
- "updating setting ~p to ~p", [Key, Val]),
- case lists:keyreplace(Key, 1, Acc0, New) of
- Acc0 ->
- [New|Acc0];
- Acc ->
- Acc
- end
- end,
- Env = lists:foldr(F1, Env0, Opts),
- ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
- F2 = fun({Key,Val}) ->
- ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
- application_controller:set_env(snmp, Key, Val)
- end,
- lists:foreach(F2, Env).
-
-
-
-
-%% Test if application is running
-mnesia_running() -> ?IS_MNESIA_RUNNING().
-crypto_running() -> ?IS_CRYPTO_RUNNING().
-
-
-start_sub(Dir) ->
- ?DBG("start_sub -> entry",[]),
- Opts = [{db_dir, Dir},
- {supervisor, [{verbosity, trace}]}],
- %% BMK BMK
-% {ok, P} = snmp_supervisor:start_sub(Dir),
- {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
- unlink(P),
- {ok, {P, self()}}.
-
-create_tables(SaNode) ->
- ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
- {attributes, [a1,a2]}]).
-
-delete_tables() ->
- mnesia:delete_table(friendsTable2),
- mnesia:delete_table(kompissTable2),
- mnesia:delete_table(snmp_variables).
-
-%% Creation is done in runtime!
-delete_mib_storage_mnesia_tables() ->
- mnesia:delete_table(snmpa_mib_data),
- mnesia:delete_table(snmpa_mib_tree),
- mnesia:delete_table(snmpa_symbolic_store).
-
-%%-----------------------------------------------------------------
-%% A test case is always one of:
-%% - v1 specific case
-%% - v2 specific case
-%% - v1 and v2 case
-%% All v1 specific cases are prefixed with v1_, and all v2 with
-%% v2_. E.g. v1_trap/v2_trap.
-%%
-%% All other cases are shared. However, the testserver uses the name
-%% of the case to generate a file for that case. The same case cannot
-%% be used in different configurations in the same suite. Therefore
-%% all these functions exists in two variants, the base function
-%% <base>, and a second version <base>_2. There may be several
-%% versions as well, <base>_N.
-%%-----------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-mib_storage_ets_cases() ->
-[mse_simple, mse_v1_processing, mse_big, mse_big2,
- mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
- mse_sa_error, mse_next_across_sa, mse_undo,
- mse_standard_mib, mse_community_mib, mse_framework_mib,
- mse_target_mib, mse_notification_mib,
- mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
- mse_mib_of].
-
-mib_storage_dets_cases() ->
-[msd_simple, msd_v1_processing, msd_big, msd_big2,
- msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
- msd_sa_error, msd_next_across_sa, msd_undo,
- msd_standard_mib, msd_community_mib, msd_framework_mib,
- msd_target_mib, msd_notification_mib,
- msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
- msd_mib_of].
-
-mib_storage_mnesia_cases() ->
-[msm_simple, msm_v1_processing, msm_big, msm_big2,
- msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
- msm_sa_error, msm_next_across_sa, msm_undo,
- msm_standard_mib, msm_community_mib, msm_framework_mib,
- msm_target_mib, msm_notification_mib,
- msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
- msm_mib_of].
-
-mse_size_check_cases() ->
-[mse_size_check].
-
-msd_size_check_cases() ->
-[msd_size_check].
-
-msm_size_check_cases() ->
-[msm_size_check].
-
-varm_mib_storage_dets_cases() ->
-[msd_varm_mib_start].
-
-varm_mib_storage_mnesia_cases() ->
-[msm_varm_mib_start].
-
-init_mib_storage_ets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,ets},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- init_ms(Config, [MibStorage]).
-
-init_ms(Config, Opts) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
-
-init_size_check_mse(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, ets},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msd(Config) when list(Config) ->
- AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage, {dets, AgentDir}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msm(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, {mnesia,[]}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_ms(Config, Opts) when list(Config) ->
- SaNode = ?GCONF(snmp_sa, Config),
- %% We are using v3 here, so crypto must be supported or else...
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end,
- create_tables(SaNode),
- AgentDir = ?GCONF(agent_dir, Config),
- MgrDir = ?GCONF(mgr_dir, Config),
- Ip = ?GCONF(ip, Config),
- ?line ok =
- config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_agent(Config, [v3], Opts)].
-
-init_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_dets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-init_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_mnesia -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-finish_mib_storage_ets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_ets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_dets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_dets -> entry", []),
- delete_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_size_check_mse(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msd(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msm(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_ms(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%% These are just interface functions to fool the test server
-mse_simple(X) -> simple(X).
-mse_v1_processing(X) -> v1_processing(X).
-mse_big(X) -> big(X).
-mse_big2(X) -> big2(X).
-mse_loop_mib(X) -> loop_mib(X).
-mse_api(X) -> api(X).
-mse_sa_register(X) -> sa_register(X).
-mse_v1_trap(X) -> v1_trap(X).
-mse_sa_error(X) -> sa_error(X).
-mse_next_across_sa(X) -> next_across_sa(X).
-mse_undo(X) -> undo(X).
-mse_standard_mib(X) -> snmp_standard_mib(X).
-mse_community_mib(X) -> snmp_community_mib(X).
-mse_framework_mib(X) -> snmp_framework_mib(X).
-mse_target_mib(X) -> snmp_target_mib(X).
-mse_notification_mib(X) -> snmp_notification_mib(X).
-mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-mse_sparse_table(X) -> sparse_table(X).
-mse_me_of(X) -> ms_me_of(X).
-mse_mib_of(X) -> ms_mib_of(X).
-
-msd_simple(X) -> simple(X).
-msd_v1_processing(X) -> v1_processing(X).
-msd_big(X) -> big(X).
-msd_big2(X) -> big2(X).
-msd_loop_mib(X) -> loop_mib(X).
-msd_api(X) -> api(X).
-msd_sa_register(X) -> sa_register(X).
-msd_v1_trap(X) -> v1_trap(X).
-msd_sa_error(X) -> sa_error(X).
-msd_next_across_sa(X) -> next_across_sa(X).
-msd_undo(X) -> undo(X).
-msd_standard_mib(X) -> snmp_standard_mib(X).
-msd_community_mib(X) -> snmp_community_mib(X).
-msd_framework_mib(X) -> snmp_framework_mib(X).
-msd_target_mib(X) -> snmp_target_mib(X).
-msd_notification_mib(X) -> snmp_notification_mib(X).
-msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msd_sparse_table(X) -> sparse_table(X).
-msd_me_of(X) -> ms_me_of(X).
-msd_mib_of(X) -> ms_mib_of(X).
-
-msm_simple(X) -> simple(X).
-msm_v1_processing(X) -> v1_processing(X).
-msm_big(X) -> big(X).
-msm_big2(X) -> big2(X).
-msm_loop_mib(X) -> loop_mib(X).
-msm_api(X) -> api(X).
-msm_sa_register(X) -> sa_register(X).
-msm_v1_trap(X) -> v1_trap(X).
-msm_sa_error(X) -> sa_error(X).
-msm_next_across_sa(X) -> next_across_sa(X).
-msm_undo(X) -> undo(X).
-msm_standard_mib(X) -> snmp_standard_mib(X).
-msm_community_mib(X) -> snmp_community_mib(X).
-msm_framework_mib(X) -> snmp_framework_mib(X).
-msm_target_mib(X) -> snmp_target_mib(X).
-msm_notification_mib(X) -> snmp_notification_mib(X).
-msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msm_sparse_table(X) -> sparse_table(X).
-msm_me_of(X) -> ms_me_of(X).
-msm_mib_of(X) -> ms_mib_of(X).
-
-
-mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
-msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
-msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
-
-msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
-msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
-
-ms_size_check(suite) -> [];
-ms_size_check(Config) when list(Config) ->
- p("ms_size_check..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?LOG("mib server size check...", []),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMPv2-MIB"),
- ?line load_master_std("SNMPv2-TM"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMPv2-MIB"),
- ?line unload_master("SNMPv2-TM"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-
-varm_mib_start(suite) -> [];
-varm_mib_start(Config) when list(Config) ->
- p("varm_mib_start..."),
- ?LOG("varm_mib_start -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- %% Start the agent
- Opts = ?GCONF(agent_opts, Config),
- Config1 = start_v1_agent(Config, Opts),
-
- %% Sleep some in order for the agent to start properly
- ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
- ?SLEEP(5000),
-
- %% Load all the mibs
- HardwiredMibs = loaded_mibs(),
- ?DBG("varm_mib_start -> load all mibs", []),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
-
- %% Unload the hardwired mibs
- ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
- ?SLEEP(1000),
- ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
- ?line unload_mibs(HardwiredMibs), %% unload hardwired
-
- ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
- ?SLEEP(1000),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- Config2 = stop_agent(Config1),
-
- %% Sleep some in order for the agent to stop properly
- ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
- ?SLEEP(5000),
-
- %% Start the agent (again)
- ?DBG("varm_mib_start -> start the agent", []),
- Config3 = start_v1_agent(Config2, Opts),
-
- ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
- ?SLEEP(5000),
-
- %% Perform the test(s)
- ?DBG("varm_mib_start -> perform the tests", []),
- try_test(snmp_community_mib),
- try_test(snmp_framework_mib),
- try_test(snmp_target_mib),
- try_test(snmp_notification_mib),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- stop_agent(Config3),
- ok.
-
-
--define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
--define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
--define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-ms_me_of(suite) -> [];
-ms_me_of(Config) when list(Config) ->
- p("ms_me_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = me_of(?snmpTrapCommunity_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = me_of(?vacmViewSpinLock_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-me_of(Oid) ->
- case snmpa:me_of(Oid) of
- {ok, #me{oid = Oid}} ->
- ok;
- {ok, #me{oid = OtherOid}} ->
- case lists:reverse(Oid) of
- [0|Rest] ->
- case lists:reverse(Rest) of
- OtherOid ->
- ok;
- AnotherOid ->
- {error, {invalid_oid, Oid, AnotherOid}}
- end;
- _ ->
- {error, {invalid_oid, Oid, OtherOid}}
- end;
- {error, Reason} ->
- {error, Reason};
- Else ->
- {error, Else}
- end.
-
-
-ms_mib_of(suite) -> [];
-ms_mib_of(Config) when list(Config) ->
- p("ms_mib_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
- 'SNMP-USER-BASED-SM-MIB'),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-mib_of(Oid, ExpectedMibName) ->
- ?DBG("mib_of -> entry with"
- "~n Oid: ~p"
- "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
- %% case snmpa:mib_of(Oid) of
- MibOf = snmpa:mib_of(Oid),
- ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
- case MibOf of
- {ok, ExpectedMibName} ->
- ok;
- {ok, OtherMibName} ->
- {error, {invalid_mib, ExpectedMibName, OtherMibName}};
- {error, Reason} ->
- {error, Reason};
- Else ->
- ?DBG("mib_of -> Else: ~n~p", [Else]),
- {error, Else}
- end.
-
-
-app_info(suite) -> [];
-app_info(Config) when list(Config) ->
- SnmpDir = app_dir(snmp),
- SslDir = app_dir(ssl),
- CryptoDir = app_dir(crypto),
- Attr = snmp:module_info(attributes),
- AppVsn =
- case lists:keysearch(app_vsn, 1, Attr) of
- {value, {app_vsn, V}} ->
- V;
- false ->
- "undefined"
- end,
- io:format("Root dir: ~s~n"
- "SNMP: Application dir: ~s~n"
- " Application ver: ~s~n"
- "SSL: Application dir: ~s~n"
- "CRYPTO: Application dir: ~s~n",
- [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
- ok.
-
-app_dir(App) ->
- case code:lib_dir(App) of
- D when list(D) ->
- filename:basename(D);
- {error, _Reason} ->
- "undefined"
- end.
-
-
-
-%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].
-
-init_v1(Config) when list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v1} | start_v1_agent(Config)].
-
-finish_v1(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v2_cases() -> [loop_mib_2];
-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].
-
-init_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_v2_agent(Config)].
-
-finish_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-v1_v2_cases() ->
-[simple_bi].
-
-init_v1_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, bilingual} | start_bilingual_agent(Config)].
-
-finish_v1_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v3_cases() -> [loop_mib_3];
-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].
-
-init_v3(Config) when list(Config) ->
- %% Make sure crypto works, otherwise start_agent will fail
- %% and we will be stuck with a bunch of mnesia tables for
- %% the rest of this suite...
- ?DBG("start_agent -> start crypto app",[]),
- case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end
- end,
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
- tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_v3_agent(Config)].
-
-finish_v3(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-mt_cases() ->
-[multi_threaded, mt_trap].
-
-init_mt(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_multi_threaded_agent(Config)].
-
-finish_mt(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-%% This one *must* be run first in each case.
-init_case(Config) when list(Config) ->
- ?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
-
- SaHost = ?HOSTNAME(SaNode),
- MgrHost = ?HOSTNAME(MgrNode),
- MasterHost = ?HOSTNAME(MasterNode),
- {ok, MasterIP} = snmp_misc:ip(MasterHost),
- {ok, MIP} = snmp_misc:ip(MgrHost),
- {ok, SIP} = snmp_misc:ip(SaHost),
-
-
- put(mgr_node, MgrNode),
- put(sa_node, SaNode),
- put(master_node, MasterNode),
- put(sa_host, SaHost),
- put(mgr_host, MgrHost),
- put(master_host, MasterHost),
- put(mip, tuple_to_list(MIP)),
- put(masterip , tuple_to_list(MasterIP)),
- put(sip, tuple_to_list(SIP)),
-
- MibDir = ?config(mib_dir, Config),
- put(mib_dir, MibDir),
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- put(std_mib_dir, StdM),
-
- MgrDir = ?config(mgr_dir, Config),
- put(mgr_dir, MgrDir),
-
- put(vsn, ?config(vsn, Config)),
- ?DBG("init_case -> exit with"
- "~n MasterNode: ~p"
- "~n SaNode: ~p"
- "~n MgrNode: ~p"
- "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
- {SaNode, MgrNode, MibDir}.
-
-load_master(Mib) ->
- ?DBG("load_master -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
-
-load_master_std(Mib) ->
- ?DBG("load_master_std -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
-
-unload_master(Mib) ->
- ?DBG("unload_master -> entry with"
- "~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
-
-loaded_mibs() ->
- ?DBG("loaded_mibs -> entry",[]),
- Info = snmpa:info(snmp_master_agent),
- {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
- [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
-
-unload_mibs(Mibs) ->
- ?DBG("unload_mibs -> entry with"
- "~n Mibs: ~p", [Mibs]),
- ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
-
-start_subagent(SaNode, RegTree, Mib) ->
- ?DBG("start_subagent -> entry with"
- "~n SaNode: ~p"
- "~n RegTree: ~p"
- "~n Mib: ~p", [SaNode, RegTree, Mib]),
- MA = whereis(snmp_master_agent),
- ?DBG("start_subagent -> MA: ~p", [MA]),
- MibDir = get(mib_dir),
- Mib1 = join(MibDir,Mib),
- %% BMK BMK
-% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
- case rpc:call(SaNode, snmpa_supervisor,
- start_sub_agent, [MA, RegTree, [Mib1]]) of
- {ok, SA} ->
- ?DBG("start_subagent -> SA: ~p", [SA]),
- {ok, SA};
- Error ->
- ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
- end.
-
-stop_subagent(SA) ->
- ?DBG("stop_subagent -> entry with"
- "~n SA: ~p", [SA]),
- %% BNK BMK
- %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
- rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
-
-%%-----------------------------------------------------------------
-%% This function takes care of the old OTP-SNMPEA-MIB.
-%% Unfortunately, the testcases were written to use the data in the
-%% internal tables, and these table are now obsolete and not used
-%% by the agent. Therefore, we emulate them by using
-%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
-%%
-%% These two rows must exist in intCommunityTable
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
-%% (But with the manager's IP address)
-%%
-%%-----------------------------------------------------------------
-init_old() ->
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [6 | "public"],
- {get(mip), "public", 2, 2}),
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [13 | "standard trap"],
- {get(mip), "standard trap", 2, 1}),
- snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
-
-
-
-simple(suite) -> [];
-simple(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(simple_standard_test).
-
-simple_2(X) -> simple(X).
-
-simple_bi(suite) -> [];
-simple_bi(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(vsn, v1), % First, try v1 manager
- try_test(simple_standard_test),
-
- put(vsn, v2), % Then, try v2 manager
- try_test(simple_standard_test).
-
-simple_3(X) ->
- simple(X).
-
-big(suite) -> [];
-big(Config) when list(Config) ->
- ?DBG("big -> entry", []),
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-big_2(X) -> big(X).
-
-big_3(X) -> big(X).
-
-
-big2(suite) -> [];
-big2(Config) when list(Config) ->
- %% This is exactly the same tests as 'big', but with the
- %% v2 equivalent of the mibs.
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
-
-big2_2(X) -> big2(X).
-
-big2_3(X) -> big2(X).
-
-
-multi_threaded(suite) -> [];
-multi_threaded(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(multi_threaded_test),
- ?line unload_master("Test1").
-
-mt_trap(suite) -> [];
-mt_trap(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- ?line load_master("TestTrapv2"),
- try_test(mt_trap_test, [MA]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("Test1").
-
-v2_types(suite) -> [];
-v2_types(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(types_v2_test),
- ?line unload_master("Test1").
-
-v2_types_3(X) -> v2_types(X).
-
-
-implied(suite) -> [];
-implied(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(implied_test,[MA]),
- ?line unload_master("Test1").
-
-implied_3(X) -> implied(X).
-
-
-sparse_table(suite) -> [];
-sparse_table(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(sparse_table_test),
- ?line unload_master("Test1").
-
-sparse_table_2(X) -> sparse_table(X).
-
-sparse_table_3(X) -> sparse_table(X).
-
-cnt_64(suite) -> [];
-cnt_64(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(cnt_64_test, [MA]),
- ?line unload_master("Test1").
-
-cnt_64_2(X) -> cnt_64(X).
-
-cnt_64_3(X) -> cnt_64(X).
-
-opaque(suite) -> [];
-opaque(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(opaque_test),
- ?line unload_master("Test1").
-
-opaque_2(X) -> opaque(X).
-
-opaque_3(X) -> opaque(X).
-
-
-change_target_addr_config(suite) -> [];
-change_target_addr_config(Config) when list(Config) ->
- p("Testing changing target address config..."),
- ?LOG("change_target_addr_config -> entry",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(sname,snmp_suite),
- put(verbosity,trace),
-
- MA = whereis(snmp_master_agent),
-
- ?LOG("change_target_addr_config -> load TestTrap",[]),
- ?line load_master("TestTrap"),
-
- ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,trace),
-
- %% First send some traps that will arive att the original manager
- ?LOG("change_target_addr_config -> send trap",[]),
- try_test(ma_trap1, [MA]),
-
- ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
-
- %% Start new dummy listener
- ?LOG("change_target_addr_config -> start dummy manager",[]),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
-
- %% Reconfigure
- ?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- %% Send the trap again
- ?LOG("change_target_addr_config -> send trap again",[]),
- catch dummy_manager_send_trap2(Pid),
-
- ?LOG("change_target_addr_config -> await trap ack",[]),
- catch dummy_manager_await_trap2_ack(),
-
- ?LOG("change_target_addr_config -> stop dummy manager",[]),
- ?line ok = dummy_manager_stop(Pid),
-
- ?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
-
- ?LOG("change_target_addr_config -> unload TestTrap",[]),
- ?line unload_master("TestTrap").
-
-
-dummy_manager_start(MA) ->
- ?DBG("dummy_manager_start -> entry",[]),
- Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
- ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
- await_dummy_manager_started(Pid).
-
-await_dummy_manager_started(Pid) ->
- receive
- {dummy_manager_started,Pid,Port} ->
- ?DBG("dummy_manager_start -> acknowledge received with"
- "~n Port: ~p",[Port]),
- {ok,Pid,Port};
- {'EXIT', Pid, Reason} ->
- {error, Pid, Reason};
- O ->
- ?LOG("dummy_manager_start -> received unknown message:"
- "~n ~p",[O]),
- await_dummy_manager_started(Pid)
- end.
-
-dummy_manager_stop(Pid) ->
- ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
- Pid ! stop,
- receive
- {dummy_manager_stopping, Pid} ->
- ?DBG("dummy_manager_stop -> acknowledge received",[]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_stop -> timeout",[]),
- timeout
- end.
-
-dummy_manager_send_trap2(Pid) ->
- ?DBG("dummy_manager_send_trap2 -> entry",[]),
- Pid ! {send_trap,testTrap2}.
-
-dummy_manager_await_trap2_ack() ->
- ?DBG("dummy_manager_await_trap2 -> entry",[]),
- receive
- {received_trap,Trap} ->
- ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
- %% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
- %% is no relation between these two test cases as far as I
- %% able to figure out...
- sleep(60000),
- ok;
- O ->
- ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_await_trap2 -> timeout",[]),
- timeout
- end.
-
-dummy_manager_init(Parent,MA) ->
- ?DBG("dummy_manager_init -> entry with"
- "~n Parent: ~p"
- "~n MA: ~p",[Parent,MA]),
- {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
- ?DBG("dummy_manager_init -> S: ~p",[S]),
- {ok,Port} = inet:port(S),
- ?DBG("dummy_manager_init -> Port: ~p",[Port]),
- Parent ! {dummy_manager_started,self(),Port},
- dummy_manager_loop(Parent,S,MA).
-
-dummy_manager_loop(P,S,MA) ->
- ?LOG("dummy_manager_loop -> ready for receive",[]),
- receive
- {send_trap,Trap} ->
- ?LOG("dummy_manager_loop -> received trap send request"
- "~n Trap: ~p",[Trap]),
- snmpa:send_trap(MA, Trap, "standard trap"),
- dummy_manager_loop(P,S,MA);
- {udp, _UdpId, Ip, UdpPort, Bytes} ->
- ?LOG("dummy_manager_loop -> received upd message"
- "~n from: ~p:~p"
- "~n size: ~p",
- [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
- R = dummy_manager_handle_message(Bytes),
- ?DBG("dummy_manager_loop -> R: ~p",[R]),
- P ! R,
- dummy_manager_loop(P,S,MA);
- stop ->
- ?DBG("dummy_manager_loop -> received stop request",[]),
- P ! {dummy_manager_stopping, self()},
- gen_udp:close(S),
- exit(normal);
- O ->
- ?LOG("dummy_manager_loop -> received unknown message:"
- "~n ~p",[O]),
- dummy_manager_loop(P,S,MA)
- end.
-
-dummy_manager_message_sz(B) when binary(B) ->
- size(B);
-dummy_manager_message_sz(L) when list(L) ->
- length(L);
-dummy_manager_message_sz(_) ->
- undefined.
-
-dummy_manager_handle_message(Bytes) ->
- case (catch snmp_pdus:dec_message(Bytes)) of
- {'EXIT',Reason} ->
- ?ERR("dummy_manager_handle_message -> "
- "failed decoding message only:~n ~p",[Reason]),
- {error,Reason};
- M ->
- ?DBG("dummy_manager_handle_message -> decoded message:"
- "~n ~p",[M]),
- {received_trap,M}
- end.
-
-
-api(suite) -> [];
-api(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(api_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-api_2(X) -> api(X).
-
-api_3(X) -> api(X).
-
-
-subagent(suite) -> [];
-subagent(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- try_test(load_test_sa),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
-
- p("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(load_test),
-
- p("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(unreg_test),
- p("Testing register subagent..."),
- rpc:call(SaNode, snmp, register_subagent,
- [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- ?line stop_subagent(SA),
- try_test(unreg_test).
-
-subagent_2(X) -> subagent(X).
-
-subagent_3(X) -> subagent(X).
-
-
-mnesia(suite) -> [];
-mnesia(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent with mnesia impl..."),
- {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- try_test(big_test_2),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
-
-mnesia_2(X) -> mnesia(X).
-
-mnesia_3(X) -> mnesia(X).
-
-
-
-mul_cases() ->
-[mul_get, mul_get_err, mul_next, mul_next_err,
- mul_set_err].
-
-
-multiple_reqs_3(_X) ->
- {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
-
-
-mul_cases_2() ->
-[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
- mul_set_err_2].
-
-
-mul_cases_3() ->
- [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
-
-
-init_mul(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- [{mul_sub, SA} | Config].
-
-finish_mul(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- SA = ?config(mul_sub, Config),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
- lists:keydelete(mul_sub, 1, Config).
-
-mul_get(suite) -> [];
-mul_get(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get..."),
- try_test(do_mul_get).
-
-mul_get_2(X) -> mul_get(X).
-
-mul_get_3(X) -> mul_get(X).
-
-
-mul_get_err(suite) -> [];
-mul_get_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get with error..."),
- try_test(do_mul_get_err).
-
-mul_get_err_2(X) -> mul_get_err(X).
-
-mul_get_err_3(X) -> mul_get_err(X).
-
-
-mul_next(suite) -> [];
-mul_next(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next).
-
-mul_next_2(X) -> mul_next(X).
-
-mul_next_3(X) -> mul_next(X).
-
-
-mul_next_err(suite) -> [];
-mul_next_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next_err).
-
-mul_next_err_2(X) -> mul_next_err(X).
-
-mul_next_err_3(X) -> mul_next_err(X).
-
-
-mul_set(suite) -> [];
-mul_set(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set..."),
- try_test(do_mul_set).
-
-mul_set_2(X) -> mul_set(X).
-
-mul_set_3(X) -> mul_set(X).
-
-
-mul_set_err(suite) -> [];
-mul_set_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set with error..."),
- try_test(do_mul_set_err).
-
-mul_set_err_2(X) -> mul_set_err(X).
-
-mul_set_err_3(X) -> mul_set_err(X).
-
-
-sa_register(suite) -> [];
-sa_register(Config) when list(Config) ->
- ?DBG("sa_register -> entry", []),
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?DBG("sa_register -> start subagent", []),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
-
- ?DBG("sa_register -> unregister subagent", []),
- p("Testing unregister subagent (2)..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Loading SA-MIB..."),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
- ?DBG("sa_register -> register subagent", []),
- rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
- try_test(sa_mib),
-
- ?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
-
-sa_register_2(X) -> sa_register(X).
-
-sa_register_3(X) -> sa_register(X).
-
-
-v1_trap(suite) -> [];
-v1_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_trap1, [MA]),
- try_test(ma_trap2, [MA]),
- try_test(ma_v2_2_v1_trap, [MA]),
- try_test(ma_v2_2_v1_trap2, [MA]),
-
- p("Testing trap sending from subagent..."),
- try_test(sa_trap1, [SA]),
- try_test(sa_trap2, [SA]),
- try_test(sa_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v2_trap(suite) -> [];
-v2_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
-
- try_test(ma_v2_trap1, [MA]),
- try_test(ma_v2_trap2, [MA]),
- try_test(ma_v1_2_v2_trap, [MA]),
- try_test(ma_v1_2_v2_trap2, [MA]),
-
- try_test(sa_mib),
- p("Testing trap sending from subagent..."),
- try_test(sa_v1_2_v2_trap1, [SA]),
- try_test(sa_v1_2_v2_trap2, [SA]),
- try_test(sa_v1_2_v2_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v3_trap(X) ->
- v2_trap(X).
-
-
-v3_inform(_X) ->
- %% v2_inform(X).
- {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
-
-init_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-init_v3_inform(X) ->
- init_v2_inform(X).
-
-finish_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-finish_v3_inform(X) ->
- finish_v2_inform(X).
-
-
-
-v2_inform_i(suite) -> [];
-v2_inform_i(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing inform sending from master agent... NOTE! This test\ntakes a "
- "few minutes (5) to complete."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_v2_inform1, [MA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2").
-
-v3_inform_i(X) -> v2_inform_i(X).
-
-
-sa_error(suite) -> [];
-sa_error(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing sa bad value (is_set_ok)..."),
- try_test(sa_errs_bad_value),
-
- p("Testing sa gen err (set)..."),
- try_test(sa_errs_gen_err),
-
- p("Testing too big..."),
- try_test(sa_too_big),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- stop_subagent(SA).
-
-sa_error_2(X) -> sa_error(X).
-
-sa_error_3(X) -> sa_error(X).
-
-
-next_across_sa(suite) -> [];
-next_across_sa(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Loading another subagent mib..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
-
- rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- p("Testing next across subagent (endOfMibView from SA)..."),
- try_test(next_across_sa),
-
- p("Unloading mib"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Starting another subagent"),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
- p("Testing next across subagent (wrong prefix from SA)..."),
- try_test(next_across_sa),
-
- stop_subagent(SA),
- stop_subagent(SA2).
-
-next_across_sa_2(X) -> next_across_sa(X).
-
-next_across_sa_3(X) -> next_across_sa(X).
-
-
-undo(suite) -> [];
-undo(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing undo phase at master agent..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
- try_test(undo_test),
- try_test(api_test2),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
-
- p("Testing bad return values from instrum. funcs..."),
- try_test(bad_return),
-
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
-
- p("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
- try_test(undo_test),
- try_test(api_test3),
-
- p("Testing undo phase across master/subagents..."),
- try_test(undo_test),
- try_test(api_test3),
- stop_subagent(SA).
-
-undo_2(X) -> undo(X).
-
-undo_3(X) -> undo(X).
-
-%% Req. Test2
-v1_processing(suite) -> [];
-v1_processing(Config) when list(Config) ->
- ?DBG("v1_processing -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v1_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v2_processing(suite) -> [];
-v2_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v3_processing(suite) -> [];
-v3_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc), % same as v2!
- ?line unload_master("Test2").
-
-
-%% We'll try get/set/trap and inform for all the auth & priv protocols.
-%% For informs, the mgr is auth-engine. The agent has to sync. This is
-%% accomplished by the first inform sent. That one will generate a
-%% report, which makes it in sync. The notification-generating
-%% application times out, and send again. This time it'll work.
-
-v3_crypto_basic(suite) -> [];
-v3_crypto_basic(_Config) ->
- EID = [0,0,0,0,0,0,0,0,0,0,0,2],
- %% From rfc2274 appendix A.3.1
- ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
- ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
- 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
- KMd5_1,
- %% From rfc2274 appendix A.3.2
- ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
- ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
- 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
- KSHA_1,
- %% From rfc2274, appendix A.5.1
- ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
- 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
- snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- %% From rfc2274, appendix A.5.2
- ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
- 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
- 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- KSHA_1t = lists:sublist(KSHA_1, 16),
- KSHA_2t = lists:sublist(KSHA_2, 16),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
- 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
-
- %% Try with correct random
- ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
- ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
- ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
- ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
- ok.
-
-
-
-v3_md5_auth(suite) -> [];
-v3_md5_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing MD5 authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_sha_auth(suite) -> [];
-v3_sha_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing SHA authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_des_priv(suite) -> [];
-v3_des_priv(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing DES encryption...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-%% Make sure mgr is in sync with agent
-v3_sync(Funcs) ->
- ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
- g([[sysDescr, 0]]),
- expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
- g([[sysDescr, 0]]),
- expect(433, [{[sysDescr,0], any}]),
- lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
-
-v3_inform_sync(MA) ->
- ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
- "standard inform", []),
- %% Make sure agent is in sync with mgr...
- ?DBG("v3_sync -> wait some time: ",[]),
- sleep(20000), % more than 1500*10 in target_addr.conf
- ?DBG("v3_sync -> await response",[]),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]).
-
-
-v2_caps(suite) -> [];
-v2_caps(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(v2_caps_i, [node()]).
-
-v2_caps_3(X) -> v2_caps(X).
-
-
-v2_caps_i(Node) ->
- ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
- g([[sysORID, Idx], [sysORDescr, Idx]]),
- ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
- {[sysORDescr, Idx], "test cap"}]),
- ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
- g([[sysORID, Idx]]),
- ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
-
-
-%% Req. Test2
-v1_proc() ->
- ?DBG("v1_proc -> entry", []),
- %% According to RFC1157.
- %% Template: <Section>:<list no>
- v1_get_p(),
- v1_get_next_p(),
- v1_set_p().
-
-
-v1_get_p() ->
- %% 4.1.2:1
- g([[test2]]),
- ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
- g([[tDescr]]),
- ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
- g([[tDescr2,0]]),
- ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
- g([[tDescr3,0]]),
- ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
- g([[tDescr4,0]]),
- ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
- {[tDescr,0], 'NULL'}]),
- g([[sysDescr,3]]),
- ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
-
- %% 4.1.2:2
- g([[tTable]]),
- ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
- g([[tEntry]]),
- ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
-
- %% 4.1.2:3
- g([[tTooBig, 0]]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.2:4
- g([[tGenErr1, 0]]),
- ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]).
-
-
-v1_get_next_p() ->
- %% 4.1.3:1
- gn([[1,3,7,1]]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
- gn([[tDescr2]]),
- ?line expect(11, tooBig, 0, any),
-
- %% 4.1.3:2
- gn([[tTooBig]]),
- io:format("We currently don't handle tooBig correct!!!\n"),
-% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
- ?line expect(20, tooBig, 0, any),
-
- %% 4.1.3:3
- gn([[tGenErr1]]),
-% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
- ?line expect(40, genErr, 1, any),
- gn([[tGenErr2]]),
-% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
- ?line expect(41, genErr, 1, any),
- gn([[sysDescr], [tGenErr3]]),
-% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
-% {[tGenErr3], 'NULL'}]).
- ?line expect(42, genErr, 2, any).
-
-v1_set_p() ->
- %% 4.1.5:1
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
- s([{[tDescr3], s, "noSuchObject"}]),
- ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
- s([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
- s([{[tDescr2,0], s, "inconsistentName"}]),
- ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
-
- %% 4.1.5:2
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.1.5:3
- %% The standard is quite incorrect here. The resp pdu was too big. In
- %% the resp pdu, we have the original vbs. In the tooBig pdu we still
- %% have to original vbs => the tooBig pdu is too big as well!!! It
- %% may not get it to the manager, unless the agent uses 'NULL' instead
- %% of the std-like original value.
- s([{[tTooBig, 0], s, ?tooBigStr}]),
- %% according to std:
-% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.5:4
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
- s([{[tDescr2, 0], s, "commit_fail"}]),
- ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
-
-%% Req. Test2
-v2_proc() ->
- %% According to RFC1905.
- %% Template: <Section>:<list no>
- ?DBG("v2_proc -> entry",[]),
- v2_get_p(),
- v2_get_next_p(),
- v2_get_bulk_p(),
- v2_set_p().
-
-v2_get_p() ->
- %% 4.2.1:2
- ?DBG("v2_get_p -> entry",[]),
- g([[test2]]),
- ?line expect(10, [{[test2], noSuchObject}]),
- g([[tDescr]]),
- ?line expect(11, [{[tDescr], noSuchObject}]),
- g([[tDescr4,0]]),
- ?line expect(12, [{[tDescr4,0], noSuchObject}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
- {[tDescr,0], noSuchObject}]),
- g([[tTable]]),
- ?line expect(14, [{[tTable], noSuchObject}]),
- g([[tEntry]]),
- ?line expect(15, [{[tEntry], noSuchObject}]),
-
- %% 4.2.1:3
- g([[tDescr2,0]]), %% instrum ret noSuchName!!!
- ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
- g([[tDescr3,0]]),
- ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
- g([[sysDescr,3]]),
- ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
- g([[tIndex,1]]),
- ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
-
- %% 4.2.1 - any other error: genErr
- g([[tGenErr1, 0]]),
- ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]),
-
- %% 4.2.1 - tooBig
- g([[tTooBig, 0]]),
- ?line expect(40, tooBig, 0, []).
-
-
-v2_get_next_p() ->
- %% 4.2.2:2
- ?DBG("v2_get_next_p -> entry",[]),
- gn([[1,3,7,1]]),
- ?line expect(10, [{[1,3,7,1], endOfMibView}]),
- gn([[sysDescr], [1,3,7,1]]),
- ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gn([[tCnt2, 1]]),
- ?line expect(12, [{[tCnt2,2], 100}]),
- gn([[tCnt2, 2]]),
- ?line expect(12, [{[tCnt2,2], endOfMibView}]),
-
- %% 4.2.2 - any other error: genErr
- gn([[tGenErr1]]),
- ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
- gn([[tGenErr2]]),
- ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
- gn([[sysDescr], [tGenErr3]]),
- ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
- {[tGenErr3], 'NULL'}]),
-
- %% 4.2.2 - tooBig
- gn([[tTooBig]]),
- ?line expect(20, tooBig, 0, []).
-
-v2_get_bulk_p() ->
- %% 4.2.3
- ?DBG("v2_get_bulk_p -> entry",[]),
- gb(1, 1, []),
- ?line expect(10, []),
- gb(-1, 1, []),
- ?line expect(11, []),
- gb(-1, -1, []),
- ?line expect(12, []),
- gb(-1, -1, []),
- ?line expect(13, []),
- gb(2, 0, [[sysDescr], [1,3,7,1]]),
- ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(1, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(0, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
- ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
- ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[sysDescr, 0], "Erlang SNMP agent"}]),
-
- gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
- ?line expect(19, []),
-
- gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
- ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
- {[sysObjectID], 'NULL'},
- {[tGenErr1], 'NULL'},
- {[sysDescr], 'NULL'}]),
- gb(0, 2, [[tCnt2, 1]]),
- ?line expect(21, [{[tCnt2,2], 100},
- {[tCnt2,2], endOfMibView}]).
-
-
-v2_set_p() ->
- %% 4.2.5:1
- ?DBG("v2_set_p -> entry",[]),
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
-
- %% 4.2.5:2
- s([{[1,3,6,1,0], s, "noSuchObject"}]),
- ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
-
- %% 4.2.5:3
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.2.5:4
- s([{[tStr, 0], s, ""}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
- s([{[tStr, 0], s, "12345"}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
-
- %% 4.2.5:5 - N/A
-
- %% 4.2.5:6
- s([{[tInt1, 0], i, 0}]),
- ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
- s([{[tInt1, 0], i, 5}]),
- ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
- s([{[tInt2, 0], i, 0}]),
- ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
- s([{[tInt2, 0], i, 5}]),
- ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
- s([{[tInt3, 0], i, 5}]),
- ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
-
- %% 4.2.5:7
- s([{[tDescrX, 1, 1], s, "noCreation"}]),
- ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
-
- %% 4.2.5:8
- s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
- ?line expect(80, inconsistentName, 1,
- [{[tDescrX, 1, 2], "inconsistentName"}]),
-
- %% 4.2.5:9
- s([{[tCnt, 1, 2], i, 5}]),
- ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
-
- %% 4.2.5:10
- s([{[tDescr2,0], s, "inconsistentValue"}]),
- ?line expect(100, inconsistentValue, 1,
- [{[tDescr2,0], "inconsistentValue"}]),
-
- %% 4.2.5:11
- s([{[tDescr2,0], s, "resourceUnavailable"}]),
- ?line expect(110, resourceUnavailable, 1,
- [{[tDescr2,0],"resourceUnavailable"}]),
-
- %% 4.2.5:12
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
-
- %% commitFailed and undoFailed is tested by the 'undo' case.
-
-
-%% Req. OLD-SNMPEA-MIB
-table_test() ->
- io:format("Testing simple get, next and set on communityTable...~n"),
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
- Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
- Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
- Key1c4 = [intCommunityAccess,get(mip),is("public")],
- EndKey = [intCommunityEntry,[9],get(mip),is("public")],
- gn([[intCommunityEntry]]),
- ?line expect(7, [{Key1c3, 2}]),
- gn([[intCommunityTable]]),
- ?line expect(71, [{Key1c3, 2}]),
- gn([[community]]),
- ?line expect(72, [{Key1c3, 2}]),
- gn([[otpSnmpeaMIB]]),
- ?line expect(73, [{Key1c3, 2}]),
- gn([[ericsson]]),
- ?line expect(74, [{Key1c3, 2}]),
- gn([Key1c3]),
- ?line expect(8, [{Key2c3, 2}]),
- gn([Key2c3]),
- ?line expect(9, [{Key1c4, 2}]),
- gn([EndKey]),
- AgentIp = [intAgentIpAddress,0],
- ?line expect(10, [{AgentIp, any}]),
- g([Key1c3]),
- ?line expect(11, [{Key1c3, 2}]),
- g([EndKey]),
- ?line ?v1_2(expect(12, noSuchName, 1, any),
- expect(12, [{EndKey, noSuchObject}])),
-
- io:format("Testing row creation/deletion on communityTable...~n"),
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
- s([{NewKeyc5, ?createAndGo}]),
- ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
- s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
- ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
- g([NewKeyc4]),
- ?line expect(16, [{NewKeyc4, 2}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(17, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc4, 2}]),
- ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
- s([{NewKeyc5, ?createAndWait}]),
- ?line expect(19, [{NewKeyc5, ?createAndWait}]),
- g([NewKeyc5]),
- ?line expect(20, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc4, 2}]),
- ?line expect(21, [{NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(22, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc3, 2}]),
- ?line expect(23, [{NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(24, [{NewKeyc5, ?notInService}]),
- s([{NewKeyc5, ?active}]),
- ?line expect(25, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(26, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc3, 3}]),
- ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
- otp_1128().
-
-%% Req. system group
-simple_standard_test() ->
- ?DBG("simple_standard_test -> entry",[]),
- gn([[1,1]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3]]),
- ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6]]),
- ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1]]),
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2]]),
- ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1]]),
- ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1,1]]),
- ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[sysDescr]]),
- ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr,0]]),
- ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr]]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{[sysDescr], noSuchObject}])),
- g([[1,6,7,0]]),
- ?line ?v1_2(expect(41, noSuchName, 1, any),
- expect(3, [{[1,6,7,0], noSuchObject}])),
- gn([[1,13]]),
- ?line ?v1_2(expect(4, noSuchName,1, any),
- expect(4, [{[1,13], endOfMibView}])),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
- g([[sysLocation, 0]]),
- ?line expect(6, [{[sysLocation, 0], "new_value"}]),
- io:format("Testing noSuchName and badValue...~n"),
- s([{[sysServices,0], 3}]),
- ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
- s([{[sysLocation, 0], i, 3}]),
- ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
- ?DBG("simple_standard_test -> done",[]),
- ok.
-
-%% This is run in the agent node
-db_notify_client(suite) -> [];
-db_notify_client(Config) when list(Config) ->
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
- [SaNode,MgrNode,MibDir]),
- snmpa_local_db:register_notify_client(self(),?MODULE),
-
- %% This call (the manager) will issue to set operations, so
- %% we expect to receive to notify(insert) calls.
- try_test(db_notify_client_test),
-
- ?DBG("await first notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
- end,
-
- ?DBG("await second notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
- end,
-
- snmpa_local_db:unregister_notify_client(self()).
-
-
-%% This is run in the manager node
-db_notify_client_test() ->
- ?DBG("set first new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?DBG("set second new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]).
-
-notify(Pid,What) ->
- ?DBG("notify(~p,~p) -> called",[Pid,What]),
- Pid ! {db_notify_test_reply,What}.
-
-
-%% Req: system group, OLD-SNMPEA-MIB, Klas1
-big_test() ->
- ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
- simple_standard_test(),
-
- ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
- gn([[klas1]]),
- ?line expect(1, [{[fname,0], ""}]),
- g([[fname,0]]),
- ?line expect(2, [{[fname,0], ""}]),
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[fname,0]]),
- ?line expect(4, [{[fname,0], "test set"}]),
-
- ?DBG("big_test -> "
- "testing next from last instance in master to subagent...",[]),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname,0], "test set"}]),
- s([{[fname,0], s, ""}]),
- ?line expect(52, [{[fname,0], ""}]),
-
- table_test(),
-
- ?DBG("big_test -> adding one row in subagent table",[]),
- _FTab = [friendsEntry],
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [friendsEntry, [3, 3]]]),
- ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?active}]),
- s([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
-
- otp_1131(),
-
- ?DBG("big_test -> adding two rows in subagent table with special INDEX",
- []),
- s([{[kompissEntry, [1, 3]], s, "kompis3"},
- {[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?createAndGo}]),
- g([[kompissEntry, [1, 3]],
- [kompissEntry, [2, 3]]]),
- ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- gn([[kompissEntry, [1]],
- [kompissEntry, [2]]]),
- ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- s([{[kompissEntry, [1, 2]], s, "kompis3"},
- {[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry, [1, 1]],
- [kompissEntry, [2, 1]]]),
- ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?active}]),
- s([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
- s([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
- ?DBG("big_test -> done",[]),
- ok.
-
-%% Req. system group, Klas2, OLD-SNMPEA-MIB
-big_test_2() ->
- p("Testing simple next/get/set @ master agent (2)..."),
- simple_standard_test(),
-
- p("Testing simple next/get/set @ subagent (2)..."),
- gn([[klas2]]),
- ?line expect(1, [{[fname2,0], ""}]),
- g([[fname2,0]]),
- ?line expect(2, [{[fname2,0], ""}]),
- s([{[fname2,0], s, "test set"}]),
- ?line expect(3, [{[fname2,0], "test set"}]),
- g([[fname2,0]]),
- ?line expect(4, [{[fname2,0], "test set"}]),
-
- otp_1298(),
-
- p("Testing next from last object in master to subagent (2)..."),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname2,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname2,0], "test set"}]),
-
- table_test(),
-
- p("Adding one row in subagent table (2)"),
- _FTab = [friendsEntry2],
- s([{[friendsEntry2, [2, 3]], s, "kompis3"},
- {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?createAndGo}]),
- g([[friendsEntry2, [2, 3]],
- [friendsEntry2, [3, 3]]]),
- ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?active}]),
- s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
-
- p("Adding two rows in subagent table with special INDEX (2)"),
- s([{[kompissEntry2, [1, 3]], s, "kompis3"},
- {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?createAndGo}]),
- g([[kompissEntry2, [1, 3]],
- [kompissEntry2, [2, 3]]]),
- ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- gn([[kompissEntry2, [1]],
- [kompissEntry2, [2]]]),
- ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- s([{[kompissEntry2, [1, 2]], s, "kompis3"},
- {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry2, [1, 1]],
- [kompissEntry2, [2, 1]]]),
- ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?active}]),
- s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
- s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
- ok.
-
-%% Req. Test1
-multi_threaded_test() ->
- p("Testing multi threaded agent..."),
- g([[multiStr,0]]),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(1, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "pelle"}]),
- ?line expect(2, [{[sysLocation, 0], "pelle"}]),
- Pid ! continue,
- ?line expect(3, [{[multiStr,0], "ok"}]),
-
- s([{[multiStr, 0], s, "block"}]),
- Pid2 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(4, [{[sysUpTime,0], any}]),
- g([[multiStr,0]]),
- Pid3 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(5, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "kalle"}]),
- Pid3 ! continue,
- ?line expect(6, [{[multiStr,0], "ok"}]),
- Pid2 ! continue,
- ?line expect(7, [{[multiStr,0], "block"}]),
- ?line expect(8, [{[sysLocation,0], "kalle"}]).
-
-%% Req. Test1, TestTrapv2
-mt_trap_test(MA) ->
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- snmpa:send_trap(MA, mtTrap, "standard trap"),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(2, [{[sysUpTime,0], any}]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- Pid ! continue,
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [2]},
- {[multiStr,0], "ok"}]).
-
-
-get_multi_pid() ->
- get_multi_pid(10).
-get_multi_pid(0) ->
- ?line ?FAIL(no_global_name);
-get_multi_pid(N) ->
- sleep(1000),
- case global:whereis_name(snmp_multi_tester) of
- Pid when pid(Pid) -> Pid;
- _ -> get_multi_pid(N-1)
- end.
-
-%% Req. Test1
-types_v2_test() ->
- p("Testing v2 types..."),
-
- s([{[bits1,0], 2#10}]),
- ?line expect(1, [{[bits1,0], ?str(2#10)}]),
- g([[bits1,0]]),
- ?line expect(2, [{[bits1,0], ?str(2#101)}]),
-
- s([{[bits2,0], 2#11000000110}]),
- ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
- g([[bits2,0]]),
- ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
-
- g([[bits3,0]]),
- ?line expect(50, genErr, 1, any),
-
- g([[bits4,0]]),
- ?line expect(51, genErr, 1, any),
-
- s([{[bits1,0], s, [2#10]}]),
- ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
-
- s([{[bits2,0], 2#11001001101010011}]),
- ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%% Req. Test1
-implied_test(MA) ->
- ?LOG("implied_test -> start",[]),
- p("Testing IMPLIED..."),
-
- snmpa:verbosity(MA,trace),
- snmpa:verbosity(MA,trace),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = "apa",
- Idx2 = "qq",
- ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
- ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
- {[testDescr, Idx1], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
- ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
- {[testDescr, Idx2], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr)",[]),
- gn([[testDescr]]),
- ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
- gn([[testDescr,Idx1]]),
- ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?destroy}]),
- ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?destroy}]),
- ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
-
- %% Try the same in other table
- Idx3 = [1, "apa"],
- Idx4 = [1, "qq"],
- ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
- ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
- {[testDescr2, Idx3], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
- ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
- {[testDescr2, Idx4], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr2)",[]),
- gn([[testDescr2]]),
- ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
- gn([[testDescr2,Idx3]]),
- ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?destroy}]),
- ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?destroy}]),
- ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
-
- snmpa:verbosity(MA,log),
-
- ?LOG("implied_test -> done",[]).
-
-
-
-%% Req. Test1
-sparse_table_test() ->
- p("Testing sparse table..."),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- s([{[sparseStatus, Idx1], i, ?createAndGo},
- {[sparseDescr, Idx1], s, "row 1"}]),
- ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
- {[sparseDescr, Idx1], "row 1"}]),
- s([{[sparseStatus, Idx2], i, ?createAndGo},
- {[sparseDescr, Idx2], s, "row 2"}]),
- ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
- {[sparseDescr, Idx2], "row 2"}]),
- ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
- [sparseStatus,Idx1], [sparseStatus,Idx2]]),
- gb(0,5,[[sparseIndex]])),
- ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
- {[sparseDescr,Idx2], "row 2"},
- {[sparseStatus,Idx1], ?active},
- {[sparseStatus,Idx2], ?active},
- {[sparseStr,0], "slut"}]),
- % Delete the rows
- s([{[sparseStatus, Idx1], i, ?destroy}]),
- ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
- s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
-
-
-%% Req. Test1
-cnt_64_test(MA) ->
- ?LOG("start cnt64 test (~p)",[MA]),
- snmpa:verbosity(MA,trace),
- ?LOG("start cnt64 test",[]),
- p("Testing Counter64, and at the same time, RowStatus is not last column"),
-
- ?DBG("get cnt64",[]),
- g([[cnt64,0]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(1, noSuchName, 1, any),
- expect(1, [{[cnt64,0],18446744073709551615}])),
- ?DBG("get-next cnt64",[]),
- gn([[cnt64]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
- expect(2, [{[cnt64,0],18446744073709551615}])),
- ?DBG("send cntTrap",[]),
- snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
- {cnt64, 10},
- {sysLocation, "here"}]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
- {[sysLocation,0], "here"}]),
- expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [1]},
- {[sysContact,0], "pelle"},
- {[cnt64,0], 10},
- {[sysLocation,0], "here"}])),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- ?DBG("create row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
- ?DBG("create row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
-
- ?DBG("get-next (cntIndex)",[]),
- gn([[cntIndex]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
- expect(3, [{[cntCnt,Idx1], 0}])),
- % Delete the rows
- ?DBG("delete row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
- ?DBG("delete row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
- catch snmpa:verbosity(MA,log),
- ?DBG("done",[]),
- ok.
-
-%% Req. Test1
-opaque_test() ->
- p("Testing Opaque datatype..."),
- g([[opaqueObj,0]]),
- ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
-
-%% Req. OLD-SNMPEA-MIB
-api_test(MaNode) ->
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
- oid_to_name, [OID]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp,
- int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
- List when list(List), length(List) == 8 -> ok;
- List when list(List), length(List) == 11 -> ok
- end.
-
-%% Req. Klas3
-api_test2() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]),
- g([[fname4,0]]),
- ?line expect(2, [{[fname4,0], 1}]).
-
-api_test3() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]).
-
-
-unreg_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[snmpInPkts, 0], any}]).
-
-load_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[fname,0], ""}]).
-
-%% Req. Klas1
-load_test_sa() ->
- gn([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line expect(1, [{[fname,0], any}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_get() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
- [sysName,0]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,0], "test"}]),
- g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
- ?line ?v1_2(expect(2, noSuchName, [1,4], any),
- expect(2, [{[1,3,7,1], noSuchObject},
- {Key1c4, 2},
- {[sysDescr,0], "Erlang SNMP agent"},
- {[1,3,7,2], noSuchObject},
- {Key1c3, 2},
- {[sysDescr,0], "Erlang SNMP agent"}])).
-
-%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
-do_mul_get_err() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(expect(1, noSuchName, 5, any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,2], noSuchInstance}])),
- g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname3,0], noSuchObject},
- {Key1c3, 2},
- {[sysName,1], noSuchInstance}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2}, {[fname,0], "test set"},
- {Key1c3, 2}, {[sysName,0], "test"}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next_err() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[1,3,6,999], endOfMibView},
- {[fname,0], "test set"},
- {[1,3,90], endOfMibView},
- {Key1c3, 2},
- {[sysName,0], "test"}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set() ->
- p("Adding one row in subagent table, and one in master table"),
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [sysLocation,0],
- [friendsEntry, [3, 3]]]),
- ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
- {[sysLocation,0], "new_value"},
- {[friendsEntry, [3, 3]], ?active}]),
- g([NewKeyc4]),
- ?line expect(3, [{NewKeyc4, 2}]),
- s([{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]),
- ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- p("Adding one row in subagent table, and one in master table"),
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {NewKeyc3, 2},
- {[sysUpTime,0], 45}, % sysUpTime (readOnly)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
- g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
- g([NewKeyc4]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB
-sa_mib() ->
- g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
- s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
-
-ma_trap1(MA) ->
- snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
- snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
-
-ma_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap2(MA) ->
- snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
- {ifAdminStatus, [1], 1},
- {ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
-
-sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
-
-ma_v2_trap1(MA) ->
- ?DBG("ma_v2_traps -> entry with MA = ~p => "
- "send standard trap: testTrapv22",[MA]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
- snmpa:send_trap(MA, testTrapv21, "standard trap"),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmp ++ [1]}]).
-
-ma_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
-
-%% Note: This test case takes a while... actually a couple of minutes.
-ma_v2_inform1(MA) ->
- ?DBG("ma_v2_inform -> entry with MA = ~p => "
- "send notification: testTrapv22",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag1, self()},
- "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag1, [_]} ->
- ok;
- {snmp_targets, tag1, Addrs1} ->
- ?line ?FAIL({bad_addrs, Addrs1})
- after
- 5000 ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag1, {got_response, _}} ->
- ok;
- {snmp_notification, tag1, {no_response, _}} ->
- ?line ?FAIL(no_response)
- after
- 20000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
-
- %%
- %% -- The rest is possibly erroneous...
- %%
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag2, self()},
- "standard inform", []),
- ?line expect(2, {inform, false},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag2, [_]} ->
- ok;
- {snmp_targets, tag2, Addrs2} ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
- ?line ?FAIL({bad_addrs, Addrs2})
- after
- 5000 ->
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag2, {got_response, _}} ->
- ?line ?FAIL(got_response);
- {snmp_notification, tag2, {no_response, _}} ->
- ok
- after
- 240000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag2) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end.
-
-
-ma_v1_2_v2_trap(MA) ->
- snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
- {[ifIndex, 1], 1},
- {[snmpTrapEnterprise, 0], [1,2,3]}]).
-
-
-ma_v1_2_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"},
- {[snmpTrapEnterprise, 0], ?system}]).
-
-
-sa_v1_2_v2_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-sa_v1_2_v2_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-sa_v1_2_v2_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_bad_value() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 5}, % badValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, badValue, 2, any),
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
- g([NewKeyc4]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_gen_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},{NewKeyc4, 2},
- {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line expect(1, genErr, 4, any),
-% The row might have been added; we don't know.
-% (as a matter of fact we do - it is added, because the agent
-% first sets its own vars, and then th SAs. Lets destroy it.
- s([{NewKeyc5, ?destroy}]),
- ?line expect(2, [{NewKeyc5, ?destroy}]).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_too_big() ->
- g([[sa, [4,0]]]),
- ?line expect(1, tooBig).
-
-%% Req. Klas1, system group, snmp group (v1/v2)
-next_across_sa() ->
- gn([[sysDescr],[klas1,5]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {[snmpInPkts, 0], any}]).
-
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
-%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
-%% Req. Klas3, Klas4
-undo_test() ->
- s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
- s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
-% unfortunatly we don't know if we'll get undoFailed or commitFailed.
-% it depends on which order the agent traverses the varbind list.
-% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
-% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line expect(6, genErr, 2, any).
-
-%% Req. Klas3, Klas4
-bad_return() ->
- g([[fStatus4,4],
- [fName4,4]]),
- ?line expect(4, genErr, 2, any),
- g([[fStatus4,5],
- [fName4,5]]),
- ?line expect(5, genErr, 1, any),
- g([[fStatus4,6],
- [fName4,6]]),
- ?line expect(6, genErr, 2, any),
- gn([[fStatus4,7],
- [fName4,7]]),
- ?line expect(7, genErr, 2, any),
- gn([[fStatus4,8],
- [fName4,8]]),
- ?line expect(8, genErr, 1, any),
- gn([[fStatus4,9],
- [fName4,9]]),
- ?line expect(9, genErr, 2, any).
-
-
-%%%-----------------------------------------------------------------
-%%% Test the implementation of standard mibs.
-%%% We should *at least* try to GET all variables, just to make
-%%% sure the instrumentation functions work.
-%%% Note that many of the functions in the standard mib is
-%%% already tested by the normal tests.
-%%%-----------------------------------------------------------------
-
-
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v1.
-%% o Test the counters and control objects in SNMP-STANDARD-MIB
-%%-----------------------------------------------------------------
-snmp_standard_mib(suite) -> [];
-snmp_standard_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?DBG("snmp_standard_mib -> std_mib_init", []),
- try_test(std_mib_init),
-
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- InBadVsns = try_test(std_mib_a),
- put(vsn, v2),
- ?DBG("snmp_standard_mib -> std_mib_read", []),
- try_test(std_mib_read),
- put(vsn, v1),
-
- ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
- Bad = try_test(std_mib_b, [InBadVsns]),
- ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
- try_test(std_mib_read, [], [{community, "bad community"}]),
- ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
- try_test(std_mib_write, [], [{community, "public"}]),
- ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
- try_test(std_mib_asn_err),
- ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
- try_test(std_mib_c, [Bad]),
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- try_test(standard_mib_a),
-
- ?DBG("snmp_standard_mib -> std_mib_finish", []),
- try_test(std_mib_finish),
- ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
- try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
- ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
- %% There are some more counters we could test here, but it's not that
- %% important, since they are removed from SNMPv2-MIB.
- ok.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_init() ->
- %% disable authentication failure traps. (otherwise w'd get many of
- %% them - this is also a test to see that it works).
- s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_finish() ->
- %% enable again
- s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_test_finish() ->
- %% force a authenticationFailure
- std_mib_write(),
- %% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_read() ->
- ?DBG("std_mib_read -> entry", []),
- g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
- ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
-
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_write() ->
- ?DBG("std_mib_write -> entry", []),
- s([{[sysLocation, 0], "new_value"}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_asn_err() ->
- snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v2 and v3.
-%% o Test the counters and control objects in SNMPv2-MIB
-%%-----------------------------------------------------------------
-snmpv2_mib_2(suite) -> [];
-snmpv2_mib_2(Config) when list(Config) ->
- ?LOG("snmpv2_mib_2 -> start",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?DBG("snmpv2_mib_2 -> standard mib init",[]),
- try_test(std_mib_init),
-
- ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
- InBadVsns = try_test(std_mib_a),
-
- ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
- put(vsn, v1),
- try_test(std_mib_read),
-
- ?DBG("snmpv2_mib_2 -> bad version read",[]),
- put(vsn, v2),
- Bad = try_test(std_mib_b, [InBadVsns]),
-
- ?DBG("snmpv2_mib_2 -> read with bad community",[]),
- try_test(std_mib_read, [], [{community, "bad community"}]),
-
- ?DBG("snmpv2_mib_2 -> write with public community",[]),
- try_test(std_mib_write, [], [{community, "public"}]),
-
- ?DBG("snmpv2_mib_2 -> asn err",[]),
- try_test(std_mib_asn_err),
-
- ?DBG("snmpv2_mib_2 -> check counters",[]),
- try_test(std_mib_c, [Bad]),
-
- ?DBG("snmpv2_mib_2 -> get som counters",[]),
- try_test(snmpv2_mib_a),
-
- ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
- try_test(std_mib_finish),
-
- ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
- "then disable auth traps",[]),
- try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
-
- ?LOG("snmpv2_mib_2 -> done",[]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_3(suite) -> [];
-snmpv2_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- InBadVsns = try_test(std_mib_a),
- put(vsn, v1),
- try_test(std_mib_read),
- put(vsn, v3),
- _Bad = try_test(std_mib_b, [InBadVsns]),
- try_test(snmpv2_mib_a),
-
- try_test(std_mib_finish).
-
--define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_test_finish() ->
- %% force a authenticationFailure
- ?DBG("ma_v2_inform -> write to std mib",[]),
- std_mib_write(),
-
- %% check that we got a trap
- ?DBG("ma_v2_inform -> await trap",[]),
- ?line expect(2, v2trap, [{[sysUpTime,0], any},
- {[snmpTrapOID,0], ?authenticationFailure}]),
-
- %% and the the inform
- ?DBG("ma_v2_inform -> await inform",[]),
- ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
- {[snmpTrapOID,0],?authenticationFailure}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_a() ->
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
-
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
- InBadVsns.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_b(InBadVsns) ->
- ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
- ?line InBadVsns2 = InBadVsns + 1,
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
- ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
- get_req(4, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
- get_req(1, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_a() ->
- ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
- s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
- {[sysLocation, 0], "val2"}]),
- s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line expect(4, inconsistentValue, 2,
- [{[sysLocation, 0], "val3"},
- {[snmpSetSerialNo,0], SetSerial}]),
- ?line ["val2"] = get_req(5, [[sysLocation,0]]).
-
-
-%%-----------------------------------------------------------------
-%% o Bad community uses/name is tested already
-%% in SNMPv2-MIB and STANDARD-MIB.
-%% o Test add/deletion of rows.
-%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
-snmp_community_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- try_test(snmp_community_mib),
- ?line unload_master("SNMP-COMMUNITY-MIB").
-
-snmp_community_mib_2(X) -> snmp_community_mib(X).
-
-%% Req. SNMP-COMMUNITY-MIB
-snmp_community_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o Test engine boots / time
-%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
-snmp_framework_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- try_test(snmp_framework_mib),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
-
-snmp_framework_mib_2(X) -> snmp_framework_mib(X).
-
-snmp_framework_mib_3(suite) -> [];
-snmp_framework_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(snmp_framework_mib).
-
-
-%% Req. SNMP-FRAMEWORK-MIB
-snmp_framework_mib() ->
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
- sleep(5000),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
- if
- EngineTime+7 < EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- EngineTime+4 > EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- true -> ok
- end,
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
- [Boots] when integer(Boots) -> ok;
- Else -> ?FAIL(Else)
- end,
- ok.
-
-%%-----------------------------------------------------------------
-%% o Test the counters
-%%-----------------------------------------------------------------
-snmp_mpd_mib_3(suite) -> [];
-snmp_mpd_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- UnknownPDUHs = try_test(snmp_mpd_mib_a),
- try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
- try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
-
-
-%% Req. SNMP-MPD-MIB
-snmp_mpd_mib_a() ->
- ?line [UnknownSecs, InvalidMsgs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0]]),
- Pdu = #pdu{type = 'get-request',
- request_id = 23,
- error_status = noError,
- error_index = 0,
- varbinds = []},
- SPdu = #scopedPdu{contextEngineID = "agentEngine",
- contextName = "",
- data = Pdu},
- ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
- V3Hdr1 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [7],
- msgSecurityModel = 23, % bad sec model
- msgSecurityParameters = []},
- V3Hdr2 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [6], % bad flag combination
- msgSecurityModel = 3,
- msgSecurityParameters = []},
- Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
- data = SPDUBytes},
- Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
- data = SPDUBytes},
- ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
- ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
- snmp_test_mgr:send_bytes(MsgBytes1),
- snmp_test_mgr:send_bytes(MsgBytes2),
-
- ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0],
- [snmpUnknownPDUHandlers, 0]]),
- ?line UnknownSecs2 = UnknownSecs + 1,
- ?line InvalidMsgs2 = InvalidMsgs + 1,
- UnknownPDUHs.
-
--define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
-snmp_mpd_mib_b() ->
- g([[sysUpTime,0]]),
- ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
-
-
-snmp_mpd_mib_c(UnknownPDUHs) ->
- ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownPDUHs2 = UnknownPDUHs + 1.
-
-
-snmp_target_mib(suite) -> [];
-snmp_target_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
- try_test(snmp_target_mib),
- ?line unload_master("SNMP-TARGET-MIB").
-
-snmp_target_mib_2(X) -> snmp_target_mib(X).
-
-snmp_target_mib_3(X) -> snmp_target_mib(X).
-
-snmp_target_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-snmp_notification_mib(suite) -> [];
-snmp_notification_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- try_test(snmp_notification_mib),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
-
-snmp_notification_mib_2(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib_3(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o add/delete views and try them
-%% o try boundaries
-%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
-snmp_view_based_acm_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
- snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib() ->
- snmpa:verbosity(net_if,trace),
- snmpa:verbosity(master_agent,trace),
- ?LOG("start snmp_view_based_acm_mib test",[]),
- %% The user "no-rights" is present in USM, and is mapped to security
- %% name 'no-rights", which is not present in VACM.
- %% So, we'll add rights for it, try them and delete them.
- %% We'll give "no-rights" write access to tDescr.0 and read access
- %% to tDescr2.0
- %% These are the options we'll use to the mgr
- Opts = [{user, "no-rights"}, {community, "no-rights"}],
- %% Find the valid secmodel, and one invalid secmodel.
- {SecMod, InvSecMod} =
- case get(vsn) of
- v1 -> {?SEC_V1, ?SEC_V2C};
- v2 -> {?SEC_V2C, ?SEC_USM};
- v3 -> {?SEC_USM, ?SEC_V1}
- end,
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Now, add a mapping from "no-rights" -> "no-rights-group"
- GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
- GRow1 =
- [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
- {GRow1Status, ?createAndGo}],
- ?DBG("set '~p'",[GRow1]),
- ?line try_test(do_set, [GRow1]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create a mapping for another sec model, and make sure it dosn't
- %% give us access
- GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
- GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
- {GRow2Status, ?createAndGo}],
-
- ?DBG("set '~p'",[GRow2]),
- ?line try_test(do_set, [GRow2]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [GRow2Status]),
-
- RVName = "rv_name",
- WVName = "wv_name",
-
- %% Access row
- ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
- ARow1Status = [vacmAccessStatus, ARow1Idx],
- ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
- {[vacmAccessReadViewName, ARow1Idx], RVName},
- {[vacmAccessWriteViewName, ARow1Idx], WVName},
- {ARow1Status, ?createAndGo}],
-
- %% This access row would give acces, if InvSecMod was valid.
- ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
- ARow2Status = [vacmAccessStatus, ARow2Idx],
- ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
- {[vacmAccessReadViewName, ARow2Idx], "internet"},
- {[vacmAccessWriteViewName, ARow2Idx], "internet"},
- {ARow2Status, ?createAndGo}],
-
- ?line try_test(do_set, [ARow2]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [ARow2Status]),
-
-
- %% Add valid row
- ?line try_test(do_set, [ARow1]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create the view family
- VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
- VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
- VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
- VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
- VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
- VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
- VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
- VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
-
- ?line try_test(add_row, [VRow1Status]),
- ?line try_test(add_row, [VRow2Status]),
- ?line try_test(add_row, [VRow3Status]),
-
- %% We're supposed to have access now...
- ?line try_test(use_rights, [], Opts),
-
- %% Change Row3 to Row4
- ?line try_test(del_row, [VRow3Status]),
- ?line try_test(add_row, [VRow4Status]),
-
- %% We should still have access...
- ?line try_test(use_rights, [], Opts),
-
- %% Delete rows
- ?line try_test(del_row, [GRow1Status]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete rest of rows
- ?line try_test(del_row, [ARow1Status]),
- ?line try_test(del_row, [VRow1Status]),
- ?line try_test(del_row, [VRow2Status]),
- ?line try_test(del_row, [VRow4Status]),
-
- ?line try_test(use_no_rights, [], Opts),
- snmpa:verbosity(master_agent,log).
-
-do_set(Row) ->
- s(Row),
- expect(1, Row).
-
-add_row(RowStatus) ->
- s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
-
-del_row(RowStatus) ->
- s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
-
-
-
-use_no_rights() ->
- g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
- g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
- gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
- s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
-
-
-use_rights() ->
- g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
- g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
- s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
- g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
-
-mk_ln(X) ->
- [length(X) | X].
-
-%%-----------------------------------------------------------------
-%% o add/delete users and try them
-%% o test all secLevels
-%% o test all combinations of protocols
-%% o try bad ops; check counters
-%%-----------------------------------------------------------------
-snmp_user_based_sm_mib_3(suite) -> [];
-snmp_user_based_sm_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
-
- %% The newUser used here already has VACM access.
-
- %% Add a new user in the simplest way; just createAndGo
- try_test(v3_sync, [[{usm_add_user1, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new user
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
- DesKey1 = lists:sublist(ShaKey1, 16),
-
- %% Change the new user's keys - 1
- try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- MgrDir = ?config(mgr_dir, Config),
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
- DesKey2 = lists:sublist(ShaKey2, 16),
-
- %% Change the new user's keys - 2
- ?line try_test(v3_sync,
- [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- reset_usm_mgr(MgrDir),
- ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
- ?line load_master("Test2"),
- ?line try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Change the new user's keys - 3
- ?line try_test(v3_sync,
- [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new keys
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Try some read requests
- ?line try_test(v3_sync, [[{usm_read, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Delete the new user
- ?line try_test(v3_sync, [[{usm_del_user, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try some bad requests
- ?line try_test(v3_sync, [[{usm_bad, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("SNMP-USER-BASED-SM-MIB").
-
--define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
-
-usm_add_user1() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
-usm_use_user() ->
- v2_proc().
-
-
-%% Change own public keys
-usm_key_change1(ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_shaxxxxxxxxxx",
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_desxxxxxx",
- DesKey),
- Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change own private keys
-usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change other's public keys
-usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
- s(Vbs1),
- ?line expect(1, noAccess, 1, any),
- Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs2),
- ?line expect(2, noAccess, 1, any),
-
-
- Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs3),
- ?line expect(1, Vbs3).
-
-usm_read() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ?line g([[usmUserSecurityName, NewRowIndex],
- [usmUserCloneFrom, NewRowIndex],
- [usmUserAuthKeyChange, NewRowIndex],
- [usmUserOwnAuthKeyChange, NewRowIndex],
- [usmUserPrivKeyChange, NewRowIndex],
- [usmUserOwnPrivKeyChange, NewRowIndex]]),
- ?line expect(1,
- [{[usmUserSecurityName, NewRowIndex], "newUser"},
- {[usmUserCloneFrom, NewRowIndex], [0,0]},
- {[usmUserAuthKeyChange, NewRowIndex], ""},
- {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
- {[usmUserPrivKeyChange, NewRowIndex], ""},
- {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
- ok.
-
-
-
-usm_del_user() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
--define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
-
--define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
-
--define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
-
--define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
-
--define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
-
--define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
-
-usm_bad() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, inconsistentName, 1, any),
-
- RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs2),
- ?line expect(2, wrongValue, 1, any),
-
- RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs3),
- ?line expect(3, Vbs3),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
- ?line expect(4, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
- ?line expect(5, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
- ?line expect(6, wrongValue, 1, any),
- ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
- ?line expect(7, wrongValue, 1, any),
-
- Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs4),
- ?line expect(1, Vbs4),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Loop through entire MIB, to make sure that all instrum. funcs
-%% works.
-%% Load all std mibs that are not loaded by default.
-%%-----------------------------------------------------------------
-loop_mib(suite) -> [];
-loop_mib(Config) when list(Config) ->
- ?LOG("loop_mib -> initiate case",[]),
- %% snmpa:verbosity(master_agent,debug),
- %% snmpa:verbosity(mib_server,info),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?DBG("loop_mib -> try",[]),
- try_test(loop_mib_1),
- ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- %% snmpa:verbosity(master_agent,log),
- %% snmpa:verbosity(mib_server,silence),
- ?LOG("loop_mib -> done",[]).
-
-
-loop_mib_2(suite) -> [];
-loop_mib_2(Config) when list(Config) ->
- ?LOG("loop_mib_2 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_2 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_2 -> load mibs",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_2 -> unload mibs",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?LOG("loop_mib_2 -> done",[]).
-
-
-loop_mib_3(suite) -> [];
-loop_mib_3(Config) when list(Config) ->
- ?LOG("loop_mib_3 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_3 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_3 -> load mibs",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_3 -> unload mibs",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?LOG("loop_mib_3 -> done",[]).
-
-
-%% Req. As many mibs all possible
-loop_mib_1() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_1([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_1(Oid, N) ->
- ?DBG("loop_it_1 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_1 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_1 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_1(NOid, N+1);
- #pdu{type='get-response', error_status=noSuchName, error_index=1,
- varbinds=[_]} ->
- ?DBG("loop_it_1 -> done",[]),
- N;
-
- #pdu{type = Type, error_status = Err, error_index = Idx,
- varbinds = Vbs} ->
- exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
- end.
-
-%% Req. As many mibs all possible
-loop_mib_2() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_2([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_2(Oid, N) ->
- ?DBG("loop_it_2 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p",[NOid]),
- N;
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_2 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_2(NOid, N+1)
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% Testing of reported bugs and other tickets.
-%%%-----------------------------------------------------------------
-
-
-
-
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1128
-%% Slogan: Bug in handling of createAndWait set-requests.
-%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
-otp_1128(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1128),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1128_2(X) -> otp_1128(X).
-
-otp_1128_3(X) -> otp_1128(X).
-
-otp_1128() ->
- io:format("Testing bug reported in ticket OTP-1128...~n"),
-
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
-
- s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(29, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(31, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(32, [{NewKeyc5, ?destroy}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1129, OTP-1169
-%% Slogan: snmpa:int_to_enum crashes on bad oids
-%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
-otp_1129(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- try_test(otp_1129_i, [node()]),
- ?line unload_master("Klas3").
-
-otp_1129_2(X) -> otp_1129(X).
-
-otp_1129_3(X) -> otp_1129(X).
-
-otp_1129_i(MaNode) ->
- io:format("Testing bug reported in ticket OTP-1129...~n"),
- false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
- false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1131
-%% Slogan: Agent crashes / erlang node halts if RowIndex in a
-%% setrequest is of bad type, e.g. an INDEX {INTEGER},
-%% and RowIdenx [3,2].
-%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
-otp_1131(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas1"),
- try_test(otp_1131),
- ?line unload_master("Klas1").
-
-otp_1131_2(X) -> otp_1131(X).
-
-otp_1131_3(X) -> otp_1131(X).
-
-otp_1131() ->
- io:format("Testing bug reported in ticket OTP-1131...~n"),
- s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
- {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1162
-%% Slogan: snmp_agent can't handle wrongValue from instrum.func
-%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
-otp_1162(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
- try_test(otp_1162),
- stop_subagent(SA).
-
-otp_1162_2(X) -> otp_1162(X).
-
-otp_1162_3(X) -> otp_1162(X).
-
-otp_1162() ->
- s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1222
-%% Slogan: snmp agent crash if faulty index is returned from instrum
-%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
-otp_1222(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
- try_test(otp_1222),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4").
-
-otp_1222_2(X) -> otp_1222(X).
-
-otp_1222_3(X) -> otp_1222(X).
-
-otp_1222() ->
- io:format("Testing bug reported in ticket OTP-1222...~n"),
- s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line expect(1, genErr, 0, any),
- s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line expect(2, genErr, 0, any).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1298
-%% Slogan: Negative INTEGER values are treated as positive.
-%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
-otp_1298(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1298),
- ?line unload_master("Klas2").
-
-otp_1298_2(X) -> otp_1298(X).
-
-otp_1298_3(X) -> otp_1298(X).
-
-otp_1298() ->
- io:format("Testing bug reported in ticket OTP-1298...~n"),
- s([{[fint,0], -1}]),
- ?line expect(1298, [{[fint,0], -1}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1331
-%% Slogan: snmp_generic should return noError when deleting non-ex row
-%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
-otp_1331(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1331),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1331_2(X) -> otp_1331(X).
-
-otp_1331_3(X) -> otp_1331(X).
-
-otp_1331() ->
- NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
- s([{NewKeyc5, ?destroy}]),
- ?line expect(1, [{NewKeyc5, ?destroy}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1338
-%% Slogan: snmp bug in initialisation of default values for mnesia tabs
-%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
-otp_1338(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1338),
- ?line unload_master("Klas2").
-
-otp_1338_2(X) -> otp_1338(X).
-
-otp_1338_3(X) -> otp_1338(X).
-
-otp_1338() ->
- s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
- g([[kName2, 7]]),
- ?line expect(2, [{[kName2, 7], "JJJ"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1342
-%% Slogan: default impl of snmp table can't handle bad index access,
-%% Set when INDEX is read-write gets into an infinite loop!
-%%-----------------------------------------------------------------
-otp_1342(suite) -> [];
-otp_1342(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas4"),
- try_test(otp_1342),
- ?line unload_master("Klas4").
-
-otp_1342_2(X) -> otp_1342(X).
-
-otp_1342_3(X) -> otp_1342(X).
-
-otp_1342() ->
- s([{[fIndex5, 1], i, 1},
- {[fName5, 1], i, 3},
- {[fStatus5, 1], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1366
-%% Slogan: snmp traps not sent to all managers
-%% Note: NYI! We need a way to tell the test server that we need
-%% mgrs on two different machines.
-%%-----------------------------------------------------------------
-otp_1366(suite) -> [];
-otp_1366(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1366),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1366_2(X) -> otp_1366(X).
-
-otp_1366_3(X) -> otp_1366(X).
-
-otp_1366() ->
- ?INF("NOT YET IMPLEMENTED", []),
- 'NYI'.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2776
-%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
-%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
-otp_2776(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_2776).
-
-otp_2776_2(X) -> otp_2776(X).
-
-otp_2776_3(X) -> otp_2776(X).
-
-otp_2776() ->
- io:format("Testing bug reported in ticket OTP-2776...~n"),
-
- Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
- Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
- Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
- Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
- Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
- Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
- Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
- Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
- Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
- Dt10_invalid = [],
- Dt11_invalid = [kalle,hobbe],
- L = [{ 1, true, Dt01_valid},
- { 2, true, Dt02_valid},
- { 3, true, Dt03_valid},
- { 4, false, Dt04_invalid},
- { 5, true, Dt05_valid},
- { 6, true, Dt06_valid},
- { 7, false, Dt07_invalid},
- { 8, true, Dt08_valid},
- { 9, false, Dt09_invalid},
- {10, false, Dt10_invalid},
- {11, false, Dt11_invalid}],
-
- ?line ok = validate_dat(L).
-
-
-validate_dat(L) -> validate_dat(L,[]).
-
-validate_dat([],V) ->
- Fun = fun({_,X}) -> case X of
- ok -> false;
- _ -> true
- end
- end,
- validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
-validate_dat([{Id,E,Dat}|T],V) ->
- validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
-
-validate_dat1([]) -> ok;
-validate_dat1(L) -> {error,L}.
-
-validate_dat2(Id, E, Dat) ->
- Res = case {E,snmp:validate_date_and_time(Dat)} of
- {E,E} -> ok;
- {E,A} -> {E,A}
- end,
- {Id, Res}.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2979
-%% Slogan: get-next on more than 1 column in an empty table
-%% returns bad response.
-%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
-otp_2979(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Test1"),
- ?line init_old(),
- try_test(otp_2979),
- ?line unload_master("Test1").
-
-otp_2979_2(X) -> otp_2979(X).
-
-otp_2979_3(X) -> otp_2979(X).
-
-otp_2979() ->
- gn([[sparseDescr], [sparseStatus]]),
- ?line expect(1, [{[sparseStr,0], "slut"},
- {[sparseStr,0], "slut"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
-%% endOfTable - should return value.
-%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
-otp_3187(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- otp_3187(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-otp_3187_2(X) -> otp_3187(X).
-
-otp_3187_3(X) -> otp_3187(X).
-
-otp_3187() ->
- ?line Elements =
- snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
- lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
- ?FAIL(endOfTable);
- true -> ok
- end
- end, Elements).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3542
-%% Slogan:
-%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
-otp_3542(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_3542).
-
-otp_3542() ->
- io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
- io:format("SNMP v3 discovery result: ~p~n",[Res]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3725
-%% Slogan: Slow response time on snmpa:int_to_enum
-%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
-otp_3725(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-otp_3725_test(MaNode) ->
- io:format("Testing feature requested in ticket OTP-3725...~n"),
- ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
- ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
- ?DBG("otp_3725_test -> Db = ~p",[Db]),
-
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [Db, intAgentIpAddress]),
- ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
- [Db,OID]),
- ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-4394
-%% Slogan: Target mib tag list check invalid
-%%-----------------------------------------------------------------
-
-
-
-init_otp_4394(Config) when list(Config) ->
- ?DBG("init_otp_4394 -> entry with"
- "~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
- MasterAgentVerbosity = {master_agent_verbosity, trace},
- NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
-
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
- ?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
- Vsn = [v1],
- Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
- ?TRAP_UDP, Ip, 4000,
- "OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
- false ->
- ?line ok
- end,
- C1 = {"a", "all-rights", "initial", "", "pc"},
- C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
- Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
- "pc1",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [],
- 2048},
- Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
- "pc2",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
- ok.
-
-
-
-finish_otp_4394(Config) when list(Config) ->
- ?DBG("finish_otp_4394 -> entry", []),
- C1 = stop_agent(Config),
- delete_files(C1),
- erase(mgr_node),
- lists:keydelete(vsn, 1, C1).
-
-otp_4394_test(suite) -> [];
-otp_4394_test(Config) ->
- ?DBG("otp_4394_test -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_4394_test1),
- ?DBG("otp_4394_test -> done", []),
- ok.
-
-otp_4394_test1() ->
- ?DBG("otp_4394_test1 -> entry", []),
- gn([[1,1]]),
- Res =
- case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
- %% {error, 1, {"?",[]}, {"~w",[timeout]}}
- {error, 1, _, {_, [timeout]}} ->
- ?DBG("otp_4394_test1 -> expected result: timeout", []),
- ok;
- Else ->
- Else
- end,
- ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
- Res.
-
-
-%%%--------------------------------------------------
-%%% Used to test the standard mib with our
-%%% configuration.
-%%%--------------------------------------------------
-run(F, A, Opts) ->
- M = get(mib_dir),
- Dir = get(mgr_dir),
- User = snmp_misc:get_option(user, Opts, "all-rights"),
- SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
- EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
- CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
- Community = snmp_misc:get_option(community, Opts, "all-rights"),
- ?DBG("run -> start crypto app",[]),
- Crypto = case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- ?CRYPTO_START()
- end,
- ?DBG("run -> Crypto: ~p",[Crypto]),
- catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- ?DBG("run -> config:~n"
- "\tM: ~p~n"
- "\tDir: ~p~n"
- "\tUser: ~p~n"
- "\tSecLevel: ~p~n"
- "\tEngineID: ~p~n"
- "\tCtxEngineID: ~p~n"
- "\tCommunity: ~p~n"
- "\tStdM: ~p",
- [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
- case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
- {packet_server_debug,true},
- {debug,true},
- {agent, get(master_host)},
- {agent_udp, 4000},
- {trap_udp, 5000},
- {recbuf,65535},
- quiet,
- get(vsn),
- {community, Community},
- {user, User},
- {sec_level, SecLevel},
- {engine_id, EngineID},
- {context_engine_id, CtxEngineID},
- {dir, Dir},
- {mibs, mibs(StdM, M)}]) of
- {ok, _Pid} ->
- Res = apply(?MODULE, F, A),
- catch snmp_test_mgr:stop(),
- Res;
- Err ->
- io:format("Error starting manager: ~p\n", [Err]),
- catch snmp_test_mgr:stop(),
- ?line exit({mgr_start, Err})
- end.
-
-
-mibs(StdMibDir,MibDir) ->
- [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
- join(MibDir, "OLD-SNMPEA-MIB.bin"),
- join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
- join(StdMibDir, "SNMP-MPD-MIB"),
- join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
- join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
- join(StdMibDir, "SNMP-TARGET-MIB"),
- join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
- join(MibDir, "Klas1.bin"),
- join(MibDir, "Klas2.bin"),
- join(MibDir, "Klas3.bin"),
- join(MibDir, "Klas4.bin"),
- join(MibDir, "SA-MIB.bin"),
- join(MibDir, "TestTrap.bin"),
- join(MibDir, "Test1.bin"),
- join(MibDir, "Test2.bin"),
- join(MibDir, "TestTrapv2.bin")].
-
-join(D,F) ->
- filename:join(D,F).
-
-%% string used in index
-is(S) -> [length(S) | S].
-
-try_test(Func) ->
- call(get(mgr_node), ?MODULE, run, [Func, [], []]).
-
-try_test(Func, A) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, []]).
-
-try_test(Func, A, Opts) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
-
-call(N,M,F,A) ->
- ?DBG("call -> entry with~n"
- " N: ~p~n"
- " M: ~p~n"
- " F: ~p~n"
- " A: ~p~n"
- " when~n"
- " get(): ~p",
- [N,M,F,A,get()]),
- spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
- receive
- {done, {'EXIT', Rn}, Loc} ->
- ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
- put(test_server_loc, Loc),
- exit(Rn);
- {done, Ret, Zed} ->
- ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
- Ret
- end.
-
-wait(From, Env, M, F, A) ->
- ?DBG("wait -> entry with ~n"
- "\tFrom: ~p~n"
- "\tEnv: ~p",[From,Env]),
- lists:foreach(fun({K,V}) -> put(K,V) end, Env),
- Rn = (catch apply(M, F, A)),
- ?DBG("wait -> Rn: ~n~p", [Rn]),
- From ! {done, Rn, get(test_server_loc)},
- exit(Rn).
-
-expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
-expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
-expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
-expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
-
-get_req(Id, Vars) ->
- ?DBG("get_req -> entry with~n"
- "\tId: ~p~n"
- "\tVars: ~p",[Id,Vars]),
- g(Vars),
- ?DBG("get_req -> await response",[]),
- {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
- ?DBG("get_req -> response: ~p",[Val]),
- Val.
-
-get_next_req(Vars) ->
- ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
- gn(Vars),
- ?DBG("get_next_req -> await response",[]),
- Response = snmp_test_mgr:receive_response(),
- ?DBG("get_next_req -> response: ~p",[Response]),
- Response.
-
-
-
-start_node(Name) ->
- ?LOG("start_node -> entry with Name: ~p",[Name]),
- M = list_to_atom(?HOSTNAME(node())),
- ?DBG("start_node -> M: ~p",[M]),
- Pa = filename:dirname(code:which(?MODULE)),
- ?DBG("start_node -> Pa: ~p",[Pa]),
-
- Args = case init:get_argument('CC_TEST') of
- {ok, [[]]} ->
- " -pa /clearcase/otp/libraries/snmp/ebin ";
- {ok, [[Path]]} ->
- " -pa " ++ Path;
- error ->
- ""
- end,
- %% Do not use start_link!!! (the proc that calls this one is tmp)
- ?DBG("start_node -> Args: ~p~n",[Args]),
- A = Args ++ " -pa " ++ Pa,
- case (catch ?START_NODE(Name, A)) of
- {ok, Node} ->
- %% Tell the test_server to not clean up things it never started.
- ?DBG("start_node -> Node: ~p",[Node]),
- {ok, Node};
- Else ->
- ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
- ?line ?FAIL(Else)
- end.
-
-
-stop_node(Node) ->
- ?LOG("stop_node -> Node: ~p",[Node]),
- rpc:cast(Node, erlang, halt, []).
-
-p(X) ->
- io:format(user, X++"\n", []).
-
-sleep(X) ->
- receive
- after
- X -> ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Configuration
-%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
- "test"),
- ?line case update_usm(Vsns, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsns, MgrDir);
- false ->
- ?line ok
- end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
- ok.
-
-delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
- lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
-
-update_usm(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-update_usm_mgr(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(filename:join(Dir,"usm.conf"),
- filename:join(Dir,"usm.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- file:close(Fid).
-
-reset_usm_mgr(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"usm.old"),
- filename:join(Dir,"usm.conf")).
-
-
-update_community([v3], _Dir) -> ok;
-update_community(_, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
- []),
- file:close(Fid).
-
-
--define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
-update_vacm(_Vsn, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
- ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
- "~w, excluded, null}.\n", [?tDescr_instance]),
- file:close(Fid).
-
-
-vacm_ver(v1) -> v1;
-vacm_ver(v2) -> v2c;
-vacm_ver(v3) -> usm.
-
-
-write_community_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
- ok = write_community_conf1(Fid, Confs),
- file:close(Fid).
-
-write_community_conf1(_, []) ->
- ok;
-write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
- [ComIdx, ComName, SecName, CtxName, TransTag]),
- write_community_conf1(Fid, Confs).
-
-
-write_target_addr_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- ok = write_target_addr_conf1(Fid, Confs),
- file:close(Fid).
-
-
-write_target_addr_conf1(_, []) ->
- ok;
-write_target_addr_conf1(Fid,
- [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
- [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz]),
- write_target_addr_conf1(Fid, Confs).
-
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- lists:foreach(fun(Vsn) ->
- ok = io:format(Fid,
- "{\"~s\", ~w, ~w, 1500, 3, "
- "\"std_trap\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP, mk_param(Vsn)]),
- case Vsn of
- v1 -> ok;
- v2 ->
- ok = io:format(Fid,
- "{\"~s.2\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)]);
- v3 ->
- ok = io:format(Fid,
- "{\"~s.3\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\", "
- "\"mgrEngine\", [], 1024}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)])
- end
- end,
- Vsns),
- file:close(Fid).
-
-mk_param(v1) -> "target_v1";
-mk_param(v2) -> "target_v2";
-mk_param(v3) -> "target_v3".
-
-mk_ip([A,B,C,D], Vsn) ->
- io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
-
-
-rewrite_target_addr_conf(Dir,NewPort) ->
- TAFile = filename:join(Dir, "target_addr.conf"),
- ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
- case file:read_file_info(TAFile) of
- {ok, _} -> ok;
- {error, R} -> ?ERR("failure reading file info of "
- "target address config file: ~p",[R]),
- ok
- end,
-
- ?line [TrapAddr|Addrs] =
- snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
-
- ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
-
- NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
-
- ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
-
- ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
- filename:join(Dir,"target_addr.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
-
- ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
-
- file:close(Fid).
-
-rewrite_target_addr_conf1(O) ->
- {ok,O}.
-
-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) ->
- ?LOG("rewrite_target_addr_conf2 -> entry with "
- "~n O: ~p",[O]),
- O.
-
-
-rewrite_target_addr_conf3(_,[]) -> ok;
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
- ParamName,EngineId}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % ParamsName
- "\"~s\"}.", % EngineId
- [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
- rewrite_target_addr_conf3(Fid,T);
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
- ParamName,EngineId,TMask,MMS}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % TagList
- "\"~s\", " % ParamsName
- "\"~s\"," % EngineId
- "~p, " % TMask
- "~p}.", % MMS
- [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
- EngineId,TMask,MMS]),
- rewrite_target_addr_conf3(Fid,T).
-
-reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
-
-write_target_params_conf(Dir, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- lists:foreach(fun(Vsn) ->
- MP = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> v3
- end,
- SM = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> usm
- end,
- ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
- "\"all-rights\", noAuthNoPriv}.~n",
- [Vsn, MP, SM])
- end,
- Vsns),
- file:close(Fid).
-
-rewrite_target_params_conf(Dir, SecName, SecLevel) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
- filename:join(Dir,"target_params.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
- [SecName, SecLevel]),
- file:close(Fid).
-
-reset_target_params_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.old"),
- filename:join(Dir,"target_params.conf")).
-
-write_notify_conf(Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
- ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
- ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
- file:close(Fid).
-
-ver_to_trap_str([v1]) -> "v1";
-ver_to_trap_str([v2]) -> "v2";
-% default is to use the latest snmp version
-ver_to_trap_str([v1,v2]) -> "v2".
-
-
-
-write_view_conf(Dir) ->
- {ok, Fid} = file:open(a(Dir,"view.conf"),write),
- ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
- ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
- file:close(Fid).
-
-a(A,B) -> lists:append(A,B).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-copy_file(From, To) ->
- {ok, Bin} = file:read_file(From),
- ok = file:write_file(To, Bin).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-display_memory_usage() ->
- Info = snmpa:info(snmp_master_agent),
- TreeSize = lists_key1search(tree_size_bytes, Info),
- ProcMem = lists_key1search(process_memory, Info),
- MibDbSize = lists_key1search([db_memory,mib], Info),
- NodeDbSize = lists_key1search([db_memory,node], Info),
- TreeDbSize = lists_key1search([db_memory,tree], Info),
- ?INF("Memory usage: "
- "~n Tree size: ~p"
- "~n Process memory size: ~p"
- "~n Mib db size: ~p"
- "~n Node db size: ~p"
- "~n Tree db size: ~p",
- [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
-
-lists_key1search([], Res) ->
- Res;
-lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- lists_key1search(Keys, Val);
- false ->
- undefined
- end;
-lists_key1search(Key, List) when atom(Key) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- Val;
- false ->
- undefined
- end.
-
-
-regs() ->
- lists:sort(registered()).
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 468280db02..e1d7f33b3f 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,8 @@ all() ->
Conf1 ++ Conf2.
groups() ->
- [{all_tcs, [], cases()},
+ [
+ {all_tcs, [], cases()},
{mib_storage, [],
[
{group, mib_storage_ets},
@@ -221,54 +222,84 @@ groups() ->
{group, otp_7157}
]
},
- {tickets2, [], [otp8395]},
+ {tickets2, [], [otp8395, otp9884]},
{otp_4394, [], [otp_4394_test]},
- {otp_7157, [], [otp_7157_test]
- }
+ {otp_7157, [], [otp_7157_test]}
].
-init_per_group(all_tcs, Config) ->
- init_all(Config);
-init_per_group(otp_7157, Config) ->
- init_otp_7157(Config);
-init_per_group(otp_4394, Config) ->
- init_otp_4394(Config);
-init_per_group(v2_inform, Config) ->
- init_v2_inform(Config);
-init_per_group(multiple_reqs_2, Config) ->
- init_mul(Config);
-init_per_group(multiple_reqs, Config) ->
- init_mul(Config);
-init_per_group(test_multi_threaded, Config) ->
- init_mt(Config);
-init_per_group(test_v3, Config) ->
- init_v3(Config);
-init_per_group(test_v1_v2, Config) ->
- init_v1_v2(Config);
-init_per_group(test_v2, Config) ->
- init_v2(Config);
-init_per_group(test_v1, Config) ->
- init_v1(Config);
-init_per_group(misc, Config) ->
- init_misc(Config);
-init_per_group(mib_storage_varm_mnesia, Config) ->
- init_varm_mib_storage_mnesia(Config);
-init_per_group(mib_storage_varm_dets, Config) ->
- init_varm_mib_storage_dets(Config);
-init_per_group(mib_storage_size_check_mnesia, Config) ->
- init_size_check_msm(Config);
-init_per_group(mib_storage_size_check_dets, Config) ->
- init_size_check_msd(Config);
-init_per_group(mib_storage_size_check_ets, Config) ->
- init_size_check_mse(Config);
-init_per_group(mib_storage_mnesia, Config) ->
- init_mib_storage_mnesia(Config);
-init_per_group(mib_storage_dets, Config) ->
- init_mib_storage_dets(Config);
-init_per_group(mib_storage_ets, Config) ->
- init_mib_storage_ets(Config);
-init_per_group(_GroupName, Config) ->
- Config.
+
+init_per_suite(Config0) when is_list(Config0) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config0: ~p", [Config0]),
+
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+
+ %% Mib-dirs
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ Config3 = [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2],
+
+ ?DBG("init_per_suite -> end with"
+ "~n Config3: ~p", [Config3]),
+
+ Config3.
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
+init_per_group(all_tcs = GroupName, Config) ->
+ init_all(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(otp_7157 = GroupName, Config) ->
+ init_otp_7157(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(otp_4394 = GroupName, Config) ->
+ init_otp_4394(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(v2_inform = GroupName, Config) ->
+ init_v2_inform(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(multiple_reqs_2 = GroupName, Config) ->
+ init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(multiple_reqs = GroupName, Config) ->
+ init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_multi_threaded = GroupName, Config) ->
+ init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v3 = GroupName, Config) ->
+ init_v3(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v1_v2 = GroupName, Config) ->
+ init_v1_v2(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v2 = GroupName, Config) ->
+ init_v2(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v1 = GroupName, Config) ->
+ init_v1(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(misc = GroupName, Config) ->
+ init_misc(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_varm_mnesia = GroupName, Config) ->
+ init_varm_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName,
+ Config));
+init_per_group(mib_storage_varm_dets = GroupName, Config) ->
+ init_varm_mib_storage_dets(snmp_test_lib:init_group_top_dir(GroupName,
+ Config));
+init_per_group(mib_storage_size_check_mnesia = GroupName, Config) ->
+ init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_size_check_dets = GroupName, Config) ->
+ init_size_check_msd(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_size_check_ets = GroupName, Config) ->
+ init_size_check_mse(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_mnesia = GroupName, Config) ->
+ init_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName,
+ Config));
+init_per_group(mib_storage_dets = GroupName, Config) ->
+ init_mib_storage_dets(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_ets = GroupName, Config) ->
+ init_mib_storage_ets(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(GroupName, Config).
end_per_group(all_tcs, Config) ->
finish_all(Config);
@@ -315,107 +346,86 @@ end_per_group(_GroupName, Config) ->
-init_per_testcase(otp8395 = Case, Config) when is_list(Config) ->
+%% ---- Init Per TestCase ----
+
+init_per_testcase(Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
+ "~n Config: ~p", [Config]),
+
+ p("Agent Info: "
+ "~n ~p", [snmpa:info()]),
+
+ init_per_testcase1(Case, Config).
+
+init_per_testcase1(otp8395 = Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [Case, Config]),
- Config2 = init_per_testcase2(Case, init_per_suite(Config)),
- otp8395({init, Config2});
-init_per_testcase(otp_7157_test = _Case, Config) when is_list(Config) ->
- ?DBG("init_per_testcase -> entry with"
+ otp8395({init, init_per_testcase2(Case, Config)});
+init_per_testcase1(otp9884 = Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
+ "~n Case: ~p"
+ "~n Config: ~p", [Case, Config]),
+ otp9884({init, init_per_testcase2(Case, Config)});
+init_per_testcase1(otp_7157_test = _Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(1)),
- [{watchdog, Dog}|Config];
-init_per_testcase(v2_inform_i = _Case, Config) when is_list(Config) ->
- ?DBG("init_per_testcase -> entry with"
+ [{watchdog, Dog} | Config ];
+init_per_testcase1(v2_inform_i = _Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(10)),
- [{watchdog, Dog}|Config];
-init_per_testcase(v3_inform_i = _Case, Config) when is_list(Config) ->
- ?DBG("init_per_testcase -> entry with"
+ [{watchdog, Dog} | Config ];
+init_per_testcase1(v3_inform_i = _Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(10)),
- [{watchdog, Dog}|Config];
-init_per_testcase(_Case, Config) when is_list(Config) ->
+ [{watchdog, Dog} | Config ];
+init_per_testcase1(_Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(6)),
- [{watchdog, Dog}|Config].
+ [{watchdog, Dog}| Config ].
-end_per_testcase(otp8395, Config) when is_list(Config) ->
- otp8395({fin, Config});
-end_per_testcase(_Case, Config) when is_list(Config) ->
- ?DBG("end_per_testcase -> entry with"
- "~n Case: ~p"
- "~n Config: ~p", [_Case, Config]),
- Dog = ?config(watchdog, Config),
- ?WD_STOP(Dog),
- Config.
+%% ---- End Per TestCase ----
-init_per_suite(Config) ->
- ?DBG("init_per_suite -> entry with"
+end_per_testcase(Case, Config) when is_list(Config) ->
+ ?DBG("end_per_testcase -> entry with"
"~n Config: ~p", [Config]),
- %% Suite root dir for test suite
- PrivDir = ?config(priv_dir, Config),
+ p("Agent Info: "
+ "~n ~p", [snmpa:info()]),
- %% Create top-directory for this sub-suite
- SuiteTopDir = filename:join([PrivDir, ?MODULE]),
- case file:make_dir(SuiteTopDir) of
- ok ->
- ok;
- {error, eexist} ->
- %% This can happen since this is not really a
- %% suite-init function.
- ok;
- {error, Reason} ->
- ?FAIL({failed_creating_suite_top_dir, SuiteTopDir, Reason})
- end,
+ display_log(Config),
+ end_per_testcase1(Case, Config).
- %% --
- %% Fix config (data-dir is not correct):
- %%
-
- Config1 = fix_data_dir(Config),
- %% Config1 = Config,
-
- %% Mib-dirs
- MibDir = ?config(data_dir, Config1),
- StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
-
- Config2 = [{suite_top_dir, SuiteTopDir},
- {mib_dir, MibDir},
- {std_mib_dir, StdMibDir} | Config1],
-
- ?DBG("init_per_suite -> done when"
- "~n Config2: ~p", [Config2]),
- Config2.
-
-%% end_per_suite(Config) ->
-end_per_suite(Config) ->
+end_per_testcase1(otp8395, Config) when is_list(Config) ->
+ otp8395({fin, Config});
+end_per_testcase1(otp9884, Config) when is_list(Config) ->
+ otp9884({fin, Config});
+end_per_testcase1(_Case, Config) when is_list(Config) ->
+ ?DBG("end_per_testcase1 -> entry with"
+ "~n Case: ~p"
+ "~n Config: ~p", [_Case, Config]),
+ Dog = ?config(watchdog, Config),
+ ?WD_STOP(Dog),
Config.
-fix_data_dir(Config) ->
- DataDir0 = ?config(data_dir, Config),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config),
- [{data_dir, DataDir} | Config1].
-
init_per_testcase2(Case, Config) ->
- SuiteToDir = ?config(suite_top_dir, Config),
-
- %% Create top-directory for this test-case
- CaseTopDir = filename:join([SuiteToDir, Case]),
- ok = file:make_dir(CaseTopDir),
+
+ ?DBG("end_per_testcase2 -> entry with"
+ "~n Case: ~p"
+ "~n Config: ~p", [Case, Config]),
+
+ CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
%% Create agent top-dir(s)
AgentTopDir = filename:join([CaseTopDir, agent]),
@@ -614,19 +624,19 @@ mib_storage_mnesia_cases() ->
msm_mib_of].
mse_size_check_cases() ->
-[mse_size_check].
+ [mse_size_check].
msd_size_check_cases() ->
-[msd_size_check].
+ [msd_size_check].
msm_size_check_cases() ->
-[msm_size_check].
+ [msm_size_check].
varm_mib_storage_dets_cases() ->
-[msd_varm_mib_start].
+ [msd_varm_mib_start].
varm_mib_storage_mnesia_cases() ->
-[msm_varm_mib_start].
+ [msm_varm_mib_start].
init_mib_storage_ets(Config) when is_list(Config) ->
?LOG("init_mib_storage_ets -> entry", []),
@@ -635,36 +645,37 @@ init_mib_storage_ets(Config) when is_list(Config) ->
init_mib_storage_dets(Config) when is_list(Config) ->
?LOG("init_mib_storage_ets -> entry", []),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ ?line AgentDbDir = ?GCONF(agent_db_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDbDir}},
init_ms(Config, [MibStorage]).
init_mib_storage_mnesia(Config) when is_list(Config) ->
?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
+ MibStorage = {snmp_mib_storage, {mnesia,[]}},
init_ms(Config, [MibStorage]).
init_ms(Config, Opts) when is_list(Config) ->
?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
MibsVerbosity = {snmp_mibserver_verbosity, trace},
SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
+ Opts1 = [MasterAgentVerbosity, MibsVerbosity, SymStoreVerbosity | Opts],
+ [{vsn, v1} | start_v1_agent(Config, Opts1)].
init_size_check_mse(Config) when is_list(Config) ->
MibStorage = {snmp_mib_storage, ets},
init_size_check_ms(Config, [MibStorage]).
init_size_check_msd(Config) when is_list(Config) ->
- AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage, {dets, AgentDir}},
+ AgentDbDir = ?GCONF(agent_db_dir, Config),
+ MibStorage = {snmp_mib_storage, {dets, AgentDbDir}},
init_size_check_ms(Config, [MibStorage]).
init_size_check_msm(Config) when is_list(Config) ->
@@ -686,22 +697,24 @@ init_size_check_ms(Config, Opts) when is_list(Config) ->
?SKIP({failed_starting_crypto, Reason})
end,
create_tables(SaNode),
- AgentDir = ?GCONF(agent_dir, Config),
- MgrDir = ?GCONF(mgr_dir, Config),
- Ip = ?GCONF(ip, Config),
- ?line ok =
- config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ ?line ok = config([v3], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v3} | start_v3_agent(Config, Opts)].
init_varm_mib_storage_dets(Config) when is_list(Config) ->
?LOG("init_varm_mib_storage_dets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
+ ?line AgentDbDir = ?GCONF(agent_db_dir, Config),
+ ?line AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
+ MibStorage = {snmp_mib_storage, {dets, AgentDbDir}},
MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
MibsVerbosity = {snmp_mibserver_verbosity, trace},
SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
@@ -710,12 +723,13 @@ init_varm_mib_storage_dets(Config) when is_list(Config) ->
init_varm_mib_storage_mnesia(Config) when is_list(Config) ->
?LOG("init_varm_mib_storage_mnesia -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
MibStorage = {snmp_mib_storage,{mnesia,[]}},
MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
MibsVerbosity = {snmp_mibserver_verbosity, trace},
@@ -1180,10 +1194,11 @@ v1_cases() ->
init_v1(Config) when is_list(Config) ->
?line SaNode = ?config(snmp_sa, Config),
?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
?line MgrDir = ?config(mgr_dir, Config),
?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line config([v1], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v1} | start_v1_agent(Config)].
finish_v1(Config) when is_list(Config) ->
@@ -1223,10 +1238,11 @@ v2_cases() ->
init_v2(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ config([v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v2} | start_v2_agent(Config)].
finish_v2(Config) when is_list(Config) ->
@@ -1242,10 +1258,11 @@ v1_v2_cases() ->
init_v1_v2(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ config([v1,v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, bilingual} | start_bilingual_agent(Config)].
finish_v1_v2(Config) when is_list(Config) ->
@@ -1306,10 +1323,10 @@ init_v3(Config) when is_list(Config) ->
end,
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
+ ?line ok = config([v3], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v3} | start_v3_agent(Config)].
@@ -1320,17 +1337,20 @@ finish_v3(Config) when is_list(Config) ->
lists:keydelete(vsn, 1, C1).
-mt_cases() ->
-[multi_threaded, mt_trap].
+mt_cases() ->
+ [
+ multi_threaded,
+ mt_trap
+ ].
init_mt(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- ?line ok =
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line ok = config([v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v2} | start_multi_threaded_agent(Config)].
finish_mt(Config) when is_list(Config) ->
@@ -1409,7 +1429,10 @@ simple(Config) when is_list(Config) ->
?P(simple),
init_case(Config),
- try_test(simple_standard_test).
+ try_test(simple_standard_test),
+
+ p("done"),
+ ok.
simple_2(X) -> ?P(simple_2), simple(X).
@@ -1498,7 +1521,8 @@ mt_trap(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(mt_trap_test, [MA]),
?line unload_master("TestTrapv2"),
- ?line unload_master("Test1").
+ ?line unload_master("Test1"),
+ ok.
v2_types(suite) -> [];
v2_types(Config) when is_list(Config) ->
@@ -1588,7 +1612,7 @@ change_target_addr_config(Config) when is_list(Config) ->
try_test(ma_trap1, [MA]),
?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
+ ?line snmpa:verbosity(local_db, silence),
%% Start new dummy listener
?LOG("change_target_addr_config -> start dummy manager",[]),
@@ -1596,9 +1620,9 @@ change_target_addr_config(Config) when is_list(Config) ->
%% Reconfigure
?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_addr_conf(AgentConfDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
%% Send the trap again
?LOG("change_target_addr_config -> send trap again",[]),
@@ -1611,7 +1635,7 @@ change_target_addr_config(Config) when is_list(Config) ->
?line ok = dummy_manager_stop(Pid),
?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
+ ?line reset_target_addr_conf(AgentConfDir),
?LOG("change_target_addr_config -> unload TestTrap",[]),
?line unload_master("TestTrap").
@@ -2054,7 +2078,7 @@ v3_inform(_X) ->
{req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
init_v2_inform(Config) when is_list(Config) ->
- _Dir = ?config(agent_dir, Config),
+ _Dir = ?config(agent_conf_dir, Config),
%% snmp_internal_mib:configure(Dir),
Config.
@@ -2062,7 +2086,7 @@ init_v3_inform(X) ->
init_v2_inform(X).
finish_v2_inform(Config) when is_list(Config) ->
- _Dir = ?config(agent_dir, Config),
+ _Dir = ?config(agent_conf_dir, Config),
%% snmp_internal_mib:configure(Dir),
Config.
@@ -2364,9 +2388,9 @@ v3_md5_auth(Config) when is_list(Config) ->
?P1("Testing MD5 authentication...takes a few seconds..."),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_params_conf(AgentConfDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
@@ -2375,14 +2399,14 @@ v3_md5_auth(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
?line unload_master("TestTrapv2"),
?line unload_master("TestTrap"),
?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
+ ?line reset_target_params_conf(AgentConfDir).
v3_sha_auth(suite) -> [];
v3_sha_auth(Config) when is_list(Config) ->
@@ -2391,9 +2415,9 @@ v3_sha_auth(Config) when is_list(Config) ->
?P1("Testing SHA authentication...takes a few seconds..."),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_params_conf(AgentConfDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
@@ -2402,14 +2426,14 @@ v3_sha_auth(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
?line unload_master("TestTrapv2"),
?line unload_master("TestTrap"),
?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
+ ?line reset_target_params_conf(AgentConfDir).
v3_des_priv(suite) -> [];
v3_des_priv(Config) when is_list(Config) ->
@@ -2418,9 +2442,9 @@ v3_des_priv(Config) when is_list(Config) ->
?P1("Testing DES encryption...takes a few seconds..."),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_params_conf(AgentConfDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
@@ -2431,14 +2455,14 @@ v3_des_priv(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
?line unload_master("TestTrapv2"),
?line unload_master("TestTrap"),
?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
+ ?line reset_target_params_conf(AgentConfDir).
%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
@@ -3134,8 +3158,9 @@ mt_trap_test(MA) ->
?DBG("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []),
snmpa:send_trap(MA, testTrapv22, "standard trap"),
?DBG("mt_trap_test(02) -> await v2trap", []),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?line expect(mt_trap_test_1, v2trap,
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
?DBG("mt_trap_test(03) -> issue mtTrap (standard trap)", []),
snmpa:send_trap(MA, mtTrap, "standard trap"),
@@ -3143,28 +3168,22 @@ mt_trap_test(MA) ->
?DBG("mt_trap_test(04) -> multi pid: ~p. Now request sysUpTime...", [Pid]),
g([[sysUpTime,0]]),
- %% Previously (before OTP-6784) this was done at 09 below
- %% when the test1:multiStr was actually executed by the
- %% worker-process, but as of 4.9.4, this is now executed
- %% my the master_agent-process...
- ?DBG("mt_trap_test(05) -> send continue to multi-pid", []),
- Pid ! continue,
-
?DBG("mt_trap_test(06) -> await sysUpTime", []),
- ?line expect(2, [{[sysUpTime,0], any}]),
+ ?line expect(mt_trap_test_2, [{[sysUpTime,0], any}]),
?DBG("mt_trap_test(07) -> issue testTrapv22 (standard trap)", []),
snmpa:send_trap(MA, testTrapv22, "standard trap"),
?DBG("mt_trap_test(08) -> await v2trap", []),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
+ ?line expect(mt_trap_test_3, v2trap,
+ [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- %% ?DBG("mt_trap_test(09) -> send continue to multi-pid", []),
- %% Pid ! continue,
+ ?DBG("mt_trap_test(09) -> send continue to multi-pid", []),
+ Pid ! continue,
?DBG("mt_trap_test(10) -> await v2trap", []),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [2]},
- {[multiStr,0], "ok"}]),
+ ?line expect(mt_trap_test_4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?testTrap ++ [2]},
+ {[multiStr,0], "ok"}]),
?DBG("mt_trap_test(11) -> done", []),
ok.
@@ -3563,53 +3582,82 @@ do_mul_set_err() ->
%% Req. SA-MIB
sa_mib() ->
g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
+ ?line expect(sa_mib_1, [{[sa, [2,0]], 3}]),
s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
+ ?line expect(sa_mib_2, [{[sa, [1,0]], "sa_test"}]),
+ ok.
ma_trap1(MA) ->
ok = snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
+ ?line expect(ma_trap1_1,
+ trap, [system], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
ok = snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
+ ?line expect(ma_trap1_2,
+ trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"}]),
+ ok.
ma_trap2(MA) ->
snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+ ?line expect(ma_trap2_3,
+ trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]),
+ ok.
ma_v2_2_v1_trap(MA) ->
snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
+ ?line expect(ma_v2_2_v1_trap_3,
+ trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]),
+ ok.
ma_v2_2_v1_trap2(MA) ->
snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
{ifAdminStatus, [1], 1},
{ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
+ ?line expect(ma_v2_2_v1_trap2_3,
+ trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ {[ifAdminStatus, 1], 1},
+ {[ifOperStatus, 1], 2}]),
+ ok.
sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
+ %% io:format("sa_trap1 -> entry with"
+ %% "~n SA: ~p"
+ %% "~n node(SA): ~p"
+ %% "~n self(): ~p"
+ %% "~n node(): ~p"
+ %% "~n", [SA, node(SA), self(), node()]),
+ _VRes = (catch snmpa:verbosity(SA, {subagents, trace})),
+ %% io:format("sa_trap1 -> SA verbosity set: "
+ %% "~n VRes: ~p"
+ %% "~n", [VRes]),
+ _TSRes = (catch snmpa:send_trap(SA, saTrap, "standard trap")),
+ %% io:format("sa_trap1 -> SA trap send: "
+ %% "~n TSRes: ~p"
+ %% "~n", [TSRes]),
+ ?line expect(sa_trap1_4,
+ trap, [ericsson], 6, 1, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"}]),
+ snmpa:verbosity(SA, {subagents, silence}),
+ ok.
sa_trap2(SA) ->
snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
+ ?line expect(sa_trap2_5,
+ trap, [ericsson], 6, 1, [{[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"}]),
+ ok.
sa_trap3(SA) ->
snmpa:send_trap(SA, saTrap2, "standard trap",
[{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
+ ?line expect(sa_trap3_6,
+ trap, [ericsson], 6, 2, [{[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]}]),
+ ok.
ma_v2_trap1(MA) ->
?DBG("ma_v2_traps -> entry with MA = ~p => "
@@ -4029,33 +4077,42 @@ ma_v1_2_v2_trap2(MA) ->
sa_v1_2_v2_trap1(SA) ->
+ snmpa:verbosity(SA, {subagents, trace}),
snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
+ ?line expect(trap1_4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]),
+ snmpa:verbosity(SA, {subagents, silence}),
+ ok.
sa_v1_2_v2_trap2(SA) ->
+ snmpa:verbosity(SA, {subagents, trace}),
snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
+ ?line expect(trap2_4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
+ {[system, [4,0]], "pelle"},
+ {[sa, [1,0]], "sa_test"},
+ {[snmpTrapEnterprise, 0], ?ericsson}]),
+ snmpa:verbosity(SA, {subagents, silence}),
+ ok.
+
sa_v1_2_v2_trap3(SA) ->
+ snmpa:verbosity(SA, {subagents, trace}),
snmpa:send_trap(SA, saTrap2, "standard trap",
[{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
+ ?line expect(trap3_4, v2trap, [{[sysUpTime, 0], any},
+ {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
+ {[system, [4,0]],
+ "{mbj,eklas}@erlang.ericsson.se"},
+ {[sa, [1,0]], "sa_test"},
+ {[intViewSubtree,4],[1,2,3,4]},
+ {[snmpTrapEnterprise, 0], ?ericsson}]),
+ snmpa:verbosity(SA, {subagents, silence}),
+ ok.
%% Req. SA-MIB, OLD-SNMPEA-MIB
@@ -4195,9 +4252,9 @@ snmp_standard_mib(Config) when is_list(Config) ->
%% Req. SNMP-STANDARD-MIB
standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
+ ?line OutPkts2 = OutPkts + 1,
%% There are some more counters we could test here, but it's not that
%% important, since they are removed from SNMPv2-MIB.
ok.
@@ -4207,27 +4264,27 @@ std_mib_init() ->
%% disable authentication failure traps. (otherwise w'd get many of
%% them - this is also a test to see that it works).
s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
+ ?line expect(std_mib_init_1, [{[snmpEnableAuthenTraps, 0], 2}]).
%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
std_mib_finish() ->
%% enable again
s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
+ ?line expect(std_mib_finish_1, [{[snmpEnableAuthenTraps, 0], 1}]).
%% Req. SNMP-STANDARD-MIB
standard_mib_test_finish() ->
- %% force a authenticationFailure
+ %% force a authenticationFailure (should result in a trap)
std_mib_write(),
%% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
+ ?line expect(standard_mib_test_finish_2, trap, [1,2,3], 4, 0, []).
%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
std_mib_read() ->
?DBG("std_mib_read -> entry", []),
g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
+ ?line expect(std_mib_read_1, timeout). % make sure we don't get a trap!
%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
@@ -4362,10 +4419,10 @@ std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
snmpv2_mib_a() ->
?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
- {[sysLocation, 0], "val2"}]),
+ ?line expect(snmpv2_mib_a_3, [{[snmpSetSerialNo,0], SetSerial},
+ {[sysLocation, 0], "val2"}]),
s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line expect(4, inconsistentValue, 2,
+ ?line expect(snmpv2_mib_a_4, inconsistentValue, 2,
[{[sysLocation, 0], "val3"},
{[snmpSetSerialNo,0], SetSerial}]),
?line ["val2"] = get_req(5, [[sysLocation,0]]).
@@ -4688,46 +4745,46 @@ snmp_view_based_acm_mib() ->
do_set(Row) ->
s(Row),
- expect(1, Row).
+ expect(do_set_1, Row).
add_row(RowStatus) ->
s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
+ expect(add_row_1, [{RowStatus, ?createAndGo}]).
del_row(RowStatus) ->
s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
+ expect(del_row_1, [{RowStatus, ?destroy}]).
use_no_rights() ->
g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
+ ?v1_2_3(expect(use_no_rights_11, noSuchName, 1, any),
+ expect(use_no_rights_12, [{[xDescr,0], noSuchObject}]),
+ expect(use_no_rights_13, authorizationError, 1, any)),
g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
+ ?v1_2_3(expect(use_no_rights_21, noSuchName, 1, any),
+ expect(use_no_rights_22, [{[xDescr2,0], noSuchObject}]),
+ expect(use_no_rights_23, authorizationError, 1, any)),
gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
+ ?v1_2_3(expect(use_no_rights_31, noSuchName, 1, any),
+ expect(use_no_rights_32, [{[xDescr], endOfMibView}]),
+ expect(use_no_rights_33, authorizationError, 1, any)),
s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
+ ?v1_2_3(expect(use_no_rights_41, noSuchName, 1, any),
+ expect(use_no_rights_42, noAccess, 1, any),
+ expect(use_no_rights_43, authorizationError, 1, any)).
use_rights() ->
g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
+ expect(use_rights_1, [{[xDescr,0], any}]),
g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
+ expect(use_rights_2, [{[xDescr2,0], any}]),
s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
+ expect(use_rights_3, noError, 0, any),
g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
+ expect(use_rights_4, [{[xDescr,0], "tryit"}]).
mk_ln(X) ->
[length(X) | X].
@@ -4749,7 +4806,7 @@ snmp_user_based_sm_mib_3(Config) when is_list(Config) ->
?P(snmp_user_based_sm_mib_3),
init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
+ _AgentDir = ?config(agent_conf_dir, Config),
?line load_master_std("SNMP-USER-BASED-SM-MIB"),
%% The newUser used here already has VACM access.
@@ -5200,16 +5257,6 @@ loop_it_2(Oid, N) ->
%%%-----------------------------------------------------------------
-
-
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-
-
-
-
-
%%-----------------------------------------------------------------
%% Ticket: OTP-1128
%% Slogan: Bug in handling of createAndWait set-requests.
@@ -5691,28 +5738,28 @@ otp_3725_test(MaNode) ->
init_otp_4394(Config) when is_list(Config) ->
?DBG("init_otp_4394 -> entry with"
"~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentConfDir, MgrDir, Ip),
MasterAgentVerbosity = {master_agent_verbosity, trace},
NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
+ Opts = [MasterAgentVerbosity, NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config, Opts)].
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
+otp_4394_config(AgentConfDir, MgrDir, Ip0) ->
?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ "~n AgentConfDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentConfDir, MgrDir, Ip0]),
Vsn = [v1],
Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsn, Ip,
?TRAP_UDP, Ip, 4000,
"OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
+ ?line case update_usm(Vsn, AgentConfDir) of
true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ ?line copy_file(filename:join(AgentConfDir, "usm.conf"),
filename:join(MgrDir, "usm.conf")),
?line update_usm_mgr(Vsn, MgrDir);
false ->
@@ -5720,8 +5767,8 @@ otp_4394_config(AgentDir, MgrDir, Ip0) ->
end,
C1 = {"a", "all-rights", "initial", "", "pc"},
C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
+ ?line write_community_conf(AgentConfDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentConfDir),
Ta1 = {"shelob v1",
[134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
"pc1",
@@ -5735,9 +5782,9 @@ otp_4394_config(AgentDir, MgrDir, Ip0) ->
"target_v1", "",
%% [255,255,255,255,0,0],
[], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
+ ?line write_target_addr_conf(AgentConfDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentConfDir, Vsn),
+ ?line write_notify_conf(AgentConfDir),
ok.
@@ -5790,10 +5837,11 @@ init_otp_7157(Config) when is_list(Config) ->
?DBG("init_otp_7157 -> entry with"
"~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
?line MgrDir = ?config(mgr_dir, Config),
?line Ip = ?config(ip, Config),
- ?line config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line config([v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
MasterAgentVerbosity = {master_agent_verbosity, trace},
NetIfVerbosity = {net_if_verbosity, trace},
Opts = [MasterAgentVerbosity, NetIfVerbosity],
@@ -5850,7 +5898,7 @@ otp_7157_test1(MA) ->
otp8395({init, Config}) when is_list(Config) ->
?DBG("otp8395(init) -> entry with"
"~n Config: ~p", [Config]),
-
+
%% --
%% Start nodes
%%
@@ -5858,7 +5906,7 @@ otp8395({init, Config}) when is_list(Config) ->
{ok, AgentNode} = start_node(agent),
%% {ok, SubAgentNode} = start_node(sub_agent),
{ok, ManagerNode} = start_node(manager),
-
+
%% --
%% Mnesia init
%%
@@ -5866,10 +5914,10 @@ otp8395({init, Config}) when is_list(Config) ->
AgentDbDir = ?config(agent_db_dir, Config),
AgentMnesiaDir = filename:join([AgentDbDir, "mnesia"]),
mnesia_init(AgentNode, AgentMnesiaDir),
-
-%% SubAgentDir = ?config(sub_agent_dir, Config),
-%% SubAgentMnesiaDir = filename:join([SubAgentDir, "mnesia"]),
-%% mnesia_init(SubAgentNode, SubAgentMnesiaDir),
+
+ %% SubAgentDir = ?config(sub_agent_dir, Config),
+ %% SubAgentMnesiaDir = filename:join([SubAgentDir, "mnesia"]),
+ %% mnesia_init(SubAgentNode, SubAgentMnesiaDir),
%% ok = mnesia_create_schema(AgentNode, [AgentNode, SubAgentNode]),
%% ok = mnesia:create_schema([AgentNode, SubAgentNode]),
@@ -5894,12 +5942,12 @@ otp8395({init, Config}) when is_list(Config) ->
%% SubAgentIP = tuple_to_list(SubAgentIP0),
{ok, ManagerIP0} = snmp_misc:ip(ManagerHost),
ManagerIP = tuple_to_list(ManagerIP0),
-
+
%% --
%% Write agent config
%%
-
+
Vsns = [v1],
AgentConfDir = ?config(agent_conf_dir, Config),
ManagerConfDir = ?config(manager_top_dir, Config),
@@ -5923,7 +5971,7 @@ otp8395({init, Config}) when is_list(Config) ->
{manager_node, ManagerNode},
{manager_host, ManagerHost},
{manager_ip, ManagerIP}|Config]),
-
+
%% --
%% Create watchdog
%%
@@ -5935,7 +5983,7 @@ otp8395({init, Config}) when is_list(Config) ->
otp8395({fin, Config}) when is_list(Config) ->
?DBG("otp8395(fin) -> entry with"
"~n Config: ~p", [Config]),
-
+
AgentNode = ?config(agent_node, Config),
ManagerNode = ?config(manager_node, Config),
@@ -5943,11 +5991,11 @@ otp8395({fin, Config}) when is_list(Config) ->
%% Stop agent (this is the nice way to do it,
%% so logs and files can be closed in the proper way).
%%
-
+
AgentSup = ?config(agent_sup, Config),
?DBG("otp8395(fin) -> stop (stand-alone) agent: ~p", [AgentSup]),
stop_stdalone_agent(AgentSup),
-
+
%% -
%% Stop mnesia
%%
@@ -5963,8 +6011,8 @@ otp8395({fin, Config}) when is_list(Config) ->
stop_node(AgentNode),
-%% SubAgentNode = ?config(sub_agent_node, Config),
-%% stop_node(SubAgentNode),
+ %% SubAgentNode = ?config(sub_agent_node, Config),
+ %% stop_node(SubAgentNode),
%% -
@@ -5984,7 +6032,7 @@ otp8395(doc) ->
otp8395(Config) when is_list(Config) ->
?DBG("otp8395 -> entry with"
"~n Config: ~p", [Config]),
-
+
?SLEEP(1000),
%% This is just to dirty trick for the ***old*** test-code
@@ -6002,8 +6050,8 @@ otp8395(Config) when is_list(Config) ->
{ok, LogInfo} = rpc:call(AgentNode, snmpa, log_info, []),
?DBG("otp8395 -> LogInfo: ~p", [LogInfo]),
-%% SyncRes = rpc:call(AgentNode, snmp, log_sync, [?audit_trail_log_name]),
-%% ?DBG("otp8395 -> SyncRes: ~p", [SyncRes]),
+ %% SyncRes = rpc:call(AgentNode, snmp, log_sync, [?audit_trail_log_name]),
+ %% ?DBG("otp8395 -> SyncRes: ~p", [SyncRes]),
ok = agent_log_validation(AgentNode),
LTTRes =
@@ -6013,7 +6061,195 @@ otp8395(Config) when is_list(Config) ->
?SLEEP(1000),
?DBG("otp8395 -> done", []),
ok.
-
+
+
+%%-----------------------------------------------------------------
+
+otp9884({init, Config}) when is_list(Config) ->
+ ?DBG("otp9884(init) -> entry with"
+ "~n Config: ~p", [Config]),
+
+ %% --
+ %% Start nodes
+ %%
+
+ {ok, AgentNode} = start_node(agent),
+
+ %% We don't use a manager in this test but the (common) config
+ %% function takes an argument that is derived from this
+ {ok, ManagerNode} = start_node(manager),
+
+ %% --
+ %% Mnesia init
+ %%
+
+ AgentDbDir = ?config(agent_db_dir, Config),
+ AgentMnesiaDir = filename:join([AgentDbDir, "mnesia"]),
+ mnesia_init(AgentNode, AgentMnesiaDir),
+
+ mnesia_create_schema(AgentNode, [AgentNode]),
+
+ mnesia_start(AgentNode),
+
+ %% --
+ %% Host & IP
+ %%
+
+ AgentHost = ?HOSTNAME(AgentNode),
+ ManagerHost = ?HOSTNAME(ManagerNode),
+
+ Host = snmp_test_lib:hostname(),
+ Ip = ?LOCALHOST(),
+ {ok, AgentIP0} = snmp_misc:ip(AgentHost),
+ AgentIP = tuple_to_list(AgentIP0),
+ {ok, ManagerIP0} = snmp_misc:ip(ManagerHost),
+ ManagerIP = tuple_to_list(ManagerIP0),
+
+
+ %% --
+ %% Write agent config
+ %%
+
+ Vsns = [v1],
+ ManagerConfDir = ?config(manager_top_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ AgentTopDir = ?config(agent_top_dir, Config),
+ AgentBkpDir1 = filename:join([AgentTopDir, backup1]),
+ AgentBkpDir2 = filename:join([AgentTopDir, backup2]),
+ ok = file:make_dir(AgentBkpDir1),
+ ok = file:make_dir(AgentBkpDir2),
+ AgentBkpDirs = [AgentBkpDir1, AgentBkpDir2],
+ snmp_agent_test_lib:config(Vsns,
+ ManagerConfDir, AgentConfDir,
+ ManagerIP, AgentIP),
+
+
+ %% --
+ %% Start the agent
+ %%
+
+ Config2 = start_agent([{host, Host},
+ {ip, Ip},
+ {agent_node, AgentNode},
+ {agent_host, AgentHost},
+ {agent_ip, AgentIP},
+ {agent_backup_dirs, AgentBkpDirs}|Config]),
+
+ %% --
+ %% Create watchdog
+ %%
+
+ Dog = ?WD_START(?MINS(1)),
+
+ [{watchdog, Dog} | Config2];
+
+otp9884({fin, Config}) when is_list(Config) ->
+ ?DBG("otp9884(fin) -> entry with"
+ "~n Config: ~p", [Config]),
+
+ AgentNode = ?config(agent_node, Config),
+ ManagerNode = ?config(manager_node, Config),
+
+ %% -
+ %% Stop agent (this is the nice way to do it,
+ %% so logs and files can be closed in the proper way).
+ %%
+
+ AgentSup = ?config(agent_sup, Config),
+ ?DBG("otp9884(fin) -> stop (stand-alone) agent: ~p", [AgentSup]),
+ stop_stdalone_agent(AgentSup),
+
+ %% -
+ %% Stop mnesia
+ %%
+ ?DBG("otp9884(fin) -> stop mnesia", []),
+ mnesia_stop(AgentNode),
+
+
+ %% -
+ %% Stop the agent node
+ %%
+
+ ?DBG("otp9884(fin) -> stop agent node", []),
+ stop_node(AgentNode),
+
+
+ %% SubAgentNode = ?config(sub_agent_node, Config),
+ %% stop_node(SubAgentNode),
+
+
+ %% -
+ %% Stop the manager node
+ %%
+
+ ?DBG("otp9884(fin) -> stop manager node", []),
+ stop_node(ManagerNode),
+
+ Dog = ?config(watchdog, Config),
+ ?WD_STOP(Dog),
+ lists:keydelete(watchdog, 1, Config);
+
+otp9884(doc) ->
+ "OTP-9884 - Simlutaneous backup call should not work. ";
+
+otp9884(Config) when is_list(Config) ->
+ ?DBG("otp9884 -> entry with"
+ "~n Config: ~p", [Config]),
+
+ AgentNode = ?config(agent_node, Config),
+ [AgentBkpDir1, AgentBkpDir2] = ?config(agent_backup_dirs, Config),
+ Self = self(),
+ timer:apply_after(1000,
+ ?MODULE, otp9884_backup, [AgentNode, Self, first, AgentBkpDir1]),
+ timer:apply_after(1000,
+ ?MODULE, otp9884_backup, [AgentNode, Self, second, AgentBkpDir2]),
+ otp9884_await_backup_completion(undefined, undefined),
+
+ ?DBG("otp9884 -> done", []),
+ ok.
+
+
+otp9884_backup(Node, Pid, Tag, Dir) ->
+ io:format("[~w] call backup function~n", [Tag]),
+ Res = rpc:call(Node, snmpa, backup, [Dir]),
+ io:format("[~w] backup result: ~p~n", [Tag, Res]),
+ Pid ! {otp9884_backup_complete, Tag, Res}.
+
+otp9884_await_backup_completion(ok, Second)
+ when ((Second =/= ok) andalso (Second =/= undefined)) ->
+ io:format("otp9884_await_backup_completion -> "
+ "first backup succeed and second failed (~p)~n", [Second]),
+ ok;
+otp9884_await_backup_completion(First, ok)
+ when ((First =/= ok) andalso (First =/= undefined)) ->
+ io:format("otp9884_await_backup_completion -> "
+ "second backup succeed and first failed (~p)~n", [First]),
+ ok;
+otp9884_await_backup_completion(First, Second)
+ when (((First =:= undefined) andalso (Second =:= undefined))
+ orelse
+ ((First =:= undefined) andalso (Second =/= undefined))
+ orelse
+ ((First =/= undefined) andalso (Second =:= undefined))) ->
+ io:format("otp9884_await_backup_completion -> await complete messages~n", []),
+ receive
+ {otp9884_backup_complete, first, Res} ->
+ io:format("otp9884_await_backup_completion -> "
+ "received complete message for first: ~p~n", [Res]),
+ otp9884_await_backup_completion(Res, Second);
+ {otp9884_backup_complete, second, Res} ->
+ io:format("otp9884_await_backup_completion -> "
+ "received complete message for second: ~p~n", [Res]),
+ otp9884_await_backup_completion(First, Res)
+ after 10000 ->
+ %% we have waited long enough
+ throw({error, {timeout, First, Second}})
+ end;
+otp9884_await_backup_completion(First, Second) ->
+ throw({error, {bad_completion, First, Second}}).
+
+
+%%-----------------------------------------------------------------
agent_log_validation(Node) ->
rpc:call(Node, ?MODULE, agent_log_validation, []).
@@ -6338,8 +6574,8 @@ write_community_conf(Dir, Conf) ->
write_target_addr_conf(Dir, Conf) ->
snmp_agent_test_lib:write_target_addr_conf(Dir, Conf).
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns).
+%% write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+%% snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns).
rewrite_target_addr_conf(Dir, NewPort) ->
snmp_agent_test_lib:rewrite_target_addr_conf(Dir, NewPort).
@@ -6372,9 +6608,42 @@ copy_file(From, To) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+display_log(Config) ->
+ case lists:keysearch(agent_log_dir, 1, Config) of
+ {value, {_, Dir}} ->
+ case lists:keysearch(snmp_master, 1, Config) of
+ {value, {_, Node}} ->
+ LogDir = Dir,
+ Mibs = [],
+ OutFile = filename:join(LogDir, "snmpa_log.txt"),
+ p("~n"
+ "========================="
+ " < Audit Trail Log > "
+ "========================="
+ "~n"),
+ rcall(Node, snmpa, log_to_txt, [LogDir, Mibs, OutFile]),
+ rcall(Node, snmpa, log_to_io, [LogDir, Mibs]),
+ p("~n"
+ "========================="
+ " < / Audit Trail Log > "
+ "========================="
+ "~n", []);
+ false ->
+ p("display_log -> no agent node found"),
+ ok
+ end;
+ false ->
+ p("display_log -> no agent log dir found: "
+ "~n ~p", [Config]),
+ ok
+ end.
+
+
+%% ------
+
display_memory_usage() ->
Info = snmpa:info(snmp_master_agent),
- AMU = display_agent_memory_uasge(Info),
+ AMU = display_agent_memory_usage(Info),
NIMU = display_net_if_memory_usage(Info),
NSMU = display_note_store_memory_usage(Info),
SSMU = display_symbolic_store_memory_usage(Info),
@@ -6384,7 +6653,7 @@ display_memory_usage() ->
AMU ++ NIMU ++ NSMU ++ SSMU ++ LDBMU ++ MSMU, []),
ok.
-display_agent_memory_uasge(Info) ->
+display_agent_memory_usage(Info) ->
AgentInfo = lists_key1search(agent, Info),
ProcMem =
lists_key1search([process_memory,master_agent], AgentInfo),
@@ -6493,3 +6762,27 @@ lists_key1search(Key, List) when is_atom(Key) ->
regs() ->
lists:sort(registered()).
+
+%% ------
+
+rcall(Node, Mod, Func, Args) ->
+ case rpc:call(Node, Mod, Func, Args) of
+ {badrpc, nodedown} ->
+ ?FAIL({rpc_failure, Node});
+ Else ->
+ Else
+ end.
+
+
+%% ------
+
+p(F) ->
+ p(F, []).
+
+p(F, A) ->
+ io:format("*** [~s] ***"
+ "~n" ++ F ++ "~n", [formated_timestamp()|A]).
+
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
+
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index a18d9f3201..238832b7c1 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,20 +119,10 @@
%%% didn't undo (since it failed).
%%%-----------------------------------------------------------------
-init_all(Config0) when is_list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
+init_all(Config) when is_list(Config) ->
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+ ?LOG("init_all -> entry with"
+ "~n Config: ~p",[Config]),
%% --
%% Start nodes
@@ -143,34 +133,43 @@ init_all(Config0) when is_list(Config0) ->
%% --
- %% Create necessary files
+ %% Create necessary files ( and dirs )
%%
- PrivDir = ?config(priv_dir, Config),
- ?DBG("init_all -> PrivDir ~p", [PrivDir]),
+ SuiteTopDir = ?config(snmp_suite_top_dir, Config),
+ ?DBG("init_all -> SuiteTopDir ~p", [SuiteTopDir]),
- TopDir = filename:join(PrivDir, snmp_agent_test),
- case file:make_dir(TopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- ?FAIL({failed_creating_subsuite_top_dir, Error})
- end,
+ AgentDir = filename:join(SuiteTopDir, "agent/"),
+ ?line ok = file:make_dir(AgentDir),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
+ AgentDbDir = filename:join(AgentDir, "db/"),
+ ?line ok = file:make_dir(AgentDbDir),
+ ?DBG("init_all -> AgentDbDir ~p", [AgentDbDir]),
- ?line ok = file:make_dir(MgrDir = filename:join(TopDir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+ AgentLogDir = filename:join(AgentDir, "log/"),
+ ?line ok = file:make_dir(AgentLogDir),
+ ?DBG("init_all -> AgentLogDir ~p", [AgentLogDir]),
- ?line ok = file:make_dir(AgentDir = filename:join(TopDir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+ AgentConfDir = filename:join(AgentDir, "conf/"),
+ ?line ok = file:make_dir(AgentConfDir),
+ ?DBG("init_all -> AgentConfDir ~p", [AgentConfDir]),
+
+ MgrDir = filename:join(SuiteTopDir, "mgr/"),
+ ?line ok = file:make_dir(MgrDir),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
- ?line ok = file:make_dir(SaDir = filename:join(TopDir, "sa_dir/")),
+ SaDir = filename:join(SuiteTopDir, "sa/"),
+ ?line ok = file:make_dir(SaDir),
?DBG("init_all -> SaDir ~p", [SaDir]),
+ SaDbDir = filename:join(SaDir, "db/"),
+ ?line ok = file:make_dir(SaDbDir),
+ ?DBG("init_all -> SaDbDir ~p", [SaDbDir]),
+
+ %% MibDir = ?config(mib_dir, Config),
+ %% ?DBG("init_all -> MibDir ~p", [DataDir]),
+
%% --
%% Start and initiate mnesia
@@ -184,11 +183,11 @@ init_all(Config0) when is_list(Config0) ->
?DBG("init_all -> application mnesia: set_env dir",[]),
?line application_controller:set_env(mnesia, dir,
- filename:join(TopDir, "Mnesia1")),
+ filename:join(AgentDbDir, "Mnesia1")),
?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(TopDir, "Mnesia2")]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(SaDir, "Mnesia2")]),
?DBG("init_all -> create mnesia schema",[]),
?line ok = mnesia:create_schema([SaNode, node()]),
@@ -199,13 +198,18 @@ init_all(Config0) when is_list(Config0) ->
?DBG("init_all -> start application mnesia on ~p",[SaNode]),
?line ok = rpc:call(SaNode, application, start, [mnesia]),
Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {snmp_master, node()},
+ {agent_dir, AgentDir ++ "/"},
+ {agent_db_dir, AgentDbDir ++ "/"},
+ {agent_log_dir, AgentLogDir ++ "/"},
+ {agent_conf_dir, AgentConfDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {sa_db_dir, SaDbDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ %% {mib_dir, DataDir},
+ {ip, Ip} |
Config].
@@ -220,11 +224,14 @@ finish_all(Config) when is_list(Config) ->
%% --- This one *must* be run first in each case ---
init_case(Config) when is_list(Config) ->
+
?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
+ "~n Config: ~p", [Config]),
+
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = ?config(snmp_master, Config),
+ %% MasterNode = node(),
SaHost = ?HOSTNAME(SaNode),
MgrHost = ?HOSTNAME(MgrNode),
@@ -296,7 +303,12 @@ call(N,M,F,A) ->
?DBG("call -> done:"
"~n Ret: ~p"
"~n Zed: ~p", [Ret, Zed]),
- Ret
+ case Ret of
+ {error, Reason} ->
+ exit(Reason);
+ OK ->
+ OK
+ end
end.
wait(From, Env, M, F, A) ->
@@ -406,7 +418,8 @@ start_v3_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
start_bilingual_agent(Config) when is_list(Config) ->
start_agent(Config, [v1,v2]).
-start_bilingual_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
+start_bilingual_agent(Config, Opts)
+ when is_list(Config) andalso is_list(Opts) ->
start_agent(Config, [v1,v2], Opts).
start_mt_agent(Config) when is_list(Config) ->
@@ -418,57 +431,33 @@ start_mt_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
start_agent(Config, Vsns) ->
start_agent(Config, Vsns, []).
start_agent(Config, Vsns, Opts) ->
+
?LOG("start_agent -> entry (~p) with"
"~n Config: ~p"
"~n Vsns: ~p"
"~n Opts: ~p", [node(), Config, Vsns, Opts]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
-%% AgentConfig =
-%% [{agent_type, master},
-%% %% {multi_threaded, MultiT},
-%% %% {priority, Prio},
-%% %% {error_report_mod, ErrorReportMod},
-%% {versions, Vsns},
-%% {db_dir, AgentDir},
-%% %% {db_init_error, DbInitError},
-%% %% {set_mechanism, SetModule},
-%% %% {authentication_service, AuthModule},
-%% {audit_trail_log, [{type, read_write},
-%% {dir, AgentDir},
-%% {size, {10240, 10}},
-%% {repair, true}]},
-%% {config, [{verbosity, info},
-%% {dir, AgentDir},
-%% {force_load, false}]},
-%% {mibs, Mibs},
-%% %% {mib_storage, MibStorage},
-%% {local_db, []},
-%% {mib_server, []},
-%% {symbolic_store, []},
-%% {note_store, []},
-%% {net_if, []},
-%% %% {supervisor, SupOpts}
-%% ],
-
+ ?line AgentLogDir = ?config(agent_log_dir, Config),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line AgentDbDir = ?config(agent_db_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
app_env_init(vsn_init(Vsns) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_local_db_verbosity, log},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, log},
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentLogDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentConfDir},
+ {snmp_db_dir, AgentDbDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_local_db_verbosity, log},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, log},
{snmp_symbolic_store_verbosity, log},
- {snmp_note_store_verbosity, log},
- {snmp_net_if_verbosity, trace}],
+ {snmp_note_store_verbosity, log},
+ {snmp_net_if_verbosity, trace}],
Opts),
@@ -724,17 +713,13 @@ expect(Id, A, B, C, D, E) ->
expect2(Id, Fun).
expect2(Id, F) ->
- io:format("~w:expect2 -> entry with"
- "~n Id: ~w"
- "~n", [?MODULE, Id]),
+ io:format("EXPECT for ~w~n", [Id]),
case F() of
{error, Reason} ->
- {error, Id, Reason};
+ io:format("EXPECT failed for ~w: ~n~p~n", [Id, Reason]),
+ throw({error, {expect, Id, Reason}});
Else ->
- io:format("~w:expect2 -> "
- "~n Id: ~w"
- "~n Else: ~p"
- "~n", [?MODULE, Id, Else]),
+ io:format("EXPECT result for ~w: ~n~p~n", [Id, Else]),
Else
end.
@@ -769,21 +754,15 @@ do_expect(Expect) when is_atom(Expect) ->
do_expect({any_pdu, To})
when is_integer(To) orelse (To =:= infinity) ->
- io:format("~w:do_expect(any_pdu) -> entry with"
- "~n To: ~w"
- "~n", [?MODULE, To]),
+ io:format("EXPECT any PDU~n", []),
receive_pdu(To);
do_expect({any_trap, To}) ->
- io:format("~w:do_expect(any_trap) -> entry with"
- "~n To: ~w"
- "~n", [?MODULE, To]),
+ io:format("EXPECT any TRAP within ~w~n", [To]),
receive_trap(To);
do_expect({timeout, To}) ->
- io:format("~w:do_expect(timeout) -> entry with"
- "~n To: ~w"
- "~n", [?MODULE, To]),
+ io:format("EXPECT nothing within ~w~n", [To]),
receive
X ->
{error, {unexpected, X}}
@@ -794,13 +773,16 @@ do_expect({timeout, To}) ->
do_expect({Err, To})
when is_atom(Err) andalso (is_integer(To) orelse (To =:= infinity)) ->
+ io:format("EXPECT error ~w within ~w~n", [Err, To]),
do_expect({{error, Err}, To});
do_expect({error, Err}) when is_atom(Err) ->
Check = fun(_, R) -> R end,
+ io:format("EXPECT error ~w~n", [Err]),
do_expect2(Check, any, Err, any, any, get_timeout());
do_expect({{error, Err}, To}) ->
Check = fun(_, R) -> R end,
+ io:format("EXPECT error ~w within ~w~n", [Err, To]),
do_expect2(Check, any, Err, any, any, To);
%% exp_varbinds() -> [exp_varbind()]
@@ -810,16 +792,25 @@ do_expect({{error, Err}, To}) ->
%% ExpVBs -> exp_varbinds() | {VbsCondition, exp_varbinds()}
do_expect(ExpVBs) ->
Check = fun(_, R) -> R end,
+ io:format("EXPECT 'get-response'"
+ "~n with"
+ "~n Varbinds: ~p~n", [ExpVBs]),
do_expect2(Check, 'get-response', noError, 0, ExpVBs, get_timeout()).
do_expect(v2trap, ExpVBs) ->
Check = fun(_, R) -> R end,
+ io:format("EXPECT 'snmpv2-trap'"
+ "~n with"
+ "~n Varbinds: ~p~n", [ExpVBs]),
do_expect2(Check, 'snmpv2-trap', noError, 0, ExpVBs, get_timeout());
do_expect(report, ExpVBs) ->
Check = fun(_, R) -> R end,
+ io:format("EXPECT 'report'"
+ "~n with"
+ "~n Varbinds: ~p~n", [ExpVBs]),
do_expect2(Check, 'report', noError, 0, ExpVBs, get_timeout());
@@ -827,16 +818,13 @@ do_expect(inform, ExpVBs) ->
do_expect({inform, true}, ExpVBs);
do_expect({inform, false}, ExpVBs) ->
- io:format("~w:do_expect(inform, false) -> entry with"
- "~n ExpVBs: ~p"
- "~n", [?MODULE, ExpVBs]),
Check = fun(_, R) -> R end,
+ io:format("EXPECT 'inform-request' (false)"
+ "~n with"
+ "~n Varbinds: ~p~n", [ExpVBs]),
do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout());
do_expect({inform, true}, ExpVBs) ->
- io:format("~w:do_expect(inform, true) -> entry with"
- "~n ExpVBs: ~p"
- "~n", [?MODULE, ExpVBs]),
Check =
fun(PDU, ok) ->
RespPDU = PDU#pdu{type = 'get-response',
@@ -847,6 +835,9 @@ do_expect({inform, true}, ExpVBs) ->
(_, Err) ->
Err
end,
+ io:format("EXPECT 'inform-request' (true)"
+ "~n with"
+ "~n Varbinds: ~p~n", [ExpVBs]),
do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout());
do_expect({inform, {error, EStat, EIdx}}, ExpVBs)
@@ -861,6 +852,11 @@ do_expect({inform, {error, EStat, EIdx}}, ExpVBs)
(_, Err) ->
Err
end,
+ io:format("EXPECT 'inform-request' (error)"
+ "~n with"
+ "~n Error Status: ~p"
+ "~n Error Index: ~p"
+ "~n Varbinds: ~p~n", [EStat, EIdx, ExpVBs]),
do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()).
@@ -871,6 +867,12 @@ do_expect(Err, Idx, ExpVBs, To)
when is_atom(Err) andalso
(is_integer(Idx) orelse is_list(Idx) orelse (Idx == any)) ->
Check = fun(_, R) -> R end,
+ io:format("EXPECT 'get-response'"
+ "~n with"
+ "~n Error: ~p"
+ "~n Index: ~p"
+ "~n Varbinds: ~p"
+ "~n within ~w~n", [Err, Idx, ExpVBs, To]),
do_expect2(Check, 'get-response', Err, Idx, ExpVBs, To).
@@ -878,15 +880,13 @@ do_expect(Type, Enterp, Generic, Specific, ExpVBs) ->
do_expect(Type, Enterp, Generic, Specific, ExpVBs, 3500).
do_expect(trap, Enterp, Generic, Specific, ExpVBs, To) ->
- io:format("~w:do_expect(trap) -> entry with"
- "~n Enterp: ~w"
- "~n Generic: ~w"
- "~n Specific: ~w"
- "~n ExpVBs: ~w"
- "~n To: ~w"
- "~nwhen"
- "~n Time: ~w"
- "~n", [?MODULE, Enterp, Generic, Specific, ExpVBs, To, t()]),
+ io:format("EXPECT trap"
+ "~n with"
+ "~n Enterp: ~w"
+ "~n Generic: ~w"
+ "~n Specific: ~w"
+ "~n Varbinds: ~w"
+ "~n within ~w~n", [Enterp, Generic, Specific, ExpVBs, To]),
PureE = purify_oid(Enterp),
case receive_trap(To) of
#trappdu{enterprise = PureE,
@@ -916,49 +916,51 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
(is_list(ExpVBs) orelse (ExpVBs =:= any)) andalso
(is_integer(To) orelse (To =:= infinity)) ->
- io:format("~w:do_expect2 -> entry with"
- "~n Type: ~w"
- "~n Err: ~w"
- "~n Idx: ~w"
- "~n ExpVBs: ~w"
- "~n To: ~w"
- "~nwhen"
- "~n Time: ~w"
- "~n", [?MODULE, Type, Err, Idx, ExpVBs, To, t()]),
-
case receive_pdu(To) of
#pdu{type = Type,
error_status = Err,
error_index = Idx} when ExpVBs =:= any ->
+ io:format("EXPECT received expected pdu (1)~n", []),
ok;
#pdu{type = Type,
request_id = ReqId,
error_status = Err2,
error_index = Idx} when ExpVBs =:= any ->
+ io:format("EXPECT received expected pdu with "
+ "unexpected error status (2): "
+ "~n Error Status: ~p~n", [Err2]),
{error, {unexpected_error_status, Err, Err2, ReqId}};
#pdu{error_status = Err} when (Type =:= any) andalso
(Idx =:= any) andalso
(ExpVBs =:= any) ->
+ io:format("EXPECT received expected pdu (3)~n", []),
ok;
#pdu{request_id = ReqId,
error_status = Err2} when (Type =:= any) andalso
(Idx =:= any) andalso
(ExpVBs =:= any) ->
+ io:format("EXPECT received expected pdu with "
+ "unexpected error status (4): "
+ "~n Error Status: ~p~n", [Err2]),
{error, {unexpected_error_status, Err, Err2, ReqId}};
#pdu{type = Type,
error_status = Err} when (Idx =:= any) andalso
(ExpVBs =:= any) ->
+ io:format("EXPECT received expected pdu (5)~n", []),
ok;
#pdu{type = Type,
request_id = ReqId,
error_status = Err2} when (Idx =:= any) andalso
(ExpVBs =:= any) ->
+ io:format("EXPECT received expected pdu with "
+ "unexpected error status (6): "
+ "~n Error Status: ~p~n", [Err2]),
{error, {unexpected_error_status, Err, Err2, ReqId}};
#pdu{type = Type,
@@ -967,8 +969,13 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) ->
case lists:member(EI, Idx) of
true ->
+ io:format("EXPECT received expected pdu with "
+ "expected error index (7)~n", []),
ok;
false ->
+ io:format("EXPECT received expected pdu with "
+ "unexpected error index (8): "
+ "~n Error Index: ~p~n", [EI]),
{error, {unexpected_error_index, EI, Idx, ReqId}}
end;
@@ -978,8 +985,15 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) ->
case lists:member(EI, Idx) of
true ->
+ io:format("EXPECT received expected pdu with "
+ "unexpected error status (9): "
+ "~n Error Status: ~p~n", [Err2]),
{error, {unexpected_error_status, Err, Err2, ReqId}};
false ->
+ io:format("EXPECT received expected pdu with "
+ "unexpected error (10): "
+ "~n Error Status: ~p"
+ "~n Error index: ~p~n", [Err2, EI]),
{error, {unexpected_error, {Err, Idx}, {Err2, EI}, ReqId}}
end;
@@ -987,6 +1001,12 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
request_id = ReqId,
error_status = Err2,
error_index = Idx2} when ExpVBs =:= any ->
+ io:format("EXPECT received unexpected pdu with (11) "
+ "~n Type: ~p"
+ "~n ReqId: ~p"
+ "~n Errot status: ~p"
+ "~n Error index: ~p"
+ "~n", [Type2, ReqId, Err2, Idx2]),
{error,
{unexpected_pdu,
{Type, Err, Idx}, {Type2, Err2, Idx2}, ReqId}};
@@ -995,11 +1015,26 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
error_status = Err,
error_index = Idx,
varbinds = VBs} = PDU ->
+ io:format("EXPECT received pdu (12): "
+ "~n [exp] Type: ~p"
+ "~n [exp] Error Status: ~p"
+ "~n [exp] Error Index: ~p"
+ "~n VBs: ~p"
+ "~nwhen"
+ "~n ExpVBs: ~p"
+ "~n", [Type, Err, Idx, VBs, ExpVBs]),
Check(PDU, check_vbs(purify_oids(ExpVBs), VBs));
#pdu{type = Type,
error_status = Err,
varbinds = VBs} = PDU when Idx =:= any ->
+ io:format("EXPECT received pdu (13): "
+ "~n [exp] Type: ~p"
+ "~n [exp] Error Status: ~p"
+ "~n VBs: ~p"
+ "~nwhen"
+ "~n ExpVBs: ~p"
+ "~n", [Type, Err, VBs, ExpVBs]),
Check(PDU, check_vbs(purify_oids(ExpVBs), VBs));
#pdu{type = Type,
@@ -1007,6 +1042,15 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
error_status = Err,
error_index = EI,
varbinds = VBs} = PDU when is_list(Idx) ->
+ io:format("EXPECT received pdu (14): "
+ "~n [exp] Type: ~p"
+ "~n ReqId: ~p"
+ "~n [exp] Error Status: ~p"
+ "~n [exp] Error Index: ~p"
+ "~n VBs: ~p"
+ "~nwhen"
+ "~n ExpVBs: ~p"
+ "~n", [Type, ReqId, Err, EI, VBs, ExpVBs]),
PureVBs = purify_oids(ExpVBs),
case lists:member(EI, Idx) of
true ->
@@ -1020,6 +1064,13 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
error_status = Err2,
error_index = Idx2,
varbinds = VBs2} ->
+ io:format("EXPECT received unexpected pdu with (15) "
+ "~n Type: ~p"
+ "~n ReqId: ~p"
+ "~n Errot status: ~p"
+ "~n Error index: ~p"
+ "~n Varbinds: ~p"
+ "~n", [Type2, ReqId, Err2, Idx2, VBs2]),
{error,
{unexpected_pdu,
{Type, Err, Idx, purify_oids(ExpVBs)},
@@ -1027,6 +1078,9 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To)
ReqId}};
Error ->
+ io:format("EXPECT received error (16): "
+ "~n Error: ~p"
+ "~n", [Error]),
Error
end.
@@ -1167,30 +1221,44 @@ stop_node(Node) ->
%%% Configuration
%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
+config(Vsns, MgrDir, AgentConfDir, MIp, AIp) ->
+ ?LOG("config -> entry with"
+ "~n Vsns: ~p"
+ "~n MgrDir: ~p"
+ "~n AgentConfDir: ~p"
+ "~n MIp: ~p"
+ "~n AIp: ~p",
+ [Vsns, MgrDir, AgentConfDir, MIp, AIp]),
+ ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsns,
+ MIp, ?TRAP_UDP, AIp, 4000,
"test"),
- ?line case update_usm(Vsns, AgentDir) of
+ ?line case update_usm(Vsns, AgentConfDir) of
true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ ?line copy_file(filename:join(AgentConfDir, "usm.conf"),
filename:join(MgrDir, "usm.conf")),
?line update_usm_mgr(Vsns, MgrDir);
false ->
?line ok
end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
+ ?line update_community(Vsns, AgentConfDir),
+ ?line update_vacm(Vsns, AgentConfDir),
+ ?line write_target_addr_conf(AgentConfDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentConfDir, Vsns),
+ ?line write_notify_conf(AgentConfDir),
ok.
delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
+ AgentDir = ?config(agent_dir, Config),
+ delete_files(AgentDir, [db, conf]).
+
+delete_files(_AgentFiles, []) ->
+ ok;
+delete_files(AgentDir, [DirName|DirNames]) ->
+ Dir = filename:join(AgentDir, DirName),
+ {ok, Files} = file:list_dir(Dir),
lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
+ Files),
+ delete_files(AgentDir, DirNames).
update_usm(Vsns, Dir) ->
case lists:member(v3, Vsns) of
@@ -1348,8 +1416,8 @@ rewrite_target_addr_conf2(_NewPort,O) ->
O.
reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
+ ?line ok = file:rename(filename:join(Dir, "target_addr.old"),
+ filename:join(Dir, "target_addr.conf")).
write_target_params_conf(Dir, Vsns) ->
F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv};
@@ -1388,7 +1456,6 @@ copy_file(From, To) ->
ok = file:write_file(To, Bin).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
display_memory_usage() ->
@@ -1466,7 +1533,7 @@ rpc(Node, F, A) ->
%%
%%
%% t() ->
-%% {A,B,C} = erlang:now(),
+%% {A,B,C} = os:timestamp(),
%% A*1000000000+B*1000+(C div 1000).
%%
%%
@@ -1478,6 +1545,6 @@ rpc(Node, F, A) ->
%% Time in milli seconds
-t() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
+%% t() ->
+%% {A,B,C} = os:timestamp(),
+%% A*1000000000+B*1000+(C div 1000).
diff --git a/lib/snmp/test/snmp_agent_v1_test.erl b/lib/snmp/test/snmp_agent_v1_test.erl
deleted file mode 100644
index 737bb25cc3..0000000000
--- a/lib/snmp/test/snmp_agent_v1_test.erl
+++ /dev/null
@@ -1,2673 +0,0 @@
-%%
-%% %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%
-%%
-
--module(snmp_agent_v1_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
--export([]).
-
--define(application, snmp).
-
--include_lib("kernel/include/file.hrl").
--include("test_server.hrl").
--include("snmp_test_lib.hrl").
--define(SNMP_USE_V3, true).
--include_lib("snmp/include/snmp_types.hrl").
-
-
--define(klas1, [1,3,6,1,2,1,7]).
--define(klas2, [1,3,6,1,2,1,9]).
--define(klas3, [1,3,6,1,2,1,8,1]).
--define(klas4, [1,3,6,1,2,1,8,4]).
--define(sa, [1,3,6,1,4,1,193,2]).
--define(system, [1,3,6,1,2,1,1]).
--define(snmp, [1,3,6,1,2,1,11]).
--define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
--define(ericsson, [1,3,6,1,4,1,193]).
--define(testTrap, [1,3,6,1,2,1,15,0]).
--define(xDescr, [1,3,6,1,2,1,17,1]).
--define(xDescr2, [1,3,6,1,2,1,17,2]).
-
--define(active, 1).
--define(notInService, 2).
--define(notReady, 3).
--define(createAndGo, 4).
--define(createAndWait, 5).
--define(destroy, 6).
-
--define(TRAP_UDP, 5000).
-
--define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
-
-
-%% -- test manager defines --
--define(MGR, snmp_test_mgr).
--define(GN(X), ?MGR:gn(X)).
--define(G(X), ?MGR:g(X)).
--define(S(X), ?MGR:s(X)).
--define(GB(X), ?MGR:gb(X)).
--define(SEND_BYTES(X), ?MGR:send_bytes(X)).
-
-%% -- agent test lib defines --
--define(LIB, snmp_agent_test_lib).
--define(INIT_CASE(X), ?LIB:init_case(X)).
--define(TRY_TEST1(A), ?LIB:try_test(A)).
--define(TRY_TEST2(A, B), ?LIB:try_test(A, B)).
--define(TRY_TEST3(A, B, C), ?LIB:try_test(A, B, C)).
--define(START_SA(A, B, C), ?LIB:start_subagent(A, B, C)).
--define(STOP_SA(A), ?LIB:stop_subagent(A)).
--define(P1(C), ?LIB:p(C)).
--define(P2(F), ?LIB:p(F,[])).
--define(P3(F,A), ?LIB:p(F,A)).
--define(RPC(N, F, A), ?LIB:rpc(N, F, A)).
-
-
--define(v1_2(V1,V2),
- case get(vsn) of
- v1 -> V1;
- _ -> V2
- end).
-
--define(v1_2_3(V1,V2,V3),
- case get(vsn) of
- v1 -> V1;
- v2 -> V2;
- _ -> V3
- end).
-
-all(suite) -> {req,
- [mnesia, distribution,
- {local_slave_nodes, 2}, {time, 360}],
- [{conf, init, cases(), finish}]}.
-
-init_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- [simple,
- db_notify_client,
- processing,
- big,
- big2,
- %% implied,
- loop_mib,
- api,
- subagent,
- mnesia,
- multiple_reqs,
- sa_register,
- v1_trap,
- sa_error,
- next_across_sa,
- undo,
- standard_mibs,
- sparse_table,
- cnt_64,
- opaque,
- %% opaque].
-
- change_target_addr_config,
-
- reported_bugs,
- tickets
- ].
-
-
-init(Config) ->
- init_all(Config),
- init_v1(Config).
-
-finish(Config) ->
- finish_v1(Config),
- finish_all(Config).
-
-init_v1(Config) when list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v1} | start_v1_agent(Config)].
-
-finish_v1(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%%-----------------------------------------------------------------
-%% This function takes care of the old OTP-SNMPEA-MIB.
-%% Unfortunately, the testcases were written to use the data in the
-%% internal tables, and these table are now obsolete and not used
-%% by the agent. Therefore, we emulate them by using
-%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
-%%
-%% These two rows must exist in intCommunityTable
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
-%% (But with the manager's IP address)
-%%
-%%-----------------------------------------------------------------
-init_old() ->
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [6 | "public"],
- {get(mip), "public", 2, 2}),
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [13 | "standard trap"],
- {get(mip), "standard trap", 2, 1}),
- snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
-
-
-%% =========================================================================
-%%
-%% C A S E S
-%%
-%% =========================================================================
-
-%% -- simple --
-
-simple(suite) -> [];
-simple(Config) when list(Config) ->
- ?P1(simple),
- ?INIT_CASE(Config),
-
- ?TRY_TEST1(simple_standard_test).
-
-simple_standard_test() ->
- ?DBG("simple_standard_test -> entry",[]),
- ?GN([[1,1]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[1,3]]),
- ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[1,3,6]]),
- ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[1,3,6,1]]),
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[1,3,6,1,2]]),
- ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[1,3,6,1,2,1]]),
- ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[1,3,6,1,2,1,1]]),
- ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?GN([[sysDescr]]),
- ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?G([[sysDescr,0]]),
- ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
-
- ?G([[sysDescr]]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{[sysDescr], noSuchObject}])),
-
- ?G([[1,6,7,0]]),
- ?line ?v1_2(expect(41, noSuchName, 1, any),
- expect(3, [{[1,6,7,0], noSuchObject}])),
-
- ?GN([[1,13]]),
- ?line ?v1_2(expect(4, noSuchName,1, any),
- expect(4, [{[1,13], endOfMibView}])),
-
- ?S([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?G([[sysLocation, 0]]),
- ?line expect(6, [{[sysLocation, 0], "new_value"}]),
-
- io:format("Testing noSuchName and badValue...~n"),
- ?S([{[sysServices,0], 3}]),
- ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
-
- ?S([{[sysLocation, 0], i, 3}]),
- ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
- ?DBG("simple_standard_test -> done",[]),
- ok.
-
-
-%% -- db_notify_client --
-
-%% This is run in the agent node
-db_notify_client(suite) -> [];
-db_notify_client(Config) when list(Config) ->
- ?P1(db_notify_client),
- {SaNode, MgrNode, MibDir} = ?INIT_CASE(Config),
- ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
- [SaNode,MgrNode,MibDir]),
- snmpa_local_db:register_notify_client(self(),?MODULE),
-
- %% This call (the manager) will issue to set operations, so
- %% we expect to receive to notify(insert) calls.
- ?TRY_TEST1(db_notify_client_test),
-
- ?DBG("await first notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
- end,
-
- ?DBG("await second notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
- end,
-
- snmpa_local_db:unregister_notify_client(self()).
-
-
-%% This is run in the manager node
-db_notify_client_test() ->
- ?DBG("set first new sysLocation",[]),
- ?S([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?DBG("set second new sysLocation",[]),
- ?S([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]).
-
-notify(Pid,What) ->
- ?DBG("notify(~p,~p) -> called",[Pid,What]),
- Pid ! {db_notify_test_reply,What}.
-
-
-%% -- processing --
-
-%% Req. Test2
-processing(suite) -> [];
-processing(Config) when list(Config) ->
- ?P1(processing),
- ?INIT_CASE(Config),
-
- ?line load_master("Test2"),
- ?TRY_TEST1(v1_proc),
- ?line unload_master("Test2").
-
-v1_proc() ->
- ?DBG("v1_proc -> entry", []),
- %% According to RFC1157.
- %% Template: <Section>:<list no>
- v1_get_p(),
- v1_get_next_p(),
- v1_set_p().
-
-v1_get_p() ->
- %% 4.1.2:1
- ?G([[test2]]),
- ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
- ?G([[tDescr]]),
- ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
- ?G([[tDescr2,0]]),
- ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
- ?G([[tDescr3,0]]),
- ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
- ?G([[tDescr4,0]]),
- ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
- ?G([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
- {[tDescr,0], 'NULL'}]),
- ?G([[sysDescr,3]]),
- ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
-
- %% 4.1.2:2
- ?G([[tTable]]),
- ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
- ?G([[tEntry]]),
- ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
-
- %% 4.1.2:3
- ?G([[tTooBig, 0]]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.2:4
- ?G([[tGenErr1, 0]]),
- ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- ?G([[tGenErr2, 0]]),
- ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- ?G([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]).
-
-v1_get_next_p() ->
- %% 4.1.3:1
- ?GN([[1,3,7,1]]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
-
- ?GN([[tDescr2]]),
- ?line expect(11, tooBig, 0, any),
-
- %% 4.1.3:2
- ?GN([[tTooBig]]),
- io:format("We currently don't handle tooBig correct!!!\n"),
- %% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
- ?line expect(20, tooBig, 0, any),
-
- %% 4.1.3:3
- ?GN([[tGenErr1]]),
- %% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
- ?line expect(40, genErr, 1, any),
-
- ?GN([[tGenErr2]]),
- %% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
- ?line expect(41, genErr, 1, any),
-
- ?GN([[sysDescr], [tGenErr3]]),
- %% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
- %% {[tGenErr3], 'NULL'}]).
- ?line expect(42, genErr, 2, any).
-
-v1_set_p() ->
- %% 4.1.5:1
- ?S([{[1,3,7,0], i, 4}]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
-
- ?S([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
-
- ?S([{[tDescr3,0], s, "read-only"}]),
- ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
-
- ?S([{[tDescr3], s, "noSuchObject"}]),
- ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
-
- ?S([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
-
- ?S([{[tDescr2,0], s, "inconsistentName"}]),
- ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
-
- %% 4.1.5:2
- ?S([{[tDescr2, 0], i, 4}]),
- ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
-
- ?S([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.1.5:3
- %% The standard is quite incorrect here. The resp pdu was too big. In
- %% the resp pdu, we have the original vbs. In the tooBig pdu we still
- %% have to original vbs => the tooBig pdu is too big as well!!! It
- %% may not get it to the manager, unless the agent uses 'NULL' instead
- %% of the std-like original value.
- ?S([{[tTooBig, 0], s, ?tooBigStr}]),
- %% according to std:
- %% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.5:4
- ?S([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
-
- ?S([{[tDescr2, 0], s, "commit_fail"}]),
- ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
-
-
-%% -- big --
-
-big(suite) -> [];
-big(Config) when list(Config) ->
- ?P1(big),
- {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1"),
- ?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- ?TRY_TEST1(big_test),
-
- ?line ?STOP_SA(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req: system group, OLD-SNMPEA-MIB, Klas1
-big_test() ->
- ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
- simple_standard_test(),
-
- ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
- ?GN([[klas1]]),
- ?line expect(1, [{[fname,0], ""}]),
-
- ?G([[fname,0]]),
- ?line expect(2, [{[fname,0], ""}]),
-
- ?S([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
-
- ?G([[fname,0]]),
- ?line expect(4, [{[fname,0], "test set"}]),
-
- ?DBG("big_test -> "
- "testing next from last instance in master to subagent...",[]),
- ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname,0], "test set"}]),
-
- ?GN([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname,0], "test set"}]),
- ?S([{[fname,0], s, ""}]),
- ?line expect(52, [{[fname,0], ""}]),
-
- table_test(),
-
- ?DBG("big_test -> adding one row in subagent table",[]),
- _FTab = [friendsEntry],
- ?S([{[friendsEntry, [2, 3]], s, "kompis3"},
- {[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
-
- ?G([[friendsEntry, [2, 3]],
- [friendsEntry, [3, 3]]]),
- ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?active}]),
-
- ?S([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
-
- otp_1131(),
-
- ?DBG("big_test -> adding two rows in subagent table with special INDEX",
- []),
- ?S([{[kompissEntry, [1, 3]], s, "kompis3"},
- {[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?createAndGo}]),
-
- ?G([[kompissEntry, [1, 3]],
- [kompissEntry, [2, 3]]]),
- ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
-
- ?GN([[kompissEntry, [1]],
- [kompissEntry, [2]]]),
- ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
-
- ?S([{[kompissEntry, [1, 2]], s, "kompis3"},
- {[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?createAndGo}]),
-
- ?GN([[kompissEntry, [1, 1]],
- [kompissEntry, [2, 1]]]),
- ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?active}]),
-
- ?S([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
-
- ?S([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
- ?DBG("big_test -> done",[]),
- ok.
-
-
-%% Req. system group, Klas2, OLD-SNMPEA-MIB
-big_test_2() ->
- ?P1(big_test_2),
-
- ?P2("Testing simple next/get/set @ master agent (2)..."),
- simple_standard_test(),
-
- p("Testing simple next/get/set @ subagent (2)..."),
- ?GN([[klas2]]),
- ?line expect(1, [{[fname2,0], ""}]),
-
- ?G([[fname2,0]]),
- ?line expect(2, [{[fname2,0], ""}]),
-
- ?S([{[fname2,0], s, "test set"}]),
- ?line expect(3, [{[fname2,0], "test set"}]),
-
- ?G([[fname2,0]]),
- ?line expect(4, [{[fname2,0], "test set"}]),
-
- otp_1298(),
-
- ?P2("Testing next from last object in master to subagent (2)..."),
- ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname2,0], "test set"}]),
-
- ?GN([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname2,0], "test set"}]),
-
- table_test(),
-
- ?P2("Adding one row in subagent table (2)"),
- ?S([{[friendsEntry2, [2, 3]], s, "kompis3"},
- {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?createAndGo}]),
-
- ?G([[friendsEntry2, [2, 3]],
- [friendsEntry2, [3, 3]]]),
- ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?active}]),
-
- ?S([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
-
- ?P2("Adding two rows in subagent table with special INDEX (2)"),
- ?S([{[kompissEntry2, [1, 3]], s, "kompis3"},
- {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?createAndGo}]),
- ?G([[kompissEntry2, [1, 3]],
- [kompissEntry2, [2, 3]]]),
- ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- ?GN([[kompissEntry2, [1]],
- [kompissEntry2, [2]]]),
- ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
-
- ?S([{[kompissEntry2, [1, 2]], s, "kompis3"},
- {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?createAndGo}]),
-
- ?GN([[kompissEntry2, [1, 1]],
- [kompissEntry2, [2, 1]]]),
- ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?active}]),
-
- ?S([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
-
- ?S([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
- ok.
-
-
-%% -- bug2 --
-
-big2(suite) -> [];
-big2(Config) when list(Config) ->
- ?P1(big2),
- %% This is exactly the same tests as 'big', but with the
- %% v2 equivalent of the mibs.
- {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
-
- ?P2("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
-
- ?TRY_TEST1(big_test),
-
- ?line ?STOP_SUBAGENT(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
-
-
-implied(suite) -> [];
-implied(Config) when list(Config) ->
- ?P1(implied),
- ?INIT_CASE(Config),
-
- ?line load_master("Test1"),
-
- ?TRY_TEST2(implied_test,[whereis(snmp_master_agent)]),
-
- ?line unload_master("Test1").
-
-%% Req. Test1
-implied_test(MA) ->
- ?LOG("implied_test -> start",[]),
-
- snmpa:verbosity(MA,trace),
- snmpa:verbosity(MA,trace),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = "apa",
- Idx2 = "qq",
-
- ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
- ?S([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
- ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
- {[testDescr, Idx1], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
-
- ?S([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
- ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
- {[testDescr, Idx2], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr)",[]),
-
- ?GN([[testDescr]]),
- ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
-
- ?GN([[testDescr,Idx1]]),
- ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
- ?S([{[testStatus, Idx1], i, ?destroy}]),
- ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
-
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
- ?S([{[testStatus, Idx2], i, ?destroy}]),
- ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
-
- %% Try the same in other table
- Idx3 = [1, "apa"],
- Idx4 = [1, "qq"],
- ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
- ?S([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
- ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
- {[testDescr2, Idx3], "row 1"}]),
-
- ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
- ?S([{[testStatus2, Idx4], i, ?createAndGo},
- {[testDescr2,Idx4],s,"row 2"}]),
- ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
- {[testDescr2, Idx4], "row 2"}]),
-
- ?DBG("implied_test -> get-next(testDescr2)",[]),
- ?GN([[testDescr2]]),
- ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
-
- ?GN([[testDescr2,Idx3]]),
- ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
- ?S([{[testStatus2, Idx3], i, ?destroy}]),
- ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
-
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
- ?S([{[testStatus2, Idx4], i, ?destroy}]),
- ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
-
- snmpa:verbosity(MA,log),
-
- ?LOG("implied_test -> done",[]).
-
-
-%% -- loop_mib --
-
-%%-----------------------------------------------------------------
-%% Loop through entire MIB, to make sure that all instrum. funcs
-%% works.
-%% Load all std mibs that are not loaded by default.
-%%-----------------------------------------------------------------
-loop_mib(suite) -> [];
-loop_mib(Config) when list(Config) ->
- ?P1(loop_mib),
- %% snmpa:verbosity(master_agent,debug),
- %% snmpa:verbosity(mib_server,info),
- {SaNode, MgrNode, MibDir} = ?INIT_CASE(Config),
- ?DBG("loop_mib -> "
- "~n SaNode: ~p"
- "~n MgrNode: ~p"
- "~n MibDir: ~p", [SaNode, MgrNode, MibDir]),
-
- ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?DBG("loop_mib -> try",[]),
-
- ?TRY_TEST1(loop_mib),
-
- ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- %% snmpa:verbosity(master_agent,log),
- %% snmpa:verbosity(mib_server,silence),
- ?LOG("loop_mib -> done",[]).
-
-%% Req. As many mibs all possible
-loop_mib() ->
- ?DBG("loop_mib -> entry",[]),
- N = loop_it([1,1], 0),
- ?P3("found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-loop_it(Oid, N) ->
- ?DBG("loop_it -> entry with"
- "~n Oid: ~p"
- "~n N: ~p", [Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it -> "
- "~n NOid: ~p"
- "~n Value: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_1 -> "
- "~n Value2: ~p",[Value2]),
- loop_it(NOid, N+1);
-
- #pdu{type='get-response', error_status=noSuchName, error_index=1,
- varbinds=[_]} ->
- ?DBG("loop_it -> done",[]),
- N;
-
- #pdu{type = Type, error_status = Err, error_index = Idx,
- varbinds = Vbs} ->
- exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
-
- end.
-
-
-%% -- api --
-
-api(suite) -> [];
-api(Config) when list(Config) ->
- ?P1(api),
- ?INIY_CASE(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- ?TRY_TEST2(api_test, [node()]),
-
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-api_test(MaNode) ->
- ?line {value, OID} = ?RPC(MaNode, name_to_oid, [intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = ?RPC(MaNode, oid_to_name, [OID]),
- ?line false = ?RPC(MaNode, name_to_oid, [intAgentIpAddres]),
- ?line false = ?RPC(MaNode, oid_to_name, [[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = ?RPC(MaNode, enum_to_int, [intViewType, excluded]),
- ?line {value, excluded} = ?RPC(MaNode, int_to_enum, [intViewType, 2]),
- ?line false = ?RPC(MaNode, enum_to_int, [intViewType, exclude]),
- ?line false = ?RPC(MaNode, enum_to_int, [intAgentIpAddress, exclude]),
- ?line false = ?RPC(MaNode, enum_to_int, [intAgentIpAddre, exclude]),
- ?line false = ?RPC(MaNode, int_to_enum, [intViewType, 3]),
- ?line false = ?RPC(MaNode, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = ?RPC(MaNode, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = ?RPC(MaNode, int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} =
- ?RPC(MaNode, enum_to_int, ['RowStatus', destroy]),
- ?line false = ?RPC(MaNode, enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = ?RPC(MaNode, enum_to_int, ['xxRowStatus', destroy]),
- ?line false = ?RPC(MaNode, int_to_enum, ['RowStatus', 25]),
- ?line false = ?RPC(MaNode, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
- List when list(List), length(List) == 8 -> ok;
- List when list(List), length(List) == 11 -> ok
- end.
-
-
-%% -- subagent --
-
-subagent(suite) -> [];
-subagent(Config) when list(Config) ->
- ?P1(subagent),
- {SaNode, _MgrNode, MibDir} = ?INIT_CASE(Config),
-
- ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1"),
-
- ?TRY_TEST1(load_test_sa),
-
- ?P2("Testing unregister subagent [~w]...", [SA]),
- MA = whereis(snmp_master_agent),
- ?RPC(SaNode, unregister_subagent, [MA, SA]),
- ?TRY_TEST1(unreg_test),
-
- ?P2("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
- ?TRY_TEST1(load_test),
-
- ?P2("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
-
- ?TRY_TEST1(unreg_test),
-
- ?P2("Testing register subagent..."),
- ?RPC(SaNode, register_subagent, [MA, ?klas1, SA]),
- ?TRY_TEST1(load_test_sa),
-
- ?line ?STOP_SA(SA),
- ?TRY_TEST1(unreg_test).
-
-%% Req. Klas1
-load_test_sa() ->
- ?GN([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line expect(1, [{[fname,0], any}]).
-
-unreg_test() ->
- ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[snmpInPkts, 0], any}]).
-
-load_test() ->
- ?GN([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[fname,0], ""}]).
-
-
-%% -- mnesia --
-
-mnesia(suite) -> [];
-mnesia(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent with mnesia impl..."),
- {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- ?TRY_TEST1(big_test_2),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- ?TRY_TEST1(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
-
-
-%% -- multiple_reqs --
-
-multiple_reqs(suite) ->
- {req, [], {conf, init_mul, mul_cases(), finish_mul}}.
-
-mul_cases() ->
- [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err].
-
-init_mul(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- [{mul_sub, SA} | Config].
-
-finish_mul(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- SA = ?config(mul_sub, Config),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
- lists:keydelete(mul_sub, 1, Config).
-
-
-%% -- mul_get --
-
-mul_get(suite) -> [];
-mul_get(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get..."),
- ?TRY_TEST1(do_mul_get).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_get() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
- [sysName,0]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,0], "test"}]),
- g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
- ?line ?v1_2(expect(2, noSuchName, [1,4], any),
- expect(2, [{[1,3,7,1], noSuchObject},
- {Key1c4, 2},
- {[sysDescr,0], "Erlang SNMP agent"},
- {[1,3,7,2], noSuchObject},
- {Key1c3, 2},
- {[sysDescr,0], "Erlang SNMP agent"}])).
-
-
-%% -- mul_get_err --
-
-mul_get_err(suite) -> [];
-mul_get_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get with error..."),
- ?TRY_TEST1(do_mul_get_err).
-
-%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
-do_mul_get_err() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(expect(1, noSuchName, 5, any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,2], noSuchInstance}])),
- g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname3,0], noSuchObject},
- {Key1c3, 2},
- {[sysName,1], noSuchInstance}])).
-
-
-%% -- mul_next --
-
-mul_next(suite) -> [];
-mul_next(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- ?TRY_TEST1(do_mul_next).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2}, {[fname,0], "test set"},
- {Key1c3, 2}, {[sysName,0], "test"}]).
-
-
-%% -- mul_next_err --
-
-mul_next_err(suite) -> [];
-mul_next_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- ?TRY_TEST1(do_mul_next_err).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next_err() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[1,3,6,999], endOfMibView},
- {[fname,0], "test set"},
- {[1,3,90], endOfMibView},
- {Key1c3, 2},
- {[sysName,0], "test"}])).
-
-
-%% -- mul_set --
-
-mul_set(suite) -> [];
-mul_set(Config) when list(Config) ->
- ?P(mul_set),
- ?INIT_CASE(Config),
-
- ?TRY_TEST1(do_mul_set).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set() ->
- p("Adding one row in subagent table, and one in master table"),
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [sysLocation,0],
- [friendsEntry, [3, 3]]]),
- ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
- {[sysLocation,0], "new_value"},
- {[friendsEntry, [3, 3]], ?active}]),
- g([NewKeyc4]),
- ?line expect(3, [{NewKeyc4, 2}]),
- s([{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]),
- ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]).
-
-
-%% -- mul_set_err --
-
-mul_set_err(suite) -> [];
-mul_set_err(Config) when list(Config) ->
- ?P(mul_set_err),
- ?INIT_CASE(Config),
-
- ?TRY_TEST1(do_mul_set_err).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- p("Adding one row in subagent table, and one in master table"),
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {NewKeyc3, 2},
- {[sysUpTime,0], 45}, % sysUpTime (readOnly)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
- g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
- g([NewKeyc4]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{NewKeyc4, noSuchInstance}])).
-
-
-%% -- sa_register --
-
-sa_register(suite) -> [];
-sa_register(Config) when list(Config) ->
- ?P1(sa_register),
- {SaNode, _MgrNode, MibDir} = ?INIT_CASE(Config),
-
- ?DBG("sa_register -> start subagent", []),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
-
- ?DBG("sa_register -> unregister subagent", []),
- ?P2("Testing unregister subagent (2)..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- ?TRY_TEST1(unreg_test),
-
- ?P2("Loading SA-MIB..."),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
- ?DBG("sa_register -> register subagent", []),
- rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
- ?TRY_TEST1(sa_mib),
-
- ?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
-
-%% Req. SA-MIB
-sa_mib() ->
- g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
- s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
-
-
-%% -- v1_trap --
-
-v1_trap(suite) -> [];
-v1_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- ?TRY_TEST2(ma_trap1, [MA]),
- ?TRY_TEST2(ma_trap2, [MA]),
- ?TRY_TEST2(ma_v2_2_v1_trap, [MA]),
- ?TRY_TEST2(ma_v2_2_v1_trap2, [MA]),
-
- p("Testing trap sending from subagent..."),
- ?TRY_TEST2(sa_trap1, [SA]),
- ?TRY_TEST2(sa_trap2, [SA]),
- ?TRY_TEST2(sa_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-ma_trap1(MA) ->
- snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
- snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
-
-ma_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap2(MA) ->
- snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
- {ifAdminStatus, [1], 1},
- {ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
-
-sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
-
-ma_v2_trap1(MA) ->
- ?DBG("ma_v2_traps -> entry with MA = ~p => "
- "send standard trap: testTrapv22",[MA]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
- snmpa:send_trap(MA, testTrapv21, "standard trap"),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmp ++ [1]}]).
-
-ma_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
-
-ma_v1_2_v2_trap(MA) ->
- snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
- {[ifIndex, 1], 1},
- {[snmpTrapEnterprise, 0], [1,2,3]}]).
-
-
-ma_v1_2_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"},
- {[snmpTrapEnterprise, 0], ?system}]).
-
-
-sa_v1_2_v2_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-sa_v1_2_v2_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-sa_v1_2_v2_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-%% -- sa_error --
-
-sa_error(suite) -> [];
-sa_error(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing sa bad value (is_set_ok)..."),
- ?TRY_TEST1(sa_errs_bad_value),
-
- p("Testing sa gen err (set)..."),
- ?TRY_TEST1(sa_errs_gen_err),
-
- p("Testing too big..."),
- ?TRY_TEST1(sa_too_big),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- stop_subagent(SA).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_bad_value() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 5}, % badValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, badValue, 2, any),
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
- g([NewKeyc4]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_gen_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},{NewKeyc4, 2},
- {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line expect(1, genErr, 4, any),
-% The row might have been added; we don't know.
-% (as a matter of fact we do - it is added, because the agent
-% first sets its own vars, and then th SAs. Lets destroy it.
- s([{NewKeyc5, ?destroy}]),
- ?line expect(2, [{NewKeyc5, ?destroy}]).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_too_big() ->
- g([[sa, [4,0]]]),
- ?line expect(1, tooBig).
-
-
-%% -- next_across_sa --
-
-next_across_sa(suite) -> [];
-next_across_sa(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Loading another subagent mib..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
-
- rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
- ?TRY_TEST1(load_test_sa),
-
- p("Testing next across subagent (endOfMibView from SA)..."),
- ?TRY_TEST1(next_across_sa),
-
- p("Unloading mib"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- ?TRY_TEST1(unreg_test),
-
- p("Starting another subagent"),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
- p("Testing next across subagent (wrong prefix from SA)..."),
- ?TRY_TEST1(next_across_sa),
-
- stop_subagent(SA),
- stop_subagent(SA2).
-
-%% Req. Klas1, system group, snmp group (v1/v2)
-next_across_sa() ->
- gn([[sysDescr],[klas1,5]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {[snmpInPkts, 0], any}]).
-
-
-%% -- undo --
-
-undo(suite) -> [];
-undo(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing undo phase at master agent..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
- ?TRY_TEST1(undo_test),
- ?TRY_TEST1(api_test2),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
-
- p("Testing bad return values from instrum. funcs..."),
- ?TRY_TEST1(bad_return),
-
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
-
- p("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
- ?TRY_TEST1(undo_test),
- ?TRY_TEST1(api_test3),
-
- p("Testing undo phase across master/subagents..."),
- ?TRY_TEST1(undo_test),
- ?TRY_TEST1(api_test3),
- stop_subagent(SA).
-
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
-%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
-%% Req. Klas3, Klas4
-undo_test() ->
- s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
- s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
- %% unfortunatly we don't know if we'll get undoFailed or commitFailed.
- %% it depends on which order the agent traverses the varbind list.
- %% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
- %% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line expect(6, genErr, 2, any).
-
-%% Req. Klas3, Klas4
-bad_return() ->
- g([[fStatus4,4],
- [fName4,4]]),
- ?line expect(4, genErr, 2, any),
- g([[fStatus4,5],
- [fName4,5]]),
- ?line expect(5, genErr, 1, any),
- g([[fStatus4,6],
- [fName4,6]]),
- ?line expect(6, genErr, 2, any),
- gn([[fStatus4,7],
- [fName4,7]]),
- ?line expect(7, genErr, 2, any),
- gn([[fStatus4,8],
- [fName4,8]]),
- ?line expect(8, genErr, 1, any),
- gn([[fStatus4,9],
- [fName4,9]]),
- ?line expect(9, genErr, 2, any).
-
-
-%% -- standard_mibs --
-
-%%%-----------------------------------------------------------------
-%%% Test the implementation of standard mibs.
-%%% We should *at least* try to GET all variables, just to make
-%%% sure the instrumentation functions work.
-%%% Note that many of the functions in the standard mib is
-%%% already tested by the normal tests.
-%%%-----------------------------------------------------------------
-standard_mibs(suite) ->
- [snmp_standard_mib,
- snmp_community_mib,
- snmp_framework_mib,
- snmp_target_mib,
- snmp_notification_mib,
- snmp_view_based_acm_mib].
-
-
-%% -- snmp_standard_mib --
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v1.
-%% o Test the counters and control objects in SNMP-STANDARD-MIB
-%%-----------------------------------------------------------------
-snmp_standard_mib(suite) -> [];
-snmp_standard_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?DBG("snmp_standard_mib -> std_mib_init", []),
- ?TRY_TEST1(std_mib_init),
-
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- InBadVsns = ?TRY_TEST1(std_mib_a),
- put(vsn, v2),
- ?DBG("snmp_standard_mib -> std_mib_read", []),
- ?TRY_TEST1(std_mib_read),
- put(vsn, v1),
-
- ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
- Bad = ?TRY_TEST2(std_mib_b, [InBadVsns]),
- ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
- ?TRY_TEST3(std_mib_read, [], [{community, "bad community"}]),
- ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
- ?TRY_TEST3(std_mib_write, [], [{community, "public"}]),
- ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
- ?TRY_TEST1(std_mib_asn_err),
- ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
- ?TRY_TEST2(std_mib_c, [Bad]),
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- ?TRY_TEST1(standard_mib_a),
-
- ?DBG("snmp_standard_mib -> std_mib_finish", []),
- ?TRY_TEST1(std_mib_finish),
- ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
- ?TRY_TEST3(standard_mib_test_finish, [], [{community, "bad community"}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
- ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
- %% There are some more counters we could test here, but it's not that
- %% important, since they are removed from SNMPv2-MIB.
- ok.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_init() ->
- %% disable authentication failure traps. (otherwise w'd get many of
- %% them - this is also a test to see that it works).
- s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_finish() ->
- %% enable again
- s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_test_finish() ->
- %% force a authenticationFailure
- std_mib_write(),
- %% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_read() ->
- ?DBG("std_mib_read -> entry", []),
- g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
- ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
-
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_write() ->
- ?DBG("std_mib_write -> entry", []),
- s([{[sysLocation, 0], "new_value"}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_asn_err() ->
- ?SEND_BYTES([48,99,67,12,0,0,0,0,0,0,5]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_a() ->
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
-
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
- InBadVsns.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_b(InBadVsns) ->
- ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
- ?line InBadVsns2 = InBadVsns + 1,
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
- ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
- get_req(4, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
- get_req(1, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
-
-
-%% -- snmp_community_mib --
-
-%%-----------------------------------------------------------------
-%% o Bad community uses/name is tested already
-%% in SNMPv2-MIB and STANDARD-MIB.
-%% o Test add/deletion of rows.
-%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
-snmp_community_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?TRY_TEST1(snmp_community_mib),
- ?line unload_master("SNMP-COMMUNITY-MIB").
-
-snmp_community_mib_2(X) -> snmp_community_mib(X).
-
-%% Req. SNMP-COMMUNITY-MIB
-snmp_community_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-
-%% -- snmp_framework_mib --
-
-%%-----------------------------------------------------------------
-%% o Test engine boots / time
-%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
-snmp_framework_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?TRY_TEST1(snmp_framework_mib),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
-
-%% Req. SNMP-FRAMEWORK-MIB
-snmp_framework_mib() ->
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
- sleep(5000),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
- if
- EngineTime+7 < EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- EngineTime+4 > EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- true -> ok
- end,
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
- [Boots] when integer(Boots) -> ok;
- Else -> ?FAIL(Else)
- end,
- ok.
-
-
-%% -- snmp_target_mib --
-
-snmp_target_mib(suite) -> [];
-snmp_target_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?TRY_TEST1(snmp_target_mib),
- ?line unload_master("SNMP-TARGET-MIB").
-
-snmp_target_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-
-%% -- snmp_notification_mib --
-
-snmp_notification_mib(suite) -> [];
-snmp_notification_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?TRY_TEST1(snmp_notification_mib),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
-
-snmp_notification_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-
-%% -- snmp_view_based_acm_mib --
-
-%%-----------------------------------------------------------------
-%% o add/delete views and try them
-%% o try boundaries
-%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
-snmp_view_based_acm_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
- snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-snmp_view_based_acm_mib() ->
- snmpa:verbosity(net_if,trace),
- snmpa:verbosity(master_agent,trace),
- ?LOG("start snmp_view_based_acm_mib test",[]),
- %% The user "no-rights" is present in USM, and is mapped to security
- %% name 'no-rights", which is not present in VACM.
- %% So, we'll add rights for it, try them and delete them.
- %% We'll give "no-rights" write access to tDescr.0 and read access
- %% to tDescr2.0
- %% These are the options we'll use to the mgr
- Opts = [{user, "no-rights"}, {community, "no-rights"}],
- %% Find the valid secmodel, and one invalid secmodel.
- {SecMod, InvSecMod} =
- case get(vsn) of
- v1 -> {?SEC_V1, ?SEC_V2C};
- v2 -> {?SEC_V2C, ?SEC_USM};
- v3 -> {?SEC_USM, ?SEC_V1}
- end,
- ?DBG("assign rights for 'no-rights'",[]),
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
-
- %% Now, add a mapping from "no-rights" -> "no-rights-group"
- GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
- GRow1 =
- [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
- {GRow1Status, ?createAndGo}],
- ?DBG("set '~p'",[GRow1]),
- ?line ?TRY_TEST2(do_set, [GRow1]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
-
- %% Create a mapping for another sec model, and make sure it dosn't
- %% give us access
- GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
- GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
- {GRow2Status, ?createAndGo}],
-
- ?DBG("set '~p'",[GRow2]),
- ?line ?TRY_TEST2(do_set, [GRow2]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line ?TRY_TEST2(del_row, [GRow2Status]),
-
- RVName = "rv_name",
- WVName = "wv_name",
-
- %% Access row
- ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
- ARow1Status = [vacmAccessStatus, ARow1Idx],
- ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
- {[vacmAccessReadViewName, ARow1Idx], RVName},
- {[vacmAccessWriteViewName, ARow1Idx], WVName},
- {ARow1Status, ?createAndGo}],
-
- %% This access row would give acces, if InvSecMod was valid.
- ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
- ARow2Status = [vacmAccessStatus, ARow2Idx],
- ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
- {[vacmAccessReadViewName, ARow2Idx], "internet"},
- {[vacmAccessWriteViewName, ARow2Idx], "internet"},
- {ARow2Status, ?createAndGo}],
-
- ?line ?TRY_TEST2(do_set, [ARow2]),
-
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line ?TRY_TEST2(del_row, [ARow2Status]),
-
-
- %% Add valid row
- ?line ?TRY_TEST2(do_set, [ARow1]),
-
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
-
- %% Create the view family
- VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
- VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
- VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
- VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
- VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
- VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
- VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
- VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
-
- ?line ?TRY_TEST2(add_row, [VRow1Status]),
- ?line ?TRY_TEST2(add_row, [VRow2Status]),
- ?line ?TRY_TEST2(add_row, [VRow3Status]),
-
- %% We're supposed to have access now...
- ?line ?TRY_TEST3(use_rights, [], Opts),
-
- %% Change Row3 to Row4
- ?line ?TRY_TEST2(del_row, [VRow3Status]),
- ?line ?TRY_TEST2(add_row, [VRow4Status]),
-
- %% We should still have access...
- ?line ?TRY_TEST3(use_rights, [], Opts),
-
- %% Delete rows
- ?line ?TRY_TEST2(del_row, [GRow1Status]),
-
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
-
- %% Delete rest of rows
- ?line ?TRY_TEST2(del_row, [ARow1Status]),
- ?line ?TRY_TEST2(del_row, [VRow1Status]),
- ?line ?TRY_TEST2(del_row, [VRow2Status]),
- ?line ?TRY_TEST2(del_row, [VRow4Status]),
-
- ?line ?TRY_TEST3(use_no_rights, [], Opts),
- snmpa:verbosity(master_agent,log).
-
-do_set(Row) ->
- s(Row),
- expect(1, Row).
-
-add_row(RowStatus) ->
- s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
-
-del_row(RowStatus) ->
- s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
-
-
-
-use_no_rights() ->
- g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
- g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
- gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
- s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
-
-
-use_rights() ->
- g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
- g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
- s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
- g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
-
-
-%% -- sparse_table --
-
-sparse_table(suite) -> [];
-sparse_table(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
-
- ?line load_master("Test1"),
- ?TRY_TEST1(sparse_table_test),
- ?line unload_master("Test1").
-
-%% Req. Test1
-sparse_table_test() ->
- p("Testing sparse table..."),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- s([{[sparseStatus, Idx1], i, ?createAndGo},
- {[sparseDescr, Idx1], s, "row 1"}]),
- ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
- {[sparseDescr, Idx1], "row 1"}]),
- s([{[sparseStatus, Idx2], i, ?createAndGo},
- {[sparseDescr, Idx2], s, "row 2"}]),
- ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
- {[sparseDescr, Idx2], "row 2"}]),
- ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
- [sparseStatus,Idx1], [sparseStatus,Idx2]]),
- gb(0,5,[[sparseIndex]])),
- ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
- {[sparseDescr,Idx2], "row 2"},
- {[sparseStatus,Idx1], ?active},
- {[sparseStatus,Idx2], ?active},
- {[sparseStr,0], "slut"}]),
- % Delete the rows
- s([{[sparseStatus, Idx1], i, ?destroy}]),
- ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
- s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
-
-
-%% -- cnt_64 --
-
-cnt_64(suite) -> [];
-cnt_64(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- ?TRY_TEST2(cnt_64_test, [MA]),
- ?line unload_master("Test1").
-
-%% Req. Test1
-cnt_64_test(MA) ->
- ?LOG("start cnt64 test (~p)",[MA]),
- snmpa:verbosity(MA,trace),
- ?LOG("start cnt64 test",[]),
- p("Testing Counter64, and at the same time, RowStatus is not last column"),
-
- ?DBG("get cnt64",[]),
- g([[cnt64,0]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(1, noSuchName, 1, any),
- expect(1, [{[cnt64,0],18446744073709551615}])),
- ?DBG("get-next cnt64",[]),
- gn([[cnt64]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
- expect(2, [{[cnt64,0],18446744073709551615}])),
- ?DBG("send cntTrap",[]),
- snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
- {cnt64, 10},
- {sysLocation, "here"}]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
- {[sysLocation,0], "here"}]),
- expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [1]},
- {[sysContact,0], "pelle"},
- {[cnt64,0], 10},
- {[sysLocation,0], "here"}])),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- ?DBG("create row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
- ?DBG("create row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
-
- ?DBG("get-next (cntIndex)",[]),
- gn([[cntIndex]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
- expect(3, [{[cntCnt,Idx1], 0}])),
- % Delete the rows
- ?DBG("delete row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
- ?DBG("delete row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
- catch snmpa:verbosity(MA,log),
- ?DBG("done",[]),
- ok.
-
-
-%% -- opaque --
-
-opaque(suite) -> [];
-opaque(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
-
- ?line load_master("Test1"),
- ?TRY_TEST1(opaque_test),
- ?line unload_master("Test1").
-
-%% Req. Test1
-opaque_test() ->
- p("Testing Opaque datatype..."),
- g([[opaqueObj,0]]),
- ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
-
-
-%% -- change_target_addr_config --
-
-change_target_addr_config(suite) -> [];
-change_target_addr_config(Config) when list(Config) ->
- p("Testing changing target address config..."),
- ?LOG("change_target_addr_config -> entry",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(sname,snmp_suite),
- put(verbosity,trace),
-
- MA = whereis(snmp_master_agent),
-
- ?LOG("change_target_addr_config -> load TestTrap",[]),
- ?line load_master("TestTrap"),
-
- ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,trace),
-
- %% First send some traps that will arive att the original manager
- ?LOG("change_target_addr_config -> send trap",[]),
- ?TRY_TEST2(ma_trap1, [MA]),
-
- ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
-
- %% Start new dummy listener
- ?LOG("change_target_addr_config -> start dummy manager",[]),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
-
- %% Reconfigure
- ?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- %% Send the trap again
- ?LOG("change_target_addr_config -> send trap again",[]),
- catch dummy_manager_send_trap2(Pid),
-
- ?LOG("change_target_addr_config -> await trap ack",[]),
- catch dummy_manager_await_trap2_ack(),
-
- ?LOG("change_target_addr_config -> stop dummy manager",[]),
- ?line ok = dummy_manager_stop(Pid),
-
- ?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
-
- ?LOG("change_target_addr_config -> unload TestTrap",[]),
- ?line unload_master("TestTrap").
-
-
-dummy_manager_start(MA) ->
- ?DBG("dummy_manager_start -> entry",[]),
- Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
- ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
- await_dummy_manager_started(Pid).
-
-await_dummy_manager_started(Pid) ->
- receive
- {dummy_manager_started,Pid,Port} ->
- ?DBG("dummy_manager_start -> acknowledge received with"
- "~n Port: ~p",[Port]),
- {ok,Pid,Port};
- {'EXIT', Pid, Reason} ->
- {error, Pid, Reason};
- O ->
- ?LOG("dummy_manager_start -> received unknown message:"
- "~n ~p",[O]),
- await_dummy_manager_started(Pid)
- end.
-
-dummy_manager_stop(Pid) ->
- ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
- Pid ! stop,
- receive
- {dummy_manager_stopping, Pid} ->
- ?DBG("dummy_manager_stop -> acknowledge received",[]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_stop -> timeout",[]),
- timeout
- end.
-
-dummy_manager_send_trap2(Pid) ->
- ?DBG("dummy_manager_send_trap2 -> entry",[]),
- Pid ! {send_trap,testTrap2}.
-
-dummy_manager_await_trap2_ack() ->
- ?DBG("dummy_manager_await_trap2 -> entry",[]),
- receive
- {received_trap,Trap} ->
- ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
- %% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
- %% is no relation between these two test cases as far as I
- %% able to figure out...
- sleep(60000),
- ok;
- O ->
- ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_await_trap2 -> timeout",[]),
- timeout
- end.
-
-dummy_manager_init(Parent,MA) ->
- ?DBG("dummy_manager_init -> entry with"
- "~n Parent: ~p"
- "~n MA: ~p",[Parent,MA]),
- {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
- ?DBG("dummy_manager_init -> S: ~p",[S]),
- {ok,Port} = inet:port(S),
- ?DBG("dummy_manager_init -> Port: ~p",[Port]),
- Parent ! {dummy_manager_started,self(),Port},
- dummy_manager_loop(Parent,S,MA).
-
-dummy_manager_loop(P,S,MA) ->
- ?LOG("dummy_manager_loop -> ready for receive",[]),
- receive
- {send_trap,Trap} ->
- ?LOG("dummy_manager_loop -> received trap send request"
- "~n Trap: ~p",[Trap]),
- snmpa:send_trap(MA, Trap, "standard trap"),
- dummy_manager_loop(P,S,MA);
- {udp, _UdpId, Ip, UdpPort, Bytes} ->
- ?LOG("dummy_manager_loop -> received upd message"
- "~n from: ~p:~p"
- "~n size: ~p",
- [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
- R = dummy_manager_handle_message(Bytes),
- ?DBG("dummy_manager_loop -> R: ~p",[R]),
- P ! R,
- dummy_manager_loop(P,S,MA);
- stop ->
- ?DBG("dummy_manager_loop -> received stop request",[]),
- P ! {dummy_manager_stopping, self()},
- gen_udp:close(S),
- exit(normal);
- O ->
- ?LOG("dummy_manager_loop -> received unknown message:"
- "~n ~p",[O]),
- dummy_manager_loop(P,S,MA)
- end.
-
-dummy_manager_message_sz(B) when binary(B) ->
- size(B);
-dummy_manager_message_sz(L) when list(L) ->
- length(L);
-dummy_manager_message_sz(_) ->
- undefined.
-
-dummy_manager_handle_message(Bytes) ->
- case (catch snmp_pdus:dec_message(Bytes)) of
- {'EXIT',Reason} ->
- ?ERR("dummy_manager_handle_message -> "
- "failed decoding message only:~n ~p",[Reason]),
- {error,Reason};
- M ->
- ?DBG("dummy_manager_handle_message -> decoded message:"
- "~n ~p",[M]),
- {received_trap,M}
- end.
-
-
-%% -- reported_bugs --
-
-%%%-----------------------------------------------------------------
-%%% Testing of reported bugs and other tickets.
-%%%-----------------------------------------------------------------
-
-reported_bugs(suite) ->
- [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].
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1128
-%% Slogan: Bug in handling of createAndWait set-requests.
-%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
-otp_1128(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?TRY_TEST1(otp_1128),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1128() ->
- io:format("Testing bug reported in ticket OTP-1128...~n"),
-
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
-
- s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(29, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(31, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(32, [{NewKeyc5, ?destroy}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1129, OTP-1169
-%% Slogan: snmpa:int_to_enum crashes on bad oids
-%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
-otp_1129(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- ?TRY_TEST2(otp_1129_i, [node()]),
- ?line unload_master("Klas3").
-
-otp_1129_i(MaNode) ->
- io:format("Testing bug reported in ticket OTP-1129...~n"),
- false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
- false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1131
-%% Slogan: Agent crashes / erlang node halts if RowIndex in a
-%% setrequest is of bad type, e.g. an INDEX {INTEGER},
-%% and RowIdenx [3,2].
-%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
-otp_1131(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas1"),
- ?TRY_TEST1(otp_1131),
- ?line unload_master("Klas1").
-
-otp_1131() ->
- io:format("Testing bug reported in ticket OTP-1131...~n"),
- s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
- {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1162
-%% Slogan: snmp_agent can't handle wrongValue from instrum.func
-%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
-otp_1162(Config) when list(Config) ->
- ?P1(otp_1162),
- {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config),
- ?line {ok, SA} = ?START_SA(SaNode, ?sa, "SA-MIB"),
- ?TRY_TEST1(otp_1162),
- ?STOP_SA(SA).
-
-otp_1162() ->
- s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1222
-%% Slogan: snmp agent crash if faulty index is returned from instrum
-%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
-otp_1222(Config) when list(Config) ->
- ?P1(otp_1222),
- ?INIT_CASE(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
- ?TRY_TEST1(otp_1222),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4").
-
-otp_1222() ->
- io:format("Testing bug reported in ticket OTP-1222...~n"),
- s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line expect(1, genErr, 0, any),
- s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line expect(2, genErr, 0, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1298
-%% Slogan: Negative INTEGER values are treated as positive.
-%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
-otp_1298(Config) when list(Config) ->
- ?P1(otp_1298),
- ?INIT_CASE(Config),
- ?line load_master("Klas2"),
- ?TRY_TEST1(otp_1298),
- ?line unload_master("Klas2").
-
-otp_1298() ->
- io:format("Testing bug reported in ticket OTP-1298...~n"),
- s([{[fint,0], -1}]),
- ?line expect(1298, [{[fint,0], -1}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1331
-%% Slogan: snmp_generic should return noError when deleting non-ex row
-%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
-otp_1331(Config) when list(Config) ->
- ?P1(otp_1331),
- ?INIT_CASE(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?TRY_TEST1(otp_1331),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1331() ->
- NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
- s([{NewKeyc5, ?destroy}]),
- ?line expect(1, [{NewKeyc5, ?destroy}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1338
-%% Slogan: snmp bug in initialisation of default values for mnesia tabs
-%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
-otp_1338(Config) when list(Config) ->
- ?P1(otp_1338),
- ?INIT_CASE(Config),
- ?line load_master("Klas2"),
- ?TRY_TEST1(otp_1338),
- ?line unload_master("Klas2").
-
-otp_1338() ->
- s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
- g([[kName2, 7]]),
- ?line expect(2, [{[kName2, 7], "JJJ"}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1342
-%% Slogan: default impl of snmp table can't handle bad index access,
-%% Set when INDEX is read-write gets into an infinite loop!
-%%-----------------------------------------------------------------
-otp_1342(suite) -> [];
-otp_1342(Config) when list(Config) ->
- ?P1(otp_1342),
- ?INIT_CASE(Config),
- ?line load_master("Klas4"),
- ?TRY_TEST1(otp_1342),
- ?line unload_master("Klas4").
-
-otp_1342() ->
- s([{[fIndex5, 1], i, 1},
- {[fName5, 1], i, 3},
- {[fStatus5, 1], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1366
-%% Slogan: snmp traps not sent to all managers
-%% Note: NYI! We need a way to tell the test server that we need
-%% mgrs on two different machines.
-%%-----------------------------------------------------------------
-otp_1366(suite) -> [];
-otp_1366(Config) when list(Config) ->
- ?P1(otp_1366),
- ?INIT_CASE(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?TRY_TEST1(otp_1366),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1366() ->
- ?INF("NOT YET IMPLEMENTED", []),
- 'NYI'.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2776
-%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
-%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
-otp_2776(Config) when list(Config) ->
- ?P1(otp_2776),
- ?INIT_CASE(Config),
- ?TRY_TEST1(otp_2776).
-
-otp_2776() ->
- io:format("Testing bug reported in ticket OTP-2776...~n"),
-
- Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
- Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
- Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
- Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
- Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
- Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
- Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
- Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
- Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
- Dt10_invalid = [],
- Dt11_invalid = [kalle,hobbe],
- L = [{ 1, true, Dt01_valid},
- { 2, true, Dt02_valid},
- { 3, true, Dt03_valid},
- { 4, false, Dt04_invalid},
- { 5, true, Dt05_valid},
- { 6, true, Dt06_valid},
- { 7, false, Dt07_invalid},
- { 8, true, Dt08_valid},
- { 9, false, Dt09_invalid},
- {10, false, Dt10_invalid},
- {11, false, Dt11_invalid}],
-
- ?line ok = validate_dat(L).
-
-
-validate_dat(L) -> validate_dat(L,[]).
-
-validate_dat([],V) ->
- Fun = fun({_,X}) -> case X of
- ok -> false;
- _ -> true
- end
- end,
- validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
-validate_dat([{Id,E,Dat}|T],V) ->
- validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
-
-validate_dat1([]) -> ok;
-validate_dat1(L) -> {error,L}.
-
-validate_dat2(Id, E, Dat) ->
- Res = case {E,snmp:validate_date_and_time(Dat)} of
- {E,E} -> ok;
- {E,A} -> {E,A}
- end,
- {Id, Res}.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2979
-%% Slogan: get-next on more than 1 column in an empty table
-%% returns bad response.
-%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
-otp_2979(Config) when list(Config) ->
- ?P1(otp_2979),
- ?INIT_CASE(Config),
- ?line load_master("Test1"),
- ?line init_old(),
- ?TRY_TEST1(otp_2979),
- ?line unload_master("Test1").
-
-otp_2979() ->
- gn([[sparseDescr], [sparseStatus]]),
- ?line expect(1, [{[sparseStr,0], "slut"},
- {[sparseStr,0], "slut"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
-%% endOfTable - should return value.
-%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
-otp_3187(Config) when list(Config) ->
- ?P1(otp_3187),
- ?INIT_CASE(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- otp_3187(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-otp_3187() ->
- ?line Elements =
- snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
- lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
- ?FAIL(endOfTable);
- true -> ok
- end
- end, Elements).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3542
-%% Slogan:
-%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
-otp_3542(Config) when list(Config) ->
- ?P1(otp_3542),
- ?INIT_CASE(Config),
- ?TRY_TEST1(otp_3542).
-
-otp_3542() ->
- io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
- io:format("SNMP v3 discovery result: ~p~n",[Res]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3725
-%% Slogan: Slow response time on snmpa:int_to_enum
-%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
-otp_3725(Config) when list(Config) ->
- ?P1(otp_3725),
- ?INIT_CASE(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?TRY_TEST2(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-otp_3725_test(MaNode) ->
- io:format("Testing feature requested in ticket OTP-3725...~n"),
- ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
- ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
- ?DBG("otp_3725_test -> Db = ~p",[Db]),
-
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [Db, intAgentIpAddress]),
- ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
- [Db,OID]),
- ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
- ok.
-
-
-%% -- tickets --
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-tickets(suite) ->
- [otp_4394].
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-4394
-%% Slogan: Target mib tag list check invalid
-%%-----------------------------------------------------------------
-
-otp_4394(suite) -> {req, [], {conf,
- init_otp_4394,
- [otp_4394_test],
- finish_otp_4394}}.
-
-init_otp_4394(Config) when list(Config) ->
- ?DBG("init_otp_4394 -> entry with"
- "~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
- MasterAgentVerbosity = {master_agent_verbosity, trace},
- NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
-
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
- ?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
- Vsn = [v1],
- Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
- ?TRAP_UDP, Ip, 4000,
- "OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
- false ->
- ?line ok
- end,
- C1 = {"a", "all-rights", "initial", "", "pc"},
- C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
- Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
- "pc1",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [],
- 2048},
- Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
- "pc2",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
- ok.
-
-finish_otp_4394(Config) when list(Config) ->
- ?DBG("finish_otp_4394 -> entry", []),
- C1 = stop_agent(Config),
- delete_files(C1),
- erase(mgr_node),
- lists:keydelete(vsn, 1, C1).
-
-otp_4394_test(suite) -> [];
-otp_4394_test(Config) ->
- ?P1(otp_4394_test),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?TRY_TEST1(otp_4394_test1),
- ?DBG("otp_4394_test -> done", []),
- ok.
-
-otp_4394_test1() ->
- ?DBG("otp_4394_test1 -> entry", []),
- gn([[1,1]]),
- Res =
- case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
- %% {error, 1, {"?",[]}, {"~w",[timeout]}}
- {error, 1, _, {_, [timeout]}} ->
- ?DBG("otp_4394_test1 -> expected result: timeout", []),
- ok;
- Else ->
- Else
- end,
- ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
- Res.
-
-
-mk_ln(X) ->
- [length(X) | X].
-
-
-
-%% string used in index
-is(S) -> [length(S) | S].
-
-expect(A,B) -> ok = ?MGR:expect(A,B).
-expect(A,B,C) -> ok = ?MGR:expect(A,B,C).
-expect(A,B,C,D) -> ok = ?MGR:expect(A,B,C,D).
-expect(A,B,C,D,E,F) -> ok = ?MGR:expect(A,B,C,D,E,F).
-
diff --git a/lib/snmp/test/snmp_agent_v2_test.erl b/lib/snmp/test/snmp_agent_v2_test.erl
deleted file mode 100644
index dc94c18ad9..0000000000
--- a/lib/snmp/test/snmp_agent_v2_test.erl
+++ /dev/null
@@ -1,5649 +0,0 @@
-%%
-%% %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%
-%%
-
--module(snmp_agent_v2_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
--compile(export_all).
-
--define(application, snmp).
-
--include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
--include("snmp_test_lib.hrl").
--define(SNMP_USE_V3, true).
--include_lib("snmp/include/snmp_types.hrl").
-%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
-
-
--define(klas1, [1,3,6,1,2,1,7]).
--define(klas2, [1,3,6,1,2,1,9]).
--define(klas3, [1,3,6,1,2,1,8,1]).
--define(klas4, [1,3,6,1,2,1,8,4]).
--define(sa, [1,3,6,1,4,1,193,2]).
--define(system, [1,3,6,1,2,1,1]).
--define(snmp, [1,3,6,1,2,1,11]).
--define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
--define(ericsson, [1,3,6,1,4,1,193]).
--define(testTrap, [1,3,6,1,2,1,15,0]).
--define(xDescr, [1,3,6,1,2,1,17,1]).
--define(xDescr2, [1,3,6,1,2,1,17,2]).
-
--define(active, 1).
--define(notInService, 2).
--define(notReady, 3).
--define(createAndGo, 4).
--define(createAndWait, 5).
--define(destroy, 6).
-
--define(TRAP_UDP, 5000).
-
--define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
-
--define(str(X), snmp_pdus:bits_to_str(X)).
-
--define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
- [?LINE, self()]),
- receive cont -> ok end
- end).
-
-
--import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
--define(v1_2(V1,V2),
- case get(vsn) of
- v1 -> V1;
- _ -> V2
- end).
-
--define(v1_2_3(V1,V2,V3),
- case get(vsn) of
- v1 -> V1;
- v2 -> V2;
- _ -> V3
- end).
-
-all() ->
-[cases()].
-
-groups() ->
- [{mib_storage, [],
- [{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()},
- {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]},
- {standard_mibs, [],
- [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]},
- {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]},
- {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]},
- {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]},
- {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]},
- {tickets, [], [{group, otp_4394}]},
- {otp_4394, [], [otp_4394_test]}].
-
-init_per_group(otp_4394, Config) ->
- init_otp_4394(Config);
-init_per_group(v2_inform, Config) ->
- init_v2_inform(Config);
-init_per_group(multiple_reqs_2, Config) ->
- init_mul(Config);
-init_per_group(multiple_reqs, Config) ->
- init_mul(Config);
-init_per_group(test_multi_threaded, Config) ->
- init_mt(Config);
-init_per_group(test_v3, Config) ->
- init_v3(Config);
-init_per_group(test_v1_v2, Config) ->
- init_v1_v2(Config);
-init_per_group(test_v2, Config) ->
- init_v2(Config);
-init_per_group(test_v1, Config) ->
- init_v1(Config);
-init_per_group(mib_storage_varm_mnesia, Config) ->
- init_varm_mib_storage_mnesia(Config);
-init_per_group(mib_storage_varm_dets, Config) ->
- init_varm_mib_storage_dets(Config);
-init_per_group(mib_storage_size_check_mnesia, Config) ->
- init_size_check_msm(Config);
-init_per_group(mib_storage_size_check_dets, Config) ->
- init_size_check_msd(Config);
-init_per_group(mib_storage_size_check_ets, Config) ->
- init_size_check_mse(Config);
-init_per_group(mib_storage_mnesia, Config) ->
- init_mib_storage_mnesia(Config);
-init_per_group(mib_storage_dets, Config) ->
- init_mib_storage_dets(Config);
-init_per_group(mib_storage_ets, Config) ->
- init_mib_storage_ets(Config);
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(otp_4394, Config) ->
- finish_otp_4394(Config);
-end_per_group(v2_inform, Config) ->
- finish_v2_inform(Config);
-end_per_group(multiple_reqs_2, Config) ->
- finish_mul(Config);
-end_per_group(multiple_reqs, Config) ->
- finish_mul(Config);
-end_per_group(test_multi_threaded, Config) ->
- finish_mt(Config);
-end_per_group(test_v3, Config) ->
- finish_v3(Config);
-end_per_group(test_v1_v2, Config) ->
- finish_v1_v2(Config);
-end_per_group(test_v2, Config) ->
- finish_v2(Config);
-end_per_group(test_v1, Config) ->
- finish_v1(Config);
-end_per_group(mib_storage_varm_mnesia, Config) ->
- finish_varm_mib_storage_mnesia(Config);
-end_per_group(mib_storage_varm_dets, Config) ->
- finish_varm_mib_storage_dets(Config);
-end_per_group(mib_storage_size_check_mnesia, Config) ->
- finish_size_check_msm(Config);
-end_per_group(mib_storage_size_check_dets, Config) ->
- finish_size_check_msd(Config);
-end_per_group(mib_storage_size_check_ets, Config) ->
- finish_size_check_mse(Config);
-end_per_group(mib_storage_mnesia, Config) ->
- finish_mib_storage_mnesia(Config);
-end_per_group(mib_storage_dets, Config) ->
- finish_mib_storage_dets(Config);
-end_per_group(mib_storage_ets, Config) ->
- finish_mib_storage_ets(Config);
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- Config.
-
-cases() ->
-case ?OSTYPE() of
- vxworks ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_multi_threaded},
- {group, mib_storage}, {group, tickets}];
- _Else ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}]
-end.
-
-
-%%%-----------------------------------------------------------------
-%%% The test case structure is as follows:
-%%%
-%%% init_all - starts mnesia,
-%%%
-%%% init_v1 - starts agent
-%%% simple
-%%% big - e.g. starts/stops subagent, load/unloads mibs
-%%% init_mul
-%%% mul_get
-%%% mul_set
-%%% <etc>
-%%% finish_mul
-%%% <etc>
-%%% finish_v1
-%%%
-%%% init_v2 - starts agent
-%%% finish_v2
-%%%
-%%% init_bilingual - starts agent
-%%% finish_bilingual
-%%%
-%%% finish_all
-%%%
-%%% There is still one problem with these testsuites. If one test
-%%% fails, it may not be possible to run some other cases, as it
-%%% may have e.g. created some row or loaded some table, that it
-%%% didn't undo (since it failed).
-%%%-----------------------------------------------------------------
-
-init_all(Config0) when list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
-
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
-
- %% --
- %% Start nodes
- %%
-
- ?line {ok, SaNode} = start_node(snmp_sa),
- ?line {ok, MgrNode} = start_node(snmp_mgr),
-
-
- %% --
- %% Create necessary files
- %%
-
- Dir = ?config(priv_dir, Config),
- ?DBG("init_all -> Dir ~p", [Dir]),
-
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
-
- file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
-
- file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
-
- file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
- ?DBG("init_all -> SaDir ~p", [SaDir]),
-
-
- %% --
- %% Start and initiate mnesia
- %%
-
- ?DBG("init_all -> load application mnesia", []),
- ?line ok = application:load(mnesia),
-
- ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, load, [mnesia]),
-
- ?DBG("init_all -> application mnesia: set_env dir",[]),
- ?line application_controller:set_env(mnesia, dir,
- filename:join(Dir, "Mnesia1")),
-
- ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(Dir, "Mnesia2")]),
-
- ?DBG("init_all -> create mnesia schema",[]),
- ?line ok = mnesia:create_schema([SaNode, node()]),
-
- ?DBG("init_all -> start application mnesia",[]),
- ?line ok = application:start(mnesia),
-
- ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
- ?line ok = rpc:call(SaNode, application, start, [mnesia]),
- Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
- Config].
-
-finish_all(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- stop_node(SaNode),
- stop_node(MgrNode),
- application:stop(mnesia).
-
-start_v1_agent(Config) when list(Config) ->
- start_agent(Config, [v1]).
-
-start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
- start_agent(Config, [v1], Opts).
-
-start_v2_agent(Config) when list(Config) ->
- start_agent(Config, [v2]).
-
-start_v3_agent(Config) when list(Config) ->
- start_agent(Config, [v3]).
-
-start_bilingual_agent(Config) when list(Config) ->
- start_agent(Config, [v1,v2]).
-
-start_multi_threaded_agent(Config) when list(Config) ->
- start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
-
-stop_agent(Config) when list(Config) ->
- ?LOG("stop_agent -> entry with"
- "~n Config: ~p",[Config]),
-
- {Sup, Par} = ?config(snmp_sup, Config),
- ?DBG("stop_agent -> attempt to stop (sup) ~p"
- "~n Sup: ~p"
- "~n Par: ~p",
- [Sup,
- (catch process_info(Sup)),
- (catch process_info(Par))]),
- stop_sup(Sup, Par),
-
- {Sup2, Par2} = ?config(snmp_sub, Config),
- ?DBG("stop_agent -> attempt to stop (sub) ~p"
- "~n Sup2: ~p"
- "~n Par2: ~p",
- [Sup2,
- (catch process_info(Sup2)),
- (catch process_info(Par2))]),
- stop_sup(Sup2, Par2),
-
- ?DBG("stop_agent -> done - now cleanup config", []),
- C1 = lists:keydelete(snmp_sup, 1, Config),
- lists:keydelete(snmp_sub, 1, C1).
-
-
-stop_sup(Pid, _) when node(Pid) == node() ->
- case (catch process_info(Pid)) of
- PI when list(PI) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- exit(Pid, kill),
- await_stopped(Pid, Ref);
- {'EXIT', _Reason} ->
- ?LOG("stop_sup -> ~p not running", [Pid]),
- ok
- end;
-stop_sup(Pid, _) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- ?LOG("stop_sup -> Ref: ~p", [Ref]),
- %% Pid ! {'EXIT', Parent, shutdown}, % usch
- exit(Pid, kill),
- await_stopped(Pid, Ref).
-
-await_stopped(Pid, Ref) ->
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ?DBG("received down message for ~p", [Pid]),
- ok
- after 10000 ->
- ?INF("await_stopped -> timeout for ~p",[Pid]),
- erlang:demonitor(Ref),
- ?FAIL({failed_stop,Pid})
- end.
-
-
-start_agent(Config, Vsn) ->
- start_agent(Config, Vsn, []).
-start_agent(Config, Vsn, Opts) ->
- ?LOG("start_agent -> entry (~p) with"
- "~n Config: ~p"
- "~n Vsn: ~p"
- "~n Opts: ~p",[node(), Config, Vsn, Opts]),
-
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
- snmp_app_env_init(vsn_init(Vsn) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, trace},
- {snmp_symbolic_store_verbosity, trace},
- {snmp_note_store_verbosity, trace},
- {snmp_net_if_verbosity, trace}],
- Opts),
-
-
- process_flag(trap_exit,true),
-
- {ok, AppSup} = snmp_app_sup:start_link(),
- unlink(AppSup),
- ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
-
- ?DBG("start_agent -> start master agent (old style)",[]),
- Sup = case (catch snmpa_app:start(normal)) of
- {ok, S} ->
- ?DBG("start_agent -> started, Sup: ~p",[S]),
- S;
-
- Else ->
- ?DBG("start_agent -> unknown result: ~n~p",[Else]),
- %% Get info about the apps we depend on
- MnesiaInfo = mnesia_running(),
- ?FAIL({start_failed,Else,MnesiaInfo})
- end,
-
- ?DBG("start_agent -> unlink from supervisor",[]),
- ?line unlink(Sup),
- ?line SaDir = ?config(sa_dir, Config),
- ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
- ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
- ?DBG("start_agent -> done",[]),
- ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
-
-
-vsn_init(Vsn) ->
- vsn_init([v1,v2,v3], Vsn, []).
-
-vsn_init([], _Vsn, Acc) ->
- Acc;
-vsn_init([V|Vsns], Vsn, Acc) ->
- case lists:member(V, Vsn) of
- true ->
- vsn_init(Vsns, Vsn, [{V, true}|Acc]);
- false ->
- vsn_init(Vsns, Vsn, [{V, false}|Acc])
- end.
-
-snmp_app_env_init(Env0, Opts) ->
- ?DBG("snmp_app_env_init -> unload snmp",[]),
- ?line application:unload(snmp),
- ?DBG("snmp_app_env_init -> load snmp",[]),
- ?line application:load(snmp),
- ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
- F1 = fun({Key,Val} = New, Acc0) ->
- ?DBG("snmp_app_env_init -> "
- "updating setting ~p to ~p", [Key, Val]),
- case lists:keyreplace(Key, 1, Acc0, New) of
- Acc0 ->
- [New|Acc0];
- Acc ->
- Acc
- end
- end,
- Env = lists:foldr(F1, Env0, Opts),
- ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
- F2 = fun({Key,Val}) ->
- ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
- application_controller:set_env(snmp, Key, Val)
- end,
- lists:foreach(F2, Env).
-
-
-
-
-%% Test if application is running
-mnesia_running() -> ?IS_MNESIA_RUNNING().
-crypto_running() -> ?IS_CRYPTO_RUNNING().
-
-
-start_sub(Dir) ->
- ?DBG("start_sub -> entry",[]),
- Opts = [{db_dir, Dir},
- {supervisor, [{verbosity, trace}]}],
- %% BMK BMK
-% {ok, P} = snmp_supervisor:start_sub(Dir),
- {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
- unlink(P),
- {ok, {P, self()}}.
-
-create_tables(SaNode) ->
- ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
- {attributes, [a1,a2]}]).
-
-delete_tables() ->
- mnesia:delete_table(friendsTable2),
- mnesia:delete_table(kompissTable2),
- mnesia:delete_table(snmp_variables).
-
-%% Creation is done in runtime!
-delete_mib_storage_mnesia_tables() ->
- mnesia:delete_table(snmpa_mib_data),
- mnesia:delete_table(snmpa_mib_tree),
- mnesia:delete_table(snmpa_symbolic_store).
-
-%%-----------------------------------------------------------------
-%% A test case is always one of:
-%% - v1 specific case
-%% - v2 specific case
-%% - v1 and v2 case
-%% All v1 specific cases are prefixed with v1_, and all v2 with
-%% v2_. E.g. v1_trap/v2_trap.
-%%
-%% All other cases are shared. However, the testserver uses the name
-%% of the case to generate a file for that case. The same case cannot
-%% be used in different configurations in the same suite. Therefore
-%% all these functions exists in two variants, the base function
-%% <base>, and a second version <base>_2. There may be several
-%% versions as well, <base>_N.
-%%-----------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-mib_storage_ets_cases() ->
-[mse_simple, mse_v1_processing, mse_big, mse_big2,
- mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
- mse_sa_error, mse_next_across_sa, mse_undo,
- mse_standard_mib, mse_community_mib, mse_framework_mib,
- mse_target_mib, mse_notification_mib,
- mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
- mse_mib_of].
-
-mib_storage_dets_cases() ->
-[msd_simple, msd_v1_processing, msd_big, msd_big2,
- msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
- msd_sa_error, msd_next_across_sa, msd_undo,
- msd_standard_mib, msd_community_mib, msd_framework_mib,
- msd_target_mib, msd_notification_mib,
- msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
- msd_mib_of].
-
-mib_storage_mnesia_cases() ->
-[msm_simple, msm_v1_processing, msm_big, msm_big2,
- msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
- msm_sa_error, msm_next_across_sa, msm_undo,
- msm_standard_mib, msm_community_mib, msm_framework_mib,
- msm_target_mib, msm_notification_mib,
- msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
- msm_mib_of].
-
-mse_size_check_cases() ->
-[mse_size_check].
-
-msd_size_check_cases() ->
-[msd_size_check].
-
-msm_size_check_cases() ->
-[msm_size_check].
-
-varm_mib_storage_dets_cases() ->
-[msd_varm_mib_start].
-
-varm_mib_storage_mnesia_cases() ->
-[msm_varm_mib_start].
-
-init_mib_storage_ets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,ets},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- init_ms(Config, [MibStorage]).
-
-init_ms(Config, Opts) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
-
-init_size_check_mse(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, ets},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msd(Config) when list(Config) ->
- AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage, {dets, AgentDir}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msm(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, {mnesia,[]}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_ms(Config, Opts) when list(Config) ->
- SaNode = ?GCONF(snmp_sa, Config),
- %% We are using v3 here, so crypto must be supported or else...
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end,
- create_tables(SaNode),
- AgentDir = ?GCONF(agent_dir, Config),
- MgrDir = ?GCONF(mgr_dir, Config),
- Ip = ?GCONF(ip, Config),
- ?line ok =
- config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_agent(Config, [v3], Opts)].
-
-init_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_dets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-init_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_mnesia -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-finish_mib_storage_ets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_ets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_dets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_dets -> entry", []),
- delete_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_size_check_mse(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msd(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msm(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_ms(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%% These are just interface functions to fool the test server
-mse_simple(X) -> simple(X).
-mse_v1_processing(X) -> v1_processing(X).
-mse_big(X) -> big(X).
-mse_big2(X) -> big2(X).
-mse_loop_mib(X) -> loop_mib(X).
-mse_api(X) -> api(X).
-mse_sa_register(X) -> sa_register(X).
-mse_v1_trap(X) -> v1_trap(X).
-mse_sa_error(X) -> sa_error(X).
-mse_next_across_sa(X) -> next_across_sa(X).
-mse_undo(X) -> undo(X).
-mse_standard_mib(X) -> snmp_standard_mib(X).
-mse_community_mib(X) -> snmp_community_mib(X).
-mse_framework_mib(X) -> snmp_framework_mib(X).
-mse_target_mib(X) -> snmp_target_mib(X).
-mse_notification_mib(X) -> snmp_notification_mib(X).
-mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-mse_sparse_table(X) -> sparse_table(X).
-mse_me_of(X) -> ms_me_of(X).
-mse_mib_of(X) -> ms_mib_of(X).
-
-msd_simple(X) -> simple(X).
-msd_v1_processing(X) -> v1_processing(X).
-msd_big(X) -> big(X).
-msd_big2(X) -> big2(X).
-msd_loop_mib(X) -> loop_mib(X).
-msd_api(X) -> api(X).
-msd_sa_register(X) -> sa_register(X).
-msd_v1_trap(X) -> v1_trap(X).
-msd_sa_error(X) -> sa_error(X).
-msd_next_across_sa(X) -> next_across_sa(X).
-msd_undo(X) -> undo(X).
-msd_standard_mib(X) -> snmp_standard_mib(X).
-msd_community_mib(X) -> snmp_community_mib(X).
-msd_framework_mib(X) -> snmp_framework_mib(X).
-msd_target_mib(X) -> snmp_target_mib(X).
-msd_notification_mib(X) -> snmp_notification_mib(X).
-msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msd_sparse_table(X) -> sparse_table(X).
-msd_me_of(X) -> ms_me_of(X).
-msd_mib_of(X) -> ms_mib_of(X).
-
-msm_simple(X) -> simple(X).
-msm_v1_processing(X) -> v1_processing(X).
-msm_big(X) -> big(X).
-msm_big2(X) -> big2(X).
-msm_loop_mib(X) -> loop_mib(X).
-msm_api(X) -> api(X).
-msm_sa_register(X) -> sa_register(X).
-msm_v1_trap(X) -> v1_trap(X).
-msm_sa_error(X) -> sa_error(X).
-msm_next_across_sa(X) -> next_across_sa(X).
-msm_undo(X) -> undo(X).
-msm_standard_mib(X) -> snmp_standard_mib(X).
-msm_community_mib(X) -> snmp_community_mib(X).
-msm_framework_mib(X) -> snmp_framework_mib(X).
-msm_target_mib(X) -> snmp_target_mib(X).
-msm_notification_mib(X) -> snmp_notification_mib(X).
-msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msm_sparse_table(X) -> sparse_table(X).
-msm_me_of(X) -> ms_me_of(X).
-msm_mib_of(X) -> ms_mib_of(X).
-
-
-mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
-msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
-msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
-
-msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
-msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
-
-ms_size_check(suite) -> [];
-ms_size_check(Config) when list(Config) ->
- p("ms_size_check..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?LOG("mib server size check...", []),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMPv2-MIB"),
- ?line load_master_std("SNMPv2-TM"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMPv2-MIB"),
- ?line unload_master("SNMPv2-TM"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-
-varm_mib_start(suite) -> [];
-varm_mib_start(Config) when list(Config) ->
- p("varm_mib_start..."),
- ?LOG("varm_mib_start -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- %% Start the agent
- Opts = ?GCONF(agent_opts, Config),
- Config1 = start_v1_agent(Config, Opts),
-
- %% Sleep some in order for the agent to start properly
- ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
- ?SLEEP(5000),
-
- %% Load all the mibs
- HardwiredMibs = loaded_mibs(),
- ?DBG("varm_mib_start -> load all mibs", []),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
-
- %% Unload the hardwired mibs
- ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
- ?SLEEP(1000),
- ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
- ?line unload_mibs(HardwiredMibs), %% unload hardwired
-
- ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
- ?SLEEP(1000),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- Config2 = stop_agent(Config1),
-
- %% Sleep some in order for the agent to stop properly
- ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
- ?SLEEP(5000),
-
- %% Start the agent (again)
- ?DBG("varm_mib_start -> start the agent", []),
- Config3 = start_v1_agent(Config2, Opts),
-
- ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
- ?SLEEP(5000),
-
- %% Perform the test(s)
- ?DBG("varm_mib_start -> perform the tests", []),
- try_test(snmp_community_mib),
- try_test(snmp_framework_mib),
- try_test(snmp_target_mib),
- try_test(snmp_notification_mib),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- stop_agent(Config3),
- ok.
-
-
--define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
--define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
--define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-ms_me_of(suite) -> [];
-ms_me_of(Config) when list(Config) ->
- p("ms_me_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = me_of(?snmpTrapCommunity_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = me_of(?vacmViewSpinLock_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-me_of(Oid) ->
- case snmpa:me_of(Oid) of
- {ok, #me{oid = Oid}} ->
- ok;
- {ok, #me{oid = OtherOid}} ->
- case lists:reverse(Oid) of
- [0|Rest] ->
- case lists:reverse(Rest) of
- OtherOid ->
- ok;
- AnotherOid ->
- {error, {invalid_oid, Oid, AnotherOid}}
- end;
- _ ->
- {error, {invalid_oid, Oid, OtherOid}}
- end;
- {error, Reason} ->
- {error, Reason};
- Else ->
- {error, Else}
- end.
-
-
-ms_mib_of(suite) -> [];
-ms_mib_of(Config) when list(Config) ->
- p("ms_mib_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
- 'SNMP-USER-BASED-SM-MIB'),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-mib_of(Oid, ExpectedMibName) ->
- ?DBG("mib_of -> entry with"
- "~n Oid: ~p"
- "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
- %% case snmpa:mib_of(Oid) of
- MibOf = snmpa:mib_of(Oid),
- ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
- case MibOf of
- {ok, ExpectedMibName} ->
- ok;
- {ok, OtherMibName} ->
- {error, {invalid_mib, ExpectedMibName, OtherMibName}};
- {error, Reason} ->
- {error, Reason};
- Else ->
- ?DBG("mib_of -> Else: ~n~p", [Else]),
- {error, Else}
- end.
-
-
-app_info(suite) -> [];
-app_info(Config) when list(Config) ->
- SnmpDir = app_dir(snmp),
- SslDir = app_dir(ssl),
- CryptoDir = app_dir(crypto),
- Attr = snmp:module_info(attributes),
- AppVsn =
- case lists:keysearch(app_vsn, 1, Attr) of
- {value, {app_vsn, V}} ->
- V;
- false ->
- "undefined"
- end,
- io:format("Root dir: ~s~n"
- "SNMP: Application dir: ~s~n"
- " Application ver: ~s~n"
- "SSL: Application dir: ~s~n"
- "CRYPTO: Application dir: ~s~n",
- [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
- ok.
-
-app_dir(App) ->
- case code:lib_dir(App) of
- D when list(D) ->
- filename:basename(D);
- {error, _Reason} ->
- "undefined"
- end.
-
-
-
-%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].
-
-init_v1(Config) when list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v1} | start_v1_agent(Config)].
-
-finish_v1(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v2_cases() -> [loop_mib_2];
-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].
-
-init_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_v2_agent(Config)].
-
-finish_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-v1_v2_cases() ->
-[simple_bi].
-
-init_v1_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, bilingual} | start_bilingual_agent(Config)].
-
-finish_v1_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v3_cases() -> [loop_mib_3];
-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].
-
-init_v3(Config) when list(Config) ->
- %% Make sure crypto works, otherwise start_agent will fail
- %% and we will be stuck with a bunch of mnesia tables for
- %% the rest of this suite...
- ?DBG("start_agent -> start crypto app",[]),
- case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end
- end,
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
- tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_v3_agent(Config)].
-
-finish_v3(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-mt_cases() ->
-[multi_threaded, mt_trap].
-
-init_mt(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_multi_threaded_agent(Config)].
-
-finish_mt(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-%% This one *must* be run first in each case.
-init_case(Config) when list(Config) ->
- ?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
-
- SaHost = ?HOSTNAME(SaNode),
- MgrHost = ?HOSTNAME(MgrNode),
- MasterHost = ?HOSTNAME(MasterNode),
- {ok, MasterIP} = snmp_misc:ip(MasterHost),
- {ok, MIP} = snmp_misc:ip(MgrHost),
- {ok, SIP} = snmp_misc:ip(SaHost),
-
-
- put(mgr_node, MgrNode),
- put(sa_node, SaNode),
- put(master_node, MasterNode),
- put(sa_host, SaHost),
- put(mgr_host, MgrHost),
- put(master_host, MasterHost),
- put(mip, tuple_to_list(MIP)),
- put(masterip , tuple_to_list(MasterIP)),
- put(sip, tuple_to_list(SIP)),
-
- MibDir = ?config(mib_dir, Config),
- put(mib_dir, MibDir),
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- put(std_mib_dir, StdM),
-
- MgrDir = ?config(mgr_dir, Config),
- put(mgr_dir, MgrDir),
-
- put(vsn, ?config(vsn, Config)),
- ?DBG("init_case -> exit with"
- "~n MasterNode: ~p"
- "~n SaNode: ~p"
- "~n MgrNode: ~p"
- "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
- {SaNode, MgrNode, MibDir}.
-
-load_master(Mib) ->
- ?DBG("load_master -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
-
-load_master_std(Mib) ->
- ?DBG("load_master_std -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
-
-unload_master(Mib) ->
- ?DBG("unload_master -> entry with"
- "~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
-
-loaded_mibs() ->
- ?DBG("loaded_mibs -> entry",[]),
- Info = snmpa:info(snmp_master_agent),
- {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
- [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
-
-unload_mibs(Mibs) ->
- ?DBG("unload_mibs -> entry with"
- "~n Mibs: ~p", [Mibs]),
- ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
-
-start_subagent(SaNode, RegTree, Mib) ->
- ?DBG("start_subagent -> entry with"
- "~n SaNode: ~p"
- "~n RegTree: ~p"
- "~n Mib: ~p", [SaNode, RegTree, Mib]),
- MA = whereis(snmp_master_agent),
- ?DBG("start_subagent -> MA: ~p", [MA]),
- MibDir = get(mib_dir),
- Mib1 = join(MibDir,Mib),
- %% BMK BMK
-% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
- case rpc:call(SaNode, snmpa_supervisor,
- start_sub_agent, [MA, RegTree, [Mib1]]) of
- {ok, SA} ->
- ?DBG("start_subagent -> SA: ~p", [SA]),
- {ok, SA};
- Error ->
- ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
- end.
-
-stop_subagent(SA) ->
- ?DBG("stop_subagent -> entry with"
- "~n SA: ~p", [SA]),
- %% BNK BMK
- %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
- rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
-
-%%-----------------------------------------------------------------
-%% This function takes care of the old OTP-SNMPEA-MIB.
-%% Unfortunately, the testcases were written to use the data in the
-%% internal tables, and these table are now obsolete and not used
-%% by the agent. Therefore, we emulate them by using
-%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
-%%
-%% These two rows must exist in intCommunityTable
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
-%% (But with the manager's IP address)
-%%
-%%-----------------------------------------------------------------
-init_old() ->
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [6 | "public"],
- {get(mip), "public", 2, 2}),
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [13 | "standard trap"],
- {get(mip), "standard trap", 2, 1}),
- snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
-
-
-
-simple(suite) -> [];
-simple(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(simple_standard_test).
-
-simple_2(X) -> simple(X).
-
-simple_bi(suite) -> [];
-simple_bi(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(vsn, v1), % First, try v1 manager
- try_test(simple_standard_test),
-
- put(vsn, v2), % Then, try v2 manager
- try_test(simple_standard_test).
-
-simple_3(X) ->
- simple(X).
-
-big(suite) -> [];
-big(Config) when list(Config) ->
- ?DBG("big -> entry", []),
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-big_2(X) -> big(X).
-
-big_3(X) -> big(X).
-
-
-big2(suite) -> [];
-big2(Config) when list(Config) ->
- %% This is exactly the same tests as 'big', but with the
- %% v2 equivalent of the mibs.
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
-
-big2_2(X) -> big2(X).
-
-big2_3(X) -> big2(X).
-
-
-multi_threaded(suite) -> [];
-multi_threaded(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(multi_threaded_test),
- ?line unload_master("Test1").
-
-mt_trap(suite) -> [];
-mt_trap(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- ?line load_master("TestTrapv2"),
- try_test(mt_trap_test, [MA]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("Test1").
-
-v2_types(suite) -> [];
-v2_types(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(types_v2_test),
- ?line unload_master("Test1").
-
-v2_types_3(X) -> v2_types(X).
-
-
-implied(suite) -> [];
-implied(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(implied_test,[MA]),
- ?line unload_master("Test1").
-
-implied_3(X) -> implied(X).
-
-
-sparse_table(suite) -> [];
-sparse_table(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(sparse_table_test),
- ?line unload_master("Test1").
-
-sparse_table_2(X) -> sparse_table(X).
-
-sparse_table_3(X) -> sparse_table(X).
-
-cnt_64(suite) -> [];
-cnt_64(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(cnt_64_test, [MA]),
- ?line unload_master("Test1").
-
-cnt_64_2(X) -> cnt_64(X).
-
-cnt_64_3(X) -> cnt_64(X).
-
-opaque(suite) -> [];
-opaque(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(opaque_test),
- ?line unload_master("Test1").
-
-opaque_2(X) -> opaque(X).
-
-opaque_3(X) -> opaque(X).
-
-
-change_target_addr_config(suite) -> [];
-change_target_addr_config(Config) when list(Config) ->
- p("Testing changing target address config..."),
- ?LOG("change_target_addr_config -> entry",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(sname,snmp_suite),
- put(verbosity,trace),
-
- MA = whereis(snmp_master_agent),
-
- ?LOG("change_target_addr_config -> load TestTrap",[]),
- ?line load_master("TestTrap"),
-
- ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,trace),
-
- %% First send some traps that will arive att the original manager
- ?LOG("change_target_addr_config -> send trap",[]),
- try_test(ma_trap1, [MA]),
-
- ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
-
- %% Start new dummy listener
- ?LOG("change_target_addr_config -> start dummy manager",[]),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
-
- %% Reconfigure
- ?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- %% Send the trap again
- ?LOG("change_target_addr_config -> send trap again",[]),
- catch dummy_manager_send_trap2(Pid),
-
- ?LOG("change_target_addr_config -> await trap ack",[]),
- catch dummy_manager_await_trap2_ack(),
-
- ?LOG("change_target_addr_config -> stop dummy manager",[]),
- ?line ok = dummy_manager_stop(Pid),
-
- ?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
-
- ?LOG("change_target_addr_config -> unload TestTrap",[]),
- ?line unload_master("TestTrap").
-
-
-dummy_manager_start(MA) ->
- ?DBG("dummy_manager_start -> entry",[]),
- Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
- ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
- await_dummy_manager_started(Pid).
-
-await_dummy_manager_started(Pid) ->
- receive
- {dummy_manager_started,Pid,Port} ->
- ?DBG("dummy_manager_start -> acknowledge received with"
- "~n Port: ~p",[Port]),
- {ok,Pid,Port};
- {'EXIT', Pid, Reason} ->
- {error, Pid, Reason};
- O ->
- ?LOG("dummy_manager_start -> received unknown message:"
- "~n ~p",[O]),
- await_dummy_manager_started(Pid)
- end.
-
-dummy_manager_stop(Pid) ->
- ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
- Pid ! stop,
- receive
- {dummy_manager_stopping, Pid} ->
- ?DBG("dummy_manager_stop -> acknowledge received",[]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_stop -> timeout",[]),
- timeout
- end.
-
-dummy_manager_send_trap2(Pid) ->
- ?DBG("dummy_manager_send_trap2 -> entry",[]),
- Pid ! {send_trap,testTrap2}.
-
-dummy_manager_await_trap2_ack() ->
- ?DBG("dummy_manager_await_trap2 -> entry",[]),
- receive
- {received_trap,Trap} ->
- ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
- %% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
- %% is no relation between these two test cases as far as I
- %% able to figure out...
- sleep(60000),
- ok;
- O ->
- ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_await_trap2 -> timeout",[]),
- timeout
- end.
-
-dummy_manager_init(Parent,MA) ->
- ?DBG("dummy_manager_init -> entry with"
- "~n Parent: ~p"
- "~n MA: ~p",[Parent,MA]),
- {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
- ?DBG("dummy_manager_init -> S: ~p",[S]),
- {ok,Port} = inet:port(S),
- ?DBG("dummy_manager_init -> Port: ~p",[Port]),
- Parent ! {dummy_manager_started,self(),Port},
- dummy_manager_loop(Parent,S,MA).
-
-dummy_manager_loop(P,S,MA) ->
- ?LOG("dummy_manager_loop -> ready for receive",[]),
- receive
- {send_trap,Trap} ->
- ?LOG("dummy_manager_loop -> received trap send request"
- "~n Trap: ~p",[Trap]),
- snmpa:send_trap(MA, Trap, "standard trap"),
- dummy_manager_loop(P,S,MA);
- {udp, _UdpId, Ip, UdpPort, Bytes} ->
- ?LOG("dummy_manager_loop -> received upd message"
- "~n from: ~p:~p"
- "~n size: ~p",
- [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
- R = dummy_manager_handle_message(Bytes),
- ?DBG("dummy_manager_loop -> R: ~p",[R]),
- P ! R,
- dummy_manager_loop(P,S,MA);
- stop ->
- ?DBG("dummy_manager_loop -> received stop request",[]),
- P ! {dummy_manager_stopping, self()},
- gen_udp:close(S),
- exit(normal);
- O ->
- ?LOG("dummy_manager_loop -> received unknown message:"
- "~n ~p",[O]),
- dummy_manager_loop(P,S,MA)
- end.
-
-dummy_manager_message_sz(B) when binary(B) ->
- size(B);
-dummy_manager_message_sz(L) when list(L) ->
- length(L);
-dummy_manager_message_sz(_) ->
- undefined.
-
-dummy_manager_handle_message(Bytes) ->
- case (catch snmp_pdus:dec_message(Bytes)) of
- {'EXIT',Reason} ->
- ?ERR("dummy_manager_handle_message -> "
- "failed decoding message only:~n ~p",[Reason]),
- {error,Reason};
- M ->
- ?DBG("dummy_manager_handle_message -> decoded message:"
- "~n ~p",[M]),
- {received_trap,M}
- end.
-
-
-api(suite) -> [];
-api(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(api_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-api_2(X) -> api(X).
-
-api_3(X) -> api(X).
-
-
-subagent(suite) -> [];
-subagent(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- try_test(load_test_sa),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
-
- p("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(load_test),
-
- p("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(unreg_test),
- p("Testing register subagent..."),
- rpc:call(SaNode, snmp, register_subagent,
- [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- ?line stop_subagent(SA),
- try_test(unreg_test).
-
-subagent_2(X) -> subagent(X).
-
-subagent_3(X) -> subagent(X).
-
-
-mnesia(suite) -> [];
-mnesia(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent with mnesia impl..."),
- {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- try_test(big_test_2),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
-
-mnesia_2(X) -> mnesia(X).
-
-mnesia_3(X) -> mnesia(X).
-
-
-
-mul_cases() ->
-[mul_get, mul_get_err, mul_next, mul_next_err,
- mul_set_err].
-
-
-multiple_reqs_3(_X) ->
- {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
-
-
-mul_cases_2() ->
-[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
- mul_set_err_2].
-
-
-mul_cases_3() ->
- [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
-
-
-init_mul(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- [{mul_sub, SA} | Config].
-
-finish_mul(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- SA = ?config(mul_sub, Config),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
- lists:keydelete(mul_sub, 1, Config).
-
-mul_get(suite) -> [];
-mul_get(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get..."),
- try_test(do_mul_get).
-
-mul_get_2(X) -> mul_get(X).
-
-mul_get_3(X) -> mul_get(X).
-
-
-mul_get_err(suite) -> [];
-mul_get_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get with error..."),
- try_test(do_mul_get_err).
-
-mul_get_err_2(X) -> mul_get_err(X).
-
-mul_get_err_3(X) -> mul_get_err(X).
-
-
-mul_next(suite) -> [];
-mul_next(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next).
-
-mul_next_2(X) -> mul_next(X).
-
-mul_next_3(X) -> mul_next(X).
-
-
-mul_next_err(suite) -> [];
-mul_next_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next_err).
-
-mul_next_err_2(X) -> mul_next_err(X).
-
-mul_next_err_3(X) -> mul_next_err(X).
-
-
-mul_set(suite) -> [];
-mul_set(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set..."),
- try_test(do_mul_set).
-
-mul_set_2(X) -> mul_set(X).
-
-mul_set_3(X) -> mul_set(X).
-
-
-mul_set_err(suite) -> [];
-mul_set_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set with error..."),
- try_test(do_mul_set_err).
-
-mul_set_err_2(X) -> mul_set_err(X).
-
-mul_set_err_3(X) -> mul_set_err(X).
-
-
-sa_register(suite) -> [];
-sa_register(Config) when list(Config) ->
- ?DBG("sa_register -> entry", []),
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?DBG("sa_register -> start subagent", []),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
-
- ?DBG("sa_register -> unregister subagent", []),
- p("Testing unregister subagent (2)..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Loading SA-MIB..."),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
- ?DBG("sa_register -> register subagent", []),
- rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
- try_test(sa_mib),
-
- ?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
-
-sa_register_2(X) -> sa_register(X).
-
-sa_register_3(X) -> sa_register(X).
-
-
-v1_trap(suite) -> [];
-v1_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_trap1, [MA]),
- try_test(ma_trap2, [MA]),
- try_test(ma_v2_2_v1_trap, [MA]),
- try_test(ma_v2_2_v1_trap2, [MA]),
-
- p("Testing trap sending from subagent..."),
- try_test(sa_trap1, [SA]),
- try_test(sa_trap2, [SA]),
- try_test(sa_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v2_trap(suite) -> [];
-v2_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
-
- try_test(ma_v2_trap1, [MA]),
- try_test(ma_v2_trap2, [MA]),
- try_test(ma_v1_2_v2_trap, [MA]),
- try_test(ma_v1_2_v2_trap2, [MA]),
-
- try_test(sa_mib),
- p("Testing trap sending from subagent..."),
- try_test(sa_v1_2_v2_trap1, [SA]),
- try_test(sa_v1_2_v2_trap2, [SA]),
- try_test(sa_v1_2_v2_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v3_trap(X) ->
- v2_trap(X).
-
-
-v3_inform(_X) ->
- %% v2_inform(X).
- {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
-
-init_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-init_v3_inform(X) ->
- init_v2_inform(X).
-
-finish_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-finish_v3_inform(X) ->
- finish_v2_inform(X).
-
-
-
-v2_inform_i(suite) -> [];
-v2_inform_i(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing inform sending from master agent... NOTE! This test\ntakes a "
- "few minutes (5) to complete."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_v2_inform1, [MA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2").
-
-v3_inform_i(X) -> v2_inform_i(X).
-
-
-sa_error(suite) -> [];
-sa_error(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing sa bad value (is_set_ok)..."),
- try_test(sa_errs_bad_value),
-
- p("Testing sa gen err (set)..."),
- try_test(sa_errs_gen_err),
-
- p("Testing too big..."),
- try_test(sa_too_big),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- stop_subagent(SA).
-
-sa_error_2(X) -> sa_error(X).
-
-sa_error_3(X) -> sa_error(X).
-
-
-next_across_sa(suite) -> [];
-next_across_sa(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Loading another subagent mib..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
-
- rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- p("Testing next across subagent (endOfMibView from SA)..."),
- try_test(next_across_sa),
-
- p("Unloading mib"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Starting another subagent"),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
- p("Testing next across subagent (wrong prefix from SA)..."),
- try_test(next_across_sa),
-
- stop_subagent(SA),
- stop_subagent(SA2).
-
-next_across_sa_2(X) -> next_across_sa(X).
-
-next_across_sa_3(X) -> next_across_sa(X).
-
-
-undo(suite) -> [];
-undo(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing undo phase at master agent..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
- try_test(undo_test),
- try_test(api_test2),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
-
- p("Testing bad return values from instrum. funcs..."),
- try_test(bad_return),
-
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
-
- p("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
- try_test(undo_test),
- try_test(api_test3),
-
- p("Testing undo phase across master/subagents..."),
- try_test(undo_test),
- try_test(api_test3),
- stop_subagent(SA).
-
-undo_2(X) -> undo(X).
-
-undo_3(X) -> undo(X).
-
-%% Req. Test2
-v1_processing(suite) -> [];
-v1_processing(Config) when list(Config) ->
- ?DBG("v1_processing -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v1_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v2_processing(suite) -> [];
-v2_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v3_processing(suite) -> [];
-v3_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc), % same as v2!
- ?line unload_master("Test2").
-
-
-%% We'll try get/set/trap and inform for all the auth & priv protocols.
-%% For informs, the mgr is auth-engine. The agent has to sync. This is
-%% accomplished by the first inform sent. That one will generate a
-%% report, which makes it in sync. The notification-generating
-%% application times out, and send again. This time it'll work.
-
-v3_crypto_basic(suite) -> [];
-v3_crypto_basic(_Config) ->
- EID = [0,0,0,0,0,0,0,0,0,0,0,2],
- %% From rfc2274 appendix A.3.1
- ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
- ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
- 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
- KMd5_1,
- %% From rfc2274 appendix A.3.2
- ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
- ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
- 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
- KSHA_1,
- %% From rfc2274, appendix A.5.1
- ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
- 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
- snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- %% From rfc2274, appendix A.5.2
- ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
- 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
- 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- KSHA_1t = lists:sublist(KSHA_1, 16),
- KSHA_2t = lists:sublist(KSHA_2, 16),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
- 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
-
- %% Try with correct random
- ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
- ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
- ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
- ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
- ok.
-
-
-
-v3_md5_auth(suite) -> [];
-v3_md5_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing MD5 authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_sha_auth(suite) -> [];
-v3_sha_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing SHA authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_des_priv(suite) -> [];
-v3_des_priv(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing DES encryption...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-%% Make sure mgr is in sync with agent
-v3_sync(Funcs) ->
- ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
- g([[sysDescr, 0]]),
- expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
- g([[sysDescr, 0]]),
- expect(433, [{[sysDescr,0], any}]),
- lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
-
-v3_inform_sync(MA) ->
- ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
- "standard inform", []),
- %% Make sure agent is in sync with mgr...
- ?DBG("v3_sync -> wait some time: ",[]),
- sleep(20000), % more than 1500*10 in target_addr.conf
- ?DBG("v3_sync -> await response",[]),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]).
-
-
-v2_caps(suite) -> [];
-v2_caps(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(v2_caps_i, [node()]).
-
-v2_caps_3(X) -> v2_caps(X).
-
-
-v2_caps_i(Node) ->
- ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
- g([[sysORID, Idx], [sysORDescr, Idx]]),
- ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
- {[sysORDescr, Idx], "test cap"}]),
- ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
- g([[sysORID, Idx]]),
- ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
-
-
-%% Req. Test2
-v1_proc() ->
- ?DBG("v1_proc -> entry", []),
- %% According to RFC1157.
- %% Template: <Section>:<list no>
- v1_get_p(),
- v1_get_next_p(),
- v1_set_p().
-
-
-v1_get_p() ->
- %% 4.1.2:1
- g([[test2]]),
- ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
- g([[tDescr]]),
- ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
- g([[tDescr2,0]]),
- ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
- g([[tDescr3,0]]),
- ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
- g([[tDescr4,0]]),
- ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
- {[tDescr,0], 'NULL'}]),
- g([[sysDescr,3]]),
- ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
-
- %% 4.1.2:2
- g([[tTable]]),
- ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
- g([[tEntry]]),
- ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
-
- %% 4.1.2:3
- g([[tTooBig, 0]]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.2:4
- g([[tGenErr1, 0]]),
- ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]).
-
-
-v1_get_next_p() ->
- %% 4.1.3:1
- gn([[1,3,7,1]]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
- gn([[tDescr2]]),
- ?line expect(11, tooBig, 0, any),
-
- %% 4.1.3:2
- gn([[tTooBig]]),
- io:format("We currently don't handle tooBig correct!!!\n"),
-% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
- ?line expect(20, tooBig, 0, any),
-
- %% 4.1.3:3
- gn([[tGenErr1]]),
-% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
- ?line expect(40, genErr, 1, any),
- gn([[tGenErr2]]),
-% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
- ?line expect(41, genErr, 1, any),
- gn([[sysDescr], [tGenErr3]]),
-% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
-% {[tGenErr3], 'NULL'}]).
- ?line expect(42, genErr, 2, any).
-
-v1_set_p() ->
- %% 4.1.5:1
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
- s([{[tDescr3], s, "noSuchObject"}]),
- ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
- s([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
- s([{[tDescr2,0], s, "inconsistentName"}]),
- ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
-
- %% 4.1.5:2
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.1.5:3
- %% The standard is quite incorrect here. The resp pdu was too big. In
- %% the resp pdu, we have the original vbs. In the tooBig pdu we still
- %% have to original vbs => the tooBig pdu is too big as well!!! It
- %% may not get it to the manager, unless the agent uses 'NULL' instead
- %% of the std-like original value.
- s([{[tTooBig, 0], s, ?tooBigStr}]),
- %% according to std:
-% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.5:4
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
- s([{[tDescr2, 0], s, "commit_fail"}]),
- ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
-
-%% Req. Test2
-v2_proc() ->
- %% According to RFC1905.
- %% Template: <Section>:<list no>
- ?DBG("v2_proc -> entry",[]),
- v2_get_p(),
- v2_get_next_p(),
- v2_get_bulk_p(),
- v2_set_p().
-
-v2_get_p() ->
- %% 4.2.1:2
- ?DBG("v2_get_p -> entry",[]),
- g([[test2]]),
- ?line expect(10, [{[test2], noSuchObject}]),
- g([[tDescr]]),
- ?line expect(11, [{[tDescr], noSuchObject}]),
- g([[tDescr4,0]]),
- ?line expect(12, [{[tDescr4,0], noSuchObject}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
- {[tDescr,0], noSuchObject}]),
- g([[tTable]]),
- ?line expect(14, [{[tTable], noSuchObject}]),
- g([[tEntry]]),
- ?line expect(15, [{[tEntry], noSuchObject}]),
-
- %% 4.2.1:3
- g([[tDescr2,0]]), %% instrum ret noSuchName!!!
- ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
- g([[tDescr3,0]]),
- ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
- g([[sysDescr,3]]),
- ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
- g([[tIndex,1]]),
- ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
-
- %% 4.2.1 - any other error: genErr
- g([[tGenErr1, 0]]),
- ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]),
-
- %% 4.2.1 - tooBig
- g([[tTooBig, 0]]),
- ?line expect(40, tooBig, 0, []).
-
-
-v2_get_next_p() ->
- %% 4.2.2:2
- ?DBG("v2_get_next_p -> entry",[]),
- gn([[1,3,7,1]]),
- ?line expect(10, [{[1,3,7,1], endOfMibView}]),
- gn([[sysDescr], [1,3,7,1]]),
- ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gn([[tCnt2, 1]]),
- ?line expect(12, [{[tCnt2,2], 100}]),
- gn([[tCnt2, 2]]),
- ?line expect(12, [{[tCnt2,2], endOfMibView}]),
-
- %% 4.2.2 - any other error: genErr
- gn([[tGenErr1]]),
- ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
- gn([[tGenErr2]]),
- ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
- gn([[sysDescr], [tGenErr3]]),
- ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
- {[tGenErr3], 'NULL'}]),
-
- %% 4.2.2 - tooBig
- gn([[tTooBig]]),
- ?line expect(20, tooBig, 0, []).
-
-v2_get_bulk_p() ->
- %% 4.2.3
- ?DBG("v2_get_bulk_p -> entry",[]),
- gb(1, 1, []),
- ?line expect(10, []),
- gb(-1, 1, []),
- ?line expect(11, []),
- gb(-1, -1, []),
- ?line expect(12, []),
- gb(-1, -1, []),
- ?line expect(13, []),
- gb(2, 0, [[sysDescr], [1,3,7,1]]),
- ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(1, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(0, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
- ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
- ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[sysDescr, 0], "Erlang SNMP agent"}]),
-
- gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
- ?line expect(19, []),
-
- gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
- ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
- {[sysObjectID], 'NULL'},
- {[tGenErr1], 'NULL'},
- {[sysDescr], 'NULL'}]),
- gb(0, 2, [[tCnt2, 1]]),
- ?line expect(21, [{[tCnt2,2], 100},
- {[tCnt2,2], endOfMibView}]).
-
-
-v2_set_p() ->
- %% 4.2.5:1
- ?DBG("v2_set_p -> entry",[]),
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
-
- %% 4.2.5:2
- s([{[1,3,6,1,0], s, "noSuchObject"}]),
- ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
-
- %% 4.2.5:3
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.2.5:4
- s([{[tStr, 0], s, ""}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
- s([{[tStr, 0], s, "12345"}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
-
- %% 4.2.5:5 - N/A
-
- %% 4.2.5:6
- s([{[tInt1, 0], i, 0}]),
- ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
- s([{[tInt1, 0], i, 5}]),
- ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
- s([{[tInt2, 0], i, 0}]),
- ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
- s([{[tInt2, 0], i, 5}]),
- ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
- s([{[tInt3, 0], i, 5}]),
- ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
-
- %% 4.2.5:7
- s([{[tDescrX, 1, 1], s, "noCreation"}]),
- ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
-
- %% 4.2.5:8
- s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
- ?line expect(80, inconsistentName, 1,
- [{[tDescrX, 1, 2], "inconsistentName"}]),
-
- %% 4.2.5:9
- s([{[tCnt, 1, 2], i, 5}]),
- ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
-
- %% 4.2.5:10
- s([{[tDescr2,0], s, "inconsistentValue"}]),
- ?line expect(100, inconsistentValue, 1,
- [{[tDescr2,0], "inconsistentValue"}]),
-
- %% 4.2.5:11
- s([{[tDescr2,0], s, "resourceUnavailable"}]),
- ?line expect(110, resourceUnavailable, 1,
- [{[tDescr2,0],"resourceUnavailable"}]),
-
- %% 4.2.5:12
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
-
- %% commitFailed and undoFailed is tested by the 'undo' case.
-
-
-%% Req. OLD-SNMPEA-MIB
-table_test() ->
- io:format("Testing simple get, next and set on communityTable...~n"),
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
- Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
- Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
- Key1c4 = [intCommunityAccess,get(mip),is("public")],
- EndKey = [intCommunityEntry,[9],get(mip),is("public")],
- gn([[intCommunityEntry]]),
- ?line expect(7, [{Key1c3, 2}]),
- gn([[intCommunityTable]]),
- ?line expect(71, [{Key1c3, 2}]),
- gn([[community]]),
- ?line expect(72, [{Key1c3, 2}]),
- gn([[otpSnmpeaMIB]]),
- ?line expect(73, [{Key1c3, 2}]),
- gn([[ericsson]]),
- ?line expect(74, [{Key1c3, 2}]),
- gn([Key1c3]),
- ?line expect(8, [{Key2c3, 2}]),
- gn([Key2c3]),
- ?line expect(9, [{Key1c4, 2}]),
- gn([EndKey]),
- AgentIp = [intAgentIpAddress,0],
- ?line expect(10, [{AgentIp, any}]),
- g([Key1c3]),
- ?line expect(11, [{Key1c3, 2}]),
- g([EndKey]),
- ?line ?v1_2(expect(12, noSuchName, 1, any),
- expect(12, [{EndKey, noSuchObject}])),
-
- io:format("Testing row creation/deletion on communityTable...~n"),
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
- s([{NewKeyc5, ?createAndGo}]),
- ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
- s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
- ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
- g([NewKeyc4]),
- ?line expect(16, [{NewKeyc4, 2}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(17, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc4, 2}]),
- ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
- s([{NewKeyc5, ?createAndWait}]),
- ?line expect(19, [{NewKeyc5, ?createAndWait}]),
- g([NewKeyc5]),
- ?line expect(20, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc4, 2}]),
- ?line expect(21, [{NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(22, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc3, 2}]),
- ?line expect(23, [{NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(24, [{NewKeyc5, ?notInService}]),
- s([{NewKeyc5, ?active}]),
- ?line expect(25, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(26, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc3, 3}]),
- ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
- otp_1128().
-
-%% Req. system group
-simple_standard_test() ->
- ?DBG("simple_standard_test -> entry",[]),
- gn([[1,1]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3]]),
- ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6]]),
- ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1]]),
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2]]),
- ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1]]),
- ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1,1]]),
- ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[sysDescr]]),
- ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr,0]]),
- ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr]]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{[sysDescr], noSuchObject}])),
- g([[1,6,7,0]]),
- ?line ?v1_2(expect(41, noSuchName, 1, any),
- expect(3, [{[1,6,7,0], noSuchObject}])),
- gn([[1,13]]),
- ?line ?v1_2(expect(4, noSuchName,1, any),
- expect(4, [{[1,13], endOfMibView}])),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
- g([[sysLocation, 0]]),
- ?line expect(6, [{[sysLocation, 0], "new_value"}]),
- io:format("Testing noSuchName and badValue...~n"),
- s([{[sysServices,0], 3}]),
- ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
- s([{[sysLocation, 0], i, 3}]),
- ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
- ?DBG("simple_standard_test -> done",[]),
- ok.
-
-%% This is run in the agent node
-db_notify_client(suite) -> [];
-db_notify_client(Config) when list(Config) ->
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
- [SaNode,MgrNode,MibDir]),
- snmpa_local_db:register_notify_client(self(),?MODULE),
-
- %% This call (the manager) will issue to set operations, so
- %% we expect to receive to notify(insert) calls.
- try_test(db_notify_client_test),
-
- ?DBG("await first notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
- end,
-
- ?DBG("await second notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
- end,
-
- snmpa_local_db:unregister_notify_client(self()).
-
-
-%% This is run in the manager node
-db_notify_client_test() ->
- ?DBG("set first new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?DBG("set second new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]).
-
-notify(Pid,What) ->
- ?DBG("notify(~p,~p) -> called",[Pid,What]),
- Pid ! {db_notify_test_reply,What}.
-
-
-%% Req: system group, OLD-SNMPEA-MIB, Klas1
-big_test() ->
- ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
- simple_standard_test(),
-
- ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
- gn([[klas1]]),
- ?line expect(1, [{[fname,0], ""}]),
- g([[fname,0]]),
- ?line expect(2, [{[fname,0], ""}]),
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[fname,0]]),
- ?line expect(4, [{[fname,0], "test set"}]),
-
- ?DBG("big_test -> "
- "testing next from last instance in master to subagent...",[]),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname,0], "test set"}]),
- s([{[fname,0], s, ""}]),
- ?line expect(52, [{[fname,0], ""}]),
-
- table_test(),
-
- ?DBG("big_test -> adding one row in subagent table",[]),
- _FTab = [friendsEntry],
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [friendsEntry, [3, 3]]]),
- ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?active}]),
- s([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
-
- otp_1131(),
-
- ?DBG("big_test -> adding two rows in subagent table with special INDEX",
- []),
- s([{[kompissEntry, [1, 3]], s, "kompis3"},
- {[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?createAndGo}]),
- g([[kompissEntry, [1, 3]],
- [kompissEntry, [2, 3]]]),
- ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- gn([[kompissEntry, [1]],
- [kompissEntry, [2]]]),
- ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- s([{[kompissEntry, [1, 2]], s, "kompis3"},
- {[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry, [1, 1]],
- [kompissEntry, [2, 1]]]),
- ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?active}]),
- s([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
- s([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
- ?DBG("big_test -> done",[]),
- ok.
-
-%% Req. system group, Klas2, OLD-SNMPEA-MIB
-big_test_2() ->
- p("Testing simple next/get/set @ master agent (2)..."),
- simple_standard_test(),
-
- p("Testing simple next/get/set @ subagent (2)..."),
- gn([[klas2]]),
- ?line expect(1, [{[fname2,0], ""}]),
- g([[fname2,0]]),
- ?line expect(2, [{[fname2,0], ""}]),
- s([{[fname2,0], s, "test set"}]),
- ?line expect(3, [{[fname2,0], "test set"}]),
- g([[fname2,0]]),
- ?line expect(4, [{[fname2,0], "test set"}]),
-
- otp_1298(),
-
- p("Testing next from last object in master to subagent (2)..."),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname2,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname2,0], "test set"}]),
-
- table_test(),
-
- p("Adding one row in subagent table (2)"),
- _FTab = [friendsEntry2],
- s([{[friendsEntry2, [2, 3]], s, "kompis3"},
- {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?createAndGo}]),
- g([[friendsEntry2, [2, 3]],
- [friendsEntry2, [3, 3]]]),
- ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?active}]),
- s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
-
- p("Adding two rows in subagent table with special INDEX (2)"),
- s([{[kompissEntry2, [1, 3]], s, "kompis3"},
- {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?createAndGo}]),
- g([[kompissEntry2, [1, 3]],
- [kompissEntry2, [2, 3]]]),
- ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- gn([[kompissEntry2, [1]],
- [kompissEntry2, [2]]]),
- ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- s([{[kompissEntry2, [1, 2]], s, "kompis3"},
- {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry2, [1, 1]],
- [kompissEntry2, [2, 1]]]),
- ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?active}]),
- s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
- s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
- ok.
-
-%% Req. Test1
-multi_threaded_test() ->
- p("Testing multi threaded agent..."),
- g([[multiStr,0]]),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(1, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "pelle"}]),
- ?line expect(2, [{[sysLocation, 0], "pelle"}]),
- Pid ! continue,
- ?line expect(3, [{[multiStr,0], "ok"}]),
-
- s([{[multiStr, 0], s, "block"}]),
- Pid2 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(4, [{[sysUpTime,0], any}]),
- g([[multiStr,0]]),
- Pid3 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(5, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "kalle"}]),
- Pid3 ! continue,
- ?line expect(6, [{[multiStr,0], "ok"}]),
- Pid2 ! continue,
- ?line expect(7, [{[multiStr,0], "block"}]),
- ?line expect(8, [{[sysLocation,0], "kalle"}]).
-
-%% Req. Test1, TestTrapv2
-mt_trap_test(MA) ->
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- snmpa:send_trap(MA, mtTrap, "standard trap"),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(2, [{[sysUpTime,0], any}]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- Pid ! continue,
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [2]},
- {[multiStr,0], "ok"}]).
-
-
-get_multi_pid() ->
- get_multi_pid(10).
-get_multi_pid(0) ->
- ?line ?FAIL(no_global_name);
-get_multi_pid(N) ->
- sleep(1000),
- case global:whereis_name(snmp_multi_tester) of
- Pid when pid(Pid) -> Pid;
- _ -> get_multi_pid(N-1)
- end.
-
-%% Req. Test1
-types_v2_test() ->
- p("Testing v2 types..."),
-
- s([{[bits1,0], 2#10}]),
- ?line expect(1, [{[bits1,0], ?str(2#10)}]),
- g([[bits1,0]]),
- ?line expect(2, [{[bits1,0], ?str(2#101)}]),
-
- s([{[bits2,0], 2#11000000110}]),
- ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
- g([[bits2,0]]),
- ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
-
- g([[bits3,0]]),
- ?line expect(50, genErr, 1, any),
-
- g([[bits4,0]]),
- ?line expect(51, genErr, 1, any),
-
- s([{[bits1,0], s, [2#10]}]),
- ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
-
- s([{[bits2,0], 2#11001001101010011}]),
- ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%% Req. Test1
-implied_test(MA) ->
- ?LOG("implied_test -> start",[]),
- p("Testing IMPLIED..."),
-
- snmpa:verbosity(MA,trace),
- snmpa:verbosity(MA,trace),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = "apa",
- Idx2 = "qq",
- ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
- ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
- {[testDescr, Idx1], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
- ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
- {[testDescr, Idx2], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr)",[]),
- gn([[testDescr]]),
- ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
- gn([[testDescr,Idx1]]),
- ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?destroy}]),
- ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?destroy}]),
- ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
-
- %% Try the same in other table
- Idx3 = [1, "apa"],
- Idx4 = [1, "qq"],
- ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
- ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
- {[testDescr2, Idx3], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
- ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
- {[testDescr2, Idx4], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr2)",[]),
- gn([[testDescr2]]),
- ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
- gn([[testDescr2,Idx3]]),
- ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?destroy}]),
- ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?destroy}]),
- ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
-
- snmpa:verbosity(MA,log),
-
- ?LOG("implied_test -> done",[]).
-
-
-
-%% Req. Test1
-sparse_table_test() ->
- p("Testing sparse table..."),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- s([{[sparseStatus, Idx1], i, ?createAndGo},
- {[sparseDescr, Idx1], s, "row 1"}]),
- ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
- {[sparseDescr, Idx1], "row 1"}]),
- s([{[sparseStatus, Idx2], i, ?createAndGo},
- {[sparseDescr, Idx2], s, "row 2"}]),
- ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
- {[sparseDescr, Idx2], "row 2"}]),
- ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
- [sparseStatus,Idx1], [sparseStatus,Idx2]]),
- gb(0,5,[[sparseIndex]])),
- ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
- {[sparseDescr,Idx2], "row 2"},
- {[sparseStatus,Idx1], ?active},
- {[sparseStatus,Idx2], ?active},
- {[sparseStr,0], "slut"}]),
- % Delete the rows
- s([{[sparseStatus, Idx1], i, ?destroy}]),
- ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
- s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
-
-
-%% Req. Test1
-cnt_64_test(MA) ->
- ?LOG("start cnt64 test (~p)",[MA]),
- snmpa:verbosity(MA,trace),
- ?LOG("start cnt64 test",[]),
- p("Testing Counter64, and at the same time, RowStatus is not last column"),
-
- ?DBG("get cnt64",[]),
- g([[cnt64,0]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(1, noSuchName, 1, any),
- expect(1, [{[cnt64,0],18446744073709551615}])),
- ?DBG("get-next cnt64",[]),
- gn([[cnt64]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
- expect(2, [{[cnt64,0],18446744073709551615}])),
- ?DBG("send cntTrap",[]),
- snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
- {cnt64, 10},
- {sysLocation, "here"}]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
- {[sysLocation,0], "here"}]),
- expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [1]},
- {[sysContact,0], "pelle"},
- {[cnt64,0], 10},
- {[sysLocation,0], "here"}])),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- ?DBG("create row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
- ?DBG("create row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
-
- ?DBG("get-next (cntIndex)",[]),
- gn([[cntIndex]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
- expect(3, [{[cntCnt,Idx1], 0}])),
- % Delete the rows
- ?DBG("delete row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
- ?DBG("delete row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
- catch snmpa:verbosity(MA,log),
- ?DBG("done",[]),
- ok.
-
-%% Req. Test1
-opaque_test() ->
- p("Testing Opaque datatype..."),
- g([[opaqueObj,0]]),
- ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
-
-%% Req. OLD-SNMPEA-MIB
-api_test(MaNode) ->
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
- oid_to_name, [OID]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp,
- int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
- List when list(List), length(List) == 8 -> ok;
- List when list(List), length(List) == 11 -> ok
- end.
-
-%% Req. Klas3
-api_test2() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]),
- g([[fname4,0]]),
- ?line expect(2, [{[fname4,0], 1}]).
-
-api_test3() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]).
-
-
-unreg_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[snmpInPkts, 0], any}]).
-
-load_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[fname,0], ""}]).
-
-%% Req. Klas1
-load_test_sa() ->
- gn([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line expect(1, [{[fname,0], any}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_get() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
- [sysName,0]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,0], "test"}]),
- g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
- ?line ?v1_2(expect(2, noSuchName, [1,4], any),
- expect(2, [{[1,3,7,1], noSuchObject},
- {Key1c4, 2},
- {[sysDescr,0], "Erlang SNMP agent"},
- {[1,3,7,2], noSuchObject},
- {Key1c3, 2},
- {[sysDescr,0], "Erlang SNMP agent"}])).
-
-%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
-do_mul_get_err() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(expect(1, noSuchName, 5, any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,2], noSuchInstance}])),
- g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname3,0], noSuchObject},
- {Key1c3, 2},
- {[sysName,1], noSuchInstance}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2}, {[fname,0], "test set"},
- {Key1c3, 2}, {[sysName,0], "test"}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next_err() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[1,3,6,999], endOfMibView},
- {[fname,0], "test set"},
- {[1,3,90], endOfMibView},
- {Key1c3, 2},
- {[sysName,0], "test"}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set() ->
- p("Adding one row in subagent table, and one in master table"),
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [sysLocation,0],
- [friendsEntry, [3, 3]]]),
- ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
- {[sysLocation,0], "new_value"},
- {[friendsEntry, [3, 3]], ?active}]),
- g([NewKeyc4]),
- ?line expect(3, [{NewKeyc4, 2}]),
- s([{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]),
- ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- p("Adding one row in subagent table, and one in master table"),
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {NewKeyc3, 2},
- {[sysUpTime,0], 45}, % sysUpTime (readOnly)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
- g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
- g([NewKeyc4]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB
-sa_mib() ->
- g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
- s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
-
-ma_trap1(MA) ->
- snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
- snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
-
-ma_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap2(MA) ->
- snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
- {ifAdminStatus, [1], 1},
- {ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
-
-sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
-
-ma_v2_trap1(MA) ->
- ?DBG("ma_v2_traps -> entry with MA = ~p => "
- "send standard trap: testTrapv22",[MA]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
- snmpa:send_trap(MA, testTrapv21, "standard trap"),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmp ++ [1]}]).
-
-ma_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
-
-%% Note: This test case takes a while... actually a couple of minutes.
-ma_v2_inform1(MA) ->
- ?DBG("ma_v2_inform -> entry with MA = ~p => "
- "send notification: testTrapv22",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag1, self()},
- "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag1, [_]} ->
- ok;
- {snmp_targets, tag1, Addrs1} ->
- ?line ?FAIL({bad_addrs, Addrs1})
- after
- 5000 ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag1, {got_response, _}} ->
- ok;
- {snmp_notification, tag1, {no_response, _}} ->
- ?line ?FAIL(no_response)
- after
- 20000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
-
- %%
- %% -- The rest is possibly erroneous...
- %%
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag2, self()},
- "standard inform", []),
- ?line expect(2, {inform, false},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag2, [_]} ->
- ok;
- {snmp_targets, tag2, Addrs2} ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
- ?line ?FAIL({bad_addrs, Addrs2})
- after
- 5000 ->
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag2, {got_response, _}} ->
- ?line ?FAIL(got_response);
- {snmp_notification, tag2, {no_response, _}} ->
- ok
- after
- 240000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag2) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end.
-
-
-ma_v1_2_v2_trap(MA) ->
- snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
- {[ifIndex, 1], 1},
- {[snmpTrapEnterprise, 0], [1,2,3]}]).
-
-
-ma_v1_2_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"},
- {[snmpTrapEnterprise, 0], ?system}]).
-
-
-sa_v1_2_v2_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-sa_v1_2_v2_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-sa_v1_2_v2_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_bad_value() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 5}, % badValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, badValue, 2, any),
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
- g([NewKeyc4]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_gen_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},{NewKeyc4, 2},
- {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line expect(1, genErr, 4, any),
-% The row might have been added; we don't know.
-% (as a matter of fact we do - it is added, because the agent
-% first sets its own vars, and then th SAs. Lets destroy it.
- s([{NewKeyc5, ?destroy}]),
- ?line expect(2, [{NewKeyc5, ?destroy}]).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_too_big() ->
- g([[sa, [4,0]]]),
- ?line expect(1, tooBig).
-
-%% Req. Klas1, system group, snmp group (v1/v2)
-next_across_sa() ->
- gn([[sysDescr],[klas1,5]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {[snmpInPkts, 0], any}]).
-
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
-%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
-%% Req. Klas3, Klas4
-undo_test() ->
- s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
- s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
-% unfortunatly we don't know if we'll get undoFailed or commitFailed.
-% it depends on which order the agent traverses the varbind list.
-% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
-% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line expect(6, genErr, 2, any).
-
-%% Req. Klas3, Klas4
-bad_return() ->
- g([[fStatus4,4],
- [fName4,4]]),
- ?line expect(4, genErr, 2, any),
- g([[fStatus4,5],
- [fName4,5]]),
- ?line expect(5, genErr, 1, any),
- g([[fStatus4,6],
- [fName4,6]]),
- ?line expect(6, genErr, 2, any),
- gn([[fStatus4,7],
- [fName4,7]]),
- ?line expect(7, genErr, 2, any),
- gn([[fStatus4,8],
- [fName4,8]]),
- ?line expect(8, genErr, 1, any),
- gn([[fStatus4,9],
- [fName4,9]]),
- ?line expect(9, genErr, 2, any).
-
-
-%%%-----------------------------------------------------------------
-%%% Test the implementation of standard mibs.
-%%% We should *at least* try to GET all variables, just to make
-%%% sure the instrumentation functions work.
-%%% Note that many of the functions in the standard mib is
-%%% already tested by the normal tests.
-%%%-----------------------------------------------------------------
-
-
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v1.
-%% o Test the counters and control objects in SNMP-STANDARD-MIB
-%%-----------------------------------------------------------------
-snmp_standard_mib(suite) -> [];
-snmp_standard_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?DBG("snmp_standard_mib -> std_mib_init", []),
- try_test(std_mib_init),
-
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- InBadVsns = try_test(std_mib_a),
- put(vsn, v2),
- ?DBG("snmp_standard_mib -> std_mib_read", []),
- try_test(std_mib_read),
- put(vsn, v1),
-
- ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
- Bad = try_test(std_mib_b, [InBadVsns]),
- ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
- try_test(std_mib_read, [], [{community, "bad community"}]),
- ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
- try_test(std_mib_write, [], [{community, "public"}]),
- ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
- try_test(std_mib_asn_err),
- ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
- try_test(std_mib_c, [Bad]),
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- try_test(standard_mib_a),
-
- ?DBG("snmp_standard_mib -> std_mib_finish", []),
- try_test(std_mib_finish),
- ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
- try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
- ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
- %% There are some more counters we could test here, but it's not that
- %% important, since they are removed from SNMPv2-MIB.
- ok.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_init() ->
- %% disable authentication failure traps. (otherwise w'd get many of
- %% them - this is also a test to see that it works).
- s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_finish() ->
- %% enable again
- s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_test_finish() ->
- %% force a authenticationFailure
- std_mib_write(),
- %% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_read() ->
- ?DBG("std_mib_read -> entry", []),
- g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
- ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
-
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_write() ->
- ?DBG("std_mib_write -> entry", []),
- s([{[sysLocation, 0], "new_value"}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_asn_err() ->
- snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v2 and v3.
-%% o Test the counters and control objects in SNMPv2-MIB
-%%-----------------------------------------------------------------
-snmpv2_mib_2(suite) -> [];
-snmpv2_mib_2(Config) when list(Config) ->
- ?LOG("snmpv2_mib_2 -> start",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?DBG("snmpv2_mib_2 -> standard mib init",[]),
- try_test(std_mib_init),
-
- ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
- InBadVsns = try_test(std_mib_a),
-
- ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
- put(vsn, v1),
- try_test(std_mib_read),
-
- ?DBG("snmpv2_mib_2 -> bad version read",[]),
- put(vsn, v2),
- Bad = try_test(std_mib_b, [InBadVsns]),
-
- ?DBG("snmpv2_mib_2 -> read with bad community",[]),
- try_test(std_mib_read, [], [{community, "bad community"}]),
-
- ?DBG("snmpv2_mib_2 -> write with public community",[]),
- try_test(std_mib_write, [], [{community, "public"}]),
-
- ?DBG("snmpv2_mib_2 -> asn err",[]),
- try_test(std_mib_asn_err),
-
- ?DBG("snmpv2_mib_2 -> check counters",[]),
- try_test(std_mib_c, [Bad]),
-
- ?DBG("snmpv2_mib_2 -> get som counters",[]),
- try_test(snmpv2_mib_a),
-
- ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
- try_test(std_mib_finish),
-
- ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
- "then disable auth traps",[]),
- try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
-
- ?LOG("snmpv2_mib_2 -> done",[]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_3(suite) -> [];
-snmpv2_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- InBadVsns = try_test(std_mib_a),
- put(vsn, v1),
- try_test(std_mib_read),
- put(vsn, v3),
- _Bad = try_test(std_mib_b, [InBadVsns]),
- try_test(snmpv2_mib_a),
-
- try_test(std_mib_finish).
-
--define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_test_finish() ->
- %% force a authenticationFailure
- ?DBG("ma_v2_inform -> write to std mib",[]),
- std_mib_write(),
-
- %% check that we got a trap
- ?DBG("ma_v2_inform -> await trap",[]),
- ?line expect(2, v2trap, [{[sysUpTime,0], any},
- {[snmpTrapOID,0], ?authenticationFailure}]),
-
- %% and the the inform
- ?DBG("ma_v2_inform -> await inform",[]),
- ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
- {[snmpTrapOID,0],?authenticationFailure}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_a() ->
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
-
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
- InBadVsns.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_b(InBadVsns) ->
- ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
- ?line InBadVsns2 = InBadVsns + 1,
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
- ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
- get_req(4, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
- get_req(1, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_a() ->
- ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
- s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
- {[sysLocation, 0], "val2"}]),
- s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line expect(4, inconsistentValue, 2,
- [{[sysLocation, 0], "val3"},
- {[snmpSetSerialNo,0], SetSerial}]),
- ?line ["val2"] = get_req(5, [[sysLocation,0]]).
-
-
-%%-----------------------------------------------------------------
-%% o Bad community uses/name is tested already
-%% in SNMPv2-MIB and STANDARD-MIB.
-%% o Test add/deletion of rows.
-%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
-snmp_community_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- try_test(snmp_community_mib),
- ?line unload_master("SNMP-COMMUNITY-MIB").
-
-snmp_community_mib_2(X) -> snmp_community_mib(X).
-
-%% Req. SNMP-COMMUNITY-MIB
-snmp_community_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o Test engine boots / time
-%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
-snmp_framework_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- try_test(snmp_framework_mib),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
-
-snmp_framework_mib_2(X) -> snmp_framework_mib(X).
-
-snmp_framework_mib_3(suite) -> [];
-snmp_framework_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(snmp_framework_mib).
-
-
-%% Req. SNMP-FRAMEWORK-MIB
-snmp_framework_mib() ->
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
- sleep(5000),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
- if
- EngineTime+7 < EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- EngineTime+4 > EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- true -> ok
- end,
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
- [Boots] when integer(Boots) -> ok;
- Else -> ?FAIL(Else)
- end,
- ok.
-
-%%-----------------------------------------------------------------
-%% o Test the counters
-%%-----------------------------------------------------------------
-snmp_mpd_mib_3(suite) -> [];
-snmp_mpd_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- UnknownPDUHs = try_test(snmp_mpd_mib_a),
- try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
- try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
-
-
-%% Req. SNMP-MPD-MIB
-snmp_mpd_mib_a() ->
- ?line [UnknownSecs, InvalidMsgs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0]]),
- Pdu = #pdu{type = 'get-request',
- request_id = 23,
- error_status = noError,
- error_index = 0,
- varbinds = []},
- SPdu = #scopedPdu{contextEngineID = "agentEngine",
- contextName = "",
- data = Pdu},
- ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
- V3Hdr1 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [7],
- msgSecurityModel = 23, % bad sec model
- msgSecurityParameters = []},
- V3Hdr2 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [6], % bad flag combination
- msgSecurityModel = 3,
- msgSecurityParameters = []},
- Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
- data = SPDUBytes},
- Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
- data = SPDUBytes},
- ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
- ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
- snmp_test_mgr:send_bytes(MsgBytes1),
- snmp_test_mgr:send_bytes(MsgBytes2),
-
- ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0],
- [snmpUnknownPDUHandlers, 0]]),
- ?line UnknownSecs2 = UnknownSecs + 1,
- ?line InvalidMsgs2 = InvalidMsgs + 1,
- UnknownPDUHs.
-
--define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
-snmp_mpd_mib_b() ->
- g([[sysUpTime,0]]),
- ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
-
-
-snmp_mpd_mib_c(UnknownPDUHs) ->
- ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownPDUHs2 = UnknownPDUHs + 1.
-
-
-snmp_target_mib(suite) -> [];
-snmp_target_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
- try_test(snmp_target_mib),
- ?line unload_master("SNMP-TARGET-MIB").
-
-snmp_target_mib_2(X) -> snmp_target_mib(X).
-
-snmp_target_mib_3(X) -> snmp_target_mib(X).
-
-snmp_target_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-snmp_notification_mib(suite) -> [];
-snmp_notification_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- try_test(snmp_notification_mib),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
-
-snmp_notification_mib_2(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib_3(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o add/delete views and try them
-%% o try boundaries
-%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
-snmp_view_based_acm_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
- snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib() ->
- snmpa:verbosity(net_if,trace),
- snmpa:verbosity(master_agent,trace),
- ?LOG("start snmp_view_based_acm_mib test",[]),
- %% The user "no-rights" is present in USM, and is mapped to security
- %% name 'no-rights", which is not present in VACM.
- %% So, we'll add rights for it, try them and delete them.
- %% We'll give "no-rights" write access to tDescr.0 and read access
- %% to tDescr2.0
- %% These are the options we'll use to the mgr
- Opts = [{user, "no-rights"}, {community, "no-rights"}],
- %% Find the valid secmodel, and one invalid secmodel.
- {SecMod, InvSecMod} =
- case get(vsn) of
- v1 -> {?SEC_V1, ?SEC_V2C};
- v2 -> {?SEC_V2C, ?SEC_USM};
- v3 -> {?SEC_USM, ?SEC_V1}
- end,
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Now, add a mapping from "no-rights" -> "no-rights-group"
- GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
- GRow1 =
- [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
- {GRow1Status, ?createAndGo}],
- ?DBG("set '~p'",[GRow1]),
- ?line try_test(do_set, [GRow1]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create a mapping for another sec model, and make sure it dosn't
- %% give us access
- GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
- GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
- {GRow2Status, ?createAndGo}],
-
- ?DBG("set '~p'",[GRow2]),
- ?line try_test(do_set, [GRow2]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [GRow2Status]),
-
- RVName = "rv_name",
- WVName = "wv_name",
-
- %% Access row
- ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
- ARow1Status = [vacmAccessStatus, ARow1Idx],
- ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
- {[vacmAccessReadViewName, ARow1Idx], RVName},
- {[vacmAccessWriteViewName, ARow1Idx], WVName},
- {ARow1Status, ?createAndGo}],
-
- %% This access row would give acces, if InvSecMod was valid.
- ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
- ARow2Status = [vacmAccessStatus, ARow2Idx],
- ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
- {[vacmAccessReadViewName, ARow2Idx], "internet"},
- {[vacmAccessWriteViewName, ARow2Idx], "internet"},
- {ARow2Status, ?createAndGo}],
-
- ?line try_test(do_set, [ARow2]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [ARow2Status]),
-
-
- %% Add valid row
- ?line try_test(do_set, [ARow1]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create the view family
- VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
- VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
- VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
- VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
- VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
- VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
- VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
- VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
-
- ?line try_test(add_row, [VRow1Status]),
- ?line try_test(add_row, [VRow2Status]),
- ?line try_test(add_row, [VRow3Status]),
-
- %% We're supposed to have access now...
- ?line try_test(use_rights, [], Opts),
-
- %% Change Row3 to Row4
- ?line try_test(del_row, [VRow3Status]),
- ?line try_test(add_row, [VRow4Status]),
-
- %% We should still have access...
- ?line try_test(use_rights, [], Opts),
-
- %% Delete rows
- ?line try_test(del_row, [GRow1Status]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete rest of rows
- ?line try_test(del_row, [ARow1Status]),
- ?line try_test(del_row, [VRow1Status]),
- ?line try_test(del_row, [VRow2Status]),
- ?line try_test(del_row, [VRow4Status]),
-
- ?line try_test(use_no_rights, [], Opts),
- snmpa:verbosity(master_agent,log).
-
-do_set(Row) ->
- s(Row),
- expect(1, Row).
-
-add_row(RowStatus) ->
- s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
-
-del_row(RowStatus) ->
- s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
-
-
-
-use_no_rights() ->
- g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
- g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
- gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
- s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
-
-
-use_rights() ->
- g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
- g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
- s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
- g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
-
-mk_ln(X) ->
- [length(X) | X].
-
-%%-----------------------------------------------------------------
-%% o add/delete users and try them
-%% o test all secLevels
-%% o test all combinations of protocols
-%% o try bad ops; check counters
-%%-----------------------------------------------------------------
-snmp_user_based_sm_mib_3(suite) -> [];
-snmp_user_based_sm_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
-
- %% The newUser used here already has VACM access.
-
- %% Add a new user in the simplest way; just createAndGo
- try_test(v3_sync, [[{usm_add_user1, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new user
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
- DesKey1 = lists:sublist(ShaKey1, 16),
-
- %% Change the new user's keys - 1
- try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- MgrDir = ?config(mgr_dir, Config),
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
- DesKey2 = lists:sublist(ShaKey2, 16),
-
- %% Change the new user's keys - 2
- ?line try_test(v3_sync,
- [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- reset_usm_mgr(MgrDir),
- ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
- ?line load_master("Test2"),
- ?line try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Change the new user's keys - 3
- ?line try_test(v3_sync,
- [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new keys
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Try some read requests
- ?line try_test(v3_sync, [[{usm_read, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Delete the new user
- ?line try_test(v3_sync, [[{usm_del_user, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try some bad requests
- ?line try_test(v3_sync, [[{usm_bad, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("SNMP-USER-BASED-SM-MIB").
-
--define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
-
-usm_add_user1() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
-usm_use_user() ->
- v2_proc().
-
-
-%% Change own public keys
-usm_key_change1(ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_shaxxxxxxxxxx",
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_desxxxxxx",
- DesKey),
- Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change own private keys
-usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change other's public keys
-usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
- s(Vbs1),
- ?line expect(1, noAccess, 1, any),
- Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs2),
- ?line expect(2, noAccess, 1, any),
-
-
- Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs3),
- ?line expect(1, Vbs3).
-
-usm_read() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ?line g([[usmUserSecurityName, NewRowIndex],
- [usmUserCloneFrom, NewRowIndex],
- [usmUserAuthKeyChange, NewRowIndex],
- [usmUserOwnAuthKeyChange, NewRowIndex],
- [usmUserPrivKeyChange, NewRowIndex],
- [usmUserOwnPrivKeyChange, NewRowIndex]]),
- ?line expect(1,
- [{[usmUserSecurityName, NewRowIndex], "newUser"},
- {[usmUserCloneFrom, NewRowIndex], [0,0]},
- {[usmUserAuthKeyChange, NewRowIndex], ""},
- {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
- {[usmUserPrivKeyChange, NewRowIndex], ""},
- {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
- ok.
-
-
-
-usm_del_user() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
--define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
-
--define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
-
--define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
-
--define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
-
--define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
-
--define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
-
-usm_bad() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, inconsistentName, 1, any),
-
- RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs2),
- ?line expect(2, wrongValue, 1, any),
-
- RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs3),
- ?line expect(3, Vbs3),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
- ?line expect(4, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
- ?line expect(5, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
- ?line expect(6, wrongValue, 1, any),
- ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
- ?line expect(7, wrongValue, 1, any),
-
- Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs4),
- ?line expect(1, Vbs4),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Loop through entire MIB, to make sure that all instrum. funcs
-%% works.
-%% Load all std mibs that are not loaded by default.
-%%-----------------------------------------------------------------
-loop_mib(suite) -> [];
-loop_mib(Config) when list(Config) ->
- ?LOG("loop_mib -> initiate case",[]),
- %% snmpa:verbosity(master_agent,debug),
- %% snmpa:verbosity(mib_server,info),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?DBG("loop_mib -> try",[]),
- try_test(loop_mib_1),
- ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- %% snmpa:verbosity(master_agent,log),
- %% snmpa:verbosity(mib_server,silence),
- ?LOG("loop_mib -> done",[]).
-
-
-loop_mib_2(suite) -> [];
-loop_mib_2(Config) when list(Config) ->
- ?LOG("loop_mib_2 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_2 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_2 -> load mibs",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_2 -> unload mibs",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?LOG("loop_mib_2 -> done",[]).
-
-
-loop_mib_3(suite) -> [];
-loop_mib_3(Config) when list(Config) ->
- ?LOG("loop_mib_3 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_3 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_3 -> load mibs",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_3 -> unload mibs",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?LOG("loop_mib_3 -> done",[]).
-
-
-%% Req. As many mibs all possible
-loop_mib_1() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_1([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_1(Oid, N) ->
- ?DBG("loop_it_1 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_1 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_1 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_1(NOid, N+1);
- #pdu{type='get-response', error_status=noSuchName, error_index=1,
- varbinds=[_]} ->
- ?DBG("loop_it_1 -> done",[]),
- N;
-
- #pdu{type = Type, error_status = Err, error_index = Idx,
- varbinds = Vbs} ->
- exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
- end.
-
-%% Req. As many mibs all possible
-loop_mib_2() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_2([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_2(Oid, N) ->
- ?DBG("loop_it_2 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p",[NOid]),
- N;
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_2 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_2(NOid, N+1)
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% Testing of reported bugs and other tickets.
-%%%-----------------------------------------------------------------
-
-
-
-
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1128
-%% Slogan: Bug in handling of createAndWait set-requests.
-%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
-otp_1128(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1128),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1128_2(X) -> otp_1128(X).
-
-otp_1128_3(X) -> otp_1128(X).
-
-otp_1128() ->
- io:format("Testing bug reported in ticket OTP-1128...~n"),
-
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
-
- s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(29, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(31, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(32, [{NewKeyc5, ?destroy}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1129, OTP-1169
-%% Slogan: snmpa:int_to_enum crashes on bad oids
-%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
-otp_1129(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- try_test(otp_1129_i, [node()]),
- ?line unload_master("Klas3").
-
-otp_1129_2(X) -> otp_1129(X).
-
-otp_1129_3(X) -> otp_1129(X).
-
-otp_1129_i(MaNode) ->
- io:format("Testing bug reported in ticket OTP-1129...~n"),
- false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
- false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1131
-%% Slogan: Agent crashes / erlang node halts if RowIndex in a
-%% setrequest is of bad type, e.g. an INDEX {INTEGER},
-%% and RowIdenx [3,2].
-%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
-otp_1131(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas1"),
- try_test(otp_1131),
- ?line unload_master("Klas1").
-
-otp_1131_2(X) -> otp_1131(X).
-
-otp_1131_3(X) -> otp_1131(X).
-
-otp_1131() ->
- io:format("Testing bug reported in ticket OTP-1131...~n"),
- s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
- {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1162
-%% Slogan: snmp_agent can't handle wrongValue from instrum.func
-%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
-otp_1162(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
- try_test(otp_1162),
- stop_subagent(SA).
-
-otp_1162_2(X) -> otp_1162(X).
-
-otp_1162_3(X) -> otp_1162(X).
-
-otp_1162() ->
- s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1222
-%% Slogan: snmp agent crash if faulty index is returned from instrum
-%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
-otp_1222(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
- try_test(otp_1222),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4").
-
-otp_1222_2(X) -> otp_1222(X).
-
-otp_1222_3(X) -> otp_1222(X).
-
-otp_1222() ->
- io:format("Testing bug reported in ticket OTP-1222...~n"),
- s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line expect(1, genErr, 0, any),
- s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line expect(2, genErr, 0, any).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1298
-%% Slogan: Negative INTEGER values are treated as positive.
-%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
-otp_1298(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1298),
- ?line unload_master("Klas2").
-
-otp_1298_2(X) -> otp_1298(X).
-
-otp_1298_3(X) -> otp_1298(X).
-
-otp_1298() ->
- io:format("Testing bug reported in ticket OTP-1298...~n"),
- s([{[fint,0], -1}]),
- ?line expect(1298, [{[fint,0], -1}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1331
-%% Slogan: snmp_generic should return noError when deleting non-ex row
-%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
-otp_1331(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1331),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1331_2(X) -> otp_1331(X).
-
-otp_1331_3(X) -> otp_1331(X).
-
-otp_1331() ->
- NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
- s([{NewKeyc5, ?destroy}]),
- ?line expect(1, [{NewKeyc5, ?destroy}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1338
-%% Slogan: snmp bug in initialisation of default values for mnesia tabs
-%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
-otp_1338(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1338),
- ?line unload_master("Klas2").
-
-otp_1338_2(X) -> otp_1338(X).
-
-otp_1338_3(X) -> otp_1338(X).
-
-otp_1338() ->
- s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
- g([[kName2, 7]]),
- ?line expect(2, [{[kName2, 7], "JJJ"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1342
-%% Slogan: default impl of snmp table can't handle bad index access,
-%% Set when INDEX is read-write gets into an infinite loop!
-%%-----------------------------------------------------------------
-otp_1342(suite) -> [];
-otp_1342(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas4"),
- try_test(otp_1342),
- ?line unload_master("Klas4").
-
-otp_1342_2(X) -> otp_1342(X).
-
-otp_1342_3(X) -> otp_1342(X).
-
-otp_1342() ->
- s([{[fIndex5, 1], i, 1},
- {[fName5, 1], i, 3},
- {[fStatus5, 1], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1366
-%% Slogan: snmp traps not sent to all managers
-%% Note: NYI! We need a way to tell the test server that we need
-%% mgrs on two different machines.
-%%-----------------------------------------------------------------
-otp_1366(suite) -> [];
-otp_1366(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1366),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1366_2(X) -> otp_1366(X).
-
-otp_1366_3(X) -> otp_1366(X).
-
-otp_1366() ->
- ?INF("NOT YET IMPLEMENTED", []),
- 'NYI'.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2776
-%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
-%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
-otp_2776(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_2776).
-
-otp_2776_2(X) -> otp_2776(X).
-
-otp_2776_3(X) -> otp_2776(X).
-
-otp_2776() ->
- io:format("Testing bug reported in ticket OTP-2776...~n"),
-
- Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
- Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
- Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
- Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
- Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
- Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
- Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
- Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
- Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
- Dt10_invalid = [],
- Dt11_invalid = [kalle,hobbe],
- L = [{ 1, true, Dt01_valid},
- { 2, true, Dt02_valid},
- { 3, true, Dt03_valid},
- { 4, false, Dt04_invalid},
- { 5, true, Dt05_valid},
- { 6, true, Dt06_valid},
- { 7, false, Dt07_invalid},
- { 8, true, Dt08_valid},
- { 9, false, Dt09_invalid},
- {10, false, Dt10_invalid},
- {11, false, Dt11_invalid}],
-
- ?line ok = validate_dat(L).
-
-
-validate_dat(L) -> validate_dat(L,[]).
-
-validate_dat([],V) ->
- Fun = fun({_,X}) -> case X of
- ok -> false;
- _ -> true
- end
- end,
- validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
-validate_dat([{Id,E,Dat}|T],V) ->
- validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
-
-validate_dat1([]) -> ok;
-validate_dat1(L) -> {error,L}.
-
-validate_dat2(Id, E, Dat) ->
- Res = case {E,snmp:validate_date_and_time(Dat)} of
- {E,E} -> ok;
- {E,A} -> {E,A}
- end,
- {Id, Res}.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2979
-%% Slogan: get-next on more than 1 column in an empty table
-%% returns bad response.
-%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
-otp_2979(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Test1"),
- ?line init_old(),
- try_test(otp_2979),
- ?line unload_master("Test1").
-
-otp_2979_2(X) -> otp_2979(X).
-
-otp_2979_3(X) -> otp_2979(X).
-
-otp_2979() ->
- gn([[sparseDescr], [sparseStatus]]),
- ?line expect(1, [{[sparseStr,0], "slut"},
- {[sparseStr,0], "slut"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
-%% endOfTable - should return value.
-%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
-otp_3187(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- otp_3187(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-otp_3187_2(X) -> otp_3187(X).
-
-otp_3187_3(X) -> otp_3187(X).
-
-otp_3187() ->
- ?line Elements =
- snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
- lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
- ?FAIL(endOfTable);
- true -> ok
- end
- end, Elements).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3542
-%% Slogan:
-%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
-otp_3542(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_3542).
-
-otp_3542() ->
- io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
- io:format("SNMP v3 discovery result: ~p~n",[Res]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3725
-%% Slogan: Slow response time on snmpa:int_to_enum
-%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
-otp_3725(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-otp_3725_test(MaNode) ->
- io:format("Testing feature requested in ticket OTP-3725...~n"),
- ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
- ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
- ?DBG("otp_3725_test -> Db = ~p",[Db]),
-
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [Db, intAgentIpAddress]),
- ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
- [Db,OID]),
- ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-4394
-%% Slogan: Target mib tag list check invalid
-%%-----------------------------------------------------------------
-
-
-
-init_otp_4394(Config) when list(Config) ->
- ?DBG("init_otp_4394 -> entry with"
- "~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
- MasterAgentVerbosity = {master_agent_verbosity, trace},
- NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
-
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
- ?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
- Vsn = [v1],
- Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
- ?TRAP_UDP, Ip, 4000,
- "OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
- false ->
- ?line ok
- end,
- C1 = {"a", "all-rights", "initial", "", "pc"},
- C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
- Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
- "pc1",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [],
- 2048},
- Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
- "pc2",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
- ok.
-
-
-
-finish_otp_4394(Config) when list(Config) ->
- ?DBG("finish_otp_4394 -> entry", []),
- C1 = stop_agent(Config),
- delete_files(C1),
- erase(mgr_node),
- lists:keydelete(vsn, 1, C1).
-
-otp_4394_test(suite) -> [];
-otp_4394_test(Config) ->
- ?DBG("otp_4394_test -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_4394_test1),
- ?DBG("otp_4394_test -> done", []),
- ok.
-
-otp_4394_test1() ->
- ?DBG("otp_4394_test1 -> entry", []),
- gn([[1,1]]),
- Res =
- case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
- %% {error, 1, {"?",[]}, {"~w",[timeout]}}
- {error, 1, _, {_, [timeout]}} ->
- ?DBG("otp_4394_test1 -> expected result: timeout", []),
- ok;
- Else ->
- Else
- end,
- ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
- Res.
-
-
-%%%--------------------------------------------------
-%%% Used to test the standard mib with our
-%%% configuration.
-%%%--------------------------------------------------
-run(F, A, Opts) ->
- M = get(mib_dir),
- Dir = get(mgr_dir),
- User = snmp_misc:get_option(user, Opts, "all-rights"),
- SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
- EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
- CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
- Community = snmp_misc:get_option(community, Opts, "all-rights"),
- ?DBG("run -> start crypto app",[]),
- Crypto = case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- ?CRYPTO_START()
- end,
- ?DBG("run -> Crypto: ~p",[Crypto]),
- catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- ?DBG("run -> config:~n"
- "\tM: ~p~n"
- "\tDir: ~p~n"
- "\tUser: ~p~n"
- "\tSecLevel: ~p~n"
- "\tEngineID: ~p~n"
- "\tCtxEngineID: ~p~n"
- "\tCommunity: ~p~n"
- "\tStdM: ~p",
- [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
- case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
- {packet_server_debug,true},
- {debug,true},
- {agent, get(master_host)},
- {agent_udp, 4000},
- {trap_udp, 5000},
- {recbuf,65535},
- quiet,
- get(vsn),
- {community, Community},
- {user, User},
- {sec_level, SecLevel},
- {engine_id, EngineID},
- {context_engine_id, CtxEngineID},
- {dir, Dir},
- {mibs, mibs(StdM, M)}]) of
- {ok, _Pid} ->
- Res = apply(?MODULE, F, A),
- catch snmp_test_mgr:stop(),
- Res;
- Err ->
- io:format("Error starting manager: ~p\n", [Err]),
- catch snmp_test_mgr:stop(),
- ?line exit({mgr_start, Err})
- end.
-
-
-mibs(StdMibDir,MibDir) ->
- [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
- join(MibDir, "OLD-SNMPEA-MIB.bin"),
- join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
- join(StdMibDir, "SNMP-MPD-MIB"),
- join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
- join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
- join(StdMibDir, "SNMP-TARGET-MIB"),
- join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
- join(MibDir, "Klas1.bin"),
- join(MibDir, "Klas2.bin"),
- join(MibDir, "Klas3.bin"),
- join(MibDir, "Klas4.bin"),
- join(MibDir, "SA-MIB.bin"),
- join(MibDir, "TestTrap.bin"),
- join(MibDir, "Test1.bin"),
- join(MibDir, "Test2.bin"),
- join(MibDir, "TestTrapv2.bin")].
-
-join(D,F) ->
- filename:join(D,F).
-
-%% string used in index
-is(S) -> [length(S) | S].
-
-try_test(Func) ->
- call(get(mgr_node), ?MODULE, run, [Func, [], []]).
-
-try_test(Func, A) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, []]).
-
-try_test(Func, A, Opts) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
-
-call(N,M,F,A) ->
- ?DBG("call -> entry with~n"
- " N: ~p~n"
- " M: ~p~n"
- " F: ~p~n"
- " A: ~p~n"
- " when~n"
- " get(): ~p",
- [N,M,F,A,get()]),
- spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
- receive
- {done, {'EXIT', Rn}, Loc} ->
- ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
- put(test_server_loc, Loc),
- exit(Rn);
- {done, Ret, Zed} ->
- ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
- Ret
- end.
-
-wait(From, Env, M, F, A) ->
- ?DBG("wait -> entry with ~n"
- "\tFrom: ~p~n"
- "\tEnv: ~p",[From,Env]),
- lists:foreach(fun({K,V}) -> put(K,V) end, Env),
- Rn = (catch apply(M, F, A)),
- ?DBG("wait -> Rn: ~n~p", [Rn]),
- From ! {done, Rn, get(test_server_loc)},
- exit(Rn).
-
-expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
-expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
-expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
-expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
-
-get_req(Id, Vars) ->
- ?DBG("get_req -> entry with~n"
- "\tId: ~p~n"
- "\tVars: ~p",[Id,Vars]),
- g(Vars),
- ?DBG("get_req -> await response",[]),
- {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
- ?DBG("get_req -> response: ~p",[Val]),
- Val.
-
-get_next_req(Vars) ->
- ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
- gn(Vars),
- ?DBG("get_next_req -> await response",[]),
- Response = snmp_test_mgr:receive_response(),
- ?DBG("get_next_req -> response: ~p",[Response]),
- Response.
-
-
-
-start_node(Name) ->
- ?LOG("start_node -> entry with Name: ~p",[Name]),
- M = list_to_atom(?HOSTNAME(node())),
- ?DBG("start_node -> M: ~p",[M]),
- Pa = filename:dirname(code:which(?MODULE)),
- ?DBG("start_node -> Pa: ~p",[Pa]),
-
- Args = case init:get_argument('CC_TEST') of
- {ok, [[]]} ->
- " -pa /clearcase/otp/libraries/snmp/ebin ";
- {ok, [[Path]]} ->
- " -pa " ++ Path;
- error ->
- ""
- end,
- %% Do not use start_link!!! (the proc that calls this one is tmp)
- ?DBG("start_node -> Args: ~p~n",[Args]),
- A = Args ++ " -pa " ++ Pa,
- case (catch ?START_NODE(Name, A)) of
- {ok, Node} ->
- %% Tell the test_server to not clean up things it never started.
- ?DBG("start_node -> Node: ~p",[Node]),
- {ok, Node};
- Else ->
- ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
- ?line ?FAIL(Else)
- end.
-
-
-stop_node(Node) ->
- ?LOG("stop_node -> Node: ~p",[Node]),
- rpc:cast(Node, erlang, halt, []).
-
-p(X) ->
- io:format(user, X++"\n", []).
-
-sleep(X) ->
- receive
- after
- X -> ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Configuration
-%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
- "test"),
- ?line case update_usm(Vsns, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsns, MgrDir);
- false ->
- ?line ok
- end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
- ok.
-
-delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
- lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
-
-update_usm(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-update_usm_mgr(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(filename:join(Dir,"usm.conf"),
- filename:join(Dir,"usm.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- file:close(Fid).
-
-reset_usm_mgr(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"usm.old"),
- filename:join(Dir,"usm.conf")).
-
-
-update_community([v3], _Dir) -> ok;
-update_community(_, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
- []),
- file:close(Fid).
-
-
--define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
-update_vacm(_Vsn, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
- ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
- "~w, excluded, null}.\n", [?tDescr_instance]),
- file:close(Fid).
-
-
-vacm_ver(v1) -> v1;
-vacm_ver(v2) -> v2c;
-vacm_ver(v3) -> usm.
-
-
-write_community_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
- ok = write_community_conf1(Fid, Confs),
- file:close(Fid).
-
-write_community_conf1(_, []) ->
- ok;
-write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
- [ComIdx, ComName, SecName, CtxName, TransTag]),
- write_community_conf1(Fid, Confs).
-
-
-write_target_addr_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- ok = write_target_addr_conf1(Fid, Confs),
- file:close(Fid).
-
-
-write_target_addr_conf1(_, []) ->
- ok;
-write_target_addr_conf1(Fid,
- [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
- [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz]),
- write_target_addr_conf1(Fid, Confs).
-
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- lists:foreach(fun(Vsn) ->
- ok = io:format(Fid,
- "{\"~s\", ~w, ~w, 1500, 3, "
- "\"std_trap\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP, mk_param(Vsn)]),
- case Vsn of
- v1 -> ok;
- v2 ->
- ok = io:format(Fid,
- "{\"~s.2\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)]);
- v3 ->
- ok = io:format(Fid,
- "{\"~s.3\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\", "
- "\"mgrEngine\", [], 1024}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)])
- end
- end,
- Vsns),
- file:close(Fid).
-
-mk_param(v1) -> "target_v1";
-mk_param(v2) -> "target_v2";
-mk_param(v3) -> "target_v3".
-
-mk_ip([A,B,C,D], Vsn) ->
- io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
-
-
-rewrite_target_addr_conf(Dir,NewPort) ->
- TAFile = filename:join(Dir, "target_addr.conf"),
- ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
- case file:read_file_info(TAFile) of
- {ok, _} -> ok;
- {error, R} -> ?ERR("failure reading file info of "
- "target address config file: ~p",[R]),
- ok
- end,
-
- ?line [TrapAddr|Addrs] =
- snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
-
- ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
-
- NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
-
- ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
-
- ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
- filename:join(Dir,"target_addr.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
-
- ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
-
- file:close(Fid).
-
-rewrite_target_addr_conf1(O) ->
- {ok,O}.
-
-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) ->
- ?LOG("rewrite_target_addr_conf2 -> entry with "
- "~n O: ~p",[O]),
- O.
-
-
-rewrite_target_addr_conf3(_,[]) -> ok;
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
- ParamName,EngineId}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % ParamsName
- "\"~s\"}.", % EngineId
- [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
- rewrite_target_addr_conf3(Fid,T);
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
- ParamName,EngineId,TMask,MMS}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % TagList
- "\"~s\", " % ParamsName
- "\"~s\"," % EngineId
- "~p, " % TMask
- "~p}.", % MMS
- [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
- EngineId,TMask,MMS]),
- rewrite_target_addr_conf3(Fid,T).
-
-reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
-
-write_target_params_conf(Dir, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- lists:foreach(fun(Vsn) ->
- MP = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> v3
- end,
- SM = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> usm
- end,
- ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
- "\"all-rights\", noAuthNoPriv}.~n",
- [Vsn, MP, SM])
- end,
- Vsns),
- file:close(Fid).
-
-rewrite_target_params_conf(Dir, SecName, SecLevel) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
- filename:join(Dir,"target_params.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
- [SecName, SecLevel]),
- file:close(Fid).
-
-reset_target_params_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.old"),
- filename:join(Dir,"target_params.conf")).
-
-write_notify_conf(Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
- ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
- ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
- file:close(Fid).
-
-ver_to_trap_str([v1]) -> "v1";
-ver_to_trap_str([v2]) -> "v2";
-% default is to use the latest snmp version
-ver_to_trap_str([v1,v2]) -> "v2".
-
-
-
-write_view_conf(Dir) ->
- {ok, Fid} = file:open(a(Dir,"view.conf"),write),
- ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
- ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
- file:close(Fid).
-
-a(A,B) -> lists:append(A,B).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-copy_file(From, To) ->
- {ok, Bin} = file:read_file(From),
- ok = file:write_file(To, Bin).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-display_memory_usage() ->
- Info = snmpa:info(snmp_master_agent),
- TreeSize = lists_key1search(tree_size_bytes, Info),
- ProcMem = lists_key1search(process_memory, Info),
- MibDbSize = lists_key1search([db_memory,mib], Info),
- NodeDbSize = lists_key1search([db_memory,node], Info),
- TreeDbSize = lists_key1search([db_memory,tree], Info),
- ?INF("Memory usage: "
- "~n Tree size: ~p"
- "~n Process memory size: ~p"
- "~n Mib db size: ~p"
- "~n Node db size: ~p"
- "~n Tree db size: ~p",
- [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
-
-lists_key1search([], Res) ->
- Res;
-lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- lists_key1search(Keys, Val);
- false ->
- undefined
- end;
-lists_key1search(Key, List) when atom(Key) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- Val;
- false ->
- undefined
- end.
-
-
-regs() ->
- lists:sort(registered()).
diff --git a/lib/snmp/test/snmp_agent_v3_test.erl b/lib/snmp/test/snmp_agent_v3_test.erl
deleted file mode 100644
index 266be72878..0000000000
--- a/lib/snmp/test/snmp_agent_v3_test.erl
+++ /dev/null
@@ -1,5649 +0,0 @@
-%%
-%% %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%
-%%
-
--module(snmp_agent_v3_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
--compile(export_all).
-
--define(application, snmp).
-
--include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
--include("snmp_test_lib.hrl").
--define(SNMP_USE_V3, true).
--include_lib("snmp/include/snmp_types.hrl").
-%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
-%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
-
-
--define(klas1, [1,3,6,1,2,1,7]).
--define(klas2, [1,3,6,1,2,1,9]).
--define(klas3, [1,3,6,1,2,1,8,1]).
--define(klas4, [1,3,6,1,2,1,8,4]).
--define(sa, [1,3,6,1,4,1,193,2]).
--define(system, [1,3,6,1,2,1,1]).
--define(snmp, [1,3,6,1,2,1,11]).
--define(snmpTraps, [1,3,6,1,6,3,1,1,5]).
--define(ericsson, [1,3,6,1,4,1,193]).
--define(testTrap, [1,3,6,1,2,1,15,0]).
--define(xDescr, [1,3,6,1,2,1,17,1]).
--define(xDescr2, [1,3,6,1,2,1,17,2]).
-
--define(active, 1).
--define(notInService, 2).
--define(notReady, 3).
--define(createAndGo, 4).
--define(createAndWait, 5).
--define(destroy, 6).
-
--define(TRAP_UDP, 5000).
-
--define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
-
--define(str(X), snmp_pdus:bits_to_str(X)).
-
--define(break(), begin io:format(user, "break at line ~w: pid: ~p\n",
- [?LINE, self()]),
- receive cont -> ok end
- end).
-
-
--import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]).
--define(v1_2(V1,V2),
- case get(vsn) of
- v1 -> V1;
- _ -> V2
- end).
-
--define(v1_2_3(V1,V2,V3),
- case get(vsn) of
- v1 -> V1;
- v2 -> V2;
- _ -> V3
- end).
-
-all() ->
-[cases()].
-
-groups() ->
- [{mib_storage, [],
- [{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()},
- {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]},
- {standard_mibs, [],
- [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]},
- {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]},
- {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]},
- {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]},
- {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]},
- {tickets, [], [{group, otp_4394}]},
- {otp_4394, [], [otp_4394_test]}].
-
-init_per_group(otp_4394, Config) ->
- init_otp_4394(Config);
-init_per_group(v2_inform, Config) ->
- init_v2_inform(Config);
-init_per_group(multiple_reqs_2, Config) ->
- init_mul(Config);
-init_per_group(multiple_reqs, Config) ->
- init_mul(Config);
-init_per_group(test_multi_threaded, Config) ->
- init_mt(Config);
-init_per_group(test_v3, Config) ->
- init_v3(Config);
-init_per_group(test_v1_v2, Config) ->
- init_v1_v2(Config);
-init_per_group(test_v2, Config) ->
- init_v2(Config);
-init_per_group(test_v1, Config) ->
- init_v1(Config);
-init_per_group(mib_storage_varm_mnesia, Config) ->
- init_varm_mib_storage_mnesia(Config);
-init_per_group(mib_storage_varm_dets, Config) ->
- init_varm_mib_storage_dets(Config);
-init_per_group(mib_storage_size_check_mnesia, Config) ->
- init_size_check_msm(Config);
-init_per_group(mib_storage_size_check_dets, Config) ->
- init_size_check_msd(Config);
-init_per_group(mib_storage_size_check_ets, Config) ->
- init_size_check_mse(Config);
-init_per_group(mib_storage_mnesia, Config) ->
- init_mib_storage_mnesia(Config);
-init_per_group(mib_storage_dets, Config) ->
- init_mib_storage_dets(Config);
-init_per_group(mib_storage_ets, Config) ->
- init_mib_storage_ets(Config);
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(otp_4394, Config) ->
- finish_otp_4394(Config);
-end_per_group(v2_inform, Config) ->
- finish_v2_inform(Config);
-end_per_group(multiple_reqs_2, Config) ->
- finish_mul(Config);
-end_per_group(multiple_reqs, Config) ->
- finish_mul(Config);
-end_per_group(test_multi_threaded, Config) ->
- finish_mt(Config);
-end_per_group(test_v3, Config) ->
- finish_v3(Config);
-end_per_group(test_v1_v2, Config) ->
- finish_v1_v2(Config);
-end_per_group(test_v2, Config) ->
- finish_v2(Config);
-end_per_group(test_v1, Config) ->
- finish_v1(Config);
-end_per_group(mib_storage_varm_mnesia, Config) ->
- finish_varm_mib_storage_mnesia(Config);
-end_per_group(mib_storage_varm_dets, Config) ->
- finish_varm_mib_storage_dets(Config);
-end_per_group(mib_storage_size_check_mnesia, Config) ->
- finish_size_check_msm(Config);
-end_per_group(mib_storage_size_check_dets, Config) ->
- finish_size_check_msd(Config);
-end_per_group(mib_storage_size_check_ets, Config) ->
- finish_size_check_mse(Config);
-end_per_group(mib_storage_mnesia, Config) ->
- finish_mib_storage_mnesia(Config);
-end_per_group(mib_storage_dets, Config) ->
- finish_mib_storage_dets(Config);
-end_per_group(mib_storage_ets, Config) ->
- finish_mib_storage_ets(Config);
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- Config.
-
-cases() ->
-case ?OSTYPE() of
- vxworks ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_multi_threaded},
- {group, mib_storage}, {group, tickets}];
- _Else ->
- [app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}]
-end.
-
-
-%%%-----------------------------------------------------------------
-%%% The test case structure is as follows:
-%%%
-%%% init_all - starts mnesia,
-%%%
-%%% init_v1 - starts agent
-%%% simple
-%%% big - e.g. starts/stops subagent, load/unloads mibs
-%%% init_mul
-%%% mul_get
-%%% mul_set
-%%% <etc>
-%%% finish_mul
-%%% <etc>
-%%% finish_v1
-%%%
-%%% init_v2 - starts agent
-%%% finish_v2
-%%%
-%%% init_bilingual - starts agent
-%%% finish_bilingual
-%%%
-%%% finish_all
-%%%
-%%% There is still one problem with these testsuites. If one test
-%%% fails, it may not be possible to run some other cases, as it
-%%% may have e.g. created some row or loaded some table, that it
-%%% didn't undo (since it failed).
-%%%-----------------------------------------------------------------
-
-init_all(Config0) when list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
-
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
-
- %% --
- %% Start nodes
- %%
-
- ?line {ok, SaNode} = start_node(snmp_sa),
- ?line {ok, MgrNode} = start_node(snmp_mgr),
-
-
- %% --
- %% Create necessary files
- %%
-
- Dir = ?config(priv_dir, Config),
- ?DBG("init_all -> Dir ~p", [Dir]),
-
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
-
- file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
-
- file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
-
- file:make_dir(SaDir = filename:join(Dir, "sa_dir/")),
- ?DBG("init_all -> SaDir ~p", [SaDir]),
-
-
- %% --
- %% Start and initiate mnesia
- %%
-
- ?DBG("init_all -> load application mnesia", []),
- ?line ok = application:load(mnesia),
-
- ?DBG("init_all -> load application mnesia on node ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, load, [mnesia]),
-
- ?DBG("init_all -> application mnesia: set_env dir",[]),
- ?line application_controller:set_env(mnesia, dir,
- filename:join(Dir, "Mnesia1")),
-
- ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(Dir, "Mnesia2")]),
-
- ?DBG("init_all -> create mnesia schema",[]),
- ?line ok = mnesia:create_schema([SaNode, node()]),
-
- ?DBG("init_all -> start application mnesia",[]),
- ?line ok = application:start(mnesia),
-
- ?DBG("init_all -> start application mnesia on ~p",[SaNode]),
- ?line ok = rpc:call(SaNode, application, start, [mnesia]),
- Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
- Config].
-
-finish_all(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- stop_node(SaNode),
- stop_node(MgrNode),
- application:stop(mnesia).
-
-start_v1_agent(Config) when list(Config) ->
- start_agent(Config, [v1]).
-
-start_v1_agent(Config,Opts) when list(Config), list(Opts) ->
- start_agent(Config, [v1], Opts).
-
-start_v2_agent(Config) when list(Config) ->
- start_agent(Config, [v2]).
-
-start_v3_agent(Config) when list(Config) ->
- start_agent(Config, [v3]).
-
-start_bilingual_agent(Config) when list(Config) ->
- start_agent(Config, [v1,v2]).
-
-start_multi_threaded_agent(Config) when list(Config) ->
- start_agent(Config, [v2], [{snmp_multi_threaded, true}]).
-
-stop_agent(Config) when list(Config) ->
- ?LOG("stop_agent -> entry with"
- "~n Config: ~p",[Config]),
-
- {Sup, Par} = ?config(snmp_sup, Config),
- ?DBG("stop_agent -> attempt to stop (sup) ~p"
- "~n Sup: ~p"
- "~n Par: ~p",
- [Sup,
- (catch process_info(Sup)),
- (catch process_info(Par))]),
- stop_sup(Sup, Par),
-
- {Sup2, Par2} = ?config(snmp_sub, Config),
- ?DBG("stop_agent -> attempt to stop (sub) ~p"
- "~n Sup2: ~p"
- "~n Par2: ~p",
- [Sup2,
- (catch process_info(Sup2)),
- (catch process_info(Par2))]),
- stop_sup(Sup2, Par2),
-
- ?DBG("stop_agent -> done - now cleanup config", []),
- C1 = lists:keydelete(snmp_sup, 1, Config),
- lists:keydelete(snmp_sub, 1, C1).
-
-
-stop_sup(Pid, _) when node(Pid) == node() ->
- case (catch process_info(Pid)) of
- PI when list(PI) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- exit(Pid, kill),
- await_stopped(Pid, Ref);
- {'EXIT', _Reason} ->
- ?LOG("stop_sup -> ~p not running", [Pid]),
- ok
- end;
-stop_sup(Pid, _) ->
- ?LOG("stop_sup -> attempt to stop ~p", [Pid]),
- Ref = erlang:monitor(process, Pid),
- ?LOG("stop_sup -> Ref: ~p", [Ref]),
- %% Pid ! {'EXIT', Parent, shutdown}, % usch
- exit(Pid, kill),
- await_stopped(Pid, Ref).
-
-await_stopped(Pid, Ref) ->
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ?DBG("received down message for ~p", [Pid]),
- ok
- after 10000 ->
- ?INF("await_stopped -> timeout for ~p",[Pid]),
- erlang:demonitor(Ref),
- ?FAIL({failed_stop,Pid})
- end.
-
-
-start_agent(Config, Vsn) ->
- start_agent(Config, Vsn, []).
-start_agent(Config, Vsn, Opts) ->
- ?LOG("start_agent -> entry (~p) with"
- "~n Config: ~p"
- "~n Vsn: ~p"
- "~n Opts: ~p",[node(), Config, Vsn, Opts]),
-
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
- snmp_app_env_init(vsn_init(Vsn) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, trace},
- {snmp_symbolic_store_verbosity, trace},
- {snmp_note_store_verbosity, trace},
- {snmp_net_if_verbosity, trace}],
- Opts),
-
-
- process_flag(trap_exit,true),
-
- {ok, AppSup} = snmp_app_sup:start_link(),
- unlink(AppSup),
- ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]),
-
- ?DBG("start_agent -> start master agent (old style)",[]),
- Sup = case (catch snmpa_app:start(normal)) of
- {ok, S} ->
- ?DBG("start_agent -> started, Sup: ~p",[S]),
- S;
-
- Else ->
- ?DBG("start_agent -> unknown result: ~n~p",[Else]),
- %% Get info about the apps we depend on
- MnesiaInfo = mnesia_running(),
- ?FAIL({start_failed,Else,MnesiaInfo})
- end,
-
- ?DBG("start_agent -> unlink from supervisor",[]),
- ?line unlink(Sup),
- ?line SaDir = ?config(sa_dir, Config),
- ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]),
- ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]),
- ?DBG("start_agent -> done",[]),
- ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config].
-
-
-vsn_init(Vsn) ->
- vsn_init([v1,v2,v3], Vsn, []).
-
-vsn_init([], _Vsn, Acc) ->
- Acc;
-vsn_init([V|Vsns], Vsn, Acc) ->
- case lists:member(V, Vsn) of
- true ->
- vsn_init(Vsns, Vsn, [{V, true}|Acc]);
- false ->
- vsn_init(Vsns, Vsn, [{V, false}|Acc])
- end.
-
-snmp_app_env_init(Env0, Opts) ->
- ?DBG("snmp_app_env_init -> unload snmp",[]),
- ?line application:unload(snmp),
- ?DBG("snmp_app_env_init -> load snmp",[]),
- ?line application:load(snmp),
- ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]),
- F1 = fun({Key,Val} = New, Acc0) ->
- ?DBG("snmp_app_env_init -> "
- "updating setting ~p to ~p", [Key, Val]),
- case lists:keyreplace(Key, 1, Acc0, New) of
- Acc0 ->
- [New|Acc0];
- Acc ->
- Acc
- end
- end,
- Env = lists:foldr(F1, Env0, Opts),
- ?DBG("snmp_app_env_init -> Env: ~p",[Env]),
- F2 = fun({Key,Val}) ->
- ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]),
- application_controller:set_env(snmp, Key, Val)
- end,
- lists:foreach(F2, Env).
-
-
-
-
-%% Test if application is running
-mnesia_running() -> ?IS_MNESIA_RUNNING().
-crypto_running() -> ?IS_CRYPTO_RUNNING().
-
-
-start_sub(Dir) ->
- ?DBG("start_sub -> entry",[]),
- Opts = [{db_dir, Dir},
- {supervisor, [{verbosity, trace}]}],
- %% BMK BMK
-% {ok, P} = snmp_supervisor:start_sub(Dir),
- {ok, P} = snmpa_supervisor:start_sub_sup(Opts),
- unlink(P),
- {ok, {P, self()}}.
-
-create_tables(SaNode) ->
- ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
- {ram_copies, [SaNode]},
- {snmp, [{key, integer}]},
- {attributes, [a1,a2,a3]}]),
- ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
- {attributes, [a1,a2]}]).
-
-delete_tables() ->
- mnesia:delete_table(friendsTable2),
- mnesia:delete_table(kompissTable2),
- mnesia:delete_table(snmp_variables).
-
-%% Creation is done in runtime!
-delete_mib_storage_mnesia_tables() ->
- mnesia:delete_table(snmpa_mib_data),
- mnesia:delete_table(snmpa_mib_tree),
- mnesia:delete_table(snmpa_symbolic_store).
-
-%%-----------------------------------------------------------------
-%% A test case is always one of:
-%% - v1 specific case
-%% - v2 specific case
-%% - v1 and v2 case
-%% All v1 specific cases are prefixed with v1_, and all v2 with
-%% v2_. E.g. v1_trap/v2_trap.
-%%
-%% All other cases are shared. However, the testserver uses the name
-%% of the case to generate a file for that case. The same case cannot
-%% be used in different configurations in the same suite. Therefore
-%% all these functions exists in two variants, the base function
-%% <base>, and a second version <base>_2. There may be several
-%% versions as well, <base>_N.
-%%-----------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-mib_storage_ets_cases() ->
-[mse_simple, mse_v1_processing, mse_big, mse_big2,
- mse_loop_mib, mse_api, mse_sa_register, mse_v1_trap,
- mse_sa_error, mse_next_across_sa, mse_undo,
- mse_standard_mib, mse_community_mib, mse_framework_mib,
- mse_target_mib, mse_notification_mib,
- mse_view_based_acm_mib, mse_sparse_table, mse_me_of,
- mse_mib_of].
-
-mib_storage_dets_cases() ->
-[msd_simple, msd_v1_processing, msd_big, msd_big2,
- msd_loop_mib, msd_api, msd_sa_register, msd_v1_trap,
- msd_sa_error, msd_next_across_sa, msd_undo,
- msd_standard_mib, msd_community_mib, msd_framework_mib,
- msd_target_mib, msd_notification_mib,
- msd_view_based_acm_mib, msd_sparse_table, msd_me_of,
- msd_mib_of].
-
-mib_storage_mnesia_cases() ->
-[msm_simple, msm_v1_processing, msm_big, msm_big2,
- msm_loop_mib, msm_api, msm_sa_register, msm_v1_trap,
- msm_sa_error, msm_next_across_sa, msm_undo,
- msm_standard_mib, msm_community_mib, msm_framework_mib,
- msm_target_mib, msm_notification_mib,
- msm_view_based_acm_mib, msm_sparse_table, msm_me_of,
- msm_mib_of].
-
-mse_size_check_cases() ->
-[mse_size_check].
-
-msd_size_check_cases() ->
-[msd_size_check].
-
-msm_size_check_cases() ->
-[msm_size_check].
-
-varm_mib_storage_dets_cases() ->
-[msd_varm_mib_start].
-
-varm_mib_storage_mnesia_cases() ->
-[msm_varm_mib_start].
-
-init_mib_storage_ets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,ets},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- init_ms(Config, [MibStorage]).
-
-init_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- init_ms(Config, [MibStorage]).
-
-init_ms(Config, Opts) when list(Config) ->
- ?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
-
-init_size_check_mse(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, ets},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msd(Config) when list(Config) ->
- AgentDir = ?GCONF(agent_dir, Config),
- MibStorage = {snmp_mib_storage, {dets, AgentDir}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_msm(Config) when list(Config) ->
- MibStorage = {snmp_mib_storage, {mnesia,[]}},
- init_size_check_ms(Config, [MibStorage]).
-
-init_size_check_ms(Config, Opts) when list(Config) ->
- SaNode = ?GCONF(snmp_sa, Config),
- %% We are using v3 here, so crypto must be supported or else...
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end,
- create_tables(SaNode),
- AgentDir = ?GCONF(agent_dir, Config),
- MgrDir = ?GCONF(mgr_dir, Config),
- Ip = ?GCONF(ip, Config),
- ?line ok =
- config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_agent(Config, [v3], Opts)].
-
-init_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_dets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{dets,AgentDir}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-init_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("init_varm_mib_storage_mnesia -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- MibStorage = {snmp_mib_storage,{mnesia,[]}},
- MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
- MibsVerbosity = {snmp_mibserver_verbosity, trace},
- SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity],
- [{vsn, v1}, {agent_opts,Opts} | Config].
-
-finish_mib_storage_ets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_ets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_mib_storage_dets -> entry", []),
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- C2 = lists:keydelete(vsn, 1, C1),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_dets(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_dets -> entry", []),
- delete_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_varm_mib_storage_mnesia(Config) when list(Config) ->
- ?LOG("finish_varm_mib_storage_mnesia -> entry", []),
- delete_tables(),
- delete_mib_storage_mnesia_tables(),
- %% C1 = stop_agent(Config), % In case something went wrong...
- delete_files(Config),
- C2 = lists:keydelete(vsn, 1, Config),
- lists:keydelete(agent_opts, 1, C2).
-
-finish_size_check_mse(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msd(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_msm(Config) when list(Config) ->
- finish_size_check_ms(Config).
-
-finish_size_check_ms(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%% These are just interface functions to fool the test server
-mse_simple(X) -> simple(X).
-mse_v1_processing(X) -> v1_processing(X).
-mse_big(X) -> big(X).
-mse_big2(X) -> big2(X).
-mse_loop_mib(X) -> loop_mib(X).
-mse_api(X) -> api(X).
-mse_sa_register(X) -> sa_register(X).
-mse_v1_trap(X) -> v1_trap(X).
-mse_sa_error(X) -> sa_error(X).
-mse_next_across_sa(X) -> next_across_sa(X).
-mse_undo(X) -> undo(X).
-mse_standard_mib(X) -> snmp_standard_mib(X).
-mse_community_mib(X) -> snmp_community_mib(X).
-mse_framework_mib(X) -> snmp_framework_mib(X).
-mse_target_mib(X) -> snmp_target_mib(X).
-mse_notification_mib(X) -> snmp_notification_mib(X).
-mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-mse_sparse_table(X) -> sparse_table(X).
-mse_me_of(X) -> ms_me_of(X).
-mse_mib_of(X) -> ms_mib_of(X).
-
-msd_simple(X) -> simple(X).
-msd_v1_processing(X) -> v1_processing(X).
-msd_big(X) -> big(X).
-msd_big2(X) -> big2(X).
-msd_loop_mib(X) -> loop_mib(X).
-msd_api(X) -> api(X).
-msd_sa_register(X) -> sa_register(X).
-msd_v1_trap(X) -> v1_trap(X).
-msd_sa_error(X) -> sa_error(X).
-msd_next_across_sa(X) -> next_across_sa(X).
-msd_undo(X) -> undo(X).
-msd_standard_mib(X) -> snmp_standard_mib(X).
-msd_community_mib(X) -> snmp_community_mib(X).
-msd_framework_mib(X) -> snmp_framework_mib(X).
-msd_target_mib(X) -> snmp_target_mib(X).
-msd_notification_mib(X) -> snmp_notification_mib(X).
-msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msd_sparse_table(X) -> sparse_table(X).
-msd_me_of(X) -> ms_me_of(X).
-msd_mib_of(X) -> ms_mib_of(X).
-
-msm_simple(X) -> simple(X).
-msm_v1_processing(X) -> v1_processing(X).
-msm_big(X) -> big(X).
-msm_big2(X) -> big2(X).
-msm_loop_mib(X) -> loop_mib(X).
-msm_api(X) -> api(X).
-msm_sa_register(X) -> sa_register(X).
-msm_v1_trap(X) -> v1_trap(X).
-msm_sa_error(X) -> sa_error(X).
-msm_next_across_sa(X) -> next_across_sa(X).
-msm_undo(X) -> undo(X).
-msm_standard_mib(X) -> snmp_standard_mib(X).
-msm_community_mib(X) -> snmp_community_mib(X).
-msm_framework_mib(X) -> snmp_framework_mib(X).
-msm_target_mib(X) -> snmp_target_mib(X).
-msm_notification_mib(X) -> snmp_notification_mib(X).
-msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X).
-msm_sparse_table(X) -> sparse_table(X).
-msm_me_of(X) -> ms_me_of(X).
-msm_mib_of(X) -> ms_mib_of(X).
-
-
-mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X).
-msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X).
-msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X).
-
-msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X).
-msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X).
-
-ms_size_check(suite) -> [];
-ms_size_check(Config) when list(Config) ->
- p("ms_size_check..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?LOG("mib server size check...", []),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMPv2-MIB"),
- ?line load_master_std("SNMPv2-TM"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMPv2-MIB"),
- ?line unload_master("SNMPv2-TM"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-
-varm_mib_start(suite) -> [];
-varm_mib_start(Config) when list(Config) ->
- p("varm_mib_start..."),
- ?LOG("varm_mib_start -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- %% Start the agent
- Opts = ?GCONF(agent_opts, Config),
- Config1 = start_v1_agent(Config, Opts),
-
- %% Sleep some in order for the agent to start properly
- ?DBG("varm_mib_start -> sleep some (before loading mobs)", []),
- ?SLEEP(5000),
-
- %% Load all the mibs
- HardwiredMibs = loaded_mibs(),
- ?DBG("varm_mib_start -> load all mibs", []),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
-
- %% Unload the hardwired mibs
- ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []),
- ?SLEEP(1000),
- ?DBG("varm_mib_start -> unload (hardwired) mibs", []),
- ?line unload_mibs(HardwiredMibs), %% unload hardwired
-
- ?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
- ?SLEEP(1000),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- Config2 = stop_agent(Config1),
-
- %% Sleep some in order for the agent to stop properly
- ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []),
- ?SLEEP(5000),
-
- %% Start the agent (again)
- ?DBG("varm_mib_start -> start the agent", []),
- Config3 = start_v1_agent(Config2, Opts),
-
- ?DBG("varm_mib_start -> sleep some (before starting tests)", []),
- ?SLEEP(5000),
-
- %% Perform the test(s)
- ?DBG("varm_mib_start -> perform the tests", []),
- try_test(snmp_community_mib),
- try_test(snmp_framework_mib),
- try_test(snmp_target_mib),
- try_test(snmp_notification_mib),
-
- %% Stop the agent (without deleting the stored files)
- ?DBG("varm_mib_start -> stop the agent", []),
- stop_agent(Config3),
- ok.
-
-
--define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]).
--define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]).
--define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-ms_me_of(suite) -> [];
-ms_me_of(Config) when list(Config) ->
- p("ms_me_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = me_of(?snmpTrapCommunity_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = me_of(?vacmViewSpinLock_instance),
-
- ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-me_of(Oid) ->
- case snmpa:me_of(Oid) of
- {ok, #me{oid = Oid}} ->
- ok;
- {ok, #me{oid = OtherOid}} ->
- case lists:reverse(Oid) of
- [0|Rest] ->
- case lists:reverse(Rest) of
- OtherOid ->
- ok;
- AnotherOid ->
- {error, {invalid_oid, Oid, AnotherOid}}
- end;
- _ ->
- {error, {invalid_oid, Oid, OtherOid}}
- end;
- {error, Reason} ->
- {error, Reason};
- Else ->
- {error, Else}
- end.
-
-
-ms_mib_of(suite) -> [];
-ms_mib_of(Config) when list(Config) ->
- p("ms_mib_of..."),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
- ?line load_master_std("OTP-SNMPEA-MIB"),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?SLEEP(2000),
-
- ?line display_memory_usage(),
-
-
- ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
- [?snmpTrapCommunity_instance]),
- ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
- [?vacmViewSpinLock_instance]),
- ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'),
-
- ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB",
- [?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance,
- 'SNMP-USER-BASED-SM-MIB'),
-
-
- ?line unload_master("OTP-SNMPEA-MIB"),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
-
- ok.
-
-mib_of(Oid, ExpectedMibName) ->
- ?DBG("mib_of -> entry with"
- "~n Oid: ~p"
- "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]),
- %% case snmpa:mib_of(Oid) of
- MibOf = snmpa:mib_of(Oid),
- ?DBG("mib_of -> MibOf: ~n~p", [MibOf]),
- case MibOf of
- {ok, ExpectedMibName} ->
- ok;
- {ok, OtherMibName} ->
- {error, {invalid_mib, ExpectedMibName, OtherMibName}};
- {error, Reason} ->
- {error, Reason};
- Else ->
- ?DBG("mib_of -> Else: ~n~p", [Else]),
- {error, Else}
- end.
-
-
-app_info(suite) -> [];
-app_info(Config) when list(Config) ->
- SnmpDir = app_dir(snmp),
- SslDir = app_dir(ssl),
- CryptoDir = app_dir(crypto),
- Attr = snmp:module_info(attributes),
- AppVsn =
- case lists:keysearch(app_vsn, 1, Attr) of
- {value, {app_vsn, V}} ->
- V;
- false ->
- "undefined"
- end,
- io:format("Root dir: ~s~n"
- "SNMP: Application dir: ~s~n"
- " Application ver: ~s~n"
- "SSL: Application dir: ~s~n"
- "CRYPTO: Application dir: ~s~n",
- [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]),
- ok.
-
-app_dir(App) ->
- case code:lib_dir(App) of
- D when list(D) ->
- filename:basename(D);
- {error, _Reason} ->
- "undefined"
- end.
-
-
-
-%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].
-
-init_v1(Config) when list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v1} | start_v1_agent(Config)].
-
-finish_v1(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v2_cases() -> [loop_mib_2];
-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].
-
-init_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_v2_agent(Config)].
-
-finish_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-v1_v2_cases() ->
-[simple_bi].
-
-init_v1_v2(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, bilingual} | start_bilingual_agent(Config)].
-
-finish_v1_v2(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-%v3_cases() -> [loop_mib_3];
-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].
-
-init_v3(Config) when list(Config) ->
- %% Make sure crypto works, otherwise start_agent will fail
- %% and we will be stuck with a bunch of mnesia tables for
- %% the rest of this suite...
- ?DBG("start_agent -> start crypto app",[]),
- case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- case ?CRYPTO_START() of
- ok ->
- case ?CRYPTO_SUPPORT() of
- {no, Reason} ->
- ?SKIP({unsupported_encryption, Reason});
- yes ->
- ok
- end;
- {error, Reason} ->
- ?SKIP({failed_starting_crypto, Reason})
- end
- end,
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
- tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v3} | start_v3_agent(Config)].
-
-finish_v3(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-
-mt_cases() ->
-[multi_threaded, mt_trap].
-
-init_mt(Config) when list(Config) ->
- SaNode = ?config(snmp_sa, Config),
- create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
- MgrDir = ?config(mgr_dir, Config),
- Ip = ?config(ip, Config),
- ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
- [{vsn, v2} | start_multi_threaded_agent(Config)].
-
-finish_mt(Config) when list(Config) ->
- delete_tables(),
- C1 = stop_agent(Config),
- delete_files(C1),
- lists:keydelete(vsn, 1, C1).
-
-%% This one *must* be run first in each case.
-init_case(Config) when list(Config) ->
- ?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
-
- SaHost = ?HOSTNAME(SaNode),
- MgrHost = ?HOSTNAME(MgrNode),
- MasterHost = ?HOSTNAME(MasterNode),
- {ok, MasterIP} = snmp_misc:ip(MasterHost),
- {ok, MIP} = snmp_misc:ip(MgrHost),
- {ok, SIP} = snmp_misc:ip(SaHost),
-
-
- put(mgr_node, MgrNode),
- put(sa_node, SaNode),
- put(master_node, MasterNode),
- put(sa_host, SaHost),
- put(mgr_host, MgrHost),
- put(master_host, MasterHost),
- put(mip, tuple_to_list(MIP)),
- put(masterip , tuple_to_list(MasterIP)),
- put(sip, tuple_to_list(SIP)),
-
- MibDir = ?config(mib_dir, Config),
- put(mib_dir, MibDir),
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- put(std_mib_dir, StdM),
-
- MgrDir = ?config(mgr_dir, Config),
- put(mgr_dir, MgrDir),
-
- put(vsn, ?config(vsn, Config)),
- ?DBG("init_case -> exit with"
- "~n MasterNode: ~p"
- "~n SaNode: ~p"
- "~n MgrNode: ~p"
- "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]),
- {SaNode, MgrNode, MibDir}.
-
-load_master(Mib) ->
- ?DBG("load_master -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]).
-
-load_master_std(Mib) ->
- ?DBG("load_master_std -> entry with"
- "~n Mib: ~p", [Mib]),
- snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety
- ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]).
-
-unload_master(Mib) ->
- ?DBG("unload_master -> entry with"
- "~n Mib: ~p", [Mib]),
- ok = snmpa:unload_mibs(snmp_master_agent, [Mib]).
-
-loaded_mibs() ->
- ?DBG("loaded_mibs -> entry",[]),
- Info = snmpa:info(snmp_master_agent),
- {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info),
- [atom_to_list(Mib) || {Mib,_,_} <- Mibs].
-
-unload_mibs(Mibs) ->
- ?DBG("unload_mibs -> entry with"
- "~n Mibs: ~p", [Mibs]),
- ok = snmpa:unload_mibs(snmp_master_agent, Mibs).
-
-start_subagent(SaNode, RegTree, Mib) ->
- ?DBG("start_subagent -> entry with"
- "~n SaNode: ~p"
- "~n RegTree: ~p"
- "~n Mib: ~p", [SaNode, RegTree, Mib]),
- MA = whereis(snmp_master_agent),
- ?DBG("start_subagent -> MA: ~p", [MA]),
- MibDir = get(mib_dir),
- Mib1 = join(MibDir,Mib),
- %% BMK BMK
-% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of
- case rpc:call(SaNode, snmpa_supervisor,
- start_sub_agent, [MA, RegTree, [Mib1]]) of
- {ok, SA} ->
- ?DBG("start_subagent -> SA: ~p", [SA]),
- {ok, SA};
- Error ->
- ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]})
- end.
-
-stop_subagent(SA) ->
- ?DBG("stop_subagent -> entry with"
- "~n SA: ~p", [SA]),
- %% BNK BMK
- %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]).
- rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]).
-
-%%-----------------------------------------------------------------
-%% This function takes care of the old OTP-SNMPEA-MIB.
-%% Unfortunately, the testcases were written to use the data in the
-%% internal tables, and these table are now obsolete and not used
-%% by the agent. Therefore, we emulate them by using
-%% OLD-SNMPEA-MIB, which uses the default impl. of all tables.
-%%
-%% These two rows must exist in intCommunityTable
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
-%% (But with the manager's IP address)
-%%
-%%-----------------------------------------------------------------
-init_old() ->
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [6 | "public"],
- {get(mip), "public", 2, 2}),
- snmpa_local_db:table_create_row(intCommunityTable,
- get(mip) ++ [13 | "standard trap"],
- {get(mip), "standard trap", 2, 1}),
- snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]).
-
-
-
-simple(suite) -> [];
-simple(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(simple_standard_test).
-
-simple_2(X) -> simple(X).
-
-simple_bi(suite) -> [];
-simple_bi(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(vsn, v1), % First, try v1 manager
- try_test(simple_standard_test),
-
- put(vsn, v2), % Then, try v2 manager
- try_test(simple_standard_test).
-
-simple_3(X) ->
- simple(X).
-
-big(suite) -> [];
-big(Config) when list(Config) ->
- ?DBG("big -> entry", []),
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-big_2(X) -> big(X).
-
-big_3(X) -> big(X).
-
-
-big2(suite) -> [];
-big2(Config) when list(Config) ->
- %% This is exactly the same tests as 'big', but with the
- %% v2 equivalent of the mibs.
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
- try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
-
-big2_2(X) -> big2(X).
-
-big2_3(X) -> big2(X).
-
-
-multi_threaded(suite) -> [];
-multi_threaded(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(multi_threaded_test),
- ?line unload_master("Test1").
-
-mt_trap(suite) -> [];
-mt_trap(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- ?line load_master("TestTrapv2"),
- try_test(mt_trap_test, [MA]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("Test1").
-
-v2_types(suite) -> [];
-v2_types(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(types_v2_test),
- ?line unload_master("Test1").
-
-v2_types_3(X) -> v2_types(X).
-
-
-implied(suite) -> [];
-implied(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(implied_test,[MA]),
- ?line unload_master("Test1").
-
-implied_3(X) -> implied(X).
-
-
-sparse_table(suite) -> [];
-sparse_table(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(sparse_table_test),
- ?line unload_master("Test1").
-
-sparse_table_2(X) -> sparse_table(X).
-
-sparse_table_3(X) -> sparse_table(X).
-
-cnt_64(suite) -> [];
-cnt_64(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test1"),
- try_test(cnt_64_test, [MA]),
- ?line unload_master("Test1").
-
-cnt_64_2(X) -> cnt_64(X).
-
-cnt_64_3(X) -> cnt_64(X).
-
-opaque(suite) -> [];
-opaque(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test1"),
- try_test(opaque_test),
- ?line unload_master("Test1").
-
-opaque_2(X) -> opaque(X).
-
-opaque_3(X) -> opaque(X).
-
-
-change_target_addr_config(suite) -> [];
-change_target_addr_config(Config) when list(Config) ->
- p("Testing changing target address config..."),
- ?LOG("change_target_addr_config -> entry",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- put(sname,snmp_suite),
- put(verbosity,trace),
-
- MA = whereis(snmp_master_agent),
-
- ?LOG("change_target_addr_config -> load TestTrap",[]),
- ?line load_master("TestTrap"),
-
- ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,trace),
-
- %% First send some traps that will arive att the original manager
- ?LOG("change_target_addr_config -> send trap",[]),
- try_test(ma_trap1, [MA]),
-
- ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
-
- %% Start new dummy listener
- ?LOG("change_target_addr_config -> start dummy manager",[]),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
-
- %% Reconfigure
- ?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- %% Send the trap again
- ?LOG("change_target_addr_config -> send trap again",[]),
- catch dummy_manager_send_trap2(Pid),
-
- ?LOG("change_target_addr_config -> await trap ack",[]),
- catch dummy_manager_await_trap2_ack(),
-
- ?LOG("change_target_addr_config -> stop dummy manager",[]),
- ?line ok = dummy_manager_stop(Pid),
-
- ?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
-
- ?LOG("change_target_addr_config -> unload TestTrap",[]),
- ?line unload_master("TestTrap").
-
-
-dummy_manager_start(MA) ->
- ?DBG("dummy_manager_start -> entry",[]),
- Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]),
- ?DBG("dummy_manager_start -> Pid: ~p",[Pid]),
- await_dummy_manager_started(Pid).
-
-await_dummy_manager_started(Pid) ->
- receive
- {dummy_manager_started,Pid,Port} ->
- ?DBG("dummy_manager_start -> acknowledge received with"
- "~n Port: ~p",[Port]),
- {ok,Pid,Port};
- {'EXIT', Pid, Reason} ->
- {error, Pid, Reason};
- O ->
- ?LOG("dummy_manager_start -> received unknown message:"
- "~n ~p",[O]),
- await_dummy_manager_started(Pid)
- end.
-
-dummy_manager_stop(Pid) ->
- ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]),
- Pid ! stop,
- receive
- {dummy_manager_stopping, Pid} ->
- ?DBG("dummy_manager_stop -> acknowledge received",[]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_stop -> timeout",[]),
- timeout
- end.
-
-dummy_manager_send_trap2(Pid) ->
- ?DBG("dummy_manager_send_trap2 -> entry",[]),
- Pid ! {send_trap,testTrap2}.
-
-dummy_manager_await_trap2_ack() ->
- ?DBG("dummy_manager_await_trap2 -> entry",[]),
- receive
- {received_trap,Trap} ->
- ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]),
- %% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
- %% is no relation between these two test cases as far as I
- %% able to figure out...
- sleep(60000),
- ok;
- O ->
- ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]),
- ok
- after 10000 ->
- ?ERR("dummy_manager_await_trap2 -> timeout",[]),
- timeout
- end.
-
-dummy_manager_init(Parent,MA) ->
- ?DBG("dummy_manager_init -> entry with"
- "~n Parent: ~p"
- "~n MA: ~p",[Parent,MA]),
- {ok,S} = gen_udp:open(0,[{recbuf,65535}]),
- ?DBG("dummy_manager_init -> S: ~p",[S]),
- {ok,Port} = inet:port(S),
- ?DBG("dummy_manager_init -> Port: ~p",[Port]),
- Parent ! {dummy_manager_started,self(),Port},
- dummy_manager_loop(Parent,S,MA).
-
-dummy_manager_loop(P,S,MA) ->
- ?LOG("dummy_manager_loop -> ready for receive",[]),
- receive
- {send_trap,Trap} ->
- ?LOG("dummy_manager_loop -> received trap send request"
- "~n Trap: ~p",[Trap]),
- snmpa:send_trap(MA, Trap, "standard trap"),
- dummy_manager_loop(P,S,MA);
- {udp, _UdpId, Ip, UdpPort, Bytes} ->
- ?LOG("dummy_manager_loop -> received upd message"
- "~n from: ~p:~p"
- "~n size: ~p",
- [Ip, UdpPort, dummy_manager_message_sz(Bytes)]),
- R = dummy_manager_handle_message(Bytes),
- ?DBG("dummy_manager_loop -> R: ~p",[R]),
- P ! R,
- dummy_manager_loop(P,S,MA);
- stop ->
- ?DBG("dummy_manager_loop -> received stop request",[]),
- P ! {dummy_manager_stopping, self()},
- gen_udp:close(S),
- exit(normal);
- O ->
- ?LOG("dummy_manager_loop -> received unknown message:"
- "~n ~p",[O]),
- dummy_manager_loop(P,S,MA)
- end.
-
-dummy_manager_message_sz(B) when binary(B) ->
- size(B);
-dummy_manager_message_sz(L) when list(L) ->
- length(L);
-dummy_manager_message_sz(_) ->
- undefined.
-
-dummy_manager_handle_message(Bytes) ->
- case (catch snmp_pdus:dec_message(Bytes)) of
- {'EXIT',Reason} ->
- ?ERR("dummy_manager_handle_message -> "
- "failed decoding message only:~n ~p",[Reason]),
- {error,Reason};
- M ->
- ?DBG("dummy_manager_handle_message -> decoded message:"
- "~n ~p",[M]),
- {received_trap,M}
- end.
-
-
-api(suite) -> [];
-api(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(api_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-api_2(X) -> api(X).
-
-api_3(X) -> api(X).
-
-
-subagent(suite) -> [];
-subagent(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- try_test(load_test_sa),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
-
- p("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(load_test),
-
- p("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]),
- try_test(unreg_test),
- p("Testing register subagent..."),
- rpc:call(SaNode, snmp, register_subagent,
- [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- ?line stop_subagent(SA),
- try_test(unreg_test).
-
-subagent_2(X) -> subagent(X).
-
-subagent_3(X) -> subagent(X).
-
-
-mnesia(suite) -> [];
-mnesia(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Starting subagent with mnesia impl..."),
- {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
-
- try_test(big_test_2),
-
- p("Testing unregister subagent..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]),
- try_test(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
-
-mnesia_2(X) -> mnesia(X).
-
-mnesia_3(X) -> mnesia(X).
-
-
-
-mul_cases() ->
-[mul_get, mul_get_err, mul_next, mul_next_err,
- mul_set_err].
-
-
-multiple_reqs_3(_X) ->
- {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}.
-
-
-mul_cases_2() ->
-[mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2,
- mul_set_err_2].
-
-
-mul_cases_3() ->
- [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3].
-
-
-init_mul(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- [{mul_sub, SA} | Config].
-
-finish_mul(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- SA = ?config(mul_sub, Config),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
- lists:keydelete(mul_sub, 1, Config).
-
-mul_get(suite) -> [];
-mul_get(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get..."),
- try_test(do_mul_get).
-
-mul_get_2(X) -> mul_get(X).
-
-mul_get_3(X) -> mul_get(X).
-
-
-mul_get_err(suite) -> [];
-mul_get_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple get with error..."),
- try_test(do_mul_get_err).
-
-mul_get_err_2(X) -> mul_get_err(X).
-
-mul_get_err_3(X) -> mul_get_err(X).
-
-
-mul_next(suite) -> [];
-mul_next(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next).
-
-mul_next_2(X) -> mul_next(X).
-
-mul_next_3(X) -> mul_next(X).
-
-
-mul_next_err(suite) -> [];
-mul_next_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple next..."),
- try_test(do_mul_next_err).
-
-mul_next_err_2(X) -> mul_next_err(X).
-
-mul_next_err_3(X) -> mul_next_err(X).
-
-
-mul_set(suite) -> [];
-mul_set(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set..."),
- try_test(do_mul_set).
-
-mul_set_2(X) -> mul_set(X).
-
-mul_set_3(X) -> mul_set(X).
-
-
-mul_set_err(suite) -> [];
-mul_set_err(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing multiple set with error..."),
- try_test(do_mul_set_err).
-
-mul_set_err_2(X) -> mul_set_err(X).
-
-mul_set_err_3(X) -> mul_set_err(X).
-
-
-sa_register(suite) -> [];
-sa_register(Config) when list(Config) ->
- ?DBG("sa_register -> entry", []),
- {SaNode, _MgrNode, MibDir} = init_case(Config),
-
- ?DBG("sa_register -> start subagent", []),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
-
- ?DBG("sa_register -> unregister subagent", []),
- p("Testing unregister subagent (2)..."),
- MA = whereis(snmp_master_agent),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Loading SA-MIB..."),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- ?DBG("sa_register -> unload mibs", []),
- snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]),
- ?DBG("sa_register -> register subagent", []),
- rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]),
- try_test(sa_mib),
-
- ?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
-
-sa_register_2(X) -> sa_register(X).
-
-sa_register_3(X) -> sa_register(X).
-
-
-v1_trap(suite) -> [];
-v1_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_trap1, [MA]),
- try_test(ma_trap2, [MA]),
- try_test(ma_v2_2_v1_trap, [MA]),
- try_test(ma_v2_2_v1_trap2, [MA]),
-
- p("Testing trap sending from subagent..."),
- try_test(sa_trap1, [SA]),
- try_test(sa_trap2, [SA]),
- try_test(sa_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v2_trap(suite) -> [];
-v2_trap(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing trap sending from master agent..."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
-
- try_test(ma_v2_trap1, [MA]),
- try_test(ma_v2_trap2, [MA]),
- try_test(ma_v1_2_v2_trap, [MA]),
- try_test(ma_v1_2_v2_trap2, [MA]),
-
- try_test(sa_mib),
- p("Testing trap sending from subagent..."),
- try_test(sa_v1_2_v2_trap1, [SA]),
- try_test(sa_v1_2_v2_trap2, [SA]),
- try_test(sa_v1_2_v2_trap3, [SA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
-
- ?line stop_subagent(SA).
-
-v3_trap(X) ->
- v2_trap(X).
-
-
-v3_inform(_X) ->
- %% v2_inform(X).
- {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
-
-init_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-init_v3_inform(X) ->
- init_v2_inform(X).
-
-finish_v2_inform(Config) when list(Config) ->
- _Dir = ?config(agent_dir, Config),
-% snmp_internal_mib:configure(Dir),
- Config.
-
-finish_v3_inform(X) ->
- finish_v2_inform(X).
-
-
-
-v2_inform_i(suite) -> [];
-v2_inform_i(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- p("Testing inform sending from master agent... NOTE! This test\ntakes a "
- "few minutes (5) to complete."),
- MA = whereis(snmp_master_agent),
-
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(ma_v2_inform1, [MA]),
-
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2").
-
-v3_inform_i(X) -> v2_inform_i(X).
-
-
-sa_error(suite) -> [];
-sa_error(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing sa bad value (is_set_ok)..."),
- try_test(sa_errs_bad_value),
-
- p("Testing sa gen err (set)..."),
- try_test(sa_errs_gen_err),
-
- p("Testing too big..."),
- try_test(sa_too_big),
-
- ?line unload_master("OLD-SNMPEA-MIB"),
- stop_subagent(SA).
-
-sa_error_2(X) -> sa_error(X).
-
-sa_error_3(X) -> sa_error(X).
-
-
-next_across_sa(suite) -> [];
-next_across_sa(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Loading another subagent mib..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]),
-
- rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]),
- try_test(load_test_sa),
-
- p("Testing next across subagent (endOfMibView from SA)..."),
- try_test(next_across_sa),
-
- p("Unloading mib"),
- snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]),
- rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]),
- try_test(unreg_test),
-
- p("Starting another subagent"),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
- p("Testing next across subagent (wrong prefix from SA)..."),
- try_test(next_across_sa),
-
- stop_subagent(SA),
- stop_subagent(SA2).
-
-next_across_sa_2(X) -> next_across_sa(X).
-
-next_across_sa_3(X) -> next_across_sa(X).
-
-
-undo(suite) -> [];
-undo(Config) when list(Config) ->
- {SaNode, _MgrNode, MibDir} = init_case(Config),
- MA = whereis(snmp_master_agent),
-
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
-
- p("Testing undo phase at master agent..."),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]),
- try_test(undo_test),
- try_test(api_test2),
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]),
-
- p("Testing bad return values from instrum. funcs..."),
- try_test(bad_return),
-
- ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]),
-
- p("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]),
- ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
- try_test(undo_test),
- try_test(api_test3),
-
- p("Testing undo phase across master/subagents..."),
- try_test(undo_test),
- try_test(api_test3),
- stop_subagent(SA).
-
-undo_2(X) -> undo(X).
-
-undo_3(X) -> undo(X).
-
-%% Req. Test2
-v1_processing(suite) -> [];
-v1_processing(Config) when list(Config) ->
- ?DBG("v1_processing -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v1_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v2_processing(suite) -> [];
-v2_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc),
- ?line unload_master("Test2").
-
-%% Req. Test2
-v3_processing(suite) -> [];
-v3_processing(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("Test2"),
- try_test(v2_proc), % same as v2!
- ?line unload_master("Test2").
-
-
-%% We'll try get/set/trap and inform for all the auth & priv protocols.
-%% For informs, the mgr is auth-engine. The agent has to sync. This is
-%% accomplished by the first inform sent. That one will generate a
-%% report, which makes it in sync. The notification-generating
-%% application times out, and send again. This time it'll work.
-
-v3_crypto_basic(suite) -> [];
-v3_crypto_basic(_Config) ->
- EID = [0,0,0,0,0,0,0,0,0,0,0,2],
- %% From rfc2274 appendix A.3.1
- ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
- ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f,
- 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] =
- KMd5_1,
- %% From rfc2274 appendix A.3.2
- ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
- ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23,
- 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] =
- KSHA_1,
- %% From rfc2274, appendix A.5.1
- ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9,
- 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] =
- snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- %% From rfc2274, appendix A.5.2
- ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4,
- 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db,
- 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
- KSHA_1t = lists:sublist(KSHA_1, 16),
- KSHA_2t = lists:sublist(KSHA_2, 16),
- ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
- 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b,
- 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] =
- snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16,
- [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
-
- %% Try with correct random
- ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
- ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
- ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
- ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
- ok.
-
-
-
-v3_md5_auth(suite) -> [];
-v3_md5_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing MD5 authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_sha_auth(suite) -> [];
-v3_sha_auth(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing SHA authentication...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-v3_des_priv(suite) -> [];
-v3_des_priv(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- p("Testing DES encryption...takes a few seconds..."),
-
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
-
- MA = whereis(snmp_master_agent),
-
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
-
- try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
-
-%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
-
-%% Make sure mgr is in sync with agent
-v3_sync(Funcs) ->
- ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]),
- g([[sysDescr, 0]]),
- expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]),
- g([[sysDescr, 0]]),
- expect(433, [{[sysDescr,0], any}]),
- lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs).
-
-v3_inform_sync(MA) ->
- ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
- "standard inform", []),
- %% Make sure agent is in sync with mgr...
- ?DBG("v3_sync -> wait some time: ",[]),
- sleep(20000), % more than 1500*10 in target_addr.conf
- ?DBG("v3_sync -> await response",[]),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]).
-
-
-v2_caps(suite) -> [];
-v2_caps(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- try_test(v2_caps_i, [node()]).
-
-v2_caps_3(X) -> v2_caps(X).
-
-
-v2_caps_i(Node) ->
- ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]),
- g([[sysORID, Idx], [sysORDescr, Idx]]),
- ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]},
- {[sysORDescr, Idx], "test cap"}]),
- ?line rpc:call(Node, snmp, del_agent_caps, [Idx]),
- g([[sysORID, Idx]]),
- ?line expect(2, [{[sysORID, Idx], noSuchInstance}]).
-
-
-%% Req. Test2
-v1_proc() ->
- ?DBG("v1_proc -> entry", []),
- %% According to RFC1157.
- %% Template: <Section>:<list no>
- v1_get_p(),
- v1_get_next_p(),
- v1_set_p().
-
-
-v1_get_p() ->
- %% 4.1.2:1
- g([[test2]]),
- ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]),
- g([[tDescr]]),
- ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]),
- g([[tDescr2,0]]),
- ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
- g([[tDescr3,0]]),
- ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
- g([[tDescr4,0]]),
- ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'},
- {[tDescr,0], 'NULL'}]),
- g([[sysDescr,3]]),
- ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
-
- %% 4.1.2:2
- g([[tTable]]),
- ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]),
- g([[tEntry]]),
- ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]),
-
- %% 4.1.2:3
- g([[tTooBig, 0]]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.2:4
- g([[tGenErr1, 0]]),
- ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]).
-
-
-v1_get_next_p() ->
- %% 4.1.3:1
- gn([[1,3,7,1]]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
- gn([[tDescr2]]),
- ?line expect(11, tooBig, 0, any),
-
- %% 4.1.3:2
- gn([[tTooBig]]),
- io:format("We currently don't handle tooBig correct!!!\n"),
-% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]),
- ?line expect(20, tooBig, 0, any),
-
- %% 4.1.3:3
- gn([[tGenErr1]]),
-% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]),
- ?line expect(40, genErr, 1, any),
- gn([[tGenErr2]]),
-% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]),
- ?line expect(41, genErr, 1, any),
- gn([[sysDescr], [tGenErr3]]),
-% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'},
-% {[tGenErr3], 'NULL'}]).
- ?line expect(42, genErr, 2, any).
-
-v1_set_p() ->
- %% 4.1.5:1
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]),
- s([{[tDescr3], s, "noSuchObject"}]),
- ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
- s([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
- s([{[tDescr2,0], s, "inconsistentName"}]),
- ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
-
- %% 4.1.5:2
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.1.5:3
- %% The standard is quite incorrect here. The resp pdu was too big. In
- %% the resp pdu, we have the original vbs. In the tooBig pdu we still
- %% have to original vbs => the tooBig pdu is too big as well!!! It
- %% may not get it to the manager, unless the agent uses 'NULL' instead
- %% of the std-like original value.
- s([{[tTooBig, 0], s, ?tooBigStr}]),
- %% according to std:
-% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
-
- %% 4.1.5:4
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
- s([{[tDescr2, 0], s, "commit_fail"}]),
- ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
-
-%% Req. Test2
-v2_proc() ->
- %% According to RFC1905.
- %% Template: <Section>:<list no>
- ?DBG("v2_proc -> entry",[]),
- v2_get_p(),
- v2_get_next_p(),
- v2_get_bulk_p(),
- v2_set_p().
-
-v2_get_p() ->
- %% 4.2.1:2
- ?DBG("v2_get_p -> entry",[]),
- g([[test2]]),
- ?line expect(10, [{[test2], noSuchObject}]),
- g([[tDescr]]),
- ?line expect(11, [{[tDescr], noSuchObject}]),
- g([[tDescr4,0]]),
- ?line expect(12, [{[tDescr4,0], noSuchObject}]),
- g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"},
- {[tDescr,0], noSuchObject}]),
- g([[tTable]]),
- ?line expect(14, [{[tTable], noSuchObject}]),
- g([[tEntry]]),
- ?line expect(15, [{[tEntry], noSuchObject}]),
-
- %% 4.2.1:3
- g([[tDescr2,0]]), %% instrum ret noSuchName!!!
- ?line expect(20, [{[tDescr2,0], noSuchInstance}]),
- g([[tDescr3,0]]),
- ?line expect(21, [{[tDescr3,0], noSuchInstance}]),
- g([[sysDescr,3]]),
- ?line expect(22, [{[sysDescr, 3], noSuchInstance}]),
- g([[tIndex,1]]),
- ?line expect(23, [{[tIndex, 1], noSuchInstance}]),
-
- %% 4.2.1 - any other error: genErr
- g([[tGenErr1, 0]]),
- ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
- g([[tGenErr2, 0]]),
- ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
- g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'},
- {[tGenErr3, 0], 'NULL'}]),
-
- %% 4.2.1 - tooBig
- g([[tTooBig, 0]]),
- ?line expect(40, tooBig, 0, []).
-
-
-v2_get_next_p() ->
- %% 4.2.2:2
- ?DBG("v2_get_next_p -> entry",[]),
- gn([[1,3,7,1]]),
- ?line expect(10, [{[1,3,7,1], endOfMibView}]),
- gn([[sysDescr], [1,3,7,1]]),
- ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gn([[tCnt2, 1]]),
- ?line expect(12, [{[tCnt2,2], 100}]),
- gn([[tCnt2, 2]]),
- ?line expect(12, [{[tCnt2,2], endOfMibView}]),
-
- %% 4.2.2 - any other error: genErr
- gn([[tGenErr1]]),
- ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]),
- gn([[tGenErr2]]),
- ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]),
- gn([[sysDescr], [tGenErr3]]),
- ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'},
- {[tGenErr3], 'NULL'}]),
-
- %% 4.2.2 - tooBig
- gn([[tTooBig]]),
- ?line expect(20, tooBig, 0, []).
-
-v2_get_bulk_p() ->
- %% 4.2.3
- ?DBG("v2_get_bulk_p -> entry",[]),
- gb(1, 1, []),
- ?line expect(10, []),
- gb(-1, 1, []),
- ?line expect(11, []),
- gb(-1, -1, []),
- ?line expect(12, []),
- gb(-1, -1, []),
- ?line expect(13, []),
- gb(2, 0, [[sysDescr], [1,3,7,1]]),
- ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(1, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView}]),
- gb(0, 2, [[sysDescr], [1,3,7,1]]),
- ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]),
- ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysDescr, 0], "Erlang SNMP agent"},
- {[1,3,7,1], endOfMibView},
- {[sysObjectID, 0], [1,2,3]},
- {[1,3,7,1], endOfMibView}]),
-
- gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
- ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"},
- {[sysDescr, 0], "Erlang SNMP agent"}]),
-
- gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
- ?line expect(19, []),
-
- gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
- ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'},
- {[sysObjectID], 'NULL'},
- {[tGenErr1], 'NULL'},
- {[sysDescr], 'NULL'}]),
- gb(0, 2, [[tCnt2, 1]]),
- ?line expect(21, [{[tCnt2,2], 100},
- {[tCnt2,2], endOfMibView}]).
-
-
-v2_set_p() ->
- %% 4.2.5:1
- ?DBG("v2_set_p -> entry",[]),
- s([{[1,3,7,0], i, 4}]),
- ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]),
- s([{[tDescr,0], s, "outside mibview"}]),
- ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]),
-
- %% 4.2.5:2
- s([{[1,3,6,1,0], s, "noSuchObject"}]),
- ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
-
- %% 4.2.5:3
- s([{[tDescr2, 0], i, 4}]),
- ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]),
- s([{[tDescr2, 0], s, "badValue"}]),
- ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]),
-
- %% 4.2.5:4
- s([{[tStr, 0], s, ""}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]),
- s([{[tStr, 0], s, "12345"}]),
- ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]),
-
- %% 4.2.5:5 - N/A
-
- %% 4.2.5:6
- s([{[tInt1, 0], i, 0}]),
- ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]),
- s([{[tInt1, 0], i, 5}]),
- ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]),
- s([{[tInt2, 0], i, 0}]),
- ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]),
- s([{[tInt2, 0], i, 5}]),
- ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]),
- s([{[tInt3, 0], i, 5}]),
- ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]),
-
- %% 4.2.5:7
- s([{[tDescrX, 1, 1], s, "noCreation"}]),
- ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
-
- %% 4.2.5:8
- s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
- ?line expect(80, inconsistentName, 1,
- [{[tDescrX, 1, 2], "inconsistentName"}]),
-
- %% 4.2.5:9
- s([{[tCnt, 1, 2], i, 5}]),
- ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]),
- s([{[tDescr3,0], s, "read-only"}]),
- ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]),
-
- %% 4.2.5:10
- s([{[tDescr2,0], s, "inconsistentValue"}]),
- ?line expect(100, inconsistentValue, 1,
- [{[tDescr2,0], "inconsistentValue"}]),
-
- %% 4.2.5:11
- s([{[tDescr2,0], s, "resourceUnavailable"}]),
- ?line expect(110, resourceUnavailable, 1,
- [{[tDescr2,0],"resourceUnavailable"}]),
-
- %% 4.2.5:12
- s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
-
- %% commitFailed and undoFailed is tested by the 'undo' case.
-
-
-%% Req. OLD-SNMPEA-MIB
-table_test() ->
- io:format("Testing simple get, next and set on communityTable...~n"),
-%% {[147,214,36,45], "public", 2, readWrite}.
-%% {[147,214,36,45], "standard trap", 2, read}.
- Key1c3 = [intCommunityViewIndex,get(mip),is("public")],
- Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")],
- Key1c4 = [intCommunityAccess,get(mip),is("public")],
- EndKey = [intCommunityEntry,[9],get(mip),is("public")],
- gn([[intCommunityEntry]]),
- ?line expect(7, [{Key1c3, 2}]),
- gn([[intCommunityTable]]),
- ?line expect(71, [{Key1c3, 2}]),
- gn([[community]]),
- ?line expect(72, [{Key1c3, 2}]),
- gn([[otpSnmpeaMIB]]),
- ?line expect(73, [{Key1c3, 2}]),
- gn([[ericsson]]),
- ?line expect(74, [{Key1c3, 2}]),
- gn([Key1c3]),
- ?line expect(8, [{Key2c3, 2}]),
- gn([Key2c3]),
- ?line expect(9, [{Key1c4, 2}]),
- gn([EndKey]),
- AgentIp = [intAgentIpAddress,0],
- ?line expect(10, [{AgentIp, any}]),
- g([Key1c3]),
- ?line expect(11, [{Key1c3, 2}]),
- g([EndKey]),
- ?line ?v1_2(expect(12, noSuchName, 1, any),
- expect(12, [{EndKey, noSuchObject}])),
-
- io:format("Testing row creation/deletion on communityTable...~n"),
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
- s([{NewKeyc5, ?createAndGo}]),
- ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any),
- s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
- ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
- g([NewKeyc4]),
- ?line expect(16, [{NewKeyc4, 2}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(17, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc4, 2}]),
- ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]),
- s([{NewKeyc5, ?createAndWait}]),
- ?line expect(19, [{NewKeyc5, ?createAndWait}]),
- g([NewKeyc5]),
- ?line expect(20, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc4, 2}]),
- ?line expect(21, [{NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(22, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc3, 2}]),
- ?line expect(23, [{NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(24, [{NewKeyc5, ?notInService}]),
- s([{NewKeyc5, ?active}]),
- ?line expect(25, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(26, [{NewKeyc5, ?destroy}]),
- s([{NewKeyc3, 3}]),
- ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]),
- otp_1128().
-
-%% Req. system group
-simple_standard_test() ->
- ?DBG("simple_standard_test -> entry",[]),
- gn([[1,1]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3]]),
- ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6]]),
- ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1]]),
- ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2]]),
- ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1]]),
- ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[1,3,6,1,2,1,1]]),
- ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]),
- gn([[sysDescr]]),
- ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr,0]]),
- ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]),
- g([[sysDescr]]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{[sysDescr], noSuchObject}])),
- g([[1,6,7,0]]),
- ?line ?v1_2(expect(41, noSuchName, 1, any),
- expect(3, [{[1,6,7,0], noSuchObject}])),
- gn([[1,13]]),
- ?line ?v1_2(expect(4, noSuchName,1, any),
- expect(4, [{[1,13], endOfMibView}])),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
- g([[sysLocation, 0]]),
- ?line expect(6, [{[sysLocation, 0], "new_value"}]),
- io:format("Testing noSuchName and badValue...~n"),
- s([{[sysServices,0], 3}]),
- ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any),
- s([{[sysLocation, 0], i, 3}]),
- ?line expect(62, ?v1_2(badValue, wrongType), 1, any),
- ?DBG("simple_standard_test -> done",[]),
- ok.
-
-%% This is run in the agent node
-db_notify_client(suite) -> [];
-db_notify_client(Config) when list(Config) ->
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p",
- [SaNode,MgrNode,MibDir]),
- snmpa_local_db:register_notify_client(self(),?MODULE),
-
- %% This call (the manager) will issue to set operations, so
- %% we expect to receive to notify(insert) calls.
- try_test(db_notify_client_test),
-
- ?DBG("await first notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok
- end,
-
- ?DBG("await second notify",[]),
- receive
- {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok
- end,
-
- snmpa_local_db:unregister_notify_client(self()).
-
-
-%% This is run in the manager node
-db_notify_client_test() ->
- ?DBG("set first new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]),
-
- ?DBG("set second new sysLocation",[]),
- s([{[sysLocation, 0], "new_value"}]),
- ?line expect(5, [{[sysLocation, 0], "new_value"}]).
-
-notify(Pid,What) ->
- ?DBG("notify(~p,~p) -> called",[Pid,What]),
- Pid ! {db_notify_test_reply,What}.
-
-
-%% Req: system group, OLD-SNMPEA-MIB, Klas1
-big_test() ->
- ?DBG("big_test -> testing simple next/get/set @ master agent...",[]),
- simple_standard_test(),
-
- ?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
- gn([[klas1]]),
- ?line expect(1, [{[fname,0], ""}]),
- g([[fname,0]]),
- ?line expect(2, [{[fname,0], ""}]),
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[fname,0]]),
- ?line expect(4, [{[fname,0], "test set"}]),
-
- ?DBG("big_test -> "
- "testing next from last instance in master to subagent...",[]),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname,0], "test set"}]),
- s([{[fname,0], s, ""}]),
- ?line expect(52, [{[fname,0], ""}]),
-
- table_test(),
-
- ?DBG("big_test -> adding one row in subagent table",[]),
- _FTab = [friendsEntry],
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [friendsEntry, [3, 3]]]),
- ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"},
- {[friendsEntry, [3, 3]], ?active}]),
- s([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]),
-
- otp_1131(),
-
- ?DBG("big_test -> adding two rows in subagent table with special INDEX",
- []),
- s([{[kompissEntry, [1, 3]], s, "kompis3"},
- {[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?createAndGo}]),
- g([[kompissEntry, [1, 3]],
- [kompissEntry, [2, 3]]]),
- ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- gn([[kompissEntry, [1]],
- [kompissEntry, [2]]]),
- ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"},
- {[kompissEntry, [2, 3]], ?active}]),
- s([{[kompissEntry, [1, 2]], s, "kompis3"},
- {[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry, [1, 1]],
- [kompissEntry, [2, 1]]]),
- ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"},
- {[kompissEntry, [2, 2]], ?active}]),
- s([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]),
- s([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]),
- ?DBG("big_test -> done",[]),
- ok.
-
-%% Req. system group, Klas2, OLD-SNMPEA-MIB
-big_test_2() ->
- p("Testing simple next/get/set @ master agent (2)..."),
- simple_standard_test(),
-
- p("Testing simple next/get/set @ subagent (2)..."),
- gn([[klas2]]),
- ?line expect(1, [{[fname2,0], ""}]),
- g([[fname2,0]]),
- ?line expect(2, [{[fname2,0], ""}]),
- s([{[fname2,0], s, "test set"}]),
- ?line expect(3, [{[fname2,0], "test set"}]),
- g([[fname2,0]]),
- ?line expect(4, [{[fname2,0], "test set"}]),
-
- otp_1298(),
-
- p("Testing next from last object in master to subagent (2)..."),
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(5, [{[fname2,0], "test set"}]),
- gn([[1,1],
- [?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"},
- {[fname2,0], "test set"}]),
-
- table_test(),
-
- p("Adding one row in subagent table (2)"),
- _FTab = [friendsEntry2],
- s([{[friendsEntry2, [2, 3]], s, "kompis3"},
- {[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?createAndGo}]),
- g([[friendsEntry2, [2, 3]],
- [friendsEntry2, [3, 3]]]),
- ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"},
- {[friendsEntry2, [3, 3]], ?active}]),
- s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]),
-
- p("Adding two rows in subagent table with special INDEX (2)"),
- s([{[kompissEntry2, [1, 3]], s, "kompis3"},
- {[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?createAndGo}]),
- g([[kompissEntry2, [1, 3]],
- [kompissEntry2, [2, 3]]]),
- ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- gn([[kompissEntry2, [1]],
- [kompissEntry2, [2]]]),
- ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"},
- {[kompissEntry2, [2, 3]], ?active}]),
- s([{[kompissEntry2, [1, 2]], s, "kompis3"},
- {[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?createAndGo}]),
- gn([[kompissEntry2, [1, 1]],
- [kompissEntry2, [2, 1]]]),
- ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"},
- {[kompissEntry2, [2, 2]], ?active}]),
- s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]),
- s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]),
- ok.
-
-%% Req. Test1
-multi_threaded_test() ->
- p("Testing multi threaded agent..."),
- g([[multiStr,0]]),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(1, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "pelle"}]),
- ?line expect(2, [{[sysLocation, 0], "pelle"}]),
- Pid ! continue,
- ?line expect(3, [{[multiStr,0], "ok"}]),
-
- s([{[multiStr, 0], s, "block"}]),
- Pid2 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(4, [{[sysUpTime,0], any}]),
- g([[multiStr,0]]),
- Pid3 = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(5, [{[sysUpTime,0], any}]),
- s([{[sysLocation, 0], s, "kalle"}]),
- Pid3 ! continue,
- ?line expect(6, [{[multiStr,0], "ok"}]),
- Pid2 ! continue,
- ?line expect(7, [{[multiStr,0], "block"}]),
- ?line expect(8, [{[sysLocation,0], "kalle"}]).
-
-%% Req. Test1, TestTrapv2
-mt_trap_test(MA) ->
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- snmpa:send_trap(MA, mtTrap, "standard trap"),
- Pid = get_multi_pid(),
- g([[sysUpTime,0]]),
- ?line expect(2, [{[sysUpTime,0], any}]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- Pid ! continue,
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [2]},
- {[multiStr,0], "ok"}]).
-
-
-get_multi_pid() ->
- get_multi_pid(10).
-get_multi_pid(0) ->
- ?line ?FAIL(no_global_name);
-get_multi_pid(N) ->
- sleep(1000),
- case global:whereis_name(snmp_multi_tester) of
- Pid when pid(Pid) -> Pid;
- _ -> get_multi_pid(N-1)
- end.
-
-%% Req. Test1
-types_v2_test() ->
- p("Testing v2 types..."),
-
- s([{[bits1,0], 2#10}]),
- ?line expect(1, [{[bits1,0], ?str(2#10)}]),
- g([[bits1,0]]),
- ?line expect(2, [{[bits1,0], ?str(2#101)}]),
-
- s([{[bits2,0], 2#11000000110}]),
- ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]),
- g([[bits2,0]]),
- ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]),
-
- g([[bits3,0]]),
- ?line expect(50, genErr, 1, any),
-
- g([[bits4,0]]),
- ?line expect(51, genErr, 1, any),
-
- s([{[bits1,0], s, [2#10]}]),
- ?line expect(6, ?v1_2(badValue, wrongValue), 1, any),
-
- s([{[bits2,0], 2#11001001101010011}]),
- ?line expect(7, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%% Req. Test1
-implied_test(MA) ->
- ?LOG("implied_test -> start",[]),
- p("Testing IMPLIED..."),
-
- snmpa:verbosity(MA,trace),
- snmpa:verbosity(MA,trace),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = "apa",
- Idx2 = "qq",
- ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]),
- ?line expect(1, [{[testStatus, Idx1], ?createAndGo},
- {[testDescr, Idx1], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]),
- ?line expect(2, [{[testStatus, Idx2], ?createAndGo},
- {[testDescr, Idx2], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr)",[]),
- gn([[testDescr]]),
- ?line expect(3, [{[testDescr,Idx1], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr) of row 1",[]),
- gn([[testDescr,Idx1]]),
- ?line expect(4, [{[testDescr,Idx2], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]),
- s([{[testStatus, Idx1], i, ?destroy}]),
- ?line expect(5, [{[testStatus, Idx1], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
- s([{[testStatus, Idx2], i, ?destroy}]),
- ?line expect(6, [{[testStatus, Idx2], ?destroy}]),
-
- %% Try the same in other table
- Idx3 = [1, "apa"],
- Idx4 = [1, "qq"],
- ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]),
- ?line expect(1, [{[testStatus2, Idx3], ?createAndGo},
- {[testDescr2, Idx3], "row 1"}]),
- ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]),
- ?line expect(2, [{[testStatus2, Idx4], ?createAndGo},
- {[testDescr2, Idx4], "row 2"}]),
- ?DBG("implied_test -> get-next(testDescr2)",[]),
- gn([[testDescr2]]),
- ?line expect(3, [{[testDescr2,Idx3], "row 1"}]),
- ?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
- gn([[testDescr2,Idx3]]),
- ?line expect(4, [{[testDescr2,Idx4], "row 2"}]),
-
- % Delete the rows
- ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]),
- s([{[testStatus2, Idx3], i, ?destroy}]),
- ?line expect(5, [{[testStatus2, Idx3], ?destroy}]),
- ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
- s([{[testStatus2, Idx4], i, ?destroy}]),
- ?line expect(6, [{[testStatus2, Idx4], ?destroy}]),
-
- snmpa:verbosity(MA,log),
-
- ?LOG("implied_test -> done",[]).
-
-
-
-%% Req. Test1
-sparse_table_test() ->
- p("Testing sparse table..."),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- s([{[sparseStatus, Idx1], i, ?createAndGo},
- {[sparseDescr, Idx1], s, "row 1"}]),
- ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo},
- {[sparseDescr, Idx1], "row 1"}]),
- s([{[sparseStatus, Idx2], i, ?createAndGo},
- {[sparseDescr, Idx2], s, "row 2"}]),
- ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo},
- {[sparseDescr, Idx2], "row 2"}]),
- ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
- [sparseStatus,Idx1], [sparseStatus,Idx2]]),
- gb(0,5,[[sparseIndex]])),
- ?line expect(3, [{[sparseDescr,Idx1], "row 1"},
- {[sparseDescr,Idx2], "row 2"},
- {[sparseStatus,Idx1], ?active},
- {[sparseStatus,Idx2], ?active},
- {[sparseStr,0], "slut"}]),
- % Delete the rows
- s([{[sparseStatus, Idx1], i, ?destroy}]),
- ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]),
- s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]).
-
-
-%% Req. Test1
-cnt_64_test(MA) ->
- ?LOG("start cnt64 test (~p)",[MA]),
- snmpa:verbosity(MA,trace),
- ?LOG("start cnt64 test",[]),
- p("Testing Counter64, and at the same time, RowStatus is not last column"),
-
- ?DBG("get cnt64",[]),
- g([[cnt64,0]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(1, noSuchName, 1, any),
- expect(1, [{[cnt64,0],18446744073709551615}])),
- ?DBG("get-next cnt64",[]),
- gn([[cnt64]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]),
- expect(2, [{[cnt64,0],18446744073709551615}])),
- ?DBG("send cntTrap",[]),
- snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"},
- {cnt64, 10},
- {sysLocation, "here"}]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"},
- {[sysLocation,0], "here"}]),
- expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?testTrap ++ [1]},
- {[sysContact,0], "pelle"},
- {[cnt64,0], 10},
- {[sysLocation,0], "here"}])),
-
- %% Create two rows, check that they are get-nexted in correct order.
- Idx1 = 1,
- Idx2 = 2,
- ?DBG("create row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]),
- ?DBG("create row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?createAndGo}]),
- ?DBG("await response",[]),
- ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]),
-
- ?DBG("get-next (cntIndex)",[]),
- gn([[cntIndex]]),
- ?DBG("await response",[]),
- ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]),
- expect(3, [{[cntCnt,Idx1], 0}])),
- % Delete the rows
- ?DBG("delete row (cntStatus): ~p",[Idx1]),
- s([{[cntStatus, Idx1], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(4, [{[cntStatus, Idx1], ?destroy}]),
- ?DBG("delete row (cntStatus): ~p",[Idx2]),
- s([{[cntStatus, Idx2], i, ?destroy}]),
- ?DBG("await response",[]),
- ?line expect(5, [{[cntStatus, Idx2], ?destroy}]),
- catch snmpa:verbosity(MA,log),
- ?DBG("done",[]),
- ok.
-
-%% Req. Test1
-opaque_test() ->
- p("Testing Opaque datatype..."),
- g([[opaqueObj,0]]),
- ?line expect(1, [{[opaqueObj,0], "opaque-data"}]).
-
-%% Req. OLD-SNMPEA-MIB
-api_test(MaNode) ->
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp,
- oid_to_name, [OID]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp,
- int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp,
- enum_to_int, ['xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
- List when list(List), length(List) == 8 -> ok;
- List when list(List), length(List) == 11 -> ok
- end.
-
-%% Req. Klas3
-api_test2() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]),
- g([[fname4,0]]),
- ?line expect(2, [{[fname4,0], 1}]).
-
-api_test3() ->
- g([[fname3,0]]),
- ?line expect(1, [{[fname3,0], "ok"}]).
-
-
-unreg_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[snmpInPkts, 0], any}]).
-
-load_test() ->
- gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line expect(1, [{[fname,0], ""}]).
-
-%% Req. Klas1
-load_test_sa() ->
- gn([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line expect(1, [{[fname,0], any}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_get() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0], Key1c4, [fname,0],Key1c3,
- [sysName,0]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,0], "test"}]),
- g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]),
- ?line ?v1_2(expect(2, noSuchName, [1,4], any),
- expect(2, [{[1,3,7,1], noSuchObject},
- {Key1c4, 2},
- {[sysDescr,0], "Erlang SNMP agent"},
- {[1,3,7,2], noSuchObject},
- {Key1c3, 2},
- {[sysDescr,0], "Erlang SNMP agent"}])).
-
-%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3.
-do_mul_get_err() ->
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(expect(1, noSuchName, 5, any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname,0], "test set"},
- {Key1c3, 2},
- {[sysName,2], noSuchInstance}])),
- g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[fname3,0], noSuchObject},
- {Key1c3, 2},
- {[sysName,1], noSuchInstance}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2}, {[fname,0], "test set"},
- {Key1c3, 2}, {[sysName,0], "test"}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_next_err() ->
- Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")],
- Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")],
- Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
- Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
- s([{[fname,0], s, "test set"}]),
- ?line expect(3, [{[fname,0], "test set"}]),
- gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(expect(1, noSuchName, [3,5], any),
- expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {Key1c4, 2},
- {[1,3,6,999], endOfMibView},
- {[fname,0], "test set"},
- {[1,3,90], endOfMibView},
- {Key1c3, 2},
- {[sysName,0], "test"}])).
-
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set() ->
- p("Adding one row in subagent table, and one in master table"),
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"},
- {NewKeyc3, 2},
- {[sysLocation,0], "new_value"},
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- g([[friendsEntry, [2, 3]],
- [sysLocation,0],
- [friendsEntry, [3, 3]]]),
- ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"},
- {[sysLocation,0], "new_value"},
- {[friendsEntry, [3, 3]], ?active}]),
- g([NewKeyc4]),
- ?line expect(3, [{NewKeyc4, 2}]),
- s([{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]),
- ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy},
- {NewKeyc5, ?destroy}]).
-
-%% Req. system group, Klas1, OLD-SNMPEA-MIB
-do_mul_set_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- p("Adding one row in subagent table, and one in master table"),
- s([{[friendsEntry, [2, 3]], s, "kompis3"},
- {NewKeyc3, 2},
- {[sysUpTime,0], 45}, % sysUpTime (readOnly)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2},
- {[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any),
- g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])),
- g([NewKeyc4]),
- ?line ?v1_2(expect(3, noSuchName, 1, any),
- expect(3, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB
-sa_mib() ->
- g([[sa, [2,0]]]),
- ?line expect(1, [{[sa, [2,0]], 3}]),
- s([{[sa, [1,0]], s, "sa_test"}]),
- ?line expect(2, [{[sa, [1,0]], "sa_test"}]).
-
-ma_trap1(MA) ->
- snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]),
- snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"}]).
-
-ma_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]).
-
-ma_v2_2_v1_trap2(MA) ->
- snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1},
- {ifAdminStatus, [1], 1},
- {ifOperStatus, [1], 2}]),
- ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
- {[ifAdminStatus, 1], 1},
- {[ifOperStatus, 1], 2}]).
-
-sa_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]],
- "pelle"},
- {[sa, [1,0]], "sa_test"}]).
-
-sa_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]}]).
-
-ma_v2_trap1(MA) ->
- ?DBG("ma_v2_traps -> entry with MA = ~p => "
- "send standard trap: testTrapv22",[MA]),
- snmpa:send_trap(MA, testTrapv22, "standard trap"),
- ?line expect(1, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]),
- snmpa:send_trap(MA, testTrapv21, "standard trap"),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmp ++ [1]}]).
-
-ma_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
-
-%% Note: This test case takes a while... actually a couple of minutes.
-ma_v2_inform1(MA) ->
- ?DBG("ma_v2_inform -> entry with MA = ~p => "
- "send notification: testTrapv22",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag1, self()},
- "standard inform", []),
- ?line expect(1, {inform, true},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag1, [_]} ->
- ok;
- {snmp_targets, tag1, Addrs1} ->
- ?line ?FAIL({bad_addrs, Addrs1})
- after
- 5000 ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag1, {got_response, _}} ->
- ok;
- {snmp_notification, tag1, {no_response, _}} ->
- ?line ?FAIL(no_response)
- after
- 20000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag1) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end,
-
- %%
- %% -- The rest is possibly erroneous...
- %%
-
- ?DBG("ma_v2_inform -> send notification: testTrapv22",[]),
- snmpa:send_notification(MA, testTrapv22, {tag2, self()},
- "standard inform", []),
- ?line expect(2, {inform, false},
- [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]}]),
- ?DBG("ma_v2_inform -> await targets",[]),
- receive
- {snmp_targets, tag2, [_]} ->
- ok;
- {snmp_targets, tag2, Addrs2} ->
- ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]),
- ?line ?FAIL({bad_addrs, Addrs2})
- after
- 5000 ->
- ?line ?FAIL(nothing_at_all)
- end,
- ?DBG("ma_v2_inform -> await notification",[]),
- receive
- {snmp_notification, tag2, {got_response, _}} ->
- ?line ?FAIL(got_response);
- {snmp_notification, tag2, {no_response, _}} ->
- ok
- after
- 240000 ->
- ?ERR("ma_v2_inform1 -> "
- "awaiting snmp_notification(tag2) timeout",[]),
- ?line ?FAIL(nothing_at_all)
- end.
-
-
-ma_v1_2_v2_trap(MA) ->
- snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line expect(2, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?snmpTraps ++ [3]},
- {[ifIndex, 1], 1},
- {[snmpTrapEnterprise, 0], [1,2,3]}]).
-
-
-ma_v1_2_v2_trap2(MA) ->
- snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line expect(3, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"},
- {[snmpTrapEnterprise, 0], ?system}]).
-
-
-sa_v1_2_v2_trap1(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap"),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-sa_v1_2_v2_trap2(SA) ->
- snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
- {[system, [4,0]], "pelle"},
- {[sa, [1,0]], "sa_test"},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-sa_v1_2_v2_trap3(SA) ->
- snmpa:send_trap(SA, saTrap2, "standard trap",
- [{intViewSubtree, [4], [1,2,3,4]}]),
- ?line expect(4, v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
- {[system, [4,0]],
- "{mbj,eklas}@erlang.ericsson.se"},
- {[sa, [1,0]], "sa_test"},
- {[intViewSubtree,4],[1,2,3,4]},
- {[snmpTrapEnterprise, 0], ?ericsson}]).
-
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_bad_value() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 5}, % badValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, badValue, 2, any),
- s([{NewKeyc3, 2},
- {[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
- {NewKeyc5, ?createAndGo},
- {NewKeyc4, 2}]),
- ?line expect(1, ?v1_2(badValue, wrongValue), 2, any),
- g([NewKeyc4]),
- ?line ?v1_2(expect(2, noSuchName, 1, any),
- expect(2, [{NewKeyc4, noSuchInstance}])).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_errs_gen_err() ->
- NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")],
- NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")],
- NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
- s([{NewKeyc3, 2},{NewKeyc4, 2},
- {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line expect(1, genErr, 4, any),
-% The row might have been added; we don't know.
-% (as a matter of fact we do - it is added, because the agent
-% first sets its own vars, and then th SAs. Lets destroy it.
- s([{NewKeyc5, ?destroy}]),
- ?line expect(2, [{NewKeyc5, ?destroy}]).
-
-%% Req. SA-MIB, OLD-SNMPEA-MIB
-sa_too_big() ->
- g([[sa, [4,0]]]),
- ?line expect(1, tooBig).
-
-%% Req. Klas1, system group, snmp group (v1/v2)
-next_across_sa() ->
- gn([[sysDescr],[klas1,5]]),
- ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"},
- {[snmpInPkts, 0], any}]).
-
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2}
-%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1}
-%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2}
-%% Req. Klas3, Klas4
-undo_test() ->
- s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any),
- s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line expect(3, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line expect(4, ?v1_2(genErr, commitFailed), 1, any),
-% unfortunatly we don't know if we'll get undoFailed or commitFailed.
-% it depends on which order the agent traverses the varbind list.
-% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]),
-% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any),
- s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line expect(6, genErr, 2, any).
-
-%% Req. Klas3, Klas4
-bad_return() ->
- g([[fStatus4,4],
- [fName4,4]]),
- ?line expect(4, genErr, 2, any),
- g([[fStatus4,5],
- [fName4,5]]),
- ?line expect(5, genErr, 1, any),
- g([[fStatus4,6],
- [fName4,6]]),
- ?line expect(6, genErr, 2, any),
- gn([[fStatus4,7],
- [fName4,7]]),
- ?line expect(7, genErr, 2, any),
- gn([[fStatus4,8],
- [fName4,8]]),
- ?line expect(8, genErr, 1, any),
- gn([[fStatus4,9],
- [fName4,9]]),
- ?line expect(9, genErr, 2, any).
-
-
-%%%-----------------------------------------------------------------
-%%% Test the implementation of standard mibs.
-%%% We should *at least* try to GET all variables, just to make
-%%% sure the instrumentation functions work.
-%%% Note that many of the functions in the standard mib is
-%%% already tested by the normal tests.
-%%%-----------------------------------------------------------------
-
-
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v1.
-%% o Test the counters and control objects in SNMP-STANDARD-MIB
-%%-----------------------------------------------------------------
-snmp_standard_mib(suite) -> [];
-snmp_standard_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?DBG("snmp_standard_mib -> std_mib_init", []),
- try_test(std_mib_init),
-
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- InBadVsns = try_test(std_mib_a),
- put(vsn, v2),
- ?DBG("snmp_standard_mib -> std_mib_read", []),
- try_test(std_mib_read),
- put(vsn, v1),
-
- ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]),
- Bad = try_test(std_mib_b, [InBadVsns]),
- ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []),
- try_test(std_mib_read, [], [{community, "bad community"}]),
- ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []),
- try_test(std_mib_write, [], [{community, "public"}]),
- ?DBG("snmp_standard_mib -> std_mib_asn_err", []),
- try_test(std_mib_asn_err),
- ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]),
- try_test(std_mib_c, [Bad]),
- ?DBG("snmp_standard_mib -> std_mib_a", []),
- try_test(standard_mib_a),
-
- ?DBG("snmp_standard_mib -> std_mib_finish", []),
- try_test(std_mib_finish),
- ?DBG("snmp_standard_mib -> std_mib_test_finish", []),
- try_test(standard_mib_test_finish, [], [{community, "bad community"}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_a() ->
- ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
- ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
- ?line OutPkts2 = OutPkts + 1,
- %% There are some more counters we could test here, but it's not that
- %% important, since they are removed from SNMPv2-MIB.
- ok.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_init() ->
- %% disable authentication failure traps. (otherwise w'd get many of
- %% them - this is also a test to see that it works).
- s([{[snmpEnableAuthenTraps,0], 2}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_finish() ->
- %% enable again
- s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]).
-
-%% Req. SNMP-STANDARD-MIB
-standard_mib_test_finish() ->
- %% force a authenticationFailure
- std_mib_write(),
- %% check that we got a trap
- ?line expect(2, trap, [1,2,3], 4, 0, []).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_read() ->
- ?DBG("std_mib_read -> entry", []),
- g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply
- ?DBG("std_mib_read -> await timeout (i.e. no reply)", []),
- ?line expect(1, timeout). % make sure we don't get a trap!
-
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_write() ->
- ?DBG("std_mib_write -> entry", []),
- s([{[sysLocation, 0], "new_value"}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_asn_err() ->
- snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]).
-
-%%-----------------------------------------------------------------
-%% For this test, the agent is configured for v2 and v3.
-%% o Test the counters and control objects in SNMPv2-MIB
-%%-----------------------------------------------------------------
-snmpv2_mib_2(suite) -> [];
-snmpv2_mib_2(Config) when list(Config) ->
- ?LOG("snmpv2_mib_2 -> start",[]),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?DBG("snmpv2_mib_2 -> standard mib init",[]),
- try_test(std_mib_init),
-
- ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]),
- InBadVsns = try_test(std_mib_a),
-
- ?DBG("snmpv2_mib_2 -> make a bad version read",[]),
- put(vsn, v1),
- try_test(std_mib_read),
-
- ?DBG("snmpv2_mib_2 -> bad version read",[]),
- put(vsn, v2),
- Bad = try_test(std_mib_b, [InBadVsns]),
-
- ?DBG("snmpv2_mib_2 -> read with bad community",[]),
- try_test(std_mib_read, [], [{community, "bad community"}]),
-
- ?DBG("snmpv2_mib_2 -> write with public community",[]),
- try_test(std_mib_write, [], [{community, "public"}]),
-
- ?DBG("snmpv2_mib_2 -> asn err",[]),
- try_test(std_mib_asn_err),
-
- ?DBG("snmpv2_mib_2 -> check counters",[]),
- try_test(std_mib_c, [Bad]),
-
- ?DBG("snmpv2_mib_2 -> get som counters",[]),
- try_test(snmpv2_mib_a),
-
- ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
- try_test(std_mib_finish),
-
- ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, "
- "then disable auth traps",[]),
- try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]),
-
- ?LOG("snmpv2_mib_2 -> done",[]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_3(suite) -> [];
-snmpv2_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- InBadVsns = try_test(std_mib_a),
- put(vsn, v1),
- try_test(std_mib_read),
- put(vsn, v3),
- _Bad = try_test(std_mib_b, [InBadVsns]),
- try_test(snmpv2_mib_a),
-
- try_test(std_mib_finish).
-
--define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]).
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_test_finish() ->
- %% force a authenticationFailure
- ?DBG("ma_v2_inform -> write to std mib",[]),
- std_mib_write(),
-
- %% check that we got a trap
- ?DBG("ma_v2_inform -> await trap",[]),
- ?line expect(2, v2trap, [{[sysUpTime,0], any},
- {[snmpTrapOID,0], ?authenticationFailure}]),
-
- %% and the the inform
- ?DBG("ma_v2_inform -> await inform",[]),
- ?line expect(2, {inform,true}, [{[sysUpTime,0], any},
- {[snmpTrapOID,0],?authenticationFailure}]).
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_a() ->
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
-
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
- InBadVsns.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_b(InBadVsns) ->
- ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
- ?line InBadVsns2 = InBadVsns + 1,
- ?line [InPkts] = get_req(2, [[snmpInPkts,0]]),
- ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]),
- ?line InPkts2 = InPkts + 1,
- ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
- get_req(4, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- {InBadCommunityNames, InBadCommunityUses, InASNErrs}.
-
-%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
-std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
- get_req(1, [[snmpInBadCommunityNames,0],
- [snmpInBadCommunityUses,0],
- [snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
-
-%% Req. SNMPv2-MIB
-snmpv2_mib_a() ->
- ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
- s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line expect(3, [{[snmpSetSerialNo,0], SetSerial},
- {[sysLocation, 0], "val2"}]),
- s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line expect(4, inconsistentValue, 2,
- [{[sysLocation, 0], "val3"},
- {[snmpSetSerialNo,0], SetSerial}]),
- ?line ["val2"] = get_req(5, [[sysLocation,0]]).
-
-
-%%-----------------------------------------------------------------
-%% o Bad community uses/name is tested already
-%% in SNMPv2-MIB and STANDARD-MIB.
-%% o Test add/deletion of rows.
-%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
-snmp_community_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- try_test(snmp_community_mib),
- ?line unload_master("SNMP-COMMUNITY-MIB").
-
-snmp_community_mib_2(X) -> snmp_community_mib(X).
-
-%% Req. SNMP-COMMUNITY-MIB
-snmp_community_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o Test engine boots / time
-%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
-snmp_framework_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- try_test(snmp_framework_mib),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
-
-snmp_framework_mib_2(X) -> snmp_framework_mib(X).
-
-snmp_framework_mib_3(suite) -> [];
-snmp_framework_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(snmp_framework_mib).
-
-
-%% Req. SNMP-FRAMEWORK-MIB
-snmp_framework_mib() ->
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
- sleep(5000),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
- if
- EngineTime+7 < EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- EngineTime+4 > EngineTime2 ->
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
- true -> ok
- end,
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
- [Boots] when integer(Boots) -> ok;
- Else -> ?FAIL(Else)
- end,
- ok.
-
-%%-----------------------------------------------------------------
-%% o Test the counters
-%%-----------------------------------------------------------------
-snmp_mpd_mib_3(suite) -> [];
-snmp_mpd_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- UnknownPDUHs = try_test(snmp_mpd_mib_a),
- try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]),
- try_test(snmp_mpd_mib_c, [UnknownPDUHs]).
-
-
-%% Req. SNMP-MPD-MIB
-snmp_mpd_mib_a() ->
- ?line [UnknownSecs, InvalidMsgs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0]]),
- Pdu = #pdu{type = 'get-request',
- request_id = 23,
- error_status = noError,
- error_index = 0,
- varbinds = []},
- SPdu = #scopedPdu{contextEngineID = "agentEngine",
- contextName = "",
- data = Pdu},
- ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
- V3Hdr1 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [7],
- msgSecurityModel = 23, % bad sec model
- msgSecurityParameters = []},
- V3Hdr2 = #v3_hdr{msgID = 21,
- msgMaxSize = 484,
- msgFlags = [6], % bad flag combination
- msgSecurityModel = 3,
- msgSecurityParameters = []},
- Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1,
- data = SPDUBytes},
- Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2,
- data = SPDUBytes},
- ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1),
- ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2),
- snmp_test_mgr:send_bytes(MsgBytes1),
- snmp_test_mgr:send_bytes(MsgBytes2),
-
- ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
- get_req(1, [[snmpUnknownSecurityModels,0],
- [snmpInvalidMsgs,0],
- [snmpUnknownPDUHandlers, 0]]),
- ?line UnknownSecs2 = UnknownSecs + 1,
- ?line InvalidMsgs2 = InvalidMsgs + 1,
- UnknownPDUHs.
-
--define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]).
-snmp_mpd_mib_b() ->
- g([[sysUpTime,0]]),
- ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]).
-
-
-snmp_mpd_mib_c(UnknownPDUHs) ->
- ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownPDUHs2 = UnknownPDUHs + 1.
-
-
-snmp_target_mib(suite) -> [];
-snmp_target_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
- try_test(snmp_target_mib),
- ?line unload_master("SNMP-TARGET-MIB").
-
-snmp_target_mib_2(X) -> snmp_target_mib(X).
-
-snmp_target_mib_3(X) -> snmp_target_mib(X).
-
-snmp_target_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-snmp_notification_mib(suite) -> [];
-snmp_notification_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- try_test(snmp_notification_mib),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
-
-snmp_notification_mib_2(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib_3(X) -> snmp_notification_mib(X).
-
-snmp_notification_mib() ->
- ?INF("NOT YET IMPLEMENTED", []),
- nyi.
-
-%%-----------------------------------------------------------------
-%% o add/delete views and try them
-%% o try boundaries
-%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
-snmp_view_based_acm_mib(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
- snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X).
-
-snmp_view_based_acm_mib() ->
- snmpa:verbosity(net_if,trace),
- snmpa:verbosity(master_agent,trace),
- ?LOG("start snmp_view_based_acm_mib test",[]),
- %% The user "no-rights" is present in USM, and is mapped to security
- %% name 'no-rights", which is not present in VACM.
- %% So, we'll add rights for it, try them and delete them.
- %% We'll give "no-rights" write access to tDescr.0 and read access
- %% to tDescr2.0
- %% These are the options we'll use to the mgr
- Opts = [{user, "no-rights"}, {community, "no-rights"}],
- %% Find the valid secmodel, and one invalid secmodel.
- {SecMod, InvSecMod} =
- case get(vsn) of
- v1 -> {?SEC_V1, ?SEC_V2C};
- v2 -> {?SEC_V2C, ?SEC_USM};
- v3 -> {?SEC_USM, ?SEC_V1}
- end,
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Now, add a mapping from "no-rights" -> "no-rights-group"
- GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
- GRow1 =
- [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
- {GRow1Status, ?createAndGo}],
- ?DBG("set '~p'",[GRow1]),
- ?line try_test(do_set, [GRow1]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create a mapping for another sec model, and make sure it dosn't
- %% give us access
- GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]],
- GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"},
- {GRow2Status, ?createAndGo}],
-
- ?DBG("set '~p'",[GRow2]),
- ?line try_test(do_set, [GRow2]),
-
- ?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [GRow2Status]),
-
- RVName = "rv_name",
- WVName = "wv_name",
-
- %% Access row
- ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1],
- ARow1Status = [vacmAccessStatus, ARow1Idx],
- ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1},
- {[vacmAccessReadViewName, ARow1Idx], RVName},
- {[vacmAccessWriteViewName, ARow1Idx], WVName},
- {ARow1Status, ?createAndGo}],
-
- %% This access row would give acces, if InvSecMod was valid.
- ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
- ARow2Status = [vacmAccessStatus, ARow2Idx],
- ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
- {[vacmAccessReadViewName, ARow2Idx], "internet"},
- {[vacmAccessWriteViewName, ARow2Idx], "internet"},
- {ARow2Status, ?createAndGo}],
-
- ?line try_test(do_set, [ARow2]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete that row
- ?line try_test(del_row, [ARow2Status]),
-
-
- %% Add valid row
- ?line try_test(do_set, [ARow1]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Create the view family
- VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
- VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access
- VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access
- VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access
- VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx],
- VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx],
- VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
- VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
-
- ?line try_test(add_row, [VRow1Status]),
- ?line try_test(add_row, [VRow2Status]),
- ?line try_test(add_row, [VRow3Status]),
-
- %% We're supposed to have access now...
- ?line try_test(use_rights, [], Opts),
-
- %% Change Row3 to Row4
- ?line try_test(del_row, [VRow3Status]),
- ?line try_test(add_row, [VRow4Status]),
-
- %% We should still have access...
- ?line try_test(use_rights, [], Opts),
-
- %% Delete rows
- ?line try_test(del_row, [GRow1Status]),
-
- ?line try_test(use_no_rights, [], Opts),
-
- %% Delete rest of rows
- ?line try_test(del_row, [ARow1Status]),
- ?line try_test(del_row, [VRow1Status]),
- ?line try_test(del_row, [VRow2Status]),
- ?line try_test(del_row, [VRow4Status]),
-
- ?line try_test(use_no_rights, [], Opts),
- snmpa:verbosity(master_agent,log).
-
-do_set(Row) ->
- s(Row),
- expect(1, Row).
-
-add_row(RowStatus) ->
- s([{RowStatus, ?createAndGo}]),
- expect(1, [{RowStatus, ?createAndGo}]).
-
-del_row(RowStatus) ->
- s([{RowStatus, ?destroy}]),
- expect(1, [{RowStatus, ?destroy}]).
-
-
-
-use_no_rights() ->
- g([[xDescr,0]]),
- ?v1_2_3(expect(11, noSuchName, 1, any),
- expect(12, [{[xDescr,0], noSuchObject}]),
- expect(13, authorizationError, 1, any)),
- g([[xDescr2,0]]),
- ?v1_2_3(expect(21, noSuchName, 1, any),
- expect(22, [{[xDescr2,0], noSuchObject}]),
- expect(23, authorizationError, 1, any)),
- gn([[xDescr]]),
- ?v1_2_3(expect(31, noSuchName, 1, any),
- expect(32, [{[xDescr], endOfMibView}]),
- expect(33, authorizationError, 1, any)),
- s([{[xDescr,0], "tryit"}]),
- ?v1_2_3(expect(41, noSuchName, 1, any),
- expect(42, noAccess, 1, any),
- expect(43, authorizationError, 1, any)).
-
-
-use_rights() ->
- g([[xDescr,0]]),
- expect(1, [{[xDescr,0], any}]),
- g([[xDescr2,0]]),
- expect(2, [{[xDescr2,0], any}]),
- s([{[xDescr,0], "tryit"}]),
- expect(3, noError, 0, any),
- g([[xDescr,0]]),
- expect(4, [{[xDescr,0], "tryit"}]).
-
-mk_ln(X) ->
- [length(X) | X].
-
-%%-----------------------------------------------------------------
-%% o add/delete users and try them
-%% o test all secLevels
-%% o test all combinations of protocols
-%% o try bad ops; check counters
-%%-----------------------------------------------------------------
-snmp_user_based_sm_mib_3(suite) -> [];
-snmp_user_based_sm_mib_3(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
-
- %% The newUser used here already has VACM access.
-
- %% Add a new user in the simplest way; just createAndGo
- try_test(v3_sync, [[{usm_add_user1, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new user
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
- DesKey1 = lists:sublist(ShaKey1, 16),
-
- %% Change the new user's keys - 1
- try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- MgrDir = ?config(mgr_dir, Config),
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
-
- ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"),
- DesKey2 = lists:sublist(ShaKey2, 16),
-
- %% Change the new user's keys - 2
- ?line try_test(v3_sync,
- [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
-
- %% Try to use the new keys
- reset_usm_mgr(MgrDir),
- ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
- ?line load_master("Test2"),
- ?line try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Change the new user's keys - 3
- ?line try_test(v3_sync,
- [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try to use the new keys
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
- try_test(v3_sync, [[{usm_use_user, []}]],
- [{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
- reset_usm_mgr(MgrDir),
-
- %% Try some read requests
- ?line try_test(v3_sync, [[{usm_read, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Delete the new user
- ?line try_test(v3_sync, [[{usm_del_user, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- %% Try some bad requests
- ?line try_test(v3_sync, [[{usm_bad, []}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
-
- ?line unload_master("SNMP-USER-BASED-SM-MIB").
-
--define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
-
-usm_add_user1() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
-usm_use_user() ->
- v2_proc().
-
-
-%% Change own public keys
-usm_key_change1(ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_shaxxxxxxxxxx",
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- "passwd_desxxxxxx",
- DesKey),
- Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change own private keys
-usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs1),
- ?line expect(1, Vbs1).
-
-%% Change other's public keys
-usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldShaKey,
- ShaKey),
- DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha,
- OldDesKey,
- DesKey),
- Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
- s(Vbs1),
- ?line expect(1, noAccess, 1, any),
- Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs2),
- ?line expect(2, noAccess, 1, any),
-
-
- Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
- {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
- s(Vbs3),
- ?line expect(1, Vbs3).
-
-usm_read() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ?line g([[usmUserSecurityName, NewRowIndex],
- [usmUserCloneFrom, NewRowIndex],
- [usmUserAuthKeyChange, NewRowIndex],
- [usmUserOwnAuthKeyChange, NewRowIndex],
- [usmUserPrivKeyChange, NewRowIndex],
- [usmUserOwnPrivKeyChange, NewRowIndex]]),
- ?line expect(1,
- [{[usmUserSecurityName, NewRowIndex], "newUser"},
- {[usmUserCloneFrom, NewRowIndex], [0,0]},
- {[usmUserAuthKeyChange, NewRowIndex], ""},
- {[usmUserOwnAuthKeyChange, NewRowIndex], ""},
- {[usmUserPrivKeyChange, NewRowIndex], ""},
- {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]),
- ok.
-
-
-
-usm_del_user() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs1),
- ?line expect(1, Vbs1),
- ok.
-
--define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
-
--define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]).
-
--define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]).
-
--define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]).
-
--define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]).
-
--define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]).
-
-usm_bad() ->
- NewRowIndex = [11,"agentEngine", 7, "newUser"],
- RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
- Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line expect(1, inconsistentName, 1, any),
-
- RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs2),
- ?line expect(2, wrongValue, 1, any),
-
- RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
- Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
- {[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs3),
- ?line expect(3, Vbs3),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
- ?line expect(4, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
- ?line expect(5, inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
- ?line expect(6, wrongValue, 1, any),
- ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
- ?line expect(7, wrongValue, 1, any),
-
- Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs4),
- ?line expect(1, Vbs4),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Loop through entire MIB, to make sure that all instrum. funcs
-%% works.
-%% Load all std mibs that are not loaded by default.
-%%-----------------------------------------------------------------
-loop_mib(suite) -> [];
-loop_mib(Config) when list(Config) ->
- ?LOG("loop_mib -> initiate case",[]),
- %% snmpa:verbosity(master_agent,debug),
- %% snmpa:verbosity(mib_server,info),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?DBG("loop_mib -> try",[]),
- try_test(loop_mib_1),
- ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- %% snmpa:verbosity(master_agent,log),
- %% snmpa:verbosity(mib_server,silence),
- ?LOG("loop_mib -> done",[]).
-
-
-loop_mib_2(suite) -> [];
-loop_mib_2(Config) when list(Config) ->
- ?LOG("loop_mib_2 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_2 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_2 -> load mibs",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
- ?line load_master_std("SNMP-MPD-MIB"),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_2 -> unload mibs",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
- ?line unload_master("SNMP-MPD-MIB"),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?LOG("loop_mib_2 -> done",[]).
-
-
-loop_mib_3(suite) -> [];
-loop_mib_3(Config) when list(Config) ->
- ?LOG("loop_mib_3 -> initiate case",[]),
- {SaNode, MgrNode, MibDir} = init_case(Config),
- ?DBG("loop_mib_3 -> ~n"
- "\tSaNode: ~p~n"
- "\tMgrNode: ~p~n"
- "\tMibDir: ~p",[SaNode, MgrNode, MibDir]),
- ?DBG("loop_mib_3 -> load mibs",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
- try_test(loop_mib_2),
- ?DBG("loop_mib_3 -> unload mibs",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("SNMP-USER-BASED-SM-MIB"),
- ?LOG("loop_mib_3 -> done",[]).
-
-
-%% Req. As many mibs all possible
-loop_mib_1() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_1([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_1(Oid, N) ->
- ?DBG("loop_it_1 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_1 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_1 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_1(NOid, N+1);
- #pdu{type='get-response', error_status=noSuchName, error_index=1,
- varbinds=[_]} ->
- ?DBG("loop_it_1 -> done",[]),
- N;
-
- #pdu{type = Type, error_status = Err, error_index = Idx,
- varbinds = Vbs} ->
- exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs})
- end.
-
-%% Req. As many mibs all possible
-loop_mib_2() ->
- ?DBG("loop_mib_1 -> entry",[]),
- N = loop_it_2([1,1], 0),
- io:format(user, "found ~w varibles\n", [N]),
- ?line N = if N < 100 -> 100;
- true -> N
- end.
-
-
-loop_it_2(Oid, N) ->
- ?DBG("loop_it_2 -> entry with~n"
- "\tOid: ~p~n"
- "\tN: ~p",[Oid,N]),
- case get_next_req([Oid]) of
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid, value = endOfMibView}]} ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p",[NOid]),
- N;
- #pdu{type='get-response', error_status=noError, error_index=0,
- varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid ->
- ?DBG("loop_it_2 -> ~n"
- "\tNOid: ~p~n"
- "\tValue: ~p",[NOid,Value]),
- ?line [Value2] = get_req(1, [NOid]), % must not be same
- ?DBG("loop_it_2 -> ~n"
- "\tValue2: ~p",[Value2]),
- loop_it_2(NOid, N+1)
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% Testing of reported bugs and other tickets.
-%%%-----------------------------------------------------------------
-
-
-
-
-
-%% These are (ticket) test cases where the initiation has to be done
-%% individually.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1128
-%% Slogan: Bug in handling of createAndWait set-requests.
-%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
-otp_1128(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1128),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1128_2(X) -> otp_1128(X).
-
-otp_1128_3(X) -> otp_1128(X).
-
-otp_1128() ->
- io:format("Testing bug reported in ticket OTP-1128...~n"),
-
- NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")],
- NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
- NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
-
- s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- g([NewKeyc5]),
- ?line expect(29, [{NewKeyc5, ?notReady}]),
- s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- g([NewKeyc5]),
- ?line expect(31, [{NewKeyc5, ?active}]),
- s([{NewKeyc5, ?destroy}]),
- ?line expect(32, [{NewKeyc5, ?destroy}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1129, OTP-1169
-%% Slogan: snmpa:int_to_enum crashes on bad oids
-%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
-otp_1129(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- try_test(otp_1129_i, [node()]),
- ?line unload_master("Klas3").
-
-otp_1129_2(X) -> otp_1129(X).
-
-otp_1129_3(X) -> otp_1129(X).
-
-otp_1129_i(MaNode) ->
- io:format("Testing bug reported in ticket OTP-1129...~n"),
- false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]),
- false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1131
-%% Slogan: Agent crashes / erlang node halts if RowIndex in a
-%% setrequest is of bad type, e.g. an INDEX {INTEGER},
-%% and RowIdenx [3,2].
-%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
-otp_1131(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas1"),
- try_test(otp_1131),
- ?line unload_master("Klas1").
-
-otp_1131_2(X) -> otp_1131(X).
-
-otp_1131_3(X) -> otp_1131(X).
-
-otp_1131() ->
- io:format("Testing bug reported in ticket OTP-1131...~n"),
- s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
- {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1162
-%% Slogan: snmp_agent can't handle wrongValue from instrum.func
-%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
-otp_1162(Config) when list(Config) ->
- {SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
- try_test(otp_1162),
- stop_subagent(SA).
-
-otp_1162_2(X) -> otp_1162(X).
-
-otp_1162_3(X) -> otp_1162(X).
-
-otp_1162() ->
- s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line expect(1, ?v1_2(badValue, wrongValue), 1, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1222
-%% Slogan: snmp agent crash if faulty index is returned from instrum
-%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
-otp_1222(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
- try_test(otp_1222),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4").
-
-otp_1222_2(X) -> otp_1222(X).
-
-otp_1222_3(X) -> otp_1222(X).
-
-otp_1222() ->
- io:format("Testing bug reported in ticket OTP-1222...~n"),
- s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line expect(1, genErr, 0, any),
- s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line expect(2, genErr, 0, any).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1298
-%% Slogan: Negative INTEGER values are treated as positive.
-%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
-otp_1298(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1298),
- ?line unload_master("Klas2").
-
-otp_1298_2(X) -> otp_1298(X).
-
-otp_1298_3(X) -> otp_1298(X).
-
-otp_1298() ->
- io:format("Testing bug reported in ticket OTP-1298...~n"),
- s([{[fint,0], -1}]),
- ?line expect(1298, [{[fint,0], -1}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1331
-%% Slogan: snmp_generic should return noError when deleting non-ex row
-%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
-otp_1331(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1331),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1331_2(X) -> otp_1331(X).
-
-otp_1331_3(X) -> otp_1331(X).
-
-otp_1331() ->
- NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
- s([{NewKeyc5, ?destroy}]),
- ?line expect(1, [{NewKeyc5, ?destroy}]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1338
-%% Slogan: snmp bug in initialisation of default values for mnesia tabs
-%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
-otp_1338(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas2"),
- try_test(otp_1338),
- ?line unload_master("Klas2").
-
-otp_1338_2(X) -> otp_1338(X).
-
-otp_1338_3(X) -> otp_1338(X).
-
-otp_1338() ->
- s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line expect(1, [{[kStatus2, 7], ?createAndGo}]),
- g([[kName2, 7]]),
- ?line expect(2, [{[kName2, 7], "JJJ"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1342
-%% Slogan: default impl of snmp table can't handle bad index access,
-%% Set when INDEX is read-write gets into an infinite loop!
-%%-----------------------------------------------------------------
-otp_1342(suite) -> [];
-otp_1342(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Klas4"),
- try_test(otp_1342),
- ?line unload_master("Klas4").
-
-otp_1342_2(X) -> otp_1342(X).
-
-otp_1342_3(X) -> otp_1342(X).
-
-otp_1342() ->
- s([{[fIndex5, 1], i, 1},
- {[fName5, 1], i, 3},
- {[fStatus5, 1], i, ?createAndGo}]),
- ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-1366
-%% Slogan: snmp traps not sent to all managers
-%% Note: NYI! We need a way to tell the test server that we need
-%% mgrs on two different machines.
-%%-----------------------------------------------------------------
-otp_1366(suite) -> [];
-otp_1366(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_1366),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-otp_1366_2(X) -> otp_1366(X).
-
-otp_1366_3(X) -> otp_1366(X).
-
-otp_1366() ->
- ?INF("NOT YET IMPLEMENTED", []),
- 'NYI'.
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2776
-%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
-%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
-otp_2776(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_2776).
-
-otp_2776_2(X) -> otp_2776(X).
-
-otp_2776_3(X) -> otp_2776(X).
-
-otp_2776() ->
- io:format("Testing bug reported in ticket OTP-2776...~n"),
-
- Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0],
- Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00
- Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0],
- Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0],
- Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0],
- Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0],
- Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2
- Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0],
- Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4
- Dt10_invalid = [],
- Dt11_invalid = [kalle,hobbe],
- L = [{ 1, true, Dt01_valid},
- { 2, true, Dt02_valid},
- { 3, true, Dt03_valid},
- { 4, false, Dt04_invalid},
- { 5, true, Dt05_valid},
- { 6, true, Dt06_valid},
- { 7, false, Dt07_invalid},
- { 8, true, Dt08_valid},
- { 9, false, Dt09_invalid},
- {10, false, Dt10_invalid},
- {11, false, Dt11_invalid}],
-
- ?line ok = validate_dat(L).
-
-
-validate_dat(L) -> validate_dat(L,[]).
-
-validate_dat([],V) ->
- Fun = fun({_,X}) -> case X of
- ok -> false;
- _ -> true
- end
- end,
- validate_dat1( lists:reverse( lists:filter(Fun,V) ) );
-validate_dat([{Id,E,Dat}|T],V) ->
- validate_dat(T,[validate_dat2(Id,E,Dat) | V]).
-
-validate_dat1([]) -> ok;
-validate_dat1(L) -> {error,L}.
-
-validate_dat2(Id, E, Dat) ->
- Res = case {E,snmp:validate_date_and_time(Dat)} of
- {E,E} -> ok;
- {E,A} -> {E,A}
- end,
- {Id, Res}.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-2979
-%% Slogan: get-next on more than 1 column in an empty table
-%% returns bad response.
-%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
-otp_2979(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master("Test1"),
- ?line init_old(),
- try_test(otp_2979),
- ?line unload_master("Test1").
-
-otp_2979_2(X) -> otp_2979(X).
-
-otp_2979_3(X) -> otp_2979(X).
-
-otp_2979() ->
- gn([[sparseDescr], [sparseStatus]]),
- ?line expect(1, [{[sparseStr,0], "slut"},
- {[sparseStr,0], "slut"}]).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
-%% endOfTable - should return value.
-%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
-otp_3187(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- otp_3187(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
-
-otp_3187_2(X) -> otp_3187(X).
-
-otp_3187_3(X) -> otp_3187(X).
-
-otp_3187() ->
- ?line Elements =
- snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
- lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
- ?FAIL(endOfTable);
- true -> ok
- end
- end, Elements).
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3542
-%% Slogan:
-%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
-otp_3542(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_3542).
-
-otp_3542() ->
- io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
- io:format("SNMP v3 discovery result: ~p~n",[Res]).
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-3725
-%% Slogan: Slow response time on snmpa:int_to_enum
-%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
-otp_3725(Config) when list(Config) ->
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
-
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
- try_test(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
-
-%% Req. OLD-SNMPEA-MIB
-otp_3725_test(MaNode) ->
- io:format("Testing feature requested in ticket OTP-3725...~n"),
- ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
- ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]),
- ?DBG("otp_3725_test -> Db = ~p",[Db]),
-
- ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid,
- [Db, intAgentIpAddress]),
- ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name,
- [Db,OID]),
- ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmp, oid_to_name,
- [Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum,
- [Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum,
- [Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmp, enum_to_int,
- [Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Ticket: OTP-4394
-%% Slogan: Target mib tag list check invalid
-%%-----------------------------------------------------------------
-
-
-
-init_otp_4394(Config) when list(Config) ->
- ?DBG("init_otp_4394 -> entry with"
- "~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
- MasterAgentVerbosity = {master_agent_verbosity, trace},
- NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
-
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
- ?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
- Vsn = [v1],
- Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
- ?TRAP_UDP, Ip, 4000,
- "OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
- false ->
- ?line ok
- end,
- C1 = {"a", "all-rights", "initial", "", "pc"},
- C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
- Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
- "pc1",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [],
- 2048},
- Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
- "pc2",
- "target_v1", "",
- %% [255,255,255,255,0,0],
- [], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
- ok.
-
-
-
-finish_otp_4394(Config) when list(Config) ->
- ?DBG("finish_otp_4394 -> entry", []),
- C1 = stop_agent(Config),
- delete_files(C1),
- erase(mgr_node),
- lists:keydelete(vsn, 1, C1).
-
-otp_4394_test(suite) -> [];
-otp_4394_test(Config) ->
- ?DBG("otp_4394_test -> entry", []),
- {_SaNode, _MgrNode, _MibDir} = init_case(Config),
- try_test(otp_4394_test1),
- ?DBG("otp_4394_test -> done", []),
- ok.
-
-otp_4394_test1() ->
- ?DBG("otp_4394_test1 -> entry", []),
- gn([[1,1]]),
- Res =
- case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of
- %% {error, 1, {"?",[]}, {"~w",[timeout]}}
- {error, 1, _, {_, [timeout]}} ->
- ?DBG("otp_4394_test1 -> expected result: timeout", []),
- ok;
- Else ->
- Else
- end,
- ?DBG("otp_4394_test1 -> done with: ~p", [Res]),
- Res.
-
-
-%%%--------------------------------------------------
-%%% Used to test the standard mib with our
-%%% configuration.
-%%%--------------------------------------------------
-run(F, A, Opts) ->
- M = get(mib_dir),
- Dir = get(mgr_dir),
- User = snmp_misc:get_option(user, Opts, "all-rights"),
- SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv),
- EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"),
- CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID),
- Community = snmp_misc:get_option(community, Opts, "all-rights"),
- ?DBG("run -> start crypto app",[]),
- Crypto = case os:type() of
- vxworks ->
- no_crypto;
- _ ->
- ?CRYPTO_START()
- end,
- ?DBG("run -> Crypto: ~p",[Crypto]),
- catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case
- StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
- ?DBG("run -> config:~n"
- "\tM: ~p~n"
- "\tDir: ~p~n"
- "\tUser: ~p~n"
- "\tSecLevel: ~p~n"
- "\tEngineID: ~p~n"
- "\tCtxEngineID: ~p~n"
- "\tCommunity: ~p~n"
- "\tStdM: ~p",
- [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]),
- case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()},
- {packet_server_debug,true},
- {debug,true},
- {agent, get(master_host)},
- {agent_udp, 4000},
- {trap_udp, 5000},
- {recbuf,65535},
- quiet,
- get(vsn),
- {community, Community},
- {user, User},
- {sec_level, SecLevel},
- {engine_id, EngineID},
- {context_engine_id, CtxEngineID},
- {dir, Dir},
- {mibs, mibs(StdM, M)}]) of
- {ok, _Pid} ->
- Res = apply(?MODULE, F, A),
- catch snmp_test_mgr:stop(),
- Res;
- Err ->
- io:format("Error starting manager: ~p\n", [Err]),
- catch snmp_test_mgr:stop(),
- ?line exit({mgr_start, Err})
- end.
-
-
-mibs(StdMibDir,MibDir) ->
- [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")),
- join(MibDir, "OLD-SNMPEA-MIB.bin"),
- join(StdMibDir, "SNMP-FRAMEWORK-MIB"),
- join(StdMibDir, "SNMP-MPD-MIB"),
- join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"),
- join(StdMibDir, "SNMP-USER-BASED-SM-MIB"),
- join(StdMibDir, "SNMP-TARGET-MIB"),
- join(StdMibDir, "SNMP-NOTIFICATION-MIB"),
- join(MibDir, "Klas1.bin"),
- join(MibDir, "Klas2.bin"),
- join(MibDir, "Klas3.bin"),
- join(MibDir, "Klas4.bin"),
- join(MibDir, "SA-MIB.bin"),
- join(MibDir, "TestTrap.bin"),
- join(MibDir, "Test1.bin"),
- join(MibDir, "Test2.bin"),
- join(MibDir, "TestTrapv2.bin")].
-
-join(D,F) ->
- filename:join(D,F).
-
-%% string used in index
-is(S) -> [length(S) | S].
-
-try_test(Func) ->
- call(get(mgr_node), ?MODULE, run, [Func, [], []]).
-
-try_test(Func, A) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, []]).
-
-try_test(Func, A, Opts) ->
- call(get(mgr_node), ?MODULE, run, [Func, A, Opts]).
-
-call(N,M,F,A) ->
- ?DBG("call -> entry with~n"
- " N: ~p~n"
- " M: ~p~n"
- " F: ~p~n"
- " A: ~p~n"
- " when~n"
- " get(): ~p",
- [N,M,F,A,get()]),
- spawn(N, ?MODULE, wait, [self(),get(),M,F,A]),
- receive
- {done, {'EXIT', Rn}, Loc} ->
- ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]),
- put(test_server_loc, Loc),
- exit(Rn);
- {done, Ret, Zed} ->
- ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]),
- Ret
- end.
-
-wait(From, Env, M, F, A) ->
- ?DBG("wait -> entry with ~n"
- "\tFrom: ~p~n"
- "\tEnv: ~p",[From,Env]),
- lists:foreach(fun({K,V}) -> put(K,V) end, Env),
- Rn = (catch apply(M, F, A)),
- ?DBG("wait -> Rn: ~n~p", [Rn]),
- From ! {done, Rn, get(test_server_loc)},
- exit(Rn).
-
-expect(A,B) -> ok = snmp_test_mgr:expect(A,B).
-expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C).
-expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D).
-expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F).
-
-get_req(Id, Vars) ->
- ?DBG("get_req -> entry with~n"
- "\tId: ~p~n"
- "\tVars: ~p",[Id,Vars]),
- g(Vars),
- ?DBG("get_req -> await response",[]),
- {ok, Val} = snmp_test_mgr:get_response(Id, Vars),
- ?DBG("get_req -> response: ~p",[Val]),
- Val.
-
-get_next_req(Vars) ->
- ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]),
- gn(Vars),
- ?DBG("get_next_req -> await response",[]),
- Response = snmp_test_mgr:receive_response(),
- ?DBG("get_next_req -> response: ~p",[Response]),
- Response.
-
-
-
-start_node(Name) ->
- ?LOG("start_node -> entry with Name: ~p",[Name]),
- M = list_to_atom(?HOSTNAME(node())),
- ?DBG("start_node -> M: ~p",[M]),
- Pa = filename:dirname(code:which(?MODULE)),
- ?DBG("start_node -> Pa: ~p",[Pa]),
-
- Args = case init:get_argument('CC_TEST') of
- {ok, [[]]} ->
- " -pa /clearcase/otp/libraries/snmp/ebin ";
- {ok, [[Path]]} ->
- " -pa " ++ Path;
- error ->
- ""
- end,
- %% Do not use start_link!!! (the proc that calls this one is tmp)
- ?DBG("start_node -> Args: ~p~n",[Args]),
- A = Args ++ " -pa " ++ Pa,
- case (catch ?START_NODE(Name, A)) of
- {ok, Node} ->
- %% Tell the test_server to not clean up things it never started.
- ?DBG("start_node -> Node: ~p",[Node]),
- {ok, Node};
- Else ->
- ?ERR("start_node -> failed with(other): Else: ~p",[Else]),
- ?line ?FAIL(Else)
- end.
-
-
-stop_node(Node) ->
- ?LOG("stop_node -> Node: ~p",[Node]),
- rpc:cast(Node, erlang, halt, []).
-
-p(X) ->
- io:format(user, X++"\n", []).
-
-sleep(X) ->
- receive
- after
- X -> ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Configuration
-%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
- "test"),
- ?line case update_usm(Vsns, AgentDir) of
- true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
- filename:join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsns, MgrDir);
- false ->
- ?line ok
- end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
- ok.
-
-delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
- lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
-
-update_usm(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"agentEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", "
- "\"all-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", "
- "\"no-rights\", zeroDotZero, "
- "usmNoAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", "
- "\"authMD5\", zeroDotZero, "
- "usmHMACMD5AuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_md5xxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", "
- "\"authSHA\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmNoPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []),
- ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", "
- "\"privDES\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-update_usm_mgr(Vsns, Dir) ->
- case lists:member(v3, Vsns) of
- true ->
- {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]),
- file:position(Fid, eof),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n",
- []),
- file:close(Fid),
- true;
- false ->
- false
- end.
-
-rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(filename:join(Dir,"usm.conf"),
- filename:join(Dir,"usm.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write),
- ok = io:format(Fid, "{\"agentEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", "
- "\"newUser\", zeroDotZero, "
- "usmHMACSHAAuthProtocol, \"\", \"\", "
- "usmDESPrivProtocol, \"\", \"\", \"\", "
- "\"~s\", \"~s\"}.\n",
- [ShaKey, DesKey]),
- file:close(Fid).
-
-reset_usm_mgr(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"usm.old"),
- filename:join(Dir,"usm.conf")).
-
-
-update_community([v3], _Dir) -> ok;
-update_community(_, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n",
- []),
- file:close(Fid).
-
-
--define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
-update_vacm(_Vsn, Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]),
- file:position(Fid, eof),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]),
- ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]),
- ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", "
- "~w, excluded, null}.\n", [?tDescr_instance]),
- file:close(Fid).
-
-
-vacm_ver(v1) -> v1;
-vacm_ver(v2) -> v2c;
-vacm_ver(v3) -> usm.
-
-
-write_community_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write),
- ok = write_community_conf1(Fid, Confs),
- file:close(Fid).
-
-write_community_conf1(_, []) ->
- ok;
-write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n",
- [ComIdx, ComName, SecName, CtxName, TransTag]),
- write_community_conf1(Fid, Confs).
-
-
-write_target_addr_conf(Dir, Confs) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- ok = write_target_addr_conf1(Fid, Confs),
- file:close(Fid).
-
-
-write_target_addr_conf1(_, []) ->
- ok;
-write_target_addr_conf1(Fid,
- [{Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz}|Confs]) ->
- ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
- [Name, Ip, Port, Timeout, Retry, TagList, ParamName,
- EngineId, TMask, MaxMsgSz]),
- write_target_addr_conf1(Fid, Confs).
-
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
- lists:foreach(fun(Vsn) ->
- ok = io:format(Fid,
- "{\"~s\", ~w, ~w, 1500, 3, "
- "\"std_trap\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP, mk_param(Vsn)]),
- case Vsn of
- v1 -> ok;
- v2 ->
- ok = io:format(Fid,
- "{\"~s.2\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\"}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)]);
- v3 ->
- ok = io:format(Fid,
- "{\"~s.3\",~w,~w,1500,3, "
- "\"std_inform\", \"~s\", "
- "\"mgrEngine\", [], 1024}.~n",
- [mk_ip(ManagerIp, Vsn),
- ManagerIp, UDP,
- mk_param(Vsn)])
- end
- end,
- Vsns),
- file:close(Fid).
-
-mk_param(v1) -> "target_v1";
-mk_param(v2) -> "target_v2";
-mk_param(v3) -> "target_v3".
-
-mk_ip([A,B,C,D], Vsn) ->
- io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]).
-
-
-rewrite_target_addr_conf(Dir,NewPort) ->
- TAFile = filename:join(Dir, "target_addr.conf"),
- ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]),
- case file:read_file_info(TAFile) of
- {ok, _} -> ok;
- {error, R} -> ?ERR("failure reading file info of "
- "target address config file: ~p",[R]),
- ok
- end,
-
- ?line [TrapAddr|Addrs] =
- snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end),
-
- ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
-
- NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs],
-
- ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
-
- ?line ok = file:rename(filename:join(Dir,"target_addr.conf"),
- filename:join(Dir,"target_addr.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write),
-
- ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs),
-
- file:close(Fid).
-
-rewrite_target_addr_conf1(O) ->
- {ok,O}.
-
-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) ->
- ?LOG("rewrite_target_addr_conf2 -> entry with "
- "~n O: ~p",[O]),
- O.
-
-
-rewrite_target_addr_conf3(_,[]) -> ok;
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,
- ParamName,EngineId}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % ParamsName
- "\"~s\"}.", % EngineId
- [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]),
- rewrite_target_addr_conf3(Fid,T);
-rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList,
- ParamName,EngineId,TMask,MMS}|T]) ->
- ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]),
- io:format(Fid,
- "{\"~s\", " % Name
- "~p, " % Ip
- "~p, " % Port
- "~p, " % Timeout
- "~p, " % Retry
- "\"~s\", " % TagList
- "\"~s\", " % ParamsName
- "\"~s\"," % EngineId
- "~p, " % TMask
- "~p}.", % MMS
- [Name,Ip,Port,Timeout,Retry,TagList,ParamName,
- EngineId,TMask,MMS]),
- rewrite_target_addr_conf3(Fid,T).
-
-reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
-
-write_target_params_conf(Dir, Vsns) ->
- {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- lists:foreach(fun(Vsn) ->
- MP = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> v3
- end,
- SM = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> usm
- end,
- ok = io:format(Fid, "{\"target_~w\", ~w, ~w, "
- "\"all-rights\", noAuthNoPriv}.~n",
- [Vsn, MP, SM])
- end,
- Vsns),
- file:close(Fid).
-
-rewrite_target_params_conf(Dir, SecName, SecLevel) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.conf"),
- filename:join(Dir,"target_params.old")),
- ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write),
- ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n",
- [SecName, SecLevel]),
- file:close(Fid).
-
-reset_target_params_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_params.old"),
- filename:join(Dir,"target_params.conf")).
-
-write_notify_conf(Dir) ->
- {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write),
- ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []),
- ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []),
- file:close(Fid).
-
-ver_to_trap_str([v1]) -> "v1";
-ver_to_trap_str([v2]) -> "v2";
-% default is to use the latest snmp version
-ver_to_trap_str([v1,v2]) -> "v2".
-
-
-
-write_view_conf(Dir) ->
- {ok, Fid} = file:open(a(Dir,"view.conf"),write),
- ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []),
- ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]),
- file:close(Fid).
-
-a(A,B) -> lists:append(A,B).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-copy_file(From, To) ->
- {ok, Bin} = file:read_file(From),
- ok = file:write_file(To, Bin).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-display_memory_usage() ->
- Info = snmpa:info(snmp_master_agent),
- TreeSize = lists_key1search(tree_size_bytes, Info),
- ProcMem = lists_key1search(process_memory, Info),
- MibDbSize = lists_key1search([db_memory,mib], Info),
- NodeDbSize = lists_key1search([db_memory,node], Info),
- TreeDbSize = lists_key1search([db_memory,tree], Info),
- ?INF("Memory usage: "
- "~n Tree size: ~p"
- "~n Process memory size: ~p"
- "~n Mib db size: ~p"
- "~n Node db size: ~p"
- "~n Tree db size: ~p",
- [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
-
-lists_key1search([], Res) ->
- Res;
-lists_key1search([Key|Keys], List) when atom(Key), list(List) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- lists_key1search(Keys, Val);
- false ->
- undefined
- end;
-lists_key1search(Key, List) when atom(Key) ->
- case lists:keysearch(Key, 1, List) of
- {value, {Key, Val}} ->
- Val;
- false ->
- undefined
- end.
-
-
-regs() ->
- lists:sort(registered()).
diff --git a/lib/snmp/test/snmp_app_test.erl b/lib/snmp/test/snmp_app_test.erl
index bc62c8d530..9b13e7cf1a 100644
--- a/lib/snmp/test/snmp_app_test.erl
+++ b/lib/snmp/test/snmp_app_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,9 @@
-module(snmp_app_test).
-export([
- all/0,groups/0,init_per_group/2,end_per_group/2, init_per_suite/1,
- end_per_suite/1,
+ all/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,
fields/1,
@@ -52,33 +53,47 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
-Cases = [fields, modules, exportall, app_depend,
- undef_funcs, {group, start_and_stop}],
- Cases.
+ Cases =
+ [
+ fields,
+ modules,
+ exportall,
+ app_depend,
+ undef_funcs,
+ {group, start_and_stop}
+ ],
+ Cases.
groups() ->
[{start_and_stop, [],
- [start_and_stop_empty, start_and_stop_with_agent,
- start_and_stop_with_manager,
- start_and_stop_with_agent_and_manager,
- start_epmty_and_then_agent_and_manager_and_stop,
- start_with_agent_and_then_manager_and_stop,
- start_with_manager_and_then_agent_and_stop]}].
+ [start_and_stop_empty,
+ start_and_stop_with_agent,
+ start_and_stop_with_manager,
+ start_and_stop_with_agent_and_manager,
+ start_epmty_and_then_agent_and_manager_and_stop,
+ start_with_agent_and_then_manager_and_stop,
+ start_with_manager_and_then_agent_and_stop]}].
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
init_per_suite(Config) when is_list(Config) ->
?DISPLAY_SUITE_INFO(),
+
+ %% Note that part of this stuff (the suite top dir creation)
+ %% may already be done (if we run the entire snmp suite).
+
PrivDir = ?config(priv_dir, Config),
TopDir = filename:join(PrivDir, app),
case file:make_dir(TopDir) of
ok ->
ok;
+ {error, eexist} ->
+ ok;
Error ->
fail({failed_creating_subsuite_top_dir, Error})
end,
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index c964b08168..257fc47952 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,6 +40,7 @@
all/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,
description/1,
oid_conflicts/1,
@@ -48,6 +49,7 @@
agent_capabilities/1,
module_compliance/1,
warnings_as_errors/1,
+ augments_extra_info/1,
otp_6150/1,
otp_8574/1,
@@ -58,6 +60,7 @@
%%----------------------------------------------------------------------
%% Internal exports
%%----------------------------------------------------------------------
+
-export([
]).
@@ -74,19 +77,41 @@
%% External functions
%%======================================================================
-init_per_testcase(_Case, Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
- [_|RL] = lists:reverse(filename:split(DataDir)),
- MibDir = join(lists:reverse(["snmp_test_data"|RL])),
- CompDir = join(Dir, "comp_dir/"),
- ?line ok = file:make_dir(CompDir),
- [{comp_dir, CompDir}, {mib_dir, MibDir} | Config].
+init_per_suite(Config0) when is_list(Config0) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config0: ~p", [Config0]),
+
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+
+ %% Mib-dirs
+ %% data_dir is trashed by the test-server / common-test
+ %% so there is no point in fixing it...
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2].
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
+init_per_testcase(Case, Config) when is_list(Config) ->
+
+ ?DBG("init_per_testcase -> entry with"
+ "~n Config: ~p", [Config]),
+
+ CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
+
+ [{case_top_dir, CaseTopDir} | Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- CompDir = ?config(comp_dir, Config),
- ?line ok = ?DEL_DIR(CompDir),
- lists:keydelete(comp_dir, 1, Config).
+ Config.
%%======================================================================
@@ -102,6 +127,7 @@ all() ->
agent_capabilities,
module_compliance,
warnings_as_errors,
+ augments_extra_info,
{group, tickets}
].
@@ -126,7 +152,7 @@ description(Config) when is_list(Config) ->
put(tname,desc),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
Filename = join(Dir,"test"),
MibSrcName = Filename ++ ".mib",
MibBinName = Filename ++ ".bin",
@@ -161,7 +187,7 @@ oid_conflicts(Config) when is_list(Config) ->
put(tname,oid_conflicts),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
Mib = join(Dir,"TESTv2.mib"),
?line ok = write_oid_conflict_mib(Mib),
?line {error,compilation_failed} =
@@ -278,7 +304,7 @@ warnings_as_errors(suite) ->
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),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8574-MIB.mib"),
OutFile = join(Dir, "OTP8574-MIB.bin"),
@@ -303,7 +329,7 @@ otp_6150(Config) when is_list(Config) ->
put(tname,otp_6150),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"),
?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
@@ -319,7 +345,7 @@ otp_8574(Config) when is_list(Config) ->
put(tname,otp_8574),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8574-MIB.mib"),
@@ -352,7 +378,7 @@ otp_8595(Config) when is_list(Config) ->
put(tname,otp_8595),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8595-MIB.mib"),
?line {ok, Mib} =
@@ -364,6 +390,47 @@ otp_8595(Config) when is_list(Config) ->
%%======================================================================
+
+augments_extra_info(suite) ->
+ [];
+augments_extra_info(Config) when is_list(Config) ->
+ put(tname, augments_extra_info),
+ p("starting with Config: ~p~n", [Config]),
+
+ Dir = ?config(case_top_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ Test2File = join(MibDir, "Test2.mib"),
+ Test3File = join(MibDir, "Test3.mib"),
+ ?line {ok, Test2BinFile} =
+ snmpc:compile(Test2File, [{outdir, Dir},
+ {verbosity, silence},
+ {group_check, false}]),
+ io:format("Test2BinFile: ~n~p~n", [Test2BinFile]),
+ ?line {ok, Test3BinFile} =
+ snmpc:compile(Test3File, [{i, [MibDir]},
+ {outdir, Dir},
+ {verbosity, silence},
+ {group_check, true}]),
+ io:format("Test3BinFile: ~n~p~n", [Test3BinFile]),
+ {ok, Test3Mib} = snmp_misc:read_mib(Test3BinFile),
+ io:format("Test3Mib: ~n~p~n", [Test3Mib]),
+ %% There is only one table in this mib
+ #mib{table_infos = [{TableName, TI}]} = Test3Mib,
+ io:format("TableName: ~p"
+ "~n Table Info: ~p"
+ "~n", [TableName, TI]),
+ #table_info{nbr_of_cols = 4,
+ defvals = DefVals,
+ not_accessible = [2,4],
+ index_types = {augments, {tEntry, undefined}},
+ first_accessible = 1} = TI,
+ io:format("Table info: ~p"
+ "~n DefVals: ~p"
+ "~n", [TableName, DefVals]),
+ ok.
+
+
+%%======================================================================
%% Internal functions
%%======================================================================
@@ -517,11 +584,11 @@ DESCRIPTION \"" ++ Desc ++ "\"
::= { test 1 }
END",
- Message = file:write_file(Filename ,Binary),
+ Message = file:write_file(Filename, Binary),
case Message of
ok -> ok;
{error, Reason} ->
- exit({failed_writing_mib,Reason})
+ exit({failed_writing_mib, Reason})
end.
@@ -546,8 +613,8 @@ check_desc(Desc1, Desc2) ->
exit({'description not equal', Desc1, Desc2}).
-join(Comp) ->
- filename:join(Comp).
+%% join(Comp) ->
+%% filename:join(Comp).
join(A,B) ->
filename:join(A,B).
@@ -566,14 +633,7 @@ p(F, A) ->
p(TName, F, A) ->
io:format("*** [~w][~s] ***"
- "~n" ++ F ++ "~n", [TName,format_timestamp(now())|A]).
-
-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).
+ "~n" ++ F ++ "~n", [TName, formated_timestamp()|A]).
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
diff --git a/lib/snmp/test/snmp_log_test.erl b/lib/snmp/test/snmp_log_test.erl
index b692017407..aeac4d1f71 100644
--- a/lib/snmp/test/snmp_log_test.erl
+++ b/lib/snmp/test/snmp_log_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -42,7 +42,11 @@
-export([
init_per_testcase/2, end_per_testcase/2,
- all/0,groups/0,init_per_group/2,end_per_group/2,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+
open_and_close/1,
open_write_and_close1/1,
@@ -109,16 +113,21 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%%======================================================================
%% ?SKIP(not_yet_implemented).
all() ->
-[open_and_close, {group, open_write_and_close},
- {group, log_to_io}, {group, log_to_txt}].
+ [
+ open_and_close,
+ {group, open_write_and_close},
+ {group, log_to_io},
+ {group, log_to_txt}].
groups() ->
- [{open_write_and_close, [],
- [open_write_and_close1, open_write_and_close2,
- open_write_and_close3, open_write_and_close4]},
- {log_to_io, [], [log_to_io1, log_to_io2]},
- {log_to_txt, [],
- [log_to_txt1, log_to_txt2, log_to_txt3]}].
+ [
+ {open_write_and_close, [],
+ [open_write_and_close1, open_write_and_close2,
+ open_write_and_close3, open_write_and_close4]},
+ {log_to_io, [], [log_to_io1, log_to_io2]},
+ {log_to_txt, [],
+ [log_to_txt1, log_to_txt2, log_to_txt3]}
+ ].
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl
index 4498d506f3..3192fe1b40 100644
--- a/lib/snmp/test/snmp_manager_config_test.erl
+++ b/lib/snmp/test/snmp_manager_config_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2726,14 +2726,7 @@ p(F, A) ->
p(TName, F, A) ->
io:format("*** [~s] ***"
- " ~w -> " ++ F ++ "~n", [format_timestamp(now()),TName|A]).
-
-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).
+ " ~w -> " ++ F ++ "~n", [formated_timestamp(),TName|A]).
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index d18f20d359..c374a2f0a6 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -49,6 +49,8 @@
init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
+
simple_start_and_stop1/1,
simple_start_and_stop2/1,
@@ -146,36 +148,43 @@
%% External functions
%%======================================================================
+init_per_suite(Config0) when is_list(Config0) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config0: ~p", [Config0]),
+
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+
+ %% Mib-dirs
+ %% data_dir is trashed by the test-server / common-test
+ %% so there is no point in fixing it...
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2].
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
init_per_testcase(Case, Config) when is_list(Config) ->
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]),
init_per_testcase2(Case, Config).
init_per_testcase2(Case, Config) ->
- ?DBG("init [~w] Nodes [1]: ~p", [Case, erlang:nodes()]),
-
- %% Fix a correct data dir (points to the wrong location):
- DataDir0 = ?config(data_dir, Config),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ ?DBG("init_per_testcase2 -> ~p", [erlang:nodes()]),
- PrivDir = ?config(priv_dir, Config),
+ CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
- TopDir = filename:join(PrivDir, ?MODULE),
- case file:make_dir(TopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- ?FAIL({failed_creating_subsuite_top_dir, Error})
- end,
-
- CaseTopDir = filename:join(TopDir, Case),
- ?line ok = file:make_dir(CaseTopDir),
-
%% -- Manager dirs --
- MgrTopDir = filename:join(CaseTopDir, "manager/"),
+ MgrTopDir = filename:join(CaseTopDir, "manager/"),
+ ?DBG("init_per_testcase2 -> try create manager top dir: ~n~p",
+ [MgrTopDir]),
?line ok = file:make_dir(MgrTopDir),
MgrConfDir = filename:join(MgrTopDir, "conf/"),
@@ -200,10 +209,9 @@ init_per_testcase2(Case, Config) ->
AgLogDir = filename:join(AgTopDir, "log/"),
?line ok = file:make_dir(AgLogDir),
- Conf = [{snmp_data_dir, DataDir},
- {watchdog, ?WD_START(?MINS(5))},
+ Conf = [{watchdog, ?WD_START(?MINS(5))},
{ip, ?LOCALHOST()},
- {top_dir, TopDir},
+ {case_top_dir, CaseTopDir},
{agent_dir, AgTopDir},
{agent_conf_dir, AgConfDir},
{agent_db_dir, AgDbDir},
@@ -388,9 +396,11 @@ all() ->
{group, user_tests},
{group, agent_tests},
{group, request_tests},
+ {group, request_tests_mt},
{group, event_tests},
+ {group, event_tests_mt},
discovery,
- {group, tickets}
+ {group, tickets}
].
groups() ->
@@ -431,6 +441,15 @@ groups() ->
{group, misc_request_tests}
]
},
+ {request_tests_mt, [],
+ [
+ {group, get_tests},
+ {group, get_next_tests},
+ {group, set_tests},
+ {group, bulk_tests},
+ {group, misc_request_tests}
+ ]
+ },
{get_tests, [],
[
simple_sync_get1,
@@ -477,18 +496,30 @@ groups() ->
misc_async2
]
},
- {event_tests, [],
- [
- trap1%% ,
- %% trap2,
- %% inform1,
- %% inform2,
- %% inform3,
- %% inform4,
- %% inform_swarm,
- %% report
- ]
- },
+ {event_tests, [],
+ [
+ trap1,
+ trap2,
+ inform1,
+ inform2,
+ inform3,
+ inform4,
+ inform_swarm,
+ report
+ ]
+ },
+ {event_tests_mt, [],
+ [
+ trap1,
+ trap2,
+ inform1,
+ inform2,
+ inform3,
+ inform4,
+ inform_swarm,
+ report
+ ]
+ },
{tickets, [],
[
{group, otp8015},
@@ -507,11 +538,21 @@ groups() ->
}
].
-init_per_group(_GroupName, Config) ->
- Config.
+init_per_group(request_tests_mt = GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(
+ GroupName,
+ [{manager_net_if_module, snmpm_net_if_mt} | Config]);
+init_per_group(event_tests_mt = GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(
+ GroupName,
+ [{manager_net_if_module, snmpm_net_if_mt} | Config]);
+init_per_group(GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(GroupName, Config).
+
end_per_group(_GroupName, Config) ->
- Config.
+ %% Do we really need to do this?
+ lists:keydelete(snmp_group_top_dir, 1, Config).
%%======================================================================
@@ -1571,6 +1612,11 @@ simple_sync_get1(Config) when is_list(Config) ->
?line ok = mgr_user_load_mib(Node, std_mib()),
Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
?line ok = do_simple_sync_get(Node, Addr, Port, Oids2),
+
+ p("Display log"),
+ display_log(Config),
+
+ p("done"),
ok.
do_simple_sync_get(Node, Addr, Port, Oids) ->
@@ -1578,7 +1624,7 @@ do_simple_sync_get(Node, Addr, Port, 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
@@ -1612,7 +1658,9 @@ simple_sync_get2(suite) -> [];
simple_sync_get2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, ssg2),
- do_simple_sync_get2(Config).
+ do_simple_sync_get2(Config),
+ display_log(Config),
+ ok.
do_simple_sync_get2(Config) ->
Get = fun(Node, TargetName, Oids) ->
@@ -1677,7 +1725,9 @@ 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),
+ display_log(Config),
+ ok.
do_simple_sync_get3(Config) ->
Self = self(),
@@ -1703,8 +1753,8 @@ do_simple_sync_get3(Config) ->
%%======================================================================
-simple_async_get1(doc) -> ["Simple (async) get-request - "
- "Old style (Addr & Port)"];
+simple_async_get1(doc) ->
+ ["Simple (async) get-request - Old style (Addr & Port)"];
simple_async_get1(suite) -> [];
simple_async_get1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1766,6 +1816,7 @@ simple_async_get1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
async_g_exec1(Node, Addr, Port, Oids) ->
@@ -1816,7 +1867,9 @@ simple_async_get2(Config) when is_list(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),
+ display_log(Config),
+ ok.
do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify) ->
?line ok = mgr_user_load_mib(MgrNode, std_mib()),
@@ -1905,7 +1958,9 @@ simple_async_get3(Config) when is_list(Config) ->
PostVerify = fun(ok) -> receive Msg -> ok end;
(Error) -> Error
end,
- do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify).
+ do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify),
+ display_log(Config),
+ ok.
async_g_exec3(Node, TargetName, Oids, SendOpts) ->
mgr_user_async_get2(Node, TargetName, Oids, SendOpts).
@@ -1999,6 +2054,8 @@ simple_sync_get_next1(Config) when is_list(Config) ->
end,
?line ok = do_simple_get_next(8,
MgrNode, Addr, Port, Oids08, VF08),
+
+ display_log(Config),
ok.
@@ -2062,7 +2119,10 @@ simple_sync_get_next2(Config) when is_list(Config) ->
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),
+ display_log(Config),
+ ok.
+
do_simple_sync_get_next2(Config, GetNext, PostVerify)
when is_function(GetNext, 3) andalso is_function(PostVerify, 1) ->
@@ -2193,7 +2253,9 @@ simple_sync_get_next3(Config) when is_list(Config) ->
PostVerify = fun(ok) -> receive Msg -> ok end;
(Error) -> Error
end,
- do_simple_sync_get_next2(Config, GetNext, PostVerify).
+ do_simple_sync_get_next2(Config, GetNext, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -2286,6 +2348,7 @@ simple_async_get_next1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -2315,7 +2378,9 @@ simple_async_get_next2(Config) when is_list(Config) ->
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),
+ display_log(Config),
+ ok.
do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify)
when is_function(GetNext, 1) andalso is_function(PostVerify, 1) ->
@@ -2437,7 +2502,9 @@ simple_async_get_next3(Config) when is_list(Config) ->
(Error) -> Error
end,
- do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify).
+ do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify),
+ display_log(Config),
+ ok.
async_gn_exec3(Node, TargetName, Oids, SendOpts) ->
mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts).
@@ -2475,6 +2542,8 @@ simple_sync_set1(Config) when is_list(Config) ->
{[sysLocation, 0], Val22}
],
?line ok = do_simple_set1(Node, Addr, Port, VAVs2),
+
+ display_log(Config),
ok.
do_simple_set1(Node, Addr, Port, VAVs) ->
@@ -2527,7 +2596,9 @@ simple_sync_set2(Config) when is_list(Config) ->
end,
PostVerify = fun() -> ok end,
- do_simple_sync_set2(Config, Set, PostVerify).
+ do_simple_sync_set2(Config, Set, PostVerify),
+ display_log(Config),
+ ok.
do_simple_sync_set2(Config, Set, PostVerify)
when is_function(Set, 3) andalso is_function(PostVerify, 0) ->
@@ -2604,7 +2675,9 @@ simple_sync_set3(Config) when is_list(Config) ->
end,
PostVerify = fun() -> receive Msg -> ok end end,
- do_simple_sync_set2(Config, Set, PostVerify).
+ do_simple_sync_set2(Config, Set, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -2663,6 +2736,7 @@ simple_async_set1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -2724,7 +2798,9 @@ simple_async_set2(Config) when is_list(Config) ->
end,
PostVerify = fun(Res) -> Res end,
- do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify).
+ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify),
+ display_log(Config),
+ ok.
do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify) ->
Requests =
@@ -2806,7 +2882,9 @@ simple_async_set3(Config) when is_list(Config) ->
(Res) -> Res
end,
- do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify).
+ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify),
+ display_log(Config),
+ ok.
async_s_exec3(Node, TargetName, VAVs, SendOpts) ->
mgr_user_async_set2(Node, TargetName, VAVs, SendOpts).
@@ -2932,6 +3010,7 @@ simple_sync_get_bulk1(Config) when is_list(Config) ->
0, 2,
[[TCnt2, 1]], VF11),
+ display_log(Config),
ok.
fl(L) ->
@@ -3004,7 +3083,9 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
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),
+ display_log(Config),
+ ok.
do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
%% -- 1 --
@@ -3169,7 +3250,9 @@ simple_sync_get_bulk3(Config) when is_list(Config) ->
(Res) -> Res
end,
- do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -3308,6 +3391,7 @@ simple_async_get_bulk1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -3340,7 +3424,9 @@ simple_async_get_bulk2(Config) when is_list(Config) ->
end,
PostVerify = fun(Res) -> Res end,
- do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify) ->
%% We re-use the verification functions from the ssgb test-case
@@ -3505,7 +3591,9 @@ simple_async_get_bulk3(Config) when is_list(Config) ->
(Res) -> Res
end,
- do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
async_gb_exec3(Node, TargetName, {NR, MR, Oids}, SendOpts) ->
mgr_user_async_get_bulk2(Node, TargetName, NR, MR, Oids, SendOpts).
@@ -3697,6 +3785,7 @@ misc_async1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -3885,6 +3974,7 @@ misc_async2(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -4099,7 +4189,9 @@ trap1(Config) when is_list(Config) ->
{5, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4290,7 +4382,9 @@ trap2(Config) when is_list(Config) ->
{7, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4415,7 +4509,9 @@ inform1(Config) when is_list(Config) ->
{6, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4423,7 +4519,7 @@ inform1(Config) when is_list(Config) ->
inform2(suite) -> [];
inform2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- put(tname,i2),
+ put(tname, i2),
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4577,7 +4673,7 @@ inform2(Config) when is_list(Config) ->
[
{1, "Manager and agent info at start of test", Cmd1},
{2, "Send notifcation [no receiver] from agent", Cmd2},
- {3, "await inform-sent acknowledge from agent", Cmd3},
+ {3, "Await inform-sent acknowledge from agent", Cmd3},
{4, "Await first inform to manager - do not reply", Cmd4},
{5, "Await second inform to manager - reply", Cmd5},
{6, "await inform-acknowledge from agent", Cmd6},
@@ -4585,7 +4681,9 @@ inform2(Config) when is_list(Config) ->
{8, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4719,7 +4817,9 @@ inform3(Config) when is_list(Config) ->
{9, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4835,7 +4935,9 @@ inform4(Config) when is_list(Config) ->
{6, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4923,7 +5025,10 @@ inform_swarm(Config) when is_list(Config) ->
{5, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
+
inform_swarm_collector(N) ->
inform_swarm_collector(N, 0, 0, 0, 10000).
@@ -5227,8 +5332,8 @@ init_agent(Config) ->
%% --
%% Retrieve some dir's
%%
- Dir = ?config(top_dir, Config),
- DataDir = ?config(data_dir, Config),
+ Dir = ?config(agent_dir, Config),
+ MibDir = ?config(mib_dir, Config),
%% --
%% Start node
@@ -5259,7 +5364,7 @@ init_agent(Config) ->
?line ok = write_agent_config(Vsns, Config),
Conf = [{agent_node, Node},
- {mib_dir, DataDir} | Config],
+ {mib_dir, MibDir} | Config],
%%
%% Start the agent
@@ -5720,6 +5825,15 @@ start_manager(Node, Vsns, Conf0, Opts) ->
AtlSeqNo = get_opt(manager_atl_seqno, Conf0, false),
+ NetIfConf =
+ case get_opt(manager_net_if_module, Conf0, no_module) of
+ no_module ->
+ [{verbosity, NetIfVerbosity}];
+ NetIfModule ->
+ [{module, NetIfModule},
+ {verbosity, NetIfVerbosity}]
+ end,
+
Env = [{versions, Vsns},
{inform_request_behaviour, IRB},
{audit_trail_log, [{type, read_write},
@@ -5732,7 +5846,7 @@ start_manager(Node, Vsns, Conf0, Opts) ->
{verbosity, ConfigVerbosity}]},
{note_store, [{verbosity, NoteStoreVerbosity}]},
{server, [{verbosity, ServerVerbosity}]},
- {net_if, [{verbosity, NetIfVerbosity}]}],
+ {net_if, NetIfConf}],
?line ok = set_mgr_env(Node, Env),
?line ok = start_snmp(Node),
@@ -6018,6 +6132,38 @@ write_conf_file(Dir, File, Str) ->
%% ------
+display_log(Config) ->
+ case lists:keysearch(manager_log_dir, 1, Config) of
+ {value, {_, Dir}} ->
+ case lists:keysearch(manager_node, 1, Config) of
+ {value, {_, Node}} ->
+ LogDir = Dir,
+ Mibs = [],
+ OutFile = j(LogDir, "snmpm_log.txt"),
+ p("~n"
+ "========================="
+ " < Audit Trail Log > "
+ "========================="
+ "~n"),
+ rcall(Node, snmpm, log_to_txt, [LogDir, Mibs, OutFile]),
+ rcall(Node, snmpm, log_to_io, [LogDir, Mibs]),
+ p("~n"
+ "========================="
+ " < / Audit Trail Log > "
+ "========================="
+ "~n");
+ false ->
+ p("display_log -> no manager node found"),
+ ok
+ end;
+ false ->
+ p("display_log -> no manager log dir found"),
+ ok
+ end.
+
+
+%% ------
+
test2_mib(Config) ->
j(test_mib_dir(Config), "Test2.bin").
@@ -6034,7 +6180,7 @@ snmpv2_mib() ->
j(mib_dir(), "SNMPv2-MIB.bin").
test_mib_dir(Config) ->
- ?config(snmp_data_dir, Config).
+ ?config(mib_dir, Config).
mib_dir() ->
j(code:priv_dir(snmp), "mibs").
@@ -6064,7 +6210,7 @@ rcall(Node, Mod, Func, Args) ->
%% Time in milli sec
%% t() ->
-%% {A,B,C} = erlang:now(),
+%% {A,B,C} = os:timestamp(),
%% A*1000000000+B*1000+(C div 1000).
@@ -6078,16 +6224,10 @@ p(F, A) ->
p(TName, F, A) ->
io:format("*** [~w][~s] ***"
- "~n" ++ F ++ "~n", [TName,format_timestamp(now())|A]).
-
-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).
+ "~n" ++ F ++ "~n", [TName, formated_timestamp()|A]).
+
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
%% p(TName, F, A) ->
%% io:format("~w -> " ++ F ++ "~n", [TName|A]).
diff --git a/lib/snmp/test/snmp_manager_user_old.erl b/lib/snmp/test/snmp_manager_user_old.erl
index edffc80dd4..6280cef51f 100755..100644
--- a/lib/snmp/test/snmp_manager_user_old.erl
+++ b/lib/snmp/test/snmp_manager_user_old.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
diff --git a/lib/snmp/test/snmp_pdus_test.erl b/lib/snmp/test/snmp_pdus_test.erl
index 07b6d6b657..0d78749bcb 100644
--- a/lib/snmp/test/snmp_pdus_test.erl
+++ b/lib/snmp/test/snmp_pdus_test.erl
@@ -39,6 +39,7 @@
otp7575/1,
otp8563/1,
otp9022/1,
+ otp10132/1,
init_per_testcase/2, end_per_testcase/2
]).
@@ -74,16 +75,16 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%% Test case definitions
%%======================================================================
all() ->
-[{group, tickets}].
+ [{group, tickets}].
groups() ->
- [{tickets, [], [otp7575, otp8563, otp9022]}].
+ [{tickets, [], [otp7575, otp8563, otp9022, otp10132]}].
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
@@ -94,7 +95,7 @@ end_per_group(_GroupName, Config) ->
%%======================================================================
otp7575(suite) -> [];
-otp7575(doc) -> ["OTP-7575"];
+otp7575(doc) -> ["OTP-7575 - Message version"];
otp7575(Config) when is_list(Config) ->
io:format("attempt to decode message with valid version~n", []),
MsgWithOkVersion = <<48,39,2,1,0,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>,
@@ -127,48 +128,55 @@ otp7575(Config) when is_list(Config) ->
otp8563(suite) -> [];
-otp8563(doc) -> ["OTP-8563"];
+otp8563(doc) -> ["OTP-8563 - Counter64"];
otp8563(Config) when is_list(Config) ->
Val1 = 16#7fffffffffffffff,
- io:format("try encode and decode ~w~n", [Val1]),
+ io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]),
Enc1 = snmp_pdus:enc_value('Counter64', Val1),
+ io:format(" => ~w~n", [Enc1]),
{{'Counter64', Val1}, []} = snmp_pdus:dec_value(Enc1),
Val2 = Val1 + 1,
- io:format("try encode and decode ~w~n", [Val2]),
+ io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]),
Enc2 = snmp_pdus:enc_value('Counter64', Val2),
+ io:format(" => ~w~n", [Enc2]),
{{'Counter64', Val2}, []} = snmp_pdus:dec_value(Enc2),
Val3 = Val2 + 1,
- io:format("try encode and decode ~w~n", [Val3]),
+ io:format("try encode and decode valule 3: ~w (0x~.16b)~n", [Val3, Val3]),
Enc3 = snmp_pdus:enc_value('Counter64', Val3),
+ io:format(" => ~w~n", [Enc3]),
{{'Counter64', Val3}, []} = snmp_pdus:dec_value(Enc3),
Val4 = 16#fffffffffffffffe,
- io:format("try encode and decode ~w~n", [Val4]),
+ io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]),
Enc4 = snmp_pdus:enc_value('Counter64', Val4),
+ io:format(" => ~w~n", [Enc4]),
{{'Counter64', Val4}, []} = snmp_pdus:dec_value(Enc4),
Val5 = Val4 + 1,
- io:format("try encode and decode ~w~n", [Val5]),
+ io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]),
Enc5 = snmp_pdus:enc_value('Counter64', Val5),
+ io:format(" => ~w~n", [Enc5]),
{{'Counter64', Val5}, []} = snmp_pdus:dec_value(Enc5),
Val6 = 16#ffffffffffffffff + 1,
- io:format("try and fail to encode ~w~n", [Val6]),
+ io:format("try and fail to encode value 6: ~w (0x~.16b)~n", [Val6, Val6]),
case (catch snmp_pdus:enc_value('Counter64', Val6)) of
{'EXIT', {error, {bad_counter64, Val6}}} ->
ok;
Unexpected6 ->
+ io:format(" => ~w~n", [Unexpected6]),
exit({unexpected_encode_result, Unexpected6, Val6})
end,
Val7 = -1,
- io:format("try and fail to encode ~w~n", [Val7]),
+ io:format("try and fail to encode value 7: ~w~n", [Val7]),
case (catch snmp_pdus:enc_value('Counter64', Val7)) of
{'EXIT', {error, {bad_counter64, Val7}}} ->
ok;
Unexpected7 ->
+ io:format(" => ~w~n", [Unexpected7]),
exit({unexpected_encode_result, Unexpected7, Val7})
end,
@@ -176,51 +184,151 @@ otp8563(Config) when is_list(Config) ->
otp9022(suite) -> [];
-otp9022(doc) -> ["OTP-9022"];
+otp9022(doc) -> ["OTP-9022 - Counter32"];
otp9022(Config) when is_list(Config) ->
- Val1 = 16#7fffffff,
- io:format("try encode and decode ~w~n", [Val1]),
+ Val0 = 2908389204,
+ io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]),
+ Enc0 = snmp_pdus:enc_value('Counter32', Val0),
+ io:format(" => ~w~n", [Enc0]),
+ {{'Counter32', Val0}, []} = snmp_pdus:dec_value(Enc0),
+
+ Val1 = 0,
+ io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]),
Enc1 = snmp_pdus:enc_value('Counter32', Val1),
+ io:format(" => ~w~n", [Enc1]),
{{'Counter32', Val1}, []} = snmp_pdus:dec_value(Enc1),
Val2 = Val1 + 1,
- io:format("try encode and decode ~w~n", [Val2]),
+ io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]),
Enc2 = snmp_pdus:enc_value('Counter32', Val2),
+ io:format(" => ~w~n", [Enc2]),
{{'Counter32', Val2}, []} = snmp_pdus:dec_value(Enc2),
- Val3 = Val2 + 1,
- io:format("try encode and decode ~w~n", [Val3]),
+ Val3 = 16#7ffffffe,
+ io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]),
Enc3 = snmp_pdus:enc_value('Counter32', Val3),
+ io:format(" => ~w~n", [Enc3]),
{{'Counter32', Val3}, []} = snmp_pdus:dec_value(Enc3),
- Val4 = 16#fffffffe,
- io:format("try encode and decode ~w~n", [Val4]),
+ Val4 = Val3 + 1,
+ io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]),
Enc4 = snmp_pdus:enc_value('Counter32', Val4),
+ io:format(" => ~w~n", [Enc4]),
{{'Counter32', Val4}, []} = snmp_pdus:dec_value(Enc4),
Val5 = Val4 + 1,
- io:format("try encode and decode ~w~n", [Val5]),
+ io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]),
Enc5 = snmp_pdus:enc_value('Counter32', Val5),
+ io:format(" => ~w~n", [Enc5]),
{{'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}}} ->
+ Val6 = 16#fffffffe,
+ io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]),
+ Enc6 = snmp_pdus:enc_value('Counter32', Val6),
+ io:format(" => ~w~n", [Enc6]),
+ {{'Counter32', Val6}, []} = snmp_pdus:dec_value(Enc6),
+
+ Val7 = Val6 + 1,
+ io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]),
+ Enc7 = snmp_pdus:enc_value('Counter32', Val7),
+ io:format(" => ~w~n", [Enc7]),
+ {{'Counter32', Val7}, []} = snmp_pdus:dec_value(Enc7),
+
+ Val8 = 16#ffffffff + 1,
+ io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]),
+ case (catch snmp_pdus:enc_value('Counter32', Val8)) of
+ {'EXIT', {error, {bad_counter32, Val8}}} ->
ok;
- Unexpected6 ->
- exit({unexpected_encode_result, Unexpected6, Val6})
+ Unexpected8 ->
+ io:format(" => ~w~n", [Unexpected8]),
+ exit({unexpected_encode_result, Unexpected8, Val8})
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}}} ->
+ Val9 = -1,
+ io:format("try and fail to encode value 9: ~w~n", [Val9]),
+ case (catch snmp_pdus:enc_value('Counter32', Val9)) of
+ {'EXIT', {error, {bad_counter32, Val9}}} ->
ok;
- Unexpected7 ->
- exit({unexpected_encode_result, Unexpected7, Val7})
+ Unexpected9 ->
+ io:format(" => ~w~n", [Unexpected9]),
+ exit({unexpected_encode_result, Unexpected9, Val9})
+ end,
+
+ ok.
+
+
+otp10132(suite) -> [];
+otp10132(doc) -> ["OTP-10132 - TimeTicks"];
+otp10132(Config) when is_list(Config) ->
+ Val0 = 2159001034,
+ io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]),
+ Enc0 = snmp_pdus:enc_value('TimeTicks', Val0),
+ io:format(" => ~w~n", [Enc0]),
+ {{'TimeTicks', Val0}, []} = snmp_pdus:dec_value(Enc0),
+
+ Val1 = 0,
+ io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]),
+ Enc1 = snmp_pdus:enc_value('TimeTicks', Val1),
+ io:format(" => ~w~n", [Enc1]),
+ {{'TimeTicks', Val1}, []} = snmp_pdus:dec_value(Enc1),
+
+ Val2 = Val1 + 1,
+ io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]),
+ Enc2 = snmp_pdus:enc_value('TimeTicks', Val2),
+ io:format(" => ~w~n", [Enc2]),
+ {{'TimeTicks', Val2}, []} = snmp_pdus:dec_value(Enc2),
+
+ Val3 = 16#7ffffffe,
+ io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]),
+ Enc3 = snmp_pdus:enc_value('TimeTicks', Val3),
+ io:format(" => ~w~n", [Enc3]),
+ {{'TimeTicks', Val3}, []} = snmp_pdus:dec_value(Enc3),
+
+ Val4 = Val3 + 1,
+ io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]),
+ Enc4 = snmp_pdus:enc_value('TimeTicks', Val4),
+ io:format(" => ~w~n", [Enc4]),
+ {{'TimeTicks', Val4}, []} = snmp_pdus:dec_value(Enc4),
+
+ Val5 = Val4 + 1,
+ io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]),
+ Enc5 = snmp_pdus:enc_value('TimeTicks', Val5),
+ io:format(" => ~w~n", [Enc5]),
+ {{'TimeTicks', Val5}, []} = snmp_pdus:dec_value(Enc5),
+
+ Val6 = 16#fffffffe,
+ io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]),
+ Enc6 = snmp_pdus:enc_value('TimeTicks', Val6),
+ io:format(" => ~w~n", [Enc6]),
+ {{'TimeTicks', Val6}, []} = snmp_pdus:dec_value(Enc6),
+
+ Val7 = Val6 + 1,
+ io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]),
+ Enc7 = snmp_pdus:enc_value('TimeTicks', Val7),
+ io:format(" => ~w~n", [Enc7]),
+ {{'TimeTicks', Val7}, []} = snmp_pdus:dec_value(Enc7),
+
+ Val8 = Val7 + 1,
+ io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]),
+ case (catch snmp_pdus:enc_value('TimeTicks', Val8)) of
+ {'EXIT', {error, {bad_timeticks, Val8}}} ->
+ ok;
+ Unexpected8 ->
+ io:format(" => ~w~n", [Unexpected8]),
+ exit({unexpected_encode_result, Unexpected8, Val8})
end,
+ Val9 = -1,
+ io:format("try and fail to encode value 9: ~w~n", [Val9]),
+ case (catch snmp_pdus:enc_value('TimeTicks', Val9)) of
+ {'EXIT', {error, {bad_timeticks, Val9}}} ->
+ ok;
+ Unexpected9 ->
+ io:format(" => ~w~n", [Unexpected9]),
+ exit({unexpected_encode_result, Unexpected9, Val9})
+ end,
+
+ io:format("done~n", []),
ok.
diff --git a/lib/snmp/test/snmp_test_data/Test3.mib b/lib/snmp/test/snmp_test_data/Test3.mib
new file mode 100644
index 0000000000..7f76e4dba4
--- /dev/null
+++ b/lib/snmp/test/snmp_test_data/Test3.mib
@@ -0,0 +1,123 @@
+Test3 DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, Integer32, snmpModules, mib-2
+ FROM SNMPv2-SMI
+ MODULE-COMPLIANCE, OBJECT-GROUP
+ FROM SNMPv2-CONF
+ tEntry
+ FROM Test2;
+
+t3MIB MODULE-IDENTITY
+ LAST-UPDATED "1203090000Z"
+ ORGANIZATION ""
+ CONTACT-INFO
+ ""
+ DESCRIPTION
+ "Test mib, used to test processing of requests."
+ ::= { snmpModules 42 }
+
+
+-- Administrative assignments ****************************************
+
+t3MIBObjects OBJECT IDENTIFIER ::= { t3MIB 1 }
+t3MIBConformance OBJECT IDENTIFIER ::= { t3MIB 2 }
+
+
+-- test4 OBJECT IDENTIFIER ::= { mib-2 18 }
+
+tAugTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF TAugEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table AUGMENTS tTable of the Test2 MIB."
+ ::= { t3MIBObjects 1 }
+
+tAugEntry OBJECT-TYPE
+ SYNTAX TAugEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An entry (conceptual row) in the sysORTable."
+ AUGMENTS { tEntry }
+ ::= { tAugTable 1 }
+
+TAugEntry ::= SEQUENCE {
+ tFoo1 OCTET STRING,
+ tFoo2 OCTET STRING,
+ tBar1 Integer32,
+ tBar2 Integer32
+}
+
+tFoo1 OBJECT-TYPE
+ SYNTAX OCTET STRING (SIZE (0..255))
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "A string."
+ DEFVAL { "foo 1" }
+ ::= { tAugEntry 1 }
+
+tFoo2 OBJECT-TYPE
+ SYNTAX OCTET STRING (SIZE (0..255))
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A string."
+ DEFVAL { "foo 2" }
+ ::= { tAugEntry 2 }
+
+tBar1 OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "An integer."
+ DEFVAL { 42 }
+ ::= { tAugEntry 3 }
+
+tBar2 OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An integer."
+ DEFVAL { 42 }
+ ::= { tAugEntry 4 }
+
+
+-- Conformance Information *******************************************
+
+t3MIBCompliances OBJECT IDENTIFIER
+ ::= { t3MIBConformance 1 }
+t3MIBGroups OBJECT IDENTIFIER
+ ::= { t3MIBConformance 2 }
+
+-- Compliance statements
+
+t3MIBCompliance MODULE-COMPLIANCE
+ STATUS current
+ DESCRIPTION
+ "The compliance statement for SNMP engines which
+ implement the SNMP-COMMUNITY-MIB."
+
+ MODULE -- this module
+ MANDATORY-GROUPS { t3Group }
+
+ ::= { t3MIBCompliances 1 }
+
+t3Group OBJECT-GROUP
+ OBJECTS {
+ tFoo1,
+ tFoo2,
+ tBar1,
+ tBar2
+ }
+ STATUS current
+ DESCRIPTION
+ "A group."
+ ::= { t3MIBGroups 1 }
+
+
+END
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index 54839d989b..26115a0c74 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The 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,10 @@
-export([hostname/0, hostname/1, localhost/0, os_type/0, sz/1,
display_suite_info/1]).
-export([non_pc_tc_maybe_skip/4, os_based_skip/1]).
--export([replace_config/3, set_config/3, get_config/2, get_config/3]).
+-export([fix_data_dir/1,
+ init_suite_top_dir/2, init_group_top_dir/2, init_testcase_top_dir/2,
+ lookup/2,
+ replace_config/3, set_config/3, get_config/2, get_config/3]).
-export([fail/3, skip/3]).
-export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]).
-export([flush_mqueue/0, trap_exit/0, trap_exit/1]).
@@ -37,7 +40,7 @@
-export([watchdog/3, watchdog_start/1, watchdog_start/2, watchdog_stop/1]).
-export([del_dir/1]).
-export([cover/1]).
--export([p/2, print/5]).
+-export([p/2, print/5, formated_timestamp/0]).
%% ----------------------------------------------------------------------
@@ -198,6 +201,97 @@ os_based_skip(_Crap) ->
%% Test suite utility functions
%%
+fix_data_dir(Config) ->
+ DataDir0 = lookup(data_dir, Config),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config),
+ [{data_dir, DataDir ++ "/"} | Config1].
+
+
+init_suite_top_dir(Suite, Config0) ->
+ io:format("~w:init_suite_top_dir -> entry with"
+ "~n Suite: ~p"
+ "~n Config0: ~p"
+ "~n", [?MODULE, Suite, Config0]),
+ Dir = lookup(priv_dir, Config0),
+ SuiteTopDir = filename:join(Dir, Suite),
+ case file:make_dir(SuiteTopDir) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ {error, Reason} ->
+ fail({failed_creating_suite_top_dir, SuiteTopDir, Reason},
+ ?MODULE, ?LINE)
+ end,
+
+ %% This is just in case...
+ Config1 = lists:keydelete(snmp_group_top_dir, 1, Config0),
+ Config2 = lists:keydelete(snmp_suite_top_dir, 1, Config1),
+ [{snmp_suite_top_dir, SuiteTopDir} | Config2].
+
+
+init_group_top_dir(GroupName, Config) ->
+ io:format("~w:init_group_top_dir -> entry with"
+ "~n GroupName: ~p"
+ "~n Config: ~p"
+ "~n", [?MODULE, GroupName, Config]),
+ case lists:keysearch(snmp_group_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ %% This is a sub-group, so create our dir within Dir
+ GroupTopDir = filename:join(Dir, GroupName),
+ case file:make_dir(GroupTopDir) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ fail({failed_creating_group_top_dir, GroupTopDir, Reason},
+ ?MODULE, ?LINE)
+ end,
+ [{snmp_group_top_dir, GroupTopDir} | Config];
+
+ _ ->
+ case lists:keysearch(snmp_suite_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ GroupTopDir = filename:join(Dir, GroupName),
+ case file:make_dir(GroupTopDir) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ fail({failed_creating_group_top_dir,
+ GroupTopDir, Reason},
+ ?MODULE, ?LINE)
+ end,
+ [{snmp_group_top_dir, GroupTopDir} | Config];
+ _ ->
+ fail(could_not_find_suite_top_dir, ?MODULE, ?LINE)
+ end
+ end.
+
+
+init_testcase_top_dir(Case, Config) ->
+ io:format("~w:init_testcase_top_dir -> entry with"
+ "~n Case: ~p"
+ "~n Config: ~p"
+ "~n", [?MODULE, Case, Config]),
+ case lists:keysearch(snmp_group_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ CaseTopDir = filename:join(Dir, Case),
+ ok = file:make_dir(CaseTopDir),
+ CaseTopDir;
+ false ->
+ case lists:keysearch(snmp_suite_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ CaseTopDir = filename:join(Dir, Case),
+ ok = file:make_dir(CaseTopDir),
+ CaseTopDir;
+ false ->
+ fail(failed_creating_case_top_dir, ?MODULE, ?LINE)
+ end
+ end.
+
+
replace_config(Key, Config, NewValue) ->
lists:keyreplace(Key, 1, Config, {Key, NewValue}).
@@ -220,6 +314,9 @@ get_config(Key,C,Default) ->
Default
end.
+lookup(Key, Config) ->
+ {value, {Key, Value}} = lists:keysearch(Key, 1, Config),
+ Value.
fail(Reason, Mod, Line) ->
exit({suite_failed, Reason, Mod, Line}).
@@ -521,15 +618,18 @@ p(F, A) when is_list(F) andalso is_list(A) ->
print(Prefix, Module, Line, Format, Args) ->
io:format("*** [~s] ~s ~p ~p ~p:~p *** " ++ Format ++ "~n",
- [format_timestamp(now()),
+ [formated_timestamp(),
Prefix, node(), self(), Module, Line|Args]).
+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",
+ io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w ~w",
[YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
lists:flatten(FormatDate).
diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl
index 84bdc6b04f..499cf7abcf 100644
--- a/lib/snmp/test/snmp_test_mgr.erl
+++ b/lib/snmp/test/snmp_test_mgr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1124,16 +1124,11 @@ d(F,A) -> d(get(debug),F,A).
d(true,F,A) ->
io:format("*** [~s] MGR_DBG *** " ++ F ++ "~n",
- [format_timestamp(now())|A]);
+ [formated_timestamp()|A]);
d(_,_F,_A) ->
ok.
-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).
+
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
diff --git a/lib/snmp/test/snmp_test_mgr_misc.erl b/lib/snmp/test/snmp_test_mgr_misc.erl
index fc6dedd96d..5525c5c3ec 100644
--- a/lib/snmp/test/snmp_test_mgr_misc.erl
+++ b/lib/snmp/test/snmp_test_mgr_misc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -779,16 +779,9 @@ d(F,A) -> d(get(debug),F,A).
d(true,F,A) ->
io:format("*** [~s] MGR_PS_DBG *** " ++ F ++ "~n",
- [format_timestamp(now())|A]);
+ [formated_timestamp()|A]);
d(_,_F,_A) ->
ok.
-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).
-
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
diff --git a/lib/snmp/test/test-mibs/RMON-MIB.mib b/lib/snmp/test/test-mibs/RMON-MIB.mib
index 0824dbde1d..fa5bc82f4a 100644
--- a/lib/snmp/test/test-mibs/RMON-MIB.mib
+++ b/lib/snmp/test/test-mibs/RMON-MIB.mib
@@ -1,3826 +1,3958 @@
- RMON-MIB DEFINITIONS ::= BEGIN
-
- IMPORTS
- Counter FROM RFC1155-SMI
- mib-2,DisplayString FROM RFC1213-MIB
- OBJECT-TYPE FROM RFC-1212
- TRAP-TYPE FROM RFC-1215;
-
- -- Remote Network Monitoring MIB
-
- rmon OBJECT IDENTIFIER ::= { mib-2 16 }
-
-
- -- textual conventions
-
- OwnerString ::= DisplayString
- -- This data type is used to model an administratively
- -- assigned name of the owner of a resource. This
- -- information is taken from the NVT ASCII character
- -- set. It is suggested that this name contain one or
-
-
- -- more of the following: IP address, management station
- -- name, network manager's name, location, or phone
- -- number.
- -- In some cases the agent itself will be the owner of
- -- an entry. In these cases, this string shall be set
- -- to a string starting with 'monitor'.
- --
- -- SNMP access control is articulated entirely in terms
- -- of the contents of MIB views; access to a particular
- -- SNMP object instance depends only upon its presence
- -- or absence in a particular MIB view and never upon
- -- its value or the value of related object instances.
- -- Thus, objects of this type afford resolution of
- -- resource contention only among cooperating managers;
- -- they realize no access control function with respect
- -- to uncooperative parties.
- --
- -- By convention, objects with this syntax are declared as
- -- having
- --
- -- SIZE (0..127)
-
- EntryStatus ::= INTEGER
- { valid(1),
- createRequest(2),
- underCreation(3),
- invalid(4)
- }
- -- The status of a table entry.
- --
- -- Setting this object to the value invalid(4) has the
- -- effect of invalidating the corresponding entry.
- -- That is, it effectively disassociates the mapping
- -- identified with said entry.
- -- It is an implementation-specific matter as to whether
- -- the agent removes an invalidated entry from the table.
- -- Accordingly, management stations must be prepared to
- -- receive tabular information from agents that
- -- corresponds to entries currently not in use. Proper
- -- interpretation of such entries requires examination
- -- of the relevant EntryStatus object.
- --
- -- An existing instance of this object cannot be set to
- -- createRequest(2). This object may only be set to
- -- createRequest(2) when this instance is created. When
- -- this object is created, the agent may wish to create
- -- supplemental object instances with default values
- -- to complete a conceptual row in this table. Because
-
-
- -- the creation of these default objects is entirely at
- -- the option of the agent, the manager must not assume
- -- that any will be created, but may make use of any that
- -- are created. Immediately after completing the create
- -- operation, the agent must set this object to
- -- underCreation(3).
- --
- -- When in the underCreation(3) state, an entry is
- -- allowed to exist in a possibly incomplete, possibly
- -- inconsistent state, usually to allow it to be
- -- modified in mutiple PDUs. When in this state, an
- -- entry is not fully active. Entries shall exist in
- -- the underCreation(3) state until the management
- -- station is finished configuring the entry and sets
- -- this object to valid(1) or aborts, setting this
- -- object to invalid(4). If the agent determines that
- -- an entry has been in the underCreation(3) state for
- -- an abnormally long time, it may decide that the
- -- management station has crashed. If the agent makes
- -- this decision, it may set this object to invalid(4)
- -- to reclaim the entry. A prudent agent will
- -- understand that the management station may need to
- -- wait for human input and will allow for that
- -- possibility in its determination of this abnormally
- -- long period.
- --
- -- An entry in the valid(1) state is fully configured and
- -- consistent and fully represents the configuration or
- -- operation such a row is intended to represent. For
- -- example, it could be a statistical function that is
- -- configured and active, or a filter that is available
- -- in the list of filters processed by the packet capture
- -- process.
- --
- -- A manager is restricted to changing the state of an
- -- entry in the following ways:
- --
- -- create under
- -- To: valid Request Creation invalid
- -- From:
- -- valid OK NO OK OK
- -- createRequest N/A N/A N/A N/A
- -- underCreation OK NO OK OK
- -- invalid NO NO NO OK
- -- nonExistent NO OK NO OK
- --
- -- In the table above, it is not applicable to move the
- -- state from the createRequest state to any other
-
-
- -- state because the manager will never find the
- -- variable in that state. The nonExistent state is
- -- not a value of the enumeration, rather it means that
- -- the entryStatus variable does not exist at all.
- --
- -- An agent may allow an entryStatus variable to change
- -- state in additional ways, so long as the semantics
- -- of the states are followed. This allowance is made
- -- to ease the implementation of the agent and is made
- -- despite the fact that managers should never
- -- excercise these additional state transitions.
-
-
- statistics OBJECT IDENTIFIER ::= { rmon 1 }
- history OBJECT IDENTIFIER ::= { rmon 2 }
- alarm OBJECT IDENTIFIER ::= { rmon 3 }
- hosts OBJECT IDENTIFIER ::= { rmon 4 }
- hostTopN OBJECT IDENTIFIER ::= { rmon 5 }
- matrix OBJECT IDENTIFIER ::= { rmon 6 }
- filter OBJECT IDENTIFIER ::= { rmon 7 }
- capture OBJECT IDENTIFIER ::= { rmon 8 }
- event OBJECT IDENTIFIER ::= { rmon 9 }
-
-
- -- The Ethernet Statistics Group
- --
- -- Implementation of the Ethernet Statistics group is
- -- optional.
- --
- -- The ethernet statistics group contains statistics
- -- measured by the probe for each monitored interface on
- -- this device. These statistics take the form of free
- -- running counters that start from zero when a valid entry
- -- is created.
- --
- -- This group currently has statistics defined only for
- -- Ethernet interfaces. Each etherStatsEntry contains
- -- statistics for one Ethernet interface. The probe must
- -- create one etherStats entry for each monitored Ethernet
- -- interface on the device.
-
- etherStatsTable OBJECT-TYPE
- SYNTAX SEQUENCE OF EtherStatsEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of Ethernet statistics entries."
- ::= { statistics 1 }
-
-
- etherStatsEntry OBJECT-TYPE
- SYNTAX EtherStatsEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A collection of statistics kept for a particular
- Ethernet interface. As an example, an instance of the
- etherStatsPkts object might be named etherStatsPkts.1"
- INDEX { etherStatsIndex }
- ::= { etherStatsTable 1 }
-
- EtherStatsEntry ::= SEQUENCE {
- etherStatsIndex INTEGER (1..65535),
- etherStatsDataSource OBJECT IDENTIFIER,
- etherStatsDropEvents Counter,
- etherStatsOctets Counter,
- etherStatsPkts Counter,
- etherStatsBroadcastPkts Counter,
- etherStatsMulticastPkts Counter,
- etherStatsCRCAlignErrors Counter,
- etherStatsUndersizePkts Counter,
- etherStatsOversizePkts Counter,
- etherStatsFragments Counter,
- etherStatsJabbers Counter,
- etherStatsCollisions Counter,
- etherStatsPkts64Octets Counter,
- etherStatsPkts65to127Octets Counter,
- etherStatsPkts128to255Octets Counter,
- etherStatsPkts256to511Octets Counter,
- etherStatsPkts512to1023Octets Counter,
- etherStatsPkts1024to1518Octets Counter,
- etherStatsOwner OwnerString,
- etherStatsStatus EntryStatus
- }
-
- etherStatsIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of this object uniquely identifies this
- etherStats entry."
- ::= { etherStatsEntry 1 }
-
- etherStatsDataSource OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- ACCESS read-write
- STATUS mandatory
-
-
- DESCRIPTION
- "This object identifies the source of the data that
- this etherStats entry is configured to analyze. This
- source can be any ethernet interface on this device.
- In order to identify a particular interface, this
- object shall identify the instance of the ifIndex
- object, defined in RFC 1213 and RFC 1573 [4,6], for
- the desired interface. For example, if an entry
- were to receive data from interface #1, this object
- would be set to ifIndex.1.
-
- The statistics in this group reflect all packets
- on the local network segment attached to the
- identified interface.
-
- An agent may or may not be able to tell if
- fundamental changes to the media of the interface
- have occurred and necessitate an invalidation of
- this entry. For example, a hot-pluggable ethernet
- card could be pulled out and replaced by a
- token-ring card. In such a case, if the agent has
- such knowledge of the change, it is recommended that
- it invalidate this entry.
-
- This object may not be modified if the associated
- etherStatsStatus object is equal to valid(1)."
- ::= { etherStatsEntry 2 }
-
- etherStatsDropEvents OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of events in which packets
- were dropped by the probe due to lack of resources.
- Note that this number is not necessarily the number of
- packets dropped; it is just the number of times this
- condition has been detected."
- ::= { etherStatsEntry 3 }
-
- etherStatsOctets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of octets of data (including
- those in bad packets) received on the
- network (excluding framing bits but including
-
-
- FCS octets).
-
- This object can be used as a reasonable estimate of
- ethernet utilization. If greater precision is
- desired, the etherStatsPkts and etherStatsOctets
- objects should be sampled before and after a common
- interval. The differences in the sampled values are
- Pkts and Octets, respectively, and the number of
- seconds in the interval is Interval. These values
- are used to calculate the Utilization as follows:
-
- Pkts * (9.6 + 6.4) + (Octets * .8)
- Utilization = -------------------------------------
- Interval * 10,000
-
- The result of this equation is the value Utilization
- which is the percent utilization of the ethernet
- segment on a scale of 0 to 100 percent."
- ::= { etherStatsEntry 4 }
-
- etherStatsPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad packets,
- broadcast packets, and multicast packets) received."
- ::= { etherStatsEntry 5 }
-
- etherStatsBroadcastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of good packets received that were
- directed to the broadcast address. Note that this
- does not include multicast packets."
- ::= { etherStatsEntry 6 }
-
- etherStatsMulticastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of good packets received that were
- directed to a multicast address. Note that this
- number does not include packets directed to the
- broadcast address."
-
-
- ::= { etherStatsEntry 7 }
-
- etherStatsCRCAlignErrors OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets received that
- had a length (excluding framing bits, but
- including FCS octets) of between 64 and 1518
- octets, inclusive, but but had either a bad
- Frame Check Sequence (FCS) with an integral
- number of octets (FCS Error) or a bad FCS with
- a non-integral number of octets (Alignment Error)."
- ::= { etherStatsEntry 8 }
-
- etherStatsUndersizePkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets received that were
- less than 64 octets long (excluding framing bits,
- but including FCS octets) and were otherwise well
- formed."
- ::= { etherStatsEntry 9 }
-
- etherStatsOversizePkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets received that were
- longer than 1518 octets (excluding framing bits,
- but including FCS octets) and were otherwise
- well formed."
- ::= { etherStatsEntry 10 }
-
- etherStatsFragments OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets received that were less
- than 64 octets in length (excluding framing bits but
- including FCS octets) and had either a bad Frame
- Check Sequence (FCS) with an integral number of
- octets (FCS Error) or a bad FCS with a non-integral
-
-
- number of octets (Alignment Error).
-
- Note that it is entirely normal for
- etherStatsFragments to increment. This is because
- it counts both runts (which are normal occurrences
- due to collisions) and noise hits."
- ::= { etherStatsEntry 11 }
-
- etherStatsJabbers OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets received that were
- longer than 1518 octets (excluding framing bits,
- but including FCS octets), and had either a bad
- Frame Check Sequence (FCS) with an integral number
- of octets (FCS Error) or a bad FCS with a
- non-integral number of octets (Alignment Error).
-
- Note that this definition of jabber is different
- than the definition in IEEE-802.3 section 8.2.1.5
- (10BASE5) and section 10.3.1.4 (10BASE2). These
- documents define jabber as the condition where any
- packet exceeds 20 ms. The allowed range to detect
- jabber is between 20 ms and 150 ms."
- ::= { etherStatsEntry 12 }
-
- etherStatsCollisions OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The best estimate of the total number of collisions
- on this Ethernet segment.
-
- The value returned will depend on the location of
- the RMON probe. Section 8.2.1.3 (10BASE-5) and
- section 10.3.1.3 (10BASE-2) of IEEE standard 802.3
- states that a station must detect a collision, in
- the receive mode, if three or more stations are
- transmitting simultaneously. A repeater port must
- detect a collision when two or more stations are
- transmitting simultaneously. Thus a probe placed on
- a repeater port could record more collisions than a
- probe connected to a station on the same segment
- would.
-
-
-
- Probe location plays a much smaller role when
- considering 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE
- standard 802.3 defines a collision as the
- simultaneous presence of signals on the DO and RD
- circuits (transmitting and receiving at the same
- time). A 10BASE-T station can only detect
- collisions when it is transmitting. Thus probes
- placed on a station and a repeater, should report
- the same number of collisions.
-
- Note also that an RMON probe inside a repeater
- should ideally report collisions between the
- repeater and one or more other hosts (transmit
- collisions as defined by IEEE 802.3k) plus receiver
- collisions observed on any coax segments to which
- the repeater is connected."
- ::= { etherStatsEntry 13 }
-
- etherStatsPkts64Octets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad
- packets) received that were 64 octets in length
- (excluding framing bits but including FCS octets)."
- ::= { etherStatsEntry 14 }
-
- etherStatsPkts65to127Octets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad
- packets) received that were between
- 65 and 127 octets in length inclusive
- (excluding framing bits but including FCS octets)."
- ::= { etherStatsEntry 15 }
-
- etherStatsPkts128to255Octets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad
- packets) received that were between
- 128 and 255 octets in length inclusive
- (excluding framing bits but including FCS octets)."
-
-
- ::= { etherStatsEntry 16 }
-
- etherStatsPkts256to511Octets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad
- packets) received that were between
- 256 and 511 octets in length inclusive
- (excluding framing bits but including FCS octets)."
- ::= { etherStatsEntry 17 }
-
- etherStatsPkts512to1023Octets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad
- packets) received that were between
- 512 and 1023 octets in length inclusive
- (excluding framing bits but including FCS octets)."
- ::= { etherStatsEntry 18 }
-
- etherStatsPkts1024to1518Octets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets (including bad
- packets) received that were between
- 1024 and 1518 octets in length inclusive
- (excluding framing bits but including FCS octets)."
- ::= { etherStatsEntry 19 }
-
- etherStatsOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { etherStatsEntry 20 }
-
- etherStatsStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
-
-
- DESCRIPTION
- "The status of this etherStats entry."
- ::= { etherStatsEntry 21 }
-
-
- -- The History Control Group
-
- -- Implementation of the History Control group is optional.
- --
- -- The history control group controls the periodic statistical
- -- sampling of data from various types of networks. The
- -- historyControlTable stores configuration entries that each
- -- define an interface, polling period, and other parameters.
- -- Once samples are taken, their data is stored in an entry
- -- in a media-specific table. Each such entry defines one
- -- sample, and is associated with the historyControlEntry that
- -- caused the sample to be taken. Each counter in the
- -- etherHistoryEntry counts the same event as its
- -- similarly-named counterpart in the etherStatsEntry,
- -- except that each value here is a cumulative sum during a
- -- sampling period.
- --
- -- If the probe keeps track of the time of day, it should
- -- start the first sample of the history at a time such that
- -- when the next hour of the day begins, a sample is
- -- started at that instant. This tends to make more
- -- user-friendly reports, and enables comparison of reports
- -- from different probes that have relatively accurate time
- -- of day.
- --
- -- The probe is encouraged to add two history control entries
- -- per monitored interface upon initialization that describe
- -- a short term and a long term polling period. Suggested
- -- parameters are 30 seconds for the short term polling period
- -- and 30 minutes for the long term period.
-
- historyControlTable OBJECT-TYPE
- SYNTAX SEQUENCE OF HistoryControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of history control entries."
- ::= { history 1 }
-
- historyControlEntry OBJECT-TYPE
- SYNTAX HistoryControlEntry
- ACCESS not-accessible
- STATUS mandatory
-
-
- DESCRIPTION
- "A list of parameters that set up a periodic sampling
- of statistics. As an example, an instance of the
- historyControlInterval object might be named
- historyControlInterval.2"
- INDEX { historyControlIndex }
- ::= { historyControlTable 1 }
-
- HistoryControlEntry ::= SEQUENCE {
- historyControlIndex INTEGER (1..65535),
- historyControlDataSource OBJECT IDENTIFIER,
- historyControlBucketsRequested INTEGER (1..65535),
- historyControlBucketsGranted INTEGER (1..65535),
- historyControlInterval INTEGER (1..3600),
- historyControlOwner OwnerString,
- historyControlStatus EntryStatus
- }
-
- historyControlIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in the
- historyControl table. Each such entry defines a
- set of samples at a particular interval for an
- interface on the device."
- ::= { historyControlEntry 1 }
-
- historyControlDataSource OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "This object identifies the source of the data for
- which historical data was collected and
- placed in a media-specific table on behalf of this
- historyControlEntry. This source can be any
- interface on this device. In order to identify
- a particular interface, this object shall identify
- the instance of the ifIndex object, defined
- in RFC 1213 and RFC 1573 [4,6], for the desired
- interface. For example, if an entry were to receive
- data from interface #1, this object would be set
- to ifIndex.1.
-
- The statistics in this group reflect all packets
- on the local network segment attached to the
-
-
- identified interface.
-
- An agent may or may not be able to tell if fundamental
- changes to the media of the interface have occurred
- and necessitate an invalidation of this entry. For
- example, a hot-pluggable ethernet card could be
- pulled out and replaced by a token-ring card. In
- such a case, if the agent has such knowledge of the
- change, it is recommended that it invalidate this
- entry.
-
- This object may not be modified if the associated
- historyControlStatus object is equal to valid(1)."
- ::= { historyControlEntry 2 }
-
- historyControlBucketsRequested OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The requested number of discrete time intervals
- over which data is to be saved in the part of the
- media-specific table associated with this
- historyControlEntry.
-
- When this object is created or modified, the probe
- should set historyControlBucketsGranted as closely to
- this object as is possible for the particular probe
- implementation and available resources."
- DEFVAL { 50 }
- ::= { historyControlEntry 3 }
-
- historyControlBucketsGranted OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of discrete sampling intervals
- over which data shall be saved in the part of
- the media-specific table associated with this
- historyControlEntry.
-
- When the associated historyControlBucketsRequested
- object is created or modified, the probe
- should set this object as closely to the requested
- value as is possible for the particular
- probe implementation and available resources. The
- probe must not lower this value except as a result
-
-
- of a modification to the associated
- historyControlBucketsRequested object.
-
- There will be times when the actual number of
- buckets associated with this entry is less than
- the value of this object. In this case, at the
- end of each sampling interval, a new bucket will
- be added to the media-specific table.
-
- When the number of buckets reaches the value of
- this object and a new bucket is to be added to the
- media-specific table, the oldest bucket associated
- with this historyControlEntry shall be deleted by
- the agent so that the new bucket can be added.
-
- When the value of this object changes to a value less
- than the current value, entries are deleted
- from the media-specific table associated with this
- historyControlEntry. Enough of the oldest of these
- entries shall be deleted by the agent so that their
- number remains less than or equal to the new value of
- this object.
-
- When the value of this object changes to a value
- greater than the current value, the number of
- associated media- specific entries may be allowed to
- grow."
- ::= { historyControlEntry 4 }
-
- historyControlInterval OBJECT-TYPE
- SYNTAX INTEGER (1..3600)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The interval in seconds over which the data is
- sampled for each bucket in the part of the
- media-specific table associated with this
- historyControlEntry. This interval can
- be set to any number of seconds between 1 and
- 3600 (1 hour).
-
- Because the counters in a bucket may overflow at their
- maximum value with no indication, a prudent manager
- will take into account the possibility of overflow
- in any of the associated counters. It is important
- to consider the minimum time in which any counter
- could overflow on a particular media type and set
- the historyControlInterval object to a value less
-
-
- than this interval. This is typically most
- important for the 'octets' counter in any
- media-specific table. For example, on an Ethernet
- network, the etherHistoryOctets counter could
- overflow in about one hour at the Ethernet's maximum
- utilization.
-
- This object may not be modified if the associated
- historyControlStatus object is equal to valid(1)."
- DEFVAL { 1800 }
- ::= { historyControlEntry 5 }
-
- historyControlOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { historyControlEntry 6 }
-
- historyControlStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this historyControl entry.
-
- Each instance of the media-specific table associated
- with this historyControlEntry will be deleted by the
- agent if this historyControlEntry is not equal to
- valid(1)."
- ::= { historyControlEntry 7 }
-
-
- -- The Ethernet History Group
-
- -- Implementation of the Ethernet History group is optional.
- --
- -- The Ethernet History group records periodic
- -- statistical samples from a network and stores them
- -- for later retrieval. Once samples are taken, their
- -- data is stored in an entry in a media-specific
- -- table. Each such entry defines one sample, and is
- -- associated with the historyControlEntry that caused
- -- the sample to be taken. This group defines the
- -- etherHistoryTable, for Ethernet networks.
- --
-
-
- etherHistoryTable OBJECT-TYPE
- SYNTAX SEQUENCE OF EtherHistoryEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of Ethernet history entries."
- ::= { history 2 }
-
- etherHistoryEntry OBJECT-TYPE
- SYNTAX EtherHistoryEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "An historical sample of Ethernet statistics on a
- particular Ethernet interface. This sample is
- associated with the historyControlEntry which set up
- the parameters for a regular collection of these
- samples. As an example, an instance of the
- etherHistoryPkts object might be named
- etherHistoryPkts.2.89"
- INDEX { etherHistoryIndex , etherHistorySampleIndex }
- ::= { etherHistoryTable 1 }
-
- EtherHistoryEntry ::= SEQUENCE {
- etherHistoryIndex INTEGER (1..65535),
- etherHistorySampleIndex INTEGER (1..2147483647),
- etherHistoryIntervalStart TimeTicks,
- etherHistoryDropEvents Counter,
- etherHistoryOctets Counter,
- etherHistoryPkts Counter,
- etherHistoryBroadcastPkts Counter,
- etherHistoryMulticastPkts Counter,
- etherHistoryCRCAlignErrors Counter,
- etherHistoryUndersizePkts Counter,
- etherHistoryOversizePkts Counter,
- etherHistoryFragments Counter,
- etherHistoryJabbers Counter,
- etherHistoryCollisions Counter,
- etherHistoryUtilization INTEGER (0..10000)
- }
-
- etherHistoryIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The history of which this entry is a part. The
- history identified by a particular value of this
-
-
- index is the same history as identified
- by the same value of historyControlIndex."
- ::= { etherHistoryEntry 1 }
-
- etherHistorySampleIndex OBJECT-TYPE
- SYNTAX INTEGER (1..2147483647)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies the particular
- sample this entry represents among all samples
- associated with the same historyControlEntry.
- This index starts at 1 and increases by one
- as each new sample is taken."
- ::= { etherHistoryEntry 2 }
-
- etherHistoryIntervalStart OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime at the start of the interval
- over which this sample was measured. If the probe
- keeps track of the time of day, it should start
- the first sample of the history at a time such that
- when the next hour of the day begins, a sample is
- started at that instant. Note that following this
- rule may require the probe to delay collecting the
- first sample of the history, as each sample must be
- of the same interval. Also note that the sample which
- is currently being collected is not accessible in this
- table until the end of its interval."
- ::= { etherHistoryEntry 3 }
-
- etherHistoryDropEvents OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of events in which packets
- were dropped by the probe due to lack of resources
- during this sampling interval. Note that this number
- is not necessarily the number of packets dropped, it
- is just the number of times this condition has been
- detected."
- ::= { etherHistoryEntry 4 }
-
- etherHistoryOctets OBJECT-TYPE
-
-
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of octets of data (including
- those in bad packets) received on the
- network (excluding framing bits but including
- FCS octets)."
- ::= { etherHistoryEntry 5 }
-
- etherHistoryPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets (including bad packets)
- received during this sampling interval."
- ::= { etherHistoryEntry 6 }
-
- etherHistoryBroadcastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets received during this
- sampling interval that were directed to the
- broadcast address."
- ::= { etherHistoryEntry 7 }
-
- etherHistoryMulticastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets received during this
- sampling interval that were directed to a
- multicast address. Note that this number does not
- include packets addressed to the broadcast address."
- ::= { etherHistoryEntry 8 }
-
- etherHistoryCRCAlignErrors OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets received during this sampling
- interval that had a length (excluding framing bits
- but including FCS octets) between 64 and 1518
-
-
- octets, inclusive, but had either a bad Frame Check
- Sequence (FCS) with an integral number of octets
- (FCS Error) or a bad FCS with a non-integral number
- of octets (Alignment Error)."
- ::= { etherHistoryEntry 9 }
-
- etherHistoryUndersizePkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets received during this
- sampling interval that were less than 64 octets
- long (excluding framing bits but including FCS
- octets) and were otherwise well formed."
- ::= { etherHistoryEntry 10 }
-
- etherHistoryOversizePkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets received during this
- sampling interval that were longer than 1518
- octets (excluding framing bits but including
- FCS octets) but were otherwise well formed."
- ::= { etherHistoryEntry 11 }
-
- etherHistoryFragments OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The total number of packets received during this
- sampling interval that were less than 64 octets in
- length (excluding framing bits but including FCS
- octets) had either a bad Frame Check Sequence (FCS)
- with an integral number of octets (FCS Error) or a bad
- FCS with a non-integral number of octets (Alignment
- Error).
-
- Note that it is entirely normal for
- etherHistoryFragments to increment. This is because
- it counts both runts (which are normal occurrences
- due to collisions) and noise hits."
- ::= { etherHistoryEntry 12 }
-
- etherHistoryJabbers OBJECT-TYPE
-
-
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets received during this
- sampling interval that were longer than 1518 octets
- (excluding framing bits but including FCS octets),
- and had either a bad Frame Check Sequence (FCS)
- with an integral number of octets (FCS Error) or
- a bad FCS with a non-integral number of octets
- (Alignment Error).
-
- Note that this definition of jabber is different
- than the definition in IEEE-802.3 section 8.2.1.5
- (10BASE5) and section 10.3.1.4 (10BASE2). These
- documents define jabber as the condition where any
- packet exceeds 20 ms. The allowed range to detect
- jabber is between 20 ms and 150 ms."
- ::= { etherHistoryEntry 13 }
-
- etherHistoryCollisions OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The best estimate of the total number of collisions
- on this Ethernet segment during this sampling
- interval.
-
- The value returned will depend on the location of
- the RMON probe. Section 8.2.1.3 (10BASE-5) and
- section 10.3.1.3 (10BASE-2) of IEEE standard 802.3
- states that a station must detect a collision, in
- the receive mode, if three or more stations are
- transmitting simultaneously. A repeater port must
- detect a collision when two or more stations are
- transmitting simultaneously. Thus a probe placed on
- a repeater port could record more collisions than a
- probe connected to a station on the same segment
- would.
-
- Probe location plays a much smaller role when
- considering 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE
- standard 802.3 defines a collision as the
- simultaneous presence of signals on the DO and RD
- circuits (transmitting and receiving at the same
- time). A 10BASE-T station can only detect
- collisions when it is transmitting. Thus probes
-
-
- placed on a station and a repeater, should report
- the same number of collisions.
-
- Note also that an RMON probe inside a repeater
- should ideally report collisions between the
- repeater and one or more other hosts (transmit
- collisions as defined by IEEE 802.3k) plus receiver
- collisions observed on any coax segments to which
- the repeater is connected."
- ::= { etherHistoryEntry 14 }
-
- etherHistoryUtilization OBJECT-TYPE
- SYNTAX INTEGER (0..10000)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The best estimate of the mean physical layer
- network utilization on this interface during this
- sampling interval, in hundredths of a percent."
- ::= { etherHistoryEntry 15 }
-
-
- -- The Alarm Group
-
- -- Implementation of the Alarm group is optional.
- --
- -- The Alarm Group requires the implementation of the Event
- -- group.
- --
- -- The Alarm group periodically takes
- -- statistical samples from variables in the probe and
- -- compares them to thresholds that have been
- -- configured. The alarm table stores configuration
- -- entries that each define a variable, polling period,
- -- and threshold parameters. If a sample is found to
- -- cross the threshold values, an event is generated.
- -- Only variables that resolve to an ASN.1 primitive
- -- type of INTEGER (INTEGER, Counter, Gauge, or
- -- TimeTicks) may be monitored in this way.
- --
- -- This function has a hysteresis mechanism to limit
- -- the generation of events. This mechanism generates
- -- one event as a threshold is crossed in the
- -- appropriate direction. No more events are generated
- -- for that threshold until the opposite threshold is
- -- crossed.
- --
- -- In the case of a sampling a deltaValue, a probe may
-
-
- -- implement this mechanism with more precision if it
- -- takes a delta sample twice per period, each time
- -- comparing the sum of the latest two samples to the
- -- threshold. This allows the detection of threshold
- -- crossings that span the sampling boundary. Note
- -- that this does not require any special configuration
- -- of the threshold value. It is suggested that probes
- -- implement this more precise algorithm.
-
- alarmTable OBJECT-TYPE
- SYNTAX SEQUENCE OF AlarmEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of alarm entries."
- ::= { alarm 1 }
-
- alarmEntry OBJECT-TYPE
- SYNTAX AlarmEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of parameters that set up a periodic checking
- for alarm conditions. For example, an instance of the
- alarmValue object might be named alarmValue.8"
- INDEX { alarmIndex }
- ::= { alarmTable 1 }
-
- AlarmEntry ::= SEQUENCE {
- alarmIndex INTEGER (1..65535),
- alarmInterval INTEGER,
- alarmVariable OBJECT IDENTIFIER,
- alarmSampleType INTEGER,
- alarmValue INTEGER,
- alarmStartupAlarm INTEGER,
- alarmRisingThreshold INTEGER,
- alarmFallingThreshold INTEGER,
- alarmRisingEventIndex INTEGER (0..65535),
- alarmFallingEventIndex INTEGER (0..65535),
- alarmOwner OwnerString,
- alarmStatus EntryStatus
- }
-
- alarmIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
-
-
- "An index that uniquely identifies an entry in the
- alarm table. Each such entry defines a
- diagnostic sample at a particular interval
- for an object on the device."
- ::= { alarmEntry 1 }
-
- alarmInterval OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The interval in seconds over which the data is
- sampled and compared with the rising and falling
- thresholds. When setting this variable, care
- should be taken in the case of deltaValue
- sampling - the interval should be set short enough
- that the sampled variable is very unlikely to
- increase or decrease by more than 2^31 - 1 during
- a single sampling interval.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 2 }
-
- alarmVariable OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The object identifier of the particular variable to
- be sampled. Only variables that resolve to an ASN.1
- primitive type of INTEGER (INTEGER, Counter, Gauge,
- or TimeTicks) may be sampled.
-
- Because SNMP access control is articulated entirely
- in terms of the contents of MIB views, no access
- control mechanism exists that can restrict the value
- of this object to identify only those objects that
- exist in a particular MIB view. Because there is
- thus no acceptable means of restricting the read
- access that could be obtained through the alarm
- mechanism, the probe must only grant write access to
- this object in those views that have read access to
- all objects on the probe.
-
- During a set operation, if the supplied variable
- name is not available in the selected MIB view, a
- badValue error must be returned. If at any time the
-
-
- variable name of an established alarmEntry is no
- longer available in the selected MIB view, the probe
- must change the status of this alarmEntry to
- invalid(4).
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 3 }
-
- alarmSampleType OBJECT-TYPE
- SYNTAX INTEGER {
- absoluteValue(1),
- deltaValue(2)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The method of sampling the selected variable and
- calculating the value to be compared against the
- thresholds. If the value of this object is
- absoluteValue(1), the value of the selected variable
- will be compared directly with the thresholds at the
- end of the sampling interval. If the value of this
- object is deltaValue(2), the value of the selected
- variable at the last sample will be subtracted from
- the current value, and the difference compared with
- the thresholds.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 4 }
-
- alarmValue OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of the statistic during the last sampling
- period. For example, if the sample type is
- deltaValue, this value will be the difference
- between the samples at the beginning and end of the
- period. If the sample type is absoluteValue, this
- value will be the sampled value at the end of the
- period.
-
- This is the value that is compared with the rising and
- falling thresholds.
-
-
-
- The value during the current sampling period is not
- made available until the period is completed and will
- remain available until the next period completes."
- ::= { alarmEntry 5 }
-
- alarmStartupAlarm OBJECT-TYPE
- SYNTAX INTEGER {
- risingAlarm(1),
- fallingAlarm(2),
- risingOrFallingAlarm(3)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The alarm that may be sent when this entry is first
- set to valid. If the first sample after this entry
- becomes valid is greater than or equal to the
- risingThreshold and alarmStartupAlarm is equal to
- risingAlarm(1) or risingOrFallingAlarm(3), then a
- single rising alarm will be generated. If the first
- sample after this entry becomes valid is less than
- or equal to the fallingThreshold and
- alarmStartupAlarm is equal to fallingAlarm(2) or
- risingOrFallingAlarm(3), then a single falling alarm
- will be generated.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 6 }
-
- alarmRisingThreshold OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "A threshold for the sampled statistic. When the
- current sampled value is greater than or equal to
- this threshold, and the value at the last sampling
- interval was less than this threshold, a single
- event will be generated. A single event will also
- be generated if the first sample after this entry
- becomes valid is greater than or equal to this
- threshold and the associated alarmStartupAlarm is
- equal to risingAlarm(1) or risingOrFallingAlarm(3).
-
- After a rising event is generated, another such event
- will not be generated until the sampled value
- falls below this threshold and reaches the
-
-
- alarmFallingThreshold.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 7 }
-
- alarmFallingThreshold OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "A threshold for the sampled statistic. When the
- current sampled value is less than or equal to this
- threshold, and the value at the last sampling
- interval was greater than this threshold, a single
- event will be generated. A single event will also
- be generated if the first sample after this entry
- becomes valid is less than or equal to this
- threshold and the associated alarmStartupAlarm is
- equal to fallingAlarm(2) or risingOrFallingAlarm(3).
-
- After a falling event is generated, another such event
- will not be generated until the sampled value
- rises above this threshold and reaches the
- alarmRisingThreshold.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 8 }
-
- alarmRisingEventIndex OBJECT-TYPE
- SYNTAX INTEGER (0..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The index of the eventEntry that is
- used when a rising threshold is crossed. The
- eventEntry identified by a particular value of
- this index is the same as identified by the same value
- of the eventIndex object. If there is no
- corresponding entry in the eventTable, then
- no association exists. In particular, if this value
- is zero, no associated event will be generated, as
- zero is not a valid event index.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 9 }
-
-
- alarmFallingEventIndex OBJECT-TYPE
- SYNTAX INTEGER (0..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The index of the eventEntry that is
- used when a falling threshold is crossed. The
- eventEntry identified by a particular value of
- this index is the same as identified by the same value
- of the eventIndex object. If there is no
- corresponding entry in the eventTable, then
- no association exists. In particular, if this value
- is zero, no associated event will be generated, as
- zero is not a valid event index.
-
- This object may not be modified if the associated
- alarmStatus object is equal to valid(1)."
- ::= { alarmEntry 10 }
-
- alarmOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { alarmEntry 11 }
-
- alarmStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this alarm entry."
- ::= { alarmEntry 12 }
-
-
- -- The Host Group
-
- -- Implementation of the Host group is optional.
- --
- -- The host group discovers new hosts on the network by
- -- keeping a list of source and destination MAC Addresses seen
- -- in good packets. For each of these addresses, the host
- -- group keeps a set of statistics. The hostControlTable
- -- controls which interfaces this function is performed on,
- -- and contains some information about the process. On
- -- behalf of each hostControlEntry, data is collected on an
-
-
- -- interface and placed in both the hostTable and the
- -- hostTimeTable. If the monitoring device finds itself
- -- short of resources, it may delete entries as needed. It
- -- is suggested that the device delete the least recently
- -- used entries first.
-
- -- The hostTable contains entries for each address
- -- discovered on a particular interface. Each entry
- -- contains statistical data about that host. This table is
- -- indexed by the MAC address of the host, through which a
- -- random access may be achieved.
-
- -- The hostTimeTable contains data in the same format as the
- -- hostTable, and must contain the same set of hosts, but is
- -- indexed using hostTimeCreationOrder rather than
- -- hostAddress.
- -- The hostTimeCreationOrder is an integer which reflects
- -- the relative order in which a particular entry was
- -- discovered and thus inserted into the table. As this
- -- order, and thus the index, is among those entries
- -- currently in the table, the index for a particular entry
- -- may change if an (earlier) entry is deleted. Thus the
- -- association between hostTimeCreationOrder and
- -- hostTimeEntry may be broken at any time.
-
- -- The hostTimeTable has two important uses. The first is the
- -- fast download of this potentially large table. Because the
- -- index of this table runs from 1 to the size of the table,
- -- inclusive, its values are predictable. This allows very
- -- efficient packing of variables into SNMP PDU's and allows
- -- a table transfer to have multiple packets outstanding.
- -- These benefits increase transfer rates tremendously.
-
- -- The second use of the hostTimeTable is the efficient
- -- discovery by the management station of new entries added
- -- to the table. After the management station has downloaded
- -- the entire table, it knows that new entries will be added
- -- immediately after the end of the current table. It can
- -- thus detect new entries there and retrieve them easily.
-
- -- Because the association between hostTimeCreationOrder and
- -- hostTimeEntry may be broken at any time, the management
- -- station must monitor the related hostControlLastDeleteTime
- -- object. When the management station thus detects a
- -- deletion, it must assume that any such associations have
- --- been broken, and invalidate any it has stored locally.
- -- This includes restarting any download of the
- -- hostTimeTable that may have been in progress, as well as
-
-
- -- rediscovering the end of the hostTimeTable so that it may
- -- detect new entries. If the management station does not
- -- detect the broken association, it may continue to refer
- -- to a particular host by its creationOrder while
- -- unwittingly retrieving the data associated with another
- -- host entirely. If this happens while downloading the
- -- host table, the management station may fail to download
- -- all of the entries in the table.
-
- hostControlTable OBJECT-TYPE
- SYNTAX SEQUENCE OF HostControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of host table control entries."
- ::= { hosts 1 }
-
- hostControlEntry OBJECT-TYPE
- SYNTAX HostControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of parameters that set up the discovery of
- hosts on a particular interface and the collection
- of statistics about these hosts. For example, an
- instance of the hostControlTableSize object might be
- named hostControlTableSize.1"
- INDEX { hostControlIndex }
- ::= { hostControlTable 1 }
-
- HostControlEntry ::= SEQUENCE {
- hostControlIndex INTEGER (1..65535),
- hostControlDataSource OBJECT IDENTIFIER,
- hostControlTableSize INTEGER,
- hostControlLastDeleteTime TimeTicks,
- hostControlOwner OwnerString,
- hostControlStatus EntryStatus
- }
-
- hostControlIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in the
- hostControl table. Each such entry defines
- a function that discovers hosts on a particular
- interface and places statistics about them in the
-
-
- hostTable and the hostTimeTable on behalf of this
- hostControlEntry."
- ::= { hostControlEntry 1 }
-
- hostControlDataSource OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "This object identifies the source of the data for
- this instance of the host function. This source
- can be any interface on this device. In order
- to identify a particular interface, this object shall
- identify the instance of the ifIndex object, defined
- in RFC 1213 and RFC 1573 [4,6], for the desired
- interface. For example, if an entry were to receive
- data from interface #1, this object would be set to
- ifIndex.1.
-
- The statistics in this group reflect all packets
- on the local network segment attached to the
- identified interface.
-
- An agent may or may not be able to tell if
- fundamental changes to the media of the interface
- have occurred and necessitate an invalidation of
- this entry. For example, a hot-pluggable ethernet
- card could be pulled out and replaced by a
- token-ring card. In such a case, if the agent has
- such knowledge of the change, it is recommended that
- it invalidate this entry.
-
- This object may not be modified if the associated
- hostControlStatus object is equal to valid(1)."
- ::= { hostControlEntry 2 }
-
- hostControlTableSize OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of hostEntries in the hostTable and the
- hostTimeTable associated with this hostControlEntry."
- ::= { hostControlEntry 3 }
-
- hostControlLastDeleteTime OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
-
-
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime when the last entry
- was deleted from the portion of the hostTable
- associated with this hostControlEntry. If no
- deletions have occurred, this value shall be zero."
- ::= { hostControlEntry 4 }
-
- hostControlOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { hostControlEntry 5 }
-
- hostControlStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this hostControl entry.
-
- If this object is not equal to valid(1), all
- associated entries in the hostTable, hostTimeTable,
- and the hostTopNTable shall be deleted by the
- agent."
- ::= { hostControlEntry 6 }
-
- hostTable OBJECT-TYPE
- SYNTAX SEQUENCE OF HostEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of host entries."
- ::= { hosts 2 }
-
- hostEntry OBJECT-TYPE
- SYNTAX HostEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A collection of statistics for a particular host
- that has been discovered on an interface of this
- device. For example, an instance of the
- hostOutBroadcastPkts object might be named
- hostOutBroadcastPkts.1.6.8.0.32.27.3.176"
-
-
- INDEX { hostIndex, hostAddress }
- ::= { hostTable 1 }
-
- HostEntry ::= SEQUENCE {
- hostAddress OCTET STRING,
- hostCreationOrder INTEGER (1..65535),
- hostIndex INTEGER (1..65535),
- hostInPkts Counter,
- hostOutPkts Counter,
- hostInOctets Counter,
- hostOutOctets Counter,
- hostOutErrors Counter,
- hostOutBroadcastPkts Counter,
- hostOutMulticastPkts Counter
- }
-
- hostAddress OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The physical address of this host."
- ::= { hostEntry 1 }
-
- hostCreationOrder OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that defines the relative ordering of
- the creation time of hosts captured for a
- particular hostControlEntry. This index shall
- be between 1 and N, where N is the value of
- the associated hostControlTableSize. The ordering
- of the indexes is based on the order of each entry's
- insertion into the table, in which entries added
- earlier have a lower index value than entries added
- later.
-
- It is important to note that the order for a
- particular entry may change as an (earlier) entry
- is deleted from the table. Because this order may
- change, management stations should make use of the
- hostControlLastDeleteTime variable in the
- hostControlEntry associated with the relevant
- portion of the hostTable. By observing
- this variable, the management station may detect
- the circumstances where a previous association
-
-
- between a value of hostCreationOrder
- and a hostEntry may no longer hold."
- ::= { hostEntry 2 }
-
- hostIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The set of collected host statistics of which
- this entry is a part. The set of hosts
- identified by a particular value of this
- index is associated with the hostControlEntry
- as identified by the same value of hostControlIndex."
- ::= { hostEntry 3 }
-
- hostInPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets transmitted to this
- address since it was added to the hostTable."
- ::= { hostEntry 4 }
-
- hostOutPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets, including bad packets,
- transmitted by this address since it was added
- to the hostTable."
- ::= { hostEntry 5 }
-
- hostInOctets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of octets transmitted to this address
- since it was added to the hostTable (excluding
- framing bits but including FCS octets), except for
- those octets in bad packets."
- ::= { hostEntry 6 }
-
- hostOutOctets OBJECT-TYPE
- SYNTAX Counter
-
-
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of octets transmitted by this address
- since it was added to the hostTable (excluding
- framing bits but including FCS octets), including
- those octets in bad packets."
- ::= { hostEntry 7 }
-
- hostOutErrors OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of bad packets transmitted by this address
- since this host was added to the hostTable."
- ::= { hostEntry 8 }
-
- hostOutBroadcastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets transmitted by this
- address that were directed to the broadcast address
- since this host was added to the hostTable."
- ::= { hostEntry 9 }
-
- hostOutMulticastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets transmitted by this
- address that were directed to a multicast address
- since this host was added to the hostTable.
- Note that this number does not include packets
- directed to the broadcast address."
- ::= { hostEntry 10 }
-
- -- host Time Table
-
- hostTimeTable OBJECT-TYPE
- SYNTAX SEQUENCE OF HostTimeEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of time-ordered host table entries."
-
-
- ::= { hosts 3 }
-
- hostTimeEntry OBJECT-TYPE
- SYNTAX HostTimeEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A collection of statistics for a particular host
- that has been discovered on an interface of this
- device. This collection includes the relative
- ordering of the creation time of this object. For
- example, an instance of the hostTimeOutBroadcastPkts
- object might be named
- hostTimeOutBroadcastPkts.1.687"
- INDEX { hostTimeIndex, hostTimeCreationOrder }
- ::= { hostTimeTable 1 }
-
- HostTimeEntry ::= SEQUENCE {
- hostTimeAddress OCTET STRING,
- hostTimeCreationOrder INTEGER (1..65535),
- hostTimeIndex INTEGER (1..65535),
- hostTimeInPkts Counter,
- hostTimeOutPkts Counter,
- hostTimeInOctets Counter,
- hostTimeOutOctets Counter,
- hostTimeOutErrors Counter,
- hostTimeOutBroadcastPkts Counter,
- hostTimeOutMulticastPkts Counter
- }
-
- hostTimeAddress OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The physical address of this host."
- ::= { hostTimeEntry 1 }
-
- hostTimeCreationOrder OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in
- the hostTime table among those entries associated
- with the same hostControlEntry. This index shall
- be between 1 and N, where N is the value of
- the associated hostControlTableSize. The ordering
-
-
- of the indexes is based on the order of each entry's
- insertion into the table, in which entries added
- earlier have a lower index value than entries added
- later. Thus the management station has the ability to
- learn of new entries added to this table without
- downloading the entire table.
-
- It is important to note that the index for a
- particular entry may change as an (earlier) entry
- is deleted from the table. Because this order may
- change, management stations should make use of the
- hostControlLastDeleteTime variable in the
- hostControlEntry associated with the relevant
- portion of the hostTimeTable. By observing
- this variable, the management station may detect
- the circumstances where a download of the table
- may have missed entries, and where a previous
- association between a value of hostTimeCreationOrder
- and a hostTimeEntry may no longer hold."
- ::= { hostTimeEntry 2 }
-
- hostTimeIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The set of collected host statistics of which
- this entry is a part. The set of hosts
- identified by a particular value of this
- index is associated with the hostControlEntry
- as identified by the same value of hostControlIndex."
- ::= { hostTimeEntry 3 }
-
- hostTimeInPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets transmitted to this
- address since it was added to the hostTimeTable."
- ::= { hostTimeEntry 4 }
-
- hostTimeOutPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of god packets transmitted by this
-
-
- address since it was added to the hostTimeTable."
- ::= { hostTimeEntry 5 }
-
- hostTimeInOctets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of octets transmitted to this address
- since it was added to the hostTimeTable (excluding
- framing bits but including FCS octets), except for
- those octets in bad packets."
- ::= { hostTimeEntry 6 }
-
- hostTimeOutOctets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of octets transmitted by this address
- since it was added to the hostTimeTable (excluding
- framing bits but including FCS octets), including
- those octets in bad packets."
- ::= { hostTimeEntry 7 }
-
- hostTimeOutErrors OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of bad packets transmitted by this address
- since this host was added to the hostTimeTable."
- ::= { hostTimeEntry 8 }
-
- hostTimeOutBroadcastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of good packets transmitted by this
- address that were directed to the broadcast address
- since this host was added to the hostTimeTable."
- ::= { hostTimeEntry 9 }
-
- hostTimeOutMulticastPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
-
-
- DESCRIPTION
- "The number of good packets transmitted by this
- address that were directed to a multicast address
- since this host was added to the hostTimeTable.
- Note that this number does not include packets
- directed to the broadcast address."
- ::= { hostTimeEntry 10 }
-
-
- -- The Host Top "N" Group
-
- -- Implementation of the Host Top N group is optional.
- --
- -- The Host Top N group requires the implementation of the
- -- host group.
- --
- -- The Host Top N group is used to prepare reports that
- -- describe the hosts that top a list ordered by one of
- -- their statistics.
- -- The available statistics are samples of one of their
- -- base statistics, over an interval specified by the
- -- management station. Thus, these statistics are rate
- -- based. The management station also selects how many such
- -- hosts are reported.
-
- -- The hostTopNControlTable is used to initiate the
- -- generation of such a report. The management station
- -- may select the parameters of such a report, such as
- -- which interface, which statistic, how many hosts,
- -- and the start and stop times of the sampling. When
- -- the report is prepared, entries are created in the
- -- hostTopNTable associated with the relevant
- -- hostTopNControlEntry. These entries are static for
- -- each report after it has been prepared.
-
- hostTopNControlTable OBJECT-TYPE
- SYNTAX SEQUENCE OF HostTopNControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of top N host control entries."
- ::= { hostTopN 1 }
-
- hostTopNControlEntry OBJECT-TYPE
- SYNTAX HostTopNControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
-
-
- "A set of parameters that control the creation of a
- report of the top N hosts according to several
- metrics. For example, an instance of the
- hostTopNDuration object might be named
- hostTopNDuration.3"
- INDEX { hostTopNControlIndex }
- ::= { hostTopNControlTable 1 }
-
- HostTopNControlEntry ::= SEQUENCE {
- hostTopNControlIndex INTEGER (1..65535),
- hostTopNHostIndex INTEGER (1..65535),
- hostTopNRateBase INTEGER,
- hostTopNTimeRemaining INTEGER,
- hostTopNDuration INTEGER,
- hostTopNRequestedSize INTEGER,
- hostTopNGrantedSize INTEGER,
- hostTopNStartTime TimeTicks,
- hostTopNOwner OwnerString,
- hostTopNStatus EntryStatus
- }
-
- hostTopNControlIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry
- in the hostTopNControl table. Each such
- entry defines one top N report prepared for
- one interface."
- ::= { hostTopNControlEntry 1 }
-
- hostTopNHostIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The host table for which a top N report will be
- prepared on behalf of this entry. The host table
- identified by a particular value of this index is
- associated with the same host table as identified by
- the same value of hostIndex.
-
- This object may not be modified if the associated
- hostTopNStatus object is equal to valid(1)."
- ::= { hostTopNControlEntry 2 }
-
- hostTopNRateBase OBJECT-TYPE
-
-
- SYNTAX INTEGER {
- hostTopNInPkts(1),
- hostTopNOutPkts(2),
- hostTopNInOctets(3),
- hostTopNOutOctets(4),
- hostTopNOutErrors(5),
- hostTopNOutBroadcastPkts(6),
- hostTopNOutMulticastPkts(7)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The variable for each host that the hostTopNRate
- variable is based upon.
-
- This object may not be modified if the associated
- hostTopNStatus object is equal to valid(1)."
- ::= { hostTopNControlEntry 3 }
-
- hostTopNTimeRemaining OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The number of seconds left in the report currently
- being collected. When this object is modified by
- the management station, a new collection is started,
- possibly aborting a currently running report. The
- new value is used as the requested duration of this
- report, which is loaded into the associated
- hostTopNDuration object.
-
- When this object is set to a non-zero value, any
- associated hostTopNEntries shall be made
- inaccessible by the monitor. While the value of
- this object is non-zero, it decrements by one per
- second until it reaches zero. During this time, all
- associated hostTopNEntries shall remain
- inaccessible. At the time that this object
- decrements to zero, the report is made accessible in
- the hostTopNTable. Thus, the hostTopN table needs
- to be created only at the end of the collection
- interval."
- DEFVAL { 0 }
- ::= { hostTopNControlEntry 4 }
-
- hostTopNDuration OBJECT-TYPE
- SYNTAX INTEGER
-
-
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of seconds that this report has collected
- during the last sampling interval, or if this
- report is currently being collected, the number
- of seconds that this report is being collected
- during this sampling interval.
-
- When the associated hostTopNTimeRemaining object is
- set, this object shall be set by the probe to the
- same value and shall not be modified until the next
- time the hostTopNTimeRemaining is set.
-
- This value shall be zero if no reports have been
- requested for this hostTopNControlEntry."
- DEFVAL { 0 }
- ::= { hostTopNControlEntry 5 }
-
- hostTopNRequestedSize OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The maximum number of hosts requested for the top N
- table.
-
- When this object is created or modified, the probe
- should set hostTopNGrantedSize as closely to this
- object as is possible for the particular probe
- implementation and available resources."
- DEFVAL { 10 }
- ::= { hostTopNControlEntry 6 }
-
- hostTopNGrantedSize OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The maximum number of hosts in the top N table.
-
- When the associated hostTopNRequestedSize object is
- created or modified, the probe should set this
- object as closely to the requested value as is
- possible for the particular implementation and
- available resources. The probe must not lower this
- value except as a result of a set to the associated
- hostTopNRequestedSize object.
-
-
- Hosts with the highest value of hostTopNRate shall be
- placed in this table in decreasing order of this rate
- until there is no more room or until there are no more
- hosts."
- ::= { hostTopNControlEntry 7 }
-
- hostTopNStartTime OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime when this top N report was
- last started. In other words, this is the time that
- the associated hostTopNTimeRemaining object was
- modified to start the requested report."
- ::= { hostTopNControlEntry 8 }
-
- hostTopNOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { hostTopNControlEntry 9 }
-
- hostTopNStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this hostTopNControl entry.
-
- If this object is not equal to valid(1), all
- associated hostTopNEntries shall be deleted by the
- agent."
- ::= { hostTopNControlEntry 10 }
-
- hostTopNTable OBJECT-TYPE
- SYNTAX SEQUENCE OF HostTopNEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of top N host entries."
- ::= { hostTopN 2 }
-
- hostTopNEntry OBJECT-TYPE
- SYNTAX HostTopNEntry
-
-
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A set of statistics for a host that is part of a
- top N report. For example, an instance of the
- hostTopNRate object might be named
- hostTopNRate.3.10"
- INDEX { hostTopNReport, hostTopNIndex }
- ::= { hostTopNTable 1 }
-
- HostTopNEntry ::= SEQUENCE {
- hostTopNReport INTEGER (1..65535),
- hostTopNIndex INTEGER (1..65535),
- hostTopNAddress OCTET STRING,
- hostTopNRate INTEGER
- }
-
- hostTopNReport OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "This object identifies the top N report of which
- this entry is a part. The set of hosts
- identified by a particular value of this
- object is part of the same report as identified
- by the same value of the hostTopNControlIndex object."
- ::= { hostTopNEntry 1 }
-
- hostTopNIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in
- the hostTopN table among those in the same report.
- This index is between 1 and N, where N is the
- number of entries in this table. Increasing values
- of hostTopNIndex shall be assigned to entries with
- decreasing values of hostTopNRate until index N
- is assigned to the entry with the lowest value of
- hostTopNRate or there are no more hostTopNEntries."
- ::= { hostTopNEntry 2 }
-
- hostTopNAddress OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
-
-
- DESCRIPTION
- "The physical address of this host."
- ::= { hostTopNEntry 3 }
-
- hostTopNRate OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The amount of change in the selected variable
- during this sampling interval. The selected
- variable is this host's instance of the object
- selected by hostTopNRateBase."
- ::= { hostTopNEntry 4 }
-
-
- -- The Matrix Group
-
- -- Implementation of the Matrix group is optional.
- --
- -- The Matrix group consists of the matrixControlTable,
- -- matrixSDTable and the matrixDSTable. These tables
- -- store statistics for a particular conversation
- -- between two addresses. As the device detects a new
- -- conversation, including those to a non-unicast
- -- address, it creates a new entry in both of the
- -- matrix tables. It must only create new entries
- -- based on information received in good packets. If
- -- the monitoring device finds itself short of
- -- resources, it may delete entries as needed. It is
- -- suggested that the device delete the least recently
- -- used entries first.
-
- matrixControlTable OBJECT-TYPE
- SYNTAX SEQUENCE OF MatrixControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of information entries for the
- traffic matrix on each interface."
- ::= { matrix 1 }
-
- matrixControlEntry OBJECT-TYPE
- SYNTAX MatrixControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "Information about a traffic matrix on a particular
-
-
- interface. For example, an instance of the
- matrixControlLastDeleteTime object might be named
- matrixControlLastDeleteTime.1"
- INDEX { matrixControlIndex }
- ::= { matrixControlTable 1 }
-
- MatrixControlEntry ::= SEQUENCE {
- matrixControlIndex INTEGER (1..65535),
- matrixControlDataSource OBJECT IDENTIFIER,
- matrixControlTableSize INTEGER,
- matrixControlLastDeleteTime TimeTicks,
- matrixControlOwner OwnerString,
- matrixControlStatus EntryStatus
- }
-
- matrixControlIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in the
- matrixControl table. Each such entry defines
- a function that discovers conversations on a
- particular interface and places statistics about
- them in the matrixSDTable and the matrixDSTable on
- behalf of this matrixControlEntry."
- ::= { matrixControlEntry 1 }
-
- matrixControlDataSource OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "This object identifies the source of
- the data from which this entry creates a traffic
- matrix. This source can be any interface on this
- device. In order to identify a particular
- interface, this object shall identify the instance
- of the ifIndex object, defined in RFC 1213 and RFC
- 1573 [4,6], for the desired interface. For example,
- if an entry were to receive data from interface #1,
- this object would be set to ifIndex.1.
-
- The statistics in this group reflect all packets
- on the local network segment attached to the
- identified interface.
-
- An agent may or may not be able to tell if
-
-
- fundamental changes to the media of the interface
- have occurred and necessitate an invalidation of
- this entry. For example, a hot-pluggable ethernet
- card could be pulled out and replaced by a
- token-ring card. In such a case, if the agent has
- such knowledge of the change, it is recommended that
- it invalidate this entry.
-
- This object may not be modified if the associated
- matrixControlStatus object is equal to valid(1)."
- ::= { matrixControlEntry 2 }
-
- matrixControlTableSize OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of matrixSDEntries in the matrixSDTable
- for this interface. This must also be the value of
- the number of entries in the matrixDSTable for this
- interface."
- ::= { matrixControlEntry 3 }
-
- matrixControlLastDeleteTime OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime when the last entry
- was deleted from the portion of the matrixSDTable
- or matrixDSTable associated with this
- matrixControlEntry. If no deletions have occurred,
- this value shall be zero."
- ::= { matrixControlEntry 4 }
-
- matrixControlOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { matrixControlEntry 5 }
-
- matrixControlStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
-
-
- DESCRIPTION
- "The status of this matrixControl entry.
-
- If this object is not equal to valid(1), all
- associated entries in the matrixSDTable and the
- matrixDSTable shall be deleted by the agent."
- ::= { matrixControlEntry 6 }
-
- matrixSDTable OBJECT-TYPE
- SYNTAX SEQUENCE OF MatrixSDEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of traffic matrix entries indexed by
- source and destination MAC address."
- ::= { matrix 2 }
-
- matrixSDEntry OBJECT-TYPE
- SYNTAX MatrixSDEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A collection of statistics for communications between
- two addresses on a particular interface. For example,
- an instance of the matrixSDPkts object might be named
- matrixSDPkts.1.6.8.0.32.27.3.176.6.8.0.32.10.8.113"
- INDEX { matrixSDIndex,
- matrixSDSourceAddress, matrixSDDestAddress }
- ::= { matrixSDTable 1 }
-
- MatrixSDEntry ::= SEQUENCE {
- matrixSDSourceAddress OCTET STRING,
- matrixSDDestAddress OCTET STRING,
- matrixSDIndex INTEGER (1..65535),
- matrixSDPkts Counter,
- matrixSDOctets Counter,
- matrixSDErrors Counter
- }
-
- matrixSDSourceAddress OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The source physical address."
- ::= { matrixSDEntry 1 }
-
- matrixSDDestAddress OBJECT-TYPE
-
-
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The destination physical address."
- ::= { matrixSDEntry 2 }
-
- matrixSDIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The set of collected matrix statistics of which
- this entry is a part. The set of matrix statistics
- identified by a particular value of this index
- is associated with the same matrixControlEntry
- as identified by the same value of
- matrixControlIndex."
- ::= { matrixSDEntry 3 }
-
- matrixSDPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets transmitted from the source
- address to the destination address (this number
- includes bad packets)."
- ::= { matrixSDEntry 4 }
-
- matrixSDOctets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of octets (excluding framing bits but
- including FCS octets) contained in all packets
- transmitted from the source address to the
- destination address."
- ::= { matrixSDEntry 5 }
-
- matrixSDErrors OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of bad packets transmitted from
- the source address to the destination address."
-
-
- ::= { matrixSDEntry 6 }
-
-
- -- Traffic matrix tables from destination to source
-
- matrixDSTable OBJECT-TYPE
- SYNTAX SEQUENCE OF MatrixDSEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of traffic matrix entries indexed by
- destination and source MAC address."
- ::= { matrix 3 }
-
- matrixDSEntry OBJECT-TYPE
- SYNTAX MatrixDSEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A collection of statistics for communications between
- two addresses on a particular interface. For example,
- an instance of the matrixSDPkts object might be named
- matrixSDPkts.1.6.8.0.32.10.8.113.6.8.0.32.27.3.176"
- INDEX { matrixDSIndex,
- matrixDSDestAddress, matrixDSSourceAddress }
- ::= { matrixDSTable 1 }
-
- MatrixDSEntry ::= SEQUENCE {
- matrixDSSourceAddress OCTET STRING,
- matrixDSDestAddress OCTET STRING,
- matrixDSIndex INTEGER (1..65535),
- matrixDSPkts Counter,
- matrixDSOctets Counter,
- matrixDSErrors Counter
- }
-
- matrixDSSourceAddress OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The source physical address."
- ::= { matrixDSEntry 1 }
-
- matrixDSDestAddress OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
-
-
- DESCRIPTION
- "The destination physical address."
- ::= { matrixDSEntry 2 }
-
- matrixDSIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The set of collected matrix statistics of which
- this entry is a part. The set of matrix statistics
- identified by a particular value of this index
- is associated with the same matrixControlEntry
- as identified by the same value of
- matrixControlIndex."
- ::= { matrixDSEntry 3 }
-
- matrixDSPkts OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets transmitted from the source
- address to the destination address (this number
- includes bad packets)."
- ::= { matrixDSEntry 4 }
-
- matrixDSOctets OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of octets (excluding framing bits
- but including FCS octets) contained in all packets
- transmitted from the source address to the
- destination address."
- ::= { matrixDSEntry 5 }
-
- matrixDSErrors OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of bad packets transmitted from
- the source address to the destination address."
- ::= { matrixDSEntry 6 }
-
-
-
-
- -- The Filter Group
-
- -- Implementation of the Filter group is optional.
- --
- -- The Filter group allows packets to be captured with an
- -- arbitrary filter expression. A logical data and
- -- event stream or "channel" is formed by the packets
- -- that match the filter expression.
- --
- -- This filter mechanism allows the creation of an arbitrary
- -- logical expression with which to filter packets. Each
- -- filter associated with a channel is OR'ed with the others.
- -- Within a filter, any bits checked in the data and status
- -- are AND'ed with respect to other bits in the same filter.
- -- The NotMask also allows for checking for inequality.
- -- Finally, the channelAcceptType object allows for
- -- inversion of the whole equation.
- --
- -- If a management station wishes to receive a trap to alert
- -- it that new packets have been captured and are available
- -- for download, it is recommended that it set up an alarm
- -- entry that monitors the value of the relevant
- -- channelMatches instance.
- --
- -- The channel can be turned on or off, and can also
- -- generate events when packets pass through it.
-
- filterTable OBJECT-TYPE
- SYNTAX SEQUENCE OF FilterEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of packet filter entries."
- ::= { filter 1 }
-
- filterEntry OBJECT-TYPE
- SYNTAX FilterEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A set of parameters for a packet filter applied on a
- particular interface. As an example, an instance of
- the filterPktData object might be named
- filterPktData.12"
- INDEX { filterIndex }
- ::= { filterTable 1 }
-
-
-
-
- FilterEntry ::= SEQUENCE {
- filterIndex INTEGER (1..65535),
- filterChannelIndex INTEGER (1..65535),
- filterPktDataOffset INTEGER,
- filterPktData OCTET STRING,
- filterPktDataMask OCTET STRING,
- filterPktDataNotMask OCTET STRING,
- filterPktStatus INTEGER,
- filterPktStatusMask INTEGER,
- filterPktStatusNotMask INTEGER,
- filterOwner OwnerString,
- filterStatus EntryStatus
- }
-
- filterIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry
- in the filter table. Each such entry defines
- one filter that is to be applied to every packet
- received on an interface."
- ::= { filterEntry 1 }
-
- filterChannelIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "This object identifies the channel of which this
- filter is a part. The filters identified by a
- particular value of this object are associated with
- the same channel as identified by the same value of
- the channelIndex object."
- ::= { filterEntry 2 }
-
- filterPktDataOffset OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The offset from the beginning of each packet where
- a match of packet data will be attempted. This offset
- is measured from the point in the physical layer
- packet after the framing bits, if any. For example,
- in an Ethernet frame, this point is at the beginning
- of the destination MAC address.
-
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- DEFVAL { 0 }
- ::= { filterEntry 3 }
-
- filterPktData OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The data that is to be matched with the input
- packet. For each packet received, this filter and
- the accompanying filterPktDataMask and
- filterPktDataNotMask will be adjusted for the
- offset. The only bits relevant to this match
- algorithm are those that have the corresponding
- filterPktDataMask bit equal to one. The following
- three rules are then applied to every packet:
-
- (1) If the packet is too short and does not have data
- corresponding to part of the filterPktData, the
- packet will fail this data match.
-
- (2) For each relevant bit from the packet with the
- corresponding filterPktDataNotMask bit set to
- zero, if the bit from the packet is not equal to
- the corresponding bit from the filterPktData,
- then the packet will fail this data match.
-
- (3) If for every relevant bit from the packet with the
- corresponding filterPktDataNotMask bit set to one,
- the bit from the packet is equal to the
- corresponding bit from the filterPktData, then
- the packet will fail this data match.
-
- Any packets that have not failed any of the three
- matches above have passed this data match. In
- particular, a zero length filter will match any
- packet.
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- ::= { filterEntry 4 }
-
- filterPktDataMask OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-write
- STATUS mandatory
-
-
- DESCRIPTION
- "The mask that is applied to the match process.
- After adjusting this mask for the offset, only those
- bits in the received packet that correspond to bits
- set in this mask are relevant for further processing
- by the match algorithm. The offset is applied to
- filterPktDataMask in the same way it is applied to the
- filter. For the purposes of the matching algorithm,
- if the associated filterPktData object is longer
- than this mask, this mask is conceptually extended
- with '1' bits until it reaches the length of the
- filterPktData object.
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- ::= { filterEntry 5 }
-
- filterPktDataNotMask OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The inversion mask that is applied to the match
- process. After adjusting this mask for the offset,
- those relevant bits in the received packet that
- correspond to bits cleared in this mask must all be
- equal to their corresponding bits in the
- filterPktData object for the packet to be accepted.
- In addition, at least one of those relevant bits in
- the received packet that correspond to bits set in
- this mask must be different to its corresponding bit
- in the filterPktData object.
-
- For the purposes of the matching algorithm, if the
- associated filterPktData object is longer than this
- mask, this mask is conceptually extended with '0'
- bits until it reaches the length of the
- filterPktData object.
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- ::= { filterEntry 6 }
-
- filterPktStatus OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
-
-
- "The status that is to be matched with the input
- packet. The only bits relevant to this match
- algorithm are those that have the corresponding
- filterPktStatusMask bit equal to one. The following
- two rules are then applied to every packet:
-
- (1) For each relevant bit from the packet status
- with the corresponding filterPktStatusNotMask bit
- set to zero, if the bit from the packet status is
- not equal to the corresponding bit from the
- filterPktStatus, then the packet will fail this
- status match.
-
- (2) If for every relevant bit from the packet status
- with the corresponding filterPktStatusNotMask bit
- set to one, the bit from the packet status is
- equal to the corresponding bit from the
- filterPktStatus, then the packet will fail this
- status match.
-
- Any packets that have not failed either of the two
- matches above have passed this status match. In
- particular, a zero length status filter will match any
- packet's status.
-
- The value of the packet status is a sum. This sum
- initially takes the value zero. Then, for each
- error, E, that has been discovered in this packet,
- 2 raised to a value representing E is added to the
- sum. The errors and the bits that represent them are
- dependent on the media type of the interface that
- this channel is receiving packets from.
-
- The errors defined for a packet captured off of an
- Ethernet interface are as follows:
-
- bit # Error
- 0 Packet is longer than 1518 octets
- 1 Packet is shorter than 64 octets
- 2 Packet experienced a CRC or Alignment
- error
-
- For example, an Ethernet fragment would have a
- value of 6 (2^1 + 2^2).
-
- As this MIB is expanded to new media types, this
- object will have other media-specific errors
- defined.
-
-
- For the purposes of this status matching algorithm,
- if the packet status is longer than this
- filterPktStatus object, this object is conceptually
- extended with '0' bits until it reaches the size of
- the packet status.
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- ::= { filterEntry 7 }
-
- filterPktStatusMask OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The mask that is applied to the status match
- process. Only those bits in the received packet
- that correspond to bits set in this mask are
- relevant for further processing by the status match
- algorithm. For the purposes of the matching
- algorithm, if the associated filterPktStatus object
- is longer than this mask, this mask is conceptually
- extended with '1' bits until it reaches the size of
- the filterPktStatus. In addition, if a packet
- status is longer than this mask, this mask is
- conceptually extended with '0' bits until it reaches
- the size of the packet status.
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- ::= { filterEntry 8 }
-
- filterPktStatusNotMask OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The inversion mask that is applied to the status
- match process. Those relevant bits in the received
- packet status that correspond to bits cleared in
- this mask must all be equal to their corresponding
- bits in the filterPktStatus object for the packet to
- be accepted. In addition, at least one of those
- relevant bits in the received packet status that
- correspond to bits set in this mask must be
- different to its corresponding bit in the
- filterPktStatus object for the packet to be
- accepted.
-
-
- For the purposes of the matching algorithm, if the
- associated filterPktStatus object or a packet status
- is longer than this mask, this mask is conceptually
- extended with '0' bits until it reaches the longer
- of the lengths of the filterPktStatus object and the
- packet status.
-
- This object may not be modified if the associated
- filterStatus object is equal to valid(1)."
- ::= { filterEntry 9 }
-
- filterOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { filterEntry 10 }
-
- filterStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this filter entry."
- ::= { filterEntry 11 }
-
- channelTable OBJECT-TYPE
- SYNTAX SEQUENCE OF ChannelEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of packet channel entries."
- ::= { filter 2 }
-
- channelEntry OBJECT-TYPE
- SYNTAX ChannelEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A set of parameters for a packet channel applied on a
- particular interface. As an example, an instance of
- the channelMatches object might be named
- channelMatches.3"
- INDEX { channelIndex }
- ::= { channelTable 1 }
-
-
-
- ChannelEntry ::= SEQUENCE {
- channelIndex INTEGER (1..65535),
- channelIfIndex INTEGER (1..65535),
- channelAcceptType INTEGER,
- channelDataControl INTEGER,
- channelTurnOnEventIndex INTEGER (0..65535),
- channelTurnOffEventIndex INTEGER (0..65535),
- channelEventIndex INTEGER (0..65535),
- channelEventStatus INTEGER,
- channelMatches Counter,
- channelDescription DisplayString (SIZE (0..127)),
- channelOwner OwnerString,
- channelStatus EntryStatus
- }
-
- channelIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in the
- channel table. Each such entry defines one channel,
- a logical data and event stream.
-
- It is suggested that before creating a channel, an
- application should scan all instances of the
- filterChannelIndex object to make sure that there
- are no pre-existing filters that would be
- inadvertently be linked to the channel."
- ::= { channelEntry 1 }
-
- channelIfIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The value of this object uniquely identifies the
- interface on this remote network monitoring device
- to which the associated filters are applied to allow
- data into this channel. The interface identified by
- a particular value of this object is the same
- interface as identified by the same value of the
- ifIndex object, defined in RFC 1213 and RFC 1573
- [4,6].
-
- The filters in this group are applied to all packets
- on the local network segment attached to the
- identified interface.
-
-
- An agent may or may not be able to tell if
- fundamental changes to the media of the interface
- have occurred and necessitate an invalidation of
- this entry. For example, a hot-pluggable ethernet
- card could be pulled out and replaced by a
- token-ring card. In such a case, if the agent has
- such knowledge of the change, it is recommended that
- it invalidate this entry.
-
- This object may not be modified if the associated
- channelStatus object is equal to valid(1)."
- ::= { channelEntry 2 }
-
- channelAcceptType OBJECT-TYPE
- SYNTAX INTEGER {
- acceptMatched(1),
- acceptFailed(2)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "This object controls the action of the filters
- associated with this channel. If this object is equal
- to acceptMatched(1), packets will be accepted to this
- channel if they are accepted by both the packet data
- and packet status matches of an associated filter. If
- this object is equal to acceptFailed(2), packets will
- be accepted to this channel only if they fail either
- the packet data match or the packet status match of
- each of the associated filters.
-
- In particular, a channel with no associated filters
- will match no packets if set to acceptMatched(1)
- case and will match all packets in the
- acceptFailed(2) case.
-
- This object may not be modified if the associated
- channelStatus object is equal to valid(1)."
- ::= { channelEntry 3 }
-
- channelDataControl OBJECT-TYPE
- SYNTAX INTEGER {
- on(1),
- off(2)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
-
-
- "This object controls the flow of data through this
- channel. If this object is on(1), data, status and
- events flow through this channel. If this object is
- off(2), data, status and events will not flow
- through this channel."
- DEFVAL { off }
- ::= { channelEntry 4 }
-
- channelTurnOnEventIndex OBJECT-TYPE
- SYNTAX INTEGER (0..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The value of this object identifies the event
- that is configured to turn the associated
- channelDataControl from off to on when the event is
- generated. The event identified by a particular value
- of this object is the same event as identified by the
- same value of the eventIndex object. If there is no
- corresponding entry in the eventTable, then no
- association exists. In fact, if no event is intended
- for this channel, channelTurnOnEventIndex must be
- set to zero, a non-existent event index.
-
- This object may not be modified if the associated
- channelStatus object is equal to valid(1)."
- ::= { channelEntry 5 }
-
- channelTurnOffEventIndex OBJECT-TYPE
- SYNTAX INTEGER (0..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The value of this object identifies the event
- that is configured to turn the associated
- channelDataControl from on to off when the event is
- generated. The event identified by a particular value
- of this object is the same event as identified by the
- same value of the eventIndex object. If there is no
- corresponding entry in the eventTable, then no
- association exists. In fact, if no event is intended
- for this channel, channelTurnOffEventIndex must be
- set to zero, a non-existent event index.
-
- This object may not be modified if the associated
- channelStatus object is equal to valid(1)."
- ::= { channelEntry 6 }
-
-
-
- channelEventIndex OBJECT-TYPE
- SYNTAX INTEGER (0..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The value of this object identifies the event
- that is configured to be generated when the
- associated channelDataControl is on and a packet
- is matched. The event identified by a particular
- value of this object is the same event as identified
- by the same value of the eventIndex object. If
- there is no corresponding entry in the eventTable,
- then no association exists. In fact, if no event is
- intended for this channel, channelEventIndex must be
- set to zero, a non-existent event index.
-
- This object may not be modified if the associated
- channelStatus object is equal to valid(1)."
- ::= { channelEntry 7 }
-
- channelEventStatus OBJECT-TYPE
- SYNTAX INTEGER {
- eventReady(1),
- eventFired(2),
- eventAlwaysReady(3)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The event status of this channel.
-
- If this channel is configured to generate events
- when packets are matched, a means of controlling
- the flow of those events is often needed. When
- this object is equal to eventReady(1), a single
- event may be generated, after which this object
- will be set by the probe to eventFired(2). While
- in the eventFired(2) state, no events will be
- generated until the object is modified to
- eventReady(1) (or eventAlwaysReady(3)). The
- management station can thus easily respond to a
- notification of an event by re-enabling this object.
-
- If the management station wishes to disable this
- flow control and allow events to be generated
- at will, this object may be set to
- eventAlwaysReady(3). Disabling the flow control
- is discouraged as it can result in high network
-
-
- traffic or other performance problems."
- DEFVAL { eventReady }
- ::= { channelEntry 8 }
-
- channelMatches OBJECT-TYPE
- SYNTAX Counter
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of times this channel has matched a
- packet. Note that this object is updated even when
- channelDataControl is set to off."
- ::= { channelEntry 9 }
-
- channelDescription OBJECT-TYPE
- SYNTAX DisplayString (SIZE (0..127))
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "A comment describing this channel."
- ::= { channelEntry 10 }
-
- channelOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { channelEntry 11 }
-
- channelStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this channel entry."
- ::= { channelEntry 12 }
-
-
- -- The Packet Capture Group
-
- -- Implementation of the Packet Capture group is optional.
- --
- -- The Packet Capture Group requires implementation of the
- -- Filter Group.
- --
- -- The Packet Capture group allows packets to be captured
-
-
- -- upon a filter match. The bufferControlTable controls
- -- the captured packets output from a channel that is
- -- associated with it. The captured packets are placed
- -- in entries in the captureBufferTable. These entries are
- -- associated with the bufferControlEntry on whose behalf they
- -- were stored.
-
- bufferControlTable OBJECT-TYPE
- SYNTAX SEQUENCE OF BufferControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of buffers control entries."
- ::= { capture 1 }
-
- bufferControlEntry OBJECT-TYPE
- SYNTAX BufferControlEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A set of parameters that control the collection of
- a stream of packets that have matched filters. As
- an example, an instance of the
- bufferControlCaptureSliceSize object might be named
- bufferControlCaptureSliceSize.3"
- INDEX { bufferControlIndex }
- ::= { bufferControlTable 1 }
-
- BufferControlEntry ::= SEQUENCE {
- bufferControlIndex INTEGER (1..65535),
- bufferControlChannelIndex INTEGER (1..65535),
- bufferControlFullStatus INTEGER,
- bufferControlFullAction INTEGER,
- bufferControlCaptureSliceSize INTEGER,
- bufferControlDownloadSliceSize INTEGER,
- bufferControlDownloadOffset INTEGER,
- bufferControlMaxOctetsRequested INTEGER,
- bufferControlMaxOctetsGranted INTEGER,
- bufferControlCapturedPackets INTEGER,
- bufferControlTurnOnTime TimeTicks,
- bufferControlOwner OwnerString,
- bufferControlStatus EntryStatus
- }
-
- bufferControlIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
-
-
- DESCRIPTION
- "An index that uniquely identifies an entry
- in the bufferControl table. The value of this
- index shall never be zero. Each such
- entry defines one set of packets that is
- captured and controlled by one or more filters."
- ::= { bufferControlEntry 1 }
-
- bufferControlChannelIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "An index that identifies the channel that is the
- source of packets for this bufferControl table.
- The channel identified by a particular value of this
- index is the same as identified by the same value of
- the channelIndex object.
-
- This object may not be modified if the associated
- bufferControlStatus object is equal to valid(1)."
- ::= { bufferControlEntry 2 }
-
- bufferControlFullStatus OBJECT-TYPE
- SYNTAX INTEGER {
- spaceAvailable(1),
- full(2)
- }
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "This object shows whether the buffer has room to
- accept new packets or if it is full.
-
- If the status is spaceAvailable(1), the buffer is
- accepting new packets normally. If the status is
- full(2) and the associated bufferControlFullAction
- object is wrapWhenFull, the buffer is accepting new
- packets by deleting enough of the oldest packets
- to make room for new ones as they arrive. Otherwise,
- if the status is full(2) and the
- bufferControlFullAction object is lockWhenFull,
- then the buffer has stopped collecting packets.
-
- When this object is set to full(2) the probe must
- not later set it to spaceAvailable(1) except in the
- case of a significant gain in resources such as
- an increase of bufferControlOctetsGranted. In
-
-
- particular, the wrap-mode action of deleting old
- packets to make room for newly arrived packets
- must not affect the value of this object."
- ::= { bufferControlEntry 3 }
-
- bufferControlFullAction OBJECT-TYPE
- SYNTAX INTEGER {
- lockWhenFull(1),
- wrapWhenFull(2) -- FIFO
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "Controls the action of the buffer when it
- reaches the full status. When in the lockWhenFull(1)
- state and a packet is added to the buffer that
- fills the buffer, the bufferControlFullStatus will
- be set to full(2) and this buffer will stop capturing
- packets."
- ::= { bufferControlEntry 4 }
-
- bufferControlCaptureSliceSize OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The maximum number of octets of each packet
- that will be saved in this capture buffer.
- For example, if a 1500 octet packet is received by
- the probe and this object is set to 500, then only
- 500 octets of the packet will be stored in the
- associated capture buffer. If this variable is set
- to 0, the capture buffer will save as many octets
- as is possible.
-
- This object may not be modified if the associated
- bufferControlStatus object is equal to valid(1)."
- DEFVAL { 100 }
- ::= { bufferControlEntry 5 }
-
- bufferControlDownloadSliceSize OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The maximum number of octets of each packet
- in this capture buffer that will be returned in
- an SNMP retrieval of that packet. For example,
-
-
- if 500 octets of a packet have been stored in the
- associated capture buffer, the associated
- bufferControlDownloadOffset is 0, and this
- object is set to 100, then the captureBufferPacket
- object that contains the packet will contain only
- the first 100 octets of the packet.
-
- A prudent manager will take into account possible
- interoperability or fragmentation problems that may
- occur if the download slice size is set too large.
- In particular, conformant SNMP implementations are not
- required to accept messages whose length exceeds 484
- octets, although they are encouraged to support larger
- datagrams whenever feasible."
- DEFVAL { 100 }
- ::= { bufferControlEntry 6 }
-
- bufferControlDownloadOffset OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The offset of the first octet of each packet
- in this capture buffer that will be returned in
- an SNMP retrieval of that packet. For example,
- if 500 octets of a packet have been stored in the
- associated capture buffer and this object is set to
- 100, then the captureBufferPacket object that
- contains the packet will contain bytes starting
- 100 octets into the packet."
- DEFVAL { 0 }
- ::= { bufferControlEntry 7 }
-
- bufferControlMaxOctetsRequested OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The requested maximum number of octets to be
- saved in this captureBuffer, including any
- implementation-specific overhead. If this variable
- is set to -1, the capture buffer will save as many
- octets as is possible.
-
- When this object is created or modified, the probe
- should set bufferControlMaxOctetsGranted as closely
- to this object as is possible for the particular probe
- implementation and available resources. However, if
-
-
- the object has the special value of -1, the probe
- must set bufferControlMaxOctetsGranted to -1."
- DEFVAL { -1 }
- ::= { bufferControlEntry 8 }
-
- bufferControlMaxOctetsGranted OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The maximum number of octets that can be
- saved in this captureBuffer, including overhead.
- If this variable is -1, the capture buffer will save
- as many octets as possible.
-
- When the bufferControlMaxOctetsRequested object is
- created or modified, the probe should set this object
- as closely to the requested value as is possible for
- the particular probe implementation and available
- resources.
- However, if the request object has the special value
- of -1, the probe must set this object to -1.
- The probe must not lower this value except as a result
- of a modification to the associated
- bufferControlMaxOctetsRequested object.
-
- When this maximum number of octets is reached
- and a new packet is to be added to this
- capture buffer and the corresponding
- bufferControlFullAction is set to wrapWhenFull(2),
- enough of the oldest packets associated with this
- capture buffer shall be deleted by the agent so
- that the new packet can be added. If the
- corresponding bufferControlFullAction is set to
- lockWhenFull(1), the new packet shall be discarded.
- In either case, the probe must set
- bufferControlFullStatus to full(2).
-
- When the value of this object changes to a value less
- than the current value, entries are deleted from
- the captureBufferTable associated with this
- bufferControlEntry. Enough of the
- oldest of these captureBufferEntries shall be
- deleted by the agent so that the number of octets
- used remains less than or equal to the new value of
- this object.
-
- When the value of this object changes to a value
-
-
- greater than the current value, the number of
- associated captureBufferEntries may be allowed to
- grow."
- ::= { bufferControlEntry 9 }
-
- bufferControlCapturedPackets OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of packets currently in this
- captureBuffer."
- ::= { bufferControlEntry 10 }
-
- bufferControlTurnOnTime OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime when this capture buffer was
- first turned on."
- ::= { bufferControlEntry 11 }
-
- bufferControlOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it."
- ::= { bufferControlEntry 12 }
-
- bufferControlStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this buffer Control Entry."
- ::= { bufferControlEntry 13 }
-
- captureBufferTable OBJECT-TYPE
- SYNTAX SEQUENCE OF CaptureBufferEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of packets captured off of a channel."
- ::= { capture 2 }
-
-
-
- captureBufferEntry OBJECT-TYPE
- SYNTAX CaptureBufferEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A packet captured off of an attached network. As an
- example, an instance of the captureBufferPacketData
- object might be named captureBufferPacketData.3.1783"
- INDEX { captureBufferControlIndex, captureBufferIndex }
- ::= { captureBufferTable 1 }
-
- CaptureBufferEntry ::= SEQUENCE {
- captureBufferControlIndex INTEGER (1..65535),
- captureBufferIndex INTEGER (1..2147483647),
- captureBufferPacketID INTEGER,
- captureBufferPacketData OCTET STRING,
- captureBufferPacketLength INTEGER,
- captureBufferPacketTime INTEGER,
- captureBufferPacketStatus INTEGER
- }
-
- captureBufferControlIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The index of the bufferControlEntry with which
- this packet is associated."
- ::= { captureBufferEntry 1 }
-
- captureBufferIndex OBJECT-TYPE
- SYNTAX INTEGER (1..2147483647)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry
- in the captureBuffer table associated with a
- particular bufferControlEntry. This index will
- start at 1 and increase by one for each new packet
- added with the same captureBufferControlIndex.
-
- Should this value reach 2147483647, the next packet
- added with the same captureBufferControlIndex shall
- cause this value to wrap around to 1."
- ::= { captureBufferEntry 2 }
-
- captureBufferPacketID OBJECT-TYPE
- SYNTAX INTEGER
-
-
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that describes the order of packets
- that are received on a particular interface.
- The packetID of a packet captured on an
- interface is defined to be greater than the
- packetID's of all packets captured previously on
- the same interface. As the captureBufferPacketID
- object has a maximum positive value of 2^31 - 1,
- any captureBufferPacketID object shall have the
- value of the associated packet's packetID mod 2^31."
- ::= { captureBufferEntry 3 }
-
- captureBufferPacketData OBJECT-TYPE
- SYNTAX OCTET STRING
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The data inside the packet, starting at the
- beginning of the packet plus any offset specified in
- the associated bufferControlDownloadOffset,
- including any link level headers. The length of the
- data in this object is the minimum of the length of
- the captured packet minus the offset, the length of
- the associated bufferControlCaptureSliceSize minus
- the offset, and the associated
- bufferControlDownloadSliceSize. If this minimum is
- less than zero, this object shall have a length of
- zero."
- ::= { captureBufferEntry 4 }
-
- captureBufferPacketLength OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The actual length (off the wire) of the packet stored
- in this entry, including FCS octets."
- ::= { captureBufferEntry 5 }
-
- captureBufferPacketTime OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The number of milliseconds that had passed since
- this capture buffer was first turned on when this
-
-
- packet was captured."
- ::= { captureBufferEntry 6 }
-
- captureBufferPacketStatus OBJECT-TYPE
- SYNTAX INTEGER
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "A value which indicates the error status of this
- packet.
-
- The value of this object is defined in the same way as
- filterPktStatus. The value is a sum. This sum
- initially takes the value zero. Then, for each
- error, E, that has been discovered in this packet,
- 2 raised to a value representing E is added to the
- sum.
-
- The errors defined for a packet captured off of an
- Ethernet interface are as follows:
-
- bit # Error
- 0 Packet is longer than 1518 octets
- 1 Packet is shorter than 64 octets
- 2 Packet experienced a CRC or Alignment
- error
- 3 First packet in this capture buffer after
- it was detected that some packets were
- not processed correctly.
- 4 Packet's order in buffer is only
- approximate (May only be set for packets
- sent from the probe)
-
- For example, an Ethernet fragment would have a
- value of 6 (2^1 + 2^2).
-
- As this MIB is expanded to new media types, this
- object will have other media-specific errors defined."
- ::= { captureBufferEntry 7 }
-
-
- -- The Event Group
-
- -- Implementation of the Event group is optional.
- --
- -- The Event group controls the generation and notification
- -- of events from this device. Each entry in the eventTable
- -- describes the parameters of the event that can be
-
-
- -- triggered. Each event entry is fired by an associated
- -- condition located elsewhere in the MIB. An event entry
- -- may also be associated- with a function elsewhere in the
- -- MIB that will be executed when the event is generated. For
- -- example, a channel may be turned on or off by the firing
- -- of an event.
- --
- -- Each eventEntry may optionally specify that a log entry
- -- be created on its behalf whenever the event occurs.
- -- Each entry may also specify that notification should
- -- occur by way of SNMP trap messages. In this case, the
- -- community for the trap message is given in the associated
- -- eventCommunity object. The enterprise and specific trap
- -- fields of the trap are determined by the condition that
- -- triggered the event. Two traps are defined: risingAlarm
- -- and fallingAlarm. If the eventTable is triggered by a
- -- condition specified elsewhere, the enterprise and
- -- specific trap fields must be specified for traps
- -- generated for that condition.
-
- eventTable OBJECT-TYPE
- SYNTAX SEQUENCE OF EventEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A list of events to be generated."
- ::= { event 1 }
-
- eventEntry OBJECT-TYPE
- SYNTAX EventEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A set of parameters that describe an event to be
- generated when certain conditions are met. As an
- example, an instance of the eventLastTimeSent object
- might be named eventLastTimeSent.6"
- INDEX { eventIndex }
- ::= { eventTable 1 }
-
- EventEntry ::= SEQUENCE {
- eventIndex INTEGER (1..65535),
- eventDescription DisplayString (SIZE (0..127)),
- eventType INTEGER,
- eventCommunity OCTET STRING (SIZE (0..127)),
- eventLastTimeSent TimeTicks,
- eventOwner OwnerString,
- eventStatus EntryStatus
-
-
- }
-
- eventIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry in the
- event table. Each such entry defines one event that
- is to be generated when the appropriate conditions
- occur."
- ::= { eventEntry 1 }
-
- eventDescription OBJECT-TYPE
- SYNTAX DisplayString (SIZE (0..127))
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "A comment describing this event entry."
- ::= { eventEntry 2 }
-
- eventType OBJECT-TYPE
- SYNTAX INTEGER {
- none(1),
- log(2),
- snmp-trap(3), -- send an SNMP trap
- log-and-trap(4)
- }
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The type of notification that the probe will make
- about this event. In the case of log, an entry is
- made in the log table for each event. In the case of
- snmp-trap, an SNMP trap is sent to one or more
- management stations."
- ::= { eventEntry 3 }
-
- eventCommunity OBJECT-TYPE
- SYNTAX OCTET STRING (SIZE (0..127))
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "If an SNMP trap is to be sent, it will be sent to
- the SNMP community specified by this octet string.
- In the future this table will be extended to include
- the party security mechanism. This object shall be
- set to a string of length zero if it is intended that
-
-
- that mechanism be used to specify the destination of
- the trap."
- ::= { eventEntry 4 }
-
- eventLastTimeSent OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime at the time this event
- entry last generated an event. If this entry has
- not generated any events, this value will be
- zero."
- ::= { eventEntry 5 }
-
- eventOwner OBJECT-TYPE
- SYNTAX OwnerString
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The entity that configured this entry and is
- therefore using the resources assigned to it.
-
- If this object contains a string starting with
- 'monitor' and has associated entries in the log
- table, all connected management stations should
- retrieve those log entries, as they may have
- significance to all management stations connected to
- this device"
- ::= { eventEntry 6 }
-
- eventStatus OBJECT-TYPE
- SYNTAX EntryStatus
- ACCESS read-write
- STATUS mandatory
- DESCRIPTION
- "The status of this event entry.
-
- If this object is not equal to valid(1), all
- associated log entries shall be deleted by the
- agent."
- ::= { eventEntry 7 }
-
- --
- logTable OBJECT-TYPE
- SYNTAX SEQUENCE OF LogEntry
- ACCESS not-accessible
- STATUS mandatory
-
-
- DESCRIPTION
- "A list of events that have been logged."
- ::= { event 2 }
-
- logEntry OBJECT-TYPE
- SYNTAX LogEntry
- ACCESS not-accessible
- STATUS mandatory
- DESCRIPTION
- "A set of data describing an event that has been
- logged. For example, an instance of the
- logDescription object might be named
- logDescription.6.47"
- INDEX { logEventIndex, logIndex }
- ::= { logTable 1 }
-
- LogEntry ::= SEQUENCE {
- logEventIndex INTEGER (1..65535),
- logIndex INTEGER (1..2147483647),
- logTime TimeTicks,
- logDescription DisplayString (SIZE (0..255))
- }
-
- logEventIndex OBJECT-TYPE
- SYNTAX INTEGER (1..65535)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The event entry that generated this log
- entry. The log identified by a particular
- value of this index is associated with the same
- eventEntry as identified by the same value
- of eventIndex."
- ::= { logEntry 1 }
-
- logIndex OBJECT-TYPE
- SYNTAX INTEGER (1..2147483647)
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An index that uniquely identifies an entry
- in the log table amongst those generated by the
- same eventEntries. These indexes are
- assigned beginning with 1 and increase by one
- with each new log entry. The association
- between values of logIndex and logEntries
- is fixed for the lifetime of each logEntry.
- The agent may choose to delete the oldest
-
-
- instances of logEntry as required because of
- lack of memory. It is an implementation-specific
- matter as to when this deletion may occur."
- ::= { logEntry 2 }
-
- logTime OBJECT-TYPE
- SYNTAX TimeTicks
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "The value of sysUpTime when this log entry was
- created."
- ::= { logEntry 3 }
-
- logDescription OBJECT-TYPE
- SYNTAX DisplayString (SIZE (0..255))
- ACCESS read-only
- STATUS mandatory
- DESCRIPTION
- "An implementation dependent description of the
- event that activated this log entry."
- ::= { logEntry 4 }
-
- -- These definitions use the TRAP-TYPE macro as
- -- defined in RFC 1215 [10]
-
- -- Remote Network Monitoring Traps
-
- risingAlarm TRAP-TYPE
- ENTERPRISE rmon
- VARIABLES { alarmIndex, alarmVariable, alarmSampleType,
- alarmValue, alarmRisingThreshold }
- DESCRIPTION
- "The SNMP trap that is generated when an alarm
- entry crosses its rising threshold and generates
- an event that is configured for sending SNMP
- traps."
- ::= 1
-
- fallingAlarm TRAP-TYPE
- ENTERPRISE rmon
- VARIABLES { alarmIndex, alarmVariable, alarmSampleType,
- alarmValue, alarmFallingThreshold }
- DESCRIPTION
- "The SNMP trap that is generated when an alarm
- entry crosses its falling threshold and generates
- an event that is configured for sending SNMP
- traps."
-
-
- ::= 2
-
- END
+RMON-MIB DEFINITIONS ::= BEGIN
+ IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY,
+ NOTIFICATION-TYPE, mib-2, Counter32,
+ Integer32, TimeTicks FROM SNMPv2-SMI
+
+ TEXTUAL-CONVENTION, DisplayString FROM SNMPv2-TC
+
+ MODULE-COMPLIANCE, OBJECT-GROUP,
+ NOTIFICATION-GROUP FROM SNMPv2-CONF;
+
+
+-- Remote Network Monitoring MIB
+
+rmonMibModule MODULE-IDENTITY
+ LAST-UPDATED "200005110000Z" -- 11 May, 2000
+ ORGANIZATION "IETF RMON MIB Working Group"
+ CONTACT-INFO
+ "Steve Waldbusser
+ Phone: +1-650-948-6500
+ Fax: +1-650-745-0671
+ DESCRIPTION
+ "Remote network monitoring devices, often called
+ monitors or probes, are instruments that exist for
+ the purpose of managing a network. This MIB defines
+ objects for managing remote network monitoring devices."
+
+ REVISION "200005110000Z" -- 11 May, 2000
+ DESCRIPTION
+ "Reformatted into SMIv2 format.
+
+ This version published as RFC 2819."
+
+ REVISION "199502010000Z" -- 1 Feb, 1995
+ DESCRIPTION
+ "Bug fixes, clarifications and minor changes based on
+ implementation experience, published as RFC1757 [18].
+
+ Two changes were made to object definitions:
+
+ 1) A new status bit has been defined for the
+ captureBufferPacketStatus object, indicating that the
+ packet order within the capture buffer may not be identical to
+ the packet order as received off the wire. This bit may only
+ be used for packets transmitted by the probe. Older NMS
+ applications can safely ignore this status bit, which might be
+ used by newer agents.
+
+ 2) The packetMatch trap has been removed. This trap was never
+ actually 'approved' and was not added to this document along
+ with the risingAlarm and fallingAlarm traps. The packetMatch
+ trap could not be throttled, which could cause disruption of
+ normal network traffic under some circumstances. An NMS should
+ configure a risingAlarm threshold on the appropriate
+ channelMatches instance if a trap is desired for a packetMatch
+ event. Note that logging of packetMatch events is still
+ supported--only trap generation for such events has been
+ removed.
+
+ In addition, several clarifications to individual object
+ definitions have been added to assist agent and NMS
+ implementors:
+
+ - global definition of 'good packets' and 'bad packets'
+
+ - more detailed text governing conceptual row creation and
+ modification
+
+ - instructions for probes relating to interface changes and
+ disruptions
+
+ - clarification of some ethernet counter definitions
+
+ - recommended formula for calculating network utilization
+
+ - clarification of channel and captureBuffer behavior for some
+ unusual conditions
+
+ - examples of proper instance naming for each table"
+
+ REVISION "199111010000Z" -- 1 Nov, 1991
+ DESCRIPTION
+ "The original version of this MIB, published as RFC1271."
+ ::= { rmonConformance 8 }
+
+ rmon OBJECT IDENTIFIER ::= { mib-2 16 }
+
+
+ -- textual conventions
+
+OwnerString ::= TEXTUAL-CONVENTION
+ STATUS current
+
+ DESCRIPTION
+ "This data type is used to model an administratively
+ assigned name of the owner of a resource. Implementations
+ must accept values composed of well-formed NVT ASCII
+ sequences. In addition, implementations should accept
+ values composed of well-formed UTF-8 sequences.
+
+ It is suggested that this name contain one or more of
+ the following: IP address, management station name,
+ network manager's name, location, or phone number.
+ In some cases the agent itself will be the owner of
+ an entry. In these cases, this string shall be set
+ to a string starting with 'monitor'.
+
+ SNMP access control is articulated entirely in terms
+ of the contents of MIB views; access to a particular
+ SNMP object instance depends only upon its presence
+ or absence in a particular MIB view and never upon
+ its value or the value of related object instances.
+ Thus, objects of this type afford resolution of
+ resource contention only among cooperating
+ managers; they realize no access control function
+ with respect to uncooperative parties."
+ SYNTAX OCTET STRING (SIZE (0..127))
+
+EntryStatus ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "The status of a table entry.
+
+ Setting this object to the value invalid(4) has the
+ effect of invalidating the corresponding entry.
+ That is, it effectively disassociates the mapping
+ identified with said entry.
+ It is an implementation-specific matter as to whether
+ the agent removes an invalidated entry from the table.
+ Accordingly, management stations must be prepared to
+ receive tabular information from agents that corresponds
+ to entries currently not in use. Proper
+ interpretation of such entries requires examination
+ of the relevant EntryStatus object.
+
+ An existing instance of this object cannot be set to
+ createRequest(2). This object may only be set to
+ createRequest(2) when this instance is created. When
+ this object is created, the agent may wish to create
+ supplemental object instances with default values
+ to complete a conceptual row in this table. Because the
+ creation of these default objects is entirely at the option
+ of the agent, the manager must not assume that any will be
+ created, but may make use of any that are created.
+ Immediately after completing the create operation, the agent
+ must set this object to underCreation(3).
+
+ When in the underCreation(3) state, an entry is allowed to
+ exist in a possibly incomplete, possibly inconsistent state,
+ usually to allow it to be modified in multiple PDUs. When in
+ this state, an entry is not fully active.
+ Entries shall exist in the underCreation(3) state until
+ the management station is finished configuring the entry
+ and sets this object to valid(1) or aborts, setting this
+ object to invalid(4). If the agent determines that an
+ entry has been in the underCreation(3) state for an
+ abnormally long time, it may decide that the management
+ station has crashed. If the agent makes this decision,
+ it may set this object to invalid(4) to reclaim the
+ entry. A prudent agent will understand that the
+ management station may need to wait for human input
+ and will allow for that possibility in its
+ determination of this abnormally long period.
+
+ An entry in the valid(1) state is fully configured and
+ consistent and fully represents the configuration or
+ operation such a row is intended to represent. For
+ example, it could be a statistical function that is
+ configured and active, or a filter that is available
+ in the list of filters processed by the packet capture
+ process.
+
+ A manager is restricted to changing the state of an entry in
+ the following ways:
+
+ To: valid createRequest underCreation invalid
+ From:
+ valid OK NO OK OK
+ createRequest N/A N/A N/A N/A
+ underCreation OK NO OK OK
+ invalid NO NO NO OK
+ nonExistent NO OK NO OK
+
+ In the table above, it is not applicable to move the state
+ from the createRequest state to any other state because the
+ manager will never find the variable in that state. The
+ nonExistent state is not a value of the enumeration, rather
+ it means that the entryStatus variable does not exist at all.
+
+ An agent may allow an entryStatus variable to change state in
+ additional ways, so long as the semantics of the states are
+ followed. This allowance is made to ease the implementation of
+ the agent and is made despite the fact that managers should
+ never exercise these additional state transitions."
+ SYNTAX INTEGER {
+ valid(1),
+ createRequest(2),
+ underCreation(3),
+ invalid(4)
+ }
+
+ statistics OBJECT IDENTIFIER ::= { rmon 1 }
+ history OBJECT IDENTIFIER ::= { rmon 2 }
+ alarm OBJECT IDENTIFIER ::= { rmon 3 }
+ hosts OBJECT IDENTIFIER ::= { rmon 4 }
+ hostTopN OBJECT IDENTIFIER ::= { rmon 5 }
+ matrix OBJECT IDENTIFIER ::= { rmon 6 }
+ filter OBJECT IDENTIFIER ::= { rmon 7 }
+ capture OBJECT IDENTIFIER ::= { rmon 8 }
+ event OBJECT IDENTIFIER ::= { rmon 9 }
+ rmonConformance OBJECT IDENTIFIER ::= { rmon 20 }
+
+-- The Ethernet Statistics Group
+--
+-- Implementation of the Ethernet Statistics group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The ethernet statistics group contains statistics measured by the
+-- probe for each monitored interface on this device. These
+-- statistics take the form of free running counters that start from
+-- zero when a valid entry is created.
+--
+-- This group currently has statistics defined only for
+-- Ethernet interfaces. Each etherStatsEntry contains statistics
+-- for one Ethernet interface. The probe must create one
+-- etherStats entry for each monitored Ethernet interface
+-- on the device.
+
+etherStatsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EtherStatsEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of Ethernet statistics entries."
+ ::= { statistics 1 }
+
+etherStatsEntry OBJECT-TYPE
+ SYNTAX EtherStatsEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A collection of statistics kept for a particular
+ Ethernet interface. As an example, an instance of the
+ etherStatsPkts object might be named etherStatsPkts.1"
+ INDEX { etherStatsIndex }
+ ::= { etherStatsTable 1 }
+
+EtherStatsEntry ::= SEQUENCE {
+ etherStatsIndex Integer32,
+ etherStatsDataSource OBJECT IDENTIFIER,
+ etherStatsDropEvents Counter32,
+ etherStatsOctets Counter32,
+ etherStatsPkts Counter32,
+ etherStatsBroadcastPkts Counter32,
+ etherStatsMulticastPkts Counter32,
+ etherStatsCRCAlignErrors Counter32,
+ etherStatsUndersizePkts Counter32,
+ etherStatsOversizePkts Counter32,
+ etherStatsFragments Counter32,
+ etherStatsJabbers Counter32,
+ etherStatsCollisions Counter32,
+ etherStatsPkts64Octets Counter32,
+ etherStatsPkts65to127Octets Counter32,
+ etherStatsPkts128to255Octets Counter32,
+ etherStatsPkts256to511Octets Counter32,
+ etherStatsPkts512to1023Octets Counter32,
+ etherStatsPkts1024to1518Octets Counter32,
+ etherStatsOwner OwnerString,
+ etherStatsStatus EntryStatus
+}
+
+etherStatsIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of this object uniquely identifies this
+ etherStats entry."
+ ::= { etherStatsEntry 1 }
+
+etherStatsDataSource OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+
+ DESCRIPTION
+ "This object identifies the source of the data that
+ this etherStats entry is configured to analyze. This
+ source can be any ethernet interface on this device.
+ In order to identify a particular interface, this object
+ shall identify the instance of the ifIndex object,
+ defined in RFC 2233 [17], for the desired interface.
+ For example, if an entry were to receive data from
+ interface #1, this object would be set to ifIndex.1.
+
+ The statistics in this group reflect all packets
+ on the local network segment attached to the identified
+ interface.
+
+ An agent may or may not be able to tell if fundamental
+ changes to the media of the interface have occurred and
+ necessitate an invalidation of this entry. For example, a
+ hot-pluggable ethernet card could be pulled out and replaced
+ by a token-ring card. In such a case, if the agent has such
+ knowledge of the change, it is recommended that it
+ invalidate this entry.
+
+ This object may not be modified if the associated
+ etherStatsStatus object is equal to valid(1)."
+ ::= { etherStatsEntry 2 }
+
+etherStatsDropEvents OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of events in which packets
+ were dropped by the probe due to lack of resources.
+ Note that this number is not necessarily the number of
+ packets dropped; it is just the number of times this
+ condition has been detected."
+ ::= { etherStatsEntry 3 }
+
+etherStatsOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of octets of data (including
+ those in bad packets) received on the
+ network (excluding framing bits but including
+ FCS octets).
+
+ This object can be used as a reasonable estimate of
+ 10-Megabit ethernet utilization. If greater precision is
+ desired, the etherStatsPkts and etherStatsOctets objects
+ should be sampled before and after a common interval. The
+ differences in the sampled values are Pkts and Octets,
+ respectively, and the number of seconds in the interval is
+ Interval. These values are used to calculate the Utilization
+ as follows:
+
+ Pkts * (9.6 + 6.4) + (Octets * .8)
+ Utilization = -------------------------------------
+ Interval * 10,000
+
+ The result of this equation is the value Utilization which
+ is the percent utilization of the ethernet segment on a
+ scale of 0 to 100 percent."
+ ::= { etherStatsEntry 4 }
+
+etherStatsPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad packets,
+ broadcast packets, and multicast packets) received."
+ ::= { etherStatsEntry 5 }
+
+etherStatsBroadcastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of good packets received that were
+ directed to the broadcast address. Note that this
+ does not include multicast packets."
+ ::= { etherStatsEntry 6 }
+
+etherStatsMulticastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of good packets received that were
+ directed to a multicast address. Note that this number
+ does not include packets directed to the broadcast
+ address."
+ ::= { etherStatsEntry 7 }
+
+etherStatsCRCAlignErrors OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets received that
+ had a length (excluding framing bits, but
+ including FCS octets) of between 64 and 1518
+ octets, inclusive, but had either a bad
+ Frame Check Sequence (FCS) with an integral
+ number of octets (FCS Error) or a bad FCS with
+ a non-integral number of octets (Alignment Error)."
+ ::= { etherStatsEntry 8 }
+
+etherStatsUndersizePkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets received that were
+ less than 64 octets long (excluding framing bits,
+ but including FCS octets) and were otherwise well
+ formed."
+ ::= { etherStatsEntry 9 }
+
+etherStatsOversizePkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets received that were
+ longer than 1518 octets (excluding framing bits,
+ but including FCS octets) and were otherwise
+ well formed."
+ ::= { etherStatsEntry 10 }
+
+etherStatsFragments OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets received that were less than
+ 64 octets in length (excluding framing bits but including
+ FCS octets) and had either a bad Frame Check Sequence
+ (FCS) with an integral number of octets (FCS Error) or a
+ bad FCS with a non-integral number of octets (Alignment
+ Error).
+
+ Note that it is entirely normal for etherStatsFragments to
+ increment. This is because it counts both runts (which are
+ normal occurrences due to collisions) and noise hits."
+ ::= { etherStatsEntry 11 }
+
+etherStatsJabbers OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets received that were
+ longer than 1518 octets (excluding framing bits,
+ but including FCS octets), and had either a bad
+ Frame Check Sequence (FCS) with an integral number
+ of octets (FCS Error) or a bad FCS with a non-integral
+ number of octets (Alignment Error).
+
+ Note that this definition of jabber is different
+ than the definition in IEEE-802.3 section 8.2.1.5
+ (10BASE5) and section 10.3.1.4 (10BASE2). These
+ documents define jabber as the condition where any
+ packet exceeds 20 ms. The allowed range to detect
+ jabber is between 20 ms and 150 ms."
+ ::= { etherStatsEntry 12 }
+
+etherStatsCollisions OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Collisions"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The best estimate of the total number of collisions
+ on this Ethernet segment.
+
+ The value returned will depend on the location of the
+ RMON probe. Section 8.2.1.3 (10BASE-5) and section
+ 10.3.1.3 (10BASE-2) of IEEE standard 802.3 states that a
+ station must detect a collision, in the receive mode, if
+ three or more stations are transmitting simultaneously. A
+ repeater port must detect a collision when two or more
+ stations are transmitting simultaneously. Thus a probe
+ placed on a repeater port could record more collisions
+ than a probe connected to a station on the same segment
+ would.
+
+ Probe location plays a much smaller role when considering
+ 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE standard 802.3
+ defines a collision as the simultaneous presence of signals
+ on the DO and RD circuits (transmitting and receiving
+ at the same time). A 10BASE-T station can only detect
+ collisions when it is transmitting. Thus probes placed on
+ a station and a repeater, should report the same number of
+ collisions.
+
+ Note also that an RMON probe inside a repeater should
+ ideally report collisions between the repeater and one or
+ more other hosts (transmit collisions as defined by IEEE
+ 802.3k) plus receiver collisions observed on any coax
+ segments to which the repeater is connected."
+ ::= { etherStatsEntry 13 }
+
+etherStatsPkts64Octets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad
+ packets) received that were 64 octets in length
+ (excluding framing bits but including FCS octets)."
+ ::= { etherStatsEntry 14 }
+
+etherStatsPkts65to127Octets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad
+ packets) received that were between
+ 65 and 127 octets in length inclusive
+ (excluding framing bits but including FCS octets)."
+ ::= { etherStatsEntry 15 }
+
+etherStatsPkts128to255Octets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad
+ packets) received that were between
+ 128 and 255 octets in length inclusive
+ (excluding framing bits but including FCS octets)."
+ ::= { etherStatsEntry 16 }
+
+etherStatsPkts256to511Octets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad
+ packets) received that were between
+ 256 and 511 octets in length inclusive
+ (excluding framing bits but including FCS octets)."
+ ::= { etherStatsEntry 17 }
+
+etherStatsPkts512to1023Octets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad
+ packets) received that were between
+ 512 and 1023 octets in length inclusive
+ (excluding framing bits but including FCS octets)."
+ ::= { etherStatsEntry 18 }
+
+etherStatsPkts1024to1518Octets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets (including bad
+ packets) received that were between
+ 1024 and 1518 octets in length inclusive
+ (excluding framing bits but including FCS octets)."
+ ::= { etherStatsEntry 19 }
+
+etherStatsOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { etherStatsEntry 20 }
+
+etherStatsStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this etherStats entry."
+ ::= { etherStatsEntry 21 }
+
+-- The History Control Group
+
+-- Implementation of the History Control group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The history control group controls the periodic statistical
+-- sampling of data from various types of networks. The
+-- historyControlTable stores configuration entries that each
+-- define an interface, polling period, and other parameters.
+-- Once samples are taken, their data is stored in an entry
+-- in a media-specific table. Each such entry defines one
+-- sample, and is associated with the historyControlEntry that
+-- caused the sample to be taken. Each counter in the
+-- etherHistoryEntry counts the same event as its similarly-named
+-- counterpart in the etherStatsEntry, except that each value here
+-- is a cumulative sum during a sampling period.
+--
+-- If the probe keeps track of the time of day, it should start
+-- the first sample of the history at a time such that
+-- when the next hour of the day begins, a sample is
+-- started at that instant. This tends to make more
+-- user-friendly reports, and enables comparison of reports
+-- from different probes that have relatively accurate time
+-- of day.
+--
+-- The probe is encouraged to add two history control entries
+-- per monitored interface upon initialization that describe a short
+-- term and a long term polling period. Suggested parameters are 30
+-- seconds for the short term polling period and 30 minutes for
+-- the long term period.
+
+historyControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF HistoryControlEntry
+ MAX-ACCESS not-accessible
+
+ STATUS current
+ DESCRIPTION
+ "A list of history control entries."
+ ::= { history 1 }
+
+historyControlEntry OBJECT-TYPE
+ SYNTAX HistoryControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of parameters that set up a periodic sampling of
+ statistics. As an example, an instance of the
+ historyControlInterval object might be named
+ historyControlInterval.2"
+ INDEX { historyControlIndex }
+ ::= { historyControlTable 1 }
+
+HistoryControlEntry ::= SEQUENCE {
+ historyControlIndex Integer32,
+ historyControlDataSource OBJECT IDENTIFIER,
+ historyControlBucketsRequested Integer32,
+ historyControlBucketsGranted Integer32,
+ historyControlInterval Integer32,
+ historyControlOwner OwnerString,
+ historyControlStatus EntryStatus
+}
+
+historyControlIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in the
+ historyControl table. Each such entry defines a
+ set of samples at a particular interval for an
+ interface on the device."
+ ::= { historyControlEntry 1 }
+
+historyControlDataSource OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This object identifies the source of the data for
+ which historical data was collected and
+ placed in a media-specific table on behalf of this
+ historyControlEntry. This source can be any
+ interface on this device. In order to identify
+ a particular interface, this object shall identify
+ the instance of the ifIndex object, defined
+ in RFC 2233 [17], for the desired interface.
+ For example, if an entry were to receive data from
+ interface #1, this object would be set to ifIndex.1.
+
+ The statistics in this group reflect all packets
+ on the local network segment attached to the identified
+ interface.
+
+ An agent may or may not be able to tell if fundamental
+ changes to the media of the interface have occurred and
+ necessitate an invalidation of this entry. For example, a
+ hot-pluggable ethernet card could be pulled out and replaced
+ by a token-ring card. In such a case, if the agent has such
+ knowledge of the change, it is recommended that it
+ invalidate this entry.
+
+ This object may not be modified if the associated
+ historyControlStatus object is equal to valid(1)."
+ ::= { historyControlEntry 2 }
+
+historyControlBucketsRequested OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The requested number of discrete time intervals
+ over which data is to be saved in the part of the
+ media-specific table associated with this
+ historyControlEntry.
+
+ When this object is created or modified, the probe
+ should set historyControlBucketsGranted as closely to
+ this object as is possible for the particular probe
+ implementation and available resources."
+ DEFVAL { 50 }
+ ::= { historyControlEntry 3 }
+
+historyControlBucketsGranted OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of discrete sampling intervals
+ over which data shall be saved in the part of
+ the media-specific table associated with this
+ historyControlEntry.
+
+ When the associated historyControlBucketsRequested
+ object is created or modified, the probe
+ should set this object as closely to the requested
+ value as is possible for the particular
+ probe implementation and available resources. The
+ probe must not lower this value except as a result
+ of a modification to the associated
+ historyControlBucketsRequested object.
+
+ There will be times when the actual number of
+ buckets associated with this entry is less than
+ the value of this object. In this case, at the
+ end of each sampling interval, a new bucket will
+ be added to the media-specific table.
+
+ When the number of buckets reaches the value of
+ this object and a new bucket is to be added to the
+ media-specific table, the oldest bucket associated
+ with this historyControlEntry shall be deleted by
+ the agent so that the new bucket can be added.
+
+ When the value of this object changes to a value less
+ than the current value, entries are deleted
+ from the media-specific table associated with this
+ historyControlEntry. Enough of the oldest of these
+ entries shall be deleted by the agent so that their
+ number remains less than or equal to the new value of
+ this object.
+
+ When the value of this object changes to a value greater
+ than the current value, the number of associated media-
+ specific entries may be allowed to grow."
+ ::= { historyControlEntry 4 }
+
+historyControlInterval OBJECT-TYPE
+ SYNTAX Integer32 (1..3600)
+ UNITS "Seconds"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The interval in seconds over which the data is
+ sampled for each bucket in the part of the
+ media-specific table associated with this
+ historyControlEntry. This interval can
+ be set to any number of seconds between 1 and
+ 3600 (1 hour).
+
+ Because the counters in a bucket may overflow at their
+ maximum value with no indication, a prudent manager will
+ take into account the possibility of overflow in any of
+ the associated counters. It is important to consider the
+ minimum time in which any counter could overflow on a
+ particular media type and set the historyControlInterval
+ object to a value less than this interval. This is
+ typically most important for the 'octets' counter in any
+ media-specific table. For example, on an Ethernet
+ network, the etherHistoryOctets counter could overflow
+ in about one hour at the Ethernet's maximum
+ utilization.
+
+ This object may not be modified if the associated
+ historyControlStatus object is equal to valid(1)."
+ DEFVAL { 1800 }
+ ::= { historyControlEntry 5 }
+
+historyControlOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { historyControlEntry 6 }
+
+historyControlStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this historyControl entry.
+
+ Each instance of the media-specific table associated
+ with this historyControlEntry will be deleted by the agent
+ if this historyControlEntry is not equal to valid(1)."
+ ::= { historyControlEntry 7 }
+
+-- The Ethernet History Group
+
+-- Implementation of the Ethernet History group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Ethernet History group records periodic statistical samples
+-- from a network and stores them for later retrieval.
+-- Once samples are taken, their data is stored in an entry
+-- in a media-specific table. Each such entry defines one
+-- sample, and is associated with the historyControlEntry that
+-- caused the sample to be taken. This group defines the
+-- etherHistoryTable, for Ethernet networks.
+--
+
+etherHistoryTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EtherHistoryEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of Ethernet history entries."
+ ::= { history 2 }
+
+etherHistoryEntry OBJECT-TYPE
+ SYNTAX EtherHistoryEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An historical sample of Ethernet statistics on a particular
+ Ethernet interface. This sample is associated with the
+ historyControlEntry which set up the parameters for
+ a regular collection of these samples. As an example, an
+ instance of the etherHistoryPkts object might be named
+ etherHistoryPkts.2.89"
+ INDEX { etherHistoryIndex , etherHistorySampleIndex }
+ ::= { etherHistoryTable 1 }
+
+EtherHistoryEntry ::= SEQUENCE {
+ etherHistoryIndex Integer32,
+ etherHistorySampleIndex Integer32,
+ etherHistoryIntervalStart TimeTicks,
+ etherHistoryDropEvents Counter32,
+ etherHistoryOctets Counter32,
+ etherHistoryPkts Counter32,
+ etherHistoryBroadcastPkts Counter32,
+ etherHistoryMulticastPkts Counter32,
+ etherHistoryCRCAlignErrors Counter32,
+ etherHistoryUndersizePkts Counter32,
+ etherHistoryOversizePkts Counter32,
+ etherHistoryFragments Counter32,
+ etherHistoryJabbers Counter32,
+ etherHistoryCollisions Counter32,
+ etherHistoryUtilization Integer32
+}
+
+etherHistoryIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The history of which this entry is a part. The
+ history identified by a particular value of this
+ index is the same history as identified
+ by the same value of historyControlIndex."
+ ::= { etherHistoryEntry 1 }
+
+etherHistorySampleIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..2147483647)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies the particular
+ sample this entry represents among all samples
+ associated with the same historyControlEntry.
+ This index starts at 1 and increases by one
+ as each new sample is taken."
+ ::= { etherHistoryEntry 2 }
+
+etherHistoryIntervalStart OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime at the start of the interval
+ over which this sample was measured. If the probe
+ keeps track of the time of day, it should start
+ the first sample of the history at a time such that
+ when the next hour of the day begins, a sample is
+ started at that instant. Note that following this
+ rule may require the probe to delay collecting the
+ first sample of the history, as each sample must be
+ of the same interval. Also note that the sample which
+ is currently being collected is not accessible in this
+ table until the end of its interval."
+ ::= { etherHistoryEntry 3 }
+
+etherHistoryDropEvents OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of events in which packets
+ were dropped by the probe due to lack of resources
+ during this sampling interval. Note that this number
+ is not necessarily the number of packets dropped, it
+ is just the number of times this condition has been
+ detected."
+ ::= { etherHistoryEntry 4 }
+
+etherHistoryOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of octets of data (including
+ those in bad packets) received on the
+ network (excluding framing bits but including
+ FCS octets)."
+ ::= { etherHistoryEntry 5 }
+
+etherHistoryPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets (including bad packets)
+ received during this sampling interval."
+ ::= { etherHistoryEntry 6 }
+
+etherHistoryBroadcastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets received during this
+ sampling interval that were directed to the
+ broadcast address."
+ ::= { etherHistoryEntry 7 }
+
+etherHistoryMulticastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets received during this
+ sampling interval that were directed to a
+ multicast address. Note that this number does not
+ include packets addressed to the broadcast address."
+ ::= { etherHistoryEntry 8 }
+
+etherHistoryCRCAlignErrors OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets received during this
+ sampling interval that had a length (excluding
+ framing bits but including FCS octets) between
+ 64 and 1518 octets, inclusive, but had either a bad Frame
+ Check Sequence (FCS) with an integral number of octets
+ (FCS Error) or a bad FCS with a non-integral number
+ of octets (Alignment Error)."
+ ::= { etherHistoryEntry 9 }
+
+etherHistoryUndersizePkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets received during this
+ sampling interval that were less than 64 octets
+ long (excluding framing bits but including FCS
+ octets) and were otherwise well formed."
+ ::= { etherHistoryEntry 10 }
+
+etherHistoryOversizePkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets received during this
+ sampling interval that were longer than 1518
+ octets (excluding framing bits but including
+ FCS octets) but were otherwise well formed."
+ ::= { etherHistoryEntry 11 }
+
+etherHistoryFragments OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of packets received during this
+ sampling interval that were less than 64 octets in
+ length (excluding framing bits but including FCS
+ octets) had either a bad Frame Check Sequence (FCS)
+ with an integral number of octets (FCS Error) or a bad
+ FCS with a non-integral number of octets (Alignment
+ Error).
+
+ Note that it is entirely normal for etherHistoryFragments to
+ increment. This is because it counts both runts (which are
+ normal occurrences due to collisions) and noise hits."
+ ::= { etherHistoryEntry 12 }
+
+etherHistoryJabbers OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets received during this
+ sampling interval that were longer than 1518 octets
+ (excluding framing bits but including FCS octets),
+ and had either a bad Frame Check Sequence (FCS)
+ with an integral number of octets (FCS Error) or
+ a bad FCS with a non-integral number of octets
+ (Alignment Error).
+
+ Note that this definition of jabber is different
+ than the definition in IEEE-802.3 section 8.2.1.5
+ (10BASE5) and section 10.3.1.4 (10BASE2). These
+ documents define jabber as the condition where any
+ packet exceeds 20 ms. The allowed range to detect
+ jabber is between 20 ms and 150 ms."
+ ::= { etherHistoryEntry 13 }
+
+etherHistoryCollisions OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Collisions"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The best estimate of the total number of collisions
+ on this Ethernet segment during this sampling
+ interval.
+
+ The value returned will depend on the location of the
+ RMON probe. Section 8.2.1.3 (10BASE-5) and section
+ 10.3.1.3 (10BASE-2) of IEEE standard 802.3 states that a
+ station must detect a collision, in the receive mode, if
+ three or more stations are transmitting simultaneously. A
+ repeater port must detect a collision when two or more
+ stations are transmitting simultaneously. Thus a probe
+ placed on a repeater port could record more collisions
+ than a probe connected to a station on the same segment
+ would.
+
+ Probe location plays a much smaller role when considering
+ 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE standard 802.3
+ defines a collision as the simultaneous presence of signals
+ on the DO and RD circuits (transmitting and receiving
+ at the same time). A 10BASE-T station can only detect
+ collisions when it is transmitting. Thus probes placed on
+ a station and a repeater, should report the same number of
+ collisions.
+
+ Note also that an RMON probe inside a repeater should
+ ideally report collisions between the repeater and one or
+ more other hosts (transmit collisions as defined by IEEE
+ 802.3k) plus receiver collisions observed on any coax
+ segments to which the repeater is connected."
+ ::= { etherHistoryEntry 14 }
+
+etherHistoryUtilization OBJECT-TYPE
+ SYNTAX Integer32 (0..10000)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The best estimate of the mean physical layer
+ network utilization on this interface during this
+ sampling interval, in hundredths of a percent."
+ ::= { etherHistoryEntry 15 }
+
+-- The Alarm Group
+
+-- Implementation of the Alarm group is optional. The Alarm Group
+-- requires the implementation of the Event group.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Alarm group periodically takes statistical samples from
+-- variables in the probe and compares them to thresholds that have
+-- been configured. The alarm table stores configuration
+-- entries that each define a variable, polling period, and
+-- threshold parameters. If a sample is found to cross the
+-- threshold values, an event is generated. Only variables that
+-- resolve to an ASN.1 primitive type of INTEGER (INTEGER, Integer32,
+-- Counter32, Counter64, Gauge32, or TimeTicks) may be monitored in
+-- this way.
+--
+-- This function has a hysteresis mechanism to limit the generation
+-- of events. This mechanism generates one event as a threshold
+-- is crossed in the appropriate direction. No more events are
+-- generated for that threshold until the opposite threshold is
+-- crossed.
+--
+-- In the case of a sampling a deltaValue, a probe may implement
+-- this mechanism with more precision if it takes a delta sample
+-- twice per period, each time comparing the sum of the latest two
+-- samples to the threshold. This allows the detection of threshold
+-- crossings that span the sampling boundary. Note that this does
+-- not require any special configuration of the threshold value.
+-- It is suggested that probes implement this more precise algorithm.
+
+alarmTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of alarm entries."
+ ::= { alarm 1 }
+
+alarmEntry OBJECT-TYPE
+ SYNTAX AlarmEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of parameters that set up a periodic checking
+ for alarm conditions. For example, an instance of the
+ alarmValue object might be named alarmValue.8"
+ INDEX { alarmIndex }
+ ::= { alarmTable 1 }
+
+AlarmEntry ::= SEQUENCE {
+ alarmIndex Integer32,
+ alarmInterval Integer32,
+ alarmVariable OBJECT IDENTIFIER,
+ alarmSampleType INTEGER,
+ alarmValue Integer32,
+ alarmStartupAlarm INTEGER,
+ alarmRisingThreshold Integer32,
+ alarmFallingThreshold Integer32,
+ alarmRisingEventIndex Integer32,
+ alarmFallingEventIndex Integer32,
+ alarmOwner OwnerString,
+ alarmStatus EntryStatus
+}
+
+alarmIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in the
+ alarm table. Each such entry defines a
+ diagnostic sample at a particular interval
+ for an object on the device."
+ ::= { alarmEntry 1 }
+
+alarmInterval OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Seconds"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The interval in seconds over which the data is
+ sampled and compared with the rising and falling
+ thresholds. When setting this variable, care
+ should be taken in the case of deltaValue
+ sampling - the interval should be set short enough
+ that the sampled variable is very unlikely to
+ increase or decrease by more than 2^31 - 1 during
+ a single sampling interval.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 2 }
+
+alarmVariable OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The object identifier of the particular variable to be
+ sampled. Only variables that resolve to an ASN.1 primitive
+ type of INTEGER (INTEGER, Integer32, Counter32, Counter64,
+ Gauge, or TimeTicks) may be sampled.
+
+ Because SNMP access control is articulated entirely
+ in terms of the contents of MIB views, no access
+ control mechanism exists that can restrict the value of
+ this object to identify only those objects that exist
+ in a particular MIB view. Because there is thus no
+ acceptable means of restricting the read access that
+ could be obtained through the alarm mechanism, the
+ probe must only grant write access to this object in
+ those views that have read access to all objects on
+ the probe.
+
+ During a set operation, if the supplied variable name is
+ not available in the selected MIB view, a badValue error
+ must be returned. If at any time the variable name of
+ an established alarmEntry is no longer available in the
+ selected MIB view, the probe must change the status of
+ this alarmEntry to invalid(4).
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 3 }
+
+alarmSampleType OBJECT-TYPE
+ SYNTAX INTEGER {
+ absoluteValue(1),
+ deltaValue(2)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The method of sampling the selected variable and
+ calculating the value to be compared against the
+ thresholds. If the value of this object is
+ absoluteValue(1), the value of the selected variable
+ will be compared directly with the thresholds at the
+ end of the sampling interval. If the value of this
+ object is deltaValue(2), the value of the selected
+ variable at the last sample will be subtracted from
+ the current value, and the difference compared with
+ the thresholds.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 4 }
+
+alarmValue OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of the statistic during the last sampling
+ period. For example, if the sample type is deltaValue,
+ this value will be the difference between the samples
+ at the beginning and end of the period. If the sample
+ type is absoluteValue, this value will be the sampled
+ value at the end of the period.
+ This is the value that is compared with the rising and
+ falling thresholds.
+
+ The value during the current sampling period is not
+ made available until the period is completed and will
+ remain available until the next period completes."
+ ::= { alarmEntry 5 }
+
+alarmStartupAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ risingAlarm(1),
+ fallingAlarm(2),
+ risingOrFallingAlarm(3)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The alarm that may be sent when this entry is first
+ set to valid. If the first sample after this entry
+ becomes valid is greater than or equal to the
+ risingThreshold and alarmStartupAlarm is equal to
+ risingAlarm(1) or risingOrFallingAlarm(3), then a single
+ rising alarm will be generated. If the first sample
+ after this entry becomes valid is less than or equal
+ to the fallingThreshold and alarmStartupAlarm is equal
+ to fallingAlarm(2) or risingOrFallingAlarm(3), then a
+ single falling alarm will be generated.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 6 }
+
+alarmRisingThreshold OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "A threshold for the sampled statistic. When the current
+ sampled value is greater than or equal to this threshold,
+ and the value at the last sampling interval was less than
+ this threshold, a single event will be generated.
+ A single event will also be generated if the first
+ sample after this entry becomes valid is greater than or
+ equal to this threshold and the associated
+ alarmStartupAlarm is equal to risingAlarm(1) or
+ risingOrFallingAlarm(3).
+
+ After a rising event is generated, another such event
+ will not be generated until the sampled value
+ falls below this threshold and reaches the
+ alarmFallingThreshold.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 7 }
+
+alarmFallingThreshold OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "A threshold for the sampled statistic. When the current
+ sampled value is less than or equal to this threshold,
+ and the value at the last sampling interval was greater than
+ this threshold, a single event will be generated.
+ A single event will also be generated if the first
+ sample after this entry becomes valid is less than or
+ equal to this threshold and the associated
+ alarmStartupAlarm is equal to fallingAlarm(2) or
+ risingOrFallingAlarm(3).
+
+ After a falling event is generated, another such event
+ will not be generated until the sampled value
+ rises above this threshold and reaches the
+ alarmRisingThreshold.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 8 }
+
+alarmRisingEventIndex OBJECT-TYPE
+ SYNTAX Integer32 (0..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The index of the eventEntry that is
+ used when a rising threshold is crossed. The
+ eventEntry identified by a particular value of
+ this index is the same as identified by the same value
+ of the eventIndex object. If there is no
+ corresponding entry in the eventTable, then
+ no association exists. In particular, if this value
+ is zero, no associated event will be generated, as
+ zero is not a valid event index.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 9 }
+
+alarmFallingEventIndex OBJECT-TYPE
+ SYNTAX Integer32 (0..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The index of the eventEntry that is
+ used when a falling threshold is crossed. The
+ eventEntry identified by a particular value of
+ this index is the same as identified by the same value
+ of the eventIndex object. If there is no
+ corresponding entry in the eventTable, then
+ no association exists. In particular, if this value
+ is zero, no associated event will be generated, as
+ zero is not a valid event index.
+
+ This object may not be modified if the associated
+ alarmStatus object is equal to valid(1)."
+ ::= { alarmEntry 10 }
+
+alarmOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { alarmEntry 11 }
+
+alarmStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this alarm entry."
+ ::= { alarmEntry 12 }
+
+-- The Host Group
+
+-- Implementation of the Host group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The host group discovers new hosts on the network by
+-- keeping a list of source and destination MAC Addresses seen
+-- in good packets. For each of these addresses, the host group
+-- keeps a set of statistics. The hostControlTable controls
+-- which interfaces this function is performed on, and contains
+-- some information about the process. On behalf of each
+-- hostControlEntry, data is collected on an interface and placed
+-- in both the hostTable and the hostTimeTable. If the
+-- monitoring device finds itself short of resources, it may
+-- delete entries as needed. It is suggested that the device
+-- delete the least recently used entries first.
+
+-- The hostTable contains entries for each address discovered on
+-- a particular interface. Each entry contains statistical
+-- data about that host. This table is indexed by the
+-- MAC address of the host, through which a random access
+-- may be achieved.
+
+-- The hostTimeTable contains data in the same format as the
+-- hostTable, and must contain the same set of hosts, but is
+-- indexed using hostTimeCreationOrder rather than hostAddress.
+-- The hostTimeCreationOrder is an integer which reflects
+-- the relative order in which a particular entry was discovered
+-- and thus inserted into the table. As this order, and thus
+-- the index, is among those entries currently in the table,
+-- the index for a particular entry may change if an
+-- (earlier) entry is deleted. Thus the association between
+-- hostTimeCreationOrder and hostTimeEntry may be broken at
+-- any time.
+
+-- The hostTimeTable has two important uses. The first is the
+-- fast download of this potentially large table. Because the
+-- index of this table runs from 1 to the size of the table,
+-- inclusive, its values are predictable. This allows very
+-- efficient packing of variables into SNMP PDU's and allows
+-- a table transfer to have multiple packets outstanding.
+-- These benefits increase transfer rates tremendously.
+
+-- The second use of the hostTimeTable is the efficient discovery
+-- by the management station of new entries added to the table.
+-- After the management station has downloaded the entire table,
+-- it knows that new entries will be added immediately after the
+-- end of the current table. It can thus detect new entries there
+-- and retrieve them easily.
+
+-- Because the association between hostTimeCreationOrder and
+-- hostTimeEntry may be broken at any time, the management
+-- station must monitor the related hostControlLastDeleteTime
+-- object. When the management station thus detects a deletion,
+-- it must assume that any such associations have been broken,
+-- and invalidate any it has stored locally. This includes
+-- restarting any download of the hostTimeTable that may have been
+-- in progress, as well as rediscovering the end of the
+-- hostTimeTable so that it may detect new entries. If the
+-- management station does not detect the broken association,
+-- it may continue to refer to a particular host by its
+-- creationOrder while unwittingly retrieving the data associated
+-- with another host entirely. If this happens while downloading
+-- the host table, the management station may fail to download
+-- all of the entries in the table.
+
+
+hostControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF HostControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of host table control entries."
+ ::= { hosts 1 }
+
+hostControlEntry OBJECT-TYPE
+ SYNTAX HostControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of parameters that set up the discovery of hosts
+ on a particular interface and the collection of statistics
+ about these hosts. For example, an instance of the
+ hostControlTableSize object might be named
+ hostControlTableSize.1"
+ INDEX { hostControlIndex }
+ ::= { hostControlTable 1 }
+
+HostControlEntry ::= SEQUENCE {
+
+ hostControlIndex Integer32,
+ hostControlDataSource OBJECT IDENTIFIER,
+ hostControlTableSize Integer32,
+ hostControlLastDeleteTime TimeTicks,
+ hostControlOwner OwnerString,
+ hostControlStatus EntryStatus
+}
+
+hostControlIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in the
+ hostControl table. Each such entry defines
+ a function that discovers hosts on a particular interface
+ and places statistics about them in the hostTable and
+ the hostTimeTable on behalf of this hostControlEntry."
+ ::= { hostControlEntry 1 }
+
+hostControlDataSource OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This object identifies the source of the data for
+ this instance of the host function. This source
+ can be any interface on this device. In order
+ to identify a particular interface, this object shall
+ identify the instance of the ifIndex object, defined
+ in RFC 2233 [17], for the desired interface.
+ For example, if an entry were to receive data from
+ interface #1, this object would be set to ifIndex.1.
+
+ The statistics in this group reflect all packets
+ on the local network segment attached to the identified
+ interface.
+
+ An agent may or may not be able to tell if fundamental
+ changes to the media of the interface have occurred and
+ necessitate an invalidation of this entry. For example, a
+ hot-pluggable ethernet card could be pulled out and replaced
+ by a token-ring card. In such a case, if the agent has such
+ knowledge of the change, it is recommended that it
+ invalidate this entry.
+
+ This object may not be modified if the associated
+ hostControlStatus object is equal to valid(1)."
+ ::= { hostControlEntry 2 }
+
+hostControlTableSize OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of hostEntries in the hostTable and the
+ hostTimeTable associated with this hostControlEntry."
+ ::= { hostControlEntry 3 }
+
+hostControlLastDeleteTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime when the last entry
+ was deleted from the portion of the hostTable
+ associated with this hostControlEntry. If no
+ deletions have occurred, this value shall be zero."
+ ::= { hostControlEntry 4 }
+
+hostControlOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { hostControlEntry 5 }
+
+hostControlStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this hostControl entry.
+
+ If this object is not equal to valid(1), all associated
+ entries in the hostTable, hostTimeTable, and the
+ hostTopNTable shall be deleted by the agent."
+ ::= { hostControlEntry 6 }
+
+hostTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF HostEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of host entries."
+ ::= { hosts 2 }
+
+hostEntry OBJECT-TYPE
+ SYNTAX HostEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A collection of statistics for a particular host that has
+ been discovered on an interface of this device. For example,
+ an instance of the hostOutBroadcastPkts object might be
+ named hostOutBroadcastPkts.1.6.8.0.32.27.3.176"
+ INDEX { hostIndex, hostAddress }
+ ::= { hostTable 1 }
+
+HostEntry ::= SEQUENCE {
+ hostAddress OCTET STRING,
+ hostCreationOrder Integer32,
+ hostIndex Integer32,
+ hostInPkts Counter32,
+ hostOutPkts Counter32,
+ hostInOctets Counter32,
+ hostOutOctets Counter32,
+ hostOutErrors Counter32,
+ hostOutBroadcastPkts Counter32,
+ hostOutMulticastPkts Counter32
+}
+
+hostAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The physical address of this host."
+ ::= { hostEntry 1 }
+
+hostCreationOrder OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that defines the relative ordering of
+ the creation time of hosts captured for a
+ particular hostControlEntry. This index shall
+ be between 1 and N, where N is the value of
+ the associated hostControlTableSize. The ordering
+ of the indexes is based on the order of each entry's
+ insertion into the table, in which entries added earlier
+ have a lower index value than entries added later.
+
+ It is important to note that the order for a
+ particular entry may change as an (earlier) entry
+ is deleted from the table. Because this order may
+ change, management stations should make use of the
+ hostControlLastDeleteTime variable in the
+ hostControlEntry associated with the relevant
+ portion of the hostTable. By observing
+ this variable, the management station may detect
+ the circumstances where a previous association
+ between a value of hostCreationOrder
+ and a hostEntry may no longer hold."
+ ::= { hostEntry 2 }
+
+hostIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The set of collected host statistics of which
+ this entry is a part. The set of hosts
+ identified by a particular value of this
+ index is associated with the hostControlEntry
+ as identified by the same value of hostControlIndex."
+ ::= { hostEntry 3 }
+
+hostInPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets transmitted to this
+ address since it was added to the hostTable."
+ ::= { hostEntry 4 }
+
+hostOutPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets, including bad packets, transmitted
+ by this address since it was added to the hostTable."
+ ::= { hostEntry 5 }
+
+hostInOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of octets transmitted to this address since
+ it was added to the hostTable (excluding framing
+ bits but including FCS octets), except for those
+ octets in bad packets."
+ ::= { hostEntry 6 }
+
+hostOutOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of octets transmitted by this address since
+ it was added to the hostTable (excluding framing
+ bits but including FCS octets), including those
+ octets in bad packets."
+ ::= { hostEntry 7 }
+
+hostOutErrors OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of bad packets transmitted by this address
+ since this host was added to the hostTable."
+ ::= { hostEntry 8 }
+
+hostOutBroadcastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets transmitted by this
+ address that were directed to the broadcast address
+ since this host was added to the hostTable."
+ ::= { hostEntry 9 }
+
+hostOutMulticastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets transmitted by this
+ address that were directed to a multicast address
+ since this host was added to the hostTable.
+ Note that this number does not include packets
+ directed to the broadcast address."
+ ::= { hostEntry 10 }
+
+-- host Time Table
+
+hostTimeTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF HostTimeEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of time-ordered host table entries."
+ ::= { hosts 3 }
+
+hostTimeEntry OBJECT-TYPE
+ SYNTAX HostTimeEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A collection of statistics for a particular host that has
+ been discovered on an interface of this device. This
+ collection includes the relative ordering of the creation
+ time of this object. For example, an instance of the
+ hostTimeOutBroadcastPkts object might be named
+ hostTimeOutBroadcastPkts.1.687"
+ INDEX { hostTimeIndex, hostTimeCreationOrder }
+ ::= { hostTimeTable 1 }
+
+HostTimeEntry ::= SEQUENCE {
+ hostTimeAddress OCTET STRING,
+ hostTimeCreationOrder Integer32,
+ hostTimeIndex Integer32,
+ hostTimeInPkts Counter32,
+ hostTimeOutPkts Counter32,
+ hostTimeInOctets Counter32,
+ hostTimeOutOctets Counter32,
+ hostTimeOutErrors Counter32,
+ hostTimeOutBroadcastPkts Counter32,
+ hostTimeOutMulticastPkts Counter32
+}
+
+hostTimeAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The physical address of this host."
+ ::= { hostTimeEntry 1 }
+
+hostTimeCreationOrder OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in
+ the hostTime table among those entries associated
+ with the same hostControlEntry. This index shall
+ be between 1 and N, where N is the value of
+ the associated hostControlTableSize. The ordering
+ of the indexes is based on the order of each entry's
+ insertion into the table, in which entries added earlier
+ have a lower index value than entries added later.
+ Thus the management station has the ability to
+ learn of new entries added to this table without
+ downloading the entire table.
+
+ It is important to note that the index for a
+ particular entry may change as an (earlier) entry
+ is deleted from the table. Because this order may
+ change, management stations should make use of the
+ hostControlLastDeleteTime variable in the
+ hostControlEntry associated with the relevant
+ portion of the hostTimeTable. By observing
+ this variable, the management station may detect
+ the circumstances where a download of the table
+ may have missed entries, and where a previous
+ association between a value of hostTimeCreationOrder
+ and a hostTimeEntry may no longer hold."
+ ::= { hostTimeEntry 2 }
+
+hostTimeIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The set of collected host statistics of which
+ this entry is a part. The set of hosts
+ identified by a particular value of this
+ index is associated with the hostControlEntry
+ as identified by the same value of hostControlIndex."
+ ::= { hostTimeEntry 3 }
+
+hostTimeInPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets transmitted to this
+ address since it was added to the hostTimeTable."
+ ::= { hostTimeEntry 4 }
+
+hostTimeOutPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets, including bad packets, transmitted
+ by this address since it was added to the hostTimeTable."
+ ::= { hostTimeEntry 5 }
+
+hostTimeInOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of octets transmitted to this address since
+ it was added to the hostTimeTable (excluding framing
+ bits but including FCS octets), except for those
+ octets in bad packets."
+ ::= { hostTimeEntry 6 }
+
+hostTimeOutOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of octets transmitted by this address since
+ it was added to the hostTimeTable (excluding framing
+ bits but including FCS octets), including those
+ octets in bad packets."
+ ::= { hostTimeEntry 7 }
+
+hostTimeOutErrors OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of bad packets transmitted by this address
+ since this host was added to the hostTimeTable."
+ ::= { hostTimeEntry 8 }
+
+hostTimeOutBroadcastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets transmitted by this
+ address that were directed to the broadcast address
+ since this host was added to the hostTimeTable."
+ ::= { hostTimeEntry 9 }
+
+hostTimeOutMulticastPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of good packets transmitted by this
+ address that were directed to a multicast address
+ since this host was added to the hostTimeTable.
+ Note that this number does not include packets directed
+ to the broadcast address."
+ ::= { hostTimeEntry 10 }
+
+-- The Host Top "N" Group
+
+-- Implementation of the Host Top N group is optional. The Host Top N
+-- group requires the implementation of the host group.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Host Top N group is used to prepare reports that describe
+-- the hosts that top a list ordered by one of their statistics.
+-- The available statistics are samples of one of their
+-- base statistics, over an interval specified by the management
+-- station. Thus, these statistics are rate based. The management
+-- station also selects how many such hosts are reported.
+
+-- The hostTopNControlTable is used to initiate the generation of
+-- such a report. The management station may select the parameters
+-- of such a report, such as which interface, which statistic,
+-- how many hosts, and the start and stop times of the sampling.
+-- When the report is prepared, entries are created in the
+-- hostTopNTable associated with the relevant hostTopNControlEntry.
+-- These entries are static for each report after it has been
+-- prepared.
+
+hostTopNControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF HostTopNControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of top N host control entries."
+ ::= { hostTopN 1 }
+
+hostTopNControlEntry OBJECT-TYPE
+ SYNTAX HostTopNControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of parameters that control the creation of a report
+ of the top N hosts according to several metrics. For
+ example, an instance of the hostTopNDuration object might
+ be named hostTopNDuration.3"
+ INDEX { hostTopNControlIndex }
+ ::= { hostTopNControlTable 1 }
+
+HostTopNControlEntry ::= SEQUENCE {
+ hostTopNControlIndex Integer32,
+ hostTopNHostIndex Integer32,
+ hostTopNRateBase INTEGER,
+ hostTopNTimeRemaining Integer32,
+ hostTopNDuration Integer32,
+ hostTopNRequestedSize Integer32,
+ hostTopNGrantedSize Integer32,
+ hostTopNStartTime TimeTicks,
+ hostTopNOwner OwnerString,
+ hostTopNStatus EntryStatus
+}
+
+hostTopNControlIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry
+ in the hostTopNControl table. Each such
+ entry defines one top N report prepared for
+ one interface."
+ ::= { hostTopNControlEntry 1 }
+
+hostTopNHostIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The host table for which a top N report will be prepared
+ on behalf of this entry. The host table identified by a
+ particular value of this index is associated with the same
+ host table as identified by the same value of
+ hostIndex.
+
+ This object may not be modified if the associated
+ hostTopNStatus object is equal to valid(1)."
+ ::= { hostTopNControlEntry 2 }
+
+hostTopNRateBase OBJECT-TYPE
+ SYNTAX INTEGER {
+ hostTopNInPkts(1),
+ hostTopNOutPkts(2),
+ hostTopNInOctets(3),
+ hostTopNOutOctets(4),
+ hostTopNOutErrors(5),
+ hostTopNOutBroadcastPkts(6),
+ hostTopNOutMulticastPkts(7)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The variable for each host that the hostTopNRate
+ variable is based upon.
+
+ This object may not be modified if the associated
+ hostTopNStatus object is equal to valid(1)."
+ ::= { hostTopNControlEntry 3 }
+
+hostTopNTimeRemaining OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Seconds"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The number of seconds left in the report currently being
+ collected. When this object is modified by the management
+ station, a new collection is started, possibly aborting
+ a currently running report. The new value is used
+ as the requested duration of this report, which is
+ loaded into the associated hostTopNDuration object.
+
+ When this object is set to a non-zero value, any
+ associated hostTopNEntries shall be made
+ inaccessible by the monitor. While the value of this
+ object is non-zero, it decrements by one per second until
+ it reaches zero. During this time, all associated
+ hostTopNEntries shall remain inaccessible. At the time
+ that this object decrements to zero, the report is made
+ accessible in the hostTopNTable. Thus, the hostTopN
+ table needs to be created only at the end of the collection
+ interval."
+ DEFVAL { 0 }
+ ::= { hostTopNControlEntry 4 }
+
+hostTopNDuration OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Seconds"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of seconds that this report has collected
+ during the last sampling interval, or if this
+ report is currently being collected, the number
+ of seconds that this report is being collected
+ during this sampling interval.
+
+ When the associated hostTopNTimeRemaining object is set,
+ this object shall be set by the probe to the same value
+ and shall not be modified until the next time
+ the hostTopNTimeRemaining is set.
+
+ This value shall be zero if no reports have been
+ requested for this hostTopNControlEntry."
+ DEFVAL { 0 }
+ ::= { hostTopNControlEntry 5 }
+
+hostTopNRequestedSize OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The maximum number of hosts requested for the top N
+ table.
+
+ When this object is created or modified, the probe
+ should set hostTopNGrantedSize as closely to this
+ object as is possible for the particular probe
+ implementation and available resources."
+ DEFVAL { 10 }
+ ::= { hostTopNControlEntry 6 }
+
+hostTopNGrantedSize OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The maximum number of hosts in the top N table.
+
+ When the associated hostTopNRequestedSize object is
+ created or modified, the probe should set this
+ object as closely to the requested value as is possible
+ for the particular implementation and available
+ resources. The probe must not lower this value except
+ as a result of a set to the associated
+ hostTopNRequestedSize object.
+
+ Hosts with the highest value of hostTopNRate shall be
+ placed in this table in decreasing order of this rate
+ until there is no more room or until there are no more
+ hosts."
+ ::= { hostTopNControlEntry 7 }
+
+hostTopNStartTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime when this top N report was
+ last started. In other words, this is the time that
+ the associated hostTopNTimeRemaining object was
+ modified to start the requested report."
+ ::= { hostTopNControlEntry 8 }
+
+hostTopNOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { hostTopNControlEntry 9 }
+
+hostTopNStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this hostTopNControl entry.
+
+ If this object is not equal to valid(1), all associated
+ hostTopNEntries shall be deleted by the agent."
+ ::= { hostTopNControlEntry 10 }
+
+hostTopNTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF HostTopNEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of top N host entries."
+ ::= { hostTopN 2 }
+
+hostTopNEntry OBJECT-TYPE
+ SYNTAX HostTopNEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of statistics for a host that is part of a top N
+ report. For example, an instance of the hostTopNRate
+ object might be named hostTopNRate.3.10"
+ INDEX { hostTopNReport, hostTopNIndex }
+ ::= { hostTopNTable 1 }
+
+HostTopNEntry ::= SEQUENCE {
+ hostTopNReport Integer32,
+ hostTopNIndex Integer32,
+ hostTopNAddress OCTET STRING,
+ hostTopNRate Integer32
+}
+
+hostTopNReport OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object identifies the top N report of which
+ this entry is a part. The set of hosts
+ identified by a particular value of this
+ object is part of the same report as identified
+ by the same value of the hostTopNControlIndex object."
+ ::= { hostTopNEntry 1 }
+
+hostTopNIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in
+ the hostTopN table among those in the same report.
+ This index is between 1 and N, where N is the
+ number of entries in this table. Increasing values
+ of hostTopNIndex shall be assigned to entries with
+ decreasing values of hostTopNRate until index N
+ is assigned to the entry with the lowest value of
+ hostTopNRate or there are no more hostTopNEntries."
+ ::= { hostTopNEntry 2 }
+
+hostTopNAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The physical address of this host."
+ ::= { hostTopNEntry 3 }
+
+hostTopNRate OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The amount of change in the selected variable
+ during this sampling interval. The selected
+ variable is this host's instance of the object
+ selected by hostTopNRateBase."
+ ::= { hostTopNEntry 4 }
+
+-- The Matrix Group
+
+-- Implementation of the Matrix group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Matrix group consists of the matrixControlTable, matrixSDTable
+-- and the matrixDSTable. These tables store statistics for a
+-- particular conversation between two addresses. As the device
+-- detects a new conversation, including those to a non-unicast
+-- address, it creates a new entry in both of the matrix tables.
+-- It must only create new entries based on information
+-- received in good packets. If the monitoring device finds
+-- itself short of resources, it may delete entries as needed.
+-- It is suggested that the device delete the least recently used
+-- entries first.
+
+matrixControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MatrixControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of information entries for the
+ traffic matrix on each interface."
+ ::= { matrix 1 }
+
+matrixControlEntry OBJECT-TYPE
+ SYNTAX MatrixControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Information about a traffic matrix on a particular
+ interface. For example, an instance of the
+ matrixControlLastDeleteTime object might be named
+ matrixControlLastDeleteTime.1"
+ INDEX { matrixControlIndex }
+ ::= { matrixControlTable 1 }
+
+MatrixControlEntry ::= SEQUENCE {
+ matrixControlIndex Integer32,
+ matrixControlDataSource OBJECT IDENTIFIER,
+ matrixControlTableSize Integer32,
+ matrixControlLastDeleteTime TimeTicks,
+ matrixControlOwner OwnerString,
+ matrixControlStatus EntryStatus
+}
+
+matrixControlIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in the
+ matrixControl table. Each such entry defines
+ a function that discovers conversations on a particular
+ interface and places statistics about them in the
+ matrixSDTable and the matrixDSTable on behalf of this
+ matrixControlEntry."
+ ::= { matrixControlEntry 1 }
+
+matrixControlDataSource OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This object identifies the source of
+ the data from which this entry creates a traffic matrix.
+ This source can be any interface on this device. In
+ order to identify a particular interface, this object
+ shall identify the instance of the ifIndex object,
+ defined in RFC 2233 [17], for the desired
+ interface. For example, if an entry were to receive data
+ from interface #1, this object would be set to ifIndex.1.
+
+ The statistics in this group reflect all packets
+ on the local network segment attached to the identified
+ interface.
+
+ An agent may or may not be able to tell if fundamental
+ changes to the media of the interface have occurred and
+ necessitate an invalidation of this entry. For example, a
+ hot-pluggable ethernet card could be pulled out and replaced
+ by a token-ring card. In such a case, if the agent has such
+ knowledge of the change, it is recommended that it
+ invalidate this entry.
+
+ This object may not be modified if the associated
+ matrixControlStatus object is equal to valid(1)."
+ ::= { matrixControlEntry 2 }
+
+matrixControlTableSize OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of matrixSDEntries in the matrixSDTable
+ for this interface. This must also be the value of
+ the number of entries in the matrixDSTable for this
+ interface."
+ ::= { matrixControlEntry 3 }
+
+matrixControlLastDeleteTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime when the last entry
+ was deleted from the portion of the matrixSDTable
+ or matrixDSTable associated with this matrixControlEntry.
+ If no deletions have occurred, this value shall be
+ zero."
+ ::= { matrixControlEntry 4 }
+
+matrixControlOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { matrixControlEntry 5 }
+
+matrixControlStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this matrixControl entry.
+ If this object is not equal to valid(1), all associated
+ entries in the matrixSDTable and the matrixDSTable
+ shall be deleted by the agent."
+ ::= { matrixControlEntry 6 }
+
+matrixSDTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MatrixSDEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of traffic matrix entries indexed by
+ source and destination MAC address."
+ ::= { matrix 2 }
+
+matrixSDEntry OBJECT-TYPE
+ SYNTAX MatrixSDEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A collection of statistics for communications between
+ two addresses on a particular interface. For example,
+ an instance of the matrixSDPkts object might be named
+ matrixSDPkts.1.6.8.0.32.27.3.176.6.8.0.32.10.8.113"
+ INDEX { matrixSDIndex,
+ matrixSDSourceAddress, matrixSDDestAddress }
+ ::= { matrixSDTable 1 }
+
+MatrixSDEntry ::= SEQUENCE {
+ matrixSDSourceAddress OCTET STRING,
+ matrixSDDestAddress OCTET STRING,
+ matrixSDIndex Integer32,
+ matrixSDPkts Counter32,
+ matrixSDOctets Counter32,
+ matrixSDErrors Counter32
+}
+
+matrixSDSourceAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The source physical address."
+ ::= { matrixSDEntry 1 }
+
+matrixSDDestAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The destination physical address."
+ ::= { matrixSDEntry 2 }
+
+matrixSDIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The set of collected matrix statistics of which
+ this entry is a part. The set of matrix statistics
+ identified by a particular value of this index
+ is associated with the same matrixControlEntry
+ as identified by the same value of matrixControlIndex."
+ ::= { matrixSDEntry 3 }
+
+matrixSDPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets transmitted from the source
+ address to the destination address (this number includes
+ bad packets)."
+ ::= { matrixSDEntry 4 }
+
+matrixSDOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of octets (excluding framing bits but
+ including FCS octets) contained in all packets
+ transmitted from the source address to the
+ destination address."
+ ::= { matrixSDEntry 5 }
+
+matrixSDErrors OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of bad packets transmitted from
+ the source address to the destination address."
+ ::= { matrixSDEntry 6 }
+
+-- Traffic matrix tables from destination to source
+
+matrixDSTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MatrixDSEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of traffic matrix entries indexed by
+ destination and source MAC address."
+ ::= { matrix 3 }
+
+matrixDSEntry OBJECT-TYPE
+ SYNTAX MatrixDSEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A collection of statistics for communications between
+ two addresses on a particular interface. For example,
+ an instance of the matrixSDPkts object might be named
+ matrixSDPkts.1.6.8.0.32.10.8.113.6.8.0.32.27.3.176"
+ INDEX { matrixDSIndex,
+ matrixDSDestAddress, matrixDSSourceAddress }
+ ::= { matrixDSTable 1 }
+
+MatrixDSEntry ::= SEQUENCE {
+ matrixDSSourceAddress OCTET STRING,
+ matrixDSDestAddress OCTET STRING,
+ matrixDSIndex Integer32,
+ matrixDSPkts Counter32,
+ matrixDSOctets Counter32,
+ matrixDSErrors Counter32
+}
+
+matrixDSSourceAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The source physical address."
+ ::= { matrixDSEntry 1 }
+
+matrixDSDestAddress OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The destination physical address."
+ ::= { matrixDSEntry 2 }
+
+matrixDSIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The set of collected matrix statistics of which
+ this entry is a part. The set of matrix statistics
+ identified by a particular value of this index
+ is associated with the same matrixControlEntry
+ as identified by the same value of matrixControlIndex."
+ ::= { matrixDSEntry 3 }
+
+matrixDSPkts OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets transmitted from the source
+ address to the destination address (this number includes
+ bad packets)."
+ ::= { matrixDSEntry 4 }
+
+matrixDSOctets OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of octets (excluding framing bits
+ but including FCS octets) contained in all packets
+ transmitted from the source address to the
+ destination address."
+ ::= { matrixDSEntry 5 }
+
+matrixDSErrors OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of bad packets transmitted from
+ the source address to the destination address."
+ ::= { matrixDSEntry 6 }
+
+-- The Filter Group
+
+-- Implementation of the Filter group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Filter group allows packets to be captured with an
+-- arbitrary filter expression. A logical data and
+-- event stream or "channel" is formed by the packets
+-- that match the filter expression.
+--
+-- This filter mechanism allows the creation of an arbitrary
+-- logical expression with which to filter packets. Each
+-- filter associated with a channel is OR'ed with the others.
+-- Within a filter, any bits checked in the data and status are
+-- AND'ed with respect to other bits in the same filter. The
+-- NotMask also allows for checking for inequality. Finally,
+-- the channelAcceptType object allows for inversion of the
+-- whole equation.
+--
+-- If a management station wishes to receive a trap to alert it
+-- that new packets have been captured and are available for
+-- download, it is recommended that it set up an alarm entry that
+-- monitors the value of the relevant channelMatches instance.
+--
+-- The channel can be turned on or off, and can also
+-- generate events when packets pass through it.
+
+filterTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF FilterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of packet filter entries."
+ ::= { filter 1 }
+
+filterEntry OBJECT-TYPE
+ SYNTAX FilterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of parameters for a packet filter applied on a
+ particular interface. As an example, an instance of the
+ filterPktData object might be named filterPktData.12"
+ INDEX { filterIndex }
+ ::= { filterTable 1 }
+
+FilterEntry ::= SEQUENCE {
+ filterIndex Integer32,
+ filterChannelIndex Integer32,
+ filterPktDataOffset Integer32,
+ filterPktData OCTET STRING,
+ filterPktDataMask OCTET STRING,
+ filterPktDataNotMask OCTET STRING,
+ filterPktStatus Integer32,
+ filterPktStatusMask Integer32,
+ filterPktStatusNotMask Integer32,
+ filterOwner OwnerString,
+ filterStatus EntryStatus
+}
+
+filterIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry
+ in the filter table. Each such entry defines
+ one filter that is to be applied to every packet
+ received on an interface."
+ ::= { filterEntry 1 }
+
+filterChannelIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This object identifies the channel of which this filter
+ is a part. The filters identified by a particular value
+ of this object are associated with the same channel as
+ identified by the same value of the channelIndex object."
+ ::= { filterEntry 2 }
+
+filterPktDataOffset OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The offset from the beginning of each packet where
+ a match of packet data will be attempted. This offset
+ is measured from the point in the physical layer
+ packet after the framing bits, if any. For example,
+ in an Ethernet frame, this point is at the beginning of
+ the destination MAC address.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ DEFVAL { 0 }
+
+ ::= { filterEntry 3 }
+
+filterPktData OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The data that is to be matched with the input packet.
+ For each packet received, this filter and the accompanying
+ filterPktDataMask and filterPktDataNotMask will be
+ adjusted for the offset. The only bits relevant to this
+ match algorithm are those that have the corresponding
+ filterPktDataMask bit equal to one. The following three
+ rules are then applied to every packet:
+
+ (1) If the packet is too short and does not have data
+ corresponding to part of the filterPktData, the packet
+ will fail this data match.
+
+ (2) For each relevant bit from the packet with the
+ corresponding filterPktDataNotMask bit set to zero, if
+ the bit from the packet is not equal to the corresponding
+ bit from the filterPktData, then the packet will fail
+ this data match.
+
+ (3) If for every relevant bit from the packet with the
+ corresponding filterPktDataNotMask bit set to one, the
+ bit from the packet is equal to the corresponding bit
+ from the filterPktData, then the packet will fail this
+ data match.
+
+ Any packets that have not failed any of the three matches
+ above have passed this data match. In particular, a zero
+ length filter will match any packet.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ ::= { filterEntry 4 }
+
+filterPktDataMask OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The mask that is applied to the match process.
+ After adjusting this mask for the offset, only those
+ bits in the received packet that correspond to bits set
+ in this mask are relevant for further processing by the
+ match algorithm. The offset is applied to filterPktDataMask
+ in the same way it is applied to the filter. For the
+ purposes of the matching algorithm, if the associated
+ filterPktData object is longer than this mask, this mask is
+ conceptually extended with '1' bits until it reaches the
+ length of the filterPktData object.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ ::= { filterEntry 5 }
+
+filterPktDataNotMask OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The inversion mask that is applied to the match
+ process. After adjusting this mask for the offset,
+ those relevant bits in the received packet that correspond
+ to bits cleared in this mask must all be equal to their
+ corresponding bits in the filterPktData object for the packet
+ to be accepted. In addition, at least one of those relevant
+ bits in the received packet that correspond to bits set in
+ this mask must be different to its corresponding bit in the
+ filterPktData object.
+
+ For the purposes of the matching algorithm, if the associated
+ filterPktData object is longer than this mask, this mask is
+ conceptually extended with '0' bits until it reaches the
+ length of the filterPktData object.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ ::= { filterEntry 6 }
+
+filterPktStatus OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status that is to be matched with the input packet.
+ The only bits relevant to this match algorithm are those that
+ have the corresponding filterPktStatusMask bit equal to one.
+ The following two rules are then applied to every packet:
+
+ (1) For each relevant bit from the packet status with the
+ corresponding filterPktStatusNotMask bit set to zero, if
+ the bit from the packet status is not equal to the
+ corresponding bit from the filterPktStatus, then the
+ packet will fail this status match.
+
+ (2) If for every relevant bit from the packet status with the
+ corresponding filterPktStatusNotMask bit set to one, the
+ bit from the packet status is equal to the corresponding
+ bit from the filterPktStatus, then the packet will fail
+ this status match.
+
+ Any packets that have not failed either of the two matches
+ above have passed this status match. In particular, a zero
+ length status filter will match any packet's status.
+
+ The value of the packet status is a sum. This sum
+ initially takes the value zero. Then, for each
+ error, E, that has been discovered in this packet,
+ 2 raised to a value representing E is added to the sum.
+ The errors and the bits that represent them are dependent
+ on the media type of the interface that this channel
+ is receiving packets from.
+
+ The errors defined for a packet captured off of an
+ Ethernet interface are as follows:
+
+ bit # Error
+ 0 Packet is longer than 1518 octets
+ 1 Packet is shorter than 64 octets
+ 2 Packet experienced a CRC or Alignment error
+
+ For example, an Ethernet fragment would have a
+ value of 6 (2^1 + 2^2).
+
+ As this MIB is expanded to new media types, this object
+ will have other media-specific errors defined.
+
+ For the purposes of this status matching algorithm, if the
+ packet status is longer than this filterPktStatus object,
+ this object is conceptually extended with '0' bits until it
+ reaches the size of the packet status.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ ::= { filterEntry 7 }
+
+filterPktStatusMask OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The mask that is applied to the status match process.
+ Only those bits in the received packet that correspond to
+ bits set in this mask are relevant for further processing
+ by the status match algorithm. For the purposes
+ of the matching algorithm, if the associated filterPktStatus
+ object is longer than this mask, this mask is conceptually
+ extended with '1' bits until it reaches the size of the
+ filterPktStatus. In addition, if a packet status is longer
+ than this mask, this mask is conceptually extended with '0'
+ bits until it reaches the size of the packet status.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ ::= { filterEntry 8 }
+
+filterPktStatusNotMask OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The inversion mask that is applied to the status match
+ process. Those relevant bits in the received packet status
+ that correspond to bits cleared in this mask must all be
+ equal to their corresponding bits in the filterPktStatus
+ object for the packet to be accepted. In addition, at least
+ one of those relevant bits in the received packet status
+ that correspond to bits set in this mask must be different
+ to its corresponding bit in the filterPktStatus object for
+ the packet to be accepted.
+
+ For the purposes of the matching algorithm, if the associated
+ filterPktStatus object or a packet status is longer than this
+ mask, this mask is conceptually extended with '0' bits until
+ it reaches the longer of the lengths of the filterPktStatus
+ object and the packet status.
+
+ This object may not be modified if the associated
+ filterStatus object is equal to valid(1)."
+ ::= { filterEntry 9 }
+
+filterOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { filterEntry 10 }
+
+filterStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this filter entry."
+ ::= { filterEntry 11 }
+
+channelTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ChannelEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of packet channel entries."
+ ::= { filter 2 }
+
+channelEntry OBJECT-TYPE
+ SYNTAX ChannelEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of parameters for a packet channel applied on a
+ particular interface. As an example, an instance of the
+ channelMatches object might be named channelMatches.3"
+ INDEX { channelIndex }
+ ::= { channelTable 1 }
+
+ChannelEntry ::= SEQUENCE {
+ channelIndex Integer32,
+ channelIfIndex Integer32,
+ channelAcceptType INTEGER,
+ channelDataControl INTEGER,
+ channelTurnOnEventIndex Integer32,
+ channelTurnOffEventIndex Integer32,
+ channelEventIndex Integer32,
+ channelEventStatus INTEGER,
+ channelMatches Counter32,
+ channelDescription DisplayString,
+ channelOwner OwnerString,
+ channelStatus EntryStatus
+}
+
+channelIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in the channel
+ table. Each such entry defines one channel, a logical
+ data and event stream.
+
+ It is suggested that before creating a channel, an
+ application should scan all instances of the
+ filterChannelIndex object to make sure that there are no
+ pre-existing filters that would be inadvertently be linked
+ to the channel."
+ ::= { channelEntry 1 }
+
+channelIfIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The value of this object uniquely identifies the
+ interface on this remote network monitoring device to which
+ the associated filters are applied to allow data into this
+ channel. The interface identified by a particular value
+ of this object is the same interface as identified by the
+ same value of the ifIndex object, defined in RFC 2233 [17].
+
+ The filters in this group are applied to all packets on
+ the local network segment attached to the identified
+ interface.
+
+ An agent may or may not be able to tell if fundamental
+ changes to the media of the interface have occurred and
+ necessitate an invalidation of this entry. For example, a
+ hot-pluggable ethernet card could be pulled out and replaced
+ by a token-ring card. In such a case, if the agent has such
+ knowledge of the change, it is recommended that it
+ invalidate this entry.
+
+ This object may not be modified if the associated
+ channelStatus object is equal to valid(1)."
+ ::= { channelEntry 2 }
+
+channelAcceptType OBJECT-TYPE
+ SYNTAX INTEGER {
+ acceptMatched(1),
+ acceptFailed(2)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This object controls the action of the filters
+ associated with this channel. If this object is equal
+ to acceptMatched(1), packets will be accepted to this
+ channel if they are accepted by both the packet data and
+ packet status matches of an associated filter. If
+ this object is equal to acceptFailed(2), packets will
+ be accepted to this channel only if they fail either
+ the packet data match or the packet status match of
+ each of the associated filters.
+
+ In particular, a channel with no associated filters will
+ match no packets if set to acceptMatched(1) case and will
+ match all packets in the acceptFailed(2) case.
+
+ This object may not be modified if the associated
+ channelStatus object is equal to valid(1)."
+ ::= { channelEntry 3 }
+
+channelDataControl OBJECT-TYPE
+ SYNTAX INTEGER {
+ on(1),
+ off(2)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This object controls the flow of data through this channel.
+ If this object is on(1), data, status and events flow
+ through this channel. If this object is off(2), data,
+ status and events will not flow through this channel."
+ DEFVAL { off }
+ ::= { channelEntry 4 }
+
+channelTurnOnEventIndex OBJECT-TYPE
+ SYNTAX Integer32 (0..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The value of this object identifies the event
+ that is configured to turn the associated
+ channelDataControl from off to on when the event is
+ generated. The event identified by a particular value
+ of this object is the same event as identified by the
+ same value of the eventIndex object. If there is no
+ corresponding entry in the eventTable, then no
+ association exists. In fact, if no event is intended
+ for this channel, channelTurnOnEventIndex must be
+ set to zero, a non-existent event index.
+
+ This object may not be modified if the associated
+ channelStatus object is equal to valid(1)."
+ ::= { channelEntry 5 }
+
+channelTurnOffEventIndex OBJECT-TYPE
+ SYNTAX Integer32 (0..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The value of this object identifies the event
+ that is configured to turn the associated
+ channelDataControl from on to off when the event is
+ generated. The event identified by a particular value
+ of this object is the same event as identified by the
+ same value of the eventIndex object. If there is no
+ corresponding entry in the eventTable, then no
+ association exists. In fact, if no event is intended
+ for this channel, channelTurnOffEventIndex must be
+ set to zero, a non-existent event index.
+
+ This object may not be modified if the associated
+ channelStatus object is equal to valid(1)."
+ ::= { channelEntry 6 }
+
+channelEventIndex OBJECT-TYPE
+ SYNTAX Integer32 (0..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The value of this object identifies the event
+ that is configured to be generated when the
+ associated channelDataControl is on and a packet
+ is matched. The event identified by a particular value
+ of this object is the same event as identified by the
+ same value of the eventIndex object. If there is no
+ corresponding entry in the eventTable, then no
+ association exists. In fact, if no event is intended
+ for this channel, channelEventIndex must be
+ set to zero, a non-existent event index.
+
+ This object may not be modified if the associated
+ channelStatus object is equal to valid(1)."
+ ::= { channelEntry 7 }
+
+channelEventStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ eventReady(1),
+ eventFired(2),
+ eventAlwaysReady(3)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The event status of this channel.
+
+ If this channel is configured to generate events
+ when packets are matched, a means of controlling
+ the flow of those events is often needed. When
+ this object is equal to eventReady(1), a single
+ event may be generated, after which this object
+ will be set by the probe to eventFired(2). While
+ in the eventFired(2) state, no events will be
+ generated until the object is modified to
+ eventReady(1) (or eventAlwaysReady(3)). The
+ management station can thus easily respond to a
+ notification of an event by re-enabling this object.
+
+ If the management station wishes to disable this
+ flow control and allow events to be generated
+ at will, this object may be set to
+ eventAlwaysReady(3). Disabling the flow control
+ is discouraged as it can result in high network
+ traffic or other performance problems."
+ DEFVAL { eventReady }
+ ::= { channelEntry 8 }
+
+channelMatches OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of times this channel has matched a packet.
+ Note that this object is updated even when
+ channelDataControl is set to off."
+ ::= { channelEntry 9 }
+
+channelDescription OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..127))
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "A comment describing this channel."
+ ::= { channelEntry 10 }
+
+channelOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { channelEntry 11 }
+
+channelStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this channel entry."
+ ::= { channelEntry 12 }
+
+-- The Packet Capture Group
+
+-- Implementation of the Packet Capture group is optional. The Packet
+-- Capture Group requires implementation of the Filter Group.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Packet Capture group allows packets to be captured
+-- upon a filter match. The bufferControlTable controls
+-- the captured packets output from a channel that is
+-- associated with it. The captured packets are placed
+-- in entries in the captureBufferTable. These entries are
+-- associated with the bufferControlEntry on whose behalf they
+-- were stored.
+
+bufferControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BufferControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of buffers control entries."
+ ::= { capture 1 }
+
+bufferControlEntry OBJECT-TYPE
+ SYNTAX BufferControlEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of parameters that control the collection of a stream
+ of packets that have matched filters. As an example, an
+ instance of the bufferControlCaptureSliceSize object might
+ be named bufferControlCaptureSliceSize.3"
+
+ INDEX { bufferControlIndex }
+ ::= { bufferControlTable 1 }
+
+BufferControlEntry ::= SEQUENCE {
+ bufferControlIndex Integer32,
+ bufferControlChannelIndex Integer32,
+ bufferControlFullStatus INTEGER,
+ bufferControlFullAction INTEGER,
+ bufferControlCaptureSliceSize Integer32,
+ bufferControlDownloadSliceSize Integer32,
+ bufferControlDownloadOffset Integer32,
+ bufferControlMaxOctetsRequested Integer32,
+ bufferControlMaxOctetsGranted Integer32,
+ bufferControlCapturedPackets Integer32,
+ bufferControlTurnOnTime TimeTicks,
+ bufferControlOwner OwnerString,
+ bufferControlStatus EntryStatus
+}
+
+bufferControlIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry
+ in the bufferControl table. The value of this
+ index shall never be zero. Each such
+ entry defines one set of packets that is
+ captured and controlled by one or more filters."
+ ::= { bufferControlEntry 1 }
+
+bufferControlChannelIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "An index that identifies the channel that is the
+ source of packets for this bufferControl table.
+ The channel identified by a particular value of this
+ index is the same as identified by the same value of
+ the channelIndex object.
+
+ This object may not be modified if the associated
+ bufferControlStatus object is equal to valid(1)."
+ ::= { bufferControlEntry 2 }
+
+bufferControlFullStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ spaceAvailable(1),
+ full(2)
+ }
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object shows whether the buffer has room to
+ accept new packets or if it is full.
+
+ If the status is spaceAvailable(1), the buffer is
+ accepting new packets normally. If the status is
+ full(2) and the associated bufferControlFullAction
+ object is wrapWhenFull, the buffer is accepting new
+ packets by deleting enough of the oldest packets
+ to make room for new ones as they arrive. Otherwise,
+ if the status is full(2) and the
+ bufferControlFullAction object is lockWhenFull,
+ then the buffer has stopped collecting packets.
+
+ When this object is set to full(2) the probe must
+ not later set it to spaceAvailable(1) except in the
+ case of a significant gain in resources such as
+ an increase of bufferControlOctetsGranted. In
+ particular, the wrap-mode action of deleting old
+ packets to make room for newly arrived packets
+ must not affect the value of this object."
+ ::= { bufferControlEntry 3 }
+
+bufferControlFullAction OBJECT-TYPE
+ SYNTAX INTEGER {
+ lockWhenFull(1),
+ wrapWhenFull(2) -- FIFO
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "Controls the action of the buffer when it
+ reaches the full status. When in the lockWhenFull(1)
+ state and a packet is added to the buffer that
+ fills the buffer, the bufferControlFullStatus will
+ be set to full(2) and this buffer will stop capturing
+ packets."
+ ::= { bufferControlEntry 4 }
+
+bufferControlCaptureSliceSize OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The maximum number of octets of each packet
+ that will be saved in this capture buffer.
+ For example, if a 1500 octet packet is received by
+ the probe and this object is set to 500, then only
+ 500 octets of the packet will be stored in the
+ associated capture buffer. If this variable is set
+ to 0, the capture buffer will save as many octets
+ as is possible.
+
+ This object may not be modified if the associated
+ bufferControlStatus object is equal to valid(1)."
+ DEFVAL { 100 }
+ ::= { bufferControlEntry 5 }
+
+bufferControlDownloadSliceSize OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The maximum number of octets of each packet
+ in this capture buffer that will be returned in
+ an SNMP retrieval of that packet. For example,
+ if 500 octets of a packet have been stored in the
+ associated capture buffer, the associated
+ bufferControlDownloadOffset is 0, and this
+ object is set to 100, then the captureBufferPacket
+ object that contains the packet will contain only
+ the first 100 octets of the packet.
+
+ A prudent manager will take into account possible
+ interoperability or fragmentation problems that may
+ occur if the download slice size is set too large.
+ In particular, conformant SNMP implementations are not
+ required to accept messages whose length exceeds 484
+ octets, although they are encouraged to support larger
+ datagrams whenever feasible."
+ DEFVAL { 100 }
+ ::= { bufferControlEntry 6 }
+
+bufferControlDownloadOffset OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The offset of the first octet of each packet
+ in this capture buffer that will be returned in
+ an SNMP retrieval of that packet. For example,
+ if 500 octets of a packet have been stored in the
+ associated capture buffer and this object is set to
+ 100, then the captureBufferPacket object that
+ contains the packet will contain bytes starting
+ 100 octets into the packet."
+ DEFVAL { 0 }
+ ::= { bufferControlEntry 7 }
+
+bufferControlMaxOctetsRequested OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The requested maximum number of octets to be
+ saved in this captureBuffer, including any
+ implementation-specific overhead. If this variable
+ is set to -1, the capture buffer will save as many
+ octets as is possible.
+
+ When this object is created or modified, the probe
+ should set bufferControlMaxOctetsGranted as closely
+ to this object as is possible for the particular probe
+ implementation and available resources. However, if
+ the object has the special value of -1, the probe
+ must set bufferControlMaxOctetsGranted to -1."
+ DEFVAL { -1 }
+ ::= { bufferControlEntry 8 }
+
+bufferControlMaxOctetsGranted OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The maximum number of octets that can be
+ saved in this captureBuffer, including overhead.
+ If this variable is -1, the capture buffer will save
+ as many octets as possible.
+
+ When the bufferControlMaxOctetsRequested object is
+ created or modified, the probe should set this object
+ as closely to the requested value as is possible for the
+ particular probe implementation and available resources.
+ However, if the request object has the special value
+ of -1, the probe must set this object to -1.
+
+ The probe must not lower this value except as a result of
+ a modification to the associated
+ bufferControlMaxOctetsRequested object.
+
+ When this maximum number of octets is reached
+ and a new packet is to be added to this
+ capture buffer and the corresponding
+ bufferControlFullAction is set to wrapWhenFull(2),
+ enough of the oldest packets associated with this
+ capture buffer shall be deleted by the agent so
+ that the new packet can be added. If the corresponding
+ bufferControlFullAction is set to lockWhenFull(1),
+ the new packet shall be discarded. In either case,
+ the probe must set bufferControlFullStatus to
+ full(2).
+
+ When the value of this object changes to a value less
+ than the current value, entries are deleted from
+ the captureBufferTable associated with this
+ bufferControlEntry. Enough of the
+ oldest of these captureBufferEntries shall be
+ deleted by the agent so that the number of octets
+ used remains less than or equal to the new value of
+ this object.
+
+ When the value of this object changes to a value greater
+ than the current value, the number of associated
+ captureBufferEntries may be allowed to grow."
+ ::= { bufferControlEntry 9 }
+
+bufferControlCapturedPackets OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Packets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of packets currently in this captureBuffer."
+ ::= { bufferControlEntry 10 }
+
+bufferControlTurnOnTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime when this capture buffer was
+ first turned on."
+ ::= { bufferControlEntry 11 }
+
+bufferControlOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it."
+ ::= { bufferControlEntry 12 }
+
+bufferControlStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this buffer Control Entry."
+ ::= { bufferControlEntry 13 }
+
+captureBufferTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF CaptureBufferEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of packets captured off of a channel."
+ ::= { capture 2 }
+
+captureBufferEntry OBJECT-TYPE
+ SYNTAX CaptureBufferEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A packet captured off of an attached network. As an
+ example, an instance of the captureBufferPacketData
+ object might be named captureBufferPacketData.3.1783"
+ INDEX { captureBufferControlIndex, captureBufferIndex }
+ ::= { captureBufferTable 1 }
+
+CaptureBufferEntry ::= SEQUENCE {
+ captureBufferControlIndex Integer32,
+ captureBufferIndex Integer32,
+ captureBufferPacketID Integer32,
+ captureBufferPacketData OCTET STRING,
+ captureBufferPacketLength Integer32,
+ captureBufferPacketTime Integer32,
+ captureBufferPacketStatus Integer32
+}
+
+captureBufferControlIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The index of the bufferControlEntry with which
+ this packet is associated."
+ ::= { captureBufferEntry 1 }
+
+captureBufferIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..2147483647)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry
+ in the captureBuffer table associated with a
+ particular bufferControlEntry. This index will
+ start at 1 and increase by one for each new packet
+ added with the same captureBufferControlIndex.
+
+ Should this value reach 2147483647, the next packet
+ added with the same captureBufferControlIndex shall
+ cause this value to wrap around to 1."
+ ::= { captureBufferEntry 2 }
+
+captureBufferPacketID OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that describes the order of packets
+ that are received on a particular interface.
+ The packetID of a packet captured on an
+ interface is defined to be greater than the
+ packetID's of all packets captured previously on
+ the same interface. As the captureBufferPacketID
+ object has a maximum positive value of 2^31 - 1,
+ any captureBufferPacketID object shall have the
+ value of the associated packet's packetID mod 2^31."
+ ::= { captureBufferEntry 3 }
+
+captureBufferPacketData OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The data inside the packet, starting at the beginning
+ of the packet plus any offset specified in the
+ associated bufferControlDownloadOffset, including any
+ link level headers. The length of the data in this object
+ is the minimum of the length of the captured packet minus
+ the offset, the length of the associated
+ bufferControlCaptureSliceSize minus the offset, and the
+ associated bufferControlDownloadSliceSize. If this minimum
+ is less than zero, this object shall have a length of zero."
+ ::= { captureBufferEntry 4 }
+
+captureBufferPacketLength OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Octets"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The actual length (off the wire) of the packet stored
+ in this entry, including FCS octets."
+ ::= { captureBufferEntry 5 }
+
+captureBufferPacketTime OBJECT-TYPE
+ SYNTAX Integer32
+ UNITS "Milliseconds"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of milliseconds that had passed since
+ this capture buffer was first turned on when this
+ packet was captured."
+ ::= { captureBufferEntry 6 }
+
+captureBufferPacketStatus OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "A value which indicates the error status of this packet.
+
+ The value of this object is defined in the same way as
+ filterPktStatus. The value is a sum. This sum
+ initially takes the value zero. Then, for each
+ error, E, that has been discovered in this packet,
+ 2 raised to a value representing E is added to the sum.
+
+ The errors defined for a packet captured off of an
+ Ethernet interface are as follows:
+
+ bit # Error
+ 0 Packet is longer than 1518 octets
+ 1 Packet is shorter than 64 octets
+ 2 Packet experienced a CRC or Alignment error
+ 3 First packet in this capture buffer after
+ it was detected that some packets were
+ not processed correctly.
+ 4 Packet's order in buffer is only approximate
+ (May only be set for packets sent from
+ the probe)
+
+ For example, an Ethernet fragment would have a
+ value of 6 (2^1 + 2^2).
+
+ As this MIB is expanded to new media types, this object
+ will have other media-specific errors defined."
+ ::= { captureBufferEntry 7 }
+
+-- The Event Group
+
+-- Implementation of the Event group is optional.
+-- Consult the MODULE-COMPLIANCE macro for the authoritative
+-- conformance information for this MIB.
+--
+-- The Event group controls the generation and notification
+-- of events from this device. Each entry in the eventTable
+-- describes the parameters of the event that can be triggered.
+-- Each event entry is fired by an associated condition located
+-- elsewhere in the MIB. An event entry may also be associated
+-- with a function elsewhere in the MIB that will be executed
+-- when the event is generated. For example, a channel may
+-- be turned on or off by the firing of an event.
+--
+-- Each eventEntry may optionally specify that a log entry
+-- be created on its behalf whenever the event occurs.
+-- Each entry may also specify that notification should
+-- occur by way of SNMP trap messages. In this case, the
+-- community for the trap message is given in the associated
+-- eventCommunity object. The enterprise and specific trap
+-- fields of the trap are determined by the condition that
+-- triggered the event. Two traps are defined: risingAlarm and
+-- fallingAlarm. If the eventTable is triggered by a condition
+-- specified elsewhere, the enterprise and specific trap fields
+-- must be specified for traps generated for that condition.
+
+eventTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EventEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of events to be generated."
+ ::= { event 1 }
+
+eventEntry OBJECT-TYPE
+ SYNTAX EventEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of parameters that describe an event to be generated
+ when certain conditions are met. As an example, an instance
+ of the eventLastTimeSent object might be named
+ eventLastTimeSent.6"
+ INDEX { eventIndex }
+ ::= { eventTable 1 }
+
+EventEntry ::= SEQUENCE {
+ eventIndex Integer32,
+ eventDescription DisplayString,
+ eventType INTEGER,
+ eventCommunity OCTET STRING,
+ eventLastTimeSent TimeTicks,
+ eventOwner OwnerString,
+ eventStatus EntryStatus
+}
+
+eventIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry in the
+ event table. Each such entry defines one event that
+ is to be generated when the appropriate conditions
+ occur."
+ ::= { eventEntry 1 }
+
+eventDescription OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..127))
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "A comment describing this event entry."
+ ::= { eventEntry 2 }
+
+eventType OBJECT-TYPE
+ SYNTAX INTEGER {
+ none(1),
+ log(2),
+ snmptrap(3), -- send an SNMP trap
+ logandtrap(4)
+ }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The type of notification that the probe will make
+ about this event. In the case of log, an entry is
+ made in the log table for each event. In the case of
+ snmp-trap, an SNMP trap is sent to one or more
+ management stations."
+ ::= { eventEntry 3 }
+
+eventCommunity OBJECT-TYPE
+ SYNTAX OCTET STRING (SIZE (0..127))
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "If an SNMP trap is to be sent, it will be sent to
+ the SNMP community specified by this octet string."
+ ::= { eventEntry 4 }
+
+eventLastTimeSent OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime at the time this event
+ entry last generated an event. If this entry has
+ not generated any events, this value will be
+ zero."
+ ::= { eventEntry 5 }
+
+eventOwner OBJECT-TYPE
+ SYNTAX OwnerString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The entity that configured this entry and is therefore
+ using the resources assigned to it.
+
+ If this object contains a string starting with 'monitor'
+ and has associated entries in the log table, all connected
+ management stations should retrieve those log entries,
+ as they may have significance to all management stations
+ connected to this device"
+ ::= { eventEntry 6 }
+
+eventStatus OBJECT-TYPE
+ SYNTAX EntryStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of this event entry.
+
+ If this object is not equal to valid(1), all associated
+ log entries shall be deleted by the agent."
+ ::= { eventEntry 7 }
+
+--
+logTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF LogEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A list of events that have been logged."
+ ::= { event 2 }
+
+logEntry OBJECT-TYPE
+ SYNTAX LogEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A set of data describing an event that has been
+ logged. For example, an instance of the logDescription
+ object might be named logDescription.6.47"
+ INDEX { logEventIndex, logIndex }
+ ::= { logTable 1 }
+
+LogEntry ::= SEQUENCE {
+ logEventIndex Integer32,
+ logIndex Integer32,
+ logTime TimeTicks,
+ logDescription DisplayString
+}
+
+logEventIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..65535)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The event entry that generated this log
+ entry. The log identified by a particular
+ value of this index is associated with the same
+ eventEntry as identified by the same value
+ of eventIndex."
+ ::= { logEntry 1 }
+
+logIndex OBJECT-TYPE
+ SYNTAX Integer32 (1..2147483647)
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An index that uniquely identifies an entry
+ in the log table amongst those generated by the
+ same eventEntries. These indexes are
+ assigned beginning with 1 and increase by one
+ with each new log entry. The association
+ between values of logIndex and logEntries
+ is fixed for the lifetime of each logEntry.
+ The agent may choose to delete the oldest
+ instances of logEntry as required because of
+ lack of memory. It is an implementation-specific
+ matter as to when this deletion may occur."
+ ::= { logEntry 2 }
+
+logTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime when this log entry was created."
+ ::= { logEntry 3 }
+
+logDescription OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..255))
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "An implementation dependent description of the
+ event that activated this log entry."
+ ::= { logEntry 4 }
+
+-- Remote Network Monitoring Traps
+
+rmonEventsV2 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION "Definition point for RMON notifications."
+ ::= { rmon 0 }
+
+risingAlarm NOTIFICATION-TYPE
+ OBJECTS { alarmIndex, alarmVariable, alarmSampleType,
+ alarmValue, alarmRisingThreshold }
+ STATUS current
+ DESCRIPTION
+ "The SNMP trap that is generated when an alarm
+ entry crosses its rising threshold and generates
+ an event that is configured for sending SNMP
+ traps."
+ ::= { rmonEventsV2 1 }
+
+fallingAlarm NOTIFICATION-TYPE
+ OBJECTS { alarmIndex, alarmVariable, alarmSampleType,
+ alarmValue, alarmFallingThreshold }
+ STATUS current
+ DESCRIPTION
+ "The SNMP trap that is generated when an alarm
+ entry crosses its falling threshold and generates
+ an event that is configured for sending SNMP
+ traps."
+ ::= { rmonEventsV2 2 }
+
+-- Conformance information
+
+rmonCompliances OBJECT IDENTIFIER ::= { rmonConformance 9 }
+rmonGroups OBJECT IDENTIFIER ::= { rmonConformance 10 }
+
+-- Compliance Statements
+rmonCompliance MODULE-COMPLIANCE
+ STATUS current
+ DESCRIPTION
+ "The requirements for conformance to the RMON MIB. At least
+ one of the groups in this module must be implemented to
+ conform to the RMON MIB. Implementations of this MIB
+ must also implement the system group of MIB-II [16] and the
+ IF-MIB [17]."
+ MODULE -- this module
+
+ GROUP rmonEtherStatsGroup
+ DESCRIPTION
+ "The RMON Ethernet Statistics Group is optional."
+
+ GROUP rmonHistoryControlGroup
+ DESCRIPTION
+ "The RMON History Control Group is optional."
+
+ GROUP rmonEthernetHistoryGroup
+ DESCRIPTION
+ "The RMON Ethernet History Group is optional."
+
+ GROUP rmonAlarmGroup
+ DESCRIPTION
+ "The RMON Alarm Group is optional."
+
+ GROUP rmonHostGroup
+ DESCRIPTION
+ "The RMON Host Group is mandatory when the
+ rmonHostTopNGroup is implemented."
+
+ GROUP rmonHostTopNGroup
+ DESCRIPTION
+ "The RMON Host Top N Group is optional."
+
+ GROUP rmonMatrixGroup
+ DESCRIPTION
+ "The RMON Matrix Group is optional."
+
+ GROUP rmonFilterGroup
+ DESCRIPTION
+ "The RMON Filter Group is mandatory when the
+ rmonPacketCaptureGroup is implemented."
+
+ GROUP rmonPacketCaptureGroup
+ DESCRIPTION
+ "The RMON Packet Capture Group is optional."
+
+ GROUP rmonEventGroup
+ DESCRIPTION
+ "The RMON Event Group is mandatory when the
+ rmonAlarmGroup is implemented."
+ ::= { rmonCompliances 1 }
+
+ rmonEtherStatsGroup OBJECT-GROUP
+ OBJECTS {
+ etherStatsIndex, etherStatsDataSource,
+ etherStatsDropEvents, etherStatsOctets, etherStatsPkts,
+ etherStatsBroadcastPkts, etherStatsMulticastPkts,
+ etherStatsCRCAlignErrors, etherStatsUndersizePkts,
+ etherStatsOversizePkts, etherStatsFragments,
+ etherStatsJabbers, etherStatsCollisions,
+ etherStatsPkts64Octets, etherStatsPkts65to127Octets,
+ etherStatsPkts128to255Octets,
+ etherStatsPkts256to511Octets,
+ etherStatsPkts512to1023Octets,
+ etherStatsPkts1024to1518Octets,
+ etherStatsOwner, etherStatsStatus
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Ethernet Statistics Group."
+ ::= { rmonGroups 1 }
+
+ rmonHistoryControlGroup OBJECT-GROUP
+ OBJECTS {
+ historyControlIndex, historyControlDataSource,
+ historyControlBucketsRequested,
+ historyControlBucketsGranted, historyControlInterval,
+ historyControlOwner, historyControlStatus
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON History Control Group."
+ ::= { rmonGroups 2 }
+
+ rmonEthernetHistoryGroup OBJECT-GROUP
+ OBJECTS {
+ etherHistoryIndex, etherHistorySampleIndex,
+ etherHistoryIntervalStart, etherHistoryDropEvents,
+ etherHistoryOctets, etherHistoryPkts,
+ etherHistoryBroadcastPkts, etherHistoryMulticastPkts,
+ etherHistoryCRCAlignErrors, etherHistoryUndersizePkts,
+ etherHistoryOversizePkts, etherHistoryFragments,
+ etherHistoryJabbers, etherHistoryCollisions,
+ etherHistoryUtilization
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Ethernet History Group."
+ ::= { rmonGroups 3 }
+
+ rmonAlarmGroup OBJECT-GROUP
+ OBJECTS {
+ alarmIndex, alarmInterval, alarmVariable,
+ alarmSampleType, alarmValue, alarmStartupAlarm,
+ alarmRisingThreshold, alarmFallingThreshold,
+ alarmRisingEventIndex, alarmFallingEventIndex,
+ alarmOwner, alarmStatus
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Alarm Group."
+ ::= { rmonGroups 4 }
+
+ rmonHostGroup OBJECT-GROUP
+ OBJECTS {
+ hostControlIndex, hostControlDataSource,
+ hostControlTableSize, hostControlLastDeleteTime,
+ hostControlOwner, hostControlStatus,
+ hostAddress, hostCreationOrder, hostIndex,
+ hostInPkts, hostOutPkts, hostInOctets,
+ hostOutOctets, hostOutErrors, hostOutBroadcastPkts,
+ hostOutMulticastPkts, hostTimeAddress,
+ hostTimeCreationOrder, hostTimeIndex,
+ hostTimeInPkts, hostTimeOutPkts, hostTimeInOctets,
+ hostTimeOutOctets, hostTimeOutErrors,
+ hostTimeOutBroadcastPkts, hostTimeOutMulticastPkts
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Host Group."
+ ::= { rmonGroups 5 }
+
+ rmonHostTopNGroup OBJECT-GROUP
+ OBJECTS {
+ hostTopNControlIndex, hostTopNHostIndex,
+ hostTopNRateBase, hostTopNTimeRemaining,
+ hostTopNDuration, hostTopNRequestedSize,
+ hostTopNGrantedSize, hostTopNStartTime,
+ hostTopNOwner, hostTopNStatus,
+ hostTopNReport, hostTopNIndex,
+ hostTopNAddress, hostTopNRate
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Host Top 'N' Group."
+ ::= { rmonGroups 6 }
+
+ rmonMatrixGroup OBJECT-GROUP
+ OBJECTS {
+ matrixControlIndex, matrixControlDataSource,
+ matrixControlTableSize, matrixControlLastDeleteTime,
+ matrixControlOwner, matrixControlStatus,
+ matrixSDSourceAddress, matrixSDDestAddress,
+ matrixSDIndex, matrixSDPkts,
+ matrixSDOctets, matrixSDErrors,
+ matrixDSSourceAddress, matrixDSDestAddress,
+ matrixDSIndex, matrixDSPkts,
+ matrixDSOctets, matrixDSErrors
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Matrix Group."
+ ::= { rmonGroups 7 }
+
+ rmonFilterGroup OBJECT-GROUP
+ OBJECTS {
+ filterIndex, filterChannelIndex, filterPktDataOffset,
+ filterPktData, filterPktDataMask,
+ filterPktDataNotMask, filterPktStatus,
+ filterPktStatusMask, filterPktStatusNotMask,
+ filterOwner, filterStatus,
+ channelIndex, channelIfIndex, channelAcceptType,
+ channelDataControl, channelTurnOnEventIndex,
+ channelTurnOffEventIndex, channelEventIndex,
+ channelEventStatus, channelMatches,
+ channelDescription, channelOwner, channelStatus
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Filter Group."
+ ::= { rmonGroups 8 }
+
+ rmonPacketCaptureGroup OBJECT-GROUP
+ OBJECTS {
+ bufferControlIndex, bufferControlChannelIndex,
+ bufferControlFullStatus, bufferControlFullAction,
+ bufferControlCaptureSliceSize,
+ bufferControlDownloadSliceSize,
+ bufferControlDownloadOffset,
+ bufferControlMaxOctetsRequested,
+ bufferControlMaxOctetsGranted,
+ bufferControlCapturedPackets,
+ bufferControlTurnOnTime,
+ bufferControlOwner, bufferControlStatus,
+ captureBufferControlIndex, captureBufferIndex,
+ captureBufferPacketID, captureBufferPacketData,
+ captureBufferPacketLength, captureBufferPacketTime,
+ captureBufferPacketStatus
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Packet Capture Group."
+ ::= { rmonGroups 9 }
+
+ rmonEventGroup OBJECT-GROUP
+ OBJECTS {
+ eventIndex, eventDescription, eventType,
+ eventCommunity, eventLastTimeSent,
+ eventOwner, eventStatus,
+ logEventIndex, logIndex, logTime,
+ logDescription
+ }
+ STATUS current
+ DESCRIPTION
+ "The RMON Event Group."
+ ::= { rmonGroups 10 }
+
+ rmonNotificationGroup NOTIFICATION-GROUP
+ NOTIFICATIONS { risingAlarm, fallingAlarm }
+ STATUS current
+ DESCRIPTION
+ "The RMON Notification Group."
+ ::= { rmonGroups 11 }
+END
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index c95e0a22d1..b90dbe4eef 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The 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%
-SNMP_VSN = 4.21.1
-PRE_VSN =
-APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)"
+APPLICATION = snmp
+SNMP_VSN = 4.22.1
+PRE_VSN =
+APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index c4d8d9901c..38782a3b00 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -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
@@ -29,15 +29,6 @@ VSN=$(SSH_VSN)
APPLICATION=ssh
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -76,33 +67,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
-TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -115,8 +83,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -131,32 +97,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES)
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
-
-endif
-
man: $(MAN3_FILES)
@@ -168,39 +108,14 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/ssh/doc/src/make.dep b/lib/ssh/doc/src/make.dep
deleted file mode 100644
index cfe2f9617b..0000000000
--- a/lib/ssh/doc/src/make.dep
+++ /dev/null
@@ -1,19 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex ref_man.tex ssh.tex ssh_channel.tex \
- ssh_connection.tex ssh_sftp.tex ssh_sftpd.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 6fc4fdc43d..a85cada732 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -29,6 +29,134 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ All keys in authorized_keys are considerd, wrongly only
+ the first one was before.</p>
+ <p>
+ Own Id: OTP-7235</p>
+ </item>
+ <item>
+ <p>
+ ssh daemon now properly handles ras host keys, in
+ previous versions only dsa host keys sufficed to set up a
+ connection.</p>
+ <p>
+ Own Id: OTP-7677</p>
+ </item>
+ <item>
+ <p>
+ ssh:shell/3 and ssh:connect/3 does not hang anymore if
+ connection negotiation fails</p>
+ <p>
+ Own Id: OTP-8111</p>
+ </item>
+ <item>
+ <p>
+ Improve check so that we will not try to read ssh packet
+ length indicator if not sure we have enough data.</p>
+ <p>
+ Own Id: OTP-8380</p>
+ </item>
+ <item>
+ <p>
+ Do not try to use user interaction when it is disabled.</p>
+ <p>
+ Own Id: OTP-9466 Aux Id: seq11886 </p>
+ </item>
+ <item>
+ <p>
+ Improved error handling of internal errors i the ssh
+ connection handling process</p>
+ <p>
+ Own Id: OTP-9905</p>
+ </item>
+ <item>
+ <p>
+ sftp daemon generates file handles correct</p>
+ <p>
+ Own Id: OTP-9948</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Document supported algorithms</p>
+ <p>
+ Own Id: OTP-8109</p>
+ </item>
+ <item>
+ <p>
+ Graceful handling of premature close from an sftp client.</p>
+ <p>
+ Own Id: OTP-9391 Aux Id: seq11838 </p>
+ </item>
+ <item>
+ <p>
+ Changed ssh implementation to use the public_key
+ application for all public key handling. This is also a
+ first step for enabling a callback API for supplying
+ public keys and handling keys protected with password
+ phrases. </p>
+ <p>
+ Additionally the test suites where improved so that they
+ do not copy the users keys to test server directories as
+ this is a security liability. Also ipv6 and file access
+ issues found in the process has been fixed.</p>
+ <p>
+ This change also solves OTP-7677 and OTP-7235</p>
+ <p>
+ This changes also involves some updates to public_keys
+ ssh-functions.</p>
+ <p>
+ Own Id: OTP-9911</p>
+ </item>
+ <item>
+ <p>
+ Added options for the ssh client to support user keys
+ files that are password protected.</p>
+ <p>
+ Own Id: OTP-10036 Aux Id: OTP-6400, Seq10595 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 2.0.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang/OTP can now be built using parallel make if you
+ limit the number of jobs, for instance using '<c>make
+ -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
+ work at the moment because of some missing
+ dependencies.</p>
+ <p>
+ Own Id: OTP-9451</p>
+ </item>
+ <item>
+ <p>
+ Ssh behaviours now use the new directive "-callback".
+ Parameters will be further specified in a later version
+ of ssh.</p>
+ <p>
+ Own Id: OTP-9796</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 2.0.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 2c5096a25f..b84b3a3dcb 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.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>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,9 +33,20 @@
<module>ssh</module>
<modulesummary>Main API of the SSH application</modulesummary>
<description>
- <p>Interface module for the SSH application</p>
+ <p>Interface module for the SSH application. </p>
</description>
+ <section>
+ <title>SSH</title>
+
+ <list type="bulleted">
+ <item>ssh requires the crypto and public_key applications.</item>
+ <item>Supported SSH-version is 2.0 </item>
+ <item>Currently supports only a minimum of mac and encryption algorithms i.e.
+ hmac-sha1, and aes128-cb and 3des-cbc.</item>
+ </list>
+
+ </section>
<section>
<title>COMMON DATA TYPES </title>
@@ -86,7 +97,7 @@
by calling ssh_connect:session_channel/2.</p>
<p>Options are:</p>
<taglist>
- <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <tag><c><![CDATA[{user_dir, string()}]]></c></tag>
<item>
<p>Sets the user directory e.i. the directory containing
ssh configuration files for the user such as
@@ -94,6 +105,18 @@
<c><![CDATA[authorized_key]]></c>. Defaults to the directory normally
referred to as <c><![CDATA[~/.ssh]]></c> </p>
</item>
+ <tag><c><![CDATA[{dsa_pass_phrase, string()}]]></c></tag>
+ <item>
+ <p>If the user dsa key is protected by a pass phrase it can be
+ supplied with this option.
+ </p>
+ </item>
+ <tag><c><![CDATA[{rsa_pass_phrase, string()}]]></c></tag>
+ <item>
+ <p>If the user rsa key is protected by a pass phrase it can be
+ supplied with this option.
+ </p>
+ </item>
<tag><c><![CDATA[{silently_accept_hosts, boolean()}]]></c></tag>
<item>
<p>When true hosts are added to the
@@ -222,17 +245,31 @@
option <c>shell</c> which is much less work than implementing
your own cli channel.
</item>
+ <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <item>
+ <p>Sets the user directory e.i. the directory containing
+ ssh configuration files for the user such as
+ <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa, id_dsa]]></c> and
+ <c><![CDATA[authorized_key]]></c>. Defaults to the directory normally
+ referred to as <c><![CDATA[~/.ssh]]></c> </p>
+ </item>
<tag><c><![CDATA[{system_dir, string()}]]></c></tag>
<item>
<p>Sets the system directory, containing the host files
that identifies the host for ssh. The default is
<c><![CDATA[/etc/ssh]]></c>, note that SSH normally
requires the host files there to be readable only by
- root.</p>
+ root.</p>
+ </item>
+ <tag><c><![CDATA[{auth_methods, string()}]]></c></tag>
+ <item>
+ <p>Comma separated string that determines which authentication methodes that the server
+ should support and in what order they will be tried. Defaults to
+ <c><![CDATA["publickey,keyboard_interactive,password"]]></c></p>
</item>
- <tag><c><![CDATA[{user_passwords, [{string() = User, string() = Password}]}]]></c></tag>
- <item>
- <p>Provide passwords for password authentication.They will
+ <tag><c><![CDATA[{user_passwords, [{string() = User, string() = Password}]}]]></c></tag>
+ <item>
+ <p>Provide passwords for password authentication.They will
be used when someone tries to connect to the server and
public key user authentication fails. The option provides
a list of valid user names and the corresponding password.
@@ -283,22 +320,6 @@
</func>
<func>
- <name>sign_data(Data, Algorithm) -> Signature | {error, Reason}</name>
- <fsummary> </fsummary>
- <type>
- <v> Data = binary()</v>
- <v> Algorithm = "ssh-rsa"</v>
- <v> Signature = binary()</v>
- <v> Reason = term()</v>
- </type>
- <desc>
- <p>Signs the supplied binary using the SSH key.
- </p>
- </desc>
- </func>
-
-
- <func>
<name>start() -> </name>
<name>start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the Ssh application. </fsummary>
@@ -356,21 +377,6 @@
</desc>
</func>
- <func>
- <name>verify_data(Data, Signature, Algorithm) -> ok | {error, Reason}</name>
- <fsummary> </fsummary>
- <type>
- <v> Data = binary()</v>
- <v> Algorithm = "ssh-rsa"</v>
- <v> Signature = binary()</v>
- <v> Reason = term()</v>
- </type>
- <desc>
- <p>Verifies the supplied binary against the binary signature.
- </p>
- </desc>
- </func>
-
</funcs>
</erlref>
diff --git a/lib/ssh/examples/Makefile b/lib/ssh/examples/Makefile
index 5f17542fb8..84c7edac8c 100644
--- a/lib/ssh/examples/Makefile
+++ b/lib/ssh/examples/Makefile
@@ -69,8 +69,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/ssh/src/DSS.asn1 b/lib/ssh/src/DSS.asn1
deleted file mode 100755
index 77aca3808b..0000000000
--- a/lib/ssh/src/DSS.asn1
+++ /dev/null
@@ -1,20 +0,0 @@
-DSS DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- EXPORTS ALL
--- All types and values defined in this module are exported for use
--- in other ASN.1 modules.
-
-DSAPrivateKey ::= SEQUENCE {
- version INTEGER,
- p INTEGER, -- p
- q INTEGER, -- q
- g INTEGER, -- q
- y INTEGER, -- y
- x INTEGER -- x
-}
-
-END
-
-
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index e7cf2c6723..b8eecd3fa2 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2010. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The 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,16 +36,22 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
# Common Macros
# ----------------------------------------------------
+# Behaviour (api) modules are first so they are compiled when
+# the compiler reaches a callback module using them.
+BEHAVIOUR_MODULES= \
+ ssh_sftpd_file_api \
+ ssh_channel \
+ ssh_key_api
+
MODULES= \
ssh \
ssh_sup \
sshc_sup \
sshd_sup \
- ssh_channel \
+ ssh_connection_sup \
ssh_connection \
ssh_connection_handler \
ssh_connection_manager \
- ssh_connection_controler \
ssh_shell \
ssh_system_sup \
ssh_subsystem_sup \
@@ -56,27 +62,27 @@ MODULES= \
ssh_auth\
ssh_bits \
ssh_cli \
- ssh_dsa \
ssh_file \
ssh_io \
ssh_math \
ssh_no_io \
- ssh_rsa \
ssh_sftp \
ssh_sftpd \
ssh_sftpd_file\
- ssh_sftpd_file_api \
ssh_transport \
ssh_userreg \
ssh_xfer
PUBLIC_HRL_FILES= ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
-ERL_FILES= $(MODULES:%=%.erl) $(ASN_ERLS)
+ERL_FILES= \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
+
-ALL_MODULES= $(MODULES) $(ASN_MODULES)
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-TARGET_FILES= $(ALL_MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
APP_FILE= ssh.app
APPUP_FILE= ssh.appup
@@ -87,50 +93,36 @@ APP_TARGET= $(EBIN)/$(APP_FILE)
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-ASN_MODULES = PKCS-1 DSS
-ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-ASN_ERLS = $(ASN_MODULES:%=%.erl)
-ASN_HRLS = $(ASN_MODULES:%=%.hrl)
-ASN_DBS = $(ASN_MODULES:%=%.asn1db)
-ASN_TABLES = $(ASN_MODULES:%=%.table)
-
-ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +inline
-
-INTERNAL_HRL_FILES = $(ASN_HRLS) ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
+INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -pa$(EBIN)
+EXTRA_ERLC_FLAGS = +warn_unused_vars
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
+ -pz $(EBIN) \
+ -pz $(ERL_TOP)/lib/public_key/ebin \
+ $(EXTRA_ERLC_FLAGS)
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug: ERLC_FLAGS += -Ddebug
+debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
- rm -f $(TARGET_FILES)
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
rm -f errs core *~
- rm -f $(ASN_ERLS) $(ASN_HRLS) $(ASN_DBS)
-$(TARGET_FILES): ssh.hrl
-
-# $(EBIN)/ssh_sftpd_file.$(EMULATOR): ERLC_FLAGS += -pa$(EBIN)
-# $(EBIN)/ssh_sftpd_file.$(EMULATOR): $(EBIN)/ssh_sftpd_file_api.$(EMULATOR)
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-%.erl %.hrl: %.asn1
- $(ERLC) $(ASN_FLAGS) $<
-
-$(EBIN)/ssh_file.$(EMULATOR) $(EBIN)/ssh_rsa.$(EMULATOR): $(ASN_HRLS)
docs:
@@ -140,12 +132,13 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(PUBLIC_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) \
+ $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(PUBLIC_HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/ssh/src/PKCS-1.asn1 b/lib/ssh/src/PKCS-1.asn1
deleted file mode 100755
index e7d6b18c63..0000000000
--- a/lib/ssh/src/PKCS-1.asn1
+++ /dev/null
@@ -1,116 +0,0 @@
-PKCS-1 {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)
- modules(0) pkcs-1(1)
-}
-
--- $Revision: 1.1 $
-
-DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- IMPORTS id-sha256, id-sha384, id-sha512
--- FROM NIST-SHA2 {
--- joint-iso-itu-t(2) country(16) us(840) organization(1)
--- gov(101) csor(3) nistalgorithm(4) modules(0) sha2(1)
--- };
-
-pkcs-1 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1
-}
-
-rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
-
-id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 }
-
-id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 }
-
-id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
-
-md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
-md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
-
-id-sha1 OBJECT IDENTIFIER ::= {
- iso(1) identified-organization(3) oiw(14) secsig(3)
- algorithms(2) 26
-}
-
-id-md2 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
-}
-
-id-md5 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
-}
-
-id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
-
-
-RSAPublicKey ::= SEQUENCE {
- modulus INTEGER, -- n
- publicExponent INTEGER -- e
-}
-
-RSAPrivateKey ::= SEQUENCE {
- version Version,
- modulus INTEGER, -- n
- publicExponent INTEGER, -- e
- privateExponent INTEGER, -- d
- prime1 INTEGER, -- p
- prime2 INTEGER, -- q
- exponent1 INTEGER, -- d mod (p-1)
- exponent2 INTEGER, -- d mod (q-1)
- coefficient INTEGER, -- (inverse of q) mod p
- otherPrimeInfos OtherPrimeInfos OPTIONAL
-}
-
-Version ::= INTEGER { two-prime(0), multi(1) }
- (CONSTRAINED BY {
- -- version must be multi if otherPrimeInfos present --
- })
-
-OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
-
-OtherPrimeInfo ::= SEQUENCE {
- prime INTEGER, -- ri
- exponent INTEGER, -- di
- coefficient INTEGER -- ti
-}
-
-Algorithm ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters ANY DEFINED BY algorithm OPTIONAL
-}
-
-AlgorithmNull ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters NULL
-}
-
-
-RSASSA-PSS-params ::= SEQUENCE {
- hashAlgorithm [0] Algorithm, -- DEFAULT sha1,
- maskGenAlgorithm [1] Algorithm, -- DEFAULT mgf1SHA1,
- saltLength [2] INTEGER DEFAULT 20,
- trailerField [3] TrailerField DEFAULT trailerFieldBC
-}
-
-TrailerField ::= INTEGER { trailerFieldBC(1) }
-
-DigestInfo ::= SEQUENCE {
- digestAlgorithm Algorithm,
- digest OCTET STRING
-}
-
-DigestInfoNull ::= SEQUENCE {
- digestAlgorithm AlgorithmNull,
- digest OCTET STRING
-}
-
-
-END -- PKCS1Definitions
-
diff --git a/lib/ssh/src/prebuild.skip b/lib/ssh/src/prebuild.skip
deleted file mode 100644
index 1d7552d98d..0000000000
--- a/lib/ssh/src/prebuild.skip
+++ /dev/null
@@ -1,2 +0,0 @@
-DSS.asn1db
-PKCS-1.asn1db
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 8a3e15841f..316c09eb06 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -3,9 +3,7 @@
{application, ssh,
[{description, "SSH-2 for Erlang/OTP"},
{vsn, "%VSN%"},
- {modules, ['DSS',
- 'PKCS-1',
- ssh,
+ {modules, [ssh,
ssh_app,
ssh_acceptor,
ssh_acceptor_sup,
@@ -17,16 +15,15 @@
ssh_connection,
ssh_connection_handler,
ssh_connection_manager,
- ssh_connection_controler,
+ ssh_connection_sup,
ssh_shell,
sshc_sup,
sshd_sup,
- ssh_dsa,
ssh_file,
ssh_io,
+ ssh_key_api,
ssh_math,
ssh_no_io,
- ssh_rsa,
ssh_sftp,
ssh_sftpd,
ssh_sftpd_file,
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 150b7d86dd..0542054596 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,22 +18,12 @@
%%
{"%VSN%",
- [
- {"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\\.*">>, [{restart_application, ssh}]},
+ {<<"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\\.*">>, [{restart_application, ssh}]},
+ {<<"1\\.*">>, [{restart_application, ssh}]}
]
}.
-
-
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index cada109df0..85f5f680e6 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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("ssh.hrl").
-include("ssh_connect.hrl").
+-include_lib("public_key/include/public_key.hrl").
-export([start/0, start/1, stop/0, connect/3, connect/4, close/1, connection_info/2,
channel_info/3,
@@ -30,6 +31,9 @@
stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2,
shell/1, shell/2, shell/3]).
+-deprecated({sign_data, 2, next_major_release}).
+-deprecated({verify_data, 3, next_major_release}).
+
-export([sign_data/2, verify_data/3]).
%%--------------------------------------------------------------------
@@ -68,17 +72,25 @@ stop() ->
connect(Host, Port, Options) ->
connect(Host, Port, Options, infinity).
connect(Host, Port, Options, Timeout) ->
- {SocketOpts, Opts} = handle_options(Options),
- DisableIpv6 = proplists:get_value(ip_v6_disabled, Opts, false),
- Inet = inetopt(DisableIpv6),
+ case handle_options(Options) of
+ {error, _Reason} = Error ->
+ Error;
+ {SocketOptions, SshOptions} ->
+ DisableIpv6 = proplists:get_value(ip_v6_disabled, SshOptions, false),
+ Inet = inetopt(DisableIpv6),
+ do_connect(Host, Port, [Inet | SocketOptions],
+ [{host, Host} | SshOptions], Timeout, DisableIpv6)
+ end.
+
+do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) ->
try sshc_sup:start_child([[{address, Host}, {port, Port},
- {role, client},
- {channel_pid, self()},
- {socket_opts, [Inet | SocketOpts]},
- {ssh_opts, [{host, Host}| Opts]}]]) of
+ {role, client},
+ {channel_pid, self()},
+ {socket_opts, SocketOptions},
+ {ssh_opts, SshOptions}]]) of
{ok, ConnectionSup} ->
{ok, Manager} =
- ssh_connection_controler:connection_manager(ConnectionSup),
+ ssh_connection_sup:connection_manager(ConnectionSup),
MRef = erlang:monitor(process, Manager),
receive
{Manager, is_connected} ->
@@ -89,6 +101,10 @@ connect(Host, Port, Options, Timeout) ->
%% might return undefined as the connection manager
%% could allready have terminated, so we will not
%% match the Manager in this case
+ {_, not_connected, {error, econnrefused}} when DisableIpv6 == false ->
+ do_demonitor(MRef, Manager),
+ do_connect(Host, Port, proplists:delete(inet6, SocketOptions),
+ SshOptions, Timeout, true);
{_, not_connected, {error, Reason}} ->
do_demonitor(MRef, Manager),
{error, Reason};
@@ -185,7 +201,7 @@ daemon(HostAddr, Port, Options0) ->
{HostAddr, inet6,
[{ip, HostAddr} | Options1]}
end,
- start_daemon(Host, Port, [{role, server} | Options], Inet).
+ start_daemon(Host, Port, Options, Inet).
%%--------------------------------------------------------------------
%% Function: stop_listener(SysRef) -> ok
@@ -247,48 +263,18 @@ shell(Host, Port, Options) ->
Error
end.
-
-%%--------------------------------------------------------------------
-%% Function: sign_data(Data, Algorithm) -> binary() |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH key to sign data.
-%%--------------------------------------------------------------------
-sign_data(Data, Algorithm) when is_binary(Data) ->
- case ssh_file:private_identity_key(Algorithm,[]) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- ssh_rsa:sign(Key, Data);
- Error ->
- Error
- end.
-
-%%--------------------------------------------------------------------
-%% Function: verify_data(Data, Signature, Algorithm) -> ok |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Signature = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH signature to verify data.
-%%--------------------------------------------------------------------
-verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
- case ssh_file:public_identity_key(Algorithm, []) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- ssh_rsa:verify(Key, Data, Signature);
- Error ->
- Error
- end.
-
-
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
start_daemon(Host, Port, Options, Inet) ->
- {SocketOpts, Opts} = handle_options(Options),
+ case handle_options(Options) of
+ {error, _Reason} = Error ->
+ Error;
+ {SocketOptions, SshOptions}->
+ do_start_daemon(Host, Port,[{role, server} |SshOptions] , [Inet | SocketOptions])
+ end.
+
+do_start_daemon(Host, Port, Options, SocketOptions) ->
case ssh_system_sup:system_supervisor(Host, Port) of
undefined ->
%% TODO: It would proably make more sense to call the
@@ -296,8 +282,8 @@ start_daemon(Host, Port, Options, Inet) ->
%% monent. The name is a legacy name!
try sshd_sup:start_child([{address, Host},
{port, Port}, {role, server},
- {socket_opts, [Inet | SocketOpts]},
- {ssh_opts, Opts}]) of
+ {socket_opts, SocketOptions},
+ {ssh_opts, Options}]) of
{ok, SysSup} ->
{ok, SysSup};
{error, {already_started, _}} ->
@@ -316,69 +302,205 @@ start_daemon(Host, Port, Options, Inet) ->
end.
handle_options(Opts) ->
- handle_options(proplists:unfold(Opts), [], []).
-handle_options([], SockOpts, Opts) ->
- {SockOpts, Opts};
-%% TODO: Could do some type checks here on plain ssh-opts
-handle_options([{system_dir, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{user_dir, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{user_dir_fun, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{silently_accept_hosts, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{user_interaction, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{public_key_alg, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{connect_timeout, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{user, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{password, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{user_passwords, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{pwdfun, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{user_auth, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{key_cb, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{role, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{channel, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{compression, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{allow_user_interaction, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{infofun, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{connectfun, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{disconnectfun , _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{failfun, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{ip_v6_disabled, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]);
-handle_options([{ip, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, [Opt |SockOpts], Opts);
-handle_options([{ifaddr, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, [Opt |SockOpts], Opts);
-handle_options([{fd, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, [Opt | SockOpts], Opts);
-handle_options([{nodelay, _} = Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, [Opt | SockOpts], Opts);
-handle_options([Opt | Rest], SockOpts, Opts) ->
- handle_options(Rest, SockOpts, [Opt | Opts]).
+ try handle_option(proplists:unfold(Opts), [], []) of
+ {_,_} = Options ->
+ Options
+ catch
+ throw:Error ->
+ Error
+ end.
+
+handle_option([], SocketOptions, SshOptions) ->
+ {SocketOptions, SshOptions};
+handle_option([{system_dir, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{user_dir, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{user_dir_fun, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{silently_accept_hosts, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{user_interaction, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{public_key_alg, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{connect_timeout, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{user, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{dsa_pass_phrase, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{rsa_pass_phrase, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{password, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{user_passwords, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{pwdfun, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{user_auth, _} = Opt | Rest],SocketOptions, SshOptions ) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{key_cb, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{role, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{compression, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+%%Backwards compatibility
+handle_option([{allow_user_interaction, Value} | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option({user_interaction, Value}) | SshOptions]);
+handle_option([{infofun, _} = Opt | Rest],SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{connectfun, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{disconnectfun, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{failfun, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{ip_v6_disabled, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{transport, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{subsystems, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{ssh_cli, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{shell, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{exec, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{auth_methods, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions).
+
+handle_ssh_option({system_dir, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({user_dir, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({user_dir_fun, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({silently_accept_hosts, Value} = Opt) when Value == true; Value == false ->
+ Opt;
+handle_ssh_option({user_interaction, Value} = Opt) when Value == true; Value == false ->
+ Opt;
+handle_ssh_option({public_key_alg, Value} = Opt) when Value == ssh_rsa; Value == ssh_dsa ->
+ Opt;
+handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity ->
+ Opt;
+handle_ssh_option({user, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({dsa_pass_phrase, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({rsa_pass_phrase, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({password, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({user_passwords, Value} = Opt) when is_list(Value)->
+ Opt;
+handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({user_auth, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) ->
+ Opt;
+handle_ssh_option({compression, Value} = Opt) when is_atom(Value) ->
+ Opt;
+handle_ssh_option({exec, {Module, Function, _}} = Opt) when is_atom(Module),
+ is_atom(Function) ->
+
+ Opt;
+handle_ssh_option({auth_methods, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({infofun, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({connectfun, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({disconnectfun , Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({failfun, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option({ip_v6_disabled, Value} = Opt) when Value == true;
+ Value == false ->
+ Opt;
+handle_ssh_option({transport, {Protocol, Cb, ClosTag}} = Opt) when is_atom(Protocol),
+ is_atom(Cb),
+ is_atom(ClosTag) ->
+ Opt;
+handle_ssh_option({subsystems, Value} = Opt) when is_list(Value) ->
+ Opt;
+handle_ssh_option({ssh_cli, {Cb, _}}= Opt) when is_atom(Cb) ->
+ Opt;
+handle_ssh_option({shell, {Module, Function, _}} = Opt) when is_atom(Module),
+ is_atom(Function) ->
+ Opt;
+handle_ssh_option({shell, Value} = Opt) when is_function(Value) ->
+ Opt;
+handle_ssh_option(Opt) ->
+ throw({error, {eoptions, Opt}}).
+
+handle_inet_option({active, _} = Opt) ->
+ throw({error, {{eoptions, Opt}, "Ssh has built in flow control, "
+ "and activ is handled internaly user is not allowd"
+ "to specify this option"}});
+handle_inet_option({inet, _} = Opt) ->
+ throw({error, {{eoptions, Opt},"Is set internaly use ip_v6_disabled to"
+ " enforce iv4 in the server, client will fallback to ipv4 if"
+ " it can not use ipv6"}});
+handle_inet_option({reuseaddr, _} = Opt) ->
+ throw({error, {{eoptions, Opt},"Is set internaly user is not allowd"
+ "to specify this option"}});
+%% Option verified by inet
+handle_inet_option(Opt) ->
+ Opt.
%% Has IPv6 been disabled?
inetopt(true) ->
inet;
inetopt(false) ->
- inet6.
+ case gen_tcp:listen(0, [inet6, {ip, loopback}]) of
+ {ok, Dummyport} ->
+ gen_tcp:close(Dummyport),
+ inet6;
+ _ ->
+ inet
+ end.
+%%%
+%% Deprecated
+%%%
+%%--------------------------------------------------------------------
+%% Function: sign_data(Data, Algorithm) -> binary() |
+%% {error, Reason}
+%%
+%% Data = binary()
+%% Algorithm = "ssh-rsa"
+%%
+%% Description: Use SSH key to sign data.
+%%--------------------------------------------------------------------
+sign_data(Data, Algorithm) when is_binary(Data) ->
+ case ssh_file:user_key(Algorithm,[]) of
+ {ok, Key} when Algorithm == "ssh-rsa" ->
+ public_key:sign(Data, sha, Key);
+ Error ->
+ Error
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: verify_data(Data, Signature, Algorithm) -> ok |
+%% {error, Reason}
+%%
+%% Data = binary()
+%% Signature = binary()
+%% Algorithm = "ssh-rsa"
+%%
+%% Description: Use SSH signature to verify data.
+%%--------------------------------------------------------------------
+verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
+ case ssh_file:user_key(Algorithm, []) of
+ {ok, #'RSAPrivateKey'{publicExponent = E, modulus = N}} when Algorithm == "ssh-rsa" ->
+ public_key:verify(Data, sha, Signature, #'RSAPublicKey'{publicExponent = E, modulus = N});
+ Error ->
+ Error
+ end.
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index ac249b05e3..da5750b6c3 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,18 +54,6 @@
-define(string(X), << ?STRING(list_to_binary(X)) >> ).
-define(binary(X), << ?STRING(X) >>).
--ifdef(debug).
--define(dbg(Debug, Fmt, As),
- case (Debug) of
- true ->
- io:format([$# | (Fmt)], (As));
- _ ->
- ok
- end).
--else.
--define(dbg(Debug, Fmt, As), ok).
--endif.
-
-define(SSH_CIPHER_NONE, 0).
-define(SSH_CIPHER_3DES, 3).
-define(SSH_CIPHER_AUTHFILE, ?SSH_CIPHER_3DES).
@@ -138,7 +126,8 @@
userauth_quiet_mode, % boolean()
userauth_supported_methods , %
userauth_methods,
- userauth_preference
+ userauth_preference,
+ available_host_keys
}).
-record(alg,
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index 59fbd24cf5..d023656c32 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -86,11 +86,11 @@ handle_connection(Callback, Address, Port, Options, Socket) ->
{ok, SubSysSup} = ssh_system_sup:start_subsystem(SystemSup, Options),
ConnectionSup = ssh_system_sup:connection_supervisor(SystemSup),
{ok, Pid} =
- ssh_connection_controler:start_manager_child(ConnectionSup,
- [server, Socket, Options, SubSysSup]),
+ ssh_connection_sup:start_manager_child(ConnectionSup,
+ [server, Socket, Options]),
Callback:controlling_process(Socket, Pid),
SshOpts = proplists:get_value(ssh_opts, Options),
- Pid ! {start_connection, server, [Address, Port, Socket, SshOpts]}.
+ Pid ! {start_connection, server, [Address, Port, Socket, SshOpts, SubSysSup]}.
handle_error(timeout) ->
ok;
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 9dbd95886e..aa452a8e09 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,8 +21,9 @@
-module(ssh_auth).
--include("ssh.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include("ssh.hrl").
-include("ssh_auth.hrl").
-include("ssh_transport.hrl").
@@ -36,18 +37,21 @@
%%--------------------------------------------------------------------
%%% Internal application API
%%--------------------------------------------------------------------
-publickey_msg([Cb, #ssh{user = User,
+publickey_msg([Alg, #ssh{user = User,
session_id = SessionId,
service = Service,
opts = Opts} = Ssh]) ->
+
+ Hash = sha, %% Maybe option?!
ssh_bits:install_messages(userauth_pk_messages()),
- Alg = Cb:alg_name(),
- case ssh_file:private_identity_key(Alg, Opts) of
- {ok, PrivKey} ->
- PubKeyBlob = ssh_file:encode_public_key(PrivKey),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:user_key(Alg, Opts) of
+ {ok, Key} ->
+ PubKeyBlob = encode_public_key(Key),
SigData = build_sig_data(SessionId,
- User, Service, Alg, PubKeyBlob),
- Sig = Cb:sign(PrivKey, SigData),
+ User, Service, PubKeyBlob, Alg),
+ Sig = ssh_transport:sign(SigData, Hash, Key),
SigBlob = list_to_binary([?string(Alg), ?binary(Sig)]),
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
@@ -58,8 +62,8 @@ publickey_msg([Cb, #ssh{user = User,
?binary(PubKeyBlob),
?binary(SigBlob)]},
Ssh);
- _Error ->
- not_ok
+ _Error ->
+ not_ok
end.
password_msg([#ssh{opts = Opts, io_cb = IoCb,
@@ -67,29 +71,40 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,
ssh_bits:install_messages(userauth_passwd_messages()),
Password = case proplists:get_value(password, Opts) of
undefined ->
- IoCb:read_password("ssh password: ");
+ user_interaction(IoCb);
PW ->
PW
end,
- ssh_transport:ssh_packet(
- #ssh_msg_userauth_request{user = User,
- service = Service,
- method = "password",
- data =
- <<?BOOLEAN(?FALSE),
- ?STRING(list_to_binary(Password))>>},
- Ssh).
+ case Password of
+ not_ok ->
+ not_ok;
+ _ ->
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_request{user = User,
+ service = Service,
+ method = "password",
+ data =
+ <<?BOOLEAN(?FALSE),
+ ?STRING(list_to_binary(Password))>>},
+ Ssh)
+ end.
+
+user_interaction(ssh_no_io) ->
+ not_ok;
+user_interaction(IoCb) ->
+ IoCb:read_password("ssh password: ").
+
%% See RFC 4256 for info on keyboard-interactive
keyboard_interactive_msg([#ssh{user = User,
- service = Service} = Ssh]) ->
+ service = Service} = Ssh]) ->
ssh_bits:install_messages(userauth_keyboard_interactive_messages()),
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
service = Service,
method = "keyboard-interactive",
data = << ?STRING(<<"">>),
- ?STRING(<<>>) >> },
+ ?STRING(<<>>) >> },
Ssh).
service_request_msg(Ssh) ->
@@ -103,12 +118,11 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
service = "ssh-connection",
method = "none",
data = <<>>},
- CbFirst = proplists:get_value(public_key_alg, Opts,
- ?PREFERRED_PK_ALG),
- CbSecond = other_cb(CbFirst),
- AllowUserInt = proplists:get_value(allow_user_interaction, Opts,
- true),
- Prefs = method_preference(CbFirst, CbSecond, AllowUserInt),
+ FirstAlg = algorithm(proplists:get_value(public_key_alg, Opts,
+ ?PREFERRED_PK_ALG)),
+ SecondAlg = other_alg(FirstAlg),
+ AllowUserInt = proplists:get_value(user_interaction, Opts, true),
+ Prefs = method_preference(FirstAlg, SecondAlg, AllowUserInt),
ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
userauth_preference = Prefs,
userauth_methods = none,
@@ -192,12 +206,12 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
?TRUE ->
case verify_sig(SessionId, User, "ssh-connection", Alg,
KeyBlob, SigWLen, Opts) of
- ok ->
+ true ->
{authorized, User,
ssh_transport:ssh_packet(
#ssh_msg_userauth_success{}, Ssh)};
- {error, Reason} ->
- {not_authorized, {User, {error, Reason}},
+ false ->
+ {not_authorized, {User, {error, "Invalid signature"}},
ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
authentications="publickey,password",
partial_success = false}, Ssh)}
@@ -228,7 +242,6 @@ handle_userauth_info_request(
PromptInfos = decode_keyboard_interactive_prompts(NumPrompts,Data),
Resps = keyboard_interact_get_responses(IoCb, Opts,
Name, Instr, PromptInfos),
- %%?dbg(true, "keyboard_interactive_reply: resps=~n#~p ~n", [Resps]),
RespBin = list_to_binary(
lists:map(fun(S) -> <<?STRING(list_to_binary(S))>> end,
Resps)),
@@ -263,15 +276,15 @@ userauth_messages() ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-method_preference(Callback1, Callback2, true) ->
- [{"publickey", ?MODULE, publickey_msg, [Callback1]},
- {"publickey", ?MODULE, publickey_msg,[Callback2]},
+method_preference(Alg1, Alg2, true) ->
+ [{"publickey", ?MODULE, publickey_msg, [Alg1]},
+ {"publickey", ?MODULE, publickey_msg,[Alg2]},
{"password", ?MODULE, password_msg, []},
{"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}
];
-method_preference(Callback1, Callback2, false) ->
- [{"publickey", ?MODULE, publickey_msg, [Callback1]},
- {"publickey", ?MODULE, publickey_msg,[Callback2]},
+method_preference(Alg1, Alg2, false) ->
+ [{"publickey", ?MODULE, publickey_msg, [Alg1]},
+ {"publickey", ?MODULE, publickey_msg,[Alg2]},
{"password", ?MODULE, password_msg, []}
].
@@ -295,7 +308,6 @@ user_name(Opts) ->
end.
check_password(User, Password, Opts) ->
- %%?dbg(true, " ~p ~p ~p ~n", [User, Password, Opts]),
case proplists:get_value(pwdfun, Opts) of
undefined ->
Static = get_password_option(Opts, User),
@@ -312,25 +324,22 @@ get_password_option(Opts, User) ->
end.
verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) ->
- case ssh_file:lookup_user_key(User, Alg, Opts) of
- {ok, OurKey} ->
- {ok, Key} = ssh_file:decode_public_key_v2(KeyBlob, Alg),
- case OurKey of
- Key ->
- NewSig = build_sig_data(SessionId,
- User, Service, Alg, KeyBlob),
- <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
- <<?UINT32(AlgLen), _Alg:AlgLen/binary,
- ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
- M = alg_to_module(Alg),
- M:verify(OurKey, NewSig, Sig);
- _ ->
- {error, key_unacceptable}
- end;
- Error -> Error
+ {ok, Key} = decode_public_key_v2(KeyBlob, Alg),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:is_auth_key(Key, User, Alg, Opts) of
+ true ->
+ PlainText = build_sig_data(SessionId, User,
+ Service, KeyBlob, Alg),
+ <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
+ <<?UINT32(AlgLen), _Alg:AlgLen/binary,
+ ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
+ ssh_transport:verify(PlainText, sha, Sig, Key);
+ false ->
+ false
end.
-build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
+build_sig_data(SessionId, User, Service, KeyBlob, Alg) ->
Sig = [?binary(SessionId),
?SSH_MSG_USERAUTH_REQUEST,
?string(User),
@@ -341,6 +350,11 @@ build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
?binary(KeyBlob)],
list_to_binary(Sig).
+algorithm(ssh_rsa) ->
+ "ssh-rsa";
+algorithm(ssh_dsa) ->
+ "ssh-dss".
+
decode_keyboard_interactive_prompts(NumPrompts, Data) ->
Types = lists:append(lists:duplicate(NumPrompts, [string, boolean])),
pairwise_tuplify(ssh_bits:decode(Data, Types)).
@@ -412,12 +426,28 @@ userauth_pk_messages() ->
binary]} % key blob
].
-alg_to_module("ssh-dss") ->
- ssh_dsa;
-alg_to_module("ssh-rsa") ->
- ssh_rsa.
-
-other_cb(ssh_rsa) ->
- ssh_dsa;
-other_cb(ssh_dsa) ->
- ssh_rsa.
+other_alg("ssh-rsa") ->
+ "ssh-dss";
+other_alg("ssh-dss") ->
+ "ssh-rsa".
+decode_public_key_v2(K_S, "ssh-rsa") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ {ok, #'RSAPublicKey'{publicExponent = E, modulus = N}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(K_S, "ssh-dss") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(_, _) ->
+ {error, bad_format}.
+
+encode_public_key(#'RSAPrivateKey'{publicExponent = E, modulus = N}) ->
+ ssh_bits:encode(["ssh-rsa",E,N], [string,mpint,mpint]);
+encode_public_key(#'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) ->
+ ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]).
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 3f0a06575c..5841f06d70 100755..100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -105,16 +105,12 @@ bignum(X) ->
install_messages(Codes) ->
foreach(fun({Name, Code, Ts}) ->
- %% ?dbg(true, "install msg: ~s = ~w ~w~n",
-%% [Name,Code,Ts]),
put({msg_name,Code}, {Name,Ts}),
put({msg_code,Name}, {Code,Ts})
end, Codes).
uninstall_messages(Codes) ->
foreach(fun({Name, Code, _Ts}) ->
- %% ?dbg(true, "uninstall msg: ~s = ~w ~w~n",
-%% [Name,Code,_Ts]),
erase({msg_name,Code}),
erase({msg_code,Name})
end, Codes).
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
index dcb2d69290..1938858420 100644
--- a/lib/ssh/src/ssh_channel.erl
+++ b/lib/ssh/src/ssh_channel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +23,23 @@
-include("ssh_connect.hrl").
+%%% Optional callbacks handle_call/3, handle_cast/2, handle_msg/2,
+%%% code_change/3
+%% Should be further specified later
+-callback init(Options::list()) ->
+ {ok, State::term()} | {ok, State::term(), Timeout::timeout()} |
+ {stop, Reason ::term()}.
+
+-callback terminate(term(), term()) -> term().
+
+-callback handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::integer(),
+ State::term()}.
-behaviour(gen_server).
%%% API
--export([behaviour_info/1, start/4, start/5, start_link/4, start_link/5, call/2, call/3,
+-export([start/4, start/5, start_link/4, start_link/5, call/2, call/3,
cast/2, reply/2, enter_loop/1]).
%% gen_server callbacks
@@ -50,17 +63,6 @@
%% API
%%====================================================================
-%%% Optionel callbacks handle_call/3, handle_cast/2, handle_msg/2,
-%%% code_change/3
-behaviour_info(callbacks) ->
- [
- {init, 1},
- {terminate, 2},
- {handle_ssh_msg, 2},
- {handle_msg, 2}
- ].
-
-
call(ChannelPid, Msg) ->
call(ChannelPid, Msg, infinity).
@@ -213,7 +215,7 @@ handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
close_sent = false} = State) ->
%% To be on the safe side, i.e. the manager has already been terminated.
(catch ssh_connection:close(ConnectionManager, ChannelId)),
- {stop, normal, State};
+ {stop, normal, State#state{close_sent = true}};
handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
channel_cb = Module,
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
index 34d4ff8fc1..932b0642f1 100755..100644
--- a/lib/ssh/src/ssh_connect.hrl
+++ b/lib/ssh/src/ssh_connect.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -253,7 +253,6 @@
-record(connection, {
requests = [], %% [{ChannelId, Pid}...] awaiting reply on request,
channel_cache,
- channel_pids = [],
port_bindings,
channel_id_seed,
cli_spec,
@@ -261,5 +260,6 @@
port,
options,
exec,
- sub_system_supervisor
+ sub_system_supervisor,
+ connection_supervisor
}).
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 7b9e9185bf..c46f799b6d 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -720,14 +720,17 @@ handle_msg(#ssh_msg_channel_request{request_type = "env"},
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = _Other,
- want_reply = WantReply}, Connection,
+ want_reply = WantReply}, #connection{channel_cache = Cache} = Connection,
ConnectionPid, _) ->
- ?dbg(true, "ssh_msg ssh_msg_channel_request: Other=~p\n",
- [_Other]),
if WantReply == true ->
- FailMsg = channel_failure_msg(ChannelId),
- {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
- Connection};
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = RemoteId} ->
+ FailMsg = channel_failure_msg(RemoteId),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
+ Connection};
+ undefined -> %% Chanel has been closed
+ {noreply, Connection}
+ end;
true ->
{noreply, Connection}
end;
@@ -746,8 +749,8 @@ handle_msg(#ssh_msg_global_request{name = _Type,
%%% This transport message will also be handled at the connection level
handle_msg(#ssh_msg_disconnect{code = Code,
- description = Description,
- language = _Lang },
+ description = Description,
+ language = _Lang },
#connection{channel_cache = Cache} = Connection0, _, _) ->
{Connection, Replies} =
ssh_channel:cache_foldl(fun(Channel, {Connection1, Acc}) ->
@@ -781,7 +784,7 @@ handle_cli_msg(#connection{channel_cache = Cache} = Connection0,
handle_cli_msg(Connection0, _, Channel, Reply0) ->
{Reply, Connection} = reply_msg(Channel, Connection0, Reply0),
{{replies, [Reply]}, Connection}.
-
+
channel_eof_msg(ChannelId) ->
#ssh_msg_channel_eof{recipient_channel = ChannelId}.
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 00b30e5434..5b3d1b8a1b 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,7 @@
-export([hello/2, kexinit/2, key_exchange/2, new_keys/2,
userauth/2, connected/2]).
--export([init/1, state_name/3, handle_event/3,
+-export([init/1, handle_event/3,
handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
%% spawn export
@@ -106,22 +106,28 @@ peer_address(ConnectionHandler) ->
%% initialize.
%%--------------------------------------------------------------------
init([Role, Manager, Socket, SshOpts]) ->
+ process_flag(trap_exit, true),
{NumVsn, StrVsn} = ssh_transport:versions(Role, SshOpts),
ssh_bits:install_messages(ssh_transport:transport_messages(NumVsn)),
{Protocol, Callback, CloseTag} =
proplists:get_value(transport, SshOpts, {tcp, gen_tcp, tcp_closed}),
- Ssh = init_ssh(Role, NumVsn, StrVsn, SshOpts, Socket),
- {ok, hello, #state{ssh_params =
- Ssh#ssh{send_sequence = 0, recv_sequence = 0},
- socket = Socket,
- decoded_data_buffer = <<>>,
- encoded_data_buffer = <<>>,
- transport_protocol = Protocol,
- transport_cb = Callback,
- transport_close_tag = CloseTag,
- manager = Manager,
- opts = SshOpts
- }}.
+ try init_ssh(Role, NumVsn, StrVsn, SshOpts, Socket) of
+ Ssh ->
+ {ok, hello, #state{ssh_params =
+ Ssh#ssh{send_sequence = 0, recv_sequence = 0},
+ socket = Socket,
+ decoded_data_buffer = <<>>,
+ encoded_data_buffer = <<>>,
+ transport_protocol = Protocol,
+ transport_cb = Callback,
+ transport_close_tag = CloseTag,
+ manager = Manager,
+ opts = SshOpts
+ }}
+ catch
+ exit:Reason ->
+ {stop, {shutdown, Reason}}
+ end.
%%--------------------------------------------------------------------
%% Function:
%% state_name(Event, State) -> {next_state, NextStateName, NextState}|
@@ -179,7 +185,12 @@ kexinit({#ssh_msg_kexinit{} = Kex, Payload},
next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State)
end.
key_exchange(#ssh_msg_kexdh_init{} = Msg,
@@ -192,7 +203,12 @@ key_exchange(#ssh_msg_kexdh_init{} = Msg,
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State)
end;
key_exchange(#ssh_msg_kexdh_reply{} = Msg,
@@ -203,7 +219,12 @@ key_exchange(#ssh_msg_kexdh_reply{} = Msg,
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State)
end;
key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg,
@@ -216,7 +237,12 @@ key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg,
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State)
end;
key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg,
@@ -227,7 +253,12 @@ key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg,
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State)
end;
key_exchange(#ssh_msg_kex_dh_gex_reply{} = Msg,
#state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
@@ -237,7 +268,12 @@ key_exchange(#ssh_msg_kex_dh_gex_reply{} = Msg,
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State)
end.
new_keys(#ssh_msg_newkeys{} = Msg, #state{ssh_params = Ssh0} = State0) ->
@@ -248,8 +284,12 @@ new_keys(#ssh_msg_newkeys{} = Msg, #state{ssh_params = Ssh0} = State0) ->
{next_state, NextStateName, next_packet(State)}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State0),
- {stop, normal, State0}
+ handle_disconnect(DisconnectMsg, State0);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = Desc,
+ language = "en"}, State0)
end.
userauth(#ssh_msg_service_request{name = "ssh-userauth"} = Msg,
@@ -262,7 +302,12 @@ userauth(#ssh_msg_service_request{name = "ssh-userauth"} = Msg,
{next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ description = Desc,
+ language = "en"}, State)
end;
userauth(#ssh_msg_service_accept{name = "ssh-userauth"},
@@ -284,7 +329,12 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection",
{next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ description = Desc,
+ language = "en"}, State)
end;
userauth(#ssh_msg_userauth_request{service = "ssh-connection",
@@ -307,7 +357,12 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection",
{next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ description = Desc,
+ language = "en"}, State)
end;
userauth(#ssh_msg_userauth_info_request{} = Msg,
@@ -319,7 +374,12 @@ userauth(#ssh_msg_userauth_info_request{} = Msg,
{next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ description = Desc,
+ language = "en"}, State)
end;
userauth(#ssh_msg_userauth_info_response{} = Msg,
@@ -330,7 +390,12 @@ userauth(#ssh_msg_userauth_info_response{} = Msg,
{next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
catch
#ssh_msg_disconnect{} = DisconnectMsg ->
- handle_disconnect(DisconnectMsg, State)
+ handle_disconnect(DisconnectMsg, State);
+ _:Error ->
+ Desc = log_error(Error),
+ handle_disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ description = Desc,
+ language = "en"}, State)
end;
userauth(#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client},
@@ -361,24 +426,11 @@ userauth(#ssh_msg_userauth_failure{authentications = Methodes},
%% The prefered authentication method failed try next method
userauth(#ssh_msg_userauth_failure{},
- #state{ssh_params = #ssh{role = client} = Ssh0,
- manager = Pid} = State) ->
+ #state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
case ssh_auth:userauth_request_msg(Ssh0) of
- {disconnect, Event, {Msg, _}} ->
- try
- send_msg(Msg, State),
- ssh_connection_manager:event(Pid, Event)
- catch
- exit:{noproc, _Reason} ->
- Report = io_lib:format("Connection Manager terminated: ~p~n",
- [Pid]),
- error_logger:info_report(Report);
- exit:Exit ->
- Report = io_lib:format("Connection Manager returned:~n~p~n~p~n",
- [Msg, Exit]),
- error_logger:info_report(Report)
- end,
- {stop, normal, State};
+ {disconnect, DisconnectMsg,{Msg, Ssh}} ->
+ send_msg(Msg, State),
+ handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh});
{Msg, Ssh} ->
send_msg(Msg, State),
{next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
@@ -398,25 +450,6 @@ connected({#ssh_msg_kexinit{}, _Payload} = Event, State) ->
kexinit(Event, State#state{renegotiate = true}).
%%--------------------------------------------------------------------
-%% Function:
-%% state_name(Event, From, State) -> {next_state, NextStateName, NextState} |
-%% {next_state, NextStateName,
-%% NextState, Timeout} |
-%% {reply, Reply, NextStateName, NextState}|
-%% {reply, Reply, NextStateName,
-%% NextState, Timeout} |
-%% {stop, Reason, NewState}|
-%% {stop, Reason, Reply, NewState}
-%% Description: There should be one instance of this function for each
-%% possible state name. Whenever a gen_fsm receives an event sent using
-%% gen_fsm:sync_send_event/2,3, the instance of this function with the same
-%% name as the current state name StateName is called to handle the event.
-%%--------------------------------------------------------------------
-state_name(_Event, _From, State) ->
- Reply = ok,
- {reply, Reply, state_name, State}.
-
-%%--------------------------------------------------------------------
%% Function:
%% handle_event(Event, StateName, State) -> {next_state, NextStateName,
%% NextState} |
@@ -566,10 +599,18 @@ handle_info({Protocol, Socket, Data}, Statename,
Statename, State);
handle_info({CloseTag, _Socket}, _StateName,
- #state{transport_close_tag = CloseTag, %%manager = Pid,
+ #state{transport_close_tag = CloseTag,
ssh_params = #ssh{role = _Role, opts = _Opts}} = State) ->
- %%ok = ssh_connection_manager:delivered(Pid),
- {stop, normal, State};
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_CONNECTION_LOST,
+ description = "Connection Lost",
+ language = "en"},
+ {stop, {shutdown, DisconnectMsg}, State};
+
+%%% So that terminate will be run when supervisor is shutdown
+handle_info({'EXIT', _Sup, Reason}, _StateName, State) ->
+ {stop, Reason, State};
+
handle_info(UnexpectedMessage, StateName, #state{ssh_params = SshParams} = State) ->
Msg = lists:flatten(io_lib:format(
"Unexpected message '~p' received in state '~p'\n"
@@ -581,7 +622,6 @@ handle_info(UnexpectedMessage, StateName, #state{ssh_params = SshParams} = State
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
@@ -596,22 +636,31 @@ terminate(normal, _, #state{transport_cb = Transport,
(catch Transport:close(Socket)),
ok;
-terminate(shutdown, _, State) ->
+%% Terminated as manager terminated
+terminate(shutdown, StateName, #state{ssh_params = Ssh0} = State) ->
DisconnectMsg =
#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Application disconnect",
+ description = "Application shutdown",
language = "en"},
- handle_disconnect(DisconnectMsg, State);
+ {SshPacket, Ssh} = ssh_transport:ssh_packet(DisconnectMsg, Ssh0),
+ send_msg(SshPacket, State),
+ terminate(normal, StateName, State#state{ssh_params = Ssh});
-terminate(Reason, _, State) ->
- Desc = io_lib:format("Erlang ssh connection handler failed with reason: "
- "~p , please report this to [email protected] \n",
- [Reason]),
+terminate({shutdown, #ssh_msg_disconnect{} = Msg}, StateName, #state{ssh_params = Ssh0, manager = Pid} = State) ->
+ {SshPacket, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
+ send_msg(SshPacket, State),
+ ssh_connection_manager:event(Pid, Msg),
+ terminate(normal, StateName, State#state{ssh_params = Ssh});
+terminate(Reason, StateName, #state{ssh_params = Ssh0, manager = Pid} = State) ->
+ log_error(Reason),
DisconnectMsg =
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_CONNECTION_LOST,
- description = Desc,
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Internal error",
language = "en"},
- handle_disconnect(DisconnectMsg, State).
+ {SshPacket, Ssh} = ssh_transport:ssh_packet(DisconnectMsg, Ssh0),
+ ssh_connection_manager:event(Pid, DisconnectMsg),
+ send_msg(SshPacket, State),
+ terminate(normal, StateName, State#state{ssh_params = Ssh}).
%%--------------------------------------------------------------------
%% Function:
@@ -637,16 +686,18 @@ init_ssh(client = Role, Vsn, Version, Options, Socket) ->
{ok, PeerAddr} = inet:peername(Socket),
PeerName = proplists:get_value(host, Options),
+ KeyCb = proplists:get_value(key_cb, Options, ssh_file),
#ssh{role = Role,
c_vsn = Vsn,
c_version = Version,
- key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ key_cb = KeyCb,
io_cb = IOCb,
userauth_quiet_mode = proplists:get_value(quiet_mode, Options, false),
opts = Options,
userauth_supported_methods = AuthMethods,
- peer = {PeerName, PeerAddr}
+ peer = {PeerName, PeerAddr},
+ available_host_keys = supported_host_keys(Role, KeyCb, Options)
};
init_ssh(server = Role, Vsn, Version, Options, Socket) ->
@@ -654,17 +705,48 @@ init_ssh(server = Role, Vsn, Version, Options, Socket) ->
AuthMethods = proplists:get_value(auth_methods, Options,
?SUPPORTED_AUTH_METHODS),
{ok, PeerAddr} = inet:peername(Socket),
-
+ KeyCb = proplists:get_value(key_cb, Options, ssh_file),
+
#ssh{role = Role,
s_vsn = Vsn,
s_version = Version,
- key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ key_cb = KeyCb,
io_cb = proplists:get_value(io_cb, Options, ssh_io),
opts = Options,
userauth_supported_methods = AuthMethods,
- peer = {undefined, PeerAddr}
+ peer = {undefined, PeerAddr},
+ available_host_keys = supported_host_keys(Role, KeyCb, Options)
}.
+supported_host_keys(client, _, _) ->
+ ["ssh-rsa", "ssh-dss"];
+supported_host_keys(server, KeyCb, Options) ->
+ lists:foldl(fun(Type, Acc) ->
+ case available_host_key(KeyCb, Type, Options) of
+ {error, _} ->
+ Acc;
+ Alg ->
+ [Alg | Acc]
+ end
+ end, [],
+ %% Prefered alg last so no need to reverse
+ ["ssh-dss", "ssh-rsa"]).
+
+available_host_key(KeyCb, "ssh-dss"= Alg, Opts) ->
+ case KeyCb:host_key('ssh-dss', Opts) of
+ {ok, _} ->
+ Alg;
+ Other ->
+ Other
+ end;
+available_host_key(KeyCb, "ssh-rsa" = Alg, Opts) ->
+ case KeyCb:host_key('ssh-rsa', Opts) of
+ {ok, _} ->
+ Alg;
+ Other ->
+ Other
+ end.
+
send_msg(Msg, #state{socket = Socket, transport_cb = Transport}) ->
Transport:send(Socket, Msg).
@@ -724,11 +806,8 @@ generate_event(<<?BYTE(Byte), _/binary>> = Msg, StateName,
next_packet(State),
{next_state, StateName, State}
catch
- exit:{noproc, _Reason} ->
- Report = io_lib:format("~p Connection Handler terminated: ~p~n",
- [self(), Pid]),
- error_logger:info_report(Report),
- {stop, normal, State0}
+ exit:{noproc, Reason} ->
+ {stop, {shutdown, Reason}, State0}
end;
generate_event(Msg, StateName, State0, EncData) ->
Event = ssh_bits:decode(Msg),
@@ -753,13 +832,18 @@ generate_event_new_state(#state{ssh_params =
next_packet(#state{decoded_data_buffer = <<>>,
encoded_data_buffer = Buff,
+ ssh_params = #ssh{decrypt_block_size = BlockSize},
socket = Socket,
- transport_protocol = Protocol} =
- State) when Buff =/= <<>> andalso size(Buff) >= 8 ->
- %% More data from the next packet has been received
- %% Fake a socket-recive message so that the data will be processed
- inet:setopts(Socket, [{active, once}]),
- self() ! {Protocol, Socket, <<>>},
+ transport_protocol = Protocol} = State) when Buff =/= <<>> ->
+ case size(Buff) >= erlang:max(8, BlockSize) of
+ true ->
+ %% Enough data from the next packet has been received to
+ %% decode the length indicator, fake a socket-recive
+ %% message so that the data will be processed
+ self() ! {Protocol, Socket, <<>>};
+ false ->
+ inet:setopts(Socket, [{active, once}])
+ end,
State;
next_packet(#state{socket = Socket} = State) ->
@@ -820,24 +904,8 @@ handle_ssh_packet(Length, StateName, #state{decoded_data_buffer = DecData0,
handle_disconnect(DisconnectMsg, State0)
end.
-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),
- ssh_connection_manager:event(Pid, Msg)
- catch
- exit:{noproc, _Reason} ->
- Report = io_lib:format("~p Connection Manager terminated: ~p~n",
- [self(), Pid]),
- error_logger:info_report(Report);
- exit:Exit ->
- Report = io_lib:format("Connection Manager returned:~n~p~n~p~n",
- [Msg, Exit]),
- error_logger:info_report(Report)
- end,
- (catch ssh_userreg:delete_user(Pid)),
- {stop, normal, State#state{ssh_params = Ssh}}.
+handle_disconnect(#ssh_msg_disconnect{} = Msg, State) ->
+ {stop, {shutdown, Msg}, State}.
counterpart_versions(NumVsn, StrVsn, #ssh{role = server} = Ssh) ->
Ssh#ssh{c_vsn = NumVsn , c_version = StrVsn};
@@ -895,3 +963,11 @@ ssh_info([peer | Rest], #ssh{peer = Peer} = SshParams, Acc) ->
ssh_info([ _ | Rest], SshParams, Acc) ->
ssh_info(Rest, SshParams, Acc).
+
+log_error(Reason) ->
+ Report = io_lib:format("Erlang ssh connection handler failed with reason: "
+ "~p ~n, Stacktace: ~p ~n"
+ "please report this to [email protected] \n",
+ [Reason, erlang:get_stacktrace()]),
+ error_logger:error_report(Report),
+ "Internal error".
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
index 9bfd5270da..e53cd4f4f7 100644
--- a/lib/ssh/src/ssh_connection_manager.erl
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +144,21 @@ adjust_window(ConnectionManager, Channel, Bytes) ->
cast(ConnectionManager, {adjust_window, Channel, Bytes}).
close(ConnectionManager, ChannelId) ->
- try call(ConnectionManager, {close, ChannelId}) of
- ok ->
+ case call(ConnectionManager, {close, ChannelId}) of
+ ok ->
ok;
- {error, channel_closed} ->
- ok
- catch
- exit:{noproc, _} ->
+ {error, channel_closed} ->
ok
- end.
+ end.
stop(ConnectionManager) ->
- try call(ConnectionManager, stop) of
+ case call(ConnectionManager, stop) of
ok ->
ok;
{error, channel_closed} ->
ok
- catch
- exit:{noproc, _} ->
- ok
end.
-
+
send(ConnectionManager, ChannelId, Type, Data, Timeout) ->
call(ConnectionManager, {data, ChannelId, Type, Data}, Timeout).
@@ -182,17 +176,15 @@ send_eof(ConnectionManager, ChannelId) ->
%% {stop, Reason}
%% Description: Initiates the server
%%--------------------------------------------------------------------
-init([server, _Socket, Opts, SubSysSup]) ->
+init([server, _Socket, Opts]) ->
process_flag(trap_exit, true),
ssh_bits:install_messages(ssh_connection:messages()),
- Cache = ssh_channel:cache_create(),
+ Cache = ssh_channel:cache_create(),
{ok, #state{role = server,
connection_state = #connection{channel_cache = Cache,
channel_id_seed = 0,
port_bindings = [],
- requests = [],
- channel_pids = [],
- sub_system_supervisor = SubSysSup},
+ requests = []},
opts = Opts,
connected = false}};
@@ -207,15 +199,14 @@ init([client, Opts]) ->
Options = proplists:get_value(ssh_opts, Opts),
ChannelPid = proplists:get_value(channel_pid, Opts),
self() !
- {start_connection, client, [Parent, Address, Port,
- ChannelPid, SocketOpts, Options]},
+ {start_connection, client, [Parent, Address, Port, SocketOpts, Options]},
{ok, #state{role = client,
client = ChannelPid,
connection_state = #connection{channel_cache = Cache,
channel_id_seed = 0,
port_bindings = [],
- requests = [],
- channel_pids = []},
+ connection_supervisor = Parent,
+ requests = []},
opts = Opts,
connected = false}}.
@@ -269,29 +260,25 @@ handle_call({ssh_msg, Pid, Msg}, From,
when Role == client andalso (not IsConnected) ->
lists:foreach(fun send_msg/1, Replies),
ClientPid ! {self(), not_connected, Reason},
- {stop, normal, State#state{connection = Connection}};
+ {stop, {shutdown, normal}, State#state{connection = Connection}};
{disconnect, Reason, {{replies, Replies}, Connection}} ->
lists:foreach(fun send_msg/1, Replies),
SSHOpts = proplists:get_value(ssh_opts, Opts),
disconnect_fun(Reason, SSHOpts),
- {stop, normal, State#state{connection_state = Connection}}
+ {stop, {shutdown, normal}, State#state{connection_state = Connection}}
catch
- exit:{noproc, Reason} ->
- Report = io_lib:format("Connection probably terminated:~n~p~n~p~n~p~n",
- [ConnectionMsg, Reason, erlang:get_stacktrace()]),
- error_logger:info_report(Report),
- {noreply, State};
- error:Error ->
- Report = io_lib:format("Connection message returned:~n~p~n~p~n~p~n",
- [ConnectionMsg, Error, erlang:get_stacktrace()]),
- error_logger:info_report(Report),
- {noreply, State};
- exit:Exit ->
- Report = io_lib:format("Connection message returned:~n~p~n~p~n~p~n",
- [ConnectionMsg, Exit, erlang:get_stacktrace()]),
- error_logger:info_report(Report),
- {noreply, State}
- end;
+ _:Error ->
+ {disconnect, Reason, {{replies, Replies}, Connection}} =
+ ssh_connection:handle_msg(
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Internal error",
+ language = "en"}, Connection0, undefined,
+ Role),
+ lists:foreach(fun send_msg/1, Replies),
+ SSHOpts = proplists:get_value(ssh_opts, Opts),
+ disconnect_fun(Reason, SSHOpts),
+ {stop, {shutdown, Error}, State#state{connection_state = Connection}}
+ end;
handle_call({global_request, Pid, _, _, _} = Request, From,
#state{connection_state =
@@ -341,7 +328,8 @@ handle_call({info, ChannelPid}, _From,
handle_call({open, ChannelPid, Type, InitialWindowSize, MaxPacketSize, Data},
From, #state{connection = Pid,
connection_state =
- #connection{channel_cache = Cache}} = State0) ->
+ #connection{channel_cache = Cache}} = State0) ->
+ erlang:monitor(process, ChannelPid),
{ChannelId, State1} = new_channel_id(State0),
Msg = ssh_connection:channel_open_msg(Type, ChannelId,
InitialWindowSize,
@@ -396,26 +384,27 @@ handle_call({close, ChannelId}, _,
#state{connection = Pid, connection_state =
#connection{channel_cache = Cache}} = State) ->
case ssh_channel:cache_lookup(Cache, ChannelId) of
- #channel{remote_id = Id} ->
+ #channel{remote_id = Id} = Channel ->
send_msg({connection_reply, Pid,
ssh_connection:channel_close_msg(Id)}),
+ ssh_channel:cache_update(Cache, Channel#channel{sent_close = true}),
{reply, ok, State};
undefined ->
{reply, ok, State}
end;
-handle_call(stop, _, #state{role = _client,
- client = _ChannelPid,
- connection = Pid} = State) ->
- DisconnectMsg =
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Application disconnect",
- language = "en"},
- (catch gen_fsm:send_all_state_event(Pid, DisconnectMsg)),
-% ssh_connection_handler:send(Pid, DisconnectMsg),
- {stop, normal, ok, State};
-handle_call(stop, _, State) ->
- {stop, normal, ok, State};
+handle_call(stop, _, #state{connection_state = Connection0,
+ role = Role,
+ opts = Opts} = State) ->
+ {disconnect, Reason, {{replies, Replies}, Connection}} =
+ ssh_connection:handle_msg(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "User closed down connection",
+ language = "en"}, Connection0, undefined,
+ Role),
+ lists:foreach(fun send_msg/1, Replies),
+ SSHOpts = proplists:get_value(ssh_opts, Opts),
+ disconnect_fun(Reason, SSHOpts),
+ {stop, normal, ok, State#state{connection_state = Connection}};
%% API violation make it the violaters problem
%% by ignoring it. The violating process will get
@@ -493,31 +482,33 @@ handle_cast({failure, ChannelId}, #state{connection = Pid} = State) ->
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info({start_connection, server,
- [Address, Port, Socket, Options]},
+ [Address, Port, Socket, Options, SubSysSup]},
#state{connection_state = CState} = State) ->
{ok, Connection} = ssh_transport:accept(Address, Port, Socket, Options),
Shell = proplists:get_value(shell, Options),
Exec = proplists:get_value(exec, Options),
CliSpec = proplists:get_value(ssh_cli, Options, {ssh_cli, [Shell]}),
+ ssh_connection_handler:send_event(Connection, socket_control),
{noreply, State#state{connection = Connection,
connection_state =
CState#connection{address = Address,
port = Port,
cli_spec = CliSpec,
options = Options,
- exec = Exec}}};
+ exec = Exec,
+ sub_system_supervisor = SubSysSup
+ }}};
handle_info({start_connection, client,
- [Parent, Address, Port, ChannelPid, SocketOpts, Options]},
- State) ->
+ [Parent, Address, Port, SocketOpts, Options]},
+ #state{client = Pid} = State) ->
case (catch ssh_transport:connect(Parent, Address,
Port, SocketOpts, Options)) of
{ok, Connection} ->
- erlang:monitor(process, ChannelPid),
{noreply, State#state{connection = Connection}};
Reason ->
- ChannelPid ! {self(), not_connected, Reason},
- {stop, normal, State}
+ Pid ! {self(), not_connected, Reason},
+ {stop, {shutdown, normal}, State}
end;
handle_info({ssh_cm, _Sender, Msg}, State0) ->
@@ -537,20 +528,13 @@ handle_info(ssh_connected, #state{role = client, client = Pid}
handle_info(ssh_connected, #state{role = server} = State) ->
{noreply, State#state{connected = true}};
-handle_info({'DOWN', _Ref, process, ChannelPid, normal}, State0) ->
- handle_down(handle_channel_down(ChannelPid, State0));
-
-handle_info({'DOWN', _Ref, process, ChannelPid, shutdown}, State0) ->
- handle_down(handle_channel_down(ChannelPid, State0));
-
-handle_info({'DOWN', _Ref, process, ChannelPid, Reason}, State0) ->
- Report = io_lib:format("Pid ~p DOWN ~p\n", [ChannelPid, Reason]),
- error_logger:error_report(Report),
- handle_down(handle_channel_down(ChannelPid, State0));
+%%% Handle that ssh channels user process goes down
+handle_info({'DOWN', _Ref, process, ChannelPid, _Reason}, State) ->
+ handle_down(handle_channel_down(ChannelPid, State));
-handle_info({'EXIT', _, _}, State) ->
- %% Handled in 'DOWN'
- {noreply, State}.
+%%% So that terminate will be run when supervisor is shutdown
+handle_info({'EXIT', _Sup, Reason}, State) ->
+ {stop, Reason, State}.
%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> void()
@@ -559,20 +543,19 @@ handle_info({'EXIT', _, _}, State) ->
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
%%--------------------------------------------------------------------
-terminate(Reason, #state{connection_state =
- #connection{requests = Requests,
- sub_system_supervisor = SubSysSup},
+terminate(_Reason, #state{role = client,
+ connection_state =
+ #connection{connection_supervisor = Supervisor}}) ->
+ sshc_sup:stop_child(Supervisor);
+
+terminate(_Reason, #state{role = server,
+ connection_state =
+ #connection{sub_system_supervisor = SubSysSup},
opts = Opts}) ->
- SSHOpts = proplists:get_value(ssh_opts, Opts),
- disconnect_fun(Reason, SSHOpts),
- (catch lists:foreach(fun({_, From}) ->
- gen_server:reply(From, {error, connection_closed})
- end, Requests)),
Address = proplists:get_value(address, Opts),
Port = proplists:get_value(port, Opts),
SystemSup = ssh_system_sup:system_supervisor(Address, Port),
- ssh_system_sup:stop_subsystem(SystemSup, SubSysSup),
- ok.
+ ssh_system_sup:stop_subsystem(SystemSup, SubSysSup).
%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
@@ -604,6 +587,10 @@ call(Pid, Msg, Timeout) ->
exit:{timeout, _} ->
{error, timeout};
exit:{normal, _} ->
+ {error, channel_closed};
+ exit:{{shutdown, _}, _} ->
+ {error, channel_closed};
+ exit:{noproc,_} ->
{error, channel_closed}
end.
@@ -617,16 +604,7 @@ decode_ssh_msg(Msg) ->
send_msg(Msg) ->
- case catch do_send_msg(Msg) of
- {'EXIT', Reason}->
- Report = io_lib:format("Connection Manager fail to send:~n~p~n"
- "Reason why it failed was:~n~p~n",
- [Msg, Reason]),
- error_logger:info_report(Report);
- _ ->
- ok
- end.
-
+ catch do_send_msg(Msg).
do_send_msg({channel_data, Pid, Data}) ->
Pid ! {ssh_cm, self(), Data};
do_send_msg({channel_requst_reply, From, Data}) ->
@@ -674,8 +652,8 @@ handle_down({{replies, Replies}, State}) ->
{noreply, State}.
handle_channel_down(ChannelPid, #state{connection_state =
- #connection{channel_cache = Cache}} =
- State) ->
+ #connection{channel_cache = Cache}} =
+ State) ->
ssh_channel:cache_foldl(
fun(Channel, Acc) when Channel#channel.user == ChannelPid ->
ssh_channel:cache_delete(Cache,
diff --git a/lib/ssh/src/ssh_connection_sup.erl b/lib/ssh/src/ssh_connection_sup.erl
new file mode 100644
index 0000000000..e3544af1c6
--- /dev/null
+++ b/lib/ssh/src/ssh_connection_sup.erl
@@ -0,0 +1,113 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 connection supervisor.
+%%----------------------------------------------------------------------
+
+-module(ssh_connection_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_handler_child/2, start_manager_child/2,
+ connection_manager/1]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link(?MODULE, [Args]).
+
+%% Will be called from the manager child process
+start_handler_child(Sup, Args) ->
+ [Spec] = child_specs(handler, Args),
+ supervisor:start_child(Sup, Spec).
+
+%% Will be called from the acceptor process
+start_manager_child(Sup, Args) ->
+ [Spec] = child_specs(manager, Args),
+ supervisor:start_child(Sup, Spec).
+
+connection_manager(SupPid) ->
+ Children = supervisor:which_children(SupPid),
+ {ok, ssh_connection_manager(Children)}.
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([Args]) ->
+ RestartStrategy = one_for_all,
+ MaxR = 0,
+ MaxT = 3600,
+ Children = child_specs(Args),
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+child_specs(Opts) ->
+ case proplists:get_value(role, Opts) of
+ client ->
+ child_specs(manager, [client | Opts]);
+ server ->
+ %% Children started by acceptor process
+ []
+ end.
+
+% The manager process starts the handler process
+child_specs(manager, Opts) ->
+ [manager_spec(Opts)];
+child_specs(handler, Opts) ->
+ [handler_spec(Opts)].
+
+manager_spec([server = Role, Socket, Opts]) ->
+ Name = make_ref(),
+ StartFunc = {ssh_connection_manager, start_link, [[Role, Socket, Opts]]},
+ Restart = temporary,
+ Shutdown = 3600,
+ Modules = [ssh_connection_manager],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules};
+
+manager_spec([client = Role | Opts]) ->
+ Name = make_ref(),
+ StartFunc = {ssh_connection_manager, start_link, [[Role, Opts]]},
+ Restart = temporary,
+ Shutdown = 3600,
+ Modules = [ssh_connection_manager],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+handler_spec([Role, Socket, Opts]) ->
+ Name = make_ref(),
+ StartFunc = {ssh_connection_handler,
+ start_link, [Role, self(), Socket, Opts]},
+ Restart = temporary,
+ Shutdown = 3600,
+ Modules = [ssh_connection_handler],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+ssh_connection_manager([{_, Child, _, [ssh_connection_manager]} | _]) ->
+ Child;
+ssh_connection_manager([_ | Rest]) ->
+ ssh_connection_manager(Rest).
diff --git a/lib/ssh/src/ssh_dsa.erl b/lib/ssh/src/ssh_dsa.erl
deleted file mode 100755
index 1b9a396f0c..0000000000
--- a/lib/ssh/src/ssh_dsa.erl
+++ /dev/null
@@ -1,95 +0,0 @@
-%%
-%% %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%
-%%
-
-%%
-
-%%% Description: dsa public-key sign and verify
-
--module(ssh_dsa).
-
--export([verify/3]).
--export([sign/2]).
--export([alg_name/0]).
-
--include("ssh.hrl").
-
-%% start() ->
-%% crypto:start().
-
-%% sign_file(File, Opts) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:private_host_dsa_key(user, Opts),
-%% sign(Key, Bin).
-
-%% verify_file(File, Sig) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:public_host_key(user, dsa),
-%% verify(Key, Bin, Sig).
-
-sign(_Private=#ssh_key { private={P,Q,G,X} },Mb) ->
- K = ssh_bits:irandom(160) rem Q,
- R = ssh_math:ipow(G, K, P) rem Q,
- Ki = ssh_math:invert(K, Q),
- <<M:160/big-unsigned-integer>> = crypto:sha(Mb),
- S = (Ki * (M + X*R)) rem Q,
- <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>.
-
-
-%% the paramiko client sends a bad sig sometimes,
-%% instead of crashing, we nicely return error, the
-%% typcally manifests itself as Sb being 39 bytes
-%% instead of 40.
-
-verify(Public, Mb, Sb) ->
- case catch xverify(Public, Mb, Sb) of
- {'EXIT', _Reason} ->
- %store({Public, Mb, Sb, _Reason}),
- {error, inconsistent_key};
- ok ->
- %store({Public, Mb, Sb, ok})
- ok
- end.
-
-%% store(Term) ->
-%% {ok, Fd} = file:open("/tmp/dsa", [append]),
-%% io:format(Fd, "~p~n~n~n", [Term]),
-%% file:close(Fd).
-
-
-xverify(_Public=#ssh_key { public={P,Q,G,Y} },Mb,Sb) ->
- <<R0:160/big-unsigned-integer, S0:160/big-unsigned-integer>> = Sb,
- ?ssh_assert(R0 >= 0 andalso R0 < Q andalso
- S0 >= 0 andalso S0 < Q, out_of_range),
- W = ssh_math:invert(S0,Q),
- <<M0:160/big-unsigned-integer>> = crypto:sha(Mb),
- U1 = (M0*W) rem Q,
- U2 = (R0*W) rem Q,
- T1 = ssh_math:ipow(G,U1,P),
- T2 = ssh_math:ipow(Y,U2,P),
- V = ((T1*T2) rem P) rem Q,
- if V == R0 ->
- ok;
- true ->
- {error, inconsistent_key}
- end.
-
-alg_name() ->
- "ssh-dss".
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 12180f56bb..d05fa8e09a 100755..100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,80 +23,98 @@
-module(ssh_file).
--include("ssh.hrl").
--include("PKCS-1.hrl").
--include("DSS.hrl").
+-behaviour(ssh_key_api).
+-include_lib("public_key/include/public_key.hrl").
-include_lib("kernel/include/file.hrl").
--export([public_host_dsa_key/2,private_host_dsa_key/2,
- public_host_rsa_key/2,private_host_rsa_key/2,
- public_host_key/2,private_host_key/2,
- lookup_host_key/3, add_host_key/3, % del_host_key/2,
- lookup_user_key/3, ssh_dir/2, file_name/3]).
-
--export([private_identity_key/2,
- public_identity_key/2]).
-%% identity_keys/2]).
-
--export([encode_public_key/1, decode_public_key_v2/2]).
+-include("ssh.hrl").
--import(lists, [reverse/1, append/1]).
+-export([host_key/2,
+ user_key/2,
+ is_host_key/4,
+ add_host_key/3,
+ is_auth_key/4]).
--define(DBG_PATHS, true).
-define(PERM_700, 8#700).
-define(PERM_644, 8#644).
+
%% API
-public_host_dsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_dsa_key.pub", Opts),
- read_public_key_v2(File, "ssh-dss").
-
-private_host_dsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_dsa_key", Opts),
- read_private_key_v2(File, "ssh-dss").
-
-public_host_rsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_rsa_key.pub", Opts),
- read_public_key_v2(File, "ssh-rsa").
-
-private_host_rsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_rsa_key", Opts),
- read_private_key_v2(File, "ssh-rsa").
-
-public_host_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_key", Opts),
- case read_private_key_v1(File,public) of
- {error, enoent} ->
- read_public_key_v1(File++".pub");
- Result ->
- Result
- end.
-
-private_host_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_key", Opts),
- read_private_key_v1(File,private).
+%% Used by server
+host_key(Algorithm, Opts) ->
+ File = file_name(system, file_base_name(Algorithm), Opts),
+ %% We do not expect host keys to have pass phrases
+ %% so probably we could hardcod Password = ignore, but
+ %% we keep it as an undocumented option for now.
+ Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore),
+ decode(File, Password).
+is_auth_key(Key, User, Alg, Opts) ->
+ case lookup_user_key(Key, User, Alg, Opts) of
+ {ok, Key} ->
+ true;
+ _ ->
+ false
+ end.
-%% in: "host" out: "host,1.2.3.4.
-add_ip(Host) ->
- case inet:getaddr(Host, inet) of
- {ok, Addr} ->
- case ssh_connection:encode_ip(Addr) of
- false -> Host;
- IPString -> Host ++ "," ++ IPString
- end;
- _ -> Host
- end.
-replace_localhost("localhost") ->
- {ok, Hostname} = inet:gethostname(),
- Hostname;
-replace_localhost(Host) ->
- Host.
+%% Used by client
+is_host_key(Key, PeerName, Algorithm, Opts) ->
+ case lookup_host_key(PeerName, Algorithm, Opts) of
+ {ok, Key} ->
+ true;
+ _ ->
+ false
+ end.
+
+user_key(Algorithm, Opts) ->
+ File = file_name(user, identity_key_filename(Algorithm), Opts),
+ Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore),
+ decode(File, Password).
+
+
+%% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+file_base_name('ssh-rsa') ->
+ "ssh_host_rsa_key";
+file_base_name('ssh-dss') ->
+ "ssh_host_dsa_key";
+file_base_name(_) ->
+ "ssh_host_key".
+
+decode(File, Password) ->
+ try
+ {ok, decode_ssh_file(read_ssh_file(File), Password)}
+ catch
+ throw:Reason ->
+ {error, Reason};
+ error:Reason ->
+ {error, Reason}
+ end.
+
+read_ssh_file(File) ->
+ {ok, Bin} = file:read_file(File),
+ Bin.
+
+%% Public key
+decode_ssh_file(SshBin, public_key) ->
+ public_key:ssh_decode(SshBin, public_key);
+
+%% Private Key
+decode_ssh_file(Pem, Password) ->
+ case public_key:pem_decode(Pem) of
+ [{_, _, not_encrypted} = Entry] ->
+ public_key:pem_entry_decode(Entry);
+ [Entry] when Password =/= ignore ->
+ public_key:pem_entry_decode(Entry, Password);
+ _ ->
+ throw("No pass phrase provided for private key file")
+ end.
+
%% lookup_host_key
%% return {ok, Key(s)} or {error, not_found}
@@ -106,15 +124,6 @@ lookup_host_key(Host, Alg, Opts) ->
Host1 = replace_localhost(Host),
do_lookup_host_key(Host1, Alg, Opts).
-do_lookup_host_key(Host, Alg, Opts) ->
- case file:open(file_name(user, "known_hosts", Opts), [read]) of
- {ok, Fd} ->
- Res = lookup_host_key_fd(Fd, Host, Alg),
- file:close(Fd),
- Res;
- {error, enoent} -> {error, not_found};
- Error -> Error
- end.
add_host_key(Host, Key, Opts) ->
Host1 = add_ip(replace_localhost(Host)),
@@ -129,383 +138,16 @@ add_host_key(Host, Key, Opts) ->
Error
end.
-%% del_host_key(Host, Opts) ->
-%% Host1 = replace_localhost(Host),
-%% case file:open(file_name(user, "known_hosts", Opts),[write,read]) of
-%% {ok, Fd} ->
-%% Res = del_key_fd(Fd, Host1),
-%% file:close(Fd),
-%% Res;
-%% Error ->
-%% Error
-%% end.
-
-identity_key_filename("ssh-dss") -> "id_dsa";
-identity_key_filename("ssh-rsa") -> "id_rsa".
-
-private_identity_key(Alg, Opts) ->
- Path = file_name(user, identity_key_filename(Alg), Opts),
- read_private_key_v2(Path, Alg).
-
-public_identity_key(Alg, Opts) ->
- Path = file_name(user, identity_key_filename(Alg) ++ ".pub", Opts),
- read_public_key_v2(Path, Alg).
-
-
-read_public_key_v2(File, Type) ->
- case file:read_file(File) of
- {ok,Bin} ->
- List = binary_to_list(Bin),
- case lists:prefix(Type, List) of
- true ->
- List1 = lists:nthtail(length(Type), List),
- K_S = ssh_bits:b64_decode(List1),
- decode_public_key_v2(K_S, Type);
- false ->
- {error, bad_format}
- end;
- Error ->
- Error
- end.
-
-decode_public_key_v2(K_S, "ssh-rsa") ->
- case ssh_bits:decode(K_S,[string,mpint,mpint]) of
- ["ssh-rsa", E, N] ->
- {ok, #ssh_key { type = rsa,
- public = {N,E},
- comment=""}};
- _ ->
- {error, bad_format}
- end;
-decode_public_key_v2(K_S, "ssh-dss") ->
- case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
- ["ssh-dss",P,Q,G,Y] ->
- {ok,#ssh_key { type = dsa,
- public = {P,Q,G,Y}
- }};
- _A ->
- {error, bad_format}
- end;
-decode_public_key_v2(_, _) ->
- {error, bad_format}.
-
-
-read_public_key_v1(File) ->
- case file:read_file(File) of
- {ok,Bin} ->
- List = binary_to_list(Bin),
- case io_lib:fread("~d ~d ~d ~s", List) of
- {ok,[_Sz,E,N,Comment],_} ->
- {ok,#ssh_key { type = rsa,
- public ={N,E},
- comment = Comment }};
- _Error ->
- {error, bad_format}
- end;
- Error ->
- Error
- end.
-
-%% pem_type("ssh-dss") -> "DSA";
-%% pem_type("ssh-rsa") -> "RSA".
-
-read_private_key_v2(File, Type) ->
- case file:read_file(File) of
- {ok, PemBin} ->
- case catch (public_key:pem_decode(PemBin)) of
- [{_, Bin, not_encrypted}] ->
- decode_private_key_v2(Bin, Type);
- Error -> %% Note we do not handle password encrypted keys at the moment
- {error, Error}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-%% case file:read_file(File) of
-%% {ok,Bin} ->
-%% case read_pem(binary_to_list(Bin), pem_type(Type)) of
-%% {ok,Bin1} ->
-%% decode_private_key_v2(Bin1, Type);
-%% Error ->
-%% Error
-%% end;
-%% Error ->
-%% Error
-%% end.
-
-decode_private_key_v2(Private,"ssh-rsa") ->
- case 'PKCS-1':decode( 'RSAPrivateKey', Private) of
- {ok,RSA} -> %% FIXME Check for two-prime version
- {ok, #ssh_key { type = rsa,
- public = {RSA#'RSAPrivateKey'.modulus,
- RSA#'RSAPrivateKey'.publicExponent},
- private = {RSA#'RSAPrivateKey'.modulus,
- RSA#'RSAPrivateKey'.privateExponent}
- }};
- Error ->
- Error
- end;
-decode_private_key_v2(Private, "ssh-dss") ->
- case 'DSS':decode('DSAPrivateKey', Private) of
- {ok,DSA} -> %% FIXME Check for two-prime version
- {ok, #ssh_key { type = dsa,
- public = {DSA#'DSAPrivateKey'.p,
- DSA#'DSAPrivateKey'.q,
- DSA#'DSAPrivateKey'.g,
- DSA#'DSAPrivateKey'.y},
- private= {DSA#'DSAPrivateKey'.p,
- DSA#'DSAPrivateKey'.q,
- DSA#'DSAPrivateKey'.g,
- DSA#'DSAPrivateKey'.x}
- }};
- _ ->
- {error,bad_format}
- end.
-
-%% SSH1 private key format
-%% <<"SSH PRIVATE KEY FILE FORMATE 1.1\n" 0:8
-%% CipherNum:8, Reserved:32,
-%% NSz/uint32, N/bignum, E/bignum, Comment/string,
-%%
-%% [ R0:8 R1:8 R0:8 R1:8, D/bignum, IQMP/bignum, Q/bignum, P/bignum, Pad(8)]>>
-%%
-%% where [ ] is encrypted using des3 (ssh1 version) and
-%% a posssibly empty pass phrase using md5(passphase) as key
-%%
-
-read_private_key_v1(File, Type) ->
- case file:read_file(File) of
- {ok,<<"SSH PRIVATE KEY FILE FORMAT 1.1\n",0,
- CipherNum,_Resereved:32,Bin/binary>>} ->
- decode_private_key_v1(Bin, CipherNum,Type);
- {ok,_} ->
- {error, bad_format};
- Error ->
- Error
- end.
-
-decode_private_key_v1(Bin, CipherNum, Type) ->
- case ssh_bits:decode(Bin,0,[uint32, bignum, bignum, string]) of
- {Offset,[_NSz,N,E,Comment]} ->
- if Type == public ->
- {ok,#ssh_key { type=rsa,
- public={N,E},
- comment=Comment}};
- Type == private ->
- <<_:Offset/binary, Encrypted/binary>> = Bin,
- case ssh_bits:decode(decrypt1(Encrypted, CipherNum),0,
- [uint32, bignum, bignum,
- bignum, bignum,{pad,8}]) of
- {_,[_,D,IQMP,Q,P]} ->
- {ok,#ssh_key { type=rsa,
- public={N,E},
- private={D,IQMP,Q,P},
- comment=Comment}};
- _ ->
- {error,bad_format}
- end
- end;
- _ ->
- {error,bad_format}
- end.
-
-
-decrypt1(Bin, CipherNum) ->
- decrypt1(Bin, CipherNum,"").
-
-decrypt1(Bin, CipherNum, Phrase) ->
- if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
- Bin;
- CipherNum == ?SSH_CIPHER_3DES ->
- <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
- K3 = K1,
- IV = <<0,0,0,0,0,0,0,0>>,
- Bin1 = crypto:des_cbc_decrypt(K3,IV,Bin),
- Bin2 = crypto:des_cbc_encrypt(K2,IV,Bin1),
- crypto:des_cbc_decrypt(K1,IV,Bin2)
- end.
-
-%% encrypt1(Bin, CipherNum) ->
-%% encrypt1(Bin, CipherNum,"").
-
-%% encrypt1(Bin, CipherNum, Phrase) ->
-%% if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
-%% Bin;
-%% CipherNum == ?SSH_CIPHER_3DES ->
-%% <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
-%% K3 = K1,
-%% IV = <<0,0,0,0,0,0,0,0>>,
-%% Bin1 = crypto:des_cbc_encrypt(K1,IV,Bin),
-%% Bin2 = crypto:des_cbc_decrypt(K2,IV,Bin1),
-%% crypto:des_cbc_encrypt(K3,IV,Bin2)
-%% end.
-
-lookup_host_key_fd(Fd, Host, Alg) ->
- case io:get_line(Fd, '') of
- eof ->
- {error, not_found};
- Line ->
- case string:tokens(Line, " ") of
- [HostList, Alg, KeyData] ->
-%% io:format(" ~p lookup_host_key_fd: HostList ~p Alg ~p KeyData ~p\n",
-%% [Host, HostList, Alg, KeyData]),
- case lists:member(Host, string:tokens(HostList, ",")) of
- true ->
- decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
- false ->
- lookup_host_key_fd(Fd, Host, Alg)
- end;
- _ ->
- lookup_host_key_fd(Fd, Host, Alg)
- end
- end.
-
-
-
-%% del_key_fd(Fd, Host) ->
-%% del_key_fd(Fd, Host, 0, 0).
-
-%% del_key_fd(Fd, Host, ReadPos0, WritePos0) ->
-%% case io:get_line(Fd, '') of
-%% eof ->
-%% if ReadPos0 == WritePos0 ->
-%% ok;
-%% true ->
-%% file:truncate(Fd)
-%% end;
-%% Line ->
-%% {ok,ReadPos1} = file:position(Fd, cur),
-%% case string:tokens(Line, " ") of
-%% [HostList, _Type, _KeyData] ->
-%% case lists:member(Host, string:tokens(HostList, ",")) of
-%% true ->
-%% del_key_fd(Fd, Host, ReadPos1, WritePos0);
-%% false ->
-%% if ReadPos0 == WritePos0 ->
-%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
-%% true ->
-%% file:position(Fd, WritePos0),
-%% file:write(Fd, Line),
-%% {ok,WritePos1} = file:position(Fd,cur),
-%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
-%% end
-%% end;
-%% _ ->
-%% if ReadPos0 == WritePos0 ->
-%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
-%% true ->
-%% file:position(Fd, WritePos0),
-%% file:write(Fd, Line),
-%% {ok,WritePos1} = file:position(Fd,cur),
-%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
-%% end
-%% end
-%% end.
-
-
-add_key_fd(Fd, Host, Key) ->
- case Key#ssh_key.type of
- rsa ->
- {N,E} = Key#ssh_key.public,
- DK = ssh_bits:b64_encode(
- ssh_bits:encode(["ssh-rsa",E,N],
- [string,mpint,mpint])),
- file:write(Fd, [Host, " ssh-rsa ", DK, "\n"]);
- dsa ->
- {P,Q,G,Y} = Key#ssh_key.public,
- DK = ssh_bits:b64_encode(
- ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint])),
- file:write(Fd, [Host, " ssh-dss ", DK, "\n"])
- end.
-
-
-%% read_pem(Cs, Type) ->
-%% case read_line(Cs) of
-%% {"-----BEGIN "++Rest,Cs1} ->
-%% case string:tokens(Rest, " ") of
-%% [Type, "PRIVATE", "KEY-----"] ->
-%% read_pem64(Cs1, [], Type);
-%% _ ->
-%% {error, bad_format}
-%% end;
-%% {"",Cs1} when Cs1 =/= "" ->
-%% read_pem(Cs1,Type);
-%% {_,""} ->
-%% {error, bad_format}
-%% end.
-
-%% read_pem64(Cs, Acc, Type) ->
-%% case read_line(Cs) of
-%% {"-----END "++Rest,_Cs1} ->
-%% case string:tokens(Rest, " ") of
-%% [Type, "PRIVATE", "KEY-----"] ->
-%% {ok,ssh_bits:b64_decode(append(reverse(Acc)))};
-%% Toks ->
-%% error_logger:format("ssh: TOKENS=~p\n", [Toks]),
-%% {error, bad_format}
-%% end;
-%% {B64, Cs1} when Cs1 =/= "" ->
-%% read_pem64(Cs1, [B64|Acc], Type);
-%% _What ->
-%% {error, bad_format}
-%% end.
-
-
-%% read_line(Cs) -> read_line(Cs,[]).
-%% read_line([$\r,$\n|T], Acc) -> {reverse(Acc), T};
-%% read_line([$\n|T], Acc) -> {reverse(Acc), T};
-%% read_line([C|T], Acc) -> read_line(T,[C|Acc]);
-%% read_line([], Acc) -> {reverse(Acc),[]}.
-
-lookup_user_key(User, Alg, Opts) ->
+lookup_user_key(Key, User, Alg, Opts) ->
SshDir = ssh_dir({remoteuser,User}, Opts),
- case lookup_user_key_f(User, SshDir, Alg, "authorized_keys", Opts) of
+ case lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys", Opts) of
{ok, Key} ->
{ok, Key};
_ ->
- lookup_user_key_f(User, SshDir, Alg, "authorized_keys2", Opts)
- end.
-
-lookup_user_key_f(_User, [], _Alg, _F, _Opts) ->
- {error, nouserdir};
-lookup_user_key_f(_User, nouserdir, _Alg, _F, _Opts) ->
- {error, nouserdir};
-lookup_user_key_f(_User, Dir, Alg, F, _Opts) ->
- FileName = filename:join(Dir, F),
- case file:open(FileName, [read]) of
- {ok, Fd} ->
- Res = lookup_user_key_fd(Fd, Alg),
- file:close(Fd),
- Res;
- {error, Reason} ->
- {error, {{openerr, Reason}, {file, FileName}}}
- end.
-
-lookup_user_key_fd(Fd, Alg) ->
- case io:get_line(Fd, '') of
- eof ->
- {error, not_found};
- Line ->
- case string:tokens(Line, " ") of
- [Alg, KeyData, _] ->
- %% io:format("lookup_user_key_fd: HostList ~p Alg ~p KeyData ~p\n",
- %% [HostList, Alg, KeyData]),
- decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
- _Other ->
- %%?dbg(false, "key_fd Other: ~w ~w\n", [Alg, _Other]),
- lookup_user_key_fd(Fd, Alg)
- end
+ lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys2", Opts)
end.
-encode_public_key(#ssh_key{type = rsa, public = {N, E}}) ->
- ssh_bits:encode(["ssh-rsa",E,N],
- [string,mpint,mpint]);
-encode_public_key(#ssh_key{type = dsa, public = {P,Q,G,Y}}) ->
- ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint]).
-
%%
%% Utils
%%
@@ -537,11 +179,130 @@ ssh_dir(user, Opts) ->
ssh_dir(system, Opts) ->
proplists:get_value(system_dir, Opts, "/etc/ssh").
+
file_name(Type, Name, Opts) ->
FN = filename:join(ssh_dir(Type, Opts), Name),
- %%?dbg(?DBG_PATHS, "file_name: ~p\n", [FN]),
FN.
+
+
+%% in: "host" out: "host,1.2.3.4.
+add_ip(Host) ->
+ case inet:getaddr(Host, inet) of
+ {ok, Addr} ->
+ case ssh_connection:encode_ip(Addr) of
+ false -> Host;
+ IPString -> Host ++ "," ++ IPString
+ end;
+ _ -> Host
+ end.
+
+replace_localhost("localhost") ->
+ {ok, Hostname} = inet:gethostname(),
+ Hostname;
+replace_localhost(Host) ->
+ Host.
+
+do_lookup_host_key(Host, Alg, Opts) ->
+ case file:open(file_name(user, "known_hosts", Opts), [read, binary]) of
+ {ok, Fd} ->
+ Res = lookup_host_key_fd(Fd, Host, Alg),
+ file:close(Fd),
+ {ok, Res};
+ {error, enoent} -> {error, not_found};
+ Error -> Error
+ end.
+
+identity_key_filename("ssh-dss") ->
+ "id_dsa";
+identity_key_filename("ssh-rsa") ->
+ "id_rsa".
+
+identity_pass_phrase("ssh-dss") ->
+ dsa_pass_phrase;
+identity_pass_phrase('ssh-dss') ->
+ dsa_pass_phrase;
+identity_pass_phrase('ssh-rsa') ->
+ rsa_pass_phrase;
+identity_pass_phrase("ssh-rsa") ->
+ rsa_pass_phrase.
+
+lookup_host_key_fd(Fd, Host, KeyType) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case public_key:ssh_decode(Line, known_hosts) of
+ [{Key, Attributes}] ->
+ handle_host(Fd, Host, proplists:get_value(hostnames, Attributes), Key, KeyType);
+ [] ->
+ lookup_host_key_fd(Fd, Host, KeyType)
+ end
+ end.
+
+handle_host(Fd, Host, HostList, Key, KeyType) ->
+ Host1 = host_name(Host),
+ case lists:member(Host1, HostList) and key_match(Key, KeyType) of
+ true ->
+ Key;
+ false ->
+ lookup_host_key_fd(Fd, Host, KeyType)
+ end.
+
+host_name(Atom) when is_atom(Atom) ->
+ atom_to_list(Atom);
+host_name(List) ->
+ List.
+
+key_match(#'RSAPublicKey'{}, "ssh-rsa") ->
+ true;
+key_match({_, #'Dss-Parms'{}}, "ssh-dss") ->
+ true;
+key_match(_, _) ->
+ false.
+
+add_key_fd(Fd, Host,Key) ->
+ SshBin = public_key:ssh_encode([{Key, [{hostnames, [Host]}]}], known_hosts),
+ file:write(Fd, SshBin).
+
+lookup_user_key_f(_, _User, [], _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(_, _User, nouserdir, _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(Key, _User, Dir, _Alg, F, _Opts) ->
+ FileName = filename:join(Dir, F),
+ case file:open(FileName, [read, binary]) of
+ {ok, Fd} ->
+ Res = lookup_user_key_fd(Fd, Key),
+ file:close(Fd),
+ Res;
+ {error, Reason} ->
+ {error, {{openerr, Reason}, {file, FileName}}}
+ end.
+
+lookup_user_key_fd(Fd, Key) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case public_key:ssh_decode(Line, auth_keys) of
+ [{AuthKey, _}] ->
+ case is_auth_key(Key, AuthKey) of
+ true ->
+ {ok, Key};
+ false ->
+ lookup_user_key_fd(Fd, Key)
+ end;
+ [] ->
+ lookup_user_key_fd(Fd, Key)
+ end
+ end.
+
+is_auth_key(Key, Key) ->
+ true;
+is_auth_key(_,_) ->
+ false.
+
default_user_dir()->
{ok,[[Home|_]]} = init:get_argument(home),
UserDir = filename:join(Home, ".ssh"),
diff --git a/lib/ssh/src/ssh_io.erl b/lib/ssh/src/ssh_io.erl
index 915fd63e4f..1dbd097423 100755..100644
--- a/lib/ssh/src/ssh_io.erl
+++ b/lib/ssh/src/ssh_io.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_key_api.erl b/lib/ssh/src/ssh_key_api.erl
new file mode 100644
index 0000000000..8085c12e21
--- /dev/null
+++ b/lib/ssh/src/ssh_key_api.erl
@@ -0,0 +1,45 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_key_api).
+
+-include_lib("public_key/include/public_key.hrl").
+-include("ssh.hrl").
+
+-type ssh_algorithm() :: string().
+-type file_error() :: file:posix() | badarg | system_limit | terminated.
+
+-callback host_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
+ {ok, [{public_key(), Attributes::list()}]} | public_key()
+ | {error, string()}.
+
+-callback user_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
+ {ok, [{public_key(), Attributes::list()}]} | public_key()
+ | {error, string()}.
+
+-callback is_host_key(Key :: public_key(), PeerName :: string(),
+ Algorithm :: ssh_algorithm(), Options :: list()) ->
+ boolean().
+
+-callback add_host_key(Host :: string(), Key :: public_key(), Options :: list()) ->
+ ok | {error, file_error()}.
+
+-callback is_auth_key(Key :: public_key(), User :: string(),
+ Algorithm :: ssh_algorithm(), Options :: list()) ->
+ boolean().
diff --git a/lib/ssh/src/ssh_math.erl b/lib/ssh/src/ssh_math.erl
index 510eb16aa6..4aa385b18d 100755..100644
--- a/lib/ssh/src/ssh_math.erl
+++ b/lib/ssh/src/ssh_math.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_rsa.erl b/lib/ssh/src/ssh_rsa.erl
deleted file mode 100755
index 91b8285b2e..0000000000
--- a/lib/ssh/src/ssh_rsa.erl
+++ /dev/null
@@ -1,298 +0,0 @@
-%%
-%% %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%
-%%
-
-%%
-
-%%% Description: rsa public-key sign and verify
-
--module(ssh_rsa).
-
--export([verify/3, sign/2]).
--export([alg_name/0]).
-
--include("ssh.hrl").
--include("PKCS-1.hrl").
-
-
--define(MGF(Seed,Len), mgf1((Seed),(Len))).
--define(HASH(X), crypto:sha((X))).
--define(HLen, 20).
-
-%% start() ->
-%% crypto:start().
-
-%% sign_file(File) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:private_host_rsa_key(user),
-%% sign(Key, Bin).
-
-%% verify_file(File, Sig) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:public_host_rsa_key(user),
-%% verify(Key, Bin, Sig).
-
-sign(Private,Mb) ->
- rsassa_pkcs1_v1_5_sign(Private,Mb).
-
-verify(Public,Mb,Sb) ->
- rsassa_pkcs1_v1_5_verify(Public,Mb,Sb).
-
-
-
-%% Integer to octet string
-i2osp(X, XLen) ->
- ssh_bits:i2bin(X, XLen).
-
-%% Octet string to Integer
-os2ip(X) ->
- ssh_bits:bin2i(X).
-
-%% decrypt1, M = message representative
-%% rsaep(#ssh_key { public={N,E}}, M) ->
-%% ?ssh_assert(M >= 0 andalso M =< N-1, out_of_range),
-%% ssh_math:ipow(M, E, N).
-
-%% encrypt1, C = cipher representative
-%% rsadp(#ssh_key { public={N,_}, private={_,D}}, C) ->
-%% ?ssh_assert(C >= 0 andalso C =< N-1, out_of_range),
-%% ssh_math:ipow(C, D, N).
-
-%% sign1, M = message representative
-rsasp1(#ssh_key { public={N,_}, private={_,D}}, M) ->
- ?ssh_assert((M >= 0 andalso M =< N-1), out_of_range),
- ssh_math:ipow(M, D, N).
-
-%% verify1, S =signature representative
-rsavp1(#ssh_key { public={N,E}}, S) ->
- ?ssh_assert(S >= 0 andalso S =< N-1, out_of_range),
- ssh_math:ipow(S, E, N).
-
-
-%% M messaage
-%% rsaes_oaep_encrypt(Public, M) ->
-%% rsaes_oaep_encrypt(Public, M, <<>>).
-
-%% rsaes_oaep_encrypt(Public=#ssh_key { public={N,_E}}, M, L) ->
-%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% MLen = size(M),
-%% %% LLen = size(L),
-%% ?ssh_assert(MLen =< K - 2*?HLen - 2, message_to_long),
-%% LHash = ?HASH(L),
-%% PS = ssh_bits:fill_bits(K - MLen - 2*?HLen - 2, 0),
-%% DB = <<LHash/binary, PS/binary, 16#01, M/binary>>,
-%% Seed = ssh_bits:random(?HLen),
-%% DbMask = ?MGF(Seed, K - ?HLen - 1),
-%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
-%% SeedMask = ?MGF(MaskedDB, ?HLen),
-%% MaskedSeed = ssh_bits:xor_bits(Seed, SeedMask),
-%% EM = <<16#00, MaskedSeed/binary, MaskedDB/binary>>,
-%% Mc = os2ip(EM),
-%% C = rsaep(Public, Mc),
-%% i2osp(C, K).
-
-%% rsaes_oaep_decrypt(Key, C) ->
-%% rsaes_oaep_decrypt(Key, C, <<>>).
-
-%% rsaes_oaep_decrypt(Private=#ssh_key { public={N,_},private={_,_}},Cb,L) ->
-%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% ?ssh_assert(K == 2*?HLen + 2, decryption_error),
-%% C = os2ip(Cb),
-%% M = rsadp(Private, C),
-%% EM = i2osp(M, K),
-%% LHash = ?HASH(L),
-%% MLen = K - ?HLen -1,
-%% case EM of
-%% <<16#00, MaskedSeed:?HLen/binary, MaskedDB:MLen>> ->
-%% SeedMask = ?MGF(MaskedDB, ?HLen),
-%% Seed = ssh_bits:xor_bits(MaskedSeed, SeedMask),
-%% DbMask = ?MGF(Seed, K - ?HLen - 1),
-%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
-%% PSLen = K - MLen - 2*?HLen - 2,
-%% case DB of
-%% <<LHash:?HLen, _PS:PSLen/binary, 16#01, M/binary>> ->
-%% M;
-%% _ ->
-%% exit(decryption_error)
-%% end;
-%% _ ->
-%% exit(decryption_error)
-%% end.
-
-
-%% rsaes_pkcs1_v1_5_encrypt(Public=#ssh_key { public={N,_}}, M) ->
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% MLen = size(M),
-%% ?ssh_assert(MLen =< K - 11, message_to_long),
-%% PS = ssh_bits:random(K - MLen - 3),
-%% EM = <<16#00,16#02,PS/binary,16#00,M/binary>>,
-%% Mc = os2ip(EM),
-%% C = rsaep(Public, Mc),
-%% i2osp(C, K).
-
-
-%% rsaes_pkcs1_v1_5_decrypt(Private=#ssh_key { public={N,_},private={_,_}},
-%% Cb) ->
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% CLen = size(Cb),
-%% ?ssh_assert(CLen == K andalso K >= 11, decryption_error),
-%% C = os2ip(Cb),
-%% M = rsadp(Private, C),
-%% EM = i2osp(M, K),
-%% PSLen = K - CLen - 3,
-%% case EM of
-%% <<16#00, 16#02, _PS:PSLen/binary, 16#00, M>> ->
-%% M;
-%% _ ->
-%% exit(decryption_error)
-%% end.
-
-%% rsassa_pss_sign(Private=#ssh_key { public={N,_},private={_,_}},Mb) ->
-%% ModBits = ssh_bits:isize(N),
-%% K = (ModBits+7) div 8,
-%% EM = emsa_pss_encode(Mb, ModBits - 1),
-%% M = os2ip(EM),
-%% S = rsasp1(Private, M),
-%% i2osp(S, K).
-
-%% rsassa_pss_verify(Public=#ssh_key { public={N,_E}},Mb,Sb) ->
-%% ModBits = ssh_bits:isize(N),
-%% K = (ModBits+7) div 8,
-%% ?ssh_assert(size(Sb) == K, invalid_signature),
-%% S = os2ip(Sb),
-%% M = rsavp1(Public,S),
-%% EMLen = (ModBits-1+7) div 8,
-%% EM = i2osp(M, EMLen),
-%% emsa_pss_verify(Mb, EM, ModBits-1).
-
-
-rsassa_pkcs1_v1_5_sign(Private=#ssh_key { public={N,_},private={_,_D}},Mb) ->
- K = (ssh_bits:isize(N)+7) div 8,
- EM = emsa_pkcs1_v1_5_encode(Mb, K),
- M = os2ip(EM),
- S = rsasp1(Private, M),
- i2osp(S, K).
-
-rsassa_pkcs1_v1_5_verify(Public=#ssh_key { public={N,_E}}, Mb, Sb) ->
- K = (ssh_bits:isize(N)+7) div 8,
- ?ssh_assert(size(Sb) == K, invalid_signature),
- S = os2ip(Sb),
- M = rsavp1(Public, S),
- EM = i2osp(M, K),
- %?dbg(true, "verify K=~p S=~w ~n#M=~w~n#EM=~w~n", [K, S, M, EM]),
- case emsa_pkcs1_v1_5_encode(Mb, K) of
- EM -> ok;
- _S ->
- {error, invalid_signature}
- end.
-
-
-emsa_pkcs1_v1_5_encode(M, EMLen) ->
- H = ?HASH(M),
- %% Must use speical xxNull types here!
- Alg = #'AlgorithmNull' { algorithm = ?'id-sha1',
- parameters = <<>> },
- {ok,TCode} = 'PKCS-1':encode('DigestInfoNull',
- #'DigestInfoNull'{ digestAlgorithm = Alg,
- digest = H }),
- T = list_to_binary(TCode),
- TLen = size(T),
- ?ssh_assert(EMLen >= TLen + 11, message_to_short),
- PS = ssh_bits:fill_bits(EMLen - TLen - 3, 16#ff),
- <<16#00, 16#01, PS/binary, 16#00, T/binary>>.
-
-
-%% emsa_pss_encode(M, EMBits) ->
-%% emsa_pss_encode(M, EMBits, 0).
-
-%% emsa_pss_encode(M, EMBits, SLen) ->
-%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
-%% EMLen = (EMBits + 7) div 8,
-%% MHash = ?HASH(M),
-%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, encoding_error),
-%% Salt = ssh_bits:random(SLen),
-%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
-%% MHash, Salt],
-%% H = ?HASH(M1),
-%% PS = ssh_bits:fill_bits(EMLen-SLen-?HLen-2, 0),
-%% DB = <<PS/binary, 16#01, Salt/binary>>,
-%% DbMask = ?MGF(H, EMLen - ?HLen -1),
-%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
-%% ZLen = 8*EMLen - EMBits,
-%% NZLen = (8 - (ZLen rem 8)) rem 8,
-%% <<_:ZLen, NZ:NZLen, MaskedDB1/binary>> = MaskedDB,
-%% MaskedDB2 = <<0:ZLen, NZ:NZLen, MaskedDB1/binary>>,
-%% <<MaskedDB2/binary, H/binary, 16#BC>>.
-
-
-%% emsa_pss_verify(M, EM, EMBits) ->
-%% emsa_pss_verify(M, EM, EMBits, 0).
-
-%% emsa_pss_verify(M, EM, EMBits, SLen) ->
-%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
-%% EMLen = (EMBits + 7) div 8,
-%% MHash = ?HASH(M),
-%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, inconsistent),
-%% MaskLen = (EMLen - ?HLen - 1)-1,
-%% ZLen = 8*EMLen - EMBits,
-%% NZLen = (8 - (ZLen rem 8)) rem 8,
-%% case EM of
-%% <<0:ZLen,Nz:NZLen,MaskedDB1:MaskLen/binary, H:?HLen/binary, 16#BC>> ->
-%% MaskedDB = <<0:ZLen,Nz:NZLen,MaskedDB1/binary>>,
-%% DbMask = ?MGF(H, EMLen - ?HLen - 1),
-%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
-%% PSLen1 = (EMLen - SLen - ?HLen - 2) - 1,
-%% PS = ssh_bits:fill_bits(PSLen1, 0),
-%% case DB of
-%% <<_:ZLen,0:NZLen,PS:PSLen1/binary,16#01,Salt:SLen/binary>> ->
-%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
-%% MHash, Salt],
-%% case ?HASH(M1) of
-%% H -> ok;
-%% _ -> exit(inconsistent)
-%% end;
-%% _ ->
-%% exit(inconsistent)
-%% end;
-%% _ ->
-%% exit(inconsistent)
-%% end.
-
-
-
-%% Mask generating function MGF1
-%% mgf1(MGFSeed, MaskLen) ->
-%% T = mgf1_loop(0, ((MaskLen + ?HLen -1) div ?HLen) - 1, MGFSeed, ""),
-%% <<R:MaskLen/binary, _/binary>> = T,
-%% R.
-
-%% mgf1_loop(Counter, N, _, T) when Counter > N ->
-%% list_to_binary(T);
-%% mgf1_loop(Counter, N, MGFSeed, T) ->
-%% C = i2osp(Counter, 4),
-%% mgf1_loop(Counter+1, N, MGFSeed, [T, ?HASH([MGFSeed, C])]).
-
-
-
-
-alg_name() ->
- "ssh-rsa".
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index f000558100..f000558100 100755..100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index da91817fd7..ec7b76b0b3 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -231,8 +231,6 @@ handle_op(?SSH_FXP_REALPATH, ReqId,
case Res of
{ok, AbsPath} ->
NewAbsPath = chroot_filename(AbsPath, State),
- ?dbg(true, "handle_op ?SSH_FXP_REALPATH: RelPath=~p AbsPath=~p\n",
- [RelPath, NewAbsPath]),
XF = State#state.xf,
Attr = #ssh_xfer_attr{type=directory},
ssh_xfer:xf_send_name(XF, ReqId, NewAbsPath, Attr),
@@ -426,18 +424,18 @@ handle_op(?SSH_FXP_RENAME, ReqId,
State0
end;
handle_op(?SSH_FXP_SYMLINK, ReqId,
- <<?UINT32(PLen), BPath:PLen/binary, ?UINT32(PLen2),
- BPath2:PLen2/binary>>,
+ <<?UINT32(PLen), Link:PLen/binary, ?UINT32(PLen2),
+ Target:PLen2/binary>>,
State0 = #state{file_handler = FileMod, file_state = FS0}) ->
- Path = relate_file_name(BPath, State0),
- Path2 = relate_file_name(BPath2, State0),
- {Status, FS1} = FileMod:make_symlink(Path2, Path, FS0),
+ LinkPath = relate_file_name(Link, State0),
+ TargetPath = relate_file_name(Target, State0),
+ {Status, FS1} = FileMod:make_symlink(TargetPath, LinkPath, FS0),
State1 = State0#state{file_state = FS1},
send_status(Status, ReqId, State1).
new_handle([], H) ->
H;
-new_handle([{N, _} | Rest], H) when N > H ->
+new_handle([{N, _,_} | Rest], H) when N =< H ->
new_handle(Rest, N+1);
new_handle([_ | Rest], H) ->
new_handle(Rest, H).
@@ -446,6 +444,8 @@ add_handle(State, XF, ReqId, Type, DirFileTuple) ->
Handles = State#state.handles,
Handle = new_handle(Handles, 0),
ssh_xfer:xf_send_handle(XF, ReqId, integer_to_list(Handle)),
+ %% OBS: If you change handles-tuple also change new_handle!
+ %% Is this this the best way to implement new handle?
State#state{handles = [{Handle, Type, DirFileTuple} | Handles]}.
get_handle(Handles, BinHandle) ->
@@ -463,7 +463,6 @@ get_handle(Handles, BinHandle) ->
read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
XF, ReqId, Handle, RelPath, {cache, Files}) ->
AbsPath = relate_file_name(RelPath, State0),
- ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
if
length(Files) > MaxLength ->
{ToSend, NewCache} = lists:split(MaxLength, Files),
@@ -484,7 +483,6 @@ read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_sta
read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
XF, ReqId, Handle, RelPath, _Status) ->
AbsPath = relate_file_name(RelPath, State0),
- ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
{Res, FS1} = FileMod:list_dir(AbsPath, FS0),
case Res of
{ok, Files} when MaxLength == 0 orelse MaxLength > length(Files) ->
@@ -516,7 +514,6 @@ get_attrs(_RelPath, [], _FileMod, FS, Acc) ->
{lists:reverse(Acc), FS};
get_attrs(RelPath, [F | Rest], FileMod, FS0, Acc) ->
Path = filename:absname(F, RelPath),
- ?dbg(true, "get_attrs fun: F=~p\n", [F]),
case FileMod:read_link_info(Path, FS0) of
{{ok, Info}, FS1} ->
Attrs = ssh_sftp:info_to_attr(Info),
@@ -560,7 +557,6 @@ stat(ReqId, RelPath, State0=#state{file_handler=FileMod,
file_state=FS0}, F) ->
AbsPath = relate_file_name(RelPath, State0),
XF = State0#state.xf,
- ?dbg(false, "stat: AbsPath=~p\n", [AbsPath]),
{Res, FS1} = FileMod:F(AbsPath, FS0),
State1 = State0#state{file_state = FS1},
case Res of
@@ -605,6 +601,8 @@ decode_4_access_flag(add_subdirectory) ->
[read];
decode_4_access_flag(append_data) ->
[append];
+decode_4_access_flag(write_attributes) ->
+ [write];
decode_4_access_flag(_) ->
[read].
@@ -619,8 +617,7 @@ open(Vsn, ReqId, Data, State) when Vsn =< 3 ->
<<?UINT32(BLen), BPath:BLen/binary, ?UINT32(PFlags),
_Attrs/binary>> = Data,
Path = binary_to_list(BPath),
- Flags = ssh_xfer:decode_open_flags(Vsn, PFlags) -- [creat, excl, trunc],
- ?dbg(true, "open: Flags=~p\n", [Flags]),
+ Flags = ssh_xfer:decode_open_flags(Vsn, PFlags),
do_open(ReqId, State, Path, Flags);
open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
<<?UINT32(BLen), BPath:BLen/binary, ?UINT32(Access),
@@ -628,7 +625,6 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
Path = binary_to_list(BPath),
FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
AcessBits = ssh_xfer:decode_ace_mask(Access),
- ?dbg(true, "open: Fl=~p\n", [FlagBits]),
%% TODO: This is to make sure the Access flags are not ignored
%% but this should be thought through better. This solution should
%% be considered a hack in order to buy some time. At least
@@ -638,15 +634,12 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
AcessFlags = decode_4_acess(AcessBits),
Flags = lists:append(lists:umerge(
[[decode_4_flags(FlagBits)] | AcessFlags])),
-
- ?dbg(true, "open: Flags=~p\n", [Flags]),
-
do_open(ReqId, State, Path, Flags).
do_open(ReqId, State0, Path, Flags) ->
#state{file_handler = FileMod, file_state = FS0, root = Root} = State0,
XF = State0#state.xf,
- F = [raw, binary | Flags],
+ F = [binary | Flags],
%% case FileMod:is_dir(Path) of %% This is version 6 we still have 5
%% true ->
%% ssh_xfer:xf_send_status(State#state.xf, ReqId,
@@ -895,14 +888,11 @@ set_stat(Attr, Path,
State0 = #state{file_handler=FileMod, file_state=FS0}) ->
{DecodedAttr, _Rest} =
ssh_xfer:decode_ATTR((State0#state.xf)#ssh_xfer.vsn, Attr),
- ?dbg(true, "set_stat DecodedAttr=~p\n", [DecodedAttr]),
Info = ssh_sftp:attr_to_info(DecodedAttr),
{Res1, FS1} = FileMod:read_link_info(Path, FS0),
case Res1 of
{ok, OldInfo} ->
NewInfo = set_file_info(Info, OldInfo),
- ?dbg(true, "set_stat Path=~p\nInfo=~p\nOldInfo=~p\nNewInfo=~p\n",
- [Path, Info, OldInfo, NewInfo]),
{Res2, FS2} = FileMod:write_file_info(Path, NewInfo, FS1),
State1 = State0#state{file_state = FS2},
{Res2, State1};
diff --git a/lib/ssh/src/ssh_sftpd_file_api.erl b/lib/ssh/src/ssh_sftpd_file_api.erl
index 176aa98194..83d90907f5 100644
--- a/lib/ssh/src/ssh_sftpd_file_api.erl
+++ b/lib/ssh/src/ssh_sftpd_file_api.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,27 +21,41 @@
-module(ssh_sftpd_file_api).
--export([behaviour_info/1]).
+%% To be further specified later
+-callback close(file:io_device(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback delete(file:name(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback del_dir(file:name(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback get_cwd(State::term()) ->
+ {{ok, Dir::term()}, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback is_dir(file:name(), State::term()) ->
+ {boolean(), State::term()}.
+-callback list_dir(file:name(), State::term()) ->
+ {{ok, Filenames::term()}, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback make_dir(Dir::term(), State::term()) ->
+ {{ok, State::term()},State::term()} | {{error, Reason::term()}, State::term()}.
+-callback make_symlink(Path2::term(), Path::term(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback open(Path::term(), Flags::term(), State::term()) ->
+ {{ok, IoDevice::term()}, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback position(file:io_device(), Offs::term(), State::term()) ->
+ {{ok, NewPosition::term()}, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback read(file:io_device(), Len::term(), State::term()) ->
+ {{ok, Data::term()},State::term()} | {eof, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback read_link(file:name(), State::term()) ->
+ {{ok, FileName::term()}, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback read_link_info(file:name(), State::term()) ->
+ {{ok, FileInfo::term()}, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback read_file_info(file:name(), State::term()) ->
+ {{ok, FileInfo::term()}, State::term()} | {{error, Reason::term()},State::term()}.
+-callback rename(file:name(), file:name(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback write(file:io_device(), Data::term(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+-callback write_file_info(file:name(),Info::term(), State::term()) ->
+ {ok, State::term()} | {{error, Reason::term()}, State::term()}.
+
+
-behaviour_info(callbacks) ->
- [
- {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}
- ];
-behaviour_info(_) ->
- undefined.
diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl
index d71b6bbc56..cd6defd535 100644
--- a/lib/ssh/src/ssh_subsystem_sup.erl
+++ b/lib/ssh/src/ssh_subsystem_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,13 +70,12 @@ ssh_connectinon_child_spec(Opts) ->
Address = proplists:get_value(address, Opts),
Port = proplists:get_value(port, Opts),
Role = proplists:get_value(role, Opts),
- Name = id(Role, ssh_connection_controler, Address, Port),
- StartFunc = {ssh_connection_controler, start_link, [Opts]},
+ Name = id(Role, ssh_connection_sup, Address, Port),
+ StartFunc = {ssh_connection_sup, start_link, [Opts]},
Restart = transient,
-% Restart = permanent,
Shutdown = 5000,
- Modules = [ssh_connection_controler],
- Type = worker,
+ Modules = [ssh_connection_sup],
+ Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
ssh_channel_child_spec(Opts) ->
@@ -86,7 +85,6 @@ ssh_channel_child_spec(Opts) ->
Name = id(Role, ssh_channel_sup, Address, Port),
StartFunc = {ssh_channel_sup, start_link, [Opts]},
Restart = transient,
-% Restart = permanent,
Shutdown = infinity,
Modules = [ssh_channel_sup],
Type = supervisor,
@@ -95,7 +93,7 @@ ssh_channel_child_spec(Opts) ->
id(Role, Sup, Address, Port) ->
{Role, Sup, Address, Port}.
-ssh_connection_sup([{_, Child, _, [ssh_connection_controler]} | _]) ->
+ssh_connection_sup([{_, Child, _, [ssh_connection_sup]} | _]) ->
Child;
ssh_connection_sup([_ | Rest]) ->
ssh_connection_sup(Rest).
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
index 920baaadef..36daf3b1ac 100644
--- a/lib/ssh/src/ssh_system_sup.erl
+++ b/lib/ssh/src/ssh_system_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -146,7 +146,7 @@ ssh_acceptor_child_spec(ServerOpts) ->
ssh_subsystem_child_spec(ServerOpts) ->
Name = make_ref(),
StartFunc = {ssh_subsystem_sup, start_link, [ServerOpts]},
- Restart = temporary,
+ Restart = transient,
Shutdown = infinity,
Modules = [ssh_subsystem_sup],
Type = supervisor,
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index de3e29e2f1..1f912c9bdf 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,10 +23,11 @@
-module(ssh_transport).
--include("ssh_transport.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/inet.hrl").
+-include("ssh_transport.hrl").
-include("ssh.hrl").
--include_lib("kernel/include/inet.hrl").
-export([connect/5, accept/4]).
-export([versions/2, hello_version_msg/1]).
@@ -38,17 +39,8 @@
handle_kex_dh_gex_group/2, handle_kex_dh_gex_reply/2,
handle_new_keys/2, handle_kex_dh_gex_request/2,
handle_kexdh_reply/2,
- unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1]).
-
-%% debug flagso
--define(DBG_ALG, true).
--define(DBG_KEX, true).
--define(DBG_CRYPTO, false).
--define(DBG_PACKET, false).
--define(DBG_MESSAGE, true).
--define(DBG_BIN_MESSAGE, true).
--define(DBG_MAC, false).
--define(DBG_ZLIB, true).
+ unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1,
+ sign/3, verify/4]).
versions(client, Options)->
Vsn = proplists:get_value(vsn, Options, ?DEFAULT_CLIENT_VERSION),
@@ -150,7 +142,7 @@ connect(ConnectionSup, Address, Port, SocketOpts, Opts) ->
case do_connect(Callback, Address, Port, SocketOpts, Timeout) of
{ok, Socket} ->
{ok, Pid} =
- ssh_connection_controler:start_handler_child(ConnectionSup,
+ ssh_connection_sup:start_handler_child(ConnectionSup,
[client, Socket,
[{address, Address},
{port, Port} |
@@ -182,12 +174,11 @@ accept(Address, Port, Socket, Options) ->
ssh_system_sup:connection_supervisor(
ssh_system_sup:system_supervisor(Address, Port)),
{ok, Pid} =
- ssh_connection_controler:start_handler_child(ConnectionSup,
+ ssh_connection_sup:start_handler_child(ConnectionSup,
[server, Socket,
[{address, Address},
{port, Port} | Options]]),
Callback:controlling_process(Socket, Pid),
- ssh_connection_handler:send_event(Pid, socket_control),
{ok, Pid}.
format_version({Major,Minor}) ->
@@ -212,24 +203,24 @@ key_exchange_init_msg(Ssh0) ->
{SshPacket, Ssh} = ssh_packet(Msg, Ssh0),
{Msg, SshPacket, Ssh}.
-kex_init(#ssh{role = Role, opts = Opts}) ->
+kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs}) ->
Random = ssh_bits:random(16),
Compression = case proplists:get_value(compression, Opts, none) of
zlib -> ["zlib", "none"];
none -> ["none", "zlib"]
end,
- kexinit_messsage(Role, Random, Compression).
+ kexinit_messsage(Role, Random, Compression, HostKeyAlgs).
key_init(client, Ssh, Value) ->
Ssh#ssh{c_keyinit = Value};
key_init(server, Ssh, Value) ->
Ssh#ssh{s_keyinit = Value}.
-kexinit_messsage(client, Random, Compression) ->
+kexinit_messsage(client, Random, Compression, HostKeyAlgs) ->
#ssh_msg_kexinit{
cookie = Random,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["ssh-rsa", "ssh-dss"],
+ server_host_key_algorithms = HostKeyAlgs,
encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
mac_algorithms_client_to_server = ["hmac-sha1"],
@@ -240,11 +231,11 @@ kexinit_messsage(client, Random, Compression) ->
languages_server_to_client = []
};
-kexinit_messsage(server, Random, Compression) ->
+kexinit_messsage(server, Random, Compression, HostKeyAlgs) ->
#ssh_msg_kexinit{
cookie = Random,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["ssh-dss"],
+ server_host_key_algorithms = HostKeyAlgs,
encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
mac_algorithms_client_to_server = ["hmac-sha1"],
@@ -300,7 +291,6 @@ install_messages('diffie-hellman-group-exchange-sha1') ->
key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) ->
{G, P} = dh_group1(),
{Private, Public} = dh_gen_key(G, P, 1024),
- %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
{SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0),
{ok, SshPacket,
Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}};
@@ -320,7 +310,6 @@ key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) ->
handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
{G, P} = dh_group1(),
{Private, Public} = dh_gen_key(G, P, 1024),
- %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
K = ssh_math:ipow(E, Private, P),
{Key, K_S} = get_host_key(Ssh0),
H = kex_h(Ssh0, K_S, E, Public, K),
@@ -329,8 +318,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
f = Public,
h_sig = H_SIG
}, Ssh0),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
{ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
shared_secret = K,
exchanged_hash = H,
@@ -338,7 +326,6 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) ->
{Private, Public} = dh_gen_key(G,P,1024),
- %%?dbg(?DBG_KEX, "public: ~p ~n", [Public]),
{SshPacket, Ssh1} =
ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0),
{ok, SshPacket,
@@ -362,8 +349,7 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
#ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) ->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Public, F, K),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
case verify_host_key(Ssh0, HostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -396,8 +382,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
Ssh0) ->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
case verify_host_key(Ssh0, HostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -423,83 +408,68 @@ sid(#ssh{session_id = Id}, _) ->
%%
get_host_key(SSH) ->
#ssh{key_cb = Mod, opts = Opts, algorithms = ALG} = SSH,
- Scope = proplists:get_value(key_scope, Opts, system),
- case ALG#alg.hkey of
- 'ssh-rsa' ->
- case Mod:private_host_rsa_key(Scope, Opts) of
- {ok,Key=#ssh_key { public={N,E}} } ->
- %%?dbg(true, "x~n", []),
- {Key,
- ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
- Error ->
- %%?dbg(true, "y~n", []),
- exit(Error)
- end;
- 'ssh-dss' ->
- case Mod:private_host_dsa_key(Scope, Opts) of
- {ok,Key=#ssh_key { public={P,Q,G,Y}}} ->
- {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint])};
- Error ->
- exit(Error)
- end;
- _ ->
- exit({error, bad_key_type})
+
+ case Mod:host_key(ALG#alg.hkey, Opts) of
+ {ok, #'RSAPrivateKey'{modulus = N, publicExponent = E} = Key} ->
+ {Key,
+ ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
+ {ok, #'DSAPrivateKey'{y = Y, p = P, q = Q, g = G} = Key} ->
+ {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
+ [string,mpint,mpint,mpint,mpint])};
+ Result ->
+ exit({error, {Result, unsupported_key_type}})
end.
-sign_host_key(Ssh, Private, H) ->
- ALG = Ssh#ssh.algorithms,
- Module = case ALG#alg.hkey of
- 'ssh-rsa' ->
- ssh_rsa;
- 'ssh-dss' ->
- ssh_dsa
- end,
- case catch Module:sign(Private, H) of
- {'EXIT', Reason} ->
- error_logger:format("SIGN FAILED: ~p\n", [Reason]),
- {error, Reason};
- SIG ->
- ssh_bits:encode([Module:alg_name() ,SIG],[string,binary])
- end.
+sign_host_key(_Ssh, #'RSAPrivateKey'{} = Private, H) ->
+ Hash = sha, %% Option ?!
+ Signature = sign(H, Hash, Private),
+ ssh_bits:encode(["ssh-rsa", Signature],[string, binary]);
+sign_host_key(_Ssh, #'DSAPrivateKey'{} = Private, H) ->
+ Hash = sha, %% Option ?!
+ RawSignature = sign(H, Hash, Private),
+ ssh_bits:encode(["ssh-dss", RawSignature],[string, binary]).
verify_host_key(SSH, K_S, H, H_SIG) ->
ALG = SSH#ssh.algorithms,
case ALG#alg.hkey of
'ssh-rsa' ->
- case ssh_bits:decode(K_S,[string,mpint,mpint]) of
- ["ssh-rsa", E, N] ->
- ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
- Public = #ssh_key { type=rsa, public={N,E} },
- case catch ssh_rsa:verify(Public, H, SIG) of
- {'EXIT', Reason} ->
- error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
- {error, bad_signature};
- ok ->
- known_host_key(SSH, Public, "ssh-rsa")
- end;
- _ ->
- {error, bad_format}
- end;
+ verify_host_key_rsa(SSH, K_S, H, H_SIG);
'ssh-dss' ->
- case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
- ["ssh-dss",P,Q,G,Y] ->
- ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
- Public = #ssh_key { type=dsa, public={P,Q,G,Y} },
- case catch ssh_dsa:verify(Public, H, SIG) of
- {'EXIT', Reason} ->
- error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
- {error, bad_signature};
- ok ->
- known_host_key(SSH, Public, "ssh-dss")
- end;
- _ ->
- {error, bad_host_key_format}
- end;
+ verify_host_key_dss(SSH, K_S, H, H_SIG);
_ ->
{error, bad_host_key_algorithm}
end.
+verify_host_key_rsa(SSH, K_S, H, H_SIG) ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = #'RSAPublicKey'{publicExponent = E, modulus = N},
+ case verify(H, sha, SIG, Public) of
+ false ->
+ {error, bad_signature};
+ true ->
+ known_host_key(SSH, Public, "ssh-rsa")
+ end;
+ _ ->
+ {error, bad_format}
+ end.
+
+verify_host_key_dss(SSH, K_S, H, H_SIG) ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = {Y, #'Dss-Parms'{p = P, q = Q, g = G}},
+ case verify(H, sha, SIG, Public) of
+ false ->
+ {error, bad_signature};
+ true ->
+ known_host_key(SSH, Public, "ssh-dss")
+ end;
+ _ ->
+ {error, bad_host_key_format}
+ end.
+
accepted_host(Ssh, PeerName, Opts) ->
case proplists:get_value(silently_accept_hosts, Opts, false) of
true ->
@@ -511,14 +481,10 @@ accepted_host(Ssh, PeerName, Opts) ->
known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh,
Public, Alg) ->
PeerName = peer_name(Peer),
- case Mod:lookup_host_key(PeerName, Alg, Opts) of
- {ok, Public} ->
+ case Mod:is_host_key(Public, PeerName, Alg, Opts) of
+ true ->
ok;
- {ok, BadPublic} ->
- error_logger:format("known_host_key: Public ~p BadPublic ~p\n",
- [Public, BadPublic]),
- {error, bad_public_key};
- {error, not_found} ->
+ false ->
case accepted_host(Ssh, PeerName, Opts) of
yes ->
Mod:add_host_key(PeerName, Public, Opts);
@@ -621,7 +587,6 @@ install_alg(SSH) ->
alg_setup(SSH) ->
ALG = SSH#ssh.algorithms,
- %%?dbg(?DBG_ALG, "ALG: setup ~p ~n", [ALG]),
SSH#ssh{kex = ALG#alg.kex,
hkey = ALG#alg.hkey,
encrypt = ALG#alg.encrypt,
@@ -638,7 +603,6 @@ alg_setup(SSH) ->
}.
alg_init(SSH0) ->
- %%?dbg(?DBG_ALG, "ALG: init~n", []),
{ok,SSH1} = send_mac_init(SSH0),
{ok,SSH2} = recv_mac_init(SSH1),
{ok,SSH3} = encrypt_init(SSH2),
@@ -648,7 +612,6 @@ alg_init(SSH0) ->
SSH6.
alg_final(SSH0) ->
- %%?dbg(?DBG_ALG, "ALG: final ~n", []),
{ok,SSH1} = send_mac_final(SSH0),
{ok,SSH2} = recv_mac_final(SSH1),
{ok,SSH3} = encrypt_final(SSH2),
@@ -669,19 +632,15 @@ select(CL, SL) ->
[] -> undefined;
[ALG|_] -> ALG
end,
- %%?dbg(?DBG_ALG, "ALG: select: ~p ~p = ~p~n", [CL, SL, C]),
C.
ssh_packet(#ssh_msg_kexinit{} = Msg, Ssh0) ->
BinMsg = ssh_bits:encode(Msg),
Ssh = key_init(Ssh0#ssh.role, Ssh0, BinMsg),
- %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
pack(BinMsg, Ssh);
ssh_packet(Msg, Ssh) ->
BinMsg = ssh_bits:encode(Msg),
- %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
- %%?dbg(?DBG_BIN_MESSAGE, "Encoded: ~p~n", [BinMsg]),
pack(BinMsg, Ssh).
pack(Data0, #ssh{encrypt_block_size = BlockSize,
@@ -732,17 +691,20 @@ msg_data(PacketData) ->
_:PaddingLen/binary>> = PacketData,
Data.
+sign(SigData, Hash, #'DSAPrivateKey'{} = Key) ->
+ DerSignature = public_key:sign(SigData, Hash, Key),
+ #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature),
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>;
+sign(SigData, Hash, Key) ->
+ public_key:sign(SigData, Hash, Key).
-%% Send a disconnect message
-%% terminate(S, SSH, Code, Message) ->
-%% M = #ssh_msg_disconnect{code=Code,
-%% description = Message,
-%% language = "en"},
-%% send_msg(S, SSH, M),
-%% gen_tcp:close(S),
-%% {error, M}.
+verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) ->
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> = Sig,
+ Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}),
+ public_key:verify(PlainText, Hash, Signature, Key);
+verify(PlainText, Hash, Sig, Key) ->
+ public_key:verify(PlainText, Hash, Sig, Key).
-
%% public key algorithms
%%
%% ssh-dss REQUIRED sign Raw DSS Key
@@ -761,9 +723,6 @@ msg_data(PacketData) ->
%%
%%
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Encryption
%%
@@ -833,19 +792,13 @@ encrypt(#ssh{encrypt = none} = Ssh, Data) ->
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
- %% [IV0,K1,K2,K3]),
Enc = crypto:des3_cbc_encrypt(K1,K2,K3,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
IV = crypto:des_cbc_ivec(Enc),
{Ssh#ssh{encrypt_ctx = IV}, Enc};
encrypt(#ssh{encrypt = 'aes128-cbc',
encrypt_keys = K,
encrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K=~p ~n",
- %% [IV0,K]),
Enc = crypto:aes_cbc_128_encrypt(K,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
IV = crypto:aes_cbc_ivec(Enc),
{Ssh#ssh{encrypt_ctx = IV}, Enc}.
@@ -893,18 +846,12 @@ decrypt(#ssh{decrypt = none} = Ssh, Data) ->
decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys,
decrypt_ctx = IV0} = Ssh, Data) ->
{K1, K2, K3} = Keys,
- %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
- %%[IV0,K1,K2,K3]),
Dec = crypto:des3_cbc_decrypt(K1,K2,K3,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
IV = crypto:des_cbc_ivec(Data),
{Ssh#ssh{decrypt_ctx = IV}, Dec};
decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key,
decrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p Key=~p ~n",
- %% [IV0,Key]),
Dec = crypto:aes_cbc_128_decrypt(Key,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
IV = crypto:aes_cbc_ivec(Data),
{Ssh#ssh{decrypt_ctx = IV}, Dec}.
@@ -936,7 +883,6 @@ compress(#ssh{compress = none} = Ssh, Data) ->
{Ssh, Data};
compress(#ssh{compress = zlib, compress_ctx = Context} = Ssh, Data) ->
Compressed = zlib:deflate(Context, Data, sync),
- %%?dbg(?DBG_ZLIB, "deflate: ~p -> ~p ~n", [Data, Compressed]),
{Ssh, list_to_binary(Compressed)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -960,7 +906,6 @@ decompress(#ssh{decompress = none} = Ssh, Data) ->
{Ssh, Data};
decompress(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh, Data) ->
Decompressed = zlib:inflate(Context, Data),
- %%?dbg(?DBG_ZLIB, "inflate: ~p -> ~p ~n", [Data, Decompressed]),
{Ssh, list_to_binary(Decompressed)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1039,7 +984,6 @@ hash(SSH, Char, N, HASH) ->
K1 = HASH([K, H, Char, SessionID]),
Sz = N div 8,
<<Key:Sz/binary, _/binary>> = hash(K, H, K1, N-128, HASH),
- %%?dbg(?DBG_KEX, "Key ~s: ~s ~n", [Char, fmt_binary(Key, 16, 4)]),
Key.
hash(_K, _H, Ki, N, _HASH) when N =< 0 ->
@@ -1055,6 +999,7 @@ kex_h(SSH, K_S, E, F, K) ->
[string,string,binary,binary,binary,
mpint,mpint,mpint]),
crypto:sha(L).
+
kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
L = if Min==-1; Max==-1 ->
@@ -1075,7 +1020,7 @@ kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
Prime, Gen, E,F,K], Ts)
end,
crypto:sha(L).
-
+
mac_key_size('hmac-sha1') -> 20*8;
mac_key_size('hmac-sha1-96') -> 20*8;
mac_key_size('hmac-md5') -> 16*8;
@@ -1105,9 +1050,6 @@ dh_gen_key(G, P, _Bits) ->
Public = ssh_math:ipow(G, Private, P),
{Private,Public}.
-%% trim(Str) ->
-%% lists:reverse(trim_head(lists:reverse(trim_head(Str)))).
-
trim_tail(Str) ->
lists:reverse(trim_head(lists:reverse(Str))).
@@ -1116,48 +1058,3 @@ trim_head([$\t|Cs]) -> trim_head(Cs);
trim_head([$\n|Cs]) -> trim_head(Cs);
trim_head([$\r|Cs]) -> trim_head(Cs);
trim_head(Cs) -> Cs.
-
-%% Retrieve session_id from ssh, needed by public-key auth
-%get_session_id(SSH) ->
-% {ok, SessionID} = call(SSH, get_session_id),
-
-%% DEBUG utils
-%% Format integers and binaries as hex blocks
-%%
-%% -ifdef(debug).
-%% fmt_binary(B, BlockSize, GroupSize) ->
-%% fmt_block(fmt_bin(B), BlockSize, GroupSize).
-
-%% fmt_block(Bin, BlockSize, GroupSize) ->
-%% fmt_block(Bin, BlockSize, 0, GroupSize).
-
-
-%% fmt_block(Bin, 0, _I, _G) ->
-%% binary_to_list(Bin);
-%% fmt_block(Bin, Sz, G, G) when G =/= 0 ->
-%% ["~n#" | fmt_block(Bin, Sz, 0, G)];
-%% fmt_block(Bin, Sz, I, G) ->
-%% case Bin of
-%% <<Block:Sz/binary, Tail/binary>> ->
-%% if Tail == <<>> ->
-%% [binary_to_list(Block)];
-%% true ->
-%% [binary_to_list(Block), " " | fmt_block(Tail, Sz, I+1, G)]
-%% end;
-%% <<>> ->
-%% [];
-%% _ ->
-%% [binary_to_list(Bin)]
-%% end.
-
-%% %% Format integer or binary as hex
-%% fmt_bin(X) when integer(X) ->
-%% list_to_binary(io_lib:format("~p", [X]));
-%% fmt_bin(X) when binary(X) ->
-%% Sz = size(X)*8,
-%% <<Y:Sz/unsigned-big>> = X,
-%% %%Fmt = "~"++integer_to_list(size(X)*2)++"~p",
-%% list_to_binary(io_lib:format("~p", [Y])).
-
-%% -endif.
-
diff --git a/lib/ssh/src/ssh_userauth.hrl b/lib/ssh/src/ssh_userauth.hrl
index 8eb2d46ed1..7c38719d92 100755..100644
--- a/lib/ssh/src/ssh_userauth.hrl
+++ b/lib/ssh/src/ssh_userauth.hrl
@@ -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_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index c9631a73b1..d5b6dd03d1 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,8 +298,6 @@ xf_send_names(#ssh_xfer{cm = CM, channel = Channel, vsn = Vsn},
Size = 1 + 4 + 4 + Len,
ToSend = [<<?UINT32(Size), ?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(Count)>>,
Data],
- %%?dbg(true, "xf_send_names: Size=~p size(ToSend)=~p\n",
- %% [Size, size(list_to_binary(ToSend))]),
ssh_connection:send(CM, Channel, ToSend).
xf_send_status(XF, ReqId, ErrorCode) ->
@@ -353,7 +351,6 @@ xf_reply(_XF, <<?SSH_FXP_DATA, ?UINT32(ReqID),
{data, ReqID, Data};
xf_reply(XF, <<?SSH_FXP_NAME, ?UINT32(ReqID),
?UINT32(Count), AData/binary>>) ->
- %%?dbg(true, "xf_reply ?SSH_FXP_NAME: AData=~p\n", [AData]),
{name, ReqID, decode_names(XF#ssh_xfer.vsn, Count, AData)};
xf_reply(XF, <<?SSH_FXP_ATTRS, ?UINT32(ReqID),
AData/binary>>) ->
@@ -579,7 +576,6 @@ encode_attr_flags(Vsn, Flags) ->
end, Flags).
encode_file_type(Type) ->
- %%?dbg(true, "encode_file_type(~p)\n", [Type]),
case Type of
regular -> ?SSH_FILEXFER_TYPE_REGULAR;
directory -> ?SSH_FILEXFER_TYPE_DIRECTORY;
@@ -660,15 +656,12 @@ encode_ATTR(Vsn, A) ->
{extended, A#ssh_xfer_attr.extensions}],
0, []),
Type = encode_file_type(A#ssh_xfer_attr.type),
- %%?dbg(true, "encode_ATTR: Vsn=~p A=~p As=~p Flags=~p Type=~p",
- %% [Vsn, A, As, Flags, Type]),
Result = list_to_binary([?uint32(Flags),
if Vsn >= 5 ->
?byte(Type);
true ->
(<<>>)
end, As]),
- %% ?dbg(true, " Result=~p\n", [Result]),
Result.
@@ -722,7 +715,6 @@ encode_As(_Vsn, [], Flags, Acc) ->
decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
- %%?dbg(true, "decode_ATTR: Vsn=~p Flags=~p Tail=~p\n", [Vsn, Flags, Tail]),
{Type,Tail2} =
if Vsn =< 3 ->
{?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
@@ -751,7 +743,6 @@ decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
Tail2).
decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
- %%?dbg(false, "decode_As: Vsn=~p AName=~p AField=~p Flags=~p Tail=~p\n", [Vsn, AName, AField, Flags, Tail]),
case AName of
size when ?is_set(?SSH_FILEXFER_ATTR_SIZE, Flags) ->
<<?UINT64(X), Tail2/binary>> = Tail,
@@ -762,7 +753,6 @@ decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
ownergroup when ?is_set(?SSH_FILEXFER_ATTR_OWNERGROUP, Flags),Vsn>=5 ->
<<?UINT32(Len), Bin:Len/binary, Tail2/binary>> = Tail,
X = binary_to_list(Bin),
- %%?dbg(true, "ownergroup X=~p\n", [X]),
decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
permissions when ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS,Flags),Vsn>=5->
@@ -824,13 +814,11 @@ decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
?UINT32(LLen), _LongName:LLen/binary,
Tail/binary>>) when Vsn =< 3 ->
Name = binary_to_list(FileName),
- %%?dbg(true, "decode_names: ~p\n", [Name]),
{A, Tail2} = decode_ATTR(Vsn, Tail),
[{Name, A} | decode_names(Vsn, I-1, Tail2)];
decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
Tail/binary>>) when Vsn >= 4 ->
Name = binary_to_list(FileName),
- %%?dbg(true, "decode_names: ~p\n", [Name]),
{A, Tail2} = decode_ATTR(Vsn, Tail),
[{Name, A} | decode_names(Vsn, I-1, Tail2)].
@@ -839,8 +827,6 @@ encode_names(Vsn, NamesAndAttrs) ->
encode_name(Vsn, {Name,Attr}, Len) when Vsn =< 3 ->
NLen = length(Name),
- %%?dbg(true, "encode_name: Vsn=~p Name=~p Attr=~p\n",
- %% [Vsn, Name, Attr]),
EncAttr = encode_ATTR(Vsn, Attr),
ALen = size(EncAttr),
NewLen = Len + NLen*2 + 4 + 4 + ALen,
diff --git a/lib/ssh/src/ssh_xfer.hrl b/lib/ssh/src/ssh_xfer.hrl
index 4a4f1a4291..c13950eb6e 100755..100644
--- a/lib/ssh/src/ssh_xfer.hrl
+++ b/lib/ssh/src/ssh_xfer.hrl
@@ -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/sshc_sup.erl b/lib/ssh/src/sshc_sup.erl
index 7c29c669e4..1d2779de23 100644
--- a/lib/ssh/src/sshc_sup.erl
+++ b/lib/ssh/src/sshc_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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 @@
-behaviour(supervisor).
--export([start_link/1, start_child/1]).
+-export([start_link/1, start_child/1, stop_child/1]).
%% Supervisor callback
-export([init/1]).
@@ -40,12 +40,19 @@ start_link(Args) ->
start_child(Args) ->
supervisor:start_child(?MODULE, Args).
+stop_child(Client) ->
+ spawn(fun() ->
+ ClientSup = whereis(?MODULE),
+ supervisor:terminate_child(ClientSup, Client)
+ end),
+ ok.
+
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
init(Args) ->
RestartStrategy = simple_one_for_one,
- MaxR = 10,
+ MaxR = 0,
MaxT = 3600,
{ok, {{RestartStrategy, MaxR, MaxT}, [child_spec(Args)]}}.
@@ -54,12 +61,9 @@ init(Args) ->
%%%=========================================================================
child_spec(_) ->
Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ssh_connection_controler, start_link, []},
- Restart = temporary,
-% Shutdown = infinity,
- Shutdown = 5000,
- Modules = [ssh_connection_controler],
-% Type = supervisor,
- Type = worker,
+ StartFunc = {ssh_connection_sup, start_link, []},
+ Restart = temporary,
+ Shutdown = infinity,
+ Modules = [ssh_connection_sup],
+ Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 1820924ed6..25072688ad 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -32,7 +32,6 @@ VSN=$(GS_VSN)
MODULES= \
ssh_test_lib \
- ssh_SUITE \
ssh_basic_SUITE \
ssh_to_openssh_SUITE \
ssh_sftp_SUITE \
@@ -111,11 +110,11 @@ 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 -)
+ $(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_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl
deleted file mode 100644
index 953c9080f9..0000000000
--- a/lib/ssh/test/ssh_SUITE.erl
+++ /dev/null
@@ -1,72 +0,0 @@
-%%
-%% %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
index 5ea0d98980..2ceaa9daa5 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,9 +41,6 @@
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!"}
@@ -55,10 +52,9 @@ init_per_suite(Config) ->
%% 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),
+end_per_suite(_Config) ->
+ ssh:stop(),
crypto:stop(),
- ssh_test_lib:remove_id_keys(Dir),
ok.
%%--------------------------------------------------------------------
@@ -75,7 +71,6 @@ end_per_suite(Config) ->
%% Description: Initialization before each test case
%%--------------------------------------------------------------------
init_per_testcase(_TestCase, Config) ->
- ssh_test_lib:known_hosts(backup),
ssh:start(),
Config.
@@ -87,9 +82,16 @@ init_per_testcase(_TestCase, Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(_TestCase, _Config) ->
+
+end_per_testcase(TestCase, Config) when TestCase == server_password_option;
+ TestCase == server_userpassword_option ->
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ ssh_test_lib:del_dirs(UserDir),
+ end_per_testcase(Config);
+end_per_testcase(_TestCase, Config) ->
+ end_per_testcase(Config).
+end_per_testcase(_Config) ->
ssh:stop(),
- ssh_test_lib:known_hosts(restore),
ok.
%%--------------------------------------------------------------------
@@ -101,32 +103,109 @@ end_per_testcase(_TestCase, _Config) ->
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
all() ->
- [exec, exec_compressed, shell, daemon_already_started,
+ [app_test,
+ {group, dsa_key},
+ {group, rsa_key},
+ {group, dsa_pass_key},
+ {group, rsa_pass_key},
+ {group, internal_error},
+ daemon_already_started,
server_password_option, server_userpassword_option,
- known_hosts].
+ close].
groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ [{dsa_key, [], [exec, exec_compressed, shell, known_hosts]},
+ {rsa_key, [], [exec, exec_compressed, shell, known_hosts]},
+ {dsa_pass_key, [], [pass_phrase]},
+ {rsa_pass_key, [], [pass_phrase]},
+ {internal_error, [], [internal_error]}
+ ].
+
+init_per_group(dsa_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ Config;
+init_per_group(rsa_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa(DataDir, PrivDir),
+ Config;
+init_per_group(rsa_pass_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa_pass_pharse(DataDir, PrivDir, "Password"),
+ [{pass_phrase, {rsa_pass_phrase, "Password"}}| Config];
+init_per_group(dsa_pass_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"),
+ [{pass_phrase, {dsa_pass_phrase, "Password"}}| Config];
+init_per_group(internal_error, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
+ Config;
+init_per_group(_, Config) ->
+ Config.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(dsa_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+end_per_group(rsa_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_rsa(PrivDir),
+ Config;
+end_per_group(dsa_pass_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+end_per_group(rsa_pass_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_rsa(PrivDir),
+ Config;
+end_per_group(internal_error, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+
+end_per_group(_, 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) ->
+app_test(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").
+app_test(doc) ->
+ ["Application consistency test."];
+app_test(Config) when is_list(Config) ->
+ ?t:app_test(ssh),
+ ok.
+%%--------------------------------------------------------------------
+misc_ssh_options(doc) ->
+ ["Test that we can set some misc options not tested elsewhere, "
+ "some options not yet present are not decided if we should support or "
+ "if they need thier own test case."];
+misc_ssh_options(suite) ->
+ [];
+misc_ssh_options(Config) when is_list(Config) ->
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ CMiscOpt0 = [{connecect_timeout, 1000}, {ip_v6_disabled, false}, {user_dir, UserDir}],
+ CMiscOpt1 = [{connecect_timeout, infinity}, {ip_v6_disabled, true}, {user_dir, UserDir}],
+ SMiscOpt0 = [{ip_v6_disabled, false}, {user_dir, UserDir}, {system_dir, SystemDir}],
+ SMiscOpt1 = [{ip_v6_disabled, true}, {user_dir, UserDir}, {system_dir, SystemDir}],
+
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ basic_test([{client_opts, CMiscOpt0 ++ ClientOpts}, {server_opts, SMiscOpt0 ++ ServerOpts}]),
+ basic_test([{client_opts, CMiscOpt1 ++ ClientOpts}, {server_opts, SMiscOpt1 ++ ServerOpts}]).
+%%--------------------------------------------------------------------
exec(doc) ->
["Test api function ssh_connection:exec"];
@@ -135,11 +214,15 @@ exec(suite) ->
exec(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
{user_interaction, false}]),
{ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
success = ssh_connection:exec(ConnectionRef, ChannelId0,
@@ -177,13 +260,16 @@ 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},
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
{compression, zlib},
{failfun, fun ssh_test_lib:failfun/2}]),
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
{user_interaction, false}]),
{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
success = ssh_connection:exec(ConnectionRef, ChannelId,
@@ -208,17 +294,24 @@ 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},
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
{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),
+ Shell = ssh_test_lib:start_shell(Port, IO, UserDir),
receive
+ {'EXIT', _, _} ->
+ test_server:fail(no_ssh_connection);
ErlShellStart ->
- test_server:format("Erlang shell start: ~p~n", [ErlShellStart])
- end,
+ test_server:format("Erlang shell start: ~p~n", [ErlShellStart]),
+ do_shell(IO, Shell)
+ end.
+
+do_shell(IO, Shell) ->
receive
ErlPrompt0 ->
test_server:format("Erlang prompt: ~p~n", [ErlPrompt0])
@@ -278,9 +371,13 @@ daemon_already_started(suite) ->
daemon_already_started(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},
+ {user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
{error, eaddrinuse} = ssh_test_lib:daemon(Port, [{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun,
fun ssh_test_lib:failfun/2}]),
ssh:stop_daemon(Pid).
@@ -291,9 +388,12 @@ server_password_option(doc) ->
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
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = ?config(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
{password, "morot"}]),
ConnectionRef =
@@ -302,12 +402,15 @@ server_password_option(Config) when is_list(Config) ->
{password, "morot"},
{user_interaction, false},
{user_dir, UserDir}]),
+
+ Reason = "Unable to connect using the available authentication methods",
+
{error, Reason} =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user, "vego"},
- {password, "foo"},
- {user_interaction, false},
- {user_dir, UserDir}]),
+ ssh: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]),
@@ -321,9 +424,12 @@ server_userpassword_option(doc) ->
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
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = ?config(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
{user_passwords, [{"vego", "morot"}]}]),
ConnectionRef =
@@ -334,25 +440,20 @@ server_userpassword_option(Config) when is_list(Config) ->
{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]),
+ Reason = "Unable to connect using the available authentication methods",
- {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]),
-
+ {error, Reason} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ {error, Reason} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "foo"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
@@ -362,16 +463,16 @@ 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},
+ PrivDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{user_dir, PrivDir},{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
- KnownHosts = filename:join(UserDir, "known_hosts"),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
file:delete(KnownHosts),
{error, enoent} = file:read_file(KnownHosts),
ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{user_dir, UserDir},
+ ssh_test_lib:connect(Host, Port, [{user_dir, PrivDir},
{user_interaction, false},
silently_accept_hosts]),
{ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity),
@@ -382,8 +483,91 @@ known_hosts(Config) when is_list(Config) ->
[HostAndIp, Alg, _KeyData] = string:tokens(Line, " "),
[Host, _Ip] = string:tokens(HostAndIp, ","),
"ssh-" ++ _ = Alg,
- ssh:stop_daemon(Pid).
+ ssh:stop_daemon(Pid).
+%%--------------------------------------------------------------------
+
+pass_phrase(doc) ->
+ ["Test that we can use keyes protected by pass phrases"];
+
+pass_phrase(suite) ->
+ [];
+
+pass_phrase(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+ PhraseArg = ?config(pass_phrase, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ PhraseArg,
+ {user_dir, UserDir},
+ {user_interaction, false}]),
+ {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+internal_error(doc) ->
+ ["Test that client does not hang if disconnects due to internal error"];
+
+internal_error(suite) ->
+ [];
+
+internal_error(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ {error,"Internal error"} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user_interaction, false}]),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+close(doc) ->
+ ["Simulate that we try to close an already closed connection"];
+
+close(suite) ->
+ [];
+
+close(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+
+ {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{"vego", "morot"}]},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ {ok, CM} = ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false}]),
+
+ exit(CM, {shutdown, normal}),
+ ok = ssh:close(CM).
+
+
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
+
+basic_test(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon(ServerOpts),
+ {ok, CM} = ssh:connect(Host, Port, ClientOpts),
+ ok = ssh:close(CM),
+ ssh:stop_daemon(Pid).
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_dsa b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
new file mode 100644
index 0000000000..9d7e0dd5fb
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU
+DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl
+zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB
+AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V
+TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3
+CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK
+SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p
+z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd
+WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39
+sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3
+xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ
+dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x
+ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak=
+-----END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key
new file mode 100644
index 0000000000..79968bdd7d
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key
@@ -0,0 +1,16 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337
+zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB
+6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB
+AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW
+NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++
+udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW
+WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt
+n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5
+sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY
++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt
+64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB
+m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT
+tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR
+-----END RSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..75d2025c71
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub
@@ -0,0 +1,5 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8
+semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW
+RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index c96b6de3ea..d40b1d544d 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,14 +24,12 @@
-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").
@@ -46,18 +44,12 @@
%% 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),
+ case (catch crypto:start()) of
+ ok ->
+ ssh:start(),
Config;
- {ok,_} ->
- {skip,"Could not start ssh!"};
- {_,ok} ->
- {skip,"Could not start crypto!"};
- {_,_} ->
- {skip,"Could not start crypto and ssh!"}
+ _ ->
+ {skip,"Could not start crypto!"}
end.
%%--------------------------------------------------------------------
@@ -67,9 +59,8 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(Config) ->
+ ssh:stop(),
crypto:stop(),
- Dir = ?config(priv_dir, Config),
- ssh_test_lib:remove_id_keys(Dir),
Config.
%%--------------------------------------------------------------------
@@ -85,39 +76,34 @@ end_per_suite(Config) ->
%% variable, but should NOT alter/remove any existing entries.
%% Description: Initiation before each test case
%%--------------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
+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].
+ case ?config(group, Config) of
+ erlang_server ->
+ {_,Host, Port} = ?config(sftpd, Config),
+ {ok, ChannelPid, Connection} =
+ ssh_sftp:start_channel(Host, Port,
+ [{user, ?USER},
+ {password, ?PASSWD},
+ {user_interaction, false},
+ {silently_accept_hosts, true}]),
+ Sftp = {ChannelPid, Connection},
+ [{sftp, Sftp}, {watchdog, Dog} | TmpConfig];
+ openssh_server when Case == links ->
+ {skip, "known bug in openssh"};
+ openssh_server ->
+ Host = ssh_test_lib:hostname(),
+ {ok, ChannelPid, Connection} =
+ ssh_sftp:start_channel(Host,
+ [{user_interaction, false},
+ {silently_accept_hosts, true}]),
+ Sftp = {ChannelPid, Connection},
+ [{sftp, Sftp}, {watchdog, Dog} | TmpConfig]
+ end.
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
@@ -127,7 +113,15 @@ 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(_Case, Config) ->
+end_per_testcase(rename_file, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ NewFileName = filename:join(PrivDir, "test.txt"),
+ file:delete(NewFileName),
+ end_per_testcase(Config);
+end_per_testcase(_, Config) ->
+ end_per_testcase(Config).
+
+end_per_testcase(Config) ->
{Sftp, Connection} = ?config(sftp, Config),
ssh_sftp:stop_channel(Sftp),
ssh:close(Connection),
@@ -144,19 +138,47 @@ end_per_testcase(_Case, Config) ->
%% 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].
+ [{group, erlang_server},
+ {group, openssh_server}].
groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ [{erlang_server, [], [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]},
+ {openssh_server, [], [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]}].
+
+init_per_group(erlang_server, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ SysDir = ?config(data_dir, Config),
+ Sftpd =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
+ {user_passwords,
+ [{?USER, ?PASSWD}]},
+ {failfun,
+ fun ssh_test_lib:failfun/2}]),
+ [{group, erlang_server}, {sftpd, Sftpd} | Config];
+
+init_per_group(openssh_server, Config) ->
+ Host = ssh_test_lib:hostname(),
+ case (catch ssh_sftp:start_channel(Host,
+ [{user_interaction, false},
+ {silently_accept_hosts, true}])) of
+ {ok, _ChannelPid, Connection} ->
+ ssh:close(Connection),
+ [{group, openssh_server} | Config];
+ _ ->
+ {skip, "No openssh server"}
+ end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(erlang_server, Config) ->
+ Config;
+end_per_group(_, Config) ->
+ Config.
%% Test cases starts here.
@@ -338,7 +360,7 @@ links(Config) when is_list(Config) ->
FileName = filename:join(PrivDir, "sftp.txt"),
LinkFileName = filename:join(PrivDir, "link_test.txt"),
- ok = ssh_sftp:make_symlink(Sftp, FileName, LinkFileName),
+ ok = ssh_sftp:make_symlink(Sftp, LinkFileName, FileName),
{ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName),
ok
end.
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa
deleted file mode 100644
index 7e3f885f5d..0000000000
--- a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa
+++ /dev/null
@@ -1,15 +0,0 @@
------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
deleted file mode 100644
index 77f57de4af..0000000000
--- a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAyymE3UZxs6YXDfqRfFLiN7GAe68WVB2zk/Oyt74fFzi5AzrEt/FURLTUvFm97mF7Ebcg6FL6yyA58pZTnyUg7qVi6+Im3JFGXf54RQGgulq8lZh+pBpUCy6fSlPr3J9g8GHqNeIG8B2Awd6Zr+AlgJZztZvwZF+Gi89cwt9eDpE= jakob@balin
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index bfe54a3e75..695a7caa7d 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The 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,6 @@
-include_lib("kernel/include/file.hrl").
--define(SFPD_PORT, 9999).
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
-define(XFER_PACKET_SIZE, 32768).
@@ -53,16 +52,18 @@
%% 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),
+ case (catch crypto:start()) of
+ ok ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ %% to make sure we don't use public-key-auth
+ %% this should be tested by other test suites
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:make_dir(UserDir),
Config;
- {ok,_} ->
- {skip,"Could not start ssh!"};
- {_,ok} ->
- {skip,"Could not start crypto!"};
- {_,_} ->
- {skip,"Could not start crypto and ssh!"}
+ _ ->
+ {skip,"Could not start crypto!"}
end.
%%--------------------------------------------------------------------
@@ -71,7 +72,12 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
+end_per_suite(Config) ->
+ SysDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(SysDir),
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:del_dir(UserDir),
+ ssh:stop(),
crypto:stop(),
ok.
@@ -91,15 +97,20 @@ end_per_suite(_Config) ->
init_per_testcase(TestCase, Config) ->
ssh:start(),
prep(Config),
- SysDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ClientUserDir = filename:join(PrivDir, nopubkey),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+
+ Port = ssh_test_lib:inet_port(node()),
+
{ok, Sftpd} =
- ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir},
+ ssh_sftpd:listen(Port, [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{user_passwords,[{?USER, ?PASSWD}]},
{pwdfun, fun(_,_) -> true end}]),
- Cm = ssh_test_lib:connect(?SFPD_PORT,
- [{system_dir, SysDir},
- {user_dir, SysDir},
+ Cm = ssh_test_lib:connect(Port,
+ [{user_dir, ClientUserDir},
{user, ?USER}, {password, ?PASSWD},
{user_interaction, false},
{silently_accept_hosts, true},
@@ -534,56 +545,60 @@ set_attributes(doc) ->
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),
+ case test_server:os_type() of
+ {win32, _} ->
+ {skip, "Known error bug in erts file:read_file_info"};
+ _ ->
+ 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),
+ {ok, FileInfo} = file:read_file_info(FileName),
- OrigPermissions = FileInfo#file_info.mode,
- Permissions = 8#400, %% User read-only
+ OrigPermissions = FileInfo#file_info.mode,
+ Permissions = not_default_permissions(),
- Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS,
+ Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS,
- Atters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR),
- ?uint32(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),
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ set_attributes_file(FileName, Atters, Cm, Channel, ReqId),
- NewAtters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR),
- ?uint32(OrigPermissions)],
+ {ok, NewFileInfo} = file:read_file_info(FileName),
+ NewPermissions = NewFileInfo#file_info.mode,
- NewReqId1 = 3,
+ %% 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("Set original permissions on the now open file"),
+ 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),
- {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
- ?UINT32(?SSH_FX_OK), _/binary>>, _} =
- set_attributes_open_file(Handle, NewAtters, Cm, Channel, NewReqId1),
+ NewAtters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR),
+ ?uint32(OrigPermissions)],
- {ok, NewFileInfo1} = file:read_file_info(FileName),
- OrigPermissions = NewFileInfo1#file_info.mode,
+ NewReqId1 = 3,
- ok.
+ 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
+ end.
%%--------------------------------------------------------------------
ver3_rename_OTP_6352(doc) ->
@@ -932,3 +947,6 @@ sshd_read_file(Config) when is_list(Config) ->
{ok, Data} = file:read_file(FileName),
ok.
+
+not_default_permissions() ->
+ 8#600. %% User read-write-only
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa b/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index 2209af05d5..4c469ed5f7 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,6 @@
-include_lib("kernel/include/file.hrl").
--define(SSHD_PORT, 9999).
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
-define(SSH_MAX_PACKET_SIZE, 32768).
@@ -48,13 +47,14 @@ init_per_suite(Config) ->
case catch crypto:start() of
ok ->
DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_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),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
Config;
_Else ->
{skip,"Could not start ssh!"}
@@ -66,7 +66,11 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
+end_per_suite(Config) ->
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:del_dir(UserDir),
+ SysDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(SysDir),
crypto:stop(),
ok.
@@ -85,7 +89,8 @@ end_per_suite(_Config) ->
%%--------------------------------------------------------------------
init_per_testcase(TestCase, Config) ->
ssh:start(),
- DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(PrivDir, system),
Options =
case atom_to_list(TestCase) of
@@ -93,50 +98,39 @@ init_per_testcase(TestCase, Config) ->
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},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{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},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{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},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
_ ->
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {user_dir, DataDir},
- {system_dir, DataDir}]
+ [{user_dir, PrivDir},
+ {system_dir, SystemDir}]
end,
- {Sftpd, Host, _Port} = ssh_test_lib:daemon(any, ?SSHD_PORT, Options),
+ {Sftpd, Host, Port} = ssh_test_lib:daemon(Options),
{ok, ChannelPid, Connection} =
- ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ ssh_sftp:start_channel(Host, Port,
[{silently_accept_hosts, true},
- {user, ?USER}, {password, ?PASSWD},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ {user_dir, PrivDir},
{timeout, 30000}]),
TmpConfig = lists:keydelete(sftp, 1, Config),
NewConfig = lists:keydelete(sftpd, 1, TmpConfig),
- [{sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
+ [{port, Port}, {sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
@@ -216,6 +210,8 @@ quit_OTP_6349(suite) ->
quit_OTP_6349(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
+ UserDir = ?config(priv_dir, Config),
+ Port = ?config(port, Config),
{Sftp, _} = ?config(sftp, Config),
@@ -226,11 +222,10 @@ quit_OTP_6349(Config) when is_list(Config) ->
Host = ssh_test_lib:hostname(),
timer:sleep(5000),
- {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, Port,
[{silently_accept_hosts, true},
{pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ {user_dir, UserDir},
{user, ?USER}, {password, ?PASSWD}]),
{ok, <<_/binary>>} = ssh_sftp:read_file(NewSftp, FileName),
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 425fae22c1..609663c87a 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,12 +43,8 @@ connect(Host, 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.
+ {ok, ConnectionRef} = ssh:connect(Host, Port, Options),
+ ConnectionRef.
daemon(Options) ->
daemon(any, inet_port(), Options).
@@ -68,15 +64,14 @@ daemon(Host, Port, Options) ->
Error
end.
-
-
+start_shell(Port, IOServer, UserDir) ->
+ spawn_link(?MODULE, init_shell, [Port, IOServer, [{user_dir, UserDir}]]).
start_shell(Port, IOServer) ->
- spawn_link(?MODULE, init_shell, [Port, IOServer]).
+ spawn_link(?MODULE, init_shell, [Port, IOServer, []]).
-init_shell(Port, IOServer) ->
+init_shell(Port, IOServer, UserDir) ->
Host = hostname(),
- UserDir = get_user_dir(),
Options = [{user_interaction, false}, {silently_accept_hosts,
true}] ++ UserDir,
group_leader(IOServer, self()),
@@ -95,13 +90,10 @@ init_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',_, _} ->
@@ -139,12 +131,18 @@ reply(TestCase, Result) ->
receive_exec_result(Msg) ->
test_server:format("Expect data! ~p", [Msg]),
receive
+ {ssh_cm,_,{data,_,1, Data}} ->
+ test_server:format("StdErr: ~p~n", [Data]),
+ receive_exec_result(Msg);
Msg ->
test_server:format("1: Collected data ~p", [Msg]),
expected;
Other ->
+ test_server:format("Other ~p", [Other]),
{unexpected_msg, Other}
end.
+
+
receive_exec_end(ConnectionRef, ChannelId) ->
Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}},
ExitStatus = {ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}},
@@ -181,27 +179,21 @@ inet_port()->
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)).
-
+setup_ssh_auth_keys(RSAFile, DSAFile, Dir) ->
+ Entries = ssh_file_entry(RSAFile) ++ ssh_file_entry(DSAFile),
+ AuthKeys = public_key:ssh_encode(Entries , auth_keys),
+ AuthKeysFile = filename:join(Dir, "authorized_keys"),
+ file:write_file(AuthKeysFile, AuthKeys).
+
+ssh_file_entry(PubFile) ->
+ case file:read_file(PubFile) of
+ {ok, Ssh} ->
+ [{Key, _}] = public_key:ssh_decode(Ssh, public_key),
+ [{Key, [{comment, "Test"}]}];
+ _ ->
+ []
+ end.
+
failfun(_User, {authmethod,none}) ->
ok;
failfun(User, Reason) ->
@@ -222,463 +214,133 @@ known_hosts(BR) ->
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) ->
+setup_dsa(DataDir, UserDir) ->
+ file:copy(filename:join(DataDir, "id_dsa"), filename:join(UserDir, "id_dsa")),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
+ setup_dsa_known_host(DataDir, UserDir),
+ setup_dsa_auth_keys(DataDir, UserDir).
- 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},
+setup_rsa(DataDir, UserDir) ->
+ file:copy(filename:join(DataDir, "id_rsa"), filename:join(UserDir, "id_rsa")),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key.pub")),
+ setup_rsa_known_host(DataDir, UserDir),
+ setup_rsa_auth_keys(DataDir, UserDir).
+
+clean_dsa(UserDir) ->
+ del_dirs(filename:join(UserDir, "system")),
+ file:delete(filename:join(UserDir,"id_dsa")),
+ file:delete(filename:join(UserDir,"known_hosts")),
+ file:delete(filename:join(UserDir,"authorized_keys")).
+
+clean_rsa(UserDir) ->
+ del_dirs(filename:join(UserDir, "system")),
+ file:delete(filename:join(UserDir,"id_rsa")),
+ file:delete(filename:join(UserDir,"known_hosts")),
+ file:delete(filename:join(UserDir,"authorized_keys")).
+
+setup_dsa_pass_pharse(DataDir, UserDir, Phrase) ->
+ {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_dsa")),
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_dsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
+ setup_dsa_known_host(DataDir, UserDir),
+ setup_dsa_auth_keys(DataDir, UserDir).
+
+setup_rsa_pass_pharse(DataDir, UserDir, Phrase) ->
+ {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_rsa")),
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_rsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
+ setup_rsa_known_host(DataDir, UserDir),
+ setup_rsa_auth_keys(DataDir, UserDir).
+
+setup_pass_pharse(KeyBin, OutFile, Phrase) ->
+ [{KeyType, _,_} = Entry0] = public_key:pem_decode(KeyBin),
+ Key = public_key:pem_entry_decode(Entry0),
+ Salt = crypto:rand_bytes(8),
+ Entry = public_key:pem_entry_encode(KeyType, Key,
+ {{"DES-CBC", Salt}, Phrase}),
+ Pem = public_key:pem_encode([Entry]),
+ file:write_file(OutFile, Pem).
+
+setup_dsa_known_host(SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_dsa_key.pub")),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
+setup_rsa_known_host(SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_rsa_key.pub")),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
+setup_known_hosts(Key, UserDir) ->
{ok, Hostname} = inet:gethostname(),
{ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
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}],
-
+ HostNames = [{hostnames,[Hostname, IP]}],
+ KnownHosts = [{Key, 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.
+ KHFile = filename:join(UserDir, "known_hosts"),
+ file:write_file(KHFile, KnownHostsEnc).
-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};
+setup_dsa_auth_keys(Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, "id_dsa")),
+ DSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ 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},
+ setup_auth_keys([{{PKey, Dss}, [{comment, "Test"}]}], UserDir).
+
+setup_rsa_auth_keys(Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, "id_rsa")),
+ RSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ #'RSAPrivateKey'{publicExponent = E, modulus = N} = RSA,
+ PKey = #'RSAPublicKey'{publicExponent = E, modulus = N},
+ setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir).
+
+setup_auth_keys(Keys, Dir) ->
+ AuthKeys = public_key:ssh_encode(Keys, auth_keys),
+ AuthKeysFile = filename:join(Dir, "authorized_keys"),
+ file:write_file(AuthKeysFile, AuthKeys).
+
+
+del_dirs(Dir) ->
+ case file:list_dir(Dir) of
+ {ok, []} ->
+ file:del_dir(Dir);
+ {ok, Files} ->
+ lists:foreach(fun(File) ->
+ FullPath = filename:join(Dir,File),
+ case filelib:is_dir(FullPath) of
+ true ->
+ del_dirs(FullPath),
+ file:del_dir(FullPath);
+ false ->
+ file:delete(FullPath)
+ end
+ end, Files);
_ ->
- #'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)}
+ ok
end.
-pem_to_der(File) ->
- {ok, PemBin} = file:read_file(File),
- public_key:pem_decode(PemBin).
+inet_port(Node) ->
+ {Port, Socket} = do_inet_port(Node),
+ rpc:call(Node, gen_tcp, close, [Socket]),
+ Port.
-der_to_pem(File, Entries) ->
- PemBin = public_key:pem_encode(Entries),
- file:write_file(File, PemBin).
+do_inet_port(Node) ->
+ {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
+ {ok, Port} = rpc:call(Node, inet, port, [Socket]),
+ {Port, Socket}.
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index f959d50484..c337617ee4 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,8 +42,12 @@
init_per_suite(Config) ->
case catch crypto:start() of
ok ->
- ssh_test_lib:make_dsa_files(Config),
- Config;
+ case gen_tcp:connect("localhost", 22, []) of
+ {error,econnrefused} ->
+ {skip,"No openssh deamon"};
+ _ ->
+ Config
+ end;
_Else ->
{skip,"Could not start crypto!"}
end.
@@ -100,26 +104,38 @@ all() ->
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]
+ [{group, erlang_client},
+ {group, erlang_server}
+ ]
end.
groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ [{erlang_client, [], [erlang_shell_client_openssh_server,
+ erlang_client_openssh_server_exec,
+ erlang_client_openssh_server_exec_compressed,
+ erlang_client_openssh_server_setenv,
+ erlang_client_openssh_server_publickey_rsa,
+ erlang_client_openssh_server_publickey_dsa,
+ erlang_client_openssh_server_password]},
+ {erlang_server, [], [erlang_server_openssh_client_exec,
+ erlang_server_openssh_client_exec_compressed,
+ erlang_server_openssh_client_pulic_key_dsa]}
+ ].
+
+init_per_group(erlang_server, Config) ->
+ DataDir = ?config(data_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa_known_host(DataDir, UserDir),
+ Config;
+init_per_group(_, Config) ->
+ Config.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(erlang_server, Config) ->
+ UserDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(UserDir),
+ Config;
+end_per_group(_, Config) ->
+ Config.
%% TEST cases starts here.
%%--------------------------------------------------------------------
@@ -229,7 +245,9 @@ erlang_server_openssh_client_exec(suite) ->
erlang_server_openssh_client_exec(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
-
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -237,7 +255,10 @@ erlang_server_openssh_client_exec(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.",
+
+ test_server:format("Cmd: ~p~n", [Cmd]),
+
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -258,6 +279,9 @@ erlang_server_openssh_client_exec_compressed(suite) ->
erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{compression, zlib},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -265,7 +289,7 @@ erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no -C "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.",
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -330,24 +354,27 @@ 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"}
+ KeyFile = filename:join(Home, ".ssh/id_rsa"),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{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);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, "no ~/.ssh/id_rsa"}
end.
+
%%--------------------------------------------------------------------
erlang_client_openssh_server_publickey_dsa(doc) ->
@@ -356,25 +383,26 @@ 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"}
+ KeyFile = filename:join(Home, ".ssh/id_dsa"),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{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);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, "no ~/.ssh/id_dsa"}
end.
-
%%--------------------------------------------------------------------
erlang_server_openssh_client_pulic_key_dsa(doc) ->
["Validate using dsa publickey."];
@@ -384,6 +412,9 @@ 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),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{public_key_alg, ssh_dsa},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -391,7 +422,8 @@ erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++
+ " " ++ Host ++ " 1+1.",
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -399,7 +431,6 @@ erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
ok
after ?TIMEOUT ->
test_server:fail("Did not receive answer")
-
end,
ssh:stop_daemon(Pid).
@@ -414,7 +445,7 @@ 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},
+ ssh:connect(any, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
{user, "foo"},
{password, "morot"},
{user_interaction, false},
@@ -428,12 +459,12 @@ erlang_client_openssh_server_password(Config) when is_list(Config) ->
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}]),
+ ssh:connect(any, ?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]);
_ ->
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index fe2b915d17..bff73a1b40 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.8
+SSH_VSN = 2.1
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index 5d808d6727..8736913c72 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -117,15 +117,15 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 5df2632149..a4da939d3e 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -30,7 +30,147 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
- <section><title>SSL 4.1.6</title>
+ <section><title>SSL 5.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Robustness and improvement to distribution over SSL</p>
+ <p>
+ Fix a bug where ssl_tls_dist_proxy would crash at caller
+ timeout. Fix a bug where a timeout from the SSL layer
+ would block the distribution indefinately. Run the proxy
+ exclusively on the loopback interface. (Thanks to Paul
+ Guyot)</p>
+ <p>
+ Own Id: OTP-9915</p>
+ </item>
+ <item>
+ <p>
+ Fix setup loop of SSL TLS dist proxy</p>
+ <p>
+ Fix potential leak of processes waiting indefinately for
+ data from closed sockets during socket setup phase.
+ (Thanks to Paul Guyot)</p>
+ <p>
+ Own Id: OTP-9916</p>
+ </item>
+ <item>
+ <p>
+ Correct spelling of registered (Thanks to Richard
+ Carlsson)</p>
+ <p>
+ Own Id: OTP-9925</p>
+ </item>
+ <item>
+ <p>
+ Added TLS PRF function to the SSL API for generation of
+ additional key material from a TLS session. (Thanks to
+ Andreas Schultz)</p>
+ <p>
+ Own Id: OTP-10024</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 5.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Invalidation handling of sessions could cause the
+ time_stamp field in the session record to be set to
+ undefined crashing the session clean up process. This did
+ not affect the connections but would result in that the
+ session table would grow.</p>
+ <p>
+ Own Id: OTP-9696 Aux Id: seq11947 </p>
+ </item>
+ <item>
+ <p>
+ Changed code to use ets:foldl and throw instead of
+ ets:next traversal, avoiding the need to explicitly call
+ ets:safe_fixtable. It was possible to get a badarg-crash
+ under special circumstances.</p>
+ <p>
+ Own Id: OTP-9703 Aux Id: seq11947 </p>
+ </item>
+ <item>
+ <p>
+ Send ssl_closed notification to active ssl user when a
+ tcp error occurs.</p>
+ <p>
+ Own Id: OTP-9734 Aux Id: seq11946 </p>
+ </item>
+ <item>
+ <p>
+ If a passive receive was ongoing during a renegotiation
+ the process evaluating ssl:recv could be left hanging for
+ ever.</p>
+ <p>
+ Own Id: OTP-9744</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support for the old ssl implementation is dropped and the
+ code is removed.</p>
+ <p>
+ Own Id: OTP-7048</p>
+ </item>
+ <item>
+ <p>
+ The erlang distribution can now be run over the new ssl
+ implementation. All options can currently not be set but
+ it is enough to replace to old ssl implementation.</p>
+ <p>
+ Own Id: OTP-7053</p>
+ </item>
+ <item>
+ <p>
+ public_key, ssl and crypto now supports PKCS-8</p>
+ <p>
+ Own Id: OTP-9312</p>
+ </item>
+ <item>
+ <p>
+ Implements a CBC timing attack counter measure. Thanks to
+ Andreas Schultz for providing the patch.</p>
+ <p>
+ Own Id: OTP-9683</p>
+ </item>
+ <item>
+ <p>
+ Mitigates an SSL/TLS Computational DoS attack by
+ disallowing the client to renegotiate many times in a row
+ in a short time interval, thanks to Tuncer Ayaz for
+ alerting us about this.</p>
+ <p>
+ Own Id: OTP-9739</p>
+ </item>
+ <item>
+ <p>
+ Implements the 1/n-1 splitting countermeasure to the
+ Rizzo Duong BEAST attack, affects SSL 3.0 and TLS 1.0.
+ Thanks to Tuncer Ayaz for alerting us about this.</p>
+ <p>
+ Own Id: OTP-9750</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 4.1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 70122e4393..5098d26a3a 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2011</year>
+ <year>1999</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,12 +36,16 @@
<list type="bulleted">
<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>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0, experimental
+ support for TLS-1.1 and TLS-1.2 is also available (no support for elliptic curve cipher suites yet).</item>
<item>For security reasons sslv2 is not supported.</item>
<item>Ephemeral Diffie-Hellman cipher suites are supported
but not Diffie Hellman Certificates cipher suites.</item>
<item>Export cipher suites are not supported as the
U.S. lifted its export restrictions in early 2000.</item>
+ <item>IDEA cipher suites are not supported as they have
+ become deprecated by the latest TLS spec so there is not any
+ real motivation to implement them.</item>
<item>CRL and policy certificate
extensions are not supported yet. </item>
</list>
@@ -62,8 +66,8 @@
</c></p>
<p>For valid options
- see <seealso marker="kernel:inet">inet(3) </seealso> and
- <seealso marker="kernel:gen_tcp">gen_tcp(3) </seealso>.
+ see <seealso marker="kernel:inet">inet(3)</seealso> and
+ <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>.
</p>
<p> <c>ssloption() = {verify, verify_type()} |
@@ -71,10 +75,11 @@
{fail_if_no_peer_cert, boolean()}
{depth, integer()} |
{cert, der_encoded()}| {certfile, path()} |
- {key, der_encoded()} | {keyfile, path()} | {password, string()} |
+ {key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'PrivateKeyInfo', der_encoded()}} |
+ {keyfile, path()} | {password, string()} |
{cacerts, [der_encoded()]} | {cacertfile, path()} |
|{dh, der_encoded()} | {dhfile, path()} | {ciphers, ciphers()} |
- {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} | {reuse_session, fun()}
+ {ssl_imp, ssl_imp()}| {reuse_sessions, boolean()} | {reuse_session, fun()}
</c></p>
<p><c>transportoption() = {CallbackModule, DataTag, ClosedTag}
@@ -105,7 +110,7 @@
<p><c>sslsocket() - opaque to the user. </c></p>
- <p><c>protocol() = sslv3 | tlsv1 </c></p>
+ <p><c>protocol() = sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2' </c></p>
<p><c>ciphers() = [ciphersuite()] | string() (according to old API)</c></p>
@@ -121,6 +126,9 @@
<p> <c>hash() = md5 | sha
</c></p>
+ <p><c>prf_random() = client_random | server_random
+ </c></p>
+
</section>
<section>
@@ -139,7 +147,7 @@
<tag>{certfile, path()}</tag>
<item>Path to a file containing the user's certificate.</item>
- <tag>{key, der_encoded()}</tag>
+ <tag>{key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'PrivateKeyInfo', der_encoded()}}</tag>
<item> The DER encoded users private key. If this option
is supplied it will override the keyfile option.</item>
@@ -189,13 +197,13 @@
</item>
<tag>{depth, integer()}</tag>
- <item>Specifies the maximum
- verification depth, i.e. how far in a chain of certificates the
- verification process can proceed before the verification is
- considered to fail. Peer certificate = 0, CA certificate = 1,
- higher level CA certificate = 2, etc. The value 2 thus means
- that a chain can at most contain peer cert, CA cert, next CA
- cert, and an additional CA cert. The default value is 1.
+ <item>
+ The depth is the maximum number of non-self-issued
+ intermediate certificates that may follow the peer certificate
+ in a valid certification path. So if depth is 0 the PEER must
+ be signed by the trusted ROOT-CA directly, if 1 the path can
+ be PEER, CA, ROOT-CA, if it is 2 PEER, CA, CA, ROOT-CA and so
+ on. The default value is 1.
</item>
<tag>{verify_fun, {Verifyfun :: fun(), InitialUserState :: term()}}</tag>
@@ -560,6 +568,26 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</func>
<func>
+ <name>prf(Socket, Secret, Label, Seed, WantedLength) -> {ok, binary()} | {error, reason()}</name>
+ <fsummary>Use a sessions pseudo random function to generate key material.</fsummary>
+ <type>
+ <v>Socket = sslsocket()</v>
+ <v>Secret = binary() | master_secret</v>
+ <v>Label = binary()</v>
+ <v>Seed = [binary() | prf_random()]</v>
+ <v>WantedLength = non_neg_integer()</v>
+ </type>
+ <desc>
+ <p>Use the pseudo random function (PRF) of a TLS session to generate
+ additional key material. It either takes user generated values for
+ <c>Secret</c> and <c>Seed</c> or atoms directing it use a specific
+ value from the session security parameters.</p>
+ <p>This function can only be used with TLS connections, <c>{error, undefined}</c>
+ is returned for SSLv3 connections.</p>
+ </desc>
+ </func>
+
+ <func>
<name>renegotiate(Socket) -> ok | {error, Reason}</name>
<fsummary> Initiates a new handshake.</fsummary>
<type>
diff --git a/lib/ssl/examples/certs/Makefile b/lib/ssl/examples/certs/Makefile
index a4f067ade6..549f11d709 100644
--- a/lib/ssl/examples/certs/Makefile
+++ b/lib/ssl/examples/certs/Makefile
@@ -54,8 +54,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/certs
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples/certs"
tar cf - etc | \
- (cd $(RELSYSDIR)/examples/certs; tar xf -)
- chmod -R ug+rw $(RELSYSDIR)/examples
+ (cd "$(RELSYSDIR)/examples/certs"; tar xf -)
+ chmod -R ug+rw "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/ssl/examples/src/Makefile b/lib/ssl/examples/src/Makefile
index c5f31b689c..420634c97e 100644
--- a/lib/ssl/examples/src/Makefile
+++ b/lib/ssl/examples/src/Makefile
@@ -63,10 +63,10 @@ docs:
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
+ $(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/ssl/examples/src/client_server.erl b/lib/ssl/examples/src/client_server.erl
index baf5a9185e..133a1764bc 100644
--- a/lib/ssl/examples/src/client_server.erl
+++ b/lib/ssl/examples/src/client_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The 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,18 +21,14 @@
-module(client_server).
--export([start/0, start/1, init_connect/1]).
+-export([start/0, init_connect/1]).
start() ->
- start([ssl, subject]).
-
-start(CertOpts) ->
%% Start ssl application
+ application:start(crypto),
+ application:start(public_key),
application:start(ssl),
- %% Always seed
- ssl:seed("ellynatefttidppohjeh"),
-
%% Let the current process be the server that listens and accepts
%% Listen
{ok, LSock} = ssl:listen(0, mk_opts(listen)),
@@ -40,14 +36,14 @@ start(CertOpts) ->
io:fwrite("Listen: port = ~w.~n", [LPort]),
%% Spawn the client process that connects to the server
- spawn(?MODULE, init_connect, [{LPort, CertOpts}]),
+ spawn(?MODULE, init_connect, [LPort]),
%% Accept
{ok, ASock} = ssl:transport_accept(LSock),
ok = ssl:ssl_accept(ASock),
io:fwrite("Accept: accepted.~n"),
- {ok, Cert} = ssl:peercert(ASock, CertOpts),
- io:fwrite("Accept: peer cert:~n~p~n", [Cert]),
+ {ok, Cert} = ssl:peercert(ASock),
+ io:fwrite("Accept: peer cert:~n~p~n", [public_key:pkix_decode_cert(Cert, otp)]),
io:fwrite("Accept: sending \"hello\".~n"),
ssl:send(ASock, "hello"),
{error, closed} = ssl:recv(ASock, 0),
@@ -59,12 +55,12 @@ start(CertOpts) ->
%% Client connect
-init_connect({LPort, CertOpts}) ->
+init_connect(LPort) ->
{ok, Host} = inet:gethostname(),
{ok, CSock} = ssl:connect(Host, LPort, mk_opts(connect)),
io:fwrite("Connect: connected.~n"),
- {ok, Cert} = ssl:peercert(CSock, CertOpts),
- io:fwrite("Connect: peer cert:~n~p~n", [Cert]),
+ {ok, Cert} = ssl:peercert(CSock),
+ io:fwrite("Connect: peer cert:~n~p~n", [public_key:pkix_decode_cert(Cert, otp)]),
{ok, Data} = ssl:recv(CSock, 0),
io:fwrite("Connect: got data: ~p~n", [Data]),
io:fwrite("Connect: closing and terminating.~n"),
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index dc69b53b28..a08444b8dd 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -37,6 +37,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
# Common Macros
# ----------------------------------------------------
+BEHAVIOUR_MODULES= \
+ ssl_session_cache_api
+
MODULES= \
ssl \
ssl_alert \
@@ -53,7 +56,6 @@ MODULES= \
ssl_handshake \
ssl_manager \
ssl_session \
- ssl_session_cache_api \
ssl_session_cache \
ssl_record \
ssl_ssl2 \
@@ -66,10 +68,15 @@ INTERNAL_HRL_FILES = \
ssl_alert.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_internal.hrl \
ssl_record.hrl
-ERL_FILES= $(MODULES:%=%.erl)
+ERL_FILES= \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
+
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
+
APP_FILE= ssl.app
APPUP_FILE= ssl.appup
@@ -83,6 +90,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# ----------------------------------------------------
EXTRA_ERLC_FLAGS = +warn_unused_vars
ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
+ -pz $(EBIN) \
-pz $(ERL_TOP)/lib/public_key/ebin \
$(EXTRA_ERLC_FLAGS) -DVSN=\"$(VSN)\"
@@ -91,6 +99,8 @@ ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
# Targets
# ----------------------------------------------------
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
+
debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
@@ -105,23 +115,18 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
docs:
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) \
- $(APPUP_TARGET) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) \
+ $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
release_docs_spec:
-
-
-
-
-
-
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 115527aae0..57c859bf24 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The 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 @@ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
Kernel = self(),
- spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end).
+ spawn_opt(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]).
do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
[Name, Address] = splitnode(Node, LongOrShortNames),
@@ -229,9 +229,7 @@ connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Addre
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
+ f_address = fun get_remote_id/2
}).
common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
@@ -273,3 +271,11 @@ common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
P = proplists:get_value(send_pend, Stats, 0),
{ok, R,W,P}
end}.
+
+get_remote_id(Socket, _Node) ->
+ case ssl_tls_dist_proxy:get_tcp_address(Socket) of
+ {ok, Address} ->
+ Address;
+ {error, _Reason} ->
+ ?shutdown(no_node)
+ end.
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 29674f30da..76550fa04b 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,21 +1,15 @@
%% -*- 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.0.1", [{restart_application, ssl}]}
+ {"5.0.1", [{restart_application, ssl}]},
+ {"5.0", [{restart_application, ssl}]},
+ {<<"4\\.*">>, [{restart_application, ssl}]},
+ {<<"3\\.*">>, [{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.0.1", [{restart_application, ssl}]}
+ {"5.0.1", [{restart_application, ssl}]},
+ {"5.0", [{restart_application, ssl}]},
+ {<<"4\\.*">>, [{restart_application, ssl}]},
+ {<<"3\\.*">>, [{restart_application, ssl}]}
]}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 35f9410562..40d933a256 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,12 +25,13 @@
-export([start/0, start/1, stop/0, transport_accept/1,
transport_accept/2, ssl_accept/1, ssl_accept/2, ssl_accept/3,
- cipher_suites/0, cipher_suites/1, close/1, shutdown/2,
+ cipher_suites/0, cipher_suites/1, suite_definition/1,
+ close/1, shutdown/2,
connect/3, connect/2, connect/4, connection_info/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]).
+ renegotiate/1, prf/5, clear_pem_cache/0, random_bytes/1]).
-deprecated({pid, 1, next_major_release}).
@@ -40,6 +41,12 @@
-include_lib("public_key/include/public_key.hrl").
+%% Visible in API
+-export_type([connect_option/0, listen_option/0, ssl_option/0, transport_option/0,
+ erl_cipher_suite/0, %% From ssl_cipher.hrl
+ tls_atom_version/0, %% From ssl_internal.hrl
+ prf_random/0]).
+
-record(config, {ssl, %% SSL parameters
inet_user, %% User set inet options
emulated, %% #socket_option{} emulated
@@ -67,7 +74,7 @@
-type ssl_imp() :: new | old.
-type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}}.
-
+-type prf_random() :: client_random | server_random.
%%--------------------------------------------------------------------
-spec start() -> ok | {error, reason()}.
@@ -298,6 +305,15 @@ peercert(#sslsocket{pid = Pid}) ->
end.
%%--------------------------------------------------------------------
+-spec suite_definition(cipher_suite()) -> erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition.
+%%--------------------------------------------------------------------
+suite_definition(S) ->
+ {KeyExchange, Cipher, Hash, _} = ssl_cipher:suite_definition(S),
+ {KeyExchange, Cipher, Hash}.
+
+%%--------------------------------------------------------------------
-spec cipher_suites() -> [erl_cipher_suite()].
-spec cipher_suites(erlang | openssl) -> [erl_cipher_suite()] | [string()].
@@ -308,7 +324,7 @@ cipher_suites() ->
cipher_suites(erlang) ->
Version = ssl_record:highest_protocol_version([]),
- [ssl_cipher:suite_definition(S) || S <- ssl_cipher:suites(Version)];
+ [suite_definition(S) || S <- ssl_cipher:suites(Version)];
cipher_suites(openssl) ->
Version = ssl_record:highest_protocol_version([]),
@@ -402,7 +418,7 @@ session_info(#sslsocket{pid = Pid, fd = new_ssl}) ->
versions() ->
Vsns = ssl_record:supported_protocol_versions(),
SupportedVsns = [ssl_record:protocol_version(Vsn) || Vsn <- Vsns],
- AvailableVsns = ?DEFAULT_SUPPORTED_VERSIONS,
+ AvailableVsns = ?ALL_SUPPORTED_VERSIONS,
[{ssl_app, ?VSN}, {supported, SupportedVsns}, {available, AvailableVsns}].
@@ -414,6 +430,26 @@ versions() ->
renegotiate(#sslsocket{pid = Pid, fd = new_ssl}) ->
ssl_connection:renegotiation(Pid).
+%%--------------------------------------------------------------------
+-spec prf(#sslsocket{}, binary() | 'master_secret', binary(),
+ binary() | prf_random(), non_neg_integer()) ->
+ {ok, binary()} | {error, reason()}.
+%%
+%% Description: use a ssl sessions TLS PRF to generate key material
+%%--------------------------------------------------------------------
+prf(#sslsocket{pid = Pid, fd = new_ssl},
+ Secret, Label, Seed, WantedLength) ->
+ ssl_connection:prf(Pid, Secret, Label, Seed, WantedLength).
+
+
+%%--------------------------------------------------------------------
+-spec clear_pem_cache() -> ok.
+%%
+%% Description: Clear the PEM cache
+%%--------------------------------------------------------------------
+clear_pem_cache() ->
+ ssl_manager:clear_pem_cache().
+
%%---------------------------------------------------------------
-spec format_error({error, term()}) -> list().
%%
@@ -448,6 +484,23 @@ format_error(Error) ->
Other
end.
+%%--------------------------------------------------------------------
+-spec random_bytes(integer()) -> binary().
+
+%%
+%% Description: Generates cryptographically secure random sequence if possible
+%% fallbacks on pseudo random function
+%%--------------------------------------------------------------------
+random_bytes(N) ->
+ try crypto:strong_rand_bytes(N) of
+ RandBytes ->
+ RandBytes
+ catch
+ error:low_entropy ->
+ crypto:rand_bytes(N)
+ end.
+
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -515,7 +568,7 @@ handle_options(Opts0, _Role) ->
throw({error, {eoptions, {verify, Value}}})
end,
- CertFile = handle_option(certfile, Opts, ""),
+ CertFile = handle_option(certfile, Opts, <<>>),
SSLOptions = #ssl_options{
versions = handle_option(versions, Opts, []),
@@ -602,17 +655,29 @@ validate_option(depth, Value) when is_integer(Value),
validate_option(cert, Value) when Value == undefined;
is_binary(Value) ->
Value;
-validate_option(certfile, Value) when Value == undefined; is_list(Value) ->
+validate_option(certfile, undefined = Value) ->
+ Value;
+validate_option(certfile, Value) when is_binary(Value) ->
Value;
+validate_option(certfile, Value) when is_list(Value) ->
+ list_to_binary(Value);
validate_option(key, undefined) ->
undefined;
validate_option(key, {KeyType, Value}) when is_binary(Value),
- KeyType == rsa;
- KeyType == dsa ->
+ KeyType == rsa; %% Backwards compatibility
+ KeyType == dsa; %% Backwards compatibility
+ KeyType == 'RSAPrivateKey';
+ KeyType == 'DSAPrivateKey';
+ KeyType == 'PrivateKeyInfo' ->
{KeyType, Value};
-validate_option(keyfile, Value) when is_list(Value) ->
+
+validate_option(keyfile, undefined) ->
+ <<>>;
+validate_option(keyfile, Value) when is_binary(Value) ->
Value;
+validate_option(keyfile, Value) when is_list(Value), Value =/= "" ->
+ list_to_binary(Value);
validate_option(password, Value) when is_list(Value) ->
Value;
@@ -622,16 +687,20 @@ validate_option(cacerts, Value) when Value == undefined;
%% certfile must be present in some cases otherwhise it can be set
%% to the empty string.
validate_option(cacertfile, undefined) ->
- "";
-validate_option(cacertfile, Value) when is_list(Value), Value =/= "" ->
+ <<>>;
+validate_option(cacertfile, Value) when is_binary(Value) ->
Value;
+validate_option(cacertfile, Value) when is_list(Value), Value =/= ""->
+ list_to_binary(Value);
validate_option(dh, Value) when Value == undefined;
is_binary(Value) ->
Value;
validate_option(dhfile, undefined = Value) ->
Value;
-validate_option(dhfile, Value) when is_list(Value), Value =/= "" ->
+validate_option(dhfile, Value) when is_binary(Value) ->
Value;
+validate_option(dhfile, Value) when is_list(Value), Value =/= "" ->
+ list_to_binary(Value);
validate_option(ciphers, Value) when is_list(Value) ->
Version = ssl_record:highest_protocol_version([]),
try cipher_suites(Version, Value)
@@ -667,7 +736,8 @@ validate_option(Opt, Value) ->
validate_versions([], Versions) ->
Versions;
-validate_versions([Version | Rest], Versions) when Version == 'tlsv1.1';
+validate_versions([Version | Rest], Versions) when Version == 'tlsv1.2';
+ Version == 'tlsv1.1';
Version == tlsv1;
Version == sslv3 ->
validate_versions(Rest, Versions);
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index eb1228afa4..222b3f1ad7 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,6 +84,8 @@ description_txt(?DECOMPRESSION_FAILURE) ->
"decompression failure";
description_txt(?HANDSHAKE_FAILURE) ->
"handshake failure";
+description_txt(?NO_CERTIFICATE_RESERVED) ->
+ "No certificate reserved";
description_txt(?BAD_CERTIFICATE) ->
"bad certificate";
description_txt(?UNSUPPORTED_CERTIFICATE) ->
diff --git a/lib/ssl/src/ssl_alert.hrl b/lib/ssl/src/ssl_alert.hrl
index 6470b82d50..92548edab7 100644
--- a/lib/ssl/src/ssl_alert.hrl
+++ b/lib/ssl/src/ssl_alert.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
%% record_overflow(22),
%% decompression_failure(30),
%% handshake_failure(40),
+%% no_certificate_RESERVED(41), %% Only sslv3
%% bad_certificate(42),
%% unsupported_certificate(43),
%% certificate_revoked(44),
@@ -69,6 +70,7 @@
-define(RECORD_OVERFLOW, 22).
-define(DECOMPRESSION_FAILURE, 30).
-define(HANDSHAKE_FAILURE, 40).
+-define(NO_CERTIFICATE_RESERVED, 41).
-define(BAD_CERTIFICATE, 42).
-define(UNSUPPORTED_CERTIFICATE, 43).
-define(CERTIFICATE_REVOKED, 44).
diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl
index c9f81726b9..0c475a6d01 100644
--- a/lib/ssl/src/ssl_app.erl
+++ b/lib/ssl/src/ssl_app.erl
@@ -27,16 +27,9 @@
-export([start/2, stop/1]).
-%%--------------------------------------------------------------------
--spec start(normal | {takeover, node()} | {failover, node()}, list()) ->
- ignore | {ok, pid()} | {error, term()}.
-%%--------------------------------------------------------------------
start(_Type, _StartArgs) ->
ssl_sup:start_link().
-%--------------------------------------------------------------------
--spec stop(term())-> ok.
-%%--------------------------------------------------------------------
stop(_State) ->
ok.
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 422ea6404b..86f5617b54 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, no_candidate, CertDbHandle) of
+ case find_issuer(OtpCert, CertDbHandle) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
@@ -103,7 +103,7 @@ certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]).
%%--------------------------------------------------------------------
--spec file_to_certificats(string(), term()) -> [der_cert()].
+-spec file_to_certificats(binary(), term()) -> [der_cert()].
%%
%% Description: Return list of DER encoded certificates.
%%--------------------------------------------------------------------
@@ -111,7 +111,7 @@ 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,
+-spec validate_extension(term(), {extension, #'Extension'{}} | {bad_cert, atom()} | valid,
term()) -> {valid, term()} |
{fail, tuple()} |
{unknown, term()}.
@@ -172,7 +172,12 @@ extensions_list(Extensions) ->
%% Description:
%%--------------------------------------------------------------------
signature_type(RSA) when RSA == ?sha1WithRSAEncryption;
- RSA == ?md5WithRSAEncryption ->
+ RSA == ?md5WithRSAEncryption;
+ RSA == ?sha224WithRSAEncryption;
+ RSA == ?sha256WithRSAEncryption;
+ RSA == ?sha384WithRSAEncryption;
+ RSA == ?sha512WithRSAEncryption
+ ->
rsa;
signature_type(?'id-dsa-with-sha1') ->
dsa.
@@ -193,7 +198,7 @@ certificate_chain(OtpCert, _Cert, CertDbHandle, CertsDbRef, Chain) ->
{_, true = SelfSigned} ->
certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, no_candidate, CertDbHandle) of
+ case find_issuer(OtpCert, CertDbHandle) of
{ok, {SerialNr, Issuer}} ->
certificate_chain(CertDbHandle, CertsDbRef, Chain,
SerialNr, Issuer, SelfSigned);
@@ -227,17 +232,24 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned
{ok, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, PrevCandidateKey, CertDbHandle) ->
- case ssl_manager:issuer_candidate(PrevCandidateKey, CertDbHandle) of
- no_more_candidates ->
- {error, issuer_not_found};
- {Key, {_Cert, ErlCertCandidate}} ->
- case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
- true ->
- public_key:pkix_issuer_id(ErlCertCandidate, self);
- false ->
- find_issuer(OtpCert, Key, CertDbHandle)
- end
+find_issuer(OtpCert, CertDbHandle) ->
+ IsIssuerFun = fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
+ case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
+ true ->
+ throw(public_key:pkix_issuer_id(ErlCertCandidate, self));
+ false ->
+ Acc
+ end;
+ (_, Acc) ->
+ Acc
+ end,
+
+ try ssl_certificate_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of
+ issuer_not_found ->
+ {error, issuer_not_found}
+ catch
+ {ok, _IssuerId} = Return ->
+ Return
end.
is_valid_extkey_usage(KeyUse, client) ->
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index 0560a02110..67d00f0da7 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,12 +24,13 @@
-module(ssl_certificate_db).
-include("ssl_internal.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/file.hrl").
-export([create/0, remove/1, add_trusted_certs/3,
- 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()}.
+ remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1,
+ ref_count/3, lookup_trusted_cert/4, foldl/3,
+ lookup_cached_pem/2, cache_pem_file/2, cache_pem_file/3,
+ lookup/2]).
%%====================================================================
%% Internal application API
@@ -43,9 +44,14 @@
%% the process that called create may call the other functions.
%%--------------------------------------------------------------------
create() ->
- [ets:new(ssl_otp_certificate_db, [set, protected]),
- ets:new(ssl_file_to_ref, [set, protected]),
- ets:new(ssl_pid_to_file, [bag, private])].
+ [%% Let connection process delete trusted certs
+ %% that can only belong to one connection. (Supplied directly
+ %% on DER format to ssl:connect/listen.)
+ ets:new(ssl_otp_cacertificate_db, [set, public]),
+ %% Let connection processes call ref_count/3 directly
+ ets:new(ssl_otp_ca_file_ref, [set, public]),
+ ets:new(ssl_otp_pem_cache, [set, protected])
+ ].
%%--------------------------------------------------------------------
-spec remove([db_handle()]) -> term().
@@ -53,7 +59,9 @@ create() ->
%% Description: Removes database db
%%--------------------------------------------------------------------
remove(Dbs) ->
- lists:foreach(fun(Db) -> true = ets:delete(Db) end, Dbs).
+ lists:foreach(fun(Db) ->
+ true = ets:delete(Db)
+ end, Dbs).
%%--------------------------------------------------------------------
-spec lookup_trusted_cert(db_handle(), certdb_ref(), serialnumber(), issuer()) ->
@@ -72,11 +80,14 @@ lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
{ok, Certs}
end.
-lookup_cached_certs(DbHandle, File) ->
- ets:lookup(DbHandle, {file, File}).
+lookup_cached_pem([_, _, PemChache], MD5) ->
+ lookup_cached_pem(PemChache, MD5);
+lookup_cached_pem(PemChache, MD5) ->
+ lookup(MD5, PemChache).
%%--------------------------------------------------------------------
--spec add_trusted_certs(pid(), string() | {der, list()}, [db_handle()]) -> {ok, [db_handle()]}.
+-spec add_trusted_certs(pid(), {erlang:timestamp(), 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
@@ -86,115 +97,55 @@ add_trusted_certs(_Pid, {der, DerList}, [CerDb, _,_]) ->
NewRef = make_ref(),
add_certs_from_der(DerList, NewRef, CerDb),
{ok, NewRef};
-add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) ->
- Ref = case lookup(File, FileToRefDb) of
- undefined ->
- NewRef = make_ref(),
- add_certs_from_file(File, NewRef, CertsDb),
- insert(File, NewRef, 1, FileToRefDb),
- NewRef;
- [OldRef] ->
- ref_count(File,FileToRefDb,1),
- OldRef
- end,
- insert(Pid, File, PidToFileDb),
- {ok, Ref}.
+
+add_trusted_certs(_Pid, File, [CertsDb, RefDb, PemChache] = Db) ->
+ MD5 = crypto:md5(File),
+ case lookup_cached_pem(Db, MD5) of
+ [{_Content, Ref}] ->
+ ref_count(Ref, RefDb, 1),
+ {ok, Ref};
+ [Content] ->
+ Ref = make_ref(),
+ update_counter(Ref, 1, RefDb),
+ insert(MD5, {Content, Ref}, PemChache),
+ add_certs_from_pem(Content, Ref, CertsDb),
+ {ok, Ref};
+ undefined ->
+ new_trusted_cert_entry({MD5, File}, Db)
+ end.
%%--------------------------------------------------------------------
--spec cache_pem_file(pid(), string(), time(), [db_handle()]) -> term().
+-spec cache_pem_file({binary(), binary()}, [db_handle()]) -> term().
+-spec cache_pem_file(reference(), {binary(), binary()}, [db_handle()]) -> term().
%%
%% Description: Cache file as binary in DB
%%--------------------------------------------------------------------
-cache_pem_file(Pid, File, Time, [CertsDb, _FileToRefDb, PidToFileDb]) ->
- {ok, PemBin} = file:read_file(File),
+cache_pem_file({MD5, File}, [_CertsDb, _RefDb, PemChache]) ->
+ {ok, PemBin} = file:read_file(File),
Content = public_key:pem_decode(PemBin),
- insert({file, File}, {Time, Content}, CertsDb),
- insert(Pid, File, PidToFileDb),
+ insert(MD5, Content, PemChache),
{ok, Content}.
-%--------------------------------------------------------------------
--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
-%% when those processes are finish the cache will be cleaned. It is
-%% a rare but possible case a new ssl client/server is started with
-%% a filename with the same name as previously started client/server
-%% but with different content.
-%% --------------------------------------------------------------------
-uncache_pem_file(File, [_CertsDb, _FileToRefDb, PidToFileDb]) ->
- Pids = select(PidToFileDb, [{{'$1', File},[],['$$']}]),
- lists:foreach(fun([Pid]) ->
- exit(Pid, shutdown)
- end, Pids).
-
-
-
-%%--------------------------------------------------------------------
--spec remove_trusted_certs(pid(), [db_handle()]) -> term().
-
-%%
-%% Description: Removes trusted certs originating from
-%% the file associated to Pid from the runtime database.
-%%--------------------------------------------------------------------
-remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) ->
- Files = lookup(Pid, PidToFileDb),
- delete(Pid, PidToFileDb),
- Clear = fun(File) ->
- delete({file,File}, CertsDb),
- try
- 0 = ref_count(File, FileToRefDb, -1),
- case lookup(File, FileToRefDb) of
- [Ref] when is_reference(Ref) ->
- remove_certs(Ref, CertsDb);
- _ -> ok
- end,
- delete(File, FileToRefDb)
- catch _:_ ->
- ok
- end
- end,
- case Files of
- undefined -> ok;
- _ ->
- [Clear(File) || File <- Files],
- ok
- end.
+cache_pem_file(Ref, {MD5, File}, [_CertsDb, _RefDb, PemChache]) ->
+ {ok, PemBin} = file:read_file(File),
+ Content = public_key:pem_decode(PemBin),
+ insert(MD5, {Content, Ref}, PemChache),
+ {ok, Content}.
+
+remove_trusted_certs(Ref, CertsDb) ->
+ remove_certs(Ref, CertsDb).
%%--------------------------------------------------------------------
--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
-%% the extension 'ce-authorityKeyIdentifier' we can
-%% try to find the issuer in the database over known
-%% certificates.
-%%--------------------------------------------------------------------
-issuer_candidate(no_candidate, Db) ->
- case ets:first(Db) of
- '$end_of_table' ->
- no_more_candidates;
- {file, _} = Key ->
- issuer_candidate(Key, Db);
- Key ->
- [Cert] = lookup(Key, Db),
- {Key, Cert}
- end;
-
-issuer_candidate(PrevCandidateKey, Db) ->
- case ets:next(Db, PrevCandidateKey) of
- '$end_of_table' ->
- no_more_candidates;
- {file, _} = Key ->
- issuer_candidate(Key, Db);
- Key ->
- [Cert] = lookup(Key, Db),
- {Key, Cert}
- end.
+-spec remove(term(), db_handle()) -> term().
+%%
+%% Description: Removes an element in a <Db>.
+%%--------------------------------------------------------------------
+remove(Key, Db) ->
+ _ = ets:delete(Db, Key).
%%--------------------------------------------------------------------
-spec lookup(term(), db_handle()) -> term() | undefined.
%%
-%% Description: Looks up an element in a certificat <Db>.
+%% Description: Looks up an element in a <Db>.
%%--------------------------------------------------------------------
lookup(Key, Db) ->
case ets:lookup(Db, Key) of
@@ -206,24 +157,55 @@ lookup(Key, Db) ->
end,
[Pick(Data) || Data <- Contents]
end.
+%%--------------------------------------------------------------------
+-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
+%% accumulator which is passed to the next call. The function returns
+%% the final value of the accumulator. Acc0 is returned if the certifate
+%% db is empty.
+%%--------------------------------------------------------------------
+foldl(Fun, Acc0, Cache) ->
+ ets:foldl(Fun, Acc0, Cache).
%%--------------------------------------------------------------------
-%%% Internal functions
+-spec ref_count(term(), db_handle(), integer()) -> integer().
+%%
+%% Description: Updates a reference counter in a <Db>.
%%--------------------------------------------------------------------
-insert(Key, Data, Db) ->
- true = ets:insert(Db, {Key, Data}).
+ref_count(Key, Db, N) ->
+ ets:update_counter(Db,Key,N).
-insert(Key, Data, Count, Db) ->
- true = ets:insert(Db, {Key, Count, Data}).
+%%--------------------------------------------------------------------
+-spec clear(db_handle()) -> term().
+%%
+%% Description: Clears the cache
+%%--------------------------------------------------------------------
+clear(Db) ->
+ ets:delete_all_objects(Db).
-ref_count(Key, Db,N) ->
- ets:update_counter(Db,Key,N).
+%%--------------------------------------------------------------------
+-spec db_size(db_handle()) -> integer().
+%%
+%% Description: Returns the size of the db
+%%--------------------------------------------------------------------
+db_size(Db) ->
+ ets:info(Db, size).
-delete(Key, Db) ->
- _ = ets:delete(Db, Key).
+%%--------------------------------------------------------------------
+%%-spec insert(Key::term(), Data::term(), Db::db_handle()) -> no_return().
+%%
+%% Description: Inserts data into <Db>
+%%--------------------------------------------------------------------
+insert(Key, Data, Db) ->
+ true = ets:insert(Db, {Key, Data}).
-select(Db, MatchSpec)->
- ets:select(Db, MatchSpec).
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+update_counter(Key, Count, Db) ->
+ true = ets:insert(Db, {Key, Count}).
remove_certs(Ref, CertsDb) ->
ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}).
@@ -232,10 +214,8 @@ add_certs_from_der(DerList, Ref, CertsDb) ->
Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end,
[Add(Cert) || Cert <- DerList].
-add_certs_from_file(File, Ref, CertsDb) ->
+add_certs_from_pem(PemEntries, Ref, CertsDb) ->
Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end,
- {ok, PemBin} = file:read_file(File),
- PemEntries = public_key:pem_decode(PemBin),
[Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries].
add_certs(Cert, Ref, CertsDb) ->
@@ -251,3 +231,10 @@ add_certs(Cert, Ref, CertsDb) ->
"it could not be correctly decoded.~n", []),
error_logger:info_report(Report)
end.
+
+new_trusted_cert_entry(FileRef, [CertsDb, RefDb, _] = Db) ->
+ Ref = make_ref(),
+ update_counter(Ref, 1, RefDb),
+ {ok, Content} = cache_pem_file(Ref, FileRef, Db),
+ add_certs_from_pem(Content, Ref, CertsDb),
+ {ok, Ref}.
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 72f02a4362..567690a413 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,25 +28,27 @@
-include("ssl_internal.hrl").
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
+-include("ssl_handshake.hrl").
-include("ssl_alert.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([security_parameters/2, suite_definition/1,
- decipher/5, cipher/4,
+-export([security_parameters/3, suite_definition/1,
+ decipher/5, cipher/5,
suite/1, suites/1, anonymous_suites/0,
- openssl_suite/1, openssl_suite_name/1, filter/2]).
+ openssl_suite/1, openssl_suite_name/1, filter/2,
+ hash_algorithm/1, sign_algorithm/1]).
-compile(inline).
%%--------------------------------------------------------------------
--spec security_parameters(cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(tls_version(), cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%%
%% Description: Returns a security parameters record where the
%% cipher values has been updated according to <CipherSuite>
%%-------------------------------------------------------------------
-security_parameters(CipherSuite, SecParams) ->
- { _, Cipher, Hash} = suite_definition(CipherSuite),
+security_parameters(Version, CipherSuite, SecParams) ->
+ { _, Cipher, Hash, PrfHashAlg} = suite_definition(CipherSuite),
SecParams#security_parameters{
cipher_suite = CipherSuite,
bulk_cipher_algorithm = bulk_cipher_algorithm(Cipher),
@@ -55,20 +57,21 @@ security_parameters(CipherSuite, SecParams) ->
expanded_key_material_length = expanded_key_material(Cipher),
key_material_length = key_material(Cipher),
iv_size = iv_size(Cipher),
- mac_algorithm = mac_algorithm(Hash),
+ mac_algorithm = hash_algorithm(Hash),
+ prf_algorithm = prf_algorithm(PrfHashAlg, Version),
hash_size = hash_size(Hash)}.
%%--------------------------------------------------------------------
--spec cipher(cipher_enum(), #cipher_state{}, binary(), binary()) ->
+-spec cipher(cipher_enum(), #cipher_state{}, binary(), binary(), tls_version()) ->
{binary(), #cipher_state{}}.
%%
%% Description: Encrypts the data and the MAC using chipher described
%% by cipher_enum() and updating the cipher state
%%-------------------------------------------------------------------
-cipher(?NULL, CipherState, <<>>, Fragment) ->
+cipher(?NULL, CipherState, <<>>, Fragment, _Version) ->
GenStreamCipherList = [Fragment, <<>>],
{GenStreamCipherList, CipherState};
-cipher(?RC4, CipherState, Mac, Fragment) ->
+cipher(?RC4, CipherState, Mac, Fragment, _Version) ->
State0 = case CipherState#cipher_state.state of
undefined -> crypto:rc4_set_key(CipherState#cipher_state.key);
S -> S
@@ -76,32 +79,41 @@ cipher(?RC4, CipherState, Mac, Fragment) ->
GenStreamCipherList = [Fragment, Mac],
{State1, T} = crypto:rc4_encrypt_with_state(State0, GenStreamCipherList),
{T, CipherState#cipher_state{state = State1}};
-cipher(?DES, CipherState, Mac, Fragment) ->
+cipher(?DES, CipherState, Mac, Fragment, Version) ->
block_cipher(fun(Key, IV, T) ->
crypto:des_cbc_encrypt(Key, IV, T)
- end, block_size(des_cbc), CipherState, Mac, Fragment);
-cipher(?'3DES', CipherState, Mac, Fragment) ->
+ end, block_size(des_cbc), CipherState, Mac, Fragment, Version);
+cipher(?'3DES', CipherState, Mac, Fragment, Version) ->
block_cipher(fun(<<K1:8/binary, K2:8/binary, K3:8/binary>>, IV, T) ->
crypto:des3_cbc_encrypt(K1, K2, K3, IV, T)
- end, block_size(des_cbc), CipherState, Mac, Fragment);
-cipher(?AES, CipherState, Mac, Fragment) ->
+ end, block_size(des_cbc), CipherState, Mac, Fragment, Version);
+cipher(?AES, CipherState, Mac, Fragment, Version) ->
block_cipher(fun(Key, IV, T) when byte_size(Key) =:= 16 ->
crypto:aes_cbc_128_encrypt(Key, IV, T);
(Key, IV, T) when byte_size(Key) =:= 32 ->
crypto:aes_cbc_256_encrypt(Key, IV, T)
- end, block_size(aes_128_cbc), CipherState, Mac, Fragment).
-%% cipher(?IDEA, CipherState, Mac, Fragment) ->
-%% block_cipher(fun(Key, IV, T) ->
-%% crypto:idea_cbc_encrypt(Key, IV, T)
-%% end, block_size(idea_cbc), CipherState, Mac, Fragment);
-
-block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
- Mac, Fragment) ->
+ end, block_size(aes_128_cbc), CipherState, Mac, Fragment, Version).
+
+build_cipher_block(BlockSz, Mac, Fragment) ->
TotSz = byte_size(Mac) + erlang:iolist_size(Fragment) + 1,
{PaddingLength, Padding} = get_padding(TotSz, BlockSz),
- L = [Fragment, Mac, PaddingLength, Padding],
+ [Fragment, Mac, PaddingLength, Padding].
+
+block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
+ Mac, Fragment, {3, N})
+ when N == 0; N == 1 ->
+ L = build_cipher_block(BlockSz, Mac, Fragment),
T = Fun(Key, IV, L),
NextIV = next_iv(T, IV),
+ {T, CS0#cipher_state{iv=NextIV}};
+
+block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
+ Mac, Fragment, {3, N})
+ when N == 2; N == 3 ->
+ NextIV = random_iv(IV),
+ L0 = build_cipher_block(BlockSz, Mac, Fragment),
+ L = [NextIV|L0],
+ T = Fun(Key, IV, L),
{T, CS0#cipher_state{iv=NextIV}}.
%%--------------------------------------------------------------------
@@ -147,25 +159,27 @@ decipher(?AES, HashSz, CipherState, Fragment, Version) ->
(Key, IV, T) when byte_size(Key) =:= 32 ->
crypto:aes_cbc_256_decrypt(Key, IV, T)
end, CipherState, HashSz, Fragment, Version).
-%% decipher(?IDEA, HashSz, CipherState, Fragment, Version) ->
-%% block_decipher(fun(Key, IV, T) ->
-%% crypto:idea_cbc_decrypt(Key, IV, T)
-%% end, CipherState, HashSz, Fragment, Version);
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
HashSz, Fragment, Version) ->
- try Fun(Key, IV, Fragment) of
- Text ->
- GBC = generic_block_cipher_from_bin(Text, HashSz),
- case is_correct_padding(GBC, Version) of
- true ->
- Content = GBC#generic_block_cipher.content,
- Mac = GBC#generic_block_cipher.mac,
- CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
- {Content, Mac, CipherState1};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end
+ try
+ Text = Fun(Key, IV, Fragment),
+ NextIV = next_iv(Fragment, IV),
+ GBC = generic_block_cipher_from_bin(Version, Text, NextIV, HashSz),
+ Content = GBC#generic_block_cipher.content,
+ Mac = GBC#generic_block_cipher.mac,
+ CipherState1 = CipherState0#cipher_state{iv=GBC#generic_block_cipher.next_iv},
+ case is_correct_padding(GBC, Version) of
+ true ->
+ {Content, Mac, CipherState1};
+ false ->
+ %% decryption failed or invalid padding,
+ %% intentionally break Content to make
+ %% sure a packet with invalid padding
+ %% but otherwise correct data will fail
+ %% the MAC test later
+ {<<16#F0, Content/binary>>, Mac, CipherState1}
+ end
catch
_:_ ->
%% This is a DECRYPTION_FAILED but
@@ -182,8 +196,8 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
%%--------------------------------------------------------------------
suites({3, 0}) ->
ssl_ssl3:suites();
-suites({3, N}) when N == 1; N == 2 ->
- ssl_tls1:suites().
+suites({3, N}) ->
+ ssl_tls1:suites(N).
%%--------------------------------------------------------------------
-spec anonymous_suites() -> [cipher_suite()].
@@ -196,10 +210,12 @@ anonymous_suites() ->
?TLS_DH_anon_WITH_DES_CBC_SHA,
?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
?TLS_DH_anon_WITH_AES_128_CBC_SHA,
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA].
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA256].
%%--------------------------------------------------------------------
--spec suite_definition(cipher_suite()) -> erl_cipher_suite().
+-spec suite_definition(cipher_suite()) -> int_cipher_suite().
%%
%% Description: Return erlang cipher suite definition.
%% Note: Currently not supported suites are commented away.
@@ -207,56 +223,81 @@ anonymous_suites() ->
%%-------------------------------------------------------------------
%% TLS v1.1 suites
suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
- {null, null, null};
+ {null, null, null, null};
%% suite_definition(?TLS_RSA_WITH_NULL_MD5) ->
-%% {rsa, null, md5};
+%% {rsa, null, md5, default_prf};
%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
-%% {rsa, null, sha};
+%% {rsa, null, sha, default_prf};
suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
- {rsa, rc4_128, md5};
-suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
- {rsa, rc4_128, sha};
-%% suite_definition(?TLS_RSA_WITH_IDEA_CBC_SHA) ->
-%% {rsa, idea_cbc, sha};
-suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
- {rsa, des_cbc, sha};
+ {rsa, rc4_128, md5, default_prf};
+suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
+ {rsa, rc4_128, sha, default_prf};
+suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ {rsa, des_cbc, sha, default_prf};
suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {rsa, '3des_ede_cbc', sha};
+ {rsa, '3des_ede_cbc', sha, default_prf};
suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
- {dhe_dss, des_cbc, sha};
+ {dhe_dss, des_cbc, sha, default_prf};
suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- {dhe_dss, '3des_ede_cbc', sha};
+ {dhe_dss, '3des_ede_cbc', sha, default_prf};
suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- {dhe_rsa, des_cbc, sha};
+ {dhe_rsa, des_cbc, sha, default_prf};
suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {dhe_rsa, '3des_ede_cbc', sha};
+ {dhe_rsa, '3des_ede_cbc', sha, default_prf};
%%% TSL V1.1 AES suites
suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- {rsa, aes_128_cbc, sha};
+ {rsa, aes_128_cbc, sha, default_prf};
suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- {dhe_dss, aes_128_cbc, sha};
+ {dhe_dss, aes_128_cbc, sha, default_prf};
suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- {dhe_rsa, aes_128_cbc, sha};
+ {dhe_rsa, aes_128_cbc, sha, default_prf};
suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- {rsa, aes_256_cbc, sha};
+ {rsa, aes_256_cbc, sha, default_prf};
suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- {dhe_dss, aes_256_cbc, sha};
+ {dhe_dss, aes_256_cbc, sha, default_prf};
suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- {dhe_rsa, aes_256_cbc, sha};
+ {dhe_rsa, aes_256_cbc, sha, default_prf};
+
+%% TLS v1.2 suites
+
+%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
+%% {rsa, null, sha, default_prf};
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ {rsa, aes_128_cbc, sha256, default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ {rsa, aes_256_cbc, sha256, default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ {dhe_dss, aes_128_cbc, sha256, default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ {dhe_rsa, aes_128_cbc, sha256, default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ {dhe_dss, aes_256_cbc, sha256, default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ {dhe_rsa, aes_256_cbc, sha256, default_prf};
+
+%% not defined YET:
+%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
+%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
%%% DH-ANON deprecated by TLS spec and not available
%%% by default, but good for testing purposes.
suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
- {dh_anon, rc4_128, md5};
+ {dh_anon, rc4_128, md5, default_prf};
suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
- {dh_anon, des_cbc, sha};
+ {dh_anon, des_cbc, sha, default_prf};
suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
- {dh_anon, '3des_ede_cbc', sha};
+ {dh_anon, '3des_ede_cbc', sha, default_prf};
suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
- {dh_anon, aes_128_cbc, sha};
+ {dh_anon, aes_128_cbc, sha, default_prf};
suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
- {dh_anon, aes_256_cbc, sha}.
+ {dh_anon, aes_256_cbc, sha, default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
+ {dh_anon, aes_128_cbc, sha256, default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
+ {dh_anon, aes_256_cbc, sha256, default_prf}.
%%--------------------------------------------------------------------
-spec suite(erl_cipher_suite()) -> cipher_suite().
@@ -273,8 +314,6 @@ suite({rsa, rc4_128, md5}) ->
?TLS_RSA_WITH_RC4_128_MD5;
suite({rsa, rc4_128, sha}) ->
?TLS_RSA_WITH_RC4_128_SHA;
-%% suite({rsa, idea_cbc, sha}) ->
-%% ?TLS_RSA_WITH_IDEA_CBC_SHA;
suite({rsa, des_cbc, sha}) ->
?TLS_RSA_WITH_DES_CBC_SHA;
suite({rsa, '3des_ede_cbc', sha}) ->
@@ -310,7 +349,28 @@ suite({dhe_dss, aes_256_cbc, sha}) ->
suite({dhe_rsa, aes_256_cbc, sha}) ->
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
suite({dh_anon, aes_256_cbc, sha}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA.
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
+
+%% TLS v1.2 suites
+
+%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
+%% {rsa, null, sha, sha256};
+suite({rsa, aes_128_cbc, sha256}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+suite({rsa, aes_256_cbc, sha256}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+suite({dhe_dss, aes_128_cbc, sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+suite({dhe_rsa, aes_128_cbc, sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+suite({dhe_dss, aes_256_cbc, sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+suite({dhe_rsa, aes_256_cbc, sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+suite({dh_anon, aes_128_cbc, sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
+suite({dh_anon, aes_256_cbc, sha256}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA256.
%%--------------------------------------------------------------------
-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
@@ -318,6 +378,18 @@ suite({dh_anon, aes_256_cbc, sha}) ->
%% Description: Return TLS cipher suite definition.
%%--------------------------------------------------------------------
%% translate constants <-> openssl-strings
+openssl_suite("DHE-RSA-AES256-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-DSS-AES256-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+openssl_suite("AES256-SHA256") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-RSA-AES128-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-DSS-AES128-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+openssl_suite("AES128-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
openssl_suite("DHE-RSA-AES256-SHA") ->
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
openssl_suite("DHE-DSS-AES256-SHA") ->
@@ -336,8 +408,6 @@ openssl_suite("DHE-DSS-AES128-SHA") ->
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
openssl_suite("AES128-SHA") ->
?TLS_RSA_WITH_AES_128_CBC_SHA;
-%%openssl_suite("IDEA-CBC-SHA") ->
-%% ?TLS_RSA_WITH_IDEA_CBC_SHA;
openssl_suite("RC4-SHA") ->
?TLS_RSA_WITH_RC4_128_SHA;
openssl_suite("RC4-MD5") ->
@@ -369,8 +439,6 @@ openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
"DHE-DSS-AES128-SHA";
openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
"AES128-SHA";
-%% openssl_suite_name(?TLS_RSA_WITH_IDEA_CBC_SHA) ->
-%% "IDEA-CBC-SHA";
openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
"RC4-SHA";
openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
@@ -379,6 +447,28 @@ openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
"EDH-RSA-DES-CBC-SHA";
openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
"DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
+ "NULL-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ "AES128-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ "AES256-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DH-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DHE-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DH-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DH-RSA-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DHE-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DHE-RSA-AES256-SHA256";
%% No oppenssl name
openssl_suite_name(Cipher) ->
suite_definition(Cipher).
@@ -406,9 +496,6 @@ filter(DerCert, Ciphers) ->
bulk_cipher_algorithm(null) ->
?NULL;
-%% Not supported yet
-%% bulk_cipher_algorithm(idea_cbc) ->
-%% ?IDEA;
bulk_cipher_algorithm(rc4_128) ->
?RC4;
bulk_cipher_algorithm(des_cbc) ->
@@ -423,8 +510,7 @@ type(Cipher) when Cipher == null;
Cipher == rc4_128 ->
?STREAM;
-type(Cipher) when Cipher == idea_cbc;
- Cipher == des_cbc;
+type(Cipher) when Cipher == des_cbc;
Cipher == '3des_ede_cbc';
Cipher == aes_128_cbc;
Cipher == aes_256_cbc ->
@@ -432,8 +518,7 @@ type(Cipher) when Cipher == idea_cbc;
key_material(null) ->
0;
-key_material(Cipher) when Cipher == idea_cbc;
- Cipher == rc4_128 ->
+key_material(rc4_128) ->
16;
key_material(des_cbc) ->
8;
@@ -446,8 +531,7 @@ key_material(aes_256_cbc) ->
expanded_key_material(null) ->
0;
-expanded_key_material(Cipher) when Cipher == idea_cbc;
- Cipher == rc4_128 ->
+expanded_key_material(rc4_128) ->
16;
expanded_key_material(Cipher) when Cipher == des_cbc ->
8;
@@ -462,8 +546,7 @@ effective_key_bits(null) ->
0;
effective_key_bits(des_cbc) ->
56;
-effective_key_bits(Cipher) when Cipher == idea_cbc;
- Cipher == rc4_128;
+effective_key_bits(Cipher) when Cipher == rc4_128;
Cipher == aes_128_cbc ->
128;
effective_key_bits('3des_ede_cbc') ->
@@ -477,8 +560,7 @@ iv_size(Cipher) when Cipher == null;
iv_size(Cipher) ->
block_size(Cipher).
-block_size(Cipher) when Cipher == idea_cbc;
- Cipher == des_cbc;
+block_size(Cipher) when Cipher == des_cbc;
Cipher == '3des_ede_cbc' ->
8;
@@ -486,28 +568,98 @@ block_size(Cipher) when Cipher == aes_128_cbc;
Cipher == aes_256_cbc ->
16.
-mac_algorithm(null) ->
- ?NULL;
-mac_algorithm(md5) ->
- ?MD5;
-mac_algorithm(sha) ->
- ?SHA.
+prf_algorithm(default_prf, {3, N}) when N >= 3 ->
+ ?SHA256;
+prf_algorithm(default_prf, {3, _}) ->
+ ?MD5SHA;
+prf_algorithm(Algo, _) ->
+ hash_algorithm(Algo).
+
+hash_algorithm(null) -> ?NULL;
+hash_algorithm(md5) -> ?MD5;
+hash_algorithm(sha) -> ?SHA; %% Only sha always refers to "SHA-1"
+hash_algorithm(sha224) -> ?SHA224;
+hash_algorithm(sha256) -> ?SHA256;
+hash_algorithm(sha384) -> ?SHA384;
+hash_algorithm(sha512) -> ?SHA512;
+hash_algorithm(?NULL) -> null;
+hash_algorithm(?MD5) -> md5;
+hash_algorithm(?SHA) -> sha;
+hash_algorithm(?SHA224) -> sha224;
+hash_algorithm(?SHA256) -> sha256;
+hash_algorithm(?SHA384) -> sha384;
+hash_algorithm(?SHA512) -> sha512.
+
+sign_algorithm(anon) -> ?ANON;
+sign_algorithm(rsa) -> ?RSA;
+sign_algorithm(dsa) -> ?DSA;
+sign_algorithm(ecdsa) -> ?ECDSA;
+sign_algorithm(?ANON) -> anon;
+sign_algorithm(?RSA) -> rsa;
+sign_algorithm(?DSA) -> dsa;
+sign_algorithm(?ECDSA) -> ecdsa.
hash_size(null) ->
0;
hash_size(md5) ->
16;
hash_size(sha) ->
- 20.
-
-generic_block_cipher_from_bin(T, HashSize) ->
+ 20;
+hash_size(sha256) ->
+ 32.
+%% Currently no supported cipher suites defaults to sha384 or sha512
+%% so these clauses are not needed at the moment.
+%% hash_size(sha384) ->
+%% 48;
+%% hash_size(sha512) ->
+%% 64.
+
+%% RFC 5246: 6.2.3.2. CBC Block Cipher
+%%
+%% Implementation note: Canvel et al. [CBCTIME] have demonstrated a
+%% timing attack on CBC padding based on the time required to compute
+%% the MAC. In order to defend against this attack, implementations
+%% MUST ensure that record processing time is essentially the same
+%% whether or not the padding is correct. In general, the best way to
+%% do this is to compute the MAC even if the padding is incorrect, and
+%% only then reject the packet. For instance, if the pad appears to be
+%% incorrect, the implementation might assume a zero-length pad and then
+%% compute the MAC. This leaves a small timing channel, since MAC
+%% performance depends to some extent on the size of the data fragment,
+%% but it is not believed to be large enough to be exploitable, due to
+%% the large block size of existing MACs and the small size of the
+%% timing signal.
+%%
+%% implementation note:
+%% We return the original (possibly invalid) PadLength in any case.
+%% An invalid PadLength will be caught by is_correct_padding/2
+%%
+generic_block_cipher_from_bin({3, N}, T, IV, HashSize)
+ when N == 0; N == 1 ->
Sz1 = byte_size(T) - 1,
- <<_:Sz1/binary, ?BYTE(PadLength)>> = T,
+ <<_:Sz1/binary, ?BYTE(PadLength0)>> = T,
+ PadLength = if
+ PadLength0 >= Sz1 -> 0;
+ true -> PadLength0
+ end,
CompressedLength = byte_size(T) - PadLength - 1 - HashSize,
<<Content:CompressedLength/binary, Mac:HashSize/binary,
- Padding:PadLength/binary, ?BYTE(PadLength)>> = T,
+ Padding:PadLength/binary, ?BYTE(PadLength0)>> = T,
#generic_block_cipher{content=Content, mac=Mac,
- padding=Padding, padding_length=PadLength}.
+ padding=Padding, padding_length=PadLength0,
+ next_iv = IV};
+
+generic_block_cipher_from_bin({3, N}, T, IV, HashSize)
+ when N == 2; N == 3 ->
+ Sz1 = byte_size(T) - 1,
+ <<_:Sz1/binary, ?BYTE(PadLength)>> = T,
+ IVLength = byte_size(IV),
+ CompressedLength = byte_size(T) - IVLength - PadLength - 1 - HashSize,
+ <<NextIV:IVLength/binary, Content:CompressedLength/binary, Mac:HashSize/binary,
+ Padding:PadLength/binary, ?BYTE(PadLength)>> = T,
+ #generic_block_cipher{content=Content, mac=Mac,
+ padding=Padding, padding_length=PadLength,
+ next_iv = NextIV}.
generic_stream_cipher_from_bin(T, HashSz) ->
Sz = byte_size(T),
@@ -516,17 +668,18 @@ generic_stream_cipher_from_bin(T, HashSz) ->
#generic_stream_cipher{content=Content,
mac=Mac}.
-is_correct_padding(_, {3, 0}) ->
- true;
-%% For interoperability reasons we do not check the padding in TLS 1.0 as it
-%% is not strictly required and breaks interopability with for instance
-%% Google.
-is_correct_padding(_, {3, 1}) ->
- true;
+%% For interoperability reasons we do not check the padding content in
+%% SSL 3.0 and TLS 1.0 as it is not strictly required and breaks
+%% interopability with for instance Google.
+is_correct_padding(#generic_block_cipher{padding_length = Len,
+ padding = Padding}, {3, N})
+ when N == 0; N == 1 ->
+ Len == byte_size(Padding);
%% Padding must be check in TLS 1.1 and after
-is_correct_padding(#generic_block_cipher{padding_length = Len, padding = Padding}, _) ->
- list_to_binary(lists:duplicate(Len, Len)) == Padding.
-
+is_correct_padding(#generic_block_cipher{padding_length = Len,
+ padding = Padding}, _) ->
+ Len == byte_size(Padding) andalso
+ list_to_binary(lists:duplicate(Len, Len)) == Padding.
get_padding(Length, BlockSize) ->
get_padding_aux(BlockSize, Length rem BlockSize).
@@ -537,6 +690,10 @@ get_padding_aux(BlockSize, PadLength) ->
N = BlockSize - PadLength,
{N, list_to_binary(lists:duplicate(N, N))}.
+random_iv(IV) ->
+ IVSz = byte_size(IV),
+ ssl:random_bytes(IVSz).
+
next_iv(Bin, IV) ->
BinSz = byte_size(Bin),
IVSz = byte_size(IV),
@@ -548,16 +705,19 @@ rsa_signed_suites() ->
dhe_rsa_suites() ++ rsa_suites().
dhe_rsa_suites() ->
- [?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ [?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_RSA_WITH_DES_CBC_SHA].
rsa_suites() ->
- [?TLS_RSA_WITH_AES_256_CBC_SHA,
+ [?TLS_RSA_WITH_AES_256_CBC_SHA256,
+ ?TLS_RSA_WITH_AES_256_CBC_SHA,
?TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256,
?TLS_RSA_WITH_AES_128_CBC_SHA,
- %%?TLS_RSA_WITH_IDEA_CBC_SHA,
?TLS_RSA_WITH_RC4_128_SHA,
?TLS_RSA_WITH_RC4_128_MD5,
?TLS_RSA_WITH_DES_CBC_SHA].
@@ -566,8 +726,10 @@ dsa_signed_suites() ->
dhe_dss_suites().
dhe_dss_suites() ->
- [?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ [?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA].
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 8bd68cc190..0f439f8ed5 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,9 @@
-type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc'
| aes_128_cbc | aes_256_cbc.
--type hash() :: null | sha | md5.
+-type hash() :: null | sha | md5 | sha256 | sha384 | sha512.
-type erl_cipher_suite() :: {key_algo(), cipher(), hash()}.
+-type int_cipher_suite() :: {key_algo(), cipher(), hash(), hash()}.
-type cipher_suite() :: binary().
-type cipher_enum() :: integer().
-type openssl_cipher_suite() :: string().
@@ -177,6 +178,47 @@
%% TLS_DH_anon_WITH_AES_256_CBC_SHA = { 0x00, 0x3A };
-define(TLS_DH_anon_WITH_AES_256_CBC_SHA, <<?BYTE(16#00), ?BYTE(16#3A)>>).
+%%% TLS 1.2 Cipher Suites RFC 5246
+
+%% TLS_RSA_WITH_NULL_SHA256 = { 0x00,0x3B };
+-define(TLS_RSA_WITH_NULL_SHA256, <<?BYTE(16#00), ?BYTE(16#3B)>>).
+
+%% TLS_RSA_WITH_AES_128_CBC_SHA256 = { 0x00,0x3C };
+-define(TLS_RSA_WITH_AES_128_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#3C)>>).
+
+%% TLS_RSA_WITH_AES_256_CBC_SHA256 = { 0x00,0x3D };
+-define(TLS_RSA_WITH_AES_256_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#3D)>>).
+
+%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = { 0x00,0x3E };
+-define(TLS_DH_DSS_WITH_AES_128_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#3E)>>).
+
+%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = { 0x00,0x3F };
+-define(TLS_DH_RSA_WITH_AES_128_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#3F)>>).
+
+%% TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = { 0x00,0x40 };
+-define(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#40)>>).
+
+%% TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = { 0x00,0x67 };
+-define(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#67)>>).
+
+%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = { 0x00,0x68 };
+-define(TLS_DH_DSS_WITH_AES_256_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#68)>>).
+
+%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = { 0x00,0x69 };
+-define(TLS_DH_RSA_WITH_AES_256_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#69)>>).
+
+%% TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = { 0x00,0x6A };
+-define(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#6A)>>).
+
+%% TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = { 0x00,0x6B };
+-define(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#6B)>>).
+
+%% TLS_DH_anon_WITH_AES_128_CBC_SHA256 = { 0x00,0x6C };
+-define(TLS_DH_anon_WITH_AES_128_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#6C)>>).
+
+%% TLS_DH_anon_WITH_AES_256_CBC_SHA256 = { 0x00,0x6D };
+-define(TLS_DH_anon_WITH_AES_256_CBC_SHA256, <<?BYTE(16#00), ?BYTE(16#6D)>>).
+
%%% Kerberos Cipher Suites
%% TLS_KRB5_WITH_DES_CBC_SHA = { 0x00,0x1E };
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index c772697f1d..ff2556c488 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,14 +40,15 @@
-export([send/2, recv/3, connect/7, ssl_accept/6, handshake/2,
socket_control/3, close/1, shutdown/2,
new_user/2, get_opts/2, set_opts/2, info/1, session_info/1,
- peer_certificate/1, sockname/1, peername/1, renegotiation/1]).
+ peer_certificate/1, sockname/1, peername/1, renegotiation/1,
+ prf/5]).
%% Called by ssl_connection_sup
-export([start_link/7]).
%% gen_fsm callbacks
--export([init/1, hello/2, certify/2, cipher/2, connection/2,
- abbreviated/2, handle_event/3,
+-export([init/1, hello/2, certify/2, cipher/2,
+ abbreviated/2, connection/2, handle_event/3,
handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
-record(state, {
@@ -66,8 +67,7 @@
tls_packets = [], % Not yet handled decode ssl/tls packets.
tls_record_buffer, % binary() buffer of incomplete records
tls_handshake_buffer, % binary() buffer of incomplete handshakes
- %% {{md5_hash, sha_hash}, {prev_md5, prev_sha}} (binary())
- tls_handshake_hashes, % see above
+ tls_handshake_history, % tls_handshake_history()
tls_cipher_texts, % list() received but not deciphered yet
cert_db, %
session, % #session{} from ssl_handshake.hrl
@@ -77,25 +77,28 @@
supported_protocol_versions, % [atom()]
client_certificate_requested = false,
key_algorithm, % atom as defined by cipher_suite
+ hashsign_algorithm, % atom as defined by cipher_suite
public_key_info, % PKIX: {Algorithm, PublicKey, PublicKeyParams}
private_key, % PKIX: #'RSAPrivateKey'{}
diffie_hellman_params, % PKIX: #'DHParameter'{} relevant for server side
diffie_hellman_keys, % {PublicKey, PrivateKey}
premaster_secret, %
- cert_db_ref, % ets_table()
- from, % term(), where to reply
+ file_ref_db, % ets()
+ cert_db_ref, % ref()
bytes_to_read, % integer(), # bytes to read in passive mode
user_data_buffer, % binary()
log_alert, % boolean()
- renegotiation, % {boolean(), From | internal | peer}
- recv_during_renegotiation, %boolean()
- send_queue, % queue()
- terminated = false %
+ renegotiation, % {boolean(), From | internal | peer}
+ start_or_recv_from, % "gen_fsm From"
+ send_queue, % queue()
+ terminated = false, %
+ allow_renegotiate = true
}).
-define(DEFAULT_DIFFIE_HELLMAN_PARAMS,
- #'DHParameter'{prime = ?DEFAULT_DIFFIE_HELLMAN_PRIME,
+ #'DHParameter'{prime = ?DEFAULT_DIFFIE_HELLMAN_PRIME,
base = ?DEFAULT_DIFFIE_HELLMAN_GENERATOR}).
+-define(WAIT_TO_ALLOW_RENEGOTIATION, 12000).
-type state_name() :: hello | abbreviated | certify | cipher | connection.
-type gen_fsm_state_return() :: {next_state, state_name(), #state{}} |
@@ -271,6 +274,16 @@ peer_certificate(ConnectionPid) ->
renegotiation(ConnectionPid) ->
sync_send_all_state_event(ConnectionPid, renegotiate).
+%%--------------------------------------------------------------------
+-spec prf(pid(), binary() | 'master_secret', binary(),
+ binary() | ssl:prf_random(), non_neg_integer()) ->
+ {ok, binary()} | {error, reason()} | {'EXIT', term()}.
+%%
+%% Description: use a ssl sessions TLS PRF to generate key material
+%%--------------------------------------------------------------------
+prf(ConnectionPid, Secret, Label, Seed, WantedLength) ->
+ sync_send_all_state_event(ConnectionPid, {prf, Secret, Label, Seed, WantedLength}).
+
%%====================================================================
%% ssl_connection_sup API
%%====================================================================
@@ -284,51 +297,39 @@ renegotiation(ConnectionPid) ->
%% does not return until Module:init/1 has returned.
%%--------------------------------------------------------------------
start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
- gen_fsm:start_link(?MODULE, [Role, Host, Port, Socket, Options,
- User, CbInfo], []).
+ {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
-%%====================================================================
-%% gen_fsm callbacks
-%%====================================================================
-%%--------------------------------------------------------------------
--spec init(list()) -> {ok, state_name(), #state{}, timeout()} | {stop, term()}.
-%% Possible return values not used now.
-%% | {ok, state_name(), #state{}} |
-%% ignore
-%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
-%% gen_fsm:start_link/3,4, this function is called by the new process to
-%% initialize.
-%%--------------------------------------------------------------------
-init([Role, Host, Port, Socket, {SSLOpts0, _} = Options,
- User, CbInfo]) ->
+init([Role, Host, Port, Socket, {SSLOpts0, _} = Options, User, CbInfo]) ->
State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
- Hashes0 = ssl_handshake:init_hashes(),
-
+ Handshake = ssl_handshake:init_handshake_history(),
+ TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}),
try ssl_init(SSLOpts0, Role) of
- {ok, Ref, CertDbHandle, CacheHandle, OwnCert, Key, DHParams} ->
+ {ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, OwnCert, Key, DHParams} ->
Session = State0#state.session,
- State = State0#state{tls_handshake_hashes = Hashes0,
- session = Session#session{own_certificate = OwnCert},
+ State = State0#state{
+ tls_handshake_history = Handshake,
+ session = Session#session{own_certificate = OwnCert,
+ time_stamp = TimeStamp},
+ file_ref_db = FileRefHandle,
cert_db_ref = Ref,
cert_db = CertDbHandle,
session_cache = CacheHandle,
private_key = Key,
diffie_hellman_params = DHParams},
- {ok, hello, State, get_timeout(State)}
- catch
+ gen_fsm:enter_loop(?MODULE, [], hello, State, get_timeout(State))
+ catch
throw:Error ->
- {stop, Error}
+ gen_fsm:enter_loop(?MODULE, [], error, {Error,State0}, get_timeout(State0))
end.
-
+
%%--------------------------------------------------------------------
-%% -spec state_name(event(), #state{}) -> gen_fsm_state_return()
-%%
%% Description:There should be one instance of this function for each
%% possible state name. Whenever a gen_fsm receives an event sent
%% using gen_fsm:send_event/2, the instance of this function with the
%% same name as the current state name StateName is called to handle
%% the event. It is also called if a timeout occurs.
%%
+
%%--------------------------------------------------------------------
-spec hello(start | #hello_request{} | #client_hello{} | #server_hello{} | term(),
#state{}) -> gen_fsm_state_return().
@@ -336,34 +337,33 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options,
hello(start, #state{host = Host, port = Port, role = client,
ssl_options = SslOpts,
session = #session{own_certificate = Cert} = Session0,
+ session_cache = Cache, session_cache_cb = CacheCb,
transport_cb = Transport, socket = Socket,
- connection_states = ConnectionStates,
+ connection_states = ConnectionStates0,
renegotiation = {Renegotiation, _}} = State0) ->
- Hello = ssl_handshake:client_hello(Host, Port,
- ConnectionStates,
- SslOpts, Renegotiation, Cert),
+ Hello = ssl_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
+ Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
- Hashes0 = ssl_handshake:init_hashes(),
- {BinMsg, CS2, Hashes1} =
- encode_handshake(Hello, Version, ConnectionStates, Hashes0),
+ Handshake0 = ssl_handshake:init_handshake_history(),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Hello, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
- State1 = State0#state{connection_states = CS2,
- negotiated_version = Version, %% Requested version
+ State1 = State0#state{connection_states = ConnectionStates,
+ negotiated_version = Version, %% Requested version
session =
- Session0#session{session_id = Hello#client_hello.session_id,
- is_resumable = false},
- tls_handshake_hashes = Hashes1},
+ Session0#session{session_id = Hello#client_hello.session_id},
+ tls_handshake_history = Handshake},
{Record, State} = next_record(State1),
- next_state(hello, Record, State);
+ next_state(hello, hello, Record, State);
hello(start, #state{role = server} = State0) ->
{Record, State} = next_record(State0),
- next_state(hello, Record, State);
+ next_state(hello, hello, Record, State);
hello(#hello_request{}, #state{role = client} = State0) ->
{Record, State} = next_record(State0),
- next_state(hello, Record, State);
+ next_state(hello, hello, Record, State);
hello(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression} = Hello,
@@ -375,19 +375,21 @@ hello(#server_hello{cipher_suite = CipherSuite,
ssl_options = SslOptions} = State0) ->
case ssl_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
{Version, NewId, ConnectionStates} ->
- {KeyAlgorithm, _, _} =
+ {KeyAlgorithm, _, _, _} =
ssl_cipher:suite_definition(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
State = State0#state{key_algorithm = KeyAlgorithm,
+ hashsign_algorithm = default_hashsign(Version, KeyAlgorithm),
negotiated_version = Version,
connection_states = ConnectionStates,
premaster_secret = PremasterSecret},
case ssl_session:is_new(OldId, NewId) of
true ->
- handle_new_session(NewId, CipherSuite, Compression, State);
+ handle_new_session(NewId, CipherSuite, Compression,
+ State#state{connection_states = ConnectionStates});
false ->
handle_resumed_session(NewId, State#state{connection_states = ConnectionStates})
end;
@@ -426,17 +428,18 @@ hello(Msg, State) ->
%%--------------------------------------------------------------------
abbreviated(#hello_request{}, State0) ->
{Record, State} = next_record(State0),
- next_state(hello, Record, State);
+ next_state(abbreviated, hello, Record, State);
abbreviated(#finished{verify_data = Data} = Finished,
#state{role = server,
negotiated_version = Version,
- tls_handshake_hashes = Hashes,
+ tls_handshake_history = Handshake,
session = #session{master_secret = MasterSecret},
connection_states = ConnectionStates0} =
State) ->
case ssl_handshake:verify_connection(Version, Finished, client,
- MasterSecret, Hashes) of
+ get_current_connection_state_prf(ConnectionStates0, write),
+ MasterSecret, Handshake) of
verified ->
ConnectionStates = ssl_record:set_client_verify_data(current_both, Data, ConnectionStates0),
next_state_connection(abbreviated,
@@ -447,18 +450,19 @@ abbreviated(#finished{verify_data = Data} = Finished,
end;
abbreviated(#finished{verify_data = Data} = Finished,
- #state{role = client, tls_handshake_hashes = Hashes0,
+ #state{role = client, tls_handshake_history = Handshake0,
session = #session{master_secret = MasterSecret},
negotiated_version = Version,
connection_states = ConnectionStates0} = State) ->
case ssl_handshake:verify_connection(Version, Finished, server,
- MasterSecret, Hashes0) of
+ get_pending_connection_state_prf(ConnectionStates0, write),
+ MasterSecret, Handshake0) of
verified ->
ConnectionStates1 = ssl_record:set_server_verify_data(current_read, Data, ConnectionStates0),
- {ConnectionStates, Hashes} =
+ {ConnectionStates, Handshake} =
finalize_handshake(State#state{connection_states = ConnectionStates1}, abbreviated),
next_state_connection(abbreviated,
- ack_connection(State#state{tls_handshake_hashes = Hashes,
+ ack_connection(State#state{tls_handshake_history = Handshake,
connection_states =
ConnectionStates}));
#alert{} = Alert ->
@@ -479,7 +483,7 @@ abbreviated(Msg, State) ->
%%--------------------------------------------------------------------
certify(#hello_request{}, State0) ->
{Record, State} = next_record(State0),
- next_state(hello, Record, State);
+ next_state(certify, hello, Record, State);
certify(#certificate{asn1_certificates = []},
#state{role = server, negotiated_version = Version,
@@ -487,7 +491,7 @@ certify(#certificate{asn1_certificates = []},
fail_if_no_peer_cert = true}} =
State) ->
Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE),
- handle_own_alert(Alert, Version, certify_certificate, State),
+ handle_own_alert(Alert, Version, certify, State),
{stop, normal, State};
certify(#certificate{asn1_certificates = []},
@@ -496,7 +500,7 @@ certify(#certificate{asn1_certificates = []},
fail_if_no_peer_cert = false}} =
State0) ->
{Record, State} = next_record(State0#state{client_certificate_requested = false}),
- next_state(certify, Record, State);
+ next_state(certify, certify, Record, State);
certify(#certificate{} = Cert,
#state{negotiated_version = Version,
@@ -511,7 +515,7 @@ certify(#certificate{} = Cert,
handle_peer_cert(PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify_certificate, State),
+ handle_own_alert(Alert, Version, certify, State),
{stop, normal, State}
end;
@@ -522,10 +526,9 @@ certify(#server_key_exchange{} = KeyExchangeMsg,
case handle_server_key(KeyExchangeMsg, State0) of
#state{} = State1 ->
{Record, State} = next_record(State1),
- next_state(certify, Record, State);
+ next_state(certify, certify, Record, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify_server_keyexchange,
- State0),
+ handle_own_alert(Alert, Version, certify, State0),
{stop, normal, State0}
end;
@@ -535,7 +538,7 @@ certify(#server_key_exchange{} = Msg,
certify(#certificate_request{}, State0) ->
{Record, State} = next_record(State0#state{client_certificate_requested = true}),
- next_state(certify, Record, State);
+ next_state(certify, certify, Record, State);
%% Master secret was determined with help of server-key exchange msg
certify(#server_hello_done{},
@@ -546,12 +549,11 @@ certify(#server_hello_done{},
role = client} = State0) ->
case ssl_handshake:master_secret(Version, Session,
ConnectionStates0, client) of
- {MasterSecret, ConnectionStates1} ->
- State = State0#state{connection_states = ConnectionStates1},
+ {MasterSecret, ConnectionStates} ->
+ State = State0#state{connection_states = ConnectionStates},
client_certify_and_key_exchange(State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version,
- certify_server_hello_done, State0),
+ handle_own_alert(Alert, Version, certify, State0),
{stop, normal, State0}
end;
@@ -564,14 +566,13 @@ certify(#server_hello_done{},
role = client} = State0) ->
case ssl_handshake:master_secret(Version, PremasterSecret,
ConnectionStates0, client) of
- {MasterSecret, ConnectionStates1} ->
+ {MasterSecret, ConnectionStates} ->
Session = Session0#session{master_secret = MasterSecret},
- State = State0#state{connection_states = ConnectionStates1,
- session = Session},
+ State = State0#state{connection_states = ConnectionStates,
+ session = Session},
client_certify_and_key_exchange(State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version,
- certify_server_hello_done, State0),
+ handle_own_alert(Alert, Version, certify, State0),
{stop, normal, State0}
end;
@@ -588,7 +589,7 @@ certify(#client_key_exchange{exchange_keys = Keys},
certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, Version), State)
catch
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify_client_key_exchange, State),
+ handle_own_alert(Alert, Version, certify, State),
{stop, normal, State}
end;
@@ -611,10 +612,9 @@ certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS
State1 = State0#state{connection_states = ConnectionStates,
session = Session},
{Record, State} = next_record(State1),
- next_state(cipher, Record, State);
+ next_state(certify, cipher, Record, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version,
- certify_client_key_exchange, State0),
+ handle_own_alert(Alert, Version, certify, State0),
{stop, normal, State0}
end;
@@ -626,10 +626,9 @@ certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPubl
case dh_master_secret(crypto:mpint(P), crypto:mpint(G), ClientPublicDhKey, ServerDhPrivateKey, State0) of
#state{} = State1 ->
{Record, State} = next_record(State1),
- next_state(cipher, Record, State);
+ next_state(certify, cipher, Record, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version,
- certify_client_key_exchange, State0),
+ handle_own_alert(Alert, Version, certify, State0),
{stop, normal, State0}
end.
@@ -639,20 +638,25 @@ certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPubl
%%--------------------------------------------------------------------
cipher(#hello_request{}, State0) ->
{Record, State} = next_record(State0),
- next_state(hello, Record, State);
+ next_state(cipher, hello, Record, State);
-cipher(#certificate_verify{signature = Signature},
+cipher(#certificate_verify{signature = Signature, hashsign_algorithm = CertHashSign},
#state{role = server,
public_key_info = PublicKeyInfo,
negotiated_version = Version,
session = #session{master_secret = MasterSecret},
- tls_handshake_hashes = Hashes
+ hashsign_algorithm = ConnectionHashSign,
+ tls_handshake_history = Handshake
} = State0) ->
+ HashSign = case CertHashSign of
+ {_, _} -> CertHashSign;
+ _ -> ConnectionHashSign
+ end,
case ssl_handshake:certificate_verify(Signature, PublicKeyInfo,
- Version, MasterSecret, Hashes) of
+ Version, HashSign, MasterSecret, Handshake) of
valid ->
{Record, State} = next_record(State0),
- next_state(cipher, Record, State);
+ next_state(cipher, cipher, Record, State);
#alert{} = Alert ->
handle_own_alert(Alert, Version, cipher, State0),
{stop, normal, State0}
@@ -665,10 +669,12 @@ cipher(#finished{verify_data = Data} = Finished,
role = Role,
session = #session{master_secret = MasterSecret}
= Session0,
- tls_handshake_hashes = Hashes0} = State) ->
+ connection_states = ConnectionStates0,
+ tls_handshake_history = Handshake0} = State) ->
case ssl_handshake:verify_connection(Version, Finished,
opposite_role(Role),
- MasterSecret, Hashes0) of
+ get_current_connection_state_prf(ConnectionStates0, read),
+ MasterSecret, Handshake0) of
verified ->
Session = register_session(Role, Host, Port, Session0),
cipher_role(Role, Data, Session, State);
@@ -689,36 +695,51 @@ cipher(Msg, State) ->
%%--------------------------------------------------------------------
connection(#hello_request{}, #state{host = Host, port = Port,
socket = Socket,
- session = #session{own_certificate = Cert},
+ session = #session{own_certificate = Cert} = Session0,
+ session_cache = Cache, session_cache_cb = CacheCb,
ssl_options = SslOpts,
negotiated_version = Version,
transport_cb = Transport,
connection_states = ConnectionStates0,
renegotiation = {Renegotiation, _},
- tls_handshake_hashes = Hashes0} = State0) ->
- Hello = ssl_handshake:client_hello(Host, Port, ConnectionStates0,
- SslOpts, Renegotiation, Cert),
+ tls_handshake_history = Handshake0} = State0) ->
+ Hello = ssl_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
+ Cache, CacheCb, Renegotiation, Cert),
- {BinMsg, ConnectionStates1, Hashes1} =
- encode_handshake(Hello, Version, ConnectionStates0, Hashes0),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Hello, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
{Record, State} = next_record(State0#state{connection_states =
- ConnectionStates1,
- tls_handshake_hashes = Hashes1}),
- next_state(hello, Record, State);
-connection(#client_hello{} = Hello, #state{role = server} = State) ->
- hello(Hello, State);
-
+ ConnectionStates,
+ session = Session0#session{session_id = Hello#client_hello.session_id},
+ tls_handshake_history = Handshake}),
+ next_state(connection, hello, Record, State);
+connection(#client_hello{} = Hello, #state{role = server, allow_renegotiate = true} = State) ->
+ %% Mitigate Computational DoS attack
+ %% http://www.educatedguesswork.org/2011/10/ssltls_and_computational_dos.html
+ %% http://www.thc.org/thc-ssl-dos/ Rather than disabling client
+ %% initiated renegotiation we will disallow many client initiated
+ %% renegotiations immediately after each other.
+ erlang:send_after(?WAIT_TO_ALLOW_RENEGOTIATION, self(), allow_renegotiate),
+ hello(Hello, State#state{allow_renegotiate = false});
+
+connection(#client_hello{}, #state{role = server, allow_renegotiate = false,
+ connection_states = ConnectionStates0,
+ socket = Socket, transport_cb = Transport,
+ negotiated_version = Version} = State0) ->
+ Alert = ?ALERT_REC(?WARNING, ?NO_RENEGOTIATION),
+ {BinMsg, ConnectionStates} =
+ encode_alert(Alert, Version, ConnectionStates0),
+ Transport:send(Socket, BinMsg),
+ next_state_connection(connection, State0#state{connection_states = ConnectionStates});
+
connection(timeout, State) ->
{next_state, connection, State, hibernate};
connection(Msg, State) ->
handle_unexpected_message(Msg, connection, State).
+
%%--------------------------------------------------------------------
--spec handle_event(term(), state_name(), #state{}) -> term().
-%% As it is not currently used gen_fsm_state_return() makes
-%% dialyzer unhappy!
-%%
%% Description: Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_all_state_event/2, this function is called to handle
%% the event. Not currently used!
@@ -727,47 +748,16 @@ handle_event(_Event, StateName, State) ->
{next_state, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
--spec handle_sync_event(term(), from(), state_name(), #state{}) ->
- gen_fsm_state_return() |
- {reply, reply(), state_name(), #state{}} |
- {reply, reply(), state_name(), #state{}, timeout()} |
- {stop, reason(), reply(), #state{}}.
-%%
%% Description: Whenever a gen_fsm receives an event sent using
%% gen_fsm:sync_send_all_state_event/2,3, this function is called to handle
%% the event.
%%--------------------------------------------------------------------
-handle_sync_event({application_data, Data0}, From, connection,
- #state{socket = Socket,
- negotiated_version = Version,
- transport_cb = Transport,
- connection_states = ConnectionStates0,
- send_queue = SendQueue,
- socket_options = SockOpts,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}}
- = State) ->
+handle_sync_event({application_data, Data}, From, connection, State) ->
%% We should look into having a worker process to do this to
%% parallize send and receive decoding and not block the receiver
%% if sending is overloading the socket.
try
- Data = encode_packet(Data0, SockOpts),
- case encode_data(Data, Version, ConnectionStates0, RenegotiateAt) of
- {Msgs, [], ConnectionStates} ->
- Result = Transport:send(Socket, Msgs),
- {reply, Result,
- connection, State#state{connection_states = ConnectionStates},
- get_timeout(State)};
- {Msgs, RestData, ConnectionStates} ->
- if
- Msgs =/= [] ->
- Transport:send(Socket, Msgs);
- true ->
- ok
- end,
- renegotiate(State#state{connection_states = ConnectionStates,
- send_queue = queue:in_r({From, RestData}, SendQueue),
- renegotiation = {true, internal}})
- end
+ write_application_data(Data, From, State)
catch throw:Error ->
{reply, Error, connection, State, get_timeout(State)}
end;
@@ -778,8 +768,8 @@ handle_sync_event({application_data, Data}, From, StateName,
State#state{send_queue = queue:in({From, Data}, Queue)},
get_timeout(State)};
-handle_sync_event(start, From, hello, State) ->
- hello(start, State#state{from = From});
+handle_sync_event(start, StartFrom, hello, State) ->
+ hello(start, State#state{start_or_recv_from = StartFrom});
%% The two clauses below could happen if a server upgrades a socket in
%% active mode. Note that in this case we are lucky that
@@ -791,8 +781,10 @@ handle_sync_event(start, From, hello, State) ->
%% they upgrade a active socket.
handle_sync_event(start, _, connection, State) ->
{reply, connected, connection, State, get_timeout(State)};
-handle_sync_event(start, From, StateName, State) ->
- {next_state, StateName, State#state{from = From}, get_timeout(State)};
+handle_sync_event(start, _From, error, {Error, State = #state{}}) ->
+ {stop, {shutdown, Error}, {error, Error}, State};
+handle_sync_event(start, StartFrom, StateName, State) ->
+ {next_state, StateName, State#state{start_or_recv_from = StartFrom}, get_timeout(State)};
handle_sync_event(close, _, StateName, State) ->
%% Run terminate before returning
@@ -823,15 +815,13 @@ handle_sync_event({shutdown, How0}, _, StateName,
{stop, normal, Error, State}
end;
-handle_sync_event({recv, N}, From, connection = StateName, State0) ->
- passive_receive(State0#state{bytes_to_read = N, from = From}, StateName);
+handle_sync_event({recv, N}, RecvFrom, connection = StateName, State0) ->
+ passive_receive(State0#state{bytes_to_read = N, start_or_recv_from = RecvFrom}, StateName);
%% Doing renegotiate wait with handling request until renegotiate is
-%% finished. Will be handled by next_state_connection/2.
-handle_sync_event({recv, N}, From, StateName, State) ->
- {next_state, StateName,
- State#state{bytes_to_read = N, from = From,
- recv_during_renegotiation = true},
+%% finished. Will be handled by next_state_is_connection/2.
+handle_sync_event({recv, N}, RecvFrom, StateName, State) ->
+ {next_state, StateName, State#state{bytes_to_read = N, start_or_recv_from = RecvFrom},
get_timeout(State)};
handle_sync_event({new_user, User}, _From, StateName,
@@ -869,7 +859,7 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
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
+ case next_state(StateName, StateName, Record, State2) of
{next_state, StateName, State, Timeout} ->
{reply, Reply, StateName, State, Timeout};
{stop, Reason, State} ->
@@ -879,11 +869,11 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
%% Active once already set
{reply, Reply, StateName, State1, get_timeout(State1)};
true ->
- case application_data(<<>>, State1) of
+ case read_application_data(<<>>, State1) of
Stop = {stop,_,_} ->
Stop;
{Record, State2} ->
- case next_state(StateName, Record, State2) of
+ case next_state(StateName, StateName, Record, State2) of
{next_state, StateName, State, Timeout} ->
{reply, Reply, StateName, State, Timeout};
{stop, Reason, State} ->
@@ -898,19 +888,45 @@ handle_sync_event(renegotiate, From, connection, State) ->
handle_sync_event(renegotiate, _, StateName, State) ->
{reply, {error, already_renegotiating}, StateName, State, get_timeout(State)};
+handle_sync_event({prf, Secret, Label, Seed, WantedLength}, _, StateName,
+ #state{connection_states = ConnectionStates,
+ negotiated_version = Version} = State) ->
+ ConnectionState =
+ ssl_record:current_connection_state(ConnectionStates, read),
+ SecParams = ConnectionState#connection_state.security_parameters,
+ #security_parameters{master_secret = MasterSecret,
+ client_random = ClientRandom,
+ server_random = ServerRandom} = SecParams,
+ Reply = try
+ SecretToUse = case Secret of
+ _ when is_binary(Secret) -> Secret;
+ master_secret -> MasterSecret
+ end,
+ SeedToUse = lists:reverse(
+ lists:foldl(fun(X, Acc) when is_binary(X) -> [X|Acc];
+ (client_random, Acc) -> [ClientRandom|Acc];
+ (server_random, Acc) -> [ServerRandom|Acc]
+ end, [], Seed)),
+ ssl_handshake:prf(Version, SecretToUse, Label, SeedToUse, WantedLength)
+ catch
+ exit:_ -> {error, badarg};
+ error:Reason -> {error, Reason}
+ end,
+ {reply, Reply, StateName, State, get_timeout(State)};
+
handle_sync_event(info, _, StateName,
#state{negotiated_version = Version,
session = #session{cipher_suite = Suite}} = State) ->
AtomVersion = ssl_record:protocol_version(Version),
- {reply, {ok, {AtomVersion, ssl_cipher:suite_definition(Suite)}},
+ {reply, {ok, {AtomVersion, ssl:suite_definition(Suite)}},
StateName, State, get_timeout(State)};
handle_sync_event(session_info, _, StateName,
#state{session = #session{session_id = Id,
cipher_suite = Suite}} = State) ->
{reply, [{session_id, Id},
- {cipher_suite, ssl_cipher:suite_definition(Suite)}],
+ {cipher_suite, ssl:suite_definition(Suite)}],
StateName, State, get_timeout(State)};
handle_sync_event(peer_certificate, _, StateName,
@@ -919,11 +935,6 @@ handle_sync_event(peer_certificate, _, StateName,
{reply, {ok, Cert}, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
--spec handle_info(msg(),state_name(), #state{}) ->
- {next_state, state_name(), #state{}}|
- {next_state, state_name(), #state{}, timeout()} |
- {stop, reason(), #state{}}.
-%%
%% Description: This function is called by a gen_fsm when it receives any
%% other message than a synchronous or asynchronous event
%% (or a system message).
@@ -931,22 +942,18 @@ handle_sync_event(peer_certificate, _, StateName,
%% raw data from TCP, unpack records
handle_info({Protocol, _, Data}, StateName,
- #state{data_tag = Protocol,
- negotiated_version = Version} = State0) ->
+ #state{data_tag = Protocol} = State0) ->
case next_tls_record(Data, State0) of
{Record, State} ->
- next_state(StateName, Record, State);
+ next_state(StateName, StateName, Record, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State0),
+ handle_normal_shutdown(Alert, StateName, State0),
{stop, normal, State0}
end;
-handle_info({CloseTag, Socket}, _StateName,
+handle_info({CloseTag, Socket}, StateName,
#state{socket = Socket, close_tag = CloseTag,
- negotiated_version = Version,
- socket_options = Opts,
- user_application = {_Mon,Pid}, from = From,
- role = Role} = State) ->
+ negotiated_version = Version} = 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
@@ -961,36 +968,35 @@ handle_info({CloseTag, Socket}, _StateName,
%%invalidate_session(Role, Host, Port, Session)
ok
end,
- alert_user(Opts#socket_options.active, Pid, From,
- ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), Role),
+ handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
{stop, normal, State};
handle_info({ErrorTag, Socket, econnaborted}, StateName,
- #state{socket = Socket, from = User, role = Role,
+ #state{socket = Socket, start_or_recv_from = StartFrom, role = Role,
error_tag = ErrorTag} = State) when StateName =/= connection ->
- alert_user(User, ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Role),
+ alert_user(StartFrom, ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Role),
{stop, normal, State};
-handle_info({ErrorTag, Socket, Reason}, _,
- #state{socket = Socket, from = User,
- role = Role, error_tag = ErrorTag} = State) ->
+handle_info({ErrorTag, Socket, Reason}, StateName, #state{socket = Socket,
+ error_tag = ErrorTag} = State) ->
Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]),
error_logger:info_report(Report),
- alert_user(User, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role),
+ handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
{stop, normal, State};
handle_info({'DOWN', MonitorRef, _, _, _}, _,
State = #state{user_application={MonitorRef,_Pid}}) ->
{stop, normal, State};
+handle_info(allow_renegotiate, StateName, State) ->
+ {next_state, StateName, State#state{allow_renegotiate = true}, get_timeout(State)};
+
handle_info(Msg, StateName, State) ->
Report = io_lib:format("SSL: Got unexpected info: ~p ~n", [Msg]),
error_logger:info_report(Report),
{next_state, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
--spec terminate(reason(), state_name(), #state{}) -> term().
-%%
%% Description:This function is called by a gen_fsm 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_fsm terminates with
@@ -1005,24 +1011,25 @@ terminate(Reason, connection, #state{negotiated_version = Version,
connection_states = ConnectionStates,
transport_cb = Transport,
socket = Socket, send_queue = SendQueue,
- renegotiation = Renegotiate}) ->
+ renegotiation = Renegotiate} = State) ->
+ handle_trusted_certs_db(State),
notify_senders(SendQueue),
notify_renegotiater(Renegotiate),
BinAlert = terminate_alert(Reason, Version, ConnectionStates),
Transport:send(Socket, BinAlert),
workaround_transport_delivery_problems(Socket, Transport, Reason),
Transport:close(Socket);
+
terminate(Reason, _StateName, #state{transport_cb = Transport,
socket = Socket, send_queue = SendQueue,
- renegotiation = Renegotiate}) ->
+ renegotiation = Renegotiate} = State) ->
+ handle_trusted_certs_db(State),
notify_senders(SendQueue),
notify_renegotiater(Renegotiate),
workaround_transport_delivery_problems(Socket, Transport, Reason),
Transport:close(Socket).
%%--------------------------------------------------------------------
--spec code_change(term(), state_name(), #state{}, list()) -> {ok, state_name(), #state{}}.
-%%
%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
%% Description: Convert process state when code is changed
%%--------------------------------------------------------------------
@@ -1064,12 +1071,12 @@ ssl_init(SslOpts, Role) ->
init_manager_name(SslOpts#ssl_options.erl_dist),
- {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert} = init_certificates(SslOpts, Role),
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, OwnCert} = init_certificates(SslOpts, Role),
PrivateKey =
- init_private_key(CertDbHandle, SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
+ init_private_key(PemCacheHandle, SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
SslOpts#ssl_options.password, Role),
- DHParams = init_diffie_hellman(CertDbHandle, SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
- {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert, PrivateKey, DHParams}.
+ DHParams = init_diffie_hellman(PemCacheHandle, SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, CacheHandle, OwnCert, PrivateKey, DHParams}.
init_manager_name(false) ->
put(ssl_manager, ssl_manager);
@@ -1080,7 +1087,7 @@ init_certificates(#ssl_options{cacerts = CaCerts,
cacertfile = CACertFile,
certfile = CertFile,
cert = Cert}, Role) ->
- {ok, CertDbRef, CertDbHandle, CacheHandle} =
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle} =
try
Certs = case CaCerts of
undefined ->
@@ -1088,56 +1095,76 @@ 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, CertDbHandle, CacheHandle, CertFile, Role).
+ init_certificates(Cert, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, CertFile, Role).
-init_certificates(undefined, CertDbRef, CertDbHandle, CacheHandle, "", _) ->
- {ok, CertDbRef, CertDbHandle, CacheHandle, undefined};
+init_certificates(undefined, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, <<>>, _) ->
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, undefined};
-init_certificates(undefined, CertDbRef, CertDbHandle, CacheHandle, CertFile, client) ->
+init_certificates(undefined, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, CertFile, client) ->
try
- [OwnCert] = ssl_certificate:file_to_certificats(CertFile, CertDbHandle),
- {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert}
+ [OwnCert] = ssl_certificate:file_to_certificats(CertFile, PemCacheHandle),
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, OwnCert}
catch _Error:_Reason ->
- {ok, CertDbRef, CertDbHandle, CacheHandle, undefined}
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, undefined}
end;
-init_certificates(undefined, CertDbRef, CertDbHandle, CacheRef, CertFile, server) ->
+init_certificates(undefined, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, CertFile, server) ->
try
- [OwnCert] = ssl_certificate:file_to_certificats(CertFile, CertDbHandle),
- {ok, CertDbRef, CertDbHandle, CacheRef, OwnCert}
+ [OwnCert] = ssl_certificate:file_to_certificats(CertFile, PemCacheHandle),
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, OwnCert}
catch
Error:Reason ->
handle_file_error(?LINE, Error, Reason, CertFile, ecertfile,
erlang:get_stacktrace())
end;
-init_certificates(Cert, CertDbRef, CertDbHandle, CacheRef, _, _) ->
- {ok, CertDbRef, CertDbHandle, CacheRef, Cert}.
+init_certificates(Cert, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, _, _) ->
+ {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, Cert}.
-init_private_key(_, undefined, "", _Password, _Client) ->
+init_private_key(_, undefined, <<>>, _Password, _Client) ->
undefined;
init_private_key(DbHandle, undefined, KeyFile, Password, _) ->
try
{ok, List} = ssl_manager:cache_pem_file(KeyFile, DbHandle),
[PemEntry] = [PemEntry || PemEntry = {PKey, _ , _} <- List,
PKey =:= 'RSAPrivateKey' orelse
- PKey =:= 'DSAPrivateKey'],
- public_key:pem_entry_decode(PemEntry, Password)
+ PKey =:= 'DSAPrivateKey' orelse
+ PKey =:= 'PrivateKeyInfo'
+ ],
+ private_key(public_key:pem_entry_decode(PemEntry, Password))
catch
Error:Reason ->
handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile,
erlang:get_stacktrace())
end;
+%% First two clauses are for backwards compatibility
init_private_key(_,{rsa, PrivateKey}, _, _,_) ->
- public_key:der_decode('RSAPrivateKey', PrivateKey);
+ init_private_key('RSAPrivateKey', PrivateKey);
init_private_key(_,{dsa, PrivateKey},_,_,_) ->
- public_key:der_decode('DSAPrivateKey', PrivateKey).
+ init_private_key('DSAPrivateKey', PrivateKey);
+init_private_key(_,{Asn1Type, PrivateKey},_,_,_) ->
+ private_key(init_private_key(Asn1Type, PrivateKey)).
+
+init_private_key(Asn1Type, PrivateKey) ->
+ public_key:der_decode(Asn1Type, PrivateKey).
+
+private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'rsaEncryption'},
+ privateKey = Key}) ->
+ public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key));
+
+private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-dsa'},
+ privateKey = Key}) ->
+ public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key));
+private_key(Key) ->
+ Key.
-spec(handle_file_error(_,_,_,_,_,_) -> no_return()).
handle_file_error(Line, Error, {badmatch, Reason}, File, Throw, Stack) ->
@@ -1198,7 +1225,7 @@ handle_peer_cert(PeerCert, PublicKeyInfo,
Session#session{peer_certificate = PeerCert},
public_key_info = PublicKeyInfo},
{Record, State} = next_record(State1),
- next_state(certify, Record, State).
+ next_state(certify, certify, Record, State).
certify_client(#state{client_certificate_requested = true, role = client,
connection_states = ConnectionStates0,
@@ -1208,13 +1235,13 @@ certify_client(#state{client_certificate_requested = true, role = client,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert},
socket = Socket,
- tls_handshake_hashes = Hashes0} = State) ->
+ tls_handshake_history = Handshake0} = State) ->
Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client),
- {BinCert, ConnectionStates1, Hashes1} =
- encode_handshake(Certificate, Version, ConnectionStates0, Hashes0),
+ {BinCert, ConnectionStates, Handshake} =
+ encode_handshake(Certificate, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinCert),
- State#state{connection_states = ConnectionStates1,
- tls_handshake_hashes = Hashes1};
+ State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake};
certify_client(#state{client_certificate_requested = false} = State) ->
State.
@@ -1226,28 +1253,29 @@ verify_client_cert(#state{client_certificate_requested = true, role = client,
private_key = PrivateKey,
session = #session{master_secret = MasterSecret,
own_certificate = OwnCert},
- tls_handshake_hashes = Hashes0} = State) ->
+ hashsign_algorithm = HashSign,
+ tls_handshake_history = Handshake0} = State) ->
+ %%TODO: for TLS 1.2 we can choose a different/stronger HashSign combination for this.
case ssl_handshake:client_certificate_verify(OwnCert, MasterSecret,
- Version, PrivateKey, Hashes0) of
+ Version, HashSign, PrivateKey, Handshake0) of
#certificate_verify{} = Verified ->
- {BinVerified, ConnectionStates1, Hashes1} =
+ {BinVerified, ConnectionStates, Handshake} =
encode_handshake(Verified, Version,
- ConnectionStates0, Hashes0),
+ ConnectionStates0, Handshake0),
Transport:send(Socket, BinVerified),
- State#state{connection_states = ConnectionStates1,
- tls_handshake_hashes = Hashes1};
+ State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake};
ignore ->
State;
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State)
-
+ throw(Alert)
end;
verify_client_cert(#state{client_certificate_requested = false} = State) ->
State.
do_server_hello(Type, #state{negotiated_version = Version,
- session = #session{session_id = SessId} = Session,
+ session = #session{session_id = SessId},
connection_states = ConnectionStates0,
renegotiation = {Renegotiation, _}}
= State0) when is_atom(Type) ->
@@ -1255,29 +1283,13 @@ do_server_hello(Type, #state{negotiated_version = Version,
ServerHello =
ssl_handshake:server_hello(SessId, Version,
ConnectionStates0, Renegotiation),
- State1 = server_hello(ServerHello, State0),
+ State = server_hello(ServerHello, State0),
case Type of
new ->
- new_server_hello(ServerHello, State1);
+ new_server_hello(ServerHello, State);
resumed ->
- ConnectionStates1 = State1#state.connection_states,
- case ssl_handshake:master_secret(Version, Session,
- ConnectionStates1, server) of
- {_, ConnectionStates2} ->
- State2 = State1#state{connection_states=ConnectionStates2,
- session = Session},
- {ConnectionStates, Hashes} =
- finalize_handshake(State2, abbreviated),
- State3 = State2#state{connection_states =
- ConnectionStates,
- tls_handshake_hashes = Hashes},
- {Record, State} = next_record(State3),
- next_state(abbreviated, Record, State);
- #alert{} = Alert ->
- handle_own_alert(Alert, Version, hello, State1),
- {stop, normal, State1}
- end
+ resumed_server_hello(State)
end.
new_server_hello(#server_hello{cipher_suite = CipherSuite,
@@ -1293,19 +1305,40 @@ new_server_hello(#server_hello{cipher_suite = CipherSuite,
cipher_suite = CipherSuite,
compression_method = Compression},
{Record, State} = next_record(State2#state{session = Session}),
- next_state(certify, Record, State)
+ next_state(hello, certify, Record, State)
catch
#alert{} = Alert ->
handle_own_alert(Alert, Version, hello, State0),
{stop, normal, State0}
end.
+resumed_server_hello(#state{session = Session,
+ connection_states = ConnectionStates0,
+ negotiated_version = Version} = State0) ->
+
+ case ssl_handshake:master_secret(Version, Session,
+ ConnectionStates0, server) of
+ {_, ConnectionStates1} ->
+ State1 = State0#state{connection_states = ConnectionStates1,
+ session = Session},
+ {ConnectionStates, Handshake} =
+ finalize_handshake(State1, abbreviated),
+ State2 = State1#state{connection_states =
+ ConnectionStates,
+ tls_handshake_history = Handshake},
+ {Record, State} = next_record(State2),
+ next_state(hello, abbreviated, Record, State);
+ #alert{} = Alert ->
+ handle_own_alert(Alert, Version, hello, State0),
+ {stop, normal, State0}
+ end.
+
handle_new_session(NewId, CipherSuite, Compression, #state{session = Session0} = State0) ->
Session = Session0#session{session_id = NewId,
cipher_suite = CipherSuite,
compression_method = Compression},
{Record, State} = next_record(State0#state{session = Session}),
- next_state(certify, Record, State).
+ next_state(hello, certify, Record, State).
handle_resumed_session(SessId, #state{connection_states = ConnectionStates0,
negotiated_version = Version,
@@ -1315,12 +1348,12 @@ handle_resumed_session(SessId, #state{connection_states = ConnectionStates0,
Session = CacheCb:lookup(Cache, {{Host, Port}, SessId}),
case ssl_handshake:master_secret(Version, Session,
ConnectionStates0, client) of
- {_, ConnectionStates1} ->
+ {_, ConnectionStates} ->
{Record, State} =
next_record(State0#state{
- connection_states = ConnectionStates1,
+ connection_states = ConnectionStates,
session = Session}),
- next_state(abbreviated, Record, State);
+ next_state(hello, abbreviated, Record, State);
#alert{} = Alert ->
handle_own_alert(Alert, Version, hello, State0),
{stop, normal, State0}
@@ -1331,16 +1364,16 @@ client_certify_and_key_exchange(#state{negotiated_version = Version} =
State0) ->
try do_client_certify_and_key_exchange(State0) of
State1 = #state{} ->
- {ConnectionStates, Hashes} = finalize_handshake(State1, certify),
+ {ConnectionStates, Handshake} = finalize_handshake(State1, certify),
State2 = State1#state{connection_states = ConnectionStates,
%% Reinitialize
client_certificate_requested = false,
- tls_handshake_hashes = Hashes},
+ tls_handshake_history = Handshake},
{Record, State} = next_record(State2),
- next_state(cipher, Record, State)
+ next_state(certify, cipher, Record, State)
catch
- #alert{} = Alert ->
- handle_own_alert(Alert, Version, client_certify_and_key_exchange, State0),
+ throw:#alert{} = Alert ->
+ handle_own_alert(Alert, Version, certify, State0),
{stop, normal, State0}
end.
@@ -1358,29 +1391,30 @@ server_hello(ServerHello, #state{transport_cb = Transport,
socket = Socket,
negotiated_version = Version,
connection_states = ConnectionStates0,
- tls_handshake_hashes = Hashes0} = State) ->
+ tls_handshake_history = Handshake0} = State) ->
CipherSuite = ServerHello#server_hello.cipher_suite,
- {KeyAlgorithm, _, _} = ssl_cipher:suite_definition(CipherSuite),
- {BinMsg, ConnectionStates1, Hashes1} =
- encode_handshake(ServerHello, Version, ConnectionStates0, Hashes0),
+ {KeyAlgorithm, _, _, _} = ssl_cipher:suite_definition(CipherSuite),
+ {BinMsg, ConnectionStates1, Handshake1} =
+ encode_handshake(ServerHello, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
State#state{connection_states = ConnectionStates1,
- tls_handshake_hashes = Hashes1,
- key_algorithm = KeyAlgorithm}.
+ tls_handshake_history = Handshake1,
+ key_algorithm = KeyAlgorithm,
+ hashsign_algorithm = default_hashsign(Version, KeyAlgorithm)}.
server_hello_done(#state{transport_cb = Transport,
socket = Socket,
negotiated_version = Version,
- connection_states = ConnectionStates,
- tls_handshake_hashes = Hashes} = State) ->
+ connection_states = ConnectionStates0,
+ tls_handshake_history = Handshake0} = State) ->
HelloDone = ssl_handshake:server_hello_done(),
- {BinHelloDone, NewConnectionStates, NewHashes} =
- encode_handshake(HelloDone, Version, ConnectionStates, Hashes),
+ {BinHelloDone, ConnectionStates, Handshake} =
+ encode_handshake(HelloDone, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinHelloDone),
- State#state{connection_states = NewConnectionStates,
- tls_handshake_hashes = NewHashes}.
+ State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake}.
certify_server(#state{key_algorithm = dh_anon} = State) ->
State;
@@ -1388,18 +1422,18 @@ certify_server(#state{key_algorithm = dh_anon} = State) ->
certify_server(#state{transport_cb = Transport,
socket = Socket,
negotiated_version = Version,
- connection_states = ConnectionStates,
- tls_handshake_hashes = Hashes,
+ connection_states = ConnectionStates0,
+ tls_handshake_history = Handshake0,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert}} = State) ->
case ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, server) of
CertMsg = #certificate{} ->
- {BinCertMsg, NewConnectionStates, NewHashes} =
- encode_handshake(CertMsg, Version, ConnectionStates, Hashes),
+ {BinCertMsg, ConnectionStates, Handshake} =
+ encode_handshake(CertMsg, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinCertMsg),
- State#state{connection_states = NewConnectionStates,
- tls_handshake_hashes = NewHashes
+ State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake
};
Alert = #alert{} ->
throw(Alert)
@@ -1408,11 +1442,12 @@ certify_server(#state{transport_cb = Transport,
key_exchange(#state{role = server, key_algorithm = rsa} = State) ->
State;
key_exchange(#state{role = server, key_algorithm = Algo,
+ hashsign_algorithm = HashSignAlgo,
diffie_hellman_params = #'DHParameter'{prime = P, base = G} = Params,
private_key = PrivateKey,
connection_states = ConnectionStates0,
negotiated_version = Version,
- tls_handshake_hashes = Hashes0,
+ tls_handshake_history = Handshake0,
socket = Socket,
transport_cb = Transport
} = State)
@@ -1425,16 +1460,16 @@ key_exchange(#state{role = server, key_algorithm = Algo,
SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Msg = ssl_handshake:key_exchange(server, {dh, Keys, Params,
- Algo, ClientRandom,
+ Msg = ssl_handshake:key_exchange(server, Version, {dh, Keys, Params,
+ HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
- {BinMsg, ConnectionStates, Hashes1} =
- encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
State#state{connection_states = ConnectionStates,
diffie_hellman_keys = Keys,
- tls_handshake_hashes = Hashes1};
+ tls_handshake_history = Handshake};
key_exchange(#state{role = client,
connection_states = ConnectionStates0,
@@ -1443,56 +1478,61 @@ key_exchange(#state{role = client,
negotiated_version = Version,
premaster_secret = PremasterSecret,
socket = Socket, transport_cb = Transport,
- tls_handshake_hashes = Hashes0} = State) ->
- Msg = rsa_key_exchange(PremasterSecret, PublicKeyInfo),
- {BinMsg, ConnectionStates1, Hashes1} =
- encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
+ tls_handshake_history = Handshake0} = State) ->
+ Msg = rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
- State#state{connection_states = ConnectionStates1,
- tls_handshake_hashes = Hashes1};
+ State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake};
key_exchange(#state{role = client,
connection_states = ConnectionStates0,
key_algorithm = Algorithm,
negotiated_version = Version,
diffie_hellman_keys = {DhPubKey, _},
socket = Socket, transport_cb = Transport,
- tls_handshake_hashes = Hashes0} = State)
+ tls_handshake_history = Handshake0} = State)
when Algorithm == dhe_dss;
Algorithm == dhe_rsa;
Algorithm == dh_anon ->
- Msg = ssl_handshake:key_exchange(client, {dh, DhPubKey}),
- {BinMsg, ConnectionStates1, Hashes1} =
- encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
+ Msg = ssl_handshake:key_exchange(client, Version, {dh, DhPubKey}),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
- State#state{connection_states = ConnectionStates1,
- tls_handshake_hashes = Hashes1}.
+ State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake}.
-rsa_key_exchange(PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
+rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
when Algorithm == ?rsaEncryption;
Algorithm == ?md2WithRSAEncryption;
Algorithm == ?md5WithRSAEncryption;
- Algorithm == ?sha1WithRSAEncryption ->
- ssl_handshake:key_exchange(client,
+ Algorithm == ?sha1WithRSAEncryption;
+ Algorithm == ?sha224WithRSAEncryption;
+ Algorithm == ?sha256WithRSAEncryption;
+ Algorithm == ?sha384WithRSAEncryption;
+ Algorithm == ?sha512WithRSAEncryption
+ ->
+ ssl_handshake:key_exchange(client, Version,
{premaster_secret, PremasterSecret,
PublicKeyInfo});
-rsa_key_exchange(_, _) ->
+rsa_key_exchange(_, _, _) ->
throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE)).
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,
+ tls_handshake_history = Handshake0,
negotiated_version = Version,
socket = Socket,
transport_cb = Transport} = State) ->
Msg = ssl_handshake:certificate_request(ConnectionStates0, CertDbHandle, CertDbRef),
- {BinMsg, ConnectionStates1, Hashes1} =
- encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
State#state{client_certificate_requested = true,
- connection_states = ConnectionStates1,
- tls_handshake_hashes = Hashes1};
+ connection_states = ConnectionStates,
+ tls_handshake_history = Handshake};
request_client_cert(#state{ssl_options = #ssl_options{verify = verify_none}} =
State) ->
State.
@@ -1518,14 +1558,16 @@ finished(#state{role = Role, socket = Socket, negotiated_version = Version,
transport_cb = Transport,
session = Session,
connection_states = ConnectionStates0,
- tls_handshake_hashes = Hashes0}, StateName) ->
+ tls_handshake_history = Handshake0}, StateName) ->
MasterSecret = Session#session.master_secret,
- Finished = ssl_handshake:finished(Version, Role, MasterSecret, Hashes0),
+ Finished = ssl_handshake:finished(Version, Role,
+ get_current_connection_state_prf(ConnectionStates0, write),
+ MasterSecret, Handshake0),
ConnectionStates1 = save_verify_data(Role, Finished, ConnectionStates0, StateName),
- {BinFinished, ConnectionStates, Hashes} =
- encode_handshake(Finished, Version, ConnectionStates1, Hashes0),
+ {BinFinished, ConnectionStates, Handshake} =
+ encode_handshake(Finished, Version, ConnectionStates1, Handshake0),
Transport:send(Socket, BinFinished),
- {ConnectionStates, Hashes}.
+ {ConnectionStates, Handshake}.
save_verify_data(client, #finished{verify_data = Data}, ConnectionStates, certify) ->
ssl_record:set_client_verify_data(current_write, Data, ConnectionStates);
@@ -1549,36 +1591,41 @@ handle_server_key(
#server_dh_params{dh_p = P,
dh_g = G,
dh_y = ServerPublicDhKey},
- signed_params = Signed},
- #state{public_key_info = PubKeyInfo,
- key_algorithm = KeyAlgo,
+ signed_params = Signed,
+ hashsign = HashSign},
+ #state{negotiated_version = Version,
+ public_key_info = PubKeyInfo,
connection_states = ConnectionStates} = State) ->
PLen = size(P),
GLen = size(G),
YLen = size(ServerPublicDhKey),
+ HashAlgo = connection_hash_algo(HashSign, State),
ConnectionState =
ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = ConnectionState#connection_state.security_parameters,
#security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- Hash = ssl_handshake:server_key_exchange_hash(KeyAlgo,
+ Hash = ssl_handshake:server_key_exchange_hash(HashAlgo,
<<ClientRandom/binary,
ServerRandom/binary,
?UINT16(PLen), P/binary,
?UINT16(GLen), G/binary,
?UINT16(YLen),
ServerPublicDhKey/binary>>),
-
- case verify_dh_params(Signed, Hash, PubKeyInfo) of
+
+ case verify_dh_params(Version, Signed, Hash, HashAlgo, PubKeyInfo) of
true ->
dh_master_secret(P, G, ServerPublicDhKey, undefined, State);
false ->
?ALERT_REC(?FATAL, ?DECRYPT_ERROR)
end.
-verify_dh_params(Signed, Hashes, {?rsaEncryption, PubKey, _PubKeyParams}) ->
+verify_dh_params({3, Minor}, Signed, Hashes, HashAlgo, {?rsaEncryption, PubKey, _PubKeyParams})
+ when Minor >= 3 ->
+ public_key:verify({digest, Hashes}, HashAlgo, Signed, PubKey);
+verify_dh_params(_Version, Signed, Hashes, _HashAlgo, {?rsaEncryption, PubKey, _PubKeyParams}) ->
case public_key:decrypt_public(Signed, PubKey,
[{rsa_pad, rsa_pkcs1_padding}]) of
Hashes ->
@@ -1586,8 +1633,8 @@ verify_dh_params(Signed, Hashes, {?rsaEncryption, PubKey, _PubKeyParams}) ->
_ ->
false
end;
-verify_dh_params(Signed, Hash, {?'id-dsa', PublicKey, PublicKeyParams}) ->
- public_key:verify(Hash, none, Signed, {PublicKey, PublicKeyParams}).
+verify_dh_params(_Version, Signed, Hash, HashAlgo, {?'id-dsa', PublicKey, PublicKeyParams}) ->
+ public_key:verify({digest, Hash}, HashAlgo, Signed, {PublicKey, PublicKeyParams}).
dh_master_secret(Prime, Base, PublicDhKey, undefined, State) ->
PMpint = mpint_binary(Prime),
@@ -1621,26 +1668,26 @@ cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0}
cipher_role(server, Data, Session, #state{connection_states = ConnectionStates0} = State) ->
ConnectionStates1 = ssl_record:set_client_verify_data(current_read, Data, ConnectionStates0),
- {ConnectionStates, Hashes} =
+ {ConnectionStates, Handshake} =
finalize_handshake(State#state{connection_states = ConnectionStates1,
session = Session}, cipher),
next_state_connection(cipher, ack_connection(State#state{connection_states =
ConnectionStates,
session = Session,
- tls_handshake_hashes =
- Hashes})).
+ tls_handshake_history =
+ Handshake})).
encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
ssl_record:encode_alert_record(Alert, Version, ConnectionStates).
encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) ->
ssl_record:encode_change_cipher_spec(Version, ConnectionStates).
-encode_handshake(HandshakeRec, Version, ConnectionStates0, Hashes0) ->
+encode_handshake(HandshakeRec, Version, ConnectionStates0, Handshake0) ->
Frag = ssl_handshake:encode_handshake(HandshakeRec, Version),
- Hashes1 = ssl_handshake:update_hashes(Hashes0, Frag),
+ Handshake1 = ssl_handshake:update_handshake_history(Handshake0, Frag),
{E, ConnectionStates1} =
ssl_record:encode_handshake(Frag, Version, ConnectionStates0),
- {E, ConnectionStates1, Hashes1}.
+ {E, ConnectionStates1, Handshake1}.
encode_packet(Data, #socket_options{packet=Packet}) ->
case Packet of
@@ -1651,15 +1698,12 @@ encode_packet(Data, #socket_options{packet=Packet}) ->
end.
encode_size_packet(Bin, Size, Max) ->
- Len = byte_size(Bin),
+ Len = erlang:byte_size(Bin),
case Len > Max of
true -> throw({error, {badarg, {packet_to_large, Len, Max}}});
false -> <<Len:Size, Bin/binary>>
end.
-encode_data(Data, Version, ConnectionStates, RenegotiateAt) ->
- ssl_record:encode_data(Data, Version, ConnectionStates, RenegotiateAt).
-
decode_alerts(Bin) ->
decode_alerts(Bin, []).
@@ -1673,20 +1717,20 @@ passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
case Buffer of
<<>> ->
{Record, State} = next_record(State0),
- next_state(StateName, Record, State);
+ next_state(StateName, StateName, Record, State);
_ ->
- case application_data(<<>>, State0) of
+ case read_application_data(<<>>, State0) of
Stop = {stop, _, _} ->
Stop;
{Record, State} ->
- next_state(StateName, Record, State)
+ next_state(StateName, StateName, Record, State)
end
end.
-application_data(Data, #state{user_application = {_Mon, Pid},
+read_application_data(Data, #state{user_application = {_Mon, Pid},
socket_options = SOpts,
bytes_to_read = BytesToRead,
- from = From,
+ start_or_recv_from = RecvFrom,
user_data_buffer = Buffer0} = State0) ->
Buffer1 = if
Buffer0 =:= <<>> -> Data;
@@ -1695,9 +1739,9 @@ application_data(Data, #state{user_application = {_Mon, Pid},
end,
case get_data(SOpts, BytesToRead, Buffer1) of
{ok, ClientData, Buffer} -> % Send data
- SocketOpt = deliver_app_data(SOpts, ClientData, Pid, From),
+ SocketOpt = deliver_app_data(SOpts, ClientData, Pid, RecvFrom),
State = State0#state{user_data_buffer = Buffer,
- from = undefined,
+ start_or_recv_from = undefined,
bytes_to_read = 0,
socket_options = SocketOpt
},
@@ -1707,15 +1751,48 @@ application_data(Data, #state{user_application = {_Mon, Pid},
%% Active and empty, get more data
next_record_if_active(State);
true -> %% We have more data
- application_data(<<>>, State)
+ read_application_data(<<>>, State)
end;
{more, Buffer} -> % no reply, we need more data
next_record(State0#state{user_data_buffer = Buffer});
{error,_Reason} -> %% Invalid packet in packet mode
- deliver_packet_error(SOpts, Buffer1, Pid, From),
+ deliver_packet_error(SOpts, Buffer1, Pid, RecvFrom),
{stop, normal, State0}
end.
+write_application_data(Data0, From, #state{socket = Socket,
+ negotiated_version = Version,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ send_queue = SendQueue,
+ socket_options = SockOpts,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State) ->
+ Data = encode_packet(Data0, SockOpts),
+
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ renegotiate(State#state{send_queue = queue:in_r({From, Data}, SendQueue),
+ renegotiation = {true, internal}});
+ false ->
+ {Msgs, ConnectionStates} = ssl_record:encode_data(Data, Version, ConnectionStates0),
+ Result = Transport:send(Socket, Msgs),
+ {reply, Result,
+ connection, State#state{connection_states = ConnectionStates}, get_timeout(State)}
+ end.
+
+time_to_renegotiate(_Data, #connection_states{current_write =
+ #connection_state{sequence_number = Num}}, RenegotiateAt) ->
+
+ %% We could do test:
+ %% is_time_to_renegotiate((erlang:byte_size(_Data) div ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt),
+ %% but we chose to have a some what lower renegotiateAt and a much cheaper test
+ is_time_to_renegotiate(Num, RenegotiateAt).
+
+is_time_to_renegotiate(N, M) when N < M->
+ false;
+is_time_to_renegotiate(_,_) ->
+ true.
+
%% Picks ClientData
get_data(_, _, <<>>) ->
{more, <<>>};
@@ -1799,14 +1876,15 @@ 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}; Packet == httph;
- Packet == httph_bin->
+ 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).
header(0, <<>>) ->
- <<>>;
+ [];
header(_, <<>>) ->
[];
header(0, Binary) ->
@@ -1817,6 +1895,10 @@ header(N, Binary) ->
send_or_reply(false, _Pid, From, Data) when From =/= undefined ->
gen_fsm:reply(From, Data);
+%% Can happen when handling own alert or tcp error/close and there is
+%% no outstanding gen_fsm sync events
+send_or_reply(false, no_pid, _, _) ->
+ ok;
send_or_reply(_, Pid, _From, Data) ->
send_user(Pid, Data).
@@ -1841,67 +1923,68 @@ handle_tls_handshake(Handle, StateName, #state{tls_packets = [Packet | Packets]}
Stop
end.
-next_state(_, #alert{} = Alert, #state{negotiated_version = Version} = State) ->
- handle_own_alert(Alert, Version, decipher_error, State),
+next_state(Current,_, #alert{} = Alert, #state{negotiated_version = Version} = State) ->
+ handle_own_alert(Alert, Version, Current, State),
{stop, normal, State};
-next_state(Next, no_record, State) ->
+next_state(_,Next, no_record, State) ->
{next_state, Next, State, get_timeout(State)};
-next_state(Next, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, State) ->
+next_state(_,Next, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, State) ->
Alerts = decode_alerts(EncAlerts),
handle_alerts(Alerts, {next_state, Next, State, get_timeout(State)});
-next_state(StateName, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
+next_state(Current, Next, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
State0 = #state{tls_handshake_buffer = Buf0, negotiated_version = Version}) ->
Handle =
fun({#hello_request{} = Packet, _}, {next_state, connection = SName, State}) ->
%% This message should not be included in handshake
%% message hashes. Starts new handshake (renegotiation)
- Hs0 = ssl_handshake:init_hashes(),
- ?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs0,
+ Hs0 = ssl_handshake:init_handshake_history(),
+ ?MODULE:SName(Packet, State#state{tls_handshake_history=Hs0,
renegotiation = {true, peer}});
({#hello_request{} = Packet, _}, {next_state, SName, State}) ->
%% This message should not be included in handshake
%% message hashes. Already in negotiation so it will be ignored!
?MODULE:SName(Packet, State);
({#client_hello{} = Packet, Raw}, {next_state, connection = SName, State}) ->
- Hs0 = ssl_handshake:init_hashes(),
- Hs1 = ssl_handshake:update_hashes(Hs0, Raw),
- ?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs1,
+ Version = Packet#client_hello.client_version,
+ Hs0 = ssl_handshake:init_handshake_history(),
+ Hs1 = ssl_handshake:update_handshake_history(Hs0, Raw),
+ ?MODULE:SName(Packet, State#state{tls_handshake_history=Hs1,
renegotiation = {true, peer}});
- ({Packet, Raw}, {next_state, SName, State = #state{tls_handshake_hashes=Hs0}}) ->
- Hs1 = ssl_handshake:update_hashes(Hs0, Raw),
- ?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs1});
+ ({Packet, Raw}, {next_state, SName, State = #state{tls_handshake_history=Hs0}}) ->
+ Hs1 = ssl_handshake:update_handshake_history(Hs0, Raw),
+ ?MODULE:SName(Packet, State#state{tls_handshake_history=Hs1});
(_, StopState) -> StopState
end,
try
- {Packets, Buf} = ssl_handshake:get_tls_handshake(Data,Buf0),
+ {Packets, Buf} = ssl_handshake:get_tls_handshake(Version,Data,Buf0),
State = State0#state{tls_packets = Packets, tls_handshake_buffer = Buf},
- handle_tls_handshake(Handle, StateName, State)
+ handle_tls_handshake(Handle, Next, State)
catch throw:#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State0),
+ handle_own_alert(Alert, Version, Current, State0),
{stop, normal, State0}
end;
-next_state(StateName, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, State0) ->
- case application_data(Data, State0) of
+next_state(_, StateName, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, State0) ->
+ case read_application_data(Data, State0) of
Stop = {stop,_,_} ->
Stop;
{Record, State} ->
- next_state(StateName, Record, State)
+ next_state(StateName, StateName, Record, State)
end;
-next_state(StateName, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = <<1>>} =
+next_state(Current, Next, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = <<1>>} =
_ChangeCipher,
#state{connection_states = ConnectionStates0} = State0) ->
ConnectionStates1 =
ssl_record:activate_pending_connection_state(ConnectionStates0, read),
{Record, State} = next_record(State0#state{connection_states = ConnectionStates1}),
- next_state(StateName, Record, State);
-next_state(StateName, #ssl_tls{type = _Unknown}, State0) ->
+ next_state(Current, Next, Record, State);
+next_state(Current, Next, #ssl_tls{type = _Unknown}, State0) ->
%% Ignore unknown type
{Record, State} = next_record(State0),
- next_state(StateName, Record, State).
+ next_state(Current, Next, Record, State).
next_tls_record(Data, #state{tls_record_buffer = Buf0,
tls_cipher_texts = CT0} = State0) ->
@@ -1940,63 +2023,49 @@ next_state_connection(StateName, #state{send_queue = Queue0,
negotiated_version = Version,
socket = Socket,
transport_cb = Transport,
- connection_states = ConnectionStates0,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}
+ connection_states = ConnectionStates0
} = State) ->
- %% Send queued up data
+ %% Send queued up data that was queued while renegotiating
case queue:out(Queue0) of
{{value, {From, Data}}, Queue} ->
- case encode_data(Data, Version, ConnectionStates0, RenegotiateAt) of
- {Msgs, [], ConnectionStates} ->
- Result = Transport:send(Socket, Msgs),
- gen_fsm:reply(From, Result),
- next_state_connection(StateName,
- State#state{connection_states = ConnectionStates,
- send_queue = Queue});
- %% This is unlikely to happen. User configuration of the
- %% undocumented test option renegotiation_at can make it more likely.
- {Msgs, RestData, ConnectionStates} ->
- if
- Msgs =/= [] ->
- Transport:send(Socket, Msgs);
- true ->
- ok
- end,
- renegotiate(State#state{connection_states = ConnectionStates,
- send_queue = queue:in_r({From, RestData}, Queue),
- renegotiation = {true, internal}})
- end;
+ {Msgs, ConnectionStates} =
+ ssl_record:encode_data(Data, Version, ConnectionStates0),
+ Result = Transport:send(Socket, Msgs),
+ gen_fsm:reply(From, Result),
+ next_state_connection(StateName,
+ State#state{connection_states = ConnectionStates,
+ send_queue = Queue});
{empty, Queue0} ->
- next_state_is_connection(State)
+ next_state_is_connection(StateName, State)
end.
-%% In next_state_is_connection/1: clear tls_handshake_hashes,
+%% In next_state_is_connection/1: clear tls_handshake,
%% premaster_secret and public_key_info (only needed during handshake)
%% to reduce memory foot print of a connection.
-next_state_is_connection(State =
- #state{recv_during_renegotiation = true, socket_options =
- #socket_options{active = false}}) ->
- passive_receive(State#state{recv_during_renegotiation = false,
- premaster_secret = undefined,
+next_state_is_connection(_, State =
+ #state{start_or_recv_from = RecvFrom,
+ socket_options =
+ #socket_options{active = false}}) when RecvFrom =/= undefined ->
+ passive_receive(State#state{premaster_secret = undefined,
public_key_info = undefined,
- tls_handshake_hashes = {<<>>, <<>>}}, connection);
+ tls_handshake_history = ssl_handshake:init_handshake_history()}, connection);
-next_state_is_connection(State0) ->
+next_state_is_connection(StateName, State0) ->
{Record, State} = next_record_if_active(State0),
- next_state(connection, Record, State#state{premaster_secret = undefined,
+ next_state(StateName, connection, Record, State#state{premaster_secret = undefined,
public_key_info = undefined,
- tls_handshake_hashes = {<<>>, <<>>}}).
+ tls_handshake_history = ssl_handshake:init_handshake_history()}).
-register_session(_, _, _, #session{is_resumable = true} = Session) ->
- Session; %% Already registered
-register_session(client, Host, Port, Session0) ->
+register_session(client, Host, Port, #session{is_resumable = new} = Session0) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Host, Port, Session),
Session;
-register_session(server, _, Port, Session0) ->
+register_session(server, _, Port, #session{is_resumable = new} = Session0) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Port, Session),
- Session.
+ Session;
+register_session(_, _, _, Session) ->
+ Session. %% Already registered
invalidate_session(client, Host, Port, Session) ->
ssl_manager:invalidate_session(Host, Port, Session);
@@ -2020,7 +2089,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions}, User,
%% We do not want to save the password in the state so that
%% could be written in the clear into error logs.
ssl_options = SSLOptions#ssl_options{password = undefined},
- session = #session{is_resumable = false},
+ session = #session{is_resumable = new},
transport_cb = CbModule,
data_tag = DataTag,
close_tag = CloseTag,
@@ -2039,7 +2108,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions}, User,
log_alert = true,
session_cache_cb = SessionCacheCb,
renegotiation = {false, first},
- recv_during_renegotiation = false,
+ start_or_recv_from = undefined,
send_queue = queue:new()
}.
@@ -2143,7 +2212,7 @@ handle_alerts([Alert | Alerts], {next_state, StateName, State, _Timeout}) ->
handle_alerts(Alerts, handle_alert(Alert, StateName, State)).
handle_alert(#alert{level = ?FATAL} = Alert, StateName,
- #state{from = From, host = Host, port = Port, session = Session,
+ #state{start_or_recv_from = From, host = Host, port = Port, session = Session,
user_application = {_Mon, Pid},
log_alert = Log, role = Role, socket_options = Opts} = State) ->
invalidate_session(Role, Host, Port, Session),
@@ -2152,16 +2221,14 @@ handle_alert(#alert{level = ?FATAL} = Alert, StateName,
{stop, normal, State};
handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
- StateName, #state{from = From, role = Role,
- user_application = {_Mon, Pid}, socket_options = Opts} = State) ->
- alert_user(StateName, Opts, Pid, From, Alert, Role),
+ StateName, State) ->
+ handle_normal_shutdown(Alert, StateName, State),
{stop, normal, State};
handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{log_alert = Log, renegotiation = {true, internal}, from = From,
- role = Role} = State) ->
+ #state{log_alert = Log, renegotiation = {true, internal}} = State) ->
log_alert(Log, StateName, Alert),
- alert_user(From, Alert, Role),
+ handle_normal_shutdown(Alert, StateName, State),
{stop, normal, State};
handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
@@ -2169,13 +2236,13 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
log_alert(Log, StateName, Alert),
gen_fsm:reply(From, {error, renegotiation_rejected}),
{Record, State} = next_record(State0),
- next_state(connection, Record, State);
+ next_state(StateName, connection, Record, State);
handle_alert(#alert{level = ?WARNING, description = ?USER_CANCELED} = Alert, StateName,
#state{log_alert = Log} = State0) ->
log_alert(Log, StateName, Alert),
{Record, State} = next_record(State0),
- next_state(StateName, Record, State).
+ next_state(StateName, StateName, Record, State).
alert_user(connection, Opts, Pid, From, Alert, Role) ->
alert_user(Opts#socket_options.active, Pid, From, Alert, Role);
@@ -2207,13 +2274,11 @@ log_alert(true, Info, Alert) ->
log_alert(false, _, _) ->
ok.
-handle_own_alert(Alert, Version, Info,
+handle_own_alert(Alert, Version, StateName,
#state{transport_cb = Transport,
socket = Socket,
- from = User,
- role = Role,
connection_states = ConnectionStates,
- log_alert = Log}) ->
+ log_alert = Log} = State) ->
try %% Try to tell the other side
{BinMsg, _} =
encode_alert(Alert, Version, ConnectionStates),
@@ -2223,25 +2288,33 @@ handle_own_alert(Alert, Version, Info,
ignore
end,
try %% Try to tell the local user
- log_alert(Log, Info, Alert),
- alert_user(User, Alert, Role)
+ log_alert(Log, StateName, Alert),
+ handle_normal_shutdown(Alert,StateName, State)
catch _:_ ->
ok
end.
+handle_normal_shutdown(Alert, _, #state{start_or_recv_from = StartFrom, role = Role, renegotiation = {false, first}}) ->
+ alert_user(StartFrom, Alert, Role);
+
+handle_normal_shutdown(Alert, StateName, #state{socket_options = Opts,
+ user_application = {_Mon, Pid},
+ start_or_recv_from = RecvFrom, role = Role}) ->
+ alert_user(StateName, Opts, Pid, RecvFrom, Alert, Role).
+
handle_unexpected_message(Msg, Info, #state{negotiated_version = Version} = State) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE),
handle_own_alert(Alert, Version, {Info, Msg}, State),
{stop, normal, State}.
make_premaster_secret({MajVer, MinVer}, rsa) ->
- Rand = crypto:rand_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2),
+ Rand = ssl:random_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2),
<<?BYTE(MajVer), ?BYTE(MinVer), Rand/binary>>;
make_premaster_secret(_, _) ->
undefined.
mpint_binary(Binary) ->
- Size = byte_size(Binary),
+ Size = erlang:byte_size(Binary),
<<?UINT32(Size), Binary/binary>>.
@@ -2253,17 +2326,17 @@ ack_connection(#state{renegotiation = {true, From}} = State) ->
gen_fsm:reply(From, ok),
State#state{renegotiation = undefined};
ack_connection(#state{renegotiation = {false, first},
- from = From} = State) when From =/= undefined ->
- gen_fsm:reply(From, connected),
- State#state{renegotiation = undefined};
+ start_or_recv_from = StartFrom} = State) when StartFrom =/= undefined ->
+ gen_fsm:reply(StartFrom, connected),
+ State#state{renegotiation = undefined, start_or_recv_from = undefined};
ack_connection(State) ->
State.
renegotiate(#state{role = client} = State) ->
%% Handle same way as if server requested
%% the renegotiation
- Hs0 = ssl_handshake:init_hashes(),
- connection(#hello_request{}, State#state{tls_handshake_hashes = Hs0});
+ Hs0 = ssl_handshake:init_handshake_history(),
+ connection(#hello_request{}, State#state{tls_handshake_history = Hs0});
renegotiate(#state{role = server,
socket = Socket,
transport_cb = Transport,
@@ -2271,14 +2344,14 @@ renegotiate(#state{role = server,
connection_states = ConnectionStates0} = State0) ->
HelloRequest = ssl_handshake:hello_request(),
Frag = ssl_handshake:encode_handshake(HelloRequest, Version),
- Hs0 = ssl_handshake:init_hashes(),
+ Hs0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates} =
ssl_record:encode_handshake(Frag, Version, ConnectionStates0),
Transport:send(Socket, BinMsg),
{Record, State} = next_record(State0#state{connection_states =
ConnectionStates,
- tls_handshake_hashes = Hs0}),
- next_state(hello, Record, State).
+ tls_handshake_history = Hs0}),
+ next_state(connection, hello, Record, State#state{allow_renegotiate = true}).
notify_senders(SendQueue) ->
lists:foreach(fun({From, _}) ->
@@ -2321,7 +2394,74 @@ linux_workaround_transport_delivery_problems(#alert{level = ?FATAL}, Socket) ->
linux_workaround_transport_delivery_problems(_, _) ->
ok.
-get_timeout(#state{ssl_options=#ssl_options{hibernate_after=undefined}}) ->
+get_timeout(#state{ssl_options=#ssl_options{hibernate_after = undefined}}) ->
infinity;
-get_timeout(#state{ssl_options=#ssl_options{hibernate_after=HibernateAfter}}) ->
+get_timeout(#state{ssl_options=#ssl_options{hibernate_after = HibernateAfter}}) ->
HibernateAfter.
+
+handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>}}) ->
+ %% No trusted certs specified
+ ok;
+handle_trusted_certs_db(#state{cert_db_ref = Ref,
+ cert_db = CertDb,
+ ssl_options = #ssl_options{cacertfile = undefined}}) ->
+ %% Certs provided as DER directly can not be shared
+ %% with other connections and it is safe to delete them when the connection ends.
+ ssl_certificate_db:remove_trusted_certs(Ref, CertDb);
+handle_trusted_certs_db(#state{file_ref_db = undefined}) ->
+ %% Something went wrong early (typically cacertfile does not exist) so there is nothing to handle
+ ok;
+handle_trusted_certs_db(#state{cert_db_ref = Ref,
+ file_ref_db = RefDb,
+ ssl_options = #ssl_options{cacertfile = File}}) ->
+ case ssl_certificate_db:ref_count(Ref, RefDb, -1) of
+ 0 ->
+ ssl_manager:clean_cert_db(Ref, File);
+ _ ->
+ ok
+ end.
+
+get_current_connection_state_prf(CStates, Direction) ->
+ CS = ssl_record:current_connection_state(CStates, Direction),
+ CS#connection_state.security_parameters#security_parameters.prf_algorithm.
+get_pending_connection_state_prf(CStates, Direction) ->
+ CS = ssl_record:pending_connection_state(CStates, Direction),
+ CS#connection_state.security_parameters#security_parameters.prf_algorithm.
+
+connection_hash_algo({HashAlgo, _}, _State) ->
+ HashAlgo;
+connection_hash_algo(_, #state{hashsign_algorithm = {HashAlgo, _}}) ->
+ HashAlgo.
+
+%% RFC 5246, Sect. 7.4.1.4.1. Signature Algorithms
+%% If the client does not send the signature_algorithms extension, the
+%% server MUST do the following:
+%%
+%% - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA,
+%% DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), behave as if client had
+%% sent the value {sha1,rsa}.
+%%
+%% - If the negotiated key exchange algorithm is one of (DHE_DSS,
+%% DH_DSS), behave as if the client had sent the value {sha1,dsa}.
+%%
+%% - If the negotiated key exchange algorithm is one of (ECDH_ECDSA,
+%% ECDHE_ECDSA), behave as if the client had sent value {sha1,ecdsa}.
+
+default_hashsign(_Version = {Major, Minor}, KeyExchange)
+ when Major == 3 andalso Minor >= 3 andalso
+ (KeyExchange == rsa orelse
+ KeyExchange == dhe_rsa orelse
+ KeyExchange == dh_rsa) ->
+ {sha, rsa};
+default_hashsign(_Version, KeyExchange)
+ when KeyExchange == rsa;
+ KeyExchange == dhe_rsa;
+ KeyExchange == dh_rsa ->
+ {md5sha, rsa};
+default_hashsign(_Version, KeyExchange)
+ when KeyExchange == dhe_dss;
+ KeyExchange == dh_dss ->
+ {sha, dsa};
+default_hashsign(_Version, KeyExchange)
+ when KeyExchange == dh_anon ->
+ {null, anon}.
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
index c1912401d7..9d9afb7707 100644
--- a/lib/ssl/src/ssl_dist_sup.erl
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -41,7 +41,6 @@ start_link() ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
--spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
init([]) ->
SessionCertManager = session_and_cert_manager_child_spec(),
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index f873a6a913..bb26302fff 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,14 +30,14 @@
-include("ssl_internal.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([master_secret/4, client_hello/6, server_hello/4, hello/4,
+-export([master_secret/4, client_hello/8, server_hello/4, hello/4,
hello_request/0, certify/7, certificate/4,
- client_certificate_verify/5, certificate_verify/5,
- certificate_request/3, key_exchange/2, server_key_exchange_hash/2,
- finished/4, verify_connection/5, get_tls_handshake/2,
+ client_certificate_verify/6, certificate_verify/6,
+ certificate_request/3, key_exchange/3, server_key_exchange_hash/2,
+ finished/5, verify_connection/6, get_tls_handshake/3,
decode_client_key/3, server_hello_done/0,
- encode_handshake/2, init_hashes/0, update_hashes/2,
- decrypt_premaster_secret/2]).
+ encode_handshake/2, init_handshake_history/0, update_handshake_history/2,
+ decrypt_premaster_secret/2, prf/5]).
-export([dec_hello_extensions/2]).
@@ -51,14 +51,17 @@
%%====================================================================
%%--------------------------------------------------------------------
-spec client_hello(host(), inet:port_number(), #connection_states{},
- #ssl_options{}, boolean(), der_cert()) -> #client_hello{}.
+ #ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
+ #client_hello{}.
%%
%% Description: Creates a client hello message.
%%--------------------------------------------------------------------
-client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions,
- ciphers = UserSuites}
- = SslOpts, Renegotiation, OwnCert) ->
-
+client_hello(Host, Port, ConnectionStates,
+ #ssl_options{versions = Versions,
+ ciphers = UserSuites
+ } = SslOpts,
+ Cache, CacheCb, Renegotiation, OwnCert) ->
+
Fun = fun(Version) ->
ssl_record:protocol_version(Version)
end,
@@ -67,15 +70,16 @@ client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions,
SecParams = Pending#connection_state.security_parameters,
Ciphers = available_suites(UserSuites, Version),
- Id = ssl_manager:client_session_id(Host, Port, SslOpts, OwnCert),
+ Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
- #client_hello{session_id = Id,
+ #client_hello{session_id = Id,
client_version = Version,
cipher_suites = cipher_suites(Ciphers, Renegotiation),
compression_methods = ssl_record:compressions(),
random = SecParams#security_parameters.client_random,
- renegotiation_info =
- renegotiation_info(client, ConnectionStates, Renegotiation)
+ renegotiation_info =
+ renegotiation_info(client, ConnectionStates, Renegotiation),
+ hash_signs = default_hash_signs()
}.
%%--------------------------------------------------------------------
@@ -118,17 +122,18 @@ hello_request() ->
%%--------------------------------------------------------------------
hello(#server_hello{cipher_suite = CipherSuite, server_version = Version,
compression_method = Compression, random = Random,
- session_id = SessionId, renegotiation_info = Info},
+ session_id = SessionId, renegotiation_info = Info,
+ hash_signs = _HashSigns},
#ssl_options{secure_renegotiate = SecureRenegotation},
ConnectionStates0, Renegotiation) ->
-
+%%TODO: select hash and signature algorigthm
case ssl_record:is_acceptable_version(Version) of
true ->
case handle_renegotiation_info(client, Info, ConnectionStates0,
Renegotiation, SecureRenegotation, []) of
{ok, ConnectionStates1} ->
ConnectionStates =
- hello_pending_connection_states(client, CipherSuite, Random,
+ hello_pending_connection_states(client, Version, CipherSuite, Random,
Compression, ConnectionStates1),
{Version, SessionId, ConnectionStates};
#alert{} = Alert ->
@@ -140,10 +145,12 @@ hello(#server_hello{cipher_suite = CipherSuite, server_version = Version,
hello(#client_hello{client_version = ClientVersion, random = Random,
cipher_suites = CipherSuites,
- renegotiation_info = Info} = Hello,
+ renegotiation_info = Info,
+ hash_signs = _HashSigns} = Hello,
#ssl_options{versions = Versions,
secure_renegotiate = SecureRenegotation} = SslOpts,
{Port, Session0, Cache, CacheCb, ConnectionStates0, Cert}, Renegotiation) ->
+%% TODO: select hash and signature algorithm
Version = select_version(ClientVersion, Versions),
case ssl_record:is_acceptable_version(Version) of
true ->
@@ -161,6 +168,7 @@ hello(#client_hello{client_version = ClientVersion, random = Random,
{ok, ConnectionStates1} ->
ConnectionStates =
hello_pending_connection_states(server,
+ Version,
CipherSuite,
Random,
Compression,
@@ -188,14 +196,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
ValidationFunAndState =
case VerifyFunAndState of
undefined ->
- {fun(OtpCert, ExtensionOrError, SslState) ->
+ {fun(OtpCert, ExtensionOrVerifyResult, SslState) ->
ssl_certificate:validate_extension(OtpCert,
- ExtensionOrError, SslState)
+ ExtensionOrVerifyResult, SslState)
end, Role};
{Fun, UserState0} ->
- {fun(OtpCert, ExtensionOrError, {SslState, UserState}) ->
+ {fun(OtpCert, {extension, _} = Extension, {SslState, UserState}) ->
case ssl_certificate:validate_extension(OtpCert,
- ExtensionOrError,
+ Extension,
SslState) of
{valid, NewSslState} ->
{valid, {NewSslState, UserState}};
@@ -204,23 +212,31 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
SslState);
{unknown, _} ->
apply_user_fun(Fun, OtpCert,
- ExtensionOrError, UserState, SslState)
- end
+ Extension, UserState, SslState)
+ end;
+ (OtpCert, VerifyResult, {SslState, UserState}) ->
+ apply_user_fun(Fun, OtpCert, VerifyResult, UserState,
+ SslState)
end, {Role, UserState0}}
end,
- {TrustedErlCert, CertPath} =
- ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef),
-
- case public_key:pkix_path_validation(TrustedErlCert,
- CertPath,
- [{max_path_length,
- MaxPathLen},
- {verify_fun, ValidationFunAndState}]) of
- {ok, {PublicKeyInfo,_}} ->
- {PeerCert, PublicKeyInfo};
- {error, Reason} ->
- path_validation_alert(Reason)
+ try
+ {TrustedErlCert, CertPath} =
+ ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef),
+ case public_key:pkix_path_validation(TrustedErlCert,
+ CertPath,
+ [{max_path_length,
+ MaxPathLen},
+ {verify_fun, ValidationFunAndState}]) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, Reason} ->
+ path_validation_alert(Reason)
+ end
+ catch
+ error:_ ->
+ %% ASN-1 decode of certificate somehow failed
+ ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN)
end.
%%--------------------------------------------------------------------
@@ -251,54 +267,51 @@ certificate(OwnCert, CertDbHandle, CertDbRef, server) ->
%%--------------------------------------------------------------------
-spec client_certificate_verify(undefined | der_cert(), binary(),
- tls_version(), private_key(),
- {{binary(), binary()},{binary(), binary()}}) ->
+ tls_version(), term(), private_key(),
+ tls_handshake_history()) ->
#certificate_verify{} | ignore | #alert{}.
%%
%% Description: Creates a certificate_verify message, called by the client.
%%--------------------------------------------------------------------
-client_certificate_verify(undefined, _, _, _, _) ->
+client_certificate_verify(undefined, _, _, _, _, _) ->
ignore;
-client_certificate_verify(_, _, _, undefined, _) ->
+client_certificate_verify(_, _, _, _, undefined, _) ->
ignore;
client_certificate_verify(OwnCert, MasterSecret, Version,
- PrivateKey, {Hashes0, _}) ->
+ {HashAlgo, SignAlgo},
+ PrivateKey, {Handshake, _}) ->
case public_key:pkix_is_fixed_dh_cert(OwnCert) of
true ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
- false ->
- Hashes =
- calc_certificate_verify(Version, MasterSecret,
- alg_oid(PrivateKey), Hashes0),
- Signed = digitally_signed(Hashes, PrivateKey),
- #certificate_verify{signature = Signed}
+ false ->
+ Hashes =
+ calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake),
+ Signed = digitally_signed(Version, Hashes, HashAlgo, PrivateKey),
+ #certificate_verify{signature = Signed, hashsign_algorithm = {HashAlgo, SignAlgo}}
end.
%%--------------------------------------------------------------------
--spec certificate_verify(binary(), public_key_info(), tls_version(),
- binary(), {_, {binary(), binary()}}) -> valid | #alert{}.
+-spec certificate_verify(binary(), public_key_info(), tls_version(), term(),
+ binary(), tls_handshake_history()) -> valid | #alert{}.
%%
%% Description: Checks that the certificate_verify message is valid.
%%--------------------------------------------------------------------
-certificate_verify(Signature, {?'rsaEncryption'= Algorithm, PublicKey, _}, Version,
- MasterSecret, {_, Hashes0}) ->
- Hashes = calc_certificate_verify(Version, MasterSecret,
- Algorithm, Hashes0),
- case public_key:decrypt_public(Signature, PublicKey,
- [{rsa_pad, rsa_pkcs1_padding}]) of
- Hashes ->
+certificate_verify(Signature, {?'rsaEncryption', PublicKey, _}, Version,
+ {HashAlgo, _SignAlgo}, MasterSecret, {_, Handshake}) ->
+ Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake),
+ case certificate_verify_rsa(Hashes, HashAlgo, Signature, PublicKey, Version) of
+ true ->
valid;
_ ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE)
end;
-certificate_verify(Signature, {?'id-dsa' = Algorithm, PublicKey, PublicKeyParams}, Version,
- MasterSecret, {_, Hashes0}) ->
- Hashes = calc_certificate_verify(Version, MasterSecret,
- Algorithm, Hashes0),
- case public_key:verify(Hashes, none, Signature, {PublicKey, PublicKeyParams}) of
- true ->
- valid;
- false ->
+certificate_verify(Signature, {?'id-dsa', PublicKey, PublicKeyParams}, Version,
+ {HashAlgo, _SignAlgo}, MasterSecret, {_, Handshake}) ->
+ Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake),
+ case public_key:verify({digest, Hashes}, sha, Signature, {PublicKey, PublicKeyParams}) of
+ true ->
+ valid;
+ false ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE)
end.
@@ -314,36 +327,38 @@ certificate_request(ConnectionStates, CertDbHandle, CertDbRef) ->
#security_parameters{cipher_suite = CipherSuite}} =
ssl_record:pending_connection_state(ConnectionStates, read),
Types = certificate_types(CipherSuite),
+ HashSigns = default_hash_signs(),
Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
+ hashsign_algorithms = HashSigns,
certificate_authorities = Authorities
}.
%%--------------------------------------------------------------------
--spec key_exchange(client | server,
+-spec key_exchange(client | server, tls_version(),
{premaster_secret, binary(), public_key_info()} |
{dh, binary()} |
- {dh, {binary(), binary()}, #'DHParameter'{}, key_algo(),
+ {dh, {binary(), binary()}, #'DHParameter'{}, {HashAlgo::atom(), SignAlgo::atom()},
binary(), binary(), private_key()}) ->
#client_key_exchange{} | #server_key_exchange{}.
%%
%% Description: Creates a keyexchange message.
%%--------------------------------------------------------------------
-key_exchange(client, {premaster_secret, Secret, {_, PublicKey, _}}) ->
+key_exchange(client, _Version, {premaster_secret, Secret, {_, PublicKey, _}}) ->
EncPremasterSecret =
encrypted_premaster_secret(Secret, PublicKey),
#client_key_exchange{exchange_keys = EncPremasterSecret};
-key_exchange(client, {dh, <<?UINT32(Len), PublicKey:Len/binary>>}) ->
+key_exchange(client, _Version, {dh, <<?UINT32(Len), PublicKey:Len/binary>>}) ->
#client_key_exchange{
exchange_keys = #client_diffie_hellman_public{
dh_public = PublicKey}
};
-key_exchange(server, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _},
+key_exchange(server, Version, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _},
#'DHParameter'{prime = P, base = G},
- KeyAlgo, ClientRandom, ServerRandom, PrivateKey}) ->
+ {HashAlgo, SignAlgo}, ClientRandom, ServerRandom, PrivateKey}) ->
<<?UINT32(_), PBin/binary>> = crypto:mpint(P),
<<?UINT32(_), GBin/binary>> = crypto:mpint(G),
PLen = byte_size(PBin),
@@ -352,20 +367,22 @@ key_exchange(server, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _},
ServerDHParams = #server_dh_params{dh_p = PBin,
dh_g = GBin, dh_y = PublicKey},
- case KeyAlgo of
- dh_anon ->
+ case HashAlgo of
+ null ->
#server_key_exchange{params = ServerDHParams,
- signed_params = <<>>};
+ signed_params = <<>>,
+ hashsign = {null, anon}};
_ ->
Hash =
- server_key_exchange_hash(KeyAlgo, <<ClientRandom/binary,
+ server_key_exchange_hash(HashAlgo, <<ClientRandom/binary,
ServerRandom/binary,
?UINT16(PLen), PBin/binary,
?UINT16(GLen), GBin/binary,
?UINT16(YLen), PublicKey/binary>>),
- Signed = digitally_signed(Hash, PrivateKey),
+ Signed = digitally_signed(Version, Hash, HashAlgo, PrivateKey),
#server_key_exchange{params = ServerDHParams,
- signed_params = Signed}
+ signed_params = Signed,
+ hashsign = {HashAlgo, SignAlgo}}
end.
%%--------------------------------------------------------------------
@@ -395,10 +412,11 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
ConnectionState =
ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = ConnectionState#connection_state.security_parameters,
- #security_parameters{client_random = ClientRandom,
+ #security_parameters{prf_algorithm = PrfAlgo,
+ client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
try master_secret(Version,
- calc_master_secret(Version,PremasterSecret,
+ calc_master_secret(Version,PrfAlgo,PremasterSecret,
ClientRandom, ServerRandom),
SecParams, ConnectionStates, Role)
catch
@@ -410,26 +428,26 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
end.
%%--------------------------------------------------------------------
--spec finished(tls_version(), client | server, binary(), {{binary(), binary()},_}) ->
+-spec finished(tls_version(), client | server, integer(), binary(), tls_handshake_history()) ->
#finished{}.
%%
%% Description: Creates a handshake finished message
%%-------------------------------------------------------------------
-finished(Version, Role, MasterSecret, {Hashes, _}) -> % use the current hashes
+finished(Version, Role, PrfAlgo, MasterSecret, {Handshake, _}) -> % use the current handshake
#finished{verify_data =
- calc_finished(Version, Role, MasterSecret, Hashes)}.
+ calc_finished(Version, Role, PrfAlgo, MasterSecret, Handshake)}.
%%--------------------------------------------------------------------
--spec verify_connection(tls_version(), #finished{}, client | server, binary(),
- {_, {binary(), binary()}}) -> verified | #alert{}.
+-spec verify_connection(tls_version(), #finished{}, client | server, integer(), binary(),
+ tls_handshake_history()) -> verified | #alert{}.
%%
%% Description: Checks the ssl handshake finished message to verify
%% the connection.
%%-------------------------------------------------------------------
verify_connection(Version, #finished{verify_data = Data},
- Role, MasterSecret, {_, {MD5, SHA}}) ->
+ Role, PrfAlgo, MasterSecret, {_, Handshake}) ->
%% use the previous hashes
- case calc_finished(Version, Role, MasterSecret, {MD5, SHA}) of
+ case calc_finished(Version, Role, PrfAlgo, MasterSecret, Handshake) of
Data ->
verified;
_ ->
@@ -447,24 +465,24 @@ server_hello_done() ->
-spec encode_handshake(tls_handshake(), tls_version()) -> iolist().
%%
%% Description: Encode a handshake packet to binary
-%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------x
encode_handshake(Package, Version) ->
{MsgType, Bin} = enc_hs(Package, Version),
Len = byte_size(Bin),
[MsgType, ?uint24(Len), Bin].
%%--------------------------------------------------------------------
--spec get_tls_handshake(binary(), binary() | iolist()) ->
+-spec get_tls_handshake(tls_version(), binary(), binary() | iolist()) ->
{[tls_handshake()], binary()}.
%%
%% Description: Given buffered and new data from ssl_record, collects
%% and returns it as a list of handshake messages, also returns leftover
%% data.
%%--------------------------------------------------------------------
-get_tls_handshake(Data, <<>>) ->
- get_tls_handshake_aux(Data, []);
-get_tls_handshake(Data, Buffer) ->
- get_tls_handshake_aux(list_to_binary([Buffer, Data]), []).
+get_tls_handshake(Version, Data, <<>>) ->
+ get_tls_handshake_aux(Version, Data, []);
+get_tls_handshake(Version, Data, Buffer) ->
+ get_tls_handshake_aux(Version, list_to_binary([Buffer, Data]), []).
%%--------------------------------------------------------------------
-spec decode_client_key(binary(), key_algo(), tls_version()) ->
@@ -476,39 +494,34 @@ decode_client_key(ClientKey, Type, Version) ->
dec_client_key(ClientKey, key_exchange_alg(Type), Version).
%%--------------------------------------------------------------------
--spec init_hashes() ->{{binary(), binary()}, {binary(), binary()}}.
+-spec init_handshake_history() -> tls_handshake_history().
%%
-%% Description: Calls crypto hash (md5 and sha) init functions to
-%% initalize the hash context.
+%% Description: Initialize the empty handshake history buffer.
%%--------------------------------------------------------------------
-init_hashes() ->
- T = {crypto:md5_init(), crypto:sha_init()},
- {T, T}.
+init_handshake_history() ->
+ {[], []}.
%%--------------------------------------------------------------------
--spec update_hashes({{binary(), binary()}, {binary(), binary()}}, Data ::term()) ->
- {{binary(), binary()}, {binary(), binary()}}.
+-spec update_handshake_history(tls_handshake_history(), Data ::term()) ->
+ tls_handshake_history().
%%
-%% Description: Calls crypto hash (md5 and sha) update functions to
-%% update the hash context with Data.
+%% Description: Update the handshake history buffer with Data.
%%--------------------------------------------------------------------
-update_hashes(Hashes, % special-case SSL2 client hello
- <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>) ->
- update_hashes(Hashes,
- <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>);
-update_hashes({{MD50, SHA0}, _Prev}, Data) ->
- {MD51, SHA1} = {crypto:md5_update(MD50, Data),
- crypto:sha_update(SHA0, Data)},
- {{MD51, SHA1}, {MD50, SHA0}}.
+update_handshake_history(Handshake, % special-case SSL2 client hello
+ <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(CSLength), ?UINT16(0),
+ ?UINT16(CDLength),
+ CipherSuites:CSLength/binary,
+ ChallengeData:CDLength/binary>>) ->
+ update_handshake_history(Handshake,
+ <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(CSLength), ?UINT16(0),
+ ?UINT16(CDLength),
+ CipherSuites:CSLength/binary,
+ ChallengeData:CDLength/binary>>);
+update_handshake_history({Handshake0, _Prev}, Data) ->
+ {[Data|Handshake0], Handshake0}.
%%--------------------------------------------------------------------
-spec decrypt_premaster_secret(binary(), #'RSAPrivateKey'{}) -> binary().
@@ -521,33 +534,45 @@ decrypt_premaster_secret(Secret, RSAPrivateKey) ->
[{rsa_pad, rsa_pkcs1_padding}])
catch
_:_ ->
+ io:format("decrypt_premaster_secret error"),
throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
end.
%%--------------------------------------------------------------------
--spec server_key_exchange_hash(rsa | dhe_rsa| dhe_dss | dh_anon, binary()) -> binary().
-
+-spec server_key_exchange_hash(md5sha | md5 | sha | sha224 |sha256 | sha384 | sha512, binary()) -> binary().
%%
%% Description: Calculate server key exchange hash
%%--------------------------------------------------------------------
-server_key_exchange_hash(Algorithm, Value) when Algorithm == rsa;
- Algorithm == dhe_rsa ->
+server_key_exchange_hash(md5sha, Value) ->
MD5 = crypto:md5(Value),
- SHA = crypto:sha(Value),
+ SHA = crypto:sha(Value),
<<MD5/binary, SHA/binary>>;
-server_key_exchange_hash(dhe_dss, Value) ->
- crypto:sha(Value).
+server_key_exchange_hash(Hash, Value) ->
+ crypto:hash(Hash, Value).
+
+%%--------------------------------------------------------------------
+-spec prf(tls_version(), binary(), binary(), [binary()], non_neg_integer()) ->
+ {ok, binary()} | {error, undefined}.
+%%
+%% Description: use the TLS PRF to generate key material
+%%--------------------------------------------------------------------
+prf({3,0}, _, _, _, _) ->
+ {error, undefined};
+prf({3,1}, Secret, Label, Seed, WantedLength) ->
+ {ok, ssl_tls1:prf(?MD5SHA, Secret, Label, Seed, WantedLength)};
+prf({3,_N}, Secret, Label, Seed, WantedLength) ->
+ {ok, ssl_tls1:prf(?SHA256, Secret, Label, Seed, WantedLength)}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length),
+get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
Body:Length/binary,Rest/binary>>, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
- H = dec_hs(Type, Body),
- get_tls_handshake_aux(Rest, [{H,Raw} | Acc]);
-get_tls_handshake_aux(Data, Acc) ->
+ H = dec_hs(Version, Type, Body),
+ get_tls_handshake_aux(Version, Rest, [{H,Raw} | Acc]);
+get_tls_handshake_aux(_Version, Data, Acc) ->
{lists:reverse(Acc), Data}.
path_validation_alert({bad_cert, cert_expired}) ->
@@ -569,24 +594,23 @@ path_validation_alert({bad_cert, unknown_ca}) ->
path_validation_alert(_) ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE).
-select_session(Hello, Port, Session, Version,
+select_session(Hello, Port, Session, Version,
#ssl_options{ciphers = UserSuites} = SslOpts, Cache, CacheCb, Cert) ->
SuggestedSessionId = Hello#client_hello.session_id,
- SessionId = ssl_manager:server_session_id(Port, SuggestedSessionId,
- SslOpts, Cert),
-
- Suites = available_suites(Cert, UserSuites, Version),
- case ssl_session:is_new(SuggestedSessionId, SessionId) of
- true ->
- CipherSuite =
- select_cipher_suite(Hello#client_hello.cipher_suites, Suites),
+ {SessionId, Resumed} = ssl_session:server_id(Port, SuggestedSessionId,
+ SslOpts, Cert,
+ Cache, CacheCb),
+ Suites = available_suites(Cert, UserSuites, Version),
+ case Resumed of
+ undefined ->
+ CipherSuite = select_cipher_suite(Hello#client_hello.cipher_suites, Suites),
Compressions = Hello#client_hello.compression_methods,
Compression = select_compression(Compressions),
{new, Session#session{session_id = SessionId,
cipher_suite = CipherSuite,
compression_method = Compression}};
- false ->
- {resumed, CacheCb:lookup(Cache, {Port, SessionId})}
+ _ ->
+ {resumed, Resumed}
end.
available_suites(UserSuites, Version) ->
@@ -705,7 +729,7 @@ handle_renegotiation_info(ConnectionStates, SecureRenegotation) ->
%% hello messages
%% NOTE : Role is the role of the receiver of the hello message
%% currently being processed.
-hello_pending_connection_states(Role, CipherSuite, Random, Compression,
+hello_pending_connection_states(Role, Version, CipherSuite, Random, Compression,
ConnectionStates) ->
ReadState =
ssl_record:pending_connection_state(ConnectionStates, read),
@@ -713,30 +737,30 @@ hello_pending_connection_states(Role, CipherSuite, Random, Compression,
ssl_record:pending_connection_state(ConnectionStates, write),
NewReadSecParams =
- hello_security_parameters(Role, ReadState, CipherSuite,
+ hello_security_parameters(Role, Version, ReadState, CipherSuite,
Random, Compression),
NewWriteSecParams =
- hello_security_parameters(Role, WriteState, CipherSuite,
+ hello_security_parameters(Role, Version, WriteState, CipherSuite,
Random, Compression),
ssl_record:update_security_params(NewReadSecParams,
NewWriteSecParams,
ConnectionStates).
-hello_security_parameters(client, ConnectionState, CipherSuite, Random,
+hello_security_parameters(client, Version, ConnectionState, CipherSuite, Random,
Compression) ->
SecParams = ConnectionState#connection_state.security_parameters,
- NewSecParams = ssl_cipher:security_parameters(CipherSuite, SecParams),
+ NewSecParams = ssl_cipher:security_parameters(Version, CipherSuite, SecParams),
NewSecParams#security_parameters{
server_random = Random,
compression_algorithm = Compression
};
-hello_security_parameters(server, ConnectionState, CipherSuite, Random,
+hello_security_parameters(server, Version, ConnectionState, CipherSuite, Random,
Compression) ->
SecParams = ConnectionState#connection_state.security_parameters,
- NewSecParams = ssl_cipher:security_parameters(CipherSuite, SecParams),
+ NewSecParams = ssl_cipher:security_parameters(Version, CipherSuite, SecParams),
NewSecParams#security_parameters{
client_random = Random,
compression_algorithm = Compression
@@ -770,13 +794,14 @@ master_secret(Version, MasterSecret, #security_parameters{
client_random = ClientRandom,
server_random = ServerRandom,
hash_size = HashSize,
+ prf_algorithm = PrfAlgo,
key_material_length = KML,
expanded_key_material_length = EKML,
iv_size = IVS},
ConnectionStates, Role) ->
{ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
ServerWriteKey, ClientIV, ServerIV} =
- setup_keys(Version, MasterSecret, ServerRandom,
+ setup_keys(Version, PrfAlgo, MasterSecret, ServerRandom,
ClientRandom, HashSize, KML, EKML, IVS),
ConnStates1 = ssl_record:set_master_secret(MasterSecret, ConnectionStates),
@@ -791,13 +816,13 @@ master_secret(Version, MasterSecret, #security_parameters{
ServerCipherState, Role)}.
-dec_hs(?HELLO_REQUEST, <<>>) ->
+dec_hs(_Version, ?HELLO_REQUEST, <<>>) ->
#hello_request{};
%% Client hello v2.
%% 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.
-dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor),
+dec_hs(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor),
?UINT16(CSLength), ?UINT16(0),
?UINT16(CDLength),
CipherSuites:CSLength/binary,
@@ -809,24 +834,27 @@ dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor),
compression_methods = [?NULL],
renegotiation_info = undefined
};
-dec_hs(?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
+dec_hs(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
?UINT16(Cs_length), CipherSuites:Cs_length/binary,
?BYTE(Cm_length), Comp_methods:Cm_length/binary,
Extensions/binary>>) ->
-
- RenegotiationInfo = proplists:get_value(renegotiation_info, dec_hello_extensions(Extensions),
- undefined),
+ HelloExtensions = dec_hello_extensions(Extensions),
+ RenegotiationInfo = proplists:get_value(renegotiation_info, HelloExtensions,
+ undefined),
+ HashSigns = proplists:get_value(hash_signs, HelloExtensions,
+ undefined),
#client_hello{
client_version = {Major,Minor},
random = Random,
session_id = Session_ID,
cipher_suites = from_2bytes(CipherSuites),
compression_methods = Comp_methods,
- renegotiation_info = RenegotiationInfo
+ renegotiation_info = RenegotiationInfo,
+ hash_signs = HashSigns
};
-dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
+dec_hs(_Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
Cipher_suite:2/binary, ?BYTE(Comp_method)>>) ->
#server_hello{
@@ -835,53 +863,81 @@ dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
session_id = Session_ID,
cipher_suite = Cipher_suite,
compression_method = Comp_method,
- renegotiation_info = undefined};
+ renegotiation_info = undefined,
+ hash_signs = undefined};
-dec_hs(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
+dec_hs(_Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
Cipher_suite:2/binary, ?BYTE(Comp_method),
?UINT16(ExtLen), Extensions:ExtLen/binary>>) ->
- RenegotiationInfo = proplists:get_value(renegotiation_info, dec_hello_extensions(Extensions, []),
- undefined),
+ HelloExtensions = dec_hello_extensions(Extensions, []),
+ RenegotiationInfo = proplists:get_value(renegotiation_info, HelloExtensions,
+ undefined),
+ HashSigns = proplists:get_value(hash_signs, HelloExtensions,
+ undefined),
#server_hello{
server_version = {Major,Minor},
random = Random,
session_id = Session_ID,
cipher_suite = Cipher_suite,
compression_method = Comp_method,
- renegotiation_info = RenegotiationInfo};
-dec_hs(?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) ->
+ renegotiation_info = RenegotiationInfo,
+ hash_signs = HashSigns};
+dec_hs(_Version, ?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) ->
#certificate{asn1_certificates = certs_to_list(ASN1Certs)};
-dec_hs(?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
+dec_hs(_Version, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
?UINT16(GLen), G:GLen/binary,
?UINT16(YLen), Y:YLen/binary,
?UINT16(0)>>) -> %% May happen if key_algorithm is dh_anon
#server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
dh_y = Y},
- signed_params = <<>>};
-dec_hs(?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
+ signed_params = <<>>, hashsign = {null, anon}};
+dec_hs({Major, Minor}, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?UINT16(YLen), Y:YLen/binary,
+ ?BYTE(HashAlgo), ?BYTE(SignAlgo),
+ ?UINT16(Len), Sig:Len/binary>>)
+ when Major == 3, Minor >= 3 ->
+ #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
+ dh_y = Y},
+ signed_params = Sig,
+ hashsign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}};
+dec_hs(_Version, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary,
?UINT16(GLen), G:GLen/binary,
?UINT16(YLen), Y:YLen/binary,
?UINT16(Len), Sig:Len/binary>>) ->
#server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G,
dh_y = Y},
- signed_params = Sig};
-dec_hs(?CERTIFICATE_REQUEST,
+ signed_params = Sig, hashsign = undefined};
+dec_hs({Major, Minor}, ?CERTIFICATE_REQUEST,
+ <<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
+ ?UINT16(HashSignsLen), HashSigns:HashSignsLen/binary,
+ ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>)
+ when Major == 3, Minor >= 3 ->
+ HashSignAlgos = [{ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)} ||
+ <<?BYTE(Hash), ?BYTE(Sign)>> <= HashSigns],
+ #certificate_request{certificate_types = CertTypes,
+ hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
+ certificate_authorities = CertAuths};
+dec_hs(_Version, ?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>) ->
#certificate_request{certificate_types = CertTypes,
certificate_authorities = CertAuths};
-dec_hs(?SERVER_HELLO_DONE, <<>>) ->
+dec_hs(_Version, ?SERVER_HELLO_DONE, <<>>) ->
#server_hello_done{};
-dec_hs(?CERTIFICATE_VERIFY,<<?UINT16(_), Signature/binary>>)->
+dec_hs({Major, Minor}, ?CERTIFICATE_VERIFY,<<HashSign:2/binary, ?UINT16(SignLen), Signature:SignLen/binary>>)
+ when Major == 3, Minor >= 3 ->
+ #certificate_verify{hashsign_algorithm = hashsign_dec(HashSign), signature = Signature};
+dec_hs(_Version, ?CERTIFICATE_VERIFY,<<?UINT16(SignLen), Signature:SignLen/binary>>)->
#certificate_verify{signature = Signature};
-dec_hs(?CLIENT_KEY_EXCHANGE, PKEPMS) ->
+dec_hs(_Version, ?CLIENT_KEY_EXCHANGE, PKEPMS) ->
#client_key_exchange{exchange_keys = PKEPMS};
-dec_hs(?FINISHED, VerifyData) ->
+dec_hs(_Version, ?FINISHED, VerifyData) ->
#finished{verify_data = VerifyData};
-dec_hs(_, _) ->
+dec_hs(_, _, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)).
dec_client_key(PKEPMS, ?KEY_EXCHANGE_RSA, {3, 0}) ->
@@ -915,6 +971,15 @@ dec_hello_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binar
dec_hello_extensions(Rest, [{renegotiation_info,
#renegotiation_info{renegotiated_connection = RenegotiateInfo}} | Acc]);
+dec_hello_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>, Acc) ->
+ SignAlgoListLen = Len - 2,
+ <<?UINT16(SignAlgoListLen), SignAlgoList/binary>> = ExtData,
+ HashSignAlgos = [{ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)} ||
+ <<?BYTE(Hash), ?BYTE(Sign)>> <= SignAlgoList],
+ dec_hello_extensions(Rest, [{hash_signs,
+ #hash_sign_algos{hash_sign_algos = HashSignAlgos}} | Acc]);
+
%% Ignore data following the ClientHello (i.e.,
%% extensions) if not understood.
dec_hello_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Acc) ->
@@ -956,14 +1021,19 @@ enc_hs(#client_hello{client_version = {Major, Minor},
session_id = SessionID,
cipher_suites = CipherSuites,
compression_methods = CompMethods,
- renegotiation_info = RenegotiationInfo}, _Version) ->
+ renegotiation_info = RenegotiationInfo,
+ hash_signs = HashSigns}, _Version) ->
SIDLength = byte_size(SessionID),
BinCompMethods = list_to_binary(CompMethods),
CmLength = byte_size(BinCompMethods),
BinCipherSuites = list_to_binary(CipherSuites),
CsLength = byte_size(BinCipherSuites),
- Extensions = hello_extensions(RenegotiationInfo),
- ExtensionsBin = enc_hello_extensions(Extensions),
+ Extensions0 = hello_extensions(RenegotiationInfo),
+ Extensions1 = if
+ Major == 3, Minor >=3 -> Extensions0 ++ hello_extensions(HashSigns);
+ true -> Extensions0
+ end,
+ ExtensionsBin = enc_hello_extensions(Extensions1),
{?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SIDLength), SessionID/binary,
?UINT16(CsLength), BinCipherSuites/binary,
@@ -987,15 +1057,30 @@ enc_hs(#certificate{asn1_certificates = ASN1CertList}, _Version) ->
{?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>};
enc_hs(#server_key_exchange{params = #server_dh_params{
dh_p = P, dh_g = G, dh_y = Y},
- signed_params = SignedParams}, _Version) ->
+ signed_params = SignedParams, hashsign = HashSign}, Version) ->
PLen = byte_size(P),
GLen = byte_size(G),
YLen = byte_size(Y),
- SignedLen = byte_size(SignedParams),
+ Signature = enc_sign(HashSign, SignedParams, Version),
{?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P/binary,
?UINT16(GLen), G/binary,
?UINT16(YLen), Y/binary,
- ?UINT16(SignedLen), SignedParams/binary>>
+ Signature/binary>>
+ };
+enc_hs(#certificate_request{certificate_types = CertTypes,
+ hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
+ certificate_authorities = CertAuths},
+ {Major, Minor})
+ when Major == 3, Minor >= 3 ->
+ HashSigns= << <<(ssl_cipher:hash_algorithm(Hash)):8, (ssl_cipher:sign_algorithm(Sign)):8>> ||
+ {Hash, Sign} <- HashSignAlgos >>,
+ CertTypesLen = byte_size(CertTypes),
+ HashSignsLen = byte_size(HashSigns),
+ CertAuthsLen = byte_size(CertAuths),
+ {?CERTIFICATE_REQUEST,
+ <<?BYTE(CertTypesLen), CertTypes/binary,
+ ?UINT16(HashSignsLen), HashSigns/binary,
+ ?UINT16(CertAuthsLen), CertAuths/binary>>
};
enc_hs(#certificate_request{certificate_types = CertTypes,
certificate_authorities = CertAuths},
@@ -1010,8 +1095,8 @@ enc_hs(#server_hello_done{}, _Version) ->
{?SERVER_HELLO_DONE, <<>>};
enc_hs(#client_key_exchange{exchange_keys = ExchangeKeys}, Version) ->
{?CLIENT_KEY_EXCHANGE, enc_cke(ExchangeKeys, Version)};
-enc_hs(#certificate_verify{signature = BinSig}, _) ->
- EncSig = enc_bin_sig(BinSig),
+enc_hs(#certificate_verify{signature = BinSig, hashsign_algorithm = HashSign}, Version) ->
+ EncSig = enc_sign(HashSign, BinSig, Version),
{?CERTIFICATE_VERIFY, EncSig};
enc_hs(#finished{verify_data = VerifyData}, _Version) ->
{?FINISHED, VerifyData}.
@@ -1025,14 +1110,23 @@ enc_cke(#client_diffie_hellman_public{dh_public = DHPublic}, _) ->
Len = byte_size(DHPublic),
<<?UINT16(Len), DHPublic/binary>>.
-enc_bin_sig(BinSig) ->
- Size = byte_size(BinSig),
- <<?UINT16(Size), BinSig/binary>>.
+enc_sign({HashAlg, SignAlg}, Signature, _Version = {Major, Minor})
+ when Major == 3, Minor >= 3->
+ SignLen = byte_size(Signature),
+ HashSign = hashsign_enc(HashAlg, SignAlg),
+ <<HashSign/binary, ?UINT16(SignLen), Signature/binary>>;
+enc_sign(_HashSign, Sign, _Version) ->
+ SignLen = byte_size(Sign),
+ <<?UINT16(SignLen), Sign/binary>>.
-%% Renegotiation info, only current extension
+hello_extensions(undefined) ->
+ [];
+%% Renegotiation info
hello_extensions(#renegotiation_info{renegotiated_connection = undefined}) ->
[];
hello_extensions(#renegotiation_info{} = Info) ->
+ [Info];
+hello_extensions(#hash_sign_algos{} = Info) ->
[Info].
enc_hello_extensions(Extensions) ->
@@ -1050,7 +1144,14 @@ enc_hello_extensions([#renegotiation_info{renegotiated_connection = ?byte(0) = I
enc_hello_extensions([#renegotiation_info{renegotiated_connection = Info} | Rest], Acc) ->
InfoLen = byte_size(Info),
Len = InfoLen +1,
- enc_hello_extensions(Rest, <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), ?BYTE(InfoLen), Info/binary, Acc/binary>>).
+ enc_hello_extensions(Rest, <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), ?BYTE(InfoLen), Info/binary, Acc/binary>>);
+
+enc_hello_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Rest], Acc) ->
+ SignAlgoList = << <<(ssl_cipher:hash_algorithm(Hash)):8, (ssl_cipher:sign_algorithm(Sign)):8>> ||
+ {Hash, Sign} <- HashSignAlgos >>,
+ ListLen = byte_size(SignAlgoList),
+ Len = ListLen + 2,
+ enc_hello_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len), ?UINT16(ListLen), SignAlgoList/binary, Acc/binary>>).
from_3bytes(Bin3) ->
@@ -1078,6 +1179,14 @@ certificate_types({KeyExchange, _, _, _})
certificate_types(_) ->
<<?BYTE(?RSA_SIGN)>>.
+hashsign_dec(<<?BYTE(HashAlgo), ?BYTE(SignAlgo)>>) ->
+ {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}.
+
+hashsign_enc(HashAlgo, SignAlgo) ->
+ Hash = ssl_cipher:hash_algorithm(HashAlgo),
+ Sign = ssl_cipher:sign_algorithm(SignAlgo),
+ <<?BYTE(Hash), ?BYTE(Sign)>>.
+
certificate_authorities(CertDbHandle, CertDbRef) ->
Authorities = certificate_authorities_from_db(CertDbHandle, CertDbRef),
Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
@@ -1092,53 +1201,47 @@ certificate_authorities(CertDbHandle, CertDbRef) ->
list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]).
certificate_authorities_from_db(CertDbHandle, CertDbRef) ->
- certificate_authorities_from_db(CertDbHandle, CertDbRef, no_candidate, []).
-
-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(CertDbHandle, CertDbRef, Key, [Cert|Acc]);
- {Key, _Cert} ->
- %% skip certs not from this ssl connection
- certificate_authorities_from_db(CertDbHandle, CertDbRef, Key, Acc)
- end.
-
-digitally_signed(Hash, #'RSAPrivateKey'{} = Key) ->
+ ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef ->
+ [Cert | Acc];
+ (_, Acc) ->
+ Acc
+ end,
+ ssl_certificate_db:foldl(ConnectionCerts, [], CertDbHandle).
+
+
+digitally_signed({3, Minor}, Hash, HashAlgo, Key) when Minor >= 3 ->
+ public_key:sign({digest, Hash}, HashAlgo, Key);
+digitally_signed(_Version, Hash, _HashAlgo, #'DSAPrivateKey'{} = Key) ->
+ public_key:sign({digest, Hash}, sha, Key);
+digitally_signed(_Version, Hash, _HashAlgo, #'RSAPrivateKey'{} = Key) ->
public_key:encrypt_private(Hash, Key,
- [{rsa_pad, rsa_pkcs1_padding}]);
-digitally_signed(Hash, #'DSAPrivateKey'{} = Key) ->
- public_key:sign(Hash, none, Key).
-
-calc_master_secret({3,0}, PremasterSecret, ClientRandom, ServerRandom) ->
+ [{rsa_pad, rsa_pkcs1_padding}]).
+
+calc_master_secret({3,0}, _PrfAlgo, PremasterSecret, ClientRandom, ServerRandom) ->
ssl_ssl3:master_secret(PremasterSecret, ClientRandom, ServerRandom);
-calc_master_secret({3,N},PremasterSecret, ClientRandom, ServerRandom)
- when N == 1; N == 2 ->
- ssl_tls1:master_secret(PremasterSecret, ClientRandom, ServerRandom).
+calc_master_secret({3,_}, PrfAlgo, PremasterSecret, ClientRandom, ServerRandom) ->
+ ssl_tls1:master_secret(PrfAlgo, PremasterSecret, ClientRandom, ServerRandom).
-setup_keys({3,0}, MasterSecret,
+setup_keys({3,0}, _PrfAlgo, MasterSecret,
ServerRandom, ClientRandom, HashSize, KML, EKML, IVS) ->
- ssl_ssl3:setup_keys(MasterSecret, ServerRandom,
+ ssl_ssl3:setup_keys(MasterSecret, ServerRandom,
ClientRandom, HashSize, KML, EKML, IVS);
-setup_keys({3,1}, MasterSecret,
+setup_keys({3,N}, PrfAlgo, MasterSecret,
ServerRandom, ClientRandom, HashSize, KML, _EKML, IVS) ->
- ssl_tls1:setup_keys(MasterSecret, ServerRandom, ClientRandom, HashSize,
+ ssl_tls1:setup_keys(N, PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
KML, IVS).
-calc_finished({3, 0}, Role, MasterSecret, Hashes) ->
- ssl_ssl3:finished(Role, MasterSecret, Hashes);
-calc_finished({3, N}, Role, MasterSecret, Hashes)
- when N == 1; N == 2 ->
- ssl_tls1:finished(Role, MasterSecret, Hashes).
+calc_finished({3, 0}, Role, _PrfAlgo, MasterSecret, Handshake) ->
+ ssl_ssl3:finished(Role, MasterSecret, lists:reverse(Handshake));
+calc_finished({3, N}, Role, PrfAlgo, MasterSecret, Handshake) ->
+ ssl_tls1:finished(Role, N, PrfAlgo, MasterSecret, lists:reverse(Handshake)).
-calc_certificate_verify({3, 0}, MasterSecret, Algorithm, Hashes) ->
- ssl_ssl3:certificate_verify(Algorithm, MasterSecret, Hashes);
-calc_certificate_verify({3, N}, _, Algorithm, Hashes)
- when N == 1; N == 2 ->
- ssl_tls1:certificate_verify(Algorithm, Hashes).
+calc_certificate_verify({3, 0}, HashAlgo, MasterSecret, Handshake) ->
+ ssl_ssl3:certificate_verify(HashAlgo, MasterSecret, lists:reverse(Handshake));
+calc_certificate_verify({3, N}, HashAlgo, _MasterSecret, Handshake) ->
+ ssl_tls1:certificate_verify(HashAlgo, N, lists:reverse(Handshake)).
key_exchange_alg(rsa) ->
?KEY_EXCHANGE_RSA;
@@ -1158,7 +1261,29 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState) ->
{unknown, {SslState, UserState}}
end.
-alg_oid(#'RSAPrivateKey'{}) ->
- ?'rsaEncryption';
-alg_oid(#'DSAPrivateKey'{}) ->
- ?'id-dsa'.
+certificate_verify_rsa(Hashes, sha, Signature, PublicKey, {Major, Minor})
+ when Major == 3, Minor >= 3 ->
+ public_key:verify({digest, Hashes}, sha, Signature, PublicKey);
+certificate_verify_rsa(Hashes, HashAlgo, Signature, PublicKey, {Major, Minor})
+ when Major == 3, Minor >= 3 ->
+ public_key:verify({digest, Hashes}, HashAlgo, Signature, PublicKey);
+certificate_verify_rsa(Hashes, _HashAlgo, Signature, PublicKey, _Version) ->
+ case public_key:decrypt_public(Signature, PublicKey,
+ [{rsa_pad, rsa_pkcs1_padding}]) of
+ Hashes -> true;
+ _ -> false
+ end.
+
+-define(TLSEXT_SIGALG_RSA(MD), {MD, rsa}).
+-define(TLSEXT_SIGALG_DSA(MD), {MD, dsa}).
+
+-define(TLSEXT_SIGALG(MD), ?TLSEXT_SIGALG_RSA(MD)).
+
+default_hash_signs() ->
+ #hash_sign_algos{hash_sign_algos =
+ [?TLSEXT_SIGALG(sha512),
+ ?TLSEXT_SIGALG(sha384),
+ ?TLSEXT_SIGALG(sha256),
+ ?TLSEXT_SIGALG(sha),
+ ?TLSEXT_SIGALG_DSA(sha),
+ ?TLSEXT_SIGALG_RSA(md5)]}.
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index fb0ebac7d1..cc17dc2975 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,6 +31,13 @@
-type algo_oid() :: ?'rsaEncryption' | ?'id-dsa'.
-type public_key_params() :: #'Dss-Parms'{} | term().
-type public_key_info() :: {algo_oid(), #'RSAPublicKey'{} | integer() , public_key_params()}.
+-type tls_handshake_history() :: {[binary()], [binary()]}.
+
+%% Signature algorithms
+-define(ANON, 0).
+-define(RSA, 1).
+-define(DSA, 2).
+-define(ECDSA, 3).
-record(session, {
session_id,
@@ -89,7 +96,8 @@
session_id, % opaque SessionID<0..32>
cipher_suites, % cipher_suites<2..2^16-1>
compression_methods, % compression_methods<1..2^8-1>,
- renegotiation_info
+ renegotiation_info,
+ hash_signs % supported combinations of hashes/signature algos
}).
-record(server_hello, {
@@ -98,7 +106,8 @@
session_id, % opaque SessionID<0..32>
cipher_suite, % cipher_suites
compression_method, % compression_method
- renegotiation_info
+ renegotiation_info,
+ hash_signs % supported combinations of hashes/signature algos
}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -129,7 +138,8 @@
-record(server_key_exchange, {
params, %% #server_rsa_params{} | #server_dh_params{}
- signed_params %% #signature{}
+ signed_params, %% #signature{}
+ hashsign %% term(atom(), atom())
}).
%% enum { anonymous, rsa, dsa } SignatureAlgorithm;
@@ -159,6 +169,7 @@
-record(certificate_request, {
certificate_types, %ClientCertificateType <1..2^8-1>
+ hashsign_algorithms, %%SignatureAndHashAlgorithm <2^16-1>;
certificate_authorities %DistinguishedName <0..2^16-1>
}).
@@ -193,6 +204,7 @@
%%% Certificate verify - RFC 4346 section 7.4.8
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-record(certificate_verify, {
+ hashsign_algorithm,
signature % binary()
}).
@@ -213,6 +225,15 @@
renegotiated_connection
}).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Signature Algorithms RFC 5746 section 7.4.1.4.1.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(SIGNATURE_ALGORITHMS_EXT, 13).
+
+-record(hash_sign_algos, {
+ hash_sign_algos
+ }).
+
-endif. % -ifdef(ssl_handshake).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 18cfcdcd68..b8f2ae3b51 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
-type host() :: inet:ip_address() | inet:hostname().
-type session_id() :: 0 | binary().
-type tls_version() :: {integer(), integer()}.
--type tls_atom_version() :: sslv3 | tlsv1.
+-type tls_atom_version() :: sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2'.
-type certdb_ref() :: reference().
-type db_handle() :: term().
-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | dh_anon.
@@ -69,11 +69,11 @@
-define(TRUE, 0).
-define(FALSE, 1).
--define(DEFAULT_SUPPORTED_VERSIONS, [tlsv1, sslv3]). % TODO: This is temporary
-%-define(DEFAULT_SUPPORTED_VERSIONS, ['tlsv1.1', tlsv1, sslv3]).
+-define(DEFAULT_SUPPORTED_VERSIONS, [tlsv1, sslv3]). %% Add 'tlsv1.1' in R16
+-define(ALL_SUPPORTED_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
-record(ssl_options, {
- versions, % 'tlsv1.1' | tlsv1 | sslv3
+ versions, % 'tlsv1.2' | 'tlsv1.1' | tlsv1 | sslv3
verify, % verify_none | verify_peer
verify_fun, % fun(CertVerifyErrors) -> boolean()
fail_if_no_peer_cert, % boolean()
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index dcf310c535..af2bfa394d 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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/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,
+ lookup_trusted_cert/4,
+ new_session_id/1, clean_cert_db/2,
register_session/2, register_session/3, invalidate_session/2,
- invalidate_session/3]).
+ invalidate_session/3, clear_pem_cache/0]).
% Spawn export
-export([init_session_validator/1]).
@@ -51,14 +51,17 @@
session_lifetime,
certificate_db,
session_validation_timer,
- last_delay_timer %% Keep for testing purposes
+ last_delay_timer = {undefined, undefined}%% Keep for testing purposes
}).
-define('24H_in_msec', 8640000).
-define('24H_in_sec', 8640).
+-define(GEN_UNIQUE_ID_MAX_TRIES, 10).
-define(SESSION_VALIDATION_INTERVAL, 60000).
--define(CERTIFICATE_CACHE_CLEANUP, 30000).
+-define(CLEAR_PEM_CACHE, 120000).
-define(CLEAN_SESSION_DB, 60000).
+-define(CLEAN_CERT_DB, 500).
+-define(NOT_TO_BIG, 10).
%%====================================================================
%% API
@@ -82,26 +85,46 @@ 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()}.
+-spec connection_init(binary()| {der, list()}, client | server) ->
+ {ok, certdb_ref(), db_handle(), db_handle(), db_handle(), db_handle()}.
%%
%% Description: Do necessary initializations for a new connection.
%%--------------------------------------------------------------------
+connection_init({der, _} = Trustedcerts, Role) ->
+ call({connection_init, Trustedcerts, Role});
+
+connection_init(<<>> = Trustedcerts, Role) ->
+ call({connection_init, Trustedcerts, Role});
+
connection_init(Trustedcerts, Role) ->
call({connection_init, Trustedcerts, Role}).
+
%%--------------------------------------------------------------------
--spec cache_pem_file(string(), term()) -> {ok, term()} | {error, reason()}.
+-spec cache_pem_file(binary(), term()) -> {ok, term()} | {error, reason()}.
%%
%% Description: Cach a pem file and return its content.
%%--------------------------------------------------------------------
cache_pem_file(File, DbHandle) ->
- try file:read_file_info(File) of
- {ok, #file_info{mtime = LastWrite}} ->
- cache_pem_file(File, LastWrite, DbHandle)
- catch
- _:Reason ->
- {error, Reason}
+ MD5 = crypto:md5(File),
+ case ssl_certificate_db:lookup_cached_pem(DbHandle, MD5) of
+ [{Content,_}] ->
+ {ok, Content};
+ [Content] ->
+ {ok, Content};
+ undefined ->
+ call({cache_pem, {MD5, File}})
end.
+
+%%--------------------------------------------------------------------
+-spec clear_pem_cache() -> ok.
+%%
+%% Description: Clear the PEM cache
+%%--------------------------------------------------------------------
+clear_pem_cache() ->
+ %% Not supported for distribution at the moement, should it be?
+ put(ssl_manager, ssl_manager),
+ call(unconditionally_clear_pem_cache).
+
%%--------------------------------------------------------------------
-spec lookup_trusted_cert(term(), reference(), serialnumber(), issuer()) ->
undefined |
@@ -112,33 +135,17 @@ cache_pem_file(File, DbHandle) ->
%% --------------------------------------------------------------------
lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
ssl_certificate_db:lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer).
-%%--------------------------------------------------------------------
--spec issuer_candidate(cert_key() | no_candidate, term()) ->
- {cert_key(),
- {der_cert(),
- #'OTPCertificate'{}}} | no_more_candidates.
-%%
-%% Description: Return next issuer candidate.
-%%--------------------------------------------------------------------
-issuer_candidate(PrevCandidateKey, DbHandle) ->
- ssl_certificate_db:issuer_candidate(PrevCandidateKey, DbHandle).
-%%--------------------------------------------------------------------
--spec client_session_id(host(), inet:port_number(), #ssl_options{},
- der_cert() | undefined) -> session_id().
-%%
-%% Description: Select a session id for the client.
-%%--------------------------------------------------------------------
-client_session_id(Host, Port, SslOpts, OwnCert) ->
- call({client_session_id, Host, Port, SslOpts, OwnCert}).
%%--------------------------------------------------------------------
--spec server_session_id(host(), inet:port_number(), #ssl_options{},
- der_cert()) -> session_id().
+-spec new_session_id(integer()) -> session_id().
%%
-%% Description: Select a session id for the server.
+%% Description: Creates a session id for the server.
%%--------------------------------------------------------------------
-server_session_id(Port, SuggestedSessionId, SslOpts, OwnCert) ->
- call({server_session_id, Port, SuggestedSessionId, SslOpts, OwnCert}).
+new_session_id(Port) ->
+ call({new_session_id, Port}).
+
+clean_cert_db(Ref, File) ->
+ erlang:send_after(?CLEAN_CERT_DB, self(), {clean_cert_db, Ref, File}).
%%--------------------------------------------------------------------
-spec register_session(inet:port_number(), #session{}) -> ok.
@@ -186,6 +193,7 @@ init([Name, Opts]) ->
SessionCache = CacheCb:init(proplists:get_value(session_cb_init_args, Opts, [])),
Timer = erlang:send_after(SessionLifeTime * 1000,
self(), validate_sessions),
+ erlang:send_after(?CLEAR_PEM_CACHE, self(), clear_pem_cache),
{ok, #state{certificate_db = CertDb,
session_cache = SessionCache,
session_cache_cb = CacheCb,
@@ -203,55 +211,44 @@ init([Name, Opts]) ->
%%
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call({{connection_init, "", _Role}, Pid}, _From,
- #state{certificate_db = [CertDb |_],
+handle_call({{connection_init, <<>>, _Role}, _Pid}, _From,
+ #state{certificate_db = [CertDb, FileRefDb, PemChace],
session_cache = Cache} = State) ->
- erlang:monitor(process, Pid),
- Result = {ok, make_ref(),CertDb, Cache},
+ Result = {ok, make_ref(),CertDb, FileRefDb, PemChace, Cache},
{reply, Result, State};
handle_call({{connection_init, Trustedcerts, _Role}, Pid}, _From,
- #state{certificate_db = [CertDb|_] =Db,
+ #state{certificate_db = [CertDb, FileRefDb, PemChace] = Db,
session_cache = Cache} = State) ->
- erlang:monitor(process, Pid),
Result =
try
{ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, Trustedcerts, Db),
- {ok, Ref, CertDb, Cache}
+ {ok, Ref, CertDb, FileRefDb, PemChace, Cache}
catch
_:Reason ->
{error, Reason}
end,
{reply, Result, State};
-handle_call({{client_session_id, Host, Port, SslOpts, OwnCert}, _}, _,
- #state{session_cache = Cache,
- session_cache_cb = CacheCb} = State) ->
- Id = ssl_session:id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
- {reply, Id, State};
-
-handle_call({{server_session_id, Port, SuggestedSessionId, SslOpts, OwnCert}, _},
+handle_call({{new_session_id,Port}, _},
_, #state{session_cache_cb = CacheCb,
- session_cache = Cache,
- session_lifetime = LifeTime} = State) ->
- Id = ssl_session:id(Port, SuggestedSessionId, SslOpts,
- Cache, CacheCb, LifeTime, OwnCert),
+ session_cache = Cache} = State) ->
+ Id = new_id(Port, ?GEN_UNIQUE_ID_MAX_TRIES, Cache, CacheCb),
{reply, Id, State};
-handle_call({{cache_pem, File, LastWrite}, Pid}, _,
+
+handle_call({{cache_pem, File}, _Pid}, _,
#state{certificate_db = Db} = State) ->
- try ssl_certificate_db:cache_pem_file(Pid, File, LastWrite, Db) of
+ try ssl_certificate_db:cache_pem_file(File, Db) of
Result ->
{reply, Result, State}
catch
_:Reason ->
{reply, {error, Reason}, State}
end;
-handle_call({{recache_pem, File, LastWrite}, Pid}, From,
- #state{certificate_db = Db} = State) ->
- ssl_certificate_db:uncache_pem_file(File, Db),
- cast({recache_pem, File, LastWrite, Pid, From}),
- {noreply, State}.
+handle_call({unconditionally_clear_pem_cache, _},_, #state{certificate_db = [_,_,PemChace]} = State) ->
+ ssl_certificate_db:clear(PemChace),
+ {reply, ok, State}.
%%--------------------------------------------------------------------
-spec handle_cast(msg(), #state{}) -> {noreply, #state{}}.
@@ -278,40 +275,16 @@ handle_cast({register_session, Port, Session},
CacheCb:update(Cache, {Port, NewSession#session.session_id}, NewSession),
{noreply, State};
-%%% 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: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}};
+ invalidate_session(Cache, CacheCb, {{Host, Port}, ID}, Session, State);
handle_cast({invalidate_session, Port, #session{session_id = ID} = Session},
#state{session_cache = Cache,
session_cache_cb = CacheCb} = 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),
- gen_server:reply(From, Msg),
- {noreply, State};
- _ -> %% Send message to self letting cleanup messages be handled
- %% first so that no reference to the old version of file
- %% exists when we cache the new one.
- cast({recache_pem, File, LastWrite, Pid, From}),
- {noreply, State0}
- end.
+ invalidate_session(Cache, CacheCb, {Port, ID}, Session, State).
%%--------------------------------------------------------------------
-spec handle_info(msg(), #state{}) -> {noreply, #state{}}.
@@ -320,7 +293,7 @@ handle_cast({recache_pem, File, LastWrite, Pid, From},
%% {stop, reason(), #state{}}.
%%
%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
+%%-------------------------------------------------------------------
handle_info(validate_sessions, #state{session_cache_cb = CacheCb,
session_cache = Cache,
session_lifetime = LifeTime
@@ -336,23 +309,38 @@ handle_info({delayed_clean_session, Key}, #state{session_cache = Cache,
CacheCb:delete(Cache, Key),
{noreply, State};
-handle_info({'EXIT', _, _}, State) ->
- %% Session validator died!! Do we need to take any action?
- %% maybe error log
+handle_info(clear_pem_cache, #state{certificate_db = [_,_,PemChace]} = State) ->
+ case ssl_certificate_db:db_size(PemChace) of
+ N when N < ?NOT_TO_BIG ->
+ ok;
+ _ ->
+ ssl_certificate_db:clear(PemChace)
+ end,
+ erlang:send_after(?CLEAR_PEM_CACHE, self(), clear_pem_cache),
{noreply, State};
-handle_info({'DOWN', _Ref, _Type, _Pid, ecacertfile}, State) ->
- {noreply, State};
-handle_info({'DOWN', _Ref, _Type, Pid, shutdown}, State) ->
- handle_info({remove_trusted_certs, Pid}, State);
-handle_info({'DOWN', _Ref, _Type, Pid, _Reason}, State) ->
- erlang:send_after(?CERTIFICATE_CACHE_CLEANUP, self(),
- {remove_trusted_certs, Pid}),
+handle_info({clean_cert_db, Ref, File},
+ #state{certificate_db = [CertDb,RefDb, PemCache]} = State) ->
+ case ssl_certificate_db:ref_count(Ref, RefDb, 0) of
+ 0 ->
+ MD5 = crypto:md5(File),
+ case ssl_certificate_db:lookup_cached_pem(PemCache, MD5) of
+ [{Content, Ref}] ->
+ ssl_certificate_db:insert(MD5, Content, PemCache);
+ undefined ->
+ ok
+ end,
+ ssl_certificate_db:remove(Ref, RefDb),
+ ssl_certificate_db:remove_trusted_certs(Ref, CertDb);
+ _ ->
+ ok
+ end,
{noreply, State};
-handle_info({remove_trusted_certs, Pid},
- #state{certificate_db = Db} = State) ->
- ssl_certificate_db:remove_trusted_certs(Pid, Db),
+
+handle_info({'EXIT', _, _}, State) ->
+ %% Session validator died!! Do we need to take any action?
+ %% maybe error log
{noreply, State};
handle_info(_Info, State) ->
@@ -424,19 +412,6 @@ session_validation({{Port, _}, Session}, LifeTime) ->
validate_session(Port, Session, LifeTime),
LifeTime.
-cache_pem_file(File, LastWrite, DbHandle) ->
- case ssl_certificate_db:lookup_cached_certs(DbHandle,File) of
- [{_, {Mtime, Content}}] ->
- case LastWrite of
- Mtime ->
- {ok, Content};
- _ ->
- call({recache_pem, File, LastWrite})
- end;
- [] ->
- call({cache_pem, File, LastWrite})
- end.
-
delay_time() ->
case application:get_env(ssl, session_delay_cleanup_time) of
{ok, Time} when is_integer(Time) ->
@@ -444,3 +419,50 @@ delay_time() ->
_ ->
?CLEAN_SESSION_DB
end.
+
+invalidate_session(Cache, CacheCb, Key, Session, #state{last_delay_timer = LastTimer} = State) ->
+ case CacheCb:lookup(Cache, Key) of
+ undefined -> %% Session is already invalidated
+ {noreply, State};
+ #session{is_resumable = new} ->
+ CacheCb:delete(Cache, Key),
+ {noreply, State};
+ _ ->
+ %% When a registered 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.
+ CacheCb:update(Cache, Key, Session#session{is_resumable = false}),
+ TRef =
+ erlang:send_after(delay_time(), self(), {delayed_clean_session, Key}),
+ {noreply, State#state{last_delay_timer = last_delay_timer(Key, TRef, LastTimer)}}
+ end.
+
+last_delay_timer({{_,_},_}, TRef, {LastServer, _}) ->
+ {LastServer, TRef};
+last_delay_timer({_,_}, TRef, {_, LastClient}) ->
+ {TRef, LastClient}.
+
+%% If we can not generate a not allready in use session ID in
+%% ?GEN_UNIQUE_ID_MAX_TRIES we make the new session uncacheable The
+%% value of ?GEN_UNIQUE_ID_MAX_TRIES is stolen from open SSL which
+%% states : "If we can not find a session id in
+%% ?GEN_UNIQUE_ID_MAX_TRIES either the RAND code is broken or someone
+%% is trying to open roughly very close to 2^128 (or 2^256) SSL
+%% sessions to our server"
+new_id(_, 0, _, _) ->
+ <<>>;
+new_id(Port, Tries, Cache, CacheCb) ->
+ Id = crypto:rand_bytes(?NUM_OF_SESSION_ID_BYTES),
+ case CacheCb:lookup(Cache, {Port, Id}) of
+ undefined ->
+ Now = calendar:datetime_to_gregorian_seconds({date(), time()}),
+ %% New sessions can not be set to resumable
+ %% until handshake is compleate and the
+ %% other session values are set.
+ CacheCb:update(Cache, {Port, Id}, #session{session_id = Id,
+ is_resumable = false,
+ time_stamp = Now}),
+ Id;
+ _ ->
+ new_id(Port, Tries - 1, Cache, CacheCb)
+ end.
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 72091fdd5f..8e93ce4634 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
%% Encoding records
-export([encode_handshake/3, encode_alert_record/3,
- encode_change_cipher_spec/2, encode_data/4]).
+ encode_change_cipher_spec/2, encode_data/3]).
%% Decoding
-export([decode_cipher_text/2]).
@@ -383,6 +383,8 @@ get_tls_records_aux(Data, Acc) ->
%% Description: Creates a protocol version record from a version atom
%% or vice versa.
%%--------------------------------------------------------------------
+protocol_version('tlsv1.2') ->
+ {3, 3};
protocol_version('tlsv1.1') ->
{3, 2};
protocol_version(tlsv1) ->
@@ -391,6 +393,8 @@ protocol_version(sslv3) ->
{3, 0};
protocol_version(sslv2) -> %% Backwards compatibility
{2, 0};
+protocol_version({3, 3}) ->
+ 'tlsv1.2';
protocol_version({3, 2}) ->
'tlsv1.1';
protocol_version({3, 1}) ->
@@ -445,9 +449,9 @@ supported_protocol_versions() ->
end,
case application:get_env(ssl, protocol_version) of
undefined ->
- lists:map(Fun, ?DEFAULT_SUPPORTED_VERSIONS);
+ lists:map(Fun, supported_protocol_versions([]));
{ok, []} ->
- lists:map(Fun, ?DEFAULT_SUPPORTED_VERSIONS);
+ lists:map(Fun, supported_protocol_versions([]));
{ok, Vsns} when is_list(Vsns) ->
Versions = lists:filter(fun is_acceptable_version/1, lists:map(Fun, Vsns)),
supported_protocol_versions(Versions);
@@ -457,7 +461,16 @@ supported_protocol_versions() ->
end.
supported_protocol_versions([]) ->
- ?DEFAULT_SUPPORTED_VERSIONS;
+ Vsns = case sufficient_tlsv1_2_crypto_support() of
+ true ->
+ %%?ALL_SUPPORTED_VERSIONS; %% Add TlS-1.2 as default in R16
+ ?DEFAULT_SUPPORTED_VERSIONS;
+ false ->
+ ?DEFAULT_SUPPORTED_VERSIONS
+ end,
+ application:set_env(ssl, protocol_version, Vsns),
+ Vsns;
+
supported_protocol_versions([_|_] = Vsns) ->
Vsns.
@@ -503,36 +516,18 @@ decode_cipher_text(CipherText, ConnnectionStates0) ->
Alert
end.
%%--------------------------------------------------------------------
--spec encode_data(iolist(), tls_version(), #connection_states{}, integer()) ->
- {iolist(), iolist(), #connection_states{}}.
+-spec encode_data(binary(), tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
%%
%% Description: Encodes data to send on the ssl-socket.
%%--------------------------------------------------------------------
-encode_data(Frag, Version, ConnectionStates, RenegotiateAt)
- when byte_size(Frag) < (?MAX_PLAIN_TEXT_LENGTH - 2048) ->
- case encode_plain_text(?APPLICATION_DATA,Version,Frag,ConnectionStates, RenegotiateAt) of
- {renegotiate, Data} ->
- {[], Data, ConnectionStates};
- {Msg, CS} ->
- {Msg, [], CS}
- end;
-
-encode_data(Frag, Version, ConnectionStates, RenegotiateAt) when is_binary(Frag) ->
- Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH - 2048),
- encode_data(Data, Version, ConnectionStates, RenegotiateAt);
-
-encode_data(Data, Version, ConnectionStates0, RenegotiateAt) when is_list(Data) ->
- {ConnectionStates, EncodedMsg, NotEncdedData} =
- lists:foldl(fun(B, {CS0, Encoded, Rest}) ->
- case encode_plain_text(?APPLICATION_DATA,
- Version, B, CS0, RenegotiateAt) of
- {renegotiate, NotEnc} ->
- {CS0, Encoded, [NotEnc | Rest]};
- {Enc, CS1} ->
- {CS1, [Enc | Encoded], Rest}
- end
- end, {ConnectionStates0, [], []}, Data),
- {lists:reverse(EncodedMsg), lists:reverse(NotEncdedData), ConnectionStates}.
+encode_data(Frag, Version,
+ #connection_states{current_write = #connection_state{
+ security_parameters =
+ #security_parameters{bulk_cipher_algorithm = BCA}}} =
+ ConnectionStates) ->
+ Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH, Version, BCA),
+ encode_iolist(?APPLICATION_DATA, Data, Version, ConnectionStates).
%%--------------------------------------------------------------------
-spec encode_handshake(iolist(), tls_version(), #connection_states{}) ->
@@ -566,19 +561,27 @@ encode_change_cipher_spec(Version, ConnectionStates) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+encode_iolist(Type, Data, Version, ConnectionStates0) ->
+ {ConnectionStates, EncodedMsg} =
+ lists:foldl(fun(Text, {CS0, Encoded}) ->
+ {Enc, CS1} = encode_plain_text(Type, Version, Text, CS0),
+ {CS1, [Enc | Encoded]}
+ end, {ConnectionStates0, []}, Data),
+ {lists:reverse(EncodedMsg), ConnectionStates}.
+
highest_protocol_version() ->
highest_protocol_version(supported_protocol_versions()).
initial_connection_state(ConnectionEnd) ->
#connection_state{security_parameters =
- initial_security_params(ConnectionEnd),
+ initial_security_params(ConnectionEnd),
sequence_number = 0
}.
initial_security_params(ConnectionEnd) ->
SecParams = #security_parameters{connection_end = ConnectionEnd,
compression_algorithm = ?NULL},
- ssl_cipher:security_parameters(?TLS_NULL_WITH_NULL_NULL,
+ ssl_cipher:security_parameters(highest_protocol_version(), ?TLS_NULL_WITH_NULL_NULL,
SecParams).
empty_connection_state(ConnectionEnd) ->
@@ -602,29 +605,23 @@ record_protocol_role(client) ->
record_protocol_role(server) ->
?SERVER.
-split_bin(Bin, ChunkSize) ->
- split_bin(Bin, ChunkSize, []).
+%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are not vulnerable to this attack.
+split_bin(<<FirstByte:8, Rest/binary>>, ChunkSize, Version, BCA) when BCA =/= ?RC4 andalso ({3, 1} == Version orelse
+ {3, 0} == Version) ->
+ do_split_bin(Rest, ChunkSize, [[FirstByte]]);
+split_bin(Bin, ChunkSize, _, _) ->
+ do_split_bin(Bin, ChunkSize, []).
-split_bin(<<>>, _, Acc) ->
+do_split_bin(<<>>, _, Acc) ->
lists:reverse(Acc);
-split_bin(Bin, ChunkSize, Acc) ->
+do_split_bin(Bin, ChunkSize, Acc) ->
case Bin of
<<Chunk:ChunkSize/binary, Rest/binary>> ->
- split_bin(Rest, ChunkSize, [Chunk | Acc]);
+ do_split_bin(Rest, ChunkSize, [Chunk | Acc]);
_ ->
lists:reverse(Acc, [Bin])
end.
-encode_plain_text(Type, Version, Data, ConnectionStates, RenegotiateAt) ->
- #connection_states{current_write =
- #connection_state{sequence_number = Num}} = ConnectionStates,
- case renegotiate(Num, RenegotiateAt) of
- false ->
- encode_plain_text(Type, Version, Data, ConnectionStates);
- true ->
- {renegotiate, Data}
- end.
-
encode_plain_text(Type, Version, Data, ConnectionStates) ->
#connection_states{current_write=#connection_state{
compression_state=CompS0,
@@ -637,11 +634,6 @@ encode_plain_text(Type, Version, Data, ConnectionStates) ->
CTBin = encode_tls_cipher_text(Type, Version, CipherText),
{CTBin, ConnectionStates#connection_states{current_write = CS2}}.
-renegotiate(N, M) when N < M->
- false;
-renegotiate(_,_) ->
- true.
-
encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment) ->
Length = erlang:iolist_size(Fragment),
[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Fragment].
@@ -654,7 +646,7 @@ cipher(Type, Version, Fragment, CS0) ->
BCA}
}} =
hash_and_bump_seqno(CS0, Type, Version, Length, Fragment),
- {Ciphered, CipherS1} = ssl_cipher:cipher(BCA, CipherS0, MacHash, Fragment),
+ {Ciphered, CipherS1} = ssl_cipher:cipher(BCA, CipherS0, MacHash, Fragment, Version),
CS2 = CS1#connection_state{cipher_state=CipherS1},
{Ciphered, CS2}.
@@ -708,6 +700,17 @@ mac_hash({_,_}, ?NULL, _MacSecret, _SeqNo, _Type,
mac_hash({3, 0}, MacAlg, MacSecret, SeqNo, Type, Length, Fragment) ->
ssl_ssl3:mac_hash(MacAlg, MacSecret, SeqNo, Type, Length, Fragment);
mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment)
- when N =:= 1; N =:= 2 ->
+ when N =:= 1; N =:= 2; N =:= 3 ->
ssl_tls1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
Length, Fragment).
+
+sufficient_tlsv1_2_crypto_support() ->
+ Data = "Sampl",
+ Data2 = "e #1",
+ Key = <<0,1,2,3,16,17,18,19,32,33,34,35,48,49,50,51,4,5,6,7,20,21,22,23,36,37,38,39,
+ 52,53,54,55,8,9,10,11,24,25,26,27,40,41,42,43,56,57,58,59>>,
+ try
+ crypto:sha256_mac(Key, lists:flatten([Data, Data2])),
+ true
+ catch _:_ -> false
+ end.
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index 5fb0070b91..f73da92a52 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,6 +47,7 @@
key_material_length, % unit 8
expanded_key_material_length, % unit 8
mac_algorithm, % unit 8
+ prf_algorithm, % unit 8
hash_size, % unit 8
compression_algorithm, % unit 8
master_secret, % opaque 48
@@ -70,9 +71,10 @@
-define(MAX_SEQENCE_NUMBER, 18446744073709552000). %% math:pow(2, 64) - 1 = 1.8446744073709552e19
%% Sequence numbers can not wrap so when max is about to be reached we should renegotiate.
%% We will renegotiate a little before so that there will be sequence numbers left
-%% for the rehandshake and a little data.
--define(MARGIN, 100).
--define(DEFAULT_RENEGOTIATE_AT, ?MAX_SEQENCE_NUMBER - ?MARGIN).
+%% for the rehandshake and a little data. Currently we decided to renegotiate a little more
+%% often as we can have a cheaper test to check if it is time to renegotiate. It will still
+%% be fairly seldom.
+-define(DEFAULT_RENEGOTIATE_AT, 268435456). %% math:pow(2, 28)
%% ConnectionEnd
-define(SERVER, 0).
@@ -96,10 +98,15 @@
%-define(TRUE, 0). %% Already defined by ssl_internal.hrl
%-define(FALSE, 1). %% Already defined by ssl_internal.hrl
-%% MACAlgorithm
+%% MAC and PRF Algorithms
%-define(NULL, 0). %% Already defined by ssl_internal.hrl
-define(MD5, 1).
-define(SHA, 2).
+-define(MD5SHA, 4711). %% Not defined in protocol used to represent old prf
+-define(SHA224, 3).
+-define(SHA256, 4).
+-define(SHA384, 5).
+-define(SHA512, 6).
%% CompressionMethod
% -define(NULL, 0). %% Already defined by ssl_internal.hrl
@@ -175,7 +182,8 @@
content, % opaque content[TLSCompressed.length];
mac, % opaque MAC[CipherSpec.hash_size];
padding, % unit 8 padding[GenericBlockCipher.padding_length];
- padding_length % uint8 padding_length;
+ padding_length, % uint8 padding_length;
+ next_iv % opaque IV[SecurityParameters.record_iv_length];
}).
-endif. % -ifdef(ssl_record).
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index bf738649f6..2ad422fc03 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,9 @@
-include("ssl_internal.hrl").
%% Internal application API
--export([is_new/2, id/4, id/7, valid_session/2]).
+-export([is_new/2, client_id/4, server_id/6, valid_session/2]).
--define(GEN_UNIQUE_ID_MAX_TRIES, 10).
+-define('24H_in_sec', 8640).
-type seconds() :: integer().
@@ -48,13 +48,13 @@ is_new(_ClientSuggestion, _ServerDecision) ->
true.
%%--------------------------------------------------------------------
--spec id({host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(),
+-spec client_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
+%% Description: Should be called by the client side to get an id
%% for the client hello message.
%%--------------------------------------------------------------------
-id(ClientInfo, Cache, CacheCb, OwnCert) ->
+client_id(ClientInfo, Cache, CacheCb, OwnCert) ->
case select_session(ClientInfo, Cache, CacheCb, OwnCert) of
no_session ->
<<>>;
@@ -62,27 +62,6 @@ id(ClientInfo, Cache, CacheCb, OwnCert) ->
SessionId
end.
-%%--------------------------------------------------------------------
--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
-%% for the server hello message.
-%%--------------------------------------------------------------------
-id(Port, <<>>, _, Cache, CacheCb, _, _) ->
- new_id(Port, ?GEN_UNIQUE_ID_MAX_TRIES, Cache, CacheCb);
-
-id(Port, SuggestedSessionId, #ssl_options{reuse_sessions = ReuseEnabled,
- reuse_session = ReuseFun},
- Cache, CacheCb, SecondLifeTime, OwnCert) ->
- case is_resumable(SuggestedSessionId, Port, ReuseEnabled,
- ReuseFun, Cache, CacheCb, SecondLifeTime, OwnCert) of
- true ->
- SuggestedSessionId;
- false ->
- new_id(Port, ?GEN_UNIQUE_ID_MAX_TRIES, Cache, CacheCb)
- end.
-%%--------------------------------------------------------------------
-spec valid_session(#session{}, seconds()) -> boolean().
%%
%% Description: Check that the session has not expired
@@ -91,70 +70,72 @@ valid_session(#session{time_stamp = TimeStamp}, LifeTime) ->
Now = calendar:datetime_to_gregorian_seconds({date(), time()}),
Now - TimeStamp < LifeTime.
+server_id(Port, <<>>, _SslOpts, _Cert, _, _) ->
+ {ssl_manager:new_session_id(Port), undefined};
+server_id(Port, SuggestedId,
+ #ssl_options{reuse_sessions = ReuseEnabled,
+ reuse_session = ReuseFun},
+ Cert, Cache, CacheCb) ->
+ LifeTime = case application:get_env(ssl, session_lifetime) of
+ {ok, Time} when is_integer(Time) -> Time;
+ _ -> ?'24H_in_sec'
+ end,
+ case is_resumable(SuggestedId, Port, ReuseEnabled,ReuseFun,
+ Cache, CacheCb, LifeTime, Cert)
+ of
+ {true, Resumed} ->
+ {SuggestedId, Resumed};
+ {false, undefined} ->
+ {ssl_manager:new_session_id(Port), undefined}
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+select_session({_, _, #ssl_options{reuse_sessions=false}}, _Cache, _CacheCb, _OwnCert) ->
+ no_session;
select_session({HostIP, Port, SslOpts}, Cache, CacheCb, OwnCert) ->
Sessions = CacheCb:select_session(Cache, {HostIP, Port}),
select_session(Sessions, SslOpts, OwnCert).
select_session([], _, _) ->
no_session;
-
-select_session(Sessions, #ssl_options{ciphers = Ciphers,
- reuse_sessions = ReuseSession}, OwnCert) ->
- IsResumable =
- fun(Session) ->
- ReuseSession andalso (Session#session.is_resumable) andalso
- lists:member(Session#session.cipher_suite, Ciphers)
- andalso (OwnCert == Session#session.own_certificate)
+select_session(Sessions, #ssl_options{ciphers = Ciphers}, OwnCert) ->
+ IsNotResumable =
+ fun([_Id, Session]) ->
+ not (resumable(Session#session.is_resumable) andalso
+ lists:member(Session#session.cipher_suite, Ciphers)
+ andalso (OwnCert == Session#session.own_certificate))
end,
- case [Id || [Id, Session] <- Sessions, IsResumable(Session)] of
- [] ->
- no_session;
- List ->
- hd(List)
+ case lists:dropwhile(IsNotResumable, Sessions) of
+ [] -> no_session;
+ [[Id, _]|_] -> Id
end.
-%% If we can not generate a not allready in use session ID in
-%% ?GEN_UNIQUE_ID_MAX_TRIES we make the new session uncacheable The
-%% value of ?GEN_UNIQUE_ID_MAX_TRIES is stolen from open SSL which
-%% states : "If we can not find a session id in
-%% ?GEN_UNIQUE_ID_MAX_TRIES either the RAND code is broken or someone
-%% is trying to open roughly very close to 2^128 (or 2^256) SSL
-%% sessions to our server"
-new_id(_, 0, _, _) ->
- <<>>;
-new_id(Port, Tries, Cache, CacheCb) ->
- Id = crypto:rand_bytes(?NUM_OF_SESSION_ID_BYTES),
- case CacheCb:lookup(Cache, {Port, Id}) of
- undefined ->
- Now = calendar:datetime_to_gregorian_seconds({date(), time()}),
- %% New sessions can not be set to resumable
- %% until handshake is compleate and the
- %% other session values are set.
- CacheCb:update(Cache, {Port, Id}, #session{session_id = Id,
- is_resumable = false,
- time_stamp = Now}),
- Id;
- _ ->
- new_id(Port, Tries - 1, Cache, CacheCb)
- end.
-
-is_resumable(SuggestedSessionId, Port, ReuseEnabled, ReuseFun, Cache,
+is_resumable(_, _, false, _, _, _, _, _) ->
+ {false, undefined};
+is_resumable(SuggestedSessionId, Port, true, ReuseFun, Cache,
CacheCb, SecondLifeTime, OwnCert) ->
case CacheCb:lookup(Cache, {Port, SuggestedSessionId}) of
#session{cipher_suite = CipherSuite,
own_certificate = SessionOwnCert,
compression_method = Compression,
- is_resumable = Is_resumable,
+ is_resumable = IsResumable,
peer_certificate = PeerCert} = Session ->
- ReuseEnabled
- andalso Is_resumable
+ case resumable(IsResumable)
andalso (OwnCert == SessionOwnCert)
- andalso valid_session(Session, SecondLifeTime)
- andalso ReuseFun(SuggestedSessionId, PeerCert,
- Compression, CipherSuite);
+ andalso valid_session(Session, SecondLifeTime)
+ andalso ReuseFun(SuggestedSessionId, PeerCert,
+ Compression, CipherSuite)
+ of
+ true -> {true, Session};
+ false -> {false, undefined}
+ end;
undefined ->
- false
+ {false, undefined}
end.
+
+resumable(new) ->
+ false;
+resumable(IsResumable) ->
+ IsResumable.
diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl
index 93969f628f..5c6ee3c54c 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +28,19 @@
-export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3,
select_session/2]).
--type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
-
%%--------------------------------------------------------------------
--spec init(list()) -> db_handle(). %% Returns reference to the cache (opaque)
-%%
%% Description: Return table reference. Called by ssl_manager process.
%%--------------------------------------------------------------------
init(_) ->
- ets:new(cache_name(), [set, protected]).
+ ets:new(cache_name(), [ordered_set, protected]).
%%--------------------------------------------------------------------
--spec terminate(db_handle()) -> any().
-%%
%% Description: Handles cache table at termination of ssl manager.
%%--------------------------------------------------------------------
terminate(Cache) ->
ets:delete(Cache).
%%--------------------------------------------------------------------
--spec lookup(db_handle(), key()) -> #session{} | undefined.
-%%
%% Description: Looks up a cach entry. Should be callable from any
%% process.
%%--------------------------------------------------------------------
@@ -61,8 +53,6 @@ lookup(Cache, Key) ->
end.
%%--------------------------------------------------------------------
--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,8 +60,6 @@ update(Cache, Key, Session) ->
ets:insert(Cache, {Key, Session}).
%%--------------------------------------------------------------------
--spec delete(db_handle(), key()) -> any().
-%%
%% Description: Delets a cache entry.
%% Will only be called from the ssl_manager process.
%%--------------------------------------------------------------------
@@ -79,8 +67,6 @@ delete(Cache, Key) ->
ets:delete(Cache, Key).
%%--------------------------------------------------------------------
--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
%% accumulator which is passed to the next call. The function returns
@@ -91,8 +77,6 @@ foldl(Fun, Acc0, Cache) ->
ets:foldl(Fun, Acc0, Cache).
%%--------------------------------------------------------------------
--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_session_cache_api.erl b/lib/ssl/src/ssl_session_cache_api.erl
index f8416bf327..f2b22b0f1b 100644
--- a/lib/ssl/src/ssl_session_cache_api.erl
+++ b/lib/ssl/src/ssl_session_cache_api.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
@@ -20,18 +20,15 @@
%%
-module(ssl_session_cache_api).
+-include("ssl_handshake.hrl").
+-include("ssl_internal.hrl").
--export([behaviour_info/1]).
+-type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
-behaviour_info(callbacks) ->
- [
- {init, 1},
- {terminate, 1},
- {lookup, 2},
- {update, 3},
- {delete, 2},
- {foldl, 3},
- {select_session, 2}
- ];
-behaviour_info(_) ->
- undefined.
+-callback init(list()) -> db_handle().
+-callback terminate(db_handle()) -> any().
+-callback lookup(db_handle(), key()) -> #session{} | undefined.
+-callback update(db_handle(), key(), #session{}) -> any().
+-callback delete(db_handle(), key()) -> any().
+-callback foldl(fun(), term(), db_handle()) -> term().
+-callback select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
diff --git a/lib/ssl/src/ssl_ssl3.erl b/lib/ssl/src/ssl_ssl3.erl
index f2926b2d2f..a11c5b8c0c 100644
--- a/lib/ssl/src/ssl_ssl3.erl
+++ b/lib/ssl/src/ssl_ssl3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,9 +54,9 @@ master_secret(PremasterSecret, ClientRandom, ServerRandom) ->
Block = generate_keyblock(PremasterSecret, ClientRandom, ServerRandom, 48),
Block.
--spec finished(client | server, binary(), {binary(), binary()}) -> binary().
+-spec finished(client | server, binary(), [binary()]) -> binary().
-finished(Role, MasterSecret, {MD5Hash, SHAHash}) ->
+finished(Role, MasterSecret, Handshake) ->
%% draft-ietf-tls-ssl-version3-00 - 5.6.9 Finished
%% struct {
%% opaque md5_hash[16];
@@ -70,13 +70,13 @@ finished(Role, MasterSecret, {MD5Hash, SHAHash}) ->
%% SHA(handshake_messages + Sender +
%% master_secret + pad1));
Sender = get_sender(Role),
- MD5 = handshake_hash(?MD5, MasterSecret, Sender, MD5Hash),
- SHA = handshake_hash(?SHA, MasterSecret, Sender, SHAHash),
+ MD5 = handshake_hash(?MD5, MasterSecret, Sender, Handshake),
+ SHA = handshake_hash(?SHA, MasterSecret, Sender, Handshake),
<<MD5/binary, SHA/binary>>.
--spec certificate_verify(OID::tuple(), binary(), {binary(), binary()}) -> binary().
+-spec certificate_verify(md5sha | sha, binary(), [binary()]) -> binary().
-certificate_verify(?'rsaEncryption', MasterSecret, {MD5Hash, SHAHash}) ->
+certificate_verify(md5sha, MasterSecret, Handshake) ->
%% md5_hash
%% MD5(master_secret + pad_2 +
%% MD5(handshake_messages + master_secret + pad_1));
@@ -84,15 +84,16 @@ certificate_verify(?'rsaEncryption', MasterSecret, {MD5Hash, SHAHash}) ->
%% SHA(master_secret + pad_2 +
%% SHA(handshake_messages + master_secret + pad_1));
- MD5 = handshake_hash(?MD5, MasterSecret, undefined, MD5Hash),
- SHA = handshake_hash(?SHA, MasterSecret, undefined, SHAHash),
+ MD5 = handshake_hash(?MD5, MasterSecret, undefined, Handshake),
+ SHA = handshake_hash(?SHA, MasterSecret, undefined, Handshake),
<<MD5/binary, SHA/binary>>;
-certificate_verify(?'id-dsa', MasterSecret, {_, SHAHash}) ->
+certificate_verify(sha, MasterSecret, Handshake) ->
%% sha_hash
%% SHA(master_secret + pad_2 +
%% SHA(handshake_messages + master_secret + pad_1));
- handshake_hash(?SHA, MasterSecret, undefined, SHAHash).
+
+ handshake_hash(?SHA, MasterSecret, undefined, Handshake).
-spec mac_hash(integer(), binary(), integer(), integer(), integer(), binary()) -> binary().
@@ -152,28 +153,17 @@ suites() ->
%%% Internal functions
%%--------------------------------------------------------------------
-hash(?MD5, Data) ->
+hash(?MD5, Data) ->
crypto:md5(Data);
-hash(?SHA, Data) ->
+hash(?SHA, Data) ->
crypto:sha(Data).
-hash_update(?MD5, Context, Data) ->
- crypto:md5_update(Context, Data);
-hash_update(?SHA, Context, Data) ->
- crypto:sha_update(Context, Data).
-
-hash_final(?MD5, Context) ->
- crypto:md5_final(Context);
-hash_final(?SHA, Context) ->
- crypto:sha_final(Context).
-
%%pad_1(?NULL) ->
%% "";
pad_1(?MD5) ->
<<"666666666666666666666666666666666666666666666666">>;
pad_1(?SHA) ->
<<"6666666666666666666666666666666666666666">>.
-
%%pad_2(?NULL) ->
%% "";
pad_2(?MD5) ->
@@ -189,19 +179,11 @@ mac_hash(Method, Secret, Data) ->
InnerHash = hash(Method, [Secret, pad_1(Method), Data]),
hash(Method, [Secret, pad_2(Method), InnerHash]).
-handshake_hash(Method, HandshakeHash, Extra) ->
- HSH = hash_update(Method, HandshakeHash, Extra),
- hash_final(Method, HSH).
-
-handshake_hash(Method, MasterSecret, undefined, HandshakeHash) ->
- InnerHash =
- handshake_hash(Method, HandshakeHash,
- [MasterSecret, pad_1(Method)]),
+handshake_hash(Method, MasterSecret, undefined, Handshake) ->
+ InnerHash = hash(Method, [Handshake, MasterSecret, pad_1(Method)]),
hash(Method, [MasterSecret, pad_2(Method), InnerHash]);
-handshake_hash(Method, MasterSecret, Sender, HandshakeHash) ->
- InnerHash =
- handshake_hash(Method, HandshakeHash,
- [Sender, MasterSecret, pad_1(Method)]),
+handshake_hash(Method, MasterSecret, Sender, Handshake) ->
+ InnerHash = hash(Method, [Handshake, Sender, MasterSecret, pad_1(Method)]),
hash(Method, [MasterSecret, pad_2(Method), InnerHash]).
get_sender(client) -> "CLNT";
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index cb10b1362a..59039a6e0a 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -41,7 +41,6 @@ start_link() ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
--spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
init([]) ->
%% OLD ssl - moved start to ssl.erl only if old
diff --git a/lib/ssl/src/ssl_tls1.erl b/lib/ssl/src/ssl_tls1.erl
index 5f9850c386..41dc1bf0dc 100644
--- a/lib/ssl/src/ssl_tls1.erl
+++ b/lib/ssl/src/ssl_tls1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,27 +26,29 @@
-include("ssl_cipher.hrl").
-include("ssl_internal.hrl").
--include("ssl_record.hrl").
+-include("ssl_record.hrl").
--export([master_secret/3, finished/3, certificate_verify/2, mac_hash/7,
- setup_keys/6, suites/0]).
+-export([master_secret/4, finished/5, certificate_verify/3, mac_hash/7,
+ setup_keys/8, suites/1, prf/5]).
%%====================================================================
%% Internal application API
%%====================================================================
--spec master_secret(binary(), binary(), binary()) -> binary().
+-spec master_secret(integer(), binary(), binary(), binary()) -> binary().
-master_secret(PreMasterSecret, ClientRandom, ServerRandom) ->
- %% RFC 2246 & 4346 - 8.1 %% master_secret = PRF(pre_master_secret,
- %% "master secret", ClientHello.random +
- %% ServerHello.random)[0..47];
- prf(PreMasterSecret, <<"master secret">>,
+master_secret(PrfAlgo, PreMasterSecret, ClientRandom, ServerRandom) ->
+ %% RFC 2246 & 4346 && RFC 5246 - 8.1 %% master_secret = PRF(pre_master_secret,
+ %% "master secret", ClientHello.random +
+ %% ServerHello.random)[0..47];
+
+ prf(PrfAlgo, PreMasterSecret, <<"master secret">>,
[ClientRandom, ServerRandom], 48).
--spec finished(client | server, binary(), {binary(), binary()}) -> binary().
+-spec finished(client | server, integer(), integer(), binary(), [binary()]) -> binary().
-finished(Role, MasterSecret, {MD5Hash, SHAHash}) ->
+finished(Role, Version, PrfAlgo, MasterSecret, Handshake)
+ when Version == 1; Version == 2; PrfAlgo == ?MD5SHA ->
%% RFC 2246 & 4346 - 7.4.9. Finished
%% struct {
%% opaque verify_data[12];
@@ -55,26 +57,39 @@ finished(Role, MasterSecret, {MD5Hash, SHAHash}) ->
%% verify_data
%% PRF(master_secret, finished_label, MD5(handshake_messages) +
%% SHA-1(handshake_messages)) [0..11];
- MD5 = hash_final(?MD5, MD5Hash),
- SHA = hash_final(?SHA, SHAHash),
- prf(MasterSecret, finished_label(Role), [MD5, SHA], 12).
+ MD5 = crypto:md5(Handshake),
+ SHA = crypto:sha(Handshake),
+ prf(?MD5SHA, MasterSecret, finished_label(Role), [MD5, SHA], 12);
+
+finished(Role, Version, PrfAlgo, MasterSecret, Handshake)
+ when Version == 3 ->
+ %% RFC 5246 - 7.4.9. Finished
+ %% struct {
+ %% opaque verify_data[12];
+ %% } Finished;
+ %%
+ %% verify_data
+ %% PRF(master_secret, finished_label, Hash(handshake_messages)) [0..11];
+ Hash = crypto:hash(mac_algo(PrfAlgo), Handshake),
+ prf(PrfAlgo, MasterSecret, finished_label(Role), Hash, 12).
--spec certificate_verify(OID::tuple(), {binary(), binary()}) -> binary().
+-spec certificate_verify(md5sha | sha, integer(), [binary()]) -> binary().
-certificate_verify(?'rsaEncryption', {MD5Hash, SHAHash}) ->
- MD5 = hash_final(?MD5, MD5Hash),
- SHA = hash_final(?SHA, SHAHash),
+certificate_verify(md5sha, _Version, Handshake) ->
+ MD5 = crypto:md5(Handshake),
+ SHA = crypto:sha(Handshake),
<<MD5/binary, SHA/binary>>;
-certificate_verify(?'id-dsa', {_, SHAHash}) ->
- hash_final(?SHA, SHAHash).
+certificate_verify(HashAlgo, _Version, Handshake) ->
+ crypto:hash(HashAlgo, Handshake).
--spec setup_keys(binary(), binary(), binary(), integer(),
- integer(), integer()) -> {binary(), binary(), binary(),
+-spec setup_keys(integer(), integer(), binary(), binary(), binary(), integer(),
+ integer(), integer()) -> {binary(), binary(), binary(),
binary(), binary(), binary()}.
-setup_keys(MasterSecret, ServerRandom, ClientRandom, HashSize,
- KeyMatLen, IVSize) ->
+setup_keys(Version, _PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
+ KeyMatLen, IVSize)
+ when Version == 1 ->
%% RFC 2246 - 6.3. Key calculation
%% key_block = PRF(SecurityParameters.master_secret,
%% "key expansion",
@@ -88,36 +103,67 @@ setup_keys(MasterSecret, ServerRandom, ClientRandom, HashSize,
%% client_write_IV[SecurityParameters.IV_size]
%% server_write_IV[SecurityParameters.IV_size]
WantedLength = 2 * (HashSize + KeyMatLen + IVSize),
- KeyBlock = prf(MasterSecret, "key expansion",
+ KeyBlock = prf(?MD5SHA, MasterSecret, "key expansion",
[ServerRandom, ClientRandom], WantedLength),
<<ClientWriteMacSecret:HashSize/binary,
ServerWriteMacSecret:HashSize/binary,
ClientWriteKey:KeyMatLen/binary, ServerWriteKey:KeyMatLen/binary,
ClientIV:IVSize/binary, ServerIV:IVSize/binary>> = KeyBlock,
{ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
- ServerWriteKey, ClientIV, ServerIV}.
+ ServerWriteKey, ClientIV, ServerIV};
+
+%% TLS v1.1
+setup_keys(Version, _PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
+ KeyMatLen, IVSize)
+ when Version == 2 ->
+ %% RFC 4346 - 6.3. Key calculation
+ %% key_block = PRF(SecurityParameters.master_secret,
+ %% "key expansion",
+ %% SecurityParameters.server_random +
+ %% SecurityParameters.client_random);
+ %% Then the key_block is partitioned as follows:
+ %% client_write_MAC_secret[SecurityParameters.hash_size]
+ %% server_write_MAC_secret[SecurityParameters.hash_size]
+ %% client_write_key[SecurityParameters.key_material_length]
+ %% server_write_key[SecurityParameters.key_material_length]
+ %%
+ %% RFC 4346 is incomplete, the client and server IVs have to
+ %% be generated just like for TLS 1.0
+ WantedLength = 2 * (HashSize + KeyMatLen + IVSize),
+ KeyBlock = prf(?MD5SHA, MasterSecret, "key expansion",
+ [ServerRandom, ClientRandom], WantedLength),
+ <<ClientWriteMacSecret:HashSize/binary,
+ ServerWriteMacSecret:HashSize/binary,
+ ClientWriteKey:KeyMatLen/binary, ServerWriteKey:KeyMatLen/binary,
+ ClientIV:IVSize/binary, ServerIV:IVSize/binary>> = KeyBlock,
+ {ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
+ ServerWriteKey, ClientIV, ServerIV};
-%% TLS v1.1 uncomment when supported.
-%% setup_keys(MasterSecret, ServerRandom, ClientRandom, HashSize, KeyMatLen) ->
-%% %% RFC 4346 - 6.3. Key calculation
-%% %% key_block = PRF(SecurityParameters.master_secret,
-%% %% "key expansion",
-%% %% SecurityParameters.server_random +
-%% %% SecurityParameters.client_random);
-%% %% Then the key_block is partitioned as follows:
-%% %% client_write_MAC_secret[SecurityParameters.hash_size]
-%% %% server_write_MAC_secret[SecurityParameters.hash_size]
-%% %% client_write_key[SecurityParameters.key_material_length]
-%% %% server_write_key[SecurityParameters.key_material_length]
-%% WantedLength = 2 * (HashSize + KeyMatLen),
-%% KeyBlock = prf(MasterSecret, "key expansion",
-%% [ServerRandom, ClientRandom], WantedLength),
-%% <<ClientWriteMacSecret:HashSize/binary,
-%% ServerWriteMacSecret:HashSize/binary,
-%% ClientWriteKey:KeyMatLen/binary, ServerWriteKey:KeyMatLen/binary>>
-%% = KeyBlock,
-%% {ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
-%% ServerWriteKey, undefined, undefined}.
+%% TLS v1.2
+setup_keys(Version, PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
+ KeyMatLen, IVSize)
+ when Version == 3 ->
+ %% RFC 5246 - 6.3. Key calculation
+ %% key_block = PRF(SecurityParameters.master_secret,
+ %% "key expansion",
+ %% SecurityParameters.server_random +
+ %% SecurityParameters.client_random);
+ %% Then the key_block is partitioned as follows:
+ %% client_write_MAC_secret[SecurityParameters.hash_size]
+ %% server_write_MAC_secret[SecurityParameters.hash_size]
+ %% client_write_key[SecurityParameters.key_material_length]
+ %% server_write_key[SecurityParameters.key_material_length]
+ %% client_write_IV[SecurityParameters.fixed_iv_length]
+ %% server_write_IV[SecurityParameters.fixed_iv_length]
+ WantedLength = 2 * (HashSize + KeyMatLen + IVSize),
+ KeyBlock = prf(PrfAlgo, MasterSecret, "key expansion",
+ [ServerRandom, ClientRandom], WantedLength),
+ <<ClientWriteMacSecret:HashSize/binary,
+ ServerWriteMacSecret:HashSize/binary,
+ ClientWriteKey:KeyMatLen/binary, ServerWriteKey:KeyMatLen/binary,
+ ClientIV:IVSize/binary, ServerIV:IVSize/binary>> = KeyBlock,
+ {ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
+ ServerWriteKey, ClientIV, ServerIV}.
-spec mac_hash(integer(), binary(), integer(), integer(), tls_version(),
integer(), binary()) -> binary().
@@ -134,9 +180,9 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
Fragment]),
Mac.
--spec suites() -> [cipher_suite()].
+-spec suites(1|2|3) -> [cipher_suite()].
-suites() ->
+suites(Minor) when Minor == 1; Minor == 2->
[
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
@@ -152,7 +198,19 @@ suites() ->
?TLS_RSA_WITH_RC4_128_MD5,
?TLS_DHE_RSA_WITH_DES_CBC_SHA,
?TLS_RSA_WITH_DES_CBC_SHA
- ].
+ ];
+
+suites(Minor) when Minor == 3 ->
+ [
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256,
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256
+ %% ?TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ %% ?TLS_DH_anon_WITH_AES_256_CBC_SHA256
+ ] ++ suites(2).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -163,7 +221,19 @@ hmac_hash(?NULL, _, _) ->
hmac_hash(?MD5, Key, Value) ->
crypto:md5_mac(Key, Value);
hmac_hash(?SHA, Key, Value) ->
- crypto:sha_mac(Key, Value).
+ crypto:sha_mac(Key, Value);
+hmac_hash(?SHA256, Key, Value) ->
+ crypto:sha256_mac(Key, Value);
+hmac_hash(?SHA384, Key, Value) ->
+ crypto:sha384_mac(Key, Value);
+hmac_hash(?SHA512, Key, Value) ->
+ crypto:sha512_mac(Key, Value).
+
+mac_algo(?MD5) -> md5;
+mac_algo(?SHA) -> sha;
+mac_algo(?SHA256) -> sha256;
+mac_algo(?SHA384) -> sha384;
+mac_algo(?SHA512) -> sha512.
% First, we define a data expansion function, P_hash(secret, data) that
% uses a single hash function to expand a secret and seed into an
@@ -182,7 +252,7 @@ p_hash(_Secret, _Seed, WantedLength, _Method, _N, [Last | Acc])
when WantedLength =< 0 ->
Keep = byte_size(Last) + WantedLength,
<<B:Keep/binary, _/binary>> = Last,
- lists:reverse(Acc, [B]);
+ list_to_binary(lists:reverse(Acc, [B]));
p_hash(Secret, Seed, WantedLength, Method, N, Acc) ->
N1 = N+1,
Bin = hmac_hash(Method, Secret, [a(N1, Secret, Seed, Method), Seed]),
@@ -214,13 +284,18 @@ split_secret(BinSecret) ->
<<_:Div/binary, Secret2:EvenLength/binary>> = BinSecret,
{Secret1, Secret2}.
-prf(Secret, Label, Seed, WantedLength) ->
+prf(?MD5SHA, Secret, Label, Seed, WantedLength) ->
%% PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
%% P_SHA-1(S2, label + seed);
{S1, S2} = split_secret(Secret),
LS = list_to_binary([Label, Seed]),
crypto:exor(p_hash(S1, LS, WantedLength, ?MD5),
- p_hash(S2, LS, WantedLength, ?SHA)).
+ p_hash(S2, LS, WantedLength, ?SHA));
+
+prf(MAC, Secret, Label, Seed, WantedLength) ->
+ %% PRF(secret, label, seed) = P_SHA256(secret, label + seed);
+ LS = list_to_binary([Label, Seed]),
+ p_hash(Secret, LS, WantedLength, MAC).
%%%% Misc help functions %%%%
@@ -228,8 +303,3 @@ finished_label(client) ->
<<"client finished">>;
finished_label(server) ->
<<"server finished">>.
-
-hash_final(?MD5, Conntext) ->
- crypto:md5_final(Conntext);
-hash_final(?SHA, Conntext) ->
- crypto:sha_final(Conntext).
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index d63eada571..a8476b104f 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The 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(ssl_tls_dist_proxy).
--export([listen/1, accept/1, connect/2, get_remote_id/2]).
+-export([listen/1, accept/1, connect/2, get_tcp_address/1]).
-export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, ssl_options/2]).
@@ -47,9 +47,6 @@ accept(Listen) ->
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
%%====================================================================
@@ -65,8 +62,8 @@ 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),
+ {ok, TcpAddress} = get_tcp_address(Socket),
+ {ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
{ok, Creation} = erl_epmd:register_node(Name, Port),
{reply, {ok, {Socket, TcpAddress, Creation}},
@@ -87,17 +84,16 @@ handle_call({connect, Ip, Port}, {From, _}, State) ->
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};
+ case gen_tcp:controlling_process(Socket, From) of
+ {error, badarg} = Error -> {reply, Error, State}; % From is dead anyway.
+ ok ->
+ flush_old_controller(From, Socket),
+ {reply, Res, State}
+ end;
{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}.
@@ -117,14 +113,18 @@ code_change(_OldVsn, St, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
get_tcp_address(Socket) ->
- {ok, Address} = inet:sockname(Socket),
- {ok, Host} = inet:gethostname(),
- #net_address{
+ case inet:sockname(Socket) of
+ {ok, Address} ->
+ {ok, Host} = inet:gethostname(),
+ NetAddress = #net_address{
address = Address,
host = Host,
protocol = proxy,
family = inet
- }.
+ },
+ {ok, NetAddress};
+ {error, _} = Error -> Error
+ end.
accept_loop(Proxy, erts = Type, Listen, Extra) ->
process_flag(priority, max),
@@ -178,8 +178,8 @@ setup_proxy(Ip, Port, Parent) ->
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),
+ {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]),
+ {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL),
Parent ! {self(), go_ahead, LPort},
case gen_tcp:accept(ErtsL) of
{ok, Erts} ->
@@ -194,7 +194,7 @@ setup_proxy(Ip, Port, Parent) ->
setup_connection(World, ErtsListen) ->
process_flag(trap_exit, true),
- TcpAddress = get_tcp_address(ErtsListen),
+ {ok, 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}]),
@@ -223,7 +223,11 @@ loop_conn_setup(World, Erts) ->
loop_conn_setup(World, Erts);
{tcp, Erts, Data} ->
ssl:send(World, Data),
- loop_conn_setup(World, Erts)
+ loop_conn_setup(World, Erts);
+ {tcp_closed, Erts} ->
+ ssl:close(World);
+ {ssl_closed, World} ->
+ gen_tcp:close(Erts)
end.
loop_conn(World, Erts) ->
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 23a9a23190..a0f54c0359 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -39,6 +39,7 @@ MODULES = \
ssl_basic_SUITE \
ssl_handshake_SUITE \
ssl_packet_SUITE \
+ ssl_cipher_SUITE \
ssl_payload_SUITE \
ssl_to_openssl_SUITE \
ssl_session_cache_SUITE \
@@ -55,6 +56,7 @@ HRL_FILES_SRC = \
ssl_internal.hrl\
ssl_alert.hrl \
ssl_handshake.hrl \
+ ssl_cipher.hrl \
ssl_record.hrl
HRL_FILES_INC =
@@ -118,11 +120,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
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 -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(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 -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl
index 8b01ca3ad4..254aa6d2f9 100644
--- a/lib/ssl/test/erl_make_certs.erl
+++ b/lib/ssl/test/erl_make_certs.erl
@@ -1,7 +1,7 @@
%%
%% %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
@@ -175,7 +175,7 @@ issuer(true, Opts, SubjectKey) ->
issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
{issuer_der(Issuer), decode_key(IssuerKey)};
issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = public_key:pem_to_der(File),
+ {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
{issuer_der(Cert), decode_key(IssuerKey)}.
issuer_der(Issuer) ->
@@ -185,7 +185,7 @@ issuer_der(Issuer) ->
Subject.
subject(undefined, IsRootCA) ->
- User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end,
+ User = if IsRootCA -> "RootCA"; true -> user() end,
Opts = [{email, User ++ "@erlang.org"},
{name, User},
{city, "Stockholm"},
@@ -196,6 +196,14 @@ subject(undefined, IsRootCA) ->
subject(Opts, _) ->
subject(Opts).
+user() ->
+ case os:getenv("USER") of
+ false ->
+ "test_user";
+ User ->
+ User
+ end.
+
subject(SubjectOpts) when is_list(SubjectOpts) ->
Encode = fun(Opt) ->
{Type,Value} = subject_enc(Opt),
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index a9109c5a6e..93f7209aea 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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,15 +27,18 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include("ssl_internal.hrl").
-include("ssl_alert.hrl").
-include("ssl_internal.hrl").
-include("ssl_record.hrl").
+-include("ssl_handshake.hrl").
-define('24H_in_sec', 86400).
-define(TIMEOUT, 60000).
-define(LONG_TIMEOUT, 600000).
-define(EXPIRE, 10).
-define(SLEEP, 500).
+-define(RENEGOTIATION_DISABLE_TIME, 12000).
%% Test server callback functions
%%--------------------------------------------------------------------
@@ -49,10 +52,10 @@
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2),
+ catch crypto:stop(),
try crypto:start() of
ok ->
application:start(public_key),
- ssl:start(),
%% make rsa certs using oppenssl
Result =
@@ -89,46 +92,28 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%% Description: Initialization before each test case
%%--------------------------------------------------------------------
-init_per_testcase(session_cache_process_list, Config) ->
- init_customized_session_cache(list, Config);
-
-init_per_testcase(session_cache_process_mnesia, Config) ->
- mnesia:start(),
- init_customized_session_cache(mnesia, Config);
-
-init_per_testcase(reuse_session_expired, Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = ssl_test_lib:timetrap(?EXPIRE * 1000 * 5),
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, session_lifetime, ?EXPIRE),
- ssl:start(),
- [{watchdog, Dog} | Config];
-
init_per_testcase(no_authority_key_identifier, Config) ->
%% Clear cach so that root cert will not
%% be found.
- ssl:stop(),
- ssl:start(),
+ ssl:clear_pem_cache(),
Config;
-init_per_testcase(TestCase, Config) when TestCase == ciphers_rsa_signed_certs_ssl3;
- TestCase == ciphers_rsa_signed_certs_openssl_names_ssl3;
- TestCase == ciphers_dsa_signed_certs_ssl3;
- TestCase == ciphers_dsa_signed_certs_openssl_names_ssl3 ->
+init_per_testcase(protocol_versions, Config) ->
ssl:stop(),
application:load(ssl),
- application:set_env(ssl, protocol_version, sslv3),
+ %% For backwards compatibility sslv2 should be filtered out.
+ application:set_env(ssl, protocol_version, [sslv2, sslv3, tlsv1]),
ssl:start(),
Config;
-init_per_testcase(protocol_versions, Config) ->
+init_per_testcase(reuse_session_expired, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = ssl_test_lib:timetrap(?EXPIRE * 1000 * 5),
ssl:stop(),
application:load(ssl),
- %% For backwards compatibility sslv2 should be filtered out.
- application:set_env(ssl, protocol_version, [sslv2, sslv3, tlsv1]),
+ application:set_env(ssl, session_lifetime, ?EXPIRE),
ssl:start(),
- Config;
+ [{watchdog, Dog} | Config];
init_per_testcase(empty_protocol_versions, Config) ->
ssl:stop(),
@@ -137,24 +122,15 @@ init_per_testcase(empty_protocol_versions, Config) ->
ssl:start(),
Config;
-init_per_testcase(different_ca_peer_sign, Config0) ->
- ssl_test_lib:make_mix_cert(Config0);
+%% init_per_testcase(different_ca_peer_sign, Config0) ->
+%% ssl_test_lib:make_mix_cert(Config0);
init_per_testcase(_TestCase, Config0) ->
+ test_server:format("TLS/SSL version ~p~n ", [ssl_record:supported_protocol_versions()]),
Config = lists:keydelete(watchdog, 1, Config0),
Dog = test_server:timetrap(?TIMEOUT),
[{watchdog, Dog} | Config].
-init_customized_session_cache(Type, Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = test_server:timetrap(?TIMEOUT),
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, session_cb, ?MODULE),
- application:set_env(ssl, session_cb_init_args, [Type]),
- ssl:start(),
- [{watchdog, Dog} | Config].
-
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
%% Case - atom()
@@ -163,27 +139,10 @@ init_customized_session_cache(Type, Config0) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(session_cache_process_list, Config) ->
- application:unset_env(ssl, session_cb),
- end_per_testcase(default_action, Config);
-end_per_testcase(session_cache_process_mnesia, Config) ->
- application:unset_env(ssl, session_cb),
- application:unset_env(ssl, session_cb_init_args),
- mnesia:stop(),
- ssl:stop(),
- ssl:start(),
- end_per_testcase(default_action, Config);
end_per_testcase(reuse_session_expired, Config) ->
application:unset_env(ssl, session_lifetime),
end_per_testcase(default_action, Config);
-end_per_testcase(TestCase, Config) when TestCase == ciphers_rsa_signed_certs_ssl3;
- TestCase == ciphers_rsa_signed_certs_openssl_names_ssl3;
- TestCase == ciphers_dsa_signed_certs_ssl3;
- TestCase == ciphers_dsa_signed_certs_openssl_names_ssl3;
- TestCase == protocol_versions;
- TestCase == empty_protocol_versions->
- application:unset_env(ssl, protocol_version),
- end_per_testcase(default_action, Config);
+
end_per_testcase(_TestCase, Config) ->
Dog = ?config(watchdog, Config),
case Dog of
@@ -204,69 +163,170 @@ end_per_testcase(_TestCase, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app, alerts, connection_info, protocol_versions,
- empty_protocol_versions, controlling_process,
- controller_dies, client_closes_socket,
- connect_dist, peername, peercert, sockname, socket_options,
- invalid_inet_get_option, invalid_inet_get_option_not_list,
+ [
+ {group, basic},
+ {group, options},
+ {group, session},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}
+ ].
+
+groups() ->
+ [{basic, [], basic_tests()},
+ {options, [], options_tests()},
+ {'tlsv1.2', [], all_versions_groups()},
+ {'tlsv1.1', [], all_versions_groups()},
+ {'tlsv1', [], all_versions_groups() ++ rizzo_tests()},
+ {'sslv3', [], all_versions_groups() ++ rizzo_tests()},
+ {api,[], api_tests()},
+ {certificate_verify, [], certificate_verify_tests()},
+ {session, [], session_tests()},
+ {renegotiate, [], renegotiate_tests()},
+ {ciphers, [], cipher_tests()},
+ {error_handling_tests, [], error_handling_tests()}
+ ].
+
+all_versions_groups ()->
+ [{group, api},
+ {group, certificate_verify},
+ {group, renegotiate},
+ {group, ciphers},
+ {group, error_handling_tests}].
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+basic_tests() ->
+ [app,
+ alerts,
+ send_close,
+ connect_twice,
+ connect_dist
+ ].
+
+options_tests() ->
+ [der_input,
+ misc_ssl_options,
+ 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,
+ invalid_inet_set_option_not_list,
invalid_inet_set_option_improper_list,
- misc_ssl_options, versions, cipher_suites, upgrade,
- 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,
- ciphers_rsa_signed_certs_openssl_names,
- ciphers_rsa_signed_certs_openssl_names_ssl3,
- ciphers_dsa_signed_certs, ciphers_dsa_signed_certs_ssl3,
- ciphers_dsa_signed_certs_openssl_names,
- ciphers_dsa_signed_certs_openssl_names_ssl3,
- anonymous_cipher_suites,
- default_reject_anonymous,
- send_close,
- close_transport_accept, dh_params,
- server_verify_peer_passive, server_verify_peer_active,
+ dh_params,
+ ecertfile,
+ ecacertfile,
+ ekeyfile,
+ eoptions,
+ protocol_versions,
+ empty_protocol_versions,
+ ipv6,
+ reuseaddr].
+
+api_tests() ->
+ [connection_info,
+ peername,
+ peercert,
+ sockname,
+ versions,
+ controlling_process,
+ upgrade,
+ upgrade_with_timeout,
+ shutdown,
+ shutdown_write,
+ shutdown_both,
+ shutdown_error,
+ hibernate
+ ].
+
+certificate_verify_tests() ->
+ [server_verify_peer_passive,
+ server_verify_peer_active,
server_verify_peer_active_once,
- server_verify_none_passive, server_verify_none_active,
+ server_verify_none_passive,
+ server_verify_none_active,
server_verify_none_active_once,
- server_verify_no_cacerts, server_require_peer_cert_ok,
+ server_verify_no_cacerts,
+ server_require_peer_cert_ok,
server_require_peer_cert_fail,
server_verify_client_once_passive,
server_verify_client_once_active,
server_verify_client_once_active_once,
- client_verify_none_passive, client_verify_none_active,
+ client_verify_none_passive,
+ client_verify_none_active,
client_verify_none_active_once,
- reuse_session,
- reuse_session_expired,
- server_does_not_want_to_reuse_session,
- client_renegotiate, server_renegotiate,
- client_renegotiate_reused_session,
- server_renegotiate_reused_session,
- client_no_wrap_sequence_number,
- server_no_wrap_sequence_number, extended_key_usage_verify_peer,
+ extended_key_usage_verify_peer,
extended_key_usage_verify_none,
- no_authority_key_identifier, invalid_signature_client,
- invalid_signature_server, cert_expired,
+ invalid_signature_client,
+ invalid_signature_server,
+ cert_expired,
client_with_cert_cipher_suites_handshake,
- unknown_server_ca_fail, der_input,
+ verify_fun_always_run_client,
+ verify_fun_always_run_server,
+ unknown_server_ca_fail,
unknown_server_ca_accept_verify_none,
unknown_server_ca_accept_verify_peer,
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, connect_twice
+ no_authority_key_identifier
].
-groups() ->
- [].
+session_tests() ->
+ [reuse_session,
+ reuse_session_expired,
+ server_does_not_want_to_reuse_session,
+ no_reuses_session_server_restart_new_cert,
+ no_reuses_session_server_restart_new_cert_file].
-init_per_group(_GroupName, Config) ->
- Config.
+renegotiate_tests() ->
+ [client_renegotiate,
+ server_renegotiate,
+ client_renegotiate_reused_session,
+ server_renegotiate_reused_session,
+ client_no_wrap_sequence_number,
+ server_no_wrap_sequence_number,
+ renegotiate_dos_mitigate_active,
+ renegotiate_dos_mitigate_passive].
-end_per_group(_GroupName, Config) ->
- Config.
+cipher_tests() ->
+ [cipher_suites,
+ ciphers_rsa_signed_certs,
+ ciphers_rsa_signed_certs_openssl_names,
+ ciphers_dsa_signed_certs,
+ ciphers_dsa_signed_certs_openssl_names,
+ anonymous_cipher_suites,
+ default_reject_anonymous].
+
+error_handling_tests()->
+ [controller_dies,
+ client_closes_socket,
+ tcp_error_propagation_in_active_mode,
+ tcp_connect,
+ tcp_connect_big,
+ close_transport_accept
+ ].
+
+rizzo_tests() ->
+ [rizzo,
+ no_rizzo_rc4].
%% Test cases starts here.
%%--------------------------------------------------------------------
@@ -393,8 +453,8 @@ controlling_process(Config) when is_list(Config) ->
ClientOpts = ?config(client_opts, Config),
ServerOpts = ?config(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- ClientMsg = "Hello server",
- ServerMsg = "Hello client",
+ ClientMsg = "Server hello",
+ ServerMsg = "Client hello",
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
@@ -415,11 +475,15 @@ controlling_process(Config) when is_list(Config) ->
[self(), Client, Server]),
receive
+ {ssl, _, "S"} ->
+ receive_s_rizzo_duong_beast();
{ssl, _, ServerMsg} ->
receive
{ssl, _, ClientMsg} ->
ok
end;
+ {ssl, _, "C"} ->
+ receive_c_rizzo_duong_beast();
{ssl, _, ClientMsg} ->
receive
{ssl, _, ServerMsg} ->
@@ -440,6 +504,28 @@ controlling_process_result(Socket, Pid, Msg) ->
ssl:send(Socket, Msg),
no_result_msg.
+receive_s_rizzo_duong_beast() ->
+ receive
+ {ssl, _, "erver hello"} ->
+ receive
+ {ssl, _, "C"} ->
+ receive
+ {ssl, _, "lient hello"} ->
+ ok
+ end
+ end
+ end.
+receive_c_rizzo_duong_beast() ->
+ receive
+ {ssl, _, "lient hello"} ->
+ receive
+ {ssl, _, "S"} ->
+ receive
+ {ssl, _, "erver hello"} ->
+ ok
+ end
+ end
+ end.
%%--------------------------------------------------------------------
controller_dies(doc) ->
["Test that the socket is closed after controlling process dies"];
@@ -1231,6 +1317,11 @@ upgrade_result(Socket) ->
%% Make sure binary is inherited from tcp socket and that we do
%% not get the list default!
receive
+ {ssl, _, <<"H">>} ->
+ receive
+ {ssl, _, <<"ello world">>} ->
+ ok
+ end;
{ssl, _, <<"Hello world">>} ->
ok
end.
@@ -1532,14 +1623,14 @@ eoptions(Config) when is_list(Config) ->
{cacertfile, ""},
{dhfile,'dh.pem' },
{ciphers, [{foo, bar, sha, ignore}]},
- {reuse_session, foo},
- {reuse_sessions, 0},
+ {reuse_session, foo},
+ {reuse_sessions, 0},
{renegotiate_at, "10"},
- {debug, 1},
+ {debug, 1},
{mode, depech},
- {packet, 8.0},
- {packet_size, "2"},
- {header, a},
+ {packet, 8.0},
+ {packet_size, "2"},
+ {header, a},
{active, trice},
{key, 'key.pem' }],
@@ -1688,21 +1779,7 @@ ciphers_rsa_signed_certs(Config) when is_list(Config) ->
ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
Ciphers = ssl_test_lib:rsa_suites(),
- test_server:format("tls1 erlang cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, rsa).
-
-ciphers_rsa_signed_certs_ssl3(doc) ->
- ["Test all rsa ssl cipher suites in ssl3"];
-
-ciphers_rsa_signed_certs_ssl3(suite) ->
- [];
-
-ciphers_rsa_signed_certs_ssl3(Config) when is_list(Config) ->
- Version =
- ssl_record:protocol_version({3,0}),
-
- Ciphers = ssl_test_lib:rsa_suites(),
- test_server:format("ssl3 erlang cipher suites ~p~n", [Ciphers]),
+ test_server:format("~p erlang cipher suites ~p~n", [Version, Ciphers]),
run_suites(Ciphers, Version, Config, rsa).
ciphers_rsa_signed_certs_openssl_names(doc) ->
@@ -1719,18 +1796,6 @@ ciphers_rsa_signed_certs_openssl_names(Config) when is_list(Config) ->
run_suites(Ciphers, Version, Config, rsa).
-ciphers_rsa_signed_certs_openssl_names_ssl3(doc) ->
- ["Test all dsa ssl cipher suites in ssl3"];
-
-ciphers_rsa_signed_certs_openssl_names_ssl3(suite) ->
- [];
-
-ciphers_rsa_signed_certs_openssl_names_ssl3(Config) when is_list(Config) ->
- Version = ssl_record:protocol_version({3,0}),
- Ciphers = ssl_test_lib:openssl_rsa_suites(),
- run_suites(Ciphers, Version, Config, rsa).
-
-
ciphers_dsa_signed_certs(doc) ->
["Test all dsa ssl cipher suites in highest support ssl/tls version"];
@@ -1742,23 +1807,8 @@ ciphers_dsa_signed_certs(Config) when is_list(Config) ->
ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
Ciphers = ssl_test_lib:dsa_suites(),
- test_server:format("tls1 erlang cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, dsa).
-
-ciphers_dsa_signed_certs_ssl3(doc) ->
- ["Test all dsa ssl cipher suites in ssl3"];
-
-ciphers_dsa_signed_certs_ssl3(suite) ->
- [];
-
-ciphers_dsa_signed_certs_ssl3(Config) when is_list(Config) ->
- Version =
- ssl_record:protocol_version({3,0}),
-
- Ciphers = ssl_test_lib:dsa_suites(),
- test_server:format("ssl3 erlang cipher suites ~p~n", [Ciphers]),
+ test_server:format("~p erlang cipher suites ~p~n", [Version, Ciphers]),
run_suites(Ciphers, Version, Config, dsa).
-
ciphers_dsa_signed_certs_openssl_names(doc) ->
["Test all dsa ssl cipher suites in highest support ssl/tls version"];
@@ -1774,18 +1824,6 @@ ciphers_dsa_signed_certs_openssl_names(Config) when is_list(Config) ->
test_server:format("tls1 openssl cipher suites ~p~n", [Ciphers]),
run_suites(Ciphers, Version, Config, dsa).
-
-ciphers_dsa_signed_certs_openssl_names_ssl3(doc) ->
- ["Test all dsa ssl cipher suites in ssl3"];
-
-ciphers_dsa_signed_certs_openssl_names_ssl3(suite) ->
- [];
-
-ciphers_dsa_signed_certs_openssl_names_ssl3(Config) when is_list(Config) ->
- Version = ssl_record:protocol_version({3,0}),
- Ciphers = ssl_test_lib:openssl_dsa_suites(),
- run_suites(Ciphers, Version, Config, dsa).
-
anonymous_cipher_suites(doc)->
["Test the anonymous ciphersuites"];
anonymous_cipher_suites(suite) ->
@@ -1822,7 +1860,7 @@ run_suites(Ciphers, Version, Config, Type) ->
end.
erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher:suite_definition(ssl_cipher:openssl_suite(Suite));
+ ssl:suite_definition(ssl_cipher:openssl_suite(Suite));
erlang_cipher_suite(Suite) ->
Suite.
@@ -2049,7 +2087,9 @@ reuse_session_expired(Config) when is_list(Config) ->
Server ! listen,
%% Make sure session is unregistered due to expiration
- test_server:sleep((?EXPIRE+1) * 1000),
+ test_server:sleep((?EXPIRE+1)),
+ [{session_id, Id} |_] = SessionInfo,
+ make_sure_expired(Hostname, Port, Id),
Client2 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -2068,6 +2108,22 @@ reuse_session_expired(Config) when is_list(Config) ->
ssl_test_lib:close(Client1),
ssl_test_lib:close(Client2).
+make_sure_expired(Host, Port, Id) ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ Cache = element(2, State),
+ case ssl_session_cache:lookup(Cache, {{Host, Port}, Id}) of
+ undefined ->
+ ok;
+ #session{is_resumable = false} ->
+ ok;
+ _ ->
+ test_server:sleep(?SLEEP),
+ make_sure_expired(Host, Port, Id)
+ end.
+
+
%%--------------------------------------------------------------------
server_does_not_want_to_reuse_session(doc) ->
["Test reuse of sessions (short handshake)"];
@@ -2313,8 +2369,8 @@ server_verify_client_once_passive(Config) when is_list(Config) ->
{options, [{active, false} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
- ssl_test_lib:close(Client0),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ ssl_test_lib:close(Client0),
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2340,7 +2396,7 @@ server_verify_client_once_active(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {?MODULE, send_recv_result_active, []}},
- {options, [{active, once}, {verify, verify_peer},
+ {options, [{active, true}, {verify, verify_peer},
{verify_client_once, true}
| ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
@@ -2351,8 +2407,8 @@ server_verify_client_once_active(Config) when is_list(Config) ->
{options, [{active, true} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
- ssl_test_lib:close(Client0),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ ssl_test_lib:close(Client0),
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2389,8 +2445,8 @@ server_verify_client_once_active_once(Config) when is_list(Config) ->
{options, [{active, once} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
- ssl_test_lib:close(Client0),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ ssl_test_lib:close(Client0),
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2592,7 +2648,7 @@ client_renegotiate(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {?MODULE,
@@ -2724,17 +2780,28 @@ client_no_wrap_sequence_number(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_record:highest_protocol_version(ssl_record:supported_protocol_versions()),
+
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib,
- trigger_renegotiate, [[ErlData, N+2]]}},
+ trigger_renegotiate, [[ErlData, treashold(N, Version)]]}},
{options, [{reuse_sessions, false},
{renegotiate_at, N} | ClientOpts]}]),
ssl_test_lib:check_result(Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+ %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast
+treashold(N, {3,0}) ->
+ (N div 2) + 1;
+treashold(N, {3,1}) ->
+ (N div 2) + 1;
+treashold(N, _) ->
+ N + 1.
+
%%--------------------------------------------------------------------
server_no_wrap_sequence_number(doc) ->
["Test that erlang server will renegotiate session when",
@@ -2784,7 +2851,7 @@ extended_key_usage_verify_peer(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
@@ -2846,7 +2913,7 @@ extended_key_usage_verify_none(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
@@ -2908,7 +2975,7 @@ no_authority_key_identifier(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
CertFile = proplists:get_value(certfile, ServerOpts),
NewCertFile = filename:join(PrivDir, "server/new_cert.pem"),
@@ -2966,7 +3033,7 @@ invalid_signature_server(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "server/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"),
@@ -2988,8 +3055,8 @@ invalid_signature_server(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, "bad certificate"},
- Client, {error,"bad certificate"}).
+ tcp_delivery_workaround(Server, {error, "bad certificate"},
+ Client, {error,"bad certificate"}).
%%--------------------------------------------------------------------
@@ -3006,7 +3073,7 @@ invalid_signature_client(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "client/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ClientCertFile = proplists:get_value(certfile, ClientOpts),
NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"),
@@ -3034,41 +3101,47 @@ invalid_signature_client(Config) when is_list(Config) ->
tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
receive
{Server, ServerMsg} ->
- receive
- {Client, ClientMsg} ->
- ok;
- {Client, {error,closed}} ->
- test_server:format("client got close");
- Unexpected ->
- test_server:fail(Unexpected)
- end;
+ client_msg(Client, ClientMsg);
{Client, ClientMsg} ->
- receive
- {Server, ServerMsg} ->
- ok;
- Unexpected ->
- test_server:fail(Unexpected)
- end;
+ server_msg(Server, ServerMsg);
{Client, {error,closed}} ->
- receive
- {Server, ServerMsg} ->
- ok;
- Unexpected ->
- test_server:fail(Unexpected)
- end;
+ server_msg(Server, ServerMsg);
{Server, {error,closed}} ->
- receive
- {Client, ClientMsg} ->
- ok;
- {Client, {error,closed}} ->
- test_server:format("client got close"),
- ok;
- Unexpected ->
- test_server:fail(Unexpected)
- end;
+ client_msg(Client, ClientMsg);
+ {Client, {error, esslconnect}} ->
+ server_msg(Server, ServerMsg);
+ {Server, {error, esslaccept}} ->
+ client_msg(Client, ClientMsg)
+ end.
+
+client_msg(Client, ClientMsg) ->
+ receive
+ {Client, ClientMsg} ->
+ ok;
+ {Client, {error,closed}} ->
+ test_server:format("client got close"),
+ ok;
+ {Client, {error, esslconnect}} ->
+ test_server:format("client got econnaborted"),
+ ok;
Unexpected ->
test_server:fail(Unexpected)
end.
+
+server_msg(Server, ServerMsg) ->
+ receive
+ {Server, ServerMsg} ->
+ ok;
+ {Server, {error,closed}} ->
+ test_server:format("server got close"),
+ ok;
+ {Server, {error, esslaccept}} ->
+ test_server:format("server got econnaborted"),
+ ok;
+ Unexpected ->
+ test_server:fail(Unexpected)
+ end.
+
%%--------------------------------------------------------------------
cert_expired(doc) ->
["Test server with invalid signature"];
@@ -3083,7 +3156,7 @@ cert_expired(Config) when is_list(Config) ->
KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = public_key:pem_entry_decode(KeyEntry),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"),
@@ -3166,6 +3239,105 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_client(doc) ->
+ ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"];
+verify_fun_always_run_client(suite) ->
+ [];
+verify_fun_always_run_client(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we can not tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [2]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}
+ | ClientOpts]}]),
+ %% Server error may be esslaccept or closed depending on timing
+ %% this is not a bug it is a circumstance of how tcp works!
+ receive
+ {Server, ServerError} ->
+ test_server:format("Server Error ~p~n", [ServerError])
+ end,
+
+ ssl_test_lib:check_result(Client, {error, esslconnect}).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_server(doc) ->
+ ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"];
+verify_fun_always_run_server(suite) ->
+ [];
+verify_fun_always_run_server(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we can not tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [2]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState} |
+ ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer}
+ | ClientOpts]}]),
+
+ %% Client error may be esslconnect or closed depending on timing
+ %% this is not a bug it is a circumstance of how tcp works!
+ receive
+ {Client, ClientError} ->
+ test_server:format("Client Error ~p~n", [ClientError])
+ end,
+
+ ssl_test_lib:check_result(Server, {error, esslaccept}).
+
%%--------------------------------------------------------------------
unknown_server_ca_fail(doc) ->
["Test that the client fails if the ca is unknown in verify_peer mode"];
@@ -3358,14 +3530,14 @@ der_input_opts(Opts) ->
Keyfile = proplists:get_value(keyfile, Opts),
Dhfile = proplists:get_value(dhfile, Opts),
[{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile),
- [{_, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
+ [{Asn1Type, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
[{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile),
CaCerts =
lists:map(fun(Entry) ->
{_, CaCert, _} = Entry,
CaCert
end, ssl_test_lib:pem_to_der(CaCertsfile)),
- {Cert, {rsa, Key}, CaCerts, DHParams}.
+ {Cert, {Asn1Type, Key}, CaCerts, DHParams}.
%%--------------------------------------------------------------------
%% different_ca_peer_sign(doc) ->
@@ -3497,6 +3669,8 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client0),
+ ssl:clear_pem_cache(),
+
NewServerOpts = new_config(PrivDir, DsaServerOpts),
Server1 =
@@ -3588,14 +3762,13 @@ hibernate(Config) ->
{from, self()},
{mfa, {?MODULE, send_recv_result_active, []}},
{options, [{hibernate_after, 1000}|ClientOpts]}]),
-
- { current_function, { _M, _F, _A } } =
+ {current_function, _} =
process_info(Pid, current_function),
timer:sleep(1100),
- { current_function, { erlang, hibernate, 3} } =
- process_info(Pid, current_function),
+ {current_function, {erlang, hibernate, 3}} =
+ process_info(Pid, current_function),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
@@ -3647,6 +3820,193 @@ connect_twice(Config) when is_list(Config) ->
ssl_test_lib:close(Client),
ssl_test_lib:close(Client1).
+%%--------------------------------------------------------------------
+renegotiate_dos_mitigate_active(doc) ->
+ ["Mitigate DOS computational attack by not allowing client to renegotiate many times in a row",
+ "immediately after each other"];
+
+renegotiate_dos_mitigate_active(suite) ->
+ [];
+
+renegotiate_dos_mitigate_active(Config) when is_list(Config) ->
+ ServerOpts = ?config(server_opts, Config),
+ ClientOpts = ?config(client_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result_active, []}},
+ {options, [ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ renegotiate_immediately, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+renegotiate_dos_mitigate_passive(doc) ->
+ ["Mitigate DOS computational attack by not allowing client to renegotiate many times in a row",
+ "immediately after each other"];
+
+renegotiate_dos_mitigate_passive(suite) ->
+ [];
+
+renegotiate_dos_mitigate_passive(Config) when is_list(Config) ->
+ ServerOpts = ?config(server_opts, Config),
+ ClientOpts = ?config(client_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ renegotiate_immediately, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+tcp_error_propagation_in_active_mode(doc) ->
+ ["Test that process recives {ssl_error, Socket, closed} when tcp error ocurres"];
+tcp_error_propagation_in_active_mode(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, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {Client, #sslsocket{pid=Pid} = SslSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, receive_msg, []}},
+ {options, ClientOpts}]),
+
+ {status, _, _, StatusInfo} = sys:get_status(Pid),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ Socket = element(10, State),
+
+ %% Fake tcp error
+ Pid ! {tcp_error, Socket, etimedout},
+
+ ssl_test_lib:check_result(Client, {ssl_closed, SslSocket}).
+
+
+%%--------------------------------------------------------------------
+
+recv_error_handling(doc) ->
+ ["Special case of call error handling"];
+recv_error_handling(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, recv_close, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {_Client, #sslsocket{} = SslSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+ ssl:close(SslSocket),
+ ssl_test_lib:check_result(Server, ok).
+
+
+%%--------------------------------------------------------------------
+
+rizzo(doc) -> ["Test that there is a 1/n-1-split for non RC4 in 'TLS < 1.1' as it is
+ vunrable to Rizzo/Dungon attack"];
+
+rizzo(Config) when is_list(Config) ->
+ Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
+ Prop = ?config(tc_group_properties, Config),
+ Version = proplists:get_value(name, Prop),
+ run_send_recv_rizzo(Ciphers, Config, Version,
+ {?MODULE, send_recv_result_active_rizzo, []}).
+%%--------------------------------------------------------------------
+no_rizzo_rc4(doc) ->
+ ["Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"];
+
+no_rizzo_rc4(Config) when is_list(Config) ->
+ Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(),Y == rc4_128],
+ Prop = ?config(tc_group_properties, Config),
+ Version = proplists:get_value(name, Prop),
+ run_send_recv_rizzo(Ciphers, Config, Version,
+ {?MODULE, send_recv_result_active_no_rizzo, []}).
+
+%%--------------------------------------------------------------------
+run_send_recv_rizzo(Ciphers, Config, Version, Mfa) ->
+ Result = lists:map(fun(Cipher) ->
+ rizzo_test(Cipher, Config, Version, Mfa) end,
+ Ciphers),
+ case lists:flatten(Result) of
+ [] ->
+ ok;
+ Error ->
+ test_server:format("Cipher suite errors: ~p~n", [Error]),
+ test_server:fail(cipher_suite_failed_see_test_case_log)
+ end.
+
+rizzo_test(Cipher, Config, Version, Mfa) ->
+ {ClientOpts, ServerOpts} = client_server_opts(Cipher, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, Mfa},
+ {options, [{active, true}, {ciphers, [Cipher]},
+ {versions, [Version]}
+ | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, Mfa},
+ {options, [{active, true} | ClientOpts]}]),
+
+ Result = ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ case Result of
+ ok ->
+ [];
+ Error ->
+ [{Cipher, Error}]
+ end.
+
+client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == rsa orelse KeyAlgo == dhe_rsa ->
+ {?config(client_opts, Config),
+ ?config(server_opts, Config)};
+client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss ->
+ {?config(client_dsa_opts, Config),
+ ?config(server_dsa_opts, Config)}.
%%--------------------------------------------------------------------
%%% Internal functions
@@ -3656,9 +4016,40 @@ send_recv_result(Socket) ->
{ok,"Hello world"} = ssl:recv(Socket, 11),
ok.
+recv_close(Socket) ->
+ {error, closed} = ssl:recv(Socket, 11),
+ receive
+ {_,{error,closed}} ->
+ error_extra_close_sent_to_user_process
+ after 500 ->
+ ok
+ end.
+
send_recv_result_active(Socket) ->
ssl:send(Socket, "Hello world"),
receive
+ {ssl, Socket, "H"} ->
+ receive
+ {ssl, Socket, "ello world"} ->
+ ok
+ end;
+ {ssl, Socket, "Hello world"} ->
+ ok
+ end.
+
+send_recv_result_active_rizzo(Socket) ->
+ ssl:send(Socket, "Hello world"),
+ receive
+ {ssl, Socket, "H"} ->
+ receive
+ {ssl, Socket, "ello world"} ->
+ ok
+ end
+ end.
+
+send_recv_result_active_no_rizzo(Socket) ->
+ ssl:send(Socket, "Hello world"),
+ receive
{ssl, Socket, "Hello world"} ->
ok
end.
@@ -3666,6 +4057,12 @@ send_recv_result_active(Socket) ->
send_recv_result_active_once(Socket) ->
ssl:send(Socket, "Hello world"),
receive
+ {ssl, Socket, "H"} ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, "ello world"} ->
+ ok
+ end;
{ssl, Socket, "Hello world"} ->
ok
end.
@@ -3686,10 +4083,29 @@ renegotiate(Socket, Data) ->
end.
renegotiate_reuse_session(Socket, Data) ->
- %% Make sure session is registerd
+ %% Make sure session is registered
test_server:sleep(?SLEEP),
renegotiate(Socket, Data).
+renegotiate_immediately(Socket) ->
+ receive
+ {ssl, Socket, "Hello world"} ->
+ ok;
+ %% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
+ {ssl, Socket, "H"} ->
+ receive
+ {ssl, Socket, "ello world"} ->
+ ok
+ end
+ end,
+ ok = ssl:renegotiate(Socket),
+ {error, renegotiation_rejected} = ssl:renegotiate(Socket),
+ test_server:sleep(?RENEGOTIATION_DISABLE_TIME +1),
+ ok = ssl:renegotiate(Socket),
+ test_server:format("Renegotiated again"),
+ ssl:send(Socket, "Hello world"),
+ ok.
+
new_config(PrivDir, ServerOpts0) ->
CaCertFile = proplists:get_value(cacertfile, ServerOpts0),
CertFile = proplists:get_value(certfile, ServerOpts0),
@@ -3863,8 +4279,17 @@ erlang_ssl_receive(Socket, Data) ->
{ssl, Socket, Data} ->
io:format("Received ~p~n",[Data]),
ok;
+ {ssl, Socket, Byte} when length(Byte) == 1 -> %% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
+ io:format("Received ~p~n",[Byte]),
+ erlang_ssl_receive(Socket, tl(Data));
Other ->
test_server:fail({unexpected_message, Other})
after ?SLEEP * 3 ->
test_server:fail({did_not_get, Data})
end.
+
+receive_msg(_) ->
+ receive
+ Msg ->
+ Msg
+ end.
diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
new file mode 100644
index 0000000000..83beeb0131
--- /dev/null
+++ b/lib/ssl/test/ssl_cipher_SUITE.erl
@@ -0,0 +1,221 @@
+%%
+%% %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_cipher_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
+-include("ssl_cipher.hrl").
+-include("ssl_alert.hrl").
+
+-define(TIMEOUT, 600000).
+
+%% 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) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ 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) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+%% 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, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = ssl_test_lib:timetrap(?TIMEOUT),
+ [{watchdog, Dog} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, Config) ->
+ Dog = ?config(watchdog, Config),
+ case Dog of
+ undefined ->
+ ok;
+ _ ->
+ test_server:timetrap_cancel(Dog)
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> TestCases
+%% Clause - atom() - suite | doc
+%% TestCases - [Case]
+%% Case - atom()
+%% Name of a test case.
+%% Description: Returns a list of all test cases in this test suite
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [aes_decipher_good, aes_decipher_good_tls11, aes_decipher_fail, aes_decipher_fail_tls11].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+aes_decipher_good(doc) ->
+ ["Decipher a known cryptotext."];
+
+aes_decipher_good(suite) ->
+ [];
+
+aes_decipher_good(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Content = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56, "HELLO\n">>,
+ Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
+ Version = {3,0},
+ {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ Version1 = {3,1},
+ {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+ ok.
+
+%%--------------------------------------------------------------------
+
+aes_decipher_good_tls11(doc) ->
+ ["Decipher a known TLS 1.1 cryptotext."];
+
+aes_decipher_good_tls11(suite) ->
+ [];
+
+%% the fragment is actuall a TLS 1.1 record, with
+%% Version = TLS 1.1, we get the correct NextIV in #cipher_state
+aes_decipher_good_tls11(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Content = <<"HELLO\n">>,
+ NextIV = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>,
+ Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
+ Version = {3,2},
+ {Content, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ Version1 = {3,2},
+ {Content, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+ ok.
+
+%%--------------------------------------------------------------------
+
+aes_decipher_fail(doc) ->
+ ["Decipher a known cryptotext."];
+
+aes_decipher_fail(suite) ->
+ [];
+
+%% same as above, last byte of key replaced
+aes_decipher_fail(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Version = {3,0},
+ {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ 32 = byte_size(Content),
+ 32 = byte_size(Mac),
+ Version1 = {3,1},
+ {Content1, Mac1, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+ 32 = byte_size(Content1),
+ 32 = byte_size(Mac1),
+ ok.
+
+%%--------------------------------------------------------------------
+
+aes_decipher_fail_tls11(doc) ->
+ ["Decipher a known TLS 1.1 cryptotext."];
+
+aes_decipher_fail_tls11(suite) ->
+ [];
+
+%% same as above, last byte of key replaced
+%% stricter padding checks in TLS 1.1 mean we get an alert instead
+aes_decipher_fail_tls11(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Version = {3,2},
+ #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ Version1 = {3,3},
+ #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+ ok.
+
+%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 23e9268f9b..818f7f1897 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
-define(DEFAULT_TIMETRAP_SECS, 240).
--define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
+-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000).
-record(node_handle,
{connection_handler,
@@ -54,9 +54,14 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config0) ->
try crypto:start() of
ok ->
- Config = add_ssl_opts_config(Config0),
- setup_certs(Config),
- Config
+ case test_server:is_cover() of
+ false ->
+ Config = add_ssl_opts_config(Config0),
+ setup_certs(Config),
+ Config;
+ true ->
+ {skip, "Can not be covered"}
+ end
catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -65,11 +70,31 @@ end_per_suite(Config) ->
application:stop(crypto),
Config.
+init_per_testcase(plain_verify_options = Case, Config) when is_list(Config) ->
+ SslFlags = setup_dist_opts([{many_verify_opts, true} | Config]),
+ Flags = case os:getenv("ERL_FLAGS") of
+ false ->
+ os:putenv("ERL_FLAGS", SslFlags),
+ "";
+ OldFlags ->
+ os:putenv("ERL_FLAGS", OldFlags ++ "" ++ SslFlags),
+ OldFlags
+ end,
+ common_init(Case, [{old_flags, Flags} | Config]);
+
init_per_testcase(Case, Config) when is_list(Config) ->
+ common_init(Case, Config).
+
+common_init(Case, Config) ->
Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
[{watchdog, Dog},{testcase, Case}|Config].
-end_per_testcase(_Case, Config) when is_list(Config) ->
+end_per_testcase(Case, Config) when is_list(Config) ->
+ Flags = proplists:get_value(old_flags, Config),
+ os:putenv("ERL_FLAGS", Flags),
+ common_end(Case, Config).
+
+common_end(_, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
@@ -95,6 +120,12 @@ basic(Config) when is_list(Config) ->
pang = net_adm:ping(Node1),
pang = net_adm:ping(Node2),
+ %% SSL nodes should not be able to communicate with the test_server node
+ %% either (and ping should return eventually).
+ TestServer = node(),
+ pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(TestServer) end),
+ pang = apply_on_ssl_node(NH2, fun () -> net_adm:ping(TestServer) end),
+
%%
%% Check that we are able to communicate over the erlang
%% distribution between the ssl nodes.
@@ -205,9 +236,9 @@ plain_verify_options(Config) when is_list(Config) ->
"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]),
+ NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node([{additional_dist_opts, DistOpts}, {many_verify_opts, true} | Config]),
+ 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),
@@ -338,7 +369,7 @@ mk_node_cmdline(ListenPort, Name, Args) ->
_ -> "-name "
end,
{ok, Pwd} = file:get_cwd(),
- Prog ++ " "
+ "\"" ++ Prog ++ "\" "
++ Static ++ " "
++ NameSw ++ " " ++ Name ++ " "
++ "-pa " ++ Pa ++ " "
@@ -355,7 +386,7 @@ mk_node_cmdline(ListenPort, Name, Args) ->
%%
await_ssl_node_up(Name, LSock) ->
- case gen_tcp:accept(LSock, ?AWAIT_SLL_NODE_UP_TIMEOUT) of
+ case gen_tcp:accept(LSock, ?AWAIT_SSL_NODE_UP_TIMEOUT) of
timeout ->
gen_tcp:close(LSock),
?t:format("Timeout waiting for ssl node ~s to come up~n",
@@ -467,8 +498,10 @@ cnct2tstsrvr([Host, Port]) when is_list(Host), is_list(Port) ->
ets:insert(test_server_info,
{test_server_handler, self()}),
ssl_node_con_loop(Socket);
- _Error ->
- halt("Failed to connect to test server")
+ Error ->
+ halt("Failed to connect to test server " ++
+ lists:flatten(io_lib:format("Host:~p ~n Port:~p~n Error:~p~n",
+ [Host, Port, Error])))
end
end),
spawn(fun () ->
@@ -476,9 +509,8 @@ cnct2tstsrvr([Host, Port]) when is_list(Host), is_list(Port) ->
receive
{'DOWN', Mon, process, ConnHandler, Reason} ->
receive after 1000 -> ok end,
- halt("test server connection handler terminated: "
- ++
- lists:flatten(io_lib:format("~p", [Reason])))
+ halt("test server connection handler terminated: " ++
+ lists:flatten(io_lib:format("~p", [Reason])))
end
end).
@@ -613,19 +645,34 @@ setup_dist_opts(Config) ->
++ "-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 "
+ case os:type() of
+ {win32, _} ->
+ "-proto_dist inet_tls "
+ ++ "-ssl_dist_opt server_certfile " ++ SKC ++ " "
+ ++ "-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 " ++ CKC ++ " "
+ ++ "-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 ";
+ _ ->
+ "-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
end,
MoreOpts = proplists:get_value(additional_dist_opts, Config, []),
DistOpts ++ MoreOpts.
@@ -682,7 +729,7 @@ add_ssl_opts_config(Config) ->
[{ssl_opts, "-boot " ++ Script} | Config]
catch
_:_ ->
- [{ssl_opts, "-pa " ++ filename:dirname(code:which(ssl))}
+ [{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.",
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 08c23b2d47..946865a3d8 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -48,7 +48,8 @@ decode_hello_handshake(_Config) ->
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, <<>>),
+ Version = {3, 0},
+ {Records, _Buffer} = ssl_handshake:get_tls_handshake(Version, HelloPacket, <<>>),
{Hello, _Data} = hd(Records),
#renegotiation_info{renegotiated_connection = <<0>>} = Hello#server_hello.renegotiation_info.
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 9d2599b778..8ce80cb725 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +53,7 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ catch crypto:stop(),
try crypto:start() of
ok ->
application:start(public_key),
@@ -121,15 +122,56 @@ end_per_testcase(_TestCase, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}
+ ].
+
+groups() ->
+ [{'tlsv1.2', [], packet_tests()},
+ {'tlsv1.1', [], packet_tests()},
+ {'tlsv1', [], packet_tests()},
+ {'sslv3', [], packet_tests()}].
+
+packet_tests() ->
+ active_packet_tests() ++ active_once_packet_tests() ++ passive_packet_tests() ++
+ [packet_send_to_large,
+ packet_cdr_decode, packet_cdr_decode_list,
+ packet_http_decode, packet_http_decode_list,
+ packet_http_bin_decode_multi,
+ packet_line_decode, packet_line_decode_list,
+ packet_asn1_decode, packet_asn1_decode_list,
+ packet_tpkt_decode, packet_tpkt_decode_list,
+ packet_sunrm_decode, packet_sunrm_decode_list].
+
+passive_packet_tests() ->
[packet_raw_passive_many_small,
packet_0_passive_many_small,
packet_1_passive_many_small,
packet_2_passive_many_small,
packet_4_passive_many_small,
- packet_raw_passive_some_big, packet_0_passive_some_big,
- packet_1_passive_some_big, packet_2_passive_some_big,
+ packet_raw_passive_some_big,
+ packet_0_passive_some_big,
+ packet_1_passive_some_big,
+ packet_2_passive_some_big,
packet_4_passive_some_big,
- packet_raw_active_once_many_small,
+ packet_httph_passive,
+ packet_httph_bin_passive,
+ packet_http_error_passive,
+ packet_wait_passive,
+ packet_size_passive,
+ packet_baddata_passive,
+ %% inet header option should be deprecated!
+ header_decode_one_byte_passive,
+ header_decode_two_bytes_passive,
+ header_decode_two_bytes_two_sent_passive,
+ header_decode_two_bytes_one_sent_passive
+ ].
+
+active_once_packet_tests() ->
+ [packet_raw_active_once_many_small,
packet_0_active_once_many_small,
packet_1_active_once_many_small,
packet_2_active_once_many_small,
@@ -139,34 +181,49 @@ all() ->
packet_1_active_once_some_big,
packet_2_active_once_some_big,
packet_4_active_once_some_big,
- packet_raw_active_many_small,
- packet_0_active_many_small, packet_1_active_many_small,
- packet_2_active_many_small, packet_4_active_many_small,
- packet_raw_active_some_big, packet_0_active_some_big,
- packet_1_active_some_big, packet_2_active_some_big,
- packet_4_active_some_big, packet_send_to_large,
- packet_wait_passive, packet_wait_active,
- packet_baddata_passive, packet_baddata_active,
- packet_size_passive, packet_size_active,
- packet_cdr_decode, packet_cdr_decode_list,
- packet_http_decode, packet_http_decode_list,
- packet_http_bin_decode_multi, packet_http_error_passive,
- packet_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,
- packet_sunrm_decode, packet_sunrm_decode_list,
- header_decode_one_byte, header_decode_two_bytes,
- header_decode_two_bytes_one_sent,
- header_decode_two_bytes_two_sent].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ packet_httph_active_once,
+ packet_httph_bin_active_once
+ ].
+
+active_packet_tests() ->
+ [packet_raw_active_many_small,
+ packet_0_active_many_small,
+ packet_1_active_many_small,
+ packet_2_active_many_small,
+ packet_4_active_many_small,
+ packet_raw_active_some_big,
+ packet_0_active_some_big,
+ packet_1_active_some_big,
+ packet_2_active_some_big,
+ packet_4_active_some_big,
+ packet_httph_active,
+ packet_httph_bin_active,
+ packet_wait_active,
+ packet_baddata_active,
+ packet_size_active,
+ %% inet header option should be deprecated!
+ header_decode_one_byte_active,
+ header_decode_two_bytes_active,
+ header_decode_two_bytes_two_sent_active,
+ header_decode_two_bytes_one_sent_active
+ ].
+
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
end_per_group(_GroupName, Config) ->
Config.
@@ -2425,11 +2482,11 @@ packet_sunrm_decode_list(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-header_decode_one_byte(doc) ->
+header_decode_one_byte_active(doc) ->
["Test setting the packet option {header, 1}"];
-header_decode_one_byte(suite) ->
+header_decode_one_byte_active(suite) ->
[];
-header_decode_one_byte(Config) when is_list(Config) ->
+header_decode_one_byte_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),
@@ -2438,7 +2495,7 @@ header_decode_one_byte(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, server_header_decode,
+ {mfa, {?MODULE, server_header_decode_active,
[Data, [11 | <<"Hello world">>]]}},
{options, [{active, true}, binary,
{header,1}|ServerOpts]}]),
@@ -2447,7 +2504,7 @@ header_decode_one_byte(Config) when is_list(Config) ->
Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, client_header_decode,
+ {mfa, {?MODULE, client_header_decode_active,
[Data, [11 | <<"Hello world">> ]]}},
{options, [{active, true}, {header, 1},
binary | ClientOpts]}]),
@@ -2459,11 +2516,11 @@ header_decode_one_byte(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-header_decode_two_bytes(doc) ->
+header_decode_two_bytes_active(doc) ->
["Test setting the packet option {header, 2}"];
-header_decode_two_bytes(suite) ->
+header_decode_two_bytes_active(suite) ->
[];
-header_decode_two_bytes(Config) when is_list(Config) ->
+header_decode_two_bytes_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),
@@ -2472,7 +2529,7 @@ header_decode_two_bytes(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, server_header_decode,
+ {mfa, {?MODULE, server_header_decode_active,
[Data, [11, $H | <<"ello world">> ]]}},
{options, [{active, true}, binary,
{header,2}|ServerOpts]}]),
@@ -2481,7 +2538,7 @@ header_decode_two_bytes(Config) when is_list(Config) ->
Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, client_header_decode,
+ {mfa, {?MODULE, client_header_decode_active,
[Data, [11, $H | <<"ello world">> ]]}},
{options, [{active, true}, {header, 2},
binary | ClientOpts]}]),
@@ -2494,11 +2551,11 @@ header_decode_two_bytes(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-header_decode_two_bytes_two_sent(doc) ->
- ["Test setting the packet option {header, 2} and sending on byte"];
-header_decode_two_bytes_two_sent(suite) ->
+header_decode_two_bytes_two_sent_active(doc) ->
+ ["Test setting the packet option {header, 2} and sending two byte"];
+header_decode_two_bytes_two_sent_active(suite) ->
[];
-header_decode_two_bytes_two_sent(Config) when is_list(Config) ->
+header_decode_two_bytes_two_sent_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),
@@ -2507,8 +2564,8 @@ header_decode_two_bytes_two_sent(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, server_header_decode,
- [Data, [$H, $e | <<>> ]]}},
+ {mfa, {?MODULE, server_header_decode_active,
+ [Data, [$H, $e]]}},
{options, [{active, true}, binary,
{header,2}|ServerOpts]}]),
@@ -2516,8 +2573,8 @@ header_decode_two_bytes_two_sent(Config) when is_list(Config) ->
Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, client_header_decode,
- [Data, [$H, $e | <<>> ]]}},
+ {mfa, {?MODULE, client_header_decode_active,
+ [Data, [$H, $e]]}},
{options, [{active, true}, {header, 2},
binary | ClientOpts]}]),
@@ -2529,11 +2586,11 @@ header_decode_two_bytes_two_sent(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-header_decode_two_bytes_one_sent(doc) ->
- ["Test setting the packet option {header, 2} and sending on byte"];
-header_decode_two_bytes_one_sent(suite) ->
+header_decode_two_bytes_one_sent_active(doc) ->
+ ["Test setting the packet option {header, 2} and sending one byte"];
+header_decode_two_bytes_one_sent_active(suite) ->
[];
-header_decode_two_bytes_one_sent(Config) when is_list(Config) ->
+header_decode_two_bytes_one_sent_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),
@@ -2542,7 +2599,7 @@ header_decode_two_bytes_one_sent(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, server_header_decode,
+ {mfa, {?MODULE, server_header_decode_active,
[Data, "H"]}},
{options, [{active, true}, binary,
{header,2}|ServerOpts]}]),
@@ -2551,7 +2608,7 @@ header_decode_two_bytes_one_sent(Config) when is_list(Config) ->
Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, client_header_decode,
+ {mfa, {?MODULE, client_header_decode_active,
[Data, "H"]}},
{options, [{active, true}, {header, 2},
binary | ClientOpts]}]),
@@ -2561,6 +2618,143 @@ header_decode_two_bytes_one_sent(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+
+header_decode_one_byte_passive(doc) ->
+ ["Test setting the packet option {header, 1}"];
+header_decode_one_byte_passive(suite) ->
+ [];
+header_decode_one_byte_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),
+
+ Data = <<11:8, "Hello world">>,
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_header_decode_passive,
+ [Data, [11 | <<"Hello world">>]]}},
+ {options, [{active, false}, binary,
+ {header,1}|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_header_decode_passive,
+ [Data, [11 | <<"Hello world">> ]]}},
+ {options, [{active, false}, {header, 1},
+ binary | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+
+header_decode_two_bytes_passive(doc) ->
+ ["Test setting the packet option {header, 2}"];
+header_decode_two_bytes_passive(suite) ->
+ [];
+header_decode_two_bytes_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),
+
+ Data = <<11:8, "Hello world">>,
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_header_decode_passive,
+ [Data, [11, $H | <<"ello world">> ]]}},
+ {options, [{active, false}, binary,
+ {header,2}|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_header_decode_passive,
+ [Data, [11, $H | <<"ello world">> ]]}},
+ {options, [{active, false}, {header, 2},
+ binary | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
+
+header_decode_two_bytes_two_sent_passive(doc) ->
+ ["Test setting the packet option {header, 2} and sending two byte"];
+header_decode_two_bytes_two_sent_passive(suite) ->
+ [];
+header_decode_two_bytes_two_sent_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),
+
+ Data = <<"He">>,
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_header_decode_passive,
+ [Data, [$H, $e]]}},
+ {options, [{active, false}, binary,
+ {header,2}|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_header_decode_passive,
+ [Data, [$H, $e]]}},
+ {options, [{active, false}, {header, 2},
+ binary | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
+
+header_decode_two_bytes_one_sent_passive(doc) ->
+ ["Test setting the packet option {header, 2} and sending one byte"];
+header_decode_two_bytes_one_sent_passive(suite) ->
+ [];
+header_decode_two_bytes_one_sent_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),
+
+ Data = <<"H">>,
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_header_decode_passive,
+ [Data, "H"]}},
+ {options, [{active, false}, binary,
+ {header,2}|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_header_decode_passive,
+ [Data, "H"]}},
+ {options, [{active, false}, {header, 2},
+ binary | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
%% Internal functions
@@ -2626,6 +2820,13 @@ active_once_raw(_, _, 0, _) ->
ok;
active_once_raw(Socket, Data, N, Acc) ->
receive
+ {ssl, Socket, Byte} when length(Byte) == 1 ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, _} ->
+ ssl:setopts(Socket, [{active, once}]),
+ active_once_raw(Socket, Data, N-1, [])
+ end;
{ssl, Socket, Data} ->
ssl:setopts(Socket, [{active, once}]),
active_once_raw(Socket, Data, N-1, []);
@@ -2648,7 +2849,14 @@ active_once_packet(Socket,_, 0) ->
{other, Other, ssl:session_info(Socket), 0}
end;
active_once_packet(Socket, Data, N) ->
- receive
+ receive
+ {ssl, Socket, Byte} when length(Byte) == 1 ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, _} ->
+ ssl:setopts(Socket, [{active, once}]),
+ active_once_packet(Socket, Data, N-1)
+ end;
{ssl, Socket, Data} ->
ok
end,
@@ -2662,6 +2870,11 @@ active_raw(_Socket, _, 0, _) ->
ok;
active_raw(Socket, Data, N, Acc) ->
receive
+ {ssl, Socket, Byte} when length(Byte) == 1 ->
+ receive
+ {ssl, Socket, _} ->
+ active_raw(Socket, Data, N -1)
+ end;
{ssl, Socket, Data} ->
active_raw(Socket, Data, N-1, []);
{ssl, Socket, Other} ->
@@ -2682,6 +2895,11 @@ active_packet(Socket, _, 0) ->
end;
active_packet(Socket, Data, N) ->
receive
+ {ssl, Socket, Byte} when length(Byte) == 1 ->
+ receive
+ {ssl, Socket, _} ->
+ active_packet(Socket, Data, N -1)
+ end;
{ssl, Socket, Data} ->
active_packet(Socket, Data, N -1);
Other ->
@@ -2723,29 +2941,52 @@ client_packet_decode(Socket, P1, P2, Packet) ->
Other2 -> exit({?LINE, Other2})
end.
-server_header_decode(Socket, Packet, Result) ->
+server_header_decode_active(Socket, Packet, Result) ->
receive
- {ssl, Socket, Result} -> ok;
- Other1 -> exit({?LINE, Other1})
- end,
- ok = ssl:send(Socket, Packet),
- receive
- {ssl, Socket, Result} -> ok;
- Other2 -> exit({?LINE, Other2})
+ {ssl, Socket, Result} ->
+ ok;
+ {ssl, Socket, Other1} ->
+ check_header_result(Result, Other1)
end,
ok = ssl:send(Socket, Packet).
-client_header_decode(Socket, Packet, Result) ->
+client_header_decode_active(Socket, Packet, Result) ->
ok = ssl:send(Socket, Packet),
receive
- {ssl, Socket, Result} -> ok;
- Other1 -> exit({?LINE, Other1})
+ {ssl, Socket, Result} ->
+ ok;
+ {ssl, Socket, Other1} ->
+ check_header_result(Result, Other1)
+ end.
+
+server_header_decode_passive(Socket, Packet, Result) ->
+ case ssl:recv(Socket, 0) of
+ {ok, Result} ->
+ ok;
+ {ok, Other} ->
+ check_header_result(Result, Other)
end,
+ ok = ssl:send(Socket, Packet).
+
+client_header_decode_passive(Socket, Packet, Result) ->
ok = ssl:send(Socket, Packet),
- receive
- {ssl, Socket, Result} -> ok;
- Other2 -> exit({?LINE, Other2})
+
+ case ssl:recv(Socket, 0) of
+ {ok, Result} ->
+ ok;
+ {ok, Other} ->
+ check_header_result(Result, Other)
end.
+
+%% The inet header option is a broken option as it does not buffer until it gets enough data.
+%% This check only checks that it has the same behavior as inet, but it is a quite useless
+%% option and the bitsynax makes it obsolete!
+check_header_result([Byte1 | _], [Byte1]) ->
+ ok;
+check_header_result([Byte1, Byte2 | _], [Byte1, Byte2]) ->
+ ok;
+check_header_result(_,Got) ->
+ exit({?LINE, Got}).
server_line_packet_decode(Socket, Packet) when is_binary(Packet) ->
[L1, L2] = string:tokens(binary_to_list(Packet), "\n"),
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index 24e86b3913..c97f97e70b 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,7 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ catch crypto:stop(),
try crypto:start() of
ok ->
application:start(public_key),
@@ -102,23 +103,56 @@ end_per_testcase(_TestCase, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.2', [], payload_tests()},
+ {'tlsv1.1', [], payload_tests()},
+ {'tlsv1', [], payload_tests()},
+ {'sslv3', [], payload_tests()}
+ ].
+
+payload_tests() ->
[server_echos_passive_small,
server_echos_active_once_small,
- server_echos_active_small, client_echos_passive_small,
+ server_echos_active_small,
+ client_echos_passive_small,
client_echos_active_once_small,
- client_echos_active_small, server_echos_passive_big,
- server_echos_active_once_big, server_echos_active_big,
- client_echos_passive_big, client_echos_active_once_big,
- client_echos_active_big, server_echos_passive_huge,
- server_echos_active_once_huge, server_echos_active_huge,
+ client_echos_active_small,
+ server_echos_passive_big,
+ server_echos_active_once_big,
+ server_echos_active_big,
+ client_echos_passive_big,
+ client_echos_active_once_big,
+ client_echos_active_big,
+ server_echos_passive_huge,
+ server_echos_active_once_huge,
+ server_echos_active_huge,
client_echos_passive_huge,
- client_echos_active_once_huge, client_echos_active_huge].
+ client_echos_active_once_huge,
+ client_echos_active_huge].
-groups() ->
- [].
-init_per_group(_GroupName, Config) ->
- Config.
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
end_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 5ea45018e6..6d758ecb01 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -49,6 +49,7 @@
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2),
+ catch crypto:stop(),
try crypto:start() of
ok ->
application:start(public_key),
@@ -210,7 +211,7 @@ session_cleanup(Config)when is_list(Config) ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
- State = state(Prop),
+ State = ssl_test_lib:state(Prop),
Cache = element(2, State),
SessionTimer = element(6, State),
@@ -225,11 +226,12 @@ session_cleanup(Config)when is_list(Config) ->
check_timer(SessionTimer),
test_server:sleep(?DELAY *2), %% Delay time + some extra time
- DelayTimer = get_delay_timer(),
+ {ServerDelayTimer, ClientDelayTimer} = get_delay_timers(),
- check_timer(DelayTimer),
+ check_timer(ServerDelayTimer),
+ check_timer(ClientDelayTimer),
- test_server:sleep(?SLEEP), %% Make sure clean has had to run
+ test_server:sleep(?SLEEP), %% Make sure clean has had time to run
undefined = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}),
undefined = ssl_session_cache:lookup(Cache, {Port, Id}),
@@ -238,31 +240,34 @@ session_cleanup(Config)when is_list(Config) ->
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)),
+ timer:sleep(?SLEEP),
+ {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
ok;
Int ->
test_server:sleep(Int),
check_timer(Timer)
end.
-get_delay_timer() ->
+get_delay_timers() ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
- State = state(Prop),
+ State = ssl_test_lib:state(Prop),
case element(7, State) of
- undefined ->
+ {undefined, undefined} ->
+ test_server:sleep(?SLEEP),
+ get_delay_timers();
+ {undefined, _} ->
+ test_server:sleep(?SLEEP),
+ get_delay_timers();
+ {_, undefined} ->
test_server:sleep(?SLEEP),
- get_delay_timer();
- DelayTimer ->
- DelayTimer
+ get_delay_timers();
+ DelayTimers ->
+ DelayTimers
end.
%%--------------------------------------------------------------------
session_cache_process_list(doc) ->
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index b7916b96eb..b39c995552 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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 @@
-include("test_server.hrl").
-include("test_server_line.hrl").
+-include_lib("public_key/include/public_key.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -661,6 +662,9 @@ cipher_result(Socket, Result) ->
%% to properly test "cipher state" handling
ssl:send(Socket, "Hello\n"),
receive
+ {ssl, Socket, "H"} ->
+ ssl:send(Socket, " world\n"),
+ receive_rizzo_duong_beast();
{ssl, Socket, "Hello\n"} ->
ssl:send(Socket, " world\n"),
receive
@@ -673,3 +677,64 @@ cipher_result(Socket, Result) ->
session_info_result(Socket) ->
ssl:session_info(Socket).
+
+
+public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
+ privateKey = Key}) ->
+ public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key));
+
+public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-dsa'},
+ privateKey = Key}) ->
+ public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key));
+public_key(Key) ->
+ Key.
+receive_rizzo_duong_beast() ->
+ receive
+ {ssl, _, "ello\n"} ->
+ receive
+ {ssl, _, " "} ->
+ receive
+ {ssl, _, "world\n"} ->
+ ok
+ end
+ end
+ end.
+
+state([{data,[{"State", State}]} | _]) ->
+ State;
+state([{data,[{"StateData", State}]} | _]) ->
+ State;
+state([_ | Rest]) ->
+ state(Rest).
+
+is_tls_version('tlsv1.2') ->
+ true;
+is_tls_version('tlsv1.1') ->
+ true;
+is_tls_version('tlsv1') ->
+ true;
+is_tls_version('sslv3') ->
+ true;
+is_tls_version(_) ->
+ false.
+
+init_tls_version(Version) ->
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, protocol_version, Version),
+ ssl:start().
+
+sufficient_crypto_support('tlsv1.2') ->
+ Data = "Sampl",
+ Data2 = "e #1",
+ Key = <<0,1,2,3,16,17,18,19,32,33,34,35,48,49,50,51,4,5,6,7,20,21,22,23,36,37,38,39,
+ 52,53,54,55,8,9,10,11,24,25,26,27,40,41,42,43,56,57,58,59>>,
+ try
+ crypto:sha256_mac(Key, lists:flatten([Data, Data2])),
+ true
+ catch _:_ -> false
+ end;
+sufficient_crypto_support(_) ->
+ true.
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 64a6a9eaf8..d446014f7b 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +50,7 @@ init_per_suite(Config0) ->
false ->
{skip, "Openssl not found"};
_ ->
+ catch crypto:stop(),
try crypto:start() of
ok ->
application:start(public_key),
@@ -106,9 +107,13 @@ init_per_testcase(TestCase, Config0) ->
special_init(TestCase, Config)
when TestCase == erlang_client_openssl_server_renegotiate;
TestCase == erlang_client_openssl_server_no_wrap_sequence_number;
- TestCase == erlang_server_openssl_client_no_wrap_sequence_number ->
+ TestCase == erlang_server_openssl_client_no_wrap_sequence_number
+ ->
check_sane_openssl_renegotaite(Config);
+special_init(ssl2_erlang_server_openssl_client, Config) ->
+ check_sane_openssl_sslv2(Config);
+
special_init(_, Config) ->
Config.
@@ -146,36 +151,59 @@ end_per_testcase(_, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [erlang_client_openssl_server,
+ [
+ {group, basic},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}
+ ].
+
+groups() ->
+ [{basic, [], basic_tests()},
+ {'tlsv1.2', [], all_versions_tests()},
+ {'tlsv1.1', [], all_versions_tests()},
+ {'tlsv1', [], all_versions_tests()},
+ {'sslv3', [], all_versions_tests()}].
+
+basic_tests() ->
+ [basic_erlang_client_openssl_server,
+ basic_erlang_server_openssl_client,
+ expired_session].
+
+all_versions_tests() ->
+ [
+ erlang_client_openssl_server,
erlang_server_openssl_client,
- tls1_erlang_client_openssl_server_dsa_cert,
- tls1_erlang_server_openssl_client_dsa_cert,
- ssl3_erlang_client_openssl_server_dsa_cert,
- ssl3_erlang_server_openssl_client_dsa_cert,
+ erlang_client_openssl_server_dsa_cert,
+ erlang_server_openssl_client_dsa_cert,
erlang_server_openssl_client_reuse_session,
erlang_client_openssl_server_renegotiate,
erlang_client_openssl_server_no_wrap_sequence_number,
erlang_server_openssl_client_no_wrap_sequence_number,
erlang_client_openssl_server_no_server_ca_cert,
- ssl3_erlang_client_openssl_server,
- ssl3_erlang_server_openssl_client,
- ssl3_erlang_client_openssl_server_client_cert,
- ssl3_erlang_server_openssl_client_client_cert,
- ssl3_erlang_server_erlang_client_client_cert,
- tls1_erlang_client_openssl_server,
- tls1_erlang_server_openssl_client,
- tls1_erlang_client_openssl_server_client_cert,
- tls1_erlang_server_openssl_client_client_cert,
- tls1_erlang_server_erlang_client_client_cert,
- ciphers_rsa_signed_certs, ciphers_dsa_signed_certs,
- erlang_client_bad_openssl_server, expired_session,
- ssl2_erlang_server_openssl_client].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ erlang_client_openssl_server_client_cert,
+ erlang_server_openssl_client_client_cert,
+ ciphers_rsa_signed_certs,
+ ciphers_dsa_signed_certs,
+ erlang_client_bad_openssl_server,
+ ssl2_erlang_server_openssl_client
+ ].
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName),
+ Config;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
end_per_group(_GroupName, Config) ->
Config.
@@ -183,12 +211,11 @@ end_per_group(_GroupName, Config) ->
%% Test cases starts here.
%%--------------------------------------------------------------------
-
-erlang_client_openssl_server(doc) ->
+basic_erlang_client_openssl_server(doc) ->
["Test erlang client with openssl server"];
-erlang_client_openssl_server(suite) ->
+basic_erlang_client_openssl_server(suite) ->
[];
-erlang_client_openssl_server(Config) when is_list(Config) ->
+basic_erlang_client_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ServerOpts = ?config(server_opts, Config),
ClientOpts = ?config(client_opts, Config),
@@ -200,8 +227,8 @@ erlang_client_openssl_server(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile,
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -222,18 +249,16 @@ erlang_client_openssl_server(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
-
%%--------------------------------------------------------------------
-erlang_server_openssl_client(doc) ->
+basic_erlang_server_openssl_client(doc) ->
["Test erlang server with openssl client"];
-erlang_server_openssl_client(suite) ->
+basic_erlang_server_openssl_client(suite) ->
[];
-erlang_server_openssl_client(Config) when is_list(Config) ->
+basic_erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ServerOpts = ?config(server_opts, Config),
@@ -246,8 +271,8 @@ erlang_server_openssl_client(Config) when is_list(Config) ->
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
+
+ Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
" -host localhost",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -256,36 +281,32 @@ erlang_server_openssl_client(Config) when is_list(Config) ->
port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
-
- ssl_test_lib:close(Server),
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
-
-%%--------------------------------------------------------------------
-
-tls1_erlang_client_openssl_server_dsa_cert(doc) ->
- ["Test erlang server with openssl client"];
-tls1_erlang_client_openssl_server_dsa_cert(suite) ->
+%%--------------------------------------------------------------------
+erlang_client_openssl_server(doc) ->
+ ["Test erlang client with openssl server"];
+erlang_client_openssl_server(suite) ->
[];
-tls1_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
+erlang_client_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = ?config(client_dsa_opts, Config),
- ServerOpts = ?config(server_dsa_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ ClientOpts = ?config(client_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
+
Data = "From openssl to erlang",
Port = ssl_test_lib:inet_port(node()),
- CaCertFile = proplists:get_value(cacertfile, ServerOpts),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -Verify 2 -tls1 -msg",
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
+ " -cert " ++ CertFile ++ " -key " ++ KeyFile,
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -299,45 +320,39 @@ tls1_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
{mfa, {?MODULE,
erlang_ssl_receive, [Data]}},
{options, ClientOpts}]),
-
port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Client, ok),
-
+ ssl_test_lib:check_result(Client, ok),
+
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
-%%--------------------------------------------------------------------
-tls1_erlang_server_openssl_client_dsa_cert(doc) ->
+%%--------------------------------------------------------------------
+erlang_server_openssl_client(doc) ->
["Test erlang server with openssl client"];
-tls1_erlang_server_openssl_client_dsa_cert(suite) ->
+erlang_server_openssl_client(suite) ->
[];
-tls1_erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
+erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = ?config(client_dsa_opts, Config),
- ServerOpts = ?config(server_dsa_verify_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
- CaCertFile = proplists:get_value(cacertfile, ClientOpts),
- CertFile = proplists:get_value(certfile, ClientOpts),
- KeyFile = proplists:get_value(keyfile, ClientOpts),
-
+
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
- " -host localhost " ++ " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -tls1 -msg",
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+
+ Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++
+ " -host localhost",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -345,20 +360,20 @@ tls1_erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
-
- ssl_test_lib:close(Server),
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
-ssl3_erlang_client_openssl_server_dsa_cert(doc) ->
+erlang_client_openssl_server_dsa_cert(doc) ->
["Test erlang server with openssl client"];
-ssl3_erlang_client_openssl_server_dsa_cert(suite) ->
+erlang_client_openssl_server_dsa_cert(suite) ->
[];
-ssl3_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
+erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ClientOpts = ?config(client_dsa_opts, Config),
ServerOpts = ?config(server_dsa_opts, Config),
@@ -371,10 +386,11 @@ ssl3_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
CaCertFile = proplists:get_value(cacertfile, ServerOpts),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -Verify 2 -ssl3 -msg",
+ ++ " -key " ++ KeyFile ++ " -Verify 2 -msg",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -395,53 +411,49 @@ ssl3_erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
-
-%%--------------------------------------------------------------------
-
-ssl3_erlang_server_openssl_client_dsa_cert(doc) ->
+%%--------------------------------------------------------------------
+erlang_server_openssl_client_dsa_cert(doc) ->
["Test erlang server with openssl client"];
-ssl3_erlang_server_openssl_client_dsa_cert(suite) ->
+erlang_server_openssl_client_dsa_cert(suite) ->
[];
-ssl3_erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
+erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ClientOpts = ?config(client_dsa_opts, Config),
- ServerOpts = ?config(server_dsa_verify_opts, Config),
+ ServerOpts = ?config(server_dsa_verify_opts, Config),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
+
Data = "From openssl to erlang",
CaCertFile = proplists:get_value(cacertfile, ClientOpts),
CertFile = proplists:get_value(certfile, ClientOpts),
KeyFile = proplists:get_value(keyfile, ClientOpts),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, ServerOpts}]),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
- " -host localhost " ++ " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -ssl3 -msg",
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++
+ " -host localhost " ++ " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
+ ++ " -key " ++ KeyFile ++ " -msg",
test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+
+ OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
port_command(OpenSslPort, Data),
-
+
ssl_test_lib:check_result(Server, ok),
-
- ssl_test_lib:close(Server),
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
-
%%--------------------------------------------------------------------
erlang_server_openssl_client_reuse_session(doc) ->
@@ -463,8 +475,8 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
{reconnect_times, 5},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -host localhost -reconnect",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -475,8 +487,8 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -500,8 +512,9 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -525,7 +538,6 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -552,8 +564,8 @@ erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -574,7 +586,6 @@ erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -601,10 +612,10 @@ erlang_server_openssl_client_no_wrap_sequence_number(Config) when is_list(Config
{from, self()},
{mfa, {ssl_test_lib,
trigger_renegotiate, [[Data, N+2]]}},
- {options, [{renegotiate_at, N} | ServerOpts]}]),
+ {options, [{renegotiate_at, N}, {reuse_sessions, false} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -host localhost -msg",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -615,8 +626,8 @@ erlang_server_openssl_client_no_wrap_sequence_number(Config) when is_list(Config
ssl_test_lib:check_result(Server, ok),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -640,8 +651,8 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -663,89 +674,16 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
%% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
-
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
-ssl3_erlang_client_openssl_server(doc) ->
- ["Test erlang client with openssl server"];
-ssl3_erlang_client_openssl_server(suite) ->
- [];
-ssl3_erlang_client_openssl_server(Config) when is_list(Config) ->
- ServerOpts = ?config(server_opts, Config),
- ClientOpts = ?config(client_opts, Config),
-
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- Port = ssl_test_lib:inet_port(node()),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -ssl3",
-
- test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
- wait_for_openssl_server(),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- connection_info, [sslv3]}},
- {options,
- [{versions, [sslv3]} | ClientOpts]}]),
- ssl_test_lib:check_result(Client, ok),
-
- ssl_test_lib:close(Client),
- %% Clean close down!
- close_port(OpensslPort),
- test_server:sleep(?SLEEP),
- ok.
-
-%%--------------------------------------------------------------------
-
-ssl3_erlang_server_openssl_client(doc) ->
- ["Test erlang server with openssl client"];
-ssl3_erlang_server_openssl_client(suite) ->
- [];
-ssl3_erlang_server_openssl_client(Config) when is_list(Config) ->
- ServerOpts = ?config(server_opts, Config),
-
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, connection_info, [sslv3]}},
- {options,
- [{versions, [sslv3]} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
- " -host localhost -ssl3",
-
- test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
- ssl_test_lib:check_result(Server, ok),
-
- close_port(OpenSslPort), %% openssl server first
- ssl_test_lib:close(Server),
- test_server:sleep(?SLEEP),
- ok.
-
-%%--------------------------------------------------------------------
-ssl3_erlang_client_openssl_server_client_cert(doc) ->
+erlang_client_openssl_server_client_cert(doc) ->
["Test erlang client with openssl server when client sends cert"];
-ssl3_erlang_client_openssl_server_client_cert(suite) ->
+erlang_client_openssl_server_client_cert(suite) ->
[];
-ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
+erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ServerOpts = ?config(server_verification_opts, Config),
ClientOpts = ?config(client_verification_opts, Config),
@@ -758,10 +696,10 @@ ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
CaCertFile = proplists:get_value(cacertfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -Verify 2 -ssl3",
+ ++ " -key " ++ KeyFile ++ " -Verify 2",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -779,7 +717,7 @@ ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Client, ok),
- %% Clean close down!
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
@@ -787,11 +725,11 @@ ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-ssl3_erlang_server_openssl_client_client_cert(doc) ->
+erlang_server_openssl_client_client_cert(doc) ->
["Test erlang server with openssl client when client sends cert"];
-ssl3_erlang_server_openssl_client_client_cert(suite) ->
+erlang_server_openssl_client_client_cert(suite) ->
[];
-ssl3_erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
+erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ServerOpts = ?config(server_verification_opts, Config),
ClientOpts = ?config(client_verification_opts, Config),
@@ -812,10 +750,10 @@ ssl3_erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
CaCertFile = proplists:get_value(cacertfile, ClientOpts),
CertFile = proplists:get_value(certfile, ClientOpts),
KeyFile = proplists:get_value(keyfile, ClientOpts),
-
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
Cmd = "openssl s_client -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -port " ++ integer_to_list(Port) ++
- " -host localhost -ssl3",
+ ++ " -key " ++ KeyFile ++ " -port " ++ integer_to_list(Port) ++ version_flag(Version) ++
+ " -host localhost",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -824,24 +762,24 @@ ssl3_erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok),
- close_port(OpenSslPort), %% openssl server first
+ %% Clean close down! Server needs to be closed first !!
+ close_port(OpenSslPort),
ssl_test_lib:close(Server),
- %% Clean close down!
process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
-ssl3_erlang_server_erlang_client_client_cert(doc) ->
+erlang_server_erlang_client_client_cert(doc) ->
["Test erlang server with erlang client when client sends cert"];
-ssl3_erlang_server_erlang_client_client_cert(suite) ->
+erlang_server_erlang_client_client_cert(suite) ->
[];
-ssl3_erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
+erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ServerOpts = ?config(server_verification_opts, Config),
ClientOpts = ?config(client_verification_opts, Config),
-
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From erlang to erlang",
@@ -849,7 +787,9 @@ ssl3_erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {?MODULE,
- erlang_ssl_receive, [Data]}},
+ erlang_ssl_receive,
+ %% Due to 1/n-1 splitting countermeasure Rizzo/Duong-Beast
+ [Data]}},
{options,
[{verify , verify_peer}
| ServerOpts]}]),
@@ -858,9 +798,10 @@ ssl3_erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
+ %% Due to 1/n-1 splitting countermeasure Rizzo/Duong-Beast
{mfa, {ssl, send, [Data]}},
{options,
- [{versions, [sslv3]} | ClientOpts]}]),
+ [{versions, [Version]} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -868,216 +809,8 @@ ssl3_erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
-
-%%--------------------------------------------------------------------
-
-tls1_erlang_client_openssl_server(doc) ->
- ["Test erlang client with openssl server"];
-tls1_erlang_client_openssl_server(suite) ->
- [];
-tls1_erlang_client_openssl_server(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ?config(server_opts, Config),
- ClientOpts = ?config(client_opts, Config),
-
-
- test_server:format("Server Opts", [ServerOpts]),
-
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- Port = ssl_test_lib:inet_port(node()),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -tls1",
-
- test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
- wait_for_openssl_server(),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- connection_info, [tlsv1]}},
- {options,
- [{versions, [tlsv1]} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok),
-
- ssl_test_lib:close(Client),
- %% Clean close down!
- close_port(OpensslPort),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-
-tls1_erlang_server_openssl_client(doc) ->
- ["Test erlang server with openssl client"];
-tls1_erlang_server_openssl_client(suite) ->
- [];
-tls1_erlang_server_openssl_client(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ?config(server_opts, Config),
-
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, connection_info, [tlsv1]}},
- {options,
- [{versions, [tlsv1]} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
- " -host localhost -tls1",
-
- test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
- ssl_test_lib:check_result(Server, ok),
-
- %% Clean close down!
- close_port(OpenSslPort),
- ssl_test_lib:close(Server),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-
-tls1_erlang_client_openssl_server_client_cert(doc) ->
- ["Test erlang client with openssl server when client sends cert"];
-tls1_erlang_client_openssl_server_client_cert(suite) ->
- [];
-tls1_erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ?config(server_verification_opts, Config),
- ClientOpts = ?config(client_verification_opts, Config),
-
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Port = ssl_test_lib:inet_port(node()),
- CaCertFile = proplists:get_value(cacertfile, ServerOpts),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -Verify 2 -tls1",
-
- test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
- wait_for_openssl_server(),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive, [Data]}},
- {options, ClientOpts}]),
- port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok),
-
- %% Clean close down!
- close_port(OpensslPort),
- ssl_test_lib:close(Client),
- process_flag(trap_exit, false),
- ok.
-
%%--------------------------------------------------------------------
-tls1_erlang_server_openssl_client_client_cert(doc) ->
- ["Test erlang server with openssl client when client sends cert"];
-tls1_erlang_server_openssl_client_client_cert(suite) ->
- [];
-tls1_erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ?config(server_verification_opts, Config),
- ClientOpts = ?config(client_verification_opts, Config),
-
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive, [Data]}},
- {options,
- [{verify , verify_peer}
- | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- CaCertFile = proplists:get_value(cacertfile, ClientOpts),
- CertFile = proplists:get_value(certfile, ClientOpts),
- KeyFile = proplists:get_value(keyfile, ClientOpts),
-
- Cmd = "openssl s_client -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -port " ++ integer_to_list(Port) ++
- " -host localhost -tls1",
-
- test_server:format("openssl cmd: ~p~n", [Cmd]),
-
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
- port_command(OpenSslPort, Data),
-
- ssl_test_lib:check_result(Server, ok),
-
- %% Clean close down!
- close_port(OpenSslPort),
- ssl_test_lib:close(Server),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-tls1_erlang_server_erlang_client_client_cert(doc) ->
- ["Test erlang server with erlang client when client sends cert"];
-tls1_erlang_server_erlang_client_client_cert(suite) ->
- [];
-tls1_erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ?config(server_verification_opts, Config),
- ClientOpts = ?config(client_verification_opts, Config),
-
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From erlang to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive, [Data]}},
- {options,
- [{verify , verify_peer}
- | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl, send, [Data]}},
- {options,
- [{versions, [tlsv1]} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- %% Clean close down!
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-
ciphers_rsa_signed_certs(doc) ->
["Test cipher suites that uses rsa certs"];
@@ -1136,7 +869,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -1171,8 +904,8 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
Result = ssl_test_lib:wait_for_result(Client, ok),
+ %% Clean close down! Server needs to be closed first !!
close_port(OpenSslPort),
- %% Clean close down!
ssl_test_lib:close(Client),
Return = case Result of
@@ -1199,26 +932,26 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
-
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++
+ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
+
test_server:format("openssl cmd: ~p~n", [Cmd]),
OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
+
wait_for_openssl_server(),
Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, server_sent_garbage, []}},
- {options,
- [{versions, [tlsv1]} | ClientOpts]}]),
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, server_sent_garbage, []}},
+ {options,
+ [{versions, [Version]} | ClientOpts]}]),
%% Send garbage
port_command(OpensslPort, ?OPENSSL_GARBAGE),
-
+
test_server:sleep(?SLEEP),
Client0 ! server_sent_garbage,
@@ -1228,17 +961,16 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
ssl_test_lib:close(Client0),
%% Make sure openssl does not hang and leave zombie process
- Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result_msg, []}},
- {options,
- [{versions, [tlsv1]} | ClientOpts]}]),
-
- ssl_test_lib:close(Client1),
-
- %% Clean close down!
+ Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg, []}},
+ {options,
+ [{versions, [Version]} | ClientOpts]}]),
+
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
+ ssl_test_lib:close(Client1),
process_flag(trap_exit, false),
ok.
@@ -1260,8 +992,8 @@ expired_session(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
+
+ Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
" -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
test_server:format("openssl cmd: ~p~n", [Cmd]),
@@ -1297,6 +1029,7 @@ expired_session(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{from, self()}, {options, ClientOpts}]),
+ %% Clean close down! Server needs to be closed first !!
close_port(OpensslPort),
ssl_test_lib:close(Client2),
process_flag(trap_exit, false).
@@ -1329,8 +1062,8 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, {error,"protocol version"}),
+ %% Clean close down! Server needs to be closed first !!
ssl_test_lib:close(Server),
-
close_port(OpenSslPort),
process_flag(trap_exit, false),
ok.
@@ -1346,6 +1079,8 @@ erlang_ssl_receive(Socket, Data) ->
%% open_ssl server sometimes hangs waiting in blocking read
ssl:send(Socket, "Got it"),
ok;
+ {ssl, Socket, Byte} when length(Byte) == 1 ->
+ erlang_ssl_receive(Socket, tl(Data));
{Port, {data,Debug}} when is_port(Port) ->
io:format("openssl ~s~n",[Debug]),
erlang_ssl_receive(Socket,Data);
@@ -1423,13 +1158,46 @@ wait_for_openssl_server() ->
%% more so than sleep!)
test_server:sleep(?SLEEP)
end.
-
+
+version_flag(tlsv1) ->
+ " -tls1 ";
+version_flag('tlsv1.1') ->
+ " -tls1_1 ";
+version_flag('tlsv1.2') ->
+ " -tls1_2 ";
+version_flag(sslv3) ->
+ " -ssl3 ".
+
check_sane_openssl_renegotaite(Config) ->
case os:cmd("openssl version") of
"OpenSSL 0.9.8" ++ _ ->
- {skip, "Known renegotiation bug in OppenSSL"};
+ {skip, "Known renegotiation bug in OpenSSL"};
"OpenSSL 0.9.7" ++ _ ->
- {skip, "Known renegotiation bug in OppenSSL"};
+ {skip, "Known renegotiation bug in OpenSSL"};
_ ->
Config
end.
+
+check_sane_openssl_sslv2(Config) ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1." ++ _ ->
+ {skip, "sslv2 by default turned of in 1.*"};
+ _ ->
+ Config
+ end.
+
+check_sane_openssl_version(Version) ->
+ case {Version, os:cmd("openssl version")} of
+ {_, "OpenSSL 1.0.1" ++ _} ->
+ true;
+ {'tlsv1.2', "OpenSSL 1.0" ++ _} ->
+ false;
+ {'tlsv1.1', "OpenSSL 1.0" ++ _} ->
+ false;
+ {'tlsv1.2', "OpenSSL 0" ++ _} ->
+ false;
+ {'tlsv1.1', "OpenSSL 0" ++ _} ->
+ false;
+ {_, _} ->
+ true
+ end.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 8286201df4..e381b73c27 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 4.1.6
+SSL_VSN = 5.1
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 16e0a86e3b..c3138c4d9f 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -83,7 +83,6 @@ XML_REF3_FILES = \
queue.xml \
random.xml \
re.xml \
- regexp.xml \
sets.xml \
shell.xml \
shell_default.xml \
@@ -174,15 +173,15 @@ $(SPECDIR)/specs_erl_id_trans.xml:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
+ $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml
index 88ce77e0d0..7b8e279788 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>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -505,7 +505,7 @@
<type>
<v>Subject = binary()</v>
<v>Pos = integer() >= 0</v>
- <v>Len = integer() >= 0</v>
+ <v>Len = integer()</v>
</type>
<desc>
<p>The same as <c>part(Subject, {Pos, Len})</c>.</p>
diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml
index e44632bfd2..ef6e1cb46f 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>2011</year>
+ <year>2000</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -156,7 +156,7 @@
<p>Creates a digraph where the vertices are
the <seealso marker="#strong_components">strongly connected
components</seealso> of <c><anno>Digraph</anno></c> as returned by
- <c>strong_components/1</c>. If X and Y are strongly
+ <c>strong_components/1</c>. If X and Y are two different strongly
connected components, and there exist vertices x and y in X
and Y respectively such that there is an
edge <seealso marker="#emanate">emanating</seealso> from x
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index efd9514db6..487b06473f 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>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -671,7 +671,7 @@ ets:is_compiled_ms(Broken).</code>
<c>duplicate_bag</c>, the function returns a list of
arbitrary length.</p>
<p>Note that the time order of object insertions is preserved;
- The first object inserted with the given key will be first
+ the first object inserted with the given key will be first
in the resulting list, and so on.</p>
<p>Insert and look-up times in tables of type <c>set</c>,
<c>bag</c> and <c>duplicate_bag</c> are constant, regardless
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index bc3a616d39..9296319b83 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -295,6 +295,12 @@
<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>
+
+ <warning><p>We don't recommend using this function. If possible,
+ use <seealso marker="beam_lib">beam_lib(3)</seealso> to extract
+ the abstract code format from the BEAM file and compile that
+ instead.</p></warning>
+
<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
diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml
index 65c866efbe..9316d60b1a 100644
--- a/lib/stdlib/doc/src/gb_trees.xml
+++ b/lib/stdlib/doc/src/gb_trees.xml
@@ -132,15 +132,6 @@
</desc>
</func>
<func>
- <name name="lookup" arity="2"/>
- <fsummary>Look up a key in a tree</fsummary>
- <desc>
- <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 name="insert" arity="3"/>
<fsummary>Insert a new key and value in a tree</fsummary>
<desc>
@@ -196,6 +187,15 @@
</desc>
</func>
<func>
+ <name name="lookup" arity="2"/>
+ <fsummary>Look up a key in a tree</fsummary>
+ <desc>
+ <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 name="map" arity="2"/>
<fsummary>Return largest key and value</fsummary>
<desc><p>Maps the function F(<anno>K</anno>, <anno>V1</anno>) -> <anno>V2</anno> to all key-value pairs
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 24bcb419fe..1601ea9892 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>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -120,8 +120,10 @@ gen_event:stop -----> Module:terminate/2
<name>start_link(EventMgrName) -> Result</name>
<fsummary>Create a generic event manager process in a supervision tree.</fsummary>
<type>
- <v>EventMgrName = {local,Name} | {global,Name}</v>
+ <v>EventMgrName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Result = {ok,Pid} | {error,{already_started,Pid}}</v>
<v>&nbsp;Pid = pid()</v>
</type>
@@ -132,10 +134,17 @@ gen_event:stop -----> Module:terminate/2
the event manager is linked to the supervisor.</p>
<p>If <c>EventMgrName={local,Name}</c>, the event manager is
registered locally as <c>Name</c> using <c>register/2</c>.
- If <c>EventMgrName={global,Name}</c>, the event manager is
- registered globally as <c>Name</c> using
+ If <c>EventMgrName={global,GlobalName}</c>, the event manager is
+ registered globally as <c>GlobalName</c> using
<c>global:register_name/2</c>. If no name is provided,
- the event manager is not registered.</p>
+ the event manager is not registered.
+ If <c>EventMgrName={via,Module,ViaName}</c>, the event manager will
+ register with the registry represented by <c>Module</c>.
+ The <c>Module</c> callback should export the functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c> and <c>send/2</c>, which should behave like the
+ corresponding functions in <c>global</c>. Thus,
+ <c>{via,global,GlobalName}</c> is a valid reference.</p>
<p>If the event manager is successfully created the function
returns <c>{ok,Pid}</c>, where <c>Pid</c> is the pid of
the event manager. If there already exists a process with
@@ -149,8 +158,10 @@ gen_event:stop -----> Module:terminate/2
<name>start(EventMgrName) -> Result</name>
<fsummary>Create a stand-alone event manager process.</fsummary>
<type>
- <v>EventMgrName = {local,Name} | {global,Name}</v>
+ <v>EventMgrName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Result = {ok,Pid} | {error,{already_started,Pid}}</v>
<v>&nbsp;Pid = pid()</v>
</type>
@@ -166,8 +177,10 @@ gen_event:stop -----> Module:terminate/2
<name>add_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Add an event handler to a generic event manager.</fsummary>
<type>
- <v>EventMgr = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgr = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -185,8 +198,10 @@ gen_event:stop -----> Module:terminate/2
<item><c>Name</c>, if the event manager is locally registered,</item>
<item><c>{Name,Node}</c>, if the event manager is locally
registered at another node, or</item>
- <item><c>{global,Name}</c>, if the event manager is globally
+ <item><c>{global,GlobalName}</c>, if the event manager is globally
registered.</item>
+ <item><c>{via,Module,ViaName}</c>, if the event manager is registered
+ through an alternative process registry.</item>
</list>
<p><c>Handler</c> is the name of the callback module <c>Module</c> or
a tuple <c>{Module,Id}</c>, where <c>Id</c> is any term.
@@ -195,20 +210,23 @@ gen_event:stop -----> Module:terminate/2
handlers using the same 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>If <c>Module:init/1</c> returns a correct value, the event
- manager adds the event handler and this function returns
+ <p>If <c>Module:init/1</c> returns a correct value indicating
+ successful completion, the event manager adds the event
+ handler and this function returns
<c>ok</c>. If <c>Module:init/1</c> fails with <c>Reason</c> or
- returns an unexpected value <c>Term</c>, the event handler is
+ returns <c>{error,Reason}</c>, the event handler is
ignored and this function returns <c>{'EXIT',Reason}</c> or
- <c>Term</c>, respectively.</p>
+ <c>{error,Reason}</c>, respectively.</p>
</desc>
</func>
<func>
<name>add_sup_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Add a supervised event handler to a generic event manager.</fsummary>
<type>
- <v>EventMgr = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgr = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -252,8 +270,10 @@ gen_event:stop -----> Module:terminate/2
<name>sync_notify(EventMgrRef, Event) -> ok</name>
<fsummary>Notify an event manager about an event.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Event = term()</v>
</type>
<desc>
@@ -277,8 +297,10 @@ gen_event:stop -----> Module:terminate/2
<name>call(EventMgrRef, Handler, Request, Timeout) -> Result</name>
<fsummary>Make a synchronous call to a generic event manager.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -317,8 +339,10 @@ gen_event:stop -----> Module:terminate/2
<name>delete_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Delete an event handler from a generic event manager.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -345,8 +369,10 @@ gen_event:stop -----> Module:terminate/2
<name>swap_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result</name>
<fsummary>Replace an event handler in a generic event manager.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler1 = Handler2 = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -389,8 +415,10 @@ gen_event:stop -----> Module:terminate/2
<name>swap_sup_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result</name>
<fsummary>Replace an event handler in a generic event manager.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler1 = Handler 2 = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -411,8 +439,10 @@ gen_event:stop -----> Module:terminate/2
<name>which_handlers(EventMgrRef) -> [Handler]</name>
<fsummary>Return all event handlers installed in a generic event manager.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Handler = Module | {Module,Id}</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Id = term()</v>
@@ -428,8 +458,10 @@ gen_event:stop -----> Module:terminate/2
<name>stop(EventMgrRef) -> ok</name>
<fsummary>Terminate a generic event manager.</fsummary>
<type>
- <v>EventMgrRef = Name | {Name,Node} | {global,Name} | pid()</v>
+ <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>Name = Node = atom()</v>
+ <v>GlobalName = ViaName = term()</v>
</type>
<desc>
<p>Terminates the event manager <c>EventMgrRef</c>. Before
@@ -448,12 +480,13 @@ gen_event:stop -----> Module:terminate/2
</section>
<funcs>
<func>
- <name>Module:init(InitArgs) -> {ok,State} | {ok,State,hibernate}</name>
+ <name>Module:init(InitArgs) -> {ok,State} | {ok,State,hibernate} | {error,Reason}</name>
<fsummary>Initialize an event handler.</fsummary>
<type>
<v>InitArgs = Args | {Args,Term}</v>
<v>&nbsp;Args = Term = term()</v>
<v>State = term()</v>
+ <v>Reason = term()</v>
</type>
<desc>
<p>Whenever a new event handler is added to an event manager,
@@ -470,8 +503,9 @@ gen_event:stop -----> Module:terminate/2
the argument provided in the function call/return tuple and
<c>Term</c> is the result of terminating the old event handler,
see <c>gen_event:swap_handler/3</c>.</p>
- <p>The function should return <c>{ok,State}</c> or <c>{ok,State, hibernate}</c>
- where <c>State</c> is the initial internal state of the event handler.</p>
+ <p>If successful, the function should return <c>{ok,State}</c>
+ or <c>{ok,State,hibernate}</c> where <c>State</c> is the
+ initial internal state of the event handler.</p>
<p>If <c>{ok,State,hibernate}</c> is returned, the event
manager will go into hibernation (by calling <seealso
marker="proc_lib#hibernate/3">proc_lib:hibernate/3</seealso>),
diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml
index 421eeb4fd3..73c1911f1e 100644
--- a/lib/stdlib/doc/src/gen_fsm.xml
+++ b/lib/stdlib/doc/src/gen_fsm.xml
@@ -84,9 +84,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<name>start_link(FsmName, Module, Args, Options) -> Result</name>
<fsummary>Create a gen_fsm process in a supervision tree.</fsummary>
<type>
- <v>FsmName = {local,Name} | {global,GlobalName}</v>
+ <v>FsmName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Module = atom()</v>
<v>Args = term()</v>
<v>Options = [Option]</v>
@@ -113,8 +114,16 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
locally as <c>Name</c> using <c>register/2</c>.
If <c>FsmName={global,GlobalName}</c>, the gen_fsm is
registered globally as <c>GlobalName</c> using
- <c>global:register_name/2</c>. If no name is provided,
- the gen_fsm is not registered.</p>
+ <c>global:register_name/2</c>.
+ If <c>EventMgrName={via,Module,ViaName}</c>, the event manager will
+ register with the registry represented by <c>Module</c>.
+ The <c>Module</c> callback should export the functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c> and <c>send/2</c>, which should behave like the
+ corresponding functions in <c>global</c>. Thus,
+ <c>{via,global,GlobalName}</c> is a valid reference.</p>
+ <p>If no name is provided,
+ the gen_fsm 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>
@@ -154,9 +163,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<name>start(FsmName, Module, Args, Options) -> Result</name>
<fsummary>Create a stand-alone gen_fsm process.</fsummary>
<type>
- <v>FsmName = {local,Name} | {global,GlobalName}</v>
+ <v>FsmName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Module = atom()</v>
<v>Args = term()</v>
<v>Options = [Option]</v>
@@ -180,9 +190,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<name>send_event(FsmRef, Event) -> ok</name>
<fsummary>Send an event asynchronously to a generic FSM.</fsummary>
<type>
- <v>FsmRef = Name | {Name,Node} | {global,GlobalName} | pid()</v>
+ <v>FsmRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Event = term()</v>
</type>
<desc>
@@ -196,9 +207,11 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<item>the pid,</item>
<item><c>Name</c>, if the gen_fsm is locally registered,</item>
<item><c>{Name,Node}</c>, if the gen_fsm is locally
- registered at another node, or</item>
- <item><c>{global,GlobalName}</c>, if the gen_fsm is globally
- registered.</item>
+ registered at another node, or</item>
+ <item><c>{global,GlobalName}</c>, if the gen_fsm is globally
+ registered.</item>
+ <item><c>{via,Module,ViaName}</c>, if the event manager is registered
+ through an alternative process registry.</item>
</list>
<p><c>Event</c> is an arbitrary term which is passed as one of
the arguments to <c>Module:StateName/2</c>.</p>
@@ -208,9 +221,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<name>send_all_state_event(FsmRef, Event) -> ok</name>
<fsummary>Send an event asynchronously to a generic FSM.</fsummary>
<type>
- <v>FsmRef = Name | {Name,Node} | {global,GlobalName} | pid()</v>
+ <v>FsmRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Event = term()</v>
</type>
<desc>
@@ -232,9 +246,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<name>sync_send_event(FsmRef, Event, Timeout) -> Reply</name>
<fsummary>Send an event synchronously to a generic FSM.</fsummary>
<type>
- <v>FsmRef = Name | {Name,Node} | {global,GlobalName} | pid()</v>
+ <v>FsmRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Event = term()</v>
<v>Timeout = int()>0 | infinity</v>
<v>Reply = term()</v>
@@ -264,9 +279,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<name>sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply</name>
<fsummary>Send an event synchronously to a generic FSM.</fsummary>
<type>
- <v>FsmRef = Name | {Name,Node} | {global,GlobalName} | pid()</v>
+ <v>FsmRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Name = Node = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Event = term()</v>
<v>Timeout = int()>0 | infinity</v>
<v>Reply = term()</v>
@@ -388,9 +404,10 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<v>&nbsp;&nbsp;&nbsp;&nbsp;| {log_to_file,FileName} | {install,{Func,FuncState}}</v>
<v>StateName = atom()</v>
<v>StateData = term()</v>
- <v>FsmName = {local,Name} | {global,GlobalName}</v>
+ <v>FsmName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Timeout = int() | infinity</v>
</type>
<desc>
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index 1045766e01..abb4c73c7b 100644
--- a/lib/stdlib/doc/src/gen_server.xml
+++ b/lib/stdlib/doc/src/gen_server.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -83,9 +83,10 @@ gen_server:abcast -----> Module:handle_cast/2
<name>start_link(ServerName, Module, Args, Options) -> Result</name>
<fsummary>Create a gen_server process in a supervision tree.</fsummary>
<type>
- <v>ServerName = {local,Name} | {global,GlobalName}</v>
+ <v>ServerName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Module = atom()</v>
<v>Args = term()</v>
<v>Options = [Option]</v>
@@ -111,14 +112,22 @@ gen_server:abcast -----> Module:handle_cast/2
If <c>ServerName={global,GlobalName}</c> the gen_server is
registered globally as <c>GlobalName</c> using
<c>global:register_name/2</c>. If no name is provided,
- the gen_server is not registered.</p>
+ the gen_server is not registered.
+ If <c>EventMgrName={via,Module,ViaName}</c>, the event manager will
+ register with the registry represented by <c>Module</c>.
+ The <c>Module</c> callback should export the functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c> and <c>send/2</c>, which should behave like the
+ corresponding functions in <c>global</c>. Thus,
+ <c>{via,global,GlobalName}</c> is a valid reference.</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>If the option <c>{timeout,Time}</c> is present,
the gen_server is allowed to spend <c>Time</c> milliseconds
initializing or it will be terminated and the start function
- will return <c>{error,timeout}</c>.</p>
+ will return <c>{error,timeout}</c>.
+ </p>
<p>If the option <c>{debug,Dbgs}</c> is present,
the corresponding <c>sys</c> function will be called for each
item in <c>Dbgs</c>. See
@@ -151,9 +160,10 @@ gen_server:abcast -----> Module:handle_cast/2
<name>start(ServerName, Module, Args, Options) -> Result</name>
<fsummary>Create a stand-alone gen_server process.</fsummary>
<type>
- <v>ServerName = {local,Name} | {global,GlobalName}</v>
+ <v>ServerName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Module = atom()</v>
<v>Args = term()</v>
<v>Options = [Option]</v>
@@ -178,9 +188,10 @@ gen_server:abcast -----> Module:handle_cast/2
<name>call(ServerRef, Request, Timeout) -> Reply</name>
<fsummary>Make a synchronous call to a generic server.</fsummary>
<type>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName} | pid()</v>
+ <v>ServerRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Request = term()</v>
<v>Timeout = int()>0 | infinity</v>
<v>Reply = term()</v>
@@ -198,6 +209,8 @@ gen_server:abcast -----> Module:handle_cast/2
registered at another node, or</item>
<item><c>{global,GlobalName}</c>, if the gen_server is
globally registered.</item>
+ <item><c>{via,Module,ViaName}</c>, if the gen_server is
+ registered through an alternative process registry.</item>
</list>
<p><c>Request</c> is an arbitrary term which is passed as one of
the arguments to <c>Module:handle_call/3</c>.</p>
@@ -281,9 +294,10 @@ gen_server:abcast -----> Module:handle_cast/2
<name>cast(ServerRef, Request) -> ok</name>
<fsummary>Send an asynchronous request to a generic server.</fsummary>
<type>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName} | pid()</v>
+ <v>ServerRef = Name | {Name,Node} | {global,GlobalName}
+ | {via,Module,ViaName} | pid()</v>
<v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Request = term()</v>
</type>
<desc>
@@ -355,9 +369,10 @@ gen_server:abcast -----> Module:handle_cast/2
<v>&nbsp;&nbsp;&nbsp;Dbg = trace | log | statistics</v>
<v>&nbsp;&nbsp;&nbsp;&nbsp;| {log_to_file,FileName} | {install,{Func,FuncState}}</v>
<v>State = term()</v>
- <v>ServerName = {local,Name} | {global,GlobalName}</v>
+ <v>ServerName = {local,Name} | {global,GlobalName}
+ | {via,Module,ViaName}</v>
<v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = term()</v>
+ <v>&nbsp;GlobalName = ViaName = term()</v>
<v>Timeout = int() | infinity</v>
</type>
<desc>
@@ -570,13 +585,14 @@ gen_server:abcast -----> Module:handle_cast/2
</desc>
</func>
<func>
- <name>Module:code_change(OldVsn, State, Extra) -> {ok, NewState}</name>
+ <name>Module:code_change(OldVsn, State, Extra) -> {ok, NewState} | {error, Reason}</name>
<fsummary>Update the internal state during upgrade/downgrade.</fsummary>
<type>
<v>OldVsn = Vsn | {down, Vsn}</v>
<v>&nbsp;&nbsp;Vsn = term()</v>
<v>State = NewState = term()</v>
<v>Extra = term()</v>
+ <v>Reason = term()</v>
</type>
<desc>
<p>This function is called by a gen_server when it should
@@ -595,7 +611,10 @@ gen_server:abcast -----> Module:handle_cast/2
<p><c>State</c> is the internal state of the gen_server.</p>
<p><c>Extra</c> is passed as-is from the <c>{advanced,Extra}</c>
part of the update instruction.</p>
- <p>The function should return the updated internal state.</p>
+ <p>If successful, the function shall return the updated
+ internal state.</p>
+ <p>If the function returns <c>{error,Reason}</c>, the ongoing
+ upgrade will fail and roll back to the old release.</p>
</desc>
</func>
<func>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index 667d758e29..e6d262466c 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -70,7 +70,7 @@
<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>
+ <seealso marker="kernel:file#open/2">file:open/2</seealso>).</p>
</desc>
</datatype>
<datatype>
diff --git a/lib/stdlib/doc/src/io_protocol.xml b/lib/stdlib/doc/src/io_protocol.xml
index 3e8ab1affc..0ff3d5c1ee 100644
--- a/lib/stdlib/doc/src/io_protocol.xml
+++ b/lib/stdlib/doc/src/io_protocol.xml
@@ -50,10 +50,10 @@ current I/O-protocol.</p>
and execution time efficiency has triggered extensions to the protocol
over the years, making the protocol larger and somewhat less easy to
implement than the original. It can certainly be argumented that the
-current protocol is to complex, but this text describes how it looks
+current protocol is too complex, but this text describes how it looks
today, not how it should have looked.</p>
-<p>The basic ideas from the original protocol still holds. The io_server
+<p>The basic ideas from the original protocol still hold. The io_server
and client communicate with one single, rather simplistic protocol and
no server state is ever present in the client. Any io_server can be
used together with any client code and client code need not be aware
@@ -62,7 +62,7 @@ of the actual device the io_server communicates with.</p>
<section>
<title>Protocol basics</title>
-<p>As described in Roberts paper, servers and clients communicate using
+<p>As described in Robert's paper, servers and clients communicate using
io_request/io_reply tuples as follows:</p>
<p><em>{io_request, From, ReplyAs, Request}</em><br/>
@@ -103,7 +103,7 @@ Reply part.</p>
<em>{put_chars, Encoding, Module, Function, Args}</em>
</p>
<list type="bulleted">
-<item>Encoding is either 'latin1' or 'unicode', meaning that the
+<item>Encoding is either 'unicode' or 'latin1', meaning that the
characters are (in case of binaries) encoded as either UTF-8 or
iso-latin-1 (pure bytes). A well behaved io_server should also
return error if list elements contain integers > 255 when the
@@ -116,13 +116,13 @@ Reply part.</p>
produces. Note that byte-oriented data is simplest sent using latin1
Encoding</item>
-<item>Characters are the data to be put on the device. If encoding is
- latin1, this is an iolist(). If encoding is unicode, this is an
+<item>Characters are the data to be put on the device. If Encoding is
+ latin1, this is an iolist(). If Encoding is unicode, this is an
Erlang standard mixed unicode list (one integer in a list per
character, characters in binaries represented as UTF-8).</item>
<item>Module, Function, Args denotes a function which will be called to
- produce the data (like io_lib:format), Args is a list of arguments
+ produce the data (like io_lib:format). Args is a list of arguments
to the function. The function should produce data in the given
Encoding. The io_server should call the function as apply(Mod, Func,
Args) and will put the returned data on the device as if it was sent
@@ -164,7 +164,7 @@ latin1, Module, Function, Args} respectively. </p>
<list type="bulleted">
<item>Encoding denotes how data is to be sent back to the client and
what data is sent to the function denoted by
- Module/Function/Arity. If the function supplied returns data as a
+ Module/Function/ExtraArgs. If the function supplied returns data as a
list, the data is converted to this encoding. If however the
function supplied returns data in some other format, no conversion
can be done and it's up to the client supplied function to return
@@ -179,7 +179,7 @@ latin1, Module, Function, Args} respectively. </p>
<item>Prompt is a list of characters (not mixed, no binaries) or an atom()
to be output as a prompt for input on the device. The Prompt is
often ignored by the io_server and a Prompt set to '' should always
- be ignored (and result in nothing being written to the device). </item>
+ be ignored (and result in nothing being written to the device).</item>
<item><p>Module, Function, ExtraArgs denotes a function and arguments to
determine when enough data is written. The function should take two
@@ -550,7 +550,7 @@ request({get_line, Encoding, _Prompt}, State) -&gt;
</code>
<p>Here we have cheated a little by more or less only implementing
-get_until and using internal helpers to implement get__chars and
+get_until and using internal helpers to implement get_chars and
get_line. In production code, this might be to inefficient, but that
of course depends on the frequency of the different requests. Before
we start actually implementing the functions put_chars/2 and
@@ -618,7 +618,7 @@ encounter an error or the list is exhausted. The last return value is
sent back to the client (it's first returned to the main loop and then
sent back by the function io_reply).</p>
-<p>The getopt and setopt requests is also simple to handle, we just
+<p>The getopt and setopt requests are also simple to handle, we just
change or read our state record:</p>
<code>
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index 7042c84437..8b31f3ac3d 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>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -663,7 +663,7 @@ splitwith(Pred, List) ->
<desc>
<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
+ <c><anno>Len</anno></c> to exceed the length of the list, in that case
the whole list is returned.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/make.dep b/lib/stdlib/doc/src/make.dep
deleted file mode 100644
index 48ee6209ef..0000000000
--- a/lib/stdlib/doc/src/make.dep
+++ /dev/null
@@ -1,40 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: array.tex base64.tex beam_lib.tex book.tex \
- c.tex calendar.tex dets.tex dict.tex digraph.tex \
- digraph_utils.tex epp.tex erl_eval.tex erl_expand_records.tex \
- erl_id_trans.tex erl_internal.tex erl_lint.tex \
- erl_parse.tex erl_pp.tex erl_scan.tex erl_tar.tex \
- ets.tex file_sorter.tex filelib.tex filename.tex \
- gb_sets.tex gb_trees.tex gen_event.tex gen_fsm.tex \
- gen_server.tex io.tex io_lib.tex io_protocol.tex \
- lib.tex lists.tex log_mf_h.tex math.tex ms_transform.tex \
- orddict.tex ordsets.tex part.tex pg.tex pool.tex \
- proc_lib.tex proplists.tex qlc.tex queue.tex \
- random.tex re.tex ref_man.tex regexp.tex sets.tex \
- shell.tex shell_default.tex slave.tex sofs.tex \
- stdlib_app.tex string.tex supervisor.tex supervisor_bridge.tex \
- sys.tex timer.tex unicode.tex unicode_usage.tex \
- win32reg.tex zip.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: ushell1.ps
-
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index f81f8bda96..ad5f8bd5ac 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -308,7 +308,7 @@ ets:select(emp_tab, ets:fun2ms(
Erlang code. Also arithmetics is allowed, as well as ordinary guard
bif's. Here's a list of bif's and expressions:</p>
<list type="bulleted">
- <item>The type tests: is_atom, is_constant, is_float, is_integer,
+ <item>The type tests: is_atom, is_float, is_integer,
is_list, is_number, is_pid, is_port, is_reference, is_tuple,
is_binary, is_function, is_record</item>
<item>The boolean operators: not, and, or, andalso, orelse </item>
@@ -318,7 +318,7 @@ ets:select(emp_tab, ets:fun2ms(
<item>The guard bif's: abs, element, hd, length, node, round, size, tl,
trunc, self</item>
<item>The obsolete type test (only in guards):
- atom, constant, float, integer,
+ atom, float, integer,
list, number, pid, port, reference, tuple,
binary, function, record</item>
</list>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index d9c220b996..4834426d5c 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -30,6 +30,462 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 1.18.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ References to <c>is_constant/1</c> (which was removed in
+ the R12 release) has been removed from documentation and
+ code.</p>
+ <p>
+ Own Id: OTP-6454 Aux Id: seq10407 </p>
+ </item>
+ <item>
+ <p>
+ Leave control back to gen_server during supervisor's
+ restart loop</p>
+ <p>
+ When an attempt to restart a child failed, supervisor
+ would earlier keep the execution flow and try to restart
+ the child over and over again until it either succeeded
+ or the restart frequency limit was reached. If none of
+ these happened, supervisor would hang forever in this
+ loop.</p>
+ <p>
+ This commit adds a timer of 0 ms where the control is
+ left back to the gen_server which implements the
+ supervisor. This way any incoming request to the
+ supervisor will be handled - which could help breaking
+ the infinite loop - e.g. shutdown request for the
+ supervisor or for the problematic child.</p>
+ <p>
+ This introduces some incompatibilities in stdlib due to
+ new return values from supervisor: <list>
+ <item>restart_child/2 can now return
+ {error,restarting}</item> <item>delete_child/2 can now
+ return {error,restarting}</item> <item>which_children/1
+ returns a list of {Id,Child,Type,Mods}, where Child, in
+ addition to the old pid() or 'undefined', now also can be
+ 'restarting'.</item> </list></p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9549</p>
+ </item>
+ <item>
+ <p>
+ If a temporary child's start function returned 'ignore',
+ then the supervisor would keep it's child specification.
+ This has been corrected. Child specifications for
+ non-existing temporary children shall never be kept.</p>
+ <p>
+ Own Id: OTP-9782 Aux Id: seq11964 </p>
+ </item>
+ <item>
+ <p> Use universal time as base in error logger
+ <p>
+ Previous conversion used the deprecated
+ calendar:local_time_to_universal_time/1 </p></p>
+ <p>
+ Own Id: OTP-9854</p>
+ </item>
+ <item>
+ <p>Calling a guard test (such as is_list/1) from the
+ top-level in a guard, would cause a compiler crash if
+ there was a local definition with the same name.
+ Corrected to reject the program with an error
+ message.</p>
+ <p>
+ Own Id: OTP-9866</p>
+ </item>
+ <item>
+ <p>
+ Fix the type spec from the doc of binary:part/3 (Thanks
+ to Ricardo Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9920</p>
+ </item>
+ <item>
+ <p>
+ Correct spelling of registered (Thanks to Richard
+ Carlsson)</p>
+ <p>
+ Own Id: OTP-9925</p>
+ </item>
+ <item>
+ <p>
+ Put gb_trees documentation into alphabetical order
+ (Thanks to Aidan Hobson Sayers)</p>
+ <p>
+ Own Id: OTP-9929</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in ETS with <c>compressed</c> option and
+ insertion of term containing large integers (>2G) on
+ 64-bit machines. Seen to cause emulator crash. (Thanks to
+ Diego Llarrull for excellent bug report)</p>
+ <p>
+ Own Id: OTP-9932</p>
+ </item>
+ <item>
+ <p>
+ Add plugin support for alternative name lookup This patch
+ introduces a new way of locating a behaviour instance:
+ {via, Module, Name}. (Thanks to Ulf Wiger)</p>
+ <p>
+ Own Id: OTP-9945</p>
+ </item>
+ <item>
+ <p> The function <c>digraph_utils:condensation/1</c> used
+ to create a digraph containing loops contradicting the
+ documentation which states that the created digraph is
+ free of cycles. This bug has been fixed. (Thanks to
+ Kostis Sagonas for finding the bug.) </p>
+ <p>
+ Own Id: OTP-9953</p>
+ </item>
+ <item>
+ <p> When an escript ends now all printout to standard
+ output and standard error gets out on the terminal. This
+ bug has been corrected by changing the behaviour of
+ erlang:halt/0,1, which should fix the same problem for
+ other escript-like applications, i.e that data stored in
+ the output port driver buffers got lost when printing on
+ a TTY and exiting through erlang:halt/0,1. </p>
+ <p> The BIF:s erlang:halt/0,1 has gotten improved
+ semantics and there is a new BIF erlang:halt/2 to
+ accomplish something like the old semantics. See the
+ documentation. </p>
+ <p> Now erlang:halt/0 and erlang:halt/1 with an integer
+ argument will close all ports and allow all pending async
+ threads operations to finish before exiting the emulator.
+ Previously erlang:halt/0 and erlang:halt(0) would just
+ wait for pending async threads operations but not close
+ ports. And erlang:halt/1 with a non-zero integer argument
+ would not even wait for pending async threads operations.
+ </p>
+ <p> To roughly the old behaviour, to not wait for ports
+ and async threads operations when you exit the emulator,
+ you use erlang:halt/2 with an integer first argument and
+ an option list containing {flush,false} as the second
+ argument. Note that now is flushing not dependant of the
+ exit code, and you can not only flush async threads
+ operations which we deemed as a strange behaviour anyway.
+ </p>
+ <p>Also, erlang:halt/1,2 has gotten a new feature: If the
+ first argument is the atom 'abort' the emulator is
+ aborted producing a core dump, if the operating system so
+ allows. </p>
+ <p>
+ Own Id: OTP-9985</p>
+ </item>
+ <item>
+ <p>
+ Add escript win32 alternative invocation. escript can now
+ be started as both "escript.exe" and "escript" (Thanks to
+ Pierre Rouleau)</p>
+ <p>
+ Own Id: OTP-9997</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 1.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved algorithm in module <c>random</c>. Avoid seed
+ values that are even divisors of the primes and by that
+ prevent getting sub-seeds that are stuck on zero. Worst
+ case was random:seed(0,0,0) that produced a series of
+ only zeros. This is an incompatible change in the sense
+ that applications that relies on reproducing a specific
+ series for a given seed will fail. The pseudo random
+ output is still deterministic but different compared to
+ earlier versions.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8713</p>
+ </item>
+ <item>
+ <p> Calls to <c>global:whereis_name/1</c> have been
+ substituted for calls to
+ <c>global:safe_whereis_name/1</c> since the latter is not
+ safe at all.</p>
+ <p>The reason for not doing this earlier is that setting
+ a global lock masked out a bug concerning the restart of
+ supervised children. The bug has now been fixed by a
+ modification of <c>global:whereis_name/1</c>. (Thanks to
+ Ulf Wiger for code contribution.)</p>
+ <p>A minor race conditions in <c>gen_fsm:start*</c> has
+ been fixed: if one of these functions returned <c>{error,
+ Reason}</c> or ignore, the name could still be registered
+ (either locally or in <c>global</c>. (This is the same
+ modification as was done for gen_server in OTP-7669.)</p>
+ <p>The undocumented function
+ <c>global:safe_whereis_name/1</c> has been removed. </p>
+ <p>
+ Own Id: OTP-9212 Aux Id: seq7117, OTP-4174 </p>
+ </item>
+ <item>
+ <p>
+ If a child of a supervisor terminates with reason
+ {shutdown,Term} it is now handled by the supervisor as if
+ the reason was 'shutdown'. </p>
+ <p>
+ For children with restart type 'permanent', this implies
+ no change. For children with restart type 'transient',
+ the child will no longer be restarted and no supervisor
+ report will be written. For children with restart type
+ 'temporary', no supervisor report will be written.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9222</p>
+ </item>
+ <item>
+ <p>
+ Minor improvement of documentation regarding supervisor
+ restart strategy for temporary and transient child
+ processes.</p>
+ <p>
+ Own Id: OTP-9381</p>
+ </item>
+ <item>
+ <p>A Dets table with sufficiently large buckets could not
+ always be repaired. This bug has been fixed. </p> <p>The
+ format of Dets files has been modified. When downgrading
+ tables created with the new system will be repaired.
+ Otherwise the modification should not be noticeable. </p>
+ <p>
+ Own Id: OTP-9607</p>
+ </item>
+ <item>
+ <p> A few contracts in the <c>lists</c> module have been
+ corrected. </p>
+ <p>
+ Own Id: OTP-9616</p>
+ </item>
+ <item>
+ <p>
+ Add '-callback' attributes in stdlib's behaviours</p>
+ <p>
+ Replace the behaviour_info(callbacks) export in stdlib's
+ behaviours with -callback' attributes for all the
+ callbacks. Update the documentation with information on
+ the callback attribute Automatically generate
+ 'behaviour_info' function from '-callback' attributes</p>
+ <p>
+ 'behaviour_info(callbacks)' is a special function that is
+ defined in a module which describes a behaviour and
+ returns a list of its callbacks.</p>
+ <p>
+ This function is now automatically generated using the
+ '-callback' specs. An error is returned by lint if user
+ defines both '-callback' attributes and the
+ behaviour_info/1 function. If no type info is needed for
+ a callback use a generic spec for it. Add '-callback'
+ attribute to language syntax</p>
+ <p>
+ Behaviours may define specs for their callbacks using the
+ familiar spec syntax, replacing the '-spec' keyword with
+ '-callback'. Simple lint checks are performed to ensure
+ that no callbacks are defined twice and all types
+ referred are declared.</p>
+ <p>
+ These attributes can be then used by tools to provide
+ documentation to the behaviour or find discrepancies in
+ the callback definitions in the callback module.</p>
+ <p>
+ Add callback specs into 'application' module in kernel
+ Add callback specs to tftp module following internet
+ documentation Add callback specs to inets_service module
+ following possibly deprecated comments</p>
+ <p>
+ Own Id: OTP-9621</p>
+ </item>
+ <item>
+ <p> If a Dets table had been properly closed but the
+ space management data could not been read, it was not
+ possible to repair the file. This bug has been fixed.
+ </p>
+ <p>
+ Own Id: OTP-9622</p>
+ </item>
+ <item>
+ <p>
+ The Unicode noncharacter code points 16#FFFE and 16#FFFE
+ were not allowed to be encoded or decoded using the
+ <c>unicode</c> module or bit syntax. That was
+ inconsistent with the other noncharacters 16#FDD0 to
+ 16#FDEF that could be encoded/decoded. To resolve the
+ inconsistency, 16#FFFE and 16#FFFE can now be encoded and
+ decoded. (Thanks to Alisdair Sullivan.)</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9624</p>
+ </item>
+ <item>
+ <p>
+ Make epp search directory of current file first when
+ including another file This completes a partial fix in
+ R11 that only worked for include_lib(). (Thanks to
+ Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9645</p>
+ </item>
+ <item>
+ <p>
+ ms_transform: Fix incorrect `variable shadowed' warnings</p>
+ <p>
+ This patch removes incorrect passing of variable bindings
+ from one function clause to another. (Thanks to Haitao
+ Li)</p>
+ <p>
+ Own Id: OTP-9646</p>
+ </item>
+ <item>
+ <p>
+ Explicitly kill dynamic children in supervisors</p>
+ <p>
+ According to the supervisor's documentation: "Important
+ note on simple-one-for-one supervisors: The dynamically
+ created child processes of a simple-one-for-one
+ supervisor are not explicitly killed, regardless of
+ shutdown strategy, but are expected to terminate when the
+ supervisor does (that is, when an exit signal from the
+ parent process is received)."</p>
+ <p>
+ All is fine as long as we stop simple_one_for_one
+ supervisor manually. Dynamic children catch the exit
+ signal from the supervisor and leave. But, if this
+ happens when we stop an application, after the top
+ supervisor has stopped, the application master kills all
+ remaining processes associated to this application. So,
+ dynamic children that trap exit signals can be killed
+ during their cleanup (here we mean inside terminate/2).
+ This is unpredictable and highly time-dependent.</p>
+ <p>
+ In this commit, supervisor module is patched to
+ explicitly terminate dynamic children accordingly to the
+ shutdown strategy.</p>
+ <p>
+ NOTE: Order in which dynamic children are stopped is not
+ defined. In fact, this is "almost" done at the same time.</p>
+ <p>
+ Stack errors when dynamic children are stopped</p>
+ <p>
+ Because a simple_one_for_one supervisor can have many
+ workers, we stack errors during its shutdown to report
+ only one message for each encountered error type. Instead
+ of reporting the child's pid, we use the number of
+ concerned children. (Thanks to Christopher Faulet)</p>
+ <p>
+ Own Id: OTP-9647</p>
+ </item>
+ <item>
+ <p>
+ Allow an infinite timeout to shutdown worker processes</p>
+ <p>
+ Now, in child specification, the shutdown value can also
+ be set to infinity for worker children. This restriction
+ was removed because this is not always possible to
+ predict the shutdown time for a worker. This is highly
+ application-dependent. Add a warning to docs about
+ workers' shutdown strategy (Thanks to Christopher Faulet)</p>
+ <p>
+ Own Id: OTP-9648</p>
+ </item>
+ <item>
+ <p>
+ A badarg would sometimes occur in supervisor when
+ printing error reports and the child pid was undefined.
+ This has been corrected.</p>
+ <p>
+ Own Id: OTP-9669</p>
+ </item>
+ <item>
+ <p>
+ Fix re:split spec not to accept option 'global'(Thanks to
+ Shunichi Shinohara)</p>
+ <p>
+ Own Id: OTP-9691</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Fix a few tests that used to fail on the HiPE
+ platform. </p>
+ <p>
+ Own Id: OTP-9637</p>
+ </item>
+ <item>
+ <p>Variables are now now allowed in '<c>fun M:F/A</c>' as
+ suggested by Richard O'Keefe in EEP-23.</p>
+ <p>The representation of '<c>fun M:F/A</c>' in the
+ abstract format has been changed in an incompatible way.
+ Tools that directly read or manipulate the abstract
+ format (such as parse transforms) may need to be updated.
+ The compiler can handle both the new and the old format
+ (i.e. extracting the abstract format from a pre-R15 BEAM
+ file and compiling it using compile:forms/1,2 will work).
+ The <c>syntax_tools</c> application can also handle both
+ formats.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9643</p>
+ </item>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ <item>
+ <p>
+ The deprecated '<c>regexp</c>' module has been removed.
+ Use the '<c>re</c>' module instead.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9737</p>
+ </item>
+ <item>
+ <p>
+ <c>filename:find_src/1,2</c> will now work on stripped
+ BEAM files (reported by Per Hedeland). The HiPE compiler
+ will also work on stripped BEAM files. The BEAM compiler
+ will no longer include compilation options given in the
+ source code itself in <c>M:module_info(compile)</c>
+ (because those options will be applied anyway if the
+ module is re-compiled).</p>
+ <p>
+ Own Id: OTP-9752</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 1.17.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index 93affc3191..1b8fa44883 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -136,6 +136,11 @@
<c>random_seed</c> to remember the current seed.</p>
<p>If a process calls <c>uniform/0</c> or <c>uniform/1</c> without
setting a seed first, <c>seed/0</c> is called automatically.</p>
+ <p>The implementation changed in R15. Upgrading to R15 will break
+ applications that expect a specific output for a given seed. The output
+ is still deterministic number series, but different compared to releases
+ older than R15. The seed <c>{0,0,0}</c> will for example no longer
+ produce a flawed series of only zeros.</p>
</section>
</erlref>
diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml
index 18867cfb68..6d5336796c 100644
--- a/lib/stdlib/doc/src/re.xml
+++ b/lib/stdlib/doc/src/re.xml
@@ -41,8 +41,7 @@
strings and binaries.</p>
<p>The regular expression syntax and semantics resemble that of
- Perl. This library replaces the deprecated pure-Erlang regexp
- library; it has a richer syntax, more options and is faster.</p>
+ Perl.</p>
<p>The library's matching algorithms are currently based on the
PCRE library, but not all of the PCRE library is interfaced and
diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml
index 85aae6151d..0f277f6c5e 100644
--- a/lib/stdlib/doc/src/ref_man.xml
+++ b/lib/stdlib/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -80,7 +80,6 @@
<xi:include href="queue.xml"/>
<xi:include href="random.xml"/>
<xi:include href="re.xml"/>
- <xi:include href="regexp.xml"/>
<xi:include href="sets.xml"/>
<xi:include href="shell.xml"/>
<xi:include href="shell_default.xml"/>
diff --git a/lib/stdlib/doc/src/regexp.xml b/lib/stdlib/doc/src/regexp.xml
deleted file mode 100644
index 35d8e1c3f8..0000000000
--- a/lib/stdlib/doc/src/regexp.xml
+++ /dev/null
@@ -1,381 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1996</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>regexp</title>
- <prepared>Robert Virding</prepared>
- <responsible>Bjarne Dacker</responsible>
- <docno>1</docno>
- <approved>Bjarne D&auml;cker</approved>
- <checked></checked>
- <date>96-09-28</date>
- <rev>A</rev>
- <file>regexp.sgml</file>
- </header>
- <module>regexp</module>
- <modulesummary>Regular Expression Functions for Strings</modulesummary>
- <description>
- <note><p>This module has been obsoleted by the
- <seealso marker="re">re</seealso> module and will be removed in a future
- release.</p></note>
- <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 name="match" arity="2"/>
- <fsummary>Match a regular expression</fsummary>
- <desc>
- <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,<anno>Start</anno>,<anno>Length</anno>}</c></tag>
- <item>
- <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,<anno>Error</anno>}</c></tag>
- <item>
- <p>if there was an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="first_match" arity="2"/>
- <fsummary>Match a regular expression</fsummary>
- <desc>
- <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,<anno>Start</anno>,<anno>Length</anno>}</c></tag>
- <item>
- <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,<anno>Error</anno>}</c></tag>
- <item>
- <p>if there was an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="matches" arity="2"/>
- <fsummary>Match a regular expression</fsummary>
- <desc>
- <p>Finds all non-overlapping matches of the
- expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>.
- It returns as follows:</p>
- <taglist>
- <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>{<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,<anno>Error</anno>}</c></tag>
- <item>
- <p>if there was an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="sub" arity="3"/>
- <fsummary>Substitute the first occurrence of a regular expression</fsummary>
- <desc>
- <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,<anno>NewString</anno>,<anno>RepCount</anno>}</c></tag>
- <item>
- <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, <anno>Error</anno>}</c></tag>
- <item>
- <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="gsub" arity="3"/>
- <fsummary>Substitute all occurrences of a regular expression</fsummary>
- <desc>
- <p>The same as <c>sub</c>, except that all non-overlapping
- occurrences of a substring matching
- <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,<anno>NewString</anno>,<anno>RepCount</anno>}</c></tag>
- <item>
- <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, <anno>Error</anno>}</c></tag>
- <item>
- <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="split" arity="2"/>
- <fsummary>Split a string into fields</fsummary>
- <desc>
- <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, <anno>FieldList</anno>}</c></tag>
- <item>
- <p>to indicate that the string has been split up into the fields of
- <c><anno>FieldList</anno></c>.</p>
- </item>
- <tag><c>{error, <anno>Error</anno>}</c></tag>
- <item>
- <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="sh_to_awk" arity="1"/>
- <fsummary>Convert an <c>sh</c>regular expression into an <c>AWK</c>one</fsummary>
- <desc>
- <p>Converts the <c>sh</c> type regular expression
- <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
- characters:</p>
- <taglist>
- <tag><c>*</c></tag>
- <item>
- <p>matches any string including the null string.</p>
- </item>
- <tag><c>?</c></tag>
- <item>
- <p>matches any single character.</p>
- </item>
- <tag><c>[...]</c></tag>
- <item>
- <p>matches any of the enclosed characters. Character
- ranges are specified by a pair of characters separated
- by a <c>-</c>. If the first character after <c>[</c> is a
- <c>!</c>, then any character not enclosed is matched.</p>
- </item>
- </taglist>
- <p>It may sometimes be more practical to use <c>sh</c> type
- expansions as they are simpler and easier to use, even though they are not as powerful.</p>
- </desc>
- </func>
- <func>
- <name name="parse" arity="1"/>
- <fsummary>Parse a regular expression</fsummary>
- <desc>
- <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, <anno>RE</anno>}</c></tag>
- <item>
- <p>if <c>RegExp</c> is correct and <c><anno>RE</anno></c> is the internal representation.</p>
- </item>
- <tag><c>{error, <anno>Error</anno>}</c></tag>
- <item>
- <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="format_error" arity="1"/>
- <fsummary>Format an error descriptor</fsummary>
- <desc>
- <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>
- </funcs>
-
- <section>
- <title>Regular Expressions</title>
- <p>The regular expressions allowed here is a subset of the set found
- in <c>egrep</c> and in the <c>AWK</c> programming language, as
- defined in the book, <c>The AWK Programming Language, by A. V. Aho, B. W. Kernighan, P. J. Weinberger</c>. They are
- composed of the following characters:</p>
- <taglist>
- <tag>c</tag>
- <item>
- <p>matches the non-metacharacter <c>c</c>.</p>
- </item>
- <tag>\c</tag>
- <item>
- <p>matches the escape sequence or literal character <c>c</c>.</p>
- </item>
- <tag>.</tag>
- <item>
- <p>matches any character.</p>
- </item>
- <tag>^</tag>
- <item>
- <p>matches the beginning of a string.</p>
- </item>
- <tag>$</tag>
- <item>
- <p>matches the end of a string.</p>
- </item>
- <tag>[abc...]</tag>
- <item>
- <p>character class, which matches any of the characters
- <c>abc...</c> Character ranges are specified by a pair of
- characters separated by a <c>-</c>.</p>
- </item>
- <tag>[^abc...]</tag>
- <item>
- <p>negated character class, which matches any character except
- <c>abc...</c>.</p>
- </item>
- <tag>r1 | r2</tag>
- <item>
- <p>alternation. It matches either <c>r1</c> or <c>r2</c>.</p>
- </item>
- <tag>r1r2</tag>
- <item>
- <p>concatenation. It matches <c>r1</c> and then <c>r2</c>.</p>
- </item>
- <tag>r+</tag>
- <item>
- <p>matches one or more <c>r</c>s.</p>
- </item>
- <tag>r*</tag>
- <item>
- <p>matches zero or more <c>r</c>s.</p>
- </item>
- <tag>r?</tag>
- <item>
- <p>matches zero or one <c>r</c>s.</p>
- </item>
- <tag>(r)</tag>
- <item>
- <p>grouping. It matches <c>r</c>.</p>
- </item>
- </taglist>
- <p>The escape sequences allowed are the same as for Erlang
- strings:</p>
- <taglist>
- <tag><c>\b</c></tag>
- <item>
- <p>backspace</p>
- </item>
- <tag><c>\f</c></tag>
- <item>
- <p>form feed </p>
- </item>
- <tag><c>\n</c></tag>
- <item>
- <p>newline (line feed) </p>
- </item>
- <tag><c>\r</c></tag>
- <item>
- <p>carriage return </p>
- </item>
- <tag><c>\t</c></tag>
- <item>
- <p>tab </p>
- </item>
- <tag><c>\e</c></tag>
- <item>
- <p>escape </p>
- </item>
- <tag><c>\v</c></tag>
- <item>
- <p>vertical tab </p>
- </item>
- <tag><c>\s</c></tag>
- <item>
- <p>space </p>
- </item>
- <tag><c>\d</c></tag>
- <item>
- <p>delete </p>
- </item>
- <tag><c>\ddd</c></tag>
- <item>
- <p>the octal value ddd </p>
- </item>
- <tag><c>\xhh</c></tag>
- <item>
- <p>The hexadecimal value <c>hh</c>.</p>
- </item>
- <tag><c>\x{h...}</c></tag>
- <item>
- <p>The hexadecimal value <c>h...</c>.</p>
- </item>
- <tag><c>\c</c></tag>
- <item>
- <p>any other character literally, for example <c>\\</c> for backslash,
- <c>\"</c> for ")</p>
- </item>
- </taglist>
- <p>To make these functions easier to use, in combination with the
- function <c>io:get_line</c> which terminates the input line with
- a new line, the <c>$</c> characters also matches a string ending
- with <c>"...\n"</c>. The following examples
- define Erlang data types:</p>
- <pre>
-Atoms [a-z][0-9a-zA-Z_]*
-
-Variables [A-Z_][0-9a-zA-Z_]*
-
-Floats (\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?</pre>
- <p>Regular expressions are written as Erlang strings when used with the functions in this module. This means that any <c>\</c> or <c>"</c> characters in a regular expression
- string must be written with <c>\</c> as they are also escape characters for the string. For example, the regular expression string for Erlang floats is:
- <c>"(\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?"</c>.</p>
- <p>It is not really necessary to have the escape sequences as part of the regular expression syntax as they can always be generated directly in the string. They are included for completeness and can they can also be useful when generating regular expressions, or when they are entered other than with Erlang strings.</p>
- </section>
-</erlref>
-
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 2e7768a1df..37c41501ae 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>2011</year>
+ <year>2001</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -317,7 +317,7 @@
but is to be preferred since it makes it possible to handle this
case even more efficiently. Examples of SetFuns:</p>
<pre>
-{sofs, union}
+fun sofs:union/1
fun(S) -> sofs:partition(1, S) end
{external, fun(A) -> A end}
{external, fun({A,_,C}) -> {C,A} end}
@@ -711,7 +711,7 @@ fun(S) -> sofs:partition(1, S) end
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>
+<input>F2 = sofs:family_projection(fun sofs:union/1, F1),</input>
<input>sofs:to_external(F2).</input>
[{a,[1,2,3]},{b,[]}]</pre>
</desc>
@@ -821,7 +821,7 @@ fun(S) -> sofs:partition(1, S) end
<input>sofs:to_external(F2).</input>
[{a,[1,2,3]},{b,[]}]</pre>
<p><c>family_union(F)</c> is equivalent to
- <c>family_projection({sofs,union},&nbsp;F)</c>.</p>
+ <c>family_projection(fun sofs:union/1,&nbsp;F)</c>.</p>
</desc>
</func>
<func>
@@ -1438,7 +1438,7 @@ true</pre>
1> <input>R1 = sofs:relation([{a,1},{b,2}]),</input>
<input>R2 = sofs:relation([{x,1},{x,2},{y,3}]),</input>
<input>S1 = sofs:from_sets([R1,R2]),</input>
-<input>S2 = sofs:specification({sofs,is_a_function}, S1),</input>
+<input>S2 = sofs:specification(fun sofs:is_a_function/1, S1),</input>
<input>sofs:to_external(S2).</input>
[[{a,1},{b,2}]]</pre>
</desc>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
index 98338b5ec2..49c60529d2 100644
--- a/lib/stdlib/doc/src/specs.xml
+++ b/lib/stdlib/doc/src/specs.xml
@@ -46,7 +46,6 @@
<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"/>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index ec607d6e4c..f9a5e245b4 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>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -55,7 +55,8 @@
monitoring its child processes. The basic idea of a supervisor is
that it should keep its child processes alive by restarting them
when necessary.</p>
- <p>The children of a supervisor is defined as a list of <em>child specifications</em>. When the supervisor is started, the child
+ <p>The children of a supervisor is defined as a list of
+ <em>child specifications</em>. When the supervisor is started, the child
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>
@@ -93,10 +94,15 @@
instead the child specification identifier is used,
<c>terminate_child/2</c> will return
<c>{error,simple_one_for_one}</c>.</p>
+ <p>Because a <c>simple_one_for_one</c> supervisor could have many
+ children, it shuts them all down at same time. So, order in which they
+ are stopped is not defined. For the same reason, it could have an
+ overhead with regards to the <c>Shutdown</c> strategy.</p>
</item>
</list>
<p>To prevent a supervisor from getting into an infinite loop of
- child process terminations and restarts, a <em>maximum restart frequency</em> is defined using two integer values <c>MaxR</c>
+ child process terminations and restarts, a <em>maximum restart frequency</em>
+ is defined using two integer values <c>MaxR</c>
and <c>MaxT</c>. If more than <c>MaxR</c> restarts occur within
<c>MaxT</c> seconds, the supervisor terminates all child
processes and then itself.
@@ -110,7 +116,7 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
M = F = atom()
A = [term()]
Restart = permanent | transient | temporary
- Shutdown = brutal_kill | int()>=0 | infinity
+ Shutdown = brutal_kill | int()>0 | infinity
Type = worker | supervisor
Modules = [Module] | dynamic
Module = atom()</pre>
@@ -123,25 +129,18 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<p><c>StartFunc</c> defines the function call used to start
the child process. It should be a module-function-arguments
tuple <c>{M,F,A}</c> used as <c>apply(M,F,A)</c>.</p>
- <p> <br></br>
-</p>
<p>The start function <em>must create and link to</em> the child
process, and should return <c>{ok,Child}</c> or
<c>{ok,Child,Info}</c> where <c>Child</c> is the pid of
the child process and <c>Info</c> an arbitrary term which is
ignored by the supervisor.</p>
- <p> <br></br>
-</p>
<p>The start function can also return <c>ignore</c> if the child
process for some reason cannot be started, in which case
- the child specification will be kept by the supervisor but
- the non-existing child process will be ignored.</p>
- <p> <br></br>
-</p>
+ the child specification will be kept by the supervisor
+ (unless it is a temporary child) but the non-existing child
+ process will be ignored.</p>
<p>If something goes wrong, the function may also return an
error tuple <c>{error,Error}</c>.</p>
- <p> <br></br>
-</p>
<p>Note that the <c>start_link</c> functions of the different
behaviour modules fulfill the above requirements.</p>
</item>
@@ -154,7 +153,7 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
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>
+ than <c>normal</c>, <c>shutdown</c> or <c>{shutdown,Term}</c>.</p>
</item>
<item>
<p><c>Shutdown</c> defines how a child process should be
@@ -169,7 +168,15 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, <c>Shutdown</c>
should be set to <c>infinity</c> to give the subtree ample
- time to shutdown.</p>
+ time to shutdown. It is also allowed to set it to <c>infinity</c>,
+ if the child process is a worker.</p>
+ <warning>
+ <p>Be careful by setting the <c>Shutdown</c> strategy to
+ <c>infinity</c> when the child process is a worker. Because, in this
+ situation, the termination of the supervision tree depends on the
+ child process, it must be implemented in a safe way and its cleanup
+ procedure must always return.</p>
+ </warning>
<p><em>Important note on simple-one-for-one supervisors:</em>
The dynamically created child processes of a
simple-one-for-one supervisor are not explicitly killed,
@@ -192,7 +199,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
the callback module, if the child process is a supervisor,
gen_server or gen_fsm. If the child process is an event
manager (gen_event) with a dynamic set of callback modules,
- <c>Modules</c> should be <c>dynamic</c>. See <em>OTP Design Principles</em> for more information about release handling.</p>
+ <c>Modules</c> should be <c>dynamic</c>. See <em>OTP Design Principles</em>
+ for more information about release handling.</p>
</item>
<item>
<p>Internally, the supervisor also keeps track of the pid
@@ -259,8 +267,14 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<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><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>
+ globally as <c>Name</c> using <c>global:register_name/2</c>. If
+ <c><anno>SupName</anno>={via,Module,Name}</c> the supervisor
+ is registered as <c>Name</c> using the registry represented by
+ <c>Module</c>. The <c>Module</c> callback should export the functions
+ <c>register_name/2</c>, <c>unregister_name/1</c> and <c>send/2</c>,
+ which should behave like the corresponding functions in <c>global</c>.
+ Thus, <c>{via,global,Name}</c> is a valid reference.</p>
+ <p>If no name is provided, the supervisor is not registered.</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>
@@ -303,6 +317,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
registered at another node, or</item>
<item><c>{global,Name}</c>, if the supervisor is globally
registered.</item>
+ <item><c>{via,Module,Name}</c>, if the supervisor is registered
+ through an alternative process registry.</item>
</list>
<p><c><anno>ChildSpec</anno></c> should be a valid child specification
(unless the supervisor is a <c>simple_one_for_one</c>
@@ -343,14 +359,23 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<desc>
<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><anno>Id</anno></c> must be the child specification
+ identifier. The process, if there is one, is terminated and,
+ unless it is a temporary child, 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 child is temporary, the child specification is deleted as
+ soon as the process terminates. This means
+ that <c>delete_child/2</c> has no meaning
+ and <c>restart_child/2</c> can not be used for these
+ children.</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
@@ -377,42 +402,52 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<c>SupRef</c>.</p>
<p>If successful, the function returns <c>ok</c>. If the child
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><anno>Id</anno></c> does not exist, the function returns
- <c>{error,not_found}</c>.</p>
+ the corresponding child process is running or about to be restarted,
+ the function returns <c>{error,running}</c> or
+ <c>{error,restarting}</c> respectively. If the child specification
+ identified by <c><anno>Id</anno></c> does not exist, the function
+ returns <c>{error,not_found}</c>.</p>
</desc>
</func>
<func>
<name name="restart_child" arity="2"/>
<fsummary>Restart a terminated child process belonging to a supervisor.</fsummary>
<desc>
- <p>Tells the supervisor <c><anno>SupRef</anno></c> to restart a child process
- corresponding to the child specification identified by
- <c><anno>Id</anno></c>. The child specification must exist and
- the corresponding child process must not be running.</p>
- <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
+ <p>Tells the supervisor <c><anno>SupRef</anno></c> to restart
+ a child process corresponding to the child specification
+ identified by <c><anno>Id</anno></c>. The child
+ specification must exist and the corresponding child process
+ must not be running.</p>
+ <p>Note that for temporary children, the child specification
+ is automatically deleted when the child terminates, and thus
+ it is not possible to restart such children.</p>
+ <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,<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>{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,<anno>Error</anno>}</c> where <c><anno>Error</anno></c> is a term containing
+ <p>If the child process start function returns an error tuple
+ or an erroneous value, or if it fails, the function returns
+ <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 name="which_children" arity="1"/>
- <fsummary>Return information about all children specifications and child processes belonging to a supervisor.</fsummary>
+ <fsummary>Return information about all children specifications and
+ child processes belonging to a supervisor.</fsummary>
<desc>
<p>Returns a newly created list with information about all child
specifications and child processes belonging to
@@ -432,7 +467,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
</item>
<item>
<p><c><anno>Child</anno></c> - the pid of the corresponding child
- process, or <c>undefined</c> if there is no such process.</p>
+ process, the atom <c>restarting</c> if the process is about to be
+ restarted or <c>undefined</c> if there is no such process.</p>
</item>
<item>
<p><c><anno>Type</anno></c> - as defined in the child specification.</p>
@@ -445,7 +481,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
</func>
<func>
<name name="count_children" arity="1"/>
- <fsummary>Return counts for the number of childspecs, active children, supervisors and workers.</fsummary>
+ <fsummary>Return counts for the number of childspecs, active children,
+ supervisors and workers.</fsummary>
<desc>
<p>Returns a property list (see <c>proplists</c>) containing the
counts for each of the following elements of the supervisor's
@@ -495,7 +532,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<v>Args = term()</v>
<v>Result = {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore</v>
<v>&nbsp;RestartStrategy = <seealso marker="#type-strategy">strategy()</seealso></v>
- <v>&nbsp;MaxR = MaxT = integer()>=0</v>
+ <v>&nbsp;MaxR = integer()>=0</v>
+ <v>&nbsp;MaxT = integer()>0</v>
<v>&nbsp;ChildSpec = <seealso marker="#type-child_spec">child_spec()</seealso></v>
</type>
<desc>
diff --git a/lib/stdlib/doc/src/supervisor_bridge.xml b/lib/stdlib/doc/src/supervisor_bridge.xml
index c1a5e7947f..f6712d6c1d 100644
--- a/lib/stdlib/doc/src/supervisor_bridge.xml
+++ b/lib/stdlib/doc/src/supervisor_bridge.xml
@@ -63,6 +63,13 @@
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 <c><anno>SupBridgeName</anno>={via,<anno>Module</anno>,<anno>Name</anno>}</c> the supervisor_bridge is
+ registered as <c><anno>Name</anno></c> using a registry represented
+ by <anno>Module</anno>. The <c>Module</c> callback should export
+ the functions <c>register_name/2</c>, <c>unregister_name/1</c>
+ and <c>send/2</c>, which should behave like the
+ corresponding functions in <c>global</c>. Thus,
+ <c>{via,global,GlobalName}</c> is a valid reference.
If no name is provided, the supervisor_bridge is not registered.
If there already exists a process with the specified
<c><anno>SupBridgeName</anno></c> the function returns
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index d02763f75c..1001ebbae4 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -203,8 +203,7 @@
<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>
+ (invalid range reserved for UTF-16 surrogate pairs)</item>
</list>
is found.
</item>
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index 0fa7de0a5c..b7b5d497d0 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -53,13 +53,13 @@
<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 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>
+<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, but 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>
<title>Standard Unicode representation in Erlang</title>
<p>In Erlang, strings are actually lists of integers. A string is defined to be encoded in the ISO-latin-1 (ISO8859-1) character set, which is, codepoint by codepoint, a sub-range of the Unicode character set.</p>
<p>The standard list encoding for strings is therefore easily extendible to cope with the whole Unicode range: A Unicode string in Erlang is simply a list containing integers, each integer being a valid Unicode codepoint and representing one character in the Unicode character set.</p>
-<p>Regular Erlang strings in ISO-latin-1 are a subset of there Unicode strings.</p>
+<p>Regular Erlang strings in ISO-latin-1 are a subset of their Unicode strings.</p>
<p>Binaries on the other hand are more troublesome. For performance reasons, programs often store textual data in binaries instead of lists, mainly because they are more compact (one byte per character instead of two words per character, as is the case with lists). Using erlang:list_to_binary/1, an regular Erlang string can be converted into a binary, effectively using the ISO-latin-1 encoding in the binary - one byte per character. This is very convenient for those regular Erlang strings, but cannot be done for Unicode lists.</p>
<p>As the UTF-8 encoding is widely spread and provides the most compact storage, it is selected as the standard encoding of Unicode characters in binaries for Erlang.</p>
@@ -210,6 +210,12 @@ Eshell V5.7 (abort with ^G)
</section>
</section>
<section>
+<title>Unicode in environment variables and parameters</title>
+<p>Environment variables and their interpretation is handled much in the same way as file names. If Unicode file names are enabled, environment variables as well as parameters to the Erlang VM are expected to be in Unicode.</p>
+<p>If Unicode file names are enabled, the calls to <seealso marker="kernel:os#os_getenv/0"><c>os:getenv/0</c></seealso>, <seealso marker="kernel:os#os_getenv/1"><c>os:getenv/1</c></seealso> and <seealso marker="kernel:os#os_putenv/2"><c>os:putenv/2</c></seealso> will handle Unicode strings. On Unix-like platforms, the built-in functions will translate environment variables in UTF-8 to/from Unicode strings, possibly with codepoints > 255. On Windows the Unicode versions of the environment system API will be used, also allowing for codepoints > 255.</p>
+<p>On Unix-like operating systems, parameters are expected to be UTF-8 without translation if Unicode file names are enabled.</p>
+</section>
+<section>
<title>Unicode-aware modules</title>
<p>Most of the modules in Erlang/OTP are of course Unicode-unaware in the sense that they have no notion of Unicode and really shouldn't have. Typically they handle non-textual or byte-oriented data (like <c>gen_tcp</c> etc).</p>
<p>Modules that actually handle textual data (like <c>io_lib</c>, <c>string</c> etc) are sometimes subject to conversion or extension to be able to handle Unicode characters.</p>
diff --git a/lib/stdlib/examples/Makefile b/lib/stdlib/examples/Makefile
index 25c88d1de3..198aceb3a9 100644
--- a/lib/stdlib/examples/Makefile
+++ b/lib/stdlib/examples/Makefile
@@ -47,6 +47,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/stdlib-$(STDLIB_VSN)/examples
EXAMPLES = erl_id_trans.erl
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(EXAMPLES) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EXAMPLES) "$(RELSYSDIR)"
release_docs_spec:
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index b63acdd40a..72e41d6473 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -419,7 +419,14 @@ expr({'fun',Line,Body}) ->
{'fun',Line,{clauses,Cs1}};
{function,F,A} ->
{'fun',Line,{function,F,A}};
- {function,M,F,A} -> %R10B-6: fun M:F/A.
+ {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) ->
+ %% R10B-6: fun M:F/A. (Backward compatibility)
+ {'fun',Line,{function,M,F,A}};
+ {function,M0,F0,A0} ->
+ %% R15: fun M:F/A with variables.
+ M = expr(M0),
+ F = expr(F0),
+ A = expr(A0),
{'fun',Line,{function,M,F,A}}
end;
expr({call,Line,F0,As0}) ->
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index 600303d7e1..54186a3ba7 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/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
@@ -105,7 +105,6 @@ MODULES= \
qlc_pt \
queue \
random \
- regexp \
sets \
shell \
shell_default \
@@ -168,6 +167,7 @@ docs:
# This is a trick so that the preloaded files will get the correct type
# specifications.
primary_bootstrap_compiler: \
+ $(BOOTSTRAP_COMPILER)/ebin/epp.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_scan.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_lint.beam \
@@ -199,13 +199,13 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) erl_parse.yrl $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) erl_parse.yrl "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl
index e221be15a1..807b5c12a1 100644
--- a/lib/stdlib/src/digraph_utils.erl
+++ b/lib/stdlib/src/digraph_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -370,5 +370,5 @@ condense('$end_of_table', _T, _SC, _G, _SCG, _I2C) ->
condense(I, T, SC, G, SCG, I2C) ->
[{_,C}] = ets:lookup(I2C, I),
digraph:add_vertex(SCG, C),
- digraph:add_edge(SCG, SC, C),
+ [digraph:add_edge(SCG, SC, C) || C =/= SC],
condense(ets:next(T, I), T, SC, G, SCG, I2C).
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 230a4a0612..ccc14610d7 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -267,8 +267,10 @@ init_server(Pid, Name, File, AtLocation, Path, Pdm, Pre) ->
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
epp_reply(Pid, {ok,self()}),
+ %% ensure directory of current source file is first in path
+ Path1 = [filename:dirname(Name) | Path],
St = #epp{file=File, location=AtLocation, delta=0, name=Name,
- name2=Name, path=Path, macs=Ms1, pre_opened = Pre},
+ name2=Name, path=Path1, macs=Ms1, pre_opened = Pre},
From = wait_request(St),
enter_file_reply(From, Name, AtLocation, AtLocation),
wait_req_scan(St);
@@ -360,18 +362,18 @@ wait_req_skip(St, Sis) ->
From = wait_request(St),
skip_toks(From, St, Sis).
-%% enter_file(Path, FileName, IncludeToken, From, EppState)
+%% enter_file(FileName, IncludeToken, From, EppState)
%% leave_file(From, EppState)
%% Handle entering and leaving included files. Notify caller when the
%% current file is changed. Note it is an error to exit a file if we are
%% in a conditional. These functions never return.
-enter_file(_Path, _NewName, Inc, From, St)
+enter_file(_NewName, Inc, From, St)
when length(St#epp.sstk) >= 8 ->
epp_reply(From, {error,{abs_loc(Inc),epp,{depth,"include"}}}),
wait_req_scan(St);
-enter_file(Path, NewName, Inc, From, St) ->
- case file:path_open(Path, NewName, [read]) of
+enter_file(NewName, Inc, From, St) ->
+ case file:path_open(St#epp.path, NewName, [read]) of
{ok,NewF,Pname} ->
Loc = start_loc(St#epp.location),
wait_req_scan(enter_file2(NewF, Pname, From, St, Loc));
@@ -384,13 +386,16 @@ enter_file(Path, NewName, Inc, From, St) ->
%% Set epp to use this file and "enter" it.
enter_file2(NewF, Pname, From, St, AtLocation) ->
- enter_file2(NewF, Pname, From, St, AtLocation, []).
-
-enter_file2(NewF, Pname, From, St, AtLocation, ExtraPath) ->
Loc = start_loc(AtLocation),
enter_file_reply(From, Pname, Loc, AtLocation),
Ms = dict:store({atom,'FILE'}, {none,[{string,Loc,Pname}]}, St#epp.macs),
- Path = St#epp.path ++ ExtraPath,
+ %% update the head of the include path to be the directory of the new
+ %% source file, so that an included file can always include other files
+ %% relative to its current location (this is also how C does it); note
+ %% that the directory of the parent source file (the previous head of
+ %% the path) must be dropped, otherwise the path used within the current
+ %% file will depend on the order of file inclusions in the parent files
+ Path = [filename:dirname(Pname) | tl(St#epp.path)],
#epp{file=NewF,location=Loc,name=Pname,delta=0,
sstk=[St|St#epp.sstk],path=Path,macs=Ms}.
@@ -655,7 +660,7 @@ scan_undef(_Toks, Undef, From, St) ->
scan_include([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}], Inc,
From, St) ->
NewName = expand_var(NewName0),
- enter_file(St#epp.path, NewName, Inc, From, St);
+ enter_file(NewName, Inc, From, St);
scan_include(_Toks, Inc, From, St) ->
epp_reply(From, {error,{abs_loc(Inc),epp,{bad,include}}}),
wait_req_scan(St).
@@ -687,9 +692,8 @@ scan_include_lib([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}],
LibName = fname_join([LibDir | Rest]),
case file:open(LibName, [read]) of
{ok,NewF} ->
- ExtraPath = [filename:dirname(LibName)],
wait_req_scan(enter_file2(NewF, LibName, From,
- St, Loc, ExtraPath));
+ St, Loc));
{error,_E2} ->
epp_reply(From,
{error,{abs_loc(Inc),epp,
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index ff032b129c..81bec21a3f 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,17 +57,7 @@ compile_cmdline(List) ->
end.
my_halt(Reason) ->
- case process_info(group_leader(), status) of
- {_,waiting} ->
- %% Now all output data is down in the driver.
- %% Give the driver some extra time before halting.
- receive after 1 -> ok end,
- halt(Reason);
- _ ->
- %% Probably still processing I/O requests.
- erlang:yield(),
- my_halt(Reason)
- end.
+ erlang:halt(Reason).
%% Run the the compiler in a separate process, trapping EXITs.
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 4f4fa16040..95ba6b1096 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -256,7 +256,8 @@ expr({'receive',_,Cs}, Bs, Lf, Ef, RBs) ->
expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs) ->
{value,T,Bs} = expr(E, Bs0, Lf, Ef, none),
receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, [], RBs);
-expr({'fun',_Line,{function,Mod,Name,Arity}}, Bs, _Lf, _Ef, RBs) ->
+expr({'fun',_Line,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) ->
+ {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef),
F = erlang:make_fun(Mod, Name, Arity),
ret_expr(F, Bs, RBs);
expr({'fun',_Line,{function,Name,Arity}}, _Bs0, _Lf, _Ef, _RBs) -> % R8
@@ -340,7 +341,7 @@ expr({call,_,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs) ->
true ->
bif(F, As, Bs3, Ef, RBs);
false ->
- do_apply({M,F}, As, Bs3, Ef, RBs)
+ do_apply(M, F, As, Bs3, Ef, RBs)
end;
expr({call,_,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs) ->
case erl_internal:bif(Func, length(As0)) of
@@ -498,11 +499,11 @@ local_func2({eval,F,As,Bs}, RBs) -> % This reply is not documented.
bif(apply, [erlang,apply,As], Bs, Ef, RBs) ->
bif(apply, As, Bs, Ef, RBs);
bif(apply, [M,F,As], Bs, Ef, RBs) ->
- do_apply({M,F}, As, Bs, Ef, RBs);
+ do_apply(M, F, As, Bs, Ef, RBs);
bif(apply, [F,As], Bs, Ef, RBs) ->
do_apply(F, As, Bs, Ef, RBs);
bif(Name, As, Bs, Ef, RBs) ->
- do_apply({erlang,Name}, As, Bs, Ef, RBs).
+ do_apply(erlang, Name, As, Bs, Ef, RBs).
%% do_apply(MF, Arguments, Bindings, ExternalFuncHandler, RBs) ->
%% {value,Value,Bindings} | Value when
@@ -562,6 +563,19 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
ret_expr(F(Func, As), Bs0, RBs)
end.
+do_apply(Mod, Func, As, Bs0, Ef, RBs) ->
+ case Ef of
+ none when RBs =:= value ->
+ %% Make tail recursive calls when possible.
+ apply(Mod, Func, As);
+ none ->
+ ret_expr(apply(Mod, Func, As), Bs0, RBs);
+ {value,F} when RBs =:= value ->
+ F({Mod,Func}, As);
+ {value,F} ->
+ ret_expr(F({Mod,Func}, As), Bs0, RBs)
+ end.
+
%% eval_lc(Expr, [Qualifier], Bindings, LocalFunctionHandler,
%% ExternalFuncHandler, RetBindings) ->
%% {value,Value,Bindings} | Value
@@ -730,10 +744,10 @@ expr_list([], Vs, _, Bs, _Lf, _Ef) ->
{reverse(Vs),Bs}.
eval_op(Op, Arg1, Arg2, Bs, Ef, RBs) ->
- do_apply({erlang,Op}, [Arg1,Arg2], Bs, Ef, RBs).
+ do_apply(erlang, Op, [Arg1,Arg2], Bs, Ef, RBs).
eval_op(Op, Arg, Bs, Ef, RBs) ->
- do_apply({erlang,Op}, [Arg], Bs, Ef, RBs).
+ do_apply(erlang, Op, [Arg], Bs, Ef, RBs).
%% if_clauses(Clauses, Bindings, LocalFuncHandler, ExtFuncHandler, RBs)
@@ -919,8 +933,9 @@ guard0([], _Bs, _Lf, _Ef) -> true.
guard_test({call,L,{atom,Ln,F},As0}, Bs0, Lf, Ef) ->
TT = type_test(F),
- guard_test({call,L,{tuple,Ln,[{atom,Ln,erlang},{atom,Ln,TT}]},As0},
- Bs0, Lf, Ef);
+ G = {call,L,{atom,Ln,TT},As0},
+ try {value,true,_} = expr(G, Bs0, Lf, Ef, none)
+ catch error:_ -> {value,false,Bs0} end;
guard_test({call,L,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,_F}=T},As0},
Bs0, Lf, Ef) ->
guard_test({call,L,T,As0}, Bs0, Lf, Ef);
@@ -932,7 +947,6 @@ type_test(integer) -> is_integer;
type_test(float) -> is_float;
type_test(number) -> is_number;
type_test(atom) -> is_atom;
-type_test(constant) -> is_constant;
type_test(list) -> is_list;
type_test(tuple) -> is_tuple;
type_test(pid) -> is_pid;
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 20fd247cea..9759a8f001 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -452,8 +452,10 @@ conj([], _E) ->
conj([{{Name,_Rp},L,R,Sz} | AL], E) ->
NL = neg_line(L),
T1 = {op,NL,'orelse',
- {call,NL,{atom,NL,is_record},[R,{atom,NL,Name},{integer,NL,Sz}]},
- {atom,NL,fail}},
+ {call,NL,
+ {remote,NL,{atom,NL,erlang},{atom,NL,is_record}},
+ [R,{atom,NL,Name},{integer,NL,Sz}]},
+ {atom,NL,fail}},
T2 = case conj(AL, none) of
empty -> T1;
C -> {op,NL,'and',C,T1}
@@ -581,7 +583,9 @@ strict_get_record_field(Line, R, {atom,_,F}=Index, Name, St0) ->
ExpRp = erl_lint:modify_line(ExpR, fun(_L) -> 0 end),
RA = {{Name,ExpRp},Line,ExpR,length(Fs)+1},
St2 = St1#exprec{strict_ra = [RA | St1#exprec.strict_ra]},
- {{call,Line,{atom,Line,element},[I,ExpR]},St2}
+ {{call,Line,
+ {remote,Line,{atom,Line,erlang},{atom,Line,element}},
+ [I,ExpR]},St2}
end.
record_pattern(I, I, Var, Sz, Line, Acc) ->
@@ -593,7 +597,9 @@ record_pattern(_, _, _, _, _, Acc) -> reverse(Acc).
sloppy_get_record_field(Line, R, Index, Name, St) ->
Fs = record_fields(Name, St),
I = index_expr(Line, Index, Name, Fs),
- expr({call,Line,{atom,Line,element},[I,R]}, St).
+ expr({call,Line,
+ {remote,Line,{atom,Line,erlang},{atom,Line,element}},
+ [I,R]}, St).
strict_record_tests([strict_record_tests | _]) -> true;
strict_record_tests([no_strict_record_tests | _]) -> false;
@@ -710,7 +716,8 @@ record_setel(R, Name, Fs, Us0) ->
{'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,
+ {call,Lf,{remote,Lf,{atom,Lf,erlang},
+ {atom,Lf,setelement}},[I,Acc,Val]} end,
R, Us)]},
{clause,NLr,[{var,NLr,'_'}],[],
[call_error(NLr, {tuple,NLr,[{atom,NLr,badrecord},{atom,NLr,Name}]})]}]}.
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index cd3b531d10..3063881890 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,6 +287,7 @@ bif(group_leader, 0) -> true;
bif(group_leader, 2) -> true;
bif(halt, 0) -> true;
bif(halt, 1) -> true;
+bif(halt, 2) -> true;
bif(hd, 1) -> true;
bif(integer_to_list, 1) -> true;
bif(integer_to_list, 2) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 78b996d94b..648ff349a4 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -248,6 +248,8 @@ format_error({illegal_guard_local_call, {F,A}}) ->
io_lib:format("call to local/imported function ~w/~w is illegal in guard",
[F,A]);
format_error(illegal_guard_expr) -> "illegal guard expression";
+format_error(deprecated_tuple_fun) ->
+ "tuple funs are deprecated and will be removed in R16";
%% --- exports ---
format_error({explicit_export,F,A}) ->
io_lib:format("in this release, the call to ~w/~w must be written "
@@ -1804,12 +1806,19 @@ guard_test(G, Vt, St0) ->
%% Specially handle record type test here.
guard_test2({call,Line,{atom,Lr,record},[E,A]}, Vt, St0) ->
gexpr({call,Line,{atom,Lr,is_record},[E,A]}, Vt, St0);
-guard_test2({call,_Line,{atom,_La,F},As}=G, Vt, St0) ->
+guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) ->
{Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this.
A = length(As),
case erl_internal:type_test(F, A) of
- true when F =/= is_record -> {Asvt,St1};
- _ -> gexpr(G, Vt, St0)
+ true when F =/= is_record, A =/= 2 ->
+ case no_guard_bif_clash(St1, {F,A}) of
+ false ->
+ {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)};
+ true ->
+ {Asvt,St1}
+ end;
+ _ ->
+ gexpr(G, Vt, St0)
end;
guard_test2(G, Vt, St) ->
%% Everything else is a guard expression.
@@ -1865,9 +1874,15 @@ gexpr({call,Line,{atom,_Lr,is_record},[E,R]}, Vt, St0) ->
gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]},
Vt, St0) ->
gexpr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0);
-gexpr({call,_Line,{atom,_Lr,is_record},[E,{atom,_,_Name},{integer,_,_}]},
+gexpr({call,Line,{atom,_Lr,is_record},[E0,{atom,_,_Name},{integer,_,_}]},
Vt, St0) ->
- gexpr(E, Vt, St0);
+ {E,St1} = gexpr(E0, Vt, St0),
+ case no_guard_bif_clash(St0, {is_record,3}) of
+ true ->
+ {E,St1};
+ false ->
+ {E,add_error(Line, {illegal_guard_local_call,{is_record,3}}, St1)}
+ end;
gexpr({call,Line,{atom,_Lr,is_record},[_,_,_]=Asvt0}, Vt, St0) ->
{Asvt,St1} = gexpr_list(Asvt0, Vt, St0),
{Asvt,add_error(Line, illegal_guard_expr, St1)};
@@ -1901,7 +1916,8 @@ gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,F}},As}, Vt, St0) ->
true -> {Asvt,St1};
false -> {Asvt,add_error(Line, illegal_guard_expr, St1)}
end;
-gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, Vt, St) ->
+gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, Vt, St0) ->
+ St = add_warning(L, deprecated_tuple_fun, St0),
gexpr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,F}},As}, Vt, St);
gexpr({op,Line,Op,A}, Vt, St0) ->
{Avt,St1} = gexpr(A, Vt, St0),
@@ -2127,8 +2143,13 @@ expr({'fun',Line,Body}, Vt, St) ->
true -> {[],St};
false -> {[],call_function(Line, F, A, St)}
end;
- {function,_M,_F,_A} ->
- {[],St}
+ {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) ->
+ %% Compatibility with pre-R15 abstract format.
+ {[],St};
+ {function,M,F,A} ->
+ %% New in R15.
+ {Bvt, St1} = expr_list([M,F,A], Vt, St),
+ {vtupdate(Bvt, Vt),St1}
end;
expr({call,_Line,{atom,_Lr,is_record},[E,{atom,Ln,Name}]}, Vt, St0) ->
{Rvt,St1} = expr(E, Vt, St0),
@@ -2762,12 +2783,6 @@ default_types() ->
{var, 1}],
dict:from_list([{T, -1} || T <- DefTypes]).
-%% R12B-5
-is_newly_introduced_builtin_type({module, 0}) -> true;
-is_newly_introduced_builtin_type({node, 0}) -> true;
-is_newly_introduced_builtin_type({nonempty_string, 0}) -> true;
-is_newly_introduced_builtin_type({term, 0}) -> true;
-is_newly_introduced_builtin_type({timeout, 0}) -> true;
%% R13
is_newly_introduced_builtin_type({arity, 0}) -> true;
is_newly_introduced_builtin_type({array, 0}) -> true; % opaque
@@ -3424,17 +3439,11 @@ obsolete_guard({call,Line,{atom,Lr,F},As}, St0) ->
false ->
deprecated_function(Line, erlang, F, As, St0);
true ->
- St1 = case F of
- constant ->
- deprecated_function(Lr, erlang, is_constant, As, St0);
- _ ->
- St0
- end,
- case is_warn_enabled(obsolete_guard, St1) of
+ case is_warn_enabled(obsolete_guard, St0) of
true ->
- add_warning(Lr,{obsolete_guard, {F, Arity}}, St1);
+ add_warning(Lr,{obsolete_guard, {F, Arity}}, St0);
false ->
- St1
+ St0
end
end;
obsolete_guard(_G, St) ->
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 709bd83e6f..928c10f7f2 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -35,7 +35,7 @@ tuple
%struct
record_expr record_tuple record_field record_fields
if_expr if_clause if_clauses case_expr cr_clause cr_clauses receive_expr
-fun_expr fun_clause fun_clauses
+fun_expr fun_clause fun_clauses atom_or_var integer_or_var
try_expr try_catch try_clause try_clauses query_expr
function_call argument_list
exprs guard
@@ -395,11 +395,17 @@ receive_expr -> 'receive' cr_clauses 'after' expr clause_body 'end' :
fun_expr -> 'fun' atom '/' integer :
{'fun',?line('$1'),{function,element(3, '$2'),element(3, '$4')}}.
-fun_expr -> 'fun' atom ':' atom '/' integer :
- {'fun',?line('$1'),{function,element(3, '$2'),element(3, '$4'),element(3,'$6')}}.
+fun_expr -> 'fun' atom_or_var ':' atom_or_var '/' integer_or_var :
+ {'fun',?line('$1'),{function,'$2','$4','$6'}}.
fun_expr -> 'fun' fun_clauses 'end' :
build_fun(?line('$1'), '$2').
+atom_or_var -> atom : '$1'.
+atom_or_var -> var : '$1'.
+
+integer_or_var -> integer : '$1'.
+integer_or_var -> var : '$1'.
+
fun_clauses -> fun_clause : ['$1'].
fun_clauses -> fun_clause ';' fun_clauses : ['$1' | '$3'].
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 7dc19f2e9b..6b5aa951cf 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -457,8 +457,16 @@ lexpr({'fun',_,{function,F,A}}, _Prec, _Hook) ->
leaf(format("fun ~w/~w", [F,A]));
lexpr({'fun',_,{function,F,A},Extra}, _Prec, _Hook) ->
{force_nl,fun_info(Extra),leaf(format("fun ~w/~w", [F,A]))};
-lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook) ->
+lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook)
+ when is_atom(M), is_atom(F), is_integer(A) ->
+ %% For backward compatibility with pre-R15 abstract format.
leaf(format("fun ~w:~w/~w", [M,F,A]));
+lexpr({'fun',_,{function,M,F,A}}, _Prec, Hook) ->
+ %% New format in R15.
+ NameItem = lexpr(M, Hook),
+ CallItem = lexpr(F, Hook),
+ ArityItem = lexpr(A, Hook),
+ ["fun ",NameItem,$:,CallItem,$/,ArityItem];
lexpr({'fun',_,{clauses,Cs}}, _Prec, Hook) ->
{list,[{first,'fun',fun_clauses(Cs, Hook)},'end']};
lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Hook) ->
diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl
index ee4f0b3a51..e9364ed787 100644
--- a/lib/stdlib/src/error_logger_file_h.erl
+++ b/lib/stdlib/src/error_logger_file_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -104,7 +104,7 @@ code_change(_OldVsn, State, _Extra) ->
%%% ------------------------------------------------------
tag_event(Event) ->
- {erlang:localtime(), Event}.
+ {erlang:universaltime(), Event}.
write_events(Fd, Events) -> write_events1(Fd, lists:reverse(Events)).
@@ -169,23 +169,18 @@ write_event(_, _) ->
maybe_utc(Time) ->
UTC = case application:get_env(sasl, utc_log) of
- {ok, Val} ->
- Val;
+ {ok, Val} -> Val;
undefined ->
%% Backwards compatible:
case application:get_env(stdlib, utc_log) of
- {ok, Val} ->
- Val;
- undefined ->
- false
+ {ok, Val} -> Val;
+ undefined -> false
end
end,
- if
- UTC =:= true ->
- {utc, calendar:local_time_to_universal_time(Time)};
- true ->
- Time
- end.
+ maybe_utc(Time, UTC).
+
+maybe_utc(Time, true) -> {utc, Time};
+maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}.
format_report(Rep) when is_list(Rep) ->
case string_p(Rep) of
@@ -238,7 +233,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT").
write_time({utc,{{Y,Mo,D},{H,Mi,S}}}, Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]);
-write_time({{Y,Mo,D},{H,Mi,S}}, Type) ->
+write_time({local, {{Y,Mo,D},{H,Mi,S}}}, Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]).
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index fa13fbb2bd..ad5891f191 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,7 +97,7 @@ set_group_leader() ->
end.
tag_event(Event) ->
- {erlang:localtime(), Event}.
+ {erlang:universaltime(), Event}.
write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod).
@@ -162,23 +162,18 @@ write_event({_Time, _Error},_IOMod) ->
maybe_utc(Time) ->
UTC = case application:get_env(sasl, utc_log) of
- {ok, Val} ->
- Val;
+ {ok, Val} -> Val;
undefined ->
%% Backwards compatible:
case application:get_env(stdlib, utc_log) of
- {ok, Val} ->
- Val;
- undefined ->
- false
+ {ok, Val} -> Val;
+ undefined -> false
end
end,
- if
- UTC =:= true ->
- {utc, calendar:local_time_to_universal_time(Time)};
- true ->
- Time
- end.
+ maybe_utc(Time, UTC).
+
+maybe_utc(Time, true) -> {utc, Time};
+maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}.
format(IOMod, String) -> format(IOMod, String, []).
format(io_lib, String, Args) -> io_lib:format(String, Args);
@@ -234,7 +229,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT").
write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]);
-write_time({{Y,Mo,D},{H,Mi,S}},Type) ->
+write_time({local, {{Y,Mo,D},{H,Mi,S}}},Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]).
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index ad49d89908..498d850df3 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
-export([script_name/0, create/2, extract/2]).
%% Internal API.
--export([start/0, start/1]).
+-export([start/0, start/1, parse_file/1]).
%%-----------------------------------------------------------------------
@@ -346,7 +346,8 @@ parse_and_run(File, Args, Options) ->
case Source of
archive ->
{ok, FileInfo} = file:read_file_info(File),
- case code:set_primary_archive(File, FormsOrBin, FileInfo) of
+ case code:set_primary_archive(File, FormsOrBin, FileInfo,
+ fun escript:parse_file/1) of
ok when CheckOnly ->
case code:load_file(Module) of
{module, _} ->
@@ -396,6 +397,19 @@ parse_and_run(File, Args, Options) ->
%% Parse script
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Only used as callback by erl_prim_loader
+parse_file(File) ->
+ try parse_file(File, false) of
+ {_Source, _Module, FormsOrBin, _HasRecs, _Mode}
+ when is_binary(FormsOrBin) ->
+ {ok, FormsOrBin};
+ _ ->
+ {error, no_archive_bin}
+ catch
+ throw:Reason ->
+ {error, Reason}
+ end.
+
parse_file(File, CheckOnly) ->
{HeaderSz, NextLineNo, Fd, Sections} =
parse_header(File, false),
@@ -848,17 +862,7 @@ fatal(Str) ->
throw(Str).
my_halt(Reason) ->
- case process_info(group_leader(), status) of
- {_,waiting} ->
- %% Now all output data is down in the driver.
- %% Give the driver some extra time before halting.
- receive after 1 -> ok end,
- halt(Reason);
- _ ->
- %% Probably still processing I/O requests.
- erlang:yield(),
- my_halt(Reason)
- end.
+ erlang:halt(Reason).
hidden_apply(App, M, F, Args) ->
try
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index d532cea187..b098d4cb91 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -264,6 +264,9 @@ ensure_dir(F) ->
case do_is_dir(Dir, file) of
true ->
ok;
+ false when Dir =:= F ->
+ %% Protect against infinite loop
+ {error,einval};
false ->
ensure_dir(Dir),
case file:make_dir(Dir) of
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 1cb9e4a25e..870af4e95f 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -147,9 +147,10 @@ basename(Name) when is_binary(Name) ->
end;
basename(Name0) ->
- Name = flatten(Name0),
+ Name1 = flatten(Name0),
{DirSep2, DrvSep} = separators(),
- basename1(skip_prefix(Name, DrvSep), [], DirSep2).
+ Name = skip_prefix(Name1, DrvSep),
+ basename1(Name, Name, DirSep2).
win_basenameb(<<Letter,$:,Rest/binary>>) when ?IS_DRIVELETTER(Letter) ->
basenameb(Rest,[<<"/">>,<<"\\">>]);
@@ -167,16 +168,18 @@ basenameb(Bin,Sep) ->
-basename1([$/|[]], Tail, DirSep2) ->
- basename1([], Tail, DirSep2);
+basename1([$/], Tail0, _DirSep2) ->
+ %% End of filename -- must get rid of trailing directory separator.
+ [_|Tail] = lists:reverse(Tail0),
+ lists:reverse(Tail);
basename1([$/|Rest], _Tail, DirSep2) ->
- basename1(Rest, [], DirSep2);
+ basename1(Rest, Rest, DirSep2);
basename1([DirSep2|Rest], Tail, DirSep2) when is_integer(DirSep2) ->
basename1([$/|Rest], Tail, DirSep2);
basename1([Char|Rest], Tail, DirSep2) when is_integer(Char) ->
- basename1(Rest, [Char|Tail], DirSep2);
+ basename1(Rest, Tail, DirSep2);
basename1([], Tail, _DirSep2) ->
- lists:reverse(Tail).
+ Tail.
skip_prefix(Name, false) ->
Name;
@@ -369,8 +372,8 @@ extension(Name0) ->
Name = flatten(Name0),
extension(Name, [], major_os_type()).
-extension([$.|Rest], _Result, OsType) ->
- extension(Rest, [$.], OsType);
+extension([$.|Rest]=Result, _Result, OsType) ->
+ extension(Rest, Result, OsType);
extension([Char|Rest], [], OsType) when is_integer(Char) ->
extension(Rest, [], OsType);
extension([$/|Rest], _Result, OsType) ->
@@ -378,9 +381,9 @@ extension([$/|Rest], _Result, OsType) ->
extension([$\\|Rest], _Result, win32) ->
extension(Rest, [], win32);
extension([Char|Rest], Result, OsType) when is_integer(Char) ->
- extension(Rest, [Char|Result], OsType);
+ extension(Rest, Result, OsType);
extension([], Result, _OsType) ->
- lists:reverse(Result).
+ Result.
%% Joins a list of filenames with directory separators.
@@ -723,6 +726,8 @@ nativename(Name0) ->
_ -> Name
end.
+win32_nativename(Name) when is_binary(Name) ->
+ binary:replace(Name, <<"/">>, <<"\\">>, [global]);
win32_nativename([$/|Rest]) ->
[$\\|win32_nativename(Rest)];
win32_nativename([C|Rest]) ->
@@ -833,16 +838,18 @@ try_file(undefined, ObjFilename, Mod, Rules) ->
Error -> Error
end;
try_file(Src, _ObjFilename, Mod, _Rules) ->
- List = Mod:module_info(compile),
- {options, Options} = lists:keyfind(options, 1, List),
+ List = case Mod:module_info(compile) of
+ none -> [];
+ List0 -> List0
+ end,
+ Options = proplists:get_value(options, List, []),
{ok, Cwd} = file:get_cwd(),
AbsPath = make_abs_path(Cwd, Src),
{AbsPath, filter_options(dirname(AbsPath), Options, [])}.
%% Filters the options.
%%
-%% 1) Remove options that have no effect on the generated code,
-%% such as report and verbose.
+%% 1) Only keep options that have any effect on code generation.
%%
%% 2) The paths found in {i, Path} and {outdir, Path} are converted
%% to absolute paths. When doing this, it is assumed that relatives
@@ -854,14 +861,10 @@ filter_options(Base, [{outdir, Path}|Rest], Result) ->
filter_options(Base, Rest, [{outdir, make_abs_path(Base, Path)}|Result]);
filter_options(Base, [{i, Path}|Rest], Result) ->
filter_options(Base, Rest, [{i, make_abs_path(Base, Path)}|Result]);
-filter_options(Base, [Option|Rest], Result) when Option =:= trace ->
- filter_options(Base, Rest, [Option|Result]);
filter_options(Base, [Option|Rest], Result) when Option =:= export_all ->
filter_options(Base, Rest, [Option|Result]);
filter_options(Base, [Option|Rest], Result) when Option =:= binary ->
filter_options(Base, Rest, [Option|Result]);
-filter_options(Base, [Option|Rest], Result) when Option =:= fast ->
- filter_options(Base, Rest, [Option|Result]);
filter_options(Base, [Tuple|Rest], Result) when element(1, Tuple) =:= d ->
filter_options(Base, Rest, [Tuple|Result]);
filter_options(Base, [Tuple|Rest], Result)
@@ -875,12 +878,7 @@ filter_options(_Base, [], Result) ->
%% Gets the source file given path of object code and module name.
get_source_file(Obj, Mod, Rules) ->
- case catch Mod:module_info(source_file) of
- {'EXIT', _Reason} ->
- source_by_rules(dirname(Obj), packages:last(Mod), Rules);
- File ->
- {ok, File}
- end.
+ source_by_rules(dirname(Obj), packages:last(Mod), Rules).
source_by_rules(Dir, Base, [{From, To}|Rest]) ->
case try_rule(Dir, Base, From, To) of
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 574146b1cd..42555aedd7 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.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,7 +36,7 @@
%%-----------------------------------------------------------------
-type linkage() :: 'link' | 'nolink'.
--type emgr_name() :: {'local', atom()} | {'global', term()}.
+-type emgr_name() :: {'local', atom()} | {'global', term()} | {via, atom(), term()}.
-type start_ret() :: {'ok', pid()} | 'ignore' | {'error', term()}.
@@ -53,7 +53,7 @@
%% start(GenMod, LinkP, Name, Mod, Args, Options)
%% GenMod = atom(), callback module implementing the 'real' fsm
%% LinkP = link | nolink
-%% Name = {local, atom()} | {global, term()}
+%% Name = {local, atom()} | {global, term()} | {via, atom(), term()}
%% Args = term(), init arguments (to Mod:init/1)
%% Options = [{timeout, Timeout} | {debug, [Flag]} | {spawn_opt, OptionList}]
%% Flag = trace | log | {logfile, File} | statistics | debug
@@ -158,9 +158,12 @@ call(Name, Label, Request, Timeout)
exit(noproc)
end;
%% Global by name
-call({global, _Name}=Process, Label, Request, Timeout)
- when Timeout =:= infinity;
- is_integer(Timeout), Timeout >= 0 ->
+call(Process, Label, Request, Timeout)
+ when ((tuple_size(Process) == 2 andalso element(1, Process) == global)
+ orelse
+ (tuple_size(Process) == 3 andalso element(1, Process) == via))
+ andalso
+ (Timeout =:= infinity orelse (is_integer(Timeout) andalso Timeout >= 0)) ->
case where(Process) of
Pid when is_pid(Pid) ->
Node = node(Pid),
@@ -273,7 +276,8 @@ reply({To, Tag}, Reply) ->
%%%-----------------------------------------------------------------
%%% Misc. functions.
%%%-----------------------------------------------------------------
-where({global, Name}) -> global:safe_whereis_name(Name);
+where({global, Name}) -> global:whereis_name(Name);
+where({via, Module, Name}) -> Module:whereis_name(Name);
where({local, Name}) -> whereis(Name).
name_register({local, Name} = LN) ->
@@ -287,8 +291,16 @@ name_register({global, Name} = GN) ->
case global:register_name(Name, self()) of
yes -> true;
no -> {false, where(GN)}
+ end;
+name_register({via, Module, Name} = GN) ->
+ case Module:register_name(Name, self()) of
+ yes ->
+ true;
+ no ->
+ {false, where(GN)}
end.
+
timeout(Options) ->
case opt(timeout, Options) of
{ok, Time} ->
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index 9879b76391..2b8ba86909 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,7 +70,8 @@
-callback init(InitArgs :: term()) ->
{ok, State :: term()} |
- {ok, State :: term(), hibernate}.
+ {ok, State :: term(), hibernate} |
+ {error, Reason :: term()}.
-callback handle_event(Event :: term(), State :: term()) ->
{ok, NewState :: term()} |
{ok, NewState :: term(), hibernate} |
@@ -106,8 +107,10 @@
-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 emgr_name() :: {'local', atom()} | {'global', atom()}
+ | {'via', atom(), term()}.
+-type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()}
+ | {'via', atom(), term()} | pid().
-type start_ret() :: {'ok', pid()} | {'error', term()}.
%%---------------------------------------------------------------------------
@@ -142,6 +145,7 @@ init_it(Starter, Parent, Name0, _, _, Options) ->
name({local,Name}) -> Name;
name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
-spec add_handler(emgr_ref(), handler(), term()) -> term().
@@ -208,6 +212,9 @@ call1(M, Handler, Query, Timeout) ->
send({global, Name}, Cmd) ->
catch global:send(Name, Cmd),
ok;
+send({via, Mod, Name}, Cmd) ->
+ catch Mod:send(Name, Cmd),
+ ok;
send(M, Cmd) ->
M ! Cmd,
ok.
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 3db8c9f4f2..e480e2ac11 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -165,7 +165,7 @@
%%% start(Name, Mod, Args, Options)
%%% start_link(Mod, Args, Options)
%%% start_link(Name, Mod, Args, Options) where:
-%%% Name ::= {local, atom()} | {global, atom()}
+%%% Name ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
%%% Mod ::= atom(), callback module implementing the 'real' fsm
%%% Args ::= term(), init arguments (to Mod:init/1)
%%% Options ::= [{debug, [Flag]}]
@@ -191,6 +191,9 @@ start_link(Name, Mod, Args, Options) ->
send_event({global, Name}, Event) ->
catch global:send(Name, {'$gen_event', Event}),
ok;
+send_event({via, Mod, Name}, Event) ->
+ catch Mod:send(Name, {'$gen_event', Event}),
+ ok;
send_event(Name, Event) ->
Name ! {'$gen_event', Event},
ok.
@@ -214,6 +217,9 @@ sync_send_event(Name, Event, Timeout) ->
send_all_state_event({global, Name}, Event) ->
catch global:send(Name, {'$gen_all_state_event', Event}),
ok;
+send_all_state_event({via, Mod, Name}, Event) ->
+ catch Mod:send(Name, {'$gen_all_state_event', Event}),
+ ok;
send_all_state_event(Name, Event) ->
Name ! {'$gen_all_state_event', Event},
ok.
@@ -273,7 +279,10 @@ cancel_timer(Ref) ->
enter_loop(Mod, Options, StateName, StateData) ->
enter_loop(Mod, Options, StateName, StateData, self(), infinity).
-enter_loop(Mod, Options, StateName, StateData, ServerName = {_,_}) ->
+enter_loop(Mod, Options, StateName, StateData, {Scope,_} = ServerName)
+ when Scope == local; Scope == global ->
+ enter_loop(Mod, Options, StateName, StateData, ServerName,infinity);
+enter_loop(Mod, Options, StateName, StateData, {via,_,_} = ServerName) ->
enter_loop(Mod, Options, StateName, StateData, ServerName,infinity);
enter_loop(Mod, Options, StateName, StateData, Timeout) ->
enter_loop(Mod, Options, StateName, StateData, self(), Timeout).
@@ -296,13 +305,22 @@ get_proc_name({local, Name}) ->
exit(process_not_registered)
end;
get_proc_name({global, Name}) ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
exit(process_not_registered_globally);
Pid when Pid =:= self() ->
Name;
_Pid ->
exit(process_not_registered_globally)
+ end;
+get_proc_name({via, Mod, Name}) ->
+ case Mod:whereis_name(Name) of
+ undefined ->
+ exit({process_not_registered_via, Mod});
+ Pid when Pid =:= self() ->
+ Name;
+ _Pid ->
+ exit({process_not_registered_via, Mod})
end.
get_parent() ->
@@ -318,9 +336,9 @@ get_parent() ->
name_to_pid(Name) ->
case whereis(Name) of
undefined ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
- exit(could_not_find_registerd_name);
+ exit(could_not_find_registered_name);
Pid ->
Pid
end;
@@ -348,12 +366,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, StateName, StateData, Mod, Timeout, Debug);
{stop, Reason} ->
+ unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
ignore ->
+ unregister_name(Name0),
proc_lib:init_ack(Starter, ignore),
exit(normal);
{'EXIT', Reason} ->
+ unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
Else ->
@@ -364,8 +385,18 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
name({local,Name}) -> Name;
name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
+unregister_name({local,Name}) ->
+ _ = (catch unregister(Name));
+unregister_name({global,Name}) ->
+ _ = global:unregister_name(Name);
+unregister_name({via, Mod, Name}) ->
+ _ = Mod:unregister_name(Name);
+unregister_name(Pid) when is_pid(Pid) ->
+ Pid.
+
%%-----------------------------------------------------------------
%% The MAIN loop
%%-----------------------------------------------------------------
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index dd0ef74f30..04308a51b7 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -134,7 +134,7 @@
term().
-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(),
Extra :: term()) ->
- {ok, NewState :: term()}.
+ {ok, NewState :: term()} | {error, Reason :: term()}.
%%% -----------------------------------------------------------------
%%% Starts a generic server.
@@ -142,7 +142,7 @@
%%% start(Name, Mod, Args, Options)
%%% start_link(Mod, Args, Options)
%%% start_link(Name, Mod, Args, Options) where:
-%%% Name ::= {local, atom()} | {global, atom()}
+%%% Name ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
%%% Mod ::= atom(), callback module implementing the 'real' server
%%% Args ::= term(), init arguments (to Mod:init/1)
%%% Options ::= [{timeout, Timeout} | {debug, [Flag]}]
@@ -194,6 +194,9 @@ call(Name, Request, Timeout) ->
cast({global,Name}, Request) ->
catch global:send(Name, cast_msg(Request)),
ok;
+cast({via, Mod, Name}, Request) ->
+ catch Mod:send(Name, cast_msg(Request)),
+ ok;
cast({Name,Node}=Dest, Request) when is_atom(Name), is_atom(Node) ->
do_cast(Dest, Request);
cast(Dest, Request) when is_atom(Dest) ->
@@ -266,7 +269,11 @@ multi_call(Nodes, Name, Req, Timeout)
enter_loop(Mod, Options, State) ->
enter_loop(Mod, Options, State, self(), infinity).
-enter_loop(Mod, Options, State, ServerName = {_, _}) ->
+enter_loop(Mod, Options, State, ServerName = {Scope, _})
+ when Scope == local; Scope == global ->
+ enter_loop(Mod, Options, State, ServerName, infinity);
+
+enter_loop(Mod, Options, State, ServerName = {via, _, _}) ->
enter_loop(Mod, Options, State, ServerName, infinity);
enter_loop(Mod, Options, State, Timeout) ->
@@ -327,12 +334,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
name({local,Name}) -> Name;
name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
unregister_name({local,Name}) ->
_ = (catch unregister(Name));
unregister_name({global,Name}) ->
_ = global:unregister_name(Name);
+unregister_name({via, Mod, Name}) ->
+ _ = Mod:unregister_name(Name);
unregister_name(Pid) when is_pid(Pid) ->
Pid.
@@ -820,13 +830,22 @@ get_proc_name({local, Name}) ->
exit(process_not_registered)
end;
get_proc_name({global, Name}) ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
exit(process_not_registered_globally);
Pid when Pid =:= self() ->
Name;
_Pid ->
exit(process_not_registered_globally)
+ end;
+get_proc_name({via, Mod, Name}) ->
+ case Mod:whereis_name(Name) of
+ undefined ->
+ exit({process_not_registered_via, Mod});
+ Pid when Pid =:= self() ->
+ Name;
+ _Pid ->
+ exit({process_not_registered_via, Mod})
end.
get_parent() ->
@@ -842,9 +861,9 @@ get_parent() ->
name_to_pid(Name) ->
case whereis(Name) of
undefined ->
- case global:safe_whereis_name(Name) of
+ case global:whereis_name(Name) of
undefined ->
- exit(could_not_find_registerd_name);
+ exit(could_not_find_registered_name);
Pid ->
Pid
end;
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
index 314fd60903..cf4b87d7eb 100644
--- a/lib/stdlib/src/lib.erl
+++ b/lib/stdlib/src/lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -209,7 +209,7 @@ explain_reason(badarg, error, [], _PF, _S) ->
explain_reason({badarg,V}, error=Cl, [], PF, S) -> % orelse, andalso
format_value(V, <<"bad argument: ">>, Cl, PF, S);
explain_reason(badarith, error, [], _PF, _S) ->
- <<"bad argument in an arithmetic expression">>;
+ <<"an error occurred when evaluating an arithmetic expression">>;
explain_reason({badarity,{Fun,As}}, error, [], _PF, _S)
when is_function(Fun) ->
%% Only the arity is displayed, not the arguments As.
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 48e22e53fa..4389fd457c 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -333,17 +333,18 @@ form({function,Line,Name0,Arity0,Clauses0}) ->
form(AnyOther) ->
AnyOther.
function(Name, Arity, Clauses0) ->
- {Clauses1,_} = clauses(Clauses0,gb_sets:new()),
+ Clauses1 = clauses(Clauses0),
{Name,Arity,Clauses1}.
-clauses([C0|Cs],Bound) ->
- {C1,Bound1} = clause(C0,Bound),
- {C2,Bound2} = clauses(Cs,Bound1),
- {[C1|C2],Bound2};
-clauses([],Bound) -> {[],Bound}.
+clauses([C0|Cs]) ->
+ C1 = clause(C0,gb_sets:new()),
+ C2 = clauses(Cs),
+ [C1|C2];
+clauses([]) -> [].
+
clause({clause,Line,H0,G0,B0},Bound) ->
{H1,Bound1} = copy(H0,Bound),
- {B1,Bound2} = copy(B0,Bound1),
- {{clause,Line,H1,G0,B1},Bound2}.
+ {B1,_Bound2} = copy(B0,Bound1),
+ {clause,Line,H1,G0,B1}.
copy({call,Line,{remote,_Line2,{atom,_Line3,ets},{atom,_Line4,fun2ms}},
As0},Bound) ->
@@ -880,7 +881,6 @@ translate_language_element(Atom) ->
end.
old_bool_test(atom,1) -> is_atom;
-old_bool_test(constant,1) -> is_constant;
old_bool_test(float,1) -> is_float;
old_bool_test(integer,1) -> is_integer;
old_bool_test(list,1) -> is_list;
@@ -895,7 +895,6 @@ old_bool_test(record,2) -> is_record;
old_bool_test(_,_) -> undefined.
bool_test(is_atom,1) -> true;
-bool_test(is_constant,1) -> true;
bool_test(is_float,1) -> true;
bool_test(is_integer,1) -> true;
bool_test(is_list,1) -> true;
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index c1285dab60..b9fbef9ed0 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The 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,37 +41,12 @@ obsolete(Module, Name, Arity) ->
no
end.
-obsolete_1(init, get_flag, 1) ->
- {removed, {init, get_argument, 1}, "R12B"};
-obsolete_1(init, get_flags, 0) ->
- {removed, {init, get_arguments, 0}, "R12B"};
-obsolete_1(init, get_args, 0) ->
- {removed, {init, get_plain_arguments, 0}, "R12B"};
-obsolete_1(unix, cmd, 1) ->
- {removed, {os,cmd,1}, "R9B"};
-
obsolete_1(net, _, _) ->
{deprecated, "module 'net' obsolete; use 'net_adm'"};
obsolete_1(erl_internal, builtins, 0) ->
{deprecated, {erl_internal, bif, 2}};
-obsolete_1(string, re_sh_to_awk, 1) ->
- {removed, {regexp, sh_to_awk, 1}, "R12B"};
-obsolete_1(string, re_parse, 1) ->
- {removed, {regexp, parse, 1}, "R12B"};
-obsolete_1(string, re_match, 2) ->
- {removed, {regexp, match, 2}, "R12B"};
-obsolete_1(string, re_sub, 3) ->
- {removed, {regexp, sub, 3}, "R12B"};
-obsolete_1(string, re_gsub, 3) ->
- {removed, {regexp, gsub, 3}, "R12B"};
-obsolete_1(string, re_split, 2) ->
- {removed, {regexp, split, 2}, "R12B"};
-
-obsolete_1(string, index, 2) ->
- {removed, {string, str, 2}, "R12B"};
-
obsolete_1(erl_eval, seq, 2) ->
{deprecated, {erl_eval, exprs, 2}};
obsolete_1(erl_eval, seq, 3) ->
@@ -81,99 +56,9 @@ obsolete_1(erl_eval, arg_list, 2) ->
obsolete_1(erl_eval, arg_list, 3) ->
{deprecated, {erl_eval, expr_list, 3}};
-obsolete_1(erl_pp, seq, 1) ->
- {removed, {erl_pp, exprs, 1}, "R12B"};
-obsolete_1(erl_pp, seq, 2) ->
- {removed, {erl_pp, exprs, 2}, "R12B"};
-
-obsolete_1(io, scan_erl_seq, 1) ->
- {removed, {io, scan_erl_exprs, 1}, "R12B"};
-obsolete_1(io, scan_erl_seq, 2) ->
- {removed, {io, scan_erl_exprs, 2}, "R12B"};
-obsolete_1(io, scan_erl_seq, 3) ->
- {removed, {io, scan_erl_exprs, 3}, "R12B"};
-obsolete_1(io, parse_erl_seq, 1) ->
- {removed, {io, parse_erl_exprs, 1}, "R12B"};
-obsolete_1(io, parse_erl_seq, 2) ->
- {removed, {io, parse_erl_exprs, 2}, "R12B"};
-obsolete_1(io, parse_erl_seq, 3) ->
- {removed, {io, parse_erl_exprs, 3}, "R12B"};
-obsolete_1(io, parse_exprs, 2) ->
- {removed, {io, parse_erl_exprs, 2}, "R12B"};
-
-obsolete_1(io_lib, scan, 1) ->
- {removed, {erl_scan, string, 1}, "R12B"};
-obsolete_1(io_lib, scan, 2) ->
- {removed, {erl_scan, string, 2}, "R12B"};
-obsolete_1(io_lib, scan, 3) ->
- {removed, {erl_scan, tokens, 3}, "R12B"};
-obsolete_1(io_lib, reserved_word, 1) ->
- {removed, {erl_scan, reserved_word, 1}, "R12B"};
-
-obsolete_1(lists, keymap, 4) ->
- {removed, {lists, keymap, 3}, "R12B"};
-obsolete_1(lists, all, 3) ->
- {removed, {lists, all, 2}, "R12B"};
-obsolete_1(lists, any, 3) ->
- {removed, {lists, any, 2}, "R12B"};
-obsolete_1(lists, map, 3) ->
- {removed, {lists, map, 2}, "R12B"};
-obsolete_1(lists, flatmap, 3) ->
- {removed, {lists, flatmap, 2}, "R12B"};
-obsolete_1(lists, foldl, 4) ->
- {removed, {lists, foldl, 3}, "R12B"};
-obsolete_1(lists, foldr, 4) ->
- {removed, {lists, foldr, 3}, "R12B"};
-obsolete_1(lists, mapfoldl, 4) ->
- {removed, {lists, mapfoldl, 3}, "R12B"};
-obsolete_1(lists, mapfoldr, 4) ->
- {removed, {lists, mapfoldr, 3}, "R12B"};
-obsolete_1(lists, filter, 3) ->
- {removed, {lists, filter, 2}, "R12B"};
-obsolete_1(lists, foreach, 3) ->
- {removed, {lists, foreach, 2}, "R12B"};
-obsolete_1(lists, zf, 3) ->
- {removed, {lists, zf, 2}, "R12B"};
-
-obsolete_1(ets, fixtable, 2) ->
- {removed, {ets, safe_fixtable, 2}, "R12B"};
-
-obsolete_1(erlang, old_binary_to_term, 1) ->
- {removed, {erlang, binary_to_term, 1}, "R12B"};
-obsolete_1(erlang, info, 1) ->
- {removed, {erlang, system_info, 1}, "R12B"};
obsolete_1(erlang, hash, 2) ->
{deprecated, {erlang, phash2, 2}};
-obsolete_1(file, file_info, 1) ->
- {removed, {file, read_file_info, 1}, "R12B"};
-
-obsolete_1(dict, dict_to_list, 1) ->
- {removed, {dict,to_list,1}, "R12B"};
-obsolete_1(dict, list_to_dict, 1) ->
- {removed, {dict,from_list,1}, "R12B"};
-obsolete_1(orddict, dict_to_list, 1) ->
- {removed, {orddict,to_list,1}, "R12B"};
-obsolete_1(orddict, list_to_dict, 1) ->
- {removed, {orddict,from_list,1}, "R12B"};
-
-obsolete_1(sets, new_set, 0) ->
- {removed, {sets, new, 0}, "R12B"};
-obsolete_1(sets, set_to_list, 1) ->
- {removed, {sets, to_list, 1}, "R12B"};
-obsolete_1(sets, list_to_set, 1) ->
- {removed, {sets, from_list, 1}, "R12B"};
-obsolete_1(sets, subset, 2) ->
- {removed, {sets, is_subset, 2}, "R12B"};
-obsolete_1(ordsets, new_set, 0) ->
- {removed, {ordsets, new, 0}, "R12B"};
-obsolete_1(ordsets, set_to_list, 1) ->
- {removed, {ordsets, to_list, 1}, "R12B"};
-obsolete_1(ordsets, list_to_set, 1) ->
- {removed, {ordsets, from_list, 1}, "R12B"};
-obsolete_1(ordsets, subset, 2) ->
- {removed, {ordsets, is_subset, 2}, "R12B"};
-
obsolete_1(calendar, local_time_to_universal_time, 1) ->
{deprecated, {calendar, local_time_to_universal_time_dst, 1}};
@@ -302,17 +187,6 @@ obsolete_1(auth, node_cookie, 1) ->
obsolete_1(auth, node_cookie, 2) ->
{deprecated, "Deprecated; use erlang:set_cookie/2 and net_adm:ping/1 instead"};
-%% Added in R11B-5.
-obsolete_1(http_base_64, _, _) ->
- {removed, "The http_base_64 module was removed in R12B; use the base64 module instead"};
-obsolete_1(httpd_util, encode_base64, 1) ->
- {removed, "Removed in R12B; use one of the encode functions in the base64 module instead"};
-obsolete_1(httpd_util, decode_base64, 1) ->
- {removed, "Removed in R12B; use one of the decode functions in the base64 module instead"};
-obsolete_1(httpd_util, to_upper, 1) ->
- {removed, {string, to_upper, 1}, "R12B"};
-obsolete_1(httpd_util, to_lower, 1) ->
- {removed, {string, to_lower, 1}, "R12B"};
obsolete_1(erlang, is_constant, 1) ->
{removed, "Removed in R13B"};
@@ -431,7 +305,7 @@ obsolete_1(ssh_sshd, stop, 1) ->
%% Added in R13A.
obsolete_1(regexp, _, _) ->
- {deprecated, "the regexp module is deprecated (will be removed in R15A); use the re module instead"};
+ {removed, "removed in R15; use the re module instead"};
obsolete_1(lists, flat_length, 1) ->
{removed,{lists,flatlength,1},"R14"};
@@ -463,20 +337,31 @@ obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
%% Added in R14B03.
obsolete_1(docb_gen, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_transform, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_xml_check, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was 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(ssl, pid, 1) ->
+ {deprecated,"deprecated (will be removed in R17); is no longer needed"};
+obsolete_1(inviso, _, _) ->
+ {deprecated,"the inviso application has been deprecated and will be removed in R16"};
+
+%% Added in R15B01.
+obsolete_1(gs, _, _) ->
+ {deprecated,"the gs application has been deprecated and will be removed in R16; use the wx application instead"};
+obsolete_1(ssh, sign_data, 2) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
+ "and public_key:sign/3 instead"};
+obsolete_1(ssh, verify_data, 3) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:ssh_decode/1, and public_key:verify/4 instead"};
obsolete_1(_, _, _) ->
no.
-
-spec is_snmp_agent_function(atom(), byte()) -> boolean().
is_snmp_agent_function(c, 1) -> true;
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index f5e180b4bd..2b691e6abf 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -1272,7 +1272,10 @@ abstr_term(Fun, Line) when is_function(Fun) ->
case erlang:fun_info(Fun, type) of
{type, external} ->
{module, Module} = erlang:fun_info(Fun, module),
- {'fun', Line, {function,Module,Name,Arity}};
+ {'fun', Line, {function,
+ {atom,Line,Module},
+ {atom,Line,Name},
+ {integer,Line,Arity}}};
{type, local} ->
{'fun', Line, {function,Name,Arity}}
end
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index dbb524cc74..d7b51a151c 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -26,6 +26,10 @@
-export([seed/0, seed/1, seed/3, uniform/0, uniform/1,
uniform_s/1, uniform_s/2, seed0/0]).
+-define(PRIME1, 30269).
+-define(PRIME2, 30307).
+-define(PRIME3, 30323).
+
%%-----------------------------------------------------------------------
%% The type of the state
@@ -44,7 +48,11 @@ seed0() ->
-spec seed() -> ran().
seed() ->
- reseed(seed0()).
+ case seed_put(seed0()) of
+ undefined -> seed0();
+ {_,_,_} = Tuple -> Tuple
+ end.
+
%% seed({A1, A2, A3})
%% Seed random number generation
@@ -66,17 +74,15 @@ seed({A1, A2, A3}) ->
A3 :: integer().
seed(A1, A2, A3) ->
- put(random_seed,
- {abs(A1) rem 30269, abs(A2) rem 30307, abs(A3) rem 30323}).
+ seed_put({(abs(A1) rem (?PRIME1-1)) + 1, % Avoid seed numbers that are
+ (abs(A2) rem (?PRIME2-1)) + 1, % even divisors of the
+ (abs(A3) rem (?PRIME3-1)) + 1}). % corresponding primes.
--spec reseed(ran()) -> ran().
-
-reseed({A1, A2, A3}) ->
- case seed(A1, A2, A3) of
- undefined -> seed0();
- {_,_,_} = Tuple -> Tuple
- end.
+-spec seed_put(ran()) -> 'undefined' | ran().
+
+seed_put(Seed) ->
+ put(random_seed, Seed).
%% uniform()
%% Returns a random float between 0 and 1.
@@ -88,11 +94,11 @@ uniform() ->
undefined -> seed0();
Tuple -> Tuple
end,
- B1 = (A1*171) rem 30269,
- B2 = (A2*172) rem 30307,
- B3 = (A3*170) rem 30323,
+ B1 = (A1*171) rem ?PRIME1,
+ B2 = (A2*172) rem ?PRIME2,
+ B3 = (A3*170) rem ?PRIME3,
put(random_seed, {B1,B2,B3}),
- R = A1/30269 + A2/30307 + A3/30323,
+ R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
R - trunc(R).
%% uniform(N) -> I
@@ -116,10 +122,10 @@ uniform(N) when is_integer(N), N >= 1 ->
State1 :: ran().
uniform_s({A1, A2, A3}) ->
- B1 = (A1*171) rem 30269,
- B2 = (A2*172) rem 30307,
- B3 = (A3*170) rem 30323,
- R = A1/30269 + A2/30307 + A3/30323,
+ B1 = (A1*171) rem ?PRIME1,
+ B2 = (A2*172) rem ?PRIME2,
+ B3 = (A3*170) rem ?PRIME3,
+ R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
{R - trunc(R), {B1,B2,B3}}.
%% uniform_s(N, State) -> {I, NewState}
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index 99bcbd722e..246d535943 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -48,7 +48,7 @@ split(Subject,RE) ->
Subject :: iodata() | unicode:charlist(),
RE :: mp() | iodata() | unicode:charlist(),
Options :: [ Option ],
- Option :: anchored | global | notbol | noteol | notempty
+ Option :: anchored | notbol | noteol | notempty
| {offset, non_neg_integer()} | {newline, nl_spec()}
| bsr_anycrlf | bsr_unicode | {return, ReturnType}
| {parts, NumParts} | group | trim | CompileOpt,
diff --git a/lib/stdlib/src/regexp.erl b/lib/stdlib/src/regexp.erl
deleted file mode 100644
index 65f9ca247d..0000000000
--- a/lib/stdlib/src/regexp.erl
+++ /dev/null
@@ -1,557 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(regexp).
-
-%% This entire module is deprecated and will be removed in a future
-%% release. Use the 're' module instead.
-%%
-%% This module provides a basic set of regular expression functions
-%% for strings. The functions provided are taken from AWK.
-%%
-%% Note that we interpret the syntax tree of a regular expression
-%% directly instead of converting it to an NFA and then interpreting
-%% that. This method seems to go significantly faster.
-
--export([sh_to_awk/1,parse/1,format_error/1,match/2,first_match/2,matches/2]).
--export([sub/3,gsub/3,split/2]).
-
--deprecated([sh_to_awk/1,parse/1,format_error/1,match/2,first_match/2,matches/2]).
--deprecated([sub/3,gsub/3,split/2]).
-
--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}.
-
-%%-compile([export_all]).
-
-%% This is the regular expression grammar used. It is equivalent to the
-%% one used in AWK, except that we allow ^ $ to be used anywhere and fail
-%% in the matching.
-%%
-%% reg -> reg1 : '$1'.
-%% reg1 -> reg1 "|" reg2 : {'or','$1','$2'}.
-%% reg1 -> reg2 : '$1'.
-%% reg2 -> reg2 reg3 : {concat,'$1','$2'}.
-%% reg2 -> reg3 : '$1'.
-%% reg3 -> reg3 "*" : {kclosure,'$1'}.
-%% reg3 -> reg3 "+" : {pclosure,'$1'}.
-%% reg3 -> reg3 "?" : {optional,'$1'}.
-%% reg3 -> reg4 : '$1'.
-%% reg4 -> "(" reg ")" : '$2'.
-%% reg4 -> "\\" char : '$2'.
-%% reg4 -> "^" : bos.
-%% reg4 -> "$" : eos.
-%% reg4 -> "." : char.
-%% reg4 -> "[" class "]" : {char_class,char_class('$2')}
-%% reg4 -> "[" "^" class "]" : {comp_class,char_class('$3')}
-%% reg4 -> "\"" chars "\"" : char_string('$2')
-%% reg4 -> char : '$1'.
-%% reg4 -> empty : epsilon.
-%% The grammar of the current regular expressions. The actual parser
-%% is a recursive descent implementation of the grammar.
-
-reg(S) -> reg1(S).
-
-%% reg1 -> reg2 reg1'
-%% reg1' -> "|" reg2
-%% reg1' -> empty
-
-reg1(S0) ->
- {L,S1} = reg2(S0),
- reg1p(S1, L).
-
-reg1p([$||S0], L) ->
- {R,S1} = reg2(S0),
- reg1p(S1, {'or',L,R});
-reg1p(S, L) -> {L,S}.
-
-%% reg2 -> reg3 reg2'
-%% reg2' -> reg3
-%% reg2' -> empty
-
-reg2(S0) ->
- {L,S1} = reg3(S0),
- reg2p(S1, L).
-
-reg2p([C|S0], L) when C =/= $|, C =/= $) ->
- {R,S1} = reg3([C|S0]),
- reg2p(S1, {concat,L,R});
-reg2p(S, L) -> {L,S}.
-
-%% reg3 -> reg4 reg3'
-%% reg3' -> "*" reg3'
-%% reg3' -> "+" reg3'
-%% reg3' -> "?" reg3'
-%% reg3' -> empty
-
-reg3(S0) ->
- {L,S1} = reg4(S0),
- reg3p(S1, L).
-
-reg3p([$*|S], L) -> reg3p(S, {kclosure,L});
-reg3p([$+|S], L) -> reg3p(S, {pclosure,L});
-reg3p([$?|S], L) -> reg3p(S, {optional,L});
-reg3p(S, L) -> {L,S}.
-
--define(HEX(C), C >= $0 andalso C =< $9 orelse
- C >= $A andalso C =< $F orelse
- C >= $a andalso C =< $f).
-
-reg4([$(|S0]) ->
- case reg(S0) of
- {R,[$)|S1]} -> {R,S1};
- {_R,_S} -> throw({error,{unterminated,"("}})
- end;
-reg4([$\\,O1,O2,O3|S]) when
- O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
- {(O1*8 + O2)*8 + O3 - 73*$0,S};
-reg4([$\\,$x,H1,H2|S]) when ?HEX(H1), ?HEX(H2) ->
- {erlang:list_to_integer([H1,H2], 16),S};
-reg4([$\\,$x,${|S]) ->
- hex(S, []);
-reg4([$\\,$x|_]) ->
- throw({error,{illegal,[$x]}});
-reg4([$\\,C|S]) -> {escape_char(C),S};
-reg4([$\\]) -> throw({error,{unterminated,"\\"}});
-reg4([$^|S]) -> {bos,S};
-reg4([$$|S]) -> {eos,S};
-reg4([$.|S]) -> {{comp_class,"\n"},S};
-reg4("[^" ++ S0) ->
- case char_class(S0) of
- {Cc,[$]|S1]} -> {{comp_class,Cc},S1};
- {_Cc,_S} -> throw({error,{unterminated,"["}})
- end;
-reg4([$[|S0]) ->
- case char_class(S0) of
- {Cc,[$]|S1]} -> {{char_class,Cc},S1};
- {_Cc,_S1} -> throw({error,{unterminated,"["}})
- end;
-%reg4([$"|S0]) ->
-% case char_string(S0) of
-% {St,[$"|S1]} -> {St,S1};
-% {St,S1} -> throw({error,{unterminated,"\""}})
-% end;
-reg4([C|S]) when C =/= $*, C =/= $+, C =/= $?, C =/= $] -> {C,S};
-reg4([C|_S]) -> throw({error,{illegal,[C]}});
-reg4([]) -> {epsilon,[]}.
-
-hex([C|Cs], L) when ?HEX(C) ->
- hex(Cs, [C|L]);
-hex([$}|S], L) ->
- case catch erlang:list_to_integer(lists:reverse(L), 16) of
- V when V =< 16#FF ->
- {V,S};
- _ ->
- throw({error,{illegal,[$}]}})
- end;
-hex(_S, _) ->
- throw({error,{unterminated,"\\x{"}}).
-
-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 = SPACE
-escape_char($d) -> $\d; %\d = DEL
-escape_char(C) -> C.
-
-char_class([$]|S]) -> char_class(S, [$]]);
-char_class(S) -> char_class(S, []).
-
-char($\\, [O1,O2,O3|S]) when
- O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
- {(O1*8 + O2)*8 + O3 - 73*$0,S};
-char($\\, [$x,H1,H2|S]) when ?HEX(H1), ?HEX(H2) ->
- {erlang:list_to_integer([H1,H2], 16),S};
-char($\\,[$x,${|S]) ->
- hex(S, []);
-char($\\,[$x|_]) ->
- throw({error,{illegal,[$x]}});
-char($\\, [C|S]) -> {escape_char(C),S};
-char(C, S) -> {C,S}.
-
-char_class([C1|S0], Cc) when C1 =/= $] ->
- case char(C1, S0) of
- {Cf,[$-,C2|S1]} when C2 =/= $] ->
- case char(C2, S1) of
- {Cl,S2} when Cf < Cl -> char_class(S2, [{Cf,Cl}|Cc]);
- {Cl,_S2} -> throw({error,{char_class,[Cf,$-,Cl]}})
- end;
- {C,S1} -> char_class(S1, [C|Cc])
- end;
-char_class(S, Cc) -> {Cc,S}.
-
-%char_string([C|S]) when C =/= $" -> char_string(S, C);
-%char_string(S) -> {epsilon,S}.
-
-%char_string([C|S0], L) when C =/= $" ->
-% char_string(S0, {concat,L,C});
-%char_string(S, L) -> {L,S}.
-
-%% -deftype re_app_res() = {match,RestPos,Rest} | nomatch.
-
-%% re_apply(String, StartPos, RegExp) -> re_app_res().
-%%
-%% Apply the (parse of the) regular expression RegExp to String. If
-%% there is a match return the position of the remaining string and
-%% the string if else return 'nomatch'. BestMatch specifies if we want
-%% the longest match, or just a match.
-%%
-%% StartPos should be the real start position as it is used to decide
-%% if we ae at the beginning of the string.
-%%
-%% Pass two functions to re_apply_or so it can decide, on the basis
-%% of BestMatch, whether to just any take any match or try both to
-%% find the longest. This is slower but saves duplicatng code.
-
-re_apply(S, St, RE) -> re_apply(RE, [], S, St).
-
-re_apply(epsilon, More, S, P) -> %This always matches
- re_apply_more(More, S, P);
-re_apply({'or',RE1,RE2}, More, S, P) ->
- re_apply_or(re_apply(RE1, More, S, P),
- re_apply(RE2, More, S, P));
-re_apply({concat,RE1,RE2}, More, S0, P) ->
- re_apply(RE1, [RE2|More], S0, P);
-re_apply({kclosure,CE}, More, S, P) ->
- %% Be careful with the recursion, explicitly do one call before
- %% looping.
- re_apply_or(re_apply_more(More, S, P),
- re_apply(CE, [{kclosure,CE}|More], S, P));
-re_apply({pclosure,CE}, More, S, P) ->
- re_apply(CE, [{kclosure,CE}|More], S, P);
-re_apply({optional,CE}, More, S, P) ->
- re_apply_or(re_apply_more(More, S, P),
- re_apply(CE, More, S, P));
-re_apply(bos, More, S, 1) -> re_apply_more(More, S, 1);
-re_apply(eos, More, [$\n|S], P) -> re_apply_more(More, S, P);
-re_apply(eos, More, [], P) -> re_apply_more(More, [], P);
-re_apply({char_class,Cc}, More, [C|S], P) ->
- case in_char_class(C, Cc) of
- true -> re_apply_more(More, S, P+1);
- false -> nomatch
- end;
-re_apply({comp_class,Cc}, More, [C|S], P) ->
- case in_char_class(C, Cc) of
- true -> nomatch;
- false -> re_apply_more(More, S, P+1)
- end;
-re_apply(C, More, [C|S], P) when is_integer(C) ->
- re_apply_more(More, S, P+1);
-re_apply(_RE, _More, _S, _P) -> nomatch.
-
-%% re_apply_more([RegExp], String, Length) -> re_app_res().
-
-re_apply_more([RE|More], S, P) -> re_apply(RE, More, S, P);
-re_apply_more([], S, P) -> {match,P,S}.
-
-%% in_char_class(Char, Class) -> bool().
-
-in_char_class(C, [{C1,C2}|_Cc]) when C >= C1, C =< C2 -> true;
-in_char_class(C, [C|_Cc]) -> true;
-in_char_class(C, [_|Cc]) -> in_char_class(C, Cc);
-in_char_class(_C, []) -> false.
-
-%% re_apply_or(Match1, Match2) -> re_app_res().
-%% If we want the best match then choose the longest match, else just
-%% choose one by trying sequentially.
-
-re_apply_or({match,P1,S1}, {match,P2,_S2}) when P1 >= P2 -> {match,P1,S1};
-re_apply_or({match,_P1,_S1}, {match,P2,S2}) -> {match,P2,S2};
-re_apply_or(nomatch, R2) -> R2;
-re_apply_or(R1, nomatch) -> R1.
-
-%% sh_to_awk(ShellRegExp)
-%% 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
- ".*" ++ sh_to_awk_1(Sh);
-sh_to_awk_1([$?|Sh]) -> %This matches any character
- [$.|sh_to_awk_1(Sh)];
-sh_to_awk_1([$[,$^,$]|Sh]) -> %This takes careful handling
- "\\^" ++ sh_to_awk_1(Sh);
-sh_to_awk_1("[^" ++ Sh) -> [$[|sh_to_awk_2(Sh, true)];
-sh_to_awk_1("[!" ++ Sh) -> "[^" ++ sh_to_awk_2(Sh, false);
-sh_to_awk_1([$[|Sh]) -> [$[|sh_to_awk_2(Sh, false)];
-sh_to_awk_1([C|Sh]) ->
- %% Unspecialise everything else which is not an escape character.
- case special_char(C) of
- true -> [$\\,C|sh_to_awk_1(Sh)];
- false -> [C|sh_to_awk_1(Sh)]
- end;
-sh_to_awk_1([]) -> ")$". %Fix the end
-
-sh_to_awk_2([$]|Sh], UpArrow) -> [$]|sh_to_awk_3(Sh, UpArrow)];
-sh_to_awk_2(Sh, UpArrow) -> sh_to_awk_3(Sh, UpArrow).
-
-sh_to_awk_3([$]|Sh], true) -> "^]" ++ sh_to_awk_1(Sh);
-sh_to_awk_3([$]|Sh], false) -> [$]|sh_to_awk_1(Sh)];
-sh_to_awk_3([C|Sh], UpArrow) -> [C|sh_to_awk_3(Sh, UpArrow)];
-sh_to_awk_3([], true) -> [$^|sh_to_awk_1([])];
-sh_to_awk_3([], false) -> sh_to_awk_1([]).
-
-%% -type special_char(char()) -> bool().
-%% Test if a character is a special character.
-
-special_char($|) -> true;
-special_char($*) -> true;
-special_char($+) -> true;
-special_char($?) -> true;
-special_char($() -> true;
-special_char($)) -> true;
-special_char($\\) -> true;
-special_char($^) -> true;
-special_char($$) -> true;
-special_char($.) -> true;
-special_char($[) -> true;
-special_char($]) -> true;
-special_char($") -> true;
-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};
- {_R,[C|_]} -> {error,{illegal,[C]}};
- {error,E} -> {error,E}
- end.
-
-%% 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}) ->
- ["illegal character class ",io_lib:write_string(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);
- {error,E} -> {error,E}
- end;
-match(S, RE) ->
- case match(RE, S, 1, 0, -1) of
- {Start,Len} when Len >= 0 ->
- {match,Start,Len};
- {_Start,_Len} -> nomatch
- end.
-
-match(RE, S, St, Pos, L) ->
- case first_match(RE, S, St) of
- {St1,L1} ->
- Nst = St1 + 1,
- if L1 > L -> match(RE, lists:nthtail(Nst-St, S), Nst, St1, L1);
- true -> match(RE, lists:nthtail(Nst-St, S), Nst, Pos, L)
- end;
- nomatch -> {Pos,L}
- end.
-
-%% -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);
- {error,E} -> {error,E}
- end;
-first_match(S, RE) ->
- case first_match(RE, S, 1) of
- {Start,Len} when Len >= 0 ->
- {match,Start,Len};
- nomatch -> nomatch
- end.
-
-first_match(RE, S, St) when S =/= [] ->
- case re_apply(S, St, RE) of
- {match,P,_Rest} -> {St,P-St};
- nomatch -> first_match(RE, tl(S), St+1)
- end;
-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);
- {error,E} -> {error,E}
- end;
-matches(S, RE) ->
- {match,matches(S, RE, 1)}.
-
-matches(S, RE, St) ->
- case first_match(RE, S, St) of
- {St1,0} -> [{St1,0}|matches(substr(S, St1+2-St), RE, St1+1)];
- {St1,L1} -> [{St1,L1}|matches(substr(S, St1+L1+1-St), RE, St1+L1)];
- nomatch -> []
- end.
-
-%% -type sub(String, RegExp, Replace) -> subsres().
-%% Substitute the first match of the regular expression RegExp with
-%% 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);
- {error,E} -> {error,E}
- end;
-sub(String, RE, Rep) ->
- Ss = sub_match(String, RE, 1),
- {ok,sub_repl(Ss, Rep, String, 1),length(Ss)}.
-
-sub_match(S, RE, St) ->
- case first_match(RE, S, St) of
- {St1,L1} -> [{St1,L1}];
- nomatch -> []
- end.
-
-sub_repl([{St,L}|Ss], Rep, S, Pos) ->
- Rs = sub_repl(Ss, Rep, S, St+L),
- substr(S, Pos, St-Pos) ++ sub_repl(Rep, substr(S, St, L), Rs);
-sub_repl([], _Rep, S, Pos) -> substr(S, Pos).
-
-sub_repl([$&|Rep], M, Rest) -> M ++ sub_repl(Rep, M, Rest);
-sub_repl("\\&" ++ Rep, M, Rest) -> [$&|sub_repl(Rep, M, Rest)];
-sub_repl([C|Rep], M, Rest) -> [C|sub_repl(Rep, M, Rest)];
-sub_repl([], _M, Rest) -> Rest.
-
-%% -type gsub(String, RegExp, Replace) -> subres().
-%% 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);
- {error,E} -> {error,E}
- end;
-gsub(String, RE, Rep) ->
- Ss = matches(String, RE, 1),
- {ok,sub_repl(Ss, Rep, String, 1),length(Ss)}.
-
-%% -type split(String, RegExp) -> splitres().
-%% 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
- [[]|Ss] -> {ok,Ss};
- Ss -> {ok,Ss}
- end;
-split(String, RegExp) when is_list(RegExp) ->
- case parse(RegExp) of
- {ok,RE} -> {ok,split_apply(String, RE, false)};
- {error,E} -> {error,E}
- end;
-split(String, RE) -> {ok,split_apply(String, RE, false)}.
-
-split_apply(S, RE, Trim) -> split_apply(S, 1, RE, Trim, []).
-
-split_apply([], _P, _RE, true, []) -> [];
-split_apply([], _P, _RE, _T, Sub) -> [reverse(Sub)];
-split_apply(S, P, RE, T, Sub) ->
- case re_apply(S, P, RE) of
- {match,P,_Rest} ->
- split_apply(tl(S), P+1, RE, T, [hd(S)|Sub]);
- {match,P1,Rest} ->
- [reverse(Sub)|split_apply(Rest, P1, RE, T, [])];
- nomatch ->
- split_apply(tl(S), P+1, RE, T, [hd(S)|Sub])
- end.
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index 964697cae6..dc450f0ee6 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1065,9 +1065,10 @@ local_func(F, As0, Bs0, _Shell, _RT, Lf, Ef) when is_atom(F) ->
non_builtin_local_func(F,As,Bs).
non_builtin_local_func(F,As,Bs) ->
- case erlang:function_exported(user_default, F, length(As)) of
+ Arity = length(As),
+ case erlang:function_exported(user_default, F, Arity) of
true ->
- {eval,{user_default,F},As,Bs};
+ {eval,erlang:make_fun(user_default, F, Arity),As,Bs};
false ->
shell_default(F,As,Bs)
end.
@@ -1079,7 +1080,7 @@ shell_default(F,As,Bs) ->
{module, _} ->
case erlang:function_exported(M,F,A) of
true ->
- {eval,{M,F},As,Bs};
+ {eval,erlang:make_fun(M, F, A),As,Bs};
false ->
shell_undef(F,A)
end;
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index 9d15f01683..a30685e830 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -2,7 +2,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,7 +85,6 @@
queue,
random,
re,
- regexp,
sets,
shell,
shell_default,
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 54a63833e6..94e81188b5 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -1 +1,27 @@
-{"%VSN%",[],[]}.
+%% -*- erlang -*-
+%% %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%
+{"%VSN%",
+ %% Up from - max two major revisions back
+ [{<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"1\\.17(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14
+ {<<"1\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R13
+ %% Down to - max two major revisions back
+ [{<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"1\\.17(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14
+ {<<"1\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R13
+}.
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 9da0d52f8c..7d3c5a0e21 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,9 @@
check_childspecs/1]).
%% Internal exports
--export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
--export([handle_cast/2]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+-export([try_again_restart/2]).
%%--------------------------------------------------------------------------
@@ -37,7 +38,7 @@
%%--------------------------------------------------------------------------
--type child() :: pid() | 'undefined'.
+-type child() :: 'undefined' | pid().
-type child_id() :: term().
-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}.
-type modules() :: [module()] | 'dynamic'.
@@ -62,8 +63,8 @@
%%--------------------------------------------------------------------------
-record(child, {% pid is undefined when child is not running
- pid = undefined :: child(),
- name,
+ pid = undefined :: child() | {restarting,pid()} | [pid()],
+ name :: child_id(),
mfargs :: mfargs(),
restart_type :: restart(),
shutdown :: shutdown(),
@@ -95,6 +96,8 @@
[ChildSpec :: child_spec()]}}
| ignore.
+-define(restarting(_Pid_), {restarting,_Pid_}).
+
%%% ---------------------------------------------------
%%% This is a general process supervisor built upon gen_server.erl.
%%% Servers/processes should/could also be built using gen_server.erl.
@@ -139,7 +142,8 @@ start_child(Supervisor, ChildSpec) ->
Result :: {'ok', Child :: child()}
| {'ok', Child :: child(), Info :: term()}
| {'error', Error},
- Error :: 'running' | 'not_found' | 'simple_one_for_one' | term().
+ Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one' |
+ term().
restart_child(Supervisor, Name) ->
call(Supervisor, {restart_child, Name}).
@@ -147,7 +151,7 @@ restart_child(Supervisor, Name) ->
SupRef :: sup_ref(),
Id :: child_id(),
Result :: 'ok' | {'error', Error},
- Error :: 'running' | 'not_found' | 'simple_one_for_one'.
+ Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one'.
delete_child(Supervisor, Name) ->
call(Supervisor, {delete_child, Name}).
@@ -169,7 +173,7 @@ terminate_child(Supervisor, Name) ->
-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when
SupRef :: sup_ref(),
Id :: child_id() | undefined,
- Child :: child(),
+ Child :: child() | 'restarting',
Type :: worker(),
Modules :: modules().
which_children(Supervisor) ->
@@ -198,6 +202,17 @@ check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
end;
check_childspecs(X) -> {error, {badarg, X}}.
+%%%-----------------------------------------------------------------
+%%% Called by timer:apply_after from restart/2
+-spec try_again_restart(SupRef, Child) -> ok when
+ SupRef :: sup_ref(),
+ Child :: child_id() | pid().
+try_again_restart(Supervisor, Child) ->
+ cast(Supervisor, {try_again_restart, Child}).
+
+cast(Supervisor, Req) ->
+ gen_server:cast(Supervisor, Req).
+
%%% ---------------------------------------------------
%%%
%%% Initialize the supervisor.
@@ -270,6 +285,8 @@ start_children(Children, SupName) -> start_children(Children, [], SupName).
start_children([Child|Chs], NChildren, SupName) ->
case do_start_child(SupName, Child) of
+ {ok, undefined} when Child#child.restart_type =:= temporary ->
+ start_children(Chs, NChildren, SupName);
{ok, Pid} ->
start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName);
{ok, Pid, _Extra} ->
@@ -325,6 +342,8 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) ->
#child{mfargs = {M, F, A}} = Child,
Args = A ++ EArgs,
case do_start_child_i(M, F, Args) of
+ {ok, undefined} when Child#child.restart_type =:= temporary ->
+ {reply, {ok, undefined}, State};
{ok, Pid} ->
NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State),
{reply, {ok, Pid}, NState};
@@ -380,6 +399,8 @@ handle_call({restart_child, Name}, _From, State) ->
Error ->
{reply, Error, State}
end;
+ {value, #child{pid=?restarting(_)}} ->
+ {reply, {error, restarting}, State};
{value, _} ->
{reply, {error, running}, State};
_ ->
@@ -391,6 +412,8 @@ handle_call({delete_child, Name}, _From, State) ->
{value, Child} when Child#child.pid =:= undefined ->
NState = remove_child(Child, State),
{reply, ok, NState};
+ {value, #child{pid=?restarting(_)}} ->
+ {reply, {error, restarting}, State};
{value, _} ->
{reply, {error, running}, State};
_ ->
@@ -409,13 +432,17 @@ handle_call(which_children, _From, #state{children = [#child{restart_type = RTyp
child_type = CT,
modules = Mods}]} =
State) when ?is_simple(State) ->
- Reply = lists:map(fun({Pid, _}) -> {undefined, Pid, CT, Mods} end,
+ Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods};
+ ({Pid, _}) -> {undefined, Pid, CT, Mods} end,
?DICT:to_list(dynamics_db(RType, State#state.dynamics))),
{reply, Reply, State};
handle_call(which_children, _From, State) ->
Resp =
- lists:map(fun(#child{pid = Pid, name = Name,
+ lists:map(fun(#child{pid = ?restarting(_), name = Name,
+ child_type = ChildType, modules = Mods}) ->
+ {Name, restarting, ChildType, Mods};
+ (#child{pid = Pid, name = Name,
child_type = ChildType, modules = Mods}) ->
{Name, Pid, ChildType, Mods}
end,
@@ -428,8 +455,11 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = temp
when ?is_simple(State) ->
{Active, Count} =
?SETS:fold(fun(Pid, {Alive, Tot}) ->
- if is_pid(Pid) -> {Alive+1, Tot +1};
- true -> {Alive, Tot + 1} end
+ case is_pid(Pid) andalso is_process_alive(Pid) of
+ true ->{Alive+1, Tot +1};
+ false ->
+ {Alive, Tot + 1}
+ end
end, {0, 0}, dynamics_db(temporary, State#state.dynamics)),
Reply = case CT of
supervisor -> [{specs, 1}, {active, Active},
@@ -444,8 +474,12 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = RTy
when ?is_simple(State) ->
{Active, Count} =
?DICT:fold(fun(Pid, _Val, {Alive, Tot}) ->
- if is_pid(Pid) -> {Alive+1, Tot +1};
- true -> {Alive, Tot + 1} end
+ case is_pid(Pid) andalso is_process_alive(Pid) of
+ true ->
+ {Alive+1, Tot +1};
+ false ->
+ {Alive, Tot + 1}
+ end
end, {0, 0}, dynamics_db(RType, State#state.dynamics)),
Reply = case CT of
supervisor -> [{specs, 1}, {active, Active},
@@ -482,14 +516,42 @@ count_child(#child{pid = Pid, child_type = supervisor},
end.
-%%% Hopefully cause a function-clause as there is no API function
-%%% that utilizes cast.
--spec handle_cast('null', state()) -> {'noreply', state()}.
+%%% If a restart attempt failed, this message is sent via
+%%% timer:apply_after(0,...) in order to give gen_server the chance to
+%%% check it's inbox before trying again.
+-spec handle_cast({try_again_restart, child_id() | pid()}, state()) ->
+ {'noreply', state()} | {stop, shutdown, state()}.
-handle_cast(null, State) ->
- error_logger:error_msg("ERROR: Supervisor received cast-message 'null'~n",
- []),
- {noreply, State}.
+handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State)
+ when ?is_simple(State) ->
+ RT = Child#child.restart_type,
+ RPid = restarting(Pid),
+ case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of
+ {ok, Args} ->
+ {M, F, _} = Child#child.mfargs,
+ NChild = Child#child{pid = RPid, mfargs = {M, F, Args}},
+ case restart(NChild,State) of
+ {ok, State1} ->
+ {noreply, State1};
+ {shutdown, State1} ->
+ {stop, shutdown, State1}
+ end;
+ error ->
+ {noreply, State}
+ end;
+
+handle_cast({try_again_restart,Name}, State) ->
+ case lists:keyfind(Name,#child.name,State#state.children) of
+ Child = #child{pid=?restarting(_)} ->
+ case restart(Child,State) of
+ {ok, State1} ->
+ {noreply, State1};
+ {shutdown, State1} ->
+ {stop, shutdown, State1}
+ end;
+ _ ->
+ {noreply,State}
+ end.
%%
%% Take care of terminated children.
@@ -515,9 +577,12 @@ handle_info(Msg, State) ->
%%
-spec terminate(term(), state()) -> 'ok'.
+terminate(_Reason, #state{children=[Child]} = State) when ?is_simple(State) ->
+ terminate_dynamic_children(Child, dynamics_db(Child#child.restart_type,
+ State#state.dynamics),
+ State#state.name);
terminate(_Reason, State) ->
- terminate_children(State#state.children, State#state.name),
- ok.
+ terminate_children(State#state.children, State#state.name).
%%
%% Change code for the supervisor.
@@ -559,13 +624,12 @@ check_flags(What) ->
{bad_flags, What}.
update_childspec(State, StartSpec) when ?is_simple(State) ->
- case check_startspec(StartSpec) of
- {ok, [Child]} ->
- {ok, State#state{children = [Child]}};
- Error ->
- {error, Error}
- end;
-
+ case check_startspec(StartSpec) of
+ {ok, [Child]} ->
+ {ok, State#state{children = [Child]}};
+ Error ->
+ {error, Error}
+ end;
update_childspec(State, StartSpec) ->
case check_startspec(StartSpec) of
{ok, Children} ->
@@ -585,7 +649,7 @@ update_childspec1([Child|OldC], Children, KeepOld) ->
end;
update_childspec1([], Children, KeepOld) ->
%% Return them in (kept) reverse start order.
- lists:reverse(Children ++ KeepOld).
+ lists:reverse(Children ++ KeepOld).
update_chsp(OldCh, Children) ->
case lists:map(fun(Ch) when OldCh#child.name =:= Ch#child.name ->
@@ -608,16 +672,16 @@ handle_start_child(Child, State) ->
case get_child(Child#child.name, State) of
false ->
case do_start_child(State#state.name, Child) of
+ {ok, undefined} when Child#child.restart_type =:= temporary ->
+ {{ok, undefined}, State};
{ok, Pid} ->
- {{ok, Pid},
- save_child(Child#child{pid = Pid}, State)};
+ {{ok, Pid}, save_child(Child#child{pid = Pid}, State)};
{ok, Pid, Extra} ->
- {{ok, Pid, Extra},
- save_child(Child#child{pid = Pid}, State)};
+ {{ok, Pid, Extra}, save_child(Child#child{pid = Pid}, State)};
{error, What} ->
{{error, {What, Child}}, State}
end;
- {value, OldChild} when OldChild#child.pid =/= undefined ->
+ {value, OldChild} when is_pid(OldChild#child.pid) ->
{{error, {already_started, OldChild#child.pid}}, State};
{value, _OldChild} ->
{{error, already_present}, State}
@@ -671,7 +735,21 @@ do_restart(temporary, Reason, Child, State) ->
restart(Child, State) ->
case add_restart(State) of
{ok, NState} ->
- restart(NState#state.strategy, Child, NState);
+ case restart(NState#state.strategy, Child, NState) of
+ {try_again,NState2} ->
+ %% Leaving control back to gen_server before
+ %% trying again. This way other incoming requsts
+ %% for the supervisor can be handled - e.g. a
+ %% shutdown request for the supervisor or the
+ %% child.
+ Id = if ?is_simple(State) -> Child#child.pid;
+ true -> Child#child.name
+ end,
+ timer:apply_after(0,?MODULE,try_again_restart,[self(),Id]),
+ {ok,NState2};
+ Other ->
+ Other
+ end;
{terminate, NState} ->
report_error(shutdown, reached_max_restart_intensity,
Child, State#state.name),
@@ -679,9 +757,9 @@ restart(Child, State) ->
end.
restart(simple_one_for_one, Child, State) ->
- #child{mfargs = {M, F, A}} = Child,
- Dynamics = ?DICT:erase(Child#child.pid, dynamics_db(Child#child.restart_type,
- State#state.dynamics)),
+ #child{pid = OldPid, mfargs = {M, F, A}} = Child,
+ Dynamics = ?DICT:erase(OldPid, dynamics_db(Child#child.restart_type,
+ State#state.dynamics)),
case do_start_child_i(M, F, A) of
{ok, Pid} ->
NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)},
@@ -690,10 +768,13 @@ restart(simple_one_for_one, Child, State) ->
NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)},
{ok, NState};
{error, Error} ->
+ NState = State#state{dynamics = ?DICT:store(restarting(OldPid), A,
+ Dynamics)},
report_error(start_error, Error, Child, State#state.name),
- restart(Child, State)
+ {try_again, NState}
end;
restart(one_for_one, Child, State) ->
+ OldPid = Child#child.pid,
case do_start_child(State#state.name, Child) of
{ok, Pid} ->
NState = replace_child(Child#child{pid = Pid}, State),
@@ -702,8 +783,9 @@ restart(one_for_one, Child, State) ->
NState = replace_child(Child#child{pid = Pid}, State),
{ok, NState};
{error, Reason} ->
+ NState = replace_child(Child#child{pid = restarting(OldPid)}, State),
report_error(start_error, Reason, Child, State#state.name),
- restart(Child, State)
+ {try_again, NState}
end;
restart(rest_for_one, Child, State) ->
{ChAfter, ChBefore} = split_child(Child#child.pid, State#state.children),
@@ -712,7 +794,9 @@ restart(rest_for_one, Child, State) ->
{ok, ChAfter3} ->
{ok, State#state{children = ChAfter3 ++ ChBefore}};
{error, ChAfter3} ->
- restart(Child, State#state{children = ChAfter3 ++ ChBefore})
+ NChild = Child#child{pid=restarting(Child#child.pid)},
+ NState = State#state{children = ChAfter3 ++ ChBefore},
+ {try_again, replace_child(NChild,NState)}
end;
restart(one_for_all, Child, State) ->
Children1 = del_child(Child#child.pid, State#state.children),
@@ -721,9 +805,14 @@ restart(one_for_all, Child, State) ->
{ok, NChs} ->
{ok, State#state{children = NChs}};
{error, NChs} ->
- restart(Child, State#state{children = NChs})
+ NChild = Child#child{pid=restarting(Child#child.pid)},
+ NState = State#state{children = NChs},
+ {try_again, replace_child(NChild,NState)}
end.
+restarting(Pid) when is_pid(Pid) -> ?restarting(Pid);
+restarting(RPid) -> RPid.
+
%%-----------------------------------------------------------------
%% Func: terminate_children/2
%% Args: Children = [child_rec()] in termination order
@@ -747,7 +836,7 @@ terminate_children([Child | Children], SupName, Res) ->
terminate_children([], _SupName, Res) ->
Res.
-do_terminate(Child, SupName) when Child#child.pid =/= undefined ->
+do_terminate(Child, SupName) when is_pid(Child#child.pid) ->
case shutdown(Child#child.pid, Child#child.shutdown) of
ok ->
ok;
@@ -758,7 +847,7 @@ do_terminate(Child, SupName) when Child#child.pid =/= undefined ->
end,
Child#child{pid = undefined};
do_terminate(Child, _SupName) ->
- Child.
+ Child#child{pid = undefined}.
%%-----------------------------------------------------------------
%% Shutdowns a child. We must check the EXIT value
@@ -830,8 +919,111 @@ monitor_child(Pid) ->
%% that will be handled in shutdown/2.
ok
end.
-
-
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate_dynamic_children/3
+%% Args: Child = child_rec()
+%% Dynamics = ?DICT() | ?SET()
+%% SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
+%% Returns: ok
+%%
+%%
+%% Shutdown all dynamic children. This happens when the supervisor is
+%% stopped. Because the supervisor can have millions of dynamic children, we
+%% can have an significative overhead here.
+%%-----------------------------------------------------------------
+terminate_dynamic_children(Child, Dynamics, SupName) ->
+ {Pids, EStack0} = monitor_dynamic_children(Child, Dynamics),
+ Sz = ?SETS:size(Pids),
+ EStack = case Child#child.shutdown of
+ brutal_kill ->
+ ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
+ wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
+ infinity ->
+ ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
+ wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
+ Time ->
+ ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
+ TRef = erlang:start_timer(Time, self(), kill),
+ wait_dynamic_children(Child, Pids, Sz, TRef, EStack0)
+ end,
+ %% Unroll stacked errors and report them
+ ?DICT:fold(fun(Reason, Ls, _) ->
+ report_error(shutdown_error, Reason,
+ Child#child{pid=Ls}, SupName)
+ end, ok, EStack).
+
+
+monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) ->
+ ?SETS:fold(fun(P, {Pids, EStack}) ->
+ case monitor_child(P) of
+ ok ->
+ {?SETS:add_element(P, Pids), EStack};
+ {error, normal} ->
+ {Pids, EStack};
+ {error, Reason} ->
+ {Pids, ?DICT:append(Reason, P, EStack)}
+ end
+ end, {?SETS:new(), ?DICT:new()}, Dynamics);
+monitor_dynamic_children(#child{restart_type=RType}, Dynamics) ->
+ ?DICT:fold(fun(P, _, {Pids, EStack}) when is_pid(P) ->
+ case monitor_child(P) of
+ ok ->
+ {?SETS:add_element(P, Pids), EStack};
+ {error, normal} when RType =/= permanent ->
+ {Pids, EStack};
+ {error, Reason} ->
+ {Pids, ?DICT:append(Reason, P, EStack)}
+ end;
+ (?restarting(_), _, {Pids, EStack}) ->
+ {Pids, EStack}
+ end, {?SETS:new(), ?DICT:new()}, Dynamics).
+
+
+wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) ->
+ EStack;
+wait_dynamic_children(_Child, _Pids, 0, TRef, EStack) ->
+ %% If the timer has expired before its cancellation, we must empty the
+ %% mail-box of the 'timeout'-message.
+ erlang:cancel_timer(TRef),
+ receive
+ {timeout, TRef, kill} ->
+ EStack
+ after 0 ->
+ EStack
+ end;
+wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz,
+ TRef, EStack) ->
+ receive
+ {'DOWN', _MRef, process, Pid, killed} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, EStack);
+
+ {'DOWN', _MRef, process, Pid, Reason} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, ?DICT:append(Reason, Pid, EStack))
+ end;
+wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz,
+ TRef, EStack) ->
+ receive
+ {'DOWN', _MRef, process, Pid, shutdown} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, EStack);
+
+ {'DOWN', _MRef, process, Pid, normal} when RType =/= permanent ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, EStack);
+
+ {'DOWN', _MRef, process, Pid, Reason} ->
+ wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ TRef, ?DICT:append(Reason, Pid, EStack));
+
+ {timeout, TRef, kill} ->
+ ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
+ wait_dynamic_children(Child, Pids, Sz-1, undefined, EStack)
+ end.
+
%%-----------------------------------------------------------------
%% Child/State manipulating functions.
%%-----------------------------------------------------------------
@@ -912,13 +1104,20 @@ 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
+ DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics),
+ case is_dynamic_pid(Pid, DynamicsDb) of
true ->
{value, Child#child{pid=Pid}};
false ->
- case erlang:is_process_alive(Pid) of
- true -> false;
- false -> {value, Child}
+ RPid = restarting(Pid),
+ case is_dynamic_pid(RPid, DynamicsDb) of
+ true ->
+ {value, Child#child{pid=RPid}};
+ false ->
+ case erlang:is_process_alive(Pid) of
+ true -> false;
+ false -> {value, Child}
+ end
end
end.
@@ -948,9 +1147,9 @@ remove_child(Child, State) ->
%% Args: SupName = {local, atom()} | {global, atom()} | self
%% Type = {Strategy, MaxIntensity, Period}
%% Strategy = one_for_one | one_for_all | simple_one_for_one |
-%% rest_for_one
-%% MaxIntensity = integer()
-%% Period = integer()
+%% rest_for_one
+%% MaxIntensity = integer() >= 0
+%% Period = integer() > 0
%% Mod :== atom()
%% Args :== term()
%% Purpose: Check that Type is of correct type (!)
@@ -1001,7 +1200,7 @@ supname(N, _) -> N.
%%% where Name is an atom
%%% Func is {Mod, Fun, Args} == {atom(), atom(), list()}
%%% RestartType is permanent | temporary | transient
-%%% Shutdown = integer() | infinity | brutal_kill
+%%% Shutdown = integer() > 0 | infinity | brutal_kill
%%% ChildType = supervisor | worker
%%% Modules = [atom()] | dynamic
%%% Returns: {ok, [child_rec()]} | Error
@@ -1053,7 +1252,7 @@ validRestartType(RestartType) -> throw({invalid_restart_type, RestartType}).
validShutdown(Shutdown, _)
when is_integer(Shutdown), Shutdown > 0 -> true;
-validShutdown(infinity, supervisor) -> true;
+validShutdown(infinity, _) -> true;
validShutdown(brutal_kill, _) -> true;
validShutdown(Shutdown, _) -> throw({invalid_shutdown, Shutdown}).
@@ -1134,6 +1333,13 @@ report_error(Error, Reason, Child, SupName) ->
error_logger:error_report(supervisor_report, ErrorMsg).
+extract_child(Child) when is_list(Child#child.pid) ->
+ [{nb_children, length(Child#child.pid)},
+ {name, Child#child.name},
+ {mfargs, Child#child.mfargs},
+ {restart_type, Child#child.restart_type},
+ {shutdown, Child#child.shutdown},
+ {child_type, Child#child.child_type}];
extract_child(Child) ->
[{pid, Child#child.pid},
{name, Child#child.name},
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index c82c8159b6..fd480726a7 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1017,7 +1017,7 @@ cd_file_header_from_lh_and_pos(LH, Pos) ->
file_name_length = FileNameLength,
extra_field_length = ExtraFieldLength,
file_comment_length = 0, % FileCommentLength,
- disk_num_start = 1, % DiskNumStart,
+ disk_num_start = 0, % DiskNumStart,
internal_attr = 0, % InternalAttr,
external_attr = 0, % ExternalAttr,
local_header_offset = Pos}.
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 5502c69fa5..29b8e28d3a 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -20,6 +20,7 @@ MODULES= \
digraph_utils_SUITE \
dummy1_h \
dummy_h \
+ dummy_via \
edlin_expand_SUITE \
epp_SUITE \
erl_eval_helper \
@@ -65,6 +66,8 @@ MODULES= \
stdlib_SUITE \
string_SUITE \
supervisor_1 \
+ supervisor_2 \
+ supervisor_deadlock \
naughty_child \
shell_SUITE \
supervisor_SUITE \
@@ -132,10 +135,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) stdlib.spec $(EMAKEFILE) \
- $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
+ @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 8fb63f33bd..bac59a3107 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -20,7 +20,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- interesting/1,random_ref_comp/1,random_ref_sr_comp/1,
+ interesting/1,scope_return/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1]).
@@ -67,7 +67,7 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [interesting, random_ref_fla_comp, random_ref_sr_comp,
+ [scope_return,interesting, random_ref_fla_comp, random_ref_sr_comp,
random_ref_comp, parts, bin_to_list, list_to_bin, copy,
referenced, guard, encode_decode, badargs,
longest_common_trap].
@@ -379,6 +379,20 @@ subj() ->
Subject.
+scope_return(doc) ->
+ ["Test correct return values for scopes (OTP-9701)."];
+scope_return(Config) when is_list(Config) ->
+ N=10000,
+ Bin=binary:copy(<<"a">>,N),
+ scope_loop(Bin,0,N).
+
+scope_loop(_,N,N) ->
+ ok;
+scope_loop(Bin,N,M) ->
+ ?line {N,1} = binary:match(Bin,<<"a">>,[{scope,{N,1}}]),
+ ?line {N,1} = binary:match(Bin,[<<"a">>,<<"b">>],[{scope,{N,1}}]),
+ scope_loop(Bin,N+1,M).
+
interesting(doc) ->
["Try some interesting patterns"];
interesting(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 63767aeda6..6f77cff2b9 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -1865,10 +1865,10 @@ fixtable(Config, Version) when is_list(Config) ->
?line {ok, _} = dets:open_file(T, Args),
%% badarg
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
- (catch dets:safe_fixtable(no_table,true)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[T,undefined],_}|_]}} =
- (catch dets:safe_fixtable(T,undefined)),
+ ?line check_badarg(catch dets:safe_fixtable(no_table,true),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:safe_fixtable(T,undefined),
+ dets, safe_fixtable, [T,undefined]),
%% The table is not allowed to grow while the elements are inserted:
@@ -1948,22 +1948,22 @@ match(Config, Version) ->
%% match, badarg
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
- (catch dets:match(no_table, '_')),
- ?line {'EXIT', {badarg, [{dets,match,[T,'_',not_a_number],_}|_]}} =
- (catch dets:match(T, '_', not_a_number)),
+ ?line check_badarg(catch dets:match(no_table, '_'),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:match(T, '_', not_a_number),
+ dets, match, [T,'_',not_a_number]),
?line {EC1, _} = dets:select(T, MSpec, 1),
- ?line {'EXIT', {badarg, [{dets,match,[EC1],_}|_]}} =
- (catch dets:match(EC1)),
+ ?line check_badarg(catch dets:match(EC1),
+ dets, match, [EC1]),
%% match_object, badarg
- ?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],_}|_]}} =
- (catch dets:match_object(T, '_', not_a_number)),
+ ?line check_badarg(catch dets:match_object(no_table, '_'),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:match_object(T, '_', not_a_number),
+ dets, match_object, [T,'_',not_a_number]),
?line {EC2, _} = dets:select(T, MSpec, 1),
- ?line {'EXIT', {badarg, [{dets,match_object,[EC2],_}|_]}} =
- (catch dets:match_object(EC2)),
+ ?line check_badarg(catch dets:match_object(EC2),
+ dets, match_object, [EC2]),
dets:safe_fixtable(T, true),
?line {[_, _], C1} = dets:match_object(T, '_', 2),
@@ -2126,17 +2126,17 @@ select(Config, Version) ->
%% badarg
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
- (catch dets:select(no_table, MSpec)),
- ?line {'EXIT', {badarg, [{dets,select,[T,<<17>>],_}|_]}} =
- (catch dets:select(T, <<17>>)),
- ?line {'EXIT', {badarg, [{dets,select,[T,[]],_}|_]}} =
- (catch dets:select(T, [])),
- ?line {'EXIT', {badarg, [{dets,select,[T,MSpec,not_a_number],_}|_]}} =
- (catch dets:select(T, MSpec, not_a_number)),
+ ?line check_badarg(catch dets:select(no_table, MSpec),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:select(T, <<17>>),
+ dets, select, [T,<<17>>]),
+ ?line check_badarg(catch dets:select(T, []),
+ dets, select, [T,[]]),
+ ?line check_badarg(catch dets:select(T, MSpec, not_a_number),
+ dets, select, [T,MSpec,not_a_number]),
?line {EC, _} = dets:match(T, '_', 1),
- ?line {'EXIT', {badarg, [{dets,select,[EC],_}|_]}} =
- (catch dets:select(EC)),
+ ?line check_badarg(catch dets:select(EC),
+ dets, select, [EC]),
AllSpec = [{'_',[],['$_']}],
@@ -2218,8 +2218,8 @@ update_counter(Config) when is_list(Config) ->
?line file:delete(Fname),
P0 = pps(),
- ?line {'EXIT', {badarg, [{dets,update_counter,[no_table,1,1],_}|_]}} =
- (catch dets:update_counter(no_table, 1, 1)),
+ ?line check_badarg(catch dets:update_counter(no_table, 1, 1),
+ dets, update_counter, [no_table,1,1]),
Args = [{file,Fname},{keypos,2}],
?line {ok, _} = dets:open_file(T, [{type,set} | Args]),
@@ -2262,67 +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},[]],_}|_]}} =
- (catch 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]],_}|_]}} =
- (catch dets:open_file(file,[foo])),
- ?line {'EXIT', {badarg,[{dets,open_file,
- [{hej,san},[{type,set}|3]],_}|_]}} =
- (catch dets:open_file({hej,san},[{type,set}|3])),
+ ?line check_badarg(catch dets:open_file({a,tuple},[]),
+ dets, open_file, [{a,tuple},[]]),
+ ?line check_badarg(catch dets:open_file({a,tuple}),
+ dets, open_file,[{a,tuple}]),
+ ?line check_badarg(catch dets:open_file(file,[foo]),
+ dets, open_file, [file,[foo]]),
+ ?line check_badarg(catch dets:open_file({hej,san},[{type,set}|3]),
+ dets, open_file, [{hej,san},[{type,set}|3]]),
%% insert
- ?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}]],_}|_]}} =
- (catch dets:insert(no_table, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,insert,[T,{1,2}],_}|_]}} =
- (catch 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]],_}|_]}} =
- (catch dets:insert(T, [{1,2,3} | 3])),
+ ?line check_badarg(catch dets:insert(no_table, {1,2}),
+ dets, insert, [no_table,{1,2}]),
+ ?line check_badarg(catch dets:insert(no_table, [{1,2}]),
+ dets, insert, [no_table,[{1,2}]]),
+ ?line check_badarg(catch dets:insert(T, {1,2}),
+ dets, insert, [T,{1,2}]),
+ ?line check_badarg(catch dets:insert(T, [{1,2}]),
+ dets, insert, [T,[{1,2}]]),
+ ?line check_badarg(catch dets:insert(T, [{1,2,3} | 3]),
+ dets, insert, [T,[{1,2,3}|3]]),
%% lookup{_keys}
- ?line {'EXIT', {badarg, [{dets,lookup_keys,[badarg,[]],_}|_]}} =
- (catch dets:lookup_keys(T, [])),
- ?line {'EXIT', {badarg, [{dets,lookup,[no_table,1],_}|_]}} =
- (catch dets:lookup(no_table, 1)),
- ?line {'EXIT', {badarg, [{dets,lookup_keys,[T,[1|2]],_}|_]}} =
- (catch dets:lookup_keys(T, [1 | 2])),
+ ?line check_badarg(catch dets:lookup_keys(T, []),
+ dets, lookup_keys, [badarg,[]]),
+ ?line check_badarg(catch dets:lookup(no_table, 1),
+ dets, lookup, [no_table,1]),
+ ?line check_badarg(catch dets:lookup_keys(T, [1 | 2]),
+ dets, lookup_keys, [T,[1|2]]),
%% member
- ?line {'EXIT', {badarg, [{dets,member,[no_table,1],_}|_]}} =
- (catch dets:member(no_table, 1)),
+ ?line check_badarg(catch dets:member(no_table, 1),
+ dets, member, [no_table,1]),
%% sync
- ?line {'EXIT', {badarg, [{dets,sync,[no_table],_}|_]}} =
- (catch dets:sync(no_table)),
+ ?line check_badarg(catch dets:sync(no_table),
+ dets, sync, [no_table]),
%% delete{_keys}
- ?line {'EXIT', {badarg, [{dets,delete,[no_table,1],_}|_]}} =
- (catch dets:delete(no_table, 1)),
+ ?line check_badarg(catch dets:delete(no_table, 1),
+ dets, delete, [no_table,1]),
%% delete_object
- ?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}],_}|_]}} =
- (catch dets:delete_object(T, {1,2})),
- ?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}]],_}|_]}} =
- (catch dets:delete_object(T, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2,3}|3]],_}|_]}} =
- (catch dets:delete_object(T, [{1,2,3} | 3])),
+ ?line check_badarg(catch dets:delete_object(no_table, {1,2,3}),
+ dets, delete_object, [no_table,{1,2,3}]),
+ ?line check_badarg(catch dets:delete_object(T, {1,2}),
+ dets, delete_object, [T,{1,2}]),
+ ?line check_badarg(catch dets:delete_object(no_table, [{1,2,3}]),
+ dets, delete_object, [no_table,[{1,2,3}]]),
+ ?line check_badarg(catch dets:delete_object(T, [{1,2}]),
+ dets, delete_object, [T,[{1,2}]]),
+ ?line check_badarg(catch dets:delete_object(T, [{1,2,3} | 3]),
+ dets, delete_object, [T,[{1,2,3}|3]]),
%% first,next,slot
- ?line {'EXIT', {badarg, [{dets,first,[no_table],_}|_]}} =
- (catch dets:first(no_table)),
- ?line {'EXIT', {badarg, [{dets,next,[no_table,1],_}|_]}} =
- (catch dets:next(no_table, 1)),
- ?line {'EXIT', {badarg, [{dets,slot,[no_table,0],_}|_]}} =
- (catch dets:slot(no_table, 0)),
+ ?line check_badarg(catch dets:first(no_table),
+ dets, first, [no_table]),
+ ?line check_badarg(catch dets:next(no_table, 1),
+ dets, next, [no_table,1]),
+ ?line check_badarg(catch dets:slot(no_table, 0),
+ dets, slot, [no_table,0]),
%% info
?line undefined = dets:info(no_table),
@@ -2330,27 +2329,27 @@ badarg(Config) when is_list(Config) ->
?line undefined = dets:info(T, foo),
%% match_delete
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
- (catch dets:match_delete(no_table, '_')),
+ ?line check_badarg(catch dets:match_delete(no_table, '_'),
+ dets, safe_fixtable, [no_table,true]),
%% delete_all_objects
- ?line {'EXIT', {badarg, [{dets,delete_all_objects,[no_table],_}|_]}} =
- (catch dets:delete_all_objects(no_table)),
+ ?line check_badarg(catch dets:delete_all_objects(no_table),
+ dets, delete_all_objects, [no_table]),
%% select_delete
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
- (catch dets:select_delete(no_table, MSpec)),
- ?line {'EXIT', {badarg, [{dets,select_delete,[T, <<17>>],_}|_]}} =
- (catch dets:select_delete(T, <<17>>)),
+ ?line check_badarg(catch dets:select_delete(no_table, MSpec),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:select_delete(T, <<17>>),
+ dets, select_delete, [T, <<17>>]),
%% traverse, fold
- ?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],_}|_]}} =
- (catch dets:foldl(fun(_, A) -> A end, [], no_table)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
- (catch dets:foldr(fun(_, A) -> A end, [], no_table)),
+ ?line check_badarg(catch dets:traverse(no_table, fun(_) -> continue end),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:foldl(fun(_, A) -> A end, [], no_table),
+ dets, safe_fixtable, [no_table,true]),
+ ?line check_badarg(catch dets:foldr(fun(_, A) -> A end, [], no_table),
+ dets, safe_fixtable, [no_table,true]),
%% close
?line ok = dets:close(T),
@@ -2358,15 +2357,16 @@ badarg(Config) when is_list(Config) ->
?line {error, not_owner} = dets:close(T),
%% init_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,_,[]],_}|_]}} =
- (catch dets:init_table(no_table, fun(X) -> X end, [])),
+ IF = fun(X) -> X end,
+ ?line check_badarg(catch dets:init_table(no_table, IF),
+ dets, init_table, [no_table,IF,[]]),
+ ?line check_badarg(catch dets:init_table(no_table, IF, []),
+ dets, init_table, [no_table,IF,[]]),
%% from_ets
Ets = ets:new(ets,[]),
- ?line {'EXIT', {badarg,[{dets,from_ets,[no_table,_],_}|_]}} =
- (catch dets:from_ets(no_table, Ets)),
+ ?line check_badarg(catch dets:from_ets(no_table, Ets),
+ dets, from_ets, [no_table,Ets]),
ets:delete(Ets),
?line {ok, T} = dets:open_file(T, Args),
@@ -4358,6 +4358,11 @@ bad_object({error,{{bad_object,_}, FileName}}, FileName) ->
bad_object({error,{{{bad_object,_,_},_,_,_}, FileName}}, FileName) ->
ok. % Debug.
+check_badarg({'EXIT', {badarg, [{M,F,Args,_} | _]}}, M, F, Args) ->
+ true;
+check_badarg({'EXIT', {badarg, [{M,F,A,_} | _]}}, M, F, Args) ->
+ true = test_server:is_native(M) andalso length(Args) =:= A.
+
check_pps(P0) ->
case pps() of
P0 ->
diff --git a/lib/stdlib/test/digraph_utils_SUITE.erl b/lib/stdlib/test/digraph_utils_SUITE.erl
index 12c486c25f..6b554c2fb7 100644
--- a/lib/stdlib/test/digraph_utils_SUITE.erl
+++ b/lib/stdlib/test/digraph_utils_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -211,8 +211,7 @@ condensation(Config) when is_list(Config) ->
{lists:sort(V1), lists:sort(V2)}
end,
?line Es = lists:map(Fun, digraph:edges(CG)),
- ?line [{[b],[c]},{[b],[d]},{[e,f,g],[e,f,g]},{[h],[h]},{[i,j],[i,j]}] =
- lists:sort(Es),
+ ?line [{[b],[c]},{[b],[d]}] = lists:sort(Es),
?line true = digraph:delete(CG),
?line true = digraph:delete(G),
ok.
diff --git a/lib/stdlib/test/dummy_via.erl b/lib/stdlib/test/dummy_via.erl
new file mode 100644
index 0000000000..e405811cbe
--- /dev/null
+++ b/lib/stdlib/test/dummy_via.erl
@@ -0,0 +1,94 @@
+-module(dummy_via).
+-export([reset/0,
+ register_name/2,
+ whereis_name/1,
+ unregister_name/1,
+ send/2]).
+
+
+reset() ->
+ P = whereis(?MODULE),
+ catch unlink(P),
+ Ref = erlang:monitor(process, P),
+ catch exit(P, kill),
+ receive {'DOWN',Ref,_,_,_} -> ok end,
+ Me = self(),
+ Pid = spawn_link(fun() ->
+ register(?MODULE, self()),
+ Me ! {self(), started},
+ loop([])
+ end),
+ receive
+ {Pid, started} ->
+ Pid
+ after 10000 ->
+ exit(timeout)
+ end.
+
+register_name(Name, Pid) when is_pid(Pid) ->
+ call({register_name, Name, Pid}).
+
+unregister_name(Name) ->
+ call({unregister_name, Name}).
+
+whereis_name(Name) ->
+ call({whereis_name, Name}).
+
+send(Name, Msg) ->
+ case whereis_name(Name) of
+ undefined ->
+ exit({badarg, {Name, Msg}});
+ Pid when is_pid(Pid) ->
+ Pid ! Msg,
+ Pid
+ end.
+
+call(Req) ->
+ MRef = erlang:monitor(process, ?MODULE),
+ ?MODULE ! {self(), MRef, Req},
+ receive
+ {'DOWN', MRef, _, _, _} ->
+ erlang:error(badarg);
+ {MRef, badarg} ->
+ erlang:error(badarg);
+ {MRef, Reply} ->
+ Reply
+ after 5000 ->
+ erlang:error(timeout)
+ end.
+
+loop(Reg) ->
+ receive
+ {'DOWN', _, _, P, _} when is_pid(P) ->
+ loop([X || {_,Pid,_} = X <- Reg, Pid =/= P]);
+ {From, Ref, Request} when is_pid(From), is_reference(Ref) ->
+ {Reply, NewReg} = handle_request(Request, Reg),
+ From ! {Ref, Reply},
+ loop(NewReg)
+ end.
+
+handle_request({register_name, Name, Pid}, Reg) when is_pid(Pid) ->
+ case lists:keyfind(Name, 1, Reg) of
+ false ->
+ Ref = erlang:monitor(process, Pid),
+ {yes, [{Name, Pid, Ref}|Reg]};
+ _ ->
+ {no, Reg}
+ end;
+handle_request({whereis_name, Name}, Reg) ->
+ case lists:keyfind(Name, 1, Reg) of
+ {_, Pid, _} ->
+ {Pid, Reg};
+ false ->
+ {undefined, Reg}
+ end;
+handle_request({unregister_name, Name}, Reg) ->
+ case lists:keyfind(Name, 1, Reg) of
+ {_, _, Ref} ->
+ catch erlang:demonitor(Ref);
+ _ ->
+ ok
+ end,
+ {ok, lists:keydelete(Name, 1, Reg)};
+handle_request(_, Reg) ->
+ {badarg, Reg}.
diff --git a/lib/stdlib/test/edlin_expand_SUITE.erl b/lib/stdlib/test/edlin_expand_SUITE.erl
index a0e198ce09..0cd2688e2e 100644
--- a/lib/stdlib/test/edlin_expand_SUITE.erl
+++ b/lib/stdlib/test/edlin_expand_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -46,10 +46,10 @@ groups() ->
[].
init_per_suite(Config) ->
- true = code:delete(expand_test),
- true = code:delete(expand_test1),
- true = code:delete('ExpandTestCaps'),
- true = code:delete('ExpandTestCaps1'),
+ (catch code:delete(expand_test)),
+ (catch code:delete(expand_test1)),
+ (catch code:delete('ExpandTestCaps')),
+ (catch code:delete('ExpandTestCaps1')),
Config.
end_per_suite(_Config) ->
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 57f3f4eddb..f79414db49 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -20,7 +20,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([rec_1/1, predef_mac/1,
+-export([rec_1/1, include_local/1, predef_mac/1,
upcase_mac_1/1, upcase_mac_2/1,
variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
@@ -63,7 +63,7 @@ end_per_testcase(_, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [rec_1, {group, upcase_mac}, predef_mac,
+ [rec_1, {group, upcase_mac}, include_local, predef_mac,
{group, variable}, otp_4870, otp_4871, otp_5362, pmod,
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
@@ -97,6 +97,22 @@ rec_1(Config) when is_list(Config) ->
?line check_errors(List),
ok.
+include_local(doc) ->
+ [];
+include_local(suite) ->
+ [];
+include_local(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line File = filename:join(DataDir, "include_local.erl"),
+ %% include_local.erl includes include/foo.hrl which
+ %% includes bar.hrl (also in include/) without requiring
+ %% any additional include path, and overriding any file
+ %% of the same name that the path points to
+ ?line {ok, List} = epp:parse_file(File, [DataDir], []),
+ ?line {value, {attribute,_,a,{true,true}}} =
+ lists:keysearch(a,3,List),
+ ok.
+
%%% Here is a little reimplementation of epp:parse_file, which times out
%%% after 4 seconds if the epp server doesn't respond. If we use the
%%% regular epp:parse_file, the test case will time out, and then epp
@@ -234,16 +250,23 @@ otp_4871(Config) when is_list(Config) ->
%% so there are some sanity checks before killing.
?line {ok,Epp} = epp:open(File, []),
timer:sleep(1),
- ?line {current_function,{epp,_,_}} = process_info(Epp, current_function),
+ ?line true = current_module(Epp, epp),
?line {monitored_by,[Io]} = process_info(Epp, monitored_by),
- ?line {current_function,{file_io_server,_,_}} =
- process_info(Io, current_function),
+ ?line true = current_module(Io, file_io_server),
?line exit(Io, emulate_crash),
timer:sleep(1),
?line {error,{_Line,epp,cannot_parse}} = otp_4871_parse_file(Epp),
?line epp:close(Epp),
ok.
+current_module(Pid, Mod) ->
+ case process_info(Pid, current_function) of
+ {current_function, undefined} ->
+ true = test_server:is_native(Mod);
+ {current_function, {Mod, _, _}} ->
+ true
+ end.
+
otp_4871_parse_file(Epp) ->
case epp:parse_erl_form(Epp) of
{ok,_} -> otp_4871_parse_file(Epp);
diff --git a/lib/stdlib/test/epp_SUITE_data/bar.hrl b/lib/stdlib/test/epp_SUITE_data/bar.hrl
new file mode 100644
index 0000000000..01c527d549
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/bar.hrl
@@ -0,0 +1,4 @@
+%% should not be included from include/foo.hrl even though the
+%% include path points here - include/bar.hrl overrides it
+
+-define(BAR_HRL, false).
diff --git a/lib/stdlib/test/epp_SUITE_data/include/bar.hrl b/lib/stdlib/test/epp_SUITE_data/include/bar.hrl
new file mode 100644
index 0000000000..038d3c900e
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include/bar.hrl
@@ -0,0 +1,3 @@
+%% included from foo.hrl in same directory
+
+-define(BAR_HRL, true).
diff --git a/lib/stdlib/test/epp_SUITE_data/include/foo.hrl b/lib/stdlib/test/epp_SUITE_data/include/foo.hrl
new file mode 100644
index 0000000000..a6dfa3d18a
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include/foo.hrl
@@ -0,0 +1,4 @@
+%% includes bar.hrl in same directory
+
+-define(FOO_HRL, true).
+-include("bar.hrl").
diff --git a/lib/stdlib/test/epp_SUITE_data/include_local.erl b/lib/stdlib/test/epp_SUITE_data/include_local.erl
new file mode 100644
index 0000000000..c8e155a064
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include_local.erl
@@ -0,0 +1,6 @@
+
+-module(include_local).
+
+-include("include/foo.hrl").
+
+-a({?FOO_HRL, ?BAR_HRL}).
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 784c7cb86e..b0c7d562d5 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1036,6 +1036,12 @@ funs(Config) when is_list(Config) ->
lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]),
?line {'EXIT',{{argument_limit,_},_}} =
(catch run_many_args(many_args1(MaxArgs+1))),
+
+ ?line check(fun() -> M = lists, F = fun M:reverse/1,
+ [1,2] = F([2,1]), ok end,
+ "begin M = lists, F = fun M:reverse/1,"
+ " [1,2] = F([2,1]), ok end.",
+ ok),
ok.
run_many_args({S, As}) ->
@@ -1161,15 +1167,22 @@ do_funs(LFH, EFH) ->
[[[0]]], ['F'], LFH, EFH),
%% Tests for a bug found by the Dialyzer - used to crash.
- ?line check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end,
- "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.",
- 47,
- ['Pmod'], LFH, EFH),
- ?line check(fun() -> Pmod = erl_eval_helper:new(42), B = Pmod:add(7), B end,
- "begin Pmod = erl_eval_helper:new(42), B = Pmod:add(7), B end.",
- 49,
- ['B','Pmod'], LFH, EFH),
-
+ case test_server:is_native(erl_eval) of
+ true ->
+ %% Parameterized modules are not supported by HiPE.
+ ok;
+ false ->
+ check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end,
+ "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.",
+ 47,
+ ['Pmod'], LFH, EFH),
+ check(fun() -> Pmod = erl_eval_helper:new(42),
+ B = Pmod:add(7), B end,
+ "begin Pmod = erl_eval_helper:new(42), "
+ "B = Pmod:add(7), B end.",
+ 49,
+ ['B','Pmod'], LFH, EFH)
+ end,
ok.
count_down(F, N) when N > 0 ->
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index f8c1ad783c..01cdb92d7b 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,6 +178,9 @@ expr(Config) when is_list(Config) ->
true ->
not_ok
end.
+
+ is_record(_, _, _) ->
+ error(wrong_is_record).
">>
],
@@ -366,6 +369,8 @@ strict(Config) when is_list(Config) ->
end
catch error:_ -> ok
end.
+ element(_, _) ->
+ error(wrong_element).
">>
],
?line run(Config, Ts1, [strict_record_tests]),
@@ -380,6 +385,8 @@ strict(Config) when is_list(Config) ->
case foo of
_ when A#r2.a =:= 1 -> ok
end.
+ element(_, _) ->
+ error(wrong_element).
">>
],
?line run(Config, Ts2, [no_strict_record_tests]),
@@ -415,6 +422,11 @@ update(Config) when is_list(Config) ->
t2() ->
R0 = #r{},
#r{_ = R0#r{a = ok}}.
+
+ %% Implicit calls to setelement/3 must go to the BIF,
+ %% not to this function.
+ setelement(_, _, _) ->
+ erlang:error(wrong_setelement_called).
">>
],
?line run(Config, Ts),
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 9041adbe5c..9f9d97b619 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1331,17 +1331,20 @@ guard(Config) when is_list(Config) ->
foo.
">>,
[warn_unused_vars, nowarn_obsolete_guard],
- {errors,[{2,erl_lint,illegal_guard_expr},
- {4,erl_lint,illegal_guard_expr},
- {6,erl_lint,illegal_guard_expr},
- {8,erl_lint,illegal_guard_expr},
- {10,erl_lint,illegal_guard_expr},
- {12,erl_lint,illegal_guard_expr},
- {14,erl_lint,illegal_guard_expr},
- {16,erl_lint,illegal_guard_expr},
- {18,erl_lint,illegal_guard_expr},
- {20,erl_lint,illegal_guard_expr}],
- []}},
+ {error,[{2,erl_lint,illegal_guard_expr},
+ {4,erl_lint,illegal_guard_expr},
+ {6,erl_lint,illegal_guard_expr},
+ {8,erl_lint,illegal_guard_expr},
+ {10,erl_lint,illegal_guard_expr},
+ {12,erl_lint,illegal_guard_expr},
+ {14,erl_lint,illegal_guard_expr},
+ {16,erl_lint,illegal_guard_expr},
+ {18,erl_lint,illegal_guard_expr},
+ {20,erl_lint,illegal_guard_expr}],
+ [{8,erl_lint,deprecated_tuple_fun},
+ {14,erl_lint,deprecated_tuple_fun},
+ {20,erl_lint,deprecated_tuple_fun},
+ {28,erl_lint,deprecated_tuple_fun}]}},
{guard6,
<<"-record(apa,{a=a,b=foo:bar()}).
apa() ->
@@ -2631,7 +2634,35 @@ bif_clash(Config) when is_list(Config) ->
binary_part(A,B,C).
">>,
[warn_unused_import],
- {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}
+ {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}},
+ %% Don't accept call to a guard BIF if there is a local definition
+ %% or an import with the same name. Note: is_record/2 is an
+ %% exception, since it is more of syntatic sugar than a real BIF.
+ {clash21,
+ <<"-export([is_list/1]).
+ -import(x, [is_tuple/1]).
+ -record(r, {a,b}).
+ x(T) when is_tuple(T) -> ok;
+ x(T) when is_list(T) -> ok.
+ y(T) when is_tuple(T) =:= true -> ok;
+ y(T) when is_list(T) =:= true -> ok;
+ y(T) when is_record(T, r, 3) -> ok;
+ y(T) when is_record(T, r, 3) =:= true -> ok;
+ y(T) when is_record(T, r) =:= true -> ok.
+ is_list(_) ->
+ ok.
+ is_record(_, _) ->
+ ok.
+ is_record(_, _, _) ->
+ ok.
+ ">>,
+ [{no_auto_import,[{is_tuple,1}]}],
+ {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}},
+ {5,erl_lint,{illegal_guard_local_call,{is_list,1}}},
+ {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}},
+ {7,erl_lint,{illegal_guard_local_call,{is_list,1}}},
+ {8,erl_lint,{illegal_guard_local_call,{is_record,3}}},
+ {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}}
],
?line [] = run(Config, Ts),
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 280c95b1aa..64853ca078 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -116,7 +116,6 @@ func(Config) when is_list(Config) ->
{func_3,
<<"t() -> fun t/0.">>},
{func_4,
- %% Has already been expanded away in sys_pre_expand.
<<"t() -> fun modul:foo/3.">>},
{func_5, % 'when' is moved down one line
<<"tkjlksjflksdjflsdjlk()
@@ -127,7 +126,9 @@ func(Config) when is_list(Config) ->
<<"t() ->
(fun() ->
true
- end)().">>}
+ end)().">>},
+ {func_7,
+ <<"t(M, F, A) -> fun M:F/A.">>}
],
?line compile(Config, Ts),
ok.
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 9f95df062b..38c085616d 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The 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 @@
module_script/1,
beam_script/1,
archive_script/1,
+ archive_script_file_access/1,
epp/1,
create_and_extract/1,
foldl/1,
@@ -44,7 +45,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, errors, strange_name, emulator_flags,
module_script, beam_script, archive_script, epp,
- create_and_extract, foldl, overflow].
+ create_and_extract, foldl, overflow,
+ archive_script_file_access].
groups() ->
[].
@@ -62,7 +64,7 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?t:minutes(1)),
+ ?line Dog = ?t:timetrap(?t:minutes(2)),
[{watchdog,Dog}|Config].
end_per_testcase(_Case, Config) ->
@@ -356,7 +358,7 @@ beam_script(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create an archive file containing two entire applications plus two
%% alternate main modules. Generate a new escript containing the archive
-%% (with .app and .beam files and ) and the escript header.
+%% (with .app and .beam files and) and the escript header.
archive_script(Config) when is_list(Config) ->
%% Copy the orig files to priv_dir
@@ -464,6 +466,147 @@ archive_script(Config) when is_list(Config) ->
ok.
+%% Test the correction of OTP-10071
+%% The errors identified are
+%%
+%% a) If primary archive was named "xxx", then a file in the same
+%% directory named "xxxyyy" would be interpreted as a file named yyy
+%% inside the archive.
+%%
+%% b) erl_prim_loader did not correctly create and normalize absolute
+%% paths for primary archive and files inside it, so unless given
+%% with exact same path files inside the archive would not be
+%% found. E.g. if escript was started as ./xxx then "xxx/file"
+%% would not be found since erl_prim_loader would try to match
+%% /full/path/to/xxx with /full/path/to/./xxx. Same problem with
+%% ../. Also, the use of symlinks in the path to the archive would
+%% cause problems.
+%%
+%% c) Depending on how the primary archive was built,
+%% erl_prim_loader:list_dir/1 would sometimes return an empty string
+%% inside the file list. This was a virtual element representing the
+%% top directory of the archive. This shall not occur.
+%%
+archive_script_file_access(Config) when is_list(Config) ->
+ %% Copy the orig files to priv_dir
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ MainMod = "archive_script_file_access",
+ MainSrc = MainMod ++ ".erl",
+ MainBeam = MainMod ++ ".beam",
+
+ Archive = filename:join([PrivDir, "archive_script_file_access.zip"]),
+ ?line {ok, _} = zip:create(Archive, ["archive_script_file_access"],
+ [{compress, []}, {cwd, DataDir}]),
+ ?line {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
+ TopDir = filename:join([PrivDir, "archive_script_file_access"]),
+
+ %% Compile the code
+ ?line ok = compile_files([MainSrc], TopDir, TopDir),
+
+ %% First, create a file structure which will be included in the archive:
+ %%
+ %% dir1/
+ %% dir1/subdir1/
+ %% dir1/subdir1/file1
+ %%
+ {ok, OldDir} = file:get_cwd(),
+ ok = file:set_cwd(TopDir),
+ DummyDir = "dir1",
+ DummySubDir = filename:join(DummyDir, "subdir1"),
+ RelDummyFile = filename:join(DummySubDir, "file1"),
+ DummyFile = filename:join(TopDir,RelDummyFile),
+ ok = filelib:ensure_dir(DummyFile),
+ ok = file:write_file(DummyFile, ["foo\nbar\nbaz"]),
+
+ %% 1. Create zip archive by adding the dummy file and the beam
+ %% file as binaries to zip.
+ %%
+ %% This used to provoke the following issues when the script was run as
+ %% "./<script_name>":
+ %% a. erl_prim_loader:read_file_info/1 returning 'error'
+ %% b. erl_prim_loader:list_dir/1 returning {ok, ["dir1", [], "file1"]}
+ %% leading to an infinite loop in reltool_target:spec_dir/1
+ Files1 =
+ lists:map(fun(Filename) ->
+ {ok, Bin} = file:read_file(Filename),
+ {Filename,Bin}
+ end,
+ [RelDummyFile,MainBeam]),
+ {ok, {"mem", Bin1}} = zip:create("mem", Files1, [memory]),
+
+ %% Create the escript
+ ScriptName1 = "archive_script_file_access1",
+ Script1 = filename:join([PrivDir, ScriptName1]),
+ Flags = "-escript main " ++ MainMod,
+ ok = escript:create(Script1,[shebang,{emu_args,Flags},{archive,Bin1}]),
+ ok = file:change_mode(Script1,8#00744),
+
+ %% If supported, create a symlink to the script. This is used to
+ %% test error b) described above this test case.
+ SymlinkName1 = "symlink_to_"++ScriptName1,
+ Symlink1 = filename:join([PrivDir, SymlinkName1]),
+ file:make_symlink(ScriptName1,Symlink1), % will fail if not supported
+
+ %% Also add a dummy file in the same directory with the same name
+ %% as the script except is also has an extension. This used to
+ %% test error a) described above this test case.
+ ok = file:write_file(Script1 ++ ".extension",
+ <<"same name as script, but with extension">>),
+
+ %% Change to script's directory and run it as "./<script_name>"
+ ok = file:set_cwd(PrivDir),
+ run(PrivDir, "./" ++ ScriptName1 ++ " " ++ ScriptName1,
+ [<<"ExitCode:0">>]),
+ ok = file:set_cwd(TopDir),
+
+
+ %% 2. Create zip archive by letting zip read the files from the file system
+ %%
+ %% The difference compared to the archive_script_file_access1 is
+ %% that this will have a file element for each directory in the
+ %% archive - while archive_script_file_access1 will only have a
+ %% file element per regular file.
+ Files2 = [DummyDir,MainBeam],
+ {ok, {"mem", Bin2}} = zip:create("mem", Files2, [memory]),
+
+ %% Create the escript
+ ScriptName2 = "archive_script_file_access2",
+ Script2 = filename:join([PrivDir, ScriptName2]),
+ ok = escript:create(Script2,[shebang,{emu_args,Flags},{archive,Bin2}]),
+ ok = file:change_mode(Script2,8#00744),
+
+ %% Also add a dummy file in the same directory with the same name
+ %% as the script except is also has an extension. This used to
+ %% test error a) described above this test case.
+ ok = file:write_file(Script2 ++ ".extension",
+ <<"same name as script, but with extension">>),
+
+ %% If supported, create a symlink to the script. This is used to
+ %% test error b) described above this test case.
+ SymlinkName2 = "symlink_to_"++ScriptName2,
+ Symlink2 = filename:join([PrivDir, SymlinkName2]),
+ file:make_symlink(ScriptName2,Symlink2), % will fail if not supported
+
+ %% Change to script's directory and run it as "./<script_name>"
+ ok = file:set_cwd(PrivDir),
+ run(PrivDir, "./" ++ ScriptName2 ++ " " ++ ScriptName2,
+ [<<"ExitCode:0">>]),
+
+ %% 3. If symlinks are supported, run one of the scripts via a symlink.
+ %%
+ %% This is in order to test error b) described above this test case.
+ case file:read_link(Symlink2) of
+ {ok,_} ->
+ run(PrivDir, "./" ++ SymlinkName2 ++ " " ++ ScriptName2,
+ [<<"ExitCode:0">>]);
+ _ -> % not supported
+ ok
+ end,
+ ok = file:set_cwd(OldDir).
+
+
compile_app(TopDir, AppName) ->
AppDir = filename:join([TopDir, AppName]),
SrcDir = filename:join([AppDir, "src"]),
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
index de56579998..431a51b0e5 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
@@ -21,6 +21,8 @@
-export([main/1]).
+-include_lib("kernel/include/file.hrl").
+
-define(DUMMY, archive_script_dummy).
-define(DICT, archive_script_dict).
@@ -32,7 +34,7 @@ main(MainArgs) ->
io:format("dummy:~p\n",[[E || E <- ErlArgs, element(1, E) =:= ?DUMMY]]),
%% Start the applications
- {error, {not_started, ?DICT}} = application:start(archive_script_dummy),
+ {error, {not_started, ?DICT}} = application:start(?DUMMY),
ok = application:start(?DICT),
ok = application:start(?DUMMY),
@@ -57,4 +59,17 @@ main(MainArgs) ->
ok = ?DICT:erase(Tab, Key),
error = ?DICT:find(Tab, Key),
ok = ?DICT:erase(Tab),
+
+ %% Check mtime related caching bug with escript/primary archive files
+ Escript = escript:script_name(),
+ {ok, FileInfo} = file:read_file_info(Escript),
+ %% Modify mtime of archive file and try to reload module
+ FileInfo2 = FileInfo#file_info{mtime=calendar:now_to_local_time(now())},
+ ok = file:write_file_info(Escript, FileInfo2),
+ Module = ?DICT,
+ {file, _} = code:is_loaded(Module),
+ true = code:delete(Module),
+ false = code:is_loaded(Module),
+ {module, Module} = code:ensure_loaded(Module),
+
ok.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
new file mode 100644
index 0000000000..b03c8ba70d
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
@@ -0,0 +1,105 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(archive_script_file_access).
+-behaviour(escript).
+
+-export([main/1]).
+
+-include_lib("kernel/include/file.hrl").
+
+main([RelArchiveFile]) ->
+
+ AbsArchiveFile = filename:absname(RelArchiveFile),
+ DotSlashArchiveFile = "./" ++ RelArchiveFile,
+
+ Beam = atom_to_list(?MODULE) ++ ".beam",
+ AbsBeam = filename:join(AbsArchiveFile,Beam),
+ RelBeam = filename:join(RelArchiveFile,Beam),
+ DotSlashBeam = filename:join(DotSlashArchiveFile,Beam),
+ Dir = "dir1",
+ AbsDir = filename:join(AbsArchiveFile,Dir),
+ RelDir = filename:join(RelArchiveFile,Dir),
+ DotSlashDir = filename:join(DotSlashArchiveFile,Dir),
+ SubDir = "subdir1",
+ AbsSubDir = filename:join(AbsDir,SubDir),
+ RelSubDir = filename:join(RelDir,SubDir),
+ DotSlashSubDir = filename:join(DotSlashDir,SubDir),
+
+ {ok,List1} = erl_prim_loader:list_dir(AbsArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(RelArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(DotSlashArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(AbsArchiveFile ++ "/"),
+ {ok,List1} = erl_prim_loader:list_dir(AbsArchiveFile ++ "/."),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([AbsDir,".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([RelDir,".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([DotSlashDir,".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([AbsSubDir,"..",".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([RelSubDir,"..",".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([DotSlashSubDir,"..",".."])),
+ false = lists:member([],List1),
+
+ %% If symlinks are supported on this platform...
+ RelSymlinkArchiveFile = "symlink_to_" ++ RelArchiveFile,
+ case file:read_link(RelSymlinkArchiveFile) of
+ {ok,_} ->
+ DotSlashSymlinkArchiveFile = "./" ++ RelSymlinkArchiveFile,
+ AbsSymlinkArchiveFile=filename:join(filename:dirname(AbsArchiveFile),
+ RelSymlinkArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(AbsSymlinkArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(RelSymlinkArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(DotSlashSymlinkArchiveFile);
+ _ -> % not supported
+ ok
+ end,
+
+
+ {ok,List2} = erl_prim_loader:list_dir(AbsDir),
+ {ok,List2} = erl_prim_loader:list_dir(RelDir),
+ {ok,List2} = erl_prim_loader:list_dir(DotSlashDir),
+ false = lists:member([],List2),
+
+ error = erl_prim_loader:list_dir(AbsBeam),
+ error = erl_prim_loader:list_dir(RelBeam),
+ error = erl_prim_loader:list_dir(DotSlashBeam),
+
+ error = erl_prim_loader:get_file(AbsArchiveFile),
+ error = erl_prim_loader:get_file(RelArchiveFile),
+ error = erl_prim_loader:get_file(DotSlashArchiveFile),
+ error = erl_prim_loader:get_file(AbsArchiveFile ++ "/"),
+ error = erl_prim_loader:get_file(AbsArchiveFile ++ "/."),
+ {ok,Bin,AbsBeam} = erl_prim_loader:get_file(AbsBeam),
+ {ok,Bin,RelBeam} = erl_prim_loader:get_file(RelBeam),
+ {ok,Bin,DotSlashBeam} = erl_prim_loader:get_file(DotSlashBeam),
+
+ {ok,#file_info{type=directory}=DFI} =
+ erl_prim_loader:read_file_info(AbsArchiveFile),
+ {ok,DFI} = erl_prim_loader:read_file_info(RelArchiveFile),
+ {ok,DFI} = erl_prim_loader:read_file_info(DotSlashArchiveFile),
+ {ok,DFI} = erl_prim_loader:read_file_info(AbsArchiveFile ++ "/"),
+ {ok,DFI} = erl_prim_loader:read_file_info(AbsArchiveFile ++ "/."),
+ {ok,#file_info{type=regular}=RFI} = erl_prim_loader:read_file_info(AbsBeam),
+ {ok,RFI} = erl_prim_loader:read_file_info(RelBeam),
+ {ok,RFI} = erl_prim_loader:read_file_info(DotSlashBeam),
+
+ F = AbsArchiveFile ++ ".extension",
+ error = erl_prim_loader:list_dir(F),
+ {ok,_,_} = erl_prim_loader:get_file(F),
+ {ok,#file_info{type=regular}} = erl_prim_loader:read_file_info(F),
+
+ ok.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index e048764a55..95f10b1df3 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,9 @@
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_9932/1]).
-export([otp_9423/1]).
+-export([otp_10182/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% Convenience for manual testing
@@ -145,6 +147,8 @@ all() ->
exit_many_large_table_owner, exit_many_tables_owner,
exit_many_many_tables_owner, write_concurrency, heir,
give_away, setopts, bad_table, types,
+ otp_10182,
+ otp_9932,
otp_9423].
groups() ->
@@ -176,6 +180,7 @@ groups() ->
meta_newdel_unnamed, meta_newdel_named]}].
init_per_suite(Config) ->
+ erts_debug:set_internal_state(available_internal_state, true),
Config.
end_per_suite(_Config) ->
@@ -304,7 +309,6 @@ t_match_spec_run(Config) when is_list(Config) ->
end,
repeat_for_permutations(F, N_MS)
end,
-
test_terms(Fun, skip_refc_check),
?line verify_etsmem(EtsMem).
@@ -324,7 +328,7 @@ t_match_spec_run_test(List, MS, Result) ->
%% Check that tracing agree
Self = self(),
- {Tracee, MonRef} = spawn_monitor(fun() -> ms_tracee(Self, List) end),
+ {Tracee, MonRef} = my_spawn_monitor(fun() -> ms_tracee(Self, List) end),
receive {Tracee, ready} -> ok end,
MST = lists:map(fun(Clause) -> ms_clause_ets_to_trace(Clause) end, MS),
@@ -585,7 +589,6 @@ select_fail_do(Opts) ->
memory(doc) -> ["Whitebox test of ets:info(X,memory)"];
memory(suite) -> [];
memory(Config) when is_list(Config) ->
- ?line erts_debug:set_internal_state(available_internal_state, true),
?line ok = chk_normal_tab_struct_size(),
repeat_for_opts(memory_do,[compressed]),
?line catch erts_debug:set_internal_state(available_internal_state, false).
@@ -714,30 +717,17 @@ adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) ->
TabDiff = ?TAB_STRUCT_SZ,
Mem1 = {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff},
- Mem2 = case {erlang:system_info({wordsize,internal}),erlang:system_info({wordsize,external})} of
- %% Halfword, corrections for regular pointers occupying two internal words.
- {4,8} ->
- {A1,B1,C1,D1} = Mem1,
- {A1+4*ets:info(T1, size)+?DB_TREE_STACK_NEED,
- B1+3*ets:info(T2, size)+?DB_HASH_SIZEOF_EXTSEG,
- C1+3*ets:info(T3, size)+?DB_HASH_SIZEOF_EXTSEG,
- D1+3*ets:info(T4, size)+?DB_HASH_SIZEOF_EXTSEG};
- _ ->
- Mem1
- end,
-
- %% Adjust for hybrid and shared heaps:
- %% Each record is one word smaller.
- %%Mem2 = case erlang:system_info(heap_type) of
- %% private ->
- %% Mem1;
- %% _ ->
- %% {A1,B1,C1,D1} = Mem1,
- %% {A1-ets:info(T1, size),B1-ets:info(T2, size),
- %% C1-ets:info(T3, size),D1-ets:info(T4, size)}
- %% end,
- %%{Mem2,{ets:info(T1,stats),ets:info(T2,stats),ets:info(T3,stats),ets:info(T4,stats)}}.
- Mem2.
+ case {erlang:system_info({wordsize,internal}),erlang:system_info({wordsize,external})} of
+ %% Halfword, corrections for regular pointers occupying two internal words.
+ {4,8} ->
+ {A1,B1,C1,D1} = Mem1,
+ {A1+4*ets:info(T1, size)+?DB_TREE_STACK_NEED,
+ B1+3*ets:info(T2, size)+?DB_HASH_SIZEOF_EXTSEG,
+ C1+3*ets:info(T3, size)+?DB_HASH_SIZEOF_EXTSEG,
+ D1+3*ets:info(T4, size)+?DB_HASH_SIZEOF_EXTSEG};
+ _ ->
+ Mem1
+ end.
t_whitebox(doc) ->
["Diverse whitebox testes"];
@@ -795,21 +785,26 @@ 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],_}|_]}} =
- (catch ets:to_dets(ETab,DTab)),
- ?line {'EXIT',{badarg,[{ets,from_dets,[ETab,DTab],_}|_]}} =
- (catch ets:from_dets(ETab,DTab)),
+ ?line check_badarg(catch ets:to_dets(ETab,DTab),
+ ets, to_dets, [ETab,DTab]),
+ ?line check_badarg(catch ets:from_dets(ETab,DTab),
+ 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],_}|_]}} =
- (catch ets:to_dets(ETab2,DTab)),
- ?line {'EXIT',{badarg,[{ets,from_dets,[ETab2,DTab],_}|_]}} =
- (catch ets:from_dets(ETab2,DTab)),
+ ?line check_badarg(catch ets:to_dets(ETab2,DTab),
+ ets, to_dets, [ETab2,DTab]),
+ ?line check_badarg(catch ets:from_dets(ETab2,DTab),
+ ets, from_dets, [ETab2,DTab]),
?line ets:delete(ETab2),
?line (catch file:delete(Fname)),
ok.
+check_badarg({'EXIT', {badarg, [{M,F,Args,_} | _]}}, M, F, Args) ->
+ true;
+check_badarg({'EXIT', {badarg, [{M,F,A,_} | _]}}, M, F, Args) ->
+ true = test_server:is_native(M) andalso length(Args) =:= A.
+
t_delete_all_objects(doc) ->
["Test ets:delete_all_objects/1"];
t_delete_all_objects(suite) ->
@@ -1031,6 +1026,8 @@ t_test_ms(Config) when is_list(Config) ->
[{{'$1','$2'},[{'<','$1','$2'}],['$$']}]),
?line {ok,false} = ets:test_ms({a,b},
[{{'$1','$2'},[{'>','$1','$2'}],['$$']}]),
+ Tpl = {a,gb_sets:new()},
+ ?line {ok,Tpl} = ets:test_ms(Tpl, [{{'_','_'}, [], ['$_']}]), % OTP-10190
?line {error,[{error,String}]} = ets:test_ms({a,b},
[{{'$1','$2'},
[{'flurp','$1','$2'}],
@@ -1942,7 +1939,7 @@ evil_update_counter(Config) when is_list(Config) ->
evil_update_counter_do(Opts) ->
?line EtsMem = etsmem(),
?line process_flag(trap_exit, true),
- ?line Pids = [spawn_link(fun() -> evil_counter(I,Opts) end) || I <- lists:seq(1, 40)],
+ ?line Pids = [my_spawn_link(fun() -> evil_counter(I,Opts) end) || I <- lists:seq(1, 40)],
?line wait_for_all(gb_sets:from_list(Pids)),
?line verify_etsmem(EtsMem),
ok.
@@ -2148,24 +2145,24 @@ heir_do(Opts) ->
Combos),
%% No heir
- {Founder1,MrefF1} = spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
+ {Founder1,MrefF1} = my_spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
Founder1 ! {go, none},
?line {"No heir",Founder1} = receive_any(),
?line {'DOWN', MrefF1, process, Founder1, normal} = receive_any(),
?line undefined = ets:info(foo),
%% An already dead heir
- {Heir2,MrefH2} = spawn_monitor(fun()->die end),
+ {Heir2,MrefH2} = my_spawn_monitor(fun()->die end),
?line {'DOWN', MrefH2, process, Heir2, normal} = receive_any(),
- {Founder2,MrefF2} = spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
+ {Founder2,MrefF2} = my_spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
Founder2 ! {go, Heir2},
?line {"No heir",Founder2} = receive_any(),
?line {'DOWN', MrefF2, process, Founder2, normal} = receive_any(),
?line undefined = ets:info(foo),
%% When heir dies before founder
- {Founder3,MrefF3} = spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
- {Heir3,MrefH3} = spawn_monitor(fun()->heir_heir(Founder3)end),
+ {Founder3,MrefF3} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
+ {Heir3,MrefH3} = my_spawn_monitor(fun()->heir_heir(Founder3)end),
Founder3 ! {go, Heir3},
?line {'DOWN', MrefH3, process, Heir3, normal} = receive_any(),
Founder3 ! die_please,
@@ -2173,14 +2170,12 @@ heir_do(Opts) ->
?line undefined = ets:info(foo),
%% When heir dies and pid reused before founder dies
- erts_debug:set_internal_state(available_internal_state,true),
NextPidIx = erts_debug:get_internal_state(next_pid),
- {Founder4,MrefF4} = spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
- {Heir4,MrefH4} = spawn_monitor(fun()->heir_heir(Founder4)end),
+ {Founder4,MrefF4} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
+ {Heir4,MrefH4} = my_spawn_monitor(fun()->heir_heir(Founder4)end),
Founder4 ! {go, Heir4},
?line {'DOWN', MrefH4, process, Heir4, normal} = receive_any(),
erts_debug:set_internal_state(next_pid, NextPidIx),
- erts_debug:set_internal_state(available_internal_state,false),
{Heir4,MrefH4_B} = spawn_monitor_with_pid(Heir4,
fun()-> ?line die_please = receive_any() end),
Founder4 ! die_please,
@@ -2256,9 +2251,9 @@ heir_heir(Founder, Mode) ->
heir_1(HeirData,Mode,Opts) ->
io:format("test with heir_data = ~p\n", [HeirData]),
Master = self(),
- ?line Founder = spawn_link(fun() -> heir_founder(Master,HeirData,Opts) end),
+ ?line Founder = my_spawn_link(fun() -> heir_founder(Master,HeirData,Opts) end),
io:format("founder spawned = ~p\n", [Founder]),
- ?line {Heir,Mref} = spawn_monitor(fun() -> heir_heir(Founder,Mode) end),
+ ?line {Heir,Mref} = my_spawn_monitor(fun() -> heir_heir(Founder,Mode) end),
io:format("heir spawned = ~p\n", [{Heir,Mref}]),
?line Founder ! {go, Heir},
?line {'DOWN', Mref, process, Heir, normal} = receive_any().
@@ -2275,7 +2270,7 @@ give_away_do(Opts) ->
Parent = self(),
%% Give and then give back
- ?line {Receiver,Mref} = spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
+ ?line {Receiver,Mref} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
?line give_me = receive_any(),
?line true = ets:give_away(T,Receiver,here_you_are),
?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
@@ -2286,7 +2281,7 @@ give_away_do(Opts) ->
%% Give and then let receiver keep it
?line true = ets:insert(T,{key,1}),
- ?line {Receiver3,Mref3} = spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
+ ?line {Receiver3,Mref3} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
?line give_me = receive_any(),
?line true = ets:give_away(T,Receiver3,here_you_are),
?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
@@ -2298,7 +2293,7 @@ give_away_do(Opts) ->
?line T2 = ets_new(foo,[private | Opts]),
?line true = ets:insert(T2,{key,1}),
?line ets:setopts(T2,{heir,self(),"Som en gummiboll..."}),
- ?line {Receiver2,Mref2} = spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
+ ?line {Receiver2,Mref2} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
?line give_me = receive_any(),
?line true = ets:give_away(T2,Receiver2,here_you_are),
?line {'EXIT',{badarg,_}} = (catch ets:lookup(T2,key)),
@@ -2313,12 +2308,12 @@ give_away_do(Opts) ->
?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,"not a pid","To wrong type")),
?line true = ets:delete(T2),
- ?line {ReceiverNeg,MrefNeg} = spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
+ ?line {ReceiverNeg,MrefNeg} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
?line give_me = receive_any(),
?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,ReceiverNeg,"A deleted table")),
?line T3 = ets_new(foo,[public | Opts]),
- spawn_link(fun()-> {'EXIT',{badarg,_}} = (catch ets:give_away(T3,ReceiverNeg,"From non owner")),
+ my_spawn_link(fun()-> {'EXIT',{badarg,_}} = (catch ets:give_away(T3,ReceiverNeg,"From non owner")),
Parent ! done
end),
?line done = receive_any(),
@@ -2354,7 +2349,7 @@ setopts_do(Opts) ->
Self = self(),
?line T = ets_new(foo,[named_table, private | Opts]),
?line none = ets:info(T,heir),
- Heir = spawn_link(fun()->heir_heir(Self) end),
+ Heir = my_spawn_link(fun()->heir_heir(Self) end),
?line ets:setopts(T,{heir,Heir,"Data"}),
?line Heir = ets:info(T,heir),
?line ets:setopts(T,{heir,self(),"Data"}),
@@ -2383,6 +2378,8 @@ setopts_do(Opts) ->
?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,private,false})),
?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,protection)),
?line ets:delete(T),
+ unlink(Heir),
+ exit(Heir, bang),
ok.
bad_table(doc) -> ["All kinds of operations with bad table argument"];
@@ -2405,14 +2402,14 @@ bad_table(Config) when is_list(Config) ->
bad_table_do(Opts, DummyFile) ->
Parent = self(),
- {Pid,Mref} = spawn_opt(fun()-> ets_new(priv,[private,named_table | Opts]),
- Priv = ets_new(priv,[private | Opts]),
- ets_new(prot,[protected,named_table | Opts]),
- Prot = ets_new(prot,[protected | Opts]),
- Parent ! {self(),Priv,Prot},
- die_please = receive_any()
- end,
- [link, monitor]),
+ {Pid,Mref} = my_spawn_opt(fun()-> ets_new(priv,[private,named_table | Opts]),
+ Priv = ets_new(priv,[private | Opts]),
+ ets_new(prot,[protected,named_table | Opts]),
+ Prot = ets_new(prot,[protected | Opts]),
+ Parent ! {self(),Priv,Prot},
+ die_please = receive_any()
+ end,
+ [link, monitor]),
{Pid,Priv,Prot} = receive_any(),
MatchSpec = {{key,'_'}, [], ['$$']},
Fun = fun(X,_) -> X end,
@@ -3258,7 +3255,7 @@ delete_large_named_table_1(Name, Flags, Data, Fix) ->
?line lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
end,
Parent = self(),
- Pid = spawn_link(fun() ->
+ Pid = my_spawn_link(fun() ->
receive
{trace,Parent,call,_} ->
ets_new(Name, [named_table])
@@ -3620,7 +3617,7 @@ cycle(Tab, L) ->
ets:insert(Tab,list_to_tuple(L)),
cycle(Tab, tl(L)++[hd(L)]).
-dynamic_go() -> spawn_link(fun dynamic_init/0).
+dynamic_go() -> my_spawn_link(fun dynamic_init/0).
dynamic_init() -> [dyn_lookup(?MODULE) || _ <- lists:seq(1, 10)].
@@ -3847,7 +3844,7 @@ safe_fixtable_do(Opts) ->
Self = self(),
?line {{_,_,_},[{Self,1}]} = ets:info(Tab,safe_fixed),
%% Test that an unjustified 'unfix' is a no-op.
- {Pid,MRef} = spawn_monitor(fun() -> true = ets:safe_fixtable(Tab,false) end),
+ {Pid,MRef} = my_spawn_monitor(fun() -> true = ets:safe_fixtable(Tab,false) end),
{'DOWN', MRef, process, Pid, normal} = receive M -> M end,
?line true = ets:info(Tab,fixed),
?line {{_,_,_},[{Self,1}]} = ets:info(Tab,safe_fixed),
@@ -4251,7 +4248,7 @@ do_heavy_concurrent(Opts) ->
?line ok = fill_tab2(Tab, 0, Size),
?line Procs = lists:map(
fun (N) ->
- spawn_link(
+ my_spawn_link(
fun () ->
do_heavy_concurrent_proc(Tab, Size, N)
end)
@@ -4855,12 +4852,7 @@ otp_7665_act(Tab,Min,Max,DelNr) ->
%% Whitebox testing of meta name table hashing.
meta_wb(Config) when is_list(Config) ->
?line EtsMem = etsmem(),
- ?line erts_debug:set_internal_state(available_internal_state, true),
- try
- repeat_for_opts(meta_wb_do)
- after
- erts_debug:set_internal_state(available_internal_state, false)
- end,
+ repeat_for_opts(meta_wb_do),
?line verify_etsmem(EtsMem).
@@ -4929,12 +4921,15 @@ colliding_names(Name) ->
grow_shrink(Config) when is_list(Config) ->
?line EtsMem = etsmem(),
- grow_shrink_0(lists:seq(3071, 5000), EtsMem).
+ ?line grow_shrink_0(lists:seq(3071, 5000), EtsMem),
+ ?line verify_etsmem(EtsMem).
grow_shrink_0([N|Ns], EtsMem) ->
?line grow_shrink_1(N, [set]),
?line grow_shrink_1(N, [ordered_set]),
- ?line verify_etsmem(EtsMem),
+ %% Verifying ets-memory here takes too long time, since
+ %% lock-free allocators were introduced...
+ %% ?line verify_etsmem(EtsMem),
grow_shrink_0(Ns, EtsMem);
grow_shrink_0([], _) -> ok.
@@ -4981,13 +4976,13 @@ grow_pseudo_deleted_do(Type) ->
?line Left = ets:info(T,size),
?line Mult = get_kept_objects(T),
filltabstr(T,Mult),
- spawn_opt(fun()-> ?line true = ets:info(T,fixed),
- Self ! start,
- io:format("Starting to filltabstr... ~p\n",[now()]),
- filltabstr(T,Mult,Mult+10000),
- io:format("Done with filltabstr. ~p\n",[now()]),
- Self ! done
- end, [link, {scheduler,2}]),
+ my_spawn_opt(fun()-> ?line true = ets:info(T,fixed),
+ Self ! start,
+ io:format("Starting to filltabstr... ~p\n",[now()]),
+ filltabstr(T,Mult,Mult+10000),
+ io:format("Done with filltabstr. ~p\n",[now()]),
+ Self ! done
+ end, [link, {scheduler,2}]),
?line start = receive_any(),
io:format("Unfixing table...~p nitems=~p\n",[now(),ets:info(T,size)]),
?line true = ets:safe_fixtable(T,false),
@@ -5021,13 +5016,13 @@ shrink_pseudo_deleted_do(Type) ->
[true]}]),
?line Half = ets:info(T,size),
?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()]),
- del_one_by_one_set(T,1,Half+1),
- io:format("Done with delete. ~p\n",[now()]),
- Self ! done
- end, [link, {scheduler,2}]),
+ my_spawn_opt(fun()-> ?line true = ets:info(T,fixed),
+ Self ! start,
+ io:format("Starting to delete... ~p\n",[now()]),
+ del_one_by_one_set(T,1,Half+1),
+ io:format("Done with delete. ~p\n",[now()]),
+ Self ! done
+ end, [link, {scheduler,2}]),
?line start = receive_any(),
io:format("Unfixing table...~p nitems=~p\n",[now(),ets:info(T,size)]),
?line true = ets:safe_fixtable(T,false),
@@ -5184,24 +5179,24 @@ smp_unfix_fix_do() ->
?line Deleted = get_kept_objects(T),
{Child, Mref} =
- spawn_opt(fun()-> ?line true = ets:info(T,fixed),
- Parent ! start,
- io:format("Child waiting for table to be unfixed... now=~p mem=~p\n",
- [now(),ets:info(T,memory)]),
- repeat_while(fun()-> ets:info(T,fixed) end),
- io:format("Table unfixed. Child Fixating! now=~p mem=~p\n",
- [now(),ets:info(T,memory)]),
- ?line true = ets:safe_fixtable(T,true),
- repeat_while(fun(Key) when Key =< NumOfObjs ->
- ets:delete(T,Key), {true,Key+1};
- (Key) -> {false,Key}
- end,
- Deleted),
- ?line 0 = ets:info(T,size),
- ?line true = get_kept_objects(T) >= Left,
- ?line done = receive_any()
- end,
- [link, monitor, {scheduler,2}]),
+ my_spawn_opt(fun()-> ?line true = ets:info(T,fixed),
+ Parent ! start,
+ io:format("Child waiting for table to be unfixed... now=~p mem=~p\n",
+ [now(),ets:info(T,memory)]),
+ repeat_while(fun()-> ets:info(T,fixed) end),
+ io:format("Table unfixed. Child Fixating! now=~p mem=~p\n",
+ [now(),ets:info(T,memory)]),
+ ?line true = ets:safe_fixtable(T,true),
+ repeat_while(fun(Key) when Key =< NumOfObjs ->
+ ets:delete(T,Key), {true,Key+1};
+ (Key) -> {false,Key}
+ end,
+ Deleted),
+ ?line 0 = ets:info(T,size),
+ ?line true = get_kept_objects(T) >= Left,
+ ?line done = receive_any()
+ end,
+ [link, monitor, {scheduler,2}]),
?line start = receive_any(),
?line true = ets:info(T,fixed),
@@ -5232,11 +5227,11 @@ otp_8166_do(WC) ->
Deleted = NumOfObjs div 2,
filltabint(T,NumOfObjs),
{ReaderPid, ReaderMref} =
- spawn_opt(fun()-> otp_8166_reader(T,NumOfObjs) end,
- [link, monitor, {scheduler,2}]),
+ my_spawn_opt(fun()-> otp_8166_reader(T,NumOfObjs) end,
+ [link, monitor, {scheduler,2}]),
{ZombieCrPid, ZombieCrMref} =
- spawn_opt(fun()-> otp_8166_zombie_creator(T,Deleted) end,
- [link, monitor, {scheduler,3}]),
+ my_spawn_opt(fun()-> otp_8166_zombie_creator(T,Deleted) end,
+ [link, monitor, {scheduler,3}]),
repeat(fun() -> ZombieCrPid ! {loop, self()},
zombies_created = receive_any(),
@@ -5432,6 +5427,22 @@ types_do(Opts) ->
?line verify_etsmem(EtsMem).
+%% OTP-9932: Memory overwrite when inserting large integers in compressed bag.
+%% Will crash with segv on 64-bit opt if not fixed.
+otp_9932(Config) when is_list(Config) ->
+ T = ets:new(xxx, [bag, compressed]),
+ Fun = fun(N) ->
+ Key = {1316110174588445 bsl N,1316110174588583 bsl N},
+ S = {Key, Key},
+ true = ets:insert(T, S),
+ [S] = ets:lookup(T, Key),
+ true = ets:insert(T, S),
+ [S] = ets:lookup(T, Key)
+ end,
+ lists:foreach(Fun, lists:seq(0, 16)),
+ ets:delete(T).
+
+
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,
@@ -5463,6 +5474,20 @@ otp_9423(Config) when is_list(Config) ->
Skipped -> Skipped
end.
+
+%% Corrupted binary in compressed table
+otp_10182(Config) when is_list(Config) ->
+ Bin = <<"aHR0cDovL2hvb3RzdWl0ZS5jb20vYy9wcm8tYWRyb2xsLWFi">>,
+ Key = {test, Bin},
+ Value = base64:decode(Bin),
+ In = {Key,Value},
+ Db = ets:new(undefined, [set, protected, {read_concurrency, true}, compressed]),
+ ets:insert(Db, In),
+ [Out] = ets:lookup(Db, Key),
+ io:format("In : ~p\nOut: ~p\n", [In,Out]),
+ ets:delete(Db),
+ In = Out.
+
@@ -5496,7 +5521,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
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)
+ Pids = [my_spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
case Laps of
infinite -> Pids;
@@ -5545,31 +5570,30 @@ my_tab_to_list(_Ts,'$end_of_table', Acc) -> lists:reverse(Acc);
my_tab_to_list(Ts,Key, Acc) ->
my_tab_to_list(Ts,ets:next(Ts,Key),[ets:lookup(Ts, Key)| Acc]).
-wait_for_all_schedulers_online_to_execute() ->
- PMs = lists:map(fun (Sched) ->
- spawn_opt(fun () -> ok end,
- [monitor, {scheduler, Sched}])
- end,
- lists:seq(1,erlang:system_info(schedulers_online))),
- lists:foreach(fun ({P, M}) ->
- receive
- {'DOWN', M, process, P, _} -> ok
- end
- end,
- PMs),
- ok.
+
+wait_for_memory_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
+ end.
+
etsmem() ->
- %% Wait until it is guaranteed that all already scheduled
- %% deallocations of DbTable structures have completed.
- wait_for_all_schedulers_online_to_execute(),
+ wait_for_memory_deallocations(),
AllTabs = lists:map(fun(T) -> {T,ets:info(T,name),ets:info(T,size),
ets:info(T,memory),ets:info(T,type)}
end, ets:all()),
+
+ EtsAllocInfo = erlang:system_info({allocator,ets_alloc}),
+ ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end,
+
Mem =
- {try erlang:memory(ets) catch error:notsup -> notsup end,
- case erlang:system_info({allocator,ets_alloc}) of
+ {ErlangMemoryEts,
+ case EtsAllocInfo of
false -> undefined;
MemInfo ->
CS = lists:foldl(
@@ -5646,6 +5670,8 @@ spawn_logger(Procs) ->
true -> exit(Proc, kill);
_ -> ok
end,
+ erlang:display({"Waiting for 'DOWN' from", Proc,
+ process_info(Proc), pid_status(Proc)}),
receive
{'DOWN', Mon, _, _, _} ->
ok
@@ -5656,6 +5682,15 @@ spawn_logger(Procs) ->
spawn_logger([From])
end.
+pid_status(Pid) ->
+ try
+ erts_debug:get_internal_state({process_status, Pid})
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ pid_status(Pid)
+ end.
+
start_spawn_logger() ->
case whereis(ets_test_spawn_logger) of
Pid when is_pid(Pid) -> true;
@@ -5681,7 +5716,7 @@ wait_for_test_procs(Kill) ->
ets_test_spawn_logger ! {sync_test_procs, Kill, self()},
receive test_procs_synced -> ok end.
-log_test_proc(Proc) ->
+log_test_proc(Proc) when is_pid(Proc) ->
ets_test_spawn_logger ! {new_test_proc, Proc},
Proc.
@@ -5693,9 +5728,17 @@ my_spawn_link(Fun) -> log_test_proc(spawn_link(Fun)).
my_spawn_link(M,F,A) -> log_test_proc(spawn_link(M,F,A)).
%%my_spawn_link(N,M,F,A) -> log_test_proc(spawn_link(N,M,F,A)).
-my_spawn_opt(Fun,Opts) -> log_test_proc(spawn_opt(Fun,Opts)).
-%%my_spawn_opt(M,F,A,Opts) -> log_test_proc(spawn_opt(M,F,A,Opts)).
-%%my_spawn_opt(N,M,F,A,Opts) -> log_test_proc(spawn_opt(N,M,F,A,Opts)).
+my_spawn_opt(Fun,Opts) ->
+ case spawn_opt(Fun,Opts) of
+ Pid when is_pid(Pid) -> log_test_proc(Pid);
+ {Pid, _} = Res when is_pid(Pid) -> log_test_proc(Pid), Res
+ end.
+
+my_spawn_monitor(Fun) ->
+ Res = spawn_monitor(Fun),
+ {Pid, _} = Res,
+ log_test_proc(Pid),
+ Res.
repeat(_Fun, 0) ->
ok;
@@ -5758,11 +5801,11 @@ spawn_monitor_with_pid(Pid, Fun, N, M) when N > M*10 ->
spawn_monitor_with_pid(Pid, Fun, N, M*10);
spawn_monitor_with_pid(Pid, Fun, N, M) ->
?line false = is_process_alive(Pid),
- case spawn(fun()-> case self() of
- Pid -> Fun();
- _ -> die
- end
- end) of
+ case my_spawn(fun()-> case self() of
+ Pid -> Fun();
+ _ -> die
+ end
+ end) of
Pid ->
{Pid, erlang:monitor(process, Pid)};
Other ->
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index 70b0d413dc..99516c0c04 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -25,7 +25,7 @@
-export([pathtype/1,rootname/1,split/1,find_src/1]).
-export([absname_bin/1, absname_bin_2/1,
basename_bin_1/1, basename_bin_2/1,
- dirname_bin/1, extension_bin/1, join_bin/1]).
+ dirname_bin/1, extension_bin/1, join_bin/1, t_nativename_bin/1]).
-export([pathtype_bin/1,rootname_bin/1,split_bin/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -38,7 +38,7 @@ all() ->
join, pathtype, rootname, split, t_nativename, find_src,
absname_bin, absname_bin_2, basename_bin_1, basename_bin_2, dirname_bin,
extension_bin,
- join_bin, pathtype_bin, rootname_bin, split_bin].
+ join_bin, pathtype_bin, rootname_bin, split_bin, t_nativename_bin].
groups() ->
[].
@@ -483,6 +483,22 @@ find_src(Config) when is_list(Config) ->
%% Try to find the source for a preloaded module.
?line {error,{preloaded,init}} = filename:find_src(init),
+
+ %% Make sure that find_src works for a slim BEAM file.
+ OldPath = code:get_path(),
+ try
+ PrivDir = ?config(priv_dir, Config),
+ code:add_patha(PrivDir),
+ Src = "simple",
+ SrcPath = filename:join(PrivDir, Src) ++ ".erl",
+ SrcContents = "-module(simple).\n",
+ ok = file:write_file(SrcPath, SrcContents),
+ {ok,simple} = compile:file(SrcPath, [slim,{outdir,PrivDir}]),
+ BeamPath = filename:join(PrivDir, Src),
+ {BeamPath,[]} = filename:find_src(simple)
+ after
+ code:set_path(OldPath)
+ end,
ok.
%%
@@ -788,3 +804,14 @@ split_bin(Config) when is_list(Config) ->
ok
end.
+t_nativename_bin(Config) when is_list(Config) ->
+ ?line <<"abcedf">> = filename:nativename(<<"abcedf">>),
+ case os:type() of
+ {win32, _} ->
+ ?line <<"a:\\temp\\arne.exe">> =
+ filename:nativename(<<"A:/temp//arne.exe/">>);
+ _ ->
+ ?line <<"/usr/tmp/arne">> =
+ filename:nativename(<<"/usr/tmp//arne/">>)
+ end.
+
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index b3a7edc140..5c51e12e35 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -62,6 +62,8 @@ start(suite) -> [];
start(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
+ ?line dummy_via:reset(),
+
?line {ok, Pid0} = gen_event:start(), %anonymous
?line [] = gen_event:which_handlers(Pid0),
?line ok = gen_event:stop(Pid0),
@@ -85,6 +87,11 @@ start(Config) when is_list(Config) ->
?line [] = gen_event:which_handlers(Pid4),
?line ok = gen_event:stop({global, my_dummy_name}),
+ ?line {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}),
+ ?line [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}),
+ ?line [] = gen_event:which_handlers(Pid5),
+ ?line ok = gen_event:stop({via, dummy_via, my_dummy_name}),
+
?line {ok, _} = gen_event:start_link({local, my_dummy_name}),
?line {error, {already_started, _}} =
gen_event:start_link({local, my_dummy_name}),
@@ -92,15 +99,28 @@ start(Config) when is_list(Config) ->
gen_event:start({local, my_dummy_name}),
?line ok = gen_event:stop(my_dummy_name),
- ?line {ok, Pid5} = gen_event:start_link({global, my_dummy_name}),
+ ?line {ok, Pid6} = gen_event:start_link({global, my_dummy_name}),
?line {error, {already_started, _}} =
gen_event:start_link({global, my_dummy_name}),
?line {error, {already_started, _}} =
gen_event:start({global, my_dummy_name}),
- exit(Pid5, shutdown),
+ exit(Pid6, shutdown),
+ receive
+ {'EXIT', Pid6, shutdown} -> ok
+ after 10000 ->
+ ?t:fail(exit_gen_event)
+ end,
+
+ ?line {ok, Pid7} = gen_event:start_link({via, dummy_via, my_dummy_name}),
+ ?line {error, {already_started, _}} =
+ gen_event:start_link({via, dummy_via, my_dummy_name}),
+ ?line {error, {already_started, _}} =
+ gen_event:start({via, dummy_via, my_dummy_name}),
+
+ exit(Pid7, shutdown),
receive
- {'EXIT', Pid5, shutdown} -> ok
+ {'EXIT', Pid7, shutdown} -> ok
after 10000 ->
?t:fail(exit_gen_event)
end,
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index d60629d841..bdb4ea65b5 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -21,11 +21,11 @@
-include_lib("test_server/include/test_server.hrl").
%% Test cases
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([ start1/1, start2/1, start3/1, start4/1 , start5/1, start6/1,
- start7/1, start8/1, start9/1, start10/1, start11/1]).
+-export([start1/1, start2/1, start3/1, start4/1, start5/1, start6/1,
+ start7/1, start8/1, start9/1, start10/1, start11/1, start12/1]).
-export([ abnormal1/1, abnormal2/1]).
@@ -56,14 +56,14 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
[{group, start}, {group, abnormal}, shutdown,
{group, sys}, hibernate, enter_loop].
-groups() ->
+groups() ->
[{start, [],
[start1, start2, start3, start4, start5, start6, start7,
- start8, start9, start10, start11]},
+ start8, start9, start10, start11, start12]},
{abnormal, [], [abnormal1, abnormal2]},
{sys, [],
[sys1, call_format_status, error_format_status]}].
@@ -258,6 +258,25 @@ start11(Config) when is_list(Config) ->
test_server:messages_get(),
ok.
+%% Via register linked
+start12(Config) when is_list(Config) ->
+ ?line dummy_via:reset(),
+ ?line {ok, Pid} =
+ gen_fsm:start_link({via, dummy_via, my_fsm}, gen_fsm_SUITE, [], []),
+ ?line {error, {already_started, Pid}} =
+ gen_fsm:start_link({via, dummy_via, my_fsm}, gen_fsm_SUITE, [], []),
+ ?line {error, {already_started, Pid}} =
+ gen_fsm:start({via, dummy_via, my_fsm}, gen_fsm_SUITE, [], []),
+
+ ?line ok = do_func_test(Pid),
+ ?line ok = do_sync_func_test(Pid),
+ ?line ok = do_func_test({via, dummy_via, my_fsm}),
+ ?line ok = do_sync_func_test({via, dummy_via, my_fsm}),
+ ?line stop_it({via, dummy_via, my_fsm}),
+
+ test_server:messages_get(),
+ ok.
+
%% Check that time outs in calls work
abnormal1(suite) -> [];
@@ -362,7 +381,25 @@ call_format_status(Config) when is_list(Config) ->
?line Status4 = sys:get_status(GlobalName2),
?line {status, Pid4, _Mod, [_PDict4, running, _, _, Data4]} = Status4,
?line [format_status_called | _] = lists:reverse(Data4),
- ?line stop_it(Pid4).
+ ?line stop_it(Pid4),
+
+ %% check that format_status can handle a name being a term other than a
+ %% pid or atom
+ ?line dummy_via:reset(),
+ ViaName1 = {via, dummy_via, "CallFormatStatus"},
+ ?line {ok, Pid5} = gen_fsm:start(ViaName1, gen_fsm_SUITE, [], []),
+ ?line Status5 = sys:get_status(ViaName1),
+ ?line {status, Pid5, _Mod, [_PDict5, running, _, _, Data5]} = Status5,
+ ?line [format_status_called | _] = lists:reverse(Data5),
+ ?line stop_it(Pid5),
+ ViaName2 = {via, dummy_via, {name, "term"}},
+ ?line {ok, Pid6} = gen_fsm:start(ViaName2, gen_fsm_SUITE, [], []),
+ ?line Status6 = sys:get_status(ViaName2),
+ ?line {status, Pid6, _Mod, [_PDict6, running, _, _, Data6]} = Status6,
+ ?line [format_status_called | _] = lists:reverse(Data6),
+ ?line stop_it(Pid6).
+
+
error_format_status(Config) when is_list(Config) ->
?line error_logger_forwarder:register(),
@@ -520,6 +557,8 @@ enter_loop(doc) ->
enter_loop(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
+ ?line dummy_via:reset(),
+
%% Locally registered process + {local, Name}
?line {ok, Pid1a} =
proc_lib:start_link(?MODULE, enter_loop, [local, local]),
@@ -623,10 +662,22 @@ enter_loop(Config) when is_list(Config) ->
{'EXIT', Pid6b, process_not_registered_globally} ->
ok
after 1000 ->
- ?line test_server:fail(gen_server_started)
+ ?line test_server:fail(gen_fsm_started)
end,
global:unregister_name(armitage),
+ dummy_via:register_name(armitage, self()),
+ ?line {ok, Pid6c} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon, via]),
+ receive
+ {'EXIT', Pid6c, {process_not_registered_via, dummy_via}} ->
+ ok
+ after 1000 ->
+ ?line test_server:fail({gen_fsm_started, process_info(self(),
+ messages)})
+ end,
+ dummy_via:unregister_name(armitage),
+
process_flag(trap_exit, OldFlag),
ok.
@@ -635,6 +686,7 @@ enter_loop(Reg1, Reg2) ->
case Reg1 of
local -> register(armitage, self());
global -> global:register_name(armitage, self());
+ via -> dummy_via:register_name(armitage, self());
anon -> ignore
end,
proc_lib:init_ack({ok, self()}),
@@ -643,6 +695,9 @@ enter_loop(Reg1, Reg2) ->
gen_fsm:enter_loop(?MODULE, [], state0, [], {local,armitage});
global ->
gen_fsm:enter_loop(?MODULE, [], state0, [], {global,armitage});
+ via ->
+ gen_fsm:enter_loop(?MODULE, [], state0, [],
+ {via, dummy_via, armitage});
anon ->
gen_fsm:enter_loop(?MODULE, [], state0, [])
end.
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index a614d6595d..48ef7e55ed 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -36,8 +36,9 @@
]).
% spawn export
--export([spec_init_local/2, spec_init_global/2,
- spec_init_default_timeout/2, spec_init_anonymous/1,
+-export([spec_init_local/2, spec_init_global/2, spec_init_via/2,
+ spec_init_default_timeout/2, spec_init_global_default_timeout/2,
+ spec_init_anonymous/1,
spec_init_anonymous_default_timeout/1,
spec_init_not_proc_lib/1, cast_fast_messup/0]).
@@ -199,6 +200,35 @@ start(Config) when is_list(Config) ->
test_server:fail(not_stopped)
end,
+ %% via register
+ ?line dummy_via:reset(),
+ ?line {ok, Pid6} =
+ gen_server:start({via, dummy_via, my_test_name},
+ gen_server_SUITE, [], []),
+ ?line ok = gen_server:call({via, dummy_via, my_test_name}, started_p),
+ ?line {error, {already_started, Pid6}} =
+ gen_server:start({via, dummy_via, my_test_name},
+ gen_server_SUITE, [], []),
+ ?line ok = gen_server:call({via, dummy_via, my_test_name}, stop),
+ test_server:sleep(1),
+ ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid6, started_p, 10)),
+
+ %% via register linked
+ ?line dummy_via:reset(),
+ ?line {ok, Pid7} =
+ gen_server:start_link({via, dummy_via, my_test_name},
+ gen_server_SUITE, [], []),
+ ?line ok = gen_server:call({via, dummy_via, my_test_name}, started_p),
+ ?line {error, {already_started, Pid7}} =
+ gen_server:start({via, dummy_via, my_test_name},
+ gen_server_SUITE, [], []),
+ ?line ok = gen_server:call({via, dummy_via, my_test_name}, stop),
+ ?line receive
+ {'EXIT', Pid7, stopped} ->
+ ok
+ after 5000 ->
+ test_server:fail(not_stopped)
+ end,
test_server:messages_get(),
%% Must wait for all error messages before going to next test.
@@ -694,7 +724,7 @@ multicall_down(Config) when is_list(Config) ->
%% We use 'global' as a gen_server to call.
?line {Good, Bad} = gen_server:multi_call([Name, node()],
global_name_server,
- {whereis, gurkburk},
+ info,
3000),
io:format("good = ~p, bad = ~p~n", [Good, Bad]),
?line [Name] = Bad,
@@ -720,7 +750,7 @@ spec_init(suite) ->
spec_init(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
-
+
?line {ok, Pid0} = start_link(spec_init_local, [{ok, my_server}, []]),
?line ok = gen_server:call(Pid0, started_p),
?line ok = gen_server:call(Pid0, stop),
@@ -790,6 +820,14 @@ spec_init(Config) when is_list(Config) ->
test_server:fail(gen_server_did_not_die)
end,
+ %% Before the OTP-10130 fix this failed because a timeout message
+ %% was generated as the spawned process crashed because a {global, Name}
+ %% was matched as a timeout value instead of matching on scope.
+ {ok, _PidHurra} =
+ start_link(spec_init_global_default_timeout, [{ok, hurra}, []]),
+ timer:sleep(1000),
+ ok = gen_server:call(_PidHurra, started_p),
+
?line Pid5 =
erlang:spawn_link(?MODULE, spec_init_not_proc_lib, [[]]),
receive
@@ -853,6 +891,8 @@ otp_5854(doc) ->
otp_5854(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
+ ?line dummy_via:reset(),
+
%% Make sure gen_server:enter_loop does not accept {local,Name}
%% when it's another process than the calling one which is
%% registered under that name
@@ -881,6 +921,18 @@ otp_5854(Config) when is_list(Config) ->
end,
global:unregister_name(armitage),
+ %% (same for {via, Mod, Name})
+ dummy_via:register_name(armitage, self()),
+ ?line {ok, Pid3} =
+ start_link(spec_init_via, [{not_ok, armitage}, []]),
+ receive
+ {'EXIT', Pid3, {process_not_registered_via, dummy_via}} ->
+ ok
+ after 1000 ->
+ ?line test_server:fail(gen_server_started)
+ end,
+ dummy_via:unregister_name(armitage),
+
process_flag(trap_exit, OldFlag),
ok.
@@ -1060,13 +1112,37 @@ spec_init_global({not_ok, Name}, Options) ->
%% Supervised init can occur here ...
gen_server:enter_loop(?MODULE, Options, {}, {global, Name}, infinity).
-spec_init_default_timeout({ok, Name}, Options) ->
+spec_init_via({ok, Name}, Options) ->
+ process_flag(trap_exit, true),
+ dummy_via:register_name(Name, self()),
+ proc_lib:init_ack({ok, self()}),
+ %% Supervised init can occur here ...
+ gen_server:enter_loop(?MODULE, Options, {},
+ {via, dummy_via, Name}, infinity);
+
+spec_init_via({not_ok, Name}, Options) ->
+ process_flag(trap_exit, true),
+ proc_lib:init_ack({ok, self()}),
+ %% Supervised init can occur here ...
+ gen_server:enter_loop(?MODULE, Options, {},
+ {via, dummy_via, Name}, infinity).
+
+spec_init_default_timeout({ok, Name}, Options) ->
process_flag(trap_exit, true),
register(Name, self()),
proc_lib:init_ack({ok, self()}),
%% Supervised init can occur here ...
gen_server:enter_loop(?MODULE, Options, {}, {local, Name}).
+%% OTP-10130, A bug was introduced where global scope was not matched when
+%% enter_loop/4 was called (no timeout).
+spec_init_global_default_timeout({ok, Name}, Options) ->
+ process_flag(trap_exit, true),
+ global:register_name(Name, self()),
+ proc_lib:init_ack({ok, self()}),
+ %% Supervised init can occur here ...
+ gen_server:enter_loop(?MODULE, Options, {}, {global, Name}).
+
spec_init_anonymous(Options) ->
process_flag(trap_exit, true),
proc_lib:init_ack({ok, self()}),
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index b69cd74edb..661d57c85b 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,7 @@
-define(privdir(Conf), ?config(priv_dir, Conf)).
-endif.
--define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -137,7 +137,7 @@ unicode_prompt(Config) when is_list(Config) ->
{putline, "io:get_line('')."},
{putline, "hej"},
{getline, "<<\"hej\\n\">>"}
- ],[],[],"-pa "++ PA),
+ ],[],[],"-pa \""++ PA++"\""),
%% And one with oldshell
?line rtnode([{putline,""},
{putline, "2."},
@@ -153,7 +153,7 @@ unicode_prompt(Config) when is_list(Config) ->
{putline, "io:get_line('')."},
{putline, "hej"},
{getline_re, ".*<<\"hej\\\\n\">>"}
- ],[],[],"-oldshell -pa "++PA),
+ ],[],[],"-oldshell -pa \""++PA++"\""),
ok.
@@ -732,7 +732,7 @@ bc_with_r12_1(Config) ->
PA = filename:dirname(code:which(?MODULE)),
Name1 = io_proto_r12_1,
?line N1 = list_to_atom(atom_to_list(Name1) ++ "@" ++ hostname()),
- ?line ?t:start_node(Name1, peer, [{args, "-pz "++PA},{erl,[{release,"r12b"}]}]),
+ ?line ?t:start_node(Name1, peer, [{args, "-pz \""++PA++"\""},{erl,[{release,"r12b"}]}]),
DataDir = ?config(data_dir,Config),
%PrivDir = ?config(priv_dir,Config),
FileName1 = filename:join([DataDir,"testdata_latin1.dat"]),
@@ -908,7 +908,7 @@ bc_with_r12_gl_1(_Config,Machine) ->
PA = filename:dirname(code:which(?MODULE)),
Name1 = io_proto_r12_gl_1,
?line N1 = list_to_atom(atom_to_list(Name1) ++ "@" ++ hostname()),
- ?line ?t:start_node(Name1, peer, [{args, "-pz "++PA},{erl,[{release,"r12b"}]}]),
+ ?line ?t:start_node(Name1, peer, [{args, "-pz \""++PA++"\""},{erl,[{release,"r12b"}]}]),
TestDataLine1 = [229,228,246],
TestDataLine1BinUtf = unicode:characters_to_binary(TestDataLine1),
TestDataLine1BinLatin = list_to_binary(TestDataLine1),
@@ -1290,7 +1290,7 @@ eof_on_pipe(Config) when is_list(Config) ->
end
end,
CommandLine1 = EchoLine ++
- Erl++" -noshell -eval "
+ "\""++Erl++"\" -noshell -eval "
"'io:format(\"~p\",[io:get_line(\"\")]),"
"io:format(\"~p\",[io:get_line(\"\")]),"
"io:format(\"~p\",[io:get_line(\"\")]).' -run init stop",
@@ -1301,7 +1301,7 @@ eof_on_pipe(Config) when is_list(Config) ->
exit({unexpected1,Other1})
end,
CommandLine2 = EchoLine ++
- Erl++" -noshell -eval "
+ "\""++Erl++"\" -noshell -eval "
"'io:setopts([binary]),io:format(\"~p\",[io:get_line(\"\")]),"
"io:format(\"~p\",[io:get_line(\"\")]),"
"io:format(\"~p\",[io:get_line(\"\")]).' -run init stop",
@@ -1340,7 +1340,8 @@ rtnode(Commands,Nodename,ErlPrefix,Extra) ->
?line {skip, Reason2};
Tempdir ->
?line SPid =
- start_runerl_node(RunErl,ErlPrefix++Erl,
+ start_runerl_node(RunErl,ErlPrefix++
+ "\\\""++Erl++"\\\"",
Tempdir,Nodename, Extra),
?line CPid = start_toerl_server(ToErl,Tempdir),
?line erase(getline_skipped),
@@ -1607,10 +1608,10 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename,Extra) ->
" "++Extra
end,
spawn(fun() ->
- ?dbg(RunErl++" "++Tempdir++"/ "++Tempdir++" \""++
- Erl++XArg++XXArg++"\""),
- os:cmd(RunErl++" "++Tempdir++"/ "++Tempdir++" \""++
- Erl++XArg++XXArg++"\"")
+ ?dbg("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++
+ " \""++Erl++XArg++XXArg++"\""),
+ os:cmd("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++
+ " \""++Erl++XArg++XXArg++"\"")
end).
start_toerl_server(ToErl,Tempdir) ->
@@ -1640,7 +1641,7 @@ try_to_erl(Command, N) ->
end.
toerl_server(Parent,ToErl,Tempdir) ->
- Port = try_to_erl(ToErl++" "++Tempdir++"/ 2>/dev/null",8),
+ Port = try_to_erl("\""++ToErl++"\" "++Tempdir++"/ 2>/dev/null",8),
case Port of
P when is_port(P) ->
Parent ! {self(),started};
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index 4e5df12798..a17307b07b 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -39,6 +39,7 @@
-export([float_1_function/1]).
-export([action_function/1]).
-export([warnings/1]).
+-export([no_warnings/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
init_per_testcase(_Func, Config) ->
@@ -55,7 +56,7 @@ all() ->
[from_shell, basic_ets, basic_dbg, records,
record_index, multipass, bitsyntax, record_defaults,
andalso_orelse, float_1_function, action_function,
- warnings, top_match, old_guards, autoimported,
+ warnings, no_warnings, top_match, old_guards, autoimported,
semicolon].
groups() ->
@@ -155,6 +156,34 @@ warnings(Config) when is_list(Config) ->
compile_ww(Prog7),
ok.
+no_warnings(suite) ->
+ [];
+no_warnings(doc) ->
+ ["Check that variables bound in other function clauses don't generate "
+ "warning"];
+no_warnings(Config) when is_list(Config) ->
+ ?line setup(Config),
+ Prog = <<"tmp(X) when X > 100 ->\n",
+ " Y=X,\n"
+ " Y;\n"
+ "tmp(X) ->\n"
+ " ets:fun2ms(fun(Y) ->\n"
+ " {X, 3*Y}\n"
+ " end)">>,
+ ?line [] = compile_no_ww(Prog),
+
+ Prog2 = <<"tmp(X) when X > 100 ->\n",
+ " Y=X,\n"
+ " Y;\n"
+ "tmp(X) when X < 200 ->\n"
+ " ok;\n"
+ "tmp(X) ->\n"
+ " ets:fun2ms(fun(Y) ->\n"
+ " {X, 3*Y}\n"
+ " end)">>,
+ ?line [] = compile_no_ww(Prog2),
+ ok.
+
andalso_orelse(suite) ->
[];
andalso_orelse(doc) ->
@@ -426,7 +455,6 @@ old_guards(Config) when is_list(Config) ->
?line setup(Config),
Tests = [
{atom,is_atom},
- {constant,is_constant},
{float,is_float},
{integer,is_integer},
{list,is_list},
@@ -461,7 +489,6 @@ old_guards(Config) when is_list(Config) ->
?line [{'$1',[{is_integer,'$1'},
{is_float,'$1'},
{is_atom,'$1'},
- {is_constant,'$1'},
{is_list,'$1'},
{is_number,'$1'},
{is_pid,'$1'},
@@ -473,7 +500,7 @@ old_guards(Config) when is_list(Config) ->
[true]}] =
compile_and_run(RD, <<
"ets:fun2ms(fun(X) when integer(X),"
- "float(X), atom(X), constant(X),"
+ "float(X), atom(X),"
"list(X), number(X), pid(X),"
"port(X), reference(X), tuple(X),"
"binary(X), record(X,a) -> true end)"
@@ -501,7 +528,6 @@ autoimported(Config) when is_list(Config) ->
{self,0},
%{float,1}, see float_1_function/1
{is_atom,1},
- {is_constant,1},
{is_float,1},
{is_integer,1},
{is_list,1},
@@ -842,6 +868,20 @@ compile_ww(Records,Expr) ->
nowarn_unused_record]),
Wlist.
+compile_no_ww(Expr) ->
+ Prog = <<
+ "-module(tmp).\n",
+ "-include_lib(\"stdlib/include/ms_transform.hrl\").\n",
+ "-export([tmp/1]).\n\n",
+ Expr/binary,".\n">>,
+ FN=temp_name(),
+ file:write_file(FN,Prog),
+ {ok,Forms} = epp:parse_file(FN,"",""),
+ {ok,tmp,_Bin,Wlist} = compile:forms(Forms,[return_warnings,
+ nowarn_unused_vars,
+ nowarn_unused_record]),
+ Wlist.
+
do_eval(String) ->
{done,{ok,T,_},[]} = erl_scan:tokens(
[],
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 98eeaee118..192268f90e 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,6 @@
%%% Purpose:Test Suite for the 'qlc' module.
%%%-----------------------------------------------------------------
-module(qlc_SUITE).
--compile(r12).
-define(QLC, qlc).
-define(QLCs, "qlc").
@@ -2970,12 +2969,14 @@ lookup1(Config) when is_list(Config) ->
[3] = lookup_keys(Q)
end, [{1,a},{3,3}])">>,
+ {cres,
<<"A = 3,
etsc(fun(E) ->
Q = qlc:q([X || X <- ets:table(E), A =:= {erlang,element}(1, X)]),
[{3,3}] = qlc:e(Q),
[3] = lookup_keys(Q)
end, [{1,a},{3,3}])">>,
+ {warnings,[{3,erl_lint,deprecated_tuple_fun}]}},
<<"etsc(fun(E) ->
A = 3,
@@ -3440,12 +3441,14 @@ lookup2(Config) when is_list(Config) ->
[r] = qlc:e(Q),
[r] = lookup_keys(Q)
end, [{keypos,1}], [#r{}])">>,
+ {cres,
<<"etsc(fun(E) ->
Q = qlc:q([element(1, X) || X <- ets:table(E),
{erlang,is_record}(X, r, 2)]),
[r] = qlc:e(Q),
[r] = lookup_keys(Q)
end, [{keypos,1}], [#r{}])">>,
+ {warnings,[{4,erl_lint,deprecated_tuple_fun}]}},
{cres,
<<"etsc(fun(E) ->
Q = qlc:q([element(1, X) || X <- ets:table(E),
@@ -3466,12 +3469,14 @@ lookup2(Config) when is_list(Config) ->
[r] = qlc:e(Q),
[r] = lookup_keys(Q)
end, [{keypos,1}], [#r{}])">>,
+ {cres,
<<"etsc(fun(E) ->
Q = qlc:q([element(1, X) || X <- ets:table(E),
{erlang,is_record}(X, r)]),
[r] = qlc:e(Q),
[r] = lookup_keys(Q)
- end, [{keypos,1}], [#r{}])">>
+ end, [{keypos,1}], [#r{}])">>,
+ {warnings,[{4,erl_lint,deprecated_tuple_fun}]}}
],
?line run(Config, <<"-record(r, {a}).\n">>, TsR),
@@ -6118,6 +6123,7 @@ otp_6964(Config) when is_list(Config) ->
qlc:e(Q, [{max_list_size,64*1024},{tmpdir_usage,Use}])
end,
D = erlang:system_flag(backtrace_depth, 0),
+ try
20000 = length(F(allowed)),
ErrReply = F(not_allowed),
{error, qlc, {tmpdir_usage,joining}} = ErrReply,
@@ -6129,8 +6135,10 @@ otp_6964(Config) when is_list(Config) ->
20000 = length(F(info_msg)),
{info, joining} = qlc_SUITE:read_error_logger(),
20000 = length(F(error_msg)),
- {error, joining} = qlc_SUITE:read_error_logger(),
- _ = erlang:system_flag(backtrace_depth, D),
+ {error, joining} = qlc_SUITE:read_error_logger()
+ after
+ _ = erlang:system_flag(backtrace_depth, D)
+ end,
qlc_SUITE:uninstall_error_logger()">>],
?line run(Config, T1),
@@ -6632,7 +6640,7 @@ otp_7232(Config) when is_list(Config) ->
{call,_,
{remote,_,{atom,_,qlc},{atom,_,sort}},
[{cons,_,
- {'fun',_,{function,math,sqrt,_}},
+ {'fun',_,{function,{atom,_,math},{atom,_,sqrt},_}},
{cons,_,
{string,_,\"<0.4.1>\"}, % could use list_to_pid..
{cons,_,{string,_,\"#Ref<\"++_},{nil,_}}}},
@@ -7399,70 +7407,37 @@ backward(doc) ->
"OTP-6674. Join info and extra constants.";
backward(suite) -> [];
backward(Config) when is_list(Config) ->
- case try_old_join_info(Config) of
- ok ->
- ok;
- Reply ->
- Reply
- end.
-
--ifdef(debug).
-try_old_join_info(_Config) ->
+ try_old_join_info(Config),
ok.
--else.
+
try_old_join_info(Config) ->
- case ?t:is_release_available("r12b") of
- true ->
- %% Check join info for handlers of extra constants. Start R12B-0.
- ?line {ok, R12} = start_node_rel(r12, r12b, slave),
- File = filename("handle.erl", Config),
- ?line file:write_file(File,
- <<"-module(handle).\n"
- "-export([create_handle/0, lookup_handle/0]).\n"
- "-include_lib(\"stdlib/include/qlc.hrl\").\n"
- "create_handle() ->\n"
- " H1 = qlc:sort([{192.0,1,a},{192.0,2,b},{192.0,3,c}]),\n"
- " qlc:q([{X, Y} || {B,X,_} <- H1,\n"
- " B =:= 192.0,\n"
- " {Y} <- [{0},{1},{2}],\n"
- " X == Y]).\n",
- "\n",
- "lookup_handle() ->\n"
- " E = qlc_SUITE:table([{1,a},{2,b},{3,c}], 1, [1]),\n"
- " qlc:q([{X, Y} || {X,_} <- E,\n"
- " {Y} <- [{0},{1},{2}],\n"
- " X =:= Y]).\n">>),
- ?line {ok, handle} = rpc:call(R12, compile, file,
- [File, [{outdir,?privdir}]]),
- ?line {module, handle} = rpc:call(R12, code, load_abs,
- [filename:rootname(File)]),
- ?line H = rpc:call(R12, handle, create_handle, []),
- ?line {module, handle} = code:load_abs(filename:rootname(File)),
- ?line {block,0,
- [{match,_,_,
- {call,_,_,
- [{lc,_,_,
- [_,
- {op,_,'=:=',
- {float,_,192.0},
- {call,_,{atom,_,element},[{integer,_,1},_]}}]}]}},
- _,_,
- {call,_,_,
- [{lc,_,_,
- [_,
- {op,_,'=:=',{var,_,'B'},{float,_,192.0}},
- {op,_,'==',{var,_,'X'},{var,_,'Y'}}]}]}]}
- = qlc:info(H,{format,abstract_code}),
- ?line [{1,1},{2,2}] = qlc:e(H),
- ?line H2 = rpc:call(R12, handle, lookup_handle, []),
- ?line {qlc,_,[{generate,_,{qlc,_,_,[{join,lookup}]}},_],[]} =
- qlc:info(H2, {format,debug}),
- ?line [{1,1},{2,2}] = qlc:e(H2),
- stop_node(R12);
- false ->
- ?line {skipped, "No support for old node"}
- end.
--endif.
+ %% Check join info for handlers of extra constants.
+ File = filename:join(?datadir, "join_info_compat.erl"),
+ M = join_info_compat,
+ {ok, M} = compile:file(File, [{outdir, ?datadir}]),
+ {module, M} = code:load_abs(filename:rootname(File)),
+ H = M:create_handle(),
+ {block,0,
+ [{match,_,_,
+ {call,_,_,
+ [{lc,_,_,
+ [_,
+ {op,_,'=:=',
+ {float,_,192.0},
+ {call,_,{atom,_,element},[{integer,_,1},_]}}]}]}},
+ _,_,
+ {call,_,_,
+ [{lc,_,_,
+ [_,
+ {op,_,'=:=',{var,_,'B'},{float,_,192.0}},
+ {op,_,'==',{var,_,'X'},{var,_,'Y'}}]}]}]}
+ = qlc:info(H,{format,abstract_code}),
+ [{1,1},{2,2}] = qlc:e(H),
+
+ H2 = M:lookup_handle(),
+ {qlc,_,[{generate,_,{qlc,_,_,[{join,lookup}]}},_],[]} =
+ qlc:info(H2, {format,debug}),
+ [{1,1},{2,2}] = qlc:e(H2).
forward(doc) ->
"";
@@ -7958,15 +7933,23 @@ run_test(Config, Extra, {cres, Body, Opts, ExpectedCompileReturn}) ->
ok
end,
+ wait_for_expected(R, Before, SourceFile, true),
+ code:purge(Mod);
+run_test(Config, Extra, Body) ->
+ run_test(Config, Extra, {cres,Body,[]}).
+
+wait_for_expected(R, Before, SourceFile, Wait) ->
Ms = erlang:process_info(self(),messages),
After = {get(), pps(), ets:all(), Ms},
- code:purge(Mod),
case {R, After} of
- {ok, Before} -> ok;
- _ -> expected({ok,Before}, {R,After}, SourceFile)
- end;
-run_test(Config, Extra, Body) ->
- run_test(Config, Extra, {cres,Body,[]}).
+ {ok, Before} ->
+ ok;
+ _ when Wait ->
+ timer:sleep(1000),
+ wait_for_expected(R, Before, SourceFile, false);
+ _ ->
+ expected({ok,Before}, {R,After}, SourceFile)
+ end.
unload_pt() ->
erlang:garbage_collect(), % get rid of references to qlc_pt...
@@ -8127,27 +8110,6 @@ fail(Source) ->
%% Copied from global_SUITE.erl.
-start_node_rel(Name, Rel, How) ->
- {Release, Compat} = case Rel of
- this ->
- {[this], "+R8"};
- Rel when is_atom(Rel) ->
- {[{release, atom_to_list(Rel)}], ""};
- RelList ->
- {RelList, ""}
- end,
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line Res = test_server:start_node(Name, How,
- [{args,
- Compat ++
- " -kernel net_setuptime 100 "
- " -pa " ++ Pa},
- {erl, Release}]),
- Res.
-
-stop_node(Node) ->
- ?line ?t:stop_node(Node).
-
install_error_logger() ->
error_logger:add_report_handler(?MODULE, self()).
diff --git a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl
new file mode 100644
index 0000000000..e0db132c47
--- /dev/null
+++ b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl
@@ -0,0 +1,1771 @@
+%%
+%% %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(join_info_compat).
+
+-compile(export_all).
+
+create_handle() ->
+ H1 = qlc:sort([{192.0,1,a},{192.0,2,b},{192.0,3,c}]),
+ qlc:q({qlc_lc,
+ % fun-info: {23,109048965,'-create_handle/0-fun-23-'}
+ fun() ->
+ {qlc_v1,
+ % fun-info: {2,105724313,'-create_handle/0-fun-2-'}
+ fun(S01_0_1, RL01_0_1, Go01_0_1) ->
+ Fun1_0_1 =
+ % fun-info: {1,131900588,'-create_handle/0-fun-1-'}
+ fun(0, RL1_0_1, _, _, _, _, _, _, _)
+ when is_list(RL1_0_1) ->
+ lists:reverse(RL1_0_1);
+ (0, _, _, _, _, _, _, _, _) ->
+ [];
+ (1,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1)
+ when is_list(RL1_0_1) ->
+ Fun1_0_1(element(1, Go1_0_1),
+ [{X1,Y1}|RL1_0_1],
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1);
+ (1,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1) ->
+ [{X1,Y1}|
+ % fun-info: {0,27702789,'-create_handle/0-fun-0-'}
+ fun() ->
+ Fun1_0_1(element(1,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1)
+ end];
+ (2,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ _,
+ B1,
+ X1) ->
+ Fun1_0_1(3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ element(4, Go1_0_1),
+ B1,
+ X1);
+ (3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ [{B1,X1,_}|C1_0_1],
+ _,
+ _) ->
+ Fun1_0_1(element(3, Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_0_1,
+ B1,
+ X1);
+ (3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ [_|C1_0_1],
+ _,
+ _) ->
+ Fun1_0_1(3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_0_1,
+ [],
+ []);
+ (3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ [],
+ _,
+ _) ->
+ Fun1_0_1(element(2, Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ [],
+ [],
+ []);
+ (3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ _,
+ _) ->
+ case C1_1_1() of
+ [{B1,X1,_}|C1_0_1] ->
+ Fun1_0_1(element(3,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_0_1,
+ B1,
+ X1);
+ [_|C1_0_1] ->
+ Fun1_0_1(3,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_0_1,
+ [],
+ []);
+ [] ->
+ Fun1_0_1(element(2,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ [],
+ [],
+ []);
+ E1_0_1 ->
+ E1_0_1
+ end;
+ (4,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1) ->
+ if
+ B1 =:= 192.0 ->
+ Fun1_0_1(element(6,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1);
+ true ->
+ Fun1_0_1(element(5,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1)
+ end;
+ (5,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ _,
+ Y1,
+ C1_1_1,
+ B1,
+ X1) ->
+ Fun1_0_1(6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ element(9, Go1_0_1),
+ Y1,
+ C1_1_1,
+ B1,
+ X1);
+ (6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ [{Y1}|C1_0_1],
+ _,
+ C1_1_1,
+ B1,
+ X1) ->
+ Fun1_0_1(element(8, Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_0_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1);
+ (6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ [_|C1_0_1],
+ _,
+ C1_1_1,
+ B1,
+ X1) ->
+ Fun1_0_1(6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_0_1,
+ [],
+ C1_1_1,
+ B1,
+ X1);
+ (6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ [],
+ _,
+ C1_1_1,
+ B1,
+ X1) ->
+ Fun1_0_1(element(7, Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ [],
+ [],
+ C1_1_1,
+ B1,
+ X1);
+ (6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ _,
+ C1_1_1,
+ B1,
+ X1) ->
+ case C1_3_1() of
+ [{Y1}|C1_0_1] ->
+ Fun1_0_1(element(8,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_0_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1);
+ [_|C1_0_1] ->
+ Fun1_0_1(6,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_0_1,
+ [],
+ C1_1_1,
+ B1,
+ X1);
+ [] ->
+ Fun1_0_1(element(7,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ [],
+ [],
+ C1_1_1,
+ B1,
+ X1);
+ E1_0_1 ->
+ E1_0_1
+ end;
+ (7,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1) ->
+ if
+ X1 == Y1 ->
+ Fun1_0_1(element(11,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1);
+ true ->
+ Fun1_0_1(element(10,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_1_1,
+ B1,
+ X1)
+ end;
+ (8,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ _,
+ B1,
+ X1) ->
+ Fun1_0_1(9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ element(14, Go1_0_1),
+ B1,
+ X1);
+ (9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ _,
+ [[{B1,X1,_}|{Y1}]|C1_0_1],
+ _,
+ _) ->
+ Fun1_0_1(element(13, Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_0_1,
+ B1,
+ X1);
+ (9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ _,
+ [_|C1_0_1],
+ _,
+ _) ->
+ Fun1_0_1(9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ [],
+ C1_0_1,
+ [],
+ []);
+ (9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ _,
+ [],
+ _,
+ _) ->
+ Fun1_0_1(element(12, Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ [],
+ [],
+ [],
+ []);
+ (9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ _,
+ C1_1_1,
+ _,
+ _) ->
+ case C1_1_1() of
+ [[{B1,X1,_}|{Y1}]|C1_0_1] ->
+ Fun1_0_1(element(13,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ Y1,
+ C1_0_1,
+ B1,
+ X1);
+ [_|C1_0_1] ->
+ Fun1_0_1(9,
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ [],
+ C1_0_1,
+ [],
+ []);
+ [] ->
+ Fun1_0_1(element(12,
+ Go1_0_1),
+ RL1_0_1,
+ Fun1_0_1,
+ Go1_0_1,
+ C1_3_1,
+ [],
+ [],
+ [],
+ []);
+ E1_0_1 ->
+ E1_0_1
+ end
+ end,
+ Fun1_0_1(S01_0_1,
+ RL01_0_1,
+ Fun1_0_1,
+ Go01_0_1,
+ [],
+ [],
+ [],
+ [],
+ [])
+ end,
+ % fun-info: {3,41816426,'-create_handle/0-fun-3-'}
+ fun() ->
+ {<<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $.:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $):8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $\026:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $r:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $F:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $":8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $<:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $):8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $\026:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $r:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $::8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $":8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $Y:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $9:8/integer-unit:1-unsigned-big,
+ $\r:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $H:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $e:8/integer-unit:1-unsigned-big,
+ $\211:8/integer-unit:1-unsigned-big,
+ $E:8/integer-unit:1-unsigned-big,
+ $\s:8/integer-unit:1-unsigned-big,
+ $>:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\023:8/integer-unit:1-unsigned-big,
+ $\210:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\232:8/integer-unit:1-unsigned-big,
+ $\226:8/integer-unit:1-unsigned-big,
+ $\223:8/integer-unit:1-unsigned-big,
+ $\237:8/integer-unit:1-unsigned-big,
+ $X:8/integer-unit:1-unsigned-big,
+ $\222:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\235:8/integer-unit:1-unsigned-big,
+ $l:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $g:8/integer-unit:1-unsigned-big,
+ $i:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\200:8/integer-unit:1-unsigned-big,
+ $\001:8/integer-unit:1-unsigned-big,
+ $R:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\r:8/integer-unit:1-unsigned-big,
+ $\214:8/integer-unit:1-unsigned-big,
+ $\030:8/integer-unit:1-unsigned-big,
+ $@:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $c:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\017:8/integer-unit:1-unsigned-big,
+ $=:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $h:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\005:8/integer-unit:1-unsigned-big,
+ $t:8/integer-unit:1-unsigned-big,
+ $u:8/integer-unit:1-unsigned-big,
+ $p:8/integer-unit:1-unsigned-big,
+ $l:8/integer-unit:1-unsigned-big,
+ $e:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $\f:8/integer-unit:1-unsigned-big,
+ $l:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\001:8/integer-unit:1-unsigned-big,
+ $h:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $v:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $r:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $\f:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\001:8/integer-unit:1-unsigned-big,
+ $Y:8/integer-unit:1-unsigned-big,
+ $j:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $*:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $H:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\005:8/integer-unit:1-unsigned-big,
+ $R:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\031:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $):8/integer-unit:1-unsigned-big,
+ $\f:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $e:8/integer-unit:1-unsigned-big,
+ $\211:8/integer-unit:1-unsigned-big,
+ $E:8/integer-unit:1-unsigned-big,
+ $\s:8/integer-unit:1-unsigned-big,
+ $.:8/integer-unit:1-unsigned-big,
+ $c:8/integer-unit:1-unsigned-big,
+ $\004:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $\022:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\205:8/integer-unit:1-unsigned-big,
+ $\t:8/integer-unit:1-unsigned-big,
+ $\216:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $j:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $+:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\f:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\024:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\222:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\202:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $D:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\034:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $f:8/integer-unit:1-unsigned-big,
+ $\220:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $s:8/integer-unit:1-unsigned-big,
+ $Y:8/integer-unit:1-unsigned-big,
+ $b:8/integer-unit:1-unsigned-big,
+ $Q:8/integer-unit:1-unsigned-big,
+ $":8/integer-unit:1-unsigned-big,
+ $W:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\023:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $\002:8/integer-unit:1-unsigned-big,
+ $\205:8/integer-unit:1-unsigned-big,
+ $\027:8/integer-unit:1-unsigned-big,
+ $\237:8/integer-unit:1-unsigned-big,
+ $\205:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $\007:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $\021:8/integer-unit:1-unsigned-big,
+ $.:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $\224:8/integer-unit:1-unsigned-big,
+ $\217:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\002:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\203:8/integer-unit:1-unsigned-big,
+ $>:8/integer-unit:1-unsigned-big,
+ $\034:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big>>}
+ end,
+ [{1,
+ 2,
+ 2,
+ {gen,
+ % fun-info: {4,131674517,'-create_handle/0-fun-4-'}
+ fun() ->
+ H1
+ end}},
+ {2,5,4,fil},
+ {3,
+ 7,
+ 5,
+ {gen,
+ % fun-info: {5,108000324,'-create_handle/0-fun-5-'}
+ fun() ->
+ [{0},{1},{2}]
+ end}},
+ {4,10,7,fil},
+ {5,
+ 12,
+ 8,
+ {gen,
+ {join,
+ '==',
+ 1,
+ 3,
+ % fun-info: {9,59718458,'-create_handle/0-fun-9-'}
+ fun(H1_0_1) ->
+ F1_0_1 =
+ % fun-info: {7,779460,'-create_handle/0-fun-7-'}
+ fun(_, []) ->
+ [];
+ (F1_0_1, [O1_0_1|C1_0_1]) ->
+ case O1_0_1 of
+ {_,_,_}
+ when
+ 192.0
+ =:=
+ element(1, O1_0_1) ->
+ [O1_0_1|
+ % fun-info: {6,23729943,'-create_handle/0-fun-6-'}
+ fun() ->
+ F1_0_1(F1_0_1,
+ C1_0_1)
+ end];
+ _ ->
+ F1_0_1(F1_0_1, C1_0_1)
+ end;
+ (F1_0_1, C1_0_1)
+ when is_function(C1_0_1) ->
+ F1_0_1(F1_0_1, C1_0_1());
+ (_, C1_0_1) ->
+ C1_0_1
+ end,
+ % fun-info: {8,43652904,'-create_handle/0-fun-8-'}
+ fun() ->
+ F1_0_1(F1_0_1, H1_0_1)
+ end
+ end,
+ % fun-info: {13,102310144,'-create_handle/0-fun-13-'}
+ fun(H1_0_1) ->
+ F1_0_1 =
+ % fun-info: {11,74362432,'-create_handle/0-fun-11-'}
+ fun(_, []) ->
+ [];
+ (F1_0_1, [O1_0_1|C1_0_1]) ->
+ case O1_0_1 of
+ {_} ->
+ [O1_0_1|
+ % fun-info: {10,23729943,'-create_handle/0-fun-10-'}
+ fun() ->
+ F1_0_1(F1_0_1,
+ C1_0_1)
+ end];
+ _ ->
+ F1_0_1(F1_0_1, C1_0_1)
+ end;
+ (F1_0_1, C1_0_1)
+ when is_function(C1_0_1) ->
+ F1_0_1(F1_0_1, C1_0_1());
+ (_, C1_0_1) ->
+ C1_0_1
+ end,
+ % fun-info: {12,43652904,'-create_handle/0-fun-12-'}
+ fun() ->
+ F1_0_1(F1_0_1, H1_0_1)
+ end
+ end,
+ % fun-info: {14,17838355,'-create_handle/0-fun-14-'}
+ fun() ->
+ {[{1,[192.0]}],[],[]}
+ end}}}],
+ % fun-info: {22,31304647,'-create_handle/0-fun-22-'}
+ fun(join) ->
+ {[[{1,"\002"},{3,"\001"}]],[]};
+ (size) ->
+ % fun-info: {15,31963143,'-create_handle/0-fun-15-'}
+ fun(0) ->
+ 2;
+ (1) ->
+ 3;
+ (3) ->
+ 1;
+ (_) ->
+ undefined
+ end;
+ (template) ->
+ % fun-info: {16,113413274,'-create_handle/0-fun-16-'}
+ fun({1,2}, '=:=') ->
+ "\001";
+ ({1,2}, '==') ->
+ "\001\002";
+ ({3,1}, '=:=') ->
+ "\002";
+ ({3,1}, '==') ->
+ "\001\002";
+ (_, _) ->
+ []
+ end;
+ (constants) ->
+ % fun-info: {18,52148739,'-create_handle/0-fun-18-'}
+ fun(1) ->
+ % fun-info: {17,5864387,'-create_handle/0-fun-17-'}
+ fun(1) ->
+ {values,[192.0],{some,[2]}};
+ (_) ->
+ false
+ end;
+ (_) ->
+ no_column_fun
+ end;
+ (n_leading_constant_columns) ->
+ % fun-info: {19,82183172,'-create_handle/0-fun-19-'}
+ fun(1) ->
+ 1;
+ (_) ->
+ 0
+ end;
+ (constant_columns) ->
+ % fun-info: {20,80910005,'-create_handle/0-fun-20-'}
+ fun(1) ->
+ "\001";
+ (_) ->
+ []
+ end;
+ (match_specs) ->
+ % fun-info: {21,91764346,'-create_handle/0-fun-21-'}
+ fun(1) ->
+ {[{{'$1','$2','_'},
+ [{'=:=','$1',192.0}],
+ ['$_']}],
+ "\002"};
+ (_) ->
+ undefined
+ end;
+ (_) ->
+ undefined
+ end}
+ end,
+ undefined}).
+
+lookup_handle() ->
+ E = qlc_SUITE:table([{1,a},{2,b},{3,c}], 1, [1]),
+ qlc:q({qlc_lc,
+ % fun-info: {46,120768015,'-lookup_handle/0-fun-22-'}
+ fun() ->
+ {qlc_v1,
+ % fun-info: {26,82970908,'-lookup_handle/0-fun-2-'}
+ fun(S02_0_1, RL02_0_1, Go02_0_1) ->
+ Fun2_0_1 =
+ % fun-info: {25,75235357,'-lookup_handle/0-fun-1-'}
+ fun(0, RL2_0_1, _, _, _, _, _, _)
+ when is_list(RL2_0_1) ->
+ lists:reverse(RL2_0_1);
+ (0, _, _, _, _, _, _, _) ->
+ [];
+ (1,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2)
+ when is_list(RL2_0_1) ->
+ Fun2_0_1(element(1, Go2_0_1),
+ [{X2,Y2}|RL2_0_1],
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2);
+ (1,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2) ->
+ [{X2,Y2}|
+ % fun-info: {24,124255471,'-lookup_handle/0-fun-0-'}
+ fun() ->
+ Fun2_0_1(element(1,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2)
+ end];
+ (2,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ _,
+ X2) ->
+ Fun2_0_1(3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ element(4, Go2_0_1),
+ X2);
+ (3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ [{X2,_}|C2_0_1],
+ _) ->
+ Fun2_0_1(element(3, Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_0_1,
+ X2);
+ (3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ [_|C2_0_1],
+ _) ->
+ Fun2_0_1(3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_0_1,
+ []);
+ (3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ [],
+ _) ->
+ Fun2_0_1(element(2, Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ [],
+ []);
+ (3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ _) ->
+ case C2_1_1() of
+ [{X2,_}|C2_0_1] ->
+ Fun2_0_1(element(3,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_0_1,
+ X2);
+ [_|C2_0_1] ->
+ Fun2_0_1(3,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_0_1,
+ []);
+ [] ->
+ Fun2_0_1(element(2,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ [],
+ []);
+ E2_0_1 ->
+ E2_0_1
+ end;
+ (4,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ _,
+ Y2,
+ C2_1_1,
+ X2) ->
+ Fun2_0_1(5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ element(7, Go2_0_1),
+ Y2,
+ C2_1_1,
+ X2);
+ (5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ [{Y2}|C2_0_1],
+ _,
+ C2_1_1,
+ X2) ->
+ Fun2_0_1(element(6, Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_0_1,
+ Y2,
+ C2_1_1,
+ X2);
+ (5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ [_|C2_0_1],
+ _,
+ C2_1_1,
+ X2) ->
+ Fun2_0_1(5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_0_1,
+ [],
+ C2_1_1,
+ X2);
+ (5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ [],
+ _,
+ C2_1_1,
+ X2) ->
+ Fun2_0_1(element(5, Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ [],
+ [],
+ C2_1_1,
+ X2);
+ (5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ _,
+ C2_1_1,
+ X2) ->
+ case C2_2_1() of
+ [{Y2}|C2_0_1] ->
+ Fun2_0_1(element(6,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_0_1,
+ Y2,
+ C2_1_1,
+ X2);
+ [_|C2_0_1] ->
+ Fun2_0_1(5,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_0_1,
+ [],
+ C2_1_1,
+ X2);
+ [] ->
+ Fun2_0_1(element(5,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ [],
+ [],
+ C2_1_1,
+ X2);
+ E2_0_1 ->
+ E2_0_1
+ end;
+ (6,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2) ->
+ if
+ X2 =:= Y2 ->
+ Fun2_0_1(element(9,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2);
+ true ->
+ Fun2_0_1(element(8,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_1_1,
+ X2)
+ end;
+ (7,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ _,
+ X2) ->
+ Fun2_0_1(8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ element(12, Go2_0_1),
+ X2);
+ (8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ _,
+ [[{X2,_}|{Y2}]|C2_0_1],
+ _) ->
+ Fun2_0_1(element(11, Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_0_1,
+ X2);
+ (8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ _,
+ [_|C2_0_1],
+ _) ->
+ Fun2_0_1(8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ [],
+ C2_0_1,
+ []);
+ (8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ _,
+ [],
+ _) ->
+ Fun2_0_1(element(10, Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ [],
+ [],
+ []);
+ (8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ _,
+ C2_1_1,
+ _) ->
+ case C2_1_1() of
+ [[{X2,_}|{Y2}]|C2_0_1] ->
+ Fun2_0_1(element(11,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ Y2,
+ C2_0_1,
+ X2);
+ [_|C2_0_1] ->
+ Fun2_0_1(8,
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ [],
+ C2_0_1,
+ []);
+ [] ->
+ Fun2_0_1(element(10,
+ Go2_0_1),
+ RL2_0_1,
+ Fun2_0_1,
+ Go2_0_1,
+ C2_2_1,
+ [],
+ [],
+ []);
+ E2_0_1 ->
+ E2_0_1
+ end
+ end,
+ Fun2_0_1(S02_0_1,
+ RL02_0_1,
+ Fun2_0_1,
+ Go02_0_1,
+ [],
+ [],
+ [],
+ [])
+ end,
+ % fun-info: {27,111349661,'-lookup_handle/0-fun-3-'}
+ fun() ->
+ {<<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $.:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $):8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $\024:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $\026:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $F:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $":8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\206:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $.:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $):8/integer-unit:1-unsigned-big,
+ $-:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $\024:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $\026:8/integer-unit:1-unsigned-big,
+ $%:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $0:8/integer-unit:1-unsigned-big,
+ $F:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\222:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $h:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\005:8/integer-unit:1-unsigned-big,
+ $t:8/integer-unit:1-unsigned-big,
+ $u:8/integer-unit:1-unsigned-big,
+ $p:8/integer-unit:1-unsigned-big,
+ $l:8/integer-unit:1-unsigned-big,
+ $e:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $\022:8/integer-unit:1-unsigned-big,
+ $l:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\001:8/integer-unit:1-unsigned-big,
+ $h:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $v:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $r:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $\022:8/integer-unit:1-unsigned-big,
+ $d:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\001:8/integer-unit:1-unsigned-big,
+ $Y:8/integer-unit:1-unsigned-big,
+ $j:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $+:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $H:8/integer-unit:1-unsigned-big,
+ $\024:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $e:8/integer-unit:1-unsigned-big,
+ $\211:8/integer-unit:1-unsigned-big,
+ $E:8/integer-unit:1-unsigned-big,
+ $\s:8/integer-unit:1-unsigned-big,
+ $>:8/integer-unit:1-unsigned-big,
+ $c:8/integer-unit:1-unsigned-big,
+ $\004:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $\022:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\227:8/integer-unit:1-unsigned-big,
+ $\t:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big>>,
+ <<$\203:8/integer-unit:1-unsigned-big,
+ $P:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\\:8/integer-unit:1-unsigned-big,
+ $x:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $a:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $+:8/integer-unit:1-unsigned-big,
+ $N:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\f:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\024:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\222:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\202:8/integer-unit:1-unsigned-big,
+ $\234:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $D:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\034:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $\006:8/integer-unit:1-unsigned-big,
+ $&:8/integer-unit:1-unsigned-big,
+ $\220:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $s:8/integer-unit:1-unsigned-big,
+ $Y:8/integer-unit:1-unsigned-big,
+ $b:8/integer-unit:1-unsigned-big,
+ $Q:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $`:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $\003:8/integer-unit:1-unsigned-big,
+ $c:8/integer-unit:1-unsigned-big,
+ $\004:8/integer-unit:1-unsigned-big,
+ $\n:8/integer-unit:1-unsigned-big,
+ $/:8/integer-unit:1-unsigned-big,
+ $>:8/integer-unit:1-unsigned-big,
+ $\v:8/integer-unit:1-unsigned-big,
+ $I:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\020:8/integer-unit:1-unsigned-big,
+ $H:8/integer-unit:1-unsigned-big,
+ $5:8/integer-unit:1-unsigned-big,
+ $#:8/integer-unit:1-unsigned-big,
+ $\\:8/integer-unit:1-unsigned-big,
+ $^:8/integer-unit:1-unsigned-big,
+ $\b:8/integer-unit:1-unsigned-big,
+ $(:8/integer-unit:1-unsigned-big,
+ $\037:8/integer-unit:1-unsigned-big,
+ $\231:8/integer-unit:1-unsigned-big,
+ $\005:8/integer-unit:1-unsigned-big,
+ $\000:8/integer-unit:1-unsigned-big,
+ $\024:8/integer-unit:1-unsigned-big,
+ $�:8/integer-unit:1-unsigned-big,
+ $\031:8/integer-unit:1-unsigned-big,
+ $M:8/integer-unit:1-unsigned-big>>}
+ end,
+ [{1,
+ 2,
+ 2,
+ {gen,
+ % fun-info: {28,75197307,'-lookup_handle/0-fun-4-'}
+ fun() ->
+ E
+ end}},
+ {2,
+ 5,
+ 4,
+ {gen,
+ % fun-info: {29,86826511,'-lookup_handle/0-fun-5-'}
+ fun() ->
+ [{0},{1},{2}]
+ end}},
+ {3,8,6,fil},
+ {4,
+ 10,
+ 7,
+ {gen,
+ {join,
+ '==',
+ 1,
+ 2,
+ % fun-info: {33,129609919,'-lookup_handle/0-fun-9-'}
+ fun(H2_0_1) ->
+ F2_0_1 =
+ % fun-info: {31,45768082,'-lookup_handle/0-fun-7-'}
+ fun(_, []) ->
+ [];
+ (F2_0_1, [O2_0_1|C2_0_1]) ->
+ case O2_0_1 of
+ {_,_} ->
+ [O2_0_1|
+ % fun-info: {30,28136696,'-lookup_handle/0-fun-6-'}
+ fun() ->
+ F2_0_1(F2_0_1,
+ C2_0_1)
+ end];
+ _ ->
+ F2_0_1(F2_0_1, C2_0_1)
+ end;
+ (F2_0_1, C2_0_1)
+ when is_function(C2_0_1) ->
+ F2_0_1(F2_0_1, C2_0_1());
+ (_, C2_0_1) ->
+ C2_0_1
+ end,
+ % fun-info: {32,48059625,'-lookup_handle/0-fun-8-'}
+ fun() ->
+ F2_0_1(F2_0_1, H2_0_1)
+ end
+ end,
+ % fun-info: {37,63676968,'-lookup_handle/0-fun-13-'}
+ fun(H2_0_1) ->
+ F2_0_1 =
+ % fun-info: {35,129320532,'-lookup_handle/0-fun-11-'}
+ fun(_, []) ->
+ [];
+ (F2_0_1, [O2_0_1|C2_0_1]) ->
+ case O2_0_1 of
+ {_} ->
+ [O2_0_1|
+ % fun-info: {34,28136696,'-lookup_handle/0-fun-10-'}
+ fun() ->
+ F2_0_1(F2_0_1,
+ C2_0_1)
+ end];
+ _ ->
+ F2_0_1(F2_0_1, C2_0_1)
+ end;
+ (F2_0_1, C2_0_1)
+ when is_function(C2_0_1) ->
+ F2_0_1(F2_0_1, C2_0_1());
+ (_, C2_0_1) ->
+ C2_0_1
+ end,
+ % fun-info: {36,48059625,'-lookup_handle/0-fun-12-'}
+ fun() ->
+ F2_0_1(F2_0_1, H2_0_1)
+ end
+ end,
+ % fun-info: {38,3236543,'-lookup_handle/0-fun-14-'}
+ fun() ->
+ {[],[],[]}
+ end}}}],
+ % fun-info: {45,56361026,'-lookup_handle/0-fun-21-'}
+ fun(join) ->
+ [[{1,"\001"},{2,"\001"}]];
+ (size) ->
+ % fun-info: {39,40607542,'-lookup_handle/0-fun-15-'}
+ fun(0) ->
+ 2;
+ (1) ->
+ 2;
+ (2) ->
+ 1;
+ (_) ->
+ undefined
+ end;
+ (template) ->
+ % fun-info: {40,34907048,'-lookup_handle/0-fun-16-'}
+ fun({1,1}, _) ->
+ "\001\002";
+ ({2,1}, _) ->
+ "\001\002";
+ (_, _) ->
+ []
+ end;
+ (constants) ->
+ % fun-info: {41,11686091,'-lookup_handle/0-fun-17-'}
+ fun(_) ->
+ no_column_fun
+ end;
+ (n_leading_constant_columns) ->
+ % fun-info: {42,21492441,'-lookup_handle/0-fun-18-'}
+ fun(_) ->
+ 0
+ end;
+ (constant_columns) ->
+ % fun-info: {43,55297177,'-lookup_handle/0-fun-19-'}
+ fun(_) ->
+ []
+ end;
+ (match_specs) ->
+ % fun-info: {44,55081557,'-lookup_handle/0-fun-20-'}
+ fun(_) ->
+ undefined
+ end;
+ (_) ->
+ undefined
+ end}
+ end,
+ undefined}).
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index 3b2e637c84..a542745e67 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -445,9 +445,17 @@ split_specials(Config) when is_list(Config) ->
ok.
-error_handling(doc) ->
- ["Test that errors are handled correctly by the erlang code."];
-error_handling(Config) when is_list(Config) ->
+%% Test that errors are handled correctly by the erlang code.
+error_handling(_Config) ->
+ case test_server:is_native(re) of
+ true ->
+ %% Exceptions from native code look too different.
+ {skip,"re is native"};
+ false ->
+ error_handling()
+ end.
+
+error_handling() ->
% This test checks the exception tuples manufactured in the erlang
% code to hide the trapping from the user at least when it comes to errors
Dog = ?t:timetrap(?t:minutes(1)),
@@ -455,14 +463,14 @@ error_handling(Config) when is_list(Config) ->
% 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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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):
@@ -473,88 +481,88 @@ error_handling(Config) when is_list(Config) ->
[<<"apa">>,
{re_pattern,1,0,_},
[global,unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:run(<<"apa">>,RE,[global,unicode])),
?line {'EXIT',{badarg,[{re,run,
["apa",
{re_pattern,1,0,_},
[global,unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa","p",[global])),
?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa","p",[{capture,all}])),
?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_},
- {?MODULE, error_handling,1,_} | _]}} =
+ {?MODULE, error_handling,0,_} | _]}} =
(catch re:split("apa","p",[{capture,all,binary}])),
?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",{1,2,3,4})),
?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",{1,2,3,4},[])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
[unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[unicode])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
[{return,banana}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[{return,banana}])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
[banana]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[banana])),
?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")),
%Exception on bad argument, not compilation error
@@ -562,7 +570,7 @@ error_handling(Config) when is_list(Config) ->
["apa",
"(p",
[banana]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(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 b6019b86f0..4b83e42ee0 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The 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,7 +153,7 @@ start_restricted_from_shell(Config) when is_list(Config) ->
comm_err(<<"begin init:stop() end.">>),
?line "exception exit: restricted shell does not allow init:stop()" =
comm_err(<<"begin F = fun() -> init:stop() end, F() end.">>),
- ?line "exception error: bad argument in an arithmetic expression" =
+ ?line "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"begin +a end.">>),
?line "exception exit: restricted shell does not allow a + b" =
comm_err(<<"begin a+b end.">>),
@@ -2359,7 +2359,7 @@ otp_6554(Config) when is_list(Config) ->
comm_err(<<"fun(X) -> not X end(a).">>),
?line "exception error: bad argument: a" =
comm_err(<<"fun(A, B) -> A orelse B end(a, b).">>),
- ?line "exception error: bad argument in an arithmetic expression" =
+ ?line "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"math:sqrt(2)/round(math:sqrt(0)).">>),
?line "exception error: interpreted function with arity 1 called with no arguments" =
comm_err(<<"fun(V) -> V end().">>),
@@ -2388,13 +2388,28 @@ 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," =
- comm_err(<<"erlang:error(function_clause, [unproper | list]).">>),
+ case test_server:is_native(erl_eval) of
+ true ->
+ %% Native code has different exit reason. Don't bother
+ %% testing them.
+ ok;
+ false ->
+ "exception error: {function_clause," =
+ comm_err(<<"erlang:error(function_clause, "
+ "[unproper | list]).">>),
+ %% Cheating:
+ "exception error: no function clause matching "
+ "erl_eval:do_apply(4)" ++ _ =
+ comm_err(<<"erlang:error(function_clause, [4]).">>),
+ "exception error: no function clause matching "
+ "lists:reverse(" ++ _ =
+ comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>),
+ "exception error: no function clause matching "
+ "lists:reverse(34) (lists.erl, line " ++ _ =
+ comm_err(<<"lists:reverse(34).">>)
+ end,
?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)" ++ _ =
- comm_err(<<"erlang:error(function_clause, [4]).">>),
?line "exception error: no function clause matching" ++ _ =
comm_err(<<"fun(a, b, c, d) -> foo end"
" (lists:seq(1,17),"
@@ -2404,10 +2419,6 @@ otp_6554(Config) when is_list(Config) ->
?line "exception error: no function clause matching" =
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) (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.">>),
?line "exception error: no such process or port" =
@@ -2467,9 +2478,9 @@ otp_6554(Config) when is_list(Config) ->
" receive {'EXIT', Pid, {{nocatch,foo},_}} -> ok end "
"end.">>),
- ?line "exception error: bad argument in an arithmetic expression" =
+ ?line "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"begin catch_exception(true), 1/0 end.">>),
- ?line "exception error: bad argument in an arithmetic expression" =
+ ?line "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"begin catch_exception(false), 1/0 end.">>),
?line "exception error: no function clause matching call to catch_exception/1" =
comm_err(<<"catch_exception(1).">>),
@@ -2626,7 +2637,7 @@ otp_8393(Config) when is_list(Config) ->
prompt_err(<<"shell:prompt_func('> ').">>),
?line _ = shell:prompt_func(default),
- ?line "exception error: bad argument in an arithmetic expression"++_ =
+ ?line "exception error: an error occurred when evaluating an arithmetic expression"++_ =
prompt_err(<<"shell:prompt_func({shell_SUITE,prompt4}).">>),
?line _ = shell:prompt_func(default),
@@ -2699,7 +2710,7 @@ prompt3(L) ->
integer_to_list(N).
prompt4(_L) ->
- erlang:apply({erlang,'/'}, [1,0]).
+ erlang:apply(fun erlang:'/'/2, [1,0]).
prompt5(_L) ->
[1050,1072,1082,1074,1086,32,1077,32,85,110,105,99,111,100,101,32,63].
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index 73b282149a..f11c6ec4d6 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -536,7 +536,7 @@ projection(Conf) when is_list(Conf) ->
from_term([], [[atom]]))),
?line {'EXIT', {badarg, _}} =
(catch projection({external, fun(X) -> X end}, from_term([[a]]))),
- ?line eval(projection({sofs,union},
+ ?line eval(projection(fun sofs:union/1,
from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
from_term([[1,2,3], [a,b,c]])),
?line eval(projection(fun(_) -> from_term([a]) end,
@@ -628,7 +628,7 @@ substitution(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch substitution({external, fun(X) -> X end}, from_term([[a]]))),
?line eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E),
- ?line eval(substitution({sofs,union},
+ ?line eval(substitution(fun sofs:union/1,
from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])),
?line eval(substitution(fun(_) -> from_term([a]) end,
@@ -745,7 +745,7 @@ restriction(Conf) when is_list(Conf) ->
?line eval(restriction(Id, S3, E), E),
?line eval(restriction(Id, from_term([], [[atom]]), set([a])),
from_term([], [[atom]])),
- ?line eval(restriction({sofs,union},
+ ?line eval(restriction(fun sofs:union/1,
from_term([[[a],[b]], [[b],[c]],
[[], [a,b]], [[1],[2]]]),
from_term([[a,b],[1,2,3],[b,c]])),
@@ -862,7 +862,7 @@ drestriction(Conf) when is_list(Conf) ->
?line eval(drestriction(Id, S3, E), S3),
?line eval(drestriction(Id, from_term([], [[atom]]), set([a])),
from_term([], [[atom]])),
- ?line eval(drestriction({sofs,union},
+ ?line eval(drestriction(fun sofs:union/1,
from_term([[[a],[b]], [[b],[c]],
[[], [a,b]], [[1],[2]]]),
from_term([[a,b],[1,2,3],[b,c]])),
@@ -1028,7 +1028,7 @@ specification(Conf) when is_list(Conf) ->
end,
?line eval(specification({external,Fun2x}, S2), from_term([[1],[3]])),
- Fun3 = fun(_) -> neither_true_or_false end,
+ Fun3 = fun(_) -> neither_true_nor_false end,
?line {'EXIT', {badarg, _}} =
(catch specification(Fun3, set([a]))),
?line {'EXIT', {badarg, _}} =
@@ -1810,8 +1810,8 @@ partition_3(Conf) when is_list(Conf) ->
S12a = from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]),
S12b = from_term([[a,b],[1,2,3],[b,c]]),
- ?line eval(partition({sofs,union}, S12a, S12b),
- lpartition({sofs,union}, S12a, S12b)),
+ ?line eval(partition(fun sofs:union/1, S12a, S12b),
+ lpartition(fun sofs:union/1, S12a, S12b)),
Fun13 = fun(_) -> from_term([a]) end,
S13a = from_term([], [[atom]]),
@@ -1879,12 +1879,9 @@ digraph(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch family_to_digraph(set([a]))),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
- (catch family_to_digraph(set([a]), [foo])),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
- (catch family_to_digraph(F, [foo])),
- ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_],_}|_]}} =
- (catch family_to_digraph(family([{a,[a]}]),[acyclic])),
+ digraph_fail(badarg, catch family_to_digraph(set([a]), [foo])),
+ digraph_fail(badarg, catch family_to_digraph(F, [foo])),
+ digraph_fail(cyclic, catch family_to_digraph(family([{a,[a]}]),[acyclic])),
?line G1 = family_to_digraph(E),
?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, foo)),
@@ -1927,6 +1924,13 @@ digraph(Conf) when is_list(Conf) ->
?line true = T0 == ets:all(),
ok.
+digraph_fail(ExitReason, Fail) ->
+ {'EXIT', {ExitReason, [{sofs,family_to_digraph,A,_}|_]}} = Fail,
+ case {test_server:is_native(sofs),A} of
+ {false,[_,_]} -> ok;
+ {true,2} -> ok
+ end.
+
constant_function(suite) -> [];
constant_function(doc) -> [""];
constant_function(Conf) when is_list(Conf) ->
@@ -1952,10 +1956,8 @@ misc(Conf) when is_list(Conf) ->
% the "functional" part:
?line eval(union(intersection(partition(1,S), partition(Id,S))),
difference(S, RR)),
-
- %% The function external:foo/1 is undefined.
?line {'EXIT', {undef, _}} =
- (catch projection({external,foo}, set([a,b,c]))),
+ (catch projection(fun external:foo/1, set([a,b,c]))),
ok.
relational_restriction(R) ->
@@ -1968,19 +1970,19 @@ family_specification(doc) -> [""];
family_specification(Conf) when is_list(Conf) ->
E = empty_set(),
%% internal
- ?line eval(family_specification({sofs, is_set}, E), E),
+ ?line eval(family_specification(fun sofs:is_set/1, E), E),
?line {'EXIT', {badarg, _}} =
- (catch family_specification({sofs,is_set}, set([]))),
+ (catch family_specification(fun sofs:is_set/1, set([]))),
?line F1 = from_term([{1,[1]}]),
- ?line eval(family_specification({sofs,is_set}, F1), F1),
+ ?line eval(family_specification(fun sofs:is_set/1, F1), F1),
Fun = fun(S) -> is_subset(S, set([0,1,2,3,4])) end,
?line F2 = family([{a,[1,2]},{b,[3,4,5]}]),
?line eval(family_specification(Fun, F2), family([{a,[1,2]}])),
?line F3 = from_term([{a,[]},{b,[]}]),
- ?line eval(family_specification({sofs,is_set}, F3), F3),
+ ?line eval(family_specification(fun sofs:is_set/1, F3), F3),
Fun2 = fun(_) -> throw(fippla) end,
?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
- Fun3 = fun(_) -> neither_true_or_false end,
+ Fun3 = fun(_) -> neither_true_nor_false end,
?line {'EXIT', {badarg, _}} =
(catch family_specification(Fun3, F3)),
@@ -2095,22 +2097,22 @@ family_projection(Conf) when is_list(Conf) ->
?line eval(family_projection(fun(X) -> X end, family([])), E),
?line L1 = [{a,[]}],
- ?line eval(family_projection({sofs,union}, E), E),
- ?line eval(family_projection({sofs,union}, from_term(L1, SSType)),
+ ?line eval(family_projection(fun sofs:union/1, E), E),
+ ?line eval(family_projection(fun sofs:union/1, from_term(L1, SSType)),
family(L1)),
?line {'EXIT', {badarg, _}} =
- (catch family_projection({sofs,union}, set([]))),
+ (catch family_projection(fun sofs:union/1, set([]))),
?line {'EXIT', {badarg, _}} =
- (catch family_projection({sofs,union}, from_term([{1,[1]}]))),
+ (catch family_projection(fun sofs:union/1, from_term([{1,[1]}]))),
?line F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType),
- ?line eval(family_projection({sofs,union}, F2),
+ ?line eval(family_projection(fun sofs:union/1, F2),
family_union(F2)),
?line F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}],
SRType),
- ?line eval(family_projection({sofs,domain}, F3), family_domain(F3)),
- ?line eval(family_projection({sofs,range}, F3), family_range(F3)),
+ ?line eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)),
+ ?line eval(family_projection(fun sofs:range/1, F3), family_range(F3)),
?line eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])),
from_term([{a,[]}])),
@@ -2290,7 +2292,7 @@ partition_family(Conf) when is_list(Conf) ->
?line eval(partition_family(1, E), E),
?line eval(partition_family(2, E), E),
- ?line eval(partition_family({sofs,union}, E), E),
+ ?line eval(partition_family(fun sofs:union/1, E), E),
?line eval(partition_family(1, ER), EF),
?line eval(partition_family(2, ER), EF),
?line {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))),
@@ -2354,7 +2356,7 @@ partition_family(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch partition_family({external, fun(X) -> X end},
from_term([[a]]))),
- ?line eval(partition_family({sofs,union},
+ ?line eval(partition_family(fun sofs:union/1,
from_term([[[1],[1,2]], [[1,2]]])),
from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])),
?line eval(partition_family(fun(X) -> X end,
diff --git a/lib/stdlib/test/stdlib_SUITE.erl b/lib/stdlib/test/stdlib_SUITE.erl
index 0cca030b3d..8a2cb5ea6b 100644
--- a/lib/stdlib/test/stdlib_SUITE.erl
+++ b/lib/stdlib/test/stdlib_SUITE.erl
@@ -33,8 +33,7 @@
-export([init_per_testcase/2, end_per_testcase/2]).
% Test cases must be exported.
--export([app_test/1]).
--define(cases, [app_test]).
+-export([app_test/1, appup_test/1]).
%%
%% all/1
@@ -42,7 +41,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app_test].
+ [app_test, appup_test].
groups() ->
[].
@@ -79,3 +78,61 @@ app_test(Config) when is_list(Config) ->
?t:app_test(stdlib),
ok.
+%% Test that appup allows upgrade from/downgrade to a maximum of two
+%% major releases back.
+appup_test(_Config) ->
+ application:load(stdlib),
+ {_,_,Vsn} = lists:keyfind(stdlib,1,application:loaded_applications()),
+ AppupFile = filename:join([code:lib_dir(stdlib),ebin,"stdlib.appup"]),
+ {ok,[{Vsn,UpFrom,DownTo}=AppupScript]} = file:consult(AppupFile),
+ ct:log("~p~n",[AppupScript]),
+ {OkVsns,NokVsns} = create_test_vsns(Vsn),
+ check_appup(OkVsns,UpFrom,{ok,[restart_new_emulator]}),
+ check_appup(OkVsns,DownTo,{ok,[restart_new_emulator]}),
+ check_appup(NokVsns,UpFrom,error),
+ check_appup(NokVsns,DownTo,error),
+ ok.
+
+create_test_vsns(Current) ->
+ [XStr,YStr|Rest] = string:tokens(Current,"."),
+ X = list_to_integer(XStr),
+ Y = list_to_integer(YStr),
+ SecondMajor = vsn(X,Y-2),
+ SecondMinor = SecondMajor ++ ".1.3",
+ FirstMajor = vsn(X,Y-1),
+ FirstMinor = FirstMajor ++ ".57",
+ ThisMajor = vsn(X,Y),
+ This =
+ case Rest of
+ [] ->
+ [];
+ ["1"] ->
+ [ThisMajor];
+ _ ->
+ ThisMinor = ThisMajor ++ ".1",
+ [ThisMajor,ThisMinor]
+ end,
+ OkVsns = This ++ [FirstMajor, FirstMinor, SecondMajor, SecondMinor],
+
+ ThirdMajor = vsn(X,Y-3),
+ ThirdMinor = ThirdMajor ++ ".10.12",
+ Illegal = ThisMajor ++ ",1",
+ Newer1Major = vsn(X,Y+1),
+ Newer1Minor = Newer1Major ++ ".1",
+ Newer2Major = ThisMajor ++ "1",
+ NokVsns = [ThirdMajor,ThirdMinor,
+ Illegal,
+ Newer1Major,Newer1Minor,
+ Newer2Major],
+ {OkVsns,NokVsns}.
+
+vsn(X,Y) ->
+ integer_to_list(X) ++ "." ++ integer_to_list(Y).
+
+check_appup([Vsn|Vsns],Instrs,Expected) ->
+ case systools_relup:appup_search_for_version(Vsn, Instrs) of
+ Expected -> check_appup(Vsns,Instrs,Expected);
+ Other -> ct:fail({unexpected_result_for_vsn,Vsn,Other})
+ end;
+check_appup([],_,_) ->
+ ok.
diff --git a/lib/stdlib/test/supervisor_1.erl b/lib/stdlib/test/supervisor_1.erl
index f819594c46..777a48e38b 100644
--- a/lib/stdlib/test/supervisor_1.erl
+++ b/lib/stdlib/test/supervisor_1.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
diff --git a/lib/stdlib/test/supervisor_2.erl b/lib/stdlib/test/supervisor_2.erl
new file mode 100644
index 0000000000..60d037f4e0
--- /dev/null
+++ b/lib/stdlib/test/supervisor_2.erl
@@ -0,0 +1,42 @@
+%%
+%% %CopyrightBegin%
+%%
+%% 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
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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: Simulates the behaviour that a child process may have.
+%% Is used by the supervisor_SUITE test suite.
+-module(supervisor_2).
+
+-export([start_child/1, init/1]).
+
+-export([handle_call/3, handle_info/2, terminate/2]).
+
+start_child(Time) when is_integer(Time), Time > 0 ->
+ gen_server:start_link(?MODULE, Time, []).
+
+init(Time) ->
+ process_flag(trap_exit, true),
+ {ok, Time}.
+
+handle_call(Req, _From, State) ->
+ {reply, Req, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, Time) ->
+ timer:sleep(Time),
+ ok.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index 2aa3131aeb..767ae3d62c 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -21,7 +21,7 @@
-module(supervisor_SUITE).
-include_lib("common_test/include/ct.hrl").
--define(TIMEOUT, 1000).
+-define(TIMEOUT, ?t:minutes(1)).
%% Testserver specific export
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -29,12 +29,15 @@
end_per_testcase/2]).
%% Internal export
--export([init/1, terminate_all_children/1]).
+-export([init/1, terminate_all_children/1,
+ middle9212/0, gen_server9212/0, handle_info/2]).
%% 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_start_ignore_child/1, sup_start_ignore_temporary_child/1,
+ sup_start_ignore_temporary_child_start_child/1,
+ sup_start_ignore_temporary_child_start_child_simple/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]).
@@ -52,13 +55,15 @@
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]).
+ simple_one_for_one_extra/1, simple_one_for_one_shutdown/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_child_specs_for_temporary_children/1,
- simple_one_for_one_scale_many_temporary_children/1]).
+ simple_one_for_one_scale_many_temporary_children/1,
+ simple_global_supervisor/1, hanging_restart_loop/1,
+ hanging_restart_loop_simple/1]).
%%-------------------------------------------------------------------------
@@ -77,13 +82,16 @@ all() ->
{group, abnormal_termination}, child_unlink, tree,
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].
+ simple_one_for_one_scale_many_temporary_children, temporary_bystander,
+ simple_global_supervisor, hanging_restart_loop, hanging_restart_loop_simple].
groups() ->
[{sup_start, [],
[sup_start_normal, sup_start_ignore_init,
- sup_start_ignore_child, sup_start_error_return,
- sup_start_fail]},
+ sup_start_ignore_child, sup_start_ignore_temporary_child,
+ sup_start_ignore_temporary_child_start_child,
+ sup_start_ignore_temporary_child_start_child_simple,
+ sup_start_error_return, sup_start_fail]},
{sup_stop, [],
[sup_stop_infinity, sup_stop_timeout,
sup_stop_brutal_kill]},
@@ -99,15 +107,13 @@ groups() ->
{restart_one_for_all, [],
[one_for_all, one_for_all_escalation]},
{restart_simple_one_for_one, [],
- [simple_one_for_one, simple_one_for_one_extra,
- simple_one_for_one_escalation]},
+ [simple_one_for_one, simple_one_for_one_shutdown,
+ simple_one_for_one_extra, simple_one_for_one_escalation]},
{restart_rest_for_one, [],
[rest_for_one, rest_for_one_escalation]}].
-init_per_suite(Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = test_server:timetrap(?TIMEOUT),
- [{watchdog, Dog} | Config].
+init_per_suite(Config) ->
+ Config.
end_per_suite(_Config) ->
ok.
@@ -120,15 +126,23 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(count_children_memory, Config) ->
try erlang:memory() of
- _ -> Config
+ _ ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ Dog = ?t:timetrap(?TIMEOUT),
+ [{watchdog,Dog}|Config]
catch error:notsup ->
{skip, "+Meamin used during test; erlang:memory/1 not available"}
end;
init_per_testcase(_Case, Config) ->
- erlang:display(_Case),
- Config.
+ Dog = ?t:timetrap(?TIMEOUT),
+ [{watchdog,Dog}|Config].
-end_per_testcase(_Case, _Config) ->
+end_per_testcase(count_children_memory, Config) ->
+ catch erts_debug:set_internal_state(available_internal_state, false),
+ ?t:timetrap_cancel(?config(watchdog,Config)),
+ ok;
+end_per_testcase(_Case, Config) ->
+ ?t:timetrap_cancel(?config(watchdog,Config)),
ok.
start_link(InitResult) ->
@@ -150,29 +164,23 @@ get_child_counts(Supervisor) ->
%%-------------------------------------------------------------------------
%% Test cases starts here.
-%%-------------------------------------------------------------------------
-sup_start_normal(doc) ->
- ["Tests that the supervisor process starts correctly and that it "
- "can be terminated gracefully."];
-sup_start_normal(suite) -> [];
+%% -------------------------------------------------------------------------
+%% Tests that the supervisor process starts correctly and that it can
+%% be terminated gracefully.
sup_start_normal(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{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) -> [];
+%% Tests what happens if init-callback returns ignore.
sup_start_ignore_init(Config) when is_list(Config) ->
process_flag(trap_exit, true),
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) -> [];
+%% Tests what happens if init-callback returns ignore.
sup_start_ignore_child(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
@@ -189,30 +197,75 @@ sup_start_ignore_child(Config) when is_list(Config) ->
[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) -> [];
+%% Tests what happens if child's init-callback returns ignore for a
+%% temporary child when ChildSpec is returned directly from supervisor
+%% init callback.
+%% Child spec shall NOT be saved!!!
+sup_start_ignore_temporary_child(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Child1 = {child1, {supervisor_1, start_child, [ignore]},
+ temporary, 1000, worker, []},
+ Child2 = {child2, {supervisor_1, start_child, []}, temporary,
+ 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child1,Child2]}}),
+
+ [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ true = is_pid(CPid2),
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+%% Tests what happens if child's init-callback returns ignore for a
+%% temporary child when child is started with start_child/2.
+%% Child spec shall NOT be saved!!!
+sup_start_ignore_temporary_child_start_child(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, [ignore]},
+ temporary, 1000, worker, []},
+ Child2 = {child2, {supervisor_1, start_child, []}, temporary,
+ 1000, worker, []},
+
+ {ok, undefined} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+
+ [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+%% Tests what happens if child's init-callback returns ignore for a
+%% temporary child when child is started with start_child/2, and the
+%% supervisor is simple_one_for_one.
+%% Child spec shall NOT be saved!!!
+sup_start_ignore_temporary_child_start_child_simple(Config)
+ when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Child1 = {child1, {supervisor_1, start_child, [ignore]},
+ temporary, 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child1]}}),
+
+ {ok, undefined} = supervisor:start_child(sup_test, []),
+ {ok, CPid2} = supervisor:start_child(sup_test, []),
+
+ [{undefined, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+%% Tests what happens if init-callback returns a invalid value.
sup_start_error_return(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{error, Term} = start_link(invalid),
check_exit_reason(Term).
%%-------------------------------------------------------------------------
-sup_start_fail(doc) ->
- ["Tests what happens if init-callback fails"];
-sup_start_fail(suite) -> [];
+%% Tests what happens if init-callback fails.
sup_start_fail(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{error, Term} = start_link(fail),
check_exit_reason(Term).
%%-------------------------------------------------------------------------
-
-sup_stop_infinity(doc) ->
- ["See sup_stop/1 when Shutdown = infinity, this walue is only allowed "
- "for children of type supervisor"];
-sup_stop_infinity(suite) -> [];
-
+%% See sup_stop/1 when Shutdown = infinity, this walue is allowed for
+%% children of type supervisor _AND_ worker.
sup_stop_infinity(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
@@ -221,19 +274,16 @@ sup_stop_infinity(Config) when is_list(Config) ->
Child2 = {child2, {supervisor_1, start_child, []}, permanent,
infinity, worker, []},
{ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid1),
- {error, {invalid_shutdown,infinity}} =
- supervisor:start_child(sup_test, Child2),
+ link(CPid2),
terminate(Pid, shutdown),
- check_exit_reason(CPid1, shutdown).
+ check_exit_reason(CPid1, shutdown),
+ check_exit_reason(CPid2, shutdown).
%%-------------------------------------------------------------------------
-
-sup_stop_timeout(doc) ->
- ["See sup_stop/1 when Shutdown = 1000"];
-sup_stop_timeout(suite) -> [];
-
+%% See sup_stop/1 when Shutdown = 1000
sup_stop_timeout(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
@@ -255,10 +305,7 @@ sup_stop_timeout(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-sup_stop_brutal_kill(doc) ->
- ["See sup_stop/1 when Shutdown = brutal_kill"];
-sup_stop_brutal_kill(suite) -> [];
-
+%% See sup_stop/1 when Shutdown = brutal_kill
sup_stop_brutal_kill(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
@@ -277,14 +324,10 @@ sup_stop_brutal_kill(Config) when is_list(Config) ->
check_exit_reason(CPid2, killed).
%%-------------------------------------------------------------------------
-extra_return(doc) ->
- ["The start function provided to start a child may "
- "return {ok, Pid} or {ok, Pid, Info}, if it returns "
- "the later check that the supervisor ignores the Info, "
- "and includes it unchanged in return from start_child/2 "
- "and restart_child/2"];
-extra_return(suite) -> [];
-
+%% The start function provided to start a child may return {ok, Pid}
+%% or {ok, Pid, Info}, if it returns the latter check that the
+%% supervisor ignores the Info, and includes it unchanged in return
+%% from start_child/2 and restart_child/2.
extra_return(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child1, {supervisor_1, start_child, [extra_return]},
@@ -324,12 +367,10 @@ extra_return(Config) when is_list(Config) ->
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 "
- "childspecs are used, handling of incorrect childspecs is tested in "
- "child_specs/1"];
-child_adm(suite) -> [];
+%% Test API functions start_child/2, terminate_child/2, delete_child/2
+%% restart_child/2, which_children/1, count_children/1. Only correct
+%% childspecs are used, handling of incorrect childspecs is tested in
+%% child_specs/1.
child_adm(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child1, {supervisor_1, start_child, []}, permanent, 1000,
@@ -393,11 +434,9 @@ child_adm(Config) when is_list(Config) ->
= (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."];
-child_adm_simple(suite) -> [];
+%% 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.
child_adm_simple(Config) when is_list(Config) ->
Child = {child, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
@@ -445,9 +484,7 @@ child_adm_simple(Config) when is_list(Config) ->
ok.
%%-------------------------------------------------------------------------
-child_specs(doc) ->
- ["Tests child specs, invalid formats should be rejected."];
-child_specs(suite) -> [];
+%% Tests child specs, invalid formats should be rejected.
child_specs(Config) when is_list(Config) ->
process_flag(trap_exit, true),
{ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
@@ -458,9 +495,8 @@ child_specs(Config) when is_list(Config) ->
B2 = {child, {m,f,[a]}, prmanent, 1000, worker, []},
B3 = {child, {m,f,[a]}, permanent, -10, worker, []},
B4 = {child, {m,f,[a]}, permanent, 10, wrker, []},
- 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]},
+ B5 = {child, {m,f,[a]}, permanent, 1000, worker, dy},
+ B6 = {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
@@ -469,6 +505,7 @@ child_specs(Config) when is_list(Config) ->
C2 = {child, {m,f,[a]}, permanent, 1000, supervisor, []},
C3 = {child, {m,f,[a]}, temporary, 1000, worker, dynamic},
C4 = {child, {m,f,[a]}, transient, 1000, worker, [m]},
+ C5 = {child, {m,f,[a]}, permanent, infinity, worker, [m]},
{error, {invalid_mfa,mfa}} = supervisor:start_child(sup_test, B1),
{error, {invalid_restart_type, prmanent}} =
@@ -477,9 +514,8 @@ child_specs(Config) when is_list(Config) ->
= supervisor:start_child(sup_test, B3),
{error, {invalid_child_type,wrker}}
= supervisor:start_child(sup_test, B4),
- {error, _} = supervisor:start_child(sup_test, B5),
{error, {invalid_modules,dy}}
- = supervisor:start_child(sup_test, B6),
+ = supervisor:start_child(sup_test, B5),
{error, {invalid_mfa,mfa}} = supervisor:check_childspecs([B1]),
{error, {invalid_restart_type,prmanent}} =
@@ -487,21 +523,19 @@ child_specs(Config) when is_list(Config) ->
{error, {invalid_shutdown,-10}} = supervisor:check_childspecs([B3]),
{error, {invalid_child_type,wrker}}
= supervisor:check_childspecs([B4]),
- {error, _} = supervisor:check_childspecs([B5]),
- {error, {invalid_modules,dy}} = supervisor:check_childspecs([B6]),
+ {error, {invalid_modules,dy}} = supervisor:check_childspecs([B5]),
{error, {invalid_module, 1}} =
- supervisor:check_childspecs([B7]),
+ supervisor:check_childspecs([B6]),
ok = supervisor:check_childspecs([C1]),
ok = supervisor:check_childspecs([C2]),
ok = supervisor:check_childspecs([C3]),
ok = supervisor:check_childspecs([C4]),
+ ok = supervisor:check_childspecs([C5]),
ok.
%%-------------------------------------------------------------------------
-permanent_normal(doc) ->
- ["A permanent child should always be restarted"];
-permanent_normal(suite) -> [];
+%% A permanent child should always be restarted.
permanent_normal(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
@@ -521,10 +555,8 @@ permanent_normal(Config) when is_list(Config) ->
[1,1,0,1] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-transient_normal(doc) ->
- ["A transient child should not be restarted if it exits with "
- "reason normal"];
-transient_normal(suite) -> [];
+%% A transient child should not be restarted if it exits with reason
+%% normal.
transient_normal(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000,
@@ -538,9 +570,7 @@ transient_normal(Config) when is_list(Config) ->
[1,0,0,1] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-temporary_normal(doc) ->
- ["A temporary process should never be restarted"];
-temporary_normal(suite) -> [];
+%% A temporary process should never be restarted.
temporary_normal(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000,
@@ -554,9 +584,7 @@ temporary_normal(Config) when is_list(Config) ->
[0,0,0,0] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-permanent_shutdown(doc) ->
- ["A permanent child should always be restarted"];
-permanent_shutdown(suite) -> [];
+%% A permanent child should always be restarted.
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,
@@ -588,10 +616,8 @@ permanent_shutdown(Config) when is_list(Config) ->
[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) -> [];
+%% A transient child should not be restarted if it exits with reason
+%% shutdown or {shutdown,Term}.
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,
@@ -612,9 +638,7 @@ transient_shutdown(Config) when is_list(Config) ->
[1,0,0,1] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-temporary_shutdown(doc) ->
- ["A temporary process should never be restarted"];
-temporary_shutdown(suite) -> [];
+%% A temporary process should never be restarted.
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,
@@ -635,9 +659,7 @@ temporary_shutdown(Config) when is_list(Config) ->
[0,0,0,0] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-permanent_abnormal(doc) ->
- ["A permanent child should always be restarted"];
-permanent_abnormal(suite) -> [];
+%% A permanent child should always be restarted.
permanent_abnormal(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
@@ -656,10 +678,7 @@ permanent_abnormal(Config) when is_list(Config) ->
[1,1,0,1] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-transient_abnormal(doc) ->
- ["A transient child should be restarted if it exits with "
- "reason abnormal"];
-transient_abnormal(suite) -> [];
+%% A transient child should be restarted if it exits with reason abnormal.
transient_abnormal(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000,
@@ -678,9 +697,7 @@ transient_abnormal(Config) when is_list(Config) ->
[1,1,0,1] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
-temporary_abnormal(doc) ->
- ["A temporary process should never be restarted"];
-temporary_abnormal(suite) -> [];
+%% A temporary process should never be restarted.
temporary_abnormal(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000,
@@ -693,11 +710,9 @@ temporary_abnormal(Config) when is_list(Config) ->
[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) -> [];
+%% 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(_Config) ->
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 100,
worker, []},
@@ -724,9 +739,7 @@ temporary_bystander(_Config) ->
[{child1, _, _, _}] = supervisor:which_children(SupPid2).
%%-------------------------------------------------------------------------
-one_for_one(doc) ->
- ["Test the one_for_one base case."];
-one_for_one(suite) -> [];
+%% Test the one_for_one base case.
one_for_one(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
@@ -756,9 +769,7 @@ one_for_one(Config) when is_list(Config) ->
check_exit([SupPid]).
%%-------------------------------------------------------------------------
-one_for_one_escalation(doc) ->
- ["Test restart escalation on a one_for_one supervisor."];
-one_for_one_escalation(suite) -> [];
+%% Test restart escalation on a one_for_one supervisor.
one_for_one_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -778,9 +789,7 @@ one_for_one_escalation(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-one_for_all(doc) ->
- ["Test the one_for_all base case."];
-one_for_all(suite) -> [];
+%% Test the one_for_all base case.
one_for_all(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -816,9 +825,7 @@ one_for_all(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-one_for_all_escalation(doc) ->
- ["Test restart escalation on a one_for_all supervisor."];
-one_for_all_escalation(suite) -> [];
+%% Test restart escalation on a one_for_all supervisor.
one_for_all_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -837,9 +844,7 @@ one_for_all_escalation(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-simple_one_for_one(doc) ->
- ["Test the simple_one_for_one base case."];
-simple_one_for_one(suite) -> [];
+%% Test the simple_one_for_one base case.
simple_one_for_one(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, []}, permanent, 1000,
@@ -868,11 +873,39 @@ simple_one_for_one(Config) when is_list(Config) ->
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."];
-simple_one_for_one_extra(suite) -> [];
+%% Test simple_one_for_one children shutdown accordingly to the
+%% supervisor's shutdown strategy.
+simple_one_for_one_shutdown(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ShutdownTime = 1000,
+ Child = {child, {supervisor_2, start_child, []},
+ permanent, 2*ShutdownTime, worker, []},
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+
+ %% Will be gracefully shutdown
+ {ok, _CPid1} = supervisor:start_child(sup_test, [ShutdownTime]),
+ {ok, _CPid2} = supervisor:start_child(sup_test, [ShutdownTime]),
+
+ %% Will be killed after 2*ShutdownTime milliseconds
+ {ok, _CPid3} = supervisor:start_child(sup_test, [5*ShutdownTime]),
+
+ {T, ok} = timer:tc(fun terminate/2, [SupPid, shutdown]),
+ if T < 1000*ShutdownTime ->
+ %% Because supervisor's children wait before exiting, it can't
+ %% terminate quickly
+ test_server:fail({shutdown_too_short, T});
+ T >= 1000*5*ShutdownTime ->
+ test_server:fail({shutdown_too_long, T});
+ true ->
+ check_exit([SupPid])
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Tests automatic restart of children who's start function return
+%% extra info.
simple_one_for_one_extra(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, [extra_info]},
@@ -897,9 +930,7 @@ simple_one_for_one_extra(Config) when is_list(Config) ->
check_exit([SupPid]).
%%-------------------------------------------------------------------------
-simple_one_for_one_escalation(doc) ->
- ["Test restart escalation on a simple_one_for_one supervisor."];
-simple_one_for_one_escalation(suite) -> [];
+%% Test restart escalation on a simple_one_for_one supervisor.
simple_one_for_one_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, []}, permanent, 1000,
@@ -914,9 +945,7 @@ simple_one_for_one_escalation(Config) when is_list(Config) ->
check_exit([SupPid, CPid2]).
%%-------------------------------------------------------------------------
-rest_for_one(doc) ->
- ["Test the rest_for_one base case."];
-rest_for_one(suite) -> [];
+%% Test the rest_for_one base case.
rest_for_one(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
@@ -964,9 +993,7 @@ rest_for_one(Config) when is_list(Config) ->
check_exit([SupPid]).
%%-------------------------------------------------------------------------
-rest_for_one_escalation(doc) ->
- ["Test restart escalation on a rest_for_one supervisor."];
-rest_for_one_escalation(suite) -> [];
+%% Test restart escalation on a rest_for_one supervisor.
rest_for_one_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
@@ -983,11 +1010,8 @@ rest_for_one_escalation(Config) when is_list(Config) ->
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) ->
- [];
+%% Test that the supervisor does not hang forever if the child unliks
+%% and then is terminated by the supervisor.
child_unlink(Config) when is_list(Config) ->
{ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
@@ -1012,10 +1036,7 @@ child_unlink(Config) when is_list(Config) ->
test_server:fail(supervisor_hangs)
end.
%%-------------------------------------------------------------------------
-tree(doc) ->
- ["Test a basic supervison tree."];
-tree(suite) ->
- [];
+%% Test a basic supervison tree.
tree(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1091,11 +1112,9 @@ tree(Config) when is_list(Config) ->
[] = 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) ->
- [];
+%% Test that count_children does not eat memory.
count_children_memory(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, []}, temporary, 1000,
@@ -1104,25 +1123,25 @@ count_children_memory(Config) when is_list(Config) ->
[supervisor:start_child(sup_test, []) || _Ignore <- lists:seq(1,1000)],
garbage_collect(),
- _Size1 = erlang:memory(processes_used),
+ _Size1 = proc_memory(),
Children = supervisor:which_children(sup_test),
- _Size2 = erlang:memory(processes_used),
+ _Size2 = proc_memory(),
ChildCount = get_child_counts(sup_test),
- _Size3 = erlang:memory(processes_used),
+ _Size3 = proc_memory(),
[supervisor:start_child(sup_test, []) || _Ignore2 <- lists:seq(1,1000)],
garbage_collect(),
Children2 = supervisor:which_children(sup_test),
- Size4 = erlang:memory(processes_used),
+ Size4 = proc_memory(),
ChildCount2 = get_child_counts(sup_test),
- Size5 = erlang:memory(processes_used),
+ Size5 = proc_memory(),
garbage_collect(),
Children3 = supervisor:which_children(sup_test),
- Size6 = erlang:memory(processes_used),
+ Size6 = proc_memory(),
ChildCount3 = get_child_counts(sup_test),
- Size7 = erlang:memory(processes_used),
+ Size7 = proc_memory(),
1000 = length(Children),
[1,1000,0,1000] = ChildCount,
@@ -1137,24 +1156,25 @@ count_children_memory(Config) when is_list(Config) ->
case (Size5 =< Size4) of
true -> ok;
false ->
- test_server:fail({count_children, used_more_memory})
+ test_server:fail({count_children, used_more_memory,Size4,Size5})
end,
case Size7 =< Size6 of
true -> ok;
false ->
- test_server:fail({count_children, used_more_memory})
+ test_server:fail({count_children, used_more_memory,Size6,Size7})
end,
[terminate(SupPid, Pid, child, kill) || {undefined, Pid, worker, _Modules} <- Children3],
[1,0,0,0] = get_child_counts(sup_test).
+proc_memory() ->
+ erts_debug:set_internal_state(wait, deallocations),
+ erlang:memory(processes_used).
+
%%-------------------------------------------------------------------------
-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 "
- "take up a huge amount of memory for no purpose."];
-do_not_save_start_parameters_for_temporary_children(suite) ->
- [];
+%% Temporary children shall not be restarted so they should not save
+%% start parameters, as it potentially can take up a huge amount of
+%% memory for no purpose.
do_not_save_start_parameters_for_temporary_children(Config) when is_list(Config) ->
process_flag(trap_exit, true),
dont_save_start_parameters_for_temporary_children(one_for_all),
@@ -1176,11 +1196,8 @@ child_spec({Name, MFA, RestartType, Shutdown, Type, Modules}, 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) ->
- [];
+%% Temporary children shall not be restarted so supervisors should not
+%% save their spec when they terminate.
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),
@@ -1329,13 +1346,18 @@ simple_one_for_one_scale_many_temporary_children(_Config) ->
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});
+ if T1 > 0 ->
+ 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;
true ->
+ %% Means T2 div T1 -> infinity
ok
end.
@@ -1347,6 +1369,188 @@ terminate_all_children([]) ->
done.
+%%-------------------------------------------------------------------------
+%% OTP-9212. Restart of global supervisor.
+simple_global_supervisor(_Config) ->
+ kill_supervisor(),
+ kill_worker(),
+ exit_worker(),
+ restart_worker(),
+ ok.
+
+kill_supervisor() ->
+ {Top, Sup2_1, Server_1} = start9212(),
+
+ %% Killing a supervisor isn't really supported, but try it anyway...
+ exit(Sup2_1, kill),
+ timer:sleep(200),
+ Sup2_2 = global:whereis_name(sup2),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Sup2_2),
+ true = is_pid(Server_2),
+ true = Sup2_1 =/= Sup2_2,
+ true = Server_1 =/= Server_2,
+
+ stop9212(Top).
+
+handle_info({fail, With, After}, _State) ->
+ timer:sleep(After),
+ erlang:error(With).
+
+kill_worker() ->
+ {Top, _Sup2, Server_1} = start9212(),
+ exit(Server_1, kill),
+ timer:sleep(200),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Server_2),
+ true = Server_1 =/= Server_2,
+ stop9212(Top).
+
+exit_worker() ->
+ %% Very much the same as kill_worker().
+ {Top, _Sup2, Server_1} = start9212(),
+ Server_1 ! {fail, normal, 0},
+ timer:sleep(200),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Server_2),
+ true = Server_1 =/= Server_2,
+ stop9212(Top).
+
+restart_worker() ->
+ {Top, _Sup2, Server_1} = start9212(),
+ ok = supervisor:terminate_child({global, sup2}, child),
+ {ok, _Child} = supervisor:restart_child({global, sup2}, child),
+ Server_2 = global:whereis_name(server),
+ true = is_pid(Server_2),
+ true = Server_1 =/= Server_2,
+ stop9212(Top).
+
+start9212() ->
+ Middle = {middle,{?MODULE,middle9212,[]}, permanent,2000,supervisor,[]},
+ InitResult = {ok, {{one_for_all,3,60}, [Middle]}},
+ {ok, TopPid} = start_link(InitResult),
+
+ Sup2 = global:whereis_name(sup2),
+ Server = global:whereis_name(server),
+ true = is_pid(Sup2),
+ true = is_pid(Server),
+ {TopPid, Sup2, Server}.
+
+stop9212(Top) ->
+ Old = process_flag(trap_exit, true),
+ exit(Top, kill),
+ timer:sleep(200),
+ undefined = global:whereis_name(sup2),
+ undefined = global:whereis_name(server),
+ check_exit([Top]),
+ _ = process_flag(trap_exit, Old),
+ ok.
+
+middle9212() ->
+ Child = {child, {?MODULE,gen_server9212,[]},permanent, 2000, worker, []},
+ InitResult = {ok, {{one_for_all,3,60}, [Child]}},
+ supervisor:start_link({global,sup2}, ?MODULE, InitResult).
+
+gen_server9212() ->
+ InitResult = {ok, []},
+ gen_server:start_link({global,server}, ?MODULE, InitResult, []).
+
+
+%%-------------------------------------------------------------------------
+%% Test that child and supervisor can be shutdown while hanging in restart loop.
+%% See OTP-9549.
+hanging_restart_loop(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ {ok, Pid} = start_link({ok, {{one_for_one, 8, 10}, []}}),
+ Child1 = {child1, {supervisor_deadlock, start_child, []},
+ permanent, brutal_kill, worker, []},
+
+ %% Ets table with state read by supervisor_deadlock.erl
+ ets:new(supervisor_deadlock,[set,named_table,public]),
+ ets:insert(supervisor_deadlock,{fail_start,false}),
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ link(CPid1),
+
+ ets:insert(supervisor_deadlock,{fail_start,true}),
+ supervisor_deadlock:restart_child(),
+ timer:sleep(2000), % allow restart to happen before proceeding
+
+ {error, already_present} = supervisor:start_child(sup_test, Child1),
+ {error, restarting} = supervisor:restart_child(sup_test, child1),
+ {error, restarting} = supervisor:delete_child(sup_test, child1),
+ [{child1,restarting,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test),
+
+ ok = supervisor:terminate_child(sup_test, child1),
+ check_exit_reason(CPid1, error),
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+
+ ets:insert(supervisor_deadlock,{fail_start,false}),
+ {ok, CPid2} = supervisor:restart_child(sup_test, child1),
+ link(CPid2),
+
+ ets:insert(supervisor_deadlock,{fail_start,true}),
+ supervisor_deadlock:restart_child(),
+ timer:sleep(2000), % allow restart to happen before proceeding
+
+ %% Terminating supervisor.
+ %% OTP-9549 fixes so this does not give a timetrap timeout -
+ %% i.e. that supervisor does not hang in restart loop.
+ terminate(Pid,shutdown),
+
+ %% Check that child died with reason from 'restart' request above
+ check_exit_reason(CPid2, error),
+ undefined = whereis(sup_test),
+ ok.
+
+%%-------------------------------------------------------------------------
+%% Test that child and supervisor can be shutdown while hanging in
+%% restart loop, simple_one_for_one.
+%% See OTP-9549.
+hanging_restart_loop_simple(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Child1 = {child1, {supervisor_deadlock, start_child, []},
+ permanent, brutal_kill, worker, []},
+ {ok, Pid} = start_link({ok, {{simple_one_for_one, 8, 10}, [Child1]}}),
+
+ %% Ets table with state read by supervisor_deadlock.erl
+ ets:new(supervisor_deadlock,[set,named_table,public]),
+ ets:insert(supervisor_deadlock,{fail_start,false}),
+
+ {ok, CPid1} = supervisor:start_child(sup_test, []),
+ link(CPid1),
+
+ ets:insert(supervisor_deadlock,{fail_start,true}),
+ supervisor_deadlock:restart_child(),
+ timer:sleep(2000), % allow restart to happen before proceeding
+
+ {error, simple_one_for_one} = supervisor:restart_child(sup_test, child1),
+ {error, simple_one_for_one} = supervisor:delete_child(sup_test, child1),
+ [{undefined,restarting,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test),
+
+ ok = supervisor:terminate_child(sup_test, CPid1),
+ check_exit_reason(CPid1, error),
+ [] = supervisor:which_children(sup_test),
+
+ ets:insert(supervisor_deadlock,{fail_start,false}),
+ {ok, CPid2} = supervisor:start_child(sup_test, []),
+ link(CPid2),
+
+ ets:insert(supervisor_deadlock,{fail_start,true}),
+ supervisor_deadlock:restart_child(),
+ timer:sleep(2000), % allow restart to happen before proceeding
+
+ %% Terminating supervisor.
+ %% OTP-9549 fixes so this does not give a timetrap timeout -
+ %% i.e. that supervisor does not hang in restart loop.
+ terminate(Pid,shutdown),
+
+ %% Check that child died with reason from 'restart' request above
+ check_exit_reason(CPid2, error),
+ undefined = whereis(sup_test),
+ ok.
%%-------------------------------------------------------------------------
terminate(Pid, Reason) when Reason =/= supervisor ->
diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl
index c4d696564d..b3056ff41a 100644
--- a/lib/stdlib/test/supervisor_bridge_SUITE.erl
+++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl
@@ -19,8 +19,9 @@
-module(supervisor_bridge_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,starting/1,
- mini_terminate/1,mini_die/1,badstart/1]).
--export([client/1,init/1,internal_loop_init/1,terminate/2]).
+ mini_terminate/1,mini_die/1,badstart/1,
+ simple_global_supervisor/1]).
+-export([client/1,init/1,internal_loop_init/1,terminate/2,server9212/0]).
-include_lib("test_server/include/test_server.hrl").
-define(bridge_name,supervisor_bridge_SUITE_server).
@@ -31,7 +32,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [starting, mini_terminate, mini_die, badstart].
+ [starting, mini_terminate, mini_die, badstart, simple_global_supervisor].
groups() ->
[].
@@ -138,7 +139,9 @@ init(3) ->
receive
{InternalPid,init_done} ->
{ok,InternalPid,self()}
- end.
+ end;
+init({4,Result}) ->
+ Result.
internal_loop_init(Parent) ->
register(?work_bridge_name, self()),
@@ -160,7 +163,9 @@ terminate(Reason,{Parent,Worker}) ->
io:format("Terminating bridge...\n"),
exit(Worker,kill),
Parent ! {dying,Reason},
- anything.
+ anything;
+terminate(_Reason, _State) ->
+ any.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -197,3 +202,30 @@ badstart(Config) when is_list(Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% OTP-9212. Restart of global supervisor.
+
+simple_global_supervisor(suite) -> [];
+simple_global_supervisor(doc) -> "Globally registered supervisor.";
+simple_global_supervisor(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap({seconds,10}),
+
+ Child = {child, {?MODULE,server9212,[]}, permanent, 2000, worker, []},
+ InitResult = {ok, {{one_for_all,3,60}, [Child]}},
+ {ok, Sup} =
+ supervisor:start_link({local,bridge9212}, ?MODULE, {4,InitResult}),
+
+ BN_1 = global:whereis_name(?bridge_name),
+ ?line exit(BN_1, kill),
+ timer:sleep(200),
+ BN_2 = global:whereis_name(?bridge_name),
+ ?line true = is_pid(BN_2),
+ ?line true = BN_1 =/= BN_2,
+
+ ?line process_flag(trap_exit, true),
+ exit(Sup, kill),
+ ?line receive {'EXIT', Sup, killed} -> ok end,
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+server9212() ->
+ supervisor_bridge:start_link({global,?bridge_name}, ?MODULE, 3).
diff --git a/lib/stdlib/test/supervisor_deadlock.erl b/lib/stdlib/test/supervisor_deadlock.erl
new file mode 100644
index 0000000000..288547a972
--- /dev/null
+++ b/lib/stdlib/test/supervisor_deadlock.erl
@@ -0,0 +1,45 @@
+-module(supervisor_deadlock).
+-compile(export_all).
+
+
+%%%-----------------------------------------------------------------
+%%% gen_server callbacks
+init([child]) ->
+ case ets:lookup(supervisor_deadlock,fail_start) of
+ [{fail_start, false}] ->
+ %% we must not fail on the first init, otherwise supervisor
+ %% terminates immediately
+ {ok, []};
+ [{fail_start, true}] ->
+ %% Restart frequency is MaxR=8, MaxT=10, so this will
+ %% ensure that restart intensity is not reached -> restart
+ %% loop
+ timer:sleep(2000), % NOTE: this could be a gen_server call timeout
+
+ {stop, error}
+ end.
+
+handle_call(_Req, _From, State) ->
+ {reply, ok, State}.
+
+%% Force a restart
+handle_cast(restart, State) ->
+ {stop, error, State}.
+
+handle_info(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% Start child
+start_child() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [child], []).
+
+restart_child() ->
+ gen_server:cast(supervisor_deadlock, restart).
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index 9ad3936928..5bc34e35af 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -533,7 +533,7 @@ symlinks(Config) when is_list(Config) ->
?line ok = file:make_dir(Dir),
?line ABadSymlink = filename:join(Dir, "bad_symlink"),
?line PointsTo = "/a/definitely/non_existing/path",
- ?line Res = case file:make_symlink("/a/definitely/non_existing/path", ABadSymlink) of
+ ?line Res = case make_symlink("/a/definitely/non_existing/path", ABadSymlink) of
{error, enotsup} ->
{skip, "Symbolic links not supported on this platform"};
ok ->
@@ -544,7 +544,30 @@ symlinks(Config) when is_list(Config) ->
%% Clean up.
?line delete_files([Dir]),
Res.
-
+
+make_symlink(Path, Link) ->
+ case os:type() of
+ {win32,_} ->
+ %% Symlinks on Windows have two problems:
+ %% 1) file:read_link_info/1 cannot read out the target
+ %% of the symlink if the target does not exist.
+ %% That is possible (but not easy) to fix in the
+ %% efile driver.
+ %%
+ %% 2) Symlinks to files and directories are different
+ %% creatures. If the target is not existing, the
+ %% symlink will be created to be of the file-pointing
+ %% type. That can be partially worked around in erl_tar
+ %% by creating all symlinks when the end of the tar
+ %% file has been reached.
+ %%
+ %% But for now, pretend that there are no symlinks on
+ %% Windows.
+ {error, enotsup};
+ _ ->
+ file:make_symlink(Path, Link)
+ end.
+
symlinks(Dir, BadSymlink, PointsTo) ->
?line Tar = filename:join(Dir, "symlink.tar"),
?line DerefTar = filename:join(Dir, "dereference.tar"),
@@ -743,9 +766,9 @@ run_in_short_tempdir(Config, Fun) ->
%% 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
+ %% in. That fact is not documented, but a usually reliable source
%% assured me that the directory structure is unlikely to change
- %% in future versions of common_test because of backward
+ %% in future versions of common_test because of backwards
%% compatibility (tools developed by users of common_test depend
%% on the current directory layout).
Base = lists:foldl(fun(_, D) ->
diff --git a/lib/stdlib/test/unicode_SUITE.erl b/lib/stdlib/test/unicode_SUITE.erl
index 9aa800209d..4055af2741 100644
--- a/lib/stdlib/test/unicode_SUITE.erl
+++ b/lib/stdlib/test/unicode_SUITE.erl
@@ -322,7 +322,7 @@ roundtrips(Config) when is_list(Config) ->
ex_roundtrips(Config) when is_list(Config) ->
?line L1 = ranges(0, 16#D800 - 1,
erlang:system_info(context_reductions) * 11),
- ?line L2 = ranges(16#DFFF + 1, 16#FFFE - 1,
+ ?line L2 = ranges(16#DFFF + 1, 16#10000 - 1,
erlang:system_info(context_reductions) * 11),
%?line L3 = ranges(16#FFFF + 1, 16#10FFFF,
% erlang:system_info(context_reductions) * 11),
@@ -569,7 +569,6 @@ utf16_illegal_sequences_bif(Config) when is_list(Config) ->
ex_utf16_illegal_sequences_bif(Config) when is_list(Config) ->
?line utf16_fail_range_bif_simple(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line utf16_fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf16_fail_range_bif(16#FFFE, 16#FFFF), %Non-characters.
?line lonely_hi_surrogate_bif(16#D800, 16#DBFF,incomplete),
?line lonely_hi_surrogate_bif(16#DC00, 16#DFFF,error),
@@ -644,7 +643,6 @@ utf8_illegal_sequences_bif(Config) when is_list(Config) ->
ex_utf8_illegal_sequences_bif(Config) when is_list(Config) ->
?line fail_range_bif(16#10FFFF+1, 16#10FFFF+512), %Too large.
?line fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line fail_range_bif(16#FFFE, 16#FFFF), %Reserved (BOM).
%% Illegal first character.
?line [fail_bif(<<I,16#8F,16#8F,16#8F>>,unicode) || I <- lists:seq(16#80, 16#BF)],
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 2f0ecd3863..3df7495ec4 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.18
+STDLIB_VSN = 1.18.2
diff --git a/lib/syntax_tools/doc/Makefile b/lib/syntax_tools/doc/Makefile
index 6afd16f669..d9981de880 100644
--- a/lib/syntax_tools/doc/Makefile
+++ b/lib/syntax_tools/doc/Makefile
@@ -78,12 +78,3 @@ release_docs_spec: docs
release_spec:
-
-
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-#-include make.dep
-
-
diff --git a/lib/syntax_tools/doc/overview.edoc b/lib/syntax_tools/doc/overview.edoc
index 23eadce8fe..df02ad0b3a 100644
--- a/lib/syntax_tools/doc/overview.edoc
+++ b/lib/syntax_tools/doc/overview.edoc
@@ -1,5 +1,9 @@
+ -*- html -*-
-@author Richard Carlsson <[email protected]>
+ Syntax Tools overview page
+
+
+@author Richard Carlsson <[email protected]>
@copyright 1997-2004 Richard Carlsson
@version {@version}
@title Erlang Syntax Tools
diff --git a/lib/syntax_tools/doc/src/Makefile b/lib/syntax_tools/doc/src/Makefile
index 291b3e3047..d1c6989bd9 100644
--- a/lib/syntax_tools/doc/src/Makefile
+++ b/lib/syntax_tools/doc/src/Makefile
@@ -125,13 +125,13 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/syntax_tools/doc/src/make.dep b/lib/syntax_tools/doc/src/make.dep
deleted file mode 100644
index acc76857bb..0000000000
--- a/lib/syntax_tools/doc/src/make.dep
+++ /dev/null
@@ -1,22 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex epp_dodger.tex erl_comment_scan.tex \
- erl_prettypr.tex erl_recomment.tex erl_syntax.tex \
- erl_syntax_lib.tex erl_tidy.tex igor.tex part.tex \
- prettypr.tex ref_man.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index 5948f7ada3..434a3e721e 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -31,6 +31,53 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 1.6.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Minor suppressions and fixes of compilation
+ warnings</p>
+ <p>
+ Own Id: OTP-10016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 1.6.7.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Variables are now now allowed in '<c>fun M:F/A</c>' as
+ suggested by Richard O'Keefe in EEP-23.</p>
+ <p>The representation of '<c>fun M:F/A</c>' in the
+ abstract format has been changed in an incompatible way.
+ Tools that directly read or manipulate the abstract
+ format (such as parse transforms) may need to be updated.
+ The compiler can handle both the new and the old format
+ (i.e. extracting the abstract format from a pre-R15 BEAM
+ file and compiling it using compile:forms/1,2 will work).
+ The <c>syntax_tools</c> application can also handle both
+ formats.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9643</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 1.6.7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/syntax_tools/examples/Makefile b/lib/syntax_tools/examples/Makefile
index 7cfe9185c2..2724b0899b 100644
--- a/lib/syntax_tools/examples/Makefile
+++ b/lib/syntax_tools/examples/Makefile
@@ -49,8 +49,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(EXAMPLE_FILES) "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile
index 50369e633e..dca5e78be9 100644
--- a/lib/syntax_tools/src/Makefile
+++ b/lib/syntax_tools/src/Makefile
@@ -26,7 +26,7 @@ EBIN = ../ebin
ifeq ($(NATIVE_LIBS_ENABLED),yes)
ERL_COMPILE_FLAGS += +native
endif
-ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import # +warn_missing_spec +warn_untyped_record
SOURCES=erl_syntax.erl erl_prettypr.erl erl_syntax_lib.erl \
erl_comment_scan.erl erl_recomment.erl erl_tidy.erl \
@@ -80,10 +80,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(OBJECTS) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(SOURCES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(OBJECTS) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(SOURCES) "$(RELSYSDIR)/src"
release_docs_spec:
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index 9f6f7d815e..b3ced34c14 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2001-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl
index 108ab3bffd..b833e1c069 100644
--- a/lib/syntax_tools/src/erl_comment_scan.erl
+++ b/lib/syntax_tools/src/erl_comment_scan.erl
@@ -16,7 +16,7 @@
%%
%% =====================================================================
%% @copyright 1997-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index 7caf0b3db6..f4bbf975c3 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 1997-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl
index fc7c515700..7b2f9f7adb 100644
--- a/lib/syntax_tools/src/erl_recomment.erl
+++ b/lib/syntax_tools/src/erl_recomment.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 1997-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 9df5f26454..76a6a6dc36 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 1997-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
@@ -26,23 +24,20 @@
%% This module defines an abstract data type for representing Erlang
%% source code as syntax trees, in a way that is backwards compatible
%% with the data structures created by the Erlang standard library
-%% parser module <code>erl_parse</code> (often referred to as "parse
+%% parser module `erl_parse' (often referred to as "parse
%% trees", which is a bit of a misnomer). This means that all
-%% <code>erl_parse</code> trees are valid abstract syntax trees, but the
+%% `erl_parse' trees are valid abstract syntax trees, but the
%% reverse is not true: abstract syntax trees can in general not be used
-%% as input to functions expecting an <code>erl_parse</code> tree.
+%% as input to functions expecting an `erl_parse' tree.
%% However, as long as an abstract syntax tree represents a correct
-%% Erlang program, the function <a
-%% href="#revert-1"><code>revert/1</code></a> should be able to
-%% transform it to the corresponding <code>erl_parse</code>
+%% Erlang program, the function {@link revert/1} should be able to
+%% transform it to the corresponding `erl_parse'
%% representation.
%%
-%% A recommended starting point for the first-time user is the
-%% documentation of the <a
-%% href="#type-syntaxTree"><code>syntaxTree()</code></a> data type, and
-%% the function <a href="#type-1"><code>type/1</code></a>.
+%% A recommended starting point for the first-time user is the documentation
+%% of the {@link syntaxTree()} data type, and the function {@link type/1}.
%%
-%% <h3><b>NOTES:</b></h3>
+%% == NOTES: ==
%%
%% This module deals with the composition and decomposition of
%% <em>syntactic</em> entities (as opposed to semantic ones); its
@@ -52,36 +47,31 @@
%% in general, the user is assumed to pass type-correct arguments - if
%% this is not done, the effects are not defined.
%%
-%% With the exception of the <code>erl_parse</code> data structures,
+%% With the exception of the {@link erl_parse()} data structures,
%% 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
+%% as `none', by a list constructor `[X | Y]', or
+%% by the empty list `[]'. This can be relied on when writing
%% functions that operate on syntax trees.
-%% @type syntaxTree(). An abstract syntax tree. The
-%% <code>erl_parse</code> "parse tree" representation is a subset of the
-%% <code>syntaxTree()</code> representation.
+%% @type syntaxTree(). An abstract syntax tree. The {@link erl_parse()}
+%% "parse tree" representation is a proper subset of the `syntaxTree()'
+%% representation.
%%
%% Every abstract syntax tree node has a <em>type</em>, given by the
-%% function <a href="#type-1"><code>type/1</code></a>. Each node also
-%% has associated <em>attributes</em>; see <a
-%% href="#get_attrs-1"><code>get_attrs/1</code></a> for details. The
-%% functions <a href="#make_tree-2"><code>make_tree/2</code></a> and <a
-%% href="#subtrees-1"><code>subtrees/1</code></a> are generic
+%% function {@link type/1}. Each node also has associated
+%% <em>attributes</em>; see {@link get_attrs/1} for details. The functions
+%% {@link make_tree/2} and {@link subtrees/1} are generic
%% constructor/decomposition functions for abstract syntax trees. The
-%% functions <a href="#abstract-1"><code>abstract/1</code></a> and <a
-%% href="#concrete-1"><code>concrete/1</code></a> convert between
+%% functions {@link abstract/1} and {@link concrete/1} convert between
%% constant Erlang terms and their syntactic representations. The set of
-%% syntax tree nodes is extensible through the <a
-%% href="#tree-2"><code>tree/2</code></a> function.
+%% syntax tree nodes is extensible through the {@link tree/2} function.
%%
-%% A syntax tree can be transformed to the <code>erl_parse</code>
-%% representation with the <a href="#revert-1"><code>revert/1</code></a>
-%% function.
+%% A syntax tree can be transformed to the {@link erl_parse()}
+%% representation with the {@link revert/1} function.
-module(erl_syntax).
@@ -309,7 +299,7 @@
data/1,
is_tree/1]).
--export_type([forms/0, syntaxTree/0, syntaxTreeAttributes/0]).
+-export_type([forms/0, syntaxTree/0, syntaxTreeAttributes/0, padding/0]).
%% =====================================================================
%% IMPLEMENTATION NOTES:
@@ -390,11 +380,15 @@
-record(wrapper, {type :: atom(),
attr = #attr{} :: #attr{},
- tree :: term()}).
+ tree :: erl_parse()}).
%% =====================================================================
--type syntaxTree() :: #tree{} | #wrapper{} | tuple(). % XXX: refine
+-type syntaxTree() :: #tree{} | #wrapper{} | erl_parse().
+
+-type erl_parse() :: erl_parse:abstract_form() | erl_parse:abstract_expr().
+%% The representation built by the Erlang standard library parser
+%% `erl_parse'. This is a subset of the {@link syntaxTree()} type.
%% =====================================================================
%%
@@ -404,12 +398,11 @@
%% =====================================================================
-%% @spec type(Node::syntaxTree()) -> atom()
-%%
-%% @doc Returns the type tag of <code>Node</code>. If <code>Node</code>
+%% @doc Returns the type tag of `Node'. If `Node'
%% does not represent a syntax tree, evaluation fails with reason
-%% <code>badarg</code>. Node types currently defined by this module are:
-%% <p><center><table border="1">
+%% `badarg'. Node types currently defined by this module are:
+%%
+%% <center><table border="1">
%% <tr>
%% <td>application</td>
%% <td>arity_qualifier</td>
@@ -476,12 +469,13 @@
%% <td>variable</td>
%% <td>warning_marker</td>
%% </tr>
-%% </table></center></p>
-%% <p>The user may (for special purposes) create additional nodes
-%% with other type tags, using the <code>tree/2</code> function.</p>
+%% </table></center>
+%%
+%% The user may (for special purposes) create additional nodes
+%% with other type tags, using the {@link tree/2} function.
%%
-%% <p>Note: The primary constructor functions for a node type should
-%% always have the same name as the node type itself.</p>
+%% Note: The primary constructor functions for a node type should
+%% always have the same name as the node type itself.
%%
%% @see tree/2
%% @see application/3
@@ -606,39 +600,38 @@ type(Node) ->
%% =====================================================================
-%% @spec is_leaf(Node::syntaxTree()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is a leaf node,
-%% otherwise <code>false</code>. The currently recognised leaf node
+%% @doc Returns `true' if `Node' is a leaf node,
+%% otherwise `false'. The currently recognised leaf node
%% types are:
-%% <p><center><table border="1">
+%%
+%% <center><table border="1">
%% <tr>
-%% <td><code>atom</code></td>
-%% <td><code>char</code></td>
-%% <td><code>comment</code></td>
-%% <td><code>eof_marker</code></td>
-%% <td><code>error_marker</code></td>
+%% <td>`atom'</td>
+%% <td>`char'</td>
+%% <td>`comment'</td>
+%% <td>`eof_marker'</td>
+%% <td>`error_marker'</td>
%% </tr><tr>
-%% <td><code>float</code></td>
-%% <td><code>integer</code></td>
-%% <td><code>nil</code></td>
-%% <td><code>operator</code></td>
-%% <td><code>string</code></td>
+%% <td>`float'</td>
+%% <td>`integer'</td>
+%% <td>`nil'</td>
+%% <td>`operator'</td>
+%% <td>`string'</td>
%% </tr><tr>
-%% <td><code>text</code></td>
-%% <td><code>underscore</code></td>
-%% <td><code>variable</code></td>
-%% <td><code>warning_marker</code></td>
+%% <td>`text'</td>
+%% <td>`underscore'</td>
+%% <td>`variable'</td>
+%% <td>`warning_marker'</td>
%% </tr>
-%% </table></center></p>
-%% <p>A node of type <code>tuple</code> is a leaf node if and only if
-%% its arity is zero.</p>
+%% </table></center>
%%
-%% <p>Note: not all literals are leaf nodes, and vice versa. E.g.,
+%% A node of type `tuple' is a leaf node if and only if its arity is zero.
+%%
+%% Note: not all literals are leaf nodes, and vice versa. E.g.,
%% tuples with nonzero arity and nonempty lists may be literals, but are
%% not leaf nodes. Variables, on the other hand, are leaf nodes but not
-%% literals.</p>
-%%
+%% literals.
+%%
%% @see type/1
%% @see is_literal/1
@@ -666,29 +659,29 @@ is_leaf(Node) ->
%% =====================================================================
-%% @spec is_form(Node::syntaxTree()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is a syntax tree
+%% @doc Returns `true' if `Node' is a syntax tree
%% representing a so-called "source code form", otherwise
-%% <code>false</code>. Forms are the Erlang source code units which,
+%% `false'. Forms are the Erlang source code units which,
%% placed in sequence, constitute an Erlang program. Current form types
%% are:
-%% <p><center><table border="1">
+%%
+%% <center><table border="1">
%% <tr>
-%% <td><code>attribute</code></td>
-%% <td><code>comment</code></td>
-%% <td><code>error_marker</code></td>
-%% <td><code>eof_marker</code></td>
-%% <td><code>form_list</code></td>
+%% <td>`attribute'</td>
+%% <td>`comment'</td>
+%% <td>`error_marker'</td>
+%% <td>`eof_marker'</td>
+%% <td>`form_list'</td>
%% </tr><tr>
-%% <td><code>function</code></td>
-%% <td><code>rule</code></td>
-%% <td><code>warning_marker</code></td>
-%% <td><code>text</code></td>
+%% <td>`function'</td>
+%% <td>`rule'</td>
+%% <td>`warning_marker'</td>
+%% <td>`text'</td>
%% </tr>
-%% </table></center></p>
+%% </table></center>
+%%
%% @see type/1
-%% @see attribute/2
+%% @see attribute/2
%% @see comment/2
%% @see eof_marker/0
%% @see error_marker/1
@@ -715,10 +708,8 @@ is_form(Node) ->
%% =====================================================================
-%% @spec get_pos(Node::syntaxTree()) -> term()
-%%
%% @doc Returns the position information associated with
-%% <code>Node</code>. This is usually a nonnegative integer (indicating
+%% `Node'. This is usually a nonnegative integer (indicating
%% the source code line number), but may be any term. By default, all
%% new tree nodes have their associated position information set to the
%% integer zero.
@@ -750,10 +741,7 @@ get_pos(Node) ->
%% =====================================================================
-%% @spec set_pos(Node::syntaxTree(), Pos::term()) -> syntaxTree()
-%%
-%% @doc Sets the position information of <code>Node</code> to
-%% <code>Pos</code>.
+%% @doc Sets the position information of `Node' to `Pos'.
%%
%% @see get_pos/1
%% @see copy_pos/2
@@ -774,14 +762,10 @@ set_pos(Node, Pos) ->
%% =====================================================================
-%% @spec copy_pos(Source::syntaxTree(), Target::syntaxTree()) ->
-%% syntaxTree()
-%%
-%% @doc Copies the position information from <code>Source</code> to
-%% <code>Target</code>.
+%% @doc Copies the position information from `Source' to `Target'.
%%
-%% <p>This is equivalent to <code>set_pos(Target,
-%% get_pos(Source))</code>, but potentially more efficient.</p>
+%% This is equivalent to `set_pos(Target,
+%% get_pos(Source))', but potentially more efficient.
%%
%% @see get_pos/1
%% @see set_pos/2
@@ -811,24 +795,20 @@ set_com(Node, Com) ->
%% =====================================================================
-%% @spec get_precomments(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the associated pre-comments of a node. This is a
%% possibly empty list of abstract comments, in top-down textual order.
%% When the code is formatted, pre-comments are typically displayed
%% directly above the node. For example:
-%% <pre>
-%% % Pre-comment of function
-%% foo(X) -> {bar, X}.</pre>
+%% ```% Pre-comment of function
+%% foo(X) -> {bar, X}.'''
%%
-%% <p>If possible, the comment should be moved before any preceding
+%% If possible, the comment should be moved before any preceding
%% separator characters on the same line. E.g.:
-%% <pre>
-%% foo([X | Xs]) ->
-%% % Pre-comment of 'bar(X)' node
-%% [bar(X) | foo(Xs)];
-%% ...</pre>
-%% (where the comment is moved before the "<code>[</code>").</p>
+%% ```foo([X | Xs]) ->
+%% % Pre-comment of 'bar(X)' node
+%% [bar(X) | foo(Xs)];
+%% ...'''
+%% (where the comment is moved before the "`['").
%%
%% @see comment/2
%% @see set_precomments/2
@@ -846,11 +826,8 @@ get_precomments_1(#attr{com = #com{pre = Cs}}) -> Cs.
%% =====================================================================
-%% @spec set_precomments(Node::syntaxTree(),
-%% Comments::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Sets the pre-comments of <code>Node</code> to
-%% <code>Comments</code>. <code>Comments</code> should be a possibly
+%% @doc Sets the pre-comments of `Node' to
+%% `Comments'. `Comments' should be a possibly
%% empty list of abstract comments, in top-down textual order.
%%
%% @see comment/2
@@ -880,15 +857,11 @@ set_precomments_1(#attr{com = Com} = Attr, Cs) ->
%% =====================================================================
-%% @spec add_precomments(Comments::[syntaxTree()],
-%% Node::syntaxTree()) -> syntaxTree()
+%% @doc Appends `Comments' to the pre-comments of `Node'.
%%
-%% @doc Appends <code>Comments</code> to the pre-comments of
-%% <code>Node</code>.
-%%
-%% <p>Note: This is equivalent to <code>set_precomments(Node,
-%% get_precomments(Node) ++ Comments)</code>, but potentially more
-%% efficient.</p>
+%% Note: This is equivalent to `set_precomments(Node,
+%% get_precomments(Node) ++ Comments)', but potentially more
+%% efficient.
%%
%% @see comment/2
%% @see get_precomments/1
@@ -915,24 +888,20 @@ add_precomments_1(Cs, #attr{com = Com} = Attr) ->
%% =====================================================================
-%% @spec get_postcomments(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the associated post-comments of a node. This is a
%% possibly empty list of abstract comments, in top-down textual order.
%% When the code is formatted, post-comments are typically displayed to
%% the right of and/or below the node. For example:
-%% <pre>
-%% {foo, X, Y} % Post-comment of tuple</pre>
+%% ```{foo, X, Y} % Post-comment of tuple'''
%%
-%% <p>If possible, the comment should be moved past any following
+%% If possible, the comment should be moved past any following
%% separator characters on the same line, rather than placing the
%% separators on the following line. E.g.:
-%% <pre>
-%% foo([X | Xs], Y) ->
-%% foo(Xs, bar(X)); % Post-comment of 'bar(X)' node
-%% ...</pre>
-%% (where the comment is moved past the rightmost "<code>)</code>" and
-%% the "<code>;</code>").</p>
+%% ```foo([X | Xs], Y) ->
+%% foo(Xs, bar(X)); % Post-comment of 'bar(X)' node
+%% ...'''
+%% (where the comment is moved past the rightmost "`)'" and
+%% the "`;'").
%%
%% @see comment/2
%% @see set_postcomments/2
@@ -950,11 +919,8 @@ get_postcomments_1(#attr{com = #com{post = Cs}}) -> Cs.
%% =====================================================================
-%% @spec set_postcomments(Node::syntaxTree(),
-%% Comments::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Sets the post-comments of <code>Node</code> to
-%% <code>Comments</code>. <code>Comments</code> should be a possibly
+%% @doc Sets the post-comments of `Node' to
+%% `Comments'. `Comments' should be a possibly
%% empty list of abstract comments, in top-down textual order
%%
%% @see comment/2
@@ -984,15 +950,11 @@ set_postcomments_1(#attr{com = Com} = Attr, Cs) ->
%% =====================================================================
-%% @spec add_postcomments(Comments::[syntaxTree()],
-%% Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Appends <code>Comments</code> to the post-comments of
-%% <code>Node</code>.
+%% @doc Appends `Comments' to the post-comments of `Node'.
%%
-%% <p>Note: This is equivalent to <code>set_postcomments(Node,
-%% get_postcomments(Node) ++ Comments)</code>, but potentially more
-%% efficient.</p>
+%% Note: This is equivalent to `set_postcomments(Node,
+%% get_postcomments(Node) ++ Comments)', but potentially more
+%% efficient.
%%
%% @see comment/2
%% @see get_postcomments/1
@@ -1019,14 +981,12 @@ add_postcomments_1(Cs, #attr{com = Com} = Attr) ->
%% =====================================================================
-%% @spec has_comments(Node::syntaxTree()) -> boolean()
+%% @doc Yields `false' if the node has no associated
+%% comments, and `true' otherwise.
%%
-%% @doc Yields <code>false</code> if the node has no associated
-%% comments, and <code>true</code> otherwise.
-%%
-%% <p>Note: This is equivalent to <code>(get_precomments(Node) == [])
-%% and (get_postcomments(Node) == [])</code>, but potentially more
-%% efficient.</p>
+%% Note: This is equivalent to `(get_precomments(Node) == [])
+%% and (get_postcomments(Node) == [])', but potentially more
+%% efficient.
%%
%% @see get_precomments/1
%% @see get_postcomments/1
@@ -1050,13 +1010,11 @@ has_comments(_) -> false.
%% =====================================================================
-%% @spec remove_comments(Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Clears the associated comments of <code>Node</code>.
+%% @doc Clears the associated comments of `Node'.
%%
-%% <p>Note: This is equivalent to
-%% <code>set_precomments(set_postcomments(Node, []), [])</code>, but
-%% potentially more efficient.</p>
+%% Note: This is equivalent to
+%% `set_precomments(set_postcomments(Node, []), [])', but
+%% potentially more efficient.
%%
%% @see set_precomments/2
%% @see set_postcomments/2
@@ -1075,16 +1033,12 @@ remove_comments(Node) ->
%% =====================================================================
-%% @spec copy_comments(Source::syntaxTree(), Target::syntaxTree()) ->
-%% syntaxTree()
-%%
-%% @doc Copies the pre- and postcomments from <code>Source</code> to
-%% <code>Target</code>.
+%% @doc Copies the pre- and postcomments from `Source' to `Target'.
%%
-%% <p>Note: This is equivalent to
-%% <code>set_postcomments(set_precomments(Target,
-%% get_precomments(Source)), get_postcomments(Source))</code>, but
-%% potentially more efficient.</p>
+%% Note: This is equivalent to
+%% `set_postcomments(set_precomments(Target,
+%% get_precomments(Source)), get_postcomments(Source))', but
+%% potentially more efficient.
%%
%% @see comment/2
%% @see get_precomments/1
@@ -1099,16 +1053,13 @@ copy_comments(Source, Target) ->
%% =====================================================================
-%% @spec join_comments(Source::syntaxTree(), Target::syntaxTree()) ->
-%% syntaxTree()
+%% @doc Appends the comments of `Source' to the current
+%% comments of `Target'.
%%
-%% @doc Appends the comments of <code>Source</code> to the current
-%% comments of <code>Target</code>.
-%%
-%% <p>Note: This is equivalent to
-%% <code>add_postcomments(get_postcomments(Source),
-%% add_precomments(get_precomments(Source), Target))</code>, but
-%% potentially more efficient.</p>
+%% Note: This is equivalent to
+%% `add_postcomments(get_postcomments(Source),
+%% add_precomments(get_precomments(Source), Target))', but
+%% potentially more efficient.
%%
%% @see comment/2
%% @see get_precomments/1
@@ -1125,8 +1076,6 @@ join_comments(Source, Target) ->
%% =====================================================================
-%% @spec get_ann(syntaxTree()) -> [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.
@@ -1142,11 +1091,7 @@ get_ann(_) -> [].
%% =====================================================================
-%% @spec set_ann(Node::syntaxTree(), Annotations::[term()]) ->
-%% syntaxTree()
-%%
-%% @doc Sets the list of user annotations of <code>Node</code> to
-%% <code>Annotations</code>.
+%% @doc Sets the list of user annotations of `Node' to `Annotations'.
%%
%% @see get_ann/1
%% @see add_ann/2
@@ -1168,13 +1113,11 @@ set_ann(Node, As) ->
%% =====================================================================
-%% @spec add_ann(Annotation::term(), Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Appends the term <code>Annotation</code> to the list of user
-%% annotations of <code>Node</code>.
+%% @doc Appends the term `Annotation' to the list of user
+%% annotations of `Node'.
%%
-%% <p>Note: this is equivalent to <code>set_ann(Node, [Annotation |
-%% get_ann(Node)])</code>, but potentially more efficient.</p>
+%% Note: this is equivalent to `set_ann(Node, [Annotation |
+%% get_ann(Node)])', but potentially more efficient.
%%
%% @see get_ann/1
%% @see set_ann/2
@@ -1195,14 +1138,10 @@ add_ann(A, Node) ->
%% =====================================================================
-%% @spec copy_ann(Source::syntaxTree(), Target::syntaxTree()) ->
-%% syntaxTree()
+%% @doc Copies the list of user annotations from `Source' to `Target'.
%%
-%% @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>
+%% Note: this is equivalent to `set_ann(Target,
+%% get_ann(Source))', but potentially more efficient.
%%
%% @see get_ann/1
%% @see set_ann/2
@@ -1214,23 +1153,20 @@ copy_ann(Source, Target) ->
%% =====================================================================
-%% @spec get_attrs(syntaxTree()) -> syntaxTreeAttributes()
-%%
%% @doc Returns a representation of the attributes associated with a
%% syntax tree node. The attributes are all the extra information that
%% can be attached to a node. Currently, this includes position
%% information, source code comments, and user annotations. The result
%% of this function cannot be inspected directly; only attached to
-%% another node (cf. <code>set_attrs/2</code>).
+%% another node (see {@link set_attrs/2}).
%%
-%% <p>For accessing individual attributes, see <code>get_pos/1</code>,
-%% <code>get_ann/1</code>, <code>get_precomments/1</code> and
-%% <code>get_postcomments/1</code>.</p>
+%% For accessing individual attributes, see {@link get_pos/1},
+%% {@link get_ann/1}, {@link get_precomments/1} and
+%% {@link get_postcomments/1}.
%%
%% @type syntaxTreeAttributes(). This is an abstract representation of
-%% syntax tree node attributes; see the function <a
-%% href="#get_attrs-1"><code>get_attrs/1</code></a>.
-%%
+%% syntax tree node attributes; see the function {@link get_attrs/1}.
+%%
%% @see set_attrs/2
%% @see get_pos/1
%% @see get_ann/1
@@ -1247,11 +1183,7 @@ get_attrs(Node) -> #attr{pos = get_pos(Node),
%% =====================================================================
-%% @spec set_attrs(Node::syntaxTree(),
-%% Attributes::syntaxTreeAttributes()) -> syntaxTree()
-%%
-%% @doc Sets the attributes of <code>Node</code> to
-%% <code>Attributes</code>.
+%% @doc Sets the attributes of `Node' to `Attributes'.
%%
%% @see get_attrs/1
%% @see copy_attrs/2
@@ -1270,14 +1202,10 @@ set_attrs(Node, Attr) ->
%% =====================================================================
-%% @spec copy_attrs(Source::syntaxTree(), Target::syntaxTree()) ->
-%% syntaxTree()
+%% @doc Copies the attributes from `Source' to `Target'.
%%
-%% @doc Copies the attributes from <code>Source</code> to
-%% <code>Target</code>.
-%%
-%% <p>Note: this is equivalent to <code>set_attrs(Target,
-%% get_attrs(Source))</code>, but potentially more efficient.</p>
+%% Note: this is equivalent to `set_attrs(Target,
+%% get_attrs(Source))', but potentially more efficient.
%%
%% @see get_attrs/1
%% @see set_attrs/2
@@ -1289,7 +1217,6 @@ copy_attrs(S, T) ->
%% =====================================================================
-%% @spec comment(Strings) -> syntaxTree()
%% @equiv comment(none, Strings)
-spec comment([string()]) -> syntaxTree().
@@ -1299,22 +1226,19 @@ comment(Strings) ->
%% =====================================================================
-%% @spec comment(Padding, Strings::[string()]) -> syntaxTree()
-%% Padding = none | integer()
-%%
%% @doc Creates an abstract comment with the given padding and text. If
-%% <code>Strings</code> is a (possibly empty) list
+%% `Strings' is a (possibly empty) list
%% <code>["<em>Txt1</em>", ..., "<em>TxtN</em>"]</code>, the result
%% represents the source code text
%% <pre>
-%% %<em>Txt1</em>
-%% ...
-%% %<em>TxtN</em></pre>
-%% <code>Padding</code> states the number of empty character positions
+%% %<em>Txt1</em>
+%% ...
+%% %<em>TxtN</em></pre>
+%% `Padding' states the number of empty character positions
%% to the left of the comment separating it horizontally from
-%% source code on the same line (if any). If <code>Padding</code> is
-%% <code>none</code>, a default positive number is used. If
-%% <code>Padding</code> is an integer less than 1, there should be no
+%% source code on the same line (if any). If `Padding' is
+%% `none', a default positive number is used. If
+%% `Padding' is an integer less than 1, there should be no
%% separating space. Comments are in themselves regarded as source
%% program forms.
%%
@@ -1338,8 +1262,6 @@ comment(Pad, Strings) ->
%% =====================================================================
-%% @spec comment_text(syntaxTree()) -> [string()]
-%%
%% @doc Returns the lines of text of the abstract comment.
%%
%% @see comment/2
@@ -1351,11 +1273,8 @@ comment_text(Node) ->
%% =====================================================================
-%% @spec comment_padding(syntaxTree()) -> none | integer()
-%%
%% @doc Returns the amount of padding before the comment, or
-%% <code>none</code>. The latter means that a default padding may be
-%% used.
+%% `none'. The latter means that a default padding may be used.
%%
%% @see comment/2
@@ -1366,23 +1285,21 @@ comment_padding(Node) ->
%% =====================================================================
-%% @spec form_list(Forms::[syntaxTree()]) -> syntaxTree()
-%%
%% @doc Creates an abstract sequence of "source code forms". If
-%% <code>Forms</code> is <code>[F1, ..., Fn]</code>, where each
-%% <code>Fi</code> is a form (cf. <code>is_form/1</code>, the result
+%% `Forms' is `[F1, ..., Fn]', where each
+%% `Fi' is a form (see {@link is_form/1}, the result
%% represents
%% <pre>
-%% <em>F1</em>
-%% ...
-%% <em>Fn</em></pre>
-%% where the <code>Fi</code> are separated by one or more line breaks. A
-%% node of type <code>form_list</code> is itself regarded as a source
-%% code form; cf. <code>flatten_form_list/1</code>.
-%%
-%% <p>Note: this is simply a way of grouping source code forms as a
+%% <em>F1</em>
+%% ...
+%% <em>Fn</em></pre>
+%% where the `Fi' are separated by one or more line breaks. A
+%% node of type `form_list' is itself regarded as a source
+%% code form; see {@link flatten_form_list/1}.
+%%
+%% Note: this is simply a way of grouping source code forms as a
%% single syntax tree, usually in order to form an Erlang module
-%% definition.</p>
+%% definition.
%%
%% @see form_list_elements/1
%% @see is_form/1
@@ -1401,9 +1318,7 @@ form_list(Forms) ->
%% =====================================================================
-%% @spec form_list_elements(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of subnodes of a <code>form_list</code> node.
+%% @doc Returns the list of subnodes of a `form_list' node.
%%
%% @see form_list/1
@@ -1414,10 +1329,8 @@ form_list_elements(Node) ->
%% =====================================================================
-%% @spec flatten_form_list(Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Flattens sublists of a <code>form_list</code> node. Returns
-%% <code>Node</code> with all subtrees of type <code>form_list</code>
+%% @doc Flattens sublists of a `form_list' node. Returns
+%% `Node' with all subtrees of type `form_list'
%% recursively expanded, yielding a single "flat" abstract form
%% sequence.
%%
@@ -1443,10 +1356,8 @@ flatten_form_list_1([], As) ->
%% =====================================================================
-%% @spec text(String::string()) -> syntaxTree()
-%%
%% @doc Creates an abstract piece of source code text. The result
-%% represents exactly the sequence of characters in <code>String</code>.
+%% represents exactly the sequence of characters in `String'.
%% This is useful in cases when one wants full control of the resulting
%% output, e.g., for the appearance of floating-point numbers or macro
%% definitions.
@@ -1463,10 +1374,7 @@ text(String) ->
%% =====================================================================
-%% @spec text_string(syntaxTree()) -> string()
-%%
-%% @doc Returns the character sequence represented by a
-%% <code>text</code> node.
+%% @doc Returns the character sequence represented by a `text' node.
%%
%% @see text/1
@@ -1477,18 +1385,15 @@ text_string(Node) ->
%% =====================================================================
-%% @spec variable(Name) -> syntaxTree()
-%% Name = atom() | string()
-%%
%% @doc Creates an abstract variable with the given name.
-%% <code>Name</code> may be any atom or string that represents a
+%% `Name' may be any atom or string that represents a
%% lexically valid variable name, but <em>not</em> a single underscore
-%% character; cf. <code>underscore/0</code>.
+%% character; see {@link underscore/0}.
%%
-%% <p>Note: no checking is done whether the character sequence
+%% Note: no checking is done whether the character sequence
%% represents a proper variable name, i.e., whether or not its first
%% character is an uppercase Erlang character, or whether it does not
-%% contain control characters, whitespace, etc.</p>
+%% contain control characters, whitespace, etc.
%%
%% @see variable_name/1
%% @see variable_literal/1
@@ -1517,9 +1422,7 @@ revert_variable(Node) ->
%% =====================================================================
-%% @spec variable_name(syntaxTree()) -> atom()
-%%
-%% @doc Returns the name of a <code>variable</code> node as an atom.
+%% @doc Returns the name of a `variable' node as an atom.
%%
%% @see variable/1
@@ -1535,9 +1438,7 @@ variable_name(Node) ->
%% =====================================================================
-%% @spec variable_literal(syntaxTree()) -> string()
-%%
-%% @doc Returns the name of a <code>variable</code> node as a string.
+%% @doc Returns the name of a `variable' node as a string.
%%
%% @see variable/1
@@ -1553,9 +1454,7 @@ variable_literal(Node) ->
%% =====================================================================
-%% @spec underscore() -> syntaxTree()
-%%
-%% @doc Creates an abstract universal pattern ("<code>_</code>"). The
+%% @doc Creates an abstract universal pattern ("`_'"). The
%% lexical representation is a single underscore character. Note that
%% this is <em>not</em> a variable, lexically speaking.
%%
@@ -1579,10 +1478,8 @@ revert_underscore(Node) ->
%% =====================================================================
-%% @spec integer(Value::integer()) -> syntaxTree()
-%%
%% @doc Creates an abstract integer literal. The lexical representation
-%% is the canonical decimal numeral of <code>Value</code>.
+%% is the canonical decimal numeral of `Value'.
%%
%% @see integer_value/1
%% @see integer_literal/1
@@ -1608,11 +1505,8 @@ revert_integer(Node) ->
%% =====================================================================
-%% @spec is_integer(Node::syntaxTree(), Value::integer()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> has type
-%% <code>integer</code> and represents <code>Value</code>, otherwise
-%% <code>false</code>.
+%% @doc Returns `true' if `Node' has type
+%% `integer' and represents `Value', otherwise `false'.
%%
%% @see integer/1
@@ -1630,9 +1524,7 @@ is_integer(Node, Value) ->
%% =====================================================================
-%% @spec integer_value(syntaxTree()) -> integer()
-%%
-%% @doc Returns the value represented by an <code>integer</code> node.
+%% @doc Returns the value represented by an `integer' node.
%%
%% @see integer/1
@@ -1648,10 +1540,7 @@ integer_value(Node) ->
%% =====================================================================
-%% @spec integer_literal(syntaxTree()) -> string()
-%%
-%% @doc Returns the numeral string represented by an
-%% <code>integer</code> node.
+%% @doc Returns the numeral string represented by an `integer' node.
%%
%% @see integer/1
@@ -1662,11 +1551,8 @@ integer_literal(Node) ->
%% =====================================================================
-%% @spec float(Value::float()) -> syntaxTree()
-%%
%% @doc Creates an abstract floating-point literal. The lexical
-%% representation is the decimal floating-point numeral of
-%% <code>Value</code>.
+%% representation is the decimal floating-point numeral of `Value'.
%%
%% @see float_value/1
%% @see float_literal/1
@@ -1701,9 +1587,7 @@ revert_float(Node) ->
%% =====================================================================
-%% @spec float_value(syntaxTree()) -> float()
-%%
-%% @doc Returns the value represented by a <code>float</code> node. Note
+%% @doc Returns the value represented by a `float' node. Note
%% that floating-point values should usually not be compared for
%% equality.
%%
@@ -1721,10 +1605,7 @@ float_value(Node) ->
%% =====================================================================
-%% @spec float_literal(syntaxTree()) -> string()
-%%
-%% @doc Returns the numeral string represented by a <code>float</code>
-%% node.
+%% @doc Returns the numeral string represented by a `float' node.
%%
%% @see float/1
@@ -1735,17 +1616,15 @@ float_literal(Node) ->
%% =====================================================================
-%% @spec char(Value::char()) -> syntaxTree()
-%%
%% @doc Creates an abstract character literal. The result represents
-%% "<code>$<em>Name</em></code>", where <code>Name</code> corresponds to
-%% <code>Value</code>.
+%% "<code>$<em>Name</em></code>", where `Name' corresponds to
+%% `Value'.
%%
-%% <p>Note: the literal corresponding to a particular character value is
-%% not uniquely defined. E.g., the character "<code>a</code>" can be
-%% written both as "<code>$a</code>" and "<code>$\141</code>", and a Tab
-%% character can be written as "<code>$\11</code>", "<code>$\011</code>"
-%% or "<code>$\t</code>".</p>
+%% Note: the literal corresponding to a particular character value is
+%% not uniquely defined. E.g., the character "`a'" can be
+%% written both as "`$a'" and "`$\141'", and a Tab
+%% character can be written as "`$\11'", "`$\011'"
+%% or "`$\t'".
%%
%% @see char_value/1
%% @see char_literal/1
@@ -1771,11 +1650,8 @@ revert_char(Node) ->
%% =====================================================================
-%% @spec is_char(Node::syntaxTree(), Value::char()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> has type
-%% <code>char</code> and represents <code>Value</code>, otherwise
-%% <code>false</code>.
+%% @doc Returns `true' if `Node' has type
+%% `char' and represents `Value', otherwise `false'.
%%
%% @see char/1
@@ -1793,9 +1669,7 @@ is_char(Node, Value) ->
%% =====================================================================
-%% @spec char_value(syntaxTree()) -> char()
-%%
-%% @doc Returns the value represented by a <code>char</code> node.
+%% @doc Returns the value represented by a `char' node.
%%
%% @see char/1
@@ -1811,10 +1685,8 @@ char_value(Node) ->
%% =====================================================================
-%% @spec char_literal(syntaxTree()) -> string()
-%%
-%% @doc Returns the literal string represented by a <code>char</code>
-%% node. This includes the leading "<code>$</code>" character.
+%% @doc Returns the literal string represented by a `char'
+%% node. This includes the leading "`$'" character.
%%
%% @see char/1
@@ -1825,16 +1697,14 @@ char_literal(Node) ->
%% =====================================================================
-%% @spec string(Value::string()) -> syntaxTree()
-%%
%% @doc Creates an abstract string literal. The result represents
%% <code>"<em>Text</em>"</code> (including the surrounding
-%% double-quotes), where <code>Text</code> corresponds to the sequence
-%% of characters in <code>Value</code>, but not representing a
-%% <em>specific</em> string literal. E.g., the result of
-%% <code>string("x\ny")</code> represents any and all of
-%% <code>"x\ny"</code>, <code>"x\12y"</code>, <code>"x\012y"</code> and
-%% <code>"x\^Jy"</code>; cf. <code>char/1</code>.
+%% double-quotes), where `Text' corresponds to the sequence
+%% of characters in `Value', but not representing a
+%% <em>specific</em> string literal.
+%%
+%% For example, the result of `string("x\ny")' represents any and all of
+%% `"x\ny"', `"x\12y"', `"x\012y"' and `"x\^Jy"'; see {@link char/1}.
%%
%% @see string_value/1
%% @see string_literal/1
@@ -1861,11 +1731,8 @@ revert_string(Node) ->
%% =====================================================================
-%% @spec is_string(Node::syntaxTree(), Value::string()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> has type
-%% <code>string</code> and represents <code>Value</code>, otherwise
-%% <code>false</code>.
+%% @doc Returns `true' if `Node' has type
+%% `string' and represents `Value', otherwise `false'.
%%
%% @see string/1
@@ -1883,9 +1750,7 @@ is_string(Node, Value) ->
%% =====================================================================
-%% @spec string_value(syntaxTree()) -> string()
-%%
-%% @doc Returns the value represented by a <code>string</code> node.
+%% @doc Returns the value represented by a `string' node.
%%
%% @see string/1
@@ -1901,9 +1766,7 @@ string_value(Node) ->
%% =====================================================================
-%% @spec string_literal(syntaxTree()) -> string()
-%%
-%% @doc Returns the literal string represented by a <code>string</code>
+%% @doc Returns the literal string represented by a `string'
%% node. This includes surrounding double-quote characters.
%%
%% @see string/1
@@ -1915,11 +1778,8 @@ string_literal(Node) ->
%% =====================================================================
-%% @spec atom(Name) -> syntaxTree()
-%% Name = atom() | string()
-%%
%% @doc Creates an abstract atom literal. The print name of the atom is
-%% the character sequence represented by <code>Name</code>.
+%% the character sequence represented by `Name'.
%%
%% @see atom_value/1
%% @see atom_name/1
@@ -1948,11 +1808,8 @@ revert_atom(Node) ->
%% =====================================================================
-%% @spec is_atom(Node::syntaxTree(), Value::atom()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> has type
-%% <code>atom</code> and represents <code>Value</code>, otherwise
-%% <code>false</code>.
+%% @doc Returns `true' if `Node' has type
+%% `atom' and represents `Value', otherwise `false'.
%%
%% @see atom/1
@@ -1970,9 +1827,7 @@ is_atom(Node, Value) ->
%% =====================================================================
-%% @spec atom_value(syntaxTree()) -> atom()
-%%
-%% @doc Returns the value represented by an <code>atom</code> node.
+%% @doc Returns the value represented by an `atom' node.
%%
%% @see atom/1
@@ -1988,9 +1843,7 @@ atom_value(Node) ->
%% =====================================================================
-%% @spec atom_name(syntaxTree()) -> string()
-%%
-%% @doc Returns the printname of an <code>atom</code> node.
+%% @doc Returns the printname of an `atom' node.
%%
%% @see atom/1
@@ -2001,15 +1854,12 @@ atom_name(Node) ->
%% =====================================================================
-%% @spec atom_literal(syntaxTree()) -> string()
-%%
-%% @doc Returns the literal string represented by an <code>atom</code>
+%% @doc Returns the literal string represented by an `atom'
%% node. This includes surrounding single-quote characters if necessary.
%%
-%% <p>Note that e.g. the result of <code>atom("x\ny")</code> represents
-%% any and all of <code>'x\ny'</code>, <code>'x\12y'</code>,
-%% <code>'x\012y'</code> and <code>'x\^Jy\'</code>; cf.
-%% <code>string/1</code>.</p>
+%% Note that e.g. the result of `atom("x\ny")' represents
+%% any and all of `'x\ny'', `'x\12y'',
+%% `'x\012y'' and `'x\^Jy\''; see {@link string/1}.
%%
%% @see atom/1
%% @see string/1
@@ -2021,14 +1871,12 @@ atom_literal(Node) ->
%% =====================================================================
-%% @spec tuple(Elements::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract tuple. If <code>Elements</code> is
-%% <code>[X1, ..., Xn]</code>, the result represents
+%% @doc Creates an abstract tuple. If `Elements' is
+%% `[X1, ..., Xn]', the result represents
%% "<code>{<em>X1</em>, ..., <em>Xn</em>}</code>".
%%
-%% <p>Note: The Erlang language has distinct 1-tuples, i.e.,
-%% <code>{X}</code> is always distinct from <code>X</code> itself.</p>
+%% Note: The Erlang language has distinct 1-tuples, i.e.,
+%% `{X}' is always distinct from `X' itself.
%%
%% @see tuple_elements/1
%% @see tuple_size/1
@@ -2055,10 +1903,7 @@ revert_tuple(Node) ->
%% =====================================================================
-%% @spec tuple_elements(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of element subtrees of a <code>tuple</code>
-%% node.
+%% @doc Returns the list of element subtrees of a `tuple' node.
%%
%% @see tuple/1
@@ -2074,13 +1919,11 @@ tuple_elements(Node) ->
%% =====================================================================
-%% @spec tuple_size(syntaxTree()) -> integer()
-%%
-%% @doc Returns the number of elements of a <code>tuple</code> node.
+%% @doc Returns the number of elements of a `tuple' node.
%%
-%% <p>Note: this is equivalent to
-%% <code>length(tuple_elements(Node))</code>, but potentially more
-%% efficient.</p>
+%% Note: this is equivalent to
+%% `length(tuple_elements(Node))', but potentially more
+%% efficient.
%%
%% @see tuple/1
%% @see tuple_elements/1
@@ -2092,7 +1935,6 @@ tuple_size(Node) ->
%% =====================================================================
-%% @spec list(List) -> syntaxTree()
%% @equiv list(List, none)
-spec list([syntaxTree()]) -> syntaxTree().
@@ -2102,35 +1944,31 @@ list(List) ->
%% =====================================================================
-%% @spec list(List, Tail) -> syntaxTree()
-%% List = [syntaxTree()]
-%% Tail = none | syntaxTree()
-%%
%% @doc Constructs an abstract list skeleton. The result has type
-%% <code>list</code> or <code>nil</code>. If <code>List</code> is a
-%% nonempty list <code>[E1, ..., En]</code>, the result has type
-%% <code>list</code> and represents either "<code>[<em>E1</em>, ...,
-%% <em>En</em>]</code>", if <code>Tail</code> is <code>none</code>, or
+%% `list' or `nil'. If `List' is a
+%% nonempty list `[E1, ..., En]', the result has type
+%% `list' and represents either "<code>[<em>E1</em>, ...,
+%% <em>En</em>]</code>", if `Tail' is `none', or
%% otherwise "<code>[<em>E1</em>, ..., <em>En</em> |
-%% <em>Tail</em>]</code>". If <code>List</code> is the empty list,
-%% <code>Tail</code> <em>must</em> be <code>none</code>, and in that
-%% case the result has type <code>nil</code> and represents
-%% "<code>[]</code>" (cf. <code>nil/0</code>).
+%% <em>Tail</em>]</code>". If `List' is the empty list,
+%% `Tail' <em>must</em> be `none', and in that
+%% case the result has type `nil' and represents
+%% "`[]'" (see {@link nil/0}).
%%
-%% <p>The difference between lists as semantic objects (built up of
+%% The difference between lists as semantic objects (built up of
%% individual "cons" and "nil" terms) and the various syntactic forms
%% for denoting lists may be bewildering at first. This module provides
%% functions both for exact control of the syntactic representation as
%% well as for the simple composition and deconstruction in terms of
-%% cons and head/tail operations.</p>
+%% cons and head/tail operations.
%%
-%% <p>Note: in <code>list(Elements, none)</code>, the "nil" list
-%% terminator is implicit and has no associated information (cf.
-%% <code>get_attrs/1</code>), while in the seemingly equivalent
-%% <code>list(Elements, Tail)</code> when <code>Tail</code> has type
-%% <code>nil</code>, the list terminator subtree <code>Tail</code> may
+%% Note: in `list(Elements, none)', the "nil" list
+%% terminator is implicit and has no associated information (see
+%% {@link get_attrs/1}), while in the seemingly equivalent
+%% `list(Elements, Tail)' when `Tail' has type
+%% `nil', the list terminator subtree `Tail' may
%% have attached attributes such as position, comments, and annotations,
-%% which will be preserved in the result.</p>
+%% which will be preserved in the result.
%%
%% @see nil/0
%% @see list/1
@@ -2187,10 +2025,8 @@ revert_list(Node) ->
S, P).
%% =====================================================================
-%% @spec nil() -> syntaxTree()
-%%
%% @doc Creates an abstract empty list. The result represents
-%% "<code>[]</code>". The empty list is traditionally called "nil".
+%% "`[]'". The empty list is traditionally called "nil".
%%
%% @see list/2
%% @see is_list_skeleton/1
@@ -2213,13 +2049,11 @@ revert_nil(Node) ->
%% =====================================================================
-%% @spec list_prefix(Node::syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the prefix element subtrees of a <code>list</code> node.
-%% If <code>Node</code> represents "<code>[<em>E1</em>, ...,
+%% @doc Returns the prefix element subtrees of a `list' node.
+%% If `Node' represents "<code>[<em>E1</em>, ...,
%% <em>En</em>]</code>" or "<code>[<em>E1</em>, ..., <em>En</em> |
-%% <em>Tail</em>]</code>", the returned value is <code>[E1, ...,
-%% En]</code>.
+%% <em>Tail</em>]</code>", the returned value is `[E1, ...,
+%% En]'.
%%
%% @see list/2
@@ -2227,28 +2061,31 @@ revert_nil(Node) ->
list_prefix(Node) ->
case unwrap(Node) of
- {cons, _, Head, _} ->
- [Head];
+ {cons, _, Head, Tail} ->
+ [Head | cons_prefix(Tail)];
Node1 ->
(data(Node1))#list.prefix
end.
+%% collects sequences of conses; cf. cons_suffix/1 below
+cons_prefix({cons, _, Head, Tail}) ->
+ [Head | cons_prefix(Tail)];
+cons_prefix(_) ->
+ [].
+
%% =====================================================================
-%% @spec list_suffix(Node::syntaxTree()) -> none | syntaxTree()
-%%
-%% @doc Returns the suffix subtree of a <code>list</code> node, if one
-%% exists. If <code>Node</code> represents "<code>[<em>E1</em>, ...,
+%% @doc Returns the suffix subtree of a `list' node, if one
+%% exists. If `Node' represents "<code>[<em>E1</em>, ...,
%% <em>En</em> | <em>Tail</em>]</code>", the returned value is
-%% <code>Tail</code>, otherwise, i.e., if <code>Node</code> represents
-%% "<code>[<em>E1</em>, ..., <em>En</em>]</code>", <code>none</code> is
+%% `Tail', otherwise, i.e., if `Node' represents
+%% "<code>[<em>E1</em>, ..., <em>En</em>]</code>", `none' is
%% returned.
%%
-%% <p>Note that even if this function returns some <code>Tail</code>
-%% that is not <code>none</code>, the type of <code>Tail</code> can be
-%% <code>nil</code>, if the tail has been given explicitly, and the list
-%% skeleton has not been compacted (cf.
-%% <code>compact_list/1</code>).</p>
+%% Note that even if this function returns some `Tail'
+%% that is not `none', the type of `Tail' can be
+%% `nil', if the tail has been given explicitly, and the list
+%% skeleton has not been compacted (see {@link compact_list/1}).
%%
%% @see list/2
%% @see nil/0
@@ -2259,34 +2096,36 @@ list_prefix(Node) ->
list_suffix(Node) ->
case unwrap(Node) of
{cons, _, _, Tail} ->
- %% If there could be comments/annotations on the tail node,
- %% we should not return `none' even if it has type `nil'.
- case Tail of
+ case cons_suffix(Tail) of
{nil, _} ->
- none; % no interesting information is lost
- _ ->
- Tail
+ none;
+ Tail1 ->
+ Tail1
end;
Node1 ->
(data(Node1))#list.suffix
end.
+%% skips sequences of conses; cf. cons_prefix/1 above
+cons_suffix({cons, _, _, Tail}) ->
+ cons_suffix(Tail);
+cons_suffix(Tail) ->
+ Tail.
+
%% =====================================================================
-%% @spec cons(Head::syntaxTree(), Tail::syntaxTree()) -> syntaxTree()
-%%
%% @doc "Optimising" list skeleton cons operation. Creates an abstract
-%% list skeleton whose first element is <code>Head</code> and whose tail
-%% corresponds to <code>Tail</code>. This is similar to
-%% <code>list([Head], Tail)</code>, except that <code>Tail</code> may
-%% not be <code>none</code>, and that the result does not necessarily
+%% list skeleton whose first element is `Head' and whose tail
+%% corresponds to `Tail'. This is similar to
+%% `list([Head], Tail)', except that `Tail' may
+%% not be `none', and that the result does not necessarily
%% represent exactly "<code>[<em>Head</em> | <em>Tail</em>]</code>", but
-%% may depend on the <code>Tail</code> subtree. E.g., if
-%% <code>Tail</code> represents <code>[X, Y]</code>, the result may
+%% may depend on the `Tail' subtree. E.g., if
+%% `Tail' represents `[X, Y]', the result may
%% represent "<code>[<em>Head</em>, X, Y]</code>", rather than
%% "<code>[<em>Head</em> | [X, Y]]</code>". Annotations on
-%% <code>Tail</code> itself may be lost if <code>Tail</code> represents
-%% a list skeleton, but comments on <code>Tail</code> are propagated to
+%% `Tail' itself may be lost if `Tail' represents
+%% a list skeleton, but comments on `Tail' are propagated to
%% the result.
%%
%% @see list/2
@@ -2308,10 +2147,8 @@ cons(Head, Tail) ->
%% =====================================================================
-%% @spec list_head(Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the head element subtree of a <code>list</code> node. If
-%% <code>Node</code> represents "<code>[<em>Head</em> ...]</code>", the
+%% @doc Returns the head element subtree of a `list' node. If
+%% `Node' represents "<code>[<em>Head</em> ...]</code>", the
%% result will represent "<code><em>Head</em></code>".
%%
%% @see list/2
@@ -2325,15 +2162,13 @@ list_head(Node) ->
%% =====================================================================
-%% @spec list_tail(Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the tail of a <code>list</code> node. If
-%% <code>Node</code> represents a single-element list
+%% @doc Returns the tail of a `list' node. If
+%% `Node' represents a single-element list
%% "<code>[<em>E</em>]</code>", then the result has type
-%% <code>nil</code>, representing "<code>[]</code>". If
-%% <code>Node</code> represents "<code>[<em>E1</em>, <em>E2</em>
+%% `nil', representing "`[]'". If
+%% `Node' represents "<code>[<em>E1</em>, <em>E2</em>
%% ...]</code>", the result will represent "<code>[<em>E2</em>
-%% ...]</code>", and if <code>Node</code> represents
+%% ...]</code>", and if `Node' represents
%% "<code>[<em>Head</em> | <em>Tail</em>]</code>", the result will
%% represent "<code><em>Tail</em></code>".
%%
@@ -2358,10 +2193,8 @@ list_tail(Node) ->
%% =====================================================================
-%% @spec is_list_skeleton(syntaxTree()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> has type
-%% <code>list</code> or <code>nil</code>, otherwise <code>false</code>.
+%% @doc Returns `true' if `Node' has type
+%% `list' or `nil', otherwise `false'.
%%
%% @see list/2
%% @see nil/0
@@ -2377,24 +2210,22 @@ is_list_skeleton(Node) ->
%% =====================================================================
-%% @spec is_proper_list(Node::syntaxTree()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents a
-%% proper list, and <code>false</code> otherwise. A proper list is a
-%% list skeleton either on the form "<code>[]</code>" or
+%% @doc Returns `true' if `Node' represents a
+%% proper list, and `false' otherwise. A proper list is a
+%% list skeleton either on the form "`[]'" or
%% "<code>[<em>E1</em>, ..., <em>En</em>]</code>", or "<code>[... |
-%% <em>Tail</em>]</code>" where recursively <code>Tail</code> also
+%% <em>Tail</em>]</code>" where recursively `Tail' also
%% represents a proper list.
%%
-%% <p>Note: Since <code>Node</code> is a syntax tree, the actual
+%% Note: Since `Node' 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>
+%% or completely unknown. Thus, if `Node' represents e.g.
+%% "`[... | Ns]'" (where `Ns' is a variable), then
+%% the function will return `false', because it is not known
+%% whether `Ns' will be bound to a list at run-time. If
+%% `Node' instead represents e.g. "`[1, 2, 3]'" or
+%% "`[A | []]'", then the function will return
+%% `true'.
%%
%% @see list/2
@@ -2417,14 +2248,11 @@ is_proper_list(Node) ->
%% =====================================================================
-%% @spec list_elements(Node::syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of element subtrees of a list skeleton.
-%% <code>Node</code> must represent a proper list. E.g., if
-%% <code>Node</code> represents "<code>[<em>X1</em>, <em>X2</em> |
+%% `Node' must represent a proper list. E.g., if
+%% `Node' 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>.
+%% `list_elements(Node)' yields the list `[X1, X2, X3, X4]'.
%%
%% @see list/2
%% @see is_proper_list/1
@@ -2450,17 +2278,15 @@ list_elements(Node, As) ->
%% =====================================================================
-%% @spec list_length(Node::syntaxTree()) -> integer()
-%%
%% @doc Returns the number of element subtrees of a list skeleton.
-%% <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
+%% `Node' must represent a proper list. E.g., if
+%% `Node' represents "`[X1 | [X2, X3 | [X4, X5,
+%% X6]]]'", then `list_length(Node)' returns the
%% integer 6.
%%
-%% <p>Note: this is equivalent to
-%% <code>length(list_elements(Node))</code>, but potentially more
-%% efficient.</p>
+%% Note: this is equivalent to
+%% `length(list_elements(Node))', but potentially more
+%% efficient.
%%
%% @see list/2
%% @see is_proper_list/1
@@ -2487,18 +2313,16 @@ list_length(Node, A) ->
%% =====================================================================
-%% @spec normalize_list(Node::syntaxTree()) -> syntaxTree()
-%%
%% @doc Expands an abstract list skeleton to its most explicit form. If
-%% <code>Node</code> represents "<code>[<em>E1</em>, ..., <em>En</em> |
+%% `Node' represents "<code>[<em>E1</em>, ..., <em>En</em> |
%% <em>Tail</em>]</code>", the result represents "<code>[<em>E1</em> |
%% ... [<em>En</em> | <em>Tail1</em>] ... ]</code>", where
-%% <code>Tail1</code> is the result of
-%% <code>normalize_list(Tail)</code>. If <code>Node</code> represents
+%% `Tail1' is the result of
+%% `normalize_list(Tail)'. If `Node' represents
%% "<code>[<em>E1</em>, ..., <em>En</em>]</code>", the result simply
%% represents "<code>[<em>E1</em> | ... [<em>En</em> | []] ...
-%% ]</code>". If <code>Node</code> does not represent a list skeleton,
-%% <code>Node</code> itself is returned.
+%% ]</code>". If `Node' does not represent a list skeleton,
+%% `Node' itself is returned.
%%
%% @see list/2
%% @see compact_list/1
@@ -2528,16 +2352,14 @@ normalize_list_1(Es, Tail) ->
%% =====================================================================
-%% @spec compact_list(Node::syntaxTree()) -> syntaxTree()
-%%
%% @doc Yields the most compact form for an abstract list skeleton. The
%% result either represents "<code>[<em>E1</em>, ..., <em>En</em> |
-%% <em>Tail</em>]</code>", where <code>Tail</code> is not a list
+%% <em>Tail</em>]</code>", where `Tail' is not a list
%% skeleton, or otherwise simply "<code>[<em>E1</em>, ...,
-%% <em>En</em>]</code>". Annotations on subtrees of <code>Node</code>
+%% <em>En</em>]</code>". Annotations on subtrees of `Node'
%% that represent list skeletons may be lost, but comments will be
-%% propagated to the result. Returns <code>Node</code> itself if
-%% <code>Node</code> does not represent a list skeleton.
+%% propagated to the result. Returns `Node' itself if
+%% `Node' does not represent a list skeleton.
%%
%% @see list/2
%% @see normalize_list/1
@@ -2575,10 +2397,8 @@ compact_list(Node) ->
%% =====================================================================
-%% @spec binary(Fields::[syntaxTree()]) -> syntaxTree()
-%%
%% @doc Creates an abstract binary-object template. If
-%% <code>Fields</code> is <code>[F1, ..., Fn]</code>, the result
+%% `Fields' is `[F1, ..., Fn]', the result
%% represents "<code>&lt;&lt;<em>F1</em>, ...,
%% <em>Fn</em>&gt;&gt;</code>".
%%
@@ -2611,10 +2431,7 @@ revert_binary(Node) ->
%% =====================================================================
-%% @spec binary_fields(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of field subtrees of a <code>binary</code>
-%% node.
+%% @doc Returns the list of field subtrees of a `binary' node.
%%
%% @see binary/1
%% @see binary_field/2
@@ -2631,7 +2448,6 @@ binary_fields(Node) ->
%% =====================================================================
-%% @spec binary_field(Body) -> syntaxTree()
%% @equiv binary_field(Body, [])
-spec binary_field(syntaxTree()) -> syntaxTree().
@@ -2641,15 +2457,11 @@ binary_field(Body) ->
%% =====================================================================
-%% @spec binary_field(Body::syntaxTree(), Size,
-%% Types::[syntaxTree()]) -> syntaxTree()
-%% Size = none | syntaxTree()
-%%
%% @doc Creates an abstract binary template field.
-%% If <code>Size</code> is <code>none</code>, this is equivalent to
-%% "<code>binary_field(Body, Types)</code>", otherwise it is
-%% equivalent to "<code>binary_field(size_qualifier(Body, Size),
-%% Types)</code>".
+%% If `Size' is `none', this is equivalent to
+%% "`binary_field(Body, Types)'", otherwise it is
+%% equivalent to "`binary_field(size_qualifier(Body, Size),
+%% Types)'".
%%
%% (This is a utility function.)
%%
@@ -2667,13 +2479,10 @@ binary_field(Body, Size, Types) ->
%% =====================================================================
-%% @spec binary_field(Body::syntaxTree(), Types::[syntaxTree()]) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract binary template field. If
-%% <code>Types</code> is the empty list, the result simply represents
-%% "<code><em>Body</em></code>", otherwise, if <code>Types</code> is
-%% <code>[T1, ..., Tn]</code>, the result represents
+%% `Types' is the empty list, the result simply represents
+%% "<code><em>Body</em></code>", otherwise, if `Types' is
+%% `[T1, ..., Tn]', the result represents
%% "<code><em>Body</em>/<em>T1</em>-...-<em>Tn</em></code>".
%%
%% @see binary/1
@@ -2727,9 +2536,7 @@ revert_binary_field(Node) ->
%% =====================================================================
-%% @spec binary_field_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>binary_field</code>.
+%% @doc Returns the body subtree of a `binary_field'.
%%
%% @see binary_field/2
@@ -2749,12 +2556,10 @@ binary_field_body(Node) ->
%% =====================================================================
-%% @spec binary_field_types(Node::syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of type-specifier subtrees of a
-%% <code>binary_field</code> node. If <code>Node</code> represents
+%% `binary_field' node. If `Node' represents
%% "<code>.../<em>T1</em>, ..., <em>Tn</em></code>", the result is
-%% <code>[T1, ..., Tn]</code>, otherwise the result is the empty list.
+%% `[T1, ..., Tn]', otherwise the result is the empty list.
%%
%% @see binary_field/2
@@ -2774,14 +2579,12 @@ binary_field_types(Node) ->
%% =====================================================================
-%% @spec binary_field_size(Node::syntaxTree()) -> none | syntaxTree()
-%%
%% @doc Returns the size specifier subtree of a
-%% <code>binary_field</code> node, if any. If <code>Node</code>
+%% `binary_field' node, if any. If `Node'
%% represents "<code><em>Body</em>:<em>Size</em></code>" or
%% "<code><em>Body</em>:<em>Size</em>/<em>T1</em>, ...,
-%% <em>Tn</em></code>", the result is <code>Size</code>, otherwise
-%% <code>none</code> is returned.
+%% <em>Tn</em></code>", the result is `Size', otherwise
+%% `none' is returned.
%%
%% (This is a utility function.)
%%
@@ -2810,9 +2613,6 @@ binary_field_size(Node) ->
%% =====================================================================
-%% @spec size_qualifier(Body::syntaxTree(), Size::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract size qualifier. The result represents
%% "<code><em>Body</em>:<em>Size</em></code>".
%%
@@ -2834,10 +2634,7 @@ size_qualifier(Body, Size) ->
%% =====================================================================
-%% @spec size_qualifier_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>size_qualifier</code>
-%% node.
+%% @doc Returns the body subtree of a `size_qualifier' node.
%%
%% @see size_qualifier/2
@@ -2848,10 +2645,8 @@ size_qualifier_body(Node) ->
%% =====================================================================
-%% @spec size_qualifier_argument(syntaxTree()) -> syntaxTree()
-%%
%% @doc Returns the argument subtree (the size) of a
-%% <code>size_qualifier</code> node.
+%% `size_qualifier' node.
%%
%% @see size_qualifier/2
@@ -2862,16 +2657,14 @@ size_qualifier_argument(Node) ->
%% =====================================================================
-%% @spec error_marker(Error::term()) -> syntaxTree()
-%%
%% @doc Creates an abstract error marker. The result represents an
%% occurrence of an error in the source code, with an associated Erlang
-%% I/O ErrorInfo structure given by <code>Error</code> (see module
+%% I/O ErrorInfo structure given by `Error' (see module
%% {@link //stdlib/io} for details). Error markers are regarded as source
%% code forms, but have no defined lexical form.
%%
-%% <p>Note: this is supported only for backwards compatibility with
-%% existing parsers and tools.</p>
+%% Note: this is supported only for backwards compatibility with
+%% existing parsers and tools.
%%
%% @see error_marker_info/1
%% @see warning_marker/1
@@ -2902,10 +2695,7 @@ revert_error_marker(Node) ->
%% =====================================================================
-%% @spec error_marker_info(syntaxTree()) -> term()
-%%
-%% @doc Returns the ErrorInfo structure of an <code>error_marker</code>
-%% node.
+%% @doc Returns the ErrorInfo structure of an `error_marker' node.
%%
%% @see error_marker/1
@@ -2921,16 +2711,14 @@ error_marker_info(Node) ->
%% =====================================================================
-%% @spec warning_marker(Error::term()) -> syntaxTree()
-%%
%% @doc Creates an abstract warning marker. The result represents an
%% occurrence of a possible problem in the source code, with an
-%% associated Erlang I/O ErrorInfo structure given by <code>Error</code>
+%% associated Erlang I/O ErrorInfo structure given by `Error'
%% (see module {@link //stdlib/io} for details). Warning markers are
%% regarded as source code forms, but have no defined lexical form.
%%
-%% <p>Note: this is supported only for backwards compatibility with
-%% existing parsers and tools.</p>
+%% Note: this is supported only for backwards compatibility with
+%% existing parsers and tools.
%%
%% @see warning_marker_info/1
%% @see error_marker/1
@@ -2961,10 +2749,7 @@ revert_warning_marker(Node) ->
%% =====================================================================
-%% @spec warning_marker_info(syntaxTree()) -> term()
-%%
-%% @doc Returns the ErrorInfo structure of a <code>warning_marker</code>
-%% node.
+%% @doc Returns the ErrorInfo structure of a `warning_marker' node.
%%
%% @see warning_marker/1
@@ -2980,16 +2765,14 @@ warning_marker_info(Node) ->
%% =====================================================================
-%% @spec eof_marker() -> syntaxTree()
-%%
%% @doc Creates an abstract end-of-file marker. This represents the
%% end of input when reading a sequence of source code forms. An
%% end-of-file marker is itself regarded as a source code form
%% (namely, the last in any sequence in which it occurs). It has no
%% defined lexical form.
%%
-%% <p>Note: this is retained only for backwards compatibility with
-%% existing parsers and tools.</p>
+%% Note: this is retained only for backwards compatibility with
+%% existing parsers and tools.
%%
%% @see error_marker/1
%% @see warning_marker/1
@@ -3013,7 +2796,6 @@ revert_eof_marker(Node) ->
%% =====================================================================
-%% @spec attribute(Name) -> syntaxTree()
%% @equiv attribute(Name, none)
-spec attribute(syntaxTree()) -> syntaxTree().
@@ -3023,23 +2805,20 @@ attribute(Name) ->
%% =====================================================================
-%% @spec attribute(Name::syntaxTree(), Arguments) -> syntaxTree()
-%% Arguments = none | [syntaxTree()]
-%%
%% @doc Creates an abstract program attribute. If
-%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
+%% `Arguments' is `[A1, ..., An]', the result
%% represents "<code>-<em>Name</em>(<em>A1</em>, ...,
-%% <em>An</em>).</code>". Otherwise, if <code>Arguments</code> is
-%% <code>none</code>, the result represents
+%% <em>An</em>).</code>". Otherwise, if `Arguments' is
+%% `none', the result represents
%% "<code>-<em>Name</em>.</code>". The latter form makes it possible
%% to represent preprocessor directives such as
-%% "<code>-endif.</code>". Attributes are source code forms.
+%% "`-endif.'". Attributes are source code forms.
%%
-%% <p>Note: The preprocessor macro definition directive
+%% Note: The preprocessor macro definition directive
%% "<code>-define(<em>Name</em>, <em>Body</em>).</code>" has relatively
-%% few requirements on the syntactical form of <code>Body</code> (viewed
-%% as a sequence of tokens). The <code>text</code> node type can be used
-%% for a <code>Body</code> that is not a normal Erlang construct.</p>
+%% few requirements on the syntactical form of `Body' (viewed
+%% as a sequence of tokens). The `text' node type can be used
+%% for a `Body' that is not a normal Erlang construct.
%%
%% @see attribute/1
%% @see attribute_name/1
@@ -3233,9 +3012,7 @@ revert_module_name(A) ->
%% =====================================================================
-%% @spec attribute_name(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the name subtree of an <code>attribute</code> node.
+%% @doc Returns the name subtree of an `attribute' node.
%%
%% @see attribute/1
@@ -3251,15 +3028,12 @@ attribute_name(Node) ->
%% =====================================================================
-%% @spec attribute_arguments(Node::syntaxTree()) ->
-%% none | [syntaxTree()]
-%%
%% @doc Returns the list of argument subtrees of an
-%% <code>attribute</code> node, if any. If <code>Node</code>
+%% `attribute' node, if any. If `Node'
%% represents "<code>-<em>Name</em>.</code>", the result is
-%% <code>none</code>. Otherwise, if <code>Node</code> represents
+%% `none'. Otherwise, if `Node' represents
%% "<code>-<em>Name</em>(<em>E1</em>, ..., <em>En</em>).</code>",
-%% <code>[E1, ..., E1]</code> is returned.
+%% `[E1, ..., E1]' is returned.
%%
%% @see attribute/1
@@ -3326,9 +3100,6 @@ attribute_arguments(Node) ->
%% =====================================================================
-%% @spec arity_qualifier(Body::syntaxTree(), Arity::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract arity qualifier. The result represents
%% "<code><em>Body</em>/<em>Arity</em></code>".
%%
@@ -3350,10 +3121,7 @@ arity_qualifier(Body, Arity) ->
%% =====================================================================
-%% @spec arity_qualifier_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of an <code>arity_qualifier</code>
-%% node.
+%% @doc Returns the body subtree of an `arity_qualifier' node.
%%
%% @see arity_qualifier/2
@@ -3364,10 +3132,8 @@ arity_qualifier_body(Node) ->
%% =====================================================================
-%% @spec arity_qualifier_argument(syntaxTree()) -> syntaxTree()
-%%
%% @doc Returns the argument (the arity) subtree of an
-%% <code>arity_qualifier</code> node.
+%% `arity_qualifier' node.
%%
%% @see arity_qualifier/2
@@ -3378,9 +3144,6 @@ arity_qualifier_argument(Node) ->
%% =====================================================================
-%% @spec module_qualifier(Module::syntaxTree(), Body::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract module qualifier. The result represents
%% "<code><em>Module</em>:<em>Body</em></code>".
%%
@@ -3414,10 +3177,8 @@ revert_module_qualifier(Node) ->
%% =====================================================================
-%% @spec module_qualifier_argument(syntaxTree()) -> syntaxTree()
-%%
%% @doc Returns the argument (the module) subtree of a
-%% <code>module_qualifier</code> node.
+%% `module_qualifier' node.
%%
%% @see module_qualifier/2
@@ -3433,10 +3194,7 @@ module_qualifier_argument(Node) ->
%% =====================================================================
-%% @spec module_qualifier_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>module_qualifier</code>
-%% node.
+%% @doc Returns the body subtree of a `module_qualifier' node.
%%
%% @see module_qualifier/2
@@ -3452,11 +3210,9 @@ module_qualifier_body(Node) ->
%% =====================================================================
-%% @spec qualified_name(Segments::[syntaxTree()]) -> syntaxTree()
-%%
%% @doc Creates an abstract qualified name. The result represents
%% "<code><em>S1</em>.<em>S2</em>. ... .<em>Sn</em></code>", if
-%% <code>Segments</code> is <code>[S1, S2, ..., Sn]</code>.
+%% `Segments' is `[S1, S2, ..., Sn]'.
%%
%% @see qualified_name_segments/1
@@ -3484,10 +3240,8 @@ revert_qualified_name(Node) ->
%% =====================================================================
-%% @spec qualified_name_segments(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of name segments of a
-%% <code>qualified_name</code> node.
+%% `qualified_name' node.
%%
%% @see qualified_name/1
@@ -3503,13 +3257,10 @@ qualified_name_segments(Node) ->
%% =====================================================================
-%% @spec function(Name::syntaxTree(), Clauses::[syntaxTree()]) ->
-%% syntaxTree()
-%%
-%% @doc Creates an abstract function definition. If <code>Clauses</code>
-%% is <code>[C1, ..., Cn]</code>, the result represents
+%% @doc Creates an abstract function definition. If `Clauses'
+%% is `[C1, ..., Cn]', the result represents
%% "<code><em>Name</em> <em>C1</em>; ...; <em>Name</em>
-%% <em>Cn</em>.</code>". More exactly, if each <code>Ci</code>
+%% <em>Cn</em>.</code>". More exactly, if each `Ci'
%% represents "<code>(<em>Pi1</em>, ..., <em>Pim</em>) <em>Gi</em> ->
%% <em>Bi</em></code>", then the result represents
%% "<code><em>Name</em>(<em>P11</em>, ..., <em>P1m</em>) <em>G1</em> ->
@@ -3523,13 +3274,12 @@ qualified_name_segments(Node) ->
%% @see is_form/1
%% @see rule/2
--record(function, {name, clauses}).
-%% XXX: This one is problematic because there is a tuple with the same
-%% tag and size that comes from 'erl_parse'
-%% -record(function, {name :: syntaxTree(), clauses :: [syntaxTree()]}).
+%% Don't use the name 'function' for this record, to avoid confusion with
+%% the tuples on the form {function,Name,Arity} used by erl_parse.
+-record(func, {name :: syntaxTree(), clauses :: [syntaxTree()]}).
%% type(Node) = function
-%% data(Node) = #function{name :: Name, clauses :: Clauses}
+%% data(Node) = #func{name :: Name, clauses :: Clauses}
%%
%% Name = syntaxTree()
%% Clauses = [syntaxTree()]
@@ -3556,7 +3306,7 @@ qualified_name_segments(Node) ->
-spec function(syntaxTree(), [syntaxTree()]) -> syntaxTree().
function(Name, Clauses) ->
- tree(function, #function{name = Name, clauses = Clauses}).
+ tree(function, #func{name = Name, clauses = Clauses}).
revert_function(Node) ->
Name = function_name(Node),
@@ -3572,9 +3322,7 @@ revert_function(Node) ->
%% =====================================================================
-%% @spec function_name(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the name subtree of a <code>function</code> node.
+%% @doc Returns the name subtree of a `function' node.
%%
%% @see function/2
@@ -3585,15 +3333,12 @@ function_name(Node) ->
{function, Pos, Name, _, _} ->
set_pos(atom(Name), Pos);
Node1 ->
- (data(Node1))#function.name
+ (data(Node1))#func.name
end.
%% =====================================================================
-%% @spec function_clauses(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of clause subtrees of a <code>function</code>
-%% node.
+%% @doc Returns the list of clause subtrees of a `function' node.
%%
%% @see function/2
@@ -3604,21 +3349,19 @@ function_clauses(Node) ->
{function, _, _, _, Clauses} ->
Clauses;
Node1 ->
- (data(Node1))#function.clauses
+ (data(Node1))#func.clauses
end.
%% =====================================================================
-%% @spec function_arity(Node::syntaxTree()) -> integer()
-%%
-%% @doc Returns the arity of a <code>function</code> node. The result
+%% @doc Returns the arity of a `function' node. The result
%% is the number of parameter patterns in the first clause of the
%% function; subsequent clauses are ignored.
%%
-%% <p>An exception is thrown if <code>function_clauses(Node)</code>
+%% An exception is thrown if `function_clauses(Node)'
%% returns an empty list, or if the first element of that list is not
-%% a syntax tree <code>C</code> of type <code>clause</code> such that
-%% <code>clause_patterns(C)</code> is a nonempty list.</p>
+%% a syntax tree `C' of type `clause' such that
+%% `clause_patterns(C)' is a nonempty list.
%%
%% @see function/2
%% @see function_clauses/1
@@ -3634,7 +3377,6 @@ function_arity(Node) ->
%% =====================================================================
-%% @spec clause(Guard, Body) -> syntaxTree()
%% @equiv clause([], Guard, Body)
-type guard() :: 'none' | syntaxTree() | [syntaxTree()] | [[syntaxTree()]].
@@ -3646,34 +3388,28 @@ clause(Guard, Body) ->
%% =====================================================================
-%% @spec clause(Patterns::[syntaxTree()], Guard,
-%% Body::[syntaxTree()]) -> syntaxTree()
-%% Guard = none | syntaxTree()
-%% | [syntaxTree()] | [[syntaxTree()]]
-%%
-%% @doc Creates an abstract clause. If <code>Patterns</code> is
-%% <code>[P1, ..., Pn]</code> and <code>Body</code> is <code>[B1, ...,
-%% Bm]</code>, then if <code>Guard</code> is <code>none</code>, the
+%% @doc Creates an abstract clause. If `Patterns' is
+%% `[P1, ..., Pn]' and `Body' is `[B1, ...,
+%% Bm]', then if `Guard' is `none', the
%% result represents "<code>(<em>P1</em>, ..., <em>Pn</em>) ->
%% <em>B1</em>, ..., <em>Bm</em></code>", otherwise, unless
-%% <code>Guard</code> is a list, the result represents
+%% `Guard' is a list, the result represents
%% "<code>(<em>P1</em>, ..., <em>Pn</em>) when <em>Guard</em> ->
%% <em>B1</em>, ..., <em>Bm</em></code>".
%%
-%% <p>For simplicity, the <code>Guard</code> argument may also be any
+%% For simplicity, the `Guard' argument may also be any
%% of the following:
%% <ul>
-%% <li>An empty list <code>[]</code>. This is equivalent to passing
-%% <code>none</code>.</li>
-%% <li>A nonempty list <code>[E1, ..., Ej]</code> of syntax trees.
-%% This is equivalent to passing <code>conjunction([E1, ...,
-%% Ej])</code>.</li>
-%% <li>A nonempty list of lists of syntax trees <code>[[E1_1, ...,
-%% E1_k1], ..., [Ej_1, ..., Ej_kj]]</code>, which is equivalent
-%% to passing <code>disjunction([conjunction([E1_1, ...,
-%% E1_k1]), ..., conjunction([Ej_1, ..., Ej_kj])])</code>.</li>
+%% <li>An empty list `[]'. This is equivalent to passing
+%% `none'.</li>
+%% <li>A nonempty list `[E1, ..., Ej]' of syntax trees.
+%% This is equivalent to passing `conjunction([E1, ...,
+%% Ej])'.</li>
+%% <li>A nonempty list of lists of syntax trees `[[E1_1, ...,
+%% E1_k1], ..., [Ej_1, ..., Ej_kj]]', which is equivalent
+%% to passing `disjunction([conjunction([E1_1, ...,
+%% E1_k1]), ..., conjunction([Ej_1, ..., Ej_kj])])'.</li>
%% </ul>
-%% </p>
%%
%% @see clause/2
%% @see clause_patterns/1
@@ -3789,10 +3525,7 @@ unfold_try_clause({clause, Pos, [{tuple, _, [C, V, _]}],
%% =====================================================================
-%% @spec clause_patterns(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of pattern subtrees of a <code>clause</code>
-%% node.
+%% @doc Returns the list of pattern subtrees of a `clause' node.
%%
%% @see clause/3
@@ -3808,13 +3541,11 @@ clause_patterns(Node) ->
%% =====================================================================
-%% @spec clause_guard(Node::syntaxTree()) -> none | syntaxTree()
-%%
-%% @doc Returns the guard subtree of a <code>clause</code> node, if
-%% any. If <code>Node</code> represents "<code>(<em>P1</em>, ...,
+%% @doc Returns the guard subtree of a `clause' node, if
+%% any. If `Node' represents "<code>(<em>P1</em>, ...,
%% <em>Pn</em>) when <em>Guard</em> -> <em>B1</em>, ...,
-%% <em>Bm</em></code>", <code>Guard</code> is returned. Otherwise, the
-%% result is <code>none</code>.
+%% <em>Bm</em></code>", `Guard' is returned. Otherwise, the
+%% result is `none'.
%%
%% @see clause/3
@@ -3836,10 +3567,7 @@ clause_guard(Node) ->
%% =====================================================================
-%% @spec clause_body(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Return the list of body subtrees of a <code>clause</code>
-%% node.
+%% @doc Return the list of body subtrees of a `clause' node.
%%
%% @see clause/3
@@ -3855,10 +3583,8 @@ clause_body(Node) ->
%% =====================================================================
-%% @spec disjunction(List::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract disjunction. If <code>List</code> is
-%% <code>[E1, ..., En]</code>, the result represents
+%% @doc Creates an abstract disjunction. If `List' is
+%% `[E1, ..., En]', the result represents
%% "<code><em>E1</em>; ...; <em>En</em></code>".
%%
%% @see disjunction_body/1
@@ -3874,10 +3600,8 @@ disjunction(Tests) ->
%% =====================================================================
-%% @spec disjunction_body(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of body subtrees of a
-%% <code>disjunction</code> node.
+%% `disjunction' node.
%%
%% @see disjunction/1
@@ -3888,10 +3612,8 @@ disjunction_body(Node) ->
%% =====================================================================
-%% @spec conjunction(List::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract conjunction. If <code>List</code> is
-%% <code>[E1, ..., En]</code>, the result represents
+%% @doc Creates an abstract conjunction. If `List' is
+%% `[E1, ..., En]', the result represents
%% "<code><em>E1</em>, ..., <em>En</em></code>".
%%
%% @see conjunction_body/1
@@ -3907,10 +3629,8 @@ conjunction(Tests) ->
%% =====================================================================
-%% @spec conjunction_body(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of body subtrees of a
-%% <code>conjunction</code> node.
+%% `conjunction' node.
%%
%% @see conjunction/1
@@ -3921,8 +3641,6 @@ conjunction_body(Node) ->
%% =====================================================================
-%% @spec catch_expr(Expr::syntaxTree()) -> syntaxTree()
-%%
%% @doc Creates an abstract catch-expression. The result represents
%% "<code>catch <em>Expr</em></code>".
%%
@@ -3949,9 +3667,7 @@ revert_catch_expr(Node) ->
%% =====================================================================
-%% @spec catch_expr_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>catch_expr</code> node.
+%% @doc Returns the body subtree of a `catch_expr' node.
%%
%% @see catch_expr/1
@@ -3967,9 +3683,6 @@ catch_expr_body(Node) ->
%% =====================================================================
-%% @spec match_expr(Pattern::syntaxTree(), Body::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract match-expression. The result represents
%% "<code><em>Pattern</em> = <em>Body</em></code>".
%%
@@ -4002,9 +3715,7 @@ revert_match_expr(Node) ->
%% =====================================================================
-%% @spec match_expr_pattern(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the pattern subtree of a <code>match_expr</code> node.
+%% @doc Returns the pattern subtree of a `match_expr' node.
%%
%% @see match_expr/2
@@ -4020,9 +3731,7 @@ match_expr_pattern(Node) ->
%% =====================================================================
-%% @spec match_expr_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>match_expr</code> node.
+%% @doc Returns the body subtree of a `match_expr' node.
%%
%% @see match_expr/2
@@ -4038,15 +3747,12 @@ match_expr_body(Node) ->
%% =====================================================================
-%% @spec operator(Name) -> syntaxTree()
-%% Name = atom() | string()
-%%
%% @doc Creates an abstract operator. The name of the operator is the
-%% character sequence represented by <code>Name</code>. This is
+%% character sequence represented by `Name'. This is
%% analogous to the print name of an atom, but an operator is never
%% written within single-quotes; e.g., the result of
-%% <code>operator('++')</code> represents "<code>++</code>" rather
-%% than "<code>'++'</code>".
+%% `operator('++')' represents "`++'" rather
+%% than "`'++''".
%%
%% @see operator_name/1
%% @see operator_literal/1
@@ -4064,9 +3770,7 @@ operator(Name) ->
%% =====================================================================
-%% @spec operator_name(syntaxTree()) -> atom()
-%%
-%% @doc Returns the name of an <code>operator</code> node. Note that
+%% @doc Returns the name of an `operator' node. Note that
%% the name is returned as an atom.
%%
%% @see operator/1
@@ -4078,11 +3782,8 @@ operator_name(Node) ->
%% =====================================================================
-%% @spec operator_literal(syntaxTree()) -> string()
-%%
%% @doc Returns the literal string represented by an
-%% <code>operator</code> node. This is simply the operator name as a
-%% string.
+%% `operator' node. This is simply the operator name as a string.
%%
%% @see operator/1
@@ -4093,9 +3794,6 @@ operator_literal(Node) ->
%% =====================================================================
-%% @spec infix_expr(Left::syntaxTree(), Operator::syntaxTree(),
-%% Right::syntaxTree()) -> syntaxTree()
-%%
%% @doc Creates an abstract infix operator expression. The result
%% represents "<code><em>Left</em> <em>Operator</em>
%% <em>Right</em></code>".
@@ -4144,10 +3842,8 @@ revert_infix_expr(Node) ->
%% =====================================================================
-%% @spec infix_expr_left(syntaxTree()) -> syntaxTree()
-%%
%% @doc Returns the left argument subtree of an
-%% <code>infix_expr</code> node.
+%% `infix_expr' node.
%%
%% @see infix_expr/3
@@ -4163,10 +3859,7 @@ infix_expr_left(Node) ->
%% =====================================================================
-%% @spec infix_expr_operator(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the operator subtree of an <code>infix_expr</code>
-%% node.
+%% @doc Returns the operator subtree of an `infix_expr' node.
%%
%% @see infix_expr/3
@@ -4182,10 +3875,8 @@ infix_expr_operator(Node) ->
%% =====================================================================
-%% @spec infix_expr_right(syntaxTree()) -> syntaxTree()
-%%
%% @doc Returns the right argument subtree of an
-%% <code>infix_expr</code> node.
+%% `infix_expr' node.
%%
%% @see infix_expr/3
@@ -4201,9 +3892,6 @@ infix_expr_right(Node) ->
%% =====================================================================
-%% @spec prefix_expr(Operator::syntaxTree(), Argument::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract prefix operator expression. The result
%% represents "<code><em>Operator</em> <em>Argument</em></code>".
%%
@@ -4247,10 +3935,7 @@ revert_prefix_expr(Node) ->
%% =====================================================================
-%% @spec prefix_expr_operator(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the operator subtree of a <code>prefix_expr</code>
-%% node.
+%% @doc Returns the operator subtree of a `prefix_expr' node.
%%
%% @see prefix_expr/2
@@ -4266,10 +3951,7 @@ prefix_expr_operator(Node) ->
%% =====================================================================
-%% @spec prefix_expr_argument(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the argument subtree of a <code>prefix_expr</code>
-%% node.
+%% @doc Returns the argument subtree of a `prefix_expr' node.
%%
%% @see prefix_expr/2
@@ -4285,7 +3967,6 @@ prefix_expr_argument(Node) ->
%% =====================================================================
-%% @spec record_field(Name) -> syntaxTree()
%% @equiv record_field(Name, none)
-spec record_field(syntaxTree()) -> syntaxTree().
@@ -4295,11 +3976,8 @@ record_field(Name) ->
%% =====================================================================
-%% @spec record_field(Name::syntaxTree(), Value) -> syntaxTree()
-%% Value = none | syntaxTree()
-%%
%% @doc Creates an abstract record field specification. If
-%% <code>Value</code> is <code>none</code>, the result represents
+%% `Value' is `none', the result represents
%% simply "<code><em>Name</em></code>", otherwise it represents
%% "<code><em>Name</em> = <em>Value</em></code>".
%%
@@ -4321,9 +3999,7 @@ record_field(Name, Value) ->
%% =====================================================================
-%% @spec record_field_name(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the name subtree of a <code>record_field</code> node.
+%% @doc Returns the name subtree of a `record_field' node.
%%
%% @see record_field/2
@@ -4334,13 +4010,11 @@ record_field_name(Node) ->
%% =====================================================================
-%% @spec record_field_value(syntaxTree()) -> none | syntaxTree()
-%%
-%% @doc Returns the value subtree of a <code>record_field</code> node,
-%% if any. If <code>Node</code> represents
-%% "<code><em>Name</em></code>", <code>none</code> is
-%% returned. Otherwise, if <code>Node</code> represents
-%% "<code><em>Name</em> = <em>Value</em></code>", <code>Value</code>
+%% @doc Returns the value subtree of a `record_field' node,
+%% if any. If `Node' represents
+%% "<code><em>Name</em></code>", `none' is
+%% returned. Otherwise, if `Node' represents
+%% "<code><em>Name</em> = <em>Value</em></code>", `Value'
%% is returned.
%%
%% @see record_field/2
@@ -4352,15 +4026,12 @@ record_field_value(Node) ->
%% =====================================================================
-%% @spec record_index_expr(Type::syntaxTree(), Field::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract record field index expression. The result
%% represents "<code>#<em>Type</em>.<em>Field</em></code>".
%%
-%% <p>(Note: the function name <code>record_index/2</code> is reserved
+%% (Note: the function name `record_index/2' is reserved
%% by the Erlang compiler, which is why that name could not be used
-%% for this constructor.)</p>
+%% for this constructor.)
%%
%% @see record_index_expr_type/1
%% @see record_index_expr_field/1
@@ -4399,10 +4070,7 @@ revert_record_index_expr(Node) ->
%% =====================================================================
-%% @spec record_index_expr_type(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the type subtree of a <code>record_index_expr</code>
-%% node.
+%% @doc Returns the type subtree of a `record_index_expr' node.
%%
%% @see record_index_expr/2
@@ -4418,10 +4086,7 @@ record_index_expr_type(Node) ->
%% =====================================================================
-%% @spec record_index_expr_field(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the field subtree of a <code>record_index_expr</code>
-%% node.
+%% @doc Returns the field subtree of a `record_index_expr' node.
%%
%% @see record_index_expr/2
@@ -4437,7 +4102,6 @@ record_index_expr_field(Node) ->
%% =====================================================================
-%% @spec record_access(Argument, Field) -> syntaxTree()
%% @equiv record_access(Argument, none, Field)
-spec record_access(syntaxTree(), syntaxTree()) -> syntaxTree().
@@ -4447,17 +4111,13 @@ record_access(Argument, Field) ->
%% =====================================================================
-%% @spec record_access(Argument::syntaxTree(), Type,
-%% Field::syntaxTree()) -> syntaxTree()
-%% Type = none | syntaxTree()
-%%
%% @doc Creates an abstract record field access expression. If
-%% <code>Type</code> is not <code>none</code>, the result represents
+%% `Type' is not `none', the result represents
%% "<code><em>Argument</em>#<em>Type</em>.<em>Field</em></code>".
%%
-%% <p>If <code>Type</code> is <code>none</code>, the result represents
+%% If `Type' is `none', the result represents
%% "<code><em>Argument</em>.<em>Field</em></code>". This is a special
-%% form only allowed within Mnemosyne queries.</p>
+%% form only allowed within Mnemosyne queries.
%%
%% @see record_access/2
%% @see record_access_argument/1
@@ -4512,10 +4172,7 @@ revert_record_access(Node) ->
%% =====================================================================
-%% @spec record_access_argument(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the argument subtree of a <code>record_access</code>
-%% node.
+%% @doc Returns the argument subtree of a `record_access' node.
%%
%% @see record_access/3
@@ -4533,14 +4190,12 @@ record_access_argument(Node) ->
%% =====================================================================
-%% @spec record_access_type(syntaxTree()) -> none | syntaxTree()
-%%
-%% @doc Returns the type subtree of a <code>record_access</code> node,
-%% if any. If <code>Node</code> represents
-%% "<code><em>Argument</em>.<em>Field</em></code>", <code>none</code>
-%% is returned, otherwise if <code>Node</code> represents
+%% @doc Returns the type subtree of a `record_access' node,
+%% if any. If `Node' represents
+%% "<code><em>Argument</em>.<em>Field</em></code>", `none'
+%% is returned, otherwise if `Node' represents
%% "<code><em>Argument</em>#<em>Type</em>.<em>Field</em></code>",
-%% <code>Type</code> is returned.
+%% `Type' is returned.
%%
%% @see record_access/3
@@ -4558,10 +4213,7 @@ record_access_type(Node) ->
%% =====================================================================
-%% @spec record_access_field(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the field subtree of a <code>record_access</code>
-%% node.
+%% @doc Returns the field subtree of a `record_access' node.
%%
%% @see record_access/3
@@ -4579,7 +4231,6 @@ record_access_field(Node) ->
%% =====================================================================
-%% @spec record_expr(Type, Fields) -> syntaxTree()
%% @equiv record_expr(none, Type, Fields)
-spec record_expr(syntaxTree(), [syntaxTree()]) -> syntaxTree().
@@ -4589,13 +4240,9 @@ record_expr(Type, Fields) ->
%% =====================================================================
-%% @spec record_expr(Argument, Type::syntaxTree(),
-%% Fields::[syntaxTree()]) -> syntaxTree()
-%% Argument = none | syntaxTree()
-%%
-%% @doc Creates an abstract record expression. If <code>Fields</code> is
-%% <code>[F1, ..., Fn]</code>, then if <code>Argument</code> is
-%% <code>none</code>, the result represents
+%% @doc Creates an abstract record expression. If `Fields' is
+%% `[F1, ..., Fn]', then if `Argument' is
+%% `none', the result represents
%% "<code>#<em>Type</em>{<em>F1</em>, ..., <em>Fn</em>}</code>",
%% otherwise it represents
%% "<code><em>Argument</em>#<em>Type</em>{<em>F1</em>, ...,
@@ -4661,14 +4308,12 @@ revert_record_expr(Node) ->
%% =====================================================================
-%% @spec record_expr_argument(syntaxTree()) -> none | syntaxTree()
-%%
-%% @doc Returns the argument subtree of a <code>record_expr</code> node,
-%% if any. If <code>Node</code> represents
-%% "<code>#<em>Type</em>{...}</code>", <code>none</code> is returned.
-%% Otherwise, if <code>Node</code> represents
+%% @doc Returns the argument subtree of a `record_expr' node,
+%% if any. If `Node' represents
+%% "<code>#<em>Type</em>{...}</code>", `none' is returned.
+%% Otherwise, if `Node' represents
%% "<code><em>Argument</em>#<em>Type</em>{...}</code>",
-%% <code>Argument</code> is returned.
+%% `Argument' is returned.
%%
%% @see record_expr/3
@@ -4686,9 +4331,7 @@ record_expr_argument(Node) ->
%% =====================================================================
-%% @spec record_expr_type(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the type subtree of a <code>record_expr</code> node.
+%% @doc Returns the type subtree of a `record_expr' node.
%%
%% @see record_expr/3
@@ -4706,10 +4349,8 @@ record_expr_type(Node) ->
%% =====================================================================
-%% @spec record_expr_fields(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of field subtrees of a
-%% <code>record_expr</code> node.
+%% `record_expr' node.
%%
%% @see record_expr/3
@@ -4727,15 +4368,11 @@ record_expr_fields(Node) ->
%% =====================================================================
-%% @spec application(Module, Function::syntaxTree(),
-%% Arguments::[syntaxTree()]) -> syntaxTree()
-%% Module = none | syntaxTree()
-%%
%% @doc Creates an abstract function application expression. If
-%% <code>Module</code> is <code>none</code>, this is call is equivalent
-%% to <code>application(Function, Arguments)</code>, otherwise it is
-%% equivalent to <code>application(module_qualifier(Module, Function),
-%% Arguments)</code>.
+%% `Module' is `none', this is call is equivalent
+%% to `application(Function, Arguments)', otherwise it is
+%% equivalent to `application(module_qualifier(Module, Function),
+%% Arguments)'.
%%
%% (This is a utility function.)
%%
@@ -4752,11 +4389,8 @@ application(Module, Name, Arguments) ->
%% =====================================================================
-%% @spec application(Operator::syntaxTree(),
-%% Arguments::[syntaxTree()]) -> syntaxTree()
-%%
%% @doc Creates an abstract function application expression. If
-%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
+%% `Arguments' is `[A1, ..., An]', the result
%% represents "<code><em>Operator</em>(<em>A1</em>, ...,
%% <em>An</em>)</code>".
%%
@@ -4794,14 +4428,11 @@ revert_application(Node) ->
%% =====================================================================
-%% @spec application_operator(syntaxTree()) -> syntaxTree()
+%% @doc Returns the operator subtree of an `application' node.
%%
-%% @doc Returns the operator subtree of an <code>application</code>
-%% node.
-%%
-%% <p>Note: if <code>Node</code> represents
+%% Note: if `Node' represents
%% "<code><em>M</em>:<em>F</em>(...)</code>", then the result is the
-%% subtree representing "<code><em>M</em>:<em>F</em></code>".</p>
+%% subtree representing "<code><em>M</em>:<em>F</em></code>".
%%
%% @see application/2
%% @see module_qualifier/2
@@ -4818,10 +4449,8 @@ application_operator(Node) ->
%% =====================================================================
-%% @spec application_arguments(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of argument subtrees of an
-%% <code>application</code> node.
+%% `application' node.
%%
%% @see application/2
@@ -4837,11 +4466,8 @@ application_arguments(Node) ->
%% =====================================================================
-%% @spec list_comp(Template::syntaxTree(), Body::[syntaxTree()]) ->
-%% syntaxTree()
-%%
-%% @doc Creates an abstract list comprehension. If <code>Body</code> is
-%% <code>[E1, ..., En]</code>, the result represents
+%% @doc Creates an abstract list comprehension. If `Body' is
+%% `[E1, ..., En]', the result represents
%% "<code>[<em>Template</em> || <em>E1</em>, ..., <em>En</em>]</code>".
%%
%% @see list_comp_template/1
@@ -4876,9 +4502,7 @@ revert_list_comp(Node) ->
%% =====================================================================
-%% @spec list_comp_template(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the template subtree of a <code>list_comp</code> node.
+%% @doc Returns the template subtree of a `list_comp' node.
%%
%% @see list_comp/2
@@ -4894,10 +4518,7 @@ list_comp_template(Node) ->
%% =====================================================================
-%% @spec list_comp_body(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of body subtrees of a <code>list_comp</code>
-%% node.
+%% @doc Returns the list of body subtrees of a `list_comp' node.
%%
%% @see list_comp/2
@@ -4912,11 +4533,8 @@ list_comp_body(Node) ->
end.
%% =====================================================================
-%% @spec binary_comp(Template::syntaxTree(), Body::[syntaxTree()]) ->
-%% syntaxTree()
-%%
-%% @doc Creates an abstract binary comprehension. If <code>Body</code> is
-%% <code>[E1, ..., En]</code>, the result represents
+%% @doc Creates an abstract binary comprehension. If `Body' is
+%% `[E1, ..., En]', the result represents
%% "<code>&lt;&lt;<em>Template</em> || <em>E1</em>, ..., <em>En</em>&gt;&gt;</code>".
%%
%% @see binary_comp_template/1
@@ -4951,9 +4569,7 @@ revert_binary_comp(Node) ->
%% =====================================================================
-%% @spec binary_comp_template(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the template subtree of a <code>binary_comp</code> node.
+%% @doc Returns the template subtree of a `binary_comp' node.
%%
%% @see binary_comp/2
@@ -4969,10 +4585,7 @@ binary_comp_template(Node) ->
%% =====================================================================
-%% @spec binary_comp_body(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of body subtrees of a <code>binary_comp</code>
-%% node.
+%% @doc Returns the list of body subtrees of a `binary_comp' node.
%%
%% @see binary_comp/2
@@ -4988,8 +4601,6 @@ binary_comp_body(Node) ->
%% =====================================================================
-%% @spec query_expr(Body::syntaxTree()) -> syntaxTree()
-%%
%% @doc Creates an abstract Mnemosyne query expression. The result
%% represents "<code>query <em>Body</em> end</code>".
%%
@@ -5018,9 +4629,7 @@ revert_query_expr(Node) ->
%% =====================================================================
-%% @spec query_expr_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>query_expr</code> node.
+%% @doc Returns the body subtree of a `query_expr' node.
%%
%% @see query_expr/1
@@ -5036,13 +4645,10 @@ query_expr_body(Node) ->
%% =====================================================================
-%% @spec rule(Name::syntaxTree(), Clauses::[syntaxTree()]) ->
-%% syntaxTree()
-%%
-%% @doc Creates an abstract Mnemosyne rule. If <code>Clauses</code> is
-%% <code>[C1, ..., Cn]</code>, the results represents
+%% @doc Creates an abstract Mnemosyne rule. If `Clauses' is
+%% `[C1, ..., Cn]', the results represents
%% "<code><em>Name</em> <em>C1</em>; ...; <em>Name</em>
-%% <em>Cn</em>.</code>". More exactly, if each <code>Ci</code>
+%% <em>Cn</em>.</code>". More exactly, if each `Ci'
%% represents "<code>(<em>Pi1</em>, ..., <em>Pim</em>) <em>Gi</em> ->
%% <em>Bi</em></code>", then the result represents
%% "<code><em>Name</em>(<em>P11</em>, ..., <em>P1m</em>) <em>G1</em> :-
@@ -5097,9 +4703,7 @@ revert_rule(Node) ->
%% =====================================================================
-%% @spec rule_name(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the name subtree of a <code>rule</code> node.
+%% @doc Returns the name subtree of a `rule' node.
%%
%% @see rule/2
@@ -5114,9 +4718,7 @@ rule_name(Node) ->
end.
%% =====================================================================
-%% @spec rule_clauses(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of clause subtrees of a <code>rule</code> node.
+%% @doc Returns the list of clause subtrees of a `rule' node.
%%
%% @see rule/2
@@ -5131,16 +4733,14 @@ rule_clauses(Node) ->
end.
%% =====================================================================
-%% @spec rule_arity(Node::syntaxTree()) -> integer()
-%%
-%% @doc Returns the arity of a <code>rule</code> node. The result is the
+%% @doc Returns the arity of a `rule' node. The result is the
%% number of parameter patterns in the first clause of the rule;
%% subsequent clauses are ignored.
%%
-%% <p>An exception is thrown if <code>rule_clauses(Node)</code> returns
+%% An exception is thrown if `rule_clauses(Node)' returns
%% an empty list, or if the first element of that list is not a syntax
-%% tree <code>C</code> of type <code>clause</code> such that
-%% <code>clause_patterns(C)</code> is a nonempty list.</p>
+%% tree `C' of type `clause' such that
+%% `clause_patterns(C)' is a nonempty list.
%%
%% @see rule/2
%% @see rule_clauses/1
@@ -5156,9 +4756,6 @@ rule_arity(Node) ->
%% =====================================================================
-%% @spec generator(Pattern::syntaxTree(), Body::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract generator. The result represents
%% "<code><em>Pattern</em> &lt;- <em>Body</em></code>".
%%
@@ -5193,9 +4790,7 @@ revert_generator(Node) ->
%% =====================================================================
-%% @spec generator_pattern(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the pattern subtree of a <code>generator</code> node.
+%% @doc Returns the pattern subtree of a `generator' node.
%%
%% @see generator/2
@@ -5211,9 +4806,7 @@ generator_pattern(Node) ->
%% =====================================================================
-%% @spec generator_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>generator</code> node.
+%% @doc Returns the body subtree of a `generator' node.
%%
%% @see generator/2
@@ -5229,9 +4822,6 @@ generator_body(Node) ->
%% =====================================================================
-%% @spec binary_generator(Pattern::syntaxTree(), Body::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract binary_generator. The result represents
%% "<code><em>Pattern</em> &lt;- <em>Body</em></code>".
%%
@@ -5266,9 +4856,7 @@ revert_binary_generator(Node) ->
%% =====================================================================
-%% @spec binary_generator_pattern(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the pattern subtree of a <code>generator</code> node.
+%% @doc Returns the pattern subtree of a `generator' node.
%%
%% @see binary_generator/2
@@ -5284,9 +4872,7 @@ binary_generator_pattern(Node) ->
%% =====================================================================
-%% @spec binary_generator_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>generator</code> node.
+%% @doc Returns the body subtree of a `generator' node.
%%
%% @see binary_generator/2
@@ -5302,10 +4888,8 @@ binary_generator_body(Node) ->
%% =====================================================================
-%% @spec block_expr(Body::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract block expression. If <code>Body</code> is
-%% <code>[B1, ..., Bn]</code>, the result represents "<code>begin
+%% @doc Creates an abstract block expression. If `Body' is
+%% `[B1, ..., Bn]', the result represents "<code>begin
%% <em>B1</em>, ..., <em>Bn</em> end</code>".
%%
%% @see block_expr_body/1
@@ -5321,7 +4905,7 @@ binary_generator_body(Node) ->
%%
%% Body = [erl_parse()] \ []
--spec block_expr(Body::[syntaxTree()]) -> syntaxTree().
+-spec block_expr([syntaxTree()]) -> syntaxTree().
block_expr(Body) ->
tree(block_expr, Body).
@@ -5333,10 +4917,7 @@ revert_block_expr(Node) ->
%% =====================================================================
-%% @spec block_expr_body(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of body subtrees of a <code>block_expr</code>
-%% node.
+%% @doc Returns the list of body subtrees of a `block_expr' node.
%%
%% @see block_expr/1
@@ -5352,12 +4933,10 @@ block_expr_body(Node) ->
%% =====================================================================
-%% @spec if_expr(Clauses::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract if-expression. If <code>Clauses</code> is
-%% <code>[C1, ..., Cn]</code>, the result represents "<code>if
+%% @doc Creates an abstract if-expression. If `Clauses' is
+%% `[C1, ..., Cn]', the result represents "<code>if
%% <em>C1</em>; ...; <em>Cn</em> end</code>". More exactly, if each
-%% <code>Ci</code> represents "<code>() <em>Gi</em> ->
+%% `Ci' represents "<code>() <em>Gi</em> ->
%% <em>Bi</em></code>", then the result represents "<code>if
%% <em>G1</em> -> <em>B1</em>; ...; <em>Gn</em> -> <em>Bn</em>
%% end</code>".
@@ -5392,10 +4971,7 @@ revert_if_expr(Node) ->
%% =====================================================================
-%% @spec if_expr_clauses(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of clause subtrees of an <code>if_expr</code>
-%% node.
+%% @doc Returns the list of clause subtrees of an `if_expr' node.
%%
%% @see if_expr/1
@@ -5411,13 +4987,10 @@ if_expr_clauses(Node) ->
%% =====================================================================
-%% @spec case_expr(Argument::syntaxTree(), Clauses::[syntaxTree()]) ->
-%% syntaxTree()
-%%
-%% @doc Creates an abstract case-expression. If <code>Clauses</code> is
-%% <code>[C1, ..., Cn]</code>, the result represents "<code>case
+%% @doc Creates an abstract case-expression. If `Clauses' is
+%% `[C1, ..., Cn]', the result represents "<code>case
%% <em>Argument</em> of <em>C1</em>; ...; <em>Cn</em> end</code>". More
-%% exactly, if each <code>Ci</code> represents "<code>(<em>Pi</em>)
+%% exactly, if each `Ci' represents "<code>(<em>Pi</em>)
%% <em>Gi</em> -> <em>Bi</em></code>", then the result represents
%% "<code>case <em>Argument</em> of <em>P1</em> <em>G1</em> ->
%% <em>B1</em>; ...; <em>Pn</em> <em>Gn</em> -> <em>Bn</em> end</code>".
@@ -5461,9 +5034,7 @@ revert_case_expr(Node) ->
%% =====================================================================
-%% @spec case_expr_argument(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the argument subtree of a <code>case_expr</code> node.
+%% @doc Returns the argument subtree of a `case_expr' node.
%%
%% @see case_expr/2
@@ -5479,10 +5050,7 @@ case_expr_argument(Node) ->
%% =====================================================================
-%% @spec case_expr_clauses(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of clause subtrees of a <code>case_expr</code>
-%% node.
+%% @doc Returns the list of clause subtrees of a `case_expr' node.
%%
%% @see case_expr/2
@@ -5498,12 +5066,10 @@ case_expr_clauses(Node) ->
%% =====================================================================
-%% @spec cond_expr(Clauses::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract cond-expression. If <code>Clauses</code> is
-%% <code>[C1, ..., Cn]</code>, the result represents "<code>cond
+%% @doc Creates an abstract cond-expression. If `Clauses' is
+%% `[C1, ..., Cn]', the result represents "<code>cond
%% <em>C1</em>; ...; <em>Cn</em> end</code>". More exactly, if each
-%% <code>Ci</code> represents "<code>() <em>Ei</em> ->
+%% `Ci' represents "<code>() <em>Ei</em> ->
%% <em>Bi</em></code>", then the result represents "<code>cond
%% <em>E1</em> -> <em>B1</em>; ...; <em>En</em> -> <em>Bn</em>
%% end</code>".
@@ -5538,10 +5104,7 @@ revert_cond_expr(Node) ->
%% =====================================================================
-%% @spec cond_expr_clauses(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of clause subtrees of a <code>cond_expr</code>
-%% node.
+%% @doc Returns the list of clause subtrees of a `cond_expr' node.
%%
%% @see cond_expr/1
@@ -5557,7 +5120,6 @@ cond_expr_clauses(Node) ->
%% =====================================================================
-%% @spec receive_expr(Clauses) -> syntaxTree()
%% @equiv receive_expr(Clauses, none, [])
-spec receive_expr([syntaxTree()]) -> syntaxTree().
@@ -5567,25 +5129,21 @@ receive_expr(Clauses) ->
%% =====================================================================
-%% @spec receive_expr(Clauses::[syntaxTree()], Timeout,
-%% Action::[syntaxTree()]) -> syntaxTree()
-%% Timeout = none | syntaxTree()
-%%
-%% @doc Creates an abstract receive-expression. If <code>Timeout</code>
-%% is <code>none</code>, the result represents "<code>receive
-%% <em>C1</em>; ...; <em>Cn</em> end</code>" (the <code>Action</code>
-%% argument is ignored). Otherwise, if <code>Clauses</code> is
-%% <code>[C1, ..., Cn]</code> and <code>Action</code> is <code>[A1, ...,
-%% Am]</code>, the result represents "<code>receive <em>C1</em>; ...;
+%% @doc Creates an abstract receive-expression. If `Timeout'
+%% is `none', the result represents "<code>receive
+%% <em>C1</em>; ...; <em>Cn</em> end</code>" (the `Action'
+%% argument is ignored). Otherwise, if `Clauses' is
+%% `[C1, ..., Cn]' and `Action' is `[A1, ...,
+%% Am]', the result represents "<code>receive <em>C1</em>; ...;
%% <em>Cn</em> after <em>Timeout</em> -> <em>A1</em>, ..., <em>Am</em>
-%% end</code>". More exactly, if each <code>Ci</code> represents
+%% end</code>". More exactly, if each `Ci' represents
%% "<code>(<em>Pi</em>) <em>Gi</em> -> <em>Bi</em></code>", then the
%% result represents "<code>receive <em>P1</em> <em>G1</em> ->
%% <em>B1</em>; ...; <em>Pn</em> <em>Gn</em> -> <em>Bn</em> ...
%% end</code>".
%%
-%% <p>Note that in Erlang, a receive-expression must have at least one
-%% clause if no timeout part is specified.</p>
+%% Note that in Erlang, a receive-expression must have at least one
+%% clause if no timeout part is specified.
%%
%% @see receive_expr_clauses/1
%% @see receive_expr_timeout/1
@@ -5649,11 +5207,8 @@ revert_receive_expr(Node) ->
%% =====================================================================
-%% @spec receive_expr_clauses(syntaxTree()) -> [syntaxTree()]
-%% type(Node) = receive_expr
-%%
%% @doc Returns the list of clause subtrees of a
-%% <code>receive_expr</code> node.
+%% `receive_expr' node.
%%
%% @see receive_expr/3
@@ -5671,15 +5226,12 @@ receive_expr_clauses(Node) ->
%% =====================================================================
-%% @spec receive_expr_timeout(Node::syntaxTree()) -> Timeout
-%% Timeout = none | syntaxTree()
-%%
-%% @doc Returns the timeout subtree of a <code>receive_expr</code> node,
-%% if any. If <code>Node</code> represents "<code>receive <em>C1</em>;
-%% ...; <em>Cn</em> end</code>", <code>none</code> is returned.
-%% Otherwise, if <code>Node</code> represents "<code>receive
+%% @doc Returns the timeout subtree of a `receive_expr' node,
+%% if any. If `Node' represents "<code>receive <em>C1</em>;
+%% ...; <em>Cn</em> end</code>", `none' is returned.
+%% Otherwise, if `Node' represents "<code>receive
%% <em>C1</em>; ...; <em>Cn</em> after <em>Timeout</em> -> ... end</code>",
-%% <code>Timeout</code> is returned.
+%% `Timeout' is returned.
%%
%% @see receive_expr/3
@@ -5697,10 +5249,8 @@ receive_expr_timeout(Node) ->
%% =====================================================================
-%% @spec receive_expr_action(Node::syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of action body subtrees of a
-%% <code>receive_expr</code> node. If <code>Node</code> represents
+%% `receive_expr' node. If `Node' represents
%% "<code>receive <em>C1</em>; ...; <em>Cn</em> end</code>", this is the
%% empty list.
%%
@@ -5720,8 +5270,6 @@ receive_expr_action(Node) ->
%% =====================================================================
-%% @spec try_expr(Body::syntaxTree(), Handlers::[syntaxTree()]) ->
-%% syntaxTree()
%% @equiv try_expr(Body, [], Handlers)
-spec try_expr([syntaxTree()], [syntaxTree()]) -> syntaxTree().
@@ -5731,8 +5279,6 @@ try_expr(Body, Handlers) ->
%% =====================================================================
-%% @spec try_expr(Body::syntaxTree(), Clauses::[syntaxTree()],
-%% Handlers::[syntaxTree()]) -> syntaxTree()
%% @equiv try_expr(Body, Clauses, Handlers, [])
-spec try_expr([syntaxTree()], [syntaxTree()], [syntaxTree()]) -> syntaxTree().
@@ -5742,8 +5288,6 @@ try_expr(Body, Clauses, Handlers) ->
%% =====================================================================
-%% @spec try_after_expr(Body::syntaxTree(), After::[syntaxTree()]) ->
-%% syntaxTree()
%% @equiv try_expr(Body, [], [], After)
-spec try_after_expr([syntaxTree()], [syntaxTree()]) -> syntaxTree().
@@ -5753,30 +5297,26 @@ try_after_expr(Body, After) ->
%% =====================================================================
-%% @spec try_expr(Body::[syntaxTree()], Clauses::[syntaxTree()],
-%% Handlers::[syntaxTree()], After::[syntaxTree()]) ->
-%% syntaxTree()
-%%
-%% @doc Creates an abstract try-expression. If <code>Body</code> is
-%% <code>[B1, ..., Bn]</code>, <code>Clauses</code> is <code>[C1, ...,
-%% Cj]</code>, <code>Handlers</code> is <code>[H1, ..., Hk]</code>, and
-%% <code>After</code> is <code>[A1, ..., Am]</code>, the result
+%% @doc Creates an abstract try-expression. If `Body' is
+%% `[B1, ..., Bn]', `Clauses' is `[C1, ...,
+%% Cj]', `Handlers' is `[H1, ..., Hk]', and
+%% `After' is `[A1, ..., Am]', the result
%% represents "<code>try <em>B1</em>, ..., <em>Bn</em> of <em>C1</em>;
%% ...; <em>Cj</em> catch <em>H1</em>; ...; <em>Hk</em> after
%% <em>A1</em>, ..., <em>Am</em> end</code>". More exactly, if each
-%% <code>Ci</code> represents "<code>(<em>CPi</em>) <em>CGi</em> ->
-%% <em>CBi</em></code>", and each <code>Hi</code> represents
+%% `Ci' represents "<code>(<em>CPi</em>) <em>CGi</em> ->
+%% <em>CBi</em></code>", and each `Hi' represents
%% "<code>(<em>HPi</em>) <em>HGi</em> -> <em>HBi</em></code>", then the
%% result represents "<code>try <em>B1</em>, ..., <em>Bn</em> of
%% <em>CP1</em> <em>CG1</em> -> <em>CB1</em>; ...; <em>CPj</em>
%% <em>CGj</em> -> <em>CBj</em> catch <em>HP1</em> <em>HG1</em> ->
%% <em>HB1</em>; ...; <em>HPk</em> <em>HGk</em> -> <em>HBk</em> after
-%% <em>A1</em>, ..., <em>Am</em> end</code>"; cf.
-%% <code>case_expr/2</code>. If <code>Clauses</code> is the empty list,
-%% the <code>of ...</code> section is left out. If <code>After</code> is
-%% the empty list, the <code>after ...</code> section is left out. If
-%% <code>Handlers</code> is the empty list, and <code>After</code> is
-%% nonempty, the <code>catch ...</code> section is left out.
+%% <em>A1</em>, ..., <em>Am</em> end</code>"; see
+%% {@link case_expr/2}. If `Clauses' is the empty list,
+%% the `of ...' section is left out. If `After' is
+%% the empty list, the `after ...' section is left out. If
+%% `Handlers' is the empty list, and `After' is
+%% nonempty, the `catch ...' section is left out.
%%
%% @see try_expr_body/1
%% @see try_expr_clauses/1
@@ -5834,10 +5374,7 @@ revert_try_expr(Node) ->
%% =====================================================================
-%% @spec try_expr_body(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of body subtrees of a <code>try_expr</code>
-%% node.
+%% @doc Returns the list of body subtrees of a `try_expr' node.
%%
%% @see try_expr/4
@@ -5853,10 +5390,8 @@ try_expr_body(Node) ->
%% =====================================================================
-%% @spec try_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of case-clause subtrees of a
-%% <code>try_expr</code> node. If <code>Node</code> represents
+%% `try_expr' node. If `Node' represents
%% "<code>try <em>Body</em> catch <em>H1</em>; ...; <em>Hn</em>
%% end</code>", the result is the empty list.
%%
@@ -5874,10 +5409,8 @@ try_expr_clauses(Node) ->
%% =====================================================================
-%% @spec try_expr_handlers(syntaxTree()) -> [syntaxTree()]
-%%
%% @doc Returns the list of handler-clause subtrees of a
-%% <code>try_expr</code> node.
+%% `try_expr' node.
%%
%% @see try_expr/4
@@ -5893,10 +5426,7 @@ try_expr_handlers(Node) ->
%% =====================================================================
-%% @spec try_expr_after(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of "after" subtrees of a <code>try_expr</code>
-%% node.
+%% @doc Returns the list of "after" subtrees of a `try_expr' node.
%%
%% @see try_expr/4
@@ -5912,9 +5442,6 @@ try_expr_after(Node) ->
%% =====================================================================
-%% @spec class_qualifier(Class::syntaxTree(), Body::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract class qualifier. The result represents
%% "<code><em>Class</em>:<em>Body</em></code>".
%%
@@ -5937,10 +5464,8 @@ class_qualifier(Class, Body) ->
%% =====================================================================
-%% @spec class_qualifier_argument(syntaxTree()) -> syntaxTree()
-%%
%% @doc Returns the argument (the class) subtree of a
-%% <code>class_qualifier</code> node.
+%% `class_qualifier' node.
%%
%% @see class_qualifier/2
@@ -5951,9 +5476,7 @@ class_qualifier_argument(Node) ->
%% =====================================================================
-%% @spec class_qualifier_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>class_qualifier</code> node.
+%% @doc Returns the body subtree of a `class_qualifier' node.
%%
%% @see class_qualifier/2
@@ -5964,13 +5487,10 @@ class_qualifier_body(Node) ->
%% =====================================================================
-%% @spec implicit_fun(Name::syntaxTree(), Arity::syntaxTree()) ->
-%% syntaxTree()
-%%
%% @doc Creates an abstract "implicit fun" expression. If
-%% <code>Arity</code> is <code>none</code>, this is equivalent to
-%% <code>implicit_fun(Name)</code>, otherwise it is equivalent to
-%% <code>implicit_fun(arity_qualifier(Name, Arity))</code>.
+%% `Arity' is `none', this is equivalent to
+%% `implicit_fun(Name)', otherwise it is equivalent to
+%% `implicit_fun(arity_qualifier(Name, Arity))'.
%%
%% (This is a utility function.)
%%
@@ -5986,14 +5506,11 @@ implicit_fun(Name, Arity) ->
%% =====================================================================
-%% @spec implicit_fun(Module::syntaxTree(), Name::syntaxTree(),
-%% Arity::syntaxTree()) -> syntaxTree()
-%%
%% @doc Creates an abstract module-qualified "implicit fun" expression.
-%% If <code>Module</code> is <code>none</code>, this is equivalent to
-%% <code>implicit_fun(Name, Arity)</code>, otherwise it is equivalent to
-%% <code>implicit_fun(module_qualifier(Module, arity_qualifier(Name,
-%% Arity))</code>.
+%% If `Module' is `none', this is equivalent to
+%% `implicit_fun(Name, Arity)', otherwise it is equivalent to
+%% `implicit_fun(module_qualifier(Module, arity_qualifier(Name,
+%% Arity))'.
%%
%% (This is a utility function.)
%%
@@ -6010,10 +5527,8 @@ implicit_fun(Module, Name, Arity) ->
%% =====================================================================
-%% @spec implicit_fun(Name::syntaxTree()) -> syntaxTree()
-%%
%% @doc Creates an abstract "implicit fun" expression. The result
-%% represents "<code>fun <em>Name</em></code>". <code>Name</code> should
+%% represents "<code>fun <em>Name</em></code>". `Name' should
%% represent either <code><em>F</em>/<em>A</em></code> or
%% <code><em>M</em>:<em>F</em>/<em>A</em></code>
%%
@@ -6072,15 +5587,13 @@ revert_implicit_fun(Node) ->
%% =====================================================================
-%% @spec implicit_fun_name(Node::syntaxTree()) -> syntaxTree()
+%% @doc Returns the name subtree of an `implicit_fun' node.
%%
-%% @doc Returns the name subtree of an <code>implicit_fun</code> node.
-%%
-%% <p>Note: if <code>Node</code> represents "<code>fun
+%% Note: if `Node' represents "<code>fun
%% <em>N</em>/<em>A</em></code>" or "<code>fun
%% <em>M</em>:<em>N</em>/<em>A</em></code>", then the result is the
%% subtree representing "<code><em>N</em>/<em>A</em></code>" or
-%% "<code><em>M</em>:<em>N</em>/<em>A</em></code>", respectively.</p>
+%% "<code><em>M</em>:<em>N</em>/<em>A</em></code>", respectively.
%%
%% @see implicit_fun/1
%% @see arity_qualifier/2
@@ -6093,23 +5606,27 @@ implicit_fun_name(Node) ->
{'fun', Pos, {function, Atom, Arity}} ->
arity_qualifier(set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos));
- {'fun', Pos, {function, Module, Atom, Arity}} ->
+ {'fun', Pos, {function, Module, Atom, Arity}}
+ when is_atom(Module), is_atom(Atom), is_integer(Arity) ->
+ %% Backward compatibility with pre-R15 abstract format.
module_qualifier(set_pos(atom(Module), Pos),
arity_qualifier(
set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos)));
+ {'fun', _Pos, {function, Module, Atom, Arity}} ->
+ %% New in R15: fun M:F/A.
+ %% XXX: Perhaps set position for this as well?
+ module_qualifier(Module, arity_qualifier(Atom, Arity));
Node1 ->
data(Node1)
end.
%% =====================================================================
-%% @spec fun_expr(Clauses::[syntaxTree()]) -> syntaxTree()
-%%
-%% @doc Creates an abstract fun-expression. If <code>Clauses</code> is
-%% <code>[C1, ..., Cn]</code>, the result represents "<code>fun
+%% @doc Creates an abstract fun-expression. If `Clauses' is
+%% `[C1, ..., Cn]', the result represents "<code>fun
%% <em>C1</em>; ...; <em>Cn</em> end</code>". More exactly, if each
-%% <code>Ci</code> represents "<code>(<em>Pi1</em>, ..., <em>Pim</em>)
+%% `Ci' represents "<code>(<em>Pi1</em>, ..., <em>Pim</em>)
%% <em>Gi</em> -> <em>Bi</em></code>", then the result represents
%% "<code>fun (<em>P11</em>, ..., <em>P1m</em>) <em>G1</em> ->
%% <em>B1</em>; ...; (<em>Pn1</em>, ..., <em>Pnm</em>) <em>Gn</em> ->
@@ -6146,10 +5663,7 @@ revert_fun_expr(Node) ->
%% =====================================================================
-%% @spec fun_expr_clauses(syntaxTree()) -> [syntaxTree()]
-%%
-%% @doc Returns the list of clause subtrees of a <code>fun_expr</code>
-%% node.
+%% @doc Returns the list of clause subtrees of a `fun_expr' node.
%%
%% @see fun_expr/1
@@ -6165,16 +5679,14 @@ fun_expr_clauses(Node) ->
%% =====================================================================
-%% @spec fun_expr_arity(syntaxTree()) -> integer()
-%%
-%% @doc Returns the arity of a <code>fun_expr</code> node. The result is
+%% @doc Returns the arity of a `fun_expr' node. The result is
%% the number of parameter patterns in the first clause of the
%% fun-expression; subsequent clauses are ignored.
%%
-%% <p>An exception is thrown if <code>fun_expr_clauses(Node)</code>
+%% An exception is thrown if `fun_expr_clauses(Node)'
%% returns an empty list, or if the first element of that list is not a
-%% syntax tree <code>C</code> of type <code>clause</code> such that
-%% <code>clause_patterns(C)</code> is a nonempty list.</p>
+%% syntax tree `C' of type `clause' such that
+%% `clause_patterns(C)' is a nonempty list.
%%
%% @see fun_expr/1
%% @see fun_expr_clauses/1
@@ -6188,8 +5700,6 @@ fun_expr_arity(Node) ->
%% =====================================================================
-%% @spec parentheses(Body::syntaxTree()) -> syntaxTree()
-%%
%% @doc Creates an abstract parenthesised expression. The result
%% represents "<code>(<em>Body</em>)</code>", independently of the
%% context.
@@ -6209,9 +5719,7 @@ revert_parentheses(Node) ->
%% =====================================================================
-%% @spec parentheses_body(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the body subtree of a <code>parentheses</code> node.
+%% @doc Returns the body subtree of a `parentheses' node.
%%
%% @see parentheses/1
@@ -6222,7 +5730,6 @@ parentheses_body(Node) ->
%% =====================================================================
-%% @spec macro(Name) -> syntaxTree()
%% @equiv macro(Name, none)
-spec macro(syntaxTree()) -> syntaxTree().
@@ -6232,25 +5739,22 @@ macro(Name) ->
%% =====================================================================
-%% @spec macro(Name::syntaxTree(), Arguments) -> syntaxTree()
-%% Arguments = none | [syntaxTree()]
-%%
-%% @doc Creates an abstract macro application. If <code>Arguments</code>
-%% is <code>none</code>, the result represents
-%% "<code>?<em>Name</em></code>", otherwise, if <code>Arguments</code>
-%% is <code>[A1, ..., An]</code>, the result represents
+%% @doc Creates an abstract macro application. If `Arguments'
+%% is `none', the result represents
+%% "<code>?<em>Name</em></code>", otherwise, if `Arguments'
+%% is `[A1, ..., An]', the result represents
%% "<code>?<em>Name</em>(<em>A1</em>, ..., <em>An</em>)</code>".
%%
-%% <p>Notes: if <code>Arguments</code> is the empty list, the result
+%% Notes: if `Arguments' is the empty list, the result
%% will thus represent "<code>?<em>Name</em>()</code>", including a pair
-%% of matching parentheses.</p>
+%% of matching parentheses.
%%
-%% <p>The only syntactical limitation imposed by the preprocessor on the
+%% The only syntactical limitation imposed by the preprocessor on the
%% arguments to a macro application (viewed as sequences of tokens) is
%% that they must be balanced with respect to parentheses, brackets,
-%% <code>begin ... end</code>, <code>case ... end</code>, etc. The
-%% <code>text</code> node type can be used to represent arguments which
-%% are not regular Erlang constructs.</p>
+%% `begin ... end', `case ... end', etc. The
+%% `text' node type can be used to represent arguments which
+%% are not regular Erlang constructs.
%%
%% @see macro_name/1
%% @see macro_arguments/1
@@ -6272,9 +5776,7 @@ macro(Name, Arguments) ->
%% =====================================================================
-%% @spec macro_name(syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns the name subtree of a <code>macro</code> node.
+%% @doc Returns the name subtree of a `macro' node.
%%
%% @see macro/2
@@ -6285,14 +5787,12 @@ macro_name(Node) ->
%% =====================================================================
-%% @spec macro_arguments(Node::syntaxTree()) -> none | [syntaxTree()]
-%%
-%% @doc Returns the list of argument subtrees of a <code>macro</code>
-%% node, if any. If <code>Node</code> represents
-%% "<code>?<em>Name</em></code>", <code>none</code> is returned.
-%% Otherwise, if <code>Node</code> represents
+%% @doc Returns the list of argument subtrees of a `macro'
+%% node, if any. If `Node' represents
+%% "<code>?<em>Name</em></code>", `none' is returned.
+%% Otherwise, if `Node' represents
%% "<code>?<em>Name</em>(<em>A1</em>, ..., <em>An</em>)</code>",
-%% <code>[A1, ..., An]</code> is returned.
+%% `[A1, ..., An]' is returned.
%%
%% @see macro/2
@@ -6303,15 +5803,13 @@ macro_arguments(Node) ->
%% =====================================================================
-%% @spec abstract(Term::term()) -> syntaxTree()
-%%
%% @doc Returns the syntax tree corresponding to an Erlang term.
-%% <code>Term</code> must be a literal term, i.e., one that can be
+%% `Term' 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. The function recognises printable strings, in order to get a
%% compact and readable representation. Evaluation fails with reason
-%% <code>badarg</code> if <code>Term</code> is not a literal term.
+%% `badarg' if `Term' is not a literal term.
%%
%% @see concrete/1
%% @see is_literal/1
@@ -6361,19 +5859,17 @@ abstract_tail(H, T) ->
%% =====================================================================
-%% @spec concrete(Node::syntaxTree()) -> term()
-%%
%% @doc Returns the Erlang term represented by a syntax tree. Evaluation
-%% fails with reason <code>badarg</code> if <code>Node</code> does not
+%% fails with reason `badarg' if `Node' does not
%% represent a literal term.
%%
-%% <p>Note: Currently, the set of syntax trees which have a concrete
+%% Note: Currently, the set of syntax trees which have a concrete
%% representation is larger than the set of trees which can be built
-%% using the function <code>abstract/1</code>. An abstract character
-%% will be concretised as an integer, while <code>abstract/1</code> does
+%% using the function {@link abstract/1}. An abstract character
+%% will be concretised as an integer, while {@link abstract/1} does
%% not at present yield an abstract character for any input. (Use the
-%% <code>char/1</code> function to explicitly create an abstract
-%% character.)</p>
+%% {@link char/1} function to explicitly create an abstract
+%% character.)
%%
%% @see abstract/1
%% @see is_literal/1
@@ -6416,7 +5912,7 @@ concrete(Node) ->
{value, concrete(F), []}
end, [], true),
B;
- _ ->
+ _ ->
erlang:error({badarg, Node})
end.
@@ -6427,12 +5923,10 @@ concrete_list([]) ->
%% =====================================================================
-%% @spec is_literal(Node::syntaxTree()) -> 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.
+%% @doc Returns `true' if `Node' represents a
+%% literal term, otherwise `false'. This function returns
+%% `true' if and only if the value of
+%% `concrete(Node)' is defined.
%%
%% @see abstract/1
%% @see concrete/1
@@ -6463,21 +5957,19 @@ is_literal(T) ->
%% =====================================================================
-%% @spec revert(Tree::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Returns an <code>erl_parse</code>-compatible representation of a
-%% syntax tree, if possible. If <code>Tree</code> represents a
+%% @doc Returns an `erl_parse'-compatible representation of a
+%% syntax tree, if possible. If `Tree' represents a
%% well-formed Erlang program or expression, the conversion should work
-%% without problems. Typically, <code>is_tree/1</code> yields
-%% <code>true</code> if conversion failed (i.e., the result is still an
-%% abstract syntax tree), and <code>false</code> otherwise.
+%% without problems. Typically, {@link is_tree/1} yields
+%% `true' if conversion failed (i.e., the result is still an
+%% abstract syntax tree), and `false' otherwise.
%%
-%% <p>The <code>is_tree/1</code> test is not completely foolproof. For a
-%% few special node types (e.g. <code>arity_qualifier</code>), if such a
+%% The {@link is_tree/1} test is not completely foolproof. For a
+%% few special node types (e.g. `arity_qualifier'), if such a
%% node occurs in a context where it is not expected, it will be left
%% unchanged as a non-reverted subtree of the result. This can only
-%% happen if <code>Tree</code> does not actually represent legal Erlang
-%% code.</p>
+%% happen if `Tree' does not actually represent legal Erlang
+%% code.
%%
%% @see revert_forms/1
%% @see //stdlib/erl_parse
@@ -6487,9 +5979,13 @@ is_literal(T) ->
revert(Node) ->
case is_tree(Node) of
false ->
- %% Just remove any wrapper. `erl_parse' nodes never contain
- %% abstract syntax tree nodes as subtrees.
- unwrap(Node);
+ %% Just remove any wrapper and copy the position. `erl_parse'
+ %% nodes never contain abstract syntax tree nodes as subtrees.
+ case unwrap(Node) of
+ {error, Info} -> {error, setelement(1,Info,get_pos(Node))};
+ {warning, Info} -> {warning, setelement(1,Info,get_pos(Node))};
+ Node1 -> setelement(2,Node1,get_pos(Node))
+ end;
true ->
case is_leaf(Node) of
true ->
@@ -6609,16 +6105,12 @@ revert_root(Node) ->
%% =====================================================================
-%% @spec revert_forms(Forms) -> [erl_parse()]
-%%
-%% Forms = syntaxTree() | [syntaxTree()]
-%%
%% @doc Reverts a sequence of Erlang source code forms. The sequence can
-%% be given either as a <code>form_list</code> syntax tree (possibly
+%% be given either as a `form_list' syntax tree (possibly
%% nested), or as a list of "program form" syntax trees. If successful,
-%% the corresponding flat list of <code>erl_parse</code>-compatible
-%% syntax trees is returned (cf. <code>revert/1</code>). If some program
-%% form could not be reverted, <code>{error, Form}</code> is thrown.
+%% the corresponding flat list of `erl_parse'-compatible
+%% syntax trees is returned (see {@link revert/1}). If some program
+%% form could not be reverted, `{error, Form}' is thrown.
%% Standalone comments in the form sequence are discarded.
%%
%% @see revert/1
@@ -6627,10 +6119,10 @@ revert_root(Node) ->
-type forms() :: syntaxTree() | [syntaxTree()].
-%% -spec revert_forms(forms()) -> [erl_parse()].
+-spec revert_forms(forms()) -> [erl_parse()].
-revert_forms(L) when is_list(L) ->
- revert_forms(form_list(L));
+revert_forms(Forms) when is_list(Forms) ->
+ revert_forms(form_list(Forms));
revert_forms(T) ->
case type(T) of
form_list ->
@@ -6667,60 +6159,54 @@ revert_forms_1([]) ->
%% =====================================================================
-%% @spec subtrees(Node::syntaxTree()) -> [[syntaxTree()]]
-%%
%% @doc Returns the grouped list of all subtrees of a syntax tree. If
-%% <code>Node</code> is a leaf node (cf. <code>is_leaf/1</code>), this
+%% `Node' is a leaf node (see {@link is_leaf/1}), this
%% is the empty list, otherwise the result is always a nonempty list,
-%% containing the lists of subtrees of <code>Node</code>, in
+%% containing the lists of subtrees of `Node', 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
+%% Depending on the type of `Node', 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>
+%% without notice.
%%
-%% <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
+%% The function {@link subtrees/1} and the constructor functions
+%% {@link make_tree/2} and {@link update_tree/2} 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>
+%% can be left to a default case.
%%
-%% <p>For example:
-%% <pre>
-%% postorder(F, Tree) ->
+%% For example:
+%% ```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
+%% end).'''
+%% maps the function `F' on `Tree' and all its
%% subtrees, doing a post-order traversal of the syntax tree. (Note the
-%% use of <code>update_tree/2</code> to preserve node attributes.) For a
+%% use of {@link update_tree/2} to preserve node attributes.) For a
%% simple function like:
-%% <pre>
-%% f(Node) ->
+%% ```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
+%% end.'''
+%% the call `postorder(fun f/1, Tree)' will yield a new
+%% representation of `Tree' in which all atom names have been
%% extended with the prefix "a_", but nothing else (including comments,
-%% annotations and line numbers) has been changed.</p>
+%% annotations and line numbers) has been changed.
%%
%% @see make_tree/2
%% @see type/1
@@ -6890,12 +6376,9 @@ subtrees(T) ->
%% =====================================================================
-%% @spec update_tree(Node::syntaxTree(), Groups::[[syntaxTree()]]) ->
-%% syntaxTree()
-%%
%% @doc Creates a syntax tree with the same type and attributes as the
-%% given tree. This is equivalent to <code>copy_attrs(Node,
-%% make_tree(type(Node), Groups))</code>.
+%% given tree. This is equivalent to `copy_attrs(Node,
+%% make_tree(type(Node), Groups))'.
%%
%% @see make_tree/2
%% @see copy_attrs/2
@@ -6908,23 +6391,20 @@ update_tree(Node, Groups) ->
%% =====================================================================
-%% @spec make_tree(Type::atom(), Groups::[[syntaxTree()]]) ->
-%% syntaxTree()
-%%
%% @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
+%% `Type' must be a node type name (see {@link type/1})
+%% that does not denote a leaf node type (see {@link is_leaf/1}).
+%% `Groups' 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>.
+%% text, grouped by category as done by {@link subtrees/1}.
%%
-%% <p>The result of <code>copy_attrs(Node, make_tree(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
+%% The result of `copy_attrs(Node, make_tree(type(Node),
+%% subtrees(Node)))' (see {@link update_tree/2}) represents
+%% the same source code text as the original `Node', assuming
+%% that `subtrees(Node)' yields a nonempty list. However, it
%% does not necessarily have the same data representation as
-%% <code>Node</code>.</p>
+%% `Node'.
%%
%% @see update_tree/2
%% @see subtrees/1
@@ -6989,42 +6469,40 @@ make_tree(tuple, [E]) -> tuple(E).
%% =====================================================================
-%% @spec meta(Tree::syntaxTree()) -> syntaxTree()
-%%
%% @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
+%% same source code text as `Tree' (although the actual data
%% representation may be different). The expression represented by
-%% <code>MetaTree</code> is <em>implementation independent</em> with
+%% `MetaTree' is <em>implementation independent</em> with
%% regard to the data structures used by the abstract syntax tree
-%% implementation. Comments attached to nodes of <code>Tree</code> will
+%% implementation. Comments attached to nodes of `Tree' will
%% be preserved, but other attributes are lost.
%%
-%% <p>Any node in <code>Tree</code> whose node type is
-%% <code>variable</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>
+%% Any node in `Tree' whose node type is
+%% `variable' (see {@link type/1}), and whose list of
+%% annotations (see {@link get_ann/1}) contains the atom
+%% `meta_var', will remain unchanged in the resulting tree,
+%% except that exactly one occurrence of `meta_var' is
+%% removed from its annotation list.
%%
-%% <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
+%% The main use of the function `meta/1' is to transform a
+%% data structure `Tree', 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
+%% printed</em>. E.g., suppose `Tree' represents a variable
+%% named "V". Then (assuming a function `print/1' for
+%% printing syntax trees), evaluating `print(abstract(Tree))'
+%% - simply using {@link abstract/1} to map the actual data
%% structure onto a syntax tree representation - would output a string
-%% that might look something like "<code>{tree, variable, ..., "V",
-%% ...}</code>", which is obviously dependent on the implementation of
+%% that might look something like "`{tree, variable, ..., "V",
+%% ...}'", 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
+%% Using `print(meta(Tree))' instead would output a
%% <em>representation independent</em> syntax tree generating
%% expression; in the above case, something like
-%% "<code>erl_syntax:variable("V")</code>".</p>
+%% "`erl_syntax:variable("V")'".
%%
%% @see abstract/1
%% @see type/1
@@ -7155,60 +6633,56 @@ meta_call(F, As) ->
%% =====================================================================
-%% @spec tree(Type) -> syntaxTree()
%% @equiv tree(Type, [])
--spec tree(atom()) -> syntaxTree().
+-spec tree(atom()) -> #tree{}.
tree(Type) ->
tree(Type, []).
%% =====================================================================
-%% @spec tree(Type::atom(), Data::term()) -> syntaxTree()
-%%
%% @doc <em>For special purposes only</em>. Creates an abstract syntax
-%% tree node with type tag <code>Type</code> and associated data
-%% <code>Data</code>.
+%% tree node with type tag `Type' and associated data
+%% `Data'.
%%
-%% <p>This function and the related <code>is_tree/1</code> and
-%% <code>data/1</code> provide a uniform way to extend the set of
-%% <code>erl_parse</code> node types. The associated data is any term,
-%% whose format may depend on the type tag.</p>
+%% This function and the related {@link is_tree/1} and
+%% {@link data/1} provide a uniform way to extend the set of
+%% `erl_parse' node types. The associated data is any term,
+%% whose format may depend on the type tag.
%%
-%% <h4>Notes:</h4>
+%% === Notes: ===
%% <ul>
%% <li>Any nodes created outside of this module must have type tags
%% distinct from those currently defined by this module; see
-%% <code>type/1</code> for a complete list.</li>
+%% {@link type/1} for a complete list.</li>
%% <li>The type tag of a syntax tree node may also be used
-%% as a primary tag by the <code>erl_parse</code> representation;
+%% as a primary tag by the `erl_parse' representation;
%% in that case, the selector functions for that node type
%% <em>must</em> handle both the abstract syntax tree and the
-%% <code>erl_parse</code> form. The function <code>type(T)</code>
+%% `erl_parse' form. The function `type(T)'
%% should return the correct type tag regardless of the
-%% representation of <code>T</code>, so that the user sees no
-%% difference between <code>erl_syntax</code> and
-%% <code>erl_parse</code> nodes.</li>
+%% representation of `T', so that the user sees no
+%% difference between `erl_syntax' and
+%% `erl_parse' nodes.</li>
%% </ul>
+%%
%% @see is_tree/1
%% @see data/1
%% @see type/1
--spec tree(atom(), term()) -> syntaxTree().
+-spec tree(atom(), term()) -> #tree{}.
tree(Type, Data) ->
#tree{type = Type, data = Data}.
%% =====================================================================
-%% @spec is_tree(Tree::syntaxTree()) -> boolean()
-%%
-%% @doc <em>For special purposes only</em>. Returns <code>true</code> if
-%% <code>Tree</code> is an abstract syntax tree and <code>false</code>
+%% @doc <em>For special purposes only</em>. Returns `true' if
+%% `Tree' is an abstract syntax tree and `false'
%% otherwise.
%%
-%% <p><em>Note</em>: this function yields <code>false</code> for all
-%% "old-style" <code>erl_parse</code>-compatible "parse trees".</p>
+%% <em>Note</em>: this function yields `false' for all
+%% "old-style" `erl_parse'-compatible "parse trees".
%%
%% @see tree/2
@@ -7221,12 +6695,10 @@ is_tree(_) ->
%% =====================================================================
-%% @spec data(Tree::syntaxTree()) -> term()
-%%
%% @doc <em>For special purposes only</em>. Returns the associated data
%% of a syntax tree node. Evaluation fails with reason
-%% <code>badarg</code> if <code>is_tree(Node)</code> does not yield
-%% <code>true</code>.
+%% `badarg' if `is_tree(Node)' does not yield
+%% `true'.
%%
%% @see tree/2
@@ -7242,26 +6714,19 @@ data(T) -> erlang:error({badarg, T}).
%% =====================================================================
-%% @spec wrap(Node::erl_parse()) -> syntaxTree()
-%%
-%% @type erl_parse() = erl_parse:parse_tree(). The "parse tree"
-%% representation built by the Erlang standard library parser
-%% <code>erl_parse</code>. This is a subset of the
-%% <a href="#type-syntaxTree"><code>syntaxTree</code></a> type.
-%%
-%% @doc Creates a wrapper structure around an <code>erl_parse</code>
+%% @doc Creates a wrapper structure around an `erl_parse'
%% "parse tree".
%%
-%% <p>This function and the related <code>unwrap/1</code> and
-%% <code>is_wrapper/1</code> provide a uniform way to attach arbitrary
-%% information to an <code>erl_parse</code> tree. Some information about
+%% This function and the related {@link unwrap/1} and
+%% {@link is_wrapper/1} provide a uniform way to attach arbitrary
+%% information to an `erl_parse' tree. Some information about
%% the encapsuled tree may be cached in the wrapper, such as the node
%% type. All functions on syntax trees must behave so that the user sees
-%% no difference between wrapped and non-wrapped <code>erl_parse</code>
+%% no difference between wrapped and non-wrapped `erl_parse'
%% trees. <em>Attaching a wrapper onto another wrapper structure is an
-%% error</em>.</p>
+%% error</em>.
-%%-spec wrap(erl_parse:parse_tree()) -> syntaxTree().
+-spec wrap(erl_parse()) -> #wrapper{}.
wrap(Node) ->
%% We assume that Node is an old-school `erl_parse' tree.
@@ -7270,24 +6735,20 @@ wrap(Node) ->
%% =====================================================================
-%% @spec unwrap(Node::syntaxTree()) -> syntaxTree()
-%%
-%% @doc Removes any wrapper structure, if present. If <code>Node</code>
+%% @doc Removes any wrapper structure, if present. If `Node'
%% is a wrapper structure, this function returns the wrapped
-%% <code>erl_parse</code> tree; otherwise it returns <code>Node</code>
+%% `erl_parse' tree; otherwise it returns `Node'
%% itself.
--spec unwrap(syntaxTree()) -> syntaxTree().
+-spec unwrap(syntaxTree()) -> #tree{} | erl_parse().
unwrap(#wrapper{tree = Node}) -> Node;
unwrap(Node) -> Node. % This could also be a new-form node.
%% =====================================================================
-%% @spec is_wrapper(Term::term()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if the argument is a wrapper
-%% structure, otherwise <code>false</code>.
+%% @doc Returns `true' if the argument is a wrapper
+%% structure, otherwise `false'.
-ifndef(NO_UNUSED).
-spec is_wrapper(term()) -> boolean().
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 97dfbfd7cd..36cd35f15d 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 1997-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index 1cfdc7234a..59cf6c0a92 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 1999-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
@@ -103,7 +101,7 @@ dir(Dir) ->
%% <dt>{regexp, string()}</dt>
%%
%% <dd>The value denotes a regular expression (see module
-%% `regexp'). Tidying will only be applied to those
+%% `re'). Tidying will only be applied to those
%% regular files whose names match this pattern. The default
%% value is `".*\\.erl$"', which matches normal
%% Erlang source file names.</dd>
@@ -124,7 +122,7 @@ dir(Dir) ->
%%
%% See the function {@link file/2} for further options.
%%
-%% @see //stdlib/regexp
+%% @see //stdlib/re
%% @see file/2
-record(dir, {follow_links = false :: boolean(),
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index aa933eb54b..37e561cbbe 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 1998-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/src/prettypr.erl b/lib/syntax_tools/src/prettypr.erl
index c13fa30998..1b5ba6b05a 100644
--- a/lib/syntax_tools/src/prettypr.erl
+++ b/lib/syntax_tools/src/prettypr.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2000-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @end
%% =====================================================================
diff --git a/lib/syntax_tools/test/Makefile b/lib/syntax_tools/test/Makefile
index 3e31bdbd50..d4733b9a42 100644
--- a/lib/syntax_tools/test/Makefile
+++ b/lib/syntax_tools/test/Makefile
@@ -57,9 +57,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) syntax_tools.spec syntax_tools.cover $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) syntax_tools.spec syntax_tools.cover "$(RELSYSDIR)"
+ chmod -R u+w "$(RELSYSDIR)"
release_docs_spec:
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index cc7ea944f9..8f774c5d75 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 1.6.7.1
+SYNTAX_TOOLS_VSN = 1.6.9
diff --git a/lib/test_server/doc/src/Makefile b/lib/test_server/doc/src/Makefile
index c7ba415e5b..3ce549f0e1 100644
--- a/lib/test_server/doc/src/Makefile
+++ b/lib/test_server/doc/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
@@ -119,23 +119,17 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
- $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(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"
release_spec:
release_tests_spec:
-
-# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-include make.dep
diff --git a/lib/test_server/doc/src/make.dep b/lib/test_server/doc/src/make.dep
deleted file mode 100644
index ee9100bd08..0000000000
--- a/lib/test_server/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: basics_chapter.tex book.tex example_chapter.tex \
- part.tex ref_man.tex run_test_chapter.tex \
- test_server_app.tex test_server_ctrl.tex \
- test_server.tex test_spec_chapter.tex \
- write_framework_chapter.tex \
- write_test_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml
index beeff55ffe..3701066e56 100644
--- a/lib/test_server/doc/src/notes.xml
+++ b/lib/test_server/doc/src/notes.xml
@@ -32,6 +32,198 @@
<file>notes.xml</file>
</header>
+<section><title>Test_Server 3.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ After a test case timeout or abortion, the
+ end_per_testcase function executes on a new dedicated
+ process. The group leader for this process should be set
+ to the IO server for the test case, which was not done
+ properly. The result of this error was that no warnings
+ about end_per_testcase failing or timing out were ever
+ printed in the test case log. Also, help functions such
+ as e.g. test_server:stop_node/1, attempting to
+ synchronize with the IO server, would hang. The fault has
+ been corrected.</p>
+ <p>
+ Own Id: OTP-9666</p>
+ </item>
+ <item>
+ <p>
+ A deadlock situation could occur if Common Test is
+ forwarding error_handler printouts to Test Server at the
+ same time a new test case is starting. This error has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9894</p>
+ </item>
+ <item>
+ <p>
+ When a test case was killed because of a timetrap
+ timeout, the current location (suite, case and line) was
+ not printed correctly in the log files. This has been
+ corrected.</p>
+ <p>
+ Own Id: OTP-9930 Aux Id: seq12002 </p>
+ </item>
+ <item>
+ <p>
+ Test Server and Common Test would add new error handlers
+ with each test run and fail to remove previously added
+ ones. In the case of Test Server, this would only happen
+ if SASL was not running on the test node. This has been
+ fixed.</p>
+ <p>
+ Own Id: OTP-9941 Aux Id: seq12009 </p>
+ </item>
+ <item>
+ <p>
+ If a test case process was terminated due to an exit
+ signal from a linked process, Test Server failed to
+ report the correct name of the suite and case to the
+ framework. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9958 Aux Id: OTP-9855 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new optional feature has been introduced that enables
+ Common Test to generate priv_dir directory names that are
+ unique for each test case or config function. The name of
+ the option/flag is 'create_priv_dir' and it can be set to
+ value 'auto_per_run' (which is the default, existing,
+ behaviour), or 'auto_per_tc' or 'manual_per_tc'. If
+ 'auto_per_tc' is used, Test Server creates a dedicated
+ priv_dir automatically for each test case (which can be
+ very expensive in case of many and/or repeated cases). If
+ 'manual_per_tc' is used, the user needs to create the
+ priv_dir explicitly by calling the new function
+ ct:make_priv_dir/0.</p>
+ <p>
+ Own Id: OTP-9659 Aux Id: seq11930 </p>
+ </item>
+ <item>
+ <p>
+ A column for test case group name has been added to the
+ suite overview HTML log file.</p>
+ <p>
+ Own Id: OTP-9730 Aux Id: seq11952 </p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use the post_end_per_testcase CT
+ hook function to print a comment for a test case in the
+ overview log file, even if the test case gets killed by a
+ timetrap or unknown exit signal, or if the
+ end_per_testcase function times out.</p>
+ <p>
+ Own Id: OTP-9855 Aux Id: seq11979 </p>
+ </item>
+ <item>
+ <p>
+ Common Test will now print error information (with a time
+ stamp) in the test case log file immediately when a test
+ case fails. This makes it easier to see when, in time,
+ the fault actually occured, and aid the job of locating
+ relevant trace and debug printouts in the log.</p>
+ <p>
+ Own Id: OTP-9904 Aux Id: seq11985, OTP-9900 </p>
+ </item>
+ <item>
+ <p>
+ Test Server has been modified to check the SASL
+ errlog_type parameter when receiving an error logger
+ event, so that it doesn't print reports of type that the
+ user has disabled.</p>
+ <p>
+ Own Id: OTP-9955 Aux Id: seq12013 </p>
+ </item>
+ <item>
+ <p>
+ If an application cannot be found by ts it is
+ automatically skipped when testing.</p>
+ <p>
+ Own Id: OTP-9971</p>
+ </item>
+ <item>
+ <p>
+ By specifying a user defined function ({M,F,A} or fun) as
+ timetrap value, either by means of an info function or by
+ calling ct:timetrap/1, it is now possible to set a
+ timetrap that will be triggered when the user function
+ returns.</p>
+ <p>
+ Own Id: OTP-9988 Aux Id: OTP-9501, seq11894 </p>
+ </item>
+ <item>
+ <p>
+ If the optional configuration functions init_per_suite/1
+ and end_per_suite/1 are not implemented in the test
+ suite, local Common Test versions of these functions are
+ called instead, and will be displayed in the overview log
+ file. Any printouts made by the pre- or
+ post_init_per_suite and pre- or post_end_per_suite hook
+ functions are saved in the log files for these functions.</p>
+ <p>
+ Own Id: OTP-9992</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Test_Server 3.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The test case group info function has been implemented in
+ Common Test. Before execution of a test case group, a
+ call is now made to <c>TestSuite:group(GroupName)</c>.
+ The function returns a list of test properties, e.g. to
+ specify timetrap values, require configuration data, etc
+ (analogue to the test suite- and test case info
+ function). The scope of the properties set by
+ <c>group(GroupName)</c> is all test cases and sub-groups
+ of group <c>GroupName</c>.</p>
+ <p>
+ Own Id: OTP-9235</p>
+ </item>
+ <item>
+ <p>
+ The look of the HTML log files generated by Common Test
+ and Test Server has been improved (and made easier to
+ customize) by means of a CSS file.</p>
+ <p>
+ Own Id: OTP-9706</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ Fix problems in CT/TS due to line numbers in exceptions.</p>
+ <p>
+ Own Id: OTP-9203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Test_Server 3.4.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/test_server/doc/src/test_server.xml b/lib/test_server/doc/src/test_server.xml
index 78bb922cc5..5bfa42c36f 100644
--- a/lib/test_server/doc/src/test_server.xml
+++ b/lib/test_server/doc/src/test_server.xml
@@ -203,7 +203,7 @@
<func>
<name>format(Format) -> ok</name>
<name>format(Format, Args)</name>
- <name>format(Pri,Format)</name>
+ <name>format(Pri, Format)</name>
<name>format(Pri, Format, Args)</name>
<fsummary></fsummary>
<type>
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index 4bc51873c2..a75855eaab 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -124,22 +124,22 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_tests_spec: opt
- $(INSTALL_DIR) $(RELEASE_PATH)/test_server
+ $(INSTALL_DIR) "$(RELEASE_PATH)/test_server"
$(INSTALL_DATA) $(ERL_FILES) $(TS_ERL_FILES) \
$(HRL_FILES) $(INTERNAL_HRL_FILES) $(TS_HRL_FILES) \
$(TS_TARGET_FILES) \
$(AUTOCONF_FILES) $(C_FILES) $(COVER_FILES) $(CONFIG) \
- $(RELEASE_PATH)/test_server
- $(INSTALL_SCRIPT) $(PROGRAMS) $(RELEASE_PATH)/test_server
+ "$(RELEASE_PATH)/test_server"
+ $(INSTALL_SCRIPT) $(PROGRAMS) "$(RELEASE_PATH)/test_server"
release_docs_spec:
diff --git a/lib/test_server/src/config.guess b/lib/test_server/src/config.guess
index 6f1eeddfcc..38a833903b 120000..100755
--- a/lib/test_server/src/config.guess
+++ b/lib/test_server/src/config.guess
@@ -1 +1,1519 @@
-../../../erts/autoconf/config.guess \ No newline at end of file
+#! /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/test_server/src/config.sub b/lib/test_server/src/config.sub
index 47a0f10138..f43233b104 120000..100755
--- a/lib/test_server/src/config.sub
+++ b/lib/test_server/src/config.sub
@@ -1 +1,1630 @@
-../../../erts/autoconf/config.sub \ No newline at end of file
+#! /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/test_server/src/configure.in b/lib/test_server/src/configure.in
index 097853bcfc..77bc993ccd 100644
--- a/lib/test_server/src/configure.in
+++ b/lib/test_server/src/configure.in
@@ -108,7 +108,7 @@ AC_CHECK_HEADER(poll.h, AC_DEFINE(HAVE_POLL_H))
# for the system.
AC_MSG_CHECKING([system version (for dynamic loading)])
-system=`uname -s`-`uname -r`
+system=`./config.sub $host`
AC_MSG_RESULT($system)
# Step 2: check for existence of -ldl library. This is needed because
@@ -119,10 +119,9 @@ AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
# Step 3: set configuration options based on system name and version.
SHLIB_LDLIBS=
-
fullSrcDir=`cd $srcdir; pwd`
case $system in
- Linux*)
+ *-linux-*)
SHLIB_CFLAGS="-fPIC"
SHLIB_SUFFIX=".so"
if test "$have_dl" = yes; then
@@ -136,7 +135,7 @@ case $system in
fi
SHLIB_EXTRACT_ALL=""
;;
- NetBSD-*|FreeBSD-*|OpenBSD-*|DragonFly*)
+ *-netbsd*|*-freebsd*|*-openbsd*|*-dragonfly*)
# Not available on all versions: check for include file.
AC_CHECK_HEADER(dlfcn.h, [
SHLIB_CFLAGS="-fpic"
@@ -153,28 +152,21 @@ case $system in
])
SHLIB_EXTRACT_ALL=""
;;
- SunOS-4*)
- SHLIB_CFLAGS="-PIC"
- SHLIB_LD="ld"
- SHLIB_LDFLAGS="$LDFLAGS"
- SHLIB_SUFFIX=".so"
- SHLIB_EXTRACT_ALL=""
- ;;
- SunOS-5*|UNIX_SV-4.2*)
+ *-solaris2*|*-sysv4*)
SHLIB_CFLAGS="-KPIC"
SHLIB_LD="/usr/ccs/bin/ld"
SHLIB_LDFLAGS="$LDFLAGS -G -z text"
SHLIB_SUFFIX=".so"
SHLIB_EXTRACT_ALL="-z allextract"
;;
- Darwin*)
+ *darwin*)
SHLIB_CFLAGS="-fno-common"
SHLIB_LD="cc"
SHLIB_LDFLAGS="$LDFLAGS -bundle -flat_namespace -undefined suppress"
SHLIB_SUFFIX=".so"
SHLIB_EXTRACT_ALL=""
;;
- OSF1*)
+ *osf1*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld"
SHLIB_LDFLAGS="$LDFLAGS -shared"
@@ -206,19 +198,19 @@ esac
if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then
case $system in
- AIX-*)
+ *-aix)
;;
- BSD/OS*)
+ *-bsd*)
;;
- IRIX*)
+ *-irix)
;;
- NetBSD-*|FreeBSD-*|OpenBSD-*)
+ *-netbsd|*-freebsd|*-openbsd)
;;
- RISCos-*)
+ *-riscos)
;;
- ULTRIX-4.*)
+ *ultrix4.*)
;;
- Darwin*)
+ *darwin*)
;;
*)
SHLIB_CFLAGS="-fPIC"
diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl
index c94d4627f9..6891e87e48 100644
--- a/lib/test_server/src/erl2html2.erl
+++ b/lib/test_server/src/erl2html2.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
@@ -32,32 +32,34 @@
%--------------------------------------------------------------------
-module(erl2html2).
--export([convert/2]).
+-export([convert/2, convert/3]).
convert([], _Dest) -> % Fake clause.
ok;
convert(File, Dest) ->
+ %% The generated code uses the BGCOLOR attribute in the
+ %% BODY tag, which wasn't valid until HTML 3.2. Also,
+ %% good HTML should either override all colour attributes
+ %% or none of them -- *never* just a few.
+ %%
+ %% FIXME: The colours should *really* be set with
+ %% stylesheets...
+ Header = ["<!DOCTYPE HTML PUBLIC "
+ "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
+ "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
+ "<html>\n"
+ "<head><title>", File, "</title></head>\n\n"
+ "<body bgcolor=\"white\" text=\"black\""
+ " link=\"blue\" vlink=\"purple\" alink=\"red\">\n"],
+ convert(File, Dest, Header).
+
+convert(File, Dest, Header) ->
case file:read_file(File) of
{ok, Bin} ->
Code=binary_to_list(Bin),
statistics(runtime),
- %% The generated code uses the BGCOLOR attribute in the
- %% BODY tag, which wasn't valid until HTML 3.2. Also,
- %% good HTML should either override all colour attributes
- %% or none of them -- *never* just a few.
- %%
- %% FIXME: The colours should *really* be set with
- %% stylesheets...
- Html0
- = ["<!DOCTYPE HTML PUBLIC "
- "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
- "<html>\n"
- "<head><title>", File, "</title></head>\n\n"
- "<body bgcolor=\"white\" text=\"black\""
- " link=\"blue\" vlink=\"purple\" alink=\"red\">\n"],
{Html1, Lines} = root(Code, [], 1),
- Html = [Html0,
+ Html = [Header,
"<pre>\n", Html1, "</pre>\n",
footer(Lines),"</body>\n</html>\n"],
file:write_file(Dest, Html);
@@ -173,10 +175,11 @@ linenum(Line) ->
end,
[A,Pred,integer_to_list(Line),":"].
-footer(Lines) ->
- {_, Time} = statistics(runtime),
-% io:format("Converted ~p lines in ~.2f Seconds.~n",
-% [Lines, Time/1000]),
- S = "<i>The transformation of this file (~p lines) took ~.2f seconds</i>",
- F = lists:flatten(io_lib:format(S, [Lines, Time/1000])),
- ["<hr size=1>",F,"<br>\n"].
+footer(_Lines) ->
+ "".
+%% {_, Time} = statistics(runtime),
+%% io:format("Converted ~p lines in ~.2f Seconds.~n",
+%% [Lines, Time/1000]),
+%% S = "<i>The transformation of this file (~p lines) took ~.2f seconds</i>",
+%% F = lists:flatten(io_lib:format(S, [Lines, Time/1000])),
+%% ["<hr size=1>",F,"<br>\n"].
diff --git a/lib/test_server/src/install-sh b/lib/test_server/src/install-sh
index a859cade7f..a5897de6ea 120000..100755
--- a/lib/test_server/src/install-sh
+++ b/lib/test_server/src/install-sh
@@ -1 +1,519 @@
-../../../erts/autoconf/install-sh \ No newline at end of file
+#!/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/test_server/src/test_server.app.src b/lib/test_server/src/test_server.app.src
index 7e87583a7b..faf7db835e 100644
--- a/lib/test_server/src/test_server.app.src
+++ b/lib/test_server/src/test_server.app.src
@@ -1,7 +1,7 @@
% This is an -*- erlang -*- file.
%% %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
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 49f97686a0..17c5f5b253 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,20 +35,22 @@
-export([fail/0,fail/1,format/1,format/2,format/3]).
-export([capture_start/0,capture_stop/0,capture_get/0]).
-export([messages_get/0]).
+-export([permit_io/2]).
-export([hours/1,minutes/1,seconds/1,sleep/1,adjusted_sleep/1,timecall/3]).
--export([timetrap_scale_factor/0,timetrap/1,timetrap_cancel/1,timetrap_cancel/0]).
+-export([timetrap_scale_factor/0,timetrap/1,get_timetrap_info/0,
+ 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]).
-export([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1]).
-export([app_test/1, app_test/2]).
-export([is_native/1]).
--export([comment/1]).
+-export([comment/1, make_priv_dir/0]).
-export([os_type/0]).
-export([run_on_shielded_node/2]).
-export([is_cover/0,is_debug/0,is_commercial/0]).
--export([break/1,continue/0]).
+-export([break/1,break/2,break/3,continue/0,continue/1]).
%%% DEBUGGER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([purify_new_leaks/0, purify_format/2, purify_new_fds_inuse/0,
@@ -522,7 +524,7 @@ stick_all_sticky(Node,Sticky) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% run_test_case_apply(Mod,Func,Args,Name,RunInit,TimetrapData) ->
+%% run_test_case_apply(Mod,Func,Args,Name,RunInit,TimetrapData,RejectIoReqs) ->
%% {Time,Value,Loc,Opts,Comment} | {died,Reason,unknown,Comment}
%%
%% Time = float() (seconds)
@@ -557,8 +559,12 @@ stick_all_sticky(Node,Sticky) ->
%% ScaleTimetrap indicates if test_server should attemp to automatically
%% compensate timetraps for runtime delays introduced by e.g. tools like
%% cover.
+%%
+%% RejectIoReqs (bool) is information about whether printouts to stdout
+%% should be visible in the minor log file or not.
-run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) ->
+run_test_case_apply({CaseNum,Mod,Func,Args,Name,
+ RunInit,TimetrapData,RejectIoReqs}) ->
purify_format("Test case #~w ~w:~w/1", [CaseNum, Mod, Func]),
case os:getenv("TS_RUN_VALGRIND") of
false ->
@@ -569,17 +575,19 @@ run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) ->
end,
test_server_h:testcase({Mod,Func,1}),
ProcBef = erlang:system_info(process_count),
- Result = run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData),
+ Result = run_test_case_apply(Mod, Func, Args, Name, RunInit,
+ TimetrapData, RejectIoReqs),
ProcAft = erlang:system_info(process_count),
purify_new_leaks(),
DetFail = get(test_server_detected_fail),
{Result,DetFail,ProcBef,ProcAft}.
-run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
+run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData, RejectIoReqs) ->
case get(test_server_job_dir) of
undefined ->
%% i'm a local target
- do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData);
+ do_run_test_case_apply(Mod, Func, Args, Name, RunInit,
+ TimetrapData, RejectIoReqs);
JobDir ->
%% i'm a remote target
case Args of
@@ -594,13 +602,14 @@ run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
Config2 = lists:keyreplace(priv_dir, 1, Config1,
{priv_dir,TargetPrivDir}),
do_run_test_case_apply(Mod, Func, [Config2], Name, RunInit,
- TimetrapData);
+ TimetrapData, RejectIoReqs);
_other ->
do_run_test_case_apply(Mod, Func, Args, Name, RunInit,
- TimetrapData)
+ TimetrapData, RejectIoReqs)
end
end.
-do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
+do_run_test_case_apply(Mod, Func, Args, Name, RunInit,
+ TimetrapData, RejectIoReqs) ->
{ok,Cwd} = file:get_cwd(),
Args2Print = case Args of
[Args1] when is_list(Args1) ->
@@ -611,6 +620,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
print(minor, "Test case started with:\n~s:~s(~p)\n", [Mod,Func,Args2Print]),
print(minor, "Current directory is ~p\n", [Cwd]),
print_timestamp(minor,"Started at "),
+ print(minor, "", [], internal_raw),
TCCallback = get(test_server_testcase_callback),
LogOpts = get(test_server_logopts),
Ref = make_ref(),
@@ -626,7 +636,8 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
end),
group_leader(OldGLeader, self()),
put(test_server_detected_fail, []),
- run_test_case_msgloop(Ref, Pid, false, false, "", undefined).
+ run_test_case_msgloop(Ref, Pid, false, RejectIoReqs, false, "",
+ undefined, starting).
%% Ugly bug (pre R5A):
%% If this process (group leader of the test case) terminates before
@@ -637,19 +648,37 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
%% A test case is known to have failed if it returns {'EXIT', _} tuple,
%% or sends a message {failed, File, Line} to it's group_leader
%%
-run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
+run_test_case_msgloop(Ref, Pid, CaptureStdout, RejectIoReqs, Terminate,
+ Comment, CurrConf, Status) ->
%% NOTE: Keep job_proxy_msgloop/0 up to date when changes
%% are made in this function!
{Timeout,ReturnValue} =
case Terminate of
{true, ReturnVal} ->
+ %% stop any timetrap timers for the test case
+ %% that have been started by this process
+ timetrap_cancel_all(Pid, false),
{20, ReturnVal};
false ->
{infinity, should_never_appear}
end,
receive
+ {test_case_initialized,Pid} ->
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,running);
+ Abort = {abort_current_testcase,_,_} when Status == starting ->
+ %% we're in init phase, must must postpone this operation
+ %% until test case execution is in progress (or FW:init_tc
+ %% gets killed)
+ self() ! Abort,
+ erlang:yield(),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{abort_current_testcase,Reason,From} ->
- Line = get_loc(Pid),
+ Line = case is_process_alive(Pid) of
+ true -> get_loc(Pid);
+ false -> unknown
+ end,
Mon = erlang:monitor(process, Pid),
exit(Pid,{testcase_aborted,Reason,Line}),
erlang:yield(),
@@ -663,76 +692,104 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
exit(Pid, kill),
%% here's the only place we know Reason, so we save
%% it as a comment, potentially replacing user data
- Error = lists:flatten(io_lib:format("Aborted: ~p",[Reason])),
+ Error = lists:flatten(io_lib:format("Aborted: ~p",
+ [Reason])),
Error1 = lists:flatten([string:strip(S,left) ||
- S <- string:tokens(Error,[$\n])]),
+ S <- string:tokens(Error,
+ [$\n])]),
if length(Error1) > 63 ->
string:substr(Error1,1,60) ++ "...";
true ->
Error1
end
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,NewComment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ NewComment,CurrConf,Status);
+ {permit_io,FromPid} ->
+ put({permit_io,FromPid},true),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,io_lib,Func,[Format,Args]}}
when is_list(Format) ->
Msg = (catch io_lib:Func(Format,Args)),
- run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,io_lib,Func,[Format,Args]}}
when is_atom(Format) ->
Msg = (catch io_lib:Func(Format,Args)),
- run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,Bytes}} ->
- run_test_case_msgloop_io(
- ReplyAs,CaptureStdout,Bytes,From,put_chars),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Bytes,From,put_chars),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,unicode,io_lib,Func,[Format,Args]}}
when is_list(Format) ->
Msg = unicode_to_latin1(catch io_lib:Func(Format,Args)),
- run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,latin1,io_lib,Func,[Format,Args]}}
when is_list(Format) ->
Msg = (catch io_lib:Func(Format,Args)),
- run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,unicode,io_lib,Func,[Format,Args]}}
when is_atom(Format) ->
Msg = unicode_to_latin1(catch io_lib:Func(Format,Args)),
- run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,latin1,io_lib,Func,[Format,Args]}}
when is_atom(Format) ->
Msg = (catch io_lib:Func(Format,Args)),
- run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,unicode,Bytes}} ->
- run_test_case_msgloop_io(
- ReplyAs,CaptureStdout,unicode_to_latin1(Bytes),From,put_chars),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ unicode_to_latin1(Bytes),From,put_chars),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{io_request,From,ReplyAs,{put_chars,latin1,Bytes}} ->
- run_test_case_msgloop_io(
- ReplyAs,CaptureStdout,Bytes,From,put_chars),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Bytes,From,put_chars),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
IoReq when element(1, IoReq) == io_request ->
%% something else, just pass it on
group_leader() ! IoReq,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{structured_io,ClientPid,Msg} ->
output(Msg, ClientPid),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{capture,NewCapture} ->
- run_test_case_msgloop(Ref,Pid,NewCapture,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,NewCapture,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{sync_apply,From,MFA} ->
sync_local_or_remote_apply(false,From,MFA),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{sync_apply_proxy,Proxy,From,MFA} ->
sync_local_or_remote_apply(Proxy,From,MFA),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{printout,Detail,Format,Args} ->
print(Detail,Format,Args),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{comment,NewComment} ->
NewComment1 = test_server_ctrl:to_string(NewComment),
NewComment2 = test_server_sup:framework_call(format_comment,
@@ -745,16 +802,42 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
Other ->
Other
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment2,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate1,
+ NewComment2,CurrConf,Status);
{read_comment,From} ->
From ! {self(),read_comment,Comment},
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{set_curr_conf,From,NewCurrConf} ->
From ! {self(),set_curr_conf,ok},
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,NewCurrConf,Status);
+ {make_priv_dir,From} when CurrConf == undefined ->
+ From ! {self(),make_priv_dir,{error,no_priv_dir_in_config}},
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
+ {make_priv_dir,From} ->
+ Result =
+ case proplists:get_value(priv_dir, element(2, CurrConf)) of
+ undefined ->
+ {error,no_priv_dir_in_config};
+ PrivDir ->
+ case file:make_dir(PrivDir) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ MkDirError ->
+ {error,{MkDirError,PrivDir}}
+ end
+ end,
+ From ! {self(),make_priv_dir,Result},
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,Terminate,
+ Comment,CurrConf,Status);
{'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} ->
RetVal = {Time/1000000,Value,mod_loc(Loc),Opts,Comment},
- run_test_case_msgloop(Ref,Pid,CaptureStdout,{true,RetVal},Comment,undefined);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ {true,RetVal},Comment,undefined,Status);
{'EXIT',Pid,Reason} ->
case Reason of
{timetrap_timeout,TVal,Loc} ->
@@ -764,37 +847,45 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
%% timout during framework call
spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,{timetrap,TVal}},
- unknown,self(),Comment),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
- Comment,undefined);
+ unknown,self()),
+ run_test_case_msgloop(Ref,Pid,
+ CaptureStdout,RejectIoReqs,
+ Terminate,Comment,
+ undefined,Status);
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
+ %% only so that the user has a chance to
+ %% clean up after init_per_testcase, even after
+ %% a timetrap timeout
NewCurrConf =
case CurrConf of
{{Mod,Func},Conf} ->
EndConfPid =
- call_end_conf(Mod,Func,Pid,
- {timetrap_timeout,TVal},
- Loc1,[{tc_status,
- {failed,
- timetrap_timeout}}|Conf],
- TVal),
+ call_end_conf(
+ Mod,Func,Pid,
+ {timetrap_timeout,TVal},
+ Loc1,[{tc_status,
+ {failed,
+ timetrap_timeout}}|Conf],
+ 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.
+ %% 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,CurrConf,Pid,
{timetrap_timeout,TVal},
- Loc1,self(),Comment),
+ Loc1,self()),
undefined
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
- Comment,NewCurrConf)
+ run_test_case_msgloop(Ref,Pid,
+ CaptureStdout,RejectIoReqs,
+ Terminate,Comment,
+ NewCurrConf,Status)
end;
{timetrap_timeout,TVal,Loc,InitOrEnd} ->
case mod_loc(Loc) of
@@ -802,14 +893,25 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
%% timout during framework call
spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,{timetrap,TVal}},
- unknown,self(),Comment);
+ unknown,self());
Loc1 ->
{Mod,_Func} = get_mf(Loc1),
spawn_fw_call(Mod,InitOrEnd,CurrConf,Pid,
{timetrap_timeout,TVal},
- Loc1,self(),Comment)
+ Loc1,self())
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
+ {testcase_aborted,ErrorMsg={user_timetrap_error,_},AbortLoc} ->
+ %% user timetrap function caused exit
+ %% during start of test case
+ {Mod,Func} = get_mf(mod_loc(AbortLoc)),
+ spawn_fw_call(Mod,Func,CurrConf,Pid,
+ ErrorMsg,unknown,self()),
+ run_test_case_msgloop(Ref,Pid,
+ CaptureStdout,RejectIoReqs,
+ Terminate,Comment,
+ undefined,Status);
{testcase_aborted,AbortReason,AbortLoc} ->
ErrorMsg = {testcase_aborted,AbortReason},
case mod_loc(AbortLoc) of
@@ -817,66 +919,108 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
%% abort during framework call
spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,ErrorMsg},
- unknown,self(),Comment),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
- Comment,undefined);
+ unknown,self()),
+ run_test_case_msgloop(Ref,Pid,
+ CaptureStdout,RejectIoReqs,
+ Terminate,Comment,
+ undefined,Status);
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
+ %% 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
NewCurrConf =
case CurrConf of
{{Mod,Func},Conf} ->
- TVal = case lists:keysearch(default_timeout,1,Conf) of
- {value,{default_timeout,Tmo}} -> Tmo;
- _ -> ?DEFAULT_TIMETRAP_SECS*1000
- end,
+ TVal =
+ case lists:keysearch(default_timeout,
+ 1,
+ Conf) of
+ {value,{default_timeout,Tmo}} ->
+ Tmo;
+ _ ->
+ ?DEFAULT_TIMETRAP_SECS*1000
+ end,
EndConfPid =
- call_end_conf(Mod,Func,Pid,ErrorMsg,
- Loc1,
- [{tc_status,{failed,ErrorMsg}}|Conf],
- TVal),
+ call_end_conf(
+ Mod,Func,Pid,
+ ErrorMsg,Loc1,
+ [{tc_status,
+ {failed,ErrorMsg}}|Conf],TVal),
{EndConfPid,{Mod,Func},Conf};
_ ->
{Mod,Func} = get_mf(Loc1),
- spawn_fw_call(Mod,Func,CurrConf,Pid,ErrorMsg,
- Loc1,self(),Comment),
+ spawn_fw_call(Mod,Func,CurrConf,Pid,
+ ErrorMsg,Loc1,self()),
undefined
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
- Comment,NewCurrConf)
+ run_test_case_msgloop(Ref,Pid,
+ CaptureStdout,RejectIoReqs,
+ Terminate,Comment,
+ NewCurrConf,Status)
end;
killed ->
%% 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,CurrConf,Pid,
+ {Mod,Func} = case CurrConf of
+ {MF,_} -> MF;
+ _ -> {undefined,undefined}
+ end,
+ spawn_fw_call(Mod,Func,CurrConf,Pid,
testcase_aborted_or_killed,
- unknown,self(),Comment),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ unknown,self()),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
{fw_error,{FwMod,FwFunc,FwError}} ->
- spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,{framework_error,FwError},
- unknown,self(),Comment),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
+ {framework_error,FwError},
+ unknown,self()),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
_Other ->
%% the testcase has terminated because of Reason (e.g. an exit
%% because a linked process failed)
- spawn_fw_call(undefined,undefined,CurrConf,Pid,Reason,
- unknown,self(),Comment),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
+ {Mod,Func} = case CurrConf of
+ {MF,_} -> MF;
+ _ -> {undefined,undefined}
+ end,
+ spawn_fw_call(Mod,Func,CurrConf,Pid,
+ Reason,unknown,self()),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status)
end;
{EndConfPid,{call_end_conf,Data,_Result}} ->
case CurrConf of
{EndConfPid,{Mod,Func},_Conf} ->
{_Mod,_Func,TCPid,TCExitReason,Loc} = Data,
- spawn_fw_call(Mod,Func,CurrConf,TCPid,TCExitReason,Loc,self(),Comment),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,undefined);
+ spawn_fw_call(Mod,Func,CurrConf,TCPid,
+ TCExitReason,Loc,self()),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,undefined,Status);
_ ->
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status)
end;
- {_FwCallPid,fw_notify_done,RetVal} ->
+ {_FwCallPid,fw_notify_done,{T,Value,Loc,Opts,AddToComment}} ->
%% the framework has been notified, we're finished
- run_test_case_msgloop(Ref,Pid,CaptureStdout,{true,RetVal},Comment,undefined);
+ RetVal =
+ case AddToComment of
+ undefined ->
+ {T,Value,Loc,Opts,Comment};
+ _ ->
+ Comment1 =
+ if Comment == "" ->
+ AddToComment;
+ true ->
+ Comment ++
+ test_server_ctrl:xhtml("<br>",
+ "<br />") ++
+ AddToComment
+ end,
+ {T,Value,Loc,Opts,Comment1}
+ end,
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ {true,RetVal},Comment,undefined,Status);
{'EXIT',_FwCallPid,{fw_notify_done,Func,Error}} ->
%% a framework function failed
CB = os:getenv("TEST_SERVER_FRAMEWORK"),
@@ -887,53 +1031,108 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
{list_to_atom(CB),Func}
end,
RetVal = {died,{framework_error,Loc,Error},Loc,"Framework error"},
- run_test_case_msgloop(Ref,Pid,CaptureStdout,{true,RetVal},Comment,undefined);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ {true,RetVal},Comment,undefined,Status);
{failed,File,Line} ->
put(test_server_detected_fail,
[{File, Line}| get(test_server_detected_fail)]),
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
+
+ {user_timetrap,Pid,_TrapTime,StartTime,E={user_timetrap_error,_},_} ->
+ case update_user_timetraps(Pid, StartTime) of
+ proceed ->
+ self() ! {abort_current_testcase,E,Pid};
+ ignore ->
+ ok
+ end,
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
+ {user_timetrap,Pid,TrapTime,StartTime,ElapsedTime,Scale} ->
+ %% a user timetrap is triggered, ignore it if new
+ %% timetrap has been started since
+ case update_user_timetraps(Pid, StartTime) of
+ proceed ->
+ TotalTime = if is_integer(TrapTime) ->
+ TrapTime + ElapsedTime;
+ true ->
+ TrapTime
+ end,
+ timetrap(TrapTime, TotalTime, Pid, Scale);
+ ignore ->
+ ok
+ end,
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
+ {timetrap_cancel_one,Handle,_From} ->
+ timetrap_cancel_one(Handle, false),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
+ {timetrap_cancel_all,TCPid,_From} ->
+ timetrap_cancel_all(TCPid, false),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
+ {get_timetrap_info,TCPid,From} ->
+ Info = get_timetrap_info(TCPid, false),
+ From ! {self(),get_timetrap_info,Info},
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
_Other when not is_tuple(_Other) ->
%% ignore anything not generated by test server
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status);
_Other when element(1, _Other) /= 'EXIT',
element(1, _Other) /= started,
element(1, _Other) /= finished,
element(1, _Other) /= print ->
%% ignore anything not generated by test server
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,RejectIoReqs,
+ Terminate,Comment,CurrConf,Status)
after Timeout ->
ReturnValue
end.
-run_test_case_msgloop_io(ReplyAs,CaptureStdout,Msg,From,Func) ->
+run_test_case_msgloop_io(From,ReplyAs,CaptureStdout,RejectIoReqs,
+ Msg,From,Func) ->
case Msg of
{'EXIT',_} ->
From ! {io_reply,ReplyAs,{error,Func}};
_ ->
From ! {io_reply,ReplyAs,ok}
end,
- if CaptureStdout /= false ->
- CaptureStdout ! {captured,Msg};
- true ->
+ Proceed = if RejectIoReqs -> get({permit_io,From});
+ true -> true
+ end,
+ if Proceed ->
+ if CaptureStdout /= false ->
+ CaptureStdout ! {captured,Msg};
+ true ->
+ ok
+ end,
+ output({minor,Msg},From);
+ true ->
ok
- end,
- output({minor,Msg},From).
+ end.
output(Msg,Sender) ->
local_or_remote_apply({test_server_ctrl,output,[Msg,Sender]}).
call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
+ %% Starter is also the group leader process
Starter = self(),
Data = {Mod,Func,TCPid,TCExitReason,Loc},
EndConfProc =
fun() ->
+ group_leader(Starter, self()),
Supervisor = self(),
EndConfApply =
fun() ->
case catch apply(Mod,end_per_testcase,[Func,Conf]) of
{'EXIT',Why} ->
+ timer:sleep(1),
group_leader() ! {printout,12,
- "ERROR! ~p:end_per_testcase(~p, ~p)"
+ "WARNING! "
+ "~p:end_per_testcase(~p, ~p)"
" crashed!\n\tReason: ~p\n",
[Mod,Func,Conf,Why]};
_ ->
@@ -948,15 +1147,23 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
{'EXIT',Pid,Reason} ->
Starter ! {self(),{call_end_conf,Data,{error,Reason}}}
after TVal ->
+ exit(Pid, kill),
+ group_leader() ! {printout,12,
+ "WARNING! ~p:end_per_testcase(~p, ~p)"
+ " failed!\n\tReason: timetrap timeout"
+ " after ~w ms!\n", [Mod,Func,Conf,TVal]},
Starter ! {self(),{call_end_conf,Data,{error,timeout}}}
end
end,
spawn_link(EndConfProc).
spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why,
- Loc,SendTo,Comment) ->
+ Loc,SendTo) ->
FwCall =
fun() ->
+ %% set group leader so that printouts/comments
+ %% from the framework get printed in the logs
+ group_leader(SendTo, self()),
Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
%% if init_per_testcase fails, the test case
%% should be skipped
@@ -968,12 +1175,12 @@ spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why,
end,
%% finished, report back
SendTo ! {self(),fw_notify_done,
- {TVal/1000,Skip,Loc,[],Comment}}
+ {TVal/1000,Skip,Loc,[],undefined}}
end,
spawn_link(FwCall);
spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
- {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) ->
+ {timetrap_timeout,TVal}=Why,_Loc,SendTo) ->
%%! 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
@@ -985,6 +1192,9 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
end,
FwCall =
fun() ->
+ %% set group leader so that printouts/comments
+ %% from the framework get printed in the logs
+ group_leader(SendTo, self()),
{RetVal,Report} =
case proplists:get_value(tc_status, EndConf1) of
undefined ->
@@ -996,6 +1206,10 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
E = {failed,{Mod,end_per_testcase,Why}},
{Result,E}
end,
+ group_leader() ! {printout,12,
+ "WARNING! ~p:end_per_testcase(~p, ~p)"
+ " failed!\n\tReason: timetrap timeout"
+ " after ~w ms!\n", [Mod,Func,EndConf,TVal]},
FailLoc = proplists:get_value(tc_fail_loc, EndConf1),
case catch do_end_tc_call(Mod,Func, FailLoc,
{Pid,Report,[EndConf1]}, Why) of
@@ -1004,39 +1218,48 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
_ ->
ok
end,
- %% if end_per_testcase fails a warning should be
- %% printed as comment
- Comment1 = if Comment == "" -> "";
- true -> Comment ++ "<br>"
- end,
- %% finished, report back
+ Warn = "<font color=\"red\">"
+ "WARNING: end_per_testcase timed out!</font>",
+ %% finished, report back (if end_per_testcase fails, a warning
+ %% should be printed as part of the comment)
SendTo ! {self(),fw_notify_done,
- {TVal/1000,RetVal,FailLoc,[],
- [Comment1,"<font color=\"red\">"
- "WARNING: end_per_testcase timed out!"
- "</font>"]}}
+ {TVal/1000,RetVal,FailLoc,[],Warn}}
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) ->
FwCall =
fun() ->
+ %% set group leader so that printouts/comments
+ %% from the framework get printed in the logs
+ group_leader(SendTo, self()),
test_server_sup:framework_call(report, [framework_error,
- {{FwMod,FwFunc},FwError}]),
+ {{FwMod,FwFunc},
+ FwError}]),
Comment =
lists:flatten(
io_lib:format("<font color=\"red\">"
- "WARNING! ~w:~w failed!</font>", [FwMod,FwFunc])),
+ "WARNING! ~w:~w failed!</font>",
+ [FwMod,FwFunc])),
%% finished, report back
SendTo ! {self(),fw_notify_done,
- {died,{error,{FwMod,FwFunc,FwError}},{FwMod,FwFunc},[],Comment}}
+ {died,{error,{FwMod,FwFunc,FwError}},
+ {FwMod,FwFunc},[],Comment}}
end,
spawn_link(FwCall);
-spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) ->
+spawn_fw_call(Mod,Func,CurrConf,Pid,Error,Loc,SendTo) ->
+ {Mod1,Func1} =
+ case {Mod,Func,CurrConf} of
+ {undefined,undefined,{{M,F},_}} -> {M,F};
+ _ -> {Mod,Func}
+ end,
FwCall =
fun() ->
- case catch fw_error_notify(Mod,Func,[],
+ %% set group leader so that printouts/comments
+ %% from the framework get printed in the logs
+ group_leader(SendTo, self()),
+ case catch fw_error_notify(Mod1,Func1,[],
Error,Loc) of
{'EXIT',FwErrorNotifyErr} ->
exit({fw_notify_done,error_notification,
@@ -1045,7 +1268,7 @@ 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, Loc,
+ case catch do_end_tc_call(Mod1,Func1, Loc,
{Pid,Error,[Conf]},Error) of
{'EXIT',FwEndTCErr} ->
exit({fw_notify_done,end_tc,FwEndTCErr});
@@ -1053,7 +1276,7 @@ spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) ->
ok
end,
%% finished, report back
- SendTo ! {self(),fw_notify_done,{died,Error,Loc,Comment}}
+ SendTo ! {self(),fw_notify_done,{died,Error,Loc,[],undefined}}
end,
spawn_link(FwCall).
@@ -1110,10 +1333,11 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit,
TimetrapData, LogOpts, TCCallback) ->
put(test_server_multiply_timetraps, TimetrapData),
put(test_server_logopts, LogOpts),
-
+ FWInitResult = test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0],
+ {ok,Args0}),
+ group_leader() ! {test_case_initialized,self()},
{{Time,Value},Loc,Opts} =
- case test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0],
- {ok,Args0}) of
+ case FWInitResult of
{ok,Args} ->
run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback);
Error = {error,_Reason} ->
@@ -1135,12 +1359,15 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit,
{auto_skip,Reason} ->
Where = {Mod,Func},
NewResult = do_end_tc_call(Mod,Func, Where, {{skip,Reason},Args0},
- {skip,{fw_auto_skip,Reason}}),
+ {skip,Reason}),
{{0,NewResult},Where,[]}
end,
exit({Ref,Time,Value,Loc,Opts}).
run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
+ %% save current state in controller loop
+ sync_send(group_leader(),set_curr_conf,{{Mod,Func},hd(Args)},
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
case RunInit of
run_init ->
put(test_server_init_or_end_conf,{init_per_testcase,Func}),
@@ -1199,8 +1426,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
%% 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),
+ 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,_} ->
@@ -1253,11 +1480,15 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
end.
do_end_tc_call(M,F, Loc, Res, Return) ->
+ IsSuite = case lists:reverse(atom_to_list(M)) of
+ [$E,$T,$I,$U,$S,$_|_] -> true;
+ _ -> false
+ end,
FwMod = os:getenv("TEST_SERVER_FRAMEWORK"),
{Mod,Func} =
if FwMod == M ; FwMod == "undefined"; FwMod == false ->
{M,F};
- is_list(Loc) and (length(Loc)>1) ->
+ (not IsSuite) and 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.
@@ -1472,7 +1703,8 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
throw:Other ->
Comment0 = case read_comment() of
"" -> "";
- Cmt -> Cmt ++ "<br>"
+ Cmt -> Cmt ++ test_server_ctrl:xhtml("<br>",
+ "<br />")
end,
set_loc(erlang:get_stacktrace()),
comment(io_lib:format("~s<font color=\"red\">"
@@ -1495,7 +1727,8 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
end,
Comment0 = case read_comment() of
"" -> "";
- Cmt -> Cmt ++ "<br>"
+ Cmt -> Cmt ++ test_server_ctrl:xhtml("<br>",
+ "<br />")
end,
comment(io_lib:format("~s<font color=\"red\">"
"WARNING: ~w crashed!"
@@ -1518,14 +1751,27 @@ get_loc(Pid) ->
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),
+ case get(test_server_loc) of
+ undefined ->
+ put(test_server_loc, Stk);
+ {Suite,Case} ->
+ %% location info unknown, check if {Suite,Case,Line}
+ %% is available in stacktrace. and if so, use stacktrace
+ %% instead of currect test_server_loc
+ case [match || {S,C,_L} <- Stk, S == Suite, C == Case] of
+ [match|_] -> put(test_server_loc, Stk);
+ _ -> ok
+ end;
+ _ ->
+ ok
+ end,
get_loc().
%% find the latest known Suite:Testcase
get_mf(MFs) ->
get_mf(MFs, {undefined,undefined}).
-get_mf([MF|MFs], Found) when is_tuple(MF) ->
+get_mf([MF|MFs], _Found) when is_tuple(MF) ->
ModFunc = {Mod,_} = case MF of
{M,F,_} -> {M,F};
MF -> MF
@@ -1547,13 +1793,20 @@ mod_loc(Loc) ->
%% handle diff line num versions
case Loc of
[{{_M,_F},_L}|_] ->
- [{?pl2a(M),F,L} || {{M,F},L} <- Loc];
+ [begin if L /= 0 -> {?pl2a(M),F,L};
+ true -> {?pl2a(M),F} end end || {{M,F},L} <- Loc];
[{_M,_F}|_] ->
[{?pl2a(M),F} || {M,F} <- Loc];
+ {{M,F},0} ->
+ [{?pl2a(M),F}];
{{M,F},L} ->
[{?pl2a(M),F,L}];
{M,ForL} ->
[{?pl2a(M),ForL}];
+ {M,F,0} ->
+ [{M,F}];
+ [{M,F,0}|Stack] ->
+ [{M,F}|Stack];
_ ->
Loc
end.
@@ -1571,7 +1824,7 @@ fw_error_notify(Mod, Func, Args, Error, Loc) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% print(Detail,Format,Args) -> ok
+%% print(Detail,Format,Args,Printer) -> ok
%% Detail = integer()
%% Format = string()
%% Args = [term()]
@@ -1582,6 +1835,9 @@ fw_error_notify(Mod, Func, Args, Error, Loc) ->
print(Detail,Format,Args) ->
local_or_remote_apply({test_server_ctrl,print,[Detail,Format,Args]}).
+print(Detail,Format,Args,Printer) ->
+ local_or_remote_apply({test_server_ctrl,print,[Detail,Format,Args,Printer]}).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% print_timsteamp(Detail,Leader) -> ok
%%
@@ -1743,6 +1999,13 @@ messages_get() ->
test_server_sup:messages_get([]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% permit_io(GroupLeader, FromPid) -> ok
+%%
+%% Make sure proceeding IO from FromPid won't get rejected
+permit_io(GroupLeader, FromPid) ->
+ GroupLeader ! {permit_io,FromPid}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sleep(Time) -> ok
%% Time = integer() | float() | infinity
%%
@@ -1845,29 +2108,40 @@ fail() ->
%% Break a test case so part of the test can be done manually.
%% Use continue/0 to continue.
break(Comment) ->
- case erase(test_server_timetraps) of
- undefined -> ok;
- List -> lists:foreach(fun({Ref,_}) -> timetrap_cancel(Ref) end, List)
- end,
+ break(?MODULE, Comment).
+
+break(CBM, Comment) ->
+ break(CBM, '', Comment).
+
+break(CBM, TestCase, Comment) ->
+ timetrap_cancel(),
+ {TCName,CntArg,PName} =
+ if TestCase == '' ->
+ {"", "", test_server_break_process};
+ true ->
+ Str = atom_to_list(TestCase),
+ {[32 | Str], Str,
+ list_to_atom("test_server_break_process_" ++ Str)}
+ end,
io:format(user,
"\n\n\n--- SEMIAUTOMATIC TESTING ---"
- "\nThe test case executes on process ~w"
+ "\nThe test case~s executes on process ~w"
"\n\n\n~s"
"\n\n\n-----------------------------\n\n"
- "Continue with --> test_server:continue().\n",
- [self(),Comment]),
- case whereis(test_server_break_process) of
+ "Continue with --> ~w:continue(~s).\n",
+ [TCName,self(),Comment,CBM,CntArg]),
+ case whereis(PName) of
undefined ->
- spawn_break_process(self());
+ spawn_break_process(self(), PName);
OldBreakProcess ->
OldBreakProcess ! cancel,
- spawn_break_process(self())
+ spawn_break_process(self(), PName)
end,
receive continue -> ok end.
-spawn_break_process(Pid) ->
+spawn_break_process(Pid, PName) ->
spawn(fun() ->
- register(test_server_break_process,self()),
+ register(PName, self()),
receive
continue -> continue(Pid);
cancel -> ok
@@ -1876,13 +2150,19 @@ spawn_break_process(Pid) ->
continue() ->
case whereis(test_server_break_process) of
- undefined ->
- ok;
- BreakProcess ->
- BreakProcess ! continue
+ undefined -> ok;
+ BreakProcess -> BreakProcess ! continue
end.
-continue(Pid) ->
+continue(TestCase) when is_atom(TestCase) ->
+ PName = list_to_atom("test_server_break_process_" ++
+ atom_to_list(TestCase)),
+ case whereis(PName) of
+ undefined -> ok;
+ BreakProcess -> BreakProcess ! continue
+ end;
+
+continue(Pid) when is_pid(Pid) ->
Pid ! continue.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1920,26 +2200,56 @@ timetrap_scale_factor() ->
%%
%% Creates a time trap, that will kill the calling process if the
%% trap is not cancelled with timetrap_cancel/1, within Timeout milliseconds.
-timetrap(Timeout0) ->
- Timeout = time_ms(Timeout0),
- cancel_default_timetrap(),
- case get(test_server_multiply_timetraps) of
- undefined -> timetrap1(Timeout, true);
- {undefined,false} -> timetrap1(Timeout, false);
- {undefined,_} -> timetrap1(Timeout, true);
- {infinity,_} -> infinity;
- {_Int,_Scale} when Timeout == infinity -> infinity;
- {Int,Scale} -> timetrap1(Timeout*Int, Scale)
- end.
+timetrap(Timeout) ->
+ MultAndScale =
+ case get(test_server_multiply_timetraps) of
+ undefined -> {fun(T) -> T end, true};
+ {undefined,false} -> {fun(T) -> T end, false};
+ {undefined,_} -> {fun(T) -> T end, true};
+ {infinity,_} -> {fun(_) -> infinity end, false};
+ {Int,Scale} -> {fun(infinity) -> infinity;
+ (T) -> T*Int end, Scale}
+ end,
+ timetrap(Timeout, Timeout, self(), MultAndScale).
+
+%% when the function is called from different process than
+%% the test case, the test_server_multiply_timetraps data
+%% is unknown and must be passed as argument
+timetrap(Timeout, TCPid, MultAndScale) ->
+ timetrap(Timeout, Timeout, TCPid, MultAndScale).
+
+timetrap(Timeout0, TimeToReport0, TCPid, MultAndScale = {Multiplier,Scale}) ->
+ %% the time_ms call will either convert Timeout to ms or spawn a
+ %% user timetrap which sends the result to the IO server process
+ Timeout = time_ms(Timeout0, TCPid, MultAndScale),
+ Timeout1 = Multiplier(Timeout),
+ TimeToReport = if Timeout0 == TimeToReport0 ->
+ Timeout1;
+ true ->
+ %% only convert to ms, don't start a
+ %% user timetrap
+ time_ms_check(TimeToReport0)
+ end,
+ cancel_default_timetrap(self() == TCPid),
+ Handle = case Timeout1 of
+ infinity ->
+ infinity;
+ _ ->
+ spawn_link(test_server_sup,timetrap,[Timeout1,TimeToReport,
+ Scale,TCPid])
+ end,
+
+ %% ERROR! This sets dict on IO process instead of testcase process
+ %% if Timeout is return value from previous user timetrap!!
-timetrap1(Timeout, Scale) ->
- TCPid = self(),
- Ref = spawn_link(test_server_sup,timetrap,[Timeout,Scale,TCPid]),
case get(test_server_timetraps) of
- undefined -> put(test_server_timetraps,[{Ref,TCPid}]);
- List -> put(test_server_timetraps,[{Ref,TCPid}|List])
+ undefined ->
+ put(test_server_timetraps,[{Handle,TCPid,{TimeToReport,Scale}}]);
+ List ->
+ List1 = lists:delete({infinity,TCPid,{infinity,false}}, List),
+ put(test_server_timetraps,[{Handle,TCPid,{TimeToReport,Scale}}|List1])
end,
- Ref.
+ Handle.
ensure_timetrap(Config) ->
case get(test_server_timetraps) of
@@ -1964,7 +2274,10 @@ ensure_timetrap(Config) ->
put(test_server_default_timetrap, timetrap(seconds(DTmo)))
end.
-cancel_default_timetrap() ->
+%% executing on IO process, no default timetrap ever set here
+cancel_default_timetrap(false) ->
+ ok;
+cancel_default_timetrap(true) ->
case get(test_server_default_timetrap) of
undefined ->
ok;
@@ -1982,75 +2295,175 @@ cancel_default_timetrap() ->
error
end.
-
-time_ms({hours,N}) -> hours(N);
-time_ms({minutes,N}) -> minutes(N);
-time_ms({seconds,N}) -> seconds(N);
-time_ms({Other,_N}) ->
+time_ms({hours,N}, _, _) -> hours(N);
+time_ms({minutes,N}, _, _) -> minutes(N);
+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_format,Other});
-time_ms(Ms) when is_integer(Ms) -> Ms;
-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(Ms, _, _) when is_integer(Ms) -> Ms;
+time_ms(infinity, _, _) -> infinity;
+time_ms(Fun, TCPid, MultAndScale) when is_function(Fun) ->
+ time_ms_apply(Fun, TCPid, MultAndScale);
+time_ms({M,F,A}=MFA, TCPid, MultAndScale) when is_atom(M), is_atom(F), is_list(A) ->
+ time_ms_apply(MFA, TCPid, MultAndScale);
+time_ms(Other, _, _) -> exit({invalid_time_format,Other}).
time_ms_check(MFA = {M,F,A}) when is_atom(M), is_atom(F), is_list(A) ->
- exit({invalid_time_format,MFA});
+ MFA;
time_ms_check(Fun) when is_function(Fun) ->
- exit({invalid_time_format,Fun});
+ Fun;
time_ms_check(Other) ->
- time_ms(Other).
+ time_ms(Other, undefined, undefined).
+
+time_ms_apply(Func, TCPid, MultAndScale) ->
+ {_,GL} = process_info(TCPid, group_leader),
+ WhoAmI = self(), % either TC or IO server
+ T0 = now(),
+ UserTTSup =
+ spawn(fun() ->
+ user_timetrap_supervisor(Func, WhoAmI, TCPid,
+ GL, T0, MultAndScale)
+ end),
+ receive
+ {UserTTSup,infinity} ->
+ %% remember the user timetrap so that it can be cancelled
+ save_user_timetrap(TCPid, UserTTSup, T0),
+ %% we need to make sure the user timetrap function
+ %% gets time to execute and return
+ timetrap(infinity, TCPid, MultAndScale)
+ after 5000 ->
+ exit(UserTTSup, kill),
+ if WhoAmI /= GL ->
+ exit({user_timetrap_error,time_ms_apply});
+ true ->
+ format("=== ERROR: User timetrap execution failed!", []),
+ ignore
+ end
+ end.
+
+user_timetrap_supervisor(Func, Spawner, TCPid, GL, T0, MultAndScale) ->
+ process_flag(trap_exit, true),
+ Spawner ! {self(),infinity},
+ MonRef = monitor(process, TCPid),
+ UserTTSup = self(),
+ group_leader(GL, UserTTSup),
+ UserTT = spawn_link(fun() -> call_user_timetrap(Func, UserTTSup) end),
+ receive
+ {UserTT,Result} ->
+ demonitor(MonRef, [flush]),
+ Elapsed = trunc(timer:now_diff(now(), T0) / 1000),
+ try time_ms_check(Result) of
+ TimeVal ->
+ %% this is the new timetrap value to set (return value
+ %% from a fun or an MFA)
+ GL ! {user_timetrap,TCPid,TimeVal,T0,Elapsed,MultAndScale}
+ catch _:_ ->
+ %% when other than a legal timetrap value is returned
+ %% which will be the normal case for user timetraps
+ GL ! {user_timetrap,TCPid,0,T0,Elapsed,MultAndScale}
+ end;
+ {'EXIT',UserTT,Error} when Error /= normal ->
+ demonitor(MonRef, [flush]),
+ GL ! {user_timetrap,TCPid,0,T0,{user_timetrap_error,Error},
+ MultAndScale};
+ {'DOWN',MonRef,_,_,_} ->
+ demonitor(MonRef, [flush]),
+ exit(UserTT, kill)
+ end.
+
+call_user_timetrap(Func, Sup) when is_function(Func) ->
+ try Func() of
+ Result ->
+ Sup ! {self(),Result}
+ catch _:Error ->
+ exit({Error,erlang:get_stacktrace()})
+ end;
+call_user_timetrap({M,F,A}, Sup) ->
+ try apply(M,F,A) of
+ Result ->
+ Sup ! {self(),Result}
+ catch _:Error ->
+ exit({Error,erlang:get_stacktrace()})
+ end.
+
+save_user_timetrap(TCPid, UserTTSup, StartTime) ->
+ %% save pid of user timetrap supervisor process so that
+ %% it may be stopped even before the timetrap func has returned
+ NewUserTT = {TCPid,{UserTTSup,StartTime}},
+ case get(test_server_user_timetrap) of
+ undefined ->
+ put(test_server_user_timetrap, [NewUserTT]);
+ UserTTSups ->
+ case proplists:get_value(TCPid, UserTTSups) of
+ undefined ->
+ put(test_server_user_timetrap,
+ [NewUserTT | UserTTSups]);
+ PrevTTSup ->
+ %% remove prev user timetrap
+ remove_user_timetrap(PrevTTSup),
+ put(test_server_user_timetrap,
+ [NewUserTT | proplists:delete(TCPid,
+ UserTTSups)])
+ end
+ end.
+
+update_user_timetraps(TCPid, StartTime) ->
+ %% called when a user timetrap is triggered
+ case get(test_server_user_timetrap) of
+ undefined ->
+ proceed;
+ UserTTs ->
+ case proplists:get_value(TCPid, UserTTs) of
+ {_UserTTSup,StartTime} -> % same timetrap
+ put(test_server_user_timetrap,
+ proplists:delete(TCPid, UserTTs)),
+ proceed;
+ {OtherUserTTSup,OtherStartTime} ->
+ case timer:now_diff(OtherStartTime, StartTime) of
+ Diff when Diff >= 0 ->
+ ignore;
+ _ ->
+ exit(OtherUserTTSup, kill),
+ put(test_server_user_timetrap,
+ proplists:delete(TCPid, UserTTs)),
+ proceed
+ end;
+ undefined ->
+ proceed
+ end
+ end.
+
+remove_user_timetrap(TTSup) ->
+ exit(TTSup, kill).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timetrap_cancel(Handle) -> ok
%% Handle = term()
%%
%% Cancels a time trap.
-timetrap_cancel(infinity) ->
- ok;
timetrap_cancel(Handle) ->
+ timetrap_cancel_one(Handle, true).
+
+timetrap_cancel_one(infinity, _SendToServer) ->
+ ok;
+timetrap_cancel_one(Handle, SendToServer) ->
case get(test_server_timetraps) of
- undefined -> ok;
- [{Handle,_}] -> erase(test_server_timetraps);
- Timers -> put(test_server_timetraps,
- lists:keydelete(Handle, 1, Timers))
+ undefined ->
+ ok;
+ [{Handle,_,_}] ->
+ erase(test_server_timetraps);
+ Timers ->
+ case lists:keysearch(Handle, 1, Timers) of
+ {value,_} ->
+ put(test_server_timetraps,
+ lists:keydelete(Handle, 1, Timers));
+ false when SendToServer == true ->
+ group_leader() ! {timetrap_cancel_one,Handle,self()};
+ false ->
+ ok
+ end
end,
test_server_sup:timetrap_cancel(Handle).
@@ -2059,16 +2472,61 @@ timetrap_cancel(Handle) ->
%%
%% Cancels timetrap for current test case.
timetrap_cancel() ->
+ timetrap_cancel_all(self(), true).
+
+timetrap_cancel_all(TCPid, SendToServer) ->
case get(test_server_timetraps) of
undefined ->
ok;
Timers ->
- case lists:keysearch(self(), 2, Timers) of
- {value,{Handle,_}} ->
- timetrap_cancel(Handle);
- _ ->
+ [timetrap_cancel_one(Handle, false) ||
+ {Handle,Pid,_} <- Timers, Pid == TCPid]
+ end,
+ case get(test_server_user_timetrap) of
+ undefined ->
+ ok;
+ UserTTs ->
+ case proplists:get_value(TCPid, UserTTs) of
+ {UserTTSup,_StartTime} ->
+ remove_user_timetrap(UserTTSup),
+ put(test_server_user_timetrap,
+ proplists:delete(TCPid, UserTTs));
+ undefined ->
ok
end
+ end,
+ if SendToServer == true ->
+ group_leader() ! {timetrap_cancel_all,TCPid,self()};
+ true ->
+ ok
+ end,
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% get_timetrap_info() -> {Timeout,Scale} | undefined
+%%
+%% Read timetrap info for current test case
+get_timetrap_info() ->
+ get_timetrap_info(self(), true).
+
+get_timetrap_info(TCPid, SendToServer) ->
+ case get(test_server_timetraps) of
+ undefined ->
+ undefined;
+ Timers ->
+ case [Info || {Handle,Pid,Info} <- Timers,
+ Pid == TCPid, Handle /= infinity] of
+ [I|_] ->
+ I;
+ [] when SendToServer == true ->
+ MsgLooper = group_leader(),
+ MsgLooper ! {get_timetrap_info,TCPid,self()},
+ receive
+ {MsgLooper,get_timetrap_info,I} -> I
+ end;
+ [] ->
+ undefined
+ end
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2492,11 +2950,23 @@ read_comment() ->
MsgLooper = group_leader(),
MsgLooper ! {read_comment,self()},
receive
- {MsgLooper,read_comment,Comment} ->
- Comment
+ {MsgLooper,read_comment,Comment} -> Comment
+ after
+ 5000 -> ""
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% make_priv_dir() -> ok
+%%
+%% Order test server to create the private directory
+%% for the current test case.
+make_priv_dir() ->
+ MsgLooper = group_leader(),
+ group_leader() ! {make_priv_dir,self()},
+ receive
+ {MsgLooper,make_priv_dir,Result} -> Result
after
- 5000 ->
- ""
+ 5000 -> error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index 4fad86d16d..df2187bc04 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -162,8 +162,9 @@
-export([jobs/0, run_test/1, wait_finish/0, idle_notify/1,
abort_current_testcase/1, abort/0]).
-export([start_get_totals/1, stop_get_totals/0]).
--export([get_levels/0, set_levels/3]).
+-export([reject_io_reqs/1, get_levels/0, set_levels/3]).
-export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]).
+-export([create_priv_dir/1]).
-export([cover/2, cover/3, cover/7,
cross_cover_analyse/1, cross_cover_analyse/2, trc/1, stop_trace/0]).
-export([testcase_callback/1]).
@@ -171,7 +172,7 @@
-export([kill_slavenodes/0]).
%%% TEST_SERVER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([output/2, print/2, print/3, print_timestamp/2]).
+-export([output/2, print/2, print/3, print/4, 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, to_string/1]).
-export([get_target_info/0]).
@@ -187,6 +188,7 @@
-export([handle_call/3, handle_cast/2, handle_info/2]).
-export([do_test_cases/4]).
-export([do_spec/2, do_spec_list/2]).
+-export([xhtml/2]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -214,9 +216,13 @@
X == auto_skip -> skipped;
true -> X end).
--record(state,{jobs=[],levels={1,19,10},
- multiply_timetraps=1,scale_timetraps=true,
- finish=false,
+-define(auto_skip_color, "#FFA64D").
+-define(user_skip_color, "#FF8000").
+-define(sortable_table_name, "SortableTable").
+
+-record(state,{jobs=[], levels={1,19,10}, reject_io_reqs=false,
+ multiply_timetraps=1, scale_timetraps=true,
+ create_priv_dir=auto_per_run, finish=false,
target_info, trc=false, cover=false, wait_for_node=[],
testcase_callback=undefined, idle_notify=[],
get_totals=false, random_seed=undefined}).
@@ -493,6 +499,9 @@ get_levels() ->
set_levels(Show, Major, Minor) ->
controller_call({set_levels,Show,Major,Minor}).
+reject_io_reqs(Bool) ->
+ controller_call({reject_io_reqs,Bool}).
+
multiply_timetraps(N) ->
controller_call({multiply_timetraps,N}).
@@ -502,6 +511,9 @@ scale_timetraps(Bool) ->
get_timetrap_parameters() ->
controller_call(get_timetrap_parameters).
+create_priv_dir(Value) ->
+ controller_call({create_priv_dir,Value}).
+
trc(TraceFile) ->
controller_call({trace,TraceFile}, 2*?ACCEPT_TIMEOUT).
@@ -642,8 +654,8 @@ init([Param]) ->
contact_main_target(local) ->
%% When used by a general framework, global registration of
%% test_server should not be required.
- case os:getenv("TEST_SERVER_FRAMEWORK") of
- FW when FW =:= false; FW =:= "undefined" ->
+ case get_fw_mod(undefined) of
+ undefined ->
%% Local target! The global test_server process implemented by
%% test_server.erl will not be started, so we simulate it by
%% globally registering this process instead.
@@ -807,6 +819,8 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) ->
[SpecName,{State#state.multiply_timetraps,
State#state.scale_timetraps}],
LogDir, Name, State#state.levels,
+ State#state.reject_io_reqs,
+ State#state.create_priv_dir,
State#state.testcase_callback, ExtraTools1),
NewJobs = [{Name,Pid}|State#state.jobs],
{reply, ok, State#state{jobs=NewJobs}};
@@ -816,6 +830,8 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) ->
[SpecList,{State#state.multiply_timetraps,
State#state.scale_timetraps}],
LogDir, Name, State#state.levels,
+ State#state.reject_io_reqs,
+ State#state.create_priv_dir,
State#state.testcase_callback, ExtraTools1),
NewJobs = [{Name,Pid}|State#state.jobs],
{reply, ok, State#state{jobs=NewJobs}};
@@ -833,6 +849,8 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) ->
{State#state.multiply_timetraps,
State#state.scale_timetraps}],
LogDir, Name, State#state.levels,
+ State#state.reject_io_reqs,
+ State#state.create_priv_dir,
State#state.testcase_callback, ExtraTools1),
NewJobs = [{Name,Pid}|State#state.jobs],
{reply, ok, State#state{jobs=NewJobs}}
@@ -964,6 +982,15 @@ handle_call({set_levels,Show,Major,Minor}, _From, State) ->
{reply,ok,State#state{levels={Show,Major,Minor}}};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% handle_call({reject_io_reqs,Bool}, _, State) -> ok
+%% Bool = bool()
+%%
+%% May be used to switch off stdout printouts to the minor log file
+
+handle_call({reject_io_reqs,Bool}, _From, State) ->
+ {reply,ok,State#state{reject_io_reqs=Bool}};
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% handle_call({multiply_timetraps,N}, _, State) -> ok
%% N = integer() | infinity
%%
@@ -1041,6 +1068,18 @@ handle_call({cover,App,Analyse}, _From, State) ->
{reply,ok,State#state{cover={App,Analyse}}};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% handle_call({create_priv_dir,Value}, _, State) -> ok | {error,Reason}
+%%
+%% Set create_priv_dir to either auto_per_run (create common priv dir once
+%% per test run), manual_per_tc (the priv dir name will be unique for each
+%% test case, but the user has to call test_server:make_priv_dir/0 to create
+%% it), or auto_per_tc (unique priv dir created automatically for each test
+%% case).
+
+handle_call({create_priv_dir,Value}, _From, State) ->
+ {reply,ok,State#state{create_priv_dir=Value}};
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% handle_call({testcase_callback,{Mod,Func}}, _, State) -> ok | {error,Reason}
%%
%% Add a callback function that will be called before and after every
@@ -1297,7 +1336,12 @@ terminate(_Reason, State) ->
end,
kill_all_jobs(State#state.jobs),
test_server_node:stop(State#state.target_info),
- test_server_h:restore(),
+ case lists:keysearch(sasl, 1, application:which_applications()) of
+ {value,_} ->
+ test_server_h:restore();
+ _ ->
+ ok
+ end,
ok.
kill_all_jobs([{_Name,JobPid}|Jobs]) ->
@@ -1312,14 +1356,16 @@ kill_all_jobs([]) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% spawn_tester(Mod, Func, Args, Dir, Name, Levels,
-%% TestCaseCallback, ExtraTools) -> Pid
+%% spawn_tester(Mod, Func, Args, Dir, Name, Levels, RejectIoReqs,
+%% CreatePrivDir, TestCaseCallback, ExtraTools) -> Pid
%% Mod = atom()
%% Func = atom()
%% Args = [term(),...]
%% Dir = string()
%% Name = string()
%% Levels = {integer(),integer(),integer()}
+%% RejectIoReqs = bool()
+%% CreatePrivDir = auto_per_run | manual_per_tc | auto_per_tc
%% TestCaseCallback = {CBMod,CBFunc} | undefined
%% ExtraTools = [ExtraTool,...]
%% ExtraTool = CoverInfo | TraceInfo | RandomSeed
@@ -1330,14 +1376,15 @@ kill_all_jobs([]) ->
%% When the named function is done executing, a summary of the results
%% is printed to the log files.
-spawn_tester(Mod, Func, Args, Dir, Name, Levels, TCCallback, ExtraTools) ->
+spawn_tester(Mod, Func, Args, Dir, Name, Levels, RejectIoReqs,
+ CreatePrivDir, TCCallback, ExtraTools) ->
spawn_link(
- fun() -> init_tester(Mod, Func, Args, Dir, Name, Levels,
- TCCallback, ExtraTools)
+ fun() -> init_tester(Mod, Func, Args, Dir, Name, Levels, RejectIoReqs,
+ CreatePrivDir, TCCallback, ExtraTools)
end).
-init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev},
- TCCallback, ExtraTools) ->
+init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev}, RejectIoReqs,
+ CreatePrivDir, TCCallback, ExtraTools) ->
process_flag(trap_exit, true),
put(test_server_name, Name),
put(test_server_dir, Dir),
@@ -1348,8 +1395,22 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev},
put(test_server_summary_level, SumLev),
put(test_server_major_level, MajLev),
put(test_server_minor_level, MinLev),
+ put(test_server_reject_io_reqs, RejectIoReqs),
+ put(test_server_create_priv_dir, CreatePrivDir),
put(test_server_random_seed, proplists:get_value(random_seed, ExtraTools)),
put(test_server_testcase_callback, TCCallback),
+ case os:getenv("TEST_SERVER_FRAMEWORK") of
+ FW when FW =:= false; FW =:= "undefined" ->
+ put(test_server_framework, '$none');
+ FW ->
+ put(test_server_framework_name, list_to_atom(FW)),
+ case os:getenv("TEST_SERVER_FRAMEWORK_NAME") of
+ FWName when FWName =:= false; FWName =:= "undefined" ->
+ put(test_server_framework_name, '$none');
+ FWName ->
+ put(test_server_framework_name, list_to_atom(FWName))
+ end
+ end,
%% before first print, read and set logging options
LogOpts = test_server_sup:framework_call(get_logopts, [], []),
put(test_server_logopts, LogOpts),
@@ -1381,8 +1442,10 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev},
end,
OkN = get(test_server_ok),
FailedN = get(test_server_failed),
- print(html,"<tr><td></td><td><b>TOTAL</b></td><td></td><td></td>"
- "<td>~.3fs</td><td><b>~s</b></td><td>~p Ok, ~p Failed~s of ~p</td></tr>\n",
+ print(html,"\n</tbody>\n<tfoot>\n"
+ "<tr><td></td><td><b>TOTAL</b></td><td></td><td></td><td></td>"
+ "<td>~.3fs</td><td><b>~s</b></td><td>~p Ok, ~p Failed~s of ~p</td></tr>\n"
+ "</tfoot>\n",
[Time,SuccessStr,OkN,FailedN,SkipStr,OkN+FailedN+SkippedN]).
%% timer:tc/3
@@ -1443,7 +1506,7 @@ stop_extra_tools([], _) ->
%% Reads the named test suite specification file, and executes it.
%%
%% This function is meant to be called by a process created by
-%% spawn_tester/7, which sets up some necessary dictionary values.
+%% spawn_tester/10, which sets up some necessary dictionary values.
do_spec(SpecName, TimetrapSpec) when is_list(SpecName) ->
case file:consult(SpecName) of
@@ -1492,7 +1555,7 @@ do_spec(SpecName, TimetrapSpec) when is_list(SpecName) ->
%% should not be used. Use a configuration test case instead.
%%
%% This function is meant to be called by a process created by
-%% spawn_tester/7, which sets up some necessary dictionary values.
+%% spawn_tester/10, which sets up some necessary dictionary values.
do_spec_list(TermList0, TimetrapSpec) ->
Nodes = [],
@@ -1659,7 +1722,7 @@ add_mod(Mod, Mods) ->
%% configuration information into the log files.
%%
%% This function is meant to be called by a process created by
-%% spawn_tester/7, which sets up some necessary dictionary values.
+%% spawn_tester/10, which sets up some necessary dictionary values.
do_test_cases(TopCases, SkipCases,
Config, MultiplyTimetrap) when is_integer(MultiplyTimetrap);
MultiplyTimetrap == infinity ->
@@ -1668,12 +1731,8 @@ do_test_cases(TopCases, SkipCases,
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,
+ {ok,TestDir} = start_log_file(),
+ FwMod = get_fw_mod(?MODULE),
case collect_all_cases(TopCases, SkipCases) of
{error,Why} ->
print(1, "Error starting: ~p", [Why]),
@@ -1692,60 +1751,89 @@ do_test_cases(TopCases, SkipCases,
[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}]),
+ TestName = if is_list(Test) ->
+ lists:flatten(io_lib:format("~s", [Test]));
+ true ->
+ lists:flatten(io_lib:format("~p", [Test]))
+ end,
+ TestDescr = "Test " ++ TestName ++ " results",
- Header =
- case test_server_sup:framework_call(overview_html_header, [Test], "") of
- "" ->
- TestName = lists:flatten(io_lib:format("~p", [Test])),
- ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
- "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n",
- "<html>\n",
- "<head><title>Test ", TestName, " results</title>\n",
- "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
- "</head>\n",
- "<body bgcolor=\"white\" text=\"black\" ",
- "link=\"blue\" vlink=\"purple\" alink=\"red\">",
- "<h2>Results from test ", TestName, "</h2>\n"];
- Html ->
- ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
- "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n" | Html]
+ test_server_sup:framework_call(report, [tests_start,{Test,N}]),
+ {Header,Footer} =
+ case test_server_sup:framework_call(get_html_wrapper,
+ [TestDescr,true,TestDir,
+ {[],[2,3,4,7,8],[1,6]}], "") of
+ Empty when (Empty == "") ; (element(2,Empty) == "") ->
+ put(basic_html, true),
+ {["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n",
+ "<html>\n",
+ "<head><title>", TestDescr, "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "</head>\n",
+ "<body bgcolor=\"white\" text=\"black\" ",
+ "link=\"blue\" vlink=\"purple\" alink=\"red\">",
+ "<h2>Results for test ", TestName, "</h2>\n"],
+ "\n</body>\n</html>\n"};
+ {basic_html,Html0,Html1} ->
+ put(basic_html, true),
+ {Html0++["<h1>Results for <i>",TestName,"</i></h1>\n"],
+ Html1};
+ {xhtml,Html0,Html1} ->
+ put(basic_html, false),
+ {Html0++["<h1>Results for <i>",TestName,"</i></h1>\n"],
+ Html1}
end,
- print(html, Header, []),
- print_timestamp(html, "Test started at "),
- print(html, "<p>Host:<br>\n"),
+ print(html, Header),
+
+ print(html, xhtml("<p>", "<h4>")),
+ print_timestamp(html, "Test started at "),
+ print(html, xhtml("</p>", "</h4>")),
+
+ print(html, xhtml("\n<p><b>Host info:</b><br>\n",
+ "\n<p><b>Host info:</b><br />\n")),
print_who(test_server_sup:hoststr(), test_server_sup:get_username()),
- print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n",
+ print(html, xhtml("<br>Used Erlang v~s in <tt>~s</tt></p>\n",
+ "<br />Used Erlang v~s in \"~s\"</p>\n"),
[erlang:system_info(version), code:root_dir()]),
-
+
if FwMod == ?MODULE ->
- print(html, "<p>Target:<br>\n"),
+ print(html, xhtml("\n<p><b>Target Info:</b><br>\n",
+ "\n<p><b>Target Info:</b><br />\n")),
print_who(TI#target_info.host, TI#target_info.username),
- print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n",
+ print(html, xhtml("<br>Used Erlang v~s in <tt>~s</tt></p>\n",
+ "<br />Used Erlang v~s in \"~s\"</p>\n"),
[TI#target_info.version, TI#target_info.root_dir]);
- true ->
+ true ->
case test_server_sup:framework_call(target_info, []) of
TargetInfo when is_list(TargetInfo),
length(TargetInfo) > 0 ->
- print(html, "<p>Target:<br>\n"),
- print(html, "~s\n", [TargetInfo]);
+ print(html, xhtml("\n<p><b>Target info:</b><br>\n",
+ "\n<p><b>Target info:</b><br />\n")),
+ print(html, "~s</p>\n", [TargetInfo]);
_ ->
ok
end
end,
-
+
print(html,
- "<p><a href=\"~s\">Full textual log</a>\n"
- "<br><a href=\"~s\">Coverage log</a>\n",
+ "<p><ul>\n"
+ "<li><a href=\"~s\">Full textual log</a></li>\n"
+ "<li><a href=\"~s\">Coverage log</a></li>\n</ul></p>\n",
[?suitelog_name,?coverlog_name]),
- print(html,"<p>~s"
- "<p>\n"
- "<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">"
- "<tr><th>Num</th><th>Module</th><th>Case</th><th>Log</th>"
- "<th>Time</th><th>Result</th><th>Comment</th></tr>\n",
- [print_if_known(N, {"Suite contains ~p test cases.\n",[N]},
+ print(html,
+ "<p>~s</p>\n" ++
+ xhtml("<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">",
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n"]) ++
+ "<tr><th>Num</th><th>Module</th><th>Group</th>" ++
+ "<th>Case</th><th>Log</th><th>Time</th><th>Result</th>" ++
+ "<th>Comment</th></tr>\n</thead>\n<tbody>\n",
+ [print_if_known(N, {"<i>Executing <b>~p</b> test cases...</i>" ++
+ xhtml("\n<br>\n", "\n<br />\n"),[N]},
{"",[]})]),
+
print(major, "=cases ~p", [get(test_server_cases)]),
print(major, "=user ~s", [TI#target_info.username]),
print(major, "=host ~s", [TI#target_info.host]),
@@ -1764,6 +1852,9 @@ do_test_cases(TopCases, SkipCases,
print(major, "=otp_release ~s", [TI#target_info.otp_release]),
print(major, "=started ~s",
[lists:flatten(timestamp_get(""))]),
+
+ put(test_server_html_footer, Footer),
+
run_test_cases(TestSpec, Config, TimetrapData)
end;
@@ -1773,13 +1864,13 @@ do_test_cases(TopCase, SkipCases, Config, TimetrapSpec) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% start_log_file() -> ok | exit({Error,Reason})
+%% start_log_file() -> {ok,TestDirName} | exit({Error,Reason})
%% Stem = string()
%%
%% Creates the log directories, the major log file and the html log file.
%% The log files are initialized with some header information.
%%
-%% The name of the log directory will be <Name>.LOGS/run.<Date>/ where
+%% The name of the log directory will be <Name>.logs/run.<Date>/ where
%% Name is the test suite name and Date is the current date and time.
start_log_file() ->
@@ -1793,18 +1884,27 @@ start_log_file() ->
exit({cant_create_log_dir,{MkDirError,Dir}})
end,
TestDir = timestamp_filename_get(filename:join(Dir, "run.")),
- case file:make_dir(TestDir) of
- ok ->
- ok;
- MkDirError2 ->
- exit({cant_create_log_dir,{MkDirError2,TestDir}})
- end,
-
- ok = file:write_file(filename:join(Dir, ?last_file), TestDir ++ "\n"),
- ok = file:write_file(?last_file, TestDir ++ "\n"),
-
- put(test_server_log_dir_base,TestDir),
- MajorName = filename:join(TestDir, ?suitelog_name),
+ TestDir1 =
+ case file:make_dir(TestDir) of
+ ok ->
+ TestDir;
+ {error,eexist} ->
+ timer:sleep(1000),
+ %% we need min 1 second between timestamps unfortunately
+ TestDirX = timestamp_filename_get(filename:join(Dir, "run.")),
+ case file:make_dir(TestDirX) of
+ ok ->
+ TestDirX;
+ MkDirError2 ->
+ exit({cant_create_log_dir,{MkDirError2,TestDirX}})
+ end;
+ MkDirError2 ->
+ exit({cant_create_log_dir,{MkDirError2,TestDir}})
+ end,
+ ok = file:write_file(filename:join(Dir, ?last_file), TestDir1 ++ "\n"),
+ ok = file:write_file(?last_file, TestDir1 ++ "\n"),
+ put(test_server_log_dir_base,TestDir1),
+ MajorName = filename:join(TestDir1, ?suitelog_name),
HtmlName = MajorName ++ ?html_ext,
{ok,Major} = file:open(MajorName, [write]),
{ok,Html} = file:open(HtmlName, [write]),
@@ -1817,14 +1917,14 @@ start_log_file() ->
make_html_link(LinkName ++ ?html_ext, HtmlName,
filename:basename(Dir)),
- PrivDir = filename:join(TestDir, ?priv_dir),
+ PrivDir = filename:join(TestDir1, ?priv_dir),
ok = file:make_dir(PrivDir),
put(test_server_priv_dir,PrivDir++"/"),
print_timestamp(13,"Suite started at "),
- LogInfo = [{topdir,Dir},{rundir,lists:flatten(TestDir)}],
+ LogInfo = [{topdir,Dir},{rundir,lists:flatten(TestDir1)}],
test_server_sup:framework_call(report, [loginfo,LogInfo]),
- ok.
+ {ok,TestDir1}.
make_html_link(LinkName, Target, Explanation) ->
%% if possible use a relative reference to Target.
@@ -1881,16 +1981,33 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) ->
{ok,Fd} = file:open(AbsName, [write]),
Lev = get(test_server_minor_level)+1000, %% far down in the minor levels
put(test_server_minor_fd, Fd),
- io:fwrite(Fd,
- "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
- "<html>\n"
- "<head><title>"++cast_to_list(Mod)++"</title>\n"
- "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n"
- "</head>\n"
- "<body bgcolor=\"white\" text=\"black\""
- " link=\"blue\" vlink=\"purple\" alink=\"red\">\n",
- []),
+
+ TestDescr = io_lib:format("Test ~p:~p result", [Mod,Func]),
+ {Header,Footer} =
+ case test_server_sup:framework_call(get_html_wrapper,
+ [TestDescr,false,
+ filename:dirname(AbsName),
+ undefined], "") of
+ Empty when (Empty == "") ; (element(2,Empty) == "") ->
+ put(basic_html, true),
+ {["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n",
+ "<html>\n",
+ "<head><title>", TestDescr, "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "</head>\n",
+ "<body bgcolor=\"white\" text=\"black\" ",
+ "link=\"blue\" vlink=\"purple\" alink=\"red\">\n"],
+ "\n</body>\n</html>\n"};
+ {basic_html,Html0,Html1} ->
+ put(basic_html, true),
+ {Html0,Html1};
+ {xhtml,Html0,Html1} ->
+ put(basic_html, false),
+ {Html0,Html1}
+ end,
+ put(test_server_minor_footer, Footer),
+ io:fwrite(Fd, Header, []),
SrcListing = downcase(cast_to_list(Mod)) ++ ?src_listing_ext,
case {filelib:is_file(filename:join(LogDir, SrcListing)),
@@ -1913,7 +2030,8 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) ->
stop_minor_log_file() ->
Fd = get(test_server_minor_fd),
- io:fwrite(Fd, "</pre>\n</body>\n</html>\n", []),
+ Footer = get(test_server_minor_footer),
+ io:fwrite(Fd, "</pre>\n" ++ Footer, []),
file:close(Fd),
put(test_server_minor_fd, undefined).
@@ -1992,12 +2110,29 @@ html_convert_modules([]) -> ok.
%% Convert source code to HTML if possible and needed.
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
+ {ok,DestInfo} when DestInfo#file_info.mtime >= SrcInfo#file_info.mtime ->
+ ok; % dest file up to date
+ _ ->
+ OutDir = get(test_server_log_dir_base),
+ Header =
+ case test_server_sup:framework_call(get_html_wrapper,
+ ["Module "++Src,false,
+ OutDir,undefined], "") of
+ Empty when (Empty == "") ; (element(2,Empty) == "") ->
+ ["<!DOCTYPE HTML PUBLIC",
+ "\"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<!-- autogenerated by 'erl2html2' -->\n",
+ "<html>\n",
+ "<head><title>Module ", Src, "</title>\n",
+ "<meta http-equiv=\"cache-control\" ",
+ "content=\"no-cache\">\n",
+ "</head>\n",
+ "<body bgcolor=\"white\" text=\"black\" ",
+ "link=\"blue\" vlink=\"purple\" alink=\"red\">\n"];
+ {_,Html,_} ->
+ Html
+ end,
+ erl2html2:convert(Src, Dest, Header)
end.
%% Copy all HTML files in InDir to OutDir.
@@ -2025,17 +2160,17 @@ add_init_and_end_per_suite([{make,_,_}=Case|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),
+ do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod),
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),
+ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod),
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),
+ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod),
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)];
@@ -2047,7 +2182,7 @@ add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod,
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),
+ do_add_init_and_end_per_suite(LastMod, LastRef, Suite, FwMod),
Case1 = {conf,Ref,proplists:delete(suite,Props),{FwMod,Func}},
PreCases ++ [Case1|add_init_and_end_per_suite(Cases, NextMod,
NextRef, FwMod)];
@@ -2057,19 +2192,19 @@ add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod,
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),
+ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod),
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),
+ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod),
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),
+ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod),
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)];
@@ -2077,10 +2212,23 @@ add_init_and_end_per_suite([], _LastMod, undefined, _FwMod) ->
[];
add_init_and_end_per_suite([], _LastMod, skipped_suite, _FwMod) ->
[];
-add_init_and_end_per_suite([], LastMod, LastRef, _FwMod) ->
- [{conf,LastRef,[],{LastMod,end_per_suite}}].
+add_init_and_end_per_suite([], LastMod, LastRef, FwMod) ->
+ %% we'll add end_per_suite here even if it's not exported
+ %% (and simply let the call fail if it's missing)
+ case erlang:function_exported(LastMod, end_per_suite, 1) of
+ true ->
+ [{conf,LastRef,[],{LastMod,end_per_suite}}];
+ false ->
+ %% let's call a "fake" end_per_suite if it exists
+ case erlang:function_exported(FwMod, end_per_suite, 1) of
+ true ->
+ [{conf,LastRef,[{suite,LastMod}],{FwMod,end_per_suite}}];
+ false ->
+ [{conf,LastRef,[],{LastMod,end_per_suite}}]
+ end
+ end.
-do_add_init_and_end_per_suite(LastMod, LastRef, Mod) ->
+do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod) ->
case code:is_loaded(Mod) of
false -> code:load_file(Mod);
_ -> ok
@@ -2091,7 +2239,16 @@ do_add_init_and_end_per_suite(LastMod, LastRef, Mod) ->
Ref = make_ref(),
{[{conf,Ref,[],{Mod,init_per_suite}}],Mod,Ref};
false ->
- {[],Mod,undefined}
+ %% let's call a "fake" init_per_suite if it exists
+ case erlang:function_exported(FwMod, init_per_suite, 1) of
+ true ->
+ Ref = make_ref(),
+ {[{conf,Ref,[{suite,Mod}],
+ {FwMod,init_per_suite}}],Mod,Ref};
+ false ->
+ {[],Mod,undefined}
+ end
+
end,
Cases =
if LastRef==undefined ->
@@ -2099,20 +2256,44 @@ do_add_init_and_end_per_suite(LastMod, LastRef, Mod) ->
LastRef==skipped_suite ->
Init;
true ->
- %% Adding end_per_suite here without checking if the
- %% function is actually exported. This is because a
- %% conf case must have an end case - so if it doesn't
- %% exist, it will only fail...
- [{conf,LastRef,[],{LastMod,end_per_suite}}|Init]
+ %% we'll add end_per_suite here even if it's not exported
+ %% (and simply let the call fail if it's missing)
+ case erlang:function_exported(LastMod, end_per_suite, 1) of
+ true ->
+ [{conf,LastRef,[],{LastMod,end_per_suite}}|Init];
+ false ->
+ %% let's call a "fake" end_per_suite if it exists
+ case erlang:function_exported(FwMod, end_per_suite, 1) of
+ true ->
+ [{conf,LastRef,[{suite,Mod}],
+ {FwMod,end_per_suite}}|Init];
+ false ->
+ [{conf,LastRef,[],{LastMod,end_per_suite}}|Init]
+ end
+ end
end,
{Cases,NextMod,NextRef}.
-do_add_end_per_suite_and_skip(LastMod, LastRef, Mod) ->
+do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod) ->
case LastRef of
No when No==undefined ; No==skipped_suite ->
{[],Mod,skipped_suite};
_Ref ->
- {[{conf,LastRef,[],{LastMod,end_per_suite}}],Mod,skipped_suite}
+ case erlang:function_exported(LastMod, end_per_suite, 1) of
+ true ->
+ {[{conf,LastRef,[],{LastMod,end_per_suite}}],
+ Mod,skipped_suite};
+ false ->
+ case erlang:function_exported(FwMod, end_per_suite, 1) of
+ true ->
+ %% let's call "fake" end_per_suite if it exists
+ {[{conf,LastRef,[],{FwMod,end_per_suite}}],
+ Mod,skipped_suite};
+ false ->
+ {[{conf,LastRef,[],{LastMod,end_per_suite}}],
+ Mod,skipped_suite}
+ end
+ end
end.
@@ -2658,23 +2839,42 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
"(configuration case ~w)", [What]);
(_) -> ok
end,
-
CfgProps = if StartConf ->
if Shuffle == undefined ->
[{tc_group_properties,Props}];
true ->
- [{tc_group_properties,[Shuffle|delete_shuffle(Props)]}]
+ [{tc_group_properties,
+ [Shuffle|delete_shuffle(Props)]}]
end;
not StartConf ->
{TcOk,TcSkip,TcFail} = get_tc_results(Status1),
[{tc_group_properties,get_props(Mode0)},
- {tc_group_result,[{ok,TcOk},{skipped,TcSkip},{failed,TcFail}]}]
+ {tc_group_result,[{ok,TcOk},
+ {skipped,TcSkip},
+ {failed,TcFail}]}]
end,
- ActualCfg =
- update_config(hd(Config), [{priv_dir,get(test_server_priv_dir)},
- {data_dir,get_data_dir(Mod)}] ++ CfgProps),
- CurrMode = curr_mode(Ref, Mode0, Mode),
+ SuiteName = proplists:get_value(suite, Props),
+ case get(test_server_create_priv_dir) of
+ auto_per_run -> % use common priv_dir
+ TSDirs = [{priv_dir,get(test_server_priv_dir)},
+ {data_dir,get_data_dir(Mod, SuiteName)}];
+ _ ->
+ TSDirs = [{data_dir,get_data_dir(Mod, SuiteName)}]
+ end,
+
+ ActualCfg =
+ if not StartConf ->
+ update_config(hd(Config), TSDirs ++ CfgProps);
+ true ->
+ GroupPath = lists:flatmap(fun({_Ref,[],_T}) -> [];
+ ({_Ref,GrProps,_T}) -> [GrProps]
+ end, Mode0),
+ update_config(hd(Config),
+ TSDirs ++ [{tc_group_path,GroupPath} | CfgProps])
+ end,
+
+ CurrMode = curr_mode(Ref, Mode0, Mode),
ConfCaseResult = run_test_case(Ref, 0, Mod, Func, [ActualCfg], skip_init, target,
TimetrapData, CurrMode),
@@ -2825,8 +3025,13 @@ run_test_cases_loop([{conf,_Ref,_Props,_X}=Conf|_Cases0],
run_test_cases_loop([{Mod,Case}|Cases], Config, TimetrapData, Mode, Status) ->
ActualCfg =
- update_config(hd(Config), [{priv_dir,get(test_server_priv_dir)},
- {data_dir,get_data_dir(Mod)}]),
+ case get(test_server_create_priv_dir) of
+ auto_per_run ->
+ update_config(hd(Config), [{priv_dir,get(test_server_priv_dir)},
+ {data_dir,get_data_dir(Mod)}]);
+ _ ->
+ update_config(hd(Config), [{data_dir,get_data_dir(Mod)}])
+ end,
run_test_cases_loop([{Mod,Case,[ActualCfg]}|Cases], Config,
TimetrapData, Mode, Status);
@@ -2991,13 +3196,20 @@ conf_start(Ref, Mode) ->
false -> 0
end.
+
get_data_dir(Mod) ->
- case code:which(Mod) of
+ get_data_dir(Mod, undefined).
+
+get_data_dir(Mod, Suite) ->
+ UseMod = if Suite == undefined -> Mod;
+ true -> Suite
+ end,
+ case code:which(UseMod) of
non_existing ->
print(12, "The module ~p is not loaded", [Mod]),
[];
FullPath ->
- filename:dirname(FullPath) ++ "/" ++ cast_to_list(Mod) ++
+ filename:dirname(FullPath) ++ "/" ++ cast_to_list(UseMod) ++
?data_dir_suffix
end.
@@ -3153,8 +3365,8 @@ skip_case(Type, Ref, CaseNum, Case, Comment, SendSync, Mode) ->
skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) ->
{{Col0,Col1},_} = get_font_style((CaseNum > 0), Mode),
- ResultCol = if Type == auto -> "#ffcc99";
- Type == user -> "#ff9933"
+ ResultCol = if Type == auto -> ?auto_skip_color;
+ Type == user -> ?user_skip_color
end,
Comment1 = reason_to_string(Comment),
@@ -3163,16 +3375,21 @@ skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) ->
print(major, "=started ~s", [lists:flatten(timestamp_get(""))]),
print(major, "=result skipped: ~s", [Comment1]),
print(2,"*** Skipping test case #~w ~p ***", [CaseNum,{Mod,Func}]),
+ TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]),
+ GroupName = case get_name(Mode) of
+ undefined -> "";
+ Name -> cast_to_list(Name)
+ end,
print(html,
- "<tr valign=top>"
- "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>"
+ TR ++ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>"
"<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>"
+ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>"
"<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>"
"<td>" ++ Col0 ++ "< >" ++ Col1 ++ "</td>"
"<td>" ++ Col0 ++ "0.000s" ++ Col1 ++ "</td>"
"<td><font color=\"~s\">SKIPPED</font></td>"
"<td>~s</td></tr>\n",
- [num2str(CaseNum),Mod,Func,ResultCol,Comment1]),
+ [num2str(CaseNum),fw_name(Mod),GroupName,Func,ResultCol,Comment1]),
if CaseNum > 0 ->
{US,AS} = get(test_server_skipped),
case Type of
@@ -3542,9 +3759,14 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where,
%% if this runs on a parallel test case process,
%% copy the dictionary from the main process
do_if_parallel(Main, fun() -> process_flag(trap_exit, true) end, ok),
- CopyDict = fun() -> lists:foreach(fun({Key,Val}) -> put(Key, Val) end, State) end,
+ CopyDict = fun() -> lists:foreach(fun({Key,Val}) ->
+ put(Key, Val)
+ end, State)
+ end,
do_if_parallel(Main, CopyDict, ok),
- do_if_parallel(Main, fun() -> put(test_server_common_io_handler, {tc,Main}) end, ok),
+ do_if_parallel(Main, fun() ->
+ put(test_server_common_io_handler, {tc,Main})
+ end, ok),
%% if io is being buffered, send start io session message
%% (no matter if case runs on parallel or main process)
case get(test_server_common_io_handler) of
@@ -3558,33 +3780,72 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where,
host ->
ok
end,
- test_server_sup:framework_call(report, [tc_start,{?pl2a(Mod),Func}]),
print(major, "=case ~p:~p", [Mod, Func]),
MinorName = start_minor_log_file(Mod, Func),
- print(minor, "<a name=top></a>", []),
+ print(minor, "<a name=\"top\"></a>", [], internal_raw),
MinorBase = filename:basename(MinorName),
print(major, "=logfile ~s", [filename:basename(MinorName)]),
+
+ UpdatedArgs =
+ %% maybe create unique private directory for test case or config func
+ case get(test_server_create_priv_dir) of
+ auto_per_run ->
+ update_config(hd(Args), [{tc_logfile,MinorName}]);
+ PrivDirMode ->
+ RunDir = filename:dirname(MinorName),
+ Ext =
+ if Num == 0 ->
+ {_,S,Us} = now(),
+ lists:flatten(io_lib:format(".~w.~w", [S,Us]));
+ true ->
+ %% create unique private directory for test case
+ RunDir = filename:dirname(MinorName),
+ lists:flatten(io_lib:format(".~w", [Num]))
+ end,
+ PrivDir = filename:join(RunDir, ?priv_dir) ++ Ext,
+ if PrivDirMode == auto_per_tc ->
+ ok = file:make_dir(PrivDir);
+ PrivDirMode == manual_per_tc ->
+ ok
+ end,
+ update_config(hd(Args), [{priv_dir,PrivDir++"/"},
+ {tc_logfile,MinorName}])
+ end,
+
+ test_server_sup:framework_call(report,
+ [tc_start,{{?pl2a(Mod),Func},MinorName}]),
+
print_props((RunInit==skip_init), get_props(Mode)),
+ GroupName = case get_name(Mode) of
+ undefined -> "";
+ Name -> cast_to_list(Name)
+ end,
print(major, "=started ~s", [lists:flatten(timestamp_get(""))]),
{{Col0,Col1},Style} = get_font_style((RunInit==run_init), Mode),
- print(html, "<tr valign=top><td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>"
- "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>"
- "<td><a href=\"~s\">~p</a></td>"
- "<td><a href=\"~s#top\"><</a> <a href=\"~s#end\">></a></td>",
- [num2str(Num),Mod,MinorBase,Func,MinorBase,MinorBase]),
+ TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]),
+ print(html, TR ++ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>"
+ "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>"
+ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>"
+ "<td><a href=\"~s\">~p</a></td>"
+ "<td><a href=\"~s#top\"><</a> <a href=\"~s#end\">></a></td>",
+ [num2str(Num),fw_name(Mod),GroupName,MinorBase,Func,
+ MinorBase,MinorBase]),
do_if_parallel(Main, ok, fun erlang:yield/0),
+
+ RejectIoReqs = get(test_server_reject_io_reqs),
%% run the test case
{Result,DetectedFail,ProcsBefore,ProcsAfter} =
- run_test_case_apply(Num, Mod, Func, Args, get_name(Mode),
- RunInit, Where, TimetrapData),
+ run_test_case_apply(Num, Mod, Func, [UpdatedArgs], get_name(Mode),
+ RunInit, Where, TimetrapData, RejectIoReqs),
{Time,RetVal,Loc,Opts,Comment} =
case Result of
Normal={_Time,_RetVal,_Loc,_Opts,_Comment} -> Normal;
{died,DReason,DLoc,DCmt} -> {died,DReason,DLoc,[],DCmt}
end,
- print(minor, "<a name=end></a>", []),
+ print(minor, "<a name=\"end\"></a>", [], internal_raw),
+ print(minor, "\n", [], internal_raw),
print_timestamp(minor, "Ended at "),
print(major, "=ended ~s", [lists:flatten(timestamp_get(""))]),
@@ -3838,9 +4099,10 @@ check_new_crash_dumps(Where) ->
progress(skip, CaseNum, Mod, Func, Loc, Reason, Time,
Comment, {St0,St1}) ->
- {Reason1,{Color,Ret}} = if_auto_skip(Reason,
- fun() -> {"#ffcc99",auto_skip} end,
- fun() -> {"#ff9933",skip} end),
+ {Reason1,{Color,Ret}} =
+ if_auto_skip(Reason,
+ fun() -> {?auto_skip_color,auto_skip} end,
+ fun() -> {?user_skip_color,skip} end),
print(major, "=result skipped", []),
print(1, "*** SKIPPED *** ~s",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
@@ -3857,7 +4119,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time,
end,
Comment1 = case Comment of
"" -> "";
- _ -> "<br>(" ++ to_string(Comment) ++ ")"
+ _ -> xhtml("<br>(","<br />(") ++ to_string(Comment) ++ ")"
end,
print(html,
"<td>" ++ St0 ++ "~.3fs" ++ St1 ++ "</td>"
@@ -3882,8 +4144,8 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T,
Comment =
case Comment0 of
"" -> "<font color=\"red\">" ++ ErrorReason ++ "</font>";
- _ -> "<font color=\"red\">" ++ ErrorReason ++ "</font><br>" ++
- to_string(Comment0)
+ _ -> "<font color=\"red\">" ++ ErrorReason ++
+ xhtml("</font><br>","</font><br />") ++ to_string(Comment0)
end,
print(html,
"<td>" ++ St0 ++ "~.3fs" ++ St1 ++ "</td>"
@@ -3908,8 +4170,8 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T,
Comment =
case Comment0 of
"" -> "<font color=\"red\">" ++ ErrorReason ++ "</font>";
- _ -> "<font color=\"red\">" ++ ErrorReason ++ "</font><br>" ++
- to_string(Comment0)
+ _ -> "<font color=\"red\">" ++ ErrorReason ++
+ xhtml("</font><br>","</font><br />") ++ to_string(Comment0)
end,
print(html,
"<td>" ++ St0 ++ "died" ++ St1 ++ "</td>"
@@ -3943,7 +4205,8 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time,
Comment =
case Comment0 of
"" -> "<font color=\"red\">" ++ ErrorReason2 ++ "</font>";
- _ -> "<font color=\"red\">" ++ ErrorReason2 ++ "</font><br>" ++
+ _ -> "<font color=\"red\">" ++ ErrorReason2 ++
+ xhtml("</font><br>","</font><br />") ++
to_string(Comment0)
end,
print(html,
@@ -3953,7 +4216,7 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time,
[TimeStr,Comment]),
print(minor, "=== location ~s", [unknown]),
{FStr,FormattedReason} = format_exception(Reason),
- print(minor, "=== reason = "++FStr, [FormattedReason]),
+ print(minor, "=== reason = " ++ FStr, [FormattedReason]),
failed;
progress(failed, CaseNum, Mod, Func, Loc, Reason, Time,
@@ -3969,7 +4232,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time,
Comment =
case Comment0 of
"" -> "";
- _ -> "<br>" ++ to_string(Comment0)
+ _ -> xhtml("<br>","<br />") ++ to_string(Comment0)
end,
FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)),
print(html,
@@ -3980,7 +4243,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time,
FormatLoc = test_server_sup:format_loc(Loc),
print(minor, "=== location ~s", [FormatLoc]),
{FStr,FormattedReason} = format_exception(Reason),
- print(minor, "=== reason = "++FStr, [FormattedReason]),
+ print(minor, "=== reason = " ++ FStr, [FormattedReason]),
failed;
progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
@@ -3999,7 +4262,7 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
_ ->
print(major, "=result ok", []),
case Comment0 of
- "" -> "";
+ "" -> "<td></td>";
_ -> "<td>" ++ to_string(Comment0) ++ "</td>"
end
end,
@@ -4015,6 +4278,46 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
%%--------------------------------------------------------------------
%% various help functions
+get_fw_mod(Mod) ->
+ case get(test_server_framework) of
+ undefined ->
+ case os:getenv("TEST_SERVER_FRAMEWORK") of
+ FW when FW =:= false; FW =:= "undefined" ->
+ Mod;
+ FW ->
+ list_to_atom(FW)
+ end;
+ '$none' -> Mod;
+ FW -> FW
+ end.
+
+fw_name(?MODULE) ->
+ test_server;
+fw_name(Mod) ->
+ case get(test_server_framework_name) of
+ undefined ->
+ case get_fw_mod(undefined) of
+ undefined ->
+ Mod;
+ Mod ->
+ case os:getenv("TEST_SERVER_FRAMEWORK_NAME") of
+ FWName when FWName =:= false; FWName =:= "undefined" ->
+ Mod;
+ FWName ->
+ list_to_atom(FWName)
+ end;
+ _ ->
+ Mod
+ end;
+ '$none' ->
+ Mod;
+ FWName ->
+ case get_fw_mod(Mod) of
+ Mod -> FWName;
+ _ -> Mod
+ end
+ end.
+
if_auto_skip(Reason={failed,{_,init_per_testcase,_}}, True, _False) ->
{Reason,True()};
if_auto_skip({_T,{skip,Reason={failed,{_,init_per_testcase,_}}},_Opts}, True, _False) ->
@@ -4118,8 +4421,8 @@ get_font_style1(default) ->
%% set to false.
format_exception(Reason={_Error,Stack}) when is_list(Stack) ->
- case os:getenv("TEST_SERVER_FRAMEWORK") of
- FW when FW =:= false; FW =:= "undefined" ->
+ case get_fw_mod(undefined) of
+ undefined ->
case application:get_env(test_server, format_exception) of
{ok,false} ->
{"~p",Reason};
@@ -4127,7 +4430,7 @@ format_exception(Reason={_Error,Stack}) when is_list(Stack) ->
do_format_exception(Reason)
end;
FW ->
- case application:get_env(list_to_atom(FW), format_exception) of
+ case application:get_env(FW, format_exception) of
{ok,false} ->
{"~p",Reason};
_ ->
@@ -4153,7 +4456,7 @@ do_format_exception(Reason={Error,Stack}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit,
-%% Where, TimetrapData) ->
+%% Where, TimetrapData, RejectIoReqs) ->
%% {{Time,RetVal,Loc,Opts,Comment},DetectedFail,ProcessesBefore,ProcessesAfter} |
%% {{died,Reason,unknown,Comment},DetectedFail,ProcessesBefore,ProcessesAfter}
%% Name = atom()
@@ -4172,19 +4475,21 @@ do_format_exception(Reason={Error,Stack}) ->
%% sent over socket to target, and test_server runs the case and sends the
%% result back over the socket. Else test_server runs the case directly on host.
-run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, host, TimetrapData) ->
+run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, host,
+ TimetrapData, RejectIoReqs) ->
test_server:run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,
- TimetrapData});
-run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, target, TimetrapData) ->
+ TimetrapData,RejectIoReqs});
+run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, target,
+ TimetrapData, RejectIoReqs) ->
case get(test_server_ctrl_job_sock) of
undefined ->
%% local target
test_server:run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,
- TimetrapData});
+ TimetrapData,RejectIoReqs});
JobSock ->
%% remote target
request(JobSock, {test_case,{CaseNum,Mod,Func,Args,Name,RunInit,
- TimetrapData}}),
+ TimetrapData,RejectIoReqs}}),
read_job_sock_loop(JobSock)
end.
@@ -4349,7 +4654,13 @@ output({html,Msg}, _Sender) ->
%% We are writing to a seekable file. Finalise so
%% we get complete valid (and viewable) HTML code.
%% Then rewind to overwrite the finalising code.
- io:put_chars(Fd, "\n</table>\n</body>\n</html>\n"),
+ io:put_chars(Fd, "\n</table>\n"),
+ case get(test_server_html_footer) of
+ undefined ->
+ io:put_chars(Fd, "</body>\n</html>\n");
+ Footer ->
+ io:put_chars(Fd, Footer)
+ end,
file:position(Fd, Pos);
{error, epipe} ->
%% The file is not seekable. We cannot erase what
@@ -4394,6 +4705,28 @@ output_to_fd(Fd, Msg, _Sender) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% xhtml(BasicHtml, XHtml) -> BasicHtml | XHtml
+%%
+xhtml(HTML, XHTML) ->
+ case get(basic_html) of
+ true -> HTML;
+ _ -> XHTML
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% odd_or_even() -> "odd" | "even"
+%%
+odd_or_even() ->
+ case get(odd_or_even) of
+ even ->
+ put(odd_or_even, odd),
+ "even";
+ _ ->
+ put(odd_or_even, even),
+ "odd"
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timestamp_filename_get(Leader) -> string()
%% Leader = string()
%%
@@ -4695,8 +5028,8 @@ collect_case([Case | Cases], St, Acc) ->
collect_case(Cases, NewSt, Acc ++ FlatCases).
collect_case_invoke(Mod, Case, MFA, St) ->
- case os:getenv("TEST_SERVER_FRAMEWORK") of
- FW when FW =:= false; FW =:= "undefined" ->
+ case get_fw_mod(undefined) of
+ undefined ->
case catch apply(Mod, Case, [suite]) of
{'EXIT',_} ->
{ok,[MFA],St};
@@ -4704,7 +5037,9 @@ 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.
@@ -4858,7 +5193,9 @@ init_props(Props) ->
end.
keep_name(Props) ->
- lists:filter(fun({name,_}) -> true; (_) -> false end, Props).
+ lists:filter(fun({name,_}) -> true;
+ ({suite,_}) -> true;
+ (_) -> false end, Props).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Target node handling functions %%
@@ -5499,9 +5836,10 @@ write_default_cross_coverlog(TestDir) ->
file:open(filename:join(TestDir,?cross_coverlog_name), [write]),
write_coverlog_header(CrossCoverLog),
io:fwrite(CrossCoverLog,
- "No cross cover modules exist for this application,<br>"
- "or cross cover analysis is not completed.\n"
- "</body></html>\n", []),
+ ["No cross cover modules exist for this application,",
+ xhtml("<br>","<br />"),
+ "or cross cover analysis is not completed.\n"
+ "</body></html>\n"], []),
file:close(CrossCoverLog).
write_cover_result_table(CoverLog,Coverage) ->
diff --git a/lib/test_server/src/test_server_h.erl b/lib/test_server/src/test_server_h.erl
index e423863b99..fdeee59326 100644
--- a/lib/test_server/src/test_server_h.erl
+++ b/lib/test_server/src/test_server_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The 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,10 +79,21 @@ set_group_leader() ->
handle_event({_Type, GL, _Msg}, State) when node(GL)/=node() ->
{ok, State};
handle_event({Tag, _GL, {_Pid, Type, _Report}} = Event, State) ->
- case report(Tag, Type) of
- sasl ->
- tag(State#state.testcase),
- sasl_report_tty_h:handle_event(Event, State#state.sasl);
+ SASL = lists:keyfind(sasl, 1, application:which_applications()),
+ case report_receiver(Tag, Type) of
+ sasl when SASL /= false ->
+ {ok,ErrLogType} = application:get_env(sasl, errlog_type),
+ SReport = sasl_report:format_report(group_leader(), ErrLogType,
+ tag_event(Event)),
+ if is_list(SReport) ->
+ tag(State#state.testcase),
+ sasl_report_tty_h:handle_event(Event,
+ State#state.sasl);
+ true -> %% Report is an atom if no logging is to be done
+ ignore
+ end;
+ sasl -> %% SASL not running
+ ignore;
kernel ->
tag(State#state.testcase),
error_logger_tty_h:handle_event(Event, State#state.kernel);
@@ -111,19 +122,22 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-report(error_report, supervisor_report) -> sasl;
-report(error_report, crash_report) -> sasl;
-report(info_report, progress) -> sasl;
-report(error, _) -> kernel;
-report(error_report, _) -> kernel;
-report(warning_msg, _) -> kernel;
-report(warning_report, _) -> kernel;
-report(info, _) -> kernel;
-report(info_msg, _) -> kernel;
-report(info_report, _) -> kernel;
-report(_, _) -> none.
+report_receiver(error_report, supervisor_report) -> sasl;
+report_receiver(error_report, crash_report) -> sasl;
+report_receiver(info_report, progress) -> sasl;
+report_receiver(error, _) -> kernel;
+report_receiver(error_report, _) -> kernel;
+report_receiver(warning_msg, _) -> kernel;
+report_receiver(warning_report, _) -> kernel;
+report_receiver(info, _) -> kernel;
+report_receiver(info_msg, _) -> kernel;
+report_receiver(info_report, _) -> kernel;
+report_receiver(_, _) -> none.
tag({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->
io:format(user, "~n=TESTCASE: ~p:~p/~p", [M,F,A]);
tag(Testcase) ->
io:format(user, "~n=TESTCASE: ~p", [Testcase]).
+
+tag_event(Event) ->
+ {calendar:local_time(), Event}.
diff --git a/lib/test_server/src/test_server_node.erl b/lib/test_server/src/test_server_node.erl
index 1fd40d1dd9..6358efa764 100644
--- a/lib/test_server/src/test_server_node.erl
+++ b/lib/test_server/src/test_server_node.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -407,7 +407,7 @@ start_node_peer(SlaveName, OptList, From, TI) ->
% Support for erl_crash_dump files..
CrashFile = filename:join([TI#target_info.test_server_dir,
"erl_crash_dump."++cast_to_list(SlaveName)]),
- CrashArgs = lists:concat([" -env ERL_CRASH_DUMP ",CrashFile," "]),
+ CrashArgs = lists:concat([" -env ERL_CRASH_DUMP \"",CrashFile,"\" "]),
FailOnError = start_node_get_option_value(fail_on_error, OptList, true),
Pa = TI#target_info.test_server_dir,
Prog0 = start_node_get_option_value(erl, OptList, default),
@@ -420,7 +420,7 @@ start_node_peer(SlaveName, OptList, From, TI) ->
Cmd = lists:concat([Prog,
" -detached ",
TI#target_info.naming, " ", SlaveName,
- " -pa ", Pa,
+ " -pa \"", Pa,"\"",
NodeStarted,
CrashArgs,
" ", Args]),
@@ -472,9 +472,9 @@ start_node_slave(SlaveName, OptList, From, TI) ->
CrashFile = filename:join([TI#target_info.test_server_dir,
"erl_crash_dump."++cast_to_list(SlaveName)]),
- CrashArgs = lists:concat([" -env ERL_CRASH_DUMP ",CrashFile," "]),
+ CrashArgs = lists:concat([" -env ERL_CRASH_DUMP \"",CrashFile,"\" "]),
Pa = TI#target_info.test_server_dir,
- Args = lists:concat([" -pa ", Pa, " ", SuppliedArgs, CrashArgs]),
+ Args = lists:concat([" -pa \"", Pa, "\" ", SuppliedArgs, CrashArgs]),
Prog0 = start_node_get_option_value(erl, OptList, default),
Prog = pick_erl_program(Prog0),
@@ -943,12 +943,23 @@ find_rel_suse_1(Rel, RootWc) ->
end.
find_rel_suse_2(Rel, RootWc) ->
- Wc = RootWc ++ "_" ++ Rel,
- case filelib:wildcard(Wc) of
- [] ->
- [];
- [R|_] ->
- [filename:join([R,"bin","erl"])]
+ RelDir = filename:dirname(RootWc),
+ Pat = filename:basename(RootWc ++ "_" ++ Rel) ++ ".*",
+ case file:list_dir(RelDir) of
+ {ok,Dirs} ->
+ case lists:filter(fun(Dir) ->
+ case re:run(Dir, Pat) of
+ nomatch -> false;
+ _ -> true
+ end
+ end, Dirs) of
+ [] ->
+ [];
+ [R|_] ->
+ [filename:join([RelDir,R,"bin","erl"])]
+ end;
+ _ ->
+ []
end.
%% suse_release() -> VersionString | none.
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index 875f45eea6..9d111ff769 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,8 @@
%%% Purpose: Test server support functions.
%%%-------------------------------------------------------------------
-module(test_server_sup).
--export([timetrap/2, timetrap/3, timetrap_cancel/1, capture_get/1, messages_get/1,
+-export([timetrap/2, timetrap/3, timetrap/4,
+ timetrap_cancel/1, capture_get/1, messages_get/1,
timecall/3, call_crash/5, app_test/2, check_new_crash_dumps/0,
cleanup_crash_dumps/0, crash_dump_dir/0, tar_crash_dumps/0,
get_username/0, get_os_family/0,
@@ -44,9 +45,12 @@
%% delays during the test (e.g. if cover is running).
timetrap(Timeout0, Pid) ->
- timetrap(Timeout0, true, Pid).
+ timetrap(Timeout0, Timeout0, true, Pid).
timetrap(Timeout0, Scale, Pid) ->
+ timetrap(Timeout0, Timeout0, Scale, Pid).
+
+timetrap(Timeout0, ReportTVal, Scale, Pid) ->
process_flag(priority, max),
Timeout = if not Scale -> Timeout0;
true -> test_server:timetrap_scale_factor() * Timeout0
@@ -54,28 +58,36 @@ timetrap(Timeout0, Scale, Pid) ->
TruncTO = trunc(Timeout),
receive
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,TruncTO,MFLs};
- InitOrEnd ->
- {timetrap_timeout,TruncTO,MFLs,InitOrEnd}
- end,
- exit(Pid, Trap),
- receive
- {'DOWN', Mon, process, Pid, _} ->
+ case is_process_alive(Pid) of
+ true ->
+ TimeToReport = if Timeout0 == ReportTVal -> TruncTO;
+ true -> ReportTVal end,
+ MFLs = test_server:get_loc(Pid),
+ Mon = erlang:monitor(process, Pid),
+ Trap =
+ case get(test_server_init_or_end_conf) of
+ undefined ->
+ {timetrap_timeout,TimeToReport,MFLs};
+ InitOrEnd ->
+ {timetrap_timeout,TimeToReport,MFLs,InitOrEnd}
+ end,
+ exit(Pid, Trap),
+ receive
+ {'DOWN', Mon, process, Pid, _} ->
+ ok
+ after 10000 ->
+ %% Pid is probably trapping exits, hit it harder...
+ catch error_logger:warning_msg(
+ "Testcase process ~p not "
+ "responding to timetrap "
+ "timeout:~n"
+ " ~p.~n"
+ "Killing testcase...~n",
+ [Pid, Trap]),
+ exit(Pid, kill)
+ end;
+ false ->
ok
- after 10000 ->
- %% Pid is probably trapping exits, hit it harder...
- catch error_logger:warning_msg("Testcase process ~p not "
- "responding to timetrap "
- "timeout:~n"
- " ~p.~n"
- "Killing testcase...~n",
- [Pid, Trap]),
- exit(Pid, kill)
end
end.
@@ -88,8 +100,12 @@ timetrap_cancel(Handle) ->
unlink(Handle),
MonRef = erlang:monitor(process, Handle),
exit(Handle, kill),
- receive {'DOWN',MonRef,_,_,_} -> ok after 2000 -> ok end.
-
+ receive {'DOWN',MonRef,_,_,_} -> ok
+ after
+ 2000 ->
+ erlang:demonitor(MonRef, [flush]),
+ ok
+ end.
capture_get(Msgs) ->
receive
@@ -99,7 +115,6 @@ capture_get(Msgs) ->
lists:reverse(Msgs)
end.
-
messages_get(Msgs) ->
receive
Msg ->
@@ -108,7 +123,6 @@ messages_get(Msgs) ->
lists:reverse(Msgs)
end.
-
timecall(M, F, A) ->
Befor = erlang:now(),
Val = apply(M, F, A),
diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl
index 729a2b11fc..4899f38d2b 100644
--- a/lib/test_server/src/ts.erl
+++ b/lib/test_server/src/ts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,10 @@
-export([run/0, run/1, run/2, run/3, run/4,
clean/0, clean/1,
tests/0, tests/1,
- install/0, install/1, install/2, index/0,
+ install/0, install/1, index/0,
estone/0, estone/1,
cross_cover_analyse/1,
+ compile_testcases/0, compile_testcases/1,
help/0]).
-export([i/0, l/1, r/0, r/1, r/2, r/3]).
@@ -88,35 +89,25 @@
-define(
install_help,
[
- " ts:install() - Install TS for local target with no Options.\n"
- " ts:install([Options])\n",
- " - Install TS for local target with Options\n"
- " ts:install({Architecture, Target_name})\n",
- " - Install TS for a remote target architecture.\n",
- " and target network name (e.g. {vxworks_cpu32, sauron}).\n",
- " ts:install({Architecture, Target_name}, [Options])\n",
- " - Install TS as above, and with Options.\n",
+ " ts:install() - Install TS with no Options.\n"
+ " ts:install([Options]) - Install TS with Options\n"
"\n",
"Installation options supported:\n",
" {longnames, true} - Use fully qualified hostnames\n",
- " {hosts, [HostList]}\n"
- " - Use theese hosts for distributed testing.\n"
" {verbose, Level} - Sets verbosity level for TS output (0,1,2), 0 is\n"
" quiet(default).\n"
- " {slavetargets, SlaveTarges}\n"
- " - Available hosts for starting slave nodes for\n"
- " platforms which cannot have more than one erlang\n"
- " node per host.\n"
- " {crossroot, TargetErlRoot}\n"
- " - Erlang root directory on target host\n"
- " Mandatory for remote targets\n"
- " {master, {MasterHost, MasterCookie}}\n"
- " - Master host and cookie for targets which are\n"
- " started as slave nodes.\n"
- " erl_boot_server must be started on master before\n"
- " test is run.\n"
- " Optional, default is controller host and then\n"
- " erl_boot_server is started autmatically\n"
+ " {crossroot, ErlTop}\n"
+ " - Erlang root directory on build host, ~n"
+ " normally same value as $ERL_TOP\n"
+ " {crossenv, [{Key,Val}]}\n"
+ " - Environmentals used by test configure on build host\n"
+ " {crossflags, FlagsString}\n"
+ " - Flags used by test configure on build host\n"
+ " {xcomp, XCompFile}\n"
+ " - The xcomp file to use for cross compiling the~n"
+ " testcases. Using this option will override any~n"
+ " cross* configurations given to ts. Note that you~n"
+ " have to have a correct ERL_TOP as well.~n"
]).
help() ->
@@ -183,26 +174,24 @@ help(installed) ->
" cover_details. Analyses modules specified in\n"
" cross.cover.\n"
" Level can be 'overview' or 'details'.\n",
+ " ts:compile_testcases()~n"
+ " ts:compile_testcases(Apps)~n"
+ " - Compile all testcases for usage in a cross ~n"
+ " compile environment."
" \n"
"Installation (already done):\n"
],
show_help([H,?install_help]).
show_help(H) ->
- io:put_chars(lists:flatten(H)).
+ io:format(lists:flatten(H)).
%% Installs tests.
install() ->
ts_install:install(install_local,[]).
-install({Architecture, Target_name}) ->
- ts_install:install({ts_lib:maybe_atom_to_list(Architecture),
- ts_lib:maybe_atom_to_list(Target_name)}, []);
install(Options) when is_list(Options) ->
ts_install:install(install_local,Options).
-install({Architecture, Target_name}, Options) when is_list(Options)->
- ts_install:install({ts_lib:maybe_atom_to_list(Architecture),
- ts_lib:maybe_atom_to_list(Target_name)}, Options).
%% Updates the local index page.
@@ -301,7 +290,15 @@ run(List, Opts) when is_list(List), is_list(Opts) ->
run(Testspec, Config) when is_atom(Testspec), is_list(Config) ->
Options=check_test_get_opts(Testspec, Config),
File=atom_to_list(Testspec),
- run_test(File, [{spec,[File++".spec"]}], Options);
+ Spec = case code:lib_dir(Testspec) of
+ {error, bad_name} when Testspec /= emulator,
+ Testspec /= system,
+ Testspec /= epmd ->
+ create_skip_spec(Testspec, tests(Testspec));
+ _ ->
+ File++".spec"
+ end,
+ run_test(File, [{spec,[Spec]}], Options);
%% Runs one module in a spec (interactive)
run(Testspec, Mod) when is_atom(Testspec), is_atom(Mod) ->
run_test({atom_to_list(Testspec), Mod},
@@ -332,6 +329,21 @@ run(Testspec, Mod, Case, Config) when is_atom(Testspec),
Args = [{suite,atom_to_list(Mod)}, {testcase,atom_to_list(Case)}],
run_test(atom_to_list(Testspec), Args, Options).
+%% Create a spec to skip all SUITES, this is used when the application
+%% to be tested is not part of the OTP release to be tested.
+create_skip_spec(Testspec, SuitesToSkip) ->
+ {ok,Cwd} = file:get_cwd(),
+ TestspecString = atom_to_list(Testspec),
+ Specname = TestspecString++"_skip.spec",
+ {ok,D} = file:open(filename:join([filename:dirname(Cwd),
+ TestspecString++"_test",Specname]),
+ [write]),
+ TestDir = "\"../"++TestspecString++"_test\"",
+ io:format(D,"{suites, "++TestDir++", all}.~n",[]),
+ io:format(D,"{skip_suites, "++TestDir++", ~w, \"Skipped as application"
+ " is not in path!\"}.",[SuitesToSkip]),
+ Specname.
+
%% Check testspec to be valid and get possible Options
%% from the config.
check_test_get_opts(Testspec, Config) ->
@@ -705,3 +717,23 @@ cover_type(cover_details) -> details.
do_load(Mod) ->
code:purge(Mod),
code:load_file(Mod).
+
+
+compile_testcases() ->
+ compile_datadirs("../*/*_data").
+
+compile_testcases(App) when is_atom(App) ->
+ compile_testcases([App]);
+compile_testcases([App | T]) ->
+ compile_datadirs(io_lib:format("../~s_test/*_data", [App])),
+ compile_testcases(T);
+compile_testcases([]) ->
+ ok.
+
+compile_datadirs(DataDirs) ->
+ {ok,Variables} = file:consult("variables"),
+
+ lists:foreach(fun(Dir) ->
+ ts_lib:make_non_erlang(Dir, Variables)
+ end,
+ filelib:wildcard(DataDirs)).
diff --git a/lib/test_server/src/ts.hrl b/lib/test_server/src/ts.hrl
index 885a726c54..db804d23a1 100644
--- a/lib/test_server/src/ts.hrl
+++ b/lib/test_server/src/ts.hrl
@@ -28,6 +28,7 @@
-define(run_summary, "suite.summary").
-define(cover_total,"total_cover.log").
-define(variables, "variables").
+-define(cross_variables, "variables-cross").
-define(LF, [10]). % Newline in VxWorks script
-define(CHAR_PER_LINE, 60). % Characters per VxWorks script building line
-define(CROSS_COOKIE, "cross"). % cookie used when cross platform testing
diff --git a/lib/test_server/src/ts_autoconf_win32.erl b/lib/test_server/src/ts_autoconf_win32.erl
index 9103542fd2..258040b39e 100644
--- a/lib/test_server/src/ts_autoconf_win32.erl
+++ b/lib/test_server/src/ts_autoconf_win32.erl
@@ -67,6 +67,7 @@ system_type(Vars) ->
{5,1,_} -> "Windows XP";
{5,2,_} -> "Windows 2003";
{6,0,_} -> "Windows Vista";
+ {6,1,_} -> "Windows 7";
{_,_,_} -> "Windows NCC-1701-D"
end;
{win32, windows} ->
diff --git a/lib/test_server/src/ts_erl_config.erl b/lib/test_server/src/ts_erl_config.erl
index 3b41f90d55..45d88016a4 100644
--- a/lib/test_server/src/ts_erl_config.erl
+++ b/lib/test_server/src/ts_erl_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
@@ -128,15 +128,15 @@ erts_lib(Vars,OsType) ->
ErtsLibInternal}
end,
[{erts_lib_include,
- filename:nativename(ErtsLibInclude)},
+ quote(filename:nativename(ErtsLibInclude))},
{erts_lib_include_generated,
- filename:nativename(ErtsLibIncludeGenerated)},
+ quote(filename:nativename(ErtsLibIncludeGenerated))},
{erts_lib_include_internal,
- filename:nativename(ErtsLibIncludeInternal)},
+ quote(filename:nativename(ErtsLibIncludeInternal))},
{erts_lib_include_internal_generated,
- filename:nativename(ErtsLibIncludeInternalGenerated)},
- {erts_lib_path, filename:nativename(ErtsLibPath)},
- {erts_lib_internal_path, filename:nativename(ErtsLibInternalPath)},
+ quote(filename:nativename(ErtsLibIncludeInternalGenerated))},
+ {erts_lib_path, quote(filename:nativename(ErtsLibPath))},
+ {erts_lib_internal_path, quote(filename:nativename(ErtsLibInternalPath))},
{erts_lib_multi_threaded, erts_lib_name(multi_threaded, OsType)},
{erts_lib_single_threaded, erts_lib_name(single_threaded, OsType)}
| Vars].
@@ -145,13 +145,13 @@ erl_include(Vars) ->
Include =
case erl_root(Vars) of
{installed, Root} ->
- filename:join([Root, "usr", "include"]);
+ quote(filename:join([Root, "usr", "include"]));
{srctree, Root, Target} ->
- filename:join([Root, "erts", "emulator", "beam"])
- ++ " -I" ++ filename:join([Root, "erts", "emulator"])
+ quote(filename:join([Root, "erts", "emulator", "beam"]))
+ ++ " -I" ++ quote(filename:join([Root, "erts", "emulator"]))
++ system_include(Root, Vars)
- ++ " -I" ++ filename:join([Root, "erts", "include"])
- ++ " -I" ++ filename:join([Root, "erts", "include", Target])
+ ++ " -I" ++ quote(filename:join([Root, "erts", "include"]))
+ ++ " -I" ++ quote(filename:join([Root, "erts", "include", Target]))
end,
[{erl_include, filename:nativename(Include)}|Vars].
@@ -163,7 +163,7 @@ system_include(Root, Vars) ->
"VxWorks" -> "sys.vxworks";
_ -> "sys/unix"
end,
- " -I" ++ filename:nativename(filename:join([Root, "erts", "emulator", SysDir])).
+ " -I" ++ quote(filename:nativename(filename:join([Root, "erts", "emulator", SysDir]))).
erl_interface(Vars,OsType) ->
{Incl, {LibPath, MkIncl}} =
@@ -220,20 +220,16 @@ erl_interface(Vars,OsType) ->
_ ->
"" % VxWorks
end,
- CrossCompile = case OsType of
- vxworks -> "true";
- _ -> "false"
- end,
- [{erl_interface_libpath, filename:nativename(LibPath)},
+ [{erl_interface_libpath, quote(filename:nativename(LibPath))},
{erl_interface_sock_libs, sock_libraries(OsType)},
{erl_interface_lib, Lib},
{erl_interface_eilib, Lib1},
{erl_interface_lib_drv, LibDrv},
{erl_interface_eilib_drv, Lib1Drv},
{erl_interface_threadlib, ThreadLib},
- {erl_interface_include, filename:nativename(Incl)},
- {erl_interface_mk_include, filename:nativename(MkIncl)},
- {erl_interface_cross_compile, CrossCompile} | Vars].
+ {erl_interface_include, quote(filename:nativename(Incl))},
+ {erl_interface_mk_include, quote(filename:nativename(MkIncl))}
+ | Vars].
ic(Vars, OsType) ->
{ClassPath, LibPath, Incl} =
@@ -250,10 +246,10 @@ ic(Vars, OsType) ->
end,
filename:join(Dir, "include")}
end,
- [{ic_classpath, filename:nativename(ClassPath)},
- {ic_libpath, filename:nativename(LibPath)},
+ [{ic_classpath, quote(filename:nativename(ClassPath))},
+ {ic_libpath, quote(filename:nativename(LibPath))},
{ic_lib, link_library("ic", OsType)},
- {ic_include_path, filename:nativename(Incl)}|Vars].
+ {ic_include_path, quote(filename:nativename(Incl))}|Vars].
jinterface(Vars, _OsType) ->
ClassPath =
@@ -263,7 +259,7 @@ jinterface(Vars, _OsType) ->
Dir ->
filename:join([Dir, "priv", "OtpErlang.jar"])
end,
- [{jinterface_classpath, filename:nativename(ClassPath)}|Vars].
+ [{jinterface_classpath, quote(filename:nativename(ClassPath))}|Vars].
lib_dir(Vars, Lib) ->
LibLibDir = case Lib of
@@ -276,8 +272,6 @@ lib_dir(Vars, Lib) ->
case {get_var(crossroot, Vars), LibLibDir} of
{{error, _}, _} -> %no crossroot
LibLibDir;
- {_, {error, _}} -> %no lib
- LibLibDir;
{CrossRoot, _} ->
%% XXX: Ugly. So ugly I won't comment it
%% /Patrik
@@ -299,18 +293,16 @@ lib_dir(Vars, Lib) ->
end.
erl_root(Vars) ->
- Root = code:root_dir(),
- case ts_lib:erlang_type() of
+ Root = case get_var(crossroot,Vars) of
+ {error, notfound} -> code:root_dir();
+ CrossRoot -> CrossRoot
+ end,
+ case ts_lib:erlang_type(Root) of
{srctree, _Version} ->
Target = get_var(target, Vars),
{srctree, Root, Target};
{_, _Version} ->
- case get_var(crossroot,Vars) of
- {error, notfound} ->
- {installed, Root};
- CrossRoot ->
- {installed, CrossRoot}
- end
+ {installed, Root}
end.
@@ -362,10 +354,17 @@ ssl(Vars, _OsType) ->
{error, bad_name} ->
throw({cannot_find_app, ssl});
Dir ->
- [{ssl_libdir, filename:nativename(Dir)}| Vars]
+ [{ssl_libdir, quote(filename:nativename(Dir))}| Vars]
end.
separators(Vars, {win32,_}) ->
[{'DS',"\\"},{'PS',";"}|Vars];
separators(Vars, _) ->
[{'DS',"/"},{'PS',":"}|Vars].
+
+quote([$ |R]) ->
+ "\\ "++quote(R);
+quote([C|R]) ->
+ [C|quote(R)];
+quote([]) ->
+ [].
diff --git a/lib/test_server/src/ts_install.erl b/lib/test_server/src/ts_install.erl
index 9703478f20..99ccfbc9bc 100644
--- a/lib/test_server/src/ts_install.erl
+++ b/lib/test_server/src/ts_install.erl
@@ -28,12 +28,25 @@ install(install_local, Options) ->
install(os:type(), Options);
install(TargetSystem, Options) ->
- io:format("Running configure for cross architecture, network target name~n"
- "~p~n", [TargetSystem]),
- case autoconf(TargetSystem) of
+ case file:consult(?variables) of
+ {ok, Vars} ->
+ case proplists:get_value(cross,Vars) of
+ "yes" when Options == []->
+ target_install(Vars);
+ _ ->
+ build_install(TargetSystem, Options)
+ end;
+ _ ->
+ build_install(TargetSystem, Options)
+ end.
+
+
+build_install(TargetSystem, Options) ->
+ XComp = parse_xcomp_file(proplists:get_value(xcomp,Options)),
+ case autoconf(TargetSystem, XComp++Options) of
{ok, Vars0} ->
OsType = os_type(TargetSystem),
- Vars1 = ts_erl_config:variables(merge(Vars0,Options),OsType),
+ Vars1 = ts_erl_config:variables(Vars0++XComp++Options,OsType),
{Options1, Vars2} = add_vars(Vars1, Options),
Vars3 = lists:flatten([Options1|Vars2]),
write_terms(?variables, Vars3);
@@ -45,32 +58,43 @@ os_type({unix,_}=OsType) -> OsType;
os_type({win32,_}=OsType) -> OsType;
os_type(_Other) -> vxworks.
-merge(Vars,[]) ->
- Vars;
-merge(Vars,[{crossroot,X}| Tail]) ->
- merge([{crossroot, X} | Vars], Tail);
-merge(Vars,[_X | Tail]) ->
- merge(Vars,Tail).
+target_install(CrossVars) ->
+ io:format("Cross installation detected, skipping configure and data_dir make~n"),
+ case file:rename(?variables,?cross_variables) of
+ ok ->
+ ok;
+ _ ->
+ io:format("Could not find variables file from cross make~n"),
+ throw(cross_installation_failed)
+ end,
+ CPU = proplists:get_value('CPU',CrossVars),
+ OS = proplists:get_value(os,CrossVars),
+ {Options,Vars} = add_vars([{cross,"yes"},{'CPU',CPU},{os,OS}],[]),
+ Variables = lists:flatten([Options|Vars]),
+ write_terms(?variables, Variables).
%% Autoconf for various platforms.
%% unix uses the configure script
%% win32 uses ts_autoconf_win32
%% VxWorks uses ts_autoconf_vxworks.
-autoconf(TargetSystem) ->
- case autoconf1(TargetSystem) of
+autoconf(TargetSystem, XComp) ->
+ case autoconf1(TargetSystem, XComp) of
ok ->
autoconf2(file:read_file("conf_vars"));
Error ->
Error
end.
-autoconf1({win32, _}) ->
+autoconf1({win32, _},[{cross,"no"}]) ->
ts_autoconf_win32:configure();
-autoconf1({unix, _}) ->
- unix_autoconf();
-autoconf1(Other) ->
- ts_autoconf_vxworks:configure(Other).
+autoconf1({unix, _},XCompFile) ->
+ unix_autoconf(XCompFile);
+autoconf1(Other,[{cross,"no"}]) ->
+ ts_autoconf_vxworks:configure(Other);
+autoconf1(_,_) ->
+ io:format("cross compilation not supported for that this platform~n"),
+ throw(cross_installation_failed).
autoconf2({ok, Bin}) ->
get_vars(binary_to_list(Bin), name, [], []);
@@ -92,27 +116,40 @@ get_vars([], name, [], Result) ->
get_vars(_, _, _, _) ->
{error, fatal_bad_conf_vars}.
-unix_autoconf() ->
+unix_autoconf(XConf) ->
Configure = filename:absname("configure"),
- Args = case catch erlang:system_info(threads) of
- false -> "";
- _ -> " --enable-shlib-thread-safety"
- end
- ++ case catch string:str(erlang:system_info(system_version),
- "debug") > 0 of
- false -> "";
- _ -> " --enable-debug-mode"
- end,
+ Flags = proplists:get_value(crossflags,XConf,[]),
+ Env = proplists:get_value(crossenv,XConf,[]),
+ Host = get_xcomp_flag("host", Flags),
+ Build = get_xcomp_flag("build", Flags),
+ Threads = [" --enable-shlib-thread-safety" ||
+ erlang:system_info(threads) /= false],
+ Debug = [" --enable-debug-mode" ||
+ string:str(erlang:system_info(system_version),"debug") > 0],
+ Args = Host ++ Build ++ Threads ++ Debug,
case filelib:is_file(Configure) of
true ->
- Env = macosx_cflags(),
- Port = open_port({spawn, Configure ++ Args},
- [stream, eof, {env,Env}]),
+ OSXEnv = macosx_cflags(),
+ io:format("Running ~sEnv: ~p~n",
+ [lists:flatten(Configure ++ Args),Env++OSXEnv]),
+ Port = open_port({spawn, lists:flatten(["\"",Configure,"\"",Args])},
+ [stream, eof, {env,Env++OSXEnv}]),
ts_lib:print_data(Port);
false ->
{error, no_configure_script}
end.
+
+get_xcomp_flag(Flag, Flags) ->
+ get_xcomp_flag(Flag, Flag, Flags).
+get_xcomp_flag(Flag, Tag, Flags) ->
+ case proplists:get_value(Flag,Flags) of
+ undefined -> "";
+ "guess" -> [" --",Tag,"=",os:cmd("$ERL_TOP/erts/autoconf/config.guess")];
+ HostVal -> [" --",Tag,"=",HostVal]
+ end.
+
+
macosx_cflags() ->
case os:type() of
{unix, darwin} ->
@@ -125,10 +162,33 @@ macosx_cflags() ->
[]
end.
+parse_xcomp_file(undefined) ->
+ [{cross,"no"}];
+parse_xcomp_file(Filepath) ->
+ {ok,Bin} = file:read_file(Filepath),
+ Lines = binary:split(Bin,<<"\n">>,[global,trim]),
+ {Envs,Flags} = parse_xcomp_file(Lines,[],[]),
+ [{cross,"yes"},{crossroot,os:getenv("ERL_TOP")},
+ {crossenv,Envs},{crossflags,Flags}].
+
+parse_xcomp_file([<<A:8,_/binary>> = Line|R],Envs,Flags)
+ when $A =< A, A =< $Z ->
+ [Var,Value] = binary:split(Line,<<"=">>),
+ parse_xcomp_file(R,[{binary_to_list(Var),
+ binary_to_list(Value)}|Envs],Flags);
+parse_xcomp_file([<<"erl_xcomp_",Line/binary>>|R],Envs,Flags) ->
+ [Var,Value] = binary:split(Line,<<"=">>),
+ parse_xcomp_file(R,Envs,[{binary_to_list(Var),
+ binary_to_list(Value)}|Flags]);
+parse_xcomp_file([_|R],Envs,Flags) ->
+ parse_xcomp_file(R,Envs,Flags);
+parse_xcomp_file([],Envs,Flags) ->
+ {lists:reverse(Envs),lists:reverse(Flags)}.
+
write_terms(Name, Terms) ->
case file:open(Name, [write]) of
{ok, Fd} ->
- Result = write_terms1(Fd, Terms),
+ Result = write_terms1(Fd, remove_duplicates(Terms)),
file:close(Fd),
Result;
{error, Reason} ->
@@ -141,6 +201,17 @@ write_terms1(Fd, [Term|Rest]) ->
write_terms1(_, []) ->
ok.
+remove_duplicates(List) ->
+ lists:reverse(
+ lists:foldl(fun({Key,Val},Acc) ->
+ R = make_ref(),
+ case proplists:get_value(Key,Acc,R) of
+ R -> [{Key,Val}|Acc];
+ _Else ->
+ Acc
+ end
+ end,[],List)).
+
add_vars(Vars0, Opts0) ->
{Opts,LongNames} =
case lists:keymember(longnames, 1, Opts0) of
@@ -209,12 +280,11 @@ platform(Vars) ->
LC = lock_checking(),
MT = modified_timing(),
AsyncThreads = async_threads(),
- HeapType = heap_type_label(),
Debug = debug(),
CpuBits = word_size(),
Common = lists:concat([Hostname,"/",OsType,"/",CpuType,CpuBits,LinuxDist,
Schedulers,BindType,KP,IOTHR,LC,MT,AsyncThreads,
- HeapType,Debug,ExtraLabel]),
+ Debug,ExtraLabel]),
PlatformId = lists:concat([ErlType, " ", Version, Common]),
PlatformLabel = ErlType ++ Common,
PlatformFilename = platform_as_filename(PlatformId),
@@ -272,12 +342,6 @@ hostname() ->
"/localhost"
end.
-heap_type_label() ->
- case catch erlang:system_info(heap_type) of
- hybrid -> "/Hybrid";
- _ -> "" %private
- end.
-
async_threads() ->
case catch erlang:system_info(threads) of
true -> "/A"++integer_to_list(erlang:system_info(thread_pool_size));
diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/test_server/src/ts_install_cth.erl
index a41916fd0a..67f2df0cae 100644
--- a/lib/test_server/src/ts_install_cth.erl
+++ b/lib/test_server/src/ts_install_cth.erl
@@ -95,17 +95,12 @@ pre_init_per_suite(_Suite,Config,State) ->
try
{ok,Variables} =
file:consult(filename:join(State#state.ts_conf_dir,"variables")),
-
- %% Make the stuff in all_SUITE_data if it exists
- AllDir = filename:join(DataDir,"../all_SUITE_data"),
- case filelib:is_dir(AllDir) of
- true ->
- make_non_erlang(AllDir,Variables);
- false ->
- ok
+ case proplists:get_value(cross,Variables) of
+ "yes" ->
+ ct:log("Not making data dir as tests have been cross compiled");
+ _ ->
+ ts_lib:make_non_erlang(DataDir, Variables)
end,
-
- make_non_erlang(DataDir, Variables),
{add_node_name(Config, State), State}
catch Error:Reason ->
@@ -219,39 +214,6 @@ terminate(_State) ->
%%% ============================================================================
%%% Local functions
%%% ============================================================================
-%% Configure and run all the Makefiles in the data dirs of the suite
-%% in question
-make_non_erlang(DataDir, Variables) ->
- {ok,CurrWD} = file:get_cwd(),
- try
- file:set_cwd(DataDir),
- MakeCommand = proplists:get_value(make_command,Variables),
-
- FirstMakefile = filename:join(DataDir,"Makefile.first"),
- case filelib:is_regular(FirstMakefile) of
- true ->
- ct:log("Making ~p",[FirstMakefile]),
- ok = ts_make:make(
- MakeCommand, DataDir, filename:basename(FirstMakefile));
- false ->
- ok
- end,
-
- MakefileSrc = filename:join(DataDir,"Makefile.src"),
- MakefileDest = filename:join(DataDir,"Makefile"),
- case filelib:is_regular(MakefileSrc) of
- true ->
- ok = ts_lib:subst_file(MakefileSrc,MakefileDest,Variables),
- ct:log("Making ~p",[MakefileDest]),
- ok = ts_make:make([{makefile,"Makefile"},{data_dir,DataDir}
- | Variables]);
- false ->
- ok
- end
- after
- file:set_cwd(CurrWD),
- timer:sleep(100)
- end.
%% Add a nodename to config if it does not exist
add_node_name(Config, State) ->
diff --git a/lib/test_server/src/ts_lib.erl b/lib/test_server/src/ts_lib.erl
index 2f0a4ea8c0..d521d2beda 100644
--- a/lib/test_server/src/ts_lib.erl
+++ b/lib/test_server/src/ts_lib.erl
@@ -24,10 +24,12 @@
%% Avoid warning for local function error/1 clashing with autoimported BIF.
-compile({no_auto_import,[error/1]}).
-export([error/1, var/2, erlang_type/0,
+ erlang_type/1,
initial_capital/1, interesting_logs/1,
specs/1, suites/2, last_test/1,
force_write_file/2, force_delete/1,
subst_file/3, subst/2, print_data/1,
+ make_non_erlang/2,
maybe_atom_to_list/1, progress/4
]).
@@ -73,8 +75,10 @@ progress(Vars, Level, Format, Args) ->
%% Returns: {Type, Version} where Type is otp|src
erlang_type() ->
+ erlang_type(code:root_dir()).
+erlang_type(RootDir) ->
{_, Version} = init:script_id(),
- RelDir = filename:join(code:root_dir(), "releases"), % Only in installed
+ RelDir = filename:join(RootDir, "releases"), % Only in installed
case filelib:is_file(RelDir) of
true -> {otp,Version}; % installed OTP
false -> {srctree,Version} % source code tree
@@ -333,3 +337,45 @@ maybe_atom_to_list(To_list) when is_list(To_list) ->
maybe_atom_to_list(To_list) when is_atom(To_list)->
atom_to_list(To_list).
+
+%% Configure and run all the Makefiles in the data dir of the suite
+%% in question
+make_non_erlang(DataDir, Variables) ->
+ %% Make the stuff in all_SUITE_data if it exists
+ AllDir = filename:join(DataDir,"../all_SUITE_data"),
+ case filelib:is_dir(AllDir) of
+ true ->
+ make_non_erlang_do(AllDir,Variables);
+ false ->
+ ok
+ end,
+ make_non_erlang_do(DataDir, Variables).
+
+make_non_erlang_do(DataDir, Variables) ->
+ try
+ MakeCommand = proplists:get_value(make_command,Variables),
+
+ FirstMakefile = filename:join(DataDir,"Makefile.first"),
+ case filelib:is_regular(FirstMakefile) of
+ true ->
+ io:format("Making ~p",[FirstMakefile]),
+ ok = ts_make:make(
+ MakeCommand, DataDir, filename:basename(FirstMakefile));
+ false ->
+ ok
+ end,
+
+ MakefileSrc = filename:join(DataDir,"Makefile.src"),
+ MakefileDest = filename:join(DataDir,"Makefile"),
+ case filelib:is_regular(MakefileSrc) of
+ true ->
+ ok = ts_lib:subst_file(MakefileSrc,MakefileDest,Variables),
+ io:format("Making ~p",[MakefileDest]),
+ ok = ts_make:make([{makefile,"Makefile"},{data_dir,DataDir}
+ | Variables]);
+ false ->
+ ok
+ end
+ after
+ timer:sleep(100) %% maybe unnecessary now when we don't do set_cwd anymore
+ end.
diff --git a/lib/test_server/src/ts_make.erl b/lib/test_server/src/ts_make.erl
index 3df66111a3..1d8ef230c7 100644
--- a/lib/test_server/src/ts_make.erl
+++ b/lib/test_server/src/ts_make.erl
@@ -25,12 +25,12 @@
%% Functions to be called from make test cases.
make(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- Makefile = ?config(makefile, Config),
- Make = ?config(make_command, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ Makefile = proplists:get_value(makefile, Config),
+ Make = proplists:get_value(make_command, Config),
case make(Make, DataDir, Makefile) of
ok -> ok;
- {error,Reason} -> ?t:fail({make_failed,Reason})
+ {error,Reason} -> exit({make_failed,Reason})
end.
unmake(Config) when is_list(Config) ->
@@ -85,7 +85,7 @@ run_make_script({win32, _}, Make, Dir, Makefile) ->
{"run_make.bat",
".\\run_make",
["@echo off\r\n",
- "cd ", filename:nativename(Dir), "\r\n",
+ "cd \"", filename:nativename(Dir), "\"\r\n",
Make, " -f ", Makefile, " \r\n",
"if errorlevel 1 echo *error*\r\n",
"if not errorlevel 1 echo *ok*\r\n"]};
@@ -93,7 +93,7 @@ run_make_script({unix, _}, Make, Dir, Makefile) ->
{"run_make",
"/bin/sh ./run_make",
["#!/bin/sh\n",
- "cd ", Dir, "\n",
+ "cd \"", Dir, "\"\n",
Make, " -f ", Makefile, " 2>&1\n",
"case $? in\n",
" 0) echo '*ok*';;\n",
diff --git a/lib/test_server/src/ts_run.erl b/lib/test_server/src/ts_run.erl
index 885a3c9b96..2e8c092400 100644
--- a/lib/test_server/src/ts_run.erl
+++ b/lib/test_server/src/ts_run.erl
@@ -229,7 +229,7 @@ make_command(Vars, Spec, State) ->
%% uncomment the line below to disable exception formatting
%% " -test_server_format_exception false",
" -boot start_sasl -sasl errlog_type error",
- " -pz ",Cwd,
+ " -pz \"",Cwd,"\"",
" -ct_test_vars ",TestVars,
" -eval \"file:set_cwd(\\\"",TestDir,"\\\")\" "
" -eval \"ct:run_test(",
@@ -334,9 +334,9 @@ path_separator() ->
end.
-make_common_test_args(Args0, Options, _Vars) ->
+make_common_test_args(Args0, Options0, _Vars) ->
Trace =
- case lists:keysearch(trace,1,Options) of
+ case lists:keysearch(trace,1,Options0) of
{value,{trace,TI}} when is_tuple(TI); is_tuple(hd(TI)) ->
ok = file:write_file(?tracefile,io_lib:format("~p.~n",[TI])),
[{ct_trace,?tracefile}];
@@ -348,7 +348,7 @@ make_common_test_args(Args0, Options, _Vars) ->
[]
end,
Cover =
- case lists:keysearch(cover,1,Options) of
+ case lists:keysearch(cover,1,Options0) of
{value,{cover, App, none, _Analyse}} ->
io:format("No cover file found for ~p~n",[App]),
[];
@@ -358,7 +358,7 @@ make_common_test_args(Args0, Options, _Vars) ->
[]
end,
- Logdir = case lists:keysearch(logdir, 1, Options) of
+ Logdir = case lists:keysearch(logdir, 1, Options0) of
{value,{logdir, _}} ->
[];
false ->
@@ -373,15 +373,16 @@ make_common_test_args(Args0, Options, _Vars) ->
{scale_timetraps, true}]
end,
- ConfigPath = case {os:getenv("TEST_CONFIG_PATH"),
- lists:keysearch(config, 1, Options)} of
- {false,{value, {config, Path}}} ->
- Path;
- {false,false} ->
- "../test_server";
- {Path,_} ->
- Path
- end,
+ {ConfigPath,
+ Options} = case {os:getenv("TEST_CONFIG_PATH"),
+ lists:keysearch(config, 1, Options0)} of
+ {_,{value, {config, Path}}} ->
+ {Path,lists:keydelete(config, 1, Options0)};
+ {false,false} ->
+ {"../test_server",Options0};
+ {Path,_} ->
+ {Path,Options0}
+ end,
ConfigFiles = [{config,[filename:join(ConfigPath,File)
|| File <- get_config_files()]}],
io_lib:format("~100000p",[Args0++Trace++Cover++Logdir++
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
index 198440bb17..b2ac95afaa 100644
--- a/lib/test_server/test/Makefile
+++ b/lib/test_server/test/Makefile
@@ -83,10 +83,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(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 -)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) "$(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_data/Makefile.src b/lib/test_server/test/test_server_SUITE_data/Makefile.src
index d5af919eec..332b855df6 100644
--- a/lib/test_server/test/test_server_SUITE_data/Makefile.src
+++ b/lib/test_server/test/test_server_SUITE_data/Makefile.src
@@ -1,2 +1,7 @@
all:
- erlc *.erl \ No newline at end of file
+ erlc test_server_SUITE.erl
+ erlc test_server_parallel01_SUITE.erl
+ erlc test_server_conf01_SUITE.erl
+ erlc test_server_shuffle01_SUITE.erl
+ erlc test_server_conf02_SUITE.erl
+ erlc test_server_skip_SUITE.erl \ No newline at end of file
diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk
index 563c1b6db6..aecf595f3f 100644
--- a/lib/test_server/vsn.mk
+++ b/lib/test_server/vsn.mk
@@ -1,2 +1 @@
-TEST_SERVER_VSN = 3.4.5
-
+TEST_SERVER_VSN = 3.5.2
diff --git a/lib/toolbar/doc/src/Makefile b/lib/toolbar/doc/src/Makefile
index 76147c111e..af907859d7 100644
--- a/lib/toolbar/doc/src/Makefile
+++ b/lib/toolbar/doc/src/Makefile
@@ -102,14 +102,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/toolbar/doc/src/make.dep b/lib/toolbar/doc/src/make.dep
deleted file mode 100644
index d93ff2a315..0000000000
--- a/lib/toolbar/doc/src/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex toolbar.tex \
- toolbar_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: bar.ps create_tool.ps
-
diff --git a/lib/toolbar/doc/src/notes.xml b/lib/toolbar/doc/src/notes.xml
index ffca2c5fbf..b901e6c8ff 100644
--- a/lib/toolbar/doc/src/notes.xml
+++ b/lib/toolbar/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,41 @@
<p>This document describes the changes made to the Toolbar
application.</p>
+<section><title>Toolbar 1.4.2.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The GS applications is now deprecated and will be
+ removed in the R16 release. The following GS-based
+ applications have been superseded by the Observer
+ application and will removed in R16: Appmon, Pman,
+ Tv.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9907</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Toolbar 1.4.2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Miscellaneous documentation build updates</p>
+ <p>
+ Own Id: OTP-9813</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Toolbar 1.4.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/toolbar/doc/src/toolbar.xml b/lib/toolbar/doc/src/toolbar.xml
index ad379438fe..2580de2242 100644
--- a/lib/toolbar/doc/src/toolbar.xml
+++ b/lib/toolbar/doc/src/toolbar.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,11 @@
<module>toolbar</module>
<modulesummary>GUI for Starting Tools and User Contributions</modulesummary>
<description>
+ <warning>
+ <p>
+ The Toolbar application is deprecated and will be removed in R16.
+ </p>
+ </warning>
<p>Toolbar makes it easier to use
the different Erlang tools - and the user contributions - which are provided.
It has a graphical user interface with an icon for each tool.
diff --git a/lib/toolbar/doc/src/toolbar_chapter.xml b/lib/toolbar/doc/src/toolbar_chapter.xml
index a80dc5bd3e..ebd47ef2fe 100644
--- a/lib/toolbar/doc/src/toolbar_chapter.xml
+++ b/lib/toolbar/doc/src/toolbar_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,6 +28,11 @@
<rev>A</rev>
<file>toolbar_chapter.xml</file>
</header>
+ <warning>
+ <p>
+ The Toolbar application is deprecated and will be removed in R16.
+ </p>
+ </warning>
<p>Toolbar provides an interface to the various Erlang tools which are available. Toolbar can also provide access to user supplied tools which are included with the Erlang software release. These tools are called GS Contributions.</p>
<p>All tools included in Toolbar must have a configuration file which contains information about the tool, such as its start function and the location of help information. The name of a configuration file must include the suffix <c>.tool</c>.
</p>
diff --git a/lib/toolbar/src/Makefile b/lib/toolbar/src/Makefile
index 14e1451609..91ce305e26 100644
--- a/lib/toolbar/src/Makefile
+++ b/lib/toolbar/src/Makefile
@@ -84,10 +84,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/toolbar/src/canvasbutton.erl b/lib/toolbar/src/canvasbutton.erl
index 38fce537bb..81e0ed43bb 100644
--- a/lib/toolbar/src/canvasbutton.erl
+++ b/lib/toolbar/src/canvasbutton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,9 @@
%% %CopyrightEnd%
%%
-module(canvasbutton).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar.erl b/lib/toolbar/src/toolbar.erl
index 67967172fe..b37c323008 100644
--- a/lib/toolbar/src/toolbar.erl
+++ b/lib/toolbar/src/toolbar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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%
%%
-module(toolbar).
+-compile([{nowarn_deprecated_function,{gs,start,1}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar_graphics.erl b/lib/toolbar/src/toolbar_graphics.erl
index ad390440e3..c4c4273c63 100644
--- a/lib/toolbar/src/toolbar_graphics.erl
+++ b/lib/toolbar/src/toolbar_graphics.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,9 @@
%% %CopyrightEnd%
%%
-module(toolbar_graphics).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar_toolconfig.erl b/lib/toolbar/src/toolbar_toolconfig.erl
index 6dccb7ba72..479033fa22 100644
--- a/lib/toolbar/src/toolbar_toolconfig.erl
+++ b/lib/toolbar/src/toolbar_toolconfig.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The 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,11 @@
%% %CopyrightEnd%
%%
-module(toolbar_toolconfig).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/vsn.mk b/lib/toolbar/vsn.mk
index 105303d785..9fbfec871f 100644
--- a/lib/toolbar/vsn.mk
+++ b/lib/toolbar/vsn.mk
@@ -1,4 +1,4 @@
-TOOLBAR_VSN = 1.4.2
+TOOLBAR_VSN = 1.4.2.2
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index 6921193154..0382d3228d 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -1,26 +1,27 @@
-# ``The contents of this file are subject to the Erlang Public License,
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of 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)/erts/include/internal/$(TARGET)/ethread.mk
USING_MINGW=@MIXED_CYGWIN_MINGW@
-USING_VC=@MIXED_CYGWIN_VC@
+USING_VC=@MIXED_VC@
CC=@CC@
LD=@LD@
@@ -138,15 +139,17 @@ EMEM_LIBS = $(LIBS) \
EMEM_OBJS = $(addprefix $(EMEM_OBJ_DIR)/,$(notdir $(EMEM_SRCS:.c=.o)))
+ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
+
#
# Misc targets
#
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
-all: erts_lib $(PROGS) $(DRIVERS)
+all: $(PROGS) $(DRIVERS)
-erts_lib:
+$(ERTS_LIB):
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
@@ -174,7 +177,7 @@ $(EMEM_OBJ_DIR)/%.o: %.c
# Program targets
#
-$(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@: $(EMEM_OBJS)
+$(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@: $(EMEM_OBJS) $(ERTS_LIB)
$(PRE_LD) $(LD) $(EMEM_LDFLAGS) -o $@ $(EMEM_OBJS) $(EMEM_LIBS)
#
@@ -185,11 +188,11 @@ include ../vsn.mk
RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(TOOLS_VSN)
release_spec: all
- $(INSTALL_DIR) $(RELSYSDIR)/c_src
- $(INSTALL_DATA) $(EMEM_SRCS) $(EMEM_HEADERS) $(RELSYSDIR)/c_src
+ $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
+ $(INSTALL_DATA) $(EMEM_SRCS) $(EMEM_HEADERS) "$(RELSYSDIR)/c_src"
ifneq ($(PROGS),)
- $(INSTALL_DIR) $(RELSYSDIR)/bin
- $(INSTALL_PROGRAM) $(PROGS) $(RELSYSDIR)/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/bin"
+ $(INSTALL_PROGRAM) $(PROGS) "$(RELSYSDIR)/bin"
endif
release_docs_spec:
diff --git a/lib/tools/c_src/erl_memory.c b/lib/tools/c_src/erl_memory.c
index 872d55e789..86e84723b1 100644
--- a/lib/tools/c_src/erl_memory.c
+++ b/lib/tools/c_src/erl_memory.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1224,7 +1224,7 @@ print_main_footer(em_state *state)
switch (state->info.stop_reason) {
case EMTP_STOP:
- p += sprintf(p, stop_str);
+ p += sprintf(p, "%s", stop_str);
break;
case EMTP_EXIT:
p += sprintf(p, exit_str, state->info.exit_status);
@@ -2339,7 +2339,7 @@ usage(char *sw, char *error)
if (error)
exit(1);
else {
- char *help_str =
+ fprintf(filep,
"\n"
" [] - switch is allowed any number of times\n"
" {} - switch is allowed at most one time\n"
@@ -2370,8 +2370,7 @@ usage(char *sw, char *error)
" " SW_CHAR "o - display operation count values\n"
" " SW_CHAR "p <P> - set listen port to <P>\n"
" " SW_CHAR "t - display info about total values\n"
- " " SW_CHAR "v - verbose output\n";
- fprintf(filep, help_str);
+ " " SW_CHAR "v - verbose output\n");
exit(0);
}
diff --git a/lib/tools/doc/src/Makefile b/lib/tools/doc/src/Makefile
index 433f123ae5..a76ce98ad6 100644
--- a/lib/tools/doc/src/Makefile
+++ b/lib/tools/doc/src/Makefile
@@ -121,14 +121,14 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml
index 6d68c90768..1c5e38109b 100644
--- a/lib/tools/doc/src/eprof.xml
+++ b/lib/tools/doc/src/eprof.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>
@@ -67,9 +67,9 @@
<p><c>Rootset</c> is a list of pids and registered names.</p>
<p>The function returns <c>profiling</c> if tracing could be enabled
for all processes in <c>Rootset</c>, or <c>error</c> otherwise.</p>
- <p>A pattern can be selected to narrow the profiling. For instance ca a specific
- module be selected and only the code processes executes in that module will be
- profiled.</p>
+ <p>A pattern can be selected to narrow the profiling. For instance a
+ specific module can be selected, and only the code executed in that
+ module will be profiled.</p>
</desc>
</func>
<func>
@@ -147,8 +147,8 @@
</type>
<desc>
<p>This function ensures that the results displayed by
- <c>analyse/0</c> and <c>total_analyse/0</c> are printed both to
- the file <c>File</c> and the screen.</p>
+ <c>analyze/0,1,2</c> are printed both to the file
+ <c>File</c> and the screen.</p>
</desc>
</func>
<func>
diff --git a/lib/tools/doc/src/make.dep b/lib/tools/doc/src/make.dep
deleted file mode 100644
index 11fa090d6f..0000000000
--- a/lib/tools/doc/src/make.dep
+++ /dev/null
@@ -1,33 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex cover.tex cover_chapter.tex cprof.tex \
- cprof_chapter.tex eprof.tex erlang_mode.tex \
- erlang_mode_chapter.tex fprof.tex fprof_chapter.tex \
- instrument.tex make.tex part.tex ref_man.tex \
- tags.tex xref.tex xref_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-cprof.tex: ../../../../system/doc/definitions/term.defs
-
-xref.tex: ../../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: venn1.ps venn2.ps
-
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 17506fb6e2..f4da132102 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -30,6 +30,110 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 2.6.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Makefiles in erts, hipe and tools have been corrected to
+ enable parallel make, i.e MAKEFLAGS=-jX where X is the
+ parallelity number. As a result of this dependencies were
+ corrected since that is what is needed for parallel make
+ to work.</p>
+ <p>
+ Own Id: OTP-9857 Aux Id: OTP-9451 </p>
+ </item>
+ <item>
+ <p>Minor suppressions and fixes of compilation
+ warnings</p>
+ <p>
+ Own Id: OTP-10016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 2.6.6.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Update system profiling principles to reflect eprof
+ performance improvements.</p>
+ <p>
+ Own Id: OTP-9656</p>
+ </item>
+ <item>
+ <p>
+ [cover] fix leftover {'DOWN', ..} msg in callers queue</p>
+ <p>
+ After stopping cover with cover:stop() there could still
+ be a {'DOWN',...} leftover message in the calling
+ process's message queue. This unexpected leftover could
+ be eliminated if erlang:demonitor/2 with option flush
+ would be used in certain points</p>
+ <p>
+ Own Id: OTP-9694</p>
+ </item>
+ <item>
+ <p>
+ Add deps as erlang-flymake include directory.</p>
+ <p>
+ Update erlang-flymake to recognize the "deps" folder as
+ an include directory. This makes erlang-flymake
+ compatible with the rebar dependency management tool's
+ default folder structure, which puts included
+ dependencies in "deps".(Thanks to Kevin Albrecht)</p>
+ <p>
+ Own Id: OTP-9791</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Variables are now now allowed in '<c>fun M:F/A</c>' as
+ suggested by Richard O'Keefe in EEP-23.</p>
+ <p>The representation of '<c>fun M:F/A</c>' in the
+ abstract format has been changed in an incompatible way.
+ Tools that directly read or manipulate the abstract
+ format (such as parse transforms) may need to be updated.
+ The compiler can handle both the new and the old format
+ (i.e. extracting the abstract format from a pre-R15 BEAM
+ file and compiling it using compile:forms/1,2 will work).
+ The <c>syntax_tools</c> application can also handle both
+ formats.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9643</p>
+ </item>
+ <item>
+ <p>
+ Tuple funs (a two-element tuple with a module name and a
+ function) are now officially deprecated and will be
+ removed in R16. Use '<c>fun M:F/A</c>' instead. To make
+ you aware that your system uses tuple funs, the very
+ first time a tuple fun is applied, a warning will be sent
+ to the error logger.</p>
+ <p>
+ Own Id: OTP-9649</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.6.6.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/emacs/Makefile b/lib/tools/emacs/Makefile
index 8533488463..69946be24a 100644
--- a/lib/tools/emacs/Makefile
+++ b/lib/tools/emacs/Makefile
@@ -71,9 +71,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/emacs
+ $(INSTALL_DIR) "$(RELSYSDIR)/emacs"
$(INSTALL_DATA) $(EL_FILES) $(README_FILES) $(TEST_FILES) \
- $(RELSYSDIR)/emacs
+ "$(RELSYSDIR)/emacs"
ifeq ($(DOCTYPE),pdf)
release_docs_spec:
@@ -82,7 +82,23 @@ ifeq ($(DOCTYPE),ps)
release_docs_spec:
else
release_docs_spec: docs
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN_FILES) $(RELEASE_PATH)/man/man3
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN_FILES) "$(RELEASE_PATH)/man/man3"
endif
endif
+
+EMACS ?= emacs
+
+test_indentation:
+ @rm -f test.erl
+ @rm -f test_indent.el
+ @echo '(load "erlang-start")' >> test_indent.el
+ @echo '(find-file "test.erl.orig")' >> test_indent.el
+ @echo "(require 'cl) ; required with Emacs < 23 for ignore-errors" >> test_indent.el
+ @echo '(erlang-mode)' >> test_indent.el
+ @echo '(toggle-debug-on-error)' >> test_indent.el
+ @echo '(erlang-indent-current-buffer)' >> test_indent.el
+ @echo '(write-file "test.erl")' >> test_indent.el
+ $(EMACS) --batch -Q -L . -l test_indent.el
+ diff -u test.erl.indented test.erl
+ @echo "No differences between expected and actual indentation"
diff --git a/lib/tools/emacs/erlang-flymake.el b/lib/tools/emacs/erlang-flymake.el
index bc368e9454..2e447b55de 100644
--- a/lib/tools/emacs/erlang-flymake.el
+++ b/lib/tools/emacs/erlang-flymake.el
@@ -60,7 +60,8 @@ check on newline and when there are no changes)."
(list (concat (erlang-flymake-get-app-dir) "ebin")))
(defun erlang-flymake-get-include-dirs ()
- (list (concat (erlang-flymake-get-app-dir) "include")))
+ (list (concat (erlang-flymake-get-app-dir) "include")
+ (concat (erlang-flymake-get-app-dir) "deps")))
(defun erlang-flymake-get-app-dir ()
(let ((src-path (file-name-directory (buffer-file-name))))
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index bc7a190fb4..8f98d6c85c 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -1516,7 +1516,7 @@ Other commands:
;; A dollar sign right before the double quote that ends a
;; string is not a character escape.
;;
- ;; And a "string" has with a double quote not escaped by a
+ ;; And a "string" consists of a double quote not escaped by a
;; dollar sign, any number of non-backslash non-newline
;; characters or escaped backslashes, a dollar sign
;; (otherwise we wouldn't care) and a double quote. This
@@ -1525,6 +1525,8 @@ Other commands:
;; know whether matching started inside a string: limiting
;; search to a single line keeps things sane.
. (("\\(?:^\\|[^$]\\)\"\\(?:[^\"\n]\\|\\\\\"\\)*\\(\\$\\)\"" 1 "w")
+ ;; Likewise for atoms
+ ("\\(?:^\\|[^$]\\)'\\(?:[^'\n]\\|\\\\'\\)*\\(\\$\\)'" 1 "w")
;; And the dollar sign in $\" escapes two characters, not
;; just one.
("\\(\\$\\)\\\\\\\"" 1 "'"))))))
@@ -2986,18 +2988,52 @@ This assumes that the preceding expression is either simple
(forward-sexp (- arg))
(let ((col (current-column)))
(skip-chars-backward " \t")
- ;; Needed to match the colon in "'foo':'bar'".
- (if (not (memq (preceding-char) '(?# ?:)))
- col
- ;; Special hack to handle: (note line break)
- ;; [#myrecord{
- ;; foo = foo}]
- (or
- (ignore-errors
- (backward-char 1)
- (forward-sexp -1)
- (current-column))
- col)))))
+ ;; Special hack to handle: (note line break)
+ ;; [#myrecord{
+ ;; foo = foo}]
+ ;; where the call (forward-sexp -1) will fail when point is at the `#'.
+ (or
+ (ignore-errors
+ ;; Needed to match the colon in "'foo':'bar'".
+ (cond ((eq (preceding-char) ?:)
+ (backward-char 1)
+ (forward-sexp -1)
+ (current-column))
+ ((eq (preceding-char) ?#)
+ ;; We may now be at:
+ ;; - either a construction of a new record
+ ;; - or update of a record, in which case we want
+ ;; the column of the expression to be updated.
+ ;;
+ ;; To see which of the two cases we are at, we first
+ ;; move an expression backwards, check for keywords,
+ ;; then immediately an expression forwards. Moving
+ ;; backwards skips past tokens like `,' or `->', but
+ ;; when moving forwards again, we won't skip past such
+ ;; tokens. We use this: if, after having moved
+ ;; forwards, we're back where we started, then it was
+ ;; a record update.
+ ;; The check for keywords is to detect cases like:
+ ;; case Something of #record_construction{...}
+ (backward-char 1)
+ (let ((record-start (point))
+ (record-start-col (current-column)))
+ (forward-sexp -1)
+ (let ((preceding-expr-col (current-column))
+ ;; white space definition according to erl_scan
+ (white-space "\000-\040\200-\240"))
+ (if (erlang-at-keyword)
+ ;; The (forward-sexp -1) call moved past a keyword
+ (1+ record-start-col)
+ (forward-sexp 1)
+ (skip-chars-forward white-space record-start)
+ ;; Are we back where we started? If so, it was an update.
+ (if (= (point) record-start)
+ preceding-expr-col
+ (goto-char record-start)
+ (1+ (current-column)))))))
+ (t col)))
+ col))))
(defun erlang-indent-parenthesis (stack-position)
(let ((previous (erlang-indent-find-preceding-expr)))
diff --git a/lib/tools/emacs/test.erl.indented b/lib/tools/emacs/test.erl.indented
index 2948ccf1b5..45d9593000 100644
--- a/lib/tools/emacs/test.erl.indented
+++ b/lib/tools/emacs/test.erl.indented
@@ -215,6 +215,11 @@ highlighting(X) % Function definitions should be highlighted
"char $in string", atom,
+ 'atom$', atom, 'atom$', atom,
+ 'atom\$', atom,
+
+ 'char $in atom', atom,
+
$[, ${, $\\, atom,
?MACRO_1,
?MACRO_2(foo),
@@ -657,3 +662,41 @@ indent_comprehensions() ->
foo() ->
[#foo{
foo = foo}].
+
+%% Record indentation
+some_function_with_a_very_long_name() ->
+ #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b},
+ case dummy_function_with_a_very_very_long_name(x) of
+ #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b} ->
+ ok;
+ Var = #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b} ->
+ Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b};
+ #xyz{
+ a=1,
+ b=2} ->
+ ok
+ end.
+
+another_function_with_a_very_very_long_name() ->
+ #rec{
+ field1=1,
+ field2=1}.
+
+some_function_name_xyz(xyzzy, #some_record{
+ field1=Field1,
+ field2=Field2}) ->
+ SomeVariable = f(#'Some-long-record-name'{
+ field_a = 1,
+ 'inter-xyz-parameters' =
+ #'Some-other-very-long-record-name'{
+ field2 = Field1,
+ field2 = Field2}}),
+ {ok, SomeVariable}.
diff --git a/lib/tools/emacs/test.erl.orig b/lib/tools/emacs/test.erl.orig
index 1221c5655e..e123150dd1 100644
--- a/lib/tools/emacs/test.erl.orig
+++ b/lib/tools/emacs/test.erl.orig
@@ -215,6 +215,11 @@ highlighting(X) % Function definitions should be highlighted
"char $in string", atom,
+ 'atom$', atom, 'atom$', atom,
+ 'atom\$', atom,
+
+ 'char $in atom', atom,
+
$[, ${, $\\, atom,
?MACRO_1,
?MACRO_2(foo),
@@ -657,3 +662,41 @@ ok.
foo() ->
[#foo{
foo = foo}].
+
+%% Record indentation
+some_function_with_a_very_long_name() ->
+ #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b},
+ case dummy_function_with_a_very_very_long_name(x) of
+ #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b} ->
+ ok;
+ Var = #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b} ->
+ Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b};
+ #xyz{
+ a=1,
+ b=2} ->
+ ok
+ end.
+
+another_function_with_a_very_very_long_name() ->
+ #rec{
+ field1=1,
+ field2=1}.
+
+some_function_name_xyz(xyzzy, #some_record{
+ field1=Field1,
+ field2=Field2}) ->
+ SomeVariable = f(#'Some-long-record-name'{
+ field_a = 1,
+ 'inter-xyz-parameters' =
+ #'Some-other-very-long-record-name'{
+ field2 = Field1,
+ field2 = Field2}}),
+ {ok, SomeVariable}.
diff --git a/lib/tools/examples/Makefile b/lib/tools/examples/Makefile
index 9fb8434633..fc14ee54d6 100644
--- a/lib/tools/examples/Makefile
+++ b/lib/tools/examples/Makefile
@@ -50,7 +50,7 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) "$(RELSYSDIR)/examples"
+ $(INSTALL_DATA) $(EXAMPLE_FILES) "$(RELSYSDIR)/examples"
release_docs_spec:
diff --git a/lib/tools/priv/Makefile b/lib/tools/priv/Makefile
index 6fea580c00..b32ba5820d 100644
--- a/lib/tools/priv/Makefile
+++ b/lib/tools/priv/Makefile
@@ -58,9 +58,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(HTDOCS_FILES) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(TOOL_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(TOOL_FILES) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index 360f4f8f29..4c0cc8cde7 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -105,10 +105,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
- $(RELSYSDIR)/ebin
+ "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index fb9744d759..e21bd1b88c 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -522,7 +522,7 @@ call(Request) ->
{?SERVER,Reply} ->
Reply
end,
- erlang:demonitor(Ref),
+ erlang:demonitor(Ref, [flush]),
Return
end.
@@ -545,7 +545,7 @@ remote_call(Node,Request) ->
{?SERVER,Reply} ->
Reply
end,
- erlang:demonitor(Ref),
+ erlang:demonitor(Ref, [flush]),
Return
end.
diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl
index 155965a65a..4cbb910f11 100644
--- a/lib/tools/src/fprof.erl
+++ b/lib/tools/src/fprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -87,9 +87,9 @@ dbg(_, _, _) ->
-apply({M, F} = Function, Args)
+apply({M, F}, Args)
when is_atom(M), is_atom(F), is_list(Args) ->
- apply_1(Function, Args, []);
+ apply_1(M, F, Args, []);
apply(Fun, Args)
when is_function(Fun), is_list(Args) ->
apply_1(Fun, Args, []);
@@ -97,22 +97,25 @@ apply(A, B) ->
erlang:error(badarg, [A, B]).
apply(M, F, Args) when is_atom(M), is_atom(F), is_list(Args) ->
- apply_1({M, F}, Args, []);
-apply({M, F} = Function, Args, Options)
+ apply_1(M, F, Args, []);
+apply({M, F}, Args, Options)
when is_atom(M), is_atom(F), is_list(Args), is_list(Options) ->
- apply_1(Function, Args, Options);
+ apply_1(M, F, Args, Options);
apply(Fun, Args, Options)
when is_function(Fun), is_list(Args), is_list(Options) ->
apply_1(Fun, Args, Options);
apply(A, B, C) ->
erlang:error(badarg, [A, B, C]).
-apply(Module, Function, Args, Options)
- when is_atom(Module), is_atom(Function), is_list(Args), is_list(Options) ->
- apply_1({Module, Function}, Args, Options);
+apply(M, F, Args, Options)
+ when is_atom(M), is_atom(F), is_list(Args), is_list(Options) ->
+ apply_1(M, F, Args, Options);
apply(A, B, C, D) ->
erlang:error(badarg, [A, B, C, D]).
+apply_1(M, F, Args, Options) ->
+ Arity = length(Args),
+ apply_1(fun M:F/Arity, Args, Options).
apply_1(Function, Args, Options) ->
{[_, Procs, Continue], Options_1} =
diff --git a/lib/tools/src/xref_compiler.erl b/lib/tools/src/xref_compiler.erl
index 1445e135be..22312c6754 100644
--- a/lib/tools/src/xref_compiler.erl
+++ b/lib/tools/src/xref_compiler.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
@@ -736,8 +736,11 @@ find_nodes(Tuple, I, T) when is_tuple(Tuple) ->
end,
{NL, NI, T1} = foldl(Fun, {[], I, T}, L),
Tag = case Tag0 of
- _ when is_function(Tag0) -> Tag0;
- _ when is_atom(Tag0) -> {sofs, Tag0}
+ _ when is_function(Tag0) ->
+ Tag0;
+ _ when is_atom(Tag0) ->
+ Arity = length(NL),
+ fun sofs:Tag0/Arity
end,
find_node({apply, Tag, NL}, NI, T1).
diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl
index d22f0df164..92f0c45c7b 100644
--- a/lib/tools/src/xref_reader.erl
+++ b/lib/tools/src/xref_reader.erl
@@ -158,15 +158,20 @@ expr({'try',_Line,Es,Scs,Ccs,As}, S) ->
S2 = clauses(Scs, S1),
S3 = clauses(Ccs, S2),
expr(As, S3);
-expr({call, Line,
- {remote, _, {atom,_,erlang}, {atom,_,make_fun}},
- [{atom,_,Mod}, {atom,_,Fun}, {integer,_,Arity}]}, S) ->
- %% Added in R10B-6. M:F/A.
- expr({'fun', Line, {function, Mod, Fun, Arity}}, S);
-expr({'fun', Line, {function, Mod, Name, Arity}}, S) ->
- %% Added in R10B-6. M:F/A.
+expr({'fun', Line, {function, {atom,_,Mod},
+ {atom,_,Name},
+ {integer,_,Arity}}}, S) ->
+ %% New format in R15. M:F/A (literals).
As = lists:duplicate(Arity, {atom, Line, foo}),
external_call(Mod, Name, As, Line, false, S);
+expr({'fun', Line, {function, Mod, Name, {integer,_,Arity}}}, S) ->
+ %% New format in R15. M:F/A (one or more variables).
+ As = lists:duplicate(Arity, {atom, Line, foo}),
+ external_call(erlang, apply, [Mod, Name, list2term(As)], Line, true, S);
+expr({'fun', Line, {function, Mod, Name, _Arity}}, S) ->
+ %% New format in R15. M:F/A (one or more variables).
+ As = {var, Line, '_'},
+ external_call(erlang, apply, [Mod, Name, As], Line, true, S);
expr({'fun', Line, {function, Name, Arity}, _Extra}, S) ->
%% Added in R8.
handle_call(local, S#xrefr.module, Name, Arity, Line, S);
@@ -286,10 +291,10 @@ check_funarg(W, ArgsList, Line, S) ->
expr(ArgsList, S1).
funarg({'fun', _, _Clauses, _Extra}, _S) -> true;
-funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars);
-funarg({call,_,{remote,_,{atom,_,erlang},{atom,_,make_fun}},_MFA}, _S) ->
- %% R10B-6. M:F/A.
+funarg({'fun', _, {function,_,_,_}}, _S) ->
+ %% New abstract format for fun M:F/A in R15.
true;
+funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars);
funarg(_, _S) -> false.
fun_args(apply2, [FunArg, Args]) -> {FunArg, Args};
diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl
index 9d4a175d88..680563e9df 100644
--- a/lib/tools/src/xref_utils.erl
+++ b/lib/tools/src/xref_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -141,7 +141,7 @@ is_string([], _) ->
is_string(Term, C) ->
is_string1(Term, C).
-is_string1([H | T], C) when H > C, H < 127 ->
+is_string1([H | T], C) when H > C ->
is_string1(T, C);
is_string1([], _) ->
true;
diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile
index 8019b7269f..b9a42041a2 100644
--- a/lib/tools/test/Makefile
+++ b/lib/tools/test/Makefile
@@ -84,11 +84,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
release_tests_spec: make_emakefile
- $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(EMAKEFILE) \
- $(ERL_FILES) $(RELSYSDIR)
- chmod -R u+w $(RELSYSDIR)
- @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ $(ERL_FILES) "$(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 fe7f92de78..0cd53a05db 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -130,13 +130,20 @@ compile(Config) when is_list(Config) ->
?line {ok,_} = compile:file(x),
?line {ok,_} = compile:file("d/y",[debug_info,{outdir,"d"},report]),
?line Key = "A Krypto Key",
- ?line {ok,_} = compile:file(crypt, [debug_info,{debug_info_key,Key},report]),
+ CryptoWorks = crypto_works(),
+ case CryptoWorks of
+ false ->
+ {ok,_} = compile:file(crypt, [debug_info,report]),
+ {ok,crypt} = cover:compile_beam("crypt.beam");
+ true ->
+ {ok,_} = compile:file(crypt, [{debug_info_key,Key},report]),
+ {error,{encrypted_abstract_code,_}} =
+ cover:compile_beam("crypt.beam"),
+ ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
+ {ok,crypt} = cover:compile_beam("crypt.beam")
+ end,
?line {ok,v} = cover:compile_beam(v),
?line {ok,w} = cover:compile_beam("w.beam"),
- ?line {error,{encrypted_abstract_code,_}} =
- cover:compile_beam("crypt.beam"),
- ?line ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
- ?line {ok,crypt} = cover:compile_beam("crypt.beam"),
?line {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x),
?line {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a),
?line {error,non_existing} = cover:compile_beam(z),
@@ -148,6 +155,15 @@ compile(Config) when is_list(Config) ->
?line Files = lsfiles(),
?line remove(files(Files, ".beam")).
+crypto_works() ->
+ try crypto:start() of
+ {error,{already_started,crypto}} -> true;
+ ok -> true
+ catch
+ error:_ ->
+ false
+ end.
+
simple_crypto_fun(Key) ->
fun(init) -> ok;
({debug_info, des3_cbc, crypt, _}) -> Key
@@ -558,14 +574,7 @@ otp_5418(Config) when is_list(Config) ->
ok.
-otp_6115(suite) -> [];
otp_6115(Config) when is_list(Config) ->
- case erlang:system_info(heap_type) of
- hybrid -> {skip,"Hybrid-heap emulator doesn't keep track of funs"};
- _ -> otp_6115_1(Config)
- end.
-
-otp_6115_1(Config) ->
?line {ok, CWD} = file:get_cwd(),
?line Dir = filename:join(?config(data_dir, Config), otp_6115),
?line ok = file:set_cwd(Dir),
@@ -583,21 +592,14 @@ otp_6115_1(Config) ->
%% called -- running cover compiled code when there is no cover
%% server and thus no ets tables to bump counters in, makes no
%% sense.
- ?line Pid1 = f1:start_fail(),
-
- %% If f1 is cover compiled, a process P is started with a
- %% reference to the fun created in start_ok/0, and
- %% cover:stop() is called, then P should survive.
- %% This is because (the fun held by) P always references the current
- %% version of the module, and is thus not affected by the cover
- %% compiled version being unloaded.
- ?line Pid2 = f1:start_ok(),
+ Pid1 = f1:start_a(),
+ Pid2 = f1:start_b(),
%% Now stop cover
?line cover:stop(),
- %% Ensure that f1 is loaded (and not cover compiled), that Pid1
- %% is dead and Pid2 is alive, but with no reference to old code
+ %% Ensure that f1 is loaded (and not cover compiled), and that
+ %% both Pid1 and Pid2 are dead.
case code:which(f1) of
Beam when is_list(Beam) ->
ok;
@@ -608,19 +610,15 @@ otp_6115_1(Config) ->
undefined ->
ok;
_PI1 ->
- RefToOldP = erlang:check_process_code(Pid1, f1),
- ?line ?t:fail({"Pid1 still alive", RefToOldP})
+ RefToOldP1 = erlang:check_process_code(Pid1, f1),
+ ?t:fail({"Pid1 still alive", RefToOldP1})
end,
case process_info(Pid2) of
- PI2 when is_list(PI2) ->
- case erlang:check_process_code(Pid2, f2) of
- false ->
- ok;
- true ->
- ?line ?t:fail("Pid2 has ref to old code")
- end;
undefined ->
- ?line ?t:fail("Pid2 has died")
+ ok;
+ _PI2 ->
+ RefToOldP2 = erlang:check_process_code(Pid1, f2),
+ ?t:fail({"Pid2 still alive", RefToOldP2})
end,
?line file:set_cwd(CWD),
diff --git a/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl b/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
index b659e5d818..5399b33f19 100644
--- a/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
+++ b/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
@@ -1,12 +1,13 @@
-module(f1).
--export([start_fail/0, start_ok/0]).
+-export([start_a/0, start_b/0]).
-start_fail() ->
+start_a() ->
f2:start(fun() ->
- io:format("this does not work\n",[])
+ ok
end).
-start_ok() ->
+start_b() ->
f2:start(fun fun1/0).
+
fun1() ->
- io:format("this works\n",[]).
+ ok.
diff --git a/lib/tools/test/eprof_SUITE.erl b/lib/tools/test/eprof_SUITE.erl
index ecdbc5ce57..3283fa571f 100644
--- a/lib/tools/test/eprof_SUITE.erl
+++ b/lib/tools/test/eprof_SUITE.erl
@@ -183,8 +183,14 @@ eed(Config) when is_list(Config) ->
?line ok = eprof:log("eprof_SUITE_logfile"),
?line stopped = eprof:stop(),
?line ?t:timetrap_cancel(TTrap),
- S = lists:flatten(io_lib:format("~p times slower", [10*(T3-T2)/(T2-T1)])),
- {comment,S}.
+ try
+ S = lists:flatten(io_lib:format("~p times slower",
+ [10*(T3-T2)/(T2-T1)])),
+ {comment,S}
+ catch
+ error:badarith ->
+ {comment,"No time elapsed. Bad clock? Fast computer?"}
+ end.
ensure_eprof_stopped() ->
Pid = whereis(eprof),
diff --git a/lib/tools/test/eprof_SUITE_data/ed.script b/lib/tools/test/eprof_SUITE_data/ed.script
index 94531a9e98..fe1625bc50 100644
--- a/lib/tools/test/eprof_SUITE_data/ed.script
+++ b/lib/tools/test/eprof_SUITE_data/ed.script
@@ -1,5 +1,7 @@
H
r eed.erl
+1,$s/Created :/Skapad :/p
+/^cmd_line/,/^file/-1p
g/^[a-z][a-zA-Z_]*\(/i\
%%% -------------------------------------------------------------\
%%% A stupid function header.\
diff --git a/lib/tools/test/eprof_SUITE_data/eed.erl b/lib/tools/test/eprof_SUITE_data/eed.erl
index 0175abdd0e..520c5f3dd1 100644
--- a/lib/tools/test/eprof_SUITE_data/eed.erl
+++ b/lib/tools/test/eprof_SUITE_data/eed.erl
@@ -10,6 +10,8 @@
-export([edit/0, edit/1, file/1, cmd_line/1]).
+-compile({no_auto_import,[error/1]}).
+
-record(state, {dot = 0, % Line number of dot.
upto_dot = [], % Lines up to dot (reversed).
after_dot = [], % Lines after dot.
@@ -60,7 +62,7 @@ loop(St0) ->
ok;
{error, Reason} ->
loop(print_error(Reason, St1));
- St2 when record(St2, state) ->
+ St2 when is_record(St2, state) ->
loop(St2)
end.
@@ -68,7 +70,7 @@ command(Cmd, St) ->
case parse_command(Cmd, St) of
quit ->
quit;
- St1 when function(St1#state.print) ->
+ St1 when is_function(St1#state.print) ->
if
St1#state.dot /= 0 ->
print_current(St1);
@@ -76,7 +78,7 @@ command(Cmd, St) ->
ok
end,
St1#state{print=false};
- St1 when record(St1, state) ->
+ St1 when is_record(St1, state) ->
St1
end.
@@ -103,13 +105,13 @@ get_input([C|Rest], St, Result) ->
get_line1(Io, Prompt, Result) ->
get_line2(Io, io:get_line(Io, Prompt), Result).
-get_line2(Io, eof, []) ->
+get_line2(_Io, eof, []) ->
eof;
-get_line2(Io, eof, Result) ->
+get_line2(_Io, eof, Result) ->
lists:reverse(Result);
get_line2(Io, [$\\, $\n], Result) ->
get_line1(Io, '', [$\n|Result]);
-get_line2(Io, [$\n], Result) ->
+get_line2(_Io, [$\n], Result) ->
lists:reverse(Result, [$\n]);
get_line2(Io, [C|Rest], Result) ->
get_line2(Io, Rest, [C|Result]).
@@ -193,7 +195,7 @@ get_one1([$+|Rest], Sum, St) ->
get_one2({ok, 1, Rest}, 1, Sum, St);
get_one1([$-|Rest], Sum, St) ->
get_one2({ok, 1, Rest}, -1, Sum, St);
-get_one1(Cmd, false, St) ->
+get_one1(_Cmd, false, _St) ->
false;
get_one1(Cmd, Sum, St) ->
{ok, Sum, Cmd, St}.
@@ -222,13 +224,13 @@ get_address([$', Mark|Rest], St) when $a =< Mark, Mark =< $z ->
false ->
{ok, 0, Rest, St}
end;
-get_address([$'|Rest], State) ->
+get_address([$'|_Rest], _State) ->
error(bad_mark);
get_address([$/|Rest], State) ->
scan_forward($/, Rest, State);
-get_address([$?|Rest], State) ->
+get_address([$?|_Rest], _State) ->
error(not_implemented);
-get_address(Cmd, St) ->
+get_address(_Cmd, _St) ->
false.
scan_forward(End, Patt0, State) ->
@@ -238,8 +240,8 @@ scan_forward(End, Patt0, State) ->
scan_forward1(Dot+1, After, NewState, Rest).
scan_forward1(Linenum, [Line|Rest], State, RestCmd) ->
- case regexp:first_match(Line#line.contents, State#state.pattern) of
- {match, _, _} ->
+ case re:run(Line#line.contents, State#state.pattern, [{capture, none}]) of
+ match ->
{ok, Linenum, RestCmd, State};
nomatch ->
scan_forward1(Linenum+1, Rest, State, RestCmd)
@@ -254,13 +256,14 @@ scan_forward1(_, [], State, RestCmd) ->
Other
end.
-scan_forward2(0, [], State, RestCmd) ->
+scan_forward2(0, [], _State, _RestCmd) ->
false;
scan_forward2(Linenum, [Line|Rest], State, RestCmd) ->
case scan_forward2(Linenum-1, Rest, State, RestCmd) of
false ->
- case regexp:first_match(Line#line.contents, State#state.pattern) of
- {match, _, _} ->
+ case re:run(Line#line.contents, State#state.pattern,
+ [{capture, none}]) of
+ match ->
{ok, Linenum, RestCmd, State};
nomatch ->
false
@@ -296,7 +299,7 @@ parse_cmd_char($t, Cont) -> Cont(fun transpose_command/3, 2, dot);
parse_cmd_char($u, Cont) -> Cont(fun undo_command/3, 0, none);
parse_cmd_char($v, Cont) -> Cont(fun vglobal_command/3, 2, all);
parse_cmd_char($w, Cont) -> Cont(fun write_command/3, 2, all);
-parse_cmd_char(_, Cont) -> error(bad_command).
+parse_cmd_char(_, _Cont) -> error(bad_command).
execute_command(Fun, NumLines, Def, State, Nums, Rest) ->
Lines = check_lines(NumLines, Def, Nums, State),
@@ -380,7 +383,7 @@ change_command(Rest, Lines, St0) ->
%% (.,.)d - delete lines
-delete_command(Rest, [0, Last], St) ->
+delete_command(_Rest, [0, _Last], _St) ->
error(bad_linenum);
delete_command(Rest, [First, Last], St0) ->
St1 = check_trailing_p(Rest, save_for_undo(St0)),
@@ -396,7 +399,7 @@ delete(Left, St0) ->
%% e file - replace buffer with new file
-enter_command(Name, [], St) when St#state.modified == true ->
+enter_command(_Name, [], St) when St#state.modified == true ->
error(buffer_modified);
enter_command(Name, [], St0) ->
enter_always_command(Name, [], St0).
@@ -439,7 +442,7 @@ mark(Sense, [First, Last], St0) ->
St1 = move_to(Last, St0),
mark1(Sense, First-1, St1).
-mark1(Sense, First, St) when St#state.dot == First ->
+mark1(_Sense, First, St) when St#state.dot == First ->
St;
mark1(Sense, First, St) ->
[Line|Prev] = St#state.upto_dot,
@@ -507,16 +510,16 @@ help_always_command([], [], St) ->
%% (.)i - insert text
-insert_command(Rest, [0], State) ->
+insert_command(_Rest, [0], _State) ->
error(bad_linenum);
insert_command(Rest, [Line], State) ->
append_command(Rest, [Line-1], State).
%% (.)kx - mark line
-mark_command(_, [0], St) ->
+mark_command(_, [0], _St) ->
error(bad_linenum);
-mark_command([Mark|Rest], [Line], St) when $a =< Mark, Mark =< $z ->
+mark_command([Mark|_Rest], [_Line], _St) when $a =< Mark, Mark =< $z ->
error(not_implemented);
mark_command(_, _, _) ->
error(bad_mark).
@@ -528,12 +531,12 @@ list_command(Rest, Lines, St) ->
%% (.,.)m - move lines
-move_command(Cmd, [First, Last], St) ->
+move_command(_Cmd, [_First, _Last], _St) ->
error(not_implemented).
%% (.,.)t - copy lines
-transpose_command(Cmd, [First, Last], St) ->
+transpose_command(_Cmd, [_First, _Last], _St) ->
error(not_implemented).
%% (.,.)n - print lines with line numbers
@@ -604,39 +607,41 @@ read(After, Name, St0) ->
subst_command(_, [0, _], _) ->
error(bad_linenum);
-subst_command([$ |Cmd0], [First, Last], St0) ->
+subst_command([$ |_Cmd0], [_First, _Last], _St0) ->
error(bad_delimiter);
-subst_command([$\n|Cmd0], [First, Last], St0) ->
+subst_command([$\n|_Cmd0], [_First, _Last], _St0) ->
error(bad_delimiter);
subst_command([Sep|Cmd0], [First, Last], St0) ->
St1 = save_for_undo(St0),
{ok, Cmd1, St2} = get_pattern(Sep, Cmd0, St1),
{ok, Replacement, Cmd2} = get_replacement(Sep, Cmd1),
- {ok, Sub, Cmd3} = subst_check_gflag(Cmd2),
+ {ok, Opts, Cmd3} = subst_check_gflag(Cmd2),
St3 = check_trailing_p(Cmd3, St2),
- subst_command(Last-First+1, Sub, Replacement, move_to(First-1, St3), nomatch);
+ subst_command(Last-First+1, Opts, Replacement,
+ move_to(First-1, St3), nomatch);
subst_command([], _, _) ->
error(bad_delimiter).
subst_command(0, _, _, _, nomatch) ->
error(nomatch);
-subst_command(0, _, _, _, StLast) when record(StLast, state) ->
+subst_command(0, _, _, _, StLast) when is_record(StLast, state) ->
StLast;
-subst_command(Left, Sub, Repl, St0, LastMatch) ->
+subst_command(Left, Opts, Repl, St0, LastMatch) ->
St1 = next_line(St0),
[Line|_] = St1#state.upto_dot,
- case regexp:Sub(Line#line.contents, St1#state.pattern, Repl) of
- {ok, _, 0} ->
- subst_command(Left-1, Sub, Repl, St1, LastMatch);
- {ok, NewContents, _} ->
+ Contents = Line#line.contents,
+ case re:replace(Contents, St1#state.pattern, Repl, Opts) of
+ Contents ->
+ subst_command(Left-1, Opts, Repl, St1, LastMatch);
+ NewContents ->
%% XXX This doesn't work with marks.
St2 = delete_current_line(St1),
St3 = insert_line(NewContents, St2),
- subst_command(Left-1, Sub, Repl, St3, St3)
+ subst_command(Left-1, Opts, Repl, St3, St3)
end.
-subst_check_gflag([$g|Cmd]) -> {ok, gsub, Cmd};
-subst_check_gflag(Cmd) -> {ok, sub, Cmd}.
+subst_check_gflag([$g|Cmd]) -> {ok, [global,{return,list}], Cmd};
+subst_check_gflag(Cmd) -> {ok, [{return,list}], Cmd}.
%% u - undo
@@ -649,7 +654,7 @@ undo_command(_, _, _) ->
%% (1,$)w - write buffer to file
-write_command(Cmd, [First, Last], St) ->
+write_command(_Cmd, [_First, _Last], _St) ->
error(not_implemented).
@@ -721,7 +726,7 @@ get_pattern(End, Cmd, State) ->
get_pattern(End, [End|Rest], State, []) when State#state.pattern /= undefined ->
{ok, Rest, State};
get_pattern(End, [End|Rest], State, Result) ->
- case regexp:parse(lists:reverse(Result)) of
+ case re:compile(lists:reverse(Result)) of
{error, _} ->
error(bad_pattern);
{ok, Re} ->
@@ -754,7 +759,7 @@ check_trailing_p([$p], St) ->
St#state{print=fun(Line, _) -> io:put_chars(Line) end};
check_trailing_p([], State) ->
State;
-check_trailing_p(Other, State) ->
+check_trailing_p(_Other, _State) ->
error(garbage_after_command).
error(Reason) ->
@@ -765,9 +770,9 @@ match(State) when State#state.dot == 0 ->
match(State) ->
[Line|_] = State#state.upto_dot,
Re = State#state.pattern,
- case regexp:first_match(Line#line.contents, Re) of
- {match, _, _} -> true;
- nomatch -> false
+ case re:run(Line#line.contents, Re, [{capture, none}]) of
+ match -> true;
+ nomatch -> false
end.
skip_blanks([$ |Rest]) ->
diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl
index 0da6d4a9ea..1bc4c11b5d 100644
--- a/lib/tools/test/fprof_SUITE.erl
+++ b/lib/tools/test/fprof_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The 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,11 +191,17 @@ tail_seq(Config) when is_list(Config) ->
%%%---------------------------------------------------------------------
-create_file_slow(doc) ->
- ["Tests the create_file_slow benchmark"];
-create_file_slow(suite) ->
- [];
-create_file_slow(Config) when is_list(Config) ->
+%% Tests the create_file_slow benchmark.
+create_file_slow(Config) ->
+ case test_server:is_native(lists) orelse
+ test_server:is_native(file) of
+ true ->
+ {skip,"Native libs -- tracing does not work"};
+ false ->
+ do_create_file_slow(Config)
+ end.
+
+do_create_file_slow(Config) ->
?line Timetrap = ?t:timetrap(?t:seconds(40)),
?line PrivDir = ?config(priv_dir, Config),
?line TraceFile =
diff --git a/lib/tools/test/lcnt_SUITE.erl b/lib/tools/test/lcnt_SUITE.erl
index f2afa60e33..1bee6021ab 100644
--- a/lib/tools/test/lcnt_SUITE.erl
+++ b/lib/tools/test/lcnt_SUITE.erl
@@ -34,7 +34,7 @@
]).
%% Default timetrap timeout (set in init_per_testcase)
--define(default_timeout, ?t:minutes(2)).
+-define(default_timeout, ?t:minutes(4)).
init_per_suite(Config) when is_list(Config) ->
Config.
@@ -49,6 +49,7 @@ init_per_testcase(_Case, Config) ->
end_per_testcase(_Case, Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog),
+ catch lcnt:stop(),
ok.
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 2f83ab4995..fd3e111d8d 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -46,13 +46,14 @@
-export([
add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1,
replace/1, update/1, deprecated/1, trycatch/1,
- abstract_modules/1, fun_mfa/1, qlc/1]).
+ abstract_modules/1, fun_mfa/1, fun_mfa_r14/1,
+ fun_mfa_vars/1, qlc/1]).
-export([
analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]).
-export([
- format_error/1, otp_7423/1, otp_7831/1]).
+ format_error/1, otp_7423/1, otp_7831/1, otp_10192/1]).
-import(lists, [append/2, flatten/1, keysearch/3, member/2, sort/1, usort/1]).
@@ -82,10 +83,10 @@ groups() ->
{files, [],
[add, default, info, lib, read, read2, remove, replace,
update, deprecated, trycatch, abstract_modules, fun_mfa,
- qlc]},
+ fun_mfa_r14, fun_mfa_vars, qlc]},
{analyses, [],
[analyze, basic, md, q, variables, unused_locals]},
- {misc, [], [format_error, otp_7423, otp_7831]}].
+ {misc, [], [format_error, otp_7423, otp_7831, otp_10192]}].
init_per_suite(Config) ->
init(Config).
@@ -1771,6 +1772,88 @@ fun_mfa(Conf) when is_list(Conf) ->
?line ok = file:delete(Beam),
ok.
+%% Same as the previous test case, except that we use a BEAM file
+%% that was compiled by an R14 compiler to test backward compatibility.
+fun_mfa_r14(Conf) when is_list(Conf) ->
+ Dir = ?config(data_dir, Conf),
+ MFile = fname(Dir, "fun_mfa_r14"),
+
+ A = fun_mfa_r14,
+ {ok, _} = xref:start(s),
+ {ok, A} = xref:add_module(s, MFile, {warnings,false}),
+ {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]},
+ {{{A,t,0},{A,t,0}},[6]},
+ {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]},
+ {{{A,t1,0},{A,t,0}},[10]},
+ {{{A,t2,0},{A,t,0}},[14]},
+ {{{A,t3,0},{A,t3,0}},[17]}]} =
+ xref:q(s, "(Lin) E"),
+
+ ok = check_state(s),
+ xref:stop(s),
+
+ ok.
+
+%% fun M:F/A with varibles.
+fun_mfa_vars(Conf) when is_list(Conf) ->
+ Dir = ?copydir,
+ File = fname(Dir, "fun_mfa_vars.erl"),
+ MFile = fname(Dir, "fun_mfa_vars"),
+ Beam = fname(Dir, "fun_mfa_vars.beam"),
+ Test = <<"-module(fun_mfa_vars).
+
+ -export([t/1, t1/1, t2/3]).
+
+ t(Mod) ->
+ F = fun Mod:bar/2,
+ (F)(a, b).
+
+ t1(Name) ->
+ F = fun ?MODULE:Name/1,
+ (F)(a).
+
+ t2(Mod, Name, Arity) ->
+ F = fun Mod:Name/Arity,
+ (F)(a).
+
+ t3(Arity) ->
+ F = fun ?MODULE:t/Arity,
+ (F)(1, 2, 3).
+
+ t4(Mod, Name) ->
+ F = fun Mod:Name/3,
+ (F)(a, b, c).
+
+ t5(Mod, Arity) ->
+ F = fun Mod:t/Arity,
+ (F)().
+ ">>,
+
+ ok = file:write_file(File, Test),
+ A = fun_mfa_vars,
+ {ok, A} = compile:file(File, [report,debug_info,{outdir,Dir}]),
+ {ok, _} = xref:start(s),
+ {ok, A} = xref:add_module(s, MFile, {warnings,false}),
+ {ok, [{{{A,t,1},{'$M_EXPR','$F_EXPR',2}},[7]},
+ {{{A,t,1},{'$M_EXPR',bar,2}},[6]},
+ {{{A,t1,1},{'$M_EXPR','$F_EXPR',1}},[11]},
+ {{{A,t1,1},{A,'$F_EXPR',1}},[10]},
+ {{{A,t2,3},{'$M_EXPR','$F_EXPR',-1}},[14]},
+ {{{A,t2,3},{'$M_EXPR','$F_EXPR',1}},[15]},
+ {{{A,t3,1},{'$M_EXPR','$F_EXPR',3}},[19]},
+ {{{A,t3,1},{fun_mfa_vars,t,-1}},[18]},
+ {{{A,t4,2},{'$M_EXPR','$F_EXPR',3}},[22,23]},
+ {{{A,t5,2},{'$M_EXPR','$F_EXPR',0}},[27]},
+ {{{A,t5,2},{'$M_EXPR',t,-1}},[26]}]} =
+ xref:q(s, "(Lin) E"),
+
+ ok = check_state(s),
+ xref:stop(s),
+
+ ok = file:delete(File),
+ ok = file:delete(Beam),
+ ok.
+
qlc(suite) -> [];
qlc(doc) -> ["OTP-5195: A bug fix when using qlc:q/1,2."];
qlc(Conf) when is_list(Conf) ->
@@ -2058,17 +2141,17 @@ basic(Conf) when is_list(Conf) ->
?line {ok, _} = eval("components (Mod) E", [[m1,m2,m3]], S),
?line {ok, _} = eval("components closure (Mod) E", [[m1,m2,m3]], S),
?line {ok, _} = eval("condensation (Mod) E",
- [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]}], S),
+ [{[m1,m2,m3],[m17]}], S),
?line {ok, _} = eval("condensation closure (Mod) E",
- [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]}], S),
+ [{[m1,m2,m3],[m17]}], S),
?line {ok, _} = eval("condensation closure closure closure (Mod) E",
- [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]}], S),
+ [{[m1,m2,m3],[m17]}], S),
?line {ok, _} = eval("weak condensation (Mod) E",
[{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]},{[m17],[m17]}], S),
?line {ok, _} = eval("strict condensation (Mod) E",
[{[m1,m2,m3],[m17]}], S),
?line {ok, _} = eval("range condensation (Mod) E",
- [[m1,m2,m3],[m17]], S),
+ [[m17]], S),
?line {ok, _} = eval("domain condensation (Mod) E",
[[m1,m2,m3]], S),
@@ -2432,6 +2515,18 @@ otp_7831(Conf) when is_list(Conf) ->
?line xref:stop(Pid2),
ok.
+otp_10192(suite) -> [];
+otp_10192(doc) ->
+ ["OTP-10192. Allow filenames with character codes greater than 126."];
+otp_10192(Conf) when is_list(Conf) ->
+ PrivDir = ?privdir,
+ {ok, _Pid} = xref:start(s),
+ Dir = filename:join(PrivDir, "�"),
+ ok = file:make_dir(Dir),
+ {ok, []} = xref:add_directory(s, Dir),
+ xref:stop(s),
+ ok.
+
%%%
%%% Utilities
%%%
diff --git a/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam
new file mode 100644
index 0000000000..4645525690
--- /dev/null
+++ b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam
Binary files differ
diff --git a/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl
new file mode 100644
index 0000000000..293bd83a8b
--- /dev/null
+++ b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl
@@ -0,0 +1,18 @@
+-module(fun_mfa_r14).
+
+-export([t/0, t1/0, t2/0, t3/0]).
+
+t() ->
+ F = fun ?MODULE:t/0,
+ (F)().
+
+t1() ->
+ F = fun t/0,
+ (F)().
+
+t2() ->
+ fun ?MODULE:t/0().
+
+t3() ->
+ fun t3/0().
+
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 2d63a33554..788ee12900 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.6.6.5
+TOOLS_VSN = 2.6.8
diff --git a/lib/tv/doc/src/Makefile b/lib/tv/doc/src/Makefile
index f30e0307a9..e36dd84b73 100644
--- a/lib/tv/doc/src/Makefile
+++ b/lib/tv/doc/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
@@ -26,14 +26,6 @@ VSN=$(TV_VSN)
APPLICATION=tv
# ----------------------------------------------------
-# Include dependency
-# ----------------------------------------------------
-
-ifndef DOCSUPPORT
-include make.dep
-endif
-
-# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
@@ -89,32 +81,10 @@ EXTRA_FILES = \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-ifdef DOCSUPPORT
-
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-else
-
-TEX_FILES_BOOK = \
- $(BOOK_FILES:%.xml=%.tex)
-TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
- $(XML_APPLICATION_FILES:%.xml=%.tex)
-TEX_FILES_USERS_GUIDE = \
- $(XML_CHAPTER_FILES:%.xml=%.tex)
-
-TOP_PDF_FILE = tv-$(VSN).pdf
-TOP_PS_FILE = tv-$(VSN).ps
-
-$(TOP_PDF_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
-
-$(TOP_PS_FILE): book.dvi ../../vsn.mk
- $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
-
-endif
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -127,8 +97,6 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-ifdef DOCSUPPORT
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -144,31 +112,6 @@ clean clean_docs:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
-else
-
-ifeq ($(DOCTYPE),pdf)
-docs: pdf
-else
-ifeq ($(DOCTYPE),ps)
-docs: ps
-else
-docs: html gifs man
-endif
-endif
-
-pdf: $(TOP_PDF_FILE)
-
-ps: $(TOP_PS_FILE)
-
-html: $(HTML_FILES) gifs
-
-clean clean_docs clean_tex:
- rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
- rm -f $(HTML_FILES) $(MAN3_FILES)
- rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
- rm -f errs core *~ $(LATEX_CLEAN)
-endif
-
man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
@@ -181,41 +124,15 @@ debug opt:
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-ifdef DOCSUPPORT
-
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-
-else
-
-ifeq ($(DOCTYPE),pdf)
-release_docs_spec: pdf
- $(INSTALL_DIR) $(RELEASE_PATH)/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
-else
-ifeq ($(DOCTYPE),ps)
-release_docs_spec: ps
- $(INSTALL_DIR) $(RELEASE_PATH)/ps
- $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
-else
-release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
-endif
-endif
-
-endif
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/tv/doc/src/make.dep b/lib/tv/doc/src/make.dep
deleted file mode 100644
index 8437e320c6..0000000000
--- a/lib/tv/doc/src/make.dep
+++ /dev/null
@@ -1,32 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex table_visualizer_chapter.tex \
- tv.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: info_window.ps set_poll_int.ps tv_create_table.ps \
- tv_record_editor_mnesia.ps tv_row_marked.ps \
- tv_row_marked_popup.ps tv_search_result.ps \
- tv_search_window.ps tv_start.ps tv_start_mnesia.ps \
- tv_start_other_node.ps tv_start_pid_sorted.ps \
- tv_start_system.ps tv_start_system_unreadable.ps \
- tv_table_browser.ps tv_table_browser_updated.ps
-
diff --git a/lib/tv/doc/src/notes.xml b/lib/tv/doc/src/notes.xml
index 77a6a43d51..9217c018e9 100644
--- a/lib/tv/doc/src/notes.xml
+++ b/lib/tv/doc/src/notes.xml
@@ -30,6 +30,41 @@
</header>
<p>This document describes the changes made to the TV application.</p>
+<section><title>TV 2.1.4.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The GS applications is now deprecated and will be
+ removed in the R16 release. The following GS-based
+ applications have been superseded by the Observer
+ application and will removed in R16: Appmon, Pman,
+ Tv.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9907</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>TV 2.1.4.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>TV 2.1.4.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tv/doc/src/table_visualizer_chapter.xml b/lib/tv/doc/src/table_visualizer_chapter.xml
index 12efbe643c..8b757f82f3 100644
--- a/lib/tv/doc/src/table_visualizer_chapter.xml
+++ b/lib/tv/doc/src/table_visualizer_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,12 @@
<rev>C</rev>
<file>table_visualizer.xml</file>
</header>
+ <warning>
+ <p>
+ The TV application has been superseded by the Observer application.
+ TV will be removed in R16.
+ </p>
+ </warning>
<p>The TV, TV, is a tool that enables the user to examine
ETS and Mnesia tables on any (connected) node in the currently running Erlang
system. Once a certain table has been opened in the tool, the content may be
diff --git a/lib/tv/doc/src/tv.xml b/lib/tv/doc/src/tv.xml
index 84b9f8c33d..05dd60b34a 100644
--- a/lib/tv/doc/src/tv.xml
+++ b/lib/tv/doc/src/tv.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1997</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -36,6 +36,12 @@
<module>tv</module>
<modulesummary>TV graphically examines ETS and Mnesia tables. </modulesummary>
<description>
+ <warning>
+ <p>
+ The TV application has been superseded by the Observer application.
+ TV will be removed in R16.
+ </p>
+ </warning>
<p>TV enables the user to examine ETS and Mnesia tables. Once
a certain table has been opened in the tool, the content may be viewed at
various levels of detail. The content viewed may also be sorted, using any
diff --git a/lib/tv/priv/Makefile b/lib/tv/priv/Makefile
index 69e3e32c8a..73ea8f4ee9 100644
--- a/lib/tv/priv/Makefile
+++ b/lib/tv/priv/Makefile
@@ -64,8 +64,8 @@ clean:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(TOOLBAR_FILES) $(RELSYSDIR)/priv
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(TOOLBAR_FILES) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/tv/src/Makefile b/lib/tv/src/Makefile
index 457b9d38c4..f078e5dee1 100644
--- a/lib/tv/src/Makefile
+++ b/lib/tv/src/Makefile
@@ -126,10 +126,10 @@ docs:
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
+ $(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/tv/src/tv_db.erl b/lib/tv/src/tv_db.erl
index 201b4c0e6b..75537418b3 100644
--- a/lib/tv/src/tv_db.erl
+++ b/lib/tv/src/tv_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,10 @@
%%%*********************************************************************
-module(tv_db).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_db_search.erl b/lib/tv/src/tv_db_search.erl
index edd3c188e2..edfa57df04 100644
--- a/lib/tv/src/tv_db_search.erl
+++ b/lib/tv/src/tv_db_search.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,6 +21,18 @@
%%%
%%%*********************************************************************
-module(tv_db_search).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
@@ -244,10 +256,10 @@ get_entry_text() ->
string_to_regexp(Str) ->
- case regexp:parse(Str) of
+ case re:compile(Str) of
{ok, RegExp} ->
{ok, RegExp};
- _Error ->
+ {error, _Error} ->
case get(error_msg_mode) of
normal ->
{error, {not_a_regexp, "Please enter a regular expression!"}};
@@ -410,33 +422,11 @@ search_for_regexp(Pattern, Elem, ListAsStr) ->
lists:flatten(tv_io_lib:write(Elem))
end,
- case regexp:first_match(ListToSearch, Pattern) of
- {match, _, _} ->
+ case re:run(ListToSearch, Pattern, [{capture,none}]) of
+ match ->
found;
- _Other ->
+ nomatch ->
not_found
- %% The code below shall be used instead if it is desired to
- %% compare each *element* in the tuples to the regular expression,
- %% i.e., treat each element as a new line/string.
- %% The difference is most easily explained through an example:
- %% If we treat each tuple as a new line/string, the regular expression
- %% "^{win" will match the string "{win, 1, 2, 3}", but not the string
- %% "{1, {win,2}}".
- %% If we treat each element as a new line/string, the RE "^{win" will match
- %% both strings above.
-
- %% SearchList = tuple_to_list(Elem),
- %% case lists:dropwhile(
- %% fun(H) ->
- %% nomatch == regexp:first_match(lists:flatten(io_lib:write(H)),
- %% Pattern)
- %% end,
- %% SearchList) of
- %% [] ->
- %% not_found;
- %% _AnyList ->
- %% found
- %% end
end.
diff --git a/lib/tv/src/tv_etsread.erl b/lib/tv/src/tv_etsread.erl
index d3240ef513..32f111c9a1 100644
--- a/lib/tv/src/tv_etsread.erl
+++ b/lib/tv/src/tv_etsread.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,9 @@
-module(tv_etsread).
+-compile([{nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_info.erl b/lib/tv/src/tv_info.erl
index 7bc31e35cd..c744888c38 100644
--- a/lib/tv/src/tv_info.erl
+++ b/lib/tv/src/tv_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,14 @@
%%
%% %CopyrightEnd%
-module(tv_info).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_ip.erl b/lib/tv/src/tv_ip.erl
index aeec4e8f6d..9f66917362 100644
--- a/lib/tv/src/tv_ip.erl
+++ b/lib/tv/src/tv_ip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,12 @@
%%
%% %CopyrightEnd%
-module(tv_ip).
+-compile([{nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_main.erl b/lib/tv/src/tv_main.erl
index 283ba4c967..b6ffbd7c49 100644
--- a/lib/tv/src/tv_main.erl
+++ b/lib/tv/src/tv_main.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,6 +16,20 @@
%%
%% %CopyrightEnd%
-module(tv_main).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_mnesia_rpc.erl b/lib/tv/src/tv_mnesia_rpc.erl
index 4a75994145..b2434fcdd3 100644
--- a/lib/tv/src/tv_mnesia_rpc.erl
+++ b/lib/tv/src/tv_mnesia_rpc.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
diff --git a/lib/tv/src/tv_new_table.erl b/lib/tv/src/tv_new_table.erl
index 3d62b0548b..779835d78a 100644
--- a/lib/tv/src/tv_new_table.erl
+++ b/lib/tv/src/tv_new_table.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,6 +16,16 @@
%%
%% %CopyrightEnd%k
-module(tv_new_table).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_nodewin.erl b/lib/tv/src/tv_nodewin.erl
index 3999d201d8..8376c4a7aa 100644
--- a/lib/tv/src/tv_nodewin.erl
+++ b/lib/tv/src/tv_nodewin.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,6 +16,15 @@
%%
%% %CopyrightEnd%
-module(tv_nodewin).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pb.erl b/lib/tv/src/tv_pb.erl
index 78a27185dc..81e7e7e2d1 100644
--- a/lib/tv/src/tv_pb.erl
+++ b/lib/tv/src/tv_pb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,9 @@
%%
%% %CopyrightEnd%
-module(tv_pb).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}}]).
diff --git a/lib/tv/src/tv_pb_funcs.erl b/lib/tv/src/tv_pb_funcs.erl
index 87a4719bbd..24d1120597 100644
--- a/lib/tv/src/tv_pb_funcs.erl
+++ b/lib/tv/src/tv_pb_funcs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,12 @@
%%
%% %CopyrightEnd%
-module(tv_pb_funcs).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_pc.erl b/lib/tv/src/tv_pc.erl
index 50214fe06a..e0612e13eb 100644
--- a/lib/tv/src/tv_pc.erl
+++ b/lib/tv/src/tv_pc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,7 @@
-module(tv_pc).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pc_menu_handling.erl b/lib/tv/src/tv_pc_menu_handling.erl
index 16195bf91f..64a06743b7 100644
--- a/lib/tv/src/tv_pc_menu_handling.erl
+++ b/lib/tv/src/tv_pc_menu_handling.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,6 +25,10 @@
-module(tv_pc_menu_handling).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pd.erl b/lib/tv/src/tv_pd.erl
index ea14bf67b1..6c38148fdd 100644
--- a/lib/tv/src/tv_pd.erl
+++ b/lib/tv/src/tv_pd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,11 @@
-module(tv_pd).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pd_display.erl b/lib/tv/src/tv_pd_display.erl
index f5a30cb640..804180da16 100644
--- a/lib/tv/src/tv_pd_display.erl
+++ b/lib/tv/src/tv_pd_display.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,13 @@
%%%*********************************************************************
-module(tv_pd_display).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_pd_frames.erl b/lib/tv/src/tv_pd_frames.erl
index 4e091ac9f0..aab40e2bba 100644
--- a/lib/tv/src/tv_pd_frames.erl
+++ b/lib/tv/src/tv_pd_frames.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,8 @@
%%
%% %CopyrightEnd%
-module(tv_pd_frames).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,frame,2}}]).
diff --git a/lib/tv/src/tv_pd_scale.erl b/lib/tv/src/tv_pd_scale.erl
index c94e57f468..04af2bb981 100644
--- a/lib/tv/src/tv_pd_scale.erl
+++ b/lib/tv/src/tv_pd_scale.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,6 +24,8 @@
-module(tv_pd_scale).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,scale,2}}]).
diff --git a/lib/tv/src/tv_pg.erl b/lib/tv/src/tv_pg.erl
index ba8782392b..7194cfb756 100644
--- a/lib/tv/src/tv_pg.erl
+++ b/lib/tv/src/tv_pg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,7 @@
%%
%% %CopyrightEnd%
-module(tv_pg).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pg_gridfcns.erl b/lib/tv/src/tv_pg_gridfcns.erl
index 3d23c8a69f..d037b42294 100644
--- a/lib/tv/src/tv_pg_gridfcns.erl
+++ b/lib/tv/src/tv_pg_gridfcns.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,6 +16,10 @@
%%
%% %CopyrightEnd%
-module(tv_pg_gridfcns).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_poll_dialog.erl b/lib/tv/src/tv_poll_dialog.erl
index 8d41251266..e33d398898 100644
--- a/lib/tv/src/tv_poll_dialog.erl
+++ b/lib/tv/src/tv_poll_dialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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,13 @@
%%%*********************************************************************
-module(tv_poll_dialog).
-
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/1, init/2]).
diff --git a/lib/tv/src/tv_pw.erl b/lib/tv/src/tv_pw.erl
index 8b3186e090..5f88c9f1fd 100644
--- a/lib/tv/src/tv_pw.erl
+++ b/lib/tv/src/tv_pw.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The 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 @@
-module(tv_pw).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pw_window.erl b/lib/tv/src/tv_pw_window.erl
index 9cb5c879c0..81f29dc41c 100644
--- a/lib/tv/src/tv_pw_window.erl
+++ b/lib/tv/src/tv_pw_window.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,6 +23,10 @@
-module(tv_pw_window).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
diff --git a/lib/tv/src/tv_rec_edit.erl b/lib/tv/src/tv_rec_edit.erl
index e8f663073e..3f9ea8b5f5 100644
--- a/lib/tv/src/tv_rec_edit.erl
+++ b/lib/tv/src/tv_rec_edit.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,6 +16,16 @@
%%
%% %CopyrightEnd%
-module(tv_rec_edit).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_utils.erl b/lib/tv/src/tv_utils.erl
index fd232bde69..799e3994cb 100644
--- a/lib/tv/src/tv_utils.erl
+++ b/lib/tv/src/tv_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The 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,6 +16,9 @@
%%
%% %CopyrightEnd%
-module(tv_utils).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}}]).
diff --git a/lib/tv/vsn.mk b/lib/tv/vsn.mk
index 43e3d2ebce..1bb8ca30f8 100644
--- a/lib/tv/vsn.mk
+++ b/lib/tv/vsn.mk
@@ -1 +1 @@
-TV_VSN = 2.1.4.7
+TV_VSN = 2.1.4.9
diff --git a/lib/typer/src/Makefile b/lib/typer/src/Makefile
index 620b3ebb69..c3fae0ad42 100644
--- a/lib/typer/src/Makefile
+++ b/lib/typer/src/Makefile
@@ -101,10 +101,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(YRL_FILES) \
- $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(INSTALL_FILES) $(RELSYSDIR)/ebin
+ "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(INSTALL_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl
index f2a70f49b7..1e40b8926e 100644
--- a/lib/typer/src/typer.erl
+++ b/lib/typer/src/typer.erl
@@ -83,6 +83,7 @@ start() ->
{Args, Analysis} = process_cl_args(),
%% io:format("Args: ~p\n", [Args]),
%% io:format("Analysis: ~p\n", [Analysis]),
+ Timer = dialyzer_timing:init(false),
TrustedFiles = filter_fd(Args#args.trusted, [], fun is_erl_file/1),
Analysis2 = extract(Analysis, TrustedFiles),
All_Files = get_all_files(Args),
@@ -91,6 +92,7 @@ start() ->
Analysis4 = collect_info(Analysis3),
%% io:format("Final: ~p\n", [Analysis4#analysis.fms]),
TypeInfo = get_type_info(Analysis4),
+ dialyzer_timing:stop(Timer),
show_or_annotate(TypeInfo),
%% io:format("\nTyper analysis finished\n"),
erlang:halt(0).
@@ -119,9 +121,9 @@ extract(#analysis{macros = Macros,
{ok, RecDict} ->
Mod = list_to_atom(filename:basename(File, ".erl")),
case dialyzer_utils:get_spec_info(Mod, AbstractCode, RecDict) of
- {ok, SpecDict} ->
+ {ok, SpecDict, CbDict} ->
CS1 = dialyzer_codeserver:store_temp_records(Mod, RecDict, CS),
- dialyzer_codeserver:store_temp_contracts(Mod, SpecDict, CS1);
+ dialyzer_codeserver:store_temp_contracts(Mod, SpecDict, CbDict, CS1);
{error, Reason} -> compile_error([Reason])
end;
{error, Reason} -> compile_error([Reason])
@@ -181,7 +183,6 @@ get_type_info(#analysis{callgraph = CallGraph,
remove_external(CallGraph, PLT) ->
{StrippedCG0, Ext} = dialyzer_callgraph:remove_external(CallGraph),
- StrippedCG = dialyzer_callgraph:finalize(StrippedCG0),
case get_external(Ext, PLT) of
[] -> ok;
Externals ->
@@ -192,7 +193,7 @@ remove_external(CallGraph, PLT) ->
_ -> msg(io_lib:format(" Unknown types: ~p\n", [ExtTypes]))
end
end,
- StrippedCG.
+ StrippedCG0.
-spec get_external([{mfa(), mfa()}], plt()) -> [mfa()].
@@ -682,10 +683,10 @@ analyze_result(show_succ, Args, Analysis) ->
analyze_result(no_spec, Args, Analysis) ->
{Args, Analysis#analysis{no_spec = true}};
analyze_result({pa, Dir}, Args, Analysis) ->
- code:add_patha(Dir),
+ true = code:add_patha(Dir),
{Args, Analysis};
analyze_result({pz, Dir}, Args, Analysis) ->
- code:add_pathz(Dir),
+ true = code:add_pathz(Dir),
{Args, Analysis}.
%%--------------------------------------------------------------------
@@ -873,16 +874,16 @@ collect_one_file_info(File, Analysis) ->
Mod = cerl:concrete(cerl:module_name(Core)),
case dialyzer_utils:get_spec_info(Mod, AbstractCode, Records) of
{error, Reason} -> compile_error([Reason]);
- {ok, SpecInfo} ->
+ {ok, SpecInfo, CbInfo} ->
ExpTypes = get_exported_types_from_core(Core),
- analyze_core_tree(Core, Records, SpecInfo, ExpTypes,
- Analysis, File)
+ analyze_core_tree(Core, Records, SpecInfo, CbInfo,
+ ExpTypes, Analysis, File)
end
end
end
end.
-analyze_core_tree(Core, Records, SpecInfo, ExpTypes, Analysis, File) ->
+analyze_core_tree(Core, Records, SpecInfo, CbInfo, ExpTypes, Analysis, File) ->
Module = cerl:concrete(cerl:module_name(Core)),
TmpTree = cerl:from_records(Core),
CS1 = Analysis#analysis.codeserver,
@@ -894,14 +895,16 @@ analyze_core_tree(Core, Records, SpecInfo, ExpTypes, Analysis, File) ->
CS5 =
case Analysis#analysis.no_spec of
true -> CS4;
- false -> dialyzer_codeserver:store_temp_contracts(Module, SpecInfo, CS4)
+ false ->
+ dialyzer_codeserver:store_temp_contracts(Module, SpecInfo, CbInfo, CS4)
end,
OldExpTypes = dialyzer_codeserver:get_temp_exported_types(CS5),
MergedExpTypes = sets:union(ExpTypes, OldExpTypes),
CS6 = dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes, CS5),
Ex_Funcs = [{0,F,A} || {_,_,{F,A}} <- cerl:module_exports(Tree)],
- TmpCG = Analysis#analysis.callgraph,
- CG = dialyzer_callgraph:scan_core_tree(Tree, TmpCG),
+ CG = Analysis#analysis.callgraph,
+ {V, E} = dialyzer_callgraph:scan_core_tree(Tree, CG),
+ dialyzer_callgraph:add_edges(E, V, CG),
Fun = fun analyze_one_function/2,
All_Defs = cerl:module_defs(Tree),
Acc = lists:foldl(Fun, #tmpAcc{file = File, module = Module}, All_Defs),
diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk
index 9e73aed286..85a7c01424 100644
--- a/lib/typer/vsn.mk
+++ b/lib/typer/vsn.mk
@@ -1 +1 @@
-TYPER_VSN = 0.9.2
+TYPER_VSN = 0.9.3
diff --git a/lib/webtool/doc/src/Makefile b/lib/webtool/doc/src/Makefile
index 7b86752738..32269e9424 100644
--- a/lib/webtool/doc/src/Makefile
+++ b/lib/webtool/doc/src/Makefile
@@ -112,16 +112,16 @@ debug opt:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
- $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/webtool/doc/src/make.dep b/lib/webtool/doc/src/make.dep
deleted file mode 100644
index 87526b3f73..0000000000
--- a/lib/webtool/doc/src/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex start_webtool.tex \
- webtool.tex webtool_chapter.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml
index c58a440937..a56fdd7b6f 100644
--- a/lib/webtool/doc/src/notes.xml
+++ b/lib/webtool/doc/src/notes.xml
@@ -31,6 +31,21 @@
<p>This document describes the changes made to the Webtool
application.</p>
+<section><title>WebTool 0.8.9.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Miscellaneous documentation build updates</p>
+ <p>
+ Own Id: OTP-9813</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>WebTool 0.8.9</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile
index 6e1c6606fe..6af997c2bb 100644
--- a/lib/webtool/priv/Makefile
+++ b/lib/webtool/priv/Makefile
@@ -67,14 +67,14 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DIR) $(RELSYSDIR)/priv/root
- $(INSTALL_DIR) $(RELSYSDIR)/priv/root/conf
- $(INSTALL_DIR) $(RELSYSDIR)/priv/root/doc
- $(INSTALL_DATA) $(HTDOCS_FILES) $(RELSYSDIR)/priv/root/doc
- $(INSTALL_DATA) $(WEBSERVER_CONFIG_FILES) $(RELSYSDIR)/priv/root/conf
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_SCRIPT) $(SCRIPTS) $(RELSYSDIR)/priv/bin
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/root"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/conf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/doc"
+ $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv/root/doc"
+ $(INSTALL_DATA) $(WEBSERVER_CONFIG_FILES) "$(RELSYSDIR)/priv/root/conf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
+ $(INSTALL_SCRIPT) $(SCRIPTS) "$(RELSYSDIR)/priv/bin"
release_docs_spec:
diff --git a/lib/webtool/src/Makefile b/lib/webtool/src/Makefile
index 62845cd370..45e8b2a6f0 100644
--- a/lib/webtool/src/Makefile
+++ b/lib/webtool/src/Makefile
@@ -87,11 +87,11 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
- $(RELSYSDIR)/ebin
+ "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk
index 2643be866e..690f9a22cf 100644
--- a/lib/webtool/vsn.mk
+++ b/lib/webtool/vsn.mk
@@ -1 +1 @@
-WEBTOOL_VSN=0.8.9
+WEBTOOL_VSN=0.8.9.1
diff --git a/lib/wx/.gitignore b/lib/wx/.gitignore
index fd76f078d7..0fa427bfe5 100644
--- a/lib/wx/.gitignore
+++ b/lib/wx/.gitignore
@@ -1,2 +1,4 @@
test_log_*
wx_test_case_info
+api_gen/gl_man?
+doc/html/* \ No newline at end of file
diff --git a/lib/wx/Makefile b/lib/wx/Makefile
index 0bc89e08ad..1ec225930e 100644
--- a/lib/wx/Makefile
+++ b/lib/wx/Makefile
@@ -1,77 +1,41 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, 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 ./vsn.mk
-include ./config.mk
-SUBDIRS = src
-ifeq ($(CAN_BUILD_DRIVER), true)
-SUBDIRS += c_src
-endif
-SUBDIRS += examples doc/src
+
+ifdef TERTIARY_BOOTSTRAP
+ INSIDE_ERLSRC = true
+ SUBDIRS = src
+else # Normal build
+ include ./config.mk
+ SUBDIRS = src
+ ifeq ($(CAN_BUILD_DRIVER), true)
+ SUBDIRS += c_src
+ endif
+ SUBDIRS += examples doc/src
+endif #TERTIARY_BOOTSTRAP
+
CLEANDIRS = $(SUBDIRS) api_gen
-ifeq ($(INSIDE_ERLSRC),true)
-# we are inside erl src
# ----------------------------------------------------
# Default Subdir Targets
# ----------------------------------------------------
SUB_DIRECTORIES=$(SUBDIRS)
-include $(ERL_TOP)/make/otp_subdir.mk
-else
-# we are building standalone wxErlang
-all: opt
-
-opt:
- @mkdir -p ebin
- @mkdir -p priv
- @mkdir -p c_src/$(SYS_TYPE)
- @for d in $(SUBDIRS); do \
- if test ! -d $$d ; then \
- echo "=== Skipping subdir $$d" ; \
- else \
- (cd $$d && $(MAKE) $@) ; \
- fi ; \
- done
-# clean, removes beam, object and target files
-
-clean:
- rm -f *~
- @for d in $(CLEANDIRS); do \
- if test ! -d $$d ; then \
- echo "=== Skipping subdir $$d" ; \
- else \
- (cd $$d && $(MAKE) $@) ; \
- fi ; \
- done
-
-docs:
- (cd doc/src/ && $(MAKE) $@)
-
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-libdir = @libdir@
-
-install:
- escript ./install.es $(INSTALLDIR)
-
-release:
- escript ./install.es --create_release
-
-endif
+include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/wx/Notes b/lib/wx/Notes
deleted file mode 100644
index 3f48a3d4fb..0000000000
--- a/lib/wx/Notes
+++ /dev/null
@@ -1,60 +0,0 @@
-- [Dgud] Added wx_object implementation so user can create callback api
- as gen_server like process/objects which gets destroyed
- when the real objects are destroyed.
-- [Dgud] Added clienData to controlWithItems functions
-- [Dgud] Improved error handling, i.e. if 'This' is NULL gives a badarg
- and connect to non existing event type gives badarg.
-- [Dgud] Added wxCalendarEvent, wx*PickerEvents, wxTreeEvent wxNotebookEvent
-- [Dgud] Added wxStaticLine wxArtProvider wxClipboard
-- [Dgud] Reworked test directory
-- [RichardC] Fixed documentation Makefile
-- [Dgud] Fixed dialyzer warnings (Thanks Kostis)
- Fixed Bugs in wxBitmap and wxCursor
-- [RichardC] Fixed a lot of warnings in the demos and examples.
-- [Dgud] Fixed the internal event handling so that callbacks,
- and batch functions can not deadlock by using wxwidgets.
-- [Dgud] **Changed** backwards incompatible:
- Changed code generator so that enum and defines will be more
- stable in the future. This requires that your code will have
- to be recompiled.
-- [HarryH] wxMenuItem:GetBitmap/SetBitmap.
-- [HarryH] Started with the samples, menu.erl
-
-Old: 2008-05-26
-- [Dgud] **Changed** backwards incompatible:
- wxListBox, wxComboBox wxChoice wxCheckListBox
- function 'new': to use more optional values.
-- [Dgud] Added Notebook class
-- [Dgud] Added missing append/insert to ctrlWithItems
-- [Dgud] Added CalenderCtrl class
-- [Dgud] Added SizerItem functions
-- [Dgud] Add wxMDI* classes and wxLayoutAlgorithm
-- [Dgud] Added wxWindow:getHandle() -> integer() to be able to
- use platform dependent 3party libs
-- [Dgud] **Changed** backwards incompatible:
- #wx.user_data to #wx.userData to conform with wx api.
-- [Dgud] Fixed array of string bugs (in several functions).
-- [Dgud] Added data to command events
-- [Dgud] Added wxList(Ctrl) events
-
-- [Dgud] Fixed installer
-- [Dgud] **Changed** the wxEvtHandler:connect api
-- [Dgud] Fixed an event callback glitch.
-- [Dgud] Removed a memory leak, and optimized the object pointers.
-- [Dgud] Added wxMiniFrame and wxSash classes
-- [Dgud] Added wxStyledTextControl, requires larger binary but is nice
- for code viewing and editors.
-
-- [Dgud] Printing functionality, test implementation see sudoku demo
-- [Dgud] Added wxHtmlEasyPrinting, and classless functions to module wx_misc
-- [Dgud] Fixed Colors to actually work
-- [Dgud] Fixed enum guard tests
-
-
-- [Dgud] Fixed defines and added some global vars, incompatible
-- [Dgud] Fixed Colors to be {R,G,B,A} everywhere (optional in args)
-- [Dgud] Fixed memory cleaning and xrc (external dialog editor) support
-- [Dgud] Reworked event handling
-- [Dgud] Added GLU module and some functions
-- [Dgud] Fixed statusbar functions.
-- [Dgud] Prefix all records in wx.hrl with wx. \ No newline at end of file
diff --git a/lib/wx/README b/lib/wx/README
index e81f16681a..77cf6c6bda 100644
--- a/lib/wx/README
+++ b/lib/wx/README
@@ -1,4 +1,3 @@
-
REQUIREMENTS:
At least Erlang-R13B with smp enabled. It Requires unicode support.
@@ -10,17 +9,11 @@ REQUIREMENTS:
And I have given up on Solaris-8|9, wxWidgets on my old gtk version
doesn't run well, 7 of 10 wxWidgets examples seg fault.
Some early tests show that Solaris 10 works, though.
-
-INSTALLING:
- The prebuilt (windows and mac) version can be installed by invoking:
- install.es
- or
- /PATH/TO/ERL/bin/escript install.es
BUILDING:
You will need wxWidgets-2.8.*
- On mac I built wxwidgets with:
+ On mac (snow leopard) I built wxwidgets with:
mkdir MYBUILD; cd MYBUILD
../configure --with-opengl --enable-unicode --enable-graphics_ctx \
@@ -30,6 +23,8 @@ BUILDING:
cd contrib/src/stc/
make && make install
+ Or grab them prebuilt from macports.
+
On linux I have used the wxwidgets-libraries that came with
the distribution. It requires wxStyledTextControl which was
prebuilt on my linux, otherwise you have to build wxWidgets
@@ -48,30 +43,6 @@ BUILDING:
I havn't tested on cygwin at all.
You need to use werl on windows, erl (non-gui) hangs wxwidgets startup.
- make
- should work if erl, gcc and g++ and wx-config is found in path.
-
-
-HELPING:
- See TODO list.
- Use it, i.e. write code which tests the library, submit tests.
- See api_gen/Readme for improving the code generation.
- My C++ knowledge isn't the best, send patches and explain why
- so I can learn something.
-
-STATUS:
- Testing I havn't done more testing than the code in test directory.
- So please help by testing and writing test suites.
- Most classes needs some argument tweaking (in wxapi.conf) to
- work as expected, but I havn't read all the documentation and
- gone through every argument on every function.
-
- See (and run) the demo in the examples directory.
-
- This library is (currently) a driver, so if the you (or I) make errors,
- such as accessing deleted objects or other things wxWidgets didn't
- expect you to do, erlang will crash hard.
-
Cheers
Dan Gudmundsson
diff --git a/lib/wx/TODO b/lib/wx/TODO
deleted file mode 100644
index bf5553b9be..0000000000
--- a/lib/wx/TODO
+++ /dev/null
@@ -1,30 +0,0 @@
-
-Improve documentation.
-
-Fix all fixme's :-)
-
-Makefiles and configure tests
- Can always be improved, especially mine.
-
-Port programs instead of drivers.
- Another backend which doesn't crash the emulator during
- developing/testing or at customer site,
- Option to wx:new().
-
-Cleanup the code!!!!
-
-Platform specific classes/functions
- wxPrinterDC for example is mac and windows only.
-
-Add user_data now that erl_driver can unpack term_binaries.
-
-Add missing clases, especially the ones used in the api:
- wxDropTarget wxXmlResourceHandler wxGLContext
-
-Testing and debugging.
-
-API stuff: (Stuff I've or others have seen that I don't have time to fix right now)
-
-================
-
-Patch wxMac with CGwarpMouseCursorPosition \ No newline at end of file
diff --git a/lib/wx/aclocal.m4 b/lib/wx/aclocal.m4
new file mode 100644
index 0000000000..a76594d86f
--- /dev/null
+++ b/lib/wx/aclocal.m4
@@ -0,0 +1,1872 @@
+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
+
+AC_DEFUN(LM_PRECIOUS_VARS,
+[
+
+dnl ERL_TOP
+AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory])
+
+dnl Tools
+AC_ARG_VAR(CC, [C compiler])
+AC_ARG_VAR(CFLAGS, [C compiler flags])
+AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags])
+AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler])
+AC_ARG_VAR(CPP, [C/C++ preprocessor])
+AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags])
+AC_ARG_VAR(CXX, [C++ compiler])
+AC_ARG_VAR(CXXFLAGS, [C++ compiler flags])
+AC_ARG_VAR(LD, [linker (is often overridden by configure)])
+AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overriden by configure)])
+AC_ARG_VAR(LIBS, [libraries])
+AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)])
+AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)])
+AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)])
+AC_ARG_VAR(RANLIB, [ranlib])
+AC_ARG_VAR(AR, [ar])
+AC_ARG_VAR(GETCONF, [getconf])
+
+dnl Cross system root
+AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)])
+
+dnl Cross compilation variables
+AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for retrieving process CPU time: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)])
+
+])
+
+AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
+[
+erl_xcomp_without_sysroot=no
+if test "$cross_compiling" = "yes"; then
+ test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes
+ test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot"
+else
+ erl_xcomp_sysroot=
+ erl_xcomp_isysroot=
+fi
+])
+
+AC_DEFUN(LM_CHECK_GETCONF,
+[
+if test "$cross_compiling" != "yes"; then
+ AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false])
+else
+ dnl First check if we got a `<HOST>-getconf' in $PATH
+ host_getconf="$host_alias-getconf"
+ AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false])
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ dnl We should perhaps give up if we have'nt found it by now, but at
+ dnl least in one Tilera MDE `getconf' under sysroot is a bourne
+ dnl shell script which we can use. We try to find `<HOST>-getconf'
+ dnl or `getconf' under sysconf, but only under sysconf since
+ dnl `getconf' in $PATH is almost guaranteed to be for the build
+ dnl machine.
+ GETCONF=
+ prfx="$erl_xcomp_sysroot"
+ AC_PATH_TOOL([GETCONF], [getconf], [false],
+ ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
+ fi
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_WINDOWS_ENVIRONMENT
+dnl
+dnl
+dnl Tries to determine thw windows build environment, i.e.
+dnl MIXED_CYGWIN_VC or MIXED_MSYS_VC
+dnl
+
+AC_DEFUN(LM_WINDOWS_ENVIRONMENT,
+[
+MIXED_CYGWIN=no
+MIXED_MSYS=no
+
+AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment)
+if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_CYGWIN_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
+ elif test -x /usr/bin/msysinfo; then
+ CFLAGS="-O2"
+ MIXED_MSYS=yes
+ AC_MSG_RESULT([MSYS and VC])
+ MIXED_MSYS_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_VC=no
+ MIXED_MSYS_VC=no
+fi
+AC_SUBST(MIXED_CYGWIN_VC)
+AC_SUBST(MIXED_MSYS_VC)
+
+MIXED_VC=no
+if test "x$MIXED_MSYS_VC" = "xyes" -o "x$MIXED_CYGWIN_VC" = "xyes" ; then
+ MIXED_VC=yes
+fi
+
+AC_SUBST(MIXED_VC)
+
+if test "x$MIXED_MSYS" != "xyes"; then
+ AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
+ if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
+ if test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([yes])
+ MIXED_CYGWIN_MINGW=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
+ else
+ AC_MSG_RESULT([undeterminable])
+ AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ MIXED_CYGWIN_MINGW=no
+ fi
+else
+ MIXED_CYGWIN_MINGW=no
+fi
+AC_SUBST(MIXED_CYGWIN_MINGW)
+
+AC_MSG_CHECKING(if we mix cygwin with any native compiler)
+if test "X$MIXED_CYGWIN" = "Xyes"; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_CYGWIN)
+
+AC_MSG_CHECKING(if we mix msys with another native compiler)
+if test "X$MIXED_MSYS" = "Xyes" ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MIXED_MSYS)
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_FIND_EMU_CC
+dnl
+dnl
+dnl Tries fairly hard to find a C compiler that can handle jump tables.
+dnl Defines the @EMU_CC@ variable for the makefiles and
+dnl inserts NO_JUMP_TABLE in the header if one cannot be found...
+dnl
+
+AC_DEFUN(LM_FIND_EMU_CC,
+ [AC_CACHE_CHECK(for a compiler that handles jumptables,
+ ac_cv_prog_emu_cc,
+ [
+AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+lbl1:
+ return 1;
+lbl2:
+ return 2;
+],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+
+if test $ac_cv_prog_emu_cc = no; then
+ for ac_progname in emu_cc.sh gcc-4.2 gcc; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_progname; then
+ ac_cv_prog_emu_cc=$ac_dir/$ac_progname
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ if test $ac_cv_prog_emu_cc != no; then
+ break
+ fi
+ done
+fi
+
+if test $ac_cv_prog_emu_cc != no; then
+ save_CC=$CC
+ save_CFLAGS=$CFLAGS
+ save_CPPFLAGS=$CPPFLAGS
+ CC=$ac_cv_prog_emu_cc
+ CFLAGS=""
+ CPPFLAGS=""
+ AC_TRY_COMPILE([],[
+#if defined(__clang_major__) && __clang_major__ >= 3
+ /* clang 3.x or later is fine */
+#elif defined(__llvm__)
+#error "this version of llvm is unable to correctly compile beam_emu.c"
+#endif
+ __label__ lbl1;
+ __label__ lbl2;
+ int x = magic();
+ static void *jtab[2];
+
+ jtab[0] = &&lbl1;
+ jtab[1] = &&lbl2;
+ goto *jtab[x];
+ lbl1:
+ return 1;
+ lbl2:
+ return 2;
+ ],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no)
+ CC=$save_CC
+ CFLAGS=$save_CFLAGS
+ CPPFLAGS=$save_CPPFLAGS
+fi
+])
+if test $ac_cv_prog_emu_cc = no; then
+ AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables])
+ EMU_CC=$CC
+else
+ EMU_CC=$ac_cv_prog_emu_cc
+fi
+AC_SUBST(EMU_CC)
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_INSTALL_DIR
+dnl
+dnl This macro may be used by any OTP application.
+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
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_PERL5
+dnl
+dnl Try to find perl version 5. If found set PERL to the absolute path
+dnl of the program, if not found set PERL to false.
+dnl
+dnl On some systems /usr/bin/perl is perl 4 and e.g.
+dnl /usr/local/bin/perl is perl 5. We try to handle this case by
+dnl putting a couple of
+dnl Tries to handle the case that there are two programs called perl
+dnl in the path and one of them is perl 5 and the other isn't.
+dnl
+AC_DEFUN(LM_PROG_PERL5,
+[AC_PATH_PROGS(PERL, perl5 perl, false,
+ /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH})
+changequote(, )dnl
+dnl[ That bracket is needed to balance the right bracket below
+if test "$PERL" = "false" || $PERL -e 'exit ($] >= 5)'; then
+changequote([, ])dnl
+ ac_cv_path_PERL=false
+ PERL=false
+dnl AC_MSG_WARN(perl version 5 not found)
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SO_BSDCOMPAT
+dnl
+dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux)
+dnl
+AC_DEFUN(LM_DECL_SO_BSDCOMPAT,
+[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat,
+AC_TRY_COMPILE([#include <sys/socket.h>], [int i = SO_BSDCOMPAT;],
+ ac_cv_decl_so_bsdcompat=yes,
+ ac_cv_decl_so_bsdcompat=no))
+
+case "${ac_cv_decl_so_bsdcompat}" in
+ "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[],
+ [Define if you have SO_BSDCOMPAT flag on sockets]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_INADDR_LOOPBACK
+dnl
+dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default
+dnl
+
+AC_DEFUN(LM_DECL_INADDR_LOOPBACK,
+[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h],
+ ac_cv_decl_inaddr_loopback,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>], [int i = INADDR_LOOPBACK;],
+ac_cv_decl_inaddr_loopback=yes, ac_cv_decl_inaddr_loopback=no)
+])
+
+if test ${ac_cv_decl_inaddr_loopback} = no; then
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h],
+ ac_cv_decl_inaddr_loopback_rpc,
+ AC_TRY_COMPILE([#include <rpc/types.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_rpc=yes,
+ ac_cv_decl_inaddr_loopback_rpc=no))
+
+ case "${ac_cv_decl_inaddr_loopback_rpc}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
+ [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h],
+ ac_cv_decl_inaddr_loopback_winsock2,
+ AC_TRY_COMPILE([#define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>],
+ [int i = INADDR_LOOPBACK;],
+ ac_cv_decl_inaddr_loopback_winsock2=yes,
+ ac_cv_decl_inaddr_loopback_winsock2=no))
+ case "${ac_cv_decl_inaddr_loopback_winsock2}" in
+ "yes" )
+ AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[],
+ [Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;;
+ * )
+ # couldn't find it anywhere
+ AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[],
+ [Define if you don't have a definition of INADDR_LOOPBACK]) ;;
+ esac;;
+ esac
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_SOCKADDR_SA_LEN
+dnl
+dnl Check if the sockaddr structure has the field sa_len
+dnl
+
+AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN,
+[AC_CACHE_CHECK([whether struct sockaddr has sa_len field],
+ ac_cv_struct_sockaddr_sa_len,
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>], [struct sockaddr s; s.sa_len = 10;],
+ ac_cv_struct_sockaddr_sa_len=yes, ac_cv_struct_sockaddr_sa_len=no))
+
+dnl FIXME convbreak
+case ${ac_cv_struct_sockaddr_sa_len} in
+ "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;;
+ *) ;;
+esac
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_STRUCT_EXCEPTION
+dnl
+dnl Check to see whether the system supports the matherr function
+dnl and its associated type "struct exception".
+dnl
+
+AC_DEFUN(LM_STRUCT_EXCEPTION,
+[AC_CACHE_CHECK([for struct exception (and matherr function)],
+ ac_cv_struct_exception,
+AC_TRY_COMPILE([#include <math.h>],
+ [struct exception x; x.type = DOMAIN; x.type = SING;],
+ ac_cv_struct_exception=yes, ac_cv_struct_exception=no))
+
+case "${ac_cv_struct_exception}" in
+ "yes" ) AC_DEFINE(USE_MATHERR,[1],[Define if you have matherr() function and struct exception type]) ;;
+ * ) ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_IPV6
+dnl
+dnl Check for ipv6 support and what the in6_addr structure is called.
+dnl (early linux used in_addr6 insted of in6_addr)
+dnl
+
+AC_DEFUN(LM_SYS_IPV6,
+[AC_MSG_CHECKING(for IP version 6 support)
+AC_CACHE_VAL(ac_cv_sys_ipv6_support,
+[ok_so_far=yes
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no)
+
+if test $ok_so_far = yes; then
+ ac_cv_sys_ipv6_support=yes
+else
+ AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif],
+ [struct in_addr6 a6; struct sockaddr_in6 s6;],
+ ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no)
+fi
+])dnl
+
+dnl
+dnl Have to use old style AC_DEFINE due to BC with old autoconf.
+dnl
+
+case ${ac_cv_sys_ipv6_support} in
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ ;;
+ in_addr6)
+ AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)])
+ AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present])
+ AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this])
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_SYS_MULTICAST
+dnl
+dnl Check for multicast support. Only checks for multicast options in
+dnl setsockopt(), no check is performed that multicasting actually works.
+dnl If options are found defines HAVE_MULTICAST_SUPPORT
+dnl
+
+AC_DEFUN(LM_SYS_MULTICAST,
+[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
+[AC_EGREP_CPP(yes,
+[#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP)
+yes
+#endif
+], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)])
+if test $ac_cv_sys_multicast_support = yes; then
+ AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1],
+ [Define if setsockopt() accepts multicast options])
+fi
+])dnl
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_DECL_SYS_ERRLIST
+dnl
+dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared
+dnl in a system header file, stdio.h or errno.h.
+dnl
+
+AC_DEFUN(LM_DECL_SYS_ERRLIST,
+[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h],
+ ac_cv_decl_sys_errlist,
+[AC_TRY_COMPILE([#include <stdio.h>
+#include <errno.h>], [char *msg = *(sys_errlist + 1);],
+ ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)])
+if test $ac_cv_decl_sys_errlist = yes; then
+ AC_DEFINE(SYS_ERRLIST_DECLARED,[],
+ [define if the variable sys_errlist is declared in a system header file])
+fi
+])
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes
+dnl [, action-if-found [, action-if-not-found]]] )
+dnl
+dnl Checks if the declaration "declaration" of "funname" conflicts
+dnl with the header files idea of how the function should be
+dnl declared. It is useful on systems which lack prototypes and you
+dnl need to provide your own (e.g. when you want to take the address
+dnl of a function). The 4'th argument is expanded if conflicting,
+dnl the 5'th argument otherwise
+dnl
+dnl
+
+AC_DEFUN(LM_CHECK_FUNC_DECL,
+[AC_MSG_CHECKING([for conflicting declaration of $1])
+AC_CACHE_VAL(ac_cv_func_decl_$1,
+[AC_TRY_COMPILE([#include <stdio.h>
+$3],[$2
+char *c = (char *)$1;
+], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")])
+if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$4], , :, [$4])
+else
+ AC_MSG_RESULT(no)
+ifelse([$5], , , [$5
+])dnl
+fi
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl AC_DOUBLE_MIDDLE_ENDIAN
+dnl
+dnl Checks whether doubles are represented in "middle-endian" format.
+dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly,
+dnl as well as DOUBLE_MIDDLE_ENDIAN.
+dnl
+dnl
+
+AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN],
+[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian,
+[# It does not; compile a test program.
+AC_RUN_IFELSE(
+[AC_LANG_SOURCE([[#include <stdlib.h>
+
+int
+main(void)
+{
+ int i = 0;
+ int zero = 0;
+ int bigendian;
+ int zero_index = 0;
+
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+
+ /* we'll use the one with 32-bit words */
+ union
+ {
+ double d;
+ unsigned int c[2];
+ } vint;
+
+ union
+ {
+ double d;
+ unsigned long c[2];
+ } vlong;
+
+ union
+ {
+ double d;
+ unsigned short c[2];
+ } vshort;
+
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ u.l = 1;
+ bigendian = (u.c[sizeof (long int) - 1] == 1);
+
+ zero_index = bigendian ? 1 : 0;
+
+ vint.d = 1.0;
+ vlong.d = 1.0;
+ vshort.d = 1.0;
+
+ if (sizeof(unsigned int) == 4)
+ {
+ if (vint.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned long) == 4)
+ {
+ if (vlong.c[zero_index] != 0)
+ zero = 1;
+ }
+ else if (sizeof(unsigned short) == 4)
+ {
+ if (vshort.c[zero_index] != 0)
+ zero = 1;
+ }
+
+ exit (zero);
+}
+]])],
+ [ac_cv_c_double_middle_endian=no],
+ [ac_cv_c_double_middle_endian=yes],
+ [ac_cv_c_double_middle=unknown])])
+case $ac_cv_c_double_middle_endian in
+ yes)
+ m4_default([$1],
+ [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1,
+ [Define to 1 if your processor stores the words in a double in
+ middle-endian format (like some ARMs).])]) ;;
+ no)
+ $2 ;;
+ *)
+ m4_default([$3],
+ [AC_MSG_WARN([unknown double endianness
+presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;;
+esac
+])# AC_C_DOUBLE_MIDDLE_ENDIAN
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_CHECK_THR_LIB
+dnl
+dnl This macro may be used by any OTP application.
+dnl
+dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also
+dnl checks for some pthread headers which will appear in DEFS or config.h.
+dnl
+
+AC_DEFUN(LM_CHECK_THR_LIB,
+[
+
+NEED_NPTL_PTHREAD_H=no
+
+dnl win32?
+AC_MSG_CHECKING([for native win32 threads])
+if test "X$host_os" = "Xwin32"; then
+ AC_MSG_RESULT(yes)
+ THR_DEFS="-DWIN32_THREADS"
+ THR_LIBS=
+ THR_LIB_NAME=win32_threads
+ THR_LIB_TYPE=win32_threads
+else
+ AC_MSG_RESULT(no)
+ THR_DEFS=
+ THR_LIBS=
+ THR_LIB_NAME=
+ THR_LIB_TYPE=posix_unknown
+
+dnl Try to find POSIX threads
+
+dnl The usual pthread lib...
+ AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
+
+dnl FreeBSD has pthreads in special c library, c_r...
+ if test "x$THR_LIBS" = "x"; then
+ AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r")
+ fi
+
+dnl On ofs1 the '-pthread' switch should be used
+ if test "x$THR_LIBS" = "x"; then
+ AC_MSG_CHECKING([if the '-pthread' switch can be used])
+ saved_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -pthread"
+ AC_TRY_LINK([#include <pthread.h>],
+ pthread_create((void*)0,(void*)0,(void*)0,(void*)0);,
+ [THR_DEFS="-pthread"
+ THR_LIBS="-pthread"])
+ CFLAGS=$saved_cflags
+ if test "x$THR_LIBS" != "x"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ if test "x$THR_LIBS" != "x"; then
+ THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
+ THR_LIB_NAME=pthread
+ case $host_os in
+ solaris*)
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
+ linux*)
+ THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
+
+ LM_CHECK_GETCONF
+ AC_MSG_CHECKING(for Native POSIX Thread Library)
+ libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
+ if test $? -eq 0; then
+ case "$libpthr_vsn" in
+ *nptl*|*NPTL*) nptl=yes;;
+ *) nptl=no;;
+ esac
+ elif test "$cross_compiling" = "yes"; then
+ case "$erl_xcomp_linux_nptl" in
+ "") nptl=cross;;
+ yes|no) nptl=$erl_xcomp_linux_nptl;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);;
+ esac
+ else
+ nptl=no
+ fi
+ AC_MSG_RESULT($nptl)
+ if test $nptl = cross; then
+ nptl=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $nptl = yes; then
+ THR_LIB_TYPE=posix_nptl
+ need_nptl_incldir=no
+ AC_CHECK_HEADER(nptl/pthread.h,
+ [need_nptl_incldir=yes
+ NEED_NPTL_PTHREAD_H=yes])
+ if test $need_nptl_incldir = yes; then
+ # Ahh...
+ nptl_path="$C_INCLUDE_PATH:$CPATH"
+ if test X$cross_compiling != Xyes; then
+ nptl_path="$nptl_path:/usr/local/include:/usr/include"
+ else
+ IROOT="$erl_xcomp_isysroot"
+ test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot"
+ test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot])
+ nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include"
+ fi
+ nptl_ws_path=
+ save_ifs="$IFS"; IFS=":"
+ for dir in $nptl_path; do
+ if test "x$dir" != "x"; then
+ nptl_ws_path="$nptl_ws_path $dir"
+ fi
+ done
+ IFS=$save_ifs
+ nptl_incldir=
+ for dir in $nptl_ws_path; do
+ AC_CHECK_HEADER($dir/nptl/pthread.h,
+ nptl_incldir=$dir/nptl)
+ if test "x$nptl_incldir" != "x"; then
+ THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
+ break
+ fi
+ done
+ if test "x$nptl_incldir" = "x"; then
+ AC_MSG_ERROR(Failed to locate nptl system include directory)
+ fi
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need THR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $THR_DEFS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h,
+ AC_DEFINE(HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ fi
+fi
+
+])
+
+AC_DEFUN(ERL_INTERNAL_LIBS,
+[
+
+ERTS_INTERNAL_X_LIBS=
+
+AC_CHECK_LIB(kstat, kstat_open,
+[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat])
+ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"])
+
+AC_SUBST(ERTS_INTERNAL_X_LIBS)
+
+])
+
+AC_DEFUN(ETHR_CHK_SYNC_OP,
+[
+ AC_MSG_CHECKING([for $3-bit $1()])
+ case "$2" in
+ "1") sync_call="$1(&var);";;
+ "2") sync_call="$1(&var, ($4) 0);";;
+ "3") sync_call="$1(&var, ($4) 0, ($4) 0);";;
+ esac
+ have_sync_op=no
+ AC_TRY_LINK([],
+ [
+ $4 res;
+ volatile $4 var;
+ res = $sync_call
+ ],
+ [have_sync_op=yes])
+ test $have_sync_op = yes && $5
+ AC_MSG_RESULT([$have_sync_op])
+])
+
+AC_DEFUN(ETHR_CHK_INTERLOCKED,
+[
+ ilckd="$1"
+ AC_MSG_CHECKING([for ${ilckd}()])
+ case "$2" in
+ "1") ilckd_call="${ilckd}(var);";;
+ "2") ilckd_call="${ilckd}(var, ($3) 0);";;
+ "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";;
+ "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
+ esac
+ have_interlocked_op=no
+ AC_TRY_LINK(
+ [
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <intrin.h>
+ ],
+ [
+ volatile $3 *var;
+ volatile $3 arr[2];
+
+ $ilckd_call
+ return 0;
+ ],
+ [have_interlocked_op=yes])
+ test $have_interlocked_op = yes && $4
+ AC_MSG_RESULT([$have_interlocked_op])
+])
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_FIND_ETHR_LIB
+dnl
+dnl NOTE! This macro may be changed at any time! Should *only* be used by
+dnl ERTS!
+dnl
+dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link
+dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS
+dnl except that the ethread lib itself is not included), ETHR_DEFS to
+dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the
+dnl thread library which the ethread library is based on, and ETHR_LIB_NAME
+dnl to the name of the library where the ethread implementation is located.
+dnl ERL_FIND_ETHR_LIB currently searches for 'pthreads', and
+dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS,
+dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the
+dnl empty string.
+dnl
+
+AC_DEFUN(ERL_FIND_ETHR_LIB,
+[
+
+LM_CHECK_THR_LIB
+ERL_INTERNAL_LIBS
+
+ethr_have_native_atomics=no
+ethr_have_native_spinlock=no
+ETHR_THR_LIB_BASE="$THR_LIB_NAME"
+ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE"
+ETHR_DEFS="$THR_DEFS"
+ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS"
+ETHR_LIBS=
+ETHR_LIB_NAME=
+
+ethr_modified_default_stack_size=
+
+dnl Name of lib where ethread implementation is located
+ethr_lib_name=ethread
+
+case "$THR_LIB_NAME" in
+
+ win32_threads)
+ ETHR_THR_LIB_BASE_DIR=win
+ # * _WIN32_WINNT >= 0x0400 is needed for
+ # TryEnterCriticalSection
+ # * _WIN32_WINNT >= 0x0403 is needed for
+ # InitializeCriticalSectionAndSpinCount
+ # The ethread lib will refuse to build if _WIN32_WINNT < 0x0403.
+ #
+ # -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it
+ # and save it in ETHR_DEFS.
+ found_win32_winnt=no
+ for cppflag in $CPPFLAGS; do
+ case $cppflag in
+ -DWINVER*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ ;;
+ -D_WIN32_WINNT*)
+ ETHR_DEFS="$ETHR_DEFS $cppflag"
+ found_win32_winnt=yes
+ ;;
+ *)
+ ;;
+ esac
+ done
+ if test $found_win32_winnt = no; then
+ AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS])
+ fi
+
+ AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads])
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()]))
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()]))
+ test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
+
+ ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()]))
+
+ test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes
+ ;;
+
+ pthread)
+ ETHR_THR_LIB_BASE_DIR=pthread
+ AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
+ case $host_os in
+ openbsd*)
+ # The default stack size is insufficient for our needs
+ # on OpenBSD. We increase it to 256 kilo words.
+ ethr_modified_default_stack_size=256;;
+ linux*)
+ ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE"
+
+ if test X$cross_compiling = Xyes; then
+ case X$erl_xcomp_linux_usable_sigusrx in
+ X) usable_sigusrx=cross;;
+ Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);;
+ esac
+ case X$erl_xcomp_linux_usable_sigaltstack in
+ X) usable_sigaltstack=cross;;
+ Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);;
+ esac
+ else
+ # FIXME: Test for actual problems instead of kernel versions
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-1]]|2.[[0-1]].*)
+ usable_sigusrx=no
+ usable_sigaltstack=no;;
+ 2.[[2-3]]|2.[[2-3]].*)
+ usable_sigusrx=yes
+ usable_sigaltstack=no;;
+ *)
+ usable_sigusrx=yes
+ usable_sigaltstack=yes;;
+ esac
+ fi
+
+ AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used)
+ AC_MSG_RESULT($usable_sigusrx)
+ if test $usable_sigusrx = cross; then
+ usable_sigusrx=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigusrx = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
+ fi
+
+ AC_MSG_CHECKING(if sigaltstack can be used)
+ AC_MSG_RESULT($usable_sigaltstack)
+ if test $usable_sigaltstack = cross; then
+ usable_sigaltstack=yes
+ AC_MSG_WARN([result yes guessed because of cross compilation])
+ fi
+ if test $usable_sigaltstack = no; then
+ ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
+ fi
+ ;;
+ *) ;;
+ esac
+
+ dnl We sometimes need ETHR_DEFS in order to find certain headers
+ dnl (at least for pthread.h on osf1).
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $ETHR_DEFS"
+
+ dnl We need the thread library in order to find some functions
+ saved_libs="$LIBS"
+ LIBS="$LIBS $ETHR_X_LIBS"
+
+ dnl
+ dnl Check for headers
+ dnl
+
+ AC_CHECK_HEADER(pthread.h, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \
+[Define if you have the <pthread.h> header file.]))
+
+ dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h>
+ AC_CHECK_HEADER(pthread/mit/pthread.h, \
+ AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \
+[Define if the pthread.h header file is in pthread/mit directory.]))
+
+ if test $NEED_NPTL_PTHREAD_H = yes; then
+ AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \
+[Define if you need the <nptl/pthread.h> header file.])
+ fi
+
+ AC_CHECK_HEADER(sched.h, \
+ AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \
+[Define if you have the <sched.h> header file.]))
+
+ AC_CHECK_HEADER(sys/time.h, \
+ AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \
+[Define if you have the <sys/time.h> header file.]))
+
+ AC_TRY_COMPILE([#include <time.h>
+ #include <sys/time.h>],
+ [struct timeval *tv; return 0;],
+ AC_DEFINE(ETHR_TIME_WITH_SYS_TIME, 1, \
+[Define if you can safely include both <sys/time.h> and <time.h>.]))
+
+
+ dnl
+ dnl Check for functions
+ dnl
+
+ AC_CHECK_FUNC(pthread_spin_lock, \
+ [ethr_have_native_spinlock=yes \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
+[Define if you have the pthread_spin_lock function.])])
+
+ have_sched_yield=no
+ have_librt_sched_yield=no
+ AC_CHECK_FUNC(sched_yield, [have_sched_yield=yes])
+ if test $have_sched_yield = no; then
+ AC_CHECK_LIB(rt, sched_yield,
+ [have_librt_sched_yield=yes
+ ETHR_X_LIBS="$ETHR_X_LIBS -lrt"])
+ fi
+ if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.])
+ AC_MSG_CHECKING([whether sched_yield() returns an int])
+ sched_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #ifdef ETHR_HAVE_SCHED_H
+ #include <sched.h>
+ #endif
+ ],
+ [int sched_yield();],
+ [sched_yield_ret_int=yes])
+ AC_MSG_RESULT([$sched_yield_ret_int])
+ if test $sched_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_yield=no
+ AC_CHECK_FUNC(pthread_yield, [have_pthread_yield=yes])
+ if test $have_pthread_yield = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.])
+ AC_MSG_CHECKING([whether pthread_yield() returns an int])
+ pthread_yield_ret_int=no
+ AC_TRY_COMPILE([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [int pthread_yield();],
+ [pthread_yield_ret_int=yes])
+ AC_MSG_RESULT([$pthread_yield_ret_int])
+ if test $pthread_yield_ret_int = yes; then
+ AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.])
+ fi
+ fi
+
+ have_pthread_rwlock_init=no
+ AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes])
+ if test $have_pthread_rwlock_init = yes; then
+
+ ethr_have_pthread_rwlockattr_setkind_np=no
+ AC_CHECK_FUNC(pthread_rwlockattr_setkind_np,
+ [ethr_have_pthread_rwlockattr_setkind_np=yes])
+
+ if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \
+[Define if you have the pthread_rwlockattr_setkind_np() function.])
+
+ AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP])
+ ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
+ AC_TRY_LINK([
+ #if defined(ETHR_NEED_NPTL_PTHREAD_H)
+ #include <nptl/pthread.h>
+ #elif defined(ETHR_HAVE_MIT_PTHREAD_H)
+ #include <pthread/mit/pthread.h>
+ #elif defined(ETHR_HAVE_PTHREAD_H)
+ #include <pthread.h>
+ #endif
+ ],
+ [
+ pthread_rwlockattr_t *attr;
+ return pthread_rwlockattr_setkind_np(attr,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+ ],
+ [ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes])
+ AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np])
+ if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
+ AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \
+[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.])
+ fi
+ fi
+ fi
+
+ if test "$force_pthread_rwlocks" = "yes"; then
+
+ AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \
+[Define if you want to force usage of pthread rwlocks])
+
+ if test $have_pthread_rwlock_init = yes; then
+ AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.])
+ else
+ AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found])
+ fi
+ fi
+
+ AC_CHECK_FUNC(pthread_attr_setguardsize, \
+ AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
+[Define if you have the pthread_attr_setguardsize function.]))
+
+ linux_futex=no
+ AC_MSG_CHECKING([for Linux futexes])
+ AC_TRY_LINK([
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <linux/futex.h>
+ #include <sys/time.h>
+ ],
+ [
+ int i = 1;
+ syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1,
+ (void*)0,(void*)0, 0);
+ syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0,
+ (void*)0,(void*)0, 0);
+ return 0;
+ ],
+ linux_futex=yes)
+ AC_MSG_RESULT([$linux_futex])
+ test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.])
+
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(long long)
+ AC_CHECK_SIZEOF(__int128_t)
+
+ if test "$ac_cv_sizeof_int" = "4"; then
+ int32="int"
+ elif test "$ac_cv_sizeof_long" = "4"; then
+ int32="long"
+ elif test "$ac_cv_sizeof_long_long" = "4"; then
+ int32="long long"
+ else
+ AC_MSG_ERROR([No 32-bit type found])
+ fi
+
+ if test "$ac_cv_sizeof_int" = "8"; then
+ int64="int"
+ elif test "$ac_cv_sizeof_long" = "8"; then
+ int64="long"
+ elif test "$ac_cv_sizeof_long_long" = "8"; then
+ int64="long long"
+ else
+ AC_MSG_ERROR([No 64-bit type found])
+ fi
+
+ int128=no
+ if test "$ac_cv_sizeof___int128_t" = "16"; then
+ int128="__int128_t"
+ fi
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32, 1, [Define if you have __sync_val_compare_and_swap() for 32-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH32, 1, [Define if you have __sync_add_and_fetch() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND32, 1, [Define if you have __sync_fetch_and_and() for 32-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR32, 1, [Define if you have __sync_fetch_and_or() for 32-bit integers]))
+
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64, 1, [Define if you have __sync_val_compare_and_swap() for 64-bit integers]))
+ test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes
+ ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH64, 1, [Define if you have __sync_add_and_fetch() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND64, 1, [Define if you have __sync_fetch_and_and() for 64-bit integers]))
+ ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR64, 1, [Define if you have __sync_fetch_and_or() for 64-bit integers]))
+
+ if test $int128 != no; then
+ ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [128], [$int128], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128, 1, [Define if you have __sync_val_compare_and_swap() for 128-bit integers]))
+ fi
+
+ AC_MSG_CHECKING([for a usable libatomic_ops implementation])
+ case "x$with_libatomic_ops" in
+ xno | xyes | x)
+ libatomic_ops_include=
+ ;;
+ *)
+ if test -d "${with_libatomic_ops}/include"; then
+ libatomic_ops_include="-I$with_libatomic_ops/include"
+ CPPFLAGS="$CPPFLAGS $libatomic_ops_include"
+ else
+ AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found])
+ fi;;
+ esac
+ ethr_have_libatomic_ops=no
+ AC_TRY_LINK([#include "atomic_ops.h"],
+ [
+ volatile AO_t x;
+ AO_t y;
+ int z;
+
+ AO_nop_full();
+ AO_store(&x, (AO_t) 0);
+ z = AO_load(&x);
+ z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1);
+ ],
+ [ethr_have_native_atomics=yes
+ ethr_have_libatomic_ops=yes])
+ AC_MSG_RESULT([$ethr_have_libatomic_ops])
+ if test $ethr_have_libatomic_ops = yes; then
+ AC_CHECK_SIZEOF(AO_t, ,
+ [
+ #include <stdio.h>
+ #include "atomic_ops.h"
+ ])
+ AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used])
+
+ AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations])
+ if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations])
+ fi
+ ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
+ elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+ AC_MSG_ERROR([No usable libatomic_ops implementation found])
+ fi
+
+ case "$host_cpu" in
+ sparc | sun4u | sparc64 | sun4v)
+ case "$with_sparc_memory_order" in
+ "TSO")
+ AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);;
+ "PSO")
+ AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);;
+ "RMO"|"")
+ AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);;
+ *)
+ AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);;
+ esac
+ ethr_have_native_atomics=yes;;
+ i86pc | i*86 | x86_64 | amd64)
+ if test "$enable_x86_out_of_order" = "yes"; then
+ AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized])
+ fi
+ ethr_have_native_atomics=yes;;
+ macppc | ppc | "Power Macintosh")
+ ethr_have_native_atomics=yes;;
+ tile)
+ ethr_have_native_atomics=yes;;
+ *)
+ ;;
+ esac
+
+ test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
+
+ dnl Restore LIBS
+ LIBS=$saved_libs
+ dnl restore CPPFLAGS
+ CPPFLAGS=$saved_cppflags
+
+ ;;
+ *)
+ ;;
+esac
+
+AC_MSG_CHECKING([whether default stack size should be modified])
+if test "x$ethr_modified_default_stack_size" != "x"; then
+ AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size])
+ AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words])
+else
+ AC_MSG_RESULT([no])
+fi
+
+if test "x$ETHR_THR_LIB_BASE" != "x"; then
+ ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS"
+ ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS"
+ ETHR_LIB_NAME=$ethr_lib_name
+fi
+
+AC_CHECK_SIZEOF(void *)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers])
+
+AC_CHECK_SIZEOF(int)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int])
+AC_CHECK_SIZEOF(long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long])
+AC_CHECK_SIZEOF(long long)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long])
+AC_CHECK_SIZEOF(__int64)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64])
+AC_CHECK_SIZEOF(__int128_t)
+AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t])
+
+
+case X$erl_xcomp_bigendian in
+ X) ;;
+ Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);;
+esac
+
+AC_C_BIGENDIAN
+
+if test "$ac_cv_c_bigendian" = "yes"; then
+ AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian])
+fi
+
+case X$erl_xcomp_double_middle_endian in
+ X) ;;
+ Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);;
+esac
+
+AC_C_DOUBLE_MIDDLE_ENDIAN
+
+AC_ARG_ENABLE(native-ethr-impls,
+ AS_HELP_STRING([--disable-native-ethr-impls],
+ [disable native ethread implementations]),
+[ case "$enableval" in
+ no) disable_native_ethr_impls=yes ;;
+ *) disable_native_ethr_impls=no ;;
+ esac ], disable_native_ethr_impls=no)
+
+AC_ARG_ENABLE(x86-out-of-order,
+ AS_HELP_STRING([--enable-x86-out-of-order],
+ [enable x86/x84_64 out of order support (default disabled)]))
+
+test "X$disable_native_ethr_impls" = "Xyes" &&
+ AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations])
+
+AC_ARG_ENABLE(prefer-gcc-native-ethr-impls,
+ AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls],
+ [prefer gcc native ethread implementations]),
+[ case "$enableval" in
+ yes) enable_prefer_gcc_native_ethr_impls=yes ;;
+ *) enable_prefer_gcc_native_ethr_impls=no ;;
+ esac ], enable_prefer_gcc_native_ethr_impls=no)
+
+test $enable_prefer_gcc_native_ethr_impls = yes &&
+ AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations])
+
+AC_ARG_WITH(libatomic_ops,
+ AS_HELP_STRING([--with-libatomic_ops=PATH],
+ [specify and prefer usage of libatomic_ops in the ethread library]))
+
+AC_ARG_WITH(with_sparc_memory_order,
+ AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO],
+ [specify sparc memory order (defaults to RMO)]))
+
+ETHR_X86_SSE2_ASM=no
+case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in
+ yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64)
+ AC_MSG_CHECKING([for gcc sse2 asm support])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -msse2"
+ gcc_sse2_asm=no
+ AC_TRY_COMPILE([],
+ [
+ long long x, *y;
+ __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
+ ],
+ [gcc_sse2_asm=yes])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$gcc_sse2_asm])
+ if test "$gcc_sse2_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements])
+ ETHR_X86_SSE2_ASM=yes
+ fi
+ ;;
+ *)
+ ;;
+esac
+
+case "$GCC-$host_cpu" in
+ yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
+ gcc_dw_cmpxchg_asm=no
+ AC_MSG_CHECKING([for gcc double word cmpxchg asm support])
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+ __asm__ __volatile__(
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "pushl %%ebx\n\t"
+ "movl %8, %%ebx\n\t"
+#endif
+#if ETHR_SIZEOF_PTR == 4
+ "lock; cmpxchg8b %0\n\t"
+#else
+ "lock; cmpxchg16b %0\n\t"
+#endif
+ "setz %3\n\t"
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "popl %%ebx\n\t"
+#endif
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new[1]),
+#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ "r"(new[0])
+#else
+ "b"(new[0])
+#endif
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test $gcc_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ AC_TRY_COMPILE([],
+ [
+ char xchgd;
+ long new[2], xchg[2], *p;
+#if !defined(__PIC__) || !__PIC__
+# error nope
+#endif
+ __asm__ __volatile__(
+ "pushl %%ebx\n\t"
+ "movl (%7), %%ebx\n\t"
+ "movl 4(%7), %%ecx\n\t"
+ "lock; cmpxchg8b %0\n\t"
+ "setz %3\n\t"
+ "popl %%ebx\n\t"
+ : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd)
+ : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new)
+ : "cc", "memory");
+
+ ],
+ [gcc_dw_cmpxchg_asm=yes])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
+ fi
+ fi
+ AC_MSG_RESULT([$gcc_dw_cmpxchg_asm])
+ if test "$gcc_dw_cmpxchg_asm" = "yes"; then
+ AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction])
+ fi;;
+ *)
+ ;;
+esac
+
+AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
+[Define if you have all ethread defines])
+
+AC_SUBST(ETHR_X_LIBS)
+AC_SUBST(ETHR_LIBS)
+AC_SUBST(ETHR_LIB_NAME)
+AC_SUBST(ETHR_DEFS)
+AC_SUBST(ETHR_THR_LIB_BASE)
+AC_SUBST(ETHR_THR_LIB_BASE_DIR)
+AC_SUBST(ETHR_X86_SSE2_ASM)
+
+])
+
+
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl ERL_TIME_CORRECTION
+dnl
+dnl In the presence of a high resolution realtime timer Erlang can adapt
+dnl its view of time relative to this timer. On solaris such a timer is
+dnl available with the syscall gethrtime(). On other OS's a fallback
+dnl solution using times() is implemented. (However on e.g. FreeBSD times()
+dnl is implemented using gettimeofday so it doesn't make much sense to
+dnl use it there...) On second thought, it seems to be safer to do it the
+dnl other way around. I.e. only use times() on OS's where we know it will
+dnl work...
+dnl
+
+AC_DEFUN(ERL_TIME_CORRECTION,
+[if test x$ac_cv_func_gethrtime = x; then
+ AC_CHECK_FUNC(gethrtime)
+fi
+if test x$clock_gettime_correction = xunknown; then
+ AC_TRY_COMPILE([#include <time.h>],
+ [struct timespec ts;
+ long long result;
+ clock_gettime(CLOCK_MONOTONIC,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);],
+ clock_gettime_compiles=yes,
+ clock_gettime_compiles=no)
+else
+ clock_gettime_compiles=no
+fi
+
+
+AC_CACHE_CHECK([how to correct for time adjustments], erl_cv_time_correction,
+[
+case $clock_gettime_correction in
+ yes)
+ erl_cv_time_correction=clock_gettime;;
+ no|unknown)
+ case $ac_cv_func_gethrtime in
+ yes)
+ erl_cv_time_correction=hrtime ;;
+ no)
+ case $host_os in
+ linux*)
+ case $clock_gettime_correction in
+ unknown)
+ if test x$clock_gettime_compiles = xyes; then
+ if test X$cross_compiling != Xyes; then
+ linux_kernel_vsn_=`uname -r`
+ case $linux_kernel_vsn_ in
+ [[0-1]].*|2.[[0-5]]|2.[[0-5]].*)
+ erl_cv_time_correction=times ;;
+ *)
+ erl_cv_time_correction=clock_gettime;;
+ esac
+ else
+ case X$erl_xcomp_linux_clock_gettime_correction in
+ X)
+ erl_cv_time_correction=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_linux_clock_gettime_correction = yes; then
+ erl_cv_time_correction=clock_gettime
+ else
+ erl_cv_time_correction=times
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_linux_clock_gettime_correction value: $erl_xcomp_linux_clock_gettime_correction]);;
+ esac
+ fi
+ else
+ erl_cv_time_correction=times
+ fi
+ ;;
+ *)
+ erl_cv_time_correction=times ;;
+ esac
+ ;;
+ *)
+ erl_cv_time_correction=none ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+])
+
+xrtlib=""
+case $erl_cv_time_correction in
+ times)
+ AC_DEFINE(CORRECT_USING_TIMES,[],
+ [Define if you do not have a high-res. timer & want to use times() instead])
+ ;;
+ clock_gettime|cross)
+ if test $erl_cv_time_correction = cross; then
+ erl_cv_time_correction=clock_gettime
+ AC_MSG_WARN([result clock_gettime guessed because of cross compilation])
+ fi
+ xrtlib="-lrt"
+ AC_DEFINE(GETHRTIME_WITH_CLOCK_GETTIME,[1],
+ [Define if you want to use clock_gettime to simulate gethrtime])
+ ;;
+esac
+dnl
+dnl Check if gethrvtime is working, and if to use procfs ioctl
+dnl or (yet to be written) write to the procfs ctl file.
+dnl
+
+AC_MSG_CHECKING([if gethrvtime works and how to use it])
+AC_TRY_RUN([
+/* gethrvtime procfs ioctl test */
+/* These need to be undef:ed to not break activation of
+ * micro level process accounting on /proc/self
+ */
+#ifdef _LARGEFILE_SOURCE
+# undef _LARGEFILE_SOURCE
+#endif
+#ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+
+int main() {
+ long msacct = PR_MSACCT;
+ int fd;
+ long long start, stop;
+ int i;
+ pid_t pid = getpid();
+ char proc_self[30] = "/proc/";
+
+ sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid);
+ if ( (fd = open(proc_self, O_WRONLY)) == -1)
+ exit(1);
+ if (ioctl(fd, PIOCSET, &msacct) < 0)
+ exit(2);
+ if (close(fd) < 0)
+ exit(3);
+ start = gethrvtime();
+ for (i = 0; i < 100; i++)
+ stop = gethrvtime();
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+}
+],
+erl_gethrvtime=procfs_ioctl,
+erl_gethrvtime=false,
+[
+case X$erl_xcomp_gethrvtime_procfs_ioctl in
+ X)
+ erl_gethrvtime=cross;;
+ Xyes|Xno)
+ if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then
+ erl_gethrvtime=procfs_ioctl
+ else
+ erl_gethrvtime=false
+ fi;;
+ *)
+ AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);;
+esac
+])
+
+case $erl_gethrvtime in
+ procfs_ioctl)
+ AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1],
+ [define if gethrvtime() works and uses ioctl() to /proc/self])
+ AC_MSG_RESULT(uses ioctl to procfs)
+ ;;
+ *)
+ if test $erl_gethrvtime = cross; then
+ erl_gethrvtime=false
+ AC_MSG_RESULT(cross)
+ AC_MSG_WARN([result 'not working' guessed because of cross compilation])
+ else
+ AC_MSG_RESULT(not working)
+ fi
+
+ dnl
+ dnl Check if clock_gettime (linux) is working
+ dnl
+
+ AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time])
+ save_libs=$LIBS
+ LIBS="-lrt"
+ AC_TRY_RUN([
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <time.h>
+ int main() {
+ long long start, stop;
+ int i;
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0)
+ exit(1);
+ start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ for (i = 0; i < 100; i++)
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
+ stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
+ if (start == 0)
+ exit(4);
+ if (start == stop)
+ exit(5);
+ exit(0); return 0;
+ }
+ ],
+ erl_clock_gettime=yes,
+ erl_clock_gettime=no,
+ [
+ case X$erl_xcomp_clock_gettime_cpu_time in
+ X) erl_clock_gettime=cross;;
+ Xyes|Xno) erl_clock_gettime=$erl_xcomp_clock_gettime_cpu_time;;
+ *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);;
+ esac
+ ])
+ LIBS=$save_libs
+ case $host_os in
+ linux*)
+ AC_MSG_RESULT([no; not stable])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ AC_MSG_RESULT($erl_clock_gettime)
+ case $erl_clock_gettime in
+ yes)
+ AC_DEFINE(HAVE_CLOCK_GETTIME,[],
+ [define if clock_gettime() works for getting process time])
+ LIBRT=-lrt
+ ;;
+ cross)
+ erl_clock_gettime=no
+ AC_MSG_WARN([result no guessed because of cross compilation])
+ LIBRT=$xrtlib
+ ;;
+ *)
+ LIBRT=$xrtlib
+ ;;
+ esac
+ ;;
+ esac
+ AC_SUBST(LIBRT)
+ ;;
+esac
+])dnl
+
+dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY
+dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
+dnl AC_LANG_JAVA instead...)
+AC_DEFUN(ERL_TRY_LINK_JAVA,
+[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
+changequote(, )dnl
+cat > conftest.java <<EOF
+$1
+class conftest { public static void main(String[] args) {
+ $2
+ ; return; }}
+EOF
+changequote([, ])dnl
+if AC_TRY_EVAL(java_link) && test -s conftest.class; then
+ ifelse([$3], , :, [rm -rf conftest*
+ $3])
+else
+ echo "configure: failed program was:" 1>&AC_FD_CC
+ cat conftest.java 1>&AC_FD_CC
+ echo "configure: PATH was $PATH" 1>&AC_FD_CC
+ifelse([$4], , , [ rm -rf conftest*
+ $4
+])dnl
+fi
+rm -f conftest*])
+#define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
+
+
diff --git a/lib/wx/api_gen/Makefile b/lib/wx/api_gen/Makefile
index 756ec598ce..8adb485ba9 100644
--- a/lib/wx/api_gen/Makefile
+++ b/lib/wx/api_gen/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
#
# The 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 @@ ERL_COMPILE_FLAGS=+debug_info +warn_unused_vars
COMPILER = gen_util wx_gen wx_gen_erl wx_gen_cpp
COMPILER_T = $(COMPILER:%=$(EBIN)/%.beam)
-GL_COMP = gl_gen gl_gen_erl gl_gen_c
+GL_COMP = gl_gen gl_gen_erl gl_gen_c gl_scan_doc
GL_COMP_T = $(GL_COMP:%=$(EBIN)/%.beam)
TARGET_EDIR = ../src/gen
diff --git a/lib/wx/api_gen/README b/lib/wx/api_gen/README
index 10b5209789..dd0c49d227 100644
--- a/lib/wx/api_gen/README
+++ b/lib/wx/api_gen/README
@@ -1,6 +1,6 @@
API GENERATION:
- Most of the code in wx is generated.
- Users of wxErlang should not normally need to regenerate the generated code,
+ Most of the code in wx is generated.
+ Users of wxErlang should not normally need to regenerate the generated code,
as it is checked in by wxErlang developers, when changes are made.
Code checked in is currently generated from wxwidgets 2.8.10.
@@ -10,6 +10,8 @@ REQUIREMENTS:
used to parse wxWidgets c++ headers and generate xml files (in
wx_xml/).
+ 2012-02-09 doxygen 1.7.4 is working fine
+
2008-09-29 doxygen 1.4.6 is required.
Later versions of Doxygen - up to 1.5.6 at least - have a bug in the xml generation
which causes us problems. This has been logged and we are waiting for a fix.
@@ -32,5 +34,12 @@ RUNNING:
I keep the opengl headers separate so I don't go backwards in version when generating the code
from another machine.
+ Also gl.h from different vendors differ so keep it consistent,
+ I have used mesa's gl.h and the glext.h from opengl.org
+ (version see GL_GLEXT_VERSION in gl.hrl)
+
+ I also get the xml documentation from opengl.org (subversion) and place it in
+ api_gen/gl_man2 (all old functions) and api_gen/gl_man4 (all the new functions).
+
CONTRIBUTION:
- Send me patches or update the svn version.
+ Send me patches
diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl
index df5b4c3405..4638d4c7ea 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -96,8 +96,8 @@ check_diff(Diff) ->
[<<>>] -> ok;
_ -> throw(diff)
end,
- <<_, _, "%% Copyright", _/binary>> = D1,
- <<_, _, "%% Copyright", _/binary>> = D2,
+ copyright(D1),
+ copyright(D2),
copyright
catch
throw:_ -> diff;
@@ -108,6 +108,10 @@ check_diff(Diff) ->
diff
end.
+copyright(<<_, _, "%% Copyright", _/binary>>) -> ok;
+copyright(<<_, _, " * Copyright", _/binary>>) -> ok;
+copyright(_) -> throw(diff).
+
w(Str) ->
w(Str, []).
w(Str,Args) ->
@@ -217,7 +221,7 @@ erl_copyright() ->
w("%%~n",[]),
w("%% %CopyrightBegin%~n",[]),
w("%%~n",[]),
- w("%% Copyright Ericsson AB ~p-2011. All Rights Reserved.~n",
+ w("%% Copyright Ericsson AB ~p-2012. All Rights Reserved.~n",
[StartYear]),
w("%%~n",[]),
w("%% The contents of this file are subject to the Erlang Public License,~n",[]),
@@ -237,7 +241,7 @@ c_copyright() ->
w("/*~n",[]),
w(" * %CopyrightBegin%~n",[]),
w(" *~n",[]),
- w(" * Copyright Ericsson AB 2008-2011. All Rights Reserved.~n",[]),
+ w(" * Copyright Ericsson AB 2008-2012. 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 8998d341e7..331ba32ba4 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,11 @@ gen_code() ->
GLDefs = parse_gl_defs(Opts),
{GLUDefines,GLUFuncs} = setup(GLUDefs, Opts),
{GLDefines,GLFuncs} = setup(GLDefs, Opts),
+ gl_gen_erl:gl_defines(GLDefines),
+ gl_gen_erl:gl_api(GLFuncs),
gl_gen_erl:glu_defines(GLUDefines),
gl_gen_erl:glu_api(GLUFuncs),
- gl_gen_erl:gl_defines(GLDefines),
- gl_gen_erl:gl_api(GLFuncs),
%%gl_gen_erl:gen_debug(GLFuncs,GLUFuncs),
gl_gen_c:gen(GLFuncs,GLUFuncs),
ok.
@@ -190,14 +190,17 @@ parse_define([#xmlElement{name=initializer,content=[#xmlText{value=V}]}|_],Def,_
try
case Val0 of
"0x" ++ Val1 ->
- Val = http_util:hexlist_to_integer(Val1),
- Def#def{val=Val, type=hex};
+ _ = http_util:hexlist_to_integer(Val1),
+ Def#def{val=Val1, type=hex};
_ ->
Val = list_to_integer(Val0),
Def#def{val=Val, type=int}
end
- catch _:_ ->
- Def#def{val=Val0, type=string}
+ catch _:_ ->
+ case catch list_to_float(Val0) of
+ {'EXIT', _} -> Def#def{val=Val0, type=string};
+ _ -> Def#def{val=Val0, type=float_str}
+ end
end;
parse_define([_|R], D, Opts) ->
parse_define(R, D, Opts);
@@ -360,7 +363,9 @@ extract_type_info2("**", Acc) -> [{by_ref,{pointer,2}}|Acc];
extract_type_info2(Type, Acc) -> [Type|Acc].
parse_type2(["void"], _T, _Opts) -> void;
-parse_type2([N="void"|R], T, Opts) ->
+parse_type2([N="void", const|R], T, Opts) ->
+ parse_type2([const|R],T#type{name=N, base=idx_binary},Opts);
+parse_type2([N="void"|R], T, Opts) ->
parse_type2(R,T#type{name=N},Opts);
parse_type2([const|R],T=#type{mod=Mod},Opts) ->
parse_type2(R,T#type{mod=[const|Mod]},Opts);
@@ -676,6 +681,7 @@ get_extension(ExtName,_Opts) ->
"IGP" ++ Name -> {reverse(Name),"PGI"};
"PH" ++ Name -> {reverse(Name),"HP"};
"YDEMERG" ++ Name -> {reverse(Name),"GREMEDY"};
+ "SEO" ++ Name -> {reverse(Name),"OES"};
%%["" ++ Name] -> {Name; %%
_ -> {ExtName, ""}
end.
diff --git a/lib/wx/api_gen/gl_gen_c.erl b/lib/wx/api_gen/gl_gen_c.erl
index 0f5cb0e1f4..be2c5cf2bf 100644
--- a/lib/wx/api_gen/gl_gen_c.erl
+++ b/lib/wx/api_gen/gl_gen_c.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
@@ -238,7 +238,7 @@ decode_arg(P=#arg{name=Name,type=#type{size=BSz,name=Type,single={list,TSz}}},A0
{P, A};
decode_arg(P=#arg{name=Name,type=#type{name=Type,base=guard_int}},A0) ->
A = align(4,A0),
- w(" ~s *~s = (~s *) * (int *) bp; bp += 4;~n", [Type,Name,Type]),
+ w(" ~s *~s = (~s *) (ErlDrvSInt) * (int *) bp; bp += 4;~n", [Type,Name,Type]),
{P, A};
decode_arg(P=#arg{name=Name,type=#type{name=Type,base=string,single=true}},A0) ->
w(" ~s *~s = (~s *) bp;~n", [Type,Name,Type]),
diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl
index f292c8723e..25f89e4ad4 100644
--- a/lib/wx/api_gen/gl_gen_erl.erl
+++ b/lib/wx/api_gen/gl_gen_erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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 : gl_gen_erl.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 18 Apr 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
@@ -31,7 +31,7 @@
-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2, max/1]).
-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]).
gl_defines(Defs) ->
@@ -40,7 +40,7 @@ gl_defines(Defs) ->
w("~n%% OPENGL DEFINITIONS~n~n", []),
w("%% This file is generated DO NOT EDIT~n~n", []),
[gen_define(Def) || Def=#def{} <- Defs],
- close(),
+ close(),
ok.
glu_defines(Defs) ->
@@ -50,36 +50,40 @@ glu_defines(Defs) ->
w("%% This file is generated DO NOT EDIT~n~n", []),
[gen_define(Def) || Def=#def{} <- Defs],
close(),
- ok.
+ ok.
gen_define(#def{name=N, val=Val, type=int}) ->
w("-define(~s, ~p).~n", [N,Val]);
+gen_define(#def{name=N, val=Val, type=float_str}) ->
+ w("-define(~s, ~s).~n", [N,Val]);
gen_define(#def{name=N, val=Val, type=hex}) ->
- w("-define(~s, ~.16#).~n", [N,Val]);
+ w("-define(~s, 16#~s).~n", [N,Val]);
gen_define(#def{name=N, val=Val, type=string}) ->
- w("-define(~s, ?~s).~n", [N,Val]).
+ w("-define(~s, ?~s).~n", [N,Val]);
+gen_define(#def{name="GLEXT_64_TYPES"++_, val=undefined, type=undefined}) ->
+ ok.
types() ->
[{"GLenum", "32/native-unsigned"},
{"GLboolean", "8/native-unsigned"},
{"GLbitfield","32/native-unsigned"}, %
%%{"GLvoid",":void "},%
- {"GLbyte", "8/native-signed"}, % 1-byte signed
- {"GLshort", "16/native-signed"}, % 2-byte signed
- {"GLint", "32/native-signed"}, % 4-byte signed
- {"GLubyte", "8/native-unsigned"}, % 1-byte unsigned
- {"GLushort", "16/native-unsigned"}, % 2-byte unsigned
- {"GLuint", "32/native-unsigned"}, % 4-byte unsigned
- {"GLsizei", "32/native-signed"}, % 4-byte signed
- {"GLfloat", "32/native-float"}, % single precision float
- {"GLclampf", "32/native-float"}, % single precision float in [0,1]
- {"GLdouble", "64/native-float"}, % double precision float
- {"GLclampd", "64/native-float"}, % double precision float in [0,1]
+ {"GLbyte", "8/native-signed"}, % 1-byte signed
+ {"GLshort", "16/native-signed"}, % 2-byte signed
+ {"GLint", "32/native-signed"}, % 4-byte signed
+ {"GLubyte", "8/native-unsigned"}, % 1-byte unsigned
+ {"GLushort", "16/native-unsigned"}, % 2-byte unsigned
+ {"GLuint", "32/native-unsigned"}, % 4-byte unsigned
+ {"GLsizei", "32/native-signed"}, % 4-byte signed
+ {"GLfloat", "32/native-float"}, % single precision float
+ {"GLclampf", "32/native-float"}, % single precision float in [0,1]
+ {"GLdouble", "64/native-float"}, % double precision float
+ {"GLclampd", "64/native-float"}, % double precision float in [0,1]
{"GLsizeiptr","64/native-unsigned"}, % 64 bits int, convert on c-side
{"GLintptr", "64/native-unsigned"}, % 64 bits int, convert on c-sidew
{"GLUquadric", "64/native-unsigned"},% Handle 32bits aargh 64bits on mac64
{"GLhandleARB","64/native-unsigned"},% Handle 32bits aargh 64bits on mac64
-
+
{"GLsync", "64/native-unsigned"}, % Pointer to record
{"GLuint64", "64/native-unsigned"},
{"GLint64", "64/native-signed"}
@@ -94,20 +98,17 @@ gl_api(Fs) ->
w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]),
w("%%~n", []),
w("%% Booleans are represented by integers 0 and 1.~n~n", []),
- w("%% @type mem(). memory block~n", []),
- w("%% @type enum(). An integer defined in gl.hrl~n", []),
- w("%% @type offset(). An integer which is an offset in an array~n", []),
- w("%% @type clamp(). A float clamped between 0.0 - 1.0~n", []),
-
- w("-module(gl).~n~n",[]),
+
+ w("-module(gl).~n~n",[]),
w("-compile(inline).~n", []),
%% w("-include(\"wxe.hrl\").~n", []),
[w("-define(~s,~s).~n", [GL,Erl]) || {GL,Erl} <- types()],
gen_types(gl),
-
+
Exp = fun(F) -> gen_export(F) end,
ExportList = lists:map(Exp,Fs),
+
w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]),
w("-export([call/2, cast/2, send_bin/1]).~n",[]),
w("%% @hidden~n", []),
@@ -140,10 +141,10 @@ gl_api(Fs) ->
w(" erlang:port_command(Port,Bin)~n", []),
w(" end.~n", []),
w("~n", []),
-
+
w("~n%% API~n~n", []),
[gen_funcs(F) || F <- Fs],
- close(),
+ close(),
ok.
glu_api(Fs) ->
@@ -155,28 +156,24 @@ glu_api(Fs) ->
w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]),
w("%%~n", []),
w("%% Booleans are represented by integers 0 and 1.~n~n", []),
- w("%% @type mem(). memory block~n", []),
- w("%% @type enum(). An integer defined in gl.hrl~n", []),
- w("%% @type offset(). An integer which is an offset in an array~n", []),
- w("%% @type clamp(). A float clamped between 0.0 - 1.0~n~n", []),
- w("-module(glu).~n",[]),
+ w("-module(glu).~n",[]),
w("-compile(inline).~n", []),
%%w("-include(\"wxe.hrl\").~n", []),
[w("-define(~s,~s).~n", [GL,Erl]) || {GL,Erl} <- types()],
gen_types(glu),
-
+
Exp = fun(F) -> gen_export(F) end,
ExportList = ["tesselate/2" | lists:map(Exp,Fs)],
w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]),
w("-import(gl, [call/2,cast/2,send_bin/1]).", []),
w("~n%% API~n~n", []),
- w("%% @spec (Vec3, [Vec3]) -> {Triangles, VertexPos}~n",[]),
- w("%% Vec3 = {float(),float(),float()}~n",[]),
- w("%% Triangles = [VertexIndex::integer()]~n",[]),
- w("%% VertexPos = binary()~n",[]),
+ %% w("%% @spec (Vec3, [Vec3]) -> {Triangles, VertexPos}~n",[]),
+ %% w("%% Vec3 = {float(),float(),float()}~n",[]),
+ %% w("%% Triangles = [VertexIndex::integer()]~n",[]),
+ %% w("%% VertexPos = binary()~n",[]),
w("%% @doc General purpose polygon triangulation.~n",[]),
w("%% The first argument is the normal and the second a list of~n"
"%% vertex positions. Returned is a list of indecies of the vertices~n"
@@ -184,6 +181,9 @@ glu_api(Fs) ->
"%% vertex positions, it starts with the vertices in Vs and~n"
"%% may contain newly created vertices in the end.~n", []),
+ w("-spec tesselate(Normal, [Vs]) -> {Triangles, VertexPos}~n", []),
+ w(" when Normal :: vertex(), Vs :: vertex(),~n", []),
+ w(" Triangles :: [integer()], VertexPos :: binary().~n", []),
w("tesselate({Nx,Ny,Nz}, Vs) ->~n",[]),
w(" call(5000, <<(length(Vs)):32/native,0:32,~n"
" Nx:?GLdouble,Ny:?GLdouble,Nz:?GLdouble,~n"
@@ -215,15 +215,21 @@ gen_funcs(F) ->
erase(current_func),
w(".~n~n",[]).
-gen_types(Where) ->
+gen_types(Where) ->
case Where of
- glu -> ignore;
+ glu ->
+ w("-type vertex() :: {float(), float(), float()}.~n", []),
+ w("-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl or glu.hrl~n", []);
gl ->
- w("-type clamp() :: float().~n", []),
- w("-type offset() :: non_neg_integer().~n", [])
+ w("-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl~n", []),
+ w("-type clamp() :: float(). %% 0.0..1.0~n", []),
+ w("-type offset() :: non_neg_integer(). %% Offset in memory block~n", [])
end,
- w("-type enum() :: non_neg_integer().~n", []),
- w("-type mem() :: binary() | tuple().~n", []),
+ w("-type matrix() :: {float(),float(),float(),float(),~n", []),
+ w(" float(),float(),float(),float(),~n", []),
+ w(" float(),float(),float(),float(),~n", []),
+ w(" float(),float(),float(),float()}.~n", []),
+ w("-type mem() :: binary() | tuple(). %% Memory block~n", []),
ok.
gen_export(F) ->
@@ -238,43 +244,182 @@ gen_export_1([F|_]) when is_list(F) ->
gen_export_1(F) when is_list(F) ->
gen_export2(get(F)).
-gen_export2(#func{name=Name,alt={vector,VecPos,Vec}}) ->
- #func{params=As0} = get(Vec),
+gen_export2(#func{name=Name,alt=Alt={vector,VecPos,Vec}}) ->
+ #func{params=As0} = get(Vec),
{As1,_As2} = lists:split(VecPos, As0),
Args = lists:filter(fun(Arg) -> func_arg(Arg) =/= skip end, As1),
- erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args) +1);
-gen_export2(#func{name=Name,params=As0}) ->
+ Export = erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args) +1),
+ DocN = doc_name(Name,Alt),
+ (get({export_arg,DocN}) == undefined) andalso put({export_arg, DocN}, Export),
+ Export;
+gen_export2(#func{name=Name,params=As0, alt=Alt}) ->
Args = lists:filter(fun(Arg) -> func_arg(Arg) =/= skip end, As0),
- erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args)).
+ Export = erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args)),
+ DocN = doc_name(Name,Alt),
+ (get({export_arg,DocN}) == undefined) andalso put({export_arg, DocN}, Export),
+ Export.
-gen_doc([#func{name=Name, alt={vector,VecPos,Vec}}]) ->
- #func{type=T,params=As} = get(Vec),
+gen_doc([#func{name=Name, params=Orig, alt={vector,VecPos,Vec}}]) ->
+ #func{type=T,params=As} = get(Vec),
{As1,As2} = lists:split(VecPos, As),
+ #arg{name=OrigName} = lists:last(Orig),
Args1 = case args(fun func_arg/1, ",", As1) of [] -> []; Else -> Else++"," end,
Args2 = args(fun func_arg/1, ",", As2),
- w("%% @spec (~s{~s}) -> ~s~n",[Args1,Args2,doc_return_types(T,As, doc)]),
w("%% @equiv ~s(~s)~n",[erl_func_name(Vec), Args1++Args2]),
- SA1 = case doc_arg_types(As1, spec) of [] -> []; E -> E++"," end,
- SA2 = doc_arg_types(As2, spec),
- w("-spec ~s(~s{~s}) -> ~s.~n",
- [erl_func_name(Name), SA1, SA2,
- doc_return_types(T,As, spec)]);
-
-gen_doc([#func{name=Name,type=T,params=As,alt=Alt}|_]) ->
- w("%% @spec (~s) -> ~s~n", [doc_arg_types(As, doc),doc_return_types(T,As, doc)]),
- GLDoc = "http://www.opengl.org/sdk/docs/man/xhtml/",
- w("%% @doc See <a href=\"~s~s.xml\">external</a> documentation.~n",
- [GLDoc, doc_name(Name,Alt)]),
- w("-spec ~s(~s) -> ~s.~n",
- [erl_func_name(Name), doc_arg_types(As, spec), doc_return_types(T,As, spec)]).
+ SA1 = case doc_arg_types(As1) of [] -> []; E -> E++"," end,
+ SA2 = doc_arg_types(As2),
+ w("-spec ~s(~s~s) -> ~s when ~s :: {~s}.~n",
+ [erl_func_name(Name), SA1, erl_arg_name(OrigName),
+ doc_return_types(T,As), erl_arg_name(OrigName), SA2]);
+
+gen_doc([F=#func{name=Name,type=T,params=As, alt=Alt}|_]) ->
+ gen_doc(Name, Alt, gen_export2(F)),
+ Ps = [Arg || #arg{name=Arg, in=In, where=Where} <- As,
+ In =/= false, Where =/= c],
+ Args = args(fun erl_arg_name/1, ", ", Ps),
+ case Args of
+ [] ->
+ w("-spec ~s(~s) -> ~s.~n",
+ [erl_func_name(Name), Args, doc_return_types(T,As)]);
+ _ -> w("-spec ~s(~s) -> ~s when ~s.~n",
+ [erl_func_name(Name), Args, doc_return_types(T,As), doc_arg_types(As)])
+ end.
+
+-define(LINE_LEN, 90).
+
+gen_doc(Name0, Alt, Export) ->
+ Name = doc_name(Name0, Alt),
+ case get({doc, Name}) of
+ undefined ->
+ GLDoc = "http://www.opengl.org/sdk/docs/man/xhtml/",
+ case parse_doc(Name, _Dir1 ="gl_man4", _Dir2="gl_man2") of
+ {error, _} ->
+ case reverse(Name) of
+ "BRA" ++ _ -> ok;
+ "TXE" ++ _ -> ok;
+ _ ->
+ %% io:format("Missing doc: no ~s.xml (~s) found in ~s or ~s~n",
+ %% [Name, Name0, Dir1, Dir2]),
+ ok
+ end,
+ w("%% @doc ~s~n%%~n%% See <a href=\"~s~s.xml\">external</a> documentation.~n",
+ [Name, GLDoc, Name]);
+ Doc ->
+ put({doc, Name}, Export),
+ format_doc(Doc, ?LINE_LEN),
+ w("~n%%~n%% See <a href=\"~s~s.xml\">external</a> documentation.~n",
+ [GLDoc, Name])
+ end;
+ Where ->
+ w("%% @doc ~n", []),
+ w("%% See {@link ~s}~n", [Where])
+ end.
+parse_doc(Name, Dir1, Dir2) ->
+ case gl_scan_doc:file(filename:join(Dir1, Name++".xml"), []) of
+ {error, {_, "no such" ++ _}} ->
+ gl_scan_doc:file(filename:join(Dir2, Name++".xml"), []);
+ Doc ->
+ Doc
+ end.
+
+format_doc(Strs, Count) when Count < 0 ->
+ w("~n%% ", []),
+ format_doc(Strs, ?LINE_LEN);
+format_doc([{constant, Const}|Rest], Count) ->
+ w("`?~s'", [Const]),
+ format_doc(Rest, Count-length(Const)-8);
+format_doc([{emphasis, Const}|Rest], Count) ->
+ w("`~s'", [Const]),
+ format_doc(Rest, Count-length(Const)-7);
+format_doc([{function, Func}|Rest], Count) ->
+ case Func of
+ "glu" ++ _ ->
+ w("``glu:~s''", [erl_func_name(Func)]);
+ "gl" ++ _ ->
+ w("``gl:~s''", [erl_func_name(Func)]);
+ _ ->
+ w("`~s'", [Func])
+ end,
+ format_doc(Rest, Count-length(Func)-7);
+format_doc([{reffunc, Func}|Rest], Count) ->
+ Out = fun(Export) ->
+ case Func of
+ "glu" ++ _ -> w(" {@link glu:~s} ", [Export]);
+ "gl" ++ _ -> w(" {@link gl:~s} ", [Export])
+ end
+ end,
+ case get({export_arg, Func}) of
+ undefined ->
+ case get({export_arg, doc_name(Func, undefined)}) of
+ undefined ->
+ %% io:format("Func ~p undefined (~p) ~n",
+ %% [Func, doc_name(Func, undef)]),
+ w("see `~s'", [Func]);
+ Export -> Out(Export)
+ end;
+ Export ->
+ Out(Export)
+ end,
+ format_doc(Rest, Count-length(Func)-10);
+format_doc([{parameter, Param}|Rest], Count) ->
+ w(" `~s' ", [erl_arg_name(Param)]),
+ format_doc(Rest, Count-length(Param)-7);
+format_doc([{equation, Eq}|Rest], Count) ->
+%% w("```", []),
+ format_doc([Eq], Count),
+%% w("'''", []),
+ format_doc(Rest, Count);
+format_doc([{fenced, Open, Close, Eq}|Rest], Count) ->
+ w(Open, []),
+ format_doc(Eq, Count),
+ w(Close, []),
+ format_doc(Rest, Count);
+
+format_doc([{code, Code}|Rest], Count) ->
+ w("``~s''", [Code]),
+ format_doc(Rest, Count-length(Code)-7);
+
+format_doc([para|Rest], _Count) ->
+ w("~n%%~n%% ", []),
+ format_doc(Rest, ?LINE_LEN);
+format_doc([break|Rest], _Count) ->
+ w("<br />~n%% ", []),
+ format_doc(Rest, ?LINE_LEN);
+format_doc([{purpose, Purpose}, para | Doc], _Count) ->
+ w("%% @doc ~s~n%%~n%% ", [uppercase(Purpose)]),
+ format_doc(Doc, ?LINE_LEN);
+format_doc([{purpose, Purpose} | Doc], _Count) ->
+ w("%% @doc ~s~n%%~n%% ", [Purpose]),
+ format_doc(Doc, ?LINE_LEN);
+format_doc([listentry|Rest], _Count) ->
+ w("~n%%~n%% ", []),
+ format_doc(Rest, ?LINE_LEN);
+format_doc([Str|Rest], Count) ->
+ case length(Str) of
+ Len when Len < Count ->
+ w("~s", [Str]),
+ format_doc(Rest, Count-Len);
+ _ ->
+ {Str1, Str2} = split(Str, Count, []),
+ w("~s~n%% ", [Str1]),
+ format_doc([Str2|Rest], ?LINE_LEN)
+ end;
+format_doc([], _) -> ok.
+
+split([$ |Str], Count, Acc) when Count =< 5 ->
+ {reverse(Acc), Str};
+split([Chr|Str], Count, Acc) ->
+ split(Str, Count-1, [Chr|Acc]);
+split([], _, Acc) ->
+ {reverse(Acc), []}.
gen_func(#func{name=Name,alt={vector,VecPos,Vec}}) ->
- #func{params=As} = get(Vec),
+ #func{params=As} = get(Vec),
{As1,As2} = lists:split(VecPos, As),
Args1 = case args(fun func_arg/1, ",", As1) of [] -> []; Else -> Else++"," end,
Args2 = args(fun func_arg/1, ",", As2),
-
+
w("~s(~s{~s}) ->", [erl_func_name(Name),Args1,Args2]),
w(" ~s(~s)", [erl_func_name(Vec), Args1++Args2]);
gen_func(_F=#func{name=Name,type=T,params=As,id=MId}) ->
@@ -290,7 +435,7 @@ gen_func(_F=#func{name=Name,type=T,params=As,id=MId}) ->
w(" cast(~p, <<~s>>)", [MId, StrArgs])
end.
-func_arg(#arg{in=In,where=W,name=Name,type=Type})
+func_arg(#arg{in=In,where=W,name=Name,type=Type})
when In =/= false, W =/= c ->
case Type of
#type{single={tuple,TSz0}} when TSz0 =/= undefined ->
@@ -305,45 +450,39 @@ func_arg(#arg{in=In,where=W,name=Name,type=Type})
end;
func_arg(_) -> skip.
-doc_arg_types(Ps0, Type) ->
+doc_arg_types(Ps0) ->
Ps = [P || P=#arg{in=In, where=Where} <- Ps0,In =/= false, Where =/= c],
- args(fun(Arg) -> doc_arg_type(Arg, Type) end, ",", Ps).
+ args(fun(Arg) -> doc_arg_type(Arg) end, ",", Ps).
-doc_return_types(T, Ps0, Type) ->
+doc_return_types(T, Ps0) ->
Ps = [P || P=#arg{in=In, where=Where} <- Ps0,In =/= true, Where =/= c],
- doc_return_types2(T, Ps, Type).
-
-doc_return_types2(void, [], _) -> "ok";
-doc_return_types2(void, [#arg{type=T}], _) -> doc_arg_type2(T);
-doc_return_types2(T, [], _) -> doc_arg_type2(T);
-doc_return_types2(void, Ps, Type) ->
- "{" ++ args(fun(Arg) -> doc_arg_type(Arg, Type) end,",",Ps) ++ "}";
-doc_return_types2(T, Ps, Type) ->
- "{" ++ doc_arg_type2(T) ++ "," ++
- args(fun(Arg) -> doc_arg_type(Arg, Type) end,",",Ps) ++ "}".
-
-doc_arg_type(#arg{name=Name,type=T}, doc) ->
- try
- erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T)
- catch _:Error ->
- io:format("Error: ~p ~p~n~p~n",[Name, Error, erlang:get_stacktrace()]),
- exit(error)
- end;
-doc_arg_type(#arg{name=Name,type=T}, spec) ->
- try
- doc_arg_type2(T)
+ doc_return_types2(T, Ps).
+
+doc_return_types2(void, []) -> "ok";
+doc_return_types2(void, [#arg{type=T}]) -> doc_arg_type2(T);
+doc_return_types2(T, []) -> doc_arg_type2(T);
+doc_return_types2(void, Ps) ->
+ "{" ++ args(fun(Arg) -> doc_arg_type(Arg) end,",",Ps) ++ "}";
+doc_return_types2(T, Ps) ->
+ "{" ++ doc_arg_type2(T) ++ "," ++
+ args(fun(Arg) -> doc_arg_type(Arg) end,",",Ps) ++ "}".
+
+doc_arg_type(#arg{name=Name,type=T}) ->
+ try
+ erl_arg_name(Name) ++ " :: " ++ doc_arg_type2(T)
catch _:Error ->
io:format("Error spec: ~p ~p~n~p~n",[Name, Error, erlang:get_stacktrace()]),
exit(error)
end.
-
doc_arg_type2(T=#type{single=true}) ->
doc_arg_type3(T);
doc_arg_type2(T=#type{single=undefined}) ->
doc_arg_type3(T);
doc_arg_type2(T=#type{single={tuple,undefined}}) ->
"{" ++ doc_arg_type3(T) ++ "}";
+doc_arg_type2(#type{base=float, single={tuple,16}}) ->
+ "matrix()";
doc_arg_type2(T=#type{single={tuple,Sz}}) ->
"{" ++ args(fun doc_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}";
doc_arg_type2(T=#type{single=list}) ->
@@ -365,21 +504,21 @@ doc_arg_type3(#type{base=bool}) -> "0|1";
doc_arg_type3(#type{base=binary}) -> "binary()";
doc_arg_type3(#type{base=memory}) -> "mem()".
-guard_test(As) ->
- Str = args(fun(#arg{name=N,type=#type{base=guard_int}}) ->
- " is_integer("++erl_arg_name(N)++")";
- (_) ->
+guard_test(As) ->
+ Str = args(fun(#arg{name=N,type=#type{base=guard_int}}) ->
+ " is_integer("++erl_arg_name(N)++")";
+ (_) ->
skip
end, ",", As),
case Str of
[] -> [];
Other -> " when " ++ Other
- end.
+ end.
-pre_marshal([#arg{name=N,in=true,type=#type{base=binary}}|R]) ->
+pre_marshal([#arg{name=N,in=true,type=#type{base=binary}}|R]) ->
w(" send_bin(~s),~n", [erl_arg_name(N)]),
pre_marshal(R);
-pre_marshal([#arg{name=N,type=#type{base=memory}}|R]) ->
+pre_marshal([#arg{name=N,type=#type{base=memory}}|R]) ->
w(" send_bin(~s),~n", [erl_arg_name(N)]),
pre_marshal(R);
pre_marshal([A=#arg{name=N,type=#type{base=string,single=list}}|R]) ->
@@ -412,14 +551,14 @@ marshal_arg(#type{size=Sz,name=Type,single={tuple,undefined}},Name,A0) ->
" (<< <<C:?"++Type++ ">> ||"
"C <- tuple_to_list("++Name++")>>)/binary",
case Sz of
- 4 ->
+ 4 ->
{Str,Align} = align(4,A0,Str0),
{Str++",0:((("++integer_to_list(Align div 4)++
"+size("++Name++")) rem 2)*32)",0};
- 8 ->
+ 8 ->
align(8,A0,Str0)
end;
-marshal_arg(#type{size=BSz,name=Type,single={tuple,TSz}},Name,A0)
+marshal_arg(#type{size=BSz,name=Type,single={tuple,TSz}},Name,A0)
when is_integer(TSz) ->
NameId = hd(Name),
Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)],
@@ -427,7 +566,7 @@ marshal_arg(#type{size=BSz,name=Type,single={tuple,TSz}},Name,A0)
align(BSz,TSz,A0,All);
marshal_arg(#type{size=BSz,name=Type,single={tuple,matrix12}},Name,A0) ->
- NameId = hd(Name),
+ NameId = hd(Name),
Ns0 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,3)],
Ns1 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(4,6)],
Ns2 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(7,9)],
@@ -436,7 +575,7 @@ marshal_arg(#type{size=BSz,name=Type,single={tuple,matrix12}},Name,A0) ->
Ns0 ++ ["0"] ++ Ns1 ++ ["0"] ++ Ns2 ++ ["0"] ++ Ns3 ++ ["1"]),
align(BSz,16,A0,All);
-marshal_arg(#type{size=Sz,name=Type,base=Base,single=list},Name,A0)
+marshal_arg(#type{size=Sz,name=Type,base=Base,single=list},Name,A0)
when Base =:= float; Base =:= int ->
KeepA = case Sz of 8 -> "0:32,"; _ -> "" end,
Str0 = "(length("++Name++")):?GLuint,"++KeepA++"\n"
@@ -459,14 +598,14 @@ marshal_arg(#type{base=string,single=true,ref={pointer,1}},Name,A0) ->
align_after(1,A0,1,1,Name,Str);
marshal_arg(#type{base=string,single=list,ref={pointer,2}},Name,A0) ->
- Str0 =
+ Str0 =
"(length("++Name++")):?GLuint,"
"(size("++Name ++ "Temp)):?GLuint,"
"(" ++ Name ++ "Temp)/binary",
{Str,A} = align(4,A0,Str0),
- {Str ++ ",0:((8-((size("++Name++"Temp)+"++
+ {Str ++ ",0:((8-((size("++Name++"Temp)+"++
integer_to_list(A) ++") rem 8)) rem 8)", 0};
-
+
marshal_arg(#type{size=Sz,name=Type,single={tuple_list,TSz}},Name,A0) ->
NameId = hd(Name),
Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)],
@@ -508,11 +647,11 @@ align(8,_,6,Str) -> {"0:16,"++Str, 0};
align(8,_,7,Str) -> {"0:8," ++Str, 0}.
align_after(8,0,_Add,_Multiplier,_Name,Str) -> {Str,0};
-align_after(4,0,Add,Mult,Name,Str) ->
+align_after(4,0,Add,Mult,Name,Str) ->
Extra = extra_align(Add,Mult),
Align = ",0:(((length("++Name++")"++Extra++") rem 2)*32)",
{Str ++ Align,0};
-align_after(4,4,Add,Mult,Name,Str) ->
+align_after(4,4,Add,Mult,Name,Str) ->
Extra = extra_align(Add,Mult),
Align = ",0:(((1+length("++Name++")"++Extra++") rem 2)*32)",
{Str ++ Align,0};
@@ -531,14 +670,14 @@ align_after(Sz,A,Add,Mult,Name,Str) ->
extra_align(0,1) -> "";
extra_align(0,M) when M > 1 -> "* " ++ integer_to_list(M);
extra_align(A,1) when A > 0 -> "+ " ++ integer_to_list(A);
-extra_align(A,M) when A > 0,M>1 ->
+extra_align(A,M) when A > 0,M>1 ->
"* " ++ integer_to_list(M) ++ "+ " ++ integer_to_list(A).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
have_return_vals(void, Ps) ->
- lists:any(fun(#arg{in=In, type=#type{base=B}}) ->
- In =/= true orelse B =:= memory
+ lists:any(fun(#arg{in=In, type=#type{base=B}}) ->
+ In =/= true orelse B =:= memory
end, Ps);
have_return_vals(#type{}, _) -> true.
@@ -550,21 +689,28 @@ erl_arg_name(Name) -> uppercase(Name).
check_name("begin") -> "'begin'";
check_name("end") -> "'end'";
check_name(Other) -> Other.
-
-
-doc_name(Name0, Alt) ->
- Name = doc_name2(Name0,Alt),
-%% case lists:member(lists:last(Name0), "uvbisdf987654312") of
-%% true -> io:format("~s ~s~n", [Name0,Name]);
-%% false -> ignore
-%% end,
- Name.
-
-doc_name2(N="glGetBufferParameteriv", _) -> N;
-doc_name2(N="glEnd", _) -> N;
-doc_name2(Name, {has_vector,_,_}) ->
+
+doc_name(N="glGetBufferParameteriv", _) -> N;
+doc_name("glEnd"++What, _) -> "glBegin"++What;
+doc_name("glDisable" ++ What, _) -> "glEnable" ++ What;
+doc_name("glPop" ++ What, _) -> "glPush" ++ What;
+doc_name("glGetBooleanv", _) -> "glGet";
+doc_name("glGetBooleani_v", _) -> "glGet";
+doc_name("glGetIntegerv", _) -> "glGet";
+doc_name("glGetIntegeri_v", _) -> "glGet";
+doc_name("glGetInteger64v", _) -> "glGet";
+doc_name("glGetInteger64i_v", _) -> "glGet";
+doc_name("glGetFloatv", _) -> "glGet";
+doc_name("glGetDoublev", _) -> "glGet";
+doc_name("glGetFloati_v", _) -> "glGet";
+doc_name("glGetDoublei_v", _) -> "glGet";
+doc_name("glUniformMatr" ++ _, _) -> "glUniform";
+doc_name("glTexSubImage" ++ _, _) -> "glTexSubImage";
+doc_name("glFramebufferText" ++ _, _) -> "glFramebufferTexture";
+doc_name("glProgramUniformMatr" ++ _, _) -> "glProgramUniform";
+doc_name(Name, {has_vector,_,_}) ->
strip_hard(reverse(Name));
-doc_name2(Name, _) ->
+doc_name(Name, _) ->
reverse(strip(reverse(Name))).
strip_hard(Rev) ->
@@ -583,6 +729,21 @@ strip([$v,$s,$N,N|R]) when N > 47, N < 58 -> R;
strip([$v,$d,$N,N|R]) when N > 47, N < 58 -> R;
strip([$v,$f,$N,N|R]) when N > 47, N < 58 -> R;
strip([$b,$u,$N,N|R]) when N > 47, N < 58 -> R;
+strip([$v,$b,$I,N|R]) when N > 47, N < 58 -> R;
+strip([$v,$i,$I,N|R]) when N > 47, N < 58 -> R;
+strip([$v,$s,$I,N|R]) when N > 47, N < 58 -> R;
+strip([$v,$d,$I,N|R]) when N > 47, N < 58 -> R;
+strip([$v,$f,$I,N|R]) when N > 47, N < 58 -> R;
+strip([$b,$u,$I,N|R]) when N > 47, N < 58 -> R;
+
+strip([$v,$b,$u,N,$I|R]) when N > 47, N < 58 ->R;
+strip([$v,$i,$u,N,$I|R]) when N > 47, N < 58 ->R;
+strip([$v,$s,$u,N,$I|R]) when N > 47, N < 58 ->R;
+strip([$v,$b,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$v,$i,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$v,$s,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$v,$d,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$v,$f,N,$I|R]) when N > 47, N < 58 -> R;
strip([$v,$b,$u,N|R]) when N > 47, N < 58 ->R;
strip([$v,$i,$u,N|R]) when N > 47, N < 58 ->R;
@@ -593,6 +754,15 @@ strip([$v,$s,N|R]) when N > 47, N < 58 -> R;
strip([$v,$d,N|R]) when N > 47, N < 58 -> R;
strip([$v,$f,N|R]) when N > 47, N < 58 -> R;
+strip([$b,$u,N,$I|R]) when N > 47, N < 58 ->R;
+strip([$i,$u,N,$I|R]) when N > 47, N < 58 ->R;
+strip([$s,$u,N,$I|R]) when N > 47, N < 58 ->R;
+strip([$b,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$i,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$s,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$d,N,$I|R]) when N > 47, N < 58 -> R;
+strip([$f,N,$I|R]) when N > 47, N < 58 -> R;
+
strip([$b,$u,N|R]) when N > 47, N < 58 ->R;
strip([$i,$u,N|R]) when N > 47, N < 58 ->R;
strip([$s,$u,N|R]) when N > 47, N < 58 ->R;
@@ -606,6 +776,7 @@ strip([$v,$b,$u|R]) -> R;
strip([$v,$i,$u|R]) -> R;
strip([$v,$s,$u|R]) -> R;
strip([$v,$b|R]) -> R;
+strip([$v,$i,$I|R]) -> R;
strip([$v,$i|R]) -> R;
strip([$v,$s|R]) -> R;
strip([$v,$d|R]) -> R;
@@ -629,6 +800,12 @@ strip([$i,$n|R]) -> [$n|R];
strip([$f,$n|R]) -> [$n|R];
strip([$d,$n|R]) -> [$n|R];
+%% strip([$D,$3|R]) -> R;
+%% strip([$D,$2|R]) -> R;
+%% strip([$D,$1|R]) -> R;
+
+strip([$I|R]) -> R;
+strip([$L|R]) -> R;
strip([$v,R]) -> R;
strip([N|R]) when N > 47, N < 58 -> R;
strip([_|R="tceRlg"]) -> R;
@@ -656,7 +833,6 @@ gen_debug(GL, GLU) ->
w("].~n~n", []),
close().
-
printd([F|R],Mod) when is_list(F) ->
printd(F,Mod),
printd(R,Mod);
@@ -667,6 +843,6 @@ printd(F,Mod) ->
#func{where=erl} -> ok;
#func{id=Id, name=Method} ->
w(" {~p, {~s, ~s, 0}},~n", [Id, Mod, erl_func_name(Method)]);
- _Other ->
- io:format("F= ~p => ~p~n", [F, _Other])
+ _Other ->
+ io:format("F= ~p => ~p~n", [F, _Other])
end.
diff --git a/lib/wx/api_gen/gl_scan_doc.erl b/lib/wx/api_gen/gl_scan_doc.erl
new file mode 100644
index 0000000000..fc7b7cf275
--- /dev/null
+++ b/lib/wx/api_gen/gl_scan_doc.erl
@@ -0,0 +1,286 @@
+%%-*-erlang-*-
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(gl_scan_doc).
+
+-export([file/2]).
+-export([event/3]).
+
+-compile(export_all).
+
+-define(error(Reason),
+ throw({gl_output_error, Reason})).
+
+-record(state, {type=undefined, gen_output=false, str=[]}).
+
+file(FileName, Options0) ->
+ {Options2, State} = parse_options(Options0),
+ Options = [skip_external_dtd, {event_fun, fun event/3}, {event_state, State}|Options2],
+ case xmerl_sax_parser:file(FileName, Options) of
+ {ok, #state{str=Str}, _} -> lists:reverse(Str);
+ Else -> Else
+ end.
+
+event(Event, _LineNo, State) ->
+ gen_output(Event, State).
+
+parse_options(Options) ->
+ parse_options(Options, #state{}).
+
+parse_options(Options, State) ->
+ {Options, State}.
+
+%% Element
+%%----------------------------------------------------------------------
+gen_output({characters, String0}, #state{gen_output=true, type=Type, str=Str} = State) ->
+ case fix_str(strip_white_space(String0)) of
+ [] -> State;
+ String ->
+ Add = case Type of
+ mi -> case hd(Str) of
+ "/" -> String;
+ "*" -> String;
+ "+" -> String;
+ "-" -> String;
+ {fenced,_,_} -> String;
+ _ ->
+ [$ |String]
+ end;
+ constant -> {constant, String};
+ emphasis -> {emphasis, String};
+ function -> {function, String};
+ reffunc -> {reffunc, String};
+ purpose -> {purpose, String};
+ parameter -> {parameter, String};
+ equation -> {equation, String};
+ _ -> String
+ end,
+ State#state{str=[Add|Str]}
+ end;
+
+gen_output({startElement, _Uri, "function", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=function};
+gen_output({endElement, _Uri, "function", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+
+gen_output({startElement, _Uri, "constant", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=constant};
+gen_output({endElement, _Uri, "constant", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+
+gen_output({startElement, _Uri, "parameter", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=parameter};
+gen_output({endElement, _Uri, "parameter", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+
+gen_output({startElement, _Uri, "emphasis", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=emphasis};
+gen_output({endElement, _Uri, "emphasis", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+
+gen_output(startDocument, State) ->
+ State;
+gen_output(endDocument, State) ->
+ State;
+
+gen_output({startElement, _Uri, "refentrytitle", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=reffunc};
+gen_output({endElement, _Uri, "refentrytitle", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+
+gen_output({startElement, _Uri, "refpurpose", _QName, _Attributes}, State) ->
+ State#state{gen_output=true, type=purpose};
+gen_output({endElement, _Uri, "refpurpose", _QName}, State) ->
+ State#state{gen_output=false, type=undefined};
+
+gen_output({startElement, _Uri, "refsect1", _QName, [{_, _, "id", "description"}]}, State) ->
+ State#state{gen_output=true};
+gen_output({endElement, _Uri, "refsect1", _QName}, State) ->
+ State#state{gen_output=false};
+
+gen_output({startElement, _Uri, "title", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{gen_output=skip};
+gen_output({endElement, _Uri, "title", _QName}, #state{gen_output=skip} = State) ->
+ State#state{gen_output=true};
+
+%% gen_output({startElement, _Uri, "inlineequation", _QName, _Attributes}, #state{gen_output=true} = State) ->
+%% State#state{type=equation};
+%% gen_output({endElement, _Uri, "inlineequation", _QName}, #state{gen_output=skip} = State) ->
+%% State#state{type=undefined};
+%% gen_output({startElement, _Uri, "informalequation", _QName, _Attributes}, #state{gen_output=true} = State) ->
+%% State#state{type=equation};
+%% gen_output({endElement, _Uri, "informalequation", _QName}, #state{gen_output=skip} = State) ->
+%% State#state{type=undefined};
+gen_output({startElement, _Uri, "mfenced", _QName, Attributes}, #state{gen_output=true, str=Str} = State) ->
+ Fenc = get_fenc(Attributes, "(", ")"),
+ State#state{str=[Fenc|Str]};
+gen_output({endElement, _Uri, "mfenced", _QName}, #state{gen_output=true, str=Str0} = State) ->
+ Check = fun(What) -> case What of {fenced,_,_} ->false; _ -> true end end,
+ {Fenced, [{fenced, Open, Close}|Str]} = lists:splitwith(Check, Str0),
+ State#state{str=[{fenced, Open, Close, lists:reverse(Fenced)}| Str]};
+
+%% gen_output({startElement, _Uri, "tgroup", _QName, Attributes}, #state{gen_output=true, str=Str} = State) ->
+%% {_, _, _, ValueStr} = lists:keyfind(3, "cols", Attributes),
+%% ColSz = list_to_integer(ValueStr),
+%% State#state{str=[{tgroup, ColSz}|Str]};
+%% gen_output({endElement, _Uri, "tgroup", _QName}, #state{gen_output=true, str=Str0} = State) ->
+%% Check = fun(What) -> case What of {tgroup, _} ->false; _ -> true end end,
+%% {Rows, [{tgroup, ColSize}|Str]} = lists:splitwith(Check, Str0),
+%% State#state{str=[{tgroup, ColSize, lists:reverse(Rows)}| Str]};
+
+%% gen_output({endElement, _Uri, "row", _QName}, #state{gen_output=true, str=Str} = State) ->
+%% State#state{type=undefined, str=[break|Str]};
+gen_output({startElement, _Uri, "informaltable", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["<table>"|Str]};
+gen_output({endElement, _Uri, "informaltable", _QName}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["</table>"|Str]};
+gen_output({startElement, _Uri, "table", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["<table>"|Str]};
+gen_output({endElement, _Uri, "table", _QName}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["</table>"|Str]};
+
+gen_output({startElement, _Uri, "tbody", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["<tbody>"|Str]};
+gen_output({endElement, _Uri, "tbody", _QName}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["</tbody>"|Str]};
+
+gen_output({startElement, _Uri, "thead", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["<tbody>"|Str]};
+gen_output({endElement, _Uri, "thead", _QName}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["</tbody>"|Str]};
+gen_output({startElement, _Uri, "row", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["<tr>"|Str]};
+gen_output({endElement, _Uri, "row", _QName}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["</tr>"|Str]};
+gen_output({startElement, _Uri, "entry", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["<td>"|Str]};
+gen_output({endElement, _Uri, "entry", _QName}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=["</td>"|Str]};
+
+gen_output({startElement, _Uri, "mi", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=mi};
+gen_output({endElement, _Uri, "mi", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+gen_output({startElement, _Uri, "mn", _QName, _Attributes}, #state{gen_output=true} = State) ->
+ State#state{type=mi};
+gen_output({endElement, _Uri, "mn", _QName}, #state{gen_output=true} = State) ->
+ State#state{type=undefined};
+
+
+
+gen_output({startElement, _Uri, "varlistentry", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ State#state{str=[listentry|Str]};
+
+gen_output({endElement, _Uri, "mfrac", _QName}, #state{gen_output=true, str=[A0,B|Str]} = State) ->
+ A = case A0 of
+ [$ |A1] -> A1;
+ A1 -> A1
+ end,
+ State#state{str=[A,"/",B|Str]};
+
+gen_output({startElement, _Uri, "para", _QName, _Attributes}, #state{gen_output=true, str=Str} = State) ->
+ case Str of
+ [para|_] -> State;
+ [": "|_] -> State;
+ [Const, listentry | Rest] ->
+ State#state{str=[": ",Const,para|Rest]};
+ [Mod, Const, listentry | Rest] ->
+ State#state{str=[": ",Mod,Const,para|Rest]};
+ _ ->
+ State#state{str=[para|Str]}
+ end;
+
+%% gen_output({startElement, _Uri, What, _QName, _Attributes}, State) ->
+%% io:format("Skipped ~s~n",[What]),
+%% State;
+
+gen_output(_E, State) ->
+ State.
+
+%%----------------------------------------------------------------------
+%% Function : parse_attributes(Attributes) -> Result
+%% Parameters:
+%% Result :
+%% Description:
+%%----------------------------------------------------------------------
+print_attributes([]) ->
+ ok;
+print_attributes([{_Uri, _Prefix, LocalName, AttrValue} |Attributes]) ->
+ io:format(" ~s=\"~s\"",[LocalName, AttrValue]),
+ print_attributes(Attributes).
+
+get_fenc([{_Uri, _Prefix, "open", AttrValue} |Attributes], _Open, Close)
+ when AttrValue /= "" ->
+ get_fenc(Attributes, fenc(AttrValue), Close);
+get_fenc([{_Uri, _Prefix, "close", AttrValue} |Attributes], Open, _Close)
+ when AttrValue /= "" ->
+ get_fenc(Attributes, Open, fenc(AttrValue));
+get_fenc([_|Attributes], Open, Close) ->
+ get_fenc(Attributes, Open, Close);
+get_fenc([], Open, Close) ->
+ {fenced,Open,Close}.
+
+fenc("&DoubleVerticalBar;") -> "||";
+fenc("&VerticalBar;") -> "|";
+fenc("&LeftCeiling;") -> "|";
+fenc("&RightCeiling;") -> "|";
+fenc("&lceil;") -> "|";
+fenc("&rceil;") -> "|";
+fenc("&LeftFloor;") -> "|";
+fenc("&RightFloor;") -> "|";
+fenc("&lfloor;") -> "|";
+fenc("&rfloor;") -> "|";
+fenc("[") -> "[";
+fenc("]") -> "]";
+fenc(Else = [_]) -> Else.
+
+strip_white_space([$ | Str = [$ |_]]) ->
+ strip_white_space(Str);
+strip_white_space([$\n| Str]) ->
+ strip_white_space([$ |Str]);
+strip_white_space([$\t| Str]) ->
+ strip_white_space([$ |Str]);
+strip_white_space([$\\| Str]) ->
+ strip_white_space(Str);
+
+strip_white_space([Char|Str]) ->
+ [Char|strip_white_space(Str)];
+strip_white_space([]) -> [].
+
+fix_str([$<|Str]) ->
+ [$&,$l,$t,$;|fix_str(Str)];
+fix_str([$>|Str]) ->
+ [$&,$g,$t,$;|fix_str(Str)];
+fix_str("&times;"++Str) ->
+ [$*|fix_str(Str)];
+fix_str("&Prime;"++Str) ->
+ [$"|fix_str(Str)];
+fix_str("&CenterDot;"++Str) ->
+ [$.|fix_str(Str)];
+fix_str("&af;"++Str) ->
+ fix_str(Str);
+fix_str("&it;"++Str) ->
+ [$ |fix_str(Str)];
+fix_str([$&|Str]) ->
+ [$&,$a,$m,$p,$; |fix_str(Str)];
+fix_str([C|Str]) when C > 255 ->
+ fix_str(Str);
+fix_str([C|Str]) ->
+ [C|fix_str(Str)];
+fix_str([]) -> [].
diff --git a/lib/wx/api_gen/glapi.conf b/lib/wx/api_gen/glapi.conf
index 525ccf8b68..59fa8f7727 100644
--- a/lib/wx/api_gen/glapi.conf
+++ b/lib/wx/api_gen/glapi.conf
@@ -57,11 +57,13 @@
"glVertexAttribP3", %*
"glVertexAttribP4", %*
- "glGetActiveSubroutineUniformiv", %% Bad API don't know what to allocate needs to ask
+ %% Bad API don't know what to allocate needs to ask
+ "glGetActiveSubroutineUniformiv",
+ "glGetActiveAtomicCounterBufferiv",
%% EXT
%% By default skip these extensions
- "SGIX","SGIS","NV","ATI","AMD","SUN","SUNX","GREMEDY",
+ "SGIX","SGIS","NV","ATI","AMD","SUN","SUNX","GREMEDY","OES","MESA",
"HP","IBM","INTEL","APPLE","3DFX","PGI","EXT"]}.
%% Exceptions to the above
@@ -336,7 +338,6 @@
{"length", [skip, {single, true}]},
{"name", {string,"bufSize","length"}}]}.
-
{"glGenRenderbuffers", {"renderbuffers", {single,{list,"n","n"}}}}.
{"glGenFramebuffers", {"framebuffers",{single,{list,"n","n"}}}}.
{"glGetRenderbufferParameteriv", {"params", {single,true}}}.
@@ -491,4 +492,5 @@
{"glScissorIndexedv", {"v", {single,{tuple,4}}}}.
{"glDepthRangeArrayv", [{"count",{c_only,{length,"v"}}}, {"v", [{single,{tuple_list,2}}]}]}.
+{"glGetInternalformativ", {"params", [out, {single, {list, "bufSize", "bufSize"}}]}}.
diff --git a/lib/wx/api_gen/wx_doxygen.conf b/lib/wx/api_gen/wx_doxygen.conf
index df150fd154..829702cbbf 100644
--- a/lib/wx/api_gen/wx_doxygen.conf
+++ b/lib/wx/api_gen/wx_doxygen.conf
@@ -251,6 +251,7 @@ PREDEFINED = \
wxUSE_DATAOBJ=1 \
wxUSE_SLIDER=1 \
wxUSE_CLIPBOARD=1 \
+ wxUSE_SYSTEM_OPTIONS=1 \
wxABI_VERSION=20809 \
__WXGTK24__=1 \
__WXGTK20__=1 \
diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
index c6810eb32c..c5802af679 100644
--- a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
+++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
@@ -18,10 +18,7 @@
%% <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html">
%% The orginal documentation</a>.
%%
-%% @headerfile "../../include/wx.hrl"
%%
-%%@type wxEvtHandler(). An object reference
-
-module(wxEvtHandler).
-include("wxe.hrl").
-include("../include/wx.hrl").
@@ -34,17 +31,16 @@
new_evt_listener/0, destroy_evt_listener/1,
get_callback/1, replace_fun_with_id/2]).
--record(evh, {et=null,id=?wxID_ANY,lastId=?wxID_ANY,skip=undefined,userdata=[],cb=0}).
-
+-export_type([wxEvtHandler/0, wx/0, event/0]).
+-type wxEvtHandler() :: wx:wx_object().
+-record(evh, {et=null,id=?wxID_ANY,lastId=?wxID_ANY,skip=undefined,userdata=[],cb=0}).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType()) -> ok
%% @doc Equivalent to {@link connect/3. connect(This, EventType, [])}
-
+-spec connect(This::wxEvtHandler(), EventType::wxEventType()) -> ok.
connect(This, EventType) ->
connect(This, EventType, []).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType(), [Options]) -> ok
%% @doc This function subscribes the to events of EventType,
%% in the range id, lastId. The events will be received as messages
%% if no callback is supplied.
@@ -63,6 +59,9 @@ connect(This, EventType) ->
%% to process the event. Default not specfied i.e. a message will
%% be delivered to the process calling this function.
%% {userData, term()} An erlang term that will be sent with the event. Default: [].
+-spec connect(This::wxEvtHandler(), EventType::wxEventType(), [Option]) -> ok when
+ Option :: {id, integer()} | {lastId, integer()} | {skip, boolean()} |
+ callback | {callback, function()} | {userData, term()}.
connect(This=#wx_ref{type=ThisT}, EventType, Options) ->
EvH = parse_opts(Options, #evh{et=EventType}),
?CLASS(ThisT,wxEvtHandler),
@@ -76,7 +75,7 @@ parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) ->
%% Check Fun Arity?
parse_opts(R, Opts#evh{cb=Fun});
parse_opts([callback|R], Opts) ->
- parse_opts(R, Opts#evh{cb=1});
+ parse_opts(R, Opts#evh{cb=self()});
parse_opts([{userData, UserData}|R],Opts) ->
parse_opts(R, Opts#evh{userdata=UserData});
parse_opts([{skip, Skip}|R],Opts) when is_boolean(Skip) ->
@@ -99,26 +98,27 @@ parse_opts([], Opts = #evh{id=Id,lastId=Lid,skip=Skip, cb=CB}) ->
Opts
end.
-%% @spec (This::wxEvtHandler()) -> true | false
+
%% @doc Equivalent to {@link disconnect/3. disconnect(This, null, [])}
%% Can also have an optional callback Fun() as an additional last argument.
-
+-spec disconnect(This::wxEvtHandler()) -> boolean().
disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}) ->
?CLASS(ThisT,wxEvtHandler),
disconnect(This, null, []).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType()) -> true | false
%% @doc Equivalent to {@link disconnect/3. disconnect(This, EventType, [])}
+-spec disconnect(This::wxEvtHandler(), EventType::wxEventType()) -> boolean().
disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType) when is_atom(EventType) ->
?CLASS(ThisT,wxEvtHandler),
disconnect(This, EventType, []).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType(), Opts) -> true | false
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html#wxevthandlerdisconnect">external documentation</a>
%% This function unsubscribes the process or callback fun from the event handler.
%% EventType may be the atom 'null' to match any eventtype.
%% Notice that the options skip and userdata is not used to match the eventhandler.
-disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType, Opts) ->
+-spec disconnect(This::wxEvtHandler(), EventType::wxEventType(), [Option]) -> boolean() when
+ Option :: {id, integer()} | {lastId, integer()} | {callback, function()}.
+disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType, Opts) ->
?CLASS(ThisT,wxEvtHandler),
EvH = parse_opts(Opts, #evh{et=EventType}),
case wxe_util:disconnect_cb(This, EvH) of
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index 209de48496..7f85151d03 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -665,7 +665,11 @@ extract_type_info2("&", Acc) -> [{by_ref,reference}|Acc];
extract_type_info2("WXDLLIMP" ++ _, Acc) -> Acc;
extract_type_info2(Type, Acc) -> [Type|Acc].
-parse_type2(["void"], _Info, _Opts, _T) -> void;
+parse_type2(["void"], _Info, _Opts, #type{by_val=ByVal}) ->
+ case ByVal of
+ true -> void;
+ false -> voidp
+ end;
parse_type2(["virtual"|R], _Info, _Opts, _T) ->
[] = R,
%% Bug in old doxygen virtual destructors have type virtual
@@ -1106,6 +1110,7 @@ type_foot_print(#type{base={enum,_}}) -> int;
type_foot_print(#type{base={ref,_}}) -> ref;
type_foot_print(#type{base={term,_}}) -> term;
type_foot_print(#type{base=eventType}) -> atom;
+type_foot_print(voidp) -> int;
%% type_foot_print({Type,Str}) when is_list(Str) ->
%% type_foot_print(Type);
type_foot_print(#type{base={comp,_,R={record,_}}}) ->
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 4632fdbffe..2209e4a53b 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,11 +64,16 @@ gen_derived_dest(Defs) ->
[gen_derived_dest_2(Class) || Class <- Defs],
ok.
-gen_derived_dest_2(C=#class{name=Class}) ->
+gen_derived_dest_2(C=#class{name=Class, options=Opts}) ->
?WTC("gen_derived_dest_2"),
Derived = is_derived(C),
TaylorMade = taylormade_class(C),
+
if Derived andalso (TaylorMade =:= false) ->
+ case lists:keysearch(ifdef,1,Opts) of
+ {value, {ifdef, What}} -> w("#if ~p~n",[What]);
+ _ -> ok
+ end,
w("class E~s : public ~s {~n",[Class,Class]),
case Class of
"wxGLCanvas" -> %% Special for cleaning up gl context
@@ -78,7 +83,13 @@ gen_derived_dest_2(C=#class{name=Class}) ->
w(" public: ~~E~s() {((WxeApp *)wxTheApp)->clearPtr(this);};~n", [Class])
end,
gen_constructors(C),
- w("};~n~n", []);
+ case lists:keysearch(ifdef,1,Opts) of
+ {value, {ifdef, Endif}} ->
+ w("};~n", []),
+ w("#endif // ~p~n~n",[Endif]);
+ _ ->
+ w("};~n~n", [])
+ end;
TaylorMade /= false ->
w("~s~n", [TaylorMade]);
true ->
@@ -324,6 +335,8 @@ declare_var(P = #param{name=Name,in=In,def=Def,type=Type}) ->
declare_type(N,false,_,#type{name="wxArrayInt"}) ->
w(" wxArrayInt ~s;~n", [N]);
+declare_type(N,false,_,#type{name="wxArrayDouble"}) ->
+ w(" wxArrayDouble ~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})
@@ -335,8 +348,14 @@ declare_type(N,false,_,#type{name="wxArrayTreeItemIds",ref=reference}) ->
w(" wxArrayTreeItemIds ~s;~n", [N]);
declare_type(N,false,_,#type{name="wxDateTime"}) ->
w(" wxDateTime ~s;~n", [N]);
+declare_type(N,false,_,#type{name="wxColour"}) ->
+ w(" wxColour ~s;~n", [N]);
+declare_type(N,false,_,#type{name=Type, base=int, ref=reference}) ->
+ w(" ~s ~s;~n", [Type,N]);
declare_type(N,false,_,#type{name=Type, base=int64, ref=reference}) ->
w(" ~s ~s;~n", [Type,N]);
+declare_type(N,false,_,#type{base={comp,_,_},single=true,name=Type,ref=reference}) ->
+ w(" ~s ~s;~n", [Type,N]);
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]);
@@ -363,6 +382,8 @@ declare_type(N,true,Def,#type{base=binary, name=char}) ->
w(" char ~sD[] = {~s}, * ~s = ~sD;~n", [N,Def,N,N]);
declare_type(_N,true,_Def,void) ->
skip;
+declare_type(_N,true,_Def,voidp) ->
+ skip;
declare_type(N,true,Def,#type{name=Type, ref={pointer,2}}) ->
%% xxxx
w(" ~s ** ~s = ~s;~n", [Type,N,Def]);
@@ -645,6 +666,16 @@ decode_arg(N,#type{name=Type,single=list,base={class,Class}},arg,A0) ->
w(" ~s.Append(*(~s *) getPtr(bp,memenv)); bp += 4;}~n", [N,Class]),
w(" bp += ((~p+ *~sLen)%2 )*4;~n", [A,N]),
0;
+decode_arg(N,#type{single=array,base={comp,Class="wxPoint2DDouble",_}},arg,A0) ->
+ 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),
+ align(A0+1,64),
+ w(" for(int i=0; i < *~sLen; i++) {~n", [N]),
+ w(" double x = * (double *) bp; bp += 8;~n double y = * (double *) bp; bp += 8;~n", []),
+ w(" ~s[i] = wxPoint2DDouble(x,y);}~n", [N]),
+ 0;
decode_arg(Name,T, Arg,_A) ->
?error({unhandled_type, {Name,T, Arg}}).
@@ -785,6 +816,7 @@ call_arg(#param{name=N,in=false,type=#type{by_val=false, 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{base=int, ref=reference, single=true}}) -> "*" ++ 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,
@@ -792,6 +824,7 @@ call_arg(#param{name=N,type={merged,_,#type{base={class,_},single=true,
when ByVal =:= true; Ref =:= reference ->
"*" ++ N;
call_arg(#param{def=Def, type=void}) when Def =/= none -> Def;
+call_arg(#param{def=Def, type=voidp}) 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.
@@ -860,7 +893,7 @@ build_return_vals(Type,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
+ case build_ret(N, {arg, False}, T) of
ok -> Free;
Other -> [Other|Free]
end;
@@ -868,12 +901,12 @@ build_ret_types(void,Ps) ->
end,
lists:foldl(Calc, [], Ps);
build_ret_types(Type,Ps) ->
- Free = case build_ret("Result", out, Type) of
+ Free = case build_ret("Result", {ret, out}, Type) of
ok -> [];
FreeStr -> [FreeStr]
end,
Calc = fun(#param{name=N,in=False,type=T}, FreeAcc) when False =/= true ->
- case build_ret(N, False, T) of
+ case build_ret(N, {arg, False}, T) of
ok -> FreeAcc;
FreeMe -> [FreeMe|FreeAcc]
end;
@@ -899,13 +932,13 @@ build_ret(Name,_,#type{base={enum,_Type},single=true}) ->
w(" rt.addInt(~s);~n",[Name]);
build_ret(Name,_,#type{base={comp,_,{record, _}},single=true}) ->
w(" rt.add(~s);~n", [Name]);
-build_ret(Name,_,#type{base={comp,_,_},single=true, ref=reference}) ->
+build_ret(Name,{ret,_},#type{base={comp,_,_},single=true, ref=reference}) ->
w(" rt.add((*~s));~n",[Name]);
build_ret(Name,_,#type{base={comp,_,_},single=true}) ->
w(" rt.add(~s);~n",[Name]);
build_ret(Name,_,#type{base=bool,single=true,by_val=true}) ->
w(" rt.addBool(~s);~n",[Name]);
-build_ret(Name,both,#type{base=int,single=true,mod=M}) ->
+build_ret(Name,{arg, both},#type{base=int,single=true,mod=M}) ->
case lists:member(unsigned, M) of
true -> w(" rt.addUint(*~s);~n",[Name]);
false -> w(" rt.addInt(*~s);~n",[Name])
@@ -917,6 +950,8 @@ build_ret(Name,_,#type{base=int,single=true,mod=M}) ->
end;
build_ret(Name,_,#type{name="wxArrayInt"}) ->
w(" rt.add(~s);~n", [Name]);
+build_ret(Name,_,#type{name="wxArrayDouble"}) ->
+ w(" rt.add(~s);~n", [Name]);
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]),
@@ -1031,9 +1066,11 @@ gen_macros() ->
w("#include <wx/toolbook.h>~n"),
w("#include <wx/listbook.h>~n"),
w("#include <wx/treebook.h>~n"),
+ w("#include <wx/taskbar.h>~n"),
w("#include <wx/html/htmlwin.h>~n"),
w("#include <wx/html/htmlcell.h>~n"),
w("#include <wx/filename.h>~n"),
+ w("#include <wx/sysopt.h>~n"),
w("~n~n", []),
w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]),
diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl
index e882ae87ca..a8f23575f3 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 @@
-include("wx_gen.hrl").
--compile(export_all).
+%%-compile(export_all).
+-export([gen/1]).
+-export([parents/1, get_unique_names/0, get_unique_name/1,
+ event_type_name/1, event_rec_name/1, filter_attrs/1]).
--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,
+
+-import(lists, [foldl/3,reverse/1, filter/2]).
+-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1,
open_write/1, close/0, erl_copyright/0, w/2,
- args/3, args/4, strip_name/2]).
+ args/3, args/4]).
gen(Defs) ->
[put({class,N},C) || C=#class{name=N} <- Defs],
@@ -128,8 +132,6 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
w("%% stored on disc or distributed for use on other nodes.~n~n", []),
w("-module(~s).~n", [Name]),
w("-include(\"wxe.hrl\").~n",[]),
- %% w("-compile(export_all).~n~n", []), %% XXXX remove ???
- %% w("-compile(nowarn_unused_vars).~n~n", []), %% XXXX remove ???
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)]),
@@ -140,10 +142,10 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",",
lists:usort(["parent_class/1"|InExported]),
60)]),
-
+ w("-export_type([~s/0]).~n", [Name]),
w("%% @hidden~n", []),
parents_check(Parents),
-
+ w("-type ~s() :: wx:wx_object().~n", [Name]),
Gen = fun(M) -> gen_method(Name,M) end,
NewMs = lists:map(Gen,reverse(Ms)),
gen_dest(C, Ms),
@@ -175,7 +177,18 @@ parents_check([Parent|Ps]) ->
w("parent_class(~s) -> true;~n",[Parent]),
parents_check(Ps).
-check_class(#type{base={class,"wx"}}) -> ok;
+check_class(#type{name="wxObject", base={class,"wx"}}) ->
+ "wx:wx_object()";
+check_class(#type{name="wxIconLocation", base={class,"wx"}}) ->
+ "wx:wx_object()";
+check_class(#type{name="wxToolBarToolBase", base={class,"wx"}, mod=Mod}) ->
+ %% Implement this some day
+ "wx:wx_object()";
+check_class(#type{name="wxValidator", base={class,"wx"}, mod=Mod}) ->
+ %% Implement this some day
+ "wx:wx_object()";
+check_class(#type{name=Name, base={class,"wx"}}) ->
+ exit({class, Name});
check_class(#type{base={class,Name},xml=Xml}) ->
case get({class,Name}) of
undefined ->
@@ -188,12 +201,15 @@ check_class(#type{base={class,Name},xml=Xml}) ->
_ ->
?warning("~s:~s: Class ~p used but not defined~n (see ~p)~n",
[get(current_class),get(current_func),Name, Xml])
- end;
+ end,
+ "wx:wx_object()";
_ ->
?warning("~s:~s: Class ~p used is enum~n",
- [get(current_class),get(current_func),Name])
+ [get(current_class),get(current_func),Name]),
+ exit(class_enum)
end;
- _ -> ok
+ _ ->
+ Name ++ ":" ++ Name ++ "()"
end.
gen_export(#class{name=Class,abstract=Abs},Ms0) ->
@@ -317,8 +333,8 @@ gen_dest(#class{name=CName,abstract=Abs}, Ms) ->
end.
gen_dest2(Class, Id) ->
- w("%% @spec (This::~s()) -> ok~n", [Class]),
w("%% @doc Destroys this object, do not use object again~n", []),
+ w("-spec destroy(This::~s()) -> ok.~n", [Class]),
w("destroy(Obj=#wx_ref{type=Type}) ->~n", []),
w(" ?CLASS(Type,~s),~n",[Class]),
case Id of
@@ -601,9 +617,9 @@ guard_test(#param{name=N,type=#type{base=int64}}) ->
guard_test(#param{name=N,type=#type{base=long}}) ->
"is_integer(" ++ erl_arg_name(N) ++ ")";
guard_test(#param{name=N,type=#type{base=float}}) ->
- "is_float(" ++ erl_arg_name(N) ++ ")";
+ "is_number(" ++ erl_arg_name(N) ++ ")";
guard_test(#param{name=N,type=#type{base=double}}) ->
- "is_float(" ++ erl_arg_name(N) ++ ")";
+ "is_number(" ++ erl_arg_name(N) ++ ")";
guard_test(#param{name=N,type=#type{base=bool}}) ->
"is_boolean(" ++ erl_arg_name(N) ++ ")";
guard_test(#param{name=N,type=#type{name="wxDateTime"}}) ->
@@ -635,245 +651,200 @@ guard_test(#param{name=N,type={class,ignore}}) ->
guard_test(T) -> ?error({unknown_type,T}).
gen_doc(_Class, [#method{method_type=destructor}]) -> skip;
-gen_doc(_Class,[#method{name=N,alias=A,params=Ps,type=T,where=erl_no_opt,method_type=MT}])->
- w("%% @spec (~s~s) -> ~s~n",[doc_arg_types(Ps),"",doc_return_types(T,Ps)]),
+gen_doc(_Class,Ms=[#method{name=N,alias=A,params=Ps,where=erl_no_opt,method_type=MT}])->
w("%% @equiv ", []),
- 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,
- Def =:= none, In =/= false, Where =/= c],
- OptsType = case Optional of
- [] -> "";
- _ when NonDef =:= [] -> "[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),
- case Class of
- "utils" ->
- w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
- "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",
- [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}) ->
- doc_return_types(T,Ps)
- end,
- 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) ||
- P=#param{in=In,def=none,where=W} <- Ps,
- In =/= false, W =/= c] ++ Opt
- end,
- Args = zip(lists:map(GetArgs, Cs)),
- Ret = lists:map(GetRet, Cs),
- w("%% @spec (~s) -> ~s~n",[args(fun doc_arg/1,",",Args),doc_ret(Ret)]),
- case Class of
- "utils" ->
- w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
- "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",
- [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_function_clause(erl_func_name(N,A),MT,Ps,empty_list,[no_guards,name_only]),
+ w("~n-spec ",[]),
+ write_specs(Ms, "\n");
+gen_doc(Class,Ms=[#method{name=N, type=T}|Rest])->
+ %%doc_optional(Optional, normal),
+ doc_link(Class, N),
+ gen_overload_doc(Rest),
+ Ps = lists:foldl(fun(#method{params=Ps}, Acc) -> Ps ++ Acc end,[],Ms),
+ doc_enum_desc(lists:usort(doc_enum(T,Ps))),
+ w("-spec ",[]),
+ write_specs(Ms, "\n"),
ok.
-gen_doc2(Name,#method{params=Ps,where=erl_no_opt,method_type=MT}) ->
- w("%% <p><c>~n",[]),
- w("%% ~s(~s) -> ", [Name,doc_arg_types(Ps)]),
- gen_function_clause(Name,MT,Ps,empty_list,[no_guards,name_only]),
- w(" </c></p>~n",[]);
-gen_doc2(Name,#method{params=Ps,type=T}) ->
+gen_overload_doc([]) -> ok;
+%%gen_overload_doc(_) -> ok;
+gen_overload_doc(Cs) ->
+ w("%% <br /> Also:<br />~n%% ",[]),
+ write_specs(Cs, "<br />\n%% "),
+ w("~n", []).
+
+write_specs(M=[#method{method_type=constructor}|_], Eol) ->
+ w("new", []),
+ write_specs1(M, Eol);
+write_specs(M=[#method{name=N, alias=A}|_], Eol) ->
+ w("~s", [erl_func_name(N,A)]),
+ write_specs1(M, Eol).
+
+write_specs1([M], Eol) ->
+ write_spec(M, Eol),
+ w(".~s", [Eol]);
+write_specs1([M|Next], Eol) ->
+ write_spec(M, Eol),
+ w(";~s ", [Eol]),
+ write_specs1(Next, Eol).
+
+write_spec(#method{params=Ps,type=T,where=erl_no_opt}, Eol) ->
+ {NonDef, _Optional} = split_optional(Ps),
+ Res = doc_return_types(T,Ps),
+ write_spec(NonDef, [], Res, Eol);
+write_spec(#method{params=Ps,type=T}, Eol) ->
{NonDef, Optional} = split_optional(Ps),
- OptsType = case Optional of
- [] -> "";
- _ when NonDef =:= [] -> "[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)]),
- doc_optional(Optional, xhtml),
- DocEnum = doc_enum(T,Ps, xhtml),
- doc_enum_desc(DocEnum),
- w("%% </p>~n",[]).
-
-doc_arg(ArgList) ->
- case all_eq(ArgList) of
- true -> hd(ArgList);
- false ->
- Get = fun(Str) ->
- [_Name|Types] = string:tokens(Str, ":"),
- case Types of
- [Type] -> Type;
- _ ->
- "term()"
- end
- end,
- Args0 = lists:map(Get, ArgList),
- Args = unique(Args0, []),
- "X::" ++ args(fun(A) -> A end, "|", Args)
- end.
-
-doc_ret(ArgList) ->
- case all_eq(ArgList) of
- true -> hd(ArgList);
- false ->
- args(fun(A) -> A end, "|", ArgList)
- end.
-
-unique([], U) -> reverse(U);
-unique([H|R], U) ->
- case lists:member(H,U) of
- false -> unique(R,[H|U]);
- true -> unique(R,U)
- end.
-
-all_eq([H|R]) -> all_eq(R,H).
-
-all_eq([H|R],H) -> all_eq(R,H);
-all_eq([],_) -> true;
-all_eq(_,_) -> false.
-
-zip(List) ->
- zip(List, [], [], []).
-
-zip([[F|L1]|List], Rest, AccL, Acc) ->
- zip(List, [L1|Rest], [F|AccL], Acc);
-zip(Empty, Rest, AccL, Acc) ->
- true = empty(Empty),
- case empty(Rest) andalso empty(AccL) of
- true -> reverse(Acc);
- false ->
- zip(reverse(Rest), [], [], [reverse(AccL)|Acc])
- end.
-
-empty([[]|R]) -> empty(R);
-empty([]) -> true;
-empty(_) -> false.
+ Res = doc_return_types(T,Ps),
+ write_spec(NonDef, Optional, Res, Eol).
+
+write_spec([], [], {simple, Res}, _Eol) ->
+ w("() -> ~s", [Res]);
+write_spec([], [], {complex, Res}, Eol) ->
+ w("() -> Resultwhen~s\tResult ::~s", [Eol,Res]);
+write_spec(Args, [], {simple, Res}, Eol) ->
+ w("(~s) -> ~s when~s\t~s",
+ [erl_arg_names(Args), Res, Eol, doc_arg_types(Args)]);
+write_spec(Args, [], {complex, Res}, Eol) ->
+ w("(~s) -> Result when~s\tResult ::~s,~s\t~s",
+ [erl_arg_names(Args), Eol, Res, Eol, doc_arg_types(Args)]);
+write_spec([], Optional, {simple, Res}, Eol) ->
+ w("([Option]) -> ~s when~s\t~s",
+ [Res, Eol, optional_type(Optional, Eol)]);
+write_spec([], Optional, {complex, Res}, Eol) ->
+ w("([Option]) -> Result when~s\tResult :: ~s,~s\t~s",
+ [Eol, Res, Eol, optional_type(Optional, Eol)]);
+write_spec(Args, Optional, {simple, Res}, Eol) ->
+ w("(~s, [Option]) -> ~s when~s\t~s,~s\t~s",
+ [erl_arg_names(Args), Res, Eol, doc_arg_types(Args), Eol, optional_type(Optional, Eol)]);
+write_spec(Args, Optional, {complex, Res}, Eol) ->
+ w("(~s, [Option]) -> Result when~s\tResult :: ~s,~s\t~s,~s\t~s",
+ [erl_arg_names(Args), Eol, Res, Eol, doc_arg_types(Args), Eol, optional_type(Optional, Eol)]).
+
+optional_type(Opts, Eol) ->
+ "Option :: " ++ args(fun optional_type2/1, Eol++"\t\t | ", Opts).
+optional_type2(#param{name=Name, def=Def, type=T}) ->
+ "{" ++ erl_option_name(Name) ++ ", " ++ doc_arg_type2(T) ++ "}". %% %% Default: " ++ Def.
+
+doc_link("utils", Func) ->
+ w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
+ "external documentation</a>.~n",
+ [lowercase_all(Func)]);
+doc_link(Class, Func) ->
+ w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">"
+ "external documentation</a>.~n",
+ [lowercase_all(Class),lowercase_all(Class),lowercase_all(Func)]).
+
+erl_arg_names(Ps0) ->
+ Ps = [Name || #param{name=Name, in=In, where=Where} <- Ps0,In =/= false, Where =/= c],
+ args(fun erl_arg_name/1, ", ", Ps).
doc_arg_types(Ps0) ->
Ps = [P || P=#param{in=In, where=Where} <- Ps0,In =/= false, Where =/= c],
args(fun doc_arg_type/1, ", ", Ps).
-doc_arg_type(#param{name=Name,def=none,type=T}) ->
- erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T);
-doc_arg_type(#param{name=Name,in=false,type=T}) ->
- erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T);
-doc_arg_type(_) -> skip.
-
-doc_arg_type2(T=#type{single=Single}) when Single =:= array; Single =:= list ->
- "[" ++ doc_arg_type3(T) ++ "]";
+
+doc_arg_type(T) ->
+ doc_arg_type(T, in).
+
+doc_arg_type(#param{name=Name,def=none,type=T}, Out) ->
+ erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T, Out);
+doc_arg_type(#param{name=Name,in=false,type=T}, Out) ->
+ erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T, Out);
+doc_arg_type(_, _) -> skip.
+
doc_arg_type2(T) ->
- doc_arg_type3(T).
-
-doc_arg_type3(#type{base=string}) -> "string()";
-doc_arg_type3(#type{name="wxChar", single=S}) when S =/= true -> "string()";
-doc_arg_type3(#type{name="wxArrayString"}) -> "[string()]";
-doc_arg_type3(#type{name="wxDateTime"}) -> "wx:datetime()";
-doc_arg_type3(#type{name="wxArtClient"}) -> "string()";
-doc_arg_type3(#type{base=int}) -> "integer()";
-doc_arg_type3(#type{base=int64}) -> "integer()";
-doc_arg_type3(#type{base=long}) -> "integer()";
-doc_arg_type3(#type{name="wxTreeItemId"}) -> "wxTreeCtrl:treeItemId()";
-doc_arg_type3(#type{base=bool}) -> "bool()";
-doc_arg_type3(#type{base=float}) -> "float()";
-doc_arg_type3(#type{base=double}) -> "float()";
-doc_arg_type3(#type{base=binary}) -> "binary()";
-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),
- case get(current_class) of
- N -> N ++ "()";
- _ -> N++":" ++ N++"()"
+ doc_arg_type2(T, in).
+
+doc_arg_type2(T=#type{single=Single}, Out) when Single =:= array; Single =:= list ->
+ "[" ++ doc_arg_type3(T, Out) ++ "]";
+doc_arg_type2(T, Out) ->
+ doc_arg_type3(T, Out).
+
+doc_arg_type3(#type{base=string}, in) -> "unicode:chardata()";
+doc_arg_type3(#type{base=string}, out) -> "unicode:charlist()";
+doc_arg_type3(#type{name="wxChar", single=S},in) when S =/= true -> "unicode:chardata()";
+doc_arg_type3(#type{name="wxChar", single=S},out) when S =/= true -> "unicode:charlist()";
+doc_arg_type3(#type{name="wxArrayString"},in) -> "unicode:chardata()";
+doc_arg_type3(#type{name="wxArrayString"},out) -> "unicode:charlist()";
+doc_arg_type3(#type{name="wxDateTime"}, _) -> "wx:wx_datetime()";
+doc_arg_type3(#type{name="wxArtClient"}, _) -> "unicode:chardata()";
+doc_arg_type3(#type{base=int}, _) -> "integer()";
+doc_arg_type3(#type{base=int64}, _) -> "integer()";
+doc_arg_type3(#type{base=long}, _) -> "integer()";
+doc_arg_type3(#type{name="wxTreeItemId"}, _) -> "wxTreeCtrl:treeItemId()";
+doc_arg_type3(#type{base=bool}, _) -> "boolean()";
+doc_arg_type3(#type{base=float}, _) -> "number()";
+doc_arg_type3(#type{base=double}, _) -> "number()";
+doc_arg_type3(#type{base=binary}, _) -> "binary()";
+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}}, _) ->
+ ClassType = check_class(T),
+ Current = get(current_class),
+ if N =:= Current -> N ++ "()";
+ true -> ClassType
end;
-doc_arg_type3({merged,_,T1=#type{base={class,N1}},_,_,T2=#type{base={class,N2}},_}) ->
- check_class(T1),
- check_class(T2),
+doc_arg_type3({merged,_,T1=#type{base={class,N1}},_,_,T2=#type{base={class,N2}},_}, _) ->
+ CT1 = check_class(T1),
+ CT2 = check_class(T2),
Curr = get(current_class),
if
- N1 =:= Curr, N2 =:= Curr -> N1++"() | "++ N2++"()";
- N1 =:= Curr -> N1++"() | "++ N2++":" ++ N2++"()";
- N2 =:= Curr -> N1++":" ++ N1++"() | "++ N2++"()";
+ N1 =:= Curr, N2 =:= Curr -> N1++"()";
+ N1 =:= Curr -> N1++"() | "++ CT2;
+ N2 =:= Curr -> CT1 ++ " | "++ N2++"()";
true ->
- N1++":" ++ N1++"() | "++ N2++":" ++ N2++"()"
+ CT1 ++ " | " ++ CT2
end;
-doc_arg_type3(#type{base={enum,{_,N}}}) -> uppercase(N);
-doc_arg_type3(#type{base={enum,N}}) -> uppercase(N);
-doc_arg_type3(#type{base={comp,"wxColour",_Tup}}) ->
- "wx:colour()";
-doc_arg_type3(#type{base={comp,_,{record,Name}}}) ->
- "wx:" ++ atom_to_list(Name) ++ "()";
-doc_arg_type3(#type{base={comp,_,Tup}}) ->
+%% doc_arg_type3(#type{base={enum,{_,N}}}, _) -> uppercase(N);
+%% doc_arg_type3(#type{base={enum,N}}, _) -> uppercase(N);
+doc_arg_type3(#type{base={enum,_N}}, _) -> "wx:wx_enum()";
+doc_arg_type3(#type{base={comp,"wxColour",_Tup}}, in) ->
+ "wx:wx_colour()";
+doc_arg_type3(#type{base={comp,"wxColour",_Tup}}, out) ->
+ "wx:wx_colour4()";
+doc_arg_type3(#type{base={comp,_,{record,Name}}}, _) ->
+ "wx:wx_" ++ atom_to_list(Name) ++ "()";
+doc_arg_type3(#type{base={comp,_,Tup}}, _) ->
Doc = fun({int,V}) -> V ++ "::integer()";
({double,V}) -> V ++ "::float()"
end,
- "{" ++ args(Doc, ",", Tup) ++ "}";
-doc_arg_type3(T) -> ?error({unknown_type,T}).
+ "{" ++ args(Doc, ", ", Tup) ++ "}";
+doc_arg_type3(T, _) -> ?error({unknown_type,T}).
doc_return_types(T, Ps) ->
doc_return_types2(T, [P || P=#param{in=In} <- Ps,In =/= true]).
-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, []) -> {simple, "ok"};
+doc_return_types2(void, [#param{type=T}]) -> {simple, doc_arg_type2(T, out)};
+doc_return_types2(T, []) -> {simple, doc_arg_type2(T, out)};
+doc_return_types2(void, Ps) when length(Ps) < 4 ->
+ {simple, "{" ++ args(fun(Arg) -> doc_arg_type(Arg, out) end,", ",Ps) ++ "}"};
doc_return_types2(void, Ps) ->
- "{" ++ args(fun doc_arg_type/1,",",Ps) ++ "}";
+ {complex, "{" ++ args(fun(Arg) -> doc_arg_type(Arg, out) end,", ",Ps) ++ "}"};
doc_return_types2(T, Ps) ->
- "{" ++ doc_arg_type2(T) ++ "," ++ args(fun doc_arg_type/1,",",Ps) ++ "}".
-
-break(xhtml) -> "<br />";
-break(_) -> "".
-
-doc_optional([],_) -> ok;
-doc_optional(Opts,Type) ->
- w("%%~s Option = ~s~n", [break(Type),args(fun doc_optional2/1, " | ", Opts)]).
+ {complex, "{Res ::" ++ doc_arg_type2(T, out) ++ ", " ++
+ args(fun(Arg) -> doc_arg_type(Arg, out) end,", ",Ps) ++ "}"}.
-doc_optional2(#param{name=Name, def=_Def, type=T}) ->
- "{" ++ erl_option_name(Name) ++ ", " ++ doc_arg_type2(T) ++ "}".
+doc_enum(#type{base={enum,Enum}},Ps) ->
+ [doc_enum_type(Enum, "res") |
+ [doc_enum_type(Type,Name) || #param{name=Name, type=#type{base={enum,Type}}} <- Ps]];
+doc_enum(_,Ps) ->
+ [doc_enum_type(Type,Name) || #param{name=Name, type=#type{base={enum,Type}}} <- Ps].
-doc_enum(#type{base={enum,Enum}},Ps,Break) ->
- [doc_enum_type(Enum,Break) |
- [doc_enum_type(Type,Break) || #param{type=#type{base={enum,Type}}} <- Ps]];
-doc_enum(_,Ps,Break) ->
- [doc_enum_type(Type,Break) || #param{type=#type{base={enum,Type}}} <- Ps].
-
-doc_enum_type(Type,Break) ->
+doc_enum_type(Type, Name) ->
{Enum0, #enum{vals=Vals}} = wx_gen:get_enum(Type),
- case Enum0 of {_, Enum} -> Enum; Enum -> Enum end,
+ Enum = case Enum0 of {_, E} -> E; E -> E end,
Consts = get(consts),
- Format = fun({Name,_What}) ->
- #const{name=Name} = gb_trees:get(Name, Consts),
- "?" ++ enum_name(Name)
+ Format = fun({N,_What}) ->
+ #const{name=N} = gb_trees:get(N, Consts),
+ "?" ++ enum_name(N)
end,
Vs = args(Format, " | ", Vals),
- w("%%~s ~s = integer()~n", [break(Break),uppercase(Enum)]),
- {uppercase(Enum),Vs}.
+ {uppercase(Enum),Name, Vs}.
doc_enum_desc([]) -> ok;
-doc_enum_desc([{Enum,Vs}|R]) ->
- w("%%<br /> ~s is one of ~s~n", [Enum,Vs]),
+doc_enum_desc([{_Enum,Name,Vs}|R]) ->
+ w("%%<br /> ~s = ~s~n", [erl_arg_name(Name),Vs]),
doc_enum_desc(R).
%% Misc functions prefixed with wx
@@ -993,7 +964,7 @@ marshal_arg(#type{single=true,base={comp,_,Comp}}, Name, Align0) ->
Str = args(fun(Str) -> Str end, ",", A),
{Str,(Align0 + length(Comp)) rem 2};
{double,_} ->
- A = [Name++Spec++":64/float" || {double,Spec} <- Comp],
+ A = [Name++Spec++":64/?F" || {double,Spec} <- Comp],
Str = args(fun(Str) -> Str end, ",", A),
align(64,Align0,Str)
end;
@@ -1019,9 +990,14 @@ marshal_arg(#type{base=Base, single=Single}, Name, Align0)
Str0 = "(length("++Name++")):32/?UI,\n"
" (<< <<X:32/?I,Y:32/?I>> || {X,Y} <- "++Name++">>)/binary",
align(32,Align0, Str0);
+ {comp, "wxPoint2DDouble", _} ->
+ Str0 = "(length("++Name++")):32/?UI,\n",
+ Str1 = " (<< <<X:64/?F,Y:64/?F>> || {X,Y} <- "++Name++">>)/binary",
+ {Str,_Align} = align(64,Align0+1, Str1),
+ {Str0 ++ Str, 0};
double ->
Str0 = "(length("++Name++")):32/?UI,\n",
- Str1 = " (<< <<C:64/float>> || C <- "++Name++">>)/binary",
+ Str1 = " (<< <<C:64/?F>> || C <- "++Name++">>)/binary",
{Str,_Align} = align(64,Align0+1, Str1),
{Str0 ++ Str, 0};
_ ->
@@ -1048,12 +1024,13 @@ enum_name(Name) ->
gen_enums_ints() ->
%% open_write("../include/wx.hrl"), opened in gen_event_recs
w("~n%% Hardcoded Records~n", []),
- w("-record(wxMouseState, {x, y, %% integer()~n"
- " leftDown, middleDown, rightDown, %% bool()~n"
- " controlDown, shiftDown, altDown, metaDown, cmdDown %% bool()~n"
+ w("-record(wxMouseState, {x :: integer(), y :: integer(),~n"
+ " leftDown :: boolean(), middleDown :: boolean, rightDown :: boolean, ~n"
+ " controlDown :: boolean(), shiftDown :: boolean(),~n"
+ " altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean()~n"
" }).~n", []),
w("-record(wxHtmlLinkInfo, {~n"
- " href, target %% string()~n"
+ " href :: unicode:chardata(), target :: unicode:chardata()~n"
" }).~n", []),
w("~n%% Hardcoded Defines~n", []),
Enums = [E || {{enum,_},E = #enum{as_atom=false}} <- get()],
@@ -1083,16 +1060,16 @@ build_enum_ints(#enum{from=From, vals=Vals},Done) ->
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) ->
+ (#const{name=Name,val=Value,is_const=true}) when is_number(Value) ->
w("-define(~s, ~p).~n", [enum_name(Name),Value]);
- (#const{name=Name,val=Value,is_const=false}) when is_integer(Value) ->
+ (#const{name=Name,val=Value,is_const=false}) when is_number(Value) ->
w("-define(~s, wxe_util:get_const(~s)).~n", [enum_name(Name),enum_name(Name)]);
(#const{name=Name,val={Str,0}}) ->
case string:tokens(Str, " |()") of
[Token] ->
- w("-define(~s, ?~s).~n", [enum_name(Name),Token]);
+ w("-define(~s, ~s).~n", [enum_name(Name),const_value(Token)]);
Tokens ->
- Def = args(fun(T) -> [$?|T] end, " bor ", Tokens),
+ Def = args(fun(T) -> const_value(T) end, " bor ", Tokens),
w("-define(~s, (~s)).~n", [enum_name(Name),Def])
end;
(#const{name=Name,val={Str,N}}) ->
@@ -1117,6 +1094,17 @@ build_enum_ints(#enum{from=From, vals=Vals},Done) ->
end,
lists:foldl(Write, Done, Vals).
+const_value(V) when is_integer(V) -> integer_to_list(V);
+const_value(V = "16#" ++ IntList) ->
+ _ = http_util:hexlist_to_integer(IntList), %% ASSERT
+ V;
+const_value(V0) ->
+ try
+ _ = list_to_integer(V0),
+ V0
+ catch _:_ -> [$?|V0]
+ end.
+
gen_event_recs() ->
open_write("../include/wx.hrl"),
erl_copyright(),
@@ -1126,82 +1114,53 @@ gen_event_recs() ->
"%% 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"
- " obj, %% Object reference that was used in the connect call.~n"
- " userData, %% User data specified in the connect call.~n"
- " event}).%% The event record~n~n",[]),
+ w("-record(wx, {id :: integer(), %% Integer Identity of object.~n"
+ " obj :: wx:wx_object(), %% Object reference that was used in the connect call.~n"
+ " userData :: term(), %% User data specified in the connect call.~n"
+ " event :: event() %% The event record~n"
+ " }).~n~n", []),
+ w("-type wx() :: #wx{}. %% wx event record ~n",[]),
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",
- [args(fun(Ev) -> Ev end, " | ", lists:sort(lists:append(Types)))]),
+ Events = [build_event_rec(C) || {_,C=#class{event=Evs}} <- get(), Evs =/= false],
+ EventSubTypes = [Type || {_Rec, Type} <- Events],
+ EventRecs = [Rec || {Rec, _Type} <- Events],
+ w("-type event() :: ~s.~n",
+ [args(fun(Ev) -> Ev++"()" end, " | ", lists:sort(EventRecs))]),
+
+ w("-type wxEventType() :: ~s.~n",
+ [args(fun(Ev) -> Ev++"()" end, " | ", lists:sort(EventSubTypes))]),
%% close(), closed in gen_enums_ints
ok.
-find_inherited_attr(Param = {PName,_}, Name) ->
- #class{parent=Parent, attributes=Attrs} = get({class, Name}),
- case lists:keysearch(atom_to_list(PName), #param.name, Attrs) of
- {value, P=#param{}} ->
- P;
- _ ->
- find_inherited_attr(Param, Parent)
- end.
-
-filter_attrs(#class{name=Name, parent=Parent,attributes=Attrs}) ->
- Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc;
- (P=#param{prot=public},Acc) -> [P|Acc];
- (#param{acc=undefined},Acc) -> Acc;
- ({inherited, PName},Acc) ->
- case find_inherited_attr(PName, Parent) of
- undefined ->
- io:format("~p:~p: Missing Event Attr ~p in ~p~n",
- [?MODULE,?LINE, PName, Name]),
- Acc;
- 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),
+ Str = args(fun(Ev) -> Ev end, " | ", EvTypes),
Attr = filter_attrs(Class),
Rec = event_rec_name(Name),
- GetName = fun(#param{name=N}) ->event_attr_name(N) end,
+ %%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,
+ EventType = Name ++ "Type",
case Attr =:= [] of
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
-%% 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]);
+ %% w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]),
+ %% w("%% Callback event: {@link ~s}~n", [Name]),
+ w("-record(~s, {type :: ~s()}). %% Callback event: {@link ~s}~n",
+ [Rec, EventType, Name]),
+ w("-type ~s() :: ~s.~n", [EventType, Str]);
false ->
- 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
-%% 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, ~s}).~n~n", [Rec,args(GetName,",",Attr)])
+ %% w("%% @type ~s() = #~s{type=wxEventType(),~s}.~n",
+ %% [Rec,Rec,args(GetType,",",Attr)]),
+ %% w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]),
+ %% w("%% Callback event: {@link ~s}~n", [Name]),
+ w("-record(~s,{type :: ~s(), %% Callback event: {@link ~s}~n\t~s}).~n",
+ [Rec,EventType, Name, args(GetType,",\n\t",Attr)]),
+ w("-type ~s() :: ~s.~n", [EventType, Str])
end,
- EvTypes.
-
-is_command_event(Name) ->
- case lists:member("wxCommandEvent", parents(Name)) of
- true -> true;
- false -> false
- end.
+ w("-type ~s() :: #~s{}. %% Callback event: {@link ~s}~n~n", [Rec,Rec,Name]),
+ {Rec, EventType}.
event_rec_name(Name0 = "wx" ++ _) ->
"tnevE" ++ Name1 = reverse(Name0),
@@ -1218,6 +1177,31 @@ event_attr_name("m_" ++ Attr) ->
event_attr_name(Attr) ->
lowercase(Attr).
+find_inherited_attr(Param = {PName,_}, Name) ->
+ #class{parent=Parent, attributes=Attrs} = get({class, Name}),
+ case lists:keysearch(atom_to_list(PName), #param.name, Attrs) of
+ {value, P=#param{}} ->
+ P;
+ _ ->
+ find_inherited_attr(Param, Parent)
+ end.
+
+filter_attrs(#class{name=Name, parent=Parent,attributes=Attrs}) ->
+ Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc;
+ (P=#param{prot=public},Acc) -> [P|Acc];
+ (#param{acc=undefined},Acc) -> Acc;
+ ({inherited, PName},Acc) ->
+ case find_inherited_attr(PName, Parent) of
+ undefined ->
+ io:format("~p:~p: Missing Event Attr ~p in ~p~n",
+ [?MODULE,?LINE, PName, Name]),
+ Acc;
+ P ->
+ [P|Acc]
+ end;
+ (P, Acc) -> [P|Acc]
+ end, [], Attrs),
+ lists:reverse(Attr1).
gen_funcnames() ->
open_write("../src/gen/wxe_debug.hrl"),
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index 8ee4451057..1f6225ce60 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,9 +330,11 @@
{'DrawRotatedText',3}, 'DrawRoundedRectangle',%'DrawSpline',
{'DrawText',2},
'EndDoc','EndPage',{'FloodFill',3},'GetBackground','GetBackgroundMode',
- 'GetBrush','GetCharHeight','GetCharWidth',{'GetClippingBox',1},'GetFont',
- 'GetLayoutDirection','GetLogicalFunction','GetMapMode','GetMultiLineTextExtent',
- 'GetPartialTextExtents','GetPen',{'GetPixel',2},'GetPPI','GetSize','GetSizeMM',
+ 'GetBrush','GetCharHeight','GetCharWidth',{'GetClippingBox',[{"rect", skip_member}]},
+ 'GetFont','GetLayoutDirection','GetLogicalFunction','GetMapMode','GetMultiLineTextExtent',
+ {'GetPartialTextExtents', [{"widths", out}]},
+ 'GetPen',{'GetPixel', [{"col", out}, {"x", skip_member}]},
+ 'GetPPI','GetSize','GetSizeMM',
'GetTextBackground','GetTextExtent','GetTextForeground',
'GetUserScale','GradientFillConcentric','GradientFillLinear',
'LogicalToDeviceX','LogicalToDeviceXRel','LogicalToDeviceY','LogicalToDeviceYRel',
@@ -355,20 +357,28 @@
%%{class,wxAutoBufferedPaintDC,wxBufferedPaintDC,[],['wxAutoBufferedPaintDC']}.
{class, wxGraphicsObject, object, [{ifdef, wxUSE_GRAPHICS_CONTEXT}],
- ['GetRenderer','IsNull']}.
-{class, wxGraphicsContext, wxGraphicsObject, [{ifdef, wxUSE_GRAPHICS_CONTEXT}],
- ['Create', %%CreateFromNative CreateFromNativeWindow
+ ['~wxGraphicsObject', 'GetRenderer','IsNull']}.
+{class, wxGraphicsContext, wxGraphicsObject,
+ [{ifdef, wxUSE_GRAPHICS_CONTEXT}, {skip, [{'StrokeLines',4}]}],
+ ['~wxGraphicsContext',
+ 'Create', %%CreateFromNative CreateFromNativeWindow
'CreatePen','CreateBrush','CreateRadialGradientBrush',
'CreateLinearGradientBrush','CreateFont','CreateMatrix',
'CreatePath','Clip','ResetClip',
- 'DrawBitmap','DrawEllipse','DrawIcon','DrawLines','DrawPath',
+ 'DrawBitmap','DrawEllipse','DrawIcon',
+ {'DrawLines', [{"n",{c_only,{length,"points"}}}, {"points", {single,array}}]},
+ 'DrawPath',
'DrawRectangle','DrawRoundedRectangle','DrawText','FillPath',
- 'StrokePath','GetNativeContext','GetPartialTextExtents',
+ 'StrokePath', %% 'GetNativeContext',
+ {'GetPartialTextExtents', [{"widths", out}]},
'GetTextExtent','Rotate','Scale','Translate',
'GetTransform','SetTransform','ConcatTransform',
- 'SetBrush','SetFont','SetPen','StrokeLine','StrokeLines']}.
+ 'SetBrush','SetFont','SetPen','StrokeLine',
+ {'StrokeLines', [{"n",{c_only,{length,"points"}}}, {"points", {single,array}}]}
+ ]}.
{class, wxGraphicsMatrix, wxGraphicsObject, [{ifdef, wxUSE_GRAPHICS_CONTEXT}],
- ['Concat','Get','GetNativeMatrix','Invert','IsEqual','IsIdentity',
+ ['Concat','Get',%%'GetNativeMatrix',
+ 'Invert','IsEqual','IsIdentity',
'Rotate','Scale','Translate','Set','TransformPoint','TransformDistance']}.
{class, wxGraphicsPath, wxGraphicsObject, [{ifdef, wxUSE_GRAPHICS_CONTEXT}],
['MoveToPoint','AddArc','AddArcToPoint','AddCircle','AddCurveToPoint',
@@ -400,17 +410,17 @@
{class, wxControl, wxWindow, [], [% 'Command','GetLabelText',
'GetLabel','SetLabel']}.
-{class, wxControlWithItems, wxControl,
- [{skip, [{'GetClientObject',1},{'SetClientObject',2}]}],
+{class, wxControlWithItems, wxControl,
+ [{skip, [{'GetClientObject',1},{'SetClientObject',2}]}],
[
- {'Append',[{"clientData",[{skip_member, void}]},
- {"strings", [{erl_func, "appendStrings"}]}]},
+ {'Append',[{"clientData",[{skip_member, voidp}]},
+ {"strings", [{erl_func, "appendStrings"}]}]},
'Clear','Delete','FindString',
%% 'GetClientData','SetClientData',
{'GetClientObject', [{"n", [{erl_func, "getClientData"}]}]},
{'SetClientObject', [{"n", [{erl_func, "setClientData"}]}]},
'GetCount','GetSelection','GetString','GetStringSelection',
- {'Insert',[{"clientData",[{skip_member, void}]}]},%'Number',
+ {'Insert',[{"clientData",[{skip_member, voidp}]}]},%'Number',
'IsEmpty','Select','SetSelection','SetString','SetStringSelection'
]}.
@@ -766,10 +776,12 @@
'GetEditControl',
'GetImageList','GetItem','GetItemBackgroundColour',
'GetItemCount',{'GetItemData', [{return, {base,int}}]},
- 'GetItemFont','GetItemPosition','GetItemRect',
- 'GetItemSpacing','GetItemState','GetItemText','GetItemTextColour',
+ 'GetItemFont', {'GetItemPosition', [{"pos", out}]},{'GetItemRect',[{"rect", out}]},
+ 'GetItemSpacing','GetItemState',
+ 'GetItemText','GetItemTextColour',
'GetNextItem','GetSelectedItemCount','GetTextColour','GetTopItem',
- 'GetViewRect',{'HitTest',[{"pSubItem",nowhere}]},'InsertColumn','InsertItem',
+ 'GetViewRect',{'HitTest',[{"pSubItem",nowhere}, {"flags", in}]},
+ 'InsertColumn','InsertItem',
%%'OnGetItemAttr', 'OnGetItemImage','OnGetItemText',
'RefreshItem','RefreshItems','ScrollList',
'SetBackgroundColour','SetColumn','SetColumnWidth','SetImageList','SetItem',
@@ -1592,9 +1604,9 @@
'HomeWrapExtend', 'LineEndWrap', 'LineEndWrapExtend', 'VCHomeWrap', 'VCHomeWrapExtend', 'LineCopy',
'MoveCaretInsideView', 'LineLength', 'BraceHighlight', 'BraceBadLight', 'BraceMatch', 'GetViewEOL',
'SetViewEOL', %'GetDocPointer', 'SetDocPointer', Hmm void pointers
- 'SetModEventMask', 'GetEdgeColumn', 'SetEdgeColumn',
- 'GetEdgeMode', 'GetEdgeColour', 'SetEdgeColour', 'SearchAnchor', 'SearchNext',
- 'SearchPrev', 'LinesOnScreen',
+ 'SetModEventMask', 'GetEdgeColumn', 'SetEdgeColumn',
+ 'SetEdgeMode', 'GetEdgeMode', 'GetEdgeColour', 'SetEdgeColour', 'SearchAnchor', 'SearchNext',
+ 'SearchPrev', 'LinesOnScreen',
'UsePopUp', 'SelectionIsRectangle', 'SetZoom', 'GetZoom',
%%'CreateDocument', 'AddRefDocument', 'ReleaseDocument', Hmm void pointers
'GetModEventMask', 'SetSTCFocus', 'GetSTCFocus', 'SetStatus', 'GetStatus',
@@ -1755,6 +1767,9 @@
'GetColour','GetFont','GetMetric','GetScreenType'
]}.
+{class, wxSystemOptions, object, [],
+ ['GetOption', 'GetOptionInt', 'HasOption', 'IsFalse', 'SetOption']}.
+
{class, wxAuiNotebookEvent, wxNotifyEvent,
[{acc, [{old_selection, "GetOldSelection()"},
{selection, "GetSelection()"},
@@ -1800,4 +1815,14 @@
{class, wxLogNull, root, [],
[wxLogNull, '~wxLogNull']}.
-
+
+{class, wxTaskBarIcon, wxEvtHandler, [],
+ [wxTaskBarIcon,'~wxTaskBarIcon',
+ %%'CreatePopupMenu', virtual overrided is a callback
+ %% 'IsIconInstalled', 'IsOk', not available on mac
+ 'PopupMenu','RemoveIcon','SetIcon']}.
+
+{class, wxTaskBarIconEvent, wxEvent,
+ [{event,[wxEVT_TASKBAR_MOVE,wxEVT_TASKBAR_LEFT_DOWN,wxEVT_TASKBAR_LEFT_UP,
+ wxEVT_TASKBAR_RIGHT_DOWN,wxEVT_TASKBAR_RIGHT_UP,
+ wxEVT_TASKBAR_LEFT_DCLICK,wxEVT_TASKBAR_RIGHT_DCLICK]}],[]}.
diff --git a/lib/wx/c_src/Makefile.in b/lib/wx/c_src/Makefile.in
index 69418f62ef..1497ac4d16 100644
--- a/lib/wx/c_src/Makefile.in
+++ b/lib/wx/c_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
#
# The 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,6 +31,8 @@ override TYPE=opt
endif
SO_EXT = @SO_EXT@
+OBJC_CC=@OBJC_CC@
+OBJC_CFLAGS=@OBJC_CFLAGS@
GENERAL = wxe_driver wxe_ps_init wxe_impl wxePrintout wxe_return wxe_gl
GENERAL_H = wxe_driver.h wxe_impl.h wxe_return.h
@@ -43,20 +45,11 @@ GL_H = egl_impl.h gen/glu_finit.h gen/gl_finit.h gen/gl_fdefs.h
HAVE_OPENGL = true
OPENGL_F = gl_funcs egl_impl
-ifneq ($(INSIDE_ERLSRC),true)
-
-ERL_DIR = @ERLANG_ROOT_DIR@
-ERL_INCS = -I$(ERL_DIR)/usr/include
-
-else
-
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
ERL_INCS= $(DED_INCLUDES)
-endif
-
SYS_TYPE = @WXERL_SYS_TYPE@
GENERAL_O = $(GENERAL:%=$(SYS_TYPE)/%.o)
@@ -116,6 +109,7 @@ endif
GL_LIBS = @GL_LIBS@
CC_O = $(CC) -c $(CFLAGS) $(WX_CFLAGS) $(COMMON_CFLAGS)
+OBJC_CC_O = $(OBJC_CC) -c $(CFLAGS) $(OBJC_CFLAGS) $(WX_CFLAGS) $(COMMON_CFLAGS)
CPP_O = $(CPP) -c $(CXX_FLAGS) $(WX_CXX_FLAGS) $(COMMON_CFLAGS)
# Targets
@@ -152,6 +146,10 @@ $(SYS_TYPE)/%.o: %.c
mkdir -p $(SYS_TYPE)
$(CC_O) $< -o $@
+$(SYS_TYPE)/wxe_ps_init.o: wxe_ps_init.c
+ mkdir -p $(SYS_TYPE)
+ $(OBJC_CC_O) $< -o $@
+
$(SYS_TYPE)/%.o: gen/%.cpp
mkdir -p $(SYS_TYPE)
$(CPP_O) $< -o $@
@@ -176,15 +174,12 @@ $(TARGET_DIR)/erl_gl$(SO_EXT): $(GL_OBJECTS)
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
-ifeq ($(INSIDE_ERLSRC),true)
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) ../priv/erlang-logo32.png $(RELSYSDIR)/priv/
- $(INSTALL_DATA) ../priv/erlang-logo64.png $(RELSYSDIR)/priv/
- $(INSTALL_PROGRAM) $(TARGET_DIR)/wxe_driver$(SO_EXT) $(RELSYSDIR)/priv/
- $(INSTALL_PROGRAM) $(TARGET_DIR)/erl_gl$(SO_EXT) $(RELSYSDIR)/priv/
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) ../priv/erlang-logo32.png "$(RELSYSDIR)/priv/"
+ $(INSTALL_DATA) ../priv/erlang-logo64.png "$(RELSYSDIR)/priv/"
+ $(INSTALL_PROGRAM) $(TARGET_DIR)/wxe_driver$(SO_EXT) "$(RELSYSDIR)/priv/"
+ $(INSTALL_PROGRAM) $(TARGET_DIR)/erl_gl$(SO_EXT) "$(RELSYSDIR)/priv/"
release_docs_spec:
-
-endif
diff --git a/lib/wx/c_src/egl_impl.cpp b/lib/wx/c_src/egl_impl.cpp
index 6d873abc44..1379f07523 100644
--- a/lib/wx/c_src/egl_impl.cpp
+++ b/lib/wx/c_src/egl_impl.cpp
@@ -70,8 +70,8 @@ typedef char DL_CHAR;
# define OPENGL_LIB "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"
# define OPENGLU_LIB "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib"
# else
-# define OPENGL_LIB "libGL.so"
-# define OPENGLU_LIB "libGLU.so"
+# define OPENGL_LIB "libGL.so.1"
+# define OPENGLU_LIB "libGLU.so.1"
# endif
#endif
extern "C" {
@@ -121,7 +121,7 @@ int load_gl_functions() {
}
}
}
- dlclose(LIBhandle);
+ // dlclose(LIBhandle);
// fprintf(stderr, "OPENGL library is loaded\r\n");
} else {
fprintf(stderr, "Could NOT load OpenGL library: %s\r\n", DLName);
@@ -150,7 +150,7 @@ int load_gl_functions() {
}
}
}
- dlclose(LIBhandle);
+ // dlclose(LIBhandle);
// fprintf(stderr, "GLU library is loaded\r\n");
} else {
fprintf(stderr, "Could NOT load OpenGL GLU library: %s\r\n", DLName);
@@ -195,7 +195,7 @@ egl_ogla_error(GLenum errorCode)
// msg.Printf(wxT("Tesselation error: %d: "), (int)errorCode);
// msg += wxString::FromAscii((char *) err);
// send_msg("error", &msg);
- fprintf(stderr, "Tesselation error: %d\r\n", (int) errorCode);
+ fprintf(stderr, "Tesselation error: %d: %s\r\n", (int) errorCode, err);
}
void CALLBACK
@@ -250,7 +250,7 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
int *vertices;
int num_vertices;
GLdouble *n;
- int n_pos, AP, res;
+ int n_pos, AP;
num_vertices = * (int *) buff; buff += 8; /* Align */
n = (double *) buff; buff += 8*3;
@@ -293,7 +293,7 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
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);
+ driver_send_term(port,caller,rt,AP);
/* fprintf(stderr, "List %d: %d %d %d \r\n", */
/* res, */
/* n_pos, */
diff --git a/lib/wx/c_src/gen/gl_fdefs.h b/lib/wx/c_src/gen/gl_fdefs.h
index a45896d30d..3e742724aa 100644
--- a/lib/wx/c_src/gen/gl_fdefs.h
+++ b/lib/wx/c_src/gen/gl_fdefs.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The 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,308 +31,180 @@ typedef struct {
} gl_fns_t;
#define GLE_GL_FUNC_START 5037
-typedef void (APIENTRY * WXEGLACCUM)(GLenum,GLfloat);
-WXE_EXTERN WXEGLACCUM weglAccum;
-typedef void (APIENTRY * WXEGLALPHAFUNC)(GLenum,GLclampf);
-WXE_EXTERN WXEGLALPHAFUNC weglAlphaFunc;
-typedef GLboolean (APIENTRY * WXEGLARETEXTURESRESIDENT)(GLsizei,const GLuint *,GLboolean *);
-WXE_EXTERN WXEGLARETEXTURESRESIDENT weglAreTexturesResident;
-typedef void (APIENTRY * WXEGLARRAYELEMENT)(GLint);
-WXE_EXTERN WXEGLARRAYELEMENT weglArrayElement;
-typedef void (APIENTRY * WXEGLBEGIN)(GLenum);
-WXE_EXTERN WXEGLBEGIN weglBegin;
-typedef void (APIENTRY * WXEGLBINDTEXTURE)(GLenum,GLuint);
-WXE_EXTERN WXEGLBINDTEXTURE weglBindTexture;
-typedef void (APIENTRY * WXEGLBITMAP)(GLsizei,GLsizei,GLfloat,GLfloat,GLfloat,GLfloat,const GLubyte *);
-WXE_EXTERN WXEGLBITMAP weglBitmap;
-typedef void (APIENTRY * WXEGLBLENDFUNC)(GLenum,GLenum);
-WXE_EXTERN WXEGLBLENDFUNC weglBlendFunc;
-typedef void (APIENTRY * WXEGLCALLLIST)(GLuint);
-WXE_EXTERN WXEGLCALLLIST weglCallList;
-typedef void (APIENTRY * WXEGLCALLLISTS)(GLsizei,GLenum,const GLuint *);
-WXE_EXTERN WXEGLCALLLISTS weglCallLists;
-typedef void (APIENTRY * WXEGLCLEAR)(GLbitfield);
-WXE_EXTERN WXEGLCLEAR weglClear;
-typedef void (APIENTRY * WXEGLCLEARACCUM)(GLfloat,GLfloat,GLfloat,GLfloat);
-WXE_EXTERN WXEGLCLEARACCUM weglClearAccum;
-typedef void (APIENTRY * WXEGLCLEARCOLOR)(GLclampf,GLclampf,GLclampf,GLclampf);
-WXE_EXTERN WXEGLCLEARCOLOR weglClearColor;
-typedef void (APIENTRY * WXEGLCLEARDEPTH)(GLclampd);
-WXE_EXTERN WXEGLCLEARDEPTH weglClearDepth;
typedef void (APIENTRY * WXEGLCLEARINDEX)(GLfloat);
WXE_EXTERN WXEGLCLEARINDEX weglClearIndex;
-typedef void (APIENTRY * WXEGLCLEARSTENCIL)(GLint);
-WXE_EXTERN WXEGLCLEARSTENCIL weglClearStencil;
-typedef void (APIENTRY * WXEGLCLIPPLANE)(GLenum,const GLdouble *);
-WXE_EXTERN WXEGLCLIPPLANE weglClipPlane;
-typedef void (APIENTRY * WXEGLCOLOR3BV)(const GLbyte *);
-WXE_EXTERN WXEGLCOLOR3BV weglColor3bv;
-typedef void (APIENTRY * WXEGLCOLOR3DV)(const GLdouble *);
-WXE_EXTERN WXEGLCOLOR3DV weglColor3dv;
-typedef void (APIENTRY * WXEGLCOLOR3FV)(const GLfloat *);
-WXE_EXTERN WXEGLCOLOR3FV weglColor3fv;
-typedef void (APIENTRY * WXEGLCOLOR3IV)(const GLint *);
-WXE_EXTERN WXEGLCOLOR3IV weglColor3iv;
-typedef void (APIENTRY * WXEGLCOLOR3SV)(const GLshort *);
-WXE_EXTERN WXEGLCOLOR3SV weglColor3sv;
-typedef void (APIENTRY * WXEGLCOLOR3UBV)(const GLubyte *);
-WXE_EXTERN WXEGLCOLOR3UBV weglColor3ubv;
-typedef void (APIENTRY * WXEGLCOLOR3UIV)(const GLuint *);
-WXE_EXTERN WXEGLCOLOR3UIV weglColor3uiv;
-typedef void (APIENTRY * WXEGLCOLOR3USV)(const GLushort *);
-WXE_EXTERN WXEGLCOLOR3USV weglColor3usv;
-typedef void (APIENTRY * WXEGLCOLOR4BV)(const GLbyte *);
-WXE_EXTERN WXEGLCOLOR4BV weglColor4bv;
-typedef void (APIENTRY * WXEGLCOLOR4DV)(const GLdouble *);
-WXE_EXTERN WXEGLCOLOR4DV weglColor4dv;
-typedef void (APIENTRY * WXEGLCOLOR4FV)(const GLfloat *);
-WXE_EXTERN WXEGLCOLOR4FV weglColor4fv;
-typedef void (APIENTRY * WXEGLCOLOR4IV)(const GLint *);
-WXE_EXTERN WXEGLCOLOR4IV weglColor4iv;
-typedef void (APIENTRY * WXEGLCOLOR4SV)(const GLshort *);
-WXE_EXTERN WXEGLCOLOR4SV weglColor4sv;
-typedef void (APIENTRY * WXEGLCOLOR4UBV)(const GLubyte *);
-WXE_EXTERN WXEGLCOLOR4UBV weglColor4ubv;
-typedef void (APIENTRY * WXEGLCOLOR4UIV)(const GLuint *);
-WXE_EXTERN WXEGLCOLOR4UIV weglColor4uiv;
-typedef void (APIENTRY * WXEGLCOLOR4USV)(const GLushort *);
-WXE_EXTERN WXEGLCOLOR4USV weglColor4usv;
+typedef void (APIENTRY * WXEGLCLEARCOLOR)(GLclampf,GLclampf,GLclampf,GLclampf);
+WXE_EXTERN WXEGLCLEARCOLOR weglClearColor;
+typedef void (APIENTRY * WXEGLCLEAR)(GLbitfield);
+WXE_EXTERN WXEGLCLEAR weglClear;
+typedef void (APIENTRY * WXEGLINDEXMASK)(GLuint);
+WXE_EXTERN WXEGLINDEXMASK weglIndexMask;
typedef void (APIENTRY * WXEGLCOLORMASK)(GLboolean,GLboolean,GLboolean,GLboolean);
WXE_EXTERN WXEGLCOLORMASK weglColorMask;
-typedef void (APIENTRY * WXEGLCOLORMATERIAL)(GLenum,GLenum);
-WXE_EXTERN WXEGLCOLORMATERIAL weglColorMaterial;
-typedef void (APIENTRY * WXEGLCOLORPOINTER)(GLint,GLenum,GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLCOLORPOINTER weglColorPointer;
-typedef void (APIENTRY * WXEGLCOPYPIXELS)(GLint,GLint,GLsizei,GLsizei,GLenum);
-WXE_EXTERN WXEGLCOPYPIXELS weglCopyPixels;
-typedef void (APIENTRY * WXEGLCOPYTEXIMAGE1D)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLint);
-WXE_EXTERN WXEGLCOPYTEXIMAGE1D weglCopyTexImage1D;
-typedef void (APIENTRY * WXEGLCOPYTEXIMAGE2D)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
-WXE_EXTERN WXEGLCOPYTEXIMAGE2D weglCopyTexImage2D;
-typedef void (APIENTRY * WXEGLCOPYTEXSUBIMAGE1D)(GLenum,GLint,GLint,GLint,GLint,GLsizei);
-WXE_EXTERN WXEGLCOPYTEXSUBIMAGE1D weglCopyTexSubImage1D;
-typedef void (APIENTRY * WXEGLCOPYTEXSUBIMAGE2D)(GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
-WXE_EXTERN WXEGLCOPYTEXSUBIMAGE2D weglCopyTexSubImage2D;
+typedef void (APIENTRY * WXEGLALPHAFUNC)(GLenum,GLclampf);
+WXE_EXTERN WXEGLALPHAFUNC weglAlphaFunc;
+typedef void (APIENTRY * WXEGLBLENDFUNC)(GLenum,GLenum);
+WXE_EXTERN WXEGLBLENDFUNC weglBlendFunc;
+typedef void (APIENTRY * WXEGLLOGICOP)(GLenum);
+WXE_EXTERN WXEGLLOGICOP weglLogicOp;
typedef void (APIENTRY * WXEGLCULLFACE)(GLenum);
WXE_EXTERN WXEGLCULLFACE weglCullFace;
-typedef void (APIENTRY * WXEGLDELETELISTS)(GLuint,GLsizei);
-WXE_EXTERN WXEGLDELETELISTS weglDeleteLists;
-typedef void (APIENTRY * WXEGLDELETETEXTURES)(GLsizei,const GLuint *);
-WXE_EXTERN WXEGLDELETETEXTURES weglDeleteTextures;
-typedef void (APIENTRY * WXEGLDEPTHFUNC)(GLenum);
-WXE_EXTERN WXEGLDEPTHFUNC weglDepthFunc;
-typedef void (APIENTRY * WXEGLDEPTHMASK)(GLboolean);
-WXE_EXTERN WXEGLDEPTHMASK weglDepthMask;
-typedef void (APIENTRY * WXEGLDEPTHRANGE)(GLclampd,GLclampd);
-WXE_EXTERN WXEGLDEPTHRANGE weglDepthRange;
-typedef void (APIENTRY * WXEGLDISABLE)(GLenum);
-WXE_EXTERN WXEGLDISABLE weglDisable;
-typedef void (APIENTRY * WXEGLDISABLECLIENTSTATE)(GLenum);
-WXE_EXTERN WXEGLDISABLECLIENTSTATE weglDisableClientState;
-typedef void (APIENTRY * WXEGLDRAWARRAYS)(GLenum,GLint,GLsizei);
-WXE_EXTERN WXEGLDRAWARRAYS weglDrawArrays;
-typedef void (APIENTRY * WXEGLDRAWBUFFER)(GLenum);
-WXE_EXTERN WXEGLDRAWBUFFER weglDrawBuffer;
-typedef void (APIENTRY * WXEGLDRAWELEMENTS)(GLenum,GLsizei,GLenum,const GLvoid *);
-WXE_EXTERN WXEGLDRAWELEMENTS weglDrawElements;
-typedef void (APIENTRY * WXEGLDRAWPIXELS)(GLsizei,GLsizei,GLenum,GLenum,const GLvoid *);
-WXE_EXTERN WXEGLDRAWPIXELS weglDrawPixels;
+typedef void (APIENTRY * WXEGLFRONTFACE)(GLenum);
+WXE_EXTERN WXEGLFRONTFACE weglFrontFace;
+typedef void (APIENTRY * WXEGLPOINTSIZE)(GLfloat);
+WXE_EXTERN WXEGLPOINTSIZE weglPointSize;
+typedef void (APIENTRY * WXEGLLINEWIDTH)(GLfloat);
+WXE_EXTERN WXEGLLINEWIDTH weglLineWidth;
+typedef void (APIENTRY * WXEGLLINESTIPPLE)(GLint,GLushort);
+WXE_EXTERN WXEGLLINESTIPPLE weglLineStipple;
+typedef void (APIENTRY * WXEGLPOLYGONMODE)(GLenum,GLenum);
+WXE_EXTERN WXEGLPOLYGONMODE weglPolygonMode;
+typedef void (APIENTRY * WXEGLPOLYGONOFFSET)(GLfloat,GLfloat);
+WXE_EXTERN WXEGLPOLYGONOFFSET weglPolygonOffset;
+typedef void (APIENTRY * WXEGLPOLYGONSTIPPLE)(const GLubyte *);
+WXE_EXTERN WXEGLPOLYGONSTIPPLE weglPolygonStipple;
+typedef void (APIENTRY * WXEGLGETPOLYGONSTIPPLE)(GLubyte *);
+WXE_EXTERN WXEGLGETPOLYGONSTIPPLE weglGetPolygonStipple;
typedef void (APIENTRY * WXEGLEDGEFLAGV)(const GLboolean *);
WXE_EXTERN WXEGLEDGEFLAGV weglEdgeFlagv;
-typedef void (APIENTRY * WXEGLEDGEFLAGPOINTER)(GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLEDGEFLAGPOINTER weglEdgeFlagPointer;
+typedef void (APIENTRY * WXEGLSCISSOR)(GLint,GLint,GLsizei,GLsizei);
+WXE_EXTERN WXEGLSCISSOR weglScissor;
+typedef void (APIENTRY * WXEGLCLIPPLANE)(GLenum,const GLdouble *);
+WXE_EXTERN WXEGLCLIPPLANE weglClipPlane;
+typedef void (APIENTRY * WXEGLGETCLIPPLANE)(GLenum,GLdouble *);
+WXE_EXTERN WXEGLGETCLIPPLANE weglGetClipPlane;
+typedef void (APIENTRY * WXEGLDRAWBUFFER)(GLenum);
+WXE_EXTERN WXEGLDRAWBUFFER weglDrawBuffer;
+typedef void (APIENTRY * WXEGLREADBUFFER)(GLenum);
+WXE_EXTERN WXEGLREADBUFFER weglReadBuffer;
typedef void (APIENTRY * WXEGLENABLE)(GLenum);
WXE_EXTERN WXEGLENABLE weglEnable;
+typedef void (APIENTRY * WXEGLDISABLE)(GLenum);
+WXE_EXTERN WXEGLDISABLE weglDisable;
+typedef GLboolean (APIENTRY * WXEGLISENABLED)(GLenum);
+WXE_EXTERN WXEGLISENABLED weglIsEnabled;
typedef void (APIENTRY * WXEGLENABLECLIENTSTATE)(GLenum);
WXE_EXTERN WXEGLENABLECLIENTSTATE weglEnableClientState;
-typedef void (APIENTRY * WXEGLEND)();
-WXE_EXTERN WXEGLEND weglEnd;
-typedef void (APIENTRY * WXEGLENDLIST)();
-WXE_EXTERN WXEGLENDLIST weglEndList;
-typedef void (APIENTRY * WXEGLEVALCOORD1DV)(const GLdouble *);
-WXE_EXTERN WXEGLEVALCOORD1DV weglEvalCoord1dv;
-typedef void (APIENTRY * WXEGLEVALCOORD1FV)(const GLfloat *);
-WXE_EXTERN WXEGLEVALCOORD1FV weglEvalCoord1fv;
-typedef void (APIENTRY * WXEGLEVALCOORD2DV)(const GLdouble *);
-WXE_EXTERN WXEGLEVALCOORD2DV weglEvalCoord2dv;
-typedef void (APIENTRY * WXEGLEVALCOORD2FV)(const GLfloat *);
-WXE_EXTERN WXEGLEVALCOORD2FV weglEvalCoord2fv;
-typedef void (APIENTRY * WXEGLEVALMESH1)(GLenum,GLint,GLint);
-WXE_EXTERN WXEGLEVALMESH1 weglEvalMesh1;
-typedef void (APIENTRY * WXEGLEVALMESH2)(GLenum,GLint,GLint,GLint,GLint);
-WXE_EXTERN WXEGLEVALMESH2 weglEvalMesh2;
-typedef void (APIENTRY * WXEGLEVALPOINT1)(GLint);
-WXE_EXTERN WXEGLEVALPOINT1 weglEvalPoint1;
-typedef void (APIENTRY * WXEGLEVALPOINT2)(GLint,GLint);
-WXE_EXTERN WXEGLEVALPOINT2 weglEvalPoint2;
-typedef void (APIENTRY * WXEGLFEEDBACKBUFFER)(GLsizei,GLenum,GLfloat *);
-WXE_EXTERN WXEGLFEEDBACKBUFFER weglFeedbackBuffer;
-typedef void (APIENTRY * WXEGLFINISH)();
-WXE_EXTERN WXEGLFINISH weglFinish;
-typedef void (APIENTRY * WXEGLFLUSH)();
-WXE_EXTERN WXEGLFLUSH weglFlush;
-typedef void (APIENTRY * WXEGLFOGF)(GLenum,GLfloat);
-WXE_EXTERN WXEGLFOGF weglFogf;
-typedef void (APIENTRY * WXEGLFOGFV)(GLenum,const GLfloat *);
-WXE_EXTERN WXEGLFOGFV weglFogfv;
-typedef void (APIENTRY * WXEGLFOGI)(GLenum,GLint);
-WXE_EXTERN WXEGLFOGI weglFogi;
-typedef void (APIENTRY * WXEGLFOGIV)(GLenum,const GLint *);
-WXE_EXTERN WXEGLFOGIV weglFogiv;
-typedef void (APIENTRY * WXEGLFRONTFACE)(GLenum);
-WXE_EXTERN WXEGLFRONTFACE weglFrontFace;
-typedef void (APIENTRY * WXEGLFRUSTUM)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
-WXE_EXTERN WXEGLFRUSTUM weglFrustum;
-typedef GLuint (APIENTRY * WXEGLGENLISTS)(GLsizei);
-WXE_EXTERN WXEGLGENLISTS weglGenLists;
-typedef void (APIENTRY * WXEGLGENTEXTURES)(GLsizei,GLuint *);
-WXE_EXTERN WXEGLGENTEXTURES weglGenTextures;
+typedef void (APIENTRY * WXEGLDISABLECLIENTSTATE)(GLenum);
+WXE_EXTERN WXEGLDISABLECLIENTSTATE weglDisableClientState;
typedef void (APIENTRY * WXEGLGETBOOLEANV)(GLenum,GLboolean *);
WXE_EXTERN WXEGLGETBOOLEANV weglGetBooleanv;
-typedef void (APIENTRY * WXEGLGETCLIPPLANE)(GLenum,GLdouble *);
-WXE_EXTERN WXEGLGETCLIPPLANE weglGetClipPlane;
typedef void (APIENTRY * WXEGLGETDOUBLEV)(GLenum,GLdouble *);
WXE_EXTERN WXEGLGETDOUBLEV weglGetDoublev;
-typedef GLenum (APIENTRY * WXEGLGETERROR)();
-WXE_EXTERN WXEGLGETERROR weglGetError;
typedef void (APIENTRY * WXEGLGETFLOATV)(GLenum,GLfloat *);
WXE_EXTERN WXEGLGETFLOATV weglGetFloatv;
typedef void (APIENTRY * WXEGLGETINTEGERV)(GLenum,GLint *);
WXE_EXTERN WXEGLGETINTEGERV weglGetIntegerv;
-typedef void (APIENTRY * WXEGLGETLIGHTFV)(GLenum,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETLIGHTFV weglGetLightfv;
-typedef void (APIENTRY * WXEGLGETLIGHTIV)(GLenum,GLenum,GLint *);
-WXE_EXTERN WXEGLGETLIGHTIV weglGetLightiv;
-typedef void (APIENTRY * WXEGLGETMAPDV)(GLenum,GLenum,GLdouble *);
-WXE_EXTERN WXEGLGETMAPDV weglGetMapdv;
-typedef void (APIENTRY * WXEGLGETMAPFV)(GLenum,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETMAPFV weglGetMapfv;
-typedef void (APIENTRY * WXEGLGETMAPIV)(GLenum,GLenum,GLint *);
-WXE_EXTERN WXEGLGETMAPIV weglGetMapiv;
-typedef void (APIENTRY * WXEGLGETMATERIALFV)(GLenum,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETMATERIALFV weglGetMaterialfv;
-typedef void (APIENTRY * WXEGLGETMATERIALIV)(GLenum,GLenum,GLint *);
-WXE_EXTERN WXEGLGETMATERIALIV weglGetMaterialiv;
-typedef void (APIENTRY * WXEGLGETPIXELMAPFV)(GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETPIXELMAPFV weglGetPixelMapfv;
-typedef void (APIENTRY * WXEGLGETPIXELMAPUIV)(GLenum,GLuint *);
-WXE_EXTERN WXEGLGETPIXELMAPUIV weglGetPixelMapuiv;
-typedef void (APIENTRY * WXEGLGETPIXELMAPUSV)(GLenum,GLushort *);
-WXE_EXTERN WXEGLGETPIXELMAPUSV weglGetPixelMapusv;
-typedef void (APIENTRY * WXEGLGETPOLYGONSTIPPLE)(GLubyte *);
-WXE_EXTERN WXEGLGETPOLYGONSTIPPLE weglGetPolygonStipple;
+typedef void (APIENTRY * WXEGLPUSHATTRIB)(GLbitfield);
+WXE_EXTERN WXEGLPUSHATTRIB weglPushAttrib;
+typedef void (APIENTRY * WXEGLPOPATTRIB)();
+WXE_EXTERN WXEGLPOPATTRIB weglPopAttrib;
+typedef void (APIENTRY * WXEGLPUSHCLIENTATTRIB)(GLbitfield);
+WXE_EXTERN WXEGLPUSHCLIENTATTRIB weglPushClientAttrib;
+typedef void (APIENTRY * WXEGLPOPCLIENTATTRIB)();
+WXE_EXTERN WXEGLPOPCLIENTATTRIB weglPopClientAttrib;
+typedef GLint (APIENTRY * WXEGLRENDERMODE)(GLenum);
+WXE_EXTERN WXEGLRENDERMODE weglRenderMode;
+typedef GLenum (APIENTRY * WXEGLGETERROR)();
+WXE_EXTERN WXEGLGETERROR weglGetError;
typedef const GLubyte * (APIENTRY * WXEGLGETSTRING)(GLenum);
WXE_EXTERN WXEGLGETSTRING weglGetString;
-typedef void (APIENTRY * WXEGLGETTEXENVFV)(GLenum,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETTEXENVFV weglGetTexEnvfv;
-typedef void (APIENTRY * WXEGLGETTEXENVIV)(GLenum,GLenum,GLint *);
-WXE_EXTERN WXEGLGETTEXENVIV weglGetTexEnviv;
-typedef void (APIENTRY * WXEGLGETTEXGENDV)(GLenum,GLenum,GLdouble *);
-WXE_EXTERN WXEGLGETTEXGENDV weglGetTexGendv;
-typedef void (APIENTRY * WXEGLGETTEXGENFV)(GLenum,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETTEXGENFV weglGetTexGenfv;
-typedef void (APIENTRY * WXEGLGETTEXGENIV)(GLenum,GLenum,GLint *);
-WXE_EXTERN WXEGLGETTEXGENIV weglGetTexGeniv;
-typedef void (APIENTRY * WXEGLGETTEXIMAGE)(GLenum,GLint,GLenum,GLenum,GLvoid *);
-WXE_EXTERN WXEGLGETTEXIMAGE weglGetTexImage;
-typedef void (APIENTRY * WXEGLGETTEXLEVELPARAMETERFV)(GLenum,GLint,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETTEXLEVELPARAMETERFV weglGetTexLevelParameterfv;
-typedef void (APIENTRY * WXEGLGETTEXLEVELPARAMETERIV)(GLenum,GLint,GLenum,GLint *);
-WXE_EXTERN WXEGLGETTEXLEVELPARAMETERIV weglGetTexLevelParameteriv;
-typedef void (APIENTRY * WXEGLGETTEXPARAMETERFV)(GLenum,GLenum,GLfloat *);
-WXE_EXTERN WXEGLGETTEXPARAMETERFV weglGetTexParameterfv;
-typedef void (APIENTRY * WXEGLGETTEXPARAMETERIV)(GLenum,GLenum,GLint *);
-WXE_EXTERN WXEGLGETTEXPARAMETERIV weglGetTexParameteriv;
+typedef void (APIENTRY * WXEGLFINISH)();
+WXE_EXTERN WXEGLFINISH weglFinish;
+typedef void (APIENTRY * WXEGLFLUSH)();
+WXE_EXTERN WXEGLFLUSH weglFlush;
typedef void (APIENTRY * WXEGLHINT)(GLenum,GLenum);
WXE_EXTERN WXEGLHINT weglHint;
-typedef void (APIENTRY * WXEGLINDEXMASK)(GLuint);
-WXE_EXTERN WXEGLINDEXMASK weglIndexMask;
-typedef void (APIENTRY * WXEGLINDEXPOINTER)(GLenum,GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLINDEXPOINTER weglIndexPointer;
-typedef void (APIENTRY * WXEGLINDEXDV)(const GLdouble *);
-WXE_EXTERN WXEGLINDEXDV weglIndexdv;
-typedef void (APIENTRY * WXEGLINDEXFV)(const GLfloat *);
-WXE_EXTERN WXEGLINDEXFV weglIndexfv;
-typedef void (APIENTRY * WXEGLINDEXIV)(const GLint *);
-WXE_EXTERN WXEGLINDEXIV weglIndexiv;
-typedef void (APIENTRY * WXEGLINDEXSV)(const GLshort *);
-WXE_EXTERN WXEGLINDEXSV weglIndexsv;
-typedef void (APIENTRY * WXEGLINDEXUBV)(const GLubyte *);
-WXE_EXTERN WXEGLINDEXUBV weglIndexubv;
-typedef void (APIENTRY * WXEGLINITNAMES)();
-WXE_EXTERN WXEGLINITNAMES weglInitNames;
-typedef void (APIENTRY * WXEGLINTERLEAVEDARRAYS)(GLenum,GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLINTERLEAVEDARRAYS weglInterleavedArrays;
-typedef GLboolean (APIENTRY * WXEGLISENABLED)(GLenum);
-WXE_EXTERN WXEGLISENABLED weglIsEnabled;
-typedef GLboolean (APIENTRY * WXEGLISLIST)(GLuint);
-WXE_EXTERN WXEGLISLIST weglIsList;
-typedef GLboolean (APIENTRY * WXEGLISTEXTURE)(GLuint);
-WXE_EXTERN WXEGLISTEXTURE weglIsTexture;
-typedef void (APIENTRY * WXEGLLIGHTMODELF)(GLenum,GLfloat);
-WXE_EXTERN WXEGLLIGHTMODELF weglLightModelf;
-typedef void (APIENTRY * WXEGLLIGHTMODELFV)(GLenum,const GLfloat *);
-WXE_EXTERN WXEGLLIGHTMODELFV weglLightModelfv;
-typedef void (APIENTRY * WXEGLLIGHTMODELI)(GLenum,GLint);
-WXE_EXTERN WXEGLLIGHTMODELI weglLightModeli;
-typedef void (APIENTRY * WXEGLLIGHTMODELIV)(GLenum,const GLint *);
-WXE_EXTERN WXEGLLIGHTMODELIV weglLightModeliv;
-typedef void (APIENTRY * WXEGLLIGHTF)(GLenum,GLenum,GLfloat);
-WXE_EXTERN WXEGLLIGHTF weglLightf;
-typedef void (APIENTRY * WXEGLLIGHTFV)(GLenum,GLenum,const GLfloat *);
-WXE_EXTERN WXEGLLIGHTFV weglLightfv;
-typedef void (APIENTRY * WXEGLLIGHTI)(GLenum,GLenum,GLint);
-WXE_EXTERN WXEGLLIGHTI weglLighti;
-typedef void (APIENTRY * WXEGLLIGHTIV)(GLenum,GLenum,const GLint *);
-WXE_EXTERN WXEGLLIGHTIV weglLightiv;
-typedef void (APIENTRY * WXEGLLINESTIPPLE)(GLint,GLushort);
-WXE_EXTERN WXEGLLINESTIPPLE weglLineStipple;
-typedef void (APIENTRY * WXEGLLINEWIDTH)(GLfloat);
-WXE_EXTERN WXEGLLINEWIDTH weglLineWidth;
-typedef void (APIENTRY * WXEGLLISTBASE)(GLuint);
-WXE_EXTERN WXEGLLISTBASE weglListBase;
+typedef void (APIENTRY * WXEGLCLEARDEPTH)(GLclampd);
+WXE_EXTERN WXEGLCLEARDEPTH weglClearDepth;
+typedef void (APIENTRY * WXEGLDEPTHFUNC)(GLenum);
+WXE_EXTERN WXEGLDEPTHFUNC weglDepthFunc;
+typedef void (APIENTRY * WXEGLDEPTHMASK)(GLboolean);
+WXE_EXTERN WXEGLDEPTHMASK weglDepthMask;
+typedef void (APIENTRY * WXEGLDEPTHRANGE)(GLclampd,GLclampd);
+WXE_EXTERN WXEGLDEPTHRANGE weglDepthRange;
+typedef void (APIENTRY * WXEGLCLEARACCUM)(GLfloat,GLfloat,GLfloat,GLfloat);
+WXE_EXTERN WXEGLCLEARACCUM weglClearAccum;
+typedef void (APIENTRY * WXEGLACCUM)(GLenum,GLfloat);
+WXE_EXTERN WXEGLACCUM weglAccum;
+typedef void (APIENTRY * WXEGLMATRIXMODE)(GLenum);
+WXE_EXTERN WXEGLMATRIXMODE weglMatrixMode;
+typedef void (APIENTRY * WXEGLORTHO)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
+WXE_EXTERN WXEGLORTHO weglOrtho;
+typedef void (APIENTRY * WXEGLFRUSTUM)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
+WXE_EXTERN WXEGLFRUSTUM weglFrustum;
+typedef void (APIENTRY * WXEGLVIEWPORT)(GLint,GLint,GLsizei,GLsizei);
+WXE_EXTERN WXEGLVIEWPORT weglViewport;
+typedef void (APIENTRY * WXEGLPUSHMATRIX)();
+WXE_EXTERN WXEGLPUSHMATRIX weglPushMatrix;
+typedef void (APIENTRY * WXEGLPOPMATRIX)();
+WXE_EXTERN WXEGLPOPMATRIX weglPopMatrix;
typedef void (APIENTRY * WXEGLLOADIDENTITY)();
WXE_EXTERN WXEGLLOADIDENTITY weglLoadIdentity;
typedef void (APIENTRY * WXEGLLOADMATRIXD)(const GLdouble *);
WXE_EXTERN WXEGLLOADMATRIXD weglLoadMatrixd;
typedef void (APIENTRY * WXEGLLOADMATRIXF)(const GLfloat *);
WXE_EXTERN WXEGLLOADMATRIXF weglLoadMatrixf;
-typedef void (APIENTRY * WXEGLLOADNAME)(GLuint);
-WXE_EXTERN WXEGLLOADNAME weglLoadName;
-typedef void (APIENTRY * WXEGLLOGICOP)(GLenum);
-WXE_EXTERN WXEGLLOGICOP weglLogicOp;
-typedef void (APIENTRY * WXEGLMAP1D)(GLenum,GLdouble,GLdouble,GLint,GLint,const GLdouble *);
-WXE_EXTERN WXEGLMAP1D weglMap1d;
-typedef void (APIENTRY * WXEGLMAP1F)(GLenum,GLfloat,GLfloat,GLint,GLint,const GLfloat *);
-WXE_EXTERN WXEGLMAP1F weglMap1f;
-typedef void (APIENTRY * WXEGLMAP2D)(GLenum,GLdouble,GLdouble,GLint,GLint,GLdouble,GLdouble,GLint,GLint,const GLdouble *);
-WXE_EXTERN WXEGLMAP2D weglMap2d;
-typedef void (APIENTRY * WXEGLMAP2F)(GLenum,GLfloat,GLfloat,GLint,GLint,GLfloat,GLfloat,GLint,GLint,const GLfloat *);
-WXE_EXTERN WXEGLMAP2F weglMap2f;
-typedef void (APIENTRY * WXEGLMAPGRID1D)(GLint,GLdouble,GLdouble);
-WXE_EXTERN WXEGLMAPGRID1D weglMapGrid1d;
-typedef void (APIENTRY * WXEGLMAPGRID1F)(GLint,GLfloat,GLfloat);
-WXE_EXTERN WXEGLMAPGRID1F weglMapGrid1f;
-typedef void (APIENTRY * WXEGLMAPGRID2D)(GLint,GLdouble,GLdouble,GLint,GLdouble,GLdouble);
-WXE_EXTERN WXEGLMAPGRID2D weglMapGrid2d;
-typedef void (APIENTRY * WXEGLMAPGRID2F)(GLint,GLfloat,GLfloat,GLint,GLfloat,GLfloat);
-WXE_EXTERN WXEGLMAPGRID2F weglMapGrid2f;
-typedef void (APIENTRY * WXEGLMATERIALF)(GLenum,GLenum,GLfloat);
-WXE_EXTERN WXEGLMATERIALF weglMaterialf;
-typedef void (APIENTRY * WXEGLMATERIALFV)(GLenum,GLenum,const GLfloat *);
-WXE_EXTERN WXEGLMATERIALFV weglMaterialfv;
-typedef void (APIENTRY * WXEGLMATERIALI)(GLenum,GLenum,GLint);
-WXE_EXTERN WXEGLMATERIALI weglMateriali;
-typedef void (APIENTRY * WXEGLMATERIALIV)(GLenum,GLenum,const GLint *);
-WXE_EXTERN WXEGLMATERIALIV weglMaterialiv;
-typedef void (APIENTRY * WXEGLMATRIXMODE)(GLenum);
-WXE_EXTERN WXEGLMATRIXMODE weglMatrixMode;
typedef void (APIENTRY * WXEGLMULTMATRIXD)(const GLdouble *);
WXE_EXTERN WXEGLMULTMATRIXD weglMultMatrixd;
typedef void (APIENTRY * WXEGLMULTMATRIXF)(const GLfloat *);
WXE_EXTERN WXEGLMULTMATRIXF weglMultMatrixf;
+typedef void (APIENTRY * WXEGLROTATED)(GLdouble,GLdouble,GLdouble,GLdouble);
+WXE_EXTERN WXEGLROTATED weglRotated;
+typedef void (APIENTRY * WXEGLROTATEF)(GLfloat,GLfloat,GLfloat,GLfloat);
+WXE_EXTERN WXEGLROTATEF weglRotatef;
+typedef void (APIENTRY * WXEGLSCALED)(GLdouble,GLdouble,GLdouble);
+WXE_EXTERN WXEGLSCALED weglScaled;
+typedef void (APIENTRY * WXEGLSCALEF)(GLfloat,GLfloat,GLfloat);
+WXE_EXTERN WXEGLSCALEF weglScalef;
+typedef void (APIENTRY * WXEGLTRANSLATED)(GLdouble,GLdouble,GLdouble);
+WXE_EXTERN WXEGLTRANSLATED weglTranslated;
+typedef void (APIENTRY * WXEGLTRANSLATEF)(GLfloat,GLfloat,GLfloat);
+WXE_EXTERN WXEGLTRANSLATEF weglTranslatef;
+typedef GLboolean (APIENTRY * WXEGLISLIST)(GLuint);
+WXE_EXTERN WXEGLISLIST weglIsList;
+typedef void (APIENTRY * WXEGLDELETELISTS)(GLuint,GLsizei);
+WXE_EXTERN WXEGLDELETELISTS weglDeleteLists;
+typedef GLuint (APIENTRY * WXEGLGENLISTS)(GLsizei);
+WXE_EXTERN WXEGLGENLISTS weglGenLists;
typedef void (APIENTRY * WXEGLNEWLIST)(GLuint,GLenum);
WXE_EXTERN WXEGLNEWLIST weglNewList;
+typedef void (APIENTRY * WXEGLENDLIST)();
+WXE_EXTERN WXEGLENDLIST weglEndList;
+typedef void (APIENTRY * WXEGLCALLLIST)(GLuint);
+WXE_EXTERN WXEGLCALLLIST weglCallList;
+typedef void (APIENTRY * WXEGLCALLLISTS)(GLsizei,GLenum,const GLuint *);
+WXE_EXTERN WXEGLCALLLISTS weglCallLists;
+typedef void (APIENTRY * WXEGLLISTBASE)(GLuint);
+WXE_EXTERN WXEGLLISTBASE weglListBase;
+typedef void (APIENTRY * WXEGLBEGIN)(GLenum);
+WXE_EXTERN WXEGLBEGIN weglBegin;
+typedef void (APIENTRY * WXEGLEND)();
+WXE_EXTERN WXEGLEND weglEnd;
+typedef void (APIENTRY * WXEGLVERTEX2DV)(const GLdouble *);
+WXE_EXTERN WXEGLVERTEX2DV weglVertex2dv;
+typedef void (APIENTRY * WXEGLVERTEX2FV)(const GLfloat *);
+WXE_EXTERN WXEGLVERTEX2FV weglVertex2fv;
+typedef void (APIENTRY * WXEGLVERTEX2IV)(const GLint *);
+WXE_EXTERN WXEGLVERTEX2IV weglVertex2iv;
+typedef void (APIENTRY * WXEGLVERTEX2SV)(const GLshort *);
+WXE_EXTERN WXEGLVERTEX2SV weglVertex2sv;
+typedef void (APIENTRY * WXEGLVERTEX3DV)(const GLdouble *);
+WXE_EXTERN WXEGLVERTEX3DV weglVertex3dv;
+typedef void (APIENTRY * WXEGLVERTEX3FV)(const GLfloat *);
+WXE_EXTERN WXEGLVERTEX3FV weglVertex3fv;
+typedef void (APIENTRY * WXEGLVERTEX3IV)(const GLint *);
+WXE_EXTERN WXEGLVERTEX3IV weglVertex3iv;
+typedef void (APIENTRY * WXEGLVERTEX3SV)(const GLshort *);
+WXE_EXTERN WXEGLVERTEX3SV weglVertex3sv;
+typedef void (APIENTRY * WXEGLVERTEX4DV)(const GLdouble *);
+WXE_EXTERN WXEGLVERTEX4DV weglVertex4dv;
+typedef void (APIENTRY * WXEGLVERTEX4FV)(const GLfloat *);
+WXE_EXTERN WXEGLVERTEX4FV weglVertex4fv;
+typedef void (APIENTRY * WXEGLVERTEX4IV)(const GLint *);
+WXE_EXTERN WXEGLVERTEX4IV weglVertex4iv;
+typedef void (APIENTRY * WXEGLVERTEX4SV)(const GLshort *);
+WXE_EXTERN WXEGLVERTEX4SV weglVertex4sv;
typedef void (APIENTRY * WXEGLNORMAL3BV)(const GLbyte *);
WXE_EXTERN WXEGLNORMAL3BV weglNormal3bv;
typedef void (APIENTRY * WXEGLNORMAL3DV)(const GLdouble *);
@@ -343,54 +215,80 @@ typedef void (APIENTRY * WXEGLNORMAL3IV)(const GLint *);
WXE_EXTERN WXEGLNORMAL3IV weglNormal3iv;
typedef void (APIENTRY * WXEGLNORMAL3SV)(const GLshort *);
WXE_EXTERN WXEGLNORMAL3SV weglNormal3sv;
-typedef void (APIENTRY * WXEGLNORMALPOINTER)(GLenum,GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLNORMALPOINTER weglNormalPointer;
-typedef void (APIENTRY * WXEGLORTHO)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
-WXE_EXTERN WXEGLORTHO weglOrtho;
-typedef void (APIENTRY * WXEGLPASSTHROUGH)(GLfloat);
-WXE_EXTERN WXEGLPASSTHROUGH weglPassThrough;
-typedef void (APIENTRY * WXEGLPIXELMAPFV)(GLenum,GLsizei,const GLfloat *);
-WXE_EXTERN WXEGLPIXELMAPFV weglPixelMapfv;
-typedef void (APIENTRY * WXEGLPIXELMAPUIV)(GLenum,GLsizei,const GLuint *);
-WXE_EXTERN WXEGLPIXELMAPUIV weglPixelMapuiv;
-typedef void (APIENTRY * WXEGLPIXELMAPUSV)(GLenum,GLsizei,const GLushort *);
-WXE_EXTERN WXEGLPIXELMAPUSV weglPixelMapusv;
-typedef void (APIENTRY * WXEGLPIXELSTOREF)(GLenum,GLfloat);
-WXE_EXTERN WXEGLPIXELSTOREF weglPixelStoref;
-typedef void (APIENTRY * WXEGLPIXELSTOREI)(GLenum,GLint);
-WXE_EXTERN WXEGLPIXELSTOREI weglPixelStorei;
-typedef void (APIENTRY * WXEGLPIXELTRANSFERF)(GLenum,GLfloat);
-WXE_EXTERN WXEGLPIXELTRANSFERF weglPixelTransferf;
-typedef void (APIENTRY * WXEGLPIXELTRANSFERI)(GLenum,GLint);
-WXE_EXTERN WXEGLPIXELTRANSFERI weglPixelTransferi;
-typedef void (APIENTRY * WXEGLPIXELZOOM)(GLfloat,GLfloat);
-WXE_EXTERN WXEGLPIXELZOOM weglPixelZoom;
-typedef void (APIENTRY * WXEGLPOINTSIZE)(GLfloat);
-WXE_EXTERN WXEGLPOINTSIZE weglPointSize;
-typedef void (APIENTRY * WXEGLPOLYGONMODE)(GLenum,GLenum);
-WXE_EXTERN WXEGLPOLYGONMODE weglPolygonMode;
-typedef void (APIENTRY * WXEGLPOLYGONOFFSET)(GLfloat,GLfloat);
-WXE_EXTERN WXEGLPOLYGONOFFSET weglPolygonOffset;
-typedef void (APIENTRY * WXEGLPOLYGONSTIPPLE)(const GLubyte *);
-WXE_EXTERN WXEGLPOLYGONSTIPPLE weglPolygonStipple;
-typedef void (APIENTRY * WXEGLPOPATTRIB)();
-WXE_EXTERN WXEGLPOPATTRIB weglPopAttrib;
-typedef void (APIENTRY * WXEGLPOPCLIENTATTRIB)();
-WXE_EXTERN WXEGLPOPCLIENTATTRIB weglPopClientAttrib;
-typedef void (APIENTRY * WXEGLPOPMATRIX)();
-WXE_EXTERN WXEGLPOPMATRIX weglPopMatrix;
-typedef void (APIENTRY * WXEGLPOPNAME)();
-WXE_EXTERN WXEGLPOPNAME weglPopName;
-typedef void (APIENTRY * WXEGLPRIORITIZETEXTURES)(GLsizei,const GLuint *,const GLclampf *);
-WXE_EXTERN WXEGLPRIORITIZETEXTURES weglPrioritizeTextures;
-typedef void (APIENTRY * WXEGLPUSHATTRIB)(GLbitfield);
-WXE_EXTERN WXEGLPUSHATTRIB weglPushAttrib;
-typedef void (APIENTRY * WXEGLPUSHCLIENTATTRIB)(GLbitfield);
-WXE_EXTERN WXEGLPUSHCLIENTATTRIB weglPushClientAttrib;
-typedef void (APIENTRY * WXEGLPUSHMATRIX)();
-WXE_EXTERN WXEGLPUSHMATRIX weglPushMatrix;
-typedef void (APIENTRY * WXEGLPUSHNAME)(GLuint);
-WXE_EXTERN WXEGLPUSHNAME weglPushName;
+typedef void (APIENTRY * WXEGLINDEXDV)(const GLdouble *);
+WXE_EXTERN WXEGLINDEXDV weglIndexdv;
+typedef void (APIENTRY * WXEGLINDEXFV)(const GLfloat *);
+WXE_EXTERN WXEGLINDEXFV weglIndexfv;
+typedef void (APIENTRY * WXEGLINDEXIV)(const GLint *);
+WXE_EXTERN WXEGLINDEXIV weglIndexiv;
+typedef void (APIENTRY * WXEGLINDEXSV)(const GLshort *);
+WXE_EXTERN WXEGLINDEXSV weglIndexsv;
+typedef void (APIENTRY * WXEGLINDEXUBV)(const GLubyte *);
+WXE_EXTERN WXEGLINDEXUBV weglIndexubv;
+typedef void (APIENTRY * WXEGLCOLOR3BV)(const GLbyte *);
+WXE_EXTERN WXEGLCOLOR3BV weglColor3bv;
+typedef void (APIENTRY * WXEGLCOLOR3DV)(const GLdouble *);
+WXE_EXTERN WXEGLCOLOR3DV weglColor3dv;
+typedef void (APIENTRY * WXEGLCOLOR3FV)(const GLfloat *);
+WXE_EXTERN WXEGLCOLOR3FV weglColor3fv;
+typedef void (APIENTRY * WXEGLCOLOR3IV)(const GLint *);
+WXE_EXTERN WXEGLCOLOR3IV weglColor3iv;
+typedef void (APIENTRY * WXEGLCOLOR3SV)(const GLshort *);
+WXE_EXTERN WXEGLCOLOR3SV weglColor3sv;
+typedef void (APIENTRY * WXEGLCOLOR3UBV)(const GLubyte *);
+WXE_EXTERN WXEGLCOLOR3UBV weglColor3ubv;
+typedef void (APIENTRY * WXEGLCOLOR3UIV)(const GLuint *);
+WXE_EXTERN WXEGLCOLOR3UIV weglColor3uiv;
+typedef void (APIENTRY * WXEGLCOLOR3USV)(const GLushort *);
+WXE_EXTERN WXEGLCOLOR3USV weglColor3usv;
+typedef void (APIENTRY * WXEGLCOLOR4BV)(const GLbyte *);
+WXE_EXTERN WXEGLCOLOR4BV weglColor4bv;
+typedef void (APIENTRY * WXEGLCOLOR4DV)(const GLdouble *);
+WXE_EXTERN WXEGLCOLOR4DV weglColor4dv;
+typedef void (APIENTRY * WXEGLCOLOR4FV)(const GLfloat *);
+WXE_EXTERN WXEGLCOLOR4FV weglColor4fv;
+typedef void (APIENTRY * WXEGLCOLOR4IV)(const GLint *);
+WXE_EXTERN WXEGLCOLOR4IV weglColor4iv;
+typedef void (APIENTRY * WXEGLCOLOR4SV)(const GLshort *);
+WXE_EXTERN WXEGLCOLOR4SV weglColor4sv;
+typedef void (APIENTRY * WXEGLCOLOR4UBV)(const GLubyte *);
+WXE_EXTERN WXEGLCOLOR4UBV weglColor4ubv;
+typedef void (APIENTRY * WXEGLCOLOR4UIV)(const GLuint *);
+WXE_EXTERN WXEGLCOLOR4UIV weglColor4uiv;
+typedef void (APIENTRY * WXEGLCOLOR4USV)(const GLushort *);
+WXE_EXTERN WXEGLCOLOR4USV weglColor4usv;
+typedef void (APIENTRY * WXEGLTEXCOORD1DV)(const GLdouble *);
+WXE_EXTERN WXEGLTEXCOORD1DV weglTexCoord1dv;
+typedef void (APIENTRY * WXEGLTEXCOORD1FV)(const GLfloat *);
+WXE_EXTERN WXEGLTEXCOORD1FV weglTexCoord1fv;
+typedef void (APIENTRY * WXEGLTEXCOORD1IV)(const GLint *);
+WXE_EXTERN WXEGLTEXCOORD1IV weglTexCoord1iv;
+typedef void (APIENTRY * WXEGLTEXCOORD1SV)(const GLshort *);
+WXE_EXTERN WXEGLTEXCOORD1SV weglTexCoord1sv;
+typedef void (APIENTRY * WXEGLTEXCOORD2DV)(const GLdouble *);
+WXE_EXTERN WXEGLTEXCOORD2DV weglTexCoord2dv;
+typedef void (APIENTRY * WXEGLTEXCOORD2FV)(const GLfloat *);
+WXE_EXTERN WXEGLTEXCOORD2FV weglTexCoord2fv;
+typedef void (APIENTRY * WXEGLTEXCOORD2IV)(const GLint *);
+WXE_EXTERN WXEGLTEXCOORD2IV weglTexCoord2iv;
+typedef void (APIENTRY * WXEGLTEXCOORD2SV)(const GLshort *);
+WXE_EXTERN WXEGLTEXCOORD2SV weglTexCoord2sv;
+typedef void (APIENTRY * WXEGLTEXCOORD3DV)(const GLdouble *);
+WXE_EXTERN WXEGLTEXCOORD3DV weglTexCoord3dv;
+typedef void (APIENTRY * WXEGLTEXCOORD3FV)(const GLfloat *);
+WXE_EXTERN WXEGLTEXCOORD3FV weglTexCoord3fv;
+typedef void (APIENTRY * WXEGLTEXCOORD3IV)(const GLint *);
+WXE_EXTERN WXEGLTEXCOORD3IV weglTexCoord3iv;
+typedef void (APIENTRY * WXEGLTEXCOORD3SV)(const GLshort *);
+WXE_EXTERN WXEGLTEXCOORD3SV weglTexCoord3sv;
+typedef void (APIENTRY * WXEGLTEXCOORD4DV)(const GLdouble *);
+WXE_EXTERN WXEGLTEXCOORD4DV weglTexCoord4dv;
+typedef void (APIENTRY * WXEGLTEXCOORD4FV)(const GLfloat *);
+WXE_EXTERN WXEGLTEXCOORD4FV weglTexCoord4fv;
+typedef void (APIENTRY * WXEGLTEXCOORD4IV)(const GLint *);
+WXE_EXTERN WXEGLTEXCOORD4IV weglTexCoord4iv;
+typedef void (APIENTRY * WXEGLTEXCOORD4SV)(const GLshort *);
+WXE_EXTERN WXEGLTEXCOORD4SV weglTexCoord4sv;
typedef void (APIENTRY * WXEGLRASTERPOS2DV)(const GLdouble *);
WXE_EXTERN WXEGLRASTERPOS2DV weglRasterPos2dv;
typedef void (APIENTRY * WXEGLRASTERPOS2FV)(const GLfloat *);
@@ -415,150 +313,252 @@ typedef void (APIENTRY * WXEGLRASTERPOS4IV)(const GLint *);
WXE_EXTERN WXEGLRASTERPOS4IV weglRasterPos4iv;
typedef void (APIENTRY * WXEGLRASTERPOS4SV)(const GLshort *);
WXE_EXTERN WXEGLRASTERPOS4SV weglRasterPos4sv;
-typedef void (APIENTRY * WXEGLREADBUFFER)(GLenum);
-WXE_EXTERN WXEGLREADBUFFER weglReadBuffer;
-typedef void (APIENTRY * WXEGLREADPIXELS)(GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,GLvoid *);
-WXE_EXTERN WXEGLREADPIXELS weglReadPixels;
typedef void (APIENTRY * WXEGLRECTD)(GLdouble,GLdouble,GLdouble,GLdouble);
WXE_EXTERN WXEGLRECTD weglRectd;
-typedef void (APIENTRY * WXEGLRECTDV)(const GLdouble *,const GLdouble *);
-WXE_EXTERN WXEGLRECTDV weglRectdv;
typedef void (APIENTRY * WXEGLRECTF)(GLfloat,GLfloat,GLfloat,GLfloat);
WXE_EXTERN WXEGLRECTF weglRectf;
-typedef void (APIENTRY * WXEGLRECTFV)(const GLfloat *,const GLfloat *);
-WXE_EXTERN WXEGLRECTFV weglRectfv;
typedef void (APIENTRY * WXEGLRECTI)(GLint,GLint,GLint,GLint);
WXE_EXTERN WXEGLRECTI weglRecti;
-typedef void (APIENTRY * WXEGLRECTIV)(const GLint *,const GLint *);
-WXE_EXTERN WXEGLRECTIV weglRectiv;
typedef void (APIENTRY * WXEGLRECTS)(GLshort,GLshort,GLshort,GLshort);
WXE_EXTERN WXEGLRECTS weglRects;
+typedef void (APIENTRY * WXEGLRECTDV)(const GLdouble *,const GLdouble *);
+WXE_EXTERN WXEGLRECTDV weglRectdv;
+typedef void (APIENTRY * WXEGLRECTFV)(const GLfloat *,const GLfloat *);
+WXE_EXTERN WXEGLRECTFV weglRectfv;
+typedef void (APIENTRY * WXEGLRECTIV)(const GLint *,const GLint *);
+WXE_EXTERN WXEGLRECTIV weglRectiv;
typedef void (APIENTRY * WXEGLRECTSV)(const GLshort *,const GLshort *);
WXE_EXTERN WXEGLRECTSV weglRectsv;
-typedef GLint (APIENTRY * WXEGLRENDERMODE)(GLenum);
-WXE_EXTERN WXEGLRENDERMODE weglRenderMode;
-typedef void (APIENTRY * WXEGLROTATED)(GLdouble,GLdouble,GLdouble,GLdouble);
-WXE_EXTERN WXEGLROTATED weglRotated;
-typedef void (APIENTRY * WXEGLROTATEF)(GLfloat,GLfloat,GLfloat,GLfloat);
-WXE_EXTERN WXEGLROTATEF weglRotatef;
-typedef void (APIENTRY * WXEGLSCALED)(GLdouble,GLdouble,GLdouble);
-WXE_EXTERN WXEGLSCALED weglScaled;
-typedef void (APIENTRY * WXEGLSCALEF)(GLfloat,GLfloat,GLfloat);
-WXE_EXTERN WXEGLSCALEF weglScalef;
-typedef void (APIENTRY * WXEGLSCISSOR)(GLint,GLint,GLsizei,GLsizei);
-WXE_EXTERN WXEGLSCISSOR weglScissor;
-typedef void (APIENTRY * WXEGLSELECTBUFFER)(GLsizei,GLuint *);
-WXE_EXTERN WXEGLSELECTBUFFER weglSelectBuffer;
+typedef void (APIENTRY * WXEGLVERTEXPOINTER)(GLint,GLenum,GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLVERTEXPOINTER weglVertexPointer;
+typedef void (APIENTRY * WXEGLNORMALPOINTER)(GLenum,GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLNORMALPOINTER weglNormalPointer;
+typedef void (APIENTRY * WXEGLCOLORPOINTER)(GLint,GLenum,GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLCOLORPOINTER weglColorPointer;
+typedef void (APIENTRY * WXEGLINDEXPOINTER)(GLenum,GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLINDEXPOINTER weglIndexPointer;
+typedef void (APIENTRY * WXEGLTEXCOORDPOINTER)(GLint,GLenum,GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLTEXCOORDPOINTER weglTexCoordPointer;
+typedef void (APIENTRY * WXEGLEDGEFLAGPOINTER)(GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLEDGEFLAGPOINTER weglEdgeFlagPointer;
+typedef void (APIENTRY * WXEGLARRAYELEMENT)(GLint);
+WXE_EXTERN WXEGLARRAYELEMENT weglArrayElement;
+typedef void (APIENTRY * WXEGLDRAWARRAYS)(GLenum,GLint,GLsizei);
+WXE_EXTERN WXEGLDRAWARRAYS weglDrawArrays;
+typedef void (APIENTRY * WXEGLDRAWELEMENTS)(GLenum,GLsizei,GLenum,const GLvoid *);
+WXE_EXTERN WXEGLDRAWELEMENTS weglDrawElements;
+typedef void (APIENTRY * WXEGLINTERLEAVEDARRAYS)(GLenum,GLsizei,const GLvoid *);
+WXE_EXTERN WXEGLINTERLEAVEDARRAYS weglInterleavedArrays;
typedef void (APIENTRY * WXEGLSHADEMODEL)(GLenum);
WXE_EXTERN WXEGLSHADEMODEL weglShadeModel;
+typedef void (APIENTRY * WXEGLLIGHTF)(GLenum,GLenum,GLfloat);
+WXE_EXTERN WXEGLLIGHTF weglLightf;
+typedef void (APIENTRY * WXEGLLIGHTI)(GLenum,GLenum,GLint);
+WXE_EXTERN WXEGLLIGHTI weglLighti;
+typedef void (APIENTRY * WXEGLLIGHTFV)(GLenum,GLenum,const GLfloat *);
+WXE_EXTERN WXEGLLIGHTFV weglLightfv;
+typedef void (APIENTRY * WXEGLLIGHTIV)(GLenum,GLenum,const GLint *);
+WXE_EXTERN WXEGLLIGHTIV weglLightiv;
+typedef void (APIENTRY * WXEGLGETLIGHTFV)(GLenum,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETLIGHTFV weglGetLightfv;
+typedef void (APIENTRY * WXEGLGETLIGHTIV)(GLenum,GLenum,GLint *);
+WXE_EXTERN WXEGLGETLIGHTIV weglGetLightiv;
+typedef void (APIENTRY * WXEGLLIGHTMODELF)(GLenum,GLfloat);
+WXE_EXTERN WXEGLLIGHTMODELF weglLightModelf;
+typedef void (APIENTRY * WXEGLLIGHTMODELI)(GLenum,GLint);
+WXE_EXTERN WXEGLLIGHTMODELI weglLightModeli;
+typedef void (APIENTRY * WXEGLLIGHTMODELFV)(GLenum,const GLfloat *);
+WXE_EXTERN WXEGLLIGHTMODELFV weglLightModelfv;
+typedef void (APIENTRY * WXEGLLIGHTMODELIV)(GLenum,const GLint *);
+WXE_EXTERN WXEGLLIGHTMODELIV weglLightModeliv;
+typedef void (APIENTRY * WXEGLMATERIALF)(GLenum,GLenum,GLfloat);
+WXE_EXTERN WXEGLMATERIALF weglMaterialf;
+typedef void (APIENTRY * WXEGLMATERIALI)(GLenum,GLenum,GLint);
+WXE_EXTERN WXEGLMATERIALI weglMateriali;
+typedef void (APIENTRY * WXEGLMATERIALFV)(GLenum,GLenum,const GLfloat *);
+WXE_EXTERN WXEGLMATERIALFV weglMaterialfv;
+typedef void (APIENTRY * WXEGLMATERIALIV)(GLenum,GLenum,const GLint *);
+WXE_EXTERN WXEGLMATERIALIV weglMaterialiv;
+typedef void (APIENTRY * WXEGLGETMATERIALFV)(GLenum,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETMATERIALFV weglGetMaterialfv;
+typedef void (APIENTRY * WXEGLGETMATERIALIV)(GLenum,GLenum,GLint *);
+WXE_EXTERN WXEGLGETMATERIALIV weglGetMaterialiv;
+typedef void (APIENTRY * WXEGLCOLORMATERIAL)(GLenum,GLenum);
+WXE_EXTERN WXEGLCOLORMATERIAL weglColorMaterial;
+typedef void (APIENTRY * WXEGLPIXELZOOM)(GLfloat,GLfloat);
+WXE_EXTERN WXEGLPIXELZOOM weglPixelZoom;
+typedef void (APIENTRY * WXEGLPIXELSTOREF)(GLenum,GLfloat);
+WXE_EXTERN WXEGLPIXELSTOREF weglPixelStoref;
+typedef void (APIENTRY * WXEGLPIXELSTOREI)(GLenum,GLint);
+WXE_EXTERN WXEGLPIXELSTOREI weglPixelStorei;
+typedef void (APIENTRY * WXEGLPIXELTRANSFERF)(GLenum,GLfloat);
+WXE_EXTERN WXEGLPIXELTRANSFERF weglPixelTransferf;
+typedef void (APIENTRY * WXEGLPIXELTRANSFERI)(GLenum,GLint);
+WXE_EXTERN WXEGLPIXELTRANSFERI weglPixelTransferi;
+typedef void (APIENTRY * WXEGLPIXELMAPFV)(GLenum,GLsizei,const GLfloat *);
+WXE_EXTERN WXEGLPIXELMAPFV weglPixelMapfv;
+typedef void (APIENTRY * WXEGLPIXELMAPUIV)(GLenum,GLsizei,const GLuint *);
+WXE_EXTERN WXEGLPIXELMAPUIV weglPixelMapuiv;
+typedef void (APIENTRY * WXEGLPIXELMAPUSV)(GLenum,GLsizei,const GLushort *);
+WXE_EXTERN WXEGLPIXELMAPUSV weglPixelMapusv;
+typedef void (APIENTRY * WXEGLGETPIXELMAPFV)(GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETPIXELMAPFV weglGetPixelMapfv;
+typedef void (APIENTRY * WXEGLGETPIXELMAPUIV)(GLenum,GLuint *);
+WXE_EXTERN WXEGLGETPIXELMAPUIV weglGetPixelMapuiv;
+typedef void (APIENTRY * WXEGLGETPIXELMAPUSV)(GLenum,GLushort *);
+WXE_EXTERN WXEGLGETPIXELMAPUSV weglGetPixelMapusv;
+typedef void (APIENTRY * WXEGLBITMAP)(GLsizei,GLsizei,GLfloat,GLfloat,GLfloat,GLfloat,const GLubyte *);
+WXE_EXTERN WXEGLBITMAP weglBitmap;
+typedef void (APIENTRY * WXEGLREADPIXELS)(GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,GLvoid *);
+WXE_EXTERN WXEGLREADPIXELS weglReadPixels;
+typedef void (APIENTRY * WXEGLDRAWPIXELS)(GLsizei,GLsizei,GLenum,GLenum,const GLvoid *);
+WXE_EXTERN WXEGLDRAWPIXELS weglDrawPixels;
+typedef void (APIENTRY * WXEGLCOPYPIXELS)(GLint,GLint,GLsizei,GLsizei,GLenum);
+WXE_EXTERN WXEGLCOPYPIXELS weglCopyPixels;
typedef void (APIENTRY * WXEGLSTENCILFUNC)(GLenum,GLint,GLuint);
WXE_EXTERN WXEGLSTENCILFUNC weglStencilFunc;
typedef void (APIENTRY * WXEGLSTENCILMASK)(GLuint);
WXE_EXTERN WXEGLSTENCILMASK weglStencilMask;
typedef void (APIENTRY * WXEGLSTENCILOP)(GLenum,GLenum,GLenum);
WXE_EXTERN WXEGLSTENCILOP weglStencilOp;
-typedef void (APIENTRY * WXEGLTEXCOORD1DV)(const GLdouble *);
-WXE_EXTERN WXEGLTEXCOORD1DV weglTexCoord1dv;
-typedef void (APIENTRY * WXEGLTEXCOORD1FV)(const GLfloat *);
-WXE_EXTERN WXEGLTEXCOORD1FV weglTexCoord1fv;
-typedef void (APIENTRY * WXEGLTEXCOORD1IV)(const GLint *);
-WXE_EXTERN WXEGLTEXCOORD1IV weglTexCoord1iv;
-typedef void (APIENTRY * WXEGLTEXCOORD1SV)(const GLshort *);
-WXE_EXTERN WXEGLTEXCOORD1SV weglTexCoord1sv;
-typedef void (APIENTRY * WXEGLTEXCOORD2DV)(const GLdouble *);
-WXE_EXTERN WXEGLTEXCOORD2DV weglTexCoord2dv;
-typedef void (APIENTRY * WXEGLTEXCOORD2FV)(const GLfloat *);
-WXE_EXTERN WXEGLTEXCOORD2FV weglTexCoord2fv;
-typedef void (APIENTRY * WXEGLTEXCOORD2IV)(const GLint *);
-WXE_EXTERN WXEGLTEXCOORD2IV weglTexCoord2iv;
-typedef void (APIENTRY * WXEGLTEXCOORD2SV)(const GLshort *);
-WXE_EXTERN WXEGLTEXCOORD2SV weglTexCoord2sv;
-typedef void (APIENTRY * WXEGLTEXCOORD3DV)(const GLdouble *);
-WXE_EXTERN WXEGLTEXCOORD3DV weglTexCoord3dv;
-typedef void (APIENTRY * WXEGLTEXCOORD3FV)(const GLfloat *);
-WXE_EXTERN WXEGLTEXCOORD3FV weglTexCoord3fv;
-typedef void (APIENTRY * WXEGLTEXCOORD3IV)(const GLint *);
-WXE_EXTERN WXEGLTEXCOORD3IV weglTexCoord3iv;
-typedef void (APIENTRY * WXEGLTEXCOORD3SV)(const GLshort *);
-WXE_EXTERN WXEGLTEXCOORD3SV weglTexCoord3sv;
-typedef void (APIENTRY * WXEGLTEXCOORD4DV)(const GLdouble *);
-WXE_EXTERN WXEGLTEXCOORD4DV weglTexCoord4dv;
-typedef void (APIENTRY * WXEGLTEXCOORD4FV)(const GLfloat *);
-WXE_EXTERN WXEGLTEXCOORD4FV weglTexCoord4fv;
-typedef void (APIENTRY * WXEGLTEXCOORD4IV)(const GLint *);
-WXE_EXTERN WXEGLTEXCOORD4IV weglTexCoord4iv;
-typedef void (APIENTRY * WXEGLTEXCOORD4SV)(const GLshort *);
-WXE_EXTERN WXEGLTEXCOORD4SV weglTexCoord4sv;
-typedef void (APIENTRY * WXEGLTEXCOORDPOINTER)(GLint,GLenum,GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLTEXCOORDPOINTER weglTexCoordPointer;
-typedef void (APIENTRY * WXEGLTEXENVF)(GLenum,GLenum,GLfloat);
-WXE_EXTERN WXEGLTEXENVF weglTexEnvf;
-typedef void (APIENTRY * WXEGLTEXENVFV)(GLenum,GLenum,const GLfloat *);
-WXE_EXTERN WXEGLTEXENVFV weglTexEnvfv;
-typedef void (APIENTRY * WXEGLTEXENVI)(GLenum,GLenum,GLint);
-WXE_EXTERN WXEGLTEXENVI weglTexEnvi;
-typedef void (APIENTRY * WXEGLTEXENVIV)(GLenum,GLenum,const GLint *);
-WXE_EXTERN WXEGLTEXENVIV weglTexEnviv;
+typedef void (APIENTRY * WXEGLCLEARSTENCIL)(GLint);
+WXE_EXTERN WXEGLCLEARSTENCIL weglClearStencil;
typedef void (APIENTRY * WXEGLTEXGEND)(GLenum,GLenum,GLdouble);
WXE_EXTERN WXEGLTEXGEND weglTexGend;
-typedef void (APIENTRY * WXEGLTEXGENDV)(GLenum,GLenum,const GLdouble *);
-WXE_EXTERN WXEGLTEXGENDV weglTexGendv;
typedef void (APIENTRY * WXEGLTEXGENF)(GLenum,GLenum,GLfloat);
WXE_EXTERN WXEGLTEXGENF weglTexGenf;
-typedef void (APIENTRY * WXEGLTEXGENFV)(GLenum,GLenum,const GLfloat *);
-WXE_EXTERN WXEGLTEXGENFV weglTexGenfv;
typedef void (APIENTRY * WXEGLTEXGENI)(GLenum,GLenum,GLint);
WXE_EXTERN WXEGLTEXGENI weglTexGeni;
+typedef void (APIENTRY * WXEGLTEXGENDV)(GLenum,GLenum,const GLdouble *);
+WXE_EXTERN WXEGLTEXGENDV weglTexGendv;
+typedef void (APIENTRY * WXEGLTEXGENFV)(GLenum,GLenum,const GLfloat *);
+WXE_EXTERN WXEGLTEXGENFV weglTexGenfv;
typedef void (APIENTRY * WXEGLTEXGENIV)(GLenum,GLenum,const GLint *);
WXE_EXTERN WXEGLTEXGENIV weglTexGeniv;
-typedef void (APIENTRY * WXEGLTEXIMAGE1D)(GLenum,GLint,GLint,GLsizei,GLint,GLenum,GLenum,const GLvoid *);
-WXE_EXTERN WXEGLTEXIMAGE1D weglTexImage1D;
-typedef void (APIENTRY * WXEGLTEXIMAGE2D)(GLenum,GLint,GLint,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid *);
-WXE_EXTERN WXEGLTEXIMAGE2D weglTexImage2D;
+typedef void (APIENTRY * WXEGLGETTEXGENDV)(GLenum,GLenum,GLdouble *);
+WXE_EXTERN WXEGLGETTEXGENDV weglGetTexGendv;
+typedef void (APIENTRY * WXEGLGETTEXGENFV)(GLenum,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETTEXGENFV weglGetTexGenfv;
+typedef void (APIENTRY * WXEGLGETTEXGENIV)(GLenum,GLenum,GLint *);
+WXE_EXTERN WXEGLGETTEXGENIV weglGetTexGeniv;
+typedef void (APIENTRY * WXEGLTEXENVF)(GLenum,GLenum,GLfloat);
+WXE_EXTERN WXEGLTEXENVF weglTexEnvf;
+typedef void (APIENTRY * WXEGLTEXENVI)(GLenum,GLenum,GLint);
+WXE_EXTERN WXEGLTEXENVI weglTexEnvi;
+typedef void (APIENTRY * WXEGLTEXENVFV)(GLenum,GLenum,const GLfloat *);
+WXE_EXTERN WXEGLTEXENVFV weglTexEnvfv;
+typedef void (APIENTRY * WXEGLTEXENVIV)(GLenum,GLenum,const GLint *);
+WXE_EXTERN WXEGLTEXENVIV weglTexEnviv;
+typedef void (APIENTRY * WXEGLGETTEXENVFV)(GLenum,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETTEXENVFV weglGetTexEnvfv;
+typedef void (APIENTRY * WXEGLGETTEXENVIV)(GLenum,GLenum,GLint *);
+WXE_EXTERN WXEGLGETTEXENVIV weglGetTexEnviv;
typedef void (APIENTRY * WXEGLTEXPARAMETERF)(GLenum,GLenum,GLfloat);
WXE_EXTERN WXEGLTEXPARAMETERF weglTexParameterf;
-typedef void (APIENTRY * WXEGLTEXPARAMETERFV)(GLenum,GLenum,const GLfloat *);
-WXE_EXTERN WXEGLTEXPARAMETERFV weglTexParameterfv;
typedef void (APIENTRY * WXEGLTEXPARAMETERI)(GLenum,GLenum,GLint);
WXE_EXTERN WXEGLTEXPARAMETERI weglTexParameteri;
+typedef void (APIENTRY * WXEGLTEXPARAMETERFV)(GLenum,GLenum,const GLfloat *);
+WXE_EXTERN WXEGLTEXPARAMETERFV weglTexParameterfv;
typedef void (APIENTRY * WXEGLTEXPARAMETERIV)(GLenum,GLenum,const GLint *);
WXE_EXTERN WXEGLTEXPARAMETERIV weglTexParameteriv;
+typedef void (APIENTRY * WXEGLGETTEXPARAMETERFV)(GLenum,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETTEXPARAMETERFV weglGetTexParameterfv;
+typedef void (APIENTRY * WXEGLGETTEXPARAMETERIV)(GLenum,GLenum,GLint *);
+WXE_EXTERN WXEGLGETTEXPARAMETERIV weglGetTexParameteriv;
+typedef void (APIENTRY * WXEGLGETTEXLEVELPARAMETERFV)(GLenum,GLint,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETTEXLEVELPARAMETERFV weglGetTexLevelParameterfv;
+typedef void (APIENTRY * WXEGLGETTEXLEVELPARAMETERIV)(GLenum,GLint,GLenum,GLint *);
+WXE_EXTERN WXEGLGETTEXLEVELPARAMETERIV weglGetTexLevelParameteriv;
+typedef void (APIENTRY * WXEGLTEXIMAGE1D)(GLenum,GLint,GLint,GLsizei,GLint,GLenum,GLenum,const GLvoid *);
+WXE_EXTERN WXEGLTEXIMAGE1D weglTexImage1D;
+typedef void (APIENTRY * WXEGLTEXIMAGE2D)(GLenum,GLint,GLint,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid *);
+WXE_EXTERN WXEGLTEXIMAGE2D weglTexImage2D;
+typedef void (APIENTRY * WXEGLGETTEXIMAGE)(GLenum,GLint,GLenum,GLenum,GLvoid *);
+WXE_EXTERN WXEGLGETTEXIMAGE weglGetTexImage;
+typedef void (APIENTRY * WXEGLGENTEXTURES)(GLsizei,GLuint *);
+WXE_EXTERN WXEGLGENTEXTURES weglGenTextures;
+typedef void (APIENTRY * WXEGLDELETETEXTURES)(GLsizei,const GLuint *);
+WXE_EXTERN WXEGLDELETETEXTURES weglDeleteTextures;
+typedef void (APIENTRY * WXEGLBINDTEXTURE)(GLenum,GLuint);
+WXE_EXTERN WXEGLBINDTEXTURE weglBindTexture;
+typedef void (APIENTRY * WXEGLPRIORITIZETEXTURES)(GLsizei,const GLuint *,const GLclampf *);
+WXE_EXTERN WXEGLPRIORITIZETEXTURES weglPrioritizeTextures;
+typedef GLboolean (APIENTRY * WXEGLARETEXTURESRESIDENT)(GLsizei,const GLuint *,GLboolean *);
+WXE_EXTERN WXEGLARETEXTURESRESIDENT weglAreTexturesResident;
+typedef GLboolean (APIENTRY * WXEGLISTEXTURE)(GLuint);
+WXE_EXTERN WXEGLISTEXTURE weglIsTexture;
typedef void (APIENTRY * WXEGLTEXSUBIMAGE1D)(GLenum,GLint,GLint,GLsizei,GLenum,GLenum,const GLvoid *);
WXE_EXTERN WXEGLTEXSUBIMAGE1D weglTexSubImage1D;
typedef void (APIENTRY * WXEGLTEXSUBIMAGE2D)(GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,const GLvoid *);
WXE_EXTERN WXEGLTEXSUBIMAGE2D weglTexSubImage2D;
-typedef void (APIENTRY * WXEGLTRANSLATED)(GLdouble,GLdouble,GLdouble);
-WXE_EXTERN WXEGLTRANSLATED weglTranslated;
-typedef void (APIENTRY * WXEGLTRANSLATEF)(GLfloat,GLfloat,GLfloat);
-WXE_EXTERN WXEGLTRANSLATEF weglTranslatef;
-typedef void (APIENTRY * WXEGLVERTEX2DV)(const GLdouble *);
-WXE_EXTERN WXEGLVERTEX2DV weglVertex2dv;
-typedef void (APIENTRY * WXEGLVERTEX2FV)(const GLfloat *);
-WXE_EXTERN WXEGLVERTEX2FV weglVertex2fv;
-typedef void (APIENTRY * WXEGLVERTEX2IV)(const GLint *);
-WXE_EXTERN WXEGLVERTEX2IV weglVertex2iv;
-typedef void (APIENTRY * WXEGLVERTEX2SV)(const GLshort *);
-WXE_EXTERN WXEGLVERTEX2SV weglVertex2sv;
-typedef void (APIENTRY * WXEGLVERTEX3DV)(const GLdouble *);
-WXE_EXTERN WXEGLVERTEX3DV weglVertex3dv;
-typedef void (APIENTRY * WXEGLVERTEX3FV)(const GLfloat *);
-WXE_EXTERN WXEGLVERTEX3FV weglVertex3fv;
-typedef void (APIENTRY * WXEGLVERTEX3IV)(const GLint *);
-WXE_EXTERN WXEGLVERTEX3IV weglVertex3iv;
-typedef void (APIENTRY * WXEGLVERTEX3SV)(const GLshort *);
-WXE_EXTERN WXEGLVERTEX3SV weglVertex3sv;
-typedef void (APIENTRY * WXEGLVERTEX4DV)(const GLdouble *);
-WXE_EXTERN WXEGLVERTEX4DV weglVertex4dv;
-typedef void (APIENTRY * WXEGLVERTEX4FV)(const GLfloat *);
-WXE_EXTERN WXEGLVERTEX4FV weglVertex4fv;
-typedef void (APIENTRY * WXEGLVERTEX4IV)(const GLint *);
-WXE_EXTERN WXEGLVERTEX4IV weglVertex4iv;
-typedef void (APIENTRY * WXEGLVERTEX4SV)(const GLshort *);
-WXE_EXTERN WXEGLVERTEX4SV weglVertex4sv;
-typedef void (APIENTRY * WXEGLVERTEXPOINTER)(GLint,GLenum,GLsizei,const GLvoid *);
-WXE_EXTERN WXEGLVERTEXPOINTER weglVertexPointer;
-typedef void (APIENTRY * WXEGLVIEWPORT)(GLint,GLint,GLsizei,GLsizei);
-WXE_EXTERN WXEGLVIEWPORT weglViewport;
+typedef void (APIENTRY * WXEGLCOPYTEXIMAGE1D)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLint);
+WXE_EXTERN WXEGLCOPYTEXIMAGE1D weglCopyTexImage1D;
+typedef void (APIENTRY * WXEGLCOPYTEXIMAGE2D)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
+WXE_EXTERN WXEGLCOPYTEXIMAGE2D weglCopyTexImage2D;
+typedef void (APIENTRY * WXEGLCOPYTEXSUBIMAGE1D)(GLenum,GLint,GLint,GLint,GLint,GLsizei);
+WXE_EXTERN WXEGLCOPYTEXSUBIMAGE1D weglCopyTexSubImage1D;
+typedef void (APIENTRY * WXEGLCOPYTEXSUBIMAGE2D)(GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+WXE_EXTERN WXEGLCOPYTEXSUBIMAGE2D weglCopyTexSubImage2D;
+typedef void (APIENTRY * WXEGLMAP1D)(GLenum,GLdouble,GLdouble,GLint,GLint,const GLdouble *);
+WXE_EXTERN WXEGLMAP1D weglMap1d;
+typedef void (APIENTRY * WXEGLMAP1F)(GLenum,GLfloat,GLfloat,GLint,GLint,const GLfloat *);
+WXE_EXTERN WXEGLMAP1F weglMap1f;
+typedef void (APIENTRY * WXEGLMAP2D)(GLenum,GLdouble,GLdouble,GLint,GLint,GLdouble,GLdouble,GLint,GLint,const GLdouble *);
+WXE_EXTERN WXEGLMAP2D weglMap2d;
+typedef void (APIENTRY * WXEGLMAP2F)(GLenum,GLfloat,GLfloat,GLint,GLint,GLfloat,GLfloat,GLint,GLint,const GLfloat *);
+WXE_EXTERN WXEGLMAP2F weglMap2f;
+typedef void (APIENTRY * WXEGLGETMAPDV)(GLenum,GLenum,GLdouble *);
+WXE_EXTERN WXEGLGETMAPDV weglGetMapdv;
+typedef void (APIENTRY * WXEGLGETMAPFV)(GLenum,GLenum,GLfloat *);
+WXE_EXTERN WXEGLGETMAPFV weglGetMapfv;
+typedef void (APIENTRY * WXEGLGETMAPIV)(GLenum,GLenum,GLint *);
+WXE_EXTERN WXEGLGETMAPIV weglGetMapiv;
+typedef void (APIENTRY * WXEGLEVALCOORD1DV)(const GLdouble *);
+WXE_EXTERN WXEGLEVALCOORD1DV weglEvalCoord1dv;
+typedef void (APIENTRY * WXEGLEVALCOORD1FV)(const GLfloat *);
+WXE_EXTERN WXEGLEVALCOORD1FV weglEvalCoord1fv;
+typedef void (APIENTRY * WXEGLEVALCOORD2DV)(const GLdouble *);
+WXE_EXTERN WXEGLEVALCOORD2DV weglEvalCoord2dv;
+typedef void (APIENTRY * WXEGLEVALCOORD2FV)(const GLfloat *);
+WXE_EXTERN WXEGLEVALCOORD2FV weglEvalCoord2fv;
+typedef void (APIENTRY * WXEGLMAPGRID1D)(GLint,GLdouble,GLdouble);
+WXE_EXTERN WXEGLMAPGRID1D weglMapGrid1d;
+typedef void (APIENTRY * WXEGLMAPGRID1F)(GLint,GLfloat,GLfloat);
+WXE_EXTERN WXEGLMAPGRID1F weglMapGrid1f;
+typedef void (APIENTRY * WXEGLMAPGRID2D)(GLint,GLdouble,GLdouble,GLint,GLdouble,GLdouble);
+WXE_EXTERN WXEGLMAPGRID2D weglMapGrid2d;
+typedef void (APIENTRY * WXEGLMAPGRID2F)(GLint,GLfloat,GLfloat,GLint,GLfloat,GLfloat);
+WXE_EXTERN WXEGLMAPGRID2F weglMapGrid2f;
+typedef void (APIENTRY * WXEGLEVALPOINT1)(GLint);
+WXE_EXTERN WXEGLEVALPOINT1 weglEvalPoint1;
+typedef void (APIENTRY * WXEGLEVALPOINT2)(GLint,GLint);
+WXE_EXTERN WXEGLEVALPOINT2 weglEvalPoint2;
+typedef void (APIENTRY * WXEGLEVALMESH1)(GLenum,GLint,GLint);
+WXE_EXTERN WXEGLEVALMESH1 weglEvalMesh1;
+typedef void (APIENTRY * WXEGLEVALMESH2)(GLenum,GLint,GLint,GLint,GLint);
+WXE_EXTERN WXEGLEVALMESH2 weglEvalMesh2;
+typedef void (APIENTRY * WXEGLFOGF)(GLenum,GLfloat);
+WXE_EXTERN WXEGLFOGF weglFogf;
+typedef void (APIENTRY * WXEGLFOGI)(GLenum,GLint);
+WXE_EXTERN WXEGLFOGI weglFogi;
+typedef void (APIENTRY * WXEGLFOGFV)(GLenum,const GLfloat *);
+WXE_EXTERN WXEGLFOGFV weglFogfv;
+typedef void (APIENTRY * WXEGLFOGIV)(GLenum,const GLint *);
+WXE_EXTERN WXEGLFOGIV weglFogiv;
+typedef void (APIENTRY * WXEGLFEEDBACKBUFFER)(GLsizei,GLenum,GLfloat *);
+WXE_EXTERN WXEGLFEEDBACKBUFFER weglFeedbackBuffer;
+typedef void (APIENTRY * WXEGLPASSTHROUGH)(GLfloat);
+WXE_EXTERN WXEGLPASSTHROUGH weglPassThrough;
+typedef void (APIENTRY * WXEGLSELECTBUFFER)(GLsizei,GLuint *);
+WXE_EXTERN WXEGLSELECTBUFFER weglSelectBuffer;
+typedef void (APIENTRY * WXEGLINITNAMES)();
+WXE_EXTERN WXEGLINITNAMES weglInitNames;
+typedef void (APIENTRY * WXEGLLOADNAME)(GLuint);
+WXE_EXTERN WXEGLLOADNAME weglLoadName;
+typedef void (APIENTRY * WXEGLPUSHNAME)(GLuint);
+WXE_EXTERN WXEGLPUSHNAME weglPushName;
+typedef void (APIENTRY * WXEGLPOPNAME)();
+WXE_EXTERN WXEGLPOPNAME weglPopName;
typedef void (APIENTRY * WXEGLBLENDCOLOR)(GLclampf,GLclampf,GLclampf,GLclampf);
WXE_EXTERN WXEGLBLENDCOLOR weglBlendColor;
typedef void (APIENTRY * WXEGLBLENDEQUATION)(GLenum);
@@ -681,13 +681,13 @@ typedef void (APIENTRY * WXEGLMULTITEXCOORD4IV)(GLenum,const GLint *);
WXE_EXTERN WXEGLMULTITEXCOORD4IV weglMultiTexCoord4iv;
typedef void (APIENTRY * WXEGLMULTITEXCOORD4SV)(GLenum,const GLshort *);
WXE_EXTERN WXEGLMULTITEXCOORD4SV weglMultiTexCoord4sv;
-typedef void (APIENTRY * WXEGLLOADTRANSPOSEMATRIXF)(const GLfloat *);
+typedef void (APIENTRY * WXEGLLOADTRANSPOSEMATRIXF)(const GLfloat m[16]);
WXE_EXTERN WXEGLLOADTRANSPOSEMATRIXF weglLoadTransposeMatrixf;
-typedef void (APIENTRY * WXEGLLOADTRANSPOSEMATRIXD)(const GLdouble *);
+typedef void (APIENTRY * WXEGLLOADTRANSPOSEMATRIXD)(const GLdouble m[16]);
WXE_EXTERN WXEGLLOADTRANSPOSEMATRIXD weglLoadTransposeMatrixd;
-typedef void (APIENTRY * WXEGLMULTTRANSPOSEMATRIXF)(const GLfloat *);
+typedef void (APIENTRY * WXEGLMULTTRANSPOSEMATRIXF)(const GLfloat m[16]);
WXE_EXTERN WXEGLMULTTRANSPOSEMATRIXF weglMultTransposeMatrixf;
-typedef void (APIENTRY * WXEGLMULTTRANSPOSEMATRIXD)(const GLdouble *);
+typedef void (APIENTRY * WXEGLMULTTRANSPOSEMATRIXD)(const GLdouble m[16]);
WXE_EXTERN WXEGLMULTTRANSPOSEMATRIXD weglMultTransposeMatrixd;
typedef void (APIENTRY * WXEGLBLENDFUNCSEPARATE)(GLenum,GLenum,GLenum,GLenum);
WXE_EXTERN WXEGLBLENDFUNCSEPARATE weglBlendFuncSeparate;
@@ -1589,16 +1589,28 @@ typedef GLuint (APIENTRY * WXEGLGETDEBUGMESSAGELOGARB)(GLuint,GLsizei,GLenum *,G
WXE_EXTERN WXEGLGETDEBUGMESSAGELOGARB weglGetDebugMessageLogARB;
typedef GLenum (APIENTRY * WXEGLGETGRAPHICSRESETSTATUSARB)();
WXE_EXTERN WXEGLGETGRAPHICSRESETSTATUSARB weglGetGraphicsResetStatusARB;
-typedef void (APIENTRY * WXEGLRESIZEBUFFERSMESA)();
-WXE_EXTERN WXEGLRESIZEBUFFERSMESA weglResizeBuffersMESA;
-typedef void (APIENTRY * WXEGLWINDOWPOS4DVMESA)(const GLdouble *);
-WXE_EXTERN WXEGLWINDOWPOS4DVMESA weglWindowPos4dvMESA;
-typedef void (APIENTRY * WXEGLWINDOWPOS4FVMESA)(const GLfloat *);
-WXE_EXTERN WXEGLWINDOWPOS4FVMESA weglWindowPos4fvMESA;
-typedef void (APIENTRY * WXEGLWINDOWPOS4IVMESA)(const GLint *);
-WXE_EXTERN WXEGLWINDOWPOS4IVMESA weglWindowPos4ivMESA;
-typedef void (APIENTRY * WXEGLWINDOWPOS4SVMESA)(const GLshort *);
-WXE_EXTERN WXEGLWINDOWPOS4SVMESA weglWindowPos4svMESA;
+typedef void (APIENTRY * WXEGLDRAWARRAYSINSTANCEDBASEINSTANCE)(GLenum,GLint,GLsizei,GLsizei,GLuint);
+WXE_EXTERN WXEGLDRAWARRAYSINSTANCEDBASEINSTANCE weglDrawArraysInstancedBaseInstance;
+typedef void (APIENTRY * WXEGLDRAWELEMENTSINSTANCEDBASEINSTANCE)(GLenum,GLsizei,GLenum,const void *,GLsizei,GLuint);
+WXE_EXTERN WXEGLDRAWELEMENTSINSTANCEDBASEINSTANCE weglDrawElementsInstancedBaseInstance;
+typedef void (APIENTRY * WXEGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE)(GLenum,GLsizei,GLenum,const void *,GLsizei,GLint,GLuint);
+WXE_EXTERN WXEGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE weglDrawElementsInstancedBaseVertexBaseInstance;
+typedef void (APIENTRY * WXEGLDRAWTRANSFORMFEEDBACKINSTANCED)(GLenum,GLuint,GLsizei);
+WXE_EXTERN WXEGLDRAWTRANSFORMFEEDBACKINSTANCED weglDrawTransformFeedbackInstanced;
+typedef void (APIENTRY * WXEGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCED)(GLenum,GLuint,GLuint,GLsizei);
+WXE_EXTERN WXEGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCED weglDrawTransformFeedbackStreamInstanced;
+typedef void (APIENTRY * WXEGLGETINTERNALFORMATIV)(GLenum,GLenum,GLenum,GLsizei,GLint *);
+WXE_EXTERN WXEGLGETINTERNALFORMATIV weglGetInternalformativ;
+typedef void (APIENTRY * WXEGLBINDIMAGETEXTURE)(GLuint,GLuint,GLint,GLboolean,GLint,GLenum,GLenum);
+WXE_EXTERN WXEGLBINDIMAGETEXTURE weglBindImageTexture;
+typedef void (APIENTRY * WXEGLMEMORYBARRIER)(GLbitfield);
+WXE_EXTERN WXEGLMEMORYBARRIER weglMemoryBarrier;
+typedef void (APIENTRY * WXEGLTEXSTORAGE1D)(GLenum,GLsizei,GLenum,GLsizei);
+WXE_EXTERN WXEGLTEXSTORAGE1D weglTexStorage1D;
+typedef void (APIENTRY * WXEGLTEXSTORAGE2D)(GLenum,GLsizei,GLenum,GLsizei,GLsizei);
+WXE_EXTERN WXEGLTEXSTORAGE2D weglTexStorage2D;
+typedef void (APIENTRY * WXEGLTEXSTORAGE3D)(GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLsizei);
+WXE_EXTERN WXEGLTEXSTORAGE3D weglTexStorage3D;
typedef void (APIENTRY * WXEGLDEPTHBOUNDSEXT)(GLclampd,GLclampd);
WXE_EXTERN WXEGLDEPTHBOUNDSEXT weglDepthBoundsEXT;
typedef void (APIENTRY * WXEGLSTENCILCLEARTAGEXT)(GLsizei,GLuint);
diff --git a/lib/wx/c_src/gen/gl_finit.h b/lib/wx/c_src/gen/gl_finit.h
index 583e36faf7..afe947ed80 100644
--- a/lib/wx/c_src/gen/gl_finit.h
+++ b/lib/wx/c_src/gen/gl_finit.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The 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,186 +20,135 @@
gl_fns_t gl_fns[] =
{
- {"glAccum", NULL, &weglAccum},
- {"glAlphaFunc", NULL, &weglAlphaFunc},
- {"glAreTexturesResident", NULL, &weglAreTexturesResident},
- {"glArrayElement", NULL, &weglArrayElement},
- {"glBegin", NULL, &weglBegin},
- {"glBindTexture", NULL, &weglBindTexture},
- {"glBitmap", NULL, &weglBitmap},
- {"glBlendFunc", NULL, &weglBlendFunc},
- {"glCallList", NULL, &weglCallList},
- {"glCallLists", NULL, &weglCallLists},
- {"glClear", NULL, &weglClear},
- {"glClearAccum", NULL, &weglClearAccum},
- {"glClearColor", NULL, &weglClearColor},
- {"glClearDepth", NULL, &weglClearDepth},
{"glClearIndex", NULL, &weglClearIndex},
- {"glClearStencil", NULL, &weglClearStencil},
- {"glClipPlane", NULL, &weglClipPlane},
- {"glColor3bv", NULL, &weglColor3bv},
- {"glColor3dv", NULL, &weglColor3dv},
- {"glColor3fv", NULL, &weglColor3fv},
- {"glColor3iv", NULL, &weglColor3iv},
- {"glColor3sv", NULL, &weglColor3sv},
- {"glColor3ubv", NULL, &weglColor3ubv},
- {"glColor3uiv", NULL, &weglColor3uiv},
- {"glColor3usv", NULL, &weglColor3usv},
- {"glColor4bv", NULL, &weglColor4bv},
- {"glColor4dv", NULL, &weglColor4dv},
- {"glColor4fv", NULL, &weglColor4fv},
- {"glColor4iv", NULL, &weglColor4iv},
- {"glColor4sv", NULL, &weglColor4sv},
- {"glColor4ubv", NULL, &weglColor4ubv},
- {"glColor4uiv", NULL, &weglColor4uiv},
- {"glColor4usv", NULL, &weglColor4usv},
+ {"glClearColor", NULL, &weglClearColor},
+ {"glClear", NULL, &weglClear},
+ {"glIndexMask", NULL, &weglIndexMask},
{"glColorMask", NULL, &weglColorMask},
- {"glColorMaterial", NULL, &weglColorMaterial},
- {"glColorPointer", NULL, &weglColorPointer},
- {"glCopyPixels", NULL, &weglCopyPixels},
- {"glCopyTexImage1D", NULL, &weglCopyTexImage1D},
- {"glCopyTexImage2D", NULL, &weglCopyTexImage2D},
- {"glCopyTexSubImage1D", NULL, &weglCopyTexSubImage1D},
- {"glCopyTexSubImage2D", NULL, &weglCopyTexSubImage2D},
+ {"glAlphaFunc", NULL, &weglAlphaFunc},
+ {"glBlendFunc", NULL, &weglBlendFunc},
+ {"glLogicOp", NULL, &weglLogicOp},
{"glCullFace", NULL, &weglCullFace},
- {"glDeleteLists", NULL, &weglDeleteLists},
- {"glDeleteTextures", NULL, &weglDeleteTextures},
- {"glDepthFunc", NULL, &weglDepthFunc},
- {"glDepthMask", NULL, &weglDepthMask},
- {"glDepthRange", NULL, &weglDepthRange},
- {"glDisable", NULL, &weglDisable},
- {"glDisableClientState", NULL, &weglDisableClientState},
- {"glDrawArrays", NULL, &weglDrawArrays},
- {"glDrawBuffer", NULL, &weglDrawBuffer},
- {"glDrawElements", NULL, &weglDrawElements},
- {"glDrawPixels", NULL, &weglDrawPixels},
+ {"glFrontFace", NULL, &weglFrontFace},
+ {"glPointSize", NULL, &weglPointSize},
+ {"glLineWidth", NULL, &weglLineWidth},
+ {"glLineStipple", NULL, &weglLineStipple},
+ {"glPolygonMode", NULL, &weglPolygonMode},
+ {"glPolygonOffset", NULL, &weglPolygonOffset},
+ {"glPolygonStipple", NULL, &weglPolygonStipple},
+ {"glGetPolygonStipple", NULL, &weglGetPolygonStipple},
{"glEdgeFlagv", NULL, &weglEdgeFlagv},
- {"glEdgeFlagPointer", NULL, &weglEdgeFlagPointer},
+ {"glScissor", NULL, &weglScissor},
+ {"glClipPlane", NULL, &weglClipPlane},
+ {"glGetClipPlane", NULL, &weglGetClipPlane},
+ {"glDrawBuffer", NULL, &weglDrawBuffer},
+ {"glReadBuffer", NULL, &weglReadBuffer},
{"glEnable", NULL, &weglEnable},
+ {"glDisable", NULL, &weglDisable},
+ {"glIsEnabled", NULL, &weglIsEnabled},
{"glEnableClientState", NULL, &weglEnableClientState},
- {"glEnd", NULL, &weglEnd},
- {"glEndList", NULL, &weglEndList},
- {"glEvalCoord1dv", NULL, &weglEvalCoord1dv},
- {"glEvalCoord1fv", NULL, &weglEvalCoord1fv},
- {"glEvalCoord2dv", NULL, &weglEvalCoord2dv},
- {"glEvalCoord2fv", NULL, &weglEvalCoord2fv},
- {"glEvalMesh1", NULL, &weglEvalMesh1},
- {"glEvalMesh2", NULL, &weglEvalMesh2},
- {"glEvalPoint1", NULL, &weglEvalPoint1},
- {"glEvalPoint2", NULL, &weglEvalPoint2},
- {"glFeedbackBuffer", NULL, &weglFeedbackBuffer},
- {"glFinish", NULL, &weglFinish},
- {"glFlush", NULL, &weglFlush},
- {"glFogf", NULL, &weglFogf},
- {"glFogfv", NULL, &weglFogfv},
- {"glFogi", NULL, &weglFogi},
- {"glFogiv", NULL, &weglFogiv},
- {"glFrontFace", NULL, &weglFrontFace},
- {"glFrustum", NULL, &weglFrustum},
- {"glGenLists", NULL, &weglGenLists},
- {"glGenTextures", NULL, &weglGenTextures},
+ {"glDisableClientState", NULL, &weglDisableClientState},
{"glGetBooleanv", NULL, &weglGetBooleanv},
- {"glGetClipPlane", NULL, &weglGetClipPlane},
{"glGetDoublev", NULL, &weglGetDoublev},
- {"glGetError", NULL, &weglGetError},
{"glGetFloatv", NULL, &weglGetFloatv},
{"glGetIntegerv", NULL, &weglGetIntegerv},
- {"glGetLightfv", NULL, &weglGetLightfv},
- {"glGetLightiv", NULL, &weglGetLightiv},
- {"glGetMapdv", NULL, &weglGetMapdv},
- {"glGetMapfv", NULL, &weglGetMapfv},
- {"glGetMapiv", NULL, &weglGetMapiv},
- {"glGetMaterialfv", NULL, &weglGetMaterialfv},
- {"glGetMaterialiv", NULL, &weglGetMaterialiv},
- {"glGetPixelMapfv", NULL, &weglGetPixelMapfv},
- {"glGetPixelMapuiv", NULL, &weglGetPixelMapuiv},
- {"glGetPixelMapusv", NULL, &weglGetPixelMapusv},
- {"glGetPolygonStipple", NULL, &weglGetPolygonStipple},
+ {"glPushAttrib", NULL, &weglPushAttrib},
+ {"glPopAttrib", NULL, &weglPopAttrib},
+ {"glPushClientAttrib", NULL, &weglPushClientAttrib},
+ {"glPopClientAttrib", NULL, &weglPopClientAttrib},
+ {"glRenderMode", NULL, &weglRenderMode},
+ {"glGetError", NULL, &weglGetError},
{"glGetString", NULL, &weglGetString},
- {"glGetTexEnvfv", NULL, &weglGetTexEnvfv},
- {"glGetTexEnviv", NULL, &weglGetTexEnviv},
- {"glGetTexGendv", NULL, &weglGetTexGendv},
- {"glGetTexGenfv", NULL, &weglGetTexGenfv},
- {"glGetTexGeniv", NULL, &weglGetTexGeniv},
- {"glGetTexImage", NULL, &weglGetTexImage},
- {"glGetTexLevelParameterfv", NULL, &weglGetTexLevelParameterfv},
- {"glGetTexLevelParameteriv", NULL, &weglGetTexLevelParameteriv},
- {"glGetTexParameterfv", NULL, &weglGetTexParameterfv},
- {"glGetTexParameteriv", NULL, &weglGetTexParameteriv},
+ {"glFinish", NULL, &weglFinish},
+ {"glFlush", NULL, &weglFlush},
{"glHint", NULL, &weglHint},
- {"glIndexMask", NULL, &weglIndexMask},
- {"glIndexPointer", NULL, &weglIndexPointer},
- {"glIndexdv", NULL, &weglIndexdv},
- {"glIndexfv", NULL, &weglIndexfv},
- {"glIndexiv", NULL, &weglIndexiv},
- {"glIndexsv", NULL, &weglIndexsv},
- {"glIndexubv", NULL, &weglIndexubv},
- {"glInitNames", NULL, &weglInitNames},
- {"glInterleavedArrays", NULL, &weglInterleavedArrays},
- {"glIsEnabled", NULL, &weglIsEnabled},
- {"glIsList", NULL, &weglIsList},
- {"glIsTexture", NULL, &weglIsTexture},
- {"glLightModelf", NULL, &weglLightModelf},
- {"glLightModelfv", NULL, &weglLightModelfv},
- {"glLightModeli", NULL, &weglLightModeli},
- {"glLightModeliv", NULL, &weglLightModeliv},
- {"glLightf", NULL, &weglLightf},
- {"glLightfv", NULL, &weglLightfv},
- {"glLighti", NULL, &weglLighti},
- {"glLightiv", NULL, &weglLightiv},
- {"glLineStipple", NULL, &weglLineStipple},
- {"glLineWidth", NULL, &weglLineWidth},
- {"glListBase", NULL, &weglListBase},
+ {"glClearDepth", NULL, &weglClearDepth},
+ {"glDepthFunc", NULL, &weglDepthFunc},
+ {"glDepthMask", NULL, &weglDepthMask},
+ {"glDepthRange", NULL, &weglDepthRange},
+ {"glClearAccum", NULL, &weglClearAccum},
+ {"glAccum", NULL, &weglAccum},
+ {"glMatrixMode", NULL, &weglMatrixMode},
+ {"glOrtho", NULL, &weglOrtho},
+ {"glFrustum", NULL, &weglFrustum},
+ {"glViewport", NULL, &weglViewport},
+ {"glPushMatrix", NULL, &weglPushMatrix},
+ {"glPopMatrix", NULL, &weglPopMatrix},
{"glLoadIdentity", NULL, &weglLoadIdentity},
{"glLoadMatrixd", NULL, &weglLoadMatrixd},
{"glLoadMatrixf", NULL, &weglLoadMatrixf},
- {"glLoadName", NULL, &weglLoadName},
- {"glLogicOp", NULL, &weglLogicOp},
- {"glMap1d", NULL, &weglMap1d},
- {"glMap1f", NULL, &weglMap1f},
- {"glMap2d", NULL, &weglMap2d},
- {"glMap2f", NULL, &weglMap2f},
- {"glMapGrid1d", NULL, &weglMapGrid1d},
- {"glMapGrid1f", NULL, &weglMapGrid1f},
- {"glMapGrid2d", NULL, &weglMapGrid2d},
- {"glMapGrid2f", NULL, &weglMapGrid2f},
- {"glMaterialf", NULL, &weglMaterialf},
- {"glMaterialfv", NULL, &weglMaterialfv},
- {"glMateriali", NULL, &weglMateriali},
- {"glMaterialiv", NULL, &weglMaterialiv},
- {"glMatrixMode", NULL, &weglMatrixMode},
{"glMultMatrixd", NULL, &weglMultMatrixd},
{"glMultMatrixf", NULL, &weglMultMatrixf},
+ {"glRotated", NULL, &weglRotated},
+ {"glRotatef", NULL, &weglRotatef},
+ {"glScaled", NULL, &weglScaled},
+ {"glScalef", NULL, &weglScalef},
+ {"glTranslated", NULL, &weglTranslated},
+ {"glTranslatef", NULL, &weglTranslatef},
+ {"glIsList", NULL, &weglIsList},
+ {"glDeleteLists", NULL, &weglDeleteLists},
+ {"glGenLists", NULL, &weglGenLists},
{"glNewList", NULL, &weglNewList},
+ {"glEndList", NULL, &weglEndList},
+ {"glCallList", NULL, &weglCallList},
+ {"glCallLists", NULL, &weglCallLists},
+ {"glListBase", NULL, &weglListBase},
+ {"glBegin", NULL, &weglBegin},
+ {"glEnd", NULL, &weglEnd},
+ {"glVertex2dv", NULL, &weglVertex2dv},
+ {"glVertex2fv", NULL, &weglVertex2fv},
+ {"glVertex2iv", NULL, &weglVertex2iv},
+ {"glVertex2sv", NULL, &weglVertex2sv},
+ {"glVertex3dv", NULL, &weglVertex3dv},
+ {"glVertex3fv", NULL, &weglVertex3fv},
+ {"glVertex3iv", NULL, &weglVertex3iv},
+ {"glVertex3sv", NULL, &weglVertex3sv},
+ {"glVertex4dv", NULL, &weglVertex4dv},
+ {"glVertex4fv", NULL, &weglVertex4fv},
+ {"glVertex4iv", NULL, &weglVertex4iv},
+ {"glVertex4sv", NULL, &weglVertex4sv},
{"glNormal3bv", NULL, &weglNormal3bv},
{"glNormal3dv", NULL, &weglNormal3dv},
{"glNormal3fv", NULL, &weglNormal3fv},
{"glNormal3iv", NULL, &weglNormal3iv},
{"glNormal3sv", NULL, &weglNormal3sv},
- {"glNormalPointer", NULL, &weglNormalPointer},
- {"glOrtho", NULL, &weglOrtho},
- {"glPassThrough", NULL, &weglPassThrough},
- {"glPixelMapfv", NULL, &weglPixelMapfv},
- {"glPixelMapuiv", NULL, &weglPixelMapuiv},
- {"glPixelMapusv", NULL, &weglPixelMapusv},
- {"glPixelStoref", NULL, &weglPixelStoref},
- {"glPixelStorei", NULL, &weglPixelStorei},
- {"glPixelTransferf", NULL, &weglPixelTransferf},
- {"glPixelTransferi", NULL, &weglPixelTransferi},
- {"glPixelZoom", NULL, &weglPixelZoom},
- {"glPointSize", NULL, &weglPointSize},
- {"glPolygonMode", NULL, &weglPolygonMode},
- {"glPolygonOffset", NULL, &weglPolygonOffset},
- {"glPolygonStipple", NULL, &weglPolygonStipple},
- {"glPopAttrib", NULL, &weglPopAttrib},
- {"glPopClientAttrib", NULL, &weglPopClientAttrib},
- {"glPopMatrix", NULL, &weglPopMatrix},
- {"glPopName", NULL, &weglPopName},
- {"glPrioritizeTextures", NULL, &weglPrioritizeTextures},
- {"glPushAttrib", NULL, &weglPushAttrib},
- {"glPushClientAttrib", NULL, &weglPushClientAttrib},
- {"glPushMatrix", NULL, &weglPushMatrix},
- {"glPushName", NULL, &weglPushName},
+ {"glIndexdv", NULL, &weglIndexdv},
+ {"glIndexfv", NULL, &weglIndexfv},
+ {"glIndexiv", NULL, &weglIndexiv},
+ {"glIndexsv", NULL, &weglIndexsv},
+ {"glIndexubv", NULL, &weglIndexubv},
+ {"glColor3bv", NULL, &weglColor3bv},
+ {"glColor3dv", NULL, &weglColor3dv},
+ {"glColor3fv", NULL, &weglColor3fv},
+ {"glColor3iv", NULL, &weglColor3iv},
+ {"glColor3sv", NULL, &weglColor3sv},
+ {"glColor3ubv", NULL, &weglColor3ubv},
+ {"glColor3uiv", NULL, &weglColor3uiv},
+ {"glColor3usv", NULL, &weglColor3usv},
+ {"glColor4bv", NULL, &weglColor4bv},
+ {"glColor4dv", NULL, &weglColor4dv},
+ {"glColor4fv", NULL, &weglColor4fv},
+ {"glColor4iv", NULL, &weglColor4iv},
+ {"glColor4sv", NULL, &weglColor4sv},
+ {"glColor4ubv", NULL, &weglColor4ubv},
+ {"glColor4uiv", NULL, &weglColor4uiv},
+ {"glColor4usv", NULL, &weglColor4usv},
+ {"glTexCoord1dv", NULL, &weglTexCoord1dv},
+ {"glTexCoord1fv", NULL, &weglTexCoord1fv},
+ {"glTexCoord1iv", NULL, &weglTexCoord1iv},
+ {"glTexCoord1sv", NULL, &weglTexCoord1sv},
+ {"glTexCoord2dv", NULL, &weglTexCoord2dv},
+ {"glTexCoord2fv", NULL, &weglTexCoord2fv},
+ {"glTexCoord2iv", NULL, &weglTexCoord2iv},
+ {"glTexCoord2sv", NULL, &weglTexCoord2sv},
+ {"glTexCoord3dv", NULL, &weglTexCoord3dv},
+ {"glTexCoord3fv", NULL, &weglTexCoord3fv},
+ {"glTexCoord3iv", NULL, &weglTexCoord3iv},
+ {"glTexCoord3sv", NULL, &weglTexCoord3sv},
+ {"glTexCoord4dv", NULL, &weglTexCoord4dv},
+ {"glTexCoord4fv", NULL, &weglTexCoord4fv},
+ {"glTexCoord4iv", NULL, &weglTexCoord4iv},
+ {"glTexCoord4sv", NULL, &weglTexCoord4sv},
{"glRasterPos2dv", NULL, &weglRasterPos2dv},
{"glRasterPos2fv", NULL, &weglRasterPos2fv},
{"glRasterPos2iv", NULL, &weglRasterPos2iv},
@@ -212,78 +161,129 @@ gl_fns_t gl_fns[] =
{"glRasterPos4fv", NULL, &weglRasterPos4fv},
{"glRasterPos4iv", NULL, &weglRasterPos4iv},
{"glRasterPos4sv", NULL, &weglRasterPos4sv},
- {"glReadBuffer", NULL, &weglReadBuffer},
- {"glReadPixels", NULL, &weglReadPixels},
{"glRectd", NULL, &weglRectd},
- {"glRectdv", NULL, &weglRectdv},
{"glRectf", NULL, &weglRectf},
- {"glRectfv", NULL, &weglRectfv},
{"glRecti", NULL, &weglRecti},
- {"glRectiv", NULL, &weglRectiv},
{"glRects", NULL, &weglRects},
+ {"glRectdv", NULL, &weglRectdv},
+ {"glRectfv", NULL, &weglRectfv},
+ {"glRectiv", NULL, &weglRectiv},
{"glRectsv", NULL, &weglRectsv},
- {"glRenderMode", NULL, &weglRenderMode},
- {"glRotated", NULL, &weglRotated},
- {"glRotatef", NULL, &weglRotatef},
- {"glScaled", NULL, &weglScaled},
- {"glScalef", NULL, &weglScalef},
- {"glScissor", NULL, &weglScissor},
- {"glSelectBuffer", NULL, &weglSelectBuffer},
+ {"glVertexPointer", NULL, &weglVertexPointer},
+ {"glNormalPointer", NULL, &weglNormalPointer},
+ {"glColorPointer", NULL, &weglColorPointer},
+ {"glIndexPointer", NULL, &weglIndexPointer},
+ {"glTexCoordPointer", NULL, &weglTexCoordPointer},
+ {"glEdgeFlagPointer", NULL, &weglEdgeFlagPointer},
+ {"glArrayElement", NULL, &weglArrayElement},
+ {"glDrawArrays", NULL, &weglDrawArrays},
+ {"glDrawElements", NULL, &weglDrawElements},
+ {"glInterleavedArrays", NULL, &weglInterleavedArrays},
{"glShadeModel", NULL, &weglShadeModel},
+ {"glLightf", NULL, &weglLightf},
+ {"glLighti", NULL, &weglLighti},
+ {"glLightfv", NULL, &weglLightfv},
+ {"glLightiv", NULL, &weglLightiv},
+ {"glGetLightfv", NULL, &weglGetLightfv},
+ {"glGetLightiv", NULL, &weglGetLightiv},
+ {"glLightModelf", NULL, &weglLightModelf},
+ {"glLightModeli", NULL, &weglLightModeli},
+ {"glLightModelfv", NULL, &weglLightModelfv},
+ {"glLightModeliv", NULL, &weglLightModeliv},
+ {"glMaterialf", NULL, &weglMaterialf},
+ {"glMateriali", NULL, &weglMateriali},
+ {"glMaterialfv", NULL, &weglMaterialfv},
+ {"glMaterialiv", NULL, &weglMaterialiv},
+ {"glGetMaterialfv", NULL, &weglGetMaterialfv},
+ {"glGetMaterialiv", NULL, &weglGetMaterialiv},
+ {"glColorMaterial", NULL, &weglColorMaterial},
+ {"glPixelZoom", NULL, &weglPixelZoom},
+ {"glPixelStoref", NULL, &weglPixelStoref},
+ {"glPixelStorei", NULL, &weglPixelStorei},
+ {"glPixelTransferf", NULL, &weglPixelTransferf},
+ {"glPixelTransferi", NULL, &weglPixelTransferi},
+ {"glPixelMapfv", NULL, &weglPixelMapfv},
+ {"glPixelMapuiv", NULL, &weglPixelMapuiv},
+ {"glPixelMapusv", NULL, &weglPixelMapusv},
+ {"glGetPixelMapfv", NULL, &weglGetPixelMapfv},
+ {"glGetPixelMapuiv", NULL, &weglGetPixelMapuiv},
+ {"glGetPixelMapusv", NULL, &weglGetPixelMapusv},
+ {"glBitmap", NULL, &weglBitmap},
+ {"glReadPixels", NULL, &weglReadPixels},
+ {"glDrawPixels", NULL, &weglDrawPixels},
+ {"glCopyPixels", NULL, &weglCopyPixels},
{"glStencilFunc", NULL, &weglStencilFunc},
{"glStencilMask", NULL, &weglStencilMask},
{"glStencilOp", NULL, &weglStencilOp},
- {"glTexCoord1dv", NULL, &weglTexCoord1dv},
- {"glTexCoord1fv", NULL, &weglTexCoord1fv},
- {"glTexCoord1iv", NULL, &weglTexCoord1iv},
- {"glTexCoord1sv", NULL, &weglTexCoord1sv},
- {"glTexCoord2dv", NULL, &weglTexCoord2dv},
- {"glTexCoord2fv", NULL, &weglTexCoord2fv},
- {"glTexCoord2iv", NULL, &weglTexCoord2iv},
- {"glTexCoord2sv", NULL, &weglTexCoord2sv},
- {"glTexCoord3dv", NULL, &weglTexCoord3dv},
- {"glTexCoord3fv", NULL, &weglTexCoord3fv},
- {"glTexCoord3iv", NULL, &weglTexCoord3iv},
- {"glTexCoord3sv", NULL, &weglTexCoord3sv},
- {"glTexCoord4dv", NULL, &weglTexCoord4dv},
- {"glTexCoord4fv", NULL, &weglTexCoord4fv},
- {"glTexCoord4iv", NULL, &weglTexCoord4iv},
- {"glTexCoord4sv", NULL, &weglTexCoord4sv},
- {"glTexCoordPointer", NULL, &weglTexCoordPointer},
- {"glTexEnvf", NULL, &weglTexEnvf},
- {"glTexEnvfv", NULL, &weglTexEnvfv},
- {"glTexEnvi", NULL, &weglTexEnvi},
- {"glTexEnviv", NULL, &weglTexEnviv},
+ {"glClearStencil", NULL, &weglClearStencil},
{"glTexGend", NULL, &weglTexGend},
- {"glTexGendv", NULL, &weglTexGendv},
{"glTexGenf", NULL, &weglTexGenf},
- {"glTexGenfv", NULL, &weglTexGenfv},
{"glTexGeni", NULL, &weglTexGeni},
+ {"glTexGendv", NULL, &weglTexGendv},
+ {"glTexGenfv", NULL, &weglTexGenfv},
{"glTexGeniv", NULL, &weglTexGeniv},
- {"glTexImage1D", NULL, &weglTexImage1D},
- {"glTexImage2D", NULL, &weglTexImage2D},
+ {"glGetTexGendv", NULL, &weglGetTexGendv},
+ {"glGetTexGenfv", NULL, &weglGetTexGenfv},
+ {"glGetTexGeniv", NULL, &weglGetTexGeniv},
+ {"glTexEnvf", NULL, &weglTexEnvf},
+ {"glTexEnvi", NULL, &weglTexEnvi},
+ {"glTexEnvfv", NULL, &weglTexEnvfv},
+ {"glTexEnviv", NULL, &weglTexEnviv},
+ {"glGetTexEnvfv", NULL, &weglGetTexEnvfv},
+ {"glGetTexEnviv", NULL, &weglGetTexEnviv},
{"glTexParameterf", NULL, &weglTexParameterf},
- {"glTexParameterfv", NULL, &weglTexParameterfv},
{"glTexParameteri", NULL, &weglTexParameteri},
+ {"glTexParameterfv", NULL, &weglTexParameterfv},
{"glTexParameteriv", NULL, &weglTexParameteriv},
+ {"glGetTexParameterfv", NULL, &weglGetTexParameterfv},
+ {"glGetTexParameteriv", NULL, &weglGetTexParameteriv},
+ {"glGetTexLevelParameterfv", NULL, &weglGetTexLevelParameterfv},
+ {"glGetTexLevelParameteriv", NULL, &weglGetTexLevelParameteriv},
+ {"glTexImage1D", NULL, &weglTexImage1D},
+ {"glTexImage2D", NULL, &weglTexImage2D},
+ {"glGetTexImage", NULL, &weglGetTexImage},
+ {"glGenTextures", NULL, &weglGenTextures},
+ {"glDeleteTextures", NULL, &weglDeleteTextures},
+ {"glBindTexture", NULL, &weglBindTexture},
+ {"glPrioritizeTextures", NULL, &weglPrioritizeTextures},
+ {"glAreTexturesResident", NULL, &weglAreTexturesResident},
+ {"glIsTexture", NULL, &weglIsTexture},
{"glTexSubImage1D", NULL, &weglTexSubImage1D},
{"glTexSubImage2D", NULL, &weglTexSubImage2D},
- {"glTranslated", NULL, &weglTranslated},
- {"glTranslatef", NULL, &weglTranslatef},
- {"glVertex2dv", NULL, &weglVertex2dv},
- {"glVertex2fv", NULL, &weglVertex2fv},
- {"glVertex2iv", NULL, &weglVertex2iv},
- {"glVertex2sv", NULL, &weglVertex2sv},
- {"glVertex3dv", NULL, &weglVertex3dv},
- {"glVertex3fv", NULL, &weglVertex3fv},
- {"glVertex3iv", NULL, &weglVertex3iv},
- {"glVertex3sv", NULL, &weglVertex3sv},
- {"glVertex4dv", NULL, &weglVertex4dv},
- {"glVertex4fv", NULL, &weglVertex4fv},
- {"glVertex4iv", NULL, &weglVertex4iv},
- {"glVertex4sv", NULL, &weglVertex4sv},
- {"glVertexPointer", NULL, &weglVertexPointer},
- {"glViewport", NULL, &weglViewport},
+ {"glCopyTexImage1D", NULL, &weglCopyTexImage1D},
+ {"glCopyTexImage2D", NULL, &weglCopyTexImage2D},
+ {"glCopyTexSubImage1D", NULL, &weglCopyTexSubImage1D},
+ {"glCopyTexSubImage2D", NULL, &weglCopyTexSubImage2D},
+ {"glMap1d", NULL, &weglMap1d},
+ {"glMap1f", NULL, &weglMap1f},
+ {"glMap2d", NULL, &weglMap2d},
+ {"glMap2f", NULL, &weglMap2f},
+ {"glGetMapdv", NULL, &weglGetMapdv},
+ {"glGetMapfv", NULL, &weglGetMapfv},
+ {"glGetMapiv", NULL, &weglGetMapiv},
+ {"glEvalCoord1dv", NULL, &weglEvalCoord1dv},
+ {"glEvalCoord1fv", NULL, &weglEvalCoord1fv},
+ {"glEvalCoord2dv", NULL, &weglEvalCoord2dv},
+ {"glEvalCoord2fv", NULL, &weglEvalCoord2fv},
+ {"glMapGrid1d", NULL, &weglMapGrid1d},
+ {"glMapGrid1f", NULL, &weglMapGrid1f},
+ {"glMapGrid2d", NULL, &weglMapGrid2d},
+ {"glMapGrid2f", NULL, &weglMapGrid2f},
+ {"glEvalPoint1", NULL, &weglEvalPoint1},
+ {"glEvalPoint2", NULL, &weglEvalPoint2},
+ {"glEvalMesh1", NULL, &weglEvalMesh1},
+ {"glEvalMesh2", NULL, &weglEvalMesh2},
+ {"glFogf", NULL, &weglFogf},
+ {"glFogi", NULL, &weglFogi},
+ {"glFogfv", NULL, &weglFogfv},
+ {"glFogiv", NULL, &weglFogiv},
+ {"glFeedbackBuffer", NULL, &weglFeedbackBuffer},
+ {"glPassThrough", NULL, &weglPassThrough},
+ {"glSelectBuffer", NULL, &weglSelectBuffer},
+ {"glInitNames", NULL, &weglInitNames},
+ {"glLoadName", NULL, &weglLoadName},
+ {"glPushName", NULL, &weglPushName},
+ {"glPopName", NULL, &weglPopName},
{"glBlendColor", NULL, &weglBlendColor},
{"glBlendEquation", NULL, &weglBlendEquation},
{"glDrawRangeElements", NULL, &weglDrawRangeElements},
@@ -367,14 +367,14 @@ gl_fns_t gl_fns[] =
{"glSecondaryColor3uiv", NULL, &weglSecondaryColor3uiv},
{"glSecondaryColor3usv", NULL, &weglSecondaryColor3usv},
{"glSecondaryColorPointer", NULL, &weglSecondaryColorPointer},
- {"glWindowPos2dv", "glWindowPos2dvMESA", &weglWindowPos2dv},
- {"glWindowPos2fv", "glWindowPos2fvMESA", &weglWindowPos2fv},
- {"glWindowPos2iv", "glWindowPos2ivMESA", &weglWindowPos2iv},
- {"glWindowPos2sv", "glWindowPos2svMESA", &weglWindowPos2sv},
- {"glWindowPos3dv", "glWindowPos3dvMESA", &weglWindowPos3dv},
- {"glWindowPos3fv", "glWindowPos3fvMESA", &weglWindowPos3fv},
- {"glWindowPos3iv", "glWindowPos3ivMESA", &weglWindowPos3iv},
- {"glWindowPos3sv", "glWindowPos3svMESA", &weglWindowPos3sv},
+ {"glWindowPos2dv", "glWindowPos2dvARB", &weglWindowPos2dv},
+ {"glWindowPos2fv", "glWindowPos2fvARB", &weglWindowPos2fv},
+ {"glWindowPos2iv", "glWindowPos2ivARB", &weglWindowPos2iv},
+ {"glWindowPos2sv", "glWindowPos2svARB", &weglWindowPos2sv},
+ {"glWindowPos3dv", "glWindowPos3dvARB", &weglWindowPos3dv},
+ {"glWindowPos3fv", "glWindowPos3fvARB", &weglWindowPos3fv},
+ {"glWindowPos3iv", "glWindowPos3ivARB", &weglWindowPos3iv},
+ {"glWindowPos3sv", "glWindowPos3svARB", &weglWindowPos3sv},
{"glGenQueries", "glGenQueriesARB", &weglGenQueries},
{"glDeleteQueries", "glDeleteQueriesARB", &weglDeleteQueries},
{"glIsQuery", "glIsQueryARB", &weglIsQuery},
@@ -799,11 +799,17 @@ gl_fns_t gl_fns[] =
{"glDebugMessageInsertARB", NULL, &weglDebugMessageInsertARB},
{"glGetDebugMessageLogARB", NULL, &weglGetDebugMessageLogARB},
{"glGetGraphicsResetStatusARB", NULL, &weglGetGraphicsResetStatusARB},
- {"glResizeBuffersMESA", NULL, &weglResizeBuffersMESA},
- {"glWindowPos4dvMESA", NULL, &weglWindowPos4dvMESA},
- {"glWindowPos4fvMESA", NULL, &weglWindowPos4fvMESA},
- {"glWindowPos4ivMESA", NULL, &weglWindowPos4ivMESA},
- {"glWindowPos4svMESA", NULL, &weglWindowPos4svMESA},
+ {"glDrawArraysInstancedBaseInstance", NULL, &weglDrawArraysInstancedBaseInstance},
+ {"glDrawElementsInstancedBaseInstance", NULL, &weglDrawElementsInstancedBaseInstance},
+ {"glDrawElementsInstancedBaseVertexBaseInstance", NULL, &weglDrawElementsInstancedBaseVertexBaseInstance},
+ {"glDrawTransformFeedbackInstanced", NULL, &weglDrawTransformFeedbackInstanced},
+ {"glDrawTransformFeedbackStreamInstanced", NULL, &weglDrawTransformFeedbackStreamInstanced},
+ {"glGetInternalformativ", NULL, &weglGetInternalformativ},
+ {"glBindImageTexture", NULL, &weglBindImageTexture},
+ {"glMemoryBarrier", NULL, &weglMemoryBarrier},
+ {"glTexStorage1D", NULL, &weglTexStorage1D},
+ {"glTexStorage2D", NULL, &weglTexStorage2D},
+ {"glTexStorage3D", NULL, &weglTexStorage3D},
{"glDepthBoundsEXT", NULL, &weglDepthBoundsEXT},
{"glStencilClearTagEXT", NULL, &weglStencilClearTagEXT},
{ NULL, NULL, NULL}};
diff --git a/lib/wx/c_src/gen/gl_funcs.cpp b/lib/wx/c_src/gen/gl_funcs.cpp
index 30542a0f02..e1bd920e71 100644
--- a/lib/wx/c_src/gen/gl_funcs.cpp
+++ b/lib/wx/c_src/gen/gl_funcs.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -346,477 +346,157 @@ case 5036: { // gluUnProject4
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5037: { // glAccum
- GLenum *op = (GLenum *) bp; bp += 4;
- GLfloat *value = (GLfloat *) bp; bp += 4;
- weglAccum(*op,*value);
-}; break;
-case 5038: { // glAlphaFunc
- GLenum *func = (GLenum *) bp; bp += 4;
- GLclampf *ref = (GLclampf *) bp; bp += 4;
- weglAlphaFunc(*func,*ref);
-}; break;
-case 5039: { // glAreTexturesResident
- int * texturesLen = (int *) bp; bp += 4;
- GLuint * textures = (GLuint *) bp; bp += (8-((*texturesLen*4+4)%8))%8;
- GLboolean *residences;
- residences = (GLboolean *) driver_alloc(sizeof(GLboolean) * *texturesLen);
- GLboolean result = weglAreTexturesResident(*texturesLen,textures,residences);
- int AP = 0; ErlDrvTermData *rt;
- rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData)*(11 + (*texturesLen)*2));
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
- for(int i=0; i < *texturesLen; i++) {
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) residences[i];}
- rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = (*texturesLen)+1;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
- driver_free(rt);
- driver_free(residences);
-}; break;
-case 5040: { // glArrayElement
- GLint *i = (GLint *) bp; bp += 4;
- weglArrayElement(*i);
-}; break;
-case 5041: { // glBegin
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglBegin(*mode);
-}; break;
-case 5042: { // glBindTexture
- GLenum *target = (GLenum *) bp; bp += 4;
- GLuint *texture = (GLuint *) bp; bp += 4;
- weglBindTexture(*target,*texture);
-}; break;
-case 5043: { // glBitmap
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLfloat *xorig = (GLfloat *) bp; bp += 4;
- GLfloat *yorig = (GLfloat *) bp; bp += 4;
- GLfloat *xmove = (GLfloat *) bp; bp += 4;
- GLfloat *ymove = (GLfloat *) bp; bp += 4;
- GLubyte *bitmap = (GLubyte *) * (int *) bp; bp += 4;
- weglBitmap(*width,*height,*xorig,*yorig,*xmove,*ymove,bitmap);
-}; break;
-case 5044: { // glBitmap
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLfloat *xorig = (GLfloat *) bp; bp += 4;
- GLfloat *yorig = (GLfloat *) bp; bp += 4;
- GLfloat *xmove = (GLfloat *) bp; bp += 4;
- GLfloat *ymove = (GLfloat *) bp; bp += 4;
- GLubyte *bitmap = (GLubyte *) bins[0];
- weglBitmap(*width,*height,*xorig,*yorig,*xmove,*ymove,bitmap);
-}; break;
-case 5045: { // glBlendFunc
- GLenum *sfactor = (GLenum *) bp; bp += 4;
- GLenum *dfactor = (GLenum *) bp; bp += 4;
- weglBlendFunc(*sfactor,*dfactor);
-}; break;
-case 5046: { // glCallList
- GLuint *list = (GLuint *) bp; bp += 4;
- weglCallList(*list);
-}; break;
-case 5047: { // glCallLists
- int * listsLen = (int *) bp; bp += 4;
- GLuint * lists = (GLuint *) bp; bp += (8-((*listsLen*4+4)%8))%8;
- weglCallLists(*listsLen,GL_UNSIGNED_INT,lists);
-}; break;
-case 5048: { // glClear
- GLbitfield *mask = (GLbitfield *) bp; bp += 4;
- weglClear(*mask);
-}; break;
-case 5049: { // glClearAccum
- GLfloat *red = (GLfloat *) bp; bp += 4;
- GLfloat *green = (GLfloat *) bp; bp += 4;
- GLfloat *blue = (GLfloat *) bp; bp += 4;
- GLfloat *alpha = (GLfloat *) bp; bp += 4;
- weglClearAccum(*red,*green,*blue,*alpha);
+case 5037: { // glClearIndex
+ GLfloat *c = (GLfloat *) bp; bp += 4;
+ weglClearIndex(*c);
}; break;
-case 5050: { // glClearColor
+case 5038: { // glClearColor
GLclampf *red = (GLclampf *) bp; bp += 4;
GLclampf *green = (GLclampf *) bp; bp += 4;
GLclampf *blue = (GLclampf *) bp; bp += 4;
GLclampf *alpha = (GLclampf *) bp; bp += 4;
weglClearColor(*red,*green,*blue,*alpha);
}; break;
-case 5051: { // glClearDepth
- GLclampd *depth = (GLclampd *) bp; bp += 8;
- weglClearDepth(*depth);
-}; break;
-case 5052: { // glClearIndex
- GLfloat *c = (GLfloat *) bp; bp += 4;
- weglClearIndex(*c);
-}; break;
-case 5053: { // glClearStencil
- GLint *s = (GLint *) bp; bp += 4;
- weglClearStencil(*s);
-}; break;
-case 5054: { // glClipPlane
- GLenum *plane = (GLenum *) bp; bp += 4;
- bp += 4;
- GLdouble * equation = (GLdouble *) bp; bp += 32;
- weglClipPlane(*plane,equation);
-}; break;
-case 5055: { // glColor3bv
- GLbyte *v = (GLbyte *) bp; bp += 1;
- weglColor3bv(v);
-}; break;
-case 5056: { // glColor3dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglColor3dv(v);
-}; break;
-case 5057: { // glColor3fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglColor3fv(v);
-}; break;
-case 5058: { // glColor3iv
- GLint *v = (GLint *) bp; bp += 4;
- weglColor3iv(v);
-}; break;
-case 5059: { // glColor3sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglColor3sv(v);
-}; break;
-case 5060: { // glColor3ubv
- GLubyte *v = (GLubyte *) bp; bp += 1;
- weglColor3ubv(v);
-}; break;
-case 5061: { // glColor3uiv
- GLuint *v = (GLuint *) bp; bp += 4;
- weglColor3uiv(v);
-}; break;
-case 5062: { // glColor3usv
- GLushort *v = (GLushort *) bp; bp += 2;
- weglColor3usv(v);
-}; break;
-case 5063: { // glColor4bv
- GLbyte *v = (GLbyte *) bp; bp += 1;
- weglColor4bv(v);
-}; break;
-case 5064: { // glColor4dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglColor4dv(v);
-}; break;
-case 5065: { // glColor4fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglColor4fv(v);
-}; break;
-case 5066: { // glColor4iv
- GLint *v = (GLint *) bp; bp += 4;
- weglColor4iv(v);
-}; break;
-case 5067: { // glColor4sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglColor4sv(v);
-}; break;
-case 5068: { // glColor4ubv
- GLubyte *v = (GLubyte *) bp; bp += 1;
- weglColor4ubv(v);
-}; break;
-case 5069: { // glColor4uiv
- GLuint *v = (GLuint *) bp; bp += 4;
- weglColor4uiv(v);
+case 5039: { // glClear
+ GLbitfield *mask = (GLbitfield *) bp; bp += 4;
+ weglClear(*mask);
}; break;
-case 5070: { // glColor4usv
- GLushort *v = (GLushort *) bp; bp += 2;
- weglColor4usv(v);
+case 5040: { // glIndexMask
+ GLuint *mask = (GLuint *) bp; bp += 4;
+ weglIndexMask(*mask);
}; break;
-case 5071: { // glColorMask
+case 5041: { // glColorMask
GLboolean *red = (GLboolean *) bp; bp += 1;
GLboolean *green = (GLboolean *) bp; bp += 1;
GLboolean *blue = (GLboolean *) bp; bp += 1;
GLboolean *alpha = (GLboolean *) bp; bp += 1;
weglColorMask(*red,*green,*blue,*alpha);
}; break;
-case 5072: { // glColorMaterial
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglColorMaterial(*face,*mode);
-}; break;
-case 5073: { // glColorPointer
- GLint *size = (GLint *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglColorPointer(*size,*type,*stride,pointer);
-}; break;
-case 5074: { // glColorPointer
- GLint *size = (GLint *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglColorPointer(*size,*type,*stride,pointer);
-}; break;
-case 5075: { // glCopyPixels
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- weglCopyPixels(*x,*y,*width,*height,*type);
-}; break;
-case 5076: { // glCopyTexImage1D
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLenum *internalFormat = (GLenum *) bp; bp += 4;
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLint *border = (GLint *) bp; bp += 4;
- weglCopyTexImage1D(*target,*level,*internalFormat,*x,*y,*width,*border);
-}; break;
-case 5077: { // glCopyTexImage2D
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLenum *internalFormat = (GLenum *) bp; bp += 4;
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLint *border = (GLint *) bp; bp += 4;
- weglCopyTexImage2D(*target,*level,*internalFormat,*x,*y,*width,*height,*border);
+case 5042: { // glAlphaFunc
+ GLenum *func = (GLenum *) bp; bp += 4;
+ GLclampf *ref = (GLclampf *) bp; bp += 4;
+ weglAlphaFunc(*func,*ref);
}; break;
-case 5078: { // glCopyTexSubImage1D
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLint *xoffset = (GLint *) bp; bp += 4;
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- weglCopyTexSubImage1D(*target,*level,*xoffset,*x,*y,*width);
+case 5043: { // glBlendFunc
+ GLenum *sfactor = (GLenum *) bp; bp += 4;
+ GLenum *dfactor = (GLenum *) bp; bp += 4;
+ weglBlendFunc(*sfactor,*dfactor);
}; break;
-case 5079: { // glCopyTexSubImage2D
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLint *xoffset = (GLint *) bp; bp += 4;
- GLint *yoffset = (GLint *) bp; bp += 4;
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- weglCopyTexSubImage2D(*target,*level,*xoffset,*yoffset,*x,*y,*width,*height);
+case 5044: { // glLogicOp
+ GLenum *opcode = (GLenum *) bp; bp += 4;
+ weglLogicOp(*opcode);
}; break;
-case 5080: { // glCullFace
+case 5045: { // glCullFace
GLenum *mode = (GLenum *) bp; bp += 4;
weglCullFace(*mode);
}; break;
-case 5081: { // glDeleteLists
- GLuint *list = (GLuint *) bp; bp += 4;
- GLsizei *range = (GLsizei *) bp; bp += 4;
- weglDeleteLists(*list,*range);
-}; break;
-case 5082: { // glDeleteTextures
- int * texturesLen = (int *) bp; bp += 4;
- GLuint * textures = (GLuint *) bp; bp += (8-((*texturesLen*4+4)%8))%8;
- weglDeleteTextures(*texturesLen,textures);
-}; break;
-case 5083: { // glDepthFunc
- GLenum *func = (GLenum *) bp; bp += 4;
- weglDepthFunc(*func);
-}; break;
-case 5084: { // glDepthMask
- GLboolean *flag = (GLboolean *) bp; bp += 1;
- weglDepthMask(*flag);
-}; break;
-case 5085: { // glDepthRange
- GLclampd *zNear = (GLclampd *) bp; bp += 8;
- GLclampd *zFar = (GLclampd *) bp; bp += 8;
- weglDepthRange(*zNear,*zFar);
-}; break;
-case 5086: { // glDisable
- GLenum *cap = (GLenum *) bp; bp += 4;
- weglDisable(*cap);
+case 5046: { // glFrontFace
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglFrontFace(*mode);
}; break;
-case 5087: { // glDisableClientState
- GLenum *array = (GLenum *) bp; bp += 4;
- weglDisableClientState(*array);
+case 5047: { // glPointSize
+ GLfloat *size = (GLfloat *) bp; bp += 4;
+ weglPointSize(*size);
}; break;
-case 5088: { // glDrawArrays
- GLenum *mode = (GLenum *) bp; bp += 4;
- GLint *first = (GLint *) bp; bp += 4;
- GLsizei *count = (GLsizei *) bp; bp += 4;
- weglDrawArrays(*mode,*first,*count);
+case 5048: { // glLineWidth
+ GLfloat *width = (GLfloat *) bp; bp += 4;
+ weglLineWidth(*width);
}; break;
-case 5089: { // glDrawBuffer
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglDrawBuffer(*mode);
+case 5049: { // glLineStipple
+ GLint *factor = (GLint *) bp; bp += 4;
+ GLushort *pattern = (GLushort *) bp; bp += 2;
+ weglLineStipple(*factor,*pattern);
}; break;
-case 5090: { // glDrawElements
+case 5050: { // glPolygonMode
+ GLenum *face = (GLenum *) bp; bp += 4;
GLenum *mode = (GLenum *) bp; bp += 4;
- GLsizei *count = (GLsizei *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) * (int *) bp; bp += 4;
- weglDrawElements(*mode,*count,*type,indices);
+ weglPolygonMode(*face,*mode);
}; break;
-case 5091: { // glDrawElements
- GLenum *mode = (GLenum *) bp; bp += 4;
- GLsizei *count = (GLsizei *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) bins[0];
- weglDrawElements(*mode,*count,*type,indices);
+case 5051: { // glPolygonOffset
+ GLfloat *factor = (GLfloat *) bp; bp += 4;
+ GLfloat *units = (GLfloat *) bp; bp += 4;
+ weglPolygonOffset(*factor,*units);
}; break;
-case 5092: { // glDrawPixels
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLenum *format = (GLenum *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
- weglDrawPixels(*width,*height,*format,*type,pixels);
+case 5052: { // glPolygonStipple
+ GLubyte *mask = (GLubyte *) bins[0];
+ weglPolygonStipple(mask);
}; break;
-case 5093: { // glDrawPixels
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLenum *format = (GLenum *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) bins[0];
- weglDrawPixels(*width,*height,*format,*type,pixels);
+case 5053: { // glGetPolygonStipple
+ ErlDrvBinary *mask = driver_alloc_binary(128);
+ weglGetPolygonStipple((GLubyte*) mask->orig_bytes);
+ int AP = 0; ErlDrvTermData rt[8];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) mask; rt[AP++] = 128; rt[AP++] = 0;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+ driver_free_binary(mask);
}; break;
-case 5094: { // glEdgeFlagv
+case 5054: { // glEdgeFlagv
GLboolean *flag = (GLboolean *) bp; bp += 1;
weglEdgeFlagv(flag);
}; break;
-case 5095: { // glEdgeFlagPointer
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglEdgeFlagPointer(*stride,pointer);
-}; break;
-case 5096: { // glEdgeFlagPointer
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglEdgeFlagPointer(*stride,pointer);
-}; break;
-case 5097: { // glEnable
- GLenum *cap = (GLenum *) bp; bp += 4;
- weglEnable(*cap);
-}; break;
-case 5098: { // glEnableClientState
- GLenum *array = (GLenum *) bp; bp += 4;
- weglEnableClientState(*array);
-}; break;
-case 5099: { // glEnd
- weglEnd();
-}; break;
-case 5100: { // glEndList
- weglEndList();
-}; break;
-case 5101: { // glEvalCoord1dv
- GLdouble *u = (GLdouble *) bp; bp += 8;
- weglEvalCoord1dv(u);
-}; break;
-case 5102: { // glEvalCoord1fv
- GLfloat *u = (GLfloat *) bp; bp += 4;
- weglEvalCoord1fv(u);
-}; break;
-case 5103: { // glEvalCoord2dv
- GLdouble *u = (GLdouble *) bp; bp += 8;
- weglEvalCoord2dv(u);
-}; break;
-case 5104: { // glEvalCoord2fv
- GLfloat *u = (GLfloat *) bp; bp += 4;
- weglEvalCoord2fv(u);
-}; break;
-case 5105: { // glEvalMesh1
- GLenum *mode = (GLenum *) bp; bp += 4;
- GLint *i1 = (GLint *) bp; bp += 4;
- GLint *i2 = (GLint *) bp; bp += 4;
- weglEvalMesh1(*mode,*i1,*i2);
-}; break;
-case 5106: { // glEvalMesh2
- GLenum *mode = (GLenum *) bp; bp += 4;
- GLint *i1 = (GLint *) bp; bp += 4;
- GLint *i2 = (GLint *) bp; bp += 4;
- GLint *j1 = (GLint *) bp; bp += 4;
- GLint *j2 = (GLint *) bp; bp += 4;
- weglEvalMesh2(*mode,*i1,*i2,*j1,*j2);
-}; break;
-case 5107: { // glEvalPoint1
- GLint *i = (GLint *) bp; bp += 4;
- weglEvalPoint1(*i);
+case 5055: { // glScissor
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ weglScissor(*x,*y,*width,*height);
}; break;
-case 5108: { // glEvalPoint2
- GLint *i = (GLint *) bp; bp += 4;
- GLint *j = (GLint *) bp; bp += 4;
- weglEvalPoint2(*i,*j);
+case 5056: { // glClipPlane
+ GLenum *plane = (GLenum *) bp; bp += 4;
+ bp += 4;
+ GLdouble * equation = (GLdouble *) bp; bp += 32;
+ weglClipPlane(*plane,equation);
}; break;
-case 5109: { // glFeedbackBuffer
- GLsizei *size = (GLsizei *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLfloat *buffer = (GLfloat *) bins[0];
- weglFeedbackBuffer(*size,*type,buffer);
- int AP = 0; ErlDrvTermData rt[6];
+case 5057: { // glGetClipPlane
+ GLenum *plane = (GLenum *) bp; bp += 4;
+ GLdouble equation[4] = {0.0,0.0,0.0,0.0};
+ weglGetClipPlane(*plane,equation);
+ int AP = 0; ErlDrvTermData rt[14];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ GLdouble *equationTmp = equation;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5110: { // glFinish
- weglFinish();
-}; break;
-case 5111: { // glFlush
- weglFlush();
-}; break;
-case 5112: { // glFogf
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglFogf(*pname,*param);
-}; break;
-case 5113: { // glFogfv
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
- weglFogfv(*pname,params);
-}; break;
-case 5114: { // glFogi
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglFogi(*pname,*param);
-}; break;
-case 5115: { // glFogiv
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
- weglFogiv(*pname,params);
+case 5058: { // glDrawBuffer
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglDrawBuffer(*mode);
}; break;
-case 5116: { // glFrontFace
+case 5059: { // glReadBuffer
GLenum *mode = (GLenum *) bp; bp += 4;
- weglFrontFace(*mode);
+ weglReadBuffer(*mode);
}; break;
-case 5117: { // glFrustum
- GLdouble *left = (GLdouble *) bp; bp += 8;
- GLdouble *right = (GLdouble *) bp; bp += 8;
- GLdouble *bottom = (GLdouble *) bp; bp += 8;
- GLdouble *top = (GLdouble *) bp; bp += 8;
- GLdouble *zNear = (GLdouble *) bp; bp += 8;
- GLdouble *zFar = (GLdouble *) bp; bp += 8;
- weglFrustum(*left,*right,*bottom,*top,*zNear,*zFar);
+case 5060: { // glEnable
+ GLenum *cap = (GLenum *) bp; bp += 4;
+ weglEnable(*cap);
}; break;
-case 5118: { // glGenLists
- GLsizei *range = (GLsizei *) bp; bp += 4;
- GLuint result = weglGenLists(*range);
+case 5061: { // glDisable
+ GLenum *cap = (GLenum *) bp; bp += 4;
+ weglDisable(*cap);
+}; break;
+case 5062: { // glIsEnabled
+ GLenum *cap = (GLenum *) bp; bp += 4;
+ GLboolean result = weglIsEnabled(*cap);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5119: { // glGenTextures
- GLsizei *n = (GLsizei *) bp; bp += 4;
- GLuint *textures;
- textures = (GLuint *) driver_alloc(sizeof(GLuint) * *n);
- weglGenTextures(*n,textures);
- int AP = 0; ErlDrvTermData *rt;
- rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData)*(7 + (*n)*2));
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- for(int i=0; i < *n; i++) {
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) textures[i];}
- rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = (*n)+1;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
- driver_free(rt);
- driver_free(textures);
+case 5063: { // glEnableClientState
+ GLenum *cap = (GLenum *) bp; bp += 4;
+ weglEnableClientState(*cap);
+}; break;
+case 5064: { // glDisableClientState
+ GLenum *cap = (GLenum *) bp; bp += 4;
+ weglDisableClientState(*cap);
}; break;
-case 5120: { // glGetBooleanv
+case 5065: { // glGetBooleanv
GLenum *pname = (GLenum *) bp; bp += 4;
GLboolean params[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
weglGetBooleanv(*pname,params);
@@ -843,22 +523,7 @@ case 5120: { // glGetBooleanv
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5121: { // glGetClipPlane
- GLenum *plane = (GLenum *) bp; bp += 4;
- GLdouble equation[4] = {0.0,0.0,0.0,0.0};
- weglGetClipPlane(*plane,equation);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble *equationTmp = equation;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) equationTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5122: { // glGetDoublev
+case 5066: { // glGetDoublev
GLenum *pname = (GLenum *) bp; bp += 4;
GLdouble params[16] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
weglGetDoublev(*pname,params);
@@ -885,15 +550,7 @@ case 5122: { // glGetDoublev
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5123: { // glGetError
- GLenum result = weglGetError();
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5124: { // glGetFloatv
+case 5067: { // glGetFloatv
GLenum *pname = (GLenum *) bp; bp += 4;
GLfloat params[16] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
weglGetFloatv(*pname,params);
@@ -921,7 +578,7 @@ case 5124: { // glGetFloatv
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5125: { // glGetIntegerv
+case 5068: { // glGetIntegerv
GLenum *pname = (GLenum *) bp; bp += 4;
GLint params[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
weglGetIntegerv(*pname,params);
@@ -948,146 +605,38 @@ case 5125: { // glGetIntegerv
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5126: { // glGetLightfv
- GLenum *light = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat params[4] = {0.0,0.0,0.0,0.0};
- weglGetLightfv(*light,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble paramsConv[4], *paramsTmp = paramsConv;
- for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5127: { // glGetLightiv
- GLenum *light = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint params[4] = {0,0,0,0};
- weglGetLightiv(*light,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLint *paramsTmp = params;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5128: { // glGetMapdv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *query = (GLenum *) bp; bp += 4;
- GLdouble *v = (GLdouble *) bins[0];
- weglGetMapdv(*target,*query,v);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5129: { // glGetMapfv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *query = (GLenum *) bp; bp += 4;
- GLfloat *v = (GLfloat *) bins[0];
- weglGetMapfv(*target,*query,v);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5130: { // glGetMapiv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *query = (GLenum *) bp; bp += 4;
- GLint *v = (GLint *) bins[0];
- weglGetMapiv(*target,*query,v);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5069: { // glPushAttrib
+ GLbitfield *mask = (GLbitfield *) bp; bp += 4;
+ weglPushAttrib(*mask);
}; break;
-case 5131: { // glGetMaterialfv
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat params[4] = {0.0,0.0,0.0,0.0};
- weglGetMaterialfv(*face,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble paramsConv[4], *paramsTmp = paramsConv;
- for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5070: { // glPopAttrib
+ weglPopAttrib();
}; break;
-case 5132: { // glGetMaterialiv
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint params[4] = {0,0,0,0};
- weglGetMaterialiv(*face,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLint *paramsTmp = params;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5071: { // glPushClientAttrib
+ GLbitfield *mask = (GLbitfield *) bp; bp += 4;
+ weglPushClientAttrib(*mask);
}; break;
-case 5133: { // glGetPixelMapfv
- GLenum *map = (GLenum *) bp; bp += 4;
- GLfloat *values = (GLfloat *) bins[0];
- weglGetPixelMapfv(*map,values);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5072: { // glPopClientAttrib
+ weglPopClientAttrib();
}; break;
-case 5134: { // glGetPixelMapuiv
- GLenum *map = (GLenum *) bp; bp += 4;
- GLuint *values = (GLuint *) bins[0];
- weglGetPixelMapuiv(*map,values);
+case 5073: { // glRenderMode
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLint result = weglRenderMode(*mode);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5135: { // glGetPixelMapusv
- GLenum *map = (GLenum *) bp; bp += 4;
- GLushort *values = (GLushort *) bins[0];
- weglGetPixelMapusv(*map,values);
+case 5074: { // glGetError
+ GLenum result = weglGetError();
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5136: { // glGetPolygonStipple
- ErlDrvBinary *mask = driver_alloc_binary(128);
- weglGetPolygonStipple((GLubyte*) mask->orig_bytes);
- int AP = 0; ErlDrvTermData rt[8];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) mask; rt[AP++] = 128; rt[AP++] = 0;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
- driver_free_binary(mask);
-}; break;
-case 5137: { // glGetString
+case 5075: { // glGetString
GLenum *name = (GLenum *) bp; bp += 4;
const GLubyte * result = weglGetString(*name);
int AP = 0; ErlDrvTermData rt[7];
@@ -1096,229 +645,139 @@ case 5137: { // glGetString
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5138: { // glGetTexEnvfv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat params[4] = {0.0,0.0,0.0,0.0};
- weglGetTexEnvfv(*target,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble paramsConv[4], *paramsTmp = paramsConv;
- for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5076: { // glFinish
+ weglFinish();
}; break;
-case 5139: { // glGetTexEnviv
+case 5077: { // glFlush
+ weglFlush();
+}; break;
+case 5078: { // glHint
GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint params[4] = {0,0,0,0};
- weglGetTexEnviv(*target,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLint *paramsTmp = params;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglHint(*target,*mode);
}; break;
-case 5140: { // glGetTexGendv
- GLenum *coord = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLdouble params[4] = {0.0,0.0,0.0,0.0};
- weglGetTexGendv(*coord,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble *paramsTmp = params;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5079: { // glClearDepth
+ GLclampd *depth = (GLclampd *) bp; bp += 8;
+ weglClearDepth(*depth);
}; break;
-case 5141: { // glGetTexGenfv
- GLenum *coord = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat params[4] = {0.0,0.0,0.0,0.0};
- weglGetTexGenfv(*coord,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble paramsConv[4], *paramsTmp = paramsConv;
- for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5080: { // glDepthFunc
+ GLenum *func = (GLenum *) bp; bp += 4;
+ weglDepthFunc(*func);
}; break;
-case 5142: { // glGetTexGeniv
- GLenum *coord = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint params[4] = {0,0,0,0};
- weglGetTexGeniv(*coord,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLint *paramsTmp = params;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5081: { // glDepthMask
+ GLboolean *flag = (GLboolean *) bp; bp += 1;
+ weglDepthMask(*flag);
}; break;
-case 5143: { // glGetTexImage
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLenum *format = (GLenum *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) bins[0];
- weglGetTexImage(*target,*level,*format,*type,pixels);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5082: { // glDepthRange
+ GLclampd *near_val = (GLclampd *) bp; bp += 8;
+ GLclampd *far_val = (GLclampd *) bp; bp += 8;
+ weglDepthRange(*near_val,*far_val);
}; break;
-case 5144: { // glGetTexLevelParameterfv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat params[1] = {0.0};
- weglGetTexLevelParameterfv(*target,*level,*pname,params);
- int AP = 0; ErlDrvTermData rt[8];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble paramsConv[1], *paramsTmp = paramsConv;
- for(int i=0; i < 1; i++) paramsConv[i] = (GLdouble) params[i];
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 1;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5083: { // glClearAccum
+ GLfloat *red = (GLfloat *) bp; bp += 4;
+ GLfloat *green = (GLfloat *) bp; bp += 4;
+ GLfloat *blue = (GLfloat *) bp; bp += 4;
+ GLfloat *alpha = (GLfloat *) bp; bp += 4;
+ weglClearAccum(*red,*green,*blue,*alpha);
}; break;
-case 5145: { // glGetTexLevelParameteriv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint params[1] = {0};
- weglGetTexLevelParameteriv(*target,*level,*pname,params);
- int AP = 0; ErlDrvTermData rt[8];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLint *paramsTmp = params;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 1;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5084: { // glAccum
+ GLenum *op = (GLenum *) bp; bp += 4;
+ GLfloat *value = (GLfloat *) bp; bp += 4;
+ weglAccum(*op,*value);
}; break;
-case 5146: { // glGetTexParameterfv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat params[4] = {0.0,0.0,0.0,0.0};
- weglGetTexParameterfv(*target,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLdouble paramsConv[4], *paramsTmp = paramsConv;
- for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5085: { // glMatrixMode
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglMatrixMode(*mode);
}; break;
-case 5147: { // glGetTexParameteriv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint params[4] = {0,0,0,0};
- weglGetTexParameteriv(*target,*pname,params);
- int AP = 0; ErlDrvTermData rt[14];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- GLint *paramsTmp = params;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5086: { // glOrtho
+ GLdouble *left = (GLdouble *) bp; bp += 8;
+ GLdouble *right = (GLdouble *) bp; bp += 8;
+ GLdouble *bottom = (GLdouble *) bp; bp += 8;
+ GLdouble *top = (GLdouble *) bp; bp += 8;
+ GLdouble *near_val = (GLdouble *) bp; bp += 8;
+ GLdouble *far_val = (GLdouble *) bp; bp += 8;
+ weglOrtho(*left,*right,*bottom,*top,*near_val,*far_val);
}; break;
-case 5148: { // glHint
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglHint(*target,*mode);
+case 5087: { // glFrustum
+ GLdouble *left = (GLdouble *) bp; bp += 8;
+ GLdouble *right = (GLdouble *) bp; bp += 8;
+ GLdouble *bottom = (GLdouble *) bp; bp += 8;
+ GLdouble *top = (GLdouble *) bp; bp += 8;
+ GLdouble *near_val = (GLdouble *) bp; bp += 8;
+ GLdouble *far_val = (GLdouble *) bp; bp += 8;
+ weglFrustum(*left,*right,*bottom,*top,*near_val,*far_val);
}; break;
-case 5149: { // glIndexMask
- GLuint *mask = (GLuint *) bp; bp += 4;
- weglIndexMask(*mask);
+case 5088: { // glViewport
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ weglViewport(*x,*y,*width,*height);
}; break;
-case 5150: { // glIndexPointer
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglIndexPointer(*type,*stride,pointer);
+case 5089: { // glPushMatrix
+ weglPushMatrix();
}; break;
-case 5151: { // glIndexPointer
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglIndexPointer(*type,*stride,pointer);
+case 5090: { // glPopMatrix
+ weglPopMatrix();
}; break;
-case 5152: { // glIndexdv
- GLdouble *c = (GLdouble *) bp; bp += 8;
- weglIndexdv(c);
+case 5091: { // glLoadIdentity
+ weglLoadIdentity();
}; break;
-case 5153: { // glIndexfv
- GLfloat *c = (GLfloat *) bp; bp += 4;
- weglIndexfv(c);
+case 5092: { // glLoadMatrixd
+ GLdouble * m = (GLdouble *) bp; bp += 128;
+ weglLoadMatrixd(m);
}; break;
-case 5154: { // glIndexiv
- GLint *c = (GLint *) bp; bp += 4;
- weglIndexiv(c);
+case 5093: { // glLoadMatrixf
+ GLfloat * m = (GLfloat *) bp; bp += 64;
+ weglLoadMatrixf(m);
}; break;
-case 5155: { // glIndexsv
- GLshort *c = (GLshort *) bp; bp += 2;
- weglIndexsv(c);
+case 5094: { // glMultMatrixd
+ GLdouble * m = (GLdouble *) bp; bp += 128;
+ weglMultMatrixd(m);
}; break;
-case 5156: { // glIndexubv
- GLubyte *c = (GLubyte *) bp; bp += 1;
- weglIndexubv(c);
+case 5095: { // glMultMatrixf
+ GLfloat * m = (GLfloat *) bp; bp += 64;
+ weglMultMatrixf(m);
}; break;
-case 5157: { // glInitNames
- weglInitNames();
+case 5096: { // glRotated
+ GLdouble *angle = (GLdouble *) bp; bp += 8;
+ GLdouble *x = (GLdouble *) bp; bp += 8;
+ GLdouble *y = (GLdouble *) bp; bp += 8;
+ GLdouble *z = (GLdouble *) bp; bp += 8;
+ weglRotated(*angle,*x,*y,*z);
}; break;
-case 5158: { // glInterleavedArrays
- GLenum *format = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglInterleavedArrays(*format,*stride,pointer);
+case 5097: { // glRotatef
+ GLfloat *angle = (GLfloat *) bp; bp += 4;
+ GLfloat *x = (GLfloat *) bp; bp += 4;
+ GLfloat *y = (GLfloat *) bp; bp += 4;
+ GLfloat *z = (GLfloat *) bp; bp += 4;
+ weglRotatef(*angle,*x,*y,*z);
}; break;
-case 5159: { // glInterleavedArrays
- GLenum *format = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglInterleavedArrays(*format,*stride,pointer);
+case 5098: { // glScaled
+ GLdouble *x = (GLdouble *) bp; bp += 8;
+ GLdouble *y = (GLdouble *) bp; bp += 8;
+ GLdouble *z = (GLdouble *) bp; bp += 8;
+ weglScaled(*x,*y,*z);
}; break;
-case 5160: { // glIsEnabled
- GLenum *cap = (GLenum *) bp; bp += 4;
- GLboolean result = weglIsEnabled(*cap);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
+case 5099: { // glScalef
+ GLfloat *x = (GLfloat *) bp; bp += 4;
+ GLfloat *y = (GLfloat *) bp; bp += 4;
+ GLfloat *z = (GLfloat *) bp; bp += 4;
+ weglScalef(*x,*y,*z);
}; break;
-case 5161: { // glIsList
+case 5100: { // glTranslated
+ GLdouble *x = (GLdouble *) bp; bp += 8;
+ GLdouble *y = (GLdouble *) bp; bp += 8;
+ GLdouble *z = (GLdouble *) bp; bp += 8;
+ weglTranslated(*x,*y,*z);
+}; break;
+case 5101: { // glTranslatef
+ GLfloat *x = (GLfloat *) bp; bp += 4;
+ GLfloat *y = (GLfloat *) bp; bp += 4;
+ GLfloat *z = (GLfloat *) bp; bp += 4;
+ weglTranslatef(*x,*y,*z);
+}; break;
+case 5102: { // glIsList
GLuint *list = (GLuint *) bp; bp += 4;
GLboolean result = weglIsList(*list);
int AP = 0; ErlDrvTermData rt[6];
@@ -1327,770 +786,1139 @@ case 5161: { // glIsList
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5162: { // glIsTexture
- GLuint *texture = (GLuint *) bp; bp += 4;
- GLboolean result = weglIsTexture(*texture);
+case 5103: { // glDeleteLists
+ GLuint *list = (GLuint *) bp; bp += 4;
+ GLsizei *range = (GLsizei *) bp; bp += 4;
+ weglDeleteLists(*list,*range);
+}; break;
+case 5104: { // glGenLists
+ GLsizei *range = (GLsizei *) bp; bp += 4;
+ GLuint result = weglGenLists(*range);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5163: { // glLightModelf
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglLightModelf(*pname,*param);
-}; break;
-case 5164: { // glLightModelfv
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
- weglLightModelfv(*pname,params);
-}; break;
-case 5165: { // glLightModeli
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglLightModeli(*pname,*param);
-}; break;
-case 5166: { // glLightModeliv
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
- weglLightModeliv(*pname,params);
+case 5105: { // glNewList
+ GLuint *list = (GLuint *) bp; bp += 4;
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglNewList(*list,*mode);
}; break;
-case 5167: { // glLightf
- GLenum *light = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglLightf(*light,*pname,*param);
+case 5106: { // glEndList
+ weglEndList();
}; break;
-case 5168: { // glLightfv
- GLenum *light = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglLightfv(*light,*pname,params);
+case 5107: { // glCallList
+ GLuint *list = (GLuint *) bp; bp += 4;
+ weglCallList(*list);
}; break;
-case 5169: { // glLighti
- GLenum *light = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglLighti(*light,*pname,*param);
+case 5108: { // glCallLists
+ int * listsLen = (int *) bp; bp += 4;
+ GLuint * lists = (GLuint *) bp; bp += (8-((*listsLen*4+4)%8))%8;
+ weglCallLists(*listsLen,GL_UNSIGNED_INT,lists);
}; break;
-case 5170: { // glLightiv
- GLenum *light = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglLightiv(*light,*pname,params);
+case 5109: { // glListBase
+ GLuint *base = (GLuint *) bp; bp += 4;
+ weglListBase(*base);
}; break;
-case 5171: { // glLineStipple
- GLint *factor = (GLint *) bp; bp += 4;
- GLushort *pattern = (GLushort *) bp; bp += 2;
- weglLineStipple(*factor,*pattern);
+case 5110: { // glBegin
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglBegin(*mode);
}; break;
-case 5172: { // glLineWidth
- GLfloat *width = (GLfloat *) bp; bp += 4;
- weglLineWidth(*width);
+case 5111: { // glEnd
+ weglEnd();
}; break;
-case 5173: { // glListBase
- GLuint *base = (GLuint *) bp; bp += 4;
- weglListBase(*base);
+case 5112: { // glVertex2dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglVertex2dv(v);
}; break;
-case 5174: { // glLoadIdentity
- weglLoadIdentity();
+case 5113: { // glVertex2fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglVertex2fv(v);
}; break;
-case 5175: { // glLoadMatrixd
- GLdouble * m = (GLdouble *) bp; bp += 128;
- weglLoadMatrixd(m);
+case 5114: { // glVertex2iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglVertex2iv(v);
}; break;
-case 5176: { // glLoadMatrixf
- GLfloat * m = (GLfloat *) bp; bp += 64;
- weglLoadMatrixf(m);
+case 5115: { // glVertex2sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglVertex2sv(v);
}; break;
-case 5177: { // glLoadName
- GLuint *name = (GLuint *) bp; bp += 4;
- weglLoadName(*name);
+case 5116: { // glVertex3dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglVertex3dv(v);
}; break;
-case 5178: { // glLogicOp
- GLenum *opcode = (GLenum *) bp; bp += 4;
- weglLogicOp(*opcode);
+case 5117: { // glVertex3fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglVertex3fv(v);
}; break;
-case 5179: { // glMap1d
- GLenum *target = (GLenum *) bp; bp += 4;
- bp += 4;
- GLdouble *u1 = (GLdouble *) bp; bp += 8;
- GLdouble *u2 = (GLdouble *) bp; bp += 8;
- GLint *stride = (GLint *) bp; bp += 4;
- GLint *order = (GLint *) bp; bp += 4;
- GLdouble *points = (GLdouble *) bins[0];
- weglMap1d(*target,*u1,*u2,*stride,*order,points);
+case 5118: { // glVertex3iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglVertex3iv(v);
}; break;
-case 5180: { // glMap1f
- GLenum *target = (GLenum *) bp; bp += 4;
- GLfloat *u1 = (GLfloat *) bp; bp += 4;
- GLfloat *u2 = (GLfloat *) bp; bp += 4;
- GLint *stride = (GLint *) bp; bp += 4;
- GLint *order = (GLint *) bp; bp += 4;
- GLfloat *points = (GLfloat *) bins[0];
- weglMap1f(*target,*u1,*u2,*stride,*order,points);
+case 5119: { // glVertex3sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglVertex3sv(v);
}; break;
-case 5181: { // glMap2d
- GLenum *target = (GLenum *) bp; bp += 4;
- bp += 4;
- GLdouble *u1 = (GLdouble *) bp; bp += 8;
- GLdouble *u2 = (GLdouble *) bp; bp += 8;
- GLint *ustride = (GLint *) bp; bp += 4;
- GLint *uorder = (GLint *) bp; bp += 4;
- GLdouble *v1 = (GLdouble *) bp; bp += 8;
- GLdouble *v2 = (GLdouble *) bp; bp += 8;
- GLint *vstride = (GLint *) bp; bp += 4;
- GLint *vorder = (GLint *) bp; bp += 4;
- GLdouble *points = (GLdouble *) bins[0];
- weglMap2d(*target,*u1,*u2,*ustride,*uorder,*v1,*v2,*vstride,*vorder,points);
+case 5120: { // glVertex4dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglVertex4dv(v);
}; break;
-case 5182: { // glMap2f
- GLenum *target = (GLenum *) bp; bp += 4;
- GLfloat *u1 = (GLfloat *) bp; bp += 4;
- GLfloat *u2 = (GLfloat *) bp; bp += 4;
- GLint *ustride = (GLint *) bp; bp += 4;
- GLint *uorder = (GLint *) bp; bp += 4;
- GLfloat *v1 = (GLfloat *) bp; bp += 4;
- GLfloat *v2 = (GLfloat *) bp; bp += 4;
- GLint *vstride = (GLint *) bp; bp += 4;
- GLint *vorder = (GLint *) bp; bp += 4;
- GLfloat *points = (GLfloat *) bins[0];
- weglMap2f(*target,*u1,*u2,*ustride,*uorder,*v1,*v2,*vstride,*vorder,points);
+case 5121: { // glVertex4fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglVertex4fv(v);
}; break;
-case 5183: { // glMapGrid1d
- GLint *un = (GLint *) bp; bp += 4;
- bp += 4;
- GLdouble *u1 = (GLdouble *) bp; bp += 8;
- GLdouble *u2 = (GLdouble *) bp; bp += 8;
- weglMapGrid1d(*un,*u1,*u2);
+case 5122: { // glVertex4iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglVertex4iv(v);
}; break;
-case 5184: { // glMapGrid1f
- GLint *un = (GLint *) bp; bp += 4;
- GLfloat *u1 = (GLfloat *) bp; bp += 4;
- GLfloat *u2 = (GLfloat *) bp; bp += 4;
- weglMapGrid1f(*un,*u1,*u2);
+case 5123: { // glVertex4sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglVertex4sv(v);
}; break;
-case 5185: { // glMapGrid2d
- GLint *un = (GLint *) bp; bp += 4;
- bp += 4;
- GLdouble *u1 = (GLdouble *) bp; bp += 8;
- GLdouble *u2 = (GLdouble *) bp; bp += 8;
- GLint *vn = (GLint *) bp; bp += 4;
- bp += 4;
- GLdouble *v1 = (GLdouble *) bp; bp += 8;
- GLdouble *v2 = (GLdouble *) bp; bp += 8;
- weglMapGrid2d(*un,*u1,*u2,*vn,*v1,*v2);
+case 5124: { // glNormal3bv
+ GLbyte *v = (GLbyte *) bp; bp += 1;
+ weglNormal3bv(v);
}; break;
-case 5186: { // glMapGrid2f
- GLint *un = (GLint *) bp; bp += 4;
- GLfloat *u1 = (GLfloat *) bp; bp += 4;
- GLfloat *u2 = (GLfloat *) bp; bp += 4;
- GLint *vn = (GLint *) bp; bp += 4;
- GLfloat *v1 = (GLfloat *) bp; bp += 4;
- GLfloat *v2 = (GLfloat *) bp; bp += 4;
- weglMapGrid2f(*un,*u1,*u2,*vn,*v1,*v2);
+case 5125: { // glNormal3dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglNormal3dv(v);
}; break;
-case 5187: { // glMaterialf
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglMaterialf(*face,*pname,*param);
+case 5126: { // glNormal3fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglNormal3fv(v);
}; break;
-case 5188: { // glMaterialfv
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglMaterialfv(*face,*pname,params);
+case 5127: { // glNormal3iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglNormal3iv(v);
}; break;
-case 5189: { // glMateriali
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglMateriali(*face,*pname,*param);
+case 5128: { // glNormal3sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglNormal3sv(v);
}; break;
-case 5190: { // glMaterialiv
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglMaterialiv(*face,*pname,params);
+case 5129: { // glIndexdv
+ GLdouble *c = (GLdouble *) bp; bp += 8;
+ weglIndexdv(c);
}; break;
-case 5191: { // glMatrixMode
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglMatrixMode(*mode);
+case 5130: { // glIndexfv
+ GLfloat *c = (GLfloat *) bp; bp += 4;
+ weglIndexfv(c);
}; break;
-case 5192: { // glMultMatrixd
- GLdouble * m = (GLdouble *) bp; bp += 128;
- weglMultMatrixd(m);
+case 5131: { // glIndexiv
+ GLint *c = (GLint *) bp; bp += 4;
+ weglIndexiv(c);
}; break;
-case 5193: { // glMultMatrixf
- GLfloat * m = (GLfloat *) bp; bp += 64;
- weglMultMatrixf(m);
+case 5132: { // glIndexsv
+ GLshort *c = (GLshort *) bp; bp += 2;
+ weglIndexsv(c);
}; break;
-case 5194: { // glNewList
- GLuint *list = (GLuint *) bp; bp += 4;
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglNewList(*list,*mode);
+case 5133: { // glIndexubv
+ GLubyte *c = (GLubyte *) bp; bp += 1;
+ weglIndexubv(c);
}; break;
-case 5195: { // glNormal3bv
+case 5134: { // glColor3bv
GLbyte *v = (GLbyte *) bp; bp += 1;
- weglNormal3bv(v);
+ weglColor3bv(v);
}; break;
-case 5196: { // glNormal3dv
+case 5135: { // glColor3dv
GLdouble *v = (GLdouble *) bp; bp += 8;
- weglNormal3dv(v);
+ weglColor3dv(v);
}; break;
-case 5197: { // glNormal3fv
+case 5136: { // glColor3fv
GLfloat *v = (GLfloat *) bp; bp += 4;
- weglNormal3fv(v);
+ weglColor3fv(v);
}; break;
-case 5198: { // glNormal3iv
+case 5137: { // glColor3iv
GLint *v = (GLint *) bp; bp += 4;
- weglNormal3iv(v);
+ weglColor3iv(v);
}; break;
-case 5199: { // glNormal3sv
+case 5138: { // glColor3sv
GLshort *v = (GLshort *) bp; bp += 2;
- weglNormal3sv(v);
+ weglColor3sv(v);
}; break;
-case 5200: { // glNormalPointer
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglNormalPointer(*type,*stride,pointer);
+case 5139: { // glColor3ubv
+ GLubyte *v = (GLubyte *) bp; bp += 1;
+ weglColor3ubv(v);
}; break;
-case 5201: { // glNormalPointer
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglNormalPointer(*type,*stride,pointer);
+case 5140: { // glColor3uiv
+ GLuint *v = (GLuint *) bp; bp += 4;
+ weglColor3uiv(v);
}; break;
-case 5202: { // glOrtho
- GLdouble *left = (GLdouble *) bp; bp += 8;
- GLdouble *right = (GLdouble *) bp; bp += 8;
- GLdouble *bottom = (GLdouble *) bp; bp += 8;
- GLdouble *top = (GLdouble *) bp; bp += 8;
- GLdouble *zNear = (GLdouble *) bp; bp += 8;
- GLdouble *zFar = (GLdouble *) bp; bp += 8;
- weglOrtho(*left,*right,*bottom,*top,*zNear,*zFar);
+case 5141: { // glColor3usv
+ GLushort *v = (GLushort *) bp; bp += 2;
+ weglColor3usv(v);
}; break;
-case 5203: { // glPassThrough
- GLfloat *token = (GLfloat *) bp; bp += 4;
- weglPassThrough(*token);
+case 5142: { // glColor4bv
+ GLbyte *v = (GLbyte *) bp; bp += 1;
+ weglColor4bv(v);
}; break;
-case 5204: { // glPixelMapfv
- GLenum *map = (GLenum *) bp; bp += 4;
- GLsizei *mapsize = (GLsizei *) bp; bp += 4;
- GLfloat *values = (GLfloat *) bins[0];
- weglPixelMapfv(*map,*mapsize,values);
+case 5143: { // glColor4dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglColor4dv(v);
}; break;
-case 5205: { // glPixelMapuiv
- GLenum *map = (GLenum *) bp; bp += 4;
- GLsizei *mapsize = (GLsizei *) bp; bp += 4;
- GLuint *values = (GLuint *) bins[0];
- weglPixelMapuiv(*map,*mapsize,values);
+case 5144: { // glColor4fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglColor4fv(v);
}; break;
-case 5206: { // glPixelMapusv
- GLenum *map = (GLenum *) bp; bp += 4;
- GLsizei *mapsize = (GLsizei *) bp; bp += 4;
- GLushort *values = (GLushort *) bins[0];
- weglPixelMapusv(*map,*mapsize,values);
+case 5145: { // glColor4iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglColor4iv(v);
}; break;
-case 5207: { // glPixelStoref
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglPixelStoref(*pname,*param);
+case 5146: { // glColor4sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglColor4sv(v);
}; break;
-case 5208: { // glPixelStorei
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglPixelStorei(*pname,*param);
+case 5147: { // glColor4ubv
+ GLubyte *v = (GLubyte *) bp; bp += 1;
+ weglColor4ubv(v);
}; break;
-case 5209: { // glPixelTransferf
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglPixelTransferf(*pname,*param);
+case 5148: { // glColor4uiv
+ GLuint *v = (GLuint *) bp; bp += 4;
+ weglColor4uiv(v);
}; break;
-case 5210: { // glPixelTransferi
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglPixelTransferi(*pname,*param);
+case 5149: { // glColor4usv
+ GLushort *v = (GLushort *) bp; bp += 2;
+ weglColor4usv(v);
}; break;
-case 5211: { // glPixelZoom
- GLfloat *xfactor = (GLfloat *) bp; bp += 4;
- GLfloat *yfactor = (GLfloat *) bp; bp += 4;
- weglPixelZoom(*xfactor,*yfactor);
+case 5150: { // glTexCoord1dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglTexCoord1dv(v);
}; break;
-case 5212: { // glPointSize
- GLfloat *size = (GLfloat *) bp; bp += 4;
- weglPointSize(*size);
+case 5151: { // glTexCoord1fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglTexCoord1fv(v);
}; break;
-case 5213: { // glPolygonMode
- GLenum *face = (GLenum *) bp; bp += 4;
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglPolygonMode(*face,*mode);
+case 5152: { // glTexCoord1iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglTexCoord1iv(v);
}; break;
-case 5214: { // glPolygonOffset
- GLfloat *factor = (GLfloat *) bp; bp += 4;
- GLfloat *units = (GLfloat *) bp; bp += 4;
- weglPolygonOffset(*factor,*units);
+case 5153: { // glTexCoord1sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglTexCoord1sv(v);
}; break;
-case 5215: { // glPolygonStipple
- GLubyte *mask = (GLubyte *) bins[0];
- weglPolygonStipple(mask);
+case 5154: { // glTexCoord2dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglTexCoord2dv(v);
}; break;
-case 5216: { // glPopAttrib
- weglPopAttrib();
+case 5155: { // glTexCoord2fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglTexCoord2fv(v);
}; break;
-case 5217: { // glPopClientAttrib
- weglPopClientAttrib();
+case 5156: { // glTexCoord2iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglTexCoord2iv(v);
}; break;
-case 5218: { // glPopMatrix
- weglPopMatrix();
+case 5157: { // glTexCoord2sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglTexCoord2sv(v);
}; break;
-case 5219: { // glPopName
- weglPopName();
+case 5158: { // glTexCoord3dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglTexCoord3dv(v);
}; break;
-case 5220: { // glPrioritizeTextures
- int * texturesLen = (int *) bp; bp += 4;
- GLuint * textures = (GLuint *) bp; bp += (8-((*texturesLen*4+4)%8))%8;
- int * prioritiesLen = (int *) bp; bp += 4;
- GLclampf * priorities = (GLclampf *) bp; bp += (8-((*prioritiesLen*4+4)%8))%8;
- weglPrioritizeTextures(*texturesLen,textures,priorities);
+case 5159: { // glTexCoord3fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglTexCoord3fv(v);
}; break;
-case 5221: { // glPushAttrib
- GLbitfield *mask = (GLbitfield *) bp; bp += 4;
- weglPushAttrib(*mask);
+case 5160: { // glTexCoord3iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglTexCoord3iv(v);
}; break;
-case 5222: { // glPushClientAttrib
- GLbitfield *mask = (GLbitfield *) bp; bp += 4;
- weglPushClientAttrib(*mask);
+case 5161: { // glTexCoord3sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglTexCoord3sv(v);
}; break;
-case 5223: { // glPushMatrix
- weglPushMatrix();
+case 5162: { // glTexCoord4dv
+ GLdouble *v = (GLdouble *) bp; bp += 8;
+ weglTexCoord4dv(v);
}; break;
-case 5224: { // glPushName
- GLuint *name = (GLuint *) bp; bp += 4;
- weglPushName(*name);
+case 5163: { // glTexCoord4fv
+ GLfloat *v = (GLfloat *) bp; bp += 4;
+ weglTexCoord4fv(v);
+}; break;
+case 5164: { // glTexCoord4iv
+ GLint *v = (GLint *) bp; bp += 4;
+ weglTexCoord4iv(v);
}; break;
-case 5225: { // glRasterPos2dv
+case 5165: { // glTexCoord4sv
+ GLshort *v = (GLshort *) bp; bp += 2;
+ weglTexCoord4sv(v);
+}; break;
+case 5166: { // glRasterPos2dv
GLdouble *v = (GLdouble *) bp; bp += 8;
weglRasterPos2dv(v);
}; break;
-case 5226: { // glRasterPos2fv
+case 5167: { // glRasterPos2fv
GLfloat *v = (GLfloat *) bp; bp += 4;
weglRasterPos2fv(v);
}; break;
-case 5227: { // glRasterPos2iv
+case 5168: { // glRasterPos2iv
GLint *v = (GLint *) bp; bp += 4;
weglRasterPos2iv(v);
}; break;
-case 5228: { // glRasterPos2sv
+case 5169: { // glRasterPos2sv
GLshort *v = (GLshort *) bp; bp += 2;
weglRasterPos2sv(v);
}; break;
-case 5229: { // glRasterPos3dv
+case 5170: { // glRasterPos3dv
GLdouble *v = (GLdouble *) bp; bp += 8;
weglRasterPos3dv(v);
}; break;
-case 5230: { // glRasterPos3fv
+case 5171: { // glRasterPos3fv
GLfloat *v = (GLfloat *) bp; bp += 4;
weglRasterPos3fv(v);
}; break;
-case 5231: { // glRasterPos3iv
+case 5172: { // glRasterPos3iv
GLint *v = (GLint *) bp; bp += 4;
weglRasterPos3iv(v);
}; break;
-case 5232: { // glRasterPos3sv
+case 5173: { // glRasterPos3sv
GLshort *v = (GLshort *) bp; bp += 2;
weglRasterPos3sv(v);
}; break;
-case 5233: { // glRasterPos4dv
+case 5174: { // glRasterPos4dv
GLdouble *v = (GLdouble *) bp; bp += 8;
weglRasterPos4dv(v);
}; break;
-case 5234: { // glRasterPos4fv
+case 5175: { // glRasterPos4fv
GLfloat *v = (GLfloat *) bp; bp += 4;
weglRasterPos4fv(v);
}; break;
-case 5235: { // glRasterPos4iv
+case 5176: { // glRasterPos4iv
GLint *v = (GLint *) bp; bp += 4;
weglRasterPos4iv(v);
}; break;
-case 5236: { // glRasterPos4sv
+case 5177: { // glRasterPos4sv
GLshort *v = (GLshort *) bp; bp += 2;
weglRasterPos4sv(v);
}; break;
-case 5237: { // glReadBuffer
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglReadBuffer(*mode);
-}; break;
-case 5238: { // glReadPixels
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- GLenum *format = (GLenum *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) bins[0];
- weglReadPixels(*x,*y,*width,*height,*format,*type,pixels);
- int AP = 0; ErlDrvTermData rt[6];
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
- rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
- driver_send_term(port,caller,rt,AP);
-}; break;
-case 5239: { // glRectd
+case 5178: { // glRectd
GLdouble *x1 = (GLdouble *) bp; bp += 8;
GLdouble *y1 = (GLdouble *) bp; bp += 8;
GLdouble *x2 = (GLdouble *) bp; bp += 8;
GLdouble *y2 = (GLdouble *) bp; bp += 8;
weglRectd(*x1,*y1,*x2,*y2);
}; break;
-case 5240: { // glRectdv
- GLdouble * v1 = (GLdouble *) bp; bp += 16;
- GLdouble * v2 = (GLdouble *) bp; bp += 16;
- weglRectdv(v1,v2);
-}; break;
-case 5241: { // glRectf
+case 5179: { // glRectf
GLfloat *x1 = (GLfloat *) bp; bp += 4;
GLfloat *y1 = (GLfloat *) bp; bp += 4;
GLfloat *x2 = (GLfloat *) bp; bp += 4;
GLfloat *y2 = (GLfloat *) bp; bp += 4;
weglRectf(*x1,*y1,*x2,*y2);
}; break;
-case 5242: { // glRectfv
- GLfloat * v1 = (GLfloat *) bp; bp += 8;
- GLfloat * v2 = (GLfloat *) bp; bp += 8;
- weglRectfv(v1,v2);
-}; break;
-case 5243: { // glRecti
+case 5180: { // glRecti
GLint *x1 = (GLint *) bp; bp += 4;
GLint *y1 = (GLint *) bp; bp += 4;
GLint *x2 = (GLint *) bp; bp += 4;
GLint *y2 = (GLint *) bp; bp += 4;
weglRecti(*x1,*y1,*x2,*y2);
}; break;
-case 5244: { // glRectiv
- GLint * v1 = (GLint *) bp; bp += 8;
- GLint * v2 = (GLint *) bp; bp += 8;
- weglRectiv(v1,v2);
-}; break;
-case 5245: { // glRects
+case 5181: { // glRects
GLshort *x1 = (GLshort *) bp; bp += 2;
GLshort *y1 = (GLshort *) bp; bp += 2;
GLshort *x2 = (GLshort *) bp; bp += 2;
GLshort *y2 = (GLshort *) bp; bp += 2;
weglRects(*x1,*y1,*x2,*y2);
}; break;
-case 5246: { // glRectsv
+case 5182: { // glRectdv
+ GLdouble * v1 = (GLdouble *) bp; bp += 16;
+ GLdouble * v2 = (GLdouble *) bp; bp += 16;
+ weglRectdv(v1,v2);
+}; break;
+case 5183: { // glRectfv
+ GLfloat * v1 = (GLfloat *) bp; bp += 8;
+ GLfloat * v2 = (GLfloat *) bp; bp += 8;
+ weglRectfv(v1,v2);
+}; break;
+case 5184: { // glRectiv
+ GLint * v1 = (GLint *) bp; bp += 8;
+ GLint * v2 = (GLint *) bp; bp += 8;
+ weglRectiv(v1,v2);
+}; break;
+case 5185: { // glRectsv
GLshort * v1 = (GLshort *) bp; bp += 4;
GLshort * v2 = (GLshort *) bp; bp += 4;
weglRectsv(v1,v2);
}; break;
-case 5247: { // glRenderMode
+case 5186: { // glVertexPointer
+ GLint *size = (GLint *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglVertexPointer(*size,*type,*stride,ptr);
+}; break;
+case 5187: { // glVertexPointer
+ GLint *size = (GLint *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) bins[0];
+ weglVertexPointer(*size,*type,*stride,ptr);
+}; break;
+case 5188: { // glNormalPointer
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglNormalPointer(*type,*stride,ptr);
+}; break;
+case 5189: { // glNormalPointer
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) bins[0];
+ weglNormalPointer(*type,*stride,ptr);
+}; break;
+case 5190: { // glColorPointer
+ GLint *size = (GLint *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglColorPointer(*size,*type,*stride,ptr);
+}; break;
+case 5191: { // glColorPointer
+ GLint *size = (GLint *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) bins[0];
+ weglColorPointer(*size,*type,*stride,ptr);
+}; break;
+case 5192: { // glIndexPointer
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglIndexPointer(*type,*stride,ptr);
+}; break;
+case 5193: { // glIndexPointer
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) bins[0];
+ weglIndexPointer(*type,*stride,ptr);
+}; break;
+case 5194: { // glTexCoordPointer
+ GLint *size = (GLint *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglTexCoordPointer(*size,*type,*stride,ptr);
+}; break;
+case 5195: { // glTexCoordPointer
+ GLint *size = (GLint *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) bins[0];
+ weglTexCoordPointer(*size,*type,*stride,ptr);
+}; break;
+case 5196: { // glEdgeFlagPointer
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglEdgeFlagPointer(*stride,ptr);
+}; break;
+case 5197: { // glEdgeFlagPointer
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *ptr = (GLvoid *) bins[0];
+ weglEdgeFlagPointer(*stride,ptr);
+}; break;
+case 5198: { // glArrayElement
+ GLint *i = (GLint *) bp; bp += 4;
+ weglArrayElement(*i);
+}; break;
+case 5199: { // glDrawArrays
GLenum *mode = (GLenum *) bp; bp += 4;
- GLint result = weglRenderMode(*mode);
+ GLint *first = (GLint *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ weglDrawArrays(*mode,*first,*count);
+}; break;
+case 5200: { // glDrawElements
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglDrawElements(*mode,*count,*type,indices);
+}; break;
+case 5201: { // glDrawElements
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) bins[0];
+ weglDrawElements(*mode,*count,*type,indices);
+}; break;
+case 5202: { // glInterleavedArrays
+ GLenum *format = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglInterleavedArrays(*format,*stride,pointer);
+}; break;
+case 5203: { // glInterleavedArrays
+ GLenum *format = (GLenum *) bp; bp += 4;
+ GLsizei *stride = (GLsizei *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) bins[0];
+ weglInterleavedArrays(*format,*stride,pointer);
+}; break;
+case 5204: { // glShadeModel
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglShadeModel(*mode);
+}; break;
+case 5205: { // glLightf
+ GLenum *light = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglLightf(*light,*pname,*param);
+}; break;
+case 5206: { // glLighti
+ GLenum *light = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglLighti(*light,*pname,*param);
+}; break;
+case 5207: { // glLightfv
+ GLenum *light = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglLightfv(*light,*pname,params);
+}; break;
+case 5208: { // glLightiv
+ GLenum *light = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglLightiv(*light,*pname,params);
+}; break;
+case 5209: { // glGetLightfv
+ GLenum *light = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat params[4] = {0.0,0.0,0.0,0.0};
+ weglGetLightfv(*light,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble paramsConv[4], *paramsTmp = paramsConv;
+ for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5210: { // glGetLightiv
+ GLenum *light = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint params[4] = {0,0,0,0};
+ weglGetLightiv(*light,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLint *paramsTmp = params;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5211: { // glLightModelf
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglLightModelf(*pname,*param);
+}; break;
+case 5212: { // glLightModeli
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglLightModeli(*pname,*param);
+}; break;
+case 5213: { // glLightModelfv
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
+ weglLightModelfv(*pname,params);
+}; break;
+case 5214: { // glLightModeliv
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
+ weglLightModeliv(*pname,params);
+}; break;
+case 5215: { // glMaterialf
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglMaterialf(*face,*pname,*param);
+}; break;
+case 5216: { // glMateriali
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglMateriali(*face,*pname,*param);
+}; break;
+case 5217: { // glMaterialfv
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglMaterialfv(*face,*pname,params);
+}; break;
+case 5218: { // glMaterialiv
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglMaterialiv(*face,*pname,params);
+}; break;
+case 5219: { // glGetMaterialfv
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat params[4] = {0.0,0.0,0.0,0.0};
+ weglGetMaterialfv(*face,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble paramsConv[4], *paramsTmp = paramsConv;
+ for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5220: { // glGetMaterialiv
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint params[4] = {0,0,0,0};
+ weglGetMaterialiv(*face,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLint *paramsTmp = params;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5221: { // glColorMaterial
+ GLenum *face = (GLenum *) bp; bp += 4;
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ weglColorMaterial(*face,*mode);
+}; break;
+case 5222: { // glPixelZoom
+ GLfloat *xfactor = (GLfloat *) bp; bp += 4;
+ GLfloat *yfactor = (GLfloat *) bp; bp += 4;
+ weglPixelZoom(*xfactor,*yfactor);
+}; break;
+case 5223: { // glPixelStoref
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglPixelStoref(*pname,*param);
+}; break;
+case 5224: { // glPixelStorei
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglPixelStorei(*pname,*param);
+}; break;
+case 5225: { // glPixelTransferf
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglPixelTransferf(*pname,*param);
+}; break;
+case 5226: { // glPixelTransferi
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglPixelTransferi(*pname,*param);
+}; break;
+case 5227: { // glPixelMapfv
+ GLenum *map = (GLenum *) bp; bp += 4;
+ GLsizei *mapsize = (GLsizei *) bp; bp += 4;
+ GLfloat *values = (GLfloat *) bins[0];
+ weglPixelMapfv(*map,*mapsize,values);
+}; break;
+case 5228: { // glPixelMapuiv
+ GLenum *map = (GLenum *) bp; bp += 4;
+ GLsizei *mapsize = (GLsizei *) bp; bp += 4;
+ GLuint *values = (GLuint *) bins[0];
+ weglPixelMapuiv(*map,*mapsize,values);
+}; break;
+case 5229: { // glPixelMapusv
+ GLenum *map = (GLenum *) bp; bp += 4;
+ GLsizei *mapsize = (GLsizei *) bp; bp += 4;
+ GLushort *values = (GLushort *) bins[0];
+ weglPixelMapusv(*map,*mapsize,values);
+}; break;
+case 5230: { // glGetPixelMapfv
+ GLenum *map = (GLenum *) bp; bp += 4;
+ GLfloat *values = (GLfloat *) bins[0];
+ weglGetPixelMapfv(*map,values);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
- rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5248: { // glRotated
- GLdouble *angle = (GLdouble *) bp; bp += 8;
- GLdouble *x = (GLdouble *) bp; bp += 8;
- GLdouble *y = (GLdouble *) bp; bp += 8;
- GLdouble *z = (GLdouble *) bp; bp += 8;
- weglRotated(*angle,*x,*y,*z);
+case 5231: { // glGetPixelMapuiv
+ GLenum *map = (GLenum *) bp; bp += 4;
+ GLuint *values = (GLuint *) bins[0];
+ weglGetPixelMapuiv(*map,values);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5249: { // glRotatef
- GLfloat *angle = (GLfloat *) bp; bp += 4;
- GLfloat *x = (GLfloat *) bp; bp += 4;
- GLfloat *y = (GLfloat *) bp; bp += 4;
- GLfloat *z = (GLfloat *) bp; bp += 4;
- weglRotatef(*angle,*x,*y,*z);
+case 5232: { // glGetPixelMapusv
+ GLenum *map = (GLenum *) bp; bp += 4;
+ GLushort *values = (GLushort *) bins[0];
+ weglGetPixelMapusv(*map,values);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5250: { // glScaled
- GLdouble *x = (GLdouble *) bp; bp += 8;
- GLdouble *y = (GLdouble *) bp; bp += 8;
- GLdouble *z = (GLdouble *) bp; bp += 8;
- weglScaled(*x,*y,*z);
+case 5233: { // glBitmap
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLfloat *xorig = (GLfloat *) bp; bp += 4;
+ GLfloat *yorig = (GLfloat *) bp; bp += 4;
+ GLfloat *xmove = (GLfloat *) bp; bp += 4;
+ GLfloat *ymove = (GLfloat *) bp; bp += 4;
+ GLubyte *bitmap = (GLubyte *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglBitmap(*width,*height,*xorig,*yorig,*xmove,*ymove,bitmap);
}; break;
-case 5251: { // glScalef
- GLfloat *x = (GLfloat *) bp; bp += 4;
- GLfloat *y = (GLfloat *) bp; bp += 4;
- GLfloat *z = (GLfloat *) bp; bp += 4;
- weglScalef(*x,*y,*z);
+case 5234: { // glBitmap
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLfloat *xorig = (GLfloat *) bp; bp += 4;
+ GLfloat *yorig = (GLfloat *) bp; bp += 4;
+ GLfloat *xmove = (GLfloat *) bp; bp += 4;
+ GLfloat *ymove = (GLfloat *) bp; bp += 4;
+ GLubyte *bitmap = (GLubyte *) bins[0];
+ weglBitmap(*width,*height,*xorig,*yorig,*xmove,*ymove,bitmap);
}; break;
-case 5252: { // glScissor
+case 5235: { // glReadPixels
GLint *x = (GLint *) bp; bp += 4;
GLint *y = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLsizei *height = (GLsizei *) bp; bp += 4;
- weglScissor(*x,*y,*width,*height);
-}; break;
-case 5253: { // glSelectBuffer
- GLsizei *size = (GLsizei *) bp; bp += 4;
- GLuint *buffer = (GLuint *) bins[0];
- weglSelectBuffer(*size,buffer);
+ GLenum *format = (GLenum *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) bins[0];
+ weglReadPixels(*x,*y,*width,*height,*format,*type,pixels);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5254: { // glShadeModel
- GLenum *mode = (GLenum *) bp; bp += 4;
- weglShadeModel(*mode);
+case 5236: { // glDrawPixels
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLenum *format = (GLenum *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglDrawPixels(*width,*height,*format,*type,pixels);
}; break;
-case 5255: { // glStencilFunc
+case 5237: { // glDrawPixels
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLenum *format = (GLenum *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) bins[0];
+ weglDrawPixels(*width,*height,*format,*type,pixels);
+}; break;
+case 5238: { // glCopyPixels
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ weglCopyPixels(*x,*y,*width,*height,*type);
+}; break;
+case 5239: { // glStencilFunc
GLenum *func = (GLenum *) bp; bp += 4;
GLint *ref = (GLint *) bp; bp += 4;
GLuint *mask = (GLuint *) bp; bp += 4;
weglStencilFunc(*func,*ref,*mask);
}; break;
-case 5256: { // glStencilMask
+case 5240: { // glStencilMask
GLuint *mask = (GLuint *) bp; bp += 4;
weglStencilMask(*mask);
}; break;
-case 5257: { // glStencilOp
+case 5241: { // glStencilOp
GLenum *fail = (GLenum *) bp; bp += 4;
GLenum *zfail = (GLenum *) bp; bp += 4;
GLenum *zpass = (GLenum *) bp; bp += 4;
weglStencilOp(*fail,*zfail,*zpass);
}; break;
-case 5258: { // glTexCoord1dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglTexCoord1dv(v);
-}; break;
-case 5259: { // glTexCoord1fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglTexCoord1fv(v);
-}; break;
-case 5260: { // glTexCoord1iv
- GLint *v = (GLint *) bp; bp += 4;
- weglTexCoord1iv(v);
-}; break;
-case 5261: { // glTexCoord1sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglTexCoord1sv(v);
-}; break;
-case 5262: { // glTexCoord2dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglTexCoord2dv(v);
-}; break;
-case 5263: { // glTexCoord2fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglTexCoord2fv(v);
-}; break;
-case 5264: { // glTexCoord2iv
- GLint *v = (GLint *) bp; bp += 4;
- weglTexCoord2iv(v);
-}; break;
-case 5265: { // glTexCoord2sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglTexCoord2sv(v);
-}; break;
-case 5266: { // glTexCoord3dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglTexCoord3dv(v);
+case 5242: { // glClearStencil
+ GLint *s = (GLint *) bp; bp += 4;
+ weglClearStencil(*s);
}; break;
-case 5267: { // glTexCoord3fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglTexCoord3fv(v);
+case 5243: { // glTexGend
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLdouble *param = (GLdouble *) bp; bp += 8;
+ weglTexGend(*coord,*pname,*param);
}; break;
-case 5268: { // glTexCoord3iv
- GLint *v = (GLint *) bp; bp += 4;
- weglTexCoord3iv(v);
+case 5244: { // glTexGenf
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglTexGenf(*coord,*pname,*param);
}; break;
-case 5269: { // glTexCoord3sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglTexCoord3sv(v);
+case 5245: { // glTexGeni
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglTexGeni(*coord,*pname,*param);
}; break;
-case 5270: { // glTexCoord4dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglTexCoord4dv(v);
+case 5246: { // glTexGendv
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 8;
+ GLdouble *params = (GLdouble *) bp; bp += *paramsLen*8;
+ weglTexGendv(*coord,*pname,params);
}; break;
-case 5271: { // glTexCoord4fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglTexCoord4fv(v);
+case 5247: { // glTexGenfv
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglTexGenfv(*coord,*pname,params);
}; break;
-case 5272: { // glTexCoord4iv
- GLint *v = (GLint *) bp; bp += 4;
- weglTexCoord4iv(v);
+case 5248: { // glTexGeniv
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglTexGeniv(*coord,*pname,params);
}; break;
-case 5273: { // glTexCoord4sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglTexCoord4sv(v);
+case 5249: { // glGetTexGendv
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLdouble params[4] = {0.0,0.0,0.0,0.0};
+ weglGetTexGendv(*coord,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble *paramsTmp = params;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5274: { // glTexCoordPointer
- GLint *size = (GLint *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglTexCoordPointer(*size,*type,*stride,pointer);
+case 5250: { // glGetTexGenfv
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat params[4] = {0.0,0.0,0.0,0.0};
+ weglGetTexGenfv(*coord,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble paramsConv[4], *paramsTmp = paramsConv;
+ for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5275: { // glTexCoordPointer
- GLint *size = (GLint *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglTexCoordPointer(*size,*type,*stride,pointer);
+case 5251: { // glGetTexGeniv
+ GLenum *coord = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint params[4] = {0,0,0,0};
+ weglGetTexGeniv(*coord,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLint *paramsTmp = params;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5276: { // glTexEnvf
+case 5252: { // glTexEnvf
GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
GLfloat *param = (GLfloat *) bp; bp += 4;
weglTexEnvf(*target,*pname,*param);
}; break;
-case 5277: { // glTexEnvfv
+case 5253: { // glTexEnvi
GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglTexEnvfv(*target,*pname,params);
+ GLint *param = (GLint *) bp; bp += 4;
+ weglTexEnvi(*target,*pname,*param);
}; break;
-case 5278: { // glTexEnvi
+case 5254: { // glTexEnvfv
GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglTexEnvi(*target,*pname,*param);
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglTexEnvfv(*target,*pname,params);
}; break;
-case 5279: { // glTexEnviv
+case 5255: { // glTexEnviv
GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
int *paramsLen = (int *) bp; bp += 4;
GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
weglTexEnviv(*target,*pname,params);
}; break;
-case 5280: { // glTexGend
- GLenum *coord = (GLenum *) bp; bp += 4;
+case 5256: { // glGetTexEnvfv
+ GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
- GLdouble *param = (GLdouble *) bp; bp += 8;
- weglTexGend(*coord,*pname,*param);
+ GLfloat params[4] = {0.0,0.0,0.0,0.0};
+ weglGetTexEnvfv(*target,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble paramsConv[4], *paramsTmp = paramsConv;
+ for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5281: { // glTexGendv
- GLenum *coord = (GLenum *) bp; bp += 4;
+case 5257: { // glGetTexEnviv
+ GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 8;
- GLdouble *params = (GLdouble *) bp; bp += *paramsLen*8;
- weglTexGendv(*coord,*pname,params);
+ GLint params[4] = {0,0,0,0};
+ weglGetTexEnviv(*target,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLint *paramsTmp = params;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5282: { // glTexGenf
- GLenum *coord = (GLenum *) bp; bp += 4;
+case 5258: { // glTexParameterf
+ GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
GLfloat *param = (GLfloat *) bp; bp += 4;
- weglTexGenf(*coord,*pname,*param);
+ weglTexParameterf(*target,*pname,*param);
}; break;
-case 5283: { // glTexGenfv
- GLenum *coord = (GLenum *) bp; bp += 4;
+case 5259: { // glTexParameteri
+ GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglTexGenfv(*coord,*pname,params);
+ GLint *param = (GLint *) bp; bp += 4;
+ weglTexParameteri(*target,*pname,*param);
}; break;
-case 5284: { // glTexGeni
- GLenum *coord = (GLenum *) bp; bp += 4;
+case 5260: { // glTexParameterfv
+ GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglTexGeni(*coord,*pname,*param);
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
+ weglTexParameterfv(*target,*pname,params);
}; break;
-case 5285: { // glTexGeniv
- GLenum *coord = (GLenum *) bp; bp += 4;
+case 5261: { // glTexParameteriv
+ GLenum *target = (GLenum *) bp; bp += 4;
GLenum *pname = (GLenum *) bp; bp += 4;
int *paramsLen = (int *) bp; bp += 4;
GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglTexGeniv(*coord,*pname,params);
+ weglTexParameteriv(*target,*pname,params);
+}; break;
+case 5262: { // glGetTexParameterfv
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat params[4] = {0.0,0.0,0.0,0.0};
+ weglGetTexParameterfv(*target,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble paramsConv[4], *paramsTmp = paramsConv;
+ for(int i=0; i < 4; i++) paramsConv[i] = (GLdouble) params[i];
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5286: { // glTexImage1D
+case 5263: { // glGetTexParameteriv
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint params[4] = {0,0,0,0};
+ weglGetTexParameteriv(*target,*pname,params);
+ int AP = 0; ErlDrvTermData rt[14];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLint *paramsTmp = params;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 4;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5264: { // glGetTexLevelParameterfv
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
- GLint *internalformat = (GLint *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat params[1] = {0.0};
+ weglGetTexLevelParameterfv(*target,*level,*pname,params);
+ int AP = 0; ErlDrvTermData rt[8];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLdouble paramsConv[1], *paramsTmp = paramsConv;
+ for(int i=0; i < 1; i++) paramsConv[i] = (GLdouble) params[i];
+ rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 1;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5265: { // glGetTexLevelParameteriv
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint params[1] = {0};
+ weglGetTexLevelParameteriv(*target,*level,*pname,params);
+ int AP = 0; ErlDrvTermData rt[8];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ GLint *paramsTmp = params;
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *paramsTmp++;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 1;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5266: { // glTexImage1D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLint *internalFormat = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
- weglTexImage1D(*target,*level,*internalformat,*width,*border,*format,*type,pixels);
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglTexImage1D(*target,*level,*internalFormat,*width,*border,*format,*type,pixels);
}; break;
-case 5287: { // glTexImage1D
+case 5267: { // glTexImage1D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
- GLint *internalformat = (GLint *) bp; bp += 4;
+ GLint *internalFormat = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
GLvoid *pixels = (GLvoid *) bins[0];
- weglTexImage1D(*target,*level,*internalformat,*width,*border,*format,*type,pixels);
+ weglTexImage1D(*target,*level,*internalFormat,*width,*border,*format,*type,pixels);
}; break;
-case 5288: { // glTexImage2D
+case 5268: { // glTexImage2D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
- GLint *internalformat = (GLint *) bp; bp += 4;
+ GLint *internalFormat = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLsizei *height = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
- weglTexImage2D(*target,*level,*internalformat,*width,*height,*border,*format,*type,pixels);
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglTexImage2D(*target,*level,*internalFormat,*width,*height,*border,*format,*type,pixels);
}; break;
-case 5289: { // glTexImage2D
+case 5269: { // glTexImage2D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
- GLint *internalformat = (GLint *) bp; bp += 4;
+ GLint *internalFormat = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLsizei *height = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
GLvoid *pixels = (GLvoid *) bins[0];
- weglTexImage2D(*target,*level,*internalformat,*width,*height,*border,*format,*type,pixels);
+ weglTexImage2D(*target,*level,*internalFormat,*width,*height,*border,*format,*type,pixels);
}; break;
-case 5290: { // glTexParameterf
+case 5270: { // glGetTexImage
GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLfloat *param = (GLfloat *) bp; bp += 4;
- weglTexParameterf(*target,*pname,*param);
+ GLint *level = (GLint *) bp; bp += 4;
+ GLenum *format = (GLenum *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) bins[0];
+ weglGetTexImage(*target,*level,*format,*type,pixels);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5291: { // glTexParameterfv
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglTexParameterfv(*target,*pname,params);
+case 5271: { // glGenTextures
+ GLsizei *n = (GLsizei *) bp; bp += 4;
+ GLuint *textures;
+ textures = (GLuint *) driver_alloc(sizeof(GLuint) * *n);
+ weglGenTextures(*n,textures);
+ int AP = 0; ErlDrvTermData *rt;
+ rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData)*(7 + (*n)*2));
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ for(int i=0; i < *n; i++) {
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) textures[i];}
+ rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = (*n)+1;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+ driver_free(rt);
+ driver_free(textures);
}; break;
-case 5292: { // glTexParameteri
- GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- GLint *param = (GLint *) bp; bp += 4;
- weglTexParameteri(*target,*pname,*param);
+case 5272: { // glDeleteTextures
+ int * texturesLen = (int *) bp; bp += 4;
+ GLuint * textures = (GLuint *) bp; bp += (8-((*texturesLen*4+4)%8))%8;
+ weglDeleteTextures(*texturesLen,textures);
}; break;
-case 5293: { // glTexParameteriv
+case 5273: { // glBindTexture
GLenum *target = (GLenum *) bp; bp += 4;
- GLenum *pname = (GLenum *) bp; bp += 4;
- int *paramsLen = (int *) bp; bp += 4;
- GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+1)%2*4;
- weglTexParameteriv(*target,*pname,params);
+ GLuint *texture = (GLuint *) bp; bp += 4;
+ weglBindTexture(*target,*texture);
+}; break;
+case 5274: { // glPrioritizeTextures
+ int * texturesLen = (int *) bp; bp += 4;
+ GLuint * textures = (GLuint *) bp; bp += (8-((*texturesLen*4+4)%8))%8;
+ int * prioritiesLen = (int *) bp; bp += 4;
+ GLclampf * priorities = (GLclampf *) bp; bp += (8-((*prioritiesLen*4+4)%8))%8;
+ weglPrioritizeTextures(*texturesLen,textures,priorities);
+}; break;
+case 5275: { // glAreTexturesResident
+ int * texturesLen = (int *) bp; bp += 4;
+ GLuint * textures = (GLuint *) bp; bp += (8-((*texturesLen*4+4)%8))%8;
+ GLboolean *residences;
+ residences = (GLboolean *) driver_alloc(sizeof(GLboolean) * *texturesLen);
+ GLboolean result = weglAreTexturesResident(*texturesLen,textures,residences);
+ int AP = 0; ErlDrvTermData *rt;
+ rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData)*(11 + (*texturesLen)*2));
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
+ for(int i=0; i < *texturesLen; i++) {
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) residences[i];}
+ rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = (*texturesLen)+1;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+ driver_free(rt);
+ driver_free(residences);
}; break;
-case 5294: { // glTexSubImage1D
+case 5276: { // glIsTexture
+ GLuint *texture = (GLuint *) bp; bp += 4;
+ GLboolean result = weglIsTexture(*texture);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) result;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5277: { // glTexSubImage1D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
GLint *xoffset = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglTexSubImage1D(*target,*level,*xoffset,*width,*format,*type,pixels);
}; break;
-case 5295: { // glTexSubImage1D
+case 5278: { // glTexSubImage1D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
GLint *xoffset = (GLint *) bp; bp += 4;
@@ -2100,7 +1928,7 @@ case 5295: { // glTexSubImage1D
GLvoid *pixels = (GLvoid *) bins[0];
weglTexSubImage1D(*target,*level,*xoffset,*width,*format,*type,pixels);
}; break;
-case 5296: { // glTexSubImage2D
+case 5279: { // glTexSubImage2D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
GLint *xoffset = (GLint *) bp; bp += 4;
@@ -2109,10 +1937,10 @@ case 5296: { // glTexSubImage2D
GLsizei *height = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglTexSubImage2D(*target,*level,*xoffset,*yoffset,*width,*height,*format,*type,pixels);
}; break;
-case 5297: { // glTexSubImage2D
+case 5280: { // glTexSubImage2D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
GLint *xoffset = (GLint *) bp; bp += 4;
@@ -2124,86 +1952,258 @@ case 5297: { // glTexSubImage2D
GLvoid *pixels = (GLvoid *) bins[0];
weglTexSubImage2D(*target,*level,*xoffset,*yoffset,*width,*height,*format,*type,pixels);
}; break;
-case 5298: { // glTranslated
- GLdouble *x = (GLdouble *) bp; bp += 8;
- GLdouble *y = (GLdouble *) bp; bp += 8;
- GLdouble *z = (GLdouble *) bp; bp += 8;
- weglTranslated(*x,*y,*z);
+case 5281: { // glCopyTexImage1D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLenum *internalformat = (GLenum *) bp; bp += 4;
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLint *border = (GLint *) bp; bp += 4;
+ weglCopyTexImage1D(*target,*level,*internalformat,*x,*y,*width,*border);
}; break;
-case 5299: { // glTranslatef
- GLfloat *x = (GLfloat *) bp; bp += 4;
- GLfloat *y = (GLfloat *) bp; bp += 4;
- GLfloat *z = (GLfloat *) bp; bp += 4;
- weglTranslatef(*x,*y,*z);
+case 5282: { // glCopyTexImage2D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLenum *internalformat = (GLenum *) bp; bp += 4;
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLint *border = (GLint *) bp; bp += 4;
+ weglCopyTexImage2D(*target,*level,*internalformat,*x,*y,*width,*height,*border);
}; break;
-case 5300: { // glVertex2dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglVertex2dv(v);
+case 5283: { // glCopyTexSubImage1D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLint *xoffset = (GLint *) bp; bp += 4;
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ weglCopyTexSubImage1D(*target,*level,*xoffset,*x,*y,*width);
}; break;
-case 5301: { // glVertex2fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglVertex2fv(v);
+case 5284: { // glCopyTexSubImage2D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLint *xoffset = (GLint *) bp; bp += 4;
+ GLint *yoffset = (GLint *) bp; bp += 4;
+ GLint *x = (GLint *) bp; bp += 4;
+ GLint *y = (GLint *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ weglCopyTexSubImage2D(*target,*level,*xoffset,*yoffset,*x,*y,*width,*height);
}; break;
-case 5302: { // glVertex2iv
- GLint *v = (GLint *) bp; bp += 4;
- weglVertex2iv(v);
+case 5285: { // glMap1d
+ GLenum *target = (GLenum *) bp; bp += 4;
+ bp += 4;
+ GLdouble *u1 = (GLdouble *) bp; bp += 8;
+ GLdouble *u2 = (GLdouble *) bp; bp += 8;
+ GLint *stride = (GLint *) bp; bp += 4;
+ GLint *order = (GLint *) bp; bp += 4;
+ GLdouble *points = (GLdouble *) bins[0];
+ weglMap1d(*target,*u1,*u2,*stride,*order,points);
}; break;
-case 5303: { // glVertex2sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglVertex2sv(v);
+case 5286: { // glMap1f
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLfloat *u1 = (GLfloat *) bp; bp += 4;
+ GLfloat *u2 = (GLfloat *) bp; bp += 4;
+ GLint *stride = (GLint *) bp; bp += 4;
+ GLint *order = (GLint *) bp; bp += 4;
+ GLfloat *points = (GLfloat *) bins[0];
+ weglMap1f(*target,*u1,*u2,*stride,*order,points);
}; break;
-case 5304: { // glVertex3dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglVertex3dv(v);
+case 5287: { // glMap2d
+ GLenum *target = (GLenum *) bp; bp += 4;
+ bp += 4;
+ GLdouble *u1 = (GLdouble *) bp; bp += 8;
+ GLdouble *u2 = (GLdouble *) bp; bp += 8;
+ GLint *ustride = (GLint *) bp; bp += 4;
+ GLint *uorder = (GLint *) bp; bp += 4;
+ GLdouble *v1 = (GLdouble *) bp; bp += 8;
+ GLdouble *v2 = (GLdouble *) bp; bp += 8;
+ GLint *vstride = (GLint *) bp; bp += 4;
+ GLint *vorder = (GLint *) bp; bp += 4;
+ GLdouble *points = (GLdouble *) bins[0];
+ weglMap2d(*target,*u1,*u2,*ustride,*uorder,*v1,*v2,*vstride,*vorder,points);
}; break;
-case 5305: { // glVertex3fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglVertex3fv(v);
+case 5288: { // glMap2f
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLfloat *u1 = (GLfloat *) bp; bp += 4;
+ GLfloat *u2 = (GLfloat *) bp; bp += 4;
+ GLint *ustride = (GLint *) bp; bp += 4;
+ GLint *uorder = (GLint *) bp; bp += 4;
+ GLfloat *v1 = (GLfloat *) bp; bp += 4;
+ GLfloat *v2 = (GLfloat *) bp; bp += 4;
+ GLint *vstride = (GLint *) bp; bp += 4;
+ GLint *vorder = (GLint *) bp; bp += 4;
+ GLfloat *points = (GLfloat *) bins[0];
+ weglMap2f(*target,*u1,*u2,*ustride,*uorder,*v1,*v2,*vstride,*vorder,points);
}; break;
-case 5306: { // glVertex3iv
- GLint *v = (GLint *) bp; bp += 4;
- weglVertex3iv(v);
+case 5289: { // glGetMapdv
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLenum *query = (GLenum *) bp; bp += 4;
+ GLdouble *v = (GLdouble *) bins[0];
+ weglGetMapdv(*target,*query,v);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5307: { // glVertex3sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglVertex3sv(v);
+case 5290: { // glGetMapfv
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLenum *query = (GLenum *) bp; bp += 4;
+ GLfloat *v = (GLfloat *) bins[0];
+ weglGetMapfv(*target,*query,v);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5308: { // glVertex4dv
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglVertex4dv(v);
+case 5291: { // glGetMapiv
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLenum *query = (GLenum *) bp; bp += 4;
+ GLint *v = (GLint *) bins[0];
+ weglGetMapiv(*target,*query,v);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5309: { // glVertex4fv
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglVertex4fv(v);
+case 5292: { // glEvalCoord1dv
+ GLdouble *u = (GLdouble *) bp; bp += 8;
+ weglEvalCoord1dv(u);
}; break;
-case 5310: { // glVertex4iv
- GLint *v = (GLint *) bp; bp += 4;
- weglVertex4iv(v);
+case 5293: { // glEvalCoord1fv
+ GLfloat *u = (GLfloat *) bp; bp += 4;
+ weglEvalCoord1fv(u);
}; break;
-case 5311: { // glVertex4sv
- GLshort *v = (GLshort *) bp; bp += 2;
- weglVertex4sv(v);
+case 5294: { // glEvalCoord2dv
+ GLdouble *u = (GLdouble *) bp; bp += 8;
+ weglEvalCoord2dv(u);
}; break;
-case 5312: { // glVertexPointer
- GLint *size = (GLint *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
- weglVertexPointer(*size,*type,*stride,pointer);
+case 5295: { // glEvalCoord2fv
+ GLfloat *u = (GLfloat *) bp; bp += 4;
+ weglEvalCoord2fv(u);
}; break;
-case 5313: { // glVertexPointer
- GLint *size = (GLint *) bp; bp += 4;
+case 5296: { // glMapGrid1d
+ GLint *un = (GLint *) bp; bp += 4;
+ bp += 4;
+ GLdouble *u1 = (GLdouble *) bp; bp += 8;
+ GLdouble *u2 = (GLdouble *) bp; bp += 8;
+ weglMapGrid1d(*un,*u1,*u2);
+}; break;
+case 5297: { // glMapGrid1f
+ GLint *un = (GLint *) bp; bp += 4;
+ GLfloat *u1 = (GLfloat *) bp; bp += 4;
+ GLfloat *u2 = (GLfloat *) bp; bp += 4;
+ weglMapGrid1f(*un,*u1,*u2);
+}; break;
+case 5298: { // glMapGrid2d
+ GLint *un = (GLint *) bp; bp += 4;
+ bp += 4;
+ GLdouble *u1 = (GLdouble *) bp; bp += 8;
+ GLdouble *u2 = (GLdouble *) bp; bp += 8;
+ GLint *vn = (GLint *) bp; bp += 4;
+ bp += 4;
+ GLdouble *v1 = (GLdouble *) bp; bp += 8;
+ GLdouble *v2 = (GLdouble *) bp; bp += 8;
+ weglMapGrid2d(*un,*u1,*u2,*vn,*v1,*v2);
+}; break;
+case 5299: { // glMapGrid2f
+ GLint *un = (GLint *) bp; bp += 4;
+ GLfloat *u1 = (GLfloat *) bp; bp += 4;
+ GLfloat *u2 = (GLfloat *) bp; bp += 4;
+ GLint *vn = (GLint *) bp; bp += 4;
+ GLfloat *v1 = (GLfloat *) bp; bp += 4;
+ GLfloat *v2 = (GLfloat *) bp; bp += 4;
+ weglMapGrid2f(*un,*u1,*u2,*vn,*v1,*v2);
+}; break;
+case 5300: { // glEvalPoint1
+ GLint *i = (GLint *) bp; bp += 4;
+ weglEvalPoint1(*i);
+}; break;
+case 5301: { // glEvalPoint2
+ GLint *i = (GLint *) bp; bp += 4;
+ GLint *j = (GLint *) bp; bp += 4;
+ weglEvalPoint2(*i,*j);
+}; break;
+case 5302: { // glEvalMesh1
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLint *i1 = (GLint *) bp; bp += 4;
+ GLint *i2 = (GLint *) bp; bp += 4;
+ weglEvalMesh1(*mode,*i1,*i2);
+}; break;
+case 5303: { // glEvalMesh2
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLint *i1 = (GLint *) bp; bp += 4;
+ GLint *i2 = (GLint *) bp; bp += 4;
+ GLint *j1 = (GLint *) bp; bp += 4;
+ GLint *j2 = (GLint *) bp; bp += 4;
+ weglEvalMesh2(*mode,*i1,*i2,*j1,*j2);
+}; break;
+case 5304: { // glFogf
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLfloat *param = (GLfloat *) bp; bp += 4;
+ weglFogf(*pname,*param);
+}; break;
+case 5305: { // glFogi
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLint *param = (GLint *) bp; bp += 4;
+ weglFogi(*pname,*param);
+}; break;
+case 5306: { // glFogfv
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLfloat *params = (GLfloat *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
+ weglFogfv(*pname,params);
+}; break;
+case 5307: { // glFogiv
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ int *paramsLen = (int *) bp; bp += 4;
+ GLint *params = (GLint *) bp; bp += *paramsLen*4+((*paramsLen)+0)%2*4;
+ weglFogiv(*pname,params);
+}; break;
+case 5308: { // glFeedbackBuffer
+ GLsizei *size = (GLsizei *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) bins[0];
- weglVertexPointer(*size,*type,*stride,pointer);
+ GLfloat *buffer = (GLfloat *) bins[0];
+ weglFeedbackBuffer(*size,*type,buffer);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
}; break;
-case 5314: { // glViewport
- GLint *x = (GLint *) bp; bp += 4;
- GLint *y = (GLint *) bp; bp += 4;
- GLsizei *width = (GLsizei *) bp; bp += 4;
- GLsizei *height = (GLsizei *) bp; bp += 4;
- weglViewport(*x,*y,*width,*height);
+case 5309: { // glPassThrough
+ GLfloat *token = (GLfloat *) bp; bp += 4;
+ weglPassThrough(*token);
+}; break;
+case 5310: { // glSelectBuffer
+ GLsizei *size = (GLsizei *) bp; bp += 4;
+ GLuint *buffer = (GLuint *) bins[0];
+ weglSelectBuffer(*size,buffer);
+ int AP = 0; ErlDrvTermData rt[6];
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+}; break;
+case 5311: { // glInitNames
+ weglInitNames();
+}; break;
+case 5312: { // glLoadName
+ GLuint *name = (GLuint *) bp; bp += 4;
+ weglLoadName(*name);
+}; break;
+case 5313: { // glPushName
+ GLuint *name = (GLuint *) bp; bp += 4;
+ weglPushName(*name);
+}; break;
+case 5314: { // glPopName
+ weglPopName();
}; break;
case 5315: { // glBlendColor
GLclampf *red = (GLclampf *) bp; bp += 4;
@@ -2222,7 +2222,7 @@ case 5317: { // glDrawRangeElements
GLuint *end = (GLuint *) bp; bp += 4;
GLsizei *count = (GLsizei *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglDrawRangeElements(*mode,*start,*end,*count,*type,indices);
}; break;
case 5318: { // glDrawRangeElements
@@ -2237,20 +2237,20 @@ case 5318: { // glDrawRangeElements
case 5319: { // glTexImage3D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
- GLint *internalformat = (GLint *) bp; bp += 4;
+ GLint *internalFormat = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLsizei *height = (GLsizei *) bp; bp += 4;
GLsizei *depth = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
- weglTexImage3D(*target,*level,*internalformat,*width,*height,*depth,*border,*format,*type,pixels);
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ weglTexImage3D(*target,*level,*internalFormat,*width,*height,*depth,*border,*format,*type,pixels);
}; break;
case 5320: { // glTexImage3D
GLenum *target = (GLenum *) bp; bp += 4;
GLint *level = (GLint *) bp; bp += 4;
- GLint *internalformat = (GLint *) bp; bp += 4;
+ GLint *internalFormat = (GLint *) bp; bp += 4;
GLsizei *width = (GLsizei *) bp; bp += 4;
GLsizei *height = (GLsizei *) bp; bp += 4;
GLsizei *depth = (GLsizei *) bp; bp += 4;
@@ -2258,7 +2258,7 @@ case 5320: { // glTexImage3D
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
GLvoid *pixels = (GLvoid *) bins[0];
- weglTexImage3D(*target,*level,*internalformat,*width,*height,*depth,*border,*format,*type,pixels);
+ weglTexImage3D(*target,*level,*internalFormat,*width,*height,*depth,*border,*format,*type,pixels);
}; break;
case 5321: { // glTexSubImage3D
GLenum *target = (GLenum *) bp; bp += 4;
@@ -2271,7 +2271,7 @@ case 5321: { // glTexSubImage3D
GLsizei *depth = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *pixels = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pixels = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglTexSubImage3D(*target,*level,*xoffset,*yoffset,*zoffset,*width,*height,*depth,*format,*type,pixels);
}; break;
case 5322: { // glTexSubImage3D
@@ -2306,7 +2306,7 @@ case 5324: { // glColorTable
GLsizei *width = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *table = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *table = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglColorTable(*target,*internalformat,*width,*format,*type,table);
}; break;
case 5325: { // glColorTable
@@ -2389,7 +2389,7 @@ case 5332: { // glColorSubTable
GLsizei *count = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglColorSubTable(*target,*start,*count,*format,*type,data);
}; break;
case 5333: { // glColorSubTable
@@ -2415,7 +2415,7 @@ case 5335: { // glConvolutionFilter1D
GLsizei *width = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *image = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *image = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglConvolutionFilter1D(*target,*internalformat,*width,*format,*type,image);
}; break;
case 5336: { // glConvolutionFilter1D
@@ -2434,7 +2434,7 @@ case 5337: { // glConvolutionFilter2D
GLsizei *height = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *image = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *image = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglConvolutionFilter2D(*target,*internalformat,*width,*height,*format,*type,image);
}; break;
case 5338: { // glConvolutionFilter2D
@@ -2530,8 +2530,8 @@ case 5346: { // glSeparableFilter2D
GLsizei *height = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *row = (GLvoid *) * (int *) bp; bp += 4;
- GLvoid *column = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *row = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ GLvoid *column = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglSeparableFilter2D(*target,*internalformat,*width,*height,*format,*type,row,column);
}; break;
case 5347: { // glSeparableFilter2D
@@ -2591,9 +2591,9 @@ case 5351: { // glGetMinmax
GLboolean *reset = (GLboolean *) bp; bp += 1;
bp += 3;
GLenum *format = (GLenum *) bp; bp += 4;
- GLenum *type = (GLenum *) bp; bp += 4;
+ GLenum *types = (GLenum *) bp; bp += 4;
GLvoid *values = (GLvoid *) bins[0];
- weglGetMinmax(*target,*reset,*format,*type,values);
+ weglGetMinmax(*target,*reset,*format,*types,values);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
@@ -2666,7 +2666,7 @@ case 5360: { // glCompressedTexImage3D
GLsizei *depth = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLsizei *imageSize = (GLsizei *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglCompressedTexImage3D(*target,*level,*internalformat,*width,*height,*depth,*border,*imageSize,data);
}; break;
case 5361: { // glCompressedTexImage3D
@@ -2689,7 +2689,7 @@ case 5362: { // glCompressedTexImage2D
GLsizei *height = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLsizei *imageSize = (GLsizei *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglCompressedTexImage2D(*target,*level,*internalformat,*width,*height,*border,*imageSize,data);
}; break;
case 5363: { // glCompressedTexImage2D
@@ -2710,7 +2710,7 @@ case 5364: { // glCompressedTexImage1D
GLsizei *width = (GLsizei *) bp; bp += 4;
GLint *border = (GLint *) bp; bp += 4;
GLsizei *imageSize = (GLsizei *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglCompressedTexImage1D(*target,*level,*internalformat,*width,*border,*imageSize,data);
}; break;
case 5365: { // glCompressedTexImage1D
@@ -2734,7 +2734,7 @@ case 5366: { // glCompressedTexSubImage3D
GLsizei *depth = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLsizei *imageSize = (GLsizei *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglCompressedTexSubImage3D(*target,*level,*xoffset,*yoffset,*zoffset,*width,*height,*depth,*format,*imageSize,data);
}; break;
case 5367: { // glCompressedTexSubImage3D
@@ -2760,7 +2760,7 @@ case 5368: { // glCompressedTexSubImage2D
GLsizei *height = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLsizei *imageSize = (GLsizei *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglCompressedTexSubImage2D(*target,*level,*xoffset,*yoffset,*width,*height,*format,*imageSize,data);
}; break;
case 5369: { // glCompressedTexSubImage2D
@@ -2782,7 +2782,7 @@ case 5370: { // glCompressedTexSubImage1D
GLsizei *width = (GLsizei *) bp; bp += 4;
GLenum *format = (GLenum *) bp; bp += 4;
GLsizei *imageSize = (GLsizei *) bp; bp += 4;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglCompressedTexSubImage1D(*target,*level,*xoffset,*width,*format,*imageSize,data);
}; break;
case 5371: { // glCompressedTexSubImage1D
@@ -2797,9 +2797,9 @@ case 5371: { // glCompressedTexSubImage1D
}; break;
case 5372: { // glGetCompressedTexImage
GLenum *target = (GLenum *) bp; bp += 4;
- GLint *level = (GLint *) bp; bp += 4;
+ GLint *lod = (GLint *) bp; bp += 4;
GLvoid *img = (GLvoid *) bins[0];
- weglGetCompressedTexImage(*target,*level,img);
+ weglGetCompressedTexImage(*target,*lod,img);
int AP = 0; ErlDrvTermData rt[6];
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "ok");
@@ -2958,7 +2958,7 @@ case 5401: { // glFogCoorddv
case 5402: { // glFogCoordPointer
GLenum *type = (GLenum *) bp; bp += 4;
GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglFogCoordPointer(*type,*stride,pointer);
}; break;
case 5403: { // glFogCoordPointer
@@ -3003,7 +3003,7 @@ case 5412: { // glSecondaryColorPointer
GLint *size = (GLint *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglSecondaryColorPointer(*size,*type,*stride,pointer);
}; break;
case 5413: { // glSecondaryColorPointer
@@ -3156,7 +3156,7 @@ case 5434: { // glBufferData
GLenum *target = (GLenum *) bp; bp += 4;
bp += 4;
GLsizeiptr size = (GLsizeiptr) * (GLuint64EXT *) bp; bp += 8;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
GLenum *usage = (GLenum *) bp; bp += 4;
weglBufferData(*target,size,data,*usage);
}; break;
@@ -3173,7 +3173,7 @@ case 5436: { // glBufferSubData
bp += 4;
GLintptr offset = (GLintptr) * (GLuint64EXT *) bp; bp += 8;
GLsizeiptr size = (GLsizeiptr) * (GLuint64EXT *) bp; bp += 8;
- GLvoid *data = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *data = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglBufferSubData(*target,offset,size,data);
}; break;
case 5437: { // glBufferSubData
@@ -3833,7 +3833,7 @@ case 5518: { // glVertexAttribPointer
GLboolean *normalized = (GLboolean *) bp; bp += 1;
bp += 3;
GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglVertexAttribPointer(*index,*size,*type,*normalized,*stride,pointer);
}; break;
case 5519: { // glVertexAttribPointer
@@ -4051,7 +4051,7 @@ case 5541: { // glVertexAttribIPointer
GLint *size = (GLint *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglVertexAttribIPointer(*index,*size,*type,*stride,pointer);
}; break;
case 5542: { // glVertexAttribIPointer
@@ -4345,7 +4345,7 @@ case 5578: { // glDrawElementsInstanced
GLenum *mode = (GLenum *) bp; bp += 4;
GLsizei *count = (GLsizei *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
GLsizei *primcount = (GLsizei *) bp; bp += 4;
weglDrawElementsInstanced(*mode,*count,*type,indices,*primcount);
}; break;
@@ -5341,7 +5341,7 @@ case 5683: { // glDrawElementsBaseVertex
GLenum *mode = (GLenum *) bp; bp += 4;
GLsizei *count = (GLsizei *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
GLint *basevertex = (GLint *) bp; bp += 4;
weglDrawElementsBaseVertex(*mode,*count,*type,indices,*basevertex);
}; break;
@@ -5359,7 +5359,7 @@ case 5685: { // glDrawRangeElementsBaseVertex
GLuint *end = (GLuint *) bp; bp += 4;
GLsizei *count = (GLsizei *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
GLint *basevertex = (GLint *) bp; bp += 4;
weglDrawRangeElementsBaseVertex(*mode,*start,*end,*count,*type,indices,*basevertex);
}; break;
@@ -5377,7 +5377,7 @@ case 5687: { // glDrawElementsInstancedBaseVertex
GLenum *mode = (GLenum *) bp; bp += 4;
GLsizei *count = (GLsizei *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indices = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indices = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
GLsizei *primcount = (GLsizei *) bp; bp += 4;
GLint *basevertex = (GLint *) bp; bp += 4;
weglDrawElementsInstancedBaseVertex(*mode,*count,*type,indices,*primcount,*basevertex);
@@ -5772,7 +5772,7 @@ case 5725: { // glGetQueryObjectui64v
}; break;
case 5726: { // glDrawArraysIndirect
GLenum *mode = (GLenum *) bp; bp += 4;
- GLvoid *indirect = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indirect = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglDrawArraysIndirect(*mode,indirect);
}; break;
case 5727: { // glDrawArraysIndirect
@@ -5783,7 +5783,7 @@ case 5727: { // glDrawArraysIndirect
case 5728: { // glDrawElementsIndirect
GLenum *mode = (GLenum *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
- GLvoid *indirect = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *indirect = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglDrawElementsIndirect(*mode,*type,indirect);
}; break;
case 5729: { // glDrawElementsIndirect
@@ -6718,7 +6718,7 @@ case 5840: { // glVertexAttribLPointer
GLint *size = (GLint *) bp; bp += 4;
GLenum *type = (GLenum *) bp; bp += 4;
GLsizei *stride = (GLsizei *) bp; bp += 4;
- GLvoid *pointer = (GLvoid *) * (int *) bp; bp += 4;
+ GLvoid *pointer = (GLvoid *) (ErlDrvSInt) * (int *) bp; bp += 4;
weglVertexAttribLPointer(*index,*size,*type,*stride,pointer);
}; break;
case 5841: { // glVertexAttribLPointer
@@ -6927,31 +6927,129 @@ case 5856: { // glGetGraphicsResetStatusARB
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
driver_send_term(port,caller,rt,AP);
}; break;
-case 5857: { // glResizeBuffersMESA
- weglResizeBuffersMESA();
+case 5857: { // glDrawArraysInstancedBaseInstance
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLint *first = (GLint *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ GLuint *baseinstance = (GLuint *) bp; bp += 4;
+ weglDrawArraysInstancedBaseInstance(*mode,*first,*count,*primcount,*baseinstance);
}; break;
-case 5858: { // glWindowPos4dvMESA
- GLdouble *v = (GLdouble *) bp; bp += 8;
- weglWindowPos4dvMESA(v);
+case 5858: { // glDrawElementsInstancedBaseInstance
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ void *indices = (void *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ GLuint *baseinstance = (GLuint *) bp; bp += 4;
+ weglDrawElementsInstancedBaseInstance(*mode,*count,*type,indices,*primcount,*baseinstance);
}; break;
-case 5859: { // glWindowPos4fvMESA
- GLfloat *v = (GLfloat *) bp; bp += 4;
- weglWindowPos4fvMESA(v);
+case 5859: { // glDrawElementsInstancedBaseInstance
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ void *indices = (void *) bins[0];
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ GLuint *baseinstance = (GLuint *) bp; bp += 4;
+ weglDrawElementsInstancedBaseInstance(*mode,*count,*type,indices,*primcount,*baseinstance);
}; break;
-case 5860: { // glWindowPos4ivMESA
- GLint *v = (GLint *) bp; bp += 4;
- weglWindowPos4ivMESA(v);
+case 5860: { // glDrawElementsInstancedBaseVertexBaseInstance
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ void *indices = (void *) (ErlDrvSInt) * (int *) bp; bp += 4;
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ GLint *basevertex = (GLint *) bp; bp += 4;
+ GLuint *baseinstance = (GLuint *) bp; bp += 4;
+ weglDrawElementsInstancedBaseVertexBaseInstance(*mode,*count,*type,indices,*primcount,*basevertex,*baseinstance);
}; break;
-case 5861: { // glWindowPos4svMESA
- GLshort *v = (GLshort *) bp; bp += 2;
- weglWindowPos4svMESA(v);
+case 5861: { // glDrawElementsInstancedBaseVertexBaseInstance
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLsizei *count = (GLsizei *) bp; bp += 4;
+ GLenum *type = (GLenum *) bp; bp += 4;
+ void *indices = (void *) bins[0];
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ GLint *basevertex = (GLint *) bp; bp += 4;
+ GLuint *baseinstance = (GLuint *) bp; bp += 4;
+ weglDrawElementsInstancedBaseVertexBaseInstance(*mode,*count,*type,indices,*primcount,*basevertex,*baseinstance);
+}; break;
+case 5862: { // glDrawTransformFeedbackInstanced
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLuint *id = (GLuint *) bp; bp += 4;
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ weglDrawTransformFeedbackInstanced(*mode,*id,*primcount);
+}; break;
+case 5863: { // glDrawTransformFeedbackStreamInstanced
+ GLenum *mode = (GLenum *) bp; bp += 4;
+ GLuint *id = (GLuint *) bp; bp += 4;
+ GLuint *stream = (GLuint *) bp; bp += 4;
+ GLsizei *primcount = (GLsizei *) bp; bp += 4;
+ weglDrawTransformFeedbackStreamInstanced(*mode,*id,*stream,*primcount);
+}; break;
+case 5864: { // glGetInternalformativ
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLenum *internalformat = (GLenum *) bp; bp += 4;
+ GLenum *pname = (GLenum *) bp; bp += 4;
+ GLsizei *bufSize = (GLsizei *) bp; bp += 4;
+ GLint *params;
+ params = (GLint *) driver_alloc(sizeof(GLint) * *bufSize);
+ weglGetInternalformativ(*target,*internalformat,*pname,*bufSize,params);
+ int AP = 0; ErlDrvTermData *rt;
+ rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData)*(7 + (*bufSize)*2));
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
+ for(int i=0; i < *bufSize; i++) {
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) params[i];}
+ rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = (*bufSize)+1;
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;
+ driver_send_term(port,caller,rt,AP);
+ driver_free(rt);
+ driver_free(params);
+}; break;
+case 5865: { // glBindImageTexture
+ GLuint *unit = (GLuint *) bp; bp += 4;
+ GLuint *texture = (GLuint *) bp; bp += 4;
+ GLint *level = (GLint *) bp; bp += 4;
+ GLboolean *layered = (GLboolean *) bp; bp += 1;
+ bp += 3;
+ GLint *layer = (GLint *) bp; bp += 4;
+ GLenum *access = (GLenum *) bp; bp += 4;
+ GLenum *format = (GLenum *) bp; bp += 4;
+ weglBindImageTexture(*unit,*texture,*level,*layered,*layer,*access,*format);
+}; break;
+case 5866: { // glMemoryBarrier
+ GLbitfield *barriers = (GLbitfield *) bp; bp += 4;
+ weglMemoryBarrier(*barriers);
+}; break;
+case 5867: { // glTexStorage1D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLsizei *levels = (GLsizei *) bp; bp += 4;
+ GLenum *internalformat = (GLenum *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ weglTexStorage1D(*target,*levels,*internalformat,*width);
+}; break;
+case 5868: { // glTexStorage2D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLsizei *levels = (GLsizei *) bp; bp += 4;
+ GLenum *internalformat = (GLenum *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ weglTexStorage2D(*target,*levels,*internalformat,*width,*height);
+}; break;
+case 5869: { // glTexStorage3D
+ GLenum *target = (GLenum *) bp; bp += 4;
+ GLsizei *levels = (GLsizei *) bp; bp += 4;
+ GLenum *internalformat = (GLenum *) bp; bp += 4;
+ GLsizei *width = (GLsizei *) bp; bp += 4;
+ GLsizei *height = (GLsizei *) bp; bp += 4;
+ GLsizei *depth = (GLsizei *) bp; bp += 4;
+ weglTexStorage3D(*target,*levels,*internalformat,*width,*height,*depth);
}; break;
-case 5862: { // glDepthBoundsEXT
+case 5870: { // glDepthBoundsEXT
GLclampd *zmin = (GLclampd *) bp; bp += 8;
GLclampd *zmax = (GLclampd *) bp; bp += 8;
weglDepthBoundsEXT(*zmin,*zmax);
}; break;
-case 5863: { // glStencilClearTagEXT
+case 5871: { // glStencilClearTagEXT
GLsizei *stencilTagBits = (GLsizei *) bp; bp += 4;
GLuint *stencilClearTag = (GLuint *) bp; bp += 4;
weglStencilClearTagEXT(*stencilTagBits,*stencilClearTag);
diff --git a/lib/wx/c_src/gen/glu_finit.h b/lib/wx/c_src/gen/glu_finit.h
index 63e9c2fc78..0e55d48a2a 100644
--- a/lib/wx/c_src/gen/glu_finit.h
+++ b/lib/wx/c_src/gen/glu_finit.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The 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_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h
index 4e4aea098d..6b7a5378cb 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-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -129,6 +129,18 @@ class EwxBufferedPaintDC : public wxBufferedPaintDC {
EwxBufferedPaintDC(wxWindow * window,int style) : wxBufferedPaintDC(window,style) {};
};
+#if wxUSE_GRAPHICS_CONTEXT
+class EwxGraphicsObject : public wxGraphicsObject {
+ public: ~EwxGraphicsObject() {((WxeApp *)wxTheApp)->clearPtr(this);};
+};
+#endif // wxUSE_GRAPHICS_CONTEXT
+
+#if wxUSE_GRAPHICS_CONTEXT
+class EwxGraphicsContext : public wxGraphicsContext {
+ public: ~EwxGraphicsContext() {((WxeApp *)wxTheApp)->clearPtr(this);};
+};
+#endif // wxUSE_GRAPHICS_CONTEXT
+
class EwxMenuBar : public wxMenuBar {
public: ~EwxMenuBar() {((WxeApp *)wxTheApp)->clearPtr(this);};
EwxMenuBar(long style) : wxMenuBar(style) {};
@@ -671,16 +683,20 @@ class EwxGLCanvas : public wxGLCanvas {
EwxGLCanvas(wxWindow * parent,wxWindowID id,const wxPoint& pos,const wxSize& size,long style,const wxString& name,int * attribList,const wxPalette& palette) : wxGLCanvas(parent,id,pos,size,style,name,attribList,palette) {};
};
+#if wxUSE_AUI
class EwxAuiManager : public wxAuiManager {
public: ~EwxAuiManager() {((WxeApp *)wxTheApp)->clearPtr(this);};
EwxAuiManager(wxWindow * managed_wnd,unsigned int flags) : wxAuiManager(managed_wnd,flags) {};
};
+#endif // wxUSE_AUI
+#if wxUSE_AUI
class EwxAuiNotebook : public wxAuiNotebook {
public: ~EwxAuiNotebook() {((WxeApp *)wxTheApp)->clearPtr(this);};
EwxAuiNotebook(wxWindow * parent,wxWindowID id,const wxPoint& pos,const wxSize& size,long style) : wxAuiNotebook(parent,id,pos,size,style) {};
EwxAuiNotebook() : wxAuiNotebook() {};
};
+#endif // wxUSE_AUI
class EwxMDIParentFrame : public wxMDIParentFrame {
public: ~EwxMDIParentFrame() {((WxeApp *)wxTheApp)->clearPtr(this);};
@@ -727,3 +743,8 @@ class EwxHtmlWindow : public wxHtmlWindow {
EwxHtmlWindow() : wxHtmlWindow() {};
};
+class EwxTaskBarIcon : public wxTaskBarIcon {
+ public: ~EwxTaskBarIcon() {((WxeApp *)wxTheApp)->clearPtr(this);};
+ EwxTaskBarIcon() : wxTaskBarIcon() {};
+};
+
diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp
index b9769318af..0afb02150a 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-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The 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,41 +266,48 @@ void initEventTable()
{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"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 223, "command_auinotebook_page_close"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 223, "command_auinotebook_page_changed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 223, "command_auinotebook_page_changing"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 223, "command_auinotebook_button"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 223, "command_auinotebook_begin_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 223, "command_auinotebook_end_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 223, "command_auinotebook_drag_motion"},
+ {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 223, "command_auinotebook_allow_dnd"},
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 222, "command_auinotebook_tab_middle_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 223, "command_auinotebook_tab_middle_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 222, "command_auinotebook_tab_middle_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 223, "command_auinotebook_tab_middle_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 222, "command_auinotebook_tab_right_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 223, "command_auinotebook_tab_right_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 222, "command_auinotebook_tab_right_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 223, "command_auinotebook_tab_right_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 222, "command_auinotebook_page_closed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 223, "command_auinotebook_page_closed"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 222, "command_auinotebook_drag_done"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 223, "command_auinotebook_drag_done"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 222, "command_auinotebook_bg_dclick"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 223, "command_auinotebook_bg_dclick"},
#endif
- {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"},
+ {wxEVT_AUI_PANE_BUTTON, 224, "aui_pane_button"},
+ {wxEVT_AUI_PANE_CLOSE, 224, "aui_pane_close"},
+ {wxEVT_AUI_PANE_MAXIMIZE, 224, "aui_pane_maximize"},
+ {wxEVT_AUI_PANE_RESTORE, 224, "aui_pane_restore"},
+ {wxEVT_AUI_RENDER, 224, "aui_render"},
+ {wxEVT_AUI_FIND_MANAGER, 224, "aui_find_manager"},
+ {wxEVT_TASKBAR_MOVE, 227, "taskbar_move"},
+ {wxEVT_TASKBAR_LEFT_DOWN, 227, "taskbar_left_down"},
+ {wxEVT_TASKBAR_LEFT_UP, 227, "taskbar_left_up"},
+ {wxEVT_TASKBAR_RIGHT_DOWN, 227, "taskbar_right_down"},
+ {wxEVT_TASKBAR_RIGHT_UP, 227, "taskbar_right_up"},
+ {wxEVT_TASKBAR_LEFT_DCLICK, 227, "taskbar_left_dclick"},
+ {wxEVT_TASKBAR_RIGHT_DCLICK, 227, "taskbar_right_dclick"},
{-1, 0, }
};
for(int i=0; event_types[i].ev_type != -1; i++) {
@@ -778,7 +785,7 @@ case 220: {// wxHtmlLinkEvent
rt.addTupleCount(3);
break;
}
-case 222: {// wxAuiNotebookEvent
+case 223: {// wxAuiNotebookEvent
wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event;
wxAuiNotebook * GetDragSource = ev->GetDragSource();
evClass = (char*)"wxAuiNotebookEvent";
@@ -790,7 +797,7 @@ case 222: {// wxAuiNotebookEvent
rt.addTupleCount(5);
break;
}
-case 223: {// wxAuiManagerEvent
+case 224: {// wxAuiManagerEvent
wxAuiManagerEvent * ev = (wxAuiManagerEvent *) event;
wxAuiManager * GetManager = ev->GetManager();
wxAuiPaneInfo * GetPane = ev->GetPane();
@@ -807,6 +814,13 @@ case 223: {// wxAuiManagerEvent
rt.addTupleCount(8);
break;
}
+case 227: {// wxTaskBarIconEvent
+ evClass = (char*)"wxTaskBarIconEvent";
+ rt.addAtom((char*)"wxTaskBarIcon");
+ rt.addAtom(Etype->eName);
+ rt.addTupleCount(2);
+ break;
+}
}
rt.addTupleCount(5);
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index afef2990b4..15012011ed 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-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -5334,14 +5334,18 @@ case wxDC_GetCharWidth: { // wxDC::GetCharWidth
break;
}
case wxDC_GetClippingBox: { // wxDC::GetClippingBox
+ wxCoord x;
+ wxCoord y;
+ wxCoord w;
+ wxCoord h;
wxDC *This = (wxDC *) getPtr(bp,memenv); bp += 4;
- int * rectX = (int *) bp; bp += 4;
- int * rectY = (int *) bp; bp += 4;
- int * rectW = (int *) bp; bp += 4;
- int * rectH = (int *) bp; bp += 4;
- wxRect rect = wxRect(*rectX,*rectY,*rectW,*rectH);
if(!This) throw wxe_badarg(0);
- This->GetClippingBox(rect);
+ This->GetClippingBox(&x,&y,&w,&h);
+ rt.addInt(x);
+ rt.addInt(y);
+ rt.addInt(w);
+ rt.addInt(h);
+ rt.addTupleCount(4);
break;
}
case wxDC_GetFont: { // wxDC::GetFont
@@ -5405,17 +5409,16 @@ case wxDC_GetMultiLineTextExtent_1: { // wxDC::GetMultiLineTextExtent
break;
}
case wxDC_GetPartialTextExtents: { // wxDC::GetPartialTextExtents
+ wxArrayInt widths;
wxDC *This = (wxDC *) getPtr(bp,memenv); bp += 4;
int * textLen = (int *) bp; bp += 4;
wxString text = wxString(bp, wxConvUTF8);
bp += *textLen+((8-((0+ *textLen) & 7)) & 7);
- int * widthsLen = (int *) bp; bp += 4;
- wxArrayInt widths;
- for(int i=0; i < *widthsLen; i++) { widths.Add(*(int *) bp); bp += 4;}
- bp += ((*widthsLen + 1) % 2 )*4;
if(!This) throw wxe_badarg(0);
bool Result = This->GetPartialTextExtents(text,widths);
rt.addBool(Result);
+ rt.add(widths);
+ rt.addTupleCount(2);
break;
}
case wxDC_GetPen: { // wxDC::GetPen
@@ -5426,18 +5429,16 @@ case wxDC_GetPen: { // wxDC::GetPen
break;
}
case wxDC_GetPixel: { // wxDC::GetPixel
+ wxColour col;
wxDC *This = (wxDC *) getPtr(bp,memenv); bp += 4;
int * ptX = (int *) bp; bp += 4;
int * ptY = (int *) bp; bp += 4;
wxPoint pt = wxPoint(*ptX,*ptY);
- int * colR = (int *) bp; bp += 4;
- int * colG = (int *) bp; bp += 4;
- int * colB = (int *) bp; bp += 4;
- int * colA = (int *) bp; bp += 4;
- wxColour col = wxColour(*colR,*colG,*colB,*colA);
if(!This) throw wxe_badarg(0);
bool Result = This->GetPixel(pt,&col);
rt.addBool(Result);
+ rt.add(col);
+ rt.addTupleCount(2);
break;
}
case wxDC_GetPPI: { // wxDC::GetPPI
@@ -6255,17 +6256,21 @@ case wxGraphicsContext_DrawIcon: { // wxGraphicsContext::DrawIcon
case wxGraphicsContext_DrawLines: { // wxGraphicsContext::DrawLines
int fillStyle=wxODDEVEN_RULE;
wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
- int * n = (int *) bp; bp += 4;
- wxDouble * pointsX = (wxDouble *) bp; bp += 8;
- wxDouble * pointsY = (wxDouble *) bp; bp += 8;
- wxPoint2DDouble points = wxPoint2DDouble(*pointsX,*pointsY);
+ int * pointsLen = (int *) bp; bp += 4;
+ wxPoint2DDouble *points;
+ points = (wxPoint2DDouble *) driver_alloc(sizeof(wxPoint2DDouble) * *pointsLen);
+ for(int i=0; i < *pointsLen; i++) {
+ double x = * (double *) bp; bp += 8;
+ double y = * (double *) bp; bp += 8;
+ points[i] = wxPoint2DDouble(x,y);}
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
fillStyle = (int)*(int *) bp; bp += 4;
} break;
}};
if(!This) throw wxe_badarg(0);
- This->DrawLines((size_t) *n,&points,fillStyle);
+ This->DrawLines(*pointsLen,points,fillStyle);
+ driver_free(points);
break;
}
case wxGraphicsContext_DrawPath: { // wxGraphicsContext::DrawPath
@@ -6372,23 +6377,15 @@ case wxGraphicsContext_StrokePath: { // wxGraphicsContext::StrokePath
This->StrokePath(*path);
break;
}
-case wxGraphicsContext_GetNativeContext: { // wxGraphicsContext::GetNativeContext
- wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
- if(!This) throw wxe_badarg(0);
- This->GetNativeContext();
- break;
-}
case wxGraphicsContext_GetPartialTextExtents: { // wxGraphicsContext::GetPartialTextExtents
+ wxArrayDouble widths;
wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
int * textLen = (int *) bp; bp += 4;
wxString text = wxString(bp, wxConvUTF8);
bp += *textLen+((8-((0+ *textLen) & 7)) & 7);
- int * widthsLen = (int *) bp; bp += 4;
- bp += 4; /* Align */
- wxArrayDouble widths;
- for(int i=0; i < *widthsLen; i++) { widths.Add(*(int *) bp); bp += 4;}
if(!This) throw wxe_badarg(0);
This->GetPartialTextExtents(text,widths);
+ rt.add(widths);
break;
}
case wxGraphicsContext_GetTextExtent: { // wxGraphicsContext::GetTextExtent
@@ -6514,27 +6511,18 @@ case wxGraphicsContext_StrokeLine: { // wxGraphicsContext::StrokeLine
This->StrokeLine((wxDouble) *x1,(wxDouble) *y1,(wxDouble) *x2,(wxDouble) *y2);
break;
}
-case wxGraphicsContext_StrokeLines_2: { // wxGraphicsContext::StrokeLines
- wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
- int * n = (int *) bp; bp += 4;
- wxDouble * pointsX = (wxDouble *) bp; bp += 8;
- wxDouble * pointsY = (wxDouble *) bp; bp += 8;
- wxPoint2DDouble points = wxPoint2DDouble(*pointsX,*pointsY);
- if(!This) throw wxe_badarg(0);
- This->StrokeLines((size_t) *n,&points);
- break;
-}
-case wxGraphicsContext_StrokeLines_3: { // wxGraphicsContext::StrokeLines
+case wxGraphicsContext_StrokeLines: { // wxGraphicsContext::StrokeLines
wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
- int * n = (int *) bp; bp += 4;
- wxDouble * beginPointsX = (wxDouble *) bp; bp += 8;
- wxDouble * beginPointsY = (wxDouble *) bp; bp += 8;
- wxPoint2DDouble beginPoints = wxPoint2DDouble(*beginPointsX,*beginPointsY);
- wxDouble * endPointsX = (wxDouble *) bp; bp += 8;
- wxDouble * endPointsY = (wxDouble *) bp; bp += 8;
- wxPoint2DDouble endPoints = wxPoint2DDouble(*endPointsX,*endPointsY);
+ int * pointsLen = (int *) bp; bp += 4;
+ wxPoint2DDouble *points;
+ points = (wxPoint2DDouble *) driver_alloc(sizeof(wxPoint2DDouble) * *pointsLen);
+ for(int i=0; i < *pointsLen; i++) {
+ double x = * (double *) bp; bp += 8;
+ double y = * (double *) bp; bp += 8;
+ points[i] = wxPoint2DDouble(x,y);}
if(!This) throw wxe_badarg(0);
- This->StrokeLines((size_t) *n,&beginPoints,&endPoints);
+ This->StrokeLines(*pointsLen,points);
+ driver_free(points);
break;
}
#endif // wxUSE_GRAPHICS_CONTEXT
@@ -6565,12 +6553,6 @@ case wxGraphicsMatrix_Get: { // wxGraphicsMatrix::Get
rt.addTupleCount(6);
break;
}
-case wxGraphicsMatrix_GetNativeMatrix: { // wxGraphicsMatrix::GetNativeMatrix
- wxGraphicsMatrix *This = (wxGraphicsMatrix *) getPtr(bp,memenv); bp += 4;
- if(!This) throw wxe_badarg(0);
- This->GetNativeMatrix();
- break;
-}
case wxGraphicsMatrix_Invert: { // wxGraphicsMatrix::Invert
wxGraphicsMatrix *This = (wxGraphicsMatrix *) getPtr(bp,memenv); bp += 4;
if(!This) throw wxe_badarg(0);
@@ -15438,25 +15420,21 @@ case wxListCtrl_GetItemFont: { // wxListCtrl::GetItemFont
break;
}
case wxListCtrl_GetItemPosition: { // wxListCtrl::GetItemPosition
+ wxPoint pos;
wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
int * item = (int *) bp; bp += 4;
- int * posX = (int *) bp; bp += 4;
- int * posY = (int *) bp; bp += 4;
- wxPoint pos = wxPoint(*posX,*posY);
if(!This) throw wxe_badarg(0);
bool Result = This->GetItemPosition((long) *item,pos);
rt.addBool(Result);
+ rt.add(pos);
+ rt.addTupleCount(2);
break;
}
case wxListCtrl_GetItemRect: { // wxListCtrl::GetItemRect
+ wxRect rect;
int code=wxLIST_RECT_BOUNDS;
wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
int * item = (int *) bp; bp += 4;
- int * rectX = (int *) bp; bp += 4;
- int * rectY = (int *) bp; bp += 4;
- int * rectW = (int *) bp; bp += 4;
- int * rectH = (int *) bp; bp += 4;
- wxRect rect = wxRect(*rectX,*rectY,*rectW,*rectH);
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
code = (int)*(int *) bp; bp += 4;
@@ -15465,6 +15443,8 @@ case wxListCtrl_GetItemRect: { // wxListCtrl::GetItemRect
if(!This) throw wxe_badarg(0);
bool Result = This->GetItemRect((long) *item,rect,code);
rt.addBool(Result);
+ rt.add(rect);
+ rt.addTupleCount(2);
break;
}
case wxListCtrl_GetItemSpacing: { // wxListCtrl::GetItemSpacing
@@ -15546,16 +15526,14 @@ case wxListCtrl_GetViewRect: { // wxListCtrl::GetViewRect
break;
}
case wxListCtrl_HitTest: { // wxListCtrl::HitTest
- int flags;
wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
int * pointX = (int *) bp; bp += 4;
int * pointY = (int *) bp; bp += 4;
wxPoint point = wxPoint(*pointX,*pointY);
+ int * flags = (int *) bp; bp += 4;
if(!This) throw wxe_badarg(0);
- long Result = This->HitTest(point,flags);
+ long Result = This->HitTest(point,*flags);
rt.addInt(Result);
- rt.addInt(flags);
- rt.addTupleCount(2);
break;
}
case wxListCtrl_InsertColumn_2: { // wxListCtrl::InsertColumn
@@ -29383,6 +29361,13 @@ case wxStyledTextCtrl_SetEdgeColumn: { // wxStyledTextCtrl::SetEdgeColumn
This->SetEdgeColumn((int) *column);
break;
}
+case wxStyledTextCtrl_SetEdgeMode: { // wxStyledTextCtrl::SetEdgeMode
+ wxStyledTextCtrl *This = (wxStyledTextCtrl *) getPtr(bp,memenv); bp += 4;
+ int * mode = (int *) bp; bp += 4;
+ if(!This) throw wxe_badarg(0);
+ This->SetEdgeMode((int) *mode);
+ break;
+}
case wxStyledTextCtrl_GetEdgeMode: { // wxStyledTextCtrl::GetEdgeMode
wxStyledTextCtrl *This = (wxStyledTextCtrl *) getPtr(bp,memenv); bp += 4;
if(!This) throw wxe_badarg(0);
@@ -31160,6 +31145,56 @@ case wxSystemSettings_GetScreenType: { // wxSystemSettings::GetScreenType
rt.addInt(Result);
break;
}
+case wxSystemOptions_GetOption: { // wxSystemOptions::GetOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ wxString Result = wxSystemOptions::GetOption(name);
+ rt.add(Result);
+ break;
+}
+case wxSystemOptions_GetOptionInt: { // wxSystemOptions::GetOptionInt
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ int Result = wxSystemOptions::GetOptionInt(name);
+ rt.addInt(Result);
+ break;
+}
+case wxSystemOptions_HasOption: { // wxSystemOptions::HasOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ bool Result = wxSystemOptions::HasOption(name);
+ rt.addBool(Result);
+ break;
+}
+case wxSystemOptions_IsFalse: { // wxSystemOptions::IsFalse
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ bool Result = wxSystemOptions::IsFalse(name);
+ rt.addBool(Result);
+ break;
+}
+case wxSystemOptions_SetOption_2_1: { // wxSystemOptions::SetOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ int * valueLen = (int *) bp; bp += 4;
+ wxString value = wxString(bp, wxConvUTF8);
+ bp += *valueLen+((8-((4+ *valueLen) & 7)) & 7);
+ wxSystemOptions::SetOption(name,value);
+ break;
+}
+case wxSystemOptions_SetOption_2_0: { // wxSystemOptions::SetOption
+ int * nameLen = (int *) bp; bp += 4;
+ wxString name = wxString(bp, wxConvUTF8);
+ bp += *nameLen+((8-((4+ *nameLen) & 7)) & 7);
+ int * value = (int *) bp; bp += 4;
+ wxSystemOptions::SetOption(name,(int) *value);
+ break;
+}
case wxAuiNotebookEvent_SetSelection: { // wxAuiNotebookEvent::SetSelection
wxAuiNotebookEvent *This = (wxAuiNotebookEvent *) getPtr(bp,memenv); bp += 4;
int * s = (int *) bp; bp += 4;
@@ -31294,7 +31329,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto
}
case wxLogNull_new: { // wxLogNull::wxLogNull
wxLogNull * Result = new wxLogNull();
- newPtr((void *) Result, 224, memenv);
+ newPtr((void *) Result, 225, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxLogNull");
break;
}
@@ -31304,6 +31339,43 @@ case wxLogNull_destroy: { // wxLogNull::destroy
delete This;}
break;
}
+case wxTaskBarIcon_new: { // wxTaskBarIcon::wxTaskBarIcon
+ wxTaskBarIcon * Result = new EwxTaskBarIcon();
+ newPtr((void *) Result, 1, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxTaskBarIcon");
+ break;
+}
+case wxTaskBarIcon_PopupMenu: { // wxTaskBarIcon::PopupMenu
+ wxTaskBarIcon *This = (wxTaskBarIcon *) getPtr(bp,memenv); bp += 4;
+ wxMenu *menu = (wxMenu *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->PopupMenu(menu);
+ rt.addBool(Result);
+ break;
+}
+case wxTaskBarIcon_RemoveIcon: { // wxTaskBarIcon::RemoveIcon
+ wxTaskBarIcon *This = (wxTaskBarIcon *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->RemoveIcon();
+ rt.addBool(Result);
+ break;
+}
+case wxTaskBarIcon_SetIcon: { // wxTaskBarIcon::SetIcon
+ wxString tooltip= wxEmptyString;
+ wxTaskBarIcon *This = (wxTaskBarIcon *) getPtr(bp,memenv); bp += 4;
+ wxIcon *icon = (wxIcon *) getPtr(bp,memenv); bp += 4;
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+ int * tooltipLen = (int *) bp; bp += 4;
+ tooltip = wxString(bp, wxConvUTF8);
+ bp += *tooltipLen+((8-((0+ *tooltipLen) & 7)) & 7);
+ } break;
+ }};
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->SetIcon(*icon,tooltip);
+ rt.addBool(Result);
+ break;
+}
default: {
wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false); error.addAtom("_wxe_error_");
error.addInt((int) Ecmd.op);
@@ -31347,7 +31419,7 @@ void WxeApp::delete_object(void *ptr, wxeRefData *refd) {
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;
+ case 225: delete (wxLogNull *) ptr; break;
default: delete (wxObject *) ptr;
}}
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index be0481564f..b24becae06 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-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The 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,9 +57,11 @@
#include <wx/toolbook.h>
#include <wx/listbook.h>
#include <wx/treebook.h>
+#include <wx/taskbar.h>
#include <wx/html/htmlwin.h>
#include <wx/html/htmlcell.h>
#include <wx/filename.h>
+#include <wx/sysopt.h>
#ifndef wxICON_DEFAULT_BITMAP_TYPE
@@ -609,2734 +611,2745 @@
#define wxDC_GetCharHeight 663
#define wxDC_GetCharWidth 664
#define wxDC_GetClippingBox 665
-#define wxDC_GetFont 666
-#define wxDC_GetLayoutDirection 667
-#define wxDC_GetLogicalFunction 668
-#define wxDC_GetMapMode 669
-#define wxDC_GetMultiLineTextExtent_4 670
-#define wxDC_GetMultiLineTextExtent_1 671
-#define wxDC_GetPartialTextExtents 672
-#define wxDC_GetPen 673
-#define wxDC_GetPixel 674
-#define wxDC_GetPPI 675
-#define wxDC_GetSize 677
-#define wxDC_GetSizeMM 679
-#define wxDC_GetTextBackground 680
-#define wxDC_GetTextExtent_4 681
-#define wxDC_GetTextExtent_1 682
-#define wxDC_GetTextForeground 684
-#define wxDC_GetUserScale 685
-#define wxDC_GradientFillConcentric_3 686
-#define wxDC_GradientFillConcentric_4 687
-#define wxDC_GradientFillLinear 688
-#define wxDC_LogicalToDeviceX 689
-#define wxDC_LogicalToDeviceXRel 690
-#define wxDC_LogicalToDeviceY 691
-#define wxDC_LogicalToDeviceYRel 692
-#define wxDC_MaxX 693
-#define wxDC_MaxY 694
-#define wxDC_MinX 695
-#define wxDC_MinY 696
-#define wxDC_IsOk 697
-#define wxDC_ResetBoundingBox 698
-#define wxDC_SetAxisOrientation 699
-#define wxDC_SetBackground 700
-#define wxDC_SetBackgroundMode 701
-#define wxDC_SetBrush 702
-#define wxDC_SetClippingRegion_2 704
-#define wxDC_SetClippingRegion_1_1 705
-#define wxDC_SetClippingRegion_1_0 706
-#define wxDC_SetDeviceOrigin 707
-#define wxDC_SetFont 708
-#define wxDC_SetLayoutDirection 709
-#define wxDC_SetLogicalFunction 710
-#define wxDC_SetMapMode 711
-#define wxDC_SetPalette 712
-#define wxDC_SetPen 713
-#define wxDC_SetTextBackground 714
-#define wxDC_SetTextForeground 715
-#define wxDC_SetUserScale 716
-#define wxDC_StartDoc 717
-#define wxDC_StartPage 718
-#define wxMirrorDC_new 719
-#define wxMirrorDC_destroy 720
-#define wxScreenDC_new 721
-#define wxScreenDC_destruct 722
-#define wxPostScriptDC_new_0 723
-#define wxPostScriptDC_new_1 724
-#define wxPostScriptDC_destruct 725
-#define wxPostScriptDC_SetResolution 726
-#define wxPostScriptDC_GetResolution 727
-#define wxWindowDC_new_0 728
-#define wxWindowDC_new_1 729
-#define wxWindowDC_destruct 730
-#define wxClientDC_new_0 731
-#define wxClientDC_new_1 732
-#define wxClientDC_destroy 733
-#define wxPaintDC_new_0 734
-#define wxPaintDC_new_1 735
-#define wxPaintDC_destroy 736
-#define wxMemoryDC_new_1_0 738
-#define wxMemoryDC_new_1_1 739
-#define wxMemoryDC_new_0 740
-#define wxMemoryDC_destruct 742
-#define wxMemoryDC_SelectObject 743
-#define wxMemoryDC_SelectObjectAsSource 744
-#define wxBufferedDC_new_0 745
-#define wxBufferedDC_new_2 746
-#define wxBufferedDC_new_3 747
-#define wxBufferedDC_destruct 748
-#define wxBufferedDC_Init_2 749
-#define wxBufferedDC_Init_3 750
-#define wxBufferedPaintDC_new_3 751
-#define wxBufferedPaintDC_new_2 752
-#define wxBufferedPaintDC_destruct 753
-#define wxGraphicsObject_GetRenderer 754
-#define wxGraphicsObject_IsNull 755
-#define wxGraphicsContext_Create_1_1 756
-#define wxGraphicsContext_Create_1_0 757
-#define wxGraphicsContext_Create_0 758
-#define wxGraphicsContext_CreatePen 759
-#define wxGraphicsContext_CreateBrush 760
-#define wxGraphicsContext_CreateRadialGradientBrush 761
-#define wxGraphicsContext_CreateLinearGradientBrush 762
-#define wxGraphicsContext_CreateFont 763
-#define wxGraphicsContext_CreateMatrix 764
-#define wxGraphicsContext_CreatePath 765
-#define wxGraphicsContext_Clip_1 766
-#define wxGraphicsContext_Clip_4 767
-#define wxGraphicsContext_ResetClip 768
-#define wxGraphicsContext_DrawBitmap 769
-#define wxGraphicsContext_DrawEllipse 770
-#define wxGraphicsContext_DrawIcon 771
-#define wxGraphicsContext_DrawLines 772
-#define wxGraphicsContext_DrawPath 773
-#define wxGraphicsContext_DrawRectangle 774
-#define wxGraphicsContext_DrawRoundedRectangle 775
-#define wxGraphicsContext_DrawText_3 776
-#define wxGraphicsContext_DrawText_4_0 777
-#define wxGraphicsContext_DrawText_4_1 778
-#define wxGraphicsContext_DrawText_5 779
-#define wxGraphicsContext_FillPath 780
-#define wxGraphicsContext_StrokePath 781
-#define wxGraphicsContext_GetNativeContext 782
-#define wxGraphicsContext_GetPartialTextExtents 783
-#define wxGraphicsContext_GetTextExtent 784
-#define wxGraphicsContext_Rotate 785
-#define wxGraphicsContext_Scale 786
-#define wxGraphicsContext_Translate 787
-#define wxGraphicsContext_GetTransform 788
-#define wxGraphicsContext_SetTransform 789
-#define wxGraphicsContext_ConcatTransform 790
-#define wxGraphicsContext_SetBrush_1_1 791
-#define wxGraphicsContext_SetBrush_1_0 792
-#define wxGraphicsContext_SetFont_1 793
-#define wxGraphicsContext_SetFont_2 794
-#define wxGraphicsContext_SetPen_1_0 795
-#define wxGraphicsContext_SetPen_1_1 796
-#define wxGraphicsContext_StrokeLine 797
-#define wxGraphicsContext_StrokeLines_2 798
-#define wxGraphicsContext_StrokeLines_3 799
-#define wxGraphicsMatrix_Concat 800
-#define wxGraphicsMatrix_Get 802
-#define wxGraphicsMatrix_GetNativeMatrix 803
-#define wxGraphicsMatrix_Invert 804
-#define wxGraphicsMatrix_IsEqual 805
-#define wxGraphicsMatrix_IsIdentity 807
-#define wxGraphicsMatrix_Rotate 808
-#define wxGraphicsMatrix_Scale 809
-#define wxGraphicsMatrix_Translate 810
-#define wxGraphicsMatrix_Set 811
-#define wxGraphicsMatrix_TransformPoint 812
-#define wxGraphicsMatrix_TransformDistance 813
-#define wxGraphicsPath_MoveToPoint_2 814
-#define wxGraphicsPath_MoveToPoint_1 815
-#define wxGraphicsPath_AddArc_6 816
-#define wxGraphicsPath_AddArc_5 817
-#define wxGraphicsPath_AddArcToPoint 818
-#define wxGraphicsPath_AddCircle 819
-#define wxGraphicsPath_AddCurveToPoint_6 820
-#define wxGraphicsPath_AddCurveToPoint_3 821
-#define wxGraphicsPath_AddEllipse 822
-#define wxGraphicsPath_AddLineToPoint_2 823
-#define wxGraphicsPath_AddLineToPoint_1 824
-#define wxGraphicsPath_AddPath 825
-#define wxGraphicsPath_AddQuadCurveToPoint 826
-#define wxGraphicsPath_AddRectangle 827
-#define wxGraphicsPath_AddRoundedRectangle 828
-#define wxGraphicsPath_CloseSubpath 829
-#define wxGraphicsPath_Contains_3 830
-#define wxGraphicsPath_Contains_2 831
-#define wxGraphicsPath_GetBox 833
-#define wxGraphicsPath_GetCurrentPoint 835
-#define wxGraphicsPath_Transform 836
-#define wxGraphicsRenderer_GetDefaultRenderer 837
-#define wxGraphicsRenderer_CreateContext_1_1 838
-#define wxGraphicsRenderer_CreateContext_1_0 839
-#define wxGraphicsRenderer_CreatePen 840
-#define wxGraphicsRenderer_CreateBrush 841
-#define wxGraphicsRenderer_CreateLinearGradientBrush 842
-#define wxGraphicsRenderer_CreateRadialGradientBrush 843
-#define wxGraphicsRenderer_CreateFont 844
-#define wxGraphicsRenderer_CreateMatrix 845
-#define wxGraphicsRenderer_CreatePath 846
-#define wxMenuBar_new_1 848
-#define wxMenuBar_new_0 850
-#define wxMenuBar_destruct 852
-#define wxMenuBar_Append 853
-#define wxMenuBar_Check 854
-#define wxMenuBar_Enable_2 855
-#define wxMenuBar_Enable_1 856
-#define wxMenuBar_EnableTop 857
-#define wxMenuBar_FindMenu 858
-#define wxMenuBar_FindMenuItem 859
-#define wxMenuBar_FindItem 860
-#define wxMenuBar_GetHelpString 861
-#define wxMenuBar_GetLabel_1 862
-#define wxMenuBar_GetLabel_0 863
-#define wxMenuBar_GetLabelTop 864
-#define wxMenuBar_GetMenu 865
-#define wxMenuBar_GetMenuCount 866
-#define wxMenuBar_Insert 867
-#define wxMenuBar_IsChecked 868
-#define wxMenuBar_IsEnabled_1 869
-#define wxMenuBar_IsEnabled_0 870
-#define wxMenuBar_Remove 871
-#define wxMenuBar_Replace 872
-#define wxMenuBar_SetHelpString 873
-#define wxMenuBar_SetLabel_2 874
-#define wxMenuBar_SetLabel_1 875
-#define wxMenuBar_SetLabelTop 876
-#define wxControl_GetLabel 877
-#define wxControl_SetLabel 878
-#define wxControlWithItems_Append_1 879
-#define wxControlWithItems_Append_2 880
-#define wxControlWithItems_appendStrings_1 881
-#define wxControlWithItems_Clear 882
-#define wxControlWithItems_Delete 883
-#define wxControlWithItems_FindString 884
-#define wxControlWithItems_getClientData 885
-#define wxControlWithItems_setClientData 886
-#define wxControlWithItems_GetCount 887
-#define wxControlWithItems_GetSelection 888
-#define wxControlWithItems_GetString 889
-#define wxControlWithItems_GetStringSelection 890
-#define wxControlWithItems_Insert_2 891
-#define wxControlWithItems_Insert_3 892
-#define wxControlWithItems_IsEmpty 893
-#define wxControlWithItems_Select 894
-#define wxControlWithItems_SetSelection 895
-#define wxControlWithItems_SetString 896
-#define wxControlWithItems_SetStringSelection 897
-#define wxMenu_new_2 900
-#define wxMenu_new_1 901
-#define wxMenu_destruct 903
-#define wxMenu_Append_3 904
-#define wxMenu_Append_1 905
-#define wxMenu_Append_4_0 906
-#define wxMenu_Append_4_1 907
-#define wxMenu_AppendCheckItem 908
-#define wxMenu_AppendRadioItem 909
-#define wxMenu_AppendSeparator 910
-#define wxMenu_Break 911
-#define wxMenu_Check 912
-#define wxMenu_Delete_1_0 913
-#define wxMenu_Delete_1_1 914
-#define wxMenu_Destroy_1_0 915
-#define wxMenu_Destroy_1_1 916
-#define wxMenu_Enable 917
-#define wxMenu_FindItem_1 918
-#define wxMenu_FindItem_2 919
-#define wxMenu_FindItemByPosition 920
-#define wxMenu_GetHelpString 921
-#define wxMenu_GetLabel 922
-#define wxMenu_GetMenuItemCount 923
-#define wxMenu_GetMenuItems 924
-#define wxMenu_GetTitle 926
-#define wxMenu_Insert_2 927
-#define wxMenu_Insert_3 928
-#define wxMenu_Insert_5_1 929
-#define wxMenu_Insert_5_0 930
-#define wxMenu_InsertCheckItem 931
-#define wxMenu_InsertRadioItem 932
-#define wxMenu_InsertSeparator 933
-#define wxMenu_IsChecked 934
-#define wxMenu_IsEnabled 935
-#define wxMenu_Prepend_1 936
-#define wxMenu_Prepend_2 937
-#define wxMenu_Prepend_4_1 938
-#define wxMenu_Prepend_4_0 939
-#define wxMenu_PrependCheckItem 940
-#define wxMenu_PrependRadioItem 941
-#define wxMenu_PrependSeparator 942
-#define wxMenu_Remove_1_0 943
-#define wxMenu_Remove_1_1 944
-#define wxMenu_SetHelpString 945
-#define wxMenu_SetLabel 946
-#define wxMenu_SetTitle 947
-#define wxMenuItem_new 948
-#define wxMenuItem_destruct 950
-#define wxMenuItem_Check 951
-#define wxMenuItem_Enable 952
-#define wxMenuItem_GetBitmap 953
-#define wxMenuItem_GetHelp 954
-#define wxMenuItem_GetId 955
-#define wxMenuItem_GetKind 956
-#define wxMenuItem_GetLabel 957
-#define wxMenuItem_GetLabelFromText 958
-#define wxMenuItem_GetMenu 959
-#define wxMenuItem_GetText 960
-#define wxMenuItem_GetSubMenu 961
-#define wxMenuItem_IsCheckable 962
-#define wxMenuItem_IsChecked 963
-#define wxMenuItem_IsEnabled 964
-#define wxMenuItem_IsSeparator 965
-#define wxMenuItem_IsSubMenu 966
-#define wxMenuItem_SetBitmap 967
-#define wxMenuItem_SetHelp 968
-#define wxMenuItem_SetMenu 969
-#define wxMenuItem_SetSubMenu 970
-#define wxMenuItem_SetText 971
-#define wxToolBar_AddControl 972
-#define wxToolBar_AddSeparator 973
-#define wxToolBar_AddTool_5 974
-#define wxToolBar_AddTool_4_0 975
-#define wxToolBar_AddTool_1 976
-#define wxToolBar_AddTool_4_1 977
-#define wxToolBar_AddTool_3 978
-#define wxToolBar_AddTool_6 979
-#define wxToolBar_AddCheckTool 980
-#define wxToolBar_AddRadioTool 981
-#define wxToolBar_DeleteTool 982
-#define wxToolBar_DeleteToolByPos 983
-#define wxToolBar_EnableTool 984
-#define wxToolBar_FindById 985
-#define wxToolBar_FindControl 986
-#define wxToolBar_FindToolForPosition 987
-#define wxToolBar_GetToolSize 988
-#define wxToolBar_GetToolBitmapSize 989
-#define wxToolBar_GetMargins 990
-#define wxToolBar_GetToolEnabled 991
-#define wxToolBar_GetToolLongHelp 992
-#define wxToolBar_GetToolPacking 993
-#define wxToolBar_GetToolPos 994
-#define wxToolBar_GetToolSeparation 995
-#define wxToolBar_GetToolShortHelp 996
-#define wxToolBar_GetToolState 997
-#define wxToolBar_InsertControl 998
-#define wxToolBar_InsertSeparator 999
-#define wxToolBar_InsertTool_5 1000
-#define wxToolBar_InsertTool_2 1001
-#define wxToolBar_InsertTool_4 1002
-#define wxToolBar_Realize 1003
-#define wxToolBar_RemoveTool 1004
-#define wxToolBar_SetMargins 1005
-#define wxToolBar_SetToolBitmapSize 1006
-#define wxToolBar_SetToolLongHelp 1007
-#define wxToolBar_SetToolPacking 1008
-#define wxToolBar_SetToolShortHelp 1009
-#define wxToolBar_SetToolSeparation 1010
-#define wxToolBar_ToggleTool 1011
-#define wxStatusBar_new_0 1013
-#define wxStatusBar_new_2 1014
-#define wxStatusBar_destruct 1016
-#define wxStatusBar_Create 1017
-#define wxStatusBar_GetFieldRect 1018
-#define wxStatusBar_GetFieldsCount 1019
-#define wxStatusBar_GetStatusText 1020
-#define wxStatusBar_PopStatusText 1021
-#define wxStatusBar_PushStatusText 1022
-#define wxStatusBar_SetFieldsCount 1023
-#define wxStatusBar_SetMinHeight 1024
-#define wxStatusBar_SetStatusText 1025
-#define wxStatusBar_SetStatusWidths 1026
-#define wxStatusBar_SetStatusStyles 1027
-#define wxBitmap_new_0 1028
-#define wxBitmap_new_3 1029
-#define wxBitmap_new_4 1030
-#define wxBitmap_new_2_0 1031
-#define wxBitmap_new_2_1 1032
-#define wxBitmap_destruct 1033
-#define wxBitmap_ConvertToImage 1034
-#define wxBitmap_CopyFromIcon 1035
-#define wxBitmap_Create 1036
-#define wxBitmap_GetDepth 1037
-#define wxBitmap_GetHeight 1038
-#define wxBitmap_GetPalette 1039
-#define wxBitmap_GetMask 1040
-#define wxBitmap_GetWidth 1041
-#define wxBitmap_GetSubBitmap 1042
-#define wxBitmap_LoadFile 1043
-#define wxBitmap_Ok 1044
-#define wxBitmap_SaveFile 1045
-#define wxBitmap_SetDepth 1046
-#define wxBitmap_SetHeight 1047
-#define wxBitmap_SetMask 1048
-#define wxBitmap_SetPalette 1049
-#define wxBitmap_SetWidth 1050
-#define wxIcon_new_0 1051
-#define wxIcon_new_2 1052
-#define wxIcon_new_1 1053
-#define wxIcon_CopyFromBitmap 1054
-#define wxIcon_destroy 1055
-#define wxIconBundle_new_0 1056
-#define wxIconBundle_new_2 1057
-#define wxIconBundle_new_1_0 1058
-#define wxIconBundle_new_1_1 1059
-#define wxIconBundle_destruct 1060
-#define wxIconBundle_AddIcon_2 1061
-#define wxIconBundle_AddIcon_1 1062
-#define wxIconBundle_GetIcon_1_1 1063
-#define wxIconBundle_GetIcon_1_0 1064
-#define wxCursor_new_0 1065
-#define wxCursor_new_1_0 1066
-#define wxCursor_new_1_1 1067
-#define wxCursor_new_4 1068
-#define wxCursor_destruct 1069
-#define wxCursor_Ok 1070
-#define wxMask_new_0 1071
-#define wxMask_new_2_1 1072
-#define wxMask_new_2_0 1073
-#define wxMask_new_1 1074
-#define wxMask_destruct 1075
-#define wxMask_Create_2_1 1076
-#define wxMask_Create_2_0 1077
-#define wxMask_Create_1 1078
-#define wxImage_new_0 1079
-#define wxImage_new_3_0 1080
-#define wxImage_new_4 1081
-#define wxImage_new_5 1082
-#define wxImage_new_2 1083
-#define wxImage_new_3_1 1084
-#define wxImage_Blur 1085
-#define wxImage_BlurHorizontal 1086
-#define wxImage_BlurVertical 1087
-#define wxImage_ConvertAlphaToMask 1088
-#define wxImage_ConvertToGreyscale 1089
-#define wxImage_ConvertToMono 1090
-#define wxImage_Copy 1091
-#define wxImage_Create_3 1092
-#define wxImage_Create_4 1093
-#define wxImage_Create_5 1094
-#define wxImage_Destroy 1095
-#define wxImage_FindFirstUnusedColour 1096
-#define wxImage_GetImageExtWildcard 1097
-#define wxImage_GetAlpha_2 1098
-#define wxImage_GetAlpha_0 1099
-#define wxImage_GetBlue 1100
-#define wxImage_GetData 1101
-#define wxImage_GetGreen 1102
-#define wxImage_GetImageCount 1103
-#define wxImage_GetHeight 1104
-#define wxImage_GetMaskBlue 1105
-#define wxImage_GetMaskGreen 1106
-#define wxImage_GetMaskRed 1107
-#define wxImage_GetOrFindMaskColour 1108
-#define wxImage_GetPalette 1109
-#define wxImage_GetRed 1110
-#define wxImage_GetSubImage 1111
-#define wxImage_GetWidth 1112
-#define wxImage_HasAlpha 1113
-#define wxImage_HasMask 1114
-#define wxImage_GetOption 1115
-#define wxImage_GetOptionInt 1116
-#define wxImage_HasOption 1117
-#define wxImage_InitAlpha 1118
-#define wxImage_InitStandardHandlers 1119
-#define wxImage_IsTransparent 1120
-#define wxImage_LoadFile_2 1121
-#define wxImage_LoadFile_3 1122
-#define wxImage_Ok 1123
-#define wxImage_RemoveHandler 1124
-#define wxImage_Mirror 1125
-#define wxImage_Replace 1126
-#define wxImage_Rescale 1127
-#define wxImage_Resize 1128
-#define wxImage_Rotate 1129
-#define wxImage_RotateHue 1130
-#define wxImage_Rotate90 1131
-#define wxImage_SaveFile_1 1132
-#define wxImage_SaveFile_2_0 1133
-#define wxImage_SaveFile_2_1 1134
-#define wxImage_Scale 1135
-#define wxImage_Size 1136
-#define wxImage_SetAlpha_3 1137
-#define wxImage_SetAlpha_2 1138
-#define wxImage_SetData_2 1139
-#define wxImage_SetData_4 1140
-#define wxImage_SetMask 1141
-#define wxImage_SetMaskColour 1142
-#define wxImage_SetMaskFromImage 1143
-#define wxImage_SetOption_2_1 1144
-#define wxImage_SetOption_2_0 1145
-#define wxImage_SetPalette 1146
-#define wxImage_SetRGB_5 1147
-#define wxImage_SetRGB_4 1148
-#define wxImage_destroy 1149
-#define wxBrush_new_0 1150
-#define wxBrush_new_2 1151
-#define wxBrush_new_1 1152
-#define wxBrush_destruct 1154
-#define wxBrush_GetColour 1155
-#define wxBrush_GetStipple 1156
-#define wxBrush_GetStyle 1157
-#define wxBrush_IsHatch 1158
-#define wxBrush_IsOk 1159
-#define wxBrush_SetColour_1 1160
-#define wxBrush_SetColour_3 1161
-#define wxBrush_SetStipple 1162
-#define wxBrush_SetStyle 1163
-#define wxPen_new_0 1164
-#define wxPen_new_2 1165
-#define wxPen_destruct 1166
-#define wxPen_GetCap 1167
-#define wxPen_GetColour 1168
-#define wxPen_GetJoin 1169
-#define wxPen_GetStyle 1170
-#define wxPen_GetWidth 1171
-#define wxPen_IsOk 1172
-#define wxPen_SetCap 1173
-#define wxPen_SetColour_1 1174
-#define wxPen_SetColour_3 1175
-#define wxPen_SetJoin 1176
-#define wxPen_SetStyle 1177
-#define wxPen_SetWidth 1178
-#define wxRegion_new_0 1179
-#define wxRegion_new_4 1180
-#define wxRegion_new_2 1181
-#define wxRegion_new_1_1 1182
-#define wxRegion_new_1_0 1184
-#define wxRegion_destruct 1186
-#define wxRegion_Clear 1187
-#define wxRegion_Contains_2 1188
-#define wxRegion_Contains_1_0 1189
-#define wxRegion_Contains_4 1190
-#define wxRegion_Contains_1_1 1191
-#define wxRegion_ConvertToBitmap 1192
-#define wxRegion_GetBox 1193
-#define wxRegion_Intersect_4 1194
-#define wxRegion_Intersect_1_1 1195
-#define wxRegion_Intersect_1_0 1196
-#define wxRegion_IsEmpty 1197
-#define wxRegion_Subtract_4 1198
-#define wxRegion_Subtract_1_1 1199
-#define wxRegion_Subtract_1_0 1200
-#define wxRegion_Offset_2 1201
-#define wxRegion_Offset_1 1202
-#define wxRegion_Union_4 1203
-#define wxRegion_Union_1_2 1204
-#define wxRegion_Union_1_1 1205
-#define wxRegion_Union_1_0 1206
-#define wxRegion_Union_3 1207
-#define wxRegion_Xor_4 1208
-#define wxRegion_Xor_1_1 1209
-#define wxRegion_Xor_1_0 1210
-#define wxAcceleratorTable_new_0 1211
-#define wxAcceleratorTable_new_2 1212
-#define wxAcceleratorTable_destruct 1213
-#define wxAcceleratorTable_Ok 1214
-#define wxAcceleratorEntry_new_1_0 1215
-#define wxAcceleratorEntry_new_1_1 1216
-#define wxAcceleratorEntry_GetCommand 1217
-#define wxAcceleratorEntry_GetFlags 1218
-#define wxAcceleratorEntry_GetKeyCode 1219
-#define wxAcceleratorEntry_Set 1220
-#define wxAcceleratorEntry_destroy 1221
-#define wxCaret_new_3 1226
-#define wxCaret_new_2 1227
-#define wxCaret_destruct 1229
-#define wxCaret_Create_3 1230
-#define wxCaret_Create_2 1231
-#define wxCaret_GetBlinkTime 1232
-#define wxCaret_GetPosition 1234
-#define wxCaret_GetSize 1236
-#define wxCaret_GetWindow 1237
-#define wxCaret_Hide 1238
-#define wxCaret_IsOk 1239
-#define wxCaret_IsVisible 1240
-#define wxCaret_Move_2 1241
-#define wxCaret_Move_1 1242
-#define wxCaret_SetBlinkTime 1243
-#define wxCaret_SetSize_2 1244
-#define wxCaret_SetSize_1 1245
-#define wxCaret_Show 1246
-#define wxSizer_Add_2_1 1247
-#define wxSizer_Add_2_0 1248
-#define wxSizer_Add_3 1249
-#define wxSizer_Add_2_3 1250
-#define wxSizer_Add_2_2 1251
-#define wxSizer_AddSpacer 1252
-#define wxSizer_AddStretchSpacer 1253
-#define wxSizer_CalcMin 1254
-#define wxSizer_Clear 1255
-#define wxSizer_Detach_1_2 1256
-#define wxSizer_Detach_1_1 1257
-#define wxSizer_Detach_1_0 1258
-#define wxSizer_Fit 1259
-#define wxSizer_FitInside 1260
-#define wxSizer_GetChildren 1261
-#define wxSizer_GetItem_2_1 1262
-#define wxSizer_GetItem_2_0 1263
-#define wxSizer_GetItem_1 1264
-#define wxSizer_GetSize 1265
-#define wxSizer_GetPosition 1266
-#define wxSizer_GetMinSize 1267
-#define wxSizer_Hide_2_0 1268
-#define wxSizer_Hide_2_1 1269
-#define wxSizer_Hide_1 1270
-#define wxSizer_Insert_3_1 1271
-#define wxSizer_Insert_3_0 1272
-#define wxSizer_Insert_4 1273
-#define wxSizer_Insert_3_3 1274
-#define wxSizer_Insert_3_2 1275
-#define wxSizer_Insert_2 1276
-#define wxSizer_InsertSpacer 1277
-#define wxSizer_InsertStretchSpacer 1278
-#define wxSizer_IsShown_1_2 1279
-#define wxSizer_IsShown_1_1 1280
-#define wxSizer_IsShown_1_0 1281
-#define wxSizer_Layout 1282
-#define wxSizer_Prepend_2_1 1283
-#define wxSizer_Prepend_2_0 1284
-#define wxSizer_Prepend_3 1285
-#define wxSizer_Prepend_2_3 1286
-#define wxSizer_Prepend_2_2 1287
-#define wxSizer_Prepend_1 1288
-#define wxSizer_PrependSpacer 1289
-#define wxSizer_PrependStretchSpacer 1290
-#define wxSizer_RecalcSizes 1291
-#define wxSizer_Remove_1_1 1292
-#define wxSizer_Remove_1_0 1293
-#define wxSizer_Replace_3_1 1294
-#define wxSizer_Replace_3_0 1295
-#define wxSizer_Replace_2 1296
-#define wxSizer_SetDimension 1297
-#define wxSizer_SetMinSize_2 1298
-#define wxSizer_SetMinSize_1 1299
-#define wxSizer_SetItemMinSize_3_2 1300
-#define wxSizer_SetItemMinSize_2_2 1301
-#define wxSizer_SetItemMinSize_3_1 1302
-#define wxSizer_SetItemMinSize_2_1 1303
-#define wxSizer_SetItemMinSize_3_0 1304
-#define wxSizer_SetItemMinSize_2_0 1305
-#define wxSizer_SetSizeHints 1306
-#define wxSizer_SetVirtualSizeHints 1307
-#define wxSizer_Show_2_2 1308
-#define wxSizer_Show_2_1 1309
-#define wxSizer_Show_2_0 1310
-#define wxSizer_Show_1 1311
-#define wxSizerFlags_new 1312
-#define wxSizerFlags_Align 1313
-#define wxSizerFlags_Border_2 1314
-#define wxSizerFlags_Border_1 1315
-#define wxSizerFlags_Center 1316
-#define wxSizerFlags_Centre 1317
-#define wxSizerFlags_Expand 1318
-#define wxSizerFlags_Left 1319
-#define wxSizerFlags_Proportion 1320
-#define wxSizerFlags_Right 1321
-#define wxSizerFlags_destroy 1322
-#define wxSizerItem_new_5_1 1323
-#define wxSizerItem_new_2_1 1324
-#define wxSizerItem_new_5_0 1325
-#define wxSizerItem_new_2_0 1326
-#define wxSizerItem_new_6 1327
-#define wxSizerItem_new_3 1328
-#define wxSizerItem_new_0 1329
-#define wxSizerItem_destruct 1330
-#define wxSizerItem_CalcMin 1331
-#define wxSizerItem_DeleteWindows 1332
-#define wxSizerItem_DetachSizer 1333
-#define wxSizerItem_GetBorder 1334
-#define wxSizerItem_GetFlag 1335
-#define wxSizerItem_GetMinSize 1336
-#define wxSizerItem_GetPosition 1337
-#define wxSizerItem_GetProportion 1338
-#define wxSizerItem_GetRatio 1339
-#define wxSizerItem_GetRect 1340
-#define wxSizerItem_GetSize 1341
-#define wxSizerItem_GetSizer 1342
-#define wxSizerItem_GetSpacer 1343
-#define wxSizerItem_GetUserData 1344
-#define wxSizerItem_GetWindow 1345
-#define wxSizerItem_IsSizer 1346
-#define wxSizerItem_IsShown 1347
-#define wxSizerItem_IsSpacer 1348
-#define wxSizerItem_IsWindow 1349
-#define wxSizerItem_SetBorder 1350
-#define wxSizerItem_SetDimension 1351
-#define wxSizerItem_SetFlag 1352
-#define wxSizerItem_SetInitSize 1353
-#define wxSizerItem_SetMinSize_1 1354
-#define wxSizerItem_SetMinSize_2 1355
-#define wxSizerItem_SetProportion 1356
-#define wxSizerItem_SetRatio_2 1357
-#define wxSizerItem_SetRatio_1_1 1358
-#define wxSizerItem_SetRatio_1_0 1359
-#define wxSizerItem_SetSizer 1360
-#define wxSizerItem_SetSpacer_1 1361
-#define wxSizerItem_SetSpacer_2 1362
-#define wxSizerItem_SetWindow 1363
-#define wxSizerItem_Show 1364
-#define wxBoxSizer_new 1365
-#define wxBoxSizer_GetOrientation 1366
-#define wxBoxSizer_destroy 1367
-#define wxStaticBoxSizer_new_2 1368
-#define wxStaticBoxSizer_new_3 1369
-#define wxStaticBoxSizer_GetStaticBox 1370
-#define wxStaticBoxSizer_destroy 1371
-#define wxGridSizer_new_4 1372
-#define wxGridSizer_new_2 1373
-#define wxGridSizer_GetCols 1374
-#define wxGridSizer_GetHGap 1375
-#define wxGridSizer_GetRows 1376
-#define wxGridSizer_GetVGap 1377
-#define wxGridSizer_SetCols 1378
-#define wxGridSizer_SetHGap 1379
-#define wxGridSizer_SetRows 1380
-#define wxGridSizer_SetVGap 1381
-#define wxGridSizer_destroy 1382
-#define wxFlexGridSizer_new_4 1383
-#define wxFlexGridSizer_new_2 1384
-#define wxFlexGridSizer_AddGrowableCol 1385
-#define wxFlexGridSizer_AddGrowableRow 1386
-#define wxFlexGridSizer_GetFlexibleDirection 1387
-#define wxFlexGridSizer_GetNonFlexibleGrowMode 1388
-#define wxFlexGridSizer_RemoveGrowableCol 1389
-#define wxFlexGridSizer_RemoveGrowableRow 1390
-#define wxFlexGridSizer_SetFlexibleDirection 1391
-#define wxFlexGridSizer_SetNonFlexibleGrowMode 1392
-#define wxFlexGridSizer_destroy 1393
-#define wxGridBagSizer_new 1394
-#define wxGridBagSizer_Add_3_2 1395
-#define wxGridBagSizer_Add_3_1 1396
-#define wxGridBagSizer_Add_4 1397
-#define wxGridBagSizer_Add_1_0 1398
-#define wxGridBagSizer_Add_2_1 1399
-#define wxGridBagSizer_Add_2_0 1400
-#define wxGridBagSizer_Add_3_0 1401
-#define wxGridBagSizer_Add_1_1 1402
-#define wxGridBagSizer_CalcMin 1403
-#define wxGridBagSizer_CheckForIntersection_2 1404
-#define wxGridBagSizer_CheckForIntersection_3 1405
-#define wxGridBagSizer_FindItem_1_1 1406
-#define wxGridBagSizer_FindItem_1_0 1407
-#define wxGridBagSizer_FindItemAtPoint 1408
-#define wxGridBagSizer_FindItemAtPosition 1409
-#define wxGridBagSizer_FindItemWithData 1410
-#define wxGridBagSizer_GetCellSize 1411
-#define wxGridBagSizer_GetEmptyCellSize 1412
-#define wxGridBagSizer_GetItemPosition_1_2 1413
-#define wxGridBagSizer_GetItemPosition_1_1 1414
-#define wxGridBagSizer_GetItemPosition_1_0 1415
-#define wxGridBagSizer_GetItemSpan_1_2 1416
-#define wxGridBagSizer_GetItemSpan_1_1 1417
-#define wxGridBagSizer_GetItemSpan_1_0 1418
-#define wxGridBagSizer_SetEmptyCellSize 1419
-#define wxGridBagSizer_SetItemPosition_2_2 1420
-#define wxGridBagSizer_SetItemPosition_2_1 1421
-#define wxGridBagSizer_SetItemPosition_2_0 1422
-#define wxGridBagSizer_SetItemSpan_2_2 1423
-#define wxGridBagSizer_SetItemSpan_2_1 1424
-#define wxGridBagSizer_SetItemSpan_2_0 1425
-#define wxGridBagSizer_destroy 1426
-#define wxStdDialogButtonSizer_new 1427
-#define wxStdDialogButtonSizer_AddButton 1428
-#define wxStdDialogButtonSizer_Realize 1429
-#define wxStdDialogButtonSizer_SetAffirmativeButton 1430
-#define wxStdDialogButtonSizer_SetCancelButton 1431
-#define wxStdDialogButtonSizer_SetNegativeButton 1432
-#define wxStdDialogButtonSizer_destroy 1433
-#define wxFont_new_0 1434
-#define wxFont_new_1 1435
-#define wxFont_new_5 1436
-#define wxFont_destruct 1438
-#define wxFont_IsFixedWidth 1439
-#define wxFont_GetDefaultEncoding 1440
-#define wxFont_GetFaceName 1441
-#define wxFont_GetFamily 1442
-#define wxFont_GetNativeFontInfoDesc 1443
-#define wxFont_GetNativeFontInfoUserDesc 1444
-#define wxFont_GetPointSize 1445
-#define wxFont_GetStyle 1446
-#define wxFont_GetUnderlined 1447
-#define wxFont_GetWeight 1448
-#define wxFont_Ok 1449
-#define wxFont_SetDefaultEncoding 1450
-#define wxFont_SetFaceName 1451
-#define wxFont_SetFamily 1452
-#define wxFont_SetPointSize 1453
-#define wxFont_SetStyle 1454
-#define wxFont_SetUnderlined 1455
-#define wxFont_SetWeight 1456
-#define wxToolTip_Enable 1457
-#define wxToolTip_SetDelay 1458
-#define wxToolTip_new 1459
-#define wxToolTip_SetTip 1460
-#define wxToolTip_GetTip 1461
-#define wxToolTip_GetWindow 1462
-#define wxToolTip_destroy 1463
-#define wxButton_new_3 1465
-#define wxButton_new_0 1466
-#define wxButton_destruct 1467
-#define wxButton_Create 1468
-#define wxButton_GetDefaultSize 1469
-#define wxButton_SetDefault 1470
-#define wxButton_SetLabel 1471
-#define wxBitmapButton_new_4 1473
-#define wxBitmapButton_new_0 1474
-#define wxBitmapButton_Create 1475
-#define wxBitmapButton_GetBitmapDisabled 1476
-#define wxBitmapButton_GetBitmapFocus 1478
-#define wxBitmapButton_GetBitmapLabel 1480
-#define wxBitmapButton_GetBitmapSelected 1482
-#define wxBitmapButton_SetBitmapDisabled 1484
-#define wxBitmapButton_SetBitmapFocus 1485
-#define wxBitmapButton_SetBitmapLabel 1486
-#define wxBitmapButton_SetBitmapSelected 1487
-#define wxBitmapButton_destroy 1488
-#define wxToggleButton_new_0 1489
-#define wxToggleButton_new_4 1490
-#define wxToggleButton_Create 1491
-#define wxToggleButton_GetValue 1492
-#define wxToggleButton_SetValue 1493
-#define wxToggleButton_destroy 1494
-#define wxCalendarCtrl_new_0 1495
-#define wxCalendarCtrl_new_3 1496
-#define wxCalendarCtrl_Create 1497
-#define wxCalendarCtrl_destruct 1498
-#define wxCalendarCtrl_SetDate 1499
-#define wxCalendarCtrl_GetDate 1500
-#define wxCalendarCtrl_EnableYearChange 1501
-#define wxCalendarCtrl_EnableMonthChange 1502
-#define wxCalendarCtrl_EnableHolidayDisplay 1503
-#define wxCalendarCtrl_SetHeaderColours 1504
-#define wxCalendarCtrl_GetHeaderColourFg 1505
-#define wxCalendarCtrl_GetHeaderColourBg 1506
-#define wxCalendarCtrl_SetHighlightColours 1507
-#define wxCalendarCtrl_GetHighlightColourFg 1508
-#define wxCalendarCtrl_GetHighlightColourBg 1509
-#define wxCalendarCtrl_SetHolidayColours 1510
-#define wxCalendarCtrl_GetHolidayColourFg 1511
-#define wxCalendarCtrl_GetHolidayColourBg 1512
-#define wxCalendarCtrl_GetAttr 1513
-#define wxCalendarCtrl_SetAttr 1514
-#define wxCalendarCtrl_SetHoliday 1515
-#define wxCalendarCtrl_ResetAttr 1516
-#define wxCalendarCtrl_HitTest 1517
-#define wxCalendarDateAttr_new_0 1518
-#define wxCalendarDateAttr_new_2_1 1519
-#define wxCalendarDateAttr_new_2_0 1520
-#define wxCalendarDateAttr_SetTextColour 1521
-#define wxCalendarDateAttr_SetBackgroundColour 1522
-#define wxCalendarDateAttr_SetBorderColour 1523
-#define wxCalendarDateAttr_SetFont 1524
-#define wxCalendarDateAttr_SetBorder 1525
-#define wxCalendarDateAttr_SetHoliday 1526
-#define wxCalendarDateAttr_HasTextColour 1527
-#define wxCalendarDateAttr_HasBackgroundColour 1528
-#define wxCalendarDateAttr_HasBorderColour 1529
-#define wxCalendarDateAttr_HasFont 1530
-#define wxCalendarDateAttr_HasBorder 1531
-#define wxCalendarDateAttr_IsHoliday 1532
-#define wxCalendarDateAttr_GetTextColour 1533
-#define wxCalendarDateAttr_GetBackgroundColour 1534
-#define wxCalendarDateAttr_GetBorderColour 1535
-#define wxCalendarDateAttr_GetFont 1536
-#define wxCalendarDateAttr_GetBorder 1537
-#define wxCalendarDateAttr_destroy 1538
-#define wxCheckBox_new_4 1540
-#define wxCheckBox_new_0 1541
-#define wxCheckBox_Create 1542
-#define wxCheckBox_GetValue 1543
-#define wxCheckBox_Get3StateValue 1544
-#define wxCheckBox_Is3rdStateAllowedForUser 1545
-#define wxCheckBox_Is3State 1546
-#define wxCheckBox_IsChecked 1547
-#define wxCheckBox_SetValue 1548
-#define wxCheckBox_Set3StateValue 1549
-#define wxCheckBox_destroy 1550
-#define wxCheckListBox_new_0 1551
-#define wxCheckListBox_new_3 1553
-#define wxCheckListBox_Check 1554
-#define wxCheckListBox_IsChecked 1555
-#define wxCheckListBox_destroy 1556
-#define wxChoice_new_3 1559
-#define wxChoice_new_0 1560
-#define wxChoice_destruct 1562
-#define wxChoice_Create 1564
-#define wxChoice_Delete 1565
-#define wxChoice_GetColumns 1566
-#define wxChoice_SetColumns 1567
-#define wxComboBox_new_0 1568
-#define wxComboBox_new_3 1570
-#define wxComboBox_destruct 1571
-#define wxComboBox_Create 1573
-#define wxComboBox_CanCopy 1574
-#define wxComboBox_CanCut 1575
-#define wxComboBox_CanPaste 1576
-#define wxComboBox_CanRedo 1577
-#define wxComboBox_CanUndo 1578
-#define wxComboBox_Copy 1579
-#define wxComboBox_Cut 1580
-#define wxComboBox_GetInsertionPoint 1581
-#define wxComboBox_GetLastPosition 1582
-#define wxComboBox_GetValue 1583
-#define wxComboBox_Paste 1584
-#define wxComboBox_Redo 1585
-#define wxComboBox_Replace 1586
-#define wxComboBox_Remove 1587
-#define wxComboBox_SetInsertionPoint 1588
-#define wxComboBox_SetInsertionPointEnd 1589
-#define wxComboBox_SetSelection_1 1590
-#define wxComboBox_SetSelection_2 1591
-#define wxComboBox_SetValue 1592
-#define wxComboBox_Undo 1593
-#define wxGauge_new_0 1594
-#define wxGauge_new_4 1595
-#define wxGauge_Create 1596
-#define wxGauge_GetBezelFace 1597
-#define wxGauge_GetRange 1598
-#define wxGauge_GetShadowWidth 1599
-#define wxGauge_GetValue 1600
-#define wxGauge_IsVertical 1601
-#define wxGauge_SetBezelFace 1602
-#define wxGauge_SetRange 1603
-#define wxGauge_SetShadowWidth 1604
-#define wxGauge_SetValue 1605
-#define wxGauge_Pulse 1606
-#define wxGauge_destroy 1607
-#define wxGenericDirCtrl_new_0 1608
-#define wxGenericDirCtrl_new_2 1609
-#define wxGenericDirCtrl_destruct 1610
-#define wxGenericDirCtrl_Create 1611
-#define wxGenericDirCtrl_Init 1612
-#define wxGenericDirCtrl_CollapseTree 1613
-#define wxGenericDirCtrl_ExpandPath 1614
-#define wxGenericDirCtrl_GetDefaultPath 1615
-#define wxGenericDirCtrl_GetPath 1616
-#define wxGenericDirCtrl_GetFilePath 1617
-#define wxGenericDirCtrl_GetFilter 1618
-#define wxGenericDirCtrl_GetFilterIndex 1619
-#define wxGenericDirCtrl_GetRootId 1620
-#define wxGenericDirCtrl_GetTreeCtrl 1621
-#define wxGenericDirCtrl_ReCreateTree 1622
-#define wxGenericDirCtrl_SetDefaultPath 1623
-#define wxGenericDirCtrl_SetFilter 1624
-#define wxGenericDirCtrl_SetFilterIndex 1625
-#define wxGenericDirCtrl_SetPath 1626
-#define wxStaticBox_new_4 1628
-#define wxStaticBox_new_0 1629
-#define wxStaticBox_Create 1630
-#define wxStaticBox_destroy 1631
-#define wxStaticLine_new_2 1633
-#define wxStaticLine_new_0 1634
-#define wxStaticLine_Create 1635
-#define wxStaticLine_IsVertical 1636
-#define wxStaticLine_GetDefaultSize 1637
-#define wxStaticLine_destroy 1638
-#define wxListBox_new_3 1641
-#define wxListBox_new_0 1642
-#define wxListBox_destruct 1644
-#define wxListBox_Create 1646
-#define wxListBox_Deselect 1647
-#define wxListBox_GetSelections 1648
-#define wxListBox_InsertItems 1649
-#define wxListBox_IsSelected 1650
-#define wxListBox_Set 1652
-#define wxListBox_HitTest 1653
-#define wxListBox_SetFirstItem_1_0 1654
-#define wxListBox_SetFirstItem_1_1 1655
-#define wxListCtrl_new_0 1656
-#define wxListCtrl_new_2 1657
-#define wxListCtrl_Arrange 1658
-#define wxListCtrl_AssignImageList 1659
-#define wxListCtrl_ClearAll 1660
-#define wxListCtrl_Create 1661
-#define wxListCtrl_DeleteAllItems 1662
-#define wxListCtrl_DeleteColumn 1663
-#define wxListCtrl_DeleteItem 1664
-#define wxListCtrl_EditLabel 1665
-#define wxListCtrl_EnsureVisible 1666
-#define wxListCtrl_FindItem_3_0 1667
-#define wxListCtrl_FindItem_3_1 1668
-#define wxListCtrl_GetColumn 1669
-#define wxListCtrl_GetColumnCount 1670
-#define wxListCtrl_GetColumnWidth 1671
-#define wxListCtrl_GetCountPerPage 1672
-#define wxListCtrl_GetEditControl 1673
-#define wxListCtrl_GetImageList 1674
-#define wxListCtrl_GetItem 1675
-#define wxListCtrl_GetItemBackgroundColour 1676
-#define wxListCtrl_GetItemCount 1677
-#define wxListCtrl_GetItemData 1678
-#define wxListCtrl_GetItemFont 1679
-#define wxListCtrl_GetItemPosition 1680
-#define wxListCtrl_GetItemRect 1681
-#define wxListCtrl_GetItemSpacing 1682
-#define wxListCtrl_GetItemState 1683
-#define wxListCtrl_GetItemText 1684
-#define wxListCtrl_GetItemTextColour 1685
-#define wxListCtrl_GetNextItem 1686
-#define wxListCtrl_GetSelectedItemCount 1687
-#define wxListCtrl_GetTextColour 1688
-#define wxListCtrl_GetTopItem 1689
-#define wxListCtrl_GetViewRect 1690
-#define wxListCtrl_HitTest 1691
-#define wxListCtrl_InsertColumn_2 1692
-#define wxListCtrl_InsertColumn_3 1693
-#define wxListCtrl_InsertItem_1 1694
-#define wxListCtrl_InsertItem_2_1 1695
-#define wxListCtrl_InsertItem_2_0 1696
-#define wxListCtrl_InsertItem_3 1697
-#define wxListCtrl_RefreshItem 1698
-#define wxListCtrl_RefreshItems 1699
-#define wxListCtrl_ScrollList 1700
-#define wxListCtrl_SetBackgroundColour 1701
-#define wxListCtrl_SetColumn 1702
-#define wxListCtrl_SetColumnWidth 1703
-#define wxListCtrl_SetImageList 1704
-#define wxListCtrl_SetItem_1 1705
-#define wxListCtrl_SetItem_4 1706
-#define wxListCtrl_SetItemBackgroundColour 1707
-#define wxListCtrl_SetItemCount 1708
-#define wxListCtrl_SetItemData 1709
-#define wxListCtrl_SetItemFont 1710
-#define wxListCtrl_SetItemImage 1711
-#define wxListCtrl_SetItemColumnImage 1712
-#define wxListCtrl_SetItemPosition 1713
-#define wxListCtrl_SetItemState 1714
-#define wxListCtrl_SetItemText 1715
-#define wxListCtrl_SetItemTextColour 1716
-#define wxListCtrl_SetSingleStyle 1717
-#define wxListCtrl_SetTextColour 1718
-#define wxListCtrl_SetWindowStyleFlag 1719
-#define wxListCtrl_SortItems 1720
-#define wxListCtrl_destroy 1721
-#define wxListView_ClearColumnImage 1722
-#define wxListView_Focus 1723
-#define wxListView_GetFirstSelected 1724
-#define wxListView_GetFocusedItem 1725
-#define wxListView_GetNextSelected 1726
-#define wxListView_IsSelected 1727
-#define wxListView_Select 1728
-#define wxListView_SetColumnImage 1729
-#define wxListItem_new_0 1730
-#define wxListItem_new_1 1731
-#define wxListItem_destruct 1732
-#define wxListItem_Clear 1733
-#define wxListItem_GetAlign 1734
-#define wxListItem_GetBackgroundColour 1735
-#define wxListItem_GetColumn 1736
-#define wxListItem_GetFont 1737
-#define wxListItem_GetId 1738
-#define wxListItem_GetImage 1739
-#define wxListItem_GetMask 1740
-#define wxListItem_GetState 1741
-#define wxListItem_GetText 1742
-#define wxListItem_GetTextColour 1743
-#define wxListItem_GetWidth 1744
-#define wxListItem_SetAlign 1745
-#define wxListItem_SetBackgroundColour 1746
-#define wxListItem_SetColumn 1747
-#define wxListItem_SetFont 1748
-#define wxListItem_SetId 1749
-#define wxListItem_SetImage 1750
-#define wxListItem_SetMask 1751
-#define wxListItem_SetState 1752
-#define wxListItem_SetStateMask 1753
-#define wxListItem_SetText 1754
-#define wxListItem_SetTextColour 1755
-#define wxListItem_SetWidth 1756
-#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
+#define wxDC_GetFont 667
+#define wxDC_GetLayoutDirection 668
+#define wxDC_GetLogicalFunction 669
+#define wxDC_GetMapMode 670
+#define wxDC_GetMultiLineTextExtent_4 671
+#define wxDC_GetMultiLineTextExtent_1 672
+#define wxDC_GetPartialTextExtents 673
+#define wxDC_GetPen 674
+#define wxDC_GetPixel 675
+#define wxDC_GetPPI 676
+#define wxDC_GetSize 678
+#define wxDC_GetSizeMM 680
+#define wxDC_GetTextBackground 681
+#define wxDC_GetTextExtent_4 682
+#define wxDC_GetTextExtent_1 683
+#define wxDC_GetTextForeground 685
+#define wxDC_GetUserScale 686
+#define wxDC_GradientFillConcentric_3 687
+#define wxDC_GradientFillConcentric_4 688
+#define wxDC_GradientFillLinear 689
+#define wxDC_LogicalToDeviceX 690
+#define wxDC_LogicalToDeviceXRel 691
+#define wxDC_LogicalToDeviceY 692
+#define wxDC_LogicalToDeviceYRel 693
+#define wxDC_MaxX 694
+#define wxDC_MaxY 695
+#define wxDC_MinX 696
+#define wxDC_MinY 697
+#define wxDC_IsOk 698
+#define wxDC_ResetBoundingBox 699
+#define wxDC_SetAxisOrientation 700
+#define wxDC_SetBackground 701
+#define wxDC_SetBackgroundMode 702
+#define wxDC_SetBrush 703
+#define wxDC_SetClippingRegion_2 705
+#define wxDC_SetClippingRegion_1_1 706
+#define wxDC_SetClippingRegion_1_0 707
+#define wxDC_SetDeviceOrigin 708
+#define wxDC_SetFont 709
+#define wxDC_SetLayoutDirection 710
+#define wxDC_SetLogicalFunction 711
+#define wxDC_SetMapMode 712
+#define wxDC_SetPalette 713
+#define wxDC_SetPen 714
+#define wxDC_SetTextBackground 715
+#define wxDC_SetTextForeground 716
+#define wxDC_SetUserScale 717
+#define wxDC_StartDoc 718
+#define wxDC_StartPage 719
+#define wxMirrorDC_new 720
+#define wxMirrorDC_destroy 721
+#define wxScreenDC_new 722
+#define wxScreenDC_destruct 723
+#define wxPostScriptDC_new_0 724
+#define wxPostScriptDC_new_1 725
+#define wxPostScriptDC_destruct 726
+#define wxPostScriptDC_SetResolution 727
+#define wxPostScriptDC_GetResolution 728
+#define wxWindowDC_new_0 729
+#define wxWindowDC_new_1 730
+#define wxWindowDC_destruct 731
+#define wxClientDC_new_0 732
+#define wxClientDC_new_1 733
+#define wxClientDC_destroy 734
+#define wxPaintDC_new_0 735
+#define wxPaintDC_new_1 736
+#define wxPaintDC_destroy 737
+#define wxMemoryDC_new_1_0 739
+#define wxMemoryDC_new_1_1 740
+#define wxMemoryDC_new_0 741
+#define wxMemoryDC_destruct 743
+#define wxMemoryDC_SelectObject 744
+#define wxMemoryDC_SelectObjectAsSource 745
+#define wxBufferedDC_new_0 746
+#define wxBufferedDC_new_2 747
+#define wxBufferedDC_new_3 748
+#define wxBufferedDC_destruct 749
+#define wxBufferedDC_Init_2 750
+#define wxBufferedDC_Init_3 751
+#define wxBufferedPaintDC_new_3 752
+#define wxBufferedPaintDC_new_2 753
+#define wxBufferedPaintDC_destruct 754
+#define wxGraphicsObject_destruct 755
+#define wxGraphicsObject_GetRenderer 756
+#define wxGraphicsObject_IsNull 757
+#define wxGraphicsContext_destruct 758
+#define wxGraphicsContext_Create_1_1 759
+#define wxGraphicsContext_Create_1_0 760
+#define wxGraphicsContext_Create_0 761
+#define wxGraphicsContext_CreatePen 762
+#define wxGraphicsContext_CreateBrush 763
+#define wxGraphicsContext_CreateRadialGradientBrush 764
+#define wxGraphicsContext_CreateLinearGradientBrush 765
+#define wxGraphicsContext_CreateFont 766
+#define wxGraphicsContext_CreateMatrix 767
+#define wxGraphicsContext_CreatePath 768
+#define wxGraphicsContext_Clip_1 769
+#define wxGraphicsContext_Clip_4 770
+#define wxGraphicsContext_ResetClip 771
+#define wxGraphicsContext_DrawBitmap 772
+#define wxGraphicsContext_DrawEllipse 773
+#define wxGraphicsContext_DrawIcon 774
+#define wxGraphicsContext_DrawLines 775
+#define wxGraphicsContext_DrawPath 776
+#define wxGraphicsContext_DrawRectangle 777
+#define wxGraphicsContext_DrawRoundedRectangle 778
+#define wxGraphicsContext_DrawText_3 779
+#define wxGraphicsContext_DrawText_4_0 780
+#define wxGraphicsContext_DrawText_4_1 781
+#define wxGraphicsContext_DrawText_5 782
+#define wxGraphicsContext_FillPath 783
+#define wxGraphicsContext_StrokePath 784
+#define wxGraphicsContext_GetPartialTextExtents 785
+#define wxGraphicsContext_GetTextExtent 786
+#define wxGraphicsContext_Rotate 787
+#define wxGraphicsContext_Scale 788
+#define wxGraphicsContext_Translate 789
+#define wxGraphicsContext_GetTransform 790
+#define wxGraphicsContext_SetTransform 791
+#define wxGraphicsContext_ConcatTransform 792
+#define wxGraphicsContext_SetBrush_1_1 793
+#define wxGraphicsContext_SetBrush_1_0 794
+#define wxGraphicsContext_SetFont_1 795
+#define wxGraphicsContext_SetFont_2 796
+#define wxGraphicsContext_SetPen_1_0 797
+#define wxGraphicsContext_SetPen_1_1 798
+#define wxGraphicsContext_StrokeLine 799
+#define wxGraphicsContext_StrokeLines 800
+#define wxGraphicsMatrix_Concat 802
+#define wxGraphicsMatrix_Get 804
+#define wxGraphicsMatrix_Invert 805
+#define wxGraphicsMatrix_IsEqual 806
+#define wxGraphicsMatrix_IsIdentity 808
+#define wxGraphicsMatrix_Rotate 809
+#define wxGraphicsMatrix_Scale 810
+#define wxGraphicsMatrix_Translate 811
+#define wxGraphicsMatrix_Set 812
+#define wxGraphicsMatrix_TransformPoint 813
+#define wxGraphicsMatrix_TransformDistance 814
+#define wxGraphicsPath_MoveToPoint_2 815
+#define wxGraphicsPath_MoveToPoint_1 816
+#define wxGraphicsPath_AddArc_6 817
+#define wxGraphicsPath_AddArc_5 818
+#define wxGraphicsPath_AddArcToPoint 819
+#define wxGraphicsPath_AddCircle 820
+#define wxGraphicsPath_AddCurveToPoint_6 821
+#define wxGraphicsPath_AddCurveToPoint_3 822
+#define wxGraphicsPath_AddEllipse 823
+#define wxGraphicsPath_AddLineToPoint_2 824
+#define wxGraphicsPath_AddLineToPoint_1 825
+#define wxGraphicsPath_AddPath 826
+#define wxGraphicsPath_AddQuadCurveToPoint 827
+#define wxGraphicsPath_AddRectangle 828
+#define wxGraphicsPath_AddRoundedRectangle 829
+#define wxGraphicsPath_CloseSubpath 830
+#define wxGraphicsPath_Contains_3 831
+#define wxGraphicsPath_Contains_2 832
+#define wxGraphicsPath_GetBox 834
+#define wxGraphicsPath_GetCurrentPoint 836
+#define wxGraphicsPath_Transform 837
+#define wxGraphicsRenderer_GetDefaultRenderer 838
+#define wxGraphicsRenderer_CreateContext_1_1 839
+#define wxGraphicsRenderer_CreateContext_1_0 840
+#define wxGraphicsRenderer_CreatePen 841
+#define wxGraphicsRenderer_CreateBrush 842
+#define wxGraphicsRenderer_CreateLinearGradientBrush 843
+#define wxGraphicsRenderer_CreateRadialGradientBrush 844
+#define wxGraphicsRenderer_CreateFont 845
+#define wxGraphicsRenderer_CreateMatrix 846
+#define wxGraphicsRenderer_CreatePath 847
+#define wxMenuBar_new_1 849
+#define wxMenuBar_new_0 851
+#define wxMenuBar_destruct 853
+#define wxMenuBar_Append 854
+#define wxMenuBar_Check 855
+#define wxMenuBar_Enable_2 856
+#define wxMenuBar_Enable_1 857
+#define wxMenuBar_EnableTop 858
+#define wxMenuBar_FindMenu 859
+#define wxMenuBar_FindMenuItem 860
+#define wxMenuBar_FindItem 861
+#define wxMenuBar_GetHelpString 862
+#define wxMenuBar_GetLabel_1 863
+#define wxMenuBar_GetLabel_0 864
+#define wxMenuBar_GetLabelTop 865
+#define wxMenuBar_GetMenu 866
+#define wxMenuBar_GetMenuCount 867
+#define wxMenuBar_Insert 868
+#define wxMenuBar_IsChecked 869
+#define wxMenuBar_IsEnabled_1 870
+#define wxMenuBar_IsEnabled_0 871
+#define wxMenuBar_Remove 872
+#define wxMenuBar_Replace 873
+#define wxMenuBar_SetHelpString 874
+#define wxMenuBar_SetLabel_2 875
+#define wxMenuBar_SetLabel_1 876
+#define wxMenuBar_SetLabelTop 877
+#define wxControl_GetLabel 878
+#define wxControl_SetLabel 879
+#define wxControlWithItems_Append_1 880
+#define wxControlWithItems_Append_2 881
+#define wxControlWithItems_appendStrings_1 882
+#define wxControlWithItems_Clear 883
+#define wxControlWithItems_Delete 884
+#define wxControlWithItems_FindString 885
+#define wxControlWithItems_getClientData 886
+#define wxControlWithItems_setClientData 887
+#define wxControlWithItems_GetCount 888
+#define wxControlWithItems_GetSelection 889
+#define wxControlWithItems_GetString 890
+#define wxControlWithItems_GetStringSelection 891
+#define wxControlWithItems_Insert_2 892
+#define wxControlWithItems_Insert_3 893
+#define wxControlWithItems_IsEmpty 894
+#define wxControlWithItems_Select 895
+#define wxControlWithItems_SetSelection 896
+#define wxControlWithItems_SetString 897
+#define wxControlWithItems_SetStringSelection 898
+#define wxMenu_new_2 901
+#define wxMenu_new_1 902
+#define wxMenu_destruct 904
+#define wxMenu_Append_3 905
+#define wxMenu_Append_1 906
+#define wxMenu_Append_4_0 907
+#define wxMenu_Append_4_1 908
+#define wxMenu_AppendCheckItem 909
+#define wxMenu_AppendRadioItem 910
+#define wxMenu_AppendSeparator 911
+#define wxMenu_Break 912
+#define wxMenu_Check 913
+#define wxMenu_Delete_1_0 914
+#define wxMenu_Delete_1_1 915
+#define wxMenu_Destroy_1_0 916
+#define wxMenu_Destroy_1_1 917
+#define wxMenu_Enable 918
+#define wxMenu_FindItem_1 919
+#define wxMenu_FindItem_2 920
+#define wxMenu_FindItemByPosition 921
+#define wxMenu_GetHelpString 922
+#define wxMenu_GetLabel 923
+#define wxMenu_GetMenuItemCount 924
+#define wxMenu_GetMenuItems 925
+#define wxMenu_GetTitle 927
+#define wxMenu_Insert_2 928
+#define wxMenu_Insert_3 929
+#define wxMenu_Insert_5_1 930
+#define wxMenu_Insert_5_0 931
+#define wxMenu_InsertCheckItem 932
+#define wxMenu_InsertRadioItem 933
+#define wxMenu_InsertSeparator 934
+#define wxMenu_IsChecked 935
+#define wxMenu_IsEnabled 936
+#define wxMenu_Prepend_1 937
+#define wxMenu_Prepend_2 938
+#define wxMenu_Prepend_4_1 939
+#define wxMenu_Prepend_4_0 940
+#define wxMenu_PrependCheckItem 941
+#define wxMenu_PrependRadioItem 942
+#define wxMenu_PrependSeparator 943
+#define wxMenu_Remove_1_0 944
+#define wxMenu_Remove_1_1 945
+#define wxMenu_SetHelpString 946
+#define wxMenu_SetLabel 947
+#define wxMenu_SetTitle 948
+#define wxMenuItem_new 949
+#define wxMenuItem_destruct 951
+#define wxMenuItem_Check 952
+#define wxMenuItem_Enable 953
+#define wxMenuItem_GetBitmap 954
+#define wxMenuItem_GetHelp 955
+#define wxMenuItem_GetId 956
+#define wxMenuItem_GetKind 957
+#define wxMenuItem_GetLabel 958
+#define wxMenuItem_GetLabelFromText 959
+#define wxMenuItem_GetMenu 960
+#define wxMenuItem_GetText 961
+#define wxMenuItem_GetSubMenu 962
+#define wxMenuItem_IsCheckable 963
+#define wxMenuItem_IsChecked 964
+#define wxMenuItem_IsEnabled 965
+#define wxMenuItem_IsSeparator 966
+#define wxMenuItem_IsSubMenu 967
+#define wxMenuItem_SetBitmap 968
+#define wxMenuItem_SetHelp 969
+#define wxMenuItem_SetMenu 970
+#define wxMenuItem_SetSubMenu 971
+#define wxMenuItem_SetText 972
+#define wxToolBar_AddControl 973
+#define wxToolBar_AddSeparator 974
+#define wxToolBar_AddTool_5 975
+#define wxToolBar_AddTool_4_0 976
+#define wxToolBar_AddTool_1 977
+#define wxToolBar_AddTool_4_1 978
+#define wxToolBar_AddTool_3 979
+#define wxToolBar_AddTool_6 980
+#define wxToolBar_AddCheckTool 981
+#define wxToolBar_AddRadioTool 982
+#define wxToolBar_DeleteTool 983
+#define wxToolBar_DeleteToolByPos 984
+#define wxToolBar_EnableTool 985
+#define wxToolBar_FindById 986
+#define wxToolBar_FindControl 987
+#define wxToolBar_FindToolForPosition 988
+#define wxToolBar_GetToolSize 989
+#define wxToolBar_GetToolBitmapSize 990
+#define wxToolBar_GetMargins 991
+#define wxToolBar_GetToolEnabled 992
+#define wxToolBar_GetToolLongHelp 993
+#define wxToolBar_GetToolPacking 994
+#define wxToolBar_GetToolPos 995
+#define wxToolBar_GetToolSeparation 996
+#define wxToolBar_GetToolShortHelp 997
+#define wxToolBar_GetToolState 998
+#define wxToolBar_InsertControl 999
+#define wxToolBar_InsertSeparator 1000
+#define wxToolBar_InsertTool_5 1001
+#define wxToolBar_InsertTool_2 1002
+#define wxToolBar_InsertTool_4 1003
+#define wxToolBar_Realize 1004
+#define wxToolBar_RemoveTool 1005
+#define wxToolBar_SetMargins 1006
+#define wxToolBar_SetToolBitmapSize 1007
+#define wxToolBar_SetToolLongHelp 1008
+#define wxToolBar_SetToolPacking 1009
+#define wxToolBar_SetToolShortHelp 1010
+#define wxToolBar_SetToolSeparation 1011
+#define wxToolBar_ToggleTool 1012
+#define wxStatusBar_new_0 1014
+#define wxStatusBar_new_2 1015
+#define wxStatusBar_destruct 1017
+#define wxStatusBar_Create 1018
+#define wxStatusBar_GetFieldRect 1019
+#define wxStatusBar_GetFieldsCount 1020
+#define wxStatusBar_GetStatusText 1021
+#define wxStatusBar_PopStatusText 1022
+#define wxStatusBar_PushStatusText 1023
+#define wxStatusBar_SetFieldsCount 1024
+#define wxStatusBar_SetMinHeight 1025
+#define wxStatusBar_SetStatusText 1026
+#define wxStatusBar_SetStatusWidths 1027
+#define wxStatusBar_SetStatusStyles 1028
+#define wxBitmap_new_0 1029
+#define wxBitmap_new_3 1030
+#define wxBitmap_new_4 1031
+#define wxBitmap_new_2_0 1032
+#define wxBitmap_new_2_1 1033
+#define wxBitmap_destruct 1034
+#define wxBitmap_ConvertToImage 1035
+#define wxBitmap_CopyFromIcon 1036
+#define wxBitmap_Create 1037
+#define wxBitmap_GetDepth 1038
+#define wxBitmap_GetHeight 1039
+#define wxBitmap_GetPalette 1040
+#define wxBitmap_GetMask 1041
+#define wxBitmap_GetWidth 1042
+#define wxBitmap_GetSubBitmap 1043
+#define wxBitmap_LoadFile 1044
+#define wxBitmap_Ok 1045
+#define wxBitmap_SaveFile 1046
+#define wxBitmap_SetDepth 1047
+#define wxBitmap_SetHeight 1048
+#define wxBitmap_SetMask 1049
+#define wxBitmap_SetPalette 1050
+#define wxBitmap_SetWidth 1051
+#define wxIcon_new_0 1052
+#define wxIcon_new_2 1053
+#define wxIcon_new_1 1054
+#define wxIcon_CopyFromBitmap 1055
+#define wxIcon_destroy 1056
+#define wxIconBundle_new_0 1057
+#define wxIconBundle_new_2 1058
+#define wxIconBundle_new_1_0 1059
+#define wxIconBundle_new_1_1 1060
+#define wxIconBundle_destruct 1061
+#define wxIconBundle_AddIcon_2 1062
+#define wxIconBundle_AddIcon_1 1063
+#define wxIconBundle_GetIcon_1_1 1064
+#define wxIconBundle_GetIcon_1_0 1065
+#define wxCursor_new_0 1066
+#define wxCursor_new_1_0 1067
+#define wxCursor_new_1_1 1068
+#define wxCursor_new_4 1069
+#define wxCursor_destruct 1070
+#define wxCursor_Ok 1071
+#define wxMask_new_0 1072
+#define wxMask_new_2_1 1073
+#define wxMask_new_2_0 1074
+#define wxMask_new_1 1075
+#define wxMask_destruct 1076
+#define wxMask_Create_2_1 1077
+#define wxMask_Create_2_0 1078
+#define wxMask_Create_1 1079
+#define wxImage_new_0 1080
+#define wxImage_new_3_0 1081
+#define wxImage_new_4 1082
+#define wxImage_new_5 1083
+#define wxImage_new_2 1084
+#define wxImage_new_3_1 1085
+#define wxImage_Blur 1086
+#define wxImage_BlurHorizontal 1087
+#define wxImage_BlurVertical 1088
+#define wxImage_ConvertAlphaToMask 1089
+#define wxImage_ConvertToGreyscale 1090
+#define wxImage_ConvertToMono 1091
+#define wxImage_Copy 1092
+#define wxImage_Create_3 1093
+#define wxImage_Create_4 1094
+#define wxImage_Create_5 1095
+#define wxImage_Destroy 1096
+#define wxImage_FindFirstUnusedColour 1097
+#define wxImage_GetImageExtWildcard 1098
+#define wxImage_GetAlpha_2 1099
+#define wxImage_GetAlpha_0 1100
+#define wxImage_GetBlue 1101
+#define wxImage_GetData 1102
+#define wxImage_GetGreen 1103
+#define wxImage_GetImageCount 1104
+#define wxImage_GetHeight 1105
+#define wxImage_GetMaskBlue 1106
+#define wxImage_GetMaskGreen 1107
+#define wxImage_GetMaskRed 1108
+#define wxImage_GetOrFindMaskColour 1109
+#define wxImage_GetPalette 1110
+#define wxImage_GetRed 1111
+#define wxImage_GetSubImage 1112
+#define wxImage_GetWidth 1113
+#define wxImage_HasAlpha 1114
+#define wxImage_HasMask 1115
+#define wxImage_GetOption 1116
+#define wxImage_GetOptionInt 1117
+#define wxImage_HasOption 1118
+#define wxImage_InitAlpha 1119
+#define wxImage_InitStandardHandlers 1120
+#define wxImage_IsTransparent 1121
+#define wxImage_LoadFile_2 1122
+#define wxImage_LoadFile_3 1123
+#define wxImage_Ok 1124
+#define wxImage_RemoveHandler 1125
+#define wxImage_Mirror 1126
+#define wxImage_Replace 1127
+#define wxImage_Rescale 1128
+#define wxImage_Resize 1129
+#define wxImage_Rotate 1130
+#define wxImage_RotateHue 1131
+#define wxImage_Rotate90 1132
+#define wxImage_SaveFile_1 1133
+#define wxImage_SaveFile_2_0 1134
+#define wxImage_SaveFile_2_1 1135
+#define wxImage_Scale 1136
+#define wxImage_Size 1137
+#define wxImage_SetAlpha_3 1138
+#define wxImage_SetAlpha_2 1139
+#define wxImage_SetData_2 1140
+#define wxImage_SetData_4 1141
+#define wxImage_SetMask 1142
+#define wxImage_SetMaskColour 1143
+#define wxImage_SetMaskFromImage 1144
+#define wxImage_SetOption_2_1 1145
+#define wxImage_SetOption_2_0 1146
+#define wxImage_SetPalette 1147
+#define wxImage_SetRGB_5 1148
+#define wxImage_SetRGB_4 1149
+#define wxImage_destroy 1150
+#define wxBrush_new_0 1151
+#define wxBrush_new_2 1152
+#define wxBrush_new_1 1153
+#define wxBrush_destruct 1155
+#define wxBrush_GetColour 1156
+#define wxBrush_GetStipple 1157
+#define wxBrush_GetStyle 1158
+#define wxBrush_IsHatch 1159
+#define wxBrush_IsOk 1160
+#define wxBrush_SetColour_1 1161
+#define wxBrush_SetColour_3 1162
+#define wxBrush_SetStipple 1163
+#define wxBrush_SetStyle 1164
+#define wxPen_new_0 1165
+#define wxPen_new_2 1166
+#define wxPen_destruct 1167
+#define wxPen_GetCap 1168
+#define wxPen_GetColour 1169
+#define wxPen_GetJoin 1170
+#define wxPen_GetStyle 1171
+#define wxPen_GetWidth 1172
+#define wxPen_IsOk 1173
+#define wxPen_SetCap 1174
+#define wxPen_SetColour_1 1175
+#define wxPen_SetColour_3 1176
+#define wxPen_SetJoin 1177
+#define wxPen_SetStyle 1178
+#define wxPen_SetWidth 1179
+#define wxRegion_new_0 1180
+#define wxRegion_new_4 1181
+#define wxRegion_new_2 1182
+#define wxRegion_new_1_1 1183
+#define wxRegion_new_1_0 1185
+#define wxRegion_destruct 1187
+#define wxRegion_Clear 1188
+#define wxRegion_Contains_2 1189
+#define wxRegion_Contains_1_0 1190
+#define wxRegion_Contains_4 1191
+#define wxRegion_Contains_1_1 1192
+#define wxRegion_ConvertToBitmap 1193
+#define wxRegion_GetBox 1194
+#define wxRegion_Intersect_4 1195
+#define wxRegion_Intersect_1_1 1196
+#define wxRegion_Intersect_1_0 1197
+#define wxRegion_IsEmpty 1198
+#define wxRegion_Subtract_4 1199
+#define wxRegion_Subtract_1_1 1200
+#define wxRegion_Subtract_1_0 1201
+#define wxRegion_Offset_2 1202
+#define wxRegion_Offset_1 1203
+#define wxRegion_Union_4 1204
+#define wxRegion_Union_1_2 1205
+#define wxRegion_Union_1_1 1206
+#define wxRegion_Union_1_0 1207
+#define wxRegion_Union_3 1208
+#define wxRegion_Xor_4 1209
+#define wxRegion_Xor_1_1 1210
+#define wxRegion_Xor_1_0 1211
+#define wxAcceleratorTable_new_0 1212
+#define wxAcceleratorTable_new_2 1213
+#define wxAcceleratorTable_destruct 1214
+#define wxAcceleratorTable_Ok 1215
+#define wxAcceleratorEntry_new_1_0 1216
+#define wxAcceleratorEntry_new_1_1 1217
+#define wxAcceleratorEntry_GetCommand 1218
+#define wxAcceleratorEntry_GetFlags 1219
+#define wxAcceleratorEntry_GetKeyCode 1220
+#define wxAcceleratorEntry_Set 1221
+#define wxAcceleratorEntry_destroy 1222
+#define wxCaret_new_3 1227
+#define wxCaret_new_2 1228
+#define wxCaret_destruct 1230
+#define wxCaret_Create_3 1231
+#define wxCaret_Create_2 1232
+#define wxCaret_GetBlinkTime 1233
+#define wxCaret_GetPosition 1235
+#define wxCaret_GetSize 1237
+#define wxCaret_GetWindow 1238
+#define wxCaret_Hide 1239
+#define wxCaret_IsOk 1240
+#define wxCaret_IsVisible 1241
+#define wxCaret_Move_2 1242
+#define wxCaret_Move_1 1243
+#define wxCaret_SetBlinkTime 1244
+#define wxCaret_SetSize_2 1245
+#define wxCaret_SetSize_1 1246
+#define wxCaret_Show 1247
+#define wxSizer_Add_2_1 1248
+#define wxSizer_Add_2_0 1249
+#define wxSizer_Add_3 1250
+#define wxSizer_Add_2_3 1251
+#define wxSizer_Add_2_2 1252
+#define wxSizer_AddSpacer 1253
+#define wxSizer_AddStretchSpacer 1254
+#define wxSizer_CalcMin 1255
+#define wxSizer_Clear 1256
+#define wxSizer_Detach_1_2 1257
+#define wxSizer_Detach_1_1 1258
+#define wxSizer_Detach_1_0 1259
+#define wxSizer_Fit 1260
+#define wxSizer_FitInside 1261
+#define wxSizer_GetChildren 1262
+#define wxSizer_GetItem_2_1 1263
+#define wxSizer_GetItem_2_0 1264
+#define wxSizer_GetItem_1 1265
+#define wxSizer_GetSize 1266
+#define wxSizer_GetPosition 1267
+#define wxSizer_GetMinSize 1268
+#define wxSizer_Hide_2_0 1269
+#define wxSizer_Hide_2_1 1270
+#define wxSizer_Hide_1 1271
+#define wxSizer_Insert_3_1 1272
+#define wxSizer_Insert_3_0 1273
+#define wxSizer_Insert_4 1274
+#define wxSizer_Insert_3_3 1275
+#define wxSizer_Insert_3_2 1276
+#define wxSizer_Insert_2 1277
+#define wxSizer_InsertSpacer 1278
+#define wxSizer_InsertStretchSpacer 1279
+#define wxSizer_IsShown_1_2 1280
+#define wxSizer_IsShown_1_1 1281
+#define wxSizer_IsShown_1_0 1282
+#define wxSizer_Layout 1283
+#define wxSizer_Prepend_2_1 1284
+#define wxSizer_Prepend_2_0 1285
+#define wxSizer_Prepend_3 1286
+#define wxSizer_Prepend_2_3 1287
+#define wxSizer_Prepend_2_2 1288
+#define wxSizer_Prepend_1 1289
+#define wxSizer_PrependSpacer 1290
+#define wxSizer_PrependStretchSpacer 1291
+#define wxSizer_RecalcSizes 1292
+#define wxSizer_Remove_1_1 1293
+#define wxSizer_Remove_1_0 1294
+#define wxSizer_Replace_3_1 1295
+#define wxSizer_Replace_3_0 1296
+#define wxSizer_Replace_2 1297
+#define wxSizer_SetDimension 1298
+#define wxSizer_SetMinSize_2 1299
+#define wxSizer_SetMinSize_1 1300
+#define wxSizer_SetItemMinSize_3_2 1301
+#define wxSizer_SetItemMinSize_2_2 1302
+#define wxSizer_SetItemMinSize_3_1 1303
+#define wxSizer_SetItemMinSize_2_1 1304
+#define wxSizer_SetItemMinSize_3_0 1305
+#define wxSizer_SetItemMinSize_2_0 1306
+#define wxSizer_SetSizeHints 1307
+#define wxSizer_SetVirtualSizeHints 1308
+#define wxSizer_Show_2_2 1309
+#define wxSizer_Show_2_1 1310
+#define wxSizer_Show_2_0 1311
+#define wxSizer_Show_1 1312
+#define wxSizerFlags_new 1313
+#define wxSizerFlags_Align 1314
+#define wxSizerFlags_Border_2 1315
+#define wxSizerFlags_Border_1 1316
+#define wxSizerFlags_Center 1317
+#define wxSizerFlags_Centre 1318
+#define wxSizerFlags_Expand 1319
+#define wxSizerFlags_Left 1320
+#define wxSizerFlags_Proportion 1321
+#define wxSizerFlags_Right 1322
+#define wxSizerFlags_destroy 1323
+#define wxSizerItem_new_5_1 1324
+#define wxSizerItem_new_2_1 1325
+#define wxSizerItem_new_5_0 1326
+#define wxSizerItem_new_2_0 1327
+#define wxSizerItem_new_6 1328
+#define wxSizerItem_new_3 1329
+#define wxSizerItem_new_0 1330
+#define wxSizerItem_destruct 1331
+#define wxSizerItem_CalcMin 1332
+#define wxSizerItem_DeleteWindows 1333
+#define wxSizerItem_DetachSizer 1334
+#define wxSizerItem_GetBorder 1335
+#define wxSizerItem_GetFlag 1336
+#define wxSizerItem_GetMinSize 1337
+#define wxSizerItem_GetPosition 1338
+#define wxSizerItem_GetProportion 1339
+#define wxSizerItem_GetRatio 1340
+#define wxSizerItem_GetRect 1341
+#define wxSizerItem_GetSize 1342
+#define wxSizerItem_GetSizer 1343
+#define wxSizerItem_GetSpacer 1344
+#define wxSizerItem_GetUserData 1345
+#define wxSizerItem_GetWindow 1346
+#define wxSizerItem_IsSizer 1347
+#define wxSizerItem_IsShown 1348
+#define wxSizerItem_IsSpacer 1349
+#define wxSizerItem_IsWindow 1350
+#define wxSizerItem_SetBorder 1351
+#define wxSizerItem_SetDimension 1352
+#define wxSizerItem_SetFlag 1353
+#define wxSizerItem_SetInitSize 1354
+#define wxSizerItem_SetMinSize_1 1355
+#define wxSizerItem_SetMinSize_2 1356
+#define wxSizerItem_SetProportion 1357
+#define wxSizerItem_SetRatio_2 1358
+#define wxSizerItem_SetRatio_1_1 1359
+#define wxSizerItem_SetRatio_1_0 1360
+#define wxSizerItem_SetSizer 1361
+#define wxSizerItem_SetSpacer_1 1362
+#define wxSizerItem_SetSpacer_2 1363
+#define wxSizerItem_SetWindow 1364
+#define wxSizerItem_Show 1365
+#define wxBoxSizer_new 1366
+#define wxBoxSizer_GetOrientation 1367
+#define wxBoxSizer_destroy 1368
+#define wxStaticBoxSizer_new_2 1369
+#define wxStaticBoxSizer_new_3 1370
+#define wxStaticBoxSizer_GetStaticBox 1371
+#define wxStaticBoxSizer_destroy 1372
+#define wxGridSizer_new_4 1373
+#define wxGridSizer_new_2 1374
+#define wxGridSizer_GetCols 1375
+#define wxGridSizer_GetHGap 1376
+#define wxGridSizer_GetRows 1377
+#define wxGridSizer_GetVGap 1378
+#define wxGridSizer_SetCols 1379
+#define wxGridSizer_SetHGap 1380
+#define wxGridSizer_SetRows 1381
+#define wxGridSizer_SetVGap 1382
+#define wxGridSizer_destroy 1383
+#define wxFlexGridSizer_new_4 1384
+#define wxFlexGridSizer_new_2 1385
+#define wxFlexGridSizer_AddGrowableCol 1386
+#define wxFlexGridSizer_AddGrowableRow 1387
+#define wxFlexGridSizer_GetFlexibleDirection 1388
+#define wxFlexGridSizer_GetNonFlexibleGrowMode 1389
+#define wxFlexGridSizer_RemoveGrowableCol 1390
+#define wxFlexGridSizer_RemoveGrowableRow 1391
+#define wxFlexGridSizer_SetFlexibleDirection 1392
+#define wxFlexGridSizer_SetNonFlexibleGrowMode 1393
+#define wxFlexGridSizer_destroy 1394
+#define wxGridBagSizer_new 1395
+#define wxGridBagSizer_Add_3_2 1396
+#define wxGridBagSizer_Add_3_1 1397
+#define wxGridBagSizer_Add_4 1398
+#define wxGridBagSizer_Add_1_0 1399
+#define wxGridBagSizer_Add_2_1 1400
+#define wxGridBagSizer_Add_2_0 1401
+#define wxGridBagSizer_Add_3_0 1402
+#define wxGridBagSizer_Add_1_1 1403
+#define wxGridBagSizer_CalcMin 1404
+#define wxGridBagSizer_CheckForIntersection_2 1405
+#define wxGridBagSizer_CheckForIntersection_3 1406
+#define wxGridBagSizer_FindItem_1_1 1407
+#define wxGridBagSizer_FindItem_1_0 1408
+#define wxGridBagSizer_FindItemAtPoint 1409
+#define wxGridBagSizer_FindItemAtPosition 1410
+#define wxGridBagSizer_FindItemWithData 1411
+#define wxGridBagSizer_GetCellSize 1412
+#define wxGridBagSizer_GetEmptyCellSize 1413
+#define wxGridBagSizer_GetItemPosition_1_2 1414
+#define wxGridBagSizer_GetItemPosition_1_1 1415
+#define wxGridBagSizer_GetItemPosition_1_0 1416
+#define wxGridBagSizer_GetItemSpan_1_2 1417
+#define wxGridBagSizer_GetItemSpan_1_1 1418
+#define wxGridBagSizer_GetItemSpan_1_0 1419
+#define wxGridBagSizer_SetEmptyCellSize 1420
+#define wxGridBagSizer_SetItemPosition_2_2 1421
+#define wxGridBagSizer_SetItemPosition_2_1 1422
+#define wxGridBagSizer_SetItemPosition_2_0 1423
+#define wxGridBagSizer_SetItemSpan_2_2 1424
+#define wxGridBagSizer_SetItemSpan_2_1 1425
+#define wxGridBagSizer_SetItemSpan_2_0 1426
+#define wxGridBagSizer_destroy 1427
+#define wxStdDialogButtonSizer_new 1428
+#define wxStdDialogButtonSizer_AddButton 1429
+#define wxStdDialogButtonSizer_Realize 1430
+#define wxStdDialogButtonSizer_SetAffirmativeButton 1431
+#define wxStdDialogButtonSizer_SetCancelButton 1432
+#define wxStdDialogButtonSizer_SetNegativeButton 1433
+#define wxStdDialogButtonSizer_destroy 1434
+#define wxFont_new_0 1435
+#define wxFont_new_1 1436
+#define wxFont_new_5 1437
+#define wxFont_destruct 1439
+#define wxFont_IsFixedWidth 1440
+#define wxFont_GetDefaultEncoding 1441
+#define wxFont_GetFaceName 1442
+#define wxFont_GetFamily 1443
+#define wxFont_GetNativeFontInfoDesc 1444
+#define wxFont_GetNativeFontInfoUserDesc 1445
+#define wxFont_GetPointSize 1446
+#define wxFont_GetStyle 1447
+#define wxFont_GetUnderlined 1448
+#define wxFont_GetWeight 1449
+#define wxFont_Ok 1450
+#define wxFont_SetDefaultEncoding 1451
+#define wxFont_SetFaceName 1452
+#define wxFont_SetFamily 1453
+#define wxFont_SetPointSize 1454
+#define wxFont_SetStyle 1455
+#define wxFont_SetUnderlined 1456
+#define wxFont_SetWeight 1457
+#define wxToolTip_Enable 1458
+#define wxToolTip_SetDelay 1459
+#define wxToolTip_new 1460
+#define wxToolTip_SetTip 1461
+#define wxToolTip_GetTip 1462
+#define wxToolTip_GetWindow 1463
+#define wxToolTip_destroy 1464
+#define wxButton_new_3 1466
+#define wxButton_new_0 1467
+#define wxButton_destruct 1468
+#define wxButton_Create 1469
+#define wxButton_GetDefaultSize 1470
+#define wxButton_SetDefault 1471
+#define wxButton_SetLabel 1472
+#define wxBitmapButton_new_4 1474
+#define wxBitmapButton_new_0 1475
+#define wxBitmapButton_Create 1476
+#define wxBitmapButton_GetBitmapDisabled 1477
+#define wxBitmapButton_GetBitmapFocus 1479
+#define wxBitmapButton_GetBitmapLabel 1481
+#define wxBitmapButton_GetBitmapSelected 1483
+#define wxBitmapButton_SetBitmapDisabled 1485
+#define wxBitmapButton_SetBitmapFocus 1486
+#define wxBitmapButton_SetBitmapLabel 1487
+#define wxBitmapButton_SetBitmapSelected 1488
+#define wxBitmapButton_destroy 1489
+#define wxToggleButton_new_0 1490
+#define wxToggleButton_new_4 1491
+#define wxToggleButton_Create 1492
+#define wxToggleButton_GetValue 1493
+#define wxToggleButton_SetValue 1494
+#define wxToggleButton_destroy 1495
+#define wxCalendarCtrl_new_0 1496
+#define wxCalendarCtrl_new_3 1497
+#define wxCalendarCtrl_Create 1498
+#define wxCalendarCtrl_destruct 1499
+#define wxCalendarCtrl_SetDate 1500
+#define wxCalendarCtrl_GetDate 1501
+#define wxCalendarCtrl_EnableYearChange 1502
+#define wxCalendarCtrl_EnableMonthChange 1503
+#define wxCalendarCtrl_EnableHolidayDisplay 1504
+#define wxCalendarCtrl_SetHeaderColours 1505
+#define wxCalendarCtrl_GetHeaderColourFg 1506
+#define wxCalendarCtrl_GetHeaderColourBg 1507
+#define wxCalendarCtrl_SetHighlightColours 1508
+#define wxCalendarCtrl_GetHighlightColourFg 1509
+#define wxCalendarCtrl_GetHighlightColourBg 1510
+#define wxCalendarCtrl_SetHolidayColours 1511
+#define wxCalendarCtrl_GetHolidayColourFg 1512
+#define wxCalendarCtrl_GetHolidayColourBg 1513
+#define wxCalendarCtrl_GetAttr 1514
+#define wxCalendarCtrl_SetAttr 1515
+#define wxCalendarCtrl_SetHoliday 1516
+#define wxCalendarCtrl_ResetAttr 1517
+#define wxCalendarCtrl_HitTest 1518
+#define wxCalendarDateAttr_new_0 1519
+#define wxCalendarDateAttr_new_2_1 1520
+#define wxCalendarDateAttr_new_2_0 1521
+#define wxCalendarDateAttr_SetTextColour 1522
+#define wxCalendarDateAttr_SetBackgroundColour 1523
+#define wxCalendarDateAttr_SetBorderColour 1524
+#define wxCalendarDateAttr_SetFont 1525
+#define wxCalendarDateAttr_SetBorder 1526
+#define wxCalendarDateAttr_SetHoliday 1527
+#define wxCalendarDateAttr_HasTextColour 1528
+#define wxCalendarDateAttr_HasBackgroundColour 1529
+#define wxCalendarDateAttr_HasBorderColour 1530
+#define wxCalendarDateAttr_HasFont 1531
+#define wxCalendarDateAttr_HasBorder 1532
+#define wxCalendarDateAttr_IsHoliday 1533
+#define wxCalendarDateAttr_GetTextColour 1534
+#define wxCalendarDateAttr_GetBackgroundColour 1535
+#define wxCalendarDateAttr_GetBorderColour 1536
+#define wxCalendarDateAttr_GetFont 1537
+#define wxCalendarDateAttr_GetBorder 1538
+#define wxCalendarDateAttr_destroy 1539
+#define wxCheckBox_new_4 1541
+#define wxCheckBox_new_0 1542
+#define wxCheckBox_Create 1543
+#define wxCheckBox_GetValue 1544
+#define wxCheckBox_Get3StateValue 1545
+#define wxCheckBox_Is3rdStateAllowedForUser 1546
+#define wxCheckBox_Is3State 1547
+#define wxCheckBox_IsChecked 1548
+#define wxCheckBox_SetValue 1549
+#define wxCheckBox_Set3StateValue 1550
+#define wxCheckBox_destroy 1551
+#define wxCheckListBox_new_0 1552
+#define wxCheckListBox_new_3 1554
+#define wxCheckListBox_Check 1555
+#define wxCheckListBox_IsChecked 1556
+#define wxCheckListBox_destroy 1557
+#define wxChoice_new_3 1560
+#define wxChoice_new_0 1561
+#define wxChoice_destruct 1563
+#define wxChoice_Create 1565
+#define wxChoice_Delete 1566
+#define wxChoice_GetColumns 1567
+#define wxChoice_SetColumns 1568
+#define wxComboBox_new_0 1569
+#define wxComboBox_new_3 1571
+#define wxComboBox_destruct 1572
+#define wxComboBox_Create 1574
+#define wxComboBox_CanCopy 1575
+#define wxComboBox_CanCut 1576
+#define wxComboBox_CanPaste 1577
+#define wxComboBox_CanRedo 1578
+#define wxComboBox_CanUndo 1579
+#define wxComboBox_Copy 1580
+#define wxComboBox_Cut 1581
+#define wxComboBox_GetInsertionPoint 1582
+#define wxComboBox_GetLastPosition 1583
+#define wxComboBox_GetValue 1584
+#define wxComboBox_Paste 1585
+#define wxComboBox_Redo 1586
+#define wxComboBox_Replace 1587
+#define wxComboBox_Remove 1588
+#define wxComboBox_SetInsertionPoint 1589
+#define wxComboBox_SetInsertionPointEnd 1590
+#define wxComboBox_SetSelection_1 1591
+#define wxComboBox_SetSelection_2 1592
+#define wxComboBox_SetValue 1593
+#define wxComboBox_Undo 1594
+#define wxGauge_new_0 1595
+#define wxGauge_new_4 1596
+#define wxGauge_Create 1597
+#define wxGauge_GetBezelFace 1598
+#define wxGauge_GetRange 1599
+#define wxGauge_GetShadowWidth 1600
+#define wxGauge_GetValue 1601
+#define wxGauge_IsVertical 1602
+#define wxGauge_SetBezelFace 1603
+#define wxGauge_SetRange 1604
+#define wxGauge_SetShadowWidth 1605
+#define wxGauge_SetValue 1606
+#define wxGauge_Pulse 1607
+#define wxGauge_destroy 1608
+#define wxGenericDirCtrl_new_0 1609
+#define wxGenericDirCtrl_new_2 1610
+#define wxGenericDirCtrl_destruct 1611
+#define wxGenericDirCtrl_Create 1612
+#define wxGenericDirCtrl_Init 1613
+#define wxGenericDirCtrl_CollapseTree 1614
+#define wxGenericDirCtrl_ExpandPath 1615
+#define wxGenericDirCtrl_GetDefaultPath 1616
+#define wxGenericDirCtrl_GetPath 1617
+#define wxGenericDirCtrl_GetFilePath 1618
+#define wxGenericDirCtrl_GetFilter 1619
+#define wxGenericDirCtrl_GetFilterIndex 1620
+#define wxGenericDirCtrl_GetRootId 1621
+#define wxGenericDirCtrl_GetTreeCtrl 1622
+#define wxGenericDirCtrl_ReCreateTree 1623
+#define wxGenericDirCtrl_SetDefaultPath 1624
+#define wxGenericDirCtrl_SetFilter 1625
+#define wxGenericDirCtrl_SetFilterIndex 1626
+#define wxGenericDirCtrl_SetPath 1627
+#define wxStaticBox_new_4 1629
+#define wxStaticBox_new_0 1630
+#define wxStaticBox_Create 1631
+#define wxStaticBox_destroy 1632
+#define wxStaticLine_new_2 1634
+#define wxStaticLine_new_0 1635
+#define wxStaticLine_Create 1636
+#define wxStaticLine_IsVertical 1637
+#define wxStaticLine_GetDefaultSize 1638
+#define wxStaticLine_destroy 1639
+#define wxListBox_new_3 1642
+#define wxListBox_new_0 1643
+#define wxListBox_destruct 1645
+#define wxListBox_Create 1647
+#define wxListBox_Deselect 1648
+#define wxListBox_GetSelections 1649
+#define wxListBox_InsertItems 1650
+#define wxListBox_IsSelected 1651
+#define wxListBox_Set 1653
+#define wxListBox_HitTest 1654
+#define wxListBox_SetFirstItem_1_0 1655
+#define wxListBox_SetFirstItem_1_1 1656
+#define wxListCtrl_new_0 1657
+#define wxListCtrl_new_2 1658
+#define wxListCtrl_Arrange 1659
+#define wxListCtrl_AssignImageList 1660
+#define wxListCtrl_ClearAll 1661
+#define wxListCtrl_Create 1662
+#define wxListCtrl_DeleteAllItems 1663
+#define wxListCtrl_DeleteColumn 1664
+#define wxListCtrl_DeleteItem 1665
+#define wxListCtrl_EditLabel 1666
+#define wxListCtrl_EnsureVisible 1667
+#define wxListCtrl_FindItem_3_0 1668
+#define wxListCtrl_FindItem_3_1 1669
+#define wxListCtrl_GetColumn 1670
+#define wxListCtrl_GetColumnCount 1671
+#define wxListCtrl_GetColumnWidth 1672
+#define wxListCtrl_GetCountPerPage 1673
+#define wxListCtrl_GetEditControl 1674
+#define wxListCtrl_GetImageList 1675
+#define wxListCtrl_GetItem 1676
+#define wxListCtrl_GetItemBackgroundColour 1677
+#define wxListCtrl_GetItemCount 1678
+#define wxListCtrl_GetItemData 1679
+#define wxListCtrl_GetItemFont 1680
+#define wxListCtrl_GetItemPosition 1681
+#define wxListCtrl_GetItemRect 1682
+#define wxListCtrl_GetItemSpacing 1683
+#define wxListCtrl_GetItemState 1684
+#define wxListCtrl_GetItemText 1685
+#define wxListCtrl_GetItemTextColour 1686
+#define wxListCtrl_GetNextItem 1687
+#define wxListCtrl_GetSelectedItemCount 1688
+#define wxListCtrl_GetTextColour 1689
+#define wxListCtrl_GetTopItem 1690
+#define wxListCtrl_GetViewRect 1691
+#define wxListCtrl_HitTest 1692
+#define wxListCtrl_InsertColumn_2 1693
+#define wxListCtrl_InsertColumn_3 1694
+#define wxListCtrl_InsertItem_1 1695
+#define wxListCtrl_InsertItem_2_1 1696
+#define wxListCtrl_InsertItem_2_0 1697
+#define wxListCtrl_InsertItem_3 1698
+#define wxListCtrl_RefreshItem 1699
+#define wxListCtrl_RefreshItems 1700
+#define wxListCtrl_ScrollList 1701
+#define wxListCtrl_SetBackgroundColour 1702
+#define wxListCtrl_SetColumn 1703
+#define wxListCtrl_SetColumnWidth 1704
+#define wxListCtrl_SetImageList 1705
+#define wxListCtrl_SetItem_1 1706
+#define wxListCtrl_SetItem_4 1707
+#define wxListCtrl_SetItemBackgroundColour 1708
+#define wxListCtrl_SetItemCount 1709
+#define wxListCtrl_SetItemData 1710
+#define wxListCtrl_SetItemFont 1711
+#define wxListCtrl_SetItemImage 1712
+#define wxListCtrl_SetItemColumnImage 1713
+#define wxListCtrl_SetItemPosition 1714
+#define wxListCtrl_SetItemState 1715
+#define wxListCtrl_SetItemText 1716
+#define wxListCtrl_SetItemTextColour 1717
+#define wxListCtrl_SetSingleStyle 1718
+#define wxListCtrl_SetTextColour 1719
+#define wxListCtrl_SetWindowStyleFlag 1720
+#define wxListCtrl_SortItems 1721
+#define wxListCtrl_destroy 1722
+#define wxListView_ClearColumnImage 1723
+#define wxListView_Focus 1724
+#define wxListView_GetFirstSelected 1725
+#define wxListView_GetFocusedItem 1726
+#define wxListView_GetNextSelected 1727
+#define wxListView_IsSelected 1728
+#define wxListView_Select 1729
+#define wxListView_SetColumnImage 1730
+#define wxListItem_new_0 1731
+#define wxListItem_new_1 1732
+#define wxListItem_destruct 1733
+#define wxListItem_Clear 1734
+#define wxListItem_GetAlign 1735
+#define wxListItem_GetBackgroundColour 1736
+#define wxListItem_GetColumn 1737
+#define wxListItem_GetFont 1738
+#define wxListItem_GetId 1739
+#define wxListItem_GetImage 1740
+#define wxListItem_GetMask 1741
+#define wxListItem_GetState 1742
+#define wxListItem_GetText 1743
+#define wxListItem_GetTextColour 1744
+#define wxListItem_GetWidth 1745
+#define wxListItem_SetAlign 1746
+#define wxListItem_SetBackgroundColour 1747
+#define wxListItem_SetColumn 1748
+#define wxListItem_SetFont 1749
+#define wxListItem_SetId 1750
+#define wxListItem_SetImage 1751
+#define wxListItem_SetMask 1752
+#define wxListItem_SetState 1753
+#define wxListItem_SetStateMask 1754
+#define wxListItem_SetText 1755
+#define wxListItem_SetTextColour 1756
+#define wxListItem_SetWidth 1757
+#define wxListItemAttr_new_0 1758
+#define wxListItemAttr_new_3 1759
+#define wxListItemAttr_GetBackgroundColour 1760
+#define wxListItemAttr_GetFont 1761
+#define wxListItemAttr_GetTextColour 1762
+#define wxListItemAttr_HasBackgroundColour 1763
+#define wxListItemAttr_HasFont 1764
+#define wxListItemAttr_HasTextColour 1765
+#define wxListItemAttr_SetBackgroundColour 1766
+#define wxListItemAttr_SetFont 1767
+#define wxListItemAttr_SetTextColour 1768
+#define wxListItemAttr_destroy 1769
+#define wxImageList_new_0 1770
+#define wxImageList_new_3 1771
+#define wxImageList_Add_1 1772
+#define wxImageList_Add_2_0 1773
+#define wxImageList_Add_2_1 1774
+#define wxImageList_Create 1775
+#define wxImageList_Draw 1777
+#define wxImageList_GetBitmap 1778
+#define wxImageList_GetIcon 1779
+#define wxImageList_GetImageCount 1780
+#define wxImageList_GetSize 1781
+#define wxImageList_Remove 1782
+#define wxImageList_RemoveAll 1783
+#define wxImageList_Replace_2 1784
+#define wxImageList_Replace_3 1785
+#define wxImageList_destroy 1786
+#define wxTextAttr_new_0 1787
+#define wxTextAttr_new_2 1788
+#define wxTextAttr_GetAlignment 1789
+#define wxTextAttr_GetBackgroundColour 1790
+#define wxTextAttr_GetFont 1791
+#define wxTextAttr_GetLeftIndent 1792
+#define wxTextAttr_GetLeftSubIndent 1793
+#define wxTextAttr_GetRightIndent 1794
+#define wxTextAttr_GetTabs 1795
+#define wxTextAttr_GetTextColour 1796
+#define wxTextAttr_HasBackgroundColour 1797
+#define wxTextAttr_HasFont 1798
+#define wxTextAttr_HasTextColour 1799
+#define wxTextAttr_GetFlags 1800
+#define wxTextAttr_IsDefault 1801
+#define wxTextAttr_SetAlignment 1802
+#define wxTextAttr_SetBackgroundColour 1803
+#define wxTextAttr_SetFlags 1804
+#define wxTextAttr_SetFont 1805
+#define wxTextAttr_SetLeftIndent 1806
+#define wxTextAttr_SetRightIndent 1807
+#define wxTextAttr_SetTabs 1808
+#define wxTextAttr_SetTextColour 1809
+#define wxTextAttr_destroy 1810
+#define wxTextCtrl_new_3 1812
+#define wxTextCtrl_new_0 1813
+#define wxTextCtrl_destruct 1815
+#define wxTextCtrl_AppendText 1816
+#define wxTextCtrl_CanCopy 1817
+#define wxTextCtrl_CanCut 1818
+#define wxTextCtrl_CanPaste 1819
+#define wxTextCtrl_CanRedo 1820
+#define wxTextCtrl_CanUndo 1821
+#define wxTextCtrl_Clear 1822
+#define wxTextCtrl_Copy 1823
+#define wxTextCtrl_Create 1824
+#define wxTextCtrl_Cut 1825
+#define wxTextCtrl_DiscardEdits 1826
+#define wxTextCtrl_EmulateKeyPress 1827
+#define wxTextCtrl_GetDefaultStyle 1828
+#define wxTextCtrl_GetInsertionPoint 1829
+#define wxTextCtrl_GetLastPosition 1830
+#define wxTextCtrl_GetLineLength 1831
+#define wxTextCtrl_GetLineText 1832
+#define wxTextCtrl_GetNumberOfLines 1833
+#define wxTextCtrl_GetRange 1834
+#define wxTextCtrl_GetSelection 1835
+#define wxTextCtrl_GetStringSelection 1836
+#define wxTextCtrl_GetStyle 1837
+#define wxTextCtrl_GetValue 1838
+#define wxTextCtrl_IsEditable 1839
+#define wxTextCtrl_IsModified 1840
+#define wxTextCtrl_IsMultiLine 1841
+#define wxTextCtrl_IsSingleLine 1842
+#define wxTextCtrl_LoadFile 1843
+#define wxTextCtrl_MarkDirty 1844
+#define wxTextCtrl_Paste 1845
+#define wxTextCtrl_PositionToXY 1846
+#define wxTextCtrl_Redo 1847
+#define wxTextCtrl_Remove 1848
+#define wxTextCtrl_Replace 1849
+#define wxTextCtrl_SaveFile 1850
+#define wxTextCtrl_SetDefaultStyle 1851
+#define wxTextCtrl_SetEditable 1852
+#define wxTextCtrl_SetInsertionPoint 1853
+#define wxTextCtrl_SetInsertionPointEnd 1854
+#define wxTextCtrl_SetMaxLength 1856
+#define wxTextCtrl_SetSelection 1857
+#define wxTextCtrl_SetStyle 1858
+#define wxTextCtrl_SetValue 1859
+#define wxTextCtrl_ShowPosition 1860
+#define wxTextCtrl_Undo 1861
+#define wxTextCtrl_WriteText 1862
+#define wxTextCtrl_XYToPosition 1863
+#define wxNotebook_new_0 1866
+#define wxNotebook_new_3 1867
+#define wxNotebook_destruct 1868
+#define wxNotebook_AddPage 1869
+#define wxNotebook_AdvanceSelection 1870
+#define wxNotebook_AssignImageList 1871
+#define wxNotebook_Create 1872
+#define wxNotebook_DeleteAllPages 1873
+#define wxNotebook_DeletePage 1874
+#define wxNotebook_RemovePage 1875
+#define wxNotebook_GetCurrentPage 1876
+#define wxNotebook_GetImageList 1877
+#define wxNotebook_GetPage 1879
+#define wxNotebook_GetPageCount 1880
+#define wxNotebook_GetPageImage 1881
+#define wxNotebook_GetPageText 1882
+#define wxNotebook_GetRowCount 1883
+#define wxNotebook_GetSelection 1884
+#define wxNotebook_GetThemeBackgroundColour 1885
+#define wxNotebook_HitTest 1887
+#define wxNotebook_InsertPage 1889
+#define wxNotebook_SetImageList 1890
+#define wxNotebook_SetPadding 1891
+#define wxNotebook_SetPageSize 1892
+#define wxNotebook_SetPageImage 1893
+#define wxNotebook_SetPageText 1894
+#define wxNotebook_SetSelection 1895
+#define wxNotebook_ChangeSelection 1896
+#define wxChoicebook_new_0 1897
+#define wxChoicebook_new_3 1898
+#define wxChoicebook_AddPage 1899
+#define wxChoicebook_AdvanceSelection 1900
+#define wxChoicebook_AssignImageList 1901
+#define wxChoicebook_Create 1902
+#define wxChoicebook_DeleteAllPages 1903
+#define wxChoicebook_DeletePage 1904
+#define wxChoicebook_RemovePage 1905
+#define wxChoicebook_GetCurrentPage 1906
+#define wxChoicebook_GetImageList 1907
+#define wxChoicebook_GetPage 1909
+#define wxChoicebook_GetPageCount 1910
+#define wxChoicebook_GetPageImage 1911
+#define wxChoicebook_GetPageText 1912
+#define wxChoicebook_GetSelection 1913
+#define wxChoicebook_HitTest 1914
+#define wxChoicebook_InsertPage 1915
+#define wxChoicebook_SetImageList 1916
+#define wxChoicebook_SetPageSize 1917
+#define wxChoicebook_SetPageImage 1918
+#define wxChoicebook_SetPageText 1919
+#define wxChoicebook_SetSelection 1920
+#define wxChoicebook_ChangeSelection 1921
+#define wxChoicebook_destroy 1922
+#define wxToolbook_new_0 1923
+#define wxToolbook_new_3 1924
+#define wxToolbook_AddPage 1925
+#define wxToolbook_AdvanceSelection 1926
+#define wxToolbook_AssignImageList 1927
+#define wxToolbook_Create 1928
+#define wxToolbook_DeleteAllPages 1929
+#define wxToolbook_DeletePage 1930
+#define wxToolbook_RemovePage 1931
+#define wxToolbook_GetCurrentPage 1932
+#define wxToolbook_GetImageList 1933
+#define wxToolbook_GetPage 1935
+#define wxToolbook_GetPageCount 1936
+#define wxToolbook_GetPageImage 1937
+#define wxToolbook_GetPageText 1938
+#define wxToolbook_GetSelection 1939
+#define wxToolbook_HitTest 1941
+#define wxToolbook_InsertPage 1942
+#define wxToolbook_SetImageList 1943
+#define wxToolbook_SetPageSize 1944
+#define wxToolbook_SetPageImage 1945
+#define wxToolbook_SetPageText 1946
+#define wxToolbook_SetSelection 1947
+#define wxToolbook_ChangeSelection 1948
+#define wxToolbook_destroy 1949
+#define wxListbook_new_0 1950
+#define wxListbook_new_3 1951
+#define wxListbook_AddPage 1952
+#define wxListbook_AdvanceSelection 1953
+#define wxListbook_AssignImageList 1954
+#define wxListbook_Create 1955
+#define wxListbook_DeleteAllPages 1956
+#define wxListbook_DeletePage 1957
+#define wxListbook_RemovePage 1958
+#define wxListbook_GetCurrentPage 1959
+#define wxListbook_GetImageList 1960
+#define wxListbook_GetPage 1962
+#define wxListbook_GetPageCount 1963
+#define wxListbook_GetPageImage 1964
+#define wxListbook_GetPageText 1965
+#define wxListbook_GetSelection 1966
+#define wxListbook_HitTest 1968
+#define wxListbook_InsertPage 1969
+#define wxListbook_SetImageList 1970
+#define wxListbook_SetPageSize 1971
+#define wxListbook_SetPageImage 1972
+#define wxListbook_SetPageText 1973
+#define wxListbook_SetSelection 1974
+#define wxListbook_ChangeSelection 1975
+#define wxListbook_destroy 1976
+#define wxTreebook_new_0 1977
+#define wxTreebook_new_3 1978
+#define wxTreebook_AddPage 1979
+#define wxTreebook_AdvanceSelection 1980
+#define wxTreebook_AssignImageList 1981
+#define wxTreebook_Create 1982
+#define wxTreebook_DeleteAllPages 1983
+#define wxTreebook_DeletePage 1984
+#define wxTreebook_RemovePage 1985
+#define wxTreebook_GetCurrentPage 1986
+#define wxTreebook_GetImageList 1987
+#define wxTreebook_GetPage 1989
+#define wxTreebook_GetPageCount 1990
+#define wxTreebook_GetPageImage 1991
+#define wxTreebook_GetPageText 1992
+#define wxTreebook_GetSelection 1993
+#define wxTreebook_ExpandNode 1994
+#define wxTreebook_IsNodeExpanded 1995
+#define wxTreebook_HitTest 1997
+#define wxTreebook_InsertPage 1998
+#define wxTreebook_InsertSubPage 1999
+#define wxTreebook_SetImageList 2000
+#define wxTreebook_SetPageSize 2001
+#define wxTreebook_SetPageImage 2002
+#define wxTreebook_SetPageText 2003
+#define wxTreebook_SetSelection 2004
+#define wxTreebook_ChangeSelection 2005
+#define wxTreebook_destroy 2006
+#define wxTreeCtrl_new_2 2009
+#define wxTreeCtrl_new_0 2010
+#define wxTreeCtrl_destruct 2012
+#define wxTreeCtrl_AddRoot 2013
+#define wxTreeCtrl_AppendItem 2014
+#define wxTreeCtrl_AssignImageList 2015
+#define wxTreeCtrl_AssignStateImageList 2016
+#define wxTreeCtrl_Collapse 2017
+#define wxTreeCtrl_CollapseAndReset 2018
+#define wxTreeCtrl_Create 2019
+#define wxTreeCtrl_Delete 2020
+#define wxTreeCtrl_DeleteAllItems 2021
+#define wxTreeCtrl_DeleteChildren 2022
+#define wxTreeCtrl_EditLabel 2023
+#define wxTreeCtrl_EnsureVisible 2024
+#define wxTreeCtrl_Expand 2025
+#define wxTreeCtrl_GetBoundingRect 2026
+#define wxTreeCtrl_GetChildrenCount 2028
+#define wxTreeCtrl_GetCount 2029
+#define wxTreeCtrl_GetEditControl 2030
+#define wxTreeCtrl_GetFirstChild 2031
+#define wxTreeCtrl_GetNextChild 2032
+#define wxTreeCtrl_GetFirstVisibleItem 2033
+#define wxTreeCtrl_GetImageList 2034
+#define wxTreeCtrl_GetIndent 2035
+#define wxTreeCtrl_GetItemBackgroundColour 2036
+#define wxTreeCtrl_GetItemData 2037
+#define wxTreeCtrl_GetItemFont 2038
+#define wxTreeCtrl_GetItemImage_1 2039
+#define wxTreeCtrl_GetItemImage_2 2040
+#define wxTreeCtrl_GetItemText 2041
+#define wxTreeCtrl_GetItemTextColour 2042
+#define wxTreeCtrl_GetLastChild 2043
+#define wxTreeCtrl_GetNextSibling 2044
+#define wxTreeCtrl_GetNextVisible 2045
+#define wxTreeCtrl_GetItemParent 2046
+#define wxTreeCtrl_GetPrevSibling 2047
+#define wxTreeCtrl_GetPrevVisible 2048
+#define wxTreeCtrl_GetRootItem 2049
+#define wxTreeCtrl_GetSelection 2050
+#define wxTreeCtrl_GetSelections 2051
+#define wxTreeCtrl_GetStateImageList 2052
+#define wxTreeCtrl_HitTest 2053
+#define wxTreeCtrl_InsertItem 2055
+#define wxTreeCtrl_IsBold 2056
+#define wxTreeCtrl_IsExpanded 2057
+#define wxTreeCtrl_IsSelected 2058
+#define wxTreeCtrl_IsVisible 2059
+#define wxTreeCtrl_ItemHasChildren 2060
+#define wxTreeCtrl_PrependItem 2061
+#define wxTreeCtrl_ScrollTo 2062
+#define wxTreeCtrl_SelectItem_1 2063
+#define wxTreeCtrl_SelectItem_2 2064
+#define wxTreeCtrl_SetIndent 2065
+#define wxTreeCtrl_SetImageList 2066
+#define wxTreeCtrl_SetItemBackgroundColour 2067
+#define wxTreeCtrl_SetItemBold 2068
+#define wxTreeCtrl_SetItemData 2069
+#define wxTreeCtrl_SetItemDropHighlight 2070
+#define wxTreeCtrl_SetItemFont 2071
+#define wxTreeCtrl_SetItemHasChildren 2072
+#define wxTreeCtrl_SetItemImage_2 2073
+#define wxTreeCtrl_SetItemImage_3 2074
+#define wxTreeCtrl_SetItemText 2075
+#define wxTreeCtrl_SetItemTextColour 2076
+#define wxTreeCtrl_SetStateImageList 2077
+#define wxTreeCtrl_SetWindowStyle 2078
+#define wxTreeCtrl_SortChildren 2079
+#define wxTreeCtrl_Toggle 2080
+#define wxTreeCtrl_ToggleItemSelection 2081
+#define wxTreeCtrl_Unselect 2082
+#define wxTreeCtrl_UnselectAll 2083
+#define wxTreeCtrl_UnselectItem 2084
+#define wxScrollBar_new_0 2085
+#define wxScrollBar_new_3 2086
+#define wxScrollBar_destruct 2087
+#define wxScrollBar_Create 2088
+#define wxScrollBar_GetRange 2089
+#define wxScrollBar_GetPageSize 2090
+#define wxScrollBar_GetThumbPosition 2091
+#define wxScrollBar_GetThumbSize 2092
+#define wxScrollBar_SetThumbPosition 2093
+#define wxScrollBar_SetScrollbar 2094
+#define wxSpinButton_new_2 2096
+#define wxSpinButton_new_0 2097
+#define wxSpinButton_Create 2098
+#define wxSpinButton_GetMax 2099
+#define wxSpinButton_GetMin 2100
+#define wxSpinButton_GetValue 2101
+#define wxSpinButton_SetRange 2102
+#define wxSpinButton_SetValue 2103
+#define wxSpinButton_destroy 2104
+#define wxSpinCtrl_new_0 2105
+#define wxSpinCtrl_new_2 2106
+#define wxSpinCtrl_Create 2108
+#define wxSpinCtrl_SetValue_1_1 2111
+#define wxSpinCtrl_SetValue_1_0 2112
+#define wxSpinCtrl_GetValue 2114
+#define wxSpinCtrl_SetRange 2116
+#define wxSpinCtrl_SetSelection 2117
+#define wxSpinCtrl_GetMin 2119
+#define wxSpinCtrl_GetMax 2121
+#define wxSpinCtrl_destroy 2122
+#define wxStaticText_new_0 2123
+#define wxStaticText_new_4 2124
+#define wxStaticText_Create 2125
+#define wxStaticText_GetLabel 2126
+#define wxStaticText_SetLabel 2127
+#define wxStaticText_Wrap 2128
+#define wxStaticText_destroy 2129
+#define wxStaticBitmap_new_0 2130
+#define wxStaticBitmap_new_4 2131
+#define wxStaticBitmap_Create 2132
+#define wxStaticBitmap_GetBitmap 2133
+#define wxStaticBitmap_SetBitmap 2134
+#define wxStaticBitmap_destroy 2135
+#define wxRadioBox_new 2136
+#define wxRadioBox_destruct 2138
+#define wxRadioBox_Create 2139
+#define wxRadioBox_Enable_2 2140
+#define wxRadioBox_Enable_1 2141
+#define wxRadioBox_GetSelection 2142
+#define wxRadioBox_GetString 2143
+#define wxRadioBox_SetSelection 2144
+#define wxRadioBox_Show_2 2145
+#define wxRadioBox_Show_1 2146
+#define wxRadioBox_GetColumnCount 2147
+#define wxRadioBox_GetItemHelpText 2148
+#define wxRadioBox_GetItemToolTip 2149
+#define wxRadioBox_GetItemFromPoint 2151
+#define wxRadioBox_GetRowCount 2152
+#define wxRadioBox_IsItemEnabled 2153
+#define wxRadioBox_IsItemShown 2154
+#define wxRadioBox_SetItemHelpText 2155
+#define wxRadioBox_SetItemToolTip 2156
+#define wxRadioButton_new_0 2157
+#define wxRadioButton_new_4 2158
+#define wxRadioButton_Create 2159
+#define wxRadioButton_GetValue 2160
+#define wxRadioButton_SetValue 2161
+#define wxRadioButton_destroy 2162
+#define wxSlider_new_6 2164
+#define wxSlider_new_0 2165
+#define wxSlider_Create 2166
+#define wxSlider_GetLineSize 2167
+#define wxSlider_GetMax 2168
+#define wxSlider_GetMin 2169
+#define wxSlider_GetPageSize 2170
+#define wxSlider_GetThumbLength 2171
+#define wxSlider_GetValue 2172
+#define wxSlider_SetLineSize 2173
+#define wxSlider_SetPageSize 2174
+#define wxSlider_SetRange 2175
+#define wxSlider_SetThumbLength 2176
+#define wxSlider_SetValue 2177
+#define wxSlider_destroy 2178
+#define wxDialog_new_4 2180
+#define wxDialog_new_0 2181
+#define wxDialog_destruct 2183
+#define wxDialog_Create 2184
+#define wxDialog_CreateButtonSizer 2185
+#define wxDialog_CreateStdDialogButtonSizer 2186
+#define wxDialog_EndModal 2187
+#define wxDialog_GetAffirmativeId 2188
+#define wxDialog_GetReturnCode 2189
+#define wxDialog_IsModal 2190
+#define wxDialog_SetAffirmativeId 2191
+#define wxDialog_SetReturnCode 2192
+#define wxDialog_Show 2193
+#define wxDialog_ShowModal 2194
+#define wxColourDialog_new_0 2195
+#define wxColourDialog_new_2 2196
+#define wxColourDialog_destruct 2197
+#define wxColourDialog_Create 2198
+#define wxColourDialog_GetColourData 2199
+#define wxColourData_new_0 2200
+#define wxColourData_new_1 2201
+#define wxColourData_destruct 2202
+#define wxColourData_GetChooseFull 2203
+#define wxColourData_GetColour 2204
+#define wxColourData_GetCustomColour 2206
+#define wxColourData_SetChooseFull 2207
+#define wxColourData_SetColour 2208
+#define wxColourData_SetCustomColour 2209
+#define wxPalette_new_0 2210
+#define wxPalette_new_4 2211
+#define wxPalette_destruct 2213
+#define wxPalette_Create 2214
+#define wxPalette_GetColoursCount 2215
+#define wxPalette_GetPixel 2216
+#define wxPalette_GetRGB 2217
+#define wxPalette_IsOk 2218
+#define wxDirDialog_new 2222
+#define wxDirDialog_destruct 2223
+#define wxDirDialog_GetPath 2224
+#define wxDirDialog_GetMessage 2225
+#define wxDirDialog_SetMessage 2226
+#define wxDirDialog_SetPath 2227
+#define wxFileDialog_new 2231
+#define wxFileDialog_destruct 2232
+#define wxFileDialog_GetDirectory 2233
+#define wxFileDialog_GetFilename 2234
+#define wxFileDialog_GetFilenames 2235
+#define wxFileDialog_GetFilterIndex 2236
+#define wxFileDialog_GetMessage 2237
+#define wxFileDialog_GetPath 2238
+#define wxFileDialog_GetPaths 2239
+#define wxFileDialog_GetWildcard 2240
+#define wxFileDialog_SetDirectory 2241
+#define wxFileDialog_SetFilename 2242
+#define wxFileDialog_SetFilterIndex 2243
+#define wxFileDialog_SetMessage 2244
+#define wxFileDialog_SetPath 2245
+#define wxFileDialog_SetWildcard 2246
+#define wxPickerBase_SetInternalMargin 2247
+#define wxPickerBase_GetInternalMargin 2248
+#define wxPickerBase_SetTextCtrlProportion 2249
+#define wxPickerBase_SetPickerCtrlProportion 2250
+#define wxPickerBase_GetTextCtrlProportion 2251
+#define wxPickerBase_GetPickerCtrlProportion 2252
+#define wxPickerBase_HasTextCtrl 2253
+#define wxPickerBase_GetTextCtrl 2254
+#define wxPickerBase_IsTextCtrlGrowable 2255
+#define wxPickerBase_SetPickerCtrlGrowable 2256
+#define wxPickerBase_SetTextCtrlGrowable 2257
+#define wxPickerBase_IsPickerCtrlGrowable 2258
+#define wxFilePickerCtrl_new_0 2259
+#define wxFilePickerCtrl_new_3 2260
+#define wxFilePickerCtrl_Create 2261
+#define wxFilePickerCtrl_GetPath 2262
+#define wxFilePickerCtrl_SetPath 2263
+#define wxFilePickerCtrl_destroy 2264
+#define wxDirPickerCtrl_new_0 2265
+#define wxDirPickerCtrl_new_3 2266
+#define wxDirPickerCtrl_Create 2267
+#define wxDirPickerCtrl_GetPath 2268
+#define wxDirPickerCtrl_SetPath 2269
+#define wxDirPickerCtrl_destroy 2270
+#define wxColourPickerCtrl_new_0 2271
+#define wxColourPickerCtrl_new_3 2272
+#define wxColourPickerCtrl_Create 2273
+#define wxColourPickerCtrl_GetColour 2274
+#define wxColourPickerCtrl_SetColour_1_1 2275
+#define wxColourPickerCtrl_SetColour_1_0 2276
+#define wxColourPickerCtrl_destroy 2277
+#define wxDatePickerCtrl_new_0 2278
+#define wxDatePickerCtrl_new_3 2279
+#define wxDatePickerCtrl_GetRange 2280
+#define wxDatePickerCtrl_GetValue 2281
+#define wxDatePickerCtrl_SetRange 2282
+#define wxDatePickerCtrl_SetValue 2283
+#define wxDatePickerCtrl_destroy 2284
+#define wxFontPickerCtrl_new_0 2285
+#define wxFontPickerCtrl_new_3 2286
+#define wxFontPickerCtrl_Create 2287
+#define wxFontPickerCtrl_GetSelectedFont 2288
+#define wxFontPickerCtrl_SetSelectedFont 2289
+#define wxFontPickerCtrl_GetMaxPointSize 2290
+#define wxFontPickerCtrl_SetMaxPointSize 2291
+#define wxFontPickerCtrl_destroy 2292
+#define wxFindReplaceDialog_new_0 2295
+#define wxFindReplaceDialog_new_4 2296
+#define wxFindReplaceDialog_destruct 2297
+#define wxFindReplaceDialog_Create 2298
+#define wxFindReplaceDialog_GetData 2299
+#define wxFindReplaceData_new_0 2300
+#define wxFindReplaceData_new_1 2301
+#define wxFindReplaceData_GetFindString 2302
+#define wxFindReplaceData_GetReplaceString 2303
+#define wxFindReplaceData_GetFlags 2304
+#define wxFindReplaceData_SetFlags 2305
+#define wxFindReplaceData_SetFindString 2306
+#define wxFindReplaceData_SetReplaceString 2307
+#define wxFindReplaceData_destroy 2308
+#define wxMultiChoiceDialog_new_0 2309
+#define wxMultiChoiceDialog_new_5 2311
+#define wxMultiChoiceDialog_GetSelections 2312
+#define wxMultiChoiceDialog_SetSelections 2313
+#define wxMultiChoiceDialog_destroy 2314
+#define wxSingleChoiceDialog_new_0 2315
+#define wxSingleChoiceDialog_new_5 2317
+#define wxSingleChoiceDialog_GetSelection 2318
+#define wxSingleChoiceDialog_GetStringSelection 2319
+#define wxSingleChoiceDialog_SetSelection 2320
+#define wxSingleChoiceDialog_destroy 2321
+#define wxTextEntryDialog_new 2322
+#define wxTextEntryDialog_GetValue 2323
+#define wxTextEntryDialog_SetValue 2324
+#define wxTextEntryDialog_destroy 2325
+#define wxPasswordEntryDialog_new 2326
+#define wxPasswordEntryDialog_destroy 2327
+#define wxFontData_new_0 2328
+#define wxFontData_new_1 2329
+#define wxFontData_destruct 2330
+#define wxFontData_EnableEffects 2331
+#define wxFontData_GetAllowSymbols 2332
+#define wxFontData_GetColour 2333
+#define wxFontData_GetChosenFont 2334
+#define wxFontData_GetEnableEffects 2335
+#define wxFontData_GetInitialFont 2336
+#define wxFontData_GetShowHelp 2337
+#define wxFontData_SetAllowSymbols 2338
+#define wxFontData_SetChosenFont 2339
+#define wxFontData_SetColour 2340
+#define wxFontData_SetInitialFont 2341
+#define wxFontData_SetRange 2342
+#define wxFontData_SetShowHelp 2343
+#define wxFontDialog_new_0 2347
+#define wxFontDialog_new_2 2349
+#define wxFontDialog_Create 2351
+#define wxFontDialog_GetFontData 2352
+#define wxFontDialog_destroy 2354
+#define wxProgressDialog_new 2355
+#define wxProgressDialog_destruct 2356
+#define wxProgressDialog_Resume 2357
+#define wxProgressDialog_Update_2 2358
+#define wxProgressDialog_Update_0 2359
+#define wxMessageDialog_new 2360
+#define wxMessageDialog_destruct 2361
+#define wxPageSetupDialog_new 2362
+#define wxPageSetupDialog_destruct 2363
+#define wxPageSetupDialog_GetPageSetupData 2364
+#define wxPageSetupDialog_ShowModal 2365
+#define wxPageSetupDialogData_new_0 2366
+#define wxPageSetupDialogData_new_1_0 2367
+#define wxPageSetupDialogData_new_1_1 2368
+#define wxPageSetupDialogData_destruct 2369
+#define wxPageSetupDialogData_EnableHelp 2370
+#define wxPageSetupDialogData_EnableMargins 2371
+#define wxPageSetupDialogData_EnableOrientation 2372
+#define wxPageSetupDialogData_EnablePaper 2373
+#define wxPageSetupDialogData_EnablePrinter 2374
+#define wxPageSetupDialogData_GetDefaultMinMargins 2375
+#define wxPageSetupDialogData_GetEnableMargins 2376
+#define wxPageSetupDialogData_GetEnableOrientation 2377
+#define wxPageSetupDialogData_GetEnablePaper 2378
+#define wxPageSetupDialogData_GetEnablePrinter 2379
+#define wxPageSetupDialogData_GetEnableHelp 2380
+#define wxPageSetupDialogData_GetDefaultInfo 2381
+#define wxPageSetupDialogData_GetMarginTopLeft 2382
+#define wxPageSetupDialogData_GetMarginBottomRight 2383
+#define wxPageSetupDialogData_GetMinMarginTopLeft 2384
+#define wxPageSetupDialogData_GetMinMarginBottomRight 2385
+#define wxPageSetupDialogData_GetPaperId 2386
+#define wxPageSetupDialogData_GetPaperSize 2387
+#define wxPageSetupDialogData_GetPrintData 2389
+#define wxPageSetupDialogData_IsOk 2390
+#define wxPageSetupDialogData_SetDefaultInfo 2391
+#define wxPageSetupDialogData_SetDefaultMinMargins 2392
+#define wxPageSetupDialogData_SetMarginTopLeft 2393
+#define wxPageSetupDialogData_SetMarginBottomRight 2394
+#define wxPageSetupDialogData_SetMinMarginTopLeft 2395
+#define wxPageSetupDialogData_SetMinMarginBottomRight 2396
+#define wxPageSetupDialogData_SetPaperId 2397
+#define wxPageSetupDialogData_SetPaperSize_1_1 2398
+#define wxPageSetupDialogData_SetPaperSize_1_0 2399
+#define wxPageSetupDialogData_SetPrintData 2400
+#define wxPrintDialog_new_2_0 2401
+#define wxPrintDialog_new_2_1 2402
+#define wxPrintDialog_destruct 2403
+#define wxPrintDialog_GetPrintDialogData 2404
+#define wxPrintDialog_GetPrintDC 2405
+#define wxPrintDialogData_new_0 2406
+#define wxPrintDialogData_new_1_1 2407
+#define wxPrintDialogData_new_1_0 2408
+#define wxPrintDialogData_destruct 2409
+#define wxPrintDialogData_EnableHelp 2410
+#define wxPrintDialogData_EnablePageNumbers 2411
+#define wxPrintDialogData_EnablePrintToFile 2412
+#define wxPrintDialogData_EnableSelection 2413
+#define wxPrintDialogData_GetAllPages 2414
+#define wxPrintDialogData_GetCollate 2415
+#define wxPrintDialogData_GetFromPage 2416
+#define wxPrintDialogData_GetMaxPage 2417
+#define wxPrintDialogData_GetMinPage 2418
+#define wxPrintDialogData_GetNoCopies 2419
+#define wxPrintDialogData_GetPrintData 2420
+#define wxPrintDialogData_GetPrintToFile 2421
+#define wxPrintDialogData_GetSelection 2422
+#define wxPrintDialogData_GetToPage 2423
+#define wxPrintDialogData_IsOk 2424
+#define wxPrintDialogData_SetCollate 2425
+#define wxPrintDialogData_SetFromPage 2426
+#define wxPrintDialogData_SetMaxPage 2427
+#define wxPrintDialogData_SetMinPage 2428
+#define wxPrintDialogData_SetNoCopies 2429
+#define wxPrintDialogData_SetPrintData 2430
+#define wxPrintDialogData_SetPrintToFile 2431
+#define wxPrintDialogData_SetSelection 2432
+#define wxPrintDialogData_SetToPage 2433
+#define wxPrintData_new_0 2434
+#define wxPrintData_new_1 2435
+#define wxPrintData_destruct 2436
+#define wxPrintData_GetCollate 2437
+#define wxPrintData_GetBin 2438
+#define wxPrintData_GetColour 2439
+#define wxPrintData_GetDuplex 2440
+#define wxPrintData_GetNoCopies 2441
+#define wxPrintData_GetOrientation 2442
+#define wxPrintData_GetPaperId 2443
+#define wxPrintData_GetPrinterName 2444
+#define wxPrintData_GetQuality 2445
+#define wxPrintData_IsOk 2446
+#define wxPrintData_SetBin 2447
+#define wxPrintData_SetCollate 2448
+#define wxPrintData_SetColour 2449
+#define wxPrintData_SetDuplex 2450
+#define wxPrintData_SetNoCopies 2451
+#define wxPrintData_SetOrientation 2452
+#define wxPrintData_SetPaperId 2453
+#define wxPrintData_SetPrinterName 2454
+#define wxPrintData_SetQuality 2455
+#define wxPrintPreview_new_2 2458
+#define wxPrintPreview_new_3 2459
+#define wxPrintPreview_destruct 2461
+#define wxPrintPreview_GetCanvas 2462
+#define wxPrintPreview_GetCurrentPage 2463
+#define wxPrintPreview_GetFrame 2464
+#define wxPrintPreview_GetMaxPage 2465
+#define wxPrintPreview_GetMinPage 2466
+#define wxPrintPreview_GetPrintout 2467
+#define wxPrintPreview_GetPrintoutForPrinting 2468
+#define wxPrintPreview_IsOk 2469
+#define wxPrintPreview_PaintPage 2470
+#define wxPrintPreview_Print 2471
+#define wxPrintPreview_RenderPage 2472
+#define wxPrintPreview_SetCanvas 2473
+#define wxPrintPreview_SetCurrentPage 2474
+#define wxPrintPreview_SetFrame 2475
+#define wxPrintPreview_SetPrintout 2476
+#define wxPrintPreview_SetZoom 2477
+#define wxPreviewFrame_new 2478
+#define wxPreviewFrame_destruct 2479
+#define wxPreviewFrame_CreateControlBar 2480
+#define wxPreviewFrame_CreateCanvas 2481
+#define wxPreviewFrame_Initialize 2482
+#define wxPreviewFrame_OnCloseWindow 2483
+#define wxPreviewControlBar_new 2484
+#define wxPreviewControlBar_destruct 2485
+#define wxPreviewControlBar_CreateButtons 2486
+#define wxPreviewControlBar_GetPrintPreview 2487
+#define wxPreviewControlBar_GetZoomControl 2488
+#define wxPreviewControlBar_SetZoomControl 2489
+#define wxPrinter_new 2491
+#define wxPrinter_CreateAbortWindow 2492
+#define wxPrinter_GetAbort 2493
+#define wxPrinter_GetLastError 2494
+#define wxPrinter_GetPrintDialogData 2495
+#define wxPrinter_Print 2496
+#define wxPrinter_PrintDialog 2497
+#define wxPrinter_ReportError 2498
+#define wxPrinter_Setup 2499
+#define wxPrinter_destroy 2500
+#define wxXmlResource_new_1 2501
+#define wxXmlResource_new_2 2502
+#define wxXmlResource_destruct 2503
+#define wxXmlResource_AttachUnknownControl 2504
+#define wxXmlResource_ClearHandlers 2505
+#define wxXmlResource_CompareVersion 2506
+#define wxXmlResource_Get 2507
+#define wxXmlResource_GetFlags 2508
+#define wxXmlResource_GetVersion 2509
+#define wxXmlResource_GetXRCID 2510
+#define wxXmlResource_InitAllHandlers 2511
+#define wxXmlResource_Load 2512
+#define wxXmlResource_LoadBitmap 2513
+#define wxXmlResource_LoadDialog_2 2514
+#define wxXmlResource_LoadDialog_3 2515
+#define wxXmlResource_LoadFrame_2 2516
+#define wxXmlResource_LoadFrame_3 2517
+#define wxXmlResource_LoadIcon 2518
+#define wxXmlResource_LoadMenu 2519
+#define wxXmlResource_LoadMenuBar_2 2520
+#define wxXmlResource_LoadMenuBar_1 2521
+#define wxXmlResource_LoadPanel_2 2522
+#define wxXmlResource_LoadPanel_3 2523
+#define wxXmlResource_LoadToolBar 2524
+#define wxXmlResource_Set 2525
+#define wxXmlResource_SetFlags 2526
+#define wxXmlResource_Unload 2527
+#define wxXmlResource_xrcctrl 2528
+#define wxHtmlEasyPrinting_new 2529
+#define wxHtmlEasyPrinting_destruct 2530
+#define wxHtmlEasyPrinting_GetPrintData 2531
+#define wxHtmlEasyPrinting_GetPageSetupData 2532
+#define wxHtmlEasyPrinting_PreviewFile 2533
+#define wxHtmlEasyPrinting_PreviewText 2534
+#define wxHtmlEasyPrinting_PrintFile 2535
+#define wxHtmlEasyPrinting_PrintText 2536
+#define wxHtmlEasyPrinting_PageSetup 2537
+#define wxHtmlEasyPrinting_SetFonts 2538
+#define wxHtmlEasyPrinting_SetHeader 2539
+#define wxHtmlEasyPrinting_SetFooter 2540
+#define wxGLCanvas_new_2 2542
+#define wxGLCanvas_new_3_1 2543
+#define wxGLCanvas_new_3_0 2544
+#define wxGLCanvas_GetContext 2545
+#define wxGLCanvas_SetCurrent 2547
+#define wxGLCanvas_SwapBuffers 2548
+#define wxGLCanvas_destroy 2549
+#define wxAuiManager_new 2550
+#define wxAuiManager_destruct 2551
+#define wxAuiManager_AddPane_2_1 2552
+#define wxAuiManager_AddPane_3 2553
+#define wxAuiManager_AddPane_2_0 2554
+#define wxAuiManager_DetachPane 2555
+#define wxAuiManager_GetAllPanes 2556
+#define wxAuiManager_GetArtProvider 2557
+#define wxAuiManager_GetDockSizeConstraint 2558
+#define wxAuiManager_GetFlags 2559
+#define wxAuiManager_GetManagedWindow 2560
+#define wxAuiManager_GetManager 2561
+#define wxAuiManager_GetPane_1_1 2562
+#define wxAuiManager_GetPane_1_0 2563
+#define wxAuiManager_HideHint 2564
+#define wxAuiManager_InsertPane 2565
+#define wxAuiManager_LoadPaneInfo 2566
+#define wxAuiManager_LoadPerspective 2567
+#define wxAuiManager_SavePaneInfo 2568
+#define wxAuiManager_SavePerspective 2569
+#define wxAuiManager_SetArtProvider 2570
+#define wxAuiManager_SetDockSizeConstraint 2571
+#define wxAuiManager_SetFlags 2572
+#define wxAuiManager_SetManagedWindow 2573
+#define wxAuiManager_ShowHint 2574
+#define wxAuiManager_UnInit 2575
+#define wxAuiManager_Update 2576
+#define wxAuiPaneInfo_new_0 2577
+#define wxAuiPaneInfo_new_1 2578
+#define wxAuiPaneInfo_destruct 2579
+#define wxAuiPaneInfo_BestSize_1 2580
+#define wxAuiPaneInfo_BestSize_2 2581
+#define wxAuiPaneInfo_Bottom 2582
+#define wxAuiPaneInfo_BottomDockable 2583
+#define wxAuiPaneInfo_Caption 2584
+#define wxAuiPaneInfo_CaptionVisible 2585
+#define wxAuiPaneInfo_Centre 2586
+#define wxAuiPaneInfo_CentrePane 2587
+#define wxAuiPaneInfo_CloseButton 2588
+#define wxAuiPaneInfo_DefaultPane 2589
+#define wxAuiPaneInfo_DestroyOnClose 2590
+#define wxAuiPaneInfo_Direction 2591
+#define wxAuiPaneInfo_Dock 2592
+#define wxAuiPaneInfo_Dockable 2593
+#define wxAuiPaneInfo_Fixed 2594
+#define wxAuiPaneInfo_Float 2595
+#define wxAuiPaneInfo_Floatable 2596
+#define wxAuiPaneInfo_FloatingPosition_1 2597
+#define wxAuiPaneInfo_FloatingPosition_2 2598
+#define wxAuiPaneInfo_FloatingSize_1 2599
+#define wxAuiPaneInfo_FloatingSize_2 2600
+#define wxAuiPaneInfo_Gripper 2601
+#define wxAuiPaneInfo_GripperTop 2602
+#define wxAuiPaneInfo_HasBorder 2603
+#define wxAuiPaneInfo_HasCaption 2604
+#define wxAuiPaneInfo_HasCloseButton 2605
+#define wxAuiPaneInfo_HasFlag 2606
+#define wxAuiPaneInfo_HasGripper 2607
+#define wxAuiPaneInfo_HasGripperTop 2608
+#define wxAuiPaneInfo_HasMaximizeButton 2609
+#define wxAuiPaneInfo_HasMinimizeButton 2610
+#define wxAuiPaneInfo_HasPinButton 2611
+#define wxAuiPaneInfo_Hide 2612
+#define wxAuiPaneInfo_IsBottomDockable 2613
+#define wxAuiPaneInfo_IsDocked 2614
+#define wxAuiPaneInfo_IsFixed 2615
+#define wxAuiPaneInfo_IsFloatable 2616
+#define wxAuiPaneInfo_IsFloating 2617
+#define wxAuiPaneInfo_IsLeftDockable 2618
+#define wxAuiPaneInfo_IsMovable 2619
+#define wxAuiPaneInfo_IsOk 2620
+#define wxAuiPaneInfo_IsResizable 2621
+#define wxAuiPaneInfo_IsRightDockable 2622
+#define wxAuiPaneInfo_IsShown 2623
+#define wxAuiPaneInfo_IsToolbar 2624
+#define wxAuiPaneInfo_IsTopDockable 2625
+#define wxAuiPaneInfo_Layer 2626
+#define wxAuiPaneInfo_Left 2627
+#define wxAuiPaneInfo_LeftDockable 2628
+#define wxAuiPaneInfo_MaxSize_1 2629
+#define wxAuiPaneInfo_MaxSize_2 2630
+#define wxAuiPaneInfo_MaximizeButton 2631
+#define wxAuiPaneInfo_MinSize_1 2632
+#define wxAuiPaneInfo_MinSize_2 2633
+#define wxAuiPaneInfo_MinimizeButton 2634
+#define wxAuiPaneInfo_Movable 2635
+#define wxAuiPaneInfo_Name 2636
+#define wxAuiPaneInfo_PaneBorder 2637
+#define wxAuiPaneInfo_PinButton 2638
+#define wxAuiPaneInfo_Position 2639
+#define wxAuiPaneInfo_Resizable 2640
+#define wxAuiPaneInfo_Right 2641
+#define wxAuiPaneInfo_RightDockable 2642
+#define wxAuiPaneInfo_Row 2643
+#define wxAuiPaneInfo_SafeSet 2644
+#define wxAuiPaneInfo_SetFlag 2645
+#define wxAuiPaneInfo_Show 2646
+#define wxAuiPaneInfo_ToolbarPane 2647
+#define wxAuiPaneInfo_Top 2648
+#define wxAuiPaneInfo_TopDockable 2649
+#define wxAuiPaneInfo_Window 2650
+#define wxAuiNotebook_new_0 2651
+#define wxAuiNotebook_new_2 2652
+#define wxAuiNotebook_AddPage 2653
+#define wxAuiNotebook_Create 2654
+#define wxAuiNotebook_DeletePage 2655
+#define wxAuiNotebook_GetArtProvider 2656
+#define wxAuiNotebook_GetPage 2657
+#define wxAuiNotebook_GetPageBitmap 2658
+#define wxAuiNotebook_GetPageCount 2659
+#define wxAuiNotebook_GetPageIndex 2660
+#define wxAuiNotebook_GetPageText 2661
+#define wxAuiNotebook_GetSelection 2662
+#define wxAuiNotebook_InsertPage 2663
+#define wxAuiNotebook_RemovePage 2664
+#define wxAuiNotebook_SetArtProvider 2665
+#define wxAuiNotebook_SetFont 2666
+#define wxAuiNotebook_SetPageBitmap 2667
+#define wxAuiNotebook_SetPageText 2668
+#define wxAuiNotebook_SetSelection 2669
+#define wxAuiNotebook_SetTabCtrlHeight 2670
+#define wxAuiNotebook_SetUniformBitmapSize 2671
+#define wxAuiNotebook_destroy 2672
+#define wxMDIParentFrame_new_0 2673
+#define wxMDIParentFrame_new_4 2674
+#define wxMDIParentFrame_destruct 2675
+#define wxMDIParentFrame_ActivateNext 2676
+#define wxMDIParentFrame_ActivatePrevious 2677
+#define wxMDIParentFrame_ArrangeIcons 2678
+#define wxMDIParentFrame_Cascade 2679
+#define wxMDIParentFrame_Create 2680
+#define wxMDIParentFrame_GetActiveChild 2681
+#define wxMDIParentFrame_GetClientWindow 2682
+#define wxMDIParentFrame_Tile 2683
+#define wxMDIChildFrame_new_0 2684
+#define wxMDIChildFrame_new_4 2685
+#define wxMDIChildFrame_destruct 2686
+#define wxMDIChildFrame_Activate 2687
+#define wxMDIChildFrame_Create 2688
+#define wxMDIChildFrame_Maximize 2689
+#define wxMDIChildFrame_Restore 2690
+#define wxMDIClientWindow_new_0 2691
+#define wxMDIClientWindow_new_2 2692
+#define wxMDIClientWindow_destruct 2693
+#define wxMDIClientWindow_CreateClient 2694
+#define wxLayoutAlgorithm_new 2695
+#define wxLayoutAlgorithm_LayoutFrame 2696
+#define wxLayoutAlgorithm_LayoutMDIFrame 2697
+#define wxLayoutAlgorithm_LayoutWindow 2698
+#define wxLayoutAlgorithm_destroy 2699
+#define wxEvent_GetId 2700
+#define wxEvent_GetSkipped 2701
+#define wxEvent_GetTimestamp 2702
+#define wxEvent_IsCommandEvent 2703
+#define wxEvent_ResumePropagation 2704
+#define wxEvent_ShouldPropagate 2705
+#define wxEvent_Skip 2706
+#define wxEvent_StopPropagation 2707
+#define wxCommandEvent_getClientData 2708
+#define wxCommandEvent_GetExtraLong 2709
+#define wxCommandEvent_GetInt 2710
+#define wxCommandEvent_GetSelection 2711
+#define wxCommandEvent_GetString 2712
+#define wxCommandEvent_IsChecked 2713
+#define wxCommandEvent_IsSelection 2714
+#define wxCommandEvent_SetInt 2715
+#define wxCommandEvent_SetString 2716
+#define wxScrollEvent_GetOrientation 2717
+#define wxScrollEvent_GetPosition 2718
+#define wxScrollWinEvent_GetOrientation 2719
+#define wxScrollWinEvent_GetPosition 2720
+#define wxMouseEvent_AltDown 2721
+#define wxMouseEvent_Button 2722
+#define wxMouseEvent_ButtonDClick 2723
+#define wxMouseEvent_ButtonDown 2724
+#define wxMouseEvent_ButtonUp 2725
+#define wxMouseEvent_CmdDown 2726
+#define wxMouseEvent_ControlDown 2727
+#define wxMouseEvent_Dragging 2728
+#define wxMouseEvent_Entering 2729
+#define wxMouseEvent_GetButton 2730
+#define wxMouseEvent_GetPosition 2733
+#define wxMouseEvent_GetLogicalPosition 2734
+#define wxMouseEvent_GetLinesPerAction 2735
+#define wxMouseEvent_GetWheelRotation 2736
+#define wxMouseEvent_GetWheelDelta 2737
+#define wxMouseEvent_GetX 2738
+#define wxMouseEvent_GetY 2739
+#define wxMouseEvent_IsButton 2740
+#define wxMouseEvent_IsPageScroll 2741
+#define wxMouseEvent_Leaving 2742
+#define wxMouseEvent_LeftDClick 2743
+#define wxMouseEvent_LeftDown 2744
+#define wxMouseEvent_LeftIsDown 2745
+#define wxMouseEvent_LeftUp 2746
+#define wxMouseEvent_MetaDown 2747
+#define wxMouseEvent_MiddleDClick 2748
+#define wxMouseEvent_MiddleDown 2749
+#define wxMouseEvent_MiddleIsDown 2750
+#define wxMouseEvent_MiddleUp 2751
+#define wxMouseEvent_Moving 2752
+#define wxMouseEvent_RightDClick 2753
+#define wxMouseEvent_RightDown 2754
+#define wxMouseEvent_RightIsDown 2755
+#define wxMouseEvent_RightUp 2756
+#define wxMouseEvent_ShiftDown 2757
+#define wxSetCursorEvent_GetCursor 2758
+#define wxSetCursorEvent_GetX 2759
+#define wxSetCursorEvent_GetY 2760
+#define wxSetCursorEvent_HasCursor 2761
+#define wxSetCursorEvent_SetCursor 2762
+#define wxKeyEvent_AltDown 2763
+#define wxKeyEvent_CmdDown 2764
+#define wxKeyEvent_ControlDown 2765
+#define wxKeyEvent_GetKeyCode 2766
+#define wxKeyEvent_GetModifiers 2767
+#define wxKeyEvent_GetPosition 2770
+#define wxKeyEvent_GetRawKeyCode 2771
+#define wxKeyEvent_GetRawKeyFlags 2772
+#define wxKeyEvent_GetUnicodeKey 2773
+#define wxKeyEvent_GetX 2774
+#define wxKeyEvent_GetY 2775
+#define wxKeyEvent_HasModifiers 2776
+#define wxKeyEvent_MetaDown 2777
+#define wxKeyEvent_ShiftDown 2778
+#define wxSizeEvent_GetSize 2779
+#define wxMoveEvent_GetPosition 2780
+#define wxEraseEvent_GetDC 2781
+#define wxFocusEvent_GetWindow 2782
+#define wxChildFocusEvent_GetWindow 2783
+#define wxMenuEvent_GetMenu 2784
+#define wxMenuEvent_GetMenuId 2785
+#define wxMenuEvent_IsPopup 2786
+#define wxCloseEvent_CanVeto 2787
+#define wxCloseEvent_GetLoggingOff 2788
+#define wxCloseEvent_SetCanVeto 2789
+#define wxCloseEvent_SetLoggingOff 2790
+#define wxCloseEvent_Veto 2791
+#define wxShowEvent_SetShow 2792
+#define wxShowEvent_GetShow 2793
+#define wxIconizeEvent_Iconized 2794
+#define wxJoystickEvent_ButtonDown 2795
+#define wxJoystickEvent_ButtonIsDown 2796
+#define wxJoystickEvent_ButtonUp 2797
+#define wxJoystickEvent_GetButtonChange 2798
+#define wxJoystickEvent_GetButtonState 2799
+#define wxJoystickEvent_GetJoystick 2800
+#define wxJoystickEvent_GetPosition 2801
+#define wxJoystickEvent_GetZPosition 2802
+#define wxJoystickEvent_IsButton 2803
+#define wxJoystickEvent_IsMove 2804
+#define wxJoystickEvent_IsZMove 2805
+#define wxUpdateUIEvent_CanUpdate 2806
+#define wxUpdateUIEvent_Check 2807
+#define wxUpdateUIEvent_Enable 2808
+#define wxUpdateUIEvent_Show 2809
+#define wxUpdateUIEvent_GetChecked 2810
+#define wxUpdateUIEvent_GetEnabled 2811
+#define wxUpdateUIEvent_GetShown 2812
+#define wxUpdateUIEvent_GetSetChecked 2813
+#define wxUpdateUIEvent_GetSetEnabled 2814
+#define wxUpdateUIEvent_GetSetShown 2815
+#define wxUpdateUIEvent_GetSetText 2816
+#define wxUpdateUIEvent_GetText 2817
+#define wxUpdateUIEvent_GetMode 2818
+#define wxUpdateUIEvent_GetUpdateInterval 2819
+#define wxUpdateUIEvent_ResetUpdateTime 2820
+#define wxUpdateUIEvent_SetMode 2821
+#define wxUpdateUIEvent_SetText 2822
+#define wxUpdateUIEvent_SetUpdateInterval 2823
+#define wxMouseCaptureChangedEvent_GetCapturedWindow 2824
+#define wxPaletteChangedEvent_SetChangedWindow 2825
+#define wxPaletteChangedEvent_GetChangedWindow 2826
+#define wxQueryNewPaletteEvent_SetPaletteRealized 2827
+#define wxQueryNewPaletteEvent_GetPaletteRealized 2828
+#define wxNavigationKeyEvent_GetDirection 2829
+#define wxNavigationKeyEvent_SetDirection 2830
+#define wxNavigationKeyEvent_IsWindowChange 2831
+#define wxNavigationKeyEvent_SetWindowChange 2832
+#define wxNavigationKeyEvent_IsFromTab 2833
+#define wxNavigationKeyEvent_SetFromTab 2834
+#define wxNavigationKeyEvent_GetCurrentFocus 2835
+#define wxNavigationKeyEvent_SetCurrentFocus 2836
+#define wxHelpEvent_GetOrigin 2837
+#define wxHelpEvent_GetPosition 2838
+#define wxHelpEvent_SetOrigin 2839
+#define wxHelpEvent_SetPosition 2840
+#define wxContextMenuEvent_GetPosition 2841
+#define wxContextMenuEvent_SetPosition 2842
+#define wxIdleEvent_CanSend 2843
+#define wxIdleEvent_GetMode 2844
+#define wxIdleEvent_RequestMore 2845
+#define wxIdleEvent_MoreRequested 2846
+#define wxIdleEvent_SetMode 2847
+#define wxGridEvent_AltDown 2848
+#define wxGridEvent_ControlDown 2849
+#define wxGridEvent_GetCol 2850
+#define wxGridEvent_GetPosition 2851
+#define wxGridEvent_GetRow 2852
+#define wxGridEvent_MetaDown 2853
+#define wxGridEvent_Selecting 2854
+#define wxGridEvent_ShiftDown 2855
+#define wxNotifyEvent_Allow 2856
+#define wxNotifyEvent_IsAllowed 2857
+#define wxNotifyEvent_Veto 2858
+#define wxSashEvent_GetEdge 2859
+#define wxSashEvent_GetDragRect 2860
+#define wxSashEvent_GetDragStatus 2861
+#define wxListEvent_GetCacheFrom 2862
+#define wxListEvent_GetCacheTo 2863
+#define wxListEvent_GetKeyCode 2864
+#define wxListEvent_GetIndex 2865
+#define wxListEvent_GetColumn 2866
+#define wxListEvent_GetPoint 2867
+#define wxListEvent_GetLabel 2868
+#define wxListEvent_GetText 2869
+#define wxListEvent_GetImage 2870
+#define wxListEvent_GetData 2871
+#define wxListEvent_GetMask 2872
+#define wxListEvent_GetItem 2873
+#define wxListEvent_IsEditCancelled 2874
+#define wxDateEvent_GetDate 2875
+#define wxCalendarEvent_GetWeekDay 2876
+#define wxFileDirPickerEvent_GetPath 2877
+#define wxColourPickerEvent_GetColour 2878
+#define wxFontPickerEvent_GetFont 2879
+#define wxStyledTextEvent_GetPosition 2880
+#define wxStyledTextEvent_GetKey 2881
+#define wxStyledTextEvent_GetModifiers 2882
+#define wxStyledTextEvent_GetModificationType 2883
+#define wxStyledTextEvent_GetText 2884
+#define wxStyledTextEvent_GetLength 2885
+#define wxStyledTextEvent_GetLinesAdded 2886
+#define wxStyledTextEvent_GetLine 2887
+#define wxStyledTextEvent_GetFoldLevelNow 2888
+#define wxStyledTextEvent_GetFoldLevelPrev 2889
+#define wxStyledTextEvent_GetMargin 2890
+#define wxStyledTextEvent_GetMessage 2891
+#define wxStyledTextEvent_GetWParam 2892
+#define wxStyledTextEvent_GetLParam 2893
+#define wxStyledTextEvent_GetListType 2894
+#define wxStyledTextEvent_GetX 2895
+#define wxStyledTextEvent_GetY 2896
+#define wxStyledTextEvent_GetDragText 2897
+#define wxStyledTextEvent_GetDragAllowMove 2898
+#define wxStyledTextEvent_GetDragResult 2899
+#define wxStyledTextEvent_GetShift 2900
+#define wxStyledTextEvent_GetControl 2901
+#define wxStyledTextEvent_GetAlt 2902
+#define utils_wxGetKeyState 2903
+#define utils_wxGetMousePosition 2904
+#define utils_wxGetMouseState 2905
+#define utils_wxSetDetectableAutoRepeat 2906
+#define utils_wxBell 2907
+#define utils_wxFindMenuItemId 2908
+#define utils_wxGenericFindWindowAtPoint 2909
+#define utils_wxFindWindowAtPoint 2910
+#define utils_wxBeginBusyCursor 2911
+#define utils_wxEndBusyCursor 2912
+#define utils_wxIsBusy 2913
+#define utils_wxShutdown 2914
+#define utils_wxShell 2915
+#define utils_wxLaunchDefaultBrowser 2916
+#define utils_wxGetEmailAddress 2917
+#define utils_wxGetUserId 2918
+#define utils_wxGetHomeDir 2919
+#define utils_wxNewId 2920
+#define utils_wxRegisterId 2921
+#define utils_wxGetCurrentId 2922
+#define utils_wxGetOsDescription 2923
+#define utils_wxIsPlatformLittleEndian 2924
+#define utils_wxIsPlatform64Bit 2925
+#define wxPrintout_new 2926
+#define wxPrintout_destruct 2927
+#define wxPrintout_GetDC 2928
+#define wxPrintout_GetPageSizeMM 2929
+#define wxPrintout_GetPageSizePixels 2930
+#define wxPrintout_GetPaperRectPixels 2931
+#define wxPrintout_GetPPIPrinter 2932
+#define wxPrintout_GetPPIScreen 2933
+#define wxPrintout_GetTitle 2934
+#define wxPrintout_IsPreview 2935
+#define wxPrintout_FitThisSizeToPaper 2936
+#define wxPrintout_FitThisSizeToPage 2937
+#define wxPrintout_FitThisSizeToPageMargins 2938
+#define wxPrintout_MapScreenSizeToPaper 2939
+#define wxPrintout_MapScreenSizeToPage 2940
+#define wxPrintout_MapScreenSizeToPageMargins 2941
+#define wxPrintout_MapScreenSizeToDevice 2942
+#define wxPrintout_GetLogicalPaperRect 2943
+#define wxPrintout_GetLogicalPageRect 2944
+#define wxPrintout_GetLogicalPageMarginsRect 2945
+#define wxPrintout_SetLogicalOrigin 2946
+#define wxPrintout_OffsetLogicalOrigin 2947
+#define wxStyledTextCtrl_new_2 2948
+#define wxStyledTextCtrl_new_0 2949
+#define wxStyledTextCtrl_destruct 2950
+#define wxStyledTextCtrl_Create 2951
+#define wxStyledTextCtrl_AddText 2952
+#define wxStyledTextCtrl_AddStyledText 2953
+#define wxStyledTextCtrl_InsertText 2954
+#define wxStyledTextCtrl_ClearAll 2955
+#define wxStyledTextCtrl_ClearDocumentStyle 2956
+#define wxStyledTextCtrl_GetLength 2957
+#define wxStyledTextCtrl_GetCharAt 2958
+#define wxStyledTextCtrl_GetCurrentPos 2959
+#define wxStyledTextCtrl_GetAnchor 2960
+#define wxStyledTextCtrl_GetStyleAt 2961
+#define wxStyledTextCtrl_Redo 2962
+#define wxStyledTextCtrl_SetUndoCollection 2963
+#define wxStyledTextCtrl_SelectAll 2964
+#define wxStyledTextCtrl_SetSavePoint 2965
+#define wxStyledTextCtrl_GetStyledText 2966
+#define wxStyledTextCtrl_CanRedo 2967
+#define wxStyledTextCtrl_MarkerLineFromHandle 2968
+#define wxStyledTextCtrl_MarkerDeleteHandle 2969
+#define wxStyledTextCtrl_GetUndoCollection 2970
+#define wxStyledTextCtrl_GetViewWhiteSpace 2971
+#define wxStyledTextCtrl_SetViewWhiteSpace 2972
+#define wxStyledTextCtrl_PositionFromPoint 2973
+#define wxStyledTextCtrl_PositionFromPointClose 2974
+#define wxStyledTextCtrl_GotoLine 2975
+#define wxStyledTextCtrl_GotoPos 2976
+#define wxStyledTextCtrl_SetAnchor 2977
+#define wxStyledTextCtrl_GetCurLine 2978
+#define wxStyledTextCtrl_GetEndStyled 2979
+#define wxStyledTextCtrl_ConvertEOLs 2980
+#define wxStyledTextCtrl_GetEOLMode 2981
+#define wxStyledTextCtrl_SetEOLMode 2982
+#define wxStyledTextCtrl_StartStyling 2983
+#define wxStyledTextCtrl_SetStyling 2984
+#define wxStyledTextCtrl_GetBufferedDraw 2985
+#define wxStyledTextCtrl_SetBufferedDraw 2986
+#define wxStyledTextCtrl_SetTabWidth 2987
+#define wxStyledTextCtrl_GetTabWidth 2988
+#define wxStyledTextCtrl_SetCodePage 2989
+#define wxStyledTextCtrl_MarkerDefine 2990
+#define wxStyledTextCtrl_MarkerSetForeground 2991
+#define wxStyledTextCtrl_MarkerSetBackground 2992
+#define wxStyledTextCtrl_MarkerAdd 2993
+#define wxStyledTextCtrl_MarkerDelete 2994
+#define wxStyledTextCtrl_MarkerDeleteAll 2995
+#define wxStyledTextCtrl_MarkerGet 2996
+#define wxStyledTextCtrl_MarkerNext 2997
+#define wxStyledTextCtrl_MarkerPrevious 2998
+#define wxStyledTextCtrl_MarkerDefineBitmap 2999
+#define wxStyledTextCtrl_MarkerAddSet 3000
+#define wxStyledTextCtrl_MarkerSetAlpha 3001
+#define wxStyledTextCtrl_SetMarginType 3002
+#define wxStyledTextCtrl_GetMarginType 3003
+#define wxStyledTextCtrl_SetMarginWidth 3004
+#define wxStyledTextCtrl_GetMarginWidth 3005
+#define wxStyledTextCtrl_SetMarginMask 3006
+#define wxStyledTextCtrl_GetMarginMask 3007
+#define wxStyledTextCtrl_SetMarginSensitive 3008
+#define wxStyledTextCtrl_GetMarginSensitive 3009
+#define wxStyledTextCtrl_StyleClearAll 3010
+#define wxStyledTextCtrl_StyleSetForeground 3011
+#define wxStyledTextCtrl_StyleSetBackground 3012
+#define wxStyledTextCtrl_StyleSetBold 3013
+#define wxStyledTextCtrl_StyleSetItalic 3014
+#define wxStyledTextCtrl_StyleSetSize 3015
+#define wxStyledTextCtrl_StyleSetFaceName 3016
+#define wxStyledTextCtrl_StyleSetEOLFilled 3017
+#define wxStyledTextCtrl_StyleResetDefault 3018
+#define wxStyledTextCtrl_StyleSetUnderline 3019
+#define wxStyledTextCtrl_StyleSetCase 3020
+#define wxStyledTextCtrl_StyleSetHotSpot 3021
+#define wxStyledTextCtrl_SetSelForeground 3022
+#define wxStyledTextCtrl_SetSelBackground 3023
+#define wxStyledTextCtrl_GetSelAlpha 3024
+#define wxStyledTextCtrl_SetSelAlpha 3025
+#define wxStyledTextCtrl_SetCaretForeground 3026
+#define wxStyledTextCtrl_CmdKeyAssign 3027
+#define wxStyledTextCtrl_CmdKeyClear 3028
+#define wxStyledTextCtrl_CmdKeyClearAll 3029
+#define wxStyledTextCtrl_SetStyleBytes 3030
+#define wxStyledTextCtrl_StyleSetVisible 3031
+#define wxStyledTextCtrl_GetCaretPeriod 3032
+#define wxStyledTextCtrl_SetCaretPeriod 3033
+#define wxStyledTextCtrl_SetWordChars 3034
+#define wxStyledTextCtrl_BeginUndoAction 3035
+#define wxStyledTextCtrl_EndUndoAction 3036
+#define wxStyledTextCtrl_IndicatorSetStyle 3037
+#define wxStyledTextCtrl_IndicatorGetStyle 3038
+#define wxStyledTextCtrl_IndicatorSetForeground 3039
+#define wxStyledTextCtrl_IndicatorGetForeground 3040
+#define wxStyledTextCtrl_SetWhitespaceForeground 3041
+#define wxStyledTextCtrl_SetWhitespaceBackground 3042
+#define wxStyledTextCtrl_GetStyleBits 3043
+#define wxStyledTextCtrl_SetLineState 3044
+#define wxStyledTextCtrl_GetLineState 3045
+#define wxStyledTextCtrl_GetMaxLineState 3046
+#define wxStyledTextCtrl_GetCaretLineVisible 3047
+#define wxStyledTextCtrl_SetCaretLineVisible 3048
+#define wxStyledTextCtrl_GetCaretLineBackground 3049
+#define wxStyledTextCtrl_SetCaretLineBackground 3050
+#define wxStyledTextCtrl_AutoCompShow 3051
+#define wxStyledTextCtrl_AutoCompCancel 3052
+#define wxStyledTextCtrl_AutoCompActive 3053
+#define wxStyledTextCtrl_AutoCompPosStart 3054
+#define wxStyledTextCtrl_AutoCompComplete 3055
+#define wxStyledTextCtrl_AutoCompStops 3056
+#define wxStyledTextCtrl_AutoCompSetSeparator 3057
+#define wxStyledTextCtrl_AutoCompGetSeparator 3058
+#define wxStyledTextCtrl_AutoCompSelect 3059
+#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3060
+#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3061
+#define wxStyledTextCtrl_AutoCompSetFillUps 3062
+#define wxStyledTextCtrl_AutoCompSetChooseSingle 3063
+#define wxStyledTextCtrl_AutoCompGetChooseSingle 3064
+#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3065
+#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3066
+#define wxStyledTextCtrl_UserListShow 3067
+#define wxStyledTextCtrl_AutoCompSetAutoHide 3068
+#define wxStyledTextCtrl_AutoCompGetAutoHide 3069
+#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3070
+#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3071
+#define wxStyledTextCtrl_RegisterImage 3072
+#define wxStyledTextCtrl_ClearRegisteredImages 3073
+#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3074
+#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3075
+#define wxStyledTextCtrl_AutoCompSetMaxWidth 3076
+#define wxStyledTextCtrl_AutoCompGetMaxWidth 3077
+#define wxStyledTextCtrl_AutoCompSetMaxHeight 3078
+#define wxStyledTextCtrl_AutoCompGetMaxHeight 3079
+#define wxStyledTextCtrl_SetIndent 3080
+#define wxStyledTextCtrl_GetIndent 3081
+#define wxStyledTextCtrl_SetUseTabs 3082
+#define wxStyledTextCtrl_GetUseTabs 3083
+#define wxStyledTextCtrl_SetLineIndentation 3084
+#define wxStyledTextCtrl_GetLineIndentation 3085
+#define wxStyledTextCtrl_GetLineIndentPosition 3086
+#define wxStyledTextCtrl_GetColumn 3087
+#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3088
+#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3089
+#define wxStyledTextCtrl_SetIndentationGuides 3090
+#define wxStyledTextCtrl_GetIndentationGuides 3091
+#define wxStyledTextCtrl_SetHighlightGuide 3092
+#define wxStyledTextCtrl_GetHighlightGuide 3093
+#define wxStyledTextCtrl_GetLineEndPosition 3094
+#define wxStyledTextCtrl_GetCodePage 3095
+#define wxStyledTextCtrl_GetCaretForeground 3096
+#define wxStyledTextCtrl_GetReadOnly 3097
+#define wxStyledTextCtrl_SetCurrentPos 3098
+#define wxStyledTextCtrl_SetSelectionStart 3099
+#define wxStyledTextCtrl_GetSelectionStart 3100
+#define wxStyledTextCtrl_SetSelectionEnd 3101
+#define wxStyledTextCtrl_GetSelectionEnd 3102
+#define wxStyledTextCtrl_SetPrintMagnification 3103
+#define wxStyledTextCtrl_GetPrintMagnification 3104
+#define wxStyledTextCtrl_SetPrintColourMode 3105
+#define wxStyledTextCtrl_GetPrintColourMode 3106
+#define wxStyledTextCtrl_FindText 3107
+#define wxStyledTextCtrl_FormatRange 3108
+#define wxStyledTextCtrl_GetFirstVisibleLine 3109
+#define wxStyledTextCtrl_GetLine 3110
+#define wxStyledTextCtrl_GetLineCount 3111
+#define wxStyledTextCtrl_SetMarginLeft 3112
+#define wxStyledTextCtrl_GetMarginLeft 3113
+#define wxStyledTextCtrl_SetMarginRight 3114
+#define wxStyledTextCtrl_GetMarginRight 3115
+#define wxStyledTextCtrl_GetModify 3116
+#define wxStyledTextCtrl_SetSelection 3117
+#define wxStyledTextCtrl_GetSelectedText 3118
+#define wxStyledTextCtrl_GetTextRange 3119
+#define wxStyledTextCtrl_HideSelection 3120
+#define wxStyledTextCtrl_LineFromPosition 3121
+#define wxStyledTextCtrl_PositionFromLine 3122
+#define wxStyledTextCtrl_LineScroll 3123
+#define wxStyledTextCtrl_EnsureCaretVisible 3124
+#define wxStyledTextCtrl_ReplaceSelection 3125
+#define wxStyledTextCtrl_SetReadOnly 3126
+#define wxStyledTextCtrl_CanPaste 3127
+#define wxStyledTextCtrl_CanUndo 3128
+#define wxStyledTextCtrl_EmptyUndoBuffer 3129
+#define wxStyledTextCtrl_Undo 3130
+#define wxStyledTextCtrl_Cut 3131
+#define wxStyledTextCtrl_Copy 3132
+#define wxStyledTextCtrl_Paste 3133
+#define wxStyledTextCtrl_Clear 3134
+#define wxStyledTextCtrl_SetText 3135
+#define wxStyledTextCtrl_GetText 3136
+#define wxStyledTextCtrl_GetTextLength 3137
+#define wxStyledTextCtrl_GetOvertype 3138
+#define wxStyledTextCtrl_SetCaretWidth 3139
+#define wxStyledTextCtrl_GetCaretWidth 3140
+#define wxStyledTextCtrl_SetTargetStart 3141
+#define wxStyledTextCtrl_GetTargetStart 3142
+#define wxStyledTextCtrl_SetTargetEnd 3143
+#define wxStyledTextCtrl_GetTargetEnd 3144
+#define wxStyledTextCtrl_ReplaceTarget 3145
+#define wxStyledTextCtrl_SearchInTarget 3146
+#define wxStyledTextCtrl_SetSearchFlags 3147
+#define wxStyledTextCtrl_GetSearchFlags 3148
+#define wxStyledTextCtrl_CallTipShow 3149
+#define wxStyledTextCtrl_CallTipCancel 3150
+#define wxStyledTextCtrl_CallTipActive 3151
+#define wxStyledTextCtrl_CallTipPosAtStart 3152
+#define wxStyledTextCtrl_CallTipSetHighlight 3153
+#define wxStyledTextCtrl_CallTipSetBackground 3154
+#define wxStyledTextCtrl_CallTipSetForeground 3155
+#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3156
+#define wxStyledTextCtrl_CallTipUseStyle 3157
+#define wxStyledTextCtrl_VisibleFromDocLine 3158
+#define wxStyledTextCtrl_DocLineFromVisible 3159
+#define wxStyledTextCtrl_WrapCount 3160
+#define wxStyledTextCtrl_SetFoldLevel 3161
+#define wxStyledTextCtrl_GetFoldLevel 3162
+#define wxStyledTextCtrl_GetLastChild 3163
+#define wxStyledTextCtrl_GetFoldParent 3164
+#define wxStyledTextCtrl_ShowLines 3165
+#define wxStyledTextCtrl_HideLines 3166
+#define wxStyledTextCtrl_GetLineVisible 3167
+#define wxStyledTextCtrl_SetFoldExpanded 3168
+#define wxStyledTextCtrl_GetFoldExpanded 3169
+#define wxStyledTextCtrl_ToggleFold 3170
+#define wxStyledTextCtrl_EnsureVisible 3171
+#define wxStyledTextCtrl_SetFoldFlags 3172
+#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3173
+#define wxStyledTextCtrl_SetTabIndents 3174
+#define wxStyledTextCtrl_GetTabIndents 3175
+#define wxStyledTextCtrl_SetBackSpaceUnIndents 3176
+#define wxStyledTextCtrl_GetBackSpaceUnIndents 3177
+#define wxStyledTextCtrl_SetMouseDwellTime 3178
+#define wxStyledTextCtrl_GetMouseDwellTime 3179
+#define wxStyledTextCtrl_WordStartPosition 3180
+#define wxStyledTextCtrl_WordEndPosition 3181
+#define wxStyledTextCtrl_SetWrapMode 3182
+#define wxStyledTextCtrl_GetWrapMode 3183
+#define wxStyledTextCtrl_SetWrapVisualFlags 3184
+#define wxStyledTextCtrl_GetWrapVisualFlags 3185
+#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3186
+#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3187
+#define wxStyledTextCtrl_SetWrapStartIndent 3188
+#define wxStyledTextCtrl_GetWrapStartIndent 3189
+#define wxStyledTextCtrl_SetLayoutCache 3190
+#define wxStyledTextCtrl_GetLayoutCache 3191
+#define wxStyledTextCtrl_SetScrollWidth 3192
+#define wxStyledTextCtrl_GetScrollWidth 3193
+#define wxStyledTextCtrl_TextWidth 3194
+#define wxStyledTextCtrl_GetEndAtLastLine 3195
+#define wxStyledTextCtrl_TextHeight 3196
+#define wxStyledTextCtrl_SetUseVerticalScrollBar 3197
+#define wxStyledTextCtrl_GetUseVerticalScrollBar 3198
+#define wxStyledTextCtrl_AppendText 3199
+#define wxStyledTextCtrl_GetTwoPhaseDraw 3200
+#define wxStyledTextCtrl_SetTwoPhaseDraw 3201
+#define wxStyledTextCtrl_TargetFromSelection 3202
+#define wxStyledTextCtrl_LinesJoin 3203
+#define wxStyledTextCtrl_LinesSplit 3204
+#define wxStyledTextCtrl_SetFoldMarginColour 3205
+#define wxStyledTextCtrl_SetFoldMarginHiColour 3206
+#define wxStyledTextCtrl_LineDown 3207
+#define wxStyledTextCtrl_LineDownExtend 3208
+#define wxStyledTextCtrl_LineUp 3209
+#define wxStyledTextCtrl_LineUpExtend 3210
+#define wxStyledTextCtrl_CharLeft 3211
+#define wxStyledTextCtrl_CharLeftExtend 3212
+#define wxStyledTextCtrl_CharRight 3213
+#define wxStyledTextCtrl_CharRightExtend 3214
+#define wxStyledTextCtrl_WordLeft 3215
+#define wxStyledTextCtrl_WordLeftExtend 3216
+#define wxStyledTextCtrl_WordRight 3217
+#define wxStyledTextCtrl_WordRightExtend 3218
+#define wxStyledTextCtrl_Home 3219
+#define wxStyledTextCtrl_HomeExtend 3220
+#define wxStyledTextCtrl_LineEnd 3221
+#define wxStyledTextCtrl_LineEndExtend 3222
+#define wxStyledTextCtrl_DocumentStart 3223
+#define wxStyledTextCtrl_DocumentStartExtend 3224
+#define wxStyledTextCtrl_DocumentEnd 3225
+#define wxStyledTextCtrl_DocumentEndExtend 3226
+#define wxStyledTextCtrl_PageUp 3227
+#define wxStyledTextCtrl_PageUpExtend 3228
+#define wxStyledTextCtrl_PageDown 3229
+#define wxStyledTextCtrl_PageDownExtend 3230
+#define wxStyledTextCtrl_EditToggleOvertype 3231
+#define wxStyledTextCtrl_Cancel 3232
+#define wxStyledTextCtrl_DeleteBack 3233
+#define wxStyledTextCtrl_Tab 3234
+#define wxStyledTextCtrl_BackTab 3235
+#define wxStyledTextCtrl_NewLine 3236
+#define wxStyledTextCtrl_FormFeed 3237
+#define wxStyledTextCtrl_VCHome 3238
+#define wxStyledTextCtrl_VCHomeExtend 3239
+#define wxStyledTextCtrl_ZoomIn 3240
+#define wxStyledTextCtrl_ZoomOut 3241
+#define wxStyledTextCtrl_DelWordLeft 3242
+#define wxStyledTextCtrl_DelWordRight 3243
+#define wxStyledTextCtrl_LineCut 3244
+#define wxStyledTextCtrl_LineDelete 3245
+#define wxStyledTextCtrl_LineTranspose 3246
+#define wxStyledTextCtrl_LineDuplicate 3247
+#define wxStyledTextCtrl_LowerCase 3248
+#define wxStyledTextCtrl_UpperCase 3249
+#define wxStyledTextCtrl_LineScrollDown 3250
+#define wxStyledTextCtrl_LineScrollUp 3251
+#define wxStyledTextCtrl_DeleteBackNotLine 3252
+#define wxStyledTextCtrl_HomeDisplay 3253
+#define wxStyledTextCtrl_HomeDisplayExtend 3254
+#define wxStyledTextCtrl_LineEndDisplay 3255
+#define wxStyledTextCtrl_LineEndDisplayExtend 3256
+#define wxStyledTextCtrl_HomeWrapExtend 3257
+#define wxStyledTextCtrl_LineEndWrap 3258
+#define wxStyledTextCtrl_LineEndWrapExtend 3259
+#define wxStyledTextCtrl_VCHomeWrap 3260
+#define wxStyledTextCtrl_VCHomeWrapExtend 3261
+#define wxStyledTextCtrl_LineCopy 3262
+#define wxStyledTextCtrl_MoveCaretInsideView 3263
+#define wxStyledTextCtrl_LineLength 3264
+#define wxStyledTextCtrl_BraceHighlight 3265
+#define wxStyledTextCtrl_BraceBadLight 3266
+#define wxStyledTextCtrl_BraceMatch 3267
+#define wxStyledTextCtrl_GetViewEOL 3268
+#define wxStyledTextCtrl_SetViewEOL 3269
+#define wxStyledTextCtrl_SetModEventMask 3270
+#define wxStyledTextCtrl_GetEdgeColumn 3271
+#define wxStyledTextCtrl_SetEdgeColumn 3272
+#define wxStyledTextCtrl_SetEdgeMode 3273
+#define wxStyledTextCtrl_GetEdgeMode 3274
+#define wxStyledTextCtrl_GetEdgeColour 3275
+#define wxStyledTextCtrl_SetEdgeColour 3276
+#define wxStyledTextCtrl_SearchAnchor 3277
+#define wxStyledTextCtrl_SearchNext 3278
+#define wxStyledTextCtrl_SearchPrev 3279
+#define wxStyledTextCtrl_LinesOnScreen 3280
+#define wxStyledTextCtrl_UsePopUp 3281
+#define wxStyledTextCtrl_SelectionIsRectangle 3282
+#define wxStyledTextCtrl_SetZoom 3283
+#define wxStyledTextCtrl_GetZoom 3284
+#define wxStyledTextCtrl_GetModEventMask 3285
+#define wxStyledTextCtrl_SetSTCFocus 3286
+#define wxStyledTextCtrl_GetSTCFocus 3287
+#define wxStyledTextCtrl_SetStatus 3288
+#define wxStyledTextCtrl_GetStatus 3289
+#define wxStyledTextCtrl_SetMouseDownCaptures 3290
+#define wxStyledTextCtrl_GetMouseDownCaptures 3291
+#define wxStyledTextCtrl_SetSTCCursor 3292
+#define wxStyledTextCtrl_GetSTCCursor 3293
+#define wxStyledTextCtrl_SetControlCharSymbol 3294
+#define wxStyledTextCtrl_GetControlCharSymbol 3295
+#define wxStyledTextCtrl_WordPartLeft 3296
+#define wxStyledTextCtrl_WordPartLeftExtend 3297
+#define wxStyledTextCtrl_WordPartRight 3298
+#define wxStyledTextCtrl_WordPartRightExtend 3299
+#define wxStyledTextCtrl_SetVisiblePolicy 3300
+#define wxStyledTextCtrl_DelLineLeft 3301
+#define wxStyledTextCtrl_DelLineRight 3302
+#define wxStyledTextCtrl_GetXOffset 3303
+#define wxStyledTextCtrl_ChooseCaretX 3304
+#define wxStyledTextCtrl_SetXCaretPolicy 3305
+#define wxStyledTextCtrl_SetYCaretPolicy 3306
+#define wxStyledTextCtrl_GetPrintWrapMode 3307
+#define wxStyledTextCtrl_SetHotspotActiveForeground 3308
+#define wxStyledTextCtrl_SetHotspotActiveBackground 3309
+#define wxStyledTextCtrl_SetHotspotActiveUnderline 3310
+#define wxStyledTextCtrl_SetHotspotSingleLine 3311
+#define wxStyledTextCtrl_ParaDownExtend 3312
+#define wxStyledTextCtrl_ParaUp 3313
+#define wxStyledTextCtrl_ParaUpExtend 3314
+#define wxStyledTextCtrl_PositionBefore 3315
+#define wxStyledTextCtrl_PositionAfter 3316
+#define wxStyledTextCtrl_CopyRange 3317
+#define wxStyledTextCtrl_CopyText 3318
+#define wxStyledTextCtrl_SetSelectionMode 3319
+#define wxStyledTextCtrl_GetSelectionMode 3320
+#define wxStyledTextCtrl_LineDownRectExtend 3321
+#define wxStyledTextCtrl_LineUpRectExtend 3322
+#define wxStyledTextCtrl_CharLeftRectExtend 3323
+#define wxStyledTextCtrl_CharRightRectExtend 3324
+#define wxStyledTextCtrl_HomeRectExtend 3325
+#define wxStyledTextCtrl_VCHomeRectExtend 3326
+#define wxStyledTextCtrl_LineEndRectExtend 3327
+#define wxStyledTextCtrl_PageUpRectExtend 3328
+#define wxStyledTextCtrl_PageDownRectExtend 3329
+#define wxStyledTextCtrl_StutteredPageUp 3330
+#define wxStyledTextCtrl_StutteredPageUpExtend 3331
+#define wxStyledTextCtrl_StutteredPageDown 3332
+#define wxStyledTextCtrl_StutteredPageDownExtend 3333
+#define wxStyledTextCtrl_WordLeftEnd 3334
+#define wxStyledTextCtrl_WordLeftEndExtend 3335
+#define wxStyledTextCtrl_WordRightEnd 3336
+#define wxStyledTextCtrl_WordRightEndExtend 3337
+#define wxStyledTextCtrl_SetWhitespaceChars 3338
+#define wxStyledTextCtrl_SetCharsDefault 3339
+#define wxStyledTextCtrl_AutoCompGetCurrent 3340
+#define wxStyledTextCtrl_Allocate 3341
+#define wxStyledTextCtrl_FindColumn 3342
+#define wxStyledTextCtrl_GetCaretSticky 3343
+#define wxStyledTextCtrl_SetCaretSticky 3344
+#define wxStyledTextCtrl_ToggleCaretSticky 3345
+#define wxStyledTextCtrl_SetPasteConvertEndings 3346
+#define wxStyledTextCtrl_GetPasteConvertEndings 3347
+#define wxStyledTextCtrl_SelectionDuplicate 3348
+#define wxStyledTextCtrl_SetCaretLineBackAlpha 3349
+#define wxStyledTextCtrl_GetCaretLineBackAlpha 3350
+#define wxStyledTextCtrl_StartRecord 3351
+#define wxStyledTextCtrl_StopRecord 3352
+#define wxStyledTextCtrl_SetLexer 3353
+#define wxStyledTextCtrl_GetLexer 3354
+#define wxStyledTextCtrl_Colourise 3355
+#define wxStyledTextCtrl_SetProperty 3356
+#define wxStyledTextCtrl_SetKeyWords 3357
+#define wxStyledTextCtrl_SetLexerLanguage 3358
+#define wxStyledTextCtrl_GetProperty 3359
+#define wxStyledTextCtrl_GetStyleBitsNeeded 3360
+#define wxStyledTextCtrl_GetCurrentLine 3361
+#define wxStyledTextCtrl_StyleSetSpec 3362
+#define wxStyledTextCtrl_StyleSetFont 3363
+#define wxStyledTextCtrl_StyleSetFontAttr 3364
+#define wxStyledTextCtrl_StyleSetCharacterSet 3365
+#define wxStyledTextCtrl_StyleSetFontEncoding 3366
+#define wxStyledTextCtrl_CmdKeyExecute 3367
+#define wxStyledTextCtrl_SetMargins 3368
+#define wxStyledTextCtrl_GetSelection 3369
+#define wxStyledTextCtrl_PointFromPosition 3370
+#define wxStyledTextCtrl_ScrollToLine 3371
+#define wxStyledTextCtrl_ScrollToColumn 3372
+#define wxStyledTextCtrl_SendMsg 3373
+#define wxStyledTextCtrl_SetVScrollBar 3374
+#define wxStyledTextCtrl_SetHScrollBar 3375
+#define wxStyledTextCtrl_GetLastKeydownProcessed 3376
+#define wxStyledTextCtrl_SetLastKeydownProcessed 3377
+#define wxStyledTextCtrl_SaveFile 3378
+#define wxStyledTextCtrl_LoadFile 3379
+#define wxStyledTextCtrl_DoDragOver 3380
+#define wxStyledTextCtrl_DoDropText 3381
+#define wxStyledTextCtrl_GetUseAntiAliasing 3382
+#define wxStyledTextCtrl_AddTextRaw 3383
+#define wxStyledTextCtrl_InsertTextRaw 3384
+#define wxStyledTextCtrl_GetCurLineRaw 3385
+#define wxStyledTextCtrl_GetLineRaw 3386
+#define wxStyledTextCtrl_GetSelectedTextRaw 3387
+#define wxStyledTextCtrl_GetTextRangeRaw 3388
+#define wxStyledTextCtrl_SetTextRaw 3389
+#define wxStyledTextCtrl_GetTextRaw 3390
+#define wxStyledTextCtrl_AppendTextRaw 3391
+#define wxArtProvider_GetBitmap 3392
+#define wxArtProvider_GetIcon 3393
+#define wxTreeEvent_GetKeyCode 3394
+#define wxTreeEvent_GetItem 3395
+#define wxTreeEvent_GetKeyEvent 3396
+#define wxTreeEvent_GetLabel 3397
+#define wxTreeEvent_GetOldItem 3398
+#define wxTreeEvent_GetPoint 3399
+#define wxTreeEvent_IsEditCancelled 3400
+#define wxTreeEvent_SetToolTip 3401
+#define wxNotebookEvent_GetOldSelection 3402
+#define wxNotebookEvent_GetSelection 3403
+#define wxNotebookEvent_SetOldSelection 3404
+#define wxNotebookEvent_SetSelection 3405
+#define wxFileDataObject_new 3406
+#define wxFileDataObject_AddFile 3407
+#define wxFileDataObject_GetFilenames 3408
+#define wxFileDataObject_destroy 3409
+#define wxTextDataObject_new 3410
+#define wxTextDataObject_GetTextLength 3411
+#define wxTextDataObject_GetText 3412
+#define wxTextDataObject_SetText 3413
+#define wxTextDataObject_destroy 3414
+#define wxBitmapDataObject_new_1_1 3415
+#define wxBitmapDataObject_new_1_0 3416
+#define wxBitmapDataObject_GetBitmap 3417
+#define wxBitmapDataObject_SetBitmap 3418
+#define wxBitmapDataObject_destroy 3419
+#define wxClipboard_new 3421
+#define wxClipboard_destruct 3422
+#define wxClipboard_AddData 3423
+#define wxClipboard_Clear 3424
+#define wxClipboard_Close 3425
+#define wxClipboard_Flush 3426
+#define wxClipboard_GetData 3427
+#define wxClipboard_IsOpened 3428
+#define wxClipboard_Open 3429
+#define wxClipboard_SetData 3430
+#define wxClipboard_UsePrimarySelection 3432
+#define wxClipboard_IsSupported 3433
+#define wxClipboard_Get 3434
+#define wxSpinEvent_GetPosition 3435
+#define wxSpinEvent_SetPosition 3436
+#define wxSplitterWindow_new_0 3437
+#define wxSplitterWindow_new_2 3438
+#define wxSplitterWindow_destruct 3439
+#define wxSplitterWindow_Create 3440
+#define wxSplitterWindow_GetMinimumPaneSize 3441
+#define wxSplitterWindow_GetSashGravity 3442
+#define wxSplitterWindow_GetSashPosition 3443
+#define wxSplitterWindow_GetSplitMode 3444
+#define wxSplitterWindow_GetWindow1 3445
+#define wxSplitterWindow_GetWindow2 3446
+#define wxSplitterWindow_Initialize 3447
+#define wxSplitterWindow_IsSplit 3448
+#define wxSplitterWindow_ReplaceWindow 3449
+#define wxSplitterWindow_SetSashGravity 3450
+#define wxSplitterWindow_SetSashPosition 3451
+#define wxSplitterWindow_SetSashSize 3452
+#define wxSplitterWindow_SetMinimumPaneSize 3453
+#define wxSplitterWindow_SetSplitMode 3454
+#define wxSplitterWindow_SplitHorizontally 3455
+#define wxSplitterWindow_SplitVertically 3456
+#define wxSplitterWindow_Unsplit 3457
+#define wxSplitterWindow_UpdateSize 3458
+#define wxSplitterEvent_GetSashPosition 3459
+#define wxSplitterEvent_GetX 3460
+#define wxSplitterEvent_GetY 3461
+#define wxSplitterEvent_GetWindowBeingRemoved 3462
+#define wxSplitterEvent_SetSashPosition 3463
+#define wxHtmlWindow_new_0 3464
+#define wxHtmlWindow_new_2 3465
+#define wxHtmlWindow_AppendToPage 3466
+#define wxHtmlWindow_GetOpenedAnchor 3467
+#define wxHtmlWindow_GetOpenedPage 3468
+#define wxHtmlWindow_GetOpenedPageTitle 3469
+#define wxHtmlWindow_GetRelatedFrame 3470
+#define wxHtmlWindow_HistoryBack 3471
+#define wxHtmlWindow_HistoryCanBack 3472
+#define wxHtmlWindow_HistoryCanForward 3473
+#define wxHtmlWindow_HistoryClear 3474
+#define wxHtmlWindow_HistoryForward 3475
+#define wxHtmlWindow_LoadFile 3476
+#define wxHtmlWindow_LoadPage 3477
+#define wxHtmlWindow_SelectAll 3478
+#define wxHtmlWindow_SelectionToText 3479
+#define wxHtmlWindow_SelectLine 3480
+#define wxHtmlWindow_SelectWord 3481
+#define wxHtmlWindow_SetBorders 3482
+#define wxHtmlWindow_SetFonts 3483
+#define wxHtmlWindow_SetPage 3484
+#define wxHtmlWindow_SetRelatedFrame 3485
+#define wxHtmlWindow_SetRelatedStatusBar 3486
+#define wxHtmlWindow_ToText 3487
+#define wxHtmlWindow_destroy 3488
+#define wxHtmlLinkEvent_GetLinkInfo 3489
+#define wxSystemSettings_GetColour 3490
+#define wxSystemSettings_GetFont 3491
+#define wxSystemSettings_GetMetric 3492
+#define wxSystemSettings_GetScreenType 3493
+#define wxSystemOptions_GetOption 3494
+#define wxSystemOptions_GetOptionInt 3495
+#define wxSystemOptions_HasOption 3496
+#define wxSystemOptions_IsFalse 3497
+#define wxSystemOptions_SetOption_2_1 3498
+#define wxSystemOptions_SetOption_2_0 3499
+#define wxAuiNotebookEvent_SetSelection 3500
+#define wxAuiNotebookEvent_GetSelection 3501
+#define wxAuiNotebookEvent_SetOldSelection 3502
+#define wxAuiNotebookEvent_GetOldSelection 3503
+#define wxAuiNotebookEvent_SetDragSource 3504
+#define wxAuiNotebookEvent_GetDragSource 3505
+#define wxAuiManagerEvent_SetManager 3506
+#define wxAuiManagerEvent_GetManager 3507
+#define wxAuiManagerEvent_SetPane 3508
+#define wxAuiManagerEvent_GetPane 3509
+#define wxAuiManagerEvent_SetButton 3510
+#define wxAuiManagerEvent_GetButton 3511
+#define wxAuiManagerEvent_SetDC 3512
+#define wxAuiManagerEvent_GetDC 3513
+#define wxAuiManagerEvent_Veto 3514
+#define wxAuiManagerEvent_GetVeto 3515
+#define wxAuiManagerEvent_SetCanVeto 3516
+#define wxAuiManagerEvent_CanVeto 3517
+#define wxLogNull_new 3518
+#define wxLogNull_destroy 3519
+#define wxTaskBarIcon_new 3520
+#define wxTaskBarIcon_destruct 3521
+#define wxTaskBarIcon_PopupMenu 3522
+#define wxTaskBarIcon_RemoveIcon 3523
+#define wxTaskBarIcon_SetIcon 3524
diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c
index 2404b13cc3..d1ed252ec0 100644
--- a/lib/wx/c_src/wxe_driver.c
+++ b/lib/wx/c_src/wxe_driver.c
@@ -40,9 +40,14 @@ static ErlDrvData wxe_driver_start(ErlDrvPort port, char *buff);
static int wxe_driver_load(void);
static void wxe_driver_stop(ErlDrvData handle);
static void wxe_driver_unload(void);
-static int wxe_driver_control(ErlDrvData handle, unsigned int command,
- char* buf, int count, char** res, int res_size);
-static int wxe_driver_call(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen, unsigned int *flags);
+static ErlDrvSSizeT wxe_driver_control(ErlDrvData handle,
+ unsigned int command,
+ char* buf, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size);
+static ErlDrvSSizeT wxe_driver_call(ErlDrvData drv_data, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen,
+ unsigned int *flags);
static void standard_outputv(ErlDrvData drv_data, ErlIOVec *ev);
static void wxe_process_died(ErlDrvData drv_data, ErlDrvMonitor *monitor);
@@ -151,17 +156,20 @@ wxe_driver_unload(void)
wxe_master = NULL;
}
-static int
+static ErlDrvSSizeT
wxe_driver_control(ErlDrvData handle, unsigned op,
- char* buf, int count, char** res, int res_size)
+ char* buf, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size)
{
wxe_data *sd = ((wxe_data *)handle);
push_command(op,buf,count,sd);
return 0;
}
-static int wxe_driver_call(ErlDrvData handle, unsigned int command,
- char *buf, int len, char **res, int rlen, unsigned int *flags)
+static ErlDrvSSizeT
+wxe_driver_call(ErlDrvData handle, unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **res, ErlDrvSizeT rlen, unsigned int *flags)
{
wxe_data *sd = ((wxe_data *)handle);
if(command == WXE_DEBUG_DRIVER) {
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index e430fbc7a2..69fcd4e362 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -331,9 +331,9 @@ 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 EV Start ");fflush(stderr);
+ //fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr);
app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
- // fprintf(stderr, ".. done \r\n");fflush(stderr);
+ //fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
wxe_batch_caller = 0;
erl_drv_mutex_unlock(wxe_batch_locker_m);
driver_demonitor_process(port, &monitor);
@@ -430,8 +430,9 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
wxeCommand *event = (wxeCommand *)node->GetData();
wxeMemEnv *memenv = getMemEnv(event->port);
batch->Erase(node);
+ // fprintf(stderr, " Ev %d %lu\r\n", event->op, event->caller);
if(event->caller == process || // Callbacks from CB process only
- event->op == WXE_CB_START || // Recursive event callback allow
+ event->op == WXE_CB_START || // Event callback start change process
// Allow connect_cb during CB i.e. msg from wxe_server.
(memenv && event->caller == memenv->owner))
{
@@ -453,6 +454,7 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
break;
default:
erl_drv_mutex_unlock(wxe_batch_locker_m);
+ size_t start=temp->GetCount();
if(event->op < OPENGL_START) {
// fprintf(stderr, " cb %d \r\n", event->op);
wxe_dispatch(*event);
@@ -460,9 +462,23 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
gl_dispatch(event->op,event->buffer,event->caller,event->bin);
}
erl_drv_mutex_lock(wxe_batch_locker_m);
- break;
+ if(temp->GetCount() > start) {
+ // We have recursed dispatch_cb and messages for this
+ // callback may be saved on temp list move them
+ // to orig list
+ for(wxList::compatibility_iterator node = temp->Item(start);
+ node;
+ node = node->GetNext()) {
+ wxeCommand *ev = (wxeCommand *)node->GetData();
+ if(ev->caller == process) {
+ batch->Append(ev);
+ temp->Erase(node);
+ }
+ }
+ }
if(callback_returned)
return;
+ break;
}
delete event;
} else {
diff --git a/lib/wx/c_src/wxe_return.cpp b/lib/wx/c_src/wxe_return.cpp
index 9fd627829e..0f3eb40efc 100644
--- a/lib/wx/c_src/wxe_return.cpp
+++ b/lib/wx/c_src/wxe_return.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -220,6 +220,16 @@ void wxeReturn::add(wxArrayInt val) {
endList(len);
}
+INLINE
+void wxeReturn::add(wxArrayDouble val) {
+ unsigned int len = val.GetCount();
+
+ for (unsigned int i = 0; i< len; i++) {
+ addFloat(val[i]);
+ }
+ endList(len);
+}
+
INLINE
void wxeReturn::add(wxUIntPtr *val) {
add(ERL_DRV_UINT, (ErlDrvTermData) val);
diff --git a/lib/wx/c_src/wxe_return.h b/lib/wx/c_src/wxe_return.h
index 0daf12eab2..b6bfa85e63 100644
--- a/lib/wx/c_src/wxe_return.h
+++ b/lib/wx/c_src/wxe_return.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2012. All Rights Reserved.
*
* The 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,6 +108,8 @@ public:
void add(wxArrayInt val);
+ void add(wxArrayDouble val);
+
void add(wxUIntPtr *val);
void add(const wxHtmlLinkInfo *val);
diff --git a/lib/wx/configure.in b/lib/wx/configure.in
index f7128db23a..8e5f696bc7 100755
--- a/lib/wx/configure.in
+++ b/lib/wx/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2008-2010. All Rights Reserved.
+dnl Copyright Ericsson AB 2008-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
@@ -67,55 +67,14 @@ AC_PROG_RANLIB
AC_PROG_CPP
AC_MSG_NOTICE(Building for [$host_os])
-MIXED_CYGWIN=no
WXERL_CAN_BUILD_DRIVER=true
-AC_MSG_CHECKING(for mixed cygwin and native VC++ environment)
-if test "X$CC" = "Xcc.sh" -a "X$host" = "Xwin32" -a "x$GCC" != x"yes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-Owx"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_VC=yes
- CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_VC=no
-fi
-AC_SUBST(MIXED_CYGWIN_VC)
-
-AC_MSG_CHECKING(for mixed cygwin and native MinGW environment)
-if test "X$CC" = "Xcc.sh" -a "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([yes])
- MIXED_CYGWIN_MINGW=yes
- CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW"
- else
- AC_MSG_RESULT([undeterminable])
- AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
- fi
-else
- AC_MSG_RESULT([no])
- MIXED_CYGWIN_MINGW=no
-fi
-AC_SUBST(MIXED_CYGWIN_MINGW)
+LM_WINDOWS_ENVIRONMENT
-AC_MSG_CHECKING(if we mix cygwin with any native compiler)
-if test "X$MIXED_CYGWIN" = "Xyes" ; then
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
+if test X"$MIXED_CYGWIN_VC" == X"yes" -o X"$MIXED_MSYS_VC" == X"yes"; then
+ CFLAGS="-Owx"
fi
-AC_SUBST(MIXED_CYGWIN)
-
-
## Check that we are in 32 bits mode on darwin
## (wxWidgets require that it currently uses 32-bits Carbon)
## Otherwise skip building wxErlang
@@ -138,10 +97,65 @@ esac
PTHR_CFLAGS="-D_THREAD_SAFE -D_REENTRANT"
+OBJC_CC=$CC
+OBJC_CFLAGS=""
+
dnl NOTE: CPPFLAGS will be included in CFLAGS at the end
case $host_os in
darwin*)
- C_ONLY_FLAGS="-ObjC"
+ AC_MSG_CHECKING([if compiler accepts -ObjC])
+ saved_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -ObjC"
+ AC_TRY_COMPILE([],[;], accept_objc_flag=true, accept_objc_flag=false)
+ if test "X$accept_objc_flag" = "Xtrue"; then
+ AC_MSG_RESULT([yes])
+ C_ONLY_FLAGS="-ObjC"
+ else
+ dnl We are probebly trying to build with a non-Apple gcc,
+ dnl which is good as long as we do not try to build Cocoa
+ dnl code. We need an Apple compiler for just that (Objective C)
+ AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([for a Cocoa compliant Objective C compiler])
+ SEARCHFOR=""
+ save_IFS=$IFS
+ IFS=:
+ set $PATH
+ IFS=$save_IFS
+ while test X"$1" != X""; do
+ dnl Add all possible paths to a real apple gcc
+ SEARCHFOR="$1/gcc-apple-4.2 $SEARCHFOR"
+ shift
+ done
+ dnl Add LLVM compilers, they will work in this case
+ SEARCHFOR="/usr/bin/clang /usr/bin/gcc $SEARCHFOR"
+ APPLE_CC=""
+ dnl SEARCHFOR is reversed, so we want to find the last existing
+ dnl executable in the list
+ for x in $SEARCHFOR; do
+ if test -x $x; then
+ APPLE_CC=$x
+ fi
+ done
+ if test X$APPLE_CC = X; then
+ AC_MSG_RESULT([no])
+ dnl Complete failure, we cannot build Cocoa code
+ if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then
+ AC_MSG_ERROR([Can not find compiler to compile Cocoa applications])
+ else
+ echo "Can not find compiler to compile Cocoa applications" > ./CONF_INFO
+ WXERL_CAN_BUILD_DRIVER=false
+ AC_MSG_WARN([Can not find compiler to compile Cocoa applications])
+ fi
+ WXERL_CAN_BUILD_DRIVER=false
+ else
+ dnl We think we found an Apple compiler and will add
+ dnl Apple specific options
+ AC_MSG_RESULT($APPLE_CC)
+ OBJC_CC=$APPLE_CC
+ OBJC_CFLAGS="-ObjC"
+ fi
+ fi
+ CFLAGS=$saved_CFLAGS
CPPFLAGS="$CPPFLAGS -D_MACOSX $PTHR_CFLAGS"
;;
mingw32)
@@ -159,10 +173,16 @@ case $host_os in
;;
esac
+AC_SUBST(OBJC_CC)
+AC_SUBST(OBJC_CFLAGS)
+
case $host_os in
darwin*)
- CFLAGS="-no-cpp-precomp $CFLAGS"
LDFLAGS="-bundle -flat_namespace -undefined warning -fPIC $LDFLAGS"
+ # Check sizof_void_p as future will hold 64bit MacOS wx
+ if test $ac_cv_sizeof_void_p = 4; then
+ LDFLAGS="-m32 $LDFLAGS"
+ fi
GL_LIBS="-framework OpenGL"
;;
win32)
@@ -287,7 +307,7 @@ dnl
if test "$cross_compiling" = "yes"; then
echo "Cross compilation of the wx driver is not supported yet, wx will NOT be usable" > ./CONF_INFO
WXERL_CAN_BUILD_DRIVER=false
-elif test X"$MIXED_CYGWIN_VC" != X"yes" ; then
+elif test X"$MIXED_CYGWIN_VC" == X"no" -a X"$MIXED_MSYS_VC" == X"no"; then
m4_include(wxwin.m4)
AM_OPTIONS_WXCONFIG
@@ -357,7 +377,11 @@ define(wx_warn_text,[
else
AC_MSG_CHECKING(for wxWidgets in standard locations)
- CWXWIN_CONFIG=`cygpath $wx_config_name 2>/dev/null`
+ if test "x$MIXED_MSYS" = "xyes"; then
+ CWXWIN_CONFIG=`win2msys_path.sh $wx_config_name 2>/dev/null`
+ else
+ CWXWIN_CONFIG=`cygpath $wx_config_name 2>/dev/null`
+ fi
CWXWIN1=`dirname $CWXWIN_CONFIG 2>/dev/null`
CWXWIN2=`dirname $CWXWIN1 2>/dev/null`
@@ -365,10 +389,24 @@ else
PROGRAMFILES=c:/Program Files
fi
- CWXWIN_PROG=`cygpath -d "$PROGRAMFILES" | cygpath -f - 2>/dev/null`
+
+ if test "x$MIXED_MSYS" = "xyes"; then
+ CWXWIN_PROG=`win2msys_path.sh "$PROGRAMFILES" 2>/dev/null`
+ else
+ CWXWIN_PROG=`cygpath -d "$PROGRAMFILES" | cygpath -f - 2>/dev/null`
+ fi
CWXWIN3=$CWXWIN_PROG/wxWidgets-2.8
CWXWIN4=$CWXWIN_PROG/wxMSW-2.8
CWX_DOCUMENTED="/opt/local/pgm/wxMSW-2.8.* /opt/local/pgm/wxWidgets-2.8.*"
+ case $ac_cv_sizeof_void_p in
+ 8)
+ CWX_DOCUMENTED="/opt/local64/pgm/wxMSW-2.8.* /opt/local64/pgm/wxWidgets-2.8.* $CWX_DOCUMENTED"
+ ;;
+ *)
+ true
+ ;;
+ esac
+
CWXPATH="$CWXWIN1 $CWXWIN2 $CWX_DOCUMENTED $CWXWIN3.* $CWXWIN4.*"
for dir in $CWXPATH; do
@@ -377,11 +415,11 @@ else
WXINCLUDE_PLAIN=$dir/include
WXINCLUDE_CONTRIB=$dir/contrib/include
WX_CFLAGS="-EHsc -D_UNICODE -DUNICODE -I$WXINCLUDE_MSVC -I$WXINCLUDE_PLAIN -I$WXINCLUDE_CONTRIB -D__WXMSW__"
- WX_CXXFLAGS=$WX_CFLAGS
+ WX_CXXFLAGS="-TP $WX_CFLAGS"
WX_LIBDIR=$dir/lib/vc_lib
WX_RESCOMP="rc.sh -I$WXINCLUDE_PLAIN -D __WIN32__"
RC_FILE_TYPE=res
- for lib in $WX_LIBDIR/wxbase*.lib; do
+ for lib in $WX_LIBDIR/wxbase*.lib $WX_LIBDIR2/wxbase*.lib; do
maybe=`echo $lib | egrep 'wxbase[[0-9]]*u\.lib'`
if test '!' -z "$maybe"; then
corelib_number=`echo $maybe | sed 's,.*\([[0-9]].\)u\.lib,\1,'`
@@ -515,7 +553,7 @@ AC_CHECK_HEADERS([wx/stc/stc.h],
[],
[WXERL_CAN_BUILD_DRIVER=false
echo "wxWidgets don't have wxStyledTextControl (stc.h), wx will NOT be useable" > ./CONF_INFO
- AC_MSG_WARN([Can not find wx/stc/stc.h])
+ AC_MSG_WARN([Can not find wx/stc/stc.h $CXXFLAGS])
],
[#ifdef WIN32
# include <windows.h>
@@ -533,7 +571,7 @@ if test X"$WX_HAVE_STATIC_LIBS" = X"true" ; then
LIBS=$WX_LIBS_STATIC
fi
-AC_LINK_IFELSE([
+AC_LINK_IFELSE([AC_LANG_SOURCE([
#ifdef WIN32
# include <windows.h>
# include <gl/gl.h>
@@ -545,6 +583,7 @@ AC_LINK_IFELSE([
#include "wx/wx.h"
#include "wx/stc/stc.h"
#include "wx/glcanvas.h"
+ ])
class MyApp : public wxApp
{
diff --git a/lib/wx/doc/src/Makefile b/lib/wx/doc/src/Makefile
index c8eb6174c4..4e6727b6a6 100644
--- a/lib/wx/doc/src/Makefile
+++ b/lib/wx/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
#
# The 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 ../../vsn.mk
include ../../config.mk
-APPLICATION=wxErlang
+APPLICATION=wx
ErlMods = wx.erl wx_object.erl
@@ -33,40 +33,7 @@ GenMods = $(shell ls ../../src/gen | grep 'wx[A-Z].*\.erl') \
ModsNoExt = $(ErlMods:%.erl=%) $(GenMods:%.erl=%)
-ifneq ($(INSIDE_ERLSRC),true)
-# ----------------------------------------------------
-# Standalone release
-# ----------------------------------------------------
-Mods = $(ErlMods:%=../../src/%) $(GenMods:%=../../src/gen/%)
-HTML_FILES = $(ErlMods:%.erl=../html/%.html) $(GenMods:%.erl=../html/%.html)
-
-GIF_FILES = ../html/erlang.png
-EXTRA_FILES = ../html/index.html \
- ../html/modules-frame.html \
- ../html/overview-summary.html \
- ../html/packages-frame.html
-
-HTML_STYLESHEET_FILES = ../html/stylesheet.css
-
-html: ../html/edoc-info
-
-docs: ../html/edoc-info
-
-../html/edoc-info: $(Mods)
- @echo "Building documentation."
- -mkdir -p ../html
- erl -noshell -pa doc -run edoc_run application "wx" '"../.."' '[{private,true},no_packages,{dir,"../html"}, {sort_functions,false}]'
-
-clean:
- rm -f *~
- (cd ../html; rm -f *.html *.css erlang.png edoc-info)
-
-opt debug:
-else
# Release directory specification
-# ----------------------------------------------------
-# Inside the erlang src
-# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = $(ErlMods:%.erl=%.xml) $(GenMods:%.erl=%.xml)
@@ -96,10 +63,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -117,30 +84,30 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-xml: $(XML_REF3_FILES) $(XML_CHAPTER_FILES)
+xml: $(XML_REF3_FILES) $(XML_CHAPTER_FILES)
-ref_man.xml: ref_man.xml.src
+ref_man.xml: ref_man.xml.src
@echo Preparing ref_man.xml
@cat ref_man.xml.src > ref_man.xml
@for d in $(ModsNoExt); do \
echo " <xi:include href=\"$$d.xml\"/>" >> ref_man.xml ; \
done
@echo "</application>" >> ref_man.xml
- @echo
+ @echo
-$(ErlMods:%.erl=%.xml):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -sort_functions false ../../src/$(@:%.xml=%.erl)
+$(ErlMods:%.erl=%.xml): ../../src/$(@:%.xml=%.erl)
+ escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -preprocess true -sort_functions false ../../src/$(@:%.xml=%.erl)
-$(GenMods:%.erl=%.xml):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -sort_functions false ../../src/gen/$(@:%.xml=%.erl)
+$(GenMods:%.erl=%.xml): ../../src/gen/$(@:%.xml=%.erl)
+ escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -i ../../src -preprocess true -sort_functions false ../../src/gen/$(@:%.xml=%.erl)
-$(XML_CHAPTER_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -chapter ../overview.edoc
+$(XML_CHAPTER_FILES): ../overview.edoc
+ escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -chapter ../overview.edoc
-debug opt:
+debug opt:
clean clean_docs:
- rm -rf $(HTMLDIR)/*
+ rm -rf $(HTMLDIR)/*
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~ ../html/edoc-info
@@ -148,22 +115,20 @@ clean clean_docs:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
-release_spec:
+release_spec:
release_tests_spec:
-
-endif
diff --git a/lib/wx/doc/src/make.dep b/lib/wx/doc/src/make.dep
deleted file mode 100644
index 91001be438..0000000000
--- a/lib/wx/doc/src/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex chapter.tex part.tex
-
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 7bd8d18592..1ba7e62d7d 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -31,6 +31,54 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 0.99.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Fix errors in wxDC and wxGraphicsContext api.</p>
+ <p>Add wxTaskBarIcon.</p> <p>Add
+ wxStyledTextControl:setEdgeMode/2.</p> <p>Add type and
+ specs for all functions and records.</p>
+ <p>
+ Own Id: OTP-9947</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 0.99.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a deadlock in the driver, which could happen if a
+ callback caused another callback to be invoked.</p>
+ <p>
+ Own Id: OTP-9725</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Implemented wxSystemOptions.</p>
+ <p>
+ Load Opengl from libGL.so.1 instead libGL.so to work
+ around linux problems.</p>
+ <p>
+ Own Id: OTP-9702</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 0.99</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/examples/Makefile b/lib/wx/examples/Makefile
index ae0ed687eb..48fccc88f7 100644
--- a/lib/wx/examples/Makefile
+++ b/lib/wx/examples/Makefile
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -22,24 +22,8 @@ include ../config.mk
SUBDIRS = demo sudoku simple xrc
-ifeq ($(INSIDE_ERLSRC),true)
SUB_DIRECTORIES=$(SUBDIRS)
# ----------------------------------------------------
# Default Subdir Targets
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_subdir.mk
-
-else
-# standalone build
-opt debug clean:
- @for d in $(SUBDIRS); do \
- if test ! -d $$d ; then \
- echo "=== Skipping subdir $$d" ; \
- else \
- (cd $$d && $(MAKE) $@) ; \
- fi ; \
- done
-
-docs:
-
-endif
diff --git a/lib/wx/examples/demo/Makefile b/lib/wx/examples/demo/Makefile
index 98d7c6a130..c60e9c3d50 100755..100644
--- a/lib/wx/examples/demo/Makefile
+++ b/lib/wx/examples/demo/Makefile
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -52,7 +52,7 @@ TESTMODS = \
ex_static \
ex_textCtrl \
ex_treeCtrl \
- ex_graphicsContext
+ ex_graphicsContext
TESTTARGETS = $(TESTMODS:%=%.beam)
@@ -64,23 +64,17 @@ clean:
rm -f $(TESTTARGETS)
rm -f *~ core erl_crash.dump
-docs:
+docs:
run: opt
- erl -smp -detached -pa $(TOPDIR)/ebin -s demo
-
-ifneq ($(INSIDE_ERLSRC),true)
+ erl -smp -detached -pa $(TOPDIR)/ebin -s demo
-%.beam: %.erl
- $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $<
-
-else
-EXRELSYSDIR = $(RELSYSDIR)/examples/demo
+EXRELSYSDIR = "$(RELSYSDIR)/examples/demo"
include $(ERL_TOP)/make/otp_release_targets.mk
-docs:
+docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
@@ -89,8 +83,3 @@ release_spec:
release_tests_spec:
release_docs_spec:
-
-endif
-
-
-
diff --git a/lib/wx/examples/demo/demo.erl b/lib/wx/examples/demo/demo.erl
index 59c20e09fb..61e71af021 100644
--- a/lib/wx/examples/demo/demo.erl
+++ b/lib/wx/examples/demo/demo.erl
@@ -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
@@ -27,7 +27,7 @@
-behaviour(wx_object).
-export([start/0, start/1, start_link/0, start_link/1, format/3,
init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-record(state, {win, demo, example, selector, log, code}).
@@ -189,6 +189,10 @@ handle_call(Msg, _From, State) ->
io:format("Got Call ~p~n",[Msg]),
{reply,ok,State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
%% Async Events are handled in handle_event as in handle_info
handle_event(#wx{event=#wxCommand{type=command_listbox_selected, cmdString=Ex}},
State = #state{demo={_,DemoSz}, example=Example, code=Code}) ->
diff --git a/lib/wx/examples/demo/ex_aui.erl b/lib/wx/examples/demo/ex_aui.erl
index 6adfd970fc..50f077638d 100644
--- a/lib/wx/examples/demo/ex_aui.erl
+++ b/lib/wx/examples/demo/ex_aui.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include("../../include/wx.hrl").
@@ -92,6 +92,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
%% Async Events are handled in handle_event as in handle_info
handle_event(#wx{obj = Notebook,
event = #wxCommand{type = command_button_clicked}},
diff --git a/lib/wx/examples/demo/ex_button.erl b/lib/wx/examples/demo/ex_button.erl
index 28c8273cb9..0dd0363933 100644
--- a/lib/wx/examples/demo/ex_button.erl
+++ b/lib/wx/examples/demo/ex_button.erl
@@ -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
@@ -26,7 +26,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-record(state,
{
@@ -153,6 +153,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p~n",[Msg]),
{reply,ok,State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl
index 844c7eddf3..1ec4760f40 100644
--- a/lib/wx/examples/demo/ex_canvas.erl
+++ b/lib/wx/examples/demo/ex_canvas.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2, handle_sync_event/3]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2, handle_sync_event/3]).
-include_lib("wx/include/wx.hrl").
@@ -144,6 +144,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_canvas_paint.erl b/lib/wx/examples/demo/ex_canvas_paint.erl
index 38d6b62f1d..9bc083766a 100644
--- a/lib/wx/examples/demo/ex_canvas_paint.erl
+++ b/lib/wx/examples/demo/ex_canvas_paint.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2, handle_sync_event/3]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2, handle_sync_event/3]).
-include_lib("wx/include/wx.hrl").
@@ -211,6 +211,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_choices.erl b/lib/wx/examples/demo/ex_choices.erl
index 75f8d22493..2e456ae249 100644
--- a/lib/wx/examples/demo/ex_choices.erl
+++ b/lib/wx/examples/demo/ex_choices.erl
@@ -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
@@ -21,7 +21,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -147,6 +147,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply, {error,nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_cursor.erl b/lib/wx/examples/demo/ex_cursor.erl
index 322bdcbb6c..c1a558541b 100644
--- a/lib/wx/examples/demo/ex_cursor.erl
+++ b/lib/wx/examples/demo/ex_cursor.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -135,6 +135,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_dialogs.erl b/lib/wx/examples/demo/ex_dialogs.erl
index 020e9eeb14..b39344f8b1 100644
--- a/lib/wx/examples/demo/ex_dialogs.erl
+++ b/lib/wx/examples/demo/ex_dialogs.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -153,6 +153,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_frame_utils.erl b/lib/wx/examples/demo/ex_frame_utils.erl
index 3064c9f3b7..a90642b355 100644
--- a/lib/wx/examples/demo/ex_frame_utils.erl
+++ b/lib/wx/examples/demo/ex_frame_utils.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -102,6 +102,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_gauge.erl b/lib/wx/examples/demo/ex_gauge.erl
index d30c3fea58..ffc667ff05 100644
--- a/lib/wx/examples/demo/ex_gauge.erl
+++ b/lib/wx/examples/demo/ex_gauge.erl
@@ -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
@@ -23,7 +23,7 @@
-include_lib("wx/include/wx.hrl").
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-record(gauge, {obj,
value,
@@ -118,6 +118,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply,ok, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
%% Async Events are handled in handle_event as in handle_info
handle_event(#wx{id = ?ID_START_STOP,
event = #wxCommand{type = command_togglebutton_clicked,
diff --git a/lib/wx/examples/demo/ex_gl.erl b/lib/wx/examples/demo/ex_gl.erl
index 53f1eda847..72dad2cf9d 100644
--- a/lib/wx/examples/demo/ex_gl.erl
+++ b/lib/wx/examples/demo/ex_gl.erl
@@ -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
@@ -21,7 +21,7 @@
-behaviour(wx_object).
-export([init/1, code_change/3, handle_info/2, handle_event/2,
- handle_call/3, terminate/2,
+ handle_call/3, handle_cast/2, terminate/2,
start/1]).
-include_lib("wx/include/wx.hrl").
@@ -118,6 +118,10 @@ handle_call(Msg, _From, State) ->
io:format("Got Call ~p~n",[Msg]),
{reply,ok,State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, not_yet_implemented, State}.
diff --git a/lib/wx/examples/demo/ex_graphicsContext.erl b/lib/wx/examples/demo/ex_graphicsContext.erl
index bcd7a75be0..c356500d99 100644
--- a/lib/wx/examples/demo/ex_graphicsContext.erl
+++ b/lib/wx/examples/demo/ex_graphicsContext.erl
@@ -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
@@ -26,7 +26,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
handle_info/2, handle_call/3,
- handle_event/2, handle_sync_event/3]).
+handle_cast/2, handle_event/2, handle_sync_event/3]).
-include_lib("wx/include/wx.hrl").
@@ -98,6 +98,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_grid.erl b/lib/wx/examples/demo/ex_grid.erl
index 2169c818ff..d1a9952ab2 100644
--- a/lib/wx/examples/demo/ex_grid.erl
+++ b/lib/wx/examples/demo/ex_grid.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -81,6 +81,10 @@ handle_info(_Msg, State) ->
handle_call(_Msg, _From, State) ->
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_htmlWindow.erl b/lib/wx/examples/demo/ex_htmlWindow.erl
index b864cd10b2..564c790e48 100644
--- a/lib/wx/examples/demo/ex_htmlWindow.erl
+++ b/lib/wx/examples/demo/ex_htmlWindow.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include("../../include/wx.hrl").
@@ -81,6 +81,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_listCtrl.erl b/lib/wx/examples/demo/ex_listCtrl.erl
index 3faec4e229..13096dfa52 100644
--- a/lib/wx/examples/demo/ex_listCtrl.erl
+++ b/lib/wx/examples/demo/ex_listCtrl.erl
@@ -23,7 +23,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-record(state,
{
@@ -147,6 +147,11 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply,ok,State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_notebook.erl b/lib/wx/examples/demo/ex_notebook.erl
index 2e16ccfffa..fc38fdae08 100644
--- a/lib/wx/examples/demo/ex_notebook.erl
+++ b/lib/wx/examples/demo/ex_notebook.erl
@@ -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
@@ -23,7 +23,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-record(state,
{
@@ -133,6 +133,11 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply,ok,State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_pickers.erl b/lib/wx/examples/demo/ex_pickers.erl
index 892c5b449d..8013a5ba32 100644
--- a/lib/wx/examples/demo/ex_pickers.erl
+++ b/lib/wx/examples/demo/ex_pickers.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -124,6 +124,11 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_popupMenu.erl b/lib/wx/examples/demo/ex_popupMenu.erl
index 8774dbef7b..d6778c5dc5 100644
--- a/lib/wx/examples/demo/ex_popupMenu.erl
+++ b/lib/wx/examples/demo/ex_popupMenu.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -90,6 +90,11 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_radioBox.erl b/lib/wx/examples/demo/ex_radioBox.erl
index 8211aec4a2..ab7685f41f 100644
--- a/lib/wx/examples/demo/ex_radioBox.erl
+++ b/lib/wx/examples/demo/ex_radioBox.erl
@@ -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
@@ -21,7 +21,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -107,6 +107,9 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply, {error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_sashWindow.erl b/lib/wx/examples/demo/ex_sashWindow.erl
index dd05f4e45f..d8a8958f28 100644
--- a/lib/wx/examples/demo/ex_sashWindow.erl
+++ b/lib/wx/examples/demo/ex_sashWindow.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -116,6 +116,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_sizers.erl b/lib/wx/examples/demo/ex_sizers.erl
index 2cc6efd503..7b9e8eb37f 100644
--- a/lib/wx/examples/demo/ex_sizers.erl
+++ b/lib/wx/examples/demo/ex_sizers.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -101,6 +101,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_slider.erl b/lib/wx/examples/demo/ex_slider.erl
index 7b669d96f6..612543ff26 100644
--- a/lib/wx/examples/demo/ex_slider.erl
+++ b/lib/wx/examples/demo/ex_slider.erl
@@ -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
@@ -21,7 +21,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -101,6 +101,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply, {error, nyi},State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_splitterWindow.erl b/lib/wx/examples/demo/ex_splitterWindow.erl
index c135f298fa..4f25b73293 100644
--- a/lib/wx/examples/demo/ex_splitterWindow.erl
+++ b/lib/wx/examples/demo/ex_splitterWindow.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -90,6 +90,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_static.erl b/lib/wx/examples/demo/ex_static.erl
index 67061520c4..013bd5ac35 100644
--- a/lib/wx/examples/demo/ex_static.erl
+++ b/lib/wx/examples/demo/ex_static.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -105,6 +105,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_textCtrl.erl b/lib/wx/examples/demo/ex_textCtrl.erl
index 95837c7c4c..d82884f30b 100644
--- a/lib/wx/examples/demo/ex_textCtrl.erl
+++ b/lib/wx/examples/demo/ex_textCtrl.erl
@@ -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
@@ -21,7 +21,7 @@
-behaviour(wx_object).
-export([start/1, init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -92,6 +92,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config,"Got Call ~p\n",[Msg]),
{reply, {error,nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/demo/ex_treeCtrl.erl b/lib/wx/examples/demo/ex_treeCtrl.erl
index fa40795393..611904500a 100644
--- a/lib/wx/examples/demo/ex_treeCtrl.erl
+++ b/lib/wx/examples/demo/ex_treeCtrl.erl
@@ -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
@@ -25,7 +25,7 @@
%% wx_object callbacks
-export([init/1, terminate/2, code_change/3,
- handle_info/2, handle_call/3, handle_event/2]).
+ handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
-include_lib("wx/include/wx.hrl").
@@ -109,6 +109,10 @@ handle_call(Msg, _From, State) ->
demo:format(State#state.config, "Got Call ~p\n", [Msg]),
{reply,{error, nyi}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, ignore, State}.
diff --git a/lib/wx/examples/simple/Makefile b/lib/wx/examples/simple/Makefile
index 41f0b46eb1..3f2bf01556 100644
--- a/lib/wx/examples/simple/Makefile
+++ b/lib/wx/examples/simple/Makefile
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -35,23 +35,17 @@ clean:
rm -f $(TESTTARGETS)
rm -f *~ core erl_crash.dump
-docs:
+docs:
run: opt
- erl -smp -detached -pa $(TOPDIR)/ebin -s hello
-
-ifneq ($(INSIDE_ERLSRC),true)
+ erl -smp -detached -pa $(TOPDIR)/ebin -s hello
-%.beam: %.erl
- $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $<
-
-else
-EXRELSYSDIR = $(RELSYSDIR)/examples/simple
+EXRELSYSDIR = "$(RELSYSDIR)/examples/simple"
include $(ERL_TOP)/make/otp_release_targets.mk
-docs:
+docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
$(INSTALL_DATA) copy.xpm sample.xpm $(TESTTARGETS) $(EXRELSYSDIR)
@@ -59,7 +53,3 @@ release_spec:
release_tests_spec:
release_docs_spec:
-
-endif
-
-
diff --git a/lib/wx/examples/simple/hello.erl b/lib/wx/examples/simple/hello.erl
index dc845ddfbb..02af1b501f 100755..100644
--- a/lib/wx/examples/simple/hello.erl
+++ b/lib/wx/examples/simple/hello.erl
@@ -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
diff --git a/lib/wx/examples/simple/menu.erl b/lib/wx/examples/simple/menu.erl
index d573fcf13a..0025a0b027 100755..100644
--- a/lib/wx/examples/simple/menu.erl
+++ b/lib/wx/examples/simple/menu.erl
@@ -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
diff --git a/lib/wx/examples/simple/minimal.erl b/lib/wx/examples/simple/minimal.erl
index dca4adc643..bdff66e217 100755..100644
--- a/lib/wx/examples/simple/minimal.erl
+++ b/lib/wx/examples/simple/minimal.erl
@@ -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
diff --git a/lib/wx/examples/simple/sample.xpm b/lib/wx/examples/simple/sample.xpm
index 3263b15f8a..3263b15f8a 100755..100644
--- a/lib/wx/examples/simple/sample.xpm
+++ b/lib/wx/examples/simple/sample.xpm
diff --git a/lib/wx/examples/sudoku/Makefile b/lib/wx/examples/sudoku/Makefile
index b86c654fdd..ec900f37e2 100755..100644
--- a/lib/wx/examples/sudoku/Makefile
+++ b/lib/wx/examples/sudoku/Makefile
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
@@ -25,7 +25,7 @@ SRC = .
BIN = .
ERLINC = $(TOPDIR)/include
ERLC = erlc
-TESTMODS = sudoku sudoku_board sudoku_game sudoku_gui
+TESTMODS = sudoku sudoku_board sudoku_game sudoku_gui
TESTTARGETS = $(TESTMODS:%=%.beam)
TESTSRC = $(TESTMODS:%=%.erl)
@@ -35,23 +35,17 @@ clean:
rm -f $(TESTTARGETS)
rm -f *~ core erl_crash.dump
-docs:
+docs:
run: opt
- erl -smp -detached -pa $(TOPDIR)/ebin -s sudoku
-
-ifneq ($(INSIDE_ERLSRC),true)
+ erl -smp -detached -pa $(TOPDIR)/ebin -s sudoku
-%.beam: %.erl
- $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $<
-
-else
-EXRELSYSDIR = $(RELSYSDIR)/examples/sudoku
+EXRELSYSDIR = "$(RELSYSDIR)/examples/sudoku"
include $(ERL_TOP)/make/otp_release_targets.mk
-docs:
+docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) sudoku.hrl $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
@@ -59,8 +53,3 @@ release_spec:
release_tests_spec:
release_docs_spec:
-
-endif
-
-
-
diff --git a/lib/wx/examples/sudoku/sudoku.erl b/lib/wx/examples/sudoku/sudoku.erl
index 01caeb9524..6749fec30a 100755..100644
--- a/lib/wx/examples/sudoku/sudoku.erl
+++ b/lib/wx/examples/sudoku/sudoku.erl
@@ -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
diff --git a/lib/wx/examples/sudoku/sudoku.hrl b/lib/wx/examples/sudoku/sudoku.hrl
index 775b563bdc..6bb2eefd07 100755..100644
--- a/lib/wx/examples/sudoku/sudoku.hrl
+++ b/lib/wx/examples/sudoku/sudoku.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
diff --git a/lib/wx/examples/sudoku/sudoku_board.erl b/lib/wx/examples/sudoku/sudoku_board.erl
index 756837582f..4b26ff97da 100755..100644
--- a/lib/wx/examples/sudoku/sudoku_board.erl
+++ b/lib/wx/examples/sudoku/sudoku_board.erl
@@ -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
@@ -30,7 +30,7 @@
draw/3,
%% Callbacks
init/1, handle_sync_event/3,
- handle_event/2, handle_info/2, handle_call/3,
+ handle_event/2, handle_info/2, handle_call/3, handle_cast/2,
code_change/3, terminate/2]).
-include("sudoku.hrl").
@@ -209,6 +209,10 @@ handle_call({draw, DC, Size},_From, S) ->
redraw(DC,Size,S),
{reply, ok, S}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, not_yet_implemented, State}.
diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl
index 470aee0e3b..ec705918b3 100755..100644
--- a/lib/wx/examples/sudoku/sudoku_game.erl
+++ b/lib/wx/examples/sudoku/sudoku_game.erl
@@ -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
diff --git a/lib/wx/examples/sudoku/sudoku_gui.erl b/lib/wx/examples/sudoku/sudoku_gui.erl
index 4aaecfe086..3d0c95ffa7 100755..100644
--- a/lib/wx/examples/sudoku/sudoku_gui.erl
+++ b/lib/wx/examples/sudoku/sudoku_gui.erl
@@ -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
@@ -24,7 +24,7 @@
%%%-------------------------------------------------------------------
-module(sudoku_gui).
--export([init/1, handle_info/2, handle_call/3, handle_event/2,
+-export([init/1, handle_info/2, handle_call/3, handle_cast/2, handle_event/2,
terminate/2, code_change/3]).
-compile(export_all).
@@ -230,6 +230,10 @@ handle_event(Msg,S) ->
handle_call(What, _From, State) ->
{stop, {call, What}, State}.
+handle_cast(Msg, State) ->
+ io:format("Got cast ~p~n",[Msg]),
+ {noreply,State}.
+
code_change(_, _, State) ->
{stop, not_yet_implemented, State}.
diff --git a/lib/wx/examples/xrc/Makefile b/lib/wx/examples/xrc/Makefile
index 1dfaae9689..9a976628a7 100755..100644
--- a/lib/wx/examples/xrc/Makefile
+++ b/lib/wx/examples/xrc/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009. All Rights Reserved.
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The 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 @@ TESTMODS = xrc
TESTTARGETS = $(TESTMODS:%=%.beam)
TESTSRC = $(TESTMODS:%=%.erl)
-RESOURCEFILES = appicon.ico basicdlg.xpm custclas.xpm fileopen.gif menu.xrc \
+RESOURCEFILES = \
+ appicon.ico basicdlg.xpm custclas.xpm fileopen.gif menu.xrc \
resource.xrc uncenter.xpm variable.xrc appicon.xpm basicdlg.xrc \
custclas.xrc filesave.gif platform.xpm stop.xpm uncenter.xrc \
artprov.xpm controls.xpm derivdlg.xpm frame.xrc platform.xrc \
@@ -48,18 +49,12 @@ docs:
run: opt
erl -smp -detached -pa $(TOPDIR)/ebin -s xrc
-ifneq ($(INSIDE_ERLSRC),true)
-
-%.beam: %.erl
- $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $<
-
-else
-EXRELSYSDIR = $(RELSYSDIR)/examples/xrc
+EXRELSYSDIR = "$(RELSYSDIR)/examples/xrc"
include $(ERL_TOP)/make/otp_release_targets.mk
docs:
-release_spec:
+release_spec: opt
$(INSTALL_DIR) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
$(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
@@ -70,7 +65,5 @@ release_tests_spec:
release_docs_spec:
-endif
-
diff --git a/lib/wx/include/gl.hrl b/lib/wx/include/gl.hrl
index 54eb551285..9004a8aa31 100644
--- a/lib/wx/include/gl.hrl
+++ b/lib/wx/include/gl.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 +37,16 @@
-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).
--define(GL_LINE_STRIP, 16#3).
--define(GL_TRIANGLES, 16#4).
--define(GL_TRIANGLE_STRIP, 16#5).
--define(GL_TRIANGLE_FAN, 16#6).
--define(GL_QUADS, 16#7).
--define(GL_QUAD_STRIP, 16#8).
--define(GL_POLYGON, 16#9).
+-define(GL_POINTS, 16#0000).
+-define(GL_LINES, 16#0001).
+-define(GL_LINE_LOOP, 16#0002).
+-define(GL_LINE_STRIP, 16#0003).
+-define(GL_TRIANGLES, 16#0004).
+-define(GL_TRIANGLE_STRIP, 16#0005).
+-define(GL_TRIANGLE_FAN, 16#0006).
+-define(GL_QUADS, 16#0007).
+-define(GL_QUAD_STRIP, 16#0008).
+-define(GL_POLYGON, 16#0009).
-define(GL_VERTEX_ARRAY, 16#8074).
-define(GL_NORMAL_ARRAY, 16#8075).
-define(GL_COLOR_ARRAY, 16#8076).
@@ -87,35 +87,35 @@
-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_MATRIX_MODE, 16#0BA0).
-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_SMOOTH, 16#0B10).
+-define(GL_POINT_SIZE, 16#0B11).
+-define(GL_POINT_SIZE_GRANULARITY, 16#0B13).
+-define(GL_POINT_SIZE_RANGE, 16#0B12).
+-define(GL_LINE_SMOOTH, 16#0B20).
+-define(GL_LINE_STIPPLE, 16#0B24).
+-define(GL_LINE_STIPPLE_PATTERN, 16#0B25).
+-define(GL_LINE_STIPPLE_REPEAT, 16#0B26).
+-define(GL_LINE_WIDTH, 16#0B21).
+-define(GL_LINE_WIDTH_GRANULARITY, 16#0B23).
+-define(GL_LINE_WIDTH_RANGE, 16#0B22).
-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_CW, 16#0900).
+-define(GL_CCW, 16#0901).
+-define(GL_FRONT, 16#0404).
+-define(GL_BACK, 16#0405).
+-define(GL_POLYGON_MODE, 16#0B40).
+-define(GL_POLYGON_SMOOTH, 16#0B41).
+-define(GL_POLYGON_STIPPLE, 16#0B42).
+-define(GL_EDGE_FLAG, 16#0B43).
+-define(GL_CULL_FACE, 16#0B44).
+-define(GL_CULL_FACE_MODE, 16#0B45).
+-define(GL_FRONT_FACE, 16#0B46).
-define(GL_POLYGON_OFFSET_FACTOR, 16#8038).
-define(GL_POLYGON_OFFSET_UNITS, 16#2A00).
-define(GL_POLYGON_OFFSET_POINT, 16#2A01).
@@ -123,25 +123,25 @@
-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).
--define(GL_LEQUAL, 16#203).
--define(GL_GREATER, 16#204).
--define(GL_NOTEQUAL, 16#205).
--define(GL_GEQUAL, 16#206).
--define(GL_ALWAYS, 16#207).
--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_LIST_BASE, 16#0B32).
+-define(GL_LIST_INDEX, 16#0B33).
+-define(GL_LIST_MODE, 16#0B30).
+-define(GL_NEVER, 16#0200).
+-define(GL_LESS, 16#0201).
+-define(GL_EQUAL, 16#0202).
+-define(GL_LEQUAL, 16#0203).
+-define(GL_GREATER, 16#0204).
+-define(GL_NOTEQUAL, 16#0205).
+-define(GL_GEQUAL, 16#0206).
+-define(GL_ALWAYS, 16#0207).
+-define(GL_DEPTH_TEST, 16#0B71).
+-define(GL_DEPTH_BITS, 16#0D56).
+-define(GL_DEPTH_CLEAR_VALUE, 16#0B73).
+-define(GL_DEPTH_FUNC, 16#0B74).
+-define(GL_DEPTH_RANGE, 16#0B70).
+-define(GL_DEPTH_WRITEMASK, 16#0B72).
-define(GL_DEPTH_COMPONENT, 16#1902).
--define(GL_LIGHTING, 16#B50).
+-define(GL_LIGHTING, 16#0B50).
-define(GL_LIGHT0, 16#4000).
-define(GL_LIGHT1, 16#4001).
-define(GL_LIGHT2, 16#4002).
@@ -164,85 +164,85 @@
-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_LIGHT_MODEL_TWO_SIDE, 16#0B52).
+-define(GL_LIGHT_MODEL_LOCAL_VIEWER, 16#0B51).
+-define(GL_LIGHT_MODEL_AMBIENT, 16#0B53).
+-define(GL_FRONT_AND_BACK, 16#0408).
+-define(GL_SHADE_MODEL, 16#0B54).
-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_COLOR_MATERIAL, 16#0B57).
+-define(GL_COLOR_MATERIAL_FACE, 16#0B55).
+-define(GL_COLOR_MATERIAL_PARAMETER, 16#0B56).
+-define(GL_NORMALIZE, 16#0BA1).
-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_ACCUM_RED_BITS, 16#0D58).
+-define(GL_ACCUM_GREEN_BITS, 16#0D59).
+-define(GL_ACCUM_BLUE_BITS, 16#0D5A).
+-define(GL_ACCUM_ALPHA_BITS, 16#0D5B).
+-define(GL_ACCUM_CLEAR_VALUE, 16#0B80).
+-define(GL_ACCUM, 16#0100).
+-define(GL_ADD, 16#0104).
+-define(GL_LOAD, 16#0101).
+-define(GL_MULT, 16#0103).
+-define(GL_RETURN, 16#0102).
+-define(GL_ALPHA_TEST, 16#0BC0).
+-define(GL_ALPHA_TEST_REF, 16#0BC2).
+-define(GL_ALPHA_TEST_FUNC, 16#0BC1).
+-define(GL_BLEND, 16#0BE2).
+-define(GL_BLEND_SRC, 16#0BE1).
+-define(GL_BLEND_DST, 16#0BE0).
-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).
--define(GL_ONE_MINUS_SRC_ALPHA, 16#303).
--define(GL_DST_ALPHA, 16#304).
--define(GL_ONE_MINUS_DST_ALPHA, 16#305).
--define(GL_DST_COLOR, 16#306).
--define(GL_ONE_MINUS_DST_COLOR, 16#307).
--define(GL_SRC_ALPHA_SATURATE, 16#308).
+-define(GL_SRC_COLOR, 16#0300).
+-define(GL_ONE_MINUS_SRC_COLOR, 16#0301).
+-define(GL_SRC_ALPHA, 16#0302).
+-define(GL_ONE_MINUS_SRC_ALPHA, 16#0303).
+-define(GL_DST_ALPHA, 16#0304).
+-define(GL_ONE_MINUS_DST_ALPHA, 16#0305).
+-define(GL_DST_COLOR, 16#0306).
+-define(GL_ONE_MINUS_DST_COLOR, 16#0307).
+-define(GL_SRC_ALPHA_SATURATE, 16#0308).
-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_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_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_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_2D, 16#0600).
+-define(GL_3D, 16#0601).
+-define(GL_3D_COLOR, 16#0602).
+-define(GL_3D_COLOR_TEXTURE, 16#0603).
+-define(GL_4D_COLOR_TEXTURE, 16#0604).
+-define(GL_POINT_TOKEN, 16#0701).
+-define(GL_LINE_TOKEN, 16#0702).
+-define(GL_LINE_RESET_TOKEN, 16#0707).
+-define(GL_POLYGON_TOKEN, 16#0703).
+-define(GL_BITMAP_TOKEN, 16#0704).
+-define(GL_DRAW_PIXEL_TOKEN, 16#0705).
+-define(GL_COPY_PIXEL_TOKEN, 16#0706).
+-define(GL_PASS_THROUGH_TOKEN, 16#0700).
+-define(GL_FEEDBACK_BUFFER_POINTER, 16#0DF0).
+-define(GL_FEEDBACK_BUFFER_SIZE, 16#0DF1).
+-define(GL_FEEDBACK_BUFFER_TYPE, 16#0DF2).
+-define(GL_SELECTION_BUFFER_POINTER, 16#0DF3).
+-define(GL_SELECTION_BUFFER_SIZE, 16#0DF4).
+-define(GL_FOG, 16#0B60).
+-define(GL_FOG_MODE, 16#0B65).
+-define(GL_FOG_DENSITY, 16#0B62).
+-define(GL_FOG_COLOR, 16#0B66).
+-define(GL_FOG_INDEX, 16#0B61).
+-define(GL_FOG_START, 16#0B63).
+-define(GL_FOG_END, 16#0B64).
-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_EXP, 16#0800).
+-define(GL_EXP2, 16#0801).
+-define(GL_LOGIC_OP, 16#0BF1).
+-define(GL_INDEX_LOGIC_OP, 16#0BF1).
+-define(GL_COLOR_LOGIC_OP, 16#0BF2).
+-define(GL_LOGIC_OP_MODE, 16#0BF0).
-define(GL_CLEAR, 16#1500).
-define(GL_SET, 16#150F).
-define(GL_COPY, 16#1503).
@@ -259,32 +259,32 @@
-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).
--define(GL_STENCIL_VALUE_MASK, 16#B93).
--define(GL_STENCIL_FAIL, 16#B94).
--define(GL_STENCIL_PASS_DEPTH_FAIL, 16#B95).
--define(GL_STENCIL_PASS_DEPTH_PASS, 16#B96).
--define(GL_STENCIL_REF, 16#B97).
--define(GL_STENCIL_WRITEMASK, 16#B98).
+-define(GL_STENCIL_BITS, 16#0D57).
+-define(GL_STENCIL_TEST, 16#0B90).
+-define(GL_STENCIL_CLEAR_VALUE, 16#0B91).
+-define(GL_STENCIL_FUNC, 16#0B92).
+-define(GL_STENCIL_VALUE_MASK, 16#0B93).
+-define(GL_STENCIL_FAIL, 16#0B94).
+-define(GL_STENCIL_PASS_DEPTH_FAIL, 16#0B95).
+-define(GL_STENCIL_PASS_DEPTH_PASS, 16#0B96).
+-define(GL_STENCIL_REF, 16#0B97).
+-define(GL_STENCIL_WRITEMASK, 16#0B98).
-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_LEFT, 16#0406).
+-define(GL_RIGHT, 16#0407).
+-define(GL_FRONT_LEFT, 16#0400).
+-define(GL_FRONT_RIGHT, 16#0401).
+-define(GL_BACK_LEFT, 16#0402).
+-define(GL_BACK_RIGHT, 16#0403).
+-define(GL_AUX0, 16#0409).
+-define(GL_AUX1, 16#040A).
+-define(GL_AUX2, 16#040B).
+-define(GL_AUX3, 16#040C).
-define(GL_COLOR_INDEX, 16#1900).
-define(GL_RED, 16#1903).
-define(GL_GREEN, 16#1904).
@@ -292,159 +292,161 @@
-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_READ_BUFFER, 16#C02).
--define(GL_DRAW_BUFFER, 16#C01).
--define(GL_DOUBLEBUFFER, 16#C32).
--define(GL_STEREO, 16#C33).
+-define(GL_ALPHA_BITS, 16#0D55).
+-define(GL_RED_BITS, 16#0D52).
+-define(GL_GREEN_BITS, 16#0D53).
+-define(GL_BLUE_BITS, 16#0D54).
+-define(GL_INDEX_BITS, 16#0D51).
+-define(GL_SUBPIXEL_BITS, 16#0D50).
+-define(GL_AUX_BUFFERS, 16#0C00).
+-define(GL_READ_BUFFER, 16#0C02).
+-define(GL_DRAW_BUFFER, 16#0C01).
+-define(GL_DOUBLEBUFFER, 16#0C32).
+-define(GL_STEREO, 16#0C33).
-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_DITHER, 16#0BD0).
-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).
--define(GL_MAX_TEXTURE_SIZE, 16#D33).
--define(GL_MAX_PIXEL_MAP_TABLE, 16#D34).
--define(GL_MAX_ATTRIB_STACK_DEPTH, 16#D35).
--define(GL_MAX_MODELVIEW_STACK_DEPTH, 16#D36).
--define(GL_MAX_NAME_STACK_DEPTH, 16#D37).
--define(GL_MAX_PROJECTION_STACK_DEPTH, 16#D38).
--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_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).
--define(GL_MAP1_NORMAL, 16#D92).
--define(GL_MAP1_TEXTURE_COORD_1, 16#D93).
--define(GL_MAP1_TEXTURE_COORD_2, 16#D94).
--define(GL_MAP1_TEXTURE_COORD_3, 16#D95).
--define(GL_MAP1_TEXTURE_COORD_4, 16#D96).
--define(GL_MAP1_VERTEX_3, 16#D97).
--define(GL_MAP1_VERTEX_4, 16#D98).
--define(GL_MAP2_COLOR_4, 16#DB0).
--define(GL_MAP2_INDEX, 16#DB1).
--define(GL_MAP2_NORMAL, 16#DB2).
--define(GL_MAP2_TEXTURE_COORD_1, 16#DB3).
--define(GL_MAP2_TEXTURE_COORD_2, 16#DB4).
--define(GL_MAP2_TEXTURE_COORD_3, 16#DB5).
--define(GL_MAP2_TEXTURE_COORD_4, 16#DB6).
--define(GL_MAP2_VERTEX_3, 16#DB7).
--define(GL_MAP2_VERTEX_4, 16#DB8).
--define(GL_MAP1_GRID_DOMAIN, 16#DD0).
--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_MAX_LIST_NESTING, 16#0B31).
+-define(GL_MAX_EVAL_ORDER, 16#0D30).
+-define(GL_MAX_LIGHTS, 16#0D31).
+-define(GL_MAX_CLIP_PLANES, 16#0D32).
+-define(GL_MAX_TEXTURE_SIZE, 16#0D33).
+-define(GL_MAX_PIXEL_MAP_TABLE, 16#0D34).
+-define(GL_MAX_ATTRIB_STACK_DEPTH, 16#0D35).
+-define(GL_MAX_MODELVIEW_STACK_DEPTH, 16#0D36).
+-define(GL_MAX_NAME_STACK_DEPTH, 16#0D37).
+-define(GL_MAX_PROJECTION_STACK_DEPTH, 16#0D38).
+-define(GL_MAX_TEXTURE_STACK_DEPTH, 16#0D39).
+-define(GL_MAX_VIEWPORT_DIMS, 16#0D3A).
+-define(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, 16#0D3B).
+-define(GL_ATTRIB_STACK_DEPTH, 16#0BB0).
+-define(GL_CLIENT_ATTRIB_STACK_DEPTH, 16#0BB1).
+-define(GL_COLOR_CLEAR_VALUE, 16#0C22).
+-define(GL_COLOR_WRITEMASK, 16#0C23).
+-define(GL_CURRENT_INDEX, 16#0B01).
+-define(GL_CURRENT_COLOR, 16#0B00).
+-define(GL_CURRENT_NORMAL, 16#0B02).
+-define(GL_CURRENT_RASTER_COLOR, 16#0B04).
+-define(GL_CURRENT_RASTER_DISTANCE, 16#0B09).
+-define(GL_CURRENT_RASTER_INDEX, 16#0B05).
+-define(GL_CURRENT_RASTER_POSITION, 16#0B07).
+-define(GL_CURRENT_RASTER_TEXTURE_COORDS, 16#0B06).
+-define(GL_CURRENT_RASTER_POSITION_VALID, 16#0B08).
+-define(GL_CURRENT_TEXTURE_COORDS, 16#0B03).
+-define(GL_INDEX_CLEAR_VALUE, 16#0C20).
+-define(GL_INDEX_MODE, 16#0C30).
+-define(GL_INDEX_WRITEMASK, 16#0C21).
+-define(GL_MODELVIEW_MATRIX, 16#0BA6).
+-define(GL_MODELVIEW_STACK_DEPTH, 16#0BA3).
+-define(GL_NAME_STACK_DEPTH, 16#0D70).
+-define(GL_PROJECTION_MATRIX, 16#0BA7).
+-define(GL_PROJECTION_STACK_DEPTH, 16#0BA4).
+-define(GL_RENDER_MODE, 16#0C40).
+-define(GL_RGBA_MODE, 16#0C31).
+-define(GL_TEXTURE_MATRIX, 16#0BA8).
+-define(GL_TEXTURE_STACK_DEPTH, 16#0BA5).
+-define(GL_VIEWPORT, 16#0BA2).
+-define(GL_AUTO_NORMAL, 16#0D80).
+-define(GL_MAP1_COLOR_4, 16#0D90).
+-define(GL_MAP1_INDEX, 16#0D91).
+-define(GL_MAP1_NORMAL, 16#0D92).
+-define(GL_MAP1_TEXTURE_COORD_1, 16#0D93).
+-define(GL_MAP1_TEXTURE_COORD_2, 16#0D94).
+-define(GL_MAP1_TEXTURE_COORD_3, 16#0D95).
+-define(GL_MAP1_TEXTURE_COORD_4, 16#0D96).
+-define(GL_MAP1_VERTEX_3, 16#0D97).
+-define(GL_MAP1_VERTEX_4, 16#0D98).
+-define(GL_MAP2_COLOR_4, 16#0DB0).
+-define(GL_MAP2_INDEX, 16#0DB1).
+-define(GL_MAP2_NORMAL, 16#0DB2).
+-define(GL_MAP2_TEXTURE_COORD_1, 16#0DB3).
+-define(GL_MAP2_TEXTURE_COORD_2, 16#0DB4).
+-define(GL_MAP2_TEXTURE_COORD_3, 16#0DB5).
+-define(GL_MAP2_TEXTURE_COORD_4, 16#0DB6).
+-define(GL_MAP2_VERTEX_3, 16#0DB7).
+-define(GL_MAP2_VERTEX_4, 16#0DB8).
+-define(GL_MAP1_GRID_DOMAIN, 16#0DD0).
+-define(GL_MAP1_GRID_SEGMENTS, 16#0DD1).
+-define(GL_MAP2_GRID_DOMAIN, 16#0DD2).
+-define(GL_MAP2_GRID_SEGMENTS, 16#0DD3).
+-define(GL_COEFF, 16#0A00).
+-define(GL_ORDER, 16#0A01).
+-define(GL_DOMAIN, 16#0A02).
+-define(GL_PERSPECTIVE_CORRECTION_HINT, 16#0C50).
+-define(GL_POINT_SMOOTH_HINT, 16#0C51).
+-define(GL_LINE_SMOOTH_HINT, 16#0C52).
+-define(GL_POLYGON_SMOOTH_HINT, 16#0C53).
+-define(GL_FOG_HINT, 16#0C54).
-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_SCISSOR_BOX, 16#0C10).
+-define(GL_SCISSOR_TEST, 16#0C11).
+-define(GL_MAP_COLOR, 16#0D10).
+-define(GL_MAP_STENCIL, 16#0D11).
+-define(GL_INDEX_SHIFT, 16#0D12).
+-define(GL_INDEX_OFFSET, 16#0D13).
+-define(GL_RED_SCALE, 16#0D14).
+-define(GL_RED_BIAS, 16#0D15).
+-define(GL_GREEN_SCALE, 16#0D18).
+-define(GL_GREEN_BIAS, 16#0D19).
+-define(GL_BLUE_SCALE, 16#0D1A).
+-define(GL_BLUE_BIAS, 16#0D1B).
+-define(GL_ALPHA_SCALE, 16#0D1C).
+-define(GL_ALPHA_BIAS, 16#0D1D).
+-define(GL_DEPTH_SCALE, 16#0D1E).
+-define(GL_DEPTH_BIAS, 16#0D1F).
+-define(GL_PIXEL_MAP_S_TO_S_SIZE, 16#0CB1).
+-define(GL_PIXEL_MAP_I_TO_I_SIZE, 16#0CB0).
+-define(GL_PIXEL_MAP_I_TO_R_SIZE, 16#0CB2).
+-define(GL_PIXEL_MAP_I_TO_G_SIZE, 16#0CB3).
+-define(GL_PIXEL_MAP_I_TO_B_SIZE, 16#0CB4).
+-define(GL_PIXEL_MAP_I_TO_A_SIZE, 16#0CB5).
+-define(GL_PIXEL_MAP_R_TO_R_SIZE, 16#0CB6).
+-define(GL_PIXEL_MAP_G_TO_G_SIZE, 16#0CB7).
+-define(GL_PIXEL_MAP_B_TO_B_SIZE, 16#0CB8).
+-define(GL_PIXEL_MAP_A_TO_A_SIZE, 16#0CB9).
+-define(GL_PIXEL_MAP_S_TO_S, 16#0C71).
+-define(GL_PIXEL_MAP_I_TO_I, 16#0C70).
+-define(GL_PIXEL_MAP_I_TO_R, 16#0C72).
+-define(GL_PIXEL_MAP_I_TO_G, 16#0C73).
+-define(GL_PIXEL_MAP_I_TO_B, 16#0C74).
+-define(GL_PIXEL_MAP_I_TO_A, 16#0C75).
+-define(GL_PIXEL_MAP_R_TO_R, 16#0C76).
+-define(GL_PIXEL_MAP_G_TO_G, 16#0C77).
+-define(GL_PIXEL_MAP_B_TO_B, 16#0C78).
+-define(GL_PIXEL_MAP_A_TO_A, 16#0C79).
+-define(GL_PACK_ALIGNMENT, 16#0D05).
+-define(GL_PACK_LSB_FIRST, 16#0D01).
+-define(GL_PACK_ROW_LENGTH, 16#0D02).
+-define(GL_PACK_SKIP_PIXELS, 16#0D04).
+-define(GL_PACK_SKIP_ROWS, 16#0D03).
+-define(GL_PACK_SWAP_BYTES, 16#0D00).
+-define(GL_UNPACK_ALIGNMENT, 16#0CF5).
+-define(GL_UNPACK_LSB_FIRST, 16#0CF1).
+-define(GL_UNPACK_ROW_LENGTH, 16#0CF2).
+-define(GL_UNPACK_SKIP_PIXELS, 16#0CF4).
+-define(GL_UNPACK_SKIP_ROWS, 16#0CF3).
+-define(GL_UNPACK_SWAP_BYTES, 16#0CF0).
+-define(GL_ZOOM_X, 16#0D16).
+-define(GL_ZOOM_Y, 16#0D17).
-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_TEXTURE_1D, 16#0DE0).
+-define(GL_TEXTURE_2D, 16#0DE1).
-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_S, 16#0C60).
+-define(GL_TEXTURE_GEN_T, 16#0C61).
+-define(GL_TEXTURE_GEN_R, 16#0C62).
+-define(GL_TEXTURE_GEN_Q, 16#0C63).
-define(GL_TEXTURE_GEN_MODE, 16#2500).
-define(GL_TEXTURE_BORDER_COLOR, 16#1004).
-define(GL_TEXTURE_WIDTH, 16#1000).
@@ -475,40 +477,38 @@
-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_INVALID_ENUM, 16#0500).
+-define(GL_INVALID_VALUE, 16#0501).
+-define(GL_INVALID_OPERATION, 16#0502).
+-define(GL_STACK_OVERFLOW, 16#0503).
+-define(GL_STACK_UNDERFLOW, 16#0504).
+-define(GL_OUT_OF_MEMORY, 16#0505).
+-define(GL_CURRENT_BIT, 16#00000001).
+-define(GL_POINT_BIT, 16#00000002).
+-define(GL_LINE_BIT, 16#00000004).
+-define(GL_POLYGON_BIT, 16#00000008).
+-define(GL_POLYGON_STIPPLE_BIT, 16#00000010).
+-define(GL_PIXEL_MODE_BIT, 16#00000020).
+-define(GL_LIGHTING_BIT, 16#00000040).
+-define(GL_FOG_BIT, 16#00000080).
+-define(GL_DEPTH_BUFFER_BIT, 16#00000100).
+-define(GL_ACCUM_BUFFER_BIT, 16#00000200).
+-define(GL_STENCIL_BUFFER_BIT, 16#00000400).
+-define(GL_VIEWPORT_BIT, 16#00000800).
+-define(GL_TRANSFORM_BIT, 16#00001000).
+-define(GL_ENABLE_BIT, 16#00002000).
+-define(GL_COLOR_BUFFER_BIT, 16#00004000).
+-define(GL_HINT_BIT, 16#00008000).
+-define(GL_EVAL_BIT, 16#00010000).
+-define(GL_LIST_BIT, 16#00020000).
+-define(GL_TEXTURE_BIT, 16#00040000).
+-define(GL_SCISSOR_BIT, 16#00080000).
+-define(GL_ALL_ATTRIB_BITS, 16#000FFFFF).
-define(GL_PROXY_TEXTURE_1D, 16#8063).
-define(GL_PROXY_TEXTURE_2D, 16#8064).
-define(GL_TEXTURE_PRIORITY, 16#8066).
@@ -549,8 +549,8 @@
-define(GL_RGB10_A2, 16#8059).
-define(GL_RGBA12, 16#805A).
-define(GL_RGBA16, 16#805B).
--define(GL_CLIENT_PIXEL_STORE_BIT, 16#1).
--define(GL_CLIENT_VERTEX_ARRAY_BIT, 16#2).
+-define(GL_CLIENT_PIXEL_STORE_BIT, 16#00000001).
+-define(GL_CLIENT_VERTEX_ARRAY_BIT, 16#00000002).
-define(GL_ALL_CLIENT_ATTRIB_BITS, 16#FFFFFFFF).
-define(GL_CLIENT_ALL_ATTRIB_BITS, 16#FFFFFFFF).
-define(GL_RESCALE_NORMAL, 16#803A).
@@ -578,10 +578,10 @@
-define(GL_TEXTURE_MAX_LOD, 16#813B).
-define(GL_TEXTURE_BASE_LEVEL, 16#813C).
-define(GL_TEXTURE_MAX_LEVEL, 16#813D).
--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_SMOOTH_POINT_SIZE_RANGE, 16#0B12).
+-define(GL_SMOOTH_POINT_SIZE_GRANULARITY, 16#0B13).
+-define(GL_SMOOTH_LINE_WIDTH_RANGE, 16#0B22).
+-define(GL_SMOOTH_LINE_WIDTH_GRANULARITY, 16#0B23).
-define(GL_ALIASED_POINT_SIZE_RANGE, 16#846D).
-define(GL_ALIASED_LINE_WIDTH_RANGE, 16#846E).
-define(GL_PACK_SKIP_IMAGES, 16#806B).
@@ -808,14 +808,14 @@
-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_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).
@@ -828,7 +828,7 @@
-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_GLEXT_VERSION, 75).
-define(GL_BLEND_DST_RGB, 16#80C8).
-define(GL_BLEND_SRC_RGB, 16#80C9).
-define(GL_BLEND_DST_ALPHA, 16#80CA).
@@ -1034,16 +1034,14 @@
-define(GL_CLIP_DISTANCE5, 16#3005).
-define(GL_CLIP_DISTANCE6, 16#3006).
-define(GL_CLIP_DISTANCE7, 16#3007).
--define(GL_MAX_CLIP_DISTANCES, 16#D32).
+-define(GL_MAX_CLIP_DISTANCES, 16#0D32).
-define(GL_MAJOR_VERSION, 16#821B).
-define(GL_MINOR_VERSION, 16#821C).
-define(GL_NUM_EXTENSIONS, 16#821D).
-define(GL_CONTEXT_FLAGS, 16#821E).
--define(GL_DEPTH_BUFFER, 16#8223).
--define(GL_STENCIL_BUFFER, 16#8224).
-define(GL_COMPRESSED_RED, 16#8225).
-define(GL_COMPRESSED_RG, 16#8226).
--define(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT, 16#1).
+-define(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT, 16#0001).
-define(GL_RGBA32F, 16#8814).
-define(GL_RGB32F, 16#8815).
-define(GL_RGBA16F, 16#881A).
@@ -1161,12 +1159,12 @@
-define(GL_SIGNED_NORMALIZED, 16#8F9C).
-define(GL_PRIMITIVE_RESTART, 16#8F9D).
-define(GL_PRIMITIVE_RESTART_INDEX, 16#8F9E).
--define(GL_CONTEXT_CORE_PROFILE_BIT, 16#1).
--define(GL_CONTEXT_COMPATIBILITY_PROFILE_BIT, 16#2).
--define(GL_LINES_ADJACENCY, 16#A).
--define(GL_LINE_STRIP_ADJACENCY, 16#B).
--define(GL_TRIANGLES_ADJACENCY, 16#C).
--define(GL_TRIANGLE_STRIP_ADJACENCY, 16#D).
+-define(GL_CONTEXT_CORE_PROFILE_BIT, 16#00000001).
+-define(GL_CONTEXT_COMPATIBILITY_PROFILE_BIT, 16#00000002).
+-define(GL_LINES_ADJACENCY, 16#000A).
+-define(GL_LINE_STRIP_ADJACENCY, 16#000B).
+-define(GL_TRIANGLES_ADJACENCY, 16#000C).
+-define(GL_TRIANGLE_STRIP_ADJACENCY, 16#000D).
-define(GL_PROGRAM_POINT_SIZE, 16#8642).
-define(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, 16#8C29).
-define(GL_FRAMEBUFFER_ATTACHMENT_LAYERED, 16#8DA7).
@@ -1553,7 +1551,7 @@
-define(GL_DEPTH_COMPONENT32F, 16#8CAC).
-define(GL_DEPTH32F_STENCIL8, 16#8CAD).
-define(GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 16#8DAD).
--define(GL_INVALID_FRAMEBUFFER_OPERATION, 16#506).
+-define(GL_INVALID_FRAMEBUFFER_OPERATION, 16#0506).
-define(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, 16#8210).
-define(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, 16#8211).
-define(GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, 16#8212).
@@ -1634,10 +1632,10 @@
-define(GL_TEXTURE_LUMINANCE_TYPE, 16#8C14).
-define(GL_TEXTURE_INTENSITY_TYPE, 16#8C15).
-define(GL_FRAMEBUFFER_SRGB, 16#8DB9).
--define(GL_LINES_ADJACENCY_ARB, 16#A).
--define(GL_LINE_STRIP_ADJACENCY_ARB, 16#B).
--define(GL_TRIANGLES_ADJACENCY_ARB, 16#C).
--define(GL_TRIANGLE_STRIP_ADJACENCY_ARB, 16#D).
+-define(GL_LINES_ADJACENCY_ARB, 16#000A).
+-define(GL_LINE_STRIP_ADJACENCY_ARB, 16#000B).
+-define(GL_TRIANGLES_ADJACENCY_ARB, 16#000C).
+-define(GL_TRIANGLE_STRIP_ADJACENCY_ARB, 16#000D).
-define(GL_PROGRAM_POINT_SIZE_ARB, 16#8642).
-define(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB, 16#8C29).
-define(GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB, 16#8DA7).
@@ -1654,12 +1652,12 @@
-define(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB, 16#8DE1).
-define(GL_HALF_FLOAT, 16#140B).
-define(GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB, 16#88FE).
--define(GL_MAP_READ_BIT, 16#1).
--define(GL_MAP_WRITE_BIT, 16#2).
--define(GL_MAP_INVALIDATE_RANGE_BIT, 16#4).
--define(GL_MAP_INVALIDATE_BUFFER_BIT, 16#8).
--define(GL_MAP_FLUSH_EXPLICIT_BIT, 16#10).
--define(GL_MAP_UNSYNCHRONIZED_BIT, 16#20).
+-define(GL_MAP_READ_BIT, 16#0001).
+-define(GL_MAP_WRITE_BIT, 16#0002).
+-define(GL_MAP_INVALIDATE_RANGE_BIT, 16#0004).
+-define(GL_MAP_INVALIDATE_BUFFER_BIT, 16#0008).
+-define(GL_MAP_FLUSH_EXPLICIT_BIT, 16#0010).
+-define(GL_MAP_UNSYNCHRONIZED_BIT, 16#0020).
-define(GL_TEXTURE_BUFFER_ARB, 16#8C2A).
-define(GL_MAX_TEXTURE_BUFFER_SIZE_ARB, 16#8C2B).
-define(GL_TEXTURE_BINDING_BUFFER_ARB, 16#8C2C).
@@ -1724,7 +1722,7 @@
-define(GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, 16#8A44).
-define(GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, 16#8A45).
-define(GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, 16#8A46).
--define(GL_INVALID_INDEX, 16#FFFFFFFF).
+-define(GL_INVALID_INDEX, 16#FFFFFFFFu).
-define(GL_COPY_READ_BUFFER, 16#8F36).
-define(GL_COPY_WRITE_BUFFER, 16#8F37).
-define(GL_DEPTH_CLAMP, 16#864F).
@@ -1746,8 +1744,8 @@
-define(GL_TIMEOUT_EXPIRED, 16#911B).
-define(GL_CONDITION_SATISFIED, 16#911C).
-define(GL_WAIT_FAILED, 16#911D).
--define(GL_SYNC_FLUSH_COMMANDS_BIT, 16#1).
--define(GL_TIMEOUT_IGNORED, 16#FFFFFFFFFFFFFFFF).
+-define(GL_SYNC_FLUSH_COMMANDS_BIT, 16#00000001).
+-define(GL_TIMEOUT_IGNORED, 16#FFFFFFFFFFFFFFFFull).
-define(GL_SAMPLE_POSITION, 16#8E50).
-define(GL_SAMPLE_MASK, 16#8E51).
-define(GL_SAMPLE_MASK_VALUE, 16#8E52).
@@ -1830,7 +1828,7 @@
-define(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, 16#8DE8).
-define(GL_NUM_COMPATIBLE_SUBROUTINES, 16#8E4A).
-define(GL_COMPATIBLE_SUBROUTINES, 16#8E4B).
--define(GL_PATCHES, 16#E).
+-define(GL_PATCHES, 16#000E).
-define(GL_PATCH_VERTICES, 16#8E72).
-define(GL_PATCH_DEFAULT_INNER_LEVEL, 16#8E73).
-define(GL_PATCH_DEFAULT_OUTER_LEVEL, 16#8E74).
@@ -1886,11 +1884,11 @@
-define(GL_PROGRAM_BINARY_LENGTH, 16#8741).
-define(GL_NUM_PROGRAM_BINARY_FORMATS, 16#87FE).
-define(GL_PROGRAM_BINARY_FORMATS, 16#87FF).
--define(GL_VERTEX_SHADER_BIT, 16#1).
--define(GL_FRAGMENT_SHADER_BIT, 16#2).
--define(GL_GEOMETRY_SHADER_BIT, 16#4).
--define(GL_TESS_CONTROL_SHADER_BIT, 16#8).
--define(GL_TESS_EVALUATION_SHADER_BIT, 16#10).
+-define(GL_VERTEX_SHADER_BIT, 16#00000001).
+-define(GL_FRAGMENT_SHADER_BIT, 16#00000002).
+-define(GL_GEOMETRY_SHADER_BIT, 16#00000004).
+-define(GL_TESS_CONTROL_SHADER_BIT, 16#00000008).
+-define(GL_TESS_EVALUATION_SHADER_BIT, 16#00000010).
-define(GL_ALL_SHADER_BITS, 16#FFFFFFFF).
-define(GL_PROGRAM_SEPARABLE, 16#8258).
-define(GL_ACTIVE_PROGRAM, 16#8259).
@@ -1925,13 +1923,117 @@
-define(GL_DEBUG_SEVERITY_HIGH_ARB, 16#9146).
-define(GL_DEBUG_SEVERITY_MEDIUM_ARB, 16#9147).
-define(GL_DEBUG_SEVERITY_LOW_ARB, 16#9148).
--define(GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB, 16#4).
+-define(GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB, 16#00000004).
-define(GL_LOSE_CONTEXT_ON_RESET_ARB, 16#8252).
-define(GL_GUILTY_CONTEXT_RESET_ARB, 16#8253).
-define(GL_INNOCENT_CONTEXT_RESET_ARB, 16#8254).
-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_UNPACK_COMPRESSED_BLOCK_WIDTH, 16#9127).
+-define(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, 16#9128).
+-define(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 16#9129).
+-define(GL_UNPACK_COMPRESSED_BLOCK_SIZE, 16#912A).
+-define(GL_PACK_COMPRESSED_BLOCK_WIDTH, 16#912B).
+-define(GL_PACK_COMPRESSED_BLOCK_HEIGHT, 16#912C).
+-define(GL_PACK_COMPRESSED_BLOCK_DEPTH, 16#912D).
+-define(GL_PACK_COMPRESSED_BLOCK_SIZE, 16#912E).
+-define(GL_NUM_SAMPLE_COUNTS, 16#9380).
+-define(GL_MIN_MAP_BUFFER_ALIGNMENT, 16#90BC).
+-define(GL_ATOMIC_COUNTER_BUFFER, 16#92C0).
+-define(GL_ATOMIC_COUNTER_BUFFER_BINDING, 16#92C1).
+-define(GL_ATOMIC_COUNTER_BUFFER_START, 16#92C2).
+-define(GL_ATOMIC_COUNTER_BUFFER_SIZE, 16#92C3).
+-define(GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE, 16#92C4).
+-define(GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS, 16#92C5).
+-define(GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, 16#92C6).
+-define(GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER, 16#92C7).
+-define(GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER, 16#92C8).
+-define(GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER, 16#92C9).
+-define(GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER, 16#92CA).
+-define(GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, 16#92CB).
+-define(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, 16#92CC).
+-define(GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, 16#92CD).
+-define(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS, 16#92CE).
+-define(GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, 16#92CF).
+-define(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, 16#92D0).
+-define(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, 16#92D1).
+-define(GL_MAX_VERTEX_ATOMIC_COUNTERS, 16#92D2).
+-define(GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, 16#92D3).
+-define(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, 16#92D4).
+-define(GL_MAX_GEOMETRY_ATOMIC_COUNTERS, 16#92D5).
+-define(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, 16#92D6).
+-define(GL_MAX_COMBINED_ATOMIC_COUNTERS, 16#92D7).
+-define(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, 16#92D8).
+-define(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, 16#92DC).
+-define(GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 16#92D9).
+-define(GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX, 16#92DA).
+-define(GL_UNSIGNED_INT_ATOMIC_COUNTER, 16#92DB).
+-define(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT, 16#00000001).
+-define(GL_ELEMENT_ARRAY_BARRIER_BIT, 16#00000002).
+-define(GL_UNIFORM_BARRIER_BIT, 16#00000004).
+-define(GL_TEXTURE_FETCH_BARRIER_BIT, 16#00000008).
+-define(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT, 16#00000020).
+-define(GL_COMMAND_BARRIER_BIT, 16#00000040).
+-define(GL_PIXEL_BUFFER_BARRIER_BIT, 16#00000080).
+-define(GL_TEXTURE_UPDATE_BARRIER_BIT, 16#00000100).
+-define(GL_BUFFER_UPDATE_BARRIER_BIT, 16#00000200).
+-define(GL_FRAMEBUFFER_BARRIER_BIT, 16#00000400).
+-define(GL_TRANSFORM_FEEDBACK_BARRIER_BIT, 16#00000800).
+-define(GL_ATOMIC_COUNTER_BARRIER_BIT, 16#00001000).
+-define(GL_ALL_BARRIER_BITS, 16#FFFFFFFF).
+-define(GL_MAX_IMAGE_UNITS, 16#8F38).
+-define(GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS, 16#8F39).
+-define(GL_IMAGE_BINDING_NAME, 16#8F3A).
+-define(GL_IMAGE_BINDING_LEVEL, 16#8F3B).
+-define(GL_IMAGE_BINDING_LAYERED, 16#8F3C).
+-define(GL_IMAGE_BINDING_LAYER, 16#8F3D).
+-define(GL_IMAGE_BINDING_ACCESS, 16#8F3E).
+-define(GL_IMAGE_1D, 16#904C).
+-define(GL_IMAGE_2D, 16#904D).
+-define(GL_IMAGE_3D, 16#904E).
+-define(GL_IMAGE_2D_RECT, 16#904F).
+-define(GL_IMAGE_CUBE, 16#9050).
+-define(GL_IMAGE_BUFFER, 16#9051).
+-define(GL_IMAGE_1D_ARRAY, 16#9052).
+-define(GL_IMAGE_2D_ARRAY, 16#9053).
+-define(GL_IMAGE_CUBE_MAP_ARRAY, 16#9054).
+-define(GL_IMAGE_2D_MULTISAMPLE, 16#9055).
+-define(GL_IMAGE_2D_MULTISAMPLE_ARRAY, 16#9056).
+-define(GL_INT_IMAGE_1D, 16#9057).
+-define(GL_INT_IMAGE_2D, 16#9058).
+-define(GL_INT_IMAGE_3D, 16#9059).
+-define(GL_INT_IMAGE_2D_RECT, 16#905A).
+-define(GL_INT_IMAGE_CUBE, 16#905B).
+-define(GL_INT_IMAGE_BUFFER, 16#905C).
+-define(GL_INT_IMAGE_1D_ARRAY, 16#905D).
+-define(GL_INT_IMAGE_2D_ARRAY, 16#905E).
+-define(GL_INT_IMAGE_CUBE_MAP_ARRAY, 16#905F).
+-define(GL_INT_IMAGE_2D_MULTISAMPLE, 16#9060).
+-define(GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, 16#9061).
+-define(GL_UNSIGNED_INT_IMAGE_1D, 16#9062).
+-define(GL_UNSIGNED_INT_IMAGE_2D, 16#9063).
+-define(GL_UNSIGNED_INT_IMAGE_3D, 16#9064).
+-define(GL_UNSIGNED_INT_IMAGE_2D_RECT, 16#9065).
+-define(GL_UNSIGNED_INT_IMAGE_CUBE, 16#9066).
+-define(GL_UNSIGNED_INT_IMAGE_BUFFER, 16#9067).
+-define(GL_UNSIGNED_INT_IMAGE_1D_ARRAY, 16#9068).
+-define(GL_UNSIGNED_INT_IMAGE_2D_ARRAY, 16#9069).
+-define(GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, 16#906A).
+-define(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, 16#906B).
+-define(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, 16#906C).
+-define(GL_MAX_IMAGE_SAMPLES, 16#906D).
+-define(GL_IMAGE_BINDING_FORMAT, 16#906E).
+-define(GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, 16#90C7).
+-define(GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE, 16#90C8).
+-define(GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS, 16#90C9).
+-define(GL_MAX_VERTEX_IMAGE_UNIFORMS, 16#90CA).
+-define(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 16#90CB).
+-define(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 16#90CC).
+-define(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 16#90CD).
+-define(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 16#90CE).
+-define(GL_MAX_COMBINED_IMAGE_UNIFORMS, 16#90CF).
+-define(GL_TEXTURE_IMMUTABLE_FORMAT, 16#912F).
-define(GL_ABGR_EXT, 16#8000).
-define(GL_CONSTANT_COLOR_EXT, 16#8001).
-define(GL_ONE_MINUS_CONSTANT_COLOR_EXT, 16#8002).
@@ -2235,8 +2337,8 @@
-define(GL_FRAMEZOOM_SGIX, 16#818B).
-define(GL_FRAMEZOOM_FACTOR_SGIX, 16#818C).
-define(GL_MAX_FRAMEZOOM_FACTOR_SGIX, 16#818D).
--define(GL_TEXTURE_DEFORMATION_BIT_SGIX, 16#1).
--define(GL_GEOMETRY_DEFORMATION_BIT_SGIX, 16#2).
+-define(GL_TEXTURE_DEFORMATION_BIT_SGIX, 16#00000001).
+-define(GL_GEOMETRY_DEFORMATION_BIT_SGIX, 16#00000002).
-define(GL_GEOMETRY_DEFORMATION_SGIX, 16#8194).
-define(GL_TEXTURE_DEFORMATION_SGIX, 16#8195).
-define(GL_DEFORMATIONS_MASK_SGIX, 16#8196).
@@ -2275,24 +2377,24 @@
-define(GL_VERTEX_CONSISTENT_HINT_PGI, 16#1A22B).
-define(GL_MATERIAL_SIDE_HINT_PGI, 16#1A22C).
-define(GL_MAX_VERTEX_HINT_PGI, 16#1A22D).
--define(GL_COLOR3_BIT_PGI, 16#10000).
--define(GL_COLOR4_BIT_PGI, 16#20000).
--define(GL_EDGEFLAG_BIT_PGI, 16#40000).
--define(GL_INDEX_BIT_PGI, 16#80000).
--define(GL_MAT_AMBIENT_BIT_PGI, 16#100000).
--define(GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI, 16#200000).
--define(GL_MAT_DIFFUSE_BIT_PGI, 16#400000).
--define(GL_MAT_EMISSION_BIT_PGI, 16#800000).
--define(GL_MAT_COLOR_INDEXES_BIT_PGI, 16#1000000).
--define(GL_MAT_SHININESS_BIT_PGI, 16#2000000).
--define(GL_MAT_SPECULAR_BIT_PGI, 16#4000000).
--define(GL_NORMAL_BIT_PGI, 16#8000000).
+-define(GL_COLOR3_BIT_PGI, 16#00010000).
+-define(GL_COLOR4_BIT_PGI, 16#00020000).
+-define(GL_EDGEFLAG_BIT_PGI, 16#00040000).
+-define(GL_INDEX_BIT_PGI, 16#00080000).
+-define(GL_MAT_AMBIENT_BIT_PGI, 16#00100000).
+-define(GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI, 16#00200000).
+-define(GL_MAT_DIFFUSE_BIT_PGI, 16#00400000).
+-define(GL_MAT_EMISSION_BIT_PGI, 16#00800000).
+-define(GL_MAT_COLOR_INDEXES_BIT_PGI, 16#01000000).
+-define(GL_MAT_SHININESS_BIT_PGI, 16#02000000).
+-define(GL_MAT_SPECULAR_BIT_PGI, 16#04000000).
+-define(GL_NORMAL_BIT_PGI, 16#08000000).
-define(GL_TEXCOORD1_BIT_PGI, 16#10000000).
-define(GL_TEXCOORD2_BIT_PGI, 16#20000000).
-define(GL_TEXCOORD3_BIT_PGI, 16#40000000).
-define(GL_TEXCOORD4_BIT_PGI, 16#80000000).
--define(GL_VERTEX23_BIT_PGI, 16#4).
--define(GL_VERTEX4_BIT_PGI, 16#8).
+-define(GL_VERTEX23_BIT_PGI, 16#00000004).
+-define(GL_VERTEX4_BIT_PGI, 16#00000008).
-define(GL_PREFER_DOUBLEBUFFER_HINT_PGI, 16#1A1F8).
-define(GL_CONSERVE_MEMORY_HINT_PGI, 16#1A1FD).
-define(GL_RECLAIM_MEMORY_HINT_PGI, 16#1A1FE).
@@ -2489,9 +2591,9 @@
-define(GL_TEXTURE_CONSTANT_DATA_SUNX, 16#81D6).
-define(GL_GLOBAL_ALPHA_SUN, 16#81D9).
-define(GL_GLOBAL_ALPHA_FACTOR_SUN, 16#81DA).
--define(GL_RESTART_SUN, 16#1).
--define(GL_REPLACE_MIDDLE_SUN, 16#2).
--define(GL_REPLACE_OLDEST_SUN, 16#3).
+-define(GL_RESTART_SUN, 16#0001).
+-define(GL_REPLACE_MIDDLE_SUN, 16#0002).
+-define(GL_REPLACE_OLDEST_SUN, 16#0003).
-define(GL_TRIANGLE_LIST_SUN, 16#81D7).
-define(GL_REPLACEMENT_CODE_SUN, 16#81D8).
-define(GL_REPLACEMENT_CODE_ARRAY_SUN, 16#85C0).
@@ -3010,19 +3112,19 @@
-define(GL_SWIZZLE_STQ_DQ_ATI, 16#8979).
-define(GL_SWIZZLE_STRQ_ATI, 16#897A).
-define(GL_SWIZZLE_STRQ_DQ_ATI, 16#897B).
--define(GL_RED_BIT_ATI, 16#1).
--define(GL_GREEN_BIT_ATI, 16#2).
--define(GL_BLUE_BIT_ATI, 16#4).
--define(GL_2X_BIT_ATI, 16#1).
--define(GL_4X_BIT_ATI, 16#2).
--define(GL_8X_BIT_ATI, 16#4).
--define(GL_HALF_BIT_ATI, 16#8).
--define(GL_QUARTER_BIT_ATI, 16#10).
--define(GL_EIGHTH_BIT_ATI, 16#20).
--define(GL_SATURATE_BIT_ATI, 16#40).
--define(GL_COMP_BIT_ATI, 16#2).
--define(GL_NEGATE_BIT_ATI, 16#4).
--define(GL_BIAS_BIT_ATI, 16#8).
+-define(GL_RED_BIT_ATI, 16#00000001).
+-define(GL_GREEN_BIT_ATI, 16#00000002).
+-define(GL_BLUE_BIT_ATI, 16#00000004).
+-define(GL_2X_BIT_ATI, 16#00000001).
+-define(GL_4X_BIT_ATI, 16#00000002).
+-define(GL_8X_BIT_ATI, 16#00000004).
+-define(GL_HALF_BIT_ATI, 16#00000008).
+-define(GL_QUARTER_BIT_ATI, 16#00000010).
+-define(GL_EIGHTH_BIT_ATI, 16#00000020).
+-define(GL_SATURATE_BIT_ATI, 16#00000040).
+-define(GL_COMP_BIT_ATI, 16#00000002).
+-define(GL_NEGATE_BIT_ATI, 16#00000004).
+-define(GL_BIAS_BIT_ATI, 16#00000008).
-define(GL_PN_TRIANGLES_ATI, 16#87F0).
-define(GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI, 16#87F1).
-define(GL_PN_TRIANGLES_POINT_MODE_ATI, 16#87F2).
@@ -3307,7 +3409,7 @@
-define(GL_MAX_PROGRAM_IF_DEPTH_NV, 16#88F6).
-define(GL_MAX_PROGRAM_LOOP_DEPTH_NV, 16#88F7).
-define(GL_MAX_PROGRAM_LOOP_COUNT_NV, 16#88F8).
--define(GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 16#506).
+-define(GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 16#0506).
-define(GL_MAX_RENDERBUFFER_SIZE_EXT, 16#84E8).
-define(GL_FRAMEBUFFER_BINDING_EXT, 16#8CA6).
-define(GL_RENDERBUFFER_BINDING_EXT, 16#8CA7).
@@ -3404,10 +3506,10 @@
-define(GL_MAX_PROGRAM_RESULT_COMPONENTS_NV, 16#8909).
-define(GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV, 16#8DA5).
-define(GL_MAX_PROGRAM_GENERIC_RESULTS_NV, 16#8DA6).
--define(GL_LINES_ADJACENCY_EXT, 16#A).
--define(GL_LINE_STRIP_ADJACENCY_EXT, 16#B).
--define(GL_TRIANGLES_ADJACENCY_EXT, 16#C).
--define(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 16#D).
+-define(GL_LINES_ADJACENCY_EXT, 16#000A).
+-define(GL_LINE_STRIP_ADJACENCY_EXT, 16#000B).
+-define(GL_TRIANGLES_ADJACENCY_EXT, 16#000C).
+-define(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 16#000D).
-define(GL_GEOMETRY_PROGRAM_NV, 16#8C26).
-define(GL_MAX_PROGRAM_OUTPUT_VERTICES_NV, 16#8C27).
-define(GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV, 16#8C28).
@@ -3789,18 +3891,18 @@
-define(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT, 16#906C).
-define(GL_MAX_IMAGE_SAMPLES_EXT, 16#906D).
-define(GL_IMAGE_BINDING_FORMAT_EXT, 16#906E).
--define(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT, 16#1).
--define(GL_ELEMENT_ARRAY_BARRIER_BIT_EXT, 16#2).
--define(GL_UNIFORM_BARRIER_BIT_EXT, 16#4).
--define(GL_TEXTURE_FETCH_BARRIER_BIT_EXT, 16#8).
--define(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT, 16#20).
--define(GL_COMMAND_BARRIER_BIT_EXT, 16#40).
--define(GL_PIXEL_BUFFER_BARRIER_BIT_EXT, 16#80).
--define(GL_TEXTURE_UPDATE_BARRIER_BIT_EXT, 16#100).
--define(GL_BUFFER_UPDATE_BARRIER_BIT_EXT, 16#200).
--define(GL_FRAMEBUFFER_BARRIER_BIT_EXT, 16#400).
--define(GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT, 16#800).
--define(GL_ATOMIC_COUNTER_BARRIER_BIT_EXT, 16#1000).
+-define(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT, 16#00000001).
+-define(GL_ELEMENT_ARRAY_BARRIER_BIT_EXT, 16#00000002).
+-define(GL_UNIFORM_BARRIER_BIT_EXT, 16#00000004).
+-define(GL_TEXTURE_FETCH_BARRIER_BIT_EXT, 16#00000008).
+-define(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT, 16#00000020).
+-define(GL_COMMAND_BARRIER_BIT_EXT, 16#00000040).
+-define(GL_PIXEL_BUFFER_BARRIER_BIT_EXT, 16#00000080).
+-define(GL_TEXTURE_UPDATE_BARRIER_BIT_EXT, 16#00000100).
+-define(GL_BUFFER_UPDATE_BARRIER_BIT_EXT, 16#00000200).
+-define(GL_FRAMEBUFFER_BARRIER_BIT_EXT, 16#00000400).
+-define(GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT, 16#00000800).
+-define(GL_ATOMIC_COUNTER_BARRIER_BIT_EXT, 16#00001000).
-define(GL_ALL_BARRIER_BITS_EXT, 16#FFFFFFFF).
-define(GL_DOUBLE_VEC2_EXT, 16#8FFC).
-define(GL_DOUBLE_VEC3_EXT, 16#8FFD).
@@ -3850,7 +3952,7 @@
-define(GL_FLOAT16_VEC2_NV, 16#8FF9).
-define(GL_FLOAT16_VEC3_NV, 16#8FFA).
-define(GL_FLOAT16_VEC4_NV, 16#8FFB).
--define(GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV, 16#10).
+-define(GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV, 16#00000010).
-define(GL_MAX_PROGRAM_PATCH_ATTRIBS_NV, 16#86D8).
-define(GL_TESS_CONTROL_PROGRAM_NV, 16#891E).
-define(GL_TESS_EVALUATION_PROGRAM_NV, 16#891F).
@@ -3882,3 +3984,432 @@
-define(GL_WRITE_DISCARD_NV, 16#88BE).
-define(GL_DEPTH_CLAMP_NEAR_AMD, 16#901E).
-define(GL_DEPTH_CLAMP_FAR_AMD, 16#901F).
+-define(GL_TEXTURE_SRGB_DECODE_EXT, 16#8A48).
+-define(GL_DECODE_EXT, 16#8A49).
+-define(GL_SKIP_DECODE_EXT, 16#8A4A).
+-define(GL_TEXTURE_COVERAGE_SAMPLES_NV, 16#9045).
+-define(GL_TEXTURE_COLOR_SAMPLES_NV, 16#9046).
+-define(GL_FACTOR_MIN_AMD, 16#901C).
+-define(GL_FACTOR_MAX_AMD, 16#901D).
+-define(GL_SUBSAMPLE_DISTANCE_AMD, 16#883F).
+-define(GL_SYNC_X11_FENCE_EXT, 16#90E1).
+-define(GL_SCALED_RESOLVE_FASTEST_EXT, 16#90BA).
+-define(GL_SCALED_RESOLVE_NICEST_EXT, 16#90BB).
+-define(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 16#9160).
+-define(GL_SET_AMD, 16#874A).
+-define(GL_REPLACE_VALUE_AMD, 16#874B).
+-define(GL_STENCIL_OP_VALUE_AMD, 16#874C).
+-define(GL_STENCIL_BACK_OP_VALUE_AMD, 16#874D).
+-define(GL_VERSION_1_2_DEPRECATED, 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_VERSION_4_2, 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_shader_bit_encoding, 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_ARB_base_instance, 1).
+-define(GL_ARB_shading_language_420pack, 1).
+-define(GL_ARB_transform_feedback_instanced, 1).
+-define(GL_ARB_compressed_texture_pixel_storage, 1).
+-define(GL_ARB_conservative_depth, 1).
+-define(GL_ARB_internalformat_query, 1).
+-define(GL_ARB_map_buffer_alignment, 1).
+-define(GL_ARB_shader_atomic_counters, 1).
+-define(GL_ARB_shader_image_load_store, 1).
+-define(GL_ARB_shading_language_packing, 1).
+-define(GL_ARB_texture_storage, 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_AMD_depth_clamp_separate, 1).
+-define(GL_EXT_texture_sRGB_decode, 1).
+-define(GL_NV_texture_multisample, 1).
+-define(GL_AMD_blend_minmax_factor, 1).
+-define(GL_AMD_sample_positions, 1).
+-define(GL_EXT_x11_sync_object, 1).
+-define(GL_AMD_multi_draw_indirect, 1).
+-define(GL_EXT_framebuffer_multisample_blit_scaled, 1).
+-define(GL_AMD_pinned_memory, 1).
+-define(GL_AMD_stencil_operation_extended, 1).
diff --git a/lib/wx/include/glu.hrl b/lib/wx/include/glu.hrl
index a2ab55d054..dc55c5bb96 100644
--- a/lib/wx/include/glu.hrl
+++ b/lib/wx/include/glu.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,4 +174,4 @@
-define(GLU_TESS_WINDING_POSITIVE, 100132).
-define(GLU_TESS_WINDING_NEGATIVE, 100133).
-define(GLU_TESS_WINDING_ABS_GEQ_TWO, 100134).
--define(GLU_TESS_MAX_COORD, ?1.0e150).
+-define(GLU_TESS_MAX_COORD, 1.0e150).
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index 8659b71985..62979908a6 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,259 +22,307 @@
%% Each event record may be sent for one or more event types.
%% The mapping to wxWidgets is one record per class.
-%% @type wx() = #wx{id=integer(), obj=wx:wxObject(), userData=term(), event=Rec}. Rec is a event record.
--record(wx, {id, %% Integer Identity of object.
- obj, %% Object reference that was used in the connect call.
- userData, %% User data specified in the connect call.
- event}).%% The event record
+-record(wx, {id :: integer(), %% Integer Identity of object.
+ obj :: wx:wx_object(), %% Object reference that was used in the connect call.
+ userData :: term(), %% User data specified in the connect call.
+ event :: event() %% The event record
+ }).
+-type wx() :: #wx{}. %% wx event record
%% Here comes the definitions of all event records.
%% they contain the event type and possible some extra information.
-%% @type wxNavigationKey() = #wxNavigationKey{type=wxEventType(),flags=integer(),focus=wxWindow:wxWindow()}.
-%% <dl><dt>EventType:</dt> <dd><em>navigation_key</em></dd></dl>
-%% Callback event: {@link wxNavigationKeyEvent}
--record(wxNavigationKey,{type, flags,focus}).
+-record(wxNavigationKey,{type :: wxNavigationKeyEventType(), %% Callback event: {@link wxNavigationKeyEvent}
+ flags :: integer(),
+ focus :: wxWindow:wxWindow()}).
+-type wxNavigationKeyEventType() :: navigation_key.
+-type wxNavigationKey() :: #wxNavigationKey{}. %% Callback event: {@link wxNavigationKeyEvent}
-%% @type wxSash() = #wxSash{type=wxEventType(),edge=WxSashEdgePosition,dragRect={X::integer(),Y::integer(),W::integer(),H::integer()},dragStatus=WxSashDragStatus}.
-%% <dl><dt>EventType:</dt> <dd><em>sash_dragged</em></dd></dl>
-%% Callback event: {@link wxSashEvent}
--record(wxSash,{type, edge,dragRect,dragStatus}).
+-record(wxSash,{type :: wxSashEventType(), %% Callback event: {@link wxSashEvent}
+ edge :: wx:wx_enum(),
+ dragRect :: {X::integer(), Y::integer(), W::integer(), H::integer()},
+ dragStatus :: wx:wx_enum()}).
+-type wxSashEventType() :: sash_dragged.
+-type wxSash() :: #wxSash{}. %% Callback event: {@link wxSashEvent}
-%% @type wxList() = #wxList{type=wxEventType(),code=integer(),oldItemIndex=integer(),itemIndex=integer(),col=integer(),pointDrag={X::integer(),Y::integer()}}.
-%% <dl><dt>EventType:</dt> <dd><em>command_list_begin_drag</em>, <em>command_list_begin_rdrag</em>, <em>command_list_begin_label_edit</em>, <em>command_list_end_label_edit</em>, <em>command_list_delete_item</em>, <em>command_list_delete_all_items</em>, <em>command_list_key_down</em>, <em>command_list_insert_item</em>, <em>command_list_col_click</em>, <em>command_list_col_right_click</em>, <em>command_list_col_begin_drag</em>, <em>command_list_col_dragging</em>, <em>command_list_col_end_drag</em>, <em>command_list_item_selected</em>, <em>command_list_item_deselected</em>, <em>command_list_item_right_click</em>, <em>command_list_item_middle_click</em>, <em>command_list_item_activated</em>, <em>command_list_item_focused</em>, <em>command_list_cache_hint</em></dd></dl>
-%% Callback event: {@link wxListEvent}
--record(wxList,{type, code,oldItemIndex,itemIndex,col,pointDrag}).
+-record(wxList,{type :: wxListEventType(), %% Callback event: {@link wxListEvent}
+ code :: integer(),
+ oldItemIndex :: integer(),
+ itemIndex :: integer(),
+ col :: integer(),
+ pointDrag :: {X::integer(), Y::integer()}}).
+-type wxListEventType() :: command_list_begin_drag | command_list_begin_rdrag | command_list_begin_label_edit | command_list_end_label_edit | command_list_delete_item | command_list_delete_all_items | command_list_key_down | command_list_insert_item | command_list_col_click | command_list_col_right_click | command_list_col_begin_drag | command_list_col_dragging | command_list_col_end_drag | command_list_item_selected | command_list_item_deselected | command_list_item_right_click | command_list_item_middle_click | command_list_item_activated | command_list_item_focused | command_list_cache_hint.
+-type wxList() :: #wxList{}. %% Callback event: {@link wxListEvent}
-%% @type wxNotebook() = #wxNotebook{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_notebook_page_changed</em>, <em>command_notebook_page_changing</em></dd></dl>
-%% Callback event: {@link wxNotebookEvent}
--record(wxNotebook, {type}).
+-record(wxNotebook, {type :: wxNotebookEventType()}). %% Callback event: {@link wxNotebookEvent}
+-type wxNotebookEventType() :: command_notebook_page_changed | command_notebook_page_changing.
+-type wxNotebook() :: #wxNotebook{}. %% Callback event: {@link wxNotebookEvent}
-%% @type wxDisplayChanged() = #wxDisplayChanged{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>display_changed</em></dd></dl>
-%% Callback event: {@link wxDisplayChangedEvent}
--record(wxDisplayChanged, {type}).
+-record(wxDisplayChanged, {type :: wxDisplayChangedEventType()}). %% Callback event: {@link wxDisplayChangedEvent}
+-type wxDisplayChangedEventType() :: display_changed.
+-type wxDisplayChanged() :: #wxDisplayChanged{}. %% Callback event: {@link wxDisplayChangedEvent}
-%% @type wxErase() = #wxErase{type=wxEventType(),dc=wxDC:wxDC()}.
-%% <dl><dt>EventType:</dt> <dd><em>erase_background</em></dd></dl>
-%% Callback event: {@link wxEraseEvent}
--record(wxErase,{type, dc}).
+-record(wxErase,{type :: wxEraseEventType(), %% Callback event: {@link wxEraseEvent}
+ dc :: wxDC:wxDC()}).
+-type wxEraseEventType() :: erase_background.
+-type wxErase() :: #wxErase{}. %% Callback event: {@link wxEraseEvent}
-%% @type wxKey() = #wxKey{type=wxEventType(),x=integer(),y=integer(),keyCode=integer(),controlDown=bool(),shiftDown=bool(),altDown=bool(),metaDown=bool(),scanCode=bool(),uniChar=integer(),rawCode=integer(),rawFlags=integer()}.
-%% <dl><dt>EventType:</dt> <dd><em>char</em>, <em>char_hook</em>, <em>key_down</em>, <em>key_up</em></dd></dl>
-%% Callback event: {@link wxKeyEvent}
--record(wxKey,{type, x,y,keyCode,controlDown,shiftDown,altDown,metaDown,scanCode,uniChar,rawCode,rawFlags}).
+-record(wxKey,{type :: wxKeyEventType(), %% Callback event: {@link wxKeyEvent}
+ x :: integer(),
+ y :: integer(),
+ keyCode :: integer(),
+ controlDown :: boolean(),
+ shiftDown :: boolean(),
+ altDown :: boolean(),
+ metaDown :: boolean(),
+ scanCode :: boolean(),
+ uniChar :: integer(),
+ rawCode :: integer(),
+ rawFlags :: integer()}).
+-type wxKeyEventType() :: char | char_hook | key_down | key_up.
+-type wxKey() :: #wxKey{}. %% Callback event: {@link wxKeyEvent}
-%% @type wxWindowDestroy() = #wxWindowDestroy{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>destroy</em></dd></dl>
-%% Callback event: {@link wxWindowDestroyEvent}
--record(wxWindowDestroy, {type}).
+-record(wxWindowDestroy, {type :: wxWindowDestroyEventType()}). %% Callback event: {@link wxWindowDestroyEvent}
+-type wxWindowDestroyEventType() :: destroy.
+-type wxWindowDestroy() :: #wxWindowDestroy{}. %% Callback event: {@link wxWindowDestroyEvent}
-%% @type wxCalendar() = #wxCalendar{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>calendar_sel_changed</em>, <em>calendar_day_changed</em>, <em>calendar_month_changed</em>, <em>calendar_year_changed</em>, <em>calendar_doubleclicked</em>, <em>calendar_weekday_clicked</em></dd></dl>
-%% Callback event: {@link wxCalendarEvent}
--record(wxCalendar, {type}).
+-record(wxCalendar, {type :: wxCalendarEventType()}). %% Callback event: {@link wxCalendarEvent}
+-type wxCalendarEventType() :: calendar_sel_changed | calendar_day_changed | calendar_month_changed | calendar_year_changed | calendar_doubleclicked | calendar_weekday_clicked.
+-type wxCalendar() :: #wxCalendar{}. %% Callback event: {@link wxCalendarEvent}
-%% @type wxSplitter() = #wxSplitter{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_splitter_sash_pos_changed</em>, <em>command_splitter_sash_pos_changing</em>, <em>command_splitter_doubleclicked</em>, <em>command_splitter_unsplit</em></dd></dl>
-%% Callback event: {@link wxSplitterEvent}
--record(wxSplitter, {type}).
+-record(wxSplitter, {type :: wxSplitterEventType()}). %% Callback event: {@link wxSplitterEvent}
+-type wxSplitterEventType() :: command_splitter_sash_pos_changed | command_splitter_sash_pos_changing | command_splitter_doubleclicked | command_splitter_unsplit.
+-type wxSplitter() :: #wxSplitter{}. %% Callback event: {@link wxSplitterEvent}
-%% @type wxScroll() = #wxScroll{type=wxEventType(),commandInt=integer(),extraLong=integer()}.
-%% <dl><dt>EventType:</dt> <dd><em>scroll_top</em>, <em>scroll_bottom</em>, <em>scroll_lineup</em>, <em>scroll_linedown</em>, <em>scroll_pageup</em>, <em>scroll_pagedown</em>, <em>scroll_thumbtrack</em>, <em>scroll_thumbrelease</em>, <em>scroll_changed</em></dd></dl>
-%% Callback event: {@link wxScrollEvent}
--record(wxScroll,{type, commandInt,extraLong}).
+-record(wxScroll,{type :: wxScrollEventType(), %% Callback event: {@link wxScrollEvent}
+ commandInt :: integer(),
+ extraLong :: integer()}).
+-type wxScrollEventType() :: scroll_top | scroll_bottom | scroll_lineup | scroll_linedown | scroll_pageup | scroll_pagedown | scroll_thumbtrack | scroll_thumbrelease | scroll_changed.
+-type wxScroll() :: #wxScroll{}. %% Callback event: {@link wxScrollEvent}
-%% @type wxMenu() = #wxMenu{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>menu_open</em>, <em>menu_close</em>, <em>menu_highlight</em></dd></dl>
-%% Callback event: {@link wxMenuEvent}
--record(wxMenu, {type}).
+-record(wxMenu, {type :: wxMenuEventType()}). %% Callback event: {@link wxMenuEvent}
+-type wxMenuEventType() :: menu_open | menu_close | menu_highlight.
+-type wxMenu() :: #wxMenu{}. %% Callback event: {@link wxMenuEvent}
-%% @type wxContextMenu() = #wxContextMenu{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>context_menu</em></dd></dl>
-%% Callback event: {@link wxContextMenuEvent}
--record(wxContextMenu, {type}).
+-record(wxContextMenu, {type :: wxContextMenuEventType()}). %% Callback event: {@link wxContextMenuEvent}
+-type wxContextMenuEventType() :: context_menu.
+-type wxContextMenu() :: #wxContextMenu{}. %% Callback event: {@link wxContextMenuEvent}
-%% @type wxShow() = #wxShow{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>show</em></dd></dl>
-%% Callback event: {@link wxShowEvent}
--record(wxShow, {type}).
+-record(wxShow, {type :: wxShowEventType()}). %% Callback event: {@link wxShowEvent}
+-type wxShowEventType() :: show.
+-type wxShow() :: #wxShow{}. %% Callback event: {@link wxShowEvent}
-%% @type wxSpin() = #wxSpin{type=wxEventType(),commandInt=integer()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_spinctrl_updated</em>, <em>spin_up</em>, <em>spin_down</em>, <em>spin</em></dd></dl>
-%% Callback event: {@link wxSpinEvent}
--record(wxSpin,{type, commandInt}).
+-record(wxSpin,{type :: wxSpinEventType(), %% Callback event: {@link wxSpinEvent}
+ commandInt :: integer()}).
+-type wxSpinEventType() :: command_spinctrl_updated | spin_up | spin_down | spin.
+-type wxSpin() :: #wxSpin{}. %% Callback event: {@link wxSpinEvent}
-%% @type wxSetCursor() = #wxSetCursor{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>set_cursor</em></dd></dl>
-%% Callback event: {@link wxSetCursorEvent}
--record(wxSetCursor, {type}).
+-record(wxSetCursor, {type :: wxSetCursorEventType()}). %% Callback event: {@link wxSetCursorEvent}
+-type wxSetCursorEventType() :: set_cursor.
+-type wxSetCursor() :: #wxSetCursor{}. %% Callback event: {@link wxSetCursorEvent}
-%% @type wxFontPicker() = #wxFontPicker{type=wxEventType(),font=wxFont:wxFont()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_fontpicker_changed</em></dd></dl>
-%% Callback event: {@link wxFontPickerEvent}
--record(wxFontPicker,{type, font}).
+-record(wxFontPicker,{type :: wxFontPickerEventType(), %% Callback event: {@link wxFontPickerEvent}
+ font :: wxFont:wxFont()}).
+-type wxFontPickerEventType() :: command_fontpicker_changed.
+-type wxFontPicker() :: #wxFontPicker{}. %% Callback event: {@link wxFontPickerEvent}
-%% @type wxScrollWin() = #wxScrollWin{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>scrollwin_top</em>, <em>scrollwin_bottom</em>, <em>scrollwin_lineup</em>, <em>scrollwin_linedown</em>, <em>scrollwin_pageup</em>, <em>scrollwin_pagedown</em>, <em>scrollwin_thumbtrack</em>, <em>scrollwin_thumbrelease</em></dd></dl>
-%% Callback event: {@link wxScrollWinEvent}
--record(wxScrollWin, {type}).
+-record(wxScrollWin, {type :: wxScrollWinEventType()}). %% Callback event: {@link wxScrollWinEvent}
+-type wxScrollWinEventType() :: scrollwin_top | scrollwin_bottom | scrollwin_lineup | scrollwin_linedown | scrollwin_pageup | scrollwin_pagedown | scrollwin_thumbtrack | scrollwin_thumbrelease.
+-type wxScrollWin() :: #wxScrollWin{}. %% Callback event: {@link wxScrollWinEvent}
-%% @type wxPaint() = #wxPaint{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>paint</em>, <em>paint_icon</em></dd></dl>
-%% Callback event: {@link wxPaintEvent}
--record(wxPaint, {type}).
+-record(wxPaint, {type :: wxPaintEventType()}). %% Callback event: {@link wxPaintEvent}
+-type wxPaintEventType() :: paint | paint_icon.
+-type wxPaint() :: #wxPaint{}. %% Callback event: {@link wxPaintEvent}
-%% @type wxChildFocus() = #wxChildFocus{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>child_focus</em></dd></dl>
-%% Callback event: {@link wxChildFocusEvent}
--record(wxChildFocus, {type}).
+-record(wxChildFocus, {type :: wxChildFocusEventType()}). %% Callback event: {@link wxChildFocusEvent}
+-type wxChildFocusEventType() :: child_focus.
+-type wxChildFocus() :: #wxChildFocus{}. %% Callback event: {@link wxChildFocusEvent}
-%% @type wxMaximize() = #wxMaximize{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>maximize</em></dd></dl>
-%% Callback event: {@link wxMaximizeEvent}
--record(wxMaximize, {type}).
+-record(wxMaximize, {type :: wxMaximizeEventType()}). %% Callback event: {@link wxMaximizeEvent}
+-type wxMaximizeEventType() :: maximize.
+-type wxMaximize() :: #wxMaximize{}. %% Callback event: {@link wxMaximizeEvent}
-%% @type wxFileDirPicker() = #wxFileDirPicker{type=wxEventType(),path=string()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_filepicker_changed</em>, <em>command_dirpicker_changed</em></dd></dl>
-%% Callback event: {@link wxFileDirPickerEvent}
--record(wxFileDirPicker,{type, path}).
+-record(wxFileDirPicker,{type :: wxFileDirPickerEventType(), %% Callback event: {@link wxFileDirPickerEvent}
+ path :: unicode:chardata()}).
+-type wxFileDirPickerEventType() :: command_filepicker_changed | command_dirpicker_changed.
+-type wxFileDirPicker() :: #wxFileDirPicker{}. %% Callback event: {@link wxFileDirPickerEvent}
-%% @type wxFocus() = #wxFocus{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>set_focus</em>, <em>kill_focus</em></dd></dl>
-%% Callback event: {@link wxFocusEvent}
--record(wxFocus, {type}).
+-record(wxFocus, {type :: wxFocusEventType()}). %% Callback event: {@link wxFocusEvent}
+-type wxFocusEventType() :: set_focus | kill_focus.
+-type wxFocus() :: #wxFocus{}. %% Callback event: {@link wxFocusEvent}
-%% @type wxDate() = #wxDate{type=wxEventType(),date=wx:datetime()}.
-%% <dl><dt>EventType:</dt> <dd><em>date_changed</em></dd></dl>
-%% Callback event: {@link wxDateEvent}
--record(wxDate,{type, date}).
+-record(wxDate,{type :: wxDateEventType(), %% Callback event: {@link wxDateEvent}
+ date :: wx:wx_datetime()}).
+-type wxDateEventType() :: date_changed.
+-type wxDate() :: #wxDate{}. %% Callback event: {@link wxDateEvent}
-%% @type wxHtmlLink() = #wxHtmlLink{type=wxEventType(),linkInfo=wx:wxHtmlLinkInfo()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_html_link_clicked</em></dd></dl>
-%% Callback event: {@link wxHtmlLinkEvent}
--record(wxHtmlLink,{type, linkInfo}).
+-record(wxHtmlLink,{type :: wxHtmlLinkEventType(), %% Callback event: {@link wxHtmlLinkEvent}
+ linkInfo :: wx:wx_wxHtmlLinkInfo()}).
+-type wxHtmlLinkEventType() :: command_html_link_clicked.
+-type wxHtmlLink() :: #wxHtmlLink{}. %% Callback event: {@link wxHtmlLinkEvent}
-%% @type wxHelp() = #wxHelp{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>help</em>, <em>detailed_help</em></dd></dl>
-%% Callback event: {@link wxHelpEvent}
--record(wxHelp, {type}).
+-record(wxHelp, {type :: wxHelpEventType()}). %% Callback event: {@link wxHelpEvent}
+-type wxHelpEventType() :: help | detailed_help.
+-type wxHelp() :: #wxHelp{}. %% Callback event: {@link wxHelpEvent}
-%% @type wxStyledText() = #wxStyledText{type=wxEventType(),position=integer(),key=integer(),modifiers=integer(),modificationType=integer(),text=string(),length=integer(),linesAdded=integer(),line=integer(),foldLevelNow=integer(),foldLevelPrev=integer(),margin=integer(),message=integer(),wParam=integer(),lParam=integer(),listType=integer(),x=integer(),y=integer(),dragText=string(),dragAllowMove=bool(),dragResult=WxDragResult}.
-%% <dl><dt>EventType:</dt> <dd><em>stc_change</em>, <em>stc_styleneeded</em>, <em>stc_charadded</em>, <em>stc_savepointreached</em>, <em>stc_savepointleft</em>, <em>stc_romodifyattempt</em>, <em>stc_key</em>, <em>stc_doubleclick</em>, <em>stc_updateui</em>, <em>stc_modified</em>, <em>stc_macrorecord</em>, <em>stc_marginclick</em>, <em>stc_needshown</em>, <em>stc_painted</em>, <em>stc_userlistselection</em>, <em>stc_uridropped</em>, <em>stc_dwellstart</em>, <em>stc_dwellend</em>, <em>stc_start_drag</em>, <em>stc_drag_over</em>, <em>stc_do_drop</em>, <em>stc_zoom</em>, <em>stc_hotspot_click</em>, <em>stc_hotspot_dclick</em>, <em>stc_calltip_click</em>, <em>stc_autocomp_selection</em></dd></dl>
-%% Callback event: {@link wxStyledTextEvent}
--record(wxStyledText,{type, position,key,modifiers,modificationType,text,length,linesAdded,line,foldLevelNow,foldLevelPrev,margin,message,wParam,lParam,listType,x,y,dragText,dragAllowMove,dragResult}).
+-record(wxStyledText,{type :: wxStyledTextEventType(), %% Callback event: {@link wxStyledTextEvent}
+ position :: integer(),
+ key :: integer(),
+ modifiers :: integer(),
+ modificationType :: integer(),
+ text :: unicode:chardata(),
+ length :: integer(),
+ linesAdded :: integer(),
+ line :: integer(),
+ foldLevelNow :: integer(),
+ foldLevelPrev :: integer(),
+ margin :: integer(),
+ message :: integer(),
+ wParam :: integer(),
+ lParam :: integer(),
+ listType :: integer(),
+ x :: integer(),
+ y :: integer(),
+ dragText :: unicode:chardata(),
+ dragAllowMove :: boolean(),
+ dragResult :: wx:wx_enum()}).
+-type wxStyledTextEventType() :: stc_change | stc_styleneeded | stc_charadded | stc_savepointreached | stc_savepointleft | stc_romodifyattempt | stc_key | stc_doubleclick | stc_updateui | stc_modified | stc_macrorecord | stc_marginclick | stc_needshown | stc_painted | stc_userlistselection | stc_uridropped | stc_dwellstart | stc_dwellend | stc_start_drag | stc_drag_over | stc_do_drop | stc_zoom | stc_hotspot_click | stc_hotspot_dclick | stc_calltip_click | stc_autocomp_selection.
+-type wxStyledText() :: #wxStyledText{}. %% Callback event: {@link wxStyledTextEvent}
-%% @type wxSysColourChanged() = #wxSysColourChanged{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>sys_colour_changed</em></dd></dl>
-%% Callback event: {@link wxSysColourChangedEvent}
--record(wxSysColourChanged, {type}).
+-record(wxSysColourChanged, {type :: wxSysColourChangedEventType()}). %% Callback event: {@link wxSysColourChangedEvent}
+-type wxSysColourChangedEventType() :: sys_colour_changed.
+-type wxSysColourChanged() :: #wxSysColourChanged{}. %% Callback event: {@link wxSysColourChangedEvent}
-%% @type wxGrid() = #wxGrid{type=wxEventType(),row=integer(),col=integer(),x=integer(),y=integer(),selecting=bool(),control=bool(),meta=bool(),shift=bool(),alt=bool()}.
-%% <dl><dt>EventType:</dt> <dd><em>grid_cell_left_click</em>, <em>grid_cell_right_click</em>, <em>grid_cell_left_dclick</em>, <em>grid_cell_right_dclick</em>, <em>grid_label_left_click</em>, <em>grid_label_right_click</em>, <em>grid_label_left_dclick</em>, <em>grid_label_right_dclick</em>, <em>grid_row_size</em>, <em>grid_col_size</em>, <em>grid_range_select</em>, <em>grid_cell_change</em>, <em>grid_select_cell</em>, <em>grid_editor_shown</em>, <em>grid_editor_hidden</em>, <em>grid_editor_created</em>, <em>grid_cell_begin_drag</em></dd></dl>
-%% Callback event: {@link wxGridEvent}
--record(wxGrid,{type, row,col,x,y,selecting,control,meta,shift,alt}).
+-record(wxGrid,{type :: wxGridEventType(), %% Callback event: {@link wxGridEvent}
+ row :: integer(),
+ col :: integer(),
+ x :: integer(),
+ y :: integer(),
+ selecting :: boolean(),
+ control :: boolean(),
+ meta :: boolean(),
+ shift :: boolean(),
+ alt :: boolean()}).
+-type wxGridEventType() :: grid_cell_left_click | grid_cell_right_click | grid_cell_left_dclick | grid_cell_right_dclick | grid_label_left_click | grid_label_right_click | grid_label_left_dclick | grid_label_right_dclick | grid_row_size | grid_col_size | grid_range_select | grid_cell_change | grid_select_cell | grid_editor_shown | grid_editor_hidden | grid_editor_created | grid_cell_begin_drag.
+-type wxGrid() :: #wxGrid{}. %% Callback event: {@link wxGridEvent}
-%% @type wxPaletteChanged() = #wxPaletteChanged{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>palette_changed</em></dd></dl>
-%% Callback event: {@link wxPaletteChangedEvent}
--record(wxPaletteChanged, {type}).
+-record(wxPaletteChanged, {type :: wxPaletteChangedEventType()}). %% Callback event: {@link wxPaletteChangedEvent}
+-type wxPaletteChangedEventType() :: palette_changed.
+-type wxPaletteChanged() :: #wxPaletteChanged{}. %% Callback event: {@link wxPaletteChangedEvent}
-%% @type wxUpdateUI() = #wxUpdateUI{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>update_ui</em></dd></dl>
-%% Callback event: {@link wxUpdateUIEvent}
--record(wxUpdateUI, {type}).
+-record(wxUpdateUI, {type :: wxUpdateUIEventType()}). %% Callback event: {@link wxUpdateUIEvent}
+-type wxUpdateUIEventType() :: update_ui.
+-type wxUpdateUI() :: #wxUpdateUI{}. %% Callback event: {@link wxUpdateUIEvent}
-%% @type wxSize() = #wxSize{type=wxEventType(),size={W::integer(),H::integer()},rect={X::integer(),Y::integer(),W::integer(),H::integer()}}.
-%% <dl><dt>EventType:</dt> <dd><em>size</em></dd></dl>
-%% Callback event: {@link wxSizeEvent}
--record(wxSize,{type, size,rect}).
+-record(wxSize,{type :: wxSizeEventType(), %% Callback event: {@link wxSizeEvent}
+ size :: {W::integer(), H::integer()},
+ rect :: {X::integer(), Y::integer(), W::integer(), H::integer()}}).
+-type wxSizeEventType() :: size.
+-type wxSize() :: #wxSize{}. %% Callback event: {@link wxSizeEvent}
-%% @type wxIconize() = #wxIconize{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>iconize</em></dd></dl>
-%% Callback event: {@link wxIconizeEvent}
--record(wxIconize, {type}).
+-record(wxIconize, {type :: wxIconizeEventType()}). %% Callback event: {@link wxIconizeEvent}
+-type wxIconizeEventType() :: iconize.
+-type wxIconize() :: #wxIconize{}. %% Callback event: {@link wxIconizeEvent}
-%% @type wxAuiNotebook() = #wxAuiNotebook{type=wxEventType(),old_selection=integer(),selection=integer(),drag_source=wxAuiNotebook:wxAuiNotebook()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_auinotebook_page_close</em>, <em>command_auinotebook_page_changed</em>, <em>command_auinotebook_page_changing</em>, <em>command_auinotebook_button</em>, <em>command_auinotebook_begin_drag</em>, <em>command_auinotebook_end_drag</em>, <em>command_auinotebook_drag_motion</em>, <em>command_auinotebook_allow_dnd</em>, <em>command_auinotebook_tab_middle_down</em>, <em>command_auinotebook_tab_middle_up</em>, <em>command_auinotebook_tab_right_down</em>, <em>command_auinotebook_tab_right_up</em>, <em>command_auinotebook_page_closed</em>, <em>command_auinotebook_drag_done</em>, <em>command_auinotebook_bg_dclick</em></dd></dl>
-%% Callback event: {@link wxAuiNotebookEvent}
--record(wxAuiNotebook,{type, old_selection,selection,drag_source}).
+-record(wxAuiNotebook,{type :: wxAuiNotebookEventType(), %% Callback event: {@link wxAuiNotebookEvent}
+ old_selection :: integer(),
+ selection :: integer(),
+ drag_source :: wxAuiNotebook:wxAuiNotebook()}).
+-type wxAuiNotebookEventType() :: command_auinotebook_page_close | command_auinotebook_page_changed | command_auinotebook_page_changing | command_auinotebook_button | command_auinotebook_begin_drag | command_auinotebook_end_drag | command_auinotebook_drag_motion | command_auinotebook_allow_dnd | command_auinotebook_tab_middle_down | command_auinotebook_tab_middle_up | command_auinotebook_tab_right_down | command_auinotebook_tab_right_up | command_auinotebook_page_closed | command_auinotebook_drag_done | command_auinotebook_bg_dclick.
+-type wxAuiNotebook() :: #wxAuiNotebook{}. %% Callback event: {@link wxAuiNotebookEvent}
-%% @type wxClose() = #wxClose{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>close_window</em>, <em>end_session</em>, <em>query_end_session</em></dd></dl>
-%% Callback event: {@link wxCloseEvent}
--record(wxClose, {type}).
+-record(wxClose, {type :: wxCloseEventType()}). %% Callback event: {@link wxCloseEvent}
+-type wxCloseEventType() :: close_window | end_session | query_end_session.
+-type wxClose() :: #wxClose{}. %% Callback event: {@link wxCloseEvent}
-%% @type wxMouseCaptureChanged() = #wxMouseCaptureChanged{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>mouse_capture_changed</em></dd></dl>
-%% Callback event: {@link wxMouseCaptureChangedEvent}
--record(wxMouseCaptureChanged, {type}).
+-record(wxMouseCaptureChanged, {type :: wxMouseCaptureChangedEventType()}). %% Callback event: {@link wxMouseCaptureChangedEvent}
+-type wxMouseCaptureChangedEventType() :: mouse_capture_changed.
+-type wxMouseCaptureChanged() :: #wxMouseCaptureChanged{}. %% Callback event: {@link wxMouseCaptureChangedEvent}
-%% @type wxMouse() = #wxMouse{type=wxEventType(),x=integer(),y=integer(),leftDown=bool(),middleDown=bool(),rightDown=bool(),controlDown=bool(),shiftDown=bool(),altDown=bool(),metaDown=bool(),wheelRotation=integer(),wheelDelta=integer(),linesPerAction=integer()}.
-%% <dl><dt>EventType:</dt> <dd><em>left_down</em>, <em>left_up</em>, <em>middle_down</em>, <em>middle_up</em>, <em>right_down</em>, <em>right_up</em>, <em>motion</em>, <em>enter_window</em>, <em>leave_window</em>, <em>left_dclick</em>, <em>middle_dclick</em>, <em>right_dclick</em>, <em>mousewheel</em>, <em>nc_left_down</em>, <em>nc_left_up</em>, <em>nc_middle_down</em>, <em>nc_middle_up</em>, <em>nc_right_down</em>, <em>nc_right_up</em>, <em>nc_motion</em>, <em>nc_enter_window</em>, <em>nc_leave_window</em>, <em>nc_left_dclick</em>, <em>nc_middle_dclick</em>, <em>nc_right_dclick</em></dd></dl>
-%% Callback event: {@link wxMouseEvent}
--record(wxMouse,{type, x,y,leftDown,middleDown,rightDown,controlDown,shiftDown,altDown,metaDown,wheelRotation,wheelDelta,linesPerAction}).
+-record(wxMouse,{type :: wxMouseEventType(), %% Callback event: {@link wxMouseEvent}
+ x :: integer(),
+ y :: integer(),
+ leftDown :: boolean(),
+ middleDown :: boolean(),
+ rightDown :: boolean(),
+ controlDown :: boolean(),
+ shiftDown :: boolean(),
+ altDown :: boolean(),
+ metaDown :: boolean(),
+ wheelRotation :: integer(),
+ wheelDelta :: integer(),
+ linesPerAction :: integer()}).
+-type wxMouseEventType() :: left_down | left_up | middle_down | middle_up | right_down | right_up | motion | enter_window | leave_window | left_dclick | middle_dclick | right_dclick | mousewheel | nc_left_down | nc_left_up | nc_middle_down | nc_middle_up | nc_right_down | nc_right_up | nc_motion | nc_enter_window | nc_leave_window | nc_left_dclick | nc_middle_dclick | nc_right_dclick.
+-type wxMouse() :: #wxMouse{}. %% Callback event: {@link wxMouseEvent}
-%% @type wxWindowCreate() = #wxWindowCreate{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>create</em></dd></dl>
-%% Callback event: {@link wxWindowCreateEvent}
--record(wxWindowCreate, {type}).
+-record(wxWindowCreate, {type :: wxWindowCreateEventType()}). %% Callback event: {@link wxWindowCreateEvent}
+-type wxWindowCreateEventType() :: create.
+-type wxWindowCreate() :: #wxWindowCreate{}. %% Callback event: {@link wxWindowCreateEvent}
-%% @type wxAuiManager() = #wxAuiManager{type=wxEventType(),manager=wxAuiManager:wxAuiManager(),pane=wxAuiPaneInfo:wxAuiPaneInfo(),button=integer(),veto_flag=bool(),canveto_flag=bool(),dc=wxDC:wxDC()}.
-%% <dl><dt>EventType:</dt> <dd><em>aui_pane_button</em>, <em>aui_pane_close</em>, <em>aui_pane_maximize</em>, <em>aui_pane_restore</em>, <em>aui_render</em>, <em>aui_find_manager</em></dd></dl>
-%% Callback event: {@link wxAuiManagerEvent}
--record(wxAuiManager,{type, manager,pane,button,veto_flag,canveto_flag,dc}).
+-record(wxAuiManager,{type :: wxAuiManagerEventType(), %% Callback event: {@link wxAuiManagerEvent}
+ manager :: wxAuiManager:wxAuiManager(),
+ pane :: wxAuiPaneInfo:wxAuiPaneInfo(),
+ button :: integer(),
+ veto_flag :: boolean(),
+ canveto_flag :: boolean(),
+ dc :: wxDC:wxDC()}).
+-type wxAuiManagerEventType() :: aui_pane_button | aui_pane_close | aui_pane_maximize | aui_pane_restore | aui_render | aui_find_manager.
+-type wxAuiManager() :: #wxAuiManager{}. %% Callback event: {@link wxAuiManagerEvent}
-%% @type wxCommand() = #wxCommand{type=wxEventType(),cmdString=string(),commandInt=integer(),extraLong=integer()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_button_clicked</em>, <em>command_checkbox_clicked</em>, <em>command_choice_selected</em>, <em>command_listbox_selected</em>, <em>command_listbox_doubleclicked</em>, <em>command_text_updated</em>, <em>command_text_enter</em>, <em>command_menu_selected</em>, <em>command_slider_updated</em>, <em>command_radiobox_selected</em>, <em>command_radiobutton_selected</em>, <em>command_scrollbar_updated</em>, <em>command_vlbox_selected</em>, <em>command_combobox_selected</em>, <em>command_tool_rclicked</em>, <em>command_tool_enter</em>, <em>command_checklistbox_toggled</em>, <em>command_togglebutton_clicked</em>, <em>command_left_click</em>, <em>command_left_dclick</em>, <em>command_right_click</em>, <em>command_set_focus</em>, <em>command_kill_focus</em>, <em>command_enter</em></dd></dl>
-%% Callback event: {@link wxCommandEvent}
--record(wxCommand,{type, cmdString,commandInt,extraLong}).
+-record(wxCommand,{type :: wxCommandEventType(), %% Callback event: {@link wxCommandEvent}
+ cmdString :: unicode:chardata(),
+ commandInt :: integer(),
+ extraLong :: integer()}).
+-type wxCommandEventType() :: command_button_clicked | command_checkbox_clicked | command_choice_selected | command_listbox_selected | command_listbox_doubleclicked | command_text_updated | command_text_enter | command_menu_selected | command_slider_updated | command_radiobox_selected | command_radiobutton_selected | command_scrollbar_updated | command_vlbox_selected | command_combobox_selected | command_tool_rclicked | command_tool_enter | command_checklistbox_toggled | command_togglebutton_clicked | command_left_click | command_left_dclick | command_right_click | command_set_focus | command_kill_focus | command_enter.
+-type wxCommand() :: #wxCommand{}. %% Callback event: {@link wxCommandEvent}
-%% @type wxJoystick() = #wxJoystick{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>joy_button_down</em>, <em>joy_button_up</em>, <em>joy_move</em>, <em>joy_zmove</em></dd></dl>
-%% Callback event: {@link wxJoystickEvent}
--record(wxJoystick, {type}).
+-record(wxJoystick, {type :: wxJoystickEventType()}). %% Callback event: {@link wxJoystickEvent}
+-type wxJoystickEventType() :: joy_button_down | joy_button_up | joy_move | joy_zmove.
+-type wxJoystick() :: #wxJoystick{}. %% Callback event: {@link wxJoystickEvent}
-%% @type wxQueryNewPalette() = #wxQueryNewPalette{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>query_new_palette</em></dd></dl>
-%% Callback event: {@link wxQueryNewPaletteEvent}
--record(wxQueryNewPalette, {type}).
+-record(wxQueryNewPalette, {type :: wxQueryNewPaletteEventType()}). %% Callback event: {@link wxQueryNewPaletteEvent}
+-type wxQueryNewPaletteEventType() :: query_new_palette.
+-type wxQueryNewPalette() :: #wxQueryNewPalette{}. %% Callback event: {@link wxQueryNewPaletteEvent}
-%% @type wxMove() = #wxMove{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>move</em></dd></dl>
-%% Callback event: {@link wxMoveEvent}
--record(wxMove, {type}).
+-record(wxMove, {type :: wxMoveEventType()}). %% Callback event: {@link wxMoveEvent}
+-type wxMoveEventType() :: move.
+-type wxMove() :: #wxMove{}. %% Callback event: {@link wxMoveEvent}
-%% @type wxIdle() = #wxIdle{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>idle</em></dd></dl>
-%% Callback event: {@link wxIdleEvent}
--record(wxIdle, {type}).
+-record(wxIdle, {type :: wxIdleEventType()}). %% Callback event: {@link wxIdleEvent}
+-type wxIdleEventType() :: idle.
+-type wxIdle() :: #wxIdle{}. %% Callback event: {@link wxIdleEvent}
-%% @type wxNcPaint() = #wxNcPaint{type=wxEventType()}.
-%% <dl><dt>EventType:</dt> <dd><em>nc_paint</em></dd></dl>
-%% Callback event: {@link wxNcPaintEvent}
--record(wxNcPaint, {type}).
+-record(wxNcPaint, {type :: wxNcPaintEventType()}). %% Callback event: {@link wxNcPaintEvent}
+-type wxNcPaintEventType() :: nc_paint.
+-type wxNcPaint() :: #wxNcPaint{}. %% Callback event: {@link wxNcPaintEvent}
-%% @type wxColourPicker() = #wxColourPicker{type=wxEventType(),colour=wx:colour()}.
-%% <dl><dt>EventType:</dt> <dd><em>command_colourpicker_changed</em></dd></dl>
-%% Callback event: {@link wxColourPickerEvent}
--record(wxColourPicker,{type, colour}).
+-record(wxColourPicker,{type :: wxColourPickerEventType(), %% Callback event: {@link wxColourPickerEvent}
+ colour :: wx:wx_colour()}).
+-type wxColourPickerEventType() :: command_colourpicker_changed.
+-type wxColourPicker() :: #wxColourPicker{}. %% Callback event: {@link wxColourPickerEvent}
-%% @type wxTree() = #wxTree{type=wxEventType(),item=integer(),itemOld=integer(),pointDrag={X::integer(),Y::integer()}}.
-%% <dl><dt>EventType:</dt> <dd><em>command_tree_begin_drag</em>, <em>command_tree_begin_rdrag</em>, <em>command_tree_begin_label_edit</em>, <em>command_tree_end_label_edit</em>, <em>command_tree_delete_item</em>, <em>command_tree_get_info</em>, <em>command_tree_set_info</em>, <em>command_tree_item_expanded</em>, <em>command_tree_item_expanding</em>, <em>command_tree_item_collapsed</em>, <em>command_tree_item_collapsing</em>, <em>command_tree_sel_changed</em>, <em>command_tree_sel_changing</em>, <em>command_tree_key_down</em>, <em>command_tree_item_activated</em>, <em>command_tree_item_right_click</em>, <em>command_tree_item_middle_click</em>, <em>command_tree_end_drag</em>, <em>command_tree_state_image_click</em>, <em>command_tree_item_gettooltip</em>, <em>command_tree_item_menu</em></dd></dl>
-%% Callback event: {@link wxTreeEvent}
--record(wxTree,{type, item,itemOld,pointDrag}).
+-record(wxTaskBarIcon, {type :: wxTaskBarIconEventType()}). %% Callback event: {@link wxTaskBarIconEvent}
+-type wxTaskBarIconEventType() :: taskbar_move | taskbar_left_down | taskbar_left_up | taskbar_right_down | taskbar_right_up | taskbar_left_dclick | taskbar_right_dclick.
+-type wxTaskBarIcon() :: #wxTaskBarIcon{}. %% Callback event: {@link wxTaskBarIconEvent}
-%% @type wxEventType() = aui_find_manager | aui_pane_button | aui_pane_close | aui_pane_maximize | aui_pane_restore | aui_render | calendar_day_changed | calendar_doubleclicked | calendar_month_changed | calendar_sel_changed | calendar_weekday_clicked | calendar_year_changed | char | char_hook | child_focus | close_window | command_auinotebook_allow_dnd | command_auinotebook_begin_drag | command_auinotebook_bg_dclick | command_auinotebook_button | command_auinotebook_drag_done | command_auinotebook_drag_motion | command_auinotebook_end_drag | command_auinotebook_page_changed | command_auinotebook_page_changing | command_auinotebook_page_close | command_auinotebook_page_closed | command_auinotebook_tab_middle_down | command_auinotebook_tab_middle_up | command_auinotebook_tab_right_down | command_auinotebook_tab_right_up | command_button_clicked | command_checkbox_clicked | command_checklistbox_toggled | command_choice_selected | command_colourpicker_changed | command_combobox_selected | command_dirpicker_changed | command_enter | command_filepicker_changed | command_fontpicker_changed | command_html_link_clicked | command_kill_focus | command_left_click | command_left_dclick | command_list_begin_drag | command_list_begin_label_edit | command_list_begin_rdrag | command_list_cache_hint | command_list_col_begin_drag | command_list_col_click | command_list_col_dragging | command_list_col_end_drag | command_list_col_right_click | command_list_delete_all_items | command_list_delete_item | command_list_end_label_edit | command_list_insert_item | command_list_item_activated | command_list_item_deselected | command_list_item_focused | command_list_item_middle_click | command_list_item_right_click | command_list_item_selected | command_list_key_down | command_listbox_doubleclicked | command_listbox_selected | command_menu_selected | command_notebook_page_changed | command_notebook_page_changing | command_radiobox_selected | command_radiobutton_selected | command_right_click | command_scrollbar_updated | command_set_focus | command_slider_updated | command_spinctrl_updated | command_splitter_doubleclicked | command_splitter_sash_pos_changed | command_splitter_sash_pos_changing | command_splitter_unsplit | command_text_enter | command_text_updated | command_togglebutton_clicked | command_tool_enter | command_tool_rclicked | command_tree_begin_drag | command_tree_begin_label_edit | command_tree_begin_rdrag | command_tree_delete_item | command_tree_end_drag | command_tree_end_label_edit | command_tree_get_info | command_tree_item_activated | command_tree_item_collapsed | command_tree_item_collapsing | command_tree_item_expanded | command_tree_item_expanding | command_tree_item_gettooltip | command_tree_item_menu | command_tree_item_middle_click | command_tree_item_right_click | command_tree_key_down | command_tree_sel_changed | command_tree_sel_changing | command_tree_set_info | command_tree_state_image_click | command_vlbox_selected | context_menu | create | date_changed | destroy | detailed_help | display_changed | end_session | enter_window | erase_background | grid_cell_begin_drag | grid_cell_change | grid_cell_left_click | grid_cell_left_dclick | grid_cell_right_click | grid_cell_right_dclick | grid_col_size | grid_editor_created | grid_editor_hidden | grid_editor_shown | grid_label_left_click | grid_label_left_dclick | grid_label_right_click | grid_label_right_dclick | grid_range_select | grid_row_size | grid_select_cell | help | iconize | idle | joy_button_down | joy_button_up | joy_move | joy_zmove | key_down | key_up | kill_focus | leave_window | left_dclick | left_down | left_up | maximize | menu_close | menu_highlight | menu_open | middle_dclick | middle_down | middle_up | motion | mouse_capture_changed | mousewheel | move | navigation_key | nc_enter_window | nc_leave_window | nc_left_dclick | nc_left_down | nc_left_up | nc_middle_dclick | nc_middle_down | nc_middle_up | nc_motion | nc_paint | nc_right_dclick | nc_right_down | nc_right_up | paint | paint_icon | palette_changed | query_end_session | query_new_palette | right_dclick | right_down | right_up | sash_dragged | scroll_bottom | scroll_changed | scroll_linedown | scroll_lineup | scroll_pagedown | scroll_pageup | scroll_thumbrelease | scroll_thumbtrack | scroll_top | scrollwin_bottom | scrollwin_linedown | scrollwin_lineup | scrollwin_pagedown | scrollwin_pageup | scrollwin_thumbrelease | scrollwin_thumbtrack | scrollwin_top | set_cursor | set_focus | show | size | spin | spin_down | spin_up | stc_autocomp_selection | stc_calltip_click | stc_change | stc_charadded | stc_do_drop | stc_doubleclick | stc_drag_over | stc_dwellend | stc_dwellstart | stc_hotspot_click | stc_hotspot_dclick | stc_key | stc_macrorecord | stc_marginclick | stc_modified | stc_needshown | stc_painted | stc_romodifyattempt | stc_savepointleft | stc_savepointreached | stc_start_drag | stc_styleneeded | stc_updateui | stc_uridropped | stc_userlistselection | stc_zoom | sys_colour_changed | update_ui.
+-record(wxTree,{type :: wxTreeEventType(), %% Callback event: {@link wxTreeEvent}
+ item :: integer(),
+ itemOld :: integer(),
+ pointDrag :: {X::integer(), Y::integer()}}).
+-type wxTreeEventType() :: command_tree_begin_drag | command_tree_begin_rdrag | command_tree_begin_label_edit | command_tree_end_label_edit | command_tree_delete_item | command_tree_get_info | command_tree_set_info | command_tree_item_expanded | command_tree_item_expanding | command_tree_item_collapsed | command_tree_item_collapsing | command_tree_sel_changed | command_tree_sel_changing | command_tree_key_down | command_tree_item_activated | command_tree_item_right_click | command_tree_item_middle_click | command_tree_end_drag | command_tree_state_image_click | command_tree_item_gettooltip | command_tree_item_menu.
+-type wxTree() :: #wxTree{}. %% Callback event: {@link wxTreeEvent}
+
+-type event() :: wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMove() | wxNavigationKey() | wxNcPaint() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy().
+-type wxEventType() :: wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNcPaintEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType().
%% Hardcoded Records
--record(wxMouseState, {x, y, %% integer()
- leftDown, middleDown, rightDown, %% bool()
- controlDown, shiftDown, altDown, metaDown, cmdDown %% bool()
+-record(wxMouseState, {x :: integer(), y :: integer(),
+ leftDown :: boolean(), middleDown :: boolean, rightDown :: boolean,
+ controlDown :: boolean(), shiftDown :: boolean(),
+ altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean()
}).
-record(wxHtmlLinkInfo, {
- href, target %% string()
+ href :: unicode:chardata(), target :: unicode:chardata()
}).
%% Hardcoded Defines
@@ -937,7 +985,7 @@
-define(wxRESET, 16384).
-define(wxBACKWARD, 8192).
-define(wxFORWARD, 4096).
--define(wxICON_MASK, (?16#00000100 bor ?16#00000200 bor ?16#00000400 bor ?16#00000800)).
+-define(wxICON_MASK, (16#00000100 bor 16#00000200 bor 16#00000400 bor 16#00000800)).
-define(wxICON_ASTERISK, ?wxICON_INFORMATION).
-define(wxICON_STOP, ?wxICON_HAND).
-define(wxICON_INFORMATION, 2048).
diff --git a/lib/wx/install.es b/lib/wx/install.es
deleted file mode 100755
index 2811c7728c..0000000000
--- a/lib/wx/install.es
+++ /dev/null
@@ -1,302 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% Install wx to an erlang distribution.
-%%
-
--module('install_es'). %% Temp workaround for buggy escript
--mode(compile).
-
-usage() ->
- io:format("install [Opts] [InstallDir]~n",[]),
- io:format(" -v verbose~n",[]),
- io:format(" -q quiet and direct no questions~n",[]),
- io:format(" --create_release To create a release~n~n",[]),
- ok.
-
-main([]) ->
- IDir = filename:join(code:root_dir(),"lib"),
- install(IDir),
- ok;
-main(Opts) ->
- IDir = options(Opts),
- install(IDir),
- ok.
-
-install_files() ->
- [{[], {files, ["README","TODO", "Notes", "license.terms"]}},
- {[src], {list, "*.?rl"}},
- {[include], {list, "*.hrl"}},
- {[src,gen], {list, "*.?rl"}},
- {[test], {list, "*.?rl"}},
- {[test], {list, "*.bmp"}},
- {[test], {files, ["wxt", "Readme"]}},
- {[samples], {files, ["sample.xpm"]}},
- {[samples,menu], {files, ["copy.xpm"]}},
- {[samples,'*'], {list, "*.?rl"}},
- {[demos,'*'], {list, "*.?rl"}},
- {[demos,xrc,rc], {list, "*"}},
- {[doc,html], {files, ["edoc-info", "erlang.png", "stylesheet.css"]}}
- ].
-
-built_files(SrcDir, Type) ->
- Dirs = [{[doc], {list, "*.html"}},
- {[ebin], {list, "*"}},
- {[test], {list, "*.beam"}},
- {[demos,'*'], {list, "*.beam"}},
- {[samples,'*'], {list, "*.beam"}}],
- case Type of
- install ->
- [{[priv,'*'], {list, "*"}}|Dirs];
- _ -> %% Create Rel
- Win32 = [{[priv,win32], {list, "*"}}| Dirs],
- case filelib:wildcard("i386-apple*",
- filename:join(SrcDir, "priv")) of
- [Mac] ->
- [{[priv,list_to_atom(Mac)], {list, "*"}}|Win32];
- [] ->
- io:format("WARNING: Missing Mac driver!~n",[]),
- Win32
- end
- end.
-
-release_files() ->
- [{[], {files, ["configure.in","Makefile","wxwin.m4", "config.mk.in", "vsn.mk"]}},
- {[], {files, ["configure", "install.es"]}},
- {[autoconf], {files, ["config.guess","config.sub","install-sh"]}},
- {[src], {files, ["Makefile"]}},
- {[c_src], {files, ["Makefile.in"]}},
- {[c_src], {list, "*.c*"}},
- {[c_src], {list, "*.h"}},
- {[c_src,gen], {list, "*.cpp"}},
- {[c_src,gen], {list, "*.h"}},
- {[doc], {files, ["overview.edoc"]}},
- {[doc,src], {files, ["Makefile"]}},
- {[test], {files, ["Makefile"]}},
-%% {[demos], {files, ["Makefile"]}},
-%% {[demos,'*'], {files, ["Makefile"]}},
-%% {[samples], {files, ["Makefile"]}},
-%% {[samples,'*'], {files, ["Makefile"]}},
- {[api_gen], {list, "*.?rl"}},
- {[api_gen], {list, "*.conf"}},
- {[api_gen], {files, ["Makefile", "README"]}},
- {[api_gen, wx_extra], {list, "*"}}
- ].
-
-options(["-v"|Os]) ->
- put(verbose,true),
- options(Os);
-options(["-q"|Os]) ->
- put(quiet,true),
- options(Os);
-options(["--help"|_]) ->
- usage(),
- halt(0);
-options(["-h"|_]) ->
- usage(),
- halt(0);
-options(["--create_release"|Os]) ->
- put(create_release,true),
- options(Os);
-options(["-" ++_ |_Os]) ->
- usage(),
- halt(1);
-options([Dir]) -> Dir;
-options([]) ->
- filename:join(code:root_dir(),"lib").
-
-install(Dir) ->
- try
- case get(create_release) of
- true -> create_release();
- _ -> install2(Dir)
- end
- catch E:R ->
- io:format("Error ~p:~p in ~n ~p~n",[E,R, erlang:get_stacktrace()])
- end.
-
-install2(IDir) ->
- SrcD = get_src_dir(),
- Ver = get_version(SrcD),
- case get(quiet) of
- true ->
- copy_files(SrcD, filename:append(IDir,Ver)),
- ok;
- _ ->
- io:format("Installing ~p~n From ~p to ~p ~n",[Ver,SrcD,IDir]),
- case is_ok('ok [y|n]? ',[y,n]) of
- y ->
- copy_files(SrcD, filename:append(IDir,Ver)),
- io:format("Install complete~n",[]),
- ok;
- n ->
- usage(),
- halt(1)
- end
- end.
-
-copy_files(FromD, ToD) ->
- Fs = install_files() ++ built_files(FromD, install),
- Copy = fun(File, From, To, Acc) ->
- ensure_dir(To),
- case file:copy(filename:join(From,File),
- filename:join(To,File)) of
- {ok, _Bytes} ->
- [File|Acc];
- {error,_} ->
- io:format("ERROR Could not install file: ~p in~n ~p~n",
- [filename:join(From,File),
- filename:join(To,File)]),
- Acc
- end
- end,
- [expand_dirs(Dir,Files,FromD,ToD,Copy,[]) || {Dir,Files} <- Fs].
-
-expand_dirs(['*'|Ds],Fs,From,To,Fun,Acc) ->
- All = filelib:wildcard("[A-Za-z]*", From),
- Filter = fun(F) -> filelib:is_dir(filename:join(From,F)) end,
- Dirs = lists:filter(Filter, All),
- lists:foldl(fun(Dir,Nacc) ->
- expand_dirs([Dir|Ds],Fs,From,To,Fun,Nacc)
- end,
- Acc, Dirs);
-expand_dirs([Dir|Ds],Fs,From,To,Fun,Acc) ->
- expand_dirs(Ds,Fs,filename:join(From,Dir),filename:join(To,Dir),Fun,Acc);
-expand_dirs([],Fs,From,To,Fun,Acc) ->
- expand_files(Fs,From,To,Fun,Acc).
-
-expand_files({files,Fs},From,To,Fun,Acc) ->
- case get(verbose) of
- true -> io:format(" Check dir ~p to ~p~n", [From,To]);
- _ -> ok
- end,
- expand_files2(Fs,From,To,Fun,Acc);
-expand_files({list,WildCard},From,To,Fun,Acc) ->
- All = filelib:wildcard(WildCard, From),
- Filter = fun(F) -> filelib:is_regular(filename:join(From,F)) end,
- Fs = lists:filter(Filter, All),
- case get(verbose) of
- true -> io:format(" Check dir ~p to ~p~n", [From,To]);
- _ -> ok
- end,
- expand_files2(Fs,From,To,Fun,Acc).
-
-expand_files2(Fs,From,To,Fun,PrevAcc) ->
- lists:foldl(fun(File, Acc) -> Fun(File, From, To, Acc) end, PrevAcc, Fs).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-create_release() ->
- All = release_files() ++ install_files(),
- SrcD = get_src_dir(),
- Ver = "wx-" ++ get_version(SrcD),
- io:format("Create release ~p~n From ~p ~n",[Ver,SrcD]),
- case is_ok('ok [y|n]? ',[y,n]) of
- y ->
- List = fun(File, From, To, Acc) ->
- case filelib:is_regular(filename:join(From,File)) of
- true ->
- [{filename:join(To, File),
- filename:join(From,File)}|Acc];
- false ->
- io:format("Warning: File ~s/~s is missing~n",[From,File]),
- Acc
- end
- end,
- Expand = fun({Dir,Fs},Acc) ->
- expand_dirs(Dir,Fs,SrcD,Ver,List,Acc)
- end,
- Files = lists:foldl(Expand,[], All),
- ok = erl_tar:create(Ver ++ ".src.tar.gz", Files, [compressed]),
- BuiltDir = built_files(SrcD, create_release),
- BuiltFs = lists:foldl(Expand,[], BuiltDir),
- ok = erl_tar:create(Ver ++ ".built.tar.gz",
- Files ++ BuiltFs,
- [compressed]),
- ok;
- n ->
- usage()
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-is_ok(Str, Answers) ->
- {ok, [Ans]} = io:fread(Str, "~a"),
- case lists:member(Ans, Answers) of
- true -> Ans;
- false ->
- io:format("Please answer ~p~n",[Answers]),
- is_ok(Str,Answers)
- end.
-
-
-ensure_dir(To) ->
- case filelib:ensure_dir(filename:join(To, "dummy")) of
- ok -> ok;
- Error ->
- io:format("Error ~p in ~p ~n",[Error, To]),
- halt(1)
- end.
-
-get_version(Dir) ->
- %% Have we installed this from a release
- %% get the directory name
- DateVariant =
- fun() ->
- {_,Month,Day} = erlang:date(),
- Date = io_lib:format("~.2.0w~.2.0w",[Month,Day]),
- {ok, Bin} = file:read_file("vsn.mk"),
- Opt = [{capture, all_but_first, list}],
- case re:run(Bin, "WX_VSN\s*=\s*(.*)", Opt) of
- {match, [Ver]} ->
- lists:flatten([Ver,"."|Date]);
- _ ->
- lists:flatten(["wx-0.98."|Date])
- end
- end,
- case Dir of
- "." ->
- %% Installing from src without a release
- DateVariant();
- Dir ->
- Base = filename:basename(Dir),
- case string:tokens(Base, "-.") of
- ["wx", Ma, Mi|_]
- when is_integer(Ma),is_integer(Mi) ->
- Base;
- _ ->
- DateVariant()
- end
- end.
-
-%% Get src dir of installation
-get_src_dir() ->
- Escript = escript:script_name(),
- Abs = filename:dirname(filename:absname(Escript)),
- Test = filename:join(Abs, "README"),
- case file:read_file(Test) of
- {ok, _} -> ok;
- {error, enoent} ->
- io:format("Error couldn't read ~s ~n",[Test]),
- halt(1)
- end,
- Abs.
-
-
diff --git a/lib/wx/src/Makefile b/lib/wx/src/Makefile
index 46bc06271c..777fb7d998 100644
--- a/lib/wx/src/Makefile
+++ b/lib/wx/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2011. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
#
# The 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,7 +18,14 @@
#
include ../vsn.mk
-include ../config.mk
+ifdef TERTIARY_BOOTSTRAP
+ VSN = $(WX_VSN)
+ include $(ERL_TOP)/make/target.mk
+ include $(ERL_TOP)/make/$(TARGET)/otp.mk
+ RELSYSDIR = $(RELEASE_PATH)/lib/wx-$(VSN)
+else # Normal build
+ include ../config.mk
+endif
ESRC = .
EGEN = gen
@@ -65,7 +72,11 @@ APPUP_SRC = $(APPUP_FILE).src
APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
# Targets
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ifdef TERTIARY_BOOTSTRAP
+ opt: $(EBIN)/wx_object.beam
+else
+ debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+endif
clean:
rm -f $(TARGET_FILES)
@@ -107,19 +118,17 @@ $(EBIN)/%.beam: $(EGEN)/%.erl $(HEADER_FILES)
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
-ifeq ($(INSIDE_ERLSRC), true)
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)/src/gen
- $(INSTALL_DATA) $(GEN_HRL) $(GEN_FILES) $(RELSYSDIR)/src/gen
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXT_HRL) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src/gen"
+ $(INSTALL_DATA) $(GEN_HRL) $(GEN_FILES) "$(RELSYSDIR)/src/gen"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(EXT_HRL) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
# $(INSTALL_DATA) ../$(ARCHIVE) $(RELEASE_PATH)/lib
release_docs_spec:
-endif
diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl
index 0ebf51d28a..ff381683ee 100644
--- a/lib/wx/src/gen/gl.erl
+++ b/lib/wx/src/gen/gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +25,6 @@
%%
%% Booleans are represented by integers 0 and 1.
-%% @type mem(). memory block
-%% @type enum(). An integer defined in gl.hrl
-%% @type offset(). An integer which is an offset in an array
-%% @type clamp(). A float clamped between 0.0 - 1.0
-module(gl).
-compile(inline).
@@ -53,71 +49,75 @@
-define(GLsync,64/native-unsigned).
-define(GLuint64,64/native-unsigned).
-define(GLint64,64/native-signed).
--type clamp() :: float().
--type offset() :: non_neg_integer().
--type enum() :: non_neg_integer().
--type mem() :: binary() | tuple().
-
--export([accum/2,alphaFunc/2,areTexturesResident/1,arrayElement/1,'begin'/1,
- bindTexture/2,bitmap/7,blendFunc/2,callList/1,callLists/1,clear/1,clearAccum/4,
- clearColor/4,clearDepth/1,clearIndex/1,clearStencil/1,clipPlane/2,
- color3b/3,color3bv/1,color3d/3,color3dv/1,color3f/3,color3fv/1,color3i/3,
- color3iv/1,color3s/3,color3sv/1,color3ub/3,color3ubv/1,color3ui/3,color3uiv/1,
- color3us/3,color3usv/1,color4b/4,color4bv/1,color4d/4,color4dv/1,color4f/4,
- color4fv/1,color4i/4,color4iv/1,color4s/4,color4sv/1,color4ub/4,color4ubv/1,
- color4ui/4,color4uiv/1,color4us/4,color4usv/1,colorMask/4,colorMaterial/2,
- colorPointer/4,copyPixels/5,copyTexImage1D/7,copyTexImage2D/8,copyTexSubImage1D/6,
- copyTexSubImage2D/8,cullFace/1,deleteLists/2,deleteTextures/1,depthFunc/1,
- depthMask/1,depthRange/2,disable/1,disableClientState/1,drawArrays/3,
- drawBuffer/1,drawElements/4,drawPixels/5,edgeFlag/1,edgeFlagPointer/2,
- edgeFlagv/1,enable/1,enableClientState/1,'end'/0,endList/0,evalCoord1d/1,
- evalCoord1dv/1,evalCoord1f/1,evalCoord1fv/1,evalCoord2d/2,evalCoord2dv/1,
- evalCoord2f/2,evalCoord2fv/1,evalMesh1/3,evalMesh2/5,evalPoint1/1,
- evalPoint2/2,feedbackBuffer/3,finish/0,flush/0,fogf/2,fogfv/2,fogi/2,
- fogiv/2,frontFace/1,frustum/6,genLists/1,genTextures/1,getBooleanv/1,
- getClipPlane/1,getDoublev/1,getError/0,getFloatv/1,getIntegerv/1,getLightfv/2,
- getLightiv/2,getMapdv/3,getMapfv/3,getMapiv/3,getMaterialfv/2,getMaterialiv/2,
- getPixelMapfv/2,getPixelMapuiv/2,getPixelMapusv/2,getPolygonStipple/0,
- getString/1,getTexEnvfv/2,getTexEnviv/2,getTexGendv/2,getTexGenfv/2,
- getTexGeniv/2,getTexImage/5,getTexLevelParameterfv/3,getTexLevelParameteriv/3,
- getTexParameterfv/2,getTexParameteriv/2,hint/2,indexMask/1,indexPointer/3,
- indexd/1,indexdv/1,indexf/1,indexfv/1,indexi/1,indexiv/1,indexs/1,indexsv/1,
- indexub/1,indexubv/1,initNames/0,interleavedArrays/3,isEnabled/1,isList/1,
- isTexture/1,lightModelf/2,lightModelfv/2,lightModeli/2,lightModeliv/2,
- lightf/3,lightfv/3,lighti/3,lightiv/3,lineStipple/2,lineWidth/1,listBase/1,
- loadIdentity/0,loadMatrixd/1,loadMatrixf/1,loadName/1,logicOp/1,map1d/6,
- map1f/6,map2d/10,map2f/10,mapGrid1d/3,mapGrid1f/3,mapGrid2d/6,mapGrid2f/6,
- materialf/3,materialfv/3,materiali/3,materialiv/3,matrixMode/1,multMatrixd/1,
- multMatrixf/1,newList/2,normal3b/3,normal3bv/1,normal3d/3,normal3dv/1,
- normal3f/3,normal3fv/1,normal3i/3,normal3iv/1,normal3s/3,normal3sv/1,
- normalPointer/3,ortho/6,passThrough/1,pixelMapfv/3,pixelMapuiv/3,pixelMapusv/3,
- pixelStoref/2,pixelStorei/2,pixelTransferf/2,pixelTransferi/2,pixelZoom/2,
- pointSize/1,polygonMode/2,polygonOffset/2,polygonStipple/1,popAttrib/0,
- popClientAttrib/0,popMatrix/0,popName/0,prioritizeTextures/2,pushAttrib/1,
- pushClientAttrib/1,pushMatrix/0,pushName/1,rasterPos2d/2,rasterPos2dv/1,
- rasterPos2f/2,rasterPos2fv/1,rasterPos2i/2,rasterPos2iv/1,rasterPos2s/2,
- rasterPos2sv/1,rasterPos3d/3,rasterPos3dv/1,rasterPos3f/3,rasterPos3fv/1,
- rasterPos3i/3,rasterPos3iv/1,rasterPos3s/3,rasterPos3sv/1,rasterPos4d/4,
- rasterPos4dv/1,rasterPos4f/4,rasterPos4fv/1,rasterPos4i/4,rasterPos4iv/1,
- rasterPos4s/4,rasterPos4sv/1,readBuffer/1,readPixels/7,rectd/4,rectdv/2,
- rectf/4,rectfv/2,recti/4,rectiv/2,rects/4,rectsv/2,renderMode/1,rotated/4,
- rotatef/4,scaled/3,scalef/3,scissor/4,selectBuffer/2,shadeModel/1,stencilFunc/3,
- stencilMask/1,stencilOp/3,texCoord1d/1,texCoord1dv/1,texCoord1f/1,
- texCoord1fv/1,texCoord1i/1,texCoord1iv/1,texCoord1s/1,texCoord1sv/1,
- texCoord2d/2,texCoord2dv/1,texCoord2f/2,texCoord2fv/1,texCoord2i/2,
- texCoord2iv/1,texCoord2s/2,texCoord2sv/1,texCoord3d/3,texCoord3dv/1,
- texCoord3f/3,texCoord3fv/1,texCoord3i/3,texCoord3iv/1,texCoord3s/3,
- texCoord3sv/1,texCoord4d/4,texCoord4dv/1,texCoord4f/4,texCoord4fv/1,
- texCoord4i/4,texCoord4iv/1,texCoord4s/4,texCoord4sv/1,texCoordPointer/4,
- texEnvf/3,texEnvfv/3,texEnvi/3,texEnviv/3,texGend/3,texGendv/3,texGenf/3,
- texGenfv/3,texGeni/3,texGeniv/3,texImage1D/8,texImage2D/9,texParameterf/3,
- texParameterfv/3,texParameteri/3,texParameteriv/3,texSubImage1D/7,
- texSubImage2D/9,translated/3,translatef/3,vertex2d/2,vertex2dv/1,vertex2f/2,
- vertex2fv/1,vertex2i/2,vertex2iv/1,vertex2s/2,vertex2sv/1,vertex3d/3,
- vertex3dv/1,vertex3f/3,vertex3fv/1,vertex3i/3,vertex3iv/1,vertex3s/3,
- vertex3sv/1,vertex4d/4,vertex4dv/1,vertex4f/4,vertex4fv/1,vertex4i/4,
- vertex4iv/1,vertex4s/4,vertex4sv/1,vertexPointer/4,viewport/4,blendColor/4,
- blendEquation/1,drawRangeElements/6,texImage3D/10,texSubImage3D/11,
+-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl
+-type clamp() :: float(). %% 0.0..1.0
+-type offset() :: non_neg_integer(). %% Offset in memory block
+-type matrix() :: {float(),float(),float(),float(),
+ float(),float(),float(),float(),
+ float(),float(),float(),float(),
+ float(),float(),float(),float()}.
+-type mem() :: binary() | tuple(). %% Memory block
+
+-export([clearIndex/1,clearColor/4,clear/1,indexMask/1,colorMask/4,alphaFunc/2,
+ blendFunc/2,logicOp/1,cullFace/1,frontFace/1,pointSize/1,lineWidth/1,
+ lineStipple/2,polygonMode/2,polygonOffset/2,polygonStipple/1,getPolygonStipple/0,
+ edgeFlag/1,edgeFlagv/1,scissor/4,clipPlane/2,getClipPlane/1,drawBuffer/1,
+ readBuffer/1,enable/1,disable/1,isEnabled/1,enableClientState/1,disableClientState/1,
+ getBooleanv/1,getDoublev/1,getFloatv/1,getIntegerv/1,pushAttrib/1,
+ popAttrib/0,pushClientAttrib/1,popClientAttrib/0,renderMode/1,getError/0,
+ getString/1,finish/0,flush/0,hint/2,clearDepth/1,depthFunc/1,depthMask/1,
+ depthRange/2,clearAccum/4,accum/2,matrixMode/1,ortho/6,frustum/6,viewport/4,
+ pushMatrix/0,popMatrix/0,loadIdentity/0,loadMatrixd/1,loadMatrixf/1,
+ multMatrixd/1,multMatrixf/1,rotated/4,rotatef/4,scaled/3,scalef/3,translated/3,
+ translatef/3,isList/1,deleteLists/2,genLists/1,newList/2,endList/0,
+ callList/1,callLists/1,listBase/1,'begin'/1,'end'/0,vertex2d/2,vertex2f/2,
+ vertex2i/2,vertex2s/2,vertex3d/3,vertex3f/3,vertex3i/3,vertex3s/3,vertex4d/4,
+ vertex4f/4,vertex4i/4,vertex4s/4,vertex2dv/1,vertex2fv/1,vertex2iv/1,
+ vertex2sv/1,vertex3dv/1,vertex3fv/1,vertex3iv/1,vertex3sv/1,vertex4dv/1,
+ vertex4fv/1,vertex4iv/1,vertex4sv/1,normal3b/3,normal3d/3,normal3f/3,
+ normal3i/3,normal3s/3,normal3bv/1,normal3dv/1,normal3fv/1,normal3iv/1,
+ normal3sv/1,indexd/1,indexf/1,indexi/1,indexs/1,indexub/1,indexdv/1,
+ indexfv/1,indexiv/1,indexsv/1,indexubv/1,color3b/3,color3d/3,color3f/3,
+ color3i/3,color3s/3,color3ub/3,color3ui/3,color3us/3,color4b/4,color4d/4,
+ color4f/4,color4i/4,color4s/4,color4ub/4,color4ui/4,color4us/4,color3bv/1,
+ color3dv/1,color3fv/1,color3iv/1,color3sv/1,color3ubv/1,color3uiv/1,
+ color3usv/1,color4bv/1,color4dv/1,color4fv/1,color4iv/1,color4sv/1,
+ color4ubv/1,color4uiv/1,color4usv/1,texCoord1d/1,texCoord1f/1,texCoord1i/1,
+ texCoord1s/1,texCoord2d/2,texCoord2f/2,texCoord2i/2,texCoord2s/2,texCoord3d/3,
+ texCoord3f/3,texCoord3i/3,texCoord3s/3,texCoord4d/4,texCoord4f/4,texCoord4i/4,
+ texCoord4s/4,texCoord1dv/1,texCoord1fv/1,texCoord1iv/1,texCoord1sv/1,
+ texCoord2dv/1,texCoord2fv/1,texCoord2iv/1,texCoord2sv/1,texCoord3dv/1,
+ texCoord3fv/1,texCoord3iv/1,texCoord3sv/1,texCoord4dv/1,texCoord4fv/1,
+ texCoord4iv/1,texCoord4sv/1,rasterPos2d/2,rasterPos2f/2,rasterPos2i/2,
+ rasterPos2s/2,rasterPos3d/3,rasterPos3f/3,rasterPos3i/3,rasterPos3s/3,
+ rasterPos4d/4,rasterPos4f/4,rasterPos4i/4,rasterPos4s/4,rasterPos2dv/1,
+ rasterPos2fv/1,rasterPos2iv/1,rasterPos2sv/1,rasterPos3dv/1,rasterPos3fv/1,
+ rasterPos3iv/1,rasterPos3sv/1,rasterPos4dv/1,rasterPos4fv/1,rasterPos4iv/1,
+ rasterPos4sv/1,rectd/4,rectf/4,recti/4,rects/4,rectdv/2,rectfv/2,rectiv/2,
+ rectsv/2,vertexPointer/4,normalPointer/3,colorPointer/4,indexPointer/3,
+ texCoordPointer/4,edgeFlagPointer/2,arrayElement/1,drawArrays/3,drawElements/4,
+ interleavedArrays/3,shadeModel/1,lightf/3,lighti/3,lightfv/3,lightiv/3,
+ getLightfv/2,getLightiv/2,lightModelf/2,lightModeli/2,lightModelfv/2,
+ lightModeliv/2,materialf/3,materiali/3,materialfv/3,materialiv/3,getMaterialfv/2,
+ getMaterialiv/2,colorMaterial/2,pixelZoom/2,pixelStoref/2,pixelStorei/2,
+ pixelTransferf/2,pixelTransferi/2,pixelMapfv/3,pixelMapuiv/3,pixelMapusv/3,
+ getPixelMapfv/2,getPixelMapuiv/2,getPixelMapusv/2,bitmap/7,readPixels/7,
+ drawPixels/5,copyPixels/5,stencilFunc/3,stencilMask/1,stencilOp/3,
+ clearStencil/1,texGend/3,texGenf/3,texGeni/3,texGendv/3,texGenfv/3,
+ texGeniv/3,getTexGendv/2,getTexGenfv/2,getTexGeniv/2,texEnvf/3,texEnvi/3,
+ texEnvfv/3,texEnviv/3,getTexEnvfv/2,getTexEnviv/2,texParameterf/3,
+ texParameteri/3,texParameterfv/3,texParameteriv/3,getTexParameterfv/2,
+ getTexParameteriv/2,getTexLevelParameterfv/3,getTexLevelParameteriv/3,
+ texImage1D/8,texImage2D/9,getTexImage/5,genTextures/1,deleteTextures/1,
+ bindTexture/2,prioritizeTextures/2,areTexturesResident/1,isTexture/1,
+ texSubImage1D/7,texSubImage2D/9,copyTexImage1D/7,copyTexImage2D/8,
+ copyTexSubImage1D/6,copyTexSubImage2D/8,map1d/6,map1f/6,map2d/10,map2f/10,
+ getMapdv/3,getMapfv/3,getMapiv/3,evalCoord1d/1,evalCoord1f/1,evalCoord1dv/1,
+ evalCoord1fv/1,evalCoord2d/2,evalCoord2f/2,evalCoord2dv/1,evalCoord2fv/1,
+ mapGrid1d/3,mapGrid1f/3,mapGrid2d/6,mapGrid2f/6,evalPoint1/1,evalPoint2/2,
+ evalMesh1/3,evalMesh2/5,fogf/2,fogi/2,fogfv/2,fogiv/2,feedbackBuffer/3,
+ passThrough/1,selectBuffer/2,initNames/0,loadName/1,pushName/1,popName/0,
+ blendColor/4,blendEquation/1,drawRangeElements/6,texImage3D/10,texSubImage3D/11,
copyTexSubImage3D/9,colorTable/6,colorTableParameterfv/3,colorTableParameteriv/3,
copyColorTable/5,getColorTable/4,getColorTableParameterfv/2,getColorTableParameteriv/2,
colorSubTable/6,copyColorSubTable/5,convolutionFilter1D/6,convolutionFilter2D/7,
@@ -267,9 +267,10 @@
viewportIndexedfv/2,scissorArrayv/2,scissorIndexed/5,scissorIndexedv/2,
depthRangeArrayv/2,depthRangeIndexed/3,getFloati_v/2,getDoublei_v/2,
debugMessageControlARB/5,debugMessageInsertARB/5,getDebugMessageLogARB/2,
- getGraphicsResetStatusARB/0,resizeBuffersMESA/0,windowPos4dMESA/4,
- windowPos4dvMESA/1,windowPos4fMESA/4,windowPos4fvMESA/1,windowPos4iMESA/4,
- windowPos4ivMESA/1,windowPos4sMESA/4,windowPos4svMESA/1,depthBoundsEXT/2,
+ getGraphicsResetStatusARB/0,drawArraysInstancedBaseInstance/5,drawElementsInstancedBaseInstance/6,
+ drawElementsInstancedBaseVertexBaseInstance/7,drawTransformFeedbackInstanced/3,
+ drawTransformFeedbackStreamInstanced/4,getInternalformativ/4,bindImageTexture/7,
+ memoryBarrier/1,texStorage1D/4,texStorage2D/5,texStorage3D/6,depthBoundsEXT/2,
stencilClearTagEXT/2]).
-export([call/2, cast/2, send_bin/1]).
@@ -306,2215 +307,8470 @@ send_bin(Tuple) when is_tuple(Tuple) ->
%% API
-%% @spec (Op::enum(),Value::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAccum.xml">external</a> documentation.
--spec accum(enum(),float()) -> ok.
-accum(Op,Value) ->
- cast(5037, <<Op:?GLenum,Value:?GLfloat>>).
-
-%% @spec (Func::enum(),Ref::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAlphaFunc.xml">external</a> documentation.
--spec alphaFunc(enum(),clamp()) -> ok.
-alphaFunc(Func,Ref) ->
- cast(5038, <<Func:?GLenum,Ref:?GLclampf>>).
+%% @doc Specify the clear value for the color index buffers
+%%
+%% ``gl:clearIndex'' specifies the index used by {@link gl:clear/1} to clear the color index
+%% buffers. `C' is not clamped. Rather, `C' is converted to a fixed-point value
+%% with unspecified precision to the right of the binary point. The integer part of this
+%% value is then masked with 2 m-1, where m is the number of bits in a color index stored
+%% in the frame buffer.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearIndex.xml">external</a> documentation.
+-spec clearIndex(C) -> ok when C :: float().
+clearIndex(C) ->
+ cast(5037, <<C:?GLfloat>>).
-%% @spec (Textures::[integer()]) -> {0|1,Residences::[0|1]}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAreTexturesResident.xml">external</a> documentation.
--spec areTexturesResident([integer()]) -> {0|1,[0|1]}.
-areTexturesResident(Textures) ->
- call(5039, <<(length(Textures)):?GLuint,
- (<< <<C:?GLuint>> || C <- Textures>>)/binary,0:(((1+length(Textures)) rem 2)*32)>>).
+%% @doc Specify clear values for the color buffers
+%%
+%% ``gl:clearColor'' specifies the red, green, blue, and alpha values used by {@link gl:clear/1}
+%% to clear the color buffers. Values specified by ``gl:clearColor'' are clamped to the
+%% range [0 1].
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml">external</a> documentation.
+-spec clearColor(Red, Green, Blue, Alpha) -> ok when Red :: clamp(),Green :: clamp(),Blue :: clamp(),Alpha :: clamp().
+clearColor(Red,Green,Blue,Alpha) ->
+ cast(5038, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>).
-%% @spec (I::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glArrayElement.xml">external</a> documentation.
--spec arrayElement(integer()) -> ok.
-arrayElement(I) ->
- cast(5040, <<I:?GLint>>).
+%% @doc Clear buffers to preset values
+%%
+%% ``gl:clear'' sets the bitplane area of the window to values previously selected by ``gl:clearColor''
+%% , ``gl:clearDepth'', and ``gl:clearStencil''. Multiple color buffers can be cleared
+%% simultaneously by selecting more than one buffer at a time using {@link gl:drawBuffer/1} .
+%%
+%% The pixel ownership test, the scissor test, dithering, and the buffer writemasks affect
+%% the operation of ``gl:clear''. The scissor box bounds the cleared region. Alpha function,
+%% blend function, logical operation, stenciling, texture mapping, and depth-buffering are
+%% ignored by ``gl:clear''.
+%%
+%% ``gl:clear'' takes a single argument that is the bitwise OR of several values indicating
+%% which buffer is to be cleared.
+%%
+%% The values are as follows:
+%%
+%% `?GL_COLOR_BUFFER_BIT': Indicates the buffers currently enabled for color writing.
+%%
+%% `?GL_DEPTH_BUFFER_BIT': Indicates the depth buffer.
+%%
+%% `?GL_STENCIL_BUFFER_BIT': Indicates the stencil buffer.
+%%
+%% The value to which each buffer is cleared depends on the setting of the clear value for
+%% that buffer.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml">external</a> documentation.
+-spec clear(Mask) -> ok when Mask :: integer().
+clear(Mask) ->
+ cast(5039, <<Mask:?GLbitfield>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml">external</a> documentation.
--spec 'begin'(enum()) -> ok.
-'begin'(Mode) ->
- cast(5041, <<Mode:?GLenum>>).
+%% @doc Control the writing of individual bits in the color index buffers
+%%
+%% ``gl:indexMask'' controls the writing of individual bits in the color index buffers.
+%% The least significant n bits of `Mask' , where n is the number of bits in a color
+%% index buffer, specify a mask. Where a 1 (one) appears in the mask, it's possible to write
+%% to the corresponding bit in the color index buffer (or buffers). Where a 0 (zero) appears,
+%% the corresponding bit is write-protected.
+%%
+%% This mask is used only in color index mode, and it affects only the buffers currently
+%% selected for writing (see {@link gl:drawBuffer/1} ). Initially, all bits are enabled for
+%% writing.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexMask.xml">external</a> documentation.
+-spec indexMask(Mask) -> ok when Mask :: integer().
+indexMask(Mask) ->
+ cast(5040, <<Mask:?GLuint>>).
-%% @spec (Target::enum(),Texture::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTexture.xml">external</a> documentation.
--spec bindTexture(enum(),integer()) -> ok.
-bindTexture(Target,Texture) ->
- cast(5042, <<Target:?GLenum,Texture:?GLuint>>).
+%% @doc Enable and disable writing of frame buffer color components
+%%
+%% ``gl:colorMask'' and ``gl:colorMaski'' specify whether the individual color components
+%% in the frame buffer can or cannot be written. ``gl:colorMaski'' sets the mask for a
+%% specific draw buffer, whereas ``gl:colorMask'' sets the mask for all draw buffers. If `Red'
+%% is `?GL_FALSE', for example, no change is made to the red component of any pixel
+%% in any of the color buffers, regardless of the drawing operation attempted.
+%%
+%% Changes to individual bits of components cannot be controlled. Rather, changes are either
+%% enabled or disabled for entire color components.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml">external</a> documentation.
+-spec colorMask(Red, Green, Blue, Alpha) -> ok when Red :: 0|1,Green :: 0|1,Blue :: 0|1,Alpha :: 0|1.
+colorMask(Red,Green,Blue,Alpha) ->
+ cast(5041, <<Red:?GLboolean,Green:?GLboolean,Blue:?GLboolean,Alpha:?GLboolean>>).
-%% @spec (Width::integer(),Height::integer(),Xorig::float(),Yorig::float(),Xmove::float(),Ymove::float(),Bitmap::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml">external</a> documentation.
--spec bitmap(integer(),integer(),float(),float(),float(),float(),offset()|mem()) -> ok.
-bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) when is_integer(Bitmap) ->
- cast(5043, <<Width:?GLsizei,Height:?GLsizei,Xorig:?GLfloat,Yorig:?GLfloat,Xmove:?GLfloat,Ymove:?GLfloat,Bitmap:?GLuint>>);
-bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) ->
- send_bin(Bitmap),
- cast(5044, <<Width:?GLsizei,Height:?GLsizei,Xorig:?GLfloat,Yorig:?GLfloat,Xmove:?GLfloat,Ymove:?GLfloat>>).
+%% @doc Specify the alpha test function
+%%
+%% The alpha test discards fragments depending on the outcome of a comparison between an
+%% incoming fragment's alpha value and a constant reference value. ``gl:alphaFunc'' specifies
+%% the reference value and the comparison function. The comparison is performed only if alpha
+%% testing is enabled. By default, it is not enabled. (See {@link gl:enable/1} and {@link gl:enable/1}
+%% of `?GL_ALPHA_TEST'.)
+%%
+%% `Func' and `Ref' specify the conditions under which the pixel is drawn. The
+%% incoming alpha value is compared to `Ref' using the function specified by `Func' .
+%% If the value passes the comparison, the incoming fragment is drawn if it also passes subsequent
+%% stencil and depth buffer tests. If the value fails the comparison, no change is made to
+%% the frame buffer at that pixel location. The comparison functions are as follows:
+%%
+%% `?GL_NEVER': Never passes.
+%%
+%% `?GL_LESS': Passes if the incoming alpha value is less than the reference value.
+%%
+%% `?GL_EQUAL': Passes if the incoming alpha value is equal to the reference value.
+%%
+%% `?GL_LEQUAL': Passes if the incoming alpha value is less than or equal to the reference
+%% value.
+%%
+%% `?GL_GREATER': Passes if the incoming alpha value is greater than the reference
+%% value.
+%%
+%% `?GL_NOTEQUAL': Passes if the incoming alpha value is not equal to the reference
+%% value.
+%%
+%% `?GL_GEQUAL': Passes if the incoming alpha value is greater than or equal to the
+%% reference value.
+%%
+%% `?GL_ALWAYS': Always passes (initial value).
+%%
+%% ``gl:alphaFunc'' operates on all pixel write operations, including those resulting from
+%% the scan conversion of points, lines, polygons, and bitmaps, and from pixel draw and copy
+%% operations. ``gl:alphaFunc'' does not affect screen clear operations.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAlphaFunc.xml">external</a> documentation.
+-spec alphaFunc(Func, Ref) -> ok when Func :: enum(),Ref :: clamp().
+alphaFunc(Func,Ref) ->
+ cast(5042, <<Func:?GLenum,Ref:?GLclampf>>).
-%% @spec (Sfactor::enum(),Dfactor::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml">external</a> documentation.
--spec blendFunc(enum(),enum()) -> ok.
+%% @doc Specify pixel arithmetic
+%%
+%% Pixels can be drawn using a function that blends the incoming (source) RGBA values with
+%% the RGBA values that are already in the frame buffer (the destination values). Blending
+%% is initially disabled. Use {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_BLEND'
+%% to enable and disable blending.
+%%
+%% ``gl:blendFunc'' defines the operation of blending for all draw buffers when it is enabled.
+%% ``gl:blendFunci'' defines the operation of blending for a single draw buffer specified
+%% by `Buf' when enabled for that draw buffer. `Sfactor' specifies which method
+%% is used to scale the source color components. `Dfactor' specifies which method is
+%% used to scale the destination color components. Both parameters must be one of the following
+%% symbolic constants: `?GL_ZERO', `?GL_ONE', `?GL_SRC_COLOR', `?GL_ONE_MINUS_SRC_COLOR'
+%% , `?GL_DST_COLOR', `?GL_ONE_MINUS_DST_COLOR', `?GL_SRC_ALPHA', `?GL_ONE_MINUS_SRC_ALPHA'
+%% , `?GL_DST_ALPHA', `?GL_ONE_MINUS_DST_ALPHA', `?GL_CONSTANT_COLOR', `?GL_ONE_MINUS_CONSTANT_COLOR'
+%% , `?GL_CONSTANT_ALPHA', `?GL_ONE_MINUS_CONSTANT_ALPHA', `?GL_SRC_ALPHA_SATURATE'
+%% , `?GL_SRC1_COLOR', `?GL_ONE_MINUS_SRC1_COLOR', `?GL_SRC1_ALPHA', and `?GL_ONE_MINUS_SRC1_ALPHA'
+%% . The possible methods are described in the following table. Each method defines four
+%% scale factors, one each for red, green, blue, and alpha. In the table and in subsequent
+%% equations, first source, second source and destination color components are referred to
+%% as (R s0 G s0 B s0 A s0), (R s1 G s1 B s1 A s1) and (R d G d B d A d), respectively. The color specified by {@link gl:blendColor/4} is referred to
+%% as (R c G c B c A c). They are understood to have integer values between 0 and (k R k G k B k A), where
+%%
+%% k c= 2(m c)-1
+%%
+%% and (m R m G m B m A) is the number of red, green, blue, and alpha bitplanes.
+%%
+%% Source and destination scale factors are referred to as (s R s G s B s A) and (d R d G d B d A). The scale factors described
+%% in the table, denoted (f R f G f B f A), represent either source or destination factors. All scale factors
+%% have range [0 1].
+%%
+%% <table><tbody><tr><td>` Parameter '</td><td>(f R f G f B f A)</td></tr></tbody><tbody><tr><td>`?GL_ZERO'
+%% </td><td>(0 0 0 0)</td></tr><tr><td>`?GL_ONE'</td><td>(1 1 1 1)</td></tr><tr><td>`?GL_SRC_COLOR'</td>
+%% <td>(R s0 k/R G s0 k/G B s0 k/B A s0 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td>(1 1 1 1)-(R s0 k/R G s0 k/G B s0 k/B
+%% A s0 k/A)</td></tr><tr><td>`?GL_DST_COLOR'
+%% </td><td>(R d k/R G d k/G B d k/B A d k/A)</td></tr><tr><td>`?GL_ONE_MINUS_DST_COLOR'</td><td>(1 1 1 1)-(R d k/R G d k/G B d k/B
+%% A d k/A)</td></tr><tr><td>`?GL_SRC_ALPHA'
+%% </td><td>(A s0 k/A A s0 k/A A s0 k/A A s0 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1 1)-(A s0 k/A A s0 k/A A s0
+%% k/A A s0 k/A)</td></tr><tr><td>`?GL_DST_ALPHA'
+%% </td><td>(A d k/A A d k/A A d k/A A d k/A)</td></tr><tr><td>`?GL_ONE_MINUS_DST_ALPHA'</td><td>(1 1 1 1)-(A d k/A A d k/A A d k/A
+%% A d k/A)</td></tr><tr><td>`?GL_CONSTANT_COLOR'
+%% </td><td>(R c G c B c A c)</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_COLOR'</td><td>(1 1 1 1)-(R c G c B c A c)</td></tr><tr><td>
+%% `?GL_CONSTANT_ALPHA'</td><td>(A c A c A c A c)</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_ALPHA'</td>
+%% <td>(1 1 1 1)-(A c A c A c A c)</td></tr><tr><td>`?GL_SRC_ALPHA_SATURATE'</td><td>(i i i 1)</td></tr><tr><td>`?GL_SRC1_COLOR'
+%% </td><td>(R s1 k/R G s1 k/G B s1 k/B A s1 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC1_COLOR'</td><td>(1 1 1 1)-(R s1 k/R G s1 k/G B
+%% s1 k/B A s1 k/A)</td></tr><tr><td>`?GL_SRC1_ALPHA'
+%% </td><td>(A s1 k/A A s1 k/A A s1 k/A A s1 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC1_ALPHA'</td><td>(1 1 1 1)-(A s1 k/A A s1 k/A A
+%% s1 k/A A s1 k/A)</td></tr></tbody></table>
+%%
+%%
+%% In the table,
+%%
+%% i= min(A s k A-A d) k/A
+%%
+%% To determine the blended RGBA values of a pixel, the system uses the following equations:
+%%
+%%
+%% R d= min(k R R s s R+R d d R) G d= min(k G G s s G+G d d G) B d= min(k B B s s B+B d d B) A d= min(k A A s s A+A d d A)
+%%
+%% Despite the apparent precision of the above equations, blending arithmetic is not exactly
+%% specified, because blending operates with imprecise integer color values. However, a blend
+%% factor that should be equal to 1 is guaranteed not to modify its multiplicand, and a blend
+%% factor equal to 0 reduces its multiplicand to 0. For example, when `Sfactor' is `?GL_SRC_ALPHA'
+%% , `Dfactor' is `?GL_ONE_MINUS_SRC_ALPHA', and A s is equal to k A, the equations
+%% reduce to simple replacement:
+%%
+%% R d= R s G d= G s B d= B s A d= A s
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml">external</a> documentation.
+-spec blendFunc(Sfactor, Dfactor) -> ok when Sfactor :: enum(),Dfactor :: enum().
blendFunc(Sfactor,Dfactor) ->
- cast(5045, <<Sfactor:?GLenum,Dfactor:?GLenum>>).
+ cast(5043, <<Sfactor:?GLenum,Dfactor:?GLenum>>).
-%% @spec (List::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallList.xml">external</a> documentation.
--spec callList(integer()) -> ok.
-callList(List) ->
- cast(5046, <<List:?GLuint>>).
-
-%% @spec (Lists::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallLists.xml">external</a> documentation.
--spec callLists([integer()]) -> ok.
-callLists(Lists) ->
- cast(5047, <<(length(Lists)):?GLuint,
- (<< <<C:?GLuint>> || C <- Lists>>)/binary,0:(((1+length(Lists)) rem 2)*32)>>).
+%% @doc Specify a logical pixel operation for rendering
+%%
+%% ``gl:logicOp'' specifies a logical operation that, when enabled, is applied between
+%% the incoming RGBA color and the RGBA color at the corresponding location in the frame
+%% buffer. To enable or disable the logical operation, call {@link gl:enable/1} and {@link gl:enable/1}
+%% using the symbolic constant `?GL_COLOR_LOGIC_OP'. The initial value is disabled.
+%%
+%% <table><tbody><tr><td>` Opcode '</td><td>` Resulting Operation '</td></tr></tbody>
+%% <tbody><tr><td>`?GL_CLEAR'</td><td> 0 </td></tr><tr><td>`?GL_SET'</td><td> 1 </td>
+%% </tr><tr><td>`?GL_COPY'</td><td> s </td></tr><tr><td>`?GL_COPY_INVERTED'</td><td>
+%% ~s </td></tr><tr><td>`?GL_NOOP'</td><td> d </td></tr><tr><td>`?GL_INVERT'</td><td>
+%% ~d </td></tr><tr><td>`?GL_AND'</td><td> s &amp; d </td></tr><tr><td>`?GL_NAND'</td>
+%% <td> ~(s &amp; d) </td></tr><tr><td>`?GL_OR'</td><td> s | d </td></tr><tr><td>`?GL_NOR'
+%% </td><td> ~(s | d) </td></tr><tr><td>`?GL_XOR'</td><td> s ^ d </td></tr><tr><td>`?GL_EQUIV'
+%% </td><td> ~(s ^ d) </td></tr><tr><td>`?GL_AND_REVERSE'</td><td> s &amp; ~d </td></tr>
+%% <tr><td>`?GL_AND_INVERTED'</td><td> ~s &amp; d </td></tr><tr><td>`?GL_OR_REVERSE'
+%% </td><td> s | ~d </td></tr><tr><td>`?GL_OR_INVERTED'</td><td> ~s | d </td></tr></tbody>
+%% </table>
+%%
+%% `Opcode' is a symbolic constant chosen from the list above. In the explanation of
+%% the logical operations, `s' represents the incoming color and `d' represents
+%% the color in the frame buffer. Standard C-language operators are used. As these bitwise
+%% operators suggest, the logical operation is applied independently to each bit pair of
+%% the source and destination colors.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml">external</a> documentation.
+-spec logicOp(Opcode) -> ok when Opcode :: enum().
+logicOp(Opcode) ->
+ cast(5044, <<Opcode:?GLenum>>).
-%% @spec (Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml">external</a> documentation.
--spec clear(integer()) -> ok.
-clear(Mask) ->
- cast(5048, <<Mask:?GLbitfield>>).
+%% @doc Specify whether front- or back-facing facets can be culled
+%%
+%% ``gl:cullFace'' specifies whether front- or back-facing facets are culled (as specified
+%% by `mode') when facet culling is enabled. Facet culling is initially disabled. To
+%% enable and disable facet culling, call the {@link gl:enable/1} and {@link gl:enable/1}
+%% commands with the argument `?GL_CULL_FACE'. Facets include triangles, quadrilaterals,
+%% polygons, and rectangles.
+%%
+%% {@link gl:frontFace/1} specifies which of the clockwise and counterclockwise facets are
+%% front-facing and back-facing. See {@link gl:frontFace/1} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml">external</a> documentation.
+-spec cullFace(Mode) -> ok when Mode :: enum().
+cullFace(Mode) ->
+ cast(5045, <<Mode:?GLenum>>).
-%% @spec (Red::float(),Green::float(),Blue::float(),Alpha::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearAccum.xml">external</a> documentation.
--spec clearAccum(float(),float(),float(),float()) -> ok.
-clearAccum(Red,Green,Blue,Alpha) ->
- cast(5049, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat,Alpha:?GLfloat>>).
+%% @doc Define front- and back-facing polygons
+%%
+%% In a scene composed entirely of opaque closed surfaces, back-facing polygons are never
+%% visible. Eliminating these invisible polygons has the obvious benefit of speeding up the
+%% rendering of the image. To enable and disable elimination of back-facing polygons, call {@link gl:enable/1}
+%% and {@link gl:enable/1} with argument `?GL_CULL_FACE'.
+%%
+%% The projection of a polygon to window coordinates is said to have clockwise winding if
+%% an imaginary object following the path from its first vertex, its second vertex, and so
+%% on, to its last vertex, and finally back to its first vertex, moves in a clockwise direction
+%% about the interior of the polygon. The polygon's winding is said to be counterclockwise
+%% if the imaginary object following the same path moves in a counterclockwise direction
+%% about the interior of the polygon. ``gl:frontFace'' specifies whether polygons with
+%% clockwise winding in window coordinates, or counterclockwise winding in window coordinates,
+%% are taken to be front-facing. Passing `?GL_CCW' to `Mode' selects counterclockwise
+%% polygons as front-facing; `?GL_CW' selects clockwise polygons as front-facing. By
+%% default, counterclockwise polygons are taken to be front-facing.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml">external</a> documentation.
+-spec frontFace(Mode) -> ok when Mode :: enum().
+frontFace(Mode) ->
+ cast(5046, <<Mode:?GLenum>>).
-%% @spec (Red::clamp(),Green::clamp(),Blue::clamp(),Alpha::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml">external</a> documentation.
--spec clearColor(clamp(),clamp(),clamp(),clamp()) -> ok.
-clearColor(Red,Green,Blue,Alpha) ->
- cast(5050, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>).
+%% @doc Specify the diameter of rasterized points
+%%
+%% ``gl:pointSize'' specifies the rasterized diameter of points. If point size mode is
+%% disabled (see {@link gl:enable/1} with parameter `?GL_PROGRAM_POINT_SIZE'), this value
+%% will be used to rasterize points. Otherwise, the value written to the shading language
+%% built-in variable gl_PointSize will be used.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml">external</a> documentation.
+-spec pointSize(Size) -> ok when Size :: float().
+pointSize(Size) ->
+ cast(5047, <<Size:?GLfloat>>).
-%% @spec (Depth::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepth.xml">external</a> documentation.
--spec clearDepth(clamp()) -> ok.
-clearDepth(Depth) ->
- cast(5051, <<Depth:?GLclampd>>).
+%% @doc Specify the width of rasterized lines
+%%
+%% ``gl:lineWidth'' specifies the rasterized width of both aliased and antialiased lines.
+%% Using a line width other than 1 has different effects, depending on whether line antialiasing
+%% is enabled. To enable and disable line antialiasing, call {@link gl:enable/1} and {@link gl:enable/1}
+%% with argument `?GL_LINE_SMOOTH'. Line antialiasing is initially disabled.
+%%
+%% If line antialiasing is disabled, the actual width is determined by rounding the supplied
+%% width to the nearest integer. (If the rounding results in the value 0, it is as if the
+%% line width were 1.) If |&amp;Delta; x|&gt;=|&amp;Delta; y|, `i' pixels are filled in each column that is rasterized,
+%% where `i' is the rounded value of `Width' . Otherwise, `i' pixels are filled
+%% in each row that is rasterized.
+%%
+%% If antialiasing is enabled, line rasterization produces a fragment for each pixel square
+%% that intersects the region lying within the rectangle having width equal to the current
+%% line width, length equal to the actual length of the line, and centered on the mathematical
+%% line segment. The coverage value for each fragment is the window coordinate area of the
+%% intersection of the rectangular region with the corresponding pixel square. This value
+%% is saved and used in the final rasterization step.
+%%
+%% Not all widths can be supported when line antialiasing is enabled. If an unsupported
+%% width is requested, the nearest supported width is used. Only width 1 is guaranteed to
+%% be supported; others depend on the implementation. Likewise, there is a range for aliased
+%% line widths as well. To query the range of supported widths and the size difference between
+%% supported widths within the range, call {@link gl:getBooleanv/1} with arguments `?GL_ALIASED_LINE_WIDTH_RANGE'
+%% , `?GL_SMOOTH_LINE_WIDTH_RANGE', and `?GL_SMOOTH_LINE_WIDTH_GRANULARITY'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml">external</a> documentation.
+-spec lineWidth(Width) -> ok when Width :: float().
+lineWidth(Width) ->
+ cast(5048, <<Width:?GLfloat>>).
-%% @spec (C::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearIndex.xml">external</a> documentation.
--spec clearIndex(float()) -> ok.
-clearIndex(C) ->
- cast(5052, <<C:?GLfloat>>).
+%% @doc Specify the line stipple pattern
+%%
+%% Line stippling masks out certain fragments produced by rasterization; those fragments
+%% will not be drawn. The masking is achieved by using three parameters: the 16-bit line
+%% stipple pattern `Pattern' , the repeat count `Factor' , and an integer stipple
+%% counter s.
+%%
+%% Counter s is reset to 0 whenever {@link gl:'begin'/1} is called and before each line segment
+%% of a {@link gl:'begin'/1} (`?GL_LINES')/ {@link gl:'begin'/1} sequence is generated. It is
+%% incremented after each fragment of a unit width aliased line segment is generated or after
+%% each i fragments of an i width line segment are generated. The i fragments associated
+%% with count s are masked out if
+%%
+%% `Pattern' bit (s/factor)% 16
+%%
+%% is 0, otherwise these fragments are sent to the frame buffer. Bit zero of `Pattern'
+%% is the least significant bit.
+%%
+%% Antialiased lines are treated as a sequence of 1*width rectangles for purposes of stippling.
+%% Whether rectangle s is rasterized or not depends on the fragment rule described for
+%% aliased lines, counting rectangles rather than groups of fragments.
+%%
+%% To enable and disable line stippling, call {@link gl:enable/1} and {@link gl:enable/1}
+%% with argument `?GL_LINE_STIPPLE'. When enabled, the line stipple pattern is applied
+%% as described above. When disabled, it is as if the pattern were all 1's. Initially, line
+%% stippling is disabled.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineStipple.xml">external</a> documentation.
+-spec lineStipple(Factor, Pattern) -> ok when Factor :: integer(),Pattern :: integer().
+lineStipple(Factor,Pattern) ->
+ cast(5049, <<Factor:?GLint,Pattern:?GLushort>>).
-%% @spec (S::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearStencil.xml">external</a> documentation.
--spec clearStencil(integer()) -> ok.
-clearStencil(S) ->
- cast(5053, <<S:?GLint>>).
+%% @doc Select a polygon rasterization mode
+%%
+%% ``gl:polygonMode'' controls the interpretation of polygons for rasterization. `Face'
+%% describes which polygons `Mode' applies to: both front and back-facing polygons (`?GL_FRONT_AND_BACK'
+%% ). The polygon mode affects only the final rasterization of polygons. In particular, a
+%% polygon's vertices are lit and the polygon is clipped and possibly culled before these
+%% modes are applied.
+%%
+%% Three modes are defined and can be specified in `Mode' :
+%%
+%% `?GL_POINT': Polygon vertices that are marked as the start of a boundary edge are
+%% drawn as points. Point attributes such as `?GL_POINT_SIZE' and `?GL_POINT_SMOOTH'
+%% control the rasterization of the points. Polygon rasterization attributes other than `?GL_POLYGON_MODE'
+%% have no effect.
+%%
+%% `?GL_LINE': Boundary edges of the polygon are drawn as line segments. Line attributes
+%% such as `?GL_LINE_WIDTH' and `?GL_LINE_SMOOTH' control the rasterization of
+%% the lines. Polygon rasterization attributes other than `?GL_POLYGON_MODE' have no
+%% effect.
+%%
+%% `?GL_FILL': The interior of the polygon is filled. Polygon attributes such as `?GL_POLYGON_SMOOTH'
+%% control the rasterization of the polygon.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml">external</a> documentation.
+-spec polygonMode(Face, Mode) -> ok when Face :: enum(),Mode :: enum().
+polygonMode(Face,Mode) ->
+ cast(5050, <<Face:?GLenum,Mode:?GLenum>>).
-%% @spec (Plane::enum(),Equation::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClipPlane.xml">external</a> documentation.
--spec clipPlane(enum(),{float(),float(),float(),float()}) -> ok.
-clipPlane(Plane,{E1,E2,E3,E4}) ->
- cast(5054, <<Plane:?GLenum,0:32,E1:?GLdouble,E2:?GLdouble,E3:?GLdouble,E4:?GLdouble>>).
+%% @doc Set the scale and units used to calculate depth values
+%%
+%% When `?GL_POLYGON_OFFSET_FILL', `?GL_POLYGON_OFFSET_LINE', or `?GL_POLYGON_OFFSET_POINT'
+%% is enabled, each fragment's `depth' value will be offset after it is interpolated
+%% from the `depth' values of the appropriate vertices. The value of the offset is
+%% factor*DZ+r*units, where DZ is a measurement of the change in depth relative to the
+%% screen area of the polygon, and r is the smallest value that is guaranteed to produce
+%% a resolvable offset for a given implementation. The offset is added before the depth test
+%% is performed and before the value is written into the depth buffer.
+%%
+%% ``gl:polygonOffset'' is useful for rendering hidden-line images, for applying decals
+%% to surfaces, and for rendering solids with highlighted edges.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml">external</a> documentation.
+-spec polygonOffset(Factor, Units) -> ok when Factor :: float(),Units :: float().
+polygonOffset(Factor,Units) ->
+ cast(5051, <<Factor:?GLfloat,Units:?GLfloat>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3b(integer(),integer(),integer()) -> ok.
-color3b(Red,Green,Blue) ->
- cast(5055, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>).
+%% @doc Set the polygon stippling pattern
+%%
+%% Polygon stippling, like line stippling (see {@link gl:lineStipple/2} ), masks out certain
+%% fragments produced by rasterization, creating a pattern. Stippling is independent of polygon
+%% antialiasing.
+%%
+%% `Pattern' is a pointer to a 32*32 stipple pattern that is stored in memory just
+%% like the pixel data supplied to a {@link gl:drawPixels/5} call with height and `width'
+%% both equal to 32, a pixel format of `?GL_COLOR_INDEX', and data type of `?GL_BITMAP'
+%% . That is, the stipple pattern is represented as a 32*32 array of 1-bit color indices
+%% packed in unsigned bytes. {@link gl:pixelStoref/2} parameters like `?GL_UNPACK_SWAP_BYTES'
+%% and `?GL_UNPACK_LSB_FIRST' affect the assembling of the bits into a stipple pattern.
+%% Pixel transfer operations (shift, offset, pixel map) are not applied to the stipple image,
+%% however.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a stipple pattern is specified, `Pattern' is
+%% treated as a byte offset into the buffer object's data store.
+%%
+%% To enable and disable polygon stippling, call {@link gl:enable/1} and {@link gl:enable/1}
+%% with argument `?GL_POLYGON_STIPPLE'. Polygon stippling is initially disabled. If
+%% it's enabled, a rasterized polygon fragment with window coordinates x w and y w is
+%% sent to the next stage of the GL if and only if the ( x w% 32)th bit in the ( y w% 32)th
+%% row of the stipple pattern is 1 (one). When polygon stippling is disabled, it is as if
+%% the stipple pattern consists of all 1's.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonStipple.xml">external</a> documentation.
+-spec polygonStipple(Mask) -> ok when Mask :: binary().
+polygonStipple(Mask) ->
+ send_bin(Mask),
+ cast(5052, <<>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3b(Red,Green,Blue)
--spec color3bv({integer(),integer(),integer()}) -> ok.
-color3bv({Red,Green,Blue}) -> color3b(Red,Green,Blue).
+%% @doc Return the polygon stipple pattern
+%%
+%% ``gl:getPolygonStipple'' returns to `Pattern' a 32*32 polygon stipple pattern.
+%% The pattern is packed into memory as if {@link gl:readPixels/7} with both `height'
+%% and `width' of 32, `type' of `?GL_BITMAP', and `format' of `?GL_COLOR_INDEX'
+%% were called, and the stipple pattern were stored in an internal 32*32 color index buffer.
+%% Unlike {@link gl:readPixels/7} , however, pixel transfer operations (shift, offset, pixel
+%% map) are not applied to the returned stipple image.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a polygon stipple pattern is requested, `Pattern'
+%% is treated as a byte offset into the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPolygonStipple.xml">external</a> documentation.
+-spec getPolygonStipple() -> binary().
+getPolygonStipple() ->
+ call(5053, <<>>).
-%% @spec (Red::float(),Green::float(),Blue::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3d(float(),float(),float()) -> ok.
-color3d(Red,Green,Blue) ->
- cast(5056, <<Red:?GLdouble,Green:?GLdouble,Blue:?GLdouble>>).
+%% @doc Flag edges as either boundary or nonboundary
+%%
+%% Each vertex of a polygon, separate triangle, or separate quadrilateral specified between
+%% a {@link gl:'begin'/1} / {@link gl:'begin'/1} pair is marked as the start of either a boundary or
+%% nonboundary edge. If the current edge flag is true when the vertex is specified, the vertex
+%% is marked as the start of a boundary edge. Otherwise, the vertex is marked as the start
+%% of a nonboundary edge. ``gl:edgeFlag'' sets the edge flag bit to `?GL_TRUE' if `Flag'
+%% is `?GL_TRUE' and to `?GL_FALSE' otherwise.
+%%
+%% The vertices of connected triangles and connected quadrilaterals are always marked as
+%% boundary, regardless of the value of the edge flag.
+%%
+%% Boundary and nonboundary edge flags on vertices are significant only if `?GL_POLYGON_MODE'
+%% is set to `?GL_POINT' or `?GL_LINE'. See {@link gl:polygonMode/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml">external</a> documentation.
+-spec edgeFlag(Flag) -> ok when Flag :: 0|1.
+edgeFlag(Flag) ->
+ cast(5054, <<Flag:?GLboolean>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3d(Red,Green,Blue)
--spec color3dv({float(),float(),float()}) -> ok.
-color3dv({Red,Green,Blue}) -> color3d(Red,Green,Blue).
+%% @equiv edgeFlag(Flag)
+-spec edgeFlagv(Flag) -> ok when Flag :: {Flag :: 0|1}.
+edgeFlagv({Flag}) -> edgeFlag(Flag).
-%% @spec (Red::float(),Green::float(),Blue::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3f(float(),float(),float()) -> ok.
-color3f(Red,Green,Blue) ->
- cast(5057, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat>>).
+%% @doc Define the scissor box
+%%
+%% ``gl:scissor'' defines a rectangle, called the scissor box, in window coordinates. The
+%% first two arguments, `X' and `Y' , specify the lower left corner of the box. `Width'
+%% and `Height' specify the width and height of the box.
+%%
+%% To enable and disable the scissor test, call {@link gl:enable/1} and {@link gl:enable/1}
+%% with argument `?GL_SCISSOR_TEST'. The test is initially disabled. While the test
+%% is enabled, only pixels that lie within the scissor box can be modified by drawing commands.
+%% Window coordinates have integer values at the shared corners of frame buffer pixels. glScissor(0,0,1,1)
+%% allows modification of only the lower left pixel in the window, and glScissor(0,0,0,0)
+%% doesn't allow modification of any pixels in the window.
+%%
+%% When the scissor test is disabled, it is as though the scissor box includes the entire
+%% window.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml">external</a> documentation.
+-spec scissor(X, Y, Width, Height) -> ok when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
+scissor(X,Y,Width,Height) ->
+ cast(5055, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3f(Red,Green,Blue)
--spec color3fv({float(),float(),float()}) -> ok.
-color3fv({Red,Green,Blue}) -> color3f(Red,Green,Blue).
+%% @doc Specify a plane against which all geometry is clipped
+%%
+%% Geometry is always clipped against the boundaries of a six-plane frustum in `x', `y'
+%% , and `z'. ``gl:clipPlane'' allows the specification of additional planes, not
+%% necessarily perpendicular to the `x', `y', or `z' axis, against which all
+%% geometry is clipped. To determine the maximum number of additional clipping planes, call {@link gl:getBooleanv/1}
+%% with argument `?GL_MAX_CLIP_PLANES'. All implementations support at least six such
+%% clipping planes. Because the resulting clipping region is the intersection of the defined
+%% half-spaces, it is always convex.
+%%
+%% ``gl:clipPlane'' specifies a half-space using a four-component plane equation. When ``gl:clipPlane''
+%% is called, `Equation' is transformed by the inverse of the modelview matrix and
+%% stored in the resulting eye coordinates. Subsequent changes to the modelview matrix have
+%% no effect on the stored plane-equation components. If the dot product of the eye coordinates
+%% of a vertex with the stored plane equation components is positive or zero, the vertex is `in'
+%% with respect to that clipping plane. Otherwise, it is `out'.
+%%
+%% To enable and disable clipping planes, call {@link gl:enable/1} and {@link gl:enable/1}
+%% with the argument `?GL_CLIP_PLANE'`i', where `i' is the plane number.
+%%
+%% All clipping planes are initially defined as (0, 0, 0, 0) in eye coordinates and are
+%% disabled.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClipPlane.xml">external</a> documentation.
+-spec clipPlane(Plane, Equation) -> ok when Plane :: enum(),Equation :: {float(),float(),float(),float()}.
+clipPlane(Plane,{E1,E2,E3,E4}) ->
+ cast(5056, <<Plane:?GLenum,0:32,E1:?GLdouble,E2:?GLdouble,E3:?GLdouble,E4:?GLdouble>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3i(integer(),integer(),integer()) -> ok.
-color3i(Red,Green,Blue) ->
- cast(5058, <<Red:?GLint,Green:?GLint,Blue:?GLint>>).
+%% @doc Return the coefficients of the specified clipping plane
+%%
+%% ``gl:getClipPlane'' returns in `Equation' the four coefficients of the plane equation
+%% for `Plane' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetClipPlane.xml">external</a> documentation.
+-spec getClipPlane(Plane) -> {float(),float(),float(),float()} when Plane :: enum().
+getClipPlane(Plane) ->
+ call(5057, <<Plane:?GLenum>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3i(Red,Green,Blue)
--spec color3iv({integer(),integer(),integer()}) -> ok.
-color3iv({Red,Green,Blue}) -> color3i(Red,Green,Blue).
+%% @doc Specify which color buffers are to be drawn into
+%%
+%% When colors are written to the frame buffer, they are written into the color buffers
+%% specified by ``gl:drawBuffer''. The specifications are as follows:
+%%
+%% `?GL_NONE': No color buffers are written.
+%%
+%% `?GL_FRONT_LEFT': Only the front left color buffer is written.
+%%
+%% `?GL_FRONT_RIGHT': Only the front right color buffer is written.
+%%
+%% `?GL_BACK_LEFT': Only the back left color buffer is written.
+%%
+%% `?GL_BACK_RIGHT': Only the back right color buffer is written.
+%%
+%% `?GL_FRONT': Only the front left and front right color buffers are written. If there
+%% is no front right color buffer, only the front left color buffer is written.
+%%
+%% `?GL_BACK': Only the back left and back right color buffers are written. If there
+%% is no back right color buffer, only the back left color buffer is written.
+%%
+%% `?GL_LEFT': Only the front left and back left color buffers are written. If there
+%% is no back left color buffer, only the front left color buffer is written.
+%%
+%% `?GL_RIGHT': Only the front right and back right color buffers are written. If there
+%% is no back right color buffer, only the front right color buffer is written.
+%%
+%% `?GL_FRONT_AND_BACK': All the front and back color buffers (front left, front right,
+%% back left, back right) are written. If there are no back color buffers, only the front
+%% left and front right color buffers are written. If there are no right color buffers, only
+%% the front left and back left color buffers are written. If there are no right or back
+%% color buffers, only the front left color buffer is written.
+%%
+%% If more than one color buffer is selected for drawing, then blending or logical operations
+%% are computed and applied independently for each color buffer and can produce different
+%% results in each buffer.
+%%
+%% Monoscopic contexts include only `left' buffers, and stereoscopic contexts include
+%% both `left' and `right' buffers. Likewise, single-buffered contexts include
+%% only `front' buffers, and double-buffered contexts include both `front' and `back'
+%% buffers. The context is selected at GL initialization.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml">external</a> documentation.
+-spec drawBuffer(Mode) -> ok when Mode :: enum().
+drawBuffer(Mode) ->
+ cast(5058, <<Mode:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3s(integer(),integer(),integer()) -> ok.
-color3s(Red,Green,Blue) ->
- cast(5059, <<Red:?GLshort,Green:?GLshort,Blue:?GLshort>>).
+%% @doc Select a color buffer source for pixels
+%%
+%% ``gl:readBuffer'' specifies a color buffer as the source for subsequent {@link gl:readPixels/7}
+%% , {@link gl:copyTexImage1D/7} , {@link gl:copyTexImage2D/8} , {@link gl:copyTexSubImage1D/6} , {@link gl:copyTexSubImage2D/8}
+%% , and {@link gl:copyTexSubImage3D/9} commands. `Mode' accepts one of twelve or more
+%% predefined values. In a fully configured system, `?GL_FRONT', `?GL_LEFT', and `?GL_FRONT_LEFT'
+%% all name the front left buffer, `?GL_FRONT_RIGHT' and `?GL_RIGHT' name the
+%% front right buffer, and `?GL_BACK_LEFT' and `?GL_BACK' name the back left buffer.
+%% Further more, the constants `?GL_COLOR_ATTACHMENT'`i' may be used to indicate
+%% the `i'th color attachment where `i' ranges from zero to the value of `?GL_MAX_COLOR_ATTACHMENTS'
+%% minus one.
+%%
+%% Nonstereo double-buffered configurations have only a front left and a back left buffer.
+%% Single-buffered configurations have a front left and a front right buffer if stereo, and
+%% only a front left buffer if nonstereo. It is an error to specify a nonexistent buffer to ``gl:readBuffer''
+%% .
+%%
+%% `Mode' is initially `?GL_FRONT' in single-buffered configurations and `?GL_BACK'
+%% in double-buffered configurations.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml">external</a> documentation.
+-spec readBuffer(Mode) -> ok when Mode :: enum().
+readBuffer(Mode) ->
+ cast(5059, <<Mode:?GLenum>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3s(Red,Green,Blue)
--spec color3sv({integer(),integer(),integer()}) -> ok.
-color3sv({Red,Green,Blue}) -> color3s(Red,Green,Blue).
+%% @doc Enable or disable server-side GL capabilities
+%%
+%% ``gl:enable'' and {@link gl:enable/1} enable and disable various capabilities. Use {@link gl:isEnabled/1}
+%% or {@link gl:getBooleanv/1} to determine the current setting of any capability. The initial value
+%% for each capability with the exception of `?GL_DITHER' and `?GL_MULTISAMPLE'
+%% is `?GL_FALSE'. The initial value for `?GL_DITHER' and `?GL_MULTISAMPLE'
+%% is `?GL_TRUE'.
+%%
+%% Both ``gl:enable'' and {@link gl:enable/1} take a single argument, `Cap' , which
+%% can assume one of the following values:
+%%
+%% Some of the GL's capabilities are indexed. ``gl:enablei'' and ``gl:disablei'' enable
+%% and disable indexed capabilities.
+%%
+%% `?GL_BLEND': If enabled, blend the computed fragment color values with the values
+%% in the color buffers. See {@link gl:blendFunc/2} .
+%%
+%% `?GL_CLIP_DISTANCE'`i': If enabled, clip geometry against user-defined half
+%% space `i'.
+%%
+%% `?GL_COLOR_LOGIC_OP': If enabled, apply the currently selected logical operation
+%% to the computed fragment color and color buffer values. See {@link gl:logicOp/1} .
+%%
+%% `?GL_CULL_FACE': If enabled, cull polygons based on their winding in window coordinates.
+%% See {@link gl:cullFace/1} .
+%%
+%% `?GL_DEPTH_CLAMP': If enabled, the -w c&amp;le; z c&amp;le; w c plane equation is
+%% ignored by view volume clipping (effectively, there is no near or far plane clipping).
+%% See {@link gl:depthRange/2} .
+%%
+%% `?GL_DEPTH_TEST': If enabled, do depth comparisons and update the depth buffer.
+%% Note that even if the depth buffer exists and the depth mask is non-zero, the depth buffer
+%% is not updated if the depth test is disabled. See {@link gl:depthFunc/1} and {@link gl:depthRange/2}
+%% .
+%%
+%% `?GL_DITHER': If enabled, dither color components or indices before they are written
+%% to the color buffer.
+%%
+%% `?GL_FRAMEBUFFER_SRGB': If enabled and the value of `?GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING'
+%% for the framebuffer attachment corresponding to the destination buffer is `?GL_SRGB',
+%% the R, G, and B destination color values (after conversion from fixed-point to floating-point)
+%% are considered to be encoded for the sRGB color space and hence are linearized prior to
+%% their use in blending.
+%%
+%% `?GL_LINE_SMOOTH': If enabled, draw lines with correct filtering. Otherwise, draw
+%% aliased lines. See {@link gl:lineWidth/1} .
+%%
+%% `?GL_MULTISAMPLE': If enabled, use multiple fragment samples in computing the final
+%% color of a pixel. See {@link gl:sampleCoverage/2} .
+%%
+%% `?GL_POLYGON_OFFSET_FILL': If enabled, and if the polygon is rendered in `?GL_FILL'
+%% mode, an offset is added to depth values of a polygon's fragments before the depth comparison
+%% is performed. See {@link gl:polygonOffset/2} .
+%%
+%% `?GL_POLYGON_OFFSET_LINE': If enabled, and if the polygon is rendered in `?GL_LINE'
+%% mode, an offset is added to depth values of a polygon's fragments before the depth comparison
+%% is performed. See {@link gl:polygonOffset/2} .
+%%
+%% `?GL_POLYGON_OFFSET_POINT': If enabled, an offset is added to depth values of a
+%% polygon's fragments before the depth comparison is performed, if the polygon is rendered
+%% in `?GL_POINT' mode. See {@link gl:polygonOffset/2} .
+%%
+%% `?GL_POLYGON_SMOOTH': If enabled, draw polygons with proper filtering. Otherwise,
+%% draw aliased polygons. For correct antialiased polygons, an alpha buffer is needed and
+%% the polygons must be sorted front to back.
+%%
+%% `?GL_PRIMITIVE_RESTART': Enables primitive restarting. If enabled, any one of the
+%% draw commands which transfers a set of generic attribute array elements to the GL will
+%% restart the primitive when the index of the vertex is equal to the primitive restart
+%% index. See {@link gl:primitiveRestartIndex/1} .
+%%
+%% `?GL_SAMPLE_ALPHA_TO_COVERAGE': If enabled, compute a temporary coverage value where
+%% each bit is determined by the alpha value at the corresponding sample location. The temporary
+%% coverage value is then ANDed with the fragment coverage value.
+%%
+%% `?GL_SAMPLE_ALPHA_TO_ONE': If enabled, each sample alpha value is replaced by the
+%% maximum representable alpha value.
+%%
+%% `?GL_SAMPLE_COVERAGE': If enabled, the fragment's coverage is ANDed with the temporary
+%% coverage value. If `?GL_SAMPLE_COVERAGE_INVERT' is set to `?GL_TRUE', invert
+%% the coverage value. See {@link gl:sampleCoverage/2} .
+%%
+%% `?GL_SAMPLE_SHADING': If enabled, the active fragment shader is run once for each
+%% covered sample, or at fraction of this rate as determined by the current value of `?GL_MIN_SAMPLE_SHADING_VALUE'
+%% . See {@link gl:minSampleShading/1} .
+%%
+%% `?GL_SAMPLE_MASK': If enabled, the sample coverage mask generated for a fragment
+%% during rasterization will be ANDed with the value of `?GL_SAMPLE_MASK_VALUE' before
+%% shading occurs. See {@link gl:sampleMaski/2} .
+%%
+%% `?GL_SCISSOR_TEST': If enabled, discard fragments that are outside the scissor rectangle.
+%% See {@link gl:scissor/4} .
+%%
+%% `?GL_STENCIL_TEST': If enabled, do stencil testing and update the stencil buffer.
+%% See {@link gl:stencilFunc/3} and {@link gl:stencilOp/3} .
+%%
+%% `?GL_TEXTURE_CUBE_MAP_SEAMLESS': If enabled, cubemap textures are sampled such that
+%% when linearly sampling from the border between two adjacent faces, texels from both faces
+%% are used to generate the final sample value. When disabled, texels from only a single
+%% face are used to construct the final sample value.
+%%
+%% `?GL_PROGRAM_POINT_SIZE': If enabled and a vertex or geometry shader is active,
+%% then the derived point size is taken from the (potentially clipped) shader builtin `?gl_PointSize'
+%% and clamped to the implementation-dependent point size range.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml">external</a> documentation.
+-spec enable(Cap) -> ok when Cap :: enum().
+enable(Cap) ->
+ cast(5060, <<Cap:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3ub(integer(),integer(),integer()) -> ok.
-color3ub(Red,Green,Blue) ->
- cast(5060, <<Red:?GLubyte,Green:?GLubyte,Blue:?GLubyte>>).
+%% @doc
+%% See {@link enable/1}
+-spec disable(Cap) -> ok when Cap :: enum().
+disable(Cap) ->
+ cast(5061, <<Cap:?GLenum>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3ub(Red,Green,Blue)
--spec color3ubv({integer(),integer(),integer()}) -> ok.
-color3ubv({Red,Green,Blue}) -> color3ub(Red,Green,Blue).
+%% @doc Test whether a capability is enabled
+%%
+%% ``gl:isEnabled'' returns `?GL_TRUE' if `Cap' is an enabled capability and
+%% returns `?GL_FALSE' otherwise. Boolean states that are indexed may be tested with ``gl:isEnabledi''
+%% . For ``gl:isEnabledi'', `Index' specifies the index of the capability to test. `Index'
+%% must be between zero and the count of indexed capabilities for `Cap' . Initially
+%% all capabilities except `?GL_DITHER' are disabled; `?GL_DITHER' is initially
+%% enabled.
+%%
+%% The following capabilities are accepted for `Cap' : <table><tbody><tr><td>` Constant '
+%% </td><td>` See '</td></tr></tbody><tbody><tr><td>`?GL_BLEND'</td><td> {@link gl:blendFunc/2}
+%% , {@link gl:logicOp/1} </td></tr><tr><td>`?GL_CLIP_DISTANCE'`i'</td><td> {@link gl:enable/1}
+%% </td></tr><tr><td>`?GL_COLOR_LOGIC_OP'</td><td> {@link gl:logicOp/1} </td></tr><tr><td>`?GL_CULL_FACE'
+%% </td><td> {@link gl:cullFace/1} </td></tr><tr><td>`?GL_DEPTH_CLAMP'</td><td> {@link gl:enable/1}
+%% </td></tr><tr><td>`?GL_DEPTH_TEST'</td><td> {@link gl:depthFunc/1} , {@link gl:depthRange/2}
+%% </td></tr><tr><td>`?GL_DITHER'</td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_FRAMEBUFFER_SRGB'
+%% </td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_LINE_SMOOTH'</td><td> {@link gl:lineWidth/1}
+%% </td></tr><tr><td>`?GL_MULTISAMPLE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>
+%% `?GL_POLYGON_SMOOTH'</td><td> {@link gl:polygonMode/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_FILL'
+%% </td><td> {@link gl:polygonOffset/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_LINE'</td><td>
+%% {@link gl:polygonOffset/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_POINT'</td><td> {@link gl:polygonOffset/2}
+%% </td></tr><tr><td>`?GL_PROGRAM_POINT_SIZE'</td><td> {@link gl:enable/1} </td></tr><tr><td>
+%% `?GL_PRIMITIVE_RESTART'</td><td> {@link gl:enable/1} , {@link gl:primitiveRestartIndex/1} </td>
+%% </tr><tr><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'</td><td> {@link gl:sampleCoverage/2} </td></tr>
+%% <tr><td>`?GL_SAMPLE_ALPHA_TO_ONE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>
+%% `?GL_SAMPLE_COVERAGE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>`?GL_SAMPLE_MASK'
+%% </td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_SCISSOR_TEST'</td><td> {@link gl:scissor/4}
+%% </td></tr><tr><td>`?GL_STENCIL_TEST'</td><td> {@link gl:stencilFunc/3} , {@link gl:stencilOp/3}
+%% </td></tr><tr><td>`?GL_TEXTURE_CUBEMAP_SEAMLESS'</td><td> {@link gl:enable/1} </td></tr>
+%% </tbody></table>
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabled.xml">external</a> documentation.
+-spec isEnabled(Cap) -> 0|1 when Cap :: enum().
+isEnabled(Cap) ->
+ call(5062, <<Cap:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3ui(integer(),integer(),integer()) -> ok.
-color3ui(Red,Green,Blue) ->
- cast(5061, <<Red:?GLuint,Green:?GLuint,Blue:?GLuint>>).
+%% @doc Enable or disable client-side capability
+%%
+%% ``gl:enableClientState'' and {@link gl:enableClientState/1} enable or disable individual
+%% client-side capabilities. By default, all client-side capabilities are disabled. Both ``gl:enableClientState''
+%% and {@link gl:enableClientState/1} take a single argument, `Cap' , which can assume
+%% one of the following values:
+%%
+%% `?GL_COLOR_ARRAY': If enabled, the color array is enabled for writing and used during
+%% rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} ,
+%% {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:colorPointer/4} .
+%%
+%% `?GL_EDGE_FLAG_ARRAY': If enabled, the edge flag array is enabled for writing and
+%% used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
+%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:edgeFlagPointer/2} .
+%%
+%% `?GL_FOG_COORD_ARRAY': If enabled, the fog coordinate array is enabled for writing
+%% and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
+%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:fogCoordPointer/3} .
+%%
+%% `?GL_INDEX_ARRAY': If enabled, the index array is enabled for writing and used during
+%% rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} ,
+%% {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:indexPointer/3} .
+%%
+%% `?GL_NORMAL_ARRAY': If enabled, the normal array is enabled for writing and used
+%% during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
+%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:normalPointer/3} .
+%%
+%% `?GL_SECONDARY_COLOR_ARRAY': If enabled, the secondary color array is enabled for
+%% writing and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
+%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:colorPointer/4} .
+%%
+%% `?GL_TEXTURE_COORD_ARRAY': If enabled, the texture coordinate array is enabled for
+%% writing and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
+%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:texCoordPointer/4} .
+%%
+%% `?GL_VERTEX_ARRAY': If enabled, the vertex array is enabled for writing and used
+%% during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
+%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
+%% is called. See {@link gl:vertexPointer/4} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml">external</a> documentation.
+-spec enableClientState(Cap) -> ok when Cap :: enum().
+enableClientState(Cap) ->
+ cast(5063, <<Cap:?GLenum>>).
+
+%% @doc
+%% See {@link enableClientState/1}
+-spec disableClientState(Cap) -> ok when Cap :: enum().
+disableClientState(Cap) ->
+ cast(5064, <<Cap:?GLenum>>).
+
+%% @doc Return the value or values of a selected parameter
+%%
+%% These four commands return values for simple state variables in GL. `Pname' is a
+%% symbolic constant indicating the state variable to be returned, and `Params' is a
+%% pointer to an array of the indicated type in which to place the returned data.
+%%
+%% Type conversion is performed if `Params' has a different type than the state variable
+%% value being requested. If ``gl:getBooleanv'' is called, a floating-point (or integer)
+%% value is converted to `?GL_FALSE' if and only if it is 0.0 (or 0). Otherwise, it
+%% is converted to `?GL_TRUE'. If ``gl:getIntegerv'' is called, boolean values are
+%% returned as `?GL_TRUE' or `?GL_FALSE', and most floating-point values are rounded
+%% to the nearest integer value. Floating-point colors and normals, however, are returned
+%% with a linear mapping that maps 1.0 to the most positive representable integer value and
+%% -1.0 to the most negative representable integer value. If ``gl:getFloatv'' or ``gl:getDoublev''
+%% is called, boolean values are returned as `?GL_TRUE' or `?GL_FALSE', and integer
+%% values are converted to floating-point values.
+%%
+%% The following symbolic constants are accepted by `Pname' :
+%%
+%% `?GL_ACTIVE_TEXTURE': `Params' returns a single value indicating the active
+%% multitexture unit. The initial value is `?GL_TEXTURE0'. See {@link gl:activeTexture/1} .
+%%
+%%
+%% `?GL_ALIASED_LINE_WIDTH_RANGE': `Params' returns a pair of values indicating
+%% the range of widths supported for aliased lines. See {@link gl:lineWidth/1} .
+%%
+%% `?GL_ARRAY_BUFFER_BINDING': `Params' returns a single value, the name of the
+%% buffer object currently bound to the target `?GL_ARRAY_BUFFER'. If no buffer object
+%% is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2} .
+%%
+%%
+%% `?GL_BLEND': `Params' returns a single boolean value indicating whether blending
+%% is enabled. The initial value is `?GL_FALSE'. See {@link gl:blendFunc/2} .
+%%
+%% `?GL_BLEND_COLOR': `Params' returns four values, the red, green, blue, and alpha
+%% values which are the components of the blend color. See {@link gl:blendColor/4} .
+%%
+%% `?GL_BLEND_DST_ALPHA': `Params' returns one value, the symbolic constant identifying
+%% the alpha destination blend function. The initial value is `?GL_ZERO'. See {@link gl:blendFunc/2}
+%% and {@link gl:blendFuncSeparate/4} .
+%%
+%% `?GL_BLEND_DST_RGB': `Params' returns one value, the symbolic constant identifying
+%% the RGB destination blend function. The initial value is `?GL_ZERO'. See {@link gl:blendFunc/2}
+%% and {@link gl:blendFuncSeparate/4} .
+%%
+%% `?GL_BLEND_EQUATION_RGB': `Params' returns one value, a symbolic constant indicating
+%% whether the RGB blend equation is `?GL_FUNC_ADD', `?GL_FUNC_SUBTRACT', `?GL_FUNC_REVERSE_SUBTRACT'
+%% , `?GL_MIN' or `?GL_MAX'. See {@link gl:blendEquationSeparate/2} .
+%%
+%% `?GL_BLEND_EQUATION_ALPHA': `Params' returns one value, a symbolic constant
+%% indicating whether the Alpha blend equation is `?GL_FUNC_ADD', `?GL_FUNC_SUBTRACT'
+%% , `?GL_FUNC_REVERSE_SUBTRACT', `?GL_MIN' or `?GL_MAX'. See {@link gl:blendEquationSeparate/2}
+%% .
+%%
+%% `?GL_BLEND_SRC_ALPHA': `Params' returns one value, the symbolic constant identifying
+%% the alpha source blend function. The initial value is `?GL_ONE'. See {@link gl:blendFunc/2}
+%% and {@link gl:blendFuncSeparate/4} .
+%%
+%% `?GL_BLEND_SRC_RGB': `Params' returns one value, the symbolic constant identifying
+%% the RGB source blend function. The initial value is `?GL_ONE'. See {@link gl:blendFunc/2}
+%% and {@link gl:blendFuncSeparate/4} .
+%%
+%% `?GL_COLOR_CLEAR_VALUE': `Params' returns four values: the red, green, blue,
+%% and alpha values used to clear the color buffers. Integer values, if requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 returns the most
+%% positive representable integer value, and -1.0 returns the most negative representable
+%% integer value. The initial value is (0, 0, 0, 0). See {@link gl:clearColor/4} .
+%%
+%% `?GL_COLOR_LOGIC_OP': `Params' returns a single boolean value indicating whether
+%% a fragment's RGBA color values are merged into the framebuffer using a logical operation.
+%% The initial value is `?GL_FALSE'. See {@link gl:logicOp/1} .
+%%
+%% `?GL_COLOR_WRITEMASK': `Params' returns four boolean values: the red, green,
+%% blue, and alpha write enables for the color buffers. The initial value is (`?GL_TRUE',
+%% `?GL_TRUE', `?GL_TRUE', `?GL_TRUE'). See {@link gl:colorMask/4} .
+%%
+%% `?GL_COMPRESSED_TEXTURE_FORMATS': `Params' returns a list of symbolic constants
+%% of length `?GL_NUM_COMPRESSED_TEXTURE_FORMATS' indicating which compressed texture
+%% formats are available. See {@link gl:compressedTexImage2D/8} .
+%%
+%% `?GL_CONTEXT_FLAGS': `Params' returns one value, the flags with which the context
+%% was created (such as debugging functionality).
+%%
+%% `?GL_CULL_FACE': `Params' returns a single boolean value indicating whether
+%% polygon culling is enabled. The initial value is `?GL_FALSE'. See {@link gl:cullFace/1}
+%% .
+%%
+%% `?GL_CURRENT_PROGRAM': `Params' returns one value, the name of the program object
+%% that is currently active, or 0 if no program object is active. See {@link gl:useProgram/1} .
+%%
+%%
+%% `?GL_DEPTH_CLEAR_VALUE': `Params' returns one value, the value that is used
+%% to clear the depth buffer. Integer values, if requested, are linearly mapped from the
+%% internal floating-point representation such that 1.0 returns the most positive representable
+%% integer value, and -1.0 returns the most negative representable integer value. The initial
+%% value is 1. See {@link gl:clearDepth/1} .
+%%
+%% `?GL_DEPTH_FUNC': `Params' returns one value, the symbolic constant that indicates
+%% the depth comparison function. The initial value is `?GL_LESS'. See {@link gl:depthFunc/1}
+%% .
+%%
+%% `?GL_DEPTH_RANGE': `Params' returns two values: the near and far mapping limits
+%% for the depth buffer. Integer values, if requested, are linearly mapped from the internal
+%% floating-point representation such that 1.0 returns the most positive representable integer
+%% value, and -1.0 returns the most negative representable integer value. The initial value
+%% is (0, 1). See {@link gl:depthRange/2} .
+%%
+%% `?GL_DEPTH_TEST': `Params' returns a single boolean value indicating whether
+%% depth testing of fragments is enabled. The initial value is `?GL_FALSE'. See {@link gl:depthFunc/1}
+%% and {@link gl:depthRange/2} .
+%%
+%% `?GL_DEPTH_WRITEMASK': `Params' returns a single boolean value indicating if
+%% the depth buffer is enabled for writing. The initial value is `?GL_TRUE'. See {@link gl:depthMask/1}
+%% .
+%%
+%% `?GL_DITHER': `Params' returns a single boolean value indicating whether dithering
+%% of fragment colors and indices is enabled. The initial value is `?GL_TRUE'.
+%%
+%% `?GL_DOUBLEBUFFER': `Params' returns a single boolean value indicating whether
+%% double buffering is supported.
+%%
+%% `?GL_DRAW_BUFFER': `Params' returns one value, a symbolic constant indicating
+%% which buffers are being drawn to. See {@link gl:drawBuffer/1} . The initial value is `?GL_BACK'
+%% if there are back buffers, otherwise it is `?GL_FRONT'.
+%%
+%% `?GL_DRAW_BUFFER'`i': `Params' returns one value, a symbolic constant indicating
+%% which buffers are being drawn to by the corresponding output color. See {@link gl:drawBuffers/1}
+%% . The initial value of `?GL_DRAW_BUFFER0' is `?GL_BACK' if there are back buffers,
+%% otherwise it is `?GL_FRONT'. The initial values of draw buffers for all other output
+%% colors is `?GL_NONE'.
+%%
+%% `?GL_DRAW_FRAMEBUFFER_BINDING': `Params' returns one value, the name of the
+%% framebuffer object currently bound to the `?GL_DRAW_FRAMEBUFFER' target. If the default
+%% framebuffer is bound, this value will be zero. The initial value is zero. See {@link gl:bindFramebuffer/2}
+%% .
+%%
+%% `?GL_READ_FRAMEBUFFER_BINDING': `Params' returns one value, the name of the
+%% framebuffer object currently bound to the `?GL_READ_FRAMEBUFFER' target. If the default
+%% framebuffer is bound, this value will be zero. The initial value is zero. See {@link gl:bindFramebuffer/2}
+%% .
+%%
+%% `?GL_ELEMENT_ARRAY_BUFFER_BINDING': `Params' returns a single value, the name
+%% of the buffer object currently bound to the target `?GL_ELEMENT_ARRAY_BUFFER'. If
+%% no buffer object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2}
+%% .
+%%
+%% `?GL_FRAGMENT_SHADER_DERIVATIVE_HINT': `Params' returns one value, a symbolic
+%% constant indicating the mode of the derivative accuracy hint for fragment shaders. The
+%% initial value is `?GL_DONT_CARE'. See {@link gl:hint/2} .
+%%
+%% `?GL_IMPLEMENTATION_COLOR_READ_FORMAT': `Params' returns a single GLenum value
+%% indicating the implementation's preferred pixel data format. See {@link gl:readPixels/7} .
+%%
+%% `?GL_IMPLEMENTATION_COLOR_READ_TYPE': `Params' returns a single GLenum value
+%% indicating the implementation's preferred pixel data type. See {@link gl:readPixels/7} .
+%%
+%% `?GL_LINE_SMOOTH': `Params' returns a single boolean value indicating whether
+%% antialiasing of lines is enabled. The initial value is `?GL_FALSE'. See {@link gl:lineWidth/1}
+%% .
+%%
+%% `?GL_LINE_SMOOTH_HINT': `Params' returns one value, a symbolic constant indicating
+%% the mode of the line antialiasing hint. The initial value is `?GL_DONT_CARE'. See {@link gl:hint/2}
+%% .
+%%
+%% `?GL_LINE_WIDTH': `Params' returns one value, the line width as specified with {@link gl:lineWidth/1}
+%% . The initial value is 1.
+%%
+%% `?GL_LAYER_PROVOKING_VERTEX': `Params' returns one value, the implementation
+%% dependent specifc vertex of a primitive that is used to select the rendering layer. If
+%% the value returned is equivalent to `?GL_PROVOKING_VERTEX', then the vertex selection
+%% follows the convention specified by {@link gl:provokingVertex/1} . If the value returned
+%% is equivalent to `?GL_FIRST_VERTEX_CONVENTION', then the selection is always taken
+%% from the first vertex in the primitive. If the value returned is equivalent to `?GL_LAST_VERTEX_CONVENTION'
+%% , then the selection is always taken from the last vertex in the primitive. If the value
+%% returned is equivalent to `?GL_UNDEFINED_VERTEX', then the selection is not guaranteed
+%% to be taken from any specific vertex in the primitive.
+%%
+%% `?GL_LINE_WIDTH_GRANULARITY': `Params' returns one value, the width difference
+%% between adjacent supported widths for antialiased lines. See {@link gl:lineWidth/1} .
+%%
+%% `?GL_LINE_WIDTH_RANGE': `Params' returns two values: the smallest and largest
+%% supported widths for antialiased lines. See {@link gl:lineWidth/1} .
+%%
+%% `?GL_LOGIC_OP_MODE': `Params' returns one value, a symbolic constant indicating
+%% the selected logic operation mode. The initial value is `?GL_COPY'. See {@link gl:logicOp/1}
+%% .
+%%
+%% `?GL_MAJOR_VERSION': `Params' returns one value, the major version number of
+%% the OpenGL API supported by the current context.
+%%
+%% `?GL_MAX_3D_TEXTURE_SIZE': `Params' returns one value, a rough estimate of the
+%% largest 3D texture that the GL can handle. The value must be at least 64. Use `?GL_PROXY_TEXTURE_3D'
+%% to determine if a texture is too large. See {@link gl:texImage3D/10} .
+%%
+%% `?GL_MAX_ARRAY_TEXTURE_LAYERS': `Params' returns one value. The value indicates
+%% the maximum number of layers allowed in an array texture, and must be at least 256. See {@link gl:texImage2D/9}
+%% .
+%%
+%% `?GL_MAX_CLIP_DISTANCES': `Params' returns one value, the maximum number of
+%% application-defined clipping distances. The value must be at least 8.
+%%
+%% `?GL_MAX_COLOR_TEXTURE_SAMPLES': `Params' returns one value, the maximum number
+%% of samples in a color multisample texture.
+%%
+%% `?GL_MAX_COMBINED_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
+%% number of atomic counters available to all active shaders.
+%%
+%% `?GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS': `Params' returns one value,
+%% the number of words for fragment shader uniform variables in all uniform blocks (including
+%% default). The value must be at least 1. See {@link gl:uniform1f/2} .
+%%
+%% `?GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS': `Params' returns one value,
+%% the number of words for geometry shader uniform variables in all uniform blocks (including
+%% default). The value must be at least 1. See {@link gl:uniform1f/2} .
+%%
+%% `?GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum
+%% supported texture image units that can be used to access texture maps from the vertex
+%% shader and the fragment processor combined. If both the vertex shader and the fragment
+%% processing stage access the same texture image unit, then that counts as using two texture
+%% image units against this limit. The value must be at least 48. See {@link gl:activeTexture/1}
+%% .
+%%
+%% `?GL_MAX_COMBINED_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
+%% of uniform blocks per program. The value must be at least 36. See {@link gl:uniformBlockBinding/3}
+%% .
+%%
+%% `?GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS': `Params' returns one value, the
+%% number of words for vertex shader uniform variables in all uniform blocks (including default).
+%% The value must be at least 1. See {@link gl:uniform1f/2} .
+%%
+%% `?GL_MAX_CUBE_MAP_TEXTURE_SIZE': `Params' returns one value. The value gives
+%% a rough estimate of the largest cube-map texture that the GL can handle. The value must
+%% be at least 1024. Use `?GL_PROXY_TEXTURE_CUBE_MAP' to determine if a texture is too
+%% large. See {@link gl:texImage2D/9} .
+%%
+%% `?GL_MAX_DEPTH_TEXTURE_SAMPLES': `Params' returns one value, the maximum number
+%% of samples in a multisample depth or depth-stencil texture.
+%%
+%% `?GL_MAX_DRAW_BUFFERS': `Params' returns one value, the maximum number of simultaneous
+%% outputs that may be written in a fragment shader. The value must be at least 8. See {@link gl:drawBuffers/1}
+%% .
+%%
+%% `?GL_MAX_DUALSOURCE_DRAW_BUFFERS': `Params' returns one value, the maximum number
+%% of active draw buffers when using dual-source blending. The value must be at least 1.
+%% See {@link gl:blendFunc/2} and {@link gl:blendFuncSeparate/4} .
+%%
+%% `?GL_MAX_ELEMENTS_INDICES': `Params' returns one value, the recommended maximum
+%% number of vertex array indices. See {@link gl:drawRangeElements/6} .
+%%
+%% `?GL_MAX_ELEMENTS_VERTICES': `Params' returns one value, the recommended maximum
+%% number of vertex array vertices. See {@link gl:drawRangeElements/6} .
+%%
+%% `?GL_MAX_FRAGMENT_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
+%% number of atomic counters available to fragment shaders.
+%%
+%% `?GL_MAX_FRAGMENT_INPUT_COMPONENTS': `Params' returns one value, the maximum
+%% number of components of the inputs read by the fragment shader, which must be at least
+%% 128.
+%%
+%% `?GL_MAX_FRAGMENT_UNIFORM_COMPONENTS': `Params' returns one value, the maximum
+%% number of individual floating-point, integer, or boolean values that can be held in uniform
+%% variable storage for a fragment shader. The value must be at least 1024. See {@link gl:uniform1f/2}
+%% .
+%%
+%% `?GL_MAX_FRAGMENT_UNIFORM_VECTORS': `Params' returns one value, the maximum
+%% number of individual 4-vectors of floating-point, integer, or boolean values that can
+%% be held in uniform variable storage for a fragment shader. The value is equal to the value
+%% of `?GL_MAX_FRAGMENT_UNIFORM_COMPONENTS' divided by 4 and must be at least 256. See {@link gl:uniform1f/2}
+%% .
+%%
+%% `?GL_MAX_FRAGMENT_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
+%% of uniform blocks per fragment shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3}
+%% .
+%%
+%% `?GL_MAX_GEOMETRY_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
+%% number of atomic counters available to geometry shaders.
+%%
+%% `?GL_MAX_GEOMETRY_INPUT_COMPONENTS': `Params' returns one value, the maximum
+%% number of components of inputs read by a geometry shader, which must be at least 64.
+%%
+%% `?GL_MAX_GEOMETRY_OUTPUT_COMPONENTS': `Params' returns one value, the maximum
+%% number of components of outputs written by a geometry shader, which must be at least 128.
+%%
+%%
+%% `?GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum
+%% supported texture image units that can be used to access texture maps from the geometry
+%% shader. The value must be at least 16. See {@link gl:activeTexture/1} .
+%%
+%% `?GL_MAX_GEOMETRY_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
+%% of uniform blocks per geometry shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3}
+%% .
+%%
+%% `?GL_MAX_GEOMETRY_UNIFORM_COMPONENTS': `Params' returns one value, the maximum
+%% number of individual floating-point, integer, or boolean values that can be held in uniform
+%% variable storage for a geometry shader. The value must be at least 1024. See {@link gl:uniform1f/2}
+%% .
+%%
+%% `?GL_MAX_INTEGER_SAMPLES': `Params' returns one value, the maximum number of
+%% samples supported in integer format multisample buffers.
+%%
+%% `?GL_MIN_MAP_BUFFER_ALIGNMENT': `Params' returns one value, the minimum alignment
+%% in basic machine units of pointers returned fromsee `glMapBuffer' and see `glMapBufferRange'
+%% . This value must be a power of two and must be at least 64.
+%%
+%% `?GL_MAX_PROGRAM_TEXEL_OFFSET': `Params' returns one value, the maximum texel
+%% offset allowed in a texture lookup, which must be at least 7.
+%%
+%% `?GL_MIN_PROGRAM_TEXEL_OFFSET': `Params' returns one value, the minimum texel
+%% offset allowed in a texture lookup, which must be at most -8.
+%%
+%% `?GL_MAX_RECTANGLE_TEXTURE_SIZE': `Params' returns one value. The value gives
+%% a rough estimate of the largest rectangular texture that the GL can handle. The value
+%% must be at least 1024. Use `?GL_PROXY_RECTANGLE_TEXTURE' to determine if a texture
+%% is too large. See {@link gl:texImage2D/9} .
+%%
+%% `?GL_MAX_RENDERBUFFER_SIZE': `Params' returns one value. The value indicates
+%% the maximum supported size for renderbuffers. See {@link gl:framebufferRenderbuffer/4} .
+%%
+%% `?GL_MAX_SAMPLE_MASK_WORDS': `Params' returns one value, the maximum number
+%% of sample mask words.
+%%
+%% `?GL_MAX_SERVER_WAIT_TIMEOUT': `Params' returns one value, the maximum {@link gl:waitSync/3}
+%% timeout interval.
+%%
+%% `?GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS': `Params' returns a single value, the
+%% maximum number of atomic counters available to tessellation control shaders.
+%%
+%% `?GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS': `Params' returns a single value,
+%% the maximum number of atomic counters available to tessellation evaluation shaders.
+%%
+%% `?GL_MAX_TEXTURE_BUFFER_SIZE': `Params' returns one value. The value gives the
+%% maximum number of texels allowed in the texel array of a texture buffer object. Value
+%% must be at least 65536.
+%%
+%% `?GL_MAX_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum supported
+%% texture image units that can be used to access texture maps from the fragment shader.
+%% The value must be at least 16. See {@link gl:activeTexture/1} .
+%%
+%% `?GL_MAX_TEXTURE_LOD_BIAS': `Params' returns one value, the maximum, absolute
+%% value of the texture level-of-detail bias. The value must be at least 2.0.
+%%
+%% `?GL_MAX_TEXTURE_SIZE': `Params' returns one value. The value gives a rough
+%% estimate of the largest texture that the GL can handle. The value must be at least 1024.
+%% Use a proxy texture target such as `?GL_PROXY_TEXTURE_1D' or `?GL_PROXY_TEXTURE_2D'
+%% to determine if a texture is too large. See {@link gl:texImage1D/8} and {@link gl:texImage2D/9}
+%% .
+%%
+%% `?GL_MAX_UNIFORM_BUFFER_BINDINGS': `Params' returns one value, the maximum number
+%% of uniform buffer binding points on the context, which must be at least 36.
+%%
+%% `?GL_MAX_UNIFORM_BLOCK_SIZE': `Params' returns one value, the maximum size in
+%% basic machine units of a uniform block, which must be at least 16384.
+%%
+%% `?GL_MAX_VARYING_COMPONENTS': `Params' returns one value, the number components
+%% for varying variables, which must be at least 60.
+%%
+%% `?GL_MAX_VARYING_VECTORS': `Params' returns one value, the number 4-vectors
+%% for varying variables, which is equal to the value of `?GL_MAX_VARYING_COMPONENTS'
+%% and must be at least 15.
+%%
+%% `?GL_MAX_VARYING_FLOATS': `Params' returns one value, the maximum number of
+%% interpolators available for processing varying variables used by vertex and fragment shaders.
+%% This value represents the number of individual floating-point values that can be interpolated;
+%% varying variables declared as vectors, matrices, and arrays will all consume multiple
+%% interpolators. The value must be at least 32.
+%%
+%% `?GL_MAX_VERTEX_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
+%% number of atomic counters available to vertex shaders.
+%%
+%% `?GL_MAX_VERTEX_ATTRIBS': `Params' returns one value, the maximum number of
+%% 4-component generic vertex attributes accessible to a vertex shader. The value must be
+%% at least 16. See {@link gl:vertexAttrib1d/2} .
+%%
+%% `?GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum
+%% supported texture image units that can be used to access texture maps from the vertex
+%% shader. The value may be at least 16. See {@link gl:activeTexture/1} .
+%%
+%% `?GL_MAX_VERTEX_UNIFORM_COMPONENTS': `Params' returns one value, the maximum
+%% number of individual floating-point, integer, or boolean values that can be held in uniform
+%% variable storage for a vertex shader. The value must be at least 1024. See {@link gl:uniform1f/2}
+%% .
+%%
+%% `?GL_MAX_VERTEX_UNIFORM_VECTORS': `Params' returns one value, the maximum number
+%% of 4-vectors that may be held in uniform variable storage for the vertex shader. The value
+%% of `?GL_MAX_VERTEX_UNIFORM_VECTORS' is equal to the value of `?GL_MAX_VERTEX_UNIFORM_COMPONENTS'
+%% and must be at least 256.
+%%
+%% `?GL_MAX_VERTEX_OUTPUT_COMPONENTS': `Params' returns one value, the maximum
+%% number of components of output written by a vertex shader, which must be at least 64.
+%%
+%% `?GL_MAX_VERTEX_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
+%% of uniform blocks per vertex shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3}
+%% .
+%%
+%% `?GL_MAX_VIEWPORT_DIMS': `Params' returns two values: the maximum supported
+%% width and height of the viewport. These must be at least as large as the visible dimensions
+%% of the display being rendered to. See {@link gl:viewport/4} .
+%%
+%% `?GL_MAX_VIEWPORTS': `Params' returns one value, the maximum number of simultaneous
+%% viewports that are supported. The value must be at least 16. See {@link gl:viewportIndexedf/5}
+%% .
+%%
+%% `?GL_MINOR_VERSION': `Params' returns one value, the minor version number of
+%% the OpenGL API supported by the current context.
+%%
+%% `?GL_NUM_COMPRESSED_TEXTURE_FORMATS': `Params' returns a single integer value
+%% indicating the number of available compressed texture formats. The minimum value is 4.
+%% See {@link gl:compressedTexImage2D/8} .
+%%
+%% `?GL_NUM_EXTENSIONS': `Params' returns one value, the number of extensions supported
+%% by the GL implementation for the current context. See {@link gl:getString/1} .
+%%
+%% `?GL_NUM_PROGRAM_BINARY_FORMATS': `Params' returns one value, the number of
+%% program binary formats supported by the implementation.
+%%
+%% `?GL_NUM_SHADER_BINARY_FORMATS': `Params' returns one value, the number of binary
+%% shader formats supported by the implementation. If this value is greater than zero, then
+%% the implementation supports loading binary shaders. If it is zero, then the loading of
+%% binary shaders by the implementation is not supported.
+%%
+%% `?GL_PACK_ALIGNMENT': `Params' returns one value, the byte alignment used for
+%% writing pixel data to memory. The initial value is 4. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_PACK_IMAGE_HEIGHT': `Params' returns one value, the image height used for
+%% writing pixel data to memory. The initial value is 0. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_PACK_LSB_FIRST': `Params' returns a single boolean value indicating whether
+%% single-bit pixels being written to memory are written first to the least significant bit
+%% of each unsigned byte. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
+%%
+%%
+%% `?GL_PACK_ROW_LENGTH': `Params' returns one value, the row length used for writing
+%% pixel data to memory. The initial value is 0. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_PACK_SKIP_IMAGES': `Params' returns one value, the number of pixel images
+%% skipped before the first pixel is written into memory. The initial value is 0. See {@link gl:pixelStoref/2}
+%% .
+%%
+%% `?GL_PACK_SKIP_PIXELS': `Params' returns one value, the number of pixel locations
+%% skipped before the first pixel is written into memory. The initial value is 0. See {@link gl:pixelStoref/2}
+%% .
+%%
+%% `?GL_PACK_SKIP_ROWS': `Params' returns one value, the number of rows of pixel
+%% locations skipped before the first pixel is written into memory. The initial value is
+%% 0. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_PACK_SWAP_BYTES': `Params' returns a single boolean value indicating whether
+%% the bytes of two-byte and four-byte pixel indices and components are swapped before being
+%% written to memory. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_PIXEL_PACK_BUFFER_BINDING': `Params' returns a single value, the name of
+%% the buffer object currently bound to the target `?GL_PIXEL_PACK_BUFFER'. If no buffer
+%% object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2}
+%% .
+%%
+%% `?GL_PIXEL_UNPACK_BUFFER_BINDING': `Params' returns a single value, the name
+%% of the buffer object currently bound to the target `?GL_PIXEL_UNPACK_BUFFER'. If
+%% no buffer object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2}
+%% .
+%%
+%% `?GL_POINT_FADE_THRESHOLD_SIZE': `Params' returns one value, the point size
+%% threshold for determining the point size. See {@link gl:pointParameterf/2} .
+%%
+%% `?GL_PRIMITIVE_RESTART_INDEX': `Params' returns one value, the current primitive
+%% restart index. The initial value is 0. See {@link gl:primitiveRestartIndex/1} .
+%%
+%% `?GL_PROGRAM_BINARY_FORMATS': `Params' an array of `?GL_NUM_PROGRAM_BINARY_FORMATS'
+%% values, indicating the proram binary formats supported by the implementation.
+%%
+%% `?GL_PROGRAM_PIPELINE_BINDING': `Params' a single value, the name of the currently
+%% bound program pipeline object, or zero if no program pipeline object is bound. See {@link gl:bindProgramPipeline/1}
+%% .
+%%
+%% `?GL_PROVOKING_VERTEX': `Params' returns one value, the currently selected provoking
+%% vertex convention. The initial value is `?GL_LAST_VERTEX_CONVENTION'. See {@link gl:provokingVertex/1}
+%% .
+%%
+%% `?GL_POINT_SIZE': `Params' returns one value, the point size as specified by {@link gl:pointSize/1}
+%% . The initial value is 1.
+%%
+%% `?GL_POINT_SIZE_GRANULARITY': `Params' returns one value, the size difference
+%% between adjacent supported sizes for antialiased points. See {@link gl:pointSize/1} .
+%%
+%% `?GL_POINT_SIZE_RANGE': `Params' returns two values: the smallest and largest
+%% supported sizes for antialiased points. The smallest size must be at most 1, and the largest
+%% size must be at least 1. See {@link gl:pointSize/1} .
+%%
+%% `?GL_POLYGON_OFFSET_FACTOR': `Params' returns one value, the scaling factor
+%% used to determine the variable offset that is added to the depth value of each fragment
+%% generated when a polygon is rasterized. The initial value is 0. See {@link gl:polygonOffset/2}
+%% .
+%%
+%% `?GL_POLYGON_OFFSET_UNITS': `Params' returns one value. This value is multiplied
+%% by an implementation-specific value and then added to the depth value of each fragment
+%% generated when a polygon is rasterized. The initial value is 0. See {@link gl:polygonOffset/2}
+%% .
+%%
+%% `?GL_POLYGON_OFFSET_FILL': `Params' returns a single boolean value indicating
+%% whether polygon offset is enabled for polygons in fill mode. The initial value is `?GL_FALSE'
+%% . See {@link gl:polygonOffset/2} .
+%%
+%% `?GL_POLYGON_OFFSET_LINE': `Params' returns a single boolean value indicating
+%% whether polygon offset is enabled for polygons in line mode. The initial value is `?GL_FALSE'
+%% . See {@link gl:polygonOffset/2} .
+%%
+%% `?GL_POLYGON_OFFSET_POINT': `Params' returns a single boolean value indicating
+%% whether polygon offset is enabled for polygons in point mode. The initial value is `?GL_FALSE'
+%% . See {@link gl:polygonOffset/2} .
+%%
+%% `?GL_POLYGON_SMOOTH': `Params' returns a single boolean value indicating whether
+%% antialiasing of polygons is enabled. The initial value is `?GL_FALSE'. See {@link gl:polygonMode/2}
+%% .
+%%
+%% `?GL_POLYGON_SMOOTH_HINT': `Params' returns one value, a symbolic constant indicating
+%% the mode of the polygon antialiasing hint. The initial value is `?GL_DONT_CARE'.
+%% See {@link gl:hint/2} .
+%%
+%% `?GL_READ_BUFFER': `Params' returns one value, a symbolic constant indicating
+%% which color buffer is selected for reading. The initial value is `?GL_BACK' if there
+%% is a back buffer, otherwise it is `?GL_FRONT'. See {@link gl:readPixels/7} .
+%%
+%% `?GL_RENDERBUFFER_BINDING': `Params' returns a single value, the name of the
+%% renderbuffer object currently bound to the target `?GL_RENDERBUFFER'. If no renderbuffer
+%% object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindRenderbuffer/2}
+%% .
+%%
+%% `?GL_SAMPLE_BUFFERS': `Params' returns a single integer value indicating the
+%% number of sample buffers associated with the framebuffer. See {@link gl:sampleCoverage/2} .
+%%
+%%
+%% `?GL_SAMPLE_COVERAGE_VALUE': `Params' returns a single positive floating-point
+%% value indicating the current sample coverage value. See {@link gl:sampleCoverage/2} .
+%%
+%% `?GL_SAMPLE_COVERAGE_INVERT': `Params' returns a single boolean value indicating
+%% if the temporary coverage value should be inverted. See {@link gl:sampleCoverage/2} .
+%%
+%% `?GL_SAMPLER_BINDING': `Params' returns a single value, the name of the sampler
+%% object currently bound to the active texture unit. The initial value is 0. See {@link gl:bindSampler/2}
+%% .
+%%
+%% `?GL_SAMPLES': `Params' returns a single integer value indicating the coverage
+%% mask size. See {@link gl:sampleCoverage/2} .
+%%
+%% `?GL_SCISSOR_BOX': `Params' returns four values: the x and y window coordinates
+%% of the scissor box, followed by its width and height. Initially the x and y window
+%% coordinates are both 0 and the width and height are set to the size of the window. See {@link gl:scissor/4}
+%% .
+%%
+%% `?GL_SCISSOR_TEST': `Params' returns a single boolean value indicating whether
+%% scissoring is enabled. The initial value is `?GL_FALSE'. See {@link gl:scissor/4} .
+%%
+%% `?GL_SHADER_COMPILER': `Params' returns a single boolean value indicating whether
+%% an online shader compiler is present in the implementation. All desktop OpenGL implementations
+%% must support online shader compilations, and therefore the value of `?GL_SHADER_COMPILER'
+%% will always be `?GL_TRUE'.
+%%
+%% `?GL_SMOOTH_LINE_WIDTH_RANGE': `Params' returns a pair of values indicating
+%% the range of widths supported for smooth (antialiased) lines. See {@link gl:lineWidth/1} .
+%%
+%% `?GL_SMOOTH_LINE_WIDTH_GRANULARITY': `Params' returns a single value indicating
+%% the level of quantization applied to smooth line width parameters.
+%%
+%% `?GL_STENCIL_BACK_FAIL': `Params' returns one value, a symbolic constant indicating
+%% what action is taken for back-facing polygons when the stencil test fails. The initial
+%% value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4} .
+%%
+%% `?GL_STENCIL_BACK_FUNC': `Params' returns one value, a symbolic constant indicating
+%% what function is used for back-facing polygons to compare the stencil reference value
+%% with the stencil buffer value. The initial value is `?GL_ALWAYS'. See {@link gl:stencilFuncSeparate/4}
+%% .
+%%
+%% `?GL_STENCIL_BACK_PASS_DEPTH_FAIL': `Params' returns one value, a symbolic constant
+%% indicating what action is taken for back-facing polygons when the stencil test passes,
+%% but the depth test fails. The initial value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4}
+%% .
+%%
+%% `?GL_STENCIL_BACK_PASS_DEPTH_PASS': `Params' returns one value, a symbolic constant
+%% indicating what action is taken for back-facing polygons when the stencil test passes
+%% and the depth test passes. The initial value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4}
+%% .
+%%
+%% `?GL_STENCIL_BACK_REF': `Params' returns one value, the reference value that
+%% is compared with the contents of the stencil buffer for back-facing polygons. The initial
+%% value is 0. See {@link gl:stencilFuncSeparate/4} .
+%%
+%% `?GL_STENCIL_BACK_VALUE_MASK': `Params' returns one value, the mask that is
+%% used for back-facing polygons to mask both the stencil reference value and the stencil
+%% buffer value before they are compared. The initial value is all 1's. See {@link gl:stencilFuncSeparate/4}
+%% .
+%%
+%% `?GL_STENCIL_BACK_WRITEMASK': `Params' returns one value, the mask that controls
+%% writing of the stencil bitplanes for back-facing polygons. The initial value is all 1's.
+%% See {@link gl:stencilMaskSeparate/2} .
+%%
+%% `?GL_STENCIL_CLEAR_VALUE': `Params' returns one value, the index to which the
+%% stencil bitplanes are cleared. The initial value is 0. See {@link gl:clearStencil/1} .
+%%
+%% `?GL_STENCIL_FAIL': `Params' returns one value, a symbolic constant indicating
+%% what action is taken when the stencil test fails. The initial value is `?GL_KEEP'.
+%% See {@link gl:stencilOp/3} . This stencil state only affects non-polygons and front-facing
+%% polygons. Back-facing polygons use separate stencil state. See {@link gl:stencilOpSeparate/4}
+%% .
+%%
+%% `?GL_STENCIL_FUNC': `Params' returns one value, a symbolic constant indicating
+%% what function is used to compare the stencil reference value with the stencil buffer value.
+%% The initial value is `?GL_ALWAYS'. See {@link gl:stencilFunc/3} . This stencil state
+%% only affects non-polygons and front-facing polygons. Back-facing polygons use separate
+%% stencil state. See {@link gl:stencilFuncSeparate/4} .
+%%
+%% `?GL_STENCIL_PASS_DEPTH_FAIL': `Params' returns one value, a symbolic constant
+%% indicating what action is taken when the stencil test passes, but the depth test fails.
+%% The initial value is `?GL_KEEP'. See {@link gl:stencilOp/3} . This stencil state only
+%% affects non-polygons and front-facing polygons. Back-facing polygons use separate stencil
+%% state. See {@link gl:stencilOpSeparate/4} .
+%%
+%% `?GL_STENCIL_PASS_DEPTH_PASS': `Params' returns one value, a symbolic constant
+%% indicating what action is taken when the stencil test passes and the depth test passes.
+%% The initial value is `?GL_KEEP'. See {@link gl:stencilOp/3} . This stencil state only
+%% affects non-polygons and front-facing polygons. Back-facing polygons use separate stencil
+%% state. See {@link gl:stencilOpSeparate/4} .
+%%
+%% `?GL_STENCIL_REF': `Params' returns one value, the reference value that is compared
+%% with the contents of the stencil buffer. The initial value is 0. See {@link gl:stencilFunc/3}
+%% . This stencil state only affects non-polygons and front-facing polygons. Back-facing
+%% polygons use separate stencil state. See {@link gl:stencilFuncSeparate/4} .
+%%
+%% `?GL_STENCIL_TEST': `Params' returns a single boolean value indicating whether
+%% stencil testing of fragments is enabled. The initial value is `?GL_FALSE'. See {@link gl:stencilFunc/3}
+%% and {@link gl:stencilOp/3} .
+%%
+%% `?GL_STENCIL_VALUE_MASK': `Params' returns one value, the mask that is used
+%% to mask both the stencil reference value and the stencil buffer value before they are
+%% compared. The initial value is all 1's. See {@link gl:stencilFunc/3} . This stencil state
+%% only affects non-polygons and front-facing polygons. Back-facing polygons use separate
+%% stencil state. See {@link gl:stencilFuncSeparate/4} .
+%%
+%% `?GL_STENCIL_WRITEMASK': `Params' returns one value, the mask that controls
+%% writing of the stencil bitplanes. The initial value is all 1's. See {@link gl:stencilMask/1}
+%% . This stencil state only affects non-polygons and front-facing polygons. Back-facing
+%% polygons use separate stencil state. See {@link gl:stencilMaskSeparate/2} .
+%%
+%% `?GL_STEREO': `Params' returns a single boolean value indicating whether stereo
+%% buffers (left and right) are supported.
+%%
+%% `?GL_SUBPIXEL_BITS': `Params' returns one value, an estimate of the number of
+%% bits of subpixel resolution that are used to position rasterized geometry in window coordinates.
+%% The value must be at least 4.
+%%
+%% `?GL_TEXTURE_BINDING_1D': `Params' returns a single value, the name of the texture
+%% currently bound to the target `?GL_TEXTURE_1D'. The initial value is 0. See {@link gl:bindTexture/2}
+%% .
+%%
+%% `?GL_TEXTURE_BINDING_1D_ARRAY': `Params' returns a single value, the name of
+%% the texture currently bound to the target `?GL_TEXTURE_1D_ARRAY'. The initial value
+%% is 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_BINDING_2D': `Params' returns a single value, the name of the texture
+%% currently bound to the target `?GL_TEXTURE_2D'. The initial value is 0. See {@link gl:bindTexture/2}
+%% .
+%%
+%% `?GL_TEXTURE_BINDING_2D_ARRAY': `Params' returns a single value, the name of
+%% the texture currently bound to the target `?GL_TEXTURE_2D_ARRAY'. The initial value
+%% is 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_BINDING_2D_MULTISAMPLE': `Params' returns a single value, the name
+%% of the texture currently bound to the target `?GL_TEXTURE_2D_MULTISAMPLE'. The initial
+%% value is 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY': `Params' returns a single value,
+%% the name of the texture currently bound to the target `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY'
+%% . The initial value is 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_BINDING_3D': `Params' returns a single value, the name of the texture
+%% currently bound to the target `?GL_TEXTURE_3D'. The initial value is 0. See {@link gl:bindTexture/2}
+%% .
+%%
+%% `?GL_TEXTURE_BINDING_BUFFER': `Params' returns a single value, the name of the
+%% texture currently bound to the target `?GL_TEXTURE_BUFFER'. The initial value is
+%% 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_BINDING_CUBE_MAP': `Params' returns a single value, the name of
+%% the texture currently bound to the target `?GL_TEXTURE_CUBE_MAP'. The initial value
+%% is 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_BINDING_RECTANGLE': `Params' returns a single value, the name of
+%% the texture currently bound to the target `?GL_TEXTURE_RECTANGLE'. The initial value
+%% is 0. See {@link gl:bindTexture/2} .
+%%
+%% `?GL_TEXTURE_COMPRESSION_HINT': `Params' returns a single value indicating the
+%% mode of the texture compression hint. The initial value is `?GL_DONT_CARE'.
+%%
+%% `?GL_TEXTURE_BUFFER_BINDING': `Params' returns a single value, the name of the
+%% texture buffer object currently bound. The initial value is 0. See {@link gl:bindBuffer/2} .
+%%
+%%
+%% `?GL_TIMESTAMP': `Params' returns a single value, the 64-bit value of the current
+%% GL time. See {@link gl:queryCounter/2} .
+%%
+%% `?GL_TRANSFORM_FEEDBACK_BUFFER_BINDING': When used with non-indexed variants of ``gl:get''
+%% (such as ``gl:getIntegerv''), `Params' returns a single value, the name of the
+%% buffer object currently bound to the target `?GL_TRANSFORM_FEEDBACK_BUFFER'. If no
+%% buffer object is bound to this target, 0 is returned. When used with indexed variants of ``gl:get''
+%% (such as ``gl:getIntegeri_v''), `Params' returns a single value, the name of the
+%% buffer object bound to the indexed transform feedback attribute stream. The initial value
+%% is 0 for all targets. See {@link gl:bindBuffer/2} , {@link gl:bindBufferBase/3} , and {@link gl:bindBufferRange/5}
+%% .
+%%
+%% `?GL_TRANSFORM_FEEDBACK_BUFFER_START': When used with indexed variants of ``gl:get''
+%% (such as ``gl:getInteger64i_v''), `Params' returns a single value, the start offset
+%% of the binding range for each transform feedback attribute stream. The initial value is
+%% 0 for all streams. See {@link gl:bindBufferRange/5} .
+%%
+%% `?GL_TRANSFORM_FEEDBACK_BUFFER_SIZE': When used with indexed variants of ``gl:get''
+%% (such as ``gl:getInteger64i_v''), `Params' returns a single value, the size of
+%% the binding range for each transform feedback attribute stream. The initial value is 0
+%% for all streams. See {@link gl:bindBufferRange/5} .
+%%
+%% `?GL_UNIFORM_BUFFER_BINDING': When used with non-indexed variants of ``gl:get''
+%% (such as ``gl:getIntegerv''), `Params' returns a single value, the name of the
+%% buffer object currently bound to the target `?GL_UNIFORM_BUFFER'. If no buffer object
+%% is bound to this target, 0 is returned. When used with indexed variants of ``gl:get''
+%% (such as ``gl:getIntegeri_v''), `Params' returns a single value, the name of the
+%% buffer object bound to the indexed uniform buffer binding point. The initial value is
+%% 0 for all targets. See {@link gl:bindBuffer/2} , {@link gl:bindBufferBase/3} , and {@link gl:bindBufferRange/5}
+%% .
+%%
+%% `?GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT': `Params' returns a single value, the
+%% minimum required alignment for uniform buffer sizes and offset. The initial value is 1.
+%% See {@link gl:uniformBlockBinding/3} .
+%%
+%% `?GL_UNIFORM_BUFFER_SIZE': When used with indexed variants of ``gl:get'' (such
+%% as ``gl:getInteger64i_v''), `Params' returns a single value, the size of the binding
+%% range for each indexed uniform buffer binding. The initial value is 0 for all bindings.
+%% See {@link gl:bindBufferRange/5} .
+%%
+%% `?GL_UNIFORM_BUFFER_START': When used with indexed variants of ``gl:get'' (such
+%% as ``gl:getInteger64i_v''), `Params' returns a single value, the start offset of
+%% the binding range for each indexed uniform buffer binding. The initial value is 0 for
+%% all bindings. See {@link gl:bindBufferRange/5} .
+%%
+%% `?GL_UNPACK_ALIGNMENT': `Params' returns one value, the byte alignment used
+%% for reading pixel data from memory. The initial value is 4. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_UNPACK_IMAGE_HEIGHT': `Params' returns one value, the image height used
+%% for reading pixel data from memory. The initial is 0. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_UNPACK_LSB_FIRST': `Params' returns a single boolean value indicating whether
+%% single-bit pixels being read from memory are read first from the least significant bit
+%% of each unsigned byte. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
+%%
+%%
+%% `?GL_UNPACK_ROW_LENGTH': `Params' returns one value, the row length used for
+%% reading pixel data from memory. The initial value is 0. See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_UNPACK_SKIP_IMAGES': `Params' returns one value, the number of pixel images
+%% skipped before the first pixel is read from memory. The initial value is 0. See {@link gl:pixelStoref/2}
+%% .
+%%
+%% `?GL_UNPACK_SKIP_PIXELS': `Params' returns one value, the number of pixel locations
+%% skipped before the first pixel is read from memory. The initial value is 0. See {@link gl:pixelStoref/2}
+%% .
+%%
+%% `?GL_UNPACK_SKIP_ROWS': `Params' returns one value, the number of rows of pixel
+%% locations skipped before the first pixel is read from memory. The initial value is 0.
+%% See {@link gl:pixelStoref/2} .
+%%
+%% `?GL_UNPACK_SWAP_BYTES': `Params' returns a single boolean value indicating
+%% whether the bytes of two-byte and four-byte pixel indices and components are swapped after
+%% being read from memory. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
+%%
+%%
+%% `?GL_VERTEX_PROGRAM_POINT_SIZE': `Params' returns a single boolean value indicating
+%% whether vertex program point size mode is enabled. If enabled, and a vertex shader is
+%% active, then the point size is taken from the shader built-in gl_PointSize. If disabled,
+%% and a vertex shader is active, then the point size is taken from the point state as specified
+%% by {@link gl:pointSize/1} . The initial value is `?GL_FALSE'.
+%%
+%% `?GL_VIEWPORT': When used with non-indexed variants of ``gl:get'' (such as ``gl:getIntegerv''
+%% ), `Params' returns four values: the x and y window coordinates of the viewport,
+%% followed by its width and height. Initially the x and y window coordinates are both
+%% set to 0, and the width and height are set to the width and height of the window into
+%% which the GL will do its rendering. See {@link gl:viewport/4} . When used with indexed
+%% variants of ``gl:get'' (such as ``gl:getIntegeri_v''), `Params' returns four
+%% values: the x and y window coordinates of the indexed viewport, followed by its width
+%% and height. Initially the x and y window coordinates are both set to 0, and the width
+%% and height are set to the width and height of the window into which the GL will do its
+%% rendering. See {@link gl:viewportIndexedf/5} .
+%%
+%% `?GL_VIEWPORT_BOUNDS_RANGE': `Params' returns two values, the minimum and maximum
+%% viewport bounds range. The minimum range should be at least [-32768, 32767].
+%%
+%% `?GL_VIEWPORT_INDEX_PROVOKING_VERTEX': `Params' returns one value, the implementation
+%% dependent specifc vertex of a primitive that is used to select the viewport index. If
+%% the value returned is equivalent to `?GL_PROVOKING_VERTEX', then the vertex selection
+%% follows the convention specified by {@link gl:provokingVertex/1} . If the value returned
+%% is equivalent to `?GL_FIRST_VERTEX_CONVENTION', then the selection is always taken
+%% from the first vertex in the primitive. If the value returned is equivalent to `?GL_LAST_VERTEX_CONVENTION'
+%% , then the selection is always taken from the last vertex in the primitive. If the value
+%% returned is equivalent to `?GL_UNDEFINED_VERTEX', then the selection is not guaranteed
+%% to be taken from any specific vertex in the primitive.
+%%
+%% `?GL_VIEWPORT_SUBPIXEL_BITS': `Params' returns a single value, the number of
+%% bits of sub-pixel precision which the GL uses to interpret the floating point viewport
+%% bounds. The minimum value is 0.
+%%
+%% Many of the boolean parameters can also be queried more easily using {@link gl:isEnabled/1}
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml">external</a> documentation.
+-spec getBooleanv(Pname) -> [0|1] when Pname :: enum().
+getBooleanv(Pname) ->
+ call(5065, <<Pname:?GLenum>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3ui(Red,Green,Blue)
--spec color3uiv({integer(),integer(),integer()}) -> ok.
-color3uiv({Red,Green,Blue}) -> color3ui(Red,Green,Blue).
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getDoublev(Pname) -> [float()] when Pname :: enum().
+getDoublev(Pname) ->
+ call(5066, <<Pname:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color3us(integer(),integer(),integer()) -> ok.
-color3us(Red,Green,Blue) ->
- cast(5062, <<Red:?GLushort,Green:?GLushort,Blue:?GLushort>>).
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getFloatv(Pname) -> [float()] when Pname :: enum().
+getFloatv(Pname) ->
+ call(5067, <<Pname:?GLenum>>).
-%% @spec ({Red,Green,Blue}) -> ok
-%% @equiv color3us(Red,Green,Blue)
--spec color3usv({integer(),integer(),integer()}) -> ok.
-color3usv({Red,Green,Blue}) -> color3us(Red,Green,Blue).
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getIntegerv(Pname) -> [integer()] when Pname :: enum().
+getIntegerv(Pname) ->
+ call(5068, <<Pname:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer(),Alpha::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4b(integer(),integer(),integer(),integer()) -> ok.
-color4b(Red,Green,Blue,Alpha) ->
- cast(5063, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte,Alpha:?GLbyte>>).
+%% @doc Push and pop the server attribute stack
+%%
+%% ``gl:pushAttrib'' takes one argument, a mask that indicates which groups of state variables
+%% to save on the attribute stack. Symbolic constants are used to set bits in the mask. `Mask'
+%% is typically constructed by specifying the bitwise-or of several of these constants
+%% together. The special mask `?GL_ALL_ATTRIB_BITS' can be used to save all stackable
+%% states.
+%%
+%% The symbolic mask constants and their associated GL state are as follows (the second
+%% column lists which attributes are saved):
+%%
+%% <table><tbody><tr><td>`?GL_ACCUM_BUFFER_BIT'</td><td> Accumulation buffer clear value
+%% </td></tr><tr><td>`?GL_COLOR_BUFFER_BIT'</td><td>`?GL_ALPHA_TEST' enable bit </td>
+%% </tr><tr><td></td><td> Alpha test function and reference value </td></tr><tr><td></td><td>
+%% `?GL_BLEND' enable bit </td></tr><tr><td></td><td> Blending source and destination
+%% functions </td></tr><tr><td></td><td> Constant blend color </td></tr><tr><td></td><td>
+%% Blending equation </td></tr><tr><td></td><td>`?GL_DITHER' enable bit </td></tr><tr><td>
+%% </td><td>`?GL_DRAW_BUFFER' setting </td></tr><tr><td></td><td>`?GL_COLOR_LOGIC_OP'
+%% enable bit </td></tr><tr><td></td><td>`?GL_INDEX_LOGIC_OP' enable bit </td></tr><tr>
+%% <td></td><td> Logic op function </td></tr><tr><td></td><td> Color mode and index mode
+%% clear values </td></tr><tr><td></td><td> Color mode and index mode writemasks </td></tr><tr>
+%% <td>`?GL_CURRENT_BIT'</td><td> Current RGBA color </td></tr><tr><td></td><td> Current
+%% color index </td></tr><tr><td></td><td> Current normal vector </td></tr><tr><td></td><td>
+%% Current texture coordinates </td></tr><tr><td></td><td> Current raster position </td></tr>
+%% <tr><td></td><td>`?GL_CURRENT_RASTER_POSITION_VALID' flag </td></tr><tr><td></td><td>
+%% RGBA color associated with current raster position </td></tr><tr><td></td><td> Color
+%% index associated with current raster position </td></tr><tr><td></td><td> Texture coordinates
+%% associated with current raster position </td></tr><tr><td></td><td>`?GL_EDGE_FLAG'
+%% flag </td></tr><tr><td>`?GL_DEPTH_BUFFER_BIT'</td><td>`?GL_DEPTH_TEST' enable
+%% bit </td></tr><tr><td></td><td> Depth buffer test function </td></tr><tr><td></td><td>
+%% Depth buffer clear value </td></tr><tr><td></td><td>`?GL_DEPTH_WRITEMASK' enable
+%% bit </td></tr><tr><td>`?GL_ENABLE_BIT'</td><td>`?GL_ALPHA_TEST' flag </td></tr><tr>
+%% <td></td><td>`?GL_AUTO_NORMAL' flag </td></tr><tr><td></td><td>`?GL_BLEND' flag
+%% </td></tr><tr><td></td><td> Enable bits for the user-definable clipping planes </td></tr><tr>
+%% <td></td><td>`?GL_COLOR_MATERIAL'</td></tr><tr><td></td><td>`?GL_CULL_FACE'
+%% flag </td></tr><tr><td></td><td>`?GL_DEPTH_TEST' flag </td></tr><tr><td></td><td>`?GL_DITHER'
+%% flag </td></tr><tr><td></td><td>`?GL_FOG' flag </td></tr><tr><td></td><td>`?GL_LIGHT'
+%% `i' where `?0' &lt;= `i' &lt; `?GL_MAX_LIGHTS'</td></tr>
+%% <tr><td></td><td>`?GL_LIGHTING' flag </td></tr><tr><td></td><td>`?GL_LINE_SMOOTH'
+%% flag </td></tr><tr><td></td><td>`?GL_LINE_STIPPLE' flag </td></tr><tr><td></td><td>`?GL_COLOR_LOGIC_OP'
+%% flag </td></tr><tr><td></td><td>`?GL_INDEX_LOGIC_OP' flag </td></tr><tr><td></td><td>
+%% `?GL_MAP1_'`x' where `x' is a map type </td></tr><tr><td></td><td>`?GL_MAP2_'
+%% `x' where `x' is a map type </td></tr><tr><td></td><td>`?GL_MULTISAMPLE'
+%% flag </td></tr><tr><td></td><td>`?GL_NORMALIZE' flag </td></tr><tr><td></td><td>`?GL_POINT_SMOOTH'
+%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_LINE' flag </td></tr><tr><td></td>
+%% <td>`?GL_POLYGON_OFFSET_FILL' flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_POINT'
+%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH' flag </td></tr><tr><td></td><td>
+%% `?GL_POLYGON_STIPPLE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'
+%% flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_ONE' flag </td></tr><tr><td></td>
+%% <td>`?GL_SAMPLE_COVERAGE' flag </td></tr><tr><td></td><td>`?GL_SCISSOR_TEST'
+%% flag </td></tr><tr><td></td><td>`?GL_STENCIL_TEST' flag </td></tr><tr><td></td><td>`?GL_TEXTURE_1D'
+%% flag </td></tr><tr><td></td><td>`?GL_TEXTURE_2D' flag </td></tr><tr><td></td><td>`?GL_TEXTURE_3D'
+%% flag </td></tr><tr><td></td><td> Flags `?GL_TEXTURE_GEN_'`x' where `x'
+%% is S, T, R, or Q </td></tr><tr><td>`?GL_EVAL_BIT'</td><td>`?GL_MAP1_'`x'
+%% enable bits, where `x' is a map type </td></tr><tr><td></td><td>`?GL_MAP2_'`x'
+%% enable bits, where `x' is a map type </td></tr><tr><td></td><td> 1D grid endpoints
+%% and divisions </td></tr><tr><td></td><td> 2D grid endpoints and divisions </td></tr><tr><td>
+%% </td><td>`?GL_AUTO_NORMAL' enable bit </td></tr><tr><td>`?GL_FOG_BIT'</td><td>`?GL_FOG'
+%% enable bit </td></tr><tr><td></td><td> Fog color </td></tr><tr><td></td><td> Fog density
+%% </td></tr><tr><td></td><td> Linear fog start </td></tr><tr><td></td><td> Linear fog end </td>
+%% </tr><tr><td></td><td> Fog index </td></tr><tr><td></td><td>`?GL_FOG_MODE' value </td>
+%% </tr><tr><td>`?GL_HINT_BIT'</td><td>`?GL_PERSPECTIVE_CORRECTION_HINT' setting </td>
+%% </tr><tr><td></td><td>`?GL_POINT_SMOOTH_HINT' setting </td></tr><tr><td></td><td>`?GL_LINE_SMOOTH_HINT'
+%% setting </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH_HINT' setting </td></tr><tr><td>
+%% </td><td>`?GL_FOG_HINT' setting </td></tr><tr><td></td><td>`?GL_GENERATE_MIPMAP_HINT'
+%% setting </td></tr><tr><td></td><td>`?GL_TEXTURE_COMPRESSION_HINT' setting </td></tr>
+%% <tr><td>`?GL_LIGHTING_BIT'</td><td>`?GL_COLOR_MATERIAL' enable bit </td></tr><tr>
+%% <td></td><td>`?GL_COLOR_MATERIAL_FACE' value </td></tr><tr><td></td><td> Color material
+%% parameters that are tracking the current color </td></tr><tr><td></td><td> Ambient scene
+%% color </td></tr><tr><td></td><td>`?GL_LIGHT_MODEL_LOCAL_VIEWER' value </td></tr><tr><td>
+%% </td><td>`?GL_LIGHT_MODEL_TWO_SIDE' setting </td></tr><tr><td></td><td>`?GL_LIGHTING'
+%% enable bit </td></tr><tr><td></td><td> Enable bit for each light </td></tr><tr><td></td><td>
+%% Ambient, diffuse, and specular intensity for each light </td></tr><tr><td></td><td> Direction,
+%% position, exponent, and cutoff angle for each light </td></tr><tr><td></td><td> Constant,
+%% linear, and quadratic attenuation factors for each light </td></tr><tr><td></td><td> Ambient,
+%% diffuse, specular, and emissive color for each material </td></tr><tr><td></td><td> Ambient,
+%% diffuse, and specular color indices for each material </td></tr><tr><td></td><td> Specular
+%% exponent for each material </td></tr><tr><td></td><td>`?GL_SHADE_MODEL' setting </td>
+%% </tr><tr><td>`?GL_LINE_BIT'</td><td>`?GL_LINE_SMOOTH' flag </td></tr><tr><td></td>
+%% <td>`?GL_LINE_STIPPLE' enable bit </td></tr><tr><td></td><td> Line stipple pattern
+%% and repeat counter </td></tr><tr><td></td><td> Line width </td></tr><tr><td>`?GL_LIST_BIT'
+%% </td><td>`?GL_LIST_BASE' setting </td></tr><tr><td>`?GL_MULTISAMPLE_BIT'</td><td>
+%% `?GL_MULTISAMPLE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'
+%% flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_ONE' flag </td></tr><tr><td></td>
+%% <td>`?GL_SAMPLE_COVERAGE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_COVERAGE_VALUE'
+%% value </td></tr><tr><td></td><td>`?GL_SAMPLE_COVERAGE_INVERT' value </td></tr><tr><td>
+%% `?GL_PIXEL_MODE_BIT'</td><td>`?GL_RED_BIAS' and `?GL_RED_SCALE' settings </td>
+%% </tr><tr><td></td><td>`?GL_GREEN_BIAS' and `?GL_GREEN_SCALE' values </td></tr><tr>
+%% <td></td><td>`?GL_BLUE_BIAS' and `?GL_BLUE_SCALE'</td></tr><tr><td></td><td>`?GL_ALPHA_BIAS'
+%% and `?GL_ALPHA_SCALE'</td></tr><tr><td></td><td>`?GL_DEPTH_BIAS' and `?GL_DEPTH_SCALE'
+%% </td></tr><tr><td></td><td>`?GL_INDEX_OFFSET' and `?GL_INDEX_SHIFT' values </td>
+%% </tr><tr><td></td><td>`?GL_MAP_COLOR' and `?GL_MAP_STENCIL' flags </td></tr><tr>
+%% <td></td><td>`?GL_ZOOM_X' and `?GL_ZOOM_Y' factors </td></tr><tr><td></td><td>`?GL_READ_BUFFER'
+%% setting </td></tr><tr><td>`?GL_POINT_BIT'</td><td>`?GL_POINT_SMOOTH' flag </td>
+%% </tr><tr><td></td><td> Point size </td></tr><tr><td>`?GL_POLYGON_BIT'</td><td>`?GL_CULL_FACE'
+%% enable bit </td></tr><tr><td></td><td>`?GL_CULL_FACE_MODE' value </td></tr><tr><td></td>
+%% <td>`?GL_FRONT_FACE' indicator </td></tr><tr><td></td><td>`?GL_POLYGON_MODE'
+%% setting </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH' flag </td></tr><tr><td></td><td>
+%% `?GL_POLYGON_STIPPLE' enable bit </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_FILL'
+%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_LINE' flag </td></tr><tr><td></td>
+%% <td>`?GL_POLYGON_OFFSET_POINT' flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_FACTOR'
+%% </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_UNITS'</td></tr><tr><td>`?GL_POLYGON_STIPPLE_BIT'
+%% </td><td> Polygon stipple image </td></tr><tr><td>`?GL_SCISSOR_BIT'</td><td>`?GL_SCISSOR_TEST'
+%% flag </td></tr><tr><td></td><td> Scissor box </td></tr><tr><td>`?GL_STENCIL_BUFFER_BIT'
+%% </td><td>`?GL_STENCIL_TEST' enable bit </td></tr><tr><td></td><td> Stencil function
+%% and reference value </td></tr><tr><td></td><td> Stencil value mask </td></tr><tr><td></td>
+%% <td> Stencil fail, pass, and depth buffer pass actions </td></tr><tr><td></td><td> Stencil
+%% buffer clear value </td></tr><tr><td></td><td> Stencil buffer writemask </td></tr><tr><td>
+%% `?GL_TEXTURE_BIT'</td><td> Enable bits for the four texture coordinates </td></tr><tr>
+%% <td></td><td> Border color for each texture image </td></tr><tr><td></td><td> Minification
+%% function for each texture image </td></tr><tr><td></td><td> Magnification function for
+%% each texture image </td></tr><tr><td></td><td> Texture coordinates and wrap mode for each
+%% texture image </td></tr><tr><td></td><td> Color and mode for each texture environment </td>
+%% </tr><tr><td></td><td> Enable bits `?GL_TEXTURE_GEN_'`x', `x' is S, T,
+%% R, and Q </td></tr><tr><td></td><td>`?GL_TEXTURE_GEN_MODE' setting for S, T, R, and
+%% Q </td></tr><tr><td></td><td> {@link gl:texGend/3} plane equations for S, T, R, and Q </td></tr>
+%% <tr><td></td><td> Current texture bindings (for example, `?GL_TEXTURE_BINDING_2D') </td>
+%% </tr><tr><td>`?GL_TRANSFORM_BIT'</td><td> Coefficients of the six clipping planes </td>
+%% </tr><tr><td></td><td> Enable bits for the user-definable clipping planes </td></tr><tr><td>
+%% </td><td>`?GL_MATRIX_MODE' value </td></tr><tr><td></td><td>`?GL_NORMALIZE'
+%% flag </td></tr><tr><td></td><td>`?GL_RESCALE_NORMAL' flag </td></tr><tr><td>`?GL_VIEWPORT_BIT'
+%% </td><td> Depth range (near and far) </td></tr><tr><td></td><td> Viewport origin and extent
+%% </td></tr></tbody></table>
+%%
+%% {@link gl:pushAttrib/1} restores the values of the state variables saved with the last ``gl:pushAttrib''
+%% command. Those not saved are left unchanged.
+%%
+%% It is an error to push attributes onto a full stack or to pop attributes off an empty
+%% stack. In either case, the error flag is set and no other change is made to GL state.
+%%
+%% Initially, the attribute stack is empty.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml">external</a> documentation.
+-spec pushAttrib(Mask) -> ok when Mask :: integer().
+pushAttrib(Mask) ->
+ cast(5069, <<Mask:?GLbitfield>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4b(Red,Green,Blue,Alpha)
--spec color4bv({integer(),integer(),integer(),integer()}) -> ok.
-color4bv({Red,Green,Blue,Alpha}) -> color4b(Red,Green,Blue,Alpha).
+%% @doc
+%% See {@link pushAttrib/1}
+-spec popAttrib() -> ok.
+popAttrib() ->
+ cast(5070, <<>>).
-%% @spec (Red::float(),Green::float(),Blue::float(),Alpha::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4d(float(),float(),float(),float()) -> ok.
-color4d(Red,Green,Blue,Alpha) ->
- cast(5064, <<Red:?GLdouble,Green:?GLdouble,Blue:?GLdouble,Alpha:?GLdouble>>).
+%% @doc Push and pop the client attribute stack
+%%
+%% ``gl:pushClientAttrib'' takes one argument, a mask that indicates which groups of client-state
+%% variables to save on the client attribute stack. Symbolic constants are used to set bits
+%% in the mask. `Mask' is typically constructed by specifying the bitwise-or of several
+%% of these constants together. The special mask `?GL_CLIENT_ALL_ATTRIB_BITS' can
+%% be used to save all stackable client state.
+%%
+%% The symbolic mask constants and their associated GL client state are as follows (the
+%% second column lists which attributes are saved):
+%%
+%% `?GL_CLIENT_PIXEL_STORE_BIT' Pixel storage modes `?GL_CLIENT_VERTEX_ARRAY_BIT'
+%% Vertex arrays (and enables)
+%%
+%% {@link gl:pushClientAttrib/1} restores the values of the client-state variables saved with
+%% the last ``gl:pushClientAttrib''. Those not saved are left unchanged.
+%%
+%% It is an error to push attributes onto a full client attribute stack or to pop attributes
+%% off an empty stack. In either case, the error flag is set, and no other change is made
+%% to GL state.
+%%
+%% Initially, the client attribute stack is empty.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml">external</a> documentation.
+-spec pushClientAttrib(Mask) -> ok when Mask :: integer().
+pushClientAttrib(Mask) ->
+ cast(5071, <<Mask:?GLbitfield>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4d(Red,Green,Blue,Alpha)
--spec color4dv({float(),float(),float(),float()}) -> ok.
-color4dv({Red,Green,Blue,Alpha}) -> color4d(Red,Green,Blue,Alpha).
+%% @doc
+%% See {@link pushClientAttrib/1}
+-spec popClientAttrib() -> ok.
+popClientAttrib() ->
+ cast(5072, <<>>).
-%% @spec (Red::float(),Green::float(),Blue::float(),Alpha::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4f(float(),float(),float(),float()) -> ok.
-color4f(Red,Green,Blue,Alpha) ->
- cast(5065, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat,Alpha:?GLfloat>>).
+%% @doc Set rasterization mode
+%%
+%% ``gl:renderMode'' sets the rasterization mode. It takes one argument, `Mode' , which
+%% can assume one of three predefined values:
+%%
+%% `?GL_RENDER': Render mode. Primitives are rasterized, producing pixel fragments,
+%% which are written into the frame buffer. This is the normal mode and also the default
+%% mode.
+%%
+%% `?GL_SELECT': Selection mode. No pixel fragments are produced, and no change to
+%% the frame buffer contents is made. Instead, a record of the names of primitives that would
+%% have been drawn if the render mode had been `?GL_RENDER' is returned in a select
+%% buffer, which must be created (see {@link gl:selectBuffer/2} ) before selection mode is
+%% entered.
+%%
+%% `?GL_FEEDBACK': Feedback mode. No pixel fragments are produced, and no change to
+%% the frame buffer contents is made. Instead, the coordinates and attributes of vertices
+%% that would have been drawn if the render mode had been `?GL_RENDER' is returned in
+%% a feedback buffer, which must be created (see {@link gl:feedbackBuffer/3} ) before feedback
+%% mode is entered.
+%%
+%% The return value of ``gl:renderMode'' is determined by the render mode at the time ``gl:renderMode''
+%% is called, rather than by `Mode' . The values returned for the three render modes
+%% are as follows:
+%%
+%% `?GL_RENDER': 0.
+%%
+%% `?GL_SELECT': The number of hit records transferred to the select buffer.
+%%
+%% `?GL_FEEDBACK': The number of values (not vertices) transferred to the feedback
+%% buffer.
+%%
+%% See the {@link gl:selectBuffer/2} and {@link gl:feedbackBuffer/3} reference pages for more
+%% details concerning selection and feedback operation.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderMode.xml">external</a> documentation.
+-spec renderMode(Mode) -> integer() when Mode :: enum().
+renderMode(Mode) ->
+ call(5073, <<Mode:?GLenum>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4f(Red,Green,Blue,Alpha)
--spec color4fv({float(),float(),float(),float()}) -> ok.
-color4fv({Red,Green,Blue,Alpha}) -> color4f(Red,Green,Blue,Alpha).
+%% @doc Return error information
+%%
+%% ``gl:getError'' returns the value of the error flag. Each detectable error is assigned
+%% a numeric code and symbolic name. When an error occurs, the error flag is set to the appropriate
+%% error code value. No other errors are recorded until ``gl:getError'' is called, the
+%% error code is returned, and the flag is reset to `?GL_NO_ERROR'. If a call to ``gl:getError''
+%% returns `?GL_NO_ERROR', there has been no detectable error since the last call to ``gl:getError''
+%% , or since the GL was initialized.
+%%
+%% To allow for distributed implementations, there may be several error flags. If any single
+%% error flag has recorded an error, the value of that flag is returned and that flag is
+%% reset to `?GL_NO_ERROR' when ``gl:getError'' is called. If more than one flag has
+%% recorded an error, ``gl:getError'' returns and clears an arbitrary error flag value.
+%% Thus, ``gl:getError'' should always be called in a loop, until it returns `?GL_NO_ERROR'
+%% , if all error flags are to be reset.
+%%
+%% Initially, all error flags are set to `?GL_NO_ERROR'.
+%%
+%% The following errors are currently defined:
+%%
+%% `?GL_NO_ERROR': No error has been recorded. The value of this symbolic constant
+%% is guaranteed to be 0.
+%%
+%% `?GL_INVALID_ENUM': An unacceptable value is specified for an enumerated argument.
+%% The offending command is ignored and has no other side effect than to set the error flag.
+%%
+%%
+%% `?GL_INVALID_VALUE': A numeric argument is out of range. The offending command is
+%% ignored and has no other side effect than to set the error flag.
+%%
+%% `?GL_INVALID_OPERATION': The specified operation is not allowed in the current state.
+%% The offending command is ignored and has no other side effect than to set the error flag.
+%%
+%%
+%% `?GL_INVALID_FRAMEBUFFER_OPERATION': The framebuffer object is not complete. The
+%% offending command is ignored and has no other side effect than to set the error flag.
+%%
+%% `?GL_OUT_OF_MEMORY': There is not enough memory left to execute the command. The
+%% state of the GL is undefined, except for the state of the error flags, after this error
+%% is recorded.
+%%
+%% When an error flag is set, results of a GL operation are undefined only if `?GL_OUT_OF_MEMORY'
+%% has occurred. In all other cases, the command generating the error is ignored and has
+%% no effect on the GL state or frame buffer contents. If the generating command returns
+%% a value, it returns 0. If ``gl:getError'' itself generates an error, it returns 0.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml">external</a> documentation.
+-spec getError() -> enum().
+getError() ->
+ call(5074, <<>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer(),Alpha::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4i(integer(),integer(),integer(),integer()) -> ok.
-color4i(Red,Green,Blue,Alpha) ->
- cast(5066, <<Red:?GLint,Green:?GLint,Blue:?GLint,Alpha:?GLint>>).
+%% @doc Return a string describing the current GL connection
+%%
+%% ``gl:getString'' returns a pointer to a static string describing some aspect of the
+%% current GL connection. `Name' can be one of the following:
+%%
+%% `?GL_VENDOR': Returns the company responsible for this GL implementation. This name
+%% does not change from release to release.
+%%
+%% `?GL_RENDERER': Returns the name of the renderer. This name is typically specific
+%% to a particular configuration of a hardware platform. It does not change from release
+%% to release.
+%%
+%% `?GL_VERSION': Returns a version or release number.
+%%
+%% `?GL_SHADING_LANGUAGE_VERSION': Returns a version or release number for the shading
+%% language.
+%%
+%% ``gl:getStringi'' returns a pointer to a static string indexed by `Index' . `Name'
+%% can be one of the following:
+%%
+%% `?GL_EXTENSIONS': For ``gl:getStringi'' only, returns the extension string supported
+%% by the implementation at `Index' .
+%%
+%% Strings `?GL_VENDOR' and `?GL_RENDERER' together uniquely specify a platform.
+%% They do not change from release to release and should be used by platform-recognition
+%% algorithms.
+%%
+%% The `?GL_VERSION' and `?GL_SHADING_LANGUAGE_VERSION' strings begin with a version
+%% number. The version number uses one of these forms:
+%%
+%% `major_number.minor_number'`major_number.minor_number.release_number'
+%%
+%% Vendor-specific information may follow the version number. Its format depends on the
+%% implementation, but a space always separates the version number and the vendor-specific
+%% information.
+%%
+%% All strings are null-terminated.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml">external</a> documentation.
+-spec getString(Name) -> string() when Name :: enum().
+getString(Name) ->
+ call(5075, <<Name:?GLenum>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4i(Red,Green,Blue,Alpha)
--spec color4iv({integer(),integer(),integer(),integer()}) -> ok.
-color4iv({Red,Green,Blue,Alpha}) -> color4i(Red,Green,Blue,Alpha).
+%% @doc Block until all GL execution is complete
+%%
+%% ``gl:finish'' does not return until the effects of all previously called GL commands
+%% are complete. Such effects include all changes to GL state, all changes to connection
+%% state, and all changes to the frame buffer contents.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFinish.xml">external</a> documentation.
+-spec finish() -> ok.
+finish() ->
+ cast(5076, <<>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer(),Alpha::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4s(integer(),integer(),integer(),integer()) -> ok.
-color4s(Red,Green,Blue,Alpha) ->
- cast(5067, <<Red:?GLshort,Green:?GLshort,Blue:?GLshort,Alpha:?GLshort>>).
+%% @doc Force execution of GL commands in finite time
+%%
+%% Different GL implementations buffer commands in several different locations, including
+%% network buffers and the graphics accelerator itself. ``gl:flush'' empties all of these
+%% buffers, causing all issued commands to be executed as quickly as they are accepted by
+%% the actual rendering engine. Though this execution may not be completed in any particular
+%% time period, it does complete in finite time.
+%%
+%% Because any GL program might be executed over a network, or on an accelerator that buffers
+%% commands, all programs should call ``gl:flush'' whenever they count on having all of
+%% their previously issued commands completed. For example, call ``gl:flush'' before waiting
+%% for user input that depends on the generated image.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml">external</a> documentation.
+-spec flush() -> ok.
+flush() ->
+ cast(5077, <<>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4s(Red,Green,Blue,Alpha)
--spec color4sv({integer(),integer(),integer(),integer()}) -> ok.
-color4sv({Red,Green,Blue,Alpha}) -> color4s(Red,Green,Blue,Alpha).
+%% @doc Specify implementation-specific hints
+%%
+%% Certain aspects of GL behavior, when there is room for interpretation, can be controlled
+%% with hints. A hint is specified with two arguments. `Target' is a symbolic constant
+%% indicating the behavior to be controlled, and `Mode' is another symbolic constant
+%% indicating the desired behavior. The initial value for each `Target' is `?GL_DONT_CARE'
+%% . `Mode' can be one of the following:
+%%
+%% `?GL_FASTEST': The most efficient option should be chosen.
+%%
+%% `?GL_NICEST': The most correct, or highest quality, option should be chosen.
+%%
+%% `?GL_DONT_CARE': No preference.
+%%
+%% Though the implementation aspects that can be hinted are well defined, the interpretation
+%% of the hints depends on the implementation. The hint aspects that can be specified with `Target'
+%% , along with suggested semantics, are as follows:
+%%
+%% `?GL_FRAGMENT_SHADER_DERIVATIVE_HINT': Indicates the accuracy of the derivative
+%% calculation for the GL shading language fragment processing built-in functions: `?dFdx'
+%% , `?dFdy', and `?fwidth'.
+%%
+%% `?GL_LINE_SMOOTH_HINT': Indicates the sampling quality of antialiased lines. If
+%% a larger filter function is applied, hinting `?GL_NICEST' can result in more pixel
+%% fragments being generated during rasterization.
+%%
+%% `?GL_POLYGON_SMOOTH_HINT': Indicates the sampling quality of antialiased polygons.
+%% Hinting `?GL_NICEST' can result in more pixel fragments being generated during rasterization,
+%% if a larger filter function is applied.
+%%
+%% `?GL_TEXTURE_COMPRESSION_HINT': Indicates the quality and performance of the compressing
+%% texture images. Hinting `?GL_FASTEST' indicates that texture images should be compressed
+%% as quickly as possible, while `?GL_NICEST' indicates that texture images should be
+%% compressed with as little image quality loss as possible. `?GL_NICEST' should be
+%% selected if the texture is to be retrieved by {@link gl:getCompressedTexImage/3} for reuse.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHint.xml">external</a> documentation.
+-spec hint(Target, Mode) -> ok when Target :: enum(),Mode :: enum().
+hint(Target,Mode) ->
+ cast(5078, <<Target:?GLenum,Mode:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer(),Alpha::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4ub(integer(),integer(),integer(),integer()) -> ok.
-color4ub(Red,Green,Blue,Alpha) ->
- cast(5068, <<Red:?GLubyte,Green:?GLubyte,Blue:?GLubyte,Alpha:?GLubyte>>).
+%% @doc Specify the clear value for the depth buffer
+%%
+%% ``gl:clearDepth'' specifies the depth value used by {@link gl:clear/1} to clear the depth
+%% buffer. Values specified by ``gl:clearDepth'' are clamped to the range [0 1].
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepth.xml">external</a> documentation.
+-spec clearDepth(Depth) -> ok when Depth :: clamp().
+clearDepth(Depth) ->
+ cast(5079, <<Depth:?GLclampd>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4ub(Red,Green,Blue,Alpha)
--spec color4ubv({integer(),integer(),integer(),integer()}) -> ok.
-color4ubv({Red,Green,Blue,Alpha}) -> color4ub(Red,Green,Blue,Alpha).
+%% @doc Specify the value used for depth buffer comparisons
+%%
+%% ``gl:depthFunc'' specifies the function used to compare each incoming pixel depth value
+%% with the depth value present in the depth buffer. The comparison is performed only if
+%% depth testing is enabled. (See {@link gl:enable/1} and {@link gl:enable/1} of `?GL_DEPTH_TEST'
+%% .)
+%%
+%% `Func' specifies the conditions under which the pixel will be drawn. The comparison
+%% functions are as follows:
+%%
+%% `?GL_NEVER': Never passes.
+%%
+%% `?GL_LESS': Passes if the incoming depth value is less than the stored depth value.
+%%
+%%
+%% `?GL_EQUAL': Passes if the incoming depth value is equal to the stored depth value.
+%%
+%%
+%% `?GL_LEQUAL': Passes if the incoming depth value is less than or equal to the stored
+%% depth value.
+%%
+%% `?GL_GREATER': Passes if the incoming depth value is greater than the stored depth
+%% value.
+%%
+%% `?GL_NOTEQUAL': Passes if the incoming depth value is not equal to the stored depth
+%% value.
+%%
+%% `?GL_GEQUAL': Passes if the incoming depth value is greater than or equal to the
+%% stored depth value.
+%%
+%% `?GL_ALWAYS': Always passes.
+%%
+%% The initial value of `Func' is `?GL_LESS'. Initially, depth testing is disabled.
+%% If depth testing is disabled or if no depth buffer exists, it is as if the depth test
+%% always passes.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml">external</a> documentation.
+-spec depthFunc(Func) -> ok when Func :: enum().
+depthFunc(Func) ->
+ cast(5080, <<Func:?GLenum>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer(),Alpha::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4ui(integer(),integer(),integer(),integer()) -> ok.
-color4ui(Red,Green,Blue,Alpha) ->
- cast(5069, <<Red:?GLuint,Green:?GLuint,Blue:?GLuint,Alpha:?GLuint>>).
+%% @doc Enable or disable writing into the depth buffer
+%%
+%% ``gl:depthMask'' specifies whether the depth buffer is enabled for writing. If `Flag'
+%% is `?GL_FALSE', depth buffer writing is disabled. Otherwise, it is enabled. Initially,
+%% depth buffer writing is enabled.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml">external</a> documentation.
+-spec depthMask(Flag) -> ok when Flag :: 0|1.
+depthMask(Flag) ->
+ cast(5081, <<Flag:?GLboolean>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4ui(Red,Green,Blue,Alpha)
--spec color4uiv({integer(),integer(),integer(),integer()}) -> ok.
-color4uiv({Red,Green,Blue,Alpha}) -> color4ui(Red,Green,Blue,Alpha).
+%% @doc Specify mapping of depth values from normalized device coordinates to window coordinates
+%%
+%% After clipping and division by `w', depth coordinates range from -1 to 1, corresponding
+%% to the near and far clipping planes. ``gl:depthRange'' specifies a linear mapping of
+%% the normalized depth coordinates in this range to window depth coordinates. Regardless
+%% of the actual depth buffer implementation, window coordinate depth values are treated
+%% as though they range from 0 through 1 (like color components). Thus, the values accepted
+%% by ``gl:depthRange'' are both clamped to this range before they are accepted.
+%%
+%% The setting of (0,1) maps the near plane to 0 and the far plane to 1. With this mapping,
+%% the depth buffer range is fully utilized.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml">external</a> documentation.
+-spec depthRange(Near_val, Far_val) -> ok when Near_val :: clamp(),Far_val :: clamp().
+depthRange(Near_val,Far_val) ->
+ cast(5082, <<Near_val:?GLclampd,Far_val:?GLclampd>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer(),Alpha::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
--spec color4us(integer(),integer(),integer(),integer()) -> ok.
-color4us(Red,Green,Blue,Alpha) ->
- cast(5070, <<Red:?GLushort,Green:?GLushort,Blue:?GLushort,Alpha:?GLushort>>).
+%% @doc Specify clear values for the accumulation buffer
+%%
+%% ``gl:clearAccum'' specifies the red, green, blue, and alpha values used by {@link gl:clear/1}
+%% to clear the accumulation buffer.
+%%
+%% Values specified by ``gl:clearAccum'' are clamped to the range [-1 1].
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearAccum.xml">external</a> documentation.
+-spec clearAccum(Red, Green, Blue, Alpha) -> ok when Red :: float(),Green :: float(),Blue :: float(),Alpha :: float().
+clearAccum(Red,Green,Blue,Alpha) ->
+ cast(5083, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat,Alpha:?GLfloat>>).
-%% @spec ({Red,Green,Blue,Alpha}) -> ok
-%% @equiv color4us(Red,Green,Blue,Alpha)
--spec color4usv({integer(),integer(),integer(),integer()}) -> ok.
-color4usv({Red,Green,Blue,Alpha}) -> color4us(Red,Green,Blue,Alpha).
+%% @doc Operate on the accumulation buffer
+%%
+%% The accumulation buffer is an extended-range color buffer. Images are not rendered into
+%% it. Rather, images rendered into one of the color buffers are added to the contents of
+%% the accumulation buffer after rendering. Effects such as antialiasing (of points, lines,
+%% and polygons), motion blur, and depth of field can be created by accumulating images generated
+%% with different transformation matrices.
+%%
+%% Each pixel in the accumulation buffer consists of red, green, blue, and alpha values.
+%% The number of bits per component in the accumulation buffer depends on the implementation.
+%% You can examine this number by calling {@link gl:getBooleanv/1} four times, with arguments
+%% `?GL_ACCUM_RED_BITS', `?GL_ACCUM_GREEN_BITS', `?GL_ACCUM_BLUE_BITS', and `?GL_ACCUM_ALPHA_BITS'
+%% . Regardless of the number of bits per component, the range of values stored by each component
+%% is [-1 1]. The accumulation buffer pixels are mapped one-to-one with frame buffer pixels.
+%%
+%% ``gl:accum'' operates on the accumulation buffer. The first argument, `Op' , is
+%% a symbolic constant that selects an accumulation buffer operation. The second argument, `Value'
+%% , is a floating-point value to be used in that operation. Five operations are specified: `?GL_ACCUM'
+%% , `?GL_LOAD', `?GL_ADD', `?GL_MULT', and `?GL_RETURN'.
+%%
+%% All accumulation buffer operations are limited to the area of the current scissor box
+%% and applied identically to the red, green, blue, and alpha components of each pixel. If
+%% a ``gl:accum'' operation results in a value outside the range [-1 1], the contents of an
+%% accumulation buffer pixel component are undefined.
+%%
+%% The operations are as follows:
+%%
+%% `?GL_ACCUM': Obtains R, G, B, and A values from the buffer currently selected for
+%% reading (see {@link gl:readBuffer/1} ). Each component value is divided by 2 n-1, where
+%% n is the number of bits allocated to each color component in the currently selected buffer.
+%% The result is a floating-point value in the range [0 1], which is multiplied by `Value'
+%% and added to the corresponding pixel component in the accumulation buffer, thereby updating
+%% the accumulation buffer.
+%%
+%% `?GL_LOAD': Similar to `?GL_ACCUM', except that the current value in the accumulation
+%% buffer is not used in the calculation of the new value. That is, the R, G, B, and A values
+%% from the currently selected buffer are divided by 2 n-1, multiplied by `Value' ,
+%% and then stored in the corresponding accumulation buffer cell, overwriting the current
+%% value.
+%%
+%% `?GL_ADD': Adds `Value' to each R, G, B, and A in the accumulation buffer.
+%%
+%% `?GL_MULT': Multiplies each R, G, B, and A in the accumulation buffer by `Value'
+%% and returns the scaled component to its corresponding accumulation buffer location.
+%%
+%% `?GL_RETURN': Transfers accumulation buffer values to the color buffer or buffers
+%% currently selected for writing. Each R, G, B, and A component is multiplied by `Value'
+%% , then multiplied by 2 n-1, clamped to the range [0 2 n-1], and stored in the corresponding
+%% display buffer cell. The only fragment operations that are applied to this transfer are
+%% pixel ownership, scissor, dithering, and color writemasks.
+%%
+%% To clear the accumulation buffer, call {@link gl:clearAccum/4} with R, G, B, and A values
+%% to set it to, then call {@link gl:clear/1} with the accumulation buffer enabled.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAccum.xml">external</a> documentation.
+-spec accum(Op, Value) -> ok when Op :: enum(),Value :: float().
+accum(Op,Value) ->
+ cast(5084, <<Op:?GLenum,Value:?GLfloat>>).
-%% @spec (Red::0|1,Green::0|1,Blue::0|1,Alpha::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml">external</a> documentation.
--spec colorMask(0|1,0|1,0|1,0|1) -> ok.
-colorMask(Red,Green,Blue,Alpha) ->
- cast(5071, <<Red:?GLboolean,Green:?GLboolean,Blue:?GLboolean,Alpha:?GLboolean>>).
+%% @doc Specify which matrix is the current matrix
+%%
+%% ``gl:matrixMode'' sets the current matrix mode. `Mode' can assume one of four values:
+%%
+%%
+%% `?GL_MODELVIEW': Applies subsequent matrix operations to the modelview matrix stack.
+%%
+%%
+%% `?GL_PROJECTION': Applies subsequent matrix operations to the projection matrix
+%% stack.
+%%
+%% `?GL_TEXTURE': Applies subsequent matrix operations to the texture matrix stack.
+%%
+%% `?GL_COLOR': Applies subsequent matrix operations to the color matrix stack.
+%%
+%% To find out which matrix stack is currently the target of all matrix operations, call {@link gl:getBooleanv/1}
+%% with argument `?GL_MATRIX_MODE'. The initial value is `?GL_MODELVIEW'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml">external</a> documentation.
+-spec matrixMode(Mode) -> ok when Mode :: enum().
+matrixMode(Mode) ->
+ cast(5085, <<Mode:?GLenum>>).
-%% @spec (Face::enum(),Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaterial.xml">external</a> documentation.
--spec colorMaterial(enum(),enum()) -> ok.
-colorMaterial(Face,Mode) ->
- cast(5072, <<Face:?GLenum,Mode:?GLenum>>).
-
-%% @spec (Size::integer(),Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorPointer.xml">external</a> documentation.
--spec colorPointer(integer(),enum(),integer(),offset()|mem()) -> ok.
-colorPointer(Size,Type,Stride,Pointer) when is_integer(Pointer) ->
- cast(5073, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
-colorPointer(Size,Type,Stride,Pointer) ->
- send_bin(Pointer),
- cast(5074, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
+%% @doc Multiply the current matrix with an orthographic matrix
+%%
+%% ``gl:ortho'' describes a transformation that produces a parallel projection. The current
+%% matrix (see {@link gl:matrixMode/1} ) is multiplied by this matrix and the result replaces
+%% the current matrix, as if {@link gl:multMatrixd/1} were called with the following matrix
+%% as its argument:
+%%
+%% ((2/(right-left)) 0 0(t x) 0(2/(top-bottom)) 0(t y) 0 0(-2/(farVal-nearVal))(t z) 0 0 0 1)
+%%
+%% where t x=-((right+left)/(right-left)) t y=-((top+bottom)/(top-bottom)) t z=-((farVal+nearVal)/(farVal-nearVal))
+%%
+%% Typically, the matrix mode is `?GL_PROJECTION', and (left bottom-nearVal) and (right top-nearVal) specify the points on
+%% the near clipping plane that are mapped to the lower left and upper right corners of the
+%% window, respectively, assuming that the eye is located at (0, 0, 0). -farVal specifies
+%% the location of the far clipping plane. Both `NearVal' and `FarVal' can be either
+%% positive or negative.
+%%
+%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the current
+%% matrix stack.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml">external</a> documentation.
+-spec ortho(Left, Right, Bottom, Top, Near_val, Far_val) -> ok when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(),Near_val :: float(),Far_val :: float().
+ortho(Left,Right,Bottom,Top,Near_val,Far_val) ->
+ cast(5086, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,Near_val:?GLdouble,Far_val:?GLdouble>>).
-%% @spec (X::integer(),Y::integer(),Width::integer(),Height::integer(),Type::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyPixels.xml">external</a> documentation.
--spec copyPixels(integer(),integer(),integer(),integer(),enum()) -> ok.
-copyPixels(X,Y,Width,Height,Type) ->
- cast(5075, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Type:?GLenum>>).
-
-%% @spec (Target::enum(),Level::integer(),InternalFormat::enum(),X::integer(),Y::integer(),Width::integer(),Border::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage1D.xml">external</a> documentation.
--spec copyTexImage1D(enum(),integer(),enum(),integer(),integer(),integer(),integer()) -> ok.
-copyTexImage1D(Target,Level,InternalFormat,X,Y,Width,Border) ->
- cast(5076, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Border:?GLint>>).
-
-%% @spec (Target::enum(),Level::integer(),InternalFormat::enum(),X::integer(),Y::integer(),Width::integer(),Height::integer(),Border::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml">external</a> documentation.
--spec copyTexImage2D(enum(),integer(),enum(),integer(),integer(),integer(),integer(),integer()) -> ok.
-copyTexImage2D(Target,Level,InternalFormat,X,Y,Width,Height,Border) ->
- cast(5077, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint>>).
-
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),X::integer(),Y::integer(),Width::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage1D.xml">external</a> documentation.
--spec copyTexSubImage1D(enum(),integer(),integer(),integer(),integer(),integer()) -> ok.
-copyTexSubImage1D(Target,Level,Xoffset,X,Y,Width) ->
- cast(5078, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei>>).
+%% @doc Multiply the current matrix by a perspective matrix
+%%
+%% ``gl:frustum'' describes a perspective matrix that produces a perspective projection.
+%% The current matrix (see {@link gl:matrixMode/1} ) is multiplied by this matrix and the result
+%% replaces the current matrix, as if {@link gl:multMatrixd/1} were called with the following
+%% matrix as its argument:
+%%
+%% [((2 nearVal)/(right-left)) 0 A 0 0((2 nearVal)/(top-bottom)) B 0 0 0 C D 0 0 -1 0]
+%%
+%% A=(right+left)/(right-left)
+%%
+%% B=(top+bottom)/(top-bottom)
+%%
+%% C=-((farVal+nearVal)/(farVal-nearVal))
+%%
+%% D=-((2 farVal nearVal)/(farVal-nearVal))
+%%
+%% Typically, the matrix mode is `?GL_PROJECTION', and (left bottom-nearVal) and (right top-nearVal) specify the points on
+%% the near clipping plane that are mapped to the lower left and upper right corners of the
+%% window, assuming that the eye is located at (0, 0, 0). -farVal specifies the location
+%% of the far clipping plane. Both `NearVal' and `FarVal' must be positive.
+%%
+%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the current
+%% matrix stack.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml">external</a> documentation.
+-spec frustum(Left, Right, Bottom, Top, Near_val, Far_val) -> ok when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(),Near_val :: float(),Far_val :: float().
+frustum(Left,Right,Bottom,Top,Near_val,Far_val) ->
+ cast(5087, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,Near_val:?GLdouble,Far_val:?GLdouble>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Yoffset::integer(),X::integer(),Y::integer(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml">external</a> documentation.
--spec copyTexSubImage2D(enum(),integer(),integer(),integer(),integer(),integer(),integer(),integer()) -> ok.
-copyTexSubImage2D(Target,Level,Xoffset,Yoffset,X,Y,Width,Height) ->
- cast(5079, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
+%% @doc Set the viewport
+%%
+%% ``gl:viewport'' specifies the affine transformation of x and y from normalized device
+%% coordinates to window coordinates. Let (x nd y nd) be normalized device coordinates. Then the window
+%% coordinates (x w y w) are computed as follows:
+%%
+%% x w=(x nd+1) (width/2)+x
+%%
+%% y w=(y nd+1) (height/2)+y
+%%
+%% Viewport width and height are silently clamped to a range that depends on the implementation.
+%% To query this range, call {@link gl:getBooleanv/1} with argument `?GL_MAX_VIEWPORT_DIMS'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml">external</a> documentation.
+-spec viewport(X, Y, Width, Height) -> ok when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
+viewport(X,Y,Width,Height) ->
+ cast(5088, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml">external</a> documentation.
--spec cullFace(enum()) -> ok.
-cullFace(Mode) ->
- cast(5080, <<Mode:?GLenum>>).
+%% @doc Push and pop the current matrix stack
+%%
+%% There is a stack of matrices for each of the matrix modes. In `?GL_MODELVIEW' mode,
+%% the stack depth is at least 32. In the other modes, `?GL_COLOR', `?GL_PROJECTION'
+%% , and `?GL_TEXTURE', the depth is at least 2. The current matrix in any mode is the
+%% matrix on the top of the stack for that mode.
+%%
+%% ``gl:pushMatrix'' pushes the current matrix stack down by one, duplicating the current
+%% matrix. That is, after a ``gl:pushMatrix'' call, the matrix on top of the stack is identical
+%% to the one below it.
+%%
+%% {@link gl:pushMatrix/0} pops the current matrix stack, replacing the current matrix with
+%% the one below it on the stack.
+%%
+%% Initially, each of the stacks contains one matrix, an identity matrix.
+%%
+%% It is an error to push a full matrix stack or to pop a matrix stack that contains only
+%% a single matrix. In either case, the error flag is set and no other change is made to
+%% GL state.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml">external</a> documentation.
+-spec pushMatrix() -> ok.
+pushMatrix() ->
+ cast(5089, <<>>).
-%% @spec (List::integer(),Range::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteLists.xml">external</a> documentation.
--spec deleteLists(integer(),integer()) -> ok.
-deleteLists(List,Range) ->
- cast(5081, <<List:?GLuint,Range:?GLsizei>>).
+%% @doc
+%% See {@link pushMatrix/0}
+-spec popMatrix() -> ok.
+popMatrix() ->
+ cast(5090, <<>>).
-%% @spec (Textures::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml">external</a> documentation.
--spec deleteTextures([integer()]) -> ok.
-deleteTextures(Textures) ->
- cast(5082, <<(length(Textures)):?GLuint,
- (<< <<C:?GLuint>> || C <- Textures>>)/binary,0:(((1+length(Textures)) rem 2)*32)>>).
+%% @doc Replace the current matrix with the identity matrix
+%%
+%% ``gl:loadIdentity'' replaces the current matrix with the identity matrix. It is semantically
+%% equivalent to calling {@link gl:loadMatrixd/1} with the identity matrix
+%%
+%% ((1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1))
+%%
+%% but in some cases it is more efficient.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml">external</a> documentation.
+-spec loadIdentity() -> ok.
+loadIdentity() ->
+ cast(5091, <<>>).
-%% @spec (Func::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml">external</a> documentation.
--spec depthFunc(enum()) -> ok.
-depthFunc(Func) ->
- cast(5083, <<Func:?GLenum>>).
+%% @doc Replace the current matrix with the specified matrix
+%%
+%% ``gl:loadMatrix'' replaces the current matrix with the one whose elements are specified
+%% by `M' . The current matrix is the projection matrix, modelview matrix, or texture
+%% matrix, depending on the current matrix mode (see {@link gl:matrixMode/1} ).
+%%
+%% The current matrix, M, defines a transformation of coordinates. For instance, assume
+%% M refers to the modelview matrix. If v=(v[0] v[1] v[2] v[3]) is the set of object coordinates of a vertex,
+%% and `M' points to an array of 16 single- or double-precision floating-point values
+%% m={m[0] m[1] ... m[15]}, then the modelview transformation M(v) does the following:
+%%
+%% M(v)=(m[0] m[4] m[8] m[12] m[1] m[5] m[9] m[13] m[2] m[6] m[10] m[14] m[3] m[7] m[11] m[15])*(v[0] v[1] v[2] v[3])
+%%
+%% Projection and texture transformations are similarly defined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml">external</a> documentation.
+-spec loadMatrixd(M) -> ok when M :: matrix().
+loadMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
+ cast(5092, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
+loadMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
+ cast(5092, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
-%% @spec (Flag::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml">external</a> documentation.
--spec depthMask(0|1) -> ok.
-depthMask(Flag) ->
- cast(5084, <<Flag:?GLboolean>>).
+%% @doc
+%% See {@link loadMatrixd/1}
+-spec loadMatrixf(M) -> ok when M :: matrix().
+loadMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
+ cast(5093, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
+loadMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
+ cast(5093, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
-%% @spec (ZNear::clamp(),ZFar::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml">external</a> documentation.
--spec depthRange(clamp(),clamp()) -> ok.
-depthRange(ZNear,ZFar) ->
- cast(5085, <<ZNear:?GLclampd,ZFar:?GLclampd>>).
+%% @doc Multiply the current matrix with the specified matrix
+%%
+%% ``gl:multMatrix'' multiplies the current matrix with the one specified using `M' ,
+%% and replaces the current matrix with the product.
+%%
+%% The current matrix is determined by the current matrix mode (see {@link gl:matrixMode/1} ).
+%% It is either the projection matrix, modelview matrix, or the texture matrix.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml">external</a> documentation.
+-spec multMatrixd(M) -> ok when M :: matrix().
+multMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
+ cast(5094, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
+multMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
+ cast(5094, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
-%% @spec (Cap::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDisable.xml">external</a> documentation.
--spec disable(enum()) -> ok.
-disable(Cap) ->
- cast(5086, <<Cap:?GLenum>>).
+%% @doc
+%% See {@link multMatrixd/1}
+-spec multMatrixf(M) -> ok when M :: matrix().
+multMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
+ cast(5095, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
+multMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
+ cast(5095, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
-%% @spec (Array::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDisableClientState.xml">external</a> documentation.
--spec disableClientState(enum()) -> ok.
-disableClientState(Array) ->
- cast(5087, <<Array:?GLenum>>).
+%% @doc Multiply the current matrix by a rotation matrix
+%%
+%% ``gl:rotate'' produces a rotation of `Angle' degrees around the vector (x y z). The current
+%% matrix (see {@link gl:matrixMode/1} ) is multiplied by a rotation matrix with the product
+%% replacing the current matrix, as if {@link gl:multMatrixd/1} were called with the following
+%% matrix as its argument:
+%%
+%% (x 2(1-c)+c x y(1-c)-z s x z(1-c)+y s 0 y x(1-c)+z s y 2(1-c)+c y z(1-c)-x s 0 x z(1-c)-y s y z(1-c)+x s z 2(1-c)+c 0 0 0 0
+%% 1)
+%%
+%% Where c= cos(angle), s= sin(angle), and ||(x y z)||= 1 (if not, the GL will normalize this vector).
+%%
+%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects
+%% drawn after ``gl:rotate'' is called are rotated. Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0}
+%% to save and restore the unrotated coordinate system.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml">external</a> documentation.
+-spec rotated(Angle, X, Y, Z) -> ok when Angle :: float(),X :: float(),Y :: float(),Z :: float().
+rotated(Angle,X,Y,Z) ->
+ cast(5096, <<Angle:?GLdouble,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Mode::enum(),First::integer(),Count::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml">external</a> documentation.
--spec drawArrays(enum(),integer(),integer()) -> ok.
-drawArrays(Mode,First,Count) ->
- cast(5088, <<Mode:?GLenum,First:?GLint,Count:?GLsizei>>).
+%% @doc
+%% See {@link rotated/4}
+-spec rotatef(Angle, X, Y, Z) -> ok when Angle :: float(),X :: float(),Y :: float(),Z :: float().
+rotatef(Angle,X,Y,Z) ->
+ cast(5097, <<Angle:?GLfloat,X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml">external</a> documentation.
--spec drawBuffer(enum()) -> ok.
-drawBuffer(Mode) ->
- cast(5089, <<Mode:?GLenum>>).
+%% @doc Multiply the current matrix by a general scaling matrix
+%%
+%% ``gl:scale'' produces a nonuniform scaling along the `x', `y', and `z'
+%% axes. The three parameters indicate the desired scale factor along each of the three axes.
+%%
+%%
+%% The current matrix (see {@link gl:matrixMode/1} ) is multiplied by this scale matrix, and
+%% the product replaces the current matrix as if {@link gl:multMatrixd/1} were called with
+%% the following matrix as its argument:
+%%
+%% (x 0 0 0 0 y 0 0 0 0 z 0 0 0 0 1)
+%%
+%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects
+%% drawn after ``gl:scale'' is called are scaled.
+%%
+%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the unscaled
+%% coordinate system.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml">external</a> documentation.
+-spec scaled(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+scaled(X,Y,Z) ->
+ cast(5098, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Mode::enum(),Count::integer(),Type::enum(),Indices::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml">external</a> documentation.
--spec drawElements(enum(),integer(),enum(),offset()|mem()) -> ok.
-drawElements(Mode,Count,Type,Indices) when is_integer(Indices) ->
- cast(5090, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>);
-drawElements(Mode,Count,Type,Indices) ->
- send_bin(Indices),
- cast(5091, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum>>).
+%% @doc
+%% See {@link scaled/3}
+-spec scalef(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+scalef(X,Y,Z) ->
+ cast(5099, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec (Width::integer(),Height::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml">external</a> documentation.
--spec drawPixels(integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
-drawPixels(Width,Height,Format,Type,Pixels) when is_integer(Pixels) ->
- cast(5092, <<Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
-drawPixels(Width,Height,Format,Type,Pixels) ->
- send_bin(Pixels),
- cast(5093, <<Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
+%% @doc Multiply the current matrix by a translation matrix
+%%
+%% ``gl:translate'' produces a translation by (x y z). The current matrix (see {@link gl:matrixMode/1}
+%% ) is multiplied by this translation matrix, with the product replacing the current matrix,
+%% as if {@link gl:multMatrixd/1} were called with the following matrix for its argument:
+%%
+%% (1 0 0 x 0 1 0 y 0 0 1 z 0 0 0 1)
+%%
+%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects
+%% drawn after a call to ``gl:translate'' are translated.
+%%
+%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the untranslated
+%% coordinate system.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml">external</a> documentation.
+-spec translated(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+translated(X,Y,Z) ->
+ cast(5100, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Flag::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml">external</a> documentation.
--spec edgeFlag(0|1) -> ok.
-edgeFlag(Flag) ->
- cast(5094, <<Flag:?GLboolean>>).
-
-%% @spec (Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlagPointer.xml">external</a> documentation.
--spec edgeFlagPointer(integer(),offset()|mem()) -> ok.
-edgeFlagPointer(Stride,Pointer) when is_integer(Pointer) ->
- cast(5095, <<Stride:?GLsizei,Pointer:?GLuint>>);
-edgeFlagPointer(Stride,Pointer) ->
- send_bin(Pointer),
- cast(5096, <<Stride:?GLsizei>>).
+%% @doc
+%% See {@link translated/3}
+-spec translatef(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+translatef(X,Y,Z) ->
+ cast(5101, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec ({Flag}) -> ok
-%% @equiv edgeFlag(Flag)
--spec edgeFlagv({0|1}) -> ok.
-edgeFlagv({Flag}) -> edgeFlag(Flag).
+%% @doc Determine if a name corresponds to a display list
+%%
+%% ``gl:isList'' returns `?GL_TRUE' if `List' is the name of a display list and
+%% returns `?GL_FALSE' if it is not, or if an error occurs.
+%%
+%% A name returned by {@link gl:genLists/1} , but not yet associated with a display list by
+%% calling {@link gl:newList/2} , is not the name of a display list.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsList.xml">external</a> documentation.
+-spec isList(List) -> 0|1 when List :: integer().
+isList(List) ->
+ call(5102, <<List:?GLuint>>).
-%% @spec (Cap::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml">external</a> documentation.
--spec enable(enum()) -> ok.
-enable(Cap) ->
- cast(5097, <<Cap:?GLenum>>).
+%% @doc Delete a contiguous group of display lists
+%%
+%% ``gl:deleteLists'' causes a contiguous group of display lists to be deleted. `List'
+%% is the name of the first display list to be deleted, and `Range' is the number of
+%% display lists to delete. All display lists d with list&lt;= d&lt;= list+range-1 are
+%% deleted.
+%%
+%% All storage locations allocated to the specified display lists are freed, and the names
+%% are available for reuse at a later time. Names within the range that do not have an associated
+%% display list are ignored. If `Range' is 0, nothing happens.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteLists.xml">external</a> documentation.
+-spec deleteLists(List, Range) -> ok when List :: integer(),Range :: integer().
+deleteLists(List,Range) ->
+ cast(5103, <<List:?GLuint,Range:?GLsizei>>).
-%% @spec (Array::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml">external</a> documentation.
--spec enableClientState(enum()) -> ok.
-enableClientState(Array) ->
- cast(5098, <<Array:?GLenum>>).
+%% @doc Generate a contiguous set of empty display lists
+%%
+%% ``gl:genLists'' has one argument, `Range' . It returns an integer `n' such
+%% that `Range' contiguous empty display lists, named n, n+1, ..., n+range-1,
+%% are created. If `Range' is 0, if there is no group of `Range' contiguous names
+%% available, or if any error is generated, no display lists are generated, and 0 is returned.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenLists.xml">external</a> documentation.
+-spec genLists(Range) -> integer() when Range :: integer().
+genLists(Range) ->
+ call(5104, <<Range:?GLsizei>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnd.xml">external</a> documentation.
--spec 'end'() -> ok.
-'end'() ->
- cast(5099, <<>>).
+%% @doc Create or replace a display list
+%%
+%% Display lists are groups of GL commands that have been stored for subsequent execution.
+%% Display lists are created with ``gl:newList''. All subsequent commands are placed in
+%% the display list, in the order issued, until {@link gl:endList/0} is called.
+%%
+%% ``gl:newList'' has two arguments. The first argument, `List' , is a positive integer
+%% that becomes the unique name for the display list. Names can be created and reserved with
+%% {@link gl:genLists/1} and tested for uniqueness with {@link gl:isList/1} . The second argument,
+%% `Mode' , is a symbolic constant that can assume one of two values:
+%%
+%% `?GL_COMPILE': Commands are merely compiled.
+%%
+%% `?GL_COMPILE_AND_EXECUTE': Commands are executed as they are compiled into the display
+%% list.
+%%
+%% Certain commands are not compiled into the display list but are executed immediately,
+%% regardless of the display-list mode. These commands are {@link gl:areTexturesResident/1} , {@link gl:colorPointer/4}
+%% , {@link gl:deleteLists/2} , {@link gl:deleteTextures/1} , {@link gl:enableClientState/1} , {@link gl:edgeFlagPointer/2}
+%% , {@link gl:enableClientState/1} , {@link gl:feedbackBuffer/3} , {@link gl:finish/0} , {@link gl:flush/0}
+%% , {@link gl:genLists/1} , {@link gl:genTextures/1} , {@link gl:indexPointer/3} , {@link gl:interleavedArrays/3}
+%% , {@link gl:isEnabled/1} , {@link gl:isList/1} , {@link gl:isTexture/1} , {@link gl:normalPointer/3}
+%% , {@link gl:pushClientAttrib/1} , {@link gl:pixelStoref/2} , {@link gl:pushClientAttrib/1} , {@link gl:readPixels/7}
+%% , {@link gl:renderMode/1} , {@link gl:selectBuffer/2} , {@link gl:texCoordPointer/4} , {@link gl:vertexPointer/4}
+%% , and all of the {@link gl:getBooleanv/1} commands.
+%%
+%% Similarly, {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , and {@link gl:texImage3D/10}
+%% are executed immediately and not compiled into the display list when their first argument
+%% is `?GL_PROXY_TEXTURE_1D', `?GL_PROXY_TEXTURE_1D', or `?GL_PROXY_TEXTURE_3D'
+%% , respectively.
+%%
+%% When the ARB_imaging extension is supported, {@link gl:histogram/4} executes immediately
+%% when its argument is `?GL_PROXY_HISTOGRAM'. Similarly, {@link gl:colorTable/6} executes
+%% immediately when its first argument is `?GL_PROXY_COLOR_TABLE', `?GL_PROXY_POST_CONVOLUTION_COLOR_TABLE'
+%% , or `?GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE'.
+%%
+%% For OpenGL versions 1.3 and greater, or when the ARB_multitexture extension is supported,
+%% {@link gl:clientActiveTexture/1} is not compiled into display lists, but executed immediately.
+%%
+%%
+%% When {@link gl:endList/0} is encountered, the display-list definition is completed by
+%% associating the list with the unique name `List' (specified in the ``gl:newList''
+%% command). If a display list with name `List' already exists, it is replaced only
+%% when {@link gl:endList/0} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml">external</a> documentation.
+-spec newList(List, Mode) -> ok when List :: integer(),Mode :: enum().
+newList(List,Mode) ->
+ cast(5105, <<List:?GLuint,Mode:?GLenum>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEndList.xml">external</a> documentation.
+%% @doc glBeginList
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginList.xml">external</a> documentation.
-spec endList() -> ok.
endList() ->
- cast(5100, <<>>).
-
-%% @spec (U::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation.
--spec evalCoord1d(float()) -> ok.
-evalCoord1d(U) ->
- cast(5101, <<U:?GLdouble>>).
-
-%% @spec ({U}) -> ok
-%% @equiv evalCoord1d(U)
--spec evalCoord1dv({float()}) -> ok.
-evalCoord1dv({U}) -> evalCoord1d(U).
-
-%% @spec (U::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation.
--spec evalCoord1f(float()) -> ok.
-evalCoord1f(U) ->
- cast(5102, <<U:?GLfloat>>).
-
-%% @spec ({U}) -> ok
-%% @equiv evalCoord1f(U)
--spec evalCoord1fv({float()}) -> ok.
-evalCoord1fv({U}) -> evalCoord1f(U).
-
-%% @spec (U::float(),V::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation.
--spec evalCoord2d(float(),float()) -> ok.
-evalCoord2d(U,V) ->
- cast(5103, <<U:?GLdouble,V:?GLdouble>>).
+ cast(5106, <<>>).
-%% @spec ({U,V}) -> ok
-%% @equiv evalCoord2d(U,V)
--spec evalCoord2dv({float(),float()}) -> ok.
-evalCoord2dv({U,V}) -> evalCoord2d(U,V).
-
-%% @spec (U::float(),V::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation.
--spec evalCoord2f(float(),float()) -> ok.
-evalCoord2f(U,V) ->
- cast(5104, <<U:?GLfloat,V:?GLfloat>>).
-
-%% @spec ({U,V}) -> ok
-%% @equiv evalCoord2f(U,V)
--spec evalCoord2fv({float(),float()}) -> ok.
-evalCoord2fv({U,V}) -> evalCoord2f(U,V).
-
-%% @spec (Mode::enum(),I1::integer(),I2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml">external</a> documentation.
--spec evalMesh1(enum(),integer(),integer()) -> ok.
-evalMesh1(Mode,I1,I2) ->
- cast(5105, <<Mode:?GLenum,I1:?GLint,I2:?GLint>>).
-
-%% @spec (Mode::enum(),I1::integer(),I2::integer(),J1::integer(),J2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml">external</a> documentation.
--spec evalMesh2(enum(),integer(),integer(),integer(),integer()) -> ok.
-evalMesh2(Mode,I1,I2,J1,J2) ->
- cast(5106, <<Mode:?GLenum,I1:?GLint,I2:?GLint,J1:?GLint,J2:?GLint>>).
-
-%% @spec (I::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml">external</a> documentation.
--spec evalPoint1(integer()) -> ok.
-evalPoint1(I) ->
- cast(5107, <<I:?GLint>>).
+%% @doc Execute a display list
+%%
+%% ``gl:callList'' causes the named display list to be executed. The commands saved in
+%% the display list are executed in order, just as if they were called without using a display
+%% list. If `List' has not been defined as a display list, ``gl:callList'' is ignored.
+%%
+%%
+%% ``gl:callList'' can appear inside a display list. To avoid the possibility of infinite
+%% recursion resulting from display lists calling one another, a limit is placed on the nesting
+%% level of display lists during display-list execution. This limit is at least 64, and it
+%% depends on the implementation.
+%%
+%% GL state is not saved and restored across a call to ``gl:callList''. Thus, changes
+%% made to GL state during the execution of a display list remain after execution of the
+%% display list is completed. Use {@link gl:pushAttrib/1} , {@link gl:pushAttrib/1} , {@link gl:pushMatrix/0}
+%% , and {@link gl:pushMatrix/0} to preserve GL state across ``gl:callList'' calls.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallList.xml">external</a> documentation.
+-spec callList(List) -> ok when List :: integer().
+callList(List) ->
+ cast(5107, <<List:?GLuint>>).
-%% @spec (I::integer(),J::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml">external</a> documentation.
--spec evalPoint2(integer(),integer()) -> ok.
-evalPoint2(I,J) ->
- cast(5108, <<I:?GLint,J:?GLint>>).
+%% @doc Execute a list of display lists
+%%
+%% ``gl:callLists'' causes each display list in the list of names passed as `Lists'
+%% to be executed. As a result, the commands saved in each display list are executed in order,
+%% just as if they were called without using a display list. Names of display lists that
+%% have not been defined are ignored.
+%%
+%% ``gl:callLists'' provides an efficient means for executing more than one display list. `Type'
+%% allows lists with various name formats to be accepted. The formats are as follows:
+%%
+%% `?GL_BYTE': `Lists' is treated as an array of signed bytes, each in the range
+%% -128 through 127.
+%%
+%% `?GL_UNSIGNED_BYTE': `Lists' is treated as an array of unsigned bytes, each
+%% in the range 0 through 255.
+%%
+%% `?GL_SHORT': `Lists' is treated as an array of signed two-byte integers, each
+%% in the range -32768 through 32767.
+%%
+%% `?GL_UNSIGNED_SHORT': `Lists' is treated as an array of unsigned two-byte integers,
+%% each in the range 0 through 65535.
+%%
+%% `?GL_INT': `Lists' is treated as an array of signed four-byte integers.
+%%
+%% `?GL_UNSIGNED_INT': `Lists' is treated as an array of unsigned four-byte integers.
+%%
+%%
+%% `?GL_FLOAT': `Lists' is treated as an array of four-byte floating-point values.
+%%
+%%
+%% `?GL_2_BYTES': `Lists' is treated as an array of unsigned bytes. Each pair of
+%% bytes specifies a single display-list name. The value of the pair is computed as 256 times
+%% the unsigned value of the first byte plus the unsigned value of the second byte.
+%%
+%% `?GL_3_BYTES': `Lists' is treated as an array of unsigned bytes. Each triplet
+%% of bytes specifies a single display-list name. The value of the triplet is computed as
+%% 65536 times the unsigned value of the first byte, plus 256 times the unsigned value of
+%% the second byte, plus the unsigned value of the third byte.
+%%
+%% `?GL_4_BYTES': `Lists' is treated as an array of unsigned bytes. Each quadruplet
+%% of bytes specifies a single display-list name. The value of the quadruplet is computed
+%% as 16777216 times the unsigned value of the first byte, plus 65536 times the unsigned
+%% value of the second byte, plus 256 times the unsigned value of the third byte, plus the
+%% unsigned value of the fourth byte.
+%%
+%% The list of display-list names is not null-terminated. Rather, `N' specifies how
+%% many names are to be taken from `Lists' .
+%%
+%% An additional level of indirection is made available with the {@link gl:listBase/1} command,
+%% which specifies an unsigned offset that is added to each display-list name specified in `Lists'
+%% before that display list is executed.
+%%
+%% ``gl:callLists'' can appear inside a display list. To avoid the possibility of infinite
+%% recursion resulting from display lists calling one another, a limit is placed on the nesting
+%% level of display lists during display-list execution. This limit must be at least 64,
+%% and it depends on the implementation.
+%%
+%% GL state is not saved and restored across a call to ``gl:callLists''. Thus, changes
+%% made to GL state during the execution of the display lists remain after execution is completed.
+%% Use {@link gl:pushAttrib/1} , {@link gl:pushAttrib/1} , {@link gl:pushMatrix/0} , and {@link gl:pushMatrix/0}
+%% to preserve GL state across ``gl:callLists'' calls.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallLists.xml">external</a> documentation.
+-spec callLists(Lists) -> ok when Lists :: [integer()].
+callLists(Lists) ->
+ cast(5108, <<(length(Lists)):?GLuint,
+ (<< <<C:?GLuint>> || C <- Lists>>)/binary,0:(((1+length(Lists)) rem 2)*32)>>).
-%% @spec (Size::integer(),Type::enum(),Buffer::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFeedbackBuffer.xml">external</a> documentation.
--spec feedbackBuffer(integer(),enum(),mem()) -> ok.
-feedbackBuffer(Size,Type,Buffer) ->
- send_bin(Buffer),
- call(5109, <<Size:?GLsizei,Type:?GLenum>>).
+%% @doc set the display-list base for
+%%
+%% {@link gl:callLists/1}
+%%
+%% {@link gl:callLists/1} specifies an array of offsets. Display-list names are generated
+%% by adding `Base' to each offset. Names that reference valid display lists are executed;
+%% the others are ignored.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glListBase.xml">external</a> documentation.
+-spec listBase(Base) -> ok when Base :: integer().
+listBase(Base) ->
+ cast(5109, <<Base:?GLuint>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFinish.xml">external</a> documentation.
--spec finish() -> ok.
-finish() ->
- cast(5110, <<>>).
+%% @doc Delimit the vertices of a primitive or a group of like primitives
+%%
+%% ``gl:'begin''' and {@link gl:'begin'/1} delimit the vertices that define a primitive or a group
+%% of like primitives. ``gl:'begin''' accepts a single argument that specifies in which of
+%% ten ways the vertices are interpreted. Taking n as an integer count starting at one,
+%% and N as the total number of vertices specified, the interpretations are as follows:
+%%
+%% `?GL_POINTS': Treats each vertex as a single point. Vertex n defines point n.
+%% N points are drawn.
+%%
+%% `?GL_LINES': Treats each pair of vertices as an independent line segment. Vertices
+%% 2 n-1 and 2 n define line n. N/2 lines are drawn.
+%%
+%% `?GL_LINE_STRIP': Draws a connected group of line segments from the first vertex
+%% to the last. Vertices n and n+1 define line n. N-1 lines are drawn.
+%%
+%% `?GL_LINE_LOOP': Draws a connected group of line segments from the first vertex
+%% to the last, then back to the first. Vertices n and n+1 define line n. The last
+%% line, however, is defined by vertices N and 1. N lines are drawn.
+%%
+%% `?GL_TRIANGLES': Treats each triplet of vertices as an independent triangle. Vertices
+%% 3 n-2, 3 n-1, and 3 n define triangle n. N/3 triangles are drawn.
+%%
+%% `?GL_TRIANGLE_STRIP': Draws a connected group of triangles. One triangle is defined
+%% for each vertex presented after the first two vertices. For odd n, vertices n, n+1,
+%% and n+2 define triangle n. For even n, vertices n+1, n, and n+2 define triangle
+%% n. N-2 triangles are drawn.
+%%
+%% `?GL_TRIANGLE_FAN': Draws a connected group of triangles. One triangle is defined
+%% for each vertex presented after the first two vertices. Vertices 1, n+1, and n+2
+%% define triangle n. N-2 triangles are drawn.
+%%
+%% `?GL_QUADS': Treats each group of four vertices as an independent quadrilateral.
+%% Vertices 4 n-3, 4 n-2, 4 n-1, and 4 n define quadrilateral n. N/4 quadrilaterals
+%% are drawn.
+%%
+%% `?GL_QUAD_STRIP': Draws a connected group of quadrilaterals. One quadrilateral is
+%% defined for each pair of vertices presented after the first pair. Vertices 2 n-1, 2
+%% n, 2 n+2, and 2 n+1 define quadrilateral n. N/2-1 quadrilaterals are drawn. Note
+%% that the order in which vertices are used to construct a quadrilateral from strip data
+%% is different from that used with independent data.
+%%
+%% `?GL_POLYGON': Draws a single, convex polygon. Vertices 1 through N define this
+%% polygon.
+%%
+%% Only a subset of GL commands can be used between ``gl:'begin''' and {@link gl:'begin'/1} .
+%% The commands are {@link gl:vertex2d/2} , {@link gl:color3b/3} , {@link gl:secondaryColor3b/3} , {@link gl:indexd/1}
+%% , {@link gl:normal3b/3} , {@link gl:fogCoordf/1} , {@link gl:texCoord1d/1} , {@link gl:multiTexCoord1d/2}
+%% , {@link gl:vertexAttrib1d/2} , {@link gl:evalCoord1d/1} , {@link gl:evalPoint1/1} , {@link gl:arrayElement/1}
+%% , {@link gl:materialf/3} , and {@link gl:edgeFlag/1} . Also, it is acceptable to use {@link gl:callList/1}
+%% or {@link gl:callLists/1} to execute display lists that include only the preceding commands.
+%% If any other GL command is executed between ``gl:'begin''' and {@link gl:'begin'/1} , the error
+%% flag is set and the command is ignored.
+%%
+%% Regardless of the value chosen for `Mode' , there is no limit to the number of vertices
+%% that can be defined between ``gl:'begin''' and {@link gl:'begin'/1} . Lines, triangles, quadrilaterals,
+%% and polygons that are incompletely specified are not drawn. Incomplete specification results
+%% when either too few vertices are provided to specify even a single primitive or when an
+%% incorrect multiple of vertices is specified. The incomplete primitive is ignored; the
+%% rest are drawn.
+%%
+%% The minimum specification of vertices for each primitive is as follows: 1 for a point,
+%% 2 for a line, 3 for a triangle, 4 for a quadrilateral, and 3 for a polygon. Modes that
+%% require a certain multiple of vertices are `?GL_LINES' (2), `?GL_TRIANGLES'
+%% (3), `?GL_QUADS' (4), and `?GL_QUAD_STRIP' (2).
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml">external</a> documentation.
+-spec 'begin'(Mode) -> ok when Mode :: enum().
+'begin'(Mode) ->
+ cast(5110, <<Mode:?GLenum>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml">external</a> documentation.
--spec flush() -> ok.
-flush() ->
+%% @doc
+%% See {@link 'begin'/1}
+-spec 'end'() -> ok.
+'end'() ->
cast(5111, <<>>).
-%% @spec (Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation.
--spec fogf(enum(),float()) -> ok.
-fogf(Pname,Param) ->
- cast(5112, <<Pname:?GLenum,Param:?GLfloat>>).
+%% @doc Specify a vertex
+%%
+%% ``gl:vertex'' commands are used within {@link gl:'begin'/1} / {@link gl:'begin'/1} pairs to specify
+%% point, line, and polygon vertices. The current color, normal, texture coordinates, and
+%% fog coordinate are associated with the vertex when ``gl:vertex'' is called.
+%%
+%% When only x and y are specified, z defaults to 0 and w defaults to 1. When x,
+%% y, and z are specified, w defaults to 1.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
+-spec vertex2d(X, Y) -> ok when X :: float(),Y :: float().
+vertex2d(X,Y) ->
+ cast(5112, <<X:?GLdouble,Y:?GLdouble>>).
-%% @spec (Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation.
--spec fogfv(enum(),{float()}) -> ok.
-fogfv(Pname,Params) ->
- cast(5113, <<Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex2f(X, Y) -> ok when X :: float(),Y :: float().
+vertex2f(X,Y) ->
+ cast(5113, <<X:?GLfloat,Y:?GLfloat>>).
-%% @spec (Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation.
--spec fogi(enum(),integer()) -> ok.
-fogi(Pname,Param) ->
- cast(5114, <<Pname:?GLenum,Param:?GLint>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex2i(X, Y) -> ok when X :: integer(),Y :: integer().
+vertex2i(X,Y) ->
+ cast(5114, <<X:?GLint,Y:?GLint>>).
-%% @spec (Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation.
--spec fogiv(enum(),{integer()}) -> ok.
-fogiv(Pname,Params) ->
- cast(5115, <<Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex2s(X, Y) -> ok when X :: integer(),Y :: integer().
+vertex2s(X,Y) ->
+ cast(5115, <<X:?GLshort,Y:?GLshort>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml">external</a> documentation.
--spec frontFace(enum()) -> ok.
-frontFace(Mode) ->
- cast(5116, <<Mode:?GLenum>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex3d(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+vertex3d(X,Y,Z) ->
+ cast(5116, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Left::float(),Right::float(),Bottom::float(),Top::float(),ZNear::float(),ZFar::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml">external</a> documentation.
--spec frustum(float(),float(),float(),float(),float(),float()) -> ok.
-frustum(Left,Right,Bottom,Top,ZNear,ZFar) ->
- cast(5117, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,ZNear:?GLdouble,ZFar:?GLdouble>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex3f(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+vertex3f(X,Y,Z) ->
+ cast(5117, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec (Range::integer()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenLists.xml">external</a> documentation.
--spec genLists(integer()) -> integer().
-genLists(Range) ->
- call(5118, <<Range:?GLsizei>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex3i(X, Y, Z) -> ok when X :: integer(),Y :: integer(),Z :: integer().
+vertex3i(X,Y,Z) ->
+ cast(5118, <<X:?GLint,Y:?GLint,Z:?GLint>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml">external</a> documentation.
--spec genTextures(integer()) -> [integer()].
-genTextures(N) ->
- call(5119, <<N:?GLsizei>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex3s(X, Y, Z) -> ok when X :: integer(),Y :: integer(),Z :: integer().
+vertex3s(X,Y,Z) ->
+ cast(5119, <<X:?GLshort,Y:?GLshort,Z:?GLshort>>).
-%% @spec (Pname::enum()) -> [0|1]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBooleanv.xml">external</a> documentation.
--spec getBooleanv(enum()) -> [0|1].
-getBooleanv(Pname) ->
- call(5120, <<Pname:?GLenum>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex4d(X, Y, Z, W) -> ok when X :: float(),Y :: float(),Z :: float(),W :: float().
+vertex4d(X,Y,Z,W) ->
+ cast(5120, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-%% @spec (Plane::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetClipPlane.xml">external</a> documentation.
--spec getClipPlane(enum()) -> {float(),float(),float(),float()}.
-getClipPlane(Plane) ->
- call(5121, <<Plane:?GLenum>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex4f(X, Y, Z, W) -> ok when X :: float(),Y :: float(),Z :: float(),W :: float().
+vertex4f(X,Y,Z,W) ->
+ cast(5121, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
-%% @spec (Pname::enum()) -> [float()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetDoublev.xml">external</a> documentation.
--spec getDoublev(enum()) -> [float()].
-getDoublev(Pname) ->
- call(5122, <<Pname:?GLenum>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex4i(X, Y, Z, W) -> ok when X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
+vertex4i(X,Y,Z,W) ->
+ cast(5122, <<X:?GLint,Y:?GLint,Z:?GLint,W:?GLint>>).
-%% @spec () -> enum()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml">external</a> documentation.
--spec getError() -> enum().
-getError() ->
- call(5123, <<>>).
+%% @doc
+%% See {@link vertex2d/2}
+-spec vertex4s(X, Y, Z, W) -> ok when X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
+vertex4s(X,Y,Z,W) ->
+ cast(5123, <<X:?GLshort,Y:?GLshort,Z:?GLshort,W:?GLshort>>).
-%% @spec (Pname::enum()) -> [float()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFloatv.xml">external</a> documentation.
--spec getFloatv(enum()) -> [float()].
-getFloatv(Pname) ->
- call(5124, <<Pname:?GLenum>>).
+%% @equiv vertex2d(X,Y)
+-spec vertex2dv(V) -> ok when V :: {X :: float(),Y :: float()}.
+vertex2dv({X,Y}) -> vertex2d(X,Y).
-%% @spec (Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetIntegerv.xml">external</a> documentation.
--spec getIntegerv(enum()) -> [integer()].
-getIntegerv(Pname) ->
- call(5125, <<Pname:?GLenum>>).
+%% @equiv vertex2f(X,Y)
+-spec vertex2fv(V) -> ok when V :: {X :: float(),Y :: float()}.
+vertex2fv({X,Y}) -> vertex2f(X,Y).
-%% @spec (Light::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml">external</a> documentation.
--spec getLightfv(enum(),enum()) -> {float(),float(),float(),float()}.
-getLightfv(Light,Pname) ->
- call(5126, <<Light:?GLenum,Pname:?GLenum>>).
+%% @equiv vertex2i(X,Y)
+-spec vertex2iv(V) -> ok when V :: {X :: integer(),Y :: integer()}.
+vertex2iv({X,Y}) -> vertex2i(X,Y).
-%% @spec (Light::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml">external</a> documentation.
--spec getLightiv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
-getLightiv(Light,Pname) ->
- call(5127, <<Light:?GLenum,Pname:?GLenum>>).
+%% @equiv vertex2s(X,Y)
+-spec vertex2sv(V) -> ok when V :: {X :: integer(),Y :: integer()}.
+vertex2sv({X,Y}) -> vertex2s(X,Y).
-%% @spec (Target::enum(),Query::enum(),V::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml">external</a> documentation.
--spec getMapdv(enum(),enum(),mem()) -> ok.
-getMapdv(Target,Query,V) ->
- send_bin(V),
- call(5128, <<Target:?GLenum,Query:?GLenum>>).
+%% @equiv vertex3d(X,Y,Z)
+-spec vertex3dv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
+vertex3dv({X,Y,Z}) -> vertex3d(X,Y,Z).
-%% @spec (Target::enum(),Query::enum(),V::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml">external</a> documentation.
--spec getMapfv(enum(),enum(),mem()) -> ok.
-getMapfv(Target,Query,V) ->
- send_bin(V),
- call(5129, <<Target:?GLenum,Query:?GLenum>>).
+%% @equiv vertex3f(X,Y,Z)
+-spec vertex3fv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
+vertex3fv({X,Y,Z}) -> vertex3f(X,Y,Z).
-%% @spec (Target::enum(),Query::enum(),V::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml">external</a> documentation.
--spec getMapiv(enum(),enum(),mem()) -> ok.
-getMapiv(Target,Query,V) ->
- send_bin(V),
- call(5130, <<Target:?GLenum,Query:?GLenum>>).
+%% @equiv vertex3i(X,Y,Z)
+-spec vertex3iv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
+vertex3iv({X,Y,Z}) -> vertex3i(X,Y,Z).
-%% @spec (Face::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml">external</a> documentation.
--spec getMaterialfv(enum(),enum()) -> {float(),float(),float(),float()}.
-getMaterialfv(Face,Pname) ->
- call(5131, <<Face:?GLenum,Pname:?GLenum>>).
+%% @equiv vertex3s(X,Y,Z)
+-spec vertex3sv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
+vertex3sv({X,Y,Z}) -> vertex3s(X,Y,Z).
-%% @spec (Face::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml">external</a> documentation.
--spec getMaterialiv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
-getMaterialiv(Face,Pname) ->
- call(5132, <<Face:?GLenum,Pname:?GLenum>>).
+%% @equiv vertex4d(X,Y,Z,W)
+-spec vertex4dv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
+vertex4dv({X,Y,Z,W}) -> vertex4d(X,Y,Z,W).
-%% @spec (Map::enum(),Values::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml">external</a> documentation.
--spec getPixelMapfv(enum(),mem()) -> ok.
-getPixelMapfv(Map,Values) ->
- send_bin(Values),
- call(5133, <<Map:?GLenum>>).
+%% @equiv vertex4f(X,Y,Z,W)
+-spec vertex4fv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
+vertex4fv({X,Y,Z,W}) -> vertex4f(X,Y,Z,W).
-%% @spec (Map::enum(),Values::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml">external</a> documentation.
--spec getPixelMapuiv(enum(),mem()) -> ok.
-getPixelMapuiv(Map,Values) ->
- send_bin(Values),
- call(5134, <<Map:?GLenum>>).
+%% @equiv vertex4i(X,Y,Z,W)
+-spec vertex4iv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
+vertex4iv({X,Y,Z,W}) -> vertex4i(X,Y,Z,W).
-%% @spec (Map::enum(),Values::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml">external</a> documentation.
--spec getPixelMapusv(enum(),mem()) -> ok.
-getPixelMapusv(Map,Values) ->
- send_bin(Values),
- call(5135, <<Map:?GLenum>>).
+%% @equiv vertex4s(X,Y,Z,W)
+-spec vertex4sv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
+vertex4sv({X,Y,Z,W}) -> vertex4s(X,Y,Z,W).
-%% @spec () -> binary()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPolygonStipple.xml">external</a> documentation.
--spec getPolygonStipple() -> binary().
-getPolygonStipple() ->
- call(5136, <<>>).
+%% @doc Set the current normal vector
+%%
+%% The current normal is set to the given coordinates whenever ``gl:normal'' is issued.
+%% Byte, short, or integer arguments are converted to floating-point format with a linear
+%% mapping that maps the most positive representable integer value to 1.0 and the most negative
+%% representable integer value to -1.0.
+%%
+%% Normals specified with ``gl:normal'' need not have unit length. If `?GL_NORMALIZE'
+%% is enabled, then normals of any length specified with ``gl:normal'' are normalized after
+%% transformation. If `?GL_RESCALE_NORMAL' is enabled, normals are scaled by a scaling
+%% factor derived from the modelview matrix. `?GL_RESCALE_NORMAL' requires that the
+%% originally specified normals were of unit length, and that the modelview matrix contain
+%% only uniform scales for proper results. To enable and disable normalization, call {@link gl:enable/1}
+%% and {@link gl:enable/1} with either `?GL_NORMALIZE' or `?GL_RESCALE_NORMAL'.
+%% Normalization is initially disabled.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
+-spec normal3b(Nx, Ny, Nz) -> ok when Nx :: integer(),Ny :: integer(),Nz :: integer().
+normal3b(Nx,Ny,Nz) ->
+ cast(5124, <<Nx:?GLbyte,Ny:?GLbyte,Nz:?GLbyte>>).
-%% @spec (Name::enum()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml">external</a> documentation.
--spec getString(enum()) -> string().
-getString(Name) ->
- call(5137, <<Name:?GLenum>>).
+%% @doc
+%% See {@link normal3b/3}
+-spec normal3d(Nx, Ny, Nz) -> ok when Nx :: float(),Ny :: float(),Nz :: float().
+normal3d(Nx,Ny,Nz) ->
+ cast(5125, <<Nx:?GLdouble,Ny:?GLdouble,Nz:?GLdouble>>).
-%% @spec (Target::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml">external</a> documentation.
--spec getTexEnvfv(enum(),enum()) -> {float(),float(),float(),float()}.
-getTexEnvfv(Target,Pname) ->
- call(5138, <<Target:?GLenum,Pname:?GLenum>>).
+%% @doc
+%% See {@link normal3b/3}
+-spec normal3f(Nx, Ny, Nz) -> ok when Nx :: float(),Ny :: float(),Nz :: float().
+normal3f(Nx,Ny,Nz) ->
+ cast(5126, <<Nx:?GLfloat,Ny:?GLfloat,Nz:?GLfloat>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml">external</a> documentation.
--spec getTexEnviv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
-getTexEnviv(Target,Pname) ->
- call(5139, <<Target:?GLenum,Pname:?GLenum>>).
+%% @doc
+%% See {@link normal3b/3}
+-spec normal3i(Nx, Ny, Nz) -> ok when Nx :: integer(),Ny :: integer(),Nz :: integer().
+normal3i(Nx,Ny,Nz) ->
+ cast(5127, <<Nx:?GLint,Ny:?GLint,Nz:?GLint>>).
-%% @spec (Coord::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml">external</a> documentation.
--spec getTexGendv(enum(),enum()) -> {float(),float(),float(),float()}.
-getTexGendv(Coord,Pname) ->
- call(5140, <<Coord:?GLenum,Pname:?GLenum>>).
+%% @doc
+%% See {@link normal3b/3}
+-spec normal3s(Nx, Ny, Nz) -> ok when Nx :: integer(),Ny :: integer(),Nz :: integer().
+normal3s(Nx,Ny,Nz) ->
+ cast(5128, <<Nx:?GLshort,Ny:?GLshort,Nz:?GLshort>>).
-%% @spec (Coord::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml">external</a> documentation.
--spec getTexGenfv(enum(),enum()) -> {float(),float(),float(),float()}.
-getTexGenfv(Coord,Pname) ->
- call(5141, <<Coord:?GLenum,Pname:?GLenum>>).
+%% @equiv normal3b(Nx,Ny,Nz)
+-spec normal3bv(V) -> ok when V :: {Nx :: integer(),Ny :: integer(),Nz :: integer()}.
+normal3bv({Nx,Ny,Nz}) -> normal3b(Nx,Ny,Nz).
-%% @spec (Coord::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml">external</a> documentation.
--spec getTexGeniv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
-getTexGeniv(Coord,Pname) ->
- call(5142, <<Coord:?GLenum,Pname:?GLenum>>).
+%% @equiv normal3d(Nx,Ny,Nz)
+-spec normal3dv(V) -> ok when V :: {Nx :: float(),Ny :: float(),Nz :: float()}.
+normal3dv({Nx,Ny,Nz}) -> normal3d(Nx,Ny,Nz).
-%% @spec (Target::enum(),Level::integer(),Format::enum(),Type::enum(),Pixels::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml">external</a> documentation.
--spec getTexImage(enum(),integer(),enum(),enum(),mem()) -> ok.
-getTexImage(Target,Level,Format,Type,Pixels) ->
- send_bin(Pixels),
- call(5143, <<Target:?GLenum,Level:?GLint,Format:?GLenum,Type:?GLenum>>).
+%% @equiv normal3f(Nx,Ny,Nz)
+-spec normal3fv(V) -> ok when V :: {Nx :: float(),Ny :: float(),Nz :: float()}.
+normal3fv({Nx,Ny,Nz}) -> normal3f(Nx,Ny,Nz).
-%% @spec (Target::enum(),Level::integer(),Pname::enum()) -> {float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml">external</a> documentation.
--spec getTexLevelParameterfv(enum(),integer(),enum()) -> {float()}.
-getTexLevelParameterfv(Target,Level,Pname) ->
- call(5144, <<Target:?GLenum,Level:?GLint,Pname:?GLenum>>).
+%% @equiv normal3i(Nx,Ny,Nz)
+-spec normal3iv(V) -> ok when V :: {Nx :: integer(),Ny :: integer(),Nz :: integer()}.
+normal3iv({Nx,Ny,Nz}) -> normal3i(Nx,Ny,Nz).
-%% @spec (Target::enum(),Level::integer(),Pname::enum()) -> {integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml">external</a> documentation.
--spec getTexLevelParameteriv(enum(),integer(),enum()) -> {integer()}.
-getTexLevelParameteriv(Target,Level,Pname) ->
- call(5145, <<Target:?GLenum,Level:?GLint,Pname:?GLenum>>).
+%% @equiv normal3s(Nx,Ny,Nz)
+-spec normal3sv(V) -> ok when V :: {Nx :: integer(),Ny :: integer(),Nz :: integer()}.
+normal3sv({Nx,Ny,Nz}) -> normal3s(Nx,Ny,Nz).
-%% @spec (Target::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml">external</a> documentation.
--spec getTexParameterfv(enum(),enum()) -> {float(),float(),float(),float()}.
-getTexParameterfv(Target,Pname) ->
- call(5146, <<Target:?GLenum,Pname:?GLenum>>).
+%% @doc Set the current color index
+%%
+%% ``gl:index'' updates the current (single-valued) color index. It takes one argument,
+%% the new value for the current color index.
+%%
+%% The current index is stored as a floating-point value. Integer values are converted directly
+%% to floating-point values, with no special mapping. The initial value is 1.
+%%
+%% Index values outside the representable range of the color index buffer are not clamped.
+%% However, before an index is dithered (if enabled) and written to the frame buffer, it
+%% is converted to fixed-point format. Any bits in the integer portion of the resulting fixed-point
+%% value that do not correspond to bits in the frame buffer are masked out.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
+-spec indexd(C) -> ok when C :: float().
+indexd(C) ->
+ cast(5129, <<C:?GLdouble>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml">external</a> documentation.
--spec getTexParameteriv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
-getTexParameteriv(Target,Pname) ->
- call(5147, <<Target:?GLenum,Pname:?GLenum>>).
+%% @doc
+%% See {@link indexd/1}
+-spec indexf(C) -> ok when C :: float().
+indexf(C) ->
+ cast(5130, <<C:?GLfloat>>).
-%% @spec (Target::enum(),Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHint.xml">external</a> documentation.
--spec hint(enum(),enum()) -> ok.
-hint(Target,Mode) ->
- cast(5148, <<Target:?GLenum,Mode:?GLenum>>).
+%% @doc
+%% See {@link indexd/1}
+-spec indexi(C) -> ok when C :: integer().
+indexi(C) ->
+ cast(5131, <<C:?GLint>>).
-%% @spec (Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexMask.xml">external</a> documentation.
--spec indexMask(integer()) -> ok.
-indexMask(Mask) ->
- cast(5149, <<Mask:?GLuint>>).
-
-%% @spec (Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexPointer.xml">external</a> documentation.
--spec indexPointer(enum(),integer(),offset()|mem()) -> ok.
-indexPointer(Type,Stride,Pointer) when is_integer(Pointer) ->
- cast(5150, <<Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
-indexPointer(Type,Stride,Pointer) ->
- send_bin(Pointer),
- cast(5151, <<Type:?GLenum,Stride:?GLsizei>>).
+%% @doc
+%% See {@link indexd/1}
+-spec indexs(C) -> ok when C :: integer().
+indexs(C) ->
+ cast(5132, <<C:?GLshort>>).
-%% @spec (C::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
--spec indexd(float()) -> ok.
-indexd(C) ->
- cast(5152, <<C:?GLdouble>>).
+%% @doc
+%% See {@link indexd/1}
+-spec indexub(C) -> ok when C :: integer().
+indexub(C) ->
+ cast(5133, <<C:?GLubyte>>).
-%% @spec ({C}) -> ok
%% @equiv indexd(C)
--spec indexdv({float()}) -> ok.
+-spec indexdv(C) -> ok when C :: {C :: float()}.
indexdv({C}) -> indexd(C).
-%% @spec (C::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
--spec indexf(float()) -> ok.
-indexf(C) ->
- cast(5153, <<C:?GLfloat>>).
-
-%% @spec ({C}) -> ok
%% @equiv indexf(C)
--spec indexfv({float()}) -> ok.
+-spec indexfv(C) -> ok when C :: {C :: float()}.
indexfv({C}) -> indexf(C).
-%% @spec (C::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
--spec indexi(integer()) -> ok.
-indexi(C) ->
- cast(5154, <<C:?GLint>>).
-
-%% @spec ({C}) -> ok
%% @equiv indexi(C)
--spec indexiv({integer()}) -> ok.
+-spec indexiv(C) -> ok when C :: {C :: integer()}.
indexiv({C}) -> indexi(C).
-%% @spec (C::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
--spec indexs(integer()) -> ok.
-indexs(C) ->
- cast(5155, <<C:?GLshort>>).
-
-%% @spec ({C}) -> ok
%% @equiv indexs(C)
--spec indexsv({integer()}) -> ok.
+-spec indexsv(C) -> ok when C :: {C :: integer()}.
indexsv({C}) -> indexs(C).
-%% @spec (C::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
--spec indexub(integer()) -> ok.
-indexub(C) ->
- cast(5156, <<C:?GLubyte>>).
-
-%% @spec ({C}) -> ok
%% @equiv indexub(C)
--spec indexubv({integer()}) -> ok.
+-spec indexubv(C) -> ok when C :: {C :: integer()}.
indexubv({C}) -> indexub(C).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInitNames.xml">external</a> documentation.
--spec initNames() -> ok.
-initNames() ->
- cast(5157, <<>>).
+%% @doc Set the current color
+%%
+%% The GL stores both a current single-valued color index and a current four-valued RGBA
+%% color. ``gl:color'' sets a new four-valued RGBA color. ``gl:color'' has two major
+%% variants: ``gl:color3'' and ``gl:color4''. ``gl:color3'' variants specify new red,
+%% green, and blue values explicitly and set the current alpha value to 1.0 (full intensity)
+%% implicitly. ``gl:color4'' variants specify all four color components explicitly.
+%%
+%% ``gl:color3b'', ``gl:color4b'', ``gl:color3s'', ``gl:color4s'', ``gl:color3i'',
+%% and ``gl:color4i'' take three or four signed byte, short, or long integers as arguments.
+%% When `v' is appended to the name, the color commands can take a pointer to an array
+%% of such values.
+%%
+%% Current color values are stored in floating-point format, with unspecified mantissa and
+%% exponent sizes. Unsigned integer color components, when specified, are linearly mapped
+%% to floating-point values such that the largest representable value maps to 1.0 (full intensity),
+%% and 0 maps to 0.0 (zero intensity). Signed integer color components, when specified, are
+%% linearly mapped to floating-point values such that the most positive representable value
+%% maps to 1.0, and the most negative representable value maps to -1.0. (Note that this
+%% mapping does not convert 0 precisely to 0.0.) Floating-point values are mapped directly.
+%%
+%% Neither floating-point nor signed integer values are clamped to the range [0 1] before the
+%% current color is updated. However, color components are clamped to this range before they
+%% are interpolated or written into a color buffer.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
+-spec color3b(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
+color3b(Red,Green,Blue) ->
+ cast(5134, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>).
-%% @spec (Format::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml">external</a> documentation.
--spec interleavedArrays(enum(),integer(),offset()|mem()) -> ok.
-interleavedArrays(Format,Stride,Pointer) when is_integer(Pointer) ->
- cast(5158, <<Format:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
-interleavedArrays(Format,Stride,Pointer) ->
- send_bin(Pointer),
- cast(5159, <<Format:?GLenum,Stride:?GLsizei>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3d(Red, Green, Blue) -> ok when Red :: float(),Green :: float(),Blue :: float().
+color3d(Red,Green,Blue) ->
+ cast(5135, <<Red:?GLdouble,Green:?GLdouble,Blue:?GLdouble>>).
-%% @spec (Cap::enum()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabled.xml">external</a> documentation.
--spec isEnabled(enum()) -> 0|1.
-isEnabled(Cap) ->
- call(5160, <<Cap:?GLenum>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3f(Red, Green, Blue) -> ok when Red :: float(),Green :: float(),Blue :: float().
+color3f(Red,Green,Blue) ->
+ cast(5136, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat>>).
-%% @spec (List::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsList.xml">external</a> documentation.
--spec isList(integer()) -> 0|1.
-isList(List) ->
- call(5161, <<List:?GLuint>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3i(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
+color3i(Red,Green,Blue) ->
+ cast(5137, <<Red:?GLint,Green:?GLint,Blue:?GLint>>).
-%% @spec (Texture::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml">external</a> documentation.
--spec isTexture(integer()) -> 0|1.
-isTexture(Texture) ->
- call(5162, <<Texture:?GLuint>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3s(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
+color3s(Red,Green,Blue) ->
+ cast(5138, <<Red:?GLshort,Green:?GLshort,Blue:?GLshort>>).
-%% @spec (Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation.
--spec lightModelf(enum(),float()) -> ok.
-lightModelf(Pname,Param) ->
- cast(5163, <<Pname:?GLenum,Param:?GLfloat>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3ub(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
+color3ub(Red,Green,Blue) ->
+ cast(5139, <<Red:?GLubyte,Green:?GLubyte,Blue:?GLubyte>>).
-%% @spec (Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation.
--spec lightModelfv(enum(),{float()}) -> ok.
-lightModelfv(Pname,Params) ->
- cast(5164, <<Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3ui(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
+color3ui(Red,Green,Blue) ->
+ cast(5140, <<Red:?GLuint,Green:?GLuint,Blue:?GLuint>>).
-%% @spec (Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation.
--spec lightModeli(enum(),integer()) -> ok.
-lightModeli(Pname,Param) ->
- cast(5165, <<Pname:?GLenum,Param:?GLint>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color3us(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
+color3us(Red,Green,Blue) ->
+ cast(5141, <<Red:?GLushort,Green:?GLushort,Blue:?GLushort>>).
-%% @spec (Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation.
--spec lightModeliv(enum(),{integer()}) -> ok.
-lightModeliv(Pname,Params) ->
- cast(5166, <<Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4b(Red, Green, Blue, Alpha) -> ok when Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer().
+color4b(Red,Green,Blue,Alpha) ->
+ cast(5142, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte,Alpha:?GLbyte>>).
-%% @spec (Light::enum(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation.
--spec lightf(enum(),enum(),float()) -> ok.
-lightf(Light,Pname,Param) ->
- cast(5167, <<Light:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4d(Red, Green, Blue, Alpha) -> ok when Red :: float(),Green :: float(),Blue :: float(),Alpha :: float().
+color4d(Red,Green,Blue,Alpha) ->
+ cast(5143, <<Red:?GLdouble,Green:?GLdouble,Blue:?GLdouble,Alpha:?GLdouble>>).
-%% @spec (Light::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation.
--spec lightfv(enum(),enum(),{float()}) -> ok.
-lightfv(Light,Pname,Params) ->
- cast(5168, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4f(Red, Green, Blue, Alpha) -> ok when Red :: float(),Green :: float(),Blue :: float(),Alpha :: float().
+color4f(Red,Green,Blue,Alpha) ->
+ cast(5144, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat,Alpha:?GLfloat>>).
-%% @spec (Light::enum(),Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation.
--spec lighti(enum(),enum(),integer()) -> ok.
-lighti(Light,Pname,Param) ->
- cast(5169, <<Light:?GLenum,Pname:?GLenum,Param:?GLint>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4i(Red, Green, Blue, Alpha) -> ok when Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer().
+color4i(Red,Green,Blue,Alpha) ->
+ cast(5145, <<Red:?GLint,Green:?GLint,Blue:?GLint,Alpha:?GLint>>).
-%% @spec (Light::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation.
--spec lightiv(enum(),enum(),{integer()}) -> ok.
-lightiv(Light,Pname,Params) ->
- cast(5170, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4s(Red, Green, Blue, Alpha) -> ok when Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer().
+color4s(Red,Green,Blue,Alpha) ->
+ cast(5146, <<Red:?GLshort,Green:?GLshort,Blue:?GLshort,Alpha:?GLshort>>).
-%% @spec (Factor::integer(),Pattern::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineStipple.xml">external</a> documentation.
--spec lineStipple(integer(),integer()) -> ok.
-lineStipple(Factor,Pattern) ->
- cast(5171, <<Factor:?GLint,Pattern:?GLushort>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4ub(Red, Green, Blue, Alpha) -> ok when Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer().
+color4ub(Red,Green,Blue,Alpha) ->
+ cast(5147, <<Red:?GLubyte,Green:?GLubyte,Blue:?GLubyte,Alpha:?GLubyte>>).
-%% @spec (Width::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml">external</a> documentation.
--spec lineWidth(float()) -> ok.
-lineWidth(Width) ->
- cast(5172, <<Width:?GLfloat>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4ui(Red, Green, Blue, Alpha) -> ok when Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer().
+color4ui(Red,Green,Blue,Alpha) ->
+ cast(5148, <<Red:?GLuint,Green:?GLuint,Blue:?GLuint,Alpha:?GLuint>>).
-%% @spec (Base::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glListBase.xml">external</a> documentation.
--spec listBase(integer()) -> ok.
-listBase(Base) ->
- cast(5173, <<Base:?GLuint>>).
+%% @doc
+%% See {@link color3b/3}
+-spec color4us(Red, Green, Blue, Alpha) -> ok when Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer().
+color4us(Red,Green,Blue,Alpha) ->
+ cast(5149, <<Red:?GLushort,Green:?GLushort,Blue:?GLushort,Alpha:?GLushort>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml">external</a> documentation.
--spec loadIdentity() -> ok.
-loadIdentity() ->
- cast(5174, <<>>).
+%% @equiv color3b(Red,Green,Blue)
+-spec color3bv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
+color3bv({Red,Green,Blue}) -> color3b(Red,Green,Blue).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml">external</a> documentation.
--spec loadMatrixd({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
-loadMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
- cast(5175, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
-loadMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
- cast(5175, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
+%% @equiv color3d(Red,Green,Blue)
+-spec color3dv(V) -> ok when V :: {Red :: float(),Green :: float(),Blue :: float()}.
+color3dv({Red,Green,Blue}) -> color3d(Red,Green,Blue).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml">external</a> documentation.
--spec loadMatrixf({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
-loadMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
- cast(5176, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
-loadMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
- cast(5176, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
+%% @equiv color3f(Red,Green,Blue)
+-spec color3fv(V) -> ok when V :: {Red :: float(),Green :: float(),Blue :: float()}.
+color3fv({Red,Green,Blue}) -> color3f(Red,Green,Blue).
-%% @spec (Name::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadName.xml">external</a> documentation.
--spec loadName(integer()) -> ok.
-loadName(Name) ->
- cast(5177, <<Name:?GLuint>>).
+%% @equiv color3i(Red,Green,Blue)
+-spec color3iv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
+color3iv({Red,Green,Blue}) -> color3i(Red,Green,Blue).
-%% @spec (Opcode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml">external</a> documentation.
--spec logicOp(enum()) -> ok.
-logicOp(Opcode) ->
- cast(5178, <<Opcode:?GLenum>>).
+%% @equiv color3s(Red,Green,Blue)
+-spec color3sv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
+color3sv({Red,Green,Blue}) -> color3s(Red,Green,Blue).
-%% @spec (Target::enum(),U1::float(),U2::float(),Stride::integer(),Order::integer(),Points::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
--spec map1d(enum(),float(),float(),integer(),integer(),binary()) -> ok.
-map1d(Target,U1,U2,Stride,Order,Points) ->
- send_bin(Points),
- cast(5179, <<Target:?GLenum,0:32,U1:?GLdouble,U2:?GLdouble,Stride:?GLint,Order:?GLint>>).
+%% @equiv color3ub(Red,Green,Blue)
+-spec color3ubv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
+color3ubv({Red,Green,Blue}) -> color3ub(Red,Green,Blue).
-%% @spec (Target::enum(),U1::float(),U2::float(),Stride::integer(),Order::integer(),Points::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
--spec map1f(enum(),float(),float(),integer(),integer(),binary()) -> ok.
-map1f(Target,U1,U2,Stride,Order,Points) ->
- send_bin(Points),
- cast(5180, <<Target:?GLenum,U1:?GLfloat,U2:?GLfloat,Stride:?GLint,Order:?GLint>>).
+%% @equiv color3ui(Red,Green,Blue)
+-spec color3uiv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
+color3uiv({Red,Green,Blue}) -> color3ui(Red,Green,Blue).
-%% @spec (Target::enum(),U1::float(),U2::float(),Ustride::integer(),Uorder::integer(),V1::float(),V2::float(),Vstride::integer(),Vorder::integer(),Points::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
--spec map2d(enum(),float(),float(),integer(),integer(),float(),float(),integer(),integer(),binary()) -> ok.
-map2d(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
- send_bin(Points),
- cast(5181, <<Target:?GLenum,0:32,U1:?GLdouble,U2:?GLdouble,Ustride:?GLint,Uorder:?GLint,V1:?GLdouble,V2:?GLdouble,Vstride:?GLint,Vorder:?GLint>>).
+%% @equiv color3us(Red,Green,Blue)
+-spec color3usv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
+color3usv({Red,Green,Blue}) -> color3us(Red,Green,Blue).
-%% @spec (Target::enum(),U1::float(),U2::float(),Ustride::integer(),Uorder::integer(),V1::float(),V2::float(),Vstride::integer(),Vorder::integer(),Points::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
--spec map2f(enum(),float(),float(),integer(),integer(),float(),float(),integer(),integer(),binary()) -> ok.
-map2f(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
- send_bin(Points),
- cast(5182, <<Target:?GLenum,U1:?GLfloat,U2:?GLfloat,Ustride:?GLint,Uorder:?GLint,V1:?GLfloat,V2:?GLfloat,Vstride:?GLint,Vorder:?GLint>>).
+%% @equiv color4b(Red,Green,Blue,Alpha)
+-spec color4bv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer()}.
+color4bv({Red,Green,Blue,Alpha}) -> color4b(Red,Green,Blue,Alpha).
-%% @spec (Un::integer(),U1::float(),U2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation.
--spec mapGrid1d(integer(),float(),float()) -> ok.
-mapGrid1d(Un,U1,U2) ->
- cast(5183, <<Un:?GLint,0:32,U1:?GLdouble,U2:?GLdouble>>).
+%% @equiv color4d(Red,Green,Blue,Alpha)
+-spec color4dv(V) -> ok when V :: {Red :: float(),Green :: float(),Blue :: float(),Alpha :: float()}.
+color4dv({Red,Green,Blue,Alpha}) -> color4d(Red,Green,Blue,Alpha).
-%% @spec (Un::integer(),U1::float(),U2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation.
--spec mapGrid1f(integer(),float(),float()) -> ok.
-mapGrid1f(Un,U1,U2) ->
- cast(5184, <<Un:?GLint,U1:?GLfloat,U2:?GLfloat>>).
+%% @equiv color4f(Red,Green,Blue,Alpha)
+-spec color4fv(V) -> ok when V :: {Red :: float(),Green :: float(),Blue :: float(),Alpha :: float()}.
+color4fv({Red,Green,Blue,Alpha}) -> color4f(Red,Green,Blue,Alpha).
-%% @spec (Un::integer(),U1::float(),U2::float(),Vn::integer(),V1::float(),V2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation.
--spec mapGrid2d(integer(),float(),float(),integer(),float(),float()) -> ok.
-mapGrid2d(Un,U1,U2,Vn,V1,V2) ->
- cast(5185, <<Un:?GLint,0:32,U1:?GLdouble,U2:?GLdouble,Vn:?GLint,0:32,V1:?GLdouble,V2:?GLdouble>>).
+%% @equiv color4i(Red,Green,Blue,Alpha)
+-spec color4iv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer()}.
+color4iv({Red,Green,Blue,Alpha}) -> color4i(Red,Green,Blue,Alpha).
-%% @spec (Un::integer(),U1::float(),U2::float(),Vn::integer(),V1::float(),V2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation.
--spec mapGrid2f(integer(),float(),float(),integer(),float(),float()) -> ok.
-mapGrid2f(Un,U1,U2,Vn,V1,V2) ->
- cast(5186, <<Un:?GLint,U1:?GLfloat,U2:?GLfloat,Vn:?GLint,V1:?GLfloat,V2:?GLfloat>>).
+%% @equiv color4s(Red,Green,Blue,Alpha)
+-spec color4sv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer()}.
+color4sv({Red,Green,Blue,Alpha}) -> color4s(Red,Green,Blue,Alpha).
-%% @spec (Face::enum(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation.
--spec materialf(enum(),enum(),float()) -> ok.
-materialf(Face,Pname,Param) ->
- cast(5187, <<Face:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
+%% @equiv color4ub(Red,Green,Blue,Alpha)
+-spec color4ubv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer()}.
+color4ubv({Red,Green,Blue,Alpha}) -> color4ub(Red,Green,Blue,Alpha).
-%% @spec (Face::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation.
--spec materialfv(enum(),enum(),{float()}) -> ok.
-materialfv(Face,Pname,Params) ->
- cast(5188, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @equiv color4ui(Red,Green,Blue,Alpha)
+-spec color4uiv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer()}.
+color4uiv({Red,Green,Blue,Alpha}) -> color4ui(Red,Green,Blue,Alpha).
-%% @spec (Face::enum(),Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation.
--spec materiali(enum(),enum(),integer()) -> ok.
-materiali(Face,Pname,Param) ->
- cast(5189, <<Face:?GLenum,Pname:?GLenum,Param:?GLint>>).
+%% @equiv color4us(Red,Green,Blue,Alpha)
+-spec color4usv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer(),Alpha :: integer()}.
+color4usv({Red,Green,Blue,Alpha}) -> color4us(Red,Green,Blue,Alpha).
-%% @spec (Face::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation.
--spec materialiv(enum(),enum(),{integer()}) -> ok.
-materialiv(Face,Pname,Params) ->
- cast(5190, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @doc Set the current texture coordinates
+%%
+%% ``gl:texCoord'' specifies texture coordinates in one, two, three, or four dimensions. ``gl:texCoord1''
+%% sets the current texture coordinates to (s 0 0 1); a call to ``gl:texCoord2'' sets them to (s t
+%% 0 1).
+%% Similarly, ``gl:texCoord3'' specifies the texture coordinates as (s t r 1), and ``gl:texCoord4''
+%% defines all four components explicitly as (s t r q).
+%%
+%% The current texture coordinates are part of the data that is associated with each vertex
+%% and with the current raster position. Initially, the values for `s', `t', `r'
+%% , and `q' are (0, 0, 0, 1).
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
+-spec texCoord1d(S) -> ok when S :: float().
+texCoord1d(S) ->
+ cast(5150, <<S:?GLdouble>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml">external</a> documentation.
--spec matrixMode(enum()) -> ok.
-matrixMode(Mode) ->
- cast(5191, <<Mode:?GLenum>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord1f(S) -> ok when S :: float().
+texCoord1f(S) ->
+ cast(5151, <<S:?GLfloat>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml">external</a> documentation.
--spec multMatrixd({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
-multMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
- cast(5192, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
-multMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
- cast(5192, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord1i(S) -> ok when S :: integer().
+texCoord1i(S) ->
+ cast(5152, <<S:?GLint>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml">external</a> documentation.
--spec multMatrixf({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
-multMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
- cast(5193, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
-multMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
- cast(5193, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord1s(S) -> ok when S :: integer().
+texCoord1s(S) ->
+ cast(5153, <<S:?GLshort>>).
-%% @spec (List::integer(),Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml">external</a> documentation.
--spec newList(integer(),enum()) -> ok.
-newList(List,Mode) ->
- cast(5194, <<List:?GLuint,Mode:?GLenum>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord2d(S, T) -> ok when S :: float(),T :: float().
+texCoord2d(S,T) ->
+ cast(5154, <<S:?GLdouble,T:?GLdouble>>).
-%% @spec (Nx::integer(),Ny::integer(),Nz::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
--spec normal3b(integer(),integer(),integer()) -> ok.
-normal3b(Nx,Ny,Nz) ->
- cast(5195, <<Nx:?GLbyte,Ny:?GLbyte,Nz:?GLbyte>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord2f(S, T) -> ok when S :: float(),T :: float().
+texCoord2f(S,T) ->
+ cast(5155, <<S:?GLfloat,T:?GLfloat>>).
-%% @spec ({Nx,Ny,Nz}) -> ok
-%% @equiv normal3b(Nx,Ny,Nz)
--spec normal3bv({integer(),integer(),integer()}) -> ok.
-normal3bv({Nx,Ny,Nz}) -> normal3b(Nx,Ny,Nz).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord2i(S, T) -> ok when S :: integer(),T :: integer().
+texCoord2i(S,T) ->
+ cast(5156, <<S:?GLint,T:?GLint>>).
-%% @spec (Nx::float(),Ny::float(),Nz::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
--spec normal3d(float(),float(),float()) -> ok.
-normal3d(Nx,Ny,Nz) ->
- cast(5196, <<Nx:?GLdouble,Ny:?GLdouble,Nz:?GLdouble>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord2s(S, T) -> ok when S :: integer(),T :: integer().
+texCoord2s(S,T) ->
+ cast(5157, <<S:?GLshort,T:?GLshort>>).
-%% @spec ({Nx,Ny,Nz}) -> ok
-%% @equiv normal3d(Nx,Ny,Nz)
--spec normal3dv({float(),float(),float()}) -> ok.
-normal3dv({Nx,Ny,Nz}) -> normal3d(Nx,Ny,Nz).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord3d(S, T, R) -> ok when S :: float(),T :: float(),R :: float().
+texCoord3d(S,T,R) ->
+ cast(5158, <<S:?GLdouble,T:?GLdouble,R:?GLdouble>>).
-%% @spec (Nx::float(),Ny::float(),Nz::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
--spec normal3f(float(),float(),float()) -> ok.
-normal3f(Nx,Ny,Nz) ->
- cast(5197, <<Nx:?GLfloat,Ny:?GLfloat,Nz:?GLfloat>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord3f(S, T, R) -> ok when S :: float(),T :: float(),R :: float().
+texCoord3f(S,T,R) ->
+ cast(5159, <<S:?GLfloat,T:?GLfloat,R:?GLfloat>>).
-%% @spec ({Nx,Ny,Nz}) -> ok
-%% @equiv normal3f(Nx,Ny,Nz)
--spec normal3fv({float(),float(),float()}) -> ok.
-normal3fv({Nx,Ny,Nz}) -> normal3f(Nx,Ny,Nz).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord3i(S, T, R) -> ok when S :: integer(),T :: integer(),R :: integer().
+texCoord3i(S,T,R) ->
+ cast(5160, <<S:?GLint,T:?GLint,R:?GLint>>).
-%% @spec (Nx::integer(),Ny::integer(),Nz::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
--spec normal3i(integer(),integer(),integer()) -> ok.
-normal3i(Nx,Ny,Nz) ->
- cast(5198, <<Nx:?GLint,Ny:?GLint,Nz:?GLint>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord3s(S, T, R) -> ok when S :: integer(),T :: integer(),R :: integer().
+texCoord3s(S,T,R) ->
+ cast(5161, <<S:?GLshort,T:?GLshort,R:?GLshort>>).
-%% @spec ({Nx,Ny,Nz}) -> ok
-%% @equiv normal3i(Nx,Ny,Nz)
--spec normal3iv({integer(),integer(),integer()}) -> ok.
-normal3iv({Nx,Ny,Nz}) -> normal3i(Nx,Ny,Nz).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord4d(S, T, R, Q) -> ok when S :: float(),T :: float(),R :: float(),Q :: float().
+texCoord4d(S,T,R,Q) ->
+ cast(5162, <<S:?GLdouble,T:?GLdouble,R:?GLdouble,Q:?GLdouble>>).
-%% @spec (Nx::integer(),Ny::integer(),Nz::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
--spec normal3s(integer(),integer(),integer()) -> ok.
-normal3s(Nx,Ny,Nz) ->
- cast(5199, <<Nx:?GLshort,Ny:?GLshort,Nz:?GLshort>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord4f(S, T, R, Q) -> ok when S :: float(),T :: float(),R :: float(),Q :: float().
+texCoord4f(S,T,R,Q) ->
+ cast(5163, <<S:?GLfloat,T:?GLfloat,R:?GLfloat,Q:?GLfloat>>).
-%% @spec ({Nx,Ny,Nz}) -> ok
-%% @equiv normal3s(Nx,Ny,Nz)
--spec normal3sv({integer(),integer(),integer()}) -> ok.
-normal3sv({Nx,Ny,Nz}) -> normal3s(Nx,Ny,Nz).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord4i(S, T, R, Q) -> ok when S :: integer(),T :: integer(),R :: integer(),Q :: integer().
+texCoord4i(S,T,R,Q) ->
+ cast(5164, <<S:?GLint,T:?GLint,R:?GLint,Q:?GLint>>).
-%% @spec (Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormalPointer.xml">external</a> documentation.
--spec normalPointer(enum(),integer(),offset()|mem()) -> ok.
-normalPointer(Type,Stride,Pointer) when is_integer(Pointer) ->
- cast(5200, <<Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
-normalPointer(Type,Stride,Pointer) ->
- send_bin(Pointer),
- cast(5201, <<Type:?GLenum,Stride:?GLsizei>>).
+%% @doc
+%% See {@link texCoord1d/1}
+-spec texCoord4s(S, T, R, Q) -> ok when S :: integer(),T :: integer(),R :: integer(),Q :: integer().
+texCoord4s(S,T,R,Q) ->
+ cast(5165, <<S:?GLshort,T:?GLshort,R:?GLshort,Q:?GLshort>>).
-%% @spec (Left::float(),Right::float(),Bottom::float(),Top::float(),ZNear::float(),ZFar::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml">external</a> documentation.
--spec ortho(float(),float(),float(),float(),float(),float()) -> ok.
-ortho(Left,Right,Bottom,Top,ZNear,ZFar) ->
- cast(5202, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,ZNear:?GLdouble,ZFar:?GLdouble>>).
+%% @equiv texCoord1d(S)
+-spec texCoord1dv(V) -> ok when V :: {S :: float()}.
+texCoord1dv({S}) -> texCoord1d(S).
-%% @spec (Token::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPassThrough.xml">external</a> documentation.
--spec passThrough(float()) -> ok.
-passThrough(Token) ->
- cast(5203, <<Token:?GLfloat>>).
+%% @equiv texCoord1f(S)
+-spec texCoord1fv(V) -> ok when V :: {S :: float()}.
+texCoord1fv({S}) -> texCoord1f(S).
-%% @spec (Map::enum(),Mapsize::integer(),Values::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml">external</a> documentation.
--spec pixelMapfv(enum(),integer(),binary()) -> ok.
-pixelMapfv(Map,Mapsize,Values) ->
- send_bin(Values),
- cast(5204, <<Map:?GLenum,Mapsize:?GLsizei>>).
+%% @equiv texCoord1i(S)
+-spec texCoord1iv(V) -> ok when V :: {S :: integer()}.
+texCoord1iv({S}) -> texCoord1i(S).
-%% @spec (Map::enum(),Mapsize::integer(),Values::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml">external</a> documentation.
--spec pixelMapuiv(enum(),integer(),binary()) -> ok.
-pixelMapuiv(Map,Mapsize,Values) ->
- send_bin(Values),
- cast(5205, <<Map:?GLenum,Mapsize:?GLsizei>>).
+%% @equiv texCoord1s(S)
+-spec texCoord1sv(V) -> ok when V :: {S :: integer()}.
+texCoord1sv({S}) -> texCoord1s(S).
-%% @spec (Map::enum(),Mapsize::integer(),Values::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml">external</a> documentation.
--spec pixelMapusv(enum(),integer(),binary()) -> ok.
-pixelMapusv(Map,Mapsize,Values) ->
- send_bin(Values),
- cast(5206, <<Map:?GLenum,Mapsize:?GLsizei>>).
+%% @equiv texCoord2d(S,T)
+-spec texCoord2dv(V) -> ok when V :: {S :: float(),T :: float()}.
+texCoord2dv({S,T}) -> texCoord2d(S,T).
-%% @spec (Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml">external</a> documentation.
--spec pixelStoref(enum(),float()) -> ok.
-pixelStoref(Pname,Param) ->
- cast(5207, <<Pname:?GLenum,Param:?GLfloat>>).
+%% @equiv texCoord2f(S,T)
+-spec texCoord2fv(V) -> ok when V :: {S :: float(),T :: float()}.
+texCoord2fv({S,T}) -> texCoord2f(S,T).
-%% @spec (Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml">external</a> documentation.
--spec pixelStorei(enum(),integer()) -> ok.
-pixelStorei(Pname,Param) ->
- cast(5208, <<Pname:?GLenum,Param:?GLint>>).
+%% @equiv texCoord2i(S,T)
+-spec texCoord2iv(V) -> ok when V :: {S :: integer(),T :: integer()}.
+texCoord2iv({S,T}) -> texCoord2i(S,T).
-%% @spec (Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml">external</a> documentation.
--spec pixelTransferf(enum(),float()) -> ok.
-pixelTransferf(Pname,Param) ->
- cast(5209, <<Pname:?GLenum,Param:?GLfloat>>).
+%% @equiv texCoord2s(S,T)
+-spec texCoord2sv(V) -> ok when V :: {S :: integer(),T :: integer()}.
+texCoord2sv({S,T}) -> texCoord2s(S,T).
-%% @spec (Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml">external</a> documentation.
--spec pixelTransferi(enum(),integer()) -> ok.
-pixelTransferi(Pname,Param) ->
- cast(5210, <<Pname:?GLenum,Param:?GLint>>).
+%% @equiv texCoord3d(S,T,R)
+-spec texCoord3dv(V) -> ok when V :: {S :: float(),T :: float(),R :: float()}.
+texCoord3dv({S,T,R}) -> texCoord3d(S,T,R).
-%% @spec (Xfactor::float(),Yfactor::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelZoom.xml">external</a> documentation.
--spec pixelZoom(float(),float()) -> ok.
-pixelZoom(Xfactor,Yfactor) ->
- cast(5211, <<Xfactor:?GLfloat,Yfactor:?GLfloat>>).
+%% @equiv texCoord3f(S,T,R)
+-spec texCoord3fv(V) -> ok when V :: {S :: float(),T :: float(),R :: float()}.
+texCoord3fv({S,T,R}) -> texCoord3f(S,T,R).
-%% @spec (Size::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml">external</a> documentation.
--spec pointSize(float()) -> ok.
-pointSize(Size) ->
- cast(5212, <<Size:?GLfloat>>).
+%% @equiv texCoord3i(S,T,R)
+-spec texCoord3iv(V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer()}.
+texCoord3iv({S,T,R}) -> texCoord3i(S,T,R).
-%% @spec (Face::enum(),Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml">external</a> documentation.
--spec polygonMode(enum(),enum()) -> ok.
-polygonMode(Face,Mode) ->
- cast(5213, <<Face:?GLenum,Mode:?GLenum>>).
+%% @equiv texCoord3s(S,T,R)
+-spec texCoord3sv(V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer()}.
+texCoord3sv({S,T,R}) -> texCoord3s(S,T,R).
-%% @spec (Factor::float(),Units::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml">external</a> documentation.
--spec polygonOffset(float(),float()) -> ok.
-polygonOffset(Factor,Units) ->
- cast(5214, <<Factor:?GLfloat,Units:?GLfloat>>).
+%% @equiv texCoord4d(S,T,R,Q)
+-spec texCoord4dv(V) -> ok when V :: {S :: float(),T :: float(),R :: float(),Q :: float()}.
+texCoord4dv({S,T,R,Q}) -> texCoord4d(S,T,R,Q).
-%% @spec (Mask::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonStipple.xml">external</a> documentation.
--spec polygonStipple(binary()) -> ok.
-polygonStipple(Mask) ->
- send_bin(Mask),
- cast(5215, <<>>).
+%% @equiv texCoord4f(S,T,R,Q)
+-spec texCoord4fv(V) -> ok when V :: {S :: float(),T :: float(),R :: float(),Q :: float()}.
+texCoord4fv({S,T,R,Q}) -> texCoord4f(S,T,R,Q).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPopAttrib.xml">external</a> documentation.
--spec popAttrib() -> ok.
-popAttrib() ->
- cast(5216, <<>>).
+%% @equiv texCoord4i(S,T,R,Q)
+-spec texCoord4iv(V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer(),Q :: integer()}.
+texCoord4iv({S,T,R,Q}) -> texCoord4i(S,T,R,Q).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPopClientAttrib.xml">external</a> documentation.
--spec popClientAttrib() -> ok.
-popClientAttrib() ->
- cast(5217, <<>>).
+%% @equiv texCoord4s(S,T,R,Q)
+-spec texCoord4sv(V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer(),Q :: integer()}.
+texCoord4sv({S,T,R,Q}) -> texCoord4s(S,T,R,Q).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPopMatrix.xml">external</a> documentation.
--spec popMatrix() -> ok.
-popMatrix() ->
- cast(5218, <<>>).
+%% @doc Specify the raster position for pixel operations
+%%
+%% The GL maintains a 3D position in window coordinates. This position, called the raster
+%% position, is used to position pixel and bitmap write operations. It is maintained with
+%% subpixel accuracy. See {@link gl:bitmap/7} , {@link gl:drawPixels/5} , and {@link gl:copyPixels/5}
+%% .
+%%
+%% The current raster position consists of three window coordinates ( x, y, z), a clip
+%% coordinate value ( w), an eye coordinate distance, a valid bit, and associated color
+%% data and texture coordinates. The w coordinate is a clip coordinate, because w is
+%% not projected to window coordinates. ``gl:rasterPos4'' specifies object coordinates x,
+%% y, z, and w explicitly. ``gl:rasterPos3'' specifies object coordinate x, y, and
+%% z explicitly, while w is implicitly set to 1. ``gl:rasterPos2'' uses the argument
+%% values for x and y while implicitly setting z and w to 0 and 1.
+%%
+%% The object coordinates presented by ``gl:rasterPos'' are treated just like those of a {@link gl:vertex2d/2}
+%% command: They are transformed by the current modelview and projection matrices and passed
+%% to the clipping stage. If the vertex is not culled, then it is projected and scaled to
+%% window coordinates, which become the new current raster position, and the `?GL_CURRENT_RASTER_POSITION_VALID'
+%% flag is set. If the vertex `is' culled, then the valid bit is cleared and the current
+%% raster position and associated color and texture coordinates are undefined.
+%%
+%% The current raster position also includes some associated color data and texture coordinates.
+%% If lighting is enabled, then `?GL_CURRENT_RASTER_COLOR' (in RGBA mode) or `?GL_CURRENT_RASTER_INDEX'
+%% (in color index mode) is set to the color produced by the lighting calculation (see {@link gl:lightf/3}
+%% , {@link gl:lightModelf/2} , and {@link gl:shadeModel/1} ). If lighting is disabled, current
+%% color (in RGBA mode, state variable `?GL_CURRENT_COLOR') or color index (in color
+%% index mode, state variable `?GL_CURRENT_INDEX') is used to update the current raster
+%% color. `?GL_CURRENT_RASTER_SECONDARY_COLOR' (in RGBA mode) is likewise updated.
+%%
+%% Likewise, `?GL_CURRENT_RASTER_TEXTURE_COORDS' is updated as a function of `?GL_CURRENT_TEXTURE_COORDS'
+%% , based on the texture matrix and the texture generation functions (see {@link gl:texGend/3} ).
+%% Finally, the distance from the origin of the eye coordinate system to the vertex as transformed
+%% by only the modelview matrix replaces `?GL_CURRENT_RASTER_DISTANCE'.
+%%
+%% Initially, the current raster position is (0, 0, 0, 1), the current raster distance is
+%% 0, the valid bit is set, the associated RGBA color is (1, 1, 1, 1), the associated color
+%% index is 1, and the associated texture coordinates are (0, 0, 0, 1). In RGBA mode, `?GL_CURRENT_RASTER_INDEX'
+%% is always 1; in color index mode, the current raster RGBA color always maintains its
+%% initial value.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
+-spec rasterPos2d(X, Y) -> ok when X :: float(),Y :: float().
+rasterPos2d(X,Y) ->
+ cast(5166, <<X:?GLdouble,Y:?GLdouble>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPopName.xml">external</a> documentation.
--spec popName() -> ok.
-popName() ->
- cast(5219, <<>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos2f(X, Y) -> ok when X :: float(),Y :: float().
+rasterPos2f(X,Y) ->
+ cast(5167, <<X:?GLfloat,Y:?GLfloat>>).
-%% @spec (Textures::[integer()],Priorities::[clamp()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrioritizeTextures.xml">external</a> documentation.
--spec prioritizeTextures([integer()],[clamp()]) -> ok.
-prioritizeTextures(Textures,Priorities) ->
- cast(5220, <<(length(Textures)):?GLuint,
- (<< <<C:?GLuint>> || C <- Textures>>)/binary,0:(((1+length(Textures)) rem 2)*32),(length(Priorities)):?GLuint,
- (<< <<C:?GLclampf>> || C <- Priorities>>)/binary,0:(((1+length(Priorities)) rem 2)*32)>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos2i(X, Y) -> ok when X :: integer(),Y :: integer().
+rasterPos2i(X,Y) ->
+ cast(5168, <<X:?GLint,Y:?GLint>>).
-%% @spec (Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml">external</a> documentation.
--spec pushAttrib(integer()) -> ok.
-pushAttrib(Mask) ->
- cast(5221, <<Mask:?GLbitfield>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos2s(X, Y) -> ok when X :: integer(),Y :: integer().
+rasterPos2s(X,Y) ->
+ cast(5169, <<X:?GLshort,Y:?GLshort>>).
-%% @spec (Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml">external</a> documentation.
--spec pushClientAttrib(integer()) -> ok.
-pushClientAttrib(Mask) ->
- cast(5222, <<Mask:?GLbitfield>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos3d(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+rasterPos3d(X,Y,Z) ->
+ cast(5170, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml">external</a> documentation.
--spec pushMatrix() -> ok.
-pushMatrix() ->
- cast(5223, <<>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos3f(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
+rasterPos3f(X,Y,Z) ->
+ cast(5171, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec (Name::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml">external</a> documentation.
--spec pushName(integer()) -> ok.
-pushName(Name) ->
- cast(5224, <<Name:?GLuint>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos3i(X, Y, Z) -> ok when X :: integer(),Y :: integer(),Z :: integer().
+rasterPos3i(X,Y,Z) ->
+ cast(5172, <<X:?GLint,Y:?GLint,Z:?GLint>>).
-%% @spec (X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos2d(float(),float()) -> ok.
-rasterPos2d(X,Y) ->
- cast(5225, <<X:?GLdouble,Y:?GLdouble>>).
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos3s(X, Y, Z) -> ok when X :: integer(),Y :: integer(),Z :: integer().
+rasterPos3s(X,Y,Z) ->
+ cast(5173, <<X:?GLshort,Y:?GLshort,Z:?GLshort>>).
+
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos4d(X, Y, Z, W) -> ok when X :: float(),Y :: float(),Z :: float(),W :: float().
+rasterPos4d(X,Y,Z,W) ->
+ cast(5174, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
+
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos4f(X, Y, Z, W) -> ok when X :: float(),Y :: float(),Z :: float(),W :: float().
+rasterPos4f(X,Y,Z,W) ->
+ cast(5175, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
+
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos4i(X, Y, Z, W) -> ok when X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
+rasterPos4i(X,Y,Z,W) ->
+ cast(5176, <<X:?GLint,Y:?GLint,Z:?GLint,W:?GLint>>).
+
+%% @doc
+%% See {@link rasterPos2d/2}
+-spec rasterPos4s(X, Y, Z, W) -> ok when X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
+rasterPos4s(X,Y,Z,W) ->
+ cast(5177, <<X:?GLshort,Y:?GLshort,Z:?GLshort,W:?GLshort>>).
-%% @spec ({X,Y}) -> ok
%% @equiv rasterPos2d(X,Y)
--spec rasterPos2dv({float(),float()}) -> ok.
+-spec rasterPos2dv(V) -> ok when V :: {X :: float(),Y :: float()}.
rasterPos2dv({X,Y}) -> rasterPos2d(X,Y).
-%% @spec (X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos2f(float(),float()) -> ok.
-rasterPos2f(X,Y) ->
- cast(5226, <<X:?GLfloat,Y:?GLfloat>>).
-
-%% @spec ({X,Y}) -> ok
%% @equiv rasterPos2f(X,Y)
--spec rasterPos2fv({float(),float()}) -> ok.
+-spec rasterPos2fv(V) -> ok when V :: {X :: float(),Y :: float()}.
rasterPos2fv({X,Y}) -> rasterPos2f(X,Y).
-%% @spec (X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos2i(integer(),integer()) -> ok.
-rasterPos2i(X,Y) ->
- cast(5227, <<X:?GLint,Y:?GLint>>).
-
-%% @spec ({X,Y}) -> ok
%% @equiv rasterPos2i(X,Y)
--spec rasterPos2iv({integer(),integer()}) -> ok.
+-spec rasterPos2iv(V) -> ok when V :: {X :: integer(),Y :: integer()}.
rasterPos2iv({X,Y}) -> rasterPos2i(X,Y).
-%% @spec (X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos2s(integer(),integer()) -> ok.
-rasterPos2s(X,Y) ->
- cast(5228, <<X:?GLshort,Y:?GLshort>>).
-
-%% @spec ({X,Y}) -> ok
%% @equiv rasterPos2s(X,Y)
--spec rasterPos2sv({integer(),integer()}) -> ok.
+-spec rasterPos2sv(V) -> ok when V :: {X :: integer(),Y :: integer()}.
rasterPos2sv({X,Y}) -> rasterPos2s(X,Y).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos3d(float(),float(),float()) -> ok.
-rasterPos3d(X,Y,Z) ->
- cast(5229, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-
-%% @spec ({X,Y,Z}) -> ok
%% @equiv rasterPos3d(X,Y,Z)
--spec rasterPos3dv({float(),float(),float()}) -> ok.
+-spec rasterPos3dv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
rasterPos3dv({X,Y,Z}) -> rasterPos3d(X,Y,Z).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos3f(float(),float(),float()) -> ok.
-rasterPos3f(X,Y,Z) ->
- cast(5230, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-
-%% @spec ({X,Y,Z}) -> ok
%% @equiv rasterPos3f(X,Y,Z)
--spec rasterPos3fv({float(),float(),float()}) -> ok.
+-spec rasterPos3fv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
rasterPos3fv({X,Y,Z}) -> rasterPos3f(X,Y,Z).
-%% @spec (X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos3i(integer(),integer(),integer()) -> ok.
-rasterPos3i(X,Y,Z) ->
- cast(5231, <<X:?GLint,Y:?GLint,Z:?GLint>>).
-
-%% @spec ({X,Y,Z}) -> ok
%% @equiv rasterPos3i(X,Y,Z)
--spec rasterPos3iv({integer(),integer(),integer()}) -> ok.
+-spec rasterPos3iv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
rasterPos3iv({X,Y,Z}) -> rasterPos3i(X,Y,Z).
-%% @spec (X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos3s(integer(),integer(),integer()) -> ok.
-rasterPos3s(X,Y,Z) ->
- cast(5232, <<X:?GLshort,Y:?GLshort,Z:?GLshort>>).
-
-%% @spec ({X,Y,Z}) -> ok
%% @equiv rasterPos3s(X,Y,Z)
--spec rasterPos3sv({integer(),integer(),integer()}) -> ok.
+-spec rasterPos3sv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
rasterPos3sv({X,Y,Z}) -> rasterPos3s(X,Y,Z).
-%% @spec (X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos4d(float(),float(),float(),float()) -> ok.
-rasterPos4d(X,Y,Z,W) ->
- cast(5233, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
%% @equiv rasterPos4d(X,Y,Z,W)
--spec rasterPos4dv({float(),float(),float(),float()}) -> ok.
+-spec rasterPos4dv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
rasterPos4dv({X,Y,Z,W}) -> rasterPos4d(X,Y,Z,W).
-%% @spec (X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos4f(float(),float(),float(),float()) -> ok.
-rasterPos4f(X,Y,Z,W) ->
- cast(5234, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
%% @equiv rasterPos4f(X,Y,Z,W)
--spec rasterPos4fv({float(),float(),float(),float()}) -> ok.
+-spec rasterPos4fv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
rasterPos4fv({X,Y,Z,W}) -> rasterPos4f(X,Y,Z,W).
-%% @spec (X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos4i(integer(),integer(),integer(),integer()) -> ok.
-rasterPos4i(X,Y,Z,W) ->
- cast(5235, <<X:?GLint,Y:?GLint,Z:?GLint,W:?GLint>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
%% @equiv rasterPos4i(X,Y,Z,W)
--spec rasterPos4iv({integer(),integer(),integer(),integer()}) -> ok.
+-spec rasterPos4iv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
rasterPos4iv({X,Y,Z,W}) -> rasterPos4i(X,Y,Z,W).
-%% @spec (X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
--spec rasterPos4s(integer(),integer(),integer(),integer()) -> ok.
-rasterPos4s(X,Y,Z,W) ->
- cast(5236, <<X:?GLshort,Y:?GLshort,Z:?GLshort,W:?GLshort>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
%% @equiv rasterPos4s(X,Y,Z,W)
--spec rasterPos4sv({integer(),integer(),integer(),integer()}) -> ok.
+-spec rasterPos4sv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
rasterPos4sv({X,Y,Z,W}) -> rasterPos4s(X,Y,Z,W).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml">external</a> documentation.
--spec readBuffer(enum()) -> ok.
-readBuffer(Mode) ->
- cast(5237, <<Mode:?GLenum>>).
+%% @doc Draw a rectangle
+%%
+%% ``gl:rect'' supports efficient specification of rectangles as two corner points. Each
+%% rectangle command takes four arguments, organized either as two consecutive pairs of (x y)
+%% coordinates or as two pointers to arrays, each containing an (x y) pair. The resulting rectangle
+%% is defined in the z= 0 plane.
+%%
+%% ``gl:rect''( `X1' , `Y1' , `X2' , `Y2' ) is exactly equivalent to the
+%% following sequence: glBegin(`?GL_POLYGON'); glVertex2( `X1' , `Y1' ); glVertex2(
+%% `X2' , `Y1' ); glVertex2( `X2' , `Y2' ); glVertex2( `X1' , `Y2' );
+%% glEnd(); Note that if the second vertex is above and to the right of the first vertex,
+%% the rectangle is constructed with a counterclockwise winding.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
+-spec rectd(X1, Y1, X2, Y2) -> ok when X1 :: float(),Y1 :: float(),X2 :: float(),Y2 :: float().
+rectd(X1,Y1,X2,Y2) ->
+ cast(5178, <<X1:?GLdouble,Y1:?GLdouble,X2:?GLdouble,Y2:?GLdouble>>).
-%% @spec (X::integer(),Y::integer(),Width::integer(),Height::integer(),Format::enum(),Type::enum(),Pixels::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml">external</a> documentation.
--spec readPixels(integer(),integer(),integer(),integer(),enum(),enum(),mem()) -> ok.
-readPixels(X,Y,Width,Height,Format,Type,Pixels) ->
- send_bin(Pixels),
- call(5238, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
+%% @doc
+%% See {@link rectd/4}
+-spec rectf(X1, Y1, X2, Y2) -> ok when X1 :: float(),Y1 :: float(),X2 :: float(),Y2 :: float().
+rectf(X1,Y1,X2,Y2) ->
+ cast(5179, <<X1:?GLfloat,Y1:?GLfloat,X2:?GLfloat,Y2:?GLfloat>>).
-%% @spec (X1::float(),Y1::float(),X2::float(),Y2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rectd(float(),float(),float(),float()) -> ok.
-rectd(X1,Y1,X2,Y2) ->
- cast(5239, <<X1:?GLdouble,Y1:?GLdouble,X2:?GLdouble,Y2:?GLdouble>>).
+%% @doc
+%% See {@link rectd/4}
+-spec recti(X1, Y1, X2, Y2) -> ok when X1 :: integer(),Y1 :: integer(),X2 :: integer(),Y2 :: integer().
+recti(X1,Y1,X2,Y2) ->
+ cast(5180, <<X1:?GLint,Y1:?GLint,X2:?GLint,Y2:?GLint>>).
-%% @spec (V1::{float(),float()},V2::{float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rectdv({float(),float()},{float(),float()}) -> ok.
-rectdv({V1,V2},{V1,V2}) ->
- cast(5240, <<V1:?GLdouble,V2:?GLdouble,V1:?GLdouble,V2:?GLdouble>>).
+%% @doc
+%% See {@link rectd/4}
+-spec rects(X1, Y1, X2, Y2) -> ok when X1 :: integer(),Y1 :: integer(),X2 :: integer(),Y2 :: integer().
+rects(X1,Y1,X2,Y2) ->
+ cast(5181, <<X1:?GLshort,Y1:?GLshort,X2:?GLshort,Y2:?GLshort>>).
-%% @spec (X1::float(),Y1::float(),X2::float(),Y2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rectf(float(),float(),float(),float()) -> ok.
-rectf(X1,Y1,X2,Y2) ->
- cast(5241, <<X1:?GLfloat,Y1:?GLfloat,X2:?GLfloat,Y2:?GLfloat>>).
+%% @doc
+%% See {@link rectd/4}
+-spec rectdv(V1, V2) -> ok when V1 :: {float(),float()},V2 :: {float(),float()}.
+rectdv({V1,V2},{V1,V2}) ->
+ cast(5182, <<V1:?GLdouble,V2:?GLdouble,V1:?GLdouble,V2:?GLdouble>>).
-%% @spec (V1::{float(),float()},V2::{float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rectfv({float(),float()},{float(),float()}) -> ok.
+%% @doc
+%% See {@link rectd/4}
+-spec rectfv(V1, V2) -> ok when V1 :: {float(),float()},V2 :: {float(),float()}.
rectfv({V1,V2},{V1,V2}) ->
- cast(5242, <<V1:?GLfloat,V2:?GLfloat,V1:?GLfloat,V2:?GLfloat>>).
+ cast(5183, <<V1:?GLfloat,V2:?GLfloat,V1:?GLfloat,V2:?GLfloat>>).
-%% @spec (X1::integer(),Y1::integer(),X2::integer(),Y2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec recti(integer(),integer(),integer(),integer()) -> ok.
-recti(X1,Y1,X2,Y2) ->
- cast(5243, <<X1:?GLint,Y1:?GLint,X2:?GLint,Y2:?GLint>>).
-
-%% @spec (V1::{integer(),integer()},V2::{integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rectiv({integer(),integer()},{integer(),integer()}) -> ok.
+%% @doc
+%% See {@link rectd/4}
+-spec rectiv(V1, V2) -> ok when V1 :: {integer(),integer()},V2 :: {integer(),integer()}.
rectiv({V1,V2},{V1,V2}) ->
- cast(5244, <<V1:?GLint,V2:?GLint,V1:?GLint,V2:?GLint>>).
+ cast(5184, <<V1:?GLint,V2:?GLint,V1:?GLint,V2:?GLint>>).
-%% @spec (X1::integer(),Y1::integer(),X2::integer(),Y2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rects(integer(),integer(),integer(),integer()) -> ok.
-rects(X1,Y1,X2,Y2) ->
- cast(5245, <<X1:?GLshort,Y1:?GLshort,X2:?GLshort,Y2:?GLshort>>).
-
-%% @spec (V1::{integer(),integer()},V2::{integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
--spec rectsv({integer(),integer()},{integer(),integer()}) -> ok.
+%% @doc
+%% See {@link rectd/4}
+-spec rectsv(V1, V2) -> ok when V1 :: {integer(),integer()},V2 :: {integer(),integer()}.
rectsv({V1,V2},{V1,V2}) ->
- cast(5246, <<V1:?GLshort,V2:?GLshort,V1:?GLshort,V2:?GLshort>>).
+ cast(5185, <<V1:?GLshort,V2:?GLshort,V1:?GLshort,V2:?GLshort>>).
-%% @spec (Mode::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderMode.xml">external</a> documentation.
--spec renderMode(enum()) -> integer().
-renderMode(Mode) ->
- call(5247, <<Mode:?GLenum>>).
+%% @doc Define an array of vertex data
+%%
+%% ``gl:vertexPointer'' specifies the location and data format of an array of vertex coordinates
+%% to use when rendering. `Size' specifies the number of coordinates per vertex, and
+%% must be 2, 3, or 4. `Type' specifies the data type of each coordinate, and `Stride'
+%% specifies the byte stride from one vertex to the next, allowing vertices and attributes
+%% to be packed into a single array or stored in separate arrays. (Single-array storage may
+%% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .)
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a vertex array is specified, `Pointer' is treated as a byte offset into the
+%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as vertex array client-side state (`?GL_VERTEX_ARRAY_BUFFER_BINDING').
+%%
+%% When a vertex array is specified, `Size' , `Type' , `Stride' , and `Pointer'
+%% are saved as client-side state, in addition to the current vertex array buffer object
+%% binding.
+%%
+%% To enable and disable the vertex array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_VERTEX_ARRAY'. If enabled, the vertex array is used when {@link gl:arrayElement/1}
+%% , {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
+%% , or {@link gl:drawRangeElements/6} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml">external</a> documentation.
+-spec vertexPointer(Size, Type, Stride, Ptr) -> ok when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
+vertexPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) ->
+ cast(5186, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
+vertexPointer(Size,Type,Stride,Ptr) ->
+ send_bin(Ptr),
+ cast(5187, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
+
+%% @doc Define an array of normals
+%%
+%% ``gl:normalPointer'' specifies the location and data format of an array of normals to
+%% use when rendering. `Type' specifies the data type of each normal coordinate, and `Stride'
+%% specifies the byte stride from one normal to the next, allowing vertices and attributes
+%% to be packed into a single array or stored in separate arrays. (Single-array storage may
+%% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .)
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a normal array is specified, `Pointer' is treated as a byte offset into the
+%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as normal vertex array client-side state (`?GL_NORMAL_ARRAY_BUFFER_BINDING'
+%% ).
+%%
+%% When a normal array is specified, `Type' , `Stride' , and `Pointer' are
+%% saved as client-side state, in addition to the current vertex array buffer object binding.
+%%
+%%
+%% To enable and disable the normal array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_NORMAL_ARRAY'. If enabled, the normal array is used when {@link gl:drawArrays/3}
+%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', {@link gl:drawRangeElements/6}
+%% , or {@link gl:arrayElement/1} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormalPointer.xml">external</a> documentation.
+-spec normalPointer(Type, Stride, Ptr) -> ok when Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
+normalPointer(Type,Stride,Ptr) when is_integer(Ptr) ->
+ cast(5188, <<Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
+normalPointer(Type,Stride,Ptr) ->
+ send_bin(Ptr),
+ cast(5189, <<Type:?GLenum,Stride:?GLsizei>>).
+
+%% @doc Define an array of colors
+%%
+%% ``gl:colorPointer'' specifies the location and data format of an array of color components
+%% to use when rendering. `Size' specifies the number of components per color, and must
+%% be 3 or 4. `Type' specifies the data type of each color component, and `Stride'
+%% specifies the byte stride from one color to the next, allowing vertices and attributes
+%% to be packed into a single array or stored in separate arrays. (Single-array storage may
+%% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .)
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a color array is specified, `Pointer' is treated as a byte offset into the
+%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as color vertex array client-side state (`?GL_COLOR_ARRAY_BUFFER_BINDING').
+%%
+%%
+%% When a color array is specified, `Size' , `Type' , `Stride' , and `Pointer'
+%% are saved as client-side state, in addition to the current vertex array buffer object
+%% binding.
+%%
+%% To enable and disable the color array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_COLOR_ARRAY'. If enabled, the color array is used when {@link gl:drawArrays/3}
+%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', {@link gl:drawRangeElements/6}
+%% , or {@link gl:arrayElement/1} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorPointer.xml">external</a> documentation.
+-spec colorPointer(Size, Type, Stride, Ptr) -> ok when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
+colorPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) ->
+ cast(5190, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
+colorPointer(Size,Type,Stride,Ptr) ->
+ send_bin(Ptr),
+ cast(5191, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
+
+%% @doc Define an array of color indexes
+%%
+%% ``gl:indexPointer'' specifies the location and data format of an array of color indexes
+%% to use when rendering. `Type' specifies the data type of each color index and `Stride'
+%% specifies the byte stride from one color index to the next, allowing vertices and attributes
+%% to be packed into a single array or stored in separate arrays.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a color index array is specified, `Pointer' is treated as a byte offset into
+%% the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as color index vertex array client-side state (`?GL_INDEX_ARRAY_BUFFER_BINDING'
+%% ).
+%%
+%% When a color index array is specified, `Type' , `Stride' , and `Pointer'
+%% are saved as client-side state, in addition to the current vertex array buffer object
+%% binding.
+%%
+%% To enable and disable the color index array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_INDEX_ARRAY'. If enabled, the color index array is used when
+%% {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
+%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexPointer.xml">external</a> documentation.
+-spec indexPointer(Type, Stride, Ptr) -> ok when Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
+indexPointer(Type,Stride,Ptr) when is_integer(Ptr) ->
+ cast(5192, <<Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
+indexPointer(Type,Stride,Ptr) ->
+ send_bin(Ptr),
+ cast(5193, <<Type:?GLenum,Stride:?GLsizei>>).
+
+%% @doc Define an array of texture coordinates
+%%
+%% ``gl:texCoordPointer'' specifies the location and data format of an array of texture
+%% coordinates to use when rendering. `Size' specifies the number of coordinates per
+%% texture coordinate set, and must be 1, 2, 3, or 4. `Type' specifies the data type
+%% of each texture coordinate, and `Stride' specifies the byte stride from one texture
+%% coordinate set to the next, allowing vertices and attributes to be packed into a single
+%% array or stored in separate arrays. (Single-array storage may be more efficient on some
+%% implementations; see {@link gl:interleavedArrays/3} .)
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a texture coordinate array is specified, `Pointer' is treated as a byte offset
+%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as texture coordinate vertex array client-side state (`?GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING'
+%% ).
+%%
+%% When a texture coordinate array is specified, `Size' , `Type' , `Stride' ,
+%% and `Pointer' are saved as client-side state, in addition to the current vertex array
+%% buffer object binding.
+%%
+%% To enable and disable a texture coordinate array, call {@link gl:enableClientState/1}
+%% and {@link gl:enableClientState/1} with the argument `?GL_TEXTURE_COORD_ARRAY'. If
+%% enabled, the texture coordinate array is used when {@link gl:arrayElement/1} , {@link gl:drawArrays/3}
+%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements',
+%% or {@link gl:drawRangeElements/6} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml">external</a> documentation.
+-spec texCoordPointer(Size, Type, Stride, Ptr) -> ok when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
+texCoordPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) ->
+ cast(5194, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
+texCoordPointer(Size,Type,Stride,Ptr) ->
+ send_bin(Ptr),
+ cast(5195, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
+
+%% @doc Define an array of edge flags
+%%
+%% ``gl:edgeFlagPointer'' specifies the location and data format of an array of boolean
+%% edge flags to use when rendering. `Stride' specifies the byte stride from one edge
+%% flag to the next, allowing vertices and attributes to be packed into a single array or
+%% stored in separate arrays.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while an edge flag array is specified, `Pointer' is treated as a byte offset into
+%% the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as edge flag vertex array client-side state (`?GL_EDGE_FLAG_ARRAY_BUFFER_BINDING'
+%% ).
+%%
+%% When an edge flag array is specified, `Stride' and `Pointer' are saved as client-side
+%% state, in addition to the current vertex array buffer object binding.
+%%
+%% To enable and disable the edge flag array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_EDGE_FLAG_ARRAY'. If enabled, the edge flag array is used
+%% when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
+%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlagPointer.xml">external</a> documentation.
+-spec edgeFlagPointer(Stride, Ptr) -> ok when Stride :: integer(),Ptr :: offset()|mem().
+edgeFlagPointer(Stride,Ptr) when is_integer(Ptr) ->
+ cast(5196, <<Stride:?GLsizei,Ptr:?GLuint>>);
+edgeFlagPointer(Stride,Ptr) ->
+ send_bin(Ptr),
+ cast(5197, <<Stride:?GLsizei>>).
+
+%% @doc Render a vertex using the specified vertex array element
+%%
+%% ``gl:arrayElement'' commands are used within {@link gl:'begin'/1} / {@link gl:'begin'/1} pairs
+%% to specify vertex and attribute data for point, line, and polygon primitives. If `?GL_VERTEX_ARRAY'
+%% is enabled when ``gl:arrayElement'' is called, a single vertex is drawn, using vertex
+%% and attribute data taken from location `I' of the enabled arrays. If `?GL_VERTEX_ARRAY'
+%% is not enabled, no drawing occurs but the attributes corresponding to the enabled arrays
+%% are modified.
+%%
+%% Use ``gl:arrayElement'' to construct primitives by indexing vertex data, rather than
+%% by streaming through arrays of data in first-to-last order. Because each call specifies
+%% only a single vertex, it is possible to explicitly specify per-primitive attributes such
+%% as a single normal for each triangle.
+%%
+%% Changes made to array data between the execution of {@link gl:'begin'/1} and the corresponding
+%% execution of {@link gl:'begin'/1} may affect calls to ``gl:arrayElement'' that are made within
+%% the same {@link gl:'begin'/1} / {@link gl:'begin'/1} period in nonsequential ways. That is, a call
+%% to ``gl:arrayElement'' that precedes a change to array data may access the changed data,
+%% and a call that follows a change to array data may access original data.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glArrayElement.xml">external</a> documentation.
+-spec arrayElement(I) -> ok when I :: integer().
+arrayElement(I) ->
+ cast(5198, <<I:?GLint>>).
-%% @spec (Angle::float(),X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml">external</a> documentation.
--spec rotated(float(),float(),float(),float()) -> ok.
-rotated(Angle,X,Y,Z) ->
- cast(5248, <<Angle:?GLdouble,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
+%% @doc Render primitives from array data
+%%
+%% ``gl:drawArrays'' specifies multiple geometric primitives with very few subroutine calls.
+%% Instead of calling a GL procedure to pass each individual vertex, normal, texture coordinate,
+%% edge flag, or color, you can prespecify separate arrays of vertices, normals, and colors
+%% and use them to construct a sequence of primitives with a single call to ``gl:drawArrays''
+%% .
+%%
+%% When ``gl:drawArrays'' is called, it uses `Count' sequential elements from each
+%% enabled array to construct a sequence of geometric primitives, beginning with element `First'
+%% . `Mode' specifies what kind of primitives are constructed and how the array elements
+%% construct those primitives.
+%%
+%% Vertex attributes that are modified by ``gl:drawArrays'' have an unspecified value
+%% after ``gl:drawArrays'' returns. Attributes that aren't modified remain well defined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml">external</a> documentation.
+-spec drawArrays(Mode, First, Count) -> ok when Mode :: enum(),First :: integer(),Count :: integer().
+drawArrays(Mode,First,Count) ->
+ cast(5199, <<Mode:?GLenum,First:?GLint,Count:?GLsizei>>).
-%% @spec (Angle::float(),X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml">external</a> documentation.
--spec rotatef(float(),float(),float(),float()) -> ok.
-rotatef(Angle,X,Y,Z) ->
- cast(5249, <<Angle:?GLfloat,X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
+%% @doc Render primitives from array data
+%%
+%% ``gl:drawElements'' specifies multiple geometric primitives with very few subroutine
+%% calls. Instead of calling a GL function to pass each individual vertex, normal, texture
+%% coordinate, edge flag, or color, you can prespecify separate arrays of vertices, normals,
+%% and so on, and use them to construct a sequence of primitives with a single call to ``gl:drawElements''
+%% .
+%%
+%% When ``gl:drawElements'' is called, it uses `Count' sequential elements from an
+%% enabled array, starting at `Indices' to construct a sequence of geometric primitives.
+%% `Mode' specifies what kind of primitives are constructed and how the array elements
+%% construct these primitives. If more than one array is enabled, each is used.
+%%
+%% Vertex attributes that are modified by ``gl:drawElements'' have an unspecified value
+%% after ``gl:drawElements'' returns. Attributes that aren't modified maintain their previous
+%% values.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml">external</a> documentation.
+-spec drawElements(Mode, Count, Type, Indices) -> ok when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem().
+drawElements(Mode,Count,Type,Indices) when is_integer(Indices) ->
+ cast(5200, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>);
+drawElements(Mode,Count,Type,Indices) ->
+ send_bin(Indices),
+ cast(5201, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum>>).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml">external</a> documentation.
--spec scaled(float(),float(),float()) -> ok.
-scaled(X,Y,Z) ->
- cast(5250, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
+%% @doc Simultaneously specify and enable several interleaved arrays
+%%
+%% ``gl:interleavedArrays'' lets you specify and enable individual color, normal, texture
+%% and vertex arrays whose elements are part of a larger aggregate array element. For some
+%% implementations, this is more efficient than specifying the arrays separately.
+%%
+%% If `Stride' is 0, the aggregate elements are stored consecutively. Otherwise, `Stride'
+%% bytes occur between the beginning of one aggregate array element and the beginning of
+%% the next aggregate array element.
+%%
+%% `Format' serves as a ``key'' describing the extraction of individual arrays from
+%% the aggregate array. If `Format' contains a T, then texture coordinates are extracted
+%% from the interleaved array. If C is present, color values are extracted. If N is present,
+%% normal coordinates are extracted. Vertex coordinates are always extracted.
+%%
+%% The digits 2, 3, and 4 denote how many values are extracted. F indicates that values
+%% are extracted as floating-point values. Colors may also be extracted as 4 unsigned bytes
+%% if 4UB follows the C. If a color is extracted as 4 unsigned bytes, the vertex array element
+%% which follows is located at the first possible floating-point aligned address.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml">external</a> documentation.
+-spec interleavedArrays(Format, Stride, Pointer) -> ok when Format :: enum(),Stride :: integer(),Pointer :: offset()|mem().
+interleavedArrays(Format,Stride,Pointer) when is_integer(Pointer) ->
+ cast(5202, <<Format:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
+interleavedArrays(Format,Stride,Pointer) ->
+ send_bin(Pointer),
+ cast(5203, <<Format:?GLenum,Stride:?GLsizei>>).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml">external</a> documentation.
--spec scalef(float(),float(),float()) -> ok.
-scalef(X,Y,Z) ->
- cast(5251, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
+%% @doc Select flat or smooth shading
+%%
+%% GL primitives can have either flat or smooth shading. Smooth shading, the default, causes
+%% the computed colors of vertices to be interpolated as the primitive is rasterized, typically
+%% assigning different colors to each resulting pixel fragment. Flat shading selects the
+%% computed color of just one vertex and assigns it to all the pixel fragments generated
+%% by rasterizing a single primitive. In either case, the computed color of a vertex is the
+%% result of lighting if lighting is enabled, or it is the current color at the time the
+%% vertex was specified if lighting is disabled.
+%%
+%% Flat and smooth shading are indistinguishable for points. Starting when {@link gl:'begin'/1}
+%% is issued and counting vertices and primitives from 1, the GL gives each flat-shaded line
+%% segment i the computed color of vertex i+1, its second vertex. Counting similarly
+%% from 1, the GL gives each flat-shaded polygon the computed color of the vertex listed
+%% in the following table. This is the last vertex to specify the polygon in all cases except
+%% single polygons, where the first vertex specifies the flat-shaded color.
+%%
+%% <table><tbody><tr><td>` Primitive Type of Polygon ' i</td><td>` Vertex '</td></tr>
+%% </tbody><tbody><tr><td> Single polygon ( i== 1) </td><td> 1 </td></tr><tr><td> Triangle
+%% strip </td><td> i+2</td></tr><tr><td> Triangle fan </td><td> i+2</td></tr><tr><td> Independent
+%% triangle </td><td> 3 i</td></tr><tr><td> Quad strip </td><td> 2 i+2</td></tr><tr><td>
+%% Independent quad </td><td> 4 i</td></tr></tbody></table>
+%%
+%% Flat and smooth shading are specified by ``gl:shadeModel'' with `Mode' set to `?GL_FLAT'
+%% and `?GL_SMOOTH', respectively.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShadeModel.xml">external</a> documentation.
+-spec shadeModel(Mode) -> ok when Mode :: enum().
+shadeModel(Mode) ->
+ cast(5204, <<Mode:?GLenum>>).
-%% @spec (X::integer(),Y::integer(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml">external</a> documentation.
--spec scissor(integer(),integer(),integer(),integer()) -> ok.
-scissor(X,Y,Width,Height) ->
- cast(5252, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
+%% @doc Set light source parameters
+%%
+%% ``gl:light'' sets the values of individual light source parameters. `Light' names
+%% the light and is a symbolic name of the form `?GL_LIGHT' i, where i ranges from 0
+%% to the value of `?GL_MAX_LIGHTS' - 1. `Pname' specifies one of ten light source
+%% parameters, again by symbolic name. `Params' is either a single value or a pointer
+%% to an array that contains the new values.
+%%
+%% To enable and disable lighting calculation, call {@link gl:enable/1} and {@link gl:enable/1}
+%% with argument `?GL_LIGHTING'. Lighting is initially disabled. When it is enabled,
+%% light sources that are enabled contribute to the lighting calculation. Light source i
+%% is enabled and disabled using {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_LIGHT'
+%% i.
+%%
+%% The ten light parameters are as follows:
+%%
+%% `?GL_AMBIENT': `Params' contains four integer or floating-point values that
+%% specify the ambient RGBA intensity of the light. Integer values are mapped linearly such
+%% that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial ambient light intensity is (0, 0, 0, 1).
+%%
+%% `?GL_DIFFUSE': `Params' contains four integer or floating-point values that
+%% specify the diffuse RGBA intensity of the light. Integer values are mapped linearly such
+%% that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for other
+%% lights, the initial value is (0, 0, 0, 1).
+%%
+%% `?GL_SPECULAR': `Params' contains four integer or floating-point values that
+%% specify the specular RGBA intensity of the light. Integer values are mapped linearly such
+%% that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for other
+%% lights, the initial value is (0, 0, 0, 1).
+%%
+%% `?GL_POSITION': `Params' contains four integer or floating-point values that
+%% specify the position of the light in homogeneous object coordinates. Both integer and
+%% floating-point values are mapped directly. Neither integer nor floating-point values are
+%% clamped.
+%%
+%% The position is transformed by the modelview matrix when ``gl:light'' is called (just
+%% as if it were a point), and it is stored in eye coordinates. If the w component of the
+%% position is 0, the light is treated as a directional source. Diffuse and specular lighting
+%% calculations take the light's direction, but not its actual position, into account, and
+%% attenuation is disabled. Otherwise, diffuse and specular lighting calculations are based
+%% on the actual location of the light in eye coordinates, and attenuation is enabled. The
+%% initial position is (0, 0, 1, 0); thus, the initial light source is directional, parallel
+%% to, and in the direction of the -z axis.
+%%
+%% `?GL_SPOT_DIRECTION': `Params' contains three integer or floating-point values
+%% that specify the direction of the light in homogeneous object coordinates. Both integer
+%% and floating-point values are mapped directly. Neither integer nor floating-point values
+%% are clamped.
+%%
+%% The spot direction is transformed by the upper 3x3 of the modelview matrix when ``gl:light''
+%% is called, and it is stored in eye coordinates. It is significant only when `?GL_SPOT_CUTOFF'
+%% is not 180, which it is initially. The initial direction is (0 0 -1).
+%%
+%% `?GL_SPOT_EXPONENT': `Params' is a single integer or floating-point value that
+%% specifies the intensity distribution of the light. Integer and floating-point values are
+%% mapped directly. Only values in the range [0 128] are accepted.
+%%
+%% Effective light intensity is attenuated by the cosine of the angle between the direction
+%% of the light and the direction from the light to the vertex being lighted, raised to the
+%% power of the spot exponent. Thus, higher spot exponents result in a more focused light
+%% source, regardless of the spot cutoff angle (see `?GL_SPOT_CUTOFF', next paragraph).
+%% The initial spot exponent is 0, resulting in uniform light distribution.
+%%
+%% `?GL_SPOT_CUTOFF': `Params' is a single integer or floating-point value that
+%% specifies the maximum spread angle of a light source. Integer and floating-point values
+%% are mapped directly. Only values in the range [0 90] and the special value 180 are accepted.
+%% If the angle between the direction of the light and the direction from the light to the
+%% vertex being lighted is greater than the spot cutoff angle, the light is completely masked.
+%% Otherwise, its intensity is controlled by the spot exponent and the attenuation factors.
+%% The initial spot cutoff is 180, resulting in uniform light distribution.
+%%
+%% `?GL_CONSTANT_ATTENUATION'
+%%
+%% `?GL_LINEAR_ATTENUATION'
+%%
+%% `?GL_QUADRATIC_ATTENUATION': `Params' is a single integer or floating-point
+%% value that specifies one of the three light attenuation factors. Integer and floating-point
+%% values are mapped directly. Only nonnegative values are accepted. If the light is positional,
+%% rather than directional, its intensity is attenuated by the reciprocal of the sum of the
+%% constant factor, the linear factor times the distance between the light and the vertex
+%% being lighted, and the quadratic factor times the square of the same distance. The initial
+%% attenuation factors are (1, 0, 0), resulting in no attenuation.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation.
+-spec lightf(Light, Pname, Param) -> ok when Light :: enum(),Pname :: enum(),Param :: float().
+lightf(Light,Pname,Param) ->
+ cast(5205, <<Light:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
-%% @spec (Size::integer(),Buffer::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml">external</a> documentation.
--spec selectBuffer(integer(),mem()) -> ok.
-selectBuffer(Size,Buffer) ->
- send_bin(Buffer),
- call(5253, <<Size:?GLsizei>>).
+%% @doc
+%% See {@link lightf/3}
+-spec lighti(Light, Pname, Param) -> ok when Light :: enum(),Pname :: enum(),Param :: integer().
+lighti(Light,Pname,Param) ->
+ cast(5206, <<Light:?GLenum,Pname:?GLenum,Param:?GLint>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShadeModel.xml">external</a> documentation.
--spec shadeModel(enum()) -> ok.
-shadeModel(Mode) ->
- cast(5254, <<Mode:?GLenum>>).
+%% @doc
+%% See {@link lightf/3}
+-spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {float()}.
+lightfv(Light,Pname,Params) ->
+ cast(5207, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Func::enum(),Ref::integer(),Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml">external</a> documentation.
--spec stencilFunc(enum(),integer(),integer()) -> ok.
-stencilFunc(Func,Ref,Mask) ->
- cast(5255, <<Func:?GLenum,Ref:?GLint,Mask:?GLuint>>).
+%% @doc
+%% See {@link lightf/3}
+-spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {integer()}.
+lightiv(Light,Pname,Params) ->
+ cast(5208, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMask.xml">external</a> documentation.
--spec stencilMask(integer()) -> ok.
-stencilMask(Mask) ->
- cast(5256, <<Mask:?GLuint>>).
+%% @doc Return light source parameter values
+%%
+%% ``gl:getLight'' returns in `Params' the value or values of a light source parameter.
+%% `Light' names the light and is a symbolic name of the form `?GL_LIGHT' i where
+%% i ranges from 0 to the value of `?GL_MAX_LIGHTS' - 1. `?GL_MAX_LIGHTS' is an
+%% implementation dependent constant that is greater than or equal to eight. `Pname'
+%% specifies one of ten light source parameters, again by symbolic name.
+%%
+%% The following parameters are defined:
+%%
+%% `?GL_AMBIENT': `Params' returns four integer or floating-point values representing
+%% the ambient intensity of the light source. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value is (0, 0, 0, 1).
+%%
+%% `?GL_DIFFUSE': `Params' returns four integer or floating-point values representing
+%% the diffuse intensity of the light source. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for
+%% other lights, the initial value is (0, 0, 0, 0).
+%%
+%% `?GL_SPECULAR': `Params' returns four integer or floating-point values representing
+%% the specular intensity of the light source. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for
+%% other lights, the initial value is (0, 0, 0, 0).
+%%
+%% `?GL_POSITION': `Params' returns four integer or floating-point values representing
+%% the position of the light source. Integer values, when requested, are computed by rounding
+%% the internal floating-point values to the nearest integer value. The returned values are
+%% those maintained in eye coordinates. They will not be equal to the values specified using
+%% {@link gl:lightf/3} , unless the modelview matrix was identity at the time {@link gl:lightf/3}
+%% was called. The initial value is (0, 0, 1, 0).
+%%
+%% `?GL_SPOT_DIRECTION': `Params' returns three integer or floating-point values
+%% representing the direction of the light source. Integer values, when requested, are computed
+%% by rounding the internal floating-point values to the nearest integer value. The returned
+%% values are those maintained in eye coordinates. They will not be equal to the values specified
+%% using {@link gl:lightf/3} , unless the modelview matrix was identity at the time {@link gl:lightf/3}
+%% was called. Although spot direction is normalized before being used in the lighting equation,
+%% the returned values are the transformed versions of the specified values prior to normalization.
+%% The initial value is (0 0 -1).
+%%
+%% `?GL_SPOT_EXPONENT': `Params' returns a single integer or floating-point value
+%% representing the spot exponent of the light. An integer value, when requested, is computed
+%% by rounding the internal floating-point representation to the nearest integer. The initial
+%% value is 0.
+%%
+%% `?GL_SPOT_CUTOFF': `Params' returns a single integer or floating-point value
+%% representing the spot cutoff angle of the light. An integer value, when requested, is
+%% computed by rounding the internal floating-point representation to the nearest integer.
+%% The initial value is 180.
+%%
+%% `?GL_CONSTANT_ATTENUATION': `Params' returns a single integer or floating-point
+%% value representing the constant (not distance-related) attenuation of the light. An integer
+%% value, when requested, is computed by rounding the internal floating-point representation
+%% to the nearest integer. The initial value is 1.
+%%
+%% `?GL_LINEAR_ATTENUATION': `Params' returns a single integer or floating-point
+%% value representing the linear attenuation of the light. An integer value, when requested,
+%% is computed by rounding the internal floating-point representation to the nearest integer.
+%% The initial value is 0.
+%%
+%% `?GL_QUADRATIC_ATTENUATION': `Params' returns a single integer or floating-point
+%% value representing the quadratic attenuation of the light. An integer value, when requested,
+%% is computed by rounding the internal floating-point representation to the nearest integer.
+%% The initial value is 0.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml">external</a> documentation.
+-spec getLightfv(Light, Pname) -> {float(),float(),float(),float()} when Light :: enum(),Pname :: enum().
+getLightfv(Light,Pname) ->
+ call(5209, <<Light:?GLenum,Pname:?GLenum>>).
-%% @spec (Fail::enum(),Zfail::enum(),Zpass::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml">external</a> documentation.
--spec stencilOp(enum(),enum(),enum()) -> ok.
-stencilOp(Fail,Zfail,Zpass) ->
- cast(5257, <<Fail:?GLenum,Zfail:?GLenum,Zpass:?GLenum>>).
+%% @doc
+%% See {@link getLightfv/2}
+-spec getLightiv(Light, Pname) -> {integer(),integer(),integer(),integer()} when Light :: enum(),Pname :: enum().
+getLightiv(Light,Pname) ->
+ call(5210, <<Light:?GLenum,Pname:?GLenum>>).
-%% @spec (S::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord1d(float()) -> ok.
-texCoord1d(S) ->
- cast(5258, <<S:?GLdouble>>).
+%% @doc Set the lighting model parameters
+%%
+%% ``gl:lightModel'' sets the lighting model parameter. `Pname' names a parameter
+%% and `Params' gives the new value. There are three lighting model parameters:
+%%
+%% `?GL_LIGHT_MODEL_AMBIENT': `Params' contains four integer or floating-point
+%% values that specify the ambient RGBA intensity of the entire scene. Integer values are
+%% mapped linearly such that the most positive representable value maps to 1.0, and the most
+%% negative representable value maps to -1.0. Floating-point values are mapped directly.
+%% Neither integer nor floating-point values are clamped. The initial ambient scene intensity
+%% is (0.2, 0.2, 0.2, 1.0).
+%%
+%% `?GL_LIGHT_MODEL_COLOR_CONTROL': `Params' must be either `?GL_SEPARATE_SPECULAR_COLOR'
+%% or `?GL_SINGLE_COLOR'. `?GL_SINGLE_COLOR' specifies that a single color is
+%% generated from the lighting computation for a vertex. `?GL_SEPARATE_SPECULAR_COLOR'
+%% specifies that the specular color computation of lighting be stored separately from the
+%% remainder of the lighting computation. The specular color is summed into the generated
+%% fragment's color after the application of texture mapping (if enabled). The initial value
+%% is `?GL_SINGLE_COLOR'.
+%%
+%% `?GL_LIGHT_MODEL_LOCAL_VIEWER': `Params' is a single integer or floating-point
+%% value that specifies how specular reflection angles are computed. If `Params' is
+%% 0 (or 0.0), specular reflection angles take the view direction to be parallel to and in
+%% the direction of the -`z' axis, regardless of the location of the vertex in eye coordinates.
+%% Otherwise, specular reflections are computed from the origin of the eye coordinate system.
+%% The initial value is 0.
+%%
+%% `?GL_LIGHT_MODEL_TWO_SIDE': `Params' is a single integer or floating-point value
+%% that specifies whether one- or two-sided lighting calculations are done for polygons.
+%% It has no effect on the lighting calculations for points, lines, or bitmaps. If `Params'
+%% is 0 (or 0.0), one-sided lighting is specified, and only the `front' material parameters
+%% are used in the lighting equation. Otherwise, two-sided lighting is specified. In this
+%% case, vertices of back-facing polygons are lighted using the `back' material parameters
+%% and have their normals reversed before the lighting equation is evaluated. Vertices of
+%% front-facing polygons are always lighted using the `front' material parameters, with
+%% no change to their normals. The initial value is 0.
+%%
+%% In RGBA mode, the lighted color of a vertex is the sum of the material emission intensity,
+%% the product of the material ambient reflectance and the lighting model full-scene ambient
+%% intensity, and the contribution of each enabled light source. Each light source contributes
+%% the sum of three terms: ambient, diffuse, and specular. The ambient light source contribution
+%% is the product of the material ambient reflectance and the light's ambient intensity.
+%% The diffuse light source contribution is the product of the material diffuse reflectance,
+%% the light's diffuse intensity, and the dot product of the vertex's normal with the normalized
+%% vector from the vertex to the light source. The specular light source contribution is
+%% the product of the material specular reflectance, the light's specular intensity, and
+%% the dot product of the normalized vertex-to-eye and vertex-to-light vectors, raised to
+%% the power of the shininess of the material. All three light source contributions are attenuated
+%% equally based on the distance from the vertex to the light source and on light source
+%% direction, spread exponent, and spread cutoff angle. All dot products are replaced with
+%% 0 if they evaluate to a negative value.
+%%
+%% The alpha component of the resulting lighted color is set to the alpha value of the material
+%% diffuse reflectance.
+%%
+%% In color index mode, the value of the lighted index of a vertex ranges from the ambient
+%% to the specular values passed to {@link gl:materialf/3} using `?GL_COLOR_INDEXES'.
+%% Diffuse and specular coefficients, computed with a (.30, .59, .11) weighting of the lights'
+%% colors, the shininess of the material, and the same reflection and attenuation equations
+%% as in the RGBA case, determine how much above ambient the resulting index is.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation.
+-spec lightModelf(Pname, Param) -> ok when Pname :: enum(),Param :: float().
+lightModelf(Pname,Param) ->
+ cast(5211, <<Pname:?GLenum,Param:?GLfloat>>).
-%% @spec ({S}) -> ok
-%% @equiv texCoord1d(S)
--spec texCoord1dv({float()}) -> ok.
-texCoord1dv({S}) -> texCoord1d(S).
+%% @doc
+%% See {@link lightModelf/2}
+-spec lightModeli(Pname, Param) -> ok when Pname :: enum(),Param :: integer().
+lightModeli(Pname,Param) ->
+ cast(5212, <<Pname:?GLenum,Param:?GLint>>).
-%% @spec (S::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord1f(float()) -> ok.
-texCoord1f(S) ->
- cast(5259, <<S:?GLfloat>>).
+%% @doc
+%% See {@link lightModelf/2}
+-spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}.
+lightModelfv(Pname,Params) ->
+ cast(5213, <<Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
-%% @spec ({S}) -> ok
-%% @equiv texCoord1f(S)
--spec texCoord1fv({float()}) -> ok.
-texCoord1fv({S}) -> texCoord1f(S).
+%% @doc
+%% See {@link lightModelf/2}
+-spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}.
+lightModeliv(Pname,Params) ->
+ cast(5214, <<Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
-%% @spec (S::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord1i(integer()) -> ok.
-texCoord1i(S) ->
- cast(5260, <<S:?GLint>>).
+%% @doc Specify material parameters for the lighting model
+%%
+%% ``gl:material'' assigns values to material parameters. There are two matched sets of
+%% material parameters. One, the `front-facing' set, is used to shade points, lines,
+%% bitmaps, and all polygons (when two-sided lighting is disabled), or just front-facing
+%% polygons (when two-sided lighting is enabled). The other set, `back-facing', is used
+%% to shade back-facing polygons only when two-sided lighting is enabled. Refer to the {@link gl:lightModelf/2}
+%% reference page for details concerning one- and two-sided lighting calculations.
+%%
+%% ``gl:material'' takes three arguments. The first, `Face' , specifies whether the `?GL_FRONT'
+%% materials, the `?GL_BACK' materials, or both `?GL_FRONT_AND_BACK' materials
+%% will be modified. The second, `Pname' , specifies which of several parameters in one
+%% or both sets will be modified. The third, `Params' , specifies what value or values
+%% will be assigned to the specified parameter.
+%%
+%% Material parameters are used in the lighting equation that is optionally applied to each
+%% vertex. The equation is discussed in the {@link gl:lightModelf/2} reference page. The parameters
+%% that can be specified using ``gl:material'', and their interpretations by the lighting
+%% equation, are as follows:
+%%
+%% `?GL_AMBIENT': `Params' contains four integer or floating-point values that
+%% specify the ambient RGBA reflectance of the material. Integer values are mapped linearly
+%% such that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial ambient reflectance for both front- and back-facing materials
+%% is (0.2, 0.2, 0.2, 1.0).
+%%
+%% `?GL_DIFFUSE': `Params' contains four integer or floating-point values that
+%% specify the diffuse RGBA reflectance of the material. Integer values are mapped linearly
+%% such that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial diffuse reflectance for both front- and back-facing materials
+%% is (0.8, 0.8, 0.8, 1.0).
+%%
+%% `?GL_SPECULAR': `Params' contains four integer or floating-point values that
+%% specify the specular RGBA reflectance of the material. Integer values are mapped linearly
+%% such that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial specular reflectance for both front- and back-facing materials
+%% is (0, 0, 0, 1).
+%%
+%% `?GL_EMISSION': `Params' contains four integer or floating-point values that
+%% specify the RGBA emitted light intensity of the material. Integer values are mapped linearly
+%% such that the most positive representable value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
+%% values are clamped. The initial emission intensity for both front- and back-facing materials
+%% is (0, 0, 0, 1).
+%%
+%% `?GL_SHININESS': `Params' is a single integer or floating-point value that specifies
+%% the RGBA specular exponent of the material. Integer and floating-point values are mapped
+%% directly. Only values in the range [0 128] are accepted. The initial specular exponent for both
+%% front- and back-facing materials is 0.
+%%
+%% `?GL_AMBIENT_AND_DIFFUSE': Equivalent to calling ``gl:material'' twice with the
+%% same parameter values, once with `?GL_AMBIENT' and once with `?GL_DIFFUSE'.
+%%
+%% `?GL_COLOR_INDEXES': `Params' contains three integer or floating-point values
+%% specifying the color indices for ambient, diffuse, and specular lighting. These three
+%% values, and `?GL_SHININESS', are the only material values used by the color index
+%% mode lighting equation. Refer to the {@link gl:lightModelf/2} reference page for a discussion
+%% of color index lighting.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation.
+-spec materialf(Face, Pname, Param) -> ok when Face :: enum(),Pname :: enum(),Param :: float().
+materialf(Face,Pname,Param) ->
+ cast(5215, <<Face:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
-%% @spec ({S}) -> ok
-%% @equiv texCoord1i(S)
--spec texCoord1iv({integer()}) -> ok.
-texCoord1iv({S}) -> texCoord1i(S).
+%% @doc
+%% See {@link materialf/3}
+-spec materiali(Face, Pname, Param) -> ok when Face :: enum(),Pname :: enum(),Param :: integer().
+materiali(Face,Pname,Param) ->
+ cast(5216, <<Face:?GLenum,Pname:?GLenum,Param:?GLint>>).
-%% @spec (S::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord1s(integer()) -> ok.
-texCoord1s(S) ->
- cast(5261, <<S:?GLshort>>).
+%% @doc
+%% See {@link materialf/3}
+-spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {float()}.
+materialfv(Face,Pname,Params) ->
+ cast(5217, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec ({S}) -> ok
-%% @equiv texCoord1s(S)
--spec texCoord1sv({integer()}) -> ok.
-texCoord1sv({S}) -> texCoord1s(S).
+%% @doc
+%% See {@link materialf/3}
+-spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {integer()}.
+materialiv(Face,Pname,Params) ->
+ cast(5218, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (S::float(),T::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord2d(float(),float()) -> ok.
-texCoord2d(S,T) ->
- cast(5262, <<S:?GLdouble,T:?GLdouble>>).
+%% @doc Return material parameters
+%%
+%% ``gl:getMaterial'' returns in `Params' the value or values of parameter `Pname'
+%% of material `Face' . Six parameters are defined:
+%%
+%% `?GL_AMBIENT': `Params' returns four integer or floating-point values representing
+%% the ambient reflectance of the material. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value is (0.2, 0.2, 0.2, 1.0)
+%%
+%% `?GL_DIFFUSE': `Params' returns four integer or floating-point values representing
+%% the diffuse reflectance of the material. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value is (0.8, 0.8, 0.8, 1.0).
+%%
+%% `?GL_SPECULAR': `Params' returns four integer or floating-point values representing
+%% the specular reflectance of the material. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value is (0, 0, 0, 1).
+%%
+%% `?GL_EMISSION': `Params' returns four integer or floating-point values representing
+%% the emitted light intensity of the material. Integer values, when requested, are linearly
+%% mapped from the internal floating-point representation such that 1.0 maps to the most
+%% positive representable integer value, and -1.0 maps to the most negative representable
+%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
+%% return value is undefined. The initial value is (0, 0, 0, 1).
+%%
+%% `?GL_SHININESS': `Params' returns one integer or floating-point value representing
+%% the specular exponent of the material. Integer values, when requested, are computed by
+%% rounding the internal floating-point value to the nearest integer value. The initial value
+%% is 0.
+%%
+%% `?GL_COLOR_INDEXES': `Params' returns three integer or floating-point values
+%% representing the ambient, diffuse, and specular indices of the material. These indices
+%% are used only for color index lighting. (All the other parameters are used only for RGBA
+%% lighting.) Integer values, when requested, are computed by rounding the internal floating-point
+%% values to the nearest integer values.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml">external</a> documentation.
+-spec getMaterialfv(Face, Pname) -> {float(),float(),float(),float()} when Face :: enum(),Pname :: enum().
+getMaterialfv(Face,Pname) ->
+ call(5219, <<Face:?GLenum,Pname:?GLenum>>).
-%% @spec ({S,T}) -> ok
-%% @equiv texCoord2d(S,T)
--spec texCoord2dv({float(),float()}) -> ok.
-texCoord2dv({S,T}) -> texCoord2d(S,T).
+%% @doc
+%% See {@link getMaterialfv/2}
+-spec getMaterialiv(Face, Pname) -> {integer(),integer(),integer(),integer()} when Face :: enum(),Pname :: enum().
+getMaterialiv(Face,Pname) ->
+ call(5220, <<Face:?GLenum,Pname:?GLenum>>).
-%% @spec (S::float(),T::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord2f(float(),float()) -> ok.
-texCoord2f(S,T) ->
- cast(5263, <<S:?GLfloat,T:?GLfloat>>).
+%% @doc Cause a material color to track the current color
+%%
+%% ``gl:colorMaterial'' specifies which material parameters track the current color. When `?GL_COLOR_MATERIAL'
+%% is enabled, the material parameter or parameters specified by `Mode' , of the material
+%% or materials specified by `Face' , track the current color at all times.
+%%
+%% To enable and disable `?GL_COLOR_MATERIAL', call {@link gl:enable/1} and {@link gl:enable/1}
+%% with argument `?GL_COLOR_MATERIAL'. `?GL_COLOR_MATERIAL' is initially disabled.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaterial.xml">external</a> documentation.
+-spec colorMaterial(Face, Mode) -> ok when Face :: enum(),Mode :: enum().
+colorMaterial(Face,Mode) ->
+ cast(5221, <<Face:?GLenum,Mode:?GLenum>>).
-%% @spec ({S,T}) -> ok
-%% @equiv texCoord2f(S,T)
--spec texCoord2fv({float(),float()}) -> ok.
-texCoord2fv({S,T}) -> texCoord2f(S,T).
+%% @doc Specify the pixel zoom factors
+%%
+%% ``gl:pixelZoom'' specifies values for the x and y zoom factors. During the execution
+%% of {@link gl:drawPixels/5} or {@link gl:copyPixels/5} , if ( xr, yr) is the current raster
+%% position, and a given element is in the mth row and nth column of the pixel rectangle,
+%% then pixels whose centers are in the rectangle with corners at
+%%
+%% ( xr+n. xfactor, yr+m. yfactor)
+%%
+%% ( xr+(n+1). xfactor, yr+(m+1). yfactor)
+%%
+%% are candidates for replacement. Any pixel whose center lies on the bottom or left edge
+%% of this rectangular region is also modified.
+%%
+%% Pixel zoom factors are not limited to positive values. Negative zoom factors reflect
+%% the resulting image about the current raster position.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelZoom.xml">external</a> documentation.
+-spec pixelZoom(Xfactor, Yfactor) -> ok when Xfactor :: float(),Yfactor :: float().
+pixelZoom(Xfactor,Yfactor) ->
+ cast(5222, <<Xfactor:?GLfloat,Yfactor:?GLfloat>>).
-%% @spec (S::integer(),T::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord2i(integer(),integer()) -> ok.
-texCoord2i(S,T) ->
- cast(5264, <<S:?GLint,T:?GLint>>).
+%% @doc Set pixel storage modes
+%%
+%% ``gl:pixelStore'' sets pixel storage modes that affect the operation of subsequent {@link gl:readPixels/7}
+%% as well as the unpacking of texture patterns (see {@link gl:texImage1D/8} , {@link gl:texImage2D/9}
+%% , {@link gl:texImage3D/10} , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7}
+%% ), {@link gl:compressedTexImage1D/7} , {@link gl:compressedTexImage2D/8} , {@link gl:compressedTexImage3D/9}
+%% , {@link gl:compressedTexSubImage1D/7} , {@link gl:compressedTexSubImage2D/9} or {@link gl:compressedTexSubImage1D/7}
+%% .
+%%
+%% `Pname' is a symbolic constant indicating the parameter to be set, and `Param'
+%% is the new value. Six of the twelve storage parameters affect how pixel data is returned
+%% to client memory. They are as follows:
+%%
+%% `?GL_PACK_SWAP_BYTES': If true, byte ordering for multibyte color components, depth
+%% components, or stencil indices is reversed. That is, if a four-byte component consists
+%% of bytes b 0, b 1, b 2, b 3, it is stored in memory as b 3, b 2, b 1, b 0 if `?GL_PACK_SWAP_BYTES'
+%% is true. `?GL_PACK_SWAP_BYTES' has no effect on the memory order of components within
+%% a pixel, only on the order of bytes within components or indices. For example, the three
+%% components of a `?GL_RGB' format pixel are always stored with red first, green second,
+%% and blue third, regardless of the value of `?GL_PACK_SWAP_BYTES'.
+%%
+%% `?GL_PACK_LSB_FIRST': If true, bits are ordered within a byte from least significant
+%% to most significant; otherwise, the first bit in each byte is the most significant one.
+%%
+%% `?GL_PACK_ROW_LENGTH': If greater than 0, `?GL_PACK_ROW_LENGTH' defines the
+%% number of pixels in a row. If the first pixel of a row is placed at location p in memory,
+%% then the location of the first pixel of the next row is obtained by skipping
+%%
+%% k={n l(a/s) |(s n l)/a| s&gt;= a s&lt; a)
+%%
+%% components or indices, where n is the number of components or indices in a pixel, l
+%% is the number of pixels in a row (`?GL_PACK_ROW_LENGTH' if it is greater than 0,
+%% the width argument to the pixel routine otherwise), a is the value of `?GL_PACK_ALIGNMENT'
+%% , and s is the size, in bytes, of a single component (if a&lt; s, then it is as if a=
+%% s). In the case of 1-bit values, the location of the next row is obtained by skipping
+%%
+%% k= 8 a |(n l)/(8 a)|
+%%
+%% components or indices.
+%%
+%% The word `component' in this description refers to the nonindex values red, green,
+%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
+%% per pixel: first red, then green, and finally blue.
+%%
+%% `?GL_PACK_IMAGE_HEIGHT': If greater than 0, `?GL_PACK_IMAGE_HEIGHT' defines
+%% the number of pixels in an image three-dimensional texture volume, where ``image'' is
+%% defined by all pixels sharing the same third dimension index. If the first pixel of a
+%% row is placed at location p in memory, then the location of the first pixel of the next
+%% row is obtained by skipping
+%%
+%% k={n l h(a/s) |(s n l h)/a| s&gt;= a s&lt; a)
+%%
+%% components or indices, where n is the number of components or indices in a pixel, l
+%% is the number of pixels in a row (`?GL_PACK_ROW_LENGTH' if it is greater than 0,
+%% the width argument to {@link gl:texImage3D/10} otherwise), h is the number of rows in
+%% a pixel image (`?GL_PACK_IMAGE_HEIGHT' if it is greater than 0, the height argument
+%% to the {@link gl:texImage3D/10} routine otherwise), a is the value of `?GL_PACK_ALIGNMENT'
+%% , and s is the size, in bytes, of a single component (if a&lt; s, then it is as if
+%% a= s).
+%%
+%% The word `component' in this description refers to the nonindex values red, green,
+%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
+%% per pixel: first red, then green, and finally blue.
+%%
+%% `?GL_PACK_SKIP_PIXELS', `?GL_PACK_SKIP_ROWS', and `?GL_PACK_SKIP_IMAGES'
+%%
+%% These values are provided as a convenience to the programmer; they provide no functionality
+%% that cannot be duplicated simply by incrementing the pointer passed to {@link gl:readPixels/7}
+%% . Setting `?GL_PACK_SKIP_PIXELS' to i is equivalent to incrementing the pointer
+%% by i n components or indices, where n is the number of components or indices in each
+%% pixel. Setting `?GL_PACK_SKIP_ROWS' to j is equivalent to incrementing the pointer
+%% by j m components or indices, where m is the number of components or indices per
+%% row, as just computed in the `?GL_PACK_ROW_LENGTH' section. Setting `?GL_PACK_SKIP_IMAGES'
+%% to k is equivalent to incrementing the pointer by k p, where p is the number of
+%% components or indices per image, as computed in the `?GL_PACK_IMAGE_HEIGHT' section.
+%%
+%%
+%% `?GL_PACK_ALIGNMENT': Specifies the alignment requirements for the start of each
+%% pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered
+%% bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries).
+%%
+%% The other six of the twelve storage parameters affect how pixel data is read from client
+%% memory. These values are significant for {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
+%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7}
+%%
+%% They are as follows:
+%%
+%% `?GL_UNPACK_SWAP_BYTES': If true, byte ordering for multibyte color components,
+%% depth components, or stencil indices is reversed. That is, if a four-byte component consists
+%% of bytes b 0, b 1, b 2, b 3, it is taken from memory as b 3, b 2, b 1, b 0 if `?GL_UNPACK_SWAP_BYTES'
+%% is true. `?GL_UNPACK_SWAP_BYTES' has no effect on the memory order of components
+%% within a pixel, only on the order of bytes within components or indices. For example,
+%% the three components of a `?GL_RGB' format pixel are always stored with red first,
+%% green second, and blue third, regardless of the value of `?GL_UNPACK_SWAP_BYTES'.
+%%
+%% `?GL_UNPACK_LSB_FIRST': If true, bits are ordered within a byte from least significant
+%% to most significant; otherwise, the first bit in each byte is the most significant one.
+%%
+%% `?GL_UNPACK_ROW_LENGTH': If greater than 0, `?GL_UNPACK_ROW_LENGTH' defines
+%% the number of pixels in a row. If the first pixel of a row is placed at location p in
+%% memory, then the location of the first pixel of the next row is obtained by skipping
+%%
+%% k={n l(a/s) |(s n l)/a| s&gt;= a s&lt; a)
+%%
+%% components or indices, where n is the number of components or indices in a pixel, l
+%% is the number of pixels in a row (`?GL_UNPACK_ROW_LENGTH' if it is greater than 0,
+%% the width argument to the pixel routine otherwise), a is the value of `?GL_UNPACK_ALIGNMENT'
+%% , and s is the size, in bytes, of a single component (if a&lt; s, then it is as if a=
+%% s). In the case of 1-bit values, the location of the next row is obtained by skipping
+%%
+%% k= 8 a |(n l)/(8 a)|
+%%
+%% components or indices.
+%%
+%% The word `component' in this description refers to the nonindex values red, green,
+%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
+%% per pixel: first red, then green, and finally blue.
+%%
+%% `?GL_UNPACK_IMAGE_HEIGHT': If greater than 0, `?GL_UNPACK_IMAGE_HEIGHT' defines
+%% the number of pixels in an image of a three-dimensional texture volume. Where ``image''
+%% is defined by all pixel sharing the same third dimension index. If the first pixel of
+%% a row is placed at location p in memory, then the location of the first pixel of the
+%% next row is obtained by skipping
+%%
+%% k={n l h(a/s) |(s n l h)/a| s&gt;= a s&lt; a)
+%%
+%% components or indices, where n is the number of components or indices in a pixel, l
+%% is the number of pixels in a row (`?GL_UNPACK_ROW_LENGTH' if it is greater than 0,
+%% the width argument to {@link gl:texImage3D/10} otherwise), h is the number of rows in
+%% an image (`?GL_UNPACK_IMAGE_HEIGHT' if it is greater than 0, the height argument
+%% to {@link gl:texImage3D/10} otherwise), a is the value of `?GL_UNPACK_ALIGNMENT',
+%% and s is the size, in bytes, of a single component (if a&lt; s, then it is as if a=
+%% s).
+%%
+%% The word `component' in this description refers to the nonindex values red, green,
+%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
+%% per pixel: first red, then green, and finally blue.
+%%
+%% `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_SKIP_ROWS'
+%%
+%% These values are provided as a convenience to the programmer; they provide no functionality
+%% that cannot be duplicated by incrementing the pointer passed to {@link gl:texImage1D/8} , {@link gl:texImage2D/9}
+%% , {@link gl:texSubImage1D/7} or {@link gl:texSubImage1D/7} . Setting `?GL_UNPACK_SKIP_PIXELS'
+%% to i is equivalent to incrementing the pointer by i n components or indices, where
+%% n is the number of components or indices in each pixel. Setting `?GL_UNPACK_SKIP_ROWS'
+%% to j is equivalent to incrementing the pointer by j k components or indices, where
+%% k is the number of components or indices per row, as just computed in the `?GL_UNPACK_ROW_LENGTH'
+%% section.
+%%
+%% `?GL_UNPACK_ALIGNMENT': Specifies the alignment requirements for the start of each
+%% pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered
+%% bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries).
+%%
+%% The following table gives the type, initial value, and range of valid values for each
+%% storage parameter that can be set with ``gl:pixelStore''.
+%%
+%% <table><tbody><tr><td> `Pname' </td><td>` Type '</td><td>` Initial Value '</td>
+%% <td>` Valid Range '</td></tr></tbody><tbody><tr><td>`?GL_PACK_SWAP_BYTES'</td><td>
+%% boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_PACK_LSB_FIRST'
+%% </td><td> boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_PACK_ROW_LENGTH'
+%% </td><td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_IMAGE_HEIGHT'</td>
+%% <td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_ROWS'</td><td>
+%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_PIXELS'</td><td> integer
+%% </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_IMAGES'</td><td> integer </td><td>
+%% 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_ALIGNMENT'</td><td> integer </td><td> 4 </td>
+%% <td> 1, 2, 4, or 8 </td></tr><tr><td>`?GL_UNPACK_SWAP_BYTES'</td><td> boolean </td><td>
+%% false </td><td> true or false </td></tr><tr><td>`?GL_UNPACK_LSB_FIRST'</td><td>
+%% boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_UNPACK_ROW_LENGTH'
+%% </td><td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_IMAGE_HEIGHT'</td>
+%% <td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_ROWS'</td><td>
+%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_PIXELS'</td><td>
+%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_IMAGES'</td><td>
+%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_ALIGNMENT'</td><td> integer
+%% </td><td> 4 </td><td> 1, 2, 4, or 8 </td></tr></tbody></table>
+%%
+%% ``gl:pixelStoref'' can be used to set any pixel store parameter. If the parameter type
+%% is boolean, then if `Param' is 0, the parameter is false; otherwise it is set to
+%% true. If `Pname' is a integer type parameter, `Param' is rounded to the nearest
+%% integer.
+%%
+%% Likewise, ``gl:pixelStorei'' can also be used to set any of the pixel store parameters.
+%% Boolean parameters are set to false if `Param' is 0 and true otherwise.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml">external</a> documentation.
+-spec pixelStoref(Pname, Param) -> ok when Pname :: enum(),Param :: float().
+pixelStoref(Pname,Param) ->
+ cast(5223, <<Pname:?GLenum,Param:?GLfloat>>).
-%% @spec ({S,T}) -> ok
-%% @equiv texCoord2i(S,T)
--spec texCoord2iv({integer(),integer()}) -> ok.
-texCoord2iv({S,T}) -> texCoord2i(S,T).
+%% @doc
+%% See {@link pixelStoref/2}
+-spec pixelStorei(Pname, Param) -> ok when Pname :: enum(),Param :: integer().
+pixelStorei(Pname,Param) ->
+ cast(5224, <<Pname:?GLenum,Param:?GLint>>).
-%% @spec (S::integer(),T::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord2s(integer(),integer()) -> ok.
-texCoord2s(S,T) ->
- cast(5265, <<S:?GLshort,T:?GLshort>>).
+%% @doc Set pixel transfer modes
+%%
+%% ``gl:pixelTransfer'' sets pixel transfer modes that affect the operation of subsequent {@link gl:copyPixels/5}
+%% , {@link gl:copyTexImage1D/7} , {@link gl:copyTexImage2D/8} , {@link gl:copyTexSubImage1D/6} , {@link gl:copyTexSubImage2D/8}
+%% , {@link gl:copyTexSubImage3D/9} , {@link gl:drawPixels/5} , {@link gl:readPixels/7} , {@link gl:texImage1D/8}
+%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7}
+%% , and {@link gl:texSubImage1D/7} commands. Additionally, if the ARB_imaging subset is supported,
+%% the routines {@link gl:colorTable/6} , {@link gl:colorSubTable/6} , {@link gl:convolutionFilter1D/6}
+%% , {@link gl:convolutionFilter2D/7} , {@link gl:histogram/4} , {@link gl:minmax/3} , and {@link gl:separableFilter2D/8}
+%% are also affected. The algorithms that are specified by pixel transfer modes operate
+%% on pixels after they are read from the frame buffer ( {@link gl:copyPixels/5} {@link gl:copyTexImage1D/7}
+%% , {@link gl:copyTexImage2D/8} , {@link gl:copyTexSubImage1D/6} , {@link gl:copyTexSubImage2D/8} ,
+%% {@link gl:copyTexSubImage3D/9} , and {@link gl:readPixels/7} ), or unpacked from client memory
+%% ( {@link gl:drawPixels/5} , {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
+%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7} ).
+%% Pixel transfer operations happen in the same order, and in the same manner, regardless
+%% of the command that resulted in the pixel operation. Pixel storage modes (see {@link gl:pixelStoref/2}
+%% ) control the unpacking of pixels being read from client memory and the packing of pixels
+%% being written back into client memory.
+%%
+%% Pixel transfer operations handle four fundamental pixel types: `color', `color index'
+%% , `depth', and `stencil'. `Color' pixels consist of four floating-point
+%% values with unspecified mantissa and exponent sizes, scaled such that 0 represents zero
+%% intensity and 1 represents full intensity. `Color indices' comprise a single fixed-point
+%% value, with unspecified precision to the right of the binary point. `Depth' pixels
+%% comprise a single floating-point value, with unspecified mantissa and exponent sizes,
+%% scaled such that 0.0 represents the minimum depth buffer value, and 1.0 represents the
+%% maximum depth buffer value. Finally, `stencil' pixels comprise a single fixed-point
+%% value, with unspecified precision to the right of the binary point.
+%%
+%% The pixel transfer operations performed on the four basic pixel types are as follows:
+%%
+%% `Color': Each of the four color components is multiplied by a scale factor, then
+%% added to a bias factor. That is, the red component is multiplied by `?GL_RED_SCALE',
+%% then added to `?GL_RED_BIAS'; the green component is multiplied by `?GL_GREEN_SCALE'
+%% , then added to `?GL_GREEN_BIAS'; the blue component is multiplied by `?GL_BLUE_SCALE'
+%% , then added to `?GL_BLUE_BIAS'; and the alpha component is multiplied by `?GL_ALPHA_SCALE'
+%% , then added to `?GL_ALPHA_BIAS'. After all four color components are scaled and
+%% biased, each is clamped to the range [0 1]. All color, scale, and bias values are specified
+%% with ``gl:pixelTransfer''.
+%%
+%% If `?GL_MAP_COLOR' is true, each color component is scaled by the size of the corresponding
+%% color-to-color map, then replaced by the contents of that map indexed by the scaled component.
+%% That is, the red component is scaled by `?GL_PIXEL_MAP_R_TO_R_SIZE', then replaced
+%% by the contents of `?GL_PIXEL_MAP_R_TO_R' indexed by itself. The green component
+%% is scaled by `?GL_PIXEL_MAP_G_TO_G_SIZE', then replaced by the contents of `?GL_PIXEL_MAP_G_TO_G'
+%% indexed by itself. The blue component is scaled by `?GL_PIXEL_MAP_B_TO_B_SIZE',
+%% then replaced by the contents of `?GL_PIXEL_MAP_B_TO_B' indexed by itself. And the
+%% alpha component is scaled by `?GL_PIXEL_MAP_A_TO_A_SIZE', then replaced by the contents
+%% of `?GL_PIXEL_MAP_A_TO_A' indexed by itself. All components taken from the maps are
+%% then clamped to the range [0 1]. `?GL_MAP_COLOR' is specified with ``gl:pixelTransfer''.
+%% The contents of the various maps are specified with {@link gl:pixelMapfv/3} .
+%%
+%% If the ARB_imaging extension is supported, each of the four color components may be scaled
+%% and biased after transformation by the color matrix. That is, the red component is multiplied
+%% by `?GL_POST_COLOR_MATRIX_RED_SCALE', then added to `?GL_POST_COLOR_MATRIX_RED_BIAS'
+%% ; the green component is multiplied by `?GL_POST_COLOR_MATRIX_GREEN_SCALE', then
+%% added to `?GL_POST_COLOR_MATRIX_GREEN_BIAS'; the blue component is multiplied by `?GL_POST_COLOR_MATRIX_BLUE_SCALE'
+%% , then added to `?GL_POST_COLOR_MATRIX_BLUE_BIAS'; and the alpha component is multiplied
+%% by `?GL_POST_COLOR_MATRIX_ALPHA_SCALE', then added to `?GL_POST_COLOR_MATRIX_ALPHA_BIAS'
+%% . After all four color components are scaled and biased, each is clamped to the range [0
+%% 1].
+%%
+%% Similarly, if the ARB_imaging extension is supported, each of the four color components
+%% may be scaled and biased after processing by the enabled convolution filter. That is,
+%% the red component is multiplied by `?GL_POST_CONVOLUTION_RED_SCALE', then added to `?GL_POST_CONVOLUTION_RED_BIAS'
+%% ; the green component is multiplied by `?GL_POST_CONVOLUTION_GREEN_SCALE', then added
+%% to `?GL_POST_CONVOLUTION_GREEN_BIAS'; the blue component is multiplied by `?GL_POST_CONVOLUTION_BLUE_SCALE'
+%% , then added to `?GL_POST_CONVOLUTION_BLUE_BIAS'; and the alpha component is multiplied
+%% by `?GL_POST_CONVOLUTION_ALPHA_SCALE', then added to `?GL_POST_CONVOLUTION_ALPHA_BIAS'
+%% . After all four color components are scaled and biased, each is clamped to the range [0
+%% 1].
+%%
+%% `Color index': Each color index is shifted left by `?GL_INDEX_SHIFT' bits;
+%% any bits beyond the number of fraction bits carried by the fixed-point index are filled
+%% with zeros. If `?GL_INDEX_SHIFT' is negative, the shift is to the right, again zero
+%% filled. Then `?GL_INDEX_OFFSET' is added to the index. `?GL_INDEX_SHIFT' and `?GL_INDEX_OFFSET'
+%% are specified with ``gl:pixelTransfer''.
+%%
+%% From this point, operation diverges depending on the required format of the resulting
+%% pixels. If the resulting pixels are to be written to a color index buffer, or if they
+%% are being read back to client memory in `?GL_COLOR_INDEX' format, the pixels continue
+%% to be treated as indices. If `?GL_MAP_COLOR' is true, each index is masked by 2 n-1
+%% , where n is `?GL_PIXEL_MAP_I_TO_I_SIZE', then replaced by the contents of `?GL_PIXEL_MAP_I_TO_I'
+%% indexed by the masked value. `?GL_MAP_COLOR' is specified with ``gl:pixelTransfer''
+%% . The contents of the index map is specified with {@link gl:pixelMapfv/3} .
+%%
+%% If the resulting pixels are to be written to an RGBA color buffer, or if they are read
+%% back to client memory in a format other than `?GL_COLOR_INDEX', the pixels are converted
+%% from indices to colors by referencing the four maps `?GL_PIXEL_MAP_I_TO_R', `?GL_PIXEL_MAP_I_TO_G'
+%% , `?GL_PIXEL_MAP_I_TO_B', and `?GL_PIXEL_MAP_I_TO_A'. Before being dereferenced,
+%% the index is masked by 2 n-1, where n is `?GL_PIXEL_MAP_I_TO_R_SIZE' for the
+%% red map, `?GL_PIXEL_MAP_I_TO_G_SIZE' for the green map, `?GL_PIXEL_MAP_I_TO_B_SIZE'
+%% for the blue map, and `?GL_PIXEL_MAP_I_TO_A_SIZE' for the alpha map. All components
+%% taken from the maps are then clamped to the range [0 1]. The contents of the four maps is
+%% specified with {@link gl:pixelMapfv/3} .
+%%
+%% `Depth': Each depth value is multiplied by `?GL_DEPTH_SCALE', added to `?GL_DEPTH_BIAS'
+%% , then clamped to the range [0 1].
+%%
+%% `Stencil': Each index is shifted `?GL_INDEX_SHIFT' bits just as a color index
+%% is, then added to `?GL_INDEX_OFFSET'. If `?GL_MAP_STENCIL' is true, each index
+%% is masked by 2 n-1, where n is `?GL_PIXEL_MAP_S_TO_S_SIZE', then replaced by
+%% the contents of `?GL_PIXEL_MAP_S_TO_S' indexed by the masked value.
+%%
+%% The following table gives the type, initial value, and range of valid values for each
+%% of the pixel transfer parameters that are set with ``gl:pixelTransfer''.
+%%
+%% <table><tbody><tr><td> `Pname' </td><td>` Type '</td><td>` Initial Value '</td>
+%% <td>` Valid Range '</td></tr></tbody><tbody><tr><td>`?GL_MAP_COLOR'</td><td>
+%% boolean </td><td> false </td><td> true/false </td></tr><tr><td>`?GL_MAP_STENCIL'</td>
+%% <td> boolean </td><td> false </td><td> true/false </td></tr><tr><td>`?GL_INDEX_SHIFT'</td>
+%% <td> integer </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_INDEX_OFFSET'</td><td> integer
+%% </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_RED_SCALE'</td><td> float </td><td> 1 </td>
+%% <td>(-)</td></tr><tr><td>`?GL_GREEN_SCALE'</td><td> float </td><td> 1 </td><td>(-)</td></tr>
+%% <tr><td>`?GL_BLUE_SCALE'</td><td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_ALPHA_SCALE'
+%% </td><td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_DEPTH_SCALE'</td><td>
+%% float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_RED_BIAS'</td><td> float </td><td>
+%% 0 </td><td>(-)</td></tr><tr><td>`?GL_GREEN_BIAS'</td><td> float </td><td> 0 </td><td>(-)</td>
+%% </tr><tr><td>`?GL_BLUE_BIAS'</td><td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_ALPHA_BIAS'
+%% </td><td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_DEPTH_BIAS'</td><td>
+%% float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_RED_SCALE'</td><td>
+%% float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_GREEN_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_BLUE_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_ALPHA_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_RED_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_GREEN_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_BLUE_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_ALPHA_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_RED_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_GREEN_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_BLUE_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_ALPHA_SCALE'</td>
+%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_RED_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_GREEN_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_BLUE_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_ALPHA_BIAS'</td>
+%% <td> float </td><td> 0 </td><td>(-)</td></tr></tbody></table>
+%%
+%% ``gl:pixelTransferf'' can be used to set any pixel transfer parameter. If the parameter
+%% type is boolean, 0 implies false and any other value implies true. If `Pname' is
+%% an integer parameter, `Param' is rounded to the nearest integer.
+%%
+%% Likewise, ``gl:pixelTransferi'' can be used to set any of the pixel transfer parameters.
+%% Boolean parameters are set to false if `Param' is 0 and to true otherwise. `Param'
+%% is converted to floating point before being assigned to real-valued parameters.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml">external</a> documentation.
+-spec pixelTransferf(Pname, Param) -> ok when Pname :: enum(),Param :: float().
+pixelTransferf(Pname,Param) ->
+ cast(5225, <<Pname:?GLenum,Param:?GLfloat>>).
-%% @spec ({S,T}) -> ok
-%% @equiv texCoord2s(S,T)
--spec texCoord2sv({integer(),integer()}) -> ok.
-texCoord2sv({S,T}) -> texCoord2s(S,T).
+%% @doc
+%% See {@link pixelTransferf/2}
+-spec pixelTransferi(Pname, Param) -> ok when Pname :: enum(),Param :: integer().
+pixelTransferi(Pname,Param) ->
+ cast(5226, <<Pname:?GLenum,Param:?GLint>>).
-%% @spec (S::float(),T::float(),R::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord3d(float(),float(),float()) -> ok.
-texCoord3d(S,T,R) ->
- cast(5266, <<S:?GLdouble,T:?GLdouble,R:?GLdouble>>).
+%% @doc Set up pixel transfer maps
+%%
+%% ``gl:pixelMap'' sets up translation tables, or `maps', used by {@link gl:copyPixels/5}
+%% , {@link gl:copyTexImage1D/7} , {@link gl:copyTexImage2D/8} , {@link gl:copyTexSubImage1D/6} , {@link gl:copyTexSubImage2D/8}
+%% , {@link gl:copyTexSubImage3D/9} , {@link gl:drawPixels/5} , {@link gl:readPixels/7} , {@link gl:texImage1D/8}
+%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7}
+%% , and {@link gl:texSubImage1D/7} . Additionally, if the ARB_imaging subset is supported,
+%% the routines {@link gl:colorTable/6} , {@link gl:colorSubTable/6} , {@link gl:convolutionFilter1D/6}
+%% , {@link gl:convolutionFilter2D/7} , {@link gl:histogram/4} , {@link gl:minmax/3} , and {@link gl:separableFilter2D/8}
+%% . Use of these maps is described completely in the {@link gl:pixelTransferf/2} reference
+%% page, and partly in the reference pages for the pixel and texture image commands. Only
+%% the specification of the maps is described in this reference page.
+%%
+%% `Map' is a symbolic map name, indicating one of ten maps to set. `Mapsize' specifies
+%% the number of entries in the map, and `Values' is a pointer to an array of `Mapsize'
+%% map values.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a pixel transfer map is specified, `Values' is
+%% treated as a byte offset into the buffer object's data store.
+%%
+%% The ten maps are as follows:
+%%
+%% `?GL_PIXEL_MAP_I_TO_I': Maps color indices to color indices.
+%%
+%% `?GL_PIXEL_MAP_S_TO_S': Maps stencil indices to stencil indices.
+%%
+%% `?GL_PIXEL_MAP_I_TO_R': Maps color indices to red components.
+%%
+%% `?GL_PIXEL_MAP_I_TO_G': Maps color indices to green components.
+%%
+%% `?GL_PIXEL_MAP_I_TO_B': Maps color indices to blue components.
+%%
+%% `?GL_PIXEL_MAP_I_TO_A': Maps color indices to alpha components.
+%%
+%% `?GL_PIXEL_MAP_R_TO_R': Maps red components to red components.
+%%
+%% `?GL_PIXEL_MAP_G_TO_G': Maps green components to green components.
+%%
+%% `?GL_PIXEL_MAP_B_TO_B': Maps blue components to blue components.
+%%
+%% `?GL_PIXEL_MAP_A_TO_A': Maps alpha components to alpha components.
+%%
+%% The entries in a map can be specified as single-precision floating-point numbers, unsigned
+%% short integers, or unsigned int integers. Maps that store color component values (all
+%% but `?GL_PIXEL_MAP_I_TO_I' and `?GL_PIXEL_MAP_S_TO_S') retain their values in
+%% floating-point format, with unspecified mantissa and exponent sizes. Floating-point values
+%% specified by ``gl:pixelMapfv'' are converted directly to the internal floating-point
+%% format of these maps, then clamped to the range [0,1]. Unsigned integer values specified
+%% by ``gl:pixelMapusv'' and ``gl:pixelMapuiv'' are converted linearly such that the
+%% largest representable integer maps to 1.0, and 0 maps to 0.0.
+%%
+%% Maps that store indices, `?GL_PIXEL_MAP_I_TO_I' and `?GL_PIXEL_MAP_S_TO_S',
+%% retain their values in fixed-point format, with an unspecified number of bits to the right
+%% of the binary point. Floating-point values specified by ``gl:pixelMapfv'' are converted
+%% directly to the internal fixed-point format of these maps. Unsigned integer values specified
+%% by ``gl:pixelMapusv'' and ``gl:pixelMapuiv'' specify integer values, with all 0's
+%% to the right of the binary point.
+%%
+%% The following table shows the initial sizes and values for each of the maps. Maps that
+%% are indexed by either color or stencil indices must have `Mapsize' = 2 n for some
+%% n or the results are undefined. The maximum allowable size for each map depends on the
+%% implementation and can be determined by calling {@link gl:getBooleanv/1} with argument `?GL_MAX_PIXEL_MAP_TABLE'
+%% . The single maximum applies to all maps; it is at least 32. <table><tbody><tr><td> `Map'
+%% </td><td>` Lookup Index '</td><td>` Lookup Value '</td><td>` Initial Size '</td>
+%% <td>` Initial Value '</td></tr></tbody><tbody><tr><td>`?GL_PIXEL_MAP_I_TO_I'</td>
+%% <td> color index </td><td> color index </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_S_TO_S'
+%% </td><td> stencil index </td><td> stencil index </td><td> 1 </td><td> 0 </td></tr><tr><td>
+%% `?GL_PIXEL_MAP_I_TO_R'</td><td> color index </td><td> R </td><td> 1 </td><td> 0 </td>
+%% </tr><tr><td>`?GL_PIXEL_MAP_I_TO_G'</td><td> color index </td><td> G </td><td> 1 </td>
+%% <td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_I_TO_B'</td><td> color index </td><td> B </td>
+%% <td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_I_TO_A'</td><td> color index </td>
+%% <td> A </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_R_TO_R'</td><td> R </td>
+%% <td> R </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_G_TO_G'</td><td> G </td>
+%% <td> G </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_B_TO_B'</td><td> B </td>
+%% <td> B </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_A_TO_A'</td><td> A </td>
+%% <td> A </td><td> 1 </td><td> 0 </td></tr></tbody></table>
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml">external</a> documentation.
+-spec pixelMapfv(Map, Mapsize, Values) -> ok when Map :: enum(),Mapsize :: integer(),Values :: binary().
+pixelMapfv(Map,Mapsize,Values) ->
+ send_bin(Values),
+ cast(5227, <<Map:?GLenum,Mapsize:?GLsizei>>).
-%% @spec ({S,T,R}) -> ok
-%% @equiv texCoord3d(S,T,R)
--spec texCoord3dv({float(),float(),float()}) -> ok.
-texCoord3dv({S,T,R}) -> texCoord3d(S,T,R).
+%% @doc
+%% See {@link pixelMapfv/3}
+-spec pixelMapuiv(Map, Mapsize, Values) -> ok when Map :: enum(),Mapsize :: integer(),Values :: binary().
+pixelMapuiv(Map,Mapsize,Values) ->
+ send_bin(Values),
+ cast(5228, <<Map:?GLenum,Mapsize:?GLsizei>>).
-%% @spec (S::float(),T::float(),R::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord3f(float(),float(),float()) -> ok.
-texCoord3f(S,T,R) ->
- cast(5267, <<S:?GLfloat,T:?GLfloat,R:?GLfloat>>).
+%% @doc
+%% See {@link pixelMapfv/3}
+-spec pixelMapusv(Map, Mapsize, Values) -> ok when Map :: enum(),Mapsize :: integer(),Values :: binary().
+pixelMapusv(Map,Mapsize,Values) ->
+ send_bin(Values),
+ cast(5229, <<Map:?GLenum,Mapsize:?GLsizei>>).
-%% @spec ({S,T,R}) -> ok
-%% @equiv texCoord3f(S,T,R)
--spec texCoord3fv({float(),float(),float()}) -> ok.
-texCoord3fv({S,T,R}) -> texCoord3f(S,T,R).
+%% @doc Return the specified pixel map
+%%
+%% See the {@link gl:pixelMapfv/3} reference page for a description of the acceptable values
+%% for the `Map' parameter. ``gl:getPixelMap'' returns in `Data' the contents
+%% of the pixel map specified in `Map' . Pixel maps are used during the execution of {@link gl:readPixels/7}
+%% , {@link gl:drawPixels/5} , {@link gl:copyPixels/5} , {@link gl:texImage1D/8} , {@link gl:texImage2D/9}
+%% , {@link gl:texImage3D/10} , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7}
+%% , {@link gl:copyTexImage1D/7} , {@link gl:copyTexImage2D/8} , {@link gl:copyTexSubImage1D/6} , {@link gl:copyTexSubImage2D/8}
+%% , and {@link gl:copyTexSubImage3D/9} . to map color indices, stencil indices, color components,
+%% and depth components to other values.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a pixel map is requested, `Data' is treated as
+%% a byte offset into the buffer object's data store.
+%%
+%% Unsigned integer values, if requested, are linearly mapped from the internal fixed or
+%% floating-point representation such that 1.0 maps to the largest representable integer
+%% value, and 0.0 maps to 0. Return unsigned integer values are undefined if the map value
+%% was not in the range [0,1].
+%%
+%% To determine the required size of `Map' , call {@link gl:getBooleanv/1} with the appropriate
+%% symbolic constant.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml">external</a> documentation.
+-spec getPixelMapfv(Map, Values) -> ok when Map :: enum(),Values :: mem().
+getPixelMapfv(Map,Values) ->
+ send_bin(Values),
+ call(5230, <<Map:?GLenum>>).
-%% @spec (S::integer(),T::integer(),R::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord3i(integer(),integer(),integer()) -> ok.
-texCoord3i(S,T,R) ->
- cast(5268, <<S:?GLint,T:?GLint,R:?GLint>>).
+%% @doc
+%% See {@link getPixelMapfv/2}
+-spec getPixelMapuiv(Map, Values) -> ok when Map :: enum(),Values :: mem().
+getPixelMapuiv(Map,Values) ->
+ send_bin(Values),
+ call(5231, <<Map:?GLenum>>).
-%% @spec ({S,T,R}) -> ok
-%% @equiv texCoord3i(S,T,R)
--spec texCoord3iv({integer(),integer(),integer()}) -> ok.
-texCoord3iv({S,T,R}) -> texCoord3i(S,T,R).
+%% @doc
+%% See {@link getPixelMapfv/2}
+-spec getPixelMapusv(Map, Values) -> ok when Map :: enum(),Values :: mem().
+getPixelMapusv(Map,Values) ->
+ send_bin(Values),
+ call(5232, <<Map:?GLenum>>).
-%% @spec (S::integer(),T::integer(),R::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord3s(integer(),integer(),integer()) -> ok.
-texCoord3s(S,T,R) ->
- cast(5269, <<S:?GLshort,T:?GLshort,R:?GLshort>>).
+%% @doc Draw a bitmap
+%%
+%% A bitmap is a binary image. When drawn, the bitmap is positioned relative to the current
+%% raster position, and frame buffer pixels corresponding to 1's in the bitmap are written
+%% using the current raster color or index. Frame buffer pixels corresponding to 0's in the
+%% bitmap are not modified.
+%%
+%% ``gl:bitmap'' takes seven arguments. The first pair specifies the width and height of
+%% the bitmap image. The second pair specifies the location of the bitmap origin relative
+%% to the lower left corner of the bitmap image. The third pair of arguments specifies `x'
+%% and `y' offsets to be added to the current raster position after the bitmap has
+%% been drawn. The final argument is a pointer to the bitmap image itself.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a bitmap image is specified, `Bitmap' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% The bitmap image is interpreted like image data for the {@link gl:drawPixels/5} command,
+%% with `Width' and `Height' corresponding to the width and height arguments of
+%% that command, and with `type' set to `?GL_BITMAP' and `format' set to `?GL_COLOR_INDEX'
+%% . Modes specified using {@link gl:pixelStoref/2} affect the interpretation of bitmap image
+%% data; modes specified using {@link gl:pixelTransferf/2} do not.
+%%
+%% If the current raster position is invalid, ``gl:bitmap'' is ignored. Otherwise, the
+%% lower left corner of the bitmap image is positioned at the window coordinates
+%%
+%% x w=|x r-x o|
+%%
+%% y w=|y r-y o|
+%%
+%% where (x r y r) is the raster position and (x o y o) is the bitmap origin. Fragments are then generated
+%% for each pixel corresponding to a 1 (one) in the bitmap image. These fragments are generated
+%% using the current raster `z' coordinate, color or color index, and current raster
+%% texture coordinates. They are then treated just as if they had been generated by a point,
+%% line, or polygon, including texture mapping, fogging, and all per-fragment operations
+%% such as alpha and depth testing.
+%%
+%% After the bitmap has been drawn, the `x' and `y' coordinates of the current
+%% raster position are offset by `Xmove' and `Ymove' . No change is made to the `z'
+%% coordinate of the current raster position, or to the current raster color, texture coordinates,
+%% or index.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml">external</a> documentation.
+-spec bitmap(Width, Height, Xorig, Yorig, Xmove, Ymove, Bitmap) -> ok when Width :: integer(),Height :: integer(),Xorig :: float(),Yorig :: float(),Xmove :: float(),Ymove :: float(),Bitmap :: offset()|mem().
+bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) when is_integer(Bitmap) ->
+ cast(5233, <<Width:?GLsizei,Height:?GLsizei,Xorig:?GLfloat,Yorig:?GLfloat,Xmove:?GLfloat,Ymove:?GLfloat,Bitmap:?GLuint>>);
+bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) ->
+ send_bin(Bitmap),
+ cast(5234, <<Width:?GLsizei,Height:?GLsizei,Xorig:?GLfloat,Yorig:?GLfloat,Xmove:?GLfloat,Ymove:?GLfloat>>).
-%% @spec ({S,T,R}) -> ok
-%% @equiv texCoord3s(S,T,R)
--spec texCoord3sv({integer(),integer(),integer()}) -> ok.
-texCoord3sv({S,T,R}) -> texCoord3s(S,T,R).
+%% @doc Read a block of pixels from the frame buffer
+%%
+%% ``gl:readPixels'' returns pixel data from the frame buffer, starting with the pixel
+%% whose lower left corner is at location ( `X' , `Y' ), into client memory starting
+%% at location `Data' . Several parameters control the processing of the pixel data before
+%% it is placed into client memory. These parameters are set with {@link gl:pixelStoref/2} .
+%% This reference page describes the effects on ``gl:readPixels'' of most, but not all
+%% of the parameters specified by these three commands.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a block of pixels is requested, `Data' is treated
+%% as a byte offset into the buffer object's data store rather than a pointer to client memory.
+%%
+%%
+%% ``gl:readPixels'' returns values from each pixel with lower left corner at (x+i y+j) for 0&lt;=
+%% i&lt; width and 0&lt;= j&lt; height. This pixel is said to be the ith pixel in the
+%% jth row. Pixels are returned in row order from the lowest to the highest row, left to
+%% right in each row.
+%%
+%% `Format' specifies the format for the returned pixel values; accepted values are:
+%%
+%% `?GL_STENCIL_INDEX': Stencil values are read from the stencil buffer. Each index
+%% is converted to fixed point, shifted left or right depending on the value and sign of `?GL_INDEX_SHIFT'
+%% , and added to `?GL_INDEX_OFFSET'. If `?GL_MAP_STENCIL' is `?GL_TRUE',
+%% indices are replaced by their mappings in the table `?GL_PIXEL_MAP_S_TO_S'.
+%%
+%% `?GL_DEPTH_COMPONENT': Depth values are read from the depth buffer. Each component
+%% is converted to floating point such that the minimum depth value maps to 0 and the maximum
+%% value maps to 1. Each component is then multiplied by `?GL_DEPTH_SCALE', added to `?GL_DEPTH_BIAS'
+%% , and finally clamped to the range [0 1].
+%%
+%% `?GL_DEPTH_STENCIL': Values are taken from both the depth and stencil buffers. The `Type'
+%% parameter must be `?GL_UNSIGNED_INT_24_8' or `?GL_FLOAT_32_UNSIGNED_INT_24_8_REV'
+%% .
+%%
+%% `?GL_RED'
+%%
+%% `?GL_GREEN'
+%%
+%% `?GL_BLUE'
+%%
+%% `?GL_RGB'
+%%
+%% `?GL_BGR'
+%%
+%% `?GL_RGBA'
+%%
+%% `?GL_BGRA': Finally, the indices or components are converted to the proper format,
+%% as specified by `Type' . If `Format' is `?GL_STENCIL_INDEX' and `Type'
+%% is not `?GL_FLOAT', each index is masked with the mask value given in the following
+%% table. If `Type' is `?GL_FLOAT', then each integer index is converted to single-precision
+%% floating-point format.
+%%
+%% If `Format' is `?GL_RED', `?GL_GREEN', `?GL_BLUE', `?GL_RGB', `?GL_BGR'
+%% , `?GL_RGBA', or `?GL_BGRA' and `Type' is not `?GL_FLOAT', each component
+%% is multiplied by the multiplier shown in the following table. If type is `?GL_FLOAT',
+%% then each component is passed as is (or converted to the client's single-precision floating-point
+%% format if it is different from the one used by the GL).
+%%
+%% <table><tbody><tr><td> `Type' </td><td>` Index Mask '</td><td>` Component Conversion '
+%% </td></tr></tbody><tbody><tr><td>`?GL_UNSIGNED_BYTE'</td><td> 2 8-1</td><td>(2 8-1) c</td></tr>
+%% <tr><td>`?GL_BYTE'</td><td> 2 7-1</td><td>((2 8-1) c-1)/2</td></tr><tr><td>`?GL_UNSIGNED_SHORT'
+%% </td><td> 2 16-1</td><td>(2 16-1) c</td></tr><tr><td>`?GL_SHORT'</td><td> 2 15-1</td><td>((2
+%% 16-1)
+%% c-1)/2</td>
+%% </tr><tr><td>`?GL_UNSIGNED_INT'</td><td> 2 32-1</td><td>(2 32-1) c</td></tr><tr><td>`?GL_INT'
+%% </td><td> 2 31-1</td><td>((2 32-1) c-1)/2</td></tr><tr><td>`?GL_HALF_FLOAT'</td><td> none </td><td>
+%% c</td></tr><tr><td>`?GL_FLOAT'</td><td> none </td><td> c</td></tr><tr><td>`?GL_UNSIGNED_BYTE_3_3_2'
+%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_BYTE_2_3_3_REV'</td><td>
+%% 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5'</td><td> 2 N-1</td><td>
+%% (2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5_REV'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr>
+%% <tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4_REV'
+%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_5_5_1'</td><td> 2
+%% N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_1_5_5_5_REV'</td><td> 2 N-1</td>
+%% <td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT_8_8_8_8_REV'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_10_10_10_2'
+%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_2_10_10_10_REV'</td><td>
+%% 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_24_8'</td><td> 2 N-1</td><td>(2
+%% N-1)
+%% c</td></tr><tr><td>`?GL_UNSIGNED_INT_10F_11F_11F_REV'</td><td> -- </td><td> Special </td>
+%% </tr><tr><td>`?GL_UNSIGNED_INT_5_9_9_9_REV'</td><td> -- </td><td> Special </td></tr><tr>
+%% <td>`?GL_FLOAT_32_UNSIGNED_INT_24_8_REV'</td><td> none </td><td> c (Depth Only) </td>
+%% </tr></tbody></table>
+%%
+%% Return values are placed in memory as follows. If `Format' is `?GL_STENCIL_INDEX'
+%% , `?GL_DEPTH_COMPONENT', `?GL_RED', `?GL_GREEN', or `?GL_BLUE', a
+%% single value is returned and the data for the ith pixel in the jth row is placed in
+%% location (j) width+i. `?GL_RGB' and `?GL_BGR' return three values, `?GL_RGBA'
+%% and `?GL_BGRA' return four values for each pixel, with all values corresponding
+%% to a single pixel occupying contiguous space in `Data' . Storage parameters set by {@link gl:pixelStoref/2}
+%% , such as `?GL_PACK_LSB_FIRST' and `?GL_PACK_SWAP_BYTES', affect the way that
+%% data is written into memory. See {@link gl:pixelStoref/2} for a description.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml">external</a> documentation.
+-spec readPixels(X, Y, Width, Height, Format, Type, Pixels) -> ok when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: mem().
+readPixels(X,Y,Width,Height,Format,Type,Pixels) ->
+ send_bin(Pixels),
+ call(5235, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (S::float(),T::float(),R::float(),Q::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord4d(float(),float(),float(),float()) -> ok.
-texCoord4d(S,T,R,Q) ->
- cast(5270, <<S:?GLdouble,T:?GLdouble,R:?GLdouble,Q:?GLdouble>>).
+%% @doc Write a block of pixels to the frame buffer
+%%
+%% ``gl:drawPixels'' reads pixel data from memory and writes it into the frame buffer relative
+%% to the current raster position, provided that the raster position is valid. Use {@link gl:rasterPos2d/2}
+%% or {@link gl:windowPos2d/2} to set the current raster position; use {@link gl:getBooleanv/1} with
+%% argument `?GL_CURRENT_RASTER_POSITION_VALID' to determine if the specified raster
+%% position is valid, and {@link gl:getBooleanv/1} with argument `?GL_CURRENT_RASTER_POSITION'
+%% to query the raster position.
+%%
+%% Several parameters define the encoding of pixel data in memory and control the processing
+%% of the pixel data before it is placed in the frame buffer. These parameters are set with
+%% four commands: {@link gl:pixelStoref/2} , {@link gl:pixelTransferf/2} , {@link gl:pixelMapfv/3} ,
+%% and {@link gl:pixelZoom/2} . This reference page describes the effects on ``gl:drawPixels''
+%% of many, but not all, of the parameters specified by these four commands.
+%%
+%% Data is read from `Data' as a sequence of signed or unsigned bytes, signed or unsigned
+%% shorts, signed or unsigned integers, or single-precision floating-point values, depending
+%% on `Type' . When `Type' is one of `?GL_UNSIGNED_BYTE', `?GL_BYTE', `?GL_UNSIGNED_SHORT'
+%% , `?GL_SHORT', `?GL_UNSIGNED_INT', `?GL_INT', or `?GL_FLOAT' each
+%% of these bytes, shorts, integers, or floating-point values is interpreted as one color
+%% or depth component, or one index, depending on `Format' . When `Type' is one of `?GL_UNSIGNED_BYTE_3_3_2'
+%% , `?GL_UNSIGNED_SHORT_5_6_5', `?GL_UNSIGNED_SHORT_4_4_4_4', `?GL_UNSIGNED_SHORT_5_5_5_1'
+%% , `?GL_UNSIGNED_INT_8_8_8_8', or `?GL_UNSIGNED_INT_10_10_10_2', each unsigned
+%% value is interpreted as containing all the components for a single pixel, with the color
+%% components arranged according to `Format' . When `Type' is one of `?GL_UNSIGNED_BYTE_2_3_3_REV'
+%% , `?GL_UNSIGNED_SHORT_5_6_5_REV', `?GL_UNSIGNED_SHORT_4_4_4_4_REV', `?GL_UNSIGNED_SHORT_1_5_5_5_REV'
+%% , `?GL_UNSIGNED_INT_8_8_8_8_REV', or `?GL_UNSIGNED_INT_2_10_10_10_REV', each
+%% unsigned value is interpreted as containing all color components, specified by `Format'
+%% , for a single pixel in a reversed order. Indices are always treated individually. Color
+%% components are treated as groups of one, two, three, or four values, again based on `Format'
+%% . Both individual indices and groups of components are referred to as pixels. If `Type'
+%% is `?GL_BITMAP', the data must be unsigned bytes, and `Format' must be either `?GL_COLOR_INDEX'
+%% or `?GL_STENCIL_INDEX'. Each unsigned byte is treated as eight 1-bit pixels, with
+%% bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} ).
+%%
+%% width*height pixels are read from memory, starting at location `Data' . By default,
+%% these pixels are taken from adjacent memory locations, except that after all `Width'
+%% pixels are read, the read pointer is advanced to the next four-byte boundary. The four-byte
+%% row alignment is specified by {@link gl:pixelStoref/2} with argument `?GL_UNPACK_ALIGNMENT'
+%% , and it can be set to one, two, four, or eight bytes. Other pixel store parameters specify
+%% different read pointer advancements, both before the first pixel is read and after all `Width'
+%% pixels are read. See the {@link gl:pixelStoref/2} reference page for details on these options.
+%%
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a block of pixels is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% The width*height pixels that are read from memory are each operated on in the same
+%% way, based on the values of several parameters specified by {@link gl:pixelTransferf/2}
+%% and {@link gl:pixelMapfv/3} . The details of these operations, as well as the target buffer
+%% into which the pixels are drawn, are specific to the format of the pixels, as specified
+%% by `Format' . `Format' can assume one of 13 symbolic values:
+%%
+%% `?GL_COLOR_INDEX': Each pixel is a single value, a color index. It is converted
+%% to fixed-point format, with an unspecified number of bits to the right of the binary point,
+%% regardless of the memory data type. Floating-point values convert to true fixed-point
+%% values. Signed and unsigned integer data is converted with all fraction bits set to 0.
+%% Bitmap data convert to either 0 or 1.
+%%
+%% Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits and added to `?GL_INDEX_OFFSET'
+%% . If `?GL_INDEX_SHIFT' is negative, the shift is to the right. In either case, zero
+%% bits fill otherwise unspecified bit locations in the result.
+%%
+%% If the GL is in RGBA mode, the resulting index is converted to an RGBA pixel with the
+%% help of the `?GL_PIXEL_MAP_I_TO_R', `?GL_PIXEL_MAP_I_TO_G', `?GL_PIXEL_MAP_I_TO_B'
+%% , and `?GL_PIXEL_MAP_I_TO_A' tables. If the GL is in color index mode, and if `?GL_MAP_COLOR'
+%% is true, the index is replaced with the value that it references in lookup table `?GL_PIXEL_MAP_I_TO_I'
+%% . Whether the lookup replacement of the index is done or not, the integer part of the
+%% index is then ANDed with 2 b-1, where b is the number of bits in a color index buffer.
+%%
+%%
+%% The GL then converts the resulting indices or RGBA colors to fragments by attaching the
+%% current raster position `z' coordinate and texture coordinates to each pixel, then
+%% assigning x and y window coordinates to the nth fragment such that x n= x r+n%
+%% width
+%%
+%% y n= y r+|n/width|
+%%
+%% where (x r y r) is the current raster position. These pixel fragments are then treated just like
+%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog,
+%% and all the fragment operations are applied before the fragments are written to the frame
+%% buffer.
+%%
+%% `?GL_STENCIL_INDEX': Each pixel is a single value, a stencil index. It is converted
+%% to fixed-point format, with an unspecified number of bits to the right of the binary point,
+%% regardless of the memory data type. Floating-point values convert to true fixed-point
+%% values. Signed and unsigned integer data is converted with all fraction bits set to 0.
+%% Bitmap data convert to either 0 or 1.
+%%
+%% Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits, and added
+%% to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' is negative, the shift is to the
+%% right. In either case, zero bits fill otherwise unspecified bit locations in the result.
+%% If `?GL_MAP_STENCIL' is true, the index is replaced with the value that it references
+%% in lookup table `?GL_PIXEL_MAP_S_TO_S'. Whether the lookup replacement of the index
+%% is done or not, the integer part of the index is then ANDed with 2 b-1, where b is
+%% the number of bits in the stencil buffer. The resulting stencil indices are then written
+%% to the stencil buffer such that the nth index is written to location
+%%
+%% x n= x r+n% width
+%%
+%% y n= y r+|n/width|
+%%
+%% where (x r y r) is the current raster position. Only the pixel ownership test, the scissor test,
+%% and the stencil writemask affect these write operations.
+%%
+%% `?GL_DEPTH_COMPONENT': Each pixel is a single-depth component. Floating-point data
+%% is converted directly to an internal floating-point format with unspecified precision.
+%% Signed integer data is mapped linearly to the internal floating-point format such that
+%% the most positive representable integer value maps to 1.0, and the most negative representable
+%% value maps to -1.0. Unsigned integer data is mapped similarly: the largest integer value
+%% maps to 1.0, and 0 maps to 0.0. The resulting floating-point depth value is then multiplied
+%% by `?GL_DEPTH_SCALE' and added to `?GL_DEPTH_BIAS'. The result is clamped to
+%% the range [0 1].
+%%
+%% The GL then converts the resulting depth components to fragments by attaching the current
+%% raster position color or color index and texture coordinates to each pixel, then assigning
+%% x and y window coordinates to the nth fragment such that
+%%
+%% x n= x r+n% width
+%%
+%% y n= y r+|n/width|
+%%
+%% where (x r y r) is the current raster position. These pixel fragments are then treated just like
+%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog,
+%% and all the fragment operations are applied before the fragments are written to the frame
+%% buffer.
+%%
+%% `?GL_RGBA'
+%%
+%% `?GL_BGRA': Each pixel is a four-component group: For `?GL_RGBA', the red component
+%% is first, followed by green, followed by blue, followed by alpha; for `?GL_BGRA'
+%% the order is blue, green, red and then alpha. Floating-point values are converted directly
+%% to an internal floating-point format with unspecified precision. Signed integer values
+%% are mapped linearly to the internal floating-point format such that the most positive
+%% representable integer value maps to 1.0, and the most negative representable value maps
+%% to -1.0. (Note that this mapping does not convert 0 precisely to 0.0.) Unsigned integer
+%% data is mapped similarly: The largest integer value maps to 1.0, and 0 maps to 0.0. The
+%% resulting floating-point color values are then multiplied by `?GL_c_SCALE' and added
+%% to `?GL_c_BIAS', where `c' is RED, GREEN, BLUE, and ALPHA for the respective
+%% color components. The results are clamped to the range [0 1].
+%%
+%% If `?GL_MAP_COLOR' is true, each color component is scaled by the size of lookup
+%% table `?GL_PIXEL_MAP_c_TO_c', then replaced by the value that it references in that
+%% table. `c' is R, G, B, or A respectively.
+%%
+%% The GL then converts the resulting RGBA colors to fragments by attaching the current
+%% raster position `z' coordinate and texture coordinates to each pixel, then assigning
+%% x and y window coordinates to the nth fragment such that
+%%
+%% x n= x r+n% width
+%%
+%% y n= y r+|n/width|
+%%
+%% where (x r y r) is the current raster position. These pixel fragments are then treated just like
+%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog,
+%% and all the fragment operations are applied before the fragments are written to the frame
+%% buffer.
+%%
+%% `?GL_RED': Each pixel is a single red component. This component is converted to
+%% the internal floating-point format in the same way the red component of an RGBA pixel
+%% is. It is then converted to an RGBA pixel with green and blue set to 0, and alpha set
+%% to 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel.
+%%
+%%
+%% `?GL_GREEN': Each pixel is a single green component. This component is converted
+%% to the internal floating-point format in the same way the green component of an RGBA pixel
+%% is. It is then converted to an RGBA pixel with red and blue set to 0, and alpha set to
+%% 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel.
+%%
+%% `?GL_BLUE': Each pixel is a single blue component. This component is converted to
+%% the internal floating-point format in the same way the blue component of an RGBA pixel
+%% is. It is then converted to an RGBA pixel with red and green set to 0, and alpha set to
+%% 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel.
+%%
+%% `?GL_ALPHA': Each pixel is a single alpha component. This component is converted
+%% to the internal floating-point format in the same way the alpha component of an RGBA pixel
+%% is. It is then converted to an RGBA pixel with red, green, and blue set to 0. After this
+%% conversion, the pixel is treated as if it had been read as an RGBA pixel.
+%%
+%% `?GL_RGB'
+%%
+%% `?GL_BGR': Each pixel is a three-component group: red first, followed by green,
+%% followed by blue; for `?GL_BGR', the first component is blue, followed by green and
+%% then red. Each component is converted to the internal floating-point format in the same
+%% way the red, green, and blue components of an RGBA pixel are. The color triple is converted
+%% to an RGBA pixel with alpha set to 1. After this conversion, the pixel is treated as if
+%% it had been read as an RGBA pixel.
+%%
+%% `?GL_LUMINANCE': Each pixel is a single luminance component. This component is converted
+%% to the internal floating-point format in the same way the red component of an RGBA pixel
+%% is. It is then converted to an RGBA pixel with red, green, and blue set to the converted
+%% luminance value, and alpha set to 1. After this conversion, the pixel is treated as if
+%% it had been read as an RGBA pixel.
+%%
+%% `?GL_LUMINANCE_ALPHA': Each pixel is a two-component group: luminance first, followed
+%% by alpha. The two components are converted to the internal floating-point format in the
+%% same way the red component of an RGBA pixel is. They are then converted to an RGBA pixel
+%% with red, green, and blue set to the converted luminance value, and alpha set to the converted
+%% alpha value. After this conversion, the pixel is treated as if it had been read as an
+%% RGBA pixel.
+%%
+%% The following table summarizes the meaning of the valid constants for the `type'
+%% parameter:
+%%
+%% <table><tbody><tr><td>` Type '</td><td>` Corresponding Type '</td></tr></tbody><tbody>
+%% <tr><td>`?GL_UNSIGNED_BYTE'</td><td> unsigned 8-bit integer </td></tr><tr><td>`?GL_BYTE'
+%% </td><td> signed 8-bit integer </td></tr><tr><td>`?GL_BITMAP'</td><td> single bits
+%% in unsigned 8-bit integers </td></tr><tr><td>`?GL_UNSIGNED_SHORT'</td><td> unsigned
+%% 16-bit integer </td></tr><tr><td>`?GL_SHORT'</td><td> signed 16-bit integer </td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT'</td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_INT'
+%% </td><td> 32-bit integer </td></tr><tr><td>`?GL_FLOAT'</td><td> single-precision
+%% floating-point </td></tr><tr><td>`?GL_UNSIGNED_BYTE_3_3_2'</td><td> unsigned 8-bit
+%% integer </td></tr><tr><td>`?GL_UNSIGNED_BYTE_2_3_3_REV'</td><td> unsigned 8-bit
+%% integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5'</td>
+%% <td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5_REV'</td><td>
+%% unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4'
+%% </td><td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4_REV'</td>
+%% <td> unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_5_5_1'
+%% </td><td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_1_5_5_5_REV'</td>
+%% <td> unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8'
+%% </td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8_REV'</td>
+%% <td> unsigned 32-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_INT_10_10_10_2'
+%% </td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_UNSIGNED_INT_2_10_10_10_REV'</td>
+%% <td> unsigned 32-bit integer with reversed component ordering </td></tr></tbody></table>
+%%
+%% The rasterization described so far assumes pixel zoom factors of 1. If {@link gl:pixelZoom/2}
+%% is used to change the x and y pixel zoom factors, pixels are converted to fragments
+%% as follows. If (x r y r) is the current raster position, and a given pixel is in the nth column
+%% and mth row of the pixel rectangle, then fragments are generated for pixels whose centers
+%% are in the rectangle with corners at
+%%
+%% (x r+(zoom x) n y r+(zoom y) m)
+%%
+%% (x r+(zoom x)(n+1) y r+(zoom y)(m+1))
+%%
+%% where zoom x is the value of `?GL_ZOOM_X' and zoom y is the value of `?GL_ZOOM_Y'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml">external</a> documentation.
+-spec drawPixels(Width, Height, Format, Type, Pixels) -> ok when Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
+drawPixels(Width,Height,Format,Type,Pixels) when is_integer(Pixels) ->
+ cast(5236, <<Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
+drawPixels(Width,Height,Format,Type,Pixels) ->
+ send_bin(Pixels),
+ cast(5237, <<Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec ({S,T,R,Q}) -> ok
-%% @equiv texCoord4d(S,T,R,Q)
--spec texCoord4dv({float(),float(),float(),float()}) -> ok.
-texCoord4dv({S,T,R,Q}) -> texCoord4d(S,T,R,Q).
+%% @doc Copy pixels in the frame buffer
+%%
+%% ``gl:copyPixels'' copies a screen-aligned rectangle of pixels from the specified frame
+%% buffer location to a region relative to the current raster position. Its operation is
+%% well defined only if the entire pixel source region is within the exposed portion of the
+%% window. Results of copies from outside the window, or from regions of the window that
+%% are not exposed, are hardware dependent and undefined.
+%%
+%% `X' and `Y' specify the window coordinates of the lower left corner of the rectangular
+%% region to be copied. `Width' and `Height' specify the dimensions of the rectangular
+%% region to be copied. Both `Width' and `Height' must not be negative.
+%%
+%% Several parameters control the processing of the pixel data while it is being copied.
+%% These parameters are set with three commands: {@link gl:pixelTransferf/2} , {@link gl:pixelMapfv/3}
+%% , and {@link gl:pixelZoom/2} . This reference page describes the effects on ``gl:copyPixels''
+%% of most, but not all, of the parameters specified by these three commands.
+%%
+%% ``gl:copyPixels'' copies values from each pixel with the lower left-hand corner at (x+i
+%% y+j)
+%% for 0&lt;= i&lt; width and 0&lt;= j&lt; height. This pixel is said to be the ith
+%% pixel in the jth row. Pixels are copied in row order from the lowest to the highest
+%% row, left to right in each row.
+%%
+%% `Type' specifies whether color, depth, or stencil data is to be copied. The details
+%% of the transfer for each data type are as follows:
+%%
+%% `?GL_COLOR': Indices or RGBA colors are read from the buffer currently specified
+%% as the read source buffer (see {@link gl:readBuffer/1} ). If the GL is in color index mode,
+%% each index that is read from this buffer is converted to a fixed-point format with an
+%% unspecified number of bits to the right of the binary point. Each index is then shifted
+%% left by `?GL_INDEX_SHIFT' bits, and added to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT'
+%% is negative, the shift is to the right. In either case, zero bits fill otherwise unspecified
+%% bit locations in the result. If `?GL_MAP_COLOR' is true, the index is replaced with
+%% the value that it references in lookup table `?GL_PIXEL_MAP_I_TO_I'. Whether the
+%% lookup replacement of the index is done or not, the integer part of the index is then
+%% ANDed with 2 b-1, where b is the number of bits in a color index buffer.
+%%
+%% If the GL is in RGBA mode, the red, green, blue, and alpha components of each pixel that
+%% is read are converted to an internal floating-point format with unspecified precision.
+%% The conversion maps the largest representable component value to 1.0, and component value
+%% 0 to 0.0. The resulting floating-point color values are then multiplied by `?GL_c_SCALE'
+%% and added to `?GL_c_BIAS', where `c' is RED, GREEN, BLUE, and ALPHA for the
+%% respective color components. The results are clamped to the range [0,1]. If `?GL_MAP_COLOR'
+%% is true, each color component is scaled by the size of lookup table `?GL_PIXEL_MAP_c_TO_c'
+%% , then replaced by the value that it references in that table. `c' is R, G, B, or
+%% A.
+%%
+%% If the ARB_imaging extension is supported, the color values may be additionally processed
+%% by color-table lookups, color-matrix transformations, and convolution filters.
+%%
+%% The GL then converts the resulting indices or RGBA colors to fragments by attaching the
+%% current raster position `z' coordinate and texture coordinates to each pixel, then
+%% assigning window coordinates (x r+i y r+j), where (x r y r) is the current raster position, and the pixel was
+%% the ith pixel in the jth row. These pixel fragments are then treated just like the
+%% fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog, and
+%% all the fragment operations are applied before the fragments are written to the frame
+%% buffer.
+%%
+%% `?GL_DEPTH': Depth values are read from the depth buffer and converted directly
+%% to an internal floating-point format with unspecified precision. The resulting floating-point
+%% depth value is then multiplied by `?GL_DEPTH_SCALE' and added to `?GL_DEPTH_BIAS'
+%% . The result is clamped to the range [0,1].
+%%
+%% The GL then converts the resulting depth components to fragments by attaching the current
+%% raster position color or color index and texture coordinates to each pixel, then assigning
+%% window coordinates (x r+i y r+j), where (x r y r) is the current raster position, and the pixel was the ith
+%% pixel in the jth row. These pixel fragments are then treated just like the fragments
+%% generated by rasterizing points, lines, or polygons. Texture mapping, fog, and all the
+%% fragment operations are applied before the fragments are written to the frame buffer.
+%%
+%% `?GL_STENCIL': Stencil indices are read from the stencil buffer and converted to
+%% an internal fixed-point format with an unspecified number of bits to the right of the
+%% binary point. Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits,
+%% and added to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' is negative, the shift
+%% is to the right. In either case, zero bits fill otherwise unspecified bit locations in
+%% the result. If `?GL_MAP_STENCIL' is true, the index is replaced with the value that
+%% it references in lookup table `?GL_PIXEL_MAP_S_TO_S'. Whether the lookup replacement
+%% of the index is done or not, the integer part of the index is then ANDed with 2 b-1,
+%% where b is the number of bits in the stencil buffer. The resulting stencil indices are
+%% then written to the stencil buffer such that the index read from the ith location of
+%% the jth row is written to location (x r+i y r+j), where (x r y r) is the current raster position. Only the
+%% pixel ownership test, the scissor test, and the stencil writemask affect these write operations.
+%%
+%%
+%% The rasterization described thus far assumes pixel zoom factors of 1.0. If {@link gl:pixelZoom/2}
+%% is used to change the x and y pixel zoom factors, pixels are converted to fragments
+%% as follows. If (x r y r) is the current raster position, and a given pixel is in the ith location
+%% in the jth row of the source pixel rectangle, then fragments are generated for pixels
+%% whose centers are in the rectangle with corners at
+%%
+%% (x r+(zoom x) i y r+(zoom y) j)
+%%
+%% and
+%%
+%% (x r+(zoom x)(i+1) y r+(zoom y)(j+1))
+%%
+%% where zoom x is the value of `?GL_ZOOM_X' and zoom y is the value of `?GL_ZOOM_Y'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyPixels.xml">external</a> documentation.
+-spec copyPixels(X, Y, Width, Height, Type) -> ok when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Type :: enum().
+copyPixels(X,Y,Width,Height,Type) ->
+ cast(5238, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Type:?GLenum>>).
-%% @spec (S::float(),T::float(),R::float(),Q::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord4f(float(),float(),float(),float()) -> ok.
-texCoord4f(S,T,R,Q) ->
- cast(5271, <<S:?GLfloat,T:?GLfloat,R:?GLfloat,Q:?GLfloat>>).
+%% @doc Set front and back function and reference value for stencil testing
+%%
+%% Stenciling, like depth-buffering, enables and disables drawing on a per-pixel basis.
+%% Stencil planes are first drawn into using GL drawing primitives, then geometry and images
+%% are rendered using the stencil planes to mask out portions of the screen. Stenciling is
+%% typically used in multipass rendering algorithms to achieve special effects, such as decals,
+%% outlining, and constructive solid geometry rendering.
+%%
+%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
+%% between the reference value and the value in the stencil buffer. To enable and disable
+%% the test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
+%% . To specify actions based on the outcome of the stencil test, call {@link gl:stencilOp/3}
+%% or {@link gl:stencilOpSeparate/4} .
+%%
+%% There can be two separate sets of `Func' , `Ref' , and `Mask' parameters;
+%% one affects back-facing polygons, and the other affects front-facing polygons as well
+%% as other non-polygon primitives. {@link gl:stencilFunc/3} sets both front and back stencil
+%% state to the same values. Use {@link gl:stencilFuncSeparate/4} to set front and back stencil
+%% state to different values.
+%%
+%% `Func' is a symbolic constant that determines the stencil comparison function. It
+%% accepts one of eight values, shown in the following list. `Ref' is an integer reference
+%% value that is used in the stencil comparison. It is clamped to the range [0 2 n-1], where n
+%% is the number of bitplanes in the stencil buffer. `Mask' is bitwise ANDed with both
+%% the reference value and the stored stencil value, with the ANDed values participating
+%% in the comparison.
+%%
+%% If `stencil' represents the value stored in the corresponding stencil buffer location,
+%% the following list shows the effect of each comparison function that can be specified by `Func'
+%% . Only if the comparison succeeds is the pixel passed through to the next stage in the
+%% rasterization process (see {@link gl:stencilOp/3} ). All tests treat `stencil' values
+%% as unsigned integers in the range [0 2 n-1], where n is the number of bitplanes in the stencil
+%% buffer.
+%%
+%% The following values are accepted by `Func' :
+%%
+%% `?GL_NEVER': Always fails.
+%%
+%% `?GL_LESS': Passes if ( `Ref' &amp; `Mask' ) &lt; ( `stencil' &amp; `Mask'
+%% ).
+%%
+%% `?GL_LEQUAL': Passes if ( `Ref' &amp; `Mask' ) &lt;= ( `stencil'
+%% &amp; `Mask' ).
+%%
+%% `?GL_GREATER': Passes if ( `Ref' &amp; `Mask' ) &gt; ( `stencil'
+%% &amp; `Mask' ).
+%%
+%% `?GL_GEQUAL': Passes if ( `Ref' &amp; `Mask' ) &gt;= ( `stencil'
+%% &amp; `Mask' ).
+%%
+%% `?GL_EQUAL': Passes if ( `Ref' &amp; `Mask' ) = ( `stencil' &amp; `Mask'
+%% ).
+%%
+%% `?GL_NOTEQUAL': Passes if ( `Ref' &amp; `Mask' ) != ( `stencil' &amp;
+%% `Mask' ).
+%%
+%% `?GL_ALWAYS': Always passes.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml">external</a> documentation.
+-spec stencilFunc(Func, Ref, Mask) -> ok when Func :: enum(),Ref :: integer(),Mask :: integer().
+stencilFunc(Func,Ref,Mask) ->
+ cast(5239, <<Func:?GLenum,Ref:?GLint,Mask:?GLuint>>).
-%% @spec ({S,T,R,Q}) -> ok
-%% @equiv texCoord4f(S,T,R,Q)
--spec texCoord4fv({float(),float(),float(),float()}) -> ok.
-texCoord4fv({S,T,R,Q}) -> texCoord4f(S,T,R,Q).
+%% @doc Control the front and back writing of individual bits in the stencil planes
+%%
+%% ``gl:stencilMask'' controls the writing of individual bits in the stencil planes. The
+%% least significant n bits of `Mask' , where n is the number of bits in the stencil
+%% buffer, specify a mask. Where a 1 appears in the mask, it's possible to write to the corresponding
+%% bit in the stencil buffer. Where a 0 appears, the corresponding bit is write-protected.
+%% Initially, all bits are enabled for writing.
+%%
+%% There can be two separate `Mask' writemasks; one affects back-facing polygons, and
+%% the other affects front-facing polygons as well as other non-polygon primitives. {@link gl:stencilMask/1}
+%% sets both front and back stencil writemasks to the same values. Use {@link gl:stencilMaskSeparate/2}
+%% to set front and back stencil writemasks to different values.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMask.xml">external</a> documentation.
+-spec stencilMask(Mask) -> ok when Mask :: integer().
+stencilMask(Mask) ->
+ cast(5240, <<Mask:?GLuint>>).
-%% @spec (S::integer(),T::integer(),R::integer(),Q::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord4i(integer(),integer(),integer(),integer()) -> ok.
-texCoord4i(S,T,R,Q) ->
- cast(5272, <<S:?GLint,T:?GLint,R:?GLint,Q:?GLint>>).
+%% @doc Set front and back stencil test actions
+%%
+%% Stenciling, like depth-buffering, enables and disables drawing on a per-pixel basis.
+%% You draw into the stencil planes using GL drawing primitives, then render geometry and
+%% images, using the stencil planes to mask out portions of the screen. Stenciling is typically
+%% used in multipass rendering algorithms to achieve special effects, such as decals, outlining,
+%% and constructive solid geometry rendering.
+%%
+%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
+%% between the value in the stencil buffer and a reference value. To enable and disable the
+%% test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
+%% ; to control it, call {@link gl:stencilFunc/3} or {@link gl:stencilFuncSeparate/4} .
+%%
+%% There can be two separate sets of `Sfail' , `Dpfail' , and `Dppass' parameters;
+%% one affects back-facing polygons, and the other affects front-facing polygons as well
+%% as other non-polygon primitives. {@link gl:stencilOp/3} sets both front and back stencil
+%% state to the same values. Use {@link gl:stencilOpSeparate/4} to set front and back stencil
+%% state to different values.
+%%
+%% ``gl:stencilOp'' takes three arguments that indicate what happens to the stored stencil
+%% value while stenciling is enabled. If the stencil test fails, no change is made to the
+%% pixel's color or depth buffers, and `Sfail' specifies what happens to the stencil
+%% buffer contents. The following eight actions are possible.
+%%
+%% `?GL_KEEP': Keeps the current value.
+%%
+%% `?GL_ZERO': Sets the stencil buffer value to 0.
+%%
+%% `?GL_REPLACE': Sets the stencil buffer value to `ref', as specified by {@link gl:stencilFunc/3}
+%% .
+%%
+%% `?GL_INCR': Increments the current stencil buffer value. Clamps to the maximum representable
+%% unsigned value.
+%%
+%% `?GL_INCR_WRAP': Increments the current stencil buffer value. Wraps stencil buffer
+%% value to zero when incrementing the maximum representable unsigned value.
+%%
+%% `?GL_DECR': Decrements the current stencil buffer value. Clamps to 0.
+%%
+%% `?GL_DECR_WRAP': Decrements the current stencil buffer value. Wraps stencil buffer
+%% value to the maximum representable unsigned value when decrementing a stencil buffer value
+%% of zero.
+%%
+%% `?GL_INVERT': Bitwise inverts the current stencil buffer value.
+%%
+%% Stencil buffer values are treated as unsigned integers. When incremented and decremented,
+%% values are clamped to 0 and 2 n-1, where n is the value returned by querying `?GL_STENCIL_BITS'
+%% .
+%%
+%% The other two arguments to ``gl:stencilOp'' specify stencil buffer actions that depend
+%% on whether subsequent depth buffer tests succeed ( `Dppass' ) or fail ( `Dpfail' )
+%% (see {@link gl:depthFunc/1} ). The actions are specified using the same eight symbolic constants
+%% as `Sfail' . Note that `Dpfail' is ignored when there is no depth buffer, or
+%% when the depth buffer is not enabled. In these cases, `Sfail' and `Dppass' specify
+%% stencil action when the stencil test fails and passes, respectively.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml">external</a> documentation.
+-spec stencilOp(Fail, Zfail, Zpass) -> ok when Fail :: enum(),Zfail :: enum(),Zpass :: enum().
+stencilOp(Fail,Zfail,Zpass) ->
+ cast(5241, <<Fail:?GLenum,Zfail:?GLenum,Zpass:?GLenum>>).
-%% @spec ({S,T,R,Q}) -> ok
-%% @equiv texCoord4i(S,T,R,Q)
--spec texCoord4iv({integer(),integer(),integer(),integer()}) -> ok.
-texCoord4iv({S,T,R,Q}) -> texCoord4i(S,T,R,Q).
+%% @doc Specify the clear value for the stencil buffer
+%%
+%% ``gl:clearStencil'' specifies the index used by {@link gl:clear/1} to clear the stencil
+%% buffer. `S' is masked with 2 m-1, where m is the number of bits in the stencil
+%% buffer.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearStencil.xml">external</a> documentation.
+-spec clearStencil(S) -> ok when S :: integer().
+clearStencil(S) ->
+ cast(5242, <<S:?GLint>>).
-%% @spec (S::integer(),T::integer(),R::integer(),Q::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
--spec texCoord4s(integer(),integer(),integer(),integer()) -> ok.
-texCoord4s(S,T,R,Q) ->
- cast(5273, <<S:?GLshort,T:?GLshort,R:?GLshort,Q:?GLshort>>).
+%% @doc Control the generation of texture coordinates
+%%
+%% ``gl:texGen'' selects a texture-coordinate generation function or supplies coefficients
+%% for one of the functions. `Coord' names one of the (`s', `t', `r', `q'
+%% ) texture coordinates; it must be one of the symbols `?GL_S', `?GL_T', `?GL_R'
+%% , or `?GL_Q'. `Pname' must be one of three symbolic constants: `?GL_TEXTURE_GEN_MODE'
+%% , `?GL_OBJECT_PLANE', or `?GL_EYE_PLANE'. If `Pname' is `?GL_TEXTURE_GEN_MODE'
+%% , then `Params' chooses a mode, one of `?GL_OBJECT_LINEAR', `?GL_EYE_LINEAR'
+%% , `?GL_SPHERE_MAP', `?GL_NORMAL_MAP', or `?GL_REFLECTION_MAP'. If `Pname'
+%% is either `?GL_OBJECT_PLANE' or `?GL_EYE_PLANE', `Params' contains coefficients
+%% for the corresponding texture generation function.
+%%
+%% If the texture generation function is `?GL_OBJECT_LINEAR', the function
+%%
+%% g= p 1*x o+p 2*y o+p 3*z o+p 4*w o
+%%
+%% is used, where g is the value computed for the coordinate named in `Coord' , p 1,
+%% p 2, p 3, and p 4 are the four values supplied in `Params' , and x o, y o, z o,
+%% and w o are the object coordinates of the vertex. This function can be used, for example,
+%% to texture-map terrain using sea level as a reference plane (defined by p 1, p 2, p
+%% 3, and p 4). The altitude of a terrain vertex is computed by the `?GL_OBJECT_LINEAR'
+%% coordinate generation function as its distance from sea level; that altitude can then
+%% be used to index the texture image to map white snow onto peaks and green grass onto foothills.
+%%
+%%
+%% If the texture generation function is `?GL_EYE_LINEAR', the function
+%%
+%% g=(p 1)"*x e+(p 2)"*y e+(p 3)"*z e+(p 4)"*w e
+%%
+%% is used, where
+%%
+%% ((p 1)" (p 2)" (p 3)" (p 4)")=(p 1 p 2 p 3 p 4) M -1
+%%
+%% and x e, y e, z e, and w e are the eye coordinates of the vertex, p 1, p 2, p 3,
+%% and p 4 are the values supplied in `Params' , and M is the modelview matrix when ``gl:texGen''
+%% is invoked. If M is poorly conditioned or singular, texture coordinates generated by
+%% the resulting function may be inaccurate or undefined.
+%%
+%% Note that the values in `Params' define a reference plane in eye coordinates. The
+%% modelview matrix that is applied to them may not be the same one in effect when the polygon
+%% vertices are transformed. This function establishes a field of texture coordinates that
+%% can produce dynamic contour lines on moving objects.
+%%
+%% If the texture generation function is `?GL_SPHERE_MAP' and `Coord' is either `?GL_S'
+%% or `?GL_T', s and t texture coordinates are generated as follows. Let `u'
+%% be the unit vector pointing from the origin to the polygon vertex (in eye coordinates).
+%% Let `n' sup prime be the current normal, after transformation to eye coordinates.
+%% Let
+%%
+%% f=(f x f y f z) T be the reflection vector such that
+%%
+%% f= u-2 n" (n") T u
+%%
+%% Finally, let m= 2 ((f x) 2+(f y) 2+(f z+1) 2). Then the values assigned to the s and t texture coordinates
+%% are
+%%
+%% s= f x/m+1/2
+%%
+%% t= f y/m+1/2
+%%
+%% To enable or disable a texture-coordinate generation function, call {@link gl:enable/1}
+%% or {@link gl:enable/1} with one of the symbolic texture-coordinate names (`?GL_TEXTURE_GEN_S'
+%% , `?GL_TEXTURE_GEN_T', `?GL_TEXTURE_GEN_R', or `?GL_TEXTURE_GEN_Q') as
+%% the argument. When enabled, the specified texture coordinate is computed according to
+%% the generating function associated with that coordinate. When disabled, subsequent vertices
+%% take the specified texture coordinate from the current set of texture coordinates. Initially,
+%% all texture generation functions are set to `?GL_EYE_LINEAR' and are disabled. Both
+%% s plane equations are (1, 0, 0, 0), both t plane equations are (0, 1, 0, 0), and all
+%% r and q plane equations are (0, 0, 0, 0).
+%%
+%% When the ARB_multitexture extension is supported, ``gl:texGen'' sets the texture generation
+%% parameters for the currently active texture unit, selected with {@link gl:activeTexture/1} .
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
+-spec texGend(Coord, Pname, Param) -> ok when Coord :: enum(),Pname :: enum(),Param :: float().
+texGend(Coord,Pname,Param) ->
+ cast(5243, <<Coord:?GLenum,Pname:?GLenum,Param:?GLdouble>>).
-%% @spec ({S,T,R,Q}) -> ok
-%% @equiv texCoord4s(S,T,R,Q)
--spec texCoord4sv({integer(),integer(),integer(),integer()}) -> ok.
-texCoord4sv({S,T,R,Q}) -> texCoord4s(S,T,R,Q).
+%% @doc
+%% See {@link texGend/3}
+-spec texGenf(Coord, Pname, Param) -> ok when Coord :: enum(),Pname :: enum(),Param :: float().
+texGenf(Coord,Pname,Param) ->
+ cast(5244, <<Coord:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
-%% @spec (Size::integer(),Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml">external</a> documentation.
--spec texCoordPointer(integer(),enum(),integer(),offset()|mem()) -> ok.
-texCoordPointer(Size,Type,Stride,Pointer) when is_integer(Pointer) ->
- cast(5274, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
-texCoordPointer(Size,Type,Stride,Pointer) ->
- send_bin(Pointer),
- cast(5275, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
+%% @doc
+%% See {@link texGend/3}
+-spec texGeni(Coord, Pname, Param) -> ok when Coord :: enum(),Pname :: enum(),Param :: integer().
+texGeni(Coord,Pname,Param) ->
+ cast(5245, <<Coord:?GLenum,Pname:?GLenum,Param:?GLint>>).
-%% @spec (Target::enum(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvf.xml">external</a> documentation.
--spec texEnvf(enum(),enum(),float()) -> ok.
-texEnvf(Target,Pname,Param) ->
- cast(5276, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
+%% @doc
+%% See {@link texGend/3}
+-spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}.
+texGendv(Coord,Pname,Params) ->
+ cast(5246, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,0:32,
+ (<< <<C:?GLdouble>> ||C <- tuple_to_list(Params)>>)/binary>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation.
--spec texEnvfv(enum(),enum(),{float()}) -> ok.
-texEnvfv(Target,Pname,Params) ->
- cast(5277, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+%% @doc
+%% See {@link texGend/3}
+-spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}.
+texGenfv(Coord,Pname,Params) ->
+ cast(5247, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target::enum(),Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvi.xml">external</a> documentation.
--spec texEnvi(enum(),enum(),integer()) -> ok.
+%% @doc
+%% See {@link texGend/3}
+-spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {integer()}.
+texGeniv(Coord,Pname,Params) ->
+ cast(5248, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+
+%% @doc Return texture coordinate generation parameters
+%%
+%% ``gl:getTexGen'' returns in `Params' selected parameters of a texture coordinate
+%% generation function that was specified using {@link gl:texGend/3} . `Coord' names one
+%% of the (`s', `t', `r', `q') texture coordinates, using the symbolic
+%% constant `?GL_S', `?GL_T', `?GL_R', or `?GL_Q'.
+%%
+%% `Pname' specifies one of three symbolic names:
+%%
+%% `?GL_TEXTURE_GEN_MODE': `Params' returns the single-valued texture generation
+%% function, a symbolic constant. The initial value is `?GL_EYE_LINEAR'.
+%%
+%% `?GL_OBJECT_PLANE': `Params' returns the four plane equation coefficients that
+%% specify object linear-coordinate generation. Integer values, when requested, are mapped
+%% directly from the internal floating-point representation.
+%%
+%% `?GL_EYE_PLANE': `Params' returns the four plane equation coefficients that
+%% specify eye linear-coordinate generation. Integer values, when requested, are mapped directly
+%% from the internal floating-point representation. The returned values are those maintained
+%% in eye coordinates. They are not equal to the values specified using {@link gl:texGend/3} ,
+%% unless the modelview matrix was identity when {@link gl:texGend/3} was called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml">external</a> documentation.
+-spec getTexGendv(Coord, Pname) -> {float(),float(),float(),float()} when Coord :: enum(),Pname :: enum().
+getTexGendv(Coord,Pname) ->
+ call(5249, <<Coord:?GLenum,Pname:?GLenum>>).
+
+%% @doc
+%% See {@link getTexGendv/2}
+-spec getTexGenfv(Coord, Pname) -> {float(),float(),float(),float()} when Coord :: enum(),Pname :: enum().
+getTexGenfv(Coord,Pname) ->
+ call(5250, <<Coord:?GLenum,Pname:?GLenum>>).
+
+%% @doc
+%% See {@link getTexGendv/2}
+-spec getTexGeniv(Coord, Pname) -> {integer(),integer(),integer(),integer()} when Coord :: enum(),Pname :: enum().
+getTexGeniv(Coord,Pname) ->
+ call(5251, <<Coord:?GLenum,Pname:?GLenum>>).
+
+%% @doc glTexEnvf
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvf.xml">external</a> documentation.
+-spec texEnvf(Target, Pname, Param) -> ok when Target :: enum(),Pname :: enum(),Param :: float().
+texEnvf(Target,Pname,Param) ->
+ cast(5252, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
+
+%% @doc glTexEnvi
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvi.xml">external</a> documentation.
+-spec texEnvi(Target, Pname, Param) -> ok when Target :: enum(),Pname :: enum(),Param :: integer().
texEnvi(Target,Pname,Param) ->
- cast(5278, <<Target:?GLenum,Pname:?GLenum,Param:?GLint>>).
+ cast(5253, <<Target:?GLenum,Pname:?GLenum,Param:?GLint>>).
+
+%% @doc Set texture environment parameters
+%%
+%% A texture environment specifies how texture values are interpreted when a fragment is
+%% textured. When `Target' is `?GL_TEXTURE_FILTER_CONTROL', `Pname' must be `?GL_TEXTURE_LOD_BIAS'
+%% . When `Target' is `?GL_TEXTURE_ENV', `Pname' can be `?GL_TEXTURE_ENV_MODE'
+%% , `?GL_TEXTURE_ENV_COLOR', `?GL_COMBINE_RGB', `?GL_COMBINE_ALPHA', `?GL_RGB_SCALE'
+%% , `?GL_ALPHA_SCALE', `?GL_SRC0_RGB', `?GL_SRC1_RGB', `?GL_SRC2_RGB', `?GL_SRC0_ALPHA'
+%% , `?GL_SRC1_ALPHA', or `?GL_SRC2_ALPHA'.
+%%
+%% If `Pname' is `?GL_TEXTURE_ENV_MODE', then `Params' is (or points to)
+%% the symbolic name of a texture function. Six texture functions may be specified: `?GL_ADD'
+%% , `?GL_MODULATE', `?GL_DECAL', `?GL_BLEND', `?GL_REPLACE', or `?GL_COMBINE'
+%% .
+%%
+%% The following table shows the correspondence of filtered texture values R t, G t, B t,
+%% A t, L t, I t to texture source components. C s and A s are used by the texture functions
+%% described below.
+%%
+%% <table><tbody><tr><td> Texture Base Internal Format </td><td> C s</td><td> A s</td></tr></tbody>
+%% <tbody><tr><td>`?GL_ALPHA'</td><td> (0, 0, 0) </td><td> A t</td></tr><tr><td>`?GL_LUMINANCE'
+%% </td><td> ( L t, L t, L t ) </td><td> 1 </td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td>
+%% <td> ( L t, L t, L t ) </td><td> A t</td></tr><tr><td>`?GL_INTENSITY'</td><td> (
+%% I t, I t, I t ) </td><td> I t</td></tr><tr><td>`?GL_RGB'</td><td> ( R t, G t, B
+%% t ) </td><td> 1 </td></tr><tr><td>`?GL_RGBA'</td><td> ( R t, G t, B t ) </td><td>
+%% A t</td></tr></tbody></table>
+%%
+%% A texture function acts on the fragment to be textured using the texture image value
+%% that applies to the fragment (see {@link gl:texParameterf/3} ) and produces an RGBA color
+%% for that fragment. The following table shows how the RGBA color is produced for each of
+%% the first five texture functions that can be chosen. C is a triple of color values (RGB)
+%% and A is the associated alpha value. RGBA values extracted from a texture image are in
+%% the range [0,1]. The subscript p refers to the color computed from the previous texture
+%% stage (or the incoming fragment if processing texture stage 0), the subscript s to the
+%% texture source color, the subscript c to the texture environment color, and the subscript
+%% v indicates a value produced by the texture function.
+%%
+%% <table><tbody><tr><td> Texture Base Internal Format </td><td>`?Value'</td><td>`?GL_REPLACE'
+%% Function </td><td>`?GL_MODULATE' Function </td><td>`?GL_DECAL' Function </td><td>
+%% `?GL_BLEND' Function </td><td>`?GL_ADD' Function </td></tr></tbody><tbody><tr><td>
+%% `?GL_ALPHA'</td><td> C v=</td><td> C p</td><td> C p</td><td> undefined </td><td> C p</td>
+%% <td> C p</td></tr><tr><td></td><td> A v=</td><td> A s</td><td> A p A s</td><td></td><td>
+%% A v= A p A s</td><td> A p A s</td></tr><tr><td>`?GL_LUMINANCE'</td><td> C v=</td><td>
+%% C s</td><td> C p C s</td><td> undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr>
+%% <tr><td> (or 1) </td><td> A v=</td><td> A p</td><td> A p</td><td></td><td> A p</td><td> A
+%% p</td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td> C v=</td><td> C s</td><td> C p C
+%% s</td><td> undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td> (or 2) </td>
+%% <td> A v=</td><td> A s</td><td> A p A s</td><td></td><td> A p A s</td><td> A p A s</td>
+%% </tr><tr><td>`?GL_INTENSITY'</td><td> C v=</td><td> C s</td><td> C p C s</td><td>
+%% undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td></td><td> A v=</td><td>
+%% A s</td><td> A p A s</td><td></td><td> A p (1-A s)+A c A s</td><td> A p+A s</td></tr><tr><td>`?GL_RGB'
+%% </td><td> C v=</td><td> C s</td><td> C p C s</td><td> C s</td><td> C p (1-C s)+C c C s</td><td>
+%% C p+C s</td></tr><tr><td> (or 3) </td><td> A v=</td><td> A p</td><td> A p</td><td> A p</td>
+%% <td> A p</td><td> A p</td></tr><tr><td>`?GL_RGBA'</td><td> C v=</td><td> C s</td><td>
+%% C p C s</td><td> C p (1-A s)+C s A s</td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td>
+%% (or 4) </td><td> A v=</td><td> A s</td><td> A p A s</td><td> A p</td><td> A p A s</td><td>
+%% A p A s</td></tr></tbody></table>
+%%
+%% If `Pname' is `?GL_TEXTURE_ENV_MODE', and `Params' is `?GL_COMBINE',
+%% the form of the texture function depends on the values of `?GL_COMBINE_RGB' and `?GL_COMBINE_ALPHA'
+%% .
+%%
+%% The following describes how the texture sources, as specified by `?GL_SRC0_RGB', `?GL_SRC1_RGB'
+%% , `?GL_SRC2_RGB', `?GL_SRC0_ALPHA', `?GL_SRC1_ALPHA', and `?GL_SRC2_ALPHA'
+%% , are combined to produce a final texture color. In the following tables, `?GL_SRC0_c'
+%% is represented by Arg0, `?GL_SRC1_c' is represented by Arg1, and `?GL_SRC2_c'
+%% is represented by Arg2.
+%%
+%% `?GL_COMBINE_RGB' accepts any of `?GL_REPLACE', `?GL_MODULATE', `?GL_ADD'
+%% , `?GL_ADD_SIGNED', `?GL_INTERPOLATE', `?GL_SUBTRACT', `?GL_DOT3_RGB',
+%% or `?GL_DOT3_RGBA'.
+%%
+%% <table><tbody><tr><td>`?GL_COMBINE_RGB'</td><td>` Texture Function '</td></tr></tbody>
+%% <tbody><tr><td>`?GL_REPLACE'</td><td> Arg0</td></tr><tr><td>`?GL_MODULATE'</td><td>
+%% Arg0*Arg1</td></tr><tr><td>`?GL_ADD'</td><td> Arg0+Arg1</td></tr><tr><td>`?GL_ADD_SIGNED'
+%% </td><td> Arg0+Arg1-0.5</td></tr><tr><td>`?GL_INTERPOLATE'</td><td> Arg0*Arg2+Arg1*(1-
+%% Arg2)</td>
+%% </tr><tr><td>`?GL_SUBTRACT'</td><td> Arg0-Arg1</td></tr><tr><td>`?GL_DOT3_RGB'
+%% or `?GL_DOT3_RGBA'</td><td> 4*((((Arg0 r)-0.5)*((Arg1 r)-0.5))+(((Arg0 g)-0.5)*((Arg1 g)-0.5))+(((Arg0 b)-0.5)*((Arg1 b)-0.5)))</td></tr></tbody></table>
+%%
+%% The scalar results for `?GL_DOT3_RGB' and `?GL_DOT3_RGBA' are placed into each
+%% of the 3 (RGB) or 4 (RGBA) components on output.
+%%
+%% Likewise, `?GL_COMBINE_ALPHA' accepts any of `?GL_REPLACE', `?GL_MODULATE',
+%% `?GL_ADD', `?GL_ADD_SIGNED', `?GL_INTERPOLATE', or `?GL_SUBTRACT'.
+%% The following table describes how alpha values are combined:
+%%
+%% <table><tbody><tr><td>`?GL_COMBINE_ALPHA'</td><td>` Texture Function '</td></tr>
+%% </tbody><tbody><tr><td>`?GL_REPLACE'</td><td> Arg0</td></tr><tr><td>`?GL_MODULATE'
+%% </td><td> Arg0*Arg1</td></tr><tr><td>`?GL_ADD'</td><td> Arg0+Arg1</td></tr><tr><td>`?GL_ADD_SIGNED'
+%% </td><td> Arg0+Arg1-0.5</td></tr><tr><td>`?GL_INTERPOLATE'</td><td> Arg0*Arg2+Arg1*(1-
+%% Arg2)</td>
+%% </tr><tr><td>`?GL_SUBTRACT'</td><td> Arg0-Arg1</td></tr></tbody></table>
+%%
+%% In the following tables, the value C s represents the color sampled from the currently
+%% bound texture, C c represents the constant texture-environment color, C f represents
+%% the primary color of the incoming fragment, and C p represents the color computed from
+%% the previous texture stage or C f if processing texture stage 0. Likewise, A s, A c,
+%% A f, and A p represent the respective alpha values.
+%%
+%% The following table describes the values assigned to Arg0, Arg1, and Arg2 based upon
+%% the RGB sources and operands:
+%%
+%% <table><tbody><tr><td>`?GL_SRCn_RGB'</td><td>`?GL_OPERANDn_RGB'</td><td>` Argument Value '
+%% </td></tr></tbody><tbody><tr><td>`?GL_TEXTURE'</td><td>`?GL_SRC_COLOR'</td><td>(C
+%% s)</td>
+%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C s)</td></tr><tr><td></td><td>
+%% `?GL_SRC_ALPHA'</td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td>
+%% <td> 1-(A s)</td></tr><tr><td>`?GL_TEXTUREn'</td><td>`?GL_SRC_COLOR'</td><td>(C s)</td></tr>
+%% <tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C s)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'
+%% </td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A s)</td></tr><tr>
+%% <td>`?GL_CONSTANT'</td><td>`?GL_SRC_COLOR'</td><td>(C c)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'
+%% </td><td> 1-(C c)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'</td><td>(A c)</td></tr><tr><td></td>
+%% <td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A c)</td></tr><tr><td>`?GL_PRIMARY_COLOR'</td>
+%% <td>`?GL_SRC_COLOR'</td><td>(C f)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td>
+%% <td> 1-(C f)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'</td><td>(A f)</td></tr><tr><td></td><td>
+%% `?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A f)</td></tr><tr><td>`?GL_PREVIOUS'</td><td>`?GL_SRC_COLOR'
+%% </td><td>(C p)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C p)</td></tr><tr>
+%% <td></td><td>`?GL_SRC_ALPHA'</td><td>(A p)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'
+%% </td><td> 1-(A p)</td></tr></tbody></table>
+%%
+%% For `?GL_TEXTUREn' sources, C s and A s represent the color and alpha, respectively,
+%% produced from texture stage n.
+%%
+%% The follow table describes the values assigned to Arg0, Arg1, and Arg2 based upon
+%% the alpha sources and operands:
+%%
+%% <table><tbody><tr><td>`?GL_SRCn_ALPHA'</td><td>`?GL_OPERANDn_ALPHA'</td><td>` Argument Value '
+%% </td></tr></tbody><tbody><tr><td>`?GL_TEXTURE'</td><td>`?GL_SRC_ALPHA'</td><td>(A
+%% s)</td>
+%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A s)</td></tr><tr><td>`?GL_TEXTUREn'
+%% </td><td>`?GL_SRC_ALPHA'</td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'
+%% </td><td> 1-(A s)</td></tr><tr><td>`?GL_CONSTANT'</td><td>`?GL_SRC_ALPHA'</td><td>(A
+%% c)</td>
+%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A c)</td></tr><tr><td>`?GL_PRIMARY_COLOR'
+%% </td><td>`?GL_SRC_ALPHA'</td><td>(A f)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'
+%% </td><td> 1-(A f)</td></tr><tr><td>`?GL_PREVIOUS'</td><td>`?GL_SRC_ALPHA'</td><td>(A
+%% p)</td>
+%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A p)</td></tr></tbody></table>
+%%
+%%
+%% The RGB and alpha results of the texture function are multipled by the values of `?GL_RGB_SCALE'
+%% and `?GL_ALPHA_SCALE', respectively, and clamped to the range [0 1].
+%%
+%% If `Pname' is `?GL_TEXTURE_ENV_COLOR', `Params' is a pointer to an array
+%% that holds an RGBA color consisting of four values. Integer color components are interpreted
+%% linearly such that the most positive integer maps to 1.0, and the most negative integer
+%% maps to -1.0. The values are clamped to the range [0,1] when they are specified. C c
+%% takes these four values.
+%%
+%% If `Pname' is `?GL_TEXTURE_LOD_BIAS', the value specified is added to the texture
+%% level-of-detail parameter, that selects which mipmap, or mipmaps depending upon the selected
+%% `?GL_TEXTURE_MIN_FILTER', will be sampled.
+%%
+%% `?GL_TEXTURE_ENV_MODE' defaults to `?GL_MODULATE' and `?GL_TEXTURE_ENV_COLOR'
+%% defaults to (0, 0, 0, 0).
+%%
+%% If `Target' is `?GL_POINT_SPRITE' and `Pname' is `?GL_COORD_REPLACE',
+%% the boolean value specified is used to either enable or disable point sprite texture coordinate
+%% replacement. The default value is `?GL_FALSE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation.
+-spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}.
+texEnvfv(Target,Pname,Params) ->
+ cast(5254, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation.
--spec texEnviv(enum(),enum(),{integer()}) -> ok.
+%% @doc
+%% See {@link texEnvfv/3}
+-spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
texEnviv(Target,Pname,Params) ->
- cast(5279, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ cast(5255, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Coord::enum(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
--spec texGend(enum(),enum(),float()) -> ok.
-texGend(Coord,Pname,Param) ->
- cast(5280, <<Coord:?GLenum,Pname:?GLenum,Param:?GLdouble>>).
+%% @doc Return texture environment parameters
+%%
+%% ``gl:getTexEnv'' returns in `Params' selected values of a texture environment that
+%% was specified with {@link gl:texEnvfv/3} . `Target' specifies a texture environment.
+%%
+%% When `Target' is `?GL_TEXTURE_FILTER_CONTROL', `Pname' must be `?GL_TEXTURE_LOD_BIAS'
+%% . When `Target' is `?GL_POINT_SPRITE', `Pname' must be `?GL_COORD_REPLACE'
+%% . When `Target' is `?GL_TEXTURE_ENV', `Pname' can be `?GL_TEXTURE_ENV_MODE'
+%% , `?GL_TEXTURE_ENV_COLOR', `?GL_COMBINE_RGB', `?GL_COMBINE_ALPHA', `?GL_RGB_SCALE'
+%% , `?GL_ALPHA_SCALE', `?GL_SRC0_RGB', `?GL_SRC1_RGB', `?GL_SRC2_RGB',
+%% `?GL_SRC0_ALPHA', `?GL_SRC1_ALPHA', or `?GL_SRC2_ALPHA'.
+%%
+%% `Pname' names a specific texture environment parameter, as follows:
+%%
+%% `?GL_TEXTURE_ENV_MODE': `Params' returns the single-valued texture environment
+%% mode, a symbolic constant. The initial value is `?GL_MODULATE'.
+%%
+%% `?GL_TEXTURE_ENV_COLOR': `Params' returns four integer or floating-point values
+%% that are the texture environment color. Integer values, when requested, are linearly mapped
+%% from the internal floating-point representation such that 1.0 maps to the most positive
+%% representable integer, and -1.0 maps to the most negative representable integer. The
+%% initial value is (0, 0, 0, 0).
+%%
+%% `?GL_TEXTURE_LOD_BIAS': `Params' returns a single floating-point value that
+%% is the texture level-of-detail bias. The initial value is 0.
+%%
+%% `?GL_COMBINE_RGB': `Params' returns a single symbolic constant value representing
+%% the current RGB combine mode. The initial value is `?GL_MODULATE'.
+%%
+%% `?GL_COMBINE_ALPHA': `Params' returns a single symbolic constant value representing
+%% the current alpha combine mode. The initial value is `?GL_MODULATE'.
+%%
+%% `?GL_SRC0_RGB': `Params' returns a single symbolic constant value representing
+%% the texture combiner zero's RGB source. The initial value is `?GL_TEXTURE'.
+%%
+%% `?GL_SRC1_RGB': `Params' returns a single symbolic constant value representing
+%% the texture combiner one's RGB source. The initial value is `?GL_PREVIOUS'.
+%%
+%% `?GL_SRC2_RGB': `Params' returns a single symbolic constant value representing
+%% the texture combiner two's RGB source. The initial value is `?GL_CONSTANT'.
+%%
+%% `?GL_SRC0_ALPHA': `Params' returns a single symbolic constant value representing
+%% the texture combiner zero's alpha source. The initial value is `?GL_TEXTURE'.
+%%
+%% `?GL_SRC1_ALPHA': `Params' returns a single symbolic constant value representing
+%% the texture combiner one's alpha source. The initial value is `?GL_PREVIOUS'.
+%%
+%% `?GL_SRC2_ALPHA': `Params' returns a single symbolic constant value representing
+%% the texture combiner two's alpha source. The initial value is `?GL_CONSTANT'.
+%%
+%% `?GL_OPERAND0_RGB': `Params' returns a single symbolic constant value representing
+%% the texture combiner zero's RGB operand. The initial value is `?GL_SRC_COLOR'.
+%%
+%% `?GL_OPERAND1_RGB': `Params' returns a single symbolic constant value representing
+%% the texture combiner one's RGB operand. The initial value is `?GL_SRC_COLOR'.
+%%
+%% `?GL_OPERAND2_RGB': `Params' returns a single symbolic constant value representing
+%% the texture combiner two's RGB operand. The initial value is `?GL_SRC_ALPHA'.
+%%
+%% `?GL_OPERAND0_ALPHA': `Params' returns a single symbolic constant value representing
+%% the texture combiner zero's alpha operand. The initial value is `?GL_SRC_ALPHA'.
+%%
+%% `?GL_OPERAND1_ALPHA': `Params' returns a single symbolic constant value representing
+%% the texture combiner one's alpha operand. The initial value is `?GL_SRC_ALPHA'.
+%%
+%% `?GL_OPERAND2_ALPHA': `Params' returns a single symbolic constant value representing
+%% the texture combiner two's alpha operand. The initial value is `?GL_SRC_ALPHA'.
+%%
+%% `?GL_RGB_SCALE': `Params' returns a single floating-point value representing
+%% the current RGB texture combiner scaling factor. The initial value is 1.0.
+%%
+%% `?GL_ALPHA_SCALE': `Params' returns a single floating-point value representing
+%% the current alpha texture combiner scaling factor. The initial value is 1.0.
+%%
+%% `?GL_COORD_REPLACE': `Params' returns a single boolean value representing the
+%% current point sprite texture coordinate replacement enable state. The initial value is `?GL_FALSE'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml">external</a> documentation.
+-spec getTexEnvfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
+getTexEnvfv(Target,Pname) ->
+ call(5256, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Coord::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
--spec texGendv(enum(),enum(),{float()}) -> ok.
-texGendv(Coord,Pname,Params) ->
- cast(5281, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,0:32,
- (<< <<C:?GLdouble>> ||C <- tuple_to_list(Params)>>)/binary>>).
+%% @doc
+%% See {@link getTexEnvfv/2}
+-spec getTexEnviv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
+getTexEnviv(Target,Pname) ->
+ call(5257, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Coord::enum(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
--spec texGenf(enum(),enum(),float()) -> ok.
-texGenf(Coord,Pname,Param) ->
- cast(5282, <<Coord:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
+%% @doc Set texture parameters
+%%
+%% ``gl:texParameter'' assigns the value or values in `Params' to the texture parameter
+%% specified as `Pname' . `Target' defines the target texture, either `?GL_TEXTURE_1D'
+%% , `?GL_TEXTURE_2D', `?GL_TEXTURE_1D_ARRAY', `?GL_TEXTURE_2D_ARRAY', `?GL_TEXTURE_RECTANGLE'
+%% , or `?GL_TEXTURE_3D'. The following symbols are accepted in `Pname' :
+%%
+%% `?GL_TEXTURE_BASE_LEVEL': Specifies the index of the lowest defined mipmap level.
+%% This is an integer value. The initial value is 0.
+%%
+%%
+%%
+%% `?GL_TEXTURE_BORDER_COLOR': The data in `Params' specifies four values that
+%% define the border values that should be used for border texels. If a texel is sampled
+%% from the border of the texture, the values of `?GL_TEXTURE_BORDER_COLOR' are interpreted
+%% as an RGBA color to match the texture's internal format and substituted for the non-existent
+%% texel data. If the texture contains depth components, the first component of `?GL_TEXTURE_BORDER_COLOR'
+%% is interpreted as a depth value. The initial value is ( 0.0, 0.0, 0.0, 0.0 ).
+%%
+%% If the values for `?GL_TEXTURE_BORDER_COLOR' are specified with ``gl:texParameterIiv''
+%% or ``gl:texParameterIuiv'', the values are stored unmodified with an internal data
+%% type of integer. If specified with ``gl:texParameteriv'', they are converted to floating
+%% point with the following equation: f= 2 c+1 2 b-/1. If specified with ``gl:texParameterfv''
+%% , they are stored unmodified as floating-point values.
+%%
+%% `?GL_TEXTURE_COMPARE_FUNC': Specifies the comparison operator used when `?GL_TEXTURE_COMPARE_MODE'
+%% is set to `?GL_COMPARE_REF_TO_TEXTURE'. Permissible values are: <table><tbody><tr><td>
+%% ` Texture Comparison Function '</td><td>` Computed result '</td></tr></tbody><tbody>
+%% <tr><td>`?GL_LEQUAL'</td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&lt;=(D t) r&gt;(D t))</td></tr><tr><td>`?GL_GEQUAL'</td><td>
+%% result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&gt;=(D t) r&lt;(D t))</td></tr><tr><td>`?GL_LESS'</td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&lt;
+%% (D t) r&gt;=(D t))</td></tr><tr><td>`?GL_GREATER'
+%% </td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&gt;(D t) r&lt;=(D t))</td></tr><tr><td>`?GL_EQUAL'</td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp;
+%% r=(D t) r&amp;ne;(D t))</td></tr><tr><td>`?GL_NOTEQUAL'
+%% </td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&amp;ne;(D t) r=(D t))</td></tr><tr><td>`?GL_ALWAYS'</td><td> result= 1.0</td></tr><tr><td>
+%% `?GL_NEVER'</td><td> result= 0.0</td></tr></tbody></table> where r is the current
+%% interpolated texture coordinate, and D t is the depth texture value sampled from the
+%% currently bound depth texture. result is assigned to the the red channel.
+%%
+%% `?GL_TEXTURE_COMPARE_MODE': Specifies the texture comparison mode for currently
+%% bound depth textures. That is, a texture whose internal format is `?GL_DEPTH_COMPONENT_*'
+%% ; see {@link gl:texImage2D/9} ) Permissible values are:
+%%
+%% `?GL_COMPARE_REF_TO_TEXTURE': Specifies that the interpolated and clamped r texture
+%% coordinate should be compared to the value in the currently bound depth texture. See the
+%% discussion of `?GL_TEXTURE_COMPARE_FUNC' for details of how the comparison is evaluated.
+%% The result of the comparison is assigned to the red channel.
+%%
+%% `?GL_NONE': Specifies that the red channel should be assigned the appropriate value
+%% from the currently bound depth texture.
+%%
+%% `?GL_TEXTURE_LOD_BIAS': `Params' specifies a fixed bias value that is to be
+%% added to the level-of-detail parameter for the texture before texture sampling. The specified
+%% value is added to the shader-supplied bias value (if any) and subsequently clamped into
+%% the implementation-defined range [( - bias max)(bias max)], where bias max is the value of the implementation
+%% defined constant `?GL_MAX_TEXTURE_LOD_BIAS'. The initial value is 0.0.
+%%
+%% `?GL_TEXTURE_MIN_FILTER': The texture minifying function is used whenever the level-of-detail
+%% function used when sampling from the texture determines that the texture should be minified.
+%% There are six defined minifying functions. Two of them use either the nearest texture
+%% elements or a weighted average of multiple texture elements to compute the texture value.
+%% The other four use mipmaps.
+%%
+%% A mipmap is an ordered set of arrays representing the same image at progressively lower
+%% resolutions. If the texture has dimensions 2 n*2 m, there are max(n m)+1 mipmaps. The first
+%% mipmap is the original texture, with dimensions 2 n*2 m. Each subsequent mipmap has
+%% dimensions 2(k-1)*2(l-1), where 2 k*2 l are the dimensions of the previous mipmap, until either
+%% k= 0 or l= 0. At that point, subsequent mipmaps have dimension 1*2(l-1) or 2(k-1)*1 until
+%% the final mipmap, which has dimension 1*1. To define the mipmaps, call {@link gl:texImage1D/8}
+%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:copyTexImage1D/7} , or {@link gl:copyTexImage2D/8}
+%% with the `level' argument indicating the order of the mipmaps. Level 0 is the original
+%% texture; level max(n m) is the final 1*1 mipmap.
+%%
+%% `Params' supplies a function for minifying the texture as one of the following:
+%%
+%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
+%% distance) to the specified texture coordinates.
+%%
+%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are
+%% closest to the specified texture coordinates. These can include items wrapped or repeated
+%% from other parts of a texture, depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T'
+%% , and on the exact mapping.
+%%
+%% `?GL_NEAREST_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
+%% of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture element
+%% closest to the specified texture coordinates) to produce a texture value.
+%%
+%% `?GL_LINEAR_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
+%% of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted average
+%% of the four texture elements that are closest to the specified texture coordinates) to
+%% produce a texture value.
+%%
+%% `?GL_NEAREST_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
+%% size of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture
+%% element closest to the specified texture coordinates ) to produce a texture value from
+%% each mipmap. The final texture value is a weighted average of those two values.
+%%
+%% `?GL_LINEAR_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
+%% size of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted
+%% average of the texture elements that are closest to the specified texture coordinates)
+%% to produce a texture value from each mipmap. The final texture value is a weighted average
+%% of those two values.
+%%
+%% As more texture elements are sampled in the minification process, fewer aliasing artifacts
+%% will be apparent. While the `?GL_NEAREST' and `?GL_LINEAR' minification functions
+%% can be faster than the other four, they sample only one or multiple texture elements to
+%% determine the texture value of the pixel being rendered and can produce moire patterns
+%% or ragged transitions. The initial value of `?GL_TEXTURE_MIN_FILTER' is `?GL_NEAREST_MIPMAP_LINEAR'
+%% .
+%%
+%%
+%%
+%% `?GL_TEXTURE_MAG_FILTER': The texture magnification function is used whenever the
+%% level-of-detail function used when sampling from the texture determines that the texture
+%% should be magified. It sets the texture magnification function to either `?GL_NEAREST'
+%% or `?GL_LINEAR' (see below). `?GL_NEAREST' is generally faster than `?GL_LINEAR'
+%% , but it can produce textured images with sharper edges because the transition between
+%% texture elements is not as smooth. The initial value of `?GL_TEXTURE_MAG_FILTER' is `?GL_LINEAR'
+%% .
+%%
+%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
+%% distance) to the specified texture coordinates.
+%%
+%% `?GL_LINEAR': Returns the weighted average of the texture elements that are closest
+%% to the specified texture coordinates. These can include items wrapped or repeated from
+%% other parts of a texture, depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T'
+%% , and on the exact mapping.
+%%
+%%
+%%
+%% `?GL_TEXTURE_MIN_LOD': Sets the minimum level-of-detail parameter. This floating-point
+%% value limits the selection of highest resolution mipmap (lowest mipmap level). The initial
+%% value is -1000.
+%%
+%%
+%%
+%% `?GL_TEXTURE_MAX_LOD': Sets the maximum level-of-detail parameter. This floating-point
+%% value limits the selection of the lowest resolution mipmap (highest mipmap level). The
+%% initial value is 1000.
+%%
+%%
+%%
+%% `?GL_TEXTURE_MAX_LEVEL': Sets the index of the highest defined mipmap level. This
+%% is an integer value. The initial value is 1000.
+%%
+%%
+%%
+%% `?GL_TEXTURE_SWIZZLE_R': Sets the swizzle that will be applied to the r component
+%% of a texel before it is returned to the shader. Valid values for `Param' are `?GL_RED'
+%% , `?GL_GREEN', `?GL_BLUE', `?GL_ALPHA', `?GL_ZERO' and `?GL_ONE'.
+%% If `?GL_TEXTURE_SWIZZLE_R' is `?GL_RED', the value for r will be taken from
+%% the first channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_GREEN'
+%% , the value for r will be taken from the second channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R'
+%% is `?GL_BLUE', the value for r will be taken from the third channel of the fetched
+%% texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ALPHA', the value for r will be taken
+%% from the fourth channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ZERO'
+%% , the value for r will be subtituted with 0.0. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ONE'
+%% , the value for r will be subtituted with 1.0. The initial value is `?GL_RED'.
+%%
+%%
+%%
+%% `?GL_TEXTURE_SWIZZLE_G': Sets the swizzle that will be applied to the g component
+%% of a texel before it is returned to the shader. Valid values for `Param' and their
+%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_GREEN'
+%% .
+%%
+%%
+%%
+%% `?GL_TEXTURE_SWIZZLE_B': Sets the swizzle that will be applied to the b component
+%% of a texel before it is returned to the shader. Valid values for `Param' and their
+%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_BLUE'
+%% .
+%%
+%%
+%%
+%% `?GL_TEXTURE_SWIZZLE_A': Sets the swizzle that will be applied to the a component
+%% of a texel before it is returned to the shader. Valid values for `Param' and their
+%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_ALPHA'
+%% .
+%%
+%%
+%%
+%% `?GL_TEXTURE_SWIZZLE_RGBA': Sets the swizzles that will be applied to the r, g,
+%% b, and a components of a texel before they are returned to the shader. Valid values for `Params'
+%% and their effects are similar to those of `?GL_TEXTURE_SWIZZLE_R', except that all
+%% channels are specified simultaneously. Setting the value of `?GL_TEXTURE_SWIZZLE_RGBA'
+%% is equivalent (assuming no errors are generated) to setting the parameters of each of `?GL_TEXTURE_SWIZZLE_R'
+%% , `?GL_TEXTURE_SWIZZLE_G', `?GL_TEXTURE_SWIZZLE_B', and `?GL_TEXTURE_SWIZZLE_A'
+%% successively.
+%%
+%%
+%%
+%% `?GL_TEXTURE_WRAP_S': Sets the wrap parameter for texture coordinate s to either `?GL_CLAMP_TO_EDGE'
+%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. `?GL_CLAMP_TO_EDGE'
+%% causes s coordinates to be clamped to the range [(1 2/N) 1-(1 2/N)], where N is the size of the texture
+%% in the direction of clamping. `?GL_CLAMP_TO_BORDER' evaluates s coordinates in a
+%% similar manner to `?GL_CLAMP_TO_EDGE'. However, in cases where clamping would have
+%% occurred in `?GL_CLAMP_TO_EDGE' mode, the fetched texel data is substituted with
+%% the values specified by `?GL_TEXTURE_BORDER_COLOR'. `?GL_REPEAT' causes the
+%% integer part of the s coordinate to be ignored; the GL uses only the fractional part,
+%% thereby creating a repeating pattern. `?GL_MIRRORED_REPEAT' causes the s coordinate
+%% to be set to the fractional part of the texture coordinate if the integer part of s
+%% is even; if the integer part of s is odd, then the s texture coordinate is set to 1-
+%% frac(s), where frac(s) represents the fractional part of s. Initially, `?GL_TEXTURE_WRAP_S'
+%% is set to `?GL_REPEAT'.
+%%
+%%
+%%
+%% `?GL_TEXTURE_WRAP_T': Sets the wrap parameter for texture coordinate t to either `?GL_CLAMP_TO_EDGE'
+%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the
+%% discussion under `?GL_TEXTURE_WRAP_S'. Initially, `?GL_TEXTURE_WRAP_T' is set
+%% to `?GL_REPEAT'.
+%%
+%%
+%%
+%% `?GL_TEXTURE_WRAP_R': Sets the wrap parameter for texture coordinate r to either `?GL_CLAMP_TO_EDGE'
+%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the
+%% discussion under `?GL_TEXTURE_WRAP_S'. Initially, `?GL_TEXTURE_WRAP_R' is set
+%% to `?GL_REPEAT'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation.
+-spec texParameterf(Target, Pname, Param) -> ok when Target :: enum(),Pname :: enum(),Param :: float().
+texParameterf(Target,Pname,Param) ->
+ cast(5258, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
-%% @spec (Coord::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
--spec texGenfv(enum(),enum(),{float()}) -> ok.
-texGenfv(Coord,Pname,Params) ->
- cast(5283, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @doc
+%% See {@link texParameterf/3}
+-spec texParameteri(Target, Pname, Param) -> ok when Target :: enum(),Pname :: enum(),Param :: integer().
+texParameteri(Target,Pname,Param) ->
+ cast(5259, <<Target:?GLenum,Pname:?GLenum,Param:?GLint>>).
-%% @spec (Coord::enum(),Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
--spec texGeni(enum(),enum(),integer()) -> ok.
-texGeni(Coord,Pname,Param) ->
- cast(5284, <<Coord:?GLenum,Pname:?GLenum,Param:?GLint>>).
+%% @doc
+%% See {@link texParameterf/3}
+-spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}.
+texParameterfv(Target,Pname,Params) ->
+ cast(5260, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Coord::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
--spec texGeniv(enum(),enum(),{integer()}) -> ok.
-texGeniv(Coord,Pname,Params) ->
- cast(5285, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
+%% @doc
+%% See {@link texParameterf/3}
+-spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
+texParameteriv(Target,Pname,Params) ->
+ cast(5261, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target::enum(),Level::integer(),Internalformat::integer(),Width::integer(),Border::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml">external</a> documentation.
--spec texImage1D(enum(),integer(),integer(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
-texImage1D(Target,Level,Internalformat,Width,Border,Format,Type,Pixels) when is_integer(Pixels) ->
- cast(5286, <<Target:?GLenum,Level:?GLint,Internalformat:?GLint,Width:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
-texImage1D(Target,Level,Internalformat,Width,Border,Format,Type,Pixels) ->
+%% @doc Return texture parameter values
+%%
+%% ``gl:getTexParameter'' returns in `Params' the value or values of the texture parameter
+%% specified as `Pname' . `Target' defines the target texture. `?GL_TEXTURE_1D',
+%% `?GL_TEXTURE_2D', `?GL_TEXTURE_3D', `?GL_TEXTURE_1D_ARRAY', `?GL_TEXTURE_2D_ARRAY'
+%% , `?GL_TEXTURE_RECTANGLE', `?GL_TEXTURE_CUBE_MAP', `?GL_TEXTURE_CUBE_MAP_ARRAY'
+%% specify one-, two-, or three-dimensional, one-dimensional array, two-dimensional array,
+%% rectangle, cube-mapped or cube-mapped array texturing, respectively. `Pname' accepts
+%% the same symbols as {@link gl:texParameterf/3} , with the same interpretations:
+%%
+%% `?GL_TEXTURE_MAG_FILTER': Returns the single-valued texture magnification filter,
+%% a symbolic constant. The initial value is `?GL_LINEAR'.
+%%
+%% `?GL_TEXTURE_MIN_FILTER': Returns the single-valued texture minification filter,
+%% a symbolic constant. The initial value is `?GL_NEAREST_MIPMAP_LINEAR'.
+%%
+%% `?GL_TEXTURE_MIN_LOD': Returns the single-valued texture minimum level-of-detail
+%% value. The initial value is -1000.
+%%
+%% `?GL_TEXTURE_MAX_LOD': Returns the single-valued texture maximum level-of-detail
+%% value. The initial value is 1000.
+%%
+%% `?GL_TEXTURE_BASE_LEVEL': Returns the single-valued base texture mipmap level. The
+%% initial value is 0.
+%%
+%% `?GL_TEXTURE_MAX_LEVEL': Returns the single-valued maximum texture mipmap array
+%% level. The initial value is 1000.
+%%
+%% `?GL_TEXTURE_SWIZZLE_R': Returns the red component swizzle. The initial value is `?GL_RED'
+%% .
+%%
+%% `?GL_TEXTURE_SWIZZLE_G': Returns the green component swizzle. The initial value is `?GL_GREEN'
+%% .
+%%
+%% `?GL_TEXTURE_SWIZZLE_B': Returns the blue component swizzle. The initial value is `?GL_BLUE'
+%% .
+%%
+%% `?GL_TEXTURE_SWIZZLE_A': Returns the alpha component swizzle. The initial value is `?GL_ALPHA'
+%% .
+%%
+%% `?GL_TEXTURE_SWIZZLE_RGBA': Returns the component swizzle for all channels in a
+%% single query.
+%%
+%% `?GL_TEXTURE_WRAP_S': Returns the single-valued wrapping function for texture coordinate
+%% s, a symbolic constant. The initial value is `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_WRAP_T': Returns the single-valued wrapping function for texture coordinate
+%% t, a symbolic constant. The initial value is `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_WRAP_R': Returns the single-valued wrapping function for texture coordinate
+%% r, a symbolic constant. The initial value is `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_BORDER_COLOR': Returns four integer or floating-point numbers that
+%% comprise the RGBA color of the texture border. Floating-point values are returned in the
+%% range [0 1]. Integer values are returned as a linear mapping of the internal floating-point
+%% representation such that 1.0 maps to the most positive representable integer and -1.0
+%% maps to the most negative representable integer. The initial value is (0, 0, 0, 0).
+%%
+%% `?GL_TEXTURE_COMPARE_MODE': Returns a single-valued texture comparison mode, a symbolic
+%% constant. The initial value is `?GL_NONE'. See {@link gl:texParameterf/3} .
+%%
+%% `?GL_TEXTURE_COMPARE_FUNC': Returns a single-valued texture comparison function,
+%% a symbolic constant. The initial value is `?GL_LEQUAL'. See {@link gl:texParameterf/3} .
+%%
+%%
+%% In addition to the parameters that may be set with {@link gl:texParameterf/3} , ``gl:getTexParameter''
+%% accepts the following read-only parameters:
+%%
+%% `?GL_TEXTURE_IMMUTABLE_FORMAT': Returns non-zero if the texture has an immutable
+%% format. Textures become immutable if their storage is specified with {@link gl:texStorage1D/4}
+%% , {@link gl:texStorage2D/5} or {@link gl:texStorage3D/6} . The initial value is `?GL_FALSE'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml">external</a> documentation.
+-spec getTexParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
+getTexParameterfv(Target,Pname) ->
+ call(5262, <<Target:?GLenum,Pname:?GLenum>>).
+
+%% @doc
+%% See {@link getTexParameterfv/2}
+-spec getTexParameteriv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
+getTexParameteriv(Target,Pname) ->
+ call(5263, <<Target:?GLenum,Pname:?GLenum>>).
+
+%% @doc Return texture parameter values for a specific level of detail
+%%
+%% ``gl:getTexLevelParameter'' returns in `Params' texture parameter values for a
+%% specific level-of-detail value, specified as `Level' . `Target' defines the target
+%% texture, either `?GL_TEXTURE_1D', `?GL_TEXTURE_2D', `?GL_TEXTURE_3D', `?GL_PROXY_TEXTURE_1D'
+%% , `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_3D', `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'
+%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y'
+%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z', or `?GL_PROXY_TEXTURE_CUBE_MAP'
+%% .
+%%
+%% `?GL_MAX_TEXTURE_SIZE', and `?GL_MAX_3D_TEXTURE_SIZE' are not really descriptive
+%% enough. It has to report the largest square texture image that can be accommodated with
+%% mipmaps and borders, but a long skinny texture, or a texture without mipmaps and borders,
+%% may easily fit in texture memory. The proxy targets allow the user to more accurately
+%% query whether the GL can accommodate a texture of a given configuration. If the texture
+%% cannot be accommodated, the texture state variables, which may be queried with ``gl:getTexLevelParameter''
+%% , are set to 0. If the texture can be accommodated, the texture state values will be set
+%% as they would be set for a non-proxy target.
+%%
+%% `Pname' specifies the texture parameter whose value or values will be returned.
+%%
+%% The accepted parameter names are as follows:
+%%
+%% `?GL_TEXTURE_WIDTH': `Params' returns a single value, the width of the texture
+%% image. This value includes the border of the texture image. The initial value is 0.
+%%
+%% `?GL_TEXTURE_HEIGHT': `Params' returns a single value, the height of the texture
+%% image. This value includes the border of the texture image. The initial value is 0.
+%%
+%% `?GL_TEXTURE_DEPTH': `Params' returns a single value, the depth of the texture
+%% image. This value includes the border of the texture image. The initial value is 0.
+%%
+%% `?GL_TEXTURE_INTERNAL_FORMAT': `Params' returns a single value, the internal
+%% format of the texture image.
+%%
+%% `?GL_TEXTURE_RED_TYPE',
+%%
+%% `?GL_TEXTURE_GREEN_TYPE',
+%%
+%% `?GL_TEXTURE_BLUE_TYPE',
+%%
+%% `?GL_TEXTURE_ALPHA_TYPE',
+%%
+%% `?GL_TEXTURE_DEPTH_TYPE': The data type used to store the component. The types `?GL_NONE'
+%% , `?GL_SIGNED_NORMALIZED', `?GL_UNSIGNED_NORMALIZED', `?GL_FLOAT', `?GL_INT'
+%% , and `?GL_UNSIGNED_INT' may be returned to indicate signed normalized fixed-point,
+%% unsigned normalized fixed-point, floating-point, integer unnormalized, and unsigned integer
+%% unnormalized components, respectively.
+%%
+%% `?GL_TEXTURE_RED_SIZE',
+%%
+%% `?GL_TEXTURE_GREEN_SIZE',
+%%
+%% `?GL_TEXTURE_BLUE_SIZE',
+%%
+%% `?GL_TEXTURE_ALPHA_SIZE',
+%%
+%% `?GL_TEXTURE_DEPTH_SIZE': The internal storage resolution of an individual component.
+%% The resolution chosen by the GL will be a close match for the resolution requested by
+%% the user with the component argument of {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
+%% , {@link gl:copyTexImage1D/7} , and {@link gl:copyTexImage2D/8} . The initial value is 0.
+%%
+%% `?GL_TEXTURE_COMPRESSED': `Params' returns a single boolean value indicating
+%% if the texture image is stored in a compressed internal format. The initiali value is `?GL_FALSE'
+%% .
+%%
+%% `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE': `Params' returns a single integer value,
+%% the number of unsigned bytes of the compressed texture image that would be returned from {@link gl:getCompressedTexImage/3}
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml">external</a> documentation.
+-spec getTexLevelParameterfv(Target, Level, Pname) -> {float()} when Target :: enum(),Level :: integer(),Pname :: enum().
+getTexLevelParameterfv(Target,Level,Pname) ->
+ call(5264, <<Target:?GLenum,Level:?GLint,Pname:?GLenum>>).
+
+%% @doc
+%% See {@link getTexLevelParameterfv/3}
+-spec getTexLevelParameteriv(Target, Level, Pname) -> {integer()} when Target :: enum(),Level :: integer(),Pname :: enum().
+getTexLevelParameteriv(Target,Level,Pname) ->
+ call(5265, <<Target:?GLenum,Level:?GLint,Pname:?GLenum>>).
+
+%% @doc Specify a one-dimensional texture image
+%%
+%% Texturing maps a portion of a specified texture image onto each graphical primitive for
+%% which texturing is enabled. To enable and disable one-dimensional texturing, call {@link gl:enable/1}
+%% and {@link gl:enable/1} with argument `?GL_TEXTURE_1D'.
+%%
+%% Texture images are defined with ``gl:texImage1D''. The arguments describe the parameters
+%% of the texture image, such as width, width of the border, level-of-detail number (see {@link gl:texParameterf/3}
+%% ), and the internal resolution and format used to store the image. The last three arguments
+%% describe how the image is represented in memory.
+%%
+%% If `Target' is `?GL_PROXY_TEXTURE_1D', no data is read from `Data' , but
+%% all of the texture image state is recalculated, checked for consistency, and checked against
+%% the implementation's capabilities. If the implementation cannot handle a texture of the
+%% requested texture size, it sets all of the image state to 0, but does not generate an
+%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
+%% level greater than or equal to 1.
+%%
+%% If `Target' is `?GL_TEXTURE_1D', data is read from `Data' as a sequence
+%% of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values,
+%% depending on `Type' . These values are grouped into sets of one, two, three, or four
+%% values, depending on `Format' , to form elements. Each data byte is treated as eight
+%% 1-bit elements, with bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2}
+%% ).
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% The first element corresponds to the left end of the texture array. Subsequent elements
+%% progress left-to-right through the remaining texels in the texture array. The final element
+%% corresponds to the right end of the texture array.
+%%
+%% `Format' determines the composition of each element in `Data' . It can assume
+%% one of these symbolic values:
+%%
+%% `?GL_RED': Each element is a single red component. The GL converts it to floating
+%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for
+%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE',
+%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
+%%
+%% `?GL_RG': Each element is a single red/green double The GL converts it to floating
+%% point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha.
+%% Each component is then multiplied by the signed scale factor `?GL_c_SCALE', added
+%% to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
+%%
+%% `?GL_RGB'
+%%
+%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and
+%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied
+%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
+%% and clamped to the range [0,1].
+%%
+%% `?GL_RGBA'
+%%
+%% `?GL_BGRA': Each element contains all four components. Each component is multiplied
+%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
+%% and clamped to the range [0,1].
+%%
+%% `?GL_DEPTH_COMPONENT': Each element is a single depth value. The GL converts it
+%% to floating point, multiplies by the signed scale factor `?GL_DEPTH_SCALE', adds
+%% the signed bias `?GL_DEPTH_BIAS', and clamps to the range [0,1].
+%%
+%% If an application wants to store the texture at a certain resolution or in a certain
+%% format, it can request the resolution and format with `InternalFormat' . The GL will
+%% choose an internal representation that closely approximates that requested by `InternalFormat'
+%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG'
+%% , `?GL_RGB' and `?GL_RGBA' must match exactly.)
+%%
+%% `InternalFormat' may be one of the base internal formats shown in Table 1, below
+%%
+%% `InternalFormat' may also be one of the sized internal formats shown in Table 2,
+%% below
+%%
+%% Finally, `InternalFormat' may also be one of the generic or compressed compressed
+%% texture formats shown in Table 3 below
+%%
+%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED'
+%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA',
+%% the GL will replace the internal format with the symbolic constant for a specific internal
+%% format and compress the texture before storage. If no corresponding internal format is
+%% available, or the GL can not compress that image for any reason, the internal format is
+%% instead replaced with a corresponding base internal format.
+%%
+%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA'
+%% or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, or blue components
+%% are encoded in the sRGB color space. Any alpha component is left unchanged. The conversion
+%% from the sRGB encoded component c s to a linear component c l is:
+%%
+%% c l={ c s/12.92if c s&amp;le; 0.04045( c s+0.055/1.055) 2.4if c s&gt; 0.04045
+%%
+%% Assume c s is the sRGB component in the range [0,1].
+%%
+%% Use the `?GL_PROXY_TEXTURE_1D' target to try out a resolution and format. The implementation
+%% will update and recompute its best match for the requested storage resolution and format.
+%% To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture cannot
+%% be accommodated, texture state is set to 0.
+%%
+%% A one-component texture image uses only the red component of the RGBA color from `Data'
+%% . A two-component image uses the R and A values. A three-component image uses the R, G,
+%% and B values. A four-component image uses all of the RGBA components.
+%%
+%% Image-based shadowing can be enabled by comparing texture r coordinates to depth texture
+%% values to generate a boolean result. See {@link gl:texParameterf/3} for details on texture
+%% comparison.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml">external</a> documentation.
+-spec texImage1D(Target, Level, InternalFormat, Width, Border, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
+texImage1D(Target,Level,InternalFormat,Width,Border,Format,Type,Pixels) when is_integer(Pixels) ->
+ cast(5266, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
+texImage1D(Target,Level,InternalFormat,Width,Border,Format,Type,Pixels) ->
+ send_bin(Pixels),
+ cast(5267, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum>>).
+
+%% @doc Specify a two-dimensional texture image
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% To define texture images, call ``gl:texImage2D''. The arguments describe the parameters
+%% of the texture image, such as height, width, width of the border, level-of-detail number
+%% (see {@link gl:texParameterf/3} ), and number of color components provided. The last three
+%% arguments describe how the image is represented in memory.
+%%
+%% If `Target' is `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY', `?GL_PROXY_TEXTURE_CUBE_MAP'
+%% , or `?GL_PROXY_TEXTURE_RECTANGLE', no data is read from `Data' , but all of
+%% the texture image state is recalculated, checked for consistency, and checked against
+%% the implementation's capabilities. If the implementation cannot handle a texture of the
+%% requested texture size, it sets all of the image state to 0, but does not generate an
+%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
+%% level greater than or equal to 1.
+%%
+%% If `Target' is `?GL_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE' or one of the `?GL_TEXTURE_CUBE_MAP'
+%% targets, data is read from `Data' as a sequence of signed or unsigned bytes, shorts,
+%% or longs, or single-precision floating-point values, depending on `Type' . These values
+%% are grouped into sets of one, two, three, or four values, depending on `Format' ,
+%% to form elements. Each data byte is treated as eight 1-bit elements, with bit ordering
+%% determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} ).
+%%
+%% If `Target' is `?GL_TEXTURE_1D_ARRAY', data is interpreted as an array of one-dimensional
+%% images.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% The first element corresponds to the lower left corner of the texture image. Subsequent
+%% elements progress left-to-right through the remaining texels in the lowest row of the
+%% texture image, and then in successively higher rows of the texture image. The final element
+%% corresponds to the upper right corner of the texture image.
+%%
+%% `Format' determines the composition of each element in `Data' . It can assume
+%% one of these symbolic values:
+%%
+%% `?GL_RED': Each element is a single red component. The GL converts it to floating
+%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for
+%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE',
+%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
+%%
+%% `?GL_RG': Each element is a red/green double. The GL converts it to floating point
+%% and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha. Each component
+%% is then multiplied by the signed scale factor `?GL_c_SCALE', added to the signed
+%% bias `?GL_c_BIAS', and clamped to the range [0,1].
+%%
+%% `?GL_RGB'
+%%
+%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and
+%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied
+%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
+%% and clamped to the range [0,1].
+%%
+%% `?GL_RGBA'
+%%
+%% `?GL_BGRA': Each element contains all four components. Each component is multiplied
+%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
+%% and clamped to the range [0,1].
+%%
+%% `?GL_DEPTH_COMPONENT': Each element is a single depth value. The GL converts it
+%% to floating point, multiplies by the signed scale factor `?GL_DEPTH_SCALE', adds
+%% the signed bias `?GL_DEPTH_BIAS', and clamps to the range [0,1].
+%%
+%% `?GL_DEPTH_STENCIL': Each element is a pair of depth and stencil values. The depth
+%% component of the pair is interpreted as in `?GL_DEPTH_COMPONENT'. The stencil component
+%% is interpreted based on specified the depth + stencil internal format.
+%%
+%% If an application wants to store the texture at a certain resolution or in a certain
+%% format, it can request the resolution and format with `InternalFormat' . The GL will
+%% choose an internal representation that closely approximates that requested by `InternalFormat'
+%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG'
+%% , `?GL_RGB', and `?GL_RGBA' must match exactly.)
+%%
+%% `InternalFormat' may be one of the base internal formats shown in Table 1, below
+%%
+%% `InternalFormat' may also be one of the sized internal formats shown in Table 2,
+%% below
+%%
+%% Finally, `InternalFormat' may also be one of the generic or compressed compressed
+%% texture formats shown in Table 3 below
+%%
+%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED'
+%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA',
+%% the GL will replace the internal format with the symbolic constant for a specific internal
+%% format and compress the texture before storage. If no corresponding internal format is
+%% available, or the GL can not compress that image for any reason, the internal format is
+%% instead replaced with a corresponding base internal format.
+%%
+%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA'
+%% , or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, or blue components
+%% are encoded in the sRGB color space. Any alpha component is left unchanged. The conversion
+%% from the sRGB encoded component c s to a linear component c l is:
+%%
+%% c l={ c s/12.92if c s&amp;le; 0.04045( c s+0.055/1.055) 2.4if c s&gt; 0.04045
+%%
+%% Assume c s is the sRGB component in the range [0,1].
+%%
+%% Use the `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY', `?GL_PROXY_TEXTURE_RECTANGLE'
+%% , or `?GL_PROXY_TEXTURE_CUBE_MAP' target to try out a resolution and format. The
+%% implementation will update and recompute its best match for the requested storage resolution
+%% and format. To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture
+%% cannot be accommodated, texture state is set to 0.
+%%
+%% A one-component texture image uses only the red component of the RGBA color extracted
+%% from `Data' . A two-component image uses the R and G values. A three-component image
+%% uses the R, G, and B values. A four-component image uses all of the RGBA components.
+%%
+%% Image-based shadowing can be enabled by comparing texture r coordinates to depth texture
+%% values to generate a boolean result. See {@link gl:texParameterf/3} for details on texture
+%% comparison.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml">external</a> documentation.
+-spec texImage2D(Target, Level, InternalFormat, Width, Height, Border, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
+texImage2D(Target,Level,InternalFormat,Width,Height,Border,Format,Type,Pixels) when is_integer(Pixels) ->
+ cast(5268, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
+texImage2D(Target,Level,InternalFormat,Width,Height,Border,Format,Type,Pixels) ->
send_bin(Pixels),
- cast(5287, <<Target:?GLenum,Level:?GLint,Internalformat:?GLint,Width:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum>>).
-
-%% @spec (Target::enum(),Level::integer(),Internalformat::integer(),Width::integer(),Height::integer(),Border::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml">external</a> documentation.
--spec texImage2D(enum(),integer(),integer(),integer(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
-texImage2D(Target,Level,Internalformat,Width,Height,Border,Format,Type,Pixels) when is_integer(Pixels) ->
- cast(5288, <<Target:?GLenum,Level:?GLint,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
-texImage2D(Target,Level,Internalformat,Width,Height,Border,Format,Type,Pixels) ->
+ cast(5269, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum>>).
+
+%% @doc Return a texture image
+%%
+%% ``gl:getTexImage'' returns a texture image into `Img' . `Target' specifies
+%% whether the desired texture image is one specified by {@link gl:texImage1D/8} (`?GL_TEXTURE_1D'
+%% ), {@link gl:texImage2D/9} (`?GL_TEXTURE_1D_ARRAY', `?GL_TEXTURE_RECTANGLE', `?GL_TEXTURE_2D'
+%% or any of `?GL_TEXTURE_CUBE_MAP_*'), or {@link gl:texImage3D/10} (`?GL_TEXTURE_2D_ARRAY'
+%% , `?GL_TEXTURE_3D'). `Level' specifies the level-of-detail number of the desired
+%% image. `Format' and `Type' specify the format and type of the desired image
+%% array. See the reference page for {@link gl:texImage1D/8} for a description of the acceptable
+%% values for the `Format' and `Type' parameters, respectively.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is requested, `Img' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% To understand the operation of ``gl:getTexImage'', consider the selected internal four-component
+%% texture image to be an RGBA color buffer the size of the image. The semantics of ``gl:getTexImage''
+%% are then identical to those of {@link gl:readPixels/7} , with the exception that no pixel
+%% transfer operations are performed, when called with the same `Format' and `Type' ,
+%% with `x' and `y' set to 0, `width' set to the width of the texture image
+%% and `height' set to 1 for 1D images, or to the height of the texture image for 2D
+%% images.
+%%
+%% If the selected texture image does not contain four components, the following mappings
+%% are applied. Single-component textures are treated as RGBA buffers with red set to the
+%% single-component value, green set to 0, blue set to 0, and alpha set to 1. Two-component
+%% textures are treated as RGBA buffers with red set to the value of component zero, alpha
+%% set to the value of component one, and green and blue set to 0. Finally, three-component
+%% textures are treated as RGBA buffers with red set to component zero, green set to component
+%% one, blue set to component two, and alpha set to 1.
+%%
+%% To determine the required size of `Img' , use {@link gl:getTexLevelParameterfv/3} to
+%% determine the dimensions of the internal texture image, then scale the required number
+%% of pixels by the storage required for each pixel, based on `Format' and `Type' .
+%% Be sure to take the pixel storage parameters into account, especially `?GL_PACK_ALIGNMENT'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml">external</a> documentation.
+-spec getTexImage(Target, Level, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),Format :: enum(),Type :: enum(),Pixels :: mem().
+getTexImage(Target,Level,Format,Type,Pixels) ->
send_bin(Pixels),
- cast(5289, <<Target:?GLenum,Level:?GLint,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum>>).
+ call(5270, <<Target:?GLenum,Level:?GLint,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation.
--spec texParameterf(enum(),enum(),float()) -> ok.
-texParameterf(Target,Pname,Param) ->
- cast(5290, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
+%% @doc Generate texture names
+%%
+%% ``gl:genTextures'' returns `N' texture names in `Textures' . There is no guarantee
+%% that the names form a contiguous set of integers; however, it is guaranteed that none
+%% of the returned names was in use immediately before the call to ``gl:genTextures''.
+%%
+%% The generated textures have no dimensionality; they assume the dimensionality of the
+%% texture target to which they are first bound (see {@link gl:bindTexture/2} ).
+%%
+%% Texture names returned by a call to ``gl:genTextures'' are not returned by subsequent
+%% calls, unless they are first deleted with {@link gl:deleteTextures/1} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml">external</a> documentation.
+-spec genTextures(N) -> [integer()] when N :: integer().
+genTextures(N) ->
+ call(5271, <<N:?GLsizei>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation.
--spec texParameterfv(enum(),enum(),{float()}) -> ok.
-texParameterfv(Target,Pname,Params) ->
- cast(5291, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @doc Delete named textures
+%%
+%% ``gl:deleteTextures'' deletes `N' textures named by the elements of the array `Textures'
+%% . After a texture is deleted, it has no contents or dimensionality, and its name is free
+%% for reuse (for example by {@link gl:genTextures/1} ). If a texture that is currently bound
+%% is deleted, the binding reverts to 0 (the default texture).
+%%
+%% ``gl:deleteTextures'' silently ignores 0's and names that do not correspond to existing
+%% textures.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml">external</a> documentation.
+-spec deleteTextures(Textures) -> ok when Textures :: [integer()].
+deleteTextures(Textures) ->
+ cast(5272, <<(length(Textures)):?GLuint,
+ (<< <<C:?GLuint>> || C <- Textures>>)/binary,0:(((1+length(Textures)) rem 2)*32)>>).
-%% @spec (Target::enum(),Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation.
--spec texParameteri(enum(),enum(),integer()) -> ok.
-texParameteri(Target,Pname,Param) ->
- cast(5292, <<Target:?GLenum,Pname:?GLenum,Param:?GLint>>).
+%% @doc Bind a named texture to a texturing target
+%%
+%% ``gl:bindTexture'' lets you create or use a named texture. Calling ``gl:bindTexture''
+%% with `Target' set to `?GL_TEXTURE_1D', `?GL_TEXTURE_2D', `?GL_TEXTURE_3D'
+%% , or `?GL_TEXTURE_1D_ARRAY', `?GL_TEXTURE_2D_ARRAY', `?GL_TEXTURE_RECTANGLE'
+%% , `?GL_TEXTURE_CUBE_MAP', `?GL_TEXTURE_2D_MULTISAMPLE' or `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY'
+%% and `Texture' set to the name of the new texture binds the texture name to the target.
+%% When a texture is bound to a target, the previous binding for that target is automatically
+%% broken.
+%%
+%% Texture names are unsigned integers. The value zero is reserved to represent the default
+%% texture for each texture target. Texture names and the corresponding texture contents
+%% are local to the shared object space of the current GL rendering context; two rendering
+%% contexts share texture names only if they explicitly enable sharing between contexts through
+%% the appropriate GL windows interfaces functions.
+%%
+%% You must use {@link gl:genTextures/1} to generate a set of new texture names.
+%%
+%% When a texture is first bound, it assumes the specified target: A texture first bound
+%% to `?GL_TEXTURE_1D' becomes one-dimensional texture, a texture first bound to `?GL_TEXTURE_2D'
+%% becomes two-dimensional texture, a texture first bound to `?GL_TEXTURE_3D' becomes
+%% three-dimensional texture, a texture first bound to `?GL_TEXTURE_1D_ARRAY' becomes
+%% one-dimensional array texture, a texture first bound to `?GL_TEXTURE_2D_ARRAY' becomes
+%% two-dimensional arary texture, a texture first bound to `?GL_TEXTURE_RECTANGLE' becomes
+%% rectangle texture, a, texture first bound to `?GL_TEXTURE_CUBE_MAP' becomes a cube-mapped
+%% texture, a texture first bound to `?GL_TEXTURE_2D_MULTISAMPLE' becomes a two-dimensional
+%% multisampled texture, and a texture first bound to `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY'
+%% becomes a two-dimensional multisampled array texture. The state of a one-dimensional texture
+%% immediately after it is first bound is equivalent to the state of the default `?GL_TEXTURE_1D'
+%% at GL initialization, and similarly for the other texture types.
+%%
+%% While a texture is bound, GL operations on the target to which it is bound affect the
+%% bound texture, and queries of the target to which it is bound return state from the bound
+%% texture. In effect, the texture targets become aliases for the textures currently bound
+%% to them, and the texture name zero refers to the default textures that were bound to them
+%% at initialization.
+%%
+%% A texture binding created with ``gl:bindTexture'' remains active until a different
+%% texture is bound to the same target, or until the bound texture is deleted with {@link gl:deleteTextures/1}
+%% .
+%%
+%% Once created, a named texture may be re-bound to its same original target as often as
+%% needed. It is usually much faster to use ``gl:bindTexture'' to bind an existing named
+%% texture to one of the texture targets than it is to reload the texture image using {@link gl:texImage1D/8}
+%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} or another similar function.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTexture.xml">external</a> documentation.
+-spec bindTexture(Target, Texture) -> ok when Target :: enum(),Texture :: integer().
+bindTexture(Target,Texture) ->
+ cast(5273, <<Target:?GLenum,Texture:?GLuint>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation.
--spec texParameteriv(enum(),enum(),{integer()}) -> ok.
-texParameteriv(Target,Pname,Params) ->
- cast(5293, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
- (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
+%% @doc Set texture residence priority
+%%
+%% ``gl:prioritizeTextures'' assigns the `N' texture priorities given in `Priorities'
+%% to the `N' textures named in `Textures' .
+%%
+%% The GL establishes a ``working set'' of textures that are resident in texture memory.
+%% These textures may be bound to a texture target much more efficiently than textures that
+%% are not resident. By specifying a priority for each texture, ``gl:prioritizeTextures''
+%% allows applications to guide the GL implementation in determining which textures should
+%% be resident.
+%%
+%% The priorities given in `Priorities' are clamped to the range [0 1] before they are
+%% assigned. 0 indicates the lowest priority; textures with priority 0 are least likely to
+%% be resident. 1 indicates the highest priority; textures with priority 1 are most likely
+%% to be resident. However, textures are not guaranteed to be resident until they are used.
+%%
+%% ``gl:prioritizeTextures'' silently ignores attempts to prioritize texture 0 or any texture
+%% name that does not correspond to an existing texture.
+%%
+%% ``gl:prioritizeTextures'' does not require that any of the textures named by `Textures'
+%% be bound to a texture target. {@link gl:texParameterf/3} may also be used to set a texture's
+%% priority, but only if the texture is currently bound. This is the only way to set the
+%% priority of a default texture.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrioritizeTextures.xml">external</a> documentation.
+-spec prioritizeTextures(Textures, Priorities) -> ok when Textures :: [integer()],Priorities :: [clamp()].
+prioritizeTextures(Textures,Priorities) ->
+ cast(5274, <<(length(Textures)):?GLuint,
+ (<< <<C:?GLuint>> || C <- Textures>>)/binary,0:(((1+length(Textures)) rem 2)*32),(length(Priorities)):?GLuint,
+ (<< <<C:?GLclampf>> || C <- Priorities>>)/binary,0:(((1+length(Priorities)) rem 2)*32)>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Width::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage1D.xml">external</a> documentation.
--spec texSubImage1D(enum(),integer(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc Determine if textures are loaded in texture memory
+%%
+%% GL establishes a ``working set'' of textures that are resident in texture memory. These
+%% textures can be bound to a texture target much more efficiently than textures that are
+%% not resident.
+%%
+%% ``gl:areTexturesResident'' queries the texture residence status of the `N' textures
+%% named by the elements of `Textures' . If all the named textures are resident, ``gl:areTexturesResident''
+%% returns `?GL_TRUE', and the contents of `Residences' are undisturbed. If not
+%% all the named textures are resident, ``gl:areTexturesResident'' returns `?GL_FALSE',
+%% and detailed status is returned in the `N' elements of `Residences' . If an element
+%% of `Residences' is `?GL_TRUE', then the texture named by the corresponding element
+%% of `Textures' is resident.
+%%
+%% The residence status of a single bound texture may also be queried by calling {@link gl:getTexParameterfv/2}
+%% with the `target' argument set to the target to which the texture is bound, and
+%% the `pname' argument set to `?GL_TEXTURE_RESIDENT'. This is the only way that
+%% the residence status of a default texture can be queried.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAreTexturesResident.xml">external</a> documentation.
+-spec areTexturesResident(Textures) -> {0|1,Residences :: [0|1]} when Textures :: [integer()].
+areTexturesResident(Textures) ->
+ call(5275, <<(length(Textures)):?GLuint,
+ (<< <<C:?GLuint>> || C <- Textures>>)/binary,0:(((1+length(Textures)) rem 2)*32)>>).
+
+%% @doc Determine if a name corresponds to a texture
+%%
+%% ``gl:isTexture'' returns `?GL_TRUE' if `Texture' is currently the name of
+%% a texture. If `Texture' is zero, or is a non-zero value that is not currently the
+%% name of a texture, or if an error occurs, ``gl:isTexture'' returns `?GL_FALSE'.
+%%
+%% A name returned by {@link gl:genTextures/1} , but not yet associated with a texture by
+%% calling {@link gl:bindTexture/2} , is not the name of a texture.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml">external</a> documentation.
+-spec isTexture(Texture) -> 0|1 when Texture :: integer().
+isTexture(Texture) ->
+ call(5276, <<Texture:?GLuint>>).
+
+%% @doc glTexSubImage
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation.
+-spec texSubImage1D(Target, Level, Xoffset, Width, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texSubImage1D(Target,Level,Xoffset,Width,Format,Type,Pixels) when is_integer(Pixels) ->
- cast(5294, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
+ cast(5277, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
texSubImage1D(Target,Level,Xoffset,Width,Format,Type,Pixels) ->
send_bin(Pixels),
- cast(5295, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum>>).
+ cast(5278, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Yoffset::integer(),Width::integer(),Height::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage2D.xml">external</a> documentation.
--spec texSubImage2D(enum(),integer(),integer(),integer(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc glTexSubImage
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation.
+-spec texSubImage2D(Target, Level, Xoffset, Yoffset, Width, Height, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,Type,Pixels) when is_integer(Pixels) ->
- cast(5296, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
+ cast(5279, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
texSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,Type,Pixels) ->
send_bin(Pixels),
- cast(5297, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
+ cast(5280, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml">external</a> documentation.
--spec translated(float(),float(),float()) -> ok.
-translated(X,Y,Z) ->
- cast(5298, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
+%% @doc Copy pixels into a 1D texture image
+%%
+%% ``gl:copyTexImage1D'' defines a one-dimensional texture image with pixels from the current
+%% `?GL_READ_BUFFER'.
+%%
+%% The screen-aligned pixel row with left corner at (x y) and with a length of width+2(border) defines
+%% the texture array at the mipmap level specified by `Level' . `Internalformat'
+%% specifies the internal format of the texture array.
+%%
+%% The pixels in the row are processed exactly as if {@link gl:readPixels/7} had been called,
+%% but the process stops just before final conversion. At this point all pixel component
+%% values are clamped to the range [0 1] and then converted to the texture's internal format
+%% for storage in the texel array.
+%%
+%% Pixel ordering is such that lower x screen coordinates correspond to lower texture
+%% coordinates.
+%%
+%% If any of the pixels within the specified row of the current `?GL_READ_BUFFER' are
+%% outside the window associated with the current rendering context, then the values obtained
+%% for those pixels are undefined.
+%%
+%% ``gl:copyTexImage1D'' defines a one-dimensional texture image with pixels from the current
+%% `?GL_READ_BUFFER'.
+%%
+%% When `Internalformat' is one of the sRGB types, the GL does not automatically convert
+%% the source pixels to the sRGB color space. In this case, the ``gl:pixelMap'' function
+%% can be used to accomplish the conversion.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage1D.xml">external</a> documentation.
+-spec copyTexImage1D(Target, Level, Internalformat, X, Y, Width, Border) -> ok when Target :: enum(),Level :: integer(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Border :: integer().
+copyTexImage1D(Target,Level,Internalformat,X,Y,Width,Border) ->
+ cast(5281, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Border:?GLint>>).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml">external</a> documentation.
--spec translatef(float(),float(),float()) -> ok.
-translatef(X,Y,Z) ->
- cast(5299, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
+%% @doc Copy pixels into a 2D texture image
+%%
+%% ``gl:copyTexImage2D'' defines a two-dimensional texture image, or cube-map texture image
+%% with pixels from the current `?GL_READ_BUFFER'.
+%%
+%% The screen-aligned pixel rectangle with lower left corner at ( `X' , `Y' ) and
+%% with a width of width+2(border) and a height of height+2(border) defines the texture array at the mipmap
+%% level specified by `Level' . `Internalformat' specifies the internal format of
+%% the texture array.
+%%
+%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
+%% called, but the process stops just before final conversion. At this point all pixel component
+%% values are clamped to the range [0 1] and then converted to the texture's internal format
+%% for storage in the texel array.
+%%
+%% Pixel ordering is such that lower x and y screen coordinates correspond to lower s
+%% and t texture coordinates.
+%%
+%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER'
+%% are outside the window associated with the current rendering context, then the values
+%% obtained for those pixels are undefined.
+%%
+%% When `Internalformat' is one of the sRGB types, the GL does not automatically convert
+%% the source pixels to the sRGB color space. In this case, the ``gl:pixelMap'' function
+%% can be used to accomplish the conversion.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml">external</a> documentation.
+-spec copyTexImage2D(Target, Level, Internalformat, X, Y, Width, Height, Border) -> ok when Target :: enum(),Level :: integer(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Border :: integer().
+copyTexImage2D(Target,Level,Internalformat,X,Y,Width,Height,Border) ->
+ cast(5282, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint>>).
-%% @spec (X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex2d(float(),float()) -> ok.
-vertex2d(X,Y) ->
- cast(5300, <<X:?GLdouble,Y:?GLdouble>>).
+%% @doc Copy a one-dimensional texture subimage
+%%
+%% ``gl:copyTexSubImage1D'' replaces a portion of a one-dimensional texture image with
+%% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the
+%% case for {@link gl:texSubImage1D/7} ).
+%%
+%% The screen-aligned pixel row with left corner at ( `X' , `Y' ), and with length `Width'
+%% replaces the portion of the texture array with x indices `Xoffset' through xoffset
+%% +width-1, inclusive. The destination in the texture array may not include any texels outside
+%% the texture array as it was originally specified.
+%%
+%% The pixels in the row are processed exactly as if {@link gl:readPixels/7} had been called,
+%% but the process stops just before final conversion. At this point, all pixel component
+%% values are clamped to the range [0 1] and then converted to the texture's internal format
+%% for storage in the texel array.
+%%
+%% It is not an error to specify a subtexture with zero width, but such a specification
+%% has no effect. If any of the pixels within the specified row of the current `?GL_READ_BUFFER'
+%% are outside the read window associated with the current rendering context, then the values
+%% obtained for those pixels are undefined.
+%%
+%% No change is made to the `internalformat', `width', or `border' parameters
+%% of the specified texture array or to texel values outside the specified subregion.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage1D.xml">external</a> documentation.
+-spec copyTexSubImage1D(Target, Level, Xoffset, X, Y, Width) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer().
+copyTexSubImage1D(Target,Level,Xoffset,X,Y,Width) ->
+ cast(5283, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei>>).
-%% @spec ({X,Y}) -> ok
-%% @equiv vertex2d(X,Y)
--spec vertex2dv({float(),float()}) -> ok.
-vertex2dv({X,Y}) -> vertex2d(X,Y).
+%% @doc Copy a two-dimensional texture subimage
+%%
+%% ``gl:copyTexSubImage2D'' replaces a rectangular portion of a two-dimensional texture
+%% image or cube-map texture image with pixels from the current `?GL_READ_BUFFER' (rather
+%% than from main memory, as is the case for {@link gl:texSubImage1D/7} ).
+%%
+%% The screen-aligned pixel rectangle with lower left corner at (x y) and with width `Width'
+%% and height `Height' replaces the portion of the texture array with x indices `Xoffset'
+%% through xoffset+width-1, inclusive, and y indices `Yoffset' through yoffset+height
+%% -1, inclusive, at the mipmap level specified by `Level' .
+%%
+%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
+%% called, but the process stops just before final conversion. At this point, all pixel component
+%% values are clamped to the range [0 1] and then converted to the texture's internal format
+%% for storage in the texel array.
+%%
+%% The destination rectangle in the texture array may not include any texels outside the
+%% texture array as it was originally specified. It is not an error to specify a subtexture
+%% with zero width or height, but such a specification has no effect.
+%%
+%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER'
+%% are outside the read window associated with the current rendering context, then the values
+%% obtained for those pixels are undefined.
+%%
+%% No change is made to the `internalformat', `width', `height', or `border'
+%% parameters of the specified texture array or to texel values outside the specified subregion.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml">external</a> documentation.
+-spec copyTexSubImage2D(Target, Level, Xoffset, Yoffset, X, Y, Width, Height) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
+copyTexSubImage2D(Target,Level,Xoffset,Yoffset,X,Y,Width,Height) ->
+ cast(5284, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex2f(float(),float()) -> ok.
-vertex2f(X,Y) ->
- cast(5301, <<X:?GLfloat,Y:?GLfloat>>).
+%% @doc glMap
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+-spec map1d(Target, U1, U2, Stride, Order, Points) -> ok when Target :: enum(),U1 :: float(),U2 :: float(),Stride :: integer(),Order :: integer(),Points :: binary().
+map1d(Target,U1,U2,Stride,Order,Points) ->
+ send_bin(Points),
+ cast(5285, <<Target:?GLenum,0:32,U1:?GLdouble,U2:?GLdouble,Stride:?GLint,Order:?GLint>>).
-%% @spec ({X,Y}) -> ok
-%% @equiv vertex2f(X,Y)
--spec vertex2fv({float(),float()}) -> ok.
-vertex2fv({X,Y}) -> vertex2f(X,Y).
+%% @doc glMap
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+-spec map1f(Target, U1, U2, Stride, Order, Points) -> ok when Target :: enum(),U1 :: float(),U2 :: float(),Stride :: integer(),Order :: integer(),Points :: binary().
+map1f(Target,U1,U2,Stride,Order,Points) ->
+ send_bin(Points),
+ cast(5286, <<Target:?GLenum,U1:?GLfloat,U2:?GLfloat,Stride:?GLint,Order:?GLint>>).
-%% @spec (X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex2i(integer(),integer()) -> ok.
-vertex2i(X,Y) ->
- cast(5302, <<X:?GLint,Y:?GLint>>).
+%% @doc glMap
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+-spec map2d(Target, U1, U2, Ustride, Uorder, V1, V2, Vstride, Vorder, Points) -> ok when Target :: enum(),U1 :: float(),U2 :: float(),Ustride :: integer(),Uorder :: integer(),V1 :: float(),V2 :: float(),Vstride :: integer(),Vorder :: integer(),Points :: binary().
+map2d(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
+ send_bin(Points),
+ cast(5287, <<Target:?GLenum,0:32,U1:?GLdouble,U2:?GLdouble,Ustride:?GLint,Uorder:?GLint,V1:?GLdouble,V2:?GLdouble,Vstride:?GLint,Vorder:?GLint>>).
-%% @spec ({X,Y}) -> ok
-%% @equiv vertex2i(X,Y)
--spec vertex2iv({integer(),integer()}) -> ok.
-vertex2iv({X,Y}) -> vertex2i(X,Y).
+%% @doc glMap
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+-spec map2f(Target, U1, U2, Ustride, Uorder, V1, V2, Vstride, Vorder, Points) -> ok when Target :: enum(),U1 :: float(),U2 :: float(),Ustride :: integer(),Uorder :: integer(),V1 :: float(),V2 :: float(),Vstride :: integer(),Vorder :: integer(),Points :: binary().
+map2f(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
+ send_bin(Points),
+ cast(5288, <<Target:?GLenum,U1:?GLfloat,U2:?GLfloat,Ustride:?GLint,Uorder:?GLint,V1:?GLfloat,V2:?GLfloat,Vstride:?GLint,Vorder:?GLint>>).
-%% @spec (X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex2s(integer(),integer()) -> ok.
-vertex2s(X,Y) ->
- cast(5303, <<X:?GLshort,Y:?GLshort>>).
+%% @doc Return evaluator parameters
+%%
+%% {@link gl:map1d/6} and {@link gl:map1d/6} define evaluators. ``gl:getMap'' returns evaluator
+%% parameters. `Target' chooses a map, `Query' selects a specific parameter, and `V'
+%% points to storage where the values will be returned.
+%%
+%% The acceptable values for the `Target' parameter are described in the {@link gl:map1d/6}
+%% and {@link gl:map1d/6} reference pages.
+%%
+%% `Query' can assume the following values:
+%%
+%% `?GL_COEFF': `V' returns the control points for the evaluator function. One-dimensional
+%% evaluators return order control points, and two-dimensional evaluators return uorder*vorder
+%% control points. Each control point consists of one, two, three, or four integer, single-precision
+%% floating-point, or double-precision floating-point values, depending on the type of the
+%% evaluator. The GL returns two-dimensional control points in row-major order, incrementing
+%% the uorder index quickly and the vorder index after each row. Integer values, when
+%% requested, are computed by rounding the internal floating-point values to the nearest
+%% integer values.
+%%
+%% `?GL_ORDER': `V' returns the order of the evaluator function. One-dimensional
+%% evaluators return a single value, order. The initial value is 1. Two-dimensional evaluators
+%% return two values, uorder and vorder. The initial value is 1,1.
+%%
+%% `?GL_DOMAIN': `V' returns the linear u and v mapping parameters. One-dimensional
+%% evaluators return two values, u1 and u2, as specified by {@link gl:map1d/6} . Two-dimensional
+%% evaluators return four values ( u1, u2, v1, and v2) as specified by {@link gl:map1d/6} .
+%% Integer values, when requested, are computed by rounding the internal floating-point values
+%% to the nearest integer values.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml">external</a> documentation.
+-spec getMapdv(Target, Query, V) -> ok when Target :: enum(),Query :: enum(),V :: mem().
+getMapdv(Target,Query,V) ->
+ send_bin(V),
+ call(5289, <<Target:?GLenum,Query:?GLenum>>).
-%% @spec ({X,Y}) -> ok
-%% @equiv vertex2s(X,Y)
--spec vertex2sv({integer(),integer()}) -> ok.
-vertex2sv({X,Y}) -> vertex2s(X,Y).
+%% @doc
+%% See {@link getMapdv/3}
+-spec getMapfv(Target, Query, V) -> ok when Target :: enum(),Query :: enum(),V :: mem().
+getMapfv(Target,Query,V) ->
+ send_bin(V),
+ call(5290, <<Target:?GLenum,Query:?GLenum>>).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex3d(float(),float(),float()) -> ok.
-vertex3d(X,Y,Z) ->
- cast(5304, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
+%% @doc
+%% See {@link getMapdv/3}
+-spec getMapiv(Target, Query, V) -> ok when Target :: enum(),Query :: enum(),V :: mem().
+getMapiv(Target,Query,V) ->
+ send_bin(V),
+ call(5291, <<Target:?GLenum,Query:?GLenum>>).
-%% @spec ({X,Y,Z}) -> ok
-%% @equiv vertex3d(X,Y,Z)
--spec vertex3dv({float(),float(),float()}) -> ok.
-vertex3dv({X,Y,Z}) -> vertex3d(X,Y,Z).
+%% @doc Evaluate enabled one- and two-dimensional maps
+%%
+%% ``gl:evalCoord1'' evaluates enabled one-dimensional maps at argument `U' . ``gl:evalCoord2''
+%% does the same for two-dimensional maps using two domain values, `U' and `V' .
+%% To define a map, call {@link gl:map1d/6} and {@link gl:map1d/6} ; to enable and disable it,
+%% call {@link gl:enable/1} and {@link gl:enable/1} .
+%%
+%% When one of the ``gl:evalCoord'' commands is issued, all currently enabled maps of
+%% the indicated dimension are evaluated. Then, for each enabled map, it is as if the corresponding
+%% GL command had been issued with the computed value. That is, if `?GL_MAP1_INDEX' or `?GL_MAP2_INDEX'
+%% is enabled, a {@link gl:indexd/1} command is simulated. If `?GL_MAP1_COLOR_4' or `?GL_MAP2_COLOR_4'
+%% is enabled, a {@link gl:color3b/3} command is simulated. If `?GL_MAP1_NORMAL' or `?GL_MAP2_NORMAL'
+%% is enabled, a normal vector is produced, and if any of `?GL_MAP1_TEXTURE_COORD_1', `?GL_MAP1_TEXTURE_COORD_2'
+%% , `?GL_MAP1_TEXTURE_COORD_3', `?GL_MAP1_TEXTURE_COORD_4', `?GL_MAP2_TEXTURE_COORD_1'
+%% , `?GL_MAP2_TEXTURE_COORD_2', `?GL_MAP2_TEXTURE_COORD_3', or `?GL_MAP2_TEXTURE_COORD_4'
+%% is enabled, then an appropriate {@link gl:texCoord1d/1} command is simulated.
+%%
+%% For color, color index, normal, and texture coordinates the GL uses evaluated values
+%% instead of current values for those evaluations that are enabled, and current values otherwise,
+%% However, the evaluated values do not update the current values. Thus, if {@link gl:vertex2d/2}
+%% commands are interspersed with ``gl:evalCoord'' commands, the color, normal, and texture
+%% coordinates associated with the {@link gl:vertex2d/2} commands are not affected by the values
+%% generated by the ``gl:evalCoord'' commands, but only by the most recent {@link gl:color3b/3}
+%% , {@link gl:indexd/1} , {@link gl:normal3b/3} , and {@link gl:texCoord1d/1} commands.
+%%
+%% No commands are issued for maps that are not enabled. If more than one texture evaluation
+%% is enabled for a particular dimension (for example, `?GL_MAP2_TEXTURE_COORD_1' and `?GL_MAP2_TEXTURE_COORD_2'
+%% ), then only the evaluation of the map that produces the larger number of coordinates
+%% (in this case, `?GL_MAP2_TEXTURE_COORD_2') is carried out. `?GL_MAP1_VERTEX_4'
+%% overrides `?GL_MAP1_VERTEX_3', and `?GL_MAP2_VERTEX_4' overrides `?GL_MAP2_VERTEX_3'
+%% , in the same manner. If neither a three- nor a four-component vertex map is enabled for
+%% the specified dimension, the ``gl:evalCoord'' command is ignored.
+%%
+%% If you have enabled automatic normal generation, by calling {@link gl:enable/1} with argument
+%% `?GL_AUTO_NORMAL', ``gl:evalCoord2'' generates surface normals analytically, regardless
+%% of the contents or enabling of the `?GL_MAP2_NORMAL' map. Let
+%%
+%% m=((&amp;PartialD; p)/(&amp;PartialD; u))*((&amp;PartialD; p)/(&amp;PartialD; v))
+%%
+%% Then the generated normal n is n= m/(||m||)
+%%
+%% If automatic normal generation is disabled, the corresponding normal map `?GL_MAP2_NORMAL'
+%% , if enabled, is used to produce a normal. If neither automatic normal generation nor
+%% a normal map is enabled, no normal is generated for ``gl:evalCoord2'' commands.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation.
+-spec evalCoord1d(U) -> ok when U :: float().
+evalCoord1d(U) ->
+ cast(5292, <<U:?GLdouble>>).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex3f(float(),float(),float()) -> ok.
-vertex3f(X,Y,Z) ->
- cast(5305, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
+%% @doc
+%% See {@link evalCoord1d/1}
+-spec evalCoord1f(U) -> ok when U :: float().
+evalCoord1f(U) ->
+ cast(5293, <<U:?GLfloat>>).
-%% @spec ({X,Y,Z}) -> ok
-%% @equiv vertex3f(X,Y,Z)
--spec vertex3fv({float(),float(),float()}) -> ok.
-vertex3fv({X,Y,Z}) -> vertex3f(X,Y,Z).
+%% @equiv evalCoord1d(U)
+-spec evalCoord1dv(U) -> ok when U :: {U :: float()}.
+evalCoord1dv({U}) -> evalCoord1d(U).
-%% @spec (X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex3i(integer(),integer(),integer()) -> ok.
-vertex3i(X,Y,Z) ->
- cast(5306, <<X:?GLint,Y:?GLint,Z:?GLint>>).
+%% @equiv evalCoord1f(U)
+-spec evalCoord1fv(U) -> ok when U :: {U :: float()}.
+evalCoord1fv({U}) -> evalCoord1f(U).
-%% @spec ({X,Y,Z}) -> ok
-%% @equiv vertex3i(X,Y,Z)
--spec vertex3iv({integer(),integer(),integer()}) -> ok.
-vertex3iv({X,Y,Z}) -> vertex3i(X,Y,Z).
+%% @doc
+%% See {@link evalCoord1d/1}
+-spec evalCoord2d(U, V) -> ok when U :: float(),V :: float().
+evalCoord2d(U,V) ->
+ cast(5294, <<U:?GLdouble,V:?GLdouble>>).
-%% @spec (X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex3s(integer(),integer(),integer()) -> ok.
-vertex3s(X,Y,Z) ->
- cast(5307, <<X:?GLshort,Y:?GLshort,Z:?GLshort>>).
+%% @doc
+%% See {@link evalCoord1d/1}
+-spec evalCoord2f(U, V) -> ok when U :: float(),V :: float().
+evalCoord2f(U,V) ->
+ cast(5295, <<U:?GLfloat,V:?GLfloat>>).
-%% @spec ({X,Y,Z}) -> ok
-%% @equiv vertex3s(X,Y,Z)
--spec vertex3sv({integer(),integer(),integer()}) -> ok.
-vertex3sv({X,Y,Z}) -> vertex3s(X,Y,Z).
+%% @equiv evalCoord2d(U,V)
+-spec evalCoord2dv(U) -> ok when U :: {U :: float(),V :: float()}.
+evalCoord2dv({U,V}) -> evalCoord2d(U,V).
-%% @spec (X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex4d(float(),float(),float(),float()) -> ok.
-vertex4d(X,Y,Z,W) ->
- cast(5308, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
+%% @equiv evalCoord2f(U,V)
+-spec evalCoord2fv(U) -> ok when U :: {U :: float(),V :: float()}.
+evalCoord2fv({U,V}) -> evalCoord2f(U,V).
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv vertex4d(X,Y,Z,W)
--spec vertex4dv({float(),float(),float(),float()}) -> ok.
-vertex4dv({X,Y,Z,W}) -> vertex4d(X,Y,Z,W).
+%% @doc Define a one- or two-dimensional mesh
+%%
+%% ``gl:mapGrid'' and {@link gl:evalMesh1/3} are used together to efficiently generate and
+%% evaluate a series of evenly-spaced map domain values. {@link gl:evalMesh1/3} steps through
+%% the integer domain of a one- or two-dimensional grid, whose range is the domain of the
+%% evaluation maps specified by {@link gl:map1d/6} and {@link gl:map1d/6} .
+%%
+%% ``gl:mapGrid1'' and ``gl:mapGrid2'' specify the linear grid mappings between the i
+%% (or i and j) integer grid coordinates, to the u (or u and v) floating-point
+%% evaluation map coordinates. See {@link gl:map1d/6} and {@link gl:map1d/6} for details of how
+%% u and v coordinates are evaluated.
+%%
+%% ``gl:mapGrid1'' specifies a single linear mapping such that integer grid coordinate
+%% 0 maps exactly to `U1' , and integer grid coordinate `Un' maps exactly to `U2'
+%% . All other integer grid coordinates i are mapped so that
+%%
+%% u= i(u2-u1)/un+u1
+%%
+%% ``gl:mapGrid2'' specifies two such linear mappings. One maps integer grid coordinate
+%% i= 0 exactly to `U1' , and integer grid coordinate i= un exactly to `U2' . The
+%% other maps integer grid coordinate j= 0 exactly to `V1' , and integer grid coordinate
+%% j= vn exactly to `V2' . Other integer grid coordinates i and j are mapped such
+%% that
+%%
+%% u= i(u2-u1)/un+u1
+%%
+%% v= j(v2-v1)/vn+v1
+%%
+%% The mappings specified by ``gl:mapGrid'' are used identically by {@link gl:evalMesh1/3}
+%% and {@link gl:evalPoint1/1} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation.
+-spec mapGrid1d(Un, U1, U2) -> ok when Un :: integer(),U1 :: float(),U2 :: float().
+mapGrid1d(Un,U1,U2) ->
+ cast(5296, <<Un:?GLint,0:32,U1:?GLdouble,U2:?GLdouble>>).
-%% @spec (X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex4f(float(),float(),float(),float()) -> ok.
-vertex4f(X,Y,Z,W) ->
- cast(5309, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
+%% @doc
+%% See {@link mapGrid1d/3}
+-spec mapGrid1f(Un, U1, U2) -> ok when Un :: integer(),U1 :: float(),U2 :: float().
+mapGrid1f(Un,U1,U2) ->
+ cast(5297, <<Un:?GLint,U1:?GLfloat,U2:?GLfloat>>).
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv vertex4f(X,Y,Z,W)
--spec vertex4fv({float(),float(),float(),float()}) -> ok.
-vertex4fv({X,Y,Z,W}) -> vertex4f(X,Y,Z,W).
+%% @doc
+%% See {@link mapGrid1d/3}
+-spec mapGrid2d(Un, U1, U2, Vn, V1, V2) -> ok when Un :: integer(),U1 :: float(),U2 :: float(),Vn :: integer(),V1 :: float(),V2 :: float().
+mapGrid2d(Un,U1,U2,Vn,V1,V2) ->
+ cast(5298, <<Un:?GLint,0:32,U1:?GLdouble,U2:?GLdouble,Vn:?GLint,0:32,V1:?GLdouble,V2:?GLdouble>>).
-%% @spec (X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex4i(integer(),integer(),integer(),integer()) -> ok.
-vertex4i(X,Y,Z,W) ->
- cast(5310, <<X:?GLint,Y:?GLint,Z:?GLint,W:?GLint>>).
+%% @doc
+%% See {@link mapGrid1d/3}
+-spec mapGrid2f(Un, U1, U2, Vn, V1, V2) -> ok when Un :: integer(),U1 :: float(),U2 :: float(),Vn :: integer(),V1 :: float(),V2 :: float().
+mapGrid2f(Un,U1,U2,Vn,V1,V2) ->
+ cast(5299, <<Un:?GLint,U1:?GLfloat,U2:?GLfloat,Vn:?GLint,V1:?GLfloat,V2:?GLfloat>>).
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv vertex4i(X,Y,Z,W)
--spec vertex4iv({integer(),integer(),integer(),integer()}) -> ok.
-vertex4iv({X,Y,Z,W}) -> vertex4i(X,Y,Z,W).
+%% @doc Generate and evaluate a single point in a mesh
+%%
+%% {@link gl:mapGrid1d/3} and {@link gl:evalMesh1/3} are used in tandem to efficiently generate
+%% and evaluate a series of evenly spaced map domain values. ``gl:evalPoint'' can be used
+%% to evaluate a single grid point in the same gridspace that is traversed by {@link gl:evalMesh1/3}
+%% . Calling ``gl:evalPoint1'' is equivalent to calling glEvalCoord1( i.&amp;Delta; u+u
+%% 1 ); where &amp;Delta; u=(u 2-u 1)/n
+%%
+%% and n, u 1, and u 2 are the arguments to the most recent {@link gl:mapGrid1d/3} command.
+%% The one absolute numeric requirement is that if i= n, then the value computed from i.&amp;Delta;
+%% u+u 1 is exactly u 2.
+%%
+%% In the two-dimensional case, ``gl:evalPoint2'', let
+%%
+%% &amp;Delta; u=(u 2-u 1)/n
+%%
+%% &amp;Delta; v=(v 2-v 1)/m
+%%
+%% where n, u 1, u 2, m, v 1, and v 2 are the arguments to the most recent {@link gl:mapGrid1d/3}
+%% command. Then the ``gl:evalPoint2'' command is equivalent to calling glEvalCoord2( i.
+%% &amp;Delta; u+u 1, j.&amp;Delta; v+v 1 ); The only absolute numeric requirements are
+%% that if i= n, then the value computed from i.&amp;Delta; u+u 1 is exactly u 2, and
+%% if j= m, then the value computed from j.&amp;Delta; v+v 1 is exactly v 2.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml">external</a> documentation.
+-spec evalPoint1(I) -> ok when I :: integer().
+evalPoint1(I) ->
+ cast(5300, <<I:?GLint>>).
-%% @spec (X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
--spec vertex4s(integer(),integer(),integer(),integer()) -> ok.
-vertex4s(X,Y,Z,W) ->
- cast(5311, <<X:?GLshort,Y:?GLshort,Z:?GLshort,W:?GLshort>>).
+%% @doc
+%% See {@link evalPoint1/1}
+-spec evalPoint2(I, J) -> ok when I :: integer(),J :: integer().
+evalPoint2(I,J) ->
+ cast(5301, <<I:?GLint,J:?GLint>>).
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv vertex4s(X,Y,Z,W)
--spec vertex4sv({integer(),integer(),integer(),integer()}) -> ok.
-vertex4sv({X,Y,Z,W}) -> vertex4s(X,Y,Z,W).
+%% @doc Compute a one- or two-dimensional grid of points or lines
+%%
+%% {@link gl:mapGrid1d/3} and ``gl:evalMesh'' are used in tandem to efficiently generate and
+%% evaluate a series of evenly-spaced map domain values. ``gl:evalMesh'' steps through
+%% the integer domain of a one- or two-dimensional grid, whose range is the domain of the
+%% evaluation maps specified by {@link gl:map1d/6} and {@link gl:map1d/6} . `Mode' determines
+%% whether the resulting vertices are connected as points, lines, or filled polygons.
+%%
+%% In the one-dimensional case, ``gl:evalMesh1'', the mesh is generated as if the following
+%% code fragment were executed:
+%%
+%% glBegin( `Type' ); for ( i = `I1' ; i &lt;= `I2' ; i += 1 ) glEvalCoord1(
+%% i.&amp;Delta; u+u 1 ); glEnd(); where
+%%
+%% &amp;Delta; u=(u 2-u 1)/n
+%%
+%% and n, u 1, and u 2 are the arguments to the most recent {@link gl:mapGrid1d/3} command.
+%% `type' is `?GL_POINTS' if `Mode' is `?GL_POINT', or `?GL_LINES'
+%% if `Mode' is `?GL_LINE'.
+%%
+%% The one absolute numeric requirement is that if i= n, then the value computed from i.
+%% &amp;Delta; u+u 1 is exactly u 2.
+%%
+%% In the two-dimensional case, ``gl:evalMesh2'', let .cp &amp;Delta; u=(u 2-u 1)/n
+%%
+%% &amp;Delta; v=(v 2-v 1)/m
+%%
+%% where n, u 1, u 2, m, v 1, and v 2 are the arguments to the most recent {@link gl:mapGrid1d/3}
+%% command. Then, if `Mode' is `?GL_FILL', the ``gl:evalMesh2'' command is equivalent
+%% to:
+%%
+%% for ( j = `J1' ; j &lt; `J2' ; j += 1 ) { glBegin( GL_QUAD_STRIP ); for ( i = `I1'
+%% ; i &lt;= `I2' ; i += 1 ) { glEvalCoord2( i.&amp;Delta; u+u 1, j.&amp;Delta; v+v 1
+%% ); glEvalCoord2( i.&amp;Delta; u+u 1,(j+1).&amp;Delta; v+v 1 ); } glEnd(); }
+%%
+%% If `Mode' is `?GL_LINE', then a call to ``gl:evalMesh2'' is equivalent to:
+%%
+%% for ( j = `J1' ; j &lt;= `J2' ; j += 1 ) { glBegin( GL_LINE_STRIP ); for ( i = `I1'
+%% ; i &lt;= `I2' ; i += 1 ) glEvalCoord2( i.&amp;Delta; u+u 1, j.&amp;Delta; v+v 1
+%% ); glEnd(); } for ( i = `I1' ; i &lt;= `I2' ; i += 1 ) { glBegin( GL_LINE_STRIP
+%% ); for ( j = `J1' ; j &lt;= `J1' ; j += 1 ) glEvalCoord2( i.&amp;Delta; u+u 1, j.
+%% &amp;Delta; v+v 1 ); glEnd(); }
+%%
+%% And finally, if `Mode' is `?GL_POINT', then a call to ``gl:evalMesh2'' is
+%% equivalent to:
+%%
+%% glBegin( GL_POINTS ); for ( j = `J1' ; j &lt;= `J2' ; j += 1 ) for ( i = `I1'
+%% ; i &lt;= `I2' ; i += 1 ) glEvalCoord2( i.&amp;Delta; u+u 1, j.&amp;Delta; v+v 1
+%% ); glEnd();
+%%
+%% In all three cases, the only absolute numeric requirements are that if i= n, then the
+%% value computed from i.&amp;Delta; u+u 1 is exactly u 2, and if j= m, then the value
+%% computed from j.&amp;Delta; v+v 1 is exactly v 2.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml">external</a> documentation.
+-spec evalMesh1(Mode, I1, I2) -> ok when Mode :: enum(),I1 :: integer(),I2 :: integer().
+evalMesh1(Mode,I1,I2) ->
+ cast(5302, <<Mode:?GLenum,I1:?GLint,I2:?GLint>>).
-%% @spec (Size::integer(),Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml">external</a> documentation.
--spec vertexPointer(integer(),enum(),integer(),offset()|mem()) -> ok.
-vertexPointer(Size,Type,Stride,Pointer) when is_integer(Pointer) ->
- cast(5312, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
-vertexPointer(Size,Type,Stride,Pointer) ->
- send_bin(Pointer),
- cast(5313, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
+%% @doc
+%% See {@link evalMesh1/3}
+-spec evalMesh2(Mode, I1, I2, J1, J2) -> ok when Mode :: enum(),I1 :: integer(),I2 :: integer(),J1 :: integer(),J2 :: integer().
+evalMesh2(Mode,I1,I2,J1,J2) ->
+ cast(5303, <<Mode:?GLenum,I1:?GLint,I2:?GLint,J1:?GLint,J2:?GLint>>).
-%% @spec (X::integer(),Y::integer(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml">external</a> documentation.
--spec viewport(integer(),integer(),integer(),integer()) -> ok.
-viewport(X,Y,Width,Height) ->
- cast(5314, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
+%% @doc Specify fog parameters
+%%
+%% Fog is initially disabled. While enabled, fog affects rasterized geometry, bitmaps, and
+%% pixel blocks, but not buffer clear operations. To enable and disable fog, call {@link gl:enable/1}
+%% and {@link gl:enable/1} with argument `?GL_FOG'.
+%%
+%% ``gl:fog'' assigns the value or values in `Params' to the fog parameter specified
+%% by `Pname' . The following values are accepted for `Pname' :
+%%
+%% `?GL_FOG_MODE': `Params' is a single integer or floating-point value that specifies
+%% the equation to be used to compute the fog blend factor, f. Three symbolic constants
+%% are accepted: `?GL_LINEAR', `?GL_EXP', and `?GL_EXP2'. The equations corresponding
+%% to these symbolic constants are defined below. The initial fog mode is `?GL_EXP'.
+%%
+%% `?GL_FOG_DENSITY': `Params' is a single integer or floating-point value that
+%% specifies density, the fog density used in both exponential fog equations. Only nonnegative
+%% densities are accepted. The initial fog density is 1.
+%%
+%% `?GL_FOG_START': `Params' is a single integer or floating-point value that specifies
+%% start, the near distance used in the linear fog equation. The initial near distance
+%% is 0.
+%%
+%% `?GL_FOG_END': `Params' is a single integer or floating-point value that specifies
+%% end, the far distance used in the linear fog equation. The initial far distance is 1.
+%%
+%% `?GL_FOG_INDEX': `Params' is a single integer or floating-point value that specifies
+%% i f, the fog color index. The initial fog index is 0.
+%%
+%% `?GL_FOG_COLOR': `Params' contains four integer or floating-point values that
+%% specify C f, the fog color. Integer values are mapped linearly such that the most positive
+%% representable value maps to 1.0, and the most negative representable value maps to -1.0.
+%% Floating-point values are mapped directly. After conversion, all color components are
+%% clamped to the range [0 1]. The initial fog color is (0, 0, 0, 0).
+%%
+%% `?GL_FOG_COORD_SRC': `Params' contains either of the following symbolic constants:
+%% `?GL_FOG_COORD' or `?GL_FRAGMENT_DEPTH'. `?GL_FOG_COORD' specifies that
+%% the current fog coordinate should be used as distance value in the fog color computation.
+%% `?GL_FRAGMENT_DEPTH' specifies that the current fragment depth should be used as
+%% distance value in the fog computation.
+%%
+%% Fog blends a fog color with each rasterized pixel fragment's post-texturing color using
+%% a blending factor f. Factor f is computed in one of three ways, depending on the fog
+%% mode. Let c be either the distance in eye coordinate from the origin (in the case that
+%% the `?GL_FOG_COORD_SRC' is `?GL_FRAGMENT_DEPTH') or the current fog coordinate
+%% (in the case that `?GL_FOG_COORD_SRC' is `?GL_FOG_COORD'). The equation for `?GL_LINEAR'
+%% fog is f=(end-c)/(end-start)
+%%
+%% The equation for `?GL_EXP' fog is f= e(-(density. c))
+%%
+%% The equation for `?GL_EXP2' fog is f= e(-(density. c)) 2
+%%
+%% Regardless of the fog mode, f is clamped to the range [0 1] after it is computed. Then,
+%% if the GL is in RGBA color mode, the fragment's red, green, and blue colors, represented
+%% by C r, are replaced by
+%%
+%% (C r)"= f*C r+(1-f)*C f
+%%
+%% Fog does not affect a fragment's alpha component.
+%%
+%% In color index mode, the fragment's color index i r is replaced by
+%%
+%% (i r)"= i r+(1-f)*i f
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation.
+-spec fogf(Pname, Param) -> ok when Pname :: enum(),Param :: float().
+fogf(Pname,Param) ->
+ cast(5304, <<Pname:?GLenum,Param:?GLfloat>>).
+
+%% @doc
+%% See {@link fogf/2}
+-spec fogi(Pname, Param) -> ok when Pname :: enum(),Param :: integer().
+fogi(Pname,Param) ->
+ cast(5305, <<Pname:?GLenum,Param:?GLint>>).
+
+%% @doc
+%% See {@link fogf/2}
+-spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}.
+fogfv(Pname,Params) ->
+ cast(5306, <<Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
+
+%% @doc
+%% See {@link fogf/2}
+-spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}.
+fogiv(Pname,Params) ->
+ cast(5307, <<Pname:?GLenum,(size(Params)):?GLuint,
+ (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
+
+%% @doc Controls feedback mode
+%%
+%% The ``gl:feedbackBuffer'' function controls feedback. Feedback, like selection, is
+%% a GL mode. The mode is selected by calling {@link gl:renderMode/1} with `?GL_FEEDBACK'.
+%% When the GL is in feedback mode, no pixels are produced by rasterization. Instead, information
+%% about primitives that would have been rasterized is fed back to the application using
+%% the GL.
+%%
+%% ``gl:feedbackBuffer'' has three arguments: `Buffer' is a pointer to an array of
+%% floating-point values into which feedback information is placed. `Size' indicates
+%% the size of the array. `Type' is a symbolic constant describing the information that
+%% is fed back for each vertex. ``gl:feedbackBuffer'' must be issued before feedback mode
+%% is enabled (by calling {@link gl:renderMode/1} with argument `?GL_FEEDBACK'). Setting
+%% `?GL_FEEDBACK' without establishing the feedback buffer, or calling ``gl:feedbackBuffer''
+%% while the GL is in feedback mode, is an error.
+%%
+%% When {@link gl:renderMode/1} is called while in feedback mode, it returns the number of
+%% entries placed in the feedback array and resets the feedback array pointer to the base
+%% of the feedback buffer. The returned value never exceeds `Size' . If the feedback
+%% data required more room than was available in `Buffer' , {@link gl:renderMode/1} returns
+%% a negative value. To take the GL out of feedback mode, call {@link gl:renderMode/1} with
+%% a parameter value other than `?GL_FEEDBACK'.
+%%
+%% While in feedback mode, each primitive, bitmap, or pixel rectangle that would be rasterized
+%% generates a block of values that are copied into the feedback array. If doing so would
+%% cause the number of entries to exceed the maximum, the block is partially written so as
+%% to fill the array (if there is any room left at all), and an overflow flag is set. Each
+%% block begins with a code indicating the primitive type, followed by values that describe
+%% the primitive's vertices and associated data. Entries are also written for bitmaps and
+%% pixel rectangles. Feedback occurs after polygon culling and {@link gl:polygonMode/2} interpretation
+%% of polygons has taken place, so polygons that are culled are not returned in the feedback
+%% buffer. It can also occur after polygons with more than three edges are broken up into
+%% triangles, if the GL implementation renders polygons by performing this decomposition.
+%%
+%% The {@link gl:passThrough/1} command can be used to insert a marker into the feedback
+%% buffer. See {@link gl:passThrough/1} .
+%%
+%% Following is the grammar for the blocks of values written into the feedback buffer. Each
+%% primitive is indicated with a unique identifying value followed by some number of vertices.
+%% Polygon entries include an integer value indicating how many vertices follow. A vertex
+%% is fed back as some number of floating-point values, as determined by `Type' . Colors
+%% are fed back as four values in RGBA mode and one value in color index mode.
+%%
+%% feedbackList feedbackItem feedbackList | feedbackItem
+%%
+%% feedbackItem point | lineSegment | polygon | bitmap | pixelRectangle | passThru
+%%
+%% point `?GL_POINT_TOKEN' vertex
+%%
+%% lineSegment `?GL_LINE_TOKEN' vertex vertex | `?GL_LINE_RESET_TOKEN' vertex
+%% vertex
+%%
+%% polygon `?GL_POLYGON_TOKEN' n polySpec
+%%
+%% polySpec polySpec vertex | vertex vertex vertex
+%%
+%% bitmap `?GL_BITMAP_TOKEN' vertex
+%%
+%% pixelRectangle `?GL_DRAW_PIXEL_TOKEN' vertex | `?GL_COPY_PIXEL_TOKEN' vertex
+%%
+%% passThru `?GL_PASS_THROUGH_TOKEN' value
+%%
+%% vertex 2d | 3d | 3dColor | 3dColorTexture | 4dColorTexture
+%%
+%% 2d value value
+%%
+%% 3d value value value
+%%
+%% 3dColor value value value color
+%%
+%% 3dColorTexture value value value color tex
+%%
+%% 4dColorTexture value value value value color tex
+%%
+%% color rgba | index
+%%
+%% rgba value value value value
+%%
+%% index value
+%%
+%% tex value value value value
+%%
+%% `value' is a floating-point number, and `n' is a floating-point integer giving
+%% the number of vertices in the polygon. `?GL_POINT_TOKEN', `?GL_LINE_TOKEN', `?GL_LINE_RESET_TOKEN'
+%% , `?GL_POLYGON_TOKEN', `?GL_BITMAP_TOKEN', `?GL_DRAW_PIXEL_TOKEN', `?GL_COPY_PIXEL_TOKEN'
+%% and `?GL_PASS_THROUGH_TOKEN' are symbolic floating-point constants. `?GL_LINE_RESET_TOKEN'
+%% is returned whenever the line stipple pattern is reset. The data returned as a vertex
+%% depends on the feedback `Type' .
+%%
+%% The following table gives the correspondence between `Type' and the number of values
+%% per vertex. `k' is 1 in color index mode and 4 in RGBA mode.
+%%
+%% <table><tbody><tr><td>` Type '</td><td>` Coordinates '</td><td>` Color '</td>
+%% <td>` Texture '</td><td>` Total Number of Values '</td></tr></tbody><tbody><tr><td>
+%% `?GL_2D'</td><td>`x', `y'</td><td></td><td></td><td> 2 </td></tr><tr><td>`?GL_3D'
+%% </td><td>`x', `y', `z'</td><td></td><td></td><td> 3 </td></tr><tr><td>`?GL_3D_COLOR'
+%% </td><td>`x', `y', `z'</td><td> k</td><td></td><td> 3+k</td></tr><tr><td>`?GL_3D_COLOR_TEXTURE'
+%% </td><td>`x', `y', `z'</td><td> k</td><td> 4 </td><td> 7+k</td></tr><tr><td>
+%% `?GL_4D_COLOR_TEXTURE'</td><td>`x', `y', `z', `w'</td><td> k</td>
+%% <td> 4 </td><td> 8+k</td></tr></tbody></table>
+%%
+%% Feedback vertex coordinates are in window coordinates, except `w', which is in clip
+%% coordinates. Feedback colors are lighted, if lighting is enabled. Feedback texture coordinates
+%% are generated, if texture coordinate generation is enabled. They are always transformed
+%% by the texture matrix.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFeedbackBuffer.xml">external</a> documentation.
+-spec feedbackBuffer(Size, Type, Buffer) -> ok when Size :: integer(),Type :: enum(),Buffer :: mem().
+feedbackBuffer(Size,Type,Buffer) ->
+ send_bin(Buffer),
+ call(5308, <<Size:?GLsizei,Type:?GLenum>>).
+
+%% @doc Place a marker in the feedback buffer
+%%
+%% Feedback is a GL render mode. The mode is selected by calling {@link gl:renderMode/1}
+%% with `?GL_FEEDBACK'. When the GL is in feedback mode, no pixels are produced by rasterization.
+%% Instead, information about primitives that would have been rasterized is fed back to the
+%% application using the GL. See the {@link gl:feedbackBuffer/3} reference page for a description
+%% of the feedback buffer and the values in it.
+%%
+%% ``gl:passThrough'' inserts a user-defined marker in the feedback buffer when it is executed
+%% in feedback mode. `Token' is returned as if it were a primitive; it is indicated
+%% with its own unique identifying value: `?GL_PASS_THROUGH_TOKEN'. The order of ``gl:passThrough''
+%% commands with respect to the specification of graphics primitives is maintained.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPassThrough.xml">external</a> documentation.
+-spec passThrough(Token) -> ok when Token :: float().
+passThrough(Token) ->
+ cast(5309, <<Token:?GLfloat>>).
-%% @spec (Red::clamp(),Green::clamp(),Blue::clamp(),Alpha::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendColor.xml">external</a> documentation.
--spec blendColor(clamp(),clamp(),clamp(),clamp()) -> ok.
+%% @doc Establish a buffer for selection mode values
+%%
+%% ``gl:selectBuffer'' has two arguments: `Buffer' is a pointer to an array of unsigned
+%% integers, and `Size' indicates the size of the array. `Buffer' returns values
+%% from the name stack (see {@link gl:initNames/0} , {@link gl:loadName/1} , {@link gl:pushName/1} )
+%% when the rendering mode is `?GL_SELECT' (see {@link gl:renderMode/1} ). ``gl:selectBuffer''
+%% must be issued before selection mode is enabled, and it must not be issued while the
+%% rendering mode is `?GL_SELECT'.
+%%
+%% A programmer can use selection to determine which primitives are drawn into some region
+%% of a window. The region is defined by the current modelview and perspective matrices.
+%%
+%% In selection mode, no pixel fragments are produced from rasterization. Instead, if a
+%% primitive or a raster position intersects the clipping volume defined by the viewing frustum
+%% and the user-defined clipping planes, this primitive causes a selection hit. (With polygons,
+%% no hit occurs if the polygon is culled.) When a change is made to the name stack, or when
+%% {@link gl:renderMode/1} is called, a hit record is copied to `Buffer' if any hits
+%% have occurred since the last such event (name stack change or {@link gl:renderMode/1} call).
+%% The hit record consists of the number of names in the name stack at the time of the event,
+%% followed by the minimum and maximum depth values of all vertices that hit since the previous
+%% event, followed by the name stack contents, bottom name first.
+%%
+%% Depth values (which are in the range [0,1]) are multiplied by 2 32-1, before being
+%% placed in the hit record.
+%%
+%% An internal index into `Buffer' is reset to 0 whenever selection mode is entered.
+%% Each time a hit record is copied into `Buffer' , the index is incremented to point
+%% to the cell just past the end of the block of names(emthat is, to the next available cell
+%% If the hit record is larger than the number of remaining locations in `Buffer' , as
+%% much data as can fit is copied, and the overflow flag is set. If the name stack is empty
+%% when a hit record is copied, that record consists of 0 followed by the minimum and maximum
+%% depth values.
+%%
+%% To exit selection mode, call {@link gl:renderMode/1} with an argument other than `?GL_SELECT'
+%% . Whenever {@link gl:renderMode/1} is called while the render mode is `?GL_SELECT',
+%% it returns the number of hit records copied to `Buffer' , resets the overflow flag
+%% and the selection buffer pointer, and initializes the name stack to be empty. If the overflow
+%% bit was set when {@link gl:renderMode/1} was called, a negative hit record count is returned.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml">external</a> documentation.
+-spec selectBuffer(Size, Buffer) -> ok when Size :: integer(),Buffer :: mem().
+selectBuffer(Size,Buffer) ->
+ send_bin(Buffer),
+ call(5310, <<Size:?GLsizei>>).
+
+%% @doc Initialize the name stack
+%%
+%% The name stack is used during selection mode to allow sets of rendering commands to be
+%% uniquely identified. It consists of an ordered set of unsigned integers. ``gl:initNames''
+%% causes the name stack to be initialized to its default empty state.
+%%
+%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:initNames''
+%% while the render mode is not `?GL_SELECT' are ignored.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInitNames.xml">external</a> documentation.
+-spec initNames() -> ok.
+initNames() ->
+ cast(5311, <<>>).
+
+%% @doc Load a name onto the name stack
+%%
+%% The name stack is used during selection mode to allow sets of rendering commands to be
+%% uniquely identified. It consists of an ordered set of unsigned integers and is initially
+%% empty.
+%%
+%% ``gl:loadName'' causes `Name' to replace the value on the top of the name stack.
+%%
+%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:loadName''
+%% while the render mode is not `?GL_SELECT' are ignored.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadName.xml">external</a> documentation.
+-spec loadName(Name) -> ok when Name :: integer().
+loadName(Name) ->
+ cast(5312, <<Name:?GLuint>>).
+
+%% @doc Push and pop the name stack
+%%
+%% The name stack is used during selection mode to allow sets of rendering commands to be
+%% uniquely identified. It consists of an ordered set of unsigned integers and is initially
+%% empty.
+%%
+%% ``gl:pushName'' causes `Name' to be pushed onto the name stack. {@link gl:pushName/1}
+%% pops one name off the top of the stack.
+%%
+%% The maximum name stack depth is implementation-dependent; call `?GL_MAX_NAME_STACK_DEPTH'
+%% to find out the value for a particular implementation. It is an error to push a name
+%% onto a full stack or to pop a name off an empty stack. It is also an error to manipulate
+%% the name stack between the execution of {@link gl:'begin'/1} and the corresponding execution
+%% of {@link gl:'begin'/1} . In any of these cases, the error flag is set and no other change is
+%% made to GL state.
+%%
+%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:pushName''
+%% or {@link gl:pushName/1} while the render mode is not `?GL_SELECT' are ignored.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml">external</a> documentation.
+-spec pushName(Name) -> ok when Name :: integer().
+pushName(Name) ->
+ cast(5313, <<Name:?GLuint>>).
+
+%% @doc
+%% See {@link pushName/1}
+-spec popName() -> ok.
+popName() ->
+ cast(5314, <<>>).
+
+%% @doc Set the blend color
+%%
+%% The `?GL_BLEND_COLOR' may be used to calculate the source and destination blending
+%% factors. The color components are clamped to the range [0 1] before being stored. See {@link gl:blendFunc/2}
+%% for a complete description of the blending operations. Initially the `?GL_BLEND_COLOR'
+%% is set to (0, 0, 0, 0).
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendColor.xml">external</a> documentation.
+-spec blendColor(Red, Green, Blue, Alpha) -> ok when Red :: clamp(),Green :: clamp(),Blue :: clamp(),Alpha :: clamp().
blendColor(Red,Green,Blue,Alpha) ->
cast(5315, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml">external</a> documentation.
--spec blendEquation(enum()) -> ok.
+%% @doc Specify the equation used for both the RGB blend equation and the Alpha blend equation
+%%
+%% The blend equations determine how a new pixel (the ''source'' color) is combined with
+%% a pixel already in the framebuffer (the ''destination'' color). This function sets both
+%% the RGB blend equation and the alpha blend equation to a single equation. ``gl:blendEquationi''
+%% specifies the blend equation for a single draw buffer whereas ``gl:blendEquation''
+%% sets the blend equation for all draw buffers.
+%%
+%% These equations use the source and destination blend factors specified by either {@link gl:blendFunc/2}
+%% or {@link gl:blendFuncSeparate/4} . See {@link gl:blendFunc/2} or {@link gl:blendFuncSeparate/4}
+%% for a description of the various blend factors.
+%%
+%% In the equations that follow, source and destination color components are referred to
+%% as (R s G s B s A s) and (R d G d B d A d), respectively. The result color is referred to as (R r G r B r A r). The source and destination
+%% blend factors are denoted (s R s G s B s A) and (d R d G d B d A), respectively. For these equations all color components
+%% are understood to have values in the range [0 1]. <table><tbody><tr><td>` Mode '</td><td>
+%% ` RGB Components '</td><td>` Alpha Component '</td></tr></tbody><tbody><tr><td>`?GL_FUNC_ADD'
+%% </td><td> Rr= R s s R+R d d R Gr= G s s G+G d d G Br= B s s B+B d d B</td><td> Ar=
+%% A s s A+A d d A</td></tr><tr><td>`?GL_FUNC_SUBTRACT'</td><td> Rr= R s s R-R d d
+%% R Gr= G s s G-G d d G Br= B s s B-B d d B</td><td> Ar= A s s A-A d d A</td></tr><tr>
+%% <td>`?GL_FUNC_REVERSE_SUBTRACT'</td><td> Rr= R d d R-R s s R Gr= G d d G-G s s G
+%% Br= B d d B-B s s B</td><td> Ar= A d d A-A s s A</td></tr><tr><td>`?GL_MIN'</td><td>
+%% Rr= min(R s R d) Gr= min(G s G d) Br= min(B s B d)</td><td> Ar= min(A s A d)</td></tr><tr><td>`?GL_MAX'</td><td> Rr=
+%% max(R s R d) Gr= max(G s G d) Br= max(B s B d)</td><td> Ar= max(A s A d)</td></tr></tbody></table>
+%%
+%% The results of these equations are clamped to the range [0 1].
+%%
+%% The `?GL_MIN' and `?GL_MAX' equations are useful for applications that analyze
+%% image data (image thresholding against a constant color, for example). The `?GL_FUNC_ADD'
+%% equation is useful for antialiasing and transparency, among other things.
+%%
+%% Initially, both the RGB blend equation and the alpha blend equation are set to `?GL_FUNC_ADD'
+%% .
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml">external</a> documentation.
+-spec blendEquation(Mode) -> ok when Mode :: enum().
blendEquation(Mode) ->
cast(5316, <<Mode:?GLenum>>).
-%% @spec (Mode::enum(),Start::integer(),End::integer(),Count::integer(),Type::enum(),Indices::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElements.xml">external</a> documentation.
--spec drawRangeElements(enum(),integer(),integer(),integer(),enum(),offset()|mem()) -> ok.
+%% @doc Render primitives from array data
+%%
+%% ``gl:drawRangeElements'' is a restricted form of {@link gl:drawElements/4} . `Mode' ,
+%% `Start' , `End' , and `Count' match the corresponding arguments to {@link gl:drawElements/4}
+%% , with the additional constraint that all values in the arrays `Count' must lie between
+%% `Start' and `End' , inclusive.
+%%
+%% Implementations denote recommended maximum amounts of vertex and index data, which may
+%% be queried by calling {@link gl:getBooleanv/1} with argument `?GL_MAX_ELEMENTS_VERTICES' and `?GL_MAX_ELEMENTS_INDICES'
+%% . If end-start+1 is greater than the value of `?GL_MAX_ELEMENTS_VERTICES', or if `Count'
+%% is greater than the value of `?GL_MAX_ELEMENTS_INDICES', then the call may operate
+%% at reduced performance. There is no requirement that all vertices in the range [start end] be referenced.
+%% However, the implementation may partially process unused vertices, reducing performance
+%% from what could be achieved with an optimal index set.
+%%
+%% When ``gl:drawRangeElements'' is called, it uses `Count' sequential elements from
+%% an enabled array, starting at `Start' to construct a sequence of geometric primitives.
+%% `Mode' specifies what kind of primitives are constructed, and how the array elements
+%% construct these primitives. If more than one array is enabled, each is used.
+%%
+%% Vertex attributes that are modified by ``gl:drawRangeElements'' have an unspecified
+%% value after ``gl:drawRangeElements'' returns. Attributes that aren't modified maintain
+%% their previous values.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElements.xml">external</a> documentation.
+-spec drawRangeElements(Mode, Start, End, Count, Type, Indices) -> ok when Mode :: enum(),Start :: integer(),End :: integer(),Count :: integer(),Type :: enum(),Indices :: offset()|mem().
drawRangeElements(Mode,Start,End,Count,Type,Indices) when is_integer(Indices) ->
cast(5317, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>);
drawRangeElements(Mode,Start,End,Count,Type,Indices) ->
send_bin(Indices),
cast(5318, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum>>).
-%% @spec (Target::enum(),Level::integer(),Internalformat::integer(),Width::integer(),Height::integer(),Depth::integer(),Border::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml">external</a> documentation.
--spec texImage3D(enum(),integer(),integer(),integer(),integer(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
-texImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,Format,Type,Pixels) when is_integer(Pixels) ->
- cast(5319, <<Target:?GLenum,Level:?GLint,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
-texImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,Format,Type,Pixels) ->
+%% @doc Specify a three-dimensional texture image
+%%
+%% Texturing maps a portion of a specified texture image onto each graphical primitive for
+%% which texturing is enabled. To enable and disable three-dimensional texturing, call {@link gl:enable/1}
+%% and {@link gl:enable/1} with argument `?GL_TEXTURE_3D'.
+%%
+%% To define texture images, call ``gl:texImage3D''. The arguments describe the parameters
+%% of the texture image, such as height, width, depth, width of the border, level-of-detail
+%% number (see {@link gl:texParameterf/3} ), and number of color components provided. The last
+%% three arguments describe how the image is represented in memory.
+%%
+%% If `Target' is `?GL_PROXY_TEXTURE_3D', no data is read from `Data' , but
+%% all of the texture image state is recalculated, checked for consistency, and checked against
+%% the implementation's capabilities. If the implementation cannot handle a texture of the
+%% requested texture size, it sets all of the image state to 0, but does not generate an
+%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
+%% level greater than or equal to 1.
+%%
+%% If `Target' is `?GL_TEXTURE_3D', data is read from `Data' as a sequence
+%% of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values,
+%% depending on `Type' . These values are grouped into sets of one, two, three, or four
+%% values, depending on `Format' , to form elements. Each data byte is treated as eight
+%% 1-bit elements, with bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2}
+%% ).
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% The first element corresponds to the lower left corner of the texture image. Subsequent
+%% elements progress left-to-right through the remaining texels in the lowest row of the
+%% texture image, and then in successively higher rows of the texture image. The final element
+%% corresponds to the upper right corner of the texture image.
+%%
+%% `Format' determines the composition of each element in `Data' . It can assume
+%% one of these symbolic values:
+%%
+%% `?GL_RED': Each element is a single red component. The GL converts it to floating
+%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for
+%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE',
+%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
+%%
+%% `?GL_RG': Each element is a red and green pair. The GL converts each to floating
+%% point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha.
+%% Each component is then multiplied by the signed scale factor `?GL_c_SCALE', added
+%% to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
+%%
+%% `?GL_RGB'
+%%
+%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and
+%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied
+%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
+%% and clamped to the range [0,1].
+%%
+%% `?GL_RGBA'
+%%
+%% `?GL_BGRA': Each element contains all four components. Each component is multiplied
+%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
+%% and clamped to the range [0,1].
+%%
+%% If an application wants to store the texture at a certain resolution or in a certain
+%% format, it can request the resolution and format with `InternalFormat' . The GL will
+%% choose an internal representation that closely approximates that requested by `InternalFormat'
+%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG'
+%% , `?GL_RGB', and `?GL_RGBA' must match exactly.)
+%%
+%% `InternalFormat' may be one of the base internal formats shown in Table 1, below
+%%
+%% `InternalFormat' may also be one of the sized internal formats shown in Table 2,
+%% below
+%%
+%% Finally, `InternalFormat' may also be one of the generic or compressed compressed
+%% texture formats shown in Table 3 below
+%%
+%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED'
+%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA',
+%% the GL will replace the internal format with the symbolic constant for a specific internal
+%% format and compress the texture before storage. If no corresponding internal format is
+%% available, or the GL can not compress that image for any reason, the internal format is
+%% instead replaced with a corresponding base internal format.
+%%
+%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA'
+%% , or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, blue, or
+%% luminance components are encoded in the sRGB color space. Any alpha component is left
+%% unchanged. The conversion from the sRGB encoded component c s to a linear component
+%% c l is:
+%%
+%% c l={ c s/12.92if c s&amp;le; 0.04045( c s+0.055/1.055) 2.4if c s&gt; 0.04045
+%%
+%% Assume c s is the sRGB component in the range [0,1].
+%%
+%% Use the `?GL_PROXY_TEXTURE_3D' target to try out a resolution and format. The implementation
+%% will update and recompute its best match for the requested storage resolution and format.
+%% To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture cannot
+%% be accommodated, texture state is set to 0.
+%%
+%% A one-component texture image uses only the red component of the RGBA color extracted
+%% from `Data' . A two-component image uses the R and A values. A three-component image
+%% uses the R, G, and B values. A four-component image uses all of the RGBA components.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml">external</a> documentation.
+-spec texImage3D(Target, Level, InternalFormat, Width, Height, Depth, Border, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
+texImage3D(Target,Level,InternalFormat,Width,Height,Depth,Border,Format,Type,Pixels) when is_integer(Pixels) ->
+ cast(5319, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
+texImage3D(Target,Level,InternalFormat,Width,Height,Depth,Border,Format,Type,Pixels) ->
send_bin(Pixels),
- cast(5320, <<Target:?GLenum,Level:?GLint,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum>>).
+ cast(5320, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Yoffset::integer(),Zoffset::integer(),Width::integer(),Height::integer(),Depth::integer(),Format::enum(),Type::enum(),Pixels::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage3D.xml">external</a> documentation.
--spec texSubImage3D(enum(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc glTexSubImage
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation.
+-spec texSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, Width, Height, Depth, Format, Type, Pixels) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5321, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
texSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,Type,Pixels) ->
send_bin(Pixels),
cast(5322, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Yoffset::integer(),Zoffset::integer(),X::integer(),Y::integer(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage3D.xml">external</a> documentation.
--spec copyTexSubImage3D(enum(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc Copy a three-dimensional texture subimage
+%%
+%% ``gl:copyTexSubImage3D'' replaces a rectangular portion of a three-dimensional texture
+%% image with pixels from the current `?GL_READ_BUFFER' (rather than from main memory,
+%% as is the case for {@link gl:texSubImage1D/7} ).
+%%
+%% The screen-aligned pixel rectangle with lower left corner at ( `X' , `Y' ) and
+%% with width `Width' and height `Height' replaces the portion of the texture array
+%% with x indices `Xoffset' through xoffset+width-1, inclusive, and y indices `Yoffset'
+%% through yoffset+height-1, inclusive, at z index `Zoffset' and at the mipmap level
+%% specified by `Level' .
+%%
+%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
+%% called, but the process stops just before final conversion. At this point, all pixel component
+%% values are clamped to the range [0 1] and then converted to the texture's internal format
+%% for storage in the texel array.
+%%
+%% The destination rectangle in the texture array may not include any texels outside the
+%% texture array as it was originally specified. It is not an error to specify a subtexture
+%% with zero width or height, but such a specification has no effect.
+%%
+%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER'
+%% are outside the read window associated with the current rendering context, then the values
+%% obtained for those pixels are undefined.
+%%
+%% No change is made to the `internalformat', `width', `height', `depth',
+%% or `border' parameters of the specified texture array or to texel values outside
+%% the specified subregion.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage3D.xml">external</a> documentation.
+-spec copyTexSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, X, Y, Width, Height) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
copyTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,X,Y,Width,Height) ->
cast(5323, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (Target::enum(),Internalformat::enum(),Width::integer(),Format::enum(),Type::enum(),Table::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTable.xml">external</a> documentation.
--spec colorTable(enum(),enum(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc Define a color lookup table
+%%
+%% ``gl:colorTable'' may be used in two ways: to test the actual size and color resolution
+%% of a lookup table given a particular set of parameters, or to load the contents of a color
+%% lookup table. Use the targets `?GL_PROXY_*' for the first case and the other targets
+%% for the second case.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a color table is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% If `Target' is `?GL_COLOR_TABLE', `?GL_POST_CONVOLUTION_COLOR_TABLE', or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'
+%% , ``gl:colorTable'' builds a color lookup table from an array of pixels. The pixel array
+%% specified by `Width' , `Format' , `Type' , and `Data' is extracted from
+%% memory and processed just as if {@link gl:drawPixels/5} were called, but processing stops
+%% after the final expansion to RGBA is completed.
+%%
+%% The four scale parameters and the four bias parameters that are defined for the table
+%% are then used to scale and bias the R, G, B, and A components of each pixel. (Use ``gl:colorTableParameter''
+%% to set these scale and bias parameters.)
+%%
+%% Next, the R, G, B, and A values are clamped to the range [0 1]. Each pixel is then converted
+%% to the internal format specified by `Internalformat' . This conversion simply maps
+%% the component values of the pixel (R, G, B, and A) to the values included in the internal
+%% format (red, green, blue, alpha, luminance, and intensity). The mapping is as follows:
+%%
+%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
+%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
+%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
+%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
+%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
+%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
+%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
+%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%% Finally, the red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in the color table. They form a one-dimensional table with indices in
+%% the range [0 width-1].
+%%
+%% If `Target' is `?GL_PROXY_*', ``gl:colorTable'' recomputes and stores the
+%% values of the proxy color table's state variables `?GL_COLOR_TABLE_FORMAT', `?GL_COLOR_TABLE_WIDTH'
+%% , `?GL_COLOR_TABLE_RED_SIZE', `?GL_COLOR_TABLE_GREEN_SIZE', `?GL_COLOR_TABLE_BLUE_SIZE'
+%% , `?GL_COLOR_TABLE_ALPHA_SIZE', `?GL_COLOR_TABLE_LUMINANCE_SIZE', and `?GL_COLOR_TABLE_INTENSITY_SIZE'
+%% . There is no effect on the image or state of any actual color table. If the specified
+%% color table is too large to be supported, then all the proxy state variables listed above
+%% are set to zero. Otherwise, the color table could be supported by ``gl:colorTable''
+%% using the corresponding non-proxy target, and the proxy state variables are set as if
+%% that target were being defined.
+%%
+%% The proxy state variables can be retrieved by calling {@link gl:getColorTableParameterfv/2}
+%% with a target of `?GL_PROXY_*'. This allows the application to decide if a particular
+%% ``gl:colorTable'' command would succeed, and to determine what the resulting color table
+%% attributes would be.
+%%
+%% If a color table is enabled, and its width is non-zero, then its contents are used to
+%% replace a subset of the components of each RGBA pixel group, based on the internal format
+%% of the table.
+%%
+%% Each pixel group has color components (R, G, B, A) that are in the range [0.0 1.0]. The color
+%% components are rescaled to the size of the color lookup table to form an index. Then a
+%% subset of the components based on the internal format of the table are replaced by the
+%% table entry selected by that index. If the color components and contents of the table
+%% are represented as follows:
+%%
+%% <table><tbody><tr><td>` Representation '</td><td>` Meaning '</td></tr></tbody><tbody>
+%% <tr><td>r</td><td> Table index computed from R</td></tr><tr><td>g</td><td> Table index
+%% computed from G</td></tr><tr><td>b</td><td> Table index computed from B</td></tr><tr><td>a
+%% </td><td> Table index computed from A</td></tr><tr><td>L[i]</td><td> Luminance value at
+%% table index i</td></tr><tr><td>I[i]</td><td> Intensity value at table index i</td></tr><tr>
+%% <td>R[i]</td><td> Red value at table index i</td></tr><tr><td>G[i]</td><td> Green value
+%% at table index i</td></tr><tr><td>B[i]</td><td> Blue value at table index i</td></tr><tr><td>
+%% A[i]</td><td> Alpha value at table index i</td></tr></tbody></table>
+%%
+%% then the result of color table lookup is as follows:
+%%
+%% <table><tbody><tr><td></td><td>` Resulting Texture Components '</td></tr><tr><td>` Table Internal Format '
+%% </td><td>` R '</td><td>` G '</td><td>` B '</td><td>` A '</td></tr></tbody>
+%% <tbody><tr><td>`?GL_ALPHA'</td><td>R</td><td>G</td><td>B</td><td>A[a]</td></tr><tr><td>
+%% `?GL_LUMINANCE'</td><td>L[r]</td><td>L[g]</td><td>L[b]</td><td>At</td></tr><tr><td>`?GL_LUMINANCE_ALPHA'
+%% </td><td>L[r]</td><td>L[g]</td><td>L[b]</td><td>A[a]</td></tr><tr><td>`?GL_INTENSITY'</td>
+%% <td>I[r]</td><td>I[g]</td><td>I[b]</td><td>I[a]</td></tr><tr><td>`?GL_RGB'</td><td>R[r]
+%% </td><td>G[g]</td><td>B[b]</td><td>A</td></tr><tr><td>`?GL_RGBA'</td><td>R[r]</td><td>
+%% G[g]</td><td>B[b]</td><td>A[a]</td></tr></tbody></table>
+%%
+%% When `?GL_COLOR_TABLE' is enabled, the colors resulting from the pixel map operation
+%% (if it is enabled) are mapped by the color lookup table before being passed to the convolution
+%% operation. The colors resulting from the convolution operation are modified by the post
+%% convolution color lookup table when `?GL_POST_CONVOLUTION_COLOR_TABLE' is enabled.
+%% These modified colors are then sent to the color matrix operation. Finally, if `?GL_POST_COLOR_MATRIX_COLOR_TABLE'
+%% is enabled, the colors resulting from the color matrix operation are mapped by the post
+%% color matrix color lookup table before being used by the histogram operation.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTable.xml">external</a> documentation.
+-spec colorTable(Target, Internalformat, Width, Format, Type, Table) -> ok when Target :: enum(),Internalformat :: enum(),Width :: integer(),Format :: enum(),Type :: enum(),Table :: offset()|mem().
colorTable(Target,Internalformat,Width,Format,Type,Table) when is_integer(Table) ->
cast(5324, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Table:?GLuint>>);
colorTable(Target,Internalformat,Width,Format,Type,Table) ->
send_bin(Table),
cast(5325, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml">external</a> documentation.
--spec colorTableParameterfv(enum(),enum(),{float(),float(),float(),float()}) -> ok.
+%% @doc Set color lookup table parameters
+%%
+%% ``gl:colorTableParameter'' is used to specify the scale factors and bias terms applied
+%% to color components when they are loaded into a color table. `Target' indicates which
+%% color table the scale and bias terms apply to; it must be set to `?GL_COLOR_TABLE', `?GL_POST_CONVOLUTION_COLOR_TABLE'
+%% , or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'.
+%%
+%% `Pname' must be `?GL_COLOR_TABLE_SCALE' to set the scale factors. In this case,
+%% `Params' points to an array of four values, which are the scale factors for red,
+%% green, blue, and alpha, in that order.
+%%
+%% `Pname' must be `?GL_COLOR_TABLE_BIAS' to set the bias terms. In this case, `Params'
+%% points to an array of four values, which are the bias terms for red, green, blue, and
+%% alpha, in that order.
+%%
+%% The color tables themselves are specified by calling {@link gl:colorTable/6} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml">external</a> documentation.
+-spec colorTableParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float(),float(),float(),float()}.
colorTableParameterfv(Target,Pname,{P1,P2,P3,P4}) ->
cast(5326, <<Target:?GLenum,Pname:?GLenum,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml">external</a> documentation.
--spec colorTableParameteriv(enum(),enum(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link colorTableParameterfv/3}
+-spec colorTableParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer(),integer(),integer(),integer()}.
colorTableParameteriv(Target,Pname,{P1,P2,P3,P4}) ->
cast(5327, <<Target:?GLenum,Pname:?GLenum,P1:?GLint,P2:?GLint,P3:?GLint,P4:?GLint>>).
-%% @spec (Target::enum(),Internalformat::enum(),X::integer(),Y::integer(),Width::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorTable.xml">external</a> documentation.
--spec copyColorTable(enum(),enum(),integer(),integer(),integer()) -> ok.
+%% @doc Copy pixels into a color table
+%%
+%% ``gl:copyColorTable'' loads a color table with pixels from the current `?GL_READ_BUFFER'
+%% (rather than from main memory, as is the case for {@link gl:colorTable/6} ).
+%%
+%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ) having
+%% width `Width' and height 1 is loaded into the color table. If any pixels within this
+%% region are outside the window that is associated with the GL context, the values obtained
+%% for those pixels are undefined.
+%%
+%% The pixels in the rectangle are processed just as if {@link gl:readPixels/7} were called,
+%% with `Internalformat' set to RGBA, but processing stops after the final conversion
+%% to RGBA.
+%%
+%% The four scale parameters and the four bias parameters that are defined for the table
+%% are then used to scale and bias the R, G, B, and A components of each pixel. The scale
+%% and bias parameters are set by calling {@link gl:colorTableParameterfv/3} .
+%%
+%% Next, the R, G, B, and A values are clamped to the range [0 1]. Each pixel is then converted
+%% to the internal format specified by `Internalformat' . This conversion simply maps
+%% the component values of the pixel (R, G, B, and A) to the values included in the internal
+%% format (red, green, blue, alpha, luminance, and intensity). The mapping is as follows:
+%%
+%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
+%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
+%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
+%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
+%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
+%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
+%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
+%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%% Finally, the red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in the color table. They form a one-dimensional table with indices in
+%% the range [0 width-1].
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorTable.xml">external</a> documentation.
+-spec copyColorTable(Target, Internalformat, X, Y, Width) -> ok when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer().
copyColorTable(Target,Internalformat,X,Y,Width) ->
cast(5328, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei>>).
-%% @spec (Target::enum(),Format::enum(),Type::enum(),Table::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTable.xml">external</a> documentation.
--spec getColorTable(enum(),enum(),enum(),mem()) -> ok.
+%% @doc Retrieve contents of a color lookup table
+%%
+%% ``gl:getColorTable'' returns in `Table' the contents of the color table specified
+%% by `Target' . No pixel transfer operations are performed, but pixel storage modes
+%% that are applicable to {@link gl:readPixels/7} are performed.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a histogram table is requested, `Table' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% Color components that are requested in the specified `Format' , but which are not
+%% included in the internal format of the color lookup table, are returned as zero. The assignments
+%% of internal color components to the components requested by `Format' are <table><tbody>
+%% <tr><td>` Internal Component '</td><td>` Resulting Component '</td></tr></tbody>
+%% <tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td></tr><tr><td>
+%% Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> Luminance
+%% </td><td> Red </td></tr><tr><td> Intensity </td><td> Red </td></tr></tbody></table>
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTable.xml">external</a> documentation.
+-spec getColorTable(Target, Format, Type, Table) -> ok when Target :: enum(),Format :: enum(),Type :: enum(),Table :: mem().
getColorTable(Target,Format,Type,Table) ->
send_bin(Table),
call(5329, <<Target:?GLenum,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml">external</a> documentation.
--spec getColorTableParameterfv(enum(),enum()) -> {float(),float(),float(),float()}.
+%% @doc Get color lookup table parameters
+%%
+%% Returns parameters specific to color table `Target' .
+%%
+%% When `Pname' is set to `?GL_COLOR_TABLE_SCALE' or `?GL_COLOR_TABLE_BIAS',
+%% ``gl:getColorTableParameter'' returns the color table scale or bias parameters for the
+%% table specified by `Target' . For these queries, `Target' must be set to `?GL_COLOR_TABLE'
+%% , `?GL_POST_CONVOLUTION_COLOR_TABLE', or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'
+%% and `Params' points to an array of four elements, which receive the scale or bias
+%% factors for red, green, blue, and alpha, in that order.
+%%
+%% ``gl:getColorTableParameter'' can also be used to retrieve the format and size parameters
+%% for a color table. For these queries, set `Target' to either the color table target
+%% or the proxy color table target. The format and size parameters are set by {@link gl:colorTable/6}
+%% .
+%%
+%% The following table lists the format and size parameters that may be queried. For each
+%% symbolic constant listed below for `Pname' , `Params' must point to an array
+%% of the given length and receive the values indicated.
+%%
+%% <table><tbody><tr><td>` Parameter '</td><td>` N '</td><td>` Meaning '</td></tr>
+%% </tbody><tbody><tr><td>`?GL_COLOR_TABLE_FORMAT'</td><td> 1 </td><td> Internal format
+%% (e.g., `?GL_RGBA') </td></tr><tr><td>`?GL_COLOR_TABLE_WIDTH'</td><td> 1 </td><td>
+%% Number of elements in table </td></tr><tr><td>`?GL_COLOR_TABLE_RED_SIZE'</td><td>
+%% 1 </td><td> Size of red component, in bits </td></tr><tr><td>`?GL_COLOR_TABLE_GREEN_SIZE'
+%% </td><td> 1 </td><td> Size of green component </td></tr><tr><td>`?GL_COLOR_TABLE_BLUE_SIZE'
+%% </td><td> 1 </td><td> Size of blue component </td></tr><tr><td>`?GL_COLOR_TABLE_ALPHA_SIZE'
+%% </td><td> 1 </td><td> Size of alpha component </td></tr><tr><td>`?GL_COLOR_TABLE_LUMINANCE_SIZE'
+%% </td><td> 1 </td><td> Size of luminance component </td></tr><tr><td>`?GL_COLOR_TABLE_INTENSITY_SIZE'
+%% </td><td> 1 </td><td> Size of intensity component </td></tr></tbody></table>
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml">external</a> documentation.
+-spec getColorTableParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
getColorTableParameterfv(Target,Pname) ->
call(5330, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml">external</a> documentation.
--spec getColorTableParameteriv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getColorTableParameterfv/2}
+-spec getColorTableParameteriv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
getColorTableParameteriv(Target,Pname) ->
call(5331, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Start::integer(),Count::integer(),Format::enum(),Type::enum(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorSubTable.xml">external</a> documentation.
--spec colorSubTable(enum(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc Respecify a portion of a color table
+%%
+%% ``gl:colorSubTable'' is used to respecify a contiguous portion of a color table previously
+%% defined using {@link gl:colorTable/6} . The pixels referenced by `Data' replace the
+%% portion of the existing table from indices `Start' to start+count-1, inclusive.
+%% This region may not include any entries outside the range of the color table as it was
+%% originally specified. It is not an error to specify a subtexture with width of 0, but
+%% such a specification has no effect.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a portion of a color table is respecified, `Data'
+%% is treated as a byte offset into the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorSubTable.xml">external</a> documentation.
+-spec colorSubTable(Target, Start, Count, Format, Type, Data) -> ok when Target :: enum(),Start :: integer(),Count :: integer(),Format :: enum(),Type :: enum(),Data :: offset()|mem().
colorSubTable(Target,Start,Count,Format,Type,Data) when is_integer(Data) ->
cast(5332, <<Target:?GLenum,Start:?GLsizei,Count:?GLsizei,Format:?GLenum,Type:?GLenum,Data:?GLuint>>);
colorSubTable(Target,Start,Count,Format,Type,Data) ->
send_bin(Data),
cast(5333, <<Target:?GLenum,Start:?GLsizei,Count:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Start::integer(),X::integer(),Y::integer(),Width::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorSubTable.xml">external</a> documentation.
--spec copyColorSubTable(enum(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc Respecify a portion of a color table
+%%
+%% ``gl:copyColorSubTable'' is used to respecify a contiguous portion of a color table
+%% previously defined using {@link gl:colorTable/6} . The pixels copied from the framebuffer
+%% replace the portion of the existing table from indices `Start' to start+x-1, inclusive.
+%% This region may not include any entries outside the range of the color table, as was originally
+%% specified. It is not an error to specify a subtexture with width of 0, but such a specification
+%% has no effect.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorSubTable.xml">external</a> documentation.
+-spec copyColorSubTable(Target, Start, X, Y, Width) -> ok when Target :: enum(),Start :: integer(),X :: integer(),Y :: integer(),Width :: integer().
copyColorSubTable(Target,Start,X,Y,Width) ->
cast(5334, <<Target:?GLenum,Start:?GLsizei,X:?GLint,Y:?GLint,Width:?GLsizei>>).
-%% @spec (Target::enum(),Internalformat::enum(),Width::integer(),Format::enum(),Type::enum(),Image::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter1D.xml">external</a> documentation.
--spec convolutionFilter1D(enum(),enum(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc Define a one-dimensional convolution filter
+%%
+%% ``gl:convolutionFilter1D'' builds a one-dimensional convolution filter kernel from an
+%% array of pixels.
+%%
+%% The pixel array specified by `Width' , `Format' , `Type' , and `Data'
+%% is extracted from memory and processed just as if {@link gl:drawPixels/5} were called,
+%% but processing stops after the final expansion to RGBA is completed.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Data' is
+%% treated as a byte offset into the buffer object's data store.
+%%
+%% The R, G, B, and A components of each pixel are next scaled by the four 1D `?GL_CONVOLUTION_FILTER_SCALE'
+%% parameters and biased by the four 1D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
+%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_1D'
+%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
+%% . The parameters themselves are vectors of four values that are applied to red, green,
+%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
+%% any time during this process.
+%%
+%% Each pixel is then converted to the internal format specified by `Internalformat' .
+%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
+%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
+%% The mapping is as follows:
+%%
+%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
+%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
+%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
+%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
+%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
+%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
+%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
+%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in floating-point rather than integer format. They form a one-dimensional
+%% filter kernel image indexed with coordinate `i' such that `i' starts at 0 and
+%% increases from left to right. Kernel location `i' is derived from the `i'th
+%% pixel, counting from 0.
+%%
+%% Note that after a convolution is performed, the resulting color components are also scaled
+%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
+%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
+%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
+%% set by {@link gl:pixelTransferf/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter1D.xml">external</a> documentation.
+-spec convolutionFilter1D(Target, Internalformat, Width, Format, Type, Image) -> ok when Target :: enum(),Internalformat :: enum(),Width :: integer(),Format :: enum(),Type :: enum(),Image :: offset()|mem().
convolutionFilter1D(Target,Internalformat,Width,Format,Type,Image) when is_integer(Image) ->
cast(5335, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Image:?GLuint>>);
convolutionFilter1D(Target,Internalformat,Width,Format,Type,Image) ->
send_bin(Image),
cast(5336, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Internalformat::enum(),Width::integer(),Height::integer(),Format::enum(),Type::enum(),Image::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter2D.xml">external</a> documentation.
--spec convolutionFilter2D(enum(),enum(),integer(),integer(),enum(),enum(),offset()|mem()) -> ok.
+%% @doc Define a two-dimensional convolution filter
+%%
+%% ``gl:convolutionFilter2D'' builds a two-dimensional convolution filter kernel from an
+%% array of pixels.
+%%
+%% The pixel array specified by `Width' , `Height' , `Format' , `Type' ,
+%% and `Data' is extracted from memory and processed just as if {@link gl:drawPixels/5}
+%% were called, but processing stops after the final expansion to RGBA is completed.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Data' is
+%% treated as a byte offset into the buffer object's data store.
+%%
+%% The R, G, B, and A components of each pixel are next scaled by the four 2D `?GL_CONVOLUTION_FILTER_SCALE'
+%% parameters and biased by the four 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
+%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_2D'
+%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
+%% . The parameters themselves are vectors of four values that are applied to red, green,
+%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
+%% any time during this process.
+%%
+%% Each pixel is then converted to the internal format specified by `Internalformat' .
+%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
+%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
+%% The mapping is as follows:
+%%
+%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
+%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
+%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
+%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
+%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
+%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
+%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
+%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in floating-point rather than integer format. They form a two-dimensional
+%% filter kernel image indexed with coordinates `i' and `j' such that `i'
+%% starts at zero and increases from left to right, and `j' starts at zero and increases
+%% from bottom to top. Kernel location `i,j' is derived from the `N'th pixel, where
+%% `N' is `i'+`j'* `Width' .
+%%
+%% Note that after a convolution is performed, the resulting color components are also scaled
+%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
+%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
+%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
+%% set by {@link gl:pixelTransferf/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter2D.xml">external</a> documentation.
+-spec convolutionFilter2D(Target, Internalformat, Width, Height, Format, Type, Image) -> ok when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Image :: offset()|mem().
convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) when is_integer(Image) ->
cast(5337, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Image:?GLuint>>);
convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) ->
send_bin(Image),
cast(5338, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation.
--spec convolutionParameterf(enum(),enum(),{float()}) -> ok.
+%% @doc Set convolution parameters
+%%
+%% ``gl:convolutionParameter'' sets the value of a convolution parameter.
+%%
+%% `Target' selects the convolution filter to be affected: `?GL_CONVOLUTION_1D', `?GL_CONVOLUTION_2D'
+%% , or `?GL_SEPARABLE_2D' for the 1D, 2D, or separable 2D filter, respectively.
+%%
+%% `Pname' selects the parameter to be changed. `?GL_CONVOLUTION_FILTER_SCALE'
+%% and `?GL_CONVOLUTION_FILTER_BIAS' affect the definition of the convolution filter
+%% kernel; see {@link gl:convolutionFilter1D/6} , {@link gl:convolutionFilter2D/7} , and {@link gl:separableFilter2D/8}
+%% for details. In these cases, `Params' v is an array of four values to be applied
+%% to red, green, blue, and alpha values, respectively. The initial value for `?GL_CONVOLUTION_FILTER_SCALE'
+%% is (1, 1, 1, 1), and the initial value for `?GL_CONVOLUTION_FILTER_BIAS' is (0,
+%% 0, 0, 0).
+%%
+%% A `Pname' value of `?GL_CONVOLUTION_BORDER_MODE' controls the convolution border
+%% mode. The accepted modes are:
+%%
+%% `?GL_REDUCE': The image resulting from convolution is smaller than the source image.
+%% If the filter width is Wf and height is Hf, and the source image width is Ws and
+%% height is Hs, then the convolved image width will be Ws-Wf+1 and height will be Hs-Hf
+%% +1. (If this reduction would generate an image with zero or negative width and/or height,
+%% the output is simply null, with no error generated.) The coordinates of the image resulting
+%% from convolution are zero through Ws-Wf in width and zero through Hs-Hf in height.
+%%
+%% `?GL_CONSTANT_BORDER': The image resulting from convolution is the same size as
+%% the source image, and processed as if the source image were surrounded by pixels with
+%% their color specified by the `?GL_CONVOLUTION_BORDER_COLOR'.
+%%
+%% `?GL_REPLICATE_BORDER': The image resulting from convolution is the same size as
+%% the source image, and processed as if the outermost pixel on the border of the source
+%% image were replicated.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation.
+-spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}.
convolutionParameterf(Target,Pname,Params) ->
cast(5339, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target,Pname,{Params}) -> ok
%% @equiv convolutionParameterf(Target,Pname,Params)
--spec convolutionParameterfv(enum(),enum(),{{float()}}) -> ok.
+-spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {float()}}.
convolutionParameterfv(Target,Pname,{Params}) -> convolutionParameterf(Target,Pname,Params).
-%% @spec (Target::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation.
--spec convolutionParameteri(enum(),enum(),{integer()}) -> ok.
+%% @doc
+%% See {@link convolutionParameterf/3}
+-spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
convolutionParameteri(Target,Pname,Params) ->
cast(5340, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target,Pname,{Params}) -> ok
%% @equiv convolutionParameteri(Target,Pname,Params)
--spec convolutionParameteriv(enum(),enum(),{{integer()}}) -> ok.
+-spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {integer()}}.
convolutionParameteriv(Target,Pname,{Params}) -> convolutionParameteri(Target,Pname,Params).
-%% @spec (Target::enum(),Internalformat::enum(),X::integer(),Y::integer(),Width::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter1D.xml">external</a> documentation.
--spec copyConvolutionFilter1D(enum(),enum(),integer(),integer(),integer()) -> ok.
+%% @doc Copy pixels into a one-dimensional convolution filter
+%%
+%% ``gl:copyConvolutionFilter1D'' defines a one-dimensional convolution filter kernel with
+%% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the
+%% case for {@link gl:convolutionFilter1D/6} ).
+%%
+%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ), width
+%% `Width' and height 1 is used to define the convolution filter. If any pixels within
+%% this region are outside the window that is associated with the GL context, the values
+%% obtained for those pixels are undefined.
+%%
+%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
+%% called with `format' set to RGBA, but the process stops just before final conversion.
+%% The R, G, B, and A components of each pixel are next scaled by the four 1D `?GL_CONVOLUTION_FILTER_SCALE'
+%% parameters and biased by the four 1D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
+%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_1D'
+%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
+%% . The parameters themselves are vectors of four values that are applied to red, green,
+%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
+%% any time during this process.
+%%
+%% Each pixel is then converted to the internal format specified by `Internalformat' .
+%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
+%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
+%% The mapping is as follows:
+%%
+%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
+%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
+%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
+%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
+%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
+%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
+%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
+%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in floating-point rather than integer format.
+%%
+%% Pixel ordering is such that lower x screen coordinates correspond to lower `i' filter
+%% image coordinates.
+%%
+%% Note that after a convolution is performed, the resulting color components are also scaled
+%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
+%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
+%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
+%% set by {@link gl:pixelTransferf/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter1D.xml">external</a> documentation.
+-spec copyConvolutionFilter1D(Target, Internalformat, X, Y, Width) -> ok when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer().
copyConvolutionFilter1D(Target,Internalformat,X,Y,Width) ->
cast(5341, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei>>).
-%% @spec (Target::enum(),Internalformat::enum(),X::integer(),Y::integer(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter2D.xml">external</a> documentation.
--spec copyConvolutionFilter2D(enum(),enum(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc Copy pixels into a two-dimensional convolution filter
+%%
+%% ``gl:copyConvolutionFilter2D'' defines a two-dimensional convolution filter kernel with
+%% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the
+%% case for {@link gl:convolutionFilter2D/7} ).
+%%
+%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ), width
+%% `Width' and height `Height' is used to define the convolution filter. If any
+%% pixels within this region are outside the window that is associated with the GL context,
+%% the values obtained for those pixels are undefined.
+%%
+%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
+%% called with `format' set to RGBA, but the process stops just before final conversion.
+%% The R, G, B, and A components of each pixel are next scaled by the four 2D `?GL_CONVOLUTION_FILTER_SCALE'
+%% parameters and biased by the four 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
+%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_2D'
+%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
+%% . The parameters themselves are vectors of four values that are applied to red, green,
+%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
+%% any time during this process.
+%%
+%% Each pixel is then converted to the internal format specified by `Internalformat' .
+%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
+%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
+%% The mapping is as follows:
+%%
+%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
+%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
+%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
+%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
+%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
+%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
+%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
+%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in floating-point rather than integer format.
+%%
+%% Pixel ordering is such that lower x screen coordinates correspond to lower `i' filter
+%% image coordinates, and lower y screen coordinates correspond to lower `j' filter
+%% image coordinates.
+%%
+%% Note that after a convolution is performed, the resulting color components are also scaled
+%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
+%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
+%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
+%% set by {@link gl:pixelTransferf/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter2D.xml">external</a> documentation.
+-spec copyConvolutionFilter2D(Target, Internalformat, X, Y, Width, Height) -> ok when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
copyConvolutionFilter2D(Target,Internalformat,X,Y,Width,Height) ->
cast(5342, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (Target::enum(),Format::enum(),Type::enum(),Image::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionFilter.xml">external</a> documentation.
--spec getConvolutionFilter(enum(),enum(),enum(),mem()) -> ok.
+%% @doc Get current 1D or 2D convolution filter kernel
+%%
+%% ``gl:getConvolutionFilter'' returns the current 1D or 2D convolution filter kernel as
+%% an image. The one- or two-dimensional image is placed in `Image' according to the
+%% specifications in `Format' and `Type' . No pixel transfer operations are performed
+%% on this image, but the relevant pixel storage modes are applied.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a convolution filter is requested, `Image' is
+%% treated as a byte offset into the buffer object's data store.
+%%
+%% Color components that are present in `Format' but not included in the internal format
+%% of the filter are returned as zero. The assignments of internal color components to the
+%% components of `Format' are as follows. <table><tbody><tr><td>` Internal Component '
+%% </td><td>` Resulting Component '</td></tr></tbody><tbody><tr><td> Red </td><td> Red </td>
+%% </tr><tr><td> Green </td><td> Green </td></tr><tr><td> Blue </td><td> Blue </td></tr><tr><td>
+%% Alpha </td><td> Alpha </td></tr><tr><td> Luminance </td><td> Red </td></tr><tr><td> Intensity
+%% </td><td> Red </td></tr></tbody></table>
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionFilter.xml">external</a> documentation.
+-spec getConvolutionFilter(Target, Format, Type, Image) -> ok when Target :: enum(),Format :: enum(),Type :: enum(),Image :: mem().
getConvolutionFilter(Target,Format,Type,Image) ->
send_bin(Image),
call(5343, <<Target:?GLenum,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml">external</a> documentation.
--spec getConvolutionParameterfv(enum(),enum()) -> {float(),float(),float(),float()}.
+%% @doc Get convolution parameters
+%%
+%% ``gl:getConvolutionParameter'' retrieves convolution parameters. `Target' determines
+%% which convolution filter is queried. `Pname' determines which parameter is returned:
+%%
+%%
+%% `?GL_CONVOLUTION_BORDER_MODE': The convolution border mode. See {@link gl:convolutionParameterf/3}
+%% for a list of border modes.
+%%
+%% `?GL_CONVOLUTION_BORDER_COLOR': The current convolution border color. `Params'
+%% must be a pointer to an array of four elements, which will receive the red, green, blue,
+%% and alpha border colors.
+%%
+%% `?GL_CONVOLUTION_FILTER_SCALE': The current filter scale factors. `Params'
+%% must be a pointer to an array of four elements, which will receive the red, green, blue,
+%% and alpha filter scale factors in that order.
+%%
+%% `?GL_CONVOLUTION_FILTER_BIAS': The current filter bias factors. `Params' must
+%% be a pointer to an array of four elements, which will receive the red, green, blue, and
+%% alpha filter bias terms in that order.
+%%
+%% `?GL_CONVOLUTION_FORMAT': The current internal format. See {@link gl:convolutionFilter1D/6}
+%% , {@link gl:convolutionFilter2D/7} , and {@link gl:separableFilter2D/8} for lists of allowable
+%% formats.
+%%
+%% `?GL_CONVOLUTION_WIDTH': The current filter image width.
+%%
+%% `?GL_CONVOLUTION_HEIGHT': The current filter image height.
+%%
+%% `?GL_MAX_CONVOLUTION_WIDTH': The maximum acceptable filter image width.
+%%
+%% `?GL_MAX_CONVOLUTION_HEIGHT': The maximum acceptable filter image height.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml">external</a> documentation.
+-spec getConvolutionParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
getConvolutionParameterfv(Target,Pname) ->
call(5344, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml">external</a> documentation.
--spec getConvolutionParameteriv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getConvolutionParameterfv/2}
+-spec getConvolutionParameteriv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
getConvolutionParameteriv(Target,Pname) ->
call(5345, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Internalformat::enum(),Width::integer(),Height::integer(),Format::enum(),Type::enum(),Row::offset()|mem(),Column::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSeparableFilter2D.xml">external</a> documentation.
--spec separableFilter2D(enum(),enum(),integer(),integer(),enum(),enum(),offset()|mem(),offset()|mem()) -> ok.
+%% @doc Define a separable two-dimensional convolution filter
+%%
+%% ``gl:separableFilter2D'' builds a two-dimensional separable convolution filter kernel
+%% from two arrays of pixels.
+%%
+%% The pixel arrays specified by ( `Width' , `Format' , `Type' , `Row' )
+%% and ( `Height' , `Format' , `Type' , `Column' ) are processed just as if
+%% they had been passed to {@link gl:drawPixels/5} , but processing stops after the final expansion
+%% to RGBA is completed.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Row' and `Column'
+%% are treated as byte offsets into the buffer object's data store.
+%%
+%% Next, the R, G, B, and A components of all pixels in both arrays are scaled by the four
+%% separable 2D `?GL_CONVOLUTION_FILTER_SCALE' parameters and biased by the four separable
+%% 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The scale and bias parameters are set
+%% by {@link gl:convolutionParameterf/3} using the `?GL_SEPARABLE_2D' target and the names
+%% `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'. The parameters
+%% themselves are vectors of four values that are applied to red, green, blue, and alpha,
+%% in that order.) The R, G, B, and A values are not clamped to [0,1] at any time during
+%% this process.
+%%
+%% Each pixel is then converted to the internal format specified by `Internalformat' .
+%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
+%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
+%% The mapping is as follows: <table><tbody><tr><td>` Internal Format '</td><td>` Red '
+%% </td><td>` Green '</td><td>` Blue '</td><td>` Alpha '</td><td>` Luminance '
+%% </td><td>` Intensity '</td></tr></tbody><tbody><tr><td>`?GL_LUMINANCE'</td><td></td>
+%% <td></td><td></td><td></td><td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td>
+%% <td></td><td></td><td></td><td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'
+%% </td><td></td><td></td><td></td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td>
+%% <td> R </td><td> G </td><td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'
+%% </td><td> R </td><td> G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
+%%
+%%
+%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
+%% pixels are stored in floating-point rather than integer format. They form two one-dimensional
+%% filter kernel images. The row image is indexed by coordinate `i' starting at zero
+%% and increasing from left to right. Each location in the row image is derived from element
+%% `i' of `Row' . The column image is indexed by coordinate `j' starting at
+%% zero and increasing from bottom to top. Each location in the column image is derived from
+%% element `j' of `Column' .
+%%
+%% Note that after a convolution is performed, the resulting color components are also scaled
+%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
+%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
+%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
+%% set by {@link gl:pixelTransferf/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSeparableFilter2D.xml">external</a> documentation.
+-spec separableFilter2D(Target, Internalformat, Width, Height, Format, Type, Row, Column) -> ok when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Row :: offset()|mem(),Column :: offset()|mem().
separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) when is_integer(Row), is_integer(Column) ->
cast(5346, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Row:?GLuint,Column:?GLuint>>);
separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) ->
@@ -2522,3497 +8778,7990 @@ separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) ->
send_bin(Column),
cast(5347, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Reset::0|1,Format::enum(),Type::enum(),Values::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogram.xml">external</a> documentation.
--spec getHistogram(enum(),0|1,enum(),enum(),mem()) -> ok.
+%% @doc Get histogram table
+%%
+%% ``gl:getHistogram'' returns the current histogram table as a one-dimensional image with
+%% the same width as the histogram. No pixel transfer operations are performed on this image,
+%% but pixel storage modes that are applicable to 1D images are honored.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a histogram table is requested, `Values' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% Color components that are requested in the specified `Format' , but which are not
+%% included in the internal format of the histogram, are returned as zero. The assignments
+%% of internal color components to the components requested by `Format' are: <table><tbody>
+%% <tr><td>` Internal Component '</td><td>` Resulting Component '</td></tr></tbody>
+%% <tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td></tr><tr><td>
+%% Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> Luminance
+%% </td><td> Red </td></tr></tbody></table>
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogram.xml">external</a> documentation.
+-spec getHistogram(Target, Reset, Format, Type, Values) -> ok when Target :: enum(),Reset :: 0|1,Format :: enum(),Type :: enum(),Values :: mem().
getHistogram(Target,Reset,Format,Type,Values) ->
send_bin(Values),
call(5348, <<Target:?GLenum,Reset:?GLboolean,0:24,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml">external</a> documentation.
--spec getHistogramParameterfv(enum(),enum()) -> {float()}.
+%% @doc Get histogram parameters
+%%
+%% ``gl:getHistogramParameter'' is used to query parameter values for the current histogram
+%% or for a proxy. The histogram state information may be queried by calling ``gl:getHistogramParameter''
+%% with a `Target' of `?GL_HISTOGRAM' (to obtain information for the current histogram
+%% table) or `?GL_PROXY_HISTOGRAM' (to obtain information from the most recent proxy
+%% request) and one of the following values for the `Pname' argument:
+%%
+%% <table><tbody><tr><td>` Parameter '</td><td>` Description '</td></tr></tbody><tbody>
+%% <tr><td>`?GL_HISTOGRAM_WIDTH'</td><td> Histogram table width </td></tr><tr><td>`?GL_HISTOGRAM_FORMAT'
+%% </td><td> Internal format </td></tr><tr><td>`?GL_HISTOGRAM_RED_SIZE'</td><td> Red
+%% component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_GREEN_SIZE'</td><td>
+%% Green component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_BLUE_SIZE'</td>
+%% <td> Blue component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_ALPHA_SIZE'
+%% </td><td> Alpha component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_LUMINANCE_SIZE'
+%% </td><td> Luminance component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_SINK'
+%% </td><td> Value of the `sink' parameter </td></tr></tbody></table>
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml">external</a> documentation.
+-spec getHistogramParameterfv(Target, Pname) -> {float()} when Target :: enum(),Pname :: enum().
getHistogramParameterfv(Target,Pname) ->
call(5349, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml">external</a> documentation.
--spec getHistogramParameteriv(enum(),enum()) -> {integer()}.
+%% @doc
+%% See {@link getHistogramParameterfv/2}
+-spec getHistogramParameteriv(Target, Pname) -> {integer()} when Target :: enum(),Pname :: enum().
getHistogramParameteriv(Target,Pname) ->
call(5350, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Reset::0|1,Format::enum(),Type::enum(),Values::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmax.xml">external</a> documentation.
--spec getMinmax(enum(),0|1,enum(),enum(),mem()) -> ok.
-getMinmax(Target,Reset,Format,Type,Values) ->
+%% @doc Get minimum and maximum pixel values
+%%
+%% ``gl:getMinmax'' returns the accumulated minimum and maximum pixel values (computed
+%% on a per-component basis) in a one-dimensional image of width 2. The first set of return
+%% values are the minima, and the second set of return values are the maxima. The format
+%% of the return values is determined by `Format' , and their type is determined by `Types'
+%% .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while minimum and maximum pixel values are requested, `Values'
+%% is treated as a byte offset into the buffer object's data store.
+%%
+%% No pixel transfer operations are performed on the return values, but pixel storage modes
+%% that are applicable to one-dimensional images are performed. Color components that are
+%% requested in the specified `Format' , but that are not included in the internal format
+%% of the minmax table, are returned as zero. The assignment of internal color components
+%% to the components requested by `Format' are as follows:
+%%
+%% <table><tbody><tr><td>` Internal Component '</td><td>` Resulting Component '</td>
+%% </tr></tbody><tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td>
+%% </tr><tr><td> Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td>
+%% Luminance </td><td> Red </td></tr></tbody></table>
+%%
+%% If `Reset' is `?GL_TRUE', the minmax table entries corresponding to the return
+%% values are reset to their initial values. Minimum and maximum values that are not returned
+%% are not modified, even if `Reset' is `?GL_TRUE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmax.xml">external</a> documentation.
+-spec getMinmax(Target, Reset, Format, Types, Values) -> ok when Target :: enum(),Reset :: 0|1,Format :: enum(),Types :: enum(),Values :: mem().
+getMinmax(Target,Reset,Format,Types,Values) ->
send_bin(Values),
- call(5351, <<Target:?GLenum,Reset:?GLboolean,0:24,Format:?GLenum,Type:?GLenum>>).
+ call(5351, <<Target:?GLenum,Reset:?GLboolean,0:24,Format:?GLenum,Types:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml">external</a> documentation.
--spec getMinmaxParameterfv(enum(),enum()) -> {float()}.
+%% @doc Get minmax parameters
+%%
+%% ``gl:getMinmaxParameter'' retrieves parameters for the current minmax table by setting `Pname'
+%% to one of the following values:
+%%
+%% <table><tbody><tr><td>` Parameter '</td><td>` Description '</td></tr></tbody><tbody>
+%% <tr><td>`?GL_MINMAX_FORMAT'</td><td> Internal format of minmax table </td></tr><tr><td>
+%% `?GL_MINMAX_SINK'</td><td> Value of the `sink' parameter </td></tr></tbody></table>
+%%
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml">external</a> documentation.
+-spec getMinmaxParameterfv(Target, Pname) -> {float()} when Target :: enum(),Pname :: enum().
getMinmaxParameterfv(Target,Pname) ->
call(5352, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml">external</a> documentation.
--spec getMinmaxParameteriv(enum(),enum()) -> {integer()}.
+%% @doc
+%% See {@link getMinmaxParameterfv/2}
+-spec getMinmaxParameteriv(Target, Pname) -> {integer()} when Target :: enum(),Pname :: enum().
getMinmaxParameteriv(Target,Pname) ->
call(5353, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Width::integer(),Internalformat::enum(),Sink::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHistogram.xml">external</a> documentation.
--spec histogram(enum(),integer(),enum(),0|1) -> ok.
+%% @doc Define histogram table
+%%
+%% When `?GL_HISTOGRAM' is enabled, RGBA color components are converted to histogram
+%% table indices by clamping to the range [0,1], multiplying by the width of the histogram
+%% table, and rounding to the nearest integer. The table entries selected by the RGBA indices
+%% are then incremented. (If the internal format of the histogram table includes luminance,
+%% then the index derived from the R color component determines the luminance table entry
+%% to be incremented.) If a histogram table entry is incremented beyond its maximum value,
+%% then its value becomes undefined. (This is not an error.)
+%%
+%% Histogramming is performed only for RGBA pixels (though these may be specified originally
+%% as color indices and converted to RGBA by index table lookup). Histogramming is enabled
+%% with {@link gl:enable/1} and disabled with {@link gl:enable/1} .
+%%
+%% When `Target' is `?GL_HISTOGRAM', ``gl:histogram'' redefines the current
+%% histogram table to have `Width' entries of the format specified by `Internalformat'
+%% . The entries are indexed 0 through width-1, and all entries are initialized to zero.
+%% The values in the previous histogram table, if any, are lost. If `Sink' is `?GL_TRUE'
+%% , then pixels are discarded after histogramming; no further processing of the pixels takes
+%% place, and no drawing, texture loading, or pixel readback will result.
+%%
+%% When `Target' is `?GL_PROXY_HISTOGRAM', ``gl:histogram'' computes all state
+%% information as if the histogram table were to be redefined, but does not actually define
+%% the new table. If the requested histogram table is too large to be supported, then the
+%% state information will be set to zero. This provides a way to determine if a histogram
+%% table with the given parameters can be supported.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHistogram.xml">external</a> documentation.
+-spec histogram(Target, Width, Internalformat, Sink) -> ok when Target :: enum(),Width :: integer(),Internalformat :: enum(),Sink :: 0|1.
histogram(Target,Width,Internalformat,Sink) ->
cast(5354, <<Target:?GLenum,Width:?GLsizei,Internalformat:?GLenum,Sink:?GLboolean>>).
-%% @spec (Target::enum(),Internalformat::enum(),Sink::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinmax.xml">external</a> documentation.
--spec minmax(enum(),enum(),0|1) -> ok.
+%% @doc Define minmax table
+%%
+%% When `?GL_MINMAX' is enabled, the RGBA components of incoming pixels are compared
+%% to the minimum and maximum values for each component, which are stored in the two-element
+%% minmax table. (The first element stores the minima, and the second element stores the
+%% maxima.) If a pixel component is greater than the corresponding component in the maximum
+%% element, then the maximum element is updated with the pixel component value. If a pixel
+%% component is less than the corresponding component in the minimum element, then the minimum
+%% element is updated with the pixel component value. (In both cases, if the internal format
+%% of the minmax table includes luminance, then the R color component of incoming pixels
+%% is used for comparison.) The contents of the minmax table may be retrieved at a later
+%% time by calling {@link gl:getMinmax/5} . The minmax operation is enabled or disabled by
+%% calling {@link gl:enable/1} or {@link gl:enable/1} , respectively, with an argument of `?GL_MINMAX'
+%% .
+%%
+%% ``gl:minmax'' redefines the current minmax table to have entries of the format specified
+%% by `Internalformat' . The maximum element is initialized with the smallest possible
+%% component values, and the minimum element is initialized with the largest possible component
+%% values. The values in the previous minmax table, if any, are lost. If `Sink' is `?GL_TRUE'
+%% , then pixels are discarded after minmax; no further processing of the pixels takes place,
+%% and no drawing, texture loading, or pixel readback will result.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinmax.xml">external</a> documentation.
+-spec minmax(Target, Internalformat, Sink) -> ok when Target :: enum(),Internalformat :: enum(),Sink :: 0|1.
minmax(Target,Internalformat,Sink) ->
cast(5355, <<Target:?GLenum,Internalformat:?GLenum,Sink:?GLboolean>>).
-%% @spec (Target::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetHistogram.xml">external</a> documentation.
--spec resetHistogram(enum()) -> ok.
+%% @doc Reset histogram table entries to zero
+%%
+%% ``gl:resetHistogram'' resets all the elements of the current histogram table to zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetHistogram.xml">external</a> documentation.
+-spec resetHistogram(Target) -> ok when Target :: enum().
resetHistogram(Target) ->
cast(5356, <<Target:?GLenum>>).
-%% @spec (Target::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetMinmax.xml">external</a> documentation.
--spec resetMinmax(enum()) -> ok.
+%% @doc Reset minmax table entries to initial values
+%%
+%% ``gl:resetMinmax'' resets the elements of the current minmax table to their initial
+%% values: the ``maximum'' element receives the minimum possible component values, and the
+%% ``minimum'' element receives the maximum possible component values.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetMinmax.xml">external</a> documentation.
+-spec resetMinmax(Target) -> ok when Target :: enum().
resetMinmax(Target) ->
cast(5357, <<Target:?GLenum>>).
-%% @spec (Texture::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml">external</a> documentation.
--spec activeTexture(enum()) -> ok.
+%% @doc Select active texture unit
+%%
+%% ``gl:activeTexture'' selects which texture unit subsequent texture state calls will
+%% affect. The number of texture units an implementation supports is implementation dependent,
+%% but must be at least 80.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml">external</a> documentation.
+-spec activeTexture(Texture) -> ok when Texture :: enum().
activeTexture(Texture) ->
cast(5358, <<Texture:?GLenum>>).
-%% @spec (Value::clamp(),Invert::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleCoverage.xml">external</a> documentation.
--spec sampleCoverage(clamp(),0|1) -> ok.
+%% @doc Specify multisample coverage parameters
+%%
+%% Multisampling samples a pixel multiple times at various implementation-dependent subpixel
+%% locations to generate antialiasing effects. Multisampling transparently antialiases points,
+%% lines, polygons, and images if it is enabled.
+%%
+%% `Value' is used in constructing a temporary mask used in determining which samples
+%% will be used in resolving the final fragment color. This mask is bitwise-anded with the
+%% coverage mask generated from the multisampling computation. If the `Invert' flag
+%% is set, the temporary mask is inverted (all bits flipped) and then the bitwise-and is
+%% computed.
+%%
+%% If an implementation does not have any multisample buffers available, or multisampling
+%% is disabled, rasterization occurs with only a single sample computing a pixel's final
+%% RGB color.
+%%
+%% Provided an implementation supports multisample buffers, and multisampling is enabled,
+%% then a pixel's final color is generated by combining several samples per pixel. Each sample
+%% contains color, depth, and stencil information, allowing those operations to be performed
+%% on each sample.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleCoverage.xml">external</a> documentation.
+-spec sampleCoverage(Value, Invert) -> ok when Value :: clamp(),Invert :: 0|1.
sampleCoverage(Value,Invert) ->
cast(5359, <<Value:?GLclampf,Invert:?GLboolean>>).
-%% @spec (Target::enum(),Level::integer(),Internalformat::enum(),Width::integer(),Height::integer(),Depth::integer(),Border::integer(),ImageSize::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage3D.xml">external</a> documentation.
--spec compressedTexImage3D(enum(),integer(),enum(),integer(),integer(),integer(),integer(),integer(),offset()|mem()) -> ok.
+%% @doc Specify a three-dimensional texture image in a compressed format
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% ``gl:compressedTexImage3D'' loads a previously defined, and retrieved, compressed three-dimensional
+%% texture image if `Target' is `?GL_TEXTURE_3D' (see {@link gl:texImage3D/10} ).
+%%
+%% If `Target' is `?GL_TEXTURE_2D_ARRAY', `Data' is treated as an array of
+%% compressed 2D textures.
+%%
+%% If `Target' is `?GL_PROXY_TEXTURE_3D' or `?GL_PROXY_TEXTURE_2D_ARRAY',
+%% no data is read from `Data' , but all of the texture image state is recalculated,
+%% checked for consistency, and checked against the implementation's capabilities. If the
+%% implementation cannot handle a texture of the requested texture size, it sets all of the
+%% image state to 0, but does not generate an error (see {@link gl:getError/0} ). To query
+%% for an entire mipmap array, use an image array level greater than or equal to 1.
+%%
+%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
+%% or an extension-specified compressed-texture format. When a texture is loaded with {@link gl:texImage2D/9}
+%% using a generic compressed texture format (e.g., `?GL_COMPRESSED_RGB'), the GL selects
+%% from one of its extensions supporting compressed textures. In order to load the compressed
+%% texture image using ``gl:compressedTexImage3D'', query the compressed texture image's
+%% size and format using {@link gl:getTexLevelParameterfv/3} .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage
+%% modes can be used to select a sub-rectangle from a larger containing rectangle. These
+%% pixel storage modes operate in the same way as they do for {@link gl:texImage1D/8} . In
+%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage
+%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT'
+%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block
+%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth
+%% in pixels.
+%%
+%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS'
+%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES'
+%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH'
+%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT'
+%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero.
+%% All parameters must be consistent with the compressed format to produce the desired results.
+%%
+%%
+%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS'
+%% must be a multiple of b w;the value of `?GL_UNPACK_SKIP_ROWS' must be a multiple
+%% of b w;the value of `?GL_UNPACK_SKIP_IMAGES' must be a multiple of b w.
+%%
+%% `ImageSize' must be equal to:
+%%
+%% b s*|width b/w|*|height b/h|*|depth b/d|
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage3D.xml">external</a> documentation.
+-spec compressedTexImage3D(Target, Level, Internalformat, Width, Height, Depth, Border, ImageSize, Data) -> ok when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Depth :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,ImageSize,Data) when is_integer(Data) ->
cast(5360, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>);
compressedTexImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,ImageSize,Data) ->
send_bin(Data),
cast(5361, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,ImageSize:?GLsizei>>).
-%% @spec (Target::enum(),Level::integer(),Internalformat::enum(),Width::integer(),Height::integer(),Border::integer(),ImageSize::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage2D.xml">external</a> documentation.
--spec compressedTexImage2D(enum(),integer(),enum(),integer(),integer(),integer(),integer(),offset()|mem()) -> ok.
+%% @doc Specify a two-dimensional texture image in a compressed format
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% ``gl:compressedTexImage2D'' loads a previously defined, and retrieved, compressed two-dimensional
+%% texture image if `Target' is `?GL_TEXTURE_2D', or one of the cube map faces
+%% such as `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'. (see {@link gl:texImage2D/9} ).
+%%
+%% If `Target' is `?GL_TEXTURE_1D_ARRAY', `Data' is treated as an array of
+%% compressed 1D textures.
+%%
+%% If `Target' is `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY' or `?GL_PROXY_CUBE_MAP'
+%% , no data is read from `Data' , but all of the texture image state is recalculated,
+%% checked for consistency, and checked against the implementation's capabilities. If the
+%% implementation cannot handle a texture of the requested texture size, it sets all of the
+%% image state to 0, but does not generate an error (see {@link gl:getError/0} ). To query
+%% for an entire mipmap array, use an image array level greater than or equal to 1.
+%%
+%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
+%% or an extension-specified compressed-texture format. When a texture is loaded with {@link gl:texImage2D/9}
+%% using a generic compressed texture format (e.g., `?GL_COMPRESSED_RGB'), the GL selects
+%% from one of its extensions supporting compressed textures. In order to load the compressed
+%% texture image using ``gl:compressedTexImage2D'', query the compressed texture image's
+%% size and format using {@link gl:getTexLevelParameterfv/3} .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage
+%% modes can be used to select a sub-rectangle from a larger containing rectangle. These
+%% pixel storage modes operate in the same way as they do for {@link gl:texImage2D/9} . In
+%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage
+%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT'
+%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block
+%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth
+%% in pixels.
+%%
+%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS'
+%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES'
+%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH'
+%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT'
+%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero.
+%% All parameters must be consistent with the compressed format to produce the desired results.
+%%
+%%
+%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS'
+%% must be a multiple of b w;the value of `?GL_UNPACK_SKIP_ROWS' must be a multiple
+%% of b w.
+%%
+%% `ImageSize' must be equal to:
+%%
+%% b s*|width b/w|*|height b/h|
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage2D.xml">external</a> documentation.
+-spec compressedTexImage2D(Target, Level, Internalformat, Width, Height, Border, ImageSize, Data) -> ok when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexImage2D(Target,Level,Internalformat,Width,Height,Border,ImageSize,Data) when is_integer(Data) ->
cast(5362, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>);
compressedTexImage2D(Target,Level,Internalformat,Width,Height,Border,ImageSize,Data) ->
send_bin(Data),
cast(5363, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Border:?GLint,ImageSize:?GLsizei>>).
-%% @spec (Target::enum(),Level::integer(),Internalformat::enum(),Width::integer(),Border::integer(),ImageSize::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage1D.xml">external</a> documentation.
--spec compressedTexImage1D(enum(),integer(),enum(),integer(),integer(),integer(),offset()|mem()) -> ok.
+%% @doc Specify a one-dimensional texture image in a compressed format
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% ``gl:compressedTexImage1D'' loads a previously defined, and retrieved, compressed one-dimensional
+%% texture image if `Target' is `?GL_TEXTURE_1D' (see {@link gl:texImage1D/8} ).
+%%
+%% If `Target' is `?GL_PROXY_TEXTURE_1D', no data is read from `Data' , but
+%% all of the texture image state is recalculated, checked for consistency, and checked against
+%% the implementation's capabilities. If the implementation cannot handle a texture of the
+%% requested texture size, it sets all of the image state to 0, but does not generate an
+%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
+%% level greater than or equal to 1.
+%%
+%% `Internalformat' must be an extension-specified compressed-texture format. When a
+%% texture is loaded with {@link gl:texImage1D/8} using a generic compressed texture format
+%% (e.g., `?GL_COMPRESSED_RGB') the GL selects from one of its extensions supporting
+%% compressed textures. In order to load the compressed texture image using ``gl:compressedTexImage1D''
+%% , query the compressed texture image's size and format using {@link gl:getTexLevelParameterfv/3}
+%% .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage
+%% modes can be used to select a sub-rectangle from a larger containing rectangle. These
+%% pixel storage modes operate in the same way as they do for {@link gl:texImage1D/8} . In
+%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage
+%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT'
+%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block
+%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth
+%% in pixels.
+%%
+%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS'
+%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES'
+%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH'
+%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT'
+%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero.
+%% All parameters must be consistent with the compressed format to produce the desired results.
+%%
+%%
+%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS'
+%% must be a multiple of b w;
+%%
+%% `ImageSize' must be equal to:
+%%
+%% b s*|width b/w|
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage1D.xml">external</a> documentation.
+-spec compressedTexImage1D(Target, Level, Internalformat, Width, Border, ImageSize, Data) -> ok when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexImage1D(Target,Level,Internalformat,Width,Border,ImageSize,Data) when is_integer(Data) ->
cast(5364, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>);
compressedTexImage1D(Target,Level,Internalformat,Width,Border,ImageSize,Data) ->
send_bin(Data),
cast(5365, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Border:?GLint,ImageSize:?GLsizei>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Yoffset::integer(),Zoffset::integer(),Width::integer(),Height::integer(),Depth::integer(),Format::enum(),ImageSize::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage3D.xml">external</a> documentation.
--spec compressedTexSubImage3D(enum(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),enum(),integer(),offset()|mem()) -> ok.
+%% @doc Specify a three-dimensional texture subimage in a compressed format
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% ``gl:compressedTexSubImage3D'' redefines a contiguous subregion of an existing three-dimensional
+%% texture image. The texels referenced by `Data' replace the portion of the existing
+%% texture array with x indices `Xoffset' and xoffset+width-1, and the y indices `Yoffset'
+%% and yoffset+height-1, and the z indices `Zoffset' and zoffset+depth-1, inclusive.
+%% This region may not include any texels outside the range of the texture array as it was
+%% originally specified. It is not an error to specify a subtexture with width of 0, but
+%% such a specification has no effect.
+%%
+%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
+%% or an extension-specified compressed-texture format. The `Format' of the compressed
+%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage3D/10}
+%% ) and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3}
+%% .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage3D.xml">external</a> documentation.
+-spec compressedTexSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, Width, Height, Depth, Format, ImageSize, Data) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,ImageSize,Data) when is_integer(Data) ->
cast(5366, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>);
compressedTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,ImageSize,Data) ->
send_bin(Data),
cast(5367, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,ImageSize:?GLsizei>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Yoffset::integer(),Width::integer(),Height::integer(),Format::enum(),ImageSize::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage2D.xml">external</a> documentation.
--spec compressedTexSubImage2D(enum(),integer(),integer(),integer(),integer(),integer(),enum(),integer(),offset()|mem()) -> ok.
+%% @doc Specify a two-dimensional texture subimage in a compressed format
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% ``gl:compressedTexSubImage2D'' redefines a contiguous subregion of an existing two-dimensional
+%% texture image. The texels referenced by `Data' replace the portion of the existing
+%% texture array with x indices `Xoffset' and xoffset+width-1, and the y indices `Yoffset'
+%% and yoffset+height-1, inclusive. This region may not include any texels outside the
+%% range of the texture array as it was originally specified. It is not an error to specify
+%% a subtexture with width of 0, but such a specification has no effect.
+%%
+%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
+%% or an extension-specified compressed-texture format. The `Format' of the compressed
+%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage2D/9}
+%% ) and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3}
+%% .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage2D.xml">external</a> documentation.
+-spec compressedTexSubImage2D(Target, Level, Xoffset, Yoffset, Width, Height, Format, ImageSize, Data) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,ImageSize,Data) when is_integer(Data) ->
cast(5368, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>);
compressedTexSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,ImageSize,Data) ->
send_bin(Data),
cast(5369, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,ImageSize:?GLsizei>>).
-%% @spec (Target::enum(),Level::integer(),Xoffset::integer(),Width::integer(),Format::enum(),ImageSize::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage1D.xml">external</a> documentation.
--spec compressedTexSubImage1D(enum(),integer(),integer(),integer(),enum(),integer(),offset()|mem()) -> ok.
+%% @doc Specify a one-dimensional texture subimage in a compressed format
+%%
+%% Texturing allows elements of an image array to be read by shaders.
+%%
+%% ``gl:compressedTexSubImage1D'' redefines a contiguous subregion of an existing one-dimensional
+%% texture image. The texels referenced by `Data' replace the portion of the existing
+%% texture array with x indices `Xoffset' and xoffset+width-1, inclusive. This region
+%% may not include any texels outside the range of the texture array as it was originally
+%% specified. It is not an error to specify a subtexture with width of 0, but such a specification
+%% has no effect.
+%%
+%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
+%% or an extension-specified compressed-texture format. The `Format' of the compressed
+%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage1D/8}
+%% ), and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3}
+%% .
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage1D.xml">external</a> documentation.
+-spec compressedTexSubImage1D(Target, Level, Xoffset, Width, Format, ImageSize, Data) -> ok when Target :: enum(),Level :: integer(),Xoffset :: integer(),Width :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexSubImage1D(Target,Level,Xoffset,Width,Format,ImageSize,Data) when is_integer(Data) ->
cast(5370, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>);
compressedTexSubImage1D(Target,Level,Xoffset,Width,Format,ImageSize,Data) ->
send_bin(Data),
cast(5371, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,ImageSize:?GLsizei>>).
-%% @spec (Target::enum(),Level::integer(),Img::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml">external</a> documentation.
--spec getCompressedTexImage(enum(),integer(),mem()) -> ok.
-getCompressedTexImage(Target,Level,Img) ->
+%% @doc Return a compressed texture image
+%%
+%% ``gl:getCompressedTexImage'' returns the compressed texture image associated with `Target'
+%% and `Lod' into `Img' . `Img' should be an array of `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE'
+%% bytes. `Target' specifies whether the desired texture image was one specified by {@link gl:texImage1D/8}
+%% (`?GL_TEXTURE_1D'), {@link gl:texImage2D/9} (`?GL_TEXTURE_2D' or any of `?GL_TEXTURE_CUBE_MAP_*'
+%% ), or {@link gl:texImage3D/10} (`?GL_TEXTURE_3D'). `Lod' specifies the level-of-detail
+%% number of the desired image.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
+%% (see {@link gl:bindBuffer/2} ) while a texture image is requested, `Img' is treated
+%% as a byte offset into the buffer object's data store.
+%%
+%% To minimize errors, first verify that the texture is compressed by calling {@link gl:getTexLevelParameterfv/3}
+%% with argument `?GL_TEXTURE_COMPRESSED'. If the texture is compressed, then determine
+%% the amount of memory required to store the compressed texture by calling {@link gl:getTexLevelParameterfv/3}
+%% with argument `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE'. Finally, retrieve the internal
+%% format of the texture by calling {@link gl:getTexLevelParameterfv/3} with argument `?GL_TEXTURE_INTERNAL_FORMAT'
+%% . To store the texture for later use, associate the internal format and size with the
+%% retrieved texture image. These data can be used by the respective texture or subtexture
+%% loading routine used for loading `Target' textures.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml">external</a> documentation.
+-spec getCompressedTexImage(Target, Lod, Img) -> ok when Target :: enum(),Lod :: integer(),Img :: mem().
+getCompressedTexImage(Target,Lod,Img) ->
send_bin(Img),
- call(5372, <<Target:?GLenum,Level:?GLint>>).
+ call(5372, <<Target:?GLenum,Lod:?GLint>>).
-%% @spec (Texture::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml">external</a> documentation.
--spec clientActiveTexture(enum()) -> ok.
+%% @doc Select active texture unit
+%%
+%% ``gl:clientActiveTexture'' selects the vertex array client state parameters to be modified
+%% by {@link gl:texCoordPointer/4} , and enabled or disabled with {@link gl:enableClientState/1}
+%% or {@link gl:enableClientState/1} , respectively, when called with a parameter of `?GL_TEXTURE_COORD_ARRAY'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml">external</a> documentation.
+-spec clientActiveTexture(Texture) -> ok when Texture :: enum().
clientActiveTexture(Texture) ->
cast(5373, <<Texture:?GLenum>>).
-%% @spec (Target::enum(),S::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord1d(enum(),float()) -> ok.
+%% @doc Set the current texture coordinates
+%%
+%% ``gl:multiTexCoord'' specifies texture coordinates in one, two, three, or four dimensions.
+%% ``gl:multiTexCoord1'' sets the current texture coordinates to (s 0 0 1); a call to ``gl:multiTexCoord2''
+%% sets them to (s t 0 1). Similarly, ``gl:multiTexCoord3'' specifies the texture coordinates as (s
+%% t r 1),
+%% and ``gl:multiTexCoord4'' defines all four components explicitly as (s t r q).
+%%
+%% The current texture coordinates are part of the data that is associated with each vertex
+%% and with the current raster position. Initially, the values for (s t r q) are (0 0 0 1).
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
+-spec multiTexCoord1d(Target, S) -> ok when Target :: enum(),S :: float().
multiTexCoord1d(Target,S) ->
cast(5374, <<Target:?GLenum,0:32,S:?GLdouble>>).
-%% @spec (Target,{S}) -> ok
%% @equiv multiTexCoord1d(Target,S)
--spec multiTexCoord1dv(enum(),{float()}) -> ok.
+-spec multiTexCoord1dv(Target :: enum(),V) -> ok when V :: {S :: float()}.
multiTexCoord1dv(Target,{S}) -> multiTexCoord1d(Target,S).
-%% @spec (Target::enum(),S::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord1f(enum(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord1f(Target, S) -> ok when Target :: enum(),S :: float().
multiTexCoord1f(Target,S) ->
cast(5375, <<Target:?GLenum,S:?GLfloat>>).
-%% @spec (Target,{S}) -> ok
%% @equiv multiTexCoord1f(Target,S)
--spec multiTexCoord1fv(enum(),{float()}) -> ok.
+-spec multiTexCoord1fv(Target :: enum(),V) -> ok when V :: {S :: float()}.
multiTexCoord1fv(Target,{S}) -> multiTexCoord1f(Target,S).
-%% @spec (Target::enum(),S::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord1i(enum(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord1i(Target, S) -> ok when Target :: enum(),S :: integer().
multiTexCoord1i(Target,S) ->
cast(5376, <<Target:?GLenum,S:?GLint>>).
-%% @spec (Target,{S}) -> ok
%% @equiv multiTexCoord1i(Target,S)
--spec multiTexCoord1iv(enum(),{integer()}) -> ok.
+-spec multiTexCoord1iv(Target :: enum(),V) -> ok when V :: {S :: integer()}.
multiTexCoord1iv(Target,{S}) -> multiTexCoord1i(Target,S).
-%% @spec (Target::enum(),S::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord1s(enum(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord1s(Target, S) -> ok when Target :: enum(),S :: integer().
multiTexCoord1s(Target,S) ->
cast(5377, <<Target:?GLenum,S:?GLshort>>).
-%% @spec (Target,{S}) -> ok
%% @equiv multiTexCoord1s(Target,S)
--spec multiTexCoord1sv(enum(),{integer()}) -> ok.
+-spec multiTexCoord1sv(Target :: enum(),V) -> ok when V :: {S :: integer()}.
multiTexCoord1sv(Target,{S}) -> multiTexCoord1s(Target,S).
-%% @spec (Target::enum(),S::float(),T::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord2d(enum(),float(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord2d(Target, S, T) -> ok when Target :: enum(),S :: float(),T :: float().
multiTexCoord2d(Target,S,T) ->
cast(5378, <<Target:?GLenum,0:32,S:?GLdouble,T:?GLdouble>>).
-%% @spec (Target,{S,T}) -> ok
%% @equiv multiTexCoord2d(Target,S,T)
--spec multiTexCoord2dv(enum(),{float(),float()}) -> ok.
+-spec multiTexCoord2dv(Target :: enum(),V) -> ok when V :: {S :: float(),T :: float()}.
multiTexCoord2dv(Target,{S,T}) -> multiTexCoord2d(Target,S,T).
-%% @spec (Target::enum(),S::float(),T::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord2f(enum(),float(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord2f(Target, S, T) -> ok when Target :: enum(),S :: float(),T :: float().
multiTexCoord2f(Target,S,T) ->
cast(5379, <<Target:?GLenum,S:?GLfloat,T:?GLfloat>>).
-%% @spec (Target,{S,T}) -> ok
%% @equiv multiTexCoord2f(Target,S,T)
--spec multiTexCoord2fv(enum(),{float(),float()}) -> ok.
+-spec multiTexCoord2fv(Target :: enum(),V) -> ok when V :: {S :: float(),T :: float()}.
multiTexCoord2fv(Target,{S,T}) -> multiTexCoord2f(Target,S,T).
-%% @spec (Target::enum(),S::integer(),T::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord2i(enum(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord2i(Target, S, T) -> ok when Target :: enum(),S :: integer(),T :: integer().
multiTexCoord2i(Target,S,T) ->
cast(5380, <<Target:?GLenum,S:?GLint,T:?GLint>>).
-%% @spec (Target,{S,T}) -> ok
%% @equiv multiTexCoord2i(Target,S,T)
--spec multiTexCoord2iv(enum(),{integer(),integer()}) -> ok.
+-spec multiTexCoord2iv(Target :: enum(),V) -> ok when V :: {S :: integer(),T :: integer()}.
multiTexCoord2iv(Target,{S,T}) -> multiTexCoord2i(Target,S,T).
-%% @spec (Target::enum(),S::integer(),T::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord2s(enum(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord2s(Target, S, T) -> ok when Target :: enum(),S :: integer(),T :: integer().
multiTexCoord2s(Target,S,T) ->
cast(5381, <<Target:?GLenum,S:?GLshort,T:?GLshort>>).
-%% @spec (Target,{S,T}) -> ok
%% @equiv multiTexCoord2s(Target,S,T)
--spec multiTexCoord2sv(enum(),{integer(),integer()}) -> ok.
+-spec multiTexCoord2sv(Target :: enum(),V) -> ok when V :: {S :: integer(),T :: integer()}.
multiTexCoord2sv(Target,{S,T}) -> multiTexCoord2s(Target,S,T).
-%% @spec (Target::enum(),S::float(),T::float(),R::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord3d(enum(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord3d(Target, S, T, R) -> ok when Target :: enum(),S :: float(),T :: float(),R :: float().
multiTexCoord3d(Target,S,T,R) ->
cast(5382, <<Target:?GLenum,0:32,S:?GLdouble,T:?GLdouble,R:?GLdouble>>).
-%% @spec (Target,{S,T,R}) -> ok
%% @equiv multiTexCoord3d(Target,S,T,R)
--spec multiTexCoord3dv(enum(),{float(),float(),float()}) -> ok.
+-spec multiTexCoord3dv(Target :: enum(),V) -> ok when V :: {S :: float(),T :: float(),R :: float()}.
multiTexCoord3dv(Target,{S,T,R}) -> multiTexCoord3d(Target,S,T,R).
-%% @spec (Target::enum(),S::float(),T::float(),R::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord3f(enum(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord3f(Target, S, T, R) -> ok when Target :: enum(),S :: float(),T :: float(),R :: float().
multiTexCoord3f(Target,S,T,R) ->
cast(5383, <<Target:?GLenum,S:?GLfloat,T:?GLfloat,R:?GLfloat>>).
-%% @spec (Target,{S,T,R}) -> ok
%% @equiv multiTexCoord3f(Target,S,T,R)
--spec multiTexCoord3fv(enum(),{float(),float(),float()}) -> ok.
+-spec multiTexCoord3fv(Target :: enum(),V) -> ok when V :: {S :: float(),T :: float(),R :: float()}.
multiTexCoord3fv(Target,{S,T,R}) -> multiTexCoord3f(Target,S,T,R).
-%% @spec (Target::enum(),S::integer(),T::integer(),R::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord3i(enum(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord3i(Target, S, T, R) -> ok when Target :: enum(),S :: integer(),T :: integer(),R :: integer().
multiTexCoord3i(Target,S,T,R) ->
cast(5384, <<Target:?GLenum,S:?GLint,T:?GLint,R:?GLint>>).
-%% @spec (Target,{S,T,R}) -> ok
%% @equiv multiTexCoord3i(Target,S,T,R)
--spec multiTexCoord3iv(enum(),{integer(),integer(),integer()}) -> ok.
+-spec multiTexCoord3iv(Target :: enum(),V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer()}.
multiTexCoord3iv(Target,{S,T,R}) -> multiTexCoord3i(Target,S,T,R).
-%% @spec (Target::enum(),S::integer(),T::integer(),R::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord3s(enum(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord3s(Target, S, T, R) -> ok when Target :: enum(),S :: integer(),T :: integer(),R :: integer().
multiTexCoord3s(Target,S,T,R) ->
cast(5385, <<Target:?GLenum,S:?GLshort,T:?GLshort,R:?GLshort>>).
-%% @spec (Target,{S,T,R}) -> ok
%% @equiv multiTexCoord3s(Target,S,T,R)
--spec multiTexCoord3sv(enum(),{integer(),integer(),integer()}) -> ok.
+-spec multiTexCoord3sv(Target :: enum(),V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer()}.
multiTexCoord3sv(Target,{S,T,R}) -> multiTexCoord3s(Target,S,T,R).
-%% @spec (Target::enum(),S::float(),T::float(),R::float(),Q::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord4d(enum(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord4d(Target, S, T, R, Q) -> ok when Target :: enum(),S :: float(),T :: float(),R :: float(),Q :: float().
multiTexCoord4d(Target,S,T,R,Q) ->
cast(5386, <<Target:?GLenum,0:32,S:?GLdouble,T:?GLdouble,R:?GLdouble,Q:?GLdouble>>).
-%% @spec (Target,{S,T,R,Q}) -> ok
%% @equiv multiTexCoord4d(Target,S,T,R,Q)
--spec multiTexCoord4dv(enum(),{float(),float(),float(),float()}) -> ok.
+-spec multiTexCoord4dv(Target :: enum(),V) -> ok when V :: {S :: float(),T :: float(),R :: float(),Q :: float()}.
multiTexCoord4dv(Target,{S,T,R,Q}) -> multiTexCoord4d(Target,S,T,R,Q).
-%% @spec (Target::enum(),S::float(),T::float(),R::float(),Q::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord4f(enum(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord4f(Target, S, T, R, Q) -> ok when Target :: enum(),S :: float(),T :: float(),R :: float(),Q :: float().
multiTexCoord4f(Target,S,T,R,Q) ->
cast(5387, <<Target:?GLenum,S:?GLfloat,T:?GLfloat,R:?GLfloat,Q:?GLfloat>>).
-%% @spec (Target,{S,T,R,Q}) -> ok
%% @equiv multiTexCoord4f(Target,S,T,R,Q)
--spec multiTexCoord4fv(enum(),{float(),float(),float(),float()}) -> ok.
+-spec multiTexCoord4fv(Target :: enum(),V) -> ok when V :: {S :: float(),T :: float(),R :: float(),Q :: float()}.
multiTexCoord4fv(Target,{S,T,R,Q}) -> multiTexCoord4f(Target,S,T,R,Q).
-%% @spec (Target::enum(),S::integer(),T::integer(),R::integer(),Q::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord4i(enum(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord4i(Target, S, T, R, Q) -> ok when Target :: enum(),S :: integer(),T :: integer(),R :: integer(),Q :: integer().
multiTexCoord4i(Target,S,T,R,Q) ->
cast(5388, <<Target:?GLenum,S:?GLint,T:?GLint,R:?GLint,Q:?GLint>>).
-%% @spec (Target,{S,T,R,Q}) -> ok
%% @equiv multiTexCoord4i(Target,S,T,R,Q)
--spec multiTexCoord4iv(enum(),{integer(),integer(),integer(),integer()}) -> ok.
+-spec multiTexCoord4iv(Target :: enum(),V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer(),Q :: integer()}.
multiTexCoord4iv(Target,{S,T,R,Q}) -> multiTexCoord4i(Target,S,T,R,Q).
-%% @spec (Target::enum(),S::integer(),T::integer(),R::integer(),Q::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
--spec multiTexCoord4s(enum(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link multiTexCoord1d/2}
+-spec multiTexCoord4s(Target, S, T, R, Q) -> ok when Target :: enum(),S :: integer(),T :: integer(),R :: integer(),Q :: integer().
multiTexCoord4s(Target,S,T,R,Q) ->
cast(5389, <<Target:?GLenum,S:?GLshort,T:?GLshort,R:?GLshort,Q:?GLshort>>).
-%% @spec (Target,{S,T,R,Q}) -> ok
%% @equiv multiTexCoord4s(Target,S,T,R,Q)
--spec multiTexCoord4sv(enum(),{integer(),integer(),integer(),integer()}) -> ok.
+-spec multiTexCoord4sv(Target :: enum(),V) -> ok when V :: {S :: integer(),T :: integer(),R :: integer(),Q :: integer()}.
multiTexCoord4sv(Target,{S,T,R,Q}) -> multiTexCoord4s(Target,S,T,R,Q).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml">external</a> documentation.
--spec loadTransposeMatrixf({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc Replace the current matrix with the specified row-major ordered matrix
+%%
+%% ``gl:loadTransposeMatrix'' replaces the current matrix with the one whose elements are
+%% specified by `M' . The current matrix is the projection matrix, modelview matrix,
+%% or texture matrix, depending on the current matrix mode (see {@link gl:matrixMode/1} ).
+%%
+%% The current matrix, M, defines a transformation of coordinates. For instance, assume
+%% M refers to the modelview matrix. If v=(v[0] v[1] v[2] v[3]) is the set of object coordinates of a vertex,
+%% and `M' points to an array of 16 single- or double-precision floating-point values
+%% m={m[0] m[1] ... m[15]}, then the modelview transformation M(v) does the following:
+%%
+%% M(v)=(m[0] m[1] m[2] m[3] m[4] m[5] m[6] m[7] m[8] m[9] m[10] m[11] m[12] m[13] m[14] m[15])*(v[0] v[1] v[2] v[3])
+%%
+%% Projection and texture transformations are similarly defined.
+%%
+%% Calling ``gl:loadTransposeMatrix'' with matrix M is identical in operation to {@link gl:loadMatrixd/1}
+%% with M T, where T represents the transpose.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml">external</a> documentation.
+-spec loadTransposeMatrixf(M) -> ok when M :: matrix().
loadTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5390, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
loadTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5390, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml">external</a> documentation.
--spec loadTransposeMatrixd({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc
+%% See {@link loadTransposeMatrixf/1}
+-spec loadTransposeMatrixd(M) -> ok when M :: matrix().
loadTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5391, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
loadTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5391, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml">external</a> documentation.
--spec multTransposeMatrixf({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc Multiply the current matrix with the specified row-major ordered matrix
+%%
+%% ``gl:multTransposeMatrix'' multiplies the current matrix with the one specified using `M'
+%% , and replaces the current matrix with the product.
+%%
+%% The current matrix is determined by the current matrix mode (see {@link gl:matrixMode/1} ).
+%% It is either the projection matrix, modelview matrix, or the texture matrix.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml">external</a> documentation.
+-spec multTransposeMatrixf(M) -> ok when M :: matrix().
multTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5392, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
multTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5392, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml">external</a> documentation.
--spec multTransposeMatrixd({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc
+%% See {@link multTransposeMatrixf/1}
+-spec multTransposeMatrixd(M) -> ok when M :: matrix().
multTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5393, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
multTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5393, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
-%% @spec (SfactorRGB::enum(),DfactorRGB::enum(),SfactorAlpha::enum(),DfactorAlpha::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml">external</a> documentation.
--spec blendFuncSeparate(enum(),enum(),enum(),enum()) -> ok.
+%% @doc Specify pixel arithmetic for RGB and alpha components separately
+%%
+%% Pixels can be drawn using a function that blends the incoming (source) RGBA values with
+%% the RGBA values that are already in the frame buffer (the destination values). Blending
+%% is initially disabled. Use {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_BLEND'
+%% to enable and disable blending.
+%%
+%% ``gl:blendFuncSeparate'' defines the operation of blending for all draw buffers when
+%% it is enabled. ``gl:blendFuncSeparatei'' defines the operation of blending for a single
+%% draw buffer specified by `Buf' when enabled for that draw buffer. `SrcRGB' specifies
+%% which method is used to scale the source RGB-color components. `DstRGB' specifies
+%% which method is used to scale the destination RGB-color components. Likewise, `SrcAlpha'
+%% specifies which method is used to scale the source alpha color component, and `DstAlpha'
+%% specifies which method is used to scale the destination alpha component. The possible
+%% methods are described in the following table. Each method defines four scale factors,
+%% one each for red, green, blue, and alpha.
+%%
+%% In the table and in subsequent equations, first source, second source and destination
+%% color components are referred to as (R s0 G s0 B s0 A s0), (R s1 G s1 B s1 A s1), and (R d G d B d A d), respectively. The color specified by {@link gl:blendColor/4}
+%% is referred to as (R c G c B c A c). They are understood to have integer values between 0 and (k R k G k B
+%% k A), where
+%%
+%% k c= 2(m c)-1
+%%
+%% and (m R m G m B m A) is the number of red, green, blue, and alpha bitplanes.
+%%
+%% Source and destination scale factors are referred to as (s R s G s B s A) and (d R d G d B d A). All scale factors have
+%% range [0 1].
+%%
+%% <table><tbody><tr><td>` Parameter '</td><td>` RGB Factor '</td><td>` Alpha Factor '
+%% </td></tr></tbody><tbody><tr><td>`?GL_ZERO'</td><td>(0 0 0)</td><td> 0</td></tr><tr><td>`?GL_ONE'
+%% </td><td>(1 1 1)</td><td> 1</td></tr><tr><td>`?GL_SRC_COLOR'</td><td>(R s0 k/R G s0 k/G B s0
+%% k/B)</td><td> A s0 k/A</td>
+%% </tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td>(1 1 1 1)-(R s0 k/R G s0 k/G B s0 k/B)</td><td> 1-A s0 k/A</td></tr><tr><td>
+%% `?GL_DST_COLOR'</td><td>(R d k/R G d k/G B d k/B)</td><td> A d k/A</td></tr><tr><td>`?GL_ONE_MINUS_DST_COLOR'
+%% </td><td>(1 1 1)-(R d k/R G d k/G B d k/B)</td><td> 1-A d k/A</td></tr><tr><td>`?GL_SRC_ALPHA'</td><td>(A s0 k/A A s0
+%% k/A A s0 k/A)</td><td> A
+%% s0 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1)-(A s0 k/A A s0 k/A A s0 k/A
+%% )</td><td> 1-A s0 k/A</td></tr>
+%% <tr><td>`?GL_DST_ALPHA'</td><td>(A d k/A A d k/A A d k/A)</td><td> A d k/A</td></tr><tr><td>`?GL_ONE_MINUS_DST_ALPHA'
+%% </td><td>(1 1 1)-(A d k/A A d k/A A d k/A)</td><td> 1-A d k/A</td></tr><tr><td>`?GL_CONSTANT_COLOR'</td><td>(R c G c
+%% B c)</td><td>
+%% A c</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_COLOR'</td><td>(1 1 1)-(R c G c B c)</td><td> 1-A c</td></tr>
+%% <tr><td>`?GL_CONSTANT_ALPHA'</td><td>(A c A c A c)</td><td> A c</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_ALPHA'
+%% </td><td>(1 1 1)-(A c A c A c)</td><td> 1-A c</td></tr><tr><td>`?GL_SRC_ALPHA_SATURATE'</td><td>(i i i)</td><td>
+%% 1</td></tr><tr><td>`?GL_SRC1_COLOR'</td><td>(R s1 k/R G s1 k/G B s1 k/B)</td><td> A s1 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'
+%% </td><td>(1 1 1 1)-(R s1 k/R G s1 k/G B s1 k/B)</td><td> 1-A s1 k/A</td></tr><tr><td>`?GL_SRC1_ALPHA'</td><td>(A s1 k/A A
+%% s1 k/A A s1 k/A)</td><td> A
+%% s1 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1)-(A s1 k/A A s1 k/A A s1 k/A
+%% )</td><td> 1-A s1 k/A</td></tr>
+%% </tbody></table>
+%%
+%% In the table,
+%%
+%% i= min(A s 1-(A d))
+%%
+%% To determine the blended RGBA values of a pixel, the system uses the following equations:
+%%
+%%
+%% R d= min(k R R s s R+R d d R) G d= min(k G G s s G+G d d G) B d= min(k B B s s B+B d d B) A d= min(k A A s s A+A d d A)
+%%
+%% Despite the apparent precision of the above equations, blending arithmetic is not exactly
+%% specified, because blending operates with imprecise integer color values. However, a blend
+%% factor that should be equal to 1 is guaranteed not to modify its multiplicand, and a blend
+%% factor equal to 0 reduces its multiplicand to 0. For example, when `SrcRGB' is `?GL_SRC_ALPHA'
+%% , `DstRGB' is `?GL_ONE_MINUS_SRC_ALPHA', and A s is equal to k A, the equations
+%% reduce to simple replacement:
+%%
+%% R d= R s G d= G s B d= B s A d= A s
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml">external</a> documentation.
+-spec blendFuncSeparate(SfactorRGB, DfactorRGB, SfactorAlpha, DfactorAlpha) -> ok when SfactorRGB :: enum(),DfactorRGB :: enum(),SfactorAlpha :: enum(),DfactorAlpha :: enum().
blendFuncSeparate(SfactorRGB,DfactorRGB,SfactorAlpha,DfactorAlpha) ->
cast(5394, <<SfactorRGB:?GLenum,DfactorRGB:?GLenum,SfactorAlpha:?GLenum,DfactorAlpha:?GLenum>>).
-%% @spec (Mode::enum(),First::[integer()],Count::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawArrays.xml">external</a> documentation.
--spec multiDrawArrays(enum(),[integer()],[integer()]) -> ok.
+%% @doc Render multiple sets of primitives from array data
+%%
+%% ``gl:multiDrawArrays'' specifies multiple sets of geometric primitives with very few
+%% subroutine calls. Instead of calling a GL procedure to pass each individual vertex, normal,
+%% texture coordinate, edge flag, or color, you can prespecify separate arrays of vertices,
+%% normals, and colors and use them to construct a sequence of primitives with a single call
+%% to ``gl:multiDrawArrays''.
+%%
+%% ``gl:multiDrawArrays'' behaves identically to {@link gl:drawArrays/3} except that `Primcount'
+%% separate ranges of elements are specified instead.
+%%
+%% When ``gl:multiDrawArrays'' is called, it uses `Count' sequential elements from
+%% each enabled array to construct a sequence of geometric primitives, beginning with element
+%% `First' . `Mode' specifies what kind of primitives are constructed, and how the
+%% array elements construct those primitives.
+%%
+%% Vertex attributes that are modified by ``gl:multiDrawArrays'' have an unspecified value
+%% after ``gl:multiDrawArrays'' returns. Attributes that aren't modified remain well defined.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawArrays.xml">external</a> documentation.
+-spec multiDrawArrays(Mode, First, Count) -> ok when Mode :: enum(),First :: [integer()],Count :: [integer()].
multiDrawArrays(Mode,First,Count) ->
cast(5395, <<Mode:?GLenum,(length(First)):?GLuint,
(<< <<C:?GLint>> || C <- First>>)/binary,0:(((length(First)) rem 2)*32),(length(Count)):?GLuint,
(<< <<C:?GLsizei>> || C <- Count>>)/binary,0:(((1+length(Count)) rem 2)*32)>>).
-%% @spec (Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation.
--spec pointParameterf(enum(),float()) -> ok.
+%% @doc Specify point parameters
+%%
+%% The following values are accepted for `Pname' :
+%%
+%% `?GL_POINT_FADE_THRESHOLD_SIZE': `Params' is a single floating-point value that
+%% specifies the threshold value to which point sizes are clamped if they exceed the specified
+%% value. The default value is 1.0.
+%%
+%% `?GL_POINT_SPRITE_COORD_ORIGIN': `Params' is a single enum specifying the point
+%% sprite texture coordinate origin, either `?GL_LOWER_LEFT' or `?GL_UPPER_LEFT'.
+%% The default value is `?GL_UPPER_LEFT'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation.
+-spec pointParameterf(Pname, Param) -> ok when Pname :: enum(),Param :: float().
pointParameterf(Pname,Param) ->
cast(5396, <<Pname:?GLenum,Param:?GLfloat>>).
-%% @spec (Pname::enum(),Params::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation.
--spec pointParameterfv(enum(),{float()}) -> ok.
+%% @doc
+%% See {@link pointParameterf/2}
+-spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}.
pointParameterfv(Pname,Params) ->
cast(5397, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
-%% @spec (Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation.
--spec pointParameteri(enum(),integer()) -> ok.
+%% @doc
+%% See {@link pointParameterf/2}
+-spec pointParameteri(Pname, Param) -> ok when Pname :: enum(),Param :: integer().
pointParameteri(Pname,Param) ->
cast(5398, <<Pname:?GLenum,Param:?GLint>>).
-%% @spec (Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation.
--spec pointParameteriv(enum(),{integer()}) -> ok.
+%% @doc
+%% See {@link pointParameterf/2}
+-spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}.
pointParameteriv(Pname,Params) ->
cast(5399, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
-%% @spec (Coord::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml">external</a> documentation.
--spec fogCoordf(float()) -> ok.
+%% @doc Set the current fog coordinates
+%%
+%% ``gl:fogCoord'' specifies the fog coordinate that is associated with each vertex and
+%% the current raster position. The value specified is interpolated and used in computing
+%% the fog color (see {@link gl:fogf/2} ).
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml">external</a> documentation.
+-spec fogCoordf(Coord) -> ok when Coord :: float().
fogCoordf(Coord) ->
cast(5400, <<Coord:?GLfloat>>).
-%% @spec ({Coord}) -> ok
%% @equiv fogCoordf(Coord)
--spec fogCoordfv({float()}) -> ok.
+-spec fogCoordfv(Coord) -> ok when Coord :: {Coord :: float()}.
fogCoordfv({Coord}) -> fogCoordf(Coord).
-%% @spec (Coord::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml">external</a> documentation.
--spec fogCoordd(float()) -> ok.
+%% @doc
+%% See {@link fogCoordf/1}
+-spec fogCoordd(Coord) -> ok when Coord :: float().
fogCoordd(Coord) ->
cast(5401, <<Coord:?GLdouble>>).
-%% @spec ({Coord}) -> ok
%% @equiv fogCoordd(Coord)
--spec fogCoorddv({float()}) -> ok.
+-spec fogCoorddv(Coord) -> ok when Coord :: {Coord :: float()}.
fogCoorddv({Coord}) -> fogCoordd(Coord).
-%% @spec (Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoordPointer.xml">external</a> documentation.
--spec fogCoordPointer(enum(),integer(),offset()|mem()) -> ok.
+%% @doc Define an array of fog coordinates
+%%
+%% ``gl:fogCoordPointer'' specifies the location and data format of an array of fog coordinates
+%% to use when rendering. `Type' specifies the data type of each fog coordinate, and `Stride'
+%% specifies the byte stride from one fog coordinate to the next, allowing vertices and
+%% attributes to be packed into a single array or stored in separate arrays.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a fog coordinate array is specified, `Pointer' is treated as a byte offset
+%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as fog coordinate vertex array client-side state (`?GL_FOG_COORD_ARRAY_BUFFER_BINDING'
+%% ).
+%%
+%% When a fog coordinate array is specified, `Type' , `Stride' , and `Pointer'
+%% are saved as client-side state, in addition to the current vertex array buffer object
+%% binding.
+%%
+%% To enable and disable the fog coordinate array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_FOG_COORD_ARRAY'. If enabled, the fog coordinate array is
+%% used when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
+%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoordPointer.xml">external</a> documentation.
+-spec fogCoordPointer(Type, Stride, Pointer) -> ok when Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
fogCoordPointer(Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5402, <<Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
fogCoordPointer(Type,Stride,Pointer) ->
send_bin(Pointer),
cast(5403, <<Type:?GLenum,Stride:?GLsizei>>).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3b(integer(),integer(),integer()) -> ok.
+%% @doc Set the current secondary color
+%%
+%% The GL stores both a primary four-valued RGBA color and a secondary four-valued RGBA
+%% color (where alpha is always set to 0.0) that is associated with every vertex.
+%%
+%% The secondary color is interpolated and applied to each fragment during rasterization
+%% when `?GL_COLOR_SUM' is enabled. When lighting is enabled, and `?GL_SEPARATE_SPECULAR_COLOR'
+%% is specified, the value of the secondary color is assigned the value computed from the
+%% specular term of the lighting computation. Both the primary and secondary current colors
+%% are applied to each fragment, regardless of the state of `?GL_COLOR_SUM', under such
+%% conditions. When `?GL_SEPARATE_SPECULAR_COLOR' is specified, the value returned from
+%% querying the current secondary color is undefined.
+%%
+%% ``gl:secondaryColor3b'', ``gl:secondaryColor3s'', and ``gl:secondaryColor3i'' take
+%% three signed byte, short, or long integers as arguments. When `v' is appended to
+%% the name, the color commands can take a pointer to an array of such values.
+%%
+%% Color values are stored in floating-point format, with unspecified mantissa and exponent
+%% sizes. Unsigned integer color components, when specified, are linearly mapped to floating-point
+%% values such that the largest representable value maps to 1.0 (full intensity), and 0 maps
+%% to 0.0 (zero intensity). Signed integer color components, when specified, are linearly
+%% mapped to floating-point values such that the most positive representable value maps to
+%% 1.0, and the most negative representable value maps to -1.0. (Note that this mapping
+%% does not convert 0 precisely to 0.0). Floating-point values are mapped directly.
+%%
+%% Neither floating-point nor signed integer values are clamped to the range [0 1] before the
+%% current color is updated. However, color components are clamped to this range before they
+%% are interpolated or written into a color buffer.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
+-spec secondaryColor3b(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3b(Red,Green,Blue) ->
cast(5404, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3b(Red,Green,Blue)
--spec secondaryColor3bv({integer(),integer(),integer()}) -> ok.
+-spec secondaryColor3bv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
secondaryColor3bv({Red,Green,Blue}) -> secondaryColor3b(Red,Green,Blue).
-%% @spec (Red::float(),Green::float(),Blue::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3d(float(),float(),float()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3d(Red, Green, Blue) -> ok when Red :: float(),Green :: float(),Blue :: float().
secondaryColor3d(Red,Green,Blue) ->
cast(5405, <<Red:?GLdouble,Green:?GLdouble,Blue:?GLdouble>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3d(Red,Green,Blue)
--spec secondaryColor3dv({float(),float(),float()}) -> ok.
+-spec secondaryColor3dv(V) -> ok when V :: {Red :: float(),Green :: float(),Blue :: float()}.
secondaryColor3dv({Red,Green,Blue}) -> secondaryColor3d(Red,Green,Blue).
-%% @spec (Red::float(),Green::float(),Blue::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3f(float(),float(),float()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3f(Red, Green, Blue) -> ok when Red :: float(),Green :: float(),Blue :: float().
secondaryColor3f(Red,Green,Blue) ->
cast(5406, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3f(Red,Green,Blue)
--spec secondaryColor3fv({float(),float(),float()}) -> ok.
+-spec secondaryColor3fv(V) -> ok when V :: {Red :: float(),Green :: float(),Blue :: float()}.
secondaryColor3fv({Red,Green,Blue}) -> secondaryColor3f(Red,Green,Blue).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3i(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3i(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3i(Red,Green,Blue) ->
cast(5407, <<Red:?GLint,Green:?GLint,Blue:?GLint>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3i(Red,Green,Blue)
--spec secondaryColor3iv({integer(),integer(),integer()}) -> ok.
+-spec secondaryColor3iv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
secondaryColor3iv({Red,Green,Blue}) -> secondaryColor3i(Red,Green,Blue).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3s(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3s(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3s(Red,Green,Blue) ->
cast(5408, <<Red:?GLshort,Green:?GLshort,Blue:?GLshort>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3s(Red,Green,Blue)
--spec secondaryColor3sv({integer(),integer(),integer()}) -> ok.
+-spec secondaryColor3sv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
secondaryColor3sv({Red,Green,Blue}) -> secondaryColor3s(Red,Green,Blue).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3ub(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3ub(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3ub(Red,Green,Blue) ->
cast(5409, <<Red:?GLubyte,Green:?GLubyte,Blue:?GLubyte>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3ub(Red,Green,Blue)
--spec secondaryColor3ubv({integer(),integer(),integer()}) -> ok.
+-spec secondaryColor3ubv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
secondaryColor3ubv({Red,Green,Blue}) -> secondaryColor3ub(Red,Green,Blue).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3ui(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3ui(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3ui(Red,Green,Blue) ->
cast(5410, <<Red:?GLuint,Green:?GLuint,Blue:?GLuint>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3ui(Red,Green,Blue)
--spec secondaryColor3uiv({integer(),integer(),integer()}) -> ok.
+-spec secondaryColor3uiv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
secondaryColor3uiv({Red,Green,Blue}) -> secondaryColor3ui(Red,Green,Blue).
-%% @spec (Red::integer(),Green::integer(),Blue::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
--spec secondaryColor3us(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link secondaryColor3b/3}
+-spec secondaryColor3us(Red, Green, Blue) -> ok when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3us(Red,Green,Blue) ->
cast(5411, <<Red:?GLushort,Green:?GLushort,Blue:?GLushort>>).
-%% @spec ({Red,Green,Blue}) -> ok
%% @equiv secondaryColor3us(Red,Green,Blue)
--spec secondaryColor3usv({integer(),integer(),integer()}) -> ok.
+-spec secondaryColor3usv(V) -> ok when V :: {Red :: integer(),Green :: integer(),Blue :: integer()}.
secondaryColor3usv({Red,Green,Blue}) -> secondaryColor3us(Red,Green,Blue).
-%% @spec (Size::integer(),Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColorPointer.xml">external</a> documentation.
--spec secondaryColorPointer(integer(),enum(),integer(),offset()|mem()) -> ok.
+%% @doc Define an array of secondary colors
+%%
+%% ``gl:secondaryColorPointer'' specifies the location and data format of an array of color
+%% components to use when rendering. `Size' specifies the number of components per color,
+%% and must be 3. `Type' specifies the data type of each color component, and `Stride'
+%% specifies the byte stride from one color to the next, allowing vertices and attributes
+%% to be packed into a single array or stored in separate arrays.
+%%
+%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
+%% ) while a secondary color array is specified, `Pointer' is treated as a byte offset
+%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
+%% ) is saved as secondary color vertex array client-side state (`?GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING'
+%% ).
+%%
+%% When a secondary color array is specified, `Size' , `Type' , `Stride' , and `Pointer'
+%% are saved as client-side state, in addition to the current vertex array buffer object
+%% binding.
+%%
+%% To enable and disable the secondary color array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
+%% with the argument `?GL_SECONDARY_COLOR_ARRAY'. If enabled, the secondary color array
+%% is used when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} ,
+%% {@link gl:drawElements/4} , see `glMultiDrawElements', or {@link gl:drawRangeElements/6}
+%% is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColorPointer.xml">external</a> documentation.
+-spec secondaryColorPointer(Size, Type, Stride, Pointer) -> ok when Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
secondaryColorPointer(Size,Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5412, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
secondaryColorPointer(Size,Type,Stride,Pointer) ->
send_bin(Pointer),
cast(5413, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
-%% @spec (X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos2d(float(),float()) -> ok.
+%% @doc Specify the raster position in window coordinates for pixel operations
+%%
+%% The GL maintains a 3D position in window coordinates. This position, called the raster
+%% position, is used to position pixel and bitmap write operations. It is maintained with
+%% subpixel accuracy. See {@link gl:bitmap/7} , {@link gl:drawPixels/5} , and {@link gl:copyPixels/5}
+%% .
+%%
+%% ``gl:windowPos2'' specifies the x and y coordinates, while z is implicitly set
+%% to 0. ``gl:windowPos3'' specifies all three coordinates. The w coordinate of the current
+%% raster position is always set to 1.0.
+%%
+%% ``gl:windowPos'' directly updates the x and y coordinates of the current raster
+%% position with the values specified. That is, the values are neither transformed by the
+%% current modelview and projection matrices, nor by the viewport-to-window transform. The
+%% z coordinate of the current raster position is updated in the following manner:
+%%
+%% z={n f(n+z*(f-n)) if z&lt;= 0 if z&gt;= 1(otherwise))
+%%
+%% where n is `?GL_DEPTH_RANGE''s near value, and f is `?GL_DEPTH_RANGE''s
+%% far value. See {@link gl:depthRange/2} .
+%%
+%% The specified coordinates are not clip-tested, causing the raster position to always
+%% be valid.
+%%
+%% The current raster position also includes some associated color data and texture coordinates.
+%% If lighting is enabled, then `?GL_CURRENT_RASTER_COLOR' (in RGBA mode) or `?GL_CURRENT_RASTER_INDEX'
+%% (in color index mode) is set to the color produced by the lighting calculation (see {@link gl:lightf/3}
+%% , {@link gl:lightModelf/2} , and {@link gl:shadeModel/1} ). If lighting is disabled, current
+%% color (in RGBA mode, state variable `?GL_CURRENT_COLOR') or color index (in color
+%% index mode, state variable `?GL_CURRENT_INDEX') is used to update the current raster
+%% color. `?GL_CURRENT_RASTER_SECONDARY_COLOR' (in RGBA mode) is likewise updated.
+%%
+%% Likewise, `?GL_CURRENT_RASTER_TEXTURE_COORDS' is updated as a function of `?GL_CURRENT_TEXTURE_COORDS'
+%% , based on the texture matrix and the texture generation functions (see {@link gl:texGend/3} ).
+%% The `?GL_CURRENT_RASTER_DISTANCE' is set to the `?GL_CURRENT_FOG_COORD'.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
+-spec windowPos2d(X, Y) -> ok when X :: float(),Y :: float().
windowPos2d(X,Y) ->
cast(5414, <<X:?GLdouble,Y:?GLdouble>>).
-%% @spec ({X,Y}) -> ok
%% @equiv windowPos2d(X,Y)
--spec windowPos2dv({float(),float()}) -> ok.
+-spec windowPos2dv(V) -> ok when V :: {X :: float(),Y :: float()}.
windowPos2dv({X,Y}) -> windowPos2d(X,Y).
-%% @spec (X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos2f(float(),float()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos2f(X, Y) -> ok when X :: float(),Y :: float().
windowPos2f(X,Y) ->
cast(5415, <<X:?GLfloat,Y:?GLfloat>>).
-%% @spec ({X,Y}) -> ok
%% @equiv windowPos2f(X,Y)
--spec windowPos2fv({float(),float()}) -> ok.
+-spec windowPos2fv(V) -> ok when V :: {X :: float(),Y :: float()}.
windowPos2fv({X,Y}) -> windowPos2f(X,Y).
-%% @spec (X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos2i(integer(),integer()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos2i(X, Y) -> ok when X :: integer(),Y :: integer().
windowPos2i(X,Y) ->
cast(5416, <<X:?GLint,Y:?GLint>>).
-%% @spec ({X,Y}) -> ok
%% @equiv windowPos2i(X,Y)
--spec windowPos2iv({integer(),integer()}) -> ok.
+-spec windowPos2iv(V) -> ok when V :: {X :: integer(),Y :: integer()}.
windowPos2iv({X,Y}) -> windowPos2i(X,Y).
-%% @spec (X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos2s(integer(),integer()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos2s(X, Y) -> ok when X :: integer(),Y :: integer().
windowPos2s(X,Y) ->
cast(5417, <<X:?GLshort,Y:?GLshort>>).
-%% @spec ({X,Y}) -> ok
%% @equiv windowPos2s(X,Y)
--spec windowPos2sv({integer(),integer()}) -> ok.
+-spec windowPos2sv(V) -> ok when V :: {X :: integer(),Y :: integer()}.
windowPos2sv({X,Y}) -> windowPos2s(X,Y).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos3d(float(),float(),float()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos3d(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
windowPos3d(X,Y,Z) ->
cast(5418, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec ({X,Y,Z}) -> ok
%% @equiv windowPos3d(X,Y,Z)
--spec windowPos3dv({float(),float(),float()}) -> ok.
+-spec windowPos3dv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
windowPos3dv({X,Y,Z}) -> windowPos3d(X,Y,Z).
-%% @spec (X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos3f(float(),float(),float()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos3f(X, Y, Z) -> ok when X :: float(),Y :: float(),Z :: float().
windowPos3f(X,Y,Z) ->
cast(5419, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec ({X,Y,Z}) -> ok
%% @equiv windowPos3f(X,Y,Z)
--spec windowPos3fv({float(),float(),float()}) -> ok.
+-spec windowPos3fv(V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
windowPos3fv({X,Y,Z}) -> windowPos3f(X,Y,Z).
-%% @spec (X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos3i(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos3i(X, Y, Z) -> ok when X :: integer(),Y :: integer(),Z :: integer().
windowPos3i(X,Y,Z) ->
cast(5420, <<X:?GLint,Y:?GLint,Z:?GLint>>).
-%% @spec ({X,Y,Z}) -> ok
%% @equiv windowPos3i(X,Y,Z)
--spec windowPos3iv({integer(),integer(),integer()}) -> ok.
+-spec windowPos3iv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
windowPos3iv({X,Y,Z}) -> windowPos3i(X,Y,Z).
-%% @spec (X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
--spec windowPos3s(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link windowPos2d/2}
+-spec windowPos3s(X, Y, Z) -> ok when X :: integer(),Y :: integer(),Z :: integer().
windowPos3s(X,Y,Z) ->
cast(5421, <<X:?GLshort,Y:?GLshort,Z:?GLshort>>).
-%% @spec ({X,Y,Z}) -> ok
%% @equiv windowPos3s(X,Y,Z)
--spec windowPos3sv({integer(),integer(),integer()}) -> ok.
+-spec windowPos3sv(V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
windowPos3sv({X,Y,Z}) -> windowPos3s(X,Y,Z).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenQueries.xml">external</a> documentation.
--spec genQueries(integer()) -> [integer()].
+%% @doc Generate query object names
+%%
+%% ``gl:genQueries'' returns `N' query object names in `Ids' . There is no guarantee
+%% that the names form a contiguous set of integers; however, it is guaranteed that none
+%% of the returned names was in use immediately before the call to ``gl:genQueries''.
+%%
+%% Query object names returned by a call to ``gl:genQueries'' are not returned by subsequent
+%% calls, unless they are first deleted with {@link gl:deleteQueries/1} .
+%%
+%% No query objects are associated with the returned query object names until they are first
+%% used by calling {@link gl:beginQuery/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenQueries.xml">external</a> documentation.
+-spec genQueries(N) -> [integer()] when N :: integer().
genQueries(N) ->
call(5422, <<N:?GLsizei>>).
-%% @spec (Ids::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteQueries.xml">external</a> documentation.
--spec deleteQueries([integer()]) -> ok.
+%% @doc Delete named query objects
+%%
+%% ``gl:deleteQueries'' deletes `N' query objects named by the elements of the array `Ids'
+%% . After a query object is deleted, it has no contents, and its name is free for reuse
+%% (for example by {@link gl:genQueries/1} ).
+%%
+%% ``gl:deleteQueries'' silently ignores 0's and names that do not correspond to existing
+%% query objects.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteQueries.xml">external</a> documentation.
+-spec deleteQueries(Ids) -> ok when Ids :: [integer()].
deleteQueries(Ids) ->
cast(5423, <<(length(Ids)):?GLuint,
(<< <<C:?GLuint>> || C <- Ids>>)/binary,0:(((1+length(Ids)) rem 2)*32)>>).
-%% @spec (Id::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsQuery.xml">external</a> documentation.
--spec isQuery(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a query object
+%%
+%% ``gl:isQuery'' returns `?GL_TRUE' if `Id' is currently the name of a query
+%% object. If `Id' is zero, or is a non-zero value that is not currently the name of
+%% a query object, or if an error occurs, ``gl:isQuery'' returns `?GL_FALSE'.
+%%
+%% A name returned by {@link gl:genQueries/1} , but not yet associated with a query object
+%% by calling {@link gl:beginQuery/2} , is not the name of a query object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsQuery.xml">external</a> documentation.
+-spec isQuery(Id) -> 0|1 when Id :: integer().
isQuery(Id) ->
call(5424, <<Id:?GLuint>>).
-%% @spec (Target::enum(),Id::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml">external</a> documentation.
--spec beginQuery(enum(),integer()) -> ok.
+%% @doc Delimit the boundaries of a query object
+%%
+%% ``gl:beginQuery'' and {@link gl:beginQuery/2} delimit the boundaries of a query object. `Query'
+%% must be a name previously returned from a call to {@link gl:genQueries/1} . If a query
+%% object with name `Id' does not yet exist it is created with the type determined by `Target'
+%% . `Target' must be one of `?GL_SAMPLES_PASSED', `?GL_ANY_SAMPLES_PASSED', `?GL_PRIMITIVES_GENERATED'
+%% , `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', or `?GL_TIME_ELAPSED'. The behavior
+%% of the query object depends on its type and is as follows.
+%%
+%% If `Target' is `?GL_SAMPLES_PASSED', `Id' must be an unused name, or the
+%% name of an existing occlusion query object. When ``gl:beginQuery'' is executed, the
+%% query object's samples-passed counter is reset to 0. Subsequent rendering will increment
+%% the counter for every sample that passes the depth test. If the value of `?GL_SAMPLE_BUFFERS'
+%% is 0, then the samples-passed count is incremented by 1 for each fragment. If the value
+%% of `?GL_SAMPLE_BUFFERS' is 1, then the samples-passed count is incremented by the
+%% number of samples whose coverage bit is set. However, implementations, at their discression
+%% may instead increase the samples-passed count by the value of `?GL_SAMPLES' if any
+%% sample in the fragment is covered. When ``gl:endQuery'' is executed, the samples-passed
+%% counter is assigned to the query object's result value. This value can be queried by calling
+%% {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'.
+%%
+%% If `Target' is `?GL_ANY_SAMPLES_PASSED', `Id' must be an unused name,
+%% or the name of an existing boolean occlusion query object. When ``gl:beginQuery'' is
+%% executed, the query object's samples-passed flag is reset to `?GL_FALSE'. Subsequent
+%% rendering causes the flag to be set to `?GL_TRUE' if any sample passes the depth
+%% test. When ``gl:endQuery'' is executed, the samples-passed flag is assigned to the query
+%% object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
+%% with `Pname' `?GL_QUERY_RESULT'.
+%%
+%% If `Target' is `?GL_PRIMITIVES_GENERATED', `Id' must be an unused name,
+%% or the name of an existing primitive query object previously bound to the `?GL_PRIMITIVES_GENERATED'
+%% query binding. When ``gl:beginQuery'' is executed, the query object's primitives-generated
+%% counter is reset to 0. Subsequent rendering will increment the counter once for every
+%% vertex that is emitted from the geometry shader, or from the vertex shader if no geometry
+%% shader is present. When ``gl:endQuery'' is executed, the primitives-generated counter
+%% is assigned to the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
+%% with `Pname' `?GL_QUERY_RESULT'.
+%%
+%% If `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', `Id' must
+%% be an unused name, or the name of an existing primitive query object previously bound
+%% to the `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' query binding. When ``gl:beginQuery''
+%% is executed, the query object's primitives-written counter is reset to 0. Subsequent
+%% rendering will increment the counter once for every vertex that is written into the bound
+%% transform feedback buffer(s). If transform feedback mode is not activated between the
+%% call to ``gl:beginQuery'' and ``gl:endQuery'', the counter will not be incremented.
+%% When ``gl:endQuery'' is executed, the primitives-written counter is assigned to the
+%% query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
+%% with `Pname' `?GL_QUERY_RESULT'.
+%%
+%% If `Target' is `?GL_TIME_ELAPSED', `Id' must be an unused name, or the
+%% name of an existing timer query object previously bound to the `?GL_TIME_ELAPSED'
+%% query binding. When ``gl:beginQuery'' is executed, the query object's time counter is
+%% reset to 0. When ``gl:endQuery'' is executed, the elapsed server time that has passed
+%% since the call to ``gl:beginQuery'' is written into the query object's time counter.
+%% This value can be queried by calling {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'
+%% .
+%%
+%% Querying the `?GL_QUERY_RESULT' implicitly flushes the GL pipeline until the rendering
+%% delimited by the query object has completed and the result is available. `?GL_QUERY_RESULT_AVAILABLE'
+%% can be queried to determine if the result is immediately available or if the rendering
+%% is not yet complete.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml">external</a> documentation.
+-spec beginQuery(Target, Id) -> ok when Target :: enum(),Id :: integer().
beginQuery(Target,Id) ->
cast(5425, <<Target:?GLenum,Id:?GLuint>>).
-%% @spec (Target::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEndQuery.xml">external</a> documentation.
--spec endQuery(enum()) -> ok.
+%% @doc
+%% See {@link beginQuery/2}
+-spec endQuery(Target) -> ok when Target :: enum().
endQuery(Target) ->
cast(5426, <<Target:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQuery.xml">external</a> documentation.
--spec getQueryiv(enum(),enum()) -> integer().
+%% @doc glGetQuery
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQuery.xml">external</a> documentation.
+-spec getQueryiv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum().
getQueryiv(Target,Pname) ->
call(5427, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Id::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml">external</a> documentation.
--spec getQueryObjectiv(integer(),enum()) -> integer().
+%% @doc Return parameters of a query object
+%%
+%% ``gl:getQueryObject'' returns in `Params' a selected parameter of the query object
+%% specified by `Id' .
+%%
+%% `Pname' names a specific query object parameter. `Pname' can be as follows:
+%%
+%% `?GL_QUERY_RESULT': `Params' returns the value of the query object's passed
+%% samples counter. The initial value is 0.
+%%
+%% `?GL_QUERY_RESULT_AVAILABLE': `Params' returns whether the passed samples counter
+%% is immediately available. If a delay would occur waiting for the query result, `?GL_FALSE'
+%% is returned. Otherwise, `?GL_TRUE' is returned, which also indicates that the results
+%% of all previous queries are available as well.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml">external</a> documentation.
+-spec getQueryObjectiv(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjectiv(Id,Pname) ->
call(5428, <<Id:?GLuint,Pname:?GLenum>>).
-%% @spec (Id::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml">external</a> documentation.
--spec getQueryObjectuiv(integer(),enum()) -> integer().
+%% @doc
+%% See {@link getQueryObjectiv/2}
+-spec getQueryObjectuiv(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjectuiv(Id,Pname) ->
call(5429, <<Id:?GLuint,Pname:?GLenum>>).
-%% @spec (Target::enum(),Buffer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml">external</a> documentation.
--spec bindBuffer(enum(),integer()) -> ok.
+%% @doc Bind a named buffer object
+%%
+%% ``gl:bindBuffer'' binds a buffer object to the specified buffer binding point. Calling ``gl:bindBuffer''
+%% with `Target' set to one of the accepted symbolic constants and `Buffer' set
+%% to the name of a buffer object binds that buffer object name to the target. If no buffer
+%% object with name `Buffer' exists, one is created with that name. When a buffer object
+%% is bound to a target, the previous binding for that target is automatically broken.
+%%
+%% Buffer object names are unsigned integers. The value zero is reserved, but there is no
+%% default buffer object for each buffer object target. Instead, `Buffer' set to zero
+%% effectively unbinds any buffer object previously bound, and restores client memory usage
+%% for that buffer object target (if supported for that target). Buffer object names and
+%% the corresponding buffer object contents are local to the shared object space of the current
+%% GL rendering context; two rendering contexts share buffer object names only if they explicitly
+%% enable sharing between contexts through the appropriate GL windows interfaces functions.
+%%
+%% {@link gl:genBuffers/1} must be used to generate a set of unused buffer object names.
+%%
+%% The state of a buffer object immediately after it is first bound is an unmapped zero-sized
+%% memory buffer with `?GL_READ_WRITE' access and `?GL_STATIC_DRAW' usage.
+%%
+%% While a non-zero buffer object name is bound, GL operations on the target to which it
+%% is bound affect the bound buffer object, and queries of the target to which it is bound
+%% return state from the bound buffer object. While buffer object name zero is bound, as
+%% in the initial state, attempts to modify or query state on the target to which it is bound
+%% generates an `?GL_INVALID_OPERATION' error.
+%%
+%% When a non-zero buffer object is bound to the `?GL_ARRAY_BUFFER' target, the vertex
+%% array pointer parameter is interpreted as an offset within the buffer object measured
+%% in basic machine units.
+%%
+%% When a non-zero buffer object is bound to the `?GL_DRAW_INDIRECT_BUFFER' target,
+%% parameters for draws issued through {@link gl:drawArraysIndirect/2} and {@link gl:drawElementsIndirect/3}
+%% are sourced from that buffer object.
+%%
+%% While a non-zero buffer object is bound to the `?GL_ELEMENT_ARRAY_BUFFER' target,
+%% the indices parameter of {@link gl:drawElements/4} , {@link gl:drawElementsInstanced/5} , {@link gl:drawElementsBaseVertex/5}
+%% , {@link gl:drawRangeElements/6} , {@link gl:drawRangeElementsBaseVertex/7} , see `glMultiDrawElements'
+%% , or see `glMultiDrawElementsBaseVertex' is interpreted as an offset within the
+%% buffer object measured in basic machine units.
+%%
+%% While a non-zero buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target,
+%% the following commands are affected: {@link gl:getCompressedTexImage/3} , {@link gl:getTexImage/5}
+%% , and {@link gl:readPixels/7} . The pointer parameter is interpreted as an offset within
+%% the buffer object measured in basic machine units.
+%%
+%% While a non-zero buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target,
+%% the following commands are affected: {@link gl:compressedTexImage1D/7} , {@link gl:compressedTexImage2D/8}
+%% , {@link gl:compressedTexImage3D/9} , {@link gl:compressedTexSubImage1D/7} , {@link gl:compressedTexSubImage2D/9}
+%% , {@link gl:compressedTexSubImage3D/11} , {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
+%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7} .
+%% The pointer parameter is interpreted as an offset within the buffer object measured in
+%% basic machine units.
+%%
+%% The buffer targets `?GL_COPY_READ_BUFFER' and `?GL_COPY_WRITE_BUFFER' are provided
+%% to allow {@link gl:copyBufferSubData/5} to be used without disturbing the state of other
+%% bindings. However, {@link gl:copyBufferSubData/5} may be used with any pair of buffer binding
+%% points.
+%%
+%% The `?GL_TRANSFORM_FEEDBACK_BUFFER' buffer binding point may be passed to ``gl:bindBuffer''
+%% , but will not directly affect transform feedback state. Instead, the indexed `?GL_TRANSFORM_FEEDBACK_BUFFER'
+%% bindings must be used through a call to {@link gl:bindBufferBase/3} or {@link gl:bindBufferRange/5}
+%% . This will affect the generic `?GL_TRANSFORM_FEEDABCK_BUFFER' binding.
+%%
+%% Likewise, the `?GL_UNIFORM_BUFFER' and `?GL_ATOMIC_COUNTER_BUFFER' buffer binding
+%% points may be used, but do not directly affect uniform buffer or atomic counter buffer
+%% state, respectively. {@link gl:bindBufferBase/3} or {@link gl:bindBufferRange/5} must be
+%% used to bind a buffer to an indexed uniform buffer or atomic counter buffer binding point.
+%%
+%%
+%% A buffer object binding created with ``gl:bindBuffer'' remains active until a different
+%% buffer object name is bound to the same target, or until the bound buffer object is deleted
+%% with {@link gl:deleteBuffers/1} .
+%%
+%% Once created, a named buffer object may be re-bound to any target as often as needed.
+%% However, the GL implementation may make choices about how to optimize the storage of a
+%% buffer object based on its initial binding target.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml">external</a> documentation.
+-spec bindBuffer(Target, Buffer) -> ok when Target :: enum(),Buffer :: integer().
bindBuffer(Target,Buffer) ->
cast(5430, <<Target:?GLenum,Buffer:?GLuint>>).
-%% @spec (Buffers::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml">external</a> documentation.
--spec deleteBuffers([integer()]) -> ok.
+%% @doc Delete named buffer objects
+%%
+%% ``gl:deleteBuffers'' deletes `N' buffer objects named by the elements of the array
+%% `Buffers' . After a buffer object is deleted, it has no contents, and its name is
+%% free for reuse (for example by {@link gl:genBuffers/1} ). If a buffer object that is currently
+%% bound is deleted, the binding reverts to 0 (the absence of any buffer object).
+%%
+%% ``gl:deleteBuffers'' silently ignores 0's and names that do not correspond to existing
+%% buffer objects.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml">external</a> documentation.
+-spec deleteBuffers(Buffers) -> ok when Buffers :: [integer()].
deleteBuffers(Buffers) ->
cast(5431, <<(length(Buffers)):?GLuint,
(<< <<C:?GLuint>> || C <- Buffers>>)/binary,0:(((1+length(Buffers)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml">external</a> documentation.
--spec genBuffers(integer()) -> [integer()].
+%% @doc Generate buffer object names
+%%
+%% ``gl:genBuffers'' returns `N' buffer object names in `Buffers' . There is no
+%% guarantee that the names form a contiguous set of integers; however, it is guaranteed
+%% that none of the returned names was in use immediately before the call to ``gl:genBuffers''
+%% .
+%%
+%% Buffer object names returned by a call to ``gl:genBuffers'' are not returned by subsequent
+%% calls, unless they are first deleted with {@link gl:deleteBuffers/1} .
+%%
+%% No buffer objects are associated with the returned buffer object names until they are
+%% first bound by calling {@link gl:bindBuffer/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml">external</a> documentation.
+-spec genBuffers(N) -> [integer()] when N :: integer().
genBuffers(N) ->
call(5432, <<N:?GLsizei>>).
-%% @spec (Buffer::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsBuffer.xml">external</a> documentation.
--spec isBuffer(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a buffer object
+%%
+%% ``gl:isBuffer'' returns `?GL_TRUE' if `Buffer' is currently the name of a
+%% buffer object. If `Buffer' is zero, or is a non-zero value that is not currently
+%% the name of a buffer object, or if an error occurs, ``gl:isBuffer'' returns `?GL_FALSE'
+%% .
+%%
+%% A name returned by {@link gl:genBuffers/1} , but not yet associated with a buffer object
+%% by calling {@link gl:bindBuffer/2} , is not the name of a buffer object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsBuffer.xml">external</a> documentation.
+-spec isBuffer(Buffer) -> 0|1 when Buffer :: integer().
isBuffer(Buffer) ->
call(5433, <<Buffer:?GLuint>>).
-%% @spec (Target::enum(),Size::integer(),Data::offset()|mem(),Usage::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml">external</a> documentation.
--spec bufferData(enum(),integer(),offset()|mem(),enum()) -> ok.
+%% @doc Creates and initializes a buffer object's data store
+%%
+%% ``gl:bufferData'' creates a new data store for the buffer object currently bound to `Target'
+%% . Any pre-existing data store is deleted. The new data store is created with the specified
+%% `Size' in bytes and `Usage' . If `Data' is not `?NULL', the data store
+%% is initialized with data from this pointer. In its initial state, the new data store
+%% is not mapped, it has a `?NULL' mapped pointer, and its mapped access is `?GL_READ_WRITE'
+%% .
+%%
+%% `Usage' is a hint to the GL implementation as to how a buffer object's data store
+%% will be accessed. This enables the GL implementation to make more intelligent decisions
+%% that may significantly impact buffer object performance. It does not, however, constrain
+%% the actual usage of the data store. `Usage' can be broken down into two parts: first,
+%% the frequency of access (modification and usage), and second, the nature of that access.
+%% The frequency of access may be one of these:
+%%
+%% STREAM: The data store contents will be modified once and used at most a few times.
+%%
+%% STATIC: The data store contents will be modified once and used many times.
+%%
+%% DYNAMIC: The data store contents will be modified repeatedly and used many times.
+%%
+%% The nature of access may be one of these:
+%%
+%% DRAW: The data store contents are modified by the application, and used as the source
+%% for GL drawing and image specification commands.
+%%
+%% READ: The data store contents are modified by reading data from the GL, and used to return
+%% that data when queried by the application.
+%%
+%% COPY: The data store contents are modified by reading data from the GL, and used as the
+%% source for GL drawing and image specification commands.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml">external</a> documentation.
+-spec bufferData(Target, Size, Data, Usage) -> ok when Target :: enum(),Size :: integer(),Data :: offset()|mem(),Usage :: enum().
bufferData(Target,Size,Data,Usage) when is_integer(Data) ->
cast(5434, <<Target:?GLenum,0:32,Size:?GLsizeiptr,Data:?GLuint,Usage:?GLenum>>);
bufferData(Target,Size,Data,Usage) ->
send_bin(Data),
cast(5435, <<Target:?GLenum,0:32,Size:?GLsizeiptr,Usage:?GLenum>>).
-%% @spec (Target::enum(),Offset::integer(),Size::integer(),Data::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferSubData.xml">external</a> documentation.
--spec bufferSubData(enum(),integer(),integer(),offset()|mem()) -> ok.
+%% @doc Updates a subset of a buffer object's data store
+%%
+%% ``gl:bufferSubData'' redefines some or all of the data store for the buffer object currently
+%% bound to `Target' . Data starting at byte offset `Offset' and extending for `Size'
+%% bytes is copied to the data store from the memory pointed to by `Data' . An error
+%% is thrown if `Offset' and `Size' together define a range beyond the bounds of
+%% the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferSubData.xml">external</a> documentation.
+-spec bufferSubData(Target, Offset, Size, Data) -> ok when Target :: enum(),Offset :: integer(),Size :: integer(),Data :: offset()|mem().
bufferSubData(Target,Offset,Size,Data) when is_integer(Data) ->
cast(5436, <<Target:?GLenum,0:32,Offset:?GLintptr,Size:?GLsizeiptr,Data:?GLuint>>);
bufferSubData(Target,Offset,Size,Data) ->
send_bin(Data),
cast(5437, <<Target:?GLenum,0:32,Offset:?GLintptr,Size:?GLsizeiptr>>).
-%% @spec (Target::enum(),Offset::integer(),Size::integer(),Data::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferSubData.xml">external</a> documentation.
--spec getBufferSubData(enum(),integer(),integer(),mem()) -> ok.
+%% @doc Returns a subset of a buffer object's data store
+%%
+%% ``gl:getBufferSubData'' returns some or all of the data from the buffer object currently
+%% bound to `Target' . Data starting at byte offset `Offset' and extending for `Size'
+%% bytes is copied from the data store to the memory pointed to by `Data' . An error
+%% is thrown if the buffer object is currently mapped, or if `Offset' and `Size'
+%% together define a range beyond the bounds of the buffer object's data store.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferSubData.xml">external</a> documentation.
+-spec getBufferSubData(Target, Offset, Size, Data) -> ok when Target :: enum(),Offset :: integer(),Size :: integer(),Data :: mem().
getBufferSubData(Target,Offset,Size,Data) ->
send_bin(Data),
call(5438, <<Target:?GLenum,0:32,Offset:?GLintptr,Size:?GLsizeiptr>>).
-%% @spec (Target::enum(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteriv.xml">external</a> documentation.
--spec getBufferParameteriv(enum(),enum()) -> integer().
+%% @doc Return parameters of a buffer object
+%%
+%% ``gl:getBufferParameteriv'' returns in `Data' a selected parameter of the buffer
+%% object specified by `Target' .
+%%
+%% `Value' names a specific buffer object parameter, as follows:
+%%
+%% `?GL_BUFFER_ACCESS': `Params' returns the access policy set while mapping the
+%% buffer object. The initial value is `?GL_READ_WRITE'.
+%%
+%% `?GL_BUFFER_MAPPED': `Params' returns a flag indicating whether the buffer object
+%% is currently mapped. The initial value is `?GL_FALSE'.
+%%
+%% `?GL_BUFFER_SIZE': `Params' returns the size of the buffer object, measured
+%% in bytes. The initial value is 0.
+%%
+%% `?GL_BUFFER_USAGE': `Params' returns the buffer object's usage pattern. The
+%% initial value is `?GL_STATIC_DRAW'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteriv.xml">external</a> documentation.
+-spec getBufferParameteriv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum().
getBufferParameteriv(Target,Pname) ->
call(5439, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (ModeRGB::enum(),ModeAlpha::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml">external</a> documentation.
--spec blendEquationSeparate(enum(),enum()) -> ok.
+%% @doc Set the RGB blend equation and the alpha blend equation separately
+%%
+%% The blend equations determines how a new pixel (the ''source'' color) is combined with
+%% a pixel already in the framebuffer (the ''destination'' color). These functions specifie
+%% one blend equation for the RGB-color components and one blend equation for the alpha
+%% component. ``gl:blendEquationSeparatei'' specifies the blend equations for a single
+%% draw buffer whereas ``gl:blendEquationSeparate'' sets the blend equations for all draw
+%% buffers.
+%%
+%% The blend equations use the source and destination blend factors specified by either {@link gl:blendFunc/2}
+%% or {@link gl:blendFuncSeparate/4} . See {@link gl:blendFunc/2} or {@link gl:blendFuncSeparate/4}
+%% for a description of the various blend factors.
+%%
+%% In the equations that follow, source and destination color components are referred to
+%% as (R s G s B s A s) and (R d G d B d A d), respectively. The result color is referred to as (R r G r B r A r). The source and destination
+%% blend factors are denoted (s R s G s B s A) and (d R d G d B d A), respectively. For these equations all color components
+%% are understood to have values in the range [0 1]. <table><tbody><tr><td>` Mode '</td><td>
+%% ` RGB Components '</td><td>` Alpha Component '</td></tr></tbody><tbody><tr><td>`?GL_FUNC_ADD'
+%% </td><td> Rr= R s s R+R d d R Gr= G s s G+G d d G Br= B s s B+B d d B</td><td> Ar=
+%% A s s A+A d d A</td></tr><tr><td>`?GL_FUNC_SUBTRACT'</td><td> Rr= R s s R-R d d
+%% R Gr= G s s G-G d d G Br= B s s B-B d d B</td><td> Ar= A s s A-A d d A</td></tr><tr>
+%% <td>`?GL_FUNC_REVERSE_SUBTRACT'</td><td> Rr= R d d R-R s s R Gr= G d d G-G s s G
+%% Br= B d d B-B s s B</td><td> Ar= A d d A-A s s A</td></tr><tr><td>`?GL_MIN'</td><td>
+%% Rr= min(R s R d) Gr= min(G s G d) Br= min(B s B d)</td><td> Ar= min(A s A d)</td></tr><tr><td>`?GL_MAX'</td><td> Rr=
+%% max(R s R d) Gr= max(G s G d) Br= max(B s B d)</td><td> Ar= max(A s A d)</td></tr></tbody></table>
+%%
+%% The results of these equations are clamped to the range [0 1].
+%%
+%% The `?GL_MIN' and `?GL_MAX' equations are useful for applications that analyze
+%% image data (image thresholding against a constant color, for example). The `?GL_FUNC_ADD'
+%% equation is useful for antialiasing and transparency, among other things.
+%%
+%% Initially, both the RGB blend equation and the alpha blend equation are set to `?GL_FUNC_ADD'
+%% .
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml">external</a> documentation.
+-spec blendEquationSeparate(ModeRGB, ModeAlpha) -> ok when ModeRGB :: enum(),ModeAlpha :: enum().
blendEquationSeparate(ModeRGB,ModeAlpha) ->
cast(5440, <<ModeRGB:?GLenum,ModeAlpha:?GLenum>>).
-%% @spec (Bufs::[enum()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml">external</a> documentation.
--spec drawBuffers([enum()]) -> ok.
+%% @doc Specifies a list of color buffers to be drawn into
+%%
+%% ``gl:drawBuffers'' defines an array of buffers into which outputs from the fragment
+%% shader data will be written. If a fragment shader writes a value to one or more user defined
+%% output variables, then the value of each variable will be written into the buffer specified
+%% at a location within `Bufs' corresponding to the location assigned to that user defined
+%% output. The draw buffer used for user defined outputs assigned to locations greater than
+%% or equal to `N' is implicitly set to `?GL_NONE' and any data written to such
+%% an output is discarded.
+%%
+%% The symbolic constants contained in `Bufs' may be any of the following:
+%%
+%% `?GL_NONE': The fragment shader output value is not written into any color buffer.
+%%
+%% `?GL_FRONT_LEFT': The fragment shader output value is written into the front left
+%% color buffer.
+%%
+%% `?GL_FRONT_RIGHT': The fragment shader output value is written into the front right
+%% color buffer.
+%%
+%% `?GL_BACK_LEFT': The fragment shader output value is written into the back left color
+%% buffer.
+%%
+%% `?GL_BACK_RIGHT': The fragment shader output value is written into the back right
+%% color buffer.
+%%
+%% `?GL_COLOR_ATTACHMENT'`n': The fragment shader output value is written into
+%% the `n'th color attachment of the current framebuffer. `n' may range from 0
+%% to the value of `?GL_MAX_COLOR_ATTACHMENTS'.
+%%
+%% Except for `?GL_NONE', the preceding symbolic constants may not appear more than
+%% once in `Bufs' . The maximum number of draw buffers supported is implementation dependent
+%% and can be queried by calling {@link gl:getBooleanv/1} with the argument `?GL_MAX_DRAW_BUFFERS'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml">external</a> documentation.
+-spec drawBuffers(Bufs) -> ok when Bufs :: [enum()].
drawBuffers(Bufs) ->
cast(5441, <<(length(Bufs)):?GLuint,
(<< <<C:?GLenum>> || C <- Bufs>>)/binary,0:(((1+length(Bufs)) rem 2)*32)>>).
-%% @spec (Face::enum(),Sfail::enum(),Dpfail::enum(),Dppass::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml">external</a> documentation.
--spec stencilOpSeparate(enum(),enum(),enum(),enum()) -> ok.
+%% @doc Set front and/or back stencil test actions
+%%
+%% Stenciling, like depth-buffering, enables and disables drawing on a per-pixel basis.
+%% You draw into the stencil planes using GL drawing primitives, then render geometry and
+%% images, using the stencil planes to mask out portions of the screen. Stenciling is typically
+%% used in multipass rendering algorithms to achieve special effects, such as decals, outlining,
+%% and constructive solid geometry rendering.
+%%
+%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
+%% between the value in the stencil buffer and a reference value. To enable and disable the
+%% test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
+%% ; to control it, call {@link gl:stencilFunc/3} or {@link gl:stencilFuncSeparate/4} .
+%%
+%% There can be two separate sets of `Sfail' , `Dpfail' , and `Dppass' parameters;
+%% one affects back-facing polygons, and the other affects front-facing polygons as well
+%% as other non-polygon primitives. {@link gl:stencilOp/3} sets both front and back stencil
+%% state to the same values, as if {@link gl:stencilOpSeparate/4} were called with `Face'
+%% set to `?GL_FRONT_AND_BACK'.
+%%
+%% ``gl:stencilOpSeparate'' takes three arguments that indicate what happens to the stored
+%% stencil value while stenciling is enabled. If the stencil test fails, no change is made
+%% to the pixel's color or depth buffers, and `Sfail' specifies what happens to the
+%% stencil buffer contents. The following eight actions are possible.
+%%
+%% `?GL_KEEP': Keeps the current value.
+%%
+%% `?GL_ZERO': Sets the stencil buffer value to 0.
+%%
+%% `?GL_REPLACE': Sets the stencil buffer value to `ref', as specified by {@link gl:stencilFunc/3}
+%% .
+%%
+%% `?GL_INCR': Increments the current stencil buffer value. Clamps to the maximum representable
+%% unsigned value.
+%%
+%% `?GL_INCR_WRAP': Increments the current stencil buffer value. Wraps stencil buffer
+%% value to zero when incrementing the maximum representable unsigned value.
+%%
+%% `?GL_DECR': Decrements the current stencil buffer value. Clamps to 0.
+%%
+%% `?GL_DECR_WRAP': Decrements the current stencil buffer value. Wraps stencil buffer
+%% value to the maximum representable unsigned value when decrementing a stencil buffer value
+%% of zero.
+%%
+%% `?GL_INVERT': Bitwise inverts the current stencil buffer value.
+%%
+%% Stencil buffer values are treated as unsigned integers. When incremented and decremented,
+%% values are clamped to 0 and 2 n-1, where n is the value returned by querying `?GL_STENCIL_BITS'
+%% .
+%%
+%% The other two arguments to ``gl:stencilOpSeparate'' specify stencil buffer actions
+%% that depend on whether subsequent depth buffer tests succeed ( `Dppass' ) or fail ( `Dpfail'
+%% ) (see {@link gl:depthFunc/1} ). The actions are specified using the same eight symbolic
+%% constants as `Sfail' . Note that `Dpfail' is ignored when there is no depth buffer,
+%% or when the depth buffer is not enabled. In these cases, `Sfail' and `Dppass'
+%% specify stencil action when the stencil test fails and passes, respectively.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml">external</a> documentation.
+-spec stencilOpSeparate(Face, Sfail, Dpfail, Dppass) -> ok when Face :: enum(),Sfail :: enum(),Dpfail :: enum(),Dppass :: enum().
stencilOpSeparate(Face,Sfail,Dpfail,Dppass) ->
cast(5442, <<Face:?GLenum,Sfail:?GLenum,Dpfail:?GLenum,Dppass:?GLenum>>).
-%% @spec (Face::enum(),Func::enum(),Ref::integer(),Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml">external</a> documentation.
--spec stencilFuncSeparate(enum(),enum(),integer(),integer()) -> ok.
+%% @doc Set front and/or back function and reference value for stencil testing
+%%
+%% Stenciling, like depth-buffering, enables and disables drawing on a per-pixel basis.
+%% You draw into the stencil planes using GL drawing primitives, then render geometry and
+%% images, using the stencil planes to mask out portions of the screen. Stenciling is typically
+%% used in multipass rendering algorithms to achieve special effects, such as decals, outlining,
+%% and constructive solid geometry rendering.
+%%
+%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
+%% between the reference value and the value in the stencil buffer. To enable and disable
+%% the test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
+%% . To specify actions based on the outcome of the stencil test, call {@link gl:stencilOp/3}
+%% or {@link gl:stencilOpSeparate/4} .
+%%
+%% There can be two separate sets of `Func' , `Ref' , and `Mask' parameters;
+%% one affects back-facing polygons, and the other affects front-facing polygons as well
+%% as other non-polygon primitives. {@link gl:stencilFunc/3} sets both front and back stencil
+%% state to the same values, as if {@link gl:stencilFuncSeparate/4} were called with `Face'
+%% set to `?GL_FRONT_AND_BACK'.
+%%
+%% `Func' is a symbolic constant that determines the stencil comparison function. It
+%% accepts one of eight values, shown in the following list. `Ref' is an integer reference
+%% value that is used in the stencil comparison. It is clamped to the range [0 2 n-1], where n
+%% is the number of bitplanes in the stencil buffer. `Mask' is bitwise ANDed with both
+%% the reference value and the stored stencil value, with the ANDed values participating
+%% in the comparison.
+%%
+%% If `stencil' represents the value stored in the corresponding stencil buffer location,
+%% the following list shows the effect of each comparison function that can be specified by `Func'
+%% . Only if the comparison succeeds is the pixel passed through to the next stage in the
+%% rasterization process (see {@link gl:stencilOp/3} ). All tests treat `stencil' values
+%% as unsigned integers in the range [0 2 n-1], where n is the number of bitplanes in the stencil
+%% buffer.
+%%
+%% The following values are accepted by `Func' :
+%%
+%% `?GL_NEVER': Always fails.
+%%
+%% `?GL_LESS': Passes if ( `Ref' &amp; `Mask' ) &lt; ( `stencil' &amp; `Mask'
+%% ).
+%%
+%% `?GL_LEQUAL': Passes if ( `Ref' &amp; `Mask' ) &lt;= ( `stencil'
+%% &amp; `Mask' ).
+%%
+%% `?GL_GREATER': Passes if ( `Ref' &amp; `Mask' ) &gt; ( `stencil'
+%% &amp; `Mask' ).
+%%
+%% `?GL_GEQUAL': Passes if ( `Ref' &amp; `Mask' ) &gt;= ( `stencil'
+%% &amp; `Mask' ).
+%%
+%% `?GL_EQUAL': Passes if ( `Ref' &amp; `Mask' ) = ( `stencil' &amp; `Mask'
+%% ).
+%%
+%% `?GL_NOTEQUAL': Passes if ( `Ref' &amp; `Mask' ) != ( `stencil' &amp;
+%% `Mask' ).
+%%
+%% `?GL_ALWAYS': Always passes.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml">external</a> documentation.
+-spec stencilFuncSeparate(Face, Func, Ref, Mask) -> ok when Face :: enum(),Func :: enum(),Ref :: integer(),Mask :: integer().
stencilFuncSeparate(Face,Func,Ref,Mask) ->
cast(5443, <<Face:?GLenum,Func:?GLenum,Ref:?GLint,Mask:?GLuint>>).
-%% @spec (Face::enum(),Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMaskSeparate.xml">external</a> documentation.
--spec stencilMaskSeparate(enum(),integer()) -> ok.
+%% @doc Control the front and/or back writing of individual bits in the stencil planes
+%%
+%% ``gl:stencilMaskSeparate'' controls the writing of individual bits in the stencil planes.
+%% The least significant n bits of `Mask' , where n is the number of bits in the
+%% stencil buffer, specify a mask. Where a 1 appears in the mask, it's possible to write
+%% to the corresponding bit in the stencil buffer. Where a 0 appears, the corresponding bit
+%% is write-protected. Initially, all bits are enabled for writing.
+%%
+%% There can be two separate `Mask' writemasks; one affects back-facing polygons, and
+%% the other affects front-facing polygons as well as other non-polygon primitives. {@link gl:stencilMask/1}
+%% sets both front and back stencil writemasks to the same values, as if {@link gl:stencilMaskSeparate/2}
+%% were called with `Face' set to `?GL_FRONT_AND_BACK'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMaskSeparate.xml">external</a> documentation.
+-spec stencilMaskSeparate(Face, Mask) -> ok when Face :: enum(),Mask :: integer().
stencilMaskSeparate(Face,Mask) ->
cast(5444, <<Face:?GLenum,Mask:?GLuint>>).
-%% @spec (Program::integer(),Shader::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachShader.xml">external</a> documentation.
--spec attachShader(integer(),integer()) -> ok.
+%% @doc Attaches a shader object to a program object
+%%
+%% In order to create a complete shader program, there must be a way to specify the list
+%% of things that will be linked together. Program objects provide this mechanism. Shaders
+%% that are to be linked together in a program object must first be attached to that program
+%% object. ``gl:attachShader'' attaches the shader object specified by `Shader' to
+%% the program object specified by `Program' . This indicates that `Shader' will
+%% be included in link operations that will be performed on `Program' .
+%%
+%% All operations that can be performed on a shader object are valid whether or not the
+%% shader object is attached to a program object. It is permissible to attach a shader object
+%% to a program object before source code has been loaded into the shader object or before
+%% the shader object has been compiled. It is permissible to attach multiple shader objects
+%% of the same type because each may contain a portion of the complete shader. It is also
+%% permissible to attach a shader object to more than one program object. If a shader object
+%% is deleted while it is attached to a program object, it will be flagged for deletion,
+%% and deletion will not occur until {@link gl:detachShader/2} is called to detach it from
+%% all program objects to which it is attached.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachShader.xml">external</a> documentation.
+-spec attachShader(Program, Shader) -> ok when Program :: integer(),Shader :: integer().
attachShader(Program,Shader) ->
cast(5445, <<Program:?GLuint,Shader:?GLuint>>).
-%% @spec (Program::integer(),Index::integer(),Name::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml">external</a> documentation.
--spec bindAttribLocation(integer(),integer(),string()) -> ok.
+%% @doc Associates a generic vertex attribute index with a named attribute variable
+%%
+%% ``gl:bindAttribLocation'' is used to associate a user-defined attribute variable in
+%% the program object specified by `Program' with a generic vertex attribute index.
+%% The name of the user-defined attribute variable is passed as a null terminated string in `Name'
+%% . The generic vertex attribute index to be bound to this variable is specified by `Index'
+%% . When `Program' is made part of current state, values provided via the generic vertex
+%% attribute `Index' will modify the value of the user-defined attribute variable specified
+%% by `Name' .
+%%
+%% If `Name' refers to a matrix attribute variable, `Index' refers to the first
+%% column of the matrix. Other matrix columns are then automatically bound to locations `Index+1'
+%% for a matrix of type `mat2'; `Index+1' and `Index+2' for a matrix of type
+%% `mat3'; and `Index+1' , `Index+2' , and `Index+3' for a matrix of type `mat4'
+%% .
+%%
+%% This command makes it possible for vertex shaders to use descriptive names for attribute
+%% variables rather than generic variables that are numbered from 0 to `?GL_MAX_VERTEX_ATTRIBS'
+%% -1. The values sent to each generic attribute index are part of current state. If a different
+%% program object is made current by calling {@link gl:useProgram/1} , the generic vertex attributes
+%% are tracked in such a way that the same values will be observed by attributes in the new
+%% program object that are also bound to `Index' .
+%%
+%% Attribute variable name-to-generic attribute index bindings for a program object can be
+%% explicitly assigned at any time by calling ``gl:bindAttribLocation''. Attribute bindings
+%% do not go into effect until {@link gl:linkProgram/1} is called. After a program object
+%% has been linked successfully, the index values for generic attributes remain fixed (and
+%% their values can be queried) until the next link command occurs.
+%%
+%% Any attribute binding that occurs after the program object has been linked will not take
+%% effect until the next time the program object is linked.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml">external</a> documentation.
+-spec bindAttribLocation(Program, Index, Name) -> ok when Program :: integer(),Index :: integer(),Name :: string().
bindAttribLocation(Program,Index,Name) ->
cast(5446, <<Program:?GLuint,Index:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Shader::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml">external</a> documentation.
--spec compileShader(integer()) -> ok.
+%% @doc Compiles a shader object
+%%
+%% ``gl:compileShader'' compiles the source code strings that have been stored in the shader
+%% object specified by `Shader' .
+%%
+%% The compilation status will be stored as part of the shader object's state. This value
+%% will be set to `?GL_TRUE' if the shader was compiled without errors and is ready
+%% for use, and `?GL_FALSE' otherwise. It can be queried by calling {@link gl:getShaderiv/2}
+%% with arguments `Shader' and `?GL_COMPILE_STATUS'.
+%%
+%% Compilation of a shader can fail for a number of reasons as specified by the OpenGL Shading
+%% Language Specification. Whether or not the compilation was successful, information about
+%% the compilation can be obtained from the shader object's information log by calling {@link gl:getShaderInfoLog/2}
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml">external</a> documentation.
+-spec compileShader(Shader) -> ok when Shader :: integer().
compileShader(Shader) ->
cast(5447, <<Shader:?GLuint>>).
-%% @spec () -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml">external</a> documentation.
+%% @doc Creates a program object
+%%
+%% ``gl:createProgram'' creates an empty program object and returns a non-zero value by
+%% which it can be referenced. A program object is an object to which shader objects can
+%% be attached. This provides a mechanism to specify the shader objects that will be linked
+%% to create a program. It also provides a means for checking the compatibility of the
+%% shaders that will be used to create a program (for instance, checking the compatibility
+%% between a vertex shader and a fragment shader). When no longer needed as part of a program
+%% object, shader objects can be detached.
+%%
+%% One or more executables are created in a program object by successfully attaching shader
+%% objects to it with {@link gl:attachShader/2} , successfully compiling the shader objects
+%% with {@link gl:compileShader/1} , and successfully linking the program object with {@link gl:linkProgram/1}
+%% . These executables are made part of current state when {@link gl:useProgram/1} is called.
+%% Program objects can be deleted by calling {@link gl:deleteProgram/1} . The memory associated
+%% with the program object will be deleted when it is no longer part of current rendering
+%% state for any context.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml">external</a> documentation.
-spec createProgram() -> integer().
createProgram() ->
call(5448, <<>>).
-%% @spec (Type::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml">external</a> documentation.
--spec createShader(enum()) -> integer().
+%% @doc Creates a shader object
+%%
+%% ``gl:createShader'' creates an empty shader object and returns a non-zero value by
+%% which it can be referenced. A shader object is used to maintain the source code strings
+%% that define a shader. `ShaderType' indicates the type of shader to be created. Five
+%% types of shader are supported. A shader of type `?GL_VERTEX_SHADER' is a shader
+%% that is intended to run on the programmable vertex processor. A shader of type `?GL_TESS_CONTROL_SHADER'
+%% is a shader that is intended to run on the programmable tessellation processor in the
+%% control stage. A shader of type `?GL_TESS_EVALUATION_SHADER' is a shader that is
+%% intended to run on the programmable tessellation processor in the evaluation stage. A
+%% shader of type `?GL_GEOMETRY_SHADER' is a shader that is intended to run on the
+%% programmable geometry processor. A shader of type `?GL_FRAGMENT_SHADER' is a shader
+%% that is intended to run on the programmable fragment processor.
+%%
+%% When created, a shader object's `?GL_SHADER_TYPE' parameter is set to either `?GL_VERTEX_SHADER'
+%% , `?GL_TESS_CONTROL_SHADER', `?GL_TESS_EVALUATION_SHADER', `?GL_GEOMETRY_SHADER'
+%% or `?GL_FRAGMENT_SHADER', depending on the value of `ShaderType' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml">external</a> documentation.
+-spec createShader(Type) -> integer() when Type :: enum().
createShader(Type) ->
call(5449, <<Type:?GLenum>>).
-%% @spec (Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml">external</a> documentation.
--spec deleteProgram(integer()) -> ok.
+%% @doc Deletes a program object
+%%
+%% ``gl:deleteProgram'' frees the memory and invalidates the name associated with the program
+%% object specified by `Program.' This command effectively undoes the effects of a call
+%% to {@link gl:createProgram/0} .
+%%
+%% If a program object is in use as part of current rendering state, it will be flagged for
+%% deletion, but it will not be deleted until it is no longer part of current state for any
+%% rendering context. If a program object to be deleted has shader objects attached to it,
+%% those shader objects will be automatically detached but not deleted unless they have already
+%% been flagged for deletion by a previous call to {@link gl:deleteShader/1} . A value of 0
+%% for `Program' will be silently ignored.
+%%
+%% To determine whether a program object has been flagged for deletion, call {@link gl:getProgramiv/2}
+%% with arguments `Program' and `?GL_DELETE_STATUS'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml">external</a> documentation.
+-spec deleteProgram(Program) -> ok when Program :: integer().
deleteProgram(Program) ->
cast(5450, <<Program:?GLuint>>).
-%% @spec (Shader::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml">external</a> documentation.
--spec deleteShader(integer()) -> ok.
+%% @doc Deletes a shader object
+%%
+%% ``gl:deleteShader'' frees the memory and invalidates the name associated with the shader
+%% object specified by `Shader' . This command effectively undoes the effects of a call
+%% to {@link gl:createShader/1} .
+%%
+%% If a shader object to be deleted is attached to a program object, it will be flagged for
+%% deletion, but it will not be deleted until it is no longer attached to any program object,
+%% for any rendering context (i.e., it must be detached from wherever it was attached before
+%% it will be deleted). A value of 0 for `Shader' will be silently ignored.
+%%
+%% To determine whether an object has been flagged for deletion, call {@link gl:getShaderiv/2}
+%% with arguments `Shader' and `?GL_DELETE_STATUS'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml">external</a> documentation.
+-spec deleteShader(Shader) -> ok when Shader :: integer().
deleteShader(Shader) ->
cast(5451, <<Shader:?GLuint>>).
-%% @spec (Program::integer(),Shader::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachShader.xml">external</a> documentation.
--spec detachShader(integer(),integer()) -> ok.
+%% @doc Detaches a shader object from a program object to which it is attached
+%%
+%% ``gl:detachShader'' detaches the shader object specified by `Shader' from the program
+%% object specified by `Program' . This command can be used to undo the effect of the
+%% command {@link gl:attachShader/2} .
+%%
+%% If `Shader' has already been flagged for deletion by a call to {@link gl:deleteShader/1}
+%% and it is not attached to any other program object, it will be deleted after it has been
+%% detached.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachShader.xml">external</a> documentation.
+-spec detachShader(Program, Shader) -> ok when Program :: integer(),Shader :: integer().
detachShader(Program,Shader) ->
cast(5452, <<Program:?GLuint,Shader:?GLuint>>).
-%% @spec (Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDisableVertexAttribArray.xml">external</a> documentation.
--spec disableVertexAttribArray(integer()) -> ok.
+%% @doc Enable or disable a generic vertex attribute array
+%%
+%% ``gl:enableVertexAttribArray'' enables the generic vertex attribute array specified by `Index'
+%% . ``gl:disableVertexAttribArray'' disables the generic vertex attribute array specified
+%% by `Index' . By default, all client-side capabilities are disabled, including all
+%% generic vertex attribute arrays. If enabled, the values in the generic vertex attribute
+%% array will be accessed and used for rendering when calls are made to vertex array commands
+%% such as {@link gl:drawArrays/3} , {@link gl:drawElements/4} , {@link gl:drawRangeElements/6} , see `glMultiDrawElements'
+%% , or {@link gl:multiDrawArrays/3} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml">external</a> documentation.
+-spec disableVertexAttribArray(Index) -> ok when Index :: integer().
disableVertexAttribArray(Index) ->
cast(5453, <<Index:?GLuint>>).
-%% @spec (Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml">external</a> documentation.
--spec enableVertexAttribArray(integer()) -> ok.
+%% @doc
+%% See {@link disableVertexAttribArray/1}
+-spec enableVertexAttribArray(Index) -> ok when Index :: integer().
enableVertexAttribArray(Index) ->
cast(5454, <<Index:?GLuint>>).
-%% @spec (Program::integer(),Index::integer(),BufSize::integer()) -> {Size::integer(),Type::enum(),Name::string()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml">external</a> documentation.
--spec getActiveAttrib(integer(),integer(),integer()) -> {integer(),enum(),string()}.
+%% @doc Returns information about an active attribute variable for the specified program object
+%%
+%% ``gl:getActiveAttrib'' returns information about an active attribute variable in the
+%% program object specified by `Program' . The number of active attributes can be obtained
+%% by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_ATTRIBUTES'. A value
+%% of 0 for `Index' selects the first active attribute variable. Permissible values
+%% for `Index' range from 0 to the number of active attribute variables minus 1.
+%%
+%% A vertex shader may use either built-in attribute variables, user-defined attribute variables,
+%% or both. Built-in attribute variables have a prefix of "gl_" and reference conventional
+%% OpenGL vertex attribtes (e.g., `Gl_Vertex' , `Gl_Normal' , etc., see the OpenGL
+%% Shading Language specification for a complete list.) User-defined attribute variables
+%% have arbitrary names and obtain their values through numbered generic vertex attributes.
+%% An attribute variable (either built-in or user-defined) is considered active if it is
+%% determined during the link operation that it may be accessed during program execution.
+%% Therefore, `Program' should have previously been the target of a call to {@link gl:linkProgram/1}
+%% , but it is not necessary for it to have been linked successfully.
+%%
+%% The size of the character buffer required to store the longest attribute variable name
+%% in `Program' can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_ATTRIBUTE_MAX_LENGTH'
+%% . This value should be used to allocate a buffer of sufficient size to store the returned
+%% attribute name. The size of this character buffer is passed in `BufSize' , and a pointer
+%% to this character buffer is passed in `Name' .
+%%
+%% ``gl:getActiveAttrib'' returns the name of the attribute variable indicated by `Index'
+%% , storing it in the character buffer specified by `Name' . The string returned will
+%% be null terminated. The actual number of characters written into this buffer is returned
+%% in `Length' , and this count does not include the null termination character. If the
+%% length of the returned string is not required, a value of `?NULL' can be passed in
+%% the `Length' argument.
+%%
+%% The `Type' argument specifies a pointer to a variable into which the attribute variable's
+%% data type will be written. The symbolic constants `?GL_FLOAT', `?GL_FLOAT_VEC2',
+%% `?GL_FLOAT_VEC3', `?GL_FLOAT_VEC4', `?GL_FLOAT_MAT2', `?GL_FLOAT_MAT3',
+%% `?GL_FLOAT_MAT4', `?GL_FLOAT_MAT2x3', `?GL_FLOAT_MAT2x4', `?GL_FLOAT_MAT3x2'
+%% , `?GL_FLOAT_MAT3x4', `?GL_FLOAT_MAT4x2', `?GL_FLOAT_MAT4x3', `?GL_INT'
+%% , `?GL_INT_VEC2', `?GL_INT_VEC3', `?GL_INT_VEC4', `?GL_UNSIGNED_INT_VEC'
+%% , `?GL_UNSIGNED_INT_VEC2', `?GL_UNSIGNED_INT_VEC3', `?GL_UNSIGNED_INT_VEC4',
+%% `?DOUBLE', `?DOUBLE_VEC2', `?DOUBLE_VEC3', `?DOUBLE_VEC4', `?DOUBLE_MAT2'
+%% , `?DOUBLE_MAT3', `?DOUBLE_MAT4', `?DOUBLE_MAT2x3', `?DOUBLE_MAT2x4',
+%% `?DOUBLE_MAT3x2', `?DOUBLE_MAT3x4', `?DOUBLE_MAT4x2', or `?DOUBLE_MAT4x3'
+%% may be returned. The `Size' argument will return the size of the attribute, in units
+%% of the type returned in `Type' .
+%%
+%% The list of active attribute variables may include both built-in attribute variables (which
+%% begin with the prefix "gl_") as well as user-defined attribute variable names.
+%%
+%% This function will return as much information as it can about the specified active attribute
+%% variable. If no information is available, `Length' will be 0, and `Name' will
+%% be an empty string. This situation could occur if this function is called after a link
+%% operation that failed. If an error occurs, the return values `Length' , `Size' , `Type'
+%% , and `Name' will be unmodified.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml">external</a> documentation.
+-spec getActiveAttrib(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer().
getActiveAttrib(Program,Index,BufSize) ->
call(5455, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Program::integer(),Index::integer(),BufSize::integer()) -> {Size::integer(),Type::enum(),Name::string()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml">external</a> documentation.
--spec getActiveUniform(integer(),integer(),integer()) -> {integer(),enum(),string()}.
+%% @doc Returns information about an active uniform variable for the specified program object
+%%
+%% ``gl:getActiveUniform'' returns information about an active uniform variable in the
+%% program object specified by `Program' . The number of active uniform variables can
+%% be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_UNIFORMS'.
+%% A value of 0 for `Index' selects the first active uniform variable. Permissible values
+%% for `Index' range from 0 to the number of active uniform variables minus 1.
+%%
+%% Shaders may use either built-in uniform variables, user-defined uniform variables, or
+%% both. Built-in uniform variables have a prefix of "gl_" and reference existing OpenGL
+%% state or values derived from such state (e.g., `Gl_DepthRangeParameters' , see the
+%% OpenGL Shading Language specification for a complete list.) User-defined uniform variables
+%% have arbitrary names and obtain their values from the application through calls to {@link gl:uniform1f/2}
+%% . A uniform variable (either built-in or user-defined) is considered active if it is determined
+%% during the link operation that it may be accessed during program execution. Therefore, `Program'
+%% should have previously been the target of a call to {@link gl:linkProgram/1} , but it is
+%% not necessary for it to have been linked successfully.
+%%
+%% The size of the character buffer required to store the longest uniform variable name in `Program'
+%% can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_UNIFORM_MAX_LENGTH'
+%% . This value should be used to allocate a buffer of sufficient size to store the returned
+%% uniform variable name. The size of this character buffer is passed in `BufSize' ,
+%% and a pointer to this character buffer is passed in `Name.'
+%%
+%% ``gl:getActiveUniform'' returns the name of the uniform variable indicated by `Index'
+%% , storing it in the character buffer specified by `Name' . The string returned will
+%% be null terminated. The actual number of characters written into this buffer is returned
+%% in `Length' , and this count does not include the null termination character. If the
+%% length of the returned string is not required, a value of `?NULL' can be passed in
+%% the `Length' argument.
+%%
+%% The `Type' argument will return a pointer to the uniform variable's data type. The
+%% symbolic constants returned for uniform types are shown in the table below. <table><tbody>
+%% <tr><td>` Returned Symbolic Contant '</td><td>` Shader Uniform Type '</td></tr></tbody>
+%% <tbody><tr><td>`?GL_FLOAT'</td><td>`?float'</td></tr><tr><td>`?GL_FLOAT_VEC2'
+%% </td><td>`?vec2'</td></tr><tr><td>`?GL_FLOAT_VEC3'</td><td>`?vec3'</td></tr>
+%% <tr><td>`?GL_FLOAT_VEC4'</td><td>`?vec4'</td></tr><tr><td>`?GL_DOUBLE'</td>
+%% <td>`?double'</td></tr><tr><td>`?GL_DOUBLE_VEC2'</td><td>`?dvec2'</td></tr>
+%% <tr><td>`?GL_DOUBLE_VEC3'</td><td>`?dvec3'</td></tr><tr><td>`?GL_DOUBLE_VEC4'
+%% </td><td>`?dvec4'</td></tr><tr><td>`?GL_INT'</td><td>`?int'</td></tr><tr><td>
+%% `?GL_INT_VEC2'</td><td>`?ivec2'</td></tr><tr><td>`?GL_INT_VEC3'</td><td>`?ivec3'
+%% </td></tr><tr><td>`?GL_INT_VEC4'</td><td>`?ivec4'</td></tr><tr><td>`?GL_UNSIGNED_INT'
+%% </td><td>`?unsigned int'</td></tr><tr><td>`?GL_UNSIGNED_INT_VEC2'</td><td>`?uvec2'
+%% </td></tr><tr><td>`?GL_UNSIGNED_INT_VEC3'</td><td>`?uvec3'</td></tr><tr><td>`?GL_UNSIGNED_INT_VEC4'
+%% </td><td>`?uvec4'</td></tr><tr><td>`?GL_BOOL'</td><td>`?bool'</td></tr><tr>
+%% <td>`?GL_BOOL_VEC2'</td><td>`?bvec2'</td></tr><tr><td>`?GL_BOOL_VEC3'</td><td>
+%% `?bvec3'</td></tr><tr><td>`?GL_BOOL_VEC4'</td><td>`?bvec4'</td></tr><tr><td>
+%% `?GL_FLOAT_MAT2'</td><td>`?mat2'</td></tr><tr><td>`?GL_FLOAT_MAT3'</td><td>
+%% `?mat3'</td></tr><tr><td>`?GL_FLOAT_MAT4'</td><td>`?mat4'</td></tr><tr><td>
+%% `?GL_FLOAT_MAT2x3'</td><td>`?mat2x3'</td></tr><tr><td>`?GL_FLOAT_MAT2x4'</td>
+%% <td>`?mat2x4'</td></tr><tr><td>`?GL_FLOAT_MAT3x2'</td><td>`?mat3x2'</td></tr>
+%% <tr><td>`?GL_FLOAT_MAT3x4'</td><td>`?mat3x4'</td></tr><tr><td>`?GL_FLOAT_MAT4x2'
+%% </td><td>`?mat4x2'</td></tr><tr><td>`?GL_FLOAT_MAT4x3'</td><td>`?mat4x3'</td>
+%% </tr><tr><td>`?GL_DOUBLE_MAT2'</td><td>`?dmat2'</td></tr><tr><td>`?GL_DOUBLE_MAT3'
+%% </td><td>`?dmat3'</td></tr><tr><td>`?GL_DOUBLE_MAT4'</td><td>`?dmat4'</td></tr>
+%% <tr><td>`?GL_DOUBLE_MAT2x3'</td><td>`?dmat2x3'</td></tr><tr><td>`?GL_DOUBLE_MAT2x4'
+%% </td><td>`?dmat2x4'</td></tr><tr><td>`?GL_DOUBLE_MAT3x2'</td><td>`?dmat3x2'</td>
+%% </tr><tr><td>`?GL_DOUBLE_MAT3x4'</td><td>`?dmat3x4'</td></tr><tr><td>`?GL_DOUBLE_MAT4x2'
+%% </td><td>`?dmat4x2'</td></tr><tr><td>`?GL_DOUBLE_MAT4x3'</td><td>`?dmat4x3'</td>
+%% </tr><tr><td>`?GL_SAMPLER_1D'</td><td>`?sampler1D'</td></tr><tr><td>`?GL_SAMPLER_2D'
+%% </td><td>`?sampler2D'</td></tr><tr><td>`?GL_SAMPLER_3D'</td><td>`?sampler3D'
+%% </td></tr><tr><td>`?GL_SAMPLER_CUBE'</td><td>`?samplerCube'</td></tr><tr><td>`?GL_SAMPLER_1D_SHADOW'
+%% </td><td>`?sampler1DShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_SHADOW'</td><td>`?sampler2DShadow'
+%% </td></tr><tr><td>`?GL_SAMPLER_1D_ARRAY'</td><td>`?sampler1DArray'</td></tr><tr>
+%% <td>`?GL_SAMPLER_2D_ARRAY'</td><td>`?sampler2DArray'</td></tr><tr><td>`?GL_SAMPLER_1D_ARRAY_SHADOW'
+%% </td><td>`?sampler1DArrayShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_ARRAY_SHADOW'</td>
+%% <td>`?sampler2DArrayShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_MULTISAMPLE'</td><td>
+%% `?sampler2DMS'</td></tr><tr><td>`?GL_SAMPLER_2D_MULTISAMPLE_ARRAY'</td><td>`?sampler2DMSArray'
+%% </td></tr><tr><td>`?GL_SAMPLER_CUBE_SHADOW'</td><td>`?samplerCubeShadow'</td></tr>
+%% <tr><td>`?GL_SAMPLER_BUFFER'</td><td>`?samplerBuffer'</td></tr><tr><td>`?GL_SAMPLER_2D_RECT'
+%% </td><td>`?sampler2DRect'</td></tr><tr><td>`?GL_SAMPLER_2D_RECT_SHADOW'</td><td>
+%% `?sampler2DRectShadow'</td></tr><tr><td>`?GL_INT_SAMPLER_1D'</td><td>`?isampler1D'
+%% </td></tr><tr><td>`?GL_INT_SAMPLER_2D'</td><td>`?isampler2D'</td></tr><tr><td>`?GL_INT_SAMPLER_3D'
+%% </td><td>`?isampler3D'</td></tr><tr><td>`?GL_INT_SAMPLER_CUBE'</td><td>`?isamplerCube'
+%% </td></tr><tr><td>`?GL_INT_SAMPLER_1D_ARRAY'</td><td>`?isampler1DArray'</td></tr>
+%% <tr><td>`?GL_INT_SAMPLER_2D_ARRAY'</td><td>`?isampler2DArray'</td></tr><tr><td>`?GL_INT_SAMPLER_2D_MULTISAMPLE'
+%% </td><td>`?isampler2DMS'</td></tr><tr><td>`?GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY'</td>
+%% <td>`?isampler2DMSArray'</td></tr><tr><td>`?GL_INT_SAMPLER_BUFFER'</td><td>`?isamplerBuffer'
+%% </td></tr><tr><td>`?GL_INT_SAMPLER_2D_RECT'</td><td>`?isampler2DRect'</td></tr><tr>
+%% <td>`?GL_UNSIGNED_INT_SAMPLER_1D'</td><td>`?usampler1D'</td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D'
+%% </td><td>`?usampler2D'</td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_3D'</td><td>`?usampler3D'
+%% </td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_CUBE'</td><td>`?usamplerCube'</td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_1D_ARRAY'</td><td>`?usampler2DArray'</td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_ARRAY'</td><td>`?usampler2DArray'</td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE'</td><td>`?usampler2DMS'</td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY'</td><td>`?usampler2DMSArray'
+%% </td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_BUFFER'</td><td>`?usamplerBuffer'</td>
+%% </tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_RECT'</td><td>`?usampler2DRect'</td></tr>
+%% <tr><td>`?GL_IMAGE_1D'</td><td>`?image1D'</td></tr><tr><td>`?GL_IMAGE_2D'</td>
+%% <td>`?image2D'</td></tr><tr><td>`?GL_IMAGE_3D'</td><td>`?image3D'</td></tr>
+%% <tr><td>`?GL_IMAGE_2D_RECT'</td><td>`?image2DRect'</td></tr><tr><td>`?GL_IMAGE_CUBE'
+%% </td><td>`?imageCube'</td></tr><tr><td>`?GL_IMAGE_BUFFER'</td><td>`?imageBuffer'
+%% </td></tr><tr><td>`?GL_IMAGE_1D_ARRAY'</td><td>`?image1DArray'</td></tr><tr><td>
+%% `?GL_IMAGE_2D_ARRAY'</td><td>`?image2DArray'</td></tr><tr><td>`?GL_IMAGE_2D_MULTISAMPLE'
+%% </td><td>`?image2DMS'</td></tr><tr><td>`?GL_IMAGE_2D_MULTISAMPLE_ARRAY'</td><td>
+%% `?image2DMSArray'</td></tr><tr><td>`?GL_INT_IMAGE_1D'</td><td>`?iimage1D'</td>
+%% </tr><tr><td>`?GL_INT_IMAGE_2D'</td><td>`?iimage2D'</td></tr><tr><td>`?GL_INT_IMAGE_3D'
+%% </td><td>`?iimage3D'</td></tr><tr><td>`?GL_INT_IMAGE_2D_RECT'</td><td>`?iimage2DRect'
+%% </td></tr><tr><td>`?GL_INT_IMAGE_CUBE'</td><td>`?iimageCube'</td></tr><tr><td>`?GL_INT_IMAGE_BUFFER'
+%% </td><td>`?iimageBuffer'</td></tr><tr><td>`?GL_INT_IMAGE_1D_ARRAY'</td><td>`?iimage1DArray'
+%% </td></tr><tr><td>`?GL_INT_IMAGE_2D_ARRAY'</td><td>`?iimage2DArray'</td></tr><tr>
+%% <td>`?GL_INT_IMAGE_2D_MULTISAMPLE'</td><td>`?iimage2DMS'</td></tr><tr><td>`?GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY'
+%% </td><td>`?iimage2DMSArray'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_1D'</td><td>
+%% `?uimage1D'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D'</td><td>`?uimage2D'
+%% </td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_3D'</td><td>`?uimage3D'</td></tr><tr><td>
+%% `?GL_UNSIGNED_INT_IMAGE_2D_RECT'</td><td>`?uimage2DRect'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_CUBE'
+%% </td><td>`?uimageCube'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_BUFFER'</td><td>
+%% `?uimageBuffer'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_1D_ARRAY'</td><td>`?uimage1DArray'
+%% </td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_ARRAY'</td><td>`?uimage2DArray'</td>
+%% </tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE'</td><td>`?uimage2DMS'</td></tr>
+%% <tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY'</td><td>`?uimage2DMSArray'</td>
+%% </tr><tr><td>`?GL_UNSIGNED_INT_ATOMIC_COUNTER'</td><td>`?atomic_uint'</td></tr></tbody>
+%% </table>
+%%
+%% If one or more elements of an array are active, the name of the array is returned in `Name'
+%% , the type is returned in `Type' , and the `Size' parameter returns the highest
+%% array element index used, plus one, as determined by the compiler and/or linker. Only
+%% one active uniform variable will be reported for a uniform array.
+%%
+%% Uniform variables that are declared as structures or arrays of structures will not be
+%% returned directly by this function. Instead, each of these uniform variables will be reduced
+%% to its fundamental components containing the "." and "[]" operators such that each of
+%% the names is valid as an argument to {@link gl:getUniformLocation/2} . Each of these reduced
+%% uniform variables is counted as one active uniform variable and is assigned an index.
+%% A valid name cannot be a structure, an array of structures, or a subcomponent of a vector
+%% or matrix.
+%%
+%% The size of the uniform variable will be returned in `Size' . Uniform variables other
+%% than arrays will have a size of 1. Structures and arrays of structures will be reduced
+%% as described earlier, such that each of the names returned will be a data type in the
+%% earlier list. If this reduction results in an array, the size returned will be as described
+%% for uniform arrays; otherwise, the size returned will be 1.
+%%
+%% The list of active uniform variables may include both built-in uniform variables (which
+%% begin with the prefix "gl_") as well as user-defined uniform variable names.
+%%
+%% This function will return as much information as it can about the specified active uniform
+%% variable. If no information is available, `Length' will be 0, and `Name' will
+%% be an empty string. This situation could occur if this function is called after a link
+%% operation that failed. If an error occurs, the return values `Length' , `Size' , `Type'
+%% , and `Name' will be unmodified.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml">external</a> documentation.
+-spec getActiveUniform(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer().
getActiveUniform(Program,Index,BufSize) ->
call(5456, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Program::integer(),MaxCount::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedShaders.xml">external</a> documentation.
--spec getAttachedShaders(integer(),integer()) -> [integer()].
+%% @doc Returns the handles of the shader objects attached to a program object
+%%
+%% ``gl:getAttachedShaders'' returns the names of the shader objects attached to `Program'
+%% . The names of shader objects that are attached to `Program' will be returned in `Shaders.'
+%% The actual number of shader names written into `Shaders' is returned in `Count.'
+%% If no shader objects are attached to `Program' , `Count' is set to 0. The maximum
+%% number of shader names that may be returned in `Shaders' is specified by `MaxCount'
+%% .
+%%
+%% If the number of names actually returned is not required (for instance, if it has just
+%% been obtained by calling {@link gl:getProgramiv/2} ), a value of `?NULL' may be passed
+%% for count. If no shader objects are attached to `Program' , a value of 0 will be returned
+%% in `Count' . The actual number of attached shaders can be obtained by calling {@link gl:getProgramiv/2}
+%% with the value `?GL_ATTACHED_SHADERS'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedShaders.xml">external</a> documentation.
+-spec getAttachedShaders(Program, MaxCount) -> [integer()] when Program :: integer(),MaxCount :: integer().
getAttachedShaders(Program,MaxCount) ->
call(5457, <<Program:?GLuint,MaxCount:?GLsizei>>).
-%% @spec (Program::integer(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml">external</a> documentation.
--spec getAttribLocation(integer(),string()) -> integer().
+%% @doc Returns the location of an attribute variable
+%%
+%% ``gl:getAttribLocation'' queries the previously linked program object specified by `Program'
+%% for the attribute variable specified by `Name' and returns the index of the generic
+%% vertex attribute that is bound to that attribute variable. If `Name' is a matrix
+%% attribute variable, the index of the first column of the matrix is returned. If the named
+%% attribute variable is not an active attribute in the specified program object or if `Name'
+%% starts with the reserved prefix "gl_", a value of -1 is returned.
+%%
+%% The association between an attribute variable name and a generic attribute index can be
+%% specified at any time by calling {@link gl:bindAttribLocation/3} . Attribute bindings do
+%% not go into effect until {@link gl:linkProgram/1} is called. After a program object has
+%% been linked successfully, the index values for attribute variables remain fixed until
+%% the next link command occurs. The attribute values can only be queried after a link if
+%% the link was successful. ``gl:getAttribLocation'' returns the binding that actually
+%% went into effect the last time {@link gl:linkProgram/1} was called for the specified program
+%% object. Attribute bindings that have been specified since the last link operation are
+%% not returned by ``gl:getAttribLocation''.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml">external</a> documentation.
+-spec getAttribLocation(Program, Name) -> integer() when Program :: integer(),Name :: string().
getAttribLocation(Program,Name) ->
call(5458, <<Program:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgram.xml">external</a> documentation.
--spec getProgramiv(integer(),enum()) -> integer().
+%% @doc Returns a parameter from a program object
+%%
+%% ``gl:getProgram'' returns in `Params' the value of a parameter for a specific program
+%% object. The following parameters are defined:
+%%
+%% `?GL_DELETE_STATUS': `Params' returns `?GL_TRUE' if `Program' is currently
+%% flagged for deletion, and `?GL_FALSE' otherwise.
+%%
+%% `?GL_LINK_STATUS': `Params' returns `?GL_TRUE' if the last link operation
+%% on `Program' was successful, and `?GL_FALSE' otherwise.
+%%
+%% `?GL_VALIDATE_STATUS': `Params' returns `?GL_TRUE' or if the last validation
+%% operation on `Program' was successful, and `?GL_FALSE' otherwise.
+%%
+%% `?GL_INFO_LOG_LENGTH': `Params' returns the number of characters in the information
+%% log for `Program' including the null termination character (i.e., the size of the
+%% character buffer required to store the information log). If `Program' has no information
+%% log, a value of 0 is returned.
+%%
+%% `?GL_ATTACHED_SHADERS': `Params' returns the number of shader objects attached
+%% to `Program' .
+%%
+%% `?GL_ACTIVE_ATOMIC_COUNTER_BUFFERS': `Params' returns the number of active attribute
+%% atomic counter buffers used by `Program' .
+%%
+%% `?GL_ACTIVE_ATTRIBUTES': `Params' returns the number of active attribute variables
+%% for `Program' .
+%%
+%% `?GL_ACTIVE_ATTRIBUTE_MAX_LENGTH': `Params' returns the length of the longest
+%% active attribute name for `Program' , including the null termination character (i.e.,
+%% the size of the character buffer required to store the longest attribute name). If no
+%% active attributes exist, 0 is returned.
+%%
+%% `?GL_ACTIVE_UNIFORMS': `Params' returns the number of active uniform variables
+%% for `Program' .
+%%
+%% `?GL_ACTIVE_UNIFORM_MAX_LENGTH': `Params' returns the length of the longest
+%% active uniform variable name for `Program' , including the null termination character
+%% (i.e., the size of the character buffer required to store the longest uniform variable
+%% name). If no active uniform variables exist, 0 is returned.
+%%
+%% `?GL_PROGRAM_BINARY_LENGTH': `Params' returns the length of the program binary,
+%% in bytes that will be returned by a call to {@link gl:getProgramBinary/2} . When a progam's
+%% `?GL_LINK_STATUS' is `?GL_FALSE', its program binary length is zero.
+%%
+%% `?GL_TRANSFORM_FEEDBACK_BUFFER_MODE': `Params' returns a symbolic constant indicating
+%% the buffer mode used when transform feedback is active. This may be `?GL_SEPARATE_ATTRIBS'
+%% or `?GL_INTERLEAVED_ATTRIBS'.
+%%
+%% `?GL_TRANSFORM_FEEDBACK_VARYINGS': `Params' returns the number of varying variables
+%% to capture in transform feedback mode for the program.
+%%
+%% `?GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH': `Params' returns the length of
+%% the longest variable name to be used for transform feedback, including the null-terminator.
+%%
+%%
+%% `?GL_GEOMETRY_VERTICES_OUT': `Params' returns the maximum number of vertices
+%% that the geometry shader in `Program' will output.
+%%
+%% `?GL_GEOMETRY_INPUT_TYPE': `Params' returns a symbolic constant indicating the
+%% primitive type accepted as input to the geometry shader contained in `Program' .
+%%
+%% `?GL_GEOMETRY_OUTPUT_TYPE': `Params' returns a symbolic constant indicating
+%% the primitive type that will be output by the geometry shader contained in `Program' .
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgram.xml">external</a> documentation.
+-spec getProgramiv(Program, Pname) -> integer() when Program :: integer(),Pname :: enum().
getProgramiv(Program,Pname) ->
call(5459, <<Program:?GLuint,Pname:?GLenum>>).
-%% @spec (Program::integer(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml">external</a> documentation.
--spec getProgramInfoLog(integer(),integer()) -> string().
+%% @doc Returns the information log for a program object
+%%
+%% ``gl:getProgramInfoLog'' returns the information log for the specified program object.
+%% The information log for a program object is modified when the program object is linked
+%% or validated. The string that is returned will be null terminated.
+%%
+%% ``gl:getProgramInfoLog'' returns in `InfoLog' as much of the information log as
+%% it can, up to a maximum of `MaxLength' characters. The number of characters actually
+%% returned, excluding the null termination character, is specified by `Length' . If
+%% the length of the returned string is not required, a value of `?NULL' can be passed
+%% in the `Length' argument. The size of the buffer required to store the returned
+%% information log can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_INFO_LOG_LENGTH'
+%% .
+%%
+%% The information log for a program object is either an empty string, or a string containing
+%% information about the last link operation, or a string containing information about the
+%% last validation operation. It may contain diagnostic messages, warning messages, and
+%% other information. When a program object is created, its information log will be a string
+%% of length 0.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml">external</a> documentation.
+-spec getProgramInfoLog(Program, BufSize) -> string() when Program :: integer(),BufSize :: integer().
getProgramInfoLog(Program,BufSize) ->
call(5460, <<Program:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Shader::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShader.xml">external</a> documentation.
--spec getShaderiv(integer(),enum()) -> integer().
+%% @doc Returns a parameter from a shader object
+%%
+%% ``gl:getShader'' returns in `Params' the value of a parameter for a specific
+%% shader object. The following parameters are defined:
+%%
+%% `?GL_SHADER_TYPE': `Params' returns `?GL_VERTEX_SHADER' if `Shader'
+%% is a vertex shader object, `?GL_GEOMETRY_SHADER' if `Shader' is a geometry
+%% shader object, and `?GL_FRAGMENT_SHADER' if `Shader' is a fragment shader
+%% object.
+%%
+%% `?GL_DELETE_STATUS': `Params' returns `?GL_TRUE' if `Shader' is
+%% currently flagged for deletion, and `?GL_FALSE' otherwise.
+%%
+%% `?GL_COMPILE_STATUS': `Params' returns `?GL_TRUE' if the last compile
+%% operation on `Shader' was successful, and `?GL_FALSE' otherwise.
+%%
+%% `?GL_INFO_LOG_LENGTH': `Params' returns the number of characters in the information
+%% log for `Shader' including the null termination character (i.e., the size of
+%% the character buffer required to store the information log). If `Shader' has
+%% no information log, a value of 0 is returned.
+%%
+%% `?GL_SHADER_SOURCE_LENGTH': `Params' returns the length of the concatenation
+%% of the source strings that make up the shader source for the `Shader' , including
+%% the null termination character. (i.e., the size of the character buffer required to
+%% store the shader source). If no source code exists, 0 is returned.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShader.xml">external</a> documentation.
+-spec getShaderiv(Shader, Pname) -> integer() when Shader :: integer(),Pname :: enum().
getShaderiv(Shader,Pname) ->
call(5461, <<Shader:?GLuint,Pname:?GLenum>>).
-%% @spec (Shader::integer(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml">external</a> documentation.
--spec getShaderInfoLog(integer(),integer()) -> string().
+%% @doc Returns the information log for a shader object
+%%
+%% ``gl:getShaderInfoLog'' returns the information log for the specified shader object.
+%% The information log for a shader object is modified when the shader is compiled. The
+%% string that is returned will be null terminated.
+%%
+%% ``gl:getShaderInfoLog'' returns in `InfoLog' as much of the information log as
+%% it can, up to a maximum of `MaxLength' characters. The number of characters actually
+%% returned, excluding the null termination character, is specified by `Length' . If
+%% the length of the returned string is not required, a value of `?NULL' can be passed
+%% in the `Length' argument. The size of the buffer required to store the returned
+%% information log can be obtained by calling {@link gl:getShaderiv/2} with the value `?GL_INFO_LOG_LENGTH'
+%% .
+%%
+%% The information log for a shader object is a string that may contain diagnostic messages,
+%% warning messages, and other information about the last compile operation. When a shader
+%% object is created, its information log will be a string of length 0.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml">external</a> documentation.
+-spec getShaderInfoLog(Shader, BufSize) -> string() when Shader :: integer(),BufSize :: integer().
getShaderInfoLog(Shader,BufSize) ->
call(5462, <<Shader:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Shader::integer(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSource.xml">external</a> documentation.
--spec getShaderSource(integer(),integer()) -> string().
+%% @doc Returns the source code string from a shader object
+%%
+%% ``gl:getShaderSource'' returns the concatenation of the source code strings from the
+%% shader object specified by `Shader' . The source code strings for a shader object
+%% are the result of a previous call to {@link gl:shaderSource/2} . The string returned by
+%% the function will be null terminated.
+%%
+%% ``gl:getShaderSource'' returns in `Source' as much of the source code string as
+%% it can, up to a maximum of `BufSize' characters. The number of characters actually
+%% returned, excluding the null termination character, is specified by `Length' . If
+%% the length of the returned string is not required, a value of `?NULL' can be passed
+%% in the `Length' argument. The size of the buffer required to store the returned source
+%% code string can be obtained by calling {@link gl:getShaderiv/2} with the value `?GL_SHADER_SOURCE_LENGTH'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSource.xml">external</a> documentation.
+-spec getShaderSource(Shader, BufSize) -> string() when Shader :: integer(),BufSize :: integer().
getShaderSource(Shader,BufSize) ->
call(5463, <<Shader:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Program::integer(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocation.xml">external</a> documentation.
--spec getUniformLocation(integer(),string()) -> integer().
+%% @doc Returns the location of a uniform variable
+%%
+%% ``gl:getUniformLocation '' returns an integer that represents the location of a specific
+%% uniform variable within a program object. `Name' must be a null terminated string
+%% that contains no white space. `Name' must be an active uniform variable name in `Program'
+%% that is not a structure, an array of structures, or a subcomponent of a vector or a matrix.
+%% This function returns -1 if `Name' does not correspond to an active uniform variable
+%% in `Program' , if `Name' starts with the reserved prefix "gl_", or if `Name'
+%% is associated with an atomic counter or a named uniform block.
+%%
+%% Uniform variables that are structures or arrays of structures may be queried by calling ``gl:getUniformLocation''
+%% for each field within the structure. The array element operator "[]" and the structure
+%% field operator "." may be used in `Name' in order to select elements within an array
+%% or fields within a structure. The result of using these operators is not allowed to be
+%% another structure, an array of structures, or a subcomponent of a vector or a matrix.
+%% Except if the last part of `Name' indicates a uniform variable array, the location
+%% of the first element of an array can be retrieved by using the name of the array, or by
+%% using the name appended by "[0]".
+%%
+%% The actual locations assigned to uniform variables are not known until the program object
+%% is linked successfully. After linking has occurred, the command ``gl:getUniformLocation''
+%% can be used to obtain the location of a uniform variable. This location value can then
+%% be passed to {@link gl:uniform1f/2} to set the value of the uniform variable or to {@link gl:getUniformfv/2}
+%% in order to query the current value of the uniform variable. After a program object has
+%% been linked successfully, the index values for uniform variables remain fixed until the
+%% next link command occurs. Uniform variable locations and values can only be queried after
+%% a link if the link was successful.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocation.xml">external</a> documentation.
+-spec getUniformLocation(Program, Name) -> integer() when Program :: integer(),Name :: string().
getUniformLocation(Program,Name) ->
call(5464, <<Program:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),Location::integer()) -> {float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation.
--spec getUniformfv(integer(),integer()) -> {float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}.
+%% @doc Returns the value of a uniform variable
+%%
+%% ``gl:getUniform'' returns in `Params' the value(s) of the specified uniform variable.
+%% The type of the uniform variable specified by `Location' determines the number of
+%% values returned. If the uniform variable is defined in the shader as a boolean, int, or
+%% float, a single value will be returned. If it is defined as a vec2, ivec2, or bvec2, two
+%% values will be returned. If it is defined as a vec3, ivec3, or bvec3, three values will
+%% be returned, and so on. To query values stored in uniform variables declared as arrays,
+%% call ``gl:getUniform'' for each element of the array. To query values stored in uniform
+%% variables declared as structures, call ``gl:getUniform'' for each field in the structure.
+%% The values for uniform variables declared as a matrix will be returned in column major
+%% order.
+%%
+%% The locations assigned to uniform variables are not known until the program object is
+%% linked. After linking has occurred, the command {@link gl:getUniformLocation/2} can be
+%% used to obtain the location of a uniform variable. This location value can then be passed
+%% to ``gl:getUniform'' in order to query the current value of the uniform variable. After
+%% a program object has been linked successfully, the index values for uniform variables
+%% remain fixed until the next link command occurs. The uniform variable values can only
+%% be queried after a link if the link was successful.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation.
+-spec getUniformfv(Program, Location) -> matrix() when Program :: integer(),Location :: integer().
getUniformfv(Program,Location) ->
call(5465, <<Program:?GLuint,Location:?GLint>>).
-%% @spec (Program::integer(),Location::integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation.
--spec getUniformiv(integer(),integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getUniformfv/2}
+-spec getUniformiv(Program, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when Program :: integer(),Location :: integer().
getUniformiv(Program,Location) ->
call(5466, <<Program:?GLuint,Location:?GLint>>).
-%% @spec (Index::integer(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml">external</a> documentation.
--spec getVertexAttribdv(integer(),enum()) -> {float(),float(),float(),float()}.
+%% @doc Return a generic vertex attribute parameter
+%%
+%% ``gl:getVertexAttrib'' returns in `Params' the value of a generic vertex attribute
+%% parameter. The generic vertex attribute to be queried is specified by `Index' , and
+%% the parameter to be queried is specified by `Pname' .
+%%
+%% The accepted parameter names are as follows:
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING': `Params' returns a single value, the
+%% name of the buffer object currently bound to the binding point corresponding to generic
+%% vertex attribute array `Index' . If no buffer object is bound, 0 is returned. The
+%% initial value is 0.
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_ENABLED': `Params' returns a single value that is non-zero
+%% (true) if the vertex attribute array for `Index' is enabled and 0 (false) if it is
+%% disabled. The initial value is `?GL_FALSE'.
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_SIZE': `Params' returns a single value, the size of
+%% the vertex attribute array for `Index' . The size is the number of values for each
+%% element of the vertex attribute array, and it will be 1, 2, 3, or 4. The initial value
+%% is 4.
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_STRIDE': `Params' returns a single value, the array
+%% stride for (number of bytes between successive elements in) the vertex attribute array
+%% for `Index' . A value of 0 indicates that the array elements are stored sequentially
+%% in memory. The initial value is 0.
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_TYPE': `Params' returns a single value, a symbolic
+%% constant indicating the array type for the vertex attribute array for `Index' . Possible
+%% values are `?GL_BYTE', `?GL_UNSIGNED_BYTE', `?GL_SHORT', `?GL_UNSIGNED_SHORT'
+%% , `?GL_INT', `?GL_UNSIGNED_INT', `?GL_FLOAT', and `?GL_DOUBLE'. The
+%% initial value is `?GL_FLOAT'.
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_NORMALIZED': `Params' returns a single value that is
+%% non-zero (true) if fixed-point data types for the vertex attribute array indicated by `Index'
+%% are normalized when they are converted to floating point, and 0 (false) otherwise. The
+%% initial value is `?GL_FALSE'.
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_INTEGER': `Params' returns a single value that is non-zero
+%% (true) if fixed-point data types for the vertex attribute array indicated by `Index'
+%% have integer data types, and 0 (false) otherwise. The initial value is 0 (`?GL_FALSE').
+%%
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_DIVISOR': `Params' returns a single value that is the
+%% frequency divisor used for instanced rendering. See {@link gl:vertexAttribDivisor/2} . The
+%% initial value is 0.
+%%
+%% `?GL_CURRENT_VERTEX_ATTRIB': `Params' returns four values that represent the
+%% current value for the generic vertex attribute specified by index. Generic vertex attribute
+%% 0 is unique in that it has no current state, so an error will be generated if `Index'
+%% is 0. The initial value for all other generic vertex attributes is (0,0,0,1).
+%%
+%% ``gl:getVertexAttribdv'' and ``gl:getVertexAttribfv'' return the current attribute
+%% values as four single-precision floating-point values; ``gl:getVertexAttribiv'' reads
+%% them as floating-point values and converts them to four integer values; ``gl:getVertexAttribIiv''
+%% and ``gl:getVertexAttribIuiv'' read and return them as signed or unsigned integer values,
+%% respectively; ``gl:getVertexAttribLdv'' reads and returns them as four double-precision
+%% floating-point values.
+%%
+%% All of the parameters except `?GL_CURRENT_VERTEX_ATTRIB' represent state stored in
+%% the currently bound vertex array object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml">external</a> documentation.
+-spec getVertexAttribdv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum().
getVertexAttribdv(Index,Pname) ->
call(5467, <<Index:?GLuint,Pname:?GLenum>>).
-%% @spec (Index::integer(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml">external</a> documentation.
--spec getVertexAttribfv(integer(),enum()) -> {float(),float(),float(),float()}.
+%% @doc
+%% See {@link getVertexAttribdv/2}
+-spec getVertexAttribfv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum().
getVertexAttribfv(Index,Pname) ->
call(5468, <<Index:?GLuint,Pname:?GLenum>>).
-%% @spec (Index::integer(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml">external</a> documentation.
--spec getVertexAttribiv(integer(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getVertexAttribdv/2}
+-spec getVertexAttribiv(Index, Pname) -> {integer(),integer(),integer(),integer()} when Index :: integer(),Pname :: enum().
getVertexAttribiv(Index,Pname) ->
call(5469, <<Index:?GLuint,Pname:?GLenum>>).
-%% @spec (Program::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgram.xml">external</a> documentation.
--spec isProgram(integer()) -> 0|1.
+%% @doc Determines if a name corresponds to a program object
+%%
+%% ``gl:isProgram'' returns `?GL_TRUE' if `Program' is the name of a program
+%% object previously created with {@link gl:createProgram/0} and not yet deleted with {@link gl:deleteProgram/1}
+%% . If `Program' is zero or a non-zero value that is not the name of a program object,
+%% or if an error occurs, ``gl:isProgram'' returns `?GL_FALSE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgram.xml">external</a> documentation.
+-spec isProgram(Program) -> 0|1 when Program :: integer().
isProgram(Program) ->
call(5470, <<Program:?GLuint>>).
-%% @spec (Shader::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsShader.xml">external</a> documentation.
--spec isShader(integer()) -> 0|1.
+%% @doc Determines if a name corresponds to a shader object
+%%
+%% ``gl:isShader'' returns `?GL_TRUE' if `Shader' is the name of a shader object
+%% previously created with {@link gl:createShader/1} and not yet deleted with {@link gl:deleteShader/1}
+%% . If `Shader' is zero or a non-zero value that is not the name of a shader object,
+%% or if an error occurs, ``gl:isShader '' returns `?GL_FALSE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsShader.xml">external</a> documentation.
+-spec isShader(Shader) -> 0|1 when Shader :: integer().
isShader(Shader) ->
call(5471, <<Shader:?GLuint>>).
-%% @spec (Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgram.xml">external</a> documentation.
--spec linkProgram(integer()) -> ok.
+%% @doc Links a program object
+%%
+%% ``gl:linkProgram'' links the program object specified by `Program' . If any shader
+%% objects of type `?GL_VERTEX_SHADER' are attached to `Program' , they will be
+%% used to create an executable that will run on the programmable vertex processor. If any
+%% shader objects of type `?GL_GEOMETRY_SHADER' are attached to `Program' , they
+%% will be used to create an executable that will run on the programmable geometry processor.
+%% If any shader objects of type `?GL_FRAGMENT_SHADER' are attached to `Program' ,
+%% they will be used to create an executable that will run on the programmable fragment processor.
+%%
+%%
+%% The status of the link operation will be stored as part of the program object's state.
+%% This value will be set to `?GL_TRUE' if the program object was linked without errors
+%% and is ready for use, and `?GL_FALSE' otherwise. It can be queried by calling {@link gl:getProgramiv/2}
+%% with arguments `Program' and `?GL_LINK_STATUS'.
+%%
+%% As a result of a successful link operation, all active user-defined uniform variables
+%% belonging to `Program' will be initialized to 0, and each of the program object's
+%% active uniform variables will be assigned a location that can be queried by calling {@link gl:getUniformLocation/2}
+%% . Also, any active user-defined attribute variables that have not been bound to a generic
+%% vertex attribute index will be bound to one at this time.
+%%
+%% Linking of a program object can fail for a number of reasons as specified in the `OpenGL Shading Language Specification'
+%% . The following lists some of the conditions that will cause a link error.
+%%
+%% The number of active attribute variables supported by the implementation has been exceeded.
+%%
+%%
+%% The storage limit for uniform variables has been exceeded.
+%%
+%% The number of active uniform variables supported by the implementation has been exceeded.
+%%
+%% The `main' function is missing for the vertex, geometry or fragment shader.
+%%
+%% A varying variable actually used in the fragment shader is not declared in the same way
+%% (or is not declared at all) in the vertex shader, or geometry shader shader if present.
+%%
+%% A reference to a function or variable name is unresolved.
+%%
+%% A shared global is declared with two different types or two different initial values.
+%%
+%% One or more of the attached shader objects has not been successfully compiled.
+%%
+%% Binding a generic attribute matrix caused some rows of the matrix to fall outside the
+%% allowed maximum of `?GL_MAX_VERTEX_ATTRIBS'.
+%%
+%% Not enough contiguous vertex attribute slots could be found to bind attribute matrices.
+%%
+%% The program object contains objects to form a fragment shader but does not contain objects
+%% to form a vertex shader.
+%%
+%% The program object contains objects to form a geometry shader but does not contain objects
+%% to form a vertex shader.
+%%
+%% The program object contains objects to form a geometry shader and the input primitive
+%% type, output primitive type, or maximum output vertex count is not specified in any compiled
+%% geometry shader object.
+%%
+%% The program object contains objects to form a geometry shader and the input primitive
+%% type, output primitive type, or maximum output vertex count is specified differently in
+%% multiple geometry shader objects.
+%%
+%% The number of active outputs in the fragment shader is greater than the value of `?GL_MAX_DRAW_BUFFERS'
+%% .
+%%
+%% The program has an active output assigned to a location greater than or equal to the value
+%% of `?GL_MAX_DUAL_SOURCE_DRAW_BUFFERS' and has an active output assigned an index
+%% greater than or equal to one.
+%%
+%% More than one varying out variable is bound to the same number and index.
+%%
+%% The explicit binding assigments do not leave enough space for the linker to automatically
+%% assign a location for a varying out array, which requires multiple contiguous locations.
+%%
+%% The `Count' specified by {@link gl:transformFeedbackVaryings/3} is non-zero, but the
+%% program object has no vertex or geometry shader.
+%%
+%% Any variable name specified to {@link gl:transformFeedbackVaryings/3} in the `Varyings'
+%% array is not declared as an output in the vertex shader (or the geometry shader, if active).
+%%
+%%
+%% Any two entries in the `Varyings' array given {@link gl:transformFeedbackVaryings/3}
+%% specify the same varying variable.
+%%
+%% The total number of components to capture in any transform feedback varying variable is
+%% greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' and the
+%% buffer mode is `?SEPARATE_ATTRIBS'.
+%%
+%% When a program object has been successfully linked, the program object can be made part
+%% of current state by calling {@link gl:useProgram/1} . Whether or not the link operation
+%% was successful, the program object's information log will be overwritten. The information
+%% log can be retrieved by calling {@link gl:getProgramInfoLog/2} .
+%%
+%% ``gl:linkProgram'' will also install the generated executables as part of the current
+%% rendering state if the link operation was successful and the specified program object
+%% is already currently in use as a result of a previous call to {@link gl:useProgram/1} .
+%% If the program object currently in use is relinked unsuccessfully, its link status will
+%% be set to `?GL_FALSE' , but the executables and associated state will remain part
+%% of the current state until a subsequent call to ``gl:useProgram'' removes it from use.
+%% After it is removed from use, it cannot be made part of current state until it has been
+%% successfully relinked.
+%%
+%% If `Program' contains shader objects of type `?GL_VERTEX_SHADER', and optionally
+%% of type `?GL_GEOMETRY_SHADER', but does not contain shader objects of type `?GL_FRAGMENT_SHADER'
+%% , the vertex shader executable will be installed on the programmable vertex processor,
+%% the geometry shader executable, if present, will be installed on the programmable geometry
+%% processor, but no executable will be installed on the fragment processor. The results
+%% of rasterizing primitives with such a program will be undefined.
+%%
+%% The program object's information log is updated and the program is generated at the time
+%% of the link operation. After the link operation, applications are free to modify attached
+%% shader objects, compile attached shader objects, detach shader objects, delete shader
+%% objects, and attach additional shader objects. None of these operations affects the information
+%% log or the program that is part of the program object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgram.xml">external</a> documentation.
+-spec linkProgram(Program) -> ok when Program :: integer().
linkProgram(Program) ->
cast(5472, <<Program:?GLuint>>).
-%% @spec (Shader::integer(),String::[string()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml">external</a> documentation.
--spec shaderSource(integer(),[string()]) -> ok.
+%% @doc Replaces the source code in a shader object
+%%
+%% ``gl:shaderSource'' sets the source code in `Shader' to the source code in the
+%% array of strings specified by `String' . Any source code previously stored in the
+%% shader object is completely replaced. The number of strings in the array is specified
+%% by `Count' . If `Length' is `?NULL', each string is assumed to be null
+%% terminated. If `Length' is a value other than `?NULL', it points to an array
+%% containing a string length for each of the corresponding elements of `String' .
+%% Each element in the `Length' array may contain the length of the corresponding
+%% string (the null character is not counted as part of the string length) or a value less
+%% than 0 to indicate that the string is null terminated. The source code strings are not
+%% scanned or parsed at this time; they are simply copied into the specified shader object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml">external</a> documentation.
+-spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: [string()].
shaderSource(Shader,String) ->
StringTemp = list_to_binary([[Str|[0]] || Str <- String ]),
cast(5473, <<Shader:?GLuint,(length(String)):?GLuint,(size(StringTemp)):?GLuint,(StringTemp)/binary,0:((8-((size(StringTemp)+0) rem 8)) rem 8)>>).
-%% @spec (Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml">external</a> documentation.
--spec useProgram(integer()) -> ok.
+%% @doc Installs a program object as part of current rendering state
+%%
+%% ``gl:useProgram'' installs the program object specified by `Program' as part of
+%% current rendering state. One or more executables are created in a program object by
+%% successfully attaching shader objects to it with {@link gl:attachShader/2} , successfully
+%% compiling the shader objects with {@link gl:compileShader/1} , and successfully linking
+%% the program object with {@link gl:linkProgram/1} .
+%%
+%% A program object will contain an executable that will run on the vertex processor if
+%% it contains one or more shader objects of type `?GL_VERTEX_SHADER' that have been
+%% successfully compiled and linked. A program object will contain an executable that will
+%% run on the geometry processor if it contains one or more shader objects of type `?GL_GEOMETRY_SHADER'
+%% that have been successfully compiled and linked. Similarly, a program object will contain
+%% an executable that will run on the fragment processor if it contains one or more shader
+%% objects of type `?GL_FRAGMENT_SHADER' that have been successfully compiled and
+%% linked.
+%%
+%% While a program object is in use, applications are free to modify attached shader objects,
+%% compile attached shader objects, attach additional shader objects, and detach or delete
+%% shader objects. None of these operations will affect the executables that are part of
+%% the current state. However, relinking the program object that is currently in use will
+%% install the program object as part of the current rendering state if the link operation
+%% was successful (see {@link gl:linkProgram/1} ). If the program object currently in use
+%% is relinked unsuccessfully, its link status will be set to `?GL_FALSE', but the
+%% executables and associated state will remain part of the current state until a subsequent
+%% call to ``gl:useProgram'' removes it from use. After it is removed from use, it cannot
+%% be made part of current state until it has been successfully relinked.
+%%
+%% If `Program' is zero, then the current rendering state refers to an `invalid'
+%% program object and the results of shader execution are undefined. However, this is not
+%% an error.
+%%
+%% If `Program' does not contain shader objects of type `?GL_FRAGMENT_SHADER',
+%% an executable will be installed on the vertex, and possibly geometry processors, but
+%% the results of fragment shader execution will be undefined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml">external</a> documentation.
+-spec useProgram(Program) -> ok when Program :: integer().
useProgram(Program) ->
cast(5474, <<Program:?GLuint>>).
-%% @spec (Location::integer(),V0::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1f(integer(),float()) -> ok.
+%% @doc Specify the value of a uniform variable for the current program object
+%%
+%% ``gl:uniform'' modifies the value of a uniform variable or a uniform variable array.
+%% The location of the uniform variable to be modified is specified by `Location' , which
+%% should be a value returned by {@link gl:getUniformLocation/2} . ``gl:uniform'' operates
+%% on the program object that was made part of current state by calling {@link gl:useProgram/1}
+%% .
+%%
+%% The commands ``gl:uniform{1|2|3|4}{f|i|ui}'' are used to change the value of the uniform
+%% variable specified by `Location' using the values passed as arguments. The number
+%% specified in the command should match the number of components in the data type of the
+%% specified uniform variable (e.g., `1' for float, int, unsigned int, bool; `2'
+%% for vec2, ivec2, uvec2, bvec2, etc.). The suffix `f' indicates that floating-point
+%% values are being passed; the suffix `i' indicates that integer values are being passed;
+%% the suffix `ui' indicates that unsigned integer values are being passed, and this
+%% type should also match the data type of the specified uniform variable. The `i' variants
+%% of this function should be used to provide values for uniform variables defined as int, ivec2
+%% , ivec3, ivec4, or arrays of these. The `ui' variants of this function should be
+%% used to provide values for uniform variables defined as unsigned int, uvec2, uvec3, uvec4,
+%% or arrays of these. The `f' variants should be used to provide values for uniform
+%% variables of type float, vec2, vec3, vec4, or arrays of these. Either the `i', `ui'
+%% or `f' variants may be used to provide values for uniform variables of type bool, bvec2
+%% , bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input
+%% value is 0 or 0.0f, and it will be set to true otherwise.
+%%
+%% All active uniform variables defined in a program object are initialized to 0 when the
+%% program object is linked successfully. They retain the values assigned to them by a call
+%% to ``gl:uniform '' until the next successful link operation occurs on the program object,
+%% when they are once again initialized to 0.
+%%
+%% The commands ``gl:uniform{1|2|3|4}{f|i|ui}v'' can be used to modify a single uniform
+%% variable or a uniform variable array. These commands pass a count and a pointer to the
+%% values to be loaded into a uniform variable or a uniform variable array. A count of 1
+%% should be used if modifying the value of a single uniform variable, and a count of 1 or
+%% greater can be used to modify an entire array or part of an array. When loading `n'
+%% elements starting at an arbitrary position `m' in a uniform variable array, elements
+%% `m' + `n' - 1 in the array will be replaced with the new values. If `M' + `N'
+%% - 1 is larger than the size of the uniform variable array, values for all array elements
+%% beyond the end of the array will be ignored. The number specified in the name of the command
+%% indicates the number of components for each element in `Value' , and it should match
+%% the number of components in the data type of the specified uniform variable (e.g., `1'
+%% for float, int, bool; `2' for vec2, ivec2, bvec2, etc.). The data type specified
+%% in the name of the command must match the data type for the specified uniform variable
+%% as described previously for ``gl:uniform{1|2|3|4}{f|i|ui}''.
+%%
+%% For uniform variable arrays, each element of the array is considered to be of the type
+%% indicated in the name of the command (e.g., ``gl:uniform3f'' or ``gl:uniform3fv''
+%% can be used to load a uniform variable array of type vec3). The number of elements of
+%% the uniform variable array to be modified is specified by `Count'
+%%
+%% The commands ``gl:uniformMatrix{2|3|4|2x3|3x2|2x4|4x2|3x4|4x3}fv'' are used to modify
+%% a matrix or an array of matrices. The numbers in the command name are interpreted as the
+%% dimensionality of the matrix. The number `2' indicates a 2 � 2 matrix (i.e., 4 values),
+%% the number `3' indicates a 3 � 3 matrix (i.e., 9 values), and the number `4'
+%% indicates a 4 � 4 matrix (i.e., 16 values). Non-square matrix dimensionality is explicit,
+%% with the first number representing the number of columns and the second number representing
+%% the number of rows. For example, `2x4' indicates a 2 � 4 matrix with 2 columns and
+%% 4 rows (i.e., 8 values). If `Transpose' is `?GL_FALSE', each matrix is assumed
+%% to be supplied in column major order. If `Transpose' is `?GL_TRUE', each matrix
+%% is assumed to be supplied in row major order. The `Count' argument indicates the
+%% number of matrices to be passed. A count of 1 should be used if modifying the value of
+%% a single matrix, and a count greater than 1 can be used to modify an array of matrices.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
+-spec uniform1f(Location, V0) -> ok when Location :: integer(),V0 :: float().
uniform1f(Location,V0) ->
cast(5475, <<Location:?GLint,V0:?GLfloat>>).
-%% @spec (Location::integer(),V0::float(),V1::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2f(integer(),float(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2f(Location, V0, V1) -> ok when Location :: integer(),V0 :: float(),V1 :: float().
uniform2f(Location,V0,V1) ->
cast(5476, <<Location:?GLint,V0:?GLfloat,V1:?GLfloat>>).
-%% @spec (Location::integer(),V0::float(),V1::float(),V2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3f(integer(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3f(Location, V0, V1, V2) -> ok when Location :: integer(),V0 :: float(),V1 :: float(),V2 :: float().
uniform3f(Location,V0,V1,V2) ->
cast(5477, <<Location:?GLint,V0:?GLfloat,V1:?GLfloat,V2:?GLfloat>>).
-%% @spec (Location::integer(),V0::float(),V1::float(),V2::float(),V3::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4f(integer(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4f(Location, V0, V1, V2, V3) -> ok when Location :: integer(),V0 :: float(),V1 :: float(),V2 :: float(),V3 :: float().
uniform4f(Location,V0,V1,V2,V3) ->
cast(5478, <<Location:?GLint,V0:?GLfloat,V1:?GLfloat,V2:?GLfloat,V3:?GLfloat>>).
-%% @spec (Location::integer(),V0::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1i(integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1i(Location, V0) -> ok when Location :: integer(),V0 :: integer().
uniform1i(Location,V0) ->
cast(5479, <<Location:?GLint,V0:?GLint>>).
-%% @spec (Location::integer(),V0::integer(),V1::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2i(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2i(Location, V0, V1) -> ok when Location :: integer(),V0 :: integer(),V1 :: integer().
uniform2i(Location,V0,V1) ->
cast(5480, <<Location:?GLint,V0:?GLint,V1:?GLint>>).
-%% @spec (Location::integer(),V0::integer(),V1::integer(),V2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3i(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3i(Location, V0, V1, V2) -> ok when Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer().
uniform3i(Location,V0,V1,V2) ->
cast(5481, <<Location:?GLint,V0:?GLint,V1:?GLint,V2:?GLint>>).
-%% @spec (Location::integer(),V0::integer(),V1::integer(),V2::integer(),V3::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4i(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4i(Location, V0, V1, V2, V3) -> ok when Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer(),V3 :: integer().
uniform4i(Location,V0,V1,V2,V3) ->
cast(5482, <<Location:?GLint,V0:?GLint,V1:?GLint,V2:?GLint,V3:?GLint>>).
-%% @spec (Location::integer(),Value::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1fv(integer(),[float()]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1fv(Location, Value) -> ok when Location :: integer(),Value :: [float()].
uniform1fv(Location,Value) ->
cast(5483, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<C:?GLfloat>> || C <- Value>>)/binary,0:(((length(Value)) rem 2)*32)>>).
-%% @spec (Location::integer(),Value::[{float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2fv(integer(),[{float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2fv(Location, Value) -> ok when Location :: integer(),Value :: [{float(),float()}].
uniform2fv(Location,Value) ->
cast(5484, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3fv(integer(),[{float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3fv(Location, Value) -> ok when Location :: integer(),Value :: [{float(),float(),float()}].
uniform3fv(Location,Value) ->
cast(5485, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4fv(integer(),[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4fv(Location, Value) -> ok when Location :: integer(),Value :: [{float(),float(),float(),float()}].
uniform4fv(Location,Value) ->
cast(5486, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1iv(integer(),[integer()]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1iv(Location, Value) -> ok when Location :: integer(),Value :: [integer()].
uniform1iv(Location,Value) ->
cast(5487, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<C:?GLint>> || C <- Value>>)/binary,0:(((length(Value)) rem 2)*32)>>).
-%% @spec (Location::integer(),Value::[{integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2iv(integer(),[{integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2iv(Location, Value) -> ok when Location :: integer(),Value :: [{integer(),integer()}].
uniform2iv(Location,Value) ->
cast(5488, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLint,V2:?GLint>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3iv(integer(),[{integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3iv(Location, Value) -> ok when Location :: integer(),Value :: [{integer(),integer(),integer()}].
uniform3iv(Location,Value) ->
cast(5489, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLint,V2:?GLint,V3:?GLint>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{integer(),integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4iv(integer(),[{integer(),integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4iv(Location, Value) -> ok when Location :: integer(),Value :: [{integer(),integer(),integer(),integer()}].
uniform4iv(Location,Value) ->
cast(5490, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix.xml">external</a> documentation.
--spec uniformMatrix2fv(integer(),0|1,[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix2fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float()}].
uniformMatrix2fv(Location,Transpose,Value) ->
cast(5491, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix.xml">external</a> documentation.
--spec uniformMatrix3fv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix3fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix3fv(Location,Transpose,Value) ->
cast(5492, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix.xml">external</a> documentation.
--spec uniformMatrix4fv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix4fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix4fv(Location,Transpose,Value) ->
cast(5493, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat,V10:?GLfloat,V11:?GLfloat,V12:?GLfloat,V13:?GLfloat,V14:?GLfloat,V15:?GLfloat,V16:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16} <- Value>>)/binary>>).
-%% @spec (Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml">external</a> documentation.
--spec validateProgram(integer()) -> ok.
+%% @doc Validates a program object
+%%
+%% ``gl:validateProgram'' checks to see whether the executables contained in `Program'
+%% can execute given the current OpenGL state. The information generated by the validation
+%% process will be stored in `Program' 's information log. The validation information
+%% may consist of an empty string, or it may be a string containing information about how
+%% the current program object interacts with the rest of current OpenGL state. This provides
+%% a way for OpenGL implementers to convey more information about why the current program
+%% is inefficient, suboptimal, failing to execute, and so on.
+%%
+%% The status of the validation operation will be stored as part of the program object's
+%% state. This value will be set to `?GL_TRUE' if the validation succeeded, and `?GL_FALSE'
+%% otherwise. It can be queried by calling {@link gl:getProgramiv/2} with arguments `Program'
+%% and `?GL_VALIDATE_STATUS'. If validation is successful, `Program' is guaranteed
+%% to execute given the current state. Otherwise, `Program' is guaranteed to not execute.
+%%
+%%
+%% This function is typically useful only during application development. The informational
+%% string stored in the information log is completely implementation dependent; therefore,
+%% an application should not expect different OpenGL implementations to produce identical
+%% information strings.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml">external</a> documentation.
+-spec validateProgram(Program) -> ok when Program :: integer().
validateProgram(Program) ->
cast(5494, <<Program:?GLuint>>).
-%% @spec (Index::integer(),X::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib1d(integer(),float()) -> ok.
+%% @doc Specifies the value of a generic vertex attribute
+%%
+%% The ``gl:vertexAttrib'' family of entry points allows an application to pass generic
+%% vertex attributes in numbered locations.
+%%
+%% Generic attributes are defined as four-component values that are organized into an array.
+%% The first entry of this array is numbered 0, and the size of the array is specified by
+%% the implementation-dependent constant `?GL_MAX_VERTEX_ATTRIBS'. Individual elements
+%% of this array can be modified with a ``gl:vertexAttrib'' call that specifies the index
+%% of the element to be modified and a value for that element.
+%%
+%% These commands can be used to specify one, two, three, or all four components of the generic
+%% vertex attribute specified by `Index' . A `1' in the name of the command indicates
+%% that only one value is passed, and it will be used to modify the first component of the
+%% generic vertex attribute. The second and third components will be set to 0, and the fourth
+%% component will be set to 1. Similarly, a `2' in the name of the command indicates
+%% that values are provided for the first two components, the third component will be set
+%% to 0, and the fourth component will be set to 1. A `3' in the name of the command
+%% indicates that values are provided for the first three components and the fourth component
+%% will be set to 1, whereas a `4' in the name indicates that values are provided for
+%% all four components.
+%%
+%% The letters `s', `f', `i', `d', `ub', `us', and `ui'
+%% indicate whether the arguments are of type short, float, int, double, unsigned byte, unsigned
+%% short, or unsigned int. When `v' is appended to the name, the commands can take a
+%% pointer to an array of such values.
+%%
+%% Additional capitalized letters can indicate further alterations to the default behavior
+%% of the glVertexAttrib function:
+%%
+%% The commands containing `N' indicate that the arguments will be passed as fixed-point
+%% values that are scaled to a normalized range according to the component conversion rules
+%% defined by the OpenGL specification. Signed values are understood to represent fixed-point
+%% values in the range [-1,1], and unsigned values are understood to represent fixed-point
+%% values in the range [0,1].
+%%
+%% The commands containing `I' indicate that the arguments are extended to full signed
+%% or unsigned integers.
+%%
+%% The commands containing `P' indicate that the arguments are stored as packed components
+%% within a larger natural type.
+%%
+%% The commands containing `L' indicate that the arguments are full 64-bit quantities
+%% and should be passed directly to shader inputs declared as 64-bit double precision types.
+%%
+%%
+%% OpenGL Shading Language attribute variables are allowed to be of type mat2, mat3, or mat4.
+%% Attributes of these types may be loaded using the ``gl:vertexAttrib'' entry points.
+%% Matrices must be loaded into successive generic attribute slots in column major order,
+%% with one column of the matrix in each generic attribute slot.
+%%
+%% A user-defined attribute variable declared in a vertex shader can be bound to a generic
+%% attribute index by calling {@link gl:bindAttribLocation/3} . This allows an application
+%% to use more descriptive variable names in a vertex shader. A subsequent change to the
+%% specified generic vertex attribute will be immediately reflected as a change to the corresponding
+%% attribute variable in the vertex shader.
+%%
+%% The binding between a generic vertex attribute index and a user-defined attribute variable
+%% in a vertex shader is part of the state of a program object, but the current value of
+%% the generic vertex attribute is not. The value of each generic vertex attribute is part
+%% of current state, just like standard vertex attributes, and it is maintained even if a
+%% different program object is used.
+%%
+%% An application may freely modify generic vertex attributes that are not bound to a named
+%% vertex shader attribute variable. These values are simply maintained as part of current
+%% state and will not be accessed by the vertex shader. If a generic vertex attribute bound
+%% to an attribute variable in a vertex shader is not updated while the vertex shader is
+%% executing, the vertex shader will repeatedly use the current value for the generic vertex
+%% attribute.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
+-spec vertexAttrib1d(Index, X) -> ok when Index :: integer(),X :: float().
vertexAttrib1d(Index,X) ->
cast(5495, <<Index:?GLuint,0:32,X:?GLdouble>>).
-%% @spec (Index,{X}) -> ok
%% @equiv vertexAttrib1d(Index,X)
--spec vertexAttrib1dv(integer(),{float()}) -> ok.
+-spec vertexAttrib1dv(Index :: integer(),V) -> ok when V :: {X :: float()}.
vertexAttrib1dv(Index,{X}) -> vertexAttrib1d(Index,X).
-%% @spec (Index::integer(),X::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib1f(integer(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib1f(Index, X) -> ok when Index :: integer(),X :: float().
vertexAttrib1f(Index,X) ->
cast(5496, <<Index:?GLuint,X:?GLfloat>>).
-%% @spec (Index,{X}) -> ok
%% @equiv vertexAttrib1f(Index,X)
--spec vertexAttrib1fv(integer(),{float()}) -> ok.
+-spec vertexAttrib1fv(Index :: integer(),V) -> ok when V :: {X :: float()}.
vertexAttrib1fv(Index,{X}) -> vertexAttrib1f(Index,X).
-%% @spec (Index::integer(),X::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib1s(integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib1s(Index, X) -> ok when Index :: integer(),X :: integer().
vertexAttrib1s(Index,X) ->
cast(5497, <<Index:?GLuint,X:?GLshort>>).
-%% @spec (Index,{X}) -> ok
%% @equiv vertexAttrib1s(Index,X)
--spec vertexAttrib1sv(integer(),{integer()}) -> ok.
+-spec vertexAttrib1sv(Index :: integer(),V) -> ok when V :: {X :: integer()}.
vertexAttrib1sv(Index,{X}) -> vertexAttrib1s(Index,X).
-%% @spec (Index::integer(),X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib2d(integer(),float(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib2d(Index, X, Y) -> ok when Index :: integer(),X :: float(),Y :: float().
vertexAttrib2d(Index,X,Y) ->
cast(5498, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble>>).
-%% @spec (Index,{X,Y}) -> ok
%% @equiv vertexAttrib2d(Index,X,Y)
--spec vertexAttrib2dv(integer(),{float(),float()}) -> ok.
+-spec vertexAttrib2dv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float()}.
vertexAttrib2dv(Index,{X,Y}) -> vertexAttrib2d(Index,X,Y).
-%% @spec (Index::integer(),X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib2f(integer(),float(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib2f(Index, X, Y) -> ok when Index :: integer(),X :: float(),Y :: float().
vertexAttrib2f(Index,X,Y) ->
cast(5499, <<Index:?GLuint,X:?GLfloat,Y:?GLfloat>>).
-%% @spec (Index,{X,Y}) -> ok
%% @equiv vertexAttrib2f(Index,X,Y)
--spec vertexAttrib2fv(integer(),{float(),float()}) -> ok.
+-spec vertexAttrib2fv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float()}.
vertexAttrib2fv(Index,{X,Y}) -> vertexAttrib2f(Index,X,Y).
-%% @spec (Index::integer(),X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib2s(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib2s(Index, X, Y) -> ok when Index :: integer(),X :: integer(),Y :: integer().
vertexAttrib2s(Index,X,Y) ->
cast(5500, <<Index:?GLuint,X:?GLshort,Y:?GLshort>>).
-%% @spec (Index,{X,Y}) -> ok
%% @equiv vertexAttrib2s(Index,X,Y)
--spec vertexAttrib2sv(integer(),{integer(),integer()}) -> ok.
+-spec vertexAttrib2sv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer()}.
vertexAttrib2sv(Index,{X,Y}) -> vertexAttrib2s(Index,X,Y).
-%% @spec (Index::integer(),X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib3d(integer(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib3d(Index, X, Y, Z) -> ok when Index :: integer(),X :: float(),Y :: float(),Z :: float().
vertexAttrib3d(Index,X,Y,Z) ->
cast(5501, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Index,{X,Y,Z}) -> ok
%% @equiv vertexAttrib3d(Index,X,Y,Z)
--spec vertexAttrib3dv(integer(),{float(),float(),float()}) -> ok.
+-spec vertexAttrib3dv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
vertexAttrib3dv(Index,{X,Y,Z}) -> vertexAttrib3d(Index,X,Y,Z).
-%% @spec (Index::integer(),X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib3f(integer(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib3f(Index, X, Y, Z) -> ok when Index :: integer(),X :: float(),Y :: float(),Z :: float().
vertexAttrib3f(Index,X,Y,Z) ->
cast(5502, <<Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat>>).
-%% @spec (Index,{X,Y,Z}) -> ok
%% @equiv vertexAttrib3f(Index,X,Y,Z)
--spec vertexAttrib3fv(integer(),{float(),float(),float()}) -> ok.
+-spec vertexAttrib3fv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
vertexAttrib3fv(Index,{X,Y,Z}) -> vertexAttrib3f(Index,X,Y,Z).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib3s(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib3s(Index, X, Y, Z) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer().
vertexAttrib3s(Index,X,Y,Z) ->
cast(5503, <<Index:?GLuint,X:?GLshort,Y:?GLshort,Z:?GLshort>>).
-%% @spec (Index,{X,Y,Z}) -> ok
%% @equiv vertexAttrib3s(Index,X,Y,Z)
--spec vertexAttrib3sv(integer(),{integer(),integer(),integer()}) -> ok.
+-spec vertexAttrib3sv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
vertexAttrib3sv(Index,{X,Y,Z}) -> vertexAttrib3s(Index,X,Y,Z).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4Nbv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4Nbv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4Nbv(Index,{V1,V2,V3,V4}) ->
cast(5504, <<Index:?GLuint,V1:?GLbyte,V2:?GLbyte,V3:?GLbyte,V4:?GLbyte>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4Niv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4Niv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4Niv(Index,{V1,V2,V3,V4}) ->
cast(5505, <<Index:?GLuint,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4Nsv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4Nsv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4Nsv(Index,{V1,V2,V3,V4}) ->
cast(5506, <<Index:?GLuint,V1:?GLshort,V2:?GLshort,V3:?GLshort,V4:?GLshort>>).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4Nub(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4Nub(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
vertexAttrib4Nub(Index,X,Y,Z,W) ->
cast(5507, <<Index:?GLuint,X:?GLubyte,Y:?GLubyte,Z:?GLubyte,W:?GLubyte>>).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttrib4Nub(Index,X,Y,Z,W)
--spec vertexAttrib4Nubv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+-spec vertexAttrib4Nubv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
vertexAttrib4Nubv(Index,{X,Y,Z,W}) -> vertexAttrib4Nub(Index,X,Y,Z,W).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4Nuiv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4Nuiv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4Nuiv(Index,{V1,V2,V3,V4}) ->
cast(5508, <<Index:?GLuint,V1:?GLuint,V2:?GLuint,V3:?GLuint,V4:?GLuint>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4Nusv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4Nusv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4Nusv(Index,{V1,V2,V3,V4}) ->
cast(5509, <<Index:?GLuint,V1:?GLushort,V2:?GLushort,V3:?GLushort,V4:?GLushort>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4bv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4bv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4bv(Index,{V1,V2,V3,V4}) ->
cast(5510, <<Index:?GLuint,V1:?GLbyte,V2:?GLbyte,V3:?GLbyte,V4:?GLbyte>>).
-%% @spec (Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4d(integer(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4d(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
vertexAttrib4d(Index,X,Y,Z,W) ->
cast(5511, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttrib4d(Index,X,Y,Z,W)
--spec vertexAttrib4dv(integer(),{float(),float(),float(),float()}) -> ok.
+-spec vertexAttrib4dv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
vertexAttrib4dv(Index,{X,Y,Z,W}) -> vertexAttrib4d(Index,X,Y,Z,W).
-%% @spec (Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4f(integer(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4f(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
vertexAttrib4f(Index,X,Y,Z,W) ->
cast(5512, <<Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttrib4f(Index,X,Y,Z,W)
--spec vertexAttrib4fv(integer(),{float(),float(),float(),float()}) -> ok.
+-spec vertexAttrib4fv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
vertexAttrib4fv(Index,{X,Y,Z,W}) -> vertexAttrib4f(Index,X,Y,Z,W).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4iv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4iv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4iv(Index,{V1,V2,V3,V4}) ->
cast(5513, <<Index:?GLuint,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4s(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4s(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
vertexAttrib4s(Index,X,Y,Z,W) ->
cast(5514, <<Index:?GLuint,X:?GLshort,Y:?GLshort,Z:?GLshort,W:?GLshort>>).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttrib4s(Index,X,Y,Z,W)
--spec vertexAttrib4sv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+-spec vertexAttrib4sv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
vertexAttrib4sv(Index,{X,Y,Z,W}) -> vertexAttrib4s(Index,X,Y,Z,W).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4ubv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4ubv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4ubv(Index,{V1,V2,V3,V4}) ->
cast(5515, <<Index:?GLuint,V1:?GLubyte,V2:?GLubyte,V3:?GLubyte,V4:?GLubyte>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4uiv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4uiv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4uiv(Index,{V1,V2,V3,V4}) ->
cast(5516, <<Index:?GLuint,V1:?GLuint,V2:?GLuint,V3:?GLuint,V4:?GLuint>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
--spec vertexAttrib4usv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttrib4usv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttrib4usv(Index,{V1,V2,V3,V4}) ->
cast(5517, <<Index:?GLuint,V1:?GLushort,V2:?GLushort,V3:?GLushort,V4:?GLushort>>).
-%% @spec (Index::integer(),Size::integer(),Type::enum(),Normalized::0|1,Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml">external</a> documentation.
--spec vertexAttribPointer(integer(),integer(),enum(),0|1,integer(),offset()|mem()) -> ok.
+%% @doc Define an array of generic vertex attribute data
+%%
+%% ``gl:vertexAttribPointer'', ``gl:vertexAttribIPointer'' and ``gl:vertexAttribLPointer''
+%% specify the location and data format of the array of generic vertex attributes at index `Index'
+%% to use when rendering. `Size' specifies the number of components per attribute and
+%% must be 1, 2, 3, 4, or `?GL_BGRA'. `Type' specifies the data type of each component,
+%% and `Stride' specifies the byte stride from one attribute to the next, allowing vertices
+%% and attributes to be packed into a single array or stored in separate arrays.
+%%
+%% For ``gl:vertexAttribPointer'', if `Normalized' is set to `?GL_TRUE', it
+%% indicates that values stored in an integer format are to be mapped to the range [-1,1]
+%% (for signed values) or [0,1] (for unsigned values) when they are accessed and converted
+%% to floating point. Otherwise, values will be converted to floats directly without normalization.
+%%
+%%
+%% For ``gl:vertexAttribIPointer'', only the integer types `?GL_BYTE', `?GL_UNSIGNED_BYTE'
+%% , `?GL_SHORT', `?GL_UNSIGNED_SHORT', `?GL_INT', `?GL_UNSIGNED_INT'
+%% are accepted. Values are always left as integer values.
+%%
+%% ``gl:vertexAttribLPointer'' specifies state for a generic vertex attribute array associated
+%% with a shader attribute variable declared with 64-bit double precision components. `Type'
+%% must be `?GL_DOUBLE'. `Index' , `Size' , and `Stride' behave as described
+%% for ``gl:vertexAttribPointer'' and ``gl:vertexAttribIPointer''.
+%%
+%% If `Pointer' is not NULL, a non-zero named buffer object must be bound to the `?GL_ARRAY_BUFFER'
+%% target (see {@link gl:bindBuffer/2} ), otherwise an error is generated. `Pointer'
+%% is treated as a byte offset into the buffer object's data store. The buffer object binding
+%% (`?GL_ARRAY_BUFFER_BINDING') is saved as generic vertex attribute array state (`?GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING'
+%% ) for index `Index' .
+%%
+%% When a generic vertex attribute array is specified, `Size' , `Type' , `Normalized'
+%% , `Stride' , and `Pointer' are saved as vertex array state, in addition to the
+%% current vertex array buffer object binding.
+%%
+%% To enable and disable a generic vertex attribute array, call {@link gl:disableVertexAttribArray/1}
+%% and {@link gl:disableVertexAttribArray/1} with `Index' . If enabled, the generic vertex
+%% attribute array is used when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4}
+%% , see `glMultiDrawElements', or {@link gl:drawRangeElements/6} is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml">external</a> documentation.
+-spec vertexAttribPointer(Index, Size, Type, Normalized, Stride, Pointer) -> ok when Index :: integer(),Size :: integer(),Type :: enum(),Normalized :: 0|1,Stride :: integer(),Pointer :: offset()|mem().
vertexAttribPointer(Index,Size,Type,Normalized,Stride,Pointer) when is_integer(Pointer) ->
cast(5518, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Normalized:?GLboolean,0:24,Stride:?GLsizei,Pointer:?GLuint>>);
vertexAttribPointer(Index,Size,Type,Normalized,Stride,Pointer) ->
send_bin(Pointer),
cast(5519, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Normalized:?GLboolean,0:24,Stride:?GLsizei>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix2x.xml">external</a> documentation.
--spec uniformMatrix2x3fv(integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix2x3fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
uniformMatrix2x3fv(Location,Transpose,Value) ->
cast(5520, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix3x.xml">external</a> documentation.
--spec uniformMatrix3x2fv(integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix3x2fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
uniformMatrix3x2fv(Location,Transpose,Value) ->
cast(5521, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix2x.xml">external</a> documentation.
--spec uniformMatrix2x4fv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix2x4fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix2x4fv(Location,Transpose,Value) ->
cast(5522, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix4x.xml">external</a> documentation.
--spec uniformMatrix4x2fv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix4x2fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix4x2fv(Location,Transpose,Value) ->
cast(5523, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix3x.xml">external</a> documentation.
--spec uniformMatrix3x4fv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix3x4fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix3x4fv(Location,Transpose,Value) ->
cast(5524, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat,V10:?GLfloat,V11:?GLfloat,V12:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix4x.xml">external</a> documentation.
--spec uniformMatrix4x3fv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix4x3fv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix4x3fv(Location,Transpose,Value) ->
cast(5525, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat,V10:?GLfloat,V11:?GLfloat,V12:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Index::integer(),R::0|1,G::0|1,B::0|1,A::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaski.xml">external</a> documentation.
--spec colorMaski(integer(),0|1,0|1,0|1,0|1) -> ok.
+%% @doc glColorMaski
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaski.xml">external</a> documentation.
+-spec colorMaski(Index, R, G, B, A) -> ok when Index :: integer(),R :: 0|1,G :: 0|1,B :: 0|1,A :: 0|1.
colorMaski(Index,R,G,B,A) ->
cast(5526, <<Index:?GLuint,R:?GLboolean,G:?GLboolean,B:?GLboolean,A:?GLboolean>>).
-%% @spec (Target::enum(),Index::integer()) -> [0|1]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBooleani_v.xml">external</a> documentation.
--spec getBooleani_v(enum(),integer()) -> [0|1].
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getBooleani_v(Target, Index) -> [0|1] when Target :: enum(),Index :: integer().
getBooleani_v(Target,Index) ->
call(5527, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetIntegeri_v.xml">external</a> documentation.
--spec getIntegeri_v(enum(),integer()) -> [integer()].
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getIntegeri_v(Target, Index) -> [integer()] when Target :: enum(),Index :: integer().
getIntegeri_v(Target,Index) ->
call(5528, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml">external</a> documentation.
--spec enablei(enum(),integer()) -> ok.
+%% @doc
+%% See {@link enable/1}
+-spec enablei(Target, Index) -> ok when Target :: enum(),Index :: integer().
enablei(Target,Index) ->
cast(5529, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDisable.xml">external</a> documentation.
--spec disablei(enum(),integer()) -> ok.
+%% @doc glEnablei
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnablei.xml">external</a> documentation.
+-spec disablei(Target, Index) -> ok when Target :: enum(),Index :: integer().
disablei(Target,Index) ->
cast(5530, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabledi.xml">external</a> documentation.
--spec isEnabledi(enum(),integer()) -> 0|1.
+%% @doc glIsEnabledi
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabledi.xml">external</a> documentation.
+-spec isEnabledi(Target, Index) -> 0|1 when Target :: enum(),Index :: integer().
isEnabledi(Target,Index) ->
call(5531, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (PrimitiveMode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginTransformFeedback.xml">external</a> documentation.
--spec beginTransformFeedback(enum()) -> ok.
+%% @doc Start transform feedback operation
+%%
+%% Transform feedback mode captures the values of varying variables written by the vertex
+%% shader (or, if active, the geometry shader). Transform feedback is said to be active after
+%% a call to ``gl:beginTransformFeedback'' until a subsequent call to {@link gl:beginTransformFeedback/1}
+%% . Transform feedback commands must be paired.
+%%
+%% If no geometry shader is present, while transform feedback is active the `Mode'
+%% parameter to {@link gl:drawArrays/3} must match those specified in the following table: <table>
+%% <tbody><tr><td>` Transform Feedback ' `PrimitiveMode' </td><td>` Allowed Render Primitive '
+%% `Modes' </td></tr></tbody><tbody><tr><td>`?GL_POINTS'</td><td>`?GL_POINTS'</td>
+%% </tr><tr><td>`?GL_LINES'</td><td>`?GL_LINES', `?GL_LINE_LOOP', `?GL_LINE_STRIP'
+%% , `?GL_LINES_ADJACENCY', `?GL_LINE_STRIP_ADJACENCY'</td></tr><tr><td>`?GL_TRIANGLES'
+%% </td><td>`?GL_TRIANGLES', `?GL_TRIANGLE_STRIP', `?GL_TRIANGLE_FAN', `?GL_TRIANGLES_ADJACENCY'
+%% , `?GL_TRIANGLE_STRIP_ADJACENCY'</td></tr></tbody></table>
+%%
+%% If a geometry shader is present, the output primitive type from the geometry shader must
+%% match those provided in the following table: <table><tbody><tr><td>` Transform Feedback '
+%% `PrimitiveMode' </td><td>` Allowed Geometry Shader Output Primitive Type '</td></tr>
+%% </tbody><tbody><tr><td>`?GL_POINTS'</td><td>`?points'</td></tr><tr><td>`?GL_LINES'
+%% </td><td>`?line_strip'</td></tr><tr><td>`?GL_TRIANGLES'</td><td>`?triangle_strip'
+%% </td></tr></tbody></table>
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginTransformFeedback.xml">external</a> documentation.
+-spec beginTransformFeedback(PrimitiveMode) -> ok when PrimitiveMode :: enum().
beginTransformFeedback(PrimitiveMode) ->
cast(5532, <<PrimitiveMode:?GLenum>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEndTransformFeedback.xml">external</a> documentation.
+%% @doc
+%% See {@link beginTransformFeedback/1}
-spec endTransformFeedback() -> ok.
endTransformFeedback() ->
cast(5533, <<>>).
-%% @spec (Target::enum(),Index::integer(),Buffer::integer(),Offset::integer(),Size::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferRange.xml">external</a> documentation.
--spec bindBufferRange(enum(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc Bind a range within a buffer object to an indexed buffer target
+%%
+%% ``gl:bindBufferRange'' binds a range the buffer object `Buffer' represented by `Offset'
+%% and `Size' to the binding point at index `Index' of the array of targets specified
+%% by `Target' . Each `Target' represents an indexed array of buffer binding points,
+%% as well as a single general binding point that can be used by other buffer manipulation
+%% functions such as {@link gl:bindBuffer/2} or see `glMapBuffer'. In addition to binding
+%% a range of `Buffer' to the indexed buffer binding target, ``gl:bindBufferBase''
+%% also binds the range to the generic buffer binding point specified by `Target' .
+%%
+%% `Offset' specifies the offset in basic machine units into the buffer object `Buffer'
+%% and `Size' specifies the amount of data that can be read from the buffer object
+%% while used as an indexed target.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferRange.xml">external</a> documentation.
+-spec bindBufferRange(Target, Index, Buffer, Offset, Size) -> ok when Target :: enum(),Index :: integer(),Buffer :: integer(),Offset :: integer(),Size :: integer().
bindBufferRange(Target,Index,Buffer,Offset,Size) ->
cast(5534, <<Target:?GLenum,Index:?GLuint,Buffer:?GLuint,0:32,Offset:?GLintptr,Size:?GLsizeiptr>>).
-%% @spec (Target::enum(),Index::integer(),Buffer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferBase.xml">external</a> documentation.
--spec bindBufferBase(enum(),integer(),integer()) -> ok.
+%% @doc Bind a buffer object to an indexed buffer target
+%%
+%% ``gl:bindBufferBase'' binds the buffer object `Buffer' to the binding point at
+%% index `Index' of the array of targets specified by `Target' . Each `Target'
+%% represents an indexed array of buffer binding points, as well as a single general binding
+%% point that can be used by other buffer manipulation functions such as {@link gl:bindBuffer/2}
+%% or see `glMapBuffer'. In addition to binding `Buffer' to the indexed buffer
+%% binding target, ``gl:bindBufferBase'' also binds `Buffer' to the generic buffer
+%% binding point specified by `Target' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferBase.xml">external</a> documentation.
+-spec bindBufferBase(Target, Index, Buffer) -> ok when Target :: enum(),Index :: integer(),Buffer :: integer().
bindBufferBase(Target,Index,Buffer) ->
cast(5535, <<Target:?GLenum,Index:?GLuint,Buffer:?GLuint>>).
-%% @spec (Program::integer(),Varyings::[string()],BufferMode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTransformFeedbackVaryings.xml">external</a> documentation.
--spec transformFeedbackVaryings(integer(),[string()],enum()) -> ok.
+%% @doc Specify values to record in transform feedback buffers
+%%
+%% The names of the vertex or geometry shader outputs to be recorded in transform feedback
+%% mode are specified using ``gl:transformFeedbackVaryings''. When a geometry shader is
+%% active, transform feedback records the values of selected geometry shader output variables
+%% from the emitted vertices. Otherwise, the values of the selected vertex shader outputs
+%% are recorded.
+%%
+%% The state set by ``gl:tranformFeedbackVaryings'' is stored and takes effect next time {@link gl:linkProgram/1}
+%% is called on `Program' . When {@link gl:linkProgram/1} is called, `Program' is
+%% linked so that the values of the specified varying variables for the vertices of each
+%% primitive generated by the GL are written to a single buffer object if `BufferMode'
+%% is `?GL_INTERLEAVED_ATTRIBS' or multiple buffer objects if `BufferMode' is `?GL_SEPARATE_ATTRIBS'
+%% .
+%%
+%% In addition to the errors generated by ``gl:transformFeedbackVaryings'', the program `Program'
+%% will fail to link if:
+%%
+%% The count specified by ``gl:transformFeedbackVaryings'' is non-zero, but the program
+%% object has no vertex or geometry shader.
+%%
+%% Any variable name specified in the `Varyings' array is not declared as an output
+%% in the vertex shader (or the geometry shader, if active).
+%%
+%% Any two entries in the `Varyings' array specify the same varying variable.
+%%
+%% The total number of components to capture in any varying variable in `Varyings'
+%% is greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' and
+%% the buffer mode is `?GL_SEPARATE_ATTRIBS'.
+%%
+%% The total number of components to capture is greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS'
+%% and the buffer mode is `?GL_INTERLEAVED_ATTRIBS'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTransformFeedbackVaryings.xml">external</a> documentation.
+-spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: [string()],BufferMode :: enum().
transformFeedbackVaryings(Program,Varyings,BufferMode) ->
VaryingsTemp = list_to_binary([[Str|[0]] || Str <- Varyings ]),
cast(5536, <<Program:?GLuint,(length(Varyings)):?GLuint,(size(VaryingsTemp)):?GLuint,(VaryingsTemp)/binary,0:((8-((size(VaryingsTemp)+0) rem 8)) rem 8),BufferMode:?GLenum>>).
-%% @spec (Program::integer(),Index::integer(),BufSize::integer()) -> {Size::integer(),Type::enum(),Name::string()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTransformFeedbackVarying.xml">external</a> documentation.
--spec getTransformFeedbackVarying(integer(),integer(),integer()) -> {integer(),enum(),string()}.
+%% @doc Retrieve information about varying variables selected for transform feedback
+%%
+%% Information about the set of varying variables in a linked program that will be captured
+%% during transform feedback may be retrieved by calling ``gl:getTransformFeedbackVarying''.
+%% ``gl:getTransformFeedbackVarying'' provides information about the varying variable selected
+%% by `Index' . An `Index' of 0 selects the first varying variable specified in
+%% the `Varyings' array passed to {@link gl:transformFeedbackVaryings/3} , and an `Index'
+%% of `?GL_TRANSFORM_FEEDBACK_VARYINGS-1' selects the last such variable.
+%%
+%% The name of the selected varying is returned as a null-terminated string in `Name' .
+%% The actual number of characters written into `Name' , excluding the null terminator,
+%% is returned in `Length' . If `Length' is NULL, no length is returned. The maximum
+%% number of characters that may be written into `Name' , including the null terminator,
+%% is specified by `BufSize' .
+%%
+%% The length of the longest varying name in program is given by `?GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH'
+%% , which can be queried with {@link gl:getProgramiv/2} .
+%%
+%% For the selected varying variable, its type is returned into `Type' . The size of
+%% the varying is returned into `Size' . The value in `Size' is in units of the
+%% type returned in `Type' . The type returned can be any of the scalar, vector, or matrix
+%% attribute types returned by {@link gl:getActiveAttrib/3} . If an error occurred, the return
+%% parameters `Length' , `Size' , `Type' and `Name' will be unmodified.
+%% This command will return as much information about the varying variables as possible.
+%% If no information is available, `Length' will be set to zero and `Name' will
+%% be an empty string. This situation could arise if ``gl:getTransformFeedbackVarying''
+%% is called after a failed link.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTransformFeedbackVarying.xml">external</a> documentation.
+-spec getTransformFeedbackVarying(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer().
getTransformFeedbackVarying(Program,Index,BufSize) ->
call(5537, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Target::enum(),Clamp::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClampColor.xml">external</a> documentation.
--spec clampColor(enum(),enum()) -> ok.
+%% @doc specify whether data read via
+%%
+%% {@link gl:readPixels/7} should be clamped
+%%
+%% ``gl:clampColor'' controls color clamping that is performed during {@link gl:readPixels/7}
+%% . `Target' must be `?GL_CLAMP_READ_COLOR'. If `Clamp' is `?GL_TRUE',
+%% read color clamping is enabled; if `Clamp' is `?GL_FALSE', read color clamping
+%% is disabled. If `Clamp' is `?GL_FIXED_ONLY', read color clamping is enabled
+%% only if the selected read buffer has fixed point components and disabled otherwise.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClampColor.xml">external</a> documentation.
+-spec clampColor(Target, Clamp) -> ok when Target :: enum(),Clamp :: enum().
clampColor(Target,Clamp) ->
cast(5538, <<Target:?GLenum,Clamp:?GLenum>>).
-%% @spec (Id::integer(),Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginConditionalRender.xml">external</a> documentation.
--spec beginConditionalRender(integer(),enum()) -> ok.
+%% @doc Start conditional rendering
+%%
+%% Conditional rendering is started using ``gl:beginConditionalRender'' and ended using ``gl:endConditionalRender''
+%% . During conditional rendering, all vertex array commands, as well as {@link gl:clear/1}
+%% and {@link gl:clearBufferiv/3} have no effect if the (`?GL_SAMPLES_PASSED') result of
+%% the query object `Id' is zero, or if the (`?GL_ANY_SAMPLES_PASSED') result is `?GL_FALSE'
+%% . The results of commands setting the current vertex state, such as {@link gl:vertexAttrib1d/2}
+%% are undefined. If the (`?GL_SAMPLES_PASSED') result is non-zero or if the (`?GL_ANY_SAMPLES_PASSED'
+%% ) result is `?GL_TRUE', such commands are not discarded. The `Id' parameter to ``gl:beginConditionalRender''
+%% must be the name of a query object previously returned from a call to {@link gl:genQueries/1}
+%% . `Mode' specifies how the results of the query object are to be interpreted. If `Mode'
+%% is `?GL_QUERY_WAIT', the GL waits for the results of the query to be available and
+%% then uses the results to determine if subsequent rendering commands are discarded. If `Mode'
+%% is `?GL_QUERY_NO_WAIT', the GL may choose to unconditionally execute the subsequent
+%% rendering commands without waiting for the query to complete.
+%%
+%% If `Mode' is `?GL_QUERY_BY_REGION_WAIT', the GL will also wait for occlusion
+%% query results and discard rendering commands if the result of the occlusion query is zero.
+%% If the query result is non-zero, subsequent rendering commands are executed, but the GL
+%% may discard the results of the commands for any region of the framebuffer that did not
+%% contribute to the sample count in the specified occlusion query. Any such discarding is
+%% done in an implementation-dependent manner, but the rendering command results may not
+%% be discarded for any samples that contributed to the occlusion query sample count. If `Mode'
+%% is `?GL_QUERY_BY_REGION_NO_WAIT', the GL operates as in `?GL_QUERY_BY_REGION_WAIT'
+%% , but may choose to unconditionally execute the subsequent rendering commands without
+%% waiting for the query to complete.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginConditionalRender.xml">external</a> documentation.
+-spec beginConditionalRender(Id, Mode) -> ok when Id :: integer(),Mode :: enum().
beginConditionalRender(Id,Mode) ->
cast(5539, <<Id:?GLuint,Mode:?GLenum>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEndConditionalRender.xml">external</a> documentation.
+%% @doc
+%% See {@link beginConditionalRender/2}
-spec endConditionalRender() -> ok.
endConditionalRender() ->
cast(5540, <<>>).
-%% @spec (Index::integer(),Size::integer(),Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribIPointer.xml">external</a> documentation.
--spec vertexAttribIPointer(integer(),integer(),enum(),integer(),offset()|mem()) -> ok.
+%% @doc glVertexAttribIPointer
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribIPointer.xml">external</a> documentation.
+-spec vertexAttribIPointer(Index, Size, Type, Stride, Pointer) -> ok when Index :: integer(),Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
vertexAttribIPointer(Index,Size,Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5541, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
vertexAttribIPointer(Index,Size,Type,Stride,Pointer) ->
send_bin(Pointer),
cast(5542, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
-%% @spec (Index::integer(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribI.xml">external</a> documentation.
--spec getVertexAttribIiv(integer(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getVertexAttribdv/2}
+-spec getVertexAttribIiv(Index, Pname) -> {integer(),integer(),integer(),integer()} when Index :: integer(),Pname :: enum().
getVertexAttribIiv(Index,Pname) ->
call(5543, <<Index:?GLuint,Pname:?GLenum>>).
-%% @spec (Index::integer(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribI.xml">external</a> documentation.
--spec getVertexAttribIuiv(integer(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc glGetVertexAttribI
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribI.xml">external</a> documentation.
+-spec getVertexAttribIuiv(Index, Pname) -> {integer(),integer(),integer(),integer()} when Index :: integer(),Pname :: enum().
getVertexAttribIuiv(Index,Pname) ->
call(5544, <<Index:?GLuint,Pname:?GLenum>>).
-%% @spec (Index::integer(),X::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI1i(integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI1i(Index, X) -> ok when Index :: integer(),X :: integer().
vertexAttribI1i(Index,X) ->
cast(5545, <<Index:?GLuint,X:?GLint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI2i(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI2i(Index, X, Y) -> ok when Index :: integer(),X :: integer(),Y :: integer().
vertexAttribI2i(Index,X,Y) ->
cast(5546, <<Index:?GLuint,X:?GLint,Y:?GLint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI3i(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI3i(Index, X, Y, Z) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer().
vertexAttribI3i(Index,X,Y,Z) ->
cast(5547, <<Index:?GLuint,X:?GLint,Y:?GLint,Z:?GLint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI4i(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI4i(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
vertexAttribI4i(Index,X,Y,Z,W) ->
cast(5548, <<Index:?GLuint,X:?GLint,Y:?GLint,Z:?GLint,W:?GLint>>).
-%% @spec (Index::integer(),X::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI1ui(integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI1ui(Index, X) -> ok when Index :: integer(),X :: integer().
vertexAttribI1ui(Index,X) ->
cast(5549, <<Index:?GLuint,X:?GLuint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI2ui(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI2ui(Index, X, Y) -> ok when Index :: integer(),X :: integer(),Y :: integer().
vertexAttribI2ui(Index,X,Y) ->
cast(5550, <<Index:?GLuint,X:?GLuint,Y:?GLuint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI3ui(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI3ui(Index, X, Y, Z) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer().
vertexAttribI3ui(Index,X,Y,Z) ->
cast(5551, <<Index:?GLuint,X:?GLuint,Y:?GLuint,Z:?GLuint>>).
-%% @spec (Index::integer(),X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI4ui(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI4ui(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: integer(),Y :: integer(),Z :: integer(),W :: integer().
vertexAttribI4ui(Index,X,Y,Z,W) ->
cast(5552, <<Index:?GLuint,X:?GLuint,Y:?GLuint,Z:?GLuint,W:?GLuint>>).
-%% @spec (Index,{X}) -> ok
%% @equiv vertexAttribI1i(Index,X)
--spec vertexAttribI1iv(integer(),{integer()}) -> ok.
+-spec vertexAttribI1iv(Index :: integer(),V) -> ok when V :: {X :: integer()}.
vertexAttribI1iv(Index,{X}) -> vertexAttribI1i(Index,X).
-%% @spec (Index,{X,Y}) -> ok
%% @equiv vertexAttribI2i(Index,X,Y)
--spec vertexAttribI2iv(integer(),{integer(),integer()}) -> ok.
+-spec vertexAttribI2iv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer()}.
vertexAttribI2iv(Index,{X,Y}) -> vertexAttribI2i(Index,X,Y).
-%% @spec (Index,{X,Y,Z}) -> ok
%% @equiv vertexAttribI3i(Index,X,Y,Z)
--spec vertexAttribI3iv(integer(),{integer(),integer(),integer()}) -> ok.
+-spec vertexAttribI3iv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
vertexAttribI3iv(Index,{X,Y,Z}) -> vertexAttribI3i(Index,X,Y,Z).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttribI4i(Index,X,Y,Z,W)
--spec vertexAttribI4iv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+-spec vertexAttribI4iv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
vertexAttribI4iv(Index,{X,Y,Z,W}) -> vertexAttribI4i(Index,X,Y,Z,W).
-%% @spec (Index,{X}) -> ok
%% @equiv vertexAttribI1ui(Index,X)
--spec vertexAttribI1uiv(integer(),{integer()}) -> ok.
+-spec vertexAttribI1uiv(Index :: integer(),V) -> ok when V :: {X :: integer()}.
vertexAttribI1uiv(Index,{X}) -> vertexAttribI1ui(Index,X).
-%% @spec (Index,{X,Y}) -> ok
%% @equiv vertexAttribI2ui(Index,X,Y)
--spec vertexAttribI2uiv(integer(),{integer(),integer()}) -> ok.
+-spec vertexAttribI2uiv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer()}.
vertexAttribI2uiv(Index,{X,Y}) -> vertexAttribI2ui(Index,X,Y).
-%% @spec (Index,{X,Y,Z}) -> ok
%% @equiv vertexAttribI3ui(Index,X,Y,Z)
--spec vertexAttribI3uiv(integer(),{integer(),integer(),integer()}) -> ok.
+-spec vertexAttribI3uiv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer()}.
vertexAttribI3uiv(Index,{X,Y,Z}) -> vertexAttribI3ui(Index,X,Y,Z).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttribI4ui(Index,X,Y,Z,W)
--spec vertexAttribI4uiv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+-spec vertexAttribI4uiv(Index :: integer(),V) -> ok when V :: {X :: integer(),Y :: integer(),Z :: integer(),W :: integer()}.
vertexAttribI4uiv(Index,{X,Y,Z,W}) -> vertexAttribI4ui(Index,X,Y,Z,W).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI4bv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI4bv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttribI4bv(Index,{V1,V2,V3,V4}) ->
cast(5553, <<Index:?GLuint,V1:?GLbyte,V2:?GLbyte,V3:?GLbyte,V4:?GLbyte>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI4sv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI4sv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttribI4sv(Index,{V1,V2,V3,V4}) ->
cast(5554, <<Index:?GLuint,V1:?GLshort,V2:?GLshort,V3:?GLshort,V4:?GLshort>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI4ubv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI4ubv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttribI4ubv(Index,{V1,V2,V3,V4}) ->
cast(5555, <<Index:?GLuint,V1:?GLubyte,V2:?GLubyte,V3:?GLubyte,V4:?GLubyte>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribI.xml">external</a> documentation.
--spec vertexAttribI4usv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc
+%% See {@link vertexAttrib1d/2}
+-spec vertexAttribI4usv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
vertexAttribI4usv(Index,{V1,V2,V3,V4}) ->
cast(5556, <<Index:?GLuint,V1:?GLushort,V2:?GLushort,V3:?GLushort,V4:?GLushort>>).
-%% @spec (Program::integer(),Location::integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation.
--spec getUniformuiv(integer(),integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getUniformfv/2}
+-spec getUniformuiv(Program, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when Program :: integer(),Location :: integer().
getUniformuiv(Program,Location) ->
call(5557, <<Program:?GLuint,Location:?GLint>>).
-%% @spec (Program::integer(),Color::integer(),Name::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocation.xml">external</a> documentation.
--spec bindFragDataLocation(integer(),integer(),string()) -> ok.
+%% @doc Bind a user-defined varying out variable to a fragment shader color number
+%%
+%% ``gl:bindFragDataLocation'' explicitly specifies the binding of the user-defined varying
+%% out variable `Name' to fragment shader color number `ColorNumber' for program `Program'
+%% . If `Name' was bound previously, its assigned binding is replaced with `ColorNumber'
+%% . `Name' must be a null-terminated string. `ColorNumber' must be less than `?GL_MAX_DRAW_BUFFERS'
+%% .
+%%
+%% The bindings specified by ``gl:bindFragDataLocation'' have no effect until `Program'
+%% is next linked. Bindings may be specified at any time after `Program' has been created.
+%% Specifically, they may be specified before shader objects are attached to the program.
+%% Therefore, any name may be specified in `Name' , including a name that is never used
+%% as a varying out variable in any fragment shader object. Names beginning with `?gl_'
+%% are reserved by the GL.
+%%
+%% In addition to the errors generated by ``gl:bindFragDataLocation'', the program `Program'
+%% will fail to link if:
+%%
+%% The number of active outputs is greater than the value `?GL_MAX_DRAW_BUFFERS'.
+%%
+%% More than one varying out variable is bound to the same color number.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocation.xml">external</a> documentation.
+-spec bindFragDataLocation(Program, Color, Name) -> ok when Program :: integer(),Color :: integer(),Name :: string().
bindFragDataLocation(Program,Color,Name) ->
cast(5558, <<Program:?GLuint,Color:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataLocation.xml">external</a> documentation.
--spec getFragDataLocation(integer(),string()) -> integer().
+%% @doc Query the bindings of color numbers to user-defined varying out variables
+%%
+%% ``gl:getFragDataLocation'' retrieves the assigned color number binding for the user-defined
+%% varying out variable `Name' for program `Program' . `Program' must have
+%% previously been linked. `Name' must be a null-terminated string. If `Name' is
+%% not the name of an active user-defined varying out fragment shader variable within `Program'
+%% , -1 will be returned.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataLocation.xml">external</a> documentation.
+-spec getFragDataLocation(Program, Name) -> integer() when Program :: integer(),Name :: string().
getFragDataLocation(Program,Name) ->
call(5559, <<Program:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8)>>).
-%% @spec (Location::integer(),V0::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1ui(integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1ui(Location, V0) -> ok when Location :: integer(),V0 :: integer().
uniform1ui(Location,V0) ->
cast(5560, <<Location:?GLint,V0:?GLuint>>).
-%% @spec (Location::integer(),V0::integer(),V1::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2ui(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2ui(Location, V0, V1) -> ok when Location :: integer(),V0 :: integer(),V1 :: integer().
uniform2ui(Location,V0,V1) ->
cast(5561, <<Location:?GLint,V0:?GLuint,V1:?GLuint>>).
-%% @spec (Location::integer(),V0::integer(),V1::integer(),V2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3ui(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3ui(Location, V0, V1, V2) -> ok when Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer().
uniform3ui(Location,V0,V1,V2) ->
cast(5562, <<Location:?GLint,V0:?GLuint,V1:?GLuint,V2:?GLuint>>).
-%% @spec (Location::integer(),V0::integer(),V1::integer(),V2::integer(),V3::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4ui(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4ui(Location, V0, V1, V2, V3) -> ok when Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer(),V3 :: integer().
uniform4ui(Location,V0,V1,V2,V3) ->
cast(5563, <<Location:?GLint,V0:?GLuint,V1:?GLuint,V2:?GLuint,V3:?GLuint>>).
-%% @spec (Location::integer(),Value::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1uiv(integer(),[integer()]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1uiv(Location, Value) -> ok when Location :: integer(),Value :: [integer()].
uniform1uiv(Location,Value) ->
cast(5564, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<C:?GLuint>> || C <- Value>>)/binary,0:(((length(Value)) rem 2)*32)>>).
-%% @spec (Location::integer(),Value::[{integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2uiv(integer(),[{integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2uiv(Location, Value) -> ok when Location :: integer(),Value :: [{integer(),integer()}].
uniform2uiv(Location,Value) ->
cast(5565, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLuint,V2:?GLuint>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3uiv(integer(),[{integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3uiv(Location, Value) -> ok when Location :: integer(),Value :: [{integer(),integer(),integer()}].
uniform3uiv(Location,Value) ->
cast(5566, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLuint,V2:?GLuint,V3:?GLuint>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{integer(),integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4uiv(integer(),[{integer(),integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4uiv(Location, Value) -> ok when Location :: integer(),Value :: [{integer(),integer(),integer(),integer()}].
uniform4uiv(Location,Value) ->
cast(5567, <<Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLuint,V2:?GLuint,V3:?GLuint,V4:?GLuint>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation.
--spec texParameterIiv(enum(),enum(),{integer()}) -> ok.
+%% @doc
+%% See {@link texParameterf/3}
+-spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
texParameterIiv(Target,Pname,Params) ->
cast(5568, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target::enum(),Pname::enum(),Params::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation.
--spec texParameterIuiv(enum(),enum(),{integer()}) -> ok.
+%% @doc glTexParameterI
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation.
+-spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
texParameterIuiv(Target,Pname,Params) ->
cast(5569, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLuint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameterI.xml">external</a> documentation.
--spec getTexParameterIiv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc
+%% See {@link getTexParameterfv/2}
+-spec getTexParameterIiv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
getTexParameterIiv(Target,Pname) ->
call(5570, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> {integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameterI.xml">external</a> documentation.
--spec getTexParameterIuiv(enum(),enum()) -> {integer(),integer(),integer(),integer()}.
+%% @doc glGetTexParameterI
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameterI.xml">external</a> documentation.
+-spec getTexParameterIuiv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
getTexParameterIuiv(Target,Pname) ->
call(5571, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Buffer::enum(),Drawbuffer::integer(),Value::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation.
--spec clearBufferiv(enum(),integer(),{integer()}) -> ok.
+%% @doc Clear individual buffers of the currently bound draw framebuffer
+%%
+%% ``gl:clearBuffer*'' clears the specified buffer to the specified value(s). If `Buffer'
+%% is `?GL_COLOR', a particular draw buffer `?GL_DRAWBUFFER' `I' is specified
+%% by passing `I' as `DrawBuffer' . In this case, `Value' points to a four-element
+%% vector specifying the R, G, B and A color to clear that draw buffer to. If `Buffer'
+%% is one of `?GL_FRONT', `?GL_BACK', `?GL_LEFT', `?GL_RIGHT', or `?GL_FRONT_AND_BACK'
+%% , identifying multiple buffers, each selected buffer is cleared to the same value. Clamping
+%% and conversion for fixed-point color buffers are performed in the same fashion as {@link gl:clearColor/4}
+%% .
+%%
+%% If `Buffer' is `?GL_DEPTH', `DrawBuffer' must be zero, and `Value'
+%% points to a single value to clear the depth buffer to. Only ``gl:clearBufferfv'' should
+%% be used to clear depth buffers. Clamping and conversion for fixed-point depth buffers
+%% are performed in the same fashion as {@link gl:clearDepth/1} .
+%%
+%% If `Buffer' is `?GL_STENCIL', `DrawBuffer' must be zero, and `Value'
+%% points to a single value to clear the stencil buffer to. Only ``gl:clearBufferiv'' should
+%% be used to clear stencil buffers. Masing and type conversion are performed in the same
+%% fashion as {@link gl:clearStencil/1} .
+%%
+%% ``gl:clearBufferfi'' may be used to clear the depth and stencil buffers. `Buffer'
+%% must be `?GL_DEPTH_STENCIL' and `DrawBuffer' must be zero. `Depth' and `Stencil'
+%% are the depth and stencil values, respectively.
+%%
+%% The result of ``gl:clearBuffer'' is undefined if no conversion between the type of `Value'
+%% and the buffer being cleared is defined. However, this is not an error.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation.
+-spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}.
clearBufferiv(Buffer,Drawbuffer,Value) ->
cast(5572, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>).
-%% @spec (Buffer::enum(),Drawbuffer::integer(),Value::{integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation.
--spec clearBufferuiv(enum(),integer(),{integer()}) -> ok.
+%% @doc
+%% See {@link clearBufferiv/3}
+-spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}.
clearBufferuiv(Buffer,Drawbuffer,Value) ->
cast(5573, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
(<< <<C:?GLuint>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>).
-%% @spec (Buffer::enum(),Drawbuffer::integer(),Value::{float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation.
--spec clearBufferfv(enum(),integer(),{float()}) -> ok.
+%% @doc
+%% See {@link clearBufferiv/3}
+-spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {float()}.
clearBufferfv(Buffer,Drawbuffer,Value) ->
cast(5574, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>).
-%% @spec (Buffer::enum(),Drawbuffer::integer(),Depth::float(),Stencil::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBufferfi.xml">external</a> documentation.
--spec clearBufferfi(enum(),integer(),float(),integer()) -> ok.
+%% @doc glClearBufferfi
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBufferfi.xml">external</a> documentation.
+-spec clearBufferfi(Buffer, Drawbuffer, Depth, Stencil) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Depth :: float(),Stencil :: integer().
clearBufferfi(Buffer,Drawbuffer,Depth,Stencil) ->
cast(5575, <<Buffer:?GLenum,Drawbuffer:?GLint,Depth:?GLfloat,Stencil:?GLint>>).
-%% @spec (Name::enum(),Index::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml">external</a> documentation.
--spec getStringi(enum(),integer()) -> string().
+%% @doc
+%% See {@link getString/1}
+-spec getStringi(Name, Index) -> string() when Name :: enum(),Index :: integer().
getStringi(Name,Index) ->
call(5576, <<Name:?GLenum,Index:?GLuint>>).
-%% @spec (Mode::enum(),First::integer(),Count::integer(),Primcount::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstance.xml">external</a> documentation.
--spec drawArraysInstanced(enum(),integer(),integer(),integer()) -> ok.
+%% @doc glDrawArraysInstance
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstance.xml">external</a> documentation.
+-spec drawArraysInstanced(Mode, First, Count, Primcount) -> ok when Mode :: enum(),First :: integer(),Count :: integer(),Primcount :: integer().
drawArraysInstanced(Mode,First,Count,Primcount) ->
cast(5577, <<Mode:?GLenum,First:?GLint,Count:?GLsizei,Primcount:?GLsizei>>).
-%% @spec (Mode::enum(),Count::integer(),Type::enum(),Indices::offset()|mem(),Primcount::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstance.xml">external</a> documentation.
--spec drawElementsInstanced(enum(),integer(),enum(),offset()|mem(),integer()) -> ok.
+%% @doc glDrawElementsInstance
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstance.xml">external</a> documentation.
+-spec drawElementsInstanced(Mode, Count, Type, Indices, Primcount) -> ok when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer().
drawElementsInstanced(Mode,Count,Type,Indices,Primcount) when is_integer(Indices) ->
cast(5578, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei>>);
drawElementsInstanced(Mode,Count,Type,Indices,Primcount) ->
send_bin(Indices),
cast(5579, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Primcount:?GLsizei>>).
-%% @spec (Target::enum(),Internalformat::enum(),Buffer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexBuffer.xml">external</a> documentation.
--spec texBuffer(enum(),enum(),integer()) -> ok.
+%% @doc Attach the storage for a buffer object to the active buffer texture
+%%
+%% ``gl:texBuffer'' attaches the storage for the buffer object named `Buffer' to the
+%% active buffer texture, and specifies the internal format for the texel array found in
+%% the attached buffer object. If `Buffer' is zero, any buffer object attached to the
+%% buffer texture is detached and no new buffer object is attached. If `Buffer' is non-zero,
+%% it must be the name of an existing buffer object. `Target' must be `?GL_TEXTURE_BUFFER'
+%% . `Internalformat' specifies the storage format, and must be one of the following
+%% sized internal formats: <table><tbody><tr><td></td><td></td><td></td><td></td><td>` Component '
+%% </td></tr></tbody><tbody><tr><td>`Sized Internal Format'</td><td>`Base Type'</td>
+%% <td>`Components'</td><td>`Norm'</td><td>0</td><td>1</td><td>2</td><td>3</td></tr>
+%% <tr><td>`?GL_R8'</td><td>ubyte</td><td>1</td><td>YES</td><td>R</td><td>0</td><td>0</td>
+%% <td>1</td></tr><tr><td>`?GL_R16'</td><td>ushort</td><td>1</td><td>YES</td><td>R</td><td>
+%% 0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R16F'</td><td>half</td><td>1</td><td>NO</td>
+%% <td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R32F'</td><td>float</td><td>
+%% 1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R8I'</td><td>
+%% byte</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R16I'
+%% </td><td>short</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>
+%% `?GL_R32I'</td><td>int</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td>
+%% </tr><tr><td>`?GL_R8UI'</td><td>ubyte</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>
+%% 0</td><td>1</td></tr><tr><td>`?GL_R16UI'</td><td>ushort</td><td>1</td><td>NO</td><td>
+%% R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R32UI'</td><td>uint</td><td>1</td>
+%% <td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8'</td><td>ubyte
+%% </td><td>2</td><td>YES</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG16'
+%% </td><td>ushort</td><td>2</td><td>YES</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr>
+%% <td>`?GL_RG16F'</td><td>half</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>
+%% 1</td></tr><tr><td>`?GL_RG32F'</td><td>float</td><td>2</td><td>NO</td><td>R</td><td>G
+%% </td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8I'</td><td>byte</td><td>2</td><td>NO</td>
+%% <td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG16I'</td><td>short</td><td>
+%% 2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG32I'</td>
+%% <td>int</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8UI'
+%% </td><td>ubyte</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>
+%% `?GL_RG16UI'</td><td>ushort</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>
+%% 1</td></tr><tr><td>`?GL_RG32UI'</td><td>uint</td><td>2</td><td>NO</td><td>R</td><td>G
+%% </td><td>0</td><td>1</td></tr><tr><td>`?GL_RGB32F'</td><td>float</td><td>3</td><td>NO
+%% </td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>`?GL_RGB32I'</td><td>int</td>
+%% <td>3</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>`?GL_RGB32UI'
+%% </td><td>uint</td><td>3</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>
+%% `?GL_RGBA8'</td><td>uint</td><td>4</td><td>YES</td><td>R</td><td>G</td><td>B</td><td>
+%% A</td></tr><tr><td>`?GL_RGBA16'</td><td>short</td><td>4</td><td>YES</td><td>R</td><td>
+%% G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA16F'</td><td>half</td><td>4</td><td>NO
+%% </td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA32F'</td><td>float
+%% </td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA8I'
+%% </td><td>byte</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>
+%% `?GL_RGBA16I'</td><td>short</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>
+%% A</td></tr><tr><td>`?GL_RGBA32I'</td><td>int</td><td>4</td><td>NO</td><td>R</td><td>G
+%% </td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA8UI'</td><td>ubyte</td><td>4</td><td>NO
+%% </td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA16UI'</td><td>ushort
+%% </td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA32UI'
+%% </td><td>uint</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr></tbody>
+%% </table>
+%%
+%% When a buffer object is attached to a buffer texture, the buffer object's data store
+%% is taken as the texture's texel array. The number of texels in the buffer texture's texel
+%% array is given by buffer_size components� sizeof( base_type/)
+%%
+%% where `buffer_size' is the size of the buffer object, in basic machine units and
+%% components and base type are the element count and base data type for elements, as specified
+%% in the table above. The number of texels in the texel array is then clamped to the implementation-dependent
+%% limit `?GL_MAX_TEXTURE_BUFFER_SIZE'. When a buffer texture is accessed in a shader,
+%% the results of a texel fetch are undefined if the specified texel coordinate is negative,
+%% or greater than or equal to the clamped number of texels in the texel array.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexBuffer.xml">external</a> documentation.
+-spec texBuffer(Target, Internalformat, Buffer) -> ok when Target :: enum(),Internalformat :: enum(),Buffer :: integer().
texBuffer(Target,Internalformat,Buffer) ->
cast(5580, <<Target:?GLenum,Internalformat:?GLenum,Buffer:?GLuint>>).
-%% @spec (Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrimitiveRestartIndex.xml">external</a> documentation.
--spec primitiveRestartIndex(integer()) -> ok.
+%% @doc Specify the primitive restart index
+%%
+%% ``gl:primitiveRestartIndex'' specifies a vertex array element that is treated specially
+%% when primitive restarting is enabled. This is known as the primitive restart index.
+%%
+%% When one of the `Draw*' commands transfers a set of generic attribute array elements
+%% to the GL, if the index within the vertex arrays corresponding to that set is equal to
+%% the primitive restart index, then the GL does not process those elements as a vertex.
+%% Instead, it is as if the drawing command ended with the immediately preceding transfer,
+%% and another drawing command is immediately started with the same parameters, but only
+%% transferring the immediately following element through the end of the originally specified
+%% elements.
+%%
+%% When either {@link gl:drawElementsBaseVertex/5} , {@link gl:drawElementsInstancedBaseVertex/6}
+%% or see `glMultiDrawElementsBaseVertex' is used, the primitive restart comparison
+%% occurs before the basevertex offset is added to the array index.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrimitiveRestartIndex.xml">external</a> documentation.
+-spec primitiveRestartIndex(Index) -> ok when Index :: integer().
primitiveRestartIndex(Index) ->
cast(5581, <<Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInteger64i_v.xml">external</a> documentation.
--spec getInteger64i_v(enum(),integer()) -> [integer()].
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getInteger64i_v(Target, Index) -> [integer()] when Target :: enum(),Index :: integer().
getInteger64i_v(Target,Index) ->
call(5582, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteri64v.xml">external</a> documentation.
--spec getBufferParameteri64v(enum(),enum()) -> [integer()].
+%% @doc glGetBufferParameteri64v
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteri64v.xml">external</a> documentation.
+-spec getBufferParameteri64v(Target, Pname) -> [integer()] when Target :: enum(),Pname :: enum().
getBufferParameteri64v(Target,Pname) ->
call(5583, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Attachment::enum(),Texture::integer(),Level::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture.xml">external</a> documentation.
--spec framebufferTexture(enum(),enum(),integer(),integer()) -> ok.
+%% @doc Attach a level of a texture object as a logical buffer to the currently bound framebuffer object
+%%
+%% ``gl:framebufferTexture'', ``gl:framebufferTexture1D'', ``gl:framebufferTexture2D'',
+%% and ``gl:framebufferTexture'' attach a selected mipmap level or image of a texture object
+%% as one of the logical buffers of the framebuffer object currently bound to `Target' .
+%% `Target' must be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER', or `?GL_FRAMEBUFFER'
+%% . `?GL_FRAMEBUFFER' is equivalent to `?GL_DRAW_FRAMEBUFFER'.
+%%
+%% `Attachment' specifies the logical attachment of the framebuffer and must be `?GL_COLOR_ATTACHMENT'
+%% `i', `?GL_DEPTH_ATTACHMENT', `?GL_STENCIL_ATTACHMENT' or `?GL_DEPTH_STENCIL_ATTACHMMENT'
+%% . `i' in `?GL_COLOR_ATTACHMENT'`i' may range from zero to the value of `?GL_MAX_COLOR_ATTACHMENTS'
+%% - 1. Attaching a level of a texture to `?GL_DEPTH_STENCIL_ATTACHMENT' is equivalent
+%% to attaching that level to both the `?GL_DEPTH_ATTACHMENT'`and' the `?GL_STENCIL_ATTACHMENT'
+%% attachment points simultaneously.
+%%
+%% `Textarget' specifies what type of texture is named by `Texture' , and for cube
+%% map textures, specifies the face that is to be attached. If `Texture' is not zero,
+%% it must be the name of an existing texture with type `Textarget' , unless it is a
+%% cube map texture, in which case `Textarget' must be `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'
+%% `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y'
+%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'.
+%%
+%% If `Texture' is non-zero, the specified `Level' of the texture object named `Texture'
+%% is attached to the framebfufer attachment point named by `Attachment' . For ``gl:framebufferTexture1D''
+%% , ``gl:framebufferTexture2D'', and ``gl:framebufferTexture3D'', `Texture' must
+%% be zero or the name of an existing texture with a target of `Textarget' , or `Texture'
+%% must be the name of an existing cube-map texture and `Textarget' must be one of `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'
+%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X'
+%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'.
+%%
+%% If `Textarget' is `?GL_TEXTURE_RECTANGLE', `?GL_TEXTURE_2D_MULTISAMPLE',
+%% or `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY', then `Level' must be zero. If `Textarget'
+%% is `?GL_TEXTURE_3D', then level must be greater than or equal to zero and less than
+%% or equal to log2 of the value of `?GL_MAX_3D_TEXTURE_SIZE'. If `Textarget' is
+%% one of `?GL_TEXTURE_CUBE_MAP_POSITIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z'
+%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'
+%% , then `Level' must be greater than or equal to zero and less than or equal to log2
+%% of the value of `?GL_MAX_CUBE_MAP_TEXTURE_SIZE'. For all other values of `Textarget'
+%% , `Level' must be greater than or equal to zero and no larger than log2 of the value
+%% of `?GL_MAX_TEXTURE_SIZE'.
+%%
+%% `Layer' specifies the layer of a 2-dimensional image within a 3-dimensional texture.
+%%
+%%
+%% For ``gl:framebufferTexture1D'', if `Texture' is not zero, then `Textarget'
+%% must be `?GL_TEXTURE_1D'. For ``gl:framebufferTexture2D'', if `Texture' is
+%% not zero, `Textarget' must be one of `?GL_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE'
+%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z'
+%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'
+%% , or `?GL_TEXTURE_2D_MULTISAMPLE'. For ``gl:framebufferTexture3D'', if `Texture'
+%% is not zero, then `Textarget' must be `?GL_TEXTURE_3D'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture.xml">external</a> documentation.
+-spec framebufferTexture(Target, Attachment, Texture, Level) -> ok when Target :: enum(),Attachment :: enum(),Texture :: integer(),Level :: integer().
framebufferTexture(Target,Attachment,Texture,Level) ->
cast(5584, <<Target:?GLenum,Attachment:?GLenum,Texture:?GLuint,Level:?GLint>>).
-%% @spec (Index::integer(),Divisor::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml">external</a> documentation.
--spec vertexAttribDivisor(integer(),integer()) -> ok.
+%% @doc Modify the rate at which generic vertex attributes advance during instanced rendering
+%%
+%% ``gl:vertexAttribDivisor'' modifies the rate at which generic vertex attributes advance
+%% when rendering multiple instances of primitives in a single draw call. If `Divisor'
+%% is zero, the attribute at slot `Index' advances once per vertex. If `Divisor'
+%% is non-zero, the attribute advances once per `Divisor' instances of the set(s) of
+%% vertices being rendered. An attribute is referred to as instanced if its `?GL_VERTEX_ATTRIB_ARRAY_DIVISOR'
+%% value is non-zero.
+%%
+%% `Index' must be less than the value of `?GL_MAX_VERTEX_ATTRIBUTES'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml">external</a> documentation.
+-spec vertexAttribDivisor(Index, Divisor) -> ok when Index :: integer(),Divisor :: integer().
vertexAttribDivisor(Index,Divisor) ->
cast(5585, <<Index:?GLuint,Divisor:?GLuint>>).
-%% @spec (Value::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinSampleShading.xml">external</a> documentation.
--spec minSampleShading(clamp()) -> ok.
+%% @doc Specifies minimum rate at which sample shaing takes place
+%%
+%% ``gl:minSampleShading'' specifies the rate at which samples are shaded within a covered
+%% pixel. Sample-rate shading is enabled by calling {@link gl:enable/1} with the parameter `?GL_SAMPLE_SHADING'
+%% . If `?GL_MULTISAMPLE' or `?GL_SAMPLE_SHADING' is disabled, sample shading has
+%% no effect. Otherwise, an implementation must provide at least as many unique color values
+%% for each covered fragment as specified by `Value' times `Samples' where `Samples'
+%% is the value of `?GL_SAMPLES' for the current framebuffer. At least 1 sample for
+%% each covered fragment is generated.
+%%
+%% A `Value' of 1.0 indicates that each sample in the framebuffer should be indpendently
+%% shaded. A `Value' of 0.0 effectively allows the GL to ignore sample rate shading.
+%% Any value between 0.0 and 1.0 allows the GL to shade only a subset of the total samples
+%% within each covered fragment. Which samples are shaded and the algorithm used to select
+%% that subset of the fragment's samples is implementation dependent.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinSampleShading.xml">external</a> documentation.
+-spec minSampleShading(Value) -> ok when Value :: clamp().
minSampleShading(Value) ->
cast(5586, <<Value:?GLclampf>>).
-%% @spec (Buf::integer(),Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml">external</a> documentation.
--spec blendEquationi(integer(),enum()) -> ok.
+%% @doc
+%% See {@link blendEquation/1}
+-spec blendEquationi(Buf, Mode) -> ok when Buf :: integer(),Mode :: enum().
blendEquationi(Buf,Mode) ->
cast(5587, <<Buf:?GLuint,Mode:?GLenum>>).
-%% @spec (Buf::integer(),ModeRGB::enum(),ModeAlpha::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml">external</a> documentation.
--spec blendEquationSeparatei(integer(),enum(),enum()) -> ok.
+%% @doc
+%% See {@link blendEquationSeparate/2}
+-spec blendEquationSeparatei(Buf, ModeRGB, ModeAlpha) -> ok when Buf :: integer(),ModeRGB :: enum(),ModeAlpha :: enum().
blendEquationSeparatei(Buf,ModeRGB,ModeAlpha) ->
cast(5588, <<Buf:?GLuint,ModeRGB:?GLenum,ModeAlpha:?GLenum>>).
-%% @spec (Buf::integer(),Src::enum(),Dst::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunci.xml">external</a> documentation.
--spec blendFunci(integer(),enum(),enum()) -> ok.
+%% @doc glBlendFunci
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunci.xml">external</a> documentation.
+-spec blendFunci(Buf, Src, Dst) -> ok when Buf :: integer(),Src :: enum(),Dst :: enum().
blendFunci(Buf,Src,Dst) ->
cast(5589, <<Buf:?GLuint,Src:?GLenum,Dst:?GLenum>>).
-%% @spec (Buf::integer(),SrcRGB::enum(),DstRGB::enum(),SrcAlpha::enum(),DstAlpha::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml">external</a> documentation.
--spec blendFuncSeparatei(integer(),enum(),enum(),enum(),enum()) -> ok.
+%% @doc
+%% See {@link blendFuncSeparate/4}
+-spec blendFuncSeparatei(Buf, SrcRGB, DstRGB, SrcAlpha, DstAlpha) -> ok when Buf :: integer(),SrcRGB :: enum(),DstRGB :: enum(),SrcAlpha :: enum(),DstAlpha :: enum().
blendFuncSeparatei(Buf,SrcRGB,DstRGB,SrcAlpha,DstAlpha) ->
cast(5590, <<Buf:?GLuint,SrcRGB:?GLenum,DstRGB:?GLenum,SrcAlpha:?GLenum,DstAlpha:?GLenum>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation.
--spec loadTransposeMatrixfARB({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc glLoadTransposeMatrixARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation.
+-spec loadTransposeMatrixfARB(M) -> ok when M :: matrix().
loadTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5591, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
loadTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5591, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation.
--spec loadTransposeMatrixdARB({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc glLoadTransposeMatrixARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation.
+-spec loadTransposeMatrixdARB(M) -> ok when M :: matrix().
loadTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5592, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
loadTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5592, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation.
--spec multTransposeMatrixfARB({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc glMultTransposeMatrixARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation.
+-spec multTransposeMatrixfARB(M) -> ok when M :: matrix().
multTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5593, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
multTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5593, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,0:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,0:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,0:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,1:?GLfloat>>).
-%% @spec (M::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation.
--spec multTransposeMatrixdARB({float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}) -> ok.
+%% @doc glMultTransposeMatrixARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation.
+-spec multTransposeMatrixdARB(M) -> ok when M :: matrix().
multTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5594, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
multTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
cast(5594, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble>>).
-%% @spec (Weights::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightbvARB([integer()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightbvARB(Weights) -> ok when Weights :: [integer()].
weightbvARB(Weights) ->
cast(5595, <<(length(Weights)):?GLuint,
(<< <<C:?GLbyte>> || C <- Weights>>)/binary,0:((8-((length(Weights)+ 4) rem 8)) rem 8)>>).
-%% @spec (Weights::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightsvARB([integer()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightsvARB(Weights) -> ok when Weights :: [integer()].
weightsvARB(Weights) ->
cast(5596, <<(length(Weights)):?GLuint,
(<< <<C:?GLshort>> || C <- Weights>>)/binary,0:((8-((length(Weights)*2+ 4) rem 8)) rem 8)>>).
-%% @spec (Weights::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightivARB([integer()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightivARB(Weights) -> ok when Weights :: [integer()].
weightivARB(Weights) ->
cast(5597, <<(length(Weights)):?GLuint,
(<< <<C:?GLint>> || C <- Weights>>)/binary,0:(((1+length(Weights)) rem 2)*32)>>).
-%% @spec (Weights::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightfvARB([float()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightfvARB(Weights) -> ok when Weights :: [float()].
weightfvARB(Weights) ->
cast(5598, <<(length(Weights)):?GLuint,
(<< <<C:?GLfloat>> || C <- Weights>>)/binary,0:(((1+length(Weights)) rem 2)*32)>>).
-%% @spec (Weights::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightdvARB([float()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightdvARB(Weights) -> ok when Weights :: [float()].
weightdvARB(Weights) ->
cast(5599, <<(length(Weights)):?GLuint,0:32,
(<< <<C:?GLdouble>> || C <- Weights>>)/binary>>).
-%% @spec (Weights::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightubvARB([integer()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightubvARB(Weights) -> ok when Weights :: [integer()].
weightubvARB(Weights) ->
cast(5600, <<(length(Weights)):?GLuint,
(<< <<C:?GLubyte>> || C <- Weights>>)/binary,0:((8-((length(Weights)+ 4) rem 8)) rem 8)>>).
-%% @spec (Weights::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightusvARB([integer()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightusvARB(Weights) -> ok when Weights :: [integer()].
weightusvARB(Weights) ->
cast(5601, <<(length(Weights)):?GLuint,
(<< <<C:?GLushort>> || C <- Weights>>)/binary,0:((8-((length(Weights)*2+ 4) rem 8)) rem 8)>>).
-%% @spec (Weights::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
--spec weightuivARB([integer()]) -> ok.
+%% @doc glWeightARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+-spec weightuivARB(Weights) -> ok when Weights :: [integer()].
weightuivARB(Weights) ->
cast(5602, <<(length(Weights)):?GLuint,
(<< <<C:?GLuint>> || C <- Weights>>)/binary,0:(((1+length(Weights)) rem 2)*32)>>).
-%% @spec (Count::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexBlenARB.xml">external</a> documentation.
--spec vertexBlendARB(integer()) -> ok.
+%% @doc glVertexBlenARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexBlenARB.xml">external</a> documentation.
+-spec vertexBlendARB(Count) -> ok when Count :: integer().
vertexBlendARB(Count) ->
cast(5603, <<Count:?GLint>>).
-%% @spec (Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCurrentPaletteMatrixARB.xml">external</a> documentation.
--spec currentPaletteMatrixARB(integer()) -> ok.
+%% @doc glCurrentPaletteMatrixARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCurrentPaletteMatrixARB.xml">external</a> documentation.
+-spec currentPaletteMatrixARB(Index) -> ok when Index :: integer().
currentPaletteMatrixARB(Index) ->
cast(5604, <<Index:?GLint>>).
-%% @spec (Indices::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
--spec matrixIndexubvARB([integer()]) -> ok.
+%% @doc glMatrixIndexARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
+-spec matrixIndexubvARB(Indices) -> ok when Indices :: [integer()].
matrixIndexubvARB(Indices) ->
cast(5605, <<(length(Indices)):?GLuint,
(<< <<C:?GLubyte>> || C <- Indices>>)/binary,0:((8-((length(Indices)+ 4) rem 8)) rem 8)>>).
-%% @spec (Indices::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
--spec matrixIndexusvARB([integer()]) -> ok.
+%% @doc glMatrixIndexARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
+-spec matrixIndexusvARB(Indices) -> ok when Indices :: [integer()].
matrixIndexusvARB(Indices) ->
cast(5606, <<(length(Indices)):?GLuint,
(<< <<C:?GLushort>> || C <- Indices>>)/binary,0:((8-((length(Indices)*2+ 4) rem 8)) rem 8)>>).
-%% @spec (Indices::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
--spec matrixIndexuivARB([integer()]) -> ok.
+%% @doc glMatrixIndexARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
+-spec matrixIndexuivARB(Indices) -> ok when Indices :: [integer()].
matrixIndexuivARB(Indices) ->
cast(5607, <<(length(Indices)):?GLuint,
(<< <<C:?GLuint>> || C <- Indices>>)/binary,0:(((1+length(Indices)) rem 2)*32)>>).
-%% @spec (Target::enum(),Format::enum(),String::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramStringARB.xml">external</a> documentation.
--spec programStringARB(enum(),enum(),string()) -> ok.
+%% @doc glProgramStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramStringARB.xml">external</a> documentation.
+-spec programStringARB(Target, Format, String) -> ok when Target :: enum(),Format :: enum(),String :: string().
programStringARB(Target,Format,String) ->
cast(5608, <<Target:?GLenum,Format:?GLenum,(list_to_binary([String|[0]]))/binary,0:((8-((length(String)+ 1) rem 8)) rem 8)>>).
-%% @spec (Target::enum(),Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramARB.xml">external</a> documentation.
--spec bindProgramARB(enum(),integer()) -> ok.
+%% @doc glBindProgramARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramARB.xml">external</a> documentation.
+-spec bindProgramARB(Target, Program) -> ok when Target :: enum(),Program :: integer().
bindProgramARB(Target,Program) ->
cast(5609, <<Target:?GLenum,Program:?GLuint>>).
-%% @spec (Programs::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramsARB.xml">external</a> documentation.
--spec deleteProgramsARB([integer()]) -> ok.
+%% @doc glDeleteProgramsARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramsARB.xml">external</a> documentation.
+-spec deleteProgramsARB(Programs) -> ok when Programs :: [integer()].
deleteProgramsARB(Programs) ->
cast(5610, <<(length(Programs)):?GLuint,
(<< <<C:?GLuint>> || C <- Programs>>)/binary,0:(((1+length(Programs)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramsARB.xml">external</a> documentation.
--spec genProgramsARB(integer()) -> [integer()].
+%% @doc glGenProgramsARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramsARB.xml">external</a> documentation.
+-spec genProgramsARB(N) -> [integer()] when N :: integer().
genProgramsARB(N) ->
call(5611, <<N:?GLsizei>>).
-%% @spec (Target::enum(),Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
--spec programEnvParameter4dARB(enum(),integer(),float(),float(),float(),float()) -> ok.
+%% @doc glProgramEnvParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+-spec programEnvParameter4dARB(Target, Index, X, Y, Z, W) -> ok when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programEnvParameter4dARB(Target,Index,X,Y,Z,W) ->
cast(5612, <<Target:?GLenum,Index:?GLuint,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-%% @spec (Target::enum(),Index::integer(),Params::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
--spec programEnvParameter4dvARB(enum(),integer(),{float(),float(),float(),float()}) -> ok.
+%% @doc glProgramEnvParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+-spec programEnvParameter4dvARB(Target, Index, Params) -> ok when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programEnvParameter4dvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5613, <<Target:?GLenum,Index:?GLuint,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble>>).
-%% @spec (Target::enum(),Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
--spec programEnvParameter4fARB(enum(),integer(),float(),float(),float(),float()) -> ok.
+%% @doc glProgramEnvParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+-spec programEnvParameter4fARB(Target, Index, X, Y, Z, W) -> ok when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programEnvParameter4fARB(Target,Index,X,Y,Z,W) ->
cast(5614, <<Target:?GLenum,Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
-%% @spec (Target::enum(),Index::integer(),Params::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
--spec programEnvParameter4fvARB(enum(),integer(),{float(),float(),float(),float()}) -> ok.
+%% @doc glProgramEnvParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+-spec programEnvParameter4fvARB(Target, Index, Params) -> ok when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programEnvParameter4fvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5615, <<Target:?GLenum,Index:?GLuint,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>).
-%% @spec (Target::enum(),Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
--spec programLocalParameter4dARB(enum(),integer(),float(),float(),float(),float()) -> ok.
+%% @doc glProgramLocalParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+-spec programLocalParameter4dARB(Target, Index, X, Y, Z, W) -> ok when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programLocalParameter4dARB(Target,Index,X,Y,Z,W) ->
cast(5616, <<Target:?GLenum,Index:?GLuint,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-%% @spec (Target::enum(),Index::integer(),Params::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
--spec programLocalParameter4dvARB(enum(),integer(),{float(),float(),float(),float()}) -> ok.
+%% @doc glProgramLocalParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+-spec programLocalParameter4dvARB(Target, Index, Params) -> ok when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programLocalParameter4dvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5617, <<Target:?GLenum,Index:?GLuint,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble>>).
-%% @spec (Target::enum(),Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
--spec programLocalParameter4fARB(enum(),integer(),float(),float(),float(),float()) -> ok.
+%% @doc glProgramLocalParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+-spec programLocalParameter4fARB(Target, Index, X, Y, Z, W) -> ok when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programLocalParameter4fARB(Target,Index,X,Y,Z,W) ->
cast(5618, <<Target:?GLenum,Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
-%% @spec (Target::enum(),Index::integer(),Params::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
--spec programLocalParameter4fvARB(enum(),integer(),{float(),float(),float(),float()}) -> ok.
+%% @doc glProgramLocalParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+-spec programLocalParameter4fvARB(Target, Index, Params) -> ok when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programLocalParameter4fvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5619, <<Target:?GLenum,Index:?GLuint,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>).
-%% @spec (Target::enum(),Index::integer()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation.
--spec getProgramEnvParameterdvARB(enum(),integer()) -> {float(),float(),float(),float()}.
+%% @doc glGetProgramEnvParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation.
+-spec getProgramEnvParameterdvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramEnvParameterdvARB(Target,Index) ->
call(5620, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation.
--spec getProgramEnvParameterfvARB(enum(),integer()) -> {float(),float(),float(),float()}.
+%% @doc glGetProgramEnvParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation.
+-spec getProgramEnvParameterfvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramEnvParameterfvARB(Target,Index) ->
call(5621, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation.
--spec getProgramLocalParameterdvARB(enum(),integer()) -> {float(),float(),float(),float()}.
+%% @doc glGetProgramLocalParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation.
+-spec getProgramLocalParameterdvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramLocalParameterdvARB(Target,Index) ->
call(5622, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation.
--spec getProgramLocalParameterfvARB(enum(),integer()) -> {float(),float(),float(),float()}.
+%% @doc glGetProgramLocalParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation.
+-spec getProgramLocalParameterfvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramLocalParameterfvARB(Target,Index) ->
call(5623, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Pname::enum(),String::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStringARB.xml">external</a> documentation.
--spec getProgramStringARB(enum(),enum(),mem()) -> ok.
+%% @doc glGetProgramStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStringARB.xml">external</a> documentation.
+-spec getProgramStringARB(Target, Pname, String) -> ok when Target :: enum(),Pname :: enum(),String :: mem().
getProgramStringARB(Target,Pname,String) ->
send_bin(String),
call(5624, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum(),Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameterARB.xml">external</a> documentation.
--spec getBufferParameterivARB(enum(),enum()) -> [integer()].
+%% @doc glGetBufferParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameterARB.xml">external</a> documentation.
+-spec getBufferParameterivARB(Target, Pname) -> [integer()] when Target :: enum(),Pname :: enum().
getBufferParameterivARB(Target,Pname) ->
call(5625, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Obj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteObjectARB.xml">external</a> documentation.
--spec deleteObjectARB(integer()) -> ok.
+%% @doc glDeleteObjectARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteObjectARB.xml">external</a> documentation.
+-spec deleteObjectARB(Obj) -> ok when Obj :: integer().
deleteObjectARB(Obj) ->
cast(5626, <<Obj:?GLhandleARB>>).
-%% @spec (Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHandleARB.xml">external</a> documentation.
--spec getHandleARB(enum()) -> integer().
+%% @doc glGetHandleARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHandleARB.xml">external</a> documentation.
+-spec getHandleARB(Pname) -> integer() when Pname :: enum().
getHandleARB(Pname) ->
call(5627, <<Pname:?GLenum>>).
-%% @spec (ContainerObj::integer(),AttachedObj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachObjectARB.xml">external</a> documentation.
--spec detachObjectARB(integer(),integer()) -> ok.
+%% @doc glDetachObjectARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachObjectARB.xml">external</a> documentation.
+-spec detachObjectARB(ContainerObj, AttachedObj) -> ok when ContainerObj :: integer(),AttachedObj :: integer().
detachObjectARB(ContainerObj,AttachedObj) ->
cast(5628, <<ContainerObj:?GLhandleARB,AttachedObj:?GLhandleARB>>).
-%% @spec (ShaderType::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderObjectARB.xml">external</a> documentation.
--spec createShaderObjectARB(enum()) -> integer().
+%% @doc glCreateShaderObjectARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderObjectARB.xml">external</a> documentation.
+-spec createShaderObjectARB(ShaderType) -> integer() when ShaderType :: enum().
createShaderObjectARB(ShaderType) ->
call(5629, <<ShaderType:?GLenum>>).
-%% @spec (ShaderObj::integer(),String::[string()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSourceARB.xml">external</a> documentation.
--spec shaderSourceARB(integer(),[string()]) -> ok.
+%% @doc glShaderSourceARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSourceARB.xml">external</a> documentation.
+-spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: [string()].
shaderSourceARB(ShaderObj,String) ->
StringTemp = list_to_binary([[Str|[0]] || Str <- String ]),
cast(5630, <<ShaderObj:?GLhandleARB,(length(String)):?GLuint,(size(StringTemp)):?GLuint,(StringTemp)/binary,0:((8-((size(StringTemp)+4) rem 8)) rem 8)>>).
-%% @spec (ShaderObj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderARB.xml">external</a> documentation.
--spec compileShaderARB(integer()) -> ok.
+%% @doc glCompileShaderARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderARB.xml">external</a> documentation.
+-spec compileShaderARB(ShaderObj) -> ok when ShaderObj :: integer().
compileShaderARB(ShaderObj) ->
cast(5631, <<ShaderObj:?GLhandleARB>>).
-%% @spec () -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgramObjectARB.xml">external</a> documentation.
+%% @doc glCreateProgramObjectARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgramObjectARB.xml">external</a> documentation.
-spec createProgramObjectARB() -> integer().
createProgramObjectARB() ->
call(5632, <<>>).
-%% @spec (ContainerObj::integer(),Obj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachObjectARB.xml">external</a> documentation.
--spec attachObjectARB(integer(),integer()) -> ok.
+%% @doc glAttachObjectARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachObjectARB.xml">external</a> documentation.
+-spec attachObjectARB(ContainerObj, Obj) -> ok when ContainerObj :: integer(),Obj :: integer().
attachObjectARB(ContainerObj,Obj) ->
cast(5633, <<ContainerObj:?GLhandleARB,Obj:?GLhandleARB>>).
-%% @spec (ProgramObj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgramARB.xml">external</a> documentation.
--spec linkProgramARB(integer()) -> ok.
+%% @doc glLinkProgramARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgramARB.xml">external</a> documentation.
+-spec linkProgramARB(ProgramObj) -> ok when ProgramObj :: integer().
linkProgramARB(ProgramObj) ->
cast(5634, <<ProgramObj:?GLhandleARB>>).
-%% @spec (ProgramObj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramObjectARB.xml">external</a> documentation.
--spec useProgramObjectARB(integer()) -> ok.
+%% @doc glUseProgramObjectARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramObjectARB.xml">external</a> documentation.
+-spec useProgramObjectARB(ProgramObj) -> ok when ProgramObj :: integer().
useProgramObjectARB(ProgramObj) ->
cast(5635, <<ProgramObj:?GLhandleARB>>).
-%% @spec (ProgramObj::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramARB.xml">external</a> documentation.
--spec validateProgramARB(integer()) -> ok.
+%% @doc glValidateProgramARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramARB.xml">external</a> documentation.
+-spec validateProgramARB(ProgramObj) -> ok when ProgramObj :: integer().
validateProgramARB(ProgramObj) ->
cast(5636, <<ProgramObj:?GLhandleARB>>).
-%% @spec (Obj::integer(),Pname::enum()) -> float()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation.
--spec getObjectParameterfvARB(integer(),enum()) -> float().
+%% @doc glGetObjectParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation.
+-spec getObjectParameterfvARB(Obj, Pname) -> float() when Obj :: integer(),Pname :: enum().
getObjectParameterfvARB(Obj,Pname) ->
call(5637, <<Obj:?GLhandleARB,Pname:?GLenum>>).
-%% @spec (Obj::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation.
--spec getObjectParameterivARB(integer(),enum()) -> integer().
+%% @doc glGetObjectParameterARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation.
+-spec getObjectParameterivARB(Obj, Pname) -> integer() when Obj :: integer(),Pname :: enum().
getObjectParameterivARB(Obj,Pname) ->
call(5638, <<Obj:?GLhandleARB,Pname:?GLenum>>).
-%% @spec (Obj::integer(),MaxLength::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInfoLogARB.xml">external</a> documentation.
--spec getInfoLogARB(integer(),integer()) -> string().
+%% @doc glGetInfoLogARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInfoLogARB.xml">external</a> documentation.
+-spec getInfoLogARB(Obj, MaxLength) -> string() when Obj :: integer(),MaxLength :: integer().
getInfoLogARB(Obj,MaxLength) ->
call(5639, <<Obj:?GLhandleARB,MaxLength:?GLsizei>>).
-%% @spec (ContainerObj::integer(),MaxCount::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedObjectsARB.xml">external</a> documentation.
--spec getAttachedObjectsARB(integer(),integer()) -> [integer()].
+%% @doc glGetAttachedObjectsARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedObjectsARB.xml">external</a> documentation.
+-spec getAttachedObjectsARB(ContainerObj, MaxCount) -> [integer()] when ContainerObj :: integer(),MaxCount :: integer().
getAttachedObjectsARB(ContainerObj,MaxCount) ->
call(5640, <<ContainerObj:?GLhandleARB,MaxCount:?GLsizei>>).
-%% @spec (ProgramObj::integer(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocationARB.xml">external</a> documentation.
--spec getUniformLocationARB(integer(),string()) -> integer().
+%% @doc glGetUniformLocationARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocationARB.xml">external</a> documentation.
+-spec getUniformLocationARB(ProgramObj, Name) -> integer() when ProgramObj :: integer(),Name :: string().
getUniformLocationARB(ProgramObj,Name) ->
call(5641, <<ProgramObj:?GLhandleARB,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (ProgramObj::integer(),Index::integer(),MaxLength::integer()) -> {Size::integer(),Type::enum(),Name::string()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformARB.xml">external</a> documentation.
--spec getActiveUniformARB(integer(),integer(),integer()) -> {integer(),enum(),string()}.
+%% @doc glGetActiveUniformARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformARB.xml">external</a> documentation.
+-spec getActiveUniformARB(ProgramObj, Index, MaxLength) -> {Size :: integer(),Type :: enum(),Name :: string()} when ProgramObj :: integer(),Index :: integer(),MaxLength :: integer().
getActiveUniformARB(ProgramObj,Index,MaxLength) ->
call(5642, <<ProgramObj:?GLhandleARB,Index:?GLuint,MaxLength:?GLsizei>>).
-%% @spec (ProgramObj::integer(),Location::integer()) -> {float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation.
--spec getUniformfvARB(integer(),integer()) -> {float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}.
+%% @doc glGetUniformARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation.
+-spec getUniformfvARB(ProgramObj, Location) -> matrix() when ProgramObj :: integer(),Location :: integer().
getUniformfvARB(ProgramObj,Location) ->
call(5643, <<ProgramObj:?GLhandleARB,Location:?GLint>>).
-%% @spec (ProgramObj::integer(),Location::integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation.
--spec getUniformivARB(integer(),integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}.
+%% @doc glGetUniformARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation.
+-spec getUniformivARB(ProgramObj, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when ProgramObj :: integer(),Location :: integer().
getUniformivARB(ProgramObj,Location) ->
call(5644, <<ProgramObj:?GLhandleARB,Location:?GLint>>).
-%% @spec (Obj::integer(),MaxLength::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSourceARB.xml">external</a> documentation.
--spec getShaderSourceARB(integer(),integer()) -> string().
+%% @doc glGetShaderSourceARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSourceARB.xml">external</a> documentation.
+-spec getShaderSourceARB(Obj, MaxLength) -> string() when Obj :: integer(),MaxLength :: integer().
getShaderSourceARB(Obj,MaxLength) ->
call(5645, <<Obj:?GLhandleARB,MaxLength:?GLsizei>>).
-%% @spec (ProgramObj::integer(),Index::integer(),Name::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocationARB.xml">external</a> documentation.
--spec bindAttribLocationARB(integer(),integer(),string()) -> ok.
+%% @doc glBindAttribLocationARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocationARB.xml">external</a> documentation.
+-spec bindAttribLocationARB(ProgramObj, Index, Name) -> ok when ProgramObj :: integer(),Index :: integer(),Name :: string().
bindAttribLocationARB(ProgramObj,Index,Name) ->
cast(5646, <<ProgramObj:?GLhandleARB,Index:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8)>>).
-%% @spec (ProgramObj::integer(),Index::integer(),MaxLength::integer()) -> {Size::integer(),Type::enum(),Name::string()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttribARB.xml">external</a> documentation.
--spec getActiveAttribARB(integer(),integer(),integer()) -> {integer(),enum(),string()}.
+%% @doc glGetActiveAttribARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttribARB.xml">external</a> documentation.
+-spec getActiveAttribARB(ProgramObj, Index, MaxLength) -> {Size :: integer(),Type :: enum(),Name :: string()} when ProgramObj :: integer(),Index :: integer(),MaxLength :: integer().
getActiveAttribARB(ProgramObj,Index,MaxLength) ->
call(5647, <<ProgramObj:?GLhandleARB,Index:?GLuint,MaxLength:?GLsizei>>).
-%% @spec (ProgramObj::integer(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocationARB.xml">external</a> documentation.
--spec getAttribLocationARB(integer(),string()) -> integer().
+%% @doc glGetAttribLocationARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocationARB.xml">external</a> documentation.
+-spec getAttribLocationARB(ProgramObj, Name) -> integer() when ProgramObj :: integer(),Name :: string().
getAttribLocationARB(ProgramObj,Name) ->
call(5648, <<ProgramObj:?GLhandleARB,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Renderbuffer::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsRenderbuffer.xml">external</a> documentation.
--spec isRenderbuffer(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a renderbuffer object
+%%
+%% ``gl:isRenderbuffer'' returns `?GL_TRUE' if `Renderbuffer' is currently the
+%% name of a renderbuffer object. If `Renderbuffer' is zero, or if `Renderbuffer'
+%% is not the name of a renderbuffer object, or if an error occurs, ``gl:isRenderbuffer''
+%% returns `?GL_FALSE'. If `Renderbuffer' is a name returned by {@link gl:genRenderbuffers/1}
+%% , by that has not yet been bound through a call to {@link gl:bindRenderbuffer/2} or {@link gl:framebufferRenderbuffer/4}
+%% , then the name is not a renderbuffer object and ``gl:isRenderbuffer'' returns `?GL_FALSE'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsRenderbuffer.xml">external</a> documentation.
+-spec isRenderbuffer(Renderbuffer) -> 0|1 when Renderbuffer :: integer().
isRenderbuffer(Renderbuffer) ->
call(5649, <<Renderbuffer:?GLuint>>).
-%% @spec (Target::enum(),Renderbuffer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindRenderbuffer.xml">external</a> documentation.
--spec bindRenderbuffer(enum(),integer()) -> ok.
+%% @doc Bind a renderbuffer to a renderbuffer target
+%%
+%% ``gl:bindRenderbuffer'' binds the renderbuffer object with name `Renderbuffer'
+%% to the renderbuffer target specified by `Target' . `Target' must be `?GL_RENDERBUFFER'
+%% . `Renderbuffer' is the name of a renderbuffer object previously returned from a
+%% call to {@link gl:genRenderbuffers/1} , or zero to break the existing binding of a renderbuffer
+%% object to `Target' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindRenderbuffer.xml">external</a> documentation.
+-spec bindRenderbuffer(Target, Renderbuffer) -> ok when Target :: enum(),Renderbuffer :: integer().
bindRenderbuffer(Target,Renderbuffer) ->
cast(5650, <<Target:?GLenum,Renderbuffer:?GLuint>>).
-%% @spec (Renderbuffers::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteRenderbuffers.xml">external</a> documentation.
--spec deleteRenderbuffers([integer()]) -> ok.
+%% @doc Delete renderbuffer objects
+%%
+%% ``gl:deleteRenderbuffers'' deletes the `N' renderbuffer objects whose names are
+%% stored in the array addressed by `Renderbuffers' . The name zero is reserved by the
+%% GL and is silently ignored, should it occur in `Renderbuffers' , as are other unused
+%% names. Once a renderbuffer object is deleted, its name is again unused and it has no contents.
+%% If a renderbuffer that is currently bound to the target `?GL_RENDERBUFFER' is deleted,
+%% it is as though {@link gl:bindRenderbuffer/2} had been executed with a `Target' of `?GL_RENDERBUFFER'
+%% and a `Name' of zero.
+%%
+%% If a renderbuffer object is attached to one or more attachment points in the currently
+%% bound framebuffer, then it as if {@link gl:framebufferRenderbuffer/4} had been called,
+%% with a `Renderbuffer' of zero for each attachment point to which this image was attached
+%% in the currently bound framebuffer. In other words, this renderbuffer object is first
+%% detached from all attachment ponits in the currently bound framebuffer. Note that the
+%% renderbuffer image is specifically `not' detached from any non-bound framebuffers.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteRenderbuffers.xml">external</a> documentation.
+-spec deleteRenderbuffers(Renderbuffers) -> ok when Renderbuffers :: [integer()].
deleteRenderbuffers(Renderbuffers) ->
cast(5651, <<(length(Renderbuffers)):?GLuint,
(<< <<C:?GLuint>> || C <- Renderbuffers>>)/binary,0:(((1+length(Renderbuffers)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenRenderbuffers.xml">external</a> documentation.
--spec genRenderbuffers(integer()) -> [integer()].
+%% @doc Generate renderbuffer object names
+%%
+%% ``gl:genRenderbuffers'' returns `N' renderbuffer object names in `Renderbuffers'
+%% . There is no guarantee that the names form a contiguous set of integers; however, it
+%% is guaranteed that none of the returned names was in use immediately before the call to ``gl:genRenderbuffers''
+%% .
+%%
+%% Renderbuffer object names returned by a call to ``gl:genRenderbuffers'' are not returned
+%% by subsequent calls, unless they are first deleted with {@link gl:deleteRenderbuffers/1} .
+%%
+%% The names returned in `Renderbuffers' are marked as used, for the purposes of ``gl:genRenderbuffers''
+%% only, but they acquire state and type only when they are first bound.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenRenderbuffers.xml">external</a> documentation.
+-spec genRenderbuffers(N) -> [integer()] when N :: integer().
genRenderbuffers(N) ->
call(5652, <<N:?GLsizei>>).
-%% @spec (Target::enum(),Internalformat::enum(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorage.xml">external</a> documentation.
--spec renderbufferStorage(enum(),enum(),integer(),integer()) -> ok.
+%% @doc Establish data storage, format and dimensions of a renderbuffer object's image
+%%
+%% ``gl:renderbufferStorage'' is equivalent to calling {@link gl:renderbufferStorageMultisample/5}
+%% with the `Samples' set to zero.
+%%
+%% The target of the operation, specified by `Target' must be `?GL_RENDERBUFFER'.
+%% `Internalformat' specifies the internal format to be used for the renderbuffer object's
+%% storage and must be a color-renderable, depth-renderable, or stencil-renderable format. `Width'
+%% and `Height' are the dimensions, in pixels, of the renderbuffer. Both `Width'
+%% and `Height' must be less than or equal to the value of `?GL_MAX_RENDERBUFFER_SIZE'
+%% .
+%%
+%% Upon success, ``gl:renderbufferStorage'' deletes any existing data store for the renderbuffer
+%% image and the contents of the data store after calling ``gl:renderbufferStorage'' are
+%% undefined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorage.xml">external</a> documentation.
+-spec renderbufferStorage(Target, Internalformat, Width, Height) -> ok when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer().
renderbufferStorage(Target,Internalformat,Width,Height) ->
cast(5653, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (Target::enum(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetRenderbufferParameter.xml">external</a> documentation.
--spec getRenderbufferParameteriv(enum(),enum()) -> integer().
+%% @doc Retrieve information about a bound renderbuffer object
+%%
+%% ``gl:getRenderbufferParameteriv'' retrieves information about a bound renderbuffer object.
+%% `Target' specifies the target of the query operation and must be `?GL_RENDERBUFFER'
+%% . `Pname' specifies the parameter whose value to query and must be one of `?GL_RENDERBUFFER_WIDTH'
+%% , `?GL_RENDERBUFFER_HEIGHT', `?GL_RENDERBUFFER_INTERNAL_FORMAT', `?GL_RENDERBUFFER_RED_SIZE'
+%% , `?GL_RENDERBUFFER_GREEN_SIZE', `?GL_RENDERBUFFER_BLUE_SIZE', `?GL_RENDERBUFFER_ALPHA_SIZE'
+%% , `?GL_RENDERBUFFER_DEPTH_SIZE', `?GL_RENDERBUFFER_DEPTH_SIZE', `?GL_RENDERBUFFER_STENCIL_SIZE'
+%% , or `?GL_RENDERBUFFER_SAMPLES'.
+%%
+%% Upon a successful return from ``gl:getRenderbufferParameteriv'', if `Pname' is `?GL_RENDERBUFFER_WIDTH'
+%% , `?GL_RENDERBUFFER_HEIGHT', `?GL_RENDERBUFFER_INTERNAL_FORMAT', or `?GL_RENDERBUFFER_SAMPLES'
+%% , then `Params' will contain the width in pixels, the height in pixels, the internal
+%% format, or the number of samples, respectively, of the image of the renderbuffer currently
+%% bound to `Target' .
+%%
+%% If `Pname' is `?GL_RENDERBUFFER_RED_SIZE', `?GL_RENDERBUFFER_GREEN_SIZE',
+%% `?GL_RENDERBUFFER_BLUE_SIZE', `?GL_RENDERBUFFER_ALPHA_SIZE', `?GL_RENDERBUFFER_DEPTH_SIZE'
+%% , or `?GL_RENDERBUFFER_STENCIL_SIZE', then `Params' will contain the actual
+%% resolutions (not the resolutions specified when the image array was defined) for the red,
+%% green, blue, alpha depth, or stencil components, respectively, of the image of the renderbuffer
+%% currently bound to `Target' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetRenderbufferParameter.xml">external</a> documentation.
+-spec getRenderbufferParameteriv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum().
getRenderbufferParameteriv(Target,Pname) ->
call(5654, <<Target:?GLenum,Pname:?GLenum>>).
-%% @spec (Framebuffer::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsFramebuffer.xml">external</a> documentation.
--spec isFramebuffer(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a framebuffer object
+%%
+%% ``gl:isFramebuffer'' returns `?GL_TRUE' if `Framebuffer' is currently the
+%% name of a framebuffer object. If `Framebuffer' is zero, or if `?framebuffer'
+%% is not the name of a framebuffer object, or if an error occurs, ``gl:isFramebuffer''
+%% returns `?GL_FALSE'. If `Framebuffer' is a name returned by {@link gl:genFramebuffers/1}
+%% , by that has not yet been bound through a call to {@link gl:bindFramebuffer/2} , then the
+%% name is not a framebuffer object and ``gl:isFramebuffer'' returns `?GL_FALSE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsFramebuffer.xml">external</a> documentation.
+-spec isFramebuffer(Framebuffer) -> 0|1 when Framebuffer :: integer().
isFramebuffer(Framebuffer) ->
call(5655, <<Framebuffer:?GLuint>>).
-%% @spec (Target::enum(),Framebuffer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFramebuffer.xml">external</a> documentation.
--spec bindFramebuffer(enum(),integer()) -> ok.
+%% @doc Bind a framebuffer to a framebuffer target
+%%
+%% ``gl:bindFramebuffer'' binds the framebuffer object with name `Framebuffer' to
+%% the framebuffer target specified by `Target' . `Target' must be either `?GL_DRAW_FRAMEBUFFER'
+%% , `?GL_READ_FRAMEBUFFER' or `?GL_FRAMEBUFFER'. If a framebuffer object is bound
+%% to `?GL_DRAW_FRAMEBUFFER' or `?GL_READ_FRAMEBUFFER', it becomes the target for
+%% rendering or readback operations, respectively, until it is deleted or another framebuffer
+%% is bound to the corresponding bind point. Calling ``gl:bindFramebuffer'' with `Target'
+%% set to `?GL_FRAMEBUFFER' binds `Framebuffer' to both the read and draw framebuffer
+%% targets. `Framebuffer' is the name of a framebuffer object previously returned from
+%% a call to {@link gl:genFramebuffers/1} , or zero to break the existing binding of a framebuffer
+%% object to `Target' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFramebuffer.xml">external</a> documentation.
+-spec bindFramebuffer(Target, Framebuffer) -> ok when Target :: enum(),Framebuffer :: integer().
bindFramebuffer(Target,Framebuffer) ->
cast(5656, <<Target:?GLenum,Framebuffer:?GLuint>>).
-%% @spec (Framebuffers::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteFramebuffers.xml">external</a> documentation.
--spec deleteFramebuffers([integer()]) -> ok.
+%% @doc Delete framebuffer objects
+%%
+%% ``gl:deleteFramebuffers'' deletes the `N' framebuffer objects whose names are stored
+%% in the array addressed by `Framebuffers' . The name zero is reserved by the GL and
+%% is silently ignored, should it occur in `Framebuffers' , as are other unused names.
+%% Once a framebuffer object is deleted, its name is again unused and it has no attachments.
+%% If a framebuffer that is currently bound to one or more of the targets `?GL_DRAW_FRAMEBUFFER'
+%% or `?GL_READ_FRAMEBUFFER' is deleted, it is as though {@link gl:bindFramebuffer/2}
+%% had been executed with the corresponding `Target' and `Framebuffer' zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteFramebuffers.xml">external</a> documentation.
+-spec deleteFramebuffers(Framebuffers) -> ok when Framebuffers :: [integer()].
deleteFramebuffers(Framebuffers) ->
cast(5657, <<(length(Framebuffers)):?GLuint,
(<< <<C:?GLuint>> || C <- Framebuffers>>)/binary,0:(((1+length(Framebuffers)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenFramebuffers.xml">external</a> documentation.
--spec genFramebuffers(integer()) -> [integer()].
+%% @doc Generate framebuffer object names
+%%
+%% ``gl:genFramebuffers'' returns `N' framebuffer object names in `Ids' . There
+%% is no guarantee that the names form a contiguous set of integers; however, it is guaranteed
+%% that none of the returned names was in use immediately before the call to ``gl:genFramebuffers''
+%% .
+%%
+%% Framebuffer object names returned by a call to ``gl:genFramebuffers'' are not returned
+%% by subsequent calls, unless they are first deleted with {@link gl:deleteFramebuffers/1} .
+%%
+%% The names returned in `Ids' are marked as used, for the purposes of ``gl:genFramebuffers''
+%% only, but they acquire state and type only when they are first bound.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenFramebuffers.xml">external</a> documentation.
+-spec genFramebuffers(N) -> [integer()] when N :: integer().
genFramebuffers(N) ->
call(5658, <<N:?GLsizei>>).
-%% @spec (Target::enum()) -> enum()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml">external</a> documentation.
--spec checkFramebufferStatus(enum()) -> enum().
+%% @doc Check the completeness status of a framebuffer
+%%
+%% ``gl:checkFramebufferStatus'' queries the completeness status of the framebuffer object
+%% currently bound to `Target' . `Target' must be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER'
+%% or `?GL_FRAMEBUFFER'. `?GL_FRAMEBUFFER' is equivalent to `?GL_DRAW_FRAMEBUFFER'
+%% .
+%%
+%% The return value is `?GL_FRAMEBUFFER_COMPLETE' if the framebuffer bound to `Target'
+%% is complete. Otherwise, the return value is determined as follows:
+%%
+%% `?GL_FRAMEBUFFER_UNDEFINED' is returned if `Target' is the default framebuffer,
+%% but the default framebuffer does not exist.
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT' is returned if any of the framebuffer attachment
+%% points are framebuffer incomplete.
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT' is returned if the framebuffer does
+%% not have at least one image attached to it.
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER' is returned if the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE'
+%% is `?GL_NONE' for any color attachment point(s) named by `?GL_DRAWBUFFERi'.
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER' is returned if `?GL_READ_BUFFER' is
+%% not `?GL_NONE' and the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_NONE'
+%% for the color attachment point named by `?GL_READ_BUFFER'.
+%%
+%% `?GL_FRAMEBUFFER_UNSUPPORTED' is returned if the combination of internal formats
+%% of the attached images violates an implementation-dependent set of restrictions.
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE' is returned if the value of `?GL_RENDERBUFFER_SAMPLES'
+%% is not the same for all attached renderbuffers; if the value of `?GL_TEXTURE_SAMPLES'
+%% is the not same for all attached textures; or, if the attached images are a mix of renderbuffers
+%% and textures, the value of `?GL_RENDERBUFFER_SAMPLES' does not match the value of `?GL_TEXTURE_SAMPLES'
+%% .
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE' is also returned if the value of `?GL_TEXTURE_FIXED_SAMPLE_LOCATIONS'
+%% is not the same for all attached textures; or, if the attached images are a mix of renderbuffers
+%% and textures, the value of `?GL_TEXTURE_FIXED_SAMPLE_LOCATIONS' is not `?GL_TRUE'
+%% for all attached textures.
+%%
+%% `?GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS' is returned if any framebuffer attachment
+%% is layered, and any populated attachment is not layered, or if all populated color attachments
+%% are not from textures of the same target.
+%%
+%% Additionally, if an error occurs, zero is returned.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml">external</a> documentation.
+-spec checkFramebufferStatus(Target) -> enum() when Target :: enum().
checkFramebufferStatus(Target) ->
call(5659, <<Target:?GLenum>>).
-%% @spec (Target::enum(),Attachment::enum(),Textarget::enum(),Texture::integer(),Level::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture1D.xml">external</a> documentation.
--spec framebufferTexture1D(enum(),enum(),enum(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link framebufferTexture/4}
+-spec framebufferTexture1D(Target, Attachment, Textarget, Texture, Level) -> ok when Target :: enum(),Attachment :: enum(),Textarget :: enum(),Texture :: integer(),Level :: integer().
framebufferTexture1D(Target,Attachment,Textarget,Texture,Level) ->
cast(5660, <<Target:?GLenum,Attachment:?GLenum,Textarget:?GLenum,Texture:?GLuint,Level:?GLint>>).
-%% @spec (Target::enum(),Attachment::enum(),Textarget::enum(),Texture::integer(),Level::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture2D.xml">external</a> documentation.
--spec framebufferTexture2D(enum(),enum(),enum(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link framebufferTexture/4}
+-spec framebufferTexture2D(Target, Attachment, Textarget, Texture, Level) -> ok when Target :: enum(),Attachment :: enum(),Textarget :: enum(),Texture :: integer(),Level :: integer().
framebufferTexture2D(Target,Attachment,Textarget,Texture,Level) ->
cast(5661, <<Target:?GLenum,Attachment:?GLenum,Textarget:?GLenum,Texture:?GLuint,Level:?GLint>>).
-%% @spec (Target::enum(),Attachment::enum(),Textarget::enum(),Texture::integer(),Level::integer(),Zoffset::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture3D.xml">external</a> documentation.
--spec framebufferTexture3D(enum(),enum(),enum(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link framebufferTexture/4}
+-spec framebufferTexture3D(Target, Attachment, Textarget, Texture, Level, Zoffset) -> ok when Target :: enum(),Attachment :: enum(),Textarget :: enum(),Texture :: integer(),Level :: integer(),Zoffset :: integer().
framebufferTexture3D(Target,Attachment,Textarget,Texture,Level,Zoffset) ->
cast(5662, <<Target:?GLenum,Attachment:?GLenum,Textarget:?GLenum,Texture:?GLuint,Level:?GLint,Zoffset:?GLint>>).
-%% @spec (Target::enum(),Attachment::enum(),Renderbuffertarget::enum(),Renderbuffer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferRenderbuffer.xml">external</a> documentation.
--spec framebufferRenderbuffer(enum(),enum(),enum(),integer()) -> ok.
+%% @doc Attach a renderbuffer as a logical buffer to the currently bound framebuffer object
+%%
+%% ``gl:framebufferRenderbuffer'' attaches a renderbuffer as one of the logical buffers
+%% of the currently bound framebuffer object. `Renderbuffer' is the name of the renderbuffer
+%% object to attach and must be either zero, or the name of an existing renderbuffer object
+%% of type `Renderbuffertarget' . If `Renderbuffer' is not zero and if ``gl:framebufferRenderbuffer''
+%% is successful, then the renderbuffer name `Renderbuffer' will be used as the logical
+%% buffer identified by `Attachment' of the framebuffer currently bound to `Target' .
+%%
+%%
+%% The value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' for the specified attachment
+%% point is set to `?GL_RENDERBUFFER' and the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME'
+%% is set to `Renderbuffer' . All other state values of the attachment point specified
+%% by `Attachment' are set to their default values. No change is made to the state of
+%% the renderbuuffer object and any previous attachment to the `Attachment' logical
+%% buffer of the framebuffer `Target' is broken.
+%%
+%% Calling ``gl:framebufferRenderbuffer'' with the renderbuffer name zero will detach
+%% the image, if any, identified by `Attachment' , in the framebuffer currently bound
+%% to `Target' . All state values of the attachment point specified by attachment in
+%% the object bound to target are set to their default values.
+%%
+%% Setting `Attachment' to the value `?GL_DEPTH_STENCIL_ATTACHMENT' is a special
+%% case causing both the depth and stencil attachments of the framebuffer object to be set
+%% to `Renderbuffer' , which should have the base internal format `?GL_DEPTH_STENCIL'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferRenderbuffer.xml">external</a> documentation.
+-spec framebufferRenderbuffer(Target, Attachment, Renderbuffertarget, Renderbuffer) -> ok when Target :: enum(),Attachment :: enum(),Renderbuffertarget :: enum(),Renderbuffer :: integer().
framebufferRenderbuffer(Target,Attachment,Renderbuffertarget,Renderbuffer) ->
cast(5663, <<Target:?GLenum,Attachment:?GLenum,Renderbuffertarget:?GLenum,Renderbuffer:?GLuint>>).
-%% @spec (Target::enum(),Attachment::enum(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFramebufferAttachmentParameter.xml">external</a> documentation.
--spec getFramebufferAttachmentParameteriv(enum(),enum(),enum()) -> integer().
+%% @doc Retrieve information about attachments of a bound framebuffer object
+%%
+%% ``gl:getFramebufferAttachmentParameter'' returns information about attachments of a
+%% bound framebuffer object. `Target' specifies the framebuffer binding point and must
+%% be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER' or `?GL_FRAMEBUFFER'. `?GL_FRAMEBUFFER'
+%% is equivalent to `?GL_DRAW_FRAMEBUFFER'.
+%%
+%% If the default framebuffer is bound to `Target' then `Attachment' must be one
+%% of `?GL_FRONT_LEFT', `?GL_FRONT_RIGHT', `?GL_BACK_LEFT', or `?GL_BACK_RIGHT'
+%% , identifying a color buffer, `?GL_DEPTH', identifying the depth buffer, or `?GL_STENCIL'
+%% , identifying the stencil buffer.
+%%
+%% If a framebuffer object is bound, then `Attachment' must be one of `?GL_COLOR_ATTACHMENT'
+%% `i', `?GL_DEPTH_ATTACHMENT', `?GL_STENCIL_ATTACHMENT', or `?GL_DEPTH_STENCIL_ATTACHMENT'
+%% . `i' in `?GL_COLOR_ATTACHMENT'`i' must be in the range zero to the value
+%% of `?GL_MAX_COLOR_ATTACHMENTS' - 1.
+%%
+%% If `Attachment' is `?GL_DEPTH_STENCIL_ATTACHMENT' and different objects are
+%% bound to the depth and stencil attachment points of `Target' the query will fail.
+%% If the same object is bound to both attachment points, information about that object will
+%% be returned.
+%%
+%% Upon successful return from ``gl:getFramebufferAttachmentParameteriv'', if `Pname'
+%% is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', then `Params' will contain one of `?GL_NONE'
+%% , `?GL_FRAMEBUFFER_DEFAULT', `?GL_TEXTURE', or `?GL_RENDERBUFFER', identifying
+%% the type of object which contains the attached image. Other values accepted for `Pname'
+%% depend on the type of object, as described below.
+%%
+%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_NONE', no
+%% framebuffer is bound to `Target' . In this case querying `Pname' `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME'
+%% will return zero, and all other queries will generate an error.
+%%
+%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is not `?GL_NONE',
+%% these queries apply to all other framebuffer types:
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE', `?GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE'
+%% , `?GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE', `?GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE'
+%% , `?GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE', or `?GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE'
+%% , then `Params' will contain the number of bits in the corresponding red, green,
+%% blue, alpha, depth, or stencil component of the specified attachment. Zero is returned
+%% if the requested component is not present in `Attachment' .
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE', `Params' will
+%% contain the format of components of the specified attachment, one of `?GL_FLOAT', `GL_INT'
+%% , `GL_UNSIGNED_INT' , `GL_SIGNED_NORMALIZED' , or `GL_UNSIGNED_NORMALIZED'
+%% for floating-point, signed integer, unsigned integer, signed normalized fixed-point, or
+%% unsigned normalized fixed-point components respectively. Only color buffers may have integer
+%% components.
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING', `Param' will
+%% contain the encoding of components of the specified attachment, one of `?GL_LINEAR'
+%% or `?GL_SRGB' for linear or sRGB-encoded components, respectively. Only color buffer
+%% components may be sRGB-encoded; such components are treated as described in sections 4.1.7
+%% and 4.1.8. For the default framebuffer, color encoding is determined by the implementation.
+%% For framebuffer objects, components are sRGB-encoded if the internal format of a color
+%% attachment is one of the color-renderable SRGB formats.
+%%
+%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_RENDERBUFFER',
+%% then:
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', `Params' will
+%% contain the name of the renderbuffer object which contains the attached image.
+%%
+%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_TEXTURE',
+%% then:
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', then `Params'
+%% will contain the name of the texture object which contains the attached image.
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', then `Params'
+%% will contain the mipmap level of the texture object which contains the attached image.
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE' and the texture
+%% object named `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' is a cube map texture, then `Params'
+%% will contain the cube map face of the cubemap texture object which contains the attached
+%% image. Otherwise `Params' will contain the value zero.
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER' and the texture object
+%% named `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' is a layer of a three-dimensional
+%% texture or a one-or two-dimensional array texture, then `Params' will contain the
+%% number of the texture layer which contains the attached image. Otherwise `Params'
+%% will contain the value zero.
+%%
+%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_LAYERED', then `Params' will
+%% contain `?GL_TRUE' if an entire level of a three-dimesional texture, cube map texture,
+%% or one-or two-dimensional array texture is attached. Otherwise, `Params' will contain
+%% `?GL_FALSE'.
+%%
+%% Any combinations of framebuffer type and `Pname' not described above will generate
+%% an error.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFramebufferAttachmentParameter.xml">external</a> documentation.
+-spec getFramebufferAttachmentParameteriv(Target, Attachment, Pname) -> integer() when Target :: enum(),Attachment :: enum(),Pname :: enum().
getFramebufferAttachmentParameteriv(Target,Attachment,Pname) ->
call(5664, <<Target:?GLenum,Attachment:?GLenum,Pname:?GLenum>>).
-%% @spec (Target::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenerateMipmap.xml">external</a> documentation.
--spec generateMipmap(enum()) -> ok.
+%% @doc Generate mipmaps for a specified texture target
+%%
+%% ``gl:generateMipmap'' generates mipmaps for the texture attached to `Target' of
+%% the active texture unit. For cube map textures, a `?GL_INVALID_OPERATION' error is
+%% generated if the texture attached to `Target' is not cube complete.
+%%
+%% Mipmap generation replaces texel array levels level base+1 through q with arrays derived
+%% from the level base array, regardless of their previous contents. All other mimap arrays,
+%% including the level base array, are left unchanged by this computation.
+%%
+%% The internal formats of the derived mipmap arrays all match those of the level base
+%% array. The contents of the derived arrays are computed by repeated, filtered reduction
+%% of the level base array. For one- and two-dimensional texture arrays, each layer is filtered
+%% independently.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenerateMipmap.xml">external</a> documentation.
+-spec generateMipmap(Target) -> ok when Target :: enum().
generateMipmap(Target) ->
cast(5665, <<Target:?GLenum>>).
-%% @spec (SrcX0::integer(),SrcY0::integer(),SrcX1::integer(),SrcY1::integer(),DstX0::integer(),DstY0::integer(),DstX1::integer(),DstY1::integer(),Mask::integer(),Filter::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlitFramebuffer.xml">external</a> documentation.
--spec blitFramebuffer(integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),enum()) -> ok.
+%% @doc Copy a block of pixels from the read framebuffer to the draw framebuffer
+%%
+%% ``gl:blitFramebuffer'' transfers a rectangle of pixel values from one region of the
+%% read framebuffer to another region in the draw framebuffer. `Mask' is the bitwise
+%% OR of a number of values indicating which buffers are to be copied. The values are `?GL_COLOR_BUFFER_BIT'
+%% , `?GL_DEPTH_BUFFER_BIT', and `?GL_STENCIL_BUFFER_BIT'. The pixels corresponding
+%% to these buffers are copied from the source rectangle bounded by the locations ( `SrcX0'
+%% ; `SrcY0' ) and ( `SrcX1' ; `SrcY1' ) to the destination rectangle bounded
+%% by the locations ( `DstX0' ; `DstY0' ) and ( `DstX1' ; `DstY1' ). The lower
+%% bounds of the rectangle are inclusive, while the upper bounds are exclusive.
+%%
+%% The actual region taken from the read framebuffer is limited to the intersection of the
+%% source buffers being transferred, which may include the color buffer selected by the read
+%% buffer, the depth buffer, and/or the stencil buffer depending on mask. The actual region
+%% written to the draw framebuffer is limited to the intersection of the destination buffers
+%% being written, which may include multiple draw buffers, the depth buffer, and/or the stencil
+%% buffer depending on mask. Whether or not the source or destination regions are altered
+%% due to these limits, the scaling and offset applied to pixels being transferred is performed
+%% as though no such limits were present.
+%%
+%% If the sizes of the source and destination rectangles are not equal, `Filter' specifies
+%% the interpolation method that will be applied to resize the source image , and must be `?GL_NEAREST'
+%% or `?GL_LINEAR'. `?GL_LINEAR' is only a valid interpolation method for the
+%% color buffer. If `Filter' is not `?GL_NEAREST' and `Mask' includes `?GL_DEPTH_BUFFER_BIT'
+%% or `?GL_STENCIL_BUFFER_BIT', no data is transferred and a `?GL_INVALID_OPERATION'
+%% error is generated.
+%%
+%% If `Filter' is `?GL_LINEAR' and the source rectangle would require sampling
+%% outside the bounds of the source framebuffer, values are read as if the `?GL_CLAMP_TO_EDGE'
+%% texture wrapping mode were applied.
+%%
+%% When the color buffer is transferred, values are taken from the read buffer of the read
+%% framebuffer and written to each of the draw buffers of the draw framebuffer.
+%%
+%% If the source and destination rectangles overlap or are the same, and the read and draw
+%% buffers are the same, the result of the operation is undefined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlitFramebuffer.xml">external</a> documentation.
+-spec blitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter) -> ok when SrcX0 :: integer(),SrcY0 :: integer(),SrcX1 :: integer(),SrcY1 :: integer(),DstX0 :: integer(),DstY0 :: integer(),DstX1 :: integer(),DstY1 :: integer(),Mask :: integer(),Filter :: enum().
blitFramebuffer(SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1,Mask,Filter) ->
cast(5666, <<SrcX0:?GLint,SrcY0:?GLint,SrcX1:?GLint,SrcY1:?GLint,DstX0:?GLint,DstY0:?GLint,DstX1:?GLint,DstY1:?GLint,Mask:?GLbitfield,Filter:?GLenum>>).
-%% @spec (Target::enum(),Samples::integer(),Internalformat::enum(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorageMultisample.xml">external</a> documentation.
--spec renderbufferStorageMultisample(enum(),integer(),enum(),integer(),integer()) -> ok.
+%% @doc Establish data storage, format, dimensions and sample count of a renderbuffer object's image
+%%
+%% ``gl:renderbufferStorageMultisample'' establishes the data storage, format, dimensions
+%% and number of samples of a renderbuffer object's image.
+%%
+%% The target of the operation, specified by `Target' must be `?GL_RENDERBUFFER'.
+%% `Internalformat' specifies the internal format to be used for the renderbuffer object's
+%% storage and must be a color-renderable, depth-renderable, or stencil-renderable format. `Width'
+%% and `Height' are the dimensions, in pixels, of the renderbuffer. Both `Width'
+%% and `Height' must be less than or equal to the value of `?GL_MAX_RENDERBUFFER_SIZE'
+%% . `Samples' specifies the number of samples to be used for the renderbuffer object's
+%% image, and must be less than or equal to the value of `?GL_MAX_SAMPLES'. If `Internalformat'
+%% is a signed or unsigned integer format then `Samples' must be less than or equal
+%% to the value of `?GL_MAX_INTEGER_SAMPLES'.
+%%
+%% Upon success, ``gl:renderbufferStorageMultisample'' deletes any existing data store
+%% for the renderbuffer image and the contents of the data store after calling ``gl:renderbufferStorageMultisample''
+%% are undefined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorageMultisample.xml">external</a> documentation.
+-spec renderbufferStorageMultisample(Target, Samples, Internalformat, Width, Height) -> ok when Target :: enum(),Samples :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer().
renderbufferStorageMultisample(Target,Samples,Internalformat,Width,Height) ->
cast(5667, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (Target::enum(),Attachment::enum(),Texture::integer(),Level::integer(),Layer::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTextureLayer.xml">external</a> documentation.
--spec framebufferTextureLayer(enum(),enum(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link framebufferTexture/4}
+-spec framebufferTextureLayer(Target, Attachment, Texture, Level, Layer) -> ok when Target :: enum(),Attachment :: enum(),Texture :: integer(),Level :: integer(),Layer :: integer().
framebufferTextureLayer(Target,Attachment,Texture,Level,Layer) ->
cast(5668, <<Target:?GLenum,Attachment:?GLenum,Texture:?GLuint,Level:?GLint,Layer:?GLint>>).
-%% @spec (Target::enum(),Attachment::enum(),Texture::integer(),Level::integer(),Face::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTextureFaceARB.xml">external</a> documentation.
--spec framebufferTextureFaceARB(enum(),enum(),integer(),integer(),enum()) -> ok.
+%% @doc
+%% See {@link framebufferTexture/4}
+-spec framebufferTextureFaceARB(Target, Attachment, Texture, Level, Face) -> ok when Target :: enum(),Attachment :: enum(),Texture :: integer(),Level :: integer(),Face :: enum().
framebufferTextureFaceARB(Target,Attachment,Texture,Level,Face) ->
cast(5669, <<Target:?GLenum,Attachment:?GLenum,Texture:?GLuint,Level:?GLint,Face:?GLenum>>).
-%% @spec (Target::enum(),Offset::integer(),Length::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlushMappedBufferRange.xml">external</a> documentation.
--spec flushMappedBufferRange(enum(),integer(),integer()) -> ok.
+%% @doc Indicate modifications to a range of a mapped buffer
+%%
+%% ``gl:flushMappedBufferRange'' indicates that modifications have been made to a range
+%% of a mapped buffer. The buffer must previously have been mapped with the `?GL_MAP_FLUSH_EXPLICIT'
+%% flag. `Offset' and `Length' indicate the modified subrange of the mapping,
+%% in basic units. The specified subrange to flush is relative to the start of the currently
+%% mapped range of the buffer. ``gl:flushMappedBufferRange'' may be called multiple times
+%% to indicate distinct subranges of the mapping which require flushing.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlushMappedBufferRange.xml">external</a> documentation.
+-spec flushMappedBufferRange(Target, Offset, Length) -> ok when Target :: enum(),Offset :: integer(),Length :: integer().
flushMappedBufferRange(Target,Offset,Length) ->
cast(5670, <<Target:?GLenum,0:32,Offset:?GLintptr,Length:?GLsizeiptr>>).
-%% @spec (Array::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindVertexArray.xml">external</a> documentation.
--spec bindVertexArray(integer()) -> ok.
+%% @doc Bind a vertex array object
+%%
+%% ``gl:bindVertexArray'' binds the vertex array object with name `Array' . `Array'
+%% is the name of a vertex array object previously returned from a call to {@link gl:genVertexArrays/1}
+%% , or zero to break the existing vertex array object binding.
+%%
+%% If no vertex array object with name `Array' exists, one is created when `Array'
+%% is first bound. If the bind is successful no change is made to the state of the vertex
+%% array object, and any previous vertex array object binding is broken.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindVertexArray.xml">external</a> documentation.
+-spec bindVertexArray(Array) -> ok when Array :: integer().
bindVertexArray(Array) ->
cast(5671, <<Array:?GLuint>>).
-%% @spec (Arrays::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteVertexArrays.xml">external</a> documentation.
--spec deleteVertexArrays([integer()]) -> ok.
+%% @doc Delete vertex array objects
+%%
+%% ``gl:deleteVertexArrays'' deletes `N' vertex array objects whose names are stored
+%% in the array addressed by `Arrays' . Once a vertex array object is deleted it has
+%% no contents and its name is again unused. If a vertex array object that is currently bound
+%% is deleted, the binding for that object reverts to zero and the default vertex array becomes
+%% current. Unused names in `Arrays' are silently ignored, as is the value zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteVertexArrays.xml">external</a> documentation.
+-spec deleteVertexArrays(Arrays) -> ok when Arrays :: [integer()].
deleteVertexArrays(Arrays) ->
cast(5672, <<(length(Arrays)):?GLuint,
(<< <<C:?GLuint>> || C <- Arrays>>)/binary,0:(((1+length(Arrays)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenVertexArrays.xml">external</a> documentation.
--spec genVertexArrays(integer()) -> [integer()].
+%% @doc Generate vertex array object names
+%%
+%% ``gl:genVertexArrays'' returns `N' vertex array object names in `Arrays' .
+%% There is no guarantee that the names form a contiguous set of integers; however, it is
+%% guaranteed that none of the returned names was in use immediately before the call to ``gl:genVertexArrays''
+%% .
+%%
+%% Vertex array object names returned by a call to ``gl:genVertexArrays'' are not returned
+%% by subsequent calls, unless they are first deleted with {@link gl:deleteVertexArrays/1} .
+%%
+%% The names returned in `Arrays' are marked as used, for the purposes of ``gl:genVertexArrays''
+%% only, but they acquire state and type only when they are first bound.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenVertexArrays.xml">external</a> documentation.
+-spec genVertexArrays(N) -> [integer()] when N :: integer().
genVertexArrays(N) ->
call(5673, <<N:?GLsizei>>).
-%% @spec (Array::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsVertexArray.xml">external</a> documentation.
--spec isVertexArray(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a vertex array object
+%%
+%% ``gl:isVertexArray'' returns `?GL_TRUE' if `Array' is currently the name of
+%% a renderbuffer object. If `Renderbuffer' is zero, or if `Array' is not the name
+%% of a renderbuffer object, or if an error occurs, ``gl:isVertexArray'' returns `?GL_FALSE'
+%% . If `Array' is a name returned by {@link gl:genVertexArrays/1} , by that has not yet
+%% been bound through a call to {@link gl:bindVertexArray/1} , then the name is not a vertex
+%% array object and ``gl:isVertexArray'' returns `?GL_FALSE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsVertexArray.xml">external</a> documentation.
+-spec isVertexArray(Array) -> 0|1 when Array :: integer().
isVertexArray(Array) ->
call(5674, <<Array:?GLuint>>).
-%% @spec (Program::integer(),UniformNames::[string()]) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformIndices.xml">external</a> documentation.
--spec getUniformIndices(integer(),[string()]) -> [integer()].
+%% @doc Retrieve the index of a named uniform block
+%%
+%% ``gl:getUniformIndices'' retrieves the indices of a number of uniforms within `Program'
+%% .
+%%
+%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
+%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
+%% must have succeeded. The link could have failed because the number of active uniforms
+%% exceeded the limit.
+%%
+%% `UniformCount' indicates both the number of elements in the array of names `UniformNames'
+%% and the number of indices that may be written to `UniformIndices' .
+%%
+%% `UniformNames' contains a list of `UniformCount' name strings identifying the
+%% uniform names to be queried for indices. For each name string in `UniformNames' ,
+%% the index assigned to the active uniform of that name will be written to the corresponding
+%% element of `UniformIndices' . If a string in `UniformNames' is not the name of
+%% an active uniform, the special value `?GL_INVALID_INDEX' will be written to the corresponding
+%% element of `UniformIndices' .
+%%
+%% If an error occurs, nothing is written to `UniformIndices' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformIndices.xml">external</a> documentation.
+-spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: [string()].
getUniformIndices(Program,UniformNames) ->
UniformNamesTemp = list_to_binary([[Str|[0]] || Str <- UniformNames ]),
call(5675, <<Program:?GLuint,(length(UniformNames)):?GLuint,(size(UniformNamesTemp)):?GLuint,(UniformNamesTemp)/binary,0:((8-((size(UniformNamesTemp)+0) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),UniformIndices::[integer()],Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniforms.xml">external</a> documentation.
--spec getActiveUniformsiv(integer(),[integer()],enum()) -> [integer()].
+%% @doc glGetActiveUniforms
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniforms.xml">external</a> documentation.
+-spec getActiveUniformsiv(Program, UniformIndices, Pname) -> [integer()] when Program :: integer(),UniformIndices :: [integer()],Pname :: enum().
getActiveUniformsiv(Program,UniformIndices,Pname) ->
call(5676, <<Program:?GLuint,(length(UniformIndices)):?GLuint,
(<< <<C:?GLuint>> || C <- UniformIndices>>)/binary,0:(((length(UniformIndices)) rem 2)*32),Pname:?GLenum>>).
-%% @spec (Program::integer(),UniformIndex::integer(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformName.xml">external</a> documentation.
--spec getActiveUniformName(integer(),integer(),integer()) -> string().
+%% @doc Query the name of an active uniform
+%%
+%% ``gl:getActiveUniformName'' returns the name of the active uniform at `UniformIndex'
+%% within `Program' . If `UniformName' is not NULL, up to `BufSize' characters
+%% (including a nul-terminator) will be written into the array whose address is specified
+%% by `UniformName' . If `Length' is not NULL, the number of characters that were
+%% (or would have been) written into `UniformName' (not including the nul-terminator)
+%% will be placed in the variable whose address is specified in `Length' . If `Length'
+%% is NULL, no length is returned. The length of the longest uniform name in `Program'
+%% is given by the value of `?GL_ACTIVE_UNIFORM_MAX_LENGTH', which can be queried with {@link gl:getProgramiv/2}
+%% .
+%%
+%% If ``gl:getActiveUniformName'' is not successful, nothing is written to `Length'
+%% or `UniformName' .
+%%
+%% `Program' must be the name of a program for which the command {@link gl:linkProgram/1}
+%% has been issued in the past. It is not necessary for `Program' to have been linked
+%% successfully. The link could have failed because the number of active uniforms exceeded
+%% the limit.
+%%
+%% `UniformIndex' must be an active uniform index of the program `Program' , in
+%% the range zero to `?GL_ACTIVE_UNIFORMS' - 1. The value of `?GL_ACTIVE_UNIFORMS'
+%% can be queried with {@link gl:getProgramiv/2} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformName.xml">external</a> documentation.
+-spec getActiveUniformName(Program, UniformIndex, BufSize) -> string() when Program :: integer(),UniformIndex :: integer(),BufSize :: integer().
getActiveUniformName(Program,UniformIndex,BufSize) ->
call(5677, <<Program:?GLuint,UniformIndex:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Program::integer(),UniformBlockName::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformBlockIndex.xml">external</a> documentation.
--spec getUniformBlockIndex(integer(),string()) -> integer().
+%% @doc Retrieve the index of a named uniform block
+%%
+%% ``gl:getUniformBlockIndex'' retrieves the index of a uniform block within `Program' .
+%%
+%%
+%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
+%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
+%% must have succeeded. The link could have failed because the number of active uniforms
+%% exceeded the limit.
+%%
+%% `UniformBlockName' must contain a nul-terminated string specifying the name of the
+%% uniform block.
+%%
+%% ``gl:getUniformBlockIndex'' returns the uniform block index for the uniform block named
+%% `UniformBlockName' of `Program' . If `UniformBlockName' does not identify
+%% an active uniform block of `Program' , ``gl:getUniformBlockIndex'' returns the special
+%% identifier, `?GL_INVALID_INDEX'. Indices of the active uniform blocks of a program
+%% are assigned in consecutive order, beginning with zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformBlockIndex.xml">external</a> documentation.
+-spec getUniformBlockIndex(Program, UniformBlockName) -> integer() when Program :: integer(),UniformBlockName :: string().
getUniformBlockIndex(Program,UniformBlockName) ->
call(5678, <<Program:?GLuint,(list_to_binary([UniformBlockName|[0]]))/binary,0:((8-((length(UniformBlockName)+ 5) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),UniformBlockIndex::integer(),Pname::enum(),Params::mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlock.xml">external</a> documentation.
--spec getActiveUniformBlockiv(integer(),integer(),enum(),mem()) -> ok.
+%% @doc Query information about an active uniform block
+%%
+%% ``gl:getActiveUniformBlockiv'' retrieves information about an active uniform block within
+%% `Program' .
+%%
+%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
+%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
+%% must have succeeded. The link could have failed because the number of active uniforms
+%% exceeded the limit.
+%%
+%% `UniformBlockIndex' is an active uniform block index of `Program' , and must
+%% be less than the value of `?GL_ACTIVE_UNIFORM_BLOCKS'.
+%%
+%% Upon success, the uniform block parameter(s) specified by `Pname' are returned in `Params'
+%% . If an error occurs, nothing will be written to `Params' .
+%%
+%% If `Pname' is `?GL_UNIFORM_BLOCK_BINDING', then the index of the uniform buffer
+%% binding point last selected by the uniform block specified by `UniformBlockIndex'
+%% for `Program' is returned. If no uniform block has been previously specified, zero
+%% is returned.
+%%
+%% If `Pname' is `?GL_UNIFORM_BLOCK_DATA_SIZE', then the implementation-dependent
+%% minimum total buffer object size, in basic machine units, required to hold all active
+%% uniforms in the uniform block identified by `UniformBlockIndex' is returned. It is
+%% neither guaranteed nor expected that a given implementation will arrange uniform values
+%% as tightly packed in a buffer object. The exception to this is the `std140 uniform block layout'
+%% , which guarantees specific packing behavior and does not require the application to query
+%% for offsets and strides. In this case the minimum size may still be queried, even though
+%% it is determined in advance based only on the uniform block declaration.
+%%
+%% If `Pname' is `?GL_UNIFORM_BLOCK_NAME_LENGTH', then the total length (including
+%% the nul terminator) of the name of the uniform block identified by `UniformBlockIndex'
+%% is returned.
+%%
+%% If `Pname' is `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS', then the number of active
+%% uniforms in the uniform block identified by `UniformBlockIndex' is returned.
+%%
+%% If `Pname' is `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES', then a list of the
+%% active uniform indices for the uniform block identified by `UniformBlockIndex' is
+%% returned. The number of elements that will be written to `Params' is the value of `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS'
+%% for `UniformBlockIndex' .
+%%
+%% If `Pname' is `?GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER', `?GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER'
+%% , or `?GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER', then a boolean value indicating
+%% whether the uniform block identified by `UniformBlockIndex' is referenced by the
+%% vertex, geometry, or fragment programming stages of program, respectively, is returned.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlock.xml">external</a> documentation.
+-spec getActiveUniformBlockiv(Program, UniformBlockIndex, Pname, Params) -> ok when Program :: integer(),UniformBlockIndex :: integer(),Pname :: enum(),Params :: mem().
getActiveUniformBlockiv(Program,UniformBlockIndex,Pname,Params) ->
send_bin(Params),
call(5679, <<Program:?GLuint,UniformBlockIndex:?GLuint,Pname:?GLenum>>).
-%% @spec (Program::integer(),UniformBlockIndex::integer(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlockName.xml">external</a> documentation.
--spec getActiveUniformBlockName(integer(),integer(),integer()) -> string().
+%% @doc Retrieve the name of an active uniform block
+%%
+%% ``gl:getActiveUniformBlockName'' retrieves the name of the active uniform block at `UniformBlockIndex'
+%% within `Program' .
+%%
+%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
+%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
+%% must have succeeded. The link could have failed because the number of active uniforms
+%% exceeded the limit.
+%%
+%% `UniformBlockIndex' is an active uniform block index of `Program' , and must
+%% be less than the value of `?GL_ACTIVE_UNIFORM_BLOCKS'.
+%%
+%% Upon success, the name of the uniform block identified by `UnifomBlockIndex' is
+%% returned into `UniformBlockName' . The name is nul-terminated. The actual number of
+%% characters written into `UniformBlockName' , excluding the nul terminator, is returned
+%% in `Length' . If `Length' is NULL, no length is returned.
+%%
+%% `BufSize' contains the maximum number of characters (including the nul terminator)
+%% that will be written into `UniformBlockName' .
+%%
+%% If an error occurs, nothing will be written to `UniformBlockName' or `Length' .
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlockName.xml">external</a> documentation.
+-spec getActiveUniformBlockName(Program, UniformBlockIndex, BufSize) -> string() when Program :: integer(),UniformBlockIndex :: integer(),BufSize :: integer().
getActiveUniformBlockName(Program,UniformBlockIndex,BufSize) ->
call(5680, <<Program:?GLuint,UniformBlockIndex:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Program::integer(),UniformBlockIndex::integer(),UniformBlockBinding::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformBlockBinding.xml">external</a> documentation.
--spec uniformBlockBinding(integer(),integer(),integer()) -> ok.
+%% @doc Assign a binding point to an active uniform block
+%%
+%% Binding points for active uniform blocks are assigned using ``gl:uniformBlockBinding''.
+%% Each of a program's active uniform blocks has a corresponding uniform buffer binding point.
+%% `Program' is the name of a program object for which the command {@link gl:linkProgram/1}
+%% has been issued in the past.
+%%
+%% If successful, ``gl:uniformBlockBinding'' specifies that `Program' will use the
+%% data store of the buffer object bound to the binding point `UniformBlockBinding'
+%% to extract the values of the uniforms in the uniform block identified by `UniformBlockIndex'
+%% .
+%%
+%% When a program object is linked or re-linked, the uniform buffer object binding point
+%% assigned to each of its active uniform blocks is reset to zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformBlockBinding.xml">external</a> documentation.
+-spec uniformBlockBinding(Program, UniformBlockIndex, UniformBlockBinding) -> ok when Program :: integer(),UniformBlockIndex :: integer(),UniformBlockBinding :: integer().
uniformBlockBinding(Program,UniformBlockIndex,UniformBlockBinding) ->
cast(5681, <<Program:?GLuint,UniformBlockIndex:?GLuint,UniformBlockBinding:?GLuint>>).
-%% @spec (ReadTarget::enum(),WriteTarget::enum(),ReadOffset::integer(),WriteOffset::integer(),Size::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyBufferSubData.xml">external</a> documentation.
--spec copyBufferSubData(enum(),enum(),integer(),integer(),integer()) -> ok.
+%% @doc Copy part of the data store of a buffer object to the data store of another buffer object
+%%
+%% ``gl:copyBufferSubData'' copies part of the data store attached to `Readtarget'
+%% to the data store attached to `Writetarget' . The number of basic machine units indicated
+%% by `Size' is copied from the source, at offset `Readoffset' to the destination
+%% at `Writeoffset' , also in basic machine units.
+%%
+%% `Readtarget' and `Writetarget' must be `?GL_ARRAY_BUFFER', `?GL_COPY_READ_BUFFER'
+%% , `?GL_COPY_WRITE_BUFFER', `?GL_ELEMENT_ARRAY_BUFFER', `?GL_PIXEL_PACK_BUFFER'
+%% , `?GL_PIXEL_UNPACK_BUFFER', `?GL_TEXTURE_BUFFER', `?GL_TRANSFORM_FEEDBACK_BUFFER'
+%% or `?GL_UNIFORM_BUFFER'. Any of these targets may be used, although the targets `?GL_COPY_READ_BUFFER'
+%% and `?GL_COPY_WRITE_BUFFER' are provided specifically to allow copies between buffers
+%% without disturbing other GL state.
+%%
+%% `Readoffset' , `Writeoffset' and `Size' must all be greater than or equal
+%% to zero. Furthermore, `Readoffset' + `Size' must not exceeed the size of the
+%% buffer object bound to `Readtarget' , and `Readoffset' + `Size' must not
+%% exceeed the size of the buffer bound to `Writetarget' . If the same buffer object
+%% is bound to both `Readtarget' and `Writetarget' , then the ranges specified by `Readoffset'
+%% , `Writeoffset' and `Size' must not overlap.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyBufferSubData.xml">external</a> documentation.
+-spec copyBufferSubData(ReadTarget, WriteTarget, ReadOffset, WriteOffset, Size) -> ok when ReadTarget :: enum(),WriteTarget :: enum(),ReadOffset :: integer(),WriteOffset :: integer(),Size :: integer().
copyBufferSubData(ReadTarget,WriteTarget,ReadOffset,WriteOffset,Size) ->
cast(5682, <<ReadTarget:?GLenum,WriteTarget:?GLenum,ReadOffset:?GLintptr,WriteOffset:?GLintptr,Size:?GLsizeiptr>>).
-%% @spec (Mode::enum(),Count::integer(),Type::enum(),Indices::offset()|mem(),Basevertex::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsBaseVertex.xml">external</a> documentation.
--spec drawElementsBaseVertex(enum(),integer(),enum(),offset()|mem(),integer()) -> ok.
+%% @doc Render primitives from array data with a per-element offset
+%%
+%% ``gl:drawElementsBaseVertex'' behaves identically to {@link gl:drawElements/4} except
+%% that the `i'th element transferred by the corresponding draw call will be taken from
+%% element `Indices' [i] + `Basevertex' of each enabled array. If the resulting
+%% value is larger than the maximum value representable by `Type' , it is as if the calculation
+%% were upconverted to 32-bit unsigned integers (with wrapping on overflow conditions). The
+%% operation is undefined if the sum would be negative.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsBaseVertex.xml">external</a> documentation.
+-spec drawElementsBaseVertex(Mode, Count, Type, Indices, Basevertex) -> ok when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Basevertex :: integer().
drawElementsBaseVertex(Mode,Count,Type,Indices,Basevertex) when is_integer(Indices) ->
cast(5683, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Basevertex:?GLint>>);
drawElementsBaseVertex(Mode,Count,Type,Indices,Basevertex) ->
send_bin(Indices),
cast(5684, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Basevertex:?GLint>>).
-%% @spec (Mode::enum(),Start::integer(),End::integer(),Count::integer(),Type::enum(),Indices::offset()|mem(),Basevertex::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElementsBaseVertex.xml">external</a> documentation.
--spec drawRangeElementsBaseVertex(enum(),integer(),integer(),integer(),enum(),offset()|mem(),integer()) -> ok.
+%% @doc Render primitives from array data with a per-element offset
+%%
+%% ``gl:drawRangeElementsBaseVertex'' is a restricted form of {@link gl:drawElementsBaseVertex/5}
+%% . `Mode' , `Start' , `End' , `Count' and `Basevertex' match the
+%% corresponding arguments to {@link gl:drawElementsBaseVertex/5} , with the additional constraint
+%% that all values in the array `Indices' must lie between `Start' and `End' ,
+%% inclusive, prior to adding `Basevertex' . Index values lying outside the range [ `Start'
+%% , `End' ] are treated in the same way as {@link gl:drawElementsBaseVertex/5} . The `i'
+%% th element transferred by the corresponding draw call will be taken from element `Indices'
+%% [i] + `Basevertex' of each enabled array. If the resulting value is larger than the
+%% maximum value representable by `Type' , it is as if the calculation were upconverted
+%% to 32-bit unsigned integers (with wrapping on overflow conditions). The operation is undefined
+%% if the sum would be negative.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElementsBaseVertex.xml">external</a> documentation.
+-spec drawRangeElementsBaseVertex(Mode, Start, End, Count, Type, Indices, Basevertex) -> ok when Mode :: enum(),Start :: integer(),End :: integer(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Basevertex :: integer().
drawRangeElementsBaseVertex(Mode,Start,End,Count,Type,Indices,Basevertex) when is_integer(Indices) ->
cast(5685, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Basevertex:?GLint>>);
drawRangeElementsBaseVertex(Mode,Start,End,Count,Type,Indices,Basevertex) ->
send_bin(Indices),
cast(5686, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Basevertex:?GLint>>).
-%% @spec (Mode::enum(),Count::integer(),Type::enum(),Indices::offset()|mem(),Primcount::integer(),Basevertex::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertex.xml">external</a> documentation.
--spec drawElementsInstancedBaseVertex(enum(),integer(),enum(),offset()|mem(),integer(),integer()) -> ok.
+%% @doc Render multiple instances of a set of primitives from array data with a per-element offset
+%%
+%% ``gl:drawElementsInstancedBaseVertex'' behaves identically to {@link gl:drawElementsInstanced/5}
+%% except that the `i'th element transferred by the corresponding draw call will be
+%% taken from element `Indices' [i] + `Basevertex' of each enabled array. If the
+%% resulting value is larger than the maximum value representable by `Type' , it is as
+%% if the calculation were upconverted to 32-bit unsigned integers (with wrapping on overflow
+%% conditions). The operation is undefined if the sum would be negative.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertex.xml">external</a> documentation.
+-spec drawElementsInstancedBaseVertex(Mode, Count, Type, Indices, Primcount, Basevertex) -> ok when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Basevertex :: integer().
drawElementsInstancedBaseVertex(Mode,Count,Type,Indices,Primcount,Basevertex) when is_integer(Indices) ->
cast(5687, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Basevertex:?GLint>>);
drawElementsInstancedBaseVertex(Mode,Count,Type,Indices,Primcount,Basevertex) ->
send_bin(Indices),
cast(5688, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Primcount:?GLsizei,Basevertex:?GLint>>).
-%% @spec (Mode::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProvokingVertex.xml">external</a> documentation.
--spec provokingVertex(enum()) -> ok.
+%% @doc Specifiy the vertex to be used as the source of data for flat shaded varyings
+%%
+%% `Flatshading' a vertex shader varying output means to assign all vetices of the primitive
+%% the same value for that output. The vertex from which these values is derived is known
+%% as the `provoking vertex' and ``gl:provokingVertex'' specifies which vertex is
+%% to be used as the source of data for flat shaded varyings.
+%%
+%% `ProvokeMode' must be either `?GL_FIRST_VERTEX_CONVENTION' or `?GL_LAST_VERTEX_CONVENTION'
+%% , and controls the selection of the vertex whose values are assigned to flatshaded varying
+%% outputs. The interpretation of these values for the supported primitive types is: <table><tbody>
+%% <tr><td>` Primitive Type of Polygon '`i'</td><td>` First Vertex Convention '
+%% </td><td>` Last Vertex Convention '</td></tr><tr><td> point </td><td>`i'</td><td>
+%% `i'</td></tr><tr><td> independent line </td><td> 2`i' - 1 </td><td> 2`i'</td>
+%% </tr><tr><td> line loop </td><td>`i'</td><td>
+%%
+%% `i' + 1, if `i' &lt; `n'
+%%
+%% 1, if `i' = `n'</td></tr><tr><td> line strip </td><td>`i'</td><td>`i'
+%% + 1 </td></tr><tr><td> independent triangle </td><td> 3`i' - 2 </td><td> 3`i'</td>
+%% </tr><tr><td> triangle strip </td><td>`i'</td><td>`i' + 2 </td></tr><tr><td>
+%% triangle fan </td><td>`i' + 1 </td><td>`i' + 2 </td></tr><tr><td> line adjacency
+%% </td><td> 4`i' - 2 </td><td> 4`i' - 1 </td></tr><tr><td> line strip adjacency </td>
+%% <td>`i' + 1 </td><td>`i' + 2 </td></tr><tr><td> triangle adjacency </td><td> 6`i'
+%% - 5 </td><td> 6`i' - 1 </td></tr><tr><td> triangle strip adjacency </td><td> 2`i'
+%% - 1 </td><td> 2`i' + 3 </td></tr></tbody></table>
+%%
+%% If a vertex or geometry shader is active, user-defined varying outputs may be flatshaded
+%% by using the flat qualifier when declaring the output.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProvokingVertex.xml">external</a> documentation.
+-spec provokingVertex(Mode) -> ok when Mode :: enum().
provokingVertex(Mode) ->
cast(5689, <<Mode:?GLenum>>).
-%% @spec (Condition::enum(),Flags::integer()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFenceSync.xml">external</a> documentation.
--spec fenceSync(enum(),integer()) -> integer().
+%% @doc Create a new sync object and insert it into the GL command stream
+%%
+%% ``gl:fenceSync'' creates a new fence sync object, inserts a fence command into the GL
+%% command stream and associates it with that sync object, and returns a non-zero name corresponding
+%% to the sync object.
+%%
+%% When the specified `Condition' of the sync object is satisfied by the fence command,
+%% the sync object is signaled by the GL, causing any {@link gl:waitSync/3} , {@link gl:clientWaitSync/3}
+%% commands blocking in `Sync' to `unblock'. No other state is affected by ``gl:fenceSync''
+%% or by the execution of the associated fence command.
+%%
+%% `Condition' must be `?GL_SYNC_GPU_COMMANDS_COMPLETE'. This condition is satisfied
+%% by completion of the fence command corresponding to the sync object and all preceding
+%% commands in the same command stream. The sync object will not be signaled until all effects
+%% from these commands on GL client and server state and the framebuffer are fully realized.
+%% Note that completion of the fence command occurs once the state of the corresponding sync
+%% object has been changed, but commands waiting on that sync object may not be unblocked
+%% until after the fence command completes.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFenceSync.xml">external</a> documentation.
+-spec fenceSync(Condition, Flags) -> integer() when Condition :: enum(),Flags :: integer().
fenceSync(Condition,Flags) ->
call(5690, <<Condition:?GLenum,Flags:?GLbitfield>>).
-%% @spec (Sync::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSync.xml">external</a> documentation.
--spec isSync(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a sync object
+%%
+%% ``gl:isSync'' returns `?GL_TRUE' if `Sync' is currently the name of a sync
+%% object. If `Sync' is not the name of a sync object, or if an error occurs, ``gl:isSync''
+%% returns `?GL_FALSE'. Note that zero is not the name of a sync object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSync.xml">external</a> documentation.
+-spec isSync(Sync) -> 0|1 when Sync :: integer().
isSync(Sync) ->
call(5691, <<Sync:?GLsync>>).
-%% @spec (Sync::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSync.xml">external</a> documentation.
--spec deleteSync(integer()) -> ok.
+%% @doc Delete a sync object
+%%
+%% ``gl:deleteSync'' deletes the sync object specified by `Sync' . If the fence command
+%% corresponding to the specified sync object has completed, or if no {@link gl:waitSync/3}
+%% or {@link gl:clientWaitSync/3} commands are blocking on `Sync' , the object is deleted
+%% immediately. Otherwise, `Sync' is flagged for deletion and will be deleted when it
+%% is no longer associated with any fence command and is no longer blocking any {@link gl:waitSync/3}
+%% or {@link gl:clientWaitSync/3} command. In either case, after ``gl:deleteSync'' returns,
+%% the name `Sync' is invalid and can no longer be used to refer to the sync object.
+%%
+%% ``gl:deleteSync'' will silently ignore a `Sync' value of zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSync.xml">external</a> documentation.
+-spec deleteSync(Sync) -> ok when Sync :: integer().
deleteSync(Sync) ->
cast(5692, <<Sync:?GLsync>>).
-%% @spec (Sync::integer(),Flags::integer(),Timeout::integer()) -> enum()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientWaitSync.xml">external</a> documentation.
--spec clientWaitSync(integer(),integer(),integer()) -> enum().
+%% @doc Block and wait for a sync object to become signaled
+%%
+%% ``gl:clientWaitSync'' causes the client to block and wait for the sync object specified
+%% by `Sync' to become signaled. If `Sync' is signaled when ``gl:clientWaitSync''
+%% is called, ``gl:clientWaitSync'' returns immediately, otherwise it will block and wait
+%% for up to `Timeout' nanoseconds for `Sync' to become signaled.
+%%
+%% The return value is one of four status values:
+%%
+%% `?GL_ALREADY_SIGNALED' indicates that `Sync' was signaled at the time that ``gl:clientWaitSync''
+%% was called.
+%%
+%% `?GL_TIMEOUT_EXPIRED' indicates that at least `Timeout' nanoseconds passed and `Sync'
+%% did not become signaled.
+%%
+%% `?GL_CONDITION_SATISFIED' indicates that `Sync' was signaled before the timeout
+%% expired.
+%%
+%% `?GL_WAIT_FAILED' indicates that an error occurred. Additionally, an OpenGL error
+%% will be generated.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientWaitSync.xml">external</a> documentation.
+-spec clientWaitSync(Sync, Flags, Timeout) -> enum() when Sync :: integer(),Flags :: integer(),Timeout :: integer().
clientWaitSync(Sync,Flags,Timeout) ->
call(5693, <<Sync:?GLsync,Flags:?GLbitfield,0:32,Timeout:?GLuint64>>).
-%% @spec (Sync::integer(),Flags::integer(),Timeout::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWaitSync.xml">external</a> documentation.
--spec waitSync(integer(),integer(),integer()) -> ok.
+%% @doc Instruct the GL server to block until the specified sync object becomes signaled
+%%
+%% ``gl:waitSync'' causes the GL server to block and wait until `Sync' becomes signaled.
+%% `Sync' is the name of an existing sync object upon which to wait. `Flags' and `Timeout'
+%% are currently not used and must be set to zero and the special value `?GL_TIMEOUT_IGNORED'
+%% , respectively
+%%
+%% `Flags' and `Timeout' are placeholders for anticipated future extensions of
+%% sync object capabilities. They must have these reserved values in order that existing
+%% code calling ``gl:waitSync'' operate properly in the presence of such extensions.. ``gl:waitSync''
+%% will always wait no longer than an implementation-dependent timeout. The duration of
+%% this timeout in nanoseconds may be queried by calling {@link gl:getBooleanv/1} with the parameter `?GL_MAX_SERVER_WAIT_TIMEOUT'
+%% . There is currently no way to determine whether ``gl:waitSync'' unblocked because the
+%% timeout expired or because the sync object being waited on was signaled.
+%%
+%% If an error occurs, ``gl:waitSync'' does not cause the GL server to block.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWaitSync.xml">external</a> documentation.
+-spec waitSync(Sync, Flags, Timeout) -> ok when Sync :: integer(),Flags :: integer(),Timeout :: integer().
waitSync(Sync,Flags,Timeout) ->
cast(5694, <<Sync:?GLsync,Flags:?GLbitfield,0:32,Timeout:?GLuint64>>).
-%% @spec (Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInteger64v.xml">external</a> documentation.
--spec getInteger64v(enum()) -> [integer()].
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getInteger64v(Pname) -> [integer()] when Pname :: enum().
getInteger64v(Pname) ->
call(5695, <<Pname:?GLenum>>).
-%% @spec (Sync::integer(),Pname::enum(),BufSize::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSync.xml">external</a> documentation.
--spec getSynciv(integer(),enum(),integer()) -> [integer()].
+%% @doc Query the properties of a sync object
+%%
+%% ``gl:getSynciv'' retrieves properties of a sync object. `Sync' specifies the name
+%% of the sync object whose properties to retrieve.
+%%
+%% On success, ``gl:getSynciv'' replaces up to `BufSize' integers in `Values'
+%% with the corresponding property values of the object being queried. The actual number
+%% of integers replaced is returned in the variable whose address is specified in `Length'
+%% . If `Length' is NULL, no length is returned.
+%%
+%% If `Pname' is `?GL_OBJECT_TYPE', a single value representing the specific type
+%% of the sync object is placed in `Values' . The only type supported is `?GL_SYNC_FENCE'
+%% .
+%%
+%% If `Pname' is `?GL_SYNC_STATUS', a single value representing the status of
+%% the sync object (`?GL_SIGNALED' or `?GL_UNSIGNALED') is placed in `Values' .
+%%
+%%
+%% If `Pname' is `?GL_SYNC_CONDITION', a single value representing the condition
+%% of the sync object is placed in `Values' . The only condition supported is `?GL_SYNC_GPU_COMMANDS_COMPLETE'
+%% .
+%%
+%% If `Pname' is `?GL_SYNC_FLAGS', a single value representing the flags with
+%% which the sync object was created is placed in `Values' . No flags are currently supported
+%%
+%%
+%% `Flags' is expected to be used in future extensions to the sync objects..
+%%
+%% If an error occurs, nothing will be written to `Values' or `Length' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSync.xml">external</a> documentation.
+-spec getSynciv(Sync, Pname, BufSize) -> [integer()] when Sync :: integer(),Pname :: enum(),BufSize :: integer().
getSynciv(Sync,Pname,BufSize) ->
call(5696, <<Sync:?GLsync,Pname:?GLenum,BufSize:?GLsizei>>).
-%% @spec (Target::enum(),Samples::integer(),Internalformat::integer(),Width::integer(),Height::integer(),Fixedsamplelocations::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2DMultisample.xml">external</a> documentation.
--spec texImage2DMultisample(enum(),integer(),integer(),integer(),integer(),0|1) -> ok.
+%% @doc Establish the data storage, format, dimensions, and number of samples of a multisample texture's image
+%%
+%% ``gl:texImage2DMultisample'' establishes the data storage, format, dimensions and number
+%% of samples of a multisample texture's image.
+%%
+%% `Target' must be `?GL_TEXTURE_2D_MULTISAMPLE' or `?GL_PROXY_TEXTURE_2D_MULTISAMPLE'
+%% . `Width' and `Height' are the dimensions in texels of the texture, and must
+%% be in the range zero to `?GL_MAX_TEXTURE_SIZE' - 1. `Samples' specifies the
+%% number of samples in the image and must be in the range zero to `?GL_MAX_SAMPLES'
+%% - 1.
+%%
+%% `Internalformat' must be a color-renderable, depth-renderable, or stencil-renderable
+%% format.
+%%
+%% If `Fixedsamplelocations' is `?GL_TRUE', the image will use identical sample
+%% locations and the same number of samples for all texels in the image, and the sample locations
+%% will not depend on the internal format or size of the image.
+%%
+%% When a multisample texture is accessed in a shader, the access takes one vector of integers
+%% describing which texel to fetch and an integer corresponding to the sample numbers describing
+%% which sample within the texel to fetch. No standard sampling instructions are allowed
+%% on the multisample texture targets.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2DMultisample.xml">external</a> documentation.
+-spec texImage2DMultisample(Target, Samples, Internalformat, Width, Height, Fixedsamplelocations) -> ok when Target :: enum(),Samples :: integer(),Internalformat :: integer(),Width :: integer(),Height :: integer(),Fixedsamplelocations :: 0|1.
texImage2DMultisample(Target,Samples,Internalformat,Width,Height,Fixedsamplelocations) ->
cast(5697, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Fixedsamplelocations:?GLboolean>>).
-%% @spec (Target::enum(),Samples::integer(),Internalformat::integer(),Width::integer(),Height::integer(),Depth::integer(),Fixedsamplelocations::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3DMultisample.xml">external</a> documentation.
--spec texImage3DMultisample(enum(),integer(),integer(),integer(),integer(),integer(),0|1) -> ok.
+%% @doc Establish the data storage, format, dimensions, and number of samples of a multisample texture's image
+%%
+%% ``gl:texImage3DMultisample'' establishes the data storage, format, dimensions and number
+%% of samples of a multisample texture's image.
+%%
+%% `Target' must be `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY' or `?GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY'
+%% . `Width' and `Height' are the dimensions in texels of the texture, and must
+%% be in the range zero to `?GL_MAX_TEXTURE_SIZE' - 1. `Depth' is the number of
+%% array slices in the array texture's image. `Samples' specifies the number of samples
+%% in the image and must be in the range zero to `?GL_MAX_SAMPLES' - 1.
+%%
+%% `Internalformat' must be a color-renderable, depth-renderable, or stencil-renderable
+%% format.
+%%
+%% If `Fixedsamplelocations' is `?GL_TRUE', the image will use identical sample
+%% locations and the same number of samples for all texels in the image, and the sample locations
+%% will not depend on the internal format or size of the image.
+%%
+%% When a multisample texture is accessed in a shader, the access takes one vector of integers
+%% describing which texel to fetch and an integer corresponding to the sample numbers describing
+%% which sample within the texel to fetch. No standard sampling instructions are allowed
+%% on the multisample texture targets.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3DMultisample.xml">external</a> documentation.
+-spec texImage3DMultisample(Target, Samples, Internalformat, Width, Height, Depth, Fixedsamplelocations) -> ok when Target :: enum(),Samples :: integer(),Internalformat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Fixedsamplelocations :: 0|1.
texImage3DMultisample(Target,Samples,Internalformat,Width,Height,Depth,Fixedsamplelocations) ->
cast(5698, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Fixedsamplelocations:?GLboolean>>).
-%% @spec (Pname::enum(),Index::integer()) -> {float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMultisample.xml">external</a> documentation.
--spec getMultisamplefv(enum(),integer()) -> {float(),float()}.
+%% @doc Retrieve the location of a sample
+%%
+%% ``gl:getMultisamplefv'' queries the location of a given sample. `Pname' specifies
+%% the sample parameter to retrieve and must be `?GL_SAMPLE_POSITION'. `Index'
+%% corresponds to the sample for which the location should be returned. The sample location
+%% is returned as two floating-point values in `Val[0]' and `Val[1]' , each between
+%% 0 and 1, corresponding to the `X' and `Y' locations respectively in the GL pixel
+%% space of that sample. (0.5, 0.5) this corresponds to the pixel center. `Index' must
+%% be between zero and the value of `?GL_SAMPLES' - 1.
+%%
+%% If the multisample mode does not have fixed sample locations, the returned values may
+%% only reflect the locations of samples within some pixels.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMultisample.xml">external</a> documentation.
+-spec getMultisamplefv(Pname, Index) -> {float(),float()} when Pname :: enum(),Index :: integer().
getMultisamplefv(Pname,Index) ->
call(5699, <<Pname:?GLenum,Index:?GLuint>>).
-%% @spec (Index::integer(),Mask::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleMaski.xml">external</a> documentation.
--spec sampleMaski(integer(),integer()) -> ok.
+%% @doc Set the value of a sub-word of the sample mask
+%%
+%% ``gl:sampleMaski'' sets one 32-bit sub-word of the multi-word sample mask, `?GL_SAMPLE_MASK_VALUE'
+%% .
+%%
+%% `MaskIndex' specifies which 32-bit sub-word of the sample mask to update, and `Mask'
+%% specifies the new value to use for that sub-word. `MaskIndex' must be less than
+%% the value of `?GL_MAX_SAMPLE_MASK_WORDS'. Bit `B' of mask word `M' corresponds
+%% to sample 32 x `M' + `B'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleMaski.xml">external</a> documentation.
+-spec sampleMaski(Index, Mask) -> ok when Index :: integer(),Mask :: integer().
sampleMaski(Index,Mask) ->
cast(5700, <<Index:?GLuint,Mask:?GLbitfield>>).
-%% @spec (Type::enum(),Name::string(),String::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNamedStringARB.xml">external</a> documentation.
--spec namedStringARB(enum(),string(),string()) -> ok.
+%% @doc glNamedStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNamedStringARB.xml">external</a> documentation.
+-spec namedStringARB(Type, Name, String) -> ok when Type :: enum(),Name :: string(),String :: string().
namedStringARB(Type,Name,String) ->
cast(5701, <<Type:?GLenum,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8),(list_to_binary([String|[0]]))/binary,0:((8-((length(String)+ 1) rem 8)) rem 8)>>).
-%% @spec (Name::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteNamedStringARB.xml">external</a> documentation.
--spec deleteNamedStringARB(string()) -> ok.
+%% @doc glDeleteNamedStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteNamedStringARB.xml">external</a> documentation.
+-spec deleteNamedStringARB(Name) -> ok when Name :: string().
deleteNamedStringARB(Name) ->
cast(5702, <<(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Shader::integer(),Path::[string()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderIncludeARB.xml">external</a> documentation.
--spec compileShaderIncludeARB(integer(),[string()]) -> ok.
+%% @doc glCompileShaderIncludeARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderIncludeARB.xml">external</a> documentation.
+-spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: [string()].
compileShaderIncludeARB(Shader,Path) ->
PathTemp = list_to_binary([[Str|[0]] || Str <- Path ]),
cast(5703, <<Shader:?GLuint,(length(Path)):?GLuint,(size(PathTemp)):?GLuint,(PathTemp)/binary,0:((8-((size(PathTemp)+0) rem 8)) rem 8)>>).
-%% @spec (Name::string()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsNamedStringARB.xml">external</a> documentation.
--spec isNamedStringARB(string()) -> 0|1.
+%% @doc glIsNamedStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsNamedStringARB.xml">external</a> documentation.
+-spec isNamedStringARB(Name) -> 0|1 when Name :: string().
isNamedStringARB(Name) ->
call(5704, <<(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Name::string(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation.
--spec getNamedStringARB(string(),integer()) -> string().
+%% @doc glGetNamedStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation.
+-spec getNamedStringARB(Name, BufSize) -> string() when Name :: string(),BufSize :: integer().
getNamedStringARB(Name,BufSize) ->
call(5705, <<(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8),BufSize:?GLsizei>>).
-%% @spec (Name::string(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation.
--spec getNamedStringivARB(string(),enum()) -> integer().
+%% @doc glGetNamedStringARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation.
+-spec getNamedStringivARB(Name, Pname) -> integer() when Name :: string(),Pname :: enum().
getNamedStringivARB(Name,Pname) ->
call(5706, <<(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8),Pname:?GLenum>>).
-%% @spec (Program::integer(),ColorNumber::integer(),Index::integer(),Name::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocationIndexe.xml">external</a> documentation.
--spec bindFragDataLocationIndexed(integer(),integer(),integer(),string()) -> ok.
+%% @doc glBindFragDataLocationIndexe
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocationIndexe.xml">external</a> documentation.
+-spec bindFragDataLocationIndexed(Program, ColorNumber, Index, Name) -> ok when Program :: integer(),ColorNumber :: integer(),Index :: integer(),Name :: string().
bindFragDataLocationIndexed(Program,ColorNumber,Index,Name) ->
cast(5707, <<Program:?GLuint,ColorNumber:?GLuint,Index:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataIndex.xml">external</a> documentation.
--spec getFragDataIndex(integer(),string()) -> integer().
+%% @doc Query the bindings of color indices to user-defined varying out variables
+%%
+%% ``gl:getFragDataIndex'' returns the index of the fragment color to which the variable `Name'
+%% was bound when the program object `Program' was last linked. If `Name' is not
+%% a varying out variable of `Program' , or if an error occurs, -1 will be returned.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataIndex.xml">external</a> documentation.
+-spec getFragDataIndex(Program, Name) -> integer() when Program :: integer(),Name :: string().
getFragDataIndex(Program,Name) ->
call(5708, <<Program:?GLuint,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 5) rem 8)) rem 8)>>).
-%% @spec (Count::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenSamplers.xml">external</a> documentation.
--spec genSamplers(integer()) -> [integer()].
+%% @doc Generate sampler object names
+%%
+%% ``gl:genSamplers'' returns `N' sampler object names in `Samplers' . There is
+%% no guarantee that the names form a contiguous set of integers; however, it is guaranteed
+%% that none of the returned names was in use immediately before the call to ``gl:genSamplers''
+%% .
+%%
+%% Sampler object names returned by a call to ``gl:genSamplers'' are not returned by subsequent
+%% calls, unless they are first deleted with {@link gl:deleteSamplers/1} .
+%%
+%% The names returned in `Samplers' are marked as used, for the purposes of ``gl:genSamplers''
+%% only, but they acquire state and type only when they are first bound.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenSamplers.xml">external</a> documentation.
+-spec genSamplers(Count) -> [integer()] when Count :: integer().
genSamplers(Count) ->
call(5709, <<Count:?GLsizei>>).
-%% @spec (Samplers::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSamplers.xml">external</a> documentation.
--spec deleteSamplers([integer()]) -> ok.
+%% @doc Delete named sampler objects
+%%
+%% ``gl:deleteSamplers'' deletes `N' sampler objects named by the elements of the
+%% array `Ids' . After a sampler object is deleted, its name is again unused. If a sampler
+%% object that is currently bound to a sampler unit is deleted, it is as though {@link gl:bindSampler/2}
+%% is called with unit set to the unit the sampler is bound to and sampler zero. Unused
+%% names in samplers are silently ignored, as is the reserved name zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSamplers.xml">external</a> documentation.
+-spec deleteSamplers(Samplers) -> ok when Samplers :: [integer()].
deleteSamplers(Samplers) ->
cast(5710, <<(length(Samplers)):?GLuint,
(<< <<C:?GLuint>> || C <- Samplers>>)/binary,0:(((1+length(Samplers)) rem 2)*32)>>).
-%% @spec (Sampler::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSampler.xml">external</a> documentation.
--spec isSampler(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a sampler object
+%%
+%% ``gl:isSampler'' returns `?GL_TRUE' if `Id' is currently the name of a sampler
+%% object. If `Id' is zero, or is a non-zero value that is not currently the name of
+%% a sampler object, or if an error occurs, ``gl:isSampler'' returns `?GL_FALSE'.
+%%
+%% A name returned by {@link gl:genSamplers/1} , is the name of a sampler object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSampler.xml">external</a> documentation.
+-spec isSampler(Sampler) -> 0|1 when Sampler :: integer().
isSampler(Sampler) ->
call(5711, <<Sampler:?GLuint>>).
-%% @spec (Unit::integer(),Sampler::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindSampler.xml">external</a> documentation.
--spec bindSampler(integer(),integer()) -> ok.
+%% @doc Bind a named sampler to a texturing target
+%%
+%% ``gl:bindSampler'' binds `Sampler' to the texture unit at index `Unit' . `Sampler'
+%% must be zero or the name of a sampler object previously returned from a call to {@link gl:genSamplers/1}
+%% . `Unit' must be less than the value of `?GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS'.
+%%
+%%
+%% When a sampler object is bound to a texture unit, its state supersedes that of the texture
+%% object bound to that texture unit. If the sampler name zero is bound to a texture unit,
+%% the currently bound texture's sampler state becomes active. A single sampler object may
+%% be bound to multiple texture units simultaneously.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindSampler.xml">external</a> documentation.
+-spec bindSampler(Unit, Sampler) -> ok when Unit :: integer(),Sampler :: integer().
bindSampler(Unit,Sampler) ->
cast(5712, <<Unit:?GLuint,Sampler:?GLuint>>).
-%% @spec (Sampler::integer(),Pname::enum(),Param::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation.
--spec samplerParameteri(integer(),enum(),integer()) -> ok.
+%% @doc Set sampler parameters
+%%
+%% ``gl:samplerParameter'' assigns the value or values in `Params' to the sampler
+%% parameter specified as `Pname' . `Sampler' specifies the sampler object to be
+%% modified, and must be the name of a sampler object previously returned from a call to {@link gl:genSamplers/1}
+%% . The following symbols are accepted in `Pname' :
+%%
+%% `?GL_TEXTURE_MIN_FILTER': The texture minifying function is used whenever the pixel
+%% being textured maps to an area greater than one texture element. There are six defined
+%% minifying functions. Two of them use the nearest one or nearest four texture elements
+%% to compute the texture value. The other four use mipmaps.
+%%
+%% A mipmap is an ordered set of arrays representing the same image at progressively lower
+%% resolutions. If the texture has dimensions 2 n*2 m, there are max(n m)+1 mipmaps. The first
+%% mipmap is the original texture, with dimensions 2 n*2 m. Each subsequent mipmap has
+%% dimensions 2(k-1)*2(l-1), where 2 k*2 l are the dimensions of the previous mipmap, until either
+%% k= 0 or l= 0. At that point, subsequent mipmaps have dimension 1*2(l-1) or 2(k-1)*1 until
+%% the final mipmap, which has dimension 1*1. To define the mipmaps, call {@link gl:texImage1D/8}
+%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:copyTexImage1D/7} , or {@link gl:copyTexImage2D/8}
+%% with the `level' argument indicating the order of the mipmaps. Level 0 is the original
+%% texture; level max(n m) is the final 1*1 mipmap.
+%%
+%% `Params' supplies a function for minifying the texture as one of the following:
+%%
+%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
+%% distance) to the center of the pixel being textured.
+%%
+%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are
+%% closest to the center of the pixel being textured. These can include border texture elements,
+%% depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T', and
+%% on the exact mapping.
+%%
+%% `?GL_NEAREST_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
+%% of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture element
+%% nearest to the center of the pixel) to produce a texture value.
+%%
+%% `?GL_LINEAR_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
+%% of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted average
+%% of the four texture elements that are closest to the center of the pixel) to produce a
+%% texture value.
+%%
+%% `?GL_NEAREST_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
+%% size of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture
+%% element nearest to the center of the pixel) to produce a texture value from each mipmap.
+%% The final texture value is a weighted average of those two values.
+%%
+%% `?GL_LINEAR_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
+%% size of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted
+%% average of the four texture elements that are closest to the center of the pixel) to produce
+%% a texture value from each mipmap. The final texture value is a weighted average of those
+%% two values.
+%%
+%% As more texture elements are sampled in the minification process, fewer aliasing artifacts
+%% will be apparent. While the `?GL_NEAREST' and `?GL_LINEAR' minification functions
+%% can be faster than the other four, they sample only one or four texture elements to determine
+%% the texture value of the pixel being rendered and can produce moire patterns or ragged
+%% transitions. The initial value of `?GL_TEXTURE_MIN_FILTER' is `?GL_NEAREST_MIPMAP_LINEAR'
+%% .
+%%
+%% `?GL_TEXTURE_MAG_FILTER': The texture magnification function is used when the pixel
+%% being textured maps to an area less than or equal to one texture element. It sets the
+%% texture magnification function to either `?GL_NEAREST' or `?GL_LINEAR' (see
+%% below). `?GL_NEAREST' is generally faster than `?GL_LINEAR', but it can produce
+%% textured images with sharper edges because the transition between texture elements is
+%% not as smooth. The initial value of `?GL_TEXTURE_MAG_FILTER' is `?GL_LINEAR'.
+%%
+%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
+%% distance) to the center of the pixel being textured.
+%%
+%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are
+%% closest to the center of the pixel being textured. These can include border texture elements,
+%% depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T', and
+%% on the exact mapping.
+%%
+%%
+%%
+%% `?GL_TEXTURE_MIN_LOD': Sets the minimum level-of-detail parameter. This floating-point
+%% value limits the selection of highest resolution mipmap (lowest mipmap level). The initial
+%% value is -1000.
+%%
+%%
+%%
+%% `?GL_TEXTURE_MAX_LOD': Sets the maximum level-of-detail parameter. This floating-point
+%% value limits the selection of the lowest resolution mipmap (highest mipmap level). The
+%% initial value is 1000.
+%%
+%%
+%%
+%% `?GL_TEXTURE_WRAP_S': Sets the wrap parameter for texture coordinate s to either `?GL_CLAMP_TO_EDGE'
+%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. `?GL_CLAMP_TO_BORDER' causes
+%% the s coordinate to be clamped to the range [(-1 2/N) 1+(1 2/N)], where N is the size of the texture in
+%% the direction of clamping.`?GL_CLAMP_TO_EDGE' causes s coordinates to be clamped
+%% to the range [(1 2/N) 1-(1 2/N)], where N is the size of the texture in the direction of clamping. `?GL_REPEAT'
+%% causes the integer part of the s coordinate to be ignored; the GL uses only the fractional
+%% part, thereby creating a repeating pattern. `?GL_MIRRORED_REPEAT' causes the s
+%% coordinate to be set to the fractional part of the texture coordinate if the integer part
+%% of s is even; if the integer part of s is odd, then the s texture coordinate is
+%% set to 1-frac(s), where frac(s) represents the fractional part of s. Initially, `?GL_TEXTURE_WRAP_S'
+%% is set to `?GL_REPEAT'.
+%%
+%%
+%%
+%% `?GL_TEXTURE_WRAP_T': Sets the wrap parameter for texture coordinate t to either `?GL_CLAMP_TO_EDGE'
+%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the discussion under `?GL_TEXTURE_WRAP_S'
+%% . Initially, `?GL_TEXTURE_WRAP_T' is set to `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_WRAP_R': Sets the wrap parameter for texture coordinate r to either `?GL_CLAMP_TO_EDGE'
+%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the discussion under `?GL_TEXTURE_WRAP_S'
+%% . Initially, `?GL_TEXTURE_WRAP_R' is set to `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_BORDER_COLOR': The data in `Params' specifies four values that
+%% define the border values that should be used for border texels. If a texel is sampled
+%% from the border of the texture, the values of `?GL_TEXTURE_BORDER_COLOR' are interpreted
+%% as an RGBA color to match the texture's internal format and substituted for the non-existent
+%% texel data. If the texture contains depth components, the first component of `?GL_TEXTURE_BORDER_COLOR'
+%% is interpreted as a depth value. The initial value is (0.0, 0.0, 0.0, 0.0).
+%%
+%% `?GL_TEXTURE_COMPARE_MODE': Specifies the texture comparison mode for currently
+%% bound textures. That is, a texture whose internal format is `?GL_DEPTH_COMPONENT_*';
+%% see {@link gl:texImage2D/9} ) Permissible values are:
+%%
+%% `?GL_COMPARE_REF_TO_TEXTURE': Specifies that the interpolated and clamped r texture
+%% coordinate should be compared to the value in the currently bound texture. See the discussion
+%% of `?GL_TEXTURE_COMPARE_FUNC' for details of how the comparison is evaluated. The
+%% result of the comparison is assigned to the red channel.
+%%
+%% `?GL_NONE': Specifies that the red channel should be assigned the appropriate value
+%% from the currently bound texture.
+%%
+%% `?GL_TEXTURE_COMPARE_FUNC': Specifies the comparison operator used when `?GL_TEXTURE_COMPARE_MODE'
+%% is set to `?GL_COMPARE_REF_TO_TEXTURE'. Permissible values are: <table><tbody><tr><td>
+%% ` Texture Comparison Function '</td><td>` Computed result '</td></tr></tbody><tbody>
+%% <tr><td>`?GL_LEQUAL'</td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&lt;=(D t) r&gt;(D t))</td></tr><tr><td>`?GL_GEQUAL'</td><td>
+%% result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&gt;=(D t) r&lt;(D t))</td></tr><tr><td>`?GL_LESS'</td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&lt;
+%% (D t) r&gt;=(D t))</td></tr><tr><td>`?GL_GREATER'
+%% </td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&gt;(D t) r&lt;=(D t))</td></tr><tr><td>`?GL_EQUAL'</td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp;
+%% r=(D t) r&amp;ne;(D t))</td></tr><tr><td>`?GL_NOTEQUAL'
+%% </td><td> result={1.0 0.0 &amp;nbsp;&amp;nbsp; r&amp;ne;(D t) r=(D t))</td></tr><tr><td>`?GL_ALWAYS'</td><td> result= 1.0</td></tr><tr><td>
+%% `?GL_NEVER'</td><td> result= 0.0</td></tr></tbody></table> where r is the current
+%% interpolated texture coordinate, and D t is the texture value sampled from the currently
+%% bound texture. result is assigned to R t.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation.
+-spec samplerParameteri(Sampler, Pname, Param) -> ok when Sampler :: integer(),Pname :: enum(),Param :: integer().
samplerParameteri(Sampler,Pname,Param) ->
cast(5713, <<Sampler:?GLuint,Pname:?GLenum,Param:?GLint>>).
-%% @spec (Sampler::integer(),Pname::enum(),Param::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation.
--spec samplerParameteriv(integer(),enum(),[integer()]) -> ok.
+%% @doc
+%% See {@link samplerParameteri/3}
+-spec samplerParameteriv(Sampler, Pname, Param) -> ok when Sampler :: integer(),Pname :: enum(),Param :: [integer()].
samplerParameteriv(Sampler,Pname,Param) ->
cast(5714, <<Sampler:?GLuint,Pname:?GLenum,(length(Param)):?GLuint,
(<< <<C:?GLint>> || C <- Param>>)/binary,0:(((1+length(Param)) rem 2)*32)>>).
-%% @spec (Sampler::integer(),Pname::enum(),Param::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation.
--spec samplerParameterf(integer(),enum(),float()) -> ok.
+%% @doc
+%% See {@link samplerParameteri/3}
+-spec samplerParameterf(Sampler, Pname, Param) -> ok when Sampler :: integer(),Pname :: enum(),Param :: float().
samplerParameterf(Sampler,Pname,Param) ->
cast(5715, <<Sampler:?GLuint,Pname:?GLenum,Param:?GLfloat>>).
-%% @spec (Sampler::integer(),Pname::enum(),Param::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation.
--spec samplerParameterfv(integer(),enum(),[float()]) -> ok.
+%% @doc
+%% See {@link samplerParameteri/3}
+-spec samplerParameterfv(Sampler, Pname, Param) -> ok when Sampler :: integer(),Pname :: enum(),Param :: [float()].
samplerParameterfv(Sampler,Pname,Param) ->
cast(5716, <<Sampler:?GLuint,Pname:?GLenum,(length(Param)):?GLuint,
(<< <<C:?GLfloat>> || C <- Param>>)/binary,0:(((1+length(Param)) rem 2)*32)>>).
-%% @spec (Sampler::integer(),Pname::enum(),Param::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameterI.xml">external</a> documentation.
--spec samplerParameterIiv(integer(),enum(),[integer()]) -> ok.
+%% @doc
+%% See {@link samplerParameteri/3}
+-spec samplerParameterIiv(Sampler, Pname, Param) -> ok when Sampler :: integer(),Pname :: enum(),Param :: [integer()].
samplerParameterIiv(Sampler,Pname,Param) ->
cast(5717, <<Sampler:?GLuint,Pname:?GLenum,(length(Param)):?GLuint,
(<< <<C:?GLint>> || C <- Param>>)/binary,0:(((1+length(Param)) rem 2)*32)>>).
-%% @spec (Sampler::integer(),Pname::enum(),Param::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameterI.xml">external</a> documentation.
--spec samplerParameterIuiv(integer(),enum(),[integer()]) -> ok.
+%% @doc glSamplerParameterI
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameterI.xml">external</a> documentation.
+-spec samplerParameterIuiv(Sampler, Pname, Param) -> ok when Sampler :: integer(),Pname :: enum(),Param :: [integer()].
samplerParameterIuiv(Sampler,Pname,Param) ->
cast(5718, <<Sampler:?GLuint,Pname:?GLenum,(length(Param)):?GLuint,
(<< <<C:?GLuint>> || C <- Param>>)/binary,0:(((1+length(Param)) rem 2)*32)>>).
-%% @spec (Sampler::integer(),Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameter.xml">external</a> documentation.
--spec getSamplerParameteriv(integer(),enum()) -> [integer()].
+%% @doc Return sampler parameter values
+%%
+%% ``gl:getSamplerParameter'' returns in `Params' the value or values of the sampler
+%% parameter specified as `Pname' . `Sampler' defines the target sampler, and must
+%% be the name of an existing sampler object, returned from a previous call to {@link gl:genSamplers/1}
+%% . `Pname' accepts the same symbols as {@link gl:samplerParameteri/3} , with the same
+%% interpretations:
+%%
+%% `?GL_TEXTURE_MAG_FILTER': Returns the single-valued texture magnification filter,
+%% a symbolic constant. The initial value is `?GL_LINEAR'.
+%%
+%% `?GL_TEXTURE_MIN_FILTER': Returns the single-valued texture minification filter,
+%% a symbolic constant. The initial value is `?GL_NEAREST_MIPMAP_LINEAR'.
+%%
+%% `?GL_TEXTURE_MIN_LOD': Returns the single-valued texture minimum level-of-detail
+%% value. The initial value is -1000.
+%%
+%% `?GL_TEXTURE_MAX_LOD': Returns the single-valued texture maximum level-of-detail
+%% value. The initial value is 1000.
+%%
+%% `?GL_TEXTURE_WRAP_S': Returns the single-valued wrapping function for texture coordinate
+%% s, a symbolic constant. The initial value is `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_WRAP_T': Returns the single-valued wrapping function for texture coordinate
+%% t, a symbolic constant. The initial value is `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_WRAP_R': Returns the single-valued wrapping function for texture coordinate
+%% r, a symbolic constant. The initial value is `?GL_REPEAT'.
+%%
+%% `?GL_TEXTURE_BORDER_COLOR': Returns four integer or floating-point numbers that
+%% comprise the RGBA color of the texture border. Floating-point values are returned in the
+%% range [0 1]. Integer values are returned as a linear mapping of the internal floating-point
+%% representation such that 1.0 maps to the most positive representable integer and -1.0
+%% maps to the most negative representable integer. The initial value is (0, 0, 0, 0).
+%%
+%% `?GL_TEXTURE_COMPARE_MODE': Returns a single-valued texture comparison mode, a symbolic
+%% constant. The initial value is `?GL_NONE'. See {@link gl:samplerParameteri/3} .
+%%
+%% `?GL_TEXTURE_COMPARE_FUNC': Returns a single-valued texture comparison function,
+%% a symbolic constant. The initial value is `?GL_LEQUAL'. See {@link gl:samplerParameteri/3}
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameter.xml">external</a> documentation.
+-spec getSamplerParameteriv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum().
getSamplerParameteriv(Sampler,Pname) ->
call(5719, <<Sampler:?GLuint,Pname:?GLenum>>).
-%% @spec (Sampler::integer(),Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameterI.xml">external</a> documentation.
--spec getSamplerParameterIiv(integer(),enum()) -> [integer()].
+%% @doc
+%% See {@link getSamplerParameteriv/2}
+-spec getSamplerParameterIiv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum().
getSamplerParameterIiv(Sampler,Pname) ->
call(5720, <<Sampler:?GLuint,Pname:?GLenum>>).
-%% @spec (Sampler::integer(),Pname::enum()) -> [float()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameter.xml">external</a> documentation.
--spec getSamplerParameterfv(integer(),enum()) -> [float()].
+%% @doc
+%% See {@link getSamplerParameteriv/2}
+-spec getSamplerParameterfv(Sampler, Pname) -> [float()] when Sampler :: integer(),Pname :: enum().
getSamplerParameterfv(Sampler,Pname) ->
call(5721, <<Sampler:?GLuint,Pname:?GLenum>>).
-%% @spec (Sampler::integer(),Pname::enum()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameterI.xml">external</a> documentation.
--spec getSamplerParameterIuiv(integer(),enum()) -> [integer()].
+%% @doc glGetSamplerParameterI
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameterI.xml">external</a> documentation.
+-spec getSamplerParameterIuiv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum().
getSamplerParameterIuiv(Sampler,Pname) ->
call(5722, <<Sampler:?GLuint,Pname:?GLenum>>).
-%% @spec (Id::integer(),Target::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glQueryCounter.xml">external</a> documentation.
--spec queryCounter(integer(),enum()) -> ok.
+%% @doc Record the GL time into a query object after all previous commands have reached the GL server but have not yet necessarily executed.
+%%
+%% ``gl:queryCounter'' causes the GL to record the current time into the query object named
+%% `Id' . `Target' must be `?GL_TIMESTAMP'. The time is recorded after all
+%% previous commands on the GL client and server state and the framebuffer have been fully
+%% realized. When the time is recorded, the query result for that object is marked available.
+%% ``gl:queryCounter'' timer queries can be used within a {@link gl:beginQuery/2} / {@link gl:beginQuery/2}
+%% block where the target is `?GL_TIME_ELAPSED' and it does not affect the result of
+%% that query object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glQueryCounter.xml">external</a> documentation.
+-spec queryCounter(Id, Target) -> ok when Id :: integer(),Target :: enum().
queryCounter(Id,Target) ->
cast(5723, <<Id:?GLuint,Target:?GLenum>>).
-%% @spec (Id::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjecti64v.xml">external</a> documentation.
--spec getQueryObjecti64v(integer(),enum()) -> integer().
+%% @doc glGetQueryObjecti64v
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjecti64v.xml">external</a> documentation.
+-spec getQueryObjecti64v(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjecti64v(Id,Pname) ->
call(5724, <<Id:?GLuint,Pname:?GLenum>>).
-%% @spec (Id::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjectui64v.xml">external</a> documentation.
--spec getQueryObjectui64v(integer(),enum()) -> integer().
+%% @doc glGetQueryObjectui64v
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjectui64v.xml">external</a> documentation.
+-spec getQueryObjectui64v(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjectui64v(Id,Pname) ->
call(5725, <<Id:?GLuint,Pname:?GLenum>>).
-%% @spec (Mode::enum(),Indirect::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysIndirect.xml">external</a> documentation.
--spec drawArraysIndirect(enum(),offset()|mem()) -> ok.
+%% @doc Render primitives from array data, taking parameters from memory
+%%
+%% ``gl:drawArraysIndirect'' specifies multiple geometric primitives with very few subroutine
+%% calls. ``gl:drawArraysIndirect'' behaves similarly to {@link gl:drawArraysInstancedBaseInstance/5}
+%% , execept that the parameters to {@link gl:drawArraysInstancedBaseInstance/5} are stored
+%% in memory at the address given by `Indirect' .
+%%
+%% The parameters addressed by `Indirect' are packed into a structure that takes the
+%% form (in C): typedef struct { uint count; uint primCount; uint first; uint baseInstance;
+%% } DrawArraysIndirectCommand; const DrawArraysIndirectCommand *cmd = (const DrawArraysIndirectCommand
+%% *)indirect; glDrawArraysInstancedBaseInstance(mode, cmd-&gt;first, cmd-&gt;count, cmd-&gt;primCount,
+%% cmd-&gt;baseInstance);
+%%
+%% If a buffer is bound to the `?GL_DRAW_INDIRECT_BUFFER' binding at the time of a
+%% call to ``gl:drawArraysIndirect'', `Indirect' is interpreted as an offset, in basic
+%% machine units, into that buffer and the parameter data is read from the buffer rather
+%% than from client memory.
+%%
+%% In contrast to {@link gl:drawArraysInstancedBaseInstance/5} , the first member of the parameter
+%% structure is unsigned, and out-of-range indices do not generate an error.
+%%
+%% Vertex attributes that are modified by ``gl:drawArraysIndirect'' have an unspecified
+%% value after ``gl:drawArraysIndirect'' returns. Attributes that aren't modified remain
+%% well defined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysIndirect.xml">external</a> documentation.
+-spec drawArraysIndirect(Mode, Indirect) -> ok when Mode :: enum(),Indirect :: offset()|mem().
drawArraysIndirect(Mode,Indirect) when is_integer(Indirect) ->
cast(5726, <<Mode:?GLenum,Indirect:?GLuint>>);
drawArraysIndirect(Mode,Indirect) ->
send_bin(Indirect),
cast(5727, <<Mode:?GLenum>>).
-%% @spec (Mode::enum(),Type::enum(),Indirect::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsIndirect.xml">external</a> documentation.
--spec drawElementsIndirect(enum(),enum(),offset()|mem()) -> ok.
+%% @doc Render indexed primitives from array data, taking parameters from memory
+%%
+%% ``gl:drawElementsIndirect'' specifies multiple indexed geometric primitives with very
+%% few subroutine calls. ``gl:drawElementsIndirect'' behaves similarly to {@link gl:drawElementsInstancedBaseVertexBaseInstance/7}
+%% , execpt that the parameters to {@link gl:drawElementsInstancedBaseVertexBaseInstance/7}
+%% are stored in memory at the address given by `Indirect' .
+%%
+%% The parameters addressed by `Indirect' are packed into a structure that takes the
+%% form (in C): typedef struct { uint count; uint primCount; uint firstIndex; uint baseVertex;
+%% uint baseInstance; } DrawElementsIndirectCommand;
+%%
+%% ``gl:drawElementsIndirect'' is equivalent to: void glDrawElementsIndirect(GLenum mode,
+%% GLenum type, const void * indirect) { const DrawElementsIndirectCommand *cmd = (const
+%% DrawElementsIndirectCommand *)indirect; glDrawElementsInstancedBaseVertexBaseInstance(mode,
+%% cmd-&gt;count, type, cmd-&gt;firstIndex + size-of-type, cmd-&gt;primCount, cmd-&gt;baseVertex,
+%% cmd-&gt;baseInstance); }
+%%
+%% If a buffer is bound to the `?GL_DRAW_INDIRECT_BUFFER' binding at the time of a
+%% call to ``gl:drawElementsIndirect'', `Indirect' is interpreted as an offset, in
+%% basic machine units, into that buffer and the parameter data is read from the buffer rather
+%% than from client memory.
+%%
+%% Note that indices stored in client memory are not supported. If no buffer is bound to
+%% the `?GL_ELEMENT_ARRAY_BUFFER' binding, an error will be generated.
+%%
+%% The results of the operation are undefined if the reservedMustBeZero member of the parameter
+%% structure is non-zero. However, no error is generated in this case.
+%%
+%% Vertex attributes that are modified by ``gl:drawElementsIndirect'' have an unspecified
+%% value after ``gl:drawElementsIndirect'' returns. Attributes that aren't modified remain
+%% well defined.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsIndirect.xml">external</a> documentation.
+-spec drawElementsIndirect(Mode, Type, Indirect) -> ok when Mode :: enum(),Type :: enum(),Indirect :: offset()|mem().
drawElementsIndirect(Mode,Type,Indirect) when is_integer(Indirect) ->
cast(5728, <<Mode:?GLenum,Type:?GLenum,Indirect:?GLuint>>);
drawElementsIndirect(Mode,Type,Indirect) ->
send_bin(Indirect),
cast(5729, <<Mode:?GLenum,Type:?GLenum>>).
-%% @spec (Location::integer(),X::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1d(integer(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1d(Location, X) -> ok when Location :: integer(),X :: float().
uniform1d(Location,X) ->
cast(5730, <<Location:?GLint,0:32,X:?GLdouble>>).
-%% @spec (Location::integer(),X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2d(integer(),float(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2d(Location, X, Y) -> ok when Location :: integer(),X :: float(),Y :: float().
uniform2d(Location,X,Y) ->
cast(5731, <<Location:?GLint,0:32,X:?GLdouble,Y:?GLdouble>>).
-%% @spec (Location::integer(),X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3d(integer(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3d(Location, X, Y, Z) -> ok when Location :: integer(),X :: float(),Y :: float(),Z :: float().
uniform3d(Location,X,Y,Z) ->
cast(5732, <<Location:?GLint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Location::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4d(integer(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4d(Location, X, Y, Z, W) -> ok when Location :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
uniform4d(Location,X,Y,Z,W) ->
cast(5733, <<Location:?GLint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-%% @spec (Location::integer(),Value::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform1dv(integer(),[float()]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform1dv(Location, Value) -> ok when Location :: integer(),Value :: [float()].
uniform1dv(Location,Value) ->
cast(5734, <<Location:?GLint,0:32,(length(Value)):?GLuint,0:32,
(<< <<C:?GLdouble>> || C <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform2dv(integer(),[{float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform2dv(Location, Value) -> ok when Location :: integer(),Value :: [{float(),float()}].
uniform2dv(Location,Value) ->
cast(5735, <<Location:?GLint,0:32,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform3dv(integer(),[{float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform3dv(Location, Value) -> ok when Location :: integer(),Value :: [{float(),float(),float()}].
uniform3dv(Location,Value) ->
cast(5736, <<Location:?GLint,0:32,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
--spec uniform4dv(integer(),[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniform4dv(Location, Value) -> ok when Location :: integer(),Value :: [{float(),float(),float(),float()}].
uniform4dv(Location,Value) ->
cast(5737, <<Location:?GLint,0:32,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix.xml">external</a> documentation.
--spec uniformMatrix2dv(integer(),0|1,[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix2dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float()}].
uniformMatrix2dv(Location,Transpose,Value) ->
cast(5738, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix.xml">external</a> documentation.
--spec uniformMatrix3dv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix3dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix3dv(Location,Transpose,Value) ->
cast(5739, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix.xml">external</a> documentation.
--spec uniformMatrix4dv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix4dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix4dv(Location,Transpose,Value) ->
cast(5740, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble,V10:?GLdouble,V11:?GLdouble,V12:?GLdouble,V13:?GLdouble,V14:?GLdouble,V15:?GLdouble,V16:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix2x.xml">external</a> documentation.
--spec uniformMatrix2x3dv(integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix2x3dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
uniformMatrix2x3dv(Location,Transpose,Value) ->
cast(5741, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix2x.xml">external</a> documentation.
--spec uniformMatrix2x4dv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix2x4dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix2x4dv(Location,Transpose,Value) ->
cast(5742, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix3x.xml">external</a> documentation.
--spec uniformMatrix3x2dv(integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix3x2dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
uniformMatrix3x2dv(Location,Transpose,Value) ->
cast(5743, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix3x.xml">external</a> documentation.
--spec uniformMatrix3x4dv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix3x4dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix3x4dv(Location,Transpose,Value) ->
cast(5744, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble,V10:?GLdouble,V11:?GLdouble,V12:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix4x.xml">external</a> documentation.
--spec uniformMatrix4x2dv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix4x2dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix4x2dv(Location,Transpose,Value) ->
cast(5745, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformMatrix4x.xml">external</a> documentation.
--spec uniformMatrix4x3dv(integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link uniform1f/2}
+-spec uniformMatrix4x3dv(Location, Transpose, Value) -> ok when Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
uniformMatrix4x3dv(Location,Transpose,Value) ->
cast(5746, <<Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble,V10:?GLdouble,V11:?GLdouble,V12:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer()) -> {float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation.
--spec getUniformdv(integer(),integer()) -> {float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}.
+%% @doc
+%% See {@link getUniformfv/2}
+-spec getUniformdv(Program, Location) -> matrix() when Program :: integer(),Location :: integer().
getUniformdv(Program,Location) ->
call(5747, <<Program:?GLuint,Location:?GLint>>).
-%% @spec (Program::integer(),Shadertype::enum(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineUniformLocation.xml">external</a> documentation.
--spec getSubroutineUniformLocation(integer(),enum(),string()) -> integer().
+%% @doc Retrieve the location of a subroutine uniform of a given shader stage within a program
+%%
+%% ``gl:getSubroutineUniformLocation'' returns the location of the subroutine uniform variable
+%% `Name' in the shader stage of type `Shadertype' attached to `Program' ,
+%% with behavior otherwise identical to {@link gl:getUniformLocation/2} .
+%%
+%% If `Name' is not the name of a subroutine uniform in the shader stage, -1 is returned,
+%% but no error is generated. If `Name' is the name of a subroutine uniform in the shader
+%% stage, a value between zero and the value of `?GL_ACTIVE_SUBROUTINE_LOCATIONS' minus
+%% one will be returned. Subroutine locations are assigned using consecutive integers in
+%% the range from zero to the value of `?GL_ACTIVE_SUBROUTINE_LOCATIONS' minus one for
+%% the shader stage. For active subroutine uniforms declared as arrays, the declared array
+%% elements are assigned consecutive locations.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineUniformLocation.xml">external</a> documentation.
+-spec getSubroutineUniformLocation(Program, Shadertype, Name) -> integer() when Program :: integer(),Shadertype :: enum(),Name :: string().
getSubroutineUniformLocation(Program,Shadertype,Name) ->
call(5748, <<Program:?GLuint,Shadertype:?GLenum,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),Shadertype::enum(),Name::string()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineIndex.xml">external</a> documentation.
--spec getSubroutineIndex(integer(),enum(),string()) -> integer().
+%% @doc Retrieve the index of a subroutine uniform of a given shader stage within a program
+%%
+%% ``gl:getSubroutineIndex'' returns the index of a subroutine uniform within a shader
+%% stage attached to a program object. `Program' contains the name of the program to
+%% which the shader is attached. `Shadertype' specifies the stage from which to query
+%% shader subroutine index. `Name' contains the null-terminated name of the subroutine
+%% uniform whose name to query.
+%%
+%% If `Name' is not the name of a subroutine uniform in the shader stage, `?GL_INVALID_INDEX'
+%% is returned, but no error is generated. If `Name' is the name of a subroutine uniform
+%% in the shader stage, a value between zero and the value of `?GL_ACTIVE_SUBROUTINES'
+%% minus one will be returned. Subroutine indices are assigned using consecutive integers
+%% in the range from zero to the value of `?GL_ACTIVE_SUBROUTINES' minus one for the
+%% shader stage.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineIndex.xml">external</a> documentation.
+-spec getSubroutineIndex(Program, Shadertype, Name) -> integer() when Program :: integer(),Shadertype :: enum(),Name :: string().
getSubroutineIndex(Program,Shadertype,Name) ->
call(5749, <<Program:?GLuint,Shadertype:?GLenum,(list_to_binary([Name|[0]]))/binary,0:((8-((length(Name)+ 1) rem 8)) rem 8)>>).
-%% @spec (Program::integer(),Shadertype::enum(),Index::integer(),Bufsize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineUniformName.xml">external</a> documentation.
--spec getActiveSubroutineUniformName(integer(),enum(),integer(),integer()) -> string().
+%% @doc Query the name of an active shader subroutine uniform
+%%
+%% ``gl:getActiveSubroutineUniformName'' retrieves the name of an active shader subroutine
+%% uniform. `Program' contains the name of the program containing the uniform. `Shadertype'
+%% specifies the stage for which which the uniform location, given by `Index' , is valid.
+%% `Index' must be between zero and the value of `?GL_ACTIVE_SUBROUTINE_UNIFORMS'
+%% minus one for the shader stage.
+%%
+%% The uniform name is returned as a null-terminated string in `Name' . The actual number
+%% of characters written into `Name' , excluding the null terminator is returned in `Length'
+%% . If `Length' is `?NULL', no length is returned. The maximum number of characters
+%% that may be written into `Name' , including the null terminator, is specified by `Bufsize'
+%% . The length of the longest subroutine uniform name in `Program' and `Shadertype'
+%% is given by the value of `?GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH', which can be
+%% queried with {@link gl:getProgramStageiv/3} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineUniformName.xml">external</a> documentation.
+-spec getActiveSubroutineUniformName(Program, Shadertype, Index, Bufsize) -> string() when Program :: integer(),Shadertype :: enum(),Index :: integer(),Bufsize :: integer().
getActiveSubroutineUniformName(Program,Shadertype,Index,Bufsize) ->
call(5750, <<Program:?GLuint,Shadertype:?GLenum,Index:?GLuint,Bufsize:?GLsizei>>).
-%% @spec (Program::integer(),Shadertype::enum(),Index::integer(),Bufsize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineName.xml">external</a> documentation.
--spec getActiveSubroutineName(integer(),enum(),integer(),integer()) -> string().
+%% @doc Query the name of an active shader subroutine
+%%
+%% ``gl:getActiveSubroutineName'' queries the name of an active shader subroutine uniform
+%% from the program object given in `Program' . `Index' specifies the index of the
+%% shader subroutine uniform within the shader stage given by `Stage' , and must between
+%% zero and the value of `?GL_ACTIVE_SUBROUTINES' minus one for the shader stage.
+%%
+%% The name of the selected subroutine is returned as a null-terminated string in `Name'
+%% . The actual number of characters written into `Name' , not including the null-terminator,
+%% is is returned in `Length' . If `Length' is `?NULL', no length is returned.
+%% The maximum number of characters that may be written into `Name' , including the null-terminator,
+%% is given in `Bufsize' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineName.xml">external</a> documentation.
+-spec getActiveSubroutineName(Program, Shadertype, Index, Bufsize) -> string() when Program :: integer(),Shadertype :: enum(),Index :: integer(),Bufsize :: integer().
getActiveSubroutineName(Program,Shadertype,Index,Bufsize) ->
call(5751, <<Program:?GLuint,Shadertype:?GLenum,Index:?GLuint,Bufsize:?GLsizei>>).
-%% @spec (Shadertype::enum(),Indices::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformSubroutines.xml">external</a> documentation.
--spec uniformSubroutinesuiv(enum(),[integer()]) -> ok.
+%% @doc Load active subroutine uniforms
+%%
+%% ``gl:uniformSubroutines'' loads all active subroutine uniforms for shader stage `Shadertype'
+%% of the current program with subroutine indices from `Indices' , storing `Indices[i]'
+%% into the uniform at location `I' . `Count' must be equal to the value of `?GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS'
+%% for the program currently in use at shader stage `Shadertype' . Furthermore, all
+%% values in `Indices' must be less than the value of `?GL_ACTIVE_SUBROUTINES'
+%% for the shader stage.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformSubroutines.xml">external</a> documentation.
+-spec uniformSubroutinesuiv(Shadertype, Indices) -> ok when Shadertype :: enum(),Indices :: [integer()].
uniformSubroutinesuiv(Shadertype,Indices) ->
cast(5752, <<Shadertype:?GLenum,(length(Indices)):?GLuint,
(<< <<C:?GLuint>> || C <- Indices>>)/binary,0:(((length(Indices)) rem 2)*32)>>).
-%% @spec (Shadertype::enum(),Location::integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformSubroutine.xml">external</a> documentation.
--spec getUniformSubroutineuiv(enum(),integer()) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()}.
+%% @doc Retrieve the value of a subroutine uniform of a given shader stage of the current program
+%%
+%% ``gl:getUniformSubroutine'' retrieves the value of the subroutine uniform at location `Location'
+%% for shader stage `Shadertype' of the current program. `Location' must be less
+%% than the value of `?GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS' for the shader currently
+%% in use at shader stage `Shadertype' . The value of the subroutine uniform is returned
+%% in `Values' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformSubroutine.xml">external</a> documentation.
+-spec getUniformSubroutineuiv(Shadertype, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when Shadertype :: enum(),Location :: integer().
getUniformSubroutineuiv(Shadertype,Location) ->
call(5753, <<Shadertype:?GLenum,Location:?GLint>>).
-%% @spec (Program::integer(),Shadertype::enum(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStage.xml">external</a> documentation.
--spec getProgramStageiv(integer(),enum(),enum()) -> integer().
+%% @doc Retrieve properties of a program object corresponding to a specified shader stage
+%%
+%% ``gl:getProgramStage'' queries a parameter of a shader stage attached to a program object.
+%% `Program' contains the name of the program to which the shader is attached. `Shadertype'
+%% specifies the stage from which to query the parameter. `Pname' specifies which parameter
+%% should be queried. The value or values of the parameter to be queried is returned in the
+%% variable whose address is given in `Values' .
+%%
+%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORMS', the number of active subroutine
+%% variables in the stage is returned in `Values' .
+%%
+%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS', the number of active
+%% subroutine variable locations in the stage is returned in `Values' .
+%%
+%% If `Pname' is `?GL_ACTIVE_SUBROUTINES', the number of active subroutines in
+%% the stage is returned in `Values' .
+%%
+%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH', the length of the
+%% longest subroutine uniform for the stage is returned in `Values' .
+%%
+%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_MAX_LENGTH', the length of the longest
+%% subroutine name for the stage is returned in `Values' . The returned name length includes
+%% space for the null-terminator.
+%%
+%% If there is no shader present of type `Shadertype' , the returned value will be consistent
+%% with a shader containing no subroutines or subroutine uniforms.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStage.xml">external</a> documentation.
+-spec getProgramStageiv(Program, Shadertype, Pname) -> integer() when Program :: integer(),Shadertype :: enum(),Pname :: enum().
getProgramStageiv(Program,Shadertype,Pname) ->
call(5754, <<Program:?GLuint,Shadertype:?GLenum,Pname:?GLenum>>).
-%% @spec (Pname::enum(),Value::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPatchParameter.xml">external</a> documentation.
--spec patchParameteri(enum(),integer()) -> ok.
+%% @doc Specifies the parameters for patch primitives
+%%
+%% ``gl:patchParameter'' specifies the parameters that will be used for patch primitives. `Pname'
+%% specifies the parameter to modify and must be either `?GL_PATCH_VERTICES', `?GL_PATCH_DEFAULT_OUTER_LEVEL'
+%% or `?GL_PATCH_DEFAULT_INNER_LEVEL'. For ``gl:patchParameteri'', `Value' specifies
+%% the new value for the parameter specified by `Pname' . For ``gl:patchParameterfv'',
+%% `Values' specifies the address of an array containing the new values for the parameter
+%% specified by `Pname' .
+%%
+%% When `Pname' is `?GL_PATCH_VERTICES', `Value' specifies the number of
+%% vertices that will be used to make up a single patch primitive. Patch primitives are consumed
+%% by the tessellation control shader (if present) and subsequently used for tessellation.
+%% When primitives are specified using {@link gl:drawArrays/3} or a similar function, each
+%% patch will be made from `Parameter' control points, each represented by a vertex
+%% taken from the enabeld vertex arrays. `Parameter' must be greater than zero, and
+%% less than or equal to the value of `?GL_MAX_PATCH_VERTICES'.
+%%
+%% When `Pname' is `?GL_PATCH_DEFAULT_OUTER_LEVEL' or `?GL_PATCH_DEFAULT_INNER_LEVEL'
+%% , `Values' contains the address of an array contiaining the default outer or inner
+%% tessellation levels, respectively, to be used when no tessellation control shader is present.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPatchParameter.xml">external</a> documentation.
+-spec patchParameteri(Pname, Value) -> ok when Pname :: enum(),Value :: integer().
patchParameteri(Pname,Value) ->
cast(5755, <<Pname:?GLenum,Value:?GLint>>).
-%% @spec (Pname::enum(),Values::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPatchParameter.xml">external</a> documentation.
--spec patchParameterfv(enum(),[float()]) -> ok.
+%% @doc
+%% See {@link patchParameteri/2}
+-spec patchParameterfv(Pname, Values) -> ok when Pname :: enum(),Values :: [float()].
patchParameterfv(Pname,Values) ->
cast(5756, <<Pname:?GLenum,(length(Values)):?GLuint,
(<< <<C:?GLfloat>> || C <- Values>>)/binary,0:(((length(Values)) rem 2)*32)>>).
-%% @spec (Target::enum(),Id::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTransformFeedback.xml">external</a> documentation.
--spec bindTransformFeedback(enum(),integer()) -> ok.
+%% @doc Bind a transform feedback object
+%%
+%% ``gl:bindTransformFeedback'' binds the transform feedback object with name `Id'
+%% to the current GL state. `Id' must be a name previously returned from a call to {@link gl:genTransformFeedbacks/1}
+%% . If `Id' has not previously been bound, a new transform feedback object with name `Id'
+%% and initialized with with the default transform state vector is created.
+%%
+%% In the initial state, a default transform feedback object is bound and treated as a transform
+%% feedback object with a name of zero. If the name zero is subsequently bound, the default
+%% transform feedback object is again bound to the GL state.
+%%
+%% While a transform feedback buffer object is bound, GL operations on the target to which
+%% it is bound affect the bound transform feedback object, and queries of the target to which
+%% a transform feedback object is bound return state from the bound object. When buffer objects
+%% are bound for transform feedback, they are attached to the currently bound transform feedback
+%% object. Buffer objects are used for trans- form feedback only if they are attached to
+%% the currently bound transform feedback object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTransformFeedback.xml">external</a> documentation.
+-spec bindTransformFeedback(Target, Id) -> ok when Target :: enum(),Id :: integer().
bindTransformFeedback(Target,Id) ->
cast(5757, <<Target:?GLenum,Id:?GLuint>>).
-%% @spec (Ids::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTransformFeedbacks.xml">external</a> documentation.
--spec deleteTransformFeedbacks([integer()]) -> ok.
+%% @doc Delete transform feedback objects
+%%
+%% ``gl:deleteTransformFeedbacks'' deletes the `N' transform feedback objects whose
+%% names are stored in the array `Ids' . Unused names in `Ids' are ignored, as is
+%% the name zero. After a transform feedback object is deleted, its name is again unused
+%% and it has no contents. If an active transform feedback object is deleted, its name immediately
+%% becomes unused, but the underlying object is not deleted until it is no longer active.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTransformFeedbacks.xml">external</a> documentation.
+-spec deleteTransformFeedbacks(Ids) -> ok when Ids :: [integer()].
deleteTransformFeedbacks(Ids) ->
cast(5758, <<(length(Ids)):?GLuint,
(<< <<C:?GLuint>> || C <- Ids>>)/binary,0:(((1+length(Ids)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTransformFeedbacks.xml">external</a> documentation.
--spec genTransformFeedbacks(integer()) -> [integer()].
+%% @doc Reserve transform feedback object names
+%%
+%% ``gl:genTransformFeedbacks'' returns `N' previously unused transform feedback object
+%% names in `Ids' . These names are marked as used, for the purposes of ``gl:genTransformFeedbacks''
+%% only, but they acquire transform feedback state only when they are first bound.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTransformFeedbacks.xml">external</a> documentation.
+-spec genTransformFeedbacks(N) -> [integer()] when N :: integer().
genTransformFeedbacks(N) ->
call(5759, <<N:?GLsizei>>).
-%% @spec (Id::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTransformFeedback.xml">external</a> documentation.
--spec isTransformFeedback(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a transform feedback object
+%%
+%% ``gl:isTransformFeedback'' returns `?GL_TRUE' if `Id' is currently the name
+%% of a transform feedback object. If `Id' is zero, or if `?id' is not the name
+%% of a transform feedback object, or if an error occurs, ``gl:isTransformFeedback'' returns
+%% `?GL_FALSE'. If `Id' is a name returned by {@link gl:genTransformFeedbacks/1} ,
+%% but that has not yet been bound through a call to {@link gl:bindTransformFeedback/2} , then
+%% the name is not a transform feedback object and ``gl:isTransformFeedback'' returns `?GL_FALSE'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTransformFeedback.xml">external</a> documentation.
+-spec isTransformFeedback(Id) -> 0|1 when Id :: integer().
isTransformFeedback(Id) ->
call(5760, <<Id:?GLuint>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPauseTransformFeedback.xml">external</a> documentation.
+%% @doc Pause transform feedback operations
+%%
+%% ``gl:pauseTransformFeedback'' pauses transform feedback operations on the currently
+%% active transform feedback object. When transform feedback operations are paused, transform
+%% feedback is still considered active and changing most transform feedback state related
+%% to the object results in an error. However, a new transform feedback object may be bound
+%% while transform feedback is paused.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPauseTransformFeedback.xml">external</a> documentation.
-spec pauseTransformFeedback() -> ok.
pauseTransformFeedback() ->
cast(5761, <<>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResumeTransformFeedback.xml">external</a> documentation.
+%% @doc Resume transform feedback operations
+%%
+%% ``gl:resumeTransformFeedback'' resumes transform feedback operations on the currently
+%% active transform feedback object. When transform feedback operations are paused, transform
+%% feedback is still considered active and changing most transform feedback state related
+%% to the object results in an error. However, a new transform feedback object may be bound
+%% while transform feedback is paused.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResumeTransformFeedback.xml">external</a> documentation.
-spec resumeTransformFeedback() -> ok.
resumeTransformFeedback() ->
cast(5762, <<>>).
-%% @spec (Mode::enum(),Id::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedback.xml">external</a> documentation.
--spec drawTransformFeedback(enum(),integer()) -> ok.
+%% @doc Render primitives using a count derived from a transform feedback object
+%%
+%% ``gl:drawTransformFeedback'' draws primitives of a type specified by `Mode' using
+%% a count retrieved from the transform feedback specified by `Id' . Calling ``gl:drawTransformFeedback''
+%% is equivalent to calling {@link gl:drawArrays/3} with `Mode' as specified, `First'
+%% set to zero, and `Count' set to the number of vertices captured on vertex stream
+%% zero the last time transform feedback was active on the transform feedback object named
+%% by `Id' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedback.xml">external</a> documentation.
+-spec drawTransformFeedback(Mode, Id) -> ok when Mode :: enum(),Id :: integer().
drawTransformFeedback(Mode,Id) ->
cast(5763, <<Mode:?GLenum,Id:?GLuint>>).
-%% @spec (Mode::enum(),Id::integer(),Stream::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStream.xml">external</a> documentation.
--spec drawTransformFeedbackStream(enum(),integer(),integer()) -> ok.
+%% @doc Render primitives using a count derived from a specifed stream of a transform feedback object
+%%
+%% ``gl:drawTransformFeedbackStream'' draws primitives of a type specified by `Mode'
+%% using a count retrieved from the transform feedback stream specified by `Stream'
+%% of the transform feedback object specified by `Id' . Calling ``gl:drawTransformFeedbackStream''
+%% is equivalent to calling {@link gl:drawArrays/3} with `Mode' as specified, `First'
+%% set to zero, and `Count' set to the number of vertices captured on vertex stream `Stream'
+%% the last time transform feedback was active on the transform feedback object named by `Id'
+%% .
+%%
+%% Calling {@link gl:drawTransformFeedback/2} is equivalent to calling ``gl:drawTransformFeedbackStream''
+%% with `Stream' set to zero.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStream.xml">external</a> documentation.
+-spec drawTransformFeedbackStream(Mode, Id, Stream) -> ok when Mode :: enum(),Id :: integer(),Stream :: integer().
drawTransformFeedbackStream(Mode,Id,Stream) ->
cast(5764, <<Mode:?GLenum,Id:?GLuint,Stream:?GLuint>>).
-%% @spec (Target::enum(),Index::integer(),Id::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexe.xml">external</a> documentation.
--spec beginQueryIndexed(enum(),integer(),integer()) -> ok.
+%% @doc glBeginQueryIndexe
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexe.xml">external</a> documentation.
+-spec beginQueryIndexed(Target, Index, Id) -> ok when Target :: enum(),Index :: integer(),Id :: integer().
beginQueryIndexed(Target,Index,Id) ->
cast(5765, <<Target:?GLenum,Index:?GLuint,Id:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEndQueryIndexe.xml">external</a> documentation.
--spec endQueryIndexed(enum(),integer()) -> ok.
+%% @doc Delimit the boundaries of a query object on an indexed target
+%%
+%% ``gl:beginQueryIndexed'' and {@link gl:endQueryIndexed/2} delimit the boundaries of a
+%% query object. `Query' must be a name previously returned from a call to {@link gl:genQueries/1}
+%% . If a query object with name `Id' does not yet exist it is created with the type
+%% determined by `Target' . `Target' must be one of `?GL_SAMPLES_PASSED', `?GL_ANY_SAMPLES_PASSED'
+%% , `?GL_PRIMITIVES_GENERATED', `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', or `?GL_TIME_ELAPSED'
+%% . The behavior of the query object depends on its type and is as follows.
+%%
+%% `Index' specifies the index of the query target and must be between a `Target' -specific
+%% maximum.
+%%
+%% If `Target' is `?GL_SAMPLES_PASSED', `Id' must be an unused name, or the
+%% name of an existing occlusion query object. When ``gl:beginQueryIndexed'' is executed,
+%% the query object's samples-passed counter is reset to 0. Subsequent rendering will increment
+%% the counter for every sample that passes the depth test. If the value of `?GL_SAMPLE_BUFFERS'
+%% is 0, then the samples-passed count is incremented by 1 for each fragment. If the value
+%% of `?GL_SAMPLE_BUFFERS' is 1, then the samples-passed count is incremented by the
+%% number of samples whose coverage bit is set. However, implementations, at their discression
+%% may instead increase the samples-passed count by the value of `?GL_SAMPLES' if any
+%% sample in the fragment is covered. When ``gl:endQueryIndexed'' is executed, the samples-passed
+%% counter is assigned to the query object's result value. This value can be queried by calling
+%% {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'. When `Target'
+%% is `?GL_SAMPLES_PASSED', `Index' must be zero.
+%%
+%% If `Target' is `?GL_ANY_SAMPLES_PASSED', `Id' must be an unused name,
+%% or the name of an existing boolean occlusion query object. When ``gl:beginQueryIndexed''
+%% is executed, the query object's samples-passed flag is reset to `?GL_FALSE'. Subsequent
+%% rendering causes the flag to be set to `?GL_TRUE' if any sample passes the depth
+%% test. When ``gl:endQueryIndexed'' is executed, the samples-passed flag is assigned to
+%% the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
+%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_ANY_SAMPLES_PASSED'
+%% , `Index' must be zero.
+%%
+%% If `Target' is `?GL_PRIMITIVES_GENERATED', `Id' must be an unused name,
+%% or the name of an existing primitive query object previously bound to the `?GL_PRIMITIVES_GENERATED'
+%% query binding. When ``gl:beginQueryIndexed'' is executed, the query object's primitives-generated
+%% counter is reset to 0. Subsequent rendering will increment the counter once for every
+%% vertex that is emitted from the geometry shader to the stream given by `Index' , or
+%% from the vertex shader if `Index' is zero and no geometry shader is present. When ``gl:endQueryIndexed''
+%% is executed, the primitives-generated counter for stream `Index' is assigned to
+%% the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
+%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_PRIMITIVES_GENERATED'
+%% , `Index' must be less than the value of `?GL_MAX_VERTEX_STREAMS'.
+%%
+%% If `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', `Id' must
+%% be an unused name, or the name of an existing primitive query object previously bound
+%% to the `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' query binding. When ``gl:beginQueryIndexed''
+%% is executed, the query object's primitives-written counter for the stream specified by `Index'
+%% is reset to 0. Subsequent rendering will increment the counter once for every vertex
+%% that is written into the bound transform feedback buffer(s) for stream `Index' . If
+%% transform feedback mode is not activated between the call to ``gl:beginQueryIndexed''
+%% and ``gl:endQueryIndexed'', the counter will not be incremented. When ``gl:endQueryIndexed''
+%% is executed, the primitives-written counter for stream `Index' is assigned to the
+%% query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
+%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN'
+%% , `Index' must be less than the value of `?GL_MAX_VERTEX_STREAMS'.
+%%
+%% If `Target' is `?GL_TIME_ELAPSED', `Id' must be an unused name, or the
+%% name of an existing timer query object previously bound to the `?GL_TIME_ELAPSED'
+%% query binding. When ``gl:beginQueryIndexed'' is executed, the query object's time counter
+%% is reset to 0. When ``gl:endQueryIndexed'' is executed, the elapsed server time that
+%% has passed since the call to ``gl:beginQueryIndexed'' is written into the query object's
+%% time counter. This value can be queried by calling {@link gl:getQueryObjectiv/2} with `Pname'
+%% `?GL_QUERY_RESULT'. When `Target' is `?GL_TIME_ELAPSED', `Index' must
+%% be zero.
+%%
+%% Querying the `?GL_QUERY_RESULT' implicitly flushes the GL pipeline until the rendering
+%% delimited by the query object has completed and the result is available. `?GL_QUERY_RESULT_AVAILABLE'
+%% can be queried to determine if the result is immediately available or if the rendering
+%% is not yet complete.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexed.xml">external</a> documentation.
+-spec endQueryIndexed(Target, Index) -> ok when Target :: enum(),Index :: integer().
endQueryIndexed(Target,Index) ->
cast(5766, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryIndexed.xml">external</a> documentation.
--spec getQueryIndexediv(enum(),integer(),enum()) -> integer().
+%% @doc Return parameters of an indexed query object target
+%%
+%% ``gl:getQueryIndexediv'' returns in `Params' a selected parameter of the indexed
+%% query object target specified by `Target' and `Index' . `Index' specifies
+%% the index of the query object target and must be between zero and a target-specific maxiumum.
+%%
+%%
+%% `Pname' names a specific query object target parameter. When `Pname' is `?GL_CURRENT_QUERY'
+%% , the name of the currently active query for the specified `Index' of `Target' ,
+%% or zero if no query is active, will be placed in `Params' . If `Pname' is `?GL_QUERY_COUNTER_BITS'
+%% , the implementation-dependent number of bits used to hold the result of queries for `Target'
+%% is returned in `Params' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryIndexed.xml">external</a> documentation.
+-spec getQueryIndexediv(Target, Index, Pname) -> integer() when Target :: enum(),Index :: integer(),Pname :: enum().
getQueryIndexediv(Target,Index,Pname) ->
call(5767, <<Target:?GLenum,Index:?GLuint,Pname:?GLenum>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReleaseShaderCompiler.xml">external</a> documentation.
+%% @doc Release resources consumed by the implementation's shader compiler
+%%
+%% ``gl:releaseShaderCompiler'' provides a hint to the implementation that it may free
+%% internal resources associated with its shader compiler. {@link gl:compileShader/1} may
+%% subsequently be called and the implementation may at that time reallocate resources previously
+%% freed by the call to ``gl:releaseShaderCompiler''.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReleaseShaderCompiler.xml">external</a> documentation.
-spec releaseShaderCompiler() -> ok.
releaseShaderCompiler() ->
cast(5768, <<>>).
-%% @spec (Shaders::[integer()],Binaryformat::enum(),Binary::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderBinary.xml">external</a> documentation.
--spec shaderBinary([integer()],enum(),binary()) -> ok.
+%% @doc Load pre-compiled shader binaries
+%%
+%% ``gl:shaderBinary'' loads pre-compiled shader binary code into the `Count' shader
+%% objects whose handles are given in `Shaders' . `Binary' points to `Length'
+%% bytes of binary shader code stored in client memory. `BinaryFormat' specifies the
+%% format of the pre-compiled code.
+%%
+%% The binary image contained in `Binary' will be decoded according to the extension
+%% specification defining the specified `BinaryFormat' token. OpenGL does not define
+%% any specific binary formats, but it does provide a mechanism to obtain token vaues for
+%% such formats provided by such extensions.
+%%
+%% Depending on the types of the shader objects in `Shaders' , ``gl:shaderBinary''
+%% will individually load binary vertex or fragment shaders, or load an executable binary
+%% that contains an optimized pair of vertex and fragment shaders stored in the same binary.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderBinary.xml">external</a> documentation.
+-spec shaderBinary(Shaders, Binaryformat, Binary) -> ok when Shaders :: [integer()],Binaryformat :: enum(),Binary :: binary().
shaderBinary(Shaders,Binaryformat,Binary) ->
send_bin(Binary),
cast(5769, <<(length(Shaders)):?GLuint,
(<< <<C:?GLuint>> || C <- Shaders>>)/binary,0:(((1+length(Shaders)) rem 2)*32),Binaryformat:?GLenum>>).
-%% @spec (Shadertype::enum(),Precisiontype::enum()) -> {Range::{integer(),integer()},Precision::integer()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderPrecisionFormat.xml">external</a> documentation.
--spec getShaderPrecisionFormat(enum(),enum()) -> {{integer(),integer()},integer()}.
+%% @doc Retrieve the range and precision for numeric formats supported by the shader compiler
+%%
+%% ``gl:getShaderPrecisionFormat'' retrieves the numeric range and precision for the implementation's
+%% representation of quantities in different numeric formats in specified shader type. `ShaderType'
+%% specifies the type of shader for which the numeric precision and range is to be retrieved
+%% and must be one of `?GL_VERTEX_SHADER' or `?GL_FRAGMENT_SHADER'. `PrecisionType'
+%% specifies the numeric format to query and must be one of `?GL_LOW_FLOAT', `?GL_MEDIUM_FLOAT'
+%% `?GL_HIGH_FLOAT', `?GL_LOW_INT', `?GL_MEDIUM_INT', or `?GL_HIGH_INT'.
+%%
+%%
+%% `Range' points to an array of two integers into which the format's numeric range
+%% will be returned. If min and max are the smallest values representable in the format,
+%% then the values returned are defined to be: `Range' [0] = floor(log2(|min|)) and `Range'
+%% [1] = floor(log2(|max|)).
+%%
+%% `Precision' specifies the address of an integer into which will be written the log2
+%% value of the number of bits of precision of the format. If the smallest representable
+%% value greater than 1 is 1 + `eps', then the integer addressed by `Precision'
+%% will contain floor(-log2(eps)).
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderPrecisionFormat.xml">external</a> documentation.
+-spec getShaderPrecisionFormat(Shadertype, Precisiontype) -> {Range :: {integer(),integer()},Precision :: integer()} when Shadertype :: enum(),Precisiontype :: enum().
getShaderPrecisionFormat(Shadertype,Precisiontype) ->
call(5770, <<Shadertype:?GLenum,Precisiontype:?GLenum>>).
-%% @spec (N::clamp(),F::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml">external</a> documentation.
--spec depthRangef(clamp(),clamp()) -> ok.
+%% @doc
+%% See {@link depthRange/2}
+-spec depthRangef(N, F) -> ok when N :: clamp(),F :: clamp().
depthRangef(N,F) ->
cast(5771, <<N:?GLclampf,F:?GLclampf>>).
-%% @spec (D::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepthf.xml">external</a> documentation.
--spec clearDepthf(clamp()) -> ok.
+%% @doc glClearDepthf
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepthf.xml">external</a> documentation.
+-spec clearDepthf(D) -> ok when D :: clamp().
clearDepthf(D) ->
cast(5772, <<D:?GLclampf>>).
-%% @spec (Program::integer(),BufSize::integer()) -> {BinaryFormat::enum(),Binary::binary()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramBinary.xml">external</a> documentation.
--spec getProgramBinary(integer(),integer()) -> {enum(),binary()}.
+%% @doc Return a binary representation of a program object's compiled and linked executable source
+%%
+%% ``gl:getProgramBinary'' returns a binary representation of the compiled and linked executable
+%% for `Program' into the array of bytes whose address is specified in `Binary' .
+%% The maximum number of bytes that may be written into `Binary' is specified by `BufSize'
+%% . If the program binary is greater in size than `BufSize' bytes, then an error is
+%% generated, otherwise the actual number of bytes written into `Binary' is returned
+%% in the variable whose address is given by `Length' . If `Length' is `?NULL',
+%% then no length is returned.
+%%
+%% The format of the program binary written into `Binary' is returned in the variable
+%% whose address is given by `BinaryFormat' , and may be implementation dependent. The
+%% binary produced by the GL may subsequently be returned to the GL by calling {@link gl:programBinary/3}
+%% , with `BinaryFormat' and `Length' set to the values returned by ``gl:getProgramBinary''
+%% , and passing the returned binary data in the `Binary' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramBinary.xml">external</a> documentation.
+-spec getProgramBinary(Program, BufSize) -> {BinaryFormat :: enum(),Binary :: binary()} when Program :: integer(),BufSize :: integer().
getProgramBinary(Program,BufSize) ->
call(5773, <<Program:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Program::integer(),BinaryFormat::enum(),Binary::binary()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramBinary.xml">external</a> documentation.
--spec programBinary(integer(),enum(),binary()) -> ok.
+%% @doc Load a program object with a program binary
+%%
+%% ``gl:programBinary'' loads a program object with a program binary previously returned
+%% from {@link gl:getProgramBinary/2} . `BinaryFormat' and `Binary' must be those
+%% returned by a previous call to {@link gl:getProgramBinary/2} , and `Length' must be
+%% the length returned by {@link gl:getProgramBinary/2} , or by {@link gl:getProgramiv/2} when
+%% called with `Pname' set to `?GL_PROGRAM_BINARY_LENGTH'. If these conditions
+%% are not met, loading the program binary will fail and `Program' 's `?GL_LINK_STATUS'
+%% will be set to `?GL_FALSE'.
+%%
+%% A program object's program binary is replaced by calls to {@link gl:linkProgram/1} or ``gl:programBinary''
+%% . When linking success or failure is concerned, ``gl:programBinary'' can be considered
+%% to perform an implicit linking operation. {@link gl:linkProgram/1} and ``gl:programBinary''
+%% both set the program object's `?GL_LINK_STATUS' to `?GL_TRUE' or `?GL_FALSE'
+%% .
+%%
+%% A successful call to ``gl:programBinary'' will reset all uniform variables to their
+%% initial values. The initial value is either the value of the variable's initializer as
+%% specified in the original shader source, or zero if no initializer was present. Additionally,
+%% all vertex shader input and fragment shader output assignments that were in effect when
+%% the program was linked before saving are restored with ``gl:programBinary'' is called.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramBinary.xml">external</a> documentation.
+-spec programBinary(Program, BinaryFormat, Binary) -> ok when Program :: integer(),BinaryFormat :: enum(),Binary :: binary().
programBinary(Program,BinaryFormat,Binary) ->
send_bin(Binary),
cast(5774, <<Program:?GLuint,BinaryFormat:?GLenum>>).
-%% @spec (Program::integer(),Pname::enum(),Value::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramParameter.xml">external</a> documentation.
--spec programParameteri(integer(),enum(),integer()) -> ok.
+%% @doc Specify a parameter for a program object
+%%
+%% ``gl:programParameter'' specifies a new value for the parameter nameed by `Pname'
+%% for the program object `Program' .
+%%
+%% If `Pname' is `?GL_PROGRAM_BINARY_RETRIEVABLE_HINT', `Value' should be `?GL_FALSE'
+%% or `?GL_TRUE' to indicate to the implementation the intention of the application
+%% to retrieve the program's binary representation with {@link gl:getProgramBinary/2} . The
+%% implementation may use this information to store information that may be useful for a
+%% future query of the program's binary. It is recommended to set `?GL_PROGRAM_BINARY_RETRIEVABLE_HINT'
+%% for the program to `?GL_TRUE' before calling {@link gl:linkProgram/1} , and using
+%% the program at run-time if the binary is to be retrieved later.
+%%
+%% If `Pname' is `?GL_PROGRAM_SEPARABLE', `Value' must be `?GL_TRUE'
+%% or `?GL_FALSE' and indicates whether `Program' can be bound to individual pipeline
+%% stages via {@link gl:useProgramStages/3} . A program's `?GL_PROGRAM_SEPARABLE' parameter
+%% must be set to `?GL_TRUE'`before' {@link gl:linkProgram/1} is called in order
+%% for it to be usable with a program pipeline object. The initial state of `?GL_PROGRAM_SEPARABLE'
+%% is `?GL_FALSE'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramParameter.xml">external</a> documentation.
+-spec programParameteri(Program, Pname, Value) -> ok when Program :: integer(),Pname :: enum(),Value :: integer().
programParameteri(Program,Pname,Value) ->
cast(5775, <<Program:?GLuint,Pname:?GLenum,Value:?GLint>>).
-%% @spec (Pipeline::integer(),Stages::integer(),Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramStages.xml">external</a> documentation.
--spec useProgramStages(integer(),integer(),integer()) -> ok.
+%% @doc Bind stages of a program object to a program pipeline
+%%
+%% ``gl:useProgramStages'' binds executables from a program object associated with a specified
+%% set of shader stages to the program pipeline object given by `Pipeline' . `Pipeline'
+%% specifies the program pipeline object to which to bind the executables. `Stages'
+%% contains a logical combination of bits indicating the shader stages to use within `Program'
+%% with the program pipeline object `Pipeline' . `Stages' must be a logical combination
+%% of `?GL_VERTEX_SHADER_BIT', `?GL_TESS_CONTROL_SHADER_BIT', `?GL_TESS_EVALUATION_SHADER_BIT'
+%% , `?GL_GEOMETRY_SHADER_BIT', and `?GL_FRAGMENT_SHADER_BIT'. Additionally, the
+%% special value `?GL_ALL_SHADER_BITS' may be specified to indicate that all executables
+%% contained in `Program' should be installed in `Pipeline' .
+%%
+%% If `Program' refers to a program object with a valid shader attached for an indicated
+%% shader stage, ``gl:useProgramStages'' installs the executable code for that stage in
+%% the indicated program pipeline object `Pipeline' . If `Program' is zero, or refers
+%% to a program object with no valid shader executable for a given stage, it is as if the
+%% pipeline object has no programmable stage configured for the indicated shader stages. If `Stages'
+%% contains bits other than those listed above, and is not equal to `?GL_ALL_SHADER_BITS'
+%% , an error is generated.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramStages.xml">external</a> documentation.
+-spec useProgramStages(Pipeline, Stages, Program) -> ok when Pipeline :: integer(),Stages :: integer(),Program :: integer().
useProgramStages(Pipeline,Stages,Program) ->
cast(5776, <<Pipeline:?GLuint,Stages:?GLbitfield,Program:?GLuint>>).
-%% @spec (Pipeline::integer(),Program::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveShaderProgram.xml">external</a> documentation.
--spec activeShaderProgram(integer(),integer()) -> ok.
+%% @doc Set the active program object for a program pipeline object
+%%
+%% ``gl:activeShaderProgram'' sets the linked program named by `Program' to be the
+%% active program for the program pipeline object `Pipeline' . The active program in
+%% the active program pipeline object is the target of calls to {@link gl:uniform1f/2} when
+%% no program has been made current through a call to {@link gl:useProgram/1} .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveShaderProgram.xml">external</a> documentation.
+-spec activeShaderProgram(Pipeline, Program) -> ok when Pipeline :: integer(),Program :: integer().
activeShaderProgram(Pipeline,Program) ->
cast(5777, <<Pipeline:?GLuint,Program:?GLuint>>).
-%% @spec (Type::enum(),Strings::[string()]) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderProgramv.xml">external</a> documentation.
--spec createShaderProgramv(enum(),[string()]) -> integer().
+%% @doc glCreateShaderProgramv
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderProgramv.xml">external</a> documentation.
+-spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: [string()].
createShaderProgramv(Type,Strings) ->
StringsTemp = list_to_binary([[Str|[0]] || Str <- Strings ]),
call(5778, <<Type:?GLenum,(length(Strings)):?GLuint,(size(StringsTemp)):?GLuint,(StringsTemp)/binary,0:((8-((size(StringsTemp)+0) rem 8)) rem 8)>>).
-%% @spec (Pipeline::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramPipeline.xml">external</a> documentation.
--spec bindProgramPipeline(integer()) -> ok.
+%% @doc Bind a program pipeline to the current context
+%%
+%% ``gl:bindProgramPipeline'' binds a program pipeline object to the current context. `Pipeline'
+%% must be a name previously returned from a call to {@link gl:genProgramPipelines/1} . If
+%% no program pipeline exists with name `Pipeline' then a new pipeline object is created
+%% with that name and initialized to the default state vector.
+%%
+%% When a program pipeline object is bound using ``gl:bindProgramPipeline'', any previous
+%% binding is broken and is replaced with a binding to the specified pipeline object. If `Pipeline'
+%% is zero, the previous binding is broken and is not replaced, leaving no pipeline object
+%% bound. If no current program object has been established by {@link gl:useProgram/1} , the
+%% program objects used for each stage and for uniform updates are taken from the bound program
+%% pipeline object, if any. If there is a current program object established by {@link gl:useProgram/1}
+%% , the bound program pipeline object has no effect on rendering or uniform updates. When
+%% a bound program pipeline object is used for rendering, individual shader executables are
+%% taken from its program objects.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramPipeline.xml">external</a> documentation.
+-spec bindProgramPipeline(Pipeline) -> ok when Pipeline :: integer().
bindProgramPipeline(Pipeline) ->
cast(5779, <<Pipeline:?GLuint>>).
-%% @spec (Pipelines::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramPipelines.xml">external</a> documentation.
--spec deleteProgramPipelines([integer()]) -> ok.
+%% @doc Delete program pipeline objects
+%%
+%% ``gl:deleteProgramPipelines'' deletes the `N' program pipeline objects whose names
+%% are stored in the array `Pipelines' . Unused names in `Pipelines' are ignored,
+%% as is the name zero. After a program pipeline object is deleted, its name is again unused
+%% and it has no contents. If program pipeline object that is currently bound is deleted,
+%% the binding for that object reverts to zero and no program pipeline object becomes current.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramPipelines.xml">external</a> documentation.
+-spec deleteProgramPipelines(Pipelines) -> ok when Pipelines :: [integer()].
deleteProgramPipelines(Pipelines) ->
cast(5780, <<(length(Pipelines)):?GLuint,
(<< <<C:?GLuint>> || C <- Pipelines>>)/binary,0:(((1+length(Pipelines)) rem 2)*32)>>).
-%% @spec (N::integer()) -> [integer()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramPipelines.xml">external</a> documentation.
--spec genProgramPipelines(integer()) -> [integer()].
+%% @doc Reserve program pipeline object names
+%%
+%% ``gl:genProgramPipelines'' returns `N' previously unused program pipeline object
+%% names in `Pipelines' . These names are marked as used, for the purposes of ``gl:genProgramPipelines''
+%% only, but they acquire program pipeline state only when they are first bound.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramPipelines.xml">external</a> documentation.
+-spec genProgramPipelines(N) -> [integer()] when N :: integer().
genProgramPipelines(N) ->
call(5781, <<N:?GLsizei>>).
-%% @spec (Pipeline::integer()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgramPipeline.xml">external</a> documentation.
--spec isProgramPipeline(integer()) -> 0|1.
+%% @doc Determine if a name corresponds to a program pipeline object
+%%
+%% ``gl:isProgramPipeline'' returns `?GL_TRUE' if `Pipeline' is currently the
+%% name of a program pipeline object. If `Pipeline' is zero, or if `?pipeline'
+%% is not the name of a program pipeline object, or if an error occurs, ``gl:isProgramPipeline''
+%% returns `?GL_FALSE'. If `Pipeline' is a name returned by {@link gl:genProgramPipelines/1}
+%% , but that has not yet been bound through a call to {@link gl:bindProgramPipeline/1} , then
+%% the name is not a program pipeline object and ``gl:isProgramPipeline'' returns `?GL_FALSE'
+%% .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgramPipeline.xml">external</a> documentation.
+-spec isProgramPipeline(Pipeline) -> 0|1 when Pipeline :: integer().
isProgramPipeline(Pipeline) ->
call(5782, <<Pipeline:?GLuint>>).
-%% @spec (Pipeline::integer(),Pname::enum()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipeline.xml">external</a> documentation.
--spec getProgramPipelineiv(integer(),enum()) -> integer().
+%% @doc Retrieve properties of a program pipeline object
+%%
+%% ``gl:getProgramPipelineiv'' retrieves the value of a property of the program pipeline
+%% object `Pipeline' . `Pname' specifies the name of the parameter whose value to
+%% retrieve. The value of the parameter is written to the variable whose address is given
+%% by `Params' .
+%%
+%% If `Pname' is `?GL_ACTIVE_PROGRAM', the name of the active program object of
+%% the program pipeline object is returned in `Params' .
+%%
+%% If `Pname' is `?GL_VERTEX_SHADER', the name of the current program object for
+%% the vertex shader type of the program pipeline object is returned in `Params' .
+%%
+%% If `Pname' is `?GL_TESS_CONTROL_SHADER', the name of the current program object
+%% for the tessellation control shader type of the program pipeline object is returned in `Params'
+%% .
+%%
+%% If `Pname' is `?GL_TESS_EVALUATION_SHADER', the name of the current program
+%% object for the tessellation evaluation shader type of the program pipeline object is returned
+%% in `Params' .
+%%
+%% If `Pname' is `?GL_GEOMETRY_SHADER', the name of the current program object
+%% for the geometry shader type of the program pipeline object is returned in `Params' .
+%%
+%%
+%% If `Pname' is `?GL_FRAGMENT_SHADER', the name of the current program object
+%% for the fragment shader type of the program pipeline object is returned in `Params' .
+%%
+%%
+%% If `Pname' is `?GL_INFO_LOG_LENGTH', the length of the info log, including
+%% the null terminator, is returned in `Params' . If there is no info log, zero is returned.
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipeline.xml">external</a> documentation.
+-spec getProgramPipelineiv(Pipeline, Pname) -> integer() when Pipeline :: integer(),Pname :: enum().
getProgramPipelineiv(Pipeline,Pname) ->
call(5783, <<Pipeline:?GLuint,Pname:?GLenum>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1i(integer(),integer(),integer()) -> ok.
+%% @doc Specify the value of a uniform variable for a specified program object
+%%
+%% ``gl:programUniform'' modifies the value of a uniform variable or a uniform variable
+%% array. The location of the uniform variable to be modified is specified by `Location' ,
+%% which should be a value returned by {@link gl:getUniformLocation/2} . ``gl:programUniform''
+%% operates on the program object specified by `Program' .
+%%
+%% The commands ``gl:programUniform{1|2|3|4}{f|i|ui}'' are used to change the value of
+%% the uniform variable specified by `Location' using the values passed as arguments.
+%% The number specified in the command should match the number of components in the data
+%% type of the specified uniform variable (e.g., `1' for float, int, unsigned int, bool;
+%% `2' for vec2, ivec2, uvec2, bvec2, etc.). The suffix `f' indicates that floating-point
+%% values are being passed; the suffix `i' indicates that integer values are being passed;
+%% the suffix `ui' indicates that unsigned integer values are being passed, and this
+%% type should also match the data type of the specified uniform variable. The `i' variants
+%% of this function should be used to provide values for uniform variables defined as int, ivec2
+%% , ivec3, ivec4, or arrays of these. The `ui' variants of this function should be
+%% used to provide values for uniform variables defined as unsigned int, uvec2, uvec3, uvec4,
+%% or arrays of these. The `f' variants should be used to provide values for uniform
+%% variables of type float, vec2, vec3, vec4, or arrays of these. Either the `i', `ui'
+%% or `f' variants may be used to provide values for uniform variables of type bool, bvec2
+%% , bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input
+%% value is 0 or 0.0f, and it will be set to true otherwise.
+%%
+%% All active uniform variables defined in a program object are initialized to 0 when the
+%% program object is linked successfully. They retain the values assigned to them by a call
+%% to ``gl:programUniform'' until the next successful link operation occurs on the program
+%% object, when they are once again initialized to 0.
+%%
+%% The commands ``gl:programUniform{1|2|3|4}{f|i|ui}v'' can be used to modify a single
+%% uniform variable or a uniform variable array. These commands pass a count and a pointer
+%% to the values to be loaded into a uniform variable or a uniform variable array. A count
+%% of 1 should be used if modifying the value of a single uniform variable, and a count of
+%% 1 or greater can be used to modify an entire array or part of an array. When loading `n'
+%% elements starting at an arbitrary position `m' in a uniform variable array, elements
+%% `m' + `n' - 1 in the array will be replaced with the new values. If `M' + `N'
+%% - 1 is larger than the size of the uniform variable array, values for all array elements
+%% beyond the end of the array will be ignored. The number specified in the name of the command
+%% indicates the number of components for each element in `Value' , and it should match
+%% the number of components in the data type of the specified uniform variable (e.g., `1'
+%% for float, int, bool; `2' for vec2, ivec2, bvec2, etc.). The data type specified
+%% in the name of the command must match the data type for the specified uniform variable
+%% as described previously for ``gl:programUniform{1|2|3|4}{f|i|ui}''.
+%%
+%% For uniform variable arrays, each element of the array is considered to be of the type
+%% indicated in the name of the command (e.g., ``gl:programUniform3f'' or ``gl:programUniform3fv''
+%% can be used to load a uniform variable array of type vec3). The number of elements of
+%% the uniform variable array to be modified is specified by `Count'
+%%
+%% The commands ``gl:programUniformMatrix{2|3|4|2x3|3x2|2x4|4x2|3x4|4x3}fv'' are used
+%% to modify a matrix or an array of matrices. The numbers in the command name are interpreted
+%% as the dimensionality of the matrix. The number `2' indicates a 2 � 2 matrix (i.e.,
+%% 4 values), the number `3' indicates a 3 � 3 matrix (i.e., 9 values), and the number `4'
+%% indicates a 4 � 4 matrix (i.e., 16 values). Non-square matrix dimensionality is explicit,
+%% with the first number representing the number of columns and the second number representing
+%% the number of rows. For example, `2x4' indicates a 2 � 4 matrix with 2 columns and
+%% 4 rows (i.e., 8 values). If `Transpose' is `?GL_FALSE', each matrix is assumed
+%% to be supplied in column major order. If `Transpose' is `?GL_TRUE', each matrix
+%% is assumed to be supplied in row major order. The `Count' argument indicates the
+%% number of matrices to be passed. A count of 1 should be used if modifying the value of
+%% a single matrix, and a count greater than 1 can be used to modify an array of matrices.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
+-spec programUniform1i(Program, Location, V0) -> ok when Program :: integer(),Location :: integer(),V0 :: integer().
programUniform1i(Program,Location,V0) ->
cast(5784, <<Program:?GLuint,Location:?GLint,V0:?GLint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1iv(integer(),integer(),[integer()]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1iv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [integer()].
programUniform1iv(Program,Location,Value) ->
cast(5785, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<C:?GLint>> || C <- Value>>)/binary,0:(((1+length(Value)) rem 2)*32)>>).
-%% @spec (Program::integer(),Location::integer(),V0::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1f(integer(),integer(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1f(Program, Location, V0) -> ok when Program :: integer(),Location :: integer(),V0 :: float().
programUniform1f(Program,Location,V0) ->
cast(5786, <<Program:?GLuint,Location:?GLint,V0:?GLfloat>>).
-%% @spec (Program::integer(),Location::integer(),Value::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1fv(integer(),integer(),[float()]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1fv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [float()].
programUniform1fv(Program,Location,Value) ->
cast(5787, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<C:?GLfloat>> || C <- Value>>)/binary,0:(((1+length(Value)) rem 2)*32)>>).
-%% @spec (Program::integer(),Location::integer(),V0::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1d(integer(),integer(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1d(Program, Location, V0) -> ok when Program :: integer(),Location :: integer(),V0 :: float().
programUniform1d(Program,Location,V0) ->
cast(5788, <<Program:?GLuint,Location:?GLint,V0:?GLdouble>>).
-%% @spec (Program::integer(),Location::integer(),Value::[float()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1dv(integer(),integer(),[float()]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1dv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [float()].
programUniform1dv(Program,Location,Value) ->
cast(5789, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,0:32,
(<< <<C:?GLdouble>> || C <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1ui(integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1ui(Program, Location, V0) -> ok when Program :: integer(),Location :: integer(),V0 :: integer().
programUniform1ui(Program,Location,V0) ->
cast(5790, <<Program:?GLuint,Location:?GLint,V0:?GLuint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[integer()]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform1uiv(integer(),integer(),[integer()]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform1uiv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [integer()].
programUniform1uiv(Program,Location,Value) ->
cast(5791, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<C:?GLuint>> || C <- Value>>)/binary,0:(((1+length(Value)) rem 2)*32)>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer(),V1::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2i(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2i(Program, Location, V0, V1) -> ok when Program :: integer(),Location :: integer(),V0 :: integer(),V1 :: integer().
programUniform2i(Program,Location,V0,V1) ->
cast(5792, <<Program:?GLuint,Location:?GLint,V0:?GLint,V1:?GLint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2iv(integer(),integer(),[{integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2iv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{integer(),integer()}].
programUniform2iv(Program,Location,Value) ->
cast(5793, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLint,V2:?GLint>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::float(),V1::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2f(integer(),integer(),float(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2f(Program, Location, V0, V1) -> ok when Program :: integer(),Location :: integer(),V0 :: float(),V1 :: float().
programUniform2f(Program,Location,V0,V1) ->
cast(5794, <<Program:?GLuint,Location:?GLint,V0:?GLfloat,V1:?GLfloat>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2fv(integer(),integer(),[{float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2fv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{float(),float()}].
programUniform2fv(Program,Location,Value) ->
cast(5795, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::float(),V1::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2d(integer(),integer(),float(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2d(Program, Location, V0, V1) -> ok when Program :: integer(),Location :: integer(),V0 :: float(),V1 :: float().
programUniform2d(Program,Location,V0,V1) ->
cast(5796, <<Program:?GLuint,Location:?GLint,V0:?GLdouble,V1:?GLdouble>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2dv(integer(),integer(),[{float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2dv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{float(),float()}].
programUniform2dv(Program,Location,Value) ->
cast(5797, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer(),V1::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2ui(integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2ui(Program, Location, V0, V1) -> ok when Program :: integer(),Location :: integer(),V0 :: integer(),V1 :: integer().
programUniform2ui(Program,Location,V0,V1) ->
cast(5798, <<Program:?GLuint,Location:?GLint,V0:?GLuint,V1:?GLuint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform2uiv(integer(),integer(),[{integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform2uiv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{integer(),integer()}].
programUniform2uiv(Program,Location,Value) ->
cast(5799, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLuint,V2:?GLuint>> || {V1,V2} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer(),V1::integer(),V2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3i(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3i(Program, Location, V0, V1, V2) -> ok when Program :: integer(),Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer().
programUniform3i(Program,Location,V0,V1,V2) ->
cast(5800, <<Program:?GLuint,Location:?GLint,V0:?GLint,V1:?GLint,V2:?GLint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3iv(integer(),integer(),[{integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3iv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{integer(),integer(),integer()}].
programUniform3iv(Program,Location,Value) ->
cast(5801, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLint,V2:?GLint,V3:?GLint>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::float(),V1::float(),V2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3f(integer(),integer(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3f(Program, Location, V0, V1, V2) -> ok when Program :: integer(),Location :: integer(),V0 :: float(),V1 :: float(),V2 :: float().
programUniform3f(Program,Location,V0,V1,V2) ->
cast(5802, <<Program:?GLuint,Location:?GLint,V0:?GLfloat,V1:?GLfloat,V2:?GLfloat>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3fv(integer(),integer(),[{float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3fv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{float(),float(),float()}].
programUniform3fv(Program,Location,Value) ->
cast(5803, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::float(),V1::float(),V2::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3d(integer(),integer(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3d(Program, Location, V0, V1, V2) -> ok when Program :: integer(),Location :: integer(),V0 :: float(),V1 :: float(),V2 :: float().
programUniform3d(Program,Location,V0,V1,V2) ->
cast(5804, <<Program:?GLuint,Location:?GLint,V0:?GLdouble,V1:?GLdouble,V2:?GLdouble>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3dv(integer(),integer(),[{float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3dv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{float(),float(),float()}].
programUniform3dv(Program,Location,Value) ->
cast(5805, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer(),V1::integer(),V2::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3ui(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3ui(Program, Location, V0, V1, V2) -> ok when Program :: integer(),Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer().
programUniform3ui(Program,Location,V0,V1,V2) ->
cast(5806, <<Program:?GLuint,Location:?GLint,V0:?GLuint,V1:?GLuint,V2:?GLuint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform3uiv(integer(),integer(),[{integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform3uiv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{integer(),integer(),integer()}].
programUniform3uiv(Program,Location,Value) ->
cast(5807, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLuint,V2:?GLuint,V3:?GLuint>> || {V1,V2,V3} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer(),V1::integer(),V2::integer(),V3::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4i(integer(),integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4i(Program, Location, V0, V1, V2, V3) -> ok when Program :: integer(),Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer(),V3 :: integer().
programUniform4i(Program,Location,V0,V1,V2,V3) ->
cast(5808, <<Program:?GLuint,Location:?GLint,V0:?GLint,V1:?GLint,V2:?GLint,V3:?GLint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{integer(),integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4iv(integer(),integer(),[{integer(),integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4iv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{integer(),integer(),integer(),integer()}].
programUniform4iv(Program,Location,Value) ->
cast(5809, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::float(),V1::float(),V2::float(),V3::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4f(integer(),integer(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4f(Program, Location, V0, V1, V2, V3) -> ok when Program :: integer(),Location :: integer(),V0 :: float(),V1 :: float(),V2 :: float(),V3 :: float().
programUniform4f(Program,Location,V0,V1,V2,V3) ->
cast(5810, <<Program:?GLuint,Location:?GLint,V0:?GLfloat,V1:?GLfloat,V2:?GLfloat,V3:?GLfloat>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4fv(integer(),integer(),[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4fv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{float(),float(),float(),float()}].
programUniform4fv(Program,Location,Value) ->
cast(5811, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::float(),V1::float(),V2::float(),V3::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4d(integer(),integer(),float(),float(),float(),float()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4d(Program, Location, V0, V1, V2, V3) -> ok when Program :: integer(),Location :: integer(),V0 :: float(),V1 :: float(),V2 :: float(),V3 :: float().
programUniform4d(Program,Location,V0,V1,V2,V3) ->
cast(5812, <<Program:?GLuint,Location:?GLint,V0:?GLdouble,V1:?GLdouble,V2:?GLdouble,V3:?GLdouble>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4dv(integer(),integer(),[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4dv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{float(),float(),float(),float()}].
programUniform4dv(Program,Location,Value) ->
cast(5813, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),V0::integer(),V1::integer(),V2::integer(),V3::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4ui(integer(),integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4ui(Program, Location, V0, V1, V2, V3) -> ok when Program :: integer(),Location :: integer(),V0 :: integer(),V1 :: integer(),V2 :: integer(),V3 :: integer().
programUniform4ui(Program,Location,V0,V1,V2,V3) ->
cast(5814, <<Program:?GLuint,Location:?GLint,V0:?GLuint,V1:?GLuint,V2:?GLuint,V3:?GLuint>>).
-%% @spec (Program::integer(),Location::integer(),Value::[{integer(),integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
--spec programUniform4uiv(integer(),integer(),[{integer(),integer(),integer(),integer()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniform4uiv(Program, Location, Value) -> ok when Program :: integer(),Location :: integer(),Value :: [{integer(),integer(),integer(),integer()}].
programUniform4uiv(Program,Location,Value) ->
cast(5815, <<Program:?GLuint,Location:?GLint,(length(Value)):?GLuint,
(<< <<V1:?GLuint,V2:?GLuint,V3:?GLuint,V4:?GLuint>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix.xml">external</a> documentation.
--spec programUniformMatrix2fv(integer(),integer(),0|1,[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix2fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float()}].
programUniformMatrix2fv(Program,Location,Transpose,Value) ->
cast(5816, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix.xml">external</a> documentation.
--spec programUniformMatrix3fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix3fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix3fv(Program,Location,Transpose,Value) ->
cast(5817, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix.xml">external</a> documentation.
--spec programUniformMatrix4fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix4fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix4fv(Program,Location,Transpose,Value) ->
cast(5818, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat,V10:?GLfloat,V11:?GLfloat,V12:?GLfloat,V13:?GLfloat,V14:?GLfloat,V15:?GLfloat,V16:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix.xml">external</a> documentation.
--spec programUniformMatrix2dv(integer(),integer(),0|1,[{float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix2dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float()}].
programUniformMatrix2dv(Program,Location,Transpose,Value) ->
cast(5819, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble>> || {V1,V2,V3,V4} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix.xml">external</a> documentation.
--spec programUniformMatrix3dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix3dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix3dv(Program,Location,Transpose,Value) ->
cast(5820, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix.xml">external</a> documentation.
--spec programUniformMatrix4dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix4dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix4dv(Program,Location,Transpose,Value) ->
cast(5821, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble,V10:?GLdouble,V11:?GLdouble,V12:?GLdouble,V13:?GLdouble,V14:?GLdouble,V15:?GLdouble,V16:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix2x.xml">external</a> documentation.
--spec programUniformMatrix2x3fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix2x3fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
programUniformMatrix2x3fv(Program,Location,Transpose,Value) ->
cast(5822, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix3x.xml">external</a> documentation.
--spec programUniformMatrix3x2fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix3x2fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
programUniformMatrix3x2fv(Program,Location,Transpose,Value) ->
cast(5823, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix2x.xml">external</a> documentation.
--spec programUniformMatrix2x4fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix2x4fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix2x4fv(Program,Location,Transpose,Value) ->
cast(5824, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix4x.xml">external</a> documentation.
--spec programUniformMatrix4x2fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix4x2fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix4x2fv(Program,Location,Transpose,Value) ->
cast(5825, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix3x.xml">external</a> documentation.
--spec programUniformMatrix3x4fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix3x4fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix3x4fv(Program,Location,Transpose,Value) ->
cast(5826, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat,V10:?GLfloat,V11:?GLfloat,V12:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix4x.xml">external</a> documentation.
--spec programUniformMatrix4x3fv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix4x3fv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix4x3fv(Program,Location,Transpose,Value) ->
cast(5827, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:24,(length(Value)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat,V5:?GLfloat,V6:?GLfloat,V7:?GLfloat,V8:?GLfloat,V9:?GLfloat,V10:?GLfloat,V11:?GLfloat,V12:?GLfloat>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix2x.xml">external</a> documentation.
--spec programUniformMatrix2x3dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix2x3dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
programUniformMatrix2x3dv(Program,Location,Transpose,Value) ->
cast(5828, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix3x.xml">external</a> documentation.
--spec programUniformMatrix3x2dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix3x2dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float()}].
programUniformMatrix3x2dv(Program,Location,Transpose,Value) ->
cast(5829, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble>> || {V1,V2,V3,V4,V5,V6} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix2x.xml">external</a> documentation.
--spec programUniformMatrix2x4dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix2x4dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix2x4dv(Program,Location,Transpose,Value) ->
cast(5830, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix4x.xml">external</a> documentation.
--spec programUniformMatrix4x2dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix4x2dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix4x2dv(Program,Location,Transpose,Value) ->
cast(5831, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix3x.xml">external</a> documentation.
--spec programUniformMatrix3x4dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix3x4dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix3x4dv(Program,Location,Transpose,Value) ->
cast(5832, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble,V10:?GLdouble,V11:?GLdouble,V12:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Program::integer(),Location::integer(),Transpose::0|1,Value::[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniformMatrix4x.xml">external</a> documentation.
--spec programUniformMatrix4x3dv(integer(),integer(),0|1,[{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}]) -> ok.
+%% @doc
+%% See {@link programUniform1i/3}
+-spec programUniformMatrix4x3dv(Program, Location, Transpose, Value) -> ok when Program :: integer(),Location :: integer(),Transpose :: 0|1,Value :: [{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()}].
programUniformMatrix4x3dv(Program,Location,Transpose,Value) ->
cast(5833, <<Program:?GLuint,Location:?GLint,Transpose:?GLboolean,0:56,(length(Value)):?GLuint,0:32,
(<< <<V1:?GLdouble,V2:?GLdouble,V3:?GLdouble,V4:?GLdouble,V5:?GLdouble,V6:?GLdouble,V7:?GLdouble,V8:?GLdouble,V9:?GLdouble,V10:?GLdouble,V11:?GLdouble,V12:?GLdouble>> || {V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12} <- Value>>)/binary>>).
-%% @spec (Pipeline::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramPipeline.xml">external</a> documentation.
--spec validateProgramPipeline(integer()) -> ok.
+%% @doc Validate a program pipeline object against current GL state
+%%
+%% ``gl:validateProgramPipeline'' instructs the implementation to validate the shader executables
+%% contained in `Pipeline' against the current GL state. The implementation may use
+%% this as an opportunity to perform any internal shader modifications that may be required
+%% to ensure correct operation of the installed shaders given the current GL state.
+%%
+%% After a program pipeline has been validated, its validation status is set to `?GL_TRUE'
+%% . The validation status of a program pipeline object may be queried by calling {@link gl:getProgramPipelineiv/2}
+%% with parameter `?GL_VALIDATE_STATUS'.
+%%
+%% If `Pipeline' is a name previously returned from a call to {@link gl:genProgramPipelines/1}
+%% but that has not yet been bound by a call to {@link gl:bindProgramPipeline/1} , a new program
+%% pipeline object is created with name `Pipeline' and the default state vector.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramPipeline.xml">external</a> documentation.
+-spec validateProgramPipeline(Pipeline) -> ok when Pipeline :: integer().
validateProgramPipeline(Pipeline) ->
cast(5834, <<Pipeline:?GLuint>>).
-%% @spec (Pipeline::integer(),BufSize::integer()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipelineInfoLog.xml">external</a> documentation.
--spec getProgramPipelineInfoLog(integer(),integer()) -> string().
+%% @doc Retrieve the info log string from a program pipeline object
+%%
+%% ``gl:getProgramPipelineInfoLog'' retrieves the info log for the program pipeline object
+%% `Pipeline' . The info log, including its null terminator, is written into the array
+%% of characters whose address is given by `InfoLog' . The maximum number of characters
+%% that may be written into `InfoLog' is given by `BufSize' , and the actual number
+%% of characters written into `InfoLog' is returned in the integer whose address is
+%% given by `Length' . If `Length' is `?NULL', no length is returned.
+%%
+%% The actual length of the info log for the program pipeline may be determined by calling {@link gl:getProgramPipelineiv/2}
+%% with `Pname' set to `?GL_INFO_LOG_LENGTH'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipelineInfoLog.xml">external</a> documentation.
+-spec getProgramPipelineInfoLog(Pipeline, BufSize) -> string() when Pipeline :: integer(),BufSize :: integer().
getProgramPipelineInfoLog(Pipeline,BufSize) ->
call(5835, <<Pipeline:?GLuint,BufSize:?GLsizei>>).
-%% @spec (Index::integer(),X::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
--spec vertexAttribL1d(integer(),float()) -> ok.
+%% @doc glVertexAttribL
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+-spec vertexAttribL1d(Index, X) -> ok when Index :: integer(),X :: float().
vertexAttribL1d(Index,X) ->
cast(5836, <<Index:?GLuint,0:32,X:?GLdouble>>).
-%% @spec (Index::integer(),X::float(),Y::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
--spec vertexAttribL2d(integer(),float(),float()) -> ok.
+%% @doc glVertexAttribL
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+-spec vertexAttribL2d(Index, X, Y) -> ok when Index :: integer(),X :: float(),Y :: float().
vertexAttribL2d(Index,X,Y) ->
cast(5837, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble>>).
-%% @spec (Index::integer(),X::float(),Y::float(),Z::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
--spec vertexAttribL3d(integer(),float(),float(),float()) -> ok.
+%% @doc glVertexAttribL
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+-spec vertexAttribL3d(Index, X, Y, Z) -> ok when Index :: integer(),X :: float(),Y :: float(),Z :: float().
vertexAttribL3d(Index,X,Y,Z) ->
cast(5838, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
-%% @spec (Index::integer(),X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
--spec vertexAttribL4d(integer(),float(),float(),float(),float()) -> ok.
+%% @doc glVertexAttribL
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+-spec vertexAttribL4d(Index, X, Y, Z, W) -> ok when Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
vertexAttribL4d(Index,X,Y,Z,W) ->
cast(5839, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-%% @spec (Index,{X}) -> ok
%% @equiv vertexAttribL1d(Index,X)
--spec vertexAttribL1dv(integer(),{float()}) -> ok.
+-spec vertexAttribL1dv(Index :: integer(),V) -> ok when V :: {X :: float()}.
vertexAttribL1dv(Index,{X}) -> vertexAttribL1d(Index,X).
-%% @spec (Index,{X,Y}) -> ok
%% @equiv vertexAttribL2d(Index,X,Y)
--spec vertexAttribL2dv(integer(),{float(),float()}) -> ok.
+-spec vertexAttribL2dv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float()}.
vertexAttribL2dv(Index,{X,Y}) -> vertexAttribL2d(Index,X,Y).
-%% @spec (Index,{X,Y,Z}) -> ok
%% @equiv vertexAttribL3d(Index,X,Y,Z)
--spec vertexAttribL3dv(integer(),{float(),float(),float()}) -> ok.
+-spec vertexAttribL3dv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float(),Z :: float()}.
vertexAttribL3dv(Index,{X,Y,Z}) -> vertexAttribL3d(Index,X,Y,Z).
-%% @spec (Index,{X,Y,Z,W}) -> ok
%% @equiv vertexAttribL4d(Index,X,Y,Z,W)
--spec vertexAttribL4dv(integer(),{float(),float(),float(),float()}) -> ok.
+-spec vertexAttribL4dv(Index :: integer(),V) -> ok when V :: {X :: float(),Y :: float(),Z :: float(),W :: float()}.
vertexAttribL4dv(Index,{X,Y,Z,W}) -> vertexAttribL4d(Index,X,Y,Z,W).
-%% @spec (Index::integer(),Size::integer(),Type::enum(),Stride::integer(),Pointer::offset()|mem()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribLPointer.xml">external</a> documentation.
--spec vertexAttribLPointer(integer(),integer(),enum(),integer(),offset()|mem()) -> ok.
+%% @doc glVertexAttribLPointer
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribLPointer.xml">external</a> documentation.
+-spec vertexAttribLPointer(Index, Size, Type, Stride, Pointer) -> ok when Index :: integer(),Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
vertexAttribLPointer(Index,Size,Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5840, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
vertexAttribLPointer(Index,Size,Type,Stride,Pointer) ->
send_bin(Pointer),
cast(5841, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei>>).
-%% @spec (Index::integer(),Pname::enum()) -> {float(),float(),float(),float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribL.xml">external</a> documentation.
--spec getVertexAttribLdv(integer(),enum()) -> {float(),float(),float(),float()}.
+%% @doc glGetVertexAttribL
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribL.xml">external</a> documentation.
+-spec getVertexAttribLdv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum().
getVertexAttribLdv(Index,Pname) ->
call(5842, <<Index:?GLuint,Pname:?GLenum>>).
-%% @spec (First::integer(),V::[{float(),float(),float(),float()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportArrayv.xml">external</a> documentation.
--spec viewportArrayv(integer(),[{float(),float(),float(),float()}]) -> ok.
+%% @doc glViewportArrayv
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportArrayv.xml">external</a> documentation.
+-spec viewportArrayv(First, V) -> ok when First :: integer(),V :: [{float(),float(),float(),float()}].
viewportArrayv(First,V) ->
cast(5843, <<First:?GLuint,(length(V)):?GLuint,
(<< <<V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat>> || {V1,V2,V3,V4} <- V>>)/binary>>).
-%% @spec (Index::integer(),X::float(),Y::float(),W::float(),H::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportIndexed.xml">external</a> documentation.
--spec viewportIndexedf(integer(),float(),float(),float(),float()) -> ok.
+%% @doc Set a specified viewport
+%%
+%% ``gl:viewportIndexedf'' and ``gl:viewportIndexedfv'' specify the parameters for a
+%% single viewport. `Index' specifies the index of the viewport to modify. `Index'
+%% must be less than the value of `?GL_MAX_VIEWPORTS'. For ``gl:viewportIndexedf'', `X'
+%% , `Y' , `W' , and `H' specify the left, bottom, width and height of the viewport
+%% in pixels, respectively. For ``gl:viewportIndexedfv'', `V' contains the address
+%% of an array of floating point values specifying the left ( x), bottom ( y), width ( w),
+%% and height ( h) of each viewport, in that order. x and y give the location of the viewport's
+%% lower left corner, and w and h give the width and height of the viewport, respectively.
+%% The viewport specifies the affine transformation of x and y from normalized device
+%% coordinates to window coordinates. Let (x nd y nd) be normalized device coordinates. Then the window
+%% coordinates (x w y w) are computed as follows:
+%%
+%% x w=(x nd+1) (width/2)+x
+%%
+%% y w=(y nd+1) (height/2)+y
+%%
+%% The location of the viewport's bottom left corner, given by ( x, y) is clamped to be
+%% within the implementaiton-dependent viewport bounds range. The viewport bounds range [
+%% min, max] can be determined by calling {@link gl:getBooleanv/1} with argument `?GL_VIEWPORT_BOUNDS_RANGE'
+%% . Viewport width and height are silently clamped to a range that depends on the implementation.
+%% To query this range, call {@link gl:getBooleanv/1} with argument `?GL_MAX_VIEWPORT_DIMS'.
+%%
+%% The precision with which the GL interprets the floating point viewport bounds is implementation-dependent
+%% and may be determined by querying the impementation-defined constant `?GL_VIEWPORT_SUBPIXEL_BITS'
+%% .
+%%
+%% Calling ``gl:viewportIndexedfv'' is equivalent to calling see `glViewportArray'
+%% with `First' set to `Index' , `Count' set to 1 and `V' passsed directly.
+%% ``gl:viewportIndexedf'' is equivalent to: void glViewportIndexedf(GLuint index, GLfloat
+%% x, GLfloat y, GLfloat w, GLfloat h) { const float v[4] = { x, y, w, h }; glViewportArrayv(index,
+%% 1, v); }
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportIndexed.xml">external</a> documentation.
+-spec viewportIndexedf(Index, X, Y, W, H) -> ok when Index :: integer(),X :: float(),Y :: float(),W :: float(),H :: float().
viewportIndexedf(Index,X,Y,W,H) ->
cast(5844, <<Index:?GLuint,X:?GLfloat,Y:?GLfloat,W:?GLfloat,H:?GLfloat>>).
-%% @spec (Index::integer(),V::{float(),float(),float(),float()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportIndexed.xml">external</a> documentation.
--spec viewportIndexedfv(integer(),{float(),float(),float(),float()}) -> ok.
+%% @doc
+%% See {@link viewportIndexedf/5}
+-spec viewportIndexedfv(Index, V) -> ok when Index :: integer(),V :: {float(),float(),float(),float()}.
viewportIndexedfv(Index,{V1,V2,V3,V4}) ->
cast(5845, <<Index:?GLuint,V1:?GLfloat,V2:?GLfloat,V3:?GLfloat,V4:?GLfloat>>).
-%% @spec (First::integer(),V::[{integer(),integer(),integer(),integer()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorArrayv.xml">external</a> documentation.
--spec scissorArrayv(integer(),[{integer(),integer(),integer(),integer()}]) -> ok.
+%% @doc glScissorArrayv
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorArrayv.xml">external</a> documentation.
+-spec scissorArrayv(First, V) -> ok when First :: integer(),V :: [{integer(),integer(),integer(),integer()}].
scissorArrayv(First,V) ->
cast(5846, <<First:?GLuint,(length(V)):?GLuint,
(<< <<V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>> || {V1,V2,V3,V4} <- V>>)/binary>>).
-%% @spec (Index::integer(),Left::integer(),Bottom::integer(),Width::integer(),Height::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation.
--spec scissorIndexed(integer(),integer(),integer(),integer(),integer()) -> ok.
+%% @doc glScissorIndexe
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation.
+-spec scissorIndexed(Index, Left, Bottom, Width, Height) -> ok when Index :: integer(),Left :: integer(),Bottom :: integer(),Width :: integer(),Height :: integer().
scissorIndexed(Index,Left,Bottom,Width,Height) ->
cast(5847, <<Index:?GLuint,Left:?GLint,Bottom:?GLint,Width:?GLsizei,Height:?GLsizei>>).
-%% @spec (Index::integer(),V::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation.
--spec scissorIndexedv(integer(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc glScissorIndexe
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation.
+-spec scissorIndexedv(Index, V) -> ok when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
scissorIndexedv(Index,{V1,V2,V3,V4}) ->
cast(5848, <<Index:?GLuint,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
-%% @spec (First::integer(),V::[{clamp(),clamp()}]) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeArrayv.xml">external</a> documentation.
--spec depthRangeArrayv(integer(),[{clamp(),clamp()}]) -> ok.
+%% @doc glDepthRangeArrayv
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeArrayv.xml">external</a> documentation.
+-spec depthRangeArrayv(First, V) -> ok when First :: integer(),V :: [{clamp(),clamp()}].
depthRangeArrayv(First,V) ->
cast(5849, <<First:?GLuint,0:32,(length(V)):?GLuint,0:32,
(<< <<V1:?GLclampd,V2:?GLclampd>> || {V1,V2} <- V>>)/binary>>).
-%% @spec (Index::integer(),N::clamp(),F::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeIndexe.xml">external</a> documentation.
--spec depthRangeIndexed(integer(),clamp(),clamp()) -> ok.
+%% @doc glDepthRangeIndexe
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeIndexe.xml">external</a> documentation.
+-spec depthRangeIndexed(Index, N, F) -> ok when Index :: integer(),N :: clamp(),F :: clamp().
depthRangeIndexed(Index,N,F) ->
cast(5850, <<Index:?GLuint,0:32,N:?GLclampd,F:?GLclampd>>).
-%% @spec (Target::enum(),Index::integer()) -> [float()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFloati_v.xml">external</a> documentation.
--spec getFloati_v(enum(),integer()) -> [float()].
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getFloati_v(Target, Index) -> [float()] when Target :: enum(),Index :: integer().
getFloati_v(Target,Index) ->
call(5851, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Target::enum(),Index::integer()) -> [float()]
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetDoublei_v.xml">external</a> documentation.
--spec getDoublei_v(enum(),integer()) -> [float()].
+%% @doc
+%% See {@link getBooleanv/1}
+-spec getDoublei_v(Target, Index) -> [float()] when Target :: enum(),Index :: integer().
getDoublei_v(Target,Index) ->
call(5852, <<Target:?GLenum,Index:?GLuint>>).
-%% @spec (Source::enum(),Type::enum(),Severity::enum(),Ids::[integer()],Enabled::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageControlARB.xml">external</a> documentation.
--spec debugMessageControlARB(enum(),enum(),enum(),[integer()],0|1) -> ok.
+%% @doc glDebugMessageControlARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageControlARB.xml">external</a> documentation.
+-spec debugMessageControlARB(Source, Type, Severity, Ids, Enabled) -> ok when Source :: enum(),Type :: enum(),Severity :: enum(),Ids :: [integer()],Enabled :: 0|1.
debugMessageControlARB(Source,Type,Severity,Ids,Enabled) ->
cast(5853, <<Source:?GLenum,Type:?GLenum,Severity:?GLenum,(length(Ids)):?GLuint,
(<< <<C:?GLuint>> || C <- Ids>>)/binary,0:(((length(Ids)) rem 2)*32),Enabled:?GLboolean>>).
-%% @spec (Source::enum(),Type::enum(),Id::integer(),Severity::enum(),Buf::string()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageInsertARB.xml">external</a> documentation.
--spec debugMessageInsertARB(enum(),enum(),integer(),enum(),string()) -> ok.
+%% @doc glDebugMessageInsertARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageInsertARB.xml">external</a> documentation.
+-spec debugMessageInsertARB(Source, Type, Id, Severity, Buf) -> ok when Source :: enum(),Type :: enum(),Id :: integer(),Severity :: enum(),Buf :: string().
debugMessageInsertARB(Source,Type,Id,Severity,Buf) ->
cast(5854, <<Source:?GLenum,Type:?GLenum,Id:?GLuint,Severity:?GLenum,(list_to_binary([Buf|[0]]))/binary,0:((8-((length(Buf)+ 1) rem 8)) rem 8)>>).
-%% @spec (Count::integer(),Bufsize::integer()) -> {integer(),Sources::[enum()],Types::[enum()],Ids::[integer()],Severities::[enum()],MessageLog::[string()]}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetDebugMessageLogARB.xml">external</a> documentation.
--spec getDebugMessageLogARB(integer(),integer()) -> {integer(),[enum()],[enum()],[integer()],[enum()],[string()]}.
+%% @doc glGetDebugMessageLogARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetDebugMessageLogARB.xml">external</a> documentation.
+-spec getDebugMessageLogARB(Count, Bufsize) -> {integer(),Sources :: [enum()],Types :: [enum()],Ids :: [integer()],Severities :: [enum()],MessageLog :: [string()]} when Count :: integer(),Bufsize :: integer().
getDebugMessageLogARB(Count,Bufsize) ->
call(5855, <<Count:?GLuint,Bufsize:?GLsizei>>).
-%% @spec () -> enum()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetGraphicsResetStatusARB.xml">external</a> documentation.
+%% @doc glGetGraphicsResetStatusARB
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetGraphicsResetStatusARB.xml">external</a> documentation.
-spec getGraphicsResetStatusARB() -> enum().
getGraphicsResetStatusARB() ->
call(5856, <<>>).
-%% @spec () -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResizeBuffersMESA.xml">external</a> documentation.
--spec resizeBuffersMESA() -> ok.
-resizeBuffersMESA() ->
- cast(5857, <<>>).
-
-%% @spec (X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos4dMESA.xml">external</a> documentation.
--spec windowPos4dMESA(float(),float(),float(),float()) -> ok.
-windowPos4dMESA(X,Y,Z,W) ->
- cast(5858, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv windowPos4dMESA(X,Y,Z,W)
--spec windowPos4dvMESA({float(),float(),float(),float()}) -> ok.
-windowPos4dvMESA({X,Y,Z,W}) -> windowPos4dMESA(X,Y,Z,W).
-
-%% @spec (X::float(),Y::float(),Z::float(),W::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos4fMESA.xml">external</a> documentation.
--spec windowPos4fMESA(float(),float(),float(),float()) -> ok.
-windowPos4fMESA(X,Y,Z,W) ->
- cast(5859, <<X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv windowPos4fMESA(X,Y,Z,W)
--spec windowPos4fvMESA({float(),float(),float(),float()}) -> ok.
-windowPos4fvMESA({X,Y,Z,W}) -> windowPos4fMESA(X,Y,Z,W).
-
-%% @spec (X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos4iMESA.xml">external</a> documentation.
--spec windowPos4iMESA(integer(),integer(),integer(),integer()) -> ok.
-windowPos4iMESA(X,Y,Z,W) ->
- cast(5860, <<X:?GLint,Y:?GLint,Z:?GLint,W:?GLint>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv windowPos4iMESA(X,Y,Z,W)
--spec windowPos4ivMESA({integer(),integer(),integer(),integer()}) -> ok.
-windowPos4ivMESA({X,Y,Z,W}) -> windowPos4iMESA(X,Y,Z,W).
-
-%% @spec (X::integer(),Y::integer(),Z::integer(),W::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos4sMESA.xml">external</a> documentation.
--spec windowPos4sMESA(integer(),integer(),integer(),integer()) -> ok.
-windowPos4sMESA(X,Y,Z,W) ->
- cast(5861, <<X:?GLshort,Y:?GLshort,Z:?GLshort,W:?GLshort>>).
-
-%% @spec ({X,Y,Z,W}) -> ok
-%% @equiv windowPos4sMESA(X,Y,Z,W)
--spec windowPos4svMESA({integer(),integer(),integer(),integer()}) -> ok.
-windowPos4svMESA({X,Y,Z,W}) -> windowPos4sMESA(X,Y,Z,W).
-
-%% @spec (Zmin::clamp(),Zmax::clamp()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthBoundsEXT.xml">external</a> documentation.
--spec depthBoundsEXT(clamp(),clamp()) -> ok.
+%% @doc Draw multiple instances of a range of elements with offset applied to instanced attributes
+%%
+%% ``gl:drawArraysInstancedBaseInstance'' behaves identically to {@link gl:drawArrays/3}
+%% except that `Primcount' instances of the range of elements are executed and the value
+%% of the internal counter `InstanceID' advances for each iteration. `InstanceID'
+%% is an internal 32-bit integer counter that may be read by a vertex shader as `?gl_InstanceID'
+%% .
+%%
+%% ``gl:drawArraysInstancedBaseInstance'' has the same effect as: if ( mode or count is
+%% invalid ) generate appropriate error else { for (int i = 0; i &lt; primcount ; i++) {
+%% instanceID = i; glDrawArrays(mode, first, count); } instanceID = 0; }
+%%
+%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2}
+%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The
+%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated
+%% as: |gl_ InstanceID/divisor|&amp;plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible
+%% value of `?gl_InstanceID'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstancedBaseInstance.xml">external</a> documentation.
+-spec drawArraysInstancedBaseInstance(Mode, First, Count, Primcount, Baseinstance) -> ok when Mode :: enum(),First :: integer(),Count :: integer(),Primcount :: integer(),Baseinstance :: integer().
+drawArraysInstancedBaseInstance(Mode,First,Count,Primcount,Baseinstance) ->
+ cast(5857, <<Mode:?GLenum,First:?GLint,Count:?GLsizei,Primcount:?GLsizei,Baseinstance:?GLuint>>).
+
+%% @doc Draw multiple instances of a set of elements with offset applied to instanced attributes
+%%
+%% ``gl:drawElementsInstancedBaseInstance'' behaves identically to {@link gl:drawElements/4}
+%% except that `Primcount' instances of the set of elements are executed and the value
+%% of the internal counter `InstanceID' advances for each iteration. `InstanceID'
+%% is an internal 32-bit integer counter that may be read by a vertex shader as `?gl_InstanceID'
+%% .
+%%
+%% ``gl:drawElementsInstancedBaseInstance'' has the same effect as: if (mode, count, or
+%% type is invalid ) generate appropriate error else { for (int i = 0; i &lt; primcount ;
+%% i++) { instanceID = i; glDrawElements(mode, count, type, indices); } instanceID = 0; }
+%%
+%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2}
+%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The
+%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated
+%% as |gl_ InstanceID/divisor|&amp;plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible
+%% value of `?gl_InstanceID'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseInstance.xml">external</a> documentation.
+-spec drawElementsInstancedBaseInstance(Mode, Count, Type, Indices, Primcount, Baseinstance) -> ok when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Baseinstance :: integer().
+drawElementsInstancedBaseInstance(Mode,Count,Type,Indices,Primcount,Baseinstance) when is_integer(Indices) ->
+ cast(5858, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Baseinstance:?GLuint>>);
+drawElementsInstancedBaseInstance(Mode,Count,Type,Indices,Primcount,Baseinstance) ->
+ send_bin(Indices),
+ cast(5859, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Primcount:?GLsizei,Baseinstance:?GLuint>>).
+
+%% @doc Render multiple instances of a set of primitives from array data with a per-element offset
+%%
+%% ``gl:drawElementsInstancedBaseVertexBaseInstance'' behaves identically to {@link gl:drawElementsInstanced/5}
+%% except that the `i'th element transferred by the corresponding draw call will be
+%% taken from element `Indices' [i] + `Basevertex' of each enabled array. If the
+%% resulting value is larger than the maximum value representable by `Type' , it is as
+%% if the calculation were upconverted to 32-bit unsigned integers (with wrapping on overflow
+%% conditions). The operation is undefined if the sum would be negative. The `Basevertex'
+%% has no effect on the shader-visible value of `?gl_VertexID'.
+%%
+%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2}
+%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The
+%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated
+%% as |gl_ InstanceID/divisor|&amp;plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible
+%% value of `?gl_InstanceID'.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertexBaseInstance.xml">external</a> documentation.
+-spec drawElementsInstancedBaseVertexBaseInstance(Mode, Count, Type, Indices, Primcount, Basevertex, Baseinstance) -> ok when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Basevertex :: integer(),Baseinstance :: integer().
+drawElementsInstancedBaseVertexBaseInstance(Mode,Count,Type,Indices,Primcount,Basevertex,Baseinstance) when is_integer(Indices) ->
+ cast(5860, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Basevertex:?GLint,Baseinstance:?GLuint>>);
+drawElementsInstancedBaseVertexBaseInstance(Mode,Count,Type,Indices,Primcount,Basevertex,Baseinstance) ->
+ send_bin(Indices),
+ cast(5861, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Primcount:?GLsizei,Basevertex:?GLint,Baseinstance:?GLuint>>).
+
+%% @doc glDrawTransformFeedbackInstance
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackInstance.xml">external</a> documentation.
+-spec drawTransformFeedbackInstanced(Mode, Id, Primcount) -> ok when Mode :: enum(),Id :: integer(),Primcount :: integer().
+drawTransformFeedbackInstanced(Mode,Id,Primcount) ->
+ cast(5862, <<Mode:?GLenum,Id:?GLuint,Primcount:?GLsizei>>).
+
+%% @doc glDrawTransformFeedbackStreamInstance
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStreamInstance.xml">external</a> documentation.
+-spec drawTransformFeedbackStreamInstanced(Mode, Id, Stream, Primcount) -> ok when Mode :: enum(),Id :: integer(),Stream :: integer(),Primcount :: integer().
+drawTransformFeedbackStreamInstanced(Mode,Id,Stream,Primcount) ->
+ cast(5863, <<Mode:?GLenum,Id:?GLuint,Stream:?GLuint,Primcount:?GLsizei>>).
+
+%% @doc glGetInternalformat
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInternalformat.xml">external</a> documentation.
+-spec getInternalformativ(Target, Internalformat, Pname, BufSize) -> [integer()] when Target :: enum(),Internalformat :: enum(),Pname :: enum(),BufSize :: integer().
+getInternalformativ(Target,Internalformat,Pname,BufSize) ->
+ call(5864, <<Target:?GLenum,Internalformat:?GLenum,Pname:?GLenum,BufSize:?GLsizei>>).
+
+%% @doc Bind a level of a texture to an image unit
+%%
+%% ``gl:bindImageTexture'' binds a single level of a texture to an image unit for the purpose
+%% of reading and writing it from shaders. `Unit' specifies the zero-based index of
+%% the image unit to which to bind the texture level. `Texture' specifies the name of
+%% an existing texture object to bind to the image unit. If `Texture' is zero, then
+%% any existing binding to the image unit is broken. `Level' specifies the level of
+%% the texture to bind to the image unit.
+%%
+%% If `Texture' is the name of a one-, two-, or three-dimensional array texture, a
+%% cube map or cube map array texture, or a two-dimensional multisample array texture, then
+%% it is possible to bind either the entire array, or only a single layer of the array to
+%% the image unit. In such cases, if `Layered' is `?GL_TRUE', the entire array
+%% is attached to the image unit and `Layer' is ignored. However, if `Layered' is `?GL_FALSE'
+%% then `Layer' specifies the layer of the array to attach to the image unit.
+%%
+%% `Access' specifies the access types to be performed by shaders and may be set to `?GL_READ_ONLY'
+%% , `?GL_WRITE_ONLY', or `?GL_READ_WRITE' to indicate read-only, write-only or
+%% read-write access, respectively. Violation of the access type specified in `Access'
+%% (for example, if a shader writes to an image bound with `Access' set to `?GL_READ_ONLY'
+%% ) will lead to undefined results, possibly including program termination.
+%%
+%% `Format' specifies the format that is to be used when performing formatted stores
+%% into the image from shaders. `Format' must be compatible with the texture's internal
+%% format and must be one of the formats listed in the following table.
+%%
+%% <table><tbody><tr><td>` Image Unit Format '</td><td>` Format Qualifier '</td></tr>
+%% </tbody><tbody><tr><td>`?GL_RGBA32F'</td><td>rgba32f</td></tr><tr><td>`?GL_RGBA16F'
+%% </td><td>rgba16f</td></tr><tr><td>`?GL_RG32F'</td><td>rg32f</td></tr><tr><td>`?GL_RG16F'
+%% </td><td>rg16f</td></tr><tr><td>`?GL_R11F_G11F_B10F'</td><td>r11f_g11f_b10f</td></tr>
+%% <tr><td>`?GL_R32F'</td><td>r32f</td></tr><tr><td>`?GL_R16F'</td><td>r16f</td></tr>
+%% <tr><td>`?GL_RGBA32UI'</td><td>rgba32ui</td></tr><tr><td>`?GL_RGBA16UI'</td><td>
+%% rgba16ui</td></tr><tr><td>`?GL_RGB10_A2UI'</td><td>rgb10_a2ui</td></tr><tr><td>`?GL_RGBA8UI'
+%% </td><td>rgba8ui</td></tr><tr><td>`?GL_RG32UI'</td><td>rg32ui</td></tr><tr><td>`?GL_RG16UI'
+%% </td><td>rg16ui</td></tr><tr><td>`?GL_RG8UI'</td><td>rg8ui</td></tr><tr><td>`?GL_R32UI'
+%% </td><td>r32ui</td></tr><tr><td>`?GL_R16UI'</td><td>r16ui</td></tr><tr><td>`?GL_R8UI'
+%% </td><td>r8ui</td></tr><tr><td>`?GL_RGBA32I'</td><td>rgba32i</td></tr><tr><td>`?GL_RGBA16I'
+%% </td><td>rgba16i</td></tr><tr><td>`?GL_RGBA8I'</td><td>rgba8i</td></tr><tr><td>`?GL_RG32I'
+%% </td><td>rg32i</td></tr><tr><td>`?GL_RG16I'</td><td>rg16i</td></tr><tr><td>`?GL_RG8I'
+%% </td><td>rg8i</td></tr><tr><td>`?GL_R32I'</td><td>r32i</td></tr><tr><td>`?GL_R16I'
+%% </td><td>r16i</td></tr><tr><td>`?GL_R8I'</td><td>r8i</td></tr><tr><td>`?GL_RGBA16'
+%% </td><td>rgba16</td></tr><tr><td>`?GL_RGB10_A2'</td><td>rgb10_a2</td></tr><tr><td>`?GL_RGBA8'
+%% </td><td>rgba8</td></tr><tr><td>`?GL_RG16'</td><td>rg16</td></tr><tr><td>`?GL_RG8'
+%% </td><td>rg8</td></tr><tr><td>`?GL_R16'</td><td>r16</td></tr><tr><td>`?GL_R8'</td>
+%% <td>r8</td></tr><tr><td>`?GL_RGBA16_SNORM'</td><td>rgba16_snorm</td></tr><tr><td>`?GL_RGBA8_SNORM'
+%% </td><td>rgba8_snorm</td></tr><tr><td>`?GL_RG16_SNORM'</td><td>rg16_snorm</td></tr><tr>
+%% <td>`?GL_RG8_SNORM'</td><td>rg8_snorm</td></tr><tr><td>`?GL_R16_SNORM'</td><td>r16_snorm
+%% </td></tr><tr><td>`?GL_R8_SNORM'</td><td>r8_snorm</td></tr></tbody></table>
+%%
+%% When a texture is bound to an image unit, the `Format' parameter for the image unit
+%% need not exactly match the texture internal format as long as the formats are considered
+%% compatible as defined in the OpenGL Specification. The matching criterion used for a given
+%% texture may be determined by calling {@link gl:getTexParameterfv/2} with `Value' set
+%% to `?GL_IMAGE_FORMAT_COMPATIBILITY_TYPE', with return values of `?GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE'
+%% and `?GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS', specifying matches by size and class,
+%% respectively.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindImageTexture.xml">external</a> documentation.
+-spec bindImageTexture(Unit, Texture, Level, Layered, Layer, Access, Format) -> ok when Unit :: integer(),Texture :: integer(),Level :: integer(),Layered :: 0|1,Layer :: integer(),Access :: enum(),Format :: enum().
+bindImageTexture(Unit,Texture,Level,Layered,Layer,Access,Format) ->
+ cast(5865, <<Unit:?GLuint,Texture:?GLuint,Level:?GLint,Layered:?GLboolean,0:24,Layer:?GLint,Access:?GLenum,Format:?GLenum>>).
+
+%% @doc Defines a barrier ordering memory transactions
+%%
+%% ``gl:memoryBarrier'' defines a barrier ordering the memory transactions issued prior
+%% to the command relative to those issued after the barrier. For the purposes of this ordering,
+%% memory transactions performed by shaders are considered to be issued by the rendering
+%% command that triggered the execution of the shader. `Barriers' is a bitfield indicating
+%% the set of operations that are synchronized with shader stores; the bits used in `Barriers'
+%% are as follows:
+%%
+%%
+%%
+%% `?GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT': If set, vertex data sourced from buffer objects
+%% after the barrier will reflect data written by shaders prior to the barrier. The set of
+%% buffer objects affected by this bit is derived from the buffer object bindings used for
+%% generic vertex attributes derived from the `?GL_VERTEX_ATTRIB_ARRAY_BUFFER' bindings.
+%%
+%%
+%% `?GL_ELEMENT_ARRAY_BARRIER_BIT': If set, vertex array indices sourced from buffer
+%% objects after the barrier will reflect data written by shaders prior to the barrier. The
+%% buffer objects affected by this bit are derived from the `?GL_ELEMENT_ARRAY_BUFFER'
+%% binding.
+%%
+%% `?GL_UNIFORM_BARRIER_BIT': Shader uniforms sourced from buffer objects after the
+%% barrier will reflect data written by shaders prior to the barrier.
+%%
+%% `?GL_TEXTURE_FETCH_BARRIER_BIT': Texture fetches from shaders, including fetches
+%% from buffer object memory via buffer textures, after the barrier will reflect data written
+%% by shaders prior to the barrier.
+%%
+%% `?GL_SHADER_IMAGE_ACCESS_BARRIER_BIT': Memory accesses using shader image load,
+%% store, and atomic built-in functions issued after the barrier will reflect data written
+%% by shaders prior to the barrier. Additionally, image stores and atomics issued after the
+%% barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches,
+%% vertex fetches) initiated prior to the barrier complete.
+%%
+%% `?GL_COMMAND_BARRIER_BIT': Command data sourced from buffer objects by Draw*Indirect
+%% commands after the barrier will reflect data written by shaders prior to the barrier.
+%% The buffer objects affected by this bit are derived from the `?GL_DRAW_INDIRECT_BUFFER'
+%% binding.
+%%
+%% `?GL_PIXEL_BUFFER_BARRIER_BIT': Reads and writes of buffer objects via the `?GL_PIXEL_PACK_BUFFER'
+%% and `?GL_PIXEL_UNPACK_BUFFER' bindings (via {@link gl:readPixels/7} , {@link gl:texSubImage1D/7}
+%% , etc.) after the barrier will reflect data written by shaders prior to the barrier. Additionally,
+%% buffer object writes issued after the barrier will wait on the completion of all shader
+%% writes initiated prior to the barrier.
+%%
+%% `?GL_TEXTURE_UPDATE_BARRIER_BIT': Writes to a texture via ``gl:tex(Sub)Image*'', ``gl:copyTex(Sub)Image*''
+%% , ``gl:compressedTex(Sub)Image*'', and reads via {@link gl:getTexImage/5} after the barrier
+%% will reflect data written by shaders prior to the barrier. Additionally, texture writes
+%% from these commands issued after the barrier will not execute until all shader writes
+%% initiated prior to the barrier complete.
+%%
+%% `?GL_BUFFER_UPDATE_BARRIER_BIT': Reads or writes via {@link gl:bufferSubData/4} , {@link gl:copyBufferSubData/5}
+%% , or {@link gl:getBufferSubData/4} , or to buffer object memory mapped by see `glMapBuffer'
+%% or see `glMapBufferRange' after the barrier will reflect data written by shaders
+%% prior to the barrier. Additionally, writes via these commands issued after the barrier
+%% will wait on the completion of any shader writes to the same memory initiated prior to
+%% the barrier.
+%%
+%% `?GL_FRAMEBUFFER_BARRIER_BIT': Reads and writes via framebuffer object attachments
+%% after the barrier will reflect data written by shaders prior to the barrier. Additionally,
+%% framebuffer writes issued after the barrier will wait on the completion of all shader
+%% writes issued prior to the barrier.
+%%
+%% `?GL_TRANSFORM_FEEDBACK_BARRIER_BIT': Writes via transform feedback bindings after
+%% the barrier will reflect data written by shaders prior to the barrier. Additionally, transform
+%% feedback writes issued after the barrier will wait on the completion of all shader writes
+%% issued prior to the barrier.
+%%
+%% `?GL_ATOMIC_COUNTER_BARRIER_BIT': Accesses to atomic counters after the barrier
+%% will reflect writes prior to the barrier.
+%%
+%% If `Barriers' is `?GL_ALL_BARRIER_BITS', shader memory accesses will be synchronized
+%% relative to all the operations described above.
+%%
+%% Implementations may cache buffer object and texture image memory that could be written
+%% by shaders in multiple caches; for example, there may be separate caches for texture,
+%% vertex fetching, and one or more caches for shader memory accesses. Implementations are
+%% not required to keep these caches coherent with shader memory writes. Stores issued by
+%% one invocation may not be immediately observable by other pipeline stages or other shader
+%% invocations because the value stored may remain in a cache local to the processor executing
+%% the store, or because data overwritten by the store is still in a cache elsewhere in the
+%% system. When ``gl:memoryBarrier'' is called, the GL flushes and/or invalidates any caches
+%% relevant to the operations specified by the `Barriers' parameter to ensure consistent
+%% ordering of operations across the barrier.
+%%
+%% To allow for independent shader invocations to communicate by reads and writes to a common
+%% memory address, image variables in the OpenGL Shading Language may be declared as "coherent".
+%% Buffer object or texture image memory accessed through such variables may be cached only
+%% if caches are automatically updated due to stores issued by any other shader invocation.
+%% If the same address is accessed using both coherent and non-coherent variables, the accesses
+%% using variables declared as coherent will observe the results stored using coherent variables
+%% in other invocations. Using variables declared as "coherent" guarantees only that the
+%% results of stores will be immediately visible to shader invocations using similarly-declared
+%% variables; calling ``gl:memoryBarrier'' is required to ensure that the stores are visible
+%% to other operations.
+%%
+%% The following guidelines may be helpful in choosing when to use coherent memory accesses
+%% and when to use barriers.
+%%
+%% Data that are read-only or constant may be accessed without using coherent variables or
+%% calling MemoryBarrier(). Updates to the read-only data via API calls such as BufferSubData
+%% will invalidate shader caches implicitly as required.
+%%
+%% Data that are shared between shader invocations at a fine granularity (e.g., written by
+%% one invocation, consumed by another invocation) should use coherent variables to read
+%% and write the shared data.
+%%
+%% Data written by one shader invocation and consumed by other shader invocations launched
+%% as a result of its execution ("dependent invocations") should use coherent variables in
+%% the producing shader invocation and call memoryBarrier() after the last write. The consuming
+%% shader invocation should also use coherent variables.
+%%
+%% Data written to image variables in one rendering pass and read by the shader in a later
+%% pass need not use coherent variables or memoryBarrier(). Calling MemoryBarrier() with
+%% the SHADER_IMAGE_ACCESS_BARRIER_BIT set in `Barriers' between passes is necessary.
+%%
+%% Data written by the shader in one rendering pass and read by another mechanism (e.g.,
+%% vertex or index buffer pulling) in a later pass need not use coherent variables or memoryBarrier().
+%% Calling ``gl:memoryBarrier'' with the appropriate bits set in `Barriers' between
+%% passes is necessary.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMemoryBarrier.xml">external</a> documentation.
+-spec memoryBarrier(Barriers) -> ok when Barriers :: integer().
+memoryBarrier(Barriers) ->
+ cast(5866, <<Barriers:?GLbitfield>>).
+
+%% @doc Simultaneously specify storage for all levels of a one-dimensional texture
+%%
+%% ``gl:texStorage1D'' specifies the storage requirements for all levels of a one-dimensional
+%% texture simultaneously. Once a texture is specified with this command, the format and
+%% dimensions of all levels become immutable unless it is a proxy texture. The contents of
+%% the image may still be modified, however, its storage requirements may not change. Such
+%% a texture is referred to as an `immutable-format' texture.
+%%
+%% Calling ``gl:texStorage1D'' is equivalent, assuming no errors are generated, to executing
+%% the following pseudo-code: for (i = 0; i &lt; levels; i++) { glTexImage1D(target, i,
+%% internalformat, width, 0, format, type, NULL); width = max(1, (width / 2)); }
+%%
+%% Since no texture data is actually provided, the values used in the pseudo-code for `Format'
+%% and `Type' are irrelevant and may be considered to be any values that are legal
+%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the
+%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F'
+%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined
+%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon
+%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The
+%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2}
+%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the
+%% dimensions or format of the texture object may be made. Using any command that might alter
+%% the dimensions or format of the texture object (such as {@link gl:texImage1D/8} or another
+%% call to ``gl:texStorage1D'') will result in the generation of a `?GL_INVALID_OPERATION'
+%% error, even if it would not, in fact, alter the dimensions or format of the object.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage1D.xml">external</a> documentation.
+-spec texStorage1D(Target, Levels, Internalformat, Width) -> ok when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer().
+texStorage1D(Target,Levels,Internalformat,Width) ->
+ cast(5867, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei>>).
+
+%% @doc Simultaneously specify storage for all levels of a two-dimensional or one-dimensional array texture
+%%
+%% ``gl:texStorage2D'' specifies the storage requirements for all levels of a two-dimensional
+%% texture or one-dimensional texture array simultaneously. Once a texture is specified with
+%% this command, the format and dimensions of all levels become immutable unless it is a
+%% proxy texture. The contents of the image may still be modified, however, its storage requirements
+%% may not change. Such a texture is referred to as an `immutable-format' texture.
+%%
+%% The behavior of ``gl:texStorage2D'' depends on the `Target' parameter. When `Target'
+%% is `?GL_TEXTURE_2D', `?GL_PROXY_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE', `?GL_PROXY_TEXTURE_RECTANGLE'
+%% or `?GL_PROXY_TEXTURE_CUBE_MAP', calling ``gl:texStorage2D'' is equivalent, assuming
+%% no errors are generated, to executing the following pseudo-code: for (i = 0; i &lt; levels;
+%% i++) { glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
+%% width = max(1, (width / 2)); height = max(1, (height / 2)); }
+%%
+%% When `Target' is `?GL_TEXTURE_CUBE_MAP', ``gl:texStorage2D'' is equivalent
+%% to: for (i = 0; i &lt; levels; i++) { for (face in (+X, -X, +Y, -Y, +Z, -Z)) { glTexImage2D(face,
+%% i, internalformat, width, height, 0, format, type, NULL); } width = max(1, (width / 2));
+%% height = max(1, (height / 2)); }
+%%
+%% When `Target' is `?GL_TEXTURE_1D' or `?GL_TEXTURE_1D_ARRAY', ``gl:texStorage2D''
+%% is equivalent to: for (i = 0; i &lt; levels; i++) { glTexImage2D(target, i, internalformat,
+%% width, height, 0, format, type, NULL); width = max(1, (width / 2)); }
+%%
+%% Since no texture data is actually provided, the values used in the pseudo-code for `Format'
+%% and `Type' are irrelevant and may be considered to be any values that are legal
+%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the
+%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F'
+%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined
+%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon
+%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The
+%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2}
+%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the
+%% dimensions or format of the texture object may be made. Using any command that might alter
+%% the dimensions or format of the texture object (such as {@link gl:texImage2D/9} or another
+%% call to ``gl:texStorage2D'') will result in the generation of a `?GL_INVALID_OPERATION'
+%% error, even if it would not, in fact, alter the dimensions or format of the object.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage2D.xml">external</a> documentation.
+-spec texStorage2D(Target, Levels, Internalformat, Width, Height) -> ok when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer().
+texStorage2D(Target,Levels,Internalformat,Width,Height) ->
+ cast(5868, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>).
+
+%% @doc Simultaneously specify storage for all levels of a three-dimensional, two-dimensional array or cube-map array texture
+%%
+%% ``gl:texStorage3D'' specifies the storage requirements for all levels of a three-dimensional,
+%% two-dimensional array or cube-map array texture simultaneously. Once a texture is specified
+%% with this command, the format and dimensions of all levels become immutable unless it
+%% is a proxy texture. The contents of the image may still be modified, however, its storage
+%% requirements may not change. Such a texture is referred to as an `immutable-format'
+%% texture.
+%%
+%% The behavior of ``gl:texStorage3D'' depends on the `Target' parameter. When `Target'
+%% is `?GL_TEXTURE_3D', or `?GL_PROXY_TEXTURE_3D', calling ``gl:texStorage3D''
+%% is equivalent, assuming no errors are generated, to executing the following pseudo-code:
+%% for (i = 0; i &lt; levels; i++) { glTexImage3D(target, i, internalformat, width, height,
+%% depth, 0, format, type, NULL); width = max(1, (width / 2)); height = max(1, (height /
+%% 2)); depth = max(1, (depth / 2)); }
+%%
+%% When `Target' is `?GL_TEXTURE_2D_ARRAY', `?GL_PROXY_TEXTURE_2D_ARRAY', `?GL_TEXTURE_CUBE_MAP_ARRAY'
+%% , or `?GL_PROXY_TEXTURE_CUBE_MAP_ARRAY', ``gl:texStorage3D'' is equivalent to:
+%% for (i = 0; i &lt; levels; i++) { glTexImage3D(target, i, internalformat, width, height,
+%% depth, 0, format, type, NULL); width = max(1, (width / 2)); height = max(1, (height /
+%% 2)); }
+%%
+%% Since no texture data is actually provided, the values used in the pseudo-code for `Format'
+%% and `Type' are irrelevant and may be considered to be any values that are legal
+%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the
+%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F'
+%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined
+%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon
+%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The
+%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2}
+%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the
+%% dimensions or format of the texture object may be made. Using any command that might alter
+%% the dimensions or format of the texture object (such as {@link gl:texImage3D/10} or another
+%% call to ``gl:texStorage3D'') will result in the generation of a `?GL_INVALID_OPERATION'
+%% error, even if it would not, in fact, alter the dimensions or format of the object.
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage3D.xml">external</a> documentation.
+-spec texStorage3D(Target, Levels, Internalformat, Width, Height, Depth) -> ok when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Depth :: integer().
+texStorage3D(Target,Levels,Internalformat,Width,Height,Depth) ->
+ cast(5869, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei>>).
+
+%% @doc glDepthBoundsEXT
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthBoundsEXT.xml">external</a> documentation.
+-spec depthBoundsEXT(Zmin, Zmax) -> ok when Zmin :: clamp(),Zmax :: clamp().
depthBoundsEXT(Zmin,Zmax) ->
- cast(5862, <<Zmin:?GLclampd,Zmax:?GLclampd>>).
+ cast(5870, <<Zmin:?GLclampd,Zmax:?GLclampd>>).
-%% @spec (StencilTagBits::integer(),StencilClearTag::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilClearTagEXT.xml">external</a> documentation.
--spec stencilClearTagEXT(integer(),integer()) -> ok.
+%% @doc glStencilClearTagEXT
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilClearTagEXT.xml">external</a> documentation.
+-spec stencilClearTagEXT(StencilTagBits, StencilClearTag) -> ok when StencilTagBits :: integer(),StencilClearTag :: integer().
stencilClearTagEXT(StencilTagBits,StencilClearTag) ->
- cast(5863, <<StencilTagBits:?GLsizei,StencilClearTag:?GLuint>>).
+ cast(5871, <<StencilTagBits:?GLsizei,StencilClearTag:?GLuint>>).
diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl
index c16f0cf125..2c82c9792f 100644
--- a/lib/wx/src/gen/glu.erl
+++ b/lib/wx/src/gen/glu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 @@
%%
%% Booleans are represented by integers 0 and 1.
-%% @type mem(). memory block
-%% @type enum(). An integer defined in gl.hrl
-%% @type offset(). An integer which is an offset in an array
-%% @type clamp(). A float clamped between 0.0 - 1.0
-
-module(glu).
-compile(inline).
-define(GLenum,32/native-unsigned).
@@ -53,8 +48,13 @@
-define(GLsync,64/native-unsigned).
-define(GLuint64,64/native-unsigned).
-define(GLint64,64/native-signed).
--type enum() :: non_neg_integer().
--type mem() :: binary() | tuple().
+-type vertex() :: {float(), float(), float()}.
+-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl or glu.hrl
+-type matrix() :: {float(),float(),float(),float(),
+ float(),float(),float(),float(),
+ float(),float(),float(),float(),
+ float(),float(),float(),float()}.
+-type mem() :: binary() | tuple(). %% Memory block
-export([tesselate/2,build1DMipmapLevels/9,build1DMipmaps/6,build2DMipmapLevels/10,
build2DMipmaps/7,build3DMipmapLevels/11,build3DMipmaps/8,checkExtension/2,
@@ -66,193 +66,676 @@
-import(gl, [call/2,cast/2,send_bin/1]).
%% API
-%% @spec (Vec3, [Vec3]) -> {Triangles, VertexPos}
-%% Vec3 = {float(),float(),float()}
-%% Triangles = [VertexIndex::integer()]
-%% VertexPos = binary()
%% @doc General purpose polygon triangulation.
%% The first argument is the normal and the second a list of
%% vertex positions. Returned is a list of indecies of the vertices
%% and a binary (64bit native float) containing an array of
%% vertex positions, it starts with the vertices in Vs and
%% may contain newly created vertices in the end.
+-spec tesselate(Normal, [Vs]) -> {Triangles, VertexPos}
+ when Normal :: vertex(), Vs :: vertex(),
+ Triangles :: [integer()], VertexPos :: binary().
tesselate({Nx,Ny,Nz}, Vs) ->
call(5000, <<(length(Vs)):32/native,0:32,
Nx:?GLdouble,Ny:?GLdouble,Nz:?GLdouble,
(<< <<Vx:?GLdouble,Vy:?GLdouble,Vz:?GLdouble >>
|| {Vx,Vy,Vz} <- Vs>>)/binary >>).
-%% @spec (Target::enum(),InternalFormat::integer(),Width::integer(),Format::enum(),Type::enum(),Level::integer(),Base::integer(),Max::integer(),Data::binary()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmapLevels.xml">external</a> documentation.
--spec build1DMipmapLevels(enum(),integer(),integer(),enum(),enum(),integer(),integer(),integer(),binary()) -> integer().
+%% @doc Builds a subset of one-dimensional mipmap levels
+%%
+%% ``glu:build1DMipmapLevels'' builds a subset of prefiltered one-dimensional texture maps
+%% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture
+%% mapped primitives.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data'
+%% in half until size 1*1 is reached. At each level, each texel in the halved mipmap
+%% level is an average of the corresponding two texels in the larger mipmap level. {@link gl:texImage1D/8}
+%% is called to load these mipmap levels from `Base' to `Max' . If `Max' is
+%% larger than the highest mipmap level for the texture of the specified size, then a GLU
+%% error code is returned (see {@link glu:errorString/1} ) and nothing is loaded.
+%%
+%% For example, if `Level' is 2 and `Width' is 16, the following levels are possible:
+%% 16*1, 8*1, 4*1, 2*1, 1*1. These correspond to levels 2 through 6 respectively.
+%% If `Base' is 3 and `Max' is 5, then only mipmap levels 8*1, 4*1 and 2*1
+%% are loaded. However, if `Max' is 7, then an error is returned and nothing is loaded
+%% since `Max' is larger than the highest mipmap level which is, in this case, 6.
+%%
+%% The highest mipmap level can be derived from the formula log 2(width*2 level).
+%%
+%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
+%% for `Type' parameter. See the {@link gl:drawPixels/5} reference page for a description
+%% of the acceptable values for `Level' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmapLevels.xml">external</a> documentation.
+-spec build1DMipmapLevels(Target, InternalFormat, Width, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary().
build1DMipmapLevels(Target,InternalFormat,Width,Format,Type,Level,Base,Max,Data) ->
send_bin(Data),
call(5010, <<Target:?GLenum,InternalFormat:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Level:?GLint,Base:?GLint,Max:?GLint>>).
-%% @spec (Target::enum(),InternalFormat::integer(),Width::integer(),Format::enum(),Type::enum(),Data::binary()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmaps.xml">external</a> documentation.
--spec build1DMipmaps(enum(),integer(),integer(),enum(),enum(),binary()) -> integer().
+%% @doc Builds a one-dimensional mipmap
+%%
+%% ``glu:build1DMipmaps'' builds a series of prefiltered one-dimensional texture maps of
+%% decreasing resolutions called a mipmap. This is used for the antialiasing of texture mapped
+%% primitives.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% Initially, the `Width' of `Data' is checked to see if it is a power of 2. If
+%% not, a copy of `Data' is scaled up or down to the nearest power of 2. (If `Width'
+%% is exactly between powers of 2, then the copy of `Data' will scale upwards.) This
+%% copy will be used for subsequent mipmapping operations described below. For example, if `Width'
+%% is 57, then a copy of `Data' will scale up to 64 before mipmapping takes place.
+%%
+%% Then, proxy textures (see {@link gl:texImage1D/8} ) are used to determine if the implementation
+%% can fit the requested texture. If not, `Width' is continually halved until it fits.
+%%
+%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half
+%% until size 1*1 is reached. At each level, each texel in the halved mipmap level is an
+%% average of the corresponding two texels in the larger mipmap level.
+%%
+%% {@link gl:texImage1D/8} is called to load each of these mipmap levels. Level 0 is a copy
+%% of `Data' . The highest level is (log 2)(width). For example, if `Width' is 64 and the implementation
+%% can store a texture of this size, the following mipmap levels are built: 64*1, 32*1,
+%% 16*1, 8*1, 4*1, 2*1, and 1*1. These correspond to levels 0 through 6, respectively.
+%%
+%%
+%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
+%% for the `Type' parameter. See the {@link gl:drawPixels/5} reference page for a description
+%% of the acceptable values for the `Data' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmaps.xml">external</a> documentation.
+-spec build1DMipmaps(Target, InternalFormat, Width, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Data :: binary().
build1DMipmaps(Target,InternalFormat,Width,Format,Type,Data) ->
send_bin(Data),
call(5011, <<Target:?GLenum,InternalFormat:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),InternalFormat::integer(),Width::integer(),Height::integer(),Format::enum(),Type::enum(),Level::integer(),Base::integer(),Max::integer(),Data::binary()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmapLevels.xml">external</a> documentation.
--spec build2DMipmapLevels(enum(),integer(),integer(),integer(),enum(),enum(),integer(),integer(),integer(),binary()) -> integer().
+%% @doc Builds a subset of two-dimensional mipmap levels
+%%
+%% ``glu:build2DMipmapLevels'' builds a subset of prefiltered two-dimensional texture maps
+%% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture
+%% mapped primitives.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data'
+%% in half along both dimensions until size 1*1 is reached. At each level, each texel
+%% in the halved mipmap level is an average of the corresponding four texels in the larger
+%% mipmap level. (In the case of rectangular images, the decimation will ultimately reach
+%% an N*1 or 1*N configuration. Here, two texels are averaged instead.) {@link gl:texImage2D/9}
+%% is called to load these mipmap levels from `Base' to `Max' . If `Max' is
+%% larger than the highest mipmap level for the texture of the specified size, then a GLU
+%% error code is returned (see {@link glu:errorString/1} ) and nothing is loaded.
+%%
+%% For example, if `Level' is 2 and `Width' is 16 and `Height' is 8, the
+%% following levels are possible: 16*8, 8*4, 4*2, 2*1, 1*1. These correspond to
+%% levels 2 through 6 respectively. If `Base' is 3 and `Max' is 5, then only mipmap
+%% levels 8*4, 4*2, and 2*1 are loaded. However, if `Max' is 7, then an error is
+%% returned and nothing is loaded since `Max' is larger than the highest mipmap level
+%% which is, in this case, 6.
+%%
+%% The highest mipmap level can be derived from the formula log 2(max(width height)*2 level).
+%%
+%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
+%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
+%% of the acceptable values for `Type' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmapLevels.xml">external</a> documentation.
+-spec build2DMipmapLevels(Target, InternalFormat, Width, Height, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary().
build2DMipmapLevels(Target,InternalFormat,Width,Height,Format,Type,Level,Base,Max,Data) ->
send_bin(Data),
call(5012, <<Target:?GLenum,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Level:?GLint,Base:?GLint,Max:?GLint>>).
-%% @spec (Target::enum(),InternalFormat::integer(),Width::integer(),Height::integer(),Format::enum(),Type::enum(),Data::binary()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmaps.xml">external</a> documentation.
--spec build2DMipmaps(enum(),integer(),integer(),integer(),enum(),enum(),binary()) -> integer().
+%% @doc Builds a two-dimensional mipmap
+%%
+%% ``glu:build2DMipmaps'' builds a series of prefiltered two-dimensional texture maps of
+%% decreasing resolutions called a mipmap. This is used for the antialiasing of texture-mapped
+%% primitives.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% Initially, the `Width' and `Height' of `Data' are checked to see if they
+%% are a power of 2. If not, a copy of `Data' (not `Data' ), is scaled up or down
+%% to the nearest power of 2. This copy will be used for subsequent mipmapping operations
+%% described below. (If `Width' or `Height' is exactly between powers of 2, then
+%% the copy of `Data' will scale upwards.) For example, if `Width' is 57 and `Height'
+%% is 23, then a copy of `Data' will scale up to 64 in `Width' and down to 16
+%% in depth, before mipmapping takes place.
+%%
+%% Then, proxy textures (see {@link gl:texImage2D/9} ) are used to determine if the implementation
+%% can fit the requested texture. If not, both dimensions are continually halved until it
+%% fits. (If the OpenGL version is (&lt;= 1.0, both maximum texture dimensions are clamped
+%% to the value returned by {@link gl:getBooleanv/1} with the argument `?GLU_MAX_TEXTURE_SIZE'
+%% .)
+%%
+%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half
+%% along both dimensions until size 1*1 is reached. At each level, each texel in the halved
+%% mipmap level is an average of the corresponding four texels in the larger mipmap level.
+%% (In the case of rectangular images, the decimation will ultimately reach an N*1 or 1*N
+%% configuration. Here, two texels are averaged instead.)
+%%
+%% {@link gl:texImage2D/9} is called to load each of these mipmap levels. Level 0 is a copy
+%% of `Data' . The highest level is (log 2)(max(width height)). For example, if `Width' is 64 and `Height'
+%% is 16 and the implementation can store a texture of this size, the following mipmap levels
+%% are built: 64*16, 32*8, 16*4, 8*2, 4*1, 2*1, and 1*1 These correspond to
+%% levels 0 through 6, respectively.
+%%
+%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
+%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
+%% of the acceptable values for `Type' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmaps.xml">external</a> documentation.
+-spec build2DMipmaps(Target, InternalFormat, Width, Height, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Data :: binary().
build2DMipmaps(Target,InternalFormat,Width,Height,Format,Type,Data) ->
send_bin(Data),
call(5013, <<Target:?GLenum,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (Target::enum(),InternalFormat::integer(),Width::integer(),Height::integer(),Depth::integer(),Format::enum(),Type::enum(),Level::integer(),Base::integer(),Max::integer(),Data::binary()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmapLevels.xml">external</a> documentation.
--spec build3DMipmapLevels(enum(),integer(),integer(),integer(),integer(),enum(),enum(),integer(),integer(),integer(),binary()) -> integer().
+%% @doc Builds a subset of three-dimensional mipmap levels
+%%
+%% ``glu:build3DMipmapLevels'' builds a subset of prefiltered three-dimensional texture
+%% maps of decreasing resolutions called a mipmap. This is used for the antialiasing of texture
+%% mapped primitives.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data'
+%% in half along both dimensions until size 1*1*1 is reached. At each level, each texel
+%% in the halved mipmap level is an average of the corresponding eight texels in the larger
+%% mipmap level. (If exactly one of the dimensions is 1, four texels are averaged. If exactly
+%% two of the dimensions are 1, two texels are averaged.) {@link gl:texImage3D/10} is called
+%% to load these mipmap levels from `Base' to `Max' . If `Max' is larger than
+%% the highest mipmap level for the texture of the specified size, then a GLU error code
+%% is returned (see {@link glu:errorString/1} ) and nothing is loaded.
+%%
+%% For example, if `Level' is 2 and `Width' is 16, `Height' is 8 and `Depth'
+%% is 4, the following levels are possible: 16*8*4, 8*4*2, 4*2*1, 2*1*1, 1*1*1.
+%% These correspond to levels 2 through 6 respectively. If `Base' is 3 and `Max'
+%% is 5, then only mipmap levels 8*4*2, 4*2*1, and 2*1*1 are loaded. However, if `Max'
+%% is 7, then an error is returned and nothing is loaded, since `Max' is larger than
+%% the highest mipmap level which is, in this case, 6.
+%%
+%% The highest mipmap level can be derived from the formula log 2(max(width height depth)*2 level).
+%%
+%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
+%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
+%% of the acceptable values for `Type' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmapLevels.xml">external</a> documentation.
+-spec build3DMipmapLevels(Target, InternalFormat, Width, Height, Depth, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary().
build3DMipmapLevels(Target,InternalFormat,Width,Height,Depth,Format,Type,Level,Base,Max,Data) ->
send_bin(Data),
call(5014, <<Target:?GLenum,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,Type:?GLenum,Level:?GLint,Base:?GLint,Max:?GLint>>).
-%% @spec (Target::enum(),InternalFormat::integer(),Width::integer(),Height::integer(),Depth::integer(),Format::enum(),Type::enum(),Data::binary()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmaps.xml">external</a> documentation.
--spec build3DMipmaps(enum(),integer(),integer(),integer(),integer(),enum(),enum(),binary()) -> integer().
+%% @doc Builds a three-dimensional mipmap
+%%
+%% ``glu:build3DMipmaps'' builds a series of prefiltered three-dimensional texture maps
+%% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture-mapped
+%% primitives.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% Initially, the `Width' , `Height' and `Depth' of `Data' are checked
+%% to see if they are a power of 2. If not, a copy of `Data' is made and scaled up or
+%% down to the nearest power of 2. (If `Width' , `Height' , or `Depth' is exactly
+%% between powers of 2, then the copy of `Data' will scale upwards.) This copy will
+%% be used for subsequent mipmapping operations described below. For example, if `Width'
+%% is 57, `Height' is 23, and `Depth' is 24, then a copy of `Data' will scale
+%% up to 64 in width, down to 16 in height, and up to 32 in depth before mipmapping takes
+%% place.
+%%
+%% Then, proxy textures (see {@link gl:texImage3D/10} ) are used to determine if the implementation
+%% can fit the requested texture. If not, all three dimensions are continually halved until
+%% it fits.
+%%
+%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half
+%% along all three dimensions until size 1*1*1 is reached. At each level, each texel in
+%% the halved mipmap level is an average of the corresponding eight texels in the larger
+%% mipmap level. (If exactly one of the dimensions is 1, four texels are averaged. If exactly
+%% two of the dimensions are 1, two texels are averaged.)
+%%
+%% {@link gl:texImage3D/10} is called to load each of these mipmap levels. Level 0 is a copy
+%% of `Data' . The highest level is (log 2)(max(width height depth)). For example, if `Width' is 64, `Height'
+%% is 16, and `Depth' is 32, and the implementation can store a texture of this size,
+%% the following mipmap levels are built: 64*16*32, 32*8*16, 16*4*8, 8*2*4, 4*1*2,
+%% 2*1*1, and 1*1*1. These correspond to levels 0 through 6, respectively.
+%%
+%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
+%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
+%% of the acceptable values for `Type' parameter.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmaps.xml">external</a> documentation.
+-spec build3DMipmaps(Target, InternalFormat, Width, Height, Depth, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Data :: binary().
build3DMipmaps(Target,InternalFormat,Width,Height,Depth,Format,Type,Data) ->
send_bin(Data),
call(5015, <<Target:?GLenum,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,Type:?GLenum>>).
-%% @spec (ExtName::string(),ExtString::string()) -> 0|1
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCheckExtension.xml">external</a> documentation.
--spec checkExtension(string(),string()) -> 0|1.
+%% @doc Determines if an extension name is supported
+%%
+%% ``glu:checkExtension'' returns `?GLU_TRUE' if `ExtName' is supported otherwise
+%% `?GLU_FALSE' is returned.
+%%
+%% This is used to check for the presence for OpenGL, GLU, or GLX extension names by passing
+%% the extension strings returned by {@link gl:getString/1} , {@link glu:getString/1} , see `glXGetClientString'
+%% , see `glXQueryExtensionsString', or see `glXQueryServerString', respectively,
+%% as `ExtString' .
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCheckExtension.xml">external</a> documentation.
+-spec checkExtension(ExtName, ExtString) -> 0|1 when ExtName :: string(),ExtString :: string().
checkExtension(ExtName,ExtString) ->
call(5016, <<(list_to_binary([ExtName|[0]]))/binary,0:((8-((length(ExtName)+ 1) rem 8)) rem 8),(list_to_binary([ExtString|[0]]))/binary,0:((8-((length(ExtString)+ 1) rem 8)) rem 8)>>).
-%% @spec (Quad::integer(),Base::float(),Top::float(),Height::float(),Slices::integer(),Stacks::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCylinder.xml">external</a> documentation.
--spec cylinder(integer(),float(),float(),float(),integer(),integer()) -> ok.
+%% @doc Draw a cylinder
+%%
+%% ``glu:cylinder'' draws a cylinder oriented along the `z' axis. The base of the
+%% cylinder is placed at `z' = 0 and the top at z= height. Like a sphere, a cylinder
+%% is subdivided around the `z' axis into slices and along the `z' axis into stacks.
+%%
+%%
+%% Note that if `Top' is set to 0.0, this routine generates a cone.
+%%
+%% If the orientation is set to `?GLU_OUTSIDE' (with {@link glu:quadricOrientation/2} ),
+%% then any generated normals point away from the `z' axis. Otherwise, they point toward
+%% the `z' axis.
+%%
+%% If texturing is turned on (with {@link glu:quadricTexture/2} ), then texture coordinates
+%% are generated so that `t' ranges linearly from 0.0 at `z' = 0 to 1.0 at `z'
+%% = `Height' , and `s' ranges from 0.0 at the +`y' axis, to 0.25 at the +`x'
+%% axis, to 0.5 at the -`y' axis, to 0.75 at the -`x' axis, and back to 1.0
+%% at the +`y' axis.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCylinder.xml">external</a> documentation.
+-spec cylinder(Quad, Base, Top, Height, Slices, Stacks) -> ok when Quad :: integer(),Base :: float(),Top :: float(),Height :: float(),Slices :: integer(),Stacks :: integer().
cylinder(Quad,Base,Top,Height,Slices,Stacks) ->
cast(5017, <<Quad:?GLUquadric,Base:?GLdouble,Top:?GLdouble,Height:?GLdouble,Slices:?GLint,Stacks:?GLint>>).
-%% @spec (Quad::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteQuadric.xml">external</a> documentation.
--spec deleteQuadric(integer()) -> ok.
+%% @doc Destroy a quadrics object
+%%
+%% ``glu:deleteQuadric'' destroys the quadrics object (created with {@link glu:newQuadric/0} )
+%% and frees any memory it uses. Once ``glu:deleteQuadric'' has been called, `Quad'
+%% cannot be used again.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteQuadric.xml">external</a> documentation.
+-spec deleteQuadric(Quad) -> ok when Quad :: integer().
deleteQuadric(Quad) ->
cast(5018, <<Quad:?GLUquadric>>).
-%% @spec (Quad::integer(),Inner::float(),Outer::float(),Slices::integer(),Loops::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDisk.xml">external</a> documentation.
--spec disk(integer(),float(),float(),integer(),integer()) -> ok.
+%% @doc Draw a disk
+%%
+%% ``glu:disk'' renders a disk on the `z' = 0 plane. The disk has a radius of `Outer'
+%% and contains a concentric circular hole with a radius of `Inner' . If `Inner'
+%% is 0, then no hole is generated. The disk is subdivided around the `z' axis into
+%% slices (like pizza slices) and also about the `z' axis into rings (as specified by `Slices'
+%% and `Loops' , respectively).
+%%
+%% With respect to orientation, the +`z' side of the disk is considered to be ``outside''
+%% (see {@link glu:quadricOrientation/2} ). This means that if the orientation is set to `?GLU_OUTSIDE'
+%% , then any normals generated point along the +`z' axis. Otherwise, they point along
+%% the -`z' axis.
+%%
+%% If texturing has been turned on (with {@link glu:quadricTexture/2} ), texture coordinates
+%% are generated linearly such that where r= outer, the value at (`r', 0, 0) is (1,
+%% 0.5), at (0, `r', 0) it is (0.5, 1), at (-`r', 0, 0) it is (0, 0.5), and at
+%% (0, -`r', 0) it is (0.5, 0).
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDisk.xml">external</a> documentation.
+-spec disk(Quad, Inner, Outer, Slices, Loops) -> ok when Quad :: integer(),Inner :: float(),Outer :: float(),Slices :: integer(),Loops :: integer().
disk(Quad,Inner,Outer,Slices,Loops) ->
cast(5019, <<Quad:?GLUquadric,Inner:?GLdouble,Outer:?GLdouble,Slices:?GLint,Loops:?GLint>>).
-%% @spec (Error::enum()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluErrorString.xml">external</a> documentation.
--spec errorString(enum()) -> string().
+%% @doc Produce an error string from a GL or GLU error code
+%%
+%% ``glu:errorString'' produces an error string from a GL or GLU error code. The string
+%% is in ISO Latin 1 format. For example, ``glu:errorString''(`?GLU_OUT_OF_MEMORY')
+%% returns the string `out of memory'.
+%%
+%% The standard GLU error codes are `?GLU_INVALID_ENUM', `?GLU_INVALID_VALUE',
+%% and `?GLU_OUT_OF_MEMORY'. Certain other GLU functions can return specialized error
+%% codes through callbacks. See the {@link gl:getError/0} reference page for the list of
+%% GL error codes.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluErrorString.xml">external</a> documentation.
+-spec errorString(Error) -> string() when Error :: enum().
errorString(Error) ->
call(5020, <<Error:?GLenum>>).
-%% @spec (Name::enum()) -> string()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluGetString.xml">external</a> documentation.
--spec getString(enum()) -> string().
+%% @doc Return a string describing the GLU version or GLU extensions
+%%
+%% ``glu:getString'' returns a pointer to a static string describing the GLU version or
+%% the GLU extensions that are supported.
+%%
+%% The version number is one of the following forms:
+%%
+%% `major_number.minor_number'`major_number.minor_number.release_number'.
+%%
+%% The version string is of the following form:
+%%
+%% `version number&lt;space&gt;vendor-specific information'
+%%
+%% Vendor-specific information is optional. Its format and contents depend on the implementation.
+%%
+%%
+%% The standard GLU contains a basic set of features and capabilities. If a company or group
+%% of companies wish to support other features, these may be included as extensions to the
+%% GLU. If `Name' is `?GLU_EXTENSIONS', then ``glu:getString'' returns a space-separated
+%% list of names of supported GLU extensions. (Extension names never contain spaces.)
+%%
+%% All strings are null-terminated.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluGetString.xml">external</a> documentation.
+-spec getString(Name) -> string() when Name :: enum().
getString(Name) ->
call(5021, <<Name:?GLenum>>).
-%% @spec (EyeX::float(),EyeY::float(),EyeZ::float(),CenterX::float(),CenterY::float(),CenterZ::float(),UpX::float(),UpY::float(),UpZ::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml">external</a> documentation.
--spec lookAt(float(),float(),float(),float(),float(),float(),float(),float(),float()) -> ok.
+%% @doc Define a viewing transformation
+%%
+%% ``glu:lookAt'' creates a viewing matrix derived from an eye point, a reference point
+%% indicating the center of the scene, and an `UP' vector.
+%%
+%% The matrix maps the reference point to the negative `z' axis and the eye point to
+%% the origin. When a typical projection matrix is used, the center of the scene therefore
+%% maps to the center of the viewport. Similarly, the direction described by the `UP'
+%% vector projected onto the viewing plane is mapped to the positive `y' axis so that
+%% it points upward in the viewport. The `UP' vector must not be parallel to the line
+%% of sight from the eye point to the reference point.
+%%
+%% Let
+%%
+%% F=(centerX-eyeX centerY-eyeY centerZ-eyeZ)
+%%
+%% Let `UP' be the vector (upX upY upZ).
+%%
+%% Then normalize as follows: f= F/(||F||)
+%%
+%% UP"= UP/(||UP||)
+%%
+%% Finally, let s= f*UP", and u= s*f.
+%%
+%% M is then constructed as follows: M=(s[0] s[1] s[2] 0 u[0] u[1] u[2] 0-f[0]-f[1]-f[2] 0 0 0 0 1)
+%%
+%% and ``glu:lookAt'' is equivalent to glMultMatrixf(M); glTranslated(-eyex, -eyey,
+%% -eyez);
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml">external</a> documentation.
+-spec lookAt(EyeX, EyeY, EyeZ, CenterX, CenterY, CenterZ, UpX, UpY, UpZ) -> ok when EyeX :: float(),EyeY :: float(),EyeZ :: float(),CenterX :: float(),CenterY :: float(),CenterZ :: float(),UpX :: float(),UpY :: float(),UpZ :: float().
lookAt(EyeX,EyeY,EyeZ,CenterX,CenterY,CenterZ,UpX,UpY,UpZ) ->
cast(5022, <<EyeX:?GLdouble,EyeY:?GLdouble,EyeZ:?GLdouble,CenterX:?GLdouble,CenterY:?GLdouble,CenterZ:?GLdouble,UpX:?GLdouble,UpY:?GLdouble,UpZ:?GLdouble>>).
-%% @spec () -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluNewQuadric.xml">external</a> documentation.
+%% @doc Create a quadrics object
+%%
+%% ``glu:newQuadric'' creates and returns a pointer to a new quadrics object. This object
+%% must be referred to when calling quadrics rendering and control functions. A return value
+%% of 0 means that there is not enough memory to allocate the object.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluNewQuadric.xml">external</a> documentation.
-spec newQuadric() -> integer().
newQuadric() ->
call(5023, <<>>).
-%% @spec (Left::float(),Right::float(),Bottom::float(),Top::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluOrtho2D.xml">external</a> documentation.
--spec ortho2D(float(),float(),float(),float()) -> ok.
+%% @doc Define a 2D orthographic projection matrix
+%%
+%% ``glu:ortho2D'' sets up a two-dimensional orthographic viewing region. This is equivalent
+%% to calling {@link gl:ortho/6} with near= -1 and far= 1.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluOrtho2D.xml">external</a> documentation.
+-spec ortho2D(Left, Right, Bottom, Top) -> ok when Left :: float(),Right :: float(),Bottom :: float(),Top :: float().
ortho2D(Left,Right,Bottom,Top) ->
cast(5024, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble>>).
-%% @spec (Quad::integer(),Inner::float(),Outer::float(),Slices::integer(),Loops::integer(),Start::float(),Sweep::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPartialDisk.xml">external</a> documentation.
--spec partialDisk(integer(),float(),float(),integer(),integer(),float(),float()) -> ok.
+%% @doc Draw an arc of a disk
+%%
+%% ``glu:partialDisk'' renders a partial disk on the z= 0 plane. A partial disk is similar
+%% to a full disk, except that only the subset of the disk from `Start' through `Start'
+%% + `Sweep' is included (where 0 degrees is along the +f2yf axis, 90 degrees along
+%% the +`x' axis, 180 degrees along the -`y' axis, and 270 degrees along the -`x'
+%% axis).
+%%
+%% The partial disk has a radius of `Outer' and contains a concentric circular hole
+%% with a radius of `Inner' . If `Inner' is 0, then no hole is generated. The partial
+%% disk is subdivided around the `z' axis into slices (like pizza slices) and also about
+%% the `z' axis into rings (as specified by `Slices' and `Loops' , respectively).
+%%
+%%
+%% With respect to orientation, the +`z' side of the partial disk is considered to
+%% be outside (see {@link glu:quadricOrientation/2} ). This means that if the orientation
+%% is set to `?GLU_OUTSIDE', then any normals generated point along the +`z' axis.
+%% Otherwise, they point along the -`z' axis.
+%%
+%% If texturing is turned on (with {@link glu:quadricTexture/2} ), texture coordinates are
+%% generated linearly such that where r= outer, the value at (`r', 0, 0) is (1.0,
+%% 0.5), at (0, `r', 0) it is (0.5, 1.0), at (-`r', 0, 0) it is (0.0, 0.5), and
+%% at (0, -`r', 0) it is (0.5, 0.0).
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPartialDisk.xml">external</a> documentation.
+-spec partialDisk(Quad, Inner, Outer, Slices, Loops, Start, Sweep) -> ok when Quad :: integer(),Inner :: float(),Outer :: float(),Slices :: integer(),Loops :: integer(),Start :: float(),Sweep :: float().
partialDisk(Quad,Inner,Outer,Slices,Loops,Start,Sweep) ->
cast(5025, <<Quad:?GLUquadric,Inner:?GLdouble,Outer:?GLdouble,Slices:?GLint,Loops:?GLint,Start:?GLdouble,Sweep:?GLdouble>>).
-%% @spec (Fovy::float(),Aspect::float(),ZNear::float(),ZFar::float()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml">external</a> documentation.
--spec perspective(float(),float(),float(),float()) -> ok.
+%% @doc Set up a perspective projection matrix
+%%
+%% ``glu:perspective'' specifies a viewing frustum into the world coordinate system. In
+%% general, the aspect ratio in ``glu:perspective'' should match the aspect ratio of the
+%% associated viewport. For example, aspect= 2.0 means the viewer's angle of view is twice
+%% as wide in `x' as it is in `y'. If the viewport is twice as wide as it is tall,
+%% it displays the image without distortion.
+%%
+%% The matrix generated by ``glu:perspective'' is multipled by the current matrix, just
+%% as if {@link gl:multMatrixd/1} were called with the generated matrix. To load the perspective
+%% matrix onto the current matrix stack instead, precede the call to ``glu:perspective''
+%% with a call to {@link gl:loadIdentity/0} .
+%%
+%% Given `f' defined as follows:
+%%
+%% f= cotangent(fovy/2) The generated matrix is
+%%
+%% (f/aspect 0 0 0 0 f 0 0 0 0(zFar+zNear)/(zNear-zFar)(2*zFar*zNear)/(zNear-zFar) 0 0 -1 0)
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml">external</a> documentation.
+-spec perspective(Fovy, Aspect, ZNear, ZFar) -> ok when Fovy :: float(),Aspect :: float(),ZNear :: float(),ZFar :: float().
perspective(Fovy,Aspect,ZNear,ZFar) ->
cast(5026, <<Fovy:?GLdouble,Aspect:?GLdouble,ZNear:?GLdouble,ZFar:?GLdouble>>).
-%% @spec (X::float(),Y::float(),DelX::float(),DelY::float(),Viewport::{integer(),integer(),integer(),integer()}) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPickMatrix.xml">external</a> documentation.
--spec pickMatrix(float(),float(),float(),float(),{integer(),integer(),integer(),integer()}) -> ok.
+%% @doc Define a picking region
+%%
+%% ``glu:pickMatrix'' creates a projection matrix that can be used to restrict drawing
+%% to a small region of the viewport. This is typically useful to determine what objects
+%% are being drawn near the cursor. Use ``glu:pickMatrix'' to restrict drawing to a small
+%% region around the cursor. Then, enter selection mode (with {@link gl:renderMode/1} ) and
+%% rerender the scene. All primitives that would have been drawn near the cursor are identified
+%% and stored in the selection buffer.
+%%
+%% The matrix created by ``glu:pickMatrix'' is multiplied by the current matrix just as
+%% if {@link gl:multMatrixd/1} is called with the generated matrix. To effectively use the
+%% generated pick matrix for picking, first call {@link gl:loadIdentity/0} to load an identity
+%% matrix onto the perspective matrix stack. Then call ``glu:pickMatrix'', and, finally,
+%% call a command (such as {@link glu:perspective/4} ) to multiply the perspective matrix by
+%% the pick matrix.
+%%
+%% When using ``glu:pickMatrix'' to pick NURBS, be careful to turn off the NURBS property
+%% `?GLU_AUTO_LOAD_MATRIX'. If `?GLU_AUTO_LOAD_MATRIX' is not turned off, then
+%% any NURBS surface rendered is subdivided differently with the pick matrix than the way
+%% it was subdivided without the pick matrix.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPickMatrix.xml">external</a> documentation.
+-spec pickMatrix(X, Y, DelX, DelY, Viewport) -> ok when X :: float(),Y :: float(),DelX :: float(),DelY :: float(),Viewport :: {integer(),integer(),integer(),integer()}.
pickMatrix(X,Y,DelX,DelY,{V1,V2,V3,V4}) ->
cast(5027, <<X:?GLdouble,Y:?GLdouble,DelX:?GLdouble,DelY:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
-%% @spec (ObjX::float(),ObjY::float(),ObjZ::float(),Model::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},Proj::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},View::{integer(),integer(),integer(),integer()}) -> {integer(),WinX::float(),WinY::float(),WinZ::float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml">external</a> documentation.
--spec project(float(),float(),float(),{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},{integer(),integer(),integer(),integer()}) -> {integer(),float(),float(),float()}.
+%% @doc Map object coordinates to window coordinates
+%%
+%% ``glu:project'' transforms the specified object coordinates into window coordinates
+%% using `Model' , `Proj' , and `View' . The result is stored in `WinX' , `WinY'
+%% , and `WinZ' . A return value of `?GLU_TRUE' indicates success, a return value
+%% of `?GLU_FALSE' indicates failure.
+%%
+%% To compute the coordinates, let v=(objX objY objZ 1.0) represented as a matrix with 4 rows and 1 column.
+%% Then ``glu:project'' computes v" as follows:
+%%
+%% v"= P*M*v
+%%
+%% where P is the current projection matrix `Proj' and M is the current modelview
+%% matrix `Model' (both represented as 4*4 matrices in column-major order).
+%%
+%% The window coordinates are then computed as follows:
+%%
+%% winX= view(0)+view(2)*(v"(0)+1)/2
+%%
+%% winY= view(1)+view(3)*(v"(1)+1)/2
+%%
+%% winZ=(v"(2)+1)/2
+%%
+%%
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml">external</a> documentation.
+-spec project(ObjX, ObjY, ObjZ, Model, Proj, View) -> {integer(),WinX :: float(),WinY :: float(),WinZ :: float()} when ObjX :: float(),ObjY :: float(),ObjZ :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()}.
project(ObjX,ObjY,ObjZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4}) ->
call(5028, <<ObjX:?GLdouble,ObjY:?GLdouble,ObjZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>);
project(ObjX,ObjY,ObjZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12},{V1,V2,V3,V4}) ->
call(5028, <<ObjX:?GLdouble,ObjY:?GLdouble,ObjZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,0:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,0:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,0:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,1:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
-%% @spec (Quad::integer(),Draw::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricDrawStyle.xml">external</a> documentation.
--spec quadricDrawStyle(integer(),enum()) -> ok.
+%% @doc Specify the draw style desired for quadrics
+%%
+%% ``glu:quadricDrawStyle'' specifies the draw style for quadrics rendered with `Quad' .
+%% The legal values are as follows:
+%%
+%% `?GLU_FILL': Quadrics are rendered with polygon primitives. The polygons are drawn
+%% in a counterclockwise fashion with respect to their normals (as defined with {@link glu:quadricOrientation/2}
+%% ).
+%%
+%% `?GLU_LINE': Quadrics are rendered as a set of lines.
+%%
+%% `?GLU_SILHOUETTE': Quadrics are rendered as a set of lines, except that edges separating
+%% coplanar faces will not be drawn.
+%%
+%% `?GLU_POINT': Quadrics are rendered as a set of points.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricDrawStyle.xml">external</a> documentation.
+-spec quadricDrawStyle(Quad, Draw) -> ok when Quad :: integer(),Draw :: enum().
quadricDrawStyle(Quad,Draw) ->
cast(5029, <<Quad:?GLUquadric,Draw:?GLenum>>).
-%% @spec (Quad::integer(),Normal::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricNormals.xml">external</a> documentation.
--spec quadricNormals(integer(),enum()) -> ok.
+%% @doc Specify what kind of normals are desired for quadrics
+%%
+%% ``glu:quadricNormals'' specifies what kind of normals are desired for quadrics rendered
+%% with `Quad' . The legal values are as follows:
+%%
+%% `?GLU_NONE': No normals are generated.
+%%
+%% `?GLU_FLAT': One normal is generated for every facet of a quadric.
+%%
+%% `?GLU_SMOOTH': One normal is generated for every vertex of a quadric. This is the
+%% initial value.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricNormals.xml">external</a> documentation.
+-spec quadricNormals(Quad, Normal) -> ok when Quad :: integer(),Normal :: enum().
quadricNormals(Quad,Normal) ->
cast(5030, <<Quad:?GLUquadric,Normal:?GLenum>>).
-%% @spec (Quad::integer(),Orientation::enum()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricOrientation.xml">external</a> documentation.
--spec quadricOrientation(integer(),enum()) -> ok.
+%% @doc Specify inside/outside orientation for quadrics
+%%
+%% ``glu:quadricOrientation'' specifies what kind of orientation is desired for quadrics
+%% rendered with `Quad' . The `Orientation' values are as follows:
+%%
+%% `?GLU_OUTSIDE': Quadrics are drawn with normals pointing outward (the initial value).
+%%
+%%
+%% `?GLU_INSIDE': Quadrics are drawn with normals pointing inward.
+%%
+%% Note that the interpretation of `outward' and `inward' depends on the quadric
+%% being drawn.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricOrientation.xml">external</a> documentation.
+-spec quadricOrientation(Quad, Orientation) -> ok when Quad :: integer(),Orientation :: enum().
quadricOrientation(Quad,Orientation) ->
cast(5031, <<Quad:?GLUquadric,Orientation:?GLenum>>).
-%% @spec (Quad::integer(),Texture::0|1) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricTexture.xml">external</a> documentation.
--spec quadricTexture(integer(),0|1) -> ok.
+%% @doc Specify if texturing is desired for quadrics
+%%
+%% ``glu:quadricTexture'' specifies if texture coordinates should be generated for quadrics
+%% rendered with `Quad' . If the value of `Texture' is `?GLU_TRUE', then texture
+%% coordinates are generated, and if `Texture' is `?GLU_FALSE', they are not.
+%% The initial value is `?GLU_FALSE'.
+%%
+%% The manner in which texture coordinates are generated depends upon the specific quadric
+%% rendered.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricTexture.xml">external</a> documentation.
+-spec quadricTexture(Quad, Texture) -> ok when Quad :: integer(),Texture :: 0|1.
quadricTexture(Quad,Texture) ->
cast(5032, <<Quad:?GLUquadric,Texture:?GLboolean>>).
-%% @spec (Format::enum(),WIn::integer(),HIn::integer(),TypeIn::enum(),DataIn::binary(),WOut::integer(),HOut::integer(),TypeOut::enum(),DataOut::mem()) -> integer()
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluScaleImage.xml">external</a> documentation.
--spec scaleImage(enum(),integer(),integer(),enum(),binary(),integer(),integer(),enum(),mem()) -> integer().
+%% @doc Scale an image to an arbitrary size
+%%
+%% ``glu:scaleImage'' scales a pixel image using the appropriate pixel store modes to
+%% unpack data from the source image and pack data into the destination image.
+%%
+%% When shrinking an image, ``glu:scaleImage'' uses a box filter to sample the source
+%% image and create pixels for the destination image. When magnifying an image, the pixels
+%% from the source image are linearly interpolated to create the destination image.
+%%
+%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
+%% ).
+%%
+%% See the {@link gl:readPixels/7} reference page for a description of the acceptable values
+%% for the `Format' , `TypeIn' , and `TypeOut' parameters.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluScaleImage.xml">external</a> documentation.
+-spec scaleImage(Format, WIn, HIn, TypeIn, DataIn, WOut, HOut, TypeOut, DataOut) -> integer() when Format :: enum(),WIn :: integer(),HIn :: integer(),TypeIn :: enum(),DataIn :: binary(),WOut :: integer(),HOut :: integer(),TypeOut :: enum(),DataOut :: mem().
scaleImage(Format,WIn,HIn,TypeIn,DataIn,WOut,HOut,TypeOut,DataOut) ->
send_bin(DataIn),
send_bin(DataOut),
call(5033, <<Format:?GLenum,WIn:?GLsizei,HIn:?GLsizei,TypeIn:?GLenum,WOut:?GLsizei,HOut:?GLsizei,TypeOut:?GLenum>>).
-%% @spec (Quad::integer(),Radius::float(),Slices::integer(),Stacks::integer()) -> ok
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluSphere.xml">external</a> documentation.
--spec sphere(integer(),float(),integer(),integer()) -> ok.
+%% @doc Draw a sphere
+%%
+%% ``glu:sphere'' draws a sphere of the given radius centered around the origin. The sphere
+%% is subdivided around the `z' axis into slices and along the `z' axis into
+%% stacks (similar to lines of longitude and latitude).
+%%
+%% If the orientation is set to `?GLU_OUTSIDE' (with {@link glu:quadricOrientation/2} ),
+%% then any normals generated point away from the center of the sphere. Otherwise, they
+%% point toward the center of the sphere.
+%%
+%% If texturing is turned on (with {@link glu:quadricTexture/2} ), then texture coordinates
+%% are generated so that `t' ranges from 0.0 at z=-radius to 1.0 at z= radius (`t'
+%% increases linearly along longitudinal lines), and `s' ranges from 0.0 at the +`y'
+%% axis, to 0.25 at the +`x' axis, to 0.5 at the -`y' axis, to 0.75 at the -`x'
+%% axis, and back to 1.0 at the +`y' axis.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluSphere.xml">external</a> documentation.
+-spec sphere(Quad, Radius, Slices, Stacks) -> ok when Quad :: integer(),Radius :: float(),Slices :: integer(),Stacks :: integer().
sphere(Quad,Radius,Slices,Stacks) ->
cast(5034, <<Quad:?GLUquadric,Radius:?GLdouble,Slices:?GLint,Stacks:?GLint>>).
-%% @spec (WinX::float(),WinY::float(),WinZ::float(),Model::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},Proj::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},View::{integer(),integer(),integer(),integer()}) -> {integer(),ObjX::float(),ObjY::float(),ObjZ::float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml">external</a> documentation.
--spec unProject(float(),float(),float(),{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},{integer(),integer(),integer(),integer()}) -> {integer(),float(),float(),float()}.
+%% @doc Map window coordinates to object coordinates
+%%
+%% ``glu:unProject'' maps the specified window coordinates into object coordinates using `Model'
+%% , `Proj' , and `View' . The result is stored in `ObjX' , `ObjY' , and `ObjZ'
+%% . A return value of `?GLU_TRUE' indicates success; a return value of `?GLU_FALSE'
+%% indicates failure.
+%%
+%% To compute the coordinates (objX objY objZ), ``glu:unProject'' multiplies the normalized device coordinates
+%% by the inverse of `Model' * `Proj' as follows:
+%%
+%% (objX objY objZ W)= INV(P M) ((2(winX-view[0]))/(view[2])-1(2(winY-view[1]))/(view[3])-1 2(winZ)-1 1) INV denotes matrix inversion. W is an unused variable, included for consistent
+%% matrix notation.
+%%
+%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml">external</a> documentation.
+-spec unProject(WinX, WinY, WinZ, Model, Proj, View) -> {integer(),ObjX :: float(),ObjY :: float(),ObjZ :: float()} when WinX :: float(),WinY :: float(),WinZ :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()}.
unProject(WinX,WinY,WinZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4}) ->
call(5035, <<WinX:?GLdouble,WinY:?GLdouble,WinZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>);
unProject(WinX,WinY,WinZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12},{V1,V2,V3,V4}) ->
call(5035, <<WinX:?GLdouble,WinY:?GLdouble,WinZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,0:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,0:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,0:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,1:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,0:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,0:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,0:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,1:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
-%% @spec (WinX::float(),WinY::float(),WinZ::float(),ClipW::float(),Model::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},Proj::{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},View::{integer(),integer(),integer(),integer()},NearVal::float(),FarVal::float()) -> {integer(),ObjX::float(),ObjY::float(),ObjZ::float(),ObjW::float()}
-%% @doc See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml">external</a> documentation.
--spec unProject4(float(),float(),float(),float(),{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},{float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float(),float()},{integer(),integer(),integer(),integer()},float(),float()) -> {integer(),float(),float(),float(),float()}.
+%% @doc
+%% See {@link unProject/6}
+-spec unProject4(WinX, WinY, WinZ, ClipW, Model, Proj, View, NearVal, FarVal) -> {integer(),ObjX :: float(),ObjY :: float(),ObjZ :: float(),ObjW :: float()} when WinX :: float(),WinY :: float(),WinZ :: float(),ClipW :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()},NearVal :: float(),FarVal :: float().
unProject4(WinX,WinY,WinZ,ClipW,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4},NearVal,FarVal) ->
call(5036, <<WinX:?GLdouble,WinY:?GLdouble,WinZ:?GLdouble,ClipW:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint,NearVal:?GLdouble,FarVal:?GLdouble>>);
unProject4(WinX,WinY,WinZ,ClipW,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12},{V1,V2,V3,V4},NearVal,FarVal) ->
diff --git a/lib/wx/src/gen/wxAcceleratorEntry.erl b/lib/wx/src/gen/wxAcceleratorEntry.erl
index d76299b300..3cf50a2348 100644
--- a/lib/wx/src/gen/wxAcceleratorEntry.erl
+++ b/lib/wx/src/gen/wxAcceleratorEntry.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,24 +29,29 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxAcceleratorEntry/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxAcceleratorEntry()
+-type wxAcceleratorEntry() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxAcceleratorEntry().
+
new() ->
new([]).
-%% @spec (X::term()|wxAcceleratorEntry()) -> wxAcceleratorEntry()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratorentry.html#wxacceleratorentrywxacceleratorentry">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new([Option]) -> wxAcceleratorEntry() </c>
-%%<br /> Option = {flags, integer()} | {keyCode, integer()} | {cmd, integer()} | {item, wxMenuItem:wxMenuItem()}
-%% </p>
-%% <p><c>
-%% new(Entry::wxAcceleratorEntry()) -> wxAcceleratorEntry() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Entry) -> wxAcceleratorEntry() when<br />
+%% Entry::wxAcceleratorEntry().<br />
+%%
+-spec new([Option]) -> wxAcceleratorEntry() when
+ Option :: {flags, integer()}
+ | {keyCode, integer()}
+ | {cmd, integer()}
+ | {item, wxMenuItem:wxMenuItem()};
+ (Entry) -> wxAcceleratorEntry() when
+ Entry::wxAcceleratorEntry().
new(Options)
when is_list(Options) ->
MOpts = fun({flags, Flags}, Acc) -> [<<1:32/?UI,Flags:32/?UI>>|Acc];
@@ -62,36 +67,42 @@ new(#wx_ref{type=EntryT,ref=EntryRef}) ->
wxe_util:construct(?wxAcceleratorEntry_new_1_1,
<<EntryRef:32/?UI>>).
-%% @spec (This::wxAcceleratorEntry()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratorentry.html#wxacceleratorentrygetcommand">external documentation</a>.
+-spec getCommand(This) -> integer() when
+ This::wxAcceleratorEntry().
getCommand(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAcceleratorEntry),
wxe_util:call(?wxAcceleratorEntry_GetCommand,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAcceleratorEntry()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratorentry.html#wxacceleratorentrygetflags">external documentation</a>.
+-spec getFlags(This) -> integer() when
+ This::wxAcceleratorEntry().
getFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAcceleratorEntry),
wxe_util:call(?wxAcceleratorEntry_GetFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAcceleratorEntry()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratorentry.html#wxacceleratorentrygetkeycode">external documentation</a>.
+-spec getKeyCode(This) -> integer() when
+ This::wxAcceleratorEntry().
getKeyCode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAcceleratorEntry),
wxe_util:call(?wxAcceleratorEntry_GetKeyCode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAcceleratorEntry(), Flags::integer(), KeyCode::integer(), Cmd::integer()) -> ok
%% @equiv set(This,Flags,KeyCode,Cmd, [])
+-spec set(This, Flags, KeyCode, Cmd) -> ok when
+ This::wxAcceleratorEntry(), Flags::integer(), KeyCode::integer(), Cmd::integer().
+
set(This,Flags,KeyCode,Cmd)
when is_record(This, wx_ref),is_integer(Flags),is_integer(KeyCode),is_integer(Cmd) ->
set(This,Flags,KeyCode,Cmd, []).
-%% @spec (This::wxAcceleratorEntry(), Flags::integer(), KeyCode::integer(), Cmd::integer(), [Option]) -> ok
-%% Option = {item, wxMenuItem:wxMenuItem()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratorentry.html#wxacceleratorentryset">external documentation</a>.
+-spec set(This, Flags, KeyCode, Cmd, [Option]) -> ok when
+ This::wxAcceleratorEntry(), Flags::integer(), KeyCode::integer(), Cmd::integer(),
+ Option :: {item, wxMenuItem:wxMenuItem()}.
set(#wx_ref{type=ThisT,ref=ThisRef},Flags,KeyCode,Cmd, Options)
when is_integer(Flags),is_integer(KeyCode),is_integer(Cmd),is_list(Options) ->
?CLASS(ThisT,wxAcceleratorEntry),
@@ -101,8 +112,8 @@ set(#wx_ref{type=ThisT,ref=ThisRef},Flags,KeyCode,Cmd, Options)
wxe_util:cast(?wxAcceleratorEntry_Set,
<<ThisRef:32/?UI,Flags:32/?UI,KeyCode:32/?UI,Cmd:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxAcceleratorEntry()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxAcceleratorEntry()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxAcceleratorEntry),
wxe_util:destroy(?wxAcceleratorEntry_destroy,Obj),
diff --git a/lib/wx/src/gen/wxAcceleratorTable.erl b/lib/wx/src/gen/wxAcceleratorTable.erl
index 5d070294e2..1b58cf3826 100644
--- a/lib/wx/src/gen/wxAcceleratorTable.erl
+++ b/lib/wx/src/gen/wxAcceleratorTable.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxAcceleratorTable/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxAcceleratorTable()
+-type wxAcceleratorTable() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratortable.html#wxacceleratortablewxacceleratortable">external documentation</a>.
+-spec new() -> wxAcceleratorTable().
new() ->
wxe_util:construct(?wxAcceleratorTable_new_0,
<<>>).
-%% @spec (N::integer(), Entries::[wxAcceleratorEntry:wxAcceleratorEntry()]) -> wxAcceleratorTable()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratortable.html#wxacceleratortablewxacceleratortable">external documentation</a>.
+-spec new(N, Entries) -> wxAcceleratorTable() when
+ N::integer(), Entries::[wxAcceleratorEntry:wxAcceleratorEntry()].
new(N,Entries)
when is_integer(N),is_list(Entries) ->
[?CLASS(EntriesT,wxAcceleratorEntry) || #wx_ref{type=EntriesT} <- Entries],
@@ -47,15 +50,16 @@ new(N,Entries)
<<N:32/?UI,(length(Entries)):32/?UI,
(<< <<(C#wx_ref.ref):32/?UI>> || C <- Entries>>)/binary, 0:(((0+length(Entries)) rem 2)*32)>>).
-%% @spec (This::wxAcceleratorTable()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxacceleratortable.html#wxacceleratortableok">external documentation</a>.
+-spec ok(This) -> boolean() when
+ This::wxAcceleratorTable().
ok(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAcceleratorTable),
wxe_util:call(?wxAcceleratorTable_Ok,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAcceleratorTable()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxAcceleratorTable()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxAcceleratorTable),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxArtProvider.erl b/lib/wx/src/gen/wxArtProvider.erl
index 7a45b0d79d..1515c46f9f 100644
--- a/lib/wx/src/gen/wxArtProvider.erl
+++ b/lib/wx/src/gen/wxArtProvider.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +29,24 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxArtProvider/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Id::string()) -> wxBitmap:wxBitmap()
+-type wxArtProvider() :: wx:wx_object().
%% @equiv getBitmap(Id, [])
+-spec getBitmap(Id) -> wxBitmap:wxBitmap() when
+ Id::unicode:chardata().
+
getBitmap(Id)
when is_list(Id) ->
getBitmap(Id, []).
-%% @spec (Id::string(), [Option]) -> wxBitmap:wxBitmap()
-%% Option = {client, string()} | {size, {W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxartprovider.html#wxartprovidergetbitmap">external documentation</a>.
+-spec getBitmap(Id, [Option]) -> wxBitmap:wxBitmap() when
+ Id::unicode:chardata(),
+ Option :: {client, unicode:chardata()}
+ | {size, {W::integer(), H::integer()}}.
getBitmap(Id, Options)
when is_list(Id),is_list(Options) ->
Id_UC = unicode:characters_to_binary([Id,0]),
@@ -51,15 +57,19 @@ getBitmap(Id, Options)
wxe_util:call(?wxArtProvider_GetBitmap,
<<(byte_size(Id_UC)):32/?UI,(Id_UC)/binary, 0:(((8- ((4+byte_size(Id_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (Id::string()) -> wxIcon:wxIcon()
%% @equiv getIcon(Id, [])
+-spec getIcon(Id) -> wxIcon:wxIcon() when
+ Id::unicode:chardata().
+
getIcon(Id)
when is_list(Id) ->
getIcon(Id, []).
-%% @spec (Id::string(), [Option]) -> wxIcon:wxIcon()
-%% Option = {client, string()} | {size, {W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxartprovider.html#wxartprovidergeticon">external documentation</a>.
+-spec getIcon(Id, [Option]) -> wxIcon:wxIcon() when
+ Id::unicode:chardata(),
+ Option :: {client, unicode:chardata()}
+ | {size, {W::integer(), H::integer()}}.
getIcon(Id, Options)
when is_list(Id),is_list(Options) ->
Id_UC = unicode:characters_to_binary([Id,0]),
diff --git a/lib/wx/src/gen/wxAuiDockArt.erl b/lib/wx/src/gen/wxAuiDockArt.erl
index f2be643dd9..d3cf1ebd0d 100644
--- a/lib/wx/src/gen/wxAuiDockArt.erl
+++ b/lib/wx/src/gen/wxAuiDockArt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxAuiDockArt/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxAuiDockArt() :: wx:wx_object().
diff --git a/lib/wx/src/gen/wxAuiManager.erl b/lib/wx/src/gen/wxAuiManager.erl
index ad0af6652d..71e851f706 100644
--- a/lib/wx/src/gen/wxAuiManager.erl
+++ b/lib/wx/src/gen/wxAuiManager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +37,22 @@
%% inherited exports
-export([connect/2,connect/3,disconnect/1,disconnect/2,disconnect/3,parent_class/1]).
+-export_type([wxAuiManager/0]).
%% @hidden
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxAuiManager()
+-type wxAuiManager() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxAuiManager().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxAuiManager()
-%% Option = {managed_wnd, wxWindow:wxWindow()} | {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerwxauimanager">external documentation</a>.
+-spec new([Option]) -> wxAuiManager() when
+ Option :: {managed_wnd, wxWindow:wxWindow()}
+ | {flags, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({managed_wnd, #wx_ref{type=Managed_wndT,ref=Managed_wndRef}}, Acc) -> ?CLASS(Managed_wndT,wxWindow),[<<1:32/?UI,Managed_wndRef:32/?UI>>|Acc];
@@ -58,22 +62,25 @@ new(Options)
wxe_util:construct(?wxAuiManager_new,
<<BinOpt/binary>>).
-%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow()) -> bool()
%% @equiv addPane(This,Window, [])
+-spec addPane(This, Window) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow().
+
addPane(This,Window)
when is_record(This, wx_ref),is_record(Window, wx_ref) ->
addPane(This,Window, []).
-%% @spec (This::wxAuiManager(),Window::wxWindow:wxWindow(),X::term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanageraddpane">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% addPane(This::wxAuiManager(), Window::wxWindow:wxWindow(), [Option]) -> bool() </c>
-%%<br /> Option = {direction, integer()} | {caption, string()}
-%% </p>
-%% <p><c>
-%% addPane(This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% addPane(This, Window, Pane_info) -> boolean() when<br />
+%% This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo().<br />
+%%
+-spec addPane(This, Window, [Option]) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow(),
+ Option :: {direction, integer()}
+ | {caption, unicode:chardata()};
+ (This, Window, Pane_info) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo().
addPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiManager),
@@ -91,8 +98,9 @@ addPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_
wxe_util:call(?wxAuiManager_AddPane_2_1,
<<ThisRef:32/?UI,WindowRef:32/?UI,Pane_infoRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo(), Drop_pos::{X::integer(),Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanageraddpane">external documentation</a>.
+-spec addPane(This, Window, Pane_info, Drop_pos) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow(), Pane_info::wxAuiPaneInfo:wxAuiPaneInfo(), Drop_pos::{X::integer(), Y::integer()}.
addPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=Pane_infoT,ref=Pane_infoRef},{Drop_posX,Drop_posY})
when is_integer(Drop_posX),is_integer(Drop_posY) ->
?CLASS(ThisT,wxAuiManager),
@@ -101,65 +109,72 @@ addPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_
wxe_util:call(?wxAuiManager_AddPane_3,
<<ThisRef:32/?UI,WindowRef:32/?UI,Pane_infoRef:32/?UI,Drop_posX:32/?UI,Drop_posY:32/?UI>>).
-%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerdetachpane">external documentation</a>.
+-spec detachPane(This, Window) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow().
detachPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxAuiManager),
?CLASS(WindowT,wxWindow),
wxe_util:call(?wxAuiManager_DetachPane,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> wxAuiPaneInfoArray:wxAuiPaneInfoArray()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetallpanes">external documentation</a>.
+-spec getAllPanes(This) -> wx:wx_object() when
+ This::wxAuiManager().
getAllPanes(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:call(?wxAuiManager_GetAllPanes,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> wxAuiDockArt:wxAuiDockArt()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetartprovider">external documentation</a>.
+-spec getArtProvider(This) -> wxAuiDockArt:wxAuiDockArt() when
+ This::wxAuiManager().
getArtProvider(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:call(?wxAuiManager_GetArtProvider,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> {Width_pct::float(),Height_pct::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetdocksizeconstraint">external documentation</a>.
+-spec getDockSizeConstraint(This) -> {Width_pct::number(), Height_pct::number()} when
+ This::wxAuiManager().
getDockSizeConstraint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:call(?wxAuiManager_GetDockSizeConstraint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetflags">external documentation</a>.
+-spec getFlags(This) -> integer() when
+ This::wxAuiManager().
getFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:call(?wxAuiManager_GetFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetmanagedwindow">external documentation</a>.
+-spec getManagedWindow(This) -> wxWindow:wxWindow() when
+ This::wxAuiManager().
getManagedWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:call(?wxAuiManager_GetManagedWindow,
<<ThisRef:32/?UI>>).
-%% @spec (Window::wxWindow:wxWindow()) -> wxAuiManager()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetmanager">external documentation</a>.
+-spec getManager(Window) -> wxAuiManager() when
+ Window::wxWindow:wxWindow().
getManager(#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(WindowT,wxWindow),
wxe_util:call(?wxAuiManager_GetManager,
<<WindowRef:32/?UI>>).
-%% @spec (This::wxAuiManager(),X::string()|term()) -> wxAuiPaneInfo:wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagergetpane">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% getPane(This::wxAuiManager(), Name::string()) -> wxAuiPaneInfo:wxAuiPaneInfo() </c>
-%% </p>
-%% <p><c>
-%% getPane(This::wxAuiManager(), Window::wxWindow:wxWindow()) -> wxAuiPaneInfo:wxAuiPaneInfo() </c>
-%% </p>
+%% <br /> Also:<br />
+%% getPane(This, Window) -> wxAuiPaneInfo:wxAuiPaneInfo() when<br />
+%% This::wxAuiManager(), Window::wxWindow:wxWindow().<br />
+%%
+-spec getPane(This, Name) -> wxAuiPaneInfo:wxAuiPaneInfo() when
+ This::wxAuiManager(), Name::unicode:chardata();
+ (This, Window) -> wxAuiPaneInfo:wxAuiPaneInfo() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow().
getPane(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxAuiManager),
@@ -172,22 +187,26 @@ getPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
wxe_util:call(?wxAuiManager_GetPane_1_1,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerhidehint">external documentation</a>.
+-spec hideHint(This) -> ok when
+ This::wxAuiManager().
hideHint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:cast(?wxAuiManager_HideHint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow(), Insert_location::wxAuiPaneInfo:wxAuiPaneInfo()) -> bool()
%% @equiv insertPane(This,Window,Insert_location, [])
+-spec insertPane(This, Window, Insert_location) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow(), Insert_location::wxAuiPaneInfo:wxAuiPaneInfo().
+
insertPane(This,Window,Insert_location)
when is_record(This, wx_ref),is_record(Window, wx_ref),is_record(Insert_location, wx_ref) ->
insertPane(This,Window,Insert_location, []).
-%% @spec (This::wxAuiManager(), Window::wxWindow:wxWindow(), Insert_location::wxAuiPaneInfo:wxAuiPaneInfo(), [Option]) -> bool()
-%% Option = {insert_level, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerinsertpane">external documentation</a>.
+-spec insertPane(This, Window, Insert_location, [Option]) -> boolean() when
+ This::wxAuiManager(), Window::wxWindow:wxWindow(), Insert_location::wxAuiPaneInfo:wxAuiPaneInfo(),
+ Option :: {insert_level, integer()}.
insertPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=Insert_locationT,ref=Insert_locationRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiManager),
@@ -199,8 +218,9 @@ insertPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#
wxe_util:call(?wxAuiManager_InsertPane,
<<ThisRef:32/?UI,WindowRef:32/?UI,Insert_locationRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiManager(), Pane_part::string(), Pane::wxAuiPaneInfo:wxAuiPaneInfo()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerloadpaneinfo">external documentation</a>.
+-spec loadPaneInfo(This, Pane_part, Pane) -> ok when
+ This::wxAuiManager(), Pane_part::unicode:chardata(), Pane::wxAuiPaneInfo:wxAuiPaneInfo().
loadPaneInfo(#wx_ref{type=ThisT,ref=ThisRef},Pane_part,#wx_ref{type=PaneT,ref=PaneRef})
when is_list(Pane_part) ->
?CLASS(ThisT,wxAuiManager),
@@ -209,15 +229,18 @@ loadPaneInfo(#wx_ref{type=ThisT,ref=ThisRef},Pane_part,#wx_ref{type=PaneT,ref=Pa
wxe_util:cast(?wxAuiManager_LoadPaneInfo,
<<ThisRef:32/?UI,(byte_size(Pane_part_UC)):32/?UI,(Pane_part_UC)/binary, 0:(((8- ((0+byte_size(Pane_part_UC)) band 16#7)) band 16#7))/unit:8,PaneRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Perspective::string()) -> bool()
%% @equiv loadPerspective(This,Perspective, [])
+-spec loadPerspective(This, Perspective) -> boolean() when
+ This::wxAuiManager(), Perspective::unicode:chardata().
+
loadPerspective(This,Perspective)
when is_record(This, wx_ref),is_list(Perspective) ->
loadPerspective(This,Perspective, []).
-%% @spec (This::wxAuiManager(), Perspective::string(), [Option]) -> bool()
-%% Option = {update, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerloadperspective">external documentation</a>.
+-spec loadPerspective(This, Perspective, [Option]) -> boolean() when
+ This::wxAuiManager(), Perspective::unicode:chardata(),
+ Option :: {update, boolean()}.
loadPerspective(#wx_ref{type=ThisT,ref=ThisRef},Perspective, Options)
when is_list(Perspective),is_list(Options) ->
?CLASS(ThisT,wxAuiManager),
@@ -228,77 +251,86 @@ loadPerspective(#wx_ref{type=ThisT,ref=ThisRef},Perspective, Options)
wxe_util:call(?wxAuiManager_LoadPerspective,
<<ThisRef:32/?UI,(byte_size(Perspective_UC)):32/?UI,(Perspective_UC)/binary, 0:(((8- ((0+byte_size(Perspective_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxAuiManager(), Pane::wxAuiPaneInfo:wxAuiPaneInfo()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagersavepaneinfo">external documentation</a>.
+-spec savePaneInfo(This, Pane) -> unicode:charlist() when
+ This::wxAuiManager(), Pane::wxAuiPaneInfo:wxAuiPaneInfo().
savePaneInfo(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PaneT,ref=PaneRef}) ->
?CLASS(ThisT,wxAuiManager),
?CLASS(PaneT,wxAuiPaneInfo),
wxe_util:call(?wxAuiManager_SavePaneInfo,
<<ThisRef:32/?UI,PaneRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagersaveperspective">external documentation</a>.
+-spec savePerspective(This) -> unicode:charlist() when
+ This::wxAuiManager().
savePerspective(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:call(?wxAuiManager_SavePerspective,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Art_provider::wxAuiDockArt:wxAuiDockArt()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagersetartprovider">external documentation</a>.
+-spec setArtProvider(This, Art_provider) -> ok when
+ This::wxAuiManager(), Art_provider::wxAuiDockArt:wxAuiDockArt().
setArtProvider(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Art_providerT,ref=Art_providerRef}) ->
?CLASS(ThisT,wxAuiManager),
?CLASS(Art_providerT,wxAuiDockArt),
wxe_util:cast(?wxAuiManager_SetArtProvider,
<<ThisRef:32/?UI,Art_providerRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Width_pct::float(), Height_pct::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagersetdocksizeconstraint">external documentation</a>.
+-spec setDockSizeConstraint(This, Width_pct, Height_pct) -> ok when
+ This::wxAuiManager(), Width_pct::number(), Height_pct::number().
setDockSizeConstraint(#wx_ref{type=ThisT,ref=ThisRef},Width_pct,Height_pct)
- when is_float(Width_pct),is_float(Height_pct) ->
+ when is_number(Width_pct),is_number(Height_pct) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:cast(?wxAuiManager_SetDockSizeConstraint,
<<ThisRef:32/?UI,0:32,Width_pct:64/?F,Height_pct:64/?F>>).
-%% @spec (This::wxAuiManager(), Flags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagersetflags">external documentation</a>.
+-spec setFlags(This, Flags) -> ok when
+ This::wxAuiManager(), Flags::integer().
setFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:cast(?wxAuiManager_SetFlags,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxAuiManager(), Managed_wnd::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagersetmanagedwindow">external documentation</a>.
+-spec setManagedWindow(This, Managed_wnd) -> ok when
+ This::wxAuiManager(), Managed_wnd::wxWindow:wxWindow().
setManagedWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Managed_wndT,ref=Managed_wndRef}) ->
?CLASS(ThisT,wxAuiManager),
?CLASS(Managed_wndT,wxWindow),
wxe_util:cast(?wxAuiManager_SetManagedWindow,
<<ThisRef:32/?UI,Managed_wndRef:32/?UI>>).
-%% @spec (This::wxAuiManager(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagershowhint">external documentation</a>.
+-spec showHint(This, Rect) -> ok when
+ This::wxAuiManager(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
showHint(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:cast(?wxAuiManager_ShowHint,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanageruninit">external documentation</a>.
+-spec unInit(This) -> ok when
+ This::wxAuiManager().
unInit(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:cast(?wxAuiManager_UnInit,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanager.html#wxauimanagerupdate">external documentation</a>.
+-spec update(This) -> ok when
+ This::wxAuiManager().
update(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManager),
wxe_util:cast(?wxAuiManager_Update,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManager()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxAuiManager()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxAuiManager),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxAuiManagerEvent.erl b/lib/wx/src/gen/wxAuiManagerEvent.erl
index b5e45f1860..feb3931696 100644
--- a/lib/wx/src/gen/wxAuiManagerEvent.erl
+++ b/lib/wx/src/gen/wxAuiManagerEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,79 +38,92 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxAuiManagerEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxAuiManagerEvent(), Mgr::wxAuiManager:wxAuiManager()) -> ok
+-type wxAuiManagerEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventsetmanager">external documentation</a>.
+-spec setManager(This, Mgr) -> ok when
+ This::wxAuiManagerEvent(), Mgr::wxAuiManager:wxAuiManager().
setManager(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MgrT,ref=MgrRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
?CLASS(MgrT,wxAuiManager),
wxe_util:cast(?wxAuiManagerEvent_SetManager,
<<ThisRef:32/?UI,MgrRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent()) -> wxAuiManager:wxAuiManager()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventgetmanager">external documentation</a>.
+-spec getManager(This) -> wxAuiManager:wxAuiManager() when
+ This::wxAuiManagerEvent().
getManager(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:call(?wxAuiManagerEvent_GetManager,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent(), P::wxAuiPaneInfo:wxAuiPaneInfo()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventsetpane">external documentation</a>.
+-spec setPane(This, P) -> ok when
+ This::wxAuiManagerEvent(), P::wxAuiPaneInfo:wxAuiPaneInfo().
setPane(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PT,ref=PRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
?CLASS(PT,wxAuiPaneInfo),
wxe_util:cast(?wxAuiManagerEvent_SetPane,
<<ThisRef:32/?UI,PRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent()) -> wxAuiPaneInfo:wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventgetpane">external documentation</a>.
+-spec getPane(This) -> wxAuiPaneInfo:wxAuiPaneInfo() when
+ This::wxAuiManagerEvent().
getPane(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:call(?wxAuiManagerEvent_GetPane,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventsetbutton">external documentation</a>.
+-spec setButton(This, B) -> ok when
+ This::wxAuiManagerEvent(), B::integer().
setButton(#wx_ref{type=ThisT,ref=ThisRef},B)
when is_integer(B) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:cast(?wxAuiManagerEvent_SetButton,
<<ThisRef:32/?UI,B:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventgetbutton">external documentation</a>.
+-spec getButton(This) -> integer() when
+ This::wxAuiManagerEvent().
getButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:call(?wxAuiManagerEvent_GetButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent(), Pdc::wxDC:wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventsetdc">external documentation</a>.
+-spec setDC(This, Pdc) -> ok when
+ This::wxAuiManagerEvent(), Pdc::wxDC:wxDC().
setDC(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PdcT,ref=PdcRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
?CLASS(PdcT,wxDC),
wxe_util:cast(?wxAuiManagerEvent_SetDC,
<<ThisRef:32/?UI,PdcRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent()) -> wxDC:wxDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventgetdc">external documentation</a>.
+-spec getDC(This) -> wxDC:wxDC() when
+ This::wxAuiManagerEvent().
getDC(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:call(?wxAuiManagerEvent_GetDC,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent()) -> ok
%% @equiv veto(This, [])
+-spec veto(This) -> ok when
+ This::wxAuiManagerEvent().
+
veto(This)
when is_record(This, wx_ref) ->
veto(This, []).
-%% @spec (This::wxAuiManagerEvent(), [Option]) -> ok
-%% Option = {veto, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventveto">external documentation</a>.
+-spec veto(This, [Option]) -> ok when
+ This::wxAuiManagerEvent(),
+ Option :: {veto, boolean()}.
veto(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiManagerEvent),
@@ -120,23 +133,26 @@ veto(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxAuiManagerEvent_Veto,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiManagerEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventgetveto">external documentation</a>.
+-spec getVeto(This) -> boolean() when
+ This::wxAuiManagerEvent().
getVeto(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:call(?wxAuiManagerEvent_GetVeto,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiManagerEvent(), Can_veto::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventsetcanveto">external documentation</a>.
+-spec setCanVeto(This, Can_veto) -> ok when
+ This::wxAuiManagerEvent(), Can_veto::boolean().
setCanVeto(#wx_ref{type=ThisT,ref=ThisRef},Can_veto)
when is_boolean(Can_veto) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:cast(?wxAuiManagerEvent_SetCanVeto,
<<ThisRef:32/?UI,(wxe_util:from_bool(Can_veto)):32/?UI>>).
-%% @spec (This::wxAuiManagerEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauimanagerevent.html#wxauimanagereventcanveto">external documentation</a>.
+-spec canVeto(This) -> boolean() when
+ This::wxAuiManagerEvent().
canVeto(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiManagerEvent),
wxe_util:call(?wxAuiManagerEvent_CanVeto,
diff --git a/lib/wx/src/gen/wxAuiNotebook.erl b/lib/wx/src/gen/wxAuiNotebook.erl
index 5d486aeaa2..afb599738f 100644
--- a/lib/wx/src/gen/wxAuiNotebook.erl
+++ b/lib/wx/src/gen/wxAuiNotebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +73,35 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxAuiNotebook/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxAuiNotebook()
+-type wxAuiNotebook() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookwxauinotebook">external documentation</a>.
+-spec new() -> wxAuiNotebook().
new() ->
wxe_util:construct(?wxAuiNotebook_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxAuiNotebook()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxAuiNotebook() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxAuiNotebook()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookwxauinotebook">external documentation</a>.
+-spec new(Parent, [Option]) -> wxAuiNotebook() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,15 +114,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxAuiNotebook_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiNotebook(), Page::wxWindow:wxWindow(), Caption::string()) -> bool()
%% @equiv addPage(This,Page,Caption, [])
+-spec addPage(This, Page, Caption) -> boolean() when
+ This::wxAuiNotebook(), Page::wxWindow:wxWindow(), Caption::unicode:chardata().
+
addPage(This,Page,Caption)
when is_record(This, wx_ref),is_record(Page, wx_ref),is_list(Caption) ->
addPage(This,Page,Caption, []).
-%% @spec (This::wxAuiNotebook(), Page::wxWindow:wxWindow(), Caption::string(), [Option]) -> bool()
-%% Option = {select, bool()} | {bitmap, wxBitmap:wxBitmap()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookaddpage">external documentation</a>.
+-spec addPage(This, Page, Caption, [Option]) -> boolean() when
+ This::wxAuiNotebook(), Page::wxWindow:wxWindow(), Caption::unicode:chardata(),
+ Option :: {select, boolean()}
+ | {bitmap, wxBitmap:wxBitmap()}.
addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Caption, Options)
when is_list(Caption),is_list(Options) ->
?CLASS(ThisT,wxAuiNotebook),
@@ -127,15 +139,21 @@ addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Caption,
wxe_util:call(?wxAuiNotebook_AddPage,
<<ThisRef:32/?UI,PageRef:32/?UI,(byte_size(Caption_UC)):32/?UI,(Caption_UC)/binary, 0:(((8- ((4+byte_size(Caption_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxAuiNotebook(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxAuiNotebook(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxAuiNotebook(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxAuiNotebook(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiNotebook),
@@ -149,76 +167,88 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxAuiNotebook_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxAuiNotebook(), Page::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookdeletepage">external documentation</a>.
+-spec deletePage(This, Page) -> boolean() when
+ This::wxAuiNotebook(), Page::integer().
deletePage(#wx_ref{type=ThisT,ref=ThisRef},Page)
when is_integer(Page) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_DeletePage,
<<ThisRef:32/?UI,Page:32/?UI>>).
-%% @spec (This::wxAuiNotebook()) -> wxAuiTabArt:wxAuiTabArt()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetartprovider">external documentation</a>.
+-spec getArtProvider(This) -> wxAuiTabArt:wxAuiTabArt() when
+ This::wxAuiNotebook().
getArtProvider(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_GetArtProvider,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page_idx::integer()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetpage">external documentation</a>.
+-spec getPage(This, Page_idx) -> wxWindow:wxWindow() when
+ This::wxAuiNotebook(), Page_idx::integer().
getPage(#wx_ref{type=ThisT,ref=ThisRef},Page_idx)
when is_integer(Page_idx) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_GetPage,
<<ThisRef:32/?UI,Page_idx:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page_idx::integer()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetpagebitmap">external documentation</a>.
+-spec getPageBitmap(This, Page_idx) -> wxBitmap:wxBitmap() when
+ This::wxAuiNotebook(), Page_idx::integer().
getPageBitmap(#wx_ref{type=ThisT,ref=ThisRef},Page_idx)
when is_integer(Page_idx) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_GetPageBitmap,
<<ThisRef:32/?UI,Page_idx:32/?UI>>).
-%% @spec (This::wxAuiNotebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetpagecount">external documentation</a>.
+-spec getPageCount(This) -> integer() when
+ This::wxAuiNotebook().
getPageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_GetPageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page_wnd::wxWindow:wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetpageindex">external documentation</a>.
+-spec getPageIndex(This, Page_wnd) -> integer() when
+ This::wxAuiNotebook(), Page_wnd::wxWindow:wxWindow().
getPageIndex(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Page_wndT,ref=Page_wndRef}) ->
?CLASS(ThisT,wxAuiNotebook),
?CLASS(Page_wndT,wxWindow),
wxe_util:call(?wxAuiNotebook_GetPageIndex,
<<ThisRef:32/?UI,Page_wndRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page_idx::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetpagetext">external documentation</a>.
+-spec getPageText(This, Page_idx) -> unicode:charlist() when
+ This::wxAuiNotebook(), Page_idx::integer().
getPageText(#wx_ref{type=ThisT,ref=ThisRef},Page_idx)
when is_integer(Page_idx) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_GetPageText,
<<ThisRef:32/?UI,Page_idx:32/?UI>>).
-%% @spec (This::wxAuiNotebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxAuiNotebook().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page_idx::integer(), Page::wxWindow:wxWindow(), Caption::string()) -> bool()
%% @equiv insertPage(This,Page_idx,Page,Caption, [])
+-spec insertPage(This, Page_idx, Page, Caption) -> boolean() when
+ This::wxAuiNotebook(), Page_idx::integer(), Page::wxWindow:wxWindow(), Caption::unicode:chardata().
+
insertPage(This,Page_idx,Page,Caption)
when is_record(This, wx_ref),is_integer(Page_idx),is_record(Page, wx_ref),is_list(Caption) ->
insertPage(This,Page_idx,Page,Caption, []).
-%% @spec (This::wxAuiNotebook(), Page_idx::integer(), Page::wxWindow:wxWindow(), Caption::string(), [Option]) -> bool()
-%% Option = {select, bool()} | {bitmap, wxBitmap:wxBitmap()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookinsertpage">external documentation</a>.
+-spec insertPage(This, Page_idx, Page, Caption, [Option]) -> boolean() when
+ This::wxAuiNotebook(), Page_idx::integer(), Page::wxWindow:wxWindow(), Caption::unicode:chardata(),
+ Option :: {select, boolean()}
+ | {bitmap, wxBitmap:wxBitmap()}.
insertPage(#wx_ref{type=ThisT,ref=ThisRef},Page_idx,#wx_ref{type=PageT,ref=PageRef},Caption, Options)
when is_integer(Page_idx),is_list(Caption),is_list(Options) ->
?CLASS(ThisT,wxAuiNotebook),
@@ -231,32 +261,36 @@ insertPage(#wx_ref{type=ThisT,ref=ThisRef},Page_idx,#wx_ref{type=PageT,ref=PageR
wxe_util:call(?wxAuiNotebook_InsertPage,
<<ThisRef:32/?UI,Page_idx:32/?UI,PageRef:32/?UI,(byte_size(Caption_UC)):32/?UI,(Caption_UC)/binary, 0:(((8- ((0+byte_size(Caption_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxAuiNotebook(), Page::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebookremovepage">external documentation</a>.
+-spec removePage(This, Page) -> boolean() when
+ This::wxAuiNotebook(), Page::integer().
removePage(#wx_ref{type=ThisT,ref=ThisRef},Page)
when is_integer(Page) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_RemovePage,
<<ThisRef:32/?UI,Page:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Art::wxAuiTabArt:wxAuiTabArt()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetartprovider">external documentation</a>.
+-spec setArtProvider(This, Art) -> ok when
+ This::wxAuiNotebook(), Art::wxAuiTabArt:wxAuiTabArt().
setArtProvider(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ArtT,ref=ArtRef}) ->
?CLASS(ThisT,wxAuiNotebook),
?CLASS(ArtT,wxAuiTabArt),
wxe_util:cast(?wxAuiNotebook_SetArtProvider,
<<ThisRef:32/?UI,ArtRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Font::wxFont:wxFont()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetfont">external documentation</a>.
+-spec setFont(This, Font) -> boolean() when
+ This::wxAuiNotebook(), Font::wxFont:wxFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxAuiNotebook),
?CLASS(FontT,wxFont),
wxe_util:call(?wxAuiNotebook_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page::integer(), Bitmap::wxBitmap:wxBitmap()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetpagebitmap">external documentation</a>.
+-spec setPageBitmap(This, Page, Bitmap) -> boolean() when
+ This::wxAuiNotebook(), Page::integer(), Bitmap::wxBitmap:wxBitmap().
setPageBitmap(#wx_ref{type=ThisT,ref=ThisRef},Page,#wx_ref{type=BitmapT,ref=BitmapRef})
when is_integer(Page) ->
?CLASS(ThisT,wxAuiNotebook),
@@ -264,8 +298,9 @@ setPageBitmap(#wx_ref{type=ThisT,ref=ThisRef},Page,#wx_ref{type=BitmapT,ref=Bitm
wxe_util:call(?wxAuiNotebook_SetPageBitmap,
<<ThisRef:32/?UI,Page:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Page::integer(), Text::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetpagetext">external documentation</a>.
+-spec setPageText(This, Page, Text) -> boolean() when
+ This::wxAuiNotebook(), Page::integer(), Text::unicode:chardata().
setPageText(#wx_ref{type=ThisT,ref=ThisRef},Page,Text)
when is_integer(Page),is_list(Text) ->
?CLASS(ThisT,wxAuiNotebook),
@@ -273,32 +308,35 @@ setPageText(#wx_ref{type=ThisT,ref=ThisRef},Page,Text)
wxe_util:call(?wxAuiNotebook_SetPageText,
<<ThisRef:32/?UI,Page:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxAuiNotebook(), New_page::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetselection">external documentation</a>.
+-spec setSelection(This, New_page) -> integer() when
+ This::wxAuiNotebook(), New_page::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},New_page)
when is_integer(New_page) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:call(?wxAuiNotebook_SetSelection,
<<ThisRef:32/?UI,New_page:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksettabctrlheight">external documentation</a>.
+-spec setTabCtrlHeight(This, Height) -> ok when
+ This::wxAuiNotebook(), Height::integer().
setTabCtrlHeight(#wx_ref{type=ThisT,ref=ThisRef},Height)
when is_integer(Height) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:cast(?wxAuiNotebook_SetTabCtrlHeight,
<<ThisRef:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxAuiNotebook(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebook.html#wxauinotebooksetuniformbitmapsize">external documentation</a>.
+-spec setUniformBitmapSize(This, Size) -> ok when
+ This::wxAuiNotebook(), Size::{W::integer(), H::integer()}.
setUniformBitmapSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxAuiNotebook),
wxe_util:cast(?wxAuiNotebook_SetUniformBitmapSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxAuiNotebook()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxAuiNotebook()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxAuiNotebook),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxAuiNotebookEvent.erl b/lib/wx/src/gen/wxAuiNotebookEvent.erl
index 09a2abf214..6a86464369 100644
--- a/lib/wx/src/gen/wxAuiNotebookEvent.erl
+++ b/lib/wx/src/gen/wxAuiNotebookEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,52 +42,60 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxAuiNotebookEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxAuiNotebookEvent(), S::integer()) -> ok
+-type wxAuiNotebookEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebookevent.html#wxauinotebookeventsetselection">external documentation</a>.
+-spec setSelection(This, S) -> ok when
+ This::wxAuiNotebookEvent(), S::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},S)
when is_integer(S) ->
?CLASS(ThisT,wxAuiNotebookEvent),
wxe_util:cast(?wxAuiNotebookEvent_SetSelection,
<<ThisRef:32/?UI,S:32/?UI>>).
-%% @spec (This::wxAuiNotebookEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebookevent.html#wxauinotebookeventgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxAuiNotebookEvent().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiNotebookEvent),
wxe_util:call(?wxAuiNotebookEvent_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiNotebookEvent(), S::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebookevent.html#wxauinotebookeventsetoldselection">external documentation</a>.
+-spec setOldSelection(This, S) -> ok when
+ This::wxAuiNotebookEvent(), S::integer().
setOldSelection(#wx_ref{type=ThisT,ref=ThisRef},S)
when is_integer(S) ->
?CLASS(ThisT,wxAuiNotebookEvent),
wxe_util:cast(?wxAuiNotebookEvent_SetOldSelection,
<<ThisRef:32/?UI,S:32/?UI>>).
-%% @spec (This::wxAuiNotebookEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebookevent.html#wxauinotebookeventgetoldselection">external documentation</a>.
+-spec getOldSelection(This) -> integer() when
+ This::wxAuiNotebookEvent().
getOldSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiNotebookEvent),
wxe_util:call(?wxAuiNotebookEvent_GetOldSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiNotebookEvent(), S::wxAuiNotebook:wxAuiNotebook()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebookevent.html#wxauinotebookeventsetdragsource">external documentation</a>.
+-spec setDragSource(This, S) -> ok when
+ This::wxAuiNotebookEvent(), S::wxAuiNotebook:wxAuiNotebook().
setDragSource(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ST,ref=SRef}) ->
?CLASS(ThisT,wxAuiNotebookEvent),
?CLASS(ST,wxAuiNotebook),
wxe_util:cast(?wxAuiNotebookEvent_SetDragSource,
<<ThisRef:32/?UI,SRef:32/?UI>>).
-%% @spec (This::wxAuiNotebookEvent()) -> wxAuiNotebook:wxAuiNotebook()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauinotebookevent.html#wxauinotebookeventgetdragsource">external documentation</a>.
+-spec getDragSource(This) -> wxAuiNotebook:wxAuiNotebook() when
+ This::wxAuiNotebookEvent().
getDragSource(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiNotebookEvent),
wxe_util:call(?wxAuiNotebookEvent_GetDragSource,
diff --git a/lib/wx/src/gen/wxAuiPaneInfo.erl b/lib/wx/src/gen/wxAuiPaneInfo.erl
index 7b1401b069..d59a8e8676 100644
--- a/lib/wx/src/gen/wxAuiPaneInfo.erl
+++ b/lib/wx/src/gen/wxAuiPaneInfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,54 +44,63 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxAuiPaneInfo/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxAuiPaneInfo()
+-type wxAuiPaneInfo() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfowxauipaneinfo">external documentation</a>.
+-spec new() -> wxAuiPaneInfo().
new() ->
wxe_util:construct(?wxAuiPaneInfo_new_0,
<<>>).
-%% @spec (C::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfowxauipaneinfo">external documentation</a>.
+-spec new(C) -> wxAuiPaneInfo() when
+ C::wxAuiPaneInfo().
new(#wx_ref{type=CT,ref=CRef}) ->
?CLASS(CT,wxAuiPaneInfo),
wxe_util:construct(?wxAuiPaneInfo_new_1,
<<CRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfobestsize">external documentation</a>.
+-spec bestSize(This, Size) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}.
bestSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_BestSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), X::integer(), Y::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfobestsize">external documentation</a>.
+-spec bestSize(This, X, Y) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), X::integer(), Y::integer().
bestSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_BestSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfobottom">external documentation</a>.
+-spec bottom(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
bottom(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Bottom,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv bottomDockable(This, [])
+-spec bottomDockable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
bottomDockable(This)
when is_record(This, wx_ref) ->
bottomDockable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfobottomdockable">external documentation</a>.
+-spec bottomDockable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
bottomDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -101,8 +110,9 @@ bottomDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_BottomDockable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), C::string()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfocaption">external documentation</a>.
+-spec caption(This, C) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), C::unicode:chardata().
caption(#wx_ref{type=ThisT,ref=ThisRef},C)
when is_list(C) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -110,15 +120,18 @@ caption(#wx_ref{type=ThisT,ref=ThisRef},C)
wxe_util:call(?wxAuiPaneInfo_Caption,
<<ThisRef:32/?UI,(byte_size(C_UC)):32/?UI,(C_UC)/binary, 0:(((8- ((0+byte_size(C_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv captionVisible(This, [])
+-spec captionVisible(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
captionVisible(This)
when is_record(This, wx_ref) ->
captionVisible(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfocaptionvisible">external documentation</a>.
+-spec captionVisible(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
captionVisible(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -128,29 +141,34 @@ captionVisible(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_CaptionVisible,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfocentre">external documentation</a>.
+-spec centre(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
centre(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Centre,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfocentrepane">external documentation</a>.
+-spec centrePane(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
centrePane(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_CentrePane,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv closeButton(This, [])
+-spec closeButton(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
closeButton(This)
when is_record(This, wx_ref) ->
closeButton(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoclosebutton">external documentation</a>.
+-spec closeButton(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
closeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -160,22 +178,26 @@ closeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_CloseButton,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfodefaultpane">external documentation</a>.
+-spec defaultPane(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
defaultPane(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_DefaultPane,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv destroyOnClose(This, [])
+-spec destroyOnClose(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
destroyOnClose(This)
when is_record(This, wx_ref) ->
destroyOnClose(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfodestroyonclose">external documentation</a>.
+-spec destroyOnClose(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
destroyOnClose(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -185,30 +207,35 @@ destroyOnClose(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_DestroyOnClose,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Direction::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfodirection">external documentation</a>.
+-spec direction(This, Direction) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Direction::integer().
direction(#wx_ref{type=ThisT,ref=ThisRef},Direction)
when is_integer(Direction) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Direction,
<<ThisRef:32/?UI,Direction:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfodock">external documentation</a>.
+-spec dock(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
dock(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Dock,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv dockable(This, [])
+-spec dockable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
dockable(This)
when is_record(This, wx_ref) ->
dockable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfodockable">external documentation</a>.
+-spec dockable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
dockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -218,29 +245,34 @@ dockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Dockable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofixed">external documentation</a>.
+-spec fixed(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
fixed(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Fixed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloat">external documentation</a>.
+-spec float(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
float(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Float,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv floatable(This, [])
+-spec floatable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
floatable(This)
when is_record(This, wx_ref) ->
floatable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatable">external documentation</a>.
+-spec floatable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
floatable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -250,47 +282,54 @@ floatable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Floatable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Pos::{X::integer(),Y::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatingposition">external documentation</a>.
+-spec floatingPosition(This, Pos) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Pos::{X::integer(), Y::integer()}.
floatingPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_FloatingPosition_1,
<<ThisRef:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), X::integer(), Y::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatingposition">external documentation</a>.
+-spec floatingPosition(This, X, Y) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), X::integer(), Y::integer().
floatingPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_FloatingPosition_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatingsize">external documentation</a>.
+-spec floatingSize(This, Size) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}.
floatingSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_FloatingSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), X::integer(), Y::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfofloatingsize">external documentation</a>.
+-spec floatingSize(This, X, Y) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), X::integer(), Y::integer().
floatingSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_FloatingSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv gripper(This, [])
+-spec gripper(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
gripper(This)
when is_record(This, wx_ref) ->
gripper(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfogripper">external documentation</a>.
+-spec gripper(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
gripper(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -300,15 +339,18 @@ gripper(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Gripper,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv gripperTop(This, [])
+-spec gripperTop(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
gripperTop(This)
when is_record(This, wx_ref) ->
gripperTop(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {attop, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfogrippertop">external documentation</a>.
+-spec gripperTop(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {attop, boolean()}.
gripperTop(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -318,192 +360,220 @@ gripperTop(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_GripperTop,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasborder">external documentation</a>.
+-spec hasBorder(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasBorder(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasBorder,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohascaption">external documentation</a>.
+-spec hasCaption(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasCaption(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasCaption,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasclosebutton">external documentation</a>.
+-spec hasCloseButton(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasCloseButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasCloseButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Flag::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasflag">external documentation</a>.
+-spec hasFlag(This, Flag) -> boolean() when
+ This::wxAuiPaneInfo(), Flag::integer().
hasFlag(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_integer(Flag) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasFlag,
<<ThisRef:32/?UI,Flag:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasgripper">external documentation</a>.
+-spec hasGripper(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasGripper(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasGripper,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasgrippertop">external documentation</a>.
+-spec hasGripperTop(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasGripperTop(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasGripperTop,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasmaximizebutton">external documentation</a>.
+-spec hasMaximizeButton(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasMaximizeButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasMaximizeButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohasminimizebutton">external documentation</a>.
+-spec hasMinimizeButton(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasMinimizeButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasMinimizeButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohaspinbutton">external documentation</a>.
+-spec hasPinButton(This) -> boolean() when
+ This::wxAuiPaneInfo().
hasPinButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_HasPinButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfohide">external documentation</a>.
+-spec hide(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
hide(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Hide,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisbottomdockable">external documentation</a>.
+-spec isBottomDockable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isBottomDockable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsBottomDockable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisdocked">external documentation</a>.
+-spec isDocked(This) -> boolean() when
+ This::wxAuiPaneInfo().
isDocked(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsDocked,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisfixed">external documentation</a>.
+-spec isFixed(This) -> boolean() when
+ This::wxAuiPaneInfo().
isFixed(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsFixed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisfloatable">external documentation</a>.
+-spec isFloatable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isFloatable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsFloatable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisfloating">external documentation</a>.
+-spec isFloating(This) -> boolean() when
+ This::wxAuiPaneInfo().
isFloating(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsFloating,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisleftdockable">external documentation</a>.
+-spec isLeftDockable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isLeftDockable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsLeftDockable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoismovable">external documentation</a>.
+-spec isMovable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isMovable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsMovable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxAuiPaneInfo().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisresizable">external documentation</a>.
+-spec isResizable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isResizable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsResizable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisrightdockable">external documentation</a>.
+-spec isRightDockable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isRightDockable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsRightDockable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoisshown">external documentation</a>.
+-spec isShown(This) -> boolean() when
+ This::wxAuiPaneInfo().
isShown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsShown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoistoolbar">external documentation</a>.
+-spec isToolbar(This) -> boolean() when
+ This::wxAuiPaneInfo().
isToolbar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsToolbar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoistopdockable">external documentation</a>.
+-spec isTopDockable(This) -> boolean() when
+ This::wxAuiPaneInfo().
isTopDockable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_IsTopDockable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Layer::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfolayer">external documentation</a>.
+-spec layer(This, Layer) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Layer::integer().
layer(#wx_ref{type=ThisT,ref=ThisRef},Layer)
when is_integer(Layer) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Layer,
<<ThisRef:32/?UI,Layer:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoleft">external documentation</a>.
+-spec left(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
left(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Left,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv leftDockable(This, [])
+-spec leftDockable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
leftDockable(This)
when is_record(This, wx_ref) ->
leftDockable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoleftdockable">external documentation</a>.
+-spec leftDockable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
leftDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -513,31 +583,36 @@ leftDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_LeftDockable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfomaxsize">external documentation</a>.
+-spec maxSize(This, Size) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}.
maxSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_MaxSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), X::integer(), Y::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfomaxsize">external documentation</a>.
+-spec maxSize(This, X, Y) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), X::integer(), Y::integer().
maxSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_MaxSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv maximizeButton(This, [])
+-spec maximizeButton(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
maximizeButton(This)
when is_record(This, wx_ref) ->
maximizeButton(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfomaximizebutton">external documentation</a>.
+-spec maximizeButton(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
maximizeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -547,31 +622,36 @@ maximizeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_MaximizeButton,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Size::{W::integer(),H::integer()}) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfominsize">external documentation</a>.
+-spec minSize(This, Size) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Size::{W::integer(), H::integer()}.
minSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_MinSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), X::integer(), Y::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfominsize">external documentation</a>.
+-spec minSize(This, X, Y) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), X::integer(), Y::integer().
minSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_MinSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv minimizeButton(This, [])
+-spec minimizeButton(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
minimizeButton(This)
when is_record(This, wx_ref) ->
minimizeButton(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfominimizebutton">external documentation</a>.
+-spec minimizeButton(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
minimizeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -581,15 +661,18 @@ minimizeButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_MinimizeButton,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv movable(This, [])
+-spec movable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
movable(This)
when is_record(This, wx_ref) ->
movable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfomovable">external documentation</a>.
+-spec movable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
movable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -599,8 +682,9 @@ movable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Movable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), N::string()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoname">external documentation</a>.
+-spec name(This, N) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), N::unicode:chardata().
name(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_list(N) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -608,15 +692,18 @@ name(#wx_ref{type=ThisT,ref=ThisRef},N)
wxe_util:call(?wxAuiPaneInfo_Name,
<<ThisRef:32/?UI,(byte_size(N_UC)):32/?UI,(N_UC)/binary, 0:(((8- ((0+byte_size(N_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv paneBorder(This, [])
+-spec paneBorder(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
paneBorder(This)
when is_record(This, wx_ref) ->
paneBorder(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfopaneborder">external documentation</a>.
+-spec paneBorder(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
paneBorder(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -626,15 +713,18 @@ paneBorder(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_PaneBorder,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv pinButton(This, [])
+-spec pinButton(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
pinButton(This)
when is_record(This, wx_ref) ->
pinButton(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {visible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfopinbutton">external documentation</a>.
+-spec pinButton(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {visible, boolean()}.
pinButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -644,23 +734,27 @@ pinButton(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_PinButton,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Pos::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoposition">external documentation</a>.
+-spec position(This, Pos) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Pos::integer().
position(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Position,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv resizable(This, [])
+-spec resizable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
resizable(This)
when is_record(This, wx_ref) ->
resizable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {resizable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinforesizable">external documentation</a>.
+-spec resizable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {resizable, boolean()}.
resizable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -670,22 +764,26 @@ resizable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Resizable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinforight">external documentation</a>.
+-spec right(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
right(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Right,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv rightDockable(This, [])
+-spec rightDockable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
rightDockable(This)
when is_record(This, wx_ref) ->
rightDockable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinforightdockable">external documentation</a>.
+-spec rightDockable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
rightDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -695,39 +793,45 @@ rightDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_RightDockable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), Row::integer()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinforow">external documentation</a>.
+-spec row(This, Row) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Row::integer().
row(#wx_ref{type=ThisT,ref=ThisRef},Row)
when is_integer(Row) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Row,
<<ThisRef:32/?UI,Row:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Source::wxAuiPaneInfo()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfosafeset">external documentation</a>.
+-spec safeSet(This, Source) -> ok when
+ This::wxAuiPaneInfo(), Source::wxAuiPaneInfo().
safeSet(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SourceT,ref=SourceRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
?CLASS(SourceT,wxAuiPaneInfo),
wxe_util:cast(?wxAuiPaneInfo_SafeSet,
<<ThisRef:32/?UI,SourceRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo(), Flag::integer(), Option_state::bool()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfosetflag">external documentation</a>.
+-spec setFlag(This, Flag, Option_state) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), Flag::integer(), Option_state::boolean().
setFlag(#wx_ref{type=ThisT,ref=ThisRef},Flag,Option_state)
when is_integer(Flag),is_boolean(Option_state) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_SetFlag,
<<ThisRef:32/?UI,Flag:32/?UI,(wxe_util:from_bool(Option_state)):32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv show(This, [])
+-spec show(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
show(This)
when is_record(This, wx_ref) ->
show(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {show, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfoshow">external documentation</a>.
+-spec show(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {show, boolean()}.
show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -737,29 +841,34 @@ show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_Show,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfotoolbarpane">external documentation</a>.
+-spec toolbarPane(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
toolbarPane(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_ToolbarPane,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfotop">external documentation</a>.
+-spec top(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
top(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
wxe_util:call(?wxAuiPaneInfo_Top,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> wxAuiPaneInfo()
%% @equiv topDockable(This, [])
+-spec topDockable(This) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo().
+
topDockable(This)
when is_record(This, wx_ref) ->
topDockable(This, []).
-%% @spec (This::wxAuiPaneInfo(), [Option]) -> wxAuiPaneInfo()
-%% Option = {b, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfotopdockable">external documentation</a>.
+-spec topDockable(This, [Option]) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(),
+ Option :: {b, boolean()}.
topDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxAuiPaneInfo),
@@ -769,16 +878,17 @@ topDockable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxAuiPaneInfo_TopDockable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxAuiPaneInfo(), W::wxWindow:wxWindow()) -> wxAuiPaneInfo()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxauipaneinfo.html#wxauipaneinfowindow">external documentation</a>.
+-spec window(This, W) -> wxAuiPaneInfo() when
+ This::wxAuiPaneInfo(), W::wxWindow:wxWindow().
window(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WT,ref=WRef}) ->
?CLASS(ThisT,wxAuiPaneInfo),
?CLASS(WT,wxWindow),
wxe_util:call(?wxAuiPaneInfo_Window,
<<ThisRef:32/?UI,WRef:32/?UI>>).
-%% @spec (This::wxAuiPaneInfo()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxAuiPaneInfo()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxAuiPaneInfo),
wxe_util:destroy(?wxAuiPaneInfo_destruct,Obj),
diff --git a/lib/wx/src/gen/wxAuiTabArt.erl b/lib/wx/src/gen/wxAuiTabArt.erl
index 725bac9664..a65c6dc8cf 100644
--- a/lib/wx/src/gen/wxAuiTabArt.erl
+++ b/lib/wx/src/gen/wxAuiTabArt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxAuiTabArt/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxAuiTabArt() :: wx:wx_object().
diff --git a/lib/wx/src/gen/wxBitmap.erl b/lib/wx/src/gen/wxBitmap.erl
index 53c57e4393..8816e27cdd 100644
--- a/lib/wx/src/gen/wxBitmap.erl
+++ b/lib/wx/src/gen/wxBitmap.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,22 +32,27 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxBitmap/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxBitmap()
+-type wxBitmap() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapwxbitmap">external documentation</a>.
+-spec new() -> wxBitmap().
new() ->
wxe_util:construct(?wxBitmap_new_0,
<<>>).
-%% @spec (X::string()|term()) -> wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapwxbitmap">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Filename::string()) -> new(Filename, []) </c></p>
-%% <p><c>
-%% new(Image::wxImage:wxImage()) -> new(Image, []) </c></p>
+%% <br /> Also:<br />
+%% new(Image) -> wxBitmap() when<br />
+%% Image::wxImage:wxImage().<br />
+%%
+%%<br /> Type = ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+-spec new(Filename) -> wxBitmap() when
+ Filename::unicode:chardata();
+ (Image) -> wxBitmap() when
+ Image::wxImage:wxImage().
new(Filename)
when is_list(Filename) ->
@@ -57,21 +62,24 @@ new(Image)
when is_record(Image, wx_ref) ->
new(Image, []).
-%% @spec (X::integer()|string()|term(),X::integer()|term()) -> wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapwxbitmap">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Width::integer(), Height::integer()) -> new(Width,Height, []) </c></p>
-%% <p><c>
-%% new(Filename::string(), [Option]) -> wxBitmap() </c>
-%%<br /> Option = {type, WxBitmapType}
-%%<br /> WxBitmapType = integer()
-%%<br /> WxBitmapType is one of ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
-%% </p>
-%% <p><c>
-%% new(Image::wxImage:wxImage(), [Option]) -> wxBitmap() </c>
-%%<br /> Option = {depth, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Filename, [Option]) -> wxBitmap() when<br />
+%% Filename::unicode:chardata(),<br />
+%% Option :: {type, wx:wx_enum()};<br />
+%% (Image, [Option]) -> wxBitmap() when<br />
+%% Image::wxImage:wxImage(),<br />
+%% Option :: {depth, integer()}.<br />
+%%
+%%<br /> Type = ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+-spec new(Width, Height) -> wxBitmap() when
+ Width::integer(), Height::integer();
+ (Filename, [Option]) -> wxBitmap() when
+ Filename::unicode:chardata(),
+ Option :: {type, wx:wx_enum()};
+ (Image, [Option]) -> wxBitmap() when
+ Image::wxImage:wxImage(),
+ Option :: {depth, integer()}.
new(Width,Height)
when is_integer(Width),is_integer(Height) ->
@@ -93,15 +101,17 @@ new(#wx_ref{type=ImageT,ref=ImageRef}, Options)
wxe_util:construct(?wxBitmap_new_2_1,
<<ImageRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (X::binary()|integer(),X::integer(),X::integer()|term()) -> wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapwxbitmap">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Bits::binary(), Width::integer(), Height::integer()) -> new(Bits,Width,Height, []) </c></p>
-%% <p><c>
-%% new(Width::integer(), Height::integer(), [Option]) -> wxBitmap() </c>
-%%<br /> Option = {depth, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Width, Height, [Option]) -> wxBitmap() when<br />
+%% Width::integer(), Height::integer(),<br />
+%% Option :: {depth, integer()}.<br />
+%%
+-spec new(Bits, Width, Height) -> wxBitmap() when
+ Bits::binary(), Width::integer(), Height::integer();
+ (Width, Height, [Option]) -> wxBitmap() when
+ Width::integer(), Height::integer(),
+ Option :: {depth, integer()}.
new(Bits,Width,Height)
when is_binary(Bits),is_integer(Width),is_integer(Height) ->
@@ -114,9 +124,10 @@ new(Width,Height, Options)
wxe_util:construct(?wxBitmap_new_3,
<<Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (Bits::binary(), Width::integer(), Height::integer(), [Option]) -> wxBitmap()
-%% Option = {depth, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapwxbitmap">external documentation</a>.
+-spec new(Bits, Width, Height, [Option]) -> wxBitmap() when
+ Bits::binary(), Width::integer(), Height::integer(),
+ Option :: {depth, integer()}.
new(Bits,Width,Height, Options)
when is_binary(Bits),is_integer(Width),is_integer(Height),is_list(Options) ->
wxe_util:send_bin(Bits),
@@ -126,30 +137,35 @@ new(Bits,Width,Height, Options)
wxe_util:construct(?wxBitmap_new_4,
<<Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxBitmap()) -> wxImage:wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapconverttoimage">external documentation</a>.
+-spec convertToImage(This) -> wxImage:wxImage() when
+ This::wxBitmap().
convertToImage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_ConvertToImage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Icon::wxIcon:wxIcon()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapcopyfromicon">external documentation</a>.
+-spec copyFromIcon(This, Icon) -> boolean() when
+ This::wxBitmap(), Icon::wxIcon:wxIcon().
copyFromIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef}) ->
?CLASS(ThisT,wxBitmap),
?CLASS(IconT,wxIcon),
wxe_util:call(?wxBitmap_CopyFromIcon,
<<ThisRef:32/?UI,IconRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Width::integer(), Height::integer()) -> bool()
%% @equiv create(This,Width,Height, [])
+-spec create(This, Width, Height) -> boolean() when
+ This::wxBitmap(), Width::integer(), Height::integer().
+
create(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
create(This,Width,Height, []).
-%% @spec (This::wxBitmap(), Width::integer(), Height::integer(), [Option]) -> bool()
-%% Option = {depth, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapcreate">external documentation</a>.
+-spec create(This, Width, Height, [Option]) -> boolean() when
+ This::wxBitmap(), Width::integer(), Height::integer(),
+ Option :: {depth, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxBitmap),
@@ -159,60 +175,68 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxBitmap_Create,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxBitmap()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetdepth">external documentation</a>.
+-spec getDepth(This) -> integer() when
+ This::wxBitmap().
getDepth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_GetDepth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetheight">external documentation</a>.
+-spec getHeight(This) -> integer() when
+ This::wxBitmap().
getHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_GetHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap()) -> wxPalette:wxPalette()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetpalette">external documentation</a>.
+-spec getPalette(This) -> wxPalette:wxPalette() when
+ This::wxBitmap().
getPalette(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_GetPalette,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap()) -> wxMask:wxMask()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetmask">external documentation</a>.
+-spec getMask(This) -> wxMask:wxMask() when
+ This::wxBitmap().
getMask(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_GetMask,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetwidth">external documentation</a>.
+-spec getWidth(This) -> integer() when
+ This::wxBitmap().
getWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_GetWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapgetsubbitmap">external documentation</a>.
+-spec getSubBitmap(This, Rect) -> wxBitmap() when
+ This::wxBitmap(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
getSubBitmap(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_GetSubBitmap,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxBitmap(), Name::string()) -> bool()
%% @equiv loadFile(This,Name, [])
+-spec loadFile(This, Name) -> boolean() when
+ This::wxBitmap(), Name::unicode:chardata().
+
loadFile(This,Name)
when is_record(This, wx_ref),is_list(Name) ->
loadFile(This,Name, []).
-%% @spec (This::wxBitmap(), Name::string(), [Option]) -> bool()
-%% Option = {type, WxBitmapType}
-%% WxBitmapType = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmaploadfile">external documentation</a>.
-%%<br /> WxBitmapType is one of ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+%%<br /> Type = ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+-spec loadFile(This, Name, [Option]) -> boolean() when
+ This::wxBitmap(), Name::unicode:chardata(),
+ Option :: {type, wx:wx_enum()}.
loadFile(#wx_ref{type=ThisT,ref=ThisRef},Name, Options)
when is_list(Name),is_list(Options) ->
?CLASS(ThisT,wxBitmap),
@@ -223,24 +247,27 @@ loadFile(#wx_ref{type=ThisT,ref=ThisRef},Name, Options)
wxe_util:call(?wxBitmap_LoadFile,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxBitmap()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapok">external documentation</a>.
+-spec ok(This) -> boolean() when
+ This::wxBitmap().
ok(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmap),
wxe_util:call(?wxBitmap_Ok,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Name::string(), Type::WxBitmapType) -> bool()
%% @equiv saveFile(This,Name,Type, [])
+-spec saveFile(This, Name, Type) -> boolean() when
+ This::wxBitmap(), Name::unicode:chardata(), Type::wx:wx_enum().
+
saveFile(This,Name,Type)
when is_record(This, wx_ref),is_list(Name),is_integer(Type) ->
saveFile(This,Name,Type, []).
-%% @spec (This::wxBitmap(), Name::string(), Type::WxBitmapType, [Option]) -> bool()
-%% Option = {palette, wxPalette:wxPalette()}
-%% WxBitmapType = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapsavefile">external documentation</a>.
-%%<br /> WxBitmapType is one of ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+%%<br /> Type = ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+-spec saveFile(This, Name, Type, [Option]) -> boolean() when
+ This::wxBitmap(), Name::unicode:chardata(), Type::wx:wx_enum(),
+ Option :: {palette, wxPalette:wxPalette()}.
saveFile(#wx_ref{type=ThisT,ref=ThisRef},Name,Type, Options)
when is_list(Name),is_integer(Type),is_list(Options) ->
?CLASS(ThisT,wxBitmap),
@@ -251,48 +278,53 @@ saveFile(#wx_ref{type=ThisT,ref=ThisRef},Name,Type, Options)
wxe_util:call(?wxBitmap_SaveFile,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,Type:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxBitmap(), Depth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapsetdepth">external documentation</a>.
+-spec setDepth(This, Depth) -> ok when
+ This::wxBitmap(), Depth::integer().
setDepth(#wx_ref{type=ThisT,ref=ThisRef},Depth)
when is_integer(Depth) ->
?CLASS(ThisT,wxBitmap),
wxe_util:cast(?wxBitmap_SetDepth,
<<ThisRef:32/?UI,Depth:32/?UI>>).
-%% @spec (This::wxBitmap(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapsetheight">external documentation</a>.
+-spec setHeight(This, Height) -> ok when
+ This::wxBitmap(), Height::integer().
setHeight(#wx_ref{type=ThisT,ref=ThisRef},Height)
when is_integer(Height) ->
?CLASS(ThisT,wxBitmap),
wxe_util:cast(?wxBitmap_SetHeight,
<<ThisRef:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxBitmap(), Mask::wxMask:wxMask()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapsetmask">external documentation</a>.
+-spec setMask(This, Mask) -> ok when
+ This::wxBitmap(), Mask::wxMask:wxMask().
setMask(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MaskT,ref=MaskRef}) ->
?CLASS(ThisT,wxBitmap),
?CLASS(MaskT,wxMask),
wxe_util:cast(?wxBitmap_SetMask,
<<ThisRef:32/?UI,MaskRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Palette::wxPalette:wxPalette()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapsetpalette">external documentation</a>.
+-spec setPalette(This, Palette) -> ok when
+ This::wxBitmap(), Palette::wxPalette:wxPalette().
setPalette(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PaletteT,ref=PaletteRef}) ->
?CLASS(ThisT,wxBitmap),
?CLASS(PaletteT,wxPalette),
wxe_util:cast(?wxBitmap_SetPalette,
<<ThisRef:32/?UI,PaletteRef:32/?UI>>).
-%% @spec (This::wxBitmap(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmap.html#wxbitmapsetwidth">external documentation</a>.
+-spec setWidth(This, Width) -> ok when
+ This::wxBitmap(), Width::integer().
setWidth(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxBitmap),
wxe_util:cast(?wxBitmap_SetWidth,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxBitmap()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBitmap()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBitmap),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxBitmapButton.erl b/lib/wx/src/gen/wxBitmapButton.erl
index 0c187bf1c1..ddddbbc1dd 100644
--- a/lib/wx/src/gen/wxBitmapButton.erl
+++ b/lib/wx/src/gen/wxBitmapButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxBitmapButton/0]).
%% @hidden
parent_class(wxButton) -> true;
parent_class(wxControl) -> true;
@@ -79,21 +80,28 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxBitmapButton()
+-type wxBitmapButton() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonwxbitmapbutton">external documentation</a>.
+-spec new() -> wxBitmapButton().
new() ->
wxe_util:construct(?wxBitmapButton_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap()) -> wxBitmapButton()
%% @equiv new(Parent,Id,Bitmap, [])
+-spec new(Parent, Id, Bitmap) -> wxBitmapButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap().
+
new(Parent,Id,Bitmap)
when is_record(Parent, wx_ref),is_integer(Id),is_record(Bitmap, wx_ref) ->
new(Parent,Id,Bitmap, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wxBitmapButton()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonwxbitmapbutton">external documentation</a>.
+-spec new(Parent, Id, Bitmap, [Option]) -> wxBitmapButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -107,15 +115,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=BitmapT,ref=BitmapRef},
wxe_util:construct(?wxBitmapButton_new_4,
<<ParentRef:32/?UI,Id:32/?UI,BitmapRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxBitmapButton(), Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap()) -> bool()
%% @equiv create(This,Parent,Id,Bitmap, [])
+-spec create(This, Parent, Id, Bitmap) -> boolean() when
+ This::wxBitmapButton(), Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap().
+
create(This,Parent,Id,Bitmap)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_record(Bitmap, wx_ref) ->
create(This,Parent,Id,Bitmap, []).
-%% @spec (This::wxBitmapButton(), Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttoncreate">external documentation</a>.
+-spec create(This, Parent, Id, Bitmap, [Option]) -> boolean() when
+ This::wxBitmapButton(), Parent::wxWindow:wxWindow(), Id::integer(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxBitmapButton),
@@ -130,68 +144,76 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#w
wxe_util:call(?wxBitmapButton_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,BitmapRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxBitmapButton()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttongetbitmapdisabled">external documentation</a>.
+-spec getBitmapDisabled(This) -> wxBitmap:wxBitmap() when
+ This::wxBitmapButton().
getBitmapDisabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmapButton),
wxe_util:call(?wxBitmapButton_GetBitmapDisabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmapButton()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttongetbitmapfocus">external documentation</a>.
+-spec getBitmapFocus(This) -> wxBitmap:wxBitmap() when
+ This::wxBitmapButton().
getBitmapFocus(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmapButton),
wxe_util:call(?wxBitmapButton_GetBitmapFocus,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmapButton()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttongetbitmaplabel">external documentation</a>.
+-spec getBitmapLabel(This) -> wxBitmap:wxBitmap() when
+ This::wxBitmapButton().
getBitmapLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmapButton),
wxe_util:call(?wxBitmapButton_GetBitmapLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmapButton()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttongetbitmapselected">external documentation</a>.
+-spec getBitmapSelected(This) -> wxBitmap:wxBitmap() when
+ This::wxBitmapButton().
getBitmapSelected(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmapButton),
wxe_util:call(?wxBitmapButton_GetBitmapSelected,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmapButton(), Disabled::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonsetbitmapdisabled">external documentation</a>.
+-spec setBitmapDisabled(This, Disabled) -> ok when
+ This::wxBitmapButton(), Disabled::wxBitmap:wxBitmap().
setBitmapDisabled(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DisabledT,ref=DisabledRef}) ->
?CLASS(ThisT,wxBitmapButton),
?CLASS(DisabledT,wxBitmap),
wxe_util:cast(?wxBitmapButton_SetBitmapDisabled,
<<ThisRef:32/?UI,DisabledRef:32/?UI>>).
-%% @spec (This::wxBitmapButton(), Focus::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonsetbitmapfocus">external documentation</a>.
+-spec setBitmapFocus(This, Focus) -> ok when
+ This::wxBitmapButton(), Focus::wxBitmap:wxBitmap().
setBitmapFocus(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FocusT,ref=FocusRef}) ->
?CLASS(ThisT,wxBitmapButton),
?CLASS(FocusT,wxBitmap),
wxe_util:cast(?wxBitmapButton_SetBitmapFocus,
<<ThisRef:32/?UI,FocusRef:32/?UI>>).
-%% @spec (This::wxBitmapButton(), Bitmap::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonsetbitmaplabel">external documentation</a>.
+-spec setBitmapLabel(This, Bitmap) -> ok when
+ This::wxBitmapButton(), Bitmap::wxBitmap:wxBitmap().
setBitmapLabel(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(ThisT,wxBitmapButton),
?CLASS(BitmapT,wxBitmap),
wxe_util:cast(?wxBitmapButton_SetBitmapLabel,
<<ThisRef:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxBitmapButton(), Sel::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapbutton.html#wxbitmapbuttonsetbitmapselected">external documentation</a>.
+-spec setBitmapSelected(This, Sel) -> ok when
+ This::wxBitmapButton(), Sel::wxBitmap:wxBitmap().
setBitmapSelected(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SelT,ref=SelRef}) ->
?CLASS(ThisT,wxBitmapButton),
?CLASS(SelT,wxBitmap),
wxe_util:cast(?wxBitmapButton_SetBitmapSelected,
<<ThisRef:32/?UI,SelRef:32/?UI>>).
-%% @spec (This::wxBitmapButton()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBitmapButton()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBitmapButton),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxBitmapDataObject.erl b/lib/wx/src/gen/wxBitmapDataObject.erl
index b5207072e3..8f9701d3c2 100644
--- a/lib/wx/src/gen/wxBitmapDataObject.erl
+++ b/lib/wx/src/gen/wxBitmapDataObject.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,25 +32,27 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxBitmapDataObject/0]).
%% @hidden
parent_class(wxDataObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxBitmapDataObject()
+-type wxBitmapDataObject() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxBitmapDataObject().
+
new() ->
new([]).
-%% @spec (X::term()) -> wxBitmapDataObject()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapdataobject.html#wxbitmapdataobjectwxbitmapdataobject">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new([Option]) -> wxBitmapDataObject() </c>
-%%<br /> Option = {bitmap, wxBitmap:wxBitmap()}
-%% </p>
-%% <p><c>
-%% new(Bitmap::wxBitmap:wxBitmap()) -> wxBitmapDataObject() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Bitmap) -> wxBitmapDataObject() when<br />
+%% Bitmap::wxBitmap:wxBitmap().<br />
+%%
+-spec new([Option]) -> wxBitmapDataObject() when
+ Option :: {bitmap, wxBitmap:wxBitmap()};
+ (Bitmap) -> wxBitmapDataObject() when
+ Bitmap::wxBitmap:wxBitmap().
new(Options)
when is_list(Options) ->
MOpts = fun({bitmap, #wx_ref{type=BitmapT,ref=BitmapRef}}, Acc) -> ?CLASS(BitmapT,wxBitmap),[<<1:32/?UI,BitmapRef:32/?UI>>|Acc];
@@ -63,23 +65,25 @@ new(#wx_ref{type=BitmapT,ref=BitmapRef}) ->
wxe_util:construct(?wxBitmapDataObject_new_1_1,
<<BitmapRef:32/?UI>>).
-%% @spec (This::wxBitmapDataObject()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapdataobject.html#wxbitmapdataobjectgetbitmap">external documentation</a>.
+-spec getBitmap(This) -> wxBitmap:wxBitmap() when
+ This::wxBitmapDataObject().
getBitmap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBitmapDataObject),
wxe_util:call(?wxBitmapDataObject_GetBitmap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBitmapDataObject(), Bitmap::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbitmapdataobject.html#wxbitmapdataobjectsetbitmap">external documentation</a>.
+-spec setBitmap(This, Bitmap) -> ok when
+ This::wxBitmapDataObject(), Bitmap::wxBitmap:wxBitmap().
setBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(ThisT,wxBitmapDataObject),
?CLASS(BitmapT,wxBitmap),
wxe_util:cast(?wxBitmapDataObject_SetBitmap,
<<ThisRef:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxBitmapDataObject()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBitmapDataObject()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBitmapDataObject),
wxe_util:destroy(?wxBitmapDataObject_destroy,Obj),
diff --git a/lib/wx/src/gen/wxBoxSizer.erl b/lib/wx/src/gen/wxBoxSizer.erl
index e6287945a9..fcf6b5fd65 100644
--- a/lib/wx/src/gen/wxBoxSizer.erl
+++ b/lib/wx/src/gen/wxBoxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +40,30 @@
setMinSize/2,setMinSize/3,setSizeHints/2,setVirtualSizeHints/2,show/2,
show/3]).
+-export_type([wxBoxSizer/0]).
%% @hidden
parent_class(wxSizer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Orient::integer()) -> wxBoxSizer()
+-type wxBoxSizer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxboxsizer.html#wxboxsizerwxboxsizer">external documentation</a>.
+-spec new(Orient) -> wxBoxSizer() when
+ Orient::integer().
new(Orient)
when is_integer(Orient) ->
wxe_util:construct(?wxBoxSizer_new,
<<Orient:32/?UI>>).
-%% @spec (This::wxBoxSizer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxboxsizer.html#wxboxsizergetorientation">external documentation</a>.
+-spec getOrientation(This) -> integer() when
+ This::wxBoxSizer().
getOrientation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBoxSizer),
wxe_util:call(?wxBoxSizer_GetOrientation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBoxSizer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBoxSizer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBoxSizer),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxBrush.erl b/lib/wx/src/gen/wxBrush.erl
index e42edd62e3..40aa62297e 100644
--- a/lib/wx/src/gen/wxBrush.erl
+++ b/lib/wx/src/gen/wxBrush.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,23 +30,26 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxBrush/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxBrush()
+-type wxBrush() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushwxbrush">external documentation</a>.
+-spec new() -> wxBrush().
new() ->
wxe_util:construct(?wxBrush_new_0,
<<>>).
-%% @spec (X::term()) -> wxBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushwxbrush">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Colour::wx:colour()) -> new(Colour, []) </c></p>
-%% <p><c>
-%% new(StippleBitmap::wxBitmap:wxBitmap()) -> wxBrush() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(StippleBitmap) -> wxBrush() when<br />
+%% StippleBitmap::wxBitmap:wxBitmap().<br />
+%%
+-spec new(Colour) -> wxBrush() when
+ Colour::wx:wx_colour();
+ (StippleBitmap) -> wxBrush() when
+ StippleBitmap::wxBitmap:wxBitmap().
new(Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
@@ -56,9 +59,10 @@ new(#wx_ref{type=StippleBitmapT,ref=StippleBitmapRef}) ->
wxe_util:construct(?wxBrush_new_1,
<<StippleBitmapRef:32/?UI>>).
-%% @spec (Colour::wx:colour(), [Option]) -> wxBrush()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushwxbrush">external documentation</a>.
+-spec new(Colour, [Option]) -> wxBrush() when
+ Colour::wx:wx_colour(),
+ Option :: {style, integer()}.
new(Colour, Options)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4,is_list(Options) ->
MOpts = fun({style, Style}, Acc) -> [<<1:32/?UI,Style:32/?UI>>|Acc];
@@ -67,75 +71,84 @@ new(Colour, Options)
wxe_util:construct(?wxBrush_new_2,
<<(wxe_util:colour_bin(Colour)):16/binary, BinOpt/binary>>).
-%% @spec (This::wxBrush()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushgetcolour">external documentation</a>.
+-spec getColour(This) -> wx:wx_colour4() when
+ This::wxBrush().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBrush),
wxe_util:call(?wxBrush_GetColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBrush()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushgetstipple">external documentation</a>.
+-spec getStipple(This) -> wxBitmap:wxBitmap() when
+ This::wxBrush().
getStipple(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBrush),
wxe_util:call(?wxBrush_GetStipple,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBrush()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushgetstyle">external documentation</a>.
+-spec getStyle(This) -> integer() when
+ This::wxBrush().
getStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBrush),
wxe_util:call(?wxBrush_GetStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBrush()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushishatch">external documentation</a>.
+-spec isHatch(This) -> boolean() when
+ This::wxBrush().
isHatch(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBrush),
wxe_util:call(?wxBrush_IsHatch,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBrush()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxBrush().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxBrush),
wxe_util:call(?wxBrush_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxBrush(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushsetcolour">external documentation</a>.
+-spec setColour(This, Col) -> ok when
+ This::wxBrush(), Col::wx:wx_colour().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Col)
when tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxBrush),
wxe_util:cast(?wxBrush_SetColour_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxBrush(), R::integer(), G::integer(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushsetcolour">external documentation</a>.
+-spec setColour(This, R, G, B) -> ok when
+ This::wxBrush(), R::integer(), G::integer(), B::integer().
setColour(#wx_ref{type=ThisT,ref=ThisRef},R,G,B)
when is_integer(R),is_integer(G),is_integer(B) ->
?CLASS(ThisT,wxBrush),
wxe_util:cast(?wxBrush_SetColour_3,
<<ThisRef:32/?UI,R:32/?UI,G:32/?UI,B:32/?UI>>).
-%% @spec (This::wxBrush(), Stipple::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushsetstipple">external documentation</a>.
+-spec setStipple(This, Stipple) -> ok when
+ This::wxBrush(), Stipple::wxBitmap:wxBitmap().
setStipple(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=StippleT,ref=StippleRef}) ->
?CLASS(ThisT,wxBrush),
?CLASS(StippleT,wxBitmap),
wxe_util:cast(?wxBrush_SetStipple,
<<ThisRef:32/?UI,StippleRef:32/?UI>>).
-%% @spec (This::wxBrush(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbrush.html#wxbrushsetstyle">external documentation</a>.
+-spec setStyle(This, Style) -> ok when
+ This::wxBrush(), Style::integer().
setStyle(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxBrush),
wxe_util:cast(?wxBrush_SetStyle,
<<ThisRef:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxBrush()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBrush()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBrush),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxBufferedDC.erl b/lib/wx/src/gen/wxBufferedDC.erl
index 6e341a8552..fd8955f4ed 100644
--- a/lib/wx/src/gen/wxBufferedDC.erl
+++ b/lib/wx/src/gen/wxBufferedDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +39,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -53,32 +53,40 @@
setMapMode/2,setPalette/2,setPen/2,setTextBackground/2,setTextForeground/2,
setUserScale/3,startDoc/2,startPage/1]).
+-export_type([wxBufferedDC/0]).
%% @hidden
parent_class(wxMemoryDC) -> true;
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxBufferedDC()
+-type wxBufferedDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcwxbuffereddc">external documentation</a>.
+-spec new() -> wxBufferedDC().
new() ->
wxe_util:construct(?wxBufferedDC_new_0,
<<>>).
-%% @spec (Dc::wxDC:wxDC()) -> wxBufferedDC()
%% @equiv new(Dc, [])
+-spec new(Dc) -> wxBufferedDC() when
+ Dc::wxDC:wxDC().
+
new(Dc)
when is_record(Dc, wx_ref) ->
new(Dc, []).
-%% @spec (Dc::wxDC:wxDC(),X::term()) -> wxBufferedDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcwxbuffereddc">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}) -> new(Dc,Area, []) </c></p>
-%% <p><c>
-%% new(Dc::wxDC:wxDC(), [Option]) -> wxBufferedDC() </c>
-%%<br /> Option = {buffer, wxBitmap:wxBitmap()} | {style, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Dc, [Option]) -> wxBufferedDC() when<br />
+%% Dc::wxDC:wxDC(),<br />
+%% Option :: {buffer, wxBitmap:wxBitmap()}<br />
+%% | {style, integer()}.<br />
+%%
+-spec new(Dc, Area) -> wxBufferedDC() when
+ Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()};
+ (Dc, [Option]) -> wxBufferedDC() when
+ Dc::wxDC:wxDC(),
+ Option :: {buffer, wxBitmap:wxBitmap()}
+ | {style, integer()}.
new(Dc,Area={AreaW,AreaH})
when is_record(Dc, wx_ref),is_integer(AreaW),is_integer(AreaH) ->
@@ -93,9 +101,10 @@ new(#wx_ref{type=DcT,ref=DcRef}, Options)
wxe_util:construct(?wxBufferedDC_new_2,
<<DcRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}, [Option]) -> wxBufferedDC()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcwxbuffereddc">external documentation</a>.
+-spec new(Dc, Area, [Option]) -> wxBufferedDC() when
+ Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()},
+ Option :: {style, integer()}.
new(#wx_ref{type=DcT,ref=DcRef},{AreaW,AreaH}, Options)
when is_integer(AreaW),is_integer(AreaH),is_list(Options) ->
?CLASS(DcT,wxDC),
@@ -105,21 +114,27 @@ new(#wx_ref{type=DcT,ref=DcRef},{AreaW,AreaH}, Options)
wxe_util:construct(?wxBufferedDC_new_3,
<<DcRef:32/?UI,AreaW:32/?UI,AreaH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxBufferedDC(), Dc::wxDC:wxDC()) -> ok
%% @equiv init(This,Dc, [])
+-spec init(This, Dc) -> ok when
+ This::wxBufferedDC(), Dc::wxDC:wxDC().
+
init(This,Dc)
when is_record(This, wx_ref),is_record(Dc, wx_ref) ->
init(This,Dc, []).
-%% @spec (This::wxBufferedDC(),Dc::wxDC:wxDC(),X::term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcinit">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% init(This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}) -> init(This,Dc,Area, []) </c></p>
-%% <p><c>
-%% init(This::wxBufferedDC(), Dc::wxDC:wxDC(), [Option]) -> ok </c>
-%%<br /> Option = {buffer, wxBitmap:wxBitmap()} | {style, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% init(This, Dc, [Option]) -> ok when<br />
+%% This::wxBufferedDC(), Dc::wxDC:wxDC(),<br />
+%% Option :: {buffer, wxBitmap:wxBitmap()}<br />
+%% | {style, integer()}.<br />
+%%
+-spec init(This, Dc, Area) -> ok when
+ This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()};
+ (This, Dc, [Option]) -> ok when
+ This::wxBufferedDC(), Dc::wxDC:wxDC(),
+ Option :: {buffer, wxBitmap:wxBitmap()}
+ | {style, integer()}.
init(This,Dc,Area={AreaW,AreaH})
when is_record(This, wx_ref),is_record(Dc, wx_ref),is_integer(AreaW),is_integer(AreaH) ->
@@ -135,9 +150,10 @@ init(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}, Options)
wxe_util:cast(?wxBufferedDC_Init_2,
<<ThisRef:32/?UI,DcRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(),H::integer()}, [Option]) -> ok
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbuffereddc.html#wxbuffereddcinit">external documentation</a>.
+-spec init(This, Dc, Area, [Option]) -> ok when
+ This::wxBufferedDC(), Dc::wxDC:wxDC(), Area::{W::integer(), H::integer()},
+ Option :: {style, integer()}.
init(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef},{AreaW,AreaH}, Options)
when is_integer(AreaW),is_integer(AreaH),is_list(Options) ->
?CLASS(ThisT,wxBufferedDC),
@@ -148,8 +164,8 @@ init(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef},{AreaW,AreaH},
wxe_util:cast(?wxBufferedDC_Init_3,
<<ThisRef:32/?UI,DcRef:32/?UI,AreaW:32/?UI,AreaH:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxBufferedDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBufferedDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBufferedDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -241,11 +257,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -259,7 +275,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxBufferedPaintDC.erl b/lib/wx/src/gen/wxBufferedPaintDC.erl
index 2712394dd8..bff61ca678 100644
--- a/lib/wx/src/gen/wxBufferedPaintDC.erl
+++ b/lib/wx/src/gen/wxBufferedPaintDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +40,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
init/2,init/3,init/4,isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,
@@ -55,27 +55,33 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxBufferedPaintDC/0]).
%% @hidden
parent_class(wxBufferedDC) -> true;
parent_class(wxMemoryDC) -> true;
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Window::wxWindow:wxWindow()) -> wxBufferedPaintDC()
+-type wxBufferedPaintDC() :: wx:wx_object().
%% @equiv new(Window, [])
+-spec new(Window) -> wxBufferedPaintDC() when
+ Window::wxWindow:wxWindow().
+
new(Window)
when is_record(Window, wx_ref) ->
new(Window, []).
-%% @spec (Window::wxWindow:wxWindow(),X::term()) -> wxBufferedPaintDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbufferedpaintdc.html#wxbufferedpaintdcwxbufferedpaintdc">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Window::wxWindow:wxWindow(), Buffer::wxBitmap:wxBitmap()) -> new(Window,Buffer, []) </c></p>
-%% <p><c>
-%% new(Window::wxWindow:wxWindow(), [Option]) -> wxBufferedPaintDC() </c>
-%%<br /> Option = {style, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Window, [Option]) -> wxBufferedPaintDC() when<br />
+%% Window::wxWindow:wxWindow(),<br />
+%% Option :: {style, integer()}.<br />
+%%
+-spec new(Window, Buffer) -> wxBufferedPaintDC() when
+ Window::wxWindow:wxWindow(), Buffer::wxBitmap:wxBitmap();
+ (Window, [Option]) -> wxBufferedPaintDC() when
+ Window::wxWindow:wxWindow(),
+ Option :: {style, integer()}.
new(Window,Buffer)
when is_record(Window, wx_ref),is_record(Buffer, wx_ref) ->
@@ -89,9 +95,10 @@ new(#wx_ref{type=WindowT,ref=WindowRef}, Options)
wxe_util:construct(?wxBufferedPaintDC_new_2,
<<WindowRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Window::wxWindow:wxWindow(), Buffer::wxBitmap:wxBitmap(), [Option]) -> wxBufferedPaintDC()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbufferedpaintdc.html#wxbufferedpaintdcwxbufferedpaintdc">external documentation</a>.
+-spec new(Window, Buffer, [Option]) -> wxBufferedPaintDC() when
+ Window::wxWindow:wxWindow(), Buffer::wxBitmap:wxBitmap(),
+ Option :: {style, integer()}.
new(#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=BufferT,ref=BufferRef}, Options)
when is_list(Options) ->
?CLASS(WindowT,wxWindow),
@@ -102,8 +109,8 @@ new(#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=BufferT,ref=BufferRef}, Opt
wxe_util:construct(?wxBufferedPaintDC_new_3,
<<WindowRef:32/?UI,BufferRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxBufferedPaintDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxBufferedPaintDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxBufferedPaintDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -202,11 +209,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -220,7 +227,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxButton.erl b/lib/wx/src/gen/wxButton.erl
index c0e21a5657..a27e5d91c2 100644
--- a/lib/wx/src/gen/wxButton.erl
+++ b/lib/wx/src/gen/wxButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +70,36 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxButton/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxButton()
+-type wxButton() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttonwxbutton">external documentation</a>.
+-spec new() -> wxButton().
new() ->
wxe_util:construct(?wxButton_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxButton()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxButton() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxButton()
-%% Option = {label, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttonwxbutton">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {label, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -104,15 +113,22 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxButton_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxButton(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxButton(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxButton(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {label, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttoncreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxButton(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {label, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxButton),
@@ -127,21 +143,23 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxButton_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec () -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttongetdefaultsize">external documentation</a>.
+-spec getDefaultSize() -> {W::integer(), H::integer()}.
getDefaultSize() ->
wxe_util:call(?wxButton_GetDefaultSize,
<<>>).
-%% @spec (This::wxButton()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttonsetdefault">external documentation</a>.
+-spec setDefault(This) -> ok when
+ This::wxButton().
setDefault(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxButton),
wxe_util:cast(?wxButton_SetDefault,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxButton(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxbutton.html#wxbuttonsetlabel">external documentation</a>.
+-spec setLabel(This, Label) -> ok when
+ This::wxButton(), Label::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
when is_list(Label) ->
?CLASS(ThisT,wxButton),
@@ -149,8 +167,8 @@ setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
wxe_util:cast(?wxButton_SetLabel,
<<ThisRef:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxButton()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxButton()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxButton),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxCalendarCtrl.erl b/lib/wx/src/gen/wxCalendarCtrl.erl
index 8ad4d5954b..01d171800b 100644
--- a/lib/wx/src/gen/wxCalendarCtrl.erl
+++ b/lib/wx/src/gen/wxCalendarCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,27 +74,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxCalendarCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxCalendarCtrl()
+-type wxCalendarCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlwxcalendarctrl">external documentation</a>.
+-spec new() -> wxCalendarCtrl().
new() ->
wxe_util:construct(?wxCalendarCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxCalendarCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxCalendarCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxCalendarCtrl()
-%% Option = {date, wx:datetime()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlwxcalendarctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxCalendarCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {date, wx:wx_datetime()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -107,15 +115,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxCalendarCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxCalendarCtrl(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxCalendarCtrl(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxCalendarCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {date, wx:datetime()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxCalendarCtrl(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {date, wx:wx_datetime()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxCalendarCtrl),
@@ -129,30 +143,35 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxCalendarCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxCalendarCtrl(), Date::wx:datetime()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlsetdate">external documentation</a>.
+-spec setDate(This, Date) -> boolean() when
+ This::wxCalendarCtrl(), Date::wx:wx_datetime().
setDate(#wx_ref{type=ThisT,ref=ThisRef},Date)
when tuple_size(Date) =:= 2 ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_SetDate,
<<ThisRef:32/?UI,(wxe_util:datetime_bin(Date)):24/binary>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:datetime()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgetdate">external documentation</a>.
+-spec getDate(This) -> wx:wx_datetime() when
+ This::wxCalendarCtrl().
getDate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetDate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl()) -> ok
%% @equiv enableYearChange(This, [])
+-spec enableYearChange(This) -> ok when
+ This::wxCalendarCtrl().
+
enableYearChange(This)
when is_record(This, wx_ref) ->
enableYearChange(This, []).
-%% @spec (This::wxCalendarCtrl(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlenableyearchange">external documentation</a>.
+-spec enableYearChange(This, [Option]) -> ok when
+ This::wxCalendarCtrl(),
+ Option :: {enable, boolean()}.
enableYearChange(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxCalendarCtrl),
@@ -162,15 +181,18 @@ enableYearChange(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxCalendarCtrl_EnableYearChange,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxCalendarCtrl()) -> ok
%% @equiv enableMonthChange(This, [])
+-spec enableMonthChange(This) -> ok when
+ This::wxCalendarCtrl().
+
enableMonthChange(This)
when is_record(This, wx_ref) ->
enableMonthChange(This, []).
-%% @spec (This::wxCalendarCtrl(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlenablemonthchange">external documentation</a>.
+-spec enableMonthChange(This, [Option]) -> ok when
+ This::wxCalendarCtrl(),
+ Option :: {enable, boolean()}.
enableMonthChange(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxCalendarCtrl),
@@ -180,15 +202,18 @@ enableMonthChange(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxCalendarCtrl_EnableMonthChange,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxCalendarCtrl()) -> ok
%% @equiv enableHolidayDisplay(This, [])
+-spec enableHolidayDisplay(This) -> ok when
+ This::wxCalendarCtrl().
+
enableHolidayDisplay(This)
when is_record(This, wx_ref) ->
enableHolidayDisplay(This, []).
-%% @spec (This::wxCalendarCtrl(), [Option]) -> ok
-%% Option = {display, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlenableholidaydisplay">external documentation</a>.
+-spec enableHolidayDisplay(This, [Option]) -> ok when
+ This::wxCalendarCtrl(),
+ Option :: {display, boolean()}.
enableHolidayDisplay(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxCalendarCtrl),
@@ -198,82 +223,93 @@ enableHolidayDisplay(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxCalendarCtrl_EnableHolidayDisplay,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxCalendarCtrl(), ColFg::wx:colour(), ColBg::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlsetheadercolours">external documentation</a>.
+-spec setHeaderColours(This, ColFg, ColBg) -> ok when
+ This::wxCalendarCtrl(), ColFg::wx:wx_colour(), ColBg::wx:wx_colour().
setHeaderColours(#wx_ref{type=ThisT,ref=ThisRef},ColFg,ColBg)
when tuple_size(ColFg) =:= 3; tuple_size(ColFg) =:= 4,tuple_size(ColBg) =:= 3; tuple_size(ColBg) =:= 4 ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:cast(?wxCalendarCtrl_SetHeaderColours,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColFg)):16/binary,(wxe_util:colour_bin(ColBg)):16/binary>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgetheadercolourfg">external documentation</a>.
+-spec getHeaderColourFg(This) -> wx:wx_colour4() when
+ This::wxCalendarCtrl().
getHeaderColourFg(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetHeaderColourFg,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgetheadercolourbg">external documentation</a>.
+-spec getHeaderColourBg(This) -> wx:wx_colour4() when
+ This::wxCalendarCtrl().
getHeaderColourBg(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetHeaderColourBg,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), ColFg::wx:colour(), ColBg::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlsethighlightcolours">external documentation</a>.
+-spec setHighlightColours(This, ColFg, ColBg) -> ok when
+ This::wxCalendarCtrl(), ColFg::wx:wx_colour(), ColBg::wx:wx_colour().
setHighlightColours(#wx_ref{type=ThisT,ref=ThisRef},ColFg,ColBg)
when tuple_size(ColFg) =:= 3; tuple_size(ColFg) =:= 4,tuple_size(ColBg) =:= 3; tuple_size(ColBg) =:= 4 ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:cast(?wxCalendarCtrl_SetHighlightColours,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColFg)):16/binary,(wxe_util:colour_bin(ColBg)):16/binary>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgethighlightcolourfg">external documentation</a>.
+-spec getHighlightColourFg(This) -> wx:wx_colour4() when
+ This::wxCalendarCtrl().
getHighlightColourFg(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetHighlightColourFg,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgethighlightcolourbg">external documentation</a>.
+-spec getHighlightColourBg(This) -> wx:wx_colour4() when
+ This::wxCalendarCtrl().
getHighlightColourBg(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetHighlightColourBg,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), ColFg::wx:colour(), ColBg::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlsetholidaycolours">external documentation</a>.
+-spec setHolidayColours(This, ColFg, ColBg) -> ok when
+ This::wxCalendarCtrl(), ColFg::wx:wx_colour(), ColBg::wx:wx_colour().
setHolidayColours(#wx_ref{type=ThisT,ref=ThisRef},ColFg,ColBg)
when tuple_size(ColFg) =:= 3; tuple_size(ColFg) =:= 4,tuple_size(ColBg) =:= 3; tuple_size(ColBg) =:= 4 ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:cast(?wxCalendarCtrl_SetHolidayColours,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColFg)):16/binary,(wxe_util:colour_bin(ColBg)):16/binary>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgetholidaycolourfg">external documentation</a>.
+-spec getHolidayColourFg(This) -> wx:wx_colour4() when
+ This::wxCalendarCtrl().
getHolidayColourFg(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetHolidayColourFg,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgetholidaycolourbg">external documentation</a>.
+-spec getHolidayColourBg(This) -> wx:wx_colour4() when
+ This::wxCalendarCtrl().
getHolidayColourBg(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetHolidayColourBg,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), Day::integer()) -> wxCalendarDateAttr:wxCalendarDateAttr()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlgetattr">external documentation</a>.
+-spec getAttr(This, Day) -> wxCalendarDateAttr:wxCalendarDateAttr() when
+ This::wxCalendarCtrl(), Day::integer().
getAttr(#wx_ref{type=ThisT,ref=ThisRef},Day)
when is_integer(Day) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_GetAttr,
<<ThisRef:32/?UI,Day:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), Day::integer(), Attr::wxCalendarDateAttr:wxCalendarDateAttr()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlsetattr">external documentation</a>.
+-spec setAttr(This, Day, Attr) -> ok when
+ This::wxCalendarCtrl(), Day::integer(), Attr::wxCalendarDateAttr:wxCalendarDateAttr().
setAttr(#wx_ref{type=ThisT,ref=ThisRef},Day,#wx_ref{type=AttrT,ref=AttrRef})
when is_integer(Day) ->
?CLASS(ThisT,wxCalendarCtrl),
@@ -281,36 +317,38 @@ setAttr(#wx_ref{type=ThisT,ref=ThisRef},Day,#wx_ref{type=AttrT,ref=AttrRef})
wxe_util:cast(?wxCalendarCtrl_SetAttr,
<<ThisRef:32/?UI,Day:32/?UI,AttrRef:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), Day::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlsetholiday">external documentation</a>.
+-spec setHoliday(This, Day) -> ok when
+ This::wxCalendarCtrl(), Day::integer().
setHoliday(#wx_ref{type=ThisT,ref=ThisRef},Day)
when is_integer(Day) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:cast(?wxCalendarCtrl_SetHoliday,
<<ThisRef:32/?UI,Day:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), Day::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlresetattr">external documentation</a>.
+-spec resetAttr(This, Day) -> ok when
+ This::wxCalendarCtrl(), Day::integer().
resetAttr(#wx_ref{type=ThisT,ref=ThisRef},Day)
when is_integer(Day) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:cast(?wxCalendarCtrl_ResetAttr,
<<ThisRef:32/?UI,Day:32/?UI>>).
-%% @spec (This::wxCalendarCtrl(), Pos::{X::integer(),Y::integer()}) -> {WxCalendarHitTestResult,Date::wx:datetime(),Wd::WeekDay}
-%% WxCalendarHitTestResult = integer()
-%% WeekDay = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarctrl.html#wxcalendarctrlhittest">external documentation</a>.
-%%<br /> WxCalendarHitTestResult is one of ?wxCAL_HITTEST_NOWHERE | ?wxCAL_HITTEST_HEADER | ?wxCAL_HITTEST_DAY | ?wxCAL_HITTEST_INCMONTH | ?wxCAL_HITTEST_DECMONTH | ?wxCAL_HITTEST_SURROUNDING_WEEK
-%%<br /> WeekDay is one of ?wxDateTime_Sun | ?wxDateTime_Mon | ?wxDateTime_Tue | ?wxDateTime_Wed | ?wxDateTime_Thu | ?wxDateTime_Fri | ?wxDateTime_Sat | ?wxDateTime_Inv_WeekDay
+%%<br /> Wd = ?wxDateTime_Sun | ?wxDateTime_Mon | ?wxDateTime_Tue | ?wxDateTime_Wed | ?wxDateTime_Thu | ?wxDateTime_Fri | ?wxDateTime_Sat | ?wxDateTime_Inv_WeekDay
+%%<br /> Res = ?wxCAL_HITTEST_NOWHERE | ?wxCAL_HITTEST_HEADER | ?wxCAL_HITTEST_DAY | ?wxCAL_HITTEST_INCMONTH | ?wxCAL_HITTEST_DECMONTH | ?wxCAL_HITTEST_SURROUNDING_WEEK
+-spec hitTest(This, Pos) -> Result when
+ Result ::{Res ::wx:wx_enum(), Date::wx:wx_datetime(), Wd::wx:wx_enum()},
+ This::wxCalendarCtrl(), Pos::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxCalendarCtrl),
wxe_util:call(?wxCalendarCtrl_HitTest,
<<ThisRef:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxCalendarCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxCalendarCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxCalendarCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxCalendarDateAttr.erl b/lib/wx/src/gen/wxCalendarDateAttr.erl
index aea8abbe54..a1891df18b 100644
--- a/lib/wx/src/gen/wxCalendarDateAttr.erl
+++ b/lib/wx/src/gen/wxCalendarDateAttr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,22 +32,27 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxCalendarDateAttr/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxCalendarDateAttr()
+-type wxCalendarDateAttr() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrwxcalendardateattr">external documentation</a>.
+-spec new() -> wxCalendarDateAttr().
new() ->
wxe_util:construct(?wxCalendarDateAttr_new_0,
<<>>).
-%% @spec (X::WxCalendarDateBorder|term()) -> wxCalendarDateAttr()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrwxcalendardateattr">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Border::WxCalendarDateBorder) -> new(Border, []) </c></p>
-%% <p><c>
-%% new(ColText::wx:colour()) -> new(ColText, []) </c></p>
+%% <br /> Also:<br />
+%% new(ColText) -> wxCalendarDateAttr() when<br />
+%% ColText::wx:wx_colour().<br />
+%%
+%%<br /> Border = ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
+-spec new(Border) -> wxCalendarDateAttr() when
+ Border::wx:wx_enum();
+ (ColText) -> wxCalendarDateAttr() when
+ ColText::wx:wx_colour().
new(Border)
when is_integer(Border) ->
@@ -57,21 +62,25 @@ new(ColText)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
new(ColText, []).
-%% @spec (X::WxCalendarDateBorder|term(),[Option]) -> wxCalendarDateAttr()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrwxcalendardateattr">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Border::WxCalendarDateBorder, [Option]) -> wxCalendarDateAttr() </c>
-%%<br /> Option = {colBorder, wx:colour()}
-%%<br /> WxCalendarDateBorder = integer()
-%%<br /> WxCalendarDateBorder is one of ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
-%% </p>
-%% <p><c>
-%% new(ColText::wx:colour(), [Option]) -> wxCalendarDateAttr() </c>
-%%<br /> Option = {colBack, wx:colour()} | {colBorder, wx:colour()} | {font, wxFont:wxFont()} | {border, WxCalendarDateBorder}
-%%<br /> WxCalendarDateBorder = integer()
-%%<br /> WxCalendarDateBorder is one of ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
-%% </p>
+%% <br /> Also:<br />
+%% new(ColText, [Option]) -> wxCalendarDateAttr() when<br />
+%% ColText::wx:wx_colour(),<br />
+%% Option :: {colBack, wx:wx_colour()}<br />
+%% | {colBorder, wx:wx_colour()}<br />
+%% | {font, wxFont:wxFont()}<br />
+%% | {border, wx:wx_enum()}.<br />
+%%
+%%<br /> Border = ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
+-spec new(Border, [Option]) -> wxCalendarDateAttr() when
+ Border::wx:wx_enum(),
+ Option :: {colBorder, wx:wx_colour()};
+ (ColText, [Option]) -> wxCalendarDateAttr() when
+ ColText::wx:wx_colour(),
+ Option :: {colBack, wx:wx_colour()}
+ | {colBorder, wx:wx_colour()}
+ | {font, wxFont:wxFont()}
+ | {border, wx:wx_enum()}.
new(Border, Options)
when is_integer(Border),is_list(Options) ->
MOpts = fun({colBorder, ColBorder}, Acc) -> [<<1:32/?UI,(wxe_util:colour_bin(ColBorder)):16/binary,0:32>>|Acc];
@@ -90,137 +99,152 @@ new(ColText, Options)
wxe_util:construct(?wxCalendarDateAttr_new_2_1,
<<(wxe_util:colour_bin(ColText)):16/binary, BinOpt/binary>>).
-%% @spec (This::wxCalendarDateAttr(), ColText::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrsettextcolour">external documentation</a>.
+-spec setTextColour(This, ColText) -> ok when
+ This::wxCalendarDateAttr(), ColText::wx:wx_colour().
setTextColour(#wx_ref{type=ThisT,ref=ThisRef},ColText)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:cast(?wxCalendarDateAttr_SetTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColText)):16/binary>>).
-%% @spec (This::wxCalendarDateAttr(), ColBack::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrsetbackgroundcolour">external documentation</a>.
+-spec setBackgroundColour(This, ColBack) -> ok when
+ This::wxCalendarDateAttr(), ColBack::wx:wx_colour().
setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},ColBack)
when tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:cast(?wxCalendarDateAttr_SetBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary>>).
-%% @spec (This::wxCalendarDateAttr(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrsetbordercolour">external documentation</a>.
+-spec setBorderColour(This, Col) -> ok when
+ This::wxCalendarDateAttr(), Col::wx:wx_colour().
setBorderColour(#wx_ref{type=ThisT,ref=ThisRef},Col)
when tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:cast(?wxCalendarDateAttr_SetBorderColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxCalendarDateAttr(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrsetfont">external documentation</a>.
+-spec setFont(This, Font) -> ok when
+ This::wxCalendarDateAttr(), Font::wxFont:wxFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxCalendarDateAttr_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr(), Border::WxCalendarDateBorder) -> ok
-%% WxCalendarDateBorder = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrsetborder">external documentation</a>.
-%%<br /> WxCalendarDateBorder is one of ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
+%%<br /> Border = ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
+-spec setBorder(This, Border) -> ok when
+ This::wxCalendarDateAttr(), Border::wx:wx_enum().
setBorder(#wx_ref{type=ThisT,ref=ThisRef},Border)
when is_integer(Border) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:cast(?wxCalendarDateAttr_SetBorder,
<<ThisRef:32/?UI,Border:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr(), Holiday::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrsetholiday">external documentation</a>.
+-spec setHoliday(This, Holiday) -> ok when
+ This::wxCalendarDateAttr(), Holiday::boolean().
setHoliday(#wx_ref{type=ThisT,ref=ThisRef},Holiday)
when is_boolean(Holiday) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:cast(?wxCalendarDateAttr_SetHoliday,
<<ThisRef:32/?UI,(wxe_util:from_bool(Holiday)):32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrhastextcolour">external documentation</a>.
+-spec hasTextColour(This) -> boolean() when
+ This::wxCalendarDateAttr().
hasTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_HasTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrhasbackgroundcolour">external documentation</a>.
+-spec hasBackgroundColour(This) -> boolean() when
+ This::wxCalendarDateAttr().
hasBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_HasBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrhasbordercolour">external documentation</a>.
+-spec hasBorderColour(This) -> boolean() when
+ This::wxCalendarDateAttr().
hasBorderColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_HasBorderColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrhasfont">external documentation</a>.
+-spec hasFont(This) -> boolean() when
+ This::wxCalendarDateAttr().
hasFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_HasFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrhasborder">external documentation</a>.
+-spec hasBorder(This) -> boolean() when
+ This::wxCalendarDateAttr().
hasBorder(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_HasBorder,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrisholiday">external documentation</a>.
+-spec isHoliday(This) -> boolean() when
+ This::wxCalendarDateAttr().
isHoliday(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_IsHoliday,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrgettextcolour">external documentation</a>.
+-spec getTextColour(This) -> wx:wx_colour4() when
+ This::wxCalendarDateAttr().
getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_GetTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrgetbackgroundcolour">external documentation</a>.
+-spec getBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxCalendarDateAttr().
getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_GetBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrgetbordercolour">external documentation</a>.
+-spec getBorderColour(This) -> wx:wx_colour4() when
+ This::wxCalendarDateAttr().
getBorderColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_GetBorderColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxCalendarDateAttr().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> WxCalendarDateBorder
-%% WxCalendarDateBorder = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendardateattr.html#wxcalendardateattrgetborder">external documentation</a>.
-%%<br /> WxCalendarDateBorder is one of ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
+%%<br /> Res = ?wxCAL_BORDER_NONE | ?wxCAL_BORDER_SQUARE | ?wxCAL_BORDER_ROUND
+-spec getBorder(This) -> wx:wx_enum() when
+ This::wxCalendarDateAttr().
getBorder(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarDateAttr),
wxe_util:call(?wxCalendarDateAttr_GetBorder,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCalendarDateAttr()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxCalendarDateAttr()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxCalendarDateAttr),
wxe_util:destroy(?wxCalendarDateAttr_destroy,Obj),
diff --git a/lib/wx/src/gen/wxCalendarEvent.erl b/lib/wx/src/gen/wxCalendarEvent.erl
index 40723711af..c062a7fa0d 100644
--- a/lib/wx/src/gen/wxCalendarEvent.erl
+++ b/lib/wx/src/gen/wxCalendarEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 +41,18 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxCalendarEvent/0]).
%% @hidden
parent_class(wxDateEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxCalendarEvent()) -> WeekDay
-%% WeekDay = integer()
+-type wxCalendarEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcalendarevent.html#wxcalendareventgetweekday">external documentation</a>.
-%%<br /> WeekDay is one of ?wxDateTime_Sun | ?wxDateTime_Mon | ?wxDateTime_Tue | ?wxDateTime_Wed | ?wxDateTime_Thu | ?wxDateTime_Fri | ?wxDateTime_Sat | ?wxDateTime_Inv_WeekDay
+%%<br /> Res = ?wxDateTime_Sun | ?wxDateTime_Mon | ?wxDateTime_Tue | ?wxDateTime_Wed | ?wxDateTime_Thu | ?wxDateTime_Fri | ?wxDateTime_Sat | ?wxDateTime_Inv_WeekDay
+-spec getWeekDay(This) -> wx:wx_enum() when
+ This::wxCalendarEvent().
getWeekDay(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCalendarEvent),
wxe_util:call(?wxCalendarEvent_GetWeekDay,
diff --git a/lib/wx/src/gen/wxCaret.erl b/lib/wx/src/gen/wxCaret.erl
index 3e1a3d544c..57db5906f3 100644
--- a/lib/wx/src/gen/wxCaret.erl
+++ b/lib/wx/src/gen/wxCaret.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,32 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxCaret/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Window::wxWindow:wxWindow(), Size::{W::integer(),H::integer()}) -> wxCaret()
+-type wxCaret() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretwxcaret">external documentation</a>.
+-spec new(Window, Size) -> wxCaret() when
+ Window::wxWindow:wxWindow(), Size::{W::integer(), H::integer()}.
new(#wx_ref{type=WindowT,ref=WindowRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(WindowT,wxWindow),
wxe_util:construct(?wxCaret_new_2,
<<WindowRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (Window::wxWindow:wxWindow(), Width::integer(), Height::integer()) -> wxCaret()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretwxcaret">external documentation</a>.
+-spec new(Window, Width, Height) -> wxCaret() when
+ Window::wxWindow:wxWindow(), Width::integer(), Height::integer().
new(#wx_ref{type=WindowT,ref=WindowRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(WindowT,wxWindow),
wxe_util:construct(?wxCaret_new_3,
<<WindowRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxCaret(), Window::wxWindow:wxWindow(), Size::{W::integer(),H::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretcreate">external documentation</a>.
+-spec create(This, Window, Size) -> boolean() when
+ This::wxCaret(), Window::wxWindow:wxWindow(), Size::{W::integer(), H::integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxCaret),
@@ -59,8 +64,9 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},{Size
wxe_util:call(?wxCaret_Create_2,
<<ThisRef:32/?UI,WindowRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxCaret(), Window::wxWindow:wxWindow(), Width::integer(), Height::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretcreate">external documentation</a>.
+-spec create(This, Window, Width, Height) -> boolean() when
+ This::wxCaret(), Window::wxWindow:wxWindow(), Width::integer(), Height::integer().
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxCaret),
@@ -68,102 +74,116 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},Width
wxe_util:call(?wxCaret_Create_3,
<<ThisRef:32/?UI,WindowRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec () -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretgetblinktime">external documentation</a>.
+-spec getBlinkTime() -> integer().
getBlinkTime() ->
wxe_util:call(?wxCaret_GetBlinkTime,
<<>>).
-%% @spec (This::wxCaret()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxCaret().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:call(?wxCaret_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretgetsize">external documentation</a>.
+-spec getSize(This) -> {W::integer(), H::integer()} when
+ This::wxCaret().
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:call(?wxCaret_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretgetwindow">external documentation</a>.
+-spec getWindow(This) -> wxWindow:wxWindow() when
+ This::wxCaret().
getWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:call(?wxCaret_GetWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcarethide">external documentation</a>.
+-spec hide(This) -> ok when
+ This::wxCaret().
hide(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:cast(?wxCaret_Hide,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxCaret().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:call(?wxCaret_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretisvisible">external documentation</a>.
+-spec isVisible(This) -> boolean() when
+ This::wxCaret().
isVisible(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCaret),
wxe_util:call(?wxCaret_IsVisible,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCaret(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretmove">external documentation</a>.
+-spec move(This, Pt) -> ok when
+ This::wxCaret(), Pt::{X::integer(), Y::integer()}.
move(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxCaret),
wxe_util:cast(?wxCaret_Move_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxCaret(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretmove">external documentation</a>.
+-spec move(This, X, Y) -> ok when
+ This::wxCaret(), X::integer(), Y::integer().
move(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxCaret),
wxe_util:cast(?wxCaret_Move_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (Milliseconds::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretsetblinktime">external documentation</a>.
+-spec setBlinkTime(Milliseconds) -> ok when
+ Milliseconds::integer().
setBlinkTime(Milliseconds)
when is_integer(Milliseconds) ->
wxe_util:cast(?wxCaret_SetBlinkTime,
<<Milliseconds:32/?UI>>).
-%% @spec (This::wxCaret(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretsetsize">external documentation</a>.
+-spec setSize(This, Size) -> ok when
+ This::wxCaret(), Size::{W::integer(), H::integer()}.
setSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxCaret),
wxe_util:cast(?wxCaret_SetSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxCaret(), Width::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretsetsize">external documentation</a>.
+-spec setSize(This, Width, Height) -> ok when
+ This::wxCaret(), Width::integer(), Height::integer().
setSize(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxCaret),
wxe_util:cast(?wxCaret_SetSize_2,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxCaret()) -> ok
%% @equiv show(This, [])
+-spec show(This) -> ok when
+ This::wxCaret().
+
show(This)
when is_record(This, wx_ref) ->
show(This, []).
-%% @spec (This::wxCaret(), [Option]) -> ok
-%% Option = {show, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcaret.html#wxcaretshow">external documentation</a>.
+-spec show(This, [Option]) -> ok when
+ This::wxCaret(),
+ Option :: {show, boolean()}.
show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxCaret),
@@ -173,8 +193,8 @@ show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxCaret_Show,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxCaret()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxCaret()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxCaret),
wxe_util:destroy(?wxCaret_destruct,Obj),
diff --git a/lib/wx/src/gen/wxCheckBox.erl b/lib/wx/src/gen/wxCheckBox.erl
index c484483379..6e30f14207 100644
--- a/lib/wx/src/gen/wxCheckBox.erl
+++ b/lib/wx/src/gen/wxCheckBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -71,27 +71,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxCheckBox/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxCheckBox()
+-type wxCheckBox() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxwxcheckbox">external documentation</a>.
+-spec new() -> wxCheckBox().
new() ->
wxe_util:construct(?wxCheckBox_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> wxCheckBox()
%% @equiv new(Parent,Id,Label, [])
+-spec new(Parent, Id, Label) -> wxCheckBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
new(Parent,Id,Label)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
new(Parent,Id,Label, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxCheckBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxwxcheckbox">external documentation</a>.
+-spec new(Parent, Id, Label, [Option]) -> wxCheckBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -105,15 +113,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
wxe_util:construct(?wxCheckBox_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxCheckBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> bool()
%% @equiv create(This,Parent,Id,Label, [])
+-spec create(This, Parent, Id, Label) -> boolean() when
+ This::wxCheckBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
create(This,Parent,Id,Label)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
create(This,Parent,Id,Label, []).
-%% @spec (This::wxCheckBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxcreate">external documentation</a>.
+-spec create(This, Parent, Id, Label, [Option]) -> boolean() when
+ This::wxCheckBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxCheckBox),
@@ -128,63 +142,68 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,La
wxe_util:call(?wxCheckBox_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxCheckBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxgetvalue">external documentation</a>.
+-spec getValue(This) -> boolean() when
+ This::wxCheckBox().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:call(?wxCheckBox_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCheckBox()) -> WxCheckBoxState
-%% WxCheckBoxState = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxget3statevalue">external documentation</a>.
-%%<br /> WxCheckBoxState is one of ?wxCHK_UNCHECKED | ?wxCHK_CHECKED | ?wxCHK_UNDETERMINED
+%%<br /> Res = ?wxCHK_UNCHECKED | ?wxCHK_CHECKED | ?wxCHK_UNDETERMINED
+-spec get3StateValue(This) -> wx:wx_enum() when
+ This::wxCheckBox().
get3StateValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:call(?wxCheckBox_Get3StateValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCheckBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxis3rdstateallowedforuser">external documentation</a>.
+-spec is3rdStateAllowedForUser(This) -> boolean() when
+ This::wxCheckBox().
is3rdStateAllowedForUser(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:call(?wxCheckBox_Is3rdStateAllowedForUser,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCheckBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxis3state">external documentation</a>.
+-spec is3State(This) -> boolean() when
+ This::wxCheckBox().
is3State(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:call(?wxCheckBox_Is3State,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCheckBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxischecked">external documentation</a>.
+-spec isChecked(This) -> boolean() when
+ This::wxCheckBox().
isChecked(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:call(?wxCheckBox_IsChecked,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCheckBox(), State::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxsetvalue">external documentation</a>.
+-spec setValue(This, State) -> ok when
+ This::wxCheckBox(), State::boolean().
setValue(#wx_ref{type=ThisT,ref=ThisRef},State)
when is_boolean(State) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:cast(?wxCheckBox_SetValue,
<<ThisRef:32/?UI,(wxe_util:from_bool(State)):32/?UI>>).
-%% @spec (This::wxCheckBox(), State::WxCheckBoxState) -> ok
-%% WxCheckBoxState = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcheckbox.html#wxcheckboxset3statevalue">external documentation</a>.
-%%<br /> WxCheckBoxState is one of ?wxCHK_UNCHECKED | ?wxCHK_CHECKED | ?wxCHK_UNDETERMINED
+%%<br /> State = ?wxCHK_UNCHECKED | ?wxCHK_CHECKED | ?wxCHK_UNDETERMINED
+-spec set3StateValue(This, State) -> ok when
+ This::wxCheckBox(), State::wx:wx_enum().
set3StateValue(#wx_ref{type=ThisT,ref=ThisRef},State)
when is_integer(State) ->
?CLASS(ThisT,wxCheckBox),
wxe_util:cast(?wxCheckBox_Set3StateValue,
<<ThisRef:32/?UI,State:32/?UI>>).
-%% @spec (This::wxCheckBox()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxCheckBox()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxCheckBox),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxCheckListBox.erl b/lib/wx/src/gen/wxCheckListBox.erl
index c692997311..382345abfa 100644
--- a/lib/wx/src/gen/wxCheckListBox.erl
+++ b/lib/wx/src/gen/wxCheckListBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -75,6 +75,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxCheckListBox/0]).
%% @hidden
parent_class(wxListBox) -> true;
parent_class(wxControlWithItems) -> true;
@@ -83,21 +84,29 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxCheckListBox()
+-type wxCheckListBox() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchecklistbox.html#wxchecklistboxwxchecklistbox">external documentation</a>.
+-spec new() -> wxCheckListBox().
new() ->
wxe_util:construct(?wxCheckListBox_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxCheckListBox()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxCheckListBox() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxCheckListBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchecklistbox.html#wxchecklistboxwxchecklistbox">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxCheckListBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {choices, [unicode:chardata()]}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -111,15 +120,18 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxCheckListBox_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxCheckListBox(), Index::integer()) -> ok
%% @equiv check(This,Index, [])
+-spec check(This, Index) -> ok when
+ This::wxCheckListBox(), Index::integer().
+
check(This,Index)
when is_record(This, wx_ref),is_integer(Index) ->
check(This,Index, []).
-%% @spec (This::wxCheckListBox(), Index::integer(), [Option]) -> ok
-%% Option = {check, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchecklistbox.html#wxchecklistboxcheck">external documentation</a>.
+-spec check(This, Index, [Option]) -> ok when
+ This::wxCheckListBox(), Index::integer(),
+ Option :: {check, boolean()}.
check(#wx_ref{type=ThisT,ref=ThisRef},Index, Options)
when is_integer(Index),is_list(Options) ->
?CLASS(ThisT,wxCheckListBox),
@@ -129,16 +141,17 @@ check(#wx_ref{type=ThisT,ref=ThisRef},Index, Options)
wxe_util:cast(?wxCheckListBox_Check,
<<ThisRef:32/?UI,Index:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxCheckListBox(), Index::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchecklistbox.html#wxchecklistboxischecked">external documentation</a>.
+-spec isChecked(This, Index) -> boolean() when
+ This::wxCheckListBox(), Index::integer().
isChecked(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxCheckListBox),
wxe_util:call(?wxCheckListBox_IsChecked,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxCheckListBox()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxCheckListBox()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxCheckListBox),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxChildFocusEvent.erl b/lib/wx/src/gen/wxChildFocusEvent.erl
index a20071cbf5..642db88c06 100644
--- a/lib/wx/src/gen/wxChildFocusEvent.erl
+++ b/lib/wx/src/gen/wxChildFocusEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxChildFocusEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxChildFocusEvent()) -> wxWindow:wxWindow()
+-type wxChildFocusEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchildfocusevent.html#wxchildfocuseventgetwindow">external documentation</a>.
+-spec getWindow(This) -> wxWindow:wxWindow() when
+ This::wxChildFocusEvent().
getWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChildFocusEvent),
wxe_util:call(?wxChildFocusEvent_GetWindow,
diff --git a/lib/wx/src/gen/wxChoice.erl b/lib/wx/src/gen/wxChoice.erl
index eaf2f0352f..92b094036e 100644
--- a/lib/wx/src/gen/wxChoice.erl
+++ b/lib/wx/src/gen/wxChoice.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxChoice/0]).
%% @hidden
parent_class(wxControlWithItems) -> true;
parent_class(wxControl) -> true;
@@ -81,21 +82,29 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxChoice()
+-type wxChoice() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicewxchoice">external documentation</a>.
+-spec new() -> wxChoice().
new() ->
wxe_util:construct(?wxChoice_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxChoice()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxChoice() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxChoice()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicewxchoice">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxChoice() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {choices, [unicode:chardata()]}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -109,15 +118,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxChoice_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Pos,Size,Choices, [])
+-spec create(This, Parent, Id, Pos, Size, Choices) -> boolean() when
+ This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()].
+
create(This,Parent,Id,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Pos,Size,Choices, []).
-%% @spec (This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
-%% Option = {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicecreate">external documentation</a>.
+-spec create(This, Parent, Id, Pos, Size, Choices, [Option]) -> boolean() when
+ This::wxChoice(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()],
+ Option :: {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,{PosX,PosY},{SizeW,SizeH},Choices, Options)
when is_integer(Id),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices),is_list(Options) ->
?CLASS(ThisT,wxChoice),
@@ -131,30 +144,35 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,{P
wxe_util:call(?wxChoice_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxChoice(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicedelete">external documentation</a>.
+-spec delete(This, N) -> ok when
+ This::wxChoice(), N::integer().
delete(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoice),
wxe_util:cast(?wxChoice_Delete,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoice()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicegetcolumns">external documentation</a>.
+-spec getColumns(This) -> integer() when
+ This::wxChoice().
getColumns(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChoice),
wxe_util:call(?wxChoice_GetColumns,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoice()) -> ok
%% @equiv setColumns(This, [])
+-spec setColumns(This) -> ok when
+ This::wxChoice().
+
setColumns(This)
when is_record(This, wx_ref) ->
setColumns(This, []).
-%% @spec (This::wxChoice(), [Option]) -> ok
-%% Option = {n, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoice.html#wxchoicesetcolumns">external documentation</a>.
+-spec setColumns(This, [Option]) -> ok when
+ This::wxChoice(),
+ Option :: {n, integer()}.
setColumns(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxChoice),
@@ -164,8 +182,8 @@ setColumns(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxChoice_SetColumns,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxChoice()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxChoice()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxChoice),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxChoicebook.erl b/lib/wx/src/gen/wxChoicebook.erl
index b724d0cad2..921e1e2882 100644
--- a/lib/wx/src/gen/wxChoicebook.erl
+++ b/lib/wx/src/gen/wxChoicebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,27 +74,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxChoicebook/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxChoicebook()
+-type wxChoicebook() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookwxchoicebook">external documentation</a>.
+-spec new() -> wxChoicebook().
new() ->
wxe_util:construct(?wxChoicebook_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxChoicebook()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxChoicebook() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxChoicebook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookwxchoicebook">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxChoicebook() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,15 +113,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxChoicebook_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxChoicebook(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv addPage(This,Page,Text, [])
+-spec addPage(This, Page, Text) -> boolean() when
+ This::wxChoicebook(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
addPage(This,Page,Text)
when is_record(This, wx_ref),is_record(Page, wx_ref),is_list(Text) ->
addPage(This,Page,Text, []).
-%% @spec (This::wxChoicebook(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookaddpage">external documentation</a>.
+-spec addPage(This, Page, Text, [Option]) -> boolean() when
+ This::wxChoicebook(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxChoicebook),
@@ -127,15 +138,18 @@ addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Op
wxe_util:call(?wxChoicebook_AddPage,
<<ThisRef:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxChoicebook()) -> ok
%% @equiv advanceSelection(This, [])
+-spec advanceSelection(This) -> ok when
+ This::wxChoicebook().
+
advanceSelection(This)
when is_record(This, wx_ref) ->
advanceSelection(This, []).
-%% @spec (This::wxChoicebook(), [Option]) -> ok
-%% Option = {forward, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookadvanceselection">external documentation</a>.
+-spec advanceSelection(This, [Option]) -> ok when
+ This::wxChoicebook(),
+ Option :: {forward, boolean()}.
advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxChoicebook),
@@ -145,23 +159,29 @@ advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxChoicebook_AdvanceSelection,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxChoicebook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList) -> ok when
+ This::wxChoicebook(), ImageList::wxImageList:wxImageList().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxChoicebook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxChoicebook_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxChoicebook(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxChoicebook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxChoicebook(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxChoicebook),
@@ -174,98 +194,114 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxChoicebook_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxChoicebook()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookdeleteallpages">external documentation</a>.
+-spec deleteAllPages(This) -> boolean() when
+ This::wxChoicebook().
deleteAllPages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_DeleteAllPages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookdeletepage">external documentation</a>.
+-spec deletePage(This, N) -> boolean() when
+ This::wxChoicebook(), N::integer().
deletePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_DeletePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookremovepage">external documentation</a>.
+-spec removePage(This, N) -> boolean() when
+ This::wxChoicebook(), N::integer().
removePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_RemovePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetcurrentpage">external documentation</a>.
+-spec getCurrentPage(This) -> wxWindow:wxWindow() when
+ This::wxChoicebook().
getCurrentPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetCurrentPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoicebook()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetimagelist">external documentation</a>.
+-spec getImageList(This) -> wxImageList:wxImageList() when
+ This::wxChoicebook().
getImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetpage">external documentation</a>.
+-spec getPage(This, N) -> wxWindow:wxWindow() when
+ This::wxChoicebook(), N::integer().
getPage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetPage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetpagecount">external documentation</a>.
+-spec getPageCount(This) -> integer() when
+ This::wxChoicebook().
getPageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetPageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetpageimage">external documentation</a>.
+-spec getPageImage(This, N) -> integer() when
+ This::wxChoicebook(), N::integer().
getPageImage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetPageImage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetpagetext">external documentation</a>.
+-spec getPageText(This, N) -> unicode:charlist() when
+ This::wxChoicebook(), N::integer().
getPageText(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetPageText,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxChoicebook().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookhittest">external documentation</a>.
+-spec hitTest(This, Pt) -> Result when
+ Result ::{Res ::integer(), Flags::integer()},
+ This::wxChoicebook(), Pt::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_HitTest,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv insertPage(This,N,Page,Text, [])
+-spec insertPage(This, N, Page, Text) -> boolean() when
+ This::wxChoicebook(), N::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
insertPage(This,N,Page,Text)
when is_record(This, wx_ref),is_integer(N),is_record(Page, wx_ref),is_list(Text) ->
insertPage(This,N,Page,Text, []).
-%% @spec (This::wxChoicebook(), N::integer(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookinsertpage">external documentation</a>.
+-spec insertPage(This, N, Page, Text, [Option]) -> boolean() when
+ This::wxChoicebook(), N::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
insertPage(#wx_ref{type=ThisT,ref=ThisRef},N,#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_integer(N),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxChoicebook),
@@ -278,32 +314,36 @@ insertPage(#wx_ref{type=ThisT,ref=ThisRef},N,#wx_ref{type=PageT,ref=PageRef},Tex
wxe_util:call(?wxChoicebook_InsertPage,
<<ThisRef:32/?UI,N:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxChoicebook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebooksetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList) -> ok when
+ This::wxChoicebook(), ImageList::wxImageList:wxImageList().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxChoicebook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxChoicebook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxChoicebook(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebooksetpagesize">external documentation</a>.
+-spec setPageSize(This, Size) -> ok when
+ This::wxChoicebook(), Size::{W::integer(), H::integer()}.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:cast(?wxChoicebook_SetPageSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer(), ImageId::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebooksetpageimage">external documentation</a>.
+-spec setPageImage(This, N, ImageId) -> boolean() when
+ This::wxChoicebook(), N::integer(), ImageId::integer().
setPageImage(#wx_ref{type=ThisT,ref=ThisRef},N,ImageId)
when is_integer(N),is_integer(ImageId) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_SetPageImage,
<<ThisRef:32/?UI,N:32/?UI,ImageId:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer(), StrText::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebooksetpagetext">external documentation</a>.
+-spec setPageText(This, N, StrText) -> boolean() when
+ This::wxChoicebook(), N::integer(), StrText::unicode:chardata().
setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
when is_integer(N),is_list(StrText) ->
?CLASS(ThisT,wxChoicebook),
@@ -311,24 +351,26 @@ setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
wxe_util:call(?wxChoicebook_SetPageText,
<<ThisRef:32/?UI,N:32/?UI,(byte_size(StrText_UC)):32/?UI,(StrText_UC)/binary, 0:(((8- ((4+byte_size(StrText_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebooksetselection">external documentation</a>.
+-spec setSelection(This, N) -> integer() when
+ This::wxChoicebook(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_SetSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxchoicebook.html#wxchoicebookchangeselection">external documentation</a>.
+-spec changeSelection(This, N) -> integer() when
+ This::wxChoicebook(), N::integer().
changeSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxChoicebook),
wxe_util:call(?wxChoicebook_ChangeSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxChoicebook()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxChoicebook()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxChoicebook),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxClientDC.erl b/lib/wx/src/gen/wxClientDC.erl
index c966fb50cc..7dfebe4068 100644
--- a/lib/wx/src/gen/wxClientDC.erl
+++ b/lib/wx/src/gen/wxClientDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +39,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -53,26 +53,29 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxClientDC/0]).
%% @hidden
parent_class(wxWindowDC) -> true;
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxClientDC()
+-type wxClientDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclientdc.html#wxclientdcwxclientdc">external documentation</a>.
+-spec new() -> wxClientDC().
new() ->
wxe_util:construct(?wxClientDC_new_0,
<<>>).
-%% @spec (Win::wxWindow:wxWindow()) -> wxClientDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclientdc.html#wxclientdcwxclientdc">external documentation</a>.
+-spec new(Win) -> wxClientDC() when
+ Win::wxWindow:wxWindow().
new(#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(WinT,wxWindow),
wxe_util:construct(?wxClientDC_new_1,
<<WinRef:32/?UI>>).
-%% @spec (This::wxClientDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxClientDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxClientDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -160,11 +163,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -178,7 +181,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxClipboard.erl b/lib/wx/src/gen/wxClipboard.erl
index 7ae27b3133..8f1d59f603 100644
--- a/lib/wx/src/gen/wxClipboard.erl
+++ b/lib/wx/src/gen/wxClipboard.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,83 +30,96 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxClipboard/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxClipboard()
+-type wxClipboard() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardwxclipboard">external documentation</a>.
+-spec new() -> wxClipboard().
new() ->
wxe_util:construct(?wxClipboard_new,
<<>>).
-%% @spec (This::wxClipboard(), Data::wxDataObject:wxDataObject()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardadddata">external documentation</a>.
+-spec addData(This, Data) -> boolean() when
+ This::wxClipboard(), Data::wxDataObject:wxDataObject().
addData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(ThisT,wxClipboard),
?CLASS(DataT,wxDataObject),
wxe_util:call(?wxClipboard_AddData,
<<ThisRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxClipboard()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxClipboard().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxClipboard),
wxe_util:cast(?wxClipboard_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxClipboard()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardclose">external documentation</a>.
+-spec close(This) -> ok when
+ This::wxClipboard().
close(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxClipboard),
wxe_util:cast(?wxClipboard_Close,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxClipboard()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardflush">external documentation</a>.
+-spec flush(This) -> boolean() when
+ This::wxClipboard().
flush(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxClipboard),
wxe_util:call(?wxClipboard_Flush,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxClipboard(), Data::wxDataObject:wxDataObject()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardgetdata">external documentation</a>.
+-spec getData(This, Data) -> boolean() when
+ This::wxClipboard(), Data::wxDataObject:wxDataObject().
getData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(ThisT,wxClipboard),
?CLASS(DataT,wxDataObject),
wxe_util:call(?wxClipboard_GetData,
<<ThisRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxClipboard()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardisopened">external documentation</a>.
+-spec isOpened(This) -> boolean() when
+ This::wxClipboard().
isOpened(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxClipboard),
wxe_util:call(?wxClipboard_IsOpened,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxClipboard()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardopen">external documentation</a>.
+-spec open(This) -> boolean() when
+ This::wxClipboard().
open(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxClipboard),
wxe_util:call(?wxClipboard_Open,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxClipboard(), Data::wxDataObject:wxDataObject()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardsetdata">external documentation</a>.
+-spec setData(This, Data) -> boolean() when
+ This::wxClipboard(), Data::wxDataObject:wxDataObject().
setData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(ThisT,wxClipboard),
?CLASS(DataT,wxDataObject),
wxe_util:call(?wxClipboard_SetData,
<<ThisRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxClipboard()) -> ok
%% @equiv usePrimarySelection(This, [])
+-spec usePrimarySelection(This) -> ok when
+ This::wxClipboard().
+
usePrimarySelection(This)
when is_record(This, wx_ref) ->
usePrimarySelection(This, []).
-%% @spec (This::wxClipboard(), [Option]) -> ok
-%% Option = {primary, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboarduseprimaryselection">external documentation</a>.
+-spec usePrimarySelection(This, [Option]) -> ok when
+ This::wxClipboard(),
+ Option :: {primary, boolean()}.
usePrimarySelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxClipboard),
@@ -116,22 +129,23 @@ usePrimarySelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxClipboard_UsePrimarySelection,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxClipboard(), Format::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardissupported">external documentation</a>.
+-spec isSupported(This, Format) -> boolean() when
+ This::wxClipboard(), Format::integer().
isSupported(#wx_ref{type=ThisT,ref=ThisRef},Format)
when is_integer(Format) ->
?CLASS(ThisT,wxClipboard),
wxe_util:call(?wxClipboard_IsSupported,
<<ThisRef:32/?UI,Format:32/?UI>>).
-%% @spec () -> wxClipboard()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxclipboard.html#wxclipboardget">external documentation</a>.
+-spec get() -> wxClipboard().
get() ->
wxe_util:call(?wxClipboard_Get,
<<>>).
-%% @spec (This::wxClipboard()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxClipboard()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxClipboard),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxCloseEvent.erl b/lib/wx/src/gen/wxCloseEvent.erl
index 706d7701de..4a682c906e 100644
--- a/lib/wx/src/gen/wxCloseEvent.erl
+++ b/lib/wx/src/gen/wxCloseEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,49 +37,58 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxCloseEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxCloseEvent()) -> bool()
+-type wxCloseEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcloseevent.html#wxcloseeventcanveto">external documentation</a>.
+-spec canVeto(This) -> boolean() when
+ This::wxCloseEvent().
canVeto(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCloseEvent),
wxe_util:call(?wxCloseEvent_CanVeto,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCloseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcloseevent.html#wxcloseeventgetloggingoff">external documentation</a>.
+-spec getLoggingOff(This) -> boolean() when
+ This::wxCloseEvent().
getLoggingOff(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCloseEvent),
wxe_util:call(?wxCloseEvent_GetLoggingOff,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCloseEvent(), CanVeto::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcloseevent.html#wxcloseeventsetcanveto">external documentation</a>.
+-spec setCanVeto(This, CanVeto) -> ok when
+ This::wxCloseEvent(), CanVeto::boolean().
setCanVeto(#wx_ref{type=ThisT,ref=ThisRef},CanVeto)
when is_boolean(CanVeto) ->
?CLASS(ThisT,wxCloseEvent),
wxe_util:cast(?wxCloseEvent_SetCanVeto,
<<ThisRef:32/?UI,(wxe_util:from_bool(CanVeto)):32/?UI>>).
-%% @spec (This::wxCloseEvent(), LogOff::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcloseevent.html#wxcloseeventsetloggingoff">external documentation</a>.
+-spec setLoggingOff(This, LogOff) -> ok when
+ This::wxCloseEvent(), LogOff::boolean().
setLoggingOff(#wx_ref{type=ThisT,ref=ThisRef},LogOff)
when is_boolean(LogOff) ->
?CLASS(ThisT,wxCloseEvent),
wxe_util:cast(?wxCloseEvent_SetLoggingOff,
<<ThisRef:32/?UI,(wxe_util:from_bool(LogOff)):32/?UI>>).
-%% @spec (This::wxCloseEvent()) -> ok
%% @equiv veto(This, [])
+-spec veto(This) -> ok when
+ This::wxCloseEvent().
+
veto(This)
when is_record(This, wx_ref) ->
veto(This, []).
-%% @spec (This::wxCloseEvent(), [Option]) -> ok
-%% Option = {veto, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcloseevent.html#wxcloseeventveto">external documentation</a>.
+-spec veto(This, [Option]) -> ok when
+ This::wxCloseEvent(),
+ Option :: {veto, boolean()}.
veto(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxCloseEvent),
diff --git a/lib/wx/src/gen/wxColourData.erl b/lib/wx/src/gen/wxColourData.erl
index dc77ea043c..289d423cb6 100644
--- a/lib/wx/src/gen/wxColourData.erl
+++ b/lib/wx/src/gen/wxColourData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,70 +30,79 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxColourData/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxColourData()
+-type wxColourData() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatawxcolourdata">external documentation</a>.
+-spec new() -> wxColourData().
new() ->
wxe_util:construct(?wxColourData_new_0,
<<>>).
-%% @spec (Data::wxColourData()) -> wxColourData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatawxcolourdata">external documentation</a>.
+-spec new(Data) -> wxColourData() when
+ Data::wxColourData().
new(#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(DataT,wxColourData),
wxe_util:construct(?wxColourData_new_1,
<<DataRef:32/?UI>>).
-%% @spec (This::wxColourData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatagetchoosefull">external documentation</a>.
+-spec getChooseFull(This) -> boolean() when
+ This::wxColourData().
getChooseFull(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxColourData),
wxe_util:call(?wxColourData_GetChooseFull,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxColourData()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatagetcolour">external documentation</a>.
+-spec getColour(This) -> wx:wx_colour4() when
+ This::wxColourData().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxColourData),
wxe_util:call(?wxColourData_GetColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxColourData(), I::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatagetcustomcolour">external documentation</a>.
+-spec getCustomColour(This, I) -> wx:wx_colour4() when
+ This::wxColourData(), I::integer().
getCustomColour(#wx_ref{type=ThisT,ref=ThisRef},I)
when is_integer(I) ->
?CLASS(ThisT,wxColourData),
wxe_util:call(?wxColourData_GetCustomColour,
<<ThisRef:32/?UI,I:32/?UI>>).
-%% @spec (This::wxColourData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatasetchoosefull">external documentation</a>.
+-spec setChooseFull(This, Flag) -> ok when
+ This::wxColourData(), Flag::boolean().
setChooseFull(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxColourData),
wxe_util:cast(?wxColourData_SetChooseFull,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxColourData(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatasetcolour">external documentation</a>.
+-spec setColour(This, Colour) -> ok when
+ This::wxColourData(), Colour::wx:wx_colour().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxColourData),
wxe_util:cast(?wxColourData_SetColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxColourData(), I::integer(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdata.html#wxcolourdatasetcustomcolour">external documentation</a>.
+-spec setCustomColour(This, I, Colour) -> ok when
+ This::wxColourData(), I::integer(), Colour::wx:wx_colour().
setCustomColour(#wx_ref{type=ThisT,ref=ThisRef},I,Colour)
when is_integer(I),tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxColourData),
wxe_util:cast(?wxColourData_SetCustomColour,
<<ThisRef:32/?UI,I:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxColourData()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxColourData()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxColourData),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxColourDialog.erl b/lib/wx/src/gen/wxColourDialog.erl
index f5677d00ff..8040112426 100644
--- a/lib/wx/src/gen/wxColourDialog.erl
+++ b/lib/wx/src/gen/wxColourDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxColourDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,21 +85,25 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxColourDialog()
+-type wxColourDialog() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdialog.html#wxcolourdialogwxcolourdialog">external documentation</a>.
+-spec new() -> wxColourDialog().
new() ->
wxe_util:construct(?wxColourDialog_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxColourDialog()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxColourDialog() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxColourDialog()
-%% Option = {data, wxColourData:wxColourData()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdialog.html#wxcolourdialogwxcolourdialog">external documentation</a>.
+-spec new(Parent, [Option]) -> wxColourDialog() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {data, wxColourData:wxColourData()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -108,15 +113,18 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxColourDialog_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxColourDialog(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxColourDialog(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxColourDialog(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {data, wxColourData:wxColourData()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdialog.html#wxcolourdialogcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxColourDialog(), Parent::wxWindow:wxWindow(),
+ Option :: {data, wxColourData:wxColourData()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxColourDialog),
@@ -127,15 +135,16 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxColourDialog_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxColourDialog()) -> wxColourData:wxColourData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourdialog.html#wxcolourdialoggetcolourdata">external documentation</a>.
+-spec getColourData(This) -> wxColourData:wxColourData() when
+ This::wxColourDialog().
getColourData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxColourDialog),
wxe_util:call(?wxColourDialog_GetColourData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxColourDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxColourDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxColourDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxColourPickerCtrl.erl b/lib/wx/src/gen/wxColourPickerCtrl.erl
index 4f0816e1fd..1ba771695f 100644
--- a/lib/wx/src/gen/wxColourPickerCtrl.erl
+++ b/lib/wx/src/gen/wxColourPickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxColourPickerCtrl/0]).
%% @hidden
parent_class(wxPickerBase) -> true;
parent_class(wxControl) -> true;
@@ -81,21 +82,29 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxColourPickerCtrl()
+-type wxColourPickerCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlwxcolourpickerctrl">external documentation</a>.
+-spec new() -> wxColourPickerCtrl().
new() ->
wxe_util:construct(?wxColourPickerCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxColourPickerCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxColourPickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxColourPickerCtrl()
-%% Option = {col, wx:colour()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlwxcolourpickerctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxColourPickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {col, wx:wx_colour()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -109,15 +118,22 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxColourPickerCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxColourPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxColourPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxColourPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {col, wx:colour()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxColourPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {col, wx:wx_colour()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxColourPickerCtrl),
@@ -132,22 +148,23 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxColourPickerCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxColourPickerCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlgetcolour">external documentation</a>.
+-spec getColour(This) -> wx:wx_colour4() when
+ This::wxColourPickerCtrl().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxColourPickerCtrl),
wxe_util:call(?wxColourPickerCtrl_GetColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxColourPickerCtrl(),X::string()|term()) -> bool()|ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerctrl.html#wxcolourpickerctrlsetcolour">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setColour(This::wxColourPickerCtrl(), Text::string()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% setColour(This::wxColourPickerCtrl(), Col::wx:colour()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setColour(This, Col) -> ok when<br />
+%% This::wxColourPickerCtrl(), Col::wx:wx_colour().<br />
+%%
+-spec setColour(This, Text) -> boolean() when
+ This::wxColourPickerCtrl(), Text::unicode:chardata();
+ (This, Col) -> ok when
+ This::wxColourPickerCtrl(), Col::wx:wx_colour().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxColourPickerCtrl),
@@ -160,8 +177,8 @@ setColour(#wx_ref{type=ThisT,ref=ThisRef},Col)
wxe_util:cast(?wxColourPickerCtrl_SetColour_1_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxColourPickerCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxColourPickerCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxColourPickerCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxColourPickerEvent.erl b/lib/wx/src/gen/wxColourPickerEvent.erl
index 9ba431b841..71a3fd3e5b 100644
--- a/lib/wx/src/gen/wxColourPickerEvent.erl
+++ b/lib/wx/src/gen/wxColourPickerEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxColourPickerEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxColourPickerEvent()) -> wx:colour()
+-type wxColourPickerEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcolourpickerevent.html#wxcolourpickereventgetcolour">external documentation</a>.
+-spec getColour(This) -> wx:wx_colour4() when
+ This::wxColourPickerEvent().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxColourPickerEvent),
wxe_util:call(?wxColourPickerEvent_GetColour,
diff --git a/lib/wx/src/gen/wxComboBox.erl b/lib/wx/src/gen/wxComboBox.erl
index 061e886734..4e6b247f67 100644
--- a/lib/wx/src/gen/wxComboBox.erl
+++ b/lib/wx/src/gen/wxComboBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +76,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxComboBox/0]).
%% @hidden
parent_class(wxControlWithItems) -> true;
parent_class(wxControl) -> true;
@@ -83,21 +84,30 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxComboBox()
+-type wxComboBox() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxwxcombobox">external documentation</a>.
+-spec new() -> wxComboBox().
new() ->
wxe_util:construct(?wxComboBox_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxComboBox()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxComboBox() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxComboBox()
-%% Option = {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxwxcombobox">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxComboBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {value, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {choices, [unicode:chardata()]}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -112,15 +122,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxComboBox_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Value,Pos,Size,Choices, [])
+-spec create(This, Parent, Id, Value, Pos, Size, Choices) -> boolean() when
+ This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::unicode:chardata(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()].
+
create(This,Parent,Id,Value,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Value),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Value,Pos,Size,Choices, []).
-%% @spec (This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
-%% Option = {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcreate">external documentation</a>.
+-spec create(This, Parent, Id, Value, Pos, Size, Choices, [Option]) -> boolean() when
+ This::wxComboBox(), Parent::wxWindow:wxWindow(), Id::integer(), Value::unicode:chardata(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()],
+ Option :: {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Value,{PosX,PosY},{SizeW,SizeH},Choices, Options)
when is_integer(Id),is_list(Value),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices),is_list(Options) ->
?CLASS(ThisT,wxComboBox),
@@ -135,92 +149,105 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Va
wxe_util:call(?wxComboBox_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((0+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxComboBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcancopy">external documentation</a>.
+-spec canCopy(This) -> boolean() when
+ This::wxComboBox().
canCopy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_CanCopy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcancut">external documentation</a>.
+-spec canCut(This) -> boolean() when
+ This::wxComboBox().
canCut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_CanCut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcanpaste">external documentation</a>.
+-spec canPaste(This) -> boolean() when
+ This::wxComboBox().
canPaste(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_CanPaste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcanredo">external documentation</a>.
+-spec canRedo(This) -> boolean() when
+ This::wxComboBox().
canRedo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_CanRedo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcanundo">external documentation</a>.
+-spec canUndo(This) -> boolean() when
+ This::wxComboBox().
canUndo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_CanUndo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcopy">external documentation</a>.
+-spec copy(This) -> ok when
+ This::wxComboBox().
copy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_Copy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxcut">external documentation</a>.
+-spec cut(This) -> ok when
+ This::wxComboBox().
cut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_Cut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxgetinsertionpoint">external documentation</a>.
+-spec getInsertionPoint(This) -> integer() when
+ This::wxComboBox().
getInsertionPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_GetInsertionPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxgetlastposition">external documentation</a>.
+-spec getLastPosition(This) -> integer() when
+ This::wxComboBox().
getLastPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_GetLastPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxgetvalue">external documentation</a>.
+-spec getValue(This) -> unicode:charlist() when
+ This::wxComboBox().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:call(?wxComboBox_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxpaste">external documentation</a>.
+-spec paste(This) -> ok when
+ This::wxComboBox().
paste(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_Paste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxredo">external documentation</a>.
+-spec redo(This) -> ok when
+ This::wxComboBox().
redo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_Redo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox(), From::integer(), To::integer(), Value::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxreplace">external documentation</a>.
+-spec replace(This, From, To, Value) -> ok when
+ This::wxComboBox(), From::integer(), To::integer(), Value::unicode:chardata().
replace(#wx_ref{type=ThisT,ref=ThisRef},From,To,Value)
when is_integer(From),is_integer(To),is_list(Value) ->
?CLASS(ThisT,wxComboBox),
@@ -228,47 +255,53 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},From,To,Value)
wxe_util:cast(?wxComboBox_Replace,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((0+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxComboBox(), From::integer(), To::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxremove">external documentation</a>.
+-spec remove(This, From, To) -> ok when
+ This::wxComboBox(), From::integer(), To::integer().
remove(#wx_ref{type=ThisT,ref=ThisRef},From,To)
when is_integer(From),is_integer(To) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_Remove,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxComboBox(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxsetinsertionpoint">external documentation</a>.
+-spec setInsertionPoint(This, Pos) -> ok when
+ This::wxComboBox(), Pos::integer().
setInsertionPoint(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_SetInsertionPoint,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxsetinsertionpointend">external documentation</a>.
+-spec setInsertionPointEnd(This) -> ok when
+ This::wxComboBox().
setInsertionPointEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_SetInsertionPointEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxsetselection">external documentation</a>.
+-spec setSelection(This, N) -> ok when
+ This::wxComboBox(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_SetSelection_1,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxComboBox(), From::integer(), To::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxsetselection">external documentation</a>.
+-spec setSelection(This, From, To) -> ok when
+ This::wxComboBox(), From::integer(), To::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},From,To)
when is_integer(From),is_integer(To) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_SetSelection_2,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxComboBox(), Value::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxsetvalue">external documentation</a>.
+-spec setValue(This, Value) -> ok when
+ This::wxComboBox(), Value::unicode:chardata().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
when is_list(Value) ->
?CLASS(ThisT,wxComboBox),
@@ -276,15 +309,16 @@ setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
wxe_util:cast(?wxComboBox_SetValue,
<<ThisRef:32/?UI,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((0+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcombobox.html#wxcomboboxundo">external documentation</a>.
+-spec undo(This) -> ok when
+ This::wxComboBox().
undo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxComboBox),
wxe_util:cast(?wxComboBox_Undo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxComboBox()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxComboBox()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxComboBox),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxCommandEvent.erl b/lib/wx/src/gen/wxCommandEvent.erl
index 57fb9cecda..a7567163cf 100644
--- a/lib/wx/src/gen/wxCommandEvent.erl
+++ b/lib/wx/src/gen/wxCommandEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,69 +38,80 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxCommandEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxCommandEvent()) -> term()
+-type wxCommandEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventgetclientobject">external documentation</a>.
+-spec getClientData(This) -> term() when
+ This::wxCommandEvent().
getClientData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_getClientData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventgetextralong">external documentation</a>.
+-spec getExtraLong(This) -> integer() when
+ This::wxCommandEvent().
getExtraLong(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_GetExtraLong,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventgetint">external documentation</a>.
+-spec getInt(This) -> integer() when
+ This::wxCommandEvent().
getInt(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_GetInt,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxCommandEvent().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventgetstring">external documentation</a>.
+-spec getString(This) -> unicode:charlist() when
+ This::wxCommandEvent().
getString(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_GetString,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventischecked">external documentation</a>.
+-spec isChecked(This) -> boolean() when
+ This::wxCommandEvent().
isChecked(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_IsChecked,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventisselection">external documentation</a>.
+-spec isSelection(This) -> boolean() when
+ This::wxCommandEvent().
isSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:call(?wxCommandEvent_IsSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCommandEvent(), I::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventsetint">external documentation</a>.
+-spec setInt(This, I) -> ok when
+ This::wxCommandEvent(), I::integer().
setInt(#wx_ref{type=ThisT,ref=ThisRef},I)
when is_integer(I) ->
?CLASS(ThisT,wxCommandEvent),
wxe_util:cast(?wxCommandEvent_SetInt,
<<ThisRef:32/?UI,I:32/?UI>>).
-%% @spec (This::wxCommandEvent(), S::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcommandevent.html#wxcommandeventsetstring">external documentation</a>.
+-spec setString(This, S) -> ok when
+ This::wxCommandEvent(), S::unicode:chardata().
setString(#wx_ref{type=ThisT,ref=ThisRef},S)
when is_list(S) ->
?CLASS(ThisT,wxCommandEvent),
diff --git a/lib/wx/src/gen/wxContextMenuEvent.erl b/lib/wx/src/gen/wxContextMenuEvent.erl
index 56ed82f37c..9312803e33 100644
--- a/lib/wx/src/gen/wxContextMenuEvent.erl
+++ b/lib/wx/src/gen/wxContextMenuEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -40,20 +40,24 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxContextMenuEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxContextMenuEvent()) -> {X::integer(),Y::integer()}
+-type wxContextMenuEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontextmenuevent.html#wxcontextmenueventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxContextMenuEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxContextMenuEvent),
wxe_util:call(?wxContextMenuEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxContextMenuEvent(), Pos::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontextmenuevent.html#wxcontextmenueventsetposition">external documentation</a>.
+-spec setPosition(This, Pos) -> ok when
+ This::wxContextMenuEvent(), Pos::{X::integer(), Y::integer()}.
setPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxContextMenuEvent),
diff --git a/lib/wx/src/gen/wxControl.erl b/lib/wx/src/gen/wxControl.erl
index e3f602e65a..f840d0c6bc 100644
--- a/lib/wx/src/gen/wxControl.erl
+++ b/lib/wx/src/gen/wxControl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 +68,24 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxControl/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxControl()) -> string()
+-type wxControl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrol.html#wxcontrolgetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxControl().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxControl),
wxe_util:call(?wxControl_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxControl(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrol.html#wxcontrolsetlabel">external documentation</a>.
+-spec setLabel(This, Label) -> ok when
+ This::wxControl(), Label::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
when is_list(Label) ->
?CLASS(ThisT,wxControl),
diff --git a/lib/wx/src/gen/wxControlWithItems.erl b/lib/wx/src/gen/wxControlWithItems.erl
index 0838b75bad..92632a1c31 100644
--- a/lib/wx/src/gen/wxControlWithItems.erl
+++ b/lib/wx/src/gen/wxControlWithItems.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,14 +72,17 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxControlWithItems/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxControlWithItems(), Item::string()) -> integer()
+-type wxControlWithItems() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsappend">external documentation</a>.
+-spec append(This, Item) -> integer() when
+ This::wxControlWithItems(), Item::unicode:chardata().
append(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_list(Item) ->
?CLASS(ThisT,wxControlWithItems),
@@ -87,8 +90,9 @@ append(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:call(?wxControlWithItems_Append_1,
<<ThisRef:32/?UI,(byte_size(Item_UC)):32/?UI,(Item_UC)/binary, 0:(((8- ((0+byte_size(Item_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxControlWithItems(), Item::string(), ClientData::term()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsappend">external documentation</a>.
+-spec append(This, Item, ClientData) -> integer() when
+ This::wxControlWithItems(), Item::unicode:chardata(), ClientData::term().
append(#wx_ref{type=ThisT,ref=ThisRef},Item,ClientData)
when is_list(Item) ->
?CLASS(ThisT,wxControlWithItems),
@@ -97,8 +101,9 @@ append(#wx_ref{type=ThisT,ref=ThisRef},Item,ClientData)
wxe_util:call(?wxControlWithItems_Append_2,
<<ThisRef:32/?UI,(byte_size(Item_UC)):32/?UI,(Item_UC)/binary, 0:(((8- ((0+byte_size(Item_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxControlWithItems(), Strings::[[string()]]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsappend">external documentation</a>.
+-spec appendStrings(This, Strings) -> ok when
+ This::wxControlWithItems(), Strings::[unicode:chardata()].
appendStrings(#wx_ref{type=ThisT,ref=ThisRef},Strings)
when is_list(Strings) ->
?CLASS(ThisT,wxControlWithItems),
@@ -107,30 +112,35 @@ appendStrings(#wx_ref{type=ThisT,ref=ThisRef},Strings)
wxe_util:cast(?wxControlWithItems_appendStrings_1,
<<ThisRef:32/?UI,(length(Strings_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Strings_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Strings_UCA])) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxControlWithItems()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxControlWithItems().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:cast(?wxControlWithItems_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxControlWithItems(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsdelete">external documentation</a>.
+-spec delete(This, N) -> ok when
+ This::wxControlWithItems(), N::integer().
delete(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:cast(?wxControlWithItems_Delete,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxControlWithItems(), S::string()) -> integer()
%% @equiv findString(This,S, [])
+-spec findString(This, S) -> integer() when
+ This::wxControlWithItems(), S::unicode:chardata().
+
findString(This,S)
when is_record(This, wx_ref),is_list(S) ->
findString(This,S, []).
-%% @spec (This::wxControlWithItems(), S::string(), [Option]) -> integer()
-%% Option = {bCase, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsfindstring">external documentation</a>.
+-spec findString(This, S, [Option]) -> integer() when
+ This::wxControlWithItems(), S::unicode:chardata(),
+ Option :: {bCase, boolean()}.
findString(#wx_ref{type=ThisT,ref=ThisRef},S, Options)
when is_list(S),is_list(Options) ->
?CLASS(ThisT,wxControlWithItems),
@@ -141,16 +151,18 @@ findString(#wx_ref{type=ThisT,ref=ThisRef},S, Options)
wxe_util:call(?wxControlWithItems_FindString,
<<ThisRef:32/?UI,(byte_size(S_UC)):32/?UI,(S_UC)/binary, 0:(((8- ((0+byte_size(S_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxControlWithItems(), N::integer()) -> term()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsgetclientobject">external documentation</a>.
+-spec getClientData(This, N) -> term() when
+ This::wxControlWithItems(), N::integer().
getClientData(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:call(?wxControlWithItems_getClientData,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxControlWithItems(), N::integer(), ClientData::term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemssetclientobject">external documentation</a>.
+-spec setClientData(This, N, ClientData) -> ok when
+ This::wxControlWithItems(), N::integer(), ClientData::term().
setClientData(#wx_ref{type=ThisT,ref=ThisRef},N,ClientData)
when is_integer(N) ->
?CLASS(ThisT,wxControlWithItems),
@@ -158,37 +170,42 @@ setClientData(#wx_ref{type=ThisT,ref=ThisRef},N,ClientData)
wxe_util:cast(?wxControlWithItems_setClientData,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxControlWithItems()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsgetcount">external documentation</a>.
+-spec getCount(This) -> integer() when
+ This::wxControlWithItems().
getCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:call(?wxControlWithItems_GetCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxControlWithItems()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxControlWithItems().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:call(?wxControlWithItems_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxControlWithItems(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsgetstring">external documentation</a>.
+-spec getString(This, N) -> unicode:charlist() when
+ This::wxControlWithItems(), N::integer().
getString(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:call(?wxControlWithItems_GetString,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxControlWithItems()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsgetstringselection">external documentation</a>.
+-spec getStringSelection(This) -> unicode:charlist() when
+ This::wxControlWithItems().
getStringSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:call(?wxControlWithItems_GetStringSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxControlWithItems(), Item::string(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsinsert">external documentation</a>.
+-spec insert(This, Item, Pos) -> integer() when
+ This::wxControlWithItems(), Item::unicode:chardata(), Pos::integer().
insert(#wx_ref{type=ThisT,ref=ThisRef},Item,Pos)
when is_list(Item),is_integer(Pos) ->
?CLASS(ThisT,wxControlWithItems),
@@ -196,8 +213,9 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Item,Pos)
wxe_util:call(?wxControlWithItems_Insert_2,
<<ThisRef:32/?UI,(byte_size(Item_UC)):32/?UI,(Item_UC)/binary, 0:(((8- ((0+byte_size(Item_UC)) band 16#7)) band 16#7))/unit:8,Pos:32/?UI>>).
-%% @spec (This::wxControlWithItems(), Item::string(), Pos::integer(), ClientData::term()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsinsert">external documentation</a>.
+-spec insert(This, Item, Pos, ClientData) -> integer() when
+ This::wxControlWithItems(), Item::unicode:chardata(), Pos::integer(), ClientData::term().
insert(#wx_ref{type=ThisT,ref=ThisRef},Item,Pos,ClientData)
when is_list(Item),is_integer(Pos) ->
?CLASS(ThisT,wxControlWithItems),
@@ -206,31 +224,35 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Item,Pos,ClientData)
wxe_util:call(?wxControlWithItems_Insert_3,
<<ThisRef:32/?UI,(byte_size(Item_UC)):32/?UI,(Item_UC)/binary, 0:(((8- ((0+byte_size(Item_UC)) band 16#7)) band 16#7))/unit:8,Pos:32/?UI>>).
-%% @spec (This::wxControlWithItems()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsisempty">external documentation</a>.
+-spec isEmpty(This) -> boolean() when
+ This::wxControlWithItems().
isEmpty(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:call(?wxControlWithItems_IsEmpty,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxControlWithItems(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemsselect">external documentation</a>.
+-spec select(This, N) -> ok when
+ This::wxControlWithItems(), N::integer().
select(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:cast(?wxControlWithItems_Select,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxControlWithItems(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemssetselection">external documentation</a>.
+-spec setSelection(This, N) -> ok when
+ This::wxControlWithItems(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxControlWithItems),
wxe_util:cast(?wxControlWithItems_SetSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxControlWithItems(), N::integer(), S::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemssetstring">external documentation</a>.
+-spec setString(This, N, S) -> ok when
+ This::wxControlWithItems(), N::integer(), S::unicode:chardata().
setString(#wx_ref{type=ThisT,ref=ThisRef},N,S)
when is_integer(N),is_list(S) ->
?CLASS(ThisT,wxControlWithItems),
@@ -238,8 +260,9 @@ setString(#wx_ref{type=ThisT,ref=ThisRef},N,S)
wxe_util:cast(?wxControlWithItems_SetString,
<<ThisRef:32/?UI,N:32/?UI,(byte_size(S_UC)):32/?UI,(S_UC)/binary, 0:(((8- ((4+byte_size(S_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxControlWithItems(), S::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcontrolwithitems.html#wxcontrolwithitemssetstringselection">external documentation</a>.
+-spec setStringSelection(This, S) -> boolean() when
+ This::wxControlWithItems(), S::unicode:chardata().
setStringSelection(#wx_ref{type=ThisT,ref=ThisRef},S)
when is_list(S) ->
?CLASS(ThisT,wxControlWithItems),
diff --git a/lib/wx/src/gen/wxCursor.erl b/lib/wx/src/gen/wxCursor.erl
index beb731fee3..b9e3a8e3f7 100644
--- a/lib/wx/src/gen/wxCursor.erl
+++ b/lib/wx/src/gen/wxCursor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,25 +34,27 @@
getSubBitmap/2,getWidth/1,loadFile/2,loadFile/3,parent_class/1,saveFile/3,
saveFile/4,setDepth/2,setHeight/2,setMask/2,setPalette/2,setWidth/2]).
+-export_type([wxCursor/0]).
%% @hidden
parent_class(wxBitmap) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxCursor()
+-type wxCursor() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcursor.html#wxcursorwxcursor">external documentation</a>.
+-spec new() -> wxCursor().
new() ->
wxe_util:construct(?wxCursor_new_0,
<<>>).
-%% @spec (X::integer()|term()) -> wxCursor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcursor.html#wxcursorwxcursor">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(CursorId::integer()) -> wxCursor() </c>
-%% </p>
-%% <p><c>
-%% new(Image::wxImage:wxImage()) -> wxCursor() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Image) -> wxCursor() when<br />
+%% Image::wxImage:wxImage().<br />
+%%
+-spec new(CursorId) -> wxCursor() when
+ CursorId::integer();
+ (Image) -> wxCursor() when
+ Image::wxImage:wxImage().
new(CursorId)
when is_integer(CursorId) ->
wxe_util:construct(?wxCursor_new_1_0,
@@ -62,15 +64,19 @@ new(#wx_ref{type=ImageT,ref=ImageRef}) ->
wxe_util:construct(?wxCursor_new_1_1,
<<ImageRef:32/?UI>>).
-%% @spec (Bits::binary(), Width::integer(), Height::integer()) -> wxCursor()
%% @equiv new(Bits,Width,Height, [])
+-spec new(Bits, Width, Height) -> wxCursor() when
+ Bits::binary(), Width::integer(), Height::integer().
+
new(Bits,Width,Height)
when is_binary(Bits),is_integer(Width),is_integer(Height) ->
new(Bits,Width,Height, []).
-%% @spec (Bits::binary(), Width::integer(), Height::integer(), [Option]) -> wxCursor()
-%% Option = {hotSpotX, integer()} | {hotSpotY, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcursor.html#wxcursorwxcursor">external documentation</a>.
+-spec new(Bits, Width, Height, [Option]) -> wxCursor() when
+ Bits::binary(), Width::integer(), Height::integer(),
+ Option :: {hotSpotX, integer()}
+ | {hotSpotY, integer()}.
new(Bits,Width,Height, Options)
when is_binary(Bits),is_integer(Width),is_integer(Height),is_list(Options) ->
wxe_util:send_bin(Bits),
@@ -81,15 +87,16 @@ new(Bits,Width,Height, Options)
wxe_util:construct(?wxCursor_new_4,
<<Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxCursor()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxcursor.html#wxcursorok">external documentation</a>.
+-spec ok(This) -> boolean() when
+ This::wxCursor().
ok(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxCursor),
wxe_util:call(?wxCursor_Ok,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxCursor()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxCursor()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxCursor),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxDC.erl b/lib/wx/src/gen/wxDC.erl
index 9bce1249f8..9f57978849 100644
--- a/lib/wx/src/gen/wxDC.erl
+++ b/lib/wx/src/gen/wxDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +32,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -49,18 +49,25 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxDC/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxDC(), DestPt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Source::wxDC(), SrcPt::{X::integer(),Y::integer()}) -> bool()
+-type wxDC() :: wx:wx_object().
%% @equiv blit(This,DestPt,Sz,Source,SrcPt, [])
+-spec blit(This, DestPt, Sz, Source, SrcPt) -> boolean() when
+ This::wxDC(), DestPt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Source::wxDC(), SrcPt::{X::integer(), Y::integer()}.
+
blit(This,DestPt={DestPtX,DestPtY},Sz={SzW,SzH},Source,SrcPt={SrcPtX,SrcPtY})
when is_record(This, wx_ref),is_integer(DestPtX),is_integer(DestPtY),is_integer(SzW),is_integer(SzH),is_record(Source, wx_ref),is_integer(SrcPtX),is_integer(SrcPtY) ->
blit(This,DestPt,Sz,Source,SrcPt, []).
-%% @spec (This::wxDC(), DestPt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Source::wxDC(), SrcPt::{X::integer(),Y::integer()}, [Option]) -> bool()
-%% Option = {rop, integer()} | {useMask, bool()} | {srcPtMask, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcblit">external documentation</a>.
+-spec blit(This, DestPt, Sz, Source, SrcPt, [Option]) -> boolean() when
+ This::wxDC(), DestPt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Source::wxDC(), SrcPt::{X::integer(), Y::integer()},
+ Option :: {rop, integer()}
+ | {useMask, boolean()}
+ | {srcPtMask, {X::integer(), Y::integer()}}.
blit(#wx_ref{type=ThisT,ref=ThisRef},{DestPtX,DestPtY},{SzW,SzH},#wx_ref{type=SourceT,ref=SourceRef},{SrcPtX,SrcPtY}, Options)
when is_integer(DestPtX),is_integer(DestPtY),is_integer(SzW),is_integer(SzH),is_integer(SrcPtX),is_integer(SrcPtY),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -73,92 +80,105 @@ blit(#wx_ref{type=ThisT,ref=ThisRef},{DestPtX,DestPtY},{SzW,SzH},#wx_ref{type=So
wxe_util:call(?wxDC_Blit,
<<ThisRef:32/?UI,DestPtX:32/?UI,DestPtY:32/?UI,SzW:32/?UI,SzH:32/?UI,SourceRef:32/?UI,SrcPtX:32/?UI,SrcPtY:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDC(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdccalcboundingbox">external documentation</a>.
+-spec calcBoundingBox(This, X, Y) -> ok when
+ This::wxDC(), X::integer(), Y::integer().
calcBoundingBox(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_CalcBoundingBox,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxDC().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdccomputescaleandorigin">external documentation</a>.
+-spec computeScaleAndOrigin(This) -> ok when
+ This::wxDC().
computeScaleAndOrigin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_ComputeScaleAndOrigin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdccrosshair">external documentation</a>.
+-spec crossHair(This, Pt) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}.
crossHair(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_CrossHair,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdestroyclippingregion">external documentation</a>.
+-spec destroyClippingRegion(This) -> ok when
+ This::wxDC().
destroyClippingRegion(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DestroyClippingRegion,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), X::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdevicetologicalx">external documentation</a>.
+-spec deviceToLogicalX(This, X) -> integer() when
+ This::wxDC(), X::integer().
deviceToLogicalX(#wx_ref{type=ThisT,ref=ThisRef},X)
when is_integer(X) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_DeviceToLogicalX,
<<ThisRef:32/?UI,X:32/?UI>>).
-%% @spec (This::wxDC(), X::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdevicetologicalxrel">external documentation</a>.
+-spec deviceToLogicalXRel(This, X) -> integer() when
+ This::wxDC(), X::integer().
deviceToLogicalXRel(#wx_ref{type=ThisT,ref=ThisRef},X)
when is_integer(X) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_DeviceToLogicalXRel,
<<ThisRef:32/?UI,X:32/?UI>>).
-%% @spec (This::wxDC(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdevicetologicaly">external documentation</a>.
+-spec deviceToLogicalY(This, Y) -> integer() when
+ This::wxDC(), Y::integer().
deviceToLogicalY(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_DeviceToLogicalY,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdevicetologicalyrel">external documentation</a>.
+-spec deviceToLogicalYRel(This, Y) -> integer() when
+ This::wxDC(), Y::integer().
deviceToLogicalYRel(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_DeviceToLogicalYRel,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC(), Pt1::{X::integer(),Y::integer()}, Pt2::{X::integer(),Y::integer()}, Centre::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawarc">external documentation</a>.
+-spec drawArc(This, Pt1, Pt2, Centre) -> ok when
+ This::wxDC(), Pt1::{X::integer(), Y::integer()}, Pt2::{X::integer(), Y::integer()}, Centre::{X::integer(), Y::integer()}.
drawArc(#wx_ref{type=ThisT,ref=ThisRef},{Pt1X,Pt1Y},{Pt2X,Pt2Y},{CentreX,CentreY})
when is_integer(Pt1X),is_integer(Pt1Y),is_integer(Pt2X),is_integer(Pt2Y),is_integer(CentreX),is_integer(CentreY) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawArc,
<<ThisRef:32/?UI,Pt1X:32/?UI,Pt1Y:32/?UI,Pt2X:32/?UI,Pt2Y:32/?UI,CentreX:32/?UI,CentreY:32/?UI>>).
-%% @spec (This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(),Y::integer()}) -> ok
%% @equiv drawBitmap(This,Bmp,Pt, [])
+-spec drawBitmap(This, Bmp, Pt) -> ok when
+ This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(), Y::integer()}.
+
drawBitmap(This,Bmp,Pt={PtX,PtY})
when is_record(This, wx_ref),is_record(Bmp, wx_ref),is_integer(PtX),is_integer(PtY) ->
drawBitmap(This,Bmp,Pt, []).
-%% @spec (This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(),Y::integer()}, [Option]) -> ok
-%% Option = {useMask, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawbitmap">external documentation</a>.
+-spec drawBitmap(This, Bmp, Pt, [Option]) -> ok when
+ This::wxDC(), Bmp::wxBitmap:wxBitmap(), Pt::{X::integer(), Y::integer()},
+ Option :: {useMask, boolean()}.
drawBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},{PtX,PtY}, Options)
when is_integer(PtX),is_integer(PtY),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -169,48 +189,54 @@ drawBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},{PtX,Pt
wxe_util:cast(?wxDC_DrawBitmap,
<<ThisRef:32/?UI,BmpRef:32/?UI,PtX:32/?UI,PtY:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawcheckmark">external documentation</a>.
+-spec drawCheckMark(This, Rect) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
drawCheckMark(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawCheckMark,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Radius::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawcircle">external documentation</a>.
+-spec drawCircle(This, Pt, Radius) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Radius::integer().
drawCircle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Radius)
when is_integer(PtX),is_integer(PtY),is_integer(Radius) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawCircle,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,Radius:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawellipse">external documentation</a>.
+-spec drawEllipse(This, Rect) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawEllipse_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawellipse">external documentation</a>.
+-spec drawEllipse(This, Pt, Sz) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}.
drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawEllipse_2,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Sa::float(), Ea::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawellipticarc">external documentation</a>.
+-spec drawEllipticArc(This, Pt, Sz, Sa, Ea) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Sa::number(), Ea::number().
drawEllipticArc(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH},Sa,Ea)
- when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH),is_float(Sa),is_float(Ea) ->
+ when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH),is_number(Sa),is_number(Ea) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawEllipticArc,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI,0:32,Sa:64/?F,Ea:64/?F>>).
-%% @spec (This::wxDC(), Icon::wxIcon:wxIcon(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawicon">external documentation</a>.
+-spec drawIcon(This, Icon, Pt) -> ok when
+ This::wxDC(), Icon::wxIcon:wxIcon(), Pt::{X::integer(), Y::integer()}.
drawIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxDC),
@@ -218,15 +244,19 @@ drawIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef},{PtX,Pt
wxe_util:cast(?wxDC_DrawIcon,
<<ThisRef:32/?UI,IconRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC(), Text::string(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @equiv drawLabel(This,Text,Rect, [])
+-spec drawLabel(This, Text, Rect) -> ok when
+ This::wxDC(), Text::unicode:chardata(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
+
drawLabel(This,Text,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_list(Text),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
drawLabel(This,Text,Rect, []).
-%% @spec (This::wxDC(), Text::string(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> ok
-%% Option = {alignment, integer()} | {indexAccel, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawlabel">external documentation</a>.
+-spec drawLabel(This, Text, Rect, [Option]) -> ok when
+ This::wxDC(), Text::unicode:chardata(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()},
+ Option :: {alignment, integer()}
+ | {indexAccel, integer()}.
drawLabel(#wx_ref{type=ThisT,ref=ThisRef},Text,{RectX,RectY,RectW,RectH}, Options)
when is_list(Text),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -238,23 +268,28 @@ drawLabel(#wx_ref{type=ThisT,ref=ThisRef},Text,{RectX,RectY,RectW,RectH}, Option
wxe_util:cast(?wxDC_DrawLabel,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDC(), Pt1::{X::integer(),Y::integer()}, Pt2::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawline">external documentation</a>.
+-spec drawLine(This, Pt1, Pt2) -> ok when
+ This::wxDC(), Pt1::{X::integer(), Y::integer()}, Pt2::{X::integer(), Y::integer()}.
drawLine(#wx_ref{type=ThisT,ref=ThisRef},{Pt1X,Pt1Y},{Pt2X,Pt2Y})
when is_integer(Pt1X),is_integer(Pt1Y),is_integer(Pt2X),is_integer(Pt2Y) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawLine,
<<ThisRef:32/?UI,Pt1X:32/?UI,Pt1Y:32/?UI,Pt2X:32/?UI,Pt2Y:32/?UI>>).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}]) -> ok
%% @equiv drawLines(This,Points, [])
+-spec drawLines(This, Points) -> ok when
+ This::wxDC(), Points::[{X::integer(), Y::integer()}].
+
drawLines(This,Points)
when is_record(This, wx_ref),is_list(Points) ->
drawLines(This,Points, []).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}], [Option]) -> ok
-%% Option = {xoffset, integer()} | {yoffset, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawlines">external documentation</a>.
+-spec drawLines(This, Points, [Option]) -> ok when
+ This::wxDC(), Points::[{X::integer(), Y::integer()}],
+ Option :: {xoffset, integer()}
+ | {yoffset, integer()}.
drawLines(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
when is_list(Points),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -266,15 +301,20 @@ drawLines(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
<<ThisRef:32/?UI,(length(Points)):32/?UI,
(<< <<X:32/?I,Y:32/?I>> || {X,Y} <- Points>>)/binary, BinOpt/binary>>).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}]) -> ok
%% @equiv drawPolygon(This,Points, [])
+-spec drawPolygon(This, Points) -> ok when
+ This::wxDC(), Points::[{X::integer(), Y::integer()}].
+
drawPolygon(This,Points)
when is_record(This, wx_ref),is_list(Points) ->
drawPolygon(This,Points, []).
-%% @spec (This::wxDC(), Points::[{X::integer(),Y::integer()}], [Option]) -> ok
-%% Option = {xoffset, integer()} | {yoffset, integer()} | {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawpolygon">external documentation</a>.
+-spec drawPolygon(This, Points, [Option]) -> ok when
+ This::wxDC(), Points::[{X::integer(), Y::integer()}],
+ Option :: {xoffset, integer()}
+ | {yoffset, integer()}
+ | {fillStyle, integer()}.
drawPolygon(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
when is_list(Points),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -287,57 +327,64 @@ drawPolygon(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
<<ThisRef:32/?UI,(length(Points)):32/?UI,
(<< <<X:32/?I,Y:32/?I>> || {X,Y} <- Points>>)/binary, BinOpt/binary>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawpoint">external documentation</a>.
+-spec drawPoint(This, Pt) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}.
drawPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawPoint,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawrectangle">external documentation</a>.
+-spec drawRectangle(This, Rect) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawRectangle_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawrectangle">external documentation</a>.
+-spec drawRectangle(This, Pt, Sz) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}.
drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawRectangle_2,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxDC(), Text::string(), Pt::{X::integer(),Y::integer()}, Angle::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawrotatedtext">external documentation</a>.
+-spec drawRotatedText(This, Text, Pt, Angle) -> ok when
+ This::wxDC(), Text::unicode:chardata(), Pt::{X::integer(), Y::integer()}, Angle::number().
drawRotatedText(#wx_ref{type=ThisT,ref=ThisRef},Text,{PtX,PtY},Angle)
- when is_list(Text),is_integer(PtX),is_integer(PtY),is_float(Angle) ->
+ when is_list(Text),is_integer(PtX),is_integer(PtY),is_number(Angle) ->
?CLASS(ThisT,wxDC),
Text_UC = unicode:characters_to_binary([Text,0]),
wxe_util:cast(?wxDC_DrawRotatedText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,PtX:32/?UI,PtY:32/?UI,Angle:64/?F>>).
-%% @spec (This::wxDC(), R::{X::integer(),Y::integer(),W::integer(),H::integer()}, Radius::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawroundedrectangle">external documentation</a>.
+-spec drawRoundedRectangle(This, R, Radius) -> ok when
+ This::wxDC(), R::{X::integer(), Y::integer(), W::integer(), H::integer()}, Radius::number().
drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},{RX,RY,RW,RH},Radius)
- when is_integer(RX),is_integer(RY),is_integer(RW),is_integer(RH),is_float(Radius) ->
+ when is_integer(RX),is_integer(RY),is_integer(RW),is_integer(RH),is_number(Radius) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawRoundedRectangle_2,
<<ThisRef:32/?UI,RX:32/?UI,RY:32/?UI,RW:32/?UI,RH:32/?UI,0:32,Radius:64/?F>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}, Radius::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawroundedrectangle">external documentation</a>.
+-spec drawRoundedRectangle(This, Pt, Sz, Radius) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}, Radius::number().
drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH},Radius)
- when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH),is_float(Radius) ->
+ when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH),is_number(Radius) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_DrawRoundedRectangle_3,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI,0:32,Radius:64/?F>>).
-%% @spec (This::wxDC(), Text::string(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcdrawtext">external documentation</a>.
+-spec drawText(This, Text, Pt) -> ok when
+ This::wxDC(), Text::unicode:chardata(), Pt::{X::integer(), Y::integer()}.
drawText(#wx_ref{type=ThisT,ref=ThisRef},Text,{PtX,PtY})
when is_list(Text),is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxDC),
@@ -345,29 +392,34 @@ drawText(#wx_ref{type=ThisT,ref=ThisRef},Text,{PtX,PtY})
wxe_util:cast(?wxDC_DrawText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcenddoc">external documentation</a>.
+-spec endDoc(This) -> ok when
+ This::wxDC().
endDoc(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_EndDoc,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcendpage">external documentation</a>.
+-spec endPage(This) -> ok when
+ This::wxDC().
endPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_EndPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Col::wx:colour()) -> bool()
%% @equiv floodFill(This,Pt,Col, [])
+-spec floodFill(This, Pt, Col) -> boolean() when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Col::wx:wx_colour().
+
floodFill(This,Pt={PtX,PtY},Col)
when is_record(This, wx_ref),is_integer(PtX),is_integer(PtY),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
floodFill(This,Pt,Col, []).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Col::wx:colour(), [Option]) -> bool()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcfloodfill">external documentation</a>.
+-spec floodFill(This, Pt, Col, [Option]) -> boolean() when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Col::wx:wx_colour(),
+ Option :: {style, integer()}.
floodFill(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Col, Options)
when is_integer(PtX),is_integer(PtY),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4,is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -377,81 +429,91 @@ floodFill(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Col, Options)
wxe_util:call(?wxDC_FloodFill,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,(wxe_util:colour_bin(Col)):16/binary, 0:32,BinOpt/binary>>).
-%% @spec (This::wxDC()) -> wxBrush:wxBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetbackground">external documentation</a>.
+-spec getBackground(This) -> wxBrush:wxBrush() when
+ This::wxDC().
getBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetbackgroundmode">external documentation</a>.
+-spec getBackgroundMode(This) -> integer() when
+ This::wxDC().
getBackgroundMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetBackgroundMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> wxBrush:wxBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetbrush">external documentation</a>.
+-spec getBrush(This) -> wxBrush:wxBrush() when
+ This::wxDC().
getBrush(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetBrush,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetcharheight">external documentation</a>.
+-spec getCharHeight(This) -> integer() when
+ This::wxDC().
getCharHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetCharHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetcharwidth">external documentation</a>.
+-spec getCharWidth(This) -> integer() when
+ This::wxDC().
getCharWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetCharWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetclippingbox">external documentation</a>.
-getClippingBox(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
- when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
+-spec getClippingBox(This) -> Result when
+ Result ::{X::integer(), Y::integer(), W::integer(), H::integer()},
+ This::wxDC().
+getClippingBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
- wxe_util:cast(?wxDC_GetClippingBox,
- <<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
+ wxe_util:call(?wxDC_GetClippingBox,
+ <<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxDC().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> WxLayoutDirection
-%% WxLayoutDirection = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetlayoutdirection">external documentation</a>.
-%%<br /> WxLayoutDirection is one of ?wxLayout_Default | ?wxLayout_LeftToRight | ?wxLayout_RightToLeft
+%%<br /> Res = ?wxLayout_Default | ?wxLayout_LeftToRight | ?wxLayout_RightToLeft
+-spec getLayoutDirection(This) -> wx:wx_enum() when
+ This::wxDC().
getLayoutDirection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetLayoutDirection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetlogicalfunction">external documentation</a>.
+-spec getLogicalFunction(This) -> integer() when
+ This::wxDC().
getLogicalFunction(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetLogicalFunction,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetmapmode">external documentation</a>.
+-spec getMapMode(This) -> integer() when
+ This::wxDC().
getMapMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetMapMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), String::string()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetmultilinetextextent">external documentation</a>.
+-spec getMultiLineTextExtent(This, String) -> {W::integer(), H::integer()} when
+ This::wxDC(), String::unicode:chardata().
getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
when is_list(String) ->
?CLASS(ThisT,wxDC),
@@ -459,9 +521,10 @@ getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
wxe_util:call(?wxDC_GetMultiLineTextExtent_1,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDC(), String::string(), [Option]) -> {Width::integer(),Height::integer(),HeightLine::integer()}
-%% Option = {font, wxFont:wxFont()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetmultilinetextextent">external documentation</a>.
+-spec getMultiLineTextExtent(This, String, [Option]) -> {Width::integer(), Height::integer(), HeightLine::integer()} when
+ This::wxDC(), String::unicode:chardata(),
+ Option :: {font, wxFont:wxFont()}.
getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
when is_list(String),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -472,61 +535,70 @@ getMultiLineTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
wxe_util:call(?wxDC_GetMultiLineTextExtent_4,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxDC(), Text::string(), Widths::[integer()]) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetpartialtextextents">external documentation</a>.
-getPartialTextExtents(#wx_ref{type=ThisT,ref=ThisRef},Text,Widths)
- when is_list(Text),is_list(Widths) ->
+-spec getPartialTextExtents(This, Text) -> Result when
+ Result ::{Res ::boolean(), Widths::[integer()]},
+ This::wxDC(), Text::unicode:chardata().
+getPartialTextExtents(#wx_ref{type=ThisT,ref=ThisRef},Text)
+ when is_list(Text) ->
?CLASS(ThisT,wxDC),
Text_UC = unicode:characters_to_binary([Text,0]),
wxe_util:call(?wxDC_GetPartialTextExtents,
- <<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,(length(Widths)):32/?UI,
- (<< <<C:32/?I>> || C <- Widths>>)/binary, 0:(((1+length(Widths)) rem 2)*32)>>).
+ <<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDC()) -> wxPen:wxPen()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetpen">external documentation</a>.
+-spec getPen(This) -> wxPen:wxPen() when
+ This::wxDC().
getPen(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetPen,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Col::wx:colour()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetpixel">external documentation</a>.
-getPixel(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},Col)
- when is_integer(PtX),is_integer(PtY),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
+-spec getPixel(This, Pt) -> Result when
+ Result ::{Res ::boolean(), Col::wx:wx_colour4()},
+ This::wxDC(), Pt::{X::integer(), Y::integer()}.
+getPixel(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
+ when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetPixel,
- <<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
+ <<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxDC()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetppi">external documentation</a>.
+-spec getPPI(This) -> {W::integer(), H::integer()} when
+ This::wxDC().
getPPI(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetPPI,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetsize">external documentation</a>.
+-spec getSize(This) -> {W::integer(), H::integer()} when
+ This::wxDC().
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetsizemm">external documentation</a>.
+-spec getSizeMM(This) -> {W::integer(), H::integer()} when
+ This::wxDC().
getSizeMM(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetSizeMM,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgettextbackground">external documentation</a>.
+-spec getTextBackground(This) -> wx:wx_colour4() when
+ This::wxDC().
getTextBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetTextBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), String::string()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgettextextent">external documentation</a>.
+-spec getTextExtent(This, String) -> {W::integer(), H::integer()} when
+ This::wxDC(), String::unicode:chardata().
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
when is_list(String) ->
?CLASS(ThisT,wxDC),
@@ -534,9 +606,11 @@ getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String)
wxe_util:call(?wxDC_GetTextExtent_1,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDC(), String::string(), [Option]) -> {X::integer(),Y::integer(),Descent::integer(),ExternalLeading::integer()}
-%% Option = {theFont, wxFont:wxFont()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgettextextent">external documentation</a>.
+-spec getTextExtent(This, String, [Option]) -> Result when
+ Result :: {X::integer(), Y::integer(), Descent::integer(), ExternalLeading::integer()},
+ This::wxDC(), String::unicode:chardata(),
+ Option :: {theFont, wxFont:wxFont()}.
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
when is_list(String),is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -547,47 +621,53 @@ getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
wxe_util:call(?wxDC_GetTextExtent_4,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxDC()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgettextforeground">external documentation</a>.
+-spec getTextForeground(This) -> wx:wx_colour4() when
+ This::wxDC().
getTextForeground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetTextForeground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> {X::float(),Y::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgetuserscale">external documentation</a>.
+-spec getUserScale(This) -> {X::number(), Y::number()} when
+ This::wxDC().
getUserScale(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_GetUserScale,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgradientfillconcentric">external documentation</a>.
+-spec gradientFillConcentric(This, Rect, InitialColour, DestColour) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:wx_colour(), DestColour::wx:wx_colour().
gradientFillConcentric(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},InitialColour,DestColour)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4 ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_GradientFillConcentric_3,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,(wxe_util:colour_bin(InitialColour)):16/binary,(wxe_util:colour_bin(DestColour)):16/binary>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour(), CircleCenter::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgradientfillconcentric">external documentation</a>.
+-spec gradientFillConcentric(This, Rect, InitialColour, DestColour, CircleCenter) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:wx_colour(), DestColour::wx:wx_colour(), CircleCenter::{X::integer(), Y::integer()}.
gradientFillConcentric(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},InitialColour,DestColour,{CircleCenterX,CircleCenterY})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4,is_integer(CircleCenterX),is_integer(CircleCenterY) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_GradientFillConcentric_4,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,(wxe_util:colour_bin(InitialColour)):16/binary,(wxe_util:colour_bin(DestColour)):16/binary,CircleCenterX:32/?UI,CircleCenterY:32/?UI>>).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour()) -> ok
%% @equiv gradientFillLinear(This,Rect,InitialColour,DestColour, [])
+-spec gradientFillLinear(This, Rect, InitialColour, DestColour) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:wx_colour(), DestColour::wx:wx_colour().
+
gradientFillLinear(This,Rect={RectX,RectY,RectW,RectH},InitialColour,DestColour)
when is_record(This, wx_ref),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4 ->
gradientFillLinear(This,Rect,InitialColour,DestColour, []).
-%% @spec (This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, InitialColour::wx:colour(), DestColour::wx:colour(), [Option]) -> ok
-%% Option = {nDirection, WxDirection}
-%% WxDirection = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcgradientfilllinear">external documentation</a>.
-%%<br /> WxDirection is one of ?wxLEFT | ?wxRIGHT | ?wxUP | ?wxDOWN | ?wxTOP | ?wxBOTTOM | ?wxNORTH | ?wxSOUTH | ?wxWEST | ?wxEAST | ?wxALL
+%%<br /> NDirection = ?wxLEFT | ?wxRIGHT | ?wxUP | ?wxDOWN | ?wxTOP | ?wxBOTTOM | ?wxNORTH | ?wxSOUTH | ?wxWEST | ?wxEAST | ?wxALL
+-spec gradientFillLinear(This, Rect, InitialColour, DestColour, [Option]) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, InitialColour::wx:wx_colour(), DestColour::wx:wx_colour(),
+ Option :: {nDirection, wx:wx_enum()}.
gradientFillLinear(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},InitialColour,DestColour, Options)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),tuple_size(InitialColour) =:= 3; tuple_size(InitialColour) =:= 4,tuple_size(DestColour) =:= 3; tuple_size(DestColour) =:= 4,is_list(Options) ->
?CLASS(ThisT,wxDC),
@@ -597,121 +677,135 @@ gradientFillLinear(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},Ini
wxe_util:cast(?wxDC_GradientFillLinear,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,(wxe_util:colour_bin(InitialColour)):16/binary,(wxe_util:colour_bin(DestColour)):16/binary, 0:32,BinOpt/binary>>).
-%% @spec (This::wxDC(), X::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdclogicaltodevicex">external documentation</a>.
+-spec logicalToDeviceX(This, X) -> integer() when
+ This::wxDC(), X::integer().
logicalToDeviceX(#wx_ref{type=ThisT,ref=ThisRef},X)
when is_integer(X) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_LogicalToDeviceX,
<<ThisRef:32/?UI,X:32/?UI>>).
-%% @spec (This::wxDC(), X::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdclogicaltodevicexrel">external documentation</a>.
+-spec logicalToDeviceXRel(This, X) -> integer() when
+ This::wxDC(), X::integer().
logicalToDeviceXRel(#wx_ref{type=ThisT,ref=ThisRef},X)
when is_integer(X) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_LogicalToDeviceXRel,
<<ThisRef:32/?UI,X:32/?UI>>).
-%% @spec (This::wxDC(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdclogicaltodevicey">external documentation</a>.
+-spec logicalToDeviceY(This, Y) -> integer() when
+ This::wxDC(), Y::integer().
logicalToDeviceY(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_LogicalToDeviceY,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdclogicaltodeviceyrel">external documentation</a>.
+-spec logicalToDeviceYRel(This, Y) -> integer() when
+ This::wxDC(), Y::integer().
logicalToDeviceYRel(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_LogicalToDeviceYRel,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcmaxx">external documentation</a>.
+-spec maxX(This) -> integer() when
+ This::wxDC().
maxX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_MaxX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcmaxy">external documentation</a>.
+-spec maxY(This) -> integer() when
+ This::wxDC().
maxY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_MaxY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcminx">external documentation</a>.
+-spec minX(This) -> integer() when
+ This::wxDC().
minX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_MinX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcminy">external documentation</a>.
+-spec minY(This) -> integer() when
+ This::wxDC().
minY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_MinY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxDC().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:call(?wxDC_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcresetboundingbox">external documentation</a>.
+-spec resetBoundingBox(This) -> ok when
+ This::wxDC().
resetBoundingBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_ResetBoundingBox,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDC(), XLeftRight::bool(), YBottomUp::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetaxisorientation">external documentation</a>.
+-spec setAxisOrientation(This, XLeftRight, YBottomUp) -> ok when
+ This::wxDC(), XLeftRight::boolean(), YBottomUp::boolean().
setAxisOrientation(#wx_ref{type=ThisT,ref=ThisRef},XLeftRight,YBottomUp)
when is_boolean(XLeftRight),is_boolean(YBottomUp) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetAxisOrientation,
<<ThisRef:32/?UI,(wxe_util:from_bool(XLeftRight)):32/?UI,(wxe_util:from_bool(YBottomUp)):32/?UI>>).
-%% @spec (This::wxDC(), Brush::wxBrush:wxBrush()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetbackground">external documentation</a>.
+-spec setBackground(This, Brush) -> ok when
+ This::wxDC(), Brush::wxBrush:wxBrush().
setBackground(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
?CLASS(ThisT,wxDC),
?CLASS(BrushT,wxBrush),
wxe_util:cast(?wxDC_SetBackground,
<<ThisRef:32/?UI,BrushRef:32/?UI>>).
-%% @spec (This::wxDC(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetbackgroundmode">external documentation</a>.
+-spec setBackgroundMode(This, Mode) -> ok when
+ This::wxDC(), Mode::integer().
setBackgroundMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetBackgroundMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxDC(), Brush::wxBrush:wxBrush()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetbrush">external documentation</a>.
+-spec setBrush(This, Brush) -> ok when
+ This::wxDC(), Brush::wxBrush:wxBrush().
setBrush(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
?CLASS(ThisT,wxDC),
?CLASS(BrushT,wxBrush),
wxe_util:cast(?wxDC_SetBrush,
<<ThisRef:32/?UI,BrushRef:32/?UI>>).
-%% @spec (This::wxDC(),X::term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetclippingregion">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setClippingRegion(This::wxDC(), Region::wxRegion:wxRegion()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setClippingRegion(This::wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setClippingRegion(This, Rect) -> ok when<br />
+%% This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec setClippingRegion(This, Region) -> ok when
+ This::wxDC(), Region::wxRegion:wxRegion();
+ (This, Rect) -> ok when
+ This::wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
setClippingRegion(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxDC),
?CLASS(RegionT,wxRegion),
@@ -723,98 +817,109 @@ setClippingRegion(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:cast(?wxDC_SetClippingRegion_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxDC(), Pt::{X::integer(),Y::integer()}, Sz::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetclippingregion">external documentation</a>.
+-spec setClippingRegion(This, Pt, Sz) -> ok when
+ This::wxDC(), Pt::{X::integer(), Y::integer()}, Sz::{W::integer(), H::integer()}.
setClippingRegion(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY},{SzW,SzH})
when is_integer(PtX),is_integer(PtY),is_integer(SzW),is_integer(SzH) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetClippingRegion_2,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxDC(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetdeviceorigin">external documentation</a>.
+-spec setDeviceOrigin(This, X, Y) -> ok when
+ This::wxDC(), X::integer(), Y::integer().
setDeviceOrigin(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetDeviceOrigin,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxDC(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetfont">external documentation</a>.
+-spec setFont(This, Font) -> ok when
+ This::wxDC(), Font::wxFont:wxFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxDC),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxDC_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxDC(), Dir::WxLayoutDirection) -> ok
-%% WxLayoutDirection = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetlayoutdirection">external documentation</a>.
-%%<br /> WxLayoutDirection is one of ?wxLayout_Default | ?wxLayout_LeftToRight | ?wxLayout_RightToLeft
+%%<br /> Dir = ?wxLayout_Default | ?wxLayout_LeftToRight | ?wxLayout_RightToLeft
+-spec setLayoutDirection(This, Dir) -> ok when
+ This::wxDC(), Dir::wx:wx_enum().
setLayoutDirection(#wx_ref{type=ThisT,ref=ThisRef},Dir)
when is_integer(Dir) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetLayoutDirection,
<<ThisRef:32/?UI,Dir:32/?UI>>).
-%% @spec (This::wxDC(), Function::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetlogicalfunction">external documentation</a>.
+-spec setLogicalFunction(This, Function) -> ok when
+ This::wxDC(), Function::integer().
setLogicalFunction(#wx_ref{type=ThisT,ref=ThisRef},Function)
when is_integer(Function) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetLogicalFunction,
<<ThisRef:32/?UI,Function:32/?UI>>).
-%% @spec (This::wxDC(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetmapmode">external documentation</a>.
+-spec setMapMode(This, Mode) -> ok when
+ This::wxDC(), Mode::integer().
setMapMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetMapMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxDC(), Palette::wxPalette:wxPalette()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetpalette">external documentation</a>.
+-spec setPalette(This, Palette) -> ok when
+ This::wxDC(), Palette::wxPalette:wxPalette().
setPalette(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PaletteT,ref=PaletteRef}) ->
?CLASS(ThisT,wxDC),
?CLASS(PaletteT,wxPalette),
wxe_util:cast(?wxDC_SetPalette,
<<ThisRef:32/?UI,PaletteRef:32/?UI>>).
-%% @spec (This::wxDC(), Pen::wxPen:wxPen()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetpen">external documentation</a>.
+-spec setPen(This, Pen) -> ok when
+ This::wxDC(), Pen::wxPen:wxPen().
setPen(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PenT,ref=PenRef}) ->
?CLASS(ThisT,wxDC),
?CLASS(PenT,wxPen),
wxe_util:cast(?wxDC_SetPen,
<<ThisRef:32/?UI,PenRef:32/?UI>>).
-%% @spec (This::wxDC(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsettextbackground">external documentation</a>.
+-spec setTextBackground(This, Colour) -> ok when
+ This::wxDC(), Colour::wx:wx_colour().
setTextBackground(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetTextBackground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxDC(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsettextforeground">external documentation</a>.
+-spec setTextForeground(This, Colour) -> ok when
+ This::wxDC(), Colour::wx:wx_colour().
setTextForeground(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetTextForeground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxDC(), X::float(), Y::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcsetuserscale">external documentation</a>.
+-spec setUserScale(This, X, Y) -> ok when
+ This::wxDC(), X::number(), Y::number().
setUserScale(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
- when is_float(X),is_float(Y) ->
+ when is_number(X),is_number(Y) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_SetUserScale,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxDC(), Message::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcstartdoc">external documentation</a>.
+-spec startDoc(This, Message) -> boolean() when
+ This::wxDC(), Message::unicode:chardata().
startDoc(#wx_ref{type=ThisT,ref=ThisRef},Message)
when is_list(Message) ->
?CLASS(ThisT,wxDC),
@@ -822,8 +927,9 @@ startDoc(#wx_ref{type=ThisT,ref=ThisRef},Message)
wxe_util:call(?wxDC_StartDoc,
<<ThisRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdc.html#wxdcstartpage">external documentation</a>.
+-spec startPage(This) -> ok when
+ This::wxDC().
startPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDC),
wxe_util:cast(?wxDC_StartPage,
diff --git a/lib/wx/src/gen/wxDataObject.erl b/lib/wx/src/gen/wxDataObject.erl
index bad6d96fb5..65b388aa48 100644
--- a/lib/wx/src/gen/wxDataObject.erl
+++ b/lib/wx/src/gen/wxDataObject.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,8 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxDataObject/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxDataObject() :: wx:wx_object().
diff --git a/lib/wx/src/gen/wxDateEvent.erl b/lib/wx/src/gen/wxDateEvent.erl
index b4b010e122..417322097f 100644
--- a/lib/wx/src/gen/wxDateEvent.erl
+++ b/lib/wx/src/gen/wxDateEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxDateEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxDateEvent()) -> wx:datetime()
+-type wxDateEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdateevent.html#wxdateeventgetdate">external documentation</a>.
+-spec getDate(This) -> wx:wx_datetime() when
+ This::wxDateEvent().
getDate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDateEvent),
wxe_util:call(?wxDateEvent_GetDate,
diff --git a/lib/wx/src/gen/wxDatePickerCtrl.erl b/lib/wx/src/gen/wxDatePickerCtrl.erl
index 2de51ce71d..6ffc2ca3f5 100644
--- a/lib/wx/src/gen/wxDatePickerCtrl.erl
+++ b/lib/wx/src/gen/wxDatePickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxDatePickerCtrl/0]).
%% @hidden
parent_class(wxPickerBase) -> true;
parent_class(wxControl) -> true;
@@ -81,21 +82,29 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxDatePickerCtrl()
+-type wxDatePickerCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlwxdatepickerctrl">external documentation</a>.
+-spec new() -> wxDatePickerCtrl().
new() ->
wxe_util:construct(?wxDatePickerCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxDatePickerCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxDatePickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxDatePickerCtrl()
-%% Option = {date, wx:datetime()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlwxdatepickerctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxDatePickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {date, wx:wx_datetime()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -109,39 +118,43 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxDatePickerCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDatePickerCtrl(), Dt1::wx:datetime(), Dt2::wx:datetime()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlgetrange">external documentation</a>.
+-spec getRange(This, Dt1, Dt2) -> boolean() when
+ This::wxDatePickerCtrl(), Dt1::wx:wx_datetime(), Dt2::wx:wx_datetime().
getRange(#wx_ref{type=ThisT,ref=ThisRef},Dt1,Dt2)
when tuple_size(Dt1) =:= 2,tuple_size(Dt2) =:= 2 ->
?CLASS(ThisT,wxDatePickerCtrl),
wxe_util:call(?wxDatePickerCtrl_GetRange,
<<ThisRef:32/?UI,(wxe_util:datetime_bin(Dt1)):24/binary,(wxe_util:datetime_bin(Dt2)):24/binary>>).
-%% @spec (This::wxDatePickerCtrl()) -> wx:datetime()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlgetvalue">external documentation</a>.
+-spec getValue(This) -> wx:wx_datetime() when
+ This::wxDatePickerCtrl().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDatePickerCtrl),
wxe_util:call(?wxDatePickerCtrl_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDatePickerCtrl(), Dt1::wx:datetime(), Dt2::wx:datetime()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlsetrange">external documentation</a>.
+-spec setRange(This, Dt1, Dt2) -> ok when
+ This::wxDatePickerCtrl(), Dt1::wx:wx_datetime(), Dt2::wx:wx_datetime().
setRange(#wx_ref{type=ThisT,ref=ThisRef},Dt1,Dt2)
when tuple_size(Dt1) =:= 2,tuple_size(Dt2) =:= 2 ->
?CLASS(ThisT,wxDatePickerCtrl),
wxe_util:cast(?wxDatePickerCtrl_SetRange,
<<ThisRef:32/?UI,(wxe_util:datetime_bin(Dt1)):24/binary,(wxe_util:datetime_bin(Dt2)):24/binary>>).
-%% @spec (This::wxDatePickerCtrl(), Date::wx:datetime()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdatepickerctrl.html#wxdatepickerctrlsetvalue">external documentation</a>.
+-spec setValue(This, Date) -> ok when
+ This::wxDatePickerCtrl(), Date::wx:wx_datetime().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Date)
when tuple_size(Date) =:= 2 ->
?CLASS(ThisT,wxDatePickerCtrl),
wxe_util:cast(?wxDatePickerCtrl_SetValue,
<<ThisRef:32/?UI,(wxe_util:datetime_bin(Date)):24/binary>>).
-%% @spec (This::wxDatePickerCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxDatePickerCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxDatePickerCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxDialog.erl b/lib/wx/src/gen/wxDialog.erl
index 8c0bd2cd76..55861b75d1 100644
--- a/lib/wx/src/gen/wxDialog.erl
+++ b/lib/wx/src/gen/wxDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +76,34 @@
thaw/1,transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxDialog/0]).
%% @hidden
parent_class(wxTopLevelWindow) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxDialog()
+-type wxDialog() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogwxdialog">external documentation</a>.
+-spec new() -> wxDialog().
new() ->
wxe_util:construct(?wxDialog_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> wxDialog()
%% @equiv new(Parent,Id,Title, [])
+-spec new(Parent, Id, Title) -> wxDialog() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
new(Parent,Id,Title)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
new(Parent,Id,Title, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxDialog()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogwxdialog">external documentation</a>.
+-spec new(Parent, Id, Title, [Option]) -> wxDialog() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -109,15 +116,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
wxe_util:construct(?wxDialog_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxDialog(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> bool()
%% @equiv create(This,Parent,Id,Title, [])
+-spec create(This, Parent, Id, Title) -> boolean() when
+ This::wxDialog(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
create(This,Parent,Id,Title)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
create(This,Parent,Id,Title, []).
-%% @spec (This::wxDialog(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogcreate">external documentation</a>.
+-spec create(This, Parent, Id, Title, [Option]) -> boolean() when
+ This::wxDialog(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ThisT,wxDialog),
@@ -131,76 +143,87 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ti
wxe_util:call(?wxDialog_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxDialog(), Flags::integer()) -> wxSizer:wxSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogcreatebuttonsizer">external documentation</a>.
+-spec createButtonSizer(This, Flags) -> wxSizer:wxSizer() when
+ This::wxDialog(), Flags::integer().
createButtonSizer(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxDialog),
wxe_util:call(?wxDialog_CreateButtonSizer,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxDialog(), Flags::integer()) -> wxStdDialogButtonSizer:wxStdDialogButtonSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogcreatestddialogbuttonsizer">external documentation</a>.
+-spec createStdDialogButtonSizer(This, Flags) -> wxStdDialogButtonSizer:wxStdDialogButtonSizer() when
+ This::wxDialog(), Flags::integer().
createStdDialogButtonSizer(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxDialog),
wxe_util:call(?wxDialog_CreateStdDialogButtonSizer,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxDialog(), RetCode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogendmodal">external documentation</a>.
+-spec endModal(This, RetCode) -> ok when
+ This::wxDialog(), RetCode::integer().
endModal(#wx_ref{type=ThisT,ref=ThisRef},RetCode)
when is_integer(RetCode) ->
?CLASS(ThisT,wxDialog),
wxe_util:cast(?wxDialog_EndModal,
<<ThisRef:32/?UI,RetCode:32/?UI>>).
-%% @spec (This::wxDialog()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialoggetaffirmativeid">external documentation</a>.
+-spec getAffirmativeId(This) -> integer() when
+ This::wxDialog().
getAffirmativeId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDialog),
wxe_util:call(?wxDialog_GetAffirmativeId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDialog()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialoggetreturncode">external documentation</a>.
+-spec getReturnCode(This) -> integer() when
+ This::wxDialog().
getReturnCode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDialog),
wxe_util:call(?wxDialog_GetReturnCode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDialog()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogismodal">external documentation</a>.
+-spec isModal(This) -> boolean() when
+ This::wxDialog().
isModal(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDialog),
wxe_util:call(?wxDialog_IsModal,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDialog(), AffirmativeId::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogsetaffirmativeid">external documentation</a>.
+-spec setAffirmativeId(This, AffirmativeId) -> ok when
+ This::wxDialog(), AffirmativeId::integer().
setAffirmativeId(#wx_ref{type=ThisT,ref=ThisRef},AffirmativeId)
when is_integer(AffirmativeId) ->
?CLASS(ThisT,wxDialog),
wxe_util:cast(?wxDialog_SetAffirmativeId,
<<ThisRef:32/?UI,AffirmativeId:32/?UI>>).
-%% @spec (This::wxDialog(), ReturnCode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogsetreturncode">external documentation</a>.
+-spec setReturnCode(This, ReturnCode) -> ok when
+ This::wxDialog(), ReturnCode::integer().
setReturnCode(#wx_ref{type=ThisT,ref=ThisRef},ReturnCode)
when is_integer(ReturnCode) ->
?CLASS(ThisT,wxDialog),
wxe_util:cast(?wxDialog_SetReturnCode,
<<ThisRef:32/?UI,ReturnCode:32/?UI>>).
-%% @spec (This::wxDialog()) -> bool()
%% @equiv show(This, [])
+-spec show(This) -> boolean() when
+ This::wxDialog().
+
show(This)
when is_record(This, wx_ref) ->
show(This, []).
-%% @spec (This::wxDialog(), [Option]) -> bool()
-%% Option = {show, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogshow">external documentation</a>.
+-spec show(This, [Option]) -> boolean() when
+ This::wxDialog(),
+ Option :: {show, boolean()}.
show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxDialog),
@@ -210,15 +233,16 @@ show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxDialog_Show,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxDialog()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdialog.html#wxdialogshowmodal">external documentation</a>.
+-spec showModal(This) -> integer() when
+ This::wxDialog().
showModal(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDialog),
wxe_util:call(?wxDialog_ShowModal,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxDirDialog.erl b/lib/wx/src/gen/wxDirDialog.erl
index 7849dce0a7..d7dc735937 100644
--- a/lib/wx/src/gen/wxDirDialog.erl
+++ b/lib/wx/src/gen/wxDirDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxDirDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,15 +85,23 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxDirDialog()
+-type wxDirDialog() :: wx:wx_object().
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxDirDialog() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxDirDialog()
-%% Option = {title, string()} | {defaultPath, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}} | {sz, {W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirdialog.html#wxdirdialogwxdirdialog">external documentation</a>.
+-spec new(Parent, [Option]) -> wxDirDialog() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {title, unicode:chardata()}
+ | {defaultPath, unicode:chardata()}
+ | {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {sz, {W::integer(), H::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,22 +115,25 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxDirDialog_new,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxDirDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirdialog.html#wxdirdialoggetpath">external documentation</a>.
+-spec getPath(This) -> unicode:charlist() when
+ This::wxDirDialog().
getPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDirDialog),
wxe_util:call(?wxDirDialog_GetPath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDirDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirdialog.html#wxdirdialoggetmessage">external documentation</a>.
+-spec getMessage(This) -> unicode:charlist() when
+ This::wxDirDialog().
getMessage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDirDialog),
wxe_util:call(?wxDirDialog_GetMessage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDirDialog(), Message::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirdialog.html#wxdirdialogsetmessage">external documentation</a>.
+-spec setMessage(This, Message) -> ok when
+ This::wxDirDialog(), Message::unicode:chardata().
setMessage(#wx_ref{type=ThisT,ref=ThisRef},Message)
when is_list(Message) ->
?CLASS(ThisT,wxDirDialog),
@@ -129,8 +141,9 @@ setMessage(#wx_ref{type=ThisT,ref=ThisRef},Message)
wxe_util:cast(?wxDirDialog_SetMessage,
<<ThisRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDirDialog(), Path::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirdialog.html#wxdirdialogsetpath">external documentation</a>.
+-spec setPath(This, Path) -> ok when
+ This::wxDirDialog(), Path::unicode:chardata().
setPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
when is_list(Path) ->
?CLASS(ThisT,wxDirDialog),
@@ -138,8 +151,8 @@ setPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
wxe_util:cast(?wxDirDialog_SetPath,
<<ThisRef:32/?UI,(byte_size(Path_UC)):32/?UI,(Path_UC)/binary, 0:(((8- ((0+byte_size(Path_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDirDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxDirDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxDirDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxDirPickerCtrl.erl b/lib/wx/src/gen/wxDirPickerCtrl.erl
index 7fb70b71e3..bbc169ae03 100644
--- a/lib/wx/src/gen/wxDirPickerCtrl.erl
+++ b/lib/wx/src/gen/wxDirPickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxDirPickerCtrl/0]).
%% @hidden
parent_class(wxPickerBase) -> true;
parent_class(wxControl) -> true;
@@ -81,21 +82,30 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxDirPickerCtrl()
+-type wxDirPickerCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlwxdirpickerctrl">external documentation</a>.
+-spec new() -> wxDirPickerCtrl().
new() ->
wxe_util:construct(?wxDirPickerCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxDirPickerCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxDirPickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxDirPickerCtrl()
-%% Option = {path, string()} | {message, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlwxdirpickerctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxDirPickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {path, unicode:chardata()}
+ | {message, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -110,15 +120,23 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxDirPickerCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxDirPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxDirPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxDirPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {path, string()} | {message, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxDirPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {path, unicode:chardata()}
+ | {message, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxDirPickerCtrl),
@@ -134,15 +152,17 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxDirPickerCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxDirPickerCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlgetpath">external documentation</a>.
+-spec getPath(This) -> unicode:charlist() when
+ This::wxDirPickerCtrl().
getPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxDirPickerCtrl),
wxe_util:call(?wxDirPickerCtrl_GetPath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxDirPickerCtrl(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxdirpickerctrl.html#wxdirpickerctrlsetpath">external documentation</a>.
+-spec setPath(This, Str) -> ok when
+ This::wxDirPickerCtrl(), Str::unicode:chardata().
setPath(#wx_ref{type=ThisT,ref=ThisRef},Str)
when is_list(Str) ->
?CLASS(ThisT,wxDirPickerCtrl),
@@ -150,8 +170,8 @@ setPath(#wx_ref{type=ThisT,ref=ThisRef},Str)
wxe_util:cast(?wxDirPickerCtrl_SetPath,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxDirPickerCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxDirPickerCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxDirPickerCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxDisplayChangedEvent.erl b/lib/wx/src/gen/wxDisplayChangedEvent.erl
index c86ef62462..0c0612564b 100644
--- a/lib/wx/src/gen/wxDisplayChangedEvent.erl
+++ b/lib/wx/src/gen/wxDisplayChangedEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,12 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxDisplayChangedEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxDisplayChangedEvent() :: wx:wx_object().
%% From wxEvent
%% @hidden
stopPropagation(This) -> wxEvent:stopPropagation(This).
diff --git a/lib/wx/src/gen/wxEraseEvent.erl b/lib/wx/src/gen/wxEraseEvent.erl
index 77139b6790..03ce8862dc 100644
--- a/lib/wx/src/gen/wxEraseEvent.erl
+++ b/lib/wx/src/gen/wxEraseEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +37,15 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxEraseEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxEraseEvent()) -> wxDC:wxDC()
+-type wxEraseEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxeraseevent.html#wxeraseeventgetdc">external documentation</a>.
+-spec getDC(This) -> wxDC:wxDC() when
+ This::wxEraseEvent().
getDC(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEraseEvent),
wxe_util:call(?wxEraseEvent_GetDC,
diff --git a/lib/wx/src/gen/wxEvent.erl b/lib/wx/src/gen/wxEvent.erl
index 403fd89f1f..1b2147a326 100644
--- a/lib/wx/src/gen/wxEvent.erl
+++ b/lib/wx/src/gen/wxEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,61 +30,72 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxEvent/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxEvent()) -> integer()
+-type wxEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventgetid">external documentation</a>.
+-spec getId(This) -> integer() when
+ This::wxEvent().
getId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEvent),
wxe_util:call(?wxEvent_GetId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventgetskipped">external documentation</a>.
+-spec getSkipped(This) -> boolean() when
+ This::wxEvent().
getSkipped(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEvent),
wxe_util:call(?wxEvent_GetSkipped,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventgettimestamp">external documentation</a>.
+-spec getTimestamp(This) -> integer() when
+ This::wxEvent().
getTimestamp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEvent),
wxe_util:call(?wxEvent_GetTimestamp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventiscommandevent">external documentation</a>.
+-spec isCommandEvent(This) -> boolean() when
+ This::wxEvent().
isCommandEvent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEvent),
wxe_util:call(?wxEvent_IsCommandEvent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxEvent(), PropagationLevel::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventresumepropagation">external documentation</a>.
+-spec resumePropagation(This, PropagationLevel) -> ok when
+ This::wxEvent(), PropagationLevel::integer().
resumePropagation(#wx_ref{type=ThisT,ref=ThisRef},PropagationLevel)
when is_integer(PropagationLevel) ->
?CLASS(ThisT,wxEvent),
wxe_util:cast(?wxEvent_ResumePropagation,
<<ThisRef:32/?UI,PropagationLevel:32/?UI>>).
-%% @spec (This::wxEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventshouldpropagate">external documentation</a>.
+-spec shouldPropagate(This) -> boolean() when
+ This::wxEvent().
shouldPropagate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEvent),
wxe_util:call(?wxEvent_ShouldPropagate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxEvent()) -> ok
%% @equiv skip(This, [])
+-spec skip(This) -> ok when
+ This::wxEvent().
+
skip(This)
when is_record(This, wx_ref) ->
skip(This, []).
-%% @spec (This::wxEvent(), [Option]) -> ok
-%% Option = {skip, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventskip">external documentation</a>.
+-spec skip(This, [Option]) -> ok when
+ This::wxEvent(),
+ Option :: {skip, boolean()}.
skip(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxEvent),
@@ -94,8 +105,9 @@ skip(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxEvent_Skip,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevent.html#wxeventstoppropagation">external documentation</a>.
+-spec stopPropagation(This) -> integer() when
+ This::wxEvent().
stopPropagation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxEvent),
wxe_util:call(?wxEvent_StopPropagation,
diff --git a/lib/wx/src/gen/wxEvtHandler.erl b/lib/wx/src/gen/wxEvtHandler.erl
index f155351b66..22c203392c 100644
--- a/lib/wx/src/gen/wxEvtHandler.erl
+++ b/lib/wx/src/gen/wxEvtHandler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,7 @@
%% <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html">
%% The orginal documentation</a>.
%%
-%% @headerfile "../../include/wx.hrl"
%%
-%%@type wxEvtHandler(). An object reference
-
-module(wxEvtHandler).
-include("wxe.hrl").
-include("../include/wx.hrl").
@@ -53,17 +50,16 @@
new_evt_listener/0, destroy_evt_listener/1,
get_callback/1, replace_fun_with_id/2]).
--record(evh, {et=null,id=?wxID_ANY,lastId=?wxID_ANY,skip=undefined,userdata=[],cb=0}).
-
+-export_type([wxEvtHandler/0, wx/0, event/0]).
+-type wxEvtHandler() :: wx:wx_object().
+-record(evh, {et=null,id=?wxID_ANY,lastId=?wxID_ANY,skip=undefined,userdata=[],cb=0}).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType()) -> ok
%% @doc Equivalent to {@link connect/3. connect(This, EventType, [])}
-
+-spec connect(This::wxEvtHandler(), EventType::wxEventType()) -> ok.
connect(This, EventType) ->
connect(This, EventType, []).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType(), [Options]) -> ok
%% @doc This function subscribes the to events of EventType,
%% in the range id, lastId. The events will be received as messages
%% if no callback is supplied.
@@ -82,6 +78,9 @@ connect(This, EventType) ->
%% to process the event. Default not specfied i.e. a message will
%% be delivered to the process calling this function.
%% {userData, term()} An erlang term that will be sent with the event. Default: [].
+-spec connect(This::wxEvtHandler(), EventType::wxEventType(), [Option]) -> ok when
+ Option :: {id, integer()} | {lastId, integer()} | {skip, boolean()} |
+ callback | {callback, function()} | {userData, term()}.
connect(This=#wx_ref{type=ThisT}, EventType, Options) ->
EvH = parse_opts(Options, #evh{et=EventType}),
?CLASS(ThisT,wxEvtHandler),
@@ -95,7 +94,7 @@ parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) ->
%% Check Fun Arity?
parse_opts(R, Opts#evh{cb=Fun});
parse_opts([callback|R], Opts) ->
- parse_opts(R, Opts#evh{cb=1});
+ parse_opts(R, Opts#evh{cb=self()});
parse_opts([{userData, UserData}|R],Opts) ->
parse_opts(R, Opts#evh{userdata=UserData});
parse_opts([{skip, Skip}|R],Opts) when is_boolean(Skip) ->
@@ -118,26 +117,27 @@ parse_opts([], Opts = #evh{id=Id,lastId=Lid,skip=Skip, cb=CB}) ->
Opts
end.
-%% @spec (This::wxEvtHandler()) -> true | false
+
%% @doc Equivalent to {@link disconnect/3. disconnect(This, null, [])}
%% Can also have an optional callback Fun() as an additional last argument.
-
+-spec disconnect(This::wxEvtHandler()) -> boolean().
disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}) ->
?CLASS(ThisT,wxEvtHandler),
disconnect(This, null, []).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType()) -> true | false
%% @doc Equivalent to {@link disconnect/3. disconnect(This, EventType, [])}
+-spec disconnect(This::wxEvtHandler(), EventType::wxEventType()) -> boolean().
disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType) when is_atom(EventType) ->
?CLASS(ThisT,wxEvtHandler),
disconnect(This, EventType, []).
-%% @spec (This::wxEvtHandler(), EventType::wxEventType(), Opts) -> true | false
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html#wxevthandlerdisconnect">external documentation</a>
%% This function unsubscribes the process or callback fun from the event handler.
%% EventType may be the atom 'null' to match any eventtype.
%% Notice that the options skip and userdata is not used to match the eventhandler.
-disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType, Opts) ->
+-spec disconnect(This::wxEvtHandler(), EventType::wxEventType(), [Option]) -> boolean() when
+ Option :: {id, integer()} | {lastId, integer()} | {callback, function()}.
+disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType, Opts) ->
?CLASS(ThisT,wxEvtHandler),
EvH = parse_opts(Opts, #evh{et=EventType}),
case wxe_util:disconnect_cb(This, EvH) of
diff --git a/lib/wx/src/gen/wxFileDataObject.erl b/lib/wx/src/gen/wxFileDataObject.erl
index 2fcfbd5374..435c795cdc 100644
--- a/lib/wx/src/gen/wxFileDataObject.erl
+++ b/lib/wx/src/gen/wxFileDataObject.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +32,21 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxFileDataObject/0]).
%% @hidden
parent_class(wxDataObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFileDataObject()
+-type wxFileDataObject() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledataobject.html#wxfiledataobjectwxfiledataobject">external documentation</a>.
+-spec new() -> wxFileDataObject().
new() ->
wxe_util:construct(?wxFileDataObject_new,
<<>>).
-%% @spec (This::wxFileDataObject(), Filename::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledataobject.html#wxfiledataobjectaddfile">external documentation</a>.
+-spec addFile(This, Filename) -> ok when
+ This::wxFileDataObject(), Filename::unicode:chardata().
addFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
when is_list(Filename) ->
?CLASS(ThisT,wxFileDataObject),
@@ -51,15 +54,16 @@ addFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
wxe_util:cast(?wxFileDataObject_AddFile,
<<ThisRef:32/?UI,(byte_size(Filename_UC)):32/?UI,(Filename_UC)/binary, 0:(((8- ((0+byte_size(Filename_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFileDataObject()) -> [[string()]]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledataobject.html#wxfiledataobjectgetfilenames">external documentation</a>.
+-spec getFilenames(This) -> [unicode:charlist()] when
+ This::wxFileDataObject().
getFilenames(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDataObject),
wxe_util:call(?wxFileDataObject_GetFilenames,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDataObject()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFileDataObject()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFileDataObject),
wxe_util:destroy(?wxFileDataObject_destroy,Obj),
diff --git a/lib/wx/src/gen/wxFileDialog.erl b/lib/wx/src/gen/wxFileDialog.erl
index cba9705335..a257905795 100644
--- a/lib/wx/src/gen/wxFileDialog.erl
+++ b/lib/wx/src/gen/wxFileDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +79,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxFileDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -86,15 +87,25 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxFileDialog()
+-type wxFileDialog() :: wx:wx_object().
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxFileDialog() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxFileDialog()
-%% Option = {message, string()} | {defaultDir, string()} | {defaultFile, string()} | {wildCard, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}} | {sz, {W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogwxfiledialog">external documentation</a>.
+-spec new(Parent, [Option]) -> wxFileDialog() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {message, unicode:chardata()}
+ | {defaultDir, unicode:chardata()}
+ | {defaultFile, unicode:chardata()}
+ | {wildCard, unicode:chardata()}
+ | {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {sz, {W::integer(), H::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -110,64 +121,73 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxFileDialog_new,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxFileDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetdirectory">external documentation</a>.
+-spec getDirectory(This) -> unicode:charlist() when
+ This::wxFileDialog().
getDirectory(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetDirectory,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetfilename">external documentation</a>.
+-spec getFilename(This) -> unicode:charlist() when
+ This::wxFileDialog().
getFilename(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetFilename,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> [[string()]]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetfilenames">external documentation</a>.
+-spec getFilenames(This) -> [unicode:charlist()] when
+ This::wxFileDialog().
getFilenames(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetFilenames,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetfilterindex">external documentation</a>.
+-spec getFilterIndex(This) -> integer() when
+ This::wxFileDialog().
getFilterIndex(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetFilterIndex,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetmessage">external documentation</a>.
+-spec getMessage(This) -> unicode:charlist() when
+ This::wxFileDialog().
getMessage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetMessage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetpath">external documentation</a>.
+-spec getPath(This) -> unicode:charlist() when
+ This::wxFileDialog().
getPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetPath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> [[string()]]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetpaths">external documentation</a>.
+-spec getPaths(This) -> [unicode:charlist()] when
+ This::wxFileDialog().
getPaths(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetPaths,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetwildcard">external documentation</a>.
+-spec getWildcard(This) -> unicode:charlist() when
+ This::wxFileDialog().
getWildcard(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:call(?wxFileDialog_GetWildcard,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFileDialog(), Dir::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogsetdirectory">external documentation</a>.
+-spec setDirectory(This, Dir) -> ok when
+ This::wxFileDialog(), Dir::unicode:chardata().
setDirectory(#wx_ref{type=ThisT,ref=ThisRef},Dir)
when is_list(Dir) ->
?CLASS(ThisT,wxFileDialog),
@@ -175,8 +195,9 @@ setDirectory(#wx_ref{type=ThisT,ref=ThisRef},Dir)
wxe_util:cast(?wxFileDialog_SetDirectory,
<<ThisRef:32/?UI,(byte_size(Dir_UC)):32/?UI,(Dir_UC)/binary, 0:(((8- ((0+byte_size(Dir_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFileDialog(), Name::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogsetfilename">external documentation</a>.
+-spec setFilename(This, Name) -> ok when
+ This::wxFileDialog(), Name::unicode:chardata().
setFilename(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxFileDialog),
@@ -184,16 +205,18 @@ setFilename(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:cast(?wxFileDialog_SetFilename,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFileDialog(), FilterIndex::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogsetfilterindex">external documentation</a>.
+-spec setFilterIndex(This, FilterIndex) -> ok when
+ This::wxFileDialog(), FilterIndex::integer().
setFilterIndex(#wx_ref{type=ThisT,ref=ThisRef},FilterIndex)
when is_integer(FilterIndex) ->
?CLASS(ThisT,wxFileDialog),
wxe_util:cast(?wxFileDialog_SetFilterIndex,
<<ThisRef:32/?UI,FilterIndex:32/?UI>>).
-%% @spec (This::wxFileDialog(), Message::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogsetmessage">external documentation</a>.
+-spec setMessage(This, Message) -> ok when
+ This::wxFileDialog(), Message::unicode:chardata().
setMessage(#wx_ref{type=ThisT,ref=ThisRef},Message)
when is_list(Message) ->
?CLASS(ThisT,wxFileDialog),
@@ -201,8 +224,9 @@ setMessage(#wx_ref{type=ThisT,ref=ThisRef},Message)
wxe_util:cast(?wxFileDialog_SetMessage,
<<ThisRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFileDialog(), Path::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogsetpath">external documentation</a>.
+-spec setPath(This, Path) -> ok when
+ This::wxFileDialog(), Path::unicode:chardata().
setPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
when is_list(Path) ->
?CLASS(ThisT,wxFileDialog),
@@ -210,8 +234,9 @@ setPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
wxe_util:cast(?wxFileDialog_SetPath,
<<ThisRef:32/?UI,(byte_size(Path_UC)):32/?UI,(Path_UC)/binary, 0:(((8- ((0+byte_size(Path_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFileDialog(), WildCard::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialogsetwildcard">external documentation</a>.
+-spec setWildcard(This, WildCard) -> ok when
+ This::wxFileDialog(), WildCard::unicode:chardata().
setWildcard(#wx_ref{type=ThisT,ref=ThisRef},WildCard)
when is_list(WildCard) ->
?CLASS(ThisT,wxFileDialog),
@@ -219,8 +244,8 @@ setWildcard(#wx_ref{type=ThisT,ref=ThisRef},WildCard)
wxe_util:cast(?wxFileDialog_SetWildcard,
<<ThisRef:32/?UI,(byte_size(WildCard_UC)):32/?UI,(WildCard_UC)/binary, 0:(((8- ((0+byte_size(WildCard_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFileDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFileDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFileDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFileDirPickerEvent.erl b/lib/wx/src/gen/wxFileDirPickerEvent.erl
index cc4880b88c..77b10a91ed 100644
--- a/lib/wx/src/gen/wxFileDirPickerEvent.erl
+++ b/lib/wx/src/gen/wxFileDirPickerEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxFileDirPickerEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxFileDirPickerEvent()) -> string()
+-type wxFileDirPickerEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledirpickerevent.html#wxfiledirpickereventgetpath">external documentation</a>.
+-spec getPath(This) -> unicode:charlist() when
+ This::wxFileDirPickerEvent().
getPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFileDirPickerEvent),
wxe_util:call(?wxFileDirPickerEvent_GetPath,
diff --git a/lib/wx/src/gen/wxFilePickerCtrl.erl b/lib/wx/src/gen/wxFilePickerCtrl.erl
index a3034aaa86..d19c8c00cb 100644
--- a/lib/wx/src/gen/wxFilePickerCtrl.erl
+++ b/lib/wx/src/gen/wxFilePickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxFilePickerCtrl/0]).
%% @hidden
parent_class(wxPickerBase) -> true;
parent_class(wxControl) -> true;
@@ -81,21 +82,31 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFilePickerCtrl()
+-type wxFilePickerCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlwxfilepickerctrl">external documentation</a>.
+-spec new() -> wxFilePickerCtrl().
new() ->
wxe_util:construct(?wxFilePickerCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxFilePickerCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxFilePickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxFilePickerCtrl()
-%% Option = {path, string()} | {message, string()} | {wildcard, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlwxfilepickerctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxFilePickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {path, unicode:chardata()}
+ | {message, unicode:chardata()}
+ | {wildcard, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -111,15 +122,24 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxFilePickerCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxFilePickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxFilePickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxFilePickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {path, string()} | {message, string()} | {wildcard, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxFilePickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {path, unicode:chardata()}
+ | {message, unicode:chardata()}
+ | {wildcard, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxFilePickerCtrl),
@@ -136,15 +156,17 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxFilePickerCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxFilePickerCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlgetpath">external documentation</a>.
+-spec getPath(This) -> unicode:charlist() when
+ This::wxFilePickerCtrl().
getPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFilePickerCtrl),
wxe_util:call(?wxFilePickerCtrl_GetPath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFilePickerCtrl(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfilepickerctrl.html#wxfilepickerctrlsetpath">external documentation</a>.
+-spec setPath(This, Str) -> ok when
+ This::wxFilePickerCtrl(), Str::unicode:chardata().
setPath(#wx_ref{type=ThisT,ref=ThisRef},Str)
when is_list(Str) ->
?CLASS(ThisT,wxFilePickerCtrl),
@@ -152,8 +174,8 @@ setPath(#wx_ref{type=ThisT,ref=ThisRef},Str)
wxe_util:cast(?wxFilePickerCtrl_SetPath,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFilePickerCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFilePickerCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFilePickerCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFindReplaceData.erl b/lib/wx/src/gen/wxFindReplaceData.erl
index 52eafa8398..8dc6036da6 100644
--- a/lib/wx/src/gen/wxFindReplaceData.erl
+++ b/lib/wx/src/gen/wxFindReplaceData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,53 +30,61 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxFindReplaceData/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFindReplaceData()
+-type wxFindReplaceData() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatawxfindreplacedata">external documentation</a>.
+-spec new() -> wxFindReplaceData().
new() ->
wxe_util:construct(?wxFindReplaceData_new_0,
<<>>).
-%% @spec (Flags::integer()) -> wxFindReplaceData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatawxfindreplacedata">external documentation</a>.
+-spec new(Flags) -> wxFindReplaceData() when
+ Flags::integer().
new(Flags)
when is_integer(Flags) ->
wxe_util:construct(?wxFindReplaceData_new_1,
<<Flags:32/?UI>>).
-%% @spec (This::wxFindReplaceData()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatagetfindstring">external documentation</a>.
+-spec getFindString(This) -> unicode:charlist() when
+ This::wxFindReplaceData().
getFindString(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFindReplaceData),
wxe_util:call(?wxFindReplaceData_GetFindString,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFindReplaceData()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatagetreplacestring">external documentation</a>.
+-spec getReplaceString(This) -> unicode:charlist() when
+ This::wxFindReplaceData().
getReplaceString(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFindReplaceData),
wxe_util:call(?wxFindReplaceData_GetReplaceString,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFindReplaceData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatagetflags">external documentation</a>.
+-spec getFlags(This) -> integer() when
+ This::wxFindReplaceData().
getFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFindReplaceData),
wxe_util:call(?wxFindReplaceData_GetFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFindReplaceData(), Flags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatasetflags">external documentation</a>.
+-spec setFlags(This, Flags) -> ok when
+ This::wxFindReplaceData(), Flags::integer().
setFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxFindReplaceData),
wxe_util:cast(?wxFindReplaceData_SetFlags,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxFindReplaceData(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatasetfindstring">external documentation</a>.
+-spec setFindString(This, Str) -> ok when
+ This::wxFindReplaceData(), Str::unicode:chardata().
setFindString(#wx_ref{type=ThisT,ref=ThisRef},Str)
when is_list(Str) ->
?CLASS(ThisT,wxFindReplaceData),
@@ -84,8 +92,9 @@ setFindString(#wx_ref{type=ThisT,ref=ThisRef},Str)
wxe_util:cast(?wxFindReplaceData_SetFindString,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFindReplaceData(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedata.html#wxfindreplacedatasetreplacestring">external documentation</a>.
+-spec setReplaceString(This, Str) -> ok when
+ This::wxFindReplaceData(), Str::unicode:chardata().
setReplaceString(#wx_ref{type=ThisT,ref=ThisRef},Str)
when is_list(Str) ->
?CLASS(ThisT,wxFindReplaceData),
@@ -93,8 +102,8 @@ setReplaceString(#wx_ref{type=ThisT,ref=ThisRef},Str)
wxe_util:cast(?wxFindReplaceData_SetReplaceString,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFindReplaceData()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFindReplaceData()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFindReplaceData),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFindReplaceDialog.erl b/lib/wx/src/gen/wxFindReplaceDialog.erl
index b37fd41831..6db9b3ed53 100644
--- a/lib/wx/src/gen/wxFindReplaceDialog.erl
+++ b/lib/wx/src/gen/wxFindReplaceDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxFindReplaceDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,21 +85,25 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFindReplaceDialog()
+-type wxFindReplaceDialog() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedialog.html#wxfindreplacedialogwxfindreplacedialog">external documentation</a>.
+-spec new() -> wxFindReplaceDialog().
new() ->
wxe_util:construct(?wxFindReplaceDialog_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::string()) -> wxFindReplaceDialog()
%% @equiv new(Parent,Data,Title, [])
+-spec new(Parent, Data, Title) -> wxFindReplaceDialog() when
+ Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::unicode:chardata().
+
new(Parent,Data,Title)
when is_record(Parent, wx_ref),is_record(Data, wx_ref),is_list(Title) ->
new(Parent,Data,Title, []).
-%% @spec (Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::string(), [Option]) -> wxFindReplaceDialog()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedialog.html#wxfindreplacedialogwxfindreplacedialog">external documentation</a>.
+-spec new(Parent, Data, Title, [Option]) -> wxFindReplaceDialog() when
+ Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::unicode:chardata(),
+ Option :: {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=DataT,ref=DataRef},Title, Options)
when is_list(Title),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -110,15 +115,18 @@ new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=DataT,ref=DataRef},Title, O
wxe_util:construct(?wxFindReplaceDialog_new_4,
<<ParentRef:32/?UI,DataRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxFindReplaceDialog(), Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::string()) -> bool()
%% @equiv create(This,Parent,Data,Title, [])
+-spec create(This, Parent, Data, Title) -> boolean() when
+ This::wxFindReplaceDialog(), Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::unicode:chardata().
+
create(This,Parent,Data,Title)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_record(Data, wx_ref),is_list(Title) ->
create(This,Parent,Data,Title, []).
-%% @spec (This::wxFindReplaceDialog(), Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::string(), [Option]) -> bool()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedialog.html#wxfindreplacedialogcreate">external documentation</a>.
+-spec create(This, Parent, Data, Title, [Option]) -> boolean() when
+ This::wxFindReplaceDialog(), Parent::wxWindow:wxWindow(), Data::wxFindReplaceData:wxFindReplaceData(), Title::unicode:chardata(),
+ Option :: {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=DataT,ref=DataRef},Title, Options)
when is_list(Title),is_list(Options) ->
?CLASS(ThisT,wxFindReplaceDialog),
@@ -131,15 +139,16 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_r
wxe_util:call(?wxFindReplaceDialog_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,DataRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxFindReplaceDialog()) -> wxFindReplaceData:wxFindReplaceData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfindreplacedialog.html#wxfindreplacedialoggetdata">external documentation</a>.
+-spec getData(This) -> wxFindReplaceData:wxFindReplaceData() when
+ This::wxFindReplaceDialog().
getData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFindReplaceDialog),
wxe_util:call(?wxFindReplaceDialog_GetData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFindReplaceDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFindReplaceDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFindReplaceDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFlexGridSizer.erl b/lib/wx/src/gen/wxFlexGridSizer.erl
index 910cc78894..91dcf6a2e7 100644
--- a/lib/wx/src/gen/wxFlexGridSizer.erl
+++ b/lib/wx/src/gen/wxFlexGridSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 +45,26 @@
setMinSize/2,setMinSize/3,setRows/2,setSizeHints/2,setVGap/2,setVirtualSizeHints/2,
show/2,show/3]).
+-export_type([wxFlexGridSizer/0]).
%% @hidden
parent_class(wxGridSizer) -> true;
parent_class(wxSizer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Cols::integer()) -> wxFlexGridSizer()
+-type wxFlexGridSizer() :: wx:wx_object().
%% @equiv new(Cols, [])
+-spec new(Cols) -> wxFlexGridSizer() when
+ Cols::integer().
+
new(Cols)
when is_integer(Cols) ->
new(Cols, []).
-%% @spec (Cols::integer(), [Option]) -> wxFlexGridSizer()
-%% Option = {vgap, integer()} | {hgap, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizerwxflexgridsizer">external documentation</a>.
+-spec new(Cols, [Option]) -> wxFlexGridSizer() when
+ Cols::integer(),
+ Option :: {vgap, integer()}
+ | {hgap, integer()}.
new(Cols, Options)
when is_integer(Cols),is_list(Options) ->
MOpts = fun({vgap, Vgap}, Acc) -> [<<1:32/?UI,Vgap:32/?UI>>|Acc];
@@ -68,22 +74,26 @@ new(Cols, Options)
wxe_util:construct(?wxFlexGridSizer_new_2,
<<Cols:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Rows::integer(), Cols::integer(), Vgap::integer(), Hgap::integer()) -> wxFlexGridSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizerwxflexgridsizer">external documentation</a>.
+-spec new(Rows, Cols, Vgap, Hgap) -> wxFlexGridSizer() when
+ Rows::integer(), Cols::integer(), Vgap::integer(), Hgap::integer().
new(Rows,Cols,Vgap,Hgap)
when is_integer(Rows),is_integer(Cols),is_integer(Vgap),is_integer(Hgap) ->
wxe_util:construct(?wxFlexGridSizer_new_4,
<<Rows:32/?UI,Cols:32/?UI,Vgap:32/?UI,Hgap:32/?UI>>).
-%% @spec (This::wxFlexGridSizer(), Idx::integer()) -> ok
%% @equiv addGrowableCol(This,Idx, [])
+-spec addGrowableCol(This, Idx) -> ok when
+ This::wxFlexGridSizer(), Idx::integer().
+
addGrowableCol(This,Idx)
when is_record(This, wx_ref),is_integer(Idx) ->
addGrowableCol(This,Idx, []).
-%% @spec (This::wxFlexGridSizer(), Idx::integer(), [Option]) -> ok
-%% Option = {proportion, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizeraddgrowablecol">external documentation</a>.
+-spec addGrowableCol(This, Idx, [Option]) -> ok when
+ This::wxFlexGridSizer(), Idx::integer(),
+ Option :: {proportion, integer()}.
addGrowableCol(#wx_ref{type=ThisT,ref=ThisRef},Idx, Options)
when is_integer(Idx),is_list(Options) ->
?CLASS(ThisT,wxFlexGridSizer),
@@ -93,15 +103,18 @@ addGrowableCol(#wx_ref{type=ThisT,ref=ThisRef},Idx, Options)
wxe_util:cast(?wxFlexGridSizer_AddGrowableCol,
<<ThisRef:32/?UI,Idx:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxFlexGridSizer(), Idx::integer()) -> ok
%% @equiv addGrowableRow(This,Idx, [])
+-spec addGrowableRow(This, Idx) -> ok when
+ This::wxFlexGridSizer(), Idx::integer().
+
addGrowableRow(This,Idx)
when is_record(This, wx_ref),is_integer(Idx) ->
addGrowableRow(This,Idx, []).
-%% @spec (This::wxFlexGridSizer(), Idx::integer(), [Option]) -> ok
-%% Option = {proportion, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizeraddgrowablerow">external documentation</a>.
+-spec addGrowableRow(This, Idx, [Option]) -> ok when
+ This::wxFlexGridSizer(), Idx::integer(),
+ Option :: {proportion, integer()}.
addGrowableRow(#wx_ref{type=ThisT,ref=ThisRef},Idx, Options)
when is_integer(Idx),is_list(Options) ->
?CLASS(ThisT,wxFlexGridSizer),
@@ -111,58 +124,62 @@ addGrowableRow(#wx_ref{type=ThisT,ref=ThisRef},Idx, Options)
wxe_util:cast(?wxFlexGridSizer_AddGrowableRow,
<<ThisRef:32/?UI,Idx:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxFlexGridSizer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizergetflexibledirection">external documentation</a>.
+-spec getFlexibleDirection(This) -> integer() when
+ This::wxFlexGridSizer().
getFlexibleDirection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFlexGridSizer),
wxe_util:call(?wxFlexGridSizer_GetFlexibleDirection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFlexGridSizer()) -> WxFlexSizerGrowMode
-%% WxFlexSizerGrowMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizergetnonflexiblegrowmode">external documentation</a>.
-%%<br /> WxFlexSizerGrowMode is one of ?wxFLEX_GROWMODE_NONE | ?wxFLEX_GROWMODE_SPECIFIED | ?wxFLEX_GROWMODE_ALL
+%%<br /> Res = ?wxFLEX_GROWMODE_NONE | ?wxFLEX_GROWMODE_SPECIFIED | ?wxFLEX_GROWMODE_ALL
+-spec getNonFlexibleGrowMode(This) -> wx:wx_enum() when
+ This::wxFlexGridSizer().
getNonFlexibleGrowMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFlexGridSizer),
wxe_util:call(?wxFlexGridSizer_GetNonFlexibleGrowMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFlexGridSizer(), Idx::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizerremovegrowablecol">external documentation</a>.
+-spec removeGrowableCol(This, Idx) -> ok when
+ This::wxFlexGridSizer(), Idx::integer().
removeGrowableCol(#wx_ref{type=ThisT,ref=ThisRef},Idx)
when is_integer(Idx) ->
?CLASS(ThisT,wxFlexGridSizer),
wxe_util:cast(?wxFlexGridSizer_RemoveGrowableCol,
<<ThisRef:32/?UI,Idx:32/?UI>>).
-%% @spec (This::wxFlexGridSizer(), Idx::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizerremovegrowablerow">external documentation</a>.
+-spec removeGrowableRow(This, Idx) -> ok when
+ This::wxFlexGridSizer(), Idx::integer().
removeGrowableRow(#wx_ref{type=ThisT,ref=ThisRef},Idx)
when is_integer(Idx) ->
?CLASS(ThisT,wxFlexGridSizer),
wxe_util:cast(?wxFlexGridSizer_RemoveGrowableRow,
<<ThisRef:32/?UI,Idx:32/?UI>>).
-%% @spec (This::wxFlexGridSizer(), Direction::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizersetflexibledirection">external documentation</a>.
+-spec setFlexibleDirection(This, Direction) -> ok when
+ This::wxFlexGridSizer(), Direction::integer().
setFlexibleDirection(#wx_ref{type=ThisT,ref=ThisRef},Direction)
when is_integer(Direction) ->
?CLASS(ThisT,wxFlexGridSizer),
wxe_util:cast(?wxFlexGridSizer_SetFlexibleDirection,
<<ThisRef:32/?UI,Direction:32/?UI>>).
-%% @spec (This::wxFlexGridSizer(), Mode::WxFlexSizerGrowMode) -> ok
-%% WxFlexSizerGrowMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxflexgridsizer.html#wxflexgridsizersetnonflexiblegrowmode">external documentation</a>.
-%%<br /> WxFlexSizerGrowMode is one of ?wxFLEX_GROWMODE_NONE | ?wxFLEX_GROWMODE_SPECIFIED | ?wxFLEX_GROWMODE_ALL
+%%<br /> Mode = ?wxFLEX_GROWMODE_NONE | ?wxFLEX_GROWMODE_SPECIFIED | ?wxFLEX_GROWMODE_ALL
+-spec setNonFlexibleGrowMode(This, Mode) -> ok when
+ This::wxFlexGridSizer(), Mode::wx:wx_enum().
setNonFlexibleGrowMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxFlexGridSizer),
wxe_util:cast(?wxFlexGridSizer_SetNonFlexibleGrowMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxFlexGridSizer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFlexGridSizer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFlexGridSizer),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFocusEvent.erl b/lib/wx/src/gen/wxFocusEvent.erl
index 46f2e2a3df..d6478c1142 100644
--- a/lib/wx/src/gen/wxFocusEvent.erl
+++ b/lib/wx/src/gen/wxFocusEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +37,15 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxFocusEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxFocusEvent()) -> wxWindow:wxWindow()
+-type wxFocusEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfocusevent.html#wxfocuseventgetwindow">external documentation</a>.
+-spec getWindow(This) -> wxWindow:wxWindow() when
+ This::wxFocusEvent().
getWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFocusEvent),
wxe_util:call(?wxFocusEvent_GetWindow,
diff --git a/lib/wx/src/gen/wxFont.erl b/lib/wx/src/gen/wxFont.erl
index 4afc53cfa8..a168e15180 100644
--- a/lib/wx/src/gen/wxFont.erl
+++ b/lib/wx/src/gen/wxFont.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,38 +33,43 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxFont/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFont()
+-type wxFont() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontwxfont">external documentation</a>.
+-spec new() -> wxFont().
new() ->
wxe_util:construct(?wxFont_new_0,
<<>>).
-%% @spec (Fontname::string()) -> wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontwxfont">external documentation</a>.
+-spec new(Fontname) -> wxFont() when
+ Fontname::unicode:chardata().
new(Fontname)
when is_list(Fontname) ->
Fontname_UC = unicode:characters_to_binary([Fontname,0]),
wxe_util:construct(?wxFont_new_1,
<<(byte_size(Fontname_UC)):32/?UI,(Fontname_UC)/binary, 0:(((8- ((4+byte_size(Fontname_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (Size::integer(), Family::WxFontFamily, Style::WxFontStyle, Weight::integer()) -> wxFont()
%% @equiv new(Size,Family,Style,Weight, [])
+-spec new(Size, Family, Style, Weight) -> wxFont() when
+ Size::integer(), Family::wx:wx_enum(), Style::wx:wx_enum(), Weight::integer().
+
new(Size,Family,Style,Weight)
when is_integer(Size),is_integer(Family),is_integer(Style),is_integer(Weight) ->
new(Size,Family,Style,Weight, []).
-%% @spec (Size::integer(), Family::WxFontFamily, Style::WxFontStyle, Weight::integer(), [Option]) -> wxFont()
-%% Option = {underlined, bool()} | {face, string()} | {encoding, WxFontEncoding}
-%% WxFontFamily = integer()
-%% WxFontStyle = integer()
-%% WxFontEncoding = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontwxfont">external documentation</a>.
-%%<br /> WxFontFamily is one of ?wxFONTFAMILY_DEFAULT | ?wxFONTFAMILY_DECORATIVE | ?wxFONTFAMILY_ROMAN | ?wxFONTFAMILY_SCRIPT | ?wxFONTFAMILY_SWISS | ?wxFONTFAMILY_MODERN | ?wxFONTFAMILY_TELETYPE | ?wxFONTFAMILY_MAX | ?wxFONTFAMILY_UNKNOWN
-%%<br /> WxFontStyle is one of ?wxFONTSTYLE_NORMAL | ?wxFONTSTYLE_ITALIC | ?wxFONTSTYLE_SLANT | ?wxFONTSTYLE_MAX
-%%<br /> WxFontEncoding is one of ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+%%<br /> Encoding = ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+%%<br /> Family = ?wxFONTFAMILY_DEFAULT | ?wxFONTFAMILY_DECORATIVE | ?wxFONTFAMILY_ROMAN | ?wxFONTFAMILY_SCRIPT | ?wxFONTFAMILY_SWISS | ?wxFONTFAMILY_MODERN | ?wxFONTFAMILY_TELETYPE | ?wxFONTFAMILY_MAX | ?wxFONTFAMILY_UNKNOWN
+%%<br /> Style = ?wxFONTSTYLE_NORMAL | ?wxFONTSTYLE_ITALIC | ?wxFONTSTYLE_SLANT | ?wxFONTSTYLE_MAX
+-spec new(Size, Family, Style, Weight, [Option]) -> wxFont() when
+ Size::integer(), Family::wx:wx_enum(), Style::wx:wx_enum(), Weight::integer(),
+ Option :: {underlined, boolean()}
+ | {face, unicode:chardata()}
+ | {encoding, wx:wx_enum()}.
new(Size,Family,Style,Weight, Options)
when is_integer(Size),is_integer(Family),is_integer(Style),is_integer(Weight),is_list(Options) ->
MOpts = fun({underlined, Underlined}, Acc) -> [<<1:32/?UI,(wxe_util:from_bool(Underlined)):32/?UI>>|Acc];
@@ -75,99 +80,107 @@ new(Size,Family,Style,Weight, Options)
wxe_util:construct(?wxFont_new_5,
<<Size:32/?UI,Family:32/?UI,Style:32/?UI,Weight:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxFont()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontisfixedwidth">external documentation</a>.
+-spec isFixedWidth(This) -> boolean() when
+ This::wxFont().
isFixedWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_IsFixedWidth,
<<ThisRef:32/?UI>>).
-%% @spec () -> WxFontEncoding
-%% WxFontEncoding = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetdefaultencoding">external documentation</a>.
-%%<br /> WxFontEncoding is one of ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+%%<br /> Res = ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+-spec getDefaultEncoding() -> wx:wx_enum().
getDefaultEncoding() ->
wxe_util:call(?wxFont_GetDefaultEncoding,
<<>>).
-%% @spec (This::wxFont()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetfacename">external documentation</a>.
+-spec getFaceName(This) -> unicode:charlist() when
+ This::wxFont().
getFaceName(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetFaceName,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> WxFontFamily
-%% WxFontFamily = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetfamily">external documentation</a>.
-%%<br /> WxFontFamily is one of ?wxFONTFAMILY_DEFAULT | ?wxFONTFAMILY_DECORATIVE | ?wxFONTFAMILY_ROMAN | ?wxFONTFAMILY_SCRIPT | ?wxFONTFAMILY_SWISS | ?wxFONTFAMILY_MODERN | ?wxFONTFAMILY_TELETYPE | ?wxFONTFAMILY_MAX | ?wxFONTFAMILY_UNKNOWN
+%%<br /> Res = ?wxFONTFAMILY_DEFAULT | ?wxFONTFAMILY_DECORATIVE | ?wxFONTFAMILY_ROMAN | ?wxFONTFAMILY_SCRIPT | ?wxFONTFAMILY_SWISS | ?wxFONTFAMILY_MODERN | ?wxFONTFAMILY_TELETYPE | ?wxFONTFAMILY_MAX | ?wxFONTFAMILY_UNKNOWN
+-spec getFamily(This) -> wx:wx_enum() when
+ This::wxFont().
getFamily(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetFamily,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetnativefontinfodesc">external documentation</a>.
+-spec getNativeFontInfoDesc(This) -> unicode:charlist() when
+ This::wxFont().
getNativeFontInfoDesc(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetNativeFontInfoDesc,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetnativefontinfouserdesc">external documentation</a>.
+-spec getNativeFontInfoUserDesc(This) -> unicode:charlist() when
+ This::wxFont().
getNativeFontInfoUserDesc(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetNativeFontInfoUserDesc,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetpointsize">external documentation</a>.
+-spec getPointSize(This) -> integer() when
+ This::wxFont().
getPointSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetPointSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> WxFontStyle
-%% WxFontStyle = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetstyle">external documentation</a>.
-%%<br /> WxFontStyle is one of ?wxFONTSTYLE_NORMAL | ?wxFONTSTYLE_ITALIC | ?wxFONTSTYLE_SLANT | ?wxFONTSTYLE_MAX
+%%<br /> Res = ?wxFONTSTYLE_NORMAL | ?wxFONTSTYLE_ITALIC | ?wxFONTSTYLE_SLANT | ?wxFONTSTYLE_MAX
+-spec getStyle(This) -> wx:wx_enum() when
+ This::wxFont().
getStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetunderlined">external documentation</a>.
+-spec getUnderlined(This) -> boolean() when
+ This::wxFont().
getUnderlined(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetUnderlined,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontgetweight">external documentation</a>.
+-spec getWeight(This) -> integer() when
+ This::wxFont().
getWeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_GetWeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFont()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontok">external documentation</a>.
+-spec ok(This) -> boolean() when
+ This::wxFont().
ok(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFont),
wxe_util:call(?wxFont_Ok,
<<ThisRef:32/?UI>>).
-%% @spec (Encoding::WxFontEncoding) -> ok
-%% WxFontEncoding = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetdefaultencoding">external documentation</a>.
-%%<br /> WxFontEncoding is one of ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+%%<br /> Encoding = ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+-spec setDefaultEncoding(Encoding) -> ok when
+ Encoding::wx:wx_enum().
setDefaultEncoding(Encoding)
when is_integer(Encoding) ->
wxe_util:cast(?wxFont_SetDefaultEncoding,
<<Encoding:32/?UI>>).
-%% @spec (This::wxFont(), FaceName::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetfacename">external documentation</a>.
+-spec setFaceName(This, FaceName) -> boolean() when
+ This::wxFont(), FaceName::unicode:chardata().
setFaceName(#wx_ref{type=ThisT,ref=ThisRef},FaceName)
when is_list(FaceName) ->
?CLASS(ThisT,wxFont),
@@ -175,52 +188,55 @@ setFaceName(#wx_ref{type=ThisT,ref=ThisRef},FaceName)
wxe_util:call(?wxFont_SetFaceName,
<<ThisRef:32/?UI,(byte_size(FaceName_UC)):32/?UI,(FaceName_UC)/binary, 0:(((8- ((0+byte_size(FaceName_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxFont(), Family::WxFontFamily) -> ok
-%% WxFontFamily = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetfamily">external documentation</a>.
-%%<br /> WxFontFamily is one of ?wxFONTFAMILY_DEFAULT | ?wxFONTFAMILY_DECORATIVE | ?wxFONTFAMILY_ROMAN | ?wxFONTFAMILY_SCRIPT | ?wxFONTFAMILY_SWISS | ?wxFONTFAMILY_MODERN | ?wxFONTFAMILY_TELETYPE | ?wxFONTFAMILY_MAX | ?wxFONTFAMILY_UNKNOWN
+%%<br /> Family = ?wxFONTFAMILY_DEFAULT | ?wxFONTFAMILY_DECORATIVE | ?wxFONTFAMILY_ROMAN | ?wxFONTFAMILY_SCRIPT | ?wxFONTFAMILY_SWISS | ?wxFONTFAMILY_MODERN | ?wxFONTFAMILY_TELETYPE | ?wxFONTFAMILY_MAX | ?wxFONTFAMILY_UNKNOWN
+-spec setFamily(This, Family) -> ok when
+ This::wxFont(), Family::wx:wx_enum().
setFamily(#wx_ref{type=ThisT,ref=ThisRef},Family)
when is_integer(Family) ->
?CLASS(ThisT,wxFont),
wxe_util:cast(?wxFont_SetFamily,
<<ThisRef:32/?UI,Family:32/?UI>>).
-%% @spec (This::wxFont(), PointSize::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetpointsize">external documentation</a>.
+-spec setPointSize(This, PointSize) -> ok when
+ This::wxFont(), PointSize::integer().
setPointSize(#wx_ref{type=ThisT,ref=ThisRef},PointSize)
when is_integer(PointSize) ->
?CLASS(ThisT,wxFont),
wxe_util:cast(?wxFont_SetPointSize,
<<ThisRef:32/?UI,PointSize:32/?UI>>).
-%% @spec (This::wxFont(), Style::WxFontStyle) -> ok
-%% WxFontStyle = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetstyle">external documentation</a>.
-%%<br /> WxFontStyle is one of ?wxFONTSTYLE_NORMAL | ?wxFONTSTYLE_ITALIC | ?wxFONTSTYLE_SLANT | ?wxFONTSTYLE_MAX
+%%<br /> Style = ?wxFONTSTYLE_NORMAL | ?wxFONTSTYLE_ITALIC | ?wxFONTSTYLE_SLANT | ?wxFONTSTYLE_MAX
+-spec setStyle(This, Style) -> ok when
+ This::wxFont(), Style::wx:wx_enum().
setStyle(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxFont),
wxe_util:cast(?wxFont_SetStyle,
<<ThisRef:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxFont(), Underlined::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetunderlined">external documentation</a>.
+-spec setUnderlined(This, Underlined) -> ok when
+ This::wxFont(), Underlined::boolean().
setUnderlined(#wx_ref{type=ThisT,ref=ThisRef},Underlined)
when is_boolean(Underlined) ->
?CLASS(ThisT,wxFont),
wxe_util:cast(?wxFont_SetUnderlined,
<<ThisRef:32/?UI,(wxe_util:from_bool(Underlined)):32/?UI>>).
-%% @spec (This::wxFont(), Weight::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfont.html#wxfontsetweight">external documentation</a>.
+-spec setWeight(This, Weight) -> ok when
+ This::wxFont(), Weight::integer().
setWeight(#wx_ref{type=ThisT,ref=ThisRef},Weight)
when is_integer(Weight) ->
?CLASS(ThisT,wxFont),
wxe_util:cast(?wxFont_SetWeight,
<<ThisRef:32/?UI,Weight:32/?UI>>).
-%% @spec (This::wxFont()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFont()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFont),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFontData.erl b/lib/wx/src/gen/wxFontData.erl
index 33015b7ca9..978d27b391 100644
--- a/lib/wx/src/gen/wxFontData.erl
+++ b/lib/wx/src/gen/wxFontData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,122 +31,138 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxFontData/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFontData()
+-type wxFontData() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatawxfontdata">external documentation</a>.
+-spec new() -> wxFontData().
new() ->
wxe_util:construct(?wxFontData_new_0,
<<>>).
-%% @spec (Data::wxFontData()) -> wxFontData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatawxfontdata">external documentation</a>.
+-spec new(Data) -> wxFontData() when
+ Data::wxFontData().
new(#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(DataT,wxFontData),
wxe_util:construct(?wxFontData_new_1,
<<DataRef:32/?UI>>).
-%% @spec (This::wxFontData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdataenableeffects">external documentation</a>.
+-spec enableEffects(This, Flag) -> ok when
+ This::wxFontData(), Flag::boolean().
enableEffects(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxFontData),
wxe_util:cast(?wxFontData_EnableEffects,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxFontData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatagetallowsymbols">external documentation</a>.
+-spec getAllowSymbols(This) -> boolean() when
+ This::wxFontData().
getAllowSymbols(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontData),
wxe_util:call(?wxFontData_GetAllowSymbols,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontData()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatagetcolour">external documentation</a>.
+-spec getColour(This) -> wx:wx_colour4() when
+ This::wxFontData().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontData),
wxe_util:call(?wxFontData_GetColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontData()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatagetchosenfont">external documentation</a>.
+-spec getChosenFont(This) -> wxFont:wxFont() when
+ This::wxFontData().
getChosenFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontData),
wxe_util:call(?wxFontData_GetChosenFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatagetenableeffects">external documentation</a>.
+-spec getEnableEffects(This) -> boolean() when
+ This::wxFontData().
getEnableEffects(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontData),
wxe_util:call(?wxFontData_GetEnableEffects,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontData()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatagetinitialfont">external documentation</a>.
+-spec getInitialFont(This) -> wxFont:wxFont() when
+ This::wxFontData().
getInitialFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontData),
wxe_util:call(?wxFontData_GetInitialFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatagetshowhelp">external documentation</a>.
+-spec getShowHelp(This) -> boolean() when
+ This::wxFontData().
getShowHelp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontData),
wxe_util:call(?wxFontData_GetShowHelp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatasetallowsymbols">external documentation</a>.
+-spec setAllowSymbols(This, Flag) -> ok when
+ This::wxFontData(), Flag::boolean().
setAllowSymbols(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxFontData),
wxe_util:cast(?wxFontData_SetAllowSymbols,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxFontData(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatasetchosenfont">external documentation</a>.
+-spec setChosenFont(This, Font) -> ok when
+ This::wxFontData(), Font::wxFont:wxFont().
setChosenFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxFontData),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxFontData_SetChosenFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxFontData(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatasetcolour">external documentation</a>.
+-spec setColour(This, Colour) -> ok when
+ This::wxFontData(), Colour::wx:wx_colour().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxFontData),
wxe_util:cast(?wxFontData_SetColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxFontData(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatasetinitialfont">external documentation</a>.
+-spec setInitialFont(This, Font) -> ok when
+ This::wxFontData(), Font::wxFont:wxFont().
setInitialFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxFontData),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxFontData_SetInitialFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxFontData(), MinRange::integer(), MaxRange::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatasetrange">external documentation</a>.
+-spec setRange(This, MinRange, MaxRange) -> ok when
+ This::wxFontData(), MinRange::integer(), MaxRange::integer().
setRange(#wx_ref{type=ThisT,ref=ThisRef},MinRange,MaxRange)
when is_integer(MinRange),is_integer(MaxRange) ->
?CLASS(ThisT,wxFontData),
wxe_util:cast(?wxFontData_SetRange,
<<ThisRef:32/?UI,MinRange:32/?UI,MaxRange:32/?UI>>).
-%% @spec (This::wxFontData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdata.html#wxfontdatasetshowhelp">external documentation</a>.
+-spec setShowHelp(This, Flag) -> ok when
+ This::wxFontData(), Flag::boolean().
setShowHelp(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxFontData),
wxe_util:cast(?wxFontData_SetShowHelp,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxFontData()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFontData()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFontData),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFontDialog.erl b/lib/wx/src/gen/wxFontDialog.erl
index 357bfe532d..6cc210a4aa 100644
--- a/lib/wx/src/gen/wxFontDialog.erl
+++ b/lib/wx/src/gen/wxFontDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxFontDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,22 +85,25 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFontDialog()
+-type wxFontDialog() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdialog.html#wxfontdialogwxfontdialog">external documentation</a>.
+-spec new() -> wxFontDialog().
new() ->
wxe_util:construct(?wxFontDialog_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Data::wxFontData:wxFontData()) -> wxFontDialog()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdialog.html#wxfontdialogwxfontdialog">external documentation</a>.
+-spec new(Parent, Data) -> wxFontDialog() when
+ Parent::wxWindow:wxWindow(), Data::wxFontData:wxFontData().
new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(ParentT,wxWindow),
?CLASS(DataT,wxFontData),
wxe_util:construct(?wxFontDialog_new_2,
<<ParentRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxFontDialog(), Parent::wxWindow:wxWindow(), Data::wxFontData:wxFontData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdialog.html#wxfontdialogcreate">external documentation</a>.
+-spec create(This, Parent, Data) -> boolean() when
+ This::wxFontDialog(), Parent::wxWindow:wxWindow(), Data::wxFontData:wxFontData().
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(ThisT,wxFontDialog),
?CLASS(ParentT,wxWindow),
@@ -107,15 +111,16 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_r
wxe_util:call(?wxFontDialog_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxFontDialog()) -> wxFontData:wxFontData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontdialog.html#wxfontdialoggetfontdata">external documentation</a>.
+-spec getFontData(This) -> wxFontData:wxFontData() when
+ This::wxFontDialog().
getFontData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontDialog),
wxe_util:call(?wxFontDialog_GetFontData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFontDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFontDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFontPickerCtrl.erl b/lib/wx/src/gen/wxFontPickerCtrl.erl
index 93d63cc930..46c0dbab4d 100644
--- a/lib/wx/src/gen/wxFontPickerCtrl.erl
+++ b/lib/wx/src/gen/wxFontPickerCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -75,6 +75,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxFontPickerCtrl/0]).
%% @hidden
parent_class(wxPickerBase) -> true;
parent_class(wxControl) -> true;
@@ -82,21 +83,29 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFontPickerCtrl()
+-type wxFontPickerCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlwxfontpickerctrl">external documentation</a>.
+-spec new() -> wxFontPickerCtrl().
new() ->
wxe_util:construct(?wxFontPickerCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxFontPickerCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxFontPickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxFontPickerCtrl()
-%% Option = {initial, wxFont:wxFont()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlwxfontpickerctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxFontPickerCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {initial, wxFont:wxFont()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -110,15 +119,22 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxFontPickerCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxFontPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxFontPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxFontPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {initial, wxFont:wxFont()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxFontPickerCtrl(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {initial, wxFont:wxFont()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxFontPickerCtrl),
@@ -133,38 +149,42 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxFontPickerCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxFontPickerCtrl()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlgetselectedfont">external documentation</a>.
+-spec getSelectedFont(This) -> wxFont:wxFont() when
+ This::wxFontPickerCtrl().
getSelectedFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontPickerCtrl),
wxe_util:call(?wxFontPickerCtrl_GetSelectedFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontPickerCtrl(), F::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlsetselectedfont">external documentation</a>.
+-spec setSelectedFont(This, F) -> ok when
+ This::wxFontPickerCtrl(), F::wxFont:wxFont().
setSelectedFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FT,ref=FRef}) ->
?CLASS(ThisT,wxFontPickerCtrl),
?CLASS(FT,wxFont),
wxe_util:cast(?wxFontPickerCtrl_SetSelectedFont,
<<ThisRef:32/?UI,FRef:32/?UI>>).
-%% @spec (This::wxFontPickerCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlgetmaxpointsize">external documentation</a>.
+-spec getMaxPointSize(This) -> integer() when
+ This::wxFontPickerCtrl().
getMaxPointSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontPickerCtrl),
wxe_util:call(?wxFontPickerCtrl_GetMaxPointSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFontPickerCtrl(), Max::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerctrl.html#wxfontpickerctrlsetmaxpointsize">external documentation</a>.
+-spec setMaxPointSize(This, Max) -> ok when
+ This::wxFontPickerCtrl(), Max::integer().
setMaxPointSize(#wx_ref{type=ThisT,ref=ThisRef},Max)
when is_integer(Max) ->
?CLASS(ThisT,wxFontPickerCtrl),
wxe_util:cast(?wxFontPickerCtrl_SetMaxPointSize,
<<ThisRef:32/?UI,Max:32/?UI>>).
-%% @spec (This::wxFontPickerCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFontPickerCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFontPickerCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxFontPickerEvent.erl b/lib/wx/src/gen/wxFontPickerEvent.erl
index 6eb456767f..2dc3606409 100644
--- a/lib/wx/src/gen/wxFontPickerEvent.erl
+++ b/lib/wx/src/gen/wxFontPickerEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,16 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxFontPickerEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxFontPickerEvent()) -> wxFont:wxFont()
+-type wxFontPickerEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfontpickerevent.html#wxfontpickereventgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxFontPickerEvent().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFontPickerEvent),
wxe_util:call(?wxFontPickerEvent_GetFont,
diff --git a/lib/wx/src/gen/wxFrame.erl b/lib/wx/src/gen/wxFrame.erl
index 5cd1e3dfd3..61f46f7a07 100644
--- a/lib/wx/src/gen/wxFrame.erl
+++ b/lib/wx/src/gen/wxFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,27 +78,34 @@
showFullScreen/3,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxFrame/0]).
%% @hidden
parent_class(wxTopLevelWindow) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxFrame()
+-type wxFrame() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframewxframe">external documentation</a>.
+-spec new() -> wxFrame().
new() ->
wxe_util:construct(?wxFrame_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> wxFrame()
%% @equiv new(Parent,Id,Title, [])
+-spec new(Parent, Id, Title) -> wxFrame() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
new(Parent,Id,Title)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
new(Parent,Id,Title, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframewxframe">external documentation</a>.
+-spec new(Parent, Id, Title, [Option]) -> wxFrame() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -111,15 +118,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
wxe_util:construct(?wxFrame_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> bool()
%% @equiv create(This,Parent,Id,Title, [])
+-spec create(This, Parent, Id, Title) -> boolean() when
+ This::wxFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
create(This,Parent,Id,Title)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
create(This,Parent,Id,Title, []).
-%% @spec (This::wxFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframecreate">external documentation</a>.
+-spec create(This, Parent, Id, Title, [Option]) -> boolean() when
+ This::wxFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ThisT,wxFrame),
@@ -133,15 +145,20 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ti
wxe_util:call(?wxFrame_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxFrame()) -> wxStatusBar:wxStatusBar()
%% @equiv createStatusBar(This, [])
+-spec createStatusBar(This) -> wxStatusBar:wxStatusBar() when
+ This::wxFrame().
+
createStatusBar(This)
when is_record(This, wx_ref) ->
createStatusBar(This, []).
-%% @spec (This::wxFrame(), [Option]) -> wxStatusBar:wxStatusBar()
-%% Option = {number, integer()} | {style, integer()} | {id, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframecreatestatusbar">external documentation</a>.
+-spec createStatusBar(This, [Option]) -> wxStatusBar:wxStatusBar() when
+ This::wxFrame(),
+ Option :: {number, integer()}
+ | {style, integer()}
+ | {id, integer()}.
createStatusBar(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxFrame),
@@ -153,15 +170,19 @@ createStatusBar(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxFrame_CreateStatusBar,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxFrame()) -> wxToolBar:wxToolBar()
%% @equiv createToolBar(This, [])
+-spec createToolBar(This) -> wxToolBar:wxToolBar() when
+ This::wxFrame().
+
createToolBar(This)
when is_record(This, wx_ref) ->
createToolBar(This, []).
-%% @spec (This::wxFrame(), [Option]) -> wxToolBar:wxToolBar()
-%% Option = {style, integer()} | {id, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframecreatetoolbar">external documentation</a>.
+-spec createToolBar(This, [Option]) -> wxToolBar:wxToolBar() when
+ This::wxFrame(),
+ Option :: {style, integer()}
+ | {id, integer()}.
createToolBar(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxFrame),
@@ -172,89 +193,102 @@ createToolBar(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxFrame_CreateToolBar,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxFrame()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframegetclientareaorigin">external documentation</a>.
+-spec getClientAreaOrigin(This) -> {X::integer(), Y::integer()} when
+ This::wxFrame().
getClientAreaOrigin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
wxe_util:call(?wxFrame_GetClientAreaOrigin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFrame()) -> wxMenuBar:wxMenuBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframegetmenubar">external documentation</a>.
+-spec getMenuBar(This) -> wxMenuBar:wxMenuBar() when
+ This::wxFrame().
getMenuBar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
wxe_util:call(?wxFrame_GetMenuBar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFrame()) -> wxStatusBar:wxStatusBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframegetstatusbar">external documentation</a>.
+-spec getStatusBar(This) -> wxStatusBar:wxStatusBar() when
+ This::wxFrame().
getStatusBar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
wxe_util:call(?wxFrame_GetStatusBar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFrame()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframegetstatusbarpane">external documentation</a>.
+-spec getStatusBarPane(This) -> integer() when
+ This::wxFrame().
getStatusBarPane(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
wxe_util:call(?wxFrame_GetStatusBarPane,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFrame()) -> wxToolBar:wxToolBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframegettoolbar">external documentation</a>.
+-spec getToolBar(This) -> wxToolBar:wxToolBar() when
+ This::wxFrame().
getToolBar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
wxe_util:call(?wxFrame_GetToolBar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFrame(), Winid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframeprocesscommand">external documentation</a>.
+-spec processCommand(This, Winid) -> boolean() when
+ This::wxFrame(), Winid::integer().
processCommand(#wx_ref{type=ThisT,ref=ThisRef},Winid)
when is_integer(Winid) ->
?CLASS(ThisT,wxFrame),
wxe_util:call(?wxFrame_ProcessCommand,
<<ThisRef:32/?UI,Winid:32/?UI>>).
-%% @spec (This::wxFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesendsizeevent">external documentation</a>.
+-spec sendSizeEvent(This) -> ok when
+ This::wxFrame().
sendSizeEvent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxFrame),
wxe_util:cast(?wxFrame_SendSizeEvent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxFrame(), Menubar::wxMenuBar:wxMenuBar()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesetmenubar">external documentation</a>.
+-spec setMenuBar(This, Menubar) -> ok when
+ This::wxFrame(), Menubar::wxMenuBar:wxMenuBar().
setMenuBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenubarT,ref=MenubarRef}) ->
?CLASS(ThisT,wxFrame),
?CLASS(MenubarT,wxMenuBar),
wxe_util:cast(?wxFrame_SetMenuBar,
<<ThisRef:32/?UI,MenubarRef:32/?UI>>).
-%% @spec (This::wxFrame(), Statbar::wxStatusBar:wxStatusBar()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesetstatusbar">external documentation</a>.
+-spec setStatusBar(This, Statbar) -> ok when
+ This::wxFrame(), Statbar::wxStatusBar:wxStatusBar().
setStatusBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=StatbarT,ref=StatbarRef}) ->
?CLASS(ThisT,wxFrame),
?CLASS(StatbarT,wxStatusBar),
wxe_util:cast(?wxFrame_SetStatusBar,
<<ThisRef:32/?UI,StatbarRef:32/?UI>>).
-%% @spec (This::wxFrame(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesetstatusbarpane">external documentation</a>.
+-spec setStatusBarPane(This, N) -> ok when
+ This::wxFrame(), N::integer().
setStatusBarPane(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxFrame),
wxe_util:cast(?wxFrame_SetStatusBarPane,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxFrame(), Text::string()) -> ok
%% @equiv setStatusText(This,Text, [])
+-spec setStatusText(This, Text) -> ok when
+ This::wxFrame(), Text::unicode:chardata().
+
setStatusText(This,Text)
when is_record(This, wx_ref),is_list(Text) ->
setStatusText(This,Text, []).
-%% @spec (This::wxFrame(), Text::string(), [Option]) -> ok
-%% Option = {number, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesetstatustext">external documentation</a>.
+-spec setStatusText(This, Text, [Option]) -> ok when
+ This::wxFrame(), Text::unicode:chardata(),
+ Option :: {number, integer()}.
setStatusText(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxFrame),
@@ -265,8 +299,9 @@ setStatusText(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
wxe_util:cast(?wxFrame_SetStatusText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxFrame(), Widths_field::[integer()]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesetstatuswidths">external documentation</a>.
+-spec setStatusWidths(This, Widths_field) -> ok when
+ This::wxFrame(), Widths_field::[integer()].
setStatusWidths(#wx_ref{type=ThisT,ref=ThisRef},Widths_field)
when is_list(Widths_field) ->
?CLASS(ThisT,wxFrame),
@@ -274,16 +309,17 @@ setStatusWidths(#wx_ref{type=ThisT,ref=ThisRef},Widths_field)
<<ThisRef:32/?UI,(length(Widths_field)):32/?UI,
(<< <<C:32/?I>> || C <- Widths_field>>)/binary, 0:(((0+length(Widths_field)) rem 2)*32)>>).
-%% @spec (This::wxFrame(), Toolbar::wxToolBar:wxToolBar()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxframe.html#wxframesettoolbar">external documentation</a>.
+-spec setToolBar(This, Toolbar) -> ok when
+ This::wxFrame(), Toolbar::wxToolBar:wxToolBar().
setToolBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ToolbarT,ref=ToolbarRef}) ->
?CLASS(ThisT,wxFrame),
?CLASS(ToolbarT,wxToolBar),
wxe_util:cast(?wxFrame_SetToolBar,
<<ThisRef:32/?UI,ToolbarRef:32/?UI>>).
-%% @spec (This::wxFrame()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxFrame()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxFrame),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxGBSizerItem.erl b/lib/wx/src/gen/wxGBSizerItem.erl
index 90dd98fdf2..1860e5f808 100644
--- a/lib/wx/src/gen/wxGBSizerItem.erl
+++ b/lib/wx/src/gen/wxGBSizerItem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,12 @@
setMinSize/2,setMinSize/3,setProportion/2,setRatio/2,setRatio/3,setSizer/2,
setSpacer/2,setSpacer/3,setWindow/2,show/2]).
+-export_type([wxGBSizerItem/0]).
%% @hidden
parent_class(wxSizerItem) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxGBSizerItem() :: wx:wx_object().
%% From wxSizerItem
%% @hidden
show(This,Show) -> wxSizerItem:show(This,Show).
diff --git a/lib/wx/src/gen/wxGLCanvas.erl b/lib/wx/src/gen/wxGLCanvas.erl
index 032d42535d..46168374af 100644
--- a/lib/wx/src/gen/wxGLCanvas.erl
+++ b/lib/wx/src/gen/wxGLCanvas.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +68,44 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxGLCanvas/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxGLCanvas()
+-type wxGLCanvas() :: wx:wx_object().
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxGLCanvas() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(),X::term()) -> wxGLCanvas()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html#wxglcanvaswxglcanvas">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Parent::wxWindow:wxWindow(), Shared::wxGLContext:wxGLContext() | wxGLCanvas()) -> new(Parent,Shared, []) </c></p>
-%% <p><c>
-%% new(Parent::wxWindow:wxWindow(), [Option]) -> wxGLCanvas() </c>
-%%<br /> Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {name, string()} | {attribList, [integer()]} | {palette, wxPalette:wxPalette()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Parent, [Option]) -> wxGLCanvas() when<br />
+%% Parent::wxWindow:wxWindow(),<br />
+%% Option :: {id, integer()}<br />
+%% | {pos, {X::integer(), Y::integer()}}<br />
+%% | {size, {W::integer(), H::integer()}}<br />
+%% | {style, integer()}<br />
+%% | {name, unicode:chardata()}<br />
+%% | {attribList, [integer()]}<br />
+%% | {palette, wxPalette:wxPalette()}.<br />
+%%
+-spec new(Parent, Shared) -> wxGLCanvas() when
+ Parent::wxWindow:wxWindow(), Shared::wx:wx_object() | wxGLCanvas();
+ (Parent, [Option]) -> wxGLCanvas() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {name, unicode:chardata()}
+ | {attribList, [integer()]}
+ | {palette, wxPalette:wxPalette()}.
new(Parent,Shared)
when is_record(Parent, wx_ref),is_record(Shared, wx_ref) ->
@@ -108,9 +126,16 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxGLCanvas_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Parent::wxWindow:wxWindow(), Shared::wxGLContext:wxGLContext() | wxGLCanvas(), [Option]) -> wxGLCanvas()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {name, string()} | {attribList, [integer()]} | {palette, wxPalette:wxPalette()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html#wxglcanvaswxglcanvas">external documentation</a>.
+-spec new(Parent, Shared, [Option]) -> wxGLCanvas() when
+ Parent::wxWindow:wxWindow(), Shared::wx:wx_object() | wxGLCanvas(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {name, unicode:chardata()}
+ | {attribList, [integer()]}
+ | {palette, wxPalette:wxPalette()}.
new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=SharedT,ref=SharedRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -133,15 +158,17 @@ new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=SharedT,ref=SharedRef}, Opt
wxe_util:construct(SharedOP,
<<ParentRef:32/?UI,SharedRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGLCanvas()) -> wxGLContext:wxGLContext()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html#wxglcanvasgetcontext">external documentation</a>.
+-spec getContext(This) -> wx:wx_object() when
+ This::wxGLCanvas().
getContext(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGLCanvas),
wxe_util:call(?wxGLCanvas_GetContext,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGLCanvas()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html#wxglcanvassetcurrent">external documentation</a>.
+-spec setCurrent(This) -> ok when
+ This::wxGLCanvas().
setCurrent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGLCanvas),
_Result = wxe_util:cast(?wxGLCanvas_SetCurrent,
@@ -149,15 +176,16 @@ setCurrent(#wx_ref{type=ThisT,ref=ThisRef}) ->
{ok, _} = wxe_master:init_opengl(),
_Result.
-%% @spec (This::wxGLCanvas()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxglcanvas.html#wxglcanvasswapbuffers">external documentation</a>.
+-spec swapBuffers(This) -> ok when
+ This::wxGLCanvas().
swapBuffers(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGLCanvas),
wxe_util:cast(?wxGLCanvas_SwapBuffers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGLCanvas()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGLCanvas()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGLCanvas),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxGauge.erl b/lib/wx/src/gen/wxGauge.erl
index 5028b29bba..7f892355c7 100644
--- a/lib/wx/src/gen/wxGauge.erl
+++ b/lib/wx/src/gen/wxGauge.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -71,27 +71,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxGauge/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGauge()
+-type wxGauge() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugewxgauge">external documentation</a>.
+-spec new() -> wxGauge().
new() ->
wxe_util:construct(?wxGauge_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Range::integer()) -> wxGauge()
%% @equiv new(Parent,Id,Range, [])
+-spec new(Parent, Id, Range) -> wxGauge() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Range::integer().
+
new(Parent,Id,Range)
when is_record(Parent, wx_ref),is_integer(Id),is_integer(Range) ->
new(Parent,Id,Range, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Range::integer(), [Option]) -> wxGauge()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugewxgauge">external documentation</a>.
+-spec new(Parent, Id, Range, [Option]) -> wxGauge() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Range::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Range, Options)
when is_integer(Id),is_integer(Range),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -104,15 +112,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Range, Options)
wxe_util:construct(?wxGauge_new_4,
<<ParentRef:32/?UI,Id:32/?UI,Range:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGauge(), Parent::wxWindow:wxWindow(), Id::integer(), Range::integer()) -> bool()
%% @equiv create(This,Parent,Id,Range, [])
+-spec create(This, Parent, Id, Range) -> boolean() when
+ This::wxGauge(), Parent::wxWindow:wxWindow(), Id::integer(), Range::integer().
+
create(This,Parent,Id,Range)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_integer(Range) ->
create(This,Parent,Id,Range, []).
-%% @spec (This::wxGauge(), Parent::wxWindow:wxWindow(), Id::integer(), Range::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugecreate">external documentation</a>.
+-spec create(This, Parent, Id, Range, [Option]) -> boolean() when
+ This::wxGauge(), Parent::wxWindow:wxWindow(), Id::integer(), Range::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Range, Options)
when is_integer(Id),is_integer(Range),is_list(Options) ->
?CLASS(ThisT,wxGauge),
@@ -126,82 +140,92 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ra
wxe_util:call(?wxGauge_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,Range:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGauge()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugegetbezelface">external documentation</a>.
+-spec getBezelFace(This) -> integer() when
+ This::wxGauge().
getBezelFace(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGauge),
wxe_util:call(?wxGauge_GetBezelFace,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGauge()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugegetrange">external documentation</a>.
+-spec getRange(This) -> integer() when
+ This::wxGauge().
getRange(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGauge),
wxe_util:call(?wxGauge_GetRange,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGauge()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugegetshadowwidth">external documentation</a>.
+-spec getShadowWidth(This) -> integer() when
+ This::wxGauge().
getShadowWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGauge),
wxe_util:call(?wxGauge_GetShadowWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGauge()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugegetvalue">external documentation</a>.
+-spec getValue(This) -> integer() when
+ This::wxGauge().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGauge),
wxe_util:call(?wxGauge_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGauge()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugeisvertical">external documentation</a>.
+-spec isVertical(This) -> boolean() when
+ This::wxGauge().
isVertical(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGauge),
wxe_util:call(?wxGauge_IsVertical,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGauge(), W::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugesetbezelface">external documentation</a>.
+-spec setBezelFace(This, W) -> ok when
+ This::wxGauge(), W::integer().
setBezelFace(#wx_ref{type=ThisT,ref=ThisRef},W)
when is_integer(W) ->
?CLASS(ThisT,wxGauge),
wxe_util:cast(?wxGauge_SetBezelFace,
<<ThisRef:32/?UI,W:32/?UI>>).
-%% @spec (This::wxGauge(), R::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugesetrange">external documentation</a>.
+-spec setRange(This, R) -> ok when
+ This::wxGauge(), R::integer().
setRange(#wx_ref{type=ThisT,ref=ThisRef},R)
when is_integer(R) ->
?CLASS(ThisT,wxGauge),
wxe_util:cast(?wxGauge_SetRange,
<<ThisRef:32/?UI,R:32/?UI>>).
-%% @spec (This::wxGauge(), W::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugesetshadowwidth">external documentation</a>.
+-spec setShadowWidth(This, W) -> ok when
+ This::wxGauge(), W::integer().
setShadowWidth(#wx_ref{type=ThisT,ref=ThisRef},W)
when is_integer(W) ->
?CLASS(ThisT,wxGauge),
wxe_util:cast(?wxGauge_SetShadowWidth,
<<ThisRef:32/?UI,W:32/?UI>>).
-%% @spec (This::wxGauge(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugesetvalue">external documentation</a>.
+-spec setValue(This, Pos) -> ok when
+ This::wxGauge(), Pos::integer().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxGauge),
wxe_util:cast(?wxGauge_SetValue,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxGauge()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgauge.html#wxgaugepulse">external documentation</a>.
+-spec pulse(This) -> ok when
+ This::wxGauge().
pulse(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGauge),
wxe_util:cast(?wxGauge_Pulse,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGauge()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGauge()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGauge),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxGenericDirCtrl.erl b/lib/wx/src/gen/wxGenericDirCtrl.erl
index 97944710f0..cb917e8fd1 100644
--- a/lib/wx/src/gen/wxGenericDirCtrl.erl
+++ b/lib/wx/src/gen/wxGenericDirCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +72,38 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxGenericDirCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGenericDirCtrl()
+-type wxGenericDirCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlwxgenericdirctrl">external documentation</a>.
+-spec new() -> wxGenericDirCtrl().
new() ->
wxe_util:construct(?wxGenericDirCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxGenericDirCtrl()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxGenericDirCtrl() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxGenericDirCtrl()
-%% Option = {id, integer()} | {dir, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {filter, string()} | {defaultFilter, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlwxgenericdirctrl">external documentation</a>.
+-spec new(Parent, [Option]) -> wxGenericDirCtrl() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {dir, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {filter, unicode:chardata()}
+ | {defaultFilter, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -108,15 +119,24 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxGenericDirCtrl_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGenericDirCtrl(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxGenericDirCtrl(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxGenericDirCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {dir, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {filter, string()} | {defaultFilter, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxGenericDirCtrl(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {dir, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {filter, unicode:chardata()}
+ | {defaultFilter, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGenericDirCtrl),
@@ -133,22 +153,25 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxGenericDirCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGenericDirCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlinit">external documentation</a>.
+-spec init(This) -> ok when
+ This::wxGenericDirCtrl().
init(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:cast(?wxGenericDirCtrl_Init,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlcollapsetree">external documentation</a>.
+-spec collapseTree(This) -> ok when
+ This::wxGenericDirCtrl().
collapseTree(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:cast(?wxGenericDirCtrl_CollapseTree,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl(), Path::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlexpandpath">external documentation</a>.
+-spec expandPath(This, Path) -> boolean() when
+ This::wxGenericDirCtrl(), Path::unicode:chardata().
expandPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
when is_list(Path) ->
?CLASS(ThisT,wxGenericDirCtrl),
@@ -156,64 +179,73 @@ expandPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
wxe_util:call(?wxGenericDirCtrl_ExpandPath,
<<ThisRef:32/?UI,(byte_size(Path_UC)):32/?UI,(Path_UC)/binary, 0:(((8- ((0+byte_size(Path_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGenericDirCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgetdefaultpath">external documentation</a>.
+-spec getDefaultPath(This) -> unicode:charlist() when
+ This::wxGenericDirCtrl().
getDefaultPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetDefaultPath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgetpath">external documentation</a>.
+-spec getPath(This) -> unicode:charlist() when
+ This::wxGenericDirCtrl().
getPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetPath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgetfilepath">external documentation</a>.
+-spec getFilePath(This) -> unicode:charlist() when
+ This::wxGenericDirCtrl().
getFilePath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetFilePath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgetfilter">external documentation</a>.
+-spec getFilter(This) -> unicode:charlist() when
+ This::wxGenericDirCtrl().
getFilter(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetFilter,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgetfilterindex">external documentation</a>.
+-spec getFilterIndex(This) -> integer() when
+ This::wxGenericDirCtrl().
getFilterIndex(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetFilterIndex,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgetrootid">external documentation</a>.
+-spec getRootId(This) -> integer() when
+ This::wxGenericDirCtrl().
getRootId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetRootId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> wxTreeCtrl:wxTreeCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlgettreectrl">external documentation</a>.
+-spec getTreeCtrl(This) -> wxTreeCtrl:wxTreeCtrl() when
+ This::wxGenericDirCtrl().
getTreeCtrl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:call(?wxGenericDirCtrl_GetTreeCtrl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlrecreatetree">external documentation</a>.
+-spec reCreateTree(This) -> ok when
+ This::wxGenericDirCtrl().
reCreateTree(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:cast(?wxGenericDirCtrl_ReCreateTree,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl(), Path::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlsetdefaultpath">external documentation</a>.
+-spec setDefaultPath(This, Path) -> ok when
+ This::wxGenericDirCtrl(), Path::unicode:chardata().
setDefaultPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
when is_list(Path) ->
?CLASS(ThisT,wxGenericDirCtrl),
@@ -221,8 +253,9 @@ setDefaultPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
wxe_util:cast(?wxGenericDirCtrl_SetDefaultPath,
<<ThisRef:32/?UI,(byte_size(Path_UC)):32/?UI,(Path_UC)/binary, 0:(((8- ((0+byte_size(Path_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGenericDirCtrl(), Filter::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlsetfilter">external documentation</a>.
+-spec setFilter(This, Filter) -> ok when
+ This::wxGenericDirCtrl(), Filter::unicode:chardata().
setFilter(#wx_ref{type=ThisT,ref=ThisRef},Filter)
when is_list(Filter) ->
?CLASS(ThisT,wxGenericDirCtrl),
@@ -230,16 +263,18 @@ setFilter(#wx_ref{type=ThisT,ref=ThisRef},Filter)
wxe_util:cast(?wxGenericDirCtrl_SetFilter,
<<ThisRef:32/?UI,(byte_size(Filter_UC)):32/?UI,(Filter_UC)/binary, 0:(((8- ((0+byte_size(Filter_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGenericDirCtrl(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlsetfilterindex">external documentation</a>.
+-spec setFilterIndex(This, N) -> ok when
+ This::wxGenericDirCtrl(), N::integer().
setFilterIndex(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxGenericDirCtrl),
wxe_util:cast(?wxGenericDirCtrl_SetFilterIndex,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxGenericDirCtrl(), Path::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgenericdirctrl.html#wxgenericdirctrlsetpath">external documentation</a>.
+-spec setPath(This, Path) -> ok when
+ This::wxGenericDirCtrl(), Path::unicode:chardata().
setPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
when is_list(Path) ->
?CLASS(ThisT,wxGenericDirCtrl),
@@ -247,8 +282,8 @@ setPath(#wx_ref{type=ThisT,ref=ThisRef},Path)
wxe_util:cast(?wxGenericDirCtrl_SetPath,
<<ThisRef:32/?UI,(byte_size(Path_UC)):32/?UI,(Path_UC)/binary, 0:(((8- ((0+byte_size(Path_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGenericDirCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGenericDirCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGenericDirCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxGraphicsBrush.erl b/lib/wx/src/gen/wxGraphicsBrush.erl
index e1ad01567d..bbc0c4b1a0 100644
--- a/lib/wx/src/gen/wxGraphicsBrush.erl
+++ b/lib/wx/src/gen/wxGraphicsBrush.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +32,12 @@
%% inherited exports
-export([getRenderer/1,isNull/1,parent_class/1]).
+-export_type([wxGraphicsBrush/0]).
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxGraphicsBrush() :: wx:wx_object().
%% From wxGraphicsObject
%% @hidden
isNull(This) -> wxGraphicsObject:isNull(This).
diff --git a/lib/wx/src/gen/wxGraphicsContext.erl b/lib/wx/src/gen/wxGraphicsContext.erl
index 040867cb11..1dfa0dd405 100644
--- a/lib/wx/src/gen/wxGraphicsContext.erl
+++ b/lib/wx/src/gen/wxGraphicsContext.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,29 +29,31 @@
-include("wxe.hrl").
-export([clip/2,clip/5,concatTransform/2,create/0,create/1,createBrush/2,createFont/2,
createFont/3,createLinearGradientBrush/7,createMatrix/1,createMatrix/2,
- createPath/1,createPen/2,createRadialGradientBrush/8,drawBitmap/6,
- drawEllipse/5,drawIcon/6,drawLines/3,drawLines/4,drawPath/2,drawPath/3,
+ createPath/1,createPen/2,createRadialGradientBrush/8,destroy/1,drawBitmap/6,
+ drawEllipse/5,drawIcon/6,drawLines/2,drawLines/3,drawPath/2,drawPath/3,
drawRectangle/5,drawRoundedRectangle/6,drawText/4,drawText/5,drawText/6,
- fillPath/2,fillPath/3,getNativeContext/1,getPartialTextExtents/3,
- getTextExtent/2,getTransform/1,resetClip/1,rotate/2,scale/3,setBrush/2,
- setFont/2,setFont/3,setPen/2,setTransform/2,strokeLine/5,strokeLines/3,
- strokeLines/4,strokePath/2,translate/3]).
+ fillPath/2,fillPath/3,getPartialTextExtents/2,getTextExtent/2,getTransform/1,
+ resetClip/1,rotate/2,scale/3,setBrush/2,setFont/2,setFont/3,setPen/2,
+ setTransform/2,strokeLine/5,strokeLines/2,strokePath/2,translate/3]).
%% inherited exports
-export([getRenderer/1,isNull/1,parent_class/1]).
+-export_type([wxGraphicsContext/0]).
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGraphicsContext()
+-type wxGraphicsContext() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreate">external documentation</a>.
+-spec create() -> wxGraphicsContext().
create() ->
wxe_util:call(?wxGraphicsContext_Create_0,
<<>>).
-%% @spec (Dc::wxWindowDC:wxWindowDC() | wxWindow:wxWindow()) -> wxGraphicsContext()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreate">external documentation</a>.
+-spec create(Dc) -> wxGraphicsContext() when
+ Dc::wxWindowDC:wxWindowDC() | wxWindow:wxWindow().
create(#wx_ref{type=DcT,ref=DcRef}) ->
DcOP = case ?CLASS_T(DcT,wxWindowDC) of
true ->
@@ -62,47 +64,54 @@ create(#wx_ref{type=DcT,ref=DcRef}) ->
wxe_util:call(DcOP,
<<DcRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Pen::wxPen:wxPen()) -> wxGraphicsPen:wxGraphicsPen()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreatepen">external documentation</a>.
+-spec createPen(This, Pen) -> wxGraphicsPen:wxGraphicsPen() when
+ This::wxGraphicsContext(), Pen::wxPen:wxPen().
createPen(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PenT,ref=PenRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(PenT,wxPen),
wxe_util:call(?wxGraphicsContext_CreatePen,
<<ThisRef:32/?UI,PenRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Brush::wxBrush:wxBrush()) -> wxGraphicsBrush:wxGraphicsBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreatebrush">external documentation</a>.
+-spec createBrush(This, Brush) -> wxGraphicsBrush:wxGraphicsBrush() when
+ This::wxGraphicsContext(), Brush::wxBrush:wxBrush().
createBrush(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(BrushT,wxBrush),
wxe_util:call(?wxGraphicsContext_CreateBrush,
<<ThisRef:32/?UI,BrushRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Xo::float(), Yo::float(), Xc::float(), Yc::float(), Radius::float(), OColor::wx:colour(), CColor::wx:colour()) -> wxGraphicsBrush:wxGraphicsBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreateradialgradientbrush">external documentation</a>.
+-spec createRadialGradientBrush(This, Xo, Yo, Xc, Yc, Radius, OColor, CColor) -> wxGraphicsBrush:wxGraphicsBrush() when
+ This::wxGraphicsContext(), Xo::number(), Yo::number(), Xc::number(), Yc::number(), Radius::number(), OColor::wx:wx_colour(), CColor::wx:wx_colour().
createRadialGradientBrush(#wx_ref{type=ThisT,ref=ThisRef},Xo,Yo,Xc,Yc,Radius,OColor,CColor)
- when is_float(Xo),is_float(Yo),is_float(Xc),is_float(Yc),is_float(Radius),tuple_size(OColor) =:= 3; tuple_size(OColor) =:= 4,tuple_size(CColor) =:= 3; tuple_size(CColor) =:= 4 ->
+ when is_number(Xo),is_number(Yo),is_number(Xc),is_number(Yc),is_number(Radius),tuple_size(OColor) =:= 3; tuple_size(OColor) =:= 4,tuple_size(CColor) =:= 3; tuple_size(CColor) =:= 4 ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:call(?wxGraphicsContext_CreateRadialGradientBrush,
<<ThisRef:32/?UI,0:32,Xo:64/?F,Yo:64/?F,Xc:64/?F,Yc:64/?F,Radius:64/?F,(wxe_util:colour_bin(OColor)):16/binary,(wxe_util:colour_bin(CColor)):16/binary>>).
-%% @spec (This::wxGraphicsContext(), X1::float(), Y1::float(), X2::float(), Y2::float(), C1::wx:colour(), C2::wx:colour()) -> wxGraphicsBrush:wxGraphicsBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreatelineargradientbrush">external documentation</a>.
+-spec createLinearGradientBrush(This, X1, Y1, X2, Y2, C1, C2) -> wxGraphicsBrush:wxGraphicsBrush() when
+ This::wxGraphicsContext(), X1::number(), Y1::number(), X2::number(), Y2::number(), C1::wx:wx_colour(), C2::wx:wx_colour().
createLinearGradientBrush(#wx_ref{type=ThisT,ref=ThisRef},X1,Y1,X2,Y2,C1,C2)
- when is_float(X1),is_float(Y1),is_float(X2),is_float(Y2),tuple_size(C1) =:= 3; tuple_size(C1) =:= 4,tuple_size(C2) =:= 3; tuple_size(C2) =:= 4 ->
+ when is_number(X1),is_number(Y1),is_number(X2),is_number(Y2),tuple_size(C1) =:= 3; tuple_size(C1) =:= 4,tuple_size(C2) =:= 3; tuple_size(C2) =:= 4 ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:call(?wxGraphicsContext_CreateLinearGradientBrush,
<<ThisRef:32/?UI,0:32,X1:64/?F,Y1:64/?F,X2:64/?F,Y2:64/?F,(wxe_util:colour_bin(C1)):16/binary,(wxe_util:colour_bin(C2)):16/binary>>).
-%% @spec (This::wxGraphicsContext(), Font::wxFont:wxFont()) -> wxGraphicsFont:wxGraphicsFont()
%% @equiv createFont(This,Font, [])
+-spec createFont(This, Font) -> wxGraphicsFont:wxGraphicsFont() when
+ This::wxGraphicsContext(), Font::wxFont:wxFont().
+
createFont(This,Font)
when is_record(This, wx_ref),is_record(Font, wx_ref) ->
createFont(This,Font, []).
-%% @spec (This::wxGraphicsContext(), Font::wxFont:wxFont(), [Option]) -> wxGraphicsFont:wxGraphicsFont()
-%% Option = {col, wx:colour()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreatefont">external documentation</a>.
+-spec createFont(This, Font, [Option]) -> wxGraphicsFont:wxGraphicsFont() when
+ This::wxGraphicsContext(), Font::wxFont:wxFont(),
+ Option :: {col, wx:wx_colour()}.
createFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsContext),
@@ -113,15 +122,23 @@ createFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}, Opti
wxe_util:call(?wxGraphicsContext_CreateFont,
<<ThisRef:32/?UI,FontRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGraphicsContext()) -> wxGraphicsMatrix:wxGraphicsMatrix()
%% @equiv createMatrix(This, [])
+-spec createMatrix(This) -> wxGraphicsMatrix:wxGraphicsMatrix() when
+ This::wxGraphicsContext().
+
createMatrix(This)
when is_record(This, wx_ref) ->
createMatrix(This, []).
-%% @spec (This::wxGraphicsContext(), [Option]) -> wxGraphicsMatrix:wxGraphicsMatrix()
-%% Option = {a, float()} | {b, float()} | {c, float()} | {d, float()} | {tx, float()} | {ty, float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreatematrix">external documentation</a>.
+-spec createMatrix(This, [Option]) -> wxGraphicsMatrix:wxGraphicsMatrix() when
+ This::wxGraphicsContext(),
+ Option :: {a, number()}
+ | {b, number()}
+ | {c, number()}
+ | {d, number()}
+ | {tx, number()}
+ | {ty, number()}.
createMatrix(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsContext),
@@ -136,89 +153,103 @@ createMatrix(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGraphicsContext_CreateMatrix,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGraphicsContext()) -> wxGraphicsPath:wxGraphicsPath()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextcreatepath">external documentation</a>.
+-spec createPath(This) -> wxGraphicsPath:wxGraphicsPath() when
+ This::wxGraphicsContext().
createPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:call(?wxGraphicsContext_CreatePath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Region::wxRegion:wxRegion()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextclip">external documentation</a>.
+-spec clip(This, Region) -> ok when
+ This::wxGraphicsContext(), Region::wxRegion:wxRegion().
clip(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(RegionT,wxRegion),
wxe_util:cast(?wxGraphicsContext_Clip_1,
<<ThisRef:32/?UI,RegionRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextclip">external documentation</a>.
+-spec clip(This, X, Y, W, H) -> ok when
+ This::wxGraphicsContext(), X::number(), Y::number(), W::number(), H::number().
clip(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_Clip_4,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsContext()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextresetclip">external documentation</a>.
+-spec resetClip(This) -> ok when
+ This::wxGraphicsContext().
resetClip(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_ResetClip,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Bmp::wxBitmap:wxBitmap(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawbitmap">external documentation</a>.
+-spec drawBitmap(This, Bmp, X, Y, W, H) -> ok when
+ This::wxGraphicsContext(), Bmp::wxBitmap:wxBitmap(), X::number(), Y::number(), W::number(), H::number().
drawBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(BmpT,wxBitmap),
wxe_util:cast(?wxGraphicsContext_DrawBitmap,
<<ThisRef:32/?UI,BmpRef:32/?UI,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsContext(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawellipse">external documentation</a>.
+-spec drawEllipse(This, X, Y, W, H) -> ok when
+ This::wxGraphicsContext(), X::number(), Y::number(), W::number(), H::number().
drawEllipse(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_DrawEllipse,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsContext(), Icon::wxIcon:wxIcon(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawicon">external documentation</a>.
+-spec drawIcon(This, Icon, X, Y, W, H) -> ok when
+ This::wxGraphicsContext(), Icon::wxIcon:wxIcon(), X::number(), Y::number(), W::number(), H::number().
drawIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(IconT,wxIcon),
wxe_util:cast(?wxGraphicsContext_DrawIcon,
<<ThisRef:32/?UI,IconRef:32/?UI,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(),Y::float()}) -> ok
-%% @equiv drawLines(This,N,Points, [])
-drawLines(This,N,Points={PointsX,PointsY})
- when is_record(This, wx_ref),is_integer(N),is_number(PointsX),is_number(PointsY) ->
- drawLines(This,N,Points, []).
+%% @equiv drawLines(This,Points, [])
+-spec drawLines(This, Points) -> ok when
+ This::wxGraphicsContext(), Points::[{X::float(), Y::float()}].
+
+drawLines(This,Points)
+ when is_record(This, wx_ref),is_list(Points) ->
+ drawLines(This,Points, []).
-%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(),Y::float()}, [Option]) -> ok
-%% Option = {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawlines">external documentation</a>.
-drawLines(#wx_ref{type=ThisT,ref=ThisRef},N,{PointsX,PointsY}, Options)
- when is_integer(N),is_number(PointsX),is_number(PointsY),is_list(Options) ->
+-spec drawLines(This, Points, [Option]) -> ok when
+ This::wxGraphicsContext(), Points::[{X::float(), Y::float()}],
+ Option :: {fillStyle, integer()}.
+drawLines(#wx_ref{type=ThisT,ref=ThisRef},Points, Options)
+ when is_list(Points),is_list(Options) ->
?CLASS(ThisT,wxGraphicsContext),
MOpts = fun({fillStyle, FillStyle}, Acc) -> [<<1:32/?UI,FillStyle:32/?UI>>|Acc];
(BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
wxe_util:cast(?wxGraphicsContext_DrawLines,
- <<ThisRef:32/?UI,N:32/?UI,PointsX:64/float,PointsY:64/float, BinOpt/binary>>).
+ <<ThisRef:32/?UI,(length(Points)):32/?UI,
+ (<< <<X:64/?F,Y:64/?F>> || {X,Y} <- Points>>)/binary, BinOpt/binary>>).
-%% @spec (This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath()) -> ok
%% @equiv drawPath(This,Path, [])
+-spec drawPath(This, Path) -> ok when
+ This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath().
+
drawPath(This,Path)
when is_record(This, wx_ref),is_record(Path, wx_ref) ->
drawPath(This,Path, []).
-%% @spec (This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath(), [Option]) -> ok
-%% Option = {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawpath">external documentation</a>.
+-spec drawPath(This, Path, [Option]) -> ok when
+ This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath(),
+ Option :: {fillStyle, integer()}.
drawPath(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PathT,ref=PathRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsContext),
@@ -229,73 +260,80 @@ drawPath(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PathT,ref=PathRef}, Option
wxe_util:cast(?wxGraphicsContext_DrawPath,
<<ThisRef:32/?UI,PathRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGraphicsContext(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawrectangle">external documentation</a>.
+-spec drawRectangle(This, X, Y, W, H) -> ok when
+ This::wxGraphicsContext(), X::number(), Y::number(), W::number(), H::number().
drawRectangle(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_DrawRectangle,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsContext(), X::float(), Y::float(), W::float(), H::float(), Radius::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawroundedrectangle">external documentation</a>.
+-spec drawRoundedRectangle(This, X, Y, W, H, Radius) -> ok when
+ This::wxGraphicsContext(), X::number(), Y::number(), W::number(), H::number(), Radius::number().
drawRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H,Radius)
- when is_float(X),is_float(Y),is_float(W),is_float(H),is_float(Radius) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H),is_number(Radius) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_DrawRoundedRectangle,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F,Radius:64/?F>>).
-%% @spec (This::wxGraphicsContext(), Str::string(), X::float(), Y::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawtext">external documentation</a>.
+-spec drawText(This, Str, X, Y) -> ok when
+ This::wxGraphicsContext(), Str::unicode:chardata(), X::number(), Y::number().
drawText(#wx_ref{type=ThisT,ref=ThisRef},Str,X,Y)
- when is_list(Str),is_float(X),is_float(Y) ->
+ when is_list(Str),is_number(X),is_number(Y) ->
?CLASS(ThisT,wxGraphicsContext),
Str_UC = unicode:characters_to_binary([Str,0]),
wxe_util:cast(?wxGraphicsContext_DrawText_3,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxGraphicsContext(),Str::string(),X::float(),Y::float(),X::float()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawtext">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% drawText(This::wxGraphicsContext(), Str::string(), X::float(), Y::float(), Angle::float()) -> ok </c>
-%% </p>
-%% <p><c>
-%% drawText(This::wxGraphicsContext(), Str::string(), X::float(), Y::float(), BackgroundBrush::wxGraphicsBrush:wxGraphicsBrush()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% drawText(This, Str, X, Y, BackgroundBrush) -> ok when<br />
+%% This::wxGraphicsContext(), Str::unicode:chardata(), X::number(), Y::number(), BackgroundBrush::wxGraphicsBrush:wxGraphicsBrush().<br />
+%%
+-spec drawText(This, Str, X, Y, Angle) -> ok when
+ This::wxGraphicsContext(), Str::unicode:chardata(), X::number(), Y::number(), Angle::number();
+ (This, Str, X, Y, BackgroundBrush) -> ok when
+ This::wxGraphicsContext(), Str::unicode:chardata(), X::number(), Y::number(), BackgroundBrush::wxGraphicsBrush:wxGraphicsBrush().
drawText(#wx_ref{type=ThisT,ref=ThisRef},Str,X,Y,Angle)
- when is_list(Str),is_float(X),is_float(Y),is_float(Angle) ->
+ when is_list(Str),is_number(X),is_number(Y),is_number(Angle) ->
?CLASS(ThisT,wxGraphicsContext),
Str_UC = unicode:characters_to_binary([Str,0]),
wxe_util:cast(?wxGraphicsContext_DrawText_4_0,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8,X:64/?F,Y:64/?F,Angle:64/?F>>);
drawText(#wx_ref{type=ThisT,ref=ThisRef},Str,X,Y,#wx_ref{type=BackgroundBrushT,ref=BackgroundBrushRef})
- when is_list(Str),is_float(X),is_float(Y) ->
+ when is_list(Str),is_number(X),is_number(Y) ->
?CLASS(ThisT,wxGraphicsContext),
Str_UC = unicode:characters_to_binary([Str,0]),
?CLASS(BackgroundBrushT,wxGraphicsBrush),
wxe_util:cast(?wxGraphicsContext_DrawText_4_1,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8,X:64/?F,Y:64/?F,BackgroundBrushRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Str::string(), X::float(), Y::float(), Angle::float(), BackgroundBrush::wxGraphicsBrush:wxGraphicsBrush()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextdrawtext">external documentation</a>.
+-spec drawText(This, Str, X, Y, Angle, BackgroundBrush) -> ok when
+ This::wxGraphicsContext(), Str::unicode:chardata(), X::number(), Y::number(), Angle::number(), BackgroundBrush::wxGraphicsBrush:wxGraphicsBrush().
drawText(#wx_ref{type=ThisT,ref=ThisRef},Str,X,Y,Angle,#wx_ref{type=BackgroundBrushT,ref=BackgroundBrushRef})
- when is_list(Str),is_float(X),is_float(Y),is_float(Angle) ->
+ when is_list(Str),is_number(X),is_number(Y),is_number(Angle) ->
?CLASS(ThisT,wxGraphicsContext),
Str_UC = unicode:characters_to_binary([Str,0]),
?CLASS(BackgroundBrushT,wxGraphicsBrush),
wxe_util:cast(?wxGraphicsContext_DrawText_5,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8,X:64/?F,Y:64/?F,Angle:64/?F,BackgroundBrushRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath()) -> ok
%% @equiv fillPath(This,Path, [])
+-spec fillPath(This, Path) -> ok when
+ This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath().
+
fillPath(This,Path)
when is_record(This, wx_ref),is_record(Path, wx_ref) ->
fillPath(This,Path, []).
-%% @spec (This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath(), [Option]) -> ok
-%% Option = {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextfillpath">external documentation</a>.
+-spec fillPath(This, Path, [Option]) -> ok when
+ This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath(),
+ Option :: {fillStyle, integer()}.
fillPath(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PathT,ref=PathRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsContext),
@@ -306,33 +344,29 @@ fillPath(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PathT,ref=PathRef}, Option
wxe_util:cast(?wxGraphicsContext_FillPath,
<<ThisRef:32/?UI,PathRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextstrokepath">external documentation</a>.
+-spec strokePath(This, Path) -> ok when
+ This::wxGraphicsContext(), Path::wxGraphicsPath:wxGraphicsPath().
strokePath(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PathT,ref=PathRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(PathT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsContext_StrokePath,
<<ThisRef:32/?UI,PathRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext()) -> ok
-%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextgetnativecontext">external documentation</a>.
-getNativeContext(#wx_ref{type=ThisT,ref=ThisRef}) ->
- ?CLASS(ThisT,wxGraphicsContext),
- wxe_util:cast(?wxGraphicsContext_GetNativeContext,
- <<ThisRef:32/?UI>>).
-
-%% @spec (This::wxGraphicsContext(), Text::string(), Widths::[float()]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextgetpartialtextextents">external documentation</a>.
-getPartialTextExtents(#wx_ref{type=ThisT,ref=ThisRef},Text,Widths)
- when is_list(Text),is_list(Widths) ->
+-spec getPartialTextExtents(This, Text) -> [number()] when
+ This::wxGraphicsContext(), Text::unicode:chardata().
+getPartialTextExtents(#wx_ref{type=ThisT,ref=ThisRef},Text)
+ when is_list(Text) ->
?CLASS(ThisT,wxGraphicsContext),
Text_UC = unicode:characters_to_binary([Text,0]),
- wxe_util:cast(?wxGraphicsContext_GetPartialTextExtents,
- <<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,(length(Widths)):32/?UI,
-0:32, (<< <<C:64/float>> || C <- Widths>>)/binary>>).
+ wxe_util:call(?wxGraphicsContext_GetPartialTextExtents,
+ <<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGraphicsContext(), Text::string()) -> {Width::float(),Height::float(),Descent::float(),ExternalLeading::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextgettextextent">external documentation</a>.
+-spec getTextExtent(This, Text) -> Result when
+ Result ::{Width::number(), Height::number(), Descent::number(), ExternalLeading::number()},
+ This::wxGraphicsContext(), Text::unicode:chardata().
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxGraphicsContext),
@@ -340,55 +374,62 @@ getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:call(?wxGraphicsContext_GetTextExtent,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGraphicsContext(), Angle::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextrotate">external documentation</a>.
+-spec rotate(This, Angle) -> ok when
+ This::wxGraphicsContext(), Angle::number().
rotate(#wx_ref{type=ThisT,ref=ThisRef},Angle)
- when is_float(Angle) ->
+ when is_number(Angle) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_Rotate,
<<ThisRef:32/?UI,0:32,Angle:64/?F>>).
-%% @spec (This::wxGraphicsContext(), XScale::float(), YScale::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextscale">external documentation</a>.
+-spec scale(This, XScale, YScale) -> ok when
+ This::wxGraphicsContext(), XScale::number(), YScale::number().
scale(#wx_ref{type=ThisT,ref=ThisRef},XScale,YScale)
- when is_float(XScale),is_float(YScale) ->
+ when is_number(XScale),is_number(YScale) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_Scale,
<<ThisRef:32/?UI,0:32,XScale:64/?F,YScale:64/?F>>).
-%% @spec (This::wxGraphicsContext(), Dx::float(), Dy::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontexttranslate">external documentation</a>.
+-spec translate(This, Dx, Dy) -> ok when
+ This::wxGraphicsContext(), Dx::number(), Dy::number().
translate(#wx_ref{type=ThisT,ref=ThisRef},Dx,Dy)
- when is_float(Dx),is_float(Dy) ->
+ when is_number(Dx),is_number(Dy) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_Translate,
<<ThisRef:32/?UI,0:32,Dx:64/?F,Dy:64/?F>>).
-%% @spec (This::wxGraphicsContext()) -> wxGraphicsMatrix:wxGraphicsMatrix()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextgettransform">external documentation</a>.
+-spec getTransform(This) -> wxGraphicsMatrix:wxGraphicsMatrix() when
+ This::wxGraphicsContext().
getTransform(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:call(?wxGraphicsContext_GetTransform,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Matrix::wxGraphicsMatrix:wxGraphicsMatrix()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextsettransform">external documentation</a>.
+-spec setTransform(This, Matrix) -> ok when
+ This::wxGraphicsContext(), Matrix::wxGraphicsMatrix:wxGraphicsMatrix().
setTransform(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MatrixT,ref=MatrixRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(MatrixT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsContext_SetTransform,
<<ThisRef:32/?UI,MatrixRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Matrix::wxGraphicsMatrix:wxGraphicsMatrix()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextconcattransform">external documentation</a>.
+-spec concatTransform(This, Matrix) -> ok when
+ This::wxGraphicsContext(), Matrix::wxGraphicsMatrix:wxGraphicsMatrix().
concatTransform(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MatrixT,ref=MatrixRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(MatrixT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsContext_ConcatTransform,
<<ThisRef:32/?UI,MatrixRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Brush::wxGraphicsBrush:wxGraphicsBrush() | wxBrush:wxBrush()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextsetbrush">external documentation</a>.
+-spec setBrush(This, Brush) -> ok when
+ This::wxGraphicsContext(), Brush::wxGraphicsBrush:wxGraphicsBrush() | wxBrush:wxBrush().
setBrush(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
?CLASS(ThisT,wxGraphicsContext),
BrushOP = case ?CLASS_T(BrushT,wxGraphicsBrush) of
@@ -400,16 +441,18 @@ setBrush(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
wxe_util:cast(BrushOP,
<<ThisRef:32/?UI,BrushRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Font::wxGraphicsFont:wxGraphicsFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextsetfont">external documentation</a>.
+-spec setFont(This, Font) -> ok when
+ This::wxGraphicsContext(), Font::wxGraphicsFont:wxGraphicsFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxGraphicsContext),
?CLASS(FontT,wxGraphicsFont),
wxe_util:cast(?wxGraphicsContext_SetFont_1,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), Font::wxFont:wxFont(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextsetfont">external documentation</a>.
+-spec setFont(This, Font, Colour) -> ok when
+ This::wxGraphicsContext(), Font::wxFont:wxFont(), Colour::wx:wx_colour().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxGraphicsContext),
@@ -417,8 +460,9 @@ setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef},Colour)
wxe_util:cast(?wxGraphicsContext_SetFont_2,
<<ThisRef:32/?UI,FontRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxGraphicsContext(), Pen::wxPen:wxPen() | wxGraphicsPen:wxGraphicsPen()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextsetpen">external documentation</a>.
+-spec setPen(This, Pen) -> ok when
+ This::wxGraphicsContext(), Pen::wxPen:wxPen() | wxGraphicsPen:wxGraphicsPen().
setPen(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PenT,ref=PenRef}) ->
?CLASS(ThisT,wxGraphicsContext),
PenOP = case ?CLASS_T(PenT,wxPen) of
@@ -430,30 +474,31 @@ setPen(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PenT,ref=PenRef}) ->
wxe_util:cast(PenOP,
<<ThisRef:32/?UI,PenRef:32/?UI>>).
-%% @spec (This::wxGraphicsContext(), X1::float(), Y1::float(), X2::float(), Y2::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextstrokeline">external documentation</a>.
+-spec strokeLine(This, X1, Y1, X2, Y2) -> ok when
+ This::wxGraphicsContext(), X1::number(), Y1::number(), X2::number(), Y2::number().
strokeLine(#wx_ref{type=ThisT,ref=ThisRef},X1,Y1,X2,Y2)
- when is_float(X1),is_float(Y1),is_float(X2),is_float(Y2) ->
+ when is_number(X1),is_number(Y1),is_number(X2),is_number(Y2) ->
?CLASS(ThisT,wxGraphicsContext),
wxe_util:cast(?wxGraphicsContext_StrokeLine,
<<ThisRef:32/?UI,0:32,X1:64/?F,Y1:64/?F,X2:64/?F,Y2:64/?F>>).
-%% @spec (This::wxGraphicsContext(), N::integer(), Points::{X::float(),Y::float()}) -> ok
-%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextstrokelines">external documentation</a>.
-strokeLines(#wx_ref{type=ThisT,ref=ThisRef},N,{PointsX,PointsY})
- when is_integer(N),is_number(PointsX),is_number(PointsY) ->
- ?CLASS(ThisT,wxGraphicsContext),
- wxe_util:cast(?wxGraphicsContext_StrokeLines_2,
- <<ThisRef:32/?UI,N:32/?UI,PointsX:64/float,PointsY:64/float>>).
-
-%% @spec (This::wxGraphicsContext(), N::integer(), BeginPoints::{X::float(),Y::float()}, EndPoints::{X::float(),Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicscontext.html#wxgraphicscontextstrokelines">external documentation</a>.
-strokeLines(#wx_ref{type=ThisT,ref=ThisRef},N,{BeginPointsX,BeginPointsY},{EndPointsX,EndPointsY})
- when is_integer(N),is_number(BeginPointsX),is_number(BeginPointsY),is_number(EndPointsX),is_number(EndPointsY) ->
- ?CLASS(ThisT,wxGraphicsContext),
- wxe_util:cast(?wxGraphicsContext_StrokeLines_3,
- <<ThisRef:32/?UI,N:32/?UI,BeginPointsX:64/float,BeginPointsY:64/float,EndPointsX:64/float,EndPointsY:64/float>>).
-
+-spec strokeLines(This, Points) -> ok when
+ This::wxGraphicsContext(), Points::[{X::float(), Y::float()}].
+strokeLines(#wx_ref{type=ThisT,ref=ThisRef},Points)
+ when is_list(Points) ->
+ ?CLASS(ThisT,wxGraphicsContext),
+ wxe_util:cast(?wxGraphicsContext_StrokeLines,
+ <<ThisRef:32/?UI,(length(Points)):32/?UI,
+ (<< <<X:64/?F,Y:64/?F>> || {X,Y} <- Points>>)/binary>>).
+
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGraphicsContext()) -> ok.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxGraphicsContext),
+ wxe_util:destroy(?DESTROY_OBJECT,Obj),
+ ok.
%% From wxGraphicsObject
%% @hidden
isNull(This) -> wxGraphicsObject:isNull(This).
diff --git a/lib/wx/src/gen/wxGraphicsFont.erl b/lib/wx/src/gen/wxGraphicsFont.erl
index 19b2172176..03220599fb 100644
--- a/lib/wx/src/gen/wxGraphicsFont.erl
+++ b/lib/wx/src/gen/wxGraphicsFont.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +32,12 @@
%% inherited exports
-export([getRenderer/1,isNull/1,parent_class/1]).
+-export_type([wxGraphicsFont/0]).
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxGraphicsFont() :: wx:wx_object().
%% From wxGraphicsObject
%% @hidden
isNull(This) -> wxGraphicsObject:isNull(This).
diff --git a/lib/wx/src/gen/wxGraphicsMatrix.erl b/lib/wx/src/gen/wxGraphicsMatrix.erl
index 38ea007c58..36c33069ad 100644
--- a/lib/wx/src/gen/wxGraphicsMatrix.erl
+++ b/lib/wx/src/gen/wxGraphicsMatrix.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,93 +27,105 @@
-module(wxGraphicsMatrix).
-include("wxe.hrl").
--export([concat/2,get/1,getNativeMatrix/1,invert/1,isEqual/2,isIdentity/1,rotate/2,
- scale/3,set/1,set/2,transformDistance/1,transformPoint/1,translate/3]).
+-export([concat/2,get/1,invert/1,isEqual/2,isIdentity/1,rotate/2,scale/3,set/1,
+ set/2,transformDistance/1,transformPoint/1,translate/3]).
%% inherited exports
-export([getRenderer/1,isNull/1,parent_class/1]).
+-export_type([wxGraphicsMatrix/0]).
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGraphicsMatrix(), T::wxGraphicsMatrix()) -> ok
+-type wxGraphicsMatrix() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixconcat">external documentation</a>.
+-spec concat(This, T) -> ok when
+ This::wxGraphicsMatrix(), T::wxGraphicsMatrix().
concat(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=TT,ref=TRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
?CLASS(TT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsMatrix_Concat,
<<ThisRef:32/?UI,TRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix()) -> {A::float(),B::float(),C::float(),D::float(),Tx::float(),Ty::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixget">external documentation</a>.
+-spec get(This) -> Result when
+ Result ::{A::number(), B::number(), C::number(), D::number(), Tx::number(), Ty::number()},
+ This::wxGraphicsMatrix().
get(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:call(?wxGraphicsMatrix_Get,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix()) -> ok
-%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixgetnativematrix">external documentation</a>.
-getNativeMatrix(#wx_ref{type=ThisT,ref=ThisRef}) ->
- ?CLASS(ThisT,wxGraphicsMatrix),
- wxe_util:cast(?wxGraphicsMatrix_GetNativeMatrix,
- <<ThisRef:32/?UI>>).
-
-%% @spec (This::wxGraphicsMatrix()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixinvert">external documentation</a>.
+-spec invert(This) -> ok when
+ This::wxGraphicsMatrix().
invert(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsMatrix_Invert,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix(), T::wxGraphicsMatrix()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixisequal">external documentation</a>.
+-spec isEqual(This, T) -> boolean() when
+ This::wxGraphicsMatrix(), T::wxGraphicsMatrix().
isEqual(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=TT,ref=TRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
?CLASS(TT,wxGraphicsMatrix),
wxe_util:call(?wxGraphicsMatrix_IsEqual,
<<ThisRef:32/?UI,TRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixisidentity">external documentation</a>.
+-spec isIdentity(This) -> boolean() when
+ This::wxGraphicsMatrix().
isIdentity(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:call(?wxGraphicsMatrix_IsIdentity,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix(), Angle::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixrotate">external documentation</a>.
+-spec rotate(This, Angle) -> ok when
+ This::wxGraphicsMatrix(), Angle::number().
rotate(#wx_ref{type=ThisT,ref=ThisRef},Angle)
- when is_float(Angle) ->
+ when is_number(Angle) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsMatrix_Rotate,
<<ThisRef:32/?UI,0:32,Angle:64/?F>>).
-%% @spec (This::wxGraphicsMatrix(), XScale::float(), YScale::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixscale">external documentation</a>.
+-spec scale(This, XScale, YScale) -> ok when
+ This::wxGraphicsMatrix(), XScale::number(), YScale::number().
scale(#wx_ref{type=ThisT,ref=ThisRef},XScale,YScale)
- when is_float(XScale),is_float(YScale) ->
+ when is_number(XScale),is_number(YScale) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsMatrix_Scale,
<<ThisRef:32/?UI,0:32,XScale:64/?F,YScale:64/?F>>).
-%% @spec (This::wxGraphicsMatrix(), Dx::float(), Dy::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixtranslate">external documentation</a>.
+-spec translate(This, Dx, Dy) -> ok when
+ This::wxGraphicsMatrix(), Dx::number(), Dy::number().
translate(#wx_ref{type=ThisT,ref=ThisRef},Dx,Dy)
- when is_float(Dx),is_float(Dy) ->
+ when is_number(Dx),is_number(Dy) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:cast(?wxGraphicsMatrix_Translate,
<<ThisRef:32/?UI,0:32,Dx:64/?F,Dy:64/?F>>).
-%% @spec (This::wxGraphicsMatrix()) -> ok
%% @equiv set(This, [])
+-spec set(This) -> ok when
+ This::wxGraphicsMatrix().
+
set(This)
when is_record(This, wx_ref) ->
set(This, []).
-%% @spec (This::wxGraphicsMatrix(), [Option]) -> ok
-%% Option = {a, float()} | {b, float()} | {c, float()} | {d, float()} | {tx, float()} | {ty, float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixset">external documentation</a>.
+-spec set(This, [Option]) -> ok when
+ This::wxGraphicsMatrix(),
+ Option :: {a, number()}
+ | {b, number()}
+ | {c, number()}
+ | {d, number()}
+ | {tx, number()}
+ | {ty, number()}.
set(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsMatrix),
@@ -128,15 +140,17 @@ set(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGraphicsMatrix_Set,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGraphicsMatrix()) -> {X::float(),Y::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixtransformpoint">external documentation</a>.
+-spec transformPoint(This) -> {X::number(), Y::number()} when
+ This::wxGraphicsMatrix().
transformPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:call(?wxGraphicsMatrix_TransformPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsMatrix()) -> {Dx::float(),Dy::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsmatrix.html#wxgraphicsmatrixtransformdistance">external documentation</a>.
+-spec transformDistance(This) -> {Dx::number(), Dy::number()} when
+ This::wxGraphicsMatrix().
transformDistance(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsMatrix),
wxe_util:call(?wxGraphicsMatrix_TransformDistance,
diff --git a/lib/wx/src/gen/wxGraphicsObject.erl b/lib/wx/src/gen/wxGraphicsObject.erl
index 7e63285b7a..857a398e1f 100644
--- a/lib/wx/src/gen/wxGraphicsObject.erl
+++ b/lib/wx/src/gen/wxGraphicsObject.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,25 +24,35 @@
-module(wxGraphicsObject).
-include("wxe.hrl").
--export([getRenderer/1,isNull/1]).
+-export([destroy/1,getRenderer/1,isNull/1]).
%% inherited exports
-export([parent_class/1]).
+-export_type([wxGraphicsObject/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGraphicsObject()) -> wxGraphicsRenderer:wxGraphicsRenderer()
+-type wxGraphicsObject() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsobject.html#wxgraphicsobjectgetrenderer">external documentation</a>.
+-spec getRenderer(This) -> wxGraphicsRenderer:wxGraphicsRenderer() when
+ This::wxGraphicsObject().
getRenderer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsObject),
wxe_util:call(?wxGraphicsObject_GetRenderer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsObject()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsobject.html#wxgraphicsobjectisnull">external documentation</a>.
+-spec isNull(This) -> boolean() when
+ This::wxGraphicsObject().
isNull(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsObject),
wxe_util:call(?wxGraphicsObject_IsNull,
<<ThisRef:32/?UI>>).
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGraphicsObject()) -> ok.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxGraphicsObject),
+ wxe_util:destroy(?DESTROY_OBJECT,Obj),
+ ok.
diff --git a/lib/wx/src/gen/wxGraphicsPath.erl b/lib/wx/src/gen/wxGraphicsPath.erl
index ff2dfb07a4..56b853899a 100644
--- a/lib/wx/src/gen/wxGraphicsPath.erl
+++ b/lib/wx/src/gen/wxGraphicsPath.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,155 +36,177 @@
%% inherited exports
-export([getRenderer/1,isNull/1,parent_class/1]).
+-export_type([wxGraphicsPath/0]).
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGraphicsPath(), P::{X::float(),Y::float()}) -> ok
+-type wxGraphicsPath() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathmovetopoint">external documentation</a>.
+-spec moveToPoint(This, P) -> ok when
+ This::wxGraphicsPath(), P::{X::float(), Y::float()}.
moveToPoint(#wx_ref{type=ThisT,ref=ThisRef},{PX,PY})
when is_number(PX),is_number(PY) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_MoveToPoint_1,
- <<ThisRef:32/?UI,0:32,PX:64/float,PY:64/float>>).
+ <<ThisRef:32/?UI,0:32,PX:64/?F,PY:64/?F>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathmovetopoint">external documentation</a>.
+-spec moveToPoint(This, X, Y) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number().
moveToPoint(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
- when is_float(X),is_float(Y) ->
+ when is_number(X),is_number(Y) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_MoveToPoint_2,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxGraphicsPath(), C::{X::float(),Y::float()}, R::float(), StartAngle::float(), EndAngle::float(), Clockwise::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddarc">external documentation</a>.
+-spec addArc(This, C, R, StartAngle, EndAngle, Clockwise) -> ok when
+ This::wxGraphicsPath(), C::{X::float(), Y::float()}, R::number(), StartAngle::number(), EndAngle::number(), Clockwise::boolean().
addArc(#wx_ref{type=ThisT,ref=ThisRef},{CX,CY},R,StartAngle,EndAngle,Clockwise)
- when is_number(CX),is_number(CY),is_float(R),is_float(StartAngle),is_float(EndAngle),is_boolean(Clockwise) ->
+ when is_number(CX),is_number(CY),is_number(R),is_number(StartAngle),is_number(EndAngle),is_boolean(Clockwise) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddArc_5,
- <<ThisRef:32/?UI,0:32,CX:64/float,CY:64/float,R:64/?F,StartAngle:64/?F,EndAngle:64/?F,(wxe_util:from_bool(Clockwise)):32/?UI>>).
+ <<ThisRef:32/?UI,0:32,CX:64/?F,CY:64/?F,R:64/?F,StartAngle:64/?F,EndAngle:64/?F,(wxe_util:from_bool(Clockwise)):32/?UI>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float(), R::float(), StartAngle::float(), EndAngle::float(), Clockwise::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddarc">external documentation</a>.
+-spec addArc(This, X, Y, R, StartAngle, EndAngle, Clockwise) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number(), R::number(), StartAngle::number(), EndAngle::number(), Clockwise::boolean().
addArc(#wx_ref{type=ThisT,ref=ThisRef},X,Y,R,StartAngle,EndAngle,Clockwise)
- when is_float(X),is_float(Y),is_float(R),is_float(StartAngle),is_float(EndAngle),is_boolean(Clockwise) ->
+ when is_number(X),is_number(Y),is_number(R),is_number(StartAngle),is_number(EndAngle),is_boolean(Clockwise) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddArc_6,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,R:64/?F,StartAngle:64/?F,EndAngle:64/?F,(wxe_util:from_bool(Clockwise)):32/?UI>>).
-%% @spec (This::wxGraphicsPath(), X1::float(), Y1::float(), X2::float(), Y2::float(), R::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddarctopoint">external documentation</a>.
+-spec addArcToPoint(This, X1, Y1, X2, Y2, R) -> ok when
+ This::wxGraphicsPath(), X1::number(), Y1::number(), X2::number(), Y2::number(), R::number().
addArcToPoint(#wx_ref{type=ThisT,ref=ThisRef},X1,Y1,X2,Y2,R)
- when is_float(X1),is_float(Y1),is_float(X2),is_float(Y2),is_float(R) ->
+ when is_number(X1),is_number(Y1),is_number(X2),is_number(Y2),is_number(R) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddArcToPoint,
<<ThisRef:32/?UI,0:32,X1:64/?F,Y1:64/?F,X2:64/?F,Y2:64/?F,R:64/?F>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float(), R::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddcircle">external documentation</a>.
+-spec addCircle(This, X, Y, R) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number(), R::number().
addCircle(#wx_ref{type=ThisT,ref=ThisRef},X,Y,R)
- when is_float(X),is_float(Y),is_float(R) ->
+ when is_number(X),is_number(Y),is_number(R) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddCircle,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,R:64/?F>>).
-%% @spec (This::wxGraphicsPath(), C1::{X::float(),Y::float()}, C2::{X::float(),Y::float()}, E::{X::float(),Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddcurvetopoint">external documentation</a>.
+-spec addCurveToPoint(This, C1, C2, E) -> ok when
+ This::wxGraphicsPath(), C1::{X::float(), Y::float()}, C2::{X::float(), Y::float()}, E::{X::float(), Y::float()}.
addCurveToPoint(#wx_ref{type=ThisT,ref=ThisRef},{C1X,C1Y},{C2X,C2Y},{EX,EY})
when is_number(C1X),is_number(C1Y),is_number(C2X),is_number(C2Y),is_number(EX),is_number(EY) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddCurveToPoint_3,
- <<ThisRef:32/?UI,0:32,C1X:64/float,C1Y:64/float,C2X:64/float,C2Y:64/float,EX:64/float,EY:64/float>>).
+ <<ThisRef:32/?UI,0:32,C1X:64/?F,C1Y:64/?F,C2X:64/?F,C2Y:64/?F,EX:64/?F,EY:64/?F>>).
-%% @spec (This::wxGraphicsPath(), Cx1::float(), Cy1::float(), Cx2::float(), Cy2::float(), X::float(), Y::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddcurvetopoint">external documentation</a>.
+-spec addCurveToPoint(This, Cx1, Cy1, Cx2, Cy2, X, Y) -> ok when
+ This::wxGraphicsPath(), Cx1::number(), Cy1::number(), Cx2::number(), Cy2::number(), X::number(), Y::number().
addCurveToPoint(#wx_ref{type=ThisT,ref=ThisRef},Cx1,Cy1,Cx2,Cy2,X,Y)
- when is_float(Cx1),is_float(Cy1),is_float(Cx2),is_float(Cy2),is_float(X),is_float(Y) ->
+ when is_number(Cx1),is_number(Cy1),is_number(Cx2),is_number(Cy2),is_number(X),is_number(Y) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddCurveToPoint_6,
<<ThisRef:32/?UI,0:32,Cx1:64/?F,Cy1:64/?F,Cx2:64/?F,Cy2:64/?F,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddellipse">external documentation</a>.
+-spec addEllipse(This, X, Y, W, H) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number(), W::number(), H::number().
addEllipse(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddEllipse,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsPath(), P::{X::float(),Y::float()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddlinetopoint">external documentation</a>.
+-spec addLineToPoint(This, P) -> ok when
+ This::wxGraphicsPath(), P::{X::float(), Y::float()}.
addLineToPoint(#wx_ref{type=ThisT,ref=ThisRef},{PX,PY})
when is_number(PX),is_number(PY) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddLineToPoint_1,
- <<ThisRef:32/?UI,0:32,PX:64/float,PY:64/float>>).
+ <<ThisRef:32/?UI,0:32,PX:64/?F,PY:64/?F>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddlinetopoint">external documentation</a>.
+-spec addLineToPoint(This, X, Y) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number().
addLineToPoint(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
- when is_float(X),is_float(Y) ->
+ when is_number(X),is_number(Y) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddLineToPoint_2,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxGraphicsPath(), Path::wxGraphicsPath()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddpath">external documentation</a>.
+-spec addPath(This, Path) -> ok when
+ This::wxGraphicsPath(), Path::wxGraphicsPath().
addPath(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PathT,ref=PathRef}) ->
?CLASS(ThisT,wxGraphicsPath),
?CLASS(PathT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddPath,
<<ThisRef:32/?UI,PathRef:32/?UI>>).
-%% @spec (This::wxGraphicsPath(), Cx::float(), Cy::float(), X::float(), Y::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddquadcurvetopoint">external documentation</a>.
+-spec addQuadCurveToPoint(This, Cx, Cy, X, Y) -> ok when
+ This::wxGraphicsPath(), Cx::number(), Cy::number(), X::number(), Y::number().
addQuadCurveToPoint(#wx_ref{type=ThisT,ref=ThisRef},Cx,Cy,X,Y)
- when is_float(Cx),is_float(Cy),is_float(X),is_float(Y) ->
+ when is_number(Cx),is_number(Cy),is_number(X),is_number(Y) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddQuadCurveToPoint,
<<ThisRef:32/?UI,0:32,Cx:64/?F,Cy:64/?F,X:64/?F,Y:64/?F>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float(), W::float(), H::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddrectangle">external documentation</a>.
+-spec addRectangle(This, X, Y, W, H) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number(), W::number(), H::number().
addRectangle(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
- when is_float(X),is_float(Y),is_float(W),is_float(H) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddRectangle,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float(), W::float(), H::float(), Radius::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathaddroundedrectangle">external documentation</a>.
+-spec addRoundedRectangle(This, X, Y, W, H, Radius) -> ok when
+ This::wxGraphicsPath(), X::number(), Y::number(), W::number(), H::number(), Radius::number().
addRoundedRectangle(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H,Radius)
- when is_float(X),is_float(Y),is_float(W),is_float(H),is_float(Radius) ->
+ when is_number(X),is_number(Y),is_number(W),is_number(H),is_number(Radius) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_AddRoundedRectangle,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F,W:64/?F,H:64/?F,Radius:64/?F>>).
-%% @spec (This::wxGraphicsPath()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathclosesubpath">external documentation</a>.
+-spec closeSubpath(This) -> ok when
+ This::wxGraphicsPath().
closeSubpath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:cast(?wxGraphicsPath_CloseSubpath,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsPath(), C::{X::float(),Y::float()}) -> bool()
%% @equiv contains(This,C, [])
+-spec contains(This, C) -> boolean() when
+ This::wxGraphicsPath(), C::{X::float(), Y::float()}.
+
contains(This,C={CX,CY})
when is_record(This, wx_ref),is_number(CX),is_number(CY) ->
contains(This,C, []).
-%% @spec (This::wxGraphicsPath(),X::float()|term(),X::float()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathcontains">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% contains(This::wxGraphicsPath(), X::float(), Y::float()) -> contains(This,X,Y, []) </c></p>
-%% <p><c>
-%% contains(This::wxGraphicsPath(), C::{X::float(),Y::float()}, [Option]) -> bool() </c>
-%%<br /> Option = {fillStyle, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% contains(This, C, [Option]) -> boolean() when<br />
+%% This::wxGraphicsPath(), C::{X::float(), Y::float()},<br />
+%% Option :: {fillStyle, integer()}.<br />
+%%
+-spec contains(This, X, Y) -> boolean() when
+ This::wxGraphicsPath(), X::number(), Y::number();
+ (This, C, [Option]) -> boolean() when
+ This::wxGraphicsPath(), C::{X::float(), Y::float()},
+ Option :: {fillStyle, integer()}.
contains(This,X,Y)
- when is_record(This, wx_ref),is_float(X),is_float(Y) ->
+ when is_record(This, wx_ref),is_number(X),is_number(Y) ->
contains(This,X,Y, []);
contains(#wx_ref{type=ThisT,ref=ThisRef},{CX,CY}, Options)
when is_number(CX),is_number(CY),is_list(Options) ->
@@ -193,13 +215,14 @@ contains(#wx_ref{type=ThisT,ref=ThisRef},{CX,CY}, Options)
(BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
wxe_util:call(?wxGraphicsPath_Contains_2,
- <<ThisRef:32/?UI,0:32,CX:64/float,CY:64/float, BinOpt/binary>>).
+ <<ThisRef:32/?UI,0:32,CX:64/?F,CY:64/?F, BinOpt/binary>>).
-%% @spec (This::wxGraphicsPath(), X::float(), Y::float(), [Option]) -> bool()
-%% Option = {fillStyle, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathcontains">external documentation</a>.
+-spec contains(This, X, Y, [Option]) -> boolean() when
+ This::wxGraphicsPath(), X::number(), Y::number(),
+ Option :: {fillStyle, integer()}.
contains(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
- when is_float(X),is_float(Y),is_list(Options) ->
+ when is_number(X),is_number(Y),is_list(Options) ->
?CLASS(ThisT,wxGraphicsPath),
MOpts = fun({fillStyle, FillStyle}, Acc) -> [<<1:32/?UI,FillStyle:32/?UI>>|Acc];
(BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
@@ -207,22 +230,25 @@ contains(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
wxe_util:call(?wxGraphicsPath_Contains_3,
<<ThisRef:32/?UI,0:32,X:64/?F,Y:64/?F, BinOpt/binary>>).
-%% @spec (This::wxGraphicsPath()) -> {X::float(),Y::float(),W::float(),H::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathgetbox">external documentation</a>.
+-spec getBox(This) -> {X::float(), Y::float(), W::float(), H::float()} when
+ This::wxGraphicsPath().
getBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:call(?wxGraphicsPath_GetBox,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsPath()) -> {X::float(),Y::float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathgetcurrentpoint">external documentation</a>.
+-spec getCurrentPoint(This) -> {X::float(), Y::float()} when
+ This::wxGraphicsPath().
getCurrentPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsPath),
wxe_util:call(?wxGraphicsPath_GetCurrentPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGraphicsPath(), Matrix::wxGraphicsMatrix:wxGraphicsMatrix()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicspath.html#wxgraphicspathtransform">external documentation</a>.
+-spec transform(This, Matrix) -> ok when
+ This::wxGraphicsPath(), Matrix::wxGraphicsMatrix:wxGraphicsMatrix().
transform(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MatrixT,ref=MatrixRef}) ->
?CLASS(ThisT,wxGraphicsPath),
?CLASS(MatrixT,wxGraphicsMatrix),
diff --git a/lib/wx/src/gen/wxGraphicsPen.erl b/lib/wx/src/gen/wxGraphicsPen.erl
index 395b05f8af..76a59e6e2c 100644
--- a/lib/wx/src/gen/wxGraphicsPen.erl
+++ b/lib/wx/src/gen/wxGraphicsPen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +32,12 @@
%% inherited exports
-export([getRenderer/1,isNull/1,parent_class/1]).
+-export_type([wxGraphicsPen/0]).
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxGraphicsPen() :: wx:wx_object().
%% From wxGraphicsObject
%% @hidden
isNull(This) -> wxGraphicsObject:isNull(This).
diff --git a/lib/wx/src/gen/wxGraphicsRenderer.erl b/lib/wx/src/gen/wxGraphicsRenderer.erl
index ed53ebf468..21082bde23 100644
--- a/lib/wx/src/gen/wxGraphicsRenderer.erl
+++ b/lib/wx/src/gen/wxGraphicsRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,17 +31,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxGraphicsRenderer/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGraphicsRenderer()
+-type wxGraphicsRenderer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderergetdefaultrenderer">external documentation</a>.
+-spec getDefaultRenderer() -> wxGraphicsRenderer().
getDefaultRenderer() ->
wxe_util:call(?wxGraphicsRenderer_GetDefaultRenderer,
<<>>).
-%% @spec (This::wxGraphicsRenderer(), Dc::wxWindowDC:wxWindowDC() | wxWindow:wxWindow()) -> wxGraphicsContext:wxGraphicsContext()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatecontext">external documentation</a>.
+-spec createContext(This, Dc) -> wxGraphicsContext:wxGraphicsContext() when
+ This::wxGraphicsRenderer(), Dc::wxWindowDC:wxWindowDC() | wxWindow:wxWindow().
createContext(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}) ->
?CLASS(ThisT,wxGraphicsRenderer),
DcOP = case ?CLASS_T(DcT,wxWindowDC) of
@@ -53,47 +56,54 @@ createContext(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}) ->
wxe_util:call(DcOP,
<<ThisRef:32/?UI,DcRef:32/?UI>>).
-%% @spec (This::wxGraphicsRenderer(), Pen::wxPen:wxPen()) -> wxGraphicsPen:wxGraphicsPen()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatepen">external documentation</a>.
+-spec createPen(This, Pen) -> wxGraphicsPen:wxGraphicsPen() when
+ This::wxGraphicsRenderer(), Pen::wxPen:wxPen().
createPen(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PenT,ref=PenRef}) ->
?CLASS(ThisT,wxGraphicsRenderer),
?CLASS(PenT,wxPen),
wxe_util:call(?wxGraphicsRenderer_CreatePen,
<<ThisRef:32/?UI,PenRef:32/?UI>>).
-%% @spec (This::wxGraphicsRenderer(), Brush::wxBrush:wxBrush()) -> wxGraphicsBrush:wxGraphicsBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatebrush">external documentation</a>.
+-spec createBrush(This, Brush) -> wxGraphicsBrush:wxGraphicsBrush() when
+ This::wxGraphicsRenderer(), Brush::wxBrush:wxBrush().
createBrush(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BrushT,ref=BrushRef}) ->
?CLASS(ThisT,wxGraphicsRenderer),
?CLASS(BrushT,wxBrush),
wxe_util:call(?wxGraphicsRenderer_CreateBrush,
<<ThisRef:32/?UI,BrushRef:32/?UI>>).
-%% @spec (This::wxGraphicsRenderer(), X1::float(), Y1::float(), X2::float(), Y2::float(), C1::wx:colour(), C2::wx:colour()) -> wxGraphicsBrush:wxGraphicsBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatelineargradientbrush">external documentation</a>.
+-spec createLinearGradientBrush(This, X1, Y1, X2, Y2, C1, C2) -> wxGraphicsBrush:wxGraphicsBrush() when
+ This::wxGraphicsRenderer(), X1::number(), Y1::number(), X2::number(), Y2::number(), C1::wx:wx_colour(), C2::wx:wx_colour().
createLinearGradientBrush(#wx_ref{type=ThisT,ref=ThisRef},X1,Y1,X2,Y2,C1,C2)
- when is_float(X1),is_float(Y1),is_float(X2),is_float(Y2),tuple_size(C1) =:= 3; tuple_size(C1) =:= 4,tuple_size(C2) =:= 3; tuple_size(C2) =:= 4 ->
+ when is_number(X1),is_number(Y1),is_number(X2),is_number(Y2),tuple_size(C1) =:= 3; tuple_size(C1) =:= 4,tuple_size(C2) =:= 3; tuple_size(C2) =:= 4 ->
?CLASS(ThisT,wxGraphicsRenderer),
wxe_util:call(?wxGraphicsRenderer_CreateLinearGradientBrush,
<<ThisRef:32/?UI,0:32,X1:64/?F,Y1:64/?F,X2:64/?F,Y2:64/?F,(wxe_util:colour_bin(C1)):16/binary,(wxe_util:colour_bin(C2)):16/binary>>).
-%% @spec (This::wxGraphicsRenderer(), Xo::float(), Yo::float(), Xc::float(), Yc::float(), Radius::float(), OColor::wx:colour(), CColor::wx:colour()) -> wxGraphicsBrush:wxGraphicsBrush()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreateradialgradientbrush">external documentation</a>.
+-spec createRadialGradientBrush(This, Xo, Yo, Xc, Yc, Radius, OColor, CColor) -> wxGraphicsBrush:wxGraphicsBrush() when
+ This::wxGraphicsRenderer(), Xo::number(), Yo::number(), Xc::number(), Yc::number(), Radius::number(), OColor::wx:wx_colour(), CColor::wx:wx_colour().
createRadialGradientBrush(#wx_ref{type=ThisT,ref=ThisRef},Xo,Yo,Xc,Yc,Radius,OColor,CColor)
- when is_float(Xo),is_float(Yo),is_float(Xc),is_float(Yc),is_float(Radius),tuple_size(OColor) =:= 3; tuple_size(OColor) =:= 4,tuple_size(CColor) =:= 3; tuple_size(CColor) =:= 4 ->
+ when is_number(Xo),is_number(Yo),is_number(Xc),is_number(Yc),is_number(Radius),tuple_size(OColor) =:= 3; tuple_size(OColor) =:= 4,tuple_size(CColor) =:= 3; tuple_size(CColor) =:= 4 ->
?CLASS(ThisT,wxGraphicsRenderer),
wxe_util:call(?wxGraphicsRenderer_CreateRadialGradientBrush,
<<ThisRef:32/?UI,0:32,Xo:64/?F,Yo:64/?F,Xc:64/?F,Yc:64/?F,Radius:64/?F,(wxe_util:colour_bin(OColor)):16/binary,(wxe_util:colour_bin(CColor)):16/binary>>).
-%% @spec (This::wxGraphicsRenderer(), Font::wxFont:wxFont()) -> wxGraphicsFont:wxGraphicsFont()
%% @equiv createFont(This,Font, [])
+-spec createFont(This, Font) -> wxGraphicsFont:wxGraphicsFont() when
+ This::wxGraphicsRenderer(), Font::wxFont:wxFont().
+
createFont(This,Font)
when is_record(This, wx_ref),is_record(Font, wx_ref) ->
createFont(This,Font, []).
-%% @spec (This::wxGraphicsRenderer(), Font::wxFont:wxFont(), [Option]) -> wxGraphicsFont:wxGraphicsFont()
-%% Option = {col, wx:colour()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatefont">external documentation</a>.
+-spec createFont(This, Font, [Option]) -> wxGraphicsFont:wxGraphicsFont() when
+ This::wxGraphicsRenderer(), Font::wxFont:wxFont(),
+ Option :: {col, wx:wx_colour()}.
createFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsRenderer),
@@ -104,15 +114,23 @@ createFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}, Opti
wxe_util:call(?wxGraphicsRenderer_CreateFont,
<<ThisRef:32/?UI,FontRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGraphicsRenderer()) -> wxGraphicsMatrix:wxGraphicsMatrix()
%% @equiv createMatrix(This, [])
+-spec createMatrix(This) -> wxGraphicsMatrix:wxGraphicsMatrix() when
+ This::wxGraphicsRenderer().
+
createMatrix(This)
when is_record(This, wx_ref) ->
createMatrix(This, []).
-%% @spec (This::wxGraphicsRenderer(), [Option]) -> wxGraphicsMatrix:wxGraphicsMatrix()
-%% Option = {a, float()} | {b, float()} | {c, float()} | {d, float()} | {tx, float()} | {ty, float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatematrix">external documentation</a>.
+-spec createMatrix(This, [Option]) -> wxGraphicsMatrix:wxGraphicsMatrix() when
+ This::wxGraphicsRenderer(),
+ Option :: {a, number()}
+ | {b, number()}
+ | {c, number()}
+ | {d, number()}
+ | {tx, number()}
+ | {ty, number()}.
createMatrix(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGraphicsRenderer),
@@ -127,8 +145,9 @@ createMatrix(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGraphicsRenderer_CreateMatrix,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGraphicsRenderer()) -> wxGraphicsPath:wxGraphicsPath()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgraphicsrenderer.html#wxgraphicsrenderercreatepath">external documentation</a>.
+-spec createPath(This) -> wxGraphicsPath:wxGraphicsPath() when
+ This::wxGraphicsRenderer().
createPath(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGraphicsRenderer),
wxe_util:call(?wxGraphicsRenderer_CreatePath,
diff --git a/lib/wx/src/gen/wxGrid.erl b/lib/wx/src/gen/wxGrid.erl
index 7b62ec33a4..2f4b45b1bc 100644
--- a/lib/wx/src/gen/wxGrid.erl
+++ b/lib/wx/src/gen/wxGrid.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +125,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxGrid/0]).
%% @hidden
parent_class(wxScrolledWindow) -> true;
parent_class(wxPanel) -> true;
@@ -132,27 +133,36 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGrid()
+-type wxGrid() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridwxgrid">external documentation</a>.
+-spec new() -> wxGrid().
new() ->
wxe_util:construct(?wxGrid_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxGrid()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxGrid() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(),X::integer(),X::integer()|term()) -> wxGrid()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridwxgrid">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Parent::wxWindow:wxWindow(), X::integer(), Y::integer()) -> new(Parent,X,Y, []) </c></p>
-%% <p><c>
-%% new(Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxGrid() </c>
-%%<br /> Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Parent, Id, [Option]) -> wxGrid() when<br />
+%% Parent::wxWindow:wxWindow(), Id::integer(),<br />
+%% Option :: {pos, {X::integer(), Y::integer()}}<br />
+%% | {size, {W::integer(), H::integer()}}<br />
+%% | {style, integer()}.<br />
+%%
+-spec new(Parent, X, Y) -> wxGrid() when
+ Parent::wxWindow:wxWindow(), X::integer(), Y::integer();
+ (Parent, Id, [Option]) -> wxGrid() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(Parent,X,Y)
when is_record(Parent, wx_ref),is_integer(X),is_integer(Y) ->
@@ -168,9 +178,12 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxGrid_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (Parent::wxWindow:wxWindow(), X::integer(), Y::integer(), [Option]) -> wxGrid()
-%% Option = {w, integer()} | {h, integer()} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridwxgrid">external documentation</a>.
+-spec new(Parent, X, Y, [Option]) -> wxGrid() when
+ Parent::wxWindow:wxWindow(), X::integer(), Y::integer(),
+ Option :: {w, integer()}
+ | {h, integer()}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},X,Y, Options)
when is_integer(X),is_integer(Y),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -182,15 +195,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},X,Y, Options)
wxe_util:construct(?wxGrid_new_4,
<<ParentRef:32/?UI,X:32/?UI,Y:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> bool()
%% @equiv appendCols(This, [])
+-spec appendCols(This) -> boolean() when
+ This::wxGrid().
+
appendCols(This)
when is_record(This, wx_ref) ->
appendCols(This, []).
-%% @spec (This::wxGrid(), [Option]) -> bool()
-%% Option = {numCols, integer()} | {updateLabels, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridappendcols">external documentation</a>.
+-spec appendCols(This, [Option]) -> boolean() when
+ This::wxGrid(),
+ Option :: {numCols, integer()}
+ | {updateLabels, boolean()}.
appendCols(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -201,15 +218,19 @@ appendCols(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGrid_AppendCols,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> bool()
%% @equiv appendRows(This, [])
+-spec appendRows(This) -> boolean() when
+ This::wxGrid().
+
appendRows(This)
when is_record(This, wx_ref) ->
appendRows(This, []).
-%% @spec (This::wxGrid(), [Option]) -> bool()
-%% Option = {numRows, integer()} | {updateLabels, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridappendrows">external documentation</a>.
+-spec appendRows(This, [Option]) -> boolean() when
+ This::wxGrid(),
+ Option :: {numRows, integer()}
+ | {updateLabels, boolean()}.
appendRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -220,22 +241,26 @@ appendRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGrid_AppendRows,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridautosize">external documentation</a>.
+-spec autoSize(This) -> ok when
+ This::wxGrid().
autoSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_AutoSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer()) -> ok
%% @equiv autoSizeColumn(This,Col, [])
+-spec autoSizeColumn(This, Col) -> ok when
+ This::wxGrid(), Col::integer().
+
autoSizeColumn(This,Col)
when is_record(This, wx_ref),is_integer(Col) ->
autoSizeColumn(This,Col, []).
-%% @spec (This::wxGrid(), Col::integer(), [Option]) -> ok
-%% Option = {setAsMin, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridautosizecolumn">external documentation</a>.
+-spec autoSizeColumn(This, Col, [Option]) -> ok when
+ This::wxGrid(), Col::integer(),
+ Option :: {setAsMin, boolean()}.
autoSizeColumn(#wx_ref{type=ThisT,ref=ThisRef},Col, Options)
when is_integer(Col),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -245,15 +270,18 @@ autoSizeColumn(#wx_ref{type=ThisT,ref=ThisRef},Col, Options)
wxe_util:cast(?wxGrid_AutoSizeColumn,
<<ThisRef:32/?UI,Col:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv autoSizeColumns(This, [])
+-spec autoSizeColumns(This) -> ok when
+ This::wxGrid().
+
autoSizeColumns(This)
when is_record(This, wx_ref) ->
autoSizeColumns(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {setAsMin, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridautosizecolumns">external documentation</a>.
+-spec autoSizeColumns(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {setAsMin, boolean()}.
autoSizeColumns(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -263,15 +291,18 @@ autoSizeColumns(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_AutoSizeColumns,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Row::integer()) -> ok
%% @equiv autoSizeRow(This,Row, [])
+-spec autoSizeRow(This, Row) -> ok when
+ This::wxGrid(), Row::integer().
+
autoSizeRow(This,Row)
when is_record(This, wx_ref),is_integer(Row) ->
autoSizeRow(This,Row, []).
-%% @spec (This::wxGrid(), Row::integer(), [Option]) -> ok
-%% Option = {setAsMin, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridautosizerow">external documentation</a>.
+-spec autoSizeRow(This, Row, [Option]) -> ok when
+ This::wxGrid(), Row::integer(),
+ Option :: {setAsMin, boolean()}.
autoSizeRow(#wx_ref{type=ThisT,ref=ThisRef},Row, Options)
when is_integer(Row),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -281,15 +312,18 @@ autoSizeRow(#wx_ref{type=ThisT,ref=ThisRef},Row, Options)
wxe_util:cast(?wxGrid_AutoSizeRow,
<<ThisRef:32/?UI,Row:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv autoSizeRows(This, [])
+-spec autoSizeRows(This) -> ok when
+ This::wxGrid().
+
autoSizeRows(This)
when is_record(This, wx_ref) ->
autoSizeRows(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {setAsMin, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridautosizerows">external documentation</a>.
+-spec autoSizeRows(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {setAsMin, boolean()}.
autoSizeRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -299,90 +333,102 @@ autoSizeRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_AutoSizeRows,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridbeginbatch">external documentation</a>.
+-spec beginBatch(This) -> ok when
+ This::wxGrid().
beginBatch(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_BeginBatch,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), TopLeft::{R::integer(),C::integer()}, BottomRight::{R::integer(),C::integer()}) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridblocktodevicerect">external documentation</a>.
+-spec blockToDeviceRect(This, TopLeft, BottomRight) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxGrid(), TopLeft::{R::integer(), C::integer()}, BottomRight::{R::integer(), C::integer()}.
blockToDeviceRect(#wx_ref{type=ThisT,ref=ThisRef},{TopLeftR,TopLeftC},{BottomRightR,BottomRightC})
when is_integer(TopLeftR),is_integer(TopLeftC),is_integer(BottomRightR),is_integer(BottomRightC) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_BlockToDeviceRect,
<<ThisRef:32/?UI,TopLeftR:32/?UI,TopLeftC:32/?UI,BottomRightR:32/?UI,BottomRightC:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcandragcolsize">external documentation</a>.
+-spec canDragColSize(This) -> boolean() when
+ This::wxGrid().
canDragColSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_CanDragColSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcandragrowsize">external documentation</a>.
+-spec canDragRowSize(This) -> boolean() when
+ This::wxGrid().
canDragRowSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_CanDragRowSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcandraggridsize">external documentation</a>.
+-spec canDragGridSize(This) -> boolean() when
+ This::wxGrid().
canDragGridSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_CanDragGridSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcanenablecellcontrol">external documentation</a>.
+-spec canEnableCellControl(This) -> boolean() when
+ This::wxGrid().
canEnableCellControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_CanEnableCellControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcelltorect">external documentation</a>.
+-spec cellToRect(This, Coords) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxGrid(), Coords::{R::integer(), C::integer()}.
cellToRect(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_CellToRect_1,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcelltorect">external documentation</a>.
+-spec cellToRect(This, Row, Col) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxGrid(), Row::integer(), Col::integer().
cellToRect(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_CellToRect_2,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcleargrid">external documentation</a>.
+-spec clearGrid(This) -> ok when
+ This::wxGrid().
clearGrid(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_ClearGrid,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridclearselection">external documentation</a>.
+-spec clearSelection(This) -> ok when
+ This::wxGrid().
clearSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_ClearSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), NumRows::integer(), NumCols::integer()) -> bool()
%% @equiv createGrid(This,NumRows,NumCols, [])
+-spec createGrid(This, NumRows, NumCols) -> boolean() when
+ This::wxGrid(), NumRows::integer(), NumCols::integer().
+
createGrid(This,NumRows,NumCols)
when is_record(This, wx_ref),is_integer(NumRows),is_integer(NumCols) ->
createGrid(This,NumRows,NumCols, []).
-%% @spec (This::wxGrid(), NumRows::integer(), NumCols::integer(), [Option]) -> bool()
-%% Option = {selmode, WxGridSelectionModes}
-%% WxGridSelectionModes = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridcreategrid">external documentation</a>.
-%%<br /> WxGridSelectionModes is one of ?wxGrid_wxGridSelectCells | ?wxGrid_wxGridSelectRows | ?wxGrid_wxGridSelectColumns
+%%<br /> Selmode = ?wxGrid_wxGridSelectCells | ?wxGrid_wxGridSelectRows | ?wxGrid_wxGridSelectColumns
+-spec createGrid(This, NumRows, NumCols, [Option]) -> boolean() when
+ This::wxGrid(), NumRows::integer(), NumCols::integer(),
+ Option :: {selmode, wx:wx_enum()}.
createGrid(#wx_ref{type=ThisT,ref=ThisRef},NumRows,NumCols, Options)
when is_integer(NumRows),is_integer(NumCols),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -392,15 +438,20 @@ createGrid(#wx_ref{type=ThisT,ref=ThisRef},NumRows,NumCols, Options)
wxe_util:call(?wxGrid_CreateGrid,
<<ThisRef:32/?UI,NumRows:32/?UI,NumCols:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> bool()
%% @equiv deleteCols(This, [])
+-spec deleteCols(This) -> boolean() when
+ This::wxGrid().
+
deleteCols(This)
when is_record(This, wx_ref) ->
deleteCols(This, []).
-%% @spec (This::wxGrid(), [Option]) -> bool()
-%% Option = {pos, integer()} | {numCols, integer()} | {updateLabels, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgriddeletecols">external documentation</a>.
+-spec deleteCols(This, [Option]) -> boolean() when
+ This::wxGrid(),
+ Option :: {pos, integer()}
+ | {numCols, integer()}
+ | {updateLabels, boolean()}.
deleteCols(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -412,15 +463,20 @@ deleteCols(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGrid_DeleteCols,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> bool()
%% @equiv deleteRows(This, [])
+-spec deleteRows(This) -> boolean() when
+ This::wxGrid().
+
deleteRows(This)
when is_record(This, wx_ref) ->
deleteRows(This, []).
-%% @spec (This::wxGrid(), [Option]) -> bool()
-%% Option = {pos, integer()} | {numRows, integer()} | {updateLabels, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgriddeleterows">external documentation</a>.
+-spec deleteRows(This, [Option]) -> boolean() when
+ This::wxGrid(),
+ Option :: {pos, integer()}
+ | {numRows, integer()}
+ | {updateLabels, boolean()}.
deleteRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -432,43 +488,50 @@ deleteRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGrid_DeleteRows,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgriddisablecelleditcontrol">external documentation</a>.
+-spec disableCellEditControl(This) -> ok when
+ This::wxGrid().
disableCellEditControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_DisableCellEditControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgriddisabledragcolsize">external documentation</a>.
+-spec disableDragColSize(This) -> ok when
+ This::wxGrid().
disableDragColSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_DisableDragColSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgriddisabledraggridsize">external documentation</a>.
+-spec disableDragGridSize(This) -> ok when
+ This::wxGrid().
disableDragGridSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_DisableDragGridSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgriddisabledragrowsize">external documentation</a>.
+-spec disableDragRowSize(This) -> ok when
+ This::wxGrid().
disableDragRowSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_DisableDragRowSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv enableCellEditControl(This, [])
+-spec enableCellEditControl(This) -> ok when
+ This::wxGrid().
+
enableCellEditControl(This)
when is_record(This, wx_ref) ->
enableCellEditControl(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridenablecelleditcontrol">external documentation</a>.
+-spec enableCellEditControl(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {enable, boolean()}.
enableCellEditControl(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -478,15 +541,18 @@ enableCellEditControl(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_EnableCellEditControl,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv enableDragColSize(This, [])
+-spec enableDragColSize(This) -> ok when
+ This::wxGrid().
+
enableDragColSize(This)
when is_record(This, wx_ref) ->
enableDragColSize(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridenabledragcolsize">external documentation</a>.
+-spec enableDragColSize(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {enable, boolean()}.
enableDragColSize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -496,15 +562,18 @@ enableDragColSize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_EnableDragColSize,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv enableDragGridSize(This, [])
+-spec enableDragGridSize(This) -> ok when
+ This::wxGrid().
+
enableDragGridSize(This)
when is_record(This, wx_ref) ->
enableDragGridSize(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridenabledraggridsize">external documentation</a>.
+-spec enableDragGridSize(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {enable, boolean()}.
enableDragGridSize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -514,15 +583,18 @@ enableDragGridSize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_EnableDragGridSize,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv enableDragRowSize(This, [])
+-spec enableDragRowSize(This) -> ok when
+ This::wxGrid().
+
enableDragRowSize(This)
when is_record(This, wx_ref) ->
enableDragRowSize(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridenabledragrowsize">external documentation</a>.
+-spec enableDragRowSize(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {enable, boolean()}.
enableDragRowSize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -532,23 +604,27 @@ enableDragRowSize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_EnableDragRowSize,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Edit::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridenableediting">external documentation</a>.
+-spec enableEditing(This, Edit) -> ok when
+ This::wxGrid(), Edit::boolean().
enableEditing(#wx_ref{type=ThisT,ref=ThisRef},Edit)
when is_boolean(Edit) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_EnableEditing,
<<ThisRef:32/?UI,(wxe_util:from_bool(Edit)):32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @equiv enableGridLines(This, [])
+-spec enableGridLines(This) -> ok when
+ This::wxGrid().
+
enableGridLines(This)
when is_record(This, wx_ref) ->
enableGridLines(This, []).
-%% @spec (This::wxGrid(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridenablegridlines">external documentation</a>.
+-spec enableGridLines(This, [Option]) -> ok when
+ This::wxGrid(),
+ Option :: {enable, boolean()}.
enableGridLines(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -558,194 +634,220 @@ enableGridLines(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGrid_EnableGridLines,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridendbatch">external documentation</a>.
+-spec endBatch(This) -> ok when
+ This::wxGrid().
endBatch(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_EndBatch,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridfit">external documentation</a>.
+-spec fit(This) -> ok when
+ This::wxGrid().
fit(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_Fit,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridforcerefresh">external documentation</a>.
+-spec forceRefresh(This) -> ok when
+ This::wxGrid().
forceRefresh(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_ForceRefresh,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetbatchcount">external documentation</a>.
+-spec getBatchCount(This) -> integer() when
+ This::wxGrid().
getBatchCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetBatchCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> {Horiz::integer(),Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellalignment">external documentation</a>.
+-spec getCellAlignment(This, Row, Col) -> {Horiz::integer(), Vert::integer()} when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellAlignment(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellAlignment,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellbackgroundcolour">external documentation</a>.
+-spec getCellBackgroundColour(This, Row, Col) -> wx:wx_colour4() when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellBackgroundColour,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcelleditor">external documentation</a>.
+-spec getCellEditor(This, Row, Col) -> wxGridCellEditor:wxGridCellEditor() when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellEditor(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellEditor,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellfont">external documentation</a>.
+-spec getCellFont(This, Row, Col) -> wxFont:wxFont() when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellFont(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellFont,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wxGridCellRenderer:wxGridCellRenderer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellrenderer">external documentation</a>.
+-spec getCellRenderer(This, Row, Col) -> wxGridCellRenderer:wxGridCellRenderer() when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellRenderer(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellRenderer,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcelltextcolour">external documentation</a>.
+-spec getCellTextColour(This, Row, Col) -> wx:wx_colour4() when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellTextColour,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellvalue">external documentation</a>.
+-spec getCellValue(This, Coords) -> unicode:charlist() when
+ This::wxGrid(), Coords::{R::integer(), C::integer()}.
getCellValue(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellValue_1,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcellvalue">external documentation</a>.
+-spec getCellValue(This, Row, Col) -> unicode:charlist() when
+ This::wxGrid(), Row::integer(), Col::integer().
getCellValue(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetCellValue_2,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid()) -> {Horiz::integer(),Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcollabelalignment">external documentation</a>.
+-spec getColLabelAlignment(This) -> {Horiz::integer(), Vert::integer()} when
+ This::wxGrid().
getColLabelAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetColLabelAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcollabelsize">external documentation</a>.
+-spec getColLabelSize(This) -> integer() when
+ This::wxGrid().
getColLabelSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetColLabelSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcollabelvalue">external documentation</a>.
+-spec getColLabelValue(This, Col) -> unicode:charlist() when
+ This::wxGrid(), Col::integer().
getColLabelValue(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetColLabelValue,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetcolminimalacceptablewidth">external documentation</a>.
+-spec getColMinimalAcceptableWidth(This) -> integer() when
+ This::wxGrid().
getColMinimalAcceptableWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetColMinimalAcceptableWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> {Horiz::integer(),Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcellalignment">external documentation</a>.
+-spec getDefaultCellAlignment(This) -> {Horiz::integer(), Vert::integer()} when
+ This::wxGrid().
getDefaultCellAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultCellAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcellbackgroundcolour">external documentation</a>.
+-spec getDefaultCellBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxGrid().
getDefaultCellBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultCellBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcellfont">external documentation</a>.
+-spec getDefaultCellFont(This) -> wxFont:wxFont() when
+ This::wxGrid().
getDefaultCellFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultCellFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcelltextcolour">external documentation</a>.
+-spec getDefaultCellTextColour(This) -> wx:wx_colour4() when
+ This::wxGrid().
getDefaultCellTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultCellTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcollabelsize">external documentation</a>.
+-spec getDefaultColLabelSize(This) -> integer() when
+ This::wxGrid().
getDefaultColLabelSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultColLabelSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultcolsize">external documentation</a>.
+-spec getDefaultColSize(This) -> integer() when
+ This::wxGrid().
getDefaultColSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultColSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaulteditor">external documentation</a>.
+-spec getDefaultEditor(This) -> wxGridCellEditor:wxGridCellEditor() when
+ This::wxGrid().
getDefaultEditor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultEditor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), C::{R::integer(),C::integer()}) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaulteditorforcell">external documentation</a>.
+-spec getDefaultEditorForCell(This, C) -> wxGridCellEditor:wxGridCellEditor() when
+ This::wxGrid(), C::{R::integer(), C::integer()}.
getDefaultEditorForCell(#wx_ref{type=ThisT,ref=ThisRef},{CR,CC})
when is_integer(CR),is_integer(CC) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultEditorForCell_1,
<<ThisRef:32/?UI,CR:32/?UI,CC:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaulteditorforcell">external documentation</a>.
+-spec getDefaultEditorForCell(This, Row, Col) -> wxGridCellEditor:wxGridCellEditor() when
+ This::wxGrid(), Row::integer(), Col::integer().
getDefaultEditorForCell(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultEditorForCell_2,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), TypeName::string()) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaulteditorfortype">external documentation</a>.
+-spec getDefaultEditorForType(This, TypeName) -> wxGridCellEditor:wxGridCellEditor() when
+ This::wxGrid(), TypeName::unicode:chardata().
getDefaultEditorForType(#wx_ref{type=ThisT,ref=ThisRef},TypeName)
when is_list(TypeName) ->
?CLASS(ThisT,wxGrid),
@@ -753,23 +855,26 @@ getDefaultEditorForType(#wx_ref{type=ThisT,ref=ThisRef},TypeName)
wxe_util:call(?wxGrid_GetDefaultEditorForType,
<<ThisRef:32/?UI,(byte_size(TypeName_UC)):32/?UI,(TypeName_UC)/binary, 0:(((8- ((0+byte_size(TypeName_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGrid()) -> wxGridCellRenderer:wxGridCellRenderer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultrenderer">external documentation</a>.
+-spec getDefaultRenderer(This) -> wxGridCellRenderer:wxGridCellRenderer() when
+ This::wxGrid().
getDefaultRenderer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultRenderer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wxGridCellRenderer:wxGridCellRenderer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultrendererforcell">external documentation</a>.
+-spec getDefaultRendererForCell(This, Row, Col) -> wxGridCellRenderer:wxGridCellRenderer() when
+ This::wxGrid(), Row::integer(), Col::integer().
getDefaultRendererForCell(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultRendererForCell,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), TypeName::string()) -> wxGridCellRenderer:wxGridCellRenderer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultrendererfortype">external documentation</a>.
+-spec getDefaultRendererForType(This, TypeName) -> wxGridCellRenderer:wxGridCellRenderer() when
+ This::wxGrid(), TypeName::unicode:chardata().
getDefaultRendererForType(#wx_ref{type=ThisT,ref=ThisRef},TypeName)
when is_list(TypeName) ->
?CLASS(ThisT,wxGrid),
@@ -777,242 +882,279 @@ getDefaultRendererForType(#wx_ref{type=ThisT,ref=ThisRef},TypeName)
wxe_util:call(?wxGrid_GetDefaultRendererForType,
<<ThisRef:32/?UI,(byte_size(TypeName_UC)):32/?UI,(TypeName_UC)/binary, 0:(((8- ((0+byte_size(TypeName_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultrowlabelsize">external documentation</a>.
+-spec getDefaultRowLabelSize(This) -> integer() when
+ This::wxGrid().
getDefaultRowLabelSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultRowLabelSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetdefaultrowsize">external documentation</a>.
+-spec getDefaultRowSize(This) -> integer() when
+ This::wxGrid().
getDefaultRowSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetDefaultRowSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridcursorcol">external documentation</a>.
+-spec getGridCursorCol(This) -> integer() when
+ This::wxGrid().
getGridCursorCol(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridCursorCol,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridcursorrow">external documentation</a>.
+-spec getGridCursorRow(This) -> integer() when
+ This::wxGrid().
getGridCursorRow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridCursorRow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridlinecolour">external documentation</a>.
+-spec getGridLineColour(This) -> wx:wx_colour4() when
+ This::wxGrid().
getGridLineColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridLineColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgridlinesenabled">external documentation</a>.
+-spec gridLinesEnabled(This) -> boolean() when
+ This::wxGrid().
gridLinesEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GridLinesEnabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetlabelbackgroundcolour">external documentation</a>.
+-spec getLabelBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxGrid().
getLabelBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetLabelBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetlabelfont">external documentation</a>.
+-spec getLabelFont(This) -> wxFont:wxFont() when
+ This::wxGrid().
getLabelFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetLabelFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetlabeltextcolour">external documentation</a>.
+-spec getLabelTextColour(This) -> wx:wx_colour4() when
+ This::wxGrid().
getLabelTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetLabelTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetnumbercols">external documentation</a>.
+-spec getNumberCols(This) -> integer() when
+ This::wxGrid().
getNumberCols(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetNumberCols,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetnumberrows">external documentation</a>.
+-spec getNumberRows(This) -> integer() when
+ This::wxGrid().
getNumberRows(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetNumberRows,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> wxGridCellAttr:wxGridCellAttr()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetorcreatecellattr">external documentation</a>.
+-spec getOrCreateCellAttr(This, Row, Col) -> wxGridCellAttr:wxGridCellAttr() when
+ This::wxGrid(), Row::integer(), Col::integer().
getOrCreateCellAttr(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetOrCreateCellAttr,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetrowminimalacceptableheight">external documentation</a>.
+-spec getRowMinimalAcceptableHeight(This) -> integer() when
+ This::wxGrid().
getRowMinimalAcceptableHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetRowMinimalAcceptableHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> {Horiz::integer(),Vert::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetrowlabelalignment">external documentation</a>.
+-spec getRowLabelAlignment(This) -> {Horiz::integer(), Vert::integer()} when
+ This::wxGrid().
getRowLabelAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetRowLabelAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetrowlabelsize">external documentation</a>.
+-spec getRowLabelSize(This) -> integer() when
+ This::wxGrid().
getRowLabelSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetRowLabelSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetrowlabelvalue">external documentation</a>.
+-spec getRowLabelValue(This, Row) -> unicode:charlist() when
+ This::wxGrid(), Row::integer().
getRowLabelValue(#wx_ref{type=ThisT,ref=ThisRef},Row)
when is_integer(Row) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetRowLabelValue,
<<ThisRef:32/?UI,Row:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetrowsize">external documentation</a>.
+-spec getRowSize(This, Row) -> integer() when
+ This::wxGrid(), Row::integer().
getRowSize(#wx_ref{type=ThisT,ref=ThisRef},Row)
when is_integer(Row) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetRowSize,
<<ThisRef:32/?UI,Row:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetscrolllinex">external documentation</a>.
+-spec getScrollLineX(This) -> integer() when
+ This::wxGrid().
getScrollLineX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetScrollLineX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetscrollliney">external documentation</a>.
+-spec getScrollLineY(This) -> integer() when
+ This::wxGrid().
getScrollLineY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetScrollLineY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [{R::integer(),C::integer()}]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectedcells">external documentation</a>.
+-spec getSelectedCells(This) -> [{R::integer(), C::integer()}] when
+ This::wxGrid().
getSelectedCells(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectedCells,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [integer()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectedcols">external documentation</a>.
+-spec getSelectedCols(This) -> [integer()] when
+ This::wxGrid().
getSelectedCols(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectedCols,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [integer()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectedrows">external documentation</a>.
+-spec getSelectedRows(This) -> [integer()] when
+ This::wxGrid().
getSelectedRows(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectedRows,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectionbackground">external documentation</a>.
+-spec getSelectionBackground(This) -> wx:wx_colour4() when
+ This::wxGrid().
getSelectionBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectionBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [{R::integer(),C::integer()}]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectionblocktopleft">external documentation</a>.
+-spec getSelectionBlockTopLeft(This) -> [{R::integer(), C::integer()}] when
+ This::wxGrid().
getSelectionBlockTopLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectionBlockTopLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> [{R::integer(),C::integer()}]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectionblockbottomright">external documentation</a>.
+-spec getSelectionBlockBottomRight(This) -> [{R::integer(), C::integer()}] when
+ This::wxGrid().
getSelectionBlockBottomRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectionBlockBottomRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetselectionforeground">external documentation</a>.
+-spec getSelectionForeground(This) -> wx:wx_colour4() when
+ This::wxGrid().
getSelectionForeground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetSelectionForeground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetviewwidth">external documentation</a>.
+-spec getViewWidth(This) -> integer() when
+ This::wxGrid().
getViewWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetViewWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridwindow">external documentation</a>.
+-spec getGridWindow(This) -> wxWindow:wxWindow() when
+ This::wxGrid().
getGridWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridrowlabelwindow">external documentation</a>.
+-spec getGridRowLabelWindow(This) -> wxWindow:wxWindow() when
+ This::wxGrid().
getGridRowLabelWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridRowLabelWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridcollabelwindow">external documentation</a>.
+-spec getGridColLabelWindow(This) -> wxWindow:wxWindow() when
+ This::wxGrid().
getGridColLabelWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridColLabelWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridgetgridcornerlabelwindow">external documentation</a>.
+-spec getGridCornerLabelWindow(This) -> wxWindow:wxWindow() when
+ This::wxGrid().
getGridCornerLabelWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_GetGridCornerLabelWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridhidecelleditcontrol">external documentation</a>.
+-spec hideCellEditControl(This) -> ok when
+ This::wxGrid().
hideCellEditControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_HideCellEditControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @equiv insertCols(This, [])
+-spec insertCols(This) -> boolean() when
+ This::wxGrid().
+
insertCols(This)
when is_record(This, wx_ref) ->
insertCols(This, []).
-%% @spec (This::wxGrid(), [Option]) -> bool()
-%% Option = {pos, integer()} | {numCols, integer()} | {updateLabels, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridinsertcols">external documentation</a>.
+-spec insertCols(This, [Option]) -> boolean() when
+ This::wxGrid(),
+ Option :: {pos, integer()}
+ | {numCols, integer()}
+ | {updateLabels, boolean()}.
insertCols(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1024,15 +1166,20 @@ insertCols(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGrid_InsertCols,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> bool()
%% @equiv insertRows(This, [])
+-spec insertRows(This) -> boolean() when
+ This::wxGrid().
+
insertRows(This)
when is_record(This, wx_ref) ->
insertRows(This, []).
-%% @spec (This::wxGrid(), [Option]) -> bool()
-%% Option = {pos, integer()} | {numRows, integer()} | {updateLabels, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridinsertrows">external documentation</a>.
+-spec insertRows(This, [Option]) -> boolean() when
+ This::wxGrid(),
+ Option :: {pos, integer()}
+ | {numRows, integer()}
+ | {updateLabels, boolean()}.
insertRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1044,73 +1191,84 @@ insertRows(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxGrid_InsertRows,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridiscelleditcontrolenabled">external documentation</a>.
+-spec isCellEditControlEnabled(This) -> boolean() when
+ This::wxGrid().
isCellEditControlEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsCellEditControlEnabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridiscurrentcellreadonly">external documentation</a>.
+-spec isCurrentCellReadOnly(This) -> boolean() when
+ This::wxGrid().
isCurrentCellReadOnly(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsCurrentCellReadOnly,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridiseditable">external documentation</a>.
+-spec isEditable(This) -> boolean() when
+ This::wxGrid().
isEditable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsEditable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisinselection">external documentation</a>.
+-spec isInSelection(This, Coords) -> boolean() when
+ This::wxGrid(), Coords::{R::integer(), C::integer()}.
isInSelection(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsInSelection_1,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisinselection">external documentation</a>.
+-spec isInSelection(This, Row, Col) -> boolean() when
+ This::wxGrid(), Row::integer(), Col::integer().
isInSelection(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsInSelection_2,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisreadonly">external documentation</a>.
+-spec isReadOnly(This, Row, Col) -> boolean() when
+ This::wxGrid(), Row::integer(), Col::integer().
isReadOnly(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsReadOnly,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisselection">external documentation</a>.
+-spec isSelection(This) -> boolean() when
+ This::wxGrid().
isSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_IsSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> bool()
%% @equiv isVisible(This,Coords, [])
+-spec isVisible(This, Coords) -> boolean() when
+ This::wxGrid(), Coords::{R::integer(), C::integer()}.
+
isVisible(This,Coords={CoordsR,CoordsC})
when is_record(This, wx_ref),is_integer(CoordsR),is_integer(CoordsC) ->
isVisible(This,Coords, []).
-%% @spec (This::wxGrid(),X::integer()|term(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisvisible">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% isVisible(This::wxGrid(), Row::integer(), Col::integer()) -> isVisible(This,Row,Col, []) </c></p>
-%% <p><c>
-%% isVisible(This::wxGrid(), Coords::{R::integer(),C::integer()}, [Option]) -> bool() </c>
-%%<br /> Option = {wholeCellVisible, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% isVisible(This, Coords, [Option]) -> boolean() when<br />
+%% This::wxGrid(), Coords::{R::integer(), C::integer()},<br />
+%% Option :: {wholeCellVisible, boolean()}.<br />
+%%
+-spec isVisible(This, Row, Col) -> boolean() when
+ This::wxGrid(), Row::integer(), Col::integer();
+ (This, Coords, [Option]) -> boolean() when
+ This::wxGrid(), Coords::{R::integer(), C::integer()},
+ Option :: {wholeCellVisible, boolean()}.
isVisible(This,Row,Col)
when is_record(This, wx_ref),is_integer(Row),is_integer(Col) ->
@@ -1124,9 +1282,10 @@ isVisible(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC}, Options)
wxe_util:call(?wxGrid_IsVisible_2,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer(), [Option]) -> bool()
-%% Option = {wholeCellVisible, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridisvisible">external documentation</a>.
+-spec isVisible(This, Row, Col, [Option]) -> boolean() when
+ This::wxGrid(), Row::integer(), Col::integer(),
+ Option :: {wholeCellVisible, boolean()}.
isVisible(#wx_ref{type=ThisT,ref=ThisRef},Row,Col, Options)
when is_integer(Row),is_integer(Col),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1136,102 +1295,115 @@ isVisible(#wx_ref{type=ThisT,ref=ThisRef},Row,Col, Options)
wxe_util:call(?wxGrid_IsVisible_3,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmakecellvisible">external documentation</a>.
+-spec makeCellVisible(This, Coords) -> ok when
+ This::wxGrid(), Coords::{R::integer(), C::integer()}.
makeCellVisible(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC})
when is_integer(CoordsR),is_integer(CoordsC) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_MakeCellVisible_1,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmakecellvisible">external documentation</a>.
+-spec makeCellVisible(This, Row, Col) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer().
makeCellVisible(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_MakeCellVisible_2,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursordown">external documentation</a>.
+-spec moveCursorDown(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorDown(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorDown,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursorleft">external documentation</a>.
+-spec moveCursorLeft(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorLeft(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorLeft,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursorright">external documentation</a>.
+-spec moveCursorRight(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorRight(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorRight,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursorup">external documentation</a>.
+-spec moveCursorUp(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorUp(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorUp,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursordownblock">external documentation</a>.
+-spec moveCursorDownBlock(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorDownBlock(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorDownBlock,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursorleftblock">external documentation</a>.
+-spec moveCursorLeftBlock(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorLeftBlock(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorLeftBlock,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursorrightblock">external documentation</a>.
+-spec moveCursorRightBlock(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorRightBlock(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorRightBlock,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid(), ExpandSelection::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovecursorupblock">external documentation</a>.
+-spec moveCursorUpBlock(This, ExpandSelection) -> boolean() when
+ This::wxGrid(), ExpandSelection::boolean().
moveCursorUpBlock(#wx_ref{type=ThisT,ref=ThisRef},ExpandSelection)
when is_boolean(ExpandSelection) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MoveCursorUpBlock,
<<ThisRef:32/?UI,(wxe_util:from_bool(ExpandSelection)):32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovepagedown">external documentation</a>.
+-spec movePageDown(This) -> boolean() when
+ This::wxGrid().
movePageDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MovePageDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridmovepageup">external documentation</a>.
+-spec movePageUp(This) -> boolean() when
+ This::wxGrid().
movePageUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_MovePageUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), TypeName::string(), Renderer::wxGridCellRenderer:wxGridCellRenderer(), Editor::wxGridCellEditor:wxGridCellEditor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridregisterdatatype">external documentation</a>.
+-spec registerDataType(This, TypeName, Renderer, Editor) -> ok when
+ This::wxGrid(), TypeName::unicode:chardata(), Renderer::wxGridCellRenderer:wxGridCellRenderer(), Editor::wxGridCellEditor:wxGridCellEditor().
registerDataType(#wx_ref{type=ThisT,ref=ThisRef},TypeName,#wx_ref{type=RendererT,ref=RendererRef},#wx_ref{type=EditorT,ref=EditorRef})
when is_list(TypeName) ->
?CLASS(ThisT,wxGrid),
@@ -1241,29 +1413,34 @@ registerDataType(#wx_ref{type=ThisT,ref=ThisRef},TypeName,#wx_ref{type=RendererT
wxe_util:cast(?wxGrid_RegisterDataType,
<<ThisRef:32/?UI,(byte_size(TypeName_UC)):32/?UI,(TypeName_UC)/binary, 0:(((8- ((0+byte_size(TypeName_UC)) band 16#7)) band 16#7))/unit:8,RendererRef:32/?UI,EditorRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsaveeditcontrolvalue">external documentation</a>.
+-spec saveEditControlValue(This) -> ok when
+ This::wxGrid().
saveEditControlValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SaveEditControlValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridselectall">external documentation</a>.
+-spec selectAll(This) -> ok when
+ This::wxGrid().
selectAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SelectAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), TopLeft::{R::integer(),C::integer()}, BottomRight::{R::integer(),C::integer()}) -> ok
%% @equiv selectBlock(This,TopLeft,BottomRight, [])
+-spec selectBlock(This, TopLeft, BottomRight) -> ok when
+ This::wxGrid(), TopLeft::{R::integer(), C::integer()}, BottomRight::{R::integer(), C::integer()}.
+
selectBlock(This,TopLeft={TopLeftR,TopLeftC},BottomRight={BottomRightR,BottomRightC})
when is_record(This, wx_ref),is_integer(TopLeftR),is_integer(TopLeftC),is_integer(BottomRightR),is_integer(BottomRightC) ->
selectBlock(This,TopLeft,BottomRight, []).
-%% @spec (This::wxGrid(), TopLeft::{R::integer(),C::integer()}, BottomRight::{R::integer(),C::integer()}, [Option]) -> ok
-%% Option = {addToSelected, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridselectblock">external documentation</a>.
+-spec selectBlock(This, TopLeft, BottomRight, [Option]) -> ok when
+ This::wxGrid(), TopLeft::{R::integer(), C::integer()}, BottomRight::{R::integer(), C::integer()},
+ Option :: {addToSelected, boolean()}.
selectBlock(#wx_ref{type=ThisT,ref=ThisRef},{TopLeftR,TopLeftC},{BottomRightR,BottomRightC}, Options)
when is_integer(TopLeftR),is_integer(TopLeftC),is_integer(BottomRightR),is_integer(BottomRightC),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1273,15 +1450,18 @@ selectBlock(#wx_ref{type=ThisT,ref=ThisRef},{TopLeftR,TopLeftC},{BottomRightR,Bo
wxe_util:cast(?wxGrid_SelectBlock_3,
<<ThisRef:32/?UI,TopLeftR:32/?UI,TopLeftC:32/?UI,BottomRightR:32/?UI,BottomRightC:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), TopRow::integer(), LeftCol::integer(), BottomRow::integer(), RightCol::integer()) -> ok
%% @equiv selectBlock(This,TopRow,LeftCol,BottomRow,RightCol, [])
+-spec selectBlock(This, TopRow, LeftCol, BottomRow, RightCol) -> ok when
+ This::wxGrid(), TopRow::integer(), LeftCol::integer(), BottomRow::integer(), RightCol::integer().
+
selectBlock(This,TopRow,LeftCol,BottomRow,RightCol)
when is_record(This, wx_ref),is_integer(TopRow),is_integer(LeftCol),is_integer(BottomRow),is_integer(RightCol) ->
selectBlock(This,TopRow,LeftCol,BottomRow,RightCol, []).
-%% @spec (This::wxGrid(), TopRow::integer(), LeftCol::integer(), BottomRow::integer(), RightCol::integer(), [Option]) -> ok
-%% Option = {addToSelected, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridselectblock">external documentation</a>.
+-spec selectBlock(This, TopRow, LeftCol, BottomRow, RightCol, [Option]) -> ok when
+ This::wxGrid(), TopRow::integer(), LeftCol::integer(), BottomRow::integer(), RightCol::integer(),
+ Option :: {addToSelected, boolean()}.
selectBlock(#wx_ref{type=ThisT,ref=ThisRef},TopRow,LeftCol,BottomRow,RightCol, Options)
when is_integer(TopRow),is_integer(LeftCol),is_integer(BottomRow),is_integer(RightCol),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1291,15 +1471,18 @@ selectBlock(#wx_ref{type=ThisT,ref=ThisRef},TopRow,LeftCol,BottomRow,RightCol, O
wxe_util:cast(?wxGrid_SelectBlock_5,
<<ThisRef:32/?UI,TopRow:32/?UI,LeftCol:32/?UI,BottomRow:32/?UI,RightCol:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Col::integer()) -> ok
%% @equiv selectCol(This,Col, [])
+-spec selectCol(This, Col) -> ok when
+ This::wxGrid(), Col::integer().
+
selectCol(This,Col)
when is_record(This, wx_ref),is_integer(Col) ->
selectCol(This,Col, []).
-%% @spec (This::wxGrid(), Col::integer(), [Option]) -> ok
-%% Option = {addToSelected, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridselectcol">external documentation</a>.
+-spec selectCol(This, Col, [Option]) -> ok when
+ This::wxGrid(), Col::integer(),
+ Option :: {addToSelected, boolean()}.
selectCol(#wx_ref{type=ThisT,ref=ThisRef},Col, Options)
when is_integer(Col),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1309,15 +1492,18 @@ selectCol(#wx_ref{type=ThisT,ref=ThisRef},Col, Options)
wxe_util:cast(?wxGrid_SelectCol,
<<ThisRef:32/?UI,Col:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid(), Row::integer()) -> ok
%% @equiv selectRow(This,Row, [])
+-spec selectRow(This, Row) -> ok when
+ This::wxGrid(), Row::integer().
+
selectRow(This,Row)
when is_record(This, wx_ref),is_integer(Row) ->
selectRow(This,Row, []).
-%% @spec (This::wxGrid(), Row::integer(), [Option]) -> ok
-%% Option = {addToSelected, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridselectrow">external documentation</a>.
+-spec selectRow(This, Row, [Option]) -> ok when
+ This::wxGrid(), Row::integer(),
+ Option :: {addToSelected, boolean()}.
selectRow(#wx_ref{type=ThisT,ref=ThisRef},Row, Options)
when is_integer(Row),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1327,47 +1513,51 @@ selectRow(#wx_ref{type=ThisT,ref=ThisRef},Row, Options)
wxe_util:cast(?wxGrid_SelectRow,
<<ThisRef:32/?UI,Row:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid(), Align::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellalignment">external documentation</a>.
+-spec setCellAlignment(This, Align) -> ok when
+ This::wxGrid(), Align::integer().
setCellAlignment(#wx_ref{type=ThisT,ref=ThisRef},Align)
when is_integer(Align) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetCellAlignment_1,
<<ThisRef:32/?UI,Align:32/?UI>>).
-%% @spec (This::wxGrid(), Align::integer(), Row::integer(), Col::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellalignment">external documentation</a>.
+-spec setCellAlignment(This, Align, Row, Col) -> ok when
+ This::wxGrid(), Align::integer(), Row::integer(), Col::integer().
setCellAlignment(#wx_ref{type=ThisT,ref=ThisRef},Align,Row,Col)
when is_integer(Align),is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetCellAlignment_3,
<<ThisRef:32/?UI,Align:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer(), Horiz::integer(), Vert::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellalignment">external documentation</a>.
+-spec setCellAlignment(This, Row, Col, Horiz, Vert) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), Horiz::integer(), Vert::integer().
setCellAlignment(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,Horiz,Vert)
when is_integer(Row),is_integer(Col),is_integer(Horiz),is_integer(Vert) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetCellAlignment_4,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI,Horiz:32/?UI,Vert:32/?UI>>).
-%% @spec (This::wxGrid(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellbackgroundcolour">external documentation</a>.
+-spec setCellBackgroundColour(This, Col) -> ok when
+ This::wxGrid(), Col::wx:wx_colour().
setCellBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Col)
when tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetCellBackgroundColour_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxGrid(),X::integer()|term(),X::integer(),X::term()|integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellbackgroundcolour">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setCellBackgroundColour(This::wxGrid(), Row::integer(), Col::integer(), Val::wx:colour()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setCellBackgroundColour(This::wxGrid(), Colour::wx:colour(), Row::integer(), Col::integer()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setCellBackgroundColour(This, Colour, Row, Col) -> ok when<br />
+%% This::wxGrid(), Colour::wx:wx_colour(), Row::integer(), Col::integer().<br />
+%%
+-spec setCellBackgroundColour(This, Row, Col, Val) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), Val::wx:wx_colour();
+ (This, Colour, Row, Col) -> ok when
+ This::wxGrid(), Colour::wx:wx_colour(), Row::integer(), Col::integer().
setCellBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,Val)
when is_integer(Row),is_integer(Col),tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
@@ -1379,8 +1569,9 @@ setCellBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Colour,Row,Col)
wxe_util:cast(?wxGrid_SetCellBackgroundColour_3_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer(), Editor::wxGridCellEditor:wxGridCellEditor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcelleditor">external documentation</a>.
+-spec setCellEditor(This, Row, Col, Editor) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), Editor::wxGridCellEditor:wxGridCellEditor().
setCellEditor(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=EditorT,ref=EditorRef})
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
@@ -1388,8 +1579,9 @@ setCellEditor(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=EditorT,ref=E
wxe_util:cast(?wxGrid_SetCellEditor,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI,EditorRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer(), Val::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellfont">external documentation</a>.
+-spec setCellFont(This, Row, Col, Val) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), Val::wxFont:wxFont().
setCellFont(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=ValT,ref=ValRef})
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
@@ -1397,8 +1589,9 @@ setCellFont(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=ValT,ref=ValRef
wxe_util:cast(?wxGrid_SetCellFont,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI,ValRef:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer(), Renderer::wxGridCellRenderer:wxGridCellRenderer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellrenderer">external documentation</a>.
+-spec setCellRenderer(This, Row, Col, Renderer) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), Renderer::wxGridCellRenderer:wxGridCellRenderer().
setCellRenderer(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=RendererT,ref=RendererRef})
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
@@ -1406,23 +1599,24 @@ setCellRenderer(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=RendererT,r
wxe_util:cast(?wxGrid_SetCellRenderer,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI,RendererRef:32/?UI>>).
-%% @spec (This::wxGrid(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcelltextcolour">external documentation</a>.
+-spec setCellTextColour(This, Col) -> ok when
+ This::wxGrid(), Col::wx:wx_colour().
setCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Col)
when tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetCellTextColour_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxGrid(),X::integer()|term(),X::integer(),X::term()|integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcelltextcolour">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setCellTextColour(This::wxGrid(), Row::integer(), Col::integer(), Val::wx:colour()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setCellTextColour(This::wxGrid(), Val::wx:colour(), Row::integer(), Col::integer()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setCellTextColour(This, Val, Row, Col) -> ok when<br />
+%% This::wxGrid(), Val::wx:wx_colour(), Row::integer(), Col::integer().<br />
+%%
+-spec setCellTextColour(This, Row, Col, Val) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), Val::wx:wx_colour();
+ (This, Val, Row, Col) -> ok when
+ This::wxGrid(), Val::wx:wx_colour(), Row::integer(), Col::integer().
setCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,Val)
when is_integer(Row),is_integer(Col),tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
@@ -1434,8 +1628,9 @@ setCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Val,Row,Col)
wxe_util:cast(?wxGrid_SetCellTextColour_3_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Coords::{R::integer(),C::integer()}, S::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellvalue">external documentation</a>.
+-spec setCellValue(This, Coords, S) -> ok when
+ This::wxGrid(), Coords::{R::integer(), C::integer()}, S::unicode:chardata().
setCellValue(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC},S)
when is_integer(CoordsR),is_integer(CoordsC),is_list(S) ->
?CLASS(ThisT,wxGrid),
@@ -1443,15 +1638,15 @@ setCellValue(#wx_ref{type=ThisT,ref=ThisRef},{CoordsR,CoordsC},S)
wxe_util:cast(?wxGrid_SetCellValue_2,
<<ThisRef:32/?UI,CoordsR:32/?UI,CoordsC:32/?UI,(byte_size(S_UC)):32/?UI,(S_UC)/binary, 0:(((8- ((0+byte_size(S_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGrid(),X::integer()|string(),X::integer(),X::string()|integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcellvalue">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setCellValue(This::wxGrid(), Row::integer(), Col::integer(), S::string()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setCellValue(This::wxGrid(), Val::string(), Row::integer(), Col::integer()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setCellValue(This, Val, Row, Col) -> ok when<br />
+%% This::wxGrid(), Val::unicode:chardata(), Row::integer(), Col::integer().<br />
+%%
+-spec setCellValue(This, Row, Col, S) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(), S::unicode:chardata();
+ (This, Val, Row, Col) -> ok when
+ This::wxGrid(), Val::unicode:chardata(), Row::integer(), Col::integer().
setCellValue(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,S)
when is_integer(Row),is_integer(Col),is_list(S) ->
?CLASS(ThisT,wxGrid),
@@ -1465,8 +1660,9 @@ setCellValue(#wx_ref{type=ThisT,ref=ThisRef},Val,Row,Col)
wxe_util:cast(?wxGrid_SetCellValue_3_1,
<<ThisRef:32/?UI,(byte_size(Val_UC)):32/?UI,(Val_UC)/binary, 0:(((8- ((0+byte_size(Val_UC)) band 16#7)) band 16#7))/unit:8,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer(), Attr::wxGridCellAttr:wxGridCellAttr()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolattr">external documentation</a>.
+-spec setColAttr(This, Col, Attr) -> ok when
+ This::wxGrid(), Col::integer(), Attr::wxGridCellAttr:wxGridCellAttr().
setColAttr(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=AttrT,ref=AttrRef})
when is_integer(Col) ->
?CLASS(ThisT,wxGrid),
@@ -1474,31 +1670,37 @@ setColAttr(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=AttrT,ref=AttrRef})
wxe_util:cast(?wxGrid_SetColAttr,
<<ThisRef:32/?UI,Col:32/?UI,AttrRef:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolformatbool">external documentation</a>.
+-spec setColFormatBool(This, Col) -> ok when
+ This::wxGrid(), Col::integer().
setColFormatBool(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColFormatBool,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolformatnumber">external documentation</a>.
+-spec setColFormatNumber(This, Col) -> ok when
+ This::wxGrid(), Col::integer().
setColFormatNumber(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColFormatNumber,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer()) -> ok
%% @equiv setColFormatFloat(This,Col, [])
+-spec setColFormatFloat(This, Col) -> ok when
+ This::wxGrid(), Col::integer().
+
setColFormatFloat(This,Col)
when is_record(This, wx_ref),is_integer(Col) ->
setColFormatFloat(This,Col, []).
-%% @spec (This::wxGrid(), Col::integer(), [Option]) -> ok
-%% Option = {width, integer()} | {precision, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolformatfloat">external documentation</a>.
+-spec setColFormatFloat(This, Col, [Option]) -> ok when
+ This::wxGrid(), Col::integer(),
+ Option :: {width, integer()}
+ | {precision, integer()}.
setColFormatFloat(#wx_ref{type=ThisT,ref=ThisRef},Col, Options)
when is_integer(Col),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1509,8 +1711,9 @@ setColFormatFloat(#wx_ref{type=ThisT,ref=ThisRef},Col, Options)
wxe_util:cast(?wxGrid_SetColFormatFloat,
<<ThisRef:32/?UI,Col:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid(), Col::integer(), TypeName::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolformatcustom">external documentation</a>.
+-spec setColFormatCustom(This, Col, TypeName) -> ok when
+ This::wxGrid(), Col::integer(), TypeName::unicode:chardata().
setColFormatCustom(#wx_ref{type=ThisT,ref=ThisRef},Col,TypeName)
when is_integer(Col),is_list(TypeName) ->
?CLASS(ThisT,wxGrid),
@@ -1518,24 +1721,27 @@ setColFormatCustom(#wx_ref{type=ThisT,ref=ThisRef},Col,TypeName)
wxe_util:cast(?wxGrid_SetColFormatCustom,
<<ThisRef:32/?UI,Col:32/?UI,(byte_size(TypeName_UC)):32/?UI,(TypeName_UC)/binary, 0:(((8- ((4+byte_size(TypeName_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGrid(), Horiz::integer(), Vert::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcollabelalignment">external documentation</a>.
+-spec setColLabelAlignment(This, Horiz, Vert) -> ok when
+ This::wxGrid(), Horiz::integer(), Vert::integer().
setColLabelAlignment(#wx_ref{type=ThisT,ref=ThisRef},Horiz,Vert)
when is_integer(Horiz),is_integer(Vert) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColLabelAlignment,
<<ThisRef:32/?UI,Horiz:32/?UI,Vert:32/?UI>>).
-%% @spec (This::wxGrid(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcollabelsize">external documentation</a>.
+-spec setColLabelSize(This, Height) -> ok when
+ This::wxGrid(), Height::integer().
setColLabelSize(#wx_ref{type=ThisT,ref=ThisRef},Height)
when is_integer(Height) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColLabelSize,
<<ThisRef:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer(), Val::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcollabelvalue">external documentation</a>.
+-spec setColLabelValue(This, Col, Val) -> ok when
+ This::wxGrid(), Col::integer(), Val::unicode:chardata().
setColLabelValue(#wx_ref{type=ThisT,ref=ThisRef},Col,Val)
when is_integer(Col),is_list(Val) ->
?CLASS(ThisT,wxGrid),
@@ -1543,87 +1749,99 @@ setColLabelValue(#wx_ref{type=ThisT,ref=ThisRef},Col,Val)
wxe_util:cast(?wxGrid_SetColLabelValue,
<<ThisRef:32/?UI,Col:32/?UI,(byte_size(Val_UC)):32/?UI,(Val_UC)/binary, 0:(((8- ((4+byte_size(Val_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGrid(), Col::integer(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolminimalwidth">external documentation</a>.
+-spec setColMinimalWidth(This, Col, Width) -> ok when
+ This::wxGrid(), Col::integer(), Width::integer().
setColMinimalWidth(#wx_ref{type=ThisT,ref=ThisRef},Col,Width)
when is_integer(Col),is_integer(Width) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColMinimalWidth,
<<ThisRef:32/?UI,Col:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGrid(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolminimalacceptablewidth">external documentation</a>.
+-spec setColMinimalAcceptableWidth(This, Width) -> ok when
+ This::wxGrid(), Width::integer().
setColMinimalAcceptableWidth(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColMinimalAcceptableWidth,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGrid(), Col::integer(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetcolsize">external documentation</a>.
+-spec setColSize(This, Col, Width) -> ok when
+ This::wxGrid(), Col::integer(), Width::integer().
setColSize(#wx_ref{type=ThisT,ref=ThisRef},Col,Width)
when is_integer(Col),is_integer(Width) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetColSize,
<<ThisRef:32/?UI,Col:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGrid(), Horiz::integer(), Vert::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultcellalignment">external documentation</a>.
+-spec setDefaultCellAlignment(This, Horiz, Vert) -> ok when
+ This::wxGrid(), Horiz::integer(), Vert::integer().
setDefaultCellAlignment(#wx_ref{type=ThisT,ref=ThisRef},Horiz,Vert)
when is_integer(Horiz),is_integer(Vert) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetDefaultCellAlignment,
<<ThisRef:32/?UI,Horiz:32/?UI,Vert:32/?UI>>).
-%% @spec (This::wxGrid(), Val::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultcellbackgroundcolour">external documentation</a>.
+-spec setDefaultCellBackgroundColour(This, Val) -> ok when
+ This::wxGrid(), Val::wx:wx_colour().
setDefaultCellBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Val)
when tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetDefaultCellBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary>>).
-%% @spec (This::wxGrid(), Val::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultcellfont">external documentation</a>.
+-spec setDefaultCellFont(This, Val) -> ok when
+ This::wxGrid(), Val::wxFont:wxFont().
setDefaultCellFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ValT,ref=ValRef}) ->
?CLASS(ThisT,wxGrid),
?CLASS(ValT,wxFont),
wxe_util:cast(?wxGrid_SetDefaultCellFont,
<<ThisRef:32/?UI,ValRef:32/?UI>>).
-%% @spec (This::wxGrid(), Val::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultcelltextcolour">external documentation</a>.
+-spec setDefaultCellTextColour(This, Val) -> ok when
+ This::wxGrid(), Val::wx:wx_colour().
setDefaultCellTextColour(#wx_ref{type=ThisT,ref=ThisRef},Val)
when tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetDefaultCellTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary>>).
-%% @spec (This::wxGrid(), Editor::wxGridCellEditor:wxGridCellEditor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaulteditor">external documentation</a>.
+-spec setDefaultEditor(This, Editor) -> ok when
+ This::wxGrid(), Editor::wxGridCellEditor:wxGridCellEditor().
setDefaultEditor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=EditorT,ref=EditorRef}) ->
?CLASS(ThisT,wxGrid),
?CLASS(EditorT,wxGridCellEditor),
wxe_util:cast(?wxGrid_SetDefaultEditor,
<<ThisRef:32/?UI,EditorRef:32/?UI>>).
-%% @spec (This::wxGrid(), Renderer::wxGridCellRenderer:wxGridCellRenderer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultrenderer">external documentation</a>.
+-spec setDefaultRenderer(This, Renderer) -> ok when
+ This::wxGrid(), Renderer::wxGridCellRenderer:wxGridCellRenderer().
setDefaultRenderer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RendererT,ref=RendererRef}) ->
?CLASS(ThisT,wxGrid),
?CLASS(RendererT,wxGridCellRenderer),
wxe_util:cast(?wxGrid_SetDefaultRenderer,
<<ThisRef:32/?UI,RendererRef:32/?UI>>).
-%% @spec (This::wxGrid(), Width::integer()) -> ok
%% @equiv setDefaultColSize(This,Width, [])
+-spec setDefaultColSize(This, Width) -> ok when
+ This::wxGrid(), Width::integer().
+
setDefaultColSize(This,Width)
when is_record(This, wx_ref),is_integer(Width) ->
setDefaultColSize(This,Width, []).
-%% @spec (This::wxGrid(), Width::integer(), [Option]) -> ok
-%% Option = {resizeExistingCols, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultcolsize">external documentation</a>.
+-spec setDefaultColSize(This, Width, [Option]) -> ok when
+ This::wxGrid(), Width::integer(),
+ Option :: {resizeExistingCols, boolean()}.
setDefaultColSize(#wx_ref{type=ThisT,ref=ThisRef},Width, Options)
when is_integer(Width),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1633,15 +1851,18 @@ setDefaultColSize(#wx_ref{type=ThisT,ref=ThisRef},Width, Options)
wxe_util:cast(?wxGrid_SetDefaultColSize,
<<ThisRef:32/?UI,Width:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid(), Height::integer()) -> ok
%% @equiv setDefaultRowSize(This,Height, [])
+-spec setDefaultRowSize(This, Height) -> ok when
+ This::wxGrid(), Height::integer().
+
setDefaultRowSize(This,Height)
when is_record(This, wx_ref),is_integer(Height) ->
setDefaultRowSize(This,Height, []).
-%% @spec (This::wxGrid(), Height::integer(), [Option]) -> ok
-%% Option = {resizeExistingRows, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetdefaultrowsize">external documentation</a>.
+-spec setDefaultRowSize(This, Height, [Option]) -> ok when
+ This::wxGrid(), Height::integer(),
+ Option :: {resizeExistingRows, boolean()}.
setDefaultRowSize(#wx_ref{type=ThisT,ref=ThisRef},Height, Options)
when is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1651,63 +1872,72 @@ setDefaultRowSize(#wx_ref{type=ThisT,ref=ThisRef},Height, Options)
wxe_util:cast(?wxGrid_SetDefaultRowSize,
<<ThisRef:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetgridcursor">external documentation</a>.
+-spec setGridCursor(This, Row, Col) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer().
setGridCursor(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetGridCursor,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGrid(), Val::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetgridlinecolour">external documentation</a>.
+-spec setGridLineColour(This, Val) -> ok when
+ This::wxGrid(), Val::wx:wx_colour().
setGridLineColour(#wx_ref{type=ThisT,ref=ThisRef},Val)
when tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetGridLineColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary>>).
-%% @spec (This::wxGrid(), Val::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetlabelbackgroundcolour">external documentation</a>.
+-spec setLabelBackgroundColour(This, Val) -> ok when
+ This::wxGrid(), Val::wx:wx_colour().
setLabelBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Val)
when tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetLabelBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary>>).
-%% @spec (This::wxGrid(), Val::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetlabelfont">external documentation</a>.
+-spec setLabelFont(This, Val) -> ok when
+ This::wxGrid(), Val::wxFont:wxFont().
setLabelFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ValT,ref=ValRef}) ->
?CLASS(ThisT,wxGrid),
?CLASS(ValT,wxFont),
wxe_util:cast(?wxGrid_SetLabelFont,
<<ThisRef:32/?UI,ValRef:32/?UI>>).
-%% @spec (This::wxGrid(), Val::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetlabeltextcolour">external documentation</a>.
+-spec setLabelTextColour(This, Val) -> ok when
+ This::wxGrid(), Val::wx:wx_colour().
setLabelTextColour(#wx_ref{type=ThisT,ref=ThisRef},Val)
when tuple_size(Val) =:= 3; tuple_size(Val) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetLabelTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Val)):16/binary>>).
-%% @spec (This::wxGrid(), ExtraWidth::integer(), ExtraHeight::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetmargins">external documentation</a>.
+-spec setMargins(This, ExtraWidth, ExtraHeight) -> ok when
+ This::wxGrid(), ExtraWidth::integer(), ExtraHeight::integer().
setMargins(#wx_ref{type=ThisT,ref=ThisRef},ExtraWidth,ExtraHeight)
when is_integer(ExtraWidth),is_integer(ExtraHeight) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetMargins,
<<ThisRef:32/?UI,ExtraWidth:32/?UI,ExtraHeight:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer()) -> ok
%% @equiv setReadOnly(This,Row,Col, [])
+-spec setReadOnly(This, Row, Col) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer().
+
setReadOnly(This,Row,Col)
when is_record(This, wx_ref),is_integer(Row),is_integer(Col) ->
setReadOnly(This,Row,Col, []).
-%% @spec (This::wxGrid(), Row::integer(), Col::integer(), [Option]) -> ok
-%% Option = {isReadOnly, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetreadonly">external documentation</a>.
+-spec setReadOnly(This, Row, Col, [Option]) -> ok when
+ This::wxGrid(), Row::integer(), Col::integer(),
+ Option :: {isReadOnly, boolean()}.
setReadOnly(#wx_ref{type=ThisT,ref=ThisRef},Row,Col, Options)
when is_integer(Row),is_integer(Col),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1717,8 +1947,9 @@ setReadOnly(#wx_ref{type=ThisT,ref=ThisRef},Row,Col, Options)
wxe_util:cast(?wxGrid_SetReadOnly,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGrid(), Row::integer(), Attr::wxGridCellAttr:wxGridCellAttr()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowattr">external documentation</a>.
+-spec setRowAttr(This, Row, Attr) -> ok when
+ This::wxGrid(), Row::integer(), Attr::wxGridCellAttr:wxGridCellAttr().
setRowAttr(#wx_ref{type=ThisT,ref=ThisRef},Row,#wx_ref{type=AttrT,ref=AttrRef})
when is_integer(Row) ->
?CLASS(ThisT,wxGrid),
@@ -1726,24 +1957,27 @@ setRowAttr(#wx_ref{type=ThisT,ref=ThisRef},Row,#wx_ref{type=AttrT,ref=AttrRef})
wxe_util:cast(?wxGrid_SetRowAttr,
<<ThisRef:32/?UI,Row:32/?UI,AttrRef:32/?UI>>).
-%% @spec (This::wxGrid(), Horiz::integer(), Vert::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowlabelalignment">external documentation</a>.
+-spec setRowLabelAlignment(This, Horiz, Vert) -> ok when
+ This::wxGrid(), Horiz::integer(), Vert::integer().
setRowLabelAlignment(#wx_ref{type=ThisT,ref=ThisRef},Horiz,Vert)
when is_integer(Horiz),is_integer(Vert) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetRowLabelAlignment,
<<ThisRef:32/?UI,Horiz:32/?UI,Vert:32/?UI>>).
-%% @spec (This::wxGrid(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowlabelsize">external documentation</a>.
+-spec setRowLabelSize(This, Width) -> ok when
+ This::wxGrid(), Width::integer().
setRowLabelSize(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetRowLabelSize,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Val::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowlabelvalue">external documentation</a>.
+-spec setRowLabelValue(This, Row, Val) -> ok when
+ This::wxGrid(), Row::integer(), Val::unicode:chardata().
setRowLabelValue(#wx_ref{type=ThisT,ref=ThisRef},Row,Val)
when is_integer(Row),is_list(Val) ->
?CLASS(ThisT,wxGrid),
@@ -1751,88 +1985,99 @@ setRowLabelValue(#wx_ref{type=ThisT,ref=ThisRef},Row,Val)
wxe_util:cast(?wxGrid_SetRowLabelValue,
<<ThisRef:32/?UI,Row:32/?UI,(byte_size(Val_UC)):32/?UI,(Val_UC)/binary, 0:(((8- ((4+byte_size(Val_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGrid(), Row::integer(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowminimalheight">external documentation</a>.
+-spec setRowMinimalHeight(This, Row, Width) -> ok when
+ This::wxGrid(), Row::integer(), Width::integer().
setRowMinimalHeight(#wx_ref{type=ThisT,ref=ThisRef},Row,Width)
when is_integer(Row),is_integer(Width) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetRowMinimalHeight,
<<ThisRef:32/?UI,Row:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGrid(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowminimalacceptableheight">external documentation</a>.
+-spec setRowMinimalAcceptableHeight(This, Width) -> ok when
+ This::wxGrid(), Width::integer().
setRowMinimalAcceptableHeight(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetRowMinimalAcceptableHeight,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGrid(), Row::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetrowsize">external documentation</a>.
+-spec setRowSize(This, Row, Height) -> ok when
+ This::wxGrid(), Row::integer(), Height::integer().
setRowSize(#wx_ref{type=ThisT,ref=ThisRef},Row,Height)
when is_integer(Row),is_integer(Height) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetRowSize,
<<ThisRef:32/?UI,Row:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxGrid(), X::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetscrolllinex">external documentation</a>.
+-spec setScrollLineX(This, X) -> ok when
+ This::wxGrid(), X::integer().
setScrollLineX(#wx_ref{type=ThisT,ref=ThisRef},X)
when is_integer(X) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetScrollLineX,
<<ThisRef:32/?UI,X:32/?UI>>).
-%% @spec (This::wxGrid(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetscrollliney">external documentation</a>.
+-spec setScrollLineY(This, Y) -> ok when
+ This::wxGrid(), Y::integer().
setScrollLineY(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetScrollLineY,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxGrid(), C::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetselectionbackground">external documentation</a>.
+-spec setSelectionBackground(This, C) -> ok when
+ This::wxGrid(), C::wx:wx_colour().
setSelectionBackground(#wx_ref{type=ThisT,ref=ThisRef},C)
when tuple_size(C) =:= 3; tuple_size(C) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetSelectionBackground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(C)):16/binary>>).
-%% @spec (This::wxGrid(), C::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetselectionforeground">external documentation</a>.
+-spec setSelectionForeground(This, C) -> ok when
+ This::wxGrid(), C::wx:wx_colour().
setSelectionForeground(#wx_ref{type=ThisT,ref=ThisRef},C)
when tuple_size(C) =:= 3; tuple_size(C) =:= 4 ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetSelectionForeground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(C)):16/binary>>).
-%% @spec (This::wxGrid(), Selmode::WxGridSelectionModes) -> ok
-%% WxGridSelectionModes = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridsetselectionmode">external documentation</a>.
-%%<br /> WxGridSelectionModes is one of ?wxGrid_wxGridSelectCells | ?wxGrid_wxGridSelectRows | ?wxGrid_wxGridSelectColumns
+%%<br /> Selmode = ?wxGrid_wxGridSelectCells | ?wxGrid_wxGridSelectRows | ?wxGrid_wxGridSelectColumns
+-spec setSelectionMode(This, Selmode) -> ok when
+ This::wxGrid(), Selmode::wx:wx_enum().
setSelectionMode(#wx_ref{type=ThisT,ref=ThisRef},Selmode)
when is_integer(Selmode) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_SetSelectionMode,
<<ThisRef:32/?UI,Selmode:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridshowcelleditcontrol">external documentation</a>.
+-spec showCellEditControl(This) -> ok when
+ This::wxGrid().
showCellEditControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGrid),
wxe_util:cast(?wxGrid_ShowCellEditControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGrid(), X::integer()) -> integer()
%% @equiv xToCol(This,X, [])
+-spec xToCol(This, X) -> integer() when
+ This::wxGrid(), X::integer().
+
xToCol(This,X)
when is_record(This, wx_ref),is_integer(X) ->
xToCol(This,X, []).
-%% @spec (This::wxGrid(), X::integer(), [Option]) -> integer()
-%% Option = {clipToMinMax, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridxtocol">external documentation</a>.
+-spec xToCol(This, X, [Option]) -> integer() when
+ This::wxGrid(), X::integer(),
+ Option :: {clipToMinMax, boolean()}.
xToCol(#wx_ref{type=ThisT,ref=ThisRef},X, Options)
when is_integer(X),is_list(Options) ->
?CLASS(ThisT,wxGrid),
@@ -1842,32 +2087,35 @@ xToCol(#wx_ref{type=ThisT,ref=ThisRef},X, Options)
wxe_util:call(?wxGrid_XToCol,
<<ThisRef:32/?UI,X:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGrid(), X::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridxtoedgeofcol">external documentation</a>.
+-spec xToEdgeOfCol(This, X) -> integer() when
+ This::wxGrid(), X::integer().
xToEdgeOfCol(#wx_ref{type=ThisT,ref=ThisRef},X)
when is_integer(X) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_XToEdgeOfCol,
<<ThisRef:32/?UI,X:32/?UI>>).
-%% @spec (This::wxGrid(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridytoedgeofrow">external documentation</a>.
+-spec yToEdgeOfRow(This, Y) -> integer() when
+ This::wxGrid(), Y::integer().
yToEdgeOfRow(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_YToEdgeOfRow,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxGrid(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgrid.html#wxgridytorow">external documentation</a>.
+-spec yToRow(This, Y) -> integer() when
+ This::wxGrid(), Y::integer().
yToRow(#wx_ref{type=ThisT,ref=ThisRef},Y)
when is_integer(Y) ->
?CLASS(ThisT,wxGrid),
wxe_util:call(?wxGrid_YToRow,
<<ThisRef:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxGrid()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGrid()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGrid),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxGridBagSizer.erl b/lib/wx/src/gen/wxGridBagSizer.erl
index cfc182cf89..e8a9ff6d76 100644
--- a/lib/wx/src/gen/wxGridBagSizer.erl
+++ b/lib/wx/src/gen/wxGridBagSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 +48,24 @@
setItemMinSize/4,setMinSize/2,setMinSize/3,setNonFlexibleGrowMode/2,
setRows/2,setSizeHints/2,setVGap/2,setVirtualSizeHints/2,show/2,show/3]).
+-export_type([wxGridBagSizer/0]).
%% @hidden
parent_class(wxFlexGridSizer) -> true;
parent_class(wxGridSizer) -> true;
parent_class(wxSizer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridBagSizer()
+-type wxGridBagSizer() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxGridBagSizer().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxGridBagSizer()
-%% Option = {vgap, integer()} | {hgap, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerwxgridbagsizer">external documentation</a>.
+-spec new([Option]) -> wxGridBagSizer() when
+ Option :: {vgap, integer()}
+ | {hgap, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({vgap, Vgap}, Acc) -> [<<1:32/?UI,Vgap:32/?UI>>|Acc];
@@ -71,8 +75,9 @@ new(Options)
wxe_util:construct(?wxGridBagSizer_new,
<<BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(), Item::wxSizerItem:wxSizerItem() | wxGBSizerItem:wxGBSizerItem()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizeradd">external documentation</a>.
+-spec add(This, Item) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Item::wxSizerItem:wxSizerItem() | wxGBSizerItem:wxGBSizerItem().
add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
?CLASS(ThisT,wxGridBagSizer),
ItemOP = case ?CLASS_T(ItemT,wxSizerItem) of
@@ -84,17 +89,27 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
wxe_util:call(ItemOP,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term(),X::integer()|term()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizeradd">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% add(This::wxGridBagSizer(), Width::integer(), Height::integer()) -> add(This,Width,Height, []) </c></p>
-%% <p><c>
-%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(),C::integer()}) -> add(This,Window,Pos, []) </c></p>
-%% <p><c>
-%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
-%% </p>
+%% <br /> Also:<br />
+%% add(This, Window, Pos) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()};<br />
+%% (This, Window, [Option]) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(),<br />
+%% Option :: {proportion, integer()}<br />
+%% | {flag, integer()}<br />
+%% | {border, integer()}<br />
+%% | {userData, wx:wx_object()}.<br />
+%%
+-spec add(This, Width, Height) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Width::integer(), Height::integer();
+ (This, Window, Pos) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()};
+ (This, Window, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()}.
add(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
@@ -121,19 +136,35 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Options
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term(),X::integer()|term(),X::term()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizeradd">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% add(This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(),C::integer()}) -> add(This,Width,Height,Pos, []) </c></p>
-%% <p><c>
-%% add(This::wxGridBagSizer(), Width::integer(), Height::integer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
-%% </p>
-%% <p><c>
-%% add(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(),C::integer()}, [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {span, {RS::integer(),CS::integer()}} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
-%% </p>
+%% <br /> Also:<br />
+%% add(This, Width, Height, [Option]) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxGridBagSizer(), Width::integer(), Height::integer(),<br />
+%% Option :: {proportion, integer()}<br />
+%% | {flag, integer()}<br />
+%% | {border, integer()}<br />
+%% | {userData, wx:wx_object()};<br />
+%% (This, Window, Pos, [Option]) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()},<br />
+%% Option :: {span, {RS::integer(), CS::integer()}}<br />
+%% | {flag, integer()}<br />
+%% | {border, integer()}<br />
+%% | {userData, wx:wx_object()}.<br />
+%%
+-spec add(This, Width, Height, Pos) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(), C::integer()};
+ (This, Width, Height, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Width::integer(), Height::integer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()};
+ (This, Window, Pos, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()},
+ Option :: {span, {RS::integer(), CS::integer()}}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()}.
add(This,Width,Height,Pos={PosR,PosC})
when is_record(This, wx_ref),is_integer(Width),is_integer(Height),is_integer(PosR),is_integer(PosC) ->
@@ -167,9 +198,13 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},{PosR,Po
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,PosR:32/?UI,PosC:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(),C::integer()}, [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {span, {RS::integer(),CS::integer()}} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizeradd">external documentation</a>.
+-spec add(This, Width, Height, Pos, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxGridBagSizer(), Width::integer(), Height::integer(), Pos::{R::integer(), C::integer()},
+ Option :: {span, {RS::integer(), CS::integer()}}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()}.
add(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,{PosR,PosC}, Options)
when is_integer(Width),is_integer(Height),is_integer(PosR),is_integer(PosC),is_list(Options) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -182,28 +217,33 @@ add(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,{PosR,PosC}, Options)
wxe_util:call(?wxGridBagSizer_Add_4,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI,PosR:32/?UI,PosC:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizercalcmin">external documentation</a>.
+-spec calcMin(This) -> {W::integer(), H::integer()} when
+ This::wxGridBagSizer().
calcMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:call(?wxGridBagSizer_CalcMin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Item::wxGBSizerItem:wxGBSizerItem()) -> bool()
%% @equiv checkForIntersection(This,Item, [])
+-spec checkForIntersection(This, Item) -> boolean() when
+ This::wxGridBagSizer(), Item::wxGBSizerItem:wxGBSizerItem().
+
checkForIntersection(This,Item)
when is_record(This, wx_ref),is_record(Item, wx_ref) ->
checkForIntersection(This,Item, []).
-%% @spec (This::wxGridBagSizer(),X::term(),X::term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizercheckforintersection">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% checkForIntersection(This::wxGridBagSizer(), Pos::{R::integer(),C::integer()}, Span::{RS::integer(),CS::integer()}) -> checkForIntersection(This,Pos,Span, []) </c></p>
-%% <p><c>
-%% checkForIntersection(This::wxGridBagSizer(), Item::wxGBSizerItem:wxGBSizerItem(), [Option]) -> bool() </c>
-%%<br /> Option = {excludeItem, wxGBSizerItem:wxGBSizerItem()}
-%% </p>
+%% <br /> Also:<br />
+%% checkForIntersection(This, Item, [Option]) -> boolean() when<br />
+%% This::wxGridBagSizer(), Item::wxGBSizerItem:wxGBSizerItem(),<br />
+%% Option :: {excludeItem, wxGBSizerItem:wxGBSizerItem()}.<br />
+%%
+-spec checkForIntersection(This, Pos, Span) -> boolean() when
+ This::wxGridBagSizer(), Pos::{R::integer(), C::integer()}, Span::{RS::integer(), CS::integer()};
+ (This, Item, [Option]) -> boolean() when
+ This::wxGridBagSizer(), Item::wxGBSizerItem:wxGBSizerItem(),
+ Option :: {excludeItem, wxGBSizerItem:wxGBSizerItem()}.
checkForIntersection(This,Pos={PosR,PosC},Span={SpanRS,SpanCS})
when is_record(This, wx_ref),is_integer(PosR),is_integer(PosC),is_integer(SpanRS),is_integer(SpanCS) ->
@@ -218,9 +258,10 @@ checkForIntersection(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=Item
wxe_util:call(?wxGridBagSizer_CheckForIntersection_2,
<<ThisRef:32/?UI,ItemRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(), Pos::{R::integer(),C::integer()}, Span::{RS::integer(),CS::integer()}, [Option]) -> bool()
-%% Option = {excludeItem, wxGBSizerItem:wxGBSizerItem()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizercheckforintersection">external documentation</a>.
+-spec checkForIntersection(This, Pos, Span, [Option]) -> boolean() when
+ This::wxGridBagSizer(), Pos::{R::integer(), C::integer()}, Span::{RS::integer(), CS::integer()},
+ Option :: {excludeItem, wxGBSizerItem:wxGBSizerItem()}.
checkForIntersection(#wx_ref{type=ThisT,ref=ThisRef},{PosR,PosC},{SpanRS,SpanCS}, Options)
when is_integer(PosR),is_integer(PosC),is_integer(SpanRS),is_integer(SpanCS),is_list(Options) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -230,8 +271,9 @@ checkForIntersection(#wx_ref{type=ThisT,ref=ThisRef},{PosR,PosC},{SpanRS,SpanCS}
wxe_util:call(?wxGridBagSizer_CheckForIntersection_3,
<<ThisRef:32/?UI,PosR:32/?UI,PosC:32/?UI,SpanRS:32/?UI,SpanCS:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> wxGBSizerItem:wxGBSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerfinditem">external documentation</a>.
+-spec findItem(This, Window) -> wxGBSizerItem:wxGBSizerItem() when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer().
findItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxGridBagSizer),
WindowOP = case ?CLASS_T(WindowT,wxWindow) of
@@ -243,54 +285,59 @@ findItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Pt::{X::integer(),Y::integer()}) -> wxGBSizerItem:wxGBSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerfinditematpoint">external documentation</a>.
+-spec findItemAtPoint(This, Pt) -> wxGBSizerItem:wxGBSizerItem() when
+ This::wxGridBagSizer(), Pt::{X::integer(), Y::integer()}.
findItemAtPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:call(?wxGridBagSizer_FindItemAtPoint,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Pos::{R::integer(),C::integer()}) -> wxGBSizerItem:wxGBSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerfinditematposition">external documentation</a>.
+-spec findItemAtPosition(This, Pos) -> wxGBSizerItem:wxGBSizerItem() when
+ This::wxGridBagSizer(), Pos::{R::integer(), C::integer()}.
findItemAtPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosR,PosC})
when is_integer(PosR),is_integer(PosC) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:call(?wxGridBagSizer_FindItemAtPosition,
<<ThisRef:32/?UI,PosR:32/?UI,PosC:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), UserData::wx:wx()) -> wxGBSizerItem:wxGBSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizerfinditemwithdata">external documentation</a>.
+-spec findItemWithData(This, UserData) -> wxGBSizerItem:wxGBSizerItem() when
+ This::wxGridBagSizer(), UserData::wx:wx_object().
findItemWithData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=UserDataT,ref=UserDataRef}) ->
?CLASS(ThisT,wxGridBagSizer),
?CLASS(UserDataT,wx),
wxe_util:call(?wxGridBagSizer_FindItemWithData,
<<ThisRef:32/?UI,UserDataRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Row::integer(), Col::integer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetcellsize">external documentation</a>.
+-spec getCellSize(This, Row, Col) -> {W::integer(), H::integer()} when
+ This::wxGridBagSizer(), Row::integer(), Col::integer().
getCellSize(#wx_ref{type=ThisT,ref=ThisRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:call(?wxGridBagSizer_GetCellSize,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGridBagSizer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetemptycellsize">external documentation</a>.
+-spec getEmptyCellSize(This) -> {W::integer(), H::integer()} when
+ This::wxGridBagSizer().
getEmptyCellSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:call(?wxGridBagSizer_GetEmptyCellSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term()) -> {R::integer(),C::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetitemposition">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% getItemPosition(This::wxGridBagSizer(), Index::integer()) -> {R::integer(),C::integer()} </c>
-%% </p>
-%% <p><c>
-%% getItemPosition(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> {R::integer(),C::integer()} </c>
-%% </p>
+%% <br /> Also:<br />
+%% getItemPosition(This, Window) -> {R::integer(), C::integer()} when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer().<br />
+%%
+-spec getItemPosition(This, Index) -> {R::integer(), C::integer()} when
+ This::wxGridBagSizer(), Index::integer();
+ (This, Window) -> {R::integer(), C::integer()} when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer().
getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -307,15 +354,15 @@ getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowR
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term()) -> {RS::integer(),CS::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizergetitemspan">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% getItemSpan(This::wxGridBagSizer(), Index::integer()) -> {RS::integer(),CS::integer()} </c>
-%% </p>
-%% <p><c>
-%% getItemSpan(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer()) -> {RS::integer(),CS::integer()} </c>
-%% </p>
+%% <br /> Also:<br />
+%% getItemSpan(This, Window) -> {RS::integer(), CS::integer()} when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer().<br />
+%%
+-spec getItemSpan(This, Index) -> {RS::integer(), CS::integer()} when
+ This::wxGridBagSizer(), Index::integer();
+ (This, Window) -> {RS::integer(), CS::integer()} when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer().
getItemSpan(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -332,23 +379,24 @@ getItemSpan(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef})
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxGridBagSizer(), Sz::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizersetemptycellsize">external documentation</a>.
+-spec setEmptyCellSize(This, Sz) -> ok when
+ This::wxGridBagSizer(), Sz::{W::integer(), H::integer()}.
setEmptyCellSize(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
when is_integer(SzW),is_integer(SzH) ->
?CLASS(ThisT,wxGridBagSizer),
wxe_util:cast(?wxGridBagSizer_SetEmptyCellSize,
<<ThisRef:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term(),Pos::{R::integer(),C::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizersetitemposition">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setItemPosition(This::wxGridBagSizer(), Index::integer(), Pos::{R::integer(),C::integer()}) -> bool() </c>
-%% </p>
-%% <p><c>
-%% setItemPosition(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(),C::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% setItemPosition(This, Window, Pos) -> boolean() when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()}.<br />
+%%
+-spec setItemPosition(This, Index, Pos) -> boolean() when
+ This::wxGridBagSizer(), Index::integer(), Pos::{R::integer(), C::integer()};
+ (This, Window, Pos) -> boolean() when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Pos::{R::integer(), C::integer()}.
setItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Index,{PosR,PosC})
when is_integer(Index),is_integer(PosR),is_integer(PosC) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -366,15 +414,15 @@ setItemPosition(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowR
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,PosR:32/?UI,PosC:32/?UI>>).
-%% @spec (This::wxGridBagSizer(),X::integer()|term(),Span::{RS::integer(),CS::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridbagsizer.html#wxgridbagsizersetitemspan">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setItemSpan(This::wxGridBagSizer(), Index::integer(), Span::{RS::integer(),CS::integer()}) -> bool() </c>
-%% </p>
-%% <p><c>
-%% setItemSpan(This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Span::{RS::integer(),CS::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% setItemSpan(This, Window, Span) -> boolean() when<br />
+%% This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Span::{RS::integer(), CS::integer()}.<br />
+%%
+-spec setItemSpan(This, Index, Span) -> boolean() when
+ This::wxGridBagSizer(), Index::integer(), Span::{RS::integer(), CS::integer()};
+ (This, Window, Span) -> boolean() when
+ This::wxGridBagSizer(), Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Span::{RS::integer(), CS::integer()}.
setItemSpan(#wx_ref{type=ThisT,ref=ThisRef},Index,{SpanRS,SpanCS})
when is_integer(Index),is_integer(SpanRS),is_integer(SpanCS) ->
?CLASS(ThisT,wxGridBagSizer),
@@ -392,8 +440,8 @@ setItemSpan(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,SpanRS:32/?UI,SpanCS:32/?UI>>).
-%% @spec (This::wxGridBagSizer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridBagSizer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridBagSizer),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxGridCellAttr.erl b/lib/wx/src/gen/wxGridCellAttr.erl
index 3d23c2acfc..f03fd99d2a 100644
--- a/lib/wx/src/gen/wxGridCellAttr.erl
+++ b/lib/wx/src/gen/wxGridCellAttr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,50 +33,59 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxGridCellAttr/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGridCellAttr(), ColText::wx:colour()) -> ok
+-type wxGridCellAttr() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsettextcolour">external documentation</a>.
+-spec setTextColour(This, ColText) -> ok when
+ This::wxGridCellAttr(), ColText::wx:wx_colour().
setTextColour(#wx_ref{type=ThisT,ref=ThisRef},ColText)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:cast(?wxGridCellAttr_SetTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColText)):16/binary>>).
-%% @spec (This::wxGridCellAttr(), ColBack::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsetbackgroundcolour">external documentation</a>.
+-spec setBackgroundColour(This, ColBack) -> ok when
+ This::wxGridCellAttr(), ColBack::wx:wx_colour().
setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},ColBack)
when tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:cast(?wxGridCellAttr_SetBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary>>).
-%% @spec (This::wxGridCellAttr(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsetfont">external documentation</a>.
+-spec setFont(This, Font) -> ok when
+ This::wxGridCellAttr(), Font::wxFont:wxFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxGridCellAttr),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxGridCellAttr_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr(), HAlign::integer(), VAlign::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsetalignment">external documentation</a>.
+-spec setAlignment(This, HAlign, VAlign) -> ok when
+ This::wxGridCellAttr(), HAlign::integer(), VAlign::integer().
setAlignment(#wx_ref{type=ThisT,ref=ThisRef},HAlign,VAlign)
when is_integer(HAlign),is_integer(VAlign) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:cast(?wxGridCellAttr_SetAlignment,
<<ThisRef:32/?UI,HAlign:32/?UI,VAlign:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> ok
%% @equiv setReadOnly(This, [])
+-spec setReadOnly(This) -> ok when
+ This::wxGridCellAttr().
+
setReadOnly(This)
when is_record(This, wx_ref) ->
setReadOnly(This, []).
-%% @spec (This::wxGridCellAttr(), [Option]) -> ok
-%% Option = {isReadOnly, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsetreadonly">external documentation</a>.
+-spec setReadOnly(This, [Option]) -> ok when
+ This::wxGridCellAttr(),
+ Option :: {isReadOnly, boolean()}.
setReadOnly(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxGridCellAttr),
@@ -86,94 +95,107 @@ setReadOnly(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxGridCellAttr_SetReadOnly,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxGridCellAttr(), Renderer::wxGridCellRenderer:wxGridCellRenderer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsetrenderer">external documentation</a>.
+-spec setRenderer(This, Renderer) -> ok when
+ This::wxGridCellAttr(), Renderer::wxGridCellRenderer:wxGridCellRenderer().
setRenderer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RendererT,ref=RendererRef}) ->
?CLASS(ThisT,wxGridCellAttr),
?CLASS(RendererT,wxGridCellRenderer),
wxe_util:cast(?wxGridCellAttr_SetRenderer,
<<ThisRef:32/?UI,RendererRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr(), Editor::wxGridCellEditor:wxGridCellEditor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrseteditor">external documentation</a>.
+-spec setEditor(This, Editor) -> ok when
+ This::wxGridCellAttr(), Editor::wxGridCellEditor:wxGridCellEditor().
setEditor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=EditorT,ref=EditorRef}) ->
?CLASS(ThisT,wxGridCellAttr),
?CLASS(EditorT,wxGridCellEditor),
wxe_util:cast(?wxGridCellAttr_SetEditor,
<<ThisRef:32/?UI,EditorRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrhastextcolour">external documentation</a>.
+-spec hasTextColour(This) -> boolean() when
+ This::wxGridCellAttr().
hasTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_HasTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrhasbackgroundcolour">external documentation</a>.
+-spec hasBackgroundColour(This) -> boolean() when
+ This::wxGridCellAttr().
hasBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_HasBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrhasfont">external documentation</a>.
+-spec hasFont(This) -> boolean() when
+ This::wxGridCellAttr().
hasFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_HasFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrhasalignment">external documentation</a>.
+-spec hasAlignment(This) -> boolean() when
+ This::wxGridCellAttr().
hasAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_HasAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrhasrenderer">external documentation</a>.
+-spec hasRenderer(This) -> boolean() when
+ This::wxGridCellAttr().
hasRenderer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_HasRenderer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrhaseditor">external documentation</a>.
+-spec hasEditor(This) -> boolean() when
+ This::wxGridCellAttr().
hasEditor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_HasEditor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgettextcolour">external documentation</a>.
+-spec getTextColour(This) -> wx:wx_colour4() when
+ This::wxGridCellAttr().
getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_GetTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgetbackgroundcolour">external documentation</a>.
+-spec getBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxGridCellAttr().
getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_GetBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxGridCellAttr().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> {HAlign::integer(),VAlign::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgetalignment">external documentation</a>.
+-spec getAlignment(This) -> {HAlign::integer(), VAlign::integer()} when
+ This::wxGridCellAttr().
getAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_GetAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr(), Grid::wxGrid:wxGrid(), Row::integer(), Col::integer()) -> wxGridCellRenderer:wxGridCellRenderer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgetrenderer">external documentation</a>.
+-spec getRenderer(This, Grid, Row, Col) -> wxGridCellRenderer:wxGridCellRenderer() when
+ This::wxGridCellAttr(), Grid::wxGrid:wxGrid(), Row::integer(), Col::integer().
getRenderer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGridCellAttr),
@@ -181,8 +203,9 @@ getRenderer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},Row,
wxe_util:call(?wxGridCellAttr_GetRenderer,
<<ThisRef:32/?UI,GridRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGridCellAttr(), Grid::wxGrid:wxGrid(), Row::integer(), Col::integer()) -> wxGridCellEditor:wxGridCellEditor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrgeteditor">external documentation</a>.
+-spec getEditor(This, Grid, Row, Col) -> wxGridCellEditor:wxGridCellEditor() when
+ This::wxGridCellAttr(), Grid::wxGrid:wxGrid(), Row::integer(), Col::integer().
getEditor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGridCellAttr),
@@ -190,15 +213,17 @@ getEditor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},Row,Co
wxe_util:call(?wxGridCellAttr_GetEditor,
<<ThisRef:32/?UI,GridRef:32/?UI,Row:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxGridCellAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrisreadonly">external documentation</a>.
+-spec isReadOnly(This) -> boolean() when
+ This::wxGridCellAttr().
isReadOnly(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellAttr),
wxe_util:call(?wxGridCellAttr_IsReadOnly,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellAttr(), DefAttr::wxGridCellAttr()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellattr.html#wxgridcellattrsetdefattr">external documentation</a>.
+-spec setDefAttr(This, DefAttr) -> ok when
+ This::wxGridCellAttr(), DefAttr::wxGridCellAttr().
setDefAttr(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DefAttrT,ref=DefAttrRef}) ->
?CLASS(ThisT,wxGridCellAttr),
?CLASS(DefAttrT,wxGridCellAttr),
diff --git a/lib/wx/src/gen/wxGridCellBoolEditor.erl b/lib/wx/src/gen/wxGridCellBoolEditor.erl
index a54cfe5eab..533554cd54 100644
--- a/lib/wx/src/gen/wxGridCellBoolEditor.erl
+++ b/lib/wx/src/gen/wxGridCellBoolEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,32 +33,37 @@
-export([beginEdit/4,endEdit/4,handleReturn/2,isCreated/1,paintBackground/3,
parent_class/1,reset/1,setSize/2,show/2,show/3,startingClick/1,startingKey/2]).
+-export_type([wxGridCellBoolEditor/0]).
%% @hidden
parent_class(wxGridCellEditor) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellBoolEditor()
+-type wxGridCellBoolEditor() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellbooleditor.html#wxgridcellbooleditorwxgridcellbooleditor">external documentation</a>.
+-spec new() -> wxGridCellBoolEditor().
new() ->
wxe_util:construct(?wxGridCellBoolEditor_new,
<<>>).
-%% @spec (Value::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellbooleditor.html#wxgridcellbooleditoristruevalue">external documentation</a>.
+-spec isTrueValue(Value) -> boolean() when
+ Value::unicode:chardata().
isTrueValue(Value)
when is_list(Value) ->
Value_UC = unicode:characters_to_binary([Value,0]),
wxe_util:call(?wxGridCellBoolEditor_IsTrueValue,
<<(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((4+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec () -> ok
%% @equiv useStringValues([])
+-spec useStringValues() -> ok.
+
useStringValues() ->
useStringValues([]).
-%% @spec ([Option]) -> ok
-%% Option = {valueTrue, string()} | {valueFalse, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellbooleditor.html#wxgridcellbooleditorusestringvalues">external documentation</a>.
+-spec useStringValues([Option]) -> ok when
+ Option :: {valueTrue, unicode:chardata()}
+ | {valueFalse, unicode:chardata()}.
useStringValues(Options)
when is_list(Options) ->
MOpts = fun({valueTrue, ValueTrue}, Acc) -> ValueTrue_UC = unicode:characters_to_binary([ValueTrue,0]),[<<1:32/?UI,(byte_size(ValueTrue_UC)):32/?UI,(ValueTrue_UC)/binary, 0:(((8- ((0+byte_size(ValueTrue_UC)) band 16#7)) band 16#7))/unit:8>>|Acc];
@@ -68,8 +73,8 @@ useStringValues(Options)
wxe_util:cast(?wxGridCellBoolEditor_UseStringValues,
<<BinOpt/binary>>).
-%% @spec (This::wxGridCellBoolEditor()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellBoolEditor()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellBoolEditor),
wxe_util:destroy(?wxGridCellBoolEditor_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellBoolRenderer.erl b/lib/wx/src/gen/wxGridCellBoolRenderer.erl
index a98091f62c..834f00a623 100644
--- a/lib/wx/src/gen/wxGridCellBoolRenderer.erl
+++ b/lib/wx/src/gen/wxGridCellBoolRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,18 +32,20 @@
%% inherited exports
-export([draw/8,getBestSize/6,parent_class/1]).
+-export_type([wxGridCellBoolRenderer/0]).
%% @hidden
parent_class(wxGridCellRenderer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellBoolRenderer()
+-type wxGridCellBoolRenderer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellboolrenderer.html#wxgridcellboolrendererwxgridcellboolrenderer">external documentation</a>.
+-spec new() -> wxGridCellBoolRenderer().
new() ->
wxe_util:construct(?wxGridCellBoolRenderer_new,
<<>>).
-%% @spec (This::wxGridCellBoolRenderer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellBoolRenderer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellBoolRenderer),
wxe_util:destroy(?wxGridCellBoolRenderer_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellChoiceEditor.erl b/lib/wx/src/gen/wxGridCellChoiceEditor.erl
index 1adee550f8..6b037e01b3 100644
--- a/lib/wx/src/gen/wxGridCellChoiceEditor.erl
+++ b/lib/wx/src/gen/wxGridCellChoiceEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,19 +33,24 @@
-export([beginEdit/4,endEdit/4,handleReturn/2,isCreated/1,paintBackground/3,
parent_class/1,reset/1,setSize/2,show/2,show/3,startingClick/1,startingKey/2]).
+-export_type([wxGridCellChoiceEditor/0]).
%% @hidden
parent_class(wxGridCellEditor) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Choices::[[string()]]) -> wxGridCellChoiceEditor()
+-type wxGridCellChoiceEditor() :: wx:wx_object().
%% @equiv new(Choices, [])
+-spec new(Choices) -> wxGridCellChoiceEditor() when
+ Choices::[unicode:chardata()].
+
new(Choices)
when is_list(Choices) ->
new(Choices, []).
-%% @spec (Choices::[[string()]], [Option]) -> wxGridCellChoiceEditor()
-%% Option = {allowOthers, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellchoiceeditor.html#wxgridcellchoiceeditorwxgridcellchoiceeditor">external documentation</a>.
+-spec new(Choices, [Option]) -> wxGridCellChoiceEditor() when
+ Choices::[unicode:chardata()],
+ Option :: {allowOthers, boolean()}.
new(Choices, Options)
when is_list(Choices),is_list(Options) ->
Choices_UCA = [unicode:characters_to_binary([ChoicesTemp,0]) ||
@@ -56,8 +61,9 @@ new(Choices, Options)
wxe_util:construct(?wxGridCellChoiceEditor_new,
<<(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxGridCellChoiceEditor(), Params::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellchoiceeditor.html#wxgridcellchoiceeditorsetparameters">external documentation</a>.
+-spec setParameters(This, Params) -> ok when
+ This::wxGridCellChoiceEditor(), Params::unicode:chardata().
setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
when is_list(Params) ->
?CLASS(ThisT,wxGridCellChoiceEditor),
@@ -65,8 +71,8 @@ setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
wxe_util:cast(?wxGridCellChoiceEditor_SetParameters,
<<ThisRef:32/?UI,(byte_size(Params_UC)):32/?UI,(Params_UC)/binary, 0:(((8- ((0+byte_size(Params_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGridCellChoiceEditor()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellChoiceEditor()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellChoiceEditor),
wxe_util:destroy(?wxGridCellChoiceEditor_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellEditor.erl b/lib/wx/src/gen/wxGridCellEditor.erl
index a27ba7bd0f..e84cdeb49a 100644
--- a/lib/wx/src/gen/wxGridCellEditor.erl
+++ b/lib/wx/src/gen/wxGridCellEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,11 +30,14 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxGridCellEditor/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGridCellEditor(), Parent::wxWindow:wxWindow(), Id::integer(), EvtHandler::wxEvtHandler:wxEvtHandler()) -> ok
+-type wxGridCellEditor() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorcreate">external documentation</a>.
+-spec create(This, Parent, Id, EvtHandler) -> ok when
+ This::wxGridCellEditor(), Parent::wxWindow:wxWindow(), Id::integer(), EvtHandler::wxEvtHandler:wxEvtHandler().
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=EvtHandlerT,ref=EvtHandlerRef})
when is_integer(Id) ->
?CLASS(ThisT,wxGridCellEditor),
@@ -43,30 +46,35 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#w
wxe_util:cast(?wxGridCellEditor_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,EvtHandlerRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditoriscreated">external documentation</a>.
+-spec isCreated(This) -> boolean() when
+ This::wxGridCellEditor().
isCreated(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellEditor),
wxe_util:call(?wxGridCellEditor_IsCreated,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorsetsize">external documentation</a>.
+-spec setSize(This, Rect) -> ok when
+ This::wxGridCellEditor(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
setSize(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxGridCellEditor),
wxe_util:cast(?wxGridCellEditor_SetSize,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Show::bool()) -> ok
%% @equiv show(This,Show, [])
+-spec show(This, Show) -> ok when
+ This::wxGridCellEditor(), Show::boolean().
+
show(This,Show)
when is_record(This, wx_ref),is_boolean(Show) ->
show(This,Show, []).
-%% @spec (This::wxGridCellEditor(), Show::bool(), [Option]) -> ok
-%% Option = {attr, wxGridCellAttr:wxGridCellAttr()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorshow">external documentation</a>.
+-spec show(This, Show, [Option]) -> ok when
+ This::wxGridCellEditor(), Show::boolean(),
+ Option :: {attr, wxGridCellAttr:wxGridCellAttr()}.
show(#wx_ref{type=ThisT,ref=ThisRef},Show, Options)
when is_boolean(Show),is_list(Options) ->
?CLASS(ThisT,wxGridCellEditor),
@@ -76,8 +84,9 @@ show(#wx_ref{type=ThisT,ref=ThisRef},Show, Options)
wxe_util:cast(?wxGridCellEditor_Show,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI, BinOpt/binary>>).
-%% @spec (This::wxGridCellEditor(), RectCell::{X::integer(),Y::integer(),W::integer(),H::integer()}, Attr::wxGridCellAttr:wxGridCellAttr()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorpaintbackground">external documentation</a>.
+-spec paintBackground(This, RectCell, Attr) -> ok when
+ This::wxGridCellEditor(), RectCell::{X::integer(), Y::integer(), W::integer(), H::integer()}, Attr::wxGridCellAttr:wxGridCellAttr().
paintBackground(#wx_ref{type=ThisT,ref=ThisRef},{RectCellX,RectCellY,RectCellW,RectCellH},#wx_ref{type=AttrT,ref=AttrRef})
when is_integer(RectCellX),is_integer(RectCellY),is_integer(RectCellW),is_integer(RectCellH) ->
?CLASS(ThisT,wxGridCellEditor),
@@ -85,8 +94,9 @@ paintBackground(#wx_ref{type=ThisT,ref=ThisRef},{RectCellX,RectCellY,RectCellW,R
wxe_util:cast(?wxGridCellEditor_PaintBackground,
<<ThisRef:32/?UI,RectCellX:32/?UI,RectCellY:32/?UI,RectCellW:32/?UI,RectCellH:32/?UI,AttrRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Row::integer(), Col::integer(), Grid::wxGrid:wxGrid()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorbeginedit">external documentation</a>.
+-spec beginEdit(This, Row, Col, Grid) -> ok when
+ This::wxGridCellEditor(), Row::integer(), Col::integer(), Grid::wxGrid:wxGrid().
beginEdit(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=GridT,ref=GridRef})
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGridCellEditor),
@@ -94,8 +104,9 @@ beginEdit(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=GridT,ref=GridRef
wxe_util:cast(?wxGridCellEditor_BeginEdit,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI,GridRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Row::integer(), Col::integer(), Grid::wxGrid:wxGrid()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorendedit">external documentation</a>.
+-spec endEdit(This, Row, Col, Grid) -> boolean() when
+ This::wxGridCellEditor(), Row::integer(), Col::integer(), Grid::wxGrid:wxGrid().
endEdit(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=GridT,ref=GridRef})
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGridCellEditor),
@@ -103,30 +114,34 @@ endEdit(#wx_ref{type=ThisT,ref=ThisRef},Row,Col,#wx_ref{type=GridT,ref=GridRef})
wxe_util:call(?wxGridCellEditor_EndEdit,
<<ThisRef:32/?UI,Row:32/?UI,Col:32/?UI,GridRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorreset">external documentation</a>.
+-spec reset(This) -> ok when
+ This::wxGridCellEditor().
reset(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellEditor),
wxe_util:cast(?wxGridCellEditor_Reset,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Event::wxKeyEvent:wxKeyEvent()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorstartingkey">external documentation</a>.
+-spec startingKey(This, Event) -> ok when
+ This::wxGridCellEditor(), Event::wxKeyEvent:wxKeyEvent().
startingKey(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=EventT,ref=EventRef}) ->
?CLASS(ThisT,wxGridCellEditor),
?CLASS(EventT,wxKeyEvent),
wxe_util:cast(?wxGridCellEditor_StartingKey,
<<ThisRef:32/?UI,EventRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorstartingclick">external documentation</a>.
+-spec startingClick(This) -> ok when
+ This::wxGridCellEditor().
startingClick(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellEditor),
wxe_util:cast(?wxGridCellEditor_StartingClick,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellEditor(), Event::wxKeyEvent:wxKeyEvent()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelleditor.html#wxgridcelleditorhandlereturn">external documentation</a>.
+-spec handleReturn(This, Event) -> ok when
+ This::wxGridCellEditor(), Event::wxKeyEvent:wxKeyEvent().
handleReturn(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=EventT,ref=EventRef}) ->
?CLASS(ThisT,wxGridCellEditor),
?CLASS(EventT,wxKeyEvent),
diff --git a/lib/wx/src/gen/wxGridCellFloatEditor.erl b/lib/wx/src/gen/wxGridCellFloatEditor.erl
index 3caad74f0e..f6b7dce15e 100644
--- a/lib/wx/src/gen/wxGridCellFloatEditor.erl
+++ b/lib/wx/src/gen/wxGridCellFloatEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,18 +33,22 @@
-export([beginEdit/4,endEdit/4,handleReturn/2,isCreated/1,paintBackground/3,
parent_class/1,reset/1,setSize/2,show/2,show/3,startingClick/1,startingKey/2]).
+-export_type([wxGridCellFloatEditor/0]).
%% @hidden
parent_class(wxGridCellEditor) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellFloatEditor()
+-type wxGridCellFloatEditor() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxGridCellFloatEditor().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxGridCellFloatEditor()
-%% Option = {width, integer()} | {precision, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloateditor.html#wxgridcellfloateditorwxgridcellfloateditor">external documentation</a>.
+-spec new([Option]) -> wxGridCellFloatEditor() when
+ Option :: {width, integer()}
+ | {precision, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({width, Width}, Acc) -> [<<1:32/?UI,Width:32/?UI>>|Acc];
@@ -54,8 +58,9 @@ new(Options)
wxe_util:construct(?wxGridCellFloatEditor_new,
<<BinOpt/binary>>).
-%% @spec (This::wxGridCellFloatEditor(), Params::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloateditor.html#wxgridcellfloateditorsetparameters">external documentation</a>.
+-spec setParameters(This, Params) -> ok when
+ This::wxGridCellFloatEditor(), Params::unicode:chardata().
setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
when is_list(Params) ->
?CLASS(ThisT,wxGridCellFloatEditor),
@@ -63,8 +68,8 @@ setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
wxe_util:cast(?wxGridCellFloatEditor_SetParameters,
<<ThisRef:32/?UI,(byte_size(Params_UC)):32/?UI,(Params_UC)/binary, 0:(((8- ((0+byte_size(Params_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGridCellFloatEditor()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellFloatEditor()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellFloatEditor),
wxe_util:destroy(?wxGridCellFloatEditor_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellFloatRenderer.erl b/lib/wx/src/gen/wxGridCellFloatRenderer.erl
index 84ffd21b37..c090a60e74 100644
--- a/lib/wx/src/gen/wxGridCellFloatRenderer.erl
+++ b/lib/wx/src/gen/wxGridCellFloatRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,19 +34,23 @@
%% inherited exports
-export([draw/8,getBestSize/6,parent_class/1]).
+-export_type([wxGridCellFloatRenderer/0]).
%% @hidden
parent_class(wxGridCellStringRenderer) -> true;
parent_class(wxGridCellRenderer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellFloatRenderer()
+-type wxGridCellFloatRenderer() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxGridCellFloatRenderer().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxGridCellFloatRenderer()
-%% Option = {width, integer()} | {precision, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloatrenderer.html#wxgridcellfloatrendererwxgridcellfloatrenderer">external documentation</a>.
+-spec new([Option]) -> wxGridCellFloatRenderer() when
+ Option :: {width, integer()}
+ | {precision, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({width, Width}, Acc) -> [<<1:32/?UI,Width:32/?UI>>|Acc];
@@ -56,22 +60,25 @@ new(Options)
wxe_util:construct(?wxGridCellFloatRenderer_new,
<<BinOpt/binary>>).
-%% @spec (This::wxGridCellFloatRenderer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloatrenderer.html#wxgridcellfloatrenderergetprecision">external documentation</a>.
+-spec getPrecision(This) -> integer() when
+ This::wxGridCellFloatRenderer().
getPrecision(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellFloatRenderer),
wxe_util:call(?wxGridCellFloatRenderer_GetPrecision,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellFloatRenderer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloatrenderer.html#wxgridcellfloatrenderergetwidth">external documentation</a>.
+-spec getWidth(This) -> integer() when
+ This::wxGridCellFloatRenderer().
getWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellFloatRenderer),
wxe_util:call(?wxGridCellFloatRenderer_GetWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellFloatRenderer(), Params::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloatrenderer.html#wxgridcellfloatrenderersetparameters">external documentation</a>.
+-spec setParameters(This, Params) -> ok when
+ This::wxGridCellFloatRenderer(), Params::unicode:chardata().
setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
when is_list(Params) ->
?CLASS(ThisT,wxGridCellFloatRenderer),
@@ -79,24 +86,26 @@ setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
wxe_util:cast(?wxGridCellFloatRenderer_SetParameters,
<<ThisRef:32/?UI,(byte_size(Params_UC)):32/?UI,(Params_UC)/binary, 0:(((8- ((0+byte_size(Params_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGridCellFloatRenderer(), Precision::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloatrenderer.html#wxgridcellfloatrenderersetprecision">external documentation</a>.
+-spec setPrecision(This, Precision) -> ok when
+ This::wxGridCellFloatRenderer(), Precision::integer().
setPrecision(#wx_ref{type=ThisT,ref=ThisRef},Precision)
when is_integer(Precision) ->
?CLASS(ThisT,wxGridCellFloatRenderer),
wxe_util:cast(?wxGridCellFloatRenderer_SetPrecision,
<<ThisRef:32/?UI,Precision:32/?UI>>).
-%% @spec (This::wxGridCellFloatRenderer(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellfloatrenderer.html#wxgridcellfloatrenderersetwidth">external documentation</a>.
+-spec setWidth(This, Width) -> ok when
+ This::wxGridCellFloatRenderer(), Width::integer().
setWidth(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxGridCellFloatRenderer),
wxe_util:cast(?wxGridCellFloatRenderer_SetWidth,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxGridCellFloatRenderer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellFloatRenderer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellFloatRenderer),
wxe_util:destroy(?wxGridCellFloatRenderer_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellNumberEditor.erl b/lib/wx/src/gen/wxGridCellNumberEditor.erl
index 4ebdbb14e9..68d5670367 100644
--- a/lib/wx/src/gen/wxGridCellNumberEditor.erl
+++ b/lib/wx/src/gen/wxGridCellNumberEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,19 +34,23 @@
-export([beginEdit/4,endEdit/4,handleReturn/2,isCreated/1,paintBackground/3,
parent_class/1,reset/1,setSize/2,show/2,show/3,startingClick/1,startingKey/2]).
+-export_type([wxGridCellNumberEditor/0]).
%% @hidden
parent_class(wxGridCellTextEditor) -> true;
parent_class(wxGridCellEditor) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellNumberEditor()
+-type wxGridCellNumberEditor() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxGridCellNumberEditor().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxGridCellNumberEditor()
-%% Option = {min, integer()} | {max, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellnumbereditor.html#wxgridcellnumbereditorwxgridcellnumbereditor">external documentation</a>.
+-spec new([Option]) -> wxGridCellNumberEditor() when
+ Option :: {min, integer()}
+ | {max, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({min, Min}, Acc) -> [<<1:32/?UI,Min:32/?UI>>|Acc];
@@ -56,15 +60,17 @@ new(Options)
wxe_util:construct(?wxGridCellNumberEditor_new,
<<BinOpt/binary>>).
-%% @spec (This::wxGridCellNumberEditor()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellnumbereditor.html#wxgridcellnumbereditorgetvalue">external documentation</a>.
+-spec getValue(This) -> unicode:charlist() when
+ This::wxGridCellNumberEditor().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridCellNumberEditor),
wxe_util:call(?wxGridCellNumberEditor_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridCellNumberEditor(), Params::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellnumbereditor.html#wxgridcellnumbereditorsetparameters">external documentation</a>.
+-spec setParameters(This, Params) -> ok when
+ This::wxGridCellNumberEditor(), Params::unicode:chardata().
setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
when is_list(Params) ->
?CLASS(ThisT,wxGridCellNumberEditor),
@@ -72,8 +78,8 @@ setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
wxe_util:cast(?wxGridCellNumberEditor_SetParameters,
<<ThisRef:32/?UI,(byte_size(Params_UC)):32/?UI,(Params_UC)/binary, 0:(((8- ((0+byte_size(Params_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGridCellNumberEditor()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellNumberEditor()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellNumberEditor),
wxe_util:destroy(?wxGridCellNumberEditor_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellNumberRenderer.erl b/lib/wx/src/gen/wxGridCellNumberRenderer.erl
index 651057bb4b..b02b6d48c9 100644
--- a/lib/wx/src/gen/wxGridCellNumberRenderer.erl
+++ b/lib/wx/src/gen/wxGridCellNumberRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,19 +33,21 @@
%% inherited exports
-export([draw/8,getBestSize/6,parent_class/1]).
+-export_type([wxGridCellNumberRenderer/0]).
%% @hidden
parent_class(wxGridCellStringRenderer) -> true;
parent_class(wxGridCellRenderer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellNumberRenderer()
+-type wxGridCellNumberRenderer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellnumberrenderer.html#wxgridcellnumberrendererwxgridcellnumberrenderer">external documentation</a>.
+-spec new() -> wxGridCellNumberRenderer().
new() ->
wxe_util:construct(?wxGridCellNumberRenderer_new,
<<>>).
-%% @spec (This::wxGridCellNumberRenderer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellNumberRenderer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellNumberRenderer),
wxe_util:destroy(?wxGridCellNumberRenderer_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellRenderer.erl b/lib/wx/src/gen/wxGridCellRenderer.erl
index d9520c478f..42d376a347 100644
--- a/lib/wx/src/gen/wxGridCellRenderer.erl
+++ b/lib/wx/src/gen/wxGridCellRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,14 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxGridCellRenderer/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, Row::integer(), Col::integer(), IsSelected::bool()) -> ok
+-type wxGridCellRenderer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellrenderer.html#wxgridcellrendererdraw">external documentation</a>.
+-spec draw(This, Grid, Attr, Dc, Rect, Row, Col, IsSelected) -> ok when
+ This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, Row::integer(), Col::integer(), IsSelected::boolean().
draw(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},#wx_ref{type=AttrT,ref=AttrRef},#wx_ref{type=DcT,ref=DcRef},{RectX,RectY,RectW,RectH},Row,Col,IsSelected)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_integer(Row),is_integer(Col),is_boolean(IsSelected) ->
?CLASS(ThisT,wxGridCellRenderer),
@@ -43,8 +46,9 @@ draw(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},#wx_ref{typ
wxe_util:cast(?wxGridCellRenderer_Draw,
<<ThisRef:32/?UI,GridRef:32/?UI,AttrRef:32/?UI,DcRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,Row:32/?UI,Col:32/?UI,(wxe_util:from_bool(IsSelected)):32/?UI>>).
-%% @spec (This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Row::integer(), Col::integer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellrenderer.html#wxgridcellrenderergetbestsize">external documentation</a>.
+-spec getBestSize(This, Grid, Attr, Dc, Row, Col) -> {W::integer(), H::integer()} when
+ This::wxGridCellRenderer(), Grid::wxGrid:wxGrid(), Attr::wxGridCellAttr:wxGridCellAttr(), Dc::wxDC:wxDC(), Row::integer(), Col::integer().
getBestSize(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=GridT,ref=GridRef},#wx_ref{type=AttrT,ref=AttrRef},#wx_ref{type=DcT,ref=DcRef},Row,Col)
when is_integer(Row),is_integer(Col) ->
?CLASS(ThisT,wxGridCellRenderer),
diff --git a/lib/wx/src/gen/wxGridCellStringRenderer.erl b/lib/wx/src/gen/wxGridCellStringRenderer.erl
index 28a79e0453..78fdf558a2 100644
--- a/lib/wx/src/gen/wxGridCellStringRenderer.erl
+++ b/lib/wx/src/gen/wxGridCellStringRenderer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,18 +32,20 @@
%% inherited exports
-export([draw/8,getBestSize/6,parent_class/1]).
+-export_type([wxGridCellStringRenderer/0]).
%% @hidden
parent_class(wxGridCellRenderer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellStringRenderer()
+-type wxGridCellStringRenderer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcellstringrenderer.html#wxgridcellstringrendererwxgridcellstringrenderer">external documentation</a>.
+-spec new() -> wxGridCellStringRenderer().
new() ->
wxe_util:construct(?wxGridCellStringRenderer_new,
<<>>).
-%% @spec (This::wxGridCellStringRenderer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellStringRenderer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellStringRenderer),
wxe_util:destroy(?wxGridCellStringRenderer_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridCellTextEditor.erl b/lib/wx/src/gen/wxGridCellTextEditor.erl
index d9ab1dc107..44a324d5ea 100644
--- a/lib/wx/src/gen/wxGridCellTextEditor.erl
+++ b/lib/wx/src/gen/wxGridCellTextEditor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,18 +33,21 @@
-export([beginEdit/4,endEdit/4,handleReturn/2,isCreated/1,paintBackground/3,
parent_class/1,reset/1,setSize/2,show/2,show/3,startingClick/1,startingKey/2]).
+-export_type([wxGridCellTextEditor/0]).
%% @hidden
parent_class(wxGridCellEditor) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxGridCellTextEditor()
+-type wxGridCellTextEditor() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelltexteditor.html#wxgridcelltexteditorwxgridcelltexteditor">external documentation</a>.
+-spec new() -> wxGridCellTextEditor().
new() ->
wxe_util:construct(?wxGridCellTextEditor_new,
<<>>).
-%% @spec (This::wxGridCellTextEditor(), Params::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridcelltexteditor.html#wxgridcelltexteditorsetparameters">external documentation</a>.
+-spec setParameters(This, Params) -> ok when
+ This::wxGridCellTextEditor(), Params::unicode:chardata().
setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
when is_list(Params) ->
?CLASS(ThisT,wxGridCellTextEditor),
@@ -52,8 +55,8 @@ setParameters(#wx_ref{type=ThisT,ref=ThisRef},Params)
wxe_util:cast(?wxGridCellTextEditor_SetParameters,
<<ThisRef:32/?UI,(byte_size(Params_UC)):32/?UI,(Params_UC)/binary, 0:(((8- ((0+byte_size(Params_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxGridCellTextEditor()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridCellTextEditor()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridCellTextEditor),
wxe_util:destroy(?wxGridCellTextEditor_destroy,Obj),
diff --git a/lib/wx/src/gen/wxGridEvent.erl b/lib/wx/src/gen/wxGridEvent.erl
index 9b7e0012ca..59c2ad53b5 100644
--- a/lib/wx/src/gen/wxGridEvent.erl
+++ b/lib/wx/src/gen/wxGridEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,63 +42,73 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxGridEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxGridEvent()) -> bool()
+-type wxGridEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventaltdown">external documentation</a>.
+-spec altDown(This) -> boolean() when
+ This::wxGridEvent().
altDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_AltDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventcontroldown">external documentation</a>.
+-spec controlDown(This) -> boolean() when
+ This::wxGridEvent().
controlDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_ControlDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventgetcol">external documentation</a>.
+-spec getCol(This) -> integer() when
+ This::wxGridEvent().
getCol(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_GetCol,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxGridEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventgetrow">external documentation</a>.
+-spec getRow(This) -> integer() when
+ This::wxGridEvent().
getRow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_GetRow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventmetadown">external documentation</a>.
+-spec metaDown(This) -> boolean() when
+ This::wxGridEvent().
metaDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_MetaDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventselecting">external documentation</a>.
+-spec selecting(This) -> boolean() when
+ This::wxGridEvent().
selecting(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_Selecting,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridevent.html#wxgrideventshiftdown">external documentation</a>.
+-spec shiftDown(This) -> boolean() when
+ This::wxGridEvent().
shiftDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridEvent),
wxe_util:call(?wxGridEvent_ShiftDown,
diff --git a/lib/wx/src/gen/wxGridSizer.erl b/lib/wx/src/gen/wxGridSizer.erl
index fd8580c70d..10c905f041 100644
--- a/lib/wx/src/gen/wxGridSizer.erl
+++ b/lib/wx/src/gen/wxGridSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,19 +41,25 @@
setMinSize/2,setMinSize/3,setSizeHints/2,setVirtualSizeHints/2,show/2,
show/3]).
+-export_type([wxGridSizer/0]).
%% @hidden
parent_class(wxSizer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Cols::integer()) -> wxGridSizer()
+-type wxGridSizer() :: wx:wx_object().
%% @equiv new(Cols, [])
+-spec new(Cols) -> wxGridSizer() when
+ Cols::integer().
+
new(Cols)
when is_integer(Cols) ->
new(Cols, []).
-%% @spec (Cols::integer(), [Option]) -> wxGridSizer()
-%% Option = {vgap, integer()} | {hgap, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizerwxgridsizer">external documentation</a>.
+-spec new(Cols, [Option]) -> wxGridSizer() when
+ Cols::integer(),
+ Option :: {vgap, integer()}
+ | {hgap, integer()}.
new(Cols, Options)
when is_integer(Cols),is_list(Options) ->
MOpts = fun({vgap, Vgap}, Acc) -> [<<1:32/?UI,Vgap:32/?UI>>|Acc];
@@ -63,75 +69,84 @@ new(Cols, Options)
wxe_util:construct(?wxGridSizer_new_2,
<<Cols:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Rows::integer(), Cols::integer(), Vgap::integer(), Hgap::integer()) -> wxGridSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizerwxgridsizer">external documentation</a>.
+-spec new(Rows, Cols, Vgap, Hgap) -> wxGridSizer() when
+ Rows::integer(), Cols::integer(), Vgap::integer(), Hgap::integer().
new(Rows,Cols,Vgap,Hgap)
when is_integer(Rows),is_integer(Cols),is_integer(Vgap),is_integer(Hgap) ->
wxe_util:construct(?wxGridSizer_new_4,
<<Rows:32/?UI,Cols:32/?UI,Vgap:32/?UI,Hgap:32/?UI>>).
-%% @spec (This::wxGridSizer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizergetcols">external documentation</a>.
+-spec getCols(This) -> integer() when
+ This::wxGridSizer().
getCols(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:call(?wxGridSizer_GetCols,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridSizer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizergethgap">external documentation</a>.
+-spec getHGap(This) -> integer() when
+ This::wxGridSizer().
getHGap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:call(?wxGridSizer_GetHGap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridSizer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizergetrows">external documentation</a>.
+-spec getRows(This) -> integer() when
+ This::wxGridSizer().
getRows(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:call(?wxGridSizer_GetRows,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridSizer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizergetvgap">external documentation</a>.
+-spec getVGap(This) -> integer() when
+ This::wxGridSizer().
getVGap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:call(?wxGridSizer_GetVGap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxGridSizer(), Cols::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizersetcols">external documentation</a>.
+-spec setCols(This, Cols) -> ok when
+ This::wxGridSizer(), Cols::integer().
setCols(#wx_ref{type=ThisT,ref=ThisRef},Cols)
when is_integer(Cols) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:cast(?wxGridSizer_SetCols,
<<ThisRef:32/?UI,Cols:32/?UI>>).
-%% @spec (This::wxGridSizer(), Gap::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizersethgap">external documentation</a>.
+-spec setHGap(This, Gap) -> ok when
+ This::wxGridSizer(), Gap::integer().
setHGap(#wx_ref{type=ThisT,ref=ThisRef},Gap)
when is_integer(Gap) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:cast(?wxGridSizer_SetHGap,
<<ThisRef:32/?UI,Gap:32/?UI>>).
-%% @spec (This::wxGridSizer(), Rows::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizersetrows">external documentation</a>.
+-spec setRows(This, Rows) -> ok when
+ This::wxGridSizer(), Rows::integer().
setRows(#wx_ref{type=ThisT,ref=ThisRef},Rows)
when is_integer(Rows) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:cast(?wxGridSizer_SetRows,
<<ThisRef:32/?UI,Rows:32/?UI>>).
-%% @spec (This::wxGridSizer(), Gap::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxgridsizer.html#wxgridsizersetvgap">external documentation</a>.
+-spec setVGap(This, Gap) -> ok when
+ This::wxGridSizer(), Gap::integer().
setVGap(#wx_ref{type=ThisT,ref=ThisRef},Gap)
when is_integer(Gap) ->
?CLASS(ThisT,wxGridSizer),
wxe_util:cast(?wxGridSizer_SetVGap,
<<ThisRef:32/?UI,Gap:32/?UI>>).
-%% @spec (This::wxGridSizer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGridSizer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxGridSizer),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxHelpEvent.erl b/lib/wx/src/gen/wxHelpEvent.erl
index ef3c666ab7..70da136be8 100644
--- a/lib/wx/src/gen/wxHelpEvent.erl
+++ b/lib/wx/src/gen/wxHelpEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,38 +37,42 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxHelpEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxHelpEvent()) -> Origin
-%% Origin = integer()
+-type wxHelpEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhelpevent.html#wxhelpeventgetorigin">external documentation</a>.
-%%<br /> Origin is one of ?wxHelpEvent_Origin_Unknown | ?wxHelpEvent_Origin_Keyboard | ?wxHelpEvent_Origin_HelpButton
+%%<br /> Res = ?wxHelpEvent_Origin_Unknown | ?wxHelpEvent_Origin_Keyboard | ?wxHelpEvent_Origin_HelpButton
+-spec getOrigin(This) -> wx:wx_enum() when
+ This::wxHelpEvent().
getOrigin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHelpEvent),
wxe_util:call(?wxHelpEvent_GetOrigin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHelpEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhelpevent.html#wxhelpeventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxHelpEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHelpEvent),
wxe_util:call(?wxHelpEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHelpEvent(), Origin::Origin) -> ok
-%% Origin = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhelpevent.html#wxhelpeventsetorigin">external documentation</a>.
-%%<br /> Origin is one of ?wxHelpEvent_Origin_Unknown | ?wxHelpEvent_Origin_Keyboard | ?wxHelpEvent_Origin_HelpButton
+%%<br /> Origin = ?wxHelpEvent_Origin_Unknown | ?wxHelpEvent_Origin_Keyboard | ?wxHelpEvent_Origin_HelpButton
+-spec setOrigin(This, Origin) -> ok when
+ This::wxHelpEvent(), Origin::wx:wx_enum().
setOrigin(#wx_ref{type=ThisT,ref=ThisRef},Origin)
when is_integer(Origin) ->
?CLASS(ThisT,wxHelpEvent),
wxe_util:cast(?wxHelpEvent_SetOrigin,
<<ThisRef:32/?UI,Origin:32/?UI>>).
-%% @spec (This::wxHelpEvent(), Pos::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhelpevent.html#wxhelpeventsetposition">external documentation</a>.
+-spec setPosition(This, Pos) -> ok when
+ This::wxHelpEvent(), Pos::{X::integer(), Y::integer()}.
setPosition(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxHelpEvent),
diff --git a/lib/wx/src/gen/wxHtmlEasyPrinting.erl b/lib/wx/src/gen/wxHtmlEasyPrinting.erl
index 15d673169a..2a5506053b 100644
--- a/lib/wx/src/gen/wxHtmlEasyPrinting.erl
+++ b/lib/wx/src/gen/wxHtmlEasyPrinting.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,17 +32,21 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxHtmlEasyPrinting/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxHtmlEasyPrinting()
+-type wxHtmlEasyPrinting() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxHtmlEasyPrinting().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxHtmlEasyPrinting()
-%% Option = {name, string()} | {parentWindow, wxWindow:wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingwxhtmleasyprinting">external documentation</a>.
+-spec new([Option]) -> wxHtmlEasyPrinting() when
+ Option :: {name, unicode:chardata()}
+ | {parentWindow, wxWindow:wxWindow()}.
new(Options)
when is_list(Options) ->
MOpts = fun({name, Name}, Acc) -> Name_UC = unicode:characters_to_binary([Name,0]),[<<1:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>|Acc];
@@ -52,22 +56,25 @@ new(Options)
wxe_util:construct(?wxHtmlEasyPrinting_new,
<<BinOpt/binary>>).
-%% @spec (This::wxHtmlEasyPrinting()) -> wxPrintData:wxPrintData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintinggetprintdata">external documentation</a>.
+-spec getPrintData(This) -> wxPrintData:wxPrintData() when
+ This::wxHtmlEasyPrinting().
getPrintData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
wxe_util:call(?wxHtmlEasyPrinting_GetPrintData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlEasyPrinting()) -> wxPageSetupDialogData:wxPageSetupDialogData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintinggetpagesetupdata">external documentation</a>.
+-spec getPageSetupData(This) -> wxPageSetupDialogData:wxPageSetupDialogData() when
+ This::wxHtmlEasyPrinting().
getPageSetupData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
wxe_util:call(?wxHtmlEasyPrinting_GetPageSetupData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlEasyPrinting(), Htmlfile::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingpreviewfile">external documentation</a>.
+-spec previewFile(This, Htmlfile) -> boolean() when
+ This::wxHtmlEasyPrinting(), Htmlfile::unicode:chardata().
previewFile(#wx_ref{type=ThisT,ref=ThisRef},Htmlfile)
when is_list(Htmlfile) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -75,15 +82,18 @@ previewFile(#wx_ref{type=ThisT,ref=ThisRef},Htmlfile)
wxe_util:call(?wxHtmlEasyPrinting_PreviewFile,
<<ThisRef:32/?UI,(byte_size(Htmlfile_UC)):32/?UI,(Htmlfile_UC)/binary, 0:(((8- ((0+byte_size(Htmlfile_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlEasyPrinting(), Htmltext::string()) -> bool()
%% @equiv previewText(This,Htmltext, [])
+-spec previewText(This, Htmltext) -> boolean() when
+ This::wxHtmlEasyPrinting(), Htmltext::unicode:chardata().
+
previewText(This,Htmltext)
when is_record(This, wx_ref),is_list(Htmltext) ->
previewText(This,Htmltext, []).
-%% @spec (This::wxHtmlEasyPrinting(), Htmltext::string(), [Option]) -> bool()
-%% Option = {basepath, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingpreviewtext">external documentation</a>.
+-spec previewText(This, Htmltext, [Option]) -> boolean() when
+ This::wxHtmlEasyPrinting(), Htmltext::unicode:chardata(),
+ Option :: {basepath, unicode:chardata()}.
previewText(#wx_ref{type=ThisT,ref=ThisRef},Htmltext, Options)
when is_list(Htmltext),is_list(Options) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -94,8 +104,9 @@ previewText(#wx_ref{type=ThisT,ref=ThisRef},Htmltext, Options)
wxe_util:call(?wxHtmlEasyPrinting_PreviewText,
<<ThisRef:32/?UI,(byte_size(Htmltext_UC)):32/?UI,(Htmltext_UC)/binary, 0:(((8- ((0+byte_size(Htmltext_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxHtmlEasyPrinting(), Htmlfile::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingprintfile">external documentation</a>.
+-spec printFile(This, Htmlfile) -> boolean() when
+ This::wxHtmlEasyPrinting(), Htmlfile::unicode:chardata().
printFile(#wx_ref{type=ThisT,ref=ThisRef},Htmlfile)
when is_list(Htmlfile) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -103,15 +114,18 @@ printFile(#wx_ref{type=ThisT,ref=ThisRef},Htmlfile)
wxe_util:call(?wxHtmlEasyPrinting_PrintFile,
<<ThisRef:32/?UI,(byte_size(Htmlfile_UC)):32/?UI,(Htmlfile_UC)/binary, 0:(((8- ((0+byte_size(Htmlfile_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlEasyPrinting(), Htmltext::string()) -> bool()
%% @equiv printText(This,Htmltext, [])
+-spec printText(This, Htmltext) -> boolean() when
+ This::wxHtmlEasyPrinting(), Htmltext::unicode:chardata().
+
printText(This,Htmltext)
when is_record(This, wx_ref),is_list(Htmltext) ->
printText(This,Htmltext, []).
-%% @spec (This::wxHtmlEasyPrinting(), Htmltext::string(), [Option]) -> bool()
-%% Option = {basepath, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingprinttext">external documentation</a>.
+-spec printText(This, Htmltext, [Option]) -> boolean() when
+ This::wxHtmlEasyPrinting(), Htmltext::unicode:chardata(),
+ Option :: {basepath, unicode:chardata()}.
printText(#wx_ref{type=ThisT,ref=ThisRef},Htmltext, Options)
when is_list(Htmltext),is_list(Options) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -122,22 +136,26 @@ printText(#wx_ref{type=ThisT,ref=ThisRef},Htmltext, Options)
wxe_util:call(?wxHtmlEasyPrinting_PrintText,
<<ThisRef:32/?UI,(byte_size(Htmltext_UC)):32/?UI,(Htmltext_UC)/binary, 0:(((8- ((0+byte_size(Htmltext_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxHtmlEasyPrinting()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingpagesetup">external documentation</a>.
+-spec pageSetup(This) -> ok when
+ This::wxHtmlEasyPrinting().
pageSetup(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
wxe_util:cast(?wxHtmlEasyPrinting_PageSetup,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlEasyPrinting(), Normal_face::string(), Fixed_face::string()) -> ok
%% @equiv setFonts(This,Normal_face,Fixed_face, [])
+-spec setFonts(This, Normal_face, Fixed_face) -> ok when
+ This::wxHtmlEasyPrinting(), Normal_face::unicode:chardata(), Fixed_face::unicode:chardata().
+
setFonts(This,Normal_face,Fixed_face)
when is_record(This, wx_ref),is_list(Normal_face),is_list(Fixed_face) ->
setFonts(This,Normal_face,Fixed_face, []).
-%% @spec (This::wxHtmlEasyPrinting(), Normal_face::string(), Fixed_face::string(), [Option]) -> ok
-%% Option = {sizes, [integer()]}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingsetfonts">external documentation</a>.
+-spec setFonts(This, Normal_face, Fixed_face, [Option]) -> ok when
+ This::wxHtmlEasyPrinting(), Normal_face::unicode:chardata(), Fixed_face::unicode:chardata(),
+ Option :: {sizes, [integer()]}.
setFonts(#wx_ref{type=ThisT,ref=ThisRef},Normal_face,Fixed_face, Options)
when is_list(Normal_face),is_list(Fixed_face),is_list(Options) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -150,15 +168,18 @@ setFonts(#wx_ref{type=ThisT,ref=ThisRef},Normal_face,Fixed_face, Options)
wxe_util:cast(?wxHtmlEasyPrinting_SetFonts,
<<ThisRef:32/?UI,(byte_size(Normal_face_UC)):32/?UI,(Normal_face_UC)/binary, 0:(((8- ((0+byte_size(Normal_face_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Fixed_face_UC)):32/?UI,(Fixed_face_UC)/binary, 0:(((8- ((4+byte_size(Fixed_face_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxHtmlEasyPrinting(), Header::string()) -> ok
%% @equiv setHeader(This,Header, [])
+-spec setHeader(This, Header) -> ok when
+ This::wxHtmlEasyPrinting(), Header::unicode:chardata().
+
setHeader(This,Header)
when is_record(This, wx_ref),is_list(Header) ->
setHeader(This,Header, []).
-%% @spec (This::wxHtmlEasyPrinting(), Header::string(), [Option]) -> ok
-%% Option = {pg, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingsetheader">external documentation</a>.
+-spec setHeader(This, Header, [Option]) -> ok when
+ This::wxHtmlEasyPrinting(), Header::unicode:chardata(),
+ Option :: {pg, integer()}.
setHeader(#wx_ref{type=ThisT,ref=ThisRef},Header, Options)
when is_list(Header),is_list(Options) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -169,15 +190,18 @@ setHeader(#wx_ref{type=ThisT,ref=ThisRef},Header, Options)
wxe_util:cast(?wxHtmlEasyPrinting_SetHeader,
<<ThisRef:32/?UI,(byte_size(Header_UC)):32/?UI,(Header_UC)/binary, 0:(((8- ((0+byte_size(Header_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxHtmlEasyPrinting(), Footer::string()) -> ok
%% @equiv setFooter(This,Footer, [])
+-spec setFooter(This, Footer) -> ok when
+ This::wxHtmlEasyPrinting(), Footer::unicode:chardata().
+
setFooter(This,Footer)
when is_record(This, wx_ref),is_list(Footer) ->
setFooter(This,Footer, []).
-%% @spec (This::wxHtmlEasyPrinting(), Footer::string(), [Option]) -> ok
-%% Option = {pg, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmleasyprinting.html#wxhtmleasyprintingsetfooter">external documentation</a>.
+-spec setFooter(This, Footer, [Option]) -> ok when
+ This::wxHtmlEasyPrinting(), Footer::unicode:chardata(),
+ Option :: {pg, integer()}.
setFooter(#wx_ref{type=ThisT,ref=ThisRef},Footer, Options)
when is_list(Footer),is_list(Options) ->
?CLASS(ThisT,wxHtmlEasyPrinting),
@@ -188,8 +212,8 @@ setFooter(#wx_ref{type=ThisT,ref=ThisRef},Footer, Options)
wxe_util:cast(?wxHtmlEasyPrinting_SetFooter,
<<ThisRef:32/?UI,(byte_size(Footer_UC)):32/?UI,(Footer_UC)/binary, 0:(((8- ((0+byte_size(Footer_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxHtmlEasyPrinting()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxHtmlEasyPrinting()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxHtmlEasyPrinting),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxHtmlLinkEvent.erl b/lib/wx/src/gen/wxHtmlLinkEvent.erl
index 166493ccbc..94fe670f35 100644
--- a/lib/wx/src/gen/wxHtmlLinkEvent.erl
+++ b/lib/wx/src/gen/wxHtmlLinkEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,16 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxHtmlLinkEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxHtmlLinkEvent()) -> wx:wxHtmlLinkInfo()
+-type wxHtmlLinkEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmllinkevent.html#wxhtmllinkeventgetlinkinfo">external documentation</a>.
+-spec getLinkInfo(This) -> wx:wx_wxHtmlLinkInfo() when
+ This::wxHtmlLinkEvent().
getLinkInfo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlLinkEvent),
wxe_util:call(?wxHtmlLinkEvent_GetLinkInfo,
diff --git a/lib/wx/src/gen/wxHtmlWindow.erl b/lib/wx/src/gen/wxHtmlWindow.erl
index ba8278ff56..4820f7d075 100644
--- a/lib/wx/src/gen/wxHtmlWindow.erl
+++ b/lib/wx/src/gen/wxHtmlWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,6 +79,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxHtmlWindow/0]).
%% @hidden
parent_class(wxScrolledWindow) -> true;
parent_class(wxPanel) -> true;
@@ -86,21 +87,28 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxHtmlWindow()
+-type wxHtmlWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowwxhtmlwindow">external documentation</a>.
+-spec new() -> wxHtmlWindow().
new() ->
wxe_util:construct(?wxHtmlWindow_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxHtmlWindow()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxHtmlWindow() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxHtmlWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowwxhtmlwindow">external documentation</a>.
+-spec new(Parent, [Option]) -> wxHtmlWindow() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -113,8 +121,9 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxHtmlWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxHtmlWindow(), Source::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowappendtopage">external documentation</a>.
+-spec appendToPage(This, Source) -> boolean() when
+ This::wxHtmlWindow(), Source::unicode:chardata().
appendToPage(#wx_ref{type=ThisT,ref=ThisRef},Source)
when is_list(Source) ->
?CLASS(ThisT,wxHtmlWindow),
@@ -122,71 +131,81 @@ appendToPage(#wx_ref{type=ThisT,ref=ThisRef},Source)
wxe_util:call(?wxHtmlWindow_AppendToPage,
<<ThisRef:32/?UI,(byte_size(Source_UC)):32/?UI,(Source_UC)/binary, 0:(((8- ((0+byte_size(Source_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowgetopenedanchor">external documentation</a>.
+-spec getOpenedAnchor(This) -> unicode:charlist() when
+ This::wxHtmlWindow().
getOpenedAnchor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_GetOpenedAnchor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowgetopenedpage">external documentation</a>.
+-spec getOpenedPage(This) -> unicode:charlist() when
+ This::wxHtmlWindow().
getOpenedPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_GetOpenedPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowgetopenedpagetitle">external documentation</a>.
+-spec getOpenedPageTitle(This) -> unicode:charlist() when
+ This::wxHtmlWindow().
getOpenedPageTitle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_GetOpenedPageTitle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> wxFrame:wxFrame()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowgetrelatedframe">external documentation</a>.
+-spec getRelatedFrame(This) -> wxFrame:wxFrame() when
+ This::wxHtmlWindow().
getRelatedFrame(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_GetRelatedFrame,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowhistoryback">external documentation</a>.
+-spec historyBack(This) -> boolean() when
+ This::wxHtmlWindow().
historyBack(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_HistoryBack,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowhistorycanback">external documentation</a>.
+-spec historyCanBack(This) -> boolean() when
+ This::wxHtmlWindow().
historyCanBack(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_HistoryCanBack,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowhistorycanforward">external documentation</a>.
+-spec historyCanForward(This) -> boolean() when
+ This::wxHtmlWindow().
historyCanForward(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_HistoryCanForward,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowhistoryclear">external documentation</a>.
+-spec historyClear(This) -> ok when
+ This::wxHtmlWindow().
historyClear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:cast(?wxHtmlWindow_HistoryClear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowhistoryforward">external documentation</a>.
+-spec historyForward(This) -> boolean() when
+ This::wxHtmlWindow().
historyForward(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_HistoryForward,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), Filename::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowloadfile">external documentation</a>.
+-spec loadFile(This, Filename) -> boolean() when
+ This::wxHtmlWindow(), Filename::unicode:chardata().
loadFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
when is_list(Filename) ->
?CLASS(ThisT,wxHtmlWindow),
@@ -194,8 +213,9 @@ loadFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
wxe_util:call(?wxHtmlWindow_LoadFile,
<<ThisRef:32/?UI,(byte_size(Filename_UC)):32/?UI,(Filename_UC)/binary, 0:(((8- ((0+byte_size(Filename_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlWindow(), Location::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowloadpage">external documentation</a>.
+-spec loadPage(This, Location) -> boolean() when
+ This::wxHtmlWindow(), Location::unicode:chardata().
loadPage(#wx_ref{type=ThisT,ref=ThisRef},Location)
when is_list(Location) ->
?CLASS(ThisT,wxHtmlWindow),
@@ -203,53 +223,61 @@ loadPage(#wx_ref{type=ThisT,ref=ThisRef},Location)
wxe_util:call(?wxHtmlWindow_LoadPage,
<<ThisRef:32/?UI,(byte_size(Location_UC)):32/?UI,(Location_UC)/binary, 0:(((8- ((0+byte_size(Location_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowselectall">external documentation</a>.
+-spec selectAll(This) -> ok when
+ This::wxHtmlWindow().
selectAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:cast(?wxHtmlWindow_SelectAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowselectiontotext">external documentation</a>.
+-spec selectionToText(This) -> unicode:charlist() when
+ This::wxHtmlWindow().
selectionToText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_SelectionToText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), Pos::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowselectline">external documentation</a>.
+-spec selectLine(This, Pos) -> ok when
+ This::wxHtmlWindow(), Pos::{X::integer(), Y::integer()}.
selectLine(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:cast(?wxHtmlWindow_SelectLine,
<<ThisRef:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), Pos::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowselectword">external documentation</a>.
+-spec selectWord(This, Pos) -> ok when
+ This::wxHtmlWindow(), Pos::{X::integer(), Y::integer()}.
selectWord(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY})
when is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:cast(?wxHtmlWindow_SelectWord,
<<ThisRef:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowsetborders">external documentation</a>.
+-spec setBorders(This, B) -> ok when
+ This::wxHtmlWindow(), B::integer().
setBorders(#wx_ref{type=ThisT,ref=ThisRef},B)
when is_integer(B) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:cast(?wxHtmlWindow_SetBorders,
<<ThisRef:32/?UI,B:32/?UI>>).
-%% @spec (This::wxHtmlWindow(), Normal_face::string(), Fixed_face::string()) -> ok
%% @equiv setFonts(This,Normal_face,Fixed_face, [])
+-spec setFonts(This, Normal_face, Fixed_face) -> ok when
+ This::wxHtmlWindow(), Normal_face::unicode:chardata(), Fixed_face::unicode:chardata().
+
setFonts(This,Normal_face,Fixed_face)
when is_record(This, wx_ref),is_list(Normal_face),is_list(Fixed_face) ->
setFonts(This,Normal_face,Fixed_face, []).
-%% @spec (This::wxHtmlWindow(), Normal_face::string(), Fixed_face::string(), [Option]) -> ok
-%% Option = {sizes, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowsetfonts">external documentation</a>.
+-spec setFonts(This, Normal_face, Fixed_face, [Option]) -> ok when
+ This::wxHtmlWindow(), Normal_face::unicode:chardata(), Fixed_face::unicode:chardata(),
+ Option :: {sizes, integer()}.
setFonts(#wx_ref{type=ThisT,ref=ThisRef},Normal_face,Fixed_face, Options)
when is_list(Normal_face),is_list(Fixed_face),is_list(Options) ->
?CLASS(ThisT,wxHtmlWindow),
@@ -261,8 +289,9 @@ setFonts(#wx_ref{type=ThisT,ref=ThisRef},Normal_face,Fixed_face, Options)
wxe_util:cast(?wxHtmlWindow_SetFonts,
<<ThisRef:32/?UI,(byte_size(Normal_face_UC)):32/?UI,(Normal_face_UC)/binary, 0:(((8- ((0+byte_size(Normal_face_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Fixed_face_UC)):32/?UI,(Fixed_face_UC)/binary, 0:(((8- ((4+byte_size(Fixed_face_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxHtmlWindow(), Source::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowsetpage">external documentation</a>.
+-spec setPage(This, Source) -> boolean() when
+ This::wxHtmlWindow(), Source::unicode:chardata().
setPage(#wx_ref{type=ThisT,ref=ThisRef},Source)
when is_list(Source) ->
?CLASS(ThisT,wxHtmlWindow),
@@ -270,8 +299,9 @@ setPage(#wx_ref{type=ThisT,ref=ThisRef},Source)
wxe_util:call(?wxHtmlWindow_SetPage,
<<ThisRef:32/?UI,(byte_size(Source_UC)):32/?UI,(Source_UC)/binary, 0:(((8- ((0+byte_size(Source_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlWindow(), Frame::wxFrame:wxFrame(), Format::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowsetrelatedframe">external documentation</a>.
+-spec setRelatedFrame(This, Frame, Format) -> ok when
+ This::wxHtmlWindow(), Frame::wxFrame:wxFrame(), Format::unicode:chardata().
setRelatedFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef},Format)
when is_list(Format) ->
?CLASS(ThisT,wxHtmlWindow),
@@ -280,23 +310,25 @@ setRelatedFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef
wxe_util:cast(?wxHtmlWindow_SetRelatedFrame,
<<ThisRef:32/?UI,FrameRef:32/?UI,(byte_size(Format_UC)):32/?UI,(Format_UC)/binary, 0:(((8- ((4+byte_size(Format_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxHtmlWindow(), Bar::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowsetrelatedstatusbar">external documentation</a>.
+-spec setRelatedStatusBar(This, Bar) -> ok when
+ This::wxHtmlWindow(), Bar::integer().
setRelatedStatusBar(#wx_ref{type=ThisT,ref=ThisRef},Bar)
when is_integer(Bar) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:cast(?wxHtmlWindow_SetRelatedStatusBar,
<<ThisRef:32/?UI,Bar:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxhtmlwindow.html#wxhtmlwindowtotext">external documentation</a>.
+-spec toText(This) -> unicode:charlist() when
+ This::wxHtmlWindow().
toText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxHtmlWindow),
wxe_util:call(?wxHtmlWindow_ToText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxHtmlWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxHtmlWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxHtmlWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxIcon.erl b/lib/wx/src/gen/wxIcon.erl
index 5b224c00b6..0f31278732 100644
--- a/lib/wx/src/gen/wxIcon.erl
+++ b/lib/wx/src/gen/wxIcon.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,24 +35,28 @@
saveFile/3,saveFile/4,setDepth/2,setHeight/2,setMask/2,setPalette/2,
setWidth/2]).
+-export_type([wxIcon/0]).
%% @hidden
parent_class(wxBitmap) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxIcon()
+-type wxIcon() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxicon.html#wxiconwxicon">external documentation</a>.
+-spec new() -> wxIcon().
new() ->
wxe_util:construct(?wxIcon_new_0,
<<>>).
-%% @spec (X::string()|term()) -> wxIcon()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxicon.html#wxiconwxicon">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Filename::string()) -> new(Filename, []) </c></p>
-%% <p><c>
-%% new(Loc::wx:wx()) -> wxIcon() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Loc) -> wxIcon() when<br />
+%% Loc::wx:wx_object().<br />
+%%
+%%<br /> Type = ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+-spec new(Filename) -> wxIcon() when
+ Filename::unicode:chardata();
+ (Loc) -> wxIcon() when
+ Loc::wx:wx_object().
new(Filename)
when is_list(Filename) ->
@@ -62,11 +66,13 @@ new(#wx_ref{type=LocT,ref=LocRef}) ->
wxe_util:construct(?wxIcon_new_1,
<<LocRef:32/?UI>>).
-%% @spec (Filename::string(), [Option]) -> wxIcon()
-%% Option = {type, WxBitmapType} | {desiredWidth, integer()} | {desiredHeight, integer()}
-%% WxBitmapType = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxicon.html#wxiconwxicon">external documentation</a>.
-%%<br /> WxBitmapType is one of ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+%%<br /> Type = ?wxBITMAP_TYPE_INVALID | ?wxBITMAP_TYPE_BMP | ?wxBITMAP_TYPE_BMP_RESOURCE | ?wxBITMAP_TYPE_RESOURCE | ?wxBITMAP_TYPE_ICO | ?wxBITMAP_TYPE_ICO_RESOURCE | ?wxBITMAP_TYPE_CUR | ?wxBITMAP_TYPE_CUR_RESOURCE | ?wxBITMAP_TYPE_XBM | ?wxBITMAP_TYPE_XBM_DATA | ?wxBITMAP_TYPE_XPM | ?wxBITMAP_TYPE_XPM_DATA | ?wxBITMAP_TYPE_TIF | ?wxBITMAP_TYPE_TIF_RESOURCE | ?wxBITMAP_TYPE_GIF | ?wxBITMAP_TYPE_GIF_RESOURCE | ?wxBITMAP_TYPE_PNG | ?wxBITMAP_TYPE_PNG_RESOURCE | ?wxBITMAP_TYPE_JPEG | ?wxBITMAP_TYPE_JPEG_RESOURCE | ?wxBITMAP_TYPE_PNM | ?wxBITMAP_TYPE_PNM_RESOURCE | ?wxBITMAP_TYPE_PCX | ?wxBITMAP_TYPE_PCX_RESOURCE | ?wxBITMAP_TYPE_PICT | ?wxBITMAP_TYPE_PICT_RESOURCE | ?wxBITMAP_TYPE_ICON | ?wxBITMAP_TYPE_ICON_RESOURCE | ?wxBITMAP_TYPE_ANI | ?wxBITMAP_TYPE_IFF | ?wxBITMAP_TYPE_TGA | ?wxBITMAP_TYPE_MACCURSOR | ?wxBITMAP_TYPE_MACCURSOR_RESOURCE | ?wxBITMAP_TYPE_ANY
+-spec new(Filename, [Option]) -> wxIcon() when
+ Filename::unicode:chardata(),
+ Option :: {type, wx:wx_enum()}
+ | {desiredWidth, integer()}
+ | {desiredHeight, integer()}.
new(Filename, Options)
when is_list(Filename),is_list(Options) ->
Filename_UC = unicode:characters_to_binary([Filename,0]),
@@ -78,16 +84,17 @@ new(Filename, Options)
wxe_util:construct(?wxIcon_new_2,
<<(byte_size(Filename_UC)):32/?UI,(Filename_UC)/binary, 0:(((8- ((4+byte_size(Filename_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxIcon(), Bmp::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxicon.html#wxiconcopyfrombitmap">external documentation</a>.
+-spec copyFromBitmap(This, Bmp) -> ok when
+ This::wxIcon(), Bmp::wxBitmap:wxBitmap().
copyFromBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef}) ->
?CLASS(ThisT,wxIcon),
?CLASS(BmpT,wxBitmap),
wxe_util:cast(?wxIcon_CopyFromBitmap,
<<ThisRef:32/?UI,BmpRef:32/?UI>>).
-%% @spec (This::wxIcon()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxIcon()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxIcon),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxIconBundle.erl b/lib/wx/src/gen/wxIconBundle.erl
index ee133cbcb9..5e8bb7cc74 100644
--- a/lib/wx/src/gen/wxIconBundle.erl
+++ b/lib/wx/src/gen/wxIconBundle.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxIconBundle/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxIconBundle()
+-type wxIconBundle() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconbundle.html#wxiconbundlewxiconbundle">external documentation</a>.
+-spec new() -> wxIconBundle().
new() ->
wxe_util:construct(?wxIconBundle_new_0,
<<>>).
-%% @spec (Ic::wxIconBundle() | wxIcon:wxIcon()) -> wxIconBundle()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconbundle.html#wxiconbundlewxiconbundle">external documentation</a>.
+-spec new(Ic) -> wxIconBundle() when
+ Ic::wxIconBundle() | wxIcon:wxIcon().
new(#wx_ref{type=IcT,ref=IcRef}) ->
IcOP = case ?CLASS_T(IcT,wxIconBundle) of
true ->
@@ -50,24 +53,27 @@ new(#wx_ref{type=IcT,ref=IcRef}) ->
wxe_util:construct(IcOP,
<<IcRef:32/?UI>>).
-%% @spec (File::string(), Type::integer()) -> wxIconBundle()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconbundle.html#wxiconbundlewxiconbundle">external documentation</a>.
+-spec new(File, Type) -> wxIconBundle() when
+ File::unicode:chardata(), Type::integer().
new(File,Type)
when is_list(File),is_integer(Type) ->
File_UC = unicode:characters_to_binary([File,0]),
wxe_util:construct(?wxIconBundle_new_2,
<<(byte_size(File_UC)):32/?UI,(File_UC)/binary, 0:(((8- ((4+byte_size(File_UC)) band 16#7)) band 16#7))/unit:8,Type:32/?UI>>).
-%% @spec (This::wxIconBundle(), Icon::wxIcon:wxIcon()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconbundle.html#wxiconbundleaddicon">external documentation</a>.
+-spec addIcon(This, Icon) -> ok when
+ This::wxIconBundle(), Icon::wxIcon:wxIcon().
addIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef}) ->
?CLASS(ThisT,wxIconBundle),
?CLASS(IconT,wxIcon),
wxe_util:cast(?wxIconBundle_AddIcon_1,
<<ThisRef:32/?UI,IconRef:32/?UI>>).
-%% @spec (This::wxIconBundle(), File::string(), Type::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconbundle.html#wxiconbundleaddicon">external documentation</a>.
+-spec addIcon(This, File, Type) -> ok when
+ This::wxIconBundle(), File::unicode:chardata(), Type::integer().
addIcon(#wx_ref{type=ThisT,ref=ThisRef},File,Type)
when is_list(File),is_integer(Type) ->
?CLASS(ThisT,wxIconBundle),
@@ -75,22 +81,24 @@ addIcon(#wx_ref{type=ThisT,ref=ThisRef},File,Type)
wxe_util:cast(?wxIconBundle_AddIcon_2,
<<ThisRef:32/?UI,(byte_size(File_UC)):32/?UI,(File_UC)/binary, 0:(((8- ((0+byte_size(File_UC)) band 16#7)) band 16#7))/unit:8,Type:32/?UI>>).
-%% @spec (This::wxIconBundle()) -> wxIcon:wxIcon()
%% @equiv getIcon(This, [])
+-spec getIcon(This) -> wxIcon:wxIcon() when
+ This::wxIconBundle().
+
getIcon(This)
when is_record(This, wx_ref) ->
getIcon(This, []).
-%% @spec (This::wxIconBundle(),X::term()) -> wxIcon:wxIcon()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconbundle.html#wxiconbundlegeticon">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% getIcon(This::wxIconBundle(), [Option]) -> wxIcon:wxIcon() </c>
-%%<br /> Option = {size, integer()}
-%% </p>
-%% <p><c>
-%% getIcon(This::wxIconBundle(), Size::{W::integer(),H::integer()}) -> wxIcon:wxIcon() </c>
-%% </p>
+%% <br /> Also:<br />
+%% getIcon(This, Size) -> wxIcon:wxIcon() when<br />
+%% This::wxIconBundle(), Size::{W::integer(), H::integer()}.<br />
+%%
+-spec getIcon(This, [Option]) -> wxIcon:wxIcon() when
+ This::wxIconBundle(),
+ Option :: {size, integer()};
+ (This, Size) -> wxIcon:wxIcon() when
+ This::wxIconBundle(), Size::{W::integer(), H::integer()}.
getIcon(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxIconBundle),
@@ -105,8 +113,8 @@ getIcon(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
wxe_util:call(?wxIconBundle_GetIcon_1_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxIconBundle()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxIconBundle()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxIconBundle),
wxe_util:destroy(?wxIconBundle_destruct,Obj),
diff --git a/lib/wx/src/gen/wxIconizeEvent.erl b/lib/wx/src/gen/wxIconizeEvent.erl
index 647d8019a1..f428ebf70f 100644
--- a/lib/wx/src/gen/wxIconizeEvent.erl
+++ b/lib/wx/src/gen/wxIconizeEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +37,15 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxIconizeEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxIconizeEvent()) -> bool()
+-type wxIconizeEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxiconizeevent.html#wxiconizeeventiconized">external documentation</a>.
+-spec iconized(This) -> boolean() when
+ This::wxIconizeEvent().
iconized(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxIconizeEvent),
wxe_util:call(?wxIconizeEvent_Iconized,
diff --git a/lib/wx/src/gen/wxIdleEvent.erl b/lib/wx/src/gen/wxIdleEvent.erl
index 87ed7e0cd2..4749026446 100644
--- a/lib/wx/src/gen/wxIdleEvent.erl
+++ b/lib/wx/src/gen/wxIdleEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,34 +37,39 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxIdleEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Win::wxWindow:wxWindow()) -> bool()
+-type wxIdleEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxidleevent.html#wxidleeventcansend">external documentation</a>.
+-spec canSend(Win) -> boolean() when
+ Win::wxWindow:wxWindow().
canSend(#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(WinT,wxWindow),
wxe_util:call(?wxIdleEvent_CanSend,
<<WinRef:32/?UI>>).
-%% @spec () -> WxIdleMode
-%% WxIdleMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxidleevent.html#wxidleeventgetmode">external documentation</a>.
-%%<br /> WxIdleMode is one of ?wxIDLE_PROCESS_ALL | ?wxIDLE_PROCESS_SPECIFIED
+%%<br /> Res = ?wxIDLE_PROCESS_ALL | ?wxIDLE_PROCESS_SPECIFIED
+-spec getMode() -> wx:wx_enum().
getMode() ->
wxe_util:call(?wxIdleEvent_GetMode,
<<>>).
-%% @spec (This::wxIdleEvent()) -> ok
%% @equiv requestMore(This, [])
+-spec requestMore(This) -> ok when
+ This::wxIdleEvent().
+
requestMore(This)
when is_record(This, wx_ref) ->
requestMore(This, []).
-%% @spec (This::wxIdleEvent(), [Option]) -> ok
-%% Option = {needMore, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxidleevent.html#wxidleeventrequestmore">external documentation</a>.
+-spec requestMore(This, [Option]) -> ok when
+ This::wxIdleEvent(),
+ Option :: {needMore, boolean()}.
requestMore(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxIdleEvent),
@@ -74,17 +79,18 @@ requestMore(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxIdleEvent_RequestMore,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxIdleEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxidleevent.html#wxidleeventmorerequested">external documentation</a>.
+-spec moreRequested(This) -> boolean() when
+ This::wxIdleEvent().
moreRequested(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxIdleEvent),
wxe_util:call(?wxIdleEvent_MoreRequested,
<<ThisRef:32/?UI>>).
-%% @spec (Mode::WxIdleMode) -> ok
-%% WxIdleMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxidleevent.html#wxidleeventsetmode">external documentation</a>.
-%%<br /> WxIdleMode is one of ?wxIDLE_PROCESS_ALL | ?wxIDLE_PROCESS_SPECIFIED
+%%<br /> Mode = ?wxIDLE_PROCESS_ALL | ?wxIDLE_PROCESS_SPECIFIED
+-spec setMode(Mode) -> ok when
+ Mode::wx:wx_enum().
setMode(Mode)
when is_integer(Mode) ->
wxe_util:cast(?wxIdleEvent_SetMode,
diff --git a/lib/wx/src/gen/wxImage.erl b/lib/wx/src/gen/wxImage.erl
index 5fe105fbb2..c21b5d4789 100644
--- a/lib/wx/src/gen/wxImage.erl
+++ b/lib/wx/src/gen/wxImage.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,30 +47,38 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxImage/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxImage()
+-type wxImage() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagewximage">external documentation</a>.
+-spec new() -> wxImage().
new() ->
wxe_util:construct(?wxImage_new_0,
<<>>).
-%% @spec (Name::string()) -> wxImage()
%% @equiv new(Name, [])
+-spec new(Name) -> wxImage() when
+ Name::unicode:chardata().
+
new(Name)
when is_list(Name) ->
new(Name, []).
-%% @spec (X::integer()|string(),X::integer()|term()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagewximage">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Width::integer(), Height::integer()) -> new(Width,Height, []) </c></p>
-%% <p><c>
-%% new(Name::string(), [Option]) -> wxImage() </c>
-%%<br /> Option = {type, integer()} | {index, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Name, [Option]) -> wxImage() when<br />
+%% Name::unicode:chardata(),<br />
+%% Option :: {type, integer()}<br />
+%% | {index, integer()}.<br />
+%%
+-spec new(Width, Height) -> wxImage() when
+ Width::integer(), Height::integer();
+ (Name, [Option]) -> wxImage() when
+ Name::unicode:chardata(),
+ Option :: {type, integer()}
+ | {index, integer()}.
new(Width,Height)
when is_integer(Width),is_integer(Height) ->
@@ -85,19 +93,23 @@ new(Name, Options)
wxe_util:construct(?wxImage_new_2,
<<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (X::integer()|string(),X::integer()|string(),X::binary()|term()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagewximage">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Width::integer(), Height::integer(), Data::binary()) -> new(Width,Height,Data, []) </c></p>
-%% <p><c>
-%% new(Width::integer(), Height::integer(), [Option]) -> wxImage() </c>
-%%<br /> Option = {clear, bool()}
-%% </p>
-%% <p><c>
-%% new(Name::string(), Mimetype::string(), [Option]) -> wxImage() </c>
-%%<br /> Option = {index, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Width, Height, [Option]) -> wxImage() when<br />
+%% Width::integer(), Height::integer(),<br />
+%% Option :: {clear, boolean()};<br />
+%% (Name, Mimetype, [Option]) -> wxImage() when<br />
+%% Name::unicode:chardata(), Mimetype::unicode:chardata(),<br />
+%% Option :: {index, integer()}.<br />
+%%
+-spec new(Width, Height, Data) -> wxImage() when
+ Width::integer(), Height::integer(), Data::binary();
+ (Width, Height, [Option]) -> wxImage() when
+ Width::integer(), Height::integer(),
+ Option :: {clear, boolean()};
+ (Name, Mimetype, [Option]) -> wxImage() when
+ Name::unicode:chardata(), Mimetype::unicode:chardata(),
+ Option :: {index, integer()}.
new(Width,Height,Data)
when is_integer(Width),is_integer(Height),is_binary(Data) ->
@@ -119,15 +131,17 @@ new(Name,Mimetype, Options)
wxe_util:construct(?wxImage_new_3_1,
<<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Mimetype_UC)):32/?UI,(Mimetype_UC)/binary, 0:(((8- ((4+byte_size(Mimetype_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (Width::integer(),Height::integer(),Data::binary(),X::binary()|term()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagewximage">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Width::integer(), Height::integer(), Data::binary(), Alpha::binary()) -> new(Width,Height,Data,Alpha, []) </c></p>
-%% <p><c>
-%% new(Width::integer(), Height::integer(), Data::binary(), [Option]) -> wxImage() </c>
-%%<br /> Option = {static_data, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% new(Width, Height, Data, [Option]) -> wxImage() when<br />
+%% Width::integer(), Height::integer(), Data::binary(),<br />
+%% Option :: {static_data, boolean()}.<br />
+%%
+-spec new(Width, Height, Data, Alpha) -> wxImage() when
+ Width::integer(), Height::integer(), Data::binary(), Alpha::binary();
+ (Width, Height, Data, [Option]) -> wxImage() when
+ Width::integer(), Height::integer(), Data::binary(),
+ Option :: {static_data, boolean()}.
new(Width,Height,Data,Alpha)
when is_integer(Width),is_integer(Height),is_binary(Data),is_binary(Alpha) ->
@@ -141,9 +155,10 @@ new(Width,Height,Data, Options)
wxe_util:construct(?wxImage_new_4,
<<Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (Width::integer(), Height::integer(), Data::binary(), Alpha::binary(), [Option]) -> wxImage()
-%% Option = {static_data, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagewximage">external documentation</a>.
+-spec new(Width, Height, Data, Alpha, [Option]) -> wxImage() when
+ Width::integer(), Height::integer(), Data::binary(), Alpha::binary(),
+ Option :: {static_data, boolean()}.
new(Width,Height,Data,Alpha, Options)
when is_integer(Width),is_integer(Height),is_binary(Data),is_binary(Alpha),is_list(Options) ->
wxe_util:send_bin(Data),
@@ -154,39 +169,45 @@ new(Width,Height,Data,Alpha, Options)
wxe_util:construct(?wxImage_new_5,
<<Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxImage(), Radius::integer()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageblur">external documentation</a>.
+-spec blur(This, Radius) -> wxImage() when
+ This::wxImage(), Radius::integer().
blur(#wx_ref{type=ThisT,ref=ThisRef},Radius)
when is_integer(Radius) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_Blur,
<<ThisRef:32/?UI,Radius:32/?UI>>).
-%% @spec (This::wxImage(), Radius::integer()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageblurhorizontal">external documentation</a>.
+-spec blurHorizontal(This, Radius) -> wxImage() when
+ This::wxImage(), Radius::integer().
blurHorizontal(#wx_ref{type=ThisT,ref=ThisRef},Radius)
when is_integer(Radius) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_BlurHorizontal,
<<ThisRef:32/?UI,Radius:32/?UI>>).
-%% @spec (This::wxImage(), Radius::integer()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageblurvertical">external documentation</a>.
+-spec blurVertical(This, Radius) -> wxImage() when
+ This::wxImage(), Radius::integer().
blurVertical(#wx_ref{type=ThisT,ref=ThisRef},Radius)
when is_integer(Radius) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_BlurVertical,
<<ThisRef:32/?UI,Radius:32/?UI>>).
-%% @spec (This::wxImage()) -> bool()
%% @equiv convertAlphaToMask(This, [])
+-spec convertAlphaToMask(This) -> boolean() when
+ This::wxImage().
+
convertAlphaToMask(This)
when is_record(This, wx_ref) ->
convertAlphaToMask(This, []).
-%% @spec (This::wxImage(), [Option]) -> bool()
-%% Option = {threshold, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageconvertalphatomask">external documentation</a>.
+-spec convertAlphaToMask(This, [Option]) -> boolean() when
+ This::wxImage(),
+ Option :: {threshold, integer()}.
convertAlphaToMask(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -196,15 +217,20 @@ convertAlphaToMask(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxImage_ConvertAlphaToMask,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage()) -> wxImage()
%% @equiv convertToGreyscale(This, [])
+-spec convertToGreyscale(This) -> wxImage() when
+ This::wxImage().
+
convertToGreyscale(This)
when is_record(This, wx_ref) ->
convertToGreyscale(This, []).
-%% @spec (This::wxImage(), [Option]) -> wxImage()
-%% Option = {lr, float()} | {lg, float()} | {lb, float()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageconverttogreyscale">external documentation</a>.
+-spec convertToGreyscale(This, [Option]) -> wxImage() when
+ This::wxImage(),
+ Option :: {lr, number()}
+ | {lg, number()}
+ | {lb, number()}.
convertToGreyscale(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -216,36 +242,42 @@ convertToGreyscale(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxImage_ConvertToGreyscale,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), R::integer(), G::integer(), B::integer()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageconverttomono">external documentation</a>.
+-spec convertToMono(This, R, G, B) -> wxImage() when
+ This::wxImage(), R::integer(), G::integer(), B::integer().
convertToMono(#wx_ref{type=ThisT,ref=ThisRef},R,G,B)
when is_integer(R),is_integer(G),is_integer(B) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_ConvertToMono,
<<ThisRef:32/?UI,R:32/?UI,G:32/?UI,B:32/?UI>>).
-%% @spec (This::wxImage()) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagecopy">external documentation</a>.
+-spec copy(This) -> wxImage() when
+ This::wxImage().
copy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_Copy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage(), Width::integer(), Height::integer()) -> bool()
%% @equiv create(This,Width,Height, [])
+-spec create(This, Width, Height) -> boolean() when
+ This::wxImage(), Width::integer(), Height::integer().
+
create(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
create(This,Width,Height, []).
-%% @spec (This::wxImage(),Width::integer(),Height::integer(),X::binary()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagecreate">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% create(This::wxImage(), Width::integer(), Height::integer(), Data::binary()) -> create(This,Width,Height,Data, []) </c></p>
-%% <p><c>
-%% create(This::wxImage(), Width::integer(), Height::integer(), [Option]) -> bool() </c>
-%%<br /> Option = {clear, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% create(This, Width, Height, [Option]) -> boolean() when<br />
+%% This::wxImage(), Width::integer(), Height::integer(),<br />
+%% Option :: {clear, boolean()}.<br />
+%%
+-spec create(This, Width, Height, Data) -> boolean() when
+ This::wxImage(), Width::integer(), Height::integer(), Data::binary();
+ (This, Width, Height, [Option]) -> boolean() when
+ This::wxImage(), Width::integer(), Height::integer(),
+ Option :: {clear, boolean()}.
create(This,Width,Height,Data)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height),is_binary(Data) ->
@@ -259,15 +291,17 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxImage_Create_3,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(),Width::integer(),Height::integer(),Data::binary(),X::binary()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagecreate">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% create(This::wxImage(), Width::integer(), Height::integer(), Data::binary(), Alpha::binary()) -> create(This,Width,Height,Data,Alpha, []) </c></p>
-%% <p><c>
-%% create(This::wxImage(), Width::integer(), Height::integer(), Data::binary(), [Option]) -> bool() </c>
-%%<br /> Option = {static_data, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% create(This, Width, Height, Data, [Option]) -> boolean() when<br />
+%% This::wxImage(), Width::integer(), Height::integer(), Data::binary(),<br />
+%% Option :: {static_data, boolean()}.<br />
+%%
+-spec create(This, Width, Height, Data, Alpha) -> boolean() when
+ This::wxImage(), Width::integer(), Height::integer(), Data::binary(), Alpha::binary();
+ (This, Width, Height, Data, [Option]) -> boolean() when
+ This::wxImage(), Width::integer(), Height::integer(), Data::binary(),
+ Option :: {static_data, boolean()}.
create(This,Width,Height,Data,Alpha)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height),is_binary(Data),is_binary(Alpha) ->
@@ -282,9 +316,10 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,Data, Options)
wxe_util:call(?wxImage_Create_4,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Width::integer(), Height::integer(), Data::binary(), Alpha::binary(), [Option]) -> bool()
-%% Option = {static_data, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagecreate">external documentation</a>.
+-spec create(This, Width, Height, Data, Alpha, [Option]) -> boolean() when
+ This::wxImage(), Width::integer(), Height::integer(), Data::binary(), Alpha::binary(),
+ Option :: {static_data, boolean()}.
create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,Data,Alpha, Options)
when is_integer(Width),is_integer(Height),is_binary(Data),is_binary(Alpha),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -296,22 +331,30 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height,Data,Alpha, Options)
wxe_util:call(?wxImage_Create_5,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagedestroy">external documentation</a>.
+-spec 'Destroy'(This) -> ok when
+ This::wxImage().
'Destroy'(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_Destroy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> {bool(),R::integer(),G::integer(),B::integer()}
%% @equiv findFirstUnusedColour(This, [])
+-spec findFirstUnusedColour(This) -> Result when
+ Result ::{Res ::boolean(), R::integer(), G::integer(), B::integer()},
+ This::wxImage().
+
findFirstUnusedColour(This)
when is_record(This, wx_ref) ->
findFirstUnusedColour(This, []).
-%% @spec (This::wxImage(), [Option]) -> {bool(),R::integer(),G::integer(),B::integer()}
-%% Option = {startR, integer()} | {startG, integer()} | {startB, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagefindfirstunusedcolour">external documentation</a>.
+-spec findFirstUnusedColour(This, [Option]) -> Result when
+ Result :: {Res ::boolean(), R::integer(), G::integer(), B::integer()},
+ This::wxImage(),
+ Option :: {startR, integer()}
+ | {startG, integer()}
+ | {startB, integer()}.
findFirstUnusedColour(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -323,59 +366,67 @@ findFirstUnusedColour(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxImage_FindFirstUnusedColour,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec () -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetimageextwildcard">external documentation</a>.
+-spec getImageExtWildcard() -> unicode:charlist().
getImageExtWildcard() ->
wxe_util:call(?wxImage_GetImageExtWildcard,
<<>>).
-%% @spec (This::wxImage()) -> binary()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetalpha">external documentation</a>.
+-spec getAlpha(This) -> binary() when
+ This::wxImage().
getAlpha(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetAlpha_0,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetalpha">external documentation</a>.
+-spec getAlpha(This, X, Y) -> integer() when
+ This::wxImage(), X::integer(), Y::integer().
getAlpha(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetAlpha_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetblue">external documentation</a>.
+-spec getBlue(This, X, Y) -> integer() when
+ This::wxImage(), X::integer(), Y::integer().
getBlue(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetBlue,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxImage()) -> binary()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetdata">external documentation</a>.
+-spec getData(This) -> binary() when
+ This::wxImage().
getData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetgreen">external documentation</a>.
+-spec getGreen(This, X, Y) -> integer() when
+ This::wxImage(), X::integer(), Y::integer().
getGreen(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetGreen,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (Name::string()) -> integer()
%% @equiv getImageCount(Name, [])
+-spec getImageCount(Name) -> integer() when
+ Name::unicode:chardata().
+
getImageCount(Name)
when is_list(Name) ->
getImageCount(Name, []).
-%% @spec (Name::string(), [Option]) -> integer()
-%% Option = {type, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetimagecount">external documentation</a>.
+-spec getImageCount(Name, [Option]) -> integer() when
+ Name::unicode:chardata(),
+ Option :: {type, integer()}.
getImageCount(Name, Options)
when is_list(Name),is_list(Options) ->
Name_UC = unicode:characters_to_binary([Name,0]),
@@ -385,87 +436,100 @@ getImageCount(Name, Options)
wxe_util:call(?wxImage_GetImageCount,
<<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxImage()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetheight">external documentation</a>.
+-spec getHeight(This) -> integer() when
+ This::wxImage().
getHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetmaskblue">external documentation</a>.
+-spec getMaskBlue(This) -> integer() when
+ This::wxImage().
getMaskBlue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetMaskBlue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetmaskgreen">external documentation</a>.
+-spec getMaskGreen(This) -> integer() when
+ This::wxImage().
getMaskGreen(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetMaskGreen,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetmaskred">external documentation</a>.
+-spec getMaskRed(This) -> integer() when
+ This::wxImage().
getMaskRed(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetMaskRed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> {bool(),R::integer(),G::integer(),B::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetorfindmaskcolour">external documentation</a>.
+-spec getOrFindMaskColour(This) -> Result when
+ Result ::{Res ::boolean(), R::integer(), G::integer(), B::integer()},
+ This::wxImage().
getOrFindMaskColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetOrFindMaskColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> wxPalette:wxPalette()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetpalette">external documentation</a>.
+-spec getPalette(This) -> wxPalette:wxPalette() when
+ This::wxImage().
getPalette(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetPalette,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetred">external documentation</a>.
+-spec getRed(This, X, Y) -> integer() when
+ This::wxImage(), X::integer(), Y::integer().
getRed(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetRed,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxImage(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> wxImage()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetsubimage">external documentation</a>.
+-spec getSubImage(This, Rect) -> wxImage() when
+ This::wxImage(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
getSubImage(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetSubImage,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxImage()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetwidth">external documentation</a>.
+-spec getWidth(This) -> integer() when
+ This::wxImage().
getWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_GetWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagehasalpha">external documentation</a>.
+-spec hasAlpha(This) -> boolean() when
+ This::wxImage().
hasAlpha(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_HasAlpha,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagehasmask">external documentation</a>.
+-spec hasMask(This) -> boolean() when
+ This::wxImage().
hasMask(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_HasMask,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImage(), Name::string()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetoption">external documentation</a>.
+-spec getOption(This, Name) -> unicode:charlist() when
+ This::wxImage(), Name::unicode:chardata().
getOption(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxImage),
@@ -473,8 +537,9 @@ getOption(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxImage_GetOption,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage(), Name::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagegetoptionint">external documentation</a>.
+-spec getOptionInt(This, Name) -> integer() when
+ This::wxImage(), Name::unicode:chardata().
getOptionInt(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxImage),
@@ -482,8 +547,9 @@ getOptionInt(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxImage_GetOptionInt,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage(), Name::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagehasoption">external documentation</a>.
+-spec hasOption(This, Name) -> boolean() when
+ This::wxImage(), Name::unicode:chardata().
hasOption(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxImage),
@@ -491,28 +557,32 @@ hasOption(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxImage_HasOption,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageinitalpha">external documentation</a>.
+-spec initAlpha(This) -> ok when
+ This::wxImage().
initAlpha(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_InitAlpha,
<<ThisRef:32/?UI>>).
-%% @spec () -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageinitstandardhandlers">external documentation</a>.
+-spec initStandardHandlers() -> ok.
initStandardHandlers() ->
wxe_util:cast(?wxImage_InitStandardHandlers,
<<>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer()) -> bool()
%% @equiv isTransparent(This,X,Y, [])
+-spec isTransparent(This, X, Y) -> boolean() when
+ This::wxImage(), X::integer(), Y::integer().
+
isTransparent(This,X,Y)
when is_record(This, wx_ref),is_integer(X),is_integer(Y) ->
isTransparent(This,X,Y, []).
-%% @spec (This::wxImage(), X::integer(), Y::integer(), [Option]) -> bool()
-%% Option = {threshold, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageistransparent">external documentation</a>.
+-spec isTransparent(This, X, Y, [Option]) -> boolean() when
+ This::wxImage(), X::integer(), Y::integer(),
+ Option :: {threshold, integer()}.
isTransparent(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
when is_integer(X),is_integer(Y),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -522,15 +592,19 @@ isTransparent(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
wxe_util:call(?wxImage_IsTransparent,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Name::string()) -> bool()
%% @equiv loadFile(This,Name, [])
+-spec loadFile(This, Name) -> boolean() when
+ This::wxImage(), Name::unicode:chardata().
+
loadFile(This,Name)
when is_record(This, wx_ref),is_list(Name) ->
loadFile(This,Name, []).
-%% @spec (This::wxImage(), Name::string(), [Option]) -> bool()
-%% Option = {type, integer()} | {index, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageloadfile">external documentation</a>.
+-spec loadFile(This, Name, [Option]) -> boolean() when
+ This::wxImage(), Name::unicode:chardata(),
+ Option :: {type, integer()}
+ | {index, integer()}.
loadFile(#wx_ref{type=ThisT,ref=ThisRef},Name, Options)
when is_list(Name),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -542,9 +616,10 @@ loadFile(#wx_ref{type=ThisT,ref=ThisRef},Name, Options)
wxe_util:call(?wxImage_LoadFile_2,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxImage(), Name::string(), Mimetype::string(), [Option]) -> bool()
-%% Option = {index, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageloadfile">external documentation</a>.
+-spec loadFile(This, Name, Mimetype, [Option]) -> boolean() when
+ This::wxImage(), Name::unicode:chardata(), Mimetype::unicode:chardata(),
+ Option :: {index, integer()}.
loadFile(#wx_ref{type=ThisT,ref=ThisRef},Name,Mimetype, Options)
when is_list(Name),is_list(Mimetype),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -556,30 +631,35 @@ loadFile(#wx_ref{type=ThisT,ref=ThisRef},Name,Mimetype, Options)
wxe_util:call(?wxImage_LoadFile_3,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Mimetype_UC)):32/?UI,(Mimetype_UC)/binary, 0:(((8- ((4+byte_size(Mimetype_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxImage()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageok">external documentation</a>.
+-spec ok(This) -> boolean() when
+ This::wxImage().
ok(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImage),
wxe_util:call(?wxImage_Ok,
<<ThisRef:32/?UI>>).
-%% @spec (Name::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageremovehandler">external documentation</a>.
+-spec removeHandler(Name) -> boolean() when
+ Name::unicode:chardata().
removeHandler(Name)
when is_list(Name) ->
Name_UC = unicode:characters_to_binary([Name,0]),
wxe_util:call(?wxImage_RemoveHandler,
<<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage()) -> wxImage()
%% @equiv mirror(This, [])
+-spec mirror(This) -> wxImage() when
+ This::wxImage().
+
mirror(This)
when is_record(This, wx_ref) ->
mirror(This, []).
-%% @spec (This::wxImage(), [Option]) -> wxImage()
-%% Option = {horizontally, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagemirror">external documentation</a>.
+-spec mirror(This, [Option]) -> wxImage() when
+ This::wxImage(),
+ Option :: {horizontally, boolean()}.
mirror(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -589,23 +669,27 @@ mirror(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxImage_Mirror,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), R1::integer(), G1::integer(), B1::integer(), R2::integer(), G2::integer(), B2::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagereplace">external documentation</a>.
+-spec replace(This, R1, G1, B1, R2, G2, B2) -> ok when
+ This::wxImage(), R1::integer(), G1::integer(), B1::integer(), R2::integer(), G2::integer(), B2::integer().
replace(#wx_ref{type=ThisT,ref=ThisRef},R1,G1,B1,R2,G2,B2)
when is_integer(R1),is_integer(G1),is_integer(B1),is_integer(R2),is_integer(G2),is_integer(B2) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_Replace,
<<ThisRef:32/?UI,R1:32/?UI,G1:32/?UI,B1:32/?UI,R2:32/?UI,G2:32/?UI,B2:32/?UI>>).
-%% @spec (This::wxImage(), Width::integer(), Height::integer()) -> wxImage()
%% @equiv rescale(This,Width,Height, [])
+-spec rescale(This, Width, Height) -> wxImage() when
+ This::wxImage(), Width::integer(), Height::integer().
+
rescale(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
rescale(This,Width,Height, []).
-%% @spec (This::wxImage(), Width::integer(), Height::integer(), [Option]) -> wxImage()
-%% Option = {quality, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagerescale">external documentation</a>.
+-spec rescale(This, Width, Height, [Option]) -> wxImage() when
+ This::wxImage(), Width::integer(), Height::integer(),
+ Option :: {quality, integer()}.
rescale(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -615,15 +699,20 @@ rescale(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxImage_Rescale,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}) -> wxImage()
%% @equiv resize(This,Size,Pos, [])
+-spec resize(This, Size, Pos) -> wxImage() when
+ This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()}.
+
resize(This,Size={SizeW,SizeH},Pos={PosX,PosY})
when is_record(This, wx_ref),is_integer(SizeW),is_integer(SizeH),is_integer(PosX),is_integer(PosY) ->
resize(This,Size,Pos, []).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}, [Option]) -> wxImage()
-%% Option = {r, integer()} | {g, integer()} | {b, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximageresize">external documentation</a>.
+-spec resize(This, Size, Pos, [Option]) -> wxImage() when
+ This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()},
+ Option :: {r, integer()}
+ | {g, integer()}
+ | {b, integer()}.
resize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
when is_integer(SizeW),is_integer(SizeH),is_integer(PosX),is_integer(PosY),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -635,17 +724,21 @@ resize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
wxe_util:call(?wxImage_Resize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI,PosX:32/?UI,PosY:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Angle::float(), Centre_of_rotation::{X::integer(),Y::integer()}) -> wxImage()
%% @equiv rotate(This,Angle,Centre_of_rotation, [])
+-spec rotate(This, Angle, Centre_of_rotation) -> wxImage() when
+ This::wxImage(), Angle::number(), Centre_of_rotation::{X::integer(), Y::integer()}.
+
rotate(This,Angle,Centre_of_rotation={Centre_of_rotationX,Centre_of_rotationY})
- when is_record(This, wx_ref),is_float(Angle),is_integer(Centre_of_rotationX),is_integer(Centre_of_rotationY) ->
+ when is_record(This, wx_ref),is_number(Angle),is_integer(Centre_of_rotationX),is_integer(Centre_of_rotationY) ->
rotate(This,Angle,Centre_of_rotation, []).
-%% @spec (This::wxImage(), Angle::float(), Centre_of_rotation::{X::integer(),Y::integer()}, [Option]) -> wxImage()
-%% Option = {interpolating, bool()} | {offset_after_rotation, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagerotate">external documentation</a>.
+-spec rotate(This, Angle, Centre_of_rotation, [Option]) -> wxImage() when
+ This::wxImage(), Angle::number(), Centre_of_rotation::{X::integer(), Y::integer()},
+ Option :: {interpolating, boolean()}
+ | {offset_after_rotation, {X::integer(), Y::integer()}}.
rotate(#wx_ref{type=ThisT,ref=ThisRef},Angle,{Centre_of_rotationX,Centre_of_rotationY}, Options)
- when is_float(Angle),is_integer(Centre_of_rotationX),is_integer(Centre_of_rotationY),is_list(Options) ->
+ when is_number(Angle),is_integer(Centre_of_rotationX),is_integer(Centre_of_rotationY),is_list(Options) ->
?CLASS(ThisT,wxImage),
MOpts = fun({interpolating, Interpolating}, Acc) -> [<<1:32/?UI,(wxe_util:from_bool(Interpolating)):32/?UI>>|Acc];
({offset_after_rotation, {Offset_after_rotationX,Offset_after_rotationY}}, Acc) -> [<<2:32/?UI,Offset_after_rotationX:32/?UI,Offset_after_rotationY:32/?UI,0:32>>|Acc];
@@ -654,23 +747,27 @@ rotate(#wx_ref{type=ThisT,ref=ThisRef},Angle,{Centre_of_rotationX,Centre_of_rota
wxe_util:call(?wxImage_Rotate,
<<ThisRef:32/?UI,0:32,Angle:64/?F,Centre_of_rotationX:32/?UI,Centre_of_rotationY:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxImage(), Angle::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagerotatehue">external documentation</a>.
+-spec rotateHue(This, Angle) -> ok when
+ This::wxImage(), Angle::number().
rotateHue(#wx_ref{type=ThisT,ref=ThisRef},Angle)
- when is_float(Angle) ->
+ when is_number(Angle) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_RotateHue,
<<ThisRef:32/?UI,0:32,Angle:64/?F>>).
-%% @spec (This::wxImage()) -> wxImage()
%% @equiv rotate90(This, [])
+-spec rotate90(This) -> wxImage() when
+ This::wxImage().
+
rotate90(This)
when is_record(This, wx_ref) ->
rotate90(This, []).
-%% @spec (This::wxImage(), [Option]) -> wxImage()
-%% Option = {clockwise, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagerotate90">external documentation</a>.
+-spec rotate90(This, [Option]) -> wxImage() when
+ This::wxImage(),
+ Option :: {clockwise, boolean()}.
rotate90(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -680,8 +777,9 @@ rotate90(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxImage_Rotate90,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Name::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesavefile">external documentation</a>.
+-spec saveFile(This, Name) -> boolean() when
+ This::wxImage(), Name::unicode:chardata().
saveFile(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxImage),
@@ -689,15 +787,15 @@ saveFile(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxImage_SaveFile_1,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage(),Name::string(),X::integer()|string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesavefile">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% saveFile(This::wxImage(), Name::string(), Type::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% saveFile(This::wxImage(), Name::string(), Mimetype::string()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% saveFile(This, Name, Mimetype) -> boolean() when<br />
+%% This::wxImage(), Name::unicode:chardata(), Mimetype::unicode:chardata().<br />
+%%
+-spec saveFile(This, Name, Type) -> boolean() when
+ This::wxImage(), Name::unicode:chardata(), Type::integer();
+ (This, Name, Mimetype) -> boolean() when
+ This::wxImage(), Name::unicode:chardata(), Mimetype::unicode:chardata().
saveFile(#wx_ref{type=ThisT,ref=ThisRef},Name,Type)
when is_list(Name),is_integer(Type) ->
?CLASS(ThisT,wxImage),
@@ -712,15 +810,18 @@ saveFile(#wx_ref{type=ThisT,ref=ThisRef},Name,Mimetype)
wxe_util:call(?wxImage_SaveFile_2_1,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Mimetype_UC)):32/?UI,(Mimetype_UC)/binary, 0:(((8- ((4+byte_size(Mimetype_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage(), Width::integer(), Height::integer()) -> wxImage()
%% @equiv scale(This,Width,Height, [])
+-spec scale(This, Width, Height) -> wxImage() when
+ This::wxImage(), Width::integer(), Height::integer().
+
scale(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
scale(This,Width,Height, []).
-%% @spec (This::wxImage(), Width::integer(), Height::integer(), [Option]) -> wxImage()
-%% Option = {quality, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagescale">external documentation</a>.
+-spec scale(This, Width, Height, [Option]) -> wxImage() when
+ This::wxImage(), Width::integer(), Height::integer(),
+ Option :: {quality, integer()}.
scale(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -730,15 +831,20 @@ scale(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxImage_Scale,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}) -> wxImage()
%% @equiv size(This,Size,Pos, [])
+-spec size(This, Size, Pos) -> wxImage() when
+ This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()}.
+
size(This,Size={SizeW,SizeH},Pos={PosX,PosY})
when is_record(This, wx_ref),is_integer(SizeW),is_integer(SizeH),is_integer(PosX),is_integer(PosY) ->
size(This,Size,Pos, []).
-%% @spec (This::wxImage(), Size::{W::integer(),H::integer()}, Pos::{X::integer(),Y::integer()}, [Option]) -> wxImage()
-%% Option = {r, integer()} | {g, integer()} | {b, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesize">external documentation</a>.
+-spec size(This, Size, Pos, [Option]) -> wxImage() when
+ This::wxImage(), Size::{W::integer(), H::integer()}, Pos::{X::integer(), Y::integer()},
+ Option :: {r, integer()}
+ | {g, integer()}
+ | {b, integer()}.
size(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
when is_integer(SizeW),is_integer(SizeH),is_integer(PosX),is_integer(PosY),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -750,15 +856,18 @@ size(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH},{PosX,PosY}, Options)
wxe_util:call(?wxImage_Size,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI,PosX:32/?UI,PosY:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Alpha::binary()) -> ok
%% @equiv setAlpha(This,Alpha, [])
+-spec setAlpha(This, Alpha) -> ok when
+ This::wxImage(), Alpha::binary().
+
setAlpha(This,Alpha)
when is_record(This, wx_ref),is_binary(Alpha) ->
setAlpha(This,Alpha, []).
-%% @spec (This::wxImage(), Alpha::binary(), [Option]) -> ok
-%% Option = {static_data, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetalpha">external documentation</a>.
+-spec setAlpha(This, Alpha, [Option]) -> ok when
+ This::wxImage(), Alpha::binary(),
+ Option :: {static_data, boolean()}.
setAlpha(#wx_ref{type=ThisT,ref=ThisRef},Alpha, Options)
when is_binary(Alpha),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -769,23 +878,27 @@ setAlpha(#wx_ref{type=ThisT,ref=ThisRef},Alpha, Options)
wxe_util:cast(?wxImage_SetAlpha_2,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer(), Alpha::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetalpha">external documentation</a>.
+-spec setAlpha(This, X, Y, Alpha) -> ok when
+ This::wxImage(), X::integer(), Y::integer(), Alpha::integer().
setAlpha(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Alpha)
when is_integer(X),is_integer(Y),is_integer(Alpha) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_SetAlpha_3,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,Alpha:32/?UI>>).
-%% @spec (This::wxImage(), Data::binary()) -> ok
%% @equiv setData(This,Data, [])
+-spec setData(This, Data) -> ok when
+ This::wxImage(), Data::binary().
+
setData(This,Data)
when is_record(This, wx_ref),is_binary(Data) ->
setData(This,Data, []).
-%% @spec (This::wxImage(), Data::binary(), [Option]) -> ok
-%% Option = {static_data, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetdata">external documentation</a>.
+-spec setData(This, Data, [Option]) -> ok when
+ This::wxImage(), Data::binary(),
+ Option :: {static_data, boolean()}.
setData(#wx_ref{type=ThisT,ref=ThisRef},Data, Options)
when is_binary(Data),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -796,15 +909,18 @@ setData(#wx_ref{type=ThisT,ref=ThisRef},Data, Options)
wxe_util:cast(?wxImage_SetData_2,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), Data::binary(), New_width::integer(), New_height::integer()) -> ok
%% @equiv setData(This,Data,New_width,New_height, [])
+-spec setData(This, Data, New_width, New_height) -> ok when
+ This::wxImage(), Data::binary(), New_width::integer(), New_height::integer().
+
setData(This,Data,New_width,New_height)
when is_record(This, wx_ref),is_binary(Data),is_integer(New_width),is_integer(New_height) ->
setData(This,Data,New_width,New_height, []).
-%% @spec (This::wxImage(), Data::binary(), New_width::integer(), New_height::integer(), [Option]) -> ok
-%% Option = {static_data, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetdata">external documentation</a>.
+-spec setData(This, Data, New_width, New_height, [Option]) -> ok when
+ This::wxImage(), Data::binary(), New_width::integer(), New_height::integer(),
+ Option :: {static_data, boolean()}.
setData(#wx_ref{type=ThisT,ref=ThisRef},Data,New_width,New_height, Options)
when is_binary(Data),is_integer(New_width),is_integer(New_height),is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -815,15 +931,18 @@ setData(#wx_ref{type=ThisT,ref=ThisRef},Data,New_width,New_height, Options)
wxe_util:cast(?wxImage_SetData_4,
<<ThisRef:32/?UI,New_width:32/?UI,New_height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage()) -> ok
%% @equiv setMask(This, [])
+-spec setMask(This) -> ok when
+ This::wxImage().
+
setMask(This)
when is_record(This, wx_ref) ->
setMask(This, []).
-%% @spec (This::wxImage(), [Option]) -> ok
-%% Option = {mask, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetmask">external documentation</a>.
+-spec setMask(This, [Option]) -> ok when
+ This::wxImage(),
+ Option :: {mask, boolean()}.
setMask(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxImage),
@@ -833,16 +952,18 @@ setMask(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxImage_SetMask,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImage(), R::integer(), G::integer(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetmaskcolour">external documentation</a>.
+-spec setMaskColour(This, R, G, B) -> ok when
+ This::wxImage(), R::integer(), G::integer(), B::integer().
setMaskColour(#wx_ref{type=ThisT,ref=ThisRef},R,G,B)
when is_integer(R),is_integer(G),is_integer(B) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_SetMaskColour,
<<ThisRef:32/?UI,R:32/?UI,G:32/?UI,B:32/?UI>>).
-%% @spec (This::wxImage(), Mask::wxImage(), Mr::integer(), Mg::integer(), Mb::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetmaskfromimage">external documentation</a>.
+-spec setMaskFromImage(This, Mask, Mr, Mg, Mb) -> boolean() when
+ This::wxImage(), Mask::wxImage(), Mr::integer(), Mg::integer(), Mb::integer().
setMaskFromImage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MaskT,ref=MaskRef},Mr,Mg,Mb)
when is_integer(Mr),is_integer(Mg),is_integer(Mb) ->
?CLASS(ThisT,wxImage),
@@ -850,15 +971,15 @@ setMaskFromImage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MaskT,ref=MaskRef}
wxe_util:call(?wxImage_SetMaskFromImage,
<<ThisRef:32/?UI,MaskRef:32/?UI,Mr:32/?UI,Mg:32/?UI,Mb:32/?UI>>).
-%% @spec (This::wxImage(),Name::string(),X::integer()|string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetoption">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setOption(This::wxImage(), Name::string(), Value::integer()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setOption(This::wxImage(), Name::string(), Value::string()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setOption(This, Name, Value) -> ok when<br />
+%% This::wxImage(), Name::unicode:chardata(), Value::unicode:chardata().<br />
+%%
+-spec setOption(This, Name, Value) -> ok when
+ This::wxImage(), Name::unicode:chardata(), Value::integer();
+ (This, Name, Value) -> ok when
+ This::wxImage(), Name::unicode:chardata(), Value::unicode:chardata().
setOption(#wx_ref{type=ThisT,ref=ThisRef},Name,Value)
when is_list(Name),is_integer(Value) ->
?CLASS(ThisT,wxImage),
@@ -873,32 +994,35 @@ setOption(#wx_ref{type=ThisT,ref=ThisRef},Name,Value)
wxe_util:cast(?wxImage_SetOption_2_1,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((4+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxImage(), Palette::wxPalette:wxPalette()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetpalette">external documentation</a>.
+-spec setPalette(This, Palette) -> ok when
+ This::wxImage(), Palette::wxPalette:wxPalette().
setPalette(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PaletteT,ref=PaletteRef}) ->
?CLASS(ThisT,wxImage),
?CLASS(PaletteT,wxPalette),
wxe_util:cast(?wxImage_SetPalette,
<<ThisRef:32/?UI,PaletteRef:32/?UI>>).
-%% @spec (This::wxImage(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, R::integer(), G::integer(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetrgb">external documentation</a>.
+-spec setRGB(This, Rect, R, G, B) -> ok when
+ This::wxImage(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}, R::integer(), G::integer(), B::integer().
setRGB(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH},R,G,B)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_integer(R),is_integer(G),is_integer(B) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_SetRGB_4,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI,R:32/?UI,G:32/?UI,B:32/?UI>>).
-%% @spec (This::wxImage(), X::integer(), Y::integer(), R::integer(), G::integer(), B::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximage.html#wximagesetrgb">external documentation</a>.
+-spec setRGB(This, X, Y, R, G, B) -> ok when
+ This::wxImage(), X::integer(), Y::integer(), R::integer(), G::integer(), B::integer().
setRGB(#wx_ref{type=ThisT,ref=ThisRef},X,Y,R,G,B)
when is_integer(X),is_integer(Y),is_integer(R),is_integer(G),is_integer(B) ->
?CLASS(ThisT,wxImage),
wxe_util:cast(?wxImage_SetRGB_5,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,R:32/?UI,G:32/?UI,B:32/?UI>>).
-%% @spec (This::wxImage()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxImage()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxImage),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxImageList.erl b/lib/wx/src/gen/wxImageList.erl
index dbd51bc47b..e9d936d129 100644
--- a/lib/wx/src/gen/wxImageList.erl
+++ b/lib/wx/src/gen/wxImageList.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,24 +31,30 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxImageList/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxImageList()
+-type wxImageList() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistwximagelist">external documentation</a>.
+-spec new() -> wxImageList().
new() ->
wxe_util:construct(?wxImageList_new_0,
<<>>).
-%% @spec (Width::integer(), Height::integer()) -> wxImageList()
%% @equiv new(Width,Height, [])
+-spec new(Width, Height) -> wxImageList() when
+ Width::integer(), Height::integer().
+
new(Width,Height)
when is_integer(Width),is_integer(Height) ->
new(Width,Height, []).
-%% @spec (Width::integer(), Height::integer(), [Option]) -> wxImageList()
-%% Option = {mask, bool()} | {initialCount, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistwximagelist">external documentation</a>.
+-spec new(Width, Height, [Option]) -> wxImageList() when
+ Width::integer(), Height::integer(),
+ Option :: {mask, boolean()}
+ | {initialCount, integer()}.
new(Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
MOpts = fun({mask, Mask}, Acc) -> [<<1:32/?UI,(wxe_util:from_bool(Mask)):32/?UI>>|Acc];
@@ -58,23 +64,24 @@ new(Width,Height, Options)
wxe_util:construct(?wxImageList_new_3,
<<Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxImageList(), Bitmap::wxBitmap:wxBitmap()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistadd">external documentation</a>.
+-spec add(This, Bitmap) -> integer() when
+ This::wxImageList(), Bitmap::wxBitmap:wxBitmap().
add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(ThisT,wxImageList),
?CLASS(BitmapT,wxBitmap),
wxe_util:call(?wxImageList_Add_1,
<<ThisRef:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxImageList(),Bitmap::wxBitmap:wxBitmap(),X::term()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistadd">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% add(This::wxImageList(), Bitmap::wxBitmap:wxBitmap(), Mask::wxBitmap:wxBitmap()) -> integer() </c>
-%% </p>
-%% <p><c>
-%% add(This::wxImageList(), Bitmap::wxBitmap:wxBitmap(), MaskColour::wx:colour()) -> integer() </c>
-%% </p>
+%% <br /> Also:<br />
+%% add(This, Bitmap, MaskColour) -> integer() when<br />
+%% This::wxImageList(), Bitmap::wxBitmap:wxBitmap(), MaskColour::wx:wx_colour().<br />
+%%
+-spec add(This, Bitmap, Mask) -> integer() when
+ This::wxImageList(), Bitmap::wxBitmap:wxBitmap(), Mask::wxBitmap:wxBitmap();
+ (This, Bitmap, MaskColour) -> integer() when
+ This::wxImageList(), Bitmap::wxBitmap:wxBitmap(), MaskColour::wx:wx_colour().
add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef},#wx_ref{type=MaskT,ref=MaskRef}) ->
?CLASS(ThisT,wxImageList),
?CLASS(BitmapT,wxBitmap),
@@ -88,15 +95,19 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef},MaskColo
wxe_util:call(?wxImageList_Add_2_1,
<<ThisRef:32/?UI,BitmapRef:32/?UI,(wxe_util:colour_bin(MaskColour)):16/binary>>).
-%% @spec (This::wxImageList(), Width::integer(), Height::integer()) -> bool()
%% @equiv create(This,Width,Height, [])
+-spec create(This, Width, Height) -> boolean() when
+ This::wxImageList(), Width::integer(), Height::integer().
+
create(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
create(This,Width,Height, []).
-%% @spec (This::wxImageList(), Width::integer(), Height::integer(), [Option]) -> bool()
-%% Option = {mask, bool()} | {initialCount, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistcreate">external documentation</a>.
+-spec create(This, Width, Height, [Option]) -> boolean() when
+ This::wxImageList(), Width::integer(), Height::integer(),
+ Option :: {mask, boolean()}
+ | {initialCount, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxImageList),
@@ -107,15 +118,19 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxImageList_Create,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImageList(), Index::integer(), Dc::wxDC:wxDC(), X::integer(), Y::integer()) -> bool()
%% @equiv draw(This,Index,Dc,X,Y, [])
+-spec draw(This, Index, Dc, X, Y) -> boolean() when
+ This::wxImageList(), Index::integer(), Dc::wxDC:wxDC(), X::integer(), Y::integer().
+
draw(This,Index,Dc,X,Y)
when is_record(This, wx_ref),is_integer(Index),is_record(Dc, wx_ref),is_integer(X),is_integer(Y) ->
draw(This,Index,Dc,X,Y, []).
-%% @spec (This::wxImageList(), Index::integer(), Dc::wxDC:wxDC(), X::integer(), Y::integer(), [Option]) -> bool()
-%% Option = {flags, integer()} | {solidBackground, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistdraw">external documentation</a>.
+-spec draw(This, Index, Dc, X, Y, [Option]) -> boolean() when
+ This::wxImageList(), Index::integer(), Dc::wxDC:wxDC(), X::integer(), Y::integer(),
+ Option :: {flags, integer()}
+ | {solidBackground, boolean()}.
draw(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=DcT,ref=DcRef},X,Y, Options)
when is_integer(Index),is_integer(X),is_integer(Y),is_list(Options) ->
?CLASS(ThisT,wxImageList),
@@ -127,54 +142,62 @@ draw(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=DcT,ref=DcRef},X,Y, Opti
wxe_util:call(?wxImageList_Draw,
<<ThisRef:32/?UI,Index:32/?UI,DcRef:32/?UI,X:32/?UI,Y:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxImageList(), Index::integer()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistgetbitmap">external documentation</a>.
+-spec getBitmap(This, Index) -> wxBitmap:wxBitmap() when
+ This::wxImageList(), Index::integer().
getBitmap(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxImageList),
wxe_util:call(?wxImageList_GetBitmap,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxImageList(), Index::integer()) -> wxIcon:wxIcon()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistgeticon">external documentation</a>.
+-spec getIcon(This, Index) -> wxIcon:wxIcon() when
+ This::wxImageList(), Index::integer().
getIcon(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxImageList),
wxe_util:call(?wxImageList_GetIcon,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxImageList()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistgetimagecount">external documentation</a>.
+-spec getImageCount(This) -> integer() when
+ This::wxImageList().
getImageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImageList),
wxe_util:call(?wxImageList_GetImageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImageList(), Index::integer()) -> {bool(),Width::integer(),Height::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistgetsize">external documentation</a>.
+-spec getSize(This, Index) -> Result when
+ Result ::{Res ::boolean(), Width::integer(), Height::integer()},
+ This::wxImageList(), Index::integer().
getSize(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxImageList),
wxe_util:call(?wxImageList_GetSize,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxImageList(), Index::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistremove">external documentation</a>.
+-spec remove(This, Index) -> boolean() when
+ This::wxImageList(), Index::integer().
remove(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxImageList),
wxe_util:call(?wxImageList_Remove,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxImageList()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistremoveall">external documentation</a>.
+-spec removeAll(This) -> boolean() when
+ This::wxImageList().
removeAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxImageList),
wxe_util:call(?wxImageList_RemoveAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxImageList(), Index::integer(), Bitmap::wxBitmap:wxBitmap()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistreplace">external documentation</a>.
+-spec replace(This, Index, Bitmap) -> boolean() when
+ This::wxImageList(), Index::integer(), Bitmap::wxBitmap:wxBitmap().
replace(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=BitmapT,ref=BitmapRef})
when is_integer(Index) ->
?CLASS(ThisT,wxImageList),
@@ -182,8 +205,9 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=BitmapT,ref=BitmapRef
wxe_util:call(?wxImageList_Replace_2,
<<ThisRef:32/?UI,Index:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxImageList(), Index::integer(), Bitmap::wxBitmap:wxBitmap(), Mask::wxBitmap:wxBitmap()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wximagelist.html#wximagelistreplace">external documentation</a>.
+-spec replace(This, Index, Bitmap, Mask) -> boolean() when
+ This::wxImageList(), Index::integer(), Bitmap::wxBitmap:wxBitmap(), Mask::wxBitmap:wxBitmap().
replace(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=BitmapT,ref=BitmapRef},#wx_ref{type=MaskT,ref=MaskRef})
when is_integer(Index) ->
?CLASS(ThisT,wxImageList),
@@ -192,8 +216,8 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=BitmapT,ref=BitmapRef
wxe_util:call(?wxImageList_Replace_3,
<<ThisRef:32/?UI,Index:32/?UI,BitmapRef:32/?UI,MaskRef:32/?UI>>).
-%% @spec (This::wxImageList()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxImageList()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxImageList),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxJoystickEvent.erl b/lib/wx/src/gen/wxJoystickEvent.erl
index 2c2d7f3968..979c36cd8c 100644
--- a/lib/wx/src/gen/wxJoystickEvent.erl
+++ b/lib/wx/src/gen/wxJoystickEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,19 +39,24 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxJoystickEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxJoystickEvent()) -> bool()
+-type wxJoystickEvent() :: wx:wx_object().
%% @equiv buttonDown(This, [])
+-spec buttonDown(This) -> boolean() when
+ This::wxJoystickEvent().
+
buttonDown(This)
when is_record(This, wx_ref) ->
buttonDown(This, []).
-%% @spec (This::wxJoystickEvent(), [Option]) -> bool()
-%% Option = {but, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventbuttondown">external documentation</a>.
+-spec buttonDown(This, [Option]) -> boolean() when
+ This::wxJoystickEvent(),
+ Option :: {but, integer()}.
buttonDown(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxJoystickEvent),
@@ -61,15 +66,18 @@ buttonDown(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxJoystickEvent_ButtonDown,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxJoystickEvent()) -> bool()
%% @equiv buttonIsDown(This, [])
+-spec buttonIsDown(This) -> boolean() when
+ This::wxJoystickEvent().
+
buttonIsDown(This)
when is_record(This, wx_ref) ->
buttonIsDown(This, []).
-%% @spec (This::wxJoystickEvent(), [Option]) -> bool()
-%% Option = {but, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventbuttonisdown">external documentation</a>.
+-spec buttonIsDown(This, [Option]) -> boolean() when
+ This::wxJoystickEvent(),
+ Option :: {but, integer()}.
buttonIsDown(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxJoystickEvent),
@@ -79,15 +87,18 @@ buttonIsDown(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxJoystickEvent_ButtonIsDown,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxJoystickEvent()) -> bool()
%% @equiv buttonUp(This, [])
+-spec buttonUp(This) -> boolean() when
+ This::wxJoystickEvent().
+
buttonUp(This)
when is_record(This, wx_ref) ->
buttonUp(This, []).
-%% @spec (This::wxJoystickEvent(), [Option]) -> bool()
-%% Option = {but, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventbuttonup">external documentation</a>.
+-spec buttonUp(This, [Option]) -> boolean() when
+ This::wxJoystickEvent(),
+ Option :: {but, integer()}.
buttonUp(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxJoystickEvent),
@@ -97,57 +108,65 @@ buttonUp(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxJoystickEvent_ButtonUp,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxJoystickEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventgetbuttonchange">external documentation</a>.
+-spec getButtonChange(This) -> integer() when
+ This::wxJoystickEvent().
getButtonChange(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_GetButtonChange,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventgetbuttonstate">external documentation</a>.
+-spec getButtonState(This) -> integer() when
+ This::wxJoystickEvent().
getButtonState(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_GetButtonState,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventgetjoystick">external documentation</a>.
+-spec getJoystick(This) -> integer() when
+ This::wxJoystickEvent().
getJoystick(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_GetJoystick,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxJoystickEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventgetzposition">external documentation</a>.
+-spec getZPosition(This) -> integer() when
+ This::wxJoystickEvent().
getZPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_GetZPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventisbutton">external documentation</a>.
+-spec isButton(This) -> boolean() when
+ This::wxJoystickEvent().
isButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_IsButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventismove">external documentation</a>.
+-spec isMove(This) -> boolean() when
+ This::wxJoystickEvent().
isMove(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_IsMove,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxJoystickEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxjoystickevent.html#wxjoystickeventiszmove">external documentation</a>.
+-spec isZMove(This) -> boolean() when
+ This::wxJoystickEvent().
isZMove(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxJoystickEvent),
wxe_util:call(?wxJoystickEvent_IsZMove,
diff --git a/lib/wx/src/gen/wxKeyEvent.erl b/lib/wx/src/gen/wxKeyEvent.erl
index 00d1e2033a..107d4be685 100644
--- a/lib/wx/src/gen/wxKeyEvent.erl
+++ b/lib/wx/src/gen/wxKeyEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,103 +39,119 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxKeyEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxKeyEvent()) -> bool()
+-type wxKeyEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventaltdown">external documentation</a>.
+-spec altDown(This) -> boolean() when
+ This::wxKeyEvent().
altDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_AltDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventcmddown">external documentation</a>.
+-spec cmdDown(This) -> boolean() when
+ This::wxKeyEvent().
cmdDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_CmdDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventcontroldown">external documentation</a>.
+-spec controlDown(This) -> boolean() when
+ This::wxKeyEvent().
controlDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_ControlDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetkeycode">external documentation</a>.
+-spec getKeyCode(This) -> integer() when
+ This::wxKeyEvent().
getKeyCode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetKeyCode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetmodifiers">external documentation</a>.
+-spec getModifiers(This) -> integer() when
+ This::wxKeyEvent().
getModifiers(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetModifiers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxKeyEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetrawkeycode">external documentation</a>.
+-spec getRawKeyCode(This) -> integer() when
+ This::wxKeyEvent().
getRawKeyCode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetRawKeyCode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetrawkeyflags">external documentation</a>.
+-spec getRawKeyFlags(This) -> integer() when
+ This::wxKeyEvent().
getRawKeyFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetRawKeyFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetunicodekey">external documentation</a>.
+-spec getUnicodeKey(This) -> integer() when
+ This::wxKeyEvent().
getUnicodeKey(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetUnicodeKey,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgetx">external documentation</a>.
+-spec getX(This) -> integer() when
+ This::wxKeyEvent().
getX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventgety">external documentation</a>.
+-spec getY(This) -> integer() when
+ This::wxKeyEvent().
getY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_GetY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventhasmodifiers">external documentation</a>.
+-spec hasModifiers(This) -> boolean() when
+ This::wxKeyEvent().
hasModifiers(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_HasModifiers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventmetadown">external documentation</a>.
+-spec metaDown(This) -> boolean() when
+ This::wxKeyEvent().
metaDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_MetaDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxkeyevent.html#wxkeyeventshiftdown">external documentation</a>.
+-spec shiftDown(This) -> boolean() when
+ This::wxKeyEvent().
shiftDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxKeyEvent),
wxe_util:call(?wxKeyEvent_ShiftDown,
diff --git a/lib/wx/src/gen/wxLayoutAlgorithm.erl b/lib/wx/src/gen/wxLayoutAlgorithm.erl
index 402d116338..d0736e2379 100644
--- a/lib/wx/src/gen/wxLayoutAlgorithm.erl
+++ b/lib/wx/src/gen/wxLayoutAlgorithm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,24 +30,29 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxLayoutAlgorithm/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxLayoutAlgorithm()
+-type wxLayoutAlgorithm() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlayoutalgorithm.html#wxlayoutalgorithmwxlayoutalgorithm">external documentation</a>.
+-spec new() -> wxLayoutAlgorithm().
new() ->
wxe_util:construct(?wxLayoutAlgorithm_new,
<<>>).
-%% @spec (This::wxLayoutAlgorithm(), Frame::wxFrame:wxFrame()) -> bool()
%% @equiv layoutFrame(This,Frame, [])
+-spec layoutFrame(This, Frame) -> boolean() when
+ This::wxLayoutAlgorithm(), Frame::wxFrame:wxFrame().
+
layoutFrame(This,Frame)
when is_record(This, wx_ref),is_record(Frame, wx_ref) ->
layoutFrame(This,Frame, []).
-%% @spec (This::wxLayoutAlgorithm(), Frame::wxFrame:wxFrame(), [Option]) -> bool()
-%% Option = {mainWindow, wxWindow:wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlayoutalgorithm.html#wxlayoutalgorithmlayoutframe">external documentation</a>.
+-spec layoutFrame(This, Frame, [Option]) -> boolean() when
+ This::wxLayoutAlgorithm(), Frame::wxFrame:wxFrame(),
+ Option :: {mainWindow, wxWindow:wxWindow()}.
layoutFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxLayoutAlgorithm),
@@ -58,15 +63,18 @@ layoutFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}, O
wxe_util:call(?wxLayoutAlgorithm_LayoutFrame,
<<ThisRef:32/?UI,FrameRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxLayoutAlgorithm(), Frame::wxMDIParentFrame:wxMDIParentFrame()) -> bool()
%% @equiv layoutMDIFrame(This,Frame, [])
+-spec layoutMDIFrame(This, Frame) -> boolean() when
+ This::wxLayoutAlgorithm(), Frame::wxMDIParentFrame:wxMDIParentFrame().
+
layoutMDIFrame(This,Frame)
when is_record(This, wx_ref),is_record(Frame, wx_ref) ->
layoutMDIFrame(This,Frame, []).
-%% @spec (This::wxLayoutAlgorithm(), Frame::wxMDIParentFrame:wxMDIParentFrame(), [Option]) -> bool()
-%% Option = {rect, {X::integer(),Y::integer(),W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlayoutalgorithm.html#wxlayoutalgorithmlayoutmdiframe">external documentation</a>.
+-spec layoutMDIFrame(This, Frame, [Option]) -> boolean() when
+ This::wxLayoutAlgorithm(), Frame::wxMDIParentFrame:wxMDIParentFrame(),
+ Option :: {rect, {X::integer(), Y::integer(), W::integer(), H::integer()}}.
layoutMDIFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxLayoutAlgorithm),
@@ -77,15 +85,18 @@ layoutMDIFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}
wxe_util:call(?wxLayoutAlgorithm_LayoutMDIFrame,
<<ThisRef:32/?UI,FrameRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxLayoutAlgorithm(), Frame::wxWindow:wxWindow()) -> bool()
%% @equiv layoutWindow(This,Frame, [])
+-spec layoutWindow(This, Frame) -> boolean() when
+ This::wxLayoutAlgorithm(), Frame::wxWindow:wxWindow().
+
layoutWindow(This,Frame)
when is_record(This, wx_ref),is_record(Frame, wx_ref) ->
layoutWindow(This,Frame, []).
-%% @spec (This::wxLayoutAlgorithm(), Frame::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {mainWindow, wxWindow:wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlayoutalgorithm.html#wxlayoutalgorithmlayoutwindow">external documentation</a>.
+-spec layoutWindow(This, Frame, [Option]) -> boolean() when
+ This::wxLayoutAlgorithm(), Frame::wxWindow:wxWindow(),
+ Option :: {mainWindow, wxWindow:wxWindow()}.
layoutWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxLayoutAlgorithm),
@@ -96,8 +107,8 @@ layoutWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef},
wxe_util:call(?wxLayoutAlgorithm_LayoutWindow,
<<ThisRef:32/?UI,FrameRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxLayoutAlgorithm()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxLayoutAlgorithm()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxLayoutAlgorithm),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxListBox.erl b/lib/wx/src/gen/wxListBox.erl
index 731209c586..fa4cbd01d5 100644
--- a/lib/wx/src/gen/wxListBox.erl
+++ b/lib/wx/src/gen/wxListBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxListBox/0]).
%% @hidden
parent_class(wxControlWithItems) -> true;
parent_class(wxControl) -> true;
@@ -81,21 +82,29 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxListBox()
+-type wxListBox() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxwxlistbox">external documentation</a>.
+-spec new() -> wxListBox().
new() ->
wxe_util:construct(?wxListBox_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxListBox()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxListBox() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxListBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {choices, [[string()]]} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxwxlistbox">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxListBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {choices, [unicode:chardata()]}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -109,15 +118,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxListBox_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Pos,Size,Choices, [])
+-spec create(This, Parent, Id, Pos, Size, Choices) -> boolean() when
+ This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()].
+
create(This,Parent,Id,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Pos,Size,Choices, []).
-%% @spec (This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
-%% Option = {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxcreate">external documentation</a>.
+-spec create(This, Parent, Id, Pos, Size, Choices, [Option]) -> boolean() when
+ This::wxListBox(), Parent::wxWindow:wxWindow(), Id::integer(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()],
+ Option :: {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,{PosX,PosY},{SizeW,SizeH},Choices, Options)
when is_integer(Id),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices),is_list(Options) ->
?CLASS(ThisT,wxListBox),
@@ -131,23 +144,27 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,{P
wxe_util:call(?wxListBox_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxListBox(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxdeselect">external documentation</a>.
+-spec deselect(This, N) -> ok when
+ This::wxListBox(), N::integer().
deselect(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListBox),
wxe_util:cast(?wxListBox_Deselect,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListBox()) -> {integer(),ASelections::[integer()]}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxgetselections">external documentation</a>.
+-spec getSelections(This) -> Result when
+ Result ::{Res ::integer(), ASelections::[integer()]},
+ This::wxListBox().
getSelections(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListBox),
wxe_util:call(?wxListBox_GetSelections,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListBox(), Items::[[string()]], Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxinsertitems">external documentation</a>.
+-spec insertItems(This, Items, Pos) -> ok when
+ This::wxListBox(), Items::[unicode:chardata()], Pos::integer().
insertItems(#wx_ref{type=ThisT,ref=ThisRef},Items,Pos)
when is_list(Items),is_integer(Pos) ->
?CLASS(ThisT,wxListBox),
@@ -156,16 +173,18 @@ insertItems(#wx_ref{type=ThisT,ref=ThisRef},Items,Pos)
wxe_util:cast(?wxListBox_InsertItems,
<<ThisRef:32/?UI,(length(Items_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Items_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Items_UCA])) band 16#7)) band 16#7))/unit:8,Pos:32/?UI>>).
-%% @spec (This::wxListBox(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxisselected">external documentation</a>.
+-spec isSelected(This, N) -> boolean() when
+ This::wxListBox(), N::integer().
isSelected(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListBox),
wxe_util:call(?wxListBox_IsSelected,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListBox(), Items::[[string()]]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxset">external documentation</a>.
+-spec set(This, Items) -> ok when
+ This::wxListBox(), Items::[unicode:chardata()].
set(#wx_ref{type=ThisT,ref=ThisRef},Items)
when is_list(Items) ->
?CLASS(ThisT,wxListBox),
@@ -174,23 +193,24 @@ set(#wx_ref{type=ThisT,ref=ThisRef},Items)
wxe_util:cast(?wxListBox_Set,
<<ThisRef:32/?UI,(length(Items_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Items_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Items_UCA])) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListBox(), Point::{X::integer(),Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxhittest">external documentation</a>.
+-spec hitTest(This, Point) -> integer() when
+ This::wxListBox(), Point::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
when is_integer(PointX),is_integer(PointY) ->
?CLASS(ThisT,wxListBox),
wxe_util:call(?wxListBox_HitTest,
<<ThisRef:32/?UI,PointX:32/?UI,PointY:32/?UI>>).
-%% @spec (This::wxListBox(),X::integer()|string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbox.html#wxlistboxsetfirstitem">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setFirstItem(This::wxListBox(), N::integer()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setFirstItem(This::wxListBox(), S::string()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setFirstItem(This, S) -> ok when<br />
+%% This::wxListBox(), S::unicode:chardata().<br />
+%%
+-spec setFirstItem(This, N) -> ok when
+ This::wxListBox(), N::integer();
+ (This, S) -> ok when
+ This::wxListBox(), S::unicode:chardata().
setFirstItem(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListBox),
@@ -203,8 +223,8 @@ setFirstItem(#wx_ref{type=ThisT,ref=ThisRef},S)
wxe_util:cast(?wxListBox_SetFirstItem_1_1,
<<ThisRef:32/?UI,(byte_size(S_UC)):32/?UI,(S_UC)/binary, 0:(((8- ((0+byte_size(S_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListBox()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxListBox()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxListBox),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxListCtrl.erl b/lib/wx/src/gen/wxListCtrl.erl
index 5799206b87..a6288fc02a 100644
--- a/lib/wx/src/gen/wxListCtrl.erl
+++ b/lib/wx/src/gen/wxListCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 @@
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,
+ getItemData/2,getItemFont/2,getItemPosition/2,getItemRect/2,getItemRect/3,
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,
+ getTopItem/1,getViewRect/1,hitTest/3,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,
@@ -83,12 +83,14 @@
show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,update/1,
updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxListCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxListCtrl() :: wx:wx_object().
%% @spec () -> wxListCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
@@ -141,15 +143,18 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
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, [])
+-spec arrange(This) -> boolean() when
+ This::wxListCtrl().
+
arrange(This)
when is_record(This, wx_ref) ->
arrange(This, []).
-%% @spec (This::wxListCtrl(), [Option]) -> bool()
-%% Option = {flag, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlarrange">external documentation</a>.
+-spec arrange(This, [Option]) -> boolean() when
+ This::wxListCtrl(),
+ Option :: {flag, integer()}.
arrange(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -159,8 +164,9 @@ arrange(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxListCtrl_Arrange,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxListCtrl(), ImageList::wxImageList:wxImageList(), Which::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList, Which) -> ok when
+ This::wxListCtrl(), ImageList::wxImageList:wxImageList(), Which::integer().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef},Which)
when is_integer(Which) ->
?CLASS(ThisT,wxListCtrl),
@@ -168,8 +174,9 @@ assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=Imag
wxe_util:cast(?wxListCtrl_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI,Which:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlclearall">external documentation</a>.
+-spec clearAll(This) -> ok when
+ This::wxListCtrl().
clearAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_ClearAll,
@@ -210,61 +217,68 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxListCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrldeleteallitems">external documentation</a>.
+-spec deleteAllItems(This) -> boolean() when
+ This::wxListCtrl().
deleteAllItems(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_DeleteAllItems,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Col::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrldeletecolumn">external documentation</a>.
+-spec deleteColumn(This, Col) -> boolean() when
+ This::wxListCtrl(), Col::integer().
deleteColumn(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_DeleteColumn,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrldeleteitem">external documentation</a>.
+-spec deleteItem(This, Item) -> boolean() when
+ This::wxListCtrl(), Item::integer().
deleteItem(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_DeleteItem,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> wxTextCtrl:wxTextCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrleditlabel">external documentation</a>.
+-spec editLabel(This, Item) -> wxTextCtrl:wxTextCtrl() when
+ This::wxListCtrl(), Item::integer().
editLabel(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_EditLabel,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlensurevisible">external documentation</a>.
+-spec ensureVisible(This, Item) -> boolean() when
+ This::wxListCtrl(), Item::integer().
ensureVisible(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_EnsureVisible,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Start::integer(), Str::string()) -> integer()
%% @equiv findItem(This,Start,Str, [])
+-spec findItem(This, Start, Str) -> integer() when
+ This::wxListCtrl(), Start::integer(), Str::unicode:chardata().
+
findItem(This,Start,Str)
when is_record(This, wx_ref),is_integer(Start),is_list(Str) ->
findItem(This,Start,Str, []).
-%% @spec (This::wxListCtrl(),Start::integer(),X::string()|term(),X::term()|integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlfinditem">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% findItem(This::wxListCtrl(), Start::integer(), Str::string(), [Option]) -> integer() </c>
-%%<br /> Option = {partial, bool()}
-%% </p>
-%% <p><c>
-%% findItem(This::wxListCtrl(), Start::integer(), Pt::{X::integer(),Y::integer()}, Direction::integer()) -> integer() </c>
-%% </p>
+%% <br /> Also:<br />
+%% findItem(This, Start, Pt, Direction) -> integer() when<br />
+%% This::wxListCtrl(), Start::integer(), Pt::{X::integer(), Y::integer()}, Direction::integer().<br />
+%%
+-spec findItem(This, Start, Str, [Option]) -> integer() when
+ This::wxListCtrl(), Start::integer(), Str::unicode:chardata(),
+ Option :: {partial, boolean()};
+ (This, Start, Pt, Direction) -> integer() when
+ This::wxListCtrl(), Start::integer(), Pt::{X::integer(), Y::integer()}, Direction::integer().
findItem(#wx_ref{type=ThisT,ref=ThisRef},Start,Str, Options)
when is_integer(Start),is_list(Str),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -280,8 +294,9 @@ findItem(#wx_ref{type=ThisT,ref=ThisRef},Start,{PtX,PtY},Direction)
wxe_util:call(?wxListCtrl_FindItem_3_1,
<<ThisRef:32/?UI,Start:32/?UI,PtX:32/?UI,PtY:32/?UI,Direction:32/?UI>>).
-%% @spec (This::wxListCtrl(), Col::integer(), Item::wxListItem:wxListItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetcolumn">external documentation</a>.
+-spec getColumn(This, Col, Item) -> boolean() when
+ This::wxListCtrl(), Col::integer(), Item::wxListItem:wxListItem().
getColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=ItemT,ref=ItemRef})
when is_integer(Col) ->
?CLASS(ThisT,wxListCtrl),
@@ -289,148 +304,173 @@ getColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=ItemT,ref=ItemRef})
wxe_util:call(?wxListCtrl_GetColumn,
<<ThisRef:32/?UI,Col:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetcolumncount">external documentation</a>.
+-spec getColumnCount(This) -> integer() when
+ This::wxListCtrl().
getColumnCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetColumnCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Col::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetcolumnwidth">external documentation</a>.
+-spec getColumnWidth(This, Col) -> integer() when
+ This::wxListCtrl(), Col::integer().
getColumnWidth(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetColumnWidth,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetcountperpage">external documentation</a>.
+-spec getCountPerPage(This) -> integer() when
+ This::wxListCtrl().
getCountPerPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetCountPerPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> wxTextCtrl:wxTextCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgeteditcontrol">external documentation</a>.
+-spec getEditControl(This) -> wxTextCtrl:wxTextCtrl() when
+ This::wxListCtrl().
getEditControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetEditControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Which::integer()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetimagelist">external documentation</a>.
+-spec getImageList(This, Which) -> wxImageList:wxImageList() when
+ This::wxListCtrl(), Which::integer().
getImageList(#wx_ref{type=ThisT,ref=ThisRef},Which)
when is_integer(Which) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetImageList,
<<ThisRef:32/?UI,Which:32/?UI>>).
-%% @spec (This::wxListCtrl(), Info::wxListItem:wxListItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitem">external documentation</a>.
+-spec getItem(This, Info) -> boolean() when
+ This::wxListCtrl(), Info::wxListItem:wxListItem().
getItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=InfoT,ref=InfoRef}) ->
?CLASS(ThisT,wxListCtrl),
?CLASS(InfoT,wxListItem),
wxe_util:call(?wxListCtrl_GetItem,
<<ThisRef:32/?UI,InfoRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitembackgroundcolour">external documentation</a>.
+-spec getItemBackgroundColour(This, Item) -> wx:wx_colour4() when
+ This::wxListCtrl(), Item::integer().
getItemBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemBackgroundColour,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemcount">external documentation</a>.
+-spec getItemCount(This) -> integer() when
+ This::wxListCtrl().
getItemCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemdata">external documentation</a>.
+-spec getItemData(This, Item) -> integer() when
+ This::wxListCtrl(), Item::integer().
getItemData(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemData,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemfont">external documentation</a>.
+-spec getItemFont(This, Item) -> wxFont:wxFont() when
+ This::wxListCtrl(), Item::integer().
getItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemFont,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Pos::{X::integer(),Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemposition">external documentation</a>.
-getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Item,{PosX,PosY})
- when is_integer(Item),is_integer(PosX),is_integer(PosY) ->
+-spec getItemPosition(This, Item) -> Result when
+ Result ::{Res ::boolean(), Pos::{X::integer(), Y::integer()}},
+ This::wxListCtrl(), Item::integer().
+getItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Item)
+ when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemPosition,
- <<ThisRef:32/?UI,Item:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
+ <<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool()
-%% @equiv getItemRect(This,Item,Rect, [])
-getItemRect(This,Item,Rect={RectX,RectY,RectW,RectH})
- when is_record(This, wx_ref),is_integer(Item),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
- getItemRect(This,Item,Rect, []).
+%% @equiv getItemRect(This,Item, [])
+-spec getItemRect(This, Item) -> Result when
+ Result ::{Res ::boolean(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}},
+ This::wxListCtrl(), Item::integer().
+
+getItemRect(This,Item)
+ when is_record(This, wx_ref),is_integer(Item) ->
+ getItemRect(This,Item, []).
-%% @spec (This::wxListCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> bool()
-%% Option = {code, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemrect">external documentation</a>.
-getItemRect(#wx_ref{type=ThisT,ref=ThisRef},Item,{RectX,RectY,RectW,RectH}, Options)
- when is_integer(Item),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_list(Options) ->
+-spec getItemRect(This, Item, [Option]) -> Result when
+ Result :: {Res ::boolean(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}},
+ This::wxListCtrl(), Item::integer(),
+ Option :: {code, integer()}.
+getItemRect(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
+ when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
MOpts = fun({code, Code}, Acc) -> [<<1:32/?UI,Code:32/?UI>>|Acc];
(BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
wxe_util:call(?wxListCtrl_GetItemRect,
- <<ThisRef:32/?UI,Item:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, BinOpt/binary>>).
+ <<ThisRef:32/?UI,Item:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListCtrl()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemspacing">external documentation</a>.
+-spec getItemSpacing(This) -> {W::integer(), H::integer()} when
+ This::wxListCtrl().
getItemSpacing(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemSpacing,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), StateMask::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemstate">external documentation</a>.
+-spec getItemState(This, Item, StateMask) -> integer() when
+ This::wxListCtrl(), Item::integer(), StateMask::integer().
getItemState(#wx_ref{type=ThisT,ref=ThisRef},Item,StateMask)
when is_integer(Item),is_integer(StateMask) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemState,
<<ThisRef:32/?UI,Item:32/?UI,StateMask:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemtext">external documentation</a>.
+-spec getItemText(This, Item) -> unicode:charlist() when
+ This::wxListCtrl(), Item::integer().
getItemText(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemText,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetitemtextcolour">external documentation</a>.
+-spec getItemTextColour(This, Item) -> wx:wx_colour4() when
+ This::wxListCtrl(), Item::integer().
getItemTextColour(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetItemTextColour,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> integer()
%% @equiv getNextItem(This,Item, [])
+-spec getNextItem(This, Item) -> integer() when
+ This::wxListCtrl(), Item::integer().
+
getNextItem(This,Item)
when is_record(This, wx_ref),is_integer(Item) ->
getNextItem(This,Item, []).
-%% @spec (This::wxListCtrl(), Item::integer(), [Option]) -> integer()
-%% Option = {geometry, integer()} | {state, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetnextitem">external documentation</a>.
+-spec getNextItem(This, Item, [Option]) -> integer() when
+ This::wxListCtrl(), Item::integer(),
+ Option :: {geometry, integer()}
+ | {state, integer()}.
getNextItem(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -441,50 +481,56 @@ getNextItem(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:call(?wxListCtrl_GetNextItem,
<<ThisRef:32/?UI,Item:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetselecteditemcount">external documentation</a>.
+-spec getSelectedItemCount(This) -> integer() when
+ This::wxListCtrl().
getSelectedItemCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetSelectedItemCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgettextcolour">external documentation</a>.
+-spec getTextColour(This) -> wx:wx_colour4() when
+ This::wxListCtrl().
getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgettopitem">external documentation</a>.
+-spec getTopItem(This) -> integer() when
+ This::wxListCtrl().
getTopItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetTopItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlgetviewrect">external documentation</a>.
+-spec getViewRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxListCtrl().
getViewRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_GetViewRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Point::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlhittest">external documentation</a>.
-hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
- when is_integer(PointX),is_integer(PointY) ->
+-spec hitTest(This, Point, Flags) -> integer() when
+ This::wxListCtrl(), Point::{X::integer(), Y::integer()}, Flags::integer().
+hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY},Flags)
+ when is_integer(PointX),is_integer(PointY),is_integer(Flags) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_HitTest,
- <<ThisRef:32/?UI,PointX:32/?UI,PointY:32/?UI>>).
+ <<ThisRef:32/?UI,PointX:32/?UI,PointY:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxListCtrl(),Col::integer(),X::string()|term()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlinsertcolumn">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insertColumn(This::wxListCtrl(), Col::integer(), Heading::string()) -> insertColumn(This,Col,Heading, []) </c></p>
-%% <p><c>
-%% insertColumn(This::wxListCtrl(), Col::integer(), Info::wxListItem:wxListItem()) -> integer() </c>
-%% </p>
+%% <br /> Also:<br />
+%% insertColumn(This, Col, Info) -> integer() when<br />
+%% This::wxListCtrl(), Col::integer(), Info::wxListItem:wxListItem().<br />
+%%
+-spec insertColumn(This, Col, Heading) -> integer() when
+ This::wxListCtrl(), Col::integer(), Heading::unicode:chardata();
+ (This, Col, Info) -> integer() when
+ This::wxListCtrl(), Col::integer(), Info::wxListItem:wxListItem().
insertColumn(This,Col,Heading)
when is_record(This, wx_ref),is_integer(Col),is_list(Heading) ->
@@ -496,9 +542,11 @@ insertColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=InfoT,ref=InfoRef}
wxe_util:call(?wxListCtrl_InsertColumn_2,
<<ThisRef:32/?UI,Col:32/?UI,InfoRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Col::integer(), Heading::string(), [Option]) -> integer()
-%% Option = {format, integer()} | {width, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlinsertcolumn">external documentation</a>.
+-spec insertColumn(This, Col, Heading, [Option]) -> integer() when
+ This::wxListCtrl(), Col::integer(), Heading::unicode:chardata(),
+ Option :: {format, integer()}
+ | {width, integer()}.
insertColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,Heading, Options)
when is_integer(Col),is_list(Heading),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -510,23 +558,24 @@ insertColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,Heading, Options)
wxe_util:call(?wxListCtrl_InsertColumn_3,
<<ThisRef:32/?UI,Col:32/?UI,(byte_size(Heading_UC)):32/?UI,(Heading_UC)/binary, 0:(((8- ((4+byte_size(Heading_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxListCtrl(), Info::wxListItem:wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlinsertitem">external documentation</a>.
+-spec insertItem(This, Info) -> integer() when
+ This::wxListCtrl(), Info::wxListItem:wxListItem().
insertItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=InfoT,ref=InfoRef}) ->
?CLASS(ThisT,wxListCtrl),
?CLASS(InfoT,wxListItem),
wxe_util:call(?wxListCtrl_InsertItem_1,
<<ThisRef:32/?UI,InfoRef:32/?UI>>).
-%% @spec (This::wxListCtrl(),Index::integer(),X::integer()|string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlinsertitem">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insertItem(This::wxListCtrl(), Index::integer(), ImageIndex::integer()) -> integer() </c>
-%% </p>
-%% <p><c>
-%% insertItem(This::wxListCtrl(), Index::integer(), Label::string()) -> integer() </c>
-%% </p>
+%% <br /> Also:<br />
+%% insertItem(This, Index, Label) -> integer() when<br />
+%% This::wxListCtrl(), Index::integer(), Label::unicode:chardata().<br />
+%%
+-spec insertItem(This, Index, ImageIndex) -> integer() when
+ This::wxListCtrl(), Index::integer(), ImageIndex::integer();
+ (This, Index, Label) -> integer() when
+ This::wxListCtrl(), Index::integer(), Label::unicode:chardata().
insertItem(#wx_ref{type=ThisT,ref=ThisRef},Index,ImageIndex)
when is_integer(Index),is_integer(ImageIndex) ->
?CLASS(ThisT,wxListCtrl),
@@ -539,8 +588,9 @@ insertItem(#wx_ref{type=ThisT,ref=ThisRef},Index,Label)
wxe_util:call(?wxListCtrl_InsertItem_2_1,
<<ThisRef:32/?UI,Index:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListCtrl(), Index::integer(), Label::string(), ImageIndex::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlinsertitem">external documentation</a>.
+-spec insertItem(This, Index, Label, ImageIndex) -> integer() when
+ This::wxListCtrl(), Index::integer(), Label::unicode:chardata(), ImageIndex::integer().
insertItem(#wx_ref{type=ThisT,ref=ThisRef},Index,Label,ImageIndex)
when is_integer(Index),is_list(Label),is_integer(ImageIndex) ->
?CLASS(ThisT,wxListCtrl),
@@ -548,40 +598,45 @@ insertItem(#wx_ref{type=ThisT,ref=ThisRef},Index,Label,ImageIndex)
wxe_util:call(?wxListCtrl_InsertItem_3,
<<ThisRef:32/?UI,Index:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8,ImageIndex:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlrefreshitem">external documentation</a>.
+-spec refreshItem(This, Item) -> ok when
+ This::wxListCtrl(), Item::integer().
refreshItem(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_RefreshItem,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListCtrl(), ItemFrom::integer(), ItemTo::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlrefreshitems">external documentation</a>.
+-spec refreshItems(This, ItemFrom, ItemTo) -> ok when
+ This::wxListCtrl(), ItemFrom::integer(), ItemTo::integer().
refreshItems(#wx_ref{type=ThisT,ref=ThisRef},ItemFrom,ItemTo)
when is_integer(ItemFrom),is_integer(ItemTo) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_RefreshItems,
<<ThisRef:32/?UI,ItemFrom:32/?UI,ItemTo:32/?UI>>).
-%% @spec (This::wxListCtrl(), Dx::integer(), Dy::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlscrolllist">external documentation</a>.
+-spec scrollList(This, Dx, Dy) -> boolean() when
+ This::wxListCtrl(), Dx::integer(), Dy::integer().
scrollList(#wx_ref{type=ThisT,ref=ThisRef},Dx,Dy)
when is_integer(Dx),is_integer(Dy) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_ScrollList,
<<ThisRef:32/?UI,Dx:32/?UI,Dy:32/?UI>>).
-%% @spec (This::wxListCtrl(), Colour::wx:colour()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetbackgroundcolour">external documentation</a>.
+-spec setBackgroundColour(This, Colour) -> boolean() when
+ This::wxListCtrl(), Colour::wx:wx_colour().
setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_SetBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxListCtrl(), Col::integer(), Item::wxListItem:wxListItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetcolumn">external documentation</a>.
+-spec setColumn(This, Col, Item) -> boolean() when
+ This::wxListCtrl(), Col::integer(), Item::wxListItem:wxListItem().
setColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=ItemT,ref=ItemRef})
when is_integer(Col) ->
?CLASS(ThisT,wxListCtrl),
@@ -589,16 +644,18 @@ setColumn(#wx_ref{type=ThisT,ref=ThisRef},Col,#wx_ref{type=ItemT,ref=ItemRef})
wxe_util:call(?wxListCtrl_SetColumn,
<<ThisRef:32/?UI,Col:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Col::integer(), Width::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetcolumnwidth">external documentation</a>.
+-spec setColumnWidth(This, Col, Width) -> boolean() when
+ This::wxListCtrl(), Col::integer(), Width::integer().
setColumnWidth(#wx_ref{type=ThisT,ref=ThisRef},Col,Width)
when is_integer(Col),is_integer(Width) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_SetColumnWidth,
<<ThisRef:32/?UI,Col:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxListCtrl(), ImageList::wxImageList:wxImageList(), Which::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList, Which) -> ok when
+ This::wxListCtrl(), ImageList::wxImageList:wxImageList(), Which::integer().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef},Which)
when is_integer(Which) ->
?CLASS(ThisT,wxListCtrl),
@@ -606,23 +663,27 @@ setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageLi
wxe_util:cast(?wxListCtrl_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI,Which:32/?UI>>).
-%% @spec (This::wxListCtrl(), Info::wxListItem:wxListItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitem">external documentation</a>.
+-spec setItem(This, Info) -> boolean() when
+ This::wxListCtrl(), Info::wxListItem:wxListItem().
setItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=InfoT,ref=InfoRef}) ->
?CLASS(ThisT,wxListCtrl),
?CLASS(InfoT,wxListItem),
wxe_util:call(?wxListCtrl_SetItem_1,
<<ThisRef:32/?UI,InfoRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Index::integer(), Col::integer(), Label::string()) -> integer()
%% @equiv setItem(This,Index,Col,Label, [])
+-spec setItem(This, Index, Col, Label) -> integer() when
+ This::wxListCtrl(), Index::integer(), Col::integer(), Label::unicode:chardata().
+
setItem(This,Index,Col,Label)
when is_record(This, wx_ref),is_integer(Index),is_integer(Col),is_list(Label) ->
setItem(This,Index,Col,Label, []).
-%% @spec (This::wxListCtrl(), Index::integer(), Col::integer(), Label::string(), [Option]) -> integer()
-%% Option = {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitem">external documentation</a>.
+-spec setItem(This, Index, Col, Label, [Option]) -> integer() when
+ This::wxListCtrl(), Index::integer(), Col::integer(), Label::unicode:chardata(),
+ Option :: {imageId, integer()}.
setItem(#wx_ref{type=ThisT,ref=ThisRef},Index,Col,Label, Options)
when is_integer(Index),is_integer(Col),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -633,32 +694,36 @@ setItem(#wx_ref{type=ThisT,ref=ThisRef},Index,Col,Label, Options)
wxe_util:call(?wxListCtrl_SetItem_4,
<<ThisRef:32/?UI,Index:32/?UI,Col:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitembackgroundcolour">external documentation</a>.
+-spec setItemBackgroundColour(This, Item, Col) -> ok when
+ This::wxListCtrl(), Item::integer(), Col::wx:wx_colour().
setItemBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Item,Col)
when is_integer(Item),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_SetItemBackgroundColour,
<<ThisRef:32/?UI,Item:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxListCtrl(), Count::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemcount">external documentation</a>.
+-spec setItemCount(This, Count) -> ok when
+ This::wxListCtrl(), Count::integer().
setItemCount(#wx_ref{type=ThisT,ref=ThisRef},Count)
when is_integer(Count) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_SetItemCount,
<<ThisRef:32/?UI,Count:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Data::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemdata">external documentation</a>.
+-spec setItemData(This, Item, Data) -> boolean() when
+ This::wxListCtrl(), Item::integer(), Data::integer().
setItemData(#wx_ref{type=ThisT,ref=ThisRef},Item,Data)
when is_integer(Item),is_integer(Data) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_SetItemData,
<<ThisRef:32/?UI,Item:32/?UI,Data:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), F::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemfont">external documentation</a>.
+-spec setItemFont(This, Item, F) -> ok when
+ This::wxListCtrl(), Item::integer(), F::wxFont:wxFont().
setItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item,#wx_ref{type=FT,ref=FRef})
when is_integer(Item) ->
?CLASS(ThisT,wxListCtrl),
@@ -666,15 +731,18 @@ setItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item,#wx_ref{type=FT,ref=FRef})
wxe_util:cast(?wxListCtrl_SetItemFont,
<<ThisRef:32/?UI,Item:32/?UI,FRef:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Image::integer()) -> bool()
%% @equiv setItemImage(This,Item,Image, [])
+-spec setItemImage(This, Item, Image) -> boolean() when
+ This::wxListCtrl(), Item::integer(), Image::integer().
+
setItemImage(This,Item,Image)
when is_record(This, wx_ref),is_integer(Item),is_integer(Image) ->
setItemImage(This,Item,Image, []).
-%% @spec (This::wxListCtrl(), Item::integer(), Image::integer(), [Option]) -> bool()
-%% Option = {selImage, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemimage">external documentation</a>.
+-spec setItemImage(This, Item, Image, [Option]) -> boolean() when
+ This::wxListCtrl(), Item::integer(), Image::integer(),
+ Option :: {selImage, integer()}.
setItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Image, Options)
when is_integer(Item),is_integer(Image),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -684,32 +752,36 @@ setItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Image, Options)
wxe_util:call(?wxListCtrl_SetItemImage,
<<ThisRef:32/?UI,Item:32/?UI,Image:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Column::integer(), Image::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemcolumnimage">external documentation</a>.
+-spec setItemColumnImage(This, Item, Column, Image) -> boolean() when
+ This::wxListCtrl(), Item::integer(), Column::integer(), Image::integer().
setItemColumnImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Column,Image)
when is_integer(Item),is_integer(Column),is_integer(Image) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_SetItemColumnImage,
<<ThisRef:32/?UI,Item:32/?UI,Column:32/?UI,Image:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Pos::{X::integer(),Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemposition">external documentation</a>.
+-spec setItemPosition(This, Item, Pos) -> boolean() when
+ This::wxListCtrl(), Item::integer(), Pos::{X::integer(), Y::integer()}.
setItemPosition(#wx_ref{type=ThisT,ref=ThisRef},Item,{PosX,PosY})
when is_integer(Item),is_integer(PosX),is_integer(PosY) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_SetItemPosition,
<<ThisRef:32/?UI,Item:32/?UI,PosX:32/?UI,PosY:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), State::integer(), StateMask::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemstate">external documentation</a>.
+-spec setItemState(This, Item, State, StateMask) -> boolean() when
+ This::wxListCtrl(), Item::integer(), State::integer(), StateMask::integer().
setItemState(#wx_ref{type=ThisT,ref=ThisRef},Item,State,StateMask)
when is_integer(Item),is_integer(State),is_integer(StateMask) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_SetItemState,
<<ThisRef:32/?UI,Item:32/?UI,State:32/?UI,StateMask:32/?UI>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemtext">external documentation</a>.
+-spec setItemText(This, Item, Str) -> ok when
+ This::wxListCtrl(), Item::integer(), Str::unicode:chardata().
setItemText(#wx_ref{type=ThisT,ref=ThisRef},Item,Str)
when is_integer(Item),is_list(Str) ->
?CLASS(ThisT,wxListCtrl),
@@ -717,23 +789,27 @@ setItemText(#wx_ref{type=ThisT,ref=ThisRef},Item,Str)
wxe_util:cast(?wxListCtrl_SetItemText,
<<ThisRef:32/?UI,Item:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((4+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListCtrl(), Item::integer(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetitemtextcolour">external documentation</a>.
+-spec setItemTextColour(This, Item, Col) -> ok when
+ This::wxListCtrl(), Item::integer(), Col::wx:wx_colour().
setItemTextColour(#wx_ref{type=ThisT,ref=ThisRef},Item,Col)
when is_integer(Item),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_SetItemTextColour,
<<ThisRef:32/?UI,Item:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxListCtrl(), Style::integer()) -> ok
%% @equiv setSingleStyle(This,Style, [])
+-spec setSingleStyle(This, Style) -> ok when
+ This::wxListCtrl(), Style::integer().
+
setSingleStyle(This,Style)
when is_record(This, wx_ref),is_integer(Style) ->
setSingleStyle(This,Style, []).
-%% @spec (This::wxListCtrl(), Style::integer(), [Option]) -> ok
-%% Option = {add, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetsinglestyle">external documentation</a>.
+-spec setSingleStyle(This, Style, [Option]) -> ok when
+ This::wxListCtrl(), Style::integer(),
+ Option :: {add, boolean()}.
setSingleStyle(#wx_ref{type=ThisT,ref=ThisRef},Style, Options)
when is_integer(Style),is_list(Options) ->
?CLASS(ThisT,wxListCtrl),
@@ -743,16 +819,18 @@ setSingleStyle(#wx_ref{type=ThisT,ref=ThisRef},Style, Options)
wxe_util:cast(?wxListCtrl_SetSingleStyle,
<<ThisRef:32/?UI,Style:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListCtrl(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsettextcolour">external documentation</a>.
+-spec setTextColour(This, Col) -> ok when
+ This::wxListCtrl(), Col::wx:wx_colour().
setTextColour(#wx_ref{type=ThisT,ref=ThisRef},Col)
when tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxListCtrl),
wxe_util:cast(?wxListCtrl_SetTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxListCtrl(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlsetwindowstyleflag">external documentation</a>.
+-spec setWindowStyleFlag(This, Style) -> ok when
+ This::wxListCtrl(), Style::integer().
setWindowStyleFlag(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxListCtrl),
@@ -777,8 +855,8 @@ sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
end,
SortId = wxe_util:get_cbId(Sort),
wxe_util:call(?wxListCtrl_SortItems, <<ThisRef:32/?UI,SortId:32/?UI>>).
-%% @spec (This::wxListCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxListCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxListCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxListEvent.erl b/lib/wx/src/gen/wxListEvent.erl
index 74f9e6095c..9cbb816096 100644
--- a/lib/wx/src/gen/wxListEvent.erl
+++ b/lib/wx/src/gen/wxListEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,98 +42,113 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxListEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxListEvent()) -> integer()
+-type wxListEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetcachefrom">external documentation</a>.
+-spec getCacheFrom(This) -> integer() when
+ This::wxListEvent().
getCacheFrom(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetCacheFrom,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetcacheto">external documentation</a>.
+-spec getCacheTo(This) -> integer() when
+ This::wxListEvent().
getCacheTo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetCacheTo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetkeycode">external documentation</a>.
+-spec getKeyCode(This) -> integer() when
+ This::wxListEvent().
getKeyCode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetKeyCode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetindex">external documentation</a>.
+-spec getIndex(This) -> integer() when
+ This::wxListEvent().
getIndex(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetIndex,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetcolumn">external documentation</a>.
+-spec getColumn(This) -> integer() when
+ This::wxListEvent().
getColumn(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetColumn,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetpoint">external documentation</a>.
+-spec getPoint(This) -> {X::integer(), Y::integer()} when
+ This::wxListEvent().
getPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxListEvent().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxListEvent().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetimage">external documentation</a>.
+-spec getImage(This) -> integer() when
+ This::wxListEvent().
getImage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetImage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetdata">external documentation</a>.
+-spec getData(This) -> integer() when
+ This::wxListEvent().
getData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetmask">external documentation</a>.
+-spec getMask(This) -> integer() when
+ This::wxListEvent().
getMask(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetMask,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> wxListItem:wxListItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventgetitem">external documentation</a>.
+-spec getItem(This) -> wxListItem:wxListItem() when
+ This::wxListEvent().
getItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_GetItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistevent.html#wxlisteventiseditcancelled">external documentation</a>.
+-spec isEditCancelled(This) -> boolean() when
+ This::wxListEvent().
isEditCancelled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListEvent),
wxe_util:call(?wxListEvent_IsEditCancelled,
diff --git a/lib/wx/src/gen/wxListItem.erl b/lib/wx/src/gen/wxListItem.erl
index 326f674b28..787d686135 100644
--- a/lib/wx/src/gen/wxListItem.erl
+++ b/lib/wx/src/gen/wxListItem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,184 +33,207 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxListItem/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxListItem()
+-type wxListItem() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemwxlistitem">external documentation</a>.
+-spec new() -> wxListItem().
new() ->
wxe_util:construct(?wxListItem_new_0,
<<>>).
-%% @spec (Item::wxListItem()) -> wxListItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemwxlistitem">external documentation</a>.
+-spec new(Item) -> wxListItem() when
+ Item::wxListItem().
new(#wx_ref{type=ItemT,ref=ItemRef}) ->
?CLASS(ItemT,wxListItem),
wxe_util:construct(?wxListItem_new_1,
<<ItemRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxListItem().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> WxListColumnFormat
-%% WxListColumnFormat = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetalign">external documentation</a>.
-%%<br /> WxListColumnFormat is one of ?wxLIST_FORMAT_LEFT | ?wxLIST_FORMAT_RIGHT | ?wxLIST_FORMAT_CENTRE | ?wxLIST_FORMAT_CENTER
+%%<br /> Res = ?wxLIST_FORMAT_LEFT | ?wxLIST_FORMAT_RIGHT | ?wxLIST_FORMAT_CENTRE | ?wxLIST_FORMAT_CENTER
+-spec getAlign(This) -> wx:wx_enum() when
+ This::wxListItem().
getAlign(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetAlign,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetbackgroundcolour">external documentation</a>.
+-spec getBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxListItem().
getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetcolumn">external documentation</a>.
+-spec getColumn(This) -> integer() when
+ This::wxListItem().
getColumn(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetColumn,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxListItem().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetid">external documentation</a>.
+-spec getId(This) -> integer() when
+ This::wxListItem().
getId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetimage">external documentation</a>.
+-spec getImage(This) -> integer() when
+ This::wxListItem().
getImage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetImage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetmask">external documentation</a>.
+-spec getMask(This) -> integer() when
+ This::wxListItem().
getMask(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetMask,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetstate">external documentation</a>.
+-spec getState(This) -> integer() when
+ This::wxListItem().
getState(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetState,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxListItem().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgettextcolour">external documentation</a>.
+-spec getTextColour(This) -> wx:wx_colour4() when
+ This::wxListItem().
getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemgetwidth">external documentation</a>.
+-spec getWidth(This) -> integer() when
+ This::wxListItem().
getWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListItem),
wxe_util:call(?wxListItem_GetWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListItem(), Align::WxListColumnFormat) -> ok
-%% WxListColumnFormat = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetalign">external documentation</a>.
-%%<br /> WxListColumnFormat is one of ?wxLIST_FORMAT_LEFT | ?wxLIST_FORMAT_RIGHT | ?wxLIST_FORMAT_CENTRE | ?wxLIST_FORMAT_CENTER
+%%<br /> Align = ?wxLIST_FORMAT_LEFT | ?wxLIST_FORMAT_RIGHT | ?wxLIST_FORMAT_CENTRE | ?wxLIST_FORMAT_CENTER
+-spec setAlign(This, Align) -> ok when
+ This::wxListItem(), Align::wx:wx_enum().
setAlign(#wx_ref{type=ThisT,ref=ThisRef},Align)
when is_integer(Align) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetAlign,
<<ThisRef:32/?UI,Align:32/?UI>>).
-%% @spec (This::wxListItem(), ColBack::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetbackgroundcolour">external documentation</a>.
+-spec setBackgroundColour(This, ColBack) -> ok when
+ This::wxListItem(), ColBack::wx:wx_colour().
setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},ColBack)
when tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary>>).
-%% @spec (This::wxListItem(), Col::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetcolumn">external documentation</a>.
+-spec setColumn(This, Col) -> ok when
+ This::wxListItem(), Col::integer().
setColumn(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetColumn,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxListItem(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetfont">external documentation</a>.
+-spec setFont(This, Font) -> ok when
+ This::wxListItem(), Font::wxFont:wxFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxListItem),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxListItem_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxListItem(), Id::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetid">external documentation</a>.
+-spec setId(This, Id) -> ok when
+ This::wxListItem(), Id::integer().
setId(#wx_ref{type=ThisT,ref=ThisRef},Id)
when is_integer(Id) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetId,
<<ThisRef:32/?UI,Id:32/?UI>>).
-%% @spec (This::wxListItem(), Image::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetimage">external documentation</a>.
+-spec setImage(This, Image) -> ok when
+ This::wxListItem(), Image::integer().
setImage(#wx_ref{type=ThisT,ref=ThisRef},Image)
when is_integer(Image) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetImage,
<<ThisRef:32/?UI,Image:32/?UI>>).
-%% @spec (This::wxListItem(), Mask::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetmask">external documentation</a>.
+-spec setMask(This, Mask) -> ok when
+ This::wxListItem(), Mask::integer().
setMask(#wx_ref{type=ThisT,ref=ThisRef},Mask)
when is_integer(Mask) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetMask,
<<ThisRef:32/?UI,Mask:32/?UI>>).
-%% @spec (This::wxListItem(), State::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetstate">external documentation</a>.
+-spec setState(This, State) -> ok when
+ This::wxListItem(), State::integer().
setState(#wx_ref{type=ThisT,ref=ThisRef},State)
when is_integer(State) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetState,
<<ThisRef:32/?UI,State:32/?UI>>).
-%% @spec (This::wxListItem(), StateMask::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetstatemask">external documentation</a>.
+-spec setStateMask(This, StateMask) -> ok when
+ This::wxListItem(), StateMask::integer().
setStateMask(#wx_ref{type=ThisT,ref=ThisRef},StateMask)
when is_integer(StateMask) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetStateMask,
<<ThisRef:32/?UI,StateMask:32/?UI>>).
-%% @spec (This::wxListItem(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsettext">external documentation</a>.
+-spec setText(This, Text) -> ok when
+ This::wxListItem(), Text::unicode:chardata().
setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxListItem),
@@ -218,24 +241,26 @@ setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxListItem_SetText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListItem(), ColText::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsettextcolour">external documentation</a>.
+-spec setTextColour(This, ColText) -> ok when
+ This::wxListItem(), ColText::wx:wx_colour().
setTextColour(#wx_ref{type=ThisT,ref=ThisRef},ColText)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColText)):16/binary>>).
-%% @spec (This::wxListItem(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitem.html#wxlistitemsetwidth">external documentation</a>.
+-spec setWidth(This, Width) -> ok when
+ This::wxListItem(), Width::integer().
setWidth(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxListItem),
wxe_util:cast(?wxListItem_SetWidth,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxListItem()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxListItem()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxListItem),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxListItemAttr.erl b/lib/wx/src/gen/wxListItemAttr.erl
index 1a43c71854..daf5ebe96a 100644
--- a/lib/wx/src/gen/wxListItemAttr.erl
+++ b/lib/wx/src/gen/wxListItemAttr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,91 +31,103 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxListItemAttr/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxListItemAttr()
+-type wxListItemAttr() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrwxlistitemattr">external documentation</a>.
+-spec new() -> wxListItemAttr().
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>.
+-spec new(ColText, ColBack, Font) -> wxListItemAttr() when
+ ColText::wx:wx_colour(), ColBack::wx:wx_colour(), Font::wxFont:wxFont().
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>.
+-spec getBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxListItemAttr().
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>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxListItemAttr().
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>.
+-spec getTextColour(This) -> wx:wx_colour4() when
+ This::wxListItemAttr().
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>.
+-spec hasBackgroundColour(This) -> boolean() when
+ This::wxListItemAttr().
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>.
+-spec hasFont(This) -> boolean() when
+ This::wxListItemAttr().
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>.
+-spec hasTextColour(This) -> boolean() when
+ This::wxListItemAttr().
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>.
+-spec setBackgroundColour(This, ColBack) -> ok when
+ This::wxListItemAttr(), ColBack::wx:wx_colour().
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>.
+-spec setFont(This, Font) -> ok when
+ This::wxListItemAttr(), Font::wxFont:wxFont().
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>.
+-spec setTextColour(This, ColText) -> ok when
+ This::wxListItemAttr(), ColText::wx:wx_colour().
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
+-spec destroy(This::wxListItemAttr()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxListItemAttr),
wxe_util:destroy(?wxListItemAttr_destroy,Obj),
diff --git a/lib/wx/src/gen/wxListView.erl b/lib/wx/src/gen/wxListView.erl
index 95a233a562..87cc28cd15 100644
--- a/lib/wx/src/gen/wxListView.erl
+++ b/lib/wx/src/gen/wxListView.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,67 +70,78 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxListView/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxListView(), Col::integer()) -> ok
+-type wxListView() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewclearcolumnimage">external documentation</a>.
+-spec clearColumnImage(This, Col) -> ok when
+ This::wxListView(), Col::integer().
clearColumnImage(#wx_ref{type=ThisT,ref=ThisRef},Col)
when is_integer(Col) ->
?CLASS(ThisT,wxListView),
wxe_util:cast(?wxListView_ClearColumnImage,
<<ThisRef:32/?UI,Col:32/?UI>>).
-%% @spec (This::wxListView(), Index::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewfocus">external documentation</a>.
+-spec focus(This, Index) -> ok when
+ This::wxListView(), Index::integer().
focus(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxListView),
wxe_util:cast(?wxListView_Focus,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxListView()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewgetfirstselected">external documentation</a>.
+-spec getFirstSelected(This) -> integer() when
+ This::wxListView().
getFirstSelected(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListView),
wxe_util:call(?wxListView_GetFirstSelected,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListView()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewgetfocuseditem">external documentation</a>.
+-spec getFocusedItem(This) -> integer() when
+ This::wxListView().
getFocusedItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListView),
wxe_util:call(?wxListView_GetFocusedItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListView(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewgetnextselected">external documentation</a>.
+-spec getNextSelected(This, Item) -> integer() when
+ This::wxListView(), Item::integer().
getNextSelected(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxListView),
wxe_util:call(?wxListView_GetNextSelected,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxListView(), Index::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewisselected">external documentation</a>.
+-spec isSelected(This, Index) -> boolean() when
+ This::wxListView(), Index::integer().
isSelected(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxListView),
wxe_util:call(?wxListView_IsSelected,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxListView(), N::integer()) -> ok
%% @equiv select(This,N, [])
+-spec select(This, N) -> ok when
+ This::wxListView(), N::integer().
+
select(This,N)
when is_record(This, wx_ref),is_integer(N) ->
select(This,N, []).
-%% @spec (This::wxListView(), N::integer(), [Option]) -> ok
-%% Option = {on, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewselect">external documentation</a>.
+-spec select(This, N, [Option]) -> ok when
+ This::wxListView(), N::integer(),
+ Option :: {on, boolean()}.
select(#wx_ref{type=ThisT,ref=ThisRef},N, Options)
when is_integer(N),is_list(Options) ->
?CLASS(ThisT,wxListView),
@@ -140,8 +151,9 @@ select(#wx_ref{type=ThisT,ref=ThisRef},N, Options)
wxe_util:cast(?wxListView_Select,
<<ThisRef:32/?UI,N:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListView(), Col::integer(), Image::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistview.html#wxlistviewsetcolumnimage">external documentation</a>.
+-spec setColumnImage(This, Col, Image) -> ok when
+ This::wxListView(), Col::integer(), Image::integer().
setColumnImage(#wx_ref{type=ThisT,ref=ThisRef},Col,Image)
when is_integer(Col),is_integer(Image) ->
?CLASS(ThisT,wxListView),
diff --git a/lib/wx/src/gen/wxListbook.erl b/lib/wx/src/gen/wxListbook.erl
index b1f0e3d9a4..0907d554f4 100644
--- a/lib/wx/src/gen/wxListbook.erl
+++ b/lib/wx/src/gen/wxListbook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,27 +74,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxListbook/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxListbook()
+-type wxListbook() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookwxlistbook">external documentation</a>.
+-spec new() -> wxListbook().
new() ->
wxe_util:construct(?wxListbook_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxListbook()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxListbook() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxListbook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookwxlistbook">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxListbook() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,15 +113,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxListbook_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxListbook(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv addPage(This,Page,Text, [])
+-spec addPage(This, Page, Text) -> boolean() when
+ This::wxListbook(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
addPage(This,Page,Text)
when is_record(This, wx_ref),is_record(Page, wx_ref),is_list(Text) ->
addPage(This,Page,Text, []).
-%% @spec (This::wxListbook(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookaddpage">external documentation</a>.
+-spec addPage(This, Page, Text, [Option]) -> boolean() when
+ This::wxListbook(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxListbook),
@@ -127,15 +138,18 @@ addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Op
wxe_util:call(?wxListbook_AddPage,
<<ThisRef:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxListbook()) -> ok
%% @equiv advanceSelection(This, [])
+-spec advanceSelection(This) -> ok when
+ This::wxListbook().
+
advanceSelection(This)
when is_record(This, wx_ref) ->
advanceSelection(This, []).
-%% @spec (This::wxListbook(), [Option]) -> ok
-%% Option = {forward, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookadvanceselection">external documentation</a>.
+-spec advanceSelection(This, [Option]) -> ok when
+ This::wxListbook(),
+ Option :: {forward, boolean()}.
advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxListbook),
@@ -145,23 +159,29 @@ advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxListbook_AdvanceSelection,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxListbook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList) -> ok when
+ This::wxListbook(), ImageList::wxImageList:wxImageList().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxListbook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxListbook_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxListbook(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxListbook(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxListbook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxListbook(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxListbook),
@@ -174,98 +194,114 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxListbook_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxListbook()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookdeleteallpages">external documentation</a>.
+-spec deleteAllPages(This) -> boolean() when
+ This::wxListbook().
deleteAllPages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_DeleteAllPages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookdeletepage">external documentation</a>.
+-spec deletePage(This, N) -> boolean() when
+ This::wxListbook(), N::integer().
deletePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_DeletePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookremovepage">external documentation</a>.
+-spec removePage(This, N) -> boolean() when
+ This::wxListbook(), N::integer().
removePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_RemovePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetcurrentpage">external documentation</a>.
+-spec getCurrentPage(This) -> wxWindow:wxWindow() when
+ This::wxListbook().
getCurrentPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetCurrentPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListbook()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetimagelist">external documentation</a>.
+-spec getImageList(This) -> wxImageList:wxImageList() when
+ This::wxListbook().
getImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetpage">external documentation</a>.
+-spec getPage(This, N) -> wxWindow:wxWindow() when
+ This::wxListbook(), N::integer().
getPage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetPage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetpagecount">external documentation</a>.
+-spec getPageCount(This) -> integer() when
+ This::wxListbook().
getPageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetPageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetpageimage">external documentation</a>.
+-spec getPageImage(This, N) -> integer() when
+ This::wxListbook(), N::integer().
getPageImage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetPageImage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetpagetext">external documentation</a>.
+-spec getPageText(This, N) -> unicode:charlist() when
+ This::wxListbook(), N::integer().
getPageText(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetPageText,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxListbook().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxListbook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookhittest">external documentation</a>.
+-spec hitTest(This, Pt) -> Result when
+ Result ::{Res ::integer(), Flags::integer()},
+ This::wxListbook(), Pt::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_HitTest,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv insertPage(This,N,Page,Text, [])
+-spec insertPage(This, N, Page, Text) -> boolean() when
+ This::wxListbook(), N::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
insertPage(This,N,Page,Text)
when is_record(This, wx_ref),is_integer(N),is_record(Page, wx_ref),is_list(Text) ->
insertPage(This,N,Page,Text, []).
-%% @spec (This::wxListbook(), N::integer(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookinsertpage">external documentation</a>.
+-spec insertPage(This, N, Page, Text, [Option]) -> boolean() when
+ This::wxListbook(), N::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
insertPage(#wx_ref{type=ThisT,ref=ThisRef},N,#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_integer(N),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxListbook),
@@ -278,32 +314,36 @@ insertPage(#wx_ref{type=ThisT,ref=ThisRef},N,#wx_ref{type=PageT,ref=PageRef},Tex
wxe_util:call(?wxListbook_InsertPage,
<<ThisRef:32/?UI,N:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxListbook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbooksetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList) -> ok when
+ This::wxListbook(), ImageList::wxImageList:wxImageList().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxListbook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxListbook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxListbook(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbooksetpagesize">external documentation</a>.
+-spec setPageSize(This, Size) -> ok when
+ This::wxListbook(), Size::{W::integer(), H::integer()}.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxListbook),
wxe_util:cast(?wxListbook_SetPageSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer(), ImageId::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbooksetpageimage">external documentation</a>.
+-spec setPageImage(This, N, ImageId) -> boolean() when
+ This::wxListbook(), N::integer(), ImageId::integer().
setPageImage(#wx_ref{type=ThisT,ref=ThisRef},N,ImageId)
when is_integer(N),is_integer(ImageId) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_SetPageImage,
<<ThisRef:32/?UI,N:32/?UI,ImageId:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer(), StrText::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbooksetpagetext">external documentation</a>.
+-spec setPageText(This, N, StrText) -> boolean() when
+ This::wxListbook(), N::integer(), StrText::unicode:chardata().
setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
when is_integer(N),is_list(StrText) ->
?CLASS(ThisT,wxListbook),
@@ -311,24 +351,26 @@ setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
wxe_util:call(?wxListbook_SetPageText,
<<ThisRef:32/?UI,N:32/?UI,(byte_size(StrText_UC)):32/?UI,(StrText_UC)/binary, 0:(((8- ((4+byte_size(StrText_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxListbook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbooksetselection">external documentation</a>.
+-spec setSelection(This, N) -> integer() when
+ This::wxListbook(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_SetSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistbook.html#wxlistbookchangeselection">external documentation</a>.
+-spec changeSelection(This, N) -> integer() when
+ This::wxListbook(), N::integer().
changeSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxListbook),
wxe_util:call(?wxListbook_ChangeSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxListbook()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxListbook()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxListbook),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxLogNull.erl b/lib/wx/src/gen/wxLogNull.erl
index 676fdf6d85..0ac4e8f9a3 100644
--- a/lib/wx/src/gen/wxLogNull.erl
+++ b/lib/wx/src/gen/wxLogNull.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,19 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxLogNull/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxLogNull()
+-type wxLogNull() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlognull.html#wxlognullwxlognull">external documentation</a>.
+-spec new() -> wxLogNull().
new() ->
wxe_util:construct(?wxLogNull_new,
<<>>).
-%% @spec (This::wxLogNull()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxLogNull()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxLogNull),
wxe_util:destroy(?wxLogNull_destroy,Obj),
diff --git a/lib/wx/src/gen/wxMDIChildFrame.erl b/lib/wx/src/gen/wxMDIChildFrame.erl
index 34edac4213..861beba34f 100644
--- a/lib/wx/src/gen/wxMDIChildFrame.erl
+++ b/lib/wx/src/gen/wxMDIChildFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +80,7 @@
thaw/1,transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxMDIChildFrame/0]).
%% @hidden
parent_class(wxFrame) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -87,21 +88,27 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMDIChildFrame()
+-type wxMDIChildFrame() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframewxmdichildframe">external documentation</a>.
+-spec new() -> wxMDIChildFrame().
new() ->
wxe_util:construct(?wxMDIChildFrame_new_0,
<<>>).
-%% @spec (Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::string()) -> wxMDIChildFrame()
%% @equiv new(Parent,Id,Title, [])
+-spec new(Parent, Id, Title) -> wxMDIChildFrame() when
+ Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::unicode:chardata().
+
new(Parent,Id,Title)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
new(Parent,Id,Title, []).
-%% @spec (Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::string(), [Option]) -> wxMDIChildFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframewxmdichildframe">external documentation</a>.
+-spec new(Parent, Id, Title, [Option]) -> wxMDIChildFrame() when
+ Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ParentT,wxMDIParentFrame),
@@ -114,22 +121,28 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
wxe_util:construct(?wxMDIChildFrame_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMDIChildFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframeactivate">external documentation</a>.
+-spec activate(This) -> ok when
+ This::wxMDIChildFrame().
activate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIChildFrame),
wxe_util:cast(?wxMDIChildFrame_Activate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIChildFrame(), Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::string()) -> bool()
%% @equiv create(This,Parent,Id,Title, [])
+-spec create(This, Parent, Id, Title) -> boolean() when
+ This::wxMDIChildFrame(), Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::unicode:chardata().
+
create(This,Parent,Id,Title)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
create(This,Parent,Id,Title, []).
-%% @spec (This::wxMDIChildFrame(), Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframecreate">external documentation</a>.
+-spec create(This, Parent, Id, Title, [Option]) -> boolean() when
+ This::wxMDIChildFrame(), Parent::wxMDIParentFrame:wxMDIParentFrame(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ThisT,wxMDIChildFrame),
@@ -143,15 +156,18 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ti
wxe_util:call(?wxMDIChildFrame_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMDIChildFrame()) -> ok
%% @equiv maximize(This, [])
+-spec maximize(This) -> ok when
+ This::wxMDIChildFrame().
+
maximize(This)
when is_record(This, wx_ref) ->
maximize(This, []).
-%% @spec (This::wxMDIChildFrame(), [Option]) -> ok
-%% Option = {maximize, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframemaximize">external documentation</a>.
+-spec maximize(This, [Option]) -> ok when
+ This::wxMDIChildFrame(),
+ Option :: {maximize, boolean()}.
maximize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMDIChildFrame),
@@ -161,15 +177,16 @@ maximize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxMDIChildFrame_Maximize,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMDIChildFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdichildframe.html#wxmdichildframerestore">external documentation</a>.
+-spec restore(This) -> ok when
+ This::wxMDIChildFrame().
restore(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIChildFrame),
wxe_util:cast(?wxMDIChildFrame_Restore,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIChildFrame()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMDIChildFrame()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMDIChildFrame),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMDIClientWindow.erl b/lib/wx/src/gen/wxMDIClientWindow.erl
index 79a11b4eb7..344dcdbbaf 100644
--- a/lib/wx/src/gen/wxMDIClientWindow.erl
+++ b/lib/wx/src/gen/wxMDIClientWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +68,31 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxMDIClientWindow/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMDIClientWindow()
+-type wxMDIClientWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiclientwindow.html#wxmdiclientwindowwxmdiclientwindow">external documentation</a>.
+-spec new() -> wxMDIClientWindow().
new() ->
wxe_util:construct(?wxMDIClientWindow_new_0,
<<>>).
-%% @spec (Parent::wxMDIParentFrame:wxMDIParentFrame()) -> wxMDIClientWindow()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxMDIClientWindow() when
+ Parent::wxMDIParentFrame:wxMDIParentFrame().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxMDIParentFrame:wxMDIParentFrame(), [Option]) -> wxMDIClientWindow()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiclientwindow.html#wxmdiclientwindowwxmdiclientwindow">external documentation</a>.
+-spec new(Parent, [Option]) -> wxMDIClientWindow() when
+ Parent::wxMDIParentFrame:wxMDIParentFrame(),
+ Option :: {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxMDIParentFrame),
@@ -97,15 +102,18 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxMDIClientWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMDIClientWindow(), Parent::wxMDIParentFrame:wxMDIParentFrame()) -> bool()
%% @equiv createClient(This,Parent, [])
+-spec createClient(This, Parent) -> boolean() when
+ This::wxMDIClientWindow(), Parent::wxMDIParentFrame:wxMDIParentFrame().
+
createClient(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
createClient(This,Parent, []).
-%% @spec (This::wxMDIClientWindow(), Parent::wxMDIParentFrame:wxMDIParentFrame(), [Option]) -> bool()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiclientwindow.html#wxmdiclientwindowcreateclient">external documentation</a>.
+-spec createClient(This, Parent, [Option]) -> boolean() when
+ This::wxMDIClientWindow(), Parent::wxMDIParentFrame:wxMDIParentFrame(),
+ Option :: {style, integer()}.
createClient(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMDIClientWindow),
@@ -116,8 +124,8 @@ createClient(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}
wxe_util:call(?wxMDIClientWindow_CreateClient,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxMDIClientWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMDIClientWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMDIClientWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMDIParentFrame.erl b/lib/wx/src/gen/wxMDIParentFrame.erl
index db47e7ac74..1a7e7387b9 100644
--- a/lib/wx/src/gen/wxMDIParentFrame.erl
+++ b/lib/wx/src/gen/wxMDIParentFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -82,6 +82,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxMDIParentFrame/0]).
%% @hidden
parent_class(wxFrame) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -89,21 +90,27 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMDIParentFrame()
+-type wxMDIParentFrame() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframewxmdiparentframe">external documentation</a>.
+-spec new() -> wxMDIParentFrame().
new() ->
wxe_util:construct(?wxMDIParentFrame_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> wxMDIParentFrame()
%% @equiv new(Parent,Id,Title, [])
+-spec new(Parent, Id, Title) -> wxMDIParentFrame() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
new(Parent,Id,Title)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
new(Parent,Id,Title, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxMDIParentFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframewxmdiparentframe">external documentation</a>.
+-spec new(Parent, Id, Title, [Option]) -> wxMDIParentFrame() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -116,43 +123,52 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
wxe_util:construct(?wxMDIParentFrame_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMDIParentFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframeactivatenext">external documentation</a>.
+-spec activateNext(This) -> ok when
+ This::wxMDIParentFrame().
activateNext(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIParentFrame),
wxe_util:cast(?wxMDIParentFrame_ActivateNext,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIParentFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframeactivateprevious">external documentation</a>.
+-spec activatePrevious(This) -> ok when
+ This::wxMDIParentFrame().
activatePrevious(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIParentFrame),
wxe_util:cast(?wxMDIParentFrame_ActivatePrevious,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIParentFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframearrangeicons">external documentation</a>.
+-spec arrangeIcons(This) -> ok when
+ This::wxMDIParentFrame().
arrangeIcons(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIParentFrame),
wxe_util:cast(?wxMDIParentFrame_ArrangeIcons,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIParentFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframecascade">external documentation</a>.
+-spec cascade(This) -> ok when
+ This::wxMDIParentFrame().
cascade(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIParentFrame),
wxe_util:cast(?wxMDIParentFrame_Cascade,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIParentFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> bool()
%% @equiv create(This,Parent,Id,Title, [])
+-spec create(This, Parent, Id, Title) -> boolean() when
+ This::wxMDIParentFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
create(This,Parent,Id,Title)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
create(This,Parent,Id,Title, []).
-%% @spec (This::wxMDIParentFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframecreate">external documentation</a>.
+-spec create(This, Parent, Id, Title, [Option]) -> boolean() when
+ This::wxMDIParentFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ThisT,wxMDIParentFrame),
@@ -166,31 +182,35 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ti
wxe_util:call(?wxMDIParentFrame_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMDIParentFrame()) -> wxMDIChildFrame:wxMDIChildFrame()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframegetactivechild">external documentation</a>.
+-spec getActiveChild(This) -> wxMDIChildFrame:wxMDIChildFrame() when
+ This::wxMDIParentFrame().
getActiveChild(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIParentFrame),
wxe_util:call(?wxMDIParentFrame_GetActiveChild,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIParentFrame()) -> wxMDIClientWindow:wxMDIClientWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframegetclientwindow">external documentation</a>.
+-spec getClientWindow(This) -> wxMDIClientWindow:wxMDIClientWindow() when
+ This::wxMDIParentFrame().
getClientWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMDIParentFrame),
wxe_util:call(?wxMDIParentFrame_GetClientWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMDIParentFrame()) -> ok
%% @equiv tile(This, [])
+-spec tile(This) -> ok when
+ This::wxMDIParentFrame().
+
tile(This)
when is_record(This, wx_ref) ->
tile(This, []).
-%% @spec (This::wxMDIParentFrame(), [Option]) -> ok
-%% Option = {orient, WxOrientation}
-%% WxOrientation = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmdiparentframe.html#wxmdiparentframetile">external documentation</a>.
-%%<br /> WxOrientation is one of ?wxHORIZONTAL | ?wxVERTICAL | ?wxBOTH
+%%<br /> Orient = ?wxHORIZONTAL | ?wxVERTICAL | ?wxBOTH
+-spec tile(This, [Option]) -> ok when
+ This::wxMDIParentFrame(),
+ Option :: {orient, wx:wx_enum()}.
tile(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMDIParentFrame),
@@ -200,8 +220,8 @@ tile(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxMDIParentFrame_Tile,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMDIParentFrame()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMDIParentFrame()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMDIParentFrame),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMask.erl b/lib/wx/src/gen/wxMask.erl
index 3b5d3340ea..296c7cbc83 100644
--- a/lib/wx/src/gen/wxMask.erl
+++ b/lib/wx/src/gen/wxMask.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,31 +29,34 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxMask/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMask()
+-type wxMask() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmask.html#wxmaskwxmask">external documentation</a>.
+-spec new() -> wxMask().
new() ->
wxe_util:construct(?wxMask_new_0,
<<>>).
-%% @spec (Bitmap::wxBitmap:wxBitmap()) -> wxMask()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmask.html#wxmaskwxmask">external documentation</a>.
+-spec new(Bitmap) -> wxMask() when
+ Bitmap::wxBitmap:wxBitmap().
new(#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(BitmapT,wxBitmap),
wxe_util:construct(?wxMask_new_1,
<<BitmapRef:32/?UI>>).
-%% @spec (Bitmap::wxBitmap:wxBitmap(),X::integer()|term()) -> wxMask()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmask.html#wxmaskwxmask">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Bitmap::wxBitmap:wxBitmap(), PaletteIndex::integer()) -> wxMask() </c>
-%% </p>
-%% <p><c>
-%% new(Bitmap::wxBitmap:wxBitmap(), Colour::wx:colour()) -> wxMask() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Bitmap, Colour) -> wxMask() when<br />
+%% Bitmap::wxBitmap:wxBitmap(), Colour::wx:wx_colour().<br />
+%%
+-spec new(Bitmap, PaletteIndex) -> wxMask() when
+ Bitmap::wxBitmap:wxBitmap(), PaletteIndex::integer();
+ (Bitmap, Colour) -> wxMask() when
+ Bitmap::wxBitmap:wxBitmap(), Colour::wx:wx_colour().
new(#wx_ref{type=BitmapT,ref=BitmapRef},PaletteIndex)
when is_integer(PaletteIndex) ->
?CLASS(BitmapT,wxBitmap),
@@ -65,23 +68,24 @@ new(#wx_ref{type=BitmapT,ref=BitmapRef},Colour)
wxe_util:construct(?wxMask_new_2_1,
<<BitmapRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxMask(), Bitmap::wxBitmap:wxBitmap()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmask.html#wxmaskcreate">external documentation</a>.
+-spec create(This, Bitmap) -> boolean() when
+ This::wxMask(), Bitmap::wxBitmap:wxBitmap().
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(ThisT,wxMask),
?CLASS(BitmapT,wxBitmap),
wxe_util:call(?wxMask_Create_1,
<<ThisRef:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxMask(),Bitmap::wxBitmap:wxBitmap(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmask.html#wxmaskcreate">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% create(This::wxMask(), Bitmap::wxBitmap:wxBitmap(), PaletteIndex::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% create(This::wxMask(), Bitmap::wxBitmap:wxBitmap(), Colour::wx:colour()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% create(This, Bitmap, Colour) -> boolean() when<br />
+%% This::wxMask(), Bitmap::wxBitmap:wxBitmap(), Colour::wx:wx_colour().<br />
+%%
+-spec create(This, Bitmap, PaletteIndex) -> boolean() when
+ This::wxMask(), Bitmap::wxBitmap:wxBitmap(), PaletteIndex::integer();
+ (This, Bitmap, Colour) -> boolean() when
+ This::wxMask(), Bitmap::wxBitmap:wxBitmap(), Colour::wx:wx_colour().
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef},PaletteIndex)
when is_integer(PaletteIndex) ->
?CLASS(ThisT,wxMask),
@@ -95,8 +99,8 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef},Colou
wxe_util:call(?wxMask_Create_2_1,
<<ThisRef:32/?UI,BitmapRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxMask()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMask()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMask),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMaximizeEvent.erl b/lib/wx/src/gen/wxMaximizeEvent.erl
index 6dd371908b..5f7b7e890d 100644
--- a/lib/wx/src/gen/wxMaximizeEvent.erl
+++ b/lib/wx/src/gen/wxMaximizeEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,12 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxMaximizeEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxMaximizeEvent() :: wx:wx_object().
%% From wxEvent
%% @hidden
stopPropagation(This) -> wxEvent:stopPropagation(This).
diff --git a/lib/wx/src/gen/wxMemoryDC.erl b/lib/wx/src/gen/wxMemoryDC.erl
index d17ebba4b7..cac20094a0 100644
--- a/lib/wx/src/gen/wxMemoryDC.erl
+++ b/lib/wx/src/gen/wxMemoryDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +38,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -52,18 +52,21 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxMemoryDC/0]).
%% @hidden
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMemoryDC()
+-type wxMemoryDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmemorydc.html#wxmemorydcwxmemorydc">external documentation</a>.
+-spec new() -> wxMemoryDC().
new() ->
wxe_util:construct(?wxMemoryDC_new_0,
<<>>).
-%% @spec (Dc::wxDC:wxDC() | wxBitmap:wxBitmap()) -> wxMemoryDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmemorydc.html#wxmemorydcwxmemorydc">external documentation</a>.
+-spec new(Dc) -> wxMemoryDC() when
+ Dc::wxDC:wxDC() | wxBitmap:wxBitmap().
new(#wx_ref{type=DcT,ref=DcRef}) ->
DcOP = case ?CLASS_T(DcT,wxDC) of
true ->
@@ -74,24 +77,26 @@ new(#wx_ref{type=DcT,ref=DcRef}) ->
wxe_util:construct(DcOP,
<<DcRef:32/?UI>>).
-%% @spec (This::wxMemoryDC(), Bmp::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmemorydc.html#wxmemorydcselectobject">external documentation</a>.
+-spec selectObject(This, Bmp) -> ok when
+ This::wxMemoryDC(), Bmp::wxBitmap:wxBitmap().
selectObject(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef}) ->
?CLASS(ThisT,wxMemoryDC),
?CLASS(BmpT,wxBitmap),
wxe_util:cast(?wxMemoryDC_SelectObject,
<<ThisRef:32/?UI,BmpRef:32/?UI>>).
-%% @spec (This::wxMemoryDC(), Bmp::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmemorydc.html#wxmemorydcselectobjectassource">external documentation</a>.
+-spec selectObjectAsSource(This, Bmp) -> ok when
+ This::wxMemoryDC(), Bmp::wxBitmap:wxBitmap().
selectObjectAsSource(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef}) ->
?CLASS(ThisT,wxMemoryDC),
?CLASS(BmpT,wxBitmap),
wxe_util:cast(?wxMemoryDC_SelectObjectAsSource,
<<ThisRef:32/?UI,BmpRef:32/?UI>>).
-%% @spec (This::wxMemoryDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMemoryDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMemoryDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -178,11 +183,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -196,7 +201,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxMenu.erl b/lib/wx/src/gen/wxMenu.erl
index 615a845d11..d91863de82 100644
--- a/lib/wx/src/gen/wxMenu.erl
+++ b/lib/wx/src/gen/wxMenu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +40,21 @@
%% inherited exports
-export([connect/2,connect/3,disconnect/1,disconnect/2,disconnect/3,parent_class/1]).
+-export_type([wxMenu/0]).
%% @hidden
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMenu()
+-type wxMenu() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxMenu().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxMenu()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuwxmenu">external documentation</a>.
+-spec new([Option]) -> wxMenu() when
+ Option :: {style, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({style, Style}, Acc) -> [<<1:32/?UI,Style:32/?UI>>|Acc];
@@ -60,9 +63,10 @@ new(Options)
wxe_util:construct(?wxMenu_new_1,
<<BinOpt/binary>>).
-%% @spec (Title::string(), [Option]) -> wxMenu()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuwxmenu">external documentation</a>.
+-spec new(Title, [Option]) -> wxMenu() when
+ Title::unicode:chardata(),
+ Option :: {style, integer()}.
new(Title, Options)
when is_list(Title),is_list(Options) ->
Title_UC = unicode:characters_to_binary([Title,0]),
@@ -72,31 +76,37 @@ new(Title, Options)
wxe_util:construct(?wxMenu_new_2,
<<(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu(), Item::wxMenuItem:wxMenuItem()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuappend">external documentation</a>.
+-spec append(This, Item) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Item::wxMenuItem:wxMenuItem().
append(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
?CLASS(ThisT,wxMenu),
?CLASS(ItemT,wxMenuItem),
wxe_util:call(?wxMenu_Append_1,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv append(This,Itemid,Text, [])
+-spec append(This, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata().
+
append(This,Itemid,Text)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text) ->
append(This,Itemid,Text, []).
-%% @spec (This::wxMenu(),Itemid::integer(),Text::string(),X::wxMenu()|term()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuappend">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% append(This::wxMenu(), Itemid::integer(), Text::string(), Submenu::wxMenu()) -> append(This,Itemid,Text,Submenu, []) </c></p>
-%% <p><c>
-%% append(This::wxMenu(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem() </c>
-%%<br /> Option = {help, string()} | {kind, WxItemKind}
-%%<br /> WxItemKind = integer()
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
-%% </p>
+%% <br /> Also:<br />
+%% append(This, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Itemid::integer(), Text::unicode:chardata(),<br />
+%% Option :: {help, unicode:chardata()}<br />
+%% | {kind, wx:wx_enum()}.<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec append(This, Itemid, Text, Submenu) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu();
+ (This, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}
+ | {kind, wx:wx_enum()}.
append(This,Itemid,Text,Submenu)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text),is_record(Submenu, wx_ref) ->
@@ -112,16 +122,17 @@ append(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
wxe_util:call(?wxMenu_Append_3,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu(),Itemid::integer(),Text::string(),X::string()|wxMenu(),X::bool()|term()) -> ok|wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuappend">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% append(This::wxMenu(), Itemid::integer(), Text::string(), Help::string(), IsCheckable::bool()) -> ok </c>
-%% </p>
-%% <p><c>
-%% append(This::wxMenu(), Itemid::integer(), Text::string(), Submenu::wxMenu(), [Option]) -> wxMenuItem:wxMenuItem() </c>
-%%<br /> Option = {help, string()}
-%% </p>
+%% <br /> Also:<br />
+%% append(This, Itemid, Text, Submenu, [Option]) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu(),<br />
+%% Option :: {help, unicode:chardata()}.<br />
+%%
+-spec append(This, Itemid, Text, Help, IsCheckable) -> ok when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Help::unicode:chardata(), IsCheckable::boolean();
+ (This, Itemid, Text, Submenu, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu(),
+ Option :: {help, unicode:chardata()}.
append(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text,Help,IsCheckable)
when is_integer(Itemid),is_list(Text),is_list(Help),is_boolean(IsCheckable) ->
?CLASS(ThisT,wxMenu),
@@ -140,15 +151,18 @@ append(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text,#wx_ref{type=SubmenuT,ref=Sub
wxe_util:call(?wxMenu_Append_4_1,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,SubmenuRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv appendCheckItem(This,Itemid,Text, [])
+-spec appendCheckItem(This, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata().
+
appendCheckItem(This,Itemid,Text)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text) ->
appendCheckItem(This,Itemid,Text, []).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {help, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuappendcheckitem">external documentation</a>.
+-spec appendCheckItem(This, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}.
appendCheckItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
when is_integer(Itemid),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -159,15 +173,18 @@ appendCheckItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
wxe_util:call(?wxMenu_AppendCheckItem,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv appendRadioItem(This,Itemid,Text, [])
+-spec appendRadioItem(This, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata().
+
appendRadioItem(This,Itemid,Text)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text) ->
appendRadioItem(This,Itemid,Text, []).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {help, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuappendradioitem">external documentation</a>.
+-spec appendRadioItem(This, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}.
appendRadioItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
when is_integer(Itemid),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -178,37 +195,40 @@ appendRadioItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
wxe_util:call(?wxMenu_AppendRadioItem,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuappendseparator">external documentation</a>.
+-spec appendSeparator(This) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu().
appendSeparator(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_AppendSeparator,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenu()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenubreak">external documentation</a>.
+-spec break(This) -> ok when
+ This::wxMenu().
break(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenu),
wxe_util:cast(?wxMenu_Break,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Check::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenucheck">external documentation</a>.
+-spec check(This, Itemid, Check) -> ok when
+ This::wxMenu(), Itemid::integer(), Check::boolean().
check(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Check)
when is_integer(Itemid),is_boolean(Check) ->
?CLASS(ThisT,wxMenu),
wxe_util:cast(?wxMenu_Check,
<<ThisRef:32/?UI,Itemid:32/?UI,(wxe_util:from_bool(Check)):32/?UI>>).
-%% @spec (This::wxMenu(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenudelete">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% delete(This::wxMenu(), Itemid::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% delete(This::wxMenu(), Item::wxMenuItem:wxMenuItem()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% delete(This, Item) -> boolean() when<br />
+%% This::wxMenu(), Item::wxMenuItem:wxMenuItem().<br />
+%%
+-spec delete(This, Itemid) -> boolean() when
+ This::wxMenu(), Itemid::integer();
+ (This, Item) -> boolean() when
+ This::wxMenu(), Item::wxMenuItem:wxMenuItem().
delete(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
@@ -220,15 +240,15 @@ delete(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
wxe_util:call(?wxMenu_Delete_1_1,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxMenu(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenudestroy">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% 'Destroy'(This::wxMenu(), Itemid::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% 'Destroy'(This::wxMenu(), Item::wxMenuItem:wxMenuItem()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% 'Destroy'(This, Item) -> boolean() when<br />
+%% This::wxMenu(), Item::wxMenuItem:wxMenuItem().<br />
+%%
+-spec 'Destroy'(This, Itemid) -> boolean() when
+ This::wxMenu(), Itemid::integer();
+ (This, Item) -> boolean() when
+ This::wxMenu(), Item::wxMenuItem:wxMenuItem().
'Destroy'(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
@@ -240,23 +260,24 @@ delete(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
wxe_util:call(?wxMenu_Destroy_1_1,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Enable::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuenable">external documentation</a>.
+-spec enable(This, Itemid, Enable) -> ok when
+ This::wxMenu(), Itemid::integer(), Enable::boolean().
enable(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Enable)
when is_integer(Itemid),is_boolean(Enable) ->
?CLASS(ThisT,wxMenu),
wxe_util:cast(?wxMenu_Enable,
<<ThisRef:32/?UI,Itemid:32/?UI,(wxe_util:from_bool(Enable)):32/?UI>>).
-%% @spec (This::wxMenu(),X::integer()|string()) -> wxMenuItem:wxMenuItem()|integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenufinditem">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% findItem(This::wxMenu(), Itemid::integer()) -> wxMenuItem:wxMenuItem() </c>
-%% </p>
-%% <p><c>
-%% findItem(This::wxMenu(), Item::string()) -> integer() </c>
-%% </p>
+%% <br /> Also:<br />
+%% findItem(This, Item) -> integer() when<br />
+%% This::wxMenu(), Item::unicode:chardata().<br />
+%%
+-spec findItem(This, Itemid) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer();
+ (This, Item) -> integer() when
+ This::wxMenu(), Item::unicode:chardata().
findItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
@@ -269,59 +290,67 @@ findItem(#wx_ref{type=ThisT,ref=ThisRef},Item)
wxe_util:call(?wxMenu_FindItem_1,
<<ThisRef:32/?UI,(byte_size(Item_UC)):32/?UI,(Item_UC)/binary, 0:(((8- ((0+byte_size(Item_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenu(), Position::integer()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenufinditembyposition">external documentation</a>.
+-spec findItemByPosition(This, Position) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Position::integer().
findItemByPosition(#wx_ref{type=ThisT,ref=ThisRef},Position)
when is_integer(Position) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_FindItemByPosition,
<<ThisRef:32/?UI,Position:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenugethelpstring">external documentation</a>.
+-spec getHelpString(This, Itemid) -> unicode:charlist() when
+ This::wxMenu(), Itemid::integer().
getHelpString(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_GetHelpString,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenugetlabel">external documentation</a>.
+-spec getLabel(This, Itemid) -> unicode:charlist() when
+ This::wxMenu(), Itemid::integer().
getLabel(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_GetLabel,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenu()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenugetmenuitemcount">external documentation</a>.
+-spec getMenuItemCount(This) -> integer() when
+ This::wxMenu().
getMenuItemCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_GetMenuItemCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenu()) -> [wxMenuItem:wxMenuItem()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenugetmenuitems">external documentation</a>.
+-spec getMenuItems(This) -> [wxMenuItem:wxMenuItem()] when
+ This::wxMenu().
getMenuItems(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_GetMenuItems,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenu()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenugettitle">external documentation</a>.
+-spec getTitle(This) -> unicode:charlist() when
+ This::wxMenu().
getTitle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_GetTitle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenu(),Pos::integer(),X::integer()|term()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuinsert">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insert(This::wxMenu(), Pos::integer(), Itemid::integer()) -> insert(This,Pos,Itemid, []) </c></p>
-%% <p><c>
-%% insert(This::wxMenu(), Pos::integer(), Item::wxMenuItem:wxMenuItem()) -> wxMenuItem:wxMenuItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% insert(This, Pos, Item) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Pos::integer(), Item::wxMenuItem:wxMenuItem().<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec insert(This, Pos, Itemid) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer();
+ (This, Pos, Item) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Item::wxMenuItem:wxMenuItem().
insert(This,Pos,Itemid)
when is_record(This, wx_ref),is_integer(Pos),is_integer(Itemid) ->
@@ -333,11 +362,13 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=ItemT,ref=ItemRef})
wxe_util:call(?wxMenu_Insert_2,
<<ThisRef:32/?UI,Pos:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxMenu(), Pos::integer(), Itemid::integer(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {text, string()} | {help, string()} | {kind, WxItemKind}
-%% WxItemKind = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuinsert">external documentation</a>.
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec insert(This, Pos, Itemid, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(),
+ Option :: {text, unicode:chardata()}
+ | {help, unicode:chardata()}
+ | {kind, wx:wx_enum()}.
insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid, Options)
when is_integer(Pos),is_integer(Itemid),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -349,22 +380,25 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid, Options)
wxe_util:call(?wxMenu_Insert_3,
<<ThisRef:32/?UI,Pos:32/?UI,Itemid:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string(), Submenu::wxMenu()) -> wxMenuItem:wxMenuItem()
%% @equiv insert(This,Pos,Itemid,Text,Submenu, [])
+-spec insert(This, Pos, Itemid, Text, Submenu) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu().
+
insert(This,Pos,Itemid,Text,Submenu)
when is_record(This, wx_ref),is_integer(Pos),is_integer(Itemid),is_list(Text),is_record(Submenu, wx_ref) ->
insert(This,Pos,Itemid,Text,Submenu, []).
-%% @spec (This::wxMenu(),Pos::integer(),Itemid::integer(),Text::string(),X::string()|wxMenu(),X::bool()|term()) -> ok|wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuinsert">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insert(This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string(), Help::string(), IsCheckable::bool()) -> ok </c>
-%% </p>
-%% <p><c>
-%% insert(This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string(), Submenu::wxMenu(), [Option]) -> wxMenuItem:wxMenuItem() </c>
-%%<br /> Option = {help, string()}
-%% </p>
+%% <br /> Also:<br />
+%% insert(This, Pos, Itemid, Text, Submenu, [Option]) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu(),<br />
+%% Option :: {help, unicode:chardata()}.<br />
+%%
+-spec insert(This, Pos, Itemid, Text, Help, IsCheckable) -> ok when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata(), Help::unicode:chardata(), IsCheckable::boolean();
+ (This, Pos, Itemid, Text, Submenu, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu(),
+ Option :: {help, unicode:chardata()}.
insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid,Text,Help,IsCheckable)
when is_integer(Pos),is_integer(Itemid),is_list(Text),is_list(Help),is_boolean(IsCheckable) ->
?CLASS(ThisT,wxMenu),
@@ -383,15 +417,18 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid,Text,#wx_ref{type=SubmenuT,ref
wxe_util:call(?wxMenu_Insert_5_1,
<<ThisRef:32/?UI,Pos:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,SubmenuRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv insertCheckItem(This,Pos,Itemid,Text, [])
+-spec insertCheckItem(This, Pos, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata().
+
insertCheckItem(This,Pos,Itemid,Text)
when is_record(This, wx_ref),is_integer(Pos),is_integer(Itemid),is_list(Text) ->
insertCheckItem(This,Pos,Itemid,Text, []).
-%% @spec (This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {help, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuinsertcheckitem">external documentation</a>.
+-spec insertCheckItem(This, Pos, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}.
insertCheckItem(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid,Text, Options)
when is_integer(Pos),is_integer(Itemid),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -402,15 +439,18 @@ insertCheckItem(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid,Text, Options)
wxe_util:call(?wxMenu_InsertCheckItem,
<<ThisRef:32/?UI,Pos:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv insertRadioItem(This,Pos,Itemid,Text, [])
+-spec insertRadioItem(This, Pos, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata().
+
insertRadioItem(This,Pos,Itemid,Text)
when is_record(This, wx_ref),is_integer(Pos),is_integer(Itemid),is_list(Text) ->
insertRadioItem(This,Pos,Itemid,Text, []).
-%% @spec (This::wxMenu(), Pos::integer(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {help, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuinsertradioitem">external documentation</a>.
+-spec insertRadioItem(This, Pos, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}.
insertRadioItem(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid,Text, Options)
when is_integer(Pos),is_integer(Itemid),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -421,38 +461,43 @@ insertRadioItem(#wx_ref{type=ThisT,ref=ThisRef},Pos,Itemid,Text, Options)
wxe_util:call(?wxMenu_InsertRadioItem,
<<ThisRef:32/?UI,Pos:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu(), Pos::integer()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuinsertseparator">external documentation</a>.
+-spec insertSeparator(This, Pos) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Pos::integer().
insertSeparator(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_InsertSeparator,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuischecked">external documentation</a>.
+-spec isChecked(This, Itemid) -> boolean() when
+ This::wxMenu(), Itemid::integer().
isChecked(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_IsChecked,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuisenabled">external documentation</a>.
+-spec isEnabled(This, Itemid) -> boolean() when
+ This::wxMenu(), Itemid::integer().
isEnabled(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_IsEnabled,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenu(),X::integer()|term()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuprepend">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% prepend(This::wxMenu(), Itemid::integer()) -> prepend(This,Itemid, []) </c></p>
-%% <p><c>
-%% prepend(This::wxMenu(), Item::wxMenuItem:wxMenuItem()) -> wxMenuItem:wxMenuItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% prepend(This, Item) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Item::wxMenuItem:wxMenuItem().<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec prepend(This, Itemid) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer();
+ (This, Item) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Item::wxMenuItem:wxMenuItem().
prepend(This,Itemid)
when is_record(This, wx_ref),is_integer(Itemid) ->
@@ -463,11 +508,13 @@ prepend(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
wxe_util:call(?wxMenu_Prepend_1,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {text, string()} | {help, string()} | {kind, WxItemKind}
-%% WxItemKind = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuprepend">external documentation</a>.
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec prepend(This, Itemid, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(),
+ Option :: {text, unicode:chardata()}
+ | {help, unicode:chardata()}
+ | {kind, wx:wx_enum()}.
prepend(#wx_ref{type=ThisT,ref=ThisRef},Itemid, Options)
when is_integer(Itemid),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -479,22 +526,25 @@ prepend(#wx_ref{type=ThisT,ref=ThisRef},Itemid, Options)
wxe_util:call(?wxMenu_Prepend_2,
<<ThisRef:32/?UI,Itemid:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string(), Submenu::wxMenu()) -> wxMenuItem:wxMenuItem()
%% @equiv prepend(This,Itemid,Text,Submenu, [])
+-spec prepend(This, Itemid, Text, Submenu) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu().
+
prepend(This,Itemid,Text,Submenu)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text),is_record(Submenu, wx_ref) ->
prepend(This,Itemid,Text,Submenu, []).
-%% @spec (This::wxMenu(),Itemid::integer(),Text::string(),X::string()|wxMenu(),X::bool()|term()) -> ok|wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuprepend">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% prepend(This::wxMenu(), Itemid::integer(), Text::string(), Help::string(), IsCheckable::bool()) -> ok </c>
-%% </p>
-%% <p><c>
-%% prepend(This::wxMenu(), Itemid::integer(), Text::string(), Submenu::wxMenu(), [Option]) -> wxMenuItem:wxMenuItem() </c>
-%%<br /> Option = {help, string()}
-%% </p>
+%% <br /> Also:<br />
+%% prepend(This, Itemid, Text, Submenu, [Option]) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu(),<br />
+%% Option :: {help, unicode:chardata()}.<br />
+%%
+-spec prepend(This, Itemid, Text, Help, IsCheckable) -> ok when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Help::unicode:chardata(), IsCheckable::boolean();
+ (This, Itemid, Text, Submenu, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(), Submenu::wxMenu(),
+ Option :: {help, unicode:chardata()}.
prepend(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text,Help,IsCheckable)
when is_integer(Itemid),is_list(Text),is_list(Help),is_boolean(IsCheckable) ->
?CLASS(ThisT,wxMenu),
@@ -513,15 +563,18 @@ prepend(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text,#wx_ref{type=SubmenuT,ref=Su
wxe_util:call(?wxMenu_Prepend_4_1,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8,SubmenuRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv prependCheckItem(This,Itemid,Text, [])
+-spec prependCheckItem(This, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata().
+
prependCheckItem(This,Itemid,Text)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text) ->
prependCheckItem(This,Itemid,Text, []).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {help, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuprependcheckitem">external documentation</a>.
+-spec prependCheckItem(This, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}.
prependCheckItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
when is_integer(Itemid),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -532,15 +585,18 @@ prependCheckItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
wxe_util:call(?wxMenu_PrependCheckItem,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string()) -> wxMenuItem:wxMenuItem()
%% @equiv prependRadioItem(This,Itemid,Text, [])
+-spec prependRadioItem(This, Itemid, Text) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata().
+
prependRadioItem(This,Itemid,Text)
when is_record(This, wx_ref),is_integer(Itemid),is_list(Text) ->
prependRadioItem(This,Itemid,Text, []).
-%% @spec (This::wxMenu(), Itemid::integer(), Text::string(), [Option]) -> wxMenuItem:wxMenuItem()
-%% Option = {help, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuprependradioitem">external documentation</a>.
+-spec prependRadioItem(This, Itemid, Text, [Option]) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer(), Text::unicode:chardata(),
+ Option :: {help, unicode:chardata()}.
prependRadioItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
when is_integer(Itemid),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxMenu),
@@ -551,22 +607,23 @@ prependRadioItem(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Text, Options)
wxe_util:call(?wxMenu_PrependRadioItem,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMenu()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuprependseparator">external documentation</a>.
+-spec prependSeparator(This) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu().
prependSeparator(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenu),
wxe_util:call(?wxMenu_PrependSeparator,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenu(),X::integer()|term()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenuremove">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% remove(This::wxMenu(), Itemid::integer()) -> wxMenuItem:wxMenuItem() </c>
-%% </p>
-%% <p><c>
-%% remove(This::wxMenu(), Item::wxMenuItem:wxMenuItem()) -> wxMenuItem:wxMenuItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% remove(This, Item) -> wxMenuItem:wxMenuItem() when<br />
+%% This::wxMenu(), Item::wxMenuItem:wxMenuItem().<br />
+%%
+-spec remove(This, Itemid) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Itemid::integer();
+ (This, Item) -> wxMenuItem:wxMenuItem() when
+ This::wxMenu(), Item::wxMenuItem:wxMenuItem().
remove(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenu),
@@ -578,8 +635,9 @@ remove(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
wxe_util:call(?wxMenu_Remove_1_1,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxMenu(), Itemid::integer(), HelpString::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenusethelpstring">external documentation</a>.
+-spec setHelpString(This, Itemid, HelpString) -> ok when
+ This::wxMenu(), Itemid::integer(), HelpString::unicode:chardata().
setHelpString(#wx_ref{type=ThisT,ref=ThisRef},Itemid,HelpString)
when is_integer(Itemid),is_list(HelpString) ->
?CLASS(ThisT,wxMenu),
@@ -587,8 +645,9 @@ setHelpString(#wx_ref{type=ThisT,ref=ThisRef},Itemid,HelpString)
wxe_util:cast(?wxMenu_SetHelpString,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(HelpString_UC)):32/?UI,(HelpString_UC)/binary, 0:(((8- ((4+byte_size(HelpString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenu(), Itemid::integer(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenusetlabel">external documentation</a>.
+-spec setLabel(This, Itemid, Label) -> ok when
+ This::wxMenu(), Itemid::integer(), Label::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Label)
when is_integer(Itemid),is_list(Label) ->
?CLASS(ThisT,wxMenu),
@@ -596,8 +655,9 @@ setLabel(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Label)
wxe_util:cast(?wxMenu_SetLabel,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenu(), Title::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenu.html#wxmenusettitle">external documentation</a>.
+-spec setTitle(This, Title) -> ok when
+ This::wxMenu(), Title::unicode:chardata().
setTitle(#wx_ref{type=ThisT,ref=ThisRef},Title)
when is_list(Title) ->
?CLASS(ThisT,wxMenu),
@@ -605,8 +665,8 @@ setTitle(#wx_ref{type=ThisT,ref=ThisRef},Title)
wxe_util:cast(?wxMenu_SetTitle,
<<ThisRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenu()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMenu()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMenu),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMenuBar.erl b/lib/wx/src/gen/wxMenuBar.erl
index 4ed1b2cbe6..b0253292bd 100644
--- a/lib/wx/src/gen/wxMenuBar.erl
+++ b/lib/wx/src/gen/wxMenuBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +72,30 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxMenuBar/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMenuBar()
+-type wxMenuBar() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarwxmenubar">external documentation</a>.
+-spec new() -> wxMenuBar().
new() ->
wxe_util:construct(?wxMenuBar_new_0,
<<>>).
-%% @spec (Style::integer()) -> wxMenuBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarwxmenubar">external documentation</a>.
+-spec new(Style) -> wxMenuBar() when
+ Style::integer().
new(Style)
when is_integer(Style) ->
wxe_util:construct(?wxMenuBar_new_1,
<<Style:32/?UI>>).
-%% @spec (This::wxMenuBar(), Menu::wxMenu:wxMenu(), Title::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarappend">external documentation</a>.
+-spec append(This, Menu, Title) -> boolean() when
+ This::wxMenuBar(), Menu::wxMenu:wxMenu(), Title::unicode:chardata().
append(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef},Title)
when is_list(Title) ->
?CLASS(ThisT,wxMenuBar),
@@ -100,23 +104,27 @@ append(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef},Title)
wxe_util:call(?wxMenuBar_Append,
<<ThisRef:32/?UI,MenuRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), Itemid::integer(), Check::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarcheck">external documentation</a>.
+-spec check(This, Itemid, Check) -> ok when
+ This::wxMenuBar(), Itemid::integer(), Check::boolean().
check(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Check)
when is_integer(Itemid),is_boolean(Check) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:cast(?wxMenuBar_Check,
<<ThisRef:32/?UI,Itemid:32/?UI,(wxe_util:from_bool(Check)):32/?UI>>).
-%% @spec (This::wxMenuBar()) -> bool()
%% @equiv enable(This, [])
+-spec enable(This) -> boolean() when
+ This::wxMenuBar().
+
enable(This)
when is_record(This, wx_ref) ->
enable(This, []).
-%% @spec (This::wxMenuBar(), [Option]) -> bool()
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarenable">external documentation</a>.
+-spec enable(This, [Option]) -> boolean() when
+ This::wxMenuBar(),
+ Option :: {enable, boolean()}.
enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMenuBar),
@@ -126,24 +134,27 @@ enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxMenuBar_Enable_1,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenuBar(), Itemid::integer(), Enable::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarenable">external documentation</a>.
+-spec enable(This, Itemid, Enable) -> ok when
+ This::wxMenuBar(), Itemid::integer(), Enable::boolean().
enable(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Enable)
when is_integer(Itemid),is_boolean(Enable) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:cast(?wxMenuBar_Enable_2,
<<ThisRef:32/?UI,Itemid:32/?UI,(wxe_util:from_bool(Enable)):32/?UI>>).
-%% @spec (This::wxMenuBar(), Pos::integer(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarenabletop">external documentation</a>.
+-spec enableTop(This, Pos, Flag) -> ok when
+ This::wxMenuBar(), Pos::integer(), Flag::boolean().
enableTop(#wx_ref{type=ThisT,ref=ThisRef},Pos,Flag)
when is_integer(Pos),is_boolean(Flag) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:cast(?wxMenuBar_EnableTop,
<<ThisRef:32/?UI,Pos:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxMenuBar(), Title::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarfindmenu">external documentation</a>.
+-spec findMenu(This, Title) -> integer() when
+ This::wxMenuBar(), Title::unicode:chardata().
findMenu(#wx_ref{type=ThisT,ref=ThisRef},Title)
when is_list(Title) ->
?CLASS(ThisT,wxMenuBar),
@@ -151,8 +162,9 @@ findMenu(#wx_ref{type=ThisT,ref=ThisRef},Title)
wxe_util:call(?wxMenuBar_FindMenu,
<<ThisRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), MenuString::string(), ItemString::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarfindmenuitem">external documentation</a>.
+-spec findMenuItem(This, MenuString, ItemString) -> integer() when
+ This::wxMenuBar(), MenuString::unicode:chardata(), ItemString::unicode:chardata().
findMenuItem(#wx_ref{type=ThisT,ref=ThisRef},MenuString,ItemString)
when is_list(MenuString),is_list(ItemString) ->
?CLASS(ThisT,wxMenuBar),
@@ -161,62 +173,70 @@ findMenuItem(#wx_ref{type=ThisT,ref=ThisRef},MenuString,ItemString)
wxe_util:call(?wxMenuBar_FindMenuItem,
<<ThisRef:32/?UI,(byte_size(MenuString_UC)):32/?UI,(MenuString_UC)/binary, 0:(((8- ((0+byte_size(MenuString_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(ItemString_UC)):32/?UI,(ItemString_UC)/binary, 0:(((8- ((4+byte_size(ItemString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), Id::integer()) -> wxMenuItem:wxMenuItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarfinditem">external documentation</a>.
+-spec findItem(This, Id) -> wxMenuItem:wxMenuItem() when
+ This::wxMenuBar(), Id::integer().
findItem(#wx_ref{type=ThisT,ref=ThisRef},Id)
when is_integer(Id) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_FindItem,
<<ThisRef:32/?UI,Id:32/?UI>>).
-%% @spec (This::wxMenuBar(), Itemid::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubargethelpstring">external documentation</a>.
+-spec getHelpString(This, Itemid) -> unicode:charlist() when
+ This::wxMenuBar(), Itemid::integer().
getHelpString(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_GetHelpString,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenuBar()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubargetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxMenuBar().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_GetLabel_0,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuBar(), Itemid::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubargetlabel">external documentation</a>.
+-spec getLabel(This, Itemid) -> unicode:charlist() when
+ This::wxMenuBar(), Itemid::integer().
getLabel(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_GetLabel_1,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenuBar(), Pos::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubargetlabeltop">external documentation</a>.
+-spec getLabelTop(This, Pos) -> unicode:charlist() when
+ This::wxMenuBar(), Pos::integer().
getLabelTop(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_GetLabelTop,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxMenuBar(), Pos::integer()) -> wxMenu:wxMenu()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubargetmenu">external documentation</a>.
+-spec getMenu(This, Pos) -> wxMenu:wxMenu() when
+ This::wxMenuBar(), Pos::integer().
getMenu(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_GetMenu,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxMenuBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubargetmenucount">external documentation</a>.
+-spec getMenuCount(This) -> integer() when
+ This::wxMenuBar().
getMenuCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_GetMenuCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuBar(), Pos::integer(), Menu::wxMenu:wxMenu(), Title::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarinsert">external documentation</a>.
+-spec insert(This, Pos, Menu, Title) -> boolean() when
+ This::wxMenuBar(), Pos::integer(), Menu::wxMenu:wxMenu(), Title::unicode:chardata().
insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=MenuT,ref=MenuRef},Title)
when is_integer(Pos),is_list(Title) ->
?CLASS(ThisT,wxMenuBar),
@@ -225,39 +245,44 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=MenuT,ref=MenuRef},Title
wxe_util:call(?wxMenuBar_Insert,
<<ThisRef:32/?UI,Pos:32/?UI,MenuRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), Itemid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarischecked">external documentation</a>.
+-spec isChecked(This, Itemid) -> boolean() when
+ This::wxMenuBar(), Itemid::integer().
isChecked(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_IsChecked,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenuBar()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarisenabled">external documentation</a>.
+-spec isEnabled(This) -> boolean() when
+ This::wxMenuBar().
isEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_IsEnabled_0,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuBar(), Itemid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarisenabled">external documentation</a>.
+-spec isEnabled(This, Itemid) -> boolean() when
+ This::wxMenuBar(), Itemid::integer().
isEnabled(#wx_ref{type=ThisT,ref=ThisRef},Itemid)
when is_integer(Itemid) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_IsEnabled_1,
<<ThisRef:32/?UI,Itemid:32/?UI>>).
-%% @spec (This::wxMenuBar(), Pos::integer()) -> wxMenu:wxMenu()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarremove">external documentation</a>.
+-spec remove(This, Pos) -> wxMenu:wxMenu() when
+ This::wxMenuBar(), Pos::integer().
remove(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxMenuBar),
wxe_util:call(?wxMenuBar_Remove,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxMenuBar(), Pos::integer(), Menu::wxMenu:wxMenu(), Title::string()) -> wxMenu:wxMenu()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarreplace">external documentation</a>.
+-spec replace(This, Pos, Menu, Title) -> wxMenu:wxMenu() when
+ This::wxMenuBar(), Pos::integer(), Menu::wxMenu:wxMenu(), Title::unicode:chardata().
replace(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=MenuT,ref=MenuRef},Title)
when is_integer(Pos),is_list(Title) ->
?CLASS(ThisT,wxMenuBar),
@@ -266,8 +291,9 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=MenuT,ref=MenuRef},Titl
wxe_util:call(?wxMenuBar_Replace,
<<ThisRef:32/?UI,Pos:32/?UI,MenuRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), Itemid::integer(), HelpString::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarsethelpstring">external documentation</a>.
+-spec setHelpString(This, Itemid, HelpString) -> ok when
+ This::wxMenuBar(), Itemid::integer(), HelpString::unicode:chardata().
setHelpString(#wx_ref{type=ThisT,ref=ThisRef},Itemid,HelpString)
when is_integer(Itemid),is_list(HelpString) ->
?CLASS(ThisT,wxMenuBar),
@@ -275,8 +301,9 @@ setHelpString(#wx_ref{type=ThisT,ref=ThisRef},Itemid,HelpString)
wxe_util:cast(?wxMenuBar_SetHelpString,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(HelpString_UC)):32/?UI,(HelpString_UC)/binary, 0:(((8- ((4+byte_size(HelpString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), S::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarsetlabel">external documentation</a>.
+-spec setLabel(This, S) -> ok when
+ This::wxMenuBar(), S::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},S)
when is_list(S) ->
?CLASS(ThisT,wxMenuBar),
@@ -284,8 +311,9 @@ setLabel(#wx_ref{type=ThisT,ref=ThisRef},S)
wxe_util:cast(?wxMenuBar_SetLabel_1,
<<ThisRef:32/?UI,(byte_size(S_UC)):32/?UI,(S_UC)/binary, 0:(((8- ((0+byte_size(S_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), Itemid::integer(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarsetlabel">external documentation</a>.
+-spec setLabel(This, Itemid, Label) -> ok when
+ This::wxMenuBar(), Itemid::integer(), Label::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Label)
when is_integer(Itemid),is_list(Label) ->
?CLASS(ThisT,wxMenuBar),
@@ -293,8 +321,9 @@ setLabel(#wx_ref{type=ThisT,ref=ThisRef},Itemid,Label)
wxe_util:cast(?wxMenuBar_SetLabel_2,
<<ThisRef:32/?UI,Itemid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar(), Pos::integer(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenubar.html#wxmenubarsetlabeltop">external documentation</a>.
+-spec setLabelTop(This, Pos, Label) -> ok when
+ This::wxMenuBar(), Pos::integer(), Label::unicode:chardata().
setLabelTop(#wx_ref{type=ThisT,ref=ThisRef},Pos,Label)
when is_integer(Pos),is_list(Label) ->
?CLASS(ThisT,wxMenuBar),
@@ -302,8 +331,8 @@ setLabelTop(#wx_ref{type=ThisT,ref=ThisRef},Pos,Label)
wxe_util:cast(?wxMenuBar_SetLabelTop,
<<ThisRef:32/?UI,Pos:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuBar()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMenuBar()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMenuBar),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMenuEvent.erl b/lib/wx/src/gen/wxMenuEvent.erl
index fe368e679a..84c4760aa6 100644
--- a/lib/wx/src/gen/wxMenuEvent.erl
+++ b/lib/wx/src/gen/wxMenuEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +37,31 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxMenuEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxMenuEvent()) -> wxMenu:wxMenu()
+-type wxMenuEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuevent.html#wxmenueventgetmenu">external documentation</a>.
+-spec getMenu(This) -> wxMenu:wxMenu() when
+ This::wxMenuEvent().
getMenu(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuEvent),
wxe_util:call(?wxMenuEvent_GetMenu,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuevent.html#wxmenueventgetmenuid">external documentation</a>.
+-spec getMenuId(This) -> integer() when
+ This::wxMenuEvent().
getMenuId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuEvent),
wxe_util:call(?wxMenuEvent_GetMenuId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuevent.html#wxmenueventispopup">external documentation</a>.
+-spec isPopup(This) -> boolean() when
+ This::wxMenuEvent().
isPopup(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuEvent),
wxe_util:call(?wxMenuEvent_IsPopup,
diff --git a/lib/wx/src/gen/wxMenuItem.erl b/lib/wx/src/gen/wxMenuItem.erl
index e2bbe681c5..7ad71a2858 100644
--- a/lib/wx/src/gen/wxMenuItem.erl
+++ b/lib/wx/src/gen/wxMenuItem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,19 +32,26 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxMenuItem/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMenuItem()
+-type wxMenuItem() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxMenuItem().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxMenuItem()
-%% Option = {parentMenu, wxMenu:wxMenu()} | {id, integer()} | {text, string()} | {help, string()} | {kind, WxItemKind} | {subMenu, wxMenu:wxMenu()}
-%% WxItemKind = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemwxmenuitem">external documentation</a>.
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec new([Option]) -> wxMenuItem() when
+ Option :: {parentMenu, wxMenu:wxMenu()}
+ | {id, integer()}
+ | {text, unicode:chardata()}
+ | {help, unicode:chardata()}
+ | {kind, wx:wx_enum()}
+ | {subMenu, wxMenu:wxMenu()}.
new(Options)
when is_list(Options) ->
MOpts = fun({parentMenu, #wx_ref{type=ParentMenuT,ref=ParentMenuRef}}, Acc) -> ?CLASS(ParentMenuT,wxMenu),[<<1:32/?UI,ParentMenuRef:32/?UI>>|Acc];
@@ -58,15 +65,18 @@ new(Options)
wxe_util:construct(?wxMenuItem_new,
<<BinOpt/binary>>).
-%% @spec (This::wxMenuItem()) -> ok
%% @equiv check(This, [])
+-spec check(This) -> ok when
+ This::wxMenuItem().
+
check(This)
when is_record(This, wx_ref) ->
check(This, []).
-%% @spec (This::wxMenuItem(), [Option]) -> ok
-%% Option = {check, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemcheck">external documentation</a>.
+-spec check(This, [Option]) -> ok when
+ This::wxMenuItem(),
+ Option :: {check, boolean()}.
check(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMenuItem),
@@ -76,15 +86,18 @@ check(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxMenuItem_Check,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenuItem()) -> ok
%% @equiv enable(This, [])
+-spec enable(This) -> ok when
+ This::wxMenuItem().
+
enable(This)
when is_record(This, wx_ref) ->
enable(This, []).
-%% @spec (This::wxMenuItem(), [Option]) -> ok
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemenable">external documentation</a>.
+-spec enable(This, [Option]) -> ok when
+ This::wxMenuItem(),
+ Option :: {enable, boolean()}.
enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMenuItem),
@@ -94,117 +107,132 @@ enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxMenuItem_Enable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMenuItem()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetbitmap">external documentation</a>.
+-spec getBitmap(This) -> wxBitmap:wxBitmap() when
+ This::wxMenuItem().
getBitmap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetBitmap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgethelp">external documentation</a>.
+-spec getHelp(This) -> unicode:charlist() when
+ This::wxMenuItem().
getHelp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetHelp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetid">external documentation</a>.
+-spec getId(This) -> integer() when
+ This::wxMenuItem().
getId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> WxItemKind
-%% WxItemKind = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetkind">external documentation</a>.
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+%%<br /> Res = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec getKind(This) -> wx:wx_enum() when
+ This::wxMenuItem().
getKind(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetKind,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxMenuItem().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (Text::string()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetlabelfromtext">external documentation</a>.
+-spec getLabelFromText(Text) -> unicode:charlist() when
+ Text::unicode:chardata().
getLabelFromText(Text)
when is_list(Text) ->
Text_UC = unicode:characters_to_binary([Text,0]),
wxe_util:call(?wxMenuItem_GetLabelFromText,
<<(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuItem()) -> wxMenu:wxMenu()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetmenu">external documentation</a>.
+-spec getMenu(This) -> wxMenu:wxMenu() when
+ This::wxMenuItem().
getMenu(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetMenu,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxMenuItem().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> wxMenu:wxMenu()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemgetsubmenu">external documentation</a>.
+-spec getSubMenu(This) -> wxMenu:wxMenu() when
+ This::wxMenuItem().
getSubMenu(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_GetSubMenu,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemischeckable">external documentation</a>.
+-spec isCheckable(This) -> boolean() when
+ This::wxMenuItem().
isCheckable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_IsCheckable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemischecked">external documentation</a>.
+-spec isChecked(This) -> boolean() when
+ This::wxMenuItem().
isChecked(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_IsChecked,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemisenabled">external documentation</a>.
+-spec isEnabled(This) -> boolean() when
+ This::wxMenuItem().
isEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_IsEnabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemisseparator">external documentation</a>.
+-spec isSeparator(This) -> boolean() when
+ This::wxMenuItem().
isSeparator(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_IsSeparator,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemissubmenu">external documentation</a>.
+-spec isSubMenu(This) -> boolean() when
+ This::wxMenuItem().
isSubMenu(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMenuItem),
wxe_util:call(?wxMenuItem_IsSubMenu,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMenuItem(), Bitmap::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemsetbitmap">external documentation</a>.
+-spec setBitmap(This, Bitmap) -> ok when
+ This::wxMenuItem(), Bitmap::wxBitmap:wxBitmap().
setBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(ThisT,wxMenuItem),
?CLASS(BitmapT,wxBitmap),
wxe_util:cast(?wxMenuItem_SetBitmap,
<<ThisRef:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxMenuItem(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemsethelp">external documentation</a>.
+-spec setHelp(This, Str) -> ok when
+ This::wxMenuItem(), Str::unicode:chardata().
setHelp(#wx_ref{type=ThisT,ref=ThisRef},Str)
when is_list(Str) ->
?CLASS(ThisT,wxMenuItem),
@@ -212,24 +240,27 @@ setHelp(#wx_ref{type=ThisT,ref=ThisRef},Str)
wxe_util:cast(?wxMenuItem_SetHelp,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuItem(), Menu::wxMenu:wxMenu()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemsetmenu">external documentation</a>.
+-spec setMenu(This, Menu) -> ok when
+ This::wxMenuItem(), Menu::wxMenu:wxMenu().
setMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef}) ->
?CLASS(ThisT,wxMenuItem),
?CLASS(MenuT,wxMenu),
wxe_util:cast(?wxMenuItem_SetMenu,
<<ThisRef:32/?UI,MenuRef:32/?UI>>).
-%% @spec (This::wxMenuItem(), Menu::wxMenu:wxMenu()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemsetsubmenu">external documentation</a>.
+-spec setSubMenu(This, Menu) -> ok when
+ This::wxMenuItem(), Menu::wxMenu:wxMenu().
setSubMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef}) ->
?CLASS(ThisT,wxMenuItem),
?CLASS(MenuT,wxMenu),
wxe_util:cast(?wxMenuItem_SetSubMenu,
<<ThisRef:32/?UI,MenuRef:32/?UI>>).
-%% @spec (This::wxMenuItem(), Str::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmenuitem.html#wxmenuitemsettext">external documentation</a>.
+-spec setText(This, Str) -> ok when
+ This::wxMenuItem(), Str::unicode:chardata().
setText(#wx_ref{type=ThisT,ref=ThisRef},Str)
when is_list(Str) ->
?CLASS(ThisT,wxMenuItem),
@@ -237,8 +268,8 @@ setText(#wx_ref{type=ThisT,ref=ThisRef},Str)
wxe_util:cast(?wxMenuItem_SetText,
<<ThisRef:32/?UI,(byte_size(Str_UC)):32/?UI,(Str_UC)/binary, 0:(((8- ((0+byte_size(Str_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxMenuItem()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMenuItem()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMenuItem),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMessageDialog.erl b/lib/wx/src/gen/wxMessageDialog.erl
index 916b201d3f..83c3e67d01 100644
--- a/lib/wx/src/gen/wxMessageDialog.erl
+++ b/lib/wx/src/gen/wxMessageDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxMessageDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,15 +85,21 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string()) -> wxMessageDialog()
+-type wxMessageDialog() :: wx:wx_object().
%% @equiv new(Parent,Message, [])
+-spec new(Parent, Message) -> wxMessageDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata().
+
new(Parent,Message)
when is_record(Parent, wx_ref),is_list(Message) ->
new(Parent,Message, []).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), [Option]) -> wxMessageDialog()
-%% Option = {caption, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmessagedialog.html#wxmessagedialogwxmessagedialog">external documentation</a>.
+-spec new(Parent, Message, [Option]) -> wxMessageDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(),
+ Option :: {caption, unicode:chardata()}
+ | {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
when is_list(Message),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -105,8 +112,8 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
wxe_util:construct(?wxMessageDialog_new,
<<ParentRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMessageDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMessageDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMessageDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMiniFrame.erl b/lib/wx/src/gen/wxMiniFrame.erl
index b86f1d7cfa..3521c6458c 100644
--- a/lib/wx/src/gen/wxMiniFrame.erl
+++ b/lib/wx/src/gen/wxMiniFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +80,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxMiniFrame/0]).
%% @hidden
parent_class(wxFrame) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -87,21 +88,27 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMiniFrame()
+-type wxMiniFrame() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxminiframe.html#wxminiframewxminiframe">external documentation</a>.
+-spec new() -> wxMiniFrame().
new() ->
wxe_util:construct(?wxMiniFrame_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> wxMiniFrame()
%% @equiv new(Parent,Id,Title, [])
+-spec new(Parent, Id, Title) -> wxMiniFrame() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
new(Parent,Id,Title)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
new(Parent,Id,Title, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> wxMiniFrame()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxminiframe.html#wxminiframewxminiframe">external documentation</a>.
+-spec new(Parent, Id, Title, [Option]) -> wxMiniFrame() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -114,15 +121,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
wxe_util:construct(?wxMiniFrame_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMiniFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string()) -> bool()
%% @equiv create(This,Parent,Id,Title, [])
+-spec create(This, Parent, Id, Title) -> boolean() when
+ This::wxMiniFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata().
+
create(This,Parent,Id,Title)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title) ->
create(This,Parent,Id,Title, []).
-%% @spec (This::wxMiniFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxminiframe.html#wxminiframecreate">external documentation</a>.
+-spec create(This, Parent, Id, Title, [Option]) -> boolean() when
+ This::wxMiniFrame(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title, Options)
when is_integer(Id),is_list(Title),is_list(Options) ->
?CLASS(ThisT,wxMiniFrame),
@@ -136,8 +148,8 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ti
wxe_util:call(?wxMiniFrame_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMiniFrame()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMiniFrame()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMiniFrame),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxMirrorDC.erl b/lib/wx/src/gen/wxMirrorDC.erl
index c218bd7e72..1fdb90e4eb 100644
--- a/lib/wx/src/gen/wxMirrorDC.erl
+++ b/lib/wx/src/gen/wxMirrorDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +38,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -52,20 +52,23 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxMirrorDC/0]).
%% @hidden
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Dc::wxDC:wxDC(), Mirror::bool()) -> wxMirrorDC()
+-type wxMirrorDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmirrordc.html#wxmirrordcwxmirrordc">external documentation</a>.
+-spec new(Dc, Mirror) -> wxMirrorDC() when
+ Dc::wxDC:wxDC(), Mirror::boolean().
new(#wx_ref{type=DcT,ref=DcRef},Mirror)
when is_boolean(Mirror) ->
?CLASS(DcT,wxDC),
wxe_util:construct(?wxMirrorDC_new,
<<DcRef:32/?UI,(wxe_util:from_bool(Mirror)):32/?UI>>).
-%% @spec (This::wxMirrorDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMirrorDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMirrorDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -152,11 +155,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -170,7 +173,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxMouseCaptureChangedEvent.erl b/lib/wx/src/gen/wxMouseCaptureChangedEvent.erl
index cb921bf2df..659582b611 100644
--- a/lib/wx/src/gen/wxMouseCaptureChangedEvent.erl
+++ b/lib/wx/src/gen/wxMouseCaptureChangedEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +37,15 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxMouseCaptureChangedEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxMouseCaptureChangedEvent()) -> wxWindow:wxWindow()
+-type wxMouseCaptureChangedEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmousecapturechangedevent.html#wxmousecapturechangedeventgetcapturedwindow">external documentation</a>.
+-spec getCapturedWindow(This) -> wxWindow:wxWindow() when
+ This::wxMouseCaptureChangedEvent().
getCapturedWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseCaptureChangedEvent),
wxe_util:call(?wxMouseCaptureChangedEvent_GetCapturedWindow,
diff --git a/lib/wx/src/gen/wxMouseEvent.erl b/lib/wx/src/gen/wxMouseEvent.erl
index fed9a33db7..97ea9e908f 100644
--- a/lib/wx/src/gen/wxMouseEvent.erl
+++ b/lib/wx/src/gen/wxMouseEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,34 +43,41 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxMouseEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxMouseEvent()) -> bool()
+-type wxMouseEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventaltdown">external documentation</a>.
+-spec altDown(This) -> boolean() when
+ This::wxMouseEvent().
altDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_AltDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent(), But::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventbutton">external documentation</a>.
+-spec button(This, But) -> boolean() when
+ This::wxMouseEvent(), But::integer().
button(#wx_ref{type=ThisT,ref=ThisRef},But)
when is_integer(But) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_Button,
<<ThisRef:32/?UI,But:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @equiv buttonDClick(This, [])
+-spec buttonDClick(This) -> boolean() when
+ This::wxMouseEvent().
+
buttonDClick(This)
when is_record(This, wx_ref) ->
buttonDClick(This, []).
-%% @spec (This::wxMouseEvent(), [Option]) -> bool()
-%% Option = {but, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventbuttondclick">external documentation</a>.
+-spec buttonDClick(This, [Option]) -> boolean() when
+ This::wxMouseEvent(),
+ Option :: {but, integer()}.
buttonDClick(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMouseEvent),
@@ -80,15 +87,18 @@ buttonDClick(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxMouseEvent_ButtonDClick,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @equiv buttonDown(This, [])
+-spec buttonDown(This) -> boolean() when
+ This::wxMouseEvent().
+
buttonDown(This)
when is_record(This, wx_ref) ->
buttonDown(This, []).
-%% @spec (This::wxMouseEvent(), [Option]) -> bool()
-%% Option = {but, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventbuttondown">external documentation</a>.
+-spec buttonDown(This, [Option]) -> boolean() when
+ This::wxMouseEvent(),
+ Option :: {but, integer()}.
buttonDown(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMouseEvent),
@@ -98,15 +108,18 @@ buttonDown(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxMouseEvent_ButtonDown,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @equiv buttonUp(This, [])
+-spec buttonUp(This) -> boolean() when
+ This::wxMouseEvent().
+
buttonUp(This)
when is_record(This, wx_ref) ->
buttonUp(This, []).
-%% @spec (This::wxMouseEvent(), [Option]) -> bool()
-%% Option = {but, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventbuttonup">external documentation</a>.
+-spec buttonUp(This, [Option]) -> boolean() when
+ This::wxMouseEvent(),
+ Option :: {but, integer()}.
buttonUp(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxMouseEvent),
@@ -116,212 +129,242 @@ buttonUp(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxMouseEvent_ButtonUp,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventcmddown">external documentation</a>.
+-spec cmdDown(This) -> boolean() when
+ This::wxMouseEvent().
cmdDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_CmdDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventcontroldown">external documentation</a>.
+-spec controlDown(This) -> boolean() when
+ This::wxMouseEvent().
controlDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_ControlDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventdragging">external documentation</a>.
+-spec dragging(This) -> boolean() when
+ This::wxMouseEvent().
dragging(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_Dragging,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseevententering">external documentation</a>.
+-spec entering(This) -> boolean() when
+ This::wxMouseEvent().
entering(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_Entering,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetbutton">external documentation</a>.
+-spec getButton(This) -> integer() when
+ This::wxMouseEvent().
getButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxMouseEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent(), Dc::wxDC:wxDC()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetlogicalposition">external documentation</a>.
+-spec getLogicalPosition(This, Dc) -> {X::integer(), Y::integer()} when
+ This::wxMouseEvent(), Dc::wxDC:wxDC().
getLogicalPosition(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}) ->
?CLASS(ThisT,wxMouseEvent),
?CLASS(DcT,wxDC),
wxe_util:call(?wxMouseEvent_GetLogicalPosition,
<<ThisRef:32/?UI,DcRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetlinesperaction">external documentation</a>.
+-spec getLinesPerAction(This) -> integer() when
+ This::wxMouseEvent().
getLinesPerAction(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetLinesPerAction,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetwheelrotation">external documentation</a>.
+-spec getWheelRotation(This) -> integer() when
+ This::wxMouseEvent().
getWheelRotation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetWheelRotation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetwheeldelta">external documentation</a>.
+-spec getWheelDelta(This) -> integer() when
+ This::wxMouseEvent().
getWheelDelta(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetWheelDelta,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgetx">external documentation</a>.
+-spec getX(This) -> integer() when
+ This::wxMouseEvent().
getX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventgety">external documentation</a>.
+-spec getY(This) -> integer() when
+ This::wxMouseEvent().
getY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_GetY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventisbutton">external documentation</a>.
+-spec isButton(This) -> boolean() when
+ This::wxMouseEvent().
isButton(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_IsButton,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventispagescroll">external documentation</a>.
+-spec isPageScroll(This) -> boolean() when
+ This::wxMouseEvent().
isPageScroll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_IsPageScroll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventleaving">external documentation</a>.
+-spec leaving(This) -> boolean() when
+ This::wxMouseEvent().
leaving(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_Leaving,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventleftdclick">external documentation</a>.
+-spec leftDClick(This) -> boolean() when
+ This::wxMouseEvent().
leftDClick(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_LeftDClick,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventleftdown">external documentation</a>.
+-spec leftDown(This) -> boolean() when
+ This::wxMouseEvent().
leftDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_LeftDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventleftisdown">external documentation</a>.
+-spec leftIsDown(This) -> boolean() when
+ This::wxMouseEvent().
leftIsDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_LeftIsDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventleftup">external documentation</a>.
+-spec leftUp(This) -> boolean() when
+ This::wxMouseEvent().
leftUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_LeftUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventmetadown">external documentation</a>.
+-spec metaDown(This) -> boolean() when
+ This::wxMouseEvent().
metaDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_MetaDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventmiddledclick">external documentation</a>.
+-spec middleDClick(This) -> boolean() when
+ This::wxMouseEvent().
middleDClick(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_MiddleDClick,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventmiddledown">external documentation</a>.
+-spec middleDown(This) -> boolean() when
+ This::wxMouseEvent().
middleDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_MiddleDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventmiddleisdown">external documentation</a>.
+-spec middleIsDown(This) -> boolean() when
+ This::wxMouseEvent().
middleIsDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_MiddleIsDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventmiddleup">external documentation</a>.
+-spec middleUp(This) -> boolean() when
+ This::wxMouseEvent().
middleUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_MiddleUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventmoving">external documentation</a>.
+-spec moving(This) -> boolean() when
+ This::wxMouseEvent().
moving(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_Moving,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventrightdclick">external documentation</a>.
+-spec rightDClick(This) -> boolean() when
+ This::wxMouseEvent().
rightDClick(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_RightDClick,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventrightdown">external documentation</a>.
+-spec rightDown(This) -> boolean() when
+ This::wxMouseEvent().
rightDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_RightDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventrightisdown">external documentation</a>.
+-spec rightIsDown(This) -> boolean() when
+ This::wxMouseEvent().
rightIsDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_RightIsDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventrightup">external documentation</a>.
+-spec rightUp(This) -> boolean() when
+ This::wxMouseEvent().
rightUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_RightUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMouseEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmouseevent.html#wxmouseeventshiftdown">external documentation</a>.
+-spec shiftDown(This) -> boolean() when
+ This::wxMouseEvent().
shiftDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMouseEvent),
wxe_util:call(?wxMouseEvent_ShiftDown,
diff --git a/lib/wx/src/gen/wxMoveEvent.erl b/lib/wx/src/gen/wxMoveEvent.erl
index 80bf59074a..b2f2fa74df 100644
--- a/lib/wx/src/gen/wxMoveEvent.erl
+++ b/lib/wx/src/gen/wxMoveEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +37,15 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxMoveEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxMoveEvent()) -> {X::integer(),Y::integer()}
+-type wxMoveEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmoveevent.html#wxmoveeventgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxMoveEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMoveEvent),
wxe_util:call(?wxMoveEvent_GetPosition,
diff --git a/lib/wx/src/gen/wxMultiChoiceDialog.erl b/lib/wx/src/gen/wxMultiChoiceDialog.erl
index e69889a1e0..6a6a6b833a 100644
--- a/lib/wx/src/gen/wxMultiChoiceDialog.erl
+++ b/lib/wx/src/gen/wxMultiChoiceDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxMultiChoiceDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,21 +85,26 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxMultiChoiceDialog()
+-type wxMultiChoiceDialog() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmultichoicedialog.html#wxmultichoicedialogwxmultichoicedialog">external documentation</a>.
+-spec new() -> wxMultiChoiceDialog().
new() ->
wxe_util:construct(?wxMultiChoiceDialog_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), Caption::string(), Choices::[[string()]]) -> wxMultiChoiceDialog()
%% @equiv new(Parent,Message,Caption,Choices, [])
+-spec new(Parent, Message, Caption, Choices) -> wxMultiChoiceDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(), Caption::unicode:chardata(), Choices::[unicode:chardata()].
+
new(Parent,Message,Caption,Choices)
when is_record(Parent, wx_ref),is_list(Message),is_list(Caption),is_list(Choices) ->
new(Parent,Message,Caption,Choices, []).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), Caption::string(), Choices::[[string()]], [Option]) -> wxMultiChoiceDialog()
-%% Option = {style, integer()} | {pos, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmultichoicedialog.html#wxmultichoicedialogwxmultichoicedialog">external documentation</a>.
+-spec new(Parent, Message, Caption, Choices, [Option]) -> wxMultiChoiceDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(), Caption::unicode:chardata(), Choices::[unicode:chardata()],
+ Option :: {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef},Message,Caption,Choices, Options)
when is_list(Message),is_list(Caption),is_list(Choices),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -113,15 +119,17 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Message,Caption,Choices, Options)
wxe_util:construct(?wxMultiChoiceDialog_new_5,
<<ParentRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Caption_UC)):32/?UI,(Caption_UC)/binary, 0:(((8- ((4+byte_size(Caption_UC)) band 16#7)) band 16#7))/unit:8,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxMultiChoiceDialog()) -> [integer()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmultichoicedialog.html#wxmultichoicedialoggetselections">external documentation</a>.
+-spec getSelections(This) -> [integer()] when
+ This::wxMultiChoiceDialog().
getSelections(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxMultiChoiceDialog),
wxe_util:call(?wxMultiChoiceDialog_GetSelections,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxMultiChoiceDialog(), Selections::[integer()]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxmultichoicedialog.html#wxmultichoicedialogsetselections">external documentation</a>.
+-spec setSelections(This, Selections) -> ok when
+ This::wxMultiChoiceDialog(), Selections::[integer()].
setSelections(#wx_ref{type=ThisT,ref=ThisRef},Selections)
when is_list(Selections) ->
?CLASS(ThisT,wxMultiChoiceDialog),
@@ -129,8 +137,8 @@ setSelections(#wx_ref{type=ThisT,ref=ThisRef},Selections)
<<ThisRef:32/?UI,(length(Selections)):32/?UI,
(<< <<C:32/?I>> || C <- Selections>>)/binary, 0:(((0+length(Selections)) rem 2)*32)>>).
-%% @spec (This::wxMultiChoiceDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxMultiChoiceDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxMultiChoiceDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxNavigationKeyEvent.erl b/lib/wx/src/gen/wxNavigationKeyEvent.erl
index 7cf7dff9aa..7559639fcd 100644
--- a/lib/wx/src/gen/wxNavigationKeyEvent.erl
+++ b/lib/wx/src/gen/wxNavigationKeyEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,64 +38,74 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxNavigationKeyEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxNavigationKeyEvent()) -> bool()
+-type wxNavigationKeyEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventgetdirection">external documentation</a>.
+-spec getDirection(This) -> boolean() when
+ This::wxNavigationKeyEvent().
getDirection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:call(?wxNavigationKeyEvent_GetDirection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent(), BForward::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventsetdirection">external documentation</a>.
+-spec setDirection(This, BForward) -> ok when
+ This::wxNavigationKeyEvent(), BForward::boolean().
setDirection(#wx_ref{type=ThisT,ref=ThisRef},BForward)
when is_boolean(BForward) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:cast(?wxNavigationKeyEvent_SetDirection,
<<ThisRef:32/?UI,(wxe_util:from_bool(BForward)):32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventiswindowchange">external documentation</a>.
+-spec isWindowChange(This) -> boolean() when
+ This::wxNavigationKeyEvent().
isWindowChange(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:call(?wxNavigationKeyEvent_IsWindowChange,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent(), BIs::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventsetwindowchange">external documentation</a>.
+-spec setWindowChange(This, BIs) -> ok when
+ This::wxNavigationKeyEvent(), BIs::boolean().
setWindowChange(#wx_ref{type=ThisT,ref=ThisRef},BIs)
when is_boolean(BIs) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:cast(?wxNavigationKeyEvent_SetWindowChange,
<<ThisRef:32/?UI,(wxe_util:from_bool(BIs)):32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventisfromtab">external documentation</a>.
+-spec isFromTab(This) -> boolean() when
+ This::wxNavigationKeyEvent().
isFromTab(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:call(?wxNavigationKeyEvent_IsFromTab,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent(), BIs::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventsetfromtab">external documentation</a>.
+-spec setFromTab(This, BIs) -> ok when
+ This::wxNavigationKeyEvent(), BIs::boolean().
setFromTab(#wx_ref{type=ThisT,ref=ThisRef},BIs)
when is_boolean(BIs) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:cast(?wxNavigationKeyEvent_SetFromTab,
<<ThisRef:32/?UI,(wxe_util:from_bool(BIs)):32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventgetcurrentfocus">external documentation</a>.
+-spec getCurrentFocus(This) -> wxWindow:wxWindow() when
+ This::wxNavigationKeyEvent().
getCurrentFocus(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNavigationKeyEvent),
wxe_util:call(?wxNavigationKeyEvent_GetCurrentFocus,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNavigationKeyEvent(), Win::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnavigationkeyevent.html#wxnavigationkeyeventsetcurrentfocus">external documentation</a>.
+-spec setCurrentFocus(This, Win) -> ok when
+ This::wxNavigationKeyEvent(), Win::wxWindow:wxWindow().
setCurrentFocus(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(ThisT,wxNavigationKeyEvent),
?CLASS(WinT,wxWindow),
diff --git a/lib/wx/src/gen/wxNcPaintEvent.erl b/lib/wx/src/gen/wxNcPaintEvent.erl
index b45420a2fc..4dd292a0be 100644
--- a/lib/wx/src/gen/wxNcPaintEvent.erl
+++ b/lib/wx/src/gen/wxNcPaintEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,12 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxNcPaintEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxNcPaintEvent() :: wx:wx_object().
%% From wxEvent
%% @hidden
stopPropagation(This) -> wxEvent:stopPropagation(This).
diff --git a/lib/wx/src/gen/wxNotebook.erl b/lib/wx/src/gen/wxNotebook.erl
index da543d7ac6..04ab62b047 100644
--- a/lib/wx/src/gen/wxNotebook.erl
+++ b/lib/wx/src/gen/wxNotebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,27 +74,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxNotebook/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxNotebook()
+-type wxNotebook() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookwxnotebook">external documentation</a>.
+-spec new() -> wxNotebook().
new() ->
wxe_util:construct(?wxNotebook_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Winid::integer()) -> wxNotebook()
%% @equiv new(Parent,Winid, [])
+-spec new(Parent, Winid) -> wxNotebook() when
+ Parent::wxWindow:wxWindow(), Winid::integer().
+
new(Parent,Winid)
when is_record(Parent, wx_ref),is_integer(Winid) ->
new(Parent,Winid, []).
-%% @spec (Parent::wxWindow:wxWindow(), Winid::integer(), [Option]) -> wxNotebook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookwxnotebook">external documentation</a>.
+-spec new(Parent, Winid, [Option]) -> wxNotebook() when
+ Parent::wxWindow:wxWindow(), Winid::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Winid, Options)
when is_integer(Winid),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,15 +113,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Winid, Options)
wxe_util:construct(?wxNotebook_new_3,
<<ParentRef:32/?UI,Winid:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxNotebook(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv addPage(This,Page,Text, [])
+-spec addPage(This, Page, Text) -> boolean() when
+ This::wxNotebook(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
addPage(This,Page,Text)
when is_record(This, wx_ref),is_record(Page, wx_ref),is_list(Text) ->
addPage(This,Page,Text, []).
-%% @spec (This::wxNotebook(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookaddpage">external documentation</a>.
+-spec addPage(This, Page, Text, [Option]) -> boolean() when
+ This::wxNotebook(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxNotebook),
@@ -127,15 +138,18 @@ addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Op
wxe_util:call(?wxNotebook_AddPage,
<<ThisRef:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxNotebook()) -> ok
%% @equiv advanceSelection(This, [])
+-spec advanceSelection(This) -> ok when
+ This::wxNotebook().
+
advanceSelection(This)
when is_record(This, wx_ref) ->
advanceSelection(This, []).
-%% @spec (This::wxNotebook(), [Option]) -> ok
-%% Option = {forward, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookadvanceselection">external documentation</a>.
+-spec advanceSelection(This, [Option]) -> ok when
+ This::wxNotebook(),
+ Option :: {forward, boolean()}.
advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxNotebook),
@@ -145,23 +159,29 @@ advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxNotebook_AdvanceSelection,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxNotebook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList) -> ok when
+ This::wxNotebook(), ImageList::wxImageList:wxImageList().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxNotebook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxNotebook_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxNotebook(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxNotebook(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxNotebook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxNotebook(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxNotebook),
@@ -174,112 +194,130 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxNotebook_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxNotebook()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookdeleteallpages">external documentation</a>.
+-spec deleteAllPages(This) -> boolean() when
+ This::wxNotebook().
deleteAllPages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_DeleteAllPages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookdeletepage">external documentation</a>.
+-spec deletePage(This, NPage) -> boolean() when
+ This::wxNotebook(), NPage::integer().
deletePage(#wx_ref{type=ThisT,ref=ThisRef},NPage)
when is_integer(NPage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_DeletePage,
<<ThisRef:32/?UI,NPage:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookremovepage">external documentation</a>.
+-spec removePage(This, NPage) -> boolean() when
+ This::wxNotebook(), NPage::integer().
removePage(#wx_ref{type=ThisT,ref=ThisRef},NPage)
when is_integer(NPage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_RemovePage,
<<ThisRef:32/?UI,NPage:32/?UI>>).
-%% @spec (This::wxNotebook()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetcurrentpage">external documentation</a>.
+-spec getCurrentPage(This) -> wxWindow:wxWindow() when
+ This::wxNotebook().
getCurrentPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetCurrentPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetimagelist">external documentation</a>.
+-spec getImageList(This) -> wxImageList:wxImageList() when
+ This::wxNotebook().
getImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook(), N::integer()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetpage">external documentation</a>.
+-spec getPage(This, N) -> wxWindow:wxWindow() when
+ This::wxNotebook(), N::integer().
getPage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetPage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxNotebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetpagecount">external documentation</a>.
+-spec getPageCount(This) -> integer() when
+ This::wxNotebook().
getPageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetPageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetpageimage">external documentation</a>.
+-spec getPageImage(This, NPage) -> integer() when
+ This::wxNotebook(), NPage::integer().
getPageImage(#wx_ref{type=ThisT,ref=ThisRef},NPage)
when is_integer(NPage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetPageImage,
<<ThisRef:32/?UI,NPage:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetpagetext">external documentation</a>.
+-spec getPageText(This, NPage) -> unicode:charlist() when
+ This::wxNotebook(), NPage::integer().
getPageText(#wx_ref{type=ThisT,ref=ThisRef},NPage)
when is_integer(NPage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetPageText,
<<ThisRef:32/?UI,NPage:32/?UI>>).
-%% @spec (This::wxNotebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetrowcount">external documentation</a>.
+-spec getRowCount(This) -> integer() when
+ This::wxNotebook().
getRowCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetRowCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxNotebook().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookgetthemebackgroundcolour">external documentation</a>.
+-spec getThemeBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxNotebook().
getThemeBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_GetThemeBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookhittest">external documentation</a>.
+-spec hitTest(This, Pt) -> Result when
+ Result ::{Res ::integer(), Flags::integer()},
+ This::wxNotebook(), Pt::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_HitTest,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxNotebook(), Position::integer(), Win::wxWindow:wxWindow(), StrText::string()) -> bool()
%% @equiv insertPage(This,Position,Win,StrText, [])
+-spec insertPage(This, Position, Win, StrText) -> boolean() when
+ This::wxNotebook(), Position::integer(), Win::wxWindow:wxWindow(), StrText::unicode:chardata().
+
insertPage(This,Position,Win,StrText)
when is_record(This, wx_ref),is_integer(Position),is_record(Win, wx_ref),is_list(StrText) ->
insertPage(This,Position,Win,StrText, []).
-%% @spec (This::wxNotebook(), Position::integer(), Win::wxWindow:wxWindow(), StrText::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookinsertpage">external documentation</a>.
+-spec insertPage(This, Position, Win, StrText, [Option]) -> boolean() when
+ This::wxNotebook(), Position::integer(), Win::wxWindow:wxWindow(), StrText::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
insertPage(#wx_ref{type=ThisT,ref=ThisRef},Position,#wx_ref{type=WinT,ref=WinRef},StrText, Options)
when is_integer(Position),is_list(StrText),is_list(Options) ->
?CLASS(ThisT,wxNotebook),
@@ -292,40 +330,45 @@ insertPage(#wx_ref{type=ThisT,ref=ThisRef},Position,#wx_ref{type=WinT,ref=WinRef
wxe_util:call(?wxNotebook_InsertPage,
<<ThisRef:32/?UI,Position:32/?UI,WinRef:32/?UI,(byte_size(StrText_UC)):32/?UI,(StrText_UC)/binary, 0:(((8- ((0+byte_size(StrText_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxNotebook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList) -> ok when
+ This::wxNotebook(), ImageList::wxImageList:wxImageList().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxNotebook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxNotebook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxNotebook(), Padding::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetpadding">external documentation</a>.
+-spec setPadding(This, Padding) -> ok when
+ This::wxNotebook(), Padding::{W::integer(), H::integer()}.
setPadding(#wx_ref{type=ThisT,ref=ThisRef},{PaddingW,PaddingH})
when is_integer(PaddingW),is_integer(PaddingH) ->
?CLASS(ThisT,wxNotebook),
wxe_util:cast(?wxNotebook_SetPadding,
<<ThisRef:32/?UI,PaddingW:32/?UI,PaddingH:32/?UI>>).
-%% @spec (This::wxNotebook(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetpagesize">external documentation</a>.
+-spec setPageSize(This, Size) -> ok when
+ This::wxNotebook(), Size::{W::integer(), H::integer()}.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxNotebook),
wxe_util:cast(?wxNotebook_SetPageSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer(), NImage::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetpageimage">external documentation</a>.
+-spec setPageImage(This, NPage, NImage) -> boolean() when
+ This::wxNotebook(), NPage::integer(), NImage::integer().
setPageImage(#wx_ref{type=ThisT,ref=ThisRef},NPage,NImage)
when is_integer(NPage),is_integer(NImage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_SetPageImage,
<<ThisRef:32/?UI,NPage:32/?UI,NImage:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer(), StrText::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetpagetext">external documentation</a>.
+-spec setPageText(This, NPage, StrText) -> boolean() when
+ This::wxNotebook(), NPage::integer(), StrText::unicode:chardata().
setPageText(#wx_ref{type=ThisT,ref=ThisRef},NPage,StrText)
when is_integer(NPage),is_list(StrText) ->
?CLASS(ThisT,wxNotebook),
@@ -333,24 +376,26 @@ setPageText(#wx_ref{type=ThisT,ref=ThisRef},NPage,StrText)
wxe_util:call(?wxNotebook_SetPageText,
<<ThisRef:32/?UI,NPage:32/?UI,(byte_size(StrText_UC)):32/?UI,(StrText_UC)/binary, 0:(((8- ((4+byte_size(StrText_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxNotebook(), NPage::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebooksetselection">external documentation</a>.
+-spec setSelection(This, NPage) -> integer() when
+ This::wxNotebook(), NPage::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},NPage)
when is_integer(NPage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_SetSelection,
<<ThisRef:32/?UI,NPage:32/?UI>>).
-%% @spec (This::wxNotebook(), NPage::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebook.html#wxnotebookchangeselection">external documentation</a>.
+-spec changeSelection(This, NPage) -> integer() when
+ This::wxNotebook(), NPage::integer().
changeSelection(#wx_ref{type=ThisT,ref=ThisRef},NPage)
when is_integer(NPage) ->
?CLASS(ThisT,wxNotebook),
wxe_util:call(?wxNotebook_ChangeSelection,
<<ThisRef:32/?UI,NPage:32/?UI>>).
-%% @spec (This::wxNotebook()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxNotebook()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxNotebook),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxNotebookEvent.erl b/lib/wx/src/gen/wxNotebookEvent.erl
index 6be826bdd2..72c0bb9cf4 100644
--- a/lib/wx/src/gen/wxNotebookEvent.erl
+++ b/lib/wx/src/gen/wxNotebookEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,36 +41,42 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxNotebookEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxNotebookEvent()) -> integer()
+-type wxNotebookEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebookevent.html#wxnotebookeventgetoldselection">external documentation</a>.
+-spec getOldSelection(This) -> integer() when
+ This::wxNotebookEvent().
getOldSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebookEvent),
wxe_util:call(?wxNotebookEvent_GetOldSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebookEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebookevent.html#wxnotebookeventgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxNotebookEvent().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotebookEvent),
wxe_util:call(?wxNotebookEvent_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotebookEvent(), NOldSel::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebookevent.html#wxnotebookeventsetoldselection">external documentation</a>.
+-spec setOldSelection(This, NOldSel) -> ok when
+ This::wxNotebookEvent(), NOldSel::integer().
setOldSelection(#wx_ref{type=ThisT,ref=ThisRef},NOldSel)
when is_integer(NOldSel) ->
?CLASS(ThisT,wxNotebookEvent),
wxe_util:cast(?wxNotebookEvent_SetOldSelection,
<<ThisRef:32/?UI,NOldSel:32/?UI>>).
-%% @spec (This::wxNotebookEvent(), NSel::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotebookevent.html#wxnotebookeventsetselection">external documentation</a>.
+-spec setSelection(This, NSel) -> ok when
+ This::wxNotebookEvent(), NSel::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},NSel)
when is_integer(NSel) ->
?CLASS(ThisT,wxNotebookEvent),
diff --git a/lib/wx/src/gen/wxNotifyEvent.erl b/lib/wx/src/gen/wxNotifyEvent.erl
index b2a6da16f0..7ba23469be 100644
--- a/lib/wx/src/gen/wxNotifyEvent.erl
+++ b/lib/wx/src/gen/wxNotifyEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +36,32 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxNotifyEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxNotifyEvent()) -> ok
+-type wxNotifyEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotifyevent.html#wxnotifyeventallow">external documentation</a>.
+-spec allow(This) -> ok when
+ This::wxNotifyEvent().
allow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotifyEvent),
wxe_util:cast(?wxNotifyEvent_Allow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotifyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotifyevent.html#wxnotifyeventisallowed">external documentation</a>.
+-spec isAllowed(This) -> boolean() when
+ This::wxNotifyEvent().
isAllowed(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotifyEvent),
wxe_util:call(?wxNotifyEvent_IsAllowed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxNotifyEvent()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxnotifyevent.html#wxnotifyeventveto">external documentation</a>.
+-spec veto(This) -> ok when
+ This::wxNotifyEvent().
veto(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxNotifyEvent),
wxe_util:cast(?wxNotifyEvent_Veto,
diff --git a/lib/wx/src/gen/wxPageSetupDialog.erl b/lib/wx/src/gen/wxPageSetupDialog.erl
index 2c11863a21..653ba5f015 100644
--- a/lib/wx/src/gen/wxPageSetupDialog.erl
+++ b/lib/wx/src/gen/wxPageSetupDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +29,23 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPageSetupDialog/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxPageSetupDialog()
+-type wxPageSetupDialog() :: wx:wx_object().
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxPageSetupDialog() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxPageSetupDialog()
-%% Option = {data, wxPageSetupDialogData:wxPageSetupDialogData()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialog.html#wxpagesetupdialogwxpagesetupdialog">external documentation</a>.
+-spec new(Parent, [Option]) -> wxPageSetupDialog() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {data, wxPageSetupDialogData:wxPageSetupDialogData()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -50,22 +55,24 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxPageSetupDialog_new,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxPageSetupDialog()) -> wxPageSetupDialogData:wxPageSetupDialogData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialog.html#wxpagesetupdialoggetpagesetupdata">external documentation</a>.
+-spec getPageSetupData(This) -> wxPageSetupDialogData:wxPageSetupDialogData() when
+ This::wxPageSetupDialog().
getPageSetupData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialog),
wxe_util:call(?wxPageSetupDialog_GetPageSetupData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialog()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialog.html#wxpagesetupdialogshowmodal">external documentation</a>.
+-spec showModal(This) -> integer() when
+ This::wxPageSetupDialog().
showModal(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialog),
wxe_util:call(?wxPageSetupDialog_ShowModal,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPageSetupDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPageSetupDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPageSetupDialogData.erl b/lib/wx/src/gen/wxPageSetupDialogData.erl
index 672ec7c083..7c453a9872 100644
--- a/lib/wx/src/gen/wxPageSetupDialogData.erl
+++ b/lib/wx/src/gen/wxPageSetupDialogData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,17 +36,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPageSetupDialogData/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPageSetupDialogData()
+-type wxPageSetupDialogData() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatawxpagesetupdialogdata">external documentation</a>.
+-spec new() -> wxPageSetupDialogData().
new() ->
wxe_util:construct(?wxPageSetupDialogData_new_0,
<<>>).
-%% @spec (PrintData::wxPrintData:wxPrintData() | wxPageSetupDialogData()) -> wxPageSetupDialogData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatawxpagesetupdialogdata">external documentation</a>.
+-spec new(PrintData) -> wxPageSetupDialogData() when
+ PrintData::wxPrintData:wxPrintData() | wxPageSetupDialogData().
new(#wx_ref{type=PrintDataT,ref=PrintDataRef}) ->
PrintDataOP = case ?CLASS_T(PrintDataT,wxPrintData) of
true ->
@@ -57,216 +60,243 @@ new(#wx_ref{type=PrintDataT,ref=PrintDataRef}) ->
wxe_util:construct(PrintDataOP,
<<PrintDataRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdataenablehelp">external documentation</a>.
+-spec enableHelp(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
enableHelp(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_EnableHelp,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdataenablemargins">external documentation</a>.
+-spec enableMargins(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
enableMargins(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_EnableMargins,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdataenableorientation">external documentation</a>.
+-spec enableOrientation(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
enableOrientation(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_EnableOrientation,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdataenablepaper">external documentation</a>.
+-spec enablePaper(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
enablePaper(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_EnablePaper,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdataenableprinter">external documentation</a>.
+-spec enablePrinter(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
enablePrinter(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_EnablePrinter,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetdefaultminmargins">external documentation</a>.
+-spec getDefaultMinMargins(This) -> boolean() when
+ This::wxPageSetupDialogData().
getDefaultMinMargins(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetDefaultMinMargins,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetenablemargins">external documentation</a>.
+-spec getEnableMargins(This) -> boolean() when
+ This::wxPageSetupDialogData().
getEnableMargins(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetEnableMargins,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetenableorientation">external documentation</a>.
+-spec getEnableOrientation(This) -> boolean() when
+ This::wxPageSetupDialogData().
getEnableOrientation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetEnableOrientation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetenablepaper">external documentation</a>.
+-spec getEnablePaper(This) -> boolean() when
+ This::wxPageSetupDialogData().
getEnablePaper(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetEnablePaper,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetenableprinter">external documentation</a>.
+-spec getEnablePrinter(This) -> boolean() when
+ This::wxPageSetupDialogData().
getEnablePrinter(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetEnablePrinter,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetenablehelp">external documentation</a>.
+-spec getEnableHelp(This) -> boolean() when
+ This::wxPageSetupDialogData().
getEnableHelp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetEnableHelp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetdefaultinfo">external documentation</a>.
+-spec getDefaultInfo(This) -> boolean() when
+ This::wxPageSetupDialogData().
getDefaultInfo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetDefaultInfo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetmargintopleft">external documentation</a>.
+-spec getMarginTopLeft(This) -> {X::integer(), Y::integer()} when
+ This::wxPageSetupDialogData().
getMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMarginTopLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetmarginbottomright">external documentation</a>.
+-spec getMarginBottomRight(This) -> {X::integer(), Y::integer()} when
+ This::wxPageSetupDialogData().
getMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMarginBottomRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetminmargintopleft">external documentation</a>.
+-spec getMinMarginTopLeft(This) -> {X::integer(), Y::integer()} when
+ This::wxPageSetupDialogData().
getMinMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMinMarginTopLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetminmarginbottomright">external documentation</a>.
+-spec getMinMarginBottomRight(This) -> {X::integer(), Y::integer()} when
+ This::wxPageSetupDialogData().
getMinMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetMinMarginBottomRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetpaperid">external documentation</a>.
+-spec getPaperId(This) -> integer() when
+ This::wxPageSetupDialogData().
getPaperId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetPaperId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetpapersize">external documentation</a>.
+-spec getPaperSize(This) -> {W::integer(), H::integer()} when
+ This::wxPageSetupDialogData().
getPaperSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetPaperSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> wxPrintData:wxPrintData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatagetprintdata">external documentation</a>.
+-spec getPrintData(This) -> wxPrintData:wxPrintData() when
+ This::wxPageSetupDialogData().
getPrintData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_GetPrintData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdataisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxPageSetupDialogData().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:call(?wxPageSetupDialogData_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetdefaultinfo">external documentation</a>.
+-spec setDefaultInfo(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
setDefaultInfo(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetDefaultInfo,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetdefaultminmargins">external documentation</a>.
+-spec setDefaultMinMargins(This, Flag) -> ok when
+ This::wxPageSetupDialogData(), Flag::boolean().
setDefaultMinMargins(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetDefaultMinMargins,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetmargintopleft">external documentation</a>.
+-spec setMarginTopLeft(This, Pt) -> ok when
+ This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}.
setMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetMarginTopLeft,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetmarginbottomright">external documentation</a>.
+-spec setMarginBottomRight(This, Pt) -> ok when
+ This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}.
setMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetMarginBottomRight,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetminmargintopleft">external documentation</a>.
+-spec setMinMarginTopLeft(This, Pt) -> ok when
+ This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}.
setMinMarginTopLeft(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetMinMarginTopLeft,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Pt::{X::integer(),Y::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetminmarginbottomright">external documentation</a>.
+-spec setMinMarginBottomRight(This, Pt) -> ok when
+ This::wxPageSetupDialogData(), Pt::{X::integer(), Y::integer()}.
setMinMarginBottomRight(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetMinMarginBottomRight,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), Id::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetpaperid">external documentation</a>.
+-spec setPaperId(This, Id) -> ok when
+ This::wxPageSetupDialogData(), Id::integer().
setPaperId(#wx_ref{type=ThisT,ref=ThisRef},Id)
when is_integer(Id) ->
?CLASS(ThisT,wxPageSetupDialogData),
wxe_util:cast(?wxPageSetupDialogData_SetPaperId,
<<ThisRef:32/?UI,Id:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(),X::integer()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetpapersize">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setPaperSize(This::wxPageSetupDialogData(), Id::integer()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setPaperSize(This::wxPageSetupDialogData(), Sz::{W::integer(),H::integer()}) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setPaperSize(This, Sz) -> ok when<br />
+%% This::wxPageSetupDialogData(), Sz::{W::integer(), H::integer()}.<br />
+%%
+-spec setPaperSize(This, Id) -> ok when
+ This::wxPageSetupDialogData(), Id::integer();
+ (This, Sz) -> ok when
+ This::wxPageSetupDialogData(), Sz::{W::integer(), H::integer()}.
setPaperSize(#wx_ref{type=ThisT,ref=ThisRef},Id)
when is_integer(Id) ->
?CLASS(ThisT,wxPageSetupDialogData),
@@ -278,16 +308,17 @@ setPaperSize(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
wxe_util:cast(?wxPageSetupDialogData_SetPaperSize_1_1,
<<ThisRef:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData(), PrintData::wxPrintData:wxPrintData()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpagesetupdialogdata.html#wxpagesetupdialogdatasetprintdata">external documentation</a>.
+-spec setPrintData(This, PrintData) -> ok when
+ This::wxPageSetupDialogData(), PrintData::wxPrintData:wxPrintData().
setPrintData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PrintDataT,ref=PrintDataRef}) ->
?CLASS(ThisT,wxPageSetupDialogData),
?CLASS(PrintDataT,wxPrintData),
wxe_util:cast(?wxPageSetupDialogData_SetPrintData,
<<ThisRef:32/?UI,PrintDataRef:32/?UI>>).
-%% @spec (This::wxPageSetupDialogData()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPageSetupDialogData()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPageSetupDialogData),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPaintDC.erl b/lib/wx/src/gen/wxPaintDC.erl
index 47d5947097..9e81bc31af 100644
--- a/lib/wx/src/gen/wxPaintDC.erl
+++ b/lib/wx/src/gen/wxPaintDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +39,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -53,26 +53,29 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxPaintDC/0]).
%% @hidden
parent_class(wxWindowDC) -> true;
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPaintDC()
+-type wxPaintDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpaintdc.html#wxpaintdcwxpaintdc">external documentation</a>.
+-spec new() -> wxPaintDC().
new() ->
wxe_util:construct(?wxPaintDC_new_0,
<<>>).
-%% @spec (Win::wxWindow:wxWindow()) -> wxPaintDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpaintdc.html#wxpaintdcwxpaintdc">external documentation</a>.
+-spec new(Win) -> wxPaintDC() when
+ Win::wxWindow:wxWindow().
new(#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(WinT,wxWindow),
wxe_util:construct(?wxPaintDC_new_1,
<<WinRef:32/?UI>>).
-%% @spec (This::wxPaintDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPaintDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPaintDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -160,11 +163,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -178,7 +181,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxPaintEvent.erl b/lib/wx/src/gen/wxPaintEvent.erl
index 2603e61623..a13db607a4 100644
--- a/lib/wx/src/gen/wxPaintEvent.erl
+++ b/lib/wx/src/gen/wxPaintEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,12 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxPaintEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxPaintEvent() :: wx:wx_object().
%% From wxEvent
%% @hidden
stopPropagation(This) -> wxEvent:stopPropagation(This).
diff --git a/lib/wx/src/gen/wxPalette.erl b/lib/wx/src/gen/wxPalette.erl
index ee1fd0016d..991f706acb 100644
--- a/lib/wx/src/gen/wxPalette.erl
+++ b/lib/wx/src/gen/wxPalette.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPalette/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPalette()
+-type wxPalette() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettewxpalette">external documentation</a>.
+-spec new() -> wxPalette().
new() ->
wxe_util:construct(?wxPalette_new_0,
<<>>).
-%% @spec (Red::binary(), Green::binary(), Blue::binary()) -> wxPalette()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettewxpalette">external documentation</a>.
+-spec new(Red, Green, Blue) -> wxPalette() when
+ Red::binary(), Green::binary(), Blue::binary().
new(Red,Green,Blue)
when is_binary(Red),is_binary(Green),is_binary(Blue) ->
wxe_util:send_bin(Red),
@@ -49,8 +52,9 @@ new(Red,Green,Blue)
wxe_util:construct(?wxPalette_new_4,
<<>>).
-%% @spec (This::wxPalette(), Red::binary(), Green::binary(), Blue::binary()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettecreate">external documentation</a>.
+-spec create(This, Red, Green, Blue) -> boolean() when
+ This::wxPalette(), Red::binary(), Green::binary(), Blue::binary().
create(#wx_ref{type=ThisT,ref=ThisRef},Red,Green,Blue)
when is_binary(Red),is_binary(Green),is_binary(Blue) ->
?CLASS(ThisT,wxPalette),
@@ -60,38 +64,43 @@ create(#wx_ref{type=ThisT,ref=ThisRef},Red,Green,Blue)
wxe_util:call(?wxPalette_Create,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPalette()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettegetcolourscount">external documentation</a>.
+-spec getColoursCount(This) -> integer() when
+ This::wxPalette().
getColoursCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPalette),
wxe_util:call(?wxPalette_GetColoursCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPalette(), Red::integer(), Green::integer(), Blue::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettegetpixel">external documentation</a>.
+-spec getPixel(This, Red, Green, Blue) -> integer() when
+ This::wxPalette(), Red::integer(), Green::integer(), Blue::integer().
getPixel(#wx_ref{type=ThisT,ref=ThisRef},Red,Green,Blue)
when is_integer(Red),is_integer(Green),is_integer(Blue) ->
?CLASS(ThisT,wxPalette),
wxe_util:call(?wxPalette_GetPixel,
<<ThisRef:32/?UI,Red:32/?UI,Green:32/?UI,Blue:32/?UI>>).
-%% @spec (This::wxPalette(), Pixel::integer()) -> {bool(),Red::integer(),Green::integer(),Blue::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpalettegetrgb">external documentation</a>.
+-spec getRGB(This, Pixel) -> Result when
+ Result ::{Res ::boolean(), Red::integer(), Green::integer(), Blue::integer()},
+ This::wxPalette(), Pixel::integer().
getRGB(#wx_ref{type=ThisT,ref=ThisRef},Pixel)
when is_integer(Pixel) ->
?CLASS(ThisT,wxPalette),
wxe_util:call(?wxPalette_GetRGB,
<<ThisRef:32/?UI,Pixel:32/?UI>>).
-%% @spec (This::wxPalette()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalette.html#wxpaletteisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxPalette().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPalette),
wxe_util:call(?wxPalette_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPalette()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPalette()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPalette),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPaletteChangedEvent.erl b/lib/wx/src/gen/wxPaletteChangedEvent.erl
index 1831bf1375..aa9ae68ec2 100644
--- a/lib/wx/src/gen/wxPaletteChangedEvent.erl
+++ b/lib/wx/src/gen/wxPaletteChangedEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 +37,24 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxPaletteChangedEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxPaletteChangedEvent(), Win::wxWindow:wxWindow()) -> ok
+-type wxPaletteChangedEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalettechangedevent.html#wxpalettechangedeventsetchangedwindow">external documentation</a>.
+-spec setChangedWindow(This, Win) -> ok when
+ This::wxPaletteChangedEvent(), Win::wxWindow:wxWindow().
setChangedWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(ThisT,wxPaletteChangedEvent),
?CLASS(WinT,wxWindow),
wxe_util:cast(?wxPaletteChangedEvent_SetChangedWindow,
<<ThisRef:32/?UI,WinRef:32/?UI>>).
-%% @spec (This::wxPaletteChangedEvent()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpalettechangedevent.html#wxpalettechangedeventgetchangedwindow">external documentation</a>.
+-spec getChangedWindow(This) -> wxWindow:wxWindow() when
+ This::wxPaletteChangedEvent().
getChangedWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPaletteChangedEvent),
wxe_util:call(?wxPaletteChangedEvent_GetChangedWindow,
diff --git a/lib/wx/src/gen/wxPanel.erl b/lib/wx/src/gen/wxPanel.erl
index 55eaa9f404..88c1b119a8 100644
--- a/lib/wx/src/gen/wxPanel.erl
+++ b/lib/wx/src/gen/wxPanel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +68,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxPanel/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPanel()
+-type wxPanel() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpanel.html#wxpanelwxpanel">external documentation</a>.
+-spec new() -> wxPanel().
new() ->
wxe_util:construct(?wxPanel_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxPanel()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxPanel() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxPanel()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpanel.html#wxpanelwxpanel">external documentation</a>.
+-spec new(Parent, [Option]) -> wxPanel() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {winid, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -100,15 +108,18 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxPanel_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Parent::wxWindow:wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer()) -> wxPanel()
%% @equiv new(Parent,X,Y,Width,Height, [])
+-spec new(Parent, X, Y, Width, Height) -> wxPanel() when
+ Parent::wxWindow:wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer().
+
new(Parent,X,Y,Width,Height)
when is_record(Parent, wx_ref),is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height) ->
new(Parent,X,Y,Width,Height, []).
-%% @spec (Parent::wxWindow:wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer(), [Option]) -> wxPanel()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpanel.html#wxpanelwxpanel">external documentation</a>.
+-spec new(Parent, X, Y, Width, Height, [Option]) -> wxPanel() when
+ Parent::wxWindow:wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer(),
+ Option :: {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},X,Y,Width,Height, Options)
when is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -118,15 +129,16 @@ new(#wx_ref{type=ParentT,ref=ParentRef},X,Y,Width,Height, Options)
wxe_util:construct(?wxPanel_new_6,
<<ParentRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxPanel()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpanel.html#wxpanelinitdialog">external documentation</a>.
+-spec initDialog(This) -> ok when
+ This::wxPanel().
initDialog(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPanel),
wxe_util:cast(?wxPanel_InitDialog,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPanel()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPanel()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPanel),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPasswordEntryDialog.erl b/lib/wx/src/gen/wxPasswordEntryDialog.erl
index f79734ab46..d5a9f6150a 100644
--- a/lib/wx/src/gen/wxPasswordEntryDialog.erl
+++ b/lib/wx/src/gen/wxPasswordEntryDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +79,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxPasswordEntryDialog/0]).
%% @hidden
parent_class(wxTextEntryDialog) -> true;
parent_class(wxDialog) -> true;
@@ -87,15 +88,22 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string()) -> wxPasswordEntryDialog()
+-type wxPasswordEntryDialog() :: wx:wx_object().
%% @equiv new(Parent,Message, [])
+-spec new(Parent, Message) -> wxPasswordEntryDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata().
+
new(Parent,Message)
when is_record(Parent, wx_ref),is_list(Message) ->
new(Parent,Message, []).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), [Option]) -> wxPasswordEntryDialog()
-%% Option = {caption, string()} | {value, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpasswordentrydialog.html#wxpasswordentrydialogwxpasswordentrydialog">external documentation</a>.
+-spec new(Parent, Message, [Option]) -> wxPasswordEntryDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(),
+ Option :: {caption, unicode:chardata()}
+ | {value, unicode:chardata()}
+ | {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
when is_list(Message),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -109,8 +117,8 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
wxe_util:construct(?wxPasswordEntryDialog_new,
<<ParentRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxPasswordEntryDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPasswordEntryDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPasswordEntryDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPen.erl b/lib/wx/src/gen/wxPen.erl
index ada95b0ee3..8b8aafddba 100644
--- a/lib/wx/src/gen/wxPen.erl
+++ b/lib/wx/src/gen/wxPen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,24 +31,30 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPen/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPen()
+-type wxPen() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpenwxpen">external documentation</a>.
+-spec new() -> wxPen().
new() ->
wxe_util:construct(?wxPen_new_0,
<<>>).
-%% @spec (Colour::wx:colour()) -> wxPen()
%% @equiv new(Colour, [])
+-spec new(Colour) -> wxPen() when
+ Colour::wx:wx_colour().
+
new(Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
new(Colour, []).
-%% @spec (Colour::wx:colour(), [Option]) -> wxPen()
-%% Option = {width, integer()} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpenwxpen">external documentation</a>.
+-spec new(Colour, [Option]) -> wxPen() when
+ Colour::wx:wx_colour(),
+ Option :: {width, integer()}
+ | {style, integer()}.
new(Colour, Options)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4,is_list(Options) ->
MOpts = fun({width, Width}, Acc) -> [<<1:32/?UI,Width:32/?UI>>|Acc];
@@ -58,98 +64,110 @@ new(Colour, Options)
wxe_util:construct(?wxPen_new_2,
<<(wxe_util:colour_bin(Colour)):16/binary, BinOpt/binary>>).
-%% @spec (This::wxPen()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpengetcap">external documentation</a>.
+-spec getCap(This) -> integer() when
+ This::wxPen().
getCap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPen),
wxe_util:call(?wxPen_GetCap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPen()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpengetcolour">external documentation</a>.
+-spec getColour(This) -> wx:wx_colour4() when
+ This::wxPen().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPen),
wxe_util:call(?wxPen_GetColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPen()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpengetjoin">external documentation</a>.
+-spec getJoin(This) -> integer() when
+ This::wxPen().
getJoin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPen),
wxe_util:call(?wxPen_GetJoin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPen()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpengetstyle">external documentation</a>.
+-spec getStyle(This) -> integer() when
+ This::wxPen().
getStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPen),
wxe_util:call(?wxPen_GetStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPen()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpengetwidth">external documentation</a>.
+-spec getWidth(This) -> integer() when
+ This::wxPen().
getWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPen),
wxe_util:call(?wxPen_GetWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPen()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpenisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxPen().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPen),
wxe_util:call(?wxPen_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPen(), CapStyle::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpensetcap">external documentation</a>.
+-spec setCap(This, CapStyle) -> ok when
+ This::wxPen(), CapStyle::integer().
setCap(#wx_ref{type=ThisT,ref=ThisRef},CapStyle)
when is_integer(CapStyle) ->
?CLASS(ThisT,wxPen),
wxe_util:cast(?wxPen_SetCap,
<<ThisRef:32/?UI,CapStyle:32/?UI>>).
-%% @spec (This::wxPen(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpensetcolour">external documentation</a>.
+-spec setColour(This, Colour) -> ok when
+ This::wxPen(), Colour::wx:wx_colour().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxPen),
wxe_util:cast(?wxPen_SetColour_1,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxPen(), Red::integer(), Green::integer(), Blue::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpensetcolour">external documentation</a>.
+-spec setColour(This, Red, Green, Blue) -> ok when
+ This::wxPen(), Red::integer(), Green::integer(), Blue::integer().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Red,Green,Blue)
when is_integer(Red),is_integer(Green),is_integer(Blue) ->
?CLASS(ThisT,wxPen),
wxe_util:cast(?wxPen_SetColour_3,
<<ThisRef:32/?UI,Red:32/?UI,Green:32/?UI,Blue:32/?UI>>).
-%% @spec (This::wxPen(), JoinStyle::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpensetjoin">external documentation</a>.
+-spec setJoin(This, JoinStyle) -> ok when
+ This::wxPen(), JoinStyle::integer().
setJoin(#wx_ref{type=ThisT,ref=ThisRef},JoinStyle)
when is_integer(JoinStyle) ->
?CLASS(ThisT,wxPen),
wxe_util:cast(?wxPen_SetJoin,
<<ThisRef:32/?UI,JoinStyle:32/?UI>>).
-%% @spec (This::wxPen(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpensetstyle">external documentation</a>.
+-spec setStyle(This, Style) -> ok when
+ This::wxPen(), Style::integer().
setStyle(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxPen),
wxe_util:cast(?wxPen_SetStyle,
<<ThisRef:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxPen(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpen.html#wxpensetwidth">external documentation</a>.
+-spec setWidth(This, Width) -> ok when
+ This::wxPen(), Width::integer().
setWidth(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxPen),
wxe_util:cast(?wxPen_SetWidth,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxPen()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPen()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPen),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPickerBase.erl b/lib/wx/src/gen/wxPickerBase.erl
index e60ab4f9d8..2253127d84 100644
--- a/lib/wx/src/gen/wxPickerBase.erl
+++ b/lib/wx/src/gen/wxPickerBase.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,87 +72,101 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxPickerBase/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxPickerBase(), Newmargin::integer()) -> ok
+-type wxPickerBase() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasesetinternalmargin">external documentation</a>.
+-spec setInternalMargin(This, Newmargin) -> ok when
+ This::wxPickerBase(), Newmargin::integer().
setInternalMargin(#wx_ref{type=ThisT,ref=ThisRef},Newmargin)
when is_integer(Newmargin) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:cast(?wxPickerBase_SetInternalMargin,
<<ThisRef:32/?UI,Newmargin:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasegetinternalmargin">external documentation</a>.
+-spec getInternalMargin(This) -> integer() when
+ This::wxPickerBase().
getInternalMargin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_GetInternalMargin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPickerBase(), Prop::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasesettextctrlproportion">external documentation</a>.
+-spec setTextCtrlProportion(This, Prop) -> ok when
+ This::wxPickerBase(), Prop::integer().
setTextCtrlProportion(#wx_ref{type=ThisT,ref=ThisRef},Prop)
when is_integer(Prop) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:cast(?wxPickerBase_SetTextCtrlProportion,
<<ThisRef:32/?UI,Prop:32/?UI>>).
-%% @spec (This::wxPickerBase(), Prop::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasesetpickerctrlproportion">external documentation</a>.
+-spec setPickerCtrlProportion(This, Prop) -> ok when
+ This::wxPickerBase(), Prop::integer().
setPickerCtrlProportion(#wx_ref{type=ThisT,ref=ThisRef},Prop)
when is_integer(Prop) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:cast(?wxPickerBase_SetPickerCtrlProportion,
<<ThisRef:32/?UI,Prop:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasegettextctrlproportion">external documentation</a>.
+-spec getTextCtrlProportion(This) -> integer() when
+ This::wxPickerBase().
getTextCtrlProportion(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_GetTextCtrlProportion,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasegetpickerctrlproportion">external documentation</a>.
+-spec getPickerCtrlProportion(This) -> integer() when
+ This::wxPickerBase().
getPickerCtrlProportion(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_GetPickerCtrlProportion,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasehastextctrl">external documentation</a>.
+-spec hasTextCtrl(This) -> boolean() when
+ This::wxPickerBase().
hasTextCtrl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_HasTextCtrl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> wxTextCtrl:wxTextCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasegettextctrl">external documentation</a>.
+-spec getTextCtrl(This) -> wxTextCtrl:wxTextCtrl() when
+ This::wxPickerBase().
getTextCtrl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_GetTextCtrl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbaseistextctrlgrowable">external documentation</a>.
+-spec isTextCtrlGrowable(This) -> boolean() when
+ This::wxPickerBase().
isTextCtrlGrowable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_IsTextCtrlGrowable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPickerBase()) -> ok
%% @equiv setPickerCtrlGrowable(This, [])
+-spec setPickerCtrlGrowable(This) -> ok when
+ This::wxPickerBase().
+
setPickerCtrlGrowable(This)
when is_record(This, wx_ref) ->
setPickerCtrlGrowable(This, []).
-%% @spec (This::wxPickerBase(), [Option]) -> ok
-%% Option = {grow, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasesetpickerctrlgrowable">external documentation</a>.
+-spec setPickerCtrlGrowable(This, [Option]) -> ok when
+ This::wxPickerBase(),
+ Option :: {grow, boolean()}.
setPickerCtrlGrowable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxPickerBase),
@@ -162,15 +176,18 @@ setPickerCtrlGrowable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxPickerBase_SetPickerCtrlGrowable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxPickerBase()) -> ok
%% @equiv setTextCtrlGrowable(This, [])
+-spec setTextCtrlGrowable(This) -> ok when
+ This::wxPickerBase().
+
setTextCtrlGrowable(This)
when is_record(This, wx_ref) ->
setTextCtrlGrowable(This, []).
-%% @spec (This::wxPickerBase(), [Option]) -> ok
-%% Option = {grow, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbasesettextctrlgrowable">external documentation</a>.
+-spec setTextCtrlGrowable(This, [Option]) -> ok when
+ This::wxPickerBase(),
+ Option :: {grow, boolean()}.
setTextCtrlGrowable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxPickerBase),
@@ -180,8 +197,9 @@ setTextCtrlGrowable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxPickerBase_SetTextCtrlGrowable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxPickerBase()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpickerbase.html#wxpickerbaseispickerctrlgrowable">external documentation</a>.
+-spec isPickerCtrlGrowable(This) -> boolean() when
+ This::wxPickerBase().
isPickerCtrlGrowable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPickerBase),
wxe_util:call(?wxPickerBase_IsPickerCtrlGrowable,
diff --git a/lib/wx/src/gen/wxPostScriptDC.erl b/lib/wx/src/gen/wxPostScriptDC.erl
index df3edfade9..2eb25b6a8e 100644
--- a/lib/wx/src/gen/wxPostScriptDC.erl
+++ b/lib/wx/src/gen/wxPostScriptDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +38,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -52,38 +52,42 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxPostScriptDC/0]).
%% @hidden
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPostScriptDC()
+-type wxPostScriptDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpostscriptdc.html#wxpostscriptdcwxpostscriptdc">external documentation</a>.
+-spec new() -> wxPostScriptDC().
new() ->
wxe_util:construct(?wxPostScriptDC_new_0,
<<>>).
-%% @spec (PrintData::wxPrintData:wxPrintData()) -> wxPostScriptDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpostscriptdc.html#wxpostscriptdcwxpostscriptdc">external documentation</a>.
+-spec new(PrintData) -> wxPostScriptDC() when
+ PrintData::wxPrintData:wxPrintData().
new(#wx_ref{type=PrintDataT,ref=PrintDataRef}) ->
?CLASS(PrintDataT,wxPrintData),
wxe_util:construct(?wxPostScriptDC_new_1,
<<PrintDataRef:32/?UI>>).
-%% @spec (Ppi::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpostscriptdc.html#wxpostscriptdcsetresolution">external documentation</a>.
+-spec setResolution(Ppi) -> ok when
+ Ppi::integer().
setResolution(Ppi)
when is_integer(Ppi) ->
wxe_util:cast(?wxPostScriptDC_SetResolution,
<<Ppi:32/?UI>>).
-%% @spec () -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpostscriptdc.html#wxpostscriptdcgetresolution">external documentation</a>.
+-spec getResolution() -> integer().
getResolution() ->
wxe_util:call(?wxPostScriptDC_GetResolution,
<<>>).
-%% @spec (This::wxPostScriptDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPostScriptDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPostScriptDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -170,11 +174,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -188,7 +192,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxPreviewCanvas.erl b/lib/wx/src/gen/wxPreviewCanvas.erl
index d33aeedb70..cc9f43e5e4 100644
--- a/lib/wx/src/gen/wxPreviewCanvas.erl
+++ b/lib/wx/src/gen/wxPreviewCanvas.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,6 +74,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxPreviewCanvas/0]).
%% @hidden
parent_class(wxScrolledWindow) -> true;
parent_class(wxPanel) -> true;
@@ -81,6 +82,7 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxPreviewCanvas() :: wx:wx_object().
%% From wxScrolledWindow
%% @hidden
setTargetWindow(This,Target) -> wxScrolledWindow:setTargetWindow(This,Target).
diff --git a/lib/wx/src/gen/wxPreviewControlBar.erl b/lib/wx/src/gen/wxPreviewControlBar.erl
index 78d46d1b95..dce3feb9ea 100644
--- a/lib/wx/src/gen/wxPreviewControlBar.erl
+++ b/lib/wx/src/gen/wxPreviewControlBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,21 +70,28 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxPreviewControlBar/0]).
%% @hidden
parent_class(wxPanel) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Preview::wxPrintPreview:wxPrintPreview(), Buttons::integer(), Parent::wxWindow:wxWindow()) -> wxPreviewControlBar()
+-type wxPreviewControlBar() :: wx:wx_object().
%% @equiv new(Preview,Buttons,Parent, [])
+-spec new(Preview, Buttons, Parent) -> wxPreviewControlBar() when
+ Preview::wxPrintPreview:wxPrintPreview(), Buttons::integer(), Parent::wxWindow:wxWindow().
+
new(Preview,Buttons,Parent)
when is_record(Preview, wx_ref),is_integer(Buttons),is_record(Parent, wx_ref) ->
new(Preview,Buttons,Parent, []).
-%% @spec (Preview::wxPrintPreview:wxPrintPreview(), Buttons::integer(), Parent::wxWindow:wxWindow(), [Option]) -> wxPreviewControlBar()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewcontrolbar.html#wxpreviewcontrolbarwxpreviewcontrolbar">external documentation</a>.
+-spec new(Preview, Buttons, Parent, [Option]) -> wxPreviewControlBar() when
+ Preview::wxPrintPreview:wxPrintPreview(), Buttons::integer(), Parent::wxWindow:wxWindow(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=PreviewT,ref=PreviewRef},Buttons,#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_integer(Buttons),is_list(Options) ->
?CLASS(PreviewT,wxPrintPreview),
@@ -97,37 +104,41 @@ new(#wx_ref{type=PreviewT,ref=PreviewRef},Buttons,#wx_ref{type=ParentT,ref=Paren
wxe_util:construct(?wxPreviewControlBar_new,
<<PreviewRef:32/?UI,Buttons:32/?UI,ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxPreviewControlBar()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewcontrolbar.html#wxpreviewcontrolbarcreatebuttons">external documentation</a>.
+-spec createButtons(This) -> ok when
+ This::wxPreviewControlBar().
createButtons(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPreviewControlBar),
wxe_util:cast(?wxPreviewControlBar_CreateButtons,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPreviewControlBar()) -> wxPrintPreview:wxPrintPreview()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewcontrolbar.html#wxpreviewcontrolbargetprintpreview">external documentation</a>.
+-spec getPrintPreview(This) -> wxPrintPreview:wxPrintPreview() when
+ This::wxPreviewControlBar().
getPrintPreview(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPreviewControlBar),
wxe_util:call(?wxPreviewControlBar_GetPrintPreview,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPreviewControlBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewcontrolbar.html#wxpreviewcontrolbargetzoomcontrol">external documentation</a>.
+-spec getZoomControl(This) -> integer() when
+ This::wxPreviewControlBar().
getZoomControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPreviewControlBar),
wxe_util:call(?wxPreviewControlBar_GetZoomControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPreviewControlBar(), Zoom::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewcontrolbar.html#wxpreviewcontrolbarsetzoomcontrol">external documentation</a>.
+-spec setZoomControl(This, Zoom) -> ok when
+ This::wxPreviewControlBar(), Zoom::integer().
setZoomControl(#wx_ref{type=ThisT,ref=ThisRef},Zoom)
when is_integer(Zoom) ->
?CLASS(ThisT,wxPreviewControlBar),
wxe_util:cast(?wxPreviewControlBar_SetZoomControl,
<<ThisRef:32/?UI,Zoom:32/?UI>>).
-%% @spec (This::wxPreviewControlBar()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPreviewControlBar()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPreviewControlBar),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPreviewFrame.erl b/lib/wx/src/gen/wxPreviewFrame.erl
index 91a32e9889..41bb0bf2bb 100644
--- a/lib/wx/src/gen/wxPreviewFrame.erl
+++ b/lib/wx/src/gen/wxPreviewFrame.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +81,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxPreviewFrame/0]).
%% @hidden
parent_class(wxFrame) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -88,15 +89,22 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Preview::wxPrintPreview:wxPrintPreview(), Parent::wxWindow:wxWindow()) -> wxPreviewFrame()
+-type wxPreviewFrame() :: wx:wx_object().
%% @equiv new(Preview,Parent, [])
+-spec new(Preview, Parent) -> wxPreviewFrame() when
+ Preview::wxPrintPreview:wxPrintPreview(), Parent::wxWindow:wxWindow().
+
new(Preview,Parent)
when is_record(Preview, wx_ref),is_record(Parent, wx_ref) ->
new(Preview,Parent, []).
-%% @spec (Preview::wxPrintPreview:wxPrintPreview(), Parent::wxWindow:wxWindow(), [Option]) -> wxPreviewFrame()
-%% Option = {title, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewframe.html#wxpreviewframewxpreviewframe">external documentation</a>.
+-spec new(Preview, Parent, [Option]) -> wxPreviewFrame() when
+ Preview::wxPrintPreview:wxPrintPreview(), Parent::wxWindow:wxWindow(),
+ Option :: {title, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=PreviewT,ref=PreviewRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(PreviewT,wxPrintPreview),
@@ -110,37 +118,41 @@ new(#wx_ref{type=PreviewT,ref=PreviewRef},#wx_ref{type=ParentT,ref=ParentRef}, O
wxe_util:construct(?wxPreviewFrame_new,
<<PreviewRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxPreviewFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewframe.html#wxpreviewframecreatecontrolbar">external documentation</a>.
+-spec createControlBar(This) -> ok when
+ This::wxPreviewFrame().
createControlBar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPreviewFrame),
wxe_util:cast(?wxPreviewFrame_CreateControlBar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPreviewFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewframe.html#wxpreviewframecreatecanvas">external documentation</a>.
+-spec createCanvas(This) -> ok when
+ This::wxPreviewFrame().
createCanvas(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPreviewFrame),
wxe_util:cast(?wxPreviewFrame_CreateCanvas,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPreviewFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewframe.html#wxpreviewframeinitialize">external documentation</a>.
+-spec initialize(This) -> ok when
+ This::wxPreviewFrame().
initialize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPreviewFrame),
wxe_util:cast(?wxPreviewFrame_Initialize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPreviewFrame(), Event::wxCloseEvent:wxCloseEvent()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxpreviewframe.html#wxpreviewframeonclosewindow">external documentation</a>.
+-spec onCloseWindow(This, Event) -> ok when
+ This::wxPreviewFrame(), Event::wxCloseEvent:wxCloseEvent().
onCloseWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=EventT,ref=EventRef}) ->
?CLASS(ThisT,wxPreviewFrame),
?CLASS(EventT,wxCloseEvent),
wxe_util:cast(?wxPreviewFrame_OnCloseWindow,
<<ThisRef:32/?UI,EventRef:32/?UI>>).
-%% @spec (This::wxPreviewFrame()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPreviewFrame()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPreviewFrame),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPrintData.erl b/lib/wx/src/gen/wxPrintData.erl
index f3e8ad3612..2cb8dd3c5f 100644
--- a/lib/wx/src/gen/wxPrintData.erl
+++ b/lib/wx/src/gen/wxPrintData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,158 +32,175 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPrintData/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPrintData()
+-type wxPrintData() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatawxprintdata">external documentation</a>.
+-spec new() -> wxPrintData().
new() ->
wxe_util:construct(?wxPrintData_new_0,
<<>>).
-%% @spec (PrintData::wxPrintData()) -> wxPrintData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatawxprintdata">external documentation</a>.
+-spec new(PrintData) -> wxPrintData() when
+ PrintData::wxPrintData().
new(#wx_ref{type=PrintDataT,ref=PrintDataRef}) ->
?CLASS(PrintDataT,wxPrintData),
wxe_util:construct(?wxPrintData_new_1,
<<PrintDataRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetcollate">external documentation</a>.
+-spec getCollate(This) -> boolean() when
+ This::wxPrintData().
getCollate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetCollate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> WxPrintBin
-%% WxPrintBin = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetbin">external documentation</a>.
-%%<br /> WxPrintBin is one of ?wxPRINTBIN_DEFAULT | ?wxPRINTBIN_ONLYONE | ?wxPRINTBIN_LOWER | ?wxPRINTBIN_MIDDLE | ?wxPRINTBIN_MANUAL | ?wxPRINTBIN_ENVELOPE | ?wxPRINTBIN_ENVMANUAL | ?wxPRINTBIN_AUTO | ?wxPRINTBIN_TRACTOR | ?wxPRINTBIN_SMALLFMT | ?wxPRINTBIN_LARGEFMT | ?wxPRINTBIN_LARGECAPACITY | ?wxPRINTBIN_CASSETTE | ?wxPRINTBIN_FORMSOURCE | ?wxPRINTBIN_USER
+%%<br /> Res = ?wxPRINTBIN_DEFAULT | ?wxPRINTBIN_ONLYONE | ?wxPRINTBIN_LOWER | ?wxPRINTBIN_MIDDLE | ?wxPRINTBIN_MANUAL | ?wxPRINTBIN_ENVELOPE | ?wxPRINTBIN_ENVMANUAL | ?wxPRINTBIN_AUTO | ?wxPRINTBIN_TRACTOR | ?wxPRINTBIN_SMALLFMT | ?wxPRINTBIN_LARGEFMT | ?wxPRINTBIN_LARGECAPACITY | ?wxPRINTBIN_CASSETTE | ?wxPRINTBIN_FORMSOURCE | ?wxPRINTBIN_USER
+-spec getBin(This) -> wx:wx_enum() when
+ This::wxPrintData().
getBin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetBin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetcolour">external documentation</a>.
+-spec getColour(This) -> boolean() when
+ This::wxPrintData().
getColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> WxDuplexMode
-%% WxDuplexMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetduplex">external documentation</a>.
-%%<br /> WxDuplexMode is one of ?wxDUPLEX_SIMPLEX | ?wxDUPLEX_HORIZONTAL | ?wxDUPLEX_VERTICAL
+%%<br /> Res = ?wxDUPLEX_SIMPLEX | ?wxDUPLEX_HORIZONTAL | ?wxDUPLEX_VERTICAL
+-spec getDuplex(This) -> wx:wx_enum() when
+ This::wxPrintData().
getDuplex(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetDuplex,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetnocopies">external documentation</a>.
+-spec getNoCopies(This) -> integer() when
+ This::wxPrintData().
getNoCopies(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetNoCopies,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetorientation">external documentation</a>.
+-spec getOrientation(This) -> integer() when
+ This::wxPrintData().
getOrientation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetOrientation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetpaperid">external documentation</a>.
+-spec getPaperId(This) -> integer() when
+ This::wxPrintData().
getPaperId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetPaperId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetprintername">external documentation</a>.
+-spec getPrinterName(This) -> unicode:charlist() when
+ This::wxPrintData().
getPrinterName(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetPrinterName,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatagetquality">external documentation</a>.
+-spec getQuality(This) -> integer() when
+ This::wxPrintData().
getQuality(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_GetQuality,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdataisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxPrintData().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintData),
wxe_util:call(?wxPrintData_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintData(), Bin::WxPrintBin) -> ok
-%% WxPrintBin = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetbin">external documentation</a>.
-%%<br /> WxPrintBin is one of ?wxPRINTBIN_DEFAULT | ?wxPRINTBIN_ONLYONE | ?wxPRINTBIN_LOWER | ?wxPRINTBIN_MIDDLE | ?wxPRINTBIN_MANUAL | ?wxPRINTBIN_ENVELOPE | ?wxPRINTBIN_ENVMANUAL | ?wxPRINTBIN_AUTO | ?wxPRINTBIN_TRACTOR | ?wxPRINTBIN_SMALLFMT | ?wxPRINTBIN_LARGEFMT | ?wxPRINTBIN_LARGECAPACITY | ?wxPRINTBIN_CASSETTE | ?wxPRINTBIN_FORMSOURCE | ?wxPRINTBIN_USER
+%%<br /> Bin = ?wxPRINTBIN_DEFAULT | ?wxPRINTBIN_ONLYONE | ?wxPRINTBIN_LOWER | ?wxPRINTBIN_MIDDLE | ?wxPRINTBIN_MANUAL | ?wxPRINTBIN_ENVELOPE | ?wxPRINTBIN_ENVMANUAL | ?wxPRINTBIN_AUTO | ?wxPRINTBIN_TRACTOR | ?wxPRINTBIN_SMALLFMT | ?wxPRINTBIN_LARGEFMT | ?wxPRINTBIN_LARGECAPACITY | ?wxPRINTBIN_CASSETTE | ?wxPRINTBIN_FORMSOURCE | ?wxPRINTBIN_USER
+-spec setBin(This, Bin) -> ok when
+ This::wxPrintData(), Bin::wx:wx_enum().
setBin(#wx_ref{type=ThisT,ref=ThisRef},Bin)
when is_integer(Bin) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetBin,
<<ThisRef:32/?UI,Bin:32/?UI>>).
-%% @spec (This::wxPrintData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetcollate">external documentation</a>.
+-spec setCollate(This, Flag) -> ok when
+ This::wxPrintData(), Flag::boolean().
setCollate(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetCollate,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintData(), Colour::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetcolour">external documentation</a>.
+-spec setColour(This, Colour) -> ok when
+ This::wxPrintData(), Colour::boolean().
setColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when is_boolean(Colour) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetColour,
<<ThisRef:32/?UI,(wxe_util:from_bool(Colour)):32/?UI>>).
-%% @spec (This::wxPrintData(), Duplex::WxDuplexMode) -> ok
-%% WxDuplexMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetduplex">external documentation</a>.
-%%<br /> WxDuplexMode is one of ?wxDUPLEX_SIMPLEX | ?wxDUPLEX_HORIZONTAL | ?wxDUPLEX_VERTICAL
+%%<br /> Duplex = ?wxDUPLEX_SIMPLEX | ?wxDUPLEX_HORIZONTAL | ?wxDUPLEX_VERTICAL
+-spec setDuplex(This, Duplex) -> ok when
+ This::wxPrintData(), Duplex::wx:wx_enum().
setDuplex(#wx_ref{type=ThisT,ref=ThisRef},Duplex)
when is_integer(Duplex) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetDuplex,
<<ThisRef:32/?UI,Duplex:32/?UI>>).
-%% @spec (This::wxPrintData(), V::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetnocopies">external documentation</a>.
+-spec setNoCopies(This, V) -> ok when
+ This::wxPrintData(), V::integer().
setNoCopies(#wx_ref{type=ThisT,ref=ThisRef},V)
when is_integer(V) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetNoCopies,
<<ThisRef:32/?UI,V:32/?UI>>).
-%% @spec (This::wxPrintData(), Orient::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetorientation">external documentation</a>.
+-spec setOrientation(This, Orient) -> ok when
+ This::wxPrintData(), Orient::integer().
setOrientation(#wx_ref{type=ThisT,ref=ThisRef},Orient)
when is_integer(Orient) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetOrientation,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxPrintData(), SizeId::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetpaperid">external documentation</a>.
+-spec setPaperId(This, SizeId) -> ok when
+ This::wxPrintData(), SizeId::integer().
setPaperId(#wx_ref{type=ThisT,ref=ThisRef},SizeId)
when is_integer(SizeId) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetPaperId,
<<ThisRef:32/?UI,SizeId:32/?UI>>).
-%% @spec (This::wxPrintData(), Name::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetprintername">external documentation</a>.
+-spec setPrinterName(This, Name) -> ok when
+ This::wxPrintData(), Name::unicode:chardata().
setPrinterName(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxPrintData),
@@ -191,16 +208,17 @@ setPrinterName(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:cast(?wxPrintData_SetPrinterName,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxPrintData(), Quality::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdata.html#wxprintdatasetquality">external documentation</a>.
+-spec setQuality(This, Quality) -> ok when
+ This::wxPrintData(), Quality::integer().
setQuality(#wx_ref{type=ThisT,ref=ThisRef},Quality)
when is_integer(Quality) ->
?CLASS(ThisT,wxPrintData),
wxe_util:cast(?wxPrintData_SetQuality,
<<ThisRef:32/?UI,Quality:32/?UI>>).
-%% @spec (This::wxPrintData()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPrintData()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPrintData),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPrintDialog.erl b/lib/wx/src/gen/wxPrintDialog.erl
index a2f4bfa4eb..34c8310e12 100644
--- a/lib/wx/src/gen/wxPrintDialog.erl
+++ b/lib/wx/src/gen/wxPrintDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxPrintDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,22 +85,25 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxPrintDialog()
+-type wxPrintDialog() :: wx:wx_object().
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxPrintDialog() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(),X::term()) -> wxPrintDialog()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialog.html#wxprintdialogwxprintdialog">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Parent::wxWindow:wxWindow(), [Option]) -> wxPrintDialog() </c>
-%%<br /> Option = {data, wxPrintDialogData:wxPrintDialogData()}
-%% </p>
-%% <p><c>
-%% new(Parent::wxWindow:wxWindow(), Data::wxPrintData:wxPrintData()) -> wxPrintDialog() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Parent, Data) -> wxPrintDialog() when<br />
+%% Parent::wxWindow:wxWindow(), Data::wxPrintData:wxPrintData().<br />
+%%
+-spec new(Parent, [Option]) -> wxPrintDialog() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {data, wxPrintDialogData:wxPrintDialogData()};
+ (Parent, Data) -> wxPrintDialog() when
+ Parent::wxWindow:wxWindow(), Data::wxPrintData:wxPrintData().
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -114,22 +118,24 @@ new(#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=DataT,ref=DataRef}) ->
wxe_util:construct(?wxPrintDialog_new_2_1,
<<ParentRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxPrintDialog()) -> wxPrintDialogData:wxPrintDialogData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialog.html#wxprintdialoggetprintdialogdata">external documentation</a>.
+-spec getPrintDialogData(This) -> wxPrintDialogData:wxPrintDialogData() when
+ This::wxPrintDialog().
getPrintDialogData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialog),
wxe_util:call(?wxPrintDialog_GetPrintDialogData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialog()) -> wxDC:wxDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialog.html#wxprintdialoggetprintdc">external documentation</a>.
+-spec getPrintDC(This) -> wxDC:wxDC() when
+ This::wxPrintDialog().
getPrintDC(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialog),
wxe_util:call(?wxPrintDialog_GetPrintDC,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPrintDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPrintDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPrintDialogData.erl b/lib/wx/src/gen/wxPrintDialogData.erl
index a7e8d41f2e..3368349164 100644
--- a/lib/wx/src/gen/wxPrintDialogData.erl
+++ b/lib/wx/src/gen/wxPrintDialogData.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,17 +33,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPrintDialogData/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPrintDialogData()
+-type wxPrintDialogData() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatawxprintdialogdata">external documentation</a>.
+-spec new() -> wxPrintDialogData().
new() ->
wxe_util:construct(?wxPrintDialogData_new_0,
<<>>).
-%% @spec (DialogData::wxPrintDialogData() | wxPrintData:wxPrintData()) -> wxPrintDialogData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatawxprintdialogdata">external documentation</a>.
+-spec new(DialogData) -> wxPrintDialogData() when
+ DialogData::wxPrintDialogData() | wxPrintData:wxPrintData().
new(#wx_ref{type=DialogDataT,ref=DialogDataRef}) ->
DialogDataOP = case ?CLASS_T(DialogDataT,wxPrintDialogData) of
true ->
@@ -54,189 +57,213 @@ new(#wx_ref{type=DialogDataT,ref=DialogDataRef}) ->
wxe_util:construct(DialogDataOP,
<<DialogDataRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdataenablehelp">external documentation</a>.
+-spec enableHelp(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
enableHelp(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_EnableHelp,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdataenablepagenumbers">external documentation</a>.
+-spec enablePageNumbers(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
enablePageNumbers(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_EnablePageNumbers,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdataenableprinttofile">external documentation</a>.
+-spec enablePrintToFile(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
enablePrintToFile(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_EnablePrintToFile,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdataenableselection">external documentation</a>.
+-spec enableSelection(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
enableSelection(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_EnableSelection,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetallpages">external documentation</a>.
+-spec getAllPages(This) -> boolean() when
+ This::wxPrintDialogData().
getAllPages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetAllPages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetcollate">external documentation</a>.
+-spec getCollate(This) -> boolean() when
+ This::wxPrintDialogData().
getCollate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetCollate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetfrompage">external documentation</a>.
+-spec getFromPage(This) -> integer() when
+ This::wxPrintDialogData().
getFromPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetFromPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetmaxpage">external documentation</a>.
+-spec getMaxPage(This) -> integer() when
+ This::wxPrintDialogData().
getMaxPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetMaxPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetminpage">external documentation</a>.
+-spec getMinPage(This) -> integer() when
+ This::wxPrintDialogData().
getMinPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetMinPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetnocopies">external documentation</a>.
+-spec getNoCopies(This) -> integer() when
+ This::wxPrintDialogData().
getNoCopies(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetNoCopies,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> wxPrintData:wxPrintData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetprintdata">external documentation</a>.
+-spec getPrintData(This) -> wxPrintData:wxPrintData() when
+ This::wxPrintDialogData().
getPrintData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetPrintData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetprinttofile">external documentation</a>.
+-spec getPrintToFile(This) -> boolean() when
+ This::wxPrintDialogData().
getPrintToFile(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetPrintToFile,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagetselection">external documentation</a>.
+-spec getSelection(This) -> boolean() when
+ This::wxPrintDialogData().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatagettopage">external documentation</a>.
+-spec getToPage(This) -> integer() when
+ This::wxPrintDialogData().
getToPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_GetToPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdataisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxPrintDialogData().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:call(?wxPrintDialogData_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetcollate">external documentation</a>.
+-spec setCollate(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
setCollate(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetCollate,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData(), V::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetfrompage">external documentation</a>.
+-spec setFromPage(This, V) -> ok when
+ This::wxPrintDialogData(), V::integer().
setFromPage(#wx_ref{type=ThisT,ref=ThisRef},V)
when is_integer(V) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetFromPage,
<<ThisRef:32/?UI,V:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), V::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetmaxpage">external documentation</a>.
+-spec setMaxPage(This, V) -> ok when
+ This::wxPrintDialogData(), V::integer().
setMaxPage(#wx_ref{type=ThisT,ref=ThisRef},V)
when is_integer(V) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetMaxPage,
<<ThisRef:32/?UI,V:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), V::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetminpage">external documentation</a>.
+-spec setMinPage(This, V) -> ok when
+ This::wxPrintDialogData(), V::integer().
setMinPage(#wx_ref{type=ThisT,ref=ThisRef},V)
when is_integer(V) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetMinPage,
<<ThisRef:32/?UI,V:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), V::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetnocopies">external documentation</a>.
+-spec setNoCopies(This, V) -> ok when
+ This::wxPrintDialogData(), V::integer().
setNoCopies(#wx_ref{type=ThisT,ref=ThisRef},V)
when is_integer(V) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetNoCopies,
<<ThisRef:32/?UI,V:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), PrintData::wxPrintData:wxPrintData()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetprintdata">external documentation</a>.
+-spec setPrintData(This, PrintData) -> ok when
+ This::wxPrintDialogData(), PrintData::wxPrintData:wxPrintData().
setPrintData(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PrintDataT,ref=PrintDataRef}) ->
?CLASS(ThisT,wxPrintDialogData),
?CLASS(PrintDataT,wxPrintData),
wxe_util:cast(?wxPrintDialogData_SetPrintData,
<<ThisRef:32/?UI,PrintDataRef:32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetprinttofile">external documentation</a>.
+-spec setPrintToFile(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
setPrintToFile(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetPrintToFile,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData(), Flag::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasetselection">external documentation</a>.
+-spec setSelection(This, Flag) -> ok when
+ This::wxPrintDialogData(), Flag::boolean().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_boolean(Flag) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetSelection,
<<ThisRef:32/?UI,(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (This::wxPrintDialogData(), V::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintdialogdata.html#wxprintdialogdatasettopage">external documentation</a>.
+-spec setToPage(This, V) -> ok when
+ This::wxPrintDialogData(), V::integer().
setToPage(#wx_ref{type=ThisT,ref=ThisRef},V)
when is_integer(V) ->
?CLASS(ThisT,wxPrintDialogData),
wxe_util:cast(?wxPrintDialogData_SetToPage,
<<ThisRef:32/?UI,V:32/?UI>>).
-%% @spec (This::wxPrintDialogData()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPrintDialogData()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPrintDialogData),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPrintPreview.erl b/lib/wx/src/gen/wxPrintPreview.erl
index 6f9a0f653f..49ab506526 100644
--- a/lib/wx/src/gen/wxPrintPreview.erl
+++ b/lib/wx/src/gen/wxPrintPreview.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +32,24 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPrintPreview/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Printout::wxPrintout:wxPrintout()) -> wxPrintPreview()
+-type wxPrintPreview() :: wx:wx_object().
%% @equiv new(Printout, [])
+-spec new(Printout) -> wxPrintPreview() when
+ Printout::wxPrintout:wxPrintout().
+
new(Printout)
when is_record(Printout, wx_ref) ->
new(Printout, []).
-%% @spec (Printout::wxPrintout:wxPrintout(), [Option]) -> wxPrintPreview()
-%% Option = {printoutForPrinting, wxPrintout:wxPrintout()} | {data, wxPrintDialogData:wxPrintDialogData()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewwxprintpreview">external documentation</a>.
+-spec new(Printout, [Option]) -> wxPrintPreview() when
+ Printout::wxPrintout:wxPrintout(),
+ Option :: {printoutForPrinting, wxPrintout:wxPrintout()}
+ | {data, wxPrintDialogData:wxPrintDialogData()}.
new(#wx_ref{type=PrintoutT,ref=PrintoutRef}, Options)
when is_list(Options) ->
?CLASS(PrintoutT,wxPrintout),
@@ -54,8 +60,9 @@ new(#wx_ref{type=PrintoutT,ref=PrintoutRef}, Options)
wxe_util:construct(?wxPrintPreview_new_2,
<<PrintoutRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Printout::wxPrintout:wxPrintout(), PrintoutForPrinting::wxPrintout:wxPrintout(), Data::wxPrintData:wxPrintData()) -> wxPrintPreview()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewwxprintpreview">external documentation</a>.
+-spec new(Printout, PrintoutForPrinting, Data) -> wxPrintPreview() when
+ Printout::wxPrintout:wxPrintout(), PrintoutForPrinting::wxPrintout:wxPrintout(), Data::wxPrintData:wxPrintData().
new(#wx_ref{type=PrintoutT,ref=PrintoutRef},#wx_ref{type=PrintoutForPrintingT,ref=PrintoutForPrintingRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(PrintoutT,wxPrintout),
?CLASS(PrintoutForPrintingT,wxPrintout),
@@ -63,64 +70,73 @@ new(#wx_ref{type=PrintoutT,ref=PrintoutRef},#wx_ref{type=PrintoutForPrintingT,re
wxe_util:construct(?wxPrintPreview_new_3,
<<PrintoutRef:32/?UI,PrintoutForPrintingRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> wxPreviewCanvas:wxPreviewCanvas()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetcanvas">external documentation</a>.
+-spec getCanvas(This) -> wxPreviewCanvas:wxPreviewCanvas() when
+ This::wxPrintPreview().
getCanvas(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetCanvas,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetcurrentpage">external documentation</a>.
+-spec getCurrentPage(This) -> integer() when
+ This::wxPrintPreview().
getCurrentPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetCurrentPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> wxFrame:wxFrame()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetframe">external documentation</a>.
+-spec getFrame(This) -> wxFrame:wxFrame() when
+ This::wxPrintPreview().
getFrame(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetFrame,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetmaxpage">external documentation</a>.
+-spec getMaxPage(This) -> integer() when
+ This::wxPrintPreview().
getMaxPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetMaxPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetminpage">external documentation</a>.
+-spec getMinPage(This) -> integer() when
+ This::wxPrintPreview().
getMinPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetMinPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> wxPrintout:wxPrintout()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetprintout">external documentation</a>.
+-spec getPrintout(This) -> wxPrintout:wxPrintout() when
+ This::wxPrintPreview().
getPrintout(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetPrintout,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> wxPrintout:wxPrintout()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewgetprintoutforprinting">external documentation</a>.
+-spec getPrintoutForPrinting(This) -> wxPrintout:wxPrintout() when
+ This::wxPrintPreview().
getPrintoutForPrinting(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_GetPrintoutForPrinting,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxPrintPreview().
isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_IsOk,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintPreview(), Canvas::wxPreviewCanvas:wxPreviewCanvas(), Dc::wxDC:wxDC()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewpaintpage">external documentation</a>.
+-spec paintPage(This, Canvas, Dc) -> boolean() when
+ This::wxPrintPreview(), Canvas::wxPreviewCanvas:wxPreviewCanvas(), Dc::wxDC:wxDC().
paintPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CanvasT,ref=CanvasRef},#wx_ref{type=DcT,ref=DcRef}) ->
?CLASS(ThisT,wxPrintPreview),
?CLASS(CanvasT,wxPreviewCanvas),
@@ -128,64 +144,71 @@ paintPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CanvasT,ref=CanvasRef},#w
wxe_util:call(?wxPrintPreview_PaintPage,
<<ThisRef:32/?UI,CanvasRef:32/?UI,DcRef:32/?UI>>).
-%% @spec (This::wxPrintPreview(), Interactive::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewprint">external documentation</a>.
+-spec print(This, Interactive) -> boolean() when
+ This::wxPrintPreview(), Interactive::boolean().
print(#wx_ref{type=ThisT,ref=ThisRef},Interactive)
when is_boolean(Interactive) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_Print,
<<ThisRef:32/?UI,(wxe_util:from_bool(Interactive)):32/?UI>>).
-%% @spec (This::wxPrintPreview(), PageNum::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewrenderpage">external documentation</a>.
+-spec renderPage(This, PageNum) -> boolean() when
+ This::wxPrintPreview(), PageNum::integer().
renderPage(#wx_ref{type=ThisT,ref=ThisRef},PageNum)
when is_integer(PageNum) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_RenderPage,
<<ThisRef:32/?UI,PageNum:32/?UI>>).
-%% @spec (This::wxPrintPreview(), Canvas::wxPreviewCanvas:wxPreviewCanvas()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewsetcanvas">external documentation</a>.
+-spec setCanvas(This, Canvas) -> ok when
+ This::wxPrintPreview(), Canvas::wxPreviewCanvas:wxPreviewCanvas().
setCanvas(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CanvasT,ref=CanvasRef}) ->
?CLASS(ThisT,wxPrintPreview),
?CLASS(CanvasT,wxPreviewCanvas),
wxe_util:cast(?wxPrintPreview_SetCanvas,
<<ThisRef:32/?UI,CanvasRef:32/?UI>>).
-%% @spec (This::wxPrintPreview(), PageNum::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewsetcurrentpage">external documentation</a>.
+-spec setCurrentPage(This, PageNum) -> boolean() when
+ This::wxPrintPreview(), PageNum::integer().
setCurrentPage(#wx_ref{type=ThisT,ref=ThisRef},PageNum)
when is_integer(PageNum) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:call(?wxPrintPreview_SetCurrentPage,
<<ThisRef:32/?UI,PageNum:32/?UI>>).
-%% @spec (This::wxPrintPreview(), Frame::wxFrame:wxFrame()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewsetframe">external documentation</a>.
+-spec setFrame(This, Frame) -> ok when
+ This::wxPrintPreview(), Frame::wxFrame:wxFrame().
setFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef}) ->
?CLASS(ThisT,wxPrintPreview),
?CLASS(FrameT,wxFrame),
wxe_util:cast(?wxPrintPreview_SetFrame,
<<ThisRef:32/?UI,FrameRef:32/?UI>>).
-%% @spec (This::wxPrintPreview(), Printout::wxPrintout:wxPrintout()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewsetprintout">external documentation</a>.
+-spec setPrintout(This, Printout) -> ok when
+ This::wxPrintPreview(), Printout::wxPrintout:wxPrintout().
setPrintout(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PrintoutT,ref=PrintoutRef}) ->
?CLASS(ThisT,wxPrintPreview),
?CLASS(PrintoutT,wxPrintout),
wxe_util:cast(?wxPrintPreview_SetPrintout,
<<ThisRef:32/?UI,PrintoutRef:32/?UI>>).
-%% @spec (This::wxPrintPreview(), Percent::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintpreview.html#wxprintpreviewsetzoom">external documentation</a>.
+-spec setZoom(This, Percent) -> ok when
+ This::wxPrintPreview(), Percent::integer().
setZoom(#wx_ref{type=ThisT,ref=ThisRef},Percent)
when is_integer(Percent) ->
?CLASS(ThisT,wxPrintPreview),
wxe_util:cast(?wxPrintPreview_SetZoom,
<<ThisRef:32/?UI,Percent:32/?UI>>).
-%% @spec (This::wxPrintPreview()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPrintPreview()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPrintPreview),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPrinter.erl b/lib/wx/src/gen/wxPrinter.erl
index af9afe18af..031483da4d 100644
--- a/lib/wx/src/gen/wxPrinter.erl
+++ b/lib/wx/src/gen/wxPrinter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPrinter/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxPrinter()
+-type wxPrinter() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxPrinter().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxPrinter()
-%% Option = {data, wxPrintDialogData:wxPrintDialogData()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprinterwxprinter">external documentation</a>.
+-spec new([Option]) -> wxPrinter() when
+ Option :: {data, wxPrintDialogData:wxPrintDialogData()}.
new(Options)
when is_list(Options) ->
MOpts = fun({data, #wx_ref{type=DataT,ref=DataRef}}, Acc) -> ?CLASS(DataT,wxPrintDialogData),[<<1:32/?UI,DataRef:32/?UI>>|Acc];
@@ -49,8 +52,9 @@ new(Options)
wxe_util:construct(?wxPrinter_new,
<<BinOpt/binary>>).
-%% @spec (This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprintercreateabortwindow">external documentation</a>.
+-spec createAbortWindow(This, Parent, Printout) -> wxWindow:wxWindow() when
+ This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout().
createAbortWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=PrintoutT,ref=PrintoutRef}) ->
?CLASS(ThisT,wxPrinter),
?CLASS(ParentT,wxWindow),
@@ -58,37 +62,41 @@ createAbortWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=Paren
wxe_util:call(?wxPrinter_CreateAbortWindow,
<<ThisRef:32/?UI,ParentRef:32/?UI,PrintoutRef:32/?UI>>).
-%% @spec (This::wxPrinter()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprintergetabort">external documentation</a>.
+-spec getAbort(This) -> boolean() when
+ This::wxPrinter().
getAbort(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrinter),
wxe_util:call(?wxPrinter_GetAbort,
<<ThisRef:32/?UI>>).
-%% @spec () -> WxPrinterError
-%% WxPrinterError = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprintergetlasterror">external documentation</a>.
-%%<br /> WxPrinterError is one of ?wxPRINTER_NO_ERROR | ?wxPRINTER_CANCELLED | ?wxPRINTER_ERROR
+%%<br /> Res = ?wxPRINTER_NO_ERROR | ?wxPRINTER_CANCELLED | ?wxPRINTER_ERROR
+-spec getLastError() -> wx:wx_enum().
getLastError() ->
wxe_util:call(?wxPrinter_GetLastError,
<<>>).
-%% @spec (This::wxPrinter()) -> wxPrintDialogData:wxPrintDialogData()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprintergetprintdialogdata">external documentation</a>.
+-spec getPrintDialogData(This) -> wxPrintDialogData:wxPrintDialogData() when
+ This::wxPrinter().
getPrintDialogData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrinter),
wxe_util:call(?wxPrinter_GetPrintDialogData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout()) -> bool()
%% @equiv print(This,Parent,Printout, [])
+-spec print(This, Parent, Printout) -> boolean() when
+ This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout().
+
print(This,Parent,Printout)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_record(Printout, wx_ref) ->
print(This,Parent,Printout, []).
-%% @spec (This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout(), [Option]) -> bool()
-%% Option = {prompt, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprinterprint">external documentation</a>.
+-spec print(This, Parent, Printout, [Option]) -> boolean() when
+ This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout(),
+ Option :: {prompt, boolean()}.
print(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=PrintoutT,ref=PrintoutRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxPrinter),
@@ -100,16 +108,18 @@ print(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_re
wxe_util:call(?wxPrinter_Print,
<<ThisRef:32/?UI,ParentRef:32/?UI,PrintoutRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxPrinter(), Parent::wxWindow:wxWindow()) -> wxDC:wxDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprinterprintdialog">external documentation</a>.
+-spec printDialog(This, Parent) -> wxDC:wxDC() when
+ This::wxPrinter(), Parent::wxWindow:wxWindow().
printDialog(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}) ->
?CLASS(ThisT,wxPrinter),
?CLASS(ParentT,wxWindow),
wxe_util:call(?wxPrinter_PrintDialog,
<<ThisRef:32/?UI,ParentRef:32/?UI>>).
-%% @spec (This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout(), Message::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprinterreporterror">external documentation</a>.
+-spec reportError(This, Parent, Printout, Message) -> ok when
+ This::wxPrinter(), Parent::wxWindow:wxWindow(), Printout::wxPrintout:wxPrintout(), Message::unicode:chardata().
reportError(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},#wx_ref{type=PrintoutT,ref=PrintoutRef},Message)
when is_list(Message) ->
?CLASS(ThisT,wxPrinter),
@@ -119,16 +129,17 @@ reportError(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},
wxe_util:cast(?wxPrinter_ReportError,
<<ThisRef:32/?UI,ParentRef:32/?UI,PrintoutRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxPrinter(), Parent::wxWindow:wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprinter.html#wxprintersetup">external documentation</a>.
+-spec setup(This, Parent) -> boolean() when
+ This::wxPrinter(), Parent::wxWindow:wxWindow().
setup(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}) ->
?CLASS(ThisT,wxPrinter),
?CLASS(ParentT,wxWindow),
wxe_util:call(?wxPrinter_Setup,
<<ThisRef:32/?UI,ParentRef:32/?UI>>).
-%% @spec (This::wxPrinter()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPrinter()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPrinter),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxPrintout.erl b/lib/wx/src/gen/wxPrintout.erl
index b5b93921e6..ab96a09c09 100644
--- a/lib/wx/src/gen/wxPrintout.erl
+++ b/lib/wx/src/gen/wxPrintout.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,9 +34,11 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxPrintout/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxPrintout() :: wx:wx_object().
%% @spec (Title::string(), OnPrintPage::function()) -> wxPrintout:wxPrintout()
%% @doc @equiv new(Title, OnPrintPage, [])
@@ -118,80 +120,91 @@ new(Title, OnPrintPage, Opts) when is_list(Title), is_function(OnPrintPage), is_
OnPrintPageId:32/?UI,
BinOpt/binary>>).
-%% @spec (This::wxPrintout()) -> wxDC:wxDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetdc">external documentation</a>.
+-spec getDC(This) -> wxDC:wxDC() when
+ This::wxPrintout().
getDC(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetDC,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetpagesizemm">external documentation</a>.
+-spec getPageSizeMM(This) -> {W::integer(), H::integer()} when
+ This::wxPrintout().
getPageSizeMM(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPageSizeMM,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetpagesizepixels">external documentation</a>.
+-spec getPageSizePixels(This) -> {W::integer(), H::integer()} when
+ This::wxPrintout().
getPageSizePixels(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPageSizePixels,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetpaperrectpixels">external documentation</a>.
+-spec getPaperRectPixels(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxPrintout().
getPaperRectPixels(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPaperRectPixels,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetppiprinter">external documentation</a>.
+-spec getPPIPrinter(This) -> {X::integer(), Y::integer()} when
+ This::wxPrintout().
getPPIPrinter(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPPIPrinter,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetppiscreen">external documentation</a>.
+-spec getPPIScreen(This) -> {X::integer(), Y::integer()} when
+ This::wxPrintout().
getPPIScreen(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetPPIScreen,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgettitle">external documentation</a>.
+-spec getTitle(This) -> unicode:charlist() when
+ This::wxPrintout().
getTitle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetTitle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutispreview">external documentation</a>.
+-spec isPreview(This) -> boolean() when
+ This::wxPrintout().
isPreview(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_IsPreview,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout(), ImageSize::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutfitthissizetopaper">external documentation</a>.
+-spec fitThisSizeToPaper(This, ImageSize) -> ok when
+ This::wxPrintout(), ImageSize::{W::integer(), H::integer()}.
fitThisSizeToPaper(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH})
when is_integer(ImageSizeW),is_integer(ImageSizeH) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_FitThisSizeToPaper,
<<ThisRef:32/?UI,ImageSizeW:32/?UI,ImageSizeH:32/?UI>>).
-%% @spec (This::wxPrintout(), ImageSize::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutfitthissizetopage">external documentation</a>.
+-spec fitThisSizeToPage(This, ImageSize) -> ok when
+ This::wxPrintout(), ImageSize::{W::integer(), H::integer()}.
fitThisSizeToPage(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH})
when is_integer(ImageSizeW),is_integer(ImageSizeH) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_FitThisSizeToPage,
<<ThisRef:32/?UI,ImageSizeW:32/?UI,ImageSizeH:32/?UI>>).
-%% @spec (This::wxPrintout(), ImageSize::{W::integer(),H::integer()}, PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutfitthissizetopagemargins">external documentation</a>.
+-spec fitThisSizeToPageMargins(This, ImageSize, PageSetupData) -> ok when
+ This::wxPrintout(), ImageSize::{W::integer(), H::integer()}, PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData().
fitThisSizeToPageMargins(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH},#wx_ref{type=PageSetupDataT,ref=PageSetupDataRef})
when is_integer(ImageSizeW),is_integer(ImageSizeH) ->
?CLASS(ThisT,wxPrintout),
@@ -199,75 +212,84 @@ fitThisSizeToPageMargins(#wx_ref{type=ThisT,ref=ThisRef},{ImageSizeW,ImageSizeH}
wxe_util:cast(?wxPrintout_FitThisSizeToPageMargins,
<<ThisRef:32/?UI,ImageSizeW:32/?UI,ImageSizeH:32/?UI,PageSetupDataRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutmapscreensizetopaper">external documentation</a>.
+-spec mapScreenSizeToPaper(This) -> ok when
+ This::wxPrintout().
mapScreenSizeToPaper(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_MapScreenSizeToPaper,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutmapscreensizetopage">external documentation</a>.
+-spec mapScreenSizeToPage(This) -> ok when
+ This::wxPrintout().
mapScreenSizeToPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_MapScreenSizeToPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout(), PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutmapscreensizetopagemargins">external documentation</a>.
+-spec mapScreenSizeToPageMargins(This, PageSetupData) -> ok when
+ This::wxPrintout(), PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData().
mapScreenSizeToPageMargins(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageSetupDataT,ref=PageSetupDataRef}) ->
?CLASS(ThisT,wxPrintout),
?CLASS(PageSetupDataT,wxPageSetupDialogData),
wxe_util:cast(?wxPrintout_MapScreenSizeToPageMargins,
<<ThisRef:32/?UI,PageSetupDataRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutmapscreensizetodevice">external documentation</a>.
+-spec mapScreenSizeToDevice(This) -> ok when
+ This::wxPrintout().
mapScreenSizeToDevice(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_MapScreenSizeToDevice,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetlogicalpaperrect">external documentation</a>.
+-spec getLogicalPaperRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxPrintout().
getLogicalPaperRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetLogicalPaperRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetlogicalpagerect">external documentation</a>.
+-spec getLogicalPageRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxPrintout().
getLogicalPageRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxPrintout),
wxe_util:call(?wxPrintout_GetLogicalPageRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxPrintout(), PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutgetlogicalpagemarginsrect">external documentation</a>.
+-spec getLogicalPageMarginsRect(This, PageSetupData) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxPrintout(), PageSetupData::wxPageSetupDialogData:wxPageSetupDialogData().
getLogicalPageMarginsRect(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageSetupDataT,ref=PageSetupDataRef}) ->
?CLASS(ThisT,wxPrintout),
?CLASS(PageSetupDataT,wxPageSetupDialogData),
wxe_util:call(?wxPrintout_GetLogicalPageMarginsRect,
<<ThisRef:32/?UI,PageSetupDataRef:32/?UI>>).
-%% @spec (This::wxPrintout(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutsetlogicalorigin">external documentation</a>.
+-spec setLogicalOrigin(This, X, Y) -> ok when
+ This::wxPrintout(), X::integer(), Y::integer().
setLogicalOrigin(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_SetLogicalOrigin,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxPrintout(), Xoff::integer(), Yoff::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprintout.html#wxprintoutoffsetlogicalorigin">external documentation</a>.
+-spec offsetLogicalOrigin(This, Xoff, Yoff) -> ok when
+ This::wxPrintout(), Xoff::integer(), Yoff::integer().
offsetLogicalOrigin(#wx_ref{type=ThisT,ref=ThisRef},Xoff,Yoff)
when is_integer(Xoff),is_integer(Yoff) ->
?CLASS(ThisT,wxPrintout),
wxe_util:cast(?wxPrintout_OffsetLogicalOrigin,
<<ThisRef:32/?UI,Xoff:32/?UI,Yoff:32/?UI>>).
-%% @spec (This::wxPrintout()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxPrintout()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxPrintout),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxProgressDialog.erl b/lib/wx/src/gen/wxProgressDialog.erl
index 69e73454b5..0f42c1d68f 100644
--- a/lib/wx/src/gen/wxProgressDialog.erl
+++ b/lib/wx/src/gen/wxProgressDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxProgressDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,15 +85,21 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Title::string(), Message::string()) -> wxProgressDialog()
+-type wxProgressDialog() :: wx:wx_object().
%% @equiv new(Title,Message, [])
+-spec new(Title, Message) -> wxProgressDialog() when
+ Title::unicode:chardata(), Message::unicode:chardata().
+
new(Title,Message)
when is_list(Title),is_list(Message) ->
new(Title,Message, []).
-%% @spec (Title::string(), Message::string(), [Option]) -> wxProgressDialog()
-%% Option = {maximum, integer()} | {parent, wxWindow:wxWindow()} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprogressdialog.html#wxprogressdialogwxprogressdialog">external documentation</a>.
+-spec new(Title, Message, [Option]) -> wxProgressDialog() when
+ Title::unicode:chardata(), Message::unicode:chardata(),
+ Option :: {maximum, integer()}
+ | {parent, wxWindow:wxWindow()}
+ | {style, integer()}.
new(Title,Message, Options)
when is_list(Title),is_list(Message),is_list(Options) ->
Title_UC = unicode:characters_to_binary([Title,0]),
@@ -105,29 +112,34 @@ new(Title,Message, Options)
wxe_util:construct(?wxProgressDialog_new,
<<(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((4+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxProgressDialog()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprogressdialog.html#wxprogressdialogresume">external documentation</a>.
+-spec resume(This) -> ok when
+ This::wxProgressDialog().
resume(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxProgressDialog),
wxe_util:cast(?wxProgressDialog_Resume,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxProgressDialog()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprogressdialog.html#wxprogressdialogupdate">external documentation</a>.
+-spec update(This) -> ok when
+ This::wxProgressDialog().
update(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxProgressDialog),
wxe_util:cast(?wxProgressDialog_Update_0,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxProgressDialog(), Value::integer()) -> bool()
%% @equiv update(This,Value, [])
+-spec update(This, Value) -> boolean() when
+ This::wxProgressDialog(), Value::integer().
+
update(This,Value)
when is_record(This, wx_ref),is_integer(Value) ->
update(This,Value, []).
-%% @spec (This::wxProgressDialog(), Value::integer(), [Option]) -> bool()
-%% Option = {newmsg, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxprogressdialog.html#wxprogressdialogupdate">external documentation</a>.
+-spec update(This, Value, [Option]) -> boolean() when
+ This::wxProgressDialog(), Value::integer(),
+ Option :: {newmsg, unicode:chardata()}.
update(#wx_ref{type=ThisT,ref=ThisRef},Value, Options)
when is_integer(Value),is_list(Options) ->
?CLASS(ThisT,wxProgressDialog),
@@ -137,8 +149,8 @@ update(#wx_ref{type=ThisT,ref=ThisRef},Value, Options)
wxe_util:call(?wxProgressDialog_Update_2,
<<ThisRef:32/?UI,Value:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxProgressDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxProgressDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxProgressDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxQueryNewPaletteEvent.erl b/lib/wx/src/gen/wxQueryNewPaletteEvent.erl
index 96c493e4a6..8123d62fe1 100644
--- a/lib/wx/src/gen/wxQueryNewPaletteEvent.erl
+++ b/lib/wx/src/gen/wxQueryNewPaletteEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 +37,24 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxQueryNewPaletteEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxQueryNewPaletteEvent(), Realized::bool()) -> ok
+-type wxQueryNewPaletteEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxquerynewpaletteevent.html#wxquerynewpaletteeventsetpaletterealized">external documentation</a>.
+-spec setPaletteRealized(This, Realized) -> ok when
+ This::wxQueryNewPaletteEvent(), Realized::boolean().
setPaletteRealized(#wx_ref{type=ThisT,ref=ThisRef},Realized)
when is_boolean(Realized) ->
?CLASS(ThisT,wxQueryNewPaletteEvent),
wxe_util:cast(?wxQueryNewPaletteEvent_SetPaletteRealized,
<<ThisRef:32/?UI,(wxe_util:from_bool(Realized)):32/?UI>>).
-%% @spec (This::wxQueryNewPaletteEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxquerynewpaletteevent.html#wxquerynewpaletteeventgetpaletterealized">external documentation</a>.
+-spec getPaletteRealized(This) -> boolean() when
+ This::wxQueryNewPaletteEvent().
getPaletteRealized(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxQueryNewPaletteEvent),
wxe_util:call(?wxQueryNewPaletteEvent_GetPaletteRealized,
diff --git a/lib/wx/src/gen/wxRadioBox.erl b/lib/wx/src/gen/wxRadioBox.erl
index 06e8833972..b7f52d7d9c 100644
--- a/lib/wx/src/gen/wxRadioBox.erl
+++ b/lib/wx/src/gen/wxRadioBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,21 +72,28 @@
thaw/1,transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxRadioBox/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> wxRadioBox()
+-type wxRadioBox() :: wx:wx_object().
%% @equiv new(Parent,Id,Title,Pos,Size,Choices, [])
+-spec new(Parent, Id, Title, Pos, Size, Choices) -> wxRadioBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()].
+
new(Parent,Id,Title,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Title),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
new(Parent,Id,Title,Pos,Size,Choices, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> wxRadioBox()
-%% Option = {majorDim, integer()} | {style, integer()} | {val, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxwxradiobox">external documentation</a>.
+-spec new(Parent, Id, Title, Pos, Size, Choices, [Option]) -> wxRadioBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()],
+ Option :: {majorDim, integer()}
+ | {style, integer()}
+ | {val, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title,{PosX,PosY},{SizeW,SizeH},Choices, Options)
when is_integer(Id),is_list(Title),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -101,15 +108,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Title,{PosX,PosY},{SizeW,SizeH},Choic
wxe_util:construct(?wxRadioBox_new,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]]) -> bool()
%% @equiv create(This,Parent,Id,Title,Pos,Size,Choices, [])
+-spec create(This, Parent, Id, Title, Pos, Size, Choices) -> boolean() when
+ This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()].
+
create(This,Parent,Id,Title,Pos={PosX,PosY},Size={SizeW,SizeH},Choices)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Title),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices) ->
create(This,Parent,Id,Title,Pos,Size,Choices, []).
-%% @spec (This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::string(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}, Choices::[[string()]], [Option]) -> bool()
-%% Option = {majorDim, integer()} | {style, integer()} | {val, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxcreate">external documentation</a>.
+-spec create(This, Parent, Id, Title, Pos, Size, Choices, [Option]) -> boolean() when
+ This::wxRadioBox(), Parent::wxWindow:wxWindow(), Id::integer(), Title::unicode:chardata(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}, Choices::[unicode:chardata()],
+ Option :: {majorDim, integer()}
+ | {style, integer()}
+ | {val, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Title,{PosX,PosY},{SizeW,SizeH},Choices, Options)
when is_integer(Id),is_list(Title),is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH),is_list(Choices),is_list(Options) ->
?CLASS(ThisT,wxRadioBox),
@@ -125,21 +137,25 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Ti
wxe_util:call(?wxRadioBox_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxRadioBox()) -> bool()
%% @equiv enable(This, [])
+-spec enable(This) -> boolean() when
+ This::wxRadioBox().
+
enable(This)
when is_record(This, wx_ref) ->
enable(This, []).
-%% @spec (This::wxRadioBox(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxenable">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% enable(This::wxRadioBox(), N::integer()) -> enable(This,N, []) </c></p>
-%% <p><c>
-%% enable(This::wxRadioBox(), [Option]) -> bool() </c>
-%%<br /> Option = {enable, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% enable(This, [Option]) -> boolean() when<br />
+%% This::wxRadioBox(),<br />
+%% Option :: {enable, boolean()}.<br />
+%%
+-spec enable(This, N) -> boolean() when
+ This::wxRadioBox(), N::integer();
+ (This, [Option]) -> boolean() when
+ This::wxRadioBox(),
+ Option :: {enable, boolean()}.
enable(This,N)
when is_record(This, wx_ref),is_integer(N) ->
@@ -153,9 +169,10 @@ enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxRadioBox_Enable_1,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxRadioBox(), N::integer(), [Option]) -> bool()
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxenable">external documentation</a>.
+-spec enable(This, N, [Option]) -> boolean() when
+ This::wxRadioBox(), N::integer(),
+ Option :: {enable, boolean()}.
enable(#wx_ref{type=ThisT,ref=ThisRef},N, Options)
when is_integer(N),is_list(Options) ->
?CLASS(ThisT,wxRadioBox),
@@ -165,44 +182,51 @@ enable(#wx_ref{type=ThisT,ref=ThisRef},N, Options)
wxe_util:call(?wxRadioBox_Enable_2,
<<ThisRef:32/?UI,N:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxRadioBox()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxRadioBox().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRadioBox(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetstring">external documentation</a>.
+-spec getString(This, N) -> unicode:charlist() when
+ This::wxRadioBox(), N::integer().
getString(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetString,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxRadioBox(), N::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxsetselection">external documentation</a>.
+-spec setSelection(This, N) -> ok when
+ This::wxRadioBox(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:cast(?wxRadioBox_SetSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxRadioBox()) -> bool()
%% @equiv show(This, [])
+-spec show(This) -> boolean() when
+ This::wxRadioBox().
+
show(This)
when is_record(This, wx_ref) ->
show(This, []).
-%% @spec (This::wxRadioBox(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxshow">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% show(This::wxRadioBox(), N::integer()) -> show(This,N, []) </c></p>
-%% <p><c>
-%% show(This::wxRadioBox(), [Option]) -> bool() </c>
-%%<br /> Option = {show, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% show(This, [Option]) -> boolean() when<br />
+%% This::wxRadioBox(),<br />
+%% Option :: {show, boolean()}.<br />
+%%
+-spec show(This, N) -> boolean() when
+ This::wxRadioBox(), N::integer();
+ (This, [Option]) -> boolean() when
+ This::wxRadioBox(),
+ Option :: {show, boolean()}.
show(This,N)
when is_record(This, wx_ref),is_integer(N) ->
@@ -216,9 +240,10 @@ show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxRadioBox_Show_1,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxRadioBox(), N::integer(), [Option]) -> bool()
-%% Option = {show, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxshow">external documentation</a>.
+-spec show(This, N, [Option]) -> boolean() when
+ This::wxRadioBox(), N::integer(),
+ Option :: {show, boolean()}.
show(#wx_ref{type=ThisT,ref=ThisRef},N, Options)
when is_integer(N),is_list(Options) ->
?CLASS(ThisT,wxRadioBox),
@@ -228,62 +253,70 @@ show(#wx_ref{type=ThisT,ref=ThisRef},N, Options)
wxe_util:call(?wxRadioBox_Show_2,
<<ThisRef:32/?UI,N:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxRadioBox()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetcolumncount">external documentation</a>.
+-spec getColumnCount(This) -> integer() when
+ This::wxRadioBox().
getColumnCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetColumnCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRadioBox(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetitemhelptext">external documentation</a>.
+-spec getItemHelpText(This, N) -> unicode:charlist() when
+ This::wxRadioBox(), N::integer().
getItemHelpText(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetItemHelpText,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxRadioBox(), Item::integer()) -> wxToolTip:wxToolTip()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetitemtooltip">external documentation</a>.
+-spec getItemToolTip(This, Item) -> wxToolTip:wxToolTip() when
+ This::wxRadioBox(), Item::integer().
getItemToolTip(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetItemToolTip,
<<ThisRef:32/?UI,Item:32/?UI>>).
-%% @spec (This::wxRadioBox(), Pt::{X::integer(),Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetitemfrompoint">external documentation</a>.
+-spec getItemFromPoint(This, Pt) -> integer() when
+ This::wxRadioBox(), Pt::{X::integer(), Y::integer()}.
getItemFromPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetItemFromPoint,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxRadioBox()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxgetrowcount">external documentation</a>.
+-spec getRowCount(This) -> integer() when
+ This::wxRadioBox().
getRowCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_GetRowCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRadioBox(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxisitemenabled">external documentation</a>.
+-spec isItemEnabled(This, N) -> boolean() when
+ This::wxRadioBox(), N::integer().
isItemEnabled(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_IsItemEnabled,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxRadioBox(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxisitemshown">external documentation</a>.
+-spec isItemShown(This, N) -> boolean() when
+ This::wxRadioBox(), N::integer().
isItemShown(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxRadioBox),
wxe_util:call(?wxRadioBox_IsItemShown,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxRadioBox(), N::integer(), HelpText::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxsetitemhelptext">external documentation</a>.
+-spec setItemHelpText(This, N, HelpText) -> ok when
+ This::wxRadioBox(), N::integer(), HelpText::unicode:chardata().
setItemHelpText(#wx_ref{type=ThisT,ref=ThisRef},N,HelpText)
when is_integer(N),is_list(HelpText) ->
?CLASS(ThisT,wxRadioBox),
@@ -291,8 +324,9 @@ setItemHelpText(#wx_ref{type=ThisT,ref=ThisRef},N,HelpText)
wxe_util:cast(?wxRadioBox_SetItemHelpText,
<<ThisRef:32/?UI,N:32/?UI,(byte_size(HelpText_UC)):32/?UI,(HelpText_UC)/binary, 0:(((8- ((4+byte_size(HelpText_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxRadioBox(), Item::integer(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobox.html#wxradioboxsetitemtooltip">external documentation</a>.
+-spec setItemToolTip(This, Item, Text) -> ok when
+ This::wxRadioBox(), Item::integer(), Text::unicode:chardata().
setItemToolTip(#wx_ref{type=ThisT,ref=ThisRef},Item,Text)
when is_integer(Item),is_list(Text) ->
?CLASS(ThisT,wxRadioBox),
@@ -300,8 +334,8 @@ setItemToolTip(#wx_ref{type=ThisT,ref=ThisRef},Item,Text)
wxe_util:cast(?wxRadioBox_SetItemToolTip,
<<ThisRef:32/?UI,Item:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxRadioBox()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxRadioBox()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxRadioBox),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxRadioButton.erl b/lib/wx/src/gen/wxRadioButton.erl
index c2c5a00be6..beb052b873 100644
--- a/lib/wx/src/gen/wxRadioButton.erl
+++ b/lib/wx/src/gen/wxRadioButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +69,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxRadioButton/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxRadioButton()
+-type wxRadioButton() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttonwxradiobutton">external documentation</a>.
+-spec new() -> wxRadioButton().
new() ->
wxe_util:construct(?wxRadioButton_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> wxRadioButton()
%% @equiv new(Parent,Id,Label, [])
+-spec new(Parent, Id, Label) -> wxRadioButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
new(Parent,Id,Label)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
new(Parent,Id,Label, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxRadioButton()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttonwxradiobutton">external documentation</a>.
+-spec new(Parent, Id, Label, [Option]) -> wxRadioButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -103,15 +111,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
wxe_util:construct(?wxRadioButton_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxRadioButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> bool()
%% @equiv create(This,Parent,Id,Label, [])
+-spec create(This, Parent, Id, Label) -> boolean() when
+ This::wxRadioButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
create(This,Parent,Id,Label)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
create(This,Parent,Id,Label, []).
-%% @spec (This::wxRadioButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttoncreate">external documentation</a>.
+-spec create(This, Parent, Id, Label, [Option]) -> boolean() when
+ This::wxRadioButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxRadioButton),
@@ -126,23 +140,25 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,La
wxe_util:call(?wxRadioButton_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxRadioButton()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttongetvalue">external documentation</a>.
+-spec getValue(This) -> boolean() when
+ This::wxRadioButton().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRadioButton),
wxe_util:call(?wxRadioButton_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRadioButton(), Val::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxradiobutton.html#wxradiobuttonsetvalue">external documentation</a>.
+-spec setValue(This, Val) -> ok when
+ This::wxRadioButton(), Val::boolean().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Val)
when is_boolean(Val) ->
?CLASS(ThisT,wxRadioButton),
wxe_util:cast(?wxRadioButton_SetValue,
<<ThisRef:32/?UI,(wxe_util:from_bool(Val)):32/?UI>>).
-%% @spec (This::wxRadioButton()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxRadioButton()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxRadioButton),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxRegion.erl b/lib/wx/src/gen/wxRegion.erl
index 4e8d98a54f..3e23623741 100644
--- a/lib/wx/src/gen/wxRegion.erl
+++ b/lib/wx/src/gen/wxRegion.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,24 +32,26 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxRegion/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxRegion()
+-type wxRegion() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionwxregion">external documentation</a>.
+-spec new() -> wxRegion().
new() ->
wxe_util:construct(?wxRegion_new_0,
<<>>).
-%% @spec (X::term()) -> wxRegion()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionwxregion">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Bmp::wxBitmap:wxBitmap()) -> wxRegion() </c>
-%% </p>
-%% <p><c>
-%% new(Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> wxRegion() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Rect) -> wxRegion() when<br />
+%% Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec new(Bmp) -> wxRegion() when
+ Bmp::wxBitmap:wxBitmap();
+ (Rect) -> wxRegion() when
+ Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
new(#wx_ref{type=BmpT,ref=BmpRef}) ->
?CLASS(BmpT,wxBitmap),
wxe_util:construct(?wxRegion_new_1_0,
@@ -59,40 +61,40 @@ new({RectX,RectY,RectW,RectH})
wxe_util:construct(?wxRegion_new_1_1,
<<RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (TopLeft::{X::integer(),Y::integer()}, BottomRight::{X::integer(),Y::integer()}) -> wxRegion()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionwxregion">external documentation</a>.
+-spec new(TopLeft, BottomRight) -> wxRegion() when
+ TopLeft::{X::integer(), Y::integer()}, BottomRight::{X::integer(), Y::integer()}.
new({TopLeftX,TopLeftY},{BottomRightX,BottomRightY})
when is_integer(TopLeftX),is_integer(TopLeftY),is_integer(BottomRightX),is_integer(BottomRightY) ->
wxe_util:construct(?wxRegion_new_2,
<<TopLeftX:32/?UI,TopLeftY:32/?UI,BottomRightX:32/?UI,BottomRightY:32/?UI>>).
-%% @spec (X::integer(), Y::integer(), W::integer(), H::integer()) -> wxRegion()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionwxregion">external documentation</a>.
+-spec new(X, Y, W, H) -> wxRegion() when
+ X::integer(), Y::integer(), W::integer(), H::integer().
new(X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
wxe_util:construct(?wxRegion_new_4,
<<X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxRegion().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRegion),
wxe_util:cast(?wxRegion_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRegion(),X::term()) -> WxRegionContain
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregioncontains">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% contains(This::wxRegion(), Pt::{X::integer(),Y::integer()}) -> WxRegionContain </c>
-%%<br /> WxRegionContain = integer()
-%%<br /> WxRegionContain is one of ?wxOutRegion | ?wxPartRegion | ?wxInRegion
-%% </p>
-%% <p><c>
-%% contains(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> WxRegionContain </c>
-%%<br /> WxRegionContain = integer()
-%%<br /> WxRegionContain is one of ?wxOutRegion | ?wxPartRegion | ?wxInRegion
-%% </p>
+%% <br /> Also:<br />
+%% contains(This, Rect) -> wx:wx_enum() when<br />
+%% This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+%%<br /> Res = ?wxOutRegion | ?wxPartRegion | ?wxInRegion
+-spec contains(This, Pt) -> wx:wx_enum() when
+ This::wxRegion(), Pt::{X::integer(), Y::integer()};
+ (This, Rect) -> wx:wx_enum() when
+ This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
contains(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxRegion),
@@ -104,49 +106,51 @@ contains(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:call(?wxRegion_Contains_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer()) -> WxRegionContain
-%% WxRegionContain = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregioncontains">external documentation</a>.
-%%<br /> WxRegionContain is one of ?wxOutRegion | ?wxPartRegion | ?wxInRegion
+%%<br /> Res = ?wxOutRegion | ?wxPartRegion | ?wxInRegion
+-spec contains(This, X, Y) -> wx:wx_enum() when
+ This::wxRegion(), X::integer(), Y::integer().
contains(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Contains_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer()) -> WxRegionContain
-%% WxRegionContain = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregioncontains">external documentation</a>.
-%%<br /> WxRegionContain is one of ?wxOutRegion | ?wxPartRegion | ?wxInRegion
+%%<br /> Res = ?wxOutRegion | ?wxPartRegion | ?wxInRegion
+-spec contains(This, X, Y, W, H) -> wx:wx_enum() when
+ This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer().
contains(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Contains_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionconverttobitmap">external documentation</a>.
+-spec convertToBitmap(This) -> wxBitmap:wxBitmap() when
+ This::wxRegion().
convertToBitmap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_ConvertToBitmap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRegion()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregiongetbox">external documentation</a>.
+-spec getBox(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxRegion().
getBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_GetBox,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRegion(),X::wxRegion()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionintersect">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% intersect(This::wxRegion(), Region::wxRegion()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% intersect(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% intersect(This, Rect) -> boolean() when<br />
+%% This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec intersect(This, Region) -> boolean() when
+ This::wxRegion(), Region::wxRegion();
+ (This, Rect) -> boolean() when
+ This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
intersect(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
?CLASS(RegionT,wxRegion),
@@ -158,30 +162,32 @@ intersect(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:call(?wxRegion_Intersect_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionintersect">external documentation</a>.
+-spec intersect(This, X, Y, W, H) -> boolean() when
+ This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer().
intersect(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Intersect_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionisempty">external documentation</a>.
+-spec isEmpty(This) -> boolean() when
+ This::wxRegion().
isEmpty(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_IsEmpty,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxRegion(),X::wxRegion()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionsubtract">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% subtract(This::wxRegion(), Region::wxRegion()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% subtract(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% subtract(This, Rect) -> boolean() when<br />
+%% This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec subtract(This, Region) -> boolean() when
+ This::wxRegion(), Region::wxRegion();
+ (This, Rect) -> boolean() when
+ This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
subtract(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
?CLASS(RegionT,wxRegion),
@@ -193,39 +199,42 @@ subtract(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:call(?wxRegion_Subtract_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionsubtract">external documentation</a>.
+-spec subtract(This, X, Y, W, H) -> boolean() when
+ This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer().
subtract(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Subtract_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion(), Pt::{X::integer(),Y::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionoffset">external documentation</a>.
+-spec offset(This, Pt) -> boolean() when
+ This::wxRegion(), Pt::{X::integer(), Y::integer()}.
offset(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Offset_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionoffset">external documentation</a>.
+-spec offset(This, X, Y) -> boolean() when
+ This::wxRegion(), X::integer(), Y::integer().
offset(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Offset_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxRegion(),X::term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionunion">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% union(This::wxRegion(), Region::wxRegion() | wxBitmap:wxBitmap()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% union(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% union(This, Rect) -> boolean() when<br />
+%% This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec union(This, Region) -> boolean() when
+ This::wxRegion(), Region::wxRegion() | wxBitmap:wxBitmap();
+ (This, Rect) -> boolean() when
+ This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
union(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
RegionOP = case ?CLASS_T(RegionT,wxRegion) of
@@ -242,15 +251,18 @@ union(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:call(?wxRegion_Union_1_2,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxRegion(), Bmp::wxBitmap:wxBitmap(), Transp::wx:colour()) -> bool()
%% @equiv union(This,Bmp,Transp, [])
+-spec union(This, Bmp, Transp) -> boolean() when
+ This::wxRegion(), Bmp::wxBitmap:wxBitmap(), Transp::wx:wx_colour().
+
union(This,Bmp,Transp)
when is_record(This, wx_ref),is_record(Bmp, wx_ref),tuple_size(Transp) =:= 3; tuple_size(Transp) =:= 4 ->
union(This,Bmp,Transp, []).
-%% @spec (This::wxRegion(), Bmp::wxBitmap:wxBitmap(), Transp::wx:colour(), [Option]) -> bool()
-%% Option = {tolerance, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionunion">external documentation</a>.
+-spec union(This, Bmp, Transp, [Option]) -> boolean() when
+ This::wxRegion(), Bmp::wxBitmap:wxBitmap(), Transp::wx:wx_colour(),
+ Option :: {tolerance, integer()}.
union(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},Transp, Options)
when tuple_size(Transp) =:= 3; tuple_size(Transp) =:= 4,is_list(Options) ->
?CLASS(ThisT,wxRegion),
@@ -261,23 +273,24 @@ union(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BmpT,ref=BmpRef},Transp, Opti
wxe_util:call(?wxRegion_Union_3,
<<ThisRef:32/?UI,BmpRef:32/?UI,(wxe_util:colour_bin(Transp)):16/binary, BinOpt/binary>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionunion">external documentation</a>.
+-spec union(This, X, Y, W, H) -> boolean() when
+ This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer().
union(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Union_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion(),X::wxRegion()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionxor">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% 'Xor'(This::wxRegion(), Region::wxRegion()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% 'Xor'(This::wxRegion(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% 'Xor'(This, Rect) -> boolean() when<br />
+%% This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec 'Xor'(This, Region) -> boolean() when
+ This::wxRegion(), Region::wxRegion();
+ (This, Rect) -> boolean() when
+ This::wxRegion(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
'Xor'(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxRegion),
?CLASS(RegionT,wxRegion),
@@ -289,16 +302,17 @@ union(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
wxe_util:call(?wxRegion_Xor_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxregion.html#wxregionxor">external documentation</a>.
+-spec 'Xor'(This, X, Y, W, H) -> boolean() when
+ This::wxRegion(), X::integer(), Y::integer(), W::integer(), H::integer().
'Xor'(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
?CLASS(ThisT,wxRegion),
wxe_util:call(?wxRegion_Xor_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxRegion()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxRegion()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxRegion),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSashEvent.erl b/lib/wx/src/gen/wxSashEvent.erl
index 480e241807..6ca4bf73ea 100644
--- a/lib/wx/src/gen/wxSashEvent.erl
+++ b/lib/wx/src/gen/wxSashEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,31 +40,34 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxSashEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSashEvent()) -> WxSashEdgePosition
-%% WxSashEdgePosition = integer()
+-type wxSashEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashevent.html#wxsasheventgetedge">external documentation</a>.
-%%<br /> WxSashEdgePosition is one of ?wxSASH_TOP | ?wxSASH_RIGHT | ?wxSASH_BOTTOM | ?wxSASH_LEFT | ?wxSASH_NONE
+%%<br /> Res = ?wxSASH_TOP | ?wxSASH_RIGHT | ?wxSASH_BOTTOM | ?wxSASH_LEFT | ?wxSASH_NONE
+-spec getEdge(This) -> wx:wx_enum() when
+ This::wxSashEvent().
getEdge(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashEvent),
wxe_util:call(?wxSashEvent_GetEdge,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashEvent()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashevent.html#wxsasheventgetdragrect">external documentation</a>.
+-spec getDragRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxSashEvent().
getDragRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashEvent),
wxe_util:call(?wxSashEvent_GetDragRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashEvent()) -> WxSashDragStatus
-%% WxSashDragStatus = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashevent.html#wxsasheventgetdragstatus">external documentation</a>.
-%%<br /> WxSashDragStatus is one of ?wxSASH_STATUS_OK | ?wxSASH_STATUS_OUT_OF_RANGE
+%%<br /> Res = ?wxSASH_STATUS_OK | ?wxSASH_STATUS_OUT_OF_RANGE
+-spec getDragStatus(This) -> wx:wx_enum() when
+ This::wxSashEvent().
getDragStatus(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashEvent),
wxe_util:call(?wxSashEvent_GetDragStatus,
diff --git a/lib/wx/src/gen/wxSashLayoutWindow.erl b/lib/wx/src/gen/wxSashLayoutWindow.erl
index 9bc5a185ba..f833f59479 100644
--- a/lib/wx/src/gen/wxSashLayoutWindow.erl
+++ b/lib/wx/src/gen/wxSashLayoutWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,27 +74,35 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxSashLayoutWindow/0]).
%% @hidden
parent_class(wxSashWindow) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSashLayoutWindow()
+-type wxSashLayoutWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowwxsashlayoutwindow">external documentation</a>.
+-spec new() -> wxSashLayoutWindow().
new() ->
wxe_util:construct(?wxSashLayoutWindow_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxSashLayoutWindow()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxSashLayoutWindow() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSashLayoutWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowwxsashlayoutwindow">external documentation</a>.
+-spec new(Parent, [Option]) -> wxSashLayoutWindow() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -107,15 +115,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxSashLayoutWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSashLayoutWindow(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxSashLayoutWindow(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxSashLayoutWindow(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxSashLayoutWindow(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSashLayoutWindow),
@@ -129,54 +143,55 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxSashLayoutWindow_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSashLayoutWindow()) -> WxLayoutAlignment
-%% WxLayoutAlignment = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowgetalignment">external documentation</a>.
-%%<br /> WxLayoutAlignment is one of ?wxLAYOUT_NONE | ?wxLAYOUT_TOP | ?wxLAYOUT_LEFT | ?wxLAYOUT_RIGHT | ?wxLAYOUT_BOTTOM
+%%<br /> Res = ?wxLAYOUT_NONE | ?wxLAYOUT_TOP | ?wxLAYOUT_LEFT | ?wxLAYOUT_RIGHT | ?wxLAYOUT_BOTTOM
+-spec getAlignment(This) -> wx:wx_enum() when
+ This::wxSashLayoutWindow().
getAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashLayoutWindow),
wxe_util:call(?wxSashLayoutWindow_GetAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashLayoutWindow()) -> WxLayoutOrientation
-%% WxLayoutOrientation = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowgetorientation">external documentation</a>.
-%%<br /> WxLayoutOrientation is one of ?wxLAYOUT_HORIZONTAL | ?wxLAYOUT_VERTICAL
+%%<br /> Res = ?wxLAYOUT_HORIZONTAL | ?wxLAYOUT_VERTICAL
+-spec getOrientation(This) -> wx:wx_enum() when
+ This::wxSashLayoutWindow().
getOrientation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashLayoutWindow),
wxe_util:call(?wxSashLayoutWindow_GetOrientation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashLayoutWindow(), Align::WxLayoutAlignment) -> ok
-%% WxLayoutAlignment = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowsetalignment">external documentation</a>.
-%%<br /> WxLayoutAlignment is one of ?wxLAYOUT_NONE | ?wxLAYOUT_TOP | ?wxLAYOUT_LEFT | ?wxLAYOUT_RIGHT | ?wxLAYOUT_BOTTOM
+%%<br /> Align = ?wxLAYOUT_NONE | ?wxLAYOUT_TOP | ?wxLAYOUT_LEFT | ?wxLAYOUT_RIGHT | ?wxLAYOUT_BOTTOM
+-spec setAlignment(This, Align) -> ok when
+ This::wxSashLayoutWindow(), Align::wx:wx_enum().
setAlignment(#wx_ref{type=ThisT,ref=ThisRef},Align)
when is_integer(Align) ->
?CLASS(ThisT,wxSashLayoutWindow),
wxe_util:cast(?wxSashLayoutWindow_SetAlignment,
<<ThisRef:32/?UI,Align:32/?UI>>).
-%% @spec (This::wxSashLayoutWindow(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowsetdefaultsize">external documentation</a>.
+-spec setDefaultSize(This, Size) -> ok when
+ This::wxSashLayoutWindow(), Size::{W::integer(), H::integer()}.
setDefaultSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxSashLayoutWindow),
wxe_util:cast(?wxSashLayoutWindow_SetDefaultSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSashLayoutWindow(), Orient::WxLayoutOrientation) -> ok
-%% WxLayoutOrientation = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashlayoutwindow.html#wxsashlayoutwindowsetorientation">external documentation</a>.
-%%<br /> WxLayoutOrientation is one of ?wxLAYOUT_HORIZONTAL | ?wxLAYOUT_VERTICAL
+%%<br /> Orient = ?wxLAYOUT_HORIZONTAL | ?wxLAYOUT_VERTICAL
+-spec setOrientation(This, Orient) -> ok when
+ This::wxSashLayoutWindow(), Orient::wx:wx_enum().
setOrientation(#wx_ref{type=ThisT,ref=ThisRef},Orient)
when is_integer(Orient) ->
?CLASS(ThisT,wxSashLayoutWindow),
wxe_util:cast(?wxSashLayoutWindow_SetOrientation,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxSashLayoutWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSashLayoutWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSashLayoutWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSashWindow.erl b/lib/wx/src/gen/wxSashWindow.erl
index 49fb82f828..7d85e05af8 100644
--- a/lib/wx/src/gen/wxSashWindow.erl
+++ b/lib/wx/src/gen/wxSashWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +70,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxSashWindow/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSashWindow()
+-type wxSashWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowwxsashwindow">external documentation</a>.
+-spec new() -> wxSashWindow().
new() ->
wxe_util:construct(?wxSashWindow_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxSashWindow()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxSashWindow() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSashWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowwxsashwindow">external documentation</a>.
+-spec new(Parent, [Option]) -> wxSashWindow() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -102,88 +110,96 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxSashWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSashWindow(), Edge::WxSashEdgePosition) -> bool()
-%% WxSashEdgePosition = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowgetsashvisible">external documentation</a>.
-%%<br /> WxSashEdgePosition is one of ?wxSASH_TOP | ?wxSASH_RIGHT | ?wxSASH_BOTTOM | ?wxSASH_LEFT | ?wxSASH_NONE
+%%<br /> Edge = ?wxSASH_TOP | ?wxSASH_RIGHT | ?wxSASH_BOTTOM | ?wxSASH_LEFT | ?wxSASH_NONE
+-spec getSashVisible(This, Edge) -> boolean() when
+ This::wxSashWindow(), Edge::wx:wx_enum().
getSashVisible(#wx_ref{type=ThisT,ref=ThisRef},Edge)
when is_integer(Edge) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:call(?wxSashWindow_GetSashVisible,
<<ThisRef:32/?UI,Edge:32/?UI>>).
-%% @spec (This::wxSashWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowgetmaximumsizex">external documentation</a>.
+-spec getMaximumSizeX(This) -> integer() when
+ This::wxSashWindow().
getMaximumSizeX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:call(?wxSashWindow_GetMaximumSizeX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowgetmaximumsizey">external documentation</a>.
+-spec getMaximumSizeY(This) -> integer() when
+ This::wxSashWindow().
getMaximumSizeY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:call(?wxSashWindow_GetMaximumSizeY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowgetminimumsizex">external documentation</a>.
+-spec getMinimumSizeX(This) -> integer() when
+ This::wxSashWindow().
getMinimumSizeX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:call(?wxSashWindow_GetMinimumSizeX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowgetminimumsizey">external documentation</a>.
+-spec getMinimumSizeY(This) -> integer() when
+ This::wxSashWindow().
getMinimumSizeY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:call(?wxSashWindow_GetMinimumSizeY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSashWindow(), Max::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowsetmaximumsizex">external documentation</a>.
+-spec setMaximumSizeX(This, Max) -> ok when
+ This::wxSashWindow(), Max::integer().
setMaximumSizeX(#wx_ref{type=ThisT,ref=ThisRef},Max)
when is_integer(Max) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:cast(?wxSashWindow_SetMaximumSizeX,
<<ThisRef:32/?UI,Max:32/?UI>>).
-%% @spec (This::wxSashWindow(), Max::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowsetmaximumsizey">external documentation</a>.
+-spec setMaximumSizeY(This, Max) -> ok when
+ This::wxSashWindow(), Max::integer().
setMaximumSizeY(#wx_ref{type=ThisT,ref=ThisRef},Max)
when is_integer(Max) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:cast(?wxSashWindow_SetMaximumSizeY,
<<ThisRef:32/?UI,Max:32/?UI>>).
-%% @spec (This::wxSashWindow(), Min::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowsetminimumsizex">external documentation</a>.
+-spec setMinimumSizeX(This, Min) -> ok when
+ This::wxSashWindow(), Min::integer().
setMinimumSizeX(#wx_ref{type=ThisT,ref=ThisRef},Min)
when is_integer(Min) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:cast(?wxSashWindow_SetMinimumSizeX,
<<ThisRef:32/?UI,Min:32/?UI>>).
-%% @spec (This::wxSashWindow(), Min::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowsetminimumsizey">external documentation</a>.
+-spec setMinimumSizeY(This, Min) -> ok when
+ This::wxSashWindow(), Min::integer().
setMinimumSizeY(#wx_ref{type=ThisT,ref=ThisRef},Min)
when is_integer(Min) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:cast(?wxSashWindow_SetMinimumSizeY,
<<ThisRef:32/?UI,Min:32/?UI>>).
-%% @spec (This::wxSashWindow(), Edge::WxSashEdgePosition, Sash::bool()) -> ok
-%% WxSashEdgePosition = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsashwindow.html#wxsashwindowsetsashvisible">external documentation</a>.
-%%<br /> WxSashEdgePosition is one of ?wxSASH_TOP | ?wxSASH_RIGHT | ?wxSASH_BOTTOM | ?wxSASH_LEFT | ?wxSASH_NONE
+%%<br /> Edge = ?wxSASH_TOP | ?wxSASH_RIGHT | ?wxSASH_BOTTOM | ?wxSASH_LEFT | ?wxSASH_NONE
+-spec setSashVisible(This, Edge, Sash) -> ok when
+ This::wxSashWindow(), Edge::wx:wx_enum(), Sash::boolean().
setSashVisible(#wx_ref{type=ThisT,ref=ThisRef},Edge,Sash)
when is_integer(Edge),is_boolean(Sash) ->
?CLASS(ThisT,wxSashWindow),
wxe_util:cast(?wxSashWindow_SetSashVisible,
<<ThisRef:32/?UI,Edge:32/?UI,(wxe_util:from_bool(Sash)):32/?UI>>).
-%% @spec (This::wxSashWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSashWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSashWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxScreenDC.erl b/lib/wx/src/gen/wxScreenDC.erl
index 4d7466f4f1..f9ab60d389 100644
--- a/lib/wx/src/gen/wxScreenDC.erl
+++ b/lib/wx/src/gen/wxScreenDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +38,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -52,18 +52,20 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxScreenDC/0]).
%% @hidden
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxScreenDC()
+-type wxScreenDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscreendc.html#wxscreendcwxscreendc">external documentation</a>.
+-spec new() -> wxScreenDC().
new() ->
wxe_util:construct(?wxScreenDC_new,
<<>>).
-%% @spec (This::wxScreenDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxScreenDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxScreenDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -150,11 +152,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -168,7 +170,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxScrollBar.erl b/lib/wx/src/gen/wxScrollBar.erl
index 41ca8d867f..4370bd1635 100644
--- a/lib/wx/src/gen/wxScrollBar.erl
+++ b/lib/wx/src/gen/wxScrollBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +70,35 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxScrollBar/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxScrollBar()
+-type wxScrollBar() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarwxscrollbar">external documentation</a>.
+-spec new() -> wxScrollBar().
new() ->
wxe_util:construct(?wxScrollBar_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxScrollBar()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxScrollBar() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxScrollBar()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarwxscrollbar">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxScrollBar() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -103,15 +111,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxScrollBar_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxScrollBar(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxScrollBar(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxScrollBar(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxScrollBar(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxScrollBar),
@@ -125,51 +139,59 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxScrollBar_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxScrollBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbargetrange">external documentation</a>.
+-spec getRange(This) -> integer() when
+ This::wxScrollBar().
getRange(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollBar),
wxe_util:call(?wxScrollBar_GetRange,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrollBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbargetpagesize">external documentation</a>.
+-spec getPageSize(This) -> integer() when
+ This::wxScrollBar().
getPageSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollBar),
wxe_util:call(?wxScrollBar_GetPageSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrollBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbargetthumbposition">external documentation</a>.
+-spec getThumbPosition(This) -> integer() when
+ This::wxScrollBar().
getThumbPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollBar),
wxe_util:call(?wxScrollBar_GetThumbPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrollBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbargetthumbsize">external documentation</a>.
+-spec getThumbSize(This) -> integer() when
+ This::wxScrollBar().
getThumbSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollBar),
wxe_util:call(?wxScrollBar_GetThumbSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrollBar(), ViewStart::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarsetthumbposition">external documentation</a>.
+-spec setThumbPosition(This, ViewStart) -> ok when
+ This::wxScrollBar(), ViewStart::integer().
setThumbPosition(#wx_ref{type=ThisT,ref=ThisRef},ViewStart)
when is_integer(ViewStart) ->
?CLASS(ThisT,wxScrollBar),
wxe_util:cast(?wxScrollBar_SetThumbPosition,
<<ThisRef:32/?UI,ViewStart:32/?UI>>).
-%% @spec (This::wxScrollBar(), Position::integer(), ThumbSize::integer(), Range::integer(), PageSize::integer()) -> ok
%% @equiv setScrollbar(This,Position,ThumbSize,Range,PageSize, [])
+-spec setScrollbar(This, Position, ThumbSize, Range, PageSize) -> ok when
+ This::wxScrollBar(), Position::integer(), ThumbSize::integer(), Range::integer(), PageSize::integer().
+
setScrollbar(This,Position,ThumbSize,Range,PageSize)
when is_record(This, wx_ref),is_integer(Position),is_integer(ThumbSize),is_integer(Range),is_integer(PageSize) ->
setScrollbar(This,Position,ThumbSize,Range,PageSize, []).
-%% @spec (This::wxScrollBar(), Position::integer(), ThumbSize::integer(), Range::integer(), PageSize::integer(), [Option]) -> ok
-%% Option = {refresh, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollbar.html#wxscrollbarsetscrollbar">external documentation</a>.
+-spec setScrollbar(This, Position, ThumbSize, Range, PageSize, [Option]) -> ok when
+ This::wxScrollBar(), Position::integer(), ThumbSize::integer(), Range::integer(), PageSize::integer(),
+ Option :: {refresh, boolean()}.
setScrollbar(#wx_ref{type=ThisT,ref=ThisRef},Position,ThumbSize,Range,PageSize, Options)
when is_integer(Position),is_integer(ThumbSize),is_integer(Range),is_integer(PageSize),is_list(Options) ->
?CLASS(ThisT,wxScrollBar),
@@ -179,8 +201,8 @@ setScrollbar(#wx_ref{type=ThisT,ref=ThisRef},Position,ThumbSize,Range,PageSize,
wxe_util:cast(?wxScrollBar_SetScrollbar,
<<ThisRef:32/?UI,Position:32/?UI,ThumbSize:32/?UI,Range:32/?UI,PageSize:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxScrollBar()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxScrollBar()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxScrollBar),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxScrollEvent.erl b/lib/wx/src/gen/wxScrollEvent.erl
index 61b99fa360..6939859d92 100644
--- a/lib/wx/src/gen/wxScrollEvent.erl
+++ b/lib/wx/src/gen/wxScrollEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -40,20 +40,24 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxScrollEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxScrollEvent()) -> integer()
+-type wxScrollEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollevent.html#wxscrolleventgetorientation">external documentation</a>.
+-spec getOrientation(This) -> integer() when
+ This::wxScrollEvent().
getOrientation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollEvent),
wxe_util:call(?wxScrollEvent_GetOrientation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrollEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollevent.html#wxscrolleventgetposition">external documentation</a>.
+-spec getPosition(This) -> integer() when
+ This::wxScrollEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollEvent),
wxe_util:call(?wxScrollEvent_GetPosition,
diff --git a/lib/wx/src/gen/wxScrollWinEvent.erl b/lib/wx/src/gen/wxScrollWinEvent.erl
index 6b33b6b564..c899d37dff 100644
--- a/lib/wx/src/gen/wxScrollWinEvent.erl
+++ b/lib/wx/src/gen/wxScrollWinEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,19 +37,23 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxScrollWinEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxScrollWinEvent()) -> integer()
+-type wxScrollWinEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollwinevent.html#wxscrollwineventgetorientation">external documentation</a>.
+-spec getOrientation(This) -> integer() when
+ This::wxScrollWinEvent().
getOrientation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollWinEvent),
wxe_util:call(?wxScrollWinEvent_GetOrientation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrollWinEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrollwinevent.html#wxscrollwineventgetposition">external documentation</a>.
+-spec getPosition(This) -> integer() when
+ This::wxScrollWinEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrollWinEvent),
wxe_util:call(?wxScrollWinEvent_GetPosition,
diff --git a/lib/wx/src/gen/wxScrolledWindow.erl b/lib/wx/src/gen/wxScrolledWindow.erl
index a6f813d1a2..9141487a8c 100644
--- a/lib/wx/src/gen/wxScrolledWindow.erl
+++ b/lib/wx/src/gen/wxScrolledWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +72,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxScrolledWindow/0]).
%% @hidden
parent_class(wxPanel) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxScrolledWindow()
+-type wxScrolledWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowwxscrolledwindow">external documentation</a>.
+-spec new() -> wxScrolledWindow().
new() ->
wxe_util:construct(?wxScrolledWindow_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxScrolledWindow()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxScrolledWindow() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxScrolledWindow()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowwxscrolledwindow">external documentation</a>.
+-spec new(Parent, [Option]) -> wxScrolledWindow() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {winid, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -105,93 +113,108 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxScrolledWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxScrolledWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcscrolledposition">external documentation</a>.
+-spec calcScrolledPosition(This, Pt) -> {X::integer(), Y::integer()} when
+ This::wxScrolledWindow(), Pt::{X::integer(), Y::integer()}.
calcScrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_CalcScrolledPosition_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> {Xx::integer(),Yy::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcscrolledposition">external documentation</a>.
+-spec calcScrolledPosition(This, X, Y) -> {Xx::integer(), Yy::integer()} when
+ This::wxScrolledWindow(), X::integer(), Y::integer().
calcScrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_CalcScrolledPosition_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcunscrolledposition">external documentation</a>.
+-spec calcUnscrolledPosition(This, Pt) -> {X::integer(), Y::integer()} when
+ This::wxScrolledWindow(), Pt::{X::integer(), Y::integer()}.
calcUnscrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_CalcUnscrolledPosition_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> {Xx::integer(),Yy::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowcalcunscrolledposition">external documentation</a>.
+-spec calcUnscrolledPosition(This, X, Y) -> {Xx::integer(), Yy::integer()} when
+ This::wxScrolledWindow(), X::integer(), Y::integer().
calcUnscrolledPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_CalcUnscrolledPosition_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), X_scrolling::bool(), Y_scrolling::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowenablescrolling">external documentation</a>.
+-spec enableScrolling(This, X_scrolling, Y_scrolling) -> ok when
+ This::wxScrolledWindow(), X_scrolling::boolean(), Y_scrolling::boolean().
enableScrolling(#wx_ref{type=ThisT,ref=ThisRef},X_scrolling,Y_scrolling)
when is_boolean(X_scrolling),is_boolean(Y_scrolling) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:cast(?wxScrolledWindow_EnableScrolling,
<<ThisRef:32/?UI,(wxe_util:from_bool(X_scrolling)):32/?UI,(wxe_util:from_bool(Y_scrolling)):32/?UI>>).
-%% @spec (This::wxScrolledWindow()) -> {PixelsPerUnitX::integer(),PixelsPerUnitY::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowgetscrollpixelsperunit">external documentation</a>.
+-spec getScrollPixelsPerUnit(This) -> {PixelsPerUnitX::integer(), PixelsPerUnitY::integer()} when
+ This::wxScrolledWindow().
getScrollPixelsPerUnit(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_GetScrollPixelsPerUnit,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrolledWindow()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowgetviewstart">external documentation</a>.
+-spec getViewStart(This) -> {X::integer(), Y::integer()} when
+ This::wxScrolledWindow().
getViewStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:call(?wxScrolledWindow_GetViewStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), Dc::wxDC:wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowdopreparedc">external documentation</a>.
+-spec doPrepareDC(This, Dc) -> ok when
+ This::wxScrolledWindow(), Dc::wxDC:wxDC().
doPrepareDC(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}) ->
?CLASS(ThisT,wxScrolledWindow),
?CLASS(DcT,wxDC),
wxe_util:cast(?wxScrolledWindow_DoPrepareDC,
<<ThisRef:32/?UI,DcRef:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), Dc::wxDC:wxDC()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowpreparedc">external documentation</a>.
+-spec prepareDC(This, Dc) -> ok when
+ This::wxScrolledWindow(), Dc::wxDC:wxDC().
prepareDC(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DcT,ref=DcRef}) ->
?CLASS(ThisT,wxScrolledWindow),
?CLASS(DcT,wxDC),
wxe_util:cast(?wxScrolledWindow_PrepareDC,
<<ThisRef:32/?UI,DcRef:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowscroll">external documentation</a>.
+-spec scroll(This, X, Y) -> ok when
+ This::wxScrolledWindow(), X::integer(), Y::integer().
scroll(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:cast(?wxScrolledWindow_Scroll,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), PixelsPerUnitX::integer(), PixelsPerUnitY::integer(), NoUnitsX::integer(), NoUnitsY::integer()) -> ok
%% @equiv setScrollbars(This,PixelsPerUnitX,PixelsPerUnitY,NoUnitsX,NoUnitsY, [])
+-spec setScrollbars(This, PixelsPerUnitX, PixelsPerUnitY, NoUnitsX, NoUnitsY) -> ok when
+ This::wxScrolledWindow(), PixelsPerUnitX::integer(), PixelsPerUnitY::integer(), NoUnitsX::integer(), NoUnitsY::integer().
+
setScrollbars(This,PixelsPerUnitX,PixelsPerUnitY,NoUnitsX,NoUnitsY)
when is_record(This, wx_ref),is_integer(PixelsPerUnitX),is_integer(PixelsPerUnitY),is_integer(NoUnitsX),is_integer(NoUnitsY) ->
setScrollbars(This,PixelsPerUnitX,PixelsPerUnitY,NoUnitsX,NoUnitsY, []).
-%% @spec (This::wxScrolledWindow(), PixelsPerUnitX::integer(), PixelsPerUnitY::integer(), NoUnitsX::integer(), NoUnitsY::integer(), [Option]) -> ok
-%% Option = {xPos, integer()} | {yPos, integer()} | {noRefresh, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowsetscrollbars">external documentation</a>.
+-spec setScrollbars(This, PixelsPerUnitX, PixelsPerUnitY, NoUnitsX, NoUnitsY, [Option]) -> ok when
+ This::wxScrolledWindow(), PixelsPerUnitX::integer(), PixelsPerUnitY::integer(), NoUnitsX::integer(), NoUnitsY::integer(),
+ Option :: {xPos, integer()}
+ | {yPos, integer()}
+ | {noRefresh, boolean()}.
setScrollbars(#wx_ref{type=ThisT,ref=ThisRef},PixelsPerUnitX,PixelsPerUnitY,NoUnitsX,NoUnitsY, Options)
when is_integer(PixelsPerUnitX),is_integer(PixelsPerUnitY),is_integer(NoUnitsX),is_integer(NoUnitsY),is_list(Options) ->
?CLASS(ThisT,wxScrolledWindow),
@@ -203,24 +226,26 @@ setScrollbars(#wx_ref{type=ThisT,ref=ThisRef},PixelsPerUnitX,PixelsPerUnitY,NoUn
wxe_util:cast(?wxScrolledWindow_SetScrollbars,
<<ThisRef:32/?UI,PixelsPerUnitX:32/?UI,PixelsPerUnitY:32/?UI,NoUnitsX:32/?UI,NoUnitsY:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxScrolledWindow(), Xstep::integer(), Ystep::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowsetscrollrate">external documentation</a>.
+-spec setScrollRate(This, Xstep, Ystep) -> ok when
+ This::wxScrolledWindow(), Xstep::integer(), Ystep::integer().
setScrollRate(#wx_ref{type=ThisT,ref=ThisRef},Xstep,Ystep)
when is_integer(Xstep),is_integer(Ystep) ->
?CLASS(ThisT,wxScrolledWindow),
wxe_util:cast(?wxScrolledWindow_SetScrollRate,
<<ThisRef:32/?UI,Xstep:32/?UI,Ystep:32/?UI>>).
-%% @spec (This::wxScrolledWindow(), Target::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxscrolledwindow.html#wxscrolledwindowsettargetwindow">external documentation</a>.
+-spec setTargetWindow(This, Target) -> ok when
+ This::wxScrolledWindow(), Target::wxWindow:wxWindow().
setTargetWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=TargetT,ref=TargetRef}) ->
?CLASS(ThisT,wxScrolledWindow),
?CLASS(TargetT,wxWindow),
wxe_util:cast(?wxScrolledWindow_SetTargetWindow,
<<ThisRef:32/?UI,TargetRef:32/?UI>>).
-%% @spec (This::wxScrolledWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxScrolledWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxScrolledWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSetCursorEvent.erl b/lib/wx/src/gen/wxSetCursorEvent.erl
index 75a41eb6ad..23ff963001 100644
--- a/lib/wx/src/gen/wxSetCursorEvent.erl
+++ b/lib/wx/src/gen/wxSetCursorEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,40 +37,47 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxSetCursorEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSetCursorEvent()) -> wxCursor:wxCursor()
+-type wxSetCursorEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsetcursorevent.html#wxsetcursoreventgetcursor">external documentation</a>.
+-spec getCursor(This) -> wxCursor:wxCursor() when
+ This::wxSetCursorEvent().
getCursor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSetCursorEvent),
wxe_util:call(?wxSetCursorEvent_GetCursor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSetCursorEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsetcursorevent.html#wxsetcursoreventgetx">external documentation</a>.
+-spec getX(This) -> integer() when
+ This::wxSetCursorEvent().
getX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSetCursorEvent),
wxe_util:call(?wxSetCursorEvent_GetX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSetCursorEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsetcursorevent.html#wxsetcursoreventgety">external documentation</a>.
+-spec getY(This) -> integer() when
+ This::wxSetCursorEvent().
getY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSetCursorEvent),
wxe_util:call(?wxSetCursorEvent_GetY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSetCursorEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsetcursorevent.html#wxsetcursoreventhascursor">external documentation</a>.
+-spec hasCursor(This) -> boolean() when
+ This::wxSetCursorEvent().
hasCursor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSetCursorEvent),
wxe_util:call(?wxSetCursorEvent_HasCursor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSetCursorEvent(), Cursor::wxCursor:wxCursor()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsetcursorevent.html#wxsetcursoreventsetcursor">external documentation</a>.
+-spec setCursor(This, Cursor) -> ok when
+ This::wxSetCursorEvent(), Cursor::wxCursor:wxCursor().
setCursor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CursorT,ref=CursorRef}) ->
?CLASS(ThisT,wxSetCursorEvent),
?CLASS(CursorT,wxCursor),
diff --git a/lib/wx/src/gen/wxShowEvent.erl b/lib/wx/src/gen/wxShowEvent.erl
index 7d5c8300d3..ffafa0978f 100644
--- a/lib/wx/src/gen/wxShowEvent.erl
+++ b/lib/wx/src/gen/wxShowEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 +37,24 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxShowEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxShowEvent(), Show::bool()) -> ok
+-type wxShowEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxshowevent.html#wxshoweventsetshow">external documentation</a>.
+-spec setShow(This, Show) -> ok when
+ This::wxShowEvent(), Show::boolean().
setShow(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxShowEvent),
wxe_util:cast(?wxShowEvent_SetShow,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxShowEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxshowevent.html#wxshoweventgetshow">external documentation</a>.
+-spec getShow(This) -> boolean() when
+ This::wxShowEvent().
getShow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxShowEvent),
wxe_util:call(?wxShowEvent_GetShow,
diff --git a/lib/wx/src/gen/wxSingleChoiceDialog.erl b/lib/wx/src/gen/wxSingleChoiceDialog.erl
index 16e0c3d8ce..db6b41ae75 100644
--- a/lib/wx/src/gen/wxSingleChoiceDialog.erl
+++ b/lib/wx/src/gen/wxSingleChoiceDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxSingleChoiceDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,21 +85,26 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSingleChoiceDialog()
+-type wxSingleChoiceDialog() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsinglechoicedialog.html#wxsinglechoicedialogwxsinglechoicedialog">external documentation</a>.
+-spec new() -> wxSingleChoiceDialog().
new() ->
wxe_util:construct(?wxSingleChoiceDialog_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), Caption::string(), Choices::[[string()]]) -> wxSingleChoiceDialog()
%% @equiv new(Parent,Message,Caption,Choices, [])
+-spec new(Parent, Message, Caption, Choices) -> wxSingleChoiceDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(), Caption::unicode:chardata(), Choices::[unicode:chardata()].
+
new(Parent,Message,Caption,Choices)
when is_record(Parent, wx_ref),is_list(Message),is_list(Caption),is_list(Choices) ->
new(Parent,Message,Caption,Choices, []).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), Caption::string(), Choices::[[string()]], [Option]) -> wxSingleChoiceDialog()
-%% Option = {style, integer()} | {pos, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsinglechoicedialog.html#wxsinglechoicedialogwxsinglechoicedialog">external documentation</a>.
+-spec new(Parent, Message, Caption, Choices, [Option]) -> wxSingleChoiceDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(), Caption::unicode:chardata(), Choices::[unicode:chardata()],
+ Option :: {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef},Message,Caption,Choices, Options)
when is_list(Message),is_list(Caption),is_list(Choices),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -113,30 +119,33 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Message,Caption,Choices, Options)
wxe_util:construct(?wxSingleChoiceDialog_new_5,
<<ParentRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Caption_UC)):32/?UI,(Caption_UC)/binary, 0:(((8- ((4+byte_size(Caption_UC)) band 16#7)) band 16#7))/unit:8,(length(Choices_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Choices_UCA>>)/binary, 0:(((8- ((4 + lists:sum([byte_size(S)+4||S<-Choices_UCA])) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxSingleChoiceDialog()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsinglechoicedialog.html#wxsinglechoicedialoggetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxSingleChoiceDialog().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSingleChoiceDialog),
wxe_util:call(?wxSingleChoiceDialog_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSingleChoiceDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsinglechoicedialog.html#wxsinglechoicedialoggetstringselection">external documentation</a>.
+-spec getStringSelection(This) -> unicode:charlist() when
+ This::wxSingleChoiceDialog().
getStringSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSingleChoiceDialog),
wxe_util:call(?wxSingleChoiceDialog_GetStringSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSingleChoiceDialog(), Sel::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsinglechoicedialog.html#wxsinglechoicedialogsetselection">external documentation</a>.
+-spec setSelection(This, Sel) -> ok when
+ This::wxSingleChoiceDialog(), Sel::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},Sel)
when is_integer(Sel) ->
?CLASS(ThisT,wxSingleChoiceDialog),
wxe_util:cast(?wxSingleChoiceDialog_SetSelection,
<<ThisRef:32/?UI,Sel:32/?UI>>).
-%% @spec (This::wxSingleChoiceDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSingleChoiceDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSingleChoiceDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSizeEvent.erl b/lib/wx/src/gen/wxSizeEvent.erl
index 9e7619ebbd..c51e48bc59 100644
--- a/lib/wx/src/gen/wxSizeEvent.erl
+++ b/lib/wx/src/gen/wxSizeEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,12 +37,15 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxSizeEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSizeEvent()) -> {W::integer(),H::integer()}
+-type wxSizeEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeevent.html#wxsizeeventgetsize">external documentation</a>.
+-spec getSize(This) -> {W::integer(), H::integer()} when
+ This::wxSizeEvent().
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizeEvent),
wxe_util:call(?wxSizeEvent_GetSize,
diff --git a/lib/wx/src/gen/wxSizer.erl b/lib/wx/src/gen/wxSizer.erl
index e9b83a7333..7edc01aa2a 100644
--- a/lib/wx/src/gen/wxSizer.erl
+++ b/lib/wx/src/gen/wxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +36,40 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxSizer/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> wxSizerItem:wxSizerItem()
+-type wxSizer() :: wx:wx_object().
%% @equiv add(This,Window, [])
+-spec add(This, Window) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer().
+
add(This,Window)
when is_record(This, wx_ref),is_record(Window, wx_ref) ->
add(This,Window, []).
-%% @spec (This::wxSizer(),X::integer()|term(),X::integer()|term()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizeradd">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% add(This::wxSizer(), Width::integer(), Height::integer()) -> add(This,Width,Height, []) </c></p>
-%% <p><c>
-%% add(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
-%% </p>
-%% <p><c>
-%% add(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% add(This, Window, [Option]) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),<br />
+%% Option :: {proportion, integer()}<br />
+%% | {flag, integer()}<br />
+%% | {border, integer()}<br />
+%% | {userData, wx:wx_object()};<br />
+%% (This, Window, Flags) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags().<br />
+%%
+-spec add(This, Width, Height) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Width::integer(), Height::integer();
+ (This, Window, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()};
+ (This, Window, Flags) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags().
add(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
@@ -91,9 +104,13 @@ add(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,FlagsRef:32/?UI>>).
-%% @spec (This::wxSizer(), Width::integer(), Height::integer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizeradd">external documentation</a>.
+-spec add(This, Width, Height, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Width::integer(), Height::integer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()}.
add(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -106,23 +123,27 @@ add(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxSizer_Add_3,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer(), Size::integer()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizeraddspacer">external documentation</a>.
+-spec addSpacer(This, Size) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Size::integer().
addSpacer(#wx_ref{type=ThisT,ref=ThisRef},Size)
when is_integer(Size) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_AddSpacer,
<<ThisRef:32/?UI,Size:32/?UI>>).
-%% @spec (This::wxSizer()) -> wxSizerItem:wxSizerItem()
%% @equiv addStretchSpacer(This, [])
+-spec addStretchSpacer(This) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer().
+
addStretchSpacer(This)
when is_record(This, wx_ref) ->
addStretchSpacer(This, []).
-%% @spec (This::wxSizer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {prop, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizeraddstretchspacer">external documentation</a>.
+-spec addStretchSpacer(This, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(),
+ Option :: {prop, integer()}.
addStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -132,22 +153,26 @@ addStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxSizer_AddStretchSpacer,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizercalcmin">external documentation</a>.
+-spec calcMin(This) -> {W::integer(), H::integer()} when
+ This::wxSizer().
calcMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_CalcMin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> ok
%% @equiv clear(This, [])
+-spec clear(This) -> ok when
+ This::wxSizer().
+
clear(This)
when is_record(This, wx_ref) ->
clear(This, []).
-%% @spec (This::wxSizer(), [Option]) -> ok
-%% Option = {delete_windows, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerclear">external documentation</a>.
+-spec clear(This, [Option]) -> ok when
+ This::wxSizer(),
+ Option :: {delete_windows, boolean()}.
clear(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -157,15 +182,15 @@ clear(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxSizer_Clear,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerdetach">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% detach(This::wxSizer(), Index::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% detach(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% detach(This, Window) -> boolean() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer().<br />
+%%
+-spec detach(This, Index) -> boolean() when
+ This::wxSizer(), Index::integer();
+ (This, Window) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer().
detach(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxSizer),
@@ -182,37 +207,41 @@ detach(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerfit">external documentation</a>.
+-spec fit(This, Window) -> {W::integer(), H::integer()} when
+ This::wxSizer(), Window::wxWindow:wxWindow().
fit(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(WindowT,wxWindow),
wxe_util:call(?wxSizer_Fit,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerfitinside">external documentation</a>.
+-spec fitInside(This, Window) -> ok when
+ This::wxSizer(), Window::wxWindow:wxWindow().
fitInside(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(WindowT,wxWindow),
wxe_util:cast(?wxSizer_FitInside,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> [wxSizerItem:wxSizerItem()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetchildren">external documentation</a>.
+-spec getChildren(This) -> [wxSizerItem:wxSizerItem()] when
+ This::wxSizer().
getChildren(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_GetChildren,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::term()|integer()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetitem">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% getItem(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> getItem(This,Window, []) </c></p>
-%% <p><c>
-%% getItem(This::wxSizer(), Index::integer()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% getItem(This, Index) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Index::integer().<br />
+%%
+-spec getItem(This, Window) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer();
+ (This, Index) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer().
getItem(This,Window)
when is_record(This, wx_ref),is_record(Window, wx_ref) ->
@@ -223,9 +252,10 @@ getItem(#wx_ref{type=ThisT,ref=ThisRef},Index)
wxe_util:call(?wxSizer_GetItem_1,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {recursive, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetitem">external documentation</a>.
+-spec getItem(This, Window, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),
+ Option :: {recursive, boolean()}.
getItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -241,35 +271,39 @@ getItem(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Opt
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSizer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetsize">external documentation</a>.
+-spec getSize(This) -> {W::integer(), H::integer()} when
+ This::wxSizer().
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxSizer().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizergetminsize">external documentation</a>.
+-spec getMinSize(This) -> {W::integer(), H::integer()} when
+ This::wxSizer().
getMinSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_GetMinSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::term()|integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerhide">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% hide(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> hide(This,Window, []) </c></p>
-%% <p><c>
-%% hide(This::wxSizer(), Index::integer()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% hide(This, Index) -> boolean() when<br />
+%% This::wxSizer(), Index::integer().<br />
+%%
+-spec hide(This, Window) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer();
+ (This, Index) -> boolean() when
+ This::wxSizer(), Index::integer().
hide(This,Window)
when is_record(This, wx_ref),is_record(Window, wx_ref) ->
@@ -280,9 +314,10 @@ hide(#wx_ref{type=ThisT,ref=ThisRef},Index)
wxe_util:call(?wxSizer_Hide_1,
<<ThisRef:32/?UI,Index:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), [Option]) -> bool()
-%% Option = {recursive, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerhide">external documentation</a>.
+-spec hide(This, Window, [Option]) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),
+ Option :: {recursive, boolean()}.
hide(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -298,8 +333,9 @@ 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(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerinsert">external documentation</a>.
+-spec insert(This, Index, Item) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(), Item::wxSizerItem:wxSizerItem().
insert(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=ItemT,ref=ItemRef})
when is_integer(Index) ->
?CLASS(ThisT,wxSizer),
@@ -307,18 +343,27 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=ItemT,ref=ItemRef})
wxe_util:call(?wxSizer_Insert_2,
<<ThisRef:32/?UI,Index:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxSizer(),Index::integer(),X::integer()|term(),X::integer()|term()) -> 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(), Width::integer(), Height::integer()) -> insert(This,Index,Width,Height, []) </c></p>
-%% <p><c>
-%% insert(This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
-%% </p>
-%% <p><c>
-%% insert(This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% insert(This, Index, Window, [Option]) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer(),<br />
+%% Option :: {proportion, integer()}<br />
+%% | {flag, integer()}<br />
+%% | {border, integer()}<br />
+%% | {userData, wx:wx_object()};<br />
+%% (This, Index, Window, Flags) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags().<br />
+%%
+-spec insert(This, Index, Width, Height) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(), Width::integer(), Height::integer();
+ (This, Index, Window, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()};
+ (This, Index, Window, Flags) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags().
insert(This,Index,Width,Height)
when is_record(This, wx_ref),is_integer(Index),is_integer(Width),is_integer(Height) ->
@@ -354,9 +399,13 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=WindowT,ref=WindowRef}
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,Index:32/?UI,WindowRef:32/?UI,FlagsRef:32/?UI>>).
-%% @spec (This::wxSizer(), Index::integer(), Width::integer(), Height::integer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerinsert">external documentation</a>.
+-spec insert(This, Index, Width, Height, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(), Width::integer(), Height::integer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()}.
insert(#wx_ref{type=ThisT,ref=ThisRef},Index,Width,Height, Options)
when is_integer(Index),is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -369,23 +418,27 @@ insert(#wx_ref{type=ThisT,ref=ThisRef},Index,Width,Height, Options)
wxe_util:call(?wxSizer_Insert_4,
<<ThisRef:32/?UI,Index:32/?UI,Width:32/?UI,Height:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSizer(), Index::integer(), Size::integer()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerinsertspacer">external documentation</a>.
+-spec insertSpacer(This, Index, Size) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(), Size::integer().
insertSpacer(#wx_ref{type=ThisT,ref=ThisRef},Index,Size)
when is_integer(Index),is_integer(Size) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_InsertSpacer,
<<ThisRef:32/?UI,Index:32/?UI,Size:32/?UI>>).
-%% @spec (This::wxSizer(), Index::integer()) -> wxSizerItem:wxSizerItem()
%% @equiv insertStretchSpacer(This,Index, [])
+-spec insertStretchSpacer(This, Index) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer().
+
insertStretchSpacer(This,Index)
when is_record(This, wx_ref),is_integer(Index) ->
insertStretchSpacer(This,Index, []).
-%% @spec (This::wxSizer(), Index::integer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {prop, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerinsertstretchspacer">external documentation</a>.
+-spec insertStretchSpacer(This, Index, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Index::integer(),
+ Option :: {prop, integer()}.
insertStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef},Index, Options)
when is_integer(Index),is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -395,15 +448,15 @@ insertStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef},Index, Options)
wxe_util:call(?wxSizer_InsertStretchSpacer,
<<ThisRef:32/?UI,Index:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSizer(),X::integer()|term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerisshown">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% isShown(This::wxSizer(), Index::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% isShown(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% isShown(This, Window) -> boolean() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer().<br />
+%%
+-spec isShown(This, Index) -> boolean() when
+ This::wxSizer(), Index::integer();
+ (This, Window) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer().
isShown(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxSizer),
@@ -420,33 +473,44 @@ isShown(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerlayout">external documentation</a>.
+-spec layout(This) -> ok when
+ This::wxSizer().
layout(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:cast(?wxSizer_Layout,
<<ThisRef:32/?UI>>).
-%% @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>.
+-spec prepend(This, Item) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Item::wxSizerItem:wxSizerItem().
prepend(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(ItemT,wxSizerItem),
wxe_util:call(?wxSizer_Prepend_1,
<<ThisRef:32/?UI,ItemRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|term(),X::integer()|term()) -> 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(), Width::integer(), Height::integer()) -> prepend(This,Width,Height, []) </c></p>
-%% <p><c>
-%% prepend(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), [Option]) -> wxSizerItem:wxSizerItem() </c>
-%%<br /> Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
-%% </p>
-%% <p><c>
-%% prepend(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
+%% <br /> Also:<br />
+%% prepend(This, Window, [Option]) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),<br />
+%% Option :: {proportion, integer()}<br />
+%% | {flag, integer()}<br />
+%% | {border, integer()}<br />
+%% | {userData, wx:wx_object()};<br />
+%% (This, Window, Flags) -> wxSizerItem:wxSizerItem() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags().<br />
+%%
+-spec prepend(This, Width, Height) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Width::integer(), Height::integer();
+ (This, Window, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()};
+ (This, Window, Flags) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Flags::wxSizerFlags:wxSizerFlags().
prepend(This,Width,Height)
when is_record(This, wx_ref),is_integer(Width),is_integer(Height) ->
@@ -481,9 +545,13 @@ prepend(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef},#wx_
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,FlagsRef:32/?UI>>).
-%% @spec (This::wxSizer(), Width::integer(), Height::integer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {proportion, integer()} | {flag, integer()} | {border, integer()} | {userData, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerprepend">external documentation</a>.
+-spec prepend(This, Width, Height, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Width::integer(), Height::integer(),
+ Option :: {proportion, integer()}
+ | {flag, integer()}
+ | {border, integer()}
+ | {userData, wx:wx_object()}.
prepend(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
when is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -496,23 +564,27 @@ prepend(#wx_ref{type=ThisT,ref=ThisRef},Width,Height, Options)
wxe_util:call(?wxSizer_Prepend_3,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer(), Size::integer()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerprependspacer">external documentation</a>.
+-spec prependSpacer(This, Size) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(), Size::integer().
prependSpacer(#wx_ref{type=ThisT,ref=ThisRef},Size)
when is_integer(Size) ->
?CLASS(ThisT,wxSizer),
wxe_util:call(?wxSizer_PrependSpacer,
<<ThisRef:32/?UI,Size:32/?UI>>).
-%% @spec (This::wxSizer()) -> wxSizerItem:wxSizerItem()
%% @equiv prependStretchSpacer(This, [])
+-spec prependStretchSpacer(This) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer().
+
prependStretchSpacer(This)
when is_record(This, wx_ref) ->
prependStretchSpacer(This, []).
-%% @spec (This::wxSizer(), [Option]) -> wxSizerItem:wxSizerItem()
-%% Option = {prop, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerprependstretchspacer">external documentation</a>.
+-spec prependStretchSpacer(This, [Option]) -> wxSizerItem:wxSizerItem() when
+ This::wxSizer(),
+ Option :: {prop, integer()}.
prependStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -522,22 +594,23 @@ prependStretchSpacer(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxSizer_PrependStretchSpacer,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerrecalcsizes">external documentation</a>.
+-spec recalcSizes(This) -> ok when
+ This::wxSizer().
recalcSizes(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizer),
wxe_util:cast(?wxSizer_RecalcSizes,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|wxSizer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerremove">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% remove(This::wxSizer(), Index::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% remove(This::wxSizer(), Sizer::wxSizer()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% remove(This, Sizer) -> boolean() when<br />
+%% This::wxSizer(), Sizer::wxSizer().<br />
+%%
+-spec remove(This, Index) -> boolean() when
+ This::wxSizer(), Index::integer();
+ (This, Sizer) -> boolean() when
+ This::wxSizer(), Sizer::wxSizer().
remove(#wx_ref{type=ThisT,ref=ThisRef},Index)
when is_integer(Index) ->
?CLASS(ThisT,wxSizer),
@@ -549,14 +622,15 @@ remove(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}) ->
wxe_util:call(?wxSizer_Remove_1_1,
<<ThisRef:32/?UI,SizerRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::term()|integer(),X::term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerreplace">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% replace(This::wxSizer(), Oldwin::wxWindow:wxWindow() | wxSizer(), Newwin::wxWindow:wxWindow() | wxSizer()) -> replace(This,Oldwin,Newwin, []) </c></p>
-%% <p><c>
-%% replace(This::wxSizer(), Index::integer(), Newitem::wxSizerItem:wxSizerItem()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% replace(This, Index, Newitem) -> boolean() when<br />
+%% This::wxSizer(), Index::integer(), Newitem::wxSizerItem:wxSizerItem().<br />
+%%
+-spec replace(This, Oldwin, Newwin) -> boolean() when
+ This::wxSizer(), Oldwin::wxWindow:wxWindow() | wxSizer(), Newwin::wxWindow:wxWindow() | wxSizer();
+ (This, Index, Newitem) -> boolean() when
+ This::wxSizer(), Index::integer(), Newitem::wxSizerItem:wxSizerItem().
replace(This,Oldwin,Newwin)
when is_record(This, wx_ref),is_record(Oldwin, wx_ref),is_record(Newwin, wx_ref) ->
@@ -568,9 +642,10 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=NewitemT,ref=NewitemR
wxe_util:call(?wxSizer_Replace_2,
<<ThisRef:32/?UI,Index:32/?UI,NewitemRef:32/?UI>>).
-%% @spec (This::wxSizer(), Oldwin::wxWindow:wxWindow() | wxSizer(), Newwin::wxWindow:wxWindow() | wxSizer(), [Option]) -> bool()
-%% Option = {recursive, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerreplace">external documentation</a>.
+-spec replace(This, Oldwin, Newwin, [Option]) -> boolean() when
+ This::wxSizer(), Oldwin::wxWindow:wxWindow() | wxSizer(), Newwin::wxWindow:wxWindow() | wxSizer(),
+ Option :: {recursive, boolean()}.
replace(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=OldwinT,ref=OldwinRef},#wx_ref{type=NewwinT,ref=NewwinRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizer),
@@ -588,39 +663,42 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=OldwinT,ref=OldwinRef},#wx_
wxe_util:call(OldwinOP,
<<ThisRef:32/?UI,OldwinRef:32/?UI,NewwinRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizer(), X::integer(), Y::integer(), Width::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetdimension">external documentation</a>.
+-spec setDimension(This, X, Y, Width, Height) -> ok when
+ This::wxSizer(), X::integer(), Y::integer(), Width::integer(), Height::integer().
setDimension(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Width,Height)
when is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxSizer),
wxe_util:cast(?wxSizer_SetDimension,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizer(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetminsize">external documentation</a>.
+-spec setMinSize(This, Size) -> ok when
+ This::wxSizer(), Size::{W::integer(), H::integer()}.
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxSizer),
wxe_util:cast(?wxSizer_SetMinSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSizer(), Width::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetminsize">external documentation</a>.
+-spec setMinSize(This, Width, Height) -> ok when
+ This::wxSizer(), Width::integer(), Height::integer().
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxSizer),
wxe_util:cast(?wxSizer_SetMinSize_2,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|term(),Size::{W::integer(),H::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetitemminsize">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setItemMinSize(This::wxSizer(), Index::integer(), Size::{W::integer(),H::integer()}) -> bool() </c>
-%% </p>
-%% <p><c>
-%% setItemMinSize(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Size::{W::integer(),H::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% setItemMinSize(This, Window, Size) -> boolean() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Size::{W::integer(), H::integer()}.<br />
+%%
+-spec setItemMinSize(This, Index, Size) -> boolean() when
+ This::wxSizer(), Index::integer(), Size::{W::integer(), H::integer()};
+ (This, Window, Size) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Size::{W::integer(), H::integer()}.
setItemMinSize(#wx_ref{type=ThisT,ref=ThisRef},Index,{SizeW,SizeH})
when is_integer(Index),is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxSizer),
@@ -638,15 +716,15 @@ setItemMinSize(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRe
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|term(),Width::integer(),Height::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetitemminsize">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setItemMinSize(This::wxSizer(), Index::integer(), Width::integer(), Height::integer()) -> bool() </c>
-%% </p>
-%% <p><c>
-%% setItemMinSize(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Width::integer(), Height::integer()) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% setItemMinSize(This, Window, Width, Height) -> boolean() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Width::integer(), Height::integer().<br />
+%%
+-spec setItemMinSize(This, Index, Width, Height) -> boolean() when
+ This::wxSizer(), Index::integer(), Width::integer(), Height::integer();
+ (This, Window, Width, Height) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), Width::integer(), Height::integer().
setItemMinSize(#wx_ref{type=ThisT,ref=ThisRef},Index,Width,Height)
when is_integer(Index),is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxSizer),
@@ -664,32 +742,37 @@ setItemMinSize(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRe
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetsizehints">external documentation</a>.
+-spec setSizeHints(This, Window) -> ok when
+ This::wxSizer(), Window::wxWindow:wxWindow().
setSizeHints(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(WindowT,wxWindow),
wxe_util:cast(?wxSizer_SetSizeHints,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer(), Window::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizersetvirtualsizehints">external documentation</a>.
+-spec setVirtualSizeHints(This, Window) -> ok when
+ This::wxSizer(), Window::wxWindow:wxWindow().
setVirtualSizeHints(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(WindowT,wxWindow),
wxe_util:cast(?wxSizer_SetVirtualSizeHints,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|term()|bool()) -> bool()|bool()|ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizershow">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% show(This::wxSizer(), Index::integer()) -> show(This,Index, []) </c></p>
-%% <p><c>
-%% show(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> show(This,Window, []) </c></p>
-%% <p><c>
-%% show(This::wxSizer(), Show::bool()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% show(This, Window) -> boolean() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer();<br />
+%% (This, Show) -> ok when<br />
+%% This::wxSizer(), Show::boolean().<br />
+%%
+-spec show(This, Index) -> boolean() when
+ This::wxSizer(), Index::integer();
+ (This, Window) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer();
+ (This, Show) -> ok when
+ This::wxSizer(), Show::boolean().
show(This,Index)
when is_record(This, wx_ref),is_integer(Index) ->
@@ -704,17 +787,20 @@ show(#wx_ref{type=ThisT,ref=ThisRef},Show)
wxe_util:cast(?wxSizer_Show_1,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxSizer(),X::integer()|term(),[Option]) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizershow">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% show(This::wxSizer(), Index::integer(), [Option]) -> bool() </c>
-%%<br /> Option = {show, bool()}
-%% </p>
-%% <p><c>
-%% show(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(), [Option]) -> bool() </c>
-%%<br /> Option = {show, bool()} | {recursive, bool()}
-%% </p>
+%% <br /> Also:<br />
+%% show(This, Window, [Option]) -> boolean() when<br />
+%% This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),<br />
+%% Option :: {show, boolean()}<br />
+%% | {recursive, boolean()}.<br />
+%%
+-spec show(This, Index, [Option]) -> boolean() when
+ This::wxSizer(), Index::integer(),
+ Option :: {show, boolean()};
+ (This, Window, [Option]) -> boolean() when
+ This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer(),
+ Option :: {show, boolean()}
+ | {recursive, boolean()}.
show(#wx_ref{type=ThisT,ref=ThisRef},Index, Options)
when is_integer(Index),is_list(Options) ->
?CLASS(ThisT,wxSizer),
diff --git a/lib/wx/src/gen/wxSizerFlags.erl b/lib/wx/src/gen/wxSizerFlags.erl
index 2a25fd2c1a..08d36d1a80 100644
--- a/lib/wx/src/gen/wxSizerFlags.erl
+++ b/lib/wx/src/gen/wxSizerFlags.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxSizerFlags/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSizerFlags()
+-type wxSizerFlags() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxSizerFlags().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxSizerFlags()
-%% Option = {proportion, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagswxsizerflags">external documentation</a>.
+-spec new([Option]) -> wxSizerFlags() when
+ Option :: {proportion, integer()}.
new(Options)
when is_list(Options) ->
MOpts = fun({proportion, Proportion}, Acc) -> [<<1:32/?UI,Proportion:32/?UI>>|Acc];
@@ -49,23 +52,27 @@ new(Options)
wxe_util:construct(?wxSizerFlags_new,
<<BinOpt/binary>>).
-%% @spec (This::wxSizerFlags(), Alignment::integer()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsalign">external documentation</a>.
+-spec align(This, Alignment) -> wxSizerFlags() when
+ This::wxSizerFlags(), Alignment::integer().
align(#wx_ref{type=ThisT,ref=ThisRef},Alignment)
when is_integer(Alignment) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Align,
<<ThisRef:32/?UI,Alignment:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> wxSizerFlags()
%% @equiv border(This, [])
+-spec border(This) -> wxSizerFlags() when
+ This::wxSizerFlags().
+
border(This)
when is_record(This, wx_ref) ->
border(This, []).
-%% @spec (This::wxSizerFlags(), [Option]) -> wxSizerFlags()
-%% Option = {direction, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsborder">external documentation</a>.
+-spec border(This, [Option]) -> wxSizerFlags() when
+ This::wxSizerFlags(),
+ Option :: {direction, integer()}.
border(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSizerFlags),
@@ -75,59 +82,66 @@ border(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxSizerFlags_Border_1,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSizerFlags(), Direction::integer(), BorderInPixels::integer()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsborder">external documentation</a>.
+-spec border(This, Direction, BorderInPixels) -> wxSizerFlags() when
+ This::wxSizerFlags(), Direction::integer(), BorderInPixels::integer().
border(#wx_ref{type=ThisT,ref=ThisRef},Direction,BorderInPixels)
when is_integer(Direction),is_integer(BorderInPixels) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Border_2,
<<ThisRef:32/?UI,Direction:32/?UI,BorderInPixels:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagscenter">external documentation</a>.
+-spec center(This) -> wxSizerFlags() when
+ This::wxSizerFlags().
center(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Center,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagscentre">external documentation</a>.
+-spec centre(This) -> wxSizerFlags() when
+ This::wxSizerFlags().
centre(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Centre,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsexpand">external documentation</a>.
+-spec expand(This) -> wxSizerFlags() when
+ This::wxSizerFlags().
expand(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Expand,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsleft">external documentation</a>.
+-spec left(This) -> wxSizerFlags() when
+ This::wxSizerFlags().
left(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Left,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerFlags(), Proportion::integer()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsproportion">external documentation</a>.
+-spec proportion(This, Proportion) -> wxSizerFlags() when
+ This::wxSizerFlags(), Proportion::integer().
proportion(#wx_ref{type=ThisT,ref=ThisRef},Proportion)
when is_integer(Proportion) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Proportion,
<<ThisRef:32/?UI,Proportion:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> wxSizerFlags()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizerflags.html#wxsizerflagsright">external documentation</a>.
+-spec right(This) -> wxSizerFlags() when
+ This::wxSizerFlags().
right(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerFlags),
wxe_util:call(?wxSizerFlags_Right,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerFlags()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSizerFlags()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSizerFlags),
wxe_util:destroy(?wxSizerFlags_destroy,Obj),
diff --git a/lib/wx/src/gen/wxSizerItem.erl b/lib/wx/src/gen/wxSizerItem.erl
index 1e9f05d53c..62655864d1 100644
--- a/lib/wx/src/gen/wxSizerItem.erl
+++ b/lib/wx/src/gen/wxSizerItem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,17 +35,20 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxSizerItem/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSizerItem()
+-type wxSizerItem() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemwxsizeritem">external documentation</a>.
+-spec new() -> wxSizerItem().
new() ->
wxe_util:construct(?wxSizerItem_new_0,
<<>>).
-%% @spec (Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Flags::wxSizerFlags:wxSizerFlags()) -> wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemwxsizeritem">external documentation</a>.
+-spec new(Window, Flags) -> wxSizerItem() when
+ Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Flags::wxSizerFlags:wxSizerFlags().
new(#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=FlagsT,ref=FlagsRef}) ->
WindowOP = case ?CLASS_T(WindowT,wxWindow) of
true ->
@@ -58,16 +61,18 @@ new(#wx_ref{type=WindowT,ref=WindowRef},#wx_ref{type=FlagsT,ref=FlagsRef}) ->
wxe_util:construct(WindowOP,
<<WindowRef:32/?UI,FlagsRef:32/?UI>>).
-%% @spec (Width::integer(), Height::integer(), Flags::wxSizerFlags:wxSizerFlags()) -> wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemwxsizeritem">external documentation</a>.
+-spec new(Width, Height, Flags) -> wxSizerItem() when
+ Width::integer(), Height::integer(), Flags::wxSizerFlags:wxSizerFlags().
new(Width,Height,#wx_ref{type=FlagsT,ref=FlagsRef})
when is_integer(Width),is_integer(Height) ->
?CLASS(FlagsT,wxSizerFlags),
wxe_util:construct(?wxSizerItem_new_3,
<<Width:32/?UI,Height:32/?UI,FlagsRef:32/?UI>>).
-%% @spec (Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Proportion::integer(), Flag::integer(), Border::integer(), UserData::wx:wx()) -> wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemwxsizeritem">external documentation</a>.
+-spec new(Window, Proportion, Flag, Border, UserData) -> wxSizerItem() when
+ Window::wxWindow:wxWindow() | wxSizer:wxSizer(), Proportion::integer(), Flag::integer(), Border::integer(), UserData::wx:wx_object().
new(#wx_ref{type=WindowT,ref=WindowRef},Proportion,Flag,Border,#wx_ref{type=UserDataT,ref=UserDataRef})
when is_integer(Proportion),is_integer(Flag),is_integer(Border) ->
WindowOP = case ?CLASS_T(WindowT,wxWindow) of
@@ -81,214 +86,241 @@ new(#wx_ref{type=WindowT,ref=WindowRef},Proportion,Flag,Border,#wx_ref{type=User
wxe_util:construct(WindowOP,
<<WindowRef:32/?UI,Proportion:32/?UI,Flag:32/?UI,Border:32/?UI,UserDataRef:32/?UI>>).
-%% @spec (Width::integer(), Height::integer(), Proportion::integer(), Flag::integer(), Border::integer(), UserData::wx:wx()) -> wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemwxsizeritem">external documentation</a>.
+-spec new(Width, Height, Proportion, Flag, Border, UserData) -> wxSizerItem() when
+ Width::integer(), Height::integer(), Proportion::integer(), Flag::integer(), Border::integer(), UserData::wx:wx_object().
new(Width,Height,Proportion,Flag,Border,#wx_ref{type=UserDataT,ref=UserDataRef})
when is_integer(Width),is_integer(Height),is_integer(Proportion),is_integer(Flag),is_integer(Border) ->
?CLASS(UserDataT,wx),
wxe_util:construct(?wxSizerItem_new_6,
<<Width:32/?UI,Height:32/?UI,Proportion:32/?UI,Flag:32/?UI,Border:32/?UI,UserDataRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemcalcmin">external documentation</a>.
+-spec calcMin(This) -> {W::integer(), H::integer()} when
+ This::wxSizerItem().
calcMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_CalcMin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemdeletewindows">external documentation</a>.
+-spec deleteWindows(This) -> ok when
+ This::wxSizerItem().
deleteWindows(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_DeleteWindows,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemdetachsizer">external documentation</a>.
+-spec detachSizer(This) -> ok when
+ This::wxSizerItem().
detachSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_DetachSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetborder">external documentation</a>.
+-spec getBorder(This) -> integer() when
+ This::wxSizerItem().
getBorder(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetBorder,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetflag">external documentation</a>.
+-spec getFlag(This) -> integer() when
+ This::wxSizerItem().
getFlag(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetFlag,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetminsize">external documentation</a>.
+-spec getMinSize(This) -> {W::integer(), H::integer()} when
+ This::wxSizerItem().
getMinSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetMinSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxSizerItem().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetproportion">external documentation</a>.
+-spec getProportion(This) -> integer() when
+ This::wxSizerItem().
getProportion(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetProportion,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> float()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetratio">external documentation</a>.
+-spec getRatio(This) -> number() when
+ This::wxSizerItem().
getRatio(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetRatio,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetrect">external documentation</a>.
+-spec getRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxSizerItem().
getRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetsize">external documentation</a>.
+-spec getSize(This) -> {W::integer(), H::integer()} when
+ This::wxSizerItem().
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> wxSizer:wxSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetsizer">external documentation</a>.
+-spec getSizer(This) -> wxSizer:wxSizer() when
+ This::wxSizerItem().
getSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetspacer">external documentation</a>.
+-spec getSpacer(This) -> {W::integer(), H::integer()} when
+ This::wxSizerItem().
getSpacer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetSpacer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetuserdata">external documentation</a>.
+-spec getUserData(This) -> wx:wx_object() when
+ This::wxSizerItem().
getUserData(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetUserData,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemgetwindow">external documentation</a>.
+-spec getWindow(This) -> wxWindow:wxWindow() when
+ This::wxSizerItem().
getWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_GetWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemissizer">external documentation</a>.
+-spec isSizer(This) -> boolean() when
+ This::wxSizerItem().
isSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_IsSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemisshown">external documentation</a>.
+-spec isShown(This) -> boolean() when
+ This::wxSizerItem().
isShown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_IsShown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemisspacer">external documentation</a>.
+-spec isSpacer(This) -> boolean() when
+ This::wxSizerItem().
isSpacer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_IsSpacer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemiswindow">external documentation</a>.
+-spec isWindow(This) -> boolean() when
+ This::wxSizerItem().
isWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:call(?wxSizerItem_IsWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizerItem(), Border::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetborder">external documentation</a>.
+-spec setBorder(This, Border) -> ok when
+ This::wxSizerItem(), Border::integer().
setBorder(#wx_ref{type=ThisT,ref=ThisRef},Border)
when is_integer(Border) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetBorder,
<<ThisRef:32/?UI,Border:32/?UI>>).
-%% @spec (This::wxSizerItem(), Pos::{X::integer(),Y::integer()}, Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetdimension">external documentation</a>.
+-spec setDimension(This, Pos, Size) -> ok when
+ This::wxSizerItem(), Pos::{X::integer(), Y::integer()}, Size::{W::integer(), H::integer()}.
setDimension(#wx_ref{type=ThisT,ref=ThisRef},{PosX,PosY},{SizeW,SizeH})
when is_integer(PosX),is_integer(PosY),is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetDimension,
<<ThisRef:32/?UI,PosX:32/?UI,PosY:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSizerItem(), Flag::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetflag">external documentation</a>.
+-spec setFlag(This, Flag) -> ok when
+ This::wxSizerItem(), Flag::integer().
setFlag(#wx_ref{type=ThisT,ref=ThisRef},Flag)
when is_integer(Flag) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetFlag,
<<ThisRef:32/?UI,Flag:32/?UI>>).
-%% @spec (This::wxSizerItem(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetinitsize">external documentation</a>.
+-spec setInitSize(This, X, Y) -> ok when
+ This::wxSizerItem(), X::integer(), Y::integer().
setInitSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetInitSize,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxSizerItem(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetminsize">external documentation</a>.
+-spec setMinSize(This, Size) -> ok when
+ This::wxSizerItem(), Size::{W::integer(), H::integer()}.
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetMinSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSizerItem(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetminsize">external documentation</a>.
+-spec setMinSize(This, X, Y) -> ok when
+ This::wxSizerItem(), X::integer(), Y::integer().
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetMinSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxSizerItem(), Proportion::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetproportion">external documentation</a>.
+-spec setProportion(This, Proportion) -> ok when
+ This::wxSizerItem(), Proportion::integer().
setProportion(#wx_ref{type=ThisT,ref=ThisRef},Proportion)
when is_integer(Proportion) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetProportion,
<<ThisRef:32/?UI,Proportion:32/?UI>>).
-%% @spec (This::wxSizerItem(),X::float()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetratio">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setRatio(This::wxSizerItem(), Ratio::float()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setRatio(This::wxSizerItem(), Size::{W::integer(),H::integer()}) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setRatio(This, Size) -> ok when<br />
+%% This::wxSizerItem(), Size::{W::integer(), H::integer()}.<br />
+%%
+-spec setRatio(This, Ratio) -> ok when
+ This::wxSizerItem(), Ratio::number();
+ (This, Size) -> ok when
+ This::wxSizerItem(), Size::{W::integer(), H::integer()}.
setRatio(#wx_ref{type=ThisT,ref=ThisRef},Ratio)
- when is_float(Ratio) ->
+ when is_number(Ratio) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetRatio_1_0,
<<ThisRef:32/?UI,Ratio:32/?F>>);
@@ -298,56 +330,62 @@ setRatio(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
wxe_util:cast(?wxSizerItem_SetRatio_1_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSizerItem(), Width::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetratio">external documentation</a>.
+-spec setRatio(This, Width, Height) -> ok when
+ This::wxSizerItem(), Width::integer(), Height::integer().
setRatio(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetRatio_2,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizerItem(), Sizer::wxSizer:wxSizer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetsizer">external documentation</a>.
+-spec setSizer(This, Sizer) -> ok when
+ This::wxSizerItem(), Sizer::wxSizer:wxSizer().
setSizer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}) ->
?CLASS(ThisT,wxSizerItem),
?CLASS(SizerT,wxSizer),
wxe_util:cast(?wxSizerItem_SetSizer,
<<ThisRef:32/?UI,SizerRef:32/?UI>>).
-%% @spec (This::wxSizerItem(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetspacer">external documentation</a>.
+-spec setSpacer(This, Size) -> ok when
+ This::wxSizerItem(), Size::{W::integer(), H::integer()}.
setSpacer(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetSpacer_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxSizerItem(), Width::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetspacer">external documentation</a>.
+-spec setSpacer(This, Width, Height) -> ok when
+ This::wxSizerItem(), Width::integer(), Height::integer().
setSpacer(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_SetSpacer_2,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxSizerItem(), Window::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemsetwindow">external documentation</a>.
+-spec setWindow(This, Window) -> ok when
+ This::wxSizerItem(), Window::wxWindow:wxWindow().
setWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSizerItem),
?CLASS(WindowT,wxWindow),
wxe_util:cast(?wxSizerItem_SetWindow,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSizerItem(), Show::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizeritem.html#wxsizeritemshow">external documentation</a>.
+-spec show(This, Show) -> ok when
+ This::wxSizerItem(), Show::boolean().
show(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxSizerItem),
wxe_util:cast(?wxSizerItem_Show,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxSizerItem()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSizerItem()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSizerItem),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSlider.erl b/lib/wx/src/gen/wxSlider.erl
index c70f127a5b..459e9b9c35 100644
--- a/lib/wx/src/gen/wxSlider.erl
+++ b/lib/wx/src/gen/wxSlider.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -71,27 +71,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxSlider/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSlider()
+-type wxSlider() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxsliderwxslider">external documentation</a>.
+-spec new() -> wxSlider().
new() ->
wxe_util:construct(?wxSlider_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer()) -> wxSlider()
%% @equiv new(Parent,Id,Value,MinValue,MaxValue, [])
+-spec new(Parent, Id, Value, MinValue, MaxValue) -> wxSlider() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer().
+
new(Parent,Id,Value,MinValue,MaxValue)
when is_record(Parent, wx_ref),is_integer(Id),is_integer(Value),is_integer(MinValue),is_integer(MaxValue) ->
new(Parent,Id,Value,MinValue,MaxValue, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer(), [Option]) -> wxSlider()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxsliderwxslider">external documentation</a>.
+-spec new(Parent, Id, Value, MinValue, MaxValue, [Option]) -> wxSlider() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Value,MinValue,MaxValue, Options)
when is_integer(Id),is_integer(Value),is_integer(MinValue),is_integer(MaxValue),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -104,15 +112,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Value,MinValue,MaxValue, Options)
wxe_util:construct(?wxSlider_new_6,
<<ParentRef:32/?UI,Id:32/?UI,Value:32/?UI,MinValue:32/?UI,MaxValue:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSlider(), Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer()) -> bool()
%% @equiv create(This,Parent,Id,Value,MinValue,MaxValue, [])
+-spec create(This, Parent, Id, Value, MinValue, MaxValue) -> boolean() when
+ This::wxSlider(), Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer().
+
create(This,Parent,Id,Value,MinValue,MaxValue)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_integer(Value),is_integer(MinValue),is_integer(MaxValue) ->
create(This,Parent,Id,Value,MinValue,MaxValue, []).
-%% @spec (This::wxSlider(), Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidercreate">external documentation</a>.
+-spec create(This, Parent, Id, Value, MinValue, MaxValue, [Option]) -> boolean() when
+ This::wxSlider(), Parent::wxWindow:wxWindow(), Id::integer(), Value::integer(), MinValue::integer(), MaxValue::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Value,MinValue,MaxValue, Options)
when is_integer(Id),is_integer(Value),is_integer(MinValue),is_integer(MaxValue),is_list(Options) ->
?CLASS(ThisT,wxSlider),
@@ -126,90 +140,101 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Va
wxe_util:call(?wxSlider_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,Value:32/?UI,MinValue:32/?UI,MaxValue:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSlider()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidergetlinesize">external documentation</a>.
+-spec getLineSize(This) -> integer() when
+ This::wxSlider().
getLineSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSlider),
wxe_util:call(?wxSlider_GetLineSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSlider()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidergetmax">external documentation</a>.
+-spec getMax(This) -> integer() when
+ This::wxSlider().
getMax(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSlider),
wxe_util:call(?wxSlider_GetMax,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSlider()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidergetmin">external documentation</a>.
+-spec getMin(This) -> integer() when
+ This::wxSlider().
getMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSlider),
wxe_util:call(?wxSlider_GetMin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSlider()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidergetpagesize">external documentation</a>.
+-spec getPageSize(This) -> integer() when
+ This::wxSlider().
getPageSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSlider),
wxe_util:call(?wxSlider_GetPageSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSlider()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidergetthumblength">external documentation</a>.
+-spec getThumbLength(This) -> integer() when
+ This::wxSlider().
getThumbLength(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSlider),
wxe_util:call(?wxSlider_GetThumbLength,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSlider()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidergetvalue">external documentation</a>.
+-spec getValue(This) -> integer() when
+ This::wxSlider().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSlider),
wxe_util:call(?wxSlider_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSlider(), LineSize::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidersetlinesize">external documentation</a>.
+-spec setLineSize(This, LineSize) -> ok when
+ This::wxSlider(), LineSize::integer().
setLineSize(#wx_ref{type=ThisT,ref=ThisRef},LineSize)
when is_integer(LineSize) ->
?CLASS(ThisT,wxSlider),
wxe_util:cast(?wxSlider_SetLineSize,
<<ThisRef:32/?UI,LineSize:32/?UI>>).
-%% @spec (This::wxSlider(), PageSize::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidersetpagesize">external documentation</a>.
+-spec setPageSize(This, PageSize) -> ok when
+ This::wxSlider(), PageSize::integer().
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},PageSize)
when is_integer(PageSize) ->
?CLASS(ThisT,wxSlider),
wxe_util:cast(?wxSlider_SetPageSize,
<<ThisRef:32/?UI,PageSize:32/?UI>>).
-%% @spec (This::wxSlider(), MinValue::integer(), MaxValue::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidersetrange">external documentation</a>.
+-spec setRange(This, MinValue, MaxValue) -> ok when
+ This::wxSlider(), MinValue::integer(), MaxValue::integer().
setRange(#wx_ref{type=ThisT,ref=ThisRef},MinValue,MaxValue)
when is_integer(MinValue),is_integer(MaxValue) ->
?CLASS(ThisT,wxSlider),
wxe_util:cast(?wxSlider_SetRange,
<<ThisRef:32/?UI,MinValue:32/?UI,MaxValue:32/?UI>>).
-%% @spec (This::wxSlider(), LenPixels::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidersetthumblength">external documentation</a>.
+-spec setThumbLength(This, LenPixels) -> ok when
+ This::wxSlider(), LenPixels::integer().
setThumbLength(#wx_ref{type=ThisT,ref=ThisRef},LenPixels)
when is_integer(LenPixels) ->
?CLASS(ThisT,wxSlider),
wxe_util:cast(?wxSlider_SetThumbLength,
<<ThisRef:32/?UI,LenPixels:32/?UI>>).
-%% @spec (This::wxSlider(), Value::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxslider.html#wxslidersetvalue">external documentation</a>.
+-spec setValue(This, Value) -> ok when
+ This::wxSlider(), Value::integer().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
when is_integer(Value) ->
?CLASS(ThisT,wxSlider),
wxe_util:cast(?wxSlider_SetValue,
<<ThisRef:32/?UI,Value:32/?UI>>).
-%% @spec (This::wxSlider()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSlider()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSlider),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSpinButton.erl b/lib/wx/src/gen/wxSpinButton.erl
index 027699e295..0f1dea75b6 100644
--- a/lib/wx/src/gen/wxSpinButton.erl
+++ b/lib/wx/src/gen/wxSpinButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +70,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxSpinButton/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSpinButton()
+-type wxSpinButton() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttonwxspinbutton">external documentation</a>.
+-spec new() -> wxSpinButton().
new() ->
wxe_util:construct(?wxSpinButton_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxSpinButton()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxSpinButton() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSpinButton()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttonwxspinbutton">external documentation</a>.
+-spec new(Parent, [Option]) -> wxSpinButton() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -103,15 +111,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxSpinButton_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSpinButton(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxSpinButton(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxSpinButton(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttoncreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxSpinButton(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSpinButton),
@@ -125,45 +139,50 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxSpinButton_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSpinButton()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttongetmax">external documentation</a>.
+-spec getMax(This) -> integer() when
+ This::wxSpinButton().
getMax(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinButton),
wxe_util:call(?wxSpinButton_GetMax,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinButton()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttongetmin">external documentation</a>.
+-spec getMin(This) -> integer() when
+ This::wxSpinButton().
getMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinButton),
wxe_util:call(?wxSpinButton_GetMin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinButton()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttongetvalue">external documentation</a>.
+-spec getValue(This) -> integer() when
+ This::wxSpinButton().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinButton),
wxe_util:call(?wxSpinButton_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinButton(), MinVal::integer(), MaxVal::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttonsetrange">external documentation</a>.
+-spec setRange(This, MinVal, MaxVal) -> ok when
+ This::wxSpinButton(), MinVal::integer(), MaxVal::integer().
setRange(#wx_ref{type=ThisT,ref=ThisRef},MinVal,MaxVal)
when is_integer(MinVal),is_integer(MaxVal) ->
?CLASS(ThisT,wxSpinButton),
wxe_util:cast(?wxSpinButton_SetRange,
<<ThisRef:32/?UI,MinVal:32/?UI,MaxVal:32/?UI>>).
-%% @spec (This::wxSpinButton(), Value::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinbutton.html#wxspinbuttonsetvalue">external documentation</a>.
+-spec setValue(This, Value) -> ok when
+ This::wxSpinButton(), Value::integer().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
when is_integer(Value) ->
?CLASS(ThisT,wxSpinButton),
wxe_util:cast(?wxSpinButton_SetValue,
<<ThisRef:32/?UI,Value:32/?UI>>).
-%% @spec (This::wxSpinButton()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSpinButton()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSpinButton),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSpinCtrl.erl b/lib/wx/src/gen/wxSpinCtrl.erl
index 6b77376b40..82e49da46d 100644
--- a/lib/wx/src/gen/wxSpinCtrl.erl
+++ b/lib/wx/src/gen/wxSpinCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +70,39 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxSpinCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSpinCtrl()
+-type wxSpinCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlwxspinctrl">external documentation</a>.
+-spec new() -> wxSpinCtrl().
new() ->
wxe_util:construct(?wxSpinCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxSpinCtrl()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxSpinCtrl() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSpinCtrl()
-%% Option = {id, integer()} | {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {min, integer()} | {max, integer()} | {initial, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlwxspinctrl">external documentation</a>.
+-spec new(Parent, [Option]) -> wxSpinCtrl() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {value, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {min, integer()}
+ | {max, integer()}
+ | {initial, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -107,15 +119,25 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxSpinCtrl_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSpinCtrl(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxSpinCtrl(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxSpinCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {min, integer()} | {max, integer()} | {initial, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxSpinCtrl(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {value, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {min, integer()}
+ | {max, integer()}
+ | {initial, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSpinCtrl),
@@ -133,15 +155,15 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxSpinCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSpinCtrl(),X::integer()|string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlsetvalue">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setValue(This::wxSpinCtrl(), Value::integer()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setValue(This::wxSpinCtrl(), Text::string()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setValue(This, Text) -> ok when<br />
+%% This::wxSpinCtrl(), Text::unicode:chardata().<br />
+%%
+-spec setValue(This, Value) -> ok when
+ This::wxSpinCtrl(), Value::integer();
+ (This, Text) -> ok when
+ This::wxSpinCtrl(), Text::unicode:chardata().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
when is_integer(Value) ->
?CLASS(ThisT,wxSpinCtrl),
@@ -154,45 +176,50 @@ setValue(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxSpinCtrl_SetValue_1_1,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxSpinCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlgetvalue">external documentation</a>.
+-spec getValue(This) -> integer() when
+ This::wxSpinCtrl().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinCtrl),
wxe_util:call(?wxSpinCtrl_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinCtrl(), MinVal::integer(), MaxVal::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlsetrange">external documentation</a>.
+-spec setRange(This, MinVal, MaxVal) -> ok when
+ This::wxSpinCtrl(), MinVal::integer(), MaxVal::integer().
setRange(#wx_ref{type=ThisT,ref=ThisRef},MinVal,MaxVal)
when is_integer(MinVal),is_integer(MaxVal) ->
?CLASS(ThisT,wxSpinCtrl),
wxe_util:cast(?wxSpinCtrl_SetRange,
<<ThisRef:32/?UI,MinVal:32/?UI,MaxVal:32/?UI>>).
-%% @spec (This::wxSpinCtrl(), From::integer(), To::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlsetselection">external documentation</a>.
+-spec setSelection(This, From, To) -> ok when
+ This::wxSpinCtrl(), From::integer(), To::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},From,To)
when is_integer(From),is_integer(To) ->
?CLASS(ThisT,wxSpinCtrl),
wxe_util:cast(?wxSpinCtrl_SetSelection,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxSpinCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlgetmin">external documentation</a>.
+-spec getMin(This) -> integer() when
+ This::wxSpinCtrl().
getMin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinCtrl),
wxe_util:call(?wxSpinCtrl_GetMin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinctrl.html#wxspinctrlgetmax">external documentation</a>.
+-spec getMax(This) -> integer() when
+ This::wxSpinCtrl().
getMax(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinCtrl),
wxe_util:call(?wxSpinCtrl_GetMax,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSpinCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSpinCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSpinEvent.erl b/lib/wx/src/gen/wxSpinEvent.erl
index 82edc70983..ecbe557c7b 100644
--- a/lib/wx/src/gen/wxSpinEvent.erl
+++ b/lib/wx/src/gen/wxSpinEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,21 +41,25 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxSpinEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSpinEvent()) -> integer()
+-type wxSpinEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinevent.html#wxspineventgetposition">external documentation</a>.
+-spec getPosition(This) -> integer() when
+ This::wxSpinEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSpinEvent),
wxe_util:call(?wxSpinEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSpinEvent(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxspinevent.html#wxspineventsetposition">external documentation</a>.
+-spec setPosition(This, Pos) -> ok when
+ This::wxSpinEvent(), Pos::integer().
setPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxSpinEvent),
diff --git a/lib/wx/src/gen/wxSplashScreen.erl b/lib/wx/src/gen/wxSplashScreen.erl
index 8806d07018..2222f5e64e 100644
--- a/lib/wx/src/gen/wxSplashScreen.erl
+++ b/lib/wx/src/gen/wxSplashScreen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +80,7 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxSplashScreen/0]).
%% @hidden
parent_class(wxFrame) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -87,21 +88,27 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSplashScreen()
+-type wxSplashScreen() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplashscreen.html#wxsplashscreenwxsplashscreen">external documentation</a>.
+-spec new() -> wxSplashScreen().
new() ->
wxe_util:construct(?wxSplashScreen_new_0,
<<>>).
-%% @spec (Bitmap::wxBitmap:wxBitmap(), SplashStyle::integer(), Milliseconds::integer(), Parent::wxWindow:wxWindow(), Id::integer()) -> wxSplashScreen()
%% @equiv new(Bitmap,SplashStyle,Milliseconds,Parent,Id, [])
+-spec new(Bitmap, SplashStyle, Milliseconds, Parent, Id) -> wxSplashScreen() when
+ Bitmap::wxBitmap:wxBitmap(), SplashStyle::integer(), Milliseconds::integer(), Parent::wxWindow:wxWindow(), Id::integer().
+
new(Bitmap,SplashStyle,Milliseconds,Parent,Id)
when is_record(Bitmap, wx_ref),is_integer(SplashStyle),is_integer(Milliseconds),is_record(Parent, wx_ref),is_integer(Id) ->
new(Bitmap,SplashStyle,Milliseconds,Parent,Id, []).
-%% @spec (Bitmap::wxBitmap:wxBitmap(), SplashStyle::integer(), Milliseconds::integer(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxSplashScreen()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplashscreen.html#wxsplashscreenwxsplashscreen">external documentation</a>.
+-spec new(Bitmap, SplashStyle, Milliseconds, Parent, Id, [Option]) -> wxSplashScreen() when
+ Bitmap::wxBitmap:wxBitmap(), SplashStyle::integer(), Milliseconds::integer(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=BitmapT,ref=BitmapRef},SplashStyle,Milliseconds,#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(SplashStyle),is_integer(Milliseconds),is_integer(Id),is_list(Options) ->
?CLASS(BitmapT,wxBitmap),
@@ -114,22 +121,24 @@ new(#wx_ref{type=BitmapT,ref=BitmapRef},SplashStyle,Milliseconds,#wx_ref{type=Pa
wxe_util:construct(?wxSplashScreen_new_6,
<<BitmapRef:32/?UI,SplashStyle:32/?UI,Milliseconds:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSplashScreen()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplashscreen.html#wxsplashscreengetsplashstyle">external documentation</a>.
+-spec getSplashStyle(This) -> integer() when
+ This::wxSplashScreen().
getSplashStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplashScreen),
wxe_util:call(?wxSplashScreen_GetSplashStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplashScreen()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplashscreen.html#wxsplashscreengettimeout">external documentation</a>.
+-spec getTimeout(This) -> integer() when
+ This::wxSplashScreen().
getTimeout(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplashScreen),
wxe_util:call(?wxSplashScreen_GetTimeout,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplashScreen()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSplashScreen()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSplashScreen),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxSplitterEvent.erl b/lib/wx/src/gen/wxSplitterEvent.erl
index 512f858284..bba9b13abd 100644
--- a/lib/wx/src/gen/wxSplitterEvent.erl
+++ b/lib/wx/src/gen/wxSplitterEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,42 +41,49 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxSplitterEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxSplitterEvent()) -> integer()
+-type wxSplitterEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterevent.html#wxsplittereventgetsashposition">external documentation</a>.
+-spec getSashPosition(This) -> integer() when
+ This::wxSplitterEvent().
getSashPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterEvent),
wxe_util:call(?wxSplitterEvent_GetSashPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterevent.html#wxsplittereventgetx">external documentation</a>.
+-spec getX(This) -> integer() when
+ This::wxSplitterEvent().
getX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterEvent),
wxe_util:call(?wxSplitterEvent_GetX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterevent.html#wxsplittereventgety">external documentation</a>.
+-spec getY(This) -> integer() when
+ This::wxSplitterEvent().
getY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterEvent),
wxe_util:call(?wxSplitterEvent_GetY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterEvent()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterevent.html#wxsplittereventgetwindowbeingremoved">external documentation</a>.
+-spec getWindowBeingRemoved(This) -> wxWindow:wxWindow() when
+ This::wxSplitterEvent().
getWindowBeingRemoved(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterEvent),
wxe_util:call(?wxSplitterEvent_GetWindowBeingRemoved,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterEvent(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterevent.html#wxsplittereventsetsashposition">external documentation</a>.
+-spec setSashPosition(This, Pos) -> ok when
+ This::wxSplitterEvent(), Pos::integer().
setSashPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxSplitterEvent),
diff --git a/lib/wx/src/gen/wxSplitterWindow.erl b/lib/wx/src/gen/wxSplitterWindow.erl
index 9e27be7475..231f93911f 100644
--- a/lib/wx/src/gen/wxSplitterWindow.erl
+++ b/lib/wx/src/gen/wxSplitterWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,26 +73,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxSplitterWindow/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxSplitterWindow()
+-type wxSplitterWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowwxsplitterwindow">external documentation</a>.
+-spec new() -> wxSplitterWindow().
new() ->
wxe_util:construct(?wxSplitterWindow_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxSplitterWindow()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxSplitterWindow() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxSplitterWindow()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowwxsplitterwindow">external documentation</a>.
+-spec new(Parent, [Option]) -> wxSplitterWindow() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -105,15 +113,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxSplitterWindow_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSplitterWindow(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxSplitterWindow(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxSplitterWindow(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxSplitterWindow(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSplitterWindow),
@@ -127,67 +141,75 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxSplitterWindow_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSplitterWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowgetminimumpanesize">external documentation</a>.
+-spec getMinimumPaneSize(This) -> integer() when
+ This::wxSplitterWindow().
getMinimumPaneSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_GetMinimumPaneSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> float()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowgetsashgravity">external documentation</a>.
+-spec getSashGravity(This) -> number() when
+ This::wxSplitterWindow().
getSashGravity(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_GetSashGravity,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowgetsashposition">external documentation</a>.
+-spec getSashPosition(This) -> integer() when
+ This::wxSplitterWindow().
getSashPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_GetSashPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> WxSplitMode
-%% WxSplitMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowgetsplitmode">external documentation</a>.
-%%<br /> WxSplitMode is one of ?wxSPLIT_HORIZONTAL | ?wxSPLIT_VERTICAL
+%%<br /> Res = ?wxSPLIT_HORIZONTAL | ?wxSPLIT_VERTICAL
+-spec getSplitMode(This) -> wx:wx_enum() when
+ This::wxSplitterWindow().
getSplitMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_GetSplitMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowgetwindow1">external documentation</a>.
+-spec getWindow1(This) -> wxWindow:wxWindow() when
+ This::wxSplitterWindow().
getWindow1(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_GetWindow1,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowgetwindow2">external documentation</a>.
+-spec getWindow2(This) -> wxWindow:wxWindow() when
+ This::wxSplitterWindow().
getWindow2(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_GetWindow2,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow(), Window::wxWindow:wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowinitialize">external documentation</a>.
+-spec initialize(This, Window) -> ok when
+ This::wxSplitterWindow(), Window::wxWindow:wxWindow().
initialize(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}) ->
?CLASS(ThisT,wxSplitterWindow),
?CLASS(WindowT,wxWindow),
wxe_util:cast(?wxSplitterWindow_Initialize,
<<ThisRef:32/?UI,WindowRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowissplit">external documentation</a>.
+-spec isSplit(This) -> boolean() when
+ This::wxSplitterWindow().
isSplit(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:call(?wxSplitterWindow_IsSplit,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow(), WinOld::wxWindow:wxWindow(), WinNew::wxWindow:wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowreplacewindow">external documentation</a>.
+-spec replaceWindow(This, WinOld, WinNew) -> boolean() when
+ This::wxSplitterWindow(), WinOld::wxWindow:wxWindow(), WinNew::wxWindow:wxWindow().
replaceWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WinOldT,ref=WinOldRef},#wx_ref{type=WinNewT,ref=WinNewRef}) ->
?CLASS(ThisT,wxSplitterWindow),
?CLASS(WinOldT,wxWindow),
@@ -195,23 +217,27 @@ replaceWindow(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WinOldT,ref=WinOldRef
wxe_util:call(?wxSplitterWindow_ReplaceWindow,
<<ThisRef:32/?UI,WinOldRef:32/?UI,WinNewRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow(), Gravity::float()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsetsashgravity">external documentation</a>.
+-spec setSashGravity(This, Gravity) -> ok when
+ This::wxSplitterWindow(), Gravity::number().
setSashGravity(#wx_ref{type=ThisT,ref=ThisRef},Gravity)
- when is_float(Gravity) ->
+ when is_number(Gravity) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:cast(?wxSplitterWindow_SetSashGravity,
<<ThisRef:32/?UI,0:32,Gravity:64/?F>>).
-%% @spec (This::wxSplitterWindow(), Position::integer()) -> ok
%% @equiv setSashPosition(This,Position, [])
+-spec setSashPosition(This, Position) -> ok when
+ This::wxSplitterWindow(), Position::integer().
+
setSashPosition(This,Position)
when is_record(This, wx_ref),is_integer(Position) ->
setSashPosition(This,Position, []).
-%% @spec (This::wxSplitterWindow(), Position::integer(), [Option]) -> ok
-%% Option = {redraw, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsetsashposition">external documentation</a>.
+-spec setSashPosition(This, Position, [Option]) -> ok when
+ This::wxSplitterWindow(), Position::integer(),
+ Option :: {redraw, boolean()}.
setSashPosition(#wx_ref{type=ThisT,ref=ThisRef},Position, Options)
when is_integer(Position),is_list(Options) ->
?CLASS(ThisT,wxSplitterWindow),
@@ -221,39 +247,45 @@ setSashPosition(#wx_ref{type=ThisT,ref=ThisRef},Position, Options)
wxe_util:cast(?wxSplitterWindow_SetSashPosition,
<<ThisRef:32/?UI,Position:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSplitterWindow(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsetsashsize">external documentation</a>.
+-spec setSashSize(This, Width) -> ok when
+ This::wxSplitterWindow(), Width::integer().
setSashSize(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:cast(?wxSplitterWindow_SetSashSize,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxSplitterWindow(), Min::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsetminimumpanesize">external documentation</a>.
+-spec setMinimumPaneSize(This, Min) -> ok when
+ This::wxSplitterWindow(), Min::integer().
setMinimumPaneSize(#wx_ref{type=ThisT,ref=ThisRef},Min)
when is_integer(Min) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:cast(?wxSplitterWindow_SetMinimumPaneSize,
<<ThisRef:32/?UI,Min:32/?UI>>).
-%% @spec (This::wxSplitterWindow(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsetsplitmode">external documentation</a>.
+-spec setSplitMode(This, Mode) -> ok when
+ This::wxSplitterWindow(), Mode::integer().
setSplitMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:cast(?wxSplitterWindow_SetSplitMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow()) -> bool()
%% @equiv splitHorizontally(This,Window1,Window2, [])
+-spec splitHorizontally(This, Window1, Window2) -> boolean() when
+ This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow().
+
splitHorizontally(This,Window1,Window2)
when is_record(This, wx_ref),is_record(Window1, wx_ref),is_record(Window2, wx_ref) ->
splitHorizontally(This,Window1,Window2, []).
-%% @spec (This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {sashPosition, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsplithorizontally">external documentation</a>.
+-spec splitHorizontally(This, Window1, Window2, [Option]) -> boolean() when
+ This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow(),
+ Option :: {sashPosition, integer()}.
splitHorizontally(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Window1T,ref=Window1Ref},#wx_ref{type=Window2T,ref=Window2Ref}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSplitterWindow),
@@ -265,15 +297,18 @@ splitHorizontally(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Window1T,ref=Wind
wxe_util:call(?wxSplitterWindow_SplitHorizontally,
<<ThisRef:32/?UI,Window1Ref:32/?UI,Window2Ref:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow()) -> bool()
%% @equiv splitVertically(This,Window1,Window2, [])
+-spec splitVertically(This, Window1, Window2) -> boolean() when
+ This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow().
+
splitVertically(This,Window1,Window2)
when is_record(This, wx_ref),is_record(Window1, wx_ref),is_record(Window2, wx_ref) ->
splitVertically(This,Window1,Window2, []).
-%% @spec (This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {sashPosition, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowsplitvertically">external documentation</a>.
+-spec splitVertically(This, Window1, Window2, [Option]) -> boolean() when
+ This::wxSplitterWindow(), Window1::wxWindow:wxWindow(), Window2::wxWindow:wxWindow(),
+ Option :: {sashPosition, integer()}.
splitVertically(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Window1T,ref=Window1Ref},#wx_ref{type=Window2T,ref=Window2Ref}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSplitterWindow),
@@ -285,15 +320,18 @@ splitVertically(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=Window1T,ref=Window
wxe_util:call(?wxSplitterWindow_SplitVertically,
<<ThisRef:32/?UI,Window1Ref:32/?UI,Window2Ref:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSplitterWindow()) -> bool()
%% @equiv unsplit(This, [])
+-spec unsplit(This) -> boolean() when
+ This::wxSplitterWindow().
+
unsplit(This)
when is_record(This, wx_ref) ->
unsplit(This, []).
-%% @spec (This::wxSplitterWindow(), [Option]) -> bool()
-%% Option = {toRemove, wxWindow:wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowunsplit">external documentation</a>.
+-spec unsplit(This, [Option]) -> boolean() when
+ This::wxSplitterWindow(),
+ Option :: {toRemove, wxWindow:wxWindow()}.
unsplit(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxSplitterWindow),
@@ -303,15 +341,16 @@ unsplit(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxSplitterWindow_Unsplit,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxSplitterWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsplitterwindow.html#wxsplitterwindowupdatesize">external documentation</a>.
+-spec updateSize(This) -> ok when
+ This::wxSplitterWindow().
updateSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxSplitterWindow),
wxe_util:cast(?wxSplitterWindow_UpdateSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSplitterWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxSplitterWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxSplitterWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStaticBitmap.erl b/lib/wx/src/gen/wxStaticBitmap.erl
index 6fbc59236d..02272c8107 100644
--- a/lib/wx/src/gen/wxStaticBitmap.erl
+++ b/lib/wx/src/gen/wxStaticBitmap.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +69,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxStaticBitmap/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStaticBitmap()
+-type wxStaticBitmap() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapwxstaticbitmap">external documentation</a>.
+-spec new() -> wxStaticBitmap().
new() ->
wxe_util:construct(?wxStaticBitmap_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap()) -> wxStaticBitmap()
%% @equiv new(Parent,Id,Label, [])
+-spec new(Parent, Id, Label) -> wxStaticBitmap() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap().
+
new(Parent,Id,Label)
when is_record(Parent, wx_ref),is_integer(Id),is_record(Label, wx_ref) ->
new(Parent,Id,Label, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap(), [Option]) -> wxStaticBitmap()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapwxstaticbitmap">external documentation</a>.
+-spec new(Parent, Id, Label, [Option]) -> wxStaticBitmap() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=LabelT,ref=LabelRef}, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -102,15 +109,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=LabelT,ref=LabelRef}, Op
wxe_util:construct(?wxStaticBitmap_new_4,
<<ParentRef:32/?UI,Id:32/?UI,LabelRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStaticBitmap(), Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap()) -> bool()
%% @equiv create(This,Parent,Id,Label, [])
+-spec create(This, Parent, Id, Label) -> boolean() when
+ This::wxStaticBitmap(), Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap().
+
create(This,Parent,Id,Label)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_record(Label, wx_ref) ->
create(This,Parent,Id,Label, []).
-%% @spec (This::wxStaticBitmap(), Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapcreate">external documentation</a>.
+-spec create(This, Parent, Id, Label, [Option]) -> boolean() when
+ This::wxStaticBitmap(), Parent::wxWindow:wxWindow(), Id::integer(), Label::wxBitmap:wxBitmap(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#wx_ref{type=LabelT,ref=LabelRef}, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxStaticBitmap),
@@ -124,23 +136,25 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,#w
wxe_util:call(?wxStaticBitmap_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,LabelRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStaticBitmap()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapgetbitmap">external documentation</a>.
+-spec getBitmap(This) -> wxBitmap:wxBitmap() when
+ This::wxStaticBitmap().
getBitmap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStaticBitmap),
wxe_util:call(?wxStaticBitmap_GetBitmap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStaticBitmap(), Bitmap::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbitmap.html#wxstaticbitmapsetbitmap">external documentation</a>.
+-spec setBitmap(This, Bitmap) -> ok when
+ This::wxStaticBitmap(), Bitmap::wxBitmap:wxBitmap().
setBitmap(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BitmapT,ref=BitmapRef}) ->
?CLASS(ThisT,wxStaticBitmap),
?CLASS(BitmapT,wxBitmap),
wxe_util:cast(?wxStaticBitmap_SetBitmap,
<<ThisRef:32/?UI,BitmapRef:32/?UI>>).
-%% @spec (This::wxStaticBitmap()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStaticBitmap()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStaticBitmap),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStaticBox.erl b/lib/wx/src/gen/wxStaticBox.erl
index ad54184867..e4e390610a 100644
--- a/lib/wx/src/gen/wxStaticBox.erl
+++ b/lib/wx/src/gen/wxStaticBox.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +69,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxStaticBox/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStaticBox()
+-type wxStaticBox() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbox.html#wxstaticboxwxstaticbox">external documentation</a>.
+-spec new() -> wxStaticBox().
new() ->
wxe_util:construct(?wxStaticBox_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> wxStaticBox()
%% @equiv new(Parent,Id,Label, [])
+-spec new(Parent, Id, Label) -> wxStaticBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
new(Parent,Id,Label)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
new(Parent,Id,Label, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxStaticBox()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbox.html#wxstaticboxwxstaticbox">external documentation</a>.
+-spec new(Parent, Id, Label, [Option]) -> wxStaticBox() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -102,15 +109,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
wxe_util:construct(?wxStaticBox_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStaticBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> bool()
%% @equiv create(This,Parent,Id,Label, [])
+-spec create(This, Parent, Id, Label) -> boolean() when
+ This::wxStaticBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
create(This,Parent,Id,Label)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
create(This,Parent,Id,Label, []).
-%% @spec (This::wxStaticBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticbox.html#wxstaticboxcreate">external documentation</a>.
+-spec create(This, Parent, Id, Label, [Option]) -> boolean() when
+ This::wxStaticBox(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxStaticBox),
@@ -124,8 +136,8 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,La
wxe_util:call(?wxStaticBox_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStaticBox()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStaticBox()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStaticBox),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStaticBoxSizer.erl b/lib/wx/src/gen/wxStaticBoxSizer.erl
index 2cf9f64325..fc8afc1146 100644
--- a/lib/wx/src/gen/wxStaticBoxSizer.erl
+++ b/lib/wx/src/gen/wxStaticBoxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,19 +41,22 @@
setItemMinSize/4,setMinSize/2,setMinSize/3,setSizeHints/2,setVirtualSizeHints/2,
show/2,show/3]).
+-export_type([wxStaticBoxSizer/0]).
%% @hidden
parent_class(wxBoxSizer) -> true;
parent_class(wxSizer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (X::integer()|term(),X::term()|integer()) -> wxStaticBoxSizer()
+-type wxStaticBoxSizer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticboxsizer.html#wxstaticboxsizerwxstaticboxsizer">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% new(Orient::integer(), Win::wxWindow:wxWindow()) -> new(Orient,Win, []) </c></p>
-%% <p><c>
-%% new(Box::wxStaticBox:wxStaticBox(), Orient::integer()) -> wxStaticBoxSizer() </c>
-%% </p>
+%% <br /> Also:<br />
+%% new(Box, Orient) -> wxStaticBoxSizer() when<br />
+%% Box::wxStaticBox:wxStaticBox(), Orient::integer().<br />
+%%
+-spec new(Orient, Win) -> wxStaticBoxSizer() when
+ Orient::integer(), Win::wxWindow:wxWindow();
+ (Box, Orient) -> wxStaticBoxSizer() when
+ Box::wxStaticBox:wxStaticBox(), Orient::integer().
new(Orient,Win)
when is_integer(Orient),is_record(Win, wx_ref) ->
@@ -64,9 +67,10 @@ new(#wx_ref{type=BoxT,ref=BoxRef},Orient)
wxe_util:construct(?wxStaticBoxSizer_new_2,
<<BoxRef:32/?UI,Orient:32/?UI>>).
-%% @spec (Orient::integer(), Win::wxWindow:wxWindow(), [Option]) -> wxStaticBoxSizer()
-%% Option = {label, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticboxsizer.html#wxstaticboxsizerwxstaticboxsizer">external documentation</a>.
+-spec new(Orient, Win, [Option]) -> wxStaticBoxSizer() when
+ Orient::integer(), Win::wxWindow:wxWindow(),
+ Option :: {label, unicode:chardata()}.
new(Orient,#wx_ref{type=WinT,ref=WinRef}, Options)
when is_integer(Orient),is_list(Options) ->
?CLASS(WinT,wxWindow),
@@ -76,15 +80,16 @@ new(Orient,#wx_ref{type=WinT,ref=WinRef}, Options)
wxe_util:construct(?wxStaticBoxSizer_new_3,
<<Orient:32/?UI,WinRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStaticBoxSizer()) -> wxStaticBox:wxStaticBox()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticboxsizer.html#wxstaticboxsizergetstaticbox">external documentation</a>.
+-spec getStaticBox(This) -> wxStaticBox:wxStaticBox() when
+ This::wxStaticBoxSizer().
getStaticBox(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStaticBoxSizer),
wxe_util:call(?wxStaticBoxSizer_GetStaticBox,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStaticBoxSizer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStaticBoxSizer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStaticBoxSizer),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStaticLine.erl b/lib/wx/src/gen/wxStaticLine.erl
index e3a1bedbdc..86a9975312 100644
--- a/lib/wx/src/gen/wxStaticLine.erl
+++ b/lib/wx/src/gen/wxStaticLine.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +70,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxStaticLine/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStaticLine()
+-type wxStaticLine() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlinewxstaticline">external documentation</a>.
+-spec new() -> wxStaticLine().
new() ->
wxe_util:construct(?wxStaticLine_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxStaticLine()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxStaticLine() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxStaticLine()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlinewxstaticline">external documentation</a>.
+-spec new(Parent, [Option]) -> wxStaticLine() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -103,15 +111,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxStaticLine_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStaticLine(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxStaticLine(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxStaticLine(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlinecreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxStaticLine(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxStaticLine),
@@ -125,21 +139,22 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxStaticLine_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStaticLine()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlineisvertical">external documentation</a>.
+-spec isVertical(This) -> boolean() when
+ This::wxStaticLine().
isVertical(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStaticLine),
wxe_util:call(?wxStaticLine_IsVertical,
<<ThisRef:32/?UI>>).
-%% @spec () -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstaticline.html#wxstaticlinegetdefaultsize">external documentation</a>.
+-spec getDefaultSize() -> integer().
getDefaultSize() ->
wxe_util:call(?wxStaticLine_GetDefaultSize,
<<>>).
-%% @spec (This::wxStaticLine()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStaticLine()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStaticLine),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStaticText.erl b/lib/wx/src/gen/wxStaticText.erl
index 46c73a5998..de779f66fc 100644
--- a/lib/wx/src/gen/wxStaticText.erl
+++ b/lib/wx/src/gen/wxStaticText.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +69,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxStaticText/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStaticText()
+-type wxStaticText() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextwxstatictext">external documentation</a>.
+-spec new() -> wxStaticText().
new() ->
wxe_util:construct(?wxStaticText_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> wxStaticText()
%% @equiv new(Parent,Id,Label, [])
+-spec new(Parent, Id, Label) -> wxStaticText() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
new(Parent,Id,Label)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
new(Parent,Id,Label, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxStaticText()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextwxstatictext">external documentation</a>.
+-spec new(Parent, Id, Label, [Option]) -> wxStaticText() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -102,15 +109,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
wxe_util:construct(?wxStaticText_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStaticText(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> bool()
%% @equiv create(This,Parent,Id,Label, [])
+-spec create(This, Parent, Id, Label) -> boolean() when
+ This::wxStaticText(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
create(This,Parent,Id,Label)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
create(This,Parent,Id,Label, []).
-%% @spec (This::wxStaticText(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextcreate">external documentation</a>.
+-spec create(This, Parent, Id, Label, [Option]) -> boolean() when
+ This::wxStaticText(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxStaticText),
@@ -124,15 +136,17 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,La
wxe_util:call(?wxStaticText_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStaticText()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextgetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxStaticText().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStaticText),
wxe_util:call(?wxStaticText_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStaticText(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextsetlabel">external documentation</a>.
+-spec setLabel(This, Label) -> ok when
+ This::wxStaticText(), Label::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
when is_list(Label) ->
?CLASS(ThisT,wxStaticText),
@@ -140,16 +154,17 @@ setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
wxe_util:cast(?wxStaticText_SetLabel,
<<ThisRef:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStaticText(), Width::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatictext.html#wxstatictextwrap">external documentation</a>.
+-spec wrap(This, Width) -> ok when
+ This::wxStaticText(), Width::integer().
wrap(#wx_ref{type=ThisT,ref=ThisRef},Width)
when is_integer(Width) ->
?CLASS(ThisT,wxStaticText),
wxe_util:cast(?wxStaticText_Wrap,
<<ThisRef:32/?UI,Width:32/?UI>>).
-%% @spec (This::wxStaticText()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStaticText()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStaticText),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStatusBar.erl b/lib/wx/src/gen/wxStatusBar.erl
index 52467117d7..31dab03b56 100644
--- a/lib/wx/src/gen/wxStatusBar.erl
+++ b/lib/wx/src/gen/wxStatusBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -71,26 +71,32 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxStatusBar/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStatusBar()
+-type wxStatusBar() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarwxstatusbar">external documentation</a>.
+-spec new() -> wxStatusBar().
new() ->
wxe_util:construct(?wxStatusBar_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxStatusBar()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxStatusBar() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxStatusBar()
-%% Option = {winid, integer()} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarwxstatusbar">external documentation</a>.
+-spec new(Parent, [Option]) -> wxStatusBar() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {winid, integer()}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -101,15 +107,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxStatusBar_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxStatusBar(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxStatusBar(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {winid, integer()} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxStatusBar(), Parent::wxWindow:wxWindow(),
+ Option :: {winid, integer()}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxStatusBar),
@@ -121,30 +131,35 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxStatusBar_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), I::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbargetfieldrect">external documentation</a>.
+-spec getFieldRect(This, I, Rect) -> boolean() when
+ This::wxStatusBar(), I::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
getFieldRect(#wx_ref{type=ThisT,ref=ThisRef},I,{RectX,RectY,RectW,RectH})
when is_integer(I),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
?CLASS(ThisT,wxStatusBar),
wxe_util:call(?wxStatusBar_GetFieldRect,
<<ThisRef:32/?UI,I:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxStatusBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbargetfieldscount">external documentation</a>.
+-spec getFieldsCount(This) -> integer() when
+ This::wxStatusBar().
getFieldsCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStatusBar),
wxe_util:call(?wxStatusBar_GetFieldsCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStatusBar()) -> string()
%% @equiv getStatusText(This, [])
+-spec getStatusText(This) -> unicode:charlist() when
+ This::wxStatusBar().
+
getStatusText(This)
when is_record(This, wx_ref) ->
getStatusText(This, []).
-%% @spec (This::wxStatusBar(), [Option]) -> string()
-%% Option = {number, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbargetstatustext">external documentation</a>.
+-spec getStatusText(This, [Option]) -> unicode:charlist() when
+ This::wxStatusBar(),
+ Option :: {number, integer()}.
getStatusText(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxStatusBar),
@@ -154,15 +169,18 @@ getStatusText(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxStatusBar_GetStatusText,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStatusBar()) -> ok
%% @equiv popStatusText(This, [])
+-spec popStatusText(This) -> ok when
+ This::wxStatusBar().
+
popStatusText(This)
when is_record(This, wx_ref) ->
popStatusText(This, []).
-%% @spec (This::wxStatusBar(), [Option]) -> ok
-%% Option = {number, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarpopstatustext">external documentation</a>.
+-spec popStatusText(This, [Option]) -> ok when
+ This::wxStatusBar(),
+ Option :: {number, integer()}.
popStatusText(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxStatusBar),
@@ -172,15 +190,18 @@ popStatusText(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxStatusBar_PopStatusText,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), Text::string()) -> ok
%% @equiv pushStatusText(This,Text, [])
+-spec pushStatusText(This, Text) -> ok when
+ This::wxStatusBar(), Text::unicode:chardata().
+
pushStatusText(This,Text)
when is_record(This, wx_ref),is_list(Text) ->
pushStatusText(This,Text, []).
-%% @spec (This::wxStatusBar(), Text::string(), [Option]) -> ok
-%% Option = {number, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarpushstatustext">external documentation</a>.
+-spec pushStatusText(This, Text, [Option]) -> ok when
+ This::wxStatusBar(), Text::unicode:chardata(),
+ Option :: {number, integer()}.
pushStatusText(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxStatusBar),
@@ -191,15 +212,18 @@ pushStatusText(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
wxe_util:cast(?wxStatusBar_PushStatusText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), Number::integer()) -> ok
%% @equiv setFieldsCount(This,Number, [])
+-spec setFieldsCount(This, Number) -> ok when
+ This::wxStatusBar(), Number::integer().
+
setFieldsCount(This,Number)
when is_record(This, wx_ref),is_integer(Number) ->
setFieldsCount(This,Number, []).
-%% @spec (This::wxStatusBar(), Number::integer(), [Option]) -> ok
-%% Option = {widths, [integer()]}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarsetfieldscount">external documentation</a>.
+-spec setFieldsCount(This, Number, [Option]) -> ok when
+ This::wxStatusBar(), Number::integer(),
+ Option :: {widths, [integer()]}.
setFieldsCount(#wx_ref{type=ThisT,ref=ThisRef},Number, Options)
when is_integer(Number),is_list(Options) ->
?CLASS(ThisT,wxStatusBar),
@@ -210,23 +234,27 @@ setFieldsCount(#wx_ref{type=ThisT,ref=ThisRef},Number, Options)
wxe_util:cast(?wxStatusBar_SetFieldsCount,
<<ThisRef:32/?UI,Number:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarsetminheight">external documentation</a>.
+-spec setMinHeight(This, Height) -> ok when
+ This::wxStatusBar(), Height::integer().
setMinHeight(#wx_ref{type=ThisT,ref=ThisRef},Height)
when is_integer(Height) ->
?CLASS(ThisT,wxStatusBar),
wxe_util:cast(?wxStatusBar_SetMinHeight,
<<ThisRef:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxStatusBar(), Text::string()) -> ok
%% @equiv setStatusText(This,Text, [])
+-spec setStatusText(This, Text) -> ok when
+ This::wxStatusBar(), Text::unicode:chardata().
+
setStatusText(This,Text)
when is_record(This, wx_ref),is_list(Text) ->
setStatusText(This,Text, []).
-%% @spec (This::wxStatusBar(), Text::string(), [Option]) -> ok
-%% Option = {number, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarsetstatustext">external documentation</a>.
+-spec setStatusText(This, Text, [Option]) -> ok when
+ This::wxStatusBar(), Text::unicode:chardata(),
+ Option :: {number, integer()}.
setStatusText(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxStatusBar),
@@ -237,8 +265,9 @@ setStatusText(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
wxe_util:cast(?wxStatusBar_SetStatusText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStatusBar(), Widths_field::[integer()]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarsetstatuswidths">external documentation</a>.
+-spec setStatusWidths(This, Widths_field) -> ok when
+ This::wxStatusBar(), Widths_field::[integer()].
setStatusWidths(#wx_ref{type=ThisT,ref=ThisRef},Widths_field)
when is_list(Widths_field) ->
?CLASS(ThisT,wxStatusBar),
@@ -246,8 +275,9 @@ setStatusWidths(#wx_ref{type=ThisT,ref=ThisRef},Widths_field)
<<ThisRef:32/?UI,(length(Widths_field)):32/?UI,
(<< <<C:32/?I>> || C <- Widths_field>>)/binary, 0:(((0+length(Widths_field)) rem 2)*32)>>).
-%% @spec (This::wxStatusBar(), Styles::[integer()]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstatusbar.html#wxstatusbarsetstatusstyles">external documentation</a>.
+-spec setStatusStyles(This, Styles) -> ok when
+ This::wxStatusBar(), Styles::[integer()].
setStatusStyles(#wx_ref{type=ThisT,ref=ThisRef},Styles)
when is_list(Styles) ->
?CLASS(ThisT,wxStatusBar),
@@ -255,8 +285,8 @@ setStatusStyles(#wx_ref{type=ThisT,ref=ThisRef},Styles)
<<ThisRef:32/?UI,(length(Styles)):32/?UI,
(<< <<C:32/?I>> || C <- Styles>>)/binary, 0:(((0+length(Styles)) rem 2)*32)>>).
-%% @spec (This::wxStatusBar()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStatusBar()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStatusBar),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStdDialogButtonSizer.erl b/lib/wx/src/gen/wxStdDialogButtonSizer.erl
index 3d31907275..078763e7cb 100644
--- a/lib/wx/src/gen/wxStdDialogButtonSizer.erl
+++ b/lib/wx/src/gen/wxStdDialogButtonSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,58 +42,65 @@
setItemMinSize/4,setMinSize/2,setMinSize/3,setSizeHints/2,setVirtualSizeHints/2,
show/2,show/3]).
+-export_type([wxStdDialogButtonSizer/0]).
%% @hidden
parent_class(wxBoxSizer) -> true;
parent_class(wxSizer) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStdDialogButtonSizer()
+-type wxStdDialogButtonSizer() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizerwxstddialogbuttonsizer">external documentation</a>.
+-spec new() -> wxStdDialogButtonSizer().
new() ->
wxe_util:construct(?wxStdDialogButtonSizer_new,
<<>>).
-%% @spec (This::wxStdDialogButtonSizer(), Button::wxButton:wxButton()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizeraddbutton">external documentation</a>.
+-spec addButton(This, Button) -> ok when
+ This::wxStdDialogButtonSizer(), Button::wxButton:wxButton().
addButton(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ButtonT,ref=ButtonRef}) ->
?CLASS(ThisT,wxStdDialogButtonSizer),
?CLASS(ButtonT,wxButton),
wxe_util:cast(?wxStdDialogButtonSizer_AddButton,
<<ThisRef:32/?UI,ButtonRef:32/?UI>>).
-%% @spec (This::wxStdDialogButtonSizer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizerrealize">external documentation</a>.
+-spec realize(This) -> ok when
+ This::wxStdDialogButtonSizer().
realize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStdDialogButtonSizer),
wxe_util:cast(?wxStdDialogButtonSizer_Realize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStdDialogButtonSizer(), Button::wxButton:wxButton()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizersetaffirmativebutton">external documentation</a>.
+-spec setAffirmativeButton(This, Button) -> ok when
+ This::wxStdDialogButtonSizer(), Button::wxButton:wxButton().
setAffirmativeButton(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ButtonT,ref=ButtonRef}) ->
?CLASS(ThisT,wxStdDialogButtonSizer),
?CLASS(ButtonT,wxButton),
wxe_util:cast(?wxStdDialogButtonSizer_SetAffirmativeButton,
<<ThisRef:32/?UI,ButtonRef:32/?UI>>).
-%% @spec (This::wxStdDialogButtonSizer(), Button::wxButton:wxButton()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizersetcancelbutton">external documentation</a>.
+-spec setCancelButton(This, Button) -> ok when
+ This::wxStdDialogButtonSizer(), Button::wxButton:wxButton().
setCancelButton(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ButtonT,ref=ButtonRef}) ->
?CLASS(ThisT,wxStdDialogButtonSizer),
?CLASS(ButtonT,wxButton),
wxe_util:cast(?wxStdDialogButtonSizer_SetCancelButton,
<<ThisRef:32/?UI,ButtonRef:32/?UI>>).
-%% @spec (This::wxStdDialogButtonSizer(), Button::wxButton:wxButton()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizersetnegativebutton">external documentation</a>.
+-spec setNegativeButton(This, Button) -> ok when
+ This::wxStdDialogButtonSizer(), Button::wxButton:wxButton().
setNegativeButton(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ButtonT,ref=ButtonRef}) ->
?CLASS(ThisT,wxStdDialogButtonSizer),
?CLASS(ButtonT,wxButton),
wxe_util:cast(?wxStdDialogButtonSizer_SetNegativeButton,
<<ThisRef:32/?UI,ButtonRef:32/?UI>>).
-%% @spec (This::wxStdDialogButtonSizer()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStdDialogButtonSizer()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStdDialogButtonSizer),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStyledTextCtrl.erl b/lib/wx/src/gen/wxStyledTextCtrl.erl
index 71d1bd0d53..f6dc2176b7 100644
--- a/lib/wx/src/gen/wxStyledTextCtrl.erl
+++ b/lib/wx/src/gen/wxStyledTextCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,14 +99,14 @@
setCaretForeground/2,setCaretLineBackAlpha/2,setCaretLineBackground/2,
setCaretLineVisible/2,setCaretPeriod/2,setCaretSticky/2,setCaretWidth/2,
setCharsDefault/1,setCodePage/2,setControlCharSymbol/2,setCurrentPos/2,
- setEOLMode/2,setEdgeColour/2,setEdgeColumn/2,setFoldExpanded/3,setFoldFlags/2,
- setFoldLevel/3,setFoldMarginColour/3,setFoldMarginHiColour/3,setHScrollBar/2,
- setHighlightGuide/2,setHotspotActiveBackground/3,setHotspotActiveForeground/3,
- setHotspotActiveUnderline/2,setHotspotSingleLine/2,setIndent/2,setIndentationGuides/2,
- setKeyWords/3,setLastKeydownProcessed/2,setLayoutCache/2,setLexer/2,
- setLexerLanguage/2,setLineIndentation/3,setLineState/3,setMarginLeft/2,
- setMarginMask/3,setMarginRight/2,setMarginSensitive/3,setMarginType/3,
- setMarginWidth/3,setMargins/3,setModEventMask/2,setMouseDownCaptures/2,
+ setEOLMode/2,setEdgeColour/2,setEdgeColumn/2,setEdgeMode/2,setFoldExpanded/3,
+ setFoldFlags/2,setFoldLevel/3,setFoldMarginColour/3,setFoldMarginHiColour/3,
+ setHScrollBar/2,setHighlightGuide/2,setHotspotActiveBackground/3,
+ setHotspotActiveForeground/3,setHotspotActiveUnderline/2,setHotspotSingleLine/2,
+ setIndent/2,setIndentationGuides/2,setKeyWords/3,setLastKeydownProcessed/2,
+ setLayoutCache/2,setLexer/2,setLexerLanguage/2,setLineIndentation/3,
+ setLineState/3,setMarginLeft/2,setMarginMask/3,setMarginRight/2,setMarginSensitive/3,
+ setMarginType/3,setMarginWidth/3,setMargins/3,setModEventMask/2,setMouseDownCaptures/2,
setMouseDwellTime/2,setPasteConvertEndings/2,setPrintColourMode/2,
setPrintMagnification/2,setProperty/3,setReadOnly/2,setSTCCursor/2,
setSTCFocus/2,setSavePoint/1,setScrollWidth/2,setSearchFlags/2,setSelAlpha/2,
@@ -171,27 +171,35 @@
transferDataToWindow/1,update/1,updateWindowUI/1,updateWindowUI/2,
validate/1,warpPointer/3]).
+-export_type([wxStyledTextCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxStyledTextCtrl()
+-type wxStyledTextCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwxstyledtextctrl">external documentation</a>.
+-spec new() -> wxStyledTextCtrl().
new() ->
wxe_util:construct(?wxStyledTextCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxStyledTextCtrl()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxStyledTextCtrl() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxStyledTextCtrl()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwxstyledtextctrl">external documentation</a>.
+-spec new(Parent, [Option]) -> wxStyledTextCtrl() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -204,15 +212,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxStyledTextCtrl_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxStyledTextCtrl(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxStyledTextCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxStyledTextCtrl(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -226,8 +240,9 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxStyledTextCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrladdtext">external documentation</a>.
+-spec addText(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
addText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -235,16 +250,18 @@ addText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_AddText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Data::wxMemoryBuffer:wxMemoryBuffer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrladdstyledtext">external documentation</a>.
+-spec addStyledText(This, Data) -> ok when
+ This::wxStyledTextCtrl(), Data::wx:wx_object().
addStyledText(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DataT,ref=DataRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
?CLASS(DataT,wxMemoryBuffer),
wxe_util:cast(?wxStyledTextCtrl_AddStyledText,
<<ThisRef:32/?UI,DataRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlinserttext">external documentation</a>.
+-spec insertText(This, Pos, Text) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer(), Text::unicode:chardata().
insertText(#wx_ref{type=ThisT,ref=ThisRef},Pos,Text)
when is_integer(Pos),is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -252,279 +269,319 @@ insertText(#wx_ref{type=ThisT,ref=ThisRef},Pos,Text)
wxe_util:cast(?wxStyledTextCtrl_InsertText,
<<ThisRef:32/?UI,Pos:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlclearall">external documentation</a>.
+-spec clearAll(This) -> ok when
+ This::wxStyledTextCtrl().
clearAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ClearAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcleardocumentstyle">external documentation</a>.
+-spec clearDocumentStyle(This) -> ok when
+ This::wxStyledTextCtrl().
clearDocumentStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ClearDocumentStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlength">external documentation</a>.
+-spec getLength(This) -> integer() when
+ This::wxStyledTextCtrl().
getLength(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLength,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcharat">external documentation</a>.
+-spec getCharAt(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
getCharAt(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCharAt,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcurrentpos">external documentation</a>.
+-spec getCurrentPos(This) -> integer() when
+ This::wxStyledTextCtrl().
getCurrentPos(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCurrentPos,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetanchor">external documentation</a>.
+-spec getAnchor(This) -> integer() when
+ This::wxStyledTextCtrl().
getAnchor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetAnchor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstyleat">external documentation</a>.
+-spec getStyleAt(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
getStyleAt(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetStyleAt,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlredo">external documentation</a>.
+-spec redo(This) -> ok when
+ This::wxStyledTextCtrl().
redo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Redo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CollectUndo::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetundocollection">external documentation</a>.
+-spec setUndoCollection(This, CollectUndo) -> ok when
+ This::wxStyledTextCtrl(), CollectUndo::boolean().
setUndoCollection(#wx_ref{type=ThisT,ref=ThisRef},CollectUndo)
when is_boolean(CollectUndo) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetUndoCollection,
<<ThisRef:32/?UI,(wxe_util:from_bool(CollectUndo)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlselectall">external documentation</a>.
+-spec selectAll(This) -> ok when
+ This::wxStyledTextCtrl().
selectAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SelectAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetsavepoint">external documentation</a>.
+-spec setSavePoint(This) -> ok when
+ This::wxStyledTextCtrl().
setSavePoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSavePoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), StartPos::integer(), EndPos::integer()) -> wxMemoryBuffer:wxMemoryBuffer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstyledtext">external documentation</a>.
+-spec getStyledText(This, StartPos, EndPos) -> wx:wx_object() when
+ This::wxStyledTextCtrl(), StartPos::integer(), EndPos::integer().
getStyledText(#wx_ref{type=ThisT,ref=ThisRef},StartPos,EndPos)
when is_integer(StartPos),is_integer(EndPos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetStyledText,
<<ThisRef:32/?UI,StartPos:32/?UI,EndPos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcanredo">external documentation</a>.
+-spec canRedo(This) -> boolean() when
+ This::wxStyledTextCtrl().
canRedo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_CanRedo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Handle::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerlinefromhandle">external documentation</a>.
+-spec markerLineFromHandle(This, Handle) -> integer() when
+ This::wxStyledTextCtrl(), Handle::integer().
markerLineFromHandle(#wx_ref{type=ThisT,ref=ThisRef},Handle)
when is_integer(Handle) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_MarkerLineFromHandle,
<<ThisRef:32/?UI,Handle:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Handle::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerdeletehandle">external documentation</a>.
+-spec markerDeleteHandle(This, Handle) -> ok when
+ This::wxStyledTextCtrl(), Handle::integer().
markerDeleteHandle(#wx_ref{type=ThisT,ref=ThisRef},Handle)
when is_integer(Handle) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerDeleteHandle,
<<ThisRef:32/?UI,Handle:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetundocollection">external documentation</a>.
+-spec getUndoCollection(This) -> boolean() when
+ This::wxStyledTextCtrl().
getUndoCollection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetUndoCollection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetviewwhitespace">external documentation</a>.
+-spec getViewWhiteSpace(This) -> integer() when
+ This::wxStyledTextCtrl().
getViewWhiteSpace(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetViewWhiteSpace,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), ViewWS::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetviewwhitespace">external documentation</a>.
+-spec setViewWhiteSpace(This, ViewWS) -> ok when
+ This::wxStyledTextCtrl(), ViewWS::integer().
setViewWhiteSpace(#wx_ref{type=ThisT,ref=ThisRef},ViewWS)
when is_integer(ViewWS) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetViewWhiteSpace,
<<ThisRef:32/?UI,ViewWS:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pt::{X::integer(),Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpositionfrompoint">external documentation</a>.
+-spec positionFromPoint(This, Pt) -> integer() when
+ This::wxStyledTextCtrl(), Pt::{X::integer(), Y::integer()}.
positionFromPoint(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_PositionFromPoint,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), X::integer(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpositionfrompointclose">external documentation</a>.
+-spec positionFromPointClose(This, X, Y) -> integer() when
+ This::wxStyledTextCtrl(), X::integer(), Y::integer().
positionFromPointClose(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_PositionFromPointClose,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgotoline">external documentation</a>.
+-spec gotoLine(This, Line) -> ok when
+ This::wxStyledTextCtrl(), Line::integer().
gotoLine(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_GotoLine,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgotopos">external documentation</a>.
+-spec gotoPos(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
gotoPos(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_GotoPos,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PosAnchor::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetanchor">external documentation</a>.
+-spec setAnchor(This, PosAnchor) -> ok when
+ This::wxStyledTextCtrl(), PosAnchor::integer().
setAnchor(#wx_ref{type=ThisT,ref=ThisRef},PosAnchor)
when is_integer(PosAnchor) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetAnchor,
<<ThisRef:32/?UI,PosAnchor:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> {string(),LinePos::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcurline">external documentation</a>.
+-spec getCurLine(This) -> Result when
+ Result ::{Res ::unicode:charlist(), LinePos::integer()},
+ This::wxStyledTextCtrl().
getCurLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCurLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetendstyled">external documentation</a>.
+-spec getEndStyled(This) -> integer() when
+ This::wxStyledTextCtrl().
getEndStyled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetEndStyled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), EolMode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlconverteols">external documentation</a>.
+-spec convertEOLs(This, EolMode) -> ok when
+ This::wxStyledTextCtrl(), EolMode::integer().
convertEOLs(#wx_ref{type=ThisT,ref=ThisRef},EolMode)
when is_integer(EolMode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ConvertEOLs,
<<ThisRef:32/?UI,EolMode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgeteolmode">external documentation</a>.
+-spec getEOLMode(This) -> integer() when
+ This::wxStyledTextCtrl().
getEOLMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetEOLMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), EolMode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlseteolmode">external documentation</a>.
+-spec setEOLMode(This, EolMode) -> ok when
+ This::wxStyledTextCtrl(), EolMode::integer().
setEOLMode(#wx_ref{type=ThisT,ref=ThisRef},EolMode)
when is_integer(EolMode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetEOLMode,
<<ThisRef:32/?UI,EolMode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer(), Mask::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstartstyling">external documentation</a>.
+-spec startStyling(This, Pos, Mask) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer(), Mask::integer().
startStyling(#wx_ref{type=ThisT,ref=ThisRef},Pos,Mask)
when is_integer(Pos),is_integer(Mask) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StartStyling,
<<ThisRef:32/?UI,Pos:32/?UI,Mask:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Length::integer(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetstyling">external documentation</a>.
+-spec setStyling(This, Length, Style) -> ok when
+ This::wxStyledTextCtrl(), Length::integer(), Style::integer().
setStyling(#wx_ref{type=ThisT,ref=ThisRef},Length,Style)
when is_integer(Length),is_integer(Style) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetStyling,
<<ThisRef:32/?UI,Length:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetbuffereddraw">external documentation</a>.
+-spec getBufferedDraw(This) -> boolean() when
+ This::wxStyledTextCtrl().
getBufferedDraw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetBufferedDraw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Buffered::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetbuffereddraw">external documentation</a>.
+-spec setBufferedDraw(This, Buffered) -> ok when
+ This::wxStyledTextCtrl(), Buffered::boolean().
setBufferedDraw(#wx_ref{type=ThisT,ref=ThisRef},Buffered)
when is_boolean(Buffered) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetBufferedDraw,
<<ThisRef:32/?UI,(wxe_util:from_bool(Buffered)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), TabWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettabwidth">external documentation</a>.
+-spec setTabWidth(This, TabWidth) -> ok when
+ This::wxStyledTextCtrl(), TabWidth::integer().
setTabWidth(#wx_ref{type=ThisT,ref=ThisRef},TabWidth)
when is_integer(TabWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetTabWidth,
<<ThisRef:32/?UI,TabWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettabwidth">external documentation</a>.
+-spec getTabWidth(This) -> integer() when
+ This::wxStyledTextCtrl().
getTabWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTabWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CodePage::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcodepage">external documentation</a>.
+-spec setCodePage(This, CodePage) -> ok when
+ This::wxStyledTextCtrl(), CodePage::integer().
setCodePage(#wx_ref{type=ThisT,ref=ThisRef},CodePage)
when is_integer(CodePage) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCodePage,
<<ThisRef:32/?UI,CodePage:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer(), MarkerSymbol::integer()) -> ok
%% @equiv markerDefine(This,MarkerNumber,MarkerSymbol, [])
+-spec markerDefine(This, MarkerNumber, MarkerSymbol) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer(), MarkerSymbol::integer().
+
markerDefine(This,MarkerNumber,MarkerSymbol)
when is_record(This, wx_ref),is_integer(MarkerNumber),is_integer(MarkerSymbol) ->
markerDefine(This,MarkerNumber,MarkerSymbol, []).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer(), MarkerSymbol::integer(), [Option]) -> ok
-%% Option = {foreground, wx:colour()} | {background, wx:colour()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerdefine">external documentation</a>.
+-spec markerDefine(This, MarkerNumber, MarkerSymbol, [Option]) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer(), MarkerSymbol::integer(),
+ Option :: {foreground, wx:wx_colour()}
+ | {background, wx:wx_colour()}.
markerDefine(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,MarkerSymbol, Options)
when is_integer(MarkerNumber),is_integer(MarkerSymbol),is_list(Options) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -535,72 +592,81 @@ markerDefine(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,MarkerSymbol, Options)
wxe_util:cast(?wxStyledTextCtrl_MarkerDefine,
<<ThisRef:32/?UI,MarkerNumber:32/?UI,MarkerSymbol:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkersetforeground">external documentation</a>.
+-spec markerSetForeground(This, MarkerNumber, Fore) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer(), Fore::wx:wx_colour().
markerSetForeground(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,Fore)
when is_integer(MarkerNumber),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerSetForeground,
<<ThisRef:32/?UI,MarkerNumber:32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkersetbackground">external documentation</a>.
+-spec markerSetBackground(This, MarkerNumber, Back) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer(), Back::wx:wx_colour().
markerSetBackground(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,Back)
when is_integer(MarkerNumber),tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerSetBackground,
<<ThisRef:32/?UI,MarkerNumber:32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), MarkerNumber::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkeradd">external documentation</a>.
+-spec markerAdd(This, Line, MarkerNumber) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer(), MarkerNumber::integer().
markerAdd(#wx_ref{type=ThisT,ref=ThisRef},Line,MarkerNumber)
when is_integer(Line),is_integer(MarkerNumber) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_MarkerAdd,
<<ThisRef:32/?UI,Line:32/?UI,MarkerNumber:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), MarkerNumber::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerdelete">external documentation</a>.
+-spec markerDelete(This, Line, MarkerNumber) -> ok when
+ This::wxStyledTextCtrl(), Line::integer(), MarkerNumber::integer().
markerDelete(#wx_ref{type=ThisT,ref=ThisRef},Line,MarkerNumber)
when is_integer(Line),is_integer(MarkerNumber) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerDelete,
<<ThisRef:32/?UI,Line:32/?UI,MarkerNumber:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerdeleteall">external documentation</a>.
+-spec markerDeleteAll(This, MarkerNumber) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer().
markerDeleteAll(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber)
when is_integer(MarkerNumber) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerDeleteAll,
<<ThisRef:32/?UI,MarkerNumber:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerget">external documentation</a>.
+-spec markerGet(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
markerGet(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_MarkerGet,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), LineStart::integer(), MarkerMask::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkernext">external documentation</a>.
+-spec markerNext(This, LineStart, MarkerMask) -> integer() when
+ This::wxStyledTextCtrl(), LineStart::integer(), MarkerMask::integer().
markerNext(#wx_ref{type=ThisT,ref=ThisRef},LineStart,MarkerMask)
when is_integer(LineStart),is_integer(MarkerMask) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_MarkerNext,
<<ThisRef:32/?UI,LineStart:32/?UI,MarkerMask:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), LineStart::integer(), MarkerMask::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerprevious">external documentation</a>.
+-spec markerPrevious(This, LineStart, MarkerMask) -> integer() when
+ This::wxStyledTextCtrl(), LineStart::integer(), MarkerMask::integer().
markerPrevious(#wx_ref{type=ThisT,ref=ThisRef},LineStart,MarkerMask)
when is_integer(LineStart),is_integer(MarkerMask) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_MarkerPrevious,
<<ThisRef:32/?UI,LineStart:32/?UI,MarkerMask:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer(), Bmp::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkerdefinebitmap">external documentation</a>.
+-spec markerDefineBitmap(This, MarkerNumber, Bmp) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer(), Bmp::wxBitmap:wxBitmap().
markerDefineBitmap(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,#wx_ref{type=BmpT,ref=BmpRef})
when is_integer(MarkerNumber) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -608,135 +674,152 @@ markerDefineBitmap(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,#wx_ref{type=Bmp
wxe_util:cast(?wxStyledTextCtrl_MarkerDefineBitmap,
<<ThisRef:32/?UI,MarkerNumber:32/?UI,BmpRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), Set::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkeraddset">external documentation</a>.
+-spec markerAddSet(This, Line, Set) -> ok when
+ This::wxStyledTextCtrl(), Line::integer(), Set::integer().
markerAddSet(#wx_ref{type=ThisT,ref=ThisRef},Line,Set)
when is_integer(Line),is_integer(Set) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerAddSet,
<<ThisRef:32/?UI,Line:32/?UI,Set:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), MarkerNumber::integer(), Alpha::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmarkersetalpha">external documentation</a>.
+-spec markerSetAlpha(This, MarkerNumber, Alpha) -> ok when
+ This::wxStyledTextCtrl(), MarkerNumber::integer(), Alpha::integer().
markerSetAlpha(#wx_ref{type=ThisT,ref=ThisRef},MarkerNumber,Alpha)
when is_integer(MarkerNumber),is_integer(Alpha) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MarkerSetAlpha,
<<ThisRef:32/?UI,MarkerNumber:32/?UI,Alpha:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer(), MarginType::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmargintype">external documentation</a>.
+-spec setMarginType(This, Margin, MarginType) -> ok when
+ This::wxStyledTextCtrl(), Margin::integer(), MarginType::integer().
setMarginType(#wx_ref{type=ThisT,ref=ThisRef},Margin,MarginType)
when is_integer(Margin),is_integer(MarginType) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMarginType,
<<ThisRef:32/?UI,Margin:32/?UI,MarginType:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmargintype">external documentation</a>.
+-spec getMarginType(This, Margin) -> integer() when
+ This::wxStyledTextCtrl(), Margin::integer().
getMarginType(#wx_ref{type=ThisT,ref=ThisRef},Margin)
when is_integer(Margin) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMarginType,
<<ThisRef:32/?UI,Margin:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer(), PixelWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmarginwidth">external documentation</a>.
+-spec setMarginWidth(This, Margin, PixelWidth) -> ok when
+ This::wxStyledTextCtrl(), Margin::integer(), PixelWidth::integer().
setMarginWidth(#wx_ref{type=ThisT,ref=ThisRef},Margin,PixelWidth)
when is_integer(Margin),is_integer(PixelWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMarginWidth,
<<ThisRef:32/?UI,Margin:32/?UI,PixelWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmarginwidth">external documentation</a>.
+-spec getMarginWidth(This, Margin) -> integer() when
+ This::wxStyledTextCtrl(), Margin::integer().
getMarginWidth(#wx_ref{type=ThisT,ref=ThisRef},Margin)
when is_integer(Margin) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMarginWidth,
<<ThisRef:32/?UI,Margin:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer(), Mask::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmarginmask">external documentation</a>.
+-spec setMarginMask(This, Margin, Mask) -> ok when
+ This::wxStyledTextCtrl(), Margin::integer(), Mask::integer().
setMarginMask(#wx_ref{type=ThisT,ref=ThisRef},Margin,Mask)
when is_integer(Margin),is_integer(Mask) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMarginMask,
<<ThisRef:32/?UI,Margin:32/?UI,Mask:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmarginmask">external documentation</a>.
+-spec getMarginMask(This, Margin) -> integer() when
+ This::wxStyledTextCtrl(), Margin::integer().
getMarginMask(#wx_ref{type=ThisT,ref=ThisRef},Margin)
when is_integer(Margin) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMarginMask,
<<ThisRef:32/?UI,Margin:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer(), Sensitive::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmarginsensitive">external documentation</a>.
+-spec setMarginSensitive(This, Margin, Sensitive) -> ok when
+ This::wxStyledTextCtrl(), Margin::integer(), Sensitive::boolean().
setMarginSensitive(#wx_ref{type=ThisT,ref=ThisRef},Margin,Sensitive)
when is_integer(Margin),is_boolean(Sensitive) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMarginSensitive,
<<ThisRef:32/?UI,Margin:32/?UI,(wxe_util:from_bool(Sensitive)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Margin::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmarginsensitive">external documentation</a>.
+-spec getMarginSensitive(This, Margin) -> boolean() when
+ This::wxStyledTextCtrl(), Margin::integer().
getMarginSensitive(#wx_ref{type=ThisT,ref=ThisRef},Margin)
when is_integer(Margin) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMarginSensitive,
<<ThisRef:32/?UI,Margin:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstyleclearall">external documentation</a>.
+-spec styleClearAll(This) -> ok when
+ This::wxStyledTextCtrl().
styleClearAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleClearAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetforeground">external documentation</a>.
+-spec styleSetForeground(This, Style, Fore) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Fore::wx:wx_colour().
styleSetForeground(#wx_ref{type=ThisT,ref=ThisRef},Style,Fore)
when is_integer(Style),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetForeground,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetbackground">external documentation</a>.
+-spec styleSetBackground(This, Style, Back) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Back::wx:wx_colour().
styleSetBackground(#wx_ref{type=ThisT,ref=ThisRef},Style,Back)
when is_integer(Style),tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetBackground,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Bold::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetbold">external documentation</a>.
+-spec styleSetBold(This, Style, Bold) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Bold::boolean().
styleSetBold(#wx_ref{type=ThisT,ref=ThisRef},Style,Bold)
when is_integer(Style),is_boolean(Bold) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetBold,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:from_bool(Bold)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Italic::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetitalic">external documentation</a>.
+-spec styleSetItalic(This, Style, Italic) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Italic::boolean().
styleSetItalic(#wx_ref{type=ThisT,ref=ThisRef},Style,Italic)
when is_integer(Style),is_boolean(Italic) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetItalic,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:from_bool(Italic)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), SizePoints::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetsize">external documentation</a>.
+-spec styleSetSize(This, Style, SizePoints) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), SizePoints::integer().
styleSetSize(#wx_ref{type=ThisT,ref=ThisRef},Style,SizePoints)
when is_integer(Style),is_integer(SizePoints) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetSize,
<<ThisRef:32/?UI,Style:32/?UI,SizePoints:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), FontName::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetfacename">external documentation</a>.
+-spec styleSetFaceName(This, Style, FontName) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), FontName::unicode:chardata().
styleSetFaceName(#wx_ref{type=ThisT,ref=ThisRef},Style,FontName)
when is_integer(Style),is_list(FontName) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -744,140 +827,158 @@ styleSetFaceName(#wx_ref{type=ThisT,ref=ThisRef},Style,FontName)
wxe_util:cast(?wxStyledTextCtrl_StyleSetFaceName,
<<ThisRef:32/?UI,Style:32/?UI,(byte_size(FontName_UC)):32/?UI,(FontName_UC)/binary, 0:(((8- ((4+byte_size(FontName_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Filled::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstyleseteolfilled">external documentation</a>.
+-spec styleSetEOLFilled(This, Style, Filled) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Filled::boolean().
styleSetEOLFilled(#wx_ref{type=ThisT,ref=ThisRef},Style,Filled)
when is_integer(Style),is_boolean(Filled) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetEOLFilled,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:from_bool(Filled)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstyleresetdefault">external documentation</a>.
+-spec styleResetDefault(This) -> ok when
+ This::wxStyledTextCtrl().
styleResetDefault(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleResetDefault,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Underline::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetunderline">external documentation</a>.
+-spec styleSetUnderline(This, Style, Underline) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Underline::boolean().
styleSetUnderline(#wx_ref{type=ThisT,ref=ThisRef},Style,Underline)
when is_integer(Style),is_boolean(Underline) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetUnderline,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:from_bool(Underline)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), CaseForce::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetcase">external documentation</a>.
+-spec styleSetCase(This, Style, CaseForce) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), CaseForce::integer().
styleSetCase(#wx_ref{type=ThisT,ref=ThisRef},Style,CaseForce)
when is_integer(Style),is_integer(CaseForce) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetCase,
<<ThisRef:32/?UI,Style:32/?UI,CaseForce:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Hotspot::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesethotspot">external documentation</a>.
+-spec styleSetHotSpot(This, Style, Hotspot) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Hotspot::boolean().
styleSetHotSpot(#wx_ref{type=ThisT,ref=ThisRef},Style,Hotspot)
when is_integer(Style),is_boolean(Hotspot) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetHotSpot,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:from_bool(Hotspot)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselforeground">external documentation</a>.
+-spec setSelForeground(This, UseSetting, Fore) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Fore::wx:wx_colour().
setSelForeground(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Fore)
when is_boolean(UseSetting),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelForeground,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselbackground">external documentation</a>.
+-spec setSelBackground(This, UseSetting, Back) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Back::wx:wx_colour().
setSelBackground(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Back)
when is_boolean(UseSetting),tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelBackground,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselalpha">external documentation</a>.
+-spec getSelAlpha(This) -> integer() when
+ This::wxStyledTextCtrl().
getSelAlpha(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelAlpha,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Alpha::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselalpha">external documentation</a>.
+-spec setSelAlpha(This, Alpha) -> ok when
+ This::wxStyledTextCtrl(), Alpha::integer().
setSelAlpha(#wx_ref{type=ThisT,ref=ThisRef},Alpha)
when is_integer(Alpha) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelAlpha,
<<ThisRef:32/?UI,Alpha:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretforeground">external documentation</a>.
+-spec setCaretForeground(This, Fore) -> ok when
+ This::wxStyledTextCtrl(), Fore::wx:wx_colour().
setCaretForeground(#wx_ref{type=ThisT,ref=ThisRef},Fore)
when tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretForeground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Key::integer(), Modifiers::integer(), Cmd::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcmdkeyassign">external documentation</a>.
+-spec cmdKeyAssign(This, Key, Modifiers, Cmd) -> ok when
+ This::wxStyledTextCtrl(), Key::integer(), Modifiers::integer(), Cmd::integer().
cmdKeyAssign(#wx_ref{type=ThisT,ref=ThisRef},Key,Modifiers,Cmd)
when is_integer(Key),is_integer(Modifiers),is_integer(Cmd) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CmdKeyAssign,
<<ThisRef:32/?UI,Key:32/?UI,Modifiers:32/?UI,Cmd:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Key::integer(), Modifiers::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcmdkeyclear">external documentation</a>.
+-spec cmdKeyClear(This, Key, Modifiers) -> ok when
+ This::wxStyledTextCtrl(), Key::integer(), Modifiers::integer().
cmdKeyClear(#wx_ref{type=ThisT,ref=ThisRef},Key,Modifiers)
when is_integer(Key),is_integer(Modifiers) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CmdKeyClear,
<<ThisRef:32/?UI,Key:32/?UI,Modifiers:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcmdkeyclearall">external documentation</a>.
+-spec cmdKeyClearAll(This) -> ok when
+ This::wxStyledTextCtrl().
cmdKeyClearAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CmdKeyClearAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Length::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetstylebytes">external documentation</a>.
+-spec setStyleBytes(This, Length) -> integer() when
+ This::wxStyledTextCtrl(), Length::integer().
setStyleBytes(#wx_ref{type=ThisT,ref=ThisRef},Length)
when is_integer(Length) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_SetStyleBytes,
<<ThisRef:32/?UI,Length:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Visible::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetvisible">external documentation</a>.
+-spec styleSetVisible(This, Style, Visible) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Visible::boolean().
styleSetVisible(#wx_ref{type=ThisT,ref=ThisRef},Style,Visible)
when is_integer(Style),is_boolean(Visible) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetVisible,
<<ThisRef:32/?UI,Style:32/?UI,(wxe_util:from_bool(Visible)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretperiod">external documentation</a>.
+-spec getCaretPeriod(This) -> integer() when
+ This::wxStyledTextCtrl().
getCaretPeriod(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretPeriod,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PeriodMilliseconds::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretperiod">external documentation</a>.
+-spec setCaretPeriod(This, PeriodMilliseconds) -> ok when
+ This::wxStyledTextCtrl(), PeriodMilliseconds::integer().
setCaretPeriod(#wx_ref{type=ThisT,ref=ThisRef},PeriodMilliseconds)
when is_integer(PeriodMilliseconds) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretPeriod,
<<ThisRef:32/?UI,PeriodMilliseconds:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Characters::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwordchars">external documentation</a>.
+-spec setWordChars(This, Characters) -> ok when
+ This::wxStyledTextCtrl(), Characters::unicode:chardata().
setWordChars(#wx_ref{type=ThisT,ref=ThisRef},Characters)
when is_list(Characters) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -885,130 +986,147 @@ setWordChars(#wx_ref{type=ThisT,ref=ThisRef},Characters)
wxe_util:cast(?wxStyledTextCtrl_SetWordChars,
<<ThisRef:32/?UI,(byte_size(Characters_UC)):32/?UI,(Characters_UC)/binary, 0:(((8- ((0+byte_size(Characters_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlbeginundoaction">external documentation</a>.
+-spec beginUndoAction(This) -> ok when
+ This::wxStyledTextCtrl().
beginUndoAction(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_BeginUndoAction,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlendundoaction">external documentation</a>.
+-spec endUndoAction(This) -> ok when
+ This::wxStyledTextCtrl().
endUndoAction(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_EndUndoAction,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Indic::integer(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlindicatorsetstyle">external documentation</a>.
+-spec indicatorSetStyle(This, Indic, Style) -> ok when
+ This::wxStyledTextCtrl(), Indic::integer(), Style::integer().
indicatorSetStyle(#wx_ref{type=ThisT,ref=ThisRef},Indic,Style)
when is_integer(Indic),is_integer(Style) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_IndicatorSetStyle,
<<ThisRef:32/?UI,Indic:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Indic::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlindicatorgetstyle">external documentation</a>.
+-spec indicatorGetStyle(This, Indic) -> integer() when
+ This::wxStyledTextCtrl(), Indic::integer().
indicatorGetStyle(#wx_ref{type=ThisT,ref=ThisRef},Indic)
when is_integer(Indic) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_IndicatorGetStyle,
<<ThisRef:32/?UI,Indic:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Indic::integer(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlindicatorsetforeground">external documentation</a>.
+-spec indicatorSetForeground(This, Indic, Fore) -> ok when
+ This::wxStyledTextCtrl(), Indic::integer(), Fore::wx:wx_colour().
indicatorSetForeground(#wx_ref{type=ThisT,ref=ThisRef},Indic,Fore)
when is_integer(Indic),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_IndicatorSetForeground,
<<ThisRef:32/?UI,Indic:32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Indic::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlindicatorgetforeground">external documentation</a>.
+-spec indicatorGetForeground(This, Indic) -> wx:wx_colour4() when
+ This::wxStyledTextCtrl(), Indic::integer().
indicatorGetForeground(#wx_ref{type=ThisT,ref=ThisRef},Indic)
when is_integer(Indic) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_IndicatorGetForeground,
<<ThisRef:32/?UI,Indic:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwhitespaceforeground">external documentation</a>.
+-spec setWhitespaceForeground(This, UseSetting, Fore) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Fore::wx:wx_colour().
setWhitespaceForeground(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Fore)
when is_boolean(UseSetting),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetWhitespaceForeground,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwhitespacebackground">external documentation</a>.
+-spec setWhitespaceBackground(This, UseSetting, Back) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Back::wx:wx_colour().
setWhitespaceBackground(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Back)
when is_boolean(UseSetting),tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetWhitespaceBackground,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstylebits">external documentation</a>.
+-spec getStyleBits(This) -> integer() when
+ This::wxStyledTextCtrl().
getStyleBits(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetStyleBits,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), State::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetlinestate">external documentation</a>.
+-spec setLineState(This, Line, State) -> ok when
+ This::wxStyledTextCtrl(), Line::integer(), State::integer().
setLineState(#wx_ref{type=ThisT,ref=ThisRef},Line,State)
when is_integer(Line),is_integer(State) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetLineState,
<<ThisRef:32/?UI,Line:32/?UI,State:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlinestate">external documentation</a>.
+-spec getLineState(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
getLineState(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineState,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmaxlinestate">external documentation</a>.
+-spec getMaxLineState(This) -> integer() when
+ This::wxStyledTextCtrl().
getMaxLineState(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMaxLineState,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretlinevisible">external documentation</a>.
+-spec getCaretLineVisible(This) -> boolean() when
+ This::wxStyledTextCtrl().
getCaretLineVisible(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretLineVisible,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Show::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretlinevisible">external documentation</a>.
+-spec setCaretLineVisible(This, Show) -> ok when
+ This::wxStyledTextCtrl(), Show::boolean().
setCaretLineVisible(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretLineVisible,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretlinebackground">external documentation</a>.
+-spec getCaretLineBackground(This) -> wx:wx_colour4() when
+ This::wxStyledTextCtrl().
getCaretLineBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretLineBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretlinebackground">external documentation</a>.
+-spec setCaretLineBackground(This, Back) -> ok when
+ This::wxStyledTextCtrl(), Back::wx:wx_colour().
setCaretLineBackground(#wx_ref{type=ThisT,ref=ThisRef},Back)
when tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretLineBackground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), LenEntered::integer(), ItemList::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompshow">external documentation</a>.
+-spec autoCompShow(This, LenEntered, ItemList) -> ok when
+ This::wxStyledTextCtrl(), LenEntered::integer(), ItemList::unicode:chardata().
autoCompShow(#wx_ref{type=ThisT,ref=ThisRef},LenEntered,ItemList)
when is_integer(LenEntered),is_list(ItemList) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1016,36 +1134,41 @@ autoCompShow(#wx_ref{type=ThisT,ref=ThisRef},LenEntered,ItemList)
wxe_util:cast(?wxStyledTextCtrl_AutoCompShow,
<<ThisRef:32/?UI,LenEntered:32/?UI,(byte_size(ItemList_UC)):32/?UI,(ItemList_UC)/binary, 0:(((8- ((4+byte_size(ItemList_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompcancel">external documentation</a>.
+-spec autoCompCancel(This) -> ok when
+ This::wxStyledTextCtrl().
autoCompCancel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompCancel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompactive">external documentation</a>.
+-spec autoCompActive(This) -> boolean() when
+ This::wxStyledTextCtrl().
autoCompActive(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompActive,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompposstart">external documentation</a>.
+-spec autoCompPosStart(This) -> integer() when
+ This::wxStyledTextCtrl().
autoCompPosStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompPosStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompcomplete">external documentation</a>.
+-spec autoCompComplete(This) -> ok when
+ This::wxStyledTextCtrl().
autoCompComplete(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompComplete,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CharacterSet::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompstops">external documentation</a>.
+-spec autoCompStops(This, CharacterSet) -> ok when
+ This::wxStyledTextCtrl(), CharacterSet::unicode:chardata().
autoCompStops(#wx_ref{type=ThisT,ref=ThisRef},CharacterSet)
when is_list(CharacterSet) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1053,23 +1176,26 @@ autoCompStops(#wx_ref{type=ThisT,ref=ThisRef},CharacterSet)
wxe_util:cast(?wxStyledTextCtrl_AutoCompStops,
<<ThisRef:32/?UI,(byte_size(CharacterSet_UC)):32/?UI,(CharacterSet_UC)/binary, 0:(((8- ((0+byte_size(CharacterSet_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), SeparatorCharacter::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetseparator">external documentation</a>.
+-spec autoCompSetSeparator(This, SeparatorCharacter) -> ok when
+ This::wxStyledTextCtrl(), SeparatorCharacter::integer().
autoCompSetSeparator(#wx_ref{type=ThisT,ref=ThisRef},SeparatorCharacter)
when is_integer(SeparatorCharacter) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetSeparator,
<<ThisRef:32/?UI,SeparatorCharacter:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetseparator">external documentation</a>.
+-spec autoCompGetSeparator(This) -> integer() when
+ This::wxStyledTextCtrl().
autoCompGetSeparator(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetSeparator,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompselect">external documentation</a>.
+-spec autoCompSelect(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
autoCompSelect(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1077,23 +1203,26 @@ autoCompSelect(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_AutoCompSelect,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Cancel::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetcancelatstart">external documentation</a>.
+-spec autoCompSetCancelAtStart(This, Cancel) -> ok when
+ This::wxStyledTextCtrl(), Cancel::boolean().
autoCompSetCancelAtStart(#wx_ref{type=ThisT,ref=ThisRef},Cancel)
when is_boolean(Cancel) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetCancelAtStart,
<<ThisRef:32/?UI,(wxe_util:from_bool(Cancel)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetcancelatstart">external documentation</a>.
+-spec autoCompGetCancelAtStart(This) -> boolean() when
+ This::wxStyledTextCtrl().
autoCompGetCancelAtStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetCancelAtStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CharacterSet::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetfillups">external documentation</a>.
+-spec autoCompSetFillUps(This, CharacterSet) -> ok when
+ This::wxStyledTextCtrl(), CharacterSet::unicode:chardata().
autoCompSetFillUps(#wx_ref{type=ThisT,ref=ThisRef},CharacterSet)
when is_list(CharacterSet) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1101,38 +1230,43 @@ autoCompSetFillUps(#wx_ref{type=ThisT,ref=ThisRef},CharacterSet)
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetFillUps,
<<ThisRef:32/?UI,(byte_size(CharacterSet_UC)):32/?UI,(CharacterSet_UC)/binary, 0:(((8- ((0+byte_size(CharacterSet_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), ChooseSingle::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetchoosesingle">external documentation</a>.
+-spec autoCompSetChooseSingle(This, ChooseSingle) -> ok when
+ This::wxStyledTextCtrl(), ChooseSingle::boolean().
autoCompSetChooseSingle(#wx_ref{type=ThisT,ref=ThisRef},ChooseSingle)
when is_boolean(ChooseSingle) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetChooseSingle,
<<ThisRef:32/?UI,(wxe_util:from_bool(ChooseSingle)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetchoosesingle">external documentation</a>.
+-spec autoCompGetChooseSingle(This) -> boolean() when
+ This::wxStyledTextCtrl().
autoCompGetChooseSingle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetChooseSingle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), IgnoreCase::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetignorecase">external documentation</a>.
+-spec autoCompSetIgnoreCase(This, IgnoreCase) -> ok when
+ This::wxStyledTextCtrl(), IgnoreCase::boolean().
autoCompSetIgnoreCase(#wx_ref{type=ThisT,ref=ThisRef},IgnoreCase)
when is_boolean(IgnoreCase) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetIgnoreCase,
<<ThisRef:32/?UI,(wxe_util:from_bool(IgnoreCase)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetignorecase">external documentation</a>.
+-spec autoCompGetIgnoreCase(This) -> boolean() when
+ This::wxStyledTextCtrl().
autoCompGetIgnoreCase(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetIgnoreCase,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), ListType::integer(), ItemList::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrluserlistshow">external documentation</a>.
+-spec userListShow(This, ListType, ItemList) -> ok when
+ This::wxStyledTextCtrl(), ListType::integer(), ItemList::unicode:chardata().
userListShow(#wx_ref{type=ThisT,ref=ThisRef},ListType,ItemList)
when is_integer(ListType),is_list(ItemList) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1140,38 +1274,43 @@ userListShow(#wx_ref{type=ThisT,ref=ThisRef},ListType,ItemList)
wxe_util:cast(?wxStyledTextCtrl_UserListShow,
<<ThisRef:32/?UI,ListType:32/?UI,(byte_size(ItemList_UC)):32/?UI,(ItemList_UC)/binary, 0:(((8- ((4+byte_size(ItemList_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), AutoHide::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetautohide">external documentation</a>.
+-spec autoCompSetAutoHide(This, AutoHide) -> ok when
+ This::wxStyledTextCtrl(), AutoHide::boolean().
autoCompSetAutoHide(#wx_ref{type=ThisT,ref=ThisRef},AutoHide)
when is_boolean(AutoHide) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetAutoHide,
<<ThisRef:32/?UI,(wxe_util:from_bool(AutoHide)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetautohide">external documentation</a>.
+-spec autoCompGetAutoHide(This) -> boolean() when
+ This::wxStyledTextCtrl().
autoCompGetAutoHide(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetAutoHide,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), DropRestOfWord::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetdroprestofword">external documentation</a>.
+-spec autoCompSetDropRestOfWord(This, DropRestOfWord) -> ok when
+ This::wxStyledTextCtrl(), DropRestOfWord::boolean().
autoCompSetDropRestOfWord(#wx_ref{type=ThisT,ref=ThisRef},DropRestOfWord)
when is_boolean(DropRestOfWord) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetDropRestOfWord,
<<ThisRef:32/?UI,(wxe_util:from_bool(DropRestOfWord)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetdroprestofword">external documentation</a>.
+-spec autoCompGetDropRestOfWord(This) -> boolean() when
+ This::wxStyledTextCtrl().
autoCompGetDropRestOfWord(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetDropRestOfWord,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Type::integer(), Bmp::wxBitmap:wxBitmap()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlregisterimage">external documentation</a>.
+-spec registerImage(This, Type, Bmp) -> ok when
+ This::wxStyledTextCtrl(), Type::integer(), Bmp::wxBitmap:wxBitmap().
registerImage(#wx_ref{type=ThisT,ref=ThisRef},Type,#wx_ref{type=BmpT,ref=BmpRef})
when is_integer(Type) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1179,271 +1318,308 @@ registerImage(#wx_ref{type=ThisT,ref=ThisRef},Type,#wx_ref{type=BmpT,ref=BmpRef}
wxe_util:cast(?wxStyledTextCtrl_RegisterImage,
<<ThisRef:32/?UI,Type:32/?UI,BmpRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlclearregisteredimages">external documentation</a>.
+-spec clearRegisteredImages(This) -> ok when
+ This::wxStyledTextCtrl().
clearRegisteredImages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ClearRegisteredImages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgettypeseparator">external documentation</a>.
+-spec autoCompGetTypeSeparator(This) -> integer() when
+ This::wxStyledTextCtrl().
autoCompGetTypeSeparator(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetTypeSeparator,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), SeparatorCharacter::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsettypeseparator">external documentation</a>.
+-spec autoCompSetTypeSeparator(This, SeparatorCharacter) -> ok when
+ This::wxStyledTextCtrl(), SeparatorCharacter::integer().
autoCompSetTypeSeparator(#wx_ref{type=ThisT,ref=ThisRef},SeparatorCharacter)
when is_integer(SeparatorCharacter) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetTypeSeparator,
<<ThisRef:32/?UI,SeparatorCharacter:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CharacterCount::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetmaxwidth">external documentation</a>.
+-spec autoCompSetMaxWidth(This, CharacterCount) -> ok when
+ This::wxStyledTextCtrl(), CharacterCount::integer().
autoCompSetMaxWidth(#wx_ref{type=ThisT,ref=ThisRef},CharacterCount)
when is_integer(CharacterCount) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetMaxWidth,
<<ThisRef:32/?UI,CharacterCount:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetmaxwidth">external documentation</a>.
+-spec autoCompGetMaxWidth(This) -> integer() when
+ This::wxStyledTextCtrl().
autoCompGetMaxWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetMaxWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), RowCount::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompsetmaxheight">external documentation</a>.
+-spec autoCompSetMaxHeight(This, RowCount) -> ok when
+ This::wxStyledTextCtrl(), RowCount::integer().
autoCompSetMaxHeight(#wx_ref{type=ThisT,ref=ThisRef},RowCount)
when is_integer(RowCount) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_AutoCompSetMaxHeight,
<<ThisRef:32/?UI,RowCount:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetmaxheight">external documentation</a>.
+-spec autoCompGetMaxHeight(This) -> integer() when
+ This::wxStyledTextCtrl().
autoCompGetMaxHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetMaxHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), IndentSize::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetindent">external documentation</a>.
+-spec setIndent(This, IndentSize) -> ok when
+ This::wxStyledTextCtrl(), IndentSize::integer().
setIndent(#wx_ref{type=ThisT,ref=ThisRef},IndentSize)
when is_integer(IndentSize) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetIndent,
<<ThisRef:32/?UI,IndentSize:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetindent">external documentation</a>.
+-spec getIndent(This) -> integer() when
+ This::wxStyledTextCtrl().
getIndent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetIndent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), UseTabs::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetusetabs">external documentation</a>.
+-spec setUseTabs(This, UseTabs) -> ok when
+ This::wxStyledTextCtrl(), UseTabs::boolean().
setUseTabs(#wx_ref{type=ThisT,ref=ThisRef},UseTabs)
when is_boolean(UseTabs) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetUseTabs,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseTabs)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetusetabs">external documentation</a>.
+-spec getUseTabs(This) -> boolean() when
+ This::wxStyledTextCtrl().
getUseTabs(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetUseTabs,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), IndentSize::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetlineindentation">external documentation</a>.
+-spec setLineIndentation(This, Line, IndentSize) -> ok when
+ This::wxStyledTextCtrl(), Line::integer(), IndentSize::integer().
setLineIndentation(#wx_ref{type=ThisT,ref=ThisRef},Line,IndentSize)
when is_integer(Line),is_integer(IndentSize) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetLineIndentation,
<<ThisRef:32/?UI,Line:32/?UI,IndentSize:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlineindentation">external documentation</a>.
+-spec getLineIndentation(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
getLineIndentation(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineIndentation,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlineindentposition">external documentation</a>.
+-spec getLineIndentPosition(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
getLineIndentPosition(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineIndentPosition,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcolumn">external documentation</a>.
+-spec getColumn(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
getColumn(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetColumn,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Show::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetusehorizontalscrollbar">external documentation</a>.
+-spec setUseHorizontalScrollBar(This, Show) -> ok when
+ This::wxStyledTextCtrl(), Show::boolean().
setUseHorizontalScrollBar(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetUseHorizontalScrollBar,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetusehorizontalscrollbar">external documentation</a>.
+-spec getUseHorizontalScrollBar(This) -> boolean() when
+ This::wxStyledTextCtrl().
getUseHorizontalScrollBar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetUseHorizontalScrollBar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Show::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetindentationguides">external documentation</a>.
+-spec setIndentationGuides(This, Show) -> ok when
+ This::wxStyledTextCtrl(), Show::boolean().
setIndentationGuides(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetIndentationGuides,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetindentationguides">external documentation</a>.
+-spec getIndentationGuides(This) -> boolean() when
+ This::wxStyledTextCtrl().
getIndentationGuides(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetIndentationGuides,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Column::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsethighlightguide">external documentation</a>.
+-spec setHighlightGuide(This, Column) -> ok when
+ This::wxStyledTextCtrl(), Column::integer().
setHighlightGuide(#wx_ref{type=ThisT,ref=ThisRef},Column)
when is_integer(Column) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetHighlightGuide,
<<ThisRef:32/?UI,Column:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgethighlightguide">external documentation</a>.
+-spec getHighlightGuide(This) -> integer() when
+ This::wxStyledTextCtrl().
getHighlightGuide(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetHighlightGuide,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlineendposition">external documentation</a>.
+-spec getLineEndPosition(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
getLineEndPosition(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineEndPosition,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcodepage">external documentation</a>.
+-spec getCodePage(This) -> integer() when
+ This::wxStyledTextCtrl().
getCodePage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCodePage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretforeground">external documentation</a>.
+-spec getCaretForeground(This) -> wx:wx_colour4() when
+ This::wxStyledTextCtrl().
getCaretForeground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretForeground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetreadonly">external documentation</a>.
+-spec getReadOnly(This) -> boolean() when
+ This::wxStyledTextCtrl().
getReadOnly(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetReadOnly,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcurrentpos">external documentation</a>.
+-spec setCurrentPos(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
setCurrentPos(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCurrentPos,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselectionstart">external documentation</a>.
+-spec setSelectionStart(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
setSelectionStart(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelectionStart,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselectionstart">external documentation</a>.
+-spec getSelectionStart(This) -> integer() when
+ This::wxStyledTextCtrl().
getSelectionStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelectionStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselectionend">external documentation</a>.
+-spec setSelectionEnd(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
setSelectionEnd(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelectionEnd,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselectionend">external documentation</a>.
+-spec getSelectionEnd(This) -> integer() when
+ This::wxStyledTextCtrl().
getSelectionEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelectionEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Magnification::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetprintmagnification">external documentation</a>.
+-spec setPrintMagnification(This, Magnification) -> ok when
+ This::wxStyledTextCtrl(), Magnification::integer().
setPrintMagnification(#wx_ref{type=ThisT,ref=ThisRef},Magnification)
when is_integer(Magnification) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetPrintMagnification,
<<ThisRef:32/?UI,Magnification:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetprintmagnification">external documentation</a>.
+-spec getPrintMagnification(This) -> integer() when
+ This::wxStyledTextCtrl().
getPrintMagnification(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetPrintMagnification,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetprintcolourmode">external documentation</a>.
+-spec setPrintColourMode(This, Mode) -> ok when
+ This::wxStyledTextCtrl(), Mode::integer().
setPrintColourMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetPrintColourMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetprintcolourmode">external documentation</a>.
+-spec getPrintColourMode(This) -> integer() when
+ This::wxStyledTextCtrl().
getPrintColourMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetPrintColourMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), MinPos::integer(), MaxPos::integer(), Text::string()) -> integer()
%% @equiv findText(This,MinPos,MaxPos,Text, [])
+-spec findText(This, MinPos, MaxPos, Text) -> integer() when
+ This::wxStyledTextCtrl(), MinPos::integer(), MaxPos::integer(), Text::unicode:chardata().
+
findText(This,MinPos,MaxPos,Text)
when is_record(This, wx_ref),is_integer(MinPos),is_integer(MaxPos),is_list(Text) ->
findText(This,MinPos,MaxPos,Text, []).
-%% @spec (This::wxStyledTextCtrl(), MinPos::integer(), MaxPos::integer(), Text::string(), [Option]) -> integer()
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlfindtext">external documentation</a>.
+-spec findText(This, MinPos, MaxPos, Text, [Option]) -> integer() when
+ This::wxStyledTextCtrl(), MinPos::integer(), MaxPos::integer(), Text::unicode:chardata(),
+ Option :: {flags, integer()}.
findText(#wx_ref{type=ThisT,ref=ThisRef},MinPos,MaxPos,Text, Options)
when is_integer(MinPos),is_integer(MaxPos),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1454,8 +1630,9 @@ findText(#wx_ref{type=ThisT,ref=ThisRef},MinPos,MaxPos,Text, Options)
wxe_util:call(?wxStyledTextCtrl_FindText,
<<ThisRef:32/?UI,MinPos:32/?UI,MaxPos:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), DoDraw::bool(), StartPos::integer(), EndPos::integer(), Draw::wxDC:wxDC(), Target::wxDC:wxDC(), RenderRect::{X::integer(),Y::integer(),W::integer(),H::integer()}, PageRect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlformatrange">external documentation</a>.
+-spec formatRange(This, DoDraw, StartPos, EndPos, Draw, Target, RenderRect, PageRect) -> integer() when
+ This::wxStyledTextCtrl(), DoDraw::boolean(), StartPos::integer(), EndPos::integer(), Draw::wxDC:wxDC(), Target::wxDC:wxDC(), RenderRect::{X::integer(), Y::integer(), W::integer(), H::integer()}, PageRect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
formatRange(#wx_ref{type=ThisT,ref=ThisRef},DoDraw,StartPos,EndPos,#wx_ref{type=DrawT,ref=DrawRef},#wx_ref{type=TargetT,ref=TargetRef},{RenderRectX,RenderRectY,RenderRectW,RenderRectH},{PageRectX,PageRectY,PageRectW,PageRectH})
when is_boolean(DoDraw),is_integer(StartPos),is_integer(EndPos),is_integer(RenderRectX),is_integer(RenderRectY),is_integer(RenderRectW),is_integer(RenderRectH),is_integer(PageRectX),is_integer(PageRectY),is_integer(PageRectW),is_integer(PageRectH) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1464,129 +1641,146 @@ formatRange(#wx_ref{type=ThisT,ref=ThisRef},DoDraw,StartPos,EndPos,#wx_ref{type=
wxe_util:call(?wxStyledTextCtrl_FormatRange,
<<ThisRef:32/?UI,(wxe_util:from_bool(DoDraw)):32/?UI,StartPos:32/?UI,EndPos:32/?UI,DrawRef:32/?UI,TargetRef:32/?UI,RenderRectX:32/?UI,RenderRectY:32/?UI,RenderRectW:32/?UI,RenderRectH:32/?UI,PageRectX:32/?UI,PageRectY:32/?UI,PageRectW:32/?UI,PageRectH:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetfirstvisibleline">external documentation</a>.
+-spec getFirstVisibleLine(This) -> integer() when
+ This::wxStyledTextCtrl().
getFirstVisibleLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetFirstVisibleLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetline">external documentation</a>.
+-spec getLine(This, Line) -> unicode:charlist() when
+ This::wxStyledTextCtrl(), Line::integer().
getLine(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLine,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlinecount">external documentation</a>.
+-spec getLineCount(This) -> integer() when
+ This::wxStyledTextCtrl().
getLineCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PixelWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmarginleft">external documentation</a>.
+-spec setMarginLeft(This, PixelWidth) -> ok when
+ This::wxStyledTextCtrl(), PixelWidth::integer().
setMarginLeft(#wx_ref{type=ThisT,ref=ThisRef},PixelWidth)
when is_integer(PixelWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMarginLeft,
<<ThisRef:32/?UI,PixelWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmarginleft">external documentation</a>.
+-spec getMarginLeft(This) -> integer() when
+ This::wxStyledTextCtrl().
getMarginLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMarginLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PixelWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmarginright">external documentation</a>.
+-spec setMarginRight(This, PixelWidth) -> ok when
+ This::wxStyledTextCtrl(), PixelWidth::integer().
setMarginRight(#wx_ref{type=ThisT,ref=ThisRef},PixelWidth)
when is_integer(PixelWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMarginRight,
<<ThisRef:32/?UI,PixelWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmarginright">external documentation</a>.
+-spec getMarginRight(This) -> integer() when
+ This::wxStyledTextCtrl().
getMarginRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMarginRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmodify">external documentation</a>.
+-spec getModify(This) -> boolean() when
+ This::wxStyledTextCtrl().
getModify(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetModify,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Start::integer(), End::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselection">external documentation</a>.
+-spec setSelection(This, Start, End) -> ok when
+ This::wxStyledTextCtrl(), Start::integer(), End::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},Start,End)
when is_integer(Start),is_integer(End) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelection,
<<ThisRef:32/?UI,Start:32/?UI,End:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselectedtext">external documentation</a>.
+-spec getSelectedText(This) -> unicode:charlist() when
+ This::wxStyledTextCtrl().
getSelectedText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelectedText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), StartPos::integer(), EndPos::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettextrange">external documentation</a>.
+-spec getTextRange(This, StartPos, EndPos) -> unicode:charlist() when
+ This::wxStyledTextCtrl(), StartPos::integer(), EndPos::integer().
getTextRange(#wx_ref{type=ThisT,ref=ThisRef},StartPos,EndPos)
when is_integer(StartPos),is_integer(EndPos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTextRange,
<<ThisRef:32/?UI,StartPos:32/?UI,EndPos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Normal::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhideselection">external documentation</a>.
+-spec hideSelection(This, Normal) -> ok when
+ This::wxStyledTextCtrl(), Normal::boolean().
hideSelection(#wx_ref{type=ThisT,ref=ThisRef},Normal)
when is_boolean(Normal) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HideSelection,
<<ThisRef:32/?UI,(wxe_util:from_bool(Normal)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinefromposition">external documentation</a>.
+-spec lineFromPosition(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
lineFromPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_LineFromPosition,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpositionfromline">external documentation</a>.
+-spec positionFromLine(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
positionFromLine(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_PositionFromLine,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Columns::integer(), Lines::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinescroll">external documentation</a>.
+-spec lineScroll(This, Columns, Lines) -> ok when
+ This::wxStyledTextCtrl(), Columns::integer(), Lines::integer().
lineScroll(#wx_ref{type=ThisT,ref=ThisRef},Columns,Lines)
when is_integer(Columns),is_integer(Lines) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineScroll,
<<ThisRef:32/?UI,Columns:32/?UI,Lines:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlensurecaretvisible">external documentation</a>.
+-spec ensureCaretVisible(This) -> ok when
+ This::wxStyledTextCtrl().
ensureCaretVisible(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_EnsureCaretVisible,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlreplaceselection">external documentation</a>.
+-spec replaceSelection(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
replaceSelection(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1594,72 +1788,82 @@ replaceSelection(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_ReplaceSelection,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), ReadOnly::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetreadonly">external documentation</a>.
+-spec setReadOnly(This, ReadOnly) -> ok when
+ This::wxStyledTextCtrl(), ReadOnly::boolean().
setReadOnly(#wx_ref{type=ThisT,ref=ThisRef},ReadOnly)
when is_boolean(ReadOnly) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetReadOnly,
<<ThisRef:32/?UI,(wxe_util:from_bool(ReadOnly)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcanpaste">external documentation</a>.
+-spec canPaste(This) -> boolean() when
+ This::wxStyledTextCtrl().
canPaste(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_CanPaste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcanundo">external documentation</a>.
+-spec canUndo(This) -> boolean() when
+ This::wxStyledTextCtrl().
canUndo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_CanUndo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlemptyundobuffer">external documentation</a>.
+-spec emptyUndoBuffer(This) -> ok when
+ This::wxStyledTextCtrl().
emptyUndoBuffer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_EmptyUndoBuffer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlundo">external documentation</a>.
+-spec undo(This) -> ok when
+ This::wxStyledTextCtrl().
undo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Undo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcut">external documentation</a>.
+-spec cut(This) -> ok when
+ This::wxStyledTextCtrl().
cut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Cut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcopy">external documentation</a>.
+-spec copy(This) -> ok when
+ This::wxStyledTextCtrl().
copy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Copy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpaste">external documentation</a>.
+-spec paste(This) -> ok when
+ This::wxStyledTextCtrl().
paste(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Paste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxStyledTextCtrl().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettext">external documentation</a>.
+-spec setText(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1667,74 +1871,84 @@ setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_SetText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxStyledTextCtrl().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettextlength">external documentation</a>.
+-spec getTextLength(This) -> integer() when
+ This::wxStyledTextCtrl().
getTextLength(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTextLength,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetovertype">external documentation</a>.
+-spec getOvertype(This) -> boolean() when
+ This::wxStyledTextCtrl().
getOvertype(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetOvertype,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PixelWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretwidth">external documentation</a>.
+-spec setCaretWidth(This, PixelWidth) -> ok when
+ This::wxStyledTextCtrl(), PixelWidth::integer().
setCaretWidth(#wx_ref{type=ThisT,ref=ThisRef},PixelWidth)
when is_integer(PixelWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretWidth,
<<ThisRef:32/?UI,PixelWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretwidth">external documentation</a>.
+-spec getCaretWidth(This) -> integer() when
+ This::wxStyledTextCtrl().
getCaretWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettargetstart">external documentation</a>.
+-spec setTargetStart(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
setTargetStart(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetTargetStart,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettargetstart">external documentation</a>.
+-spec getTargetStart(This) -> integer() when
+ This::wxStyledTextCtrl().
getTargetStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTargetStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettargetend">external documentation</a>.
+-spec setTargetEnd(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
setTargetEnd(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetTargetEnd,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettargetend">external documentation</a>.
+-spec getTargetEnd(This) -> integer() when
+ This::wxStyledTextCtrl().
getTargetEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTargetEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlreplacetarget">external documentation</a>.
+-spec replaceTarget(This, Text) -> integer() when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
replaceTarget(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1742,8 +1956,9 @@ replaceTarget(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:call(?wxStyledTextCtrl_ReplaceTarget,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsearchintarget">external documentation</a>.
+-spec searchInTarget(This, Text) -> integer() when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
searchInTarget(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1751,23 +1966,26 @@ searchInTarget(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:call(?wxStyledTextCtrl_SearchInTarget,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Flags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetsearchflags">external documentation</a>.
+-spec setSearchFlags(This, Flags) -> ok when
+ This::wxStyledTextCtrl(), Flags::integer().
setSearchFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSearchFlags,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetsearchflags">external documentation</a>.
+-spec getSearchFlags(This) -> integer() when
+ This::wxStyledTextCtrl().
getSearchFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSearchFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer(), Definition::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipshow">external documentation</a>.
+-spec callTipShow(This, Pos, Definition) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer(), Definition::unicode:chardata().
callTipShow(#wx_ref{type=ThisT,ref=ThisRef},Pos,Definition)
when is_integer(Pos),is_list(Definition) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -1775,348 +1993,393 @@ callTipShow(#wx_ref{type=ThisT,ref=ThisRef},Pos,Definition)
wxe_util:cast(?wxStyledTextCtrl_CallTipShow,
<<ThisRef:32/?UI,Pos:32/?UI,(byte_size(Definition_UC)):32/?UI,(Definition_UC)/binary, 0:(((8- ((4+byte_size(Definition_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipcancel">external documentation</a>.
+-spec callTipCancel(This) -> ok when
+ This::wxStyledTextCtrl().
callTipCancel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CallTipCancel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipactive">external documentation</a>.
+-spec callTipActive(This) -> boolean() when
+ This::wxStyledTextCtrl().
callTipActive(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_CallTipActive,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipposatstart">external documentation</a>.
+-spec callTipPosAtStart(This) -> integer() when
+ This::wxStyledTextCtrl().
callTipPosAtStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_CallTipPosAtStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Start::integer(), End::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipsethighlight">external documentation</a>.
+-spec callTipSetHighlight(This, Start, End) -> ok when
+ This::wxStyledTextCtrl(), Start::integer(), End::integer().
callTipSetHighlight(#wx_ref{type=ThisT,ref=ThisRef},Start,End)
when is_integer(Start),is_integer(End) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CallTipSetHighlight,
<<ThisRef:32/?UI,Start:32/?UI,End:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipsetbackground">external documentation</a>.
+-spec callTipSetBackground(This, Back) -> ok when
+ This::wxStyledTextCtrl(), Back::wx:wx_colour().
callTipSetBackground(#wx_ref{type=ThisT,ref=ThisRef},Back)
when tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CallTipSetBackground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipsetforeground">external documentation</a>.
+-spec callTipSetForeground(This, Fore) -> ok when
+ This::wxStyledTextCtrl(), Fore::wx:wx_colour().
callTipSetForeground(#wx_ref{type=ThisT,ref=ThisRef},Fore)
when tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CallTipSetForeground,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipsetforegroundhighlight">external documentation</a>.
+-spec callTipSetForegroundHighlight(This, Fore) -> ok when
+ This::wxStyledTextCtrl(), Fore::wx:wx_colour().
callTipSetForegroundHighlight(#wx_ref{type=ThisT,ref=ThisRef},Fore)
when tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CallTipSetForegroundHighlight,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), TabSize::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcalltipusestyle">external documentation</a>.
+-spec callTipUseStyle(This, TabSize) -> ok when
+ This::wxStyledTextCtrl(), TabSize::integer().
callTipUseStyle(#wx_ref{type=ThisT,ref=ThisRef},TabSize)
when is_integer(TabSize) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CallTipUseStyle,
<<ThisRef:32/?UI,TabSize:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlvisiblefromdocline">external documentation</a>.
+-spec visibleFromDocLine(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
visibleFromDocLine(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_VisibleFromDocLine,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), LineDisplay::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldoclinefromvisible">external documentation</a>.
+-spec docLineFromVisible(This, LineDisplay) -> integer() when
+ This::wxStyledTextCtrl(), LineDisplay::integer().
docLineFromVisible(#wx_ref{type=ThisT,ref=ThisRef},LineDisplay)
when is_integer(LineDisplay) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_DocLineFromVisible,
<<ThisRef:32/?UI,LineDisplay:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwrapcount">external documentation</a>.
+-spec wrapCount(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
wrapCount(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_WrapCount,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), Level::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetfoldlevel">external documentation</a>.
+-spec setFoldLevel(This, Line, Level) -> ok when
+ This::wxStyledTextCtrl(), Line::integer(), Level::integer().
setFoldLevel(#wx_ref{type=ThisT,ref=ThisRef},Line,Level)
when is_integer(Line),is_integer(Level) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetFoldLevel,
<<ThisRef:32/?UI,Line:32/?UI,Level:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetfoldlevel">external documentation</a>.
+-spec getFoldLevel(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
getFoldLevel(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetFoldLevel,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), Level::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlastchild">external documentation</a>.
+-spec getLastChild(This, Line, Level) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer(), Level::integer().
getLastChild(#wx_ref{type=ThisT,ref=ThisRef},Line,Level)
when is_integer(Line),is_integer(Level) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLastChild,
<<ThisRef:32/?UI,Line:32/?UI,Level:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetfoldparent">external documentation</a>.
+-spec getFoldParent(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
getFoldParent(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetFoldParent,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), LineStart::integer(), LineEnd::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlshowlines">external documentation</a>.
+-spec showLines(This, LineStart, LineEnd) -> ok when
+ This::wxStyledTextCtrl(), LineStart::integer(), LineEnd::integer().
showLines(#wx_ref{type=ThisT,ref=ThisRef},LineStart,LineEnd)
when is_integer(LineStart),is_integer(LineEnd) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ShowLines,
<<ThisRef:32/?UI,LineStart:32/?UI,LineEnd:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), LineStart::integer(), LineEnd::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhidelines">external documentation</a>.
+-spec hideLines(This, LineStart, LineEnd) -> ok when
+ This::wxStyledTextCtrl(), LineStart::integer(), LineEnd::integer().
hideLines(#wx_ref{type=ThisT,ref=ThisRef},LineStart,LineEnd)
when is_integer(LineStart),is_integer(LineEnd) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HideLines,
<<ThisRef:32/?UI,LineStart:32/?UI,LineEnd:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlinevisible">external documentation</a>.
+-spec getLineVisible(This, Line) -> boolean() when
+ This::wxStyledTextCtrl(), Line::integer().
getLineVisible(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineVisible,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), Expanded::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetfoldexpanded">external documentation</a>.
+-spec setFoldExpanded(This, Line, Expanded) -> ok when
+ This::wxStyledTextCtrl(), Line::integer(), Expanded::boolean().
setFoldExpanded(#wx_ref{type=ThisT,ref=ThisRef},Line,Expanded)
when is_integer(Line),is_boolean(Expanded) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetFoldExpanded,
<<ThisRef:32/?UI,Line:32/?UI,(wxe_util:from_bool(Expanded)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetfoldexpanded">external documentation</a>.
+-spec getFoldExpanded(This, Line) -> boolean() when
+ This::wxStyledTextCtrl(), Line::integer().
getFoldExpanded(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetFoldExpanded,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrltogglefold">external documentation</a>.
+-spec toggleFold(This, Line) -> ok when
+ This::wxStyledTextCtrl(), Line::integer().
toggleFold(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ToggleFold,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlensurevisible">external documentation</a>.
+-spec ensureVisible(This, Line) -> ok when
+ This::wxStyledTextCtrl(), Line::integer().
ensureVisible(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_EnsureVisible,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Flags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetfoldflags">external documentation</a>.
+-spec setFoldFlags(This, Flags) -> ok when
+ This::wxStyledTextCtrl(), Flags::integer().
setFoldFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetFoldFlags,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlensurevisibleenforcepolicy">external documentation</a>.
+-spec ensureVisibleEnforcePolicy(This, Line) -> ok when
+ This::wxStyledTextCtrl(), Line::integer().
ensureVisibleEnforcePolicy(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_EnsureVisibleEnforcePolicy,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), TabIndents::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettabindents">external documentation</a>.
+-spec setTabIndents(This, TabIndents) -> ok when
+ This::wxStyledTextCtrl(), TabIndents::boolean().
setTabIndents(#wx_ref{type=ThisT,ref=ThisRef},TabIndents)
when is_boolean(TabIndents) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetTabIndents,
<<ThisRef:32/?UI,(wxe_util:from_bool(TabIndents)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettabindents">external documentation</a>.
+-spec getTabIndents(This) -> boolean() when
+ This::wxStyledTextCtrl().
getTabIndents(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTabIndents,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), BsUnIndents::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetbackspaceunindents">external documentation</a>.
+-spec setBackSpaceUnIndents(This, BsUnIndents) -> ok when
+ This::wxStyledTextCtrl(), BsUnIndents::boolean().
setBackSpaceUnIndents(#wx_ref{type=ThisT,ref=ThisRef},BsUnIndents)
when is_boolean(BsUnIndents) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetBackSpaceUnIndents,
<<ThisRef:32/?UI,(wxe_util:from_bool(BsUnIndents)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetbackspaceunindents">external documentation</a>.
+-spec getBackSpaceUnIndents(This) -> boolean() when
+ This::wxStyledTextCtrl().
getBackSpaceUnIndents(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetBackSpaceUnIndents,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PeriodMilliseconds::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmousedwelltime">external documentation</a>.
+-spec setMouseDwellTime(This, PeriodMilliseconds) -> ok when
+ This::wxStyledTextCtrl(), PeriodMilliseconds::integer().
setMouseDwellTime(#wx_ref{type=ThisT,ref=ThisRef},PeriodMilliseconds)
when is_integer(PeriodMilliseconds) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMouseDwellTime,
<<ThisRef:32/?UI,PeriodMilliseconds:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmousedwelltime">external documentation</a>.
+-spec getMouseDwellTime(This) -> integer() when
+ This::wxStyledTextCtrl().
getMouseDwellTime(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMouseDwellTime,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer(), OnlyWordCharacters::bool()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordstartposition">external documentation</a>.
+-spec wordStartPosition(This, Pos, OnlyWordCharacters) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer(), OnlyWordCharacters::boolean().
wordStartPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos,OnlyWordCharacters)
when is_integer(Pos),is_boolean(OnlyWordCharacters) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_WordStartPosition,
<<ThisRef:32/?UI,Pos:32/?UI,(wxe_util:from_bool(OnlyWordCharacters)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer(), OnlyWordCharacters::bool()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordendposition">external documentation</a>.
+-spec wordEndPosition(This, Pos, OnlyWordCharacters) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer(), OnlyWordCharacters::boolean().
wordEndPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos,OnlyWordCharacters)
when is_integer(Pos),is_boolean(OnlyWordCharacters) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_WordEndPosition,
<<ThisRef:32/?UI,Pos:32/?UI,(wxe_util:from_bool(OnlyWordCharacters)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwrapmode">external documentation</a>.
+-spec setWrapMode(This, Mode) -> ok when
+ This::wxStyledTextCtrl(), Mode::integer().
setWrapMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetWrapMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetwrapmode">external documentation</a>.
+-spec getWrapMode(This) -> integer() when
+ This::wxStyledTextCtrl().
getWrapMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetWrapMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), WrapVisualFlags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwrapvisualflags">external documentation</a>.
+-spec setWrapVisualFlags(This, WrapVisualFlags) -> ok when
+ This::wxStyledTextCtrl(), WrapVisualFlags::integer().
setWrapVisualFlags(#wx_ref{type=ThisT,ref=ThisRef},WrapVisualFlags)
when is_integer(WrapVisualFlags) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetWrapVisualFlags,
<<ThisRef:32/?UI,WrapVisualFlags:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetwrapvisualflags">external documentation</a>.
+-spec getWrapVisualFlags(This) -> integer() when
+ This::wxStyledTextCtrl().
getWrapVisualFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetWrapVisualFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), WrapVisualFlagsLocation::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwrapvisualflagslocation">external documentation</a>.
+-spec setWrapVisualFlagsLocation(This, WrapVisualFlagsLocation) -> ok when
+ This::wxStyledTextCtrl(), WrapVisualFlagsLocation::integer().
setWrapVisualFlagsLocation(#wx_ref{type=ThisT,ref=ThisRef},WrapVisualFlagsLocation)
when is_integer(WrapVisualFlagsLocation) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetWrapVisualFlagsLocation,
<<ThisRef:32/?UI,WrapVisualFlagsLocation:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetwrapvisualflagslocation">external documentation</a>.
+-spec getWrapVisualFlagsLocation(This) -> integer() when
+ This::wxStyledTextCtrl().
getWrapVisualFlagsLocation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetWrapVisualFlagsLocation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Indent::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwrapstartindent">external documentation</a>.
+-spec setWrapStartIndent(This, Indent) -> ok when
+ This::wxStyledTextCtrl(), Indent::integer().
setWrapStartIndent(#wx_ref{type=ThisT,ref=ThisRef},Indent)
when is_integer(Indent) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetWrapStartIndent,
<<ThisRef:32/?UI,Indent:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetwrapstartindent">external documentation</a>.
+-spec getWrapStartIndent(This) -> integer() when
+ This::wxStyledTextCtrl().
getWrapStartIndent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetWrapStartIndent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetlayoutcache">external documentation</a>.
+-spec setLayoutCache(This, Mode) -> ok when
+ This::wxStyledTextCtrl(), Mode::integer().
setLayoutCache(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetLayoutCache,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlayoutcache">external documentation</a>.
+-spec getLayoutCache(This) -> integer() when
+ This::wxStyledTextCtrl().
getLayoutCache(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLayoutCache,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PixelWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetscrollwidth">external documentation</a>.
+-spec setScrollWidth(This, PixelWidth) -> ok when
+ This::wxStyledTextCtrl(), PixelWidth::integer().
setScrollWidth(#wx_ref{type=ThisT,ref=ThisRef},PixelWidth)
when is_integer(PixelWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetScrollWidth,
<<ThisRef:32/?UI,PixelWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetscrollwidth">external documentation</a>.
+-spec getScrollWidth(This) -> integer() when
+ This::wxStyledTextCtrl().
getScrollWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetScrollWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Text::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrltextwidth">external documentation</a>.
+-spec textWidth(This, Style, Text) -> integer() when
+ This::wxStyledTextCtrl(), Style::integer(), Text::unicode:chardata().
textWidth(#wx_ref{type=ThisT,ref=ThisRef},Style,Text)
when is_integer(Style),is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -2124,38 +2387,43 @@ textWidth(#wx_ref{type=ThisT,ref=ThisRef},Style,Text)
wxe_util:call(?wxStyledTextCtrl_TextWidth,
<<ThisRef:32/?UI,Style:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetendatlastline">external documentation</a>.
+-spec getEndAtLastLine(This) -> boolean() when
+ This::wxStyledTextCtrl().
getEndAtLastLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetEndAtLastLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrltextheight">external documentation</a>.
+-spec textHeight(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
textHeight(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_TextHeight,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Show::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetuseverticalscrollbar">external documentation</a>.
+-spec setUseVerticalScrollBar(This, Show) -> ok when
+ This::wxStyledTextCtrl(), Show::boolean().
setUseVerticalScrollBar(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetUseVerticalScrollBar,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetuseverticalscrollbar">external documentation</a>.
+-spec getUseVerticalScrollBar(This) -> boolean() when
+ This::wxStyledTextCtrl().
getUseVerticalScrollBar(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetUseVerticalScrollBar,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlappendtext">external documentation</a>.
+-spec appendText(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::unicode:chardata().
appendText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -2163,559 +2431,646 @@ appendText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_AppendText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettwophasedraw">external documentation</a>.
+-spec getTwoPhaseDraw(This) -> boolean() when
+ This::wxStyledTextCtrl().
getTwoPhaseDraw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTwoPhaseDraw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), TwoPhase::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettwophasedraw">external documentation</a>.
+-spec setTwoPhaseDraw(This, TwoPhase) -> ok when
+ This::wxStyledTextCtrl(), TwoPhase::boolean().
setTwoPhaseDraw(#wx_ref{type=ThisT,ref=ThisRef},TwoPhase)
when is_boolean(TwoPhase) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetTwoPhaseDraw,
<<ThisRef:32/?UI,(wxe_util:from_bool(TwoPhase)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrltargetfromselection">external documentation</a>.
+-spec targetFromSelection(This) -> ok when
+ This::wxStyledTextCtrl().
targetFromSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_TargetFromSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinesjoin">external documentation</a>.
+-spec linesJoin(This) -> ok when
+ This::wxStyledTextCtrl().
linesJoin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LinesJoin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), PixelWidth::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinessplit">external documentation</a>.
+-spec linesSplit(This, PixelWidth) -> ok when
+ This::wxStyledTextCtrl(), PixelWidth::integer().
linesSplit(#wx_ref{type=ThisT,ref=ThisRef},PixelWidth)
when is_integer(PixelWidth) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LinesSplit,
<<ThisRef:32/?UI,PixelWidth:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetfoldmargincolour">external documentation</a>.
+-spec setFoldMarginColour(This, UseSetting, Back) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Back::wx:wx_colour().
setFoldMarginColour(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Back)
when is_boolean(UseSetting),tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetFoldMarginColour,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetfoldmarginhicolour">external documentation</a>.
+-spec setFoldMarginHiColour(This, UseSetting, Fore) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Fore::wx:wx_colour().
setFoldMarginHiColour(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Fore)
when is_boolean(UseSetting),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetFoldMarginHiColour,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinedown">external documentation</a>.
+-spec lineDown(This) -> ok when
+ This::wxStyledTextCtrl().
lineDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinedownextend">external documentation</a>.
+-spec lineDownExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineDownExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineDownExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineup">external documentation</a>.
+-spec lineUp(This) -> ok when
+ This::wxStyledTextCtrl().
lineUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineupextend">external documentation</a>.
+-spec lineUpExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineUpExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineUpExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcharleft">external documentation</a>.
+-spec charLeft(This) -> ok when
+ This::wxStyledTextCtrl().
charLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CharLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcharleftextend">external documentation</a>.
+-spec charLeftExtend(This) -> ok when
+ This::wxStyledTextCtrl().
charLeftExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CharLeftExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcharright">external documentation</a>.
+-spec charRight(This) -> ok when
+ This::wxStyledTextCtrl().
charRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CharRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcharrightextend">external documentation</a>.
+-spec charRightExtend(This) -> ok when
+ This::wxStyledTextCtrl().
charRightExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CharRightExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordleft">external documentation</a>.
+-spec wordLeft(This) -> ok when
+ This::wxStyledTextCtrl().
wordLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordleftextend">external documentation</a>.
+-spec wordLeftExtend(This) -> ok when
+ This::wxStyledTextCtrl().
wordLeftExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordLeftExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordright">external documentation</a>.
+-spec wordRight(This) -> ok when
+ This::wxStyledTextCtrl().
wordRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordrightextend">external documentation</a>.
+-spec wordRightExtend(This) -> ok when
+ This::wxStyledTextCtrl().
wordRightExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordRightExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhome">external documentation</a>.
+-spec home(This) -> ok when
+ This::wxStyledTextCtrl().
home(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Home,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhomeextend">external documentation</a>.
+-spec homeExtend(This) -> ok when
+ This::wxStyledTextCtrl().
homeExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HomeExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineend">external documentation</a>.
+-spec lineEnd(This) -> ok when
+ This::wxStyledTextCtrl().
lineEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineendextend">external documentation</a>.
+-spec lineEndExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineEndExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEndExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldocumentstart">external documentation</a>.
+-spec documentStart(This) -> ok when
+ This::wxStyledTextCtrl().
documentStart(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DocumentStart,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldocumentstartextend">external documentation</a>.
+-spec documentStartExtend(This) -> ok when
+ This::wxStyledTextCtrl().
documentStartExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DocumentStartExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldocumentend">external documentation</a>.
+-spec documentEnd(This) -> ok when
+ This::wxStyledTextCtrl().
documentEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DocumentEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldocumentendextend">external documentation</a>.
+-spec documentEndExtend(This) -> ok when
+ This::wxStyledTextCtrl().
documentEndExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DocumentEndExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpageup">external documentation</a>.
+-spec pageUp(This) -> ok when
+ This::wxStyledTextCtrl().
pageUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_PageUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpageupextend">external documentation</a>.
+-spec pageUpExtend(This) -> ok when
+ This::wxStyledTextCtrl().
pageUpExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_PageUpExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpagedown">external documentation</a>.
+-spec pageDown(This) -> ok when
+ This::wxStyledTextCtrl().
pageDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_PageDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpagedownextend">external documentation</a>.
+-spec pageDownExtend(This) -> ok when
+ This::wxStyledTextCtrl().
pageDownExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_PageDownExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrledittoggleovertype">external documentation</a>.
+-spec editToggleOvertype(This) -> ok when
+ This::wxStyledTextCtrl().
editToggleOvertype(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_EditToggleOvertype,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcancel">external documentation</a>.
+-spec cancel(This) -> ok when
+ This::wxStyledTextCtrl().
cancel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Cancel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldeleteback">external documentation</a>.
+-spec deleteBack(This) -> ok when
+ This::wxStyledTextCtrl().
deleteBack(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DeleteBack,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrltab">external documentation</a>.
+-spec tab(This) -> ok when
+ This::wxStyledTextCtrl().
tab(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Tab,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlbacktab">external documentation</a>.
+-spec backTab(This) -> ok when
+ This::wxStyledTextCtrl().
backTab(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_BackTab,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlnewline">external documentation</a>.
+-spec newLine(This) -> ok when
+ This::wxStyledTextCtrl().
newLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_NewLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlformfeed">external documentation</a>.
+-spec formFeed(This) -> ok when
+ This::wxStyledTextCtrl().
formFeed(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_FormFeed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlvchome">external documentation</a>.
+-spec vCHome(This) -> ok when
+ This::wxStyledTextCtrl().
vCHome(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_VCHome,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlvchomeextend">external documentation</a>.
+-spec vCHomeExtend(This) -> ok when
+ This::wxStyledTextCtrl().
vCHomeExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_VCHomeExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlzoomin">external documentation</a>.
+-spec zoomIn(This) -> ok when
+ This::wxStyledTextCtrl().
zoomIn(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ZoomIn,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlzoomout">external documentation</a>.
+-spec zoomOut(This) -> ok when
+ This::wxStyledTextCtrl().
zoomOut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ZoomOut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldelwordleft">external documentation</a>.
+-spec delWordLeft(This) -> ok when
+ This::wxStyledTextCtrl().
delWordLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DelWordLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldelwordright">external documentation</a>.
+-spec delWordRight(This) -> ok when
+ This::wxStyledTextCtrl().
delWordRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DelWordRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinecut">external documentation</a>.
+-spec lineCut(This) -> ok when
+ This::wxStyledTextCtrl().
lineCut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineCut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinedelete">external documentation</a>.
+-spec lineDelete(This) -> ok when
+ This::wxStyledTextCtrl().
lineDelete(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineDelete,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinetranspose">external documentation</a>.
+-spec lineTranspose(This) -> ok when
+ This::wxStyledTextCtrl().
lineTranspose(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineTranspose,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineduplicate">external documentation</a>.
+-spec lineDuplicate(This) -> ok when
+ This::wxStyledTextCtrl().
lineDuplicate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineDuplicate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllowercase">external documentation</a>.
+-spec lowerCase(This) -> ok when
+ This::wxStyledTextCtrl().
lowerCase(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LowerCase,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrluppercase">external documentation</a>.
+-spec upperCase(This) -> ok when
+ This::wxStyledTextCtrl().
upperCase(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_UpperCase,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinescrolldown">external documentation</a>.
+-spec lineScrollDown(This) -> ok when
+ This::wxStyledTextCtrl().
lineScrollDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineScrollDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinescrollup">external documentation</a>.
+-spec lineScrollUp(This) -> ok when
+ This::wxStyledTextCtrl().
lineScrollUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineScrollUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldeletebacknotline">external documentation</a>.
+-spec deleteBackNotLine(This) -> ok when
+ This::wxStyledTextCtrl().
deleteBackNotLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DeleteBackNotLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhomedisplay">external documentation</a>.
+-spec homeDisplay(This) -> ok when
+ This::wxStyledTextCtrl().
homeDisplay(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HomeDisplay,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhomedisplayextend">external documentation</a>.
+-spec homeDisplayExtend(This) -> ok when
+ This::wxStyledTextCtrl().
homeDisplayExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HomeDisplayExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineenddisplay">external documentation</a>.
+-spec lineEndDisplay(This) -> ok when
+ This::wxStyledTextCtrl().
lineEndDisplay(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEndDisplay,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineenddisplayextend">external documentation</a>.
+-spec lineEndDisplayExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineEndDisplayExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEndDisplayExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhomewrapextend">external documentation</a>.
+-spec homeWrapExtend(This) -> ok when
+ This::wxStyledTextCtrl().
homeWrapExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HomeWrapExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineendwrap">external documentation</a>.
+-spec lineEndWrap(This) -> ok when
+ This::wxStyledTextCtrl().
lineEndWrap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEndWrap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineendwrapextend">external documentation</a>.
+-spec lineEndWrapExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineEndWrapExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEndWrapExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlvchomewrap">external documentation</a>.
+-spec vCHomeWrap(This) -> ok when
+ This::wxStyledTextCtrl().
vCHomeWrap(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_VCHomeWrap,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlvchomewrapextend">external documentation</a>.
+-spec vCHomeWrapExtend(This) -> ok when
+ This::wxStyledTextCtrl().
vCHomeWrapExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_VCHomeWrapExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinecopy">external documentation</a>.
+-spec lineCopy(This) -> ok when
+ This::wxStyledTextCtrl().
lineCopy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineCopy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlmovecaretinsideview">external documentation</a>.
+-spec moveCaretInsideView(This) -> ok when
+ This::wxStyledTextCtrl().
moveCaretInsideView(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_MoveCaretInsideView,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinelength">external documentation</a>.
+-spec lineLength(This, Line) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer().
lineLength(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_LineLength,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos1::integer(), Pos2::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlbracehighlight">external documentation</a>.
+-spec braceHighlight(This, Pos1, Pos2) -> ok when
+ This::wxStyledTextCtrl(), Pos1::integer(), Pos2::integer().
braceHighlight(#wx_ref{type=ThisT,ref=ThisRef},Pos1,Pos2)
when is_integer(Pos1),is_integer(Pos2) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_BraceHighlight,
<<ThisRef:32/?UI,Pos1:32/?UI,Pos2:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlbracebadlight">external documentation</a>.
+-spec braceBadLight(This, Pos) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer().
braceBadLight(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_BraceBadLight,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlbracematch">external documentation</a>.
+-spec braceMatch(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
braceMatch(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_BraceMatch,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetvieweol">external documentation</a>.
+-spec getViewEOL(This) -> boolean() when
+ This::wxStyledTextCtrl().
getViewEOL(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetViewEOL,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Visible::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetvieweol">external documentation</a>.
+-spec setViewEOL(This, Visible) -> ok when
+ This::wxStyledTextCtrl(), Visible::boolean().
setViewEOL(#wx_ref{type=ThisT,ref=ThisRef},Visible)
when is_boolean(Visible) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetViewEOL,
<<ThisRef:32/?UI,(wxe_util:from_bool(Visible)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Mask::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmodeventmask">external documentation</a>.
+-spec setModEventMask(This, Mask) -> ok when
+ This::wxStyledTextCtrl(), Mask::integer().
setModEventMask(#wx_ref{type=ThisT,ref=ThisRef},Mask)
when is_integer(Mask) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetModEventMask,
<<ThisRef:32/?UI,Mask:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetedgecolumn">external documentation</a>.
+-spec getEdgeColumn(This) -> integer() when
+ This::wxStyledTextCtrl().
getEdgeColumn(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetEdgeColumn,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Column::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetedgecolumn">external documentation</a>.
+-spec setEdgeColumn(This, Column) -> ok when
+ This::wxStyledTextCtrl(), Column::integer().
setEdgeColumn(#wx_ref{type=ThisT,ref=ThisRef},Column)
when is_integer(Column) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetEdgeColumn,
<<ThisRef:32/?UI,Column:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetedgemode">external documentation</a>.
+-spec setEdgeMode(This, Mode) -> ok when
+ This::wxStyledTextCtrl(), Mode::integer().
+setEdgeMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
+ when is_integer(Mode) ->
+ ?CLASS(ThisT,wxStyledTextCtrl),
+ wxe_util:cast(?wxStyledTextCtrl_SetEdgeMode,
+ <<ThisRef:32/?UI,Mode:32/?UI>>).
+
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetedgemode">external documentation</a>.
+-spec getEdgeMode(This) -> integer() when
+ This::wxStyledTextCtrl().
getEdgeMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetEdgeMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetedgecolour">external documentation</a>.
+-spec getEdgeColour(This) -> wx:wx_colour4() when
+ This::wxStyledTextCtrl().
getEdgeColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetEdgeColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), EdgeColour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetedgecolour">external documentation</a>.
+-spec setEdgeColour(This, EdgeColour) -> ok when
+ This::wxStyledTextCtrl(), EdgeColour::wx:wx_colour().
setEdgeColour(#wx_ref{type=ThisT,ref=ThisRef},EdgeColour)
when tuple_size(EdgeColour) =:= 3; tuple_size(EdgeColour) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetEdgeColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(EdgeColour)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsearchanchor">external documentation</a>.
+-spec searchAnchor(This) -> ok when
+ This::wxStyledTextCtrl().
searchAnchor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SearchAnchor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Flags::integer(), Text::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsearchnext">external documentation</a>.
+-spec searchNext(This, Flags, Text) -> integer() when
+ This::wxStyledTextCtrl(), Flags::integer(), Text::unicode:chardata().
searchNext(#wx_ref{type=ThisT,ref=ThisRef},Flags,Text)
when is_integer(Flags),is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -2723,8 +3078,9 @@ searchNext(#wx_ref{type=ThisT,ref=ThisRef},Flags,Text)
wxe_util:call(?wxStyledTextCtrl_SearchNext,
<<ThisRef:32/?UI,Flags:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Flags::integer(), Text::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsearchprev">external documentation</a>.
+-spec searchPrev(This, Flags, Text) -> integer() when
+ This::wxStyledTextCtrl(), Flags::integer(), Text::unicode:chardata().
searchPrev(#wx_ref{type=ThisT,ref=ThisRef},Flags,Text)
when is_integer(Flags),is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -2732,291 +3088,330 @@ searchPrev(#wx_ref{type=ThisT,ref=ThisRef},Flags,Text)
wxe_util:call(?wxStyledTextCtrl_SearchPrev,
<<ThisRef:32/?UI,Flags:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinesonscreen">external documentation</a>.
+-spec linesOnScreen(This) -> integer() when
+ This::wxStyledTextCtrl().
linesOnScreen(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_LinesOnScreen,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), AllowPopUp::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlusepopup">external documentation</a>.
+-spec usePopUp(This, AllowPopUp) -> ok when
+ This::wxStyledTextCtrl(), AllowPopUp::boolean().
usePopUp(#wx_ref{type=ThisT,ref=ThisRef},AllowPopUp)
when is_boolean(AllowPopUp) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_UsePopUp,
<<ThisRef:32/?UI,(wxe_util:from_bool(AllowPopUp)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlselectionisrectangle">external documentation</a>.
+-spec selectionIsRectangle(This) -> boolean() when
+ This::wxStyledTextCtrl().
selectionIsRectangle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_SelectionIsRectangle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Zoom::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetzoom">external documentation</a>.
+-spec setZoom(This, Zoom) -> ok when
+ This::wxStyledTextCtrl(), Zoom::integer().
setZoom(#wx_ref{type=ThisT,ref=ThisRef},Zoom)
when is_integer(Zoom) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetZoom,
<<ThisRef:32/?UI,Zoom:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetzoom">external documentation</a>.
+-spec getZoom(This) -> integer() when
+ This::wxStyledTextCtrl().
getZoom(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetZoom,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmodeventmask">external documentation</a>.
+-spec getModEventMask(This) -> integer() when
+ This::wxStyledTextCtrl().
getModEventMask(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetModEventMask,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Focus::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetstcfocus">external documentation</a>.
+-spec setSTCFocus(This, Focus) -> ok when
+ This::wxStyledTextCtrl(), Focus::boolean().
setSTCFocus(#wx_ref{type=ThisT,ref=ThisRef},Focus)
when is_boolean(Focus) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSTCFocus,
<<ThisRef:32/?UI,(wxe_util:from_bool(Focus)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstcfocus">external documentation</a>.
+-spec getSTCFocus(This) -> boolean() when
+ This::wxStyledTextCtrl().
getSTCFocus(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSTCFocus,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), StatusCode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetstatus">external documentation</a>.
+-spec setStatus(This, StatusCode) -> ok when
+ This::wxStyledTextCtrl(), StatusCode::integer().
setStatus(#wx_ref{type=ThisT,ref=ThisRef},StatusCode)
when is_integer(StatusCode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetStatus,
<<ThisRef:32/?UI,StatusCode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstatus">external documentation</a>.
+-spec getStatus(This) -> integer() when
+ This::wxStyledTextCtrl().
getStatus(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetStatus,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Captures::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmousedowncaptures">external documentation</a>.
+-spec setMouseDownCaptures(This, Captures) -> ok when
+ This::wxStyledTextCtrl(), Captures::boolean().
setMouseDownCaptures(#wx_ref{type=ThisT,ref=ThisRef},Captures)
when is_boolean(Captures) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMouseDownCaptures,
<<ThisRef:32/?UI,(wxe_util:from_bool(Captures)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetmousedowncaptures">external documentation</a>.
+-spec getMouseDownCaptures(This) -> boolean() when
+ This::wxStyledTextCtrl().
getMouseDownCaptures(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetMouseDownCaptures,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CursorType::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetstccursor">external documentation</a>.
+-spec setSTCCursor(This, CursorType) -> ok when
+ This::wxStyledTextCtrl(), CursorType::integer().
setSTCCursor(#wx_ref{type=ThisT,ref=ThisRef},CursorType)
when is_integer(CursorType) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSTCCursor,
<<ThisRef:32/?UI,CursorType:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstccursor">external documentation</a>.
+-spec getSTCCursor(This) -> integer() when
+ This::wxStyledTextCtrl().
getSTCCursor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSTCCursor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Symbol::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcontrolcharsymbol">external documentation</a>.
+-spec setControlCharSymbol(This, Symbol) -> ok when
+ This::wxStyledTextCtrl(), Symbol::integer().
setControlCharSymbol(#wx_ref{type=ThisT,ref=ThisRef},Symbol)
when is_integer(Symbol) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetControlCharSymbol,
<<ThisRef:32/?UI,Symbol:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcontrolcharsymbol">external documentation</a>.
+-spec getControlCharSymbol(This) -> integer() when
+ This::wxStyledTextCtrl().
getControlCharSymbol(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetControlCharSymbol,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordpartleft">external documentation</a>.
+-spec wordPartLeft(This) -> ok when
+ This::wxStyledTextCtrl().
wordPartLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordPartLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordpartleftextend">external documentation</a>.
+-spec wordPartLeftExtend(This) -> ok when
+ This::wxStyledTextCtrl().
wordPartLeftExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordPartLeftExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordpartright">external documentation</a>.
+-spec wordPartRight(This) -> ok when
+ This::wxStyledTextCtrl().
wordPartRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordPartRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordpartrightextend">external documentation</a>.
+-spec wordPartRightExtend(This) -> ok when
+ This::wxStyledTextCtrl().
wordPartRightExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordPartRightExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), VisiblePolicy::integer(), VisibleSlop::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetvisiblepolicy">external documentation</a>.
+-spec setVisiblePolicy(This, VisiblePolicy, VisibleSlop) -> ok when
+ This::wxStyledTextCtrl(), VisiblePolicy::integer(), VisibleSlop::integer().
setVisiblePolicy(#wx_ref{type=ThisT,ref=ThisRef},VisiblePolicy,VisibleSlop)
when is_integer(VisiblePolicy),is_integer(VisibleSlop) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetVisiblePolicy,
<<ThisRef:32/?UI,VisiblePolicy:32/?UI,VisibleSlop:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldellineleft">external documentation</a>.
+-spec delLineLeft(This) -> ok when
+ This::wxStyledTextCtrl().
delLineLeft(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DelLineLeft,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldellineright">external documentation</a>.
+-spec delLineRight(This) -> ok when
+ This::wxStyledTextCtrl().
delLineRight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_DelLineRight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetxoffset">external documentation</a>.
+-spec getXOffset(This) -> integer() when
+ This::wxStyledTextCtrl().
getXOffset(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetXOffset,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlchoosecaretx">external documentation</a>.
+-spec chooseCaretX(This) -> ok when
+ This::wxStyledTextCtrl().
chooseCaretX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ChooseCaretX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CaretPolicy::integer(), CaretSlop::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetxcaretpolicy">external documentation</a>.
+-spec setXCaretPolicy(This, CaretPolicy, CaretSlop) -> ok when
+ This::wxStyledTextCtrl(), CaretPolicy::integer(), CaretSlop::integer().
setXCaretPolicy(#wx_ref{type=ThisT,ref=ThisRef},CaretPolicy,CaretSlop)
when is_integer(CaretPolicy),is_integer(CaretSlop) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetXCaretPolicy,
<<ThisRef:32/?UI,CaretPolicy:32/?UI,CaretSlop:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), CaretPolicy::integer(), CaretSlop::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetycaretpolicy">external documentation</a>.
+-spec setYCaretPolicy(This, CaretPolicy, CaretSlop) -> ok when
+ This::wxStyledTextCtrl(), CaretPolicy::integer(), CaretSlop::integer().
setYCaretPolicy(#wx_ref{type=ThisT,ref=ThisRef},CaretPolicy,CaretSlop)
when is_integer(CaretPolicy),is_integer(CaretSlop) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetYCaretPolicy,
<<ThisRef:32/?UI,CaretPolicy:32/?UI,CaretSlop:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetprintwrapmode">external documentation</a>.
+-spec getPrintWrapMode(This) -> integer() when
+ This::wxStyledTextCtrl().
getPrintWrapMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetPrintWrapMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Fore::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsethotspotactiveforeground">external documentation</a>.
+-spec setHotspotActiveForeground(This, UseSetting, Fore) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Fore::wx:wx_colour().
setHotspotActiveForeground(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Fore)
when is_boolean(UseSetting),tuple_size(Fore) =:= 3; tuple_size(Fore) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetHotspotActiveForeground,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Fore)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), UseSetting::bool(), Back::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsethotspotactivebackground">external documentation</a>.
+-spec setHotspotActiveBackground(This, UseSetting, Back) -> ok when
+ This::wxStyledTextCtrl(), UseSetting::boolean(), Back::wx:wx_colour().
setHotspotActiveBackground(#wx_ref{type=ThisT,ref=ThisRef},UseSetting,Back)
when is_boolean(UseSetting),tuple_size(Back) =:= 3; tuple_size(Back) =:= 4 ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetHotspotActiveBackground,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseSetting)):32/?UI,(wxe_util:colour_bin(Back)):16/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Underline::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsethotspotactiveunderline">external documentation</a>.
+-spec setHotspotActiveUnderline(This, Underline) -> ok when
+ This::wxStyledTextCtrl(), Underline::boolean().
setHotspotActiveUnderline(#wx_ref{type=ThisT,ref=ThisRef},Underline)
when is_boolean(Underline) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetHotspotActiveUnderline,
<<ThisRef:32/?UI,(wxe_util:from_bool(Underline)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), SingleLine::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsethotspotsingleline">external documentation</a>.
+-spec setHotspotSingleLine(This, SingleLine) -> ok when
+ This::wxStyledTextCtrl(), SingleLine::boolean().
setHotspotSingleLine(#wx_ref{type=ThisT,ref=ThisRef},SingleLine)
when is_boolean(SingleLine) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetHotspotSingleLine,
<<ThisRef:32/?UI,(wxe_util:from_bool(SingleLine)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlparadownextend">external documentation</a>.
+-spec paraDownExtend(This) -> ok when
+ This::wxStyledTextCtrl().
paraDownExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ParaDownExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlparaup">external documentation</a>.
+-spec paraUp(This) -> ok when
+ This::wxStyledTextCtrl().
paraUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ParaUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlparaupextend">external documentation</a>.
+-spec paraUpExtend(This) -> ok when
+ This::wxStyledTextCtrl().
paraUpExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ParaUpExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpositionbefore">external documentation</a>.
+-spec positionBefore(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
positionBefore(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_PositionBefore,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpositionafter">external documentation</a>.
+-spec positionAfter(This, Pos) -> integer() when
+ This::wxStyledTextCtrl(), Pos::integer().
positionAfter(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_PositionAfter,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Start::integer(), End::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcopyrange">external documentation</a>.
+-spec copyRange(This, Start, End) -> ok when
+ This::wxStyledTextCtrl(), Start::integer(), End::integer().
copyRange(#wx_ref{type=ThisT,ref=ThisRef},Start,End)
when is_integer(Start),is_integer(End) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CopyRange,
<<ThisRef:32/?UI,Start:32/?UI,End:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Length::integer(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcopytext">external documentation</a>.
+-spec copyText(This, Length, Text) -> ok when
+ This::wxStyledTextCtrl(), Length::integer(), Text::unicode:chardata().
copyText(#wx_ref{type=ThisT,ref=ThisRef},Length,Text)
when is_integer(Length),is_list(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3024,142 +3419,162 @@ copyText(#wx_ref{type=ThisT,ref=ThisRef},Length,Text)
wxe_util:cast(?wxStyledTextCtrl_CopyText,
<<ThisRef:32/?UI,Length:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Mode::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetselectionmode">external documentation</a>.
+-spec setSelectionMode(This, Mode) -> ok when
+ This::wxStyledTextCtrl(), Mode::integer().
setSelectionMode(#wx_ref{type=ThisT,ref=ThisRef},Mode)
when is_integer(Mode) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetSelectionMode,
<<ThisRef:32/?UI,Mode:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselectionmode">external documentation</a>.
+-spec getSelectionMode(This) -> integer() when
+ This::wxStyledTextCtrl().
getSelectionMode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelectionMode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllinedownrectextend">external documentation</a>.
+-spec lineDownRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineDownRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineDownRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineuprectextend">external documentation</a>.
+-spec lineUpRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineUpRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineUpRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcharleftrectextend">external documentation</a>.
+-spec charLeftRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
charLeftRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CharLeftRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcharrightrectextend">external documentation</a>.
+-spec charRightRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
charRightRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CharRightRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlhomerectextend">external documentation</a>.
+-spec homeRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
homeRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_HomeRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlvchomerectextend">external documentation</a>.
+-spec vCHomeRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
vCHomeRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_VCHomeRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrllineendrectextend">external documentation</a>.
+-spec lineEndRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
lineEndRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_LineEndRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpageuprectextend">external documentation</a>.
+-spec pageUpRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
pageUpRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_PageUpRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpagedownrectextend">external documentation</a>.
+-spec pageDownRectExtend(This) -> ok when
+ This::wxStyledTextCtrl().
pageDownRectExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_PageDownRectExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstutteredpageup">external documentation</a>.
+-spec stutteredPageUp(This) -> ok when
+ This::wxStyledTextCtrl().
stutteredPageUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StutteredPageUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstutteredpageupextend">external documentation</a>.
+-spec stutteredPageUpExtend(This) -> ok when
+ This::wxStyledTextCtrl().
stutteredPageUpExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StutteredPageUpExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstutteredpagedown">external documentation</a>.
+-spec stutteredPageDown(This) -> ok when
+ This::wxStyledTextCtrl().
stutteredPageDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StutteredPageDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstutteredpagedownextend">external documentation</a>.
+-spec stutteredPageDownExtend(This) -> ok when
+ This::wxStyledTextCtrl().
stutteredPageDownExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StutteredPageDownExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordleftend">external documentation</a>.
+-spec wordLeftEnd(This) -> ok when
+ This::wxStyledTextCtrl().
wordLeftEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordLeftEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordleftendextend">external documentation</a>.
+-spec wordLeftEndExtend(This) -> ok when
+ This::wxStyledTextCtrl().
wordLeftEndExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordLeftEndExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordrightend">external documentation</a>.
+-spec wordRightEnd(This) -> ok when
+ This::wxStyledTextCtrl().
wordRightEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordRightEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlwordrightendextend">external documentation</a>.
+-spec wordRightEndExtend(This) -> ok when
+ This::wxStyledTextCtrl().
wordRightEndExtend(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_WordRightEndExtend,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Characters::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetwhitespacechars">external documentation</a>.
+-spec setWhitespaceChars(This, Characters) -> ok when
+ This::wxStyledTextCtrl(), Characters::unicode:chardata().
setWhitespaceChars(#wx_ref{type=ThisT,ref=ThisRef},Characters)
when is_list(Characters) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3167,134 +3582,152 @@ setWhitespaceChars(#wx_ref{type=ThisT,ref=ThisRef},Characters)
wxe_util:cast(?wxStyledTextCtrl_SetWhitespaceChars,
<<ThisRef:32/?UI,(byte_size(Characters_UC)):32/?UI,(Characters_UC)/binary, 0:(((8- ((0+byte_size(Characters_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcharsdefault">external documentation</a>.
+-spec setCharsDefault(This) -> ok when
+ This::wxStyledTextCtrl().
setCharsDefault(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCharsDefault,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlautocompgetcurrent">external documentation</a>.
+-spec autoCompGetCurrent(This) -> integer() when
+ This::wxStyledTextCtrl().
autoCompGetCurrent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_AutoCompGetCurrent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Bytes::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlallocate">external documentation</a>.
+-spec allocate(This, Bytes) -> ok when
+ This::wxStyledTextCtrl(), Bytes::integer().
allocate(#wx_ref{type=ThisT,ref=ThisRef},Bytes)
when is_integer(Bytes) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Allocate,
<<ThisRef:32/?UI,Bytes:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer(), Column::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlfindcolumn">external documentation</a>.
+-spec findColumn(This, Line, Column) -> integer() when
+ This::wxStyledTextCtrl(), Line::integer(), Column::integer().
findColumn(#wx_ref{type=ThisT,ref=ThisRef},Line,Column)
when is_integer(Line),is_integer(Column) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_FindColumn,
<<ThisRef:32/?UI,Line:32/?UI,Column:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretsticky">external documentation</a>.
+-spec getCaretSticky(This) -> boolean() when
+ This::wxStyledTextCtrl().
getCaretSticky(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretSticky,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), UseCaretStickyBehaviour::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretsticky">external documentation</a>.
+-spec setCaretSticky(This, UseCaretStickyBehaviour) -> ok when
+ This::wxStyledTextCtrl(), UseCaretStickyBehaviour::boolean().
setCaretSticky(#wx_ref{type=ThisT,ref=ThisRef},UseCaretStickyBehaviour)
when is_boolean(UseCaretStickyBehaviour) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretSticky,
<<ThisRef:32/?UI,(wxe_util:from_bool(UseCaretStickyBehaviour)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrltogglecaretsticky">external documentation</a>.
+-spec toggleCaretSticky(This) -> ok when
+ This::wxStyledTextCtrl().
toggleCaretSticky(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ToggleCaretSticky,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Convert::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetpasteconvertendings">external documentation</a>.
+-spec setPasteConvertEndings(This, Convert) -> ok when
+ This::wxStyledTextCtrl(), Convert::boolean().
setPasteConvertEndings(#wx_ref{type=ThisT,ref=ThisRef},Convert)
when is_boolean(Convert) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetPasteConvertEndings,
<<ThisRef:32/?UI,(wxe_util:from_bool(Convert)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetpasteconvertendings">external documentation</a>.
+-spec getPasteConvertEndings(This) -> boolean() when
+ This::wxStyledTextCtrl().
getPasteConvertEndings(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetPasteConvertEndings,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlselectionduplicate">external documentation</a>.
+-spec selectionDuplicate(This) -> ok when
+ This::wxStyledTextCtrl().
selectionDuplicate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SelectionDuplicate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Alpha::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetcaretlinebackalpha">external documentation</a>.
+-spec setCaretLineBackAlpha(This, Alpha) -> ok when
+ This::wxStyledTextCtrl(), Alpha::integer().
setCaretLineBackAlpha(#wx_ref{type=ThisT,ref=ThisRef},Alpha)
when is_integer(Alpha) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetCaretLineBackAlpha,
<<ThisRef:32/?UI,Alpha:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcaretlinebackalpha">external documentation</a>.
+-spec getCaretLineBackAlpha(This) -> integer() when
+ This::wxStyledTextCtrl().
getCaretLineBackAlpha(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCaretLineBackAlpha,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstartrecord">external documentation</a>.
+-spec startRecord(This) -> ok when
+ This::wxStyledTextCtrl().
startRecord(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StartRecord,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstoprecord">external documentation</a>.
+-spec stopRecord(This) -> ok when
+ This::wxStyledTextCtrl().
stopRecord(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StopRecord,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Lexer::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetlexer">external documentation</a>.
+-spec setLexer(This, Lexer) -> ok when
+ This::wxStyledTextCtrl(), Lexer::integer().
setLexer(#wx_ref{type=ThisT,ref=ThisRef},Lexer)
when is_integer(Lexer) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetLexer,
<<ThisRef:32/?UI,Lexer:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlexer">external documentation</a>.
+-spec getLexer(This) -> integer() when
+ This::wxStyledTextCtrl().
getLexer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLexer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Start::integer(), End::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcolourise">external documentation</a>.
+-spec colourise(This, Start, End) -> ok when
+ This::wxStyledTextCtrl(), Start::integer(), End::integer().
colourise(#wx_ref{type=ThisT,ref=ThisRef},Start,End)
when is_integer(Start),is_integer(End) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_Colourise,
<<ThisRef:32/?UI,Start:32/?UI,End:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Key::string(), Value::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetproperty">external documentation</a>.
+-spec setProperty(This, Key, Value) -> ok when
+ This::wxStyledTextCtrl(), Key::unicode:chardata(), Value::unicode:chardata().
setProperty(#wx_ref{type=ThisT,ref=ThisRef},Key,Value)
when is_list(Key),is_list(Value) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3303,8 +3736,9 @@ setProperty(#wx_ref{type=ThisT,ref=ThisRef},Key,Value)
wxe_util:cast(?wxStyledTextCtrl_SetProperty,
<<ThisRef:32/?UI,(byte_size(Key_UC)):32/?UI,(Key_UC)/binary, 0:(((8- ((0+byte_size(Key_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((4+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), KeywordSet::integer(), KeyWords::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetkeywords">external documentation</a>.
+-spec setKeyWords(This, KeywordSet, KeyWords) -> ok when
+ This::wxStyledTextCtrl(), KeywordSet::integer(), KeyWords::unicode:chardata().
setKeyWords(#wx_ref{type=ThisT,ref=ThisRef},KeywordSet,KeyWords)
when is_integer(KeywordSet),is_list(KeyWords) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3312,8 +3746,9 @@ setKeyWords(#wx_ref{type=ThisT,ref=ThisRef},KeywordSet,KeyWords)
wxe_util:cast(?wxStyledTextCtrl_SetKeyWords,
<<ThisRef:32/?UI,KeywordSet:32/?UI,(byte_size(KeyWords_UC)):32/?UI,(KeyWords_UC)/binary, 0:(((8- ((4+byte_size(KeyWords_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Language::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetlexerlanguage">external documentation</a>.
+-spec setLexerLanguage(This, Language) -> ok when
+ This::wxStyledTextCtrl(), Language::unicode:chardata().
setLexerLanguage(#wx_ref{type=ThisT,ref=ThisRef},Language)
when is_list(Language) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3321,8 +3756,9 @@ setLexerLanguage(#wx_ref{type=ThisT,ref=ThisRef},Language)
wxe_util:cast(?wxStyledTextCtrl_SetLexerLanguage,
<<ThisRef:32/?UI,(byte_size(Language_UC)):32/?UI,(Language_UC)/binary, 0:(((8- ((0+byte_size(Language_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Key::string()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetproperty">external documentation</a>.
+-spec getProperty(This, Key) -> unicode:charlist() when
+ This::wxStyledTextCtrl(), Key::unicode:chardata().
getProperty(#wx_ref{type=ThisT,ref=ThisRef},Key)
when is_list(Key) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3330,22 +3766,25 @@ getProperty(#wx_ref{type=ThisT,ref=ThisRef},Key)
wxe_util:call(?wxStyledTextCtrl_GetProperty,
<<ThisRef:32/?UI,(byte_size(Key_UC)):32/?UI,(Key_UC)/binary, 0:(((8- ((0+byte_size(Key_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetstylebitsneeded">external documentation</a>.
+-spec getStyleBitsNeeded(This) -> integer() when
+ This::wxStyledTextCtrl().
getStyleBitsNeeded(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetStyleBitsNeeded,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcurrentline">external documentation</a>.
+-spec getCurrentLine(This) -> integer() when
+ This::wxStyledTextCtrl().
getCurrentLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCurrentLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), StyleNum::integer(), Spec::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetspec">external documentation</a>.
+-spec styleSetSpec(This, StyleNum, Spec) -> ok when
+ This::wxStyledTextCtrl(), StyleNum::integer(), Spec::unicode:chardata().
styleSetSpec(#wx_ref{type=ThisT,ref=ThisRef},StyleNum,Spec)
when is_integer(StyleNum),is_list(Spec) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3353,8 +3792,9 @@ styleSetSpec(#wx_ref{type=ThisT,ref=ThisRef},StyleNum,Spec)
wxe_util:cast(?wxStyledTextCtrl_StyleSetSpec,
<<ThisRef:32/?UI,StyleNum:32/?UI,(byte_size(Spec_UC)):32/?UI,(Spec_UC)/binary, 0:(((8- ((4+byte_size(Spec_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), StyleNum::integer(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetfont">external documentation</a>.
+-spec styleSetFont(This, StyleNum, Font) -> ok when
+ This::wxStyledTextCtrl(), StyleNum::integer(), Font::wxFont:wxFont().
styleSetFont(#wx_ref{type=ThisT,ref=ThisRef},StyleNum,#wx_ref{type=FontT,ref=FontRef})
when is_integer(StyleNum) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3362,17 +3802,19 @@ styleSetFont(#wx_ref{type=ThisT,ref=ThisRef},StyleNum,#wx_ref{type=FontT,ref=Fon
wxe_util:cast(?wxStyledTextCtrl_StyleSetFont,
<<ThisRef:32/?UI,StyleNum:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), StyleNum::integer(), Size::integer(), FaceName::string(), Bold::bool(), Italic::bool(), Underline::bool()) -> ok
%% @equiv styleSetFontAttr(This,StyleNum,Size,FaceName,Bold,Italic,Underline, [])
+-spec styleSetFontAttr(This, StyleNum, Size, FaceName, Bold, Italic, Underline) -> ok when
+ This::wxStyledTextCtrl(), StyleNum::integer(), Size::integer(), FaceName::unicode:chardata(), Bold::boolean(), Italic::boolean(), Underline::boolean().
+
styleSetFontAttr(This,StyleNum,Size,FaceName,Bold,Italic,Underline)
when is_record(This, wx_ref),is_integer(StyleNum),is_integer(Size),is_list(FaceName),is_boolean(Bold),is_boolean(Italic),is_boolean(Underline) ->
styleSetFontAttr(This,StyleNum,Size,FaceName,Bold,Italic,Underline, []).
-%% @spec (This::wxStyledTextCtrl(), StyleNum::integer(), Size::integer(), FaceName::string(), Bold::bool(), Italic::bool(), Underline::bool(), [Option]) -> ok
-%% Option = {encoding, WxFontEncoding}
-%% WxFontEncoding = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetfontattr">external documentation</a>.
-%%<br /> WxFontEncoding is one of ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+%%<br /> Encoding = ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+-spec styleSetFontAttr(This, StyleNum, Size, FaceName, Bold, Italic, Underline, [Option]) -> ok when
+ This::wxStyledTextCtrl(), StyleNum::integer(), Size::integer(), FaceName::unicode:chardata(), Bold::boolean(), Italic::boolean(), Underline::boolean(),
+ Option :: {encoding, wx:wx_enum()}.
styleSetFontAttr(#wx_ref{type=ThisT,ref=ThisRef},StyleNum,Size,FaceName,Bold,Italic,Underline, Options)
when is_integer(StyleNum),is_integer(Size),is_list(FaceName),is_boolean(Bold),is_boolean(Italic),is_boolean(Underline),is_list(Options) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3383,80 +3825,91 @@ styleSetFontAttr(#wx_ref{type=ThisT,ref=ThisRef},StyleNum,Size,FaceName,Bold,Ita
wxe_util:cast(?wxStyledTextCtrl_StyleSetFontAttr,
<<ThisRef:32/?UI,StyleNum:32/?UI,Size:32/?UI,(byte_size(FaceName_UC)):32/?UI,(FaceName_UC)/binary, 0:(((8- ((0+byte_size(FaceName_UC)) band 16#7)) band 16#7))/unit:8,(wxe_util:from_bool(Bold)):32/?UI,(wxe_util:from_bool(Italic)):32/?UI,(wxe_util:from_bool(Underline)):32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), CharacterSet::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetcharacterset">external documentation</a>.
+-spec styleSetCharacterSet(This, Style, CharacterSet) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), CharacterSet::integer().
styleSetCharacterSet(#wx_ref{type=ThisT,ref=ThisRef},Style,CharacterSet)
when is_integer(Style),is_integer(CharacterSet) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetCharacterSet,
<<ThisRef:32/?UI,Style:32/?UI,CharacterSet:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Style::integer(), Encoding::WxFontEncoding) -> ok
-%% WxFontEncoding = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlstylesetfontencoding">external documentation</a>.
-%%<br /> WxFontEncoding is one of ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+%%<br /> Encoding = ?wxFONTENCODING_SYSTEM | ?wxFONTENCODING_DEFAULT | ?wxFONTENCODING_ISO8859_1 | ?wxFONTENCODING_ISO8859_2 | ?wxFONTENCODING_ISO8859_3 | ?wxFONTENCODING_ISO8859_4 | ?wxFONTENCODING_ISO8859_5 | ?wxFONTENCODING_ISO8859_6 | ?wxFONTENCODING_ISO8859_7 | ?wxFONTENCODING_ISO8859_8 | ?wxFONTENCODING_ISO8859_9 | ?wxFONTENCODING_ISO8859_10 | ?wxFONTENCODING_ISO8859_11 | ?wxFONTENCODING_ISO8859_12 | ?wxFONTENCODING_ISO8859_13 | ?wxFONTENCODING_ISO8859_14 | ?wxFONTENCODING_ISO8859_15 | ?wxFONTENCODING_ISO8859_MAX | ?wxFONTENCODING_KOI8 | ?wxFONTENCODING_KOI8_U | ?wxFONTENCODING_ALTERNATIVE | ?wxFONTENCODING_BULGARIAN | ?wxFONTENCODING_CP437 | ?wxFONTENCODING_CP850 | ?wxFONTENCODING_CP852 | ?wxFONTENCODING_CP855 | ?wxFONTENCODING_CP866 | ?wxFONTENCODING_CP874 | ?wxFONTENCODING_CP932 | ?wxFONTENCODING_CP936 | ?wxFONTENCODING_CP949 | ?wxFONTENCODING_CP950 | ?wxFONTENCODING_CP1250 | ?wxFONTENCODING_CP1251 | ?wxFONTENCODING_CP1252 | ?wxFONTENCODING_CP1253 | ?wxFONTENCODING_CP1254 | ?wxFONTENCODING_CP1255 | ?wxFONTENCODING_CP1256 | ?wxFONTENCODING_CP1257 | ?wxFONTENCODING_CP12_MAX | ?wxFONTENCODING_UTF7 | ?wxFONTENCODING_UTF8 | ?wxFONTENCODING_EUC_JP | ?wxFONTENCODING_UTF16BE | ?wxFONTENCODING_UTF16LE | ?wxFONTENCODING_UTF32BE | ?wxFONTENCODING_UTF32LE | ?wxFONTENCODING_MACROMAN | ?wxFONTENCODING_MACJAPANESE | ?wxFONTENCODING_MACCHINESETRAD | ?wxFONTENCODING_MACKOREAN | ?wxFONTENCODING_MACARABIC | ?wxFONTENCODING_MACHEBREW | ?wxFONTENCODING_MACGREEK | ?wxFONTENCODING_MACCYRILLIC | ?wxFONTENCODING_MACDEVANAGARI | ?wxFONTENCODING_MACGURMUKHI | ?wxFONTENCODING_MACGUJARATI | ?wxFONTENCODING_MACORIYA | ?wxFONTENCODING_MACBENGALI | ?wxFONTENCODING_MACTAMIL | ?wxFONTENCODING_MACTELUGU | ?wxFONTENCODING_MACKANNADA | ?wxFONTENCODING_MACMALAJALAM | ?wxFONTENCODING_MACSINHALESE | ?wxFONTENCODING_MACBURMESE | ?wxFONTENCODING_MACKHMER | ?wxFONTENCODING_MACTHAI | ?wxFONTENCODING_MACLAOTIAN | ?wxFONTENCODING_MACGEORGIAN | ?wxFONTENCODING_MACARMENIAN | ?wxFONTENCODING_MACCHINESESIMP | ?wxFONTENCODING_MACTIBETAN | ?wxFONTENCODING_MACMONGOLIAN | ?wxFONTENCODING_MACETHIOPIC | ?wxFONTENCODING_MACCENTRALEUR | ?wxFONTENCODING_MACVIATNAMESE | ?wxFONTENCODING_MACARABICEXT | ?wxFONTENCODING_MACSYMBOL | ?wxFONTENCODING_MACDINGBATS | ?wxFONTENCODING_MACTURKISH | ?wxFONTENCODING_MACCROATIAN | ?wxFONTENCODING_MACICELANDIC | ?wxFONTENCODING_MACROMANIAN | ?wxFONTENCODING_MACCELTIC | ?wxFONTENCODING_MACGAELIC | ?wxFONTENCODING_MACKEYBOARD | ?wxFONTENCODING_MAX | ?wxFONTENCODING_MACMIN | ?wxFONTENCODING_MACMAX | ?wxFONTENCODING_UTF16 | ?wxFONTENCODING_UTF32 | ?wxFONTENCODING_UNICODE | ?wxFONTENCODING_GB2312 | ?wxFONTENCODING_BIG5 | ?wxFONTENCODING_SHIFT_JIS
+-spec styleSetFontEncoding(This, Style, Encoding) -> ok when
+ This::wxStyledTextCtrl(), Style::integer(), Encoding::wx:wx_enum().
styleSetFontEncoding(#wx_ref{type=ThisT,ref=ThisRef},Style,Encoding)
when is_integer(Style),is_integer(Encoding) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_StyleSetFontEncoding,
<<ThisRef:32/?UI,Style:32/?UI,Encoding:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Cmd::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlcmdkeyexecute">external documentation</a>.
+-spec cmdKeyExecute(This, Cmd) -> ok when
+ This::wxStyledTextCtrl(), Cmd::integer().
cmdKeyExecute(#wx_ref{type=ThisT,ref=ThisRef},Cmd)
when is_integer(Cmd) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_CmdKeyExecute,
<<ThisRef:32/?UI,Cmd:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Left::integer(), Right::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetmargins">external documentation</a>.
+-spec setMargins(This, Left, Right) -> ok when
+ This::wxStyledTextCtrl(), Left::integer(), Right::integer().
setMargins(#wx_ref{type=ThisT,ref=ThisRef},Left,Right)
when is_integer(Left),is_integer(Right) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetMargins,
<<ThisRef:32/?UI,Left:32/?UI,Right:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> {StartPos::integer(),EndPos::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselection">external documentation</a>.
+-spec getSelection(This) -> {StartPos::integer(), EndPos::integer()} when
+ This::wxStyledTextCtrl().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlpointfromposition">external documentation</a>.
+-spec pointFromPosition(This, Pos) -> {X::integer(), Y::integer()} when
+ This::wxStyledTextCtrl(), Pos::integer().
pointFromPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_PointFromPosition,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlscrolltoline">external documentation</a>.
+-spec scrollToLine(This, Line) -> ok when
+ This::wxStyledTextCtrl(), Line::integer().
scrollToLine(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ScrollToLine,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Column::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlscrolltocolumn">external documentation</a>.
+-spec scrollToColumn(This, Column) -> ok when
+ This::wxStyledTextCtrl(), Column::integer().
scrollToColumn(#wx_ref{type=ThisT,ref=ThisRef},Column)
when is_integer(Column) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_ScrollToColumn,
<<ThisRef:32/?UI,Column:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Msg::integer()) -> integer()
%% @equiv sendMsg(This,Msg, [])
+-spec sendMsg(This, Msg) -> integer() when
+ This::wxStyledTextCtrl(), Msg::integer().
+
sendMsg(This,Msg)
when is_record(This, wx_ref),is_integer(Msg) ->
sendMsg(This,Msg, []).
-%% @spec (This::wxStyledTextCtrl(), Msg::integer(), [Option]) -> integer()
-%% Option = {wp, integer()} | {lp, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsendmsg">external documentation</a>.
+-spec sendMsg(This, Msg, [Option]) -> integer() when
+ This::wxStyledTextCtrl(), Msg::integer(),
+ Option :: {wp, integer()}
+ | {lp, integer()}.
sendMsg(#wx_ref{type=ThisT,ref=ThisRef},Msg, Options)
when is_integer(Msg),is_list(Options) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3467,39 +3920,44 @@ sendMsg(#wx_ref{type=ThisT,ref=ThisRef},Msg, Options)
wxe_util:call(?wxStyledTextCtrl_SendMsg,
<<ThisRef:32/?UI,Msg:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxStyledTextCtrl(), Bar::wxScrollBar:wxScrollBar()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetvscrollbar">external documentation</a>.
+-spec setVScrollBar(This, Bar) -> ok when
+ This::wxStyledTextCtrl(), Bar::wxScrollBar:wxScrollBar().
setVScrollBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BarT,ref=BarRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
?CLASS(BarT,wxScrollBar),
wxe_util:cast(?wxStyledTextCtrl_SetVScrollBar,
<<ThisRef:32/?UI,BarRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Bar::wxScrollBar:wxScrollBar()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsethscrollbar">external documentation</a>.
+-spec setHScrollBar(This, Bar) -> ok when
+ This::wxStyledTextCtrl(), Bar::wxScrollBar:wxScrollBar().
setHScrollBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=BarT,ref=BarRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
?CLASS(BarT,wxScrollBar),
wxe_util:cast(?wxStyledTextCtrl_SetHScrollBar,
<<ThisRef:32/?UI,BarRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlastkeydownprocessed">external documentation</a>.
+-spec getLastKeydownProcessed(This) -> boolean() when
+ This::wxStyledTextCtrl().
getLastKeydownProcessed(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLastKeydownProcessed,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Val::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsetlastkeydownprocessed">external documentation</a>.
+-spec setLastKeydownProcessed(This, Val) -> ok when
+ This::wxStyledTextCtrl(), Val::boolean().
setLastKeydownProcessed(#wx_ref{type=ThisT,ref=ThisRef},Val)
when is_boolean(Val) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:cast(?wxStyledTextCtrl_SetLastKeydownProcessed,
<<ThisRef:32/?UI,(wxe_util:from_bool(Val)):32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Filename::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsavefile">external documentation</a>.
+-spec saveFile(This, Filename) -> boolean() when
+ This::wxStyledTextCtrl(), Filename::unicode:chardata().
saveFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
when is_list(Filename) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3507,8 +3965,9 @@ saveFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
wxe_util:call(?wxStyledTextCtrl_SaveFile,
<<ThisRef:32/?UI,(byte_size(Filename_UC)):32/?UI,(Filename_UC)/binary, 0:(((8- ((0+byte_size(Filename_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), Filename::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlloadfile">external documentation</a>.
+-spec loadFile(This, Filename) -> boolean() when
+ This::wxStyledTextCtrl(), Filename::unicode:chardata().
loadFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
when is_list(Filename) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3516,20 +3975,20 @@ loadFile(#wx_ref{type=ThisT,ref=ThisRef},Filename)
wxe_util:call(?wxStyledTextCtrl_LoadFile,
<<ThisRef:32/?UI,(byte_size(Filename_UC)):32/?UI,(Filename_UC)/binary, 0:(((8- ((0+byte_size(Filename_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl(), X::integer(), Y::integer(), Def::WxDragResult) -> WxDragResult
-%% WxDragResult = integer()
-%% WxDragResult = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldodragover">external documentation</a>.
-%%<br /> WxDragResult is one of ?wxDragError | ?wxDragNone | ?wxDragCopy | ?wxDragMove | ?wxDragLink | ?wxDragCancel
-%%<br /> WxDragResult is one of ?wxDragError | ?wxDragNone | ?wxDragCopy | ?wxDragMove | ?wxDragLink | ?wxDragCancel
+%%<br /> Def = ?wxDragError | ?wxDragNone | ?wxDragCopy | ?wxDragMove | ?wxDragLink | ?wxDragCancel
+%%<br /> Res = ?wxDragError | ?wxDragNone | ?wxDragCopy | ?wxDragMove | ?wxDragLink | ?wxDragCancel
+-spec doDragOver(This, X, Y, Def) -> wx:wx_enum() when
+ This::wxStyledTextCtrl(), X::integer(), Y::integer(), Def::wx:wx_enum().
doDragOver(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Def)
when is_integer(X),is_integer(Y),is_integer(Def) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_DoDragOver,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,Def:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), X::integer(), Y::integer(), Data::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrldodroptext">external documentation</a>.
+-spec doDropText(This, X, Y, Data) -> boolean() when
+ This::wxStyledTextCtrl(), X::integer(), Y::integer(), Data::unicode:chardata().
doDropText(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Data)
when is_integer(X),is_integer(Y),is_list(Data) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3537,15 +3996,17 @@ doDropText(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Data)
wxe_util:call(?wxStyledTextCtrl_DoDropText,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,(byte_size(Data_UC)):32/?UI,(Data_UC)/binary, 0:(((8- ((0+byte_size(Data_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxStyledTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetuseantialiasing">external documentation</a>.
+-spec getUseAntiAliasing(This) -> boolean() when
+ This::wxStyledTextCtrl().
getUseAntiAliasing(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetUseAntiAliasing,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::binary()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrladdtextraw">external documentation</a>.
+-spec addTextRaw(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::binary().
addTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_binary(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3553,8 +4014,9 @@ addTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_AddTextRaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Pos::integer(), Text::binary()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlinserttextraw">external documentation</a>.
+-spec insertTextRaw(This, Pos, Text) -> ok when
+ This::wxStyledTextCtrl(), Pos::integer(), Text::binary().
insertTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Pos,Text)
when is_integer(Pos),is_binary(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3562,38 +4024,44 @@ insertTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Pos,Text)
wxe_util:cast(?wxStyledTextCtrl_InsertTextRaw,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> {binary(),LinePos::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetcurlineraw">external documentation</a>.
+-spec getCurLineRaw(This) -> Result when
+ Result ::{Res ::binary(), LinePos::integer()},
+ This::wxStyledTextCtrl().
getCurLineRaw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetCurLineRaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Line::integer()) -> binary()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetlineraw">external documentation</a>.
+-spec getLineRaw(This, Line) -> binary() when
+ This::wxStyledTextCtrl(), Line::integer().
getLineRaw(#wx_ref{type=ThisT,ref=ThisRef},Line)
when is_integer(Line) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetLineRaw,
<<ThisRef:32/?UI,Line:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> binary()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgetselectedtextraw">external documentation</a>.
+-spec getSelectedTextRaw(This) -> binary() when
+ This::wxStyledTextCtrl().
getSelectedTextRaw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetSelectedTextRaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), StartPos::integer(), EndPos::integer()) -> binary()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettextrangeraw">external documentation</a>.
+-spec getTextRangeRaw(This, StartPos, EndPos) -> binary() when
+ This::wxStyledTextCtrl(), StartPos::integer(), EndPos::integer().
getTextRangeRaw(#wx_ref{type=ThisT,ref=ThisRef},StartPos,EndPos)
when is_integer(StartPos),is_integer(EndPos) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTextRangeRaw,
<<ThisRef:32/?UI,StartPos:32/?UI,EndPos:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::binary()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlsettextraw">external documentation</a>.
+-spec setTextRaw(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::binary().
setTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_binary(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3601,15 +4069,17 @@ setTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_SetTextRaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> binary()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlgettextraw">external documentation</a>.
+-spec getTextRaw(This) -> binary() when
+ This::wxStyledTextCtrl().
getTextRaw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextCtrl),
wxe_util:call(?wxStyledTextCtrl_GetTextRaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl(), Text::binary()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextctrl.html#wxstyledtextctrlappendtextraw">external documentation</a>.
+-spec appendTextRaw(This, Text) -> ok when
+ This::wxStyledTextCtrl(), Text::binary().
appendTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_binary(Text) ->
?CLASS(ThisT,wxStyledTextCtrl),
@@ -3617,8 +4087,8 @@ appendTextRaw(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxStyledTextCtrl_AppendTextRaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxStyledTextCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxStyledTextCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxStyledTextEvent.erl b/lib/wx/src/gen/wxStyledTextEvent.erl
index 5d98ae585d..1c2c79fe5d 100644
--- a/lib/wx/src/gen/wxStyledTextEvent.erl
+++ b/lib/wx/src/gen/wxStyledTextEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,169 +44,193 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxStyledTextEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxStyledTextEvent()) -> integer()
+-type wxStyledTextEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetposition">external documentation</a>.
+-spec getPosition(This) -> integer() when
+ This::wxStyledTextEvent().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetkey">external documentation</a>.
+-spec getKey(This) -> integer() when
+ This::wxStyledTextEvent().
getKey(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetKey,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetmodifiers">external documentation</a>.
+-spec getModifiers(This) -> integer() when
+ This::wxStyledTextEvent().
getModifiers(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetModifiers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetmodificationtype">external documentation</a>.
+-spec getModificationType(This) -> integer() when
+ This::wxStyledTextEvent().
getModificationType(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetModificationType,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxStyledTextEvent().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetlength">external documentation</a>.
+-spec getLength(This) -> integer() when
+ This::wxStyledTextEvent().
getLength(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetLength,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetlinesadded">external documentation</a>.
+-spec getLinesAdded(This) -> integer() when
+ This::wxStyledTextEvent().
getLinesAdded(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetLinesAdded,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetline">external documentation</a>.
+-spec getLine(This) -> integer() when
+ This::wxStyledTextEvent().
getLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetfoldlevelnow">external documentation</a>.
+-spec getFoldLevelNow(This) -> integer() when
+ This::wxStyledTextEvent().
getFoldLevelNow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetFoldLevelNow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetfoldlevelprev">external documentation</a>.
+-spec getFoldLevelPrev(This) -> integer() when
+ This::wxStyledTextEvent().
getFoldLevelPrev(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetFoldLevelPrev,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetmargin">external documentation</a>.
+-spec getMargin(This) -> integer() when
+ This::wxStyledTextEvent().
getMargin(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetMargin,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetmessage">external documentation</a>.
+-spec getMessage(This) -> integer() when
+ This::wxStyledTextEvent().
getMessage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetMessage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetwparam">external documentation</a>.
+-spec getWParam(This) -> integer() when
+ This::wxStyledTextEvent().
getWParam(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetWParam,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetlparam">external documentation</a>.
+-spec getLParam(This) -> integer() when
+ This::wxStyledTextEvent().
getLParam(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetLParam,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetlisttype">external documentation</a>.
+-spec getListType(This) -> integer() when
+ This::wxStyledTextEvent().
getListType(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetListType,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetx">external documentation</a>.
+-spec getX(This) -> integer() when
+ This::wxStyledTextEvent().
getX(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetX,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgety">external documentation</a>.
+-spec getY(This) -> integer() when
+ This::wxStyledTextEvent().
getY(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetY,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetdragtext">external documentation</a>.
+-spec getDragText(This) -> unicode:charlist() when
+ This::wxStyledTextEvent().
getDragText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetDragText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetdragallowmove">external documentation</a>.
+-spec getDragAllowMove(This) -> boolean() when
+ This::wxStyledTextEvent().
getDragAllowMove(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetDragAllowMove,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> WxDragResult
-%% WxDragResult = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetdragresult">external documentation</a>.
-%%<br /> WxDragResult is one of ?wxDragError | ?wxDragNone | ?wxDragCopy | ?wxDragMove | ?wxDragLink | ?wxDragCancel
+%%<br /> Res = ?wxDragError | ?wxDragNone | ?wxDragCopy | ?wxDragMove | ?wxDragLink | ?wxDragCancel
+-spec getDragResult(This) -> wx:wx_enum() when
+ This::wxStyledTextEvent().
getDragResult(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetDragResult,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetshift">external documentation</a>.
+-spec getShift(This) -> boolean() when
+ This::wxStyledTextEvent().
getShift(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetShift,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetcontrol">external documentation</a>.
+-spec getControl(This) -> boolean() when
+ This::wxStyledTextEvent().
getControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxStyledTextEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxstyledtextevent.html#wxstyledtexteventgetalt">external documentation</a>.
+-spec getAlt(This) -> boolean() when
+ This::wxStyledTextEvent().
getAlt(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxStyledTextEvent),
wxe_util:call(?wxStyledTextEvent_GetAlt,
diff --git a/lib/wx/src/gen/wxSysColourChangedEvent.erl b/lib/wx/src/gen/wxSysColourChangedEvent.erl
index 0d86edcf5b..94777748d2 100644
--- a/lib/wx/src/gen/wxSysColourChangedEvent.erl
+++ b/lib/wx/src/gen/wxSysColourChangedEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +37,12 @@
-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+-export_type([wxSysColourChangedEvent/0]).
%% @hidden
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxSysColourChangedEvent() :: wx:wx_object().
%% From wxEvent
%% @hidden
stopPropagation(This) -> wxEvent:stopPropagation(This).
diff --git a/lib/wx/src/gen/wxSystemOptions.erl b/lib/wx/src/gen/wxSystemOptions.erl
new file mode 100644
index 0000000000..757eb698a2
--- /dev/null
+++ b/lib/wx/src/gen/wxSystemOptions.erl
@@ -0,0 +1,93 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_wxsystemoptions.html">wxSystemOptions</a>.
+%% @type wxSystemOptions(). 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(wxSystemOptions).
+-include("wxe.hrl").
+-export([getOption/1,getOptionInt/1,hasOption/1,isFalse/1,setOption/2]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+-export_type([wxSystemOptions/0]).
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxSystemOptions() :: wx:wx_object().
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionsgetoption">external documentation</a>.
+-spec getOption(Name) -> unicode:charlist() when
+ Name::unicode:chardata().
+getOption(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_GetOption,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionsgetoptionint">external documentation</a>.
+-spec getOptionInt(Name) -> integer() when
+ Name::unicode:chardata().
+getOptionInt(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_GetOptionInt,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionshasoption">external documentation</a>.
+-spec hasOption(Name) -> boolean() when
+ Name::unicode:chardata().
+hasOption(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_HasOption,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionsisfalse">external documentation</a>.
+-spec isFalse(Name) -> boolean() when
+ Name::unicode:chardata().
+isFalse(Name)
+ when is_list(Name) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:call(?wxSystemOptions_IsFalse,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemoptions.html#wxsystemoptionssetoption">external documentation</a>.
+%% <br /> Also:<br />
+%% setOption(Name, Value) -> ok when<br />
+%% Name::unicode:chardata(), Value::unicode:chardata().<br />
+%%
+-spec setOption(Name, Value) -> ok when
+ Name::unicode:chardata(), Value::integer();
+ (Name, Value) -> ok when
+ Name::unicode:chardata(), Value::unicode:chardata().
+setOption(Name,Value)
+ when is_list(Name),is_integer(Value) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ wxe_util:cast(?wxSystemOptions_SetOption_2_0,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,Value:32/?UI>>);
+setOption(Name,Value)
+ when is_list(Name),is_list(Value) ->
+ Name_UC = unicode:characters_to_binary([Name,0]),
+ Value_UC = unicode:characters_to_binary([Value,0]),
+ wxe_util:cast(?wxSystemOptions_SetOption_2_1,
+ <<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((4+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
+
diff --git a/lib/wx/src/gen/wxSystemSettings.erl b/lib/wx/src/gen/wxSystemSettings.erl
index 3f7e0a1ad6..a3bae5c85f 100644
--- a/lib/wx/src/gen/wxSystemSettings.erl
+++ b/lib/wx/src/gen/wxSystemSettings.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,38 +29,42 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxSystemSettings/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Index::WxSystemColour) -> wx:colour()
-%% WxSystemColour = integer()
+-type wxSystemSettings() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemsettings.html#wxsystemsettingsgetcolour">external documentation</a>.
-%%<br /> WxSystemColour is one of ?wxSYS_COLOUR_SCROLLBAR | ?wxSYS_COLOUR_BACKGROUND | ?wxSYS_COLOUR_DESKTOP | ?wxSYS_COLOUR_ACTIVECAPTION | ?wxSYS_COLOUR_INACTIVECAPTION | ?wxSYS_COLOUR_MENU | ?wxSYS_COLOUR_WINDOW | ?wxSYS_COLOUR_WINDOWFRAME | ?wxSYS_COLOUR_MENUTEXT | ?wxSYS_COLOUR_WINDOWTEXT | ?wxSYS_COLOUR_CAPTIONTEXT | ?wxSYS_COLOUR_ACTIVEBORDER | ?wxSYS_COLOUR_INACTIVEBORDER | ?wxSYS_COLOUR_APPWORKSPACE | ?wxSYS_COLOUR_HIGHLIGHT | ?wxSYS_COLOUR_HIGHLIGHTTEXT | ?wxSYS_COLOUR_BTNFACE | ?wxSYS_COLOUR_3DFACE | ?wxSYS_COLOUR_BTNSHADOW | ?wxSYS_COLOUR_3DSHADOW | ?wxSYS_COLOUR_GRAYTEXT | ?wxSYS_COLOUR_BTNTEXT | ?wxSYS_COLOUR_INACTIVECAPTIONTEXT | ?wxSYS_COLOUR_BTNHIGHLIGHT | ?wxSYS_COLOUR_BTNHILIGHT | ?wxSYS_COLOUR_3DHIGHLIGHT | ?wxSYS_COLOUR_3DHILIGHT | ?wxSYS_COLOUR_3DDKSHADOW | ?wxSYS_COLOUR_3DLIGHT | ?wxSYS_COLOUR_INFOTEXT | ?wxSYS_COLOUR_INFOBK | ?wxSYS_COLOUR_LISTBOX | ?wxSYS_COLOUR_HOTLIGHT | ?wxSYS_COLOUR_GRADIENTACTIVECAPTION | ?wxSYS_COLOUR_GRADIENTINACTIVECAPTION | ?wxSYS_COLOUR_MENUHILIGHT | ?wxSYS_COLOUR_MENUBAR | ?wxSYS_COLOUR_LISTBOXTEXT | ?wxSYS_COLOUR_MAX
+%%<br /> Index = ?wxSYS_COLOUR_SCROLLBAR | ?wxSYS_COLOUR_BACKGROUND | ?wxSYS_COLOUR_DESKTOP | ?wxSYS_COLOUR_ACTIVECAPTION | ?wxSYS_COLOUR_INACTIVECAPTION | ?wxSYS_COLOUR_MENU | ?wxSYS_COLOUR_WINDOW | ?wxSYS_COLOUR_WINDOWFRAME | ?wxSYS_COLOUR_MENUTEXT | ?wxSYS_COLOUR_WINDOWTEXT | ?wxSYS_COLOUR_CAPTIONTEXT | ?wxSYS_COLOUR_ACTIVEBORDER | ?wxSYS_COLOUR_INACTIVEBORDER | ?wxSYS_COLOUR_APPWORKSPACE | ?wxSYS_COLOUR_HIGHLIGHT | ?wxSYS_COLOUR_HIGHLIGHTTEXT | ?wxSYS_COLOUR_BTNFACE | ?wxSYS_COLOUR_3DFACE | ?wxSYS_COLOUR_BTNSHADOW | ?wxSYS_COLOUR_3DSHADOW | ?wxSYS_COLOUR_GRAYTEXT | ?wxSYS_COLOUR_BTNTEXT | ?wxSYS_COLOUR_INACTIVECAPTIONTEXT | ?wxSYS_COLOUR_BTNHIGHLIGHT | ?wxSYS_COLOUR_BTNHILIGHT | ?wxSYS_COLOUR_3DHIGHLIGHT | ?wxSYS_COLOUR_3DHILIGHT | ?wxSYS_COLOUR_3DDKSHADOW | ?wxSYS_COLOUR_3DLIGHT | ?wxSYS_COLOUR_INFOTEXT | ?wxSYS_COLOUR_INFOBK | ?wxSYS_COLOUR_LISTBOX | ?wxSYS_COLOUR_HOTLIGHT | ?wxSYS_COLOUR_GRADIENTACTIVECAPTION | ?wxSYS_COLOUR_GRADIENTINACTIVECAPTION | ?wxSYS_COLOUR_MENUHILIGHT | ?wxSYS_COLOUR_MENUBAR | ?wxSYS_COLOUR_LISTBOXTEXT | ?wxSYS_COLOUR_MAX
+-spec getColour(Index) -> wx:wx_colour4() when
+ Index::wx:wx_enum().
getColour(Index)
when is_integer(Index) ->
wxe_util:call(?wxSystemSettings_GetColour,
<<Index:32/?UI>>).
-%% @spec (Index::WxSystemFont) -> wxFont:wxFont()
-%% WxSystemFont = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemsettings.html#wxsystemsettingsgetfont">external documentation</a>.
-%%<br /> WxSystemFont is one of ?wxSYS_OEM_FIXED_FONT | ?wxSYS_ANSI_FIXED_FONT | ?wxSYS_ANSI_VAR_FONT | ?wxSYS_SYSTEM_FONT | ?wxSYS_DEVICE_DEFAULT_FONT | ?wxSYS_DEFAULT_PALETTE | ?wxSYS_SYSTEM_FIXED_FONT | ?wxSYS_DEFAULT_GUI_FONT | ?wxSYS_ICONTITLE_FONT
+%%<br /> Index = ?wxSYS_OEM_FIXED_FONT | ?wxSYS_ANSI_FIXED_FONT | ?wxSYS_ANSI_VAR_FONT | ?wxSYS_SYSTEM_FONT | ?wxSYS_DEVICE_DEFAULT_FONT | ?wxSYS_DEFAULT_PALETTE | ?wxSYS_SYSTEM_FIXED_FONT | ?wxSYS_DEFAULT_GUI_FONT | ?wxSYS_ICONTITLE_FONT
+-spec getFont(Index) -> wxFont:wxFont() when
+ Index::wx:wx_enum().
getFont(Index)
when is_integer(Index) ->
wxe_util:call(?wxSystemSettings_GetFont,
<<Index:32/?UI>>).
-%% @spec (Index::WxSystemMetric) -> integer()
%% @equiv getMetric(Index, [])
+-spec getMetric(Index) -> integer() when
+ Index::wx:wx_enum().
+
getMetric(Index)
when is_integer(Index) ->
getMetric(Index, []).
-%% @spec (Index::WxSystemMetric, [Option]) -> integer()
-%% Option = {win, wxWindow:wxWindow()}
-%% WxSystemMetric = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemsettings.html#wxsystemsettingsgetmetric">external documentation</a>.
-%%<br /> WxSystemMetric is one of ?wxSYS_MOUSE_BUTTONS | ?wxSYS_BORDER_X | ?wxSYS_BORDER_Y | ?wxSYS_CURSOR_X | ?wxSYS_CURSOR_Y | ?wxSYS_DCLICK_X | ?wxSYS_DCLICK_Y | ?wxSYS_DRAG_X | ?wxSYS_DRAG_Y | ?wxSYS_EDGE_X | ?wxSYS_EDGE_Y | ?wxSYS_HSCROLL_ARROW_X | ?wxSYS_HSCROLL_ARROW_Y | ?wxSYS_HTHUMB_X | ?wxSYS_ICON_X | ?wxSYS_ICON_Y | ?wxSYS_ICONSPACING_X | ?wxSYS_ICONSPACING_Y | ?wxSYS_WINDOWMIN_X | ?wxSYS_WINDOWMIN_Y | ?wxSYS_SCREEN_X | ?wxSYS_SCREEN_Y | ?wxSYS_FRAMESIZE_X | ?wxSYS_FRAMESIZE_Y | ?wxSYS_SMALLICON_X | ?wxSYS_SMALLICON_Y | ?wxSYS_HSCROLL_Y | ?wxSYS_VSCROLL_X | ?wxSYS_VSCROLL_ARROW_X | ?wxSYS_VSCROLL_ARROW_Y | ?wxSYS_VTHUMB_Y | ?wxSYS_CAPTION_Y | ?wxSYS_MENU_Y | ?wxSYS_NETWORK_PRESENT | ?wxSYS_PENWINDOWS_PRESENT | ?wxSYS_SHOW_SOUNDS | ?wxSYS_SWAP_BUTTONS
+%%<br /> Index = ?wxSYS_MOUSE_BUTTONS | ?wxSYS_BORDER_X | ?wxSYS_BORDER_Y | ?wxSYS_CURSOR_X | ?wxSYS_CURSOR_Y | ?wxSYS_DCLICK_X | ?wxSYS_DCLICK_Y | ?wxSYS_DRAG_X | ?wxSYS_DRAG_Y | ?wxSYS_EDGE_X | ?wxSYS_EDGE_Y | ?wxSYS_HSCROLL_ARROW_X | ?wxSYS_HSCROLL_ARROW_Y | ?wxSYS_HTHUMB_X | ?wxSYS_ICON_X | ?wxSYS_ICON_Y | ?wxSYS_ICONSPACING_X | ?wxSYS_ICONSPACING_Y | ?wxSYS_WINDOWMIN_X | ?wxSYS_WINDOWMIN_Y | ?wxSYS_SCREEN_X | ?wxSYS_SCREEN_Y | ?wxSYS_FRAMESIZE_X | ?wxSYS_FRAMESIZE_Y | ?wxSYS_SMALLICON_X | ?wxSYS_SMALLICON_Y | ?wxSYS_HSCROLL_Y | ?wxSYS_VSCROLL_X | ?wxSYS_VSCROLL_ARROW_X | ?wxSYS_VSCROLL_ARROW_Y | ?wxSYS_VTHUMB_Y | ?wxSYS_CAPTION_Y | ?wxSYS_MENU_Y | ?wxSYS_NETWORK_PRESENT | ?wxSYS_PENWINDOWS_PRESENT | ?wxSYS_SHOW_SOUNDS | ?wxSYS_SWAP_BUTTONS
+-spec getMetric(Index, [Option]) -> integer() when
+ Index::wx:wx_enum(),
+ Option :: {win, wxWindow:wxWindow()}.
getMetric(Index, Options)
when is_integer(Index),is_list(Options) ->
MOpts = fun({win, #wx_ref{type=WinT,ref=WinRef}}, Acc) -> ?CLASS(WinT,wxWindow),[<<1:32/?UI,WinRef:32/?UI>>|Acc];
@@ -69,10 +73,9 @@ getMetric(Index, Options)
wxe_util:call(?wxSystemSettings_GetMetric,
<<Index:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec () -> WxSystemScreenType
-%% WxSystemScreenType = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsystemsettings.html#wxsystemsettingsgetscreentype">external documentation</a>.
-%%<br /> WxSystemScreenType is one of ?wxSYS_SCREEN_NONE | ?wxSYS_SCREEN_TINY | ?wxSYS_SCREEN_PDA | ?wxSYS_SCREEN_SMALL | ?wxSYS_SCREEN_DESKTOP
+%%<br /> Res = ?wxSYS_SCREEN_NONE | ?wxSYS_SCREEN_TINY | ?wxSYS_SCREEN_PDA | ?wxSYS_SCREEN_SMALL | ?wxSYS_SCREEN_DESKTOP
+-spec getScreenType() -> wx:wx_enum().
getScreenType() ->
wxe_util:call(?wxSystemSettings_GetScreenType,
<<>>).
diff --git a/lib/wx/src/gen/wxTaskBarIcon.erl b/lib/wx/src/gen/wxTaskBarIcon.erl
new file mode 100644
index 0000000000..5ca2c91b16
--- /dev/null
+++ b/lib/wx/src/gen/wxTaskBarIcon.erl
@@ -0,0 +1,102 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_wxtaskbaricon.html">wxTaskBarIcon</a>.
+%% <p>This class is derived (and can use functions) from:
+%% <br />{@link wxEvtHandler}
+%% </p>
+%% @type wxTaskBarIcon(). 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(wxTaskBarIcon).
+-include("wxe.hrl").
+-export([destroy/1,new/0,popupMenu/2,removeIcon/1,setIcon/2,setIcon/3]).
+
+%% inherited exports
+-export([connect/2,connect/3,disconnect/1,disconnect/2,disconnect/3,parent_class/1]).
+
+-export_type([wxTaskBarIcon/0]).
+%% @hidden
+parent_class(wxEvtHandler) -> true;
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxTaskBarIcon() :: wx:wx_object().
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtaskbaricon.html#wxtaskbariconwxtaskbaricon">external documentation</a>.
+-spec new() -> wxTaskBarIcon().
+new() ->
+ wxe_util:construct(?wxTaskBarIcon_new,
+ <<>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtaskbaricon.html#wxtaskbariconpopupmenu">external documentation</a>.
+-spec popupMenu(This, Menu) -> boolean() when
+ This::wxTaskBarIcon(), Menu::wxMenu:wxMenu().
+popupMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef}) ->
+ ?CLASS(ThisT,wxTaskBarIcon),
+ ?CLASS(MenuT,wxMenu),
+ wxe_util:call(?wxTaskBarIcon_PopupMenu,
+ <<ThisRef:32/?UI,MenuRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtaskbaricon.html#wxtaskbariconremoveicon">external documentation</a>.
+-spec removeIcon(This) -> boolean() when
+ This::wxTaskBarIcon().
+removeIcon(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxTaskBarIcon),
+ wxe_util:call(?wxTaskBarIcon_RemoveIcon,
+ <<ThisRef:32/?UI>>).
+
+%% @equiv setIcon(This,Icon, [])
+-spec setIcon(This, Icon) -> boolean() when
+ This::wxTaskBarIcon(), Icon::wxIcon:wxIcon().
+
+setIcon(This,Icon)
+ when is_record(This, wx_ref),is_record(Icon, wx_ref) ->
+ setIcon(This,Icon, []).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtaskbaricon.html#wxtaskbariconseticon">external documentation</a>.
+-spec setIcon(This, Icon, [Option]) -> boolean() when
+ This::wxTaskBarIcon(), Icon::wxIcon:wxIcon(),
+ Option :: {tooltip, unicode:chardata()}.
+setIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef}, Options)
+ when is_list(Options) ->
+ ?CLASS(ThisT,wxTaskBarIcon),
+ ?CLASS(IconT,wxIcon),
+ MOpts = fun({tooltip, Tooltip}, Acc) -> Tooltip_UC = unicode:characters_to_binary([Tooltip,0]),[<<1:32/?UI,(byte_size(Tooltip_UC)):32/?UI,(Tooltip_UC)/binary, 0:(((8- ((0+byte_size(Tooltip_UC)) band 16#7)) band 16#7))/unit:8>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:call(?wxTaskBarIcon_SetIcon,
+ <<ThisRef:32/?UI,IconRef:32/?UI, BinOpt/binary>>).
+
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTaskBarIcon()) -> ok.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxTaskBarIcon),
+ wxe_util:destroy(?DESTROY_OBJECT,Obj),
+ ok.
+ %% From wxEvtHandler
+%% @hidden
+disconnect(This,EventType, Options) -> wxEvtHandler:disconnect(This,EventType, Options).
+%% @hidden
+disconnect(This,EventType) -> wxEvtHandler:disconnect(This,EventType).
+%% @hidden
+disconnect(This) -> wxEvtHandler:disconnect(This).
+%% @hidden
+connect(This,EventType, Options) -> wxEvtHandler:connect(This,EventType, Options).
+%% @hidden
+connect(This,EventType) -> wxEvtHandler:connect(This,EventType).
diff --git a/lib/wx/src/gen/wxTaskBarIconEvent.erl b/lib/wx/src/gen/wxTaskBarIconEvent.erl
new file mode 100644
index 0000000000..9f2af608c5
--- /dev/null
+++ b/lib/wx/src/gen/wxTaskBarIconEvent.erl
@@ -0,0 +1,64 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_wxtaskbariconevent.html">wxTaskBarIconEvent</a>.
+%% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt>
+%% <dd><em>taskbar_move</em>, <em>taskbar_left_down</em>, <em>taskbar_left_up</em>, <em>taskbar_right_down</em>, <em>taskbar_right_up</em>, <em>taskbar_left_dclick</em>, <em>taskbar_right_dclick</em></dd></dl>
+%% See also the message variant {@link wxEvtHandler:wxTaskBarIcon(). #wxTaskBarIcon{}} event record type.
+%%
+%% <p>This class is derived (and can use functions) from:
+%% <br />{@link wxEvent}
+%% </p>
+%% @type wxTaskBarIconEvent(). 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(wxTaskBarIconEvent).
+-include("wxe.hrl").
+-export([]).
+
+%% inherited exports
+-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
+ resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+
+-export_type([wxTaskBarIconEvent/0]).
+%% @hidden
+parent_class(wxEvent) -> true;
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxTaskBarIconEvent() :: wx:wx_object().
+ %% From wxEvent
+%% @hidden
+stopPropagation(This) -> wxEvent:stopPropagation(This).
+%% @hidden
+skip(This, Options) -> wxEvent:skip(This, Options).
+%% @hidden
+skip(This) -> wxEvent:skip(This).
+%% @hidden
+shouldPropagate(This) -> wxEvent:shouldPropagate(This).
+%% @hidden
+resumePropagation(This,PropagationLevel) -> wxEvent:resumePropagation(This,PropagationLevel).
+%% @hidden
+isCommandEvent(This) -> wxEvent:isCommandEvent(This).
+%% @hidden
+getTimestamp(This) -> wxEvent:getTimestamp(This).
+%% @hidden
+getSkipped(This) -> wxEvent:getSkipped(This).
+%% @hidden
+getId(This) -> wxEvent:getId(This).
diff --git a/lib/wx/src/gen/wxTextAttr.erl b/lib/wx/src/gen/wxTextAttr.erl
index 056dc59161..16bb943359 100644
--- a/lib/wx/src/gen/wxTextAttr.erl
+++ b/lib/wx/src/gen/wxTextAttr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,26 +34,32 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxTextAttr/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxTextAttr()
+-type wxTextAttr() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrwxtextattr">external documentation</a>.
+-spec new() -> wxTextAttr().
new() ->
wxe_util:construct(?wxTextAttr_new_0,
<<>>).
-%% @spec (ColText::wx:colour()) -> wxTextAttr()
%% @equiv new(ColText, [])
+-spec new(ColText) -> wxTextAttr() when
+ ColText::wx:wx_colour().
+
new(ColText)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
new(ColText, []).
-%% @spec (ColText::wx:colour(), [Option]) -> wxTextAttr()
-%% Option = {colBack, wx:colour()} | {font, wxFont:wxFont()} | {alignment, WxTextAttrAlignment}
-%% WxTextAttrAlignment = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrwxtextattr">external documentation</a>.
-%%<br /> WxTextAttrAlignment is one of ?wxTEXT_ALIGNMENT_DEFAULT | ?wxTEXT_ALIGNMENT_LEFT | ?wxTEXT_ALIGNMENT_CENTRE | ?wxTEXT_ALIGNMENT_CENTER | ?wxTEXT_ALIGNMENT_RIGHT | ?wxTEXT_ALIGNMENT_JUSTIFIED
+%%<br /> Alignment = ?wxTEXT_ALIGNMENT_DEFAULT | ?wxTEXT_ALIGNMENT_LEFT | ?wxTEXT_ALIGNMENT_CENTRE | ?wxTEXT_ALIGNMENT_CENTER | ?wxTEXT_ALIGNMENT_RIGHT | ?wxTEXT_ALIGNMENT_JUSTIFIED
+-spec new(ColText, [Option]) -> wxTextAttr() when
+ ColText::wx:wx_colour(),
+ Option :: {colBack, wx:wx_colour()}
+ | {font, wxFont:wxFont()}
+ | {alignment, wx:wx_enum()}.
new(ColText, Options)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4,is_list(Options) ->
MOpts = fun({colBack, ColBack}, Acc) -> [<<1:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary,0:32>>|Acc];
@@ -64,134 +70,151 @@ new(ColText, Options)
wxe_util:construct(?wxTextAttr_new_2,
<<(wxe_util:colour_bin(ColText)):16/binary, BinOpt/binary>>).
-%% @spec (This::wxTextAttr()) -> WxTextAttrAlignment
-%% WxTextAttrAlignment = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetalignment">external documentation</a>.
-%%<br /> WxTextAttrAlignment is one of ?wxTEXT_ALIGNMENT_DEFAULT | ?wxTEXT_ALIGNMENT_LEFT | ?wxTEXT_ALIGNMENT_CENTRE | ?wxTEXT_ALIGNMENT_CENTER | ?wxTEXT_ALIGNMENT_RIGHT | ?wxTEXT_ALIGNMENT_JUSTIFIED
+%%<br /> Res = ?wxTEXT_ALIGNMENT_DEFAULT | ?wxTEXT_ALIGNMENT_LEFT | ?wxTEXT_ALIGNMENT_CENTRE | ?wxTEXT_ALIGNMENT_CENTER | ?wxTEXT_ALIGNMENT_RIGHT | ?wxTEXT_ALIGNMENT_JUSTIFIED
+-spec getAlignment(This) -> wx:wx_enum() when
+ This::wxTextAttr().
getAlignment(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetAlignment,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetbackgroundcolour">external documentation</a>.
+-spec getBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxTextAttr().
getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxTextAttr().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetleftindent">external documentation</a>.
+-spec getLeftIndent(This) -> integer() when
+ This::wxTextAttr().
getLeftIndent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetLeftIndent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetleftsubindent">external documentation</a>.
+-spec getLeftSubIndent(This) -> integer() when
+ This::wxTextAttr().
getLeftSubIndent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetLeftSubIndent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetrightindent">external documentation</a>.
+-spec getRightIndent(This) -> integer() when
+ This::wxTextAttr().
getRightIndent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetRightIndent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> [integer()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgettabs">external documentation</a>.
+-spec getTabs(This) -> [integer()] when
+ This::wxTextAttr().
getTabs(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetTabs,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgettextcolour">external documentation</a>.
+-spec getTextColour(This) -> wx:wx_colour4() when
+ This::wxTextAttr().
getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrhasbackgroundcolour">external documentation</a>.
+-spec hasBackgroundColour(This) -> boolean() when
+ This::wxTextAttr().
hasBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_HasBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrhasfont">external documentation</a>.
+-spec hasFont(This) -> boolean() when
+ This::wxTextAttr().
hasFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_HasFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrhastextcolour">external documentation</a>.
+-spec hasTextColour(This) -> boolean() when
+ This::wxTextAttr().
hasTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_HasTextColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrgetflags">external documentation</a>.
+-spec getFlags(This) -> integer() when
+ This::wxTextAttr().
getFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_GetFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrisdefault">external documentation</a>.
+-spec isDefault(This) -> boolean() when
+ This::wxTextAttr().
isDefault(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:call(?wxTextAttr_IsDefault,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextAttr(), Alignment::WxTextAttrAlignment) -> ok
-%% WxTextAttrAlignment = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsetalignment">external documentation</a>.
-%%<br /> WxTextAttrAlignment is one of ?wxTEXT_ALIGNMENT_DEFAULT | ?wxTEXT_ALIGNMENT_LEFT | ?wxTEXT_ALIGNMENT_CENTRE | ?wxTEXT_ALIGNMENT_CENTER | ?wxTEXT_ALIGNMENT_RIGHT | ?wxTEXT_ALIGNMENT_JUSTIFIED
+%%<br /> Alignment = ?wxTEXT_ALIGNMENT_DEFAULT | ?wxTEXT_ALIGNMENT_LEFT | ?wxTEXT_ALIGNMENT_CENTRE | ?wxTEXT_ALIGNMENT_CENTER | ?wxTEXT_ALIGNMENT_RIGHT | ?wxTEXT_ALIGNMENT_JUSTIFIED
+-spec setAlignment(This, Alignment) -> ok when
+ This::wxTextAttr(), Alignment::wx:wx_enum().
setAlignment(#wx_ref{type=ThisT,ref=ThisRef},Alignment)
when is_integer(Alignment) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:cast(?wxTextAttr_SetAlignment,
<<ThisRef:32/?UI,Alignment:32/?UI>>).
-%% @spec (This::wxTextAttr(), ColBack::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsetbackgroundcolour">external documentation</a>.
+-spec setBackgroundColour(This, ColBack) -> ok when
+ This::wxTextAttr(), ColBack::wx:wx_colour().
setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},ColBack)
when tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
?CLASS(ThisT,wxTextAttr),
wxe_util:cast(?wxTextAttr_SetBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary>>).
-%% @spec (This::wxTextAttr(), Flags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsetflags">external documentation</a>.
+-spec setFlags(This, Flags) -> ok when
+ This::wxTextAttr(), Flags::integer().
setFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:cast(?wxTextAttr_SetFlags,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxTextAttr(), Font::wxFont:wxFont()) -> ok
%% @equiv setFont(This,Font, [])
+-spec setFont(This, Font) -> ok when
+ This::wxTextAttr(), Font::wxFont:wxFont().
+
setFont(This,Font)
when is_record(This, wx_ref),is_record(Font, wx_ref) ->
setFont(This,Font, []).
-%% @spec (This::wxTextAttr(), Font::wxFont:wxFont(), [Option]) -> ok
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsetfont">external documentation</a>.
+-spec setFont(This, Font, [Option]) -> ok when
+ This::wxTextAttr(), Font::wxFont:wxFont(),
+ Option :: {flags, integer()}.
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTextAttr),
@@ -202,15 +225,18 @@ setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}, Options
wxe_util:cast(?wxTextAttr_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTextAttr(), Indent::integer()) -> ok
%% @equiv setLeftIndent(This,Indent, [])
+-spec setLeftIndent(This, Indent) -> ok when
+ This::wxTextAttr(), Indent::integer().
+
setLeftIndent(This,Indent)
when is_record(This, wx_ref),is_integer(Indent) ->
setLeftIndent(This,Indent, []).
-%% @spec (This::wxTextAttr(), Indent::integer(), [Option]) -> ok
-%% Option = {subIndent, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsetleftindent">external documentation</a>.
+-spec setLeftIndent(This, Indent, [Option]) -> ok when
+ This::wxTextAttr(), Indent::integer(),
+ Option :: {subIndent, integer()}.
setLeftIndent(#wx_ref{type=ThisT,ref=ThisRef},Indent, Options)
when is_integer(Indent),is_list(Options) ->
?CLASS(ThisT,wxTextAttr),
@@ -220,16 +246,18 @@ setLeftIndent(#wx_ref{type=ThisT,ref=ThisRef},Indent, Options)
wxe_util:cast(?wxTextAttr_SetLeftIndent,
<<ThisRef:32/?UI,Indent:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTextAttr(), Indent::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsetrightindent">external documentation</a>.
+-spec setRightIndent(This, Indent) -> ok when
+ This::wxTextAttr(), Indent::integer().
setRightIndent(#wx_ref{type=ThisT,ref=ThisRef},Indent)
when is_integer(Indent) ->
?CLASS(ThisT,wxTextAttr),
wxe_util:cast(?wxTextAttr_SetRightIndent,
<<ThisRef:32/?UI,Indent:32/?UI>>).
-%% @spec (This::wxTextAttr(), Tabs::[integer()]) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsettabs">external documentation</a>.
+-spec setTabs(This, Tabs) -> ok when
+ This::wxTextAttr(), Tabs::[integer()].
setTabs(#wx_ref{type=ThisT,ref=ThisRef},Tabs)
when is_list(Tabs) ->
?CLASS(ThisT,wxTextAttr),
@@ -237,16 +265,17 @@ setTabs(#wx_ref{type=ThisT,ref=ThisRef},Tabs)
<<ThisRef:32/?UI,(length(Tabs)):32/?UI,
(<< <<C:32/?I>> || C <- Tabs>>)/binary, 0:(((0+length(Tabs)) rem 2)*32)>>).
-%% @spec (This::wxTextAttr(), ColText::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextattr.html#wxtextattrsettextcolour">external documentation</a>.
+-spec setTextColour(This, ColText) -> ok when
+ This::wxTextAttr(), ColText::wx:wx_colour().
setTextColour(#wx_ref{type=ThisT,ref=ThisRef},ColText)
when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
?CLASS(ThisT,wxTextAttr),
wxe_util:cast(?wxTextAttr_SetTextColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(ColText)):16/binary>>).
-%% @spec (This::wxTextAttr()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTextAttr()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxTextAttr),
wxe_util:destroy(?wxTextAttr_destroy,Obj),
diff --git a/lib/wx/src/gen/wxTextCtrl.erl b/lib/wx/src/gen/wxTextCtrl.erl
index b4af23bdd9..e1f82c40c3 100644
--- a/lib/wx/src/gen/wxTextCtrl.erl
+++ b/lib/wx/src/gen/wxTextCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +77,36 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxTextCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxTextCtrl()
+-type wxTextCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlwxtextctrl">external documentation</a>.
+-spec new() -> wxTextCtrl().
new() ->
wxe_util:construct(?wxTextCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxTextCtrl()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxTextCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxTextCtrl()
-%% Option = {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlwxtextctrl">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxTextCtrl() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {value, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -111,8 +120,9 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxTextCtrl_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlappendtext">external documentation</a>.
+-spec appendText(This, Text) -> ok when
+ This::wxTextCtrl(), Text::unicode:chardata().
appendText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxTextCtrl),
@@ -120,64 +130,78 @@ appendText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxTextCtrl_AppendText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcancopy">external documentation</a>.
+-spec canCopy(This) -> boolean() when
+ This::wxTextCtrl().
canCopy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_CanCopy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcancut">external documentation</a>.
+-spec canCut(This) -> boolean() when
+ This::wxTextCtrl().
canCut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_CanCut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcanpaste">external documentation</a>.
+-spec canPaste(This) -> boolean() when
+ This::wxTextCtrl().
canPaste(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_CanPaste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcanredo">external documentation</a>.
+-spec canRedo(This) -> boolean() when
+ This::wxTextCtrl().
canRedo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_CanRedo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcanundo">external documentation</a>.
+-spec canUndo(This) -> boolean() when
+ This::wxTextCtrl().
canUndo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_CanUndo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxTextCtrl().
clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Clear,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcopy">external documentation</a>.
+-spec copy(This) -> ok when
+ This::wxTextCtrl().
copy(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Copy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxTextCtrl(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxTextCtrl(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {value, string()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxTextCtrl(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {value, unicode:chardata()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxTextCtrl),
@@ -192,96 +216,109 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxTextCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlcut">external documentation</a>.
+-spec cut(This) -> ok when
+ This::wxTextCtrl().
cut(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Cut,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrldiscardedits">external documentation</a>.
+-spec discardEdits(This) -> ok when
+ This::wxTextCtrl().
discardEdits(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_DiscardEdits,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Event::wxKeyEvent:wxKeyEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlemulatekeypress">external documentation</a>.
+-spec emulateKeyPress(This, Event) -> boolean() when
+ This::wxTextCtrl(), Event::wxKeyEvent:wxKeyEvent().
emulateKeyPress(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=EventT,ref=EventRef}) ->
?CLASS(ThisT,wxTextCtrl),
?CLASS(EventT,wxKeyEvent),
wxe_util:call(?wxTextCtrl_EmulateKeyPress,
<<ThisRef:32/?UI,EventRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> wxTextAttr:wxTextAttr()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetdefaultstyle">external documentation</a>.
+-spec getDefaultStyle(This) -> wxTextAttr:wxTextAttr() when
+ This::wxTextCtrl().
getDefaultStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetDefaultStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetinsertionpoint">external documentation</a>.
+-spec getInsertionPoint(This) -> integer() when
+ This::wxTextCtrl().
getInsertionPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetInsertionPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetlastposition">external documentation</a>.
+-spec getLastPosition(This) -> integer() when
+ This::wxTextCtrl().
getLastPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetLastPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), LineNo::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetlinelength">external documentation</a>.
+-spec getLineLength(This, LineNo) -> integer() when
+ This::wxTextCtrl(), LineNo::integer().
getLineLength(#wx_ref{type=ThisT,ref=ThisRef},LineNo)
when is_integer(LineNo) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetLineLength,
<<ThisRef:32/?UI,LineNo:32/?UI>>).
-%% @spec (This::wxTextCtrl(), LineNo::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetlinetext">external documentation</a>.
+-spec getLineText(This, LineNo) -> unicode:charlist() when
+ This::wxTextCtrl(), LineNo::integer().
getLineText(#wx_ref{type=ThisT,ref=ThisRef},LineNo)
when is_integer(LineNo) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetLineText,
<<ThisRef:32/?UI,LineNo:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetnumberoflines">external documentation</a>.
+-spec getNumberOfLines(This) -> integer() when
+ This::wxTextCtrl().
getNumberOfLines(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetNumberOfLines,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), From::integer(), To::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetrange">external documentation</a>.
+-spec getRange(This, From, To) -> unicode:charlist() when
+ This::wxTextCtrl(), From::integer(), To::integer().
getRange(#wx_ref{type=ThisT,ref=ThisRef},From,To)
when is_integer(From),is_integer(To) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetRange,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> {From::integer(),To::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetselection">external documentation</a>.
+-spec getSelection(This) -> {From::integer(), To::integer()} when
+ This::wxTextCtrl().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetstringselection">external documentation</a>.
+-spec getStringSelection(This) -> unicode:charlist() when
+ This::wxTextCtrl().
getStringSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetStringSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Position::integer(), Style::wxTextAttr:wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetstyle">external documentation</a>.
+-spec getStyle(This, Position, Style) -> boolean() when
+ This::wxTextCtrl(), Position::integer(), Style::wxTextAttr:wxTextAttr().
getStyle(#wx_ref{type=ThisT,ref=ThisRef},Position,#wx_ref{type=StyleT,ref=StyleRef})
when is_integer(Position) ->
?CLASS(ThisT,wxTextCtrl),
@@ -289,50 +326,58 @@ getStyle(#wx_ref{type=ThisT,ref=ThisRef},Position,#wx_ref{type=StyleT,ref=StyleR
wxe_util:call(?wxTextCtrl_GetStyle,
<<ThisRef:32/?UI,Position:32/?UI,StyleRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlgetvalue">external documentation</a>.
+-spec getValue(This) -> unicode:charlist() when
+ This::wxTextCtrl().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrliseditable">external documentation</a>.
+-spec isEditable(This) -> boolean() when
+ This::wxTextCtrl().
isEditable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_IsEditable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlismodified">external documentation</a>.
+-spec isModified(This) -> boolean() when
+ This::wxTextCtrl().
isModified(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_IsModified,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlismultiline">external documentation</a>.
+-spec isMultiLine(This) -> boolean() when
+ This::wxTextCtrl().
isMultiLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_IsMultiLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlissingleline">external documentation</a>.
+-spec isSingleLine(This) -> boolean() when
+ This::wxTextCtrl().
isSingleLine(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_IsSingleLine,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), File::string()) -> bool()
%% @equiv loadFile(This,File, [])
+-spec loadFile(This, File) -> boolean() when
+ This::wxTextCtrl(), File::unicode:chardata().
+
loadFile(This,File)
when is_record(This, wx_ref),is_list(File) ->
loadFile(This,File, []).
-%% @spec (This::wxTextCtrl(), File::string(), [Option]) -> bool()
-%% Option = {fileType, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlloadfile">external documentation</a>.
+-spec loadFile(This, File, [Option]) -> boolean() when
+ This::wxTextCtrl(), File::unicode:chardata(),
+ Option :: {fileType, integer()}.
loadFile(#wx_ref{type=ThisT,ref=ThisRef},File, Options)
when is_list(File),is_list(Options) ->
?CLASS(ThisT,wxTextCtrl),
@@ -343,45 +388,52 @@ loadFile(#wx_ref{type=ThisT,ref=ThisRef},File, Options)
wxe_util:call(?wxTextCtrl_LoadFile,
<<ThisRef:32/?UI,(byte_size(File_UC)):32/?UI,(File_UC)/binary, 0:(((8- ((0+byte_size(File_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlmarkdirty">external documentation</a>.
+-spec markDirty(This) -> ok when
+ This::wxTextCtrl().
markDirty(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_MarkDirty,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlpaste">external documentation</a>.
+-spec paste(This) -> ok when
+ This::wxTextCtrl().
paste(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Paste,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Pos::integer()) -> {bool(),X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlpositiontoxy">external documentation</a>.
+-spec positionToXY(This, Pos) -> Result when
+ Result ::{Res ::boolean(), X::integer(), Y::integer()},
+ This::wxTextCtrl(), Pos::integer().
positionToXY(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_PositionToXY,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlredo">external documentation</a>.
+-spec redo(This) -> ok when
+ This::wxTextCtrl().
redo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Redo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), From::integer(), To::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlremove">external documentation</a>.
+-spec remove(This, From, To) -> ok when
+ This::wxTextCtrl(), From::integer(), To::integer().
remove(#wx_ref{type=ThisT,ref=ThisRef},From,To)
when is_integer(From),is_integer(To) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Remove,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxTextCtrl(), From::integer(), To::integer(), Value::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlreplace">external documentation</a>.
+-spec replace(This, From, To, Value) -> ok when
+ This::wxTextCtrl(), From::integer(), To::integer(), Value::unicode:chardata().
replace(#wx_ref{type=ThisT,ref=ThisRef},From,To,Value)
when is_integer(From),is_integer(To),is_list(Value) ->
?CLASS(ThisT,wxTextCtrl),
@@ -389,15 +441,19 @@ replace(#wx_ref{type=ThisT,ref=ThisRef},From,To,Value)
wxe_util:cast(?wxTextCtrl_Replace,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((0+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTextCtrl()) -> bool()
%% @equiv saveFile(This, [])
+-spec saveFile(This) -> boolean() when
+ This::wxTextCtrl().
+
saveFile(This)
when is_record(This, wx_ref) ->
saveFile(This, []).
-%% @spec (This::wxTextCtrl(), [Option]) -> bool()
-%% Option = {file, string()} | {fileType, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsavefile">external documentation</a>.
+-spec saveFile(This, [Option]) -> boolean() when
+ This::wxTextCtrl(),
+ Option :: {file, unicode:chardata()}
+ | {fileType, integer()}.
saveFile(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTextCtrl),
@@ -408,55 +464,62 @@ saveFile(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxTextCtrl_SaveFile,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTextCtrl(), Style::wxTextAttr:wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetdefaultstyle">external documentation</a>.
+-spec setDefaultStyle(This, Style) -> boolean() when
+ This::wxTextCtrl(), Style::wxTextAttr:wxTextAttr().
setDefaultStyle(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=StyleT,ref=StyleRef}) ->
?CLASS(ThisT,wxTextCtrl),
?CLASS(StyleT,wxTextAttr),
wxe_util:call(?wxTextCtrl_SetDefaultStyle,
<<ThisRef:32/?UI,StyleRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Editable::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlseteditable">external documentation</a>.
+-spec setEditable(This, Editable) -> ok when
+ This::wxTextCtrl(), Editable::boolean().
setEditable(#wx_ref{type=ThisT,ref=ThisRef},Editable)
when is_boolean(Editable) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_SetEditable,
<<ThisRef:32/?UI,(wxe_util:from_bool(Editable)):32/?UI>>).
-%% @spec (This::wxTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetinsertionpoint">external documentation</a>.
+-spec setInsertionPoint(This, Pos) -> ok when
+ This::wxTextCtrl(), Pos::integer().
setInsertionPoint(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_SetInsertionPoint,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetinsertionpointend">external documentation</a>.
+-spec setInsertionPointEnd(This) -> ok when
+ This::wxTextCtrl().
setInsertionPointEnd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_SetInsertionPointEnd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Len::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetmaxlength">external documentation</a>.
+-spec setMaxLength(This, Len) -> ok when
+ This::wxTextCtrl(), Len::integer().
setMaxLength(#wx_ref{type=ThisT,ref=ThisRef},Len)
when is_integer(Len) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_SetMaxLength,
<<ThisRef:32/?UI,Len:32/?UI>>).
-%% @spec (This::wxTextCtrl(), From::integer(), To::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetselection">external documentation</a>.
+-spec setSelection(This, From, To) -> ok when
+ This::wxTextCtrl(), From::integer(), To::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},From,To)
when is_integer(From),is_integer(To) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_SetSelection,
<<ThisRef:32/?UI,From:32/?UI,To:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Start::integer(), End::integer(), Style::wxTextAttr:wxTextAttr()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetstyle">external documentation</a>.
+-spec setStyle(This, Start, End, Style) -> boolean() when
+ This::wxTextCtrl(), Start::integer(), End::integer(), Style::wxTextAttr:wxTextAttr().
setStyle(#wx_ref{type=ThisT,ref=ThisRef},Start,End,#wx_ref{type=StyleT,ref=StyleRef})
when is_integer(Start),is_integer(End) ->
?CLASS(ThisT,wxTextCtrl),
@@ -464,8 +527,9 @@ setStyle(#wx_ref{type=ThisT,ref=ThisRef},Start,End,#wx_ref{type=StyleT,ref=Style
wxe_util:call(?wxTextCtrl_SetStyle,
<<ThisRef:32/?UI,Start:32/?UI,End:32/?UI,StyleRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Value::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlsetvalue">external documentation</a>.
+-spec setValue(This, Value) -> ok when
+ This::wxTextCtrl(), Value::unicode:chardata().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
when is_list(Value) ->
?CLASS(ThisT,wxTextCtrl),
@@ -473,23 +537,26 @@ setValue(#wx_ref{type=ThisT,ref=ThisRef},Value)
wxe_util:cast(?wxTextCtrl_SetValue,
<<ThisRef:32/?UI,(byte_size(Value_UC)):32/?UI,(Value_UC)/binary, 0:(((8- ((0+byte_size(Value_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTextCtrl(), Pos::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlshowposition">external documentation</a>.
+-spec showPosition(This, Pos) -> ok when
+ This::wxTextCtrl(), Pos::integer().
showPosition(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_ShowPosition,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlundo">external documentation</a>.
+-spec undo(This) -> ok when
+ This::wxTextCtrl().
undo(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:cast(?wxTextCtrl_Undo,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextCtrl(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlwritetext">external documentation</a>.
+-spec writeText(This, Text) -> ok when
+ This::wxTextCtrl(), Text::unicode:chardata().
writeText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxTextCtrl),
@@ -497,16 +564,17 @@ writeText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxTextCtrl_WriteText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTextCtrl(), X::integer(), Y::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextctrl.html#wxtextctrlxytoposition">external documentation</a>.
+-spec xYToPosition(This, X, Y) -> integer() when
+ This::wxTextCtrl(), X::integer(), Y::integer().
xYToPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxTextCtrl),
wxe_util:call(?wxTextCtrl_XYToPosition,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxTextCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTextCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxTextCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxTextDataObject.erl b/lib/wx/src/gen/wxTextDataObject.erl
index f4fe3b5e0c..4ffa2de4a7 100644
--- a/lib/wx/src/gen/wxTextDataObject.erl
+++ b/lib/wx/src/gen/wxTextDataObject.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,18 +32,21 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxTextDataObject/0]).
%% @hidden
parent_class(wxDataObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxTextDataObject()
+-type wxTextDataObject() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxTextDataObject().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxTextDataObject()
-%% Option = {text, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextdataobject.html#wxtextdataobjectwxtextdataobject">external documentation</a>.
+-spec new([Option]) -> wxTextDataObject() when
+ Option :: {text, unicode:chardata()}.
new(Options)
when is_list(Options) ->
MOpts = fun({text, Text}, Acc) -> Text_UC = unicode:characters_to_binary([Text,0]),[<<1:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>|Acc];
@@ -52,22 +55,25 @@ new(Options)
wxe_util:construct(?wxTextDataObject_new,
<<BinOpt/binary>>).
-%% @spec (This::wxTextDataObject()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextdataobject.html#wxtextdataobjectgettextlength">external documentation</a>.
+-spec getTextLength(This) -> integer() when
+ This::wxTextDataObject().
getTextLength(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextDataObject),
wxe_util:call(?wxTextDataObject_GetTextLength,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextDataObject()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextdataobject.html#wxtextdataobjectgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxTextDataObject().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextDataObject),
wxe_util:call(?wxTextDataObject_GetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextDataObject(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextdataobject.html#wxtextdataobjectsettext">external documentation</a>.
+-spec setText(This, Text) -> ok when
+ This::wxTextDataObject(), Text::unicode:chardata().
setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxTextDataObject),
@@ -75,8 +81,8 @@ setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxTextDataObject_SetText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTextDataObject()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTextDataObject()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxTextDataObject),
wxe_util:destroy(?wxTextDataObject_destroy,Obj),
diff --git a/lib/wx/src/gen/wxTextEntryDialog.erl b/lib/wx/src/gen/wxTextEntryDialog.erl
index a30c32dd53..78e6e32b98 100644
--- a/lib/wx/src/gen/wxTextEntryDialog.erl
+++ b/lib/wx/src/gen/wxTextEntryDialog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,6 +77,7 @@
transferDataFromWindow/1,transferDataToWindow/1,update/1,updateWindowUI/1,
updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxTextEntryDialog/0]).
%% @hidden
parent_class(wxDialog) -> true;
parent_class(wxTopLevelWindow) -> true;
@@ -84,15 +85,22 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string()) -> wxTextEntryDialog()
+-type wxTextEntryDialog() :: wx:wx_object().
%% @equiv new(Parent,Message, [])
+-spec new(Parent, Message) -> wxTextEntryDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata().
+
new(Parent,Message)
when is_record(Parent, wx_ref),is_list(Message) ->
new(Parent,Message, []).
-%% @spec (Parent::wxWindow:wxWindow(), Message::string(), [Option]) -> wxTextEntryDialog()
-%% Option = {caption, string()} | {value, string()} | {style, integer()} | {pos, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextentrydialog.html#wxtextentrydialogwxtextentrydialog">external documentation</a>.
+-spec new(Parent, Message, [Option]) -> wxTextEntryDialog() when
+ Parent::wxWindow:wxWindow(), Message::unicode:chardata(),
+ Option :: {caption, unicode:chardata()}
+ | {value, unicode:chardata()}
+ | {style, integer()}
+ | {pos, {X::integer(), Y::integer()}}.
new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
when is_list(Message),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,15 +114,17 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Message, Options)
wxe_util:construct(?wxTextEntryDialog_new,
<<ParentRef:32/?UI,(byte_size(Message_UC)):32/?UI,(Message_UC)/binary, 0:(((8- ((0+byte_size(Message_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTextEntryDialog()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextentrydialog.html#wxtextentrydialoggetvalue">external documentation</a>.
+-spec getValue(This) -> unicode:charlist() when
+ This::wxTextEntryDialog().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTextEntryDialog),
wxe_util:call(?wxTextEntryDialog_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTextEntryDialog(), Val::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtextentrydialog.html#wxtextentrydialogsetvalue">external documentation</a>.
+-spec setValue(This, Val) -> ok when
+ This::wxTextEntryDialog(), Val::unicode:chardata().
setValue(#wx_ref{type=ThisT,ref=ThisRef},Val)
when is_list(Val) ->
?CLASS(ThisT,wxTextEntryDialog),
@@ -122,8 +132,8 @@ setValue(#wx_ref{type=ThisT,ref=ThisRef},Val)
wxe_util:cast(?wxTextEntryDialog_SetValue,
<<ThisRef:32/?UI,(byte_size(Val_UC)):32/?UI,(Val_UC)/binary, 0:(((8- ((0+byte_size(Val_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTextEntryDialog()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTextEntryDialog()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxTextEntryDialog),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxToggleButton.erl b/lib/wx/src/gen/wxToggleButton.erl
index ab595c1906..ed2f564952 100644
--- a/lib/wx/src/gen/wxToggleButton.erl
+++ b/lib/wx/src/gen/wxToggleButton.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,27 +69,35 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxToggleButton/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxToggleButton()
+-type wxToggleButton() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttonwxtogglebutton">external documentation</a>.
+-spec new() -> wxToggleButton().
new() ->
wxe_util:construct(?wxToggleButton_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> wxToggleButton()
%% @equiv new(Parent,Id,Label, [])
+-spec new(Parent, Id, Label) -> wxToggleButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
new(Parent,Id,Label)
when is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
new(Parent,Id,Label, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> wxToggleButton()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttonwxtogglebutton">external documentation</a>.
+-spec new(Parent, Id, Label, [Option]) -> wxToggleButton() when
+ Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -103,15 +111,21 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
wxe_util:construct(?wxToggleButton_new_4,
<<ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxToggleButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string()) -> bool()
%% @equiv create(This,Parent,Id,Label, [])
+-spec create(This, Parent, Id, Label) -> boolean() when
+ This::wxToggleButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata().
+
create(This,Parent,Id,Label)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id),is_list(Label) ->
create(This,Parent,Id,Label, []).
-%% @spec (This::wxToggleButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::string(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttoncreate">external documentation</a>.
+-spec create(This, Parent, Id, Label, [Option]) -> boolean() when
+ This::wxToggleButton(), Parent::wxWindow:wxWindow(), Id::integer(), Label::unicode:chardata(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,Label, Options)
when is_integer(Id),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxToggleButton),
@@ -126,23 +140,25 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id,La
wxe_util:call(?wxToggleButton_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxToggleButton()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttongetvalue">external documentation</a>.
+-spec getValue(This) -> boolean() when
+ This::wxToggleButton().
getValue(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToggleButton),
wxe_util:call(?wxToggleButton_GetValue,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToggleButton(), State::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtogglebutton.html#wxtogglebuttonsetvalue">external documentation</a>.
+-spec setValue(This, State) -> ok when
+ This::wxToggleButton(), State::boolean().
setValue(#wx_ref{type=ThisT,ref=ThisRef},State)
when is_boolean(State) ->
?CLASS(ThisT,wxToggleButton),
wxe_util:cast(?wxToggleButton_SetValue,
<<ThisRef:32/?UI,(wxe_util:from_bool(State)):32/?UI>>).
-%% @spec (This::wxToggleButton()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxToggleButton()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxToggleButton),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxToolBar.erl b/lib/wx/src/gen/wxToolBar.erl
index c68936d493..9401e30e20 100644
--- a/lib/wx/src/gen/wxToolBar.erl
+++ b/lib/wx/src/gen/wxToolBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,52 +77,66 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxToolBar/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxToolBar(), Control::wxControl:wxControl()) -> wx:wx()
+-type wxToolBar() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddcontrol">external documentation</a>.
+-spec addControl(This, Control) -> wx:wx_object() when
+ This::wxToolBar(), Control::wxControl:wxControl().
addControl(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ControlT,ref=ControlRef}) ->
?CLASS(ThisT,wxToolBar),
?CLASS(ControlT,wxControl),
wxe_util:call(?wxToolBar_AddControl,
<<ThisRef:32/?UI,ControlRef:32/?UI>>).
-%% @spec (This::wxToolBar()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddseparator">external documentation</a>.
+-spec addSeparator(This) -> wx:wx_object() when
+ This::wxToolBar().
addSeparator(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_AddSeparator,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Tool::wx:wx()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddtool">external documentation</a>.
+-spec addTool(This, Tool) -> wx:wx_object() when
+ This::wxToolBar(), Tool::wx:wx_object().
addTool(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ToolT,ref=ToolRef}) ->
?CLASS(ThisT,wxToolBar),
?CLASS(ToolT,wx),
wxe_util:call(?wxToolBar_AddTool_1,
<<ThisRef:32/?UI,ToolRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap()) -> wx:wx()
%% @equiv addTool(This,Toolid,Bitmap, [])
+-spec addTool(This, Toolid, Bitmap) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap().
+
addTool(This,Toolid,Bitmap)
when is_record(This, wx_ref),is_integer(Toolid),is_record(Bitmap, wx_ref) ->
addTool(This,Toolid,Bitmap, []).
-%% @spec (This::wxToolBar(),Toolid::integer(),X::string()|term(),X::term()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddtool">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap()) -> addTool(This,Toolid,Label,Bitmap, []) </c></p>
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap()) -> addTool(This,Toolid,Bitmap,BmpDisabled, []) </c></p>
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wx:wx() </c>
-%%<br /> Option = {shortHelpString, string()} | {longHelpString, string()}
-%% </p>
+%% <br /> Also:<br />
+%% addTool(This, Toolid, Bitmap, BmpDisabled) -> wx:wx_object() when<br />
+%% This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap();<br />
+%% (This, Toolid, Bitmap, [Option]) -> wx:wx_object() when<br />
+%% This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(),<br />
+%% Option :: {shortHelpString, unicode:chardata()}<br />
+%% | {longHelpString, unicode:chardata()}.<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec addTool(This, Toolid, Label, Bitmap) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap();
+ (This, Toolid, Bitmap, BmpDisabled) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap();
+ (This, Toolid, Bitmap, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {shortHelpString, unicode:chardata()}
+ | {longHelpString, unicode:chardata()}.
addTool(This,Toolid,Label,Bitmap)
when is_record(This, wx_ref),is_integer(Toolid),is_list(Label),is_record(Bitmap, wx_ref) ->
@@ -142,21 +156,32 @@ addTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,#wx_ref{type=BitmapT,ref=BitmapRe
wxe_util:call(?wxToolBar_AddTool_3,
<<ThisRef:32/?UI,Toolid:32/?UI,BitmapRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxToolBar(),Toolid::integer(),X::string()|term(),X::term(),X::term()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddtool">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap()) -> addTool(This,Toolid,Label,Bitmap,BmpDisabled, []) </c></p>
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wx:wx() </c>
-%%<br /> Option = {shortHelp, string()} | {kind, WxItemKind}
-%%<br /> WxItemKind = integer()
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
-%% </p>
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(), [Option]) -> wx:wx() </c>
-%%<br /> Option = {toggle, bool()} | {clientData, wx:wx()} | {shortHelpString, string()} | {longHelpString, string()}
-%% </p>
+%% <br /> Also:<br />
+%% addTool(This, Toolid, Label, Bitmap, [Option]) -> wx:wx_object() when<br />
+%% This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(),<br />
+%% Option :: {shortHelp, unicode:chardata()}<br />
+%% | {kind, wx:wx_enum()};<br />
+%% (This, Toolid, Bitmap, BmpDisabled, [Option]) -> wx:wx_object() when<br />
+%% This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(),<br />
+%% Option :: {toggle, boolean()}<br />
+%% | {clientData, wx:wx_object()}<br />
+%% | {shortHelpString, unicode:chardata()}<br />
+%% | {longHelpString, unicode:chardata()}.<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec addTool(This, Toolid, Label, Bitmap, BmpDisabled) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap();
+ (This, Toolid, Label, Bitmap, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {shortHelp, unicode:chardata()}
+ | {kind, wx:wx_enum()};
+ (This, Toolid, Bitmap, BmpDisabled, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(),
+ Option :: {toggle, boolean()}
+ | {clientData, wx:wx_object()}
+ | {shortHelpString, unicode:chardata()}
+ | {longHelpString, unicode:chardata()}.
addTool(This,Toolid,Label,Bitmap,BmpDisabled)
when is_record(This, wx_ref),is_integer(Toolid),is_list(Label),is_record(Bitmap, wx_ref),is_record(BmpDisabled, wx_ref) ->
@@ -186,17 +211,24 @@ addTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,#wx_ref{type=BitmapT,ref=BitmapRe
wxe_util:call(?wxToolBar_AddTool_4_1,
<<ThisRef:32/?UI,Toolid:32/?UI,BitmapRef:32/?UI,BmpDisabledRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxToolBar(),Toolid::integer(),X::term()|string(),X::term(),X::bool()|term(),X::integer()|term()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddtool">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(), Toggle::bool(), XPos::integer()) -> addTool(This,Toolid,Bitmap,BmpDisabled,Toggle,XPos, []) </c></p>
-%% <p><c>
-%% addTool(This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(), [Option]) -> wx:wx() </c>
-%%<br /> Option = {kind, WxItemKind} | {shortHelp, string()} | {longHelp, string()} | {data, wx:wx()}
-%%<br /> WxItemKind = integer()
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
-%% </p>
+%% <br /> Also:<br />
+%% addTool(This, Toolid, Label, Bitmap, BmpDisabled, [Option]) -> wx:wx_object() when<br />
+%% This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(),<br />
+%% Option :: {kind, wx:wx_enum()}<br />
+%% | {shortHelp, unicode:chardata()}<br />
+%% | {longHelp, unicode:chardata()}<br />
+%% | {data, wx:wx_object()}.<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec addTool(This, Toolid, Bitmap, BmpDisabled, Toggle, XPos) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(), Toggle::boolean(), XPos::integer();
+ (This, Toolid, Label, Bitmap, BmpDisabled, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(),
+ Option :: {kind, wx:wx_enum()}
+ | {shortHelp, unicode:chardata()}
+ | {longHelp, unicode:chardata()}
+ | {data, wx:wx_object()}.
addTool(This,Toolid,Bitmap,BmpDisabled,Toggle,XPos)
when is_record(This, wx_ref),is_integer(Toolid),is_record(Bitmap, wx_ref),is_record(BmpDisabled, wx_ref),is_boolean(Toggle),is_integer(XPos) ->
@@ -216,9 +248,13 @@ addTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,ref=Bi
wxe_util:call(?wxToolBar_AddTool_5,
<<ThisRef:32/?UI,Toolid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8,BitmapRef:32/?UI,BmpDisabledRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(), Toggle::bool(), XPos::integer(), [Option]) -> wx:wx()
-%% Option = {yPos, integer()} | {clientData, wx:wx()} | {shortHelp, string()} | {longHelp, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddtool">external documentation</a>.
+-spec addTool(This, Toolid, Bitmap, BmpDisabled, Toggle, XPos, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), BmpDisabled::wxBitmap:wxBitmap(), Toggle::boolean(), XPos::integer(),
+ Option :: {yPos, integer()}
+ | {clientData, wx:wx_object()}
+ | {shortHelp, unicode:chardata()}
+ | {longHelp, unicode:chardata()}.
addTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,#wx_ref{type=BitmapT,ref=BitmapRef},#wx_ref{type=BmpDisabledT,ref=BmpDisabledRef},Toggle,XPos, Options)
when is_integer(Toolid),is_boolean(Toggle),is_integer(XPos),is_list(Options) ->
?CLASS(ThisT,wxToolBar),
@@ -233,15 +269,21 @@ addTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,#wx_ref{type=BitmapT,ref=BitmapRe
wxe_util:call(?wxToolBar_AddTool_6,
<<ThisRef:32/?UI,Toolid:32/?UI,BitmapRef:32/?UI,BmpDisabledRef:32/?UI,(wxe_util:from_bool(Toggle)):32/?UI,XPos:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap()) -> wx:wx()
%% @equiv addCheckTool(This,Toolid,Label,Bitmap, [])
+-spec addCheckTool(This, Toolid, Label, Bitmap) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap().
+
addCheckTool(This,Toolid,Label,Bitmap)
when is_record(This, wx_ref),is_integer(Toolid),is_list(Label),is_record(Bitmap, wx_ref) ->
addCheckTool(This,Toolid,Label,Bitmap, []).
-%% @spec (This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wx:wx()
-%% Option = {bmpDisabled, wxBitmap:wxBitmap()} | {shortHelp, string()} | {longHelp, string()} | {data, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddchecktool">external documentation</a>.
+-spec addCheckTool(This, Toolid, Label, Bitmap, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {bmpDisabled, wxBitmap:wxBitmap()}
+ | {shortHelp, unicode:chardata()}
+ | {longHelp, unicode:chardata()}
+ | {data, wx:wx_object()}.
addCheckTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Toolid),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxToolBar),
@@ -256,15 +298,21 @@ addCheckTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,r
wxe_util:call(?wxToolBar_AddCheckTool,
<<ThisRef:32/?UI,Toolid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8,BitmapRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap()) -> wx:wx()
%% @equiv addRadioTool(This,Toolid,Label,Bitmap, [])
+-spec addRadioTool(This, Toolid, Label, Bitmap) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap().
+
addRadioTool(This,Toolid,Label,Bitmap)
when is_record(This, wx_ref),is_integer(Toolid),is_list(Label),is_record(Bitmap, wx_ref) ->
addRadioTool(This,Toolid,Label,Bitmap, []).
-%% @spec (This::wxToolBar(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wx:wx()
-%% Option = {bmpDisabled, wxBitmap:wxBitmap()} | {shortHelp, string()} | {longHelp, string()} | {data, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbaraddradiotool">external documentation</a>.
+-spec addRadioTool(This, Toolid, Label, Bitmap, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {bmpDisabled, wxBitmap:wxBitmap()}
+ | {shortHelp, unicode:chardata()}
+ | {longHelp, unicode:chardata()}
+ | {data, wx:wx_object()}.
addRadioTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Toolid),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxToolBar),
@@ -279,131 +327,148 @@ addRadioTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,r
wxe_util:call(?wxToolBar_AddRadioTool,
<<ThisRef:32/?UI,Toolid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8,BitmapRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbardeletetool">external documentation</a>.
+-spec deleteTool(This, Toolid) -> boolean() when
+ This::wxToolBar(), Toolid::integer().
deleteTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_DeleteTool,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), Pos::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbardeletetoolbypos">external documentation</a>.
+-spec deleteToolByPos(This, Pos) -> boolean() when
+ This::wxToolBar(), Pos::integer().
deleteToolByPos(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_DeleteToolByPos,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), Enable::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarenabletool">external documentation</a>.
+-spec enableTool(This, Toolid, Enable) -> ok when
+ This::wxToolBar(), Toolid::integer(), Enable::boolean().
enableTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Enable)
when is_integer(Toolid),is_boolean(Enable) ->
?CLASS(ThisT,wxToolBar),
wxe_util:cast(?wxToolBar_EnableTool,
<<ThisRef:32/?UI,Toolid:32/?UI,(wxe_util:from_bool(Enable)):32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarfindbyid">external documentation</a>.
+-spec findById(This, Toolid) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer().
findById(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_FindById,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> wxControl:wxControl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarfindcontrol">external documentation</a>.
+-spec findControl(This, Toolid) -> wxControl:wxControl() when
+ This::wxToolBar(), Toolid::integer().
findControl(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_FindControl,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), X::integer(), Y::integer()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarfindtoolforposition">external documentation</a>.
+-spec findToolForPosition(This, X, Y) -> wx:wx_object() when
+ This::wxToolBar(), X::integer(), Y::integer().
findToolForPosition(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_FindToolForPosition,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxToolBar()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolsize">external documentation</a>.
+-spec getToolSize(This) -> {W::integer(), H::integer()} when
+ This::wxToolBar().
getToolSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolbitmapsize">external documentation</a>.
+-spec getToolBitmapSize(This) -> {W::integer(), H::integer()} when
+ This::wxToolBar().
getToolBitmapSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolBitmapSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargetmargins">external documentation</a>.
+-spec getMargins(This) -> {W::integer(), H::integer()} when
+ This::wxToolBar().
getMargins(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetMargins,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolenabled">external documentation</a>.
+-spec getToolEnabled(This, Toolid) -> boolean() when
+ This::wxToolBar(), Toolid::integer().
getToolEnabled(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolEnabled,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoollonghelp">external documentation</a>.
+-spec getToolLongHelp(This, Toolid) -> unicode:charlist() when
+ This::wxToolBar(), Toolid::integer().
getToolLongHelp(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolLongHelp,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolpacking">external documentation</a>.
+-spec getToolPacking(This) -> integer() when
+ This::wxToolBar().
getToolPacking(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolPacking,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Id::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolpos">external documentation</a>.
+-spec getToolPos(This, Id) -> integer() when
+ This::wxToolBar(), Id::integer().
getToolPos(#wx_ref{type=ThisT,ref=ThisRef},Id)
when is_integer(Id) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolPos,
<<ThisRef:32/?UI,Id:32/?UI>>).
-%% @spec (This::wxToolBar()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolseparation">external documentation</a>.
+-spec getToolSeparation(This) -> integer() when
+ This::wxToolBar().
getToolSeparation(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolSeparation,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolshorthelp">external documentation</a>.
+-spec getToolShortHelp(This, Toolid) -> unicode:charlist() when
+ This::wxToolBar(), Toolid::integer().
getToolShortHelp(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolShortHelp,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbargettoolstate">external documentation</a>.
+-spec getToolState(This, Toolid) -> boolean() when
+ This::wxToolBar(), Toolid::integer().
getToolState(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_GetToolState,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), Pos::integer(), Control::wxControl:wxControl()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarinsertcontrol">external documentation</a>.
+-spec insertControl(This, Pos, Control) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer(), Control::wxControl:wxControl().
insertControl(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=ControlT,ref=ControlRef})
when is_integer(Pos) ->
?CLASS(ThisT,wxToolBar),
@@ -411,16 +476,18 @@ insertControl(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=ControlT,ref=Cont
wxe_util:call(?wxToolBar_InsertControl,
<<ThisRef:32/?UI,Pos:32/?UI,ControlRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Pos::integer()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarinsertseparator">external documentation</a>.
+-spec insertSeparator(This, Pos) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer().
insertSeparator(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_InsertSeparator,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxToolBar(), Pos::integer(), Tool::wx:wx()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarinserttool">external documentation</a>.
+-spec insertTool(This, Pos, Tool) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer(), Tool::wx:wx_object().
insertTool(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=ToolT,ref=ToolRef})
when is_integer(Pos) ->
?CLASS(ThisT,wxToolBar),
@@ -428,21 +495,34 @@ insertTool(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=ToolT,ref=ToolRef})
wxe_util:call(?wxToolBar_InsertTool_2,
<<ThisRef:32/?UI,Pos:32/?UI,ToolRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Pos::integer(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap()) -> wx:wx()
%% @equiv insertTool(This,Pos,Toolid,Bitmap, [])
+-spec insertTool(This, Pos, Toolid, Bitmap) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap().
+
insertTool(This,Pos,Toolid,Bitmap)
when is_record(This, wx_ref),is_integer(Pos),is_integer(Toolid),is_record(Bitmap, wx_ref) ->
insertTool(This,Pos,Toolid,Bitmap, []).
-%% @spec (This::wxToolBar(),Pos::integer(),Toolid::integer(),X::string()|term(),X::term()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarinserttool">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insertTool(This::wxToolBar(), Pos::integer(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap()) -> insertTool(This,Pos,Toolid,Label,Bitmap, []) </c></p>
-%% <p><c>
-%% insertTool(This::wxToolBar(), Pos::integer(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wx:wx() </c>
-%%<br /> Option = {bmpDisabled, wxBitmap:wxBitmap()} | {toggle, bool()} | {clientData, wx:wx()} | {shortHelp, string()} | {longHelp, string()}
-%% </p>
+%% <br /> Also:<br />
+%% insertTool(This, Pos, Toolid, Bitmap, [Option]) -> wx:wx_object() when<br />
+%% This::wxToolBar(), Pos::integer(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(),<br />
+%% Option :: {bmpDisabled, wxBitmap:wxBitmap()}<br />
+%% | {toggle, boolean()}<br />
+%% | {clientData, wx:wx_object()}<br />
+%% | {shortHelp, unicode:chardata()}<br />
+%% | {longHelp, unicode:chardata()}.<br />
+%%
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec insertTool(This, Pos, Toolid, Label, Bitmap) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap();
+ (This, Pos, Toolid, Bitmap, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer(), Toolid::integer(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {bmpDisabled, wxBitmap:wxBitmap()}
+ | {toggle, boolean()}
+ | {clientData, wx:wx_object()}
+ | {shortHelp, unicode:chardata()}
+ | {longHelp, unicode:chardata()}.
insertTool(This,Pos,Toolid,Label,Bitmap)
when is_record(This, wx_ref),is_integer(Pos),is_integer(Toolid),is_list(Label),is_record(Bitmap, wx_ref) ->
@@ -461,11 +541,15 @@ insertTool(#wx_ref{type=ThisT,ref=ThisRef},Pos,Toolid,#wx_ref{type=BitmapT,ref=B
wxe_util:call(?wxToolBar_InsertTool_4,
<<ThisRef:32/?UI,Pos:32/?UI,Toolid:32/?UI,BitmapRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxToolBar(), Pos::integer(), Toolid::integer(), Label::string(), Bitmap::wxBitmap:wxBitmap(), [Option]) -> wx:wx()
-%% Option = {bmpDisabled, wxBitmap:wxBitmap()} | {kind, WxItemKind} | {shortHelp, string()} | {longHelp, string()} | {clientData, wx:wx()}
-%% WxItemKind = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarinserttool">external documentation</a>.
-%%<br /> WxItemKind is one of ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+%%<br /> Kind = ?wxITEM_SEPARATOR | ?wxITEM_NORMAL | ?wxITEM_CHECK | ?wxITEM_RADIO | ?wxITEM_MAX
+-spec insertTool(This, Pos, Toolid, Label, Bitmap, [Option]) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer(), Toolid::integer(), Label::unicode:chardata(), Bitmap::wxBitmap:wxBitmap(),
+ Option :: {bmpDisabled, wxBitmap:wxBitmap()}
+ | {kind, wx:wx_enum()}
+ | {shortHelp, unicode:chardata()}
+ | {longHelp, unicode:chardata()}
+ | {clientData, wx:wx_object()}.
insertTool(#wx_ref{type=ThisT,ref=ThisRef},Pos,Toolid,Label,#wx_ref{type=BitmapT,ref=BitmapRef}, Options)
when is_integer(Pos),is_integer(Toolid),is_list(Label),is_list(Options) ->
?CLASS(ThisT,wxToolBar),
@@ -481,39 +565,44 @@ insertTool(#wx_ref{type=ThisT,ref=ThisRef},Pos,Toolid,Label,#wx_ref{type=BitmapT
wxe_util:call(?wxToolBar_InsertTool_5,
<<ThisRef:32/?UI,Pos:32/?UI,Toolid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8,BitmapRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxToolBar()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarrealize">external documentation</a>.
+-spec realize(This) -> boolean() when
+ This::wxToolBar().
realize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_Realize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer()) -> wx:wx()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarremovetool">external documentation</a>.
+-spec removeTool(This, Toolid) -> wx:wx_object() when
+ This::wxToolBar(), Toolid::integer().
removeTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid)
when is_integer(Toolid) ->
?CLASS(ThisT,wxToolBar),
wxe_util:call(?wxToolBar_RemoveTool,
<<ThisRef:32/?UI,Toolid:32/?UI>>).
-%% @spec (This::wxToolBar(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsetmargins">external documentation</a>.
+-spec setMargins(This, X, Y) -> ok when
+ This::wxToolBar(), X::integer(), Y::integer().
setMargins(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxToolBar),
wxe_util:cast(?wxToolBar_SetMargins,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxToolBar(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsettoolbitmapsize">external documentation</a>.
+-spec setToolBitmapSize(This, Size) -> ok when
+ This::wxToolBar(), Size::{W::integer(), H::integer()}.
setToolBitmapSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxToolBar),
wxe_util:cast(?wxToolBar_SetToolBitmapSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), HelpString::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsettoollonghelp">external documentation</a>.
+-spec setToolLongHelp(This, Toolid, HelpString) -> ok when
+ This::wxToolBar(), Toolid::integer(), HelpString::unicode:chardata().
setToolLongHelp(#wx_ref{type=ThisT,ref=ThisRef},Toolid,HelpString)
when is_integer(Toolid),is_list(HelpString) ->
?CLASS(ThisT,wxToolBar),
@@ -521,16 +610,18 @@ setToolLongHelp(#wx_ref{type=ThisT,ref=ThisRef},Toolid,HelpString)
wxe_util:cast(?wxToolBar_SetToolLongHelp,
<<ThisRef:32/?UI,Toolid:32/?UI,(byte_size(HelpString_UC)):32/?UI,(HelpString_UC)/binary, 0:(((8- ((4+byte_size(HelpString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxToolBar(), Packing::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsettoolpacking">external documentation</a>.
+-spec setToolPacking(This, Packing) -> ok when
+ This::wxToolBar(), Packing::integer().
setToolPacking(#wx_ref{type=ThisT,ref=ThisRef},Packing)
when is_integer(Packing) ->
?CLASS(ThisT,wxToolBar),
wxe_util:cast(?wxToolBar_SetToolPacking,
<<ThisRef:32/?UI,Packing:32/?UI>>).
-%% @spec (This::wxToolBar(), Id::integer(), HelpString::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsettoolshorthelp">external documentation</a>.
+-spec setToolShortHelp(This, Id, HelpString) -> ok when
+ This::wxToolBar(), Id::integer(), HelpString::unicode:chardata().
setToolShortHelp(#wx_ref{type=ThisT,ref=ThisRef},Id,HelpString)
when is_integer(Id),is_list(HelpString) ->
?CLASS(ThisT,wxToolBar),
@@ -538,16 +629,18 @@ setToolShortHelp(#wx_ref{type=ThisT,ref=ThisRef},Id,HelpString)
wxe_util:cast(?wxToolBar_SetToolShortHelp,
<<ThisRef:32/?UI,Id:32/?UI,(byte_size(HelpString_UC)):32/?UI,(HelpString_UC)/binary, 0:(((8- ((4+byte_size(HelpString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxToolBar(), Separation::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbarsettoolseparation">external documentation</a>.
+-spec setToolSeparation(This, Separation) -> ok when
+ This::wxToolBar(), Separation::integer().
setToolSeparation(#wx_ref{type=ThisT,ref=ThisRef},Separation)
when is_integer(Separation) ->
?CLASS(ThisT,wxToolBar),
wxe_util:cast(?wxToolBar_SetToolSeparation,
<<ThisRef:32/?UI,Separation:32/?UI>>).
-%% @spec (This::wxToolBar(), Toolid::integer(), Toggle::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbar.html#wxtoolbartoggletool">external documentation</a>.
+-spec toggleTool(This, Toolid, Toggle) -> ok when
+ This::wxToolBar(), Toolid::integer(), Toggle::boolean().
toggleTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Toggle)
when is_integer(Toolid),is_boolean(Toggle) ->
?CLASS(ThisT,wxToolBar),
diff --git a/lib/wx/src/gen/wxToolTip.erl b/lib/wx/src/gen/wxToolTip.erl
index b0749c851a..e9b5510357 100644
--- a/lib/wx/src/gen/wxToolTip.erl
+++ b/lib/wx/src/gen/wxToolTip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,33 +29,39 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxToolTip/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Flag::bool()) -> ok
+-type wxToolTip() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtooltip.html#wxtooltipenable">external documentation</a>.
+-spec enable(Flag) -> ok when
+ Flag::boolean().
enable(Flag)
when is_boolean(Flag) ->
wxe_util:cast(?wxToolTip_Enable,
<<(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec (Msecs::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtooltip.html#wxtooltipsetdelay">external documentation</a>.
+-spec setDelay(Msecs) -> ok when
+ Msecs::integer().
setDelay(Msecs)
when is_integer(Msecs) ->
wxe_util:cast(?wxToolTip_SetDelay,
<<Msecs:32/?UI>>).
-%% @spec (Tip::string()) -> wxToolTip()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtooltip.html#wxtooltipwxtooltip">external documentation</a>.
+-spec new(Tip) -> wxToolTip() when
+ Tip::unicode:chardata().
new(Tip)
when is_list(Tip) ->
Tip_UC = unicode:characters_to_binary([Tip,0]),
wxe_util:construct(?wxToolTip_new,
<<(byte_size(Tip_UC)):32/?UI,(Tip_UC)/binary, 0:(((8- ((4+byte_size(Tip_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxToolTip(), Tip::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtooltip.html#wxtooltipsettip">external documentation</a>.
+-spec setTip(This, Tip) -> ok when
+ This::wxToolTip(), Tip::unicode:chardata().
setTip(#wx_ref{type=ThisT,ref=ThisRef},Tip)
when is_list(Tip) ->
?CLASS(ThisT,wxToolTip),
@@ -63,22 +69,24 @@ setTip(#wx_ref{type=ThisT,ref=ThisRef},Tip)
wxe_util:cast(?wxToolTip_SetTip,
<<ThisRef:32/?UI,(byte_size(Tip_UC)):32/?UI,(Tip_UC)/binary, 0:(((8- ((0+byte_size(Tip_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxToolTip()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtooltip.html#wxtooltipgettip">external documentation</a>.
+-spec getTip(This) -> unicode:charlist() when
+ This::wxToolTip().
getTip(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolTip),
wxe_util:call(?wxToolTip_GetTip,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolTip()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtooltip.html#wxtooltipgetwindow">external documentation</a>.
+-spec getWindow(This) -> wxWindow:wxWindow() when
+ This::wxToolTip().
getWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolTip),
wxe_util:call(?wxToolTip_GetWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolTip()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxToolTip()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxToolTip),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxToolbook.erl b/lib/wx/src/gen/wxToolbook.erl
index 4d188e979d..9172f7a2d9 100644
--- a/lib/wx/src/gen/wxToolbook.erl
+++ b/lib/wx/src/gen/wxToolbook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -74,27 +74,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxToolbook/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxToolbook()
+-type wxToolbook() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookwxtoolbook">external documentation</a>.
+-spec new() -> wxToolbook().
new() ->
wxe_util:construct(?wxToolbook_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxToolbook()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxToolbook() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxToolbook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookwxtoolbook">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxToolbook() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -106,15 +113,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxToolbook_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxToolbook(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv addPage(This,Page,Text, [])
+-spec addPage(This, Page, Text) -> boolean() when
+ This::wxToolbook(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
addPage(This,Page,Text)
when is_record(This, wx_ref),is_record(Page, wx_ref),is_list(Text) ->
addPage(This,Page,Text, []).
-%% @spec (This::wxToolbook(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookaddpage">external documentation</a>.
+-spec addPage(This, Page, Text, [Option]) -> boolean() when
+ This::wxToolbook(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxToolbook),
@@ -127,15 +138,18 @@ addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Op
wxe_util:call(?wxToolbook_AddPage,
<<ThisRef:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxToolbook()) -> ok
%% @equiv advanceSelection(This, [])
+-spec advanceSelection(This) -> ok when
+ This::wxToolbook().
+
advanceSelection(This)
when is_record(This, wx_ref) ->
advanceSelection(This, []).
-%% @spec (This::wxToolbook(), [Option]) -> ok
-%% Option = {forward, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookadvanceselection">external documentation</a>.
+-spec advanceSelection(This, [Option]) -> ok when
+ This::wxToolbook(),
+ Option :: {forward, boolean()}.
advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxToolbook),
@@ -145,23 +159,29 @@ advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxToolbook_AdvanceSelection,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxToolbook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList) -> ok when
+ This::wxToolbook(), ImageList::wxImageList:wxImageList().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxToolbook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxToolbook_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxToolbook(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxToolbook(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxToolbook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxToolbook(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxToolbook),
@@ -174,98 +194,114 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxToolbook_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxToolbook()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookdeleteallpages">external documentation</a>.
+-spec deleteAllPages(This) -> boolean() when
+ This::wxToolbook().
deleteAllPages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_DeleteAllPages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookdeletepage">external documentation</a>.
+-spec deletePage(This, N) -> boolean() when
+ This::wxToolbook(), N::integer().
deletePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_DeletePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookremovepage">external documentation</a>.
+-spec removePage(This, N) -> boolean() when
+ This::wxToolbook(), N::integer().
removePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_RemovePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetcurrentpage">external documentation</a>.
+-spec getCurrentPage(This) -> wxWindow:wxWindow() when
+ This::wxToolbook().
getCurrentPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetCurrentPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolbook()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetimagelist">external documentation</a>.
+-spec getImageList(This) -> wxImageList:wxImageList() when
+ This::wxToolbook().
getImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetpage">external documentation</a>.
+-spec getPage(This, N) -> wxWindow:wxWindow() when
+ This::wxToolbook(), N::integer().
getPage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetPage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetpagecount">external documentation</a>.
+-spec getPageCount(This) -> integer() when
+ This::wxToolbook().
getPageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetPageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetpageimage">external documentation</a>.
+-spec getPageImage(This, N) -> integer() when
+ This::wxToolbook(), N::integer().
getPageImage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetPageImage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetpagetext">external documentation</a>.
+-spec getPageText(This, N) -> unicode:charlist() when
+ This::wxToolbook(), N::integer().
getPageText(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetPageText,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxToolbook().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxToolbook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookhittest">external documentation</a>.
+-spec hitTest(This, Pt) -> Result when
+ Result ::{Res ::integer(), Flags::integer()},
+ This::wxToolbook(), Pt::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_HitTest,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv insertPage(This,N,Page,Text, [])
+-spec insertPage(This, N, Page, Text) -> boolean() when
+ This::wxToolbook(), N::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
insertPage(This,N,Page,Text)
when is_record(This, wx_ref),is_integer(N),is_record(Page, wx_ref),is_list(Text) ->
insertPage(This,N,Page,Text, []).
-%% @spec (This::wxToolbook(), N::integer(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookinsertpage">external documentation</a>.
+-spec insertPage(This, N, Page, Text, [Option]) -> boolean() when
+ This::wxToolbook(), N::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
insertPage(#wx_ref{type=ThisT,ref=ThisRef},N,#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_integer(N),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxToolbook),
@@ -278,32 +314,36 @@ insertPage(#wx_ref{type=ThisT,ref=ThisRef},N,#wx_ref{type=PageT,ref=PageRef},Tex
wxe_util:call(?wxToolbook_InsertPage,
<<ThisRef:32/?UI,N:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxToolbook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbooksetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList) -> ok when
+ This::wxToolbook(), ImageList::wxImageList:wxImageList().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxToolbook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxToolbook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxToolbook(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbooksetpagesize">external documentation</a>.
+-spec setPageSize(This, Size) -> ok when
+ This::wxToolbook(), Size::{W::integer(), H::integer()}.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxToolbook),
wxe_util:cast(?wxToolbook_SetPageSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer(), ImageId::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbooksetpageimage">external documentation</a>.
+-spec setPageImage(This, N, ImageId) -> boolean() when
+ This::wxToolbook(), N::integer(), ImageId::integer().
setPageImage(#wx_ref{type=ThisT,ref=ThisRef},N,ImageId)
when is_integer(N),is_integer(ImageId) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_SetPageImage,
<<ThisRef:32/?UI,N:32/?UI,ImageId:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer(), StrText::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbooksetpagetext">external documentation</a>.
+-spec setPageText(This, N, StrText) -> boolean() when
+ This::wxToolbook(), N::integer(), StrText::unicode:chardata().
setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
when is_integer(N),is_list(StrText) ->
?CLASS(ThisT,wxToolbook),
@@ -311,24 +351,26 @@ setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
wxe_util:call(?wxToolbook_SetPageText,
<<ThisRef:32/?UI,N:32/?UI,(byte_size(StrText_UC)):32/?UI,(StrText_UC)/binary, 0:(((8- ((4+byte_size(StrText_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxToolbook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbooksetselection">external documentation</a>.
+-spec setSelection(This, N) -> integer() when
+ This::wxToolbook(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_SetSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoolbook.html#wxtoolbookchangeselection">external documentation</a>.
+-spec changeSelection(This, N) -> integer() when
+ This::wxToolbook(), N::integer().
changeSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxToolbook),
wxe_util:call(?wxToolbook_ChangeSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxToolbook()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxToolbook()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxToolbook),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxTopLevelWindow.erl b/lib/wx/src/gen/wxTopLevelWindow.erl
index e0551b480f..5659c0927f 100644
--- a/lib/wx/src/gen/wxTopLevelWindow.erl
+++ b/lib/wx/src/gen/wxTopLevelWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,48 +72,57 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxTopLevelWindow/0]).
%% @hidden
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxTopLevelWindow()) -> wxIcon:wxIcon()
+-type wxTopLevelWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowgeticon">external documentation</a>.
+-spec getIcon(This) -> wxIcon:wxIcon() when
+ This::wxTopLevelWindow().
getIcon(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_GetIcon,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> wxIconBundle:wxIconBundle()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowgeticons">external documentation</a>.
+-spec getIcons(This) -> wxIconBundle:wxIconBundle() when
+ This::wxTopLevelWindow().
getIcons(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_GetIcons,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowgettitle">external documentation</a>.
+-spec getTitle(This) -> unicode:charlist() when
+ This::wxTopLevelWindow().
getTitle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_GetTitle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowisactive">external documentation</a>.
+-spec isActive(This) -> boolean() when
+ This::wxTopLevelWindow().
isActive(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_IsActive,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> ok
%% @equiv iconize(This, [])
+-spec iconize(This) -> ok when
+ This::wxTopLevelWindow().
+
iconize(This)
when is_record(This, wx_ref) ->
iconize(This, []).
-%% @spec (This::wxTopLevelWindow(), [Option]) -> ok
-%% Option = {iconize, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowiconize">external documentation</a>.
+-spec iconize(This, [Option]) -> ok when
+ This::wxTopLevelWindow(),
+ Option :: {iconize, boolean()}.
iconize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTopLevelWindow),
@@ -123,36 +132,42 @@ iconize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxTopLevelWindow_Iconize,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTopLevelWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowisfullscreen">external documentation</a>.
+-spec isFullScreen(This) -> boolean() when
+ This::wxTopLevelWindow().
isFullScreen(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_IsFullScreen,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowisiconized">external documentation</a>.
+-spec isIconized(This) -> boolean() when
+ This::wxTopLevelWindow().
isIconized(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_IsIconized,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowismaximized">external documentation</a>.
+-spec isMaximized(This) -> boolean() when
+ This::wxTopLevelWindow().
isMaximized(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
wxe_util:call(?wxTopLevelWindow_IsMaximized,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> ok
%% @equiv maximize(This, [])
+-spec maximize(This) -> ok when
+ This::wxTopLevelWindow().
+
maximize(This)
when is_record(This, wx_ref) ->
maximize(This, []).
-%% @spec (This::wxTopLevelWindow(), [Option]) -> ok
-%% Option = {maximize, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowmaximize">external documentation</a>.
+-spec maximize(This, [Option]) -> ok when
+ This::wxTopLevelWindow(),
+ Option :: {maximize, boolean()}.
maximize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTopLevelWindow),
@@ -162,15 +177,18 @@ maximize(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxTopLevelWindow_Maximize,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTopLevelWindow()) -> ok
%% @equiv requestUserAttention(This, [])
+-spec requestUserAttention(This) -> ok when
+ This::wxTopLevelWindow().
+
requestUserAttention(This)
when is_record(This, wx_ref) ->
requestUserAttention(This, []).
-%% @spec (This::wxTopLevelWindow(), [Option]) -> ok
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowrequestuserattention">external documentation</a>.
+-spec requestUserAttention(This, [Option]) -> ok when
+ This::wxTopLevelWindow(),
+ Option :: {flags, integer()}.
requestUserAttention(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTopLevelWindow),
@@ -180,31 +198,36 @@ requestUserAttention(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxTopLevelWindow_RequestUserAttention,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTopLevelWindow(), Icon::wxIcon:wxIcon()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowseticon">external documentation</a>.
+-spec setIcon(This, Icon) -> ok when
+ This::wxTopLevelWindow(), Icon::wxIcon:wxIcon().
setIcon(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconT,ref=IconRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
?CLASS(IconT,wxIcon),
wxe_util:cast(?wxTopLevelWindow_SetIcon,
<<ThisRef:32/?UI,IconRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow(), Icons::wxIconBundle:wxIconBundle()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowseticons">external documentation</a>.
+-spec setIcons(This, Icons) -> ok when
+ This::wxTopLevelWindow(), Icons::wxIconBundle:wxIconBundle().
setIcons(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=IconsT,ref=IconsRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
?CLASS(IconsT,wxIconBundle),
wxe_util:cast(?wxTopLevelWindow_SetIcons,
<<ThisRef:32/?UI,IconsRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow()) -> ok
%% @equiv centerOnScreen(This, [])
+-spec centerOnScreen(This) -> ok when
+ This::wxTopLevelWindow().
+
centerOnScreen(This)
when is_record(This, wx_ref) ->
centerOnScreen(This, []).
-%% @spec (This::wxTopLevelWindow(), [Option]) -> ok
-%% Option = {dir, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowcenteronscreen">external documentation</a>.
+-spec centerOnScreen(This, [Option]) -> ok when
+ This::wxTopLevelWindow(),
+ Option :: {dir, integer()}.
centerOnScreen(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTopLevelWindow),
@@ -214,15 +237,18 @@ centerOnScreen(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxTopLevelWindow_CenterOnScreen,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTopLevelWindow()) -> ok
%% @equiv centreOnScreen(This, [])
+-spec centreOnScreen(This) -> ok when
+ This::wxTopLevelWindow().
+
centreOnScreen(This)
when is_record(This, wx_ref) ->
centreOnScreen(This, []).
-%% @spec (This::wxTopLevelWindow(), [Option]) -> ok
-%% Option = {dir, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowcentreonscreen">external documentation</a>.
+-spec centreOnScreen(This, [Option]) -> ok when
+ This::wxTopLevelWindow(),
+ Option :: {dir, integer()}.
centreOnScreen(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTopLevelWindow),
@@ -232,16 +258,18 @@ centreOnScreen(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxTopLevelWindow_CentreOnScreen,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTopLevelWindow(), Region::wxRegion:wxRegion()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowsetshape">external documentation</a>.
+-spec setShape(This, Region) -> boolean() when
+ This::wxTopLevelWindow(), Region::wxRegion:wxRegion().
setShape(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=RegionT,ref=RegionRef}) ->
?CLASS(ThisT,wxTopLevelWindow),
?CLASS(RegionT,wxRegion),
wxe_util:call(?wxTopLevelWindow_SetShape,
<<ThisRef:32/?UI,RegionRef:32/?UI>>).
-%% @spec (This::wxTopLevelWindow(), Title::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowsettitle">external documentation</a>.
+-spec setTitle(This, Title) -> ok when
+ This::wxTopLevelWindow(), Title::unicode:chardata().
setTitle(#wx_ref{type=ThisT,ref=ThisRef},Title)
when is_list(Title) ->
?CLASS(ThisT,wxTopLevelWindow),
@@ -249,15 +277,18 @@ setTitle(#wx_ref{type=ThisT,ref=ThisRef},Title)
wxe_util:cast(?wxTopLevelWindow_SetTitle,
<<ThisRef:32/?UI,(byte_size(Title_UC)):32/?UI,(Title_UC)/binary, 0:(((8- ((0+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTopLevelWindow(), Show::bool()) -> bool()
%% @equiv showFullScreen(This,Show, [])
+-spec showFullScreen(This, Show) -> boolean() when
+ This::wxTopLevelWindow(), Show::boolean().
+
showFullScreen(This,Show)
when is_record(This, wx_ref),is_boolean(Show) ->
showFullScreen(This,Show, []).
-%% @spec (This::wxTopLevelWindow(), Show::bool(), [Option]) -> bool()
-%% Option = {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtoplevelwindow.html#wxtoplevelwindowshowfullscreen">external documentation</a>.
+-spec showFullScreen(This, Show, [Option]) -> boolean() when
+ This::wxTopLevelWindow(), Show::boolean(),
+ Option :: {style, integer()}.
showFullScreen(#wx_ref{type=ThisT,ref=ThisRef},Show, Options)
when is_boolean(Show),is_list(Options) ->
?CLASS(ThisT,wxTopLevelWindow),
diff --git a/lib/wx/src/gen/wxTreeCtrl.erl b/lib/wx/src/gen/wxTreeCtrl.erl
index e3fe4c9612..dfa9e691ce 100644
--- a/lib/wx/src/gen/wxTreeCtrl.erl
+++ b/lib/wx/src/gen/wxTreeCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -89,27 +89,36 @@
show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,update/1,
updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxTreeCtrl/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxTreeCtrl()
+-type wxTreeCtrl() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlwxtreectrl">external documentation</a>.
+-spec new() -> wxTreeCtrl().
new() ->
wxe_util:construct(?wxTreeCtrl_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow()) -> wxTreeCtrl()
%% @equiv new(Parent, [])
+-spec new(Parent) -> wxTreeCtrl() when
+ Parent::wxWindow:wxWindow().
+
new(Parent)
when is_record(Parent, wx_ref) ->
new(Parent, []).
-%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxTreeCtrl()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlwxtreectrl">external documentation</a>.
+-spec new(Parent, [Option]) -> wxTreeCtrl() when
+ Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -123,15 +132,20 @@ new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
wxe_util:construct(?wxTreeCtrl_new_2,
<<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Text::string()) -> integer()
%% @equiv addRoot(This,Text, [])
+-spec addRoot(This, Text) -> integer() when
+ This::wxTreeCtrl(), Text::unicode:chardata().
+
addRoot(This,Text)
when is_record(This, wx_ref),is_list(Text) ->
addRoot(This,Text, []).
-%% @spec (This::wxTreeCtrl(), Text::string(), [Option]) -> integer()
-%% Option = {image, integer()} | {selectedImage, integer()} | {data, term()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrladdroot">external documentation</a>.
+-spec addRoot(This, Text, [Option]) -> integer() when
+ This::wxTreeCtrl(), Text::unicode:chardata(),
+ Option :: {image, integer()}
+ | {selectedImage, integer()}
+ | {data, term()}.
addRoot(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -144,15 +158,20 @@ addRoot(#wx_ref{type=ThisT,ref=ThisRef},Text, Options)
wxe_util:call(?wxTreeCtrl_AddRoot,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Parent::integer(), Text::string()) -> integer()
%% @equiv appendItem(This,Parent,Text, [])
+-spec appendItem(This, Parent, Text) -> integer() when
+ This::wxTreeCtrl(), Parent::integer(), Text::unicode:chardata().
+
appendItem(This,Parent,Text)
when is_record(This, wx_ref),is_integer(Parent),is_list(Text) ->
appendItem(This,Parent,Text, []).
-%% @spec (This::wxTreeCtrl(), Parent::integer(), Text::string(), [Option]) -> integer()
-%% Option = {image, integer()} | {selectedImage, integer()} | {data, term()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlappenditem">external documentation</a>.
+-spec appendItem(This, Parent, Text, [Option]) -> integer() when
+ This::wxTreeCtrl(), Parent::integer(), Text::unicode:chardata(),
+ Option :: {image, integer()}
+ | {selectedImage, integer()}
+ | {data, term()}.
appendItem(#wx_ref{type=ThisT,ref=ThisRef},Parent,Text, Options)
when is_integer(Parent),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -165,47 +184,58 @@ appendItem(#wx_ref{type=ThisT,ref=ThisRef},Parent,Text, Options)
wxe_util:call(?wxTreeCtrl_AppendItem,
<<ThisRef:32/?UI,0:32,Parent:64/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList) -> ok when
+ This::wxTreeCtrl(), ImageList::wxImageList:wxImageList().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxTreeCtrl),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxTreeCtrl_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlassignstateimagelist">external documentation</a>.
+-spec assignStateImageList(This, ImageList) -> ok when
+ This::wxTreeCtrl(), ImageList::wxImageList:wxImageList().
assignStateImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxTreeCtrl),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxTreeCtrl_AssignStateImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlcollapse">external documentation</a>.
+-spec collapse(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
collapse(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_Collapse,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlcollapseandreset">external documentation</a>.
+-spec collapseAndReset(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
collapseAndReset(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_CollapseAndReset,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
+-spec create(This, Parent) -> boolean() when
+ This::wxTreeCtrl(), Parent::wxWindow:wxWindow().
+
create(This,Parent)
when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
create(This,Parent, []).
-%% @spec (This::wxTreeCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {id, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlcreate">external documentation</a>.
+-spec create(This, Parent, [Option]) -> boolean() when
+ This::wxTreeCtrl(), Parent::wxWindow:wxWindow(),
+ Option :: {id, integer()}
+ | {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}
+ | {validator, wx:wx_object()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -220,62 +250,71 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Opti
wxe_util:call(?wxTreeCtrl_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrldelete">external documentation</a>.
+-spec delete(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
delete(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_Delete,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrldeleteallitems">external documentation</a>.
+-spec deleteAllItems(This) -> ok when
+ This::wxTreeCtrl().
deleteAllItems(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_DeleteAllItems,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrldeletechildren">external documentation</a>.
+-spec deleteChildren(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
deleteChildren(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_DeleteChildren,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> wxTextCtrl:wxTextCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrleditlabel">external documentation</a>.
+-spec editLabel(This, Item) -> wxTextCtrl:wxTextCtrl() when
+ This::wxTreeCtrl(), Item::integer().
editLabel(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_EditLabel,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlensurevisible">external documentation</a>.
+-spec ensureVisible(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
ensureVisible(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_EnsureVisible,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlexpand">external documentation</a>.
+-spec expand(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
expand(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_Expand,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool()
%% @equiv getBoundingRect(This,Item,Rect, [])
+-spec getBoundingRect(This, Item, Rect) -> boolean() when
+ This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
+
getBoundingRect(This,Item,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_integer(Item),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
getBoundingRect(This,Item,Rect, []).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> bool()
-%% Option = {textOnly, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetboundingrect">external documentation</a>.
+-spec getBoundingRect(This, Item, Rect, [Option]) -> boolean() when
+ This::wxTreeCtrl(), Item::integer(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()},
+ Option :: {textOnly, boolean()}.
getBoundingRect(#wx_ref{type=ThisT,ref=ThisRef},Item,{RectX,RectY,RectW,RectH}, Options)
when is_integer(Item),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -285,15 +324,18 @@ getBoundingRect(#wx_ref{type=ThisT,ref=ThisRef},Item,{RectX,RectY,RectW,RectH},
wxe_util:call(?wxTreeCtrl_GetBoundingRect,
<<ThisRef:32/?UI,0:32,Item:64/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @equiv getChildrenCount(This,Item, [])
+-spec getChildrenCount(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
+
getChildrenCount(This,Item)
when is_record(This, wx_ref),is_integer(Item) ->
getChildrenCount(This,Item, []).
-%% @spec (This::wxTreeCtrl(), Item::integer(), [Option]) -> integer()
-%% Option = {recursively, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetchildrencount">external documentation</a>.
+-spec getChildrenCount(This, Item, [Option]) -> integer() when
+ This::wxTreeCtrl(), Item::integer(),
+ Option :: {recursively, boolean()}.
getChildrenCount(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -303,94 +345,107 @@ getChildrenCount(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:call(?wxTreeCtrl_GetChildrenCount,
<<ThisRef:32/?UI,0:32,Item:64/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetcount">external documentation</a>.
+-spec getCount(This) -> integer() when
+ This::wxTreeCtrl().
getCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> wxTextCtrl:wxTextCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgeteditcontrol">external documentation</a>.
+-spec getEditControl(This) -> wxTextCtrl:wxTextCtrl() when
+ This::wxTreeCtrl().
getEditControl(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetEditControl,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> {integer(),Cookie::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetfirstchild">external documentation</a>.
+-spec getFirstChild(This, Item) -> Result when
+ Result ::{Res ::integer(), Cookie::integer()},
+ This::wxTreeCtrl(), Item::integer().
getFirstChild(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetFirstChild,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Cookie::integer()) -> {integer(),Cookie::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetnextchild">external documentation</a>.
+-spec getNextChild(This, Item, Cookie) -> Result when
+ Result ::{Res ::integer(), Cookie::integer()},
+ This::wxTreeCtrl(), Item::integer(), Cookie::integer().
getNextChild(#wx_ref{type=ThisT,ref=ThisRef},Item,Cookie)
when is_integer(Item),is_integer(Cookie) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetNextChild,
<<ThisRef:32/?UI,0:32,Item:64/?UI,Cookie:64/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetfirstvisibleitem">external documentation</a>.
+-spec getFirstVisibleItem(This) -> integer() when
+ This::wxTreeCtrl().
getFirstVisibleItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetFirstVisibleItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetimagelist">external documentation</a>.
+-spec getImageList(This) -> wxImageList:wxImageList() when
+ This::wxTreeCtrl().
getImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetindent">external documentation</a>.
+-spec getIndent(This) -> integer() when
+ This::wxTreeCtrl().
getIndent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetIndent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitembackgroundcolour">external documentation</a>.
+-spec getItemBackgroundColour(This, Item) -> wx:wx_colour4() when
+ This::wxTreeCtrl(), Item::integer().
getItemBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemBackgroundColour,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> term()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemdata">external documentation</a>.
+-spec getItemData(This, Item) -> term() when
+ This::wxTreeCtrl(), Item::integer().
getItemData(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemData,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemfont">external documentation</a>.
+-spec getItemFont(This, Item) -> wxFont:wxFont() when
+ This::wxTreeCtrl(), Item::integer().
getItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemFont,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemimage">external documentation</a>.
+-spec getItemImage(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemImage_1,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), [Option]) -> integer()
-%% Option = {which, WxTreeItemIcon}
-%% WxTreeItemIcon = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemimage">external documentation</a>.
-%%<br /> WxTreeItemIcon is one of ?wxTreeItemIcon_Normal | ?wxTreeItemIcon_Selected | ?wxTreeItemIcon_Expanded | ?wxTreeItemIcon_SelectedExpanded | ?wxTreeItemIcon_Max
+%%<br /> Which = ?wxTreeItemIcon_Normal | ?wxTreeItemIcon_Selected | ?wxTreeItemIcon_Expanded | ?wxTreeItemIcon_SelectedExpanded | ?wxTreeItemIcon_Max
+-spec getItemImage(This, Item, [Option]) -> integer() when
+ This::wxTreeCtrl(), Item::integer(),
+ Option :: {which, wx:wx_enum()}.
getItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -400,115 +455,134 @@ getItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:call(?wxTreeCtrl_GetItemImage_2,
<<ThisRef:32/?UI,0:32,Item:64/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemtext">external documentation</a>.
+-spec getItemText(This, Item) -> unicode:charlist() when
+ This::wxTreeCtrl(), Item::integer().
getItemText(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemText,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemtextcolour">external documentation</a>.
+-spec getItemTextColour(This, Item) -> wx:wx_colour4() when
+ This::wxTreeCtrl(), Item::integer().
getItemTextColour(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemTextColour,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetlastchild">external documentation</a>.
+-spec getLastChild(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getLastChild(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetLastChild,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetnextsibling">external documentation</a>.
+-spec getNextSibling(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getNextSibling(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetNextSibling,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetnextvisible">external documentation</a>.
+-spec getNextVisible(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getNextVisible(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetNextVisible,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetitemparent">external documentation</a>.
+-spec getItemParent(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getItemParent(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetItemParent,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetprevsibling">external documentation</a>.
+-spec getPrevSibling(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getPrevSibling(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetPrevSibling,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetprevvisible">external documentation</a>.
+-spec getPrevVisible(This, Item) -> integer() when
+ This::wxTreeCtrl(), Item::integer().
getPrevVisible(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetPrevVisible,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetrootitem">external documentation</a>.
+-spec getRootItem(This) -> integer() when
+ This::wxTreeCtrl().
getRootItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetRootItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxTreeCtrl().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> {integer(),Val::[integer()]}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetselections">external documentation</a>.
+-spec getSelections(This) -> Result when
+ Result ::{Res ::integer(), Val::[integer()]},
+ This::wxTreeCtrl().
getSelections(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetSelections,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlgetstateimagelist">external documentation</a>.
+-spec getStateImageList(This) -> wxImageList:wxImageList() when
+ This::wxTreeCtrl().
getStateImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_GetStateImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Point::{X::integer(),Y::integer()}) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlhittest">external documentation</a>.
+-spec hitTest(This, Point) -> integer() when
+ This::wxTreeCtrl(), Point::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
when is_integer(PointX),is_integer(PointY) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_HitTest,
<<ThisRef:32/?UI,PointX:32/?UI,PointY:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Parent::integer(), Pos::integer(), Text::string()) -> integer()
%% @equiv insertItem(This,Parent,Pos,Text, [])
+-spec insertItem(This, Parent, Pos, Text) -> integer() when
+ This::wxTreeCtrl(), Parent::integer(), Pos::integer(), Text::unicode:chardata().
+
insertItem(This,Parent,Pos,Text)
when is_record(This, wx_ref),is_integer(Parent),is_integer(Pos),is_list(Text) ->
insertItem(This,Parent,Pos,Text, []).
-%% @spec (This::wxTreeCtrl(), Parent::integer(), Pos::integer(), Text::string(), [Option]) -> integer()
-%% Option = {image, integer()} | {selImage, integer()} | {data, term()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlinsertitem">external documentation</a>.
+-spec insertItem(This, Parent, Pos, Text, [Option]) -> integer() when
+ This::wxTreeCtrl(), Parent::integer(), Pos::integer(), Text::unicode:chardata(),
+ Option :: {image, integer()}
+ | {selImage, integer()}
+ | {data, term()}.
insertItem(#wx_ref{type=ThisT,ref=ThisRef},Parent,Pos,Text, Options)
when is_integer(Parent),is_integer(Pos),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -521,55 +595,65 @@ insertItem(#wx_ref{type=ThisT,ref=ThisRef},Parent,Pos,Text, Options)
wxe_util:call(?wxTreeCtrl_InsertItem,
<<ThisRef:32/?UI,0:32,Parent:64/?UI,Pos:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlisbold">external documentation</a>.
+-spec isBold(This, Item) -> boolean() when
+ This::wxTreeCtrl(), Item::integer().
isBold(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_IsBold,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlisexpanded">external documentation</a>.
+-spec isExpanded(This, Item) -> boolean() when
+ This::wxTreeCtrl(), Item::integer().
isExpanded(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_IsExpanded,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlisselected">external documentation</a>.
+-spec isSelected(This, Item) -> boolean() when
+ This::wxTreeCtrl(), Item::integer().
isSelected(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_IsSelected,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlisvisible">external documentation</a>.
+-spec isVisible(This, Item) -> boolean() when
+ This::wxTreeCtrl(), Item::integer().
isVisible(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_IsVisible,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlitemhaschildren">external documentation</a>.
+-spec itemHasChildren(This, Item) -> boolean() when
+ This::wxTreeCtrl(), Item::integer().
itemHasChildren(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:call(?wxTreeCtrl_ItemHasChildren,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Parent::integer(), Text::string()) -> integer()
%% @equiv prependItem(This,Parent,Text, [])
+-spec prependItem(This, Parent, Text) -> integer() when
+ This::wxTreeCtrl(), Parent::integer(), Text::unicode:chardata().
+
prependItem(This,Parent,Text)
when is_record(This, wx_ref),is_integer(Parent),is_list(Text) ->
prependItem(This,Parent,Text, []).
-%% @spec (This::wxTreeCtrl(), Parent::integer(), Text::string(), [Option]) -> integer()
-%% Option = {image, integer()} | {selectedImage, integer()} | {data, term()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlprependitem">external documentation</a>.
+-spec prependItem(This, Parent, Text, [Option]) -> integer() when
+ This::wxTreeCtrl(), Parent::integer(), Text::unicode:chardata(),
+ Option :: {image, integer()}
+ | {selectedImage, integer()}
+ | {data, term()}.
prependItem(#wx_ref{type=ThisT,ref=ThisRef},Parent,Text, Options)
when is_integer(Parent),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -582,25 +666,28 @@ prependItem(#wx_ref{type=ThisT,ref=ThisRef},Parent,Text, Options)
wxe_util:call(?wxTreeCtrl_PrependItem,
<<ThisRef:32/?UI,0:32,Parent:64/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlscrollto">external documentation</a>.
+-spec scrollTo(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
scrollTo(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_ScrollTo,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlselectitem">external documentation</a>.
+-spec selectItem(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
selectItem(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SelectItem_1,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), [Option]) -> ok
-%% Option = {select, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlselectitem">external documentation</a>.
+-spec selectItem(This, Item, [Option]) -> ok when
+ This::wxTreeCtrl(), Item::integer(),
+ Option :: {select, boolean()}.
selectItem(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -610,39 +697,45 @@ selectItem(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:cast(?wxTreeCtrl_SelectItem_2,
<<ThisRef:32/?UI,0:32,Item:64/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Indent::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetindent">external documentation</a>.
+-spec setIndent(This, Indent) -> ok when
+ This::wxTreeCtrl(), Indent::integer().
setIndent(#wx_ref{type=ThisT,ref=ThisRef},Indent)
when is_integer(Indent) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SetIndent,
<<ThisRef:32/?UI,Indent:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList) -> ok when
+ This::wxTreeCtrl(), ImageList::wxImageList:wxImageList().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxTreeCtrl),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxTreeCtrl_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitembackgroundcolour">external documentation</a>.
+-spec setItemBackgroundColour(This, Item, Col) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Col::wx:wx_colour().
setItemBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Item,Col)
when is_integer(Item),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SetItemBackgroundColour,
<<ThisRef:32/?UI,0:32,Item:64/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @equiv setItemBold(This,Item, [])
+-spec setItemBold(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
+
setItemBold(This,Item)
when is_record(This, wx_ref),is_integer(Item) ->
setItemBold(This,Item, []).
-%% @spec (This::wxTreeCtrl(), Item::integer(), [Option]) -> ok
-%% Option = {bold, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitembold">external documentation</a>.
+-spec setItemBold(This, Item, [Option]) -> ok when
+ This::wxTreeCtrl(), Item::integer(),
+ Option :: {bold, boolean()}.
setItemBold(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -652,8 +745,9 @@ setItemBold(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:cast(?wxTreeCtrl_SetItemBold,
<<ThisRef:32/?UI,0:32,Item:64/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Data::term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemdata">external documentation</a>.
+-spec setItemData(This, Item, Data) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Data::term().
setItemData(#wx_ref{type=ThisT,ref=ThisRef},Item,Data)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -661,15 +755,18 @@ setItemData(#wx_ref{type=ThisT,ref=ThisRef},Item,Data)
wxe_util:cast(?wxTreeCtrl_SetItemData,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @equiv setItemDropHighlight(This,Item, [])
+-spec setItemDropHighlight(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
+
setItemDropHighlight(This,Item)
when is_record(This, wx_ref),is_integer(Item) ->
setItemDropHighlight(This,Item, []).
-%% @spec (This::wxTreeCtrl(), Item::integer(), [Option]) -> ok
-%% Option = {highlight, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemdrophighlight">external documentation</a>.
+-spec setItemDropHighlight(This, Item, [Option]) -> ok when
+ This::wxTreeCtrl(), Item::integer(),
+ Option :: {highlight, boolean()}.
setItemDropHighlight(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -679,8 +776,9 @@ setItemDropHighlight(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:cast(?wxTreeCtrl_SetItemDropHighlight,
<<ThisRef:32/?UI,0:32,Item:64/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemfont">external documentation</a>.
+-spec setItemFont(This, Item, Font) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Font::wxFont:wxFont().
setItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item,#wx_ref{type=FontT,ref=FontRef})
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -688,15 +786,18 @@ setItemFont(#wx_ref{type=ThisT,ref=ThisRef},Item,#wx_ref{type=FontT,ref=FontRef}
wxe_util:cast(?wxTreeCtrl_SetItemFont,
<<ThisRef:32/?UI,0:32,Item:64/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @equiv setItemHasChildren(This,Item, [])
+-spec setItemHasChildren(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
+
setItemHasChildren(This,Item)
when is_record(This, wx_ref),is_integer(Item) ->
setItemHasChildren(This,Item, []).
-%% @spec (This::wxTreeCtrl(), Item::integer(), [Option]) -> ok
-%% Option = {has, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemhaschildren">external documentation</a>.
+-spec setItemHasChildren(This, Item, [Option]) -> ok when
+ This::wxTreeCtrl(), Item::integer(),
+ Option :: {has, boolean()}.
setItemHasChildren(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
when is_integer(Item),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -706,19 +807,20 @@ setItemHasChildren(#wx_ref{type=ThisT,ref=ThisRef},Item, Options)
wxe_util:cast(?wxTreeCtrl_SetItemHasChildren,
<<ThisRef:32/?UI,0:32,Item:64/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Image::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemimage">external documentation</a>.
+-spec setItemImage(This, Item, Image) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Image::integer().
setItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Image)
when is_integer(Item),is_integer(Image) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SetItemImage_2,
<<ThisRef:32/?UI,0:32,Item:64/?UI,Image:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Image::integer(), [Option]) -> ok
-%% Option = {which, WxTreeItemIcon}
-%% WxTreeItemIcon = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemimage">external documentation</a>.
-%%<br /> WxTreeItemIcon is one of ?wxTreeItemIcon_Normal | ?wxTreeItemIcon_Selected | ?wxTreeItemIcon_Expanded | ?wxTreeItemIcon_SelectedExpanded | ?wxTreeItemIcon_Max
+%%<br /> Which = ?wxTreeItemIcon_Normal | ?wxTreeItemIcon_Selected | ?wxTreeItemIcon_Expanded | ?wxTreeItemIcon_SelectedExpanded | ?wxTreeItemIcon_Max
+-spec setItemImage(This, Item, Image, [Option]) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Image::integer(),
+ Option :: {which, wx:wx_enum()}.
setItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Image, Options)
when is_integer(Item),is_integer(Image),is_list(Options) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -728,8 +830,9 @@ setItemImage(#wx_ref{type=ThisT,ref=ThisRef},Item,Image, Options)
wxe_util:cast(?wxTreeCtrl_SetItemImage_3,
<<ThisRef:32/?UI,0:32,Item:64/?UI,Image:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemtext">external documentation</a>.
+-spec setItemText(This, Item, Text) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Text::unicode:chardata().
setItemText(#wx_ref{type=ThisT,ref=ThisRef},Item,Text)
when is_integer(Item),is_list(Text) ->
?CLASS(ThisT,wxTreeCtrl),
@@ -737,78 +840,87 @@ setItemText(#wx_ref{type=ThisT,ref=ThisRef},Item,Text)
wxe_util:cast(?wxTreeCtrl_SetItemText,
<<ThisRef:32/?UI,0:32,Item:64/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTreeCtrl(), Item::integer(), Col::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetitemtextcolour">external documentation</a>.
+-spec setItemTextColour(This, Item, Col) -> ok when
+ This::wxTreeCtrl(), Item::integer(), Col::wx:wx_colour().
setItemTextColour(#wx_ref{type=ThisT,ref=ThisRef},Item,Col)
when is_integer(Item),tuple_size(Col) =:= 3; tuple_size(Col) =:= 4 ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SetItemTextColour,
<<ThisRef:32/?UI,0:32,Item:64/?UI,(wxe_util:colour_bin(Col)):16/binary>>).
-%% @spec (This::wxTreeCtrl(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetstateimagelist">external documentation</a>.
+-spec setStateImageList(This, ImageList) -> ok when
+ This::wxTreeCtrl(), ImageList::wxImageList:wxImageList().
setStateImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxTreeCtrl),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxTreeCtrl_SetStateImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Styles::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsetwindowstyle">external documentation</a>.
+-spec setWindowStyle(This, Styles) -> ok when
+ This::wxTreeCtrl(), Styles::integer().
setWindowStyle(#wx_ref{type=ThisT,ref=ThisRef},Styles)
when is_integer(Styles) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SetWindowStyle,
<<ThisRef:32/?UI,Styles:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlsortchildren">external documentation</a>.
+-spec sortChildren(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
sortChildren(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_SortChildren,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrltoggle">external documentation</a>.
+-spec toggle(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
toggle(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_Toggle,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrltoggleitemselection">external documentation</a>.
+-spec toggleItemSelection(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
toggleItemSelection(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_ToggleItemSelection,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlunselect">external documentation</a>.
+-spec unselect(This) -> ok when
+ This::wxTreeCtrl().
unselect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_Unselect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlunselectall">external documentation</a>.
+-spec unselectAll(This) -> ok when
+ This::wxTreeCtrl().
unselectAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_UnselectAll,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeCtrl(), Item::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreectrl.html#wxtreectrlunselectitem">external documentation</a>.
+-spec unselectItem(This, Item) -> ok when
+ This::wxTreeCtrl(), Item::integer().
unselectItem(#wx_ref{type=ThisT,ref=ThisRef},Item)
when is_integer(Item) ->
?CLASS(ThisT,wxTreeCtrl),
wxe_util:cast(?wxTreeCtrl_UnselectItem,
<<ThisRef:32/?UI,0:32,Item:64/?UI>>).
-%% @spec (This::wxTreeCtrl()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTreeCtrl()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxTreeCtrl),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxTreeEvent.erl b/lib/wx/src/gen/wxTreeEvent.erl
index d5379b7abe..d042fb93e5 100644
--- a/lib/wx/src/gen/wxTreeEvent.erl
+++ b/lib/wx/src/gen/wxTreeEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,63 +42,73 @@
isSelection/1,parent_class/1,resumePropagation/2,setInt/2,setString/2,
shouldPropagate/1,skip/1,skip/2,stopPropagation/1,veto/1]).
+-export_type([wxTreeEvent/0]).
%% @hidden
parent_class(wxNotifyEvent) -> true;
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (This::wxTreeEvent()) -> integer()
+-type wxTreeEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetkeycode">external documentation</a>.
+-spec getKeyCode(This) -> integer() when
+ This::wxTreeEvent().
getKeyCode(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_GetKeyCode,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetitem">external documentation</a>.
+-spec getItem(This) -> integer() when
+ This::wxTreeEvent().
getItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_GetItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> wxKeyEvent:wxKeyEvent()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetkeyevent">external documentation</a>.
+-spec getKeyEvent(This) -> wxKeyEvent:wxKeyEvent() when
+ This::wxTreeEvent().
getKeyEvent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_GetKeyEvent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxTreeEvent().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetolditem">external documentation</a>.
+-spec getOldItem(This) -> integer() when
+ This::wxTreeEvent().
getOldItem(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_GetOldItem,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventgetpoint">external documentation</a>.
+-spec getPoint(This) -> {X::integer(), Y::integer()} when
+ This::wxTreeEvent().
getPoint(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_GetPoint,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventiseditcancelled">external documentation</a>.
+-spec isEditCancelled(This) -> boolean() when
+ This::wxTreeEvent().
isEditCancelled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreeEvent),
wxe_util:call(?wxTreeEvent_IsEditCancelled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreeEvent(), ToolTip::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreeevent.html#wxtreeeventsettooltip">external documentation</a>.
+-spec setToolTip(This, ToolTip) -> ok when
+ This::wxTreeEvent(), ToolTip::unicode:chardata().
setToolTip(#wx_ref{type=ThisT,ref=ThisRef},ToolTip)
when is_list(ToolTip) ->
?CLASS(ThisT,wxTreeEvent),
diff --git a/lib/wx/src/gen/wxTreebook.erl b/lib/wx/src/gen/wxTreebook.erl
index a515ec9639..5d08c12cce 100644
--- a/lib/wx/src/gen/wxTreebook.erl
+++ b/lib/wx/src/gen/wxTreebook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
%%
%% The 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,27 +75,34 @@
show/1,show/2,thaw/1,transferDataFromWindow/1,transferDataToWindow/1,
update/1,updateWindowUI/1,updateWindowUI/2,validate/1,warpPointer/3]).
+-export_type([wxTreebook/0]).
%% @hidden
parent_class(wxControl) -> true;
parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxTreebook()
+-type wxTreebook() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookwxtreebook">external documentation</a>.
+-spec new() -> wxTreebook().
new() ->
wxe_util:construct(?wxTreebook_new_0,
<<>>).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer()) -> wxTreebook()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxTreebook() when
+ Parent::wxWindow:wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> wxTreebook()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookwxtreebook">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxTreebook() when
+ Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -107,15 +114,19 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxTreebook_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreebook(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv addPage(This,Page,Text, [])
+-spec addPage(This, Page, Text) -> boolean() when
+ This::wxTreebook(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
addPage(This,Page,Text)
when is_record(This, wx_ref),is_record(Page, wx_ref),is_list(Text) ->
addPage(This,Page,Text, []).
-%% @spec (This::wxTreebook(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookaddpage">external documentation</a>.
+-spec addPage(This, Page, Text, [Option]) -> boolean() when
+ This::wxTreebook(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreebook),
@@ -128,15 +139,18 @@ addPage(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PageT,ref=PageRef},Text, Op
wxe_util:call(?wxTreebook_AddPage,
<<ThisRef:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((4+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreebook()) -> ok
%% @equiv advanceSelection(This, [])
+-spec advanceSelection(This) -> ok when
+ This::wxTreebook().
+
advanceSelection(This)
when is_record(This, wx_ref) ->
advanceSelection(This, []).
-%% @spec (This::wxTreebook(), [Option]) -> ok
-%% Option = {forward, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookadvanceselection">external documentation</a>.
+-spec advanceSelection(This, [Option]) -> ok when
+ This::wxTreebook(),
+ Option :: {forward, boolean()}.
advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxTreebook),
@@ -146,23 +160,29 @@ advanceSelection(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxTreebook_AdvanceSelection,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTreebook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookassignimagelist">external documentation</a>.
+-spec assignImageList(This, ImageList) -> ok when
+ This::wxTreebook(), ImageList::wxImageList:wxImageList().
assignImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxTreebook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxTreebook_AssignImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreebook(), Parent::wxWindow:wxWindow(), Id::integer()) -> bool()
%% @equiv create(This,Parent,Id, [])
+-spec create(This, Parent, Id) -> boolean() when
+ This::wxTreebook(), Parent::wxWindow:wxWindow(), Id::integer().
+
create(This,Parent,Id)
when is_record(This, wx_ref),is_record(Parent, wx_ref),is_integer(Id) ->
create(This,Parent,Id, []).
-%% @spec (This::wxTreebook(), Parent::wxWindow:wxWindow(), Id::integer(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookcreate">external documentation</a>.
+-spec create(This, Parent, Id, [Option]) -> boolean() when
+ This::wxTreebook(), Parent::wxWindow:wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ThisT,wxTreebook),
@@ -175,90 +195,103 @@ create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Id, O
wxe_util:call(?wxTreebook_Create,
<<ThisRef:32/?UI,ParentRef:32/?UI,Id:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxTreebook()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookdeleteallpages">external documentation</a>.
+-spec deleteAllPages(This) -> boolean() when
+ This::wxTreebook().
deleteAllPages(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_DeleteAllPages,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreebook(), Pos::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookdeletepage">external documentation</a>.
+-spec deletePage(This, Pos) -> boolean() when
+ This::wxTreebook(), Pos::integer().
deletePage(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_DeletePage,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookremovepage">external documentation</a>.
+-spec removePage(This, N) -> boolean() when
+ This::wxTreebook(), N::integer().
removePage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_RemovePage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxTreebook()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetcurrentpage">external documentation</a>.
+-spec getCurrentPage(This) -> wxWindow:wxWindow() when
+ This::wxTreebook().
getCurrentPage(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetCurrentPage,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreebook()) -> wxImageList:wxImageList()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetimagelist">external documentation</a>.
+-spec getImageList(This) -> wxImageList:wxImageList() when
+ This::wxTreebook().
getImageList(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetImageList,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer()) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetpage">external documentation</a>.
+-spec getPage(This, N) -> wxWindow:wxWindow() when
+ This::wxTreebook(), N::integer().
getPage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetPage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxTreebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetpagecount">external documentation</a>.
+-spec getPageCount(This) -> integer() when
+ This::wxTreebook().
getPageCount(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetPageCount,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetpageimage">external documentation</a>.
+-spec getPageImage(This, N) -> integer() when
+ This::wxTreebook(), N::integer().
getPageImage(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetPageImage,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetpagetext">external documentation</a>.
+-spec getPageText(This, N) -> unicode:charlist() when
+ This::wxTreebook(), N::integer().
getPageText(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetPageText,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxTreebook()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookgetselection">external documentation</a>.
+-spec getSelection(This) -> integer() when
+ This::wxTreebook().
getSelection(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_GetSelection,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxTreebook(), Pos::integer()) -> bool()
%% @equiv expandNode(This,Pos, [])
+-spec expandNode(This, Pos) -> boolean() when
+ This::wxTreebook(), Pos::integer().
+
expandNode(This,Pos)
when is_record(This, wx_ref),is_integer(Pos) ->
expandNode(This,Pos, []).
-%% @spec (This::wxTreebook(), Pos::integer(), [Option]) -> bool()
-%% Option = {expand, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookexpandnode">external documentation</a>.
+-spec expandNode(This, Pos, [Option]) -> boolean() when
+ This::wxTreebook(), Pos::integer(),
+ Option :: {expand, boolean()}.
expandNode(#wx_ref{type=ThisT,ref=ThisRef},Pos, Options)
when is_integer(Pos),is_list(Options) ->
?CLASS(ThisT,wxTreebook),
@@ -268,31 +301,38 @@ expandNode(#wx_ref{type=ThisT,ref=ThisRef},Pos, Options)
wxe_util:call(?wxTreebook_ExpandNode,
<<ThisRef:32/?UI,Pos:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxTreebook(), Pos::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookisnodeexpanded">external documentation</a>.
+-spec isNodeExpanded(This, Pos) -> boolean() when
+ This::wxTreebook(), Pos::integer().
isNodeExpanded(#wx_ref{type=ThisT,ref=ThisRef},Pos)
when is_integer(Pos) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_IsNodeExpanded,
<<ThisRef:32/?UI,Pos:32/?UI>>).
-%% @spec (This::wxTreebook(), Pt::{X::integer(),Y::integer()}) -> {integer(),Flags::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookhittest">external documentation</a>.
+-spec hitTest(This, Pt) -> Result when
+ Result ::{Res ::integer(), Flags::integer()},
+ This::wxTreebook(), Pt::{X::integer(), Y::integer()}.
hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_HitTest,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv insertPage(This,Pos,Page,Text, [])
+-spec insertPage(This, Pos, Page, Text) -> boolean() when
+ This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
insertPage(This,Pos,Page,Text)
when is_record(This, wx_ref),is_integer(Pos),is_record(Page, wx_ref),is_list(Text) ->
insertPage(This,Pos,Page,Text, []).
-%% @spec (This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookinsertpage">external documentation</a>.
+-spec insertPage(This, Pos, Page, Text, [Option]) -> boolean() when
+ This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
insertPage(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_integer(Pos),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreebook),
@@ -305,15 +345,19 @@ insertPage(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=PageT,ref=PageRef},T
wxe_util:call(?wxTreebook_InsertPage,
<<ThisRef:32/?UI,Pos:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::string()) -> bool()
%% @equiv insertSubPage(This,Pos,Page,Text, [])
+-spec insertSubPage(This, Pos, Page, Text) -> boolean() when
+ This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata().
+
insertSubPage(This,Pos,Page,Text)
when is_record(This, wx_ref),is_integer(Pos),is_record(Page, wx_ref),is_list(Text) ->
insertSubPage(This,Pos,Page,Text, []).
-%% @spec (This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::string(), [Option]) -> bool()
-%% Option = {bSelect, bool()} | {imageId, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookinsertsubpage">external documentation</a>.
+-spec insertSubPage(This, Pos, Page, Text, [Option]) -> boolean() when
+ This::wxTreebook(), Pos::integer(), Page::wxWindow:wxWindow(), Text::unicode:chardata(),
+ Option :: {bSelect, boolean()}
+ | {imageId, integer()}.
insertSubPage(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=PageT,ref=PageRef},Text, Options)
when is_integer(Pos),is_list(Text),is_list(Options) ->
?CLASS(ThisT,wxTreebook),
@@ -326,32 +370,36 @@ insertSubPage(#wx_ref{type=ThisT,ref=ThisRef},Pos,#wx_ref{type=PageT,ref=PageRef
wxe_util:call(?wxTreebook_InsertSubPage,
<<ThisRef:32/?UI,Pos:32/?UI,PageRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxTreebook(), ImageList::wxImageList:wxImageList()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebooksetimagelist">external documentation</a>.
+-spec setImageList(This, ImageList) -> ok when
+ This::wxTreebook(), ImageList::wxImageList:wxImageList().
setImageList(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ImageListT,ref=ImageListRef}) ->
?CLASS(ThisT,wxTreebook),
?CLASS(ImageListT,wxImageList),
wxe_util:cast(?wxTreebook_SetImageList,
<<ThisRef:32/?UI,ImageListRef:32/?UI>>).
-%% @spec (This::wxTreebook(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebooksetpagesize">external documentation</a>.
+-spec setPageSize(This, Size) -> ok when
+ This::wxTreebook(), Size::{W::integer(), H::integer()}.
setPageSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxTreebook),
wxe_util:cast(?wxTreebook_SetPageSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer(), ImageId::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebooksetpageimage">external documentation</a>.
+-spec setPageImage(This, N, ImageId) -> boolean() when
+ This::wxTreebook(), N::integer(), ImageId::integer().
setPageImage(#wx_ref{type=ThisT,ref=ThisRef},N,ImageId)
when is_integer(N),is_integer(ImageId) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_SetPageImage,
<<ThisRef:32/?UI,N:32/?UI,ImageId:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer(), StrText::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebooksetpagetext">external documentation</a>.
+-spec setPageText(This, N, StrText) -> boolean() when
+ This::wxTreebook(), N::integer(), StrText::unicode:chardata().
setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
when is_integer(N),is_list(StrText) ->
?CLASS(ThisT,wxTreebook),
@@ -359,24 +407,26 @@ setPageText(#wx_ref{type=ThisT,ref=ThisRef},N,StrText)
wxe_util:call(?wxTreebook_SetPageText,
<<ThisRef:32/?UI,N:32/?UI,(byte_size(StrText_UC)):32/?UI,(StrText_UC)/binary, 0:(((8- ((4+byte_size(StrText_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxTreebook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebooksetselection">external documentation</a>.
+-spec setSelection(This, N) -> integer() when
+ This::wxTreebook(), N::integer().
setSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_SetSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxTreebook(), N::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxtreebook.html#wxtreebookchangeselection">external documentation</a>.
+-spec changeSelection(This, N) -> integer() when
+ This::wxTreebook(), N::integer().
changeSelection(#wx_ref{type=ThisT,ref=ThisRef},N)
when is_integer(N) ->
?CLASS(ThisT,wxTreebook),
wxe_util:call(?wxTreebook_ChangeSelection,
<<ThisRef:32/?UI,N:32/?UI>>).
-%% @spec (This::wxTreebook()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxTreebook()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxTreebook),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxUpdateUIEvent.erl b/lib/wx/src/gen/wxUpdateUIEvent.erl
index baf9fc8b52..f6d46611ab 100644
--- a/lib/wx/src/gen/wxUpdateUIEvent.erl
+++ b/lib/wx/src/gen/wxUpdateUIEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,129 +42,143 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxUpdateUIEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec (Win::wxWindow:wxWindow()) -> bool()
+-type wxUpdateUIEvent() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventcanupdate">external documentation</a>.
+-spec canUpdate(Win) -> boolean() when
+ Win::wxWindow:wxWindow().
canUpdate(#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(WinT,wxWindow),
wxe_util:call(?wxUpdateUIEvent_CanUpdate,
<<WinRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent(), Check::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventcheck">external documentation</a>.
+-spec check(This, Check) -> ok when
+ This::wxUpdateUIEvent(), Check::boolean().
check(#wx_ref{type=ThisT,ref=ThisRef},Check)
when is_boolean(Check) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:cast(?wxUpdateUIEvent_Check,
<<ThisRef:32/?UI,(wxe_util:from_bool(Check)):32/?UI>>).
-%% @spec (This::wxUpdateUIEvent(), Enable::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventenable">external documentation</a>.
+-spec enable(This, Enable) -> ok when
+ This::wxUpdateUIEvent(), Enable::boolean().
enable(#wx_ref{type=ThisT,ref=ThisRef},Enable)
when is_boolean(Enable) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:cast(?wxUpdateUIEvent_Enable,
<<ThisRef:32/?UI,(wxe_util:from_bool(Enable)):32/?UI>>).
-%% @spec (This::wxUpdateUIEvent(), Show::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventshow">external documentation</a>.
+-spec show(This, Show) -> ok when
+ This::wxUpdateUIEvent(), Show::boolean().
show(#wx_ref{type=ThisT,ref=ThisRef},Show)
when is_boolean(Show) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:cast(?wxUpdateUIEvent_Show,
<<ThisRef:32/?UI,(wxe_util:from_bool(Show)):32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetchecked">external documentation</a>.
+-spec getChecked(This) -> boolean() when
+ This::wxUpdateUIEvent().
getChecked(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetChecked,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetenabled">external documentation</a>.
+-spec getEnabled(This) -> boolean() when
+ This::wxUpdateUIEvent().
getEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetEnabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetshown">external documentation</a>.
+-spec getShown(This) -> boolean() when
+ This::wxUpdateUIEvent().
getShown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetShown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetsetchecked">external documentation</a>.
+-spec getSetChecked(This) -> boolean() when
+ This::wxUpdateUIEvent().
getSetChecked(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetSetChecked,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetsetenabled">external documentation</a>.
+-spec getSetEnabled(This) -> boolean() when
+ This::wxUpdateUIEvent().
getSetEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetSetEnabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetsetshown">external documentation</a>.
+-spec getSetShown(This) -> boolean() when
+ This::wxUpdateUIEvent().
getSetShown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetSetShown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetsettext">external documentation</a>.
+-spec getSetText(This) -> boolean() when
+ This::wxUpdateUIEvent().
getSetText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetSetText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgettext">external documentation</a>.
+-spec getText(This) -> unicode:charlist() when
+ This::wxUpdateUIEvent().
getText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxUpdateUIEvent),
wxe_util:call(?wxUpdateUIEvent_GetText,
<<ThisRef:32/?UI>>).
-%% @spec () -> WxUpdateUIMode
-%% WxUpdateUIMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetmode">external documentation</a>.
-%%<br /> WxUpdateUIMode is one of ?wxUPDATE_UI_PROCESS_ALL | ?wxUPDATE_UI_PROCESS_SPECIFIED
+%%<br /> Res = ?wxUPDATE_UI_PROCESS_ALL | ?wxUPDATE_UI_PROCESS_SPECIFIED
+-spec getMode() -> wx:wx_enum().
getMode() ->
wxe_util:call(?wxUpdateUIEvent_GetMode,
<<>>).
-%% @spec () -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventgetupdateinterval">external documentation</a>.
+-spec getUpdateInterval() -> integer().
getUpdateInterval() ->
wxe_util:call(?wxUpdateUIEvent_GetUpdateInterval,
<<>>).
-%% @spec () -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventresetupdatetime">external documentation</a>.
+-spec resetUpdateTime() -> ok.
resetUpdateTime() ->
wxe_util:cast(?wxUpdateUIEvent_ResetUpdateTime,
<<>>).
-%% @spec (Mode::WxUpdateUIMode) -> ok
-%% WxUpdateUIMode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventsetmode">external documentation</a>.
-%%<br /> WxUpdateUIMode is one of ?wxUPDATE_UI_PROCESS_ALL | ?wxUPDATE_UI_PROCESS_SPECIFIED
+%%<br /> Mode = ?wxUPDATE_UI_PROCESS_ALL | ?wxUPDATE_UI_PROCESS_SPECIFIED
+-spec setMode(Mode) -> ok when
+ Mode::wx:wx_enum().
setMode(Mode)
when is_integer(Mode) ->
wxe_util:cast(?wxUpdateUIEvent_SetMode,
<<Mode:32/?UI>>).
-%% @spec (This::wxUpdateUIEvent(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventsettext">external documentation</a>.
+-spec setText(This, Text) -> ok when
+ This::wxUpdateUIEvent(), Text::unicode:chardata().
setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxUpdateUIEvent),
@@ -172,8 +186,9 @@ setText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxUpdateUIEvent_SetText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (UpdateInterval::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxupdateuievent.html#wxupdateuieventsetupdateinterval">external documentation</a>.
+-spec setUpdateInterval(UpdateInterval) -> ok when
+ UpdateInterval::integer().
setUpdateInterval(UpdateInterval)
when is_integer(UpdateInterval) ->
wxe_util:cast(?wxUpdateUIEvent_SetUpdateInterval,
diff --git a/lib/wx/src/gen/wxWindow.erl b/lib/wx/src/gen/wxWindow.erl
index 031314bfe2..229633a106 100644
--- a/lib/wx/src/gen/wxWindow.erl
+++ b/lib/wx/src/gen/wxWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,25 +69,32 @@
%% inherited exports
-export([connect/2,connect/3,disconnect/1,disconnect/2,disconnect/3,parent_class/1]).
+-export_type([wxWindow/0]).
%% @hidden
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxWindow()
+-type wxWindow() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowwxwindow">external documentation</a>.
+-spec new() -> wxWindow().
new() ->
wxe_util:construct(?wxWindow_new_0,
<<>>).
-%% @spec (Parent::wxWindow(), Id::integer()) -> wxWindow()
%% @equiv new(Parent,Id, [])
+-spec new(Parent, Id) -> wxWindow() when
+ Parent::wxWindow(), Id::integer().
+
new(Parent,Id)
when is_record(Parent, wx_ref),is_integer(Id) ->
new(Parent,Id, []).
-%% @spec (Parent::wxWindow(), Id::integer(), [Option]) -> wxWindow()
-%% Option = {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowwxwindow">external documentation</a>.
+-spec new(Parent, Id, [Option]) -> wxWindow() when
+ Parent::wxWindow(), Id::integer(),
+ Option :: {pos, {X::integer(), Y::integer()}}
+ | {size, {W::integer(), H::integer()}}
+ | {style, integer()}.
new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
when is_integer(Id),is_list(Options) ->
?CLASS(ParentT,wxWindow),
@@ -99,30 +106,35 @@ new(#wx_ref{type=ParentT,ref=ParentRef},Id, Options)
wxe_util:construct(?wxWindow_new_3,
<<ParentRef:32/?UI,Id:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcachebestsize">external documentation</a>.
+-spec cacheBestSize(This, Size) -> ok when
+ This::wxWindow(), Size::{W::integer(), H::integer()}.
cacheBestSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_CacheBestSize,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcapturemouse">external documentation</a>.
+-spec captureMouse(This) -> ok when
+ This::wxWindow().
captureMouse(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_CaptureMouse,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv center(This, [])
+-spec center(This) -> ok when
+ This::wxWindow().
+
center(This)
when is_record(This, wx_ref) ->
center(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {dir, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcenter">external documentation</a>.
+-spec center(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {dir, integer()}.
center(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -132,15 +144,18 @@ center(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_Center,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv centerOnParent(This, [])
+-spec centerOnParent(This) -> ok when
+ This::wxWindow().
+
centerOnParent(This)
when is_record(This, wx_ref) ->
centerOnParent(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {dir, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcenteronparent">external documentation</a>.
+-spec centerOnParent(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {dir, integer()}.
centerOnParent(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -150,15 +165,18 @@ centerOnParent(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_CenterOnParent,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv centre(This, [])
+-spec centre(This) -> ok when
+ This::wxWindow().
+
centre(This)
when is_record(This, wx_ref) ->
centre(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {dir, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcentre">external documentation</a>.
+-spec centre(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {dir, integer()}.
centre(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -168,15 +186,18 @@ centre(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_Centre,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv centreOnParent(This, [])
+-spec centreOnParent(This) -> ok when
+ This::wxWindow().
+
centreOnParent(This)
when is_record(This, wx_ref) ->
centreOnParent(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {dir, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowcentreonparent">external documentation</a>.
+-spec centreOnParent(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {dir, integer()}.
centreOnParent(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -186,38 +207,44 @@ centreOnParent(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_CentreOnParent,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowclearbackground">external documentation</a>.
+-spec clearBackground(This) -> ok when
+ This::wxWindow().
clearBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_ClearBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowclienttoscreen">external documentation</a>.
+-spec clientToScreen(This, Pt) -> {X::integer(), Y::integer()} when
+ This::wxWindow(), Pt::{X::integer(), Y::integer()}.
clientToScreen(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ClientToScreen_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowclienttoscreen">external documentation</a>.
+-spec clientToScreen(This, X, Y) -> {X::integer(), Y::integer()} when
+ This::wxWindow(), X::integer(), Y::integer().
clientToScreen(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ClientToScreen_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @equiv close(This, [])
+-spec close(This) -> boolean() when
+ This::wxWindow().
+
close(This)
when is_record(This, wx_ref) ->
close(This, []).
-%% @spec (This::wxWindow(), [Option]) -> bool()
-%% Option = {force, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowclose">external documentation</a>.
+-spec close(This, [Option]) -> boolean() when
+ This::wxWindow(),
+ Option :: {force, boolean()}.
close(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -227,52 +254,60 @@ close(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxWindow_Close,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Sz::{W::integer(),H::integer()}) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowconvertdialogtopixels">external documentation</a>.
+-spec convertDialogToPixels(This, Sz) -> {W::integer(), H::integer()} when
+ This::wxWindow(), Sz::{W::integer(), H::integer()}.
convertDialogToPixels(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
when is_integer(SzW),is_integer(SzH) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ConvertDialogToPixels,
<<ThisRef:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxWindow(), Sz::{W::integer(),H::integer()}) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowconvertpixelstodialog">external documentation</a>.
+-spec convertPixelsToDialog(This, Sz) -> {W::integer(), H::integer()} when
+ This::wxWindow(), Sz::{W::integer(), H::integer()}.
convertPixelsToDialog(#wx_ref{type=ThisT,ref=ThisRef},{SzW,SzH})
when is_integer(SzW),is_integer(SzH) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ConvertPixelsToDialog,
<<ThisRef:32/?UI,SzW:32/?UI,SzH:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowdestroy">external documentation</a>.
+-spec 'Destroy'(This) -> boolean() when
+ This::wxWindow().
'Destroy'(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_Destroy,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowdestroychildren">external documentation</a>.
+-spec destroyChildren(This) -> boolean() when
+ This::wxWindow().
destroyChildren(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_DestroyChildren,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowdisable">external documentation</a>.
+-spec disable(This) -> boolean() when
+ This::wxWindow().
disable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_Disable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @equiv enable(This, [])
+-spec enable(This) -> boolean() when
+ This::wxWindow().
+
enable(This)
when is_record(This, wx_ref) ->
enable(This, []).
-%% @spec (This::wxWindow(), [Option]) -> bool()
-%% Option = {enable, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowenable">external documentation</a>.
+-spec enable(This, [Option]) -> boolean() when
+ This::wxWindow(),
+ Option :: {enable, boolean()}.
enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -282,21 +317,21 @@ enable(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxWindow_Enable,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec () -> wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfindfocus">external documentation</a>.
+-spec findFocus() -> wxWindow().
findFocus() ->
wxe_util:call(?wxWindow_FindFocus,
<<>>).
-%% @spec (This::wxWindow(),X::integer()|string()) -> wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfindwindow">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% findWindow(This::wxWindow(), Winid::integer()) -> wxWindow() </c>
-%% </p>
-%% <p><c>
-%% findWindow(This::wxWindow(), Name::string()) -> wxWindow() </c>
-%% </p>
+%% <br /> Also:<br />
+%% findWindow(This, Name) -> wxWindow() when<br />
+%% This::wxWindow(), Name::unicode:chardata().<br />
+%%
+-spec findWindow(This, Winid) -> wxWindow() when
+ This::wxWindow(), Winid::integer();
+ (This, Name) -> wxWindow() when
+ This::wxWindow(), Name::unicode:chardata().
findWindow(#wx_ref{type=ThisT,ref=ThisRef},Winid)
when is_integer(Winid) ->
?CLASS(ThisT,wxWindow),
@@ -309,15 +344,18 @@ findWindow(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxWindow_FindWindow_1_1,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (Winid::integer()) -> wxWindow()
%% @equiv findWindowById(Winid, [])
+-spec findWindowById(Winid) -> wxWindow() when
+ Winid::integer().
+
findWindowById(Winid)
when is_integer(Winid) ->
findWindowById(Winid, []).
-%% @spec (Winid::integer(), [Option]) -> wxWindow()
-%% Option = {parent, wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfindwindowbyid">external documentation</a>.
+-spec findWindowById(Winid, [Option]) -> wxWindow() when
+ Winid::integer(),
+ Option :: {parent, wxWindow()}.
findWindowById(Winid, Options)
when is_integer(Winid),is_list(Options) ->
MOpts = fun({parent, #wx_ref{type=ParentT,ref=ParentRef}}, Acc) -> ?CLASS(ParentT,wxWindow),[<<1:32/?UI,ParentRef:32/?UI>>|Acc];
@@ -326,15 +364,18 @@ findWindowById(Winid, Options)
wxe_util:call(?wxWindow_FindWindowById,
<<Winid:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (Name::string()) -> wxWindow()
%% @equiv findWindowByName(Name, [])
+-spec findWindowByName(Name) -> wxWindow() when
+ Name::unicode:chardata().
+
findWindowByName(Name)
when is_list(Name) ->
findWindowByName(Name, []).
-%% @spec (Name::string(), [Option]) -> wxWindow()
-%% Option = {parent, wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfindwindowbyname">external documentation</a>.
+-spec findWindowByName(Name, [Option]) -> wxWindow() when
+ Name::unicode:chardata(),
+ Option :: {parent, wxWindow()}.
findWindowByName(Name, Options)
when is_list(Name),is_list(Options) ->
Name_UC = unicode:characters_to_binary([Name,0]),
@@ -344,15 +385,18 @@ findWindowByName(Name, Options)
wxe_util:call(?wxWindow_FindWindowByName,
<<(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (Label::string()) -> wxWindow()
%% @equiv findWindowByLabel(Label, [])
+-spec findWindowByLabel(Label) -> wxWindow() when
+ Label::unicode:chardata().
+
findWindowByLabel(Label)
when is_list(Label) ->
findWindowByLabel(Label, []).
-%% @spec (Label::string(), [Option]) -> wxWindow()
-%% Option = {parent, wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfindwindowbylabel">external documentation</a>.
+-spec findWindowByLabel(Label, [Option]) -> wxWindow() when
+ Label::unicode:chardata(),
+ Option :: {parent, wxWindow()}.
findWindowByLabel(Label, Options)
when is_list(Label),is_list(Options) ->
Label_UC = unicode:characters_to_binary([Label,0]),
@@ -362,285 +406,326 @@ findWindowByLabel(Label, Options)
wxe_util:call(?wxWindow_FindWindowByLabel,
<<(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfit">external documentation</a>.
+-spec fit(This) -> ok when
+ This::wxWindow().
fit(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_Fit,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfitinside">external documentation</a>.
+-spec fitInside(This) -> ok when
+ This::wxWindow().
fitInside(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_FitInside,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowfreeze">external documentation</a>.
+-spec freeze(This) -> ok when
+ This::wxWindow().
freeze(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_Freeze,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxAcceleratorTable:wxAcceleratorTable()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetacceleratortable">external documentation</a>.
+-spec getAcceleratorTable(This) -> wxAcceleratorTable:wxAcceleratorTable() when
+ This::wxWindow().
getAcceleratorTable(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetAcceleratorTable,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetbackgroundcolour">external documentation</a>.
+-spec getBackgroundColour(This) -> wx:wx_colour4() when
+ This::wxWindow().
getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetBackgroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> WxBackgroundStyle
-%% WxBackgroundStyle = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetbackgroundstyle">external documentation</a>.
-%%<br /> WxBackgroundStyle is one of ?wxBG_STYLE_SYSTEM | ?wxBG_STYLE_COLOUR | ?wxBG_STYLE_CUSTOM
+%%<br /> Res = ?wxBG_STYLE_SYSTEM | ?wxBG_STYLE_COLOUR | ?wxBG_STYLE_CUSTOM
+-spec getBackgroundStyle(This) -> wx:wx_enum() when
+ This::wxWindow().
getBackgroundStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetBackgroundStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetbestsize">external documentation</a>.
+-spec getBestSize(This) -> {W::integer(), H::integer()} when
+ This::wxWindow().
getBestSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetBestSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxCaret:wxCaret()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetcaret">external documentation</a>.
+-spec getCaret(This) -> wxCaret:wxCaret() when
+ This::wxWindow().
getCaret(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetCaret,
<<ThisRef:32/?UI>>).
-%% @spec () -> wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetcapture">external documentation</a>.
+-spec getCapture() -> wxWindow().
getCapture() ->
wxe_util:call(?wxWindow_GetCapture,
<<>>).
-%% @spec (This::wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetcharheight">external documentation</a>.
+-spec getCharHeight(This) -> integer() when
+ This::wxWindow().
getCharHeight(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetCharHeight,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetcharwidth">external documentation</a>.
+-spec getCharWidth(This) -> integer() when
+ This::wxWindow().
getCharWidth(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetCharWidth,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> [wxWindow()]
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetchildren">external documentation</a>.
+-spec getChildren(This) -> [wxWindow()] when
+ This::wxWindow().
getChildren(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetChildren,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetclientsize">external documentation</a>.
+-spec getClientSize(This) -> {W::integer(), H::integer()} when
+ This::wxWindow().
getClientSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetClientSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxSizer:wxSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetcontainingsizer">external documentation</a>.
+-spec getContainingSizer(This) -> wxSizer:wxSizer() when
+ This::wxWindow().
getContainingSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetContainingSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxCursor:wxCursor()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetcursor">external documentation</a>.
+-spec getCursor(This) -> wxCursor:wxCursor() when
+ This::wxWindow().
getCursor(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetCursor,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxDropTarget:wxDropTarget()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetdroptarget">external documentation</a>.
+-spec getDropTarget(This) -> wx:wx_object() when
+ This::wxWindow().
getDropTarget(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetDropTarget,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxEvtHandler:wxEvtHandler()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgeteventhandler">external documentation</a>.
+-spec getEventHandler(This) -> wxEvtHandler:wxEvtHandler() when
+ This::wxWindow().
getEventHandler(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetEventHandler,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetextrastyle">external documentation</a>.
+-spec getExtraStyle(This) -> integer() when
+ This::wxWindow().
getExtraStyle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetExtraStyle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxFont:wxFont()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetfont">external documentation</a>.
+-spec getFont(This) -> wxFont:wxFont() when
+ This::wxWindow().
getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetFont,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wx:colour()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetforegroundcolour">external documentation</a>.
+-spec getForegroundColour(This) -> wx:wx_colour4() when
+ This::wxWindow().
getForegroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetForegroundColour,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetgrandparent">external documentation</a>.
+-spec getGrandParent(This) -> wxWindow() when
+ This::wxWindow().
getGrandParent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetGrandParent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgethandle">external documentation</a>.
+-spec getHandle(This) -> integer() when
+ This::wxWindow().
getHandle(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetHandle,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgethelptext">external documentation</a>.
+-spec getHelpText(This) -> unicode:charlist() when
+ This::wxWindow().
getHelpText(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetHelpText,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetid">external documentation</a>.
+-spec getId(This) -> integer() when
+ This::wxWindow().
getId(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetId,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetlabel">external documentation</a>.
+-spec getLabel(This) -> unicode:charlist() when
+ This::wxWindow().
getLabel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetLabel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetmaxsize">external documentation</a>.
+-spec getMaxSize(This) -> {W::integer(), H::integer()} when
+ This::wxWindow().
getMaxSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetMaxSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetminsize">external documentation</a>.
+-spec getMinSize(This) -> {W::integer(), H::integer()} when
+ This::wxWindow().
getMinSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetMinSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetname">external documentation</a>.
+-spec getName(This) -> unicode:charlist() when
+ This::wxWindow().
getName(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetName,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetparent">external documentation</a>.
+-spec getParent(This) -> wxWindow() when
+ This::wxWindow().
getParent(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetParent,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetposition">external documentation</a>.
+-spec getPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxWindow().
getPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetrect">external documentation</a>.
+-spec getRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxWindow().
getRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscreenposition">external documentation</a>.
+-spec getScreenPosition(This) -> {X::integer(), Y::integer()} when
+ This::wxWindow().
getScreenPosition(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetScreenPosition,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer(),W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscreenrect">external documentation</a>.
+-spec getScreenRect(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxWindow().
getScreenRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetScreenRect,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Orient::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscrollpos">external documentation</a>.
+-spec getScrollPos(This, Orient) -> integer() when
+ This::wxWindow(), Orient::integer().
getScrollPos(#wx_ref{type=ThisT,ref=ThisRef},Orient)
when is_integer(Orient) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetScrollPos,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxWindow(), Orient::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscrollrange">external documentation</a>.
+-spec getScrollRange(This, Orient) -> integer() when
+ This::wxWindow(), Orient::integer().
getScrollRange(#wx_ref{type=ThisT,ref=ThisRef},Orient)
when is_integer(Orient) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetScrollRange,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxWindow(), Orient::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetscrollthumb">external documentation</a>.
+-spec getScrollThumb(This, Orient) -> integer() when
+ This::wxWindow(), Orient::integer().
getScrollThumb(#wx_ref{type=ThisT,ref=ThisRef},Orient)
when is_integer(Orient) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetScrollThumb,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetsize">external documentation</a>.
+-spec getSize(This) -> {W::integer(), H::integer()} when
+ This::wxWindow().
getSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxSizer:wxSizer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetsizer">external documentation</a>.
+-spec getSizer(This) -> wxSizer:wxSizer() when
+ This::wxWindow().
getSizer(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetSizer,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), String::string()) -> {X::integer(),Y::integer(),Descent::integer(),ExternalLeading::integer()}
%% @equiv getTextExtent(This,String, [])
+-spec getTextExtent(This, String) -> Result when
+ Result ::{X::integer(), Y::integer(), Descent::integer(), ExternalLeading::integer()},
+ This::wxWindow(), String::unicode:chardata().
+
getTextExtent(This,String)
when is_record(This, wx_ref),is_list(String) ->
getTextExtent(This,String, []).
-%% @spec (This::wxWindow(), String::string(), [Option]) -> {X::integer(),Y::integer(),Descent::integer(),ExternalLeading::integer()}
-%% Option = {theFont, wxFont:wxFont()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgettextextent">external documentation</a>.
+-spec getTextExtent(This, String, [Option]) -> Result when
+ Result :: {X::integer(), Y::integer(), Descent::integer(), ExternalLeading::integer()},
+ This::wxWindow(), String::unicode:chardata(),
+ Option :: {theFont, wxFont:wxFont()}.
getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
when is_list(String),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -651,109 +736,121 @@ getTextExtent(#wx_ref{type=ThisT,ref=ThisRef},String, Options)
wxe_util:call(?wxWindow_GetTextExtent,
<<ThisRef:32/?UI,(byte_size(String_UC)):32/?UI,(String_UC)/binary, 0:(((8- ((0+byte_size(String_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> wxToolTip:wxToolTip()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgettooltip">external documentation</a>.
+-spec getToolTip(This) -> wxToolTip:wxToolTip() when
+ This::wxWindow().
getToolTip(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetToolTip,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxRegion:wxRegion()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetupdateregion">external documentation</a>.
+-spec getUpdateRegion(This) -> wxRegion:wxRegion() when
+ This::wxWindow().
getUpdateRegion(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetUpdateRegion,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {W::integer(),H::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetvirtualsize">external documentation</a>.
+-spec getVirtualSize(This) -> {W::integer(), H::integer()} when
+ This::wxWindow().
getVirtualSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetVirtualSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetwindowstyleflag">external documentation</a>.
+-spec getWindowStyleFlag(This) -> integer() when
+ This::wxWindow().
getWindowStyleFlag(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetWindowStyleFlag,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> WxWindowVariant
-%% WxWindowVariant = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowgetwindowvariant">external documentation</a>.
-%%<br /> WxWindowVariant is one of ?wxWINDOW_VARIANT_NORMAL | ?wxWINDOW_VARIANT_SMALL | ?wxWINDOW_VARIANT_MINI | ?wxWINDOW_VARIANT_LARGE | ?wxWINDOW_VARIANT_MAX
+%%<br /> Res = ?wxWINDOW_VARIANT_NORMAL | ?wxWINDOW_VARIANT_SMALL | ?wxWINDOW_VARIANT_MINI | ?wxWINDOW_VARIANT_LARGE | ?wxWINDOW_VARIANT_MAX
+-spec getWindowVariant(This) -> wx:wx_enum() when
+ This::wxWindow().
getWindowVariant(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_GetWindowVariant,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowhascapture">external documentation</a>.
+-spec hasCapture(This) -> boolean() when
+ This::wxWindow().
hasCapture(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_HasCapture,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Orient::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowhasscrollbar">external documentation</a>.
+-spec hasScrollbar(This, Orient) -> boolean() when
+ This::wxWindow(), Orient::integer().
hasScrollbar(#wx_ref{type=ThisT,ref=ThisRef},Orient)
when is_integer(Orient) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_HasScrollbar,
<<ThisRef:32/?UI,Orient:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowhastransparentbackground">external documentation</a>.
+-spec hasTransparentBackground(This) -> boolean() when
+ This::wxWindow().
hasTransparentBackground(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_HasTransparentBackground,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowhide">external documentation</a>.
+-spec hide(This) -> boolean() when
+ This::wxWindow().
hide(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_Hide,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowinheritattributes">external documentation</a>.
+-spec inheritAttributes(This) -> ok when
+ This::wxWindow().
inheritAttributes(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_InheritAttributes,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowinitdialog">external documentation</a>.
+-spec initDialog(This) -> ok when
+ This::wxWindow().
initDialog(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_InitDialog,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowinvalidatebestsize">external documentation</a>.
+-spec invalidateBestSize(This) -> ok when
+ This::wxWindow().
invalidateBestSize(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_InvalidateBestSize,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisenabled">external documentation</a>.
+-spec isEnabled(This) -> boolean() when
+ This::wxWindow().
isEnabled(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_IsEnabled,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(),X::term()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisexposed">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% isExposed(This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> bool() </c>
-%% </p>
-%% <p><c>
-%% isExposed(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> bool() </c>
-%% </p>
+%% <br /> Also:<br />
+%% isExposed(This, Rect) -> boolean() when<br />
+%% This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec isExposed(This, Pt) -> boolean() when
+ This::wxWindow(), Pt::{X::integer(), Y::integer()};
+ (This, Rect) -> boolean() when
+ This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
isExposed(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxWindow),
@@ -765,80 +862,92 @@ isExposed(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:call(?wxWindow_IsExposed_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisexposed">external documentation</a>.
+-spec isExposed(This, X, Y) -> boolean() when
+ This::wxWindow(), X::integer(), Y::integer().
isExposed(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_IsExposed_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer(), W::integer(), H::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisexposed">external documentation</a>.
+-spec isExposed(This, X, Y, W, H) -> boolean() when
+ This::wxWindow(), X::integer(), Y::integer(), W::integer(), H::integer().
isExposed(#wx_ref{type=ThisT,ref=ThisRef},X,Y,W,H)
when is_integer(X),is_integer(Y),is_integer(W),is_integer(H) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_IsExposed_4,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,W:32/?UI,H:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisretained">external documentation</a>.
+-spec isRetained(This) -> boolean() when
+ This::wxWindow().
isRetained(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_IsRetained,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowisshown">external documentation</a>.
+-spec isShown(This) -> boolean() when
+ This::wxWindow().
isShown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_IsShown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowistoplevel">external documentation</a>.
+-spec isTopLevel(This) -> boolean() when
+ This::wxWindow().
isTopLevel(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_IsTopLevel,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowlayout">external documentation</a>.
+-spec layout(This) -> boolean() when
+ This::wxWindow().
layout(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_Layout,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowlinedown">external documentation</a>.
+-spec lineDown(This) -> boolean() when
+ This::wxWindow().
lineDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_LineDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowlineup">external documentation</a>.
+-spec lineUp(This) -> boolean() when
+ This::wxWindow().
lineUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_LineUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowlower">external documentation</a>.
+-spec lower(This) -> ok when
+ This::wxWindow().
lower(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_Lower,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv makeModal(This, [])
+-spec makeModal(This) -> ok when
+ This::wxWindow().
+
makeModal(This)
when is_record(This, wx_ref) ->
makeModal(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {modal, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowmakemodal">external documentation</a>.
+-spec makeModal(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {modal, boolean()}.
makeModal(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -848,21 +957,25 @@ makeModal(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_MakeModal,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> ok
%% @equiv move(This,Pt, [])
+-spec move(This, Pt) -> ok when
+ This::wxWindow(), Pt::{X::integer(), Y::integer()}.
+
move(This,Pt={PtX,PtY})
when is_record(This, wx_ref),is_integer(PtX),is_integer(PtY) ->
move(This,Pt, []).
-%% @spec (This::wxWindow(),X::integer()|term(),X::integer()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowmove">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% move(This::wxWindow(), X::integer(), Y::integer()) -> move(This,X,Y, []) </c></p>
-%% <p><c>
-%% move(This::wxWindow(), Pt::{X::integer(),Y::integer()}, [Option]) -> ok </c>
-%%<br /> Option = {flags, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% move(This, Pt, [Option]) -> ok when<br />
+%% This::wxWindow(), Pt::{X::integer(), Y::integer()},<br />
+%% Option :: {flags, integer()}.<br />
+%%
+-spec move(This, X, Y) -> ok when
+ This::wxWindow(), X::integer(), Y::integer();
+ (This, Pt, [Option]) -> ok when
+ This::wxWindow(), Pt::{X::integer(), Y::integer()},
+ Option :: {flags, integer()}.
move(This,X,Y)
when is_record(This, wx_ref),is_integer(X),is_integer(Y) ->
@@ -876,9 +989,10 @@ move(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY}, Options)
wxe_util:cast(?wxWindow_Move_2,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer(), [Option]) -> ok
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowmove">external documentation</a>.
+-spec move(This, X, Y, [Option]) -> ok when
+ This::wxWindow(), X::integer(), Y::integer(),
+ Option :: {flags, integer()}.
move(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
when is_integer(X),is_integer(Y),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -888,31 +1002,36 @@ move(#wx_ref{type=ThisT,ref=ThisRef},X,Y, Options)
wxe_util:cast(?wxWindow_Move_3,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Win::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowmoveafterintaborder">external documentation</a>.
+-spec moveAfterInTabOrder(This, Win) -> ok when
+ This::wxWindow(), Win::wxWindow().
moveAfterInTabOrder(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(WinT,wxWindow),
wxe_util:cast(?wxWindow_MoveAfterInTabOrder,
<<ThisRef:32/?UI,WinRef:32/?UI>>).
-%% @spec (This::wxWindow(), Win::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowmovebeforeintaborder">external documentation</a>.
+-spec moveBeforeInTabOrder(This, Win) -> ok when
+ This::wxWindow(), Win::wxWindow().
moveBeforeInTabOrder(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(WinT,wxWindow),
wxe_util:cast(?wxWindow_MoveBeforeInTabOrder,
<<ThisRef:32/?UI,WinRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @equiv navigate(This, [])
+-spec navigate(This) -> boolean() when
+ This::wxWindow().
+
navigate(This)
when is_record(This, wx_ref) ->
navigate(This, []).
-%% @spec (This::wxWindow(), [Option]) -> bool()
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindownavigate">external documentation</a>.
+-spec navigate(This, [Option]) -> boolean() when
+ This::wxWindow(),
+ Option :: {flags, integer()}.
navigate(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -922,29 +1041,34 @@ navigate(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxWindow_Navigate,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowpagedown">external documentation</a>.
+-spec pageDown(This) -> boolean() when
+ This::wxWindow().
pageDown(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_PageDown,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowpageup">external documentation</a>.
+-spec pageUp(This) -> boolean() when
+ This::wxWindow().
pageUp(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_PageUp,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> wxEvtHandler:wxEvtHandler()
%% @equiv popEventHandler(This, [])
+-spec popEventHandler(This) -> wxEvtHandler:wxEvtHandler() when
+ This::wxWindow().
+
popEventHandler(This)
when is_record(This, wx_ref) ->
popEventHandler(This, []).
-%% @spec (This::wxWindow(), [Option]) -> wxEvtHandler:wxEvtHandler()
-%% Option = {deleteHandler, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowpopeventhandler">external documentation</a>.
+-spec popEventHandler(This, [Option]) -> wxEvtHandler:wxEvtHandler() when
+ This::wxWindow(),
+ Option :: {deleteHandler, boolean()}.
popEventHandler(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -954,15 +1078,18 @@ popEventHandler(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxWindow_PopEventHandler,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Menu::wxMenu:wxMenu()) -> bool()
%% @equiv popupMenu(This,Menu, [])
+-spec popupMenu(This, Menu) -> boolean() when
+ This::wxWindow(), Menu::wxMenu:wxMenu().
+
popupMenu(This,Menu)
when is_record(This, wx_ref),is_record(Menu, wx_ref) ->
popupMenu(This,Menu, []).
-%% @spec (This::wxWindow(), Menu::wxMenu:wxMenu(), [Option]) -> bool()
-%% Option = {pos, {X::integer(),Y::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowpopupmenu">external documentation</a>.
+-spec popupMenu(This, Menu, [Option]) -> boolean() when
+ This::wxWindow(), Menu::wxMenu:wxMenu(),
+ Option :: {pos, {X::integer(), Y::integer()}}.
popupMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -973,8 +1100,9 @@ popupMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef}, Optio
wxe_util:call(?wxWindow_PopupMenu_2,
<<ThisRef:32/?UI,MenuRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxWindow(), Menu::wxMenu:wxMenu(), X::integer(), Y::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowpopupmenu">external documentation</a>.
+-spec popupMenu(This, Menu, X, Y) -> boolean() when
+ This::wxWindow(), Menu::wxMenu:wxMenu(), X::integer(), Y::integer().
popupMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxWindow),
@@ -982,22 +1110,27 @@ popupMenu(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=MenuT,ref=MenuRef},X,Y)
wxe_util:call(?wxWindow_PopupMenu_3,
<<ThisRef:32/?UI,MenuRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowraise">external documentation</a>.
+-spec raise(This) -> ok when
+ This::wxWindow().
raise(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_Raise,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv refresh(This, [])
+-spec refresh(This) -> ok when
+ This::wxWindow().
+
refresh(This)
when is_record(This, wx_ref) ->
refresh(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {eraseBackground, bool()} | {rect, {X::integer(),Y::integer(),W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowrefresh">external documentation</a>.
+-spec refresh(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {eraseBackground, boolean()}
+ | {rect, {X::integer(), Y::integer(), W::integer(), H::integer()}}.
refresh(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1008,15 +1141,18 @@ refresh(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_Refresh,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok
%% @equiv refreshRect(This,Rect, [])
+-spec refreshRect(This, Rect) -> ok when
+ This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
+
refreshRect(This,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
refreshRect(This,Rect, []).
-%% @spec (This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> ok
-%% Option = {eraseBackground, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowrefreshrect">external documentation</a>.
+-spec refreshRect(This, Rect, [Option]) -> ok when
+ This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()},
+ Option :: {eraseBackground, boolean()}.
refreshRect(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH}, Options)
when is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1026,69 +1162,79 @@ refreshRect(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH}, Options)
wxe_util:cast(?wxWindow_RefreshRect,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowreleasemouse">external documentation</a>.
+-spec releaseMouse(This) -> ok when
+ This::wxWindow().
releaseMouse(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_ReleaseMouse,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Child::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowremovechild">external documentation</a>.
+-spec removeChild(This, Child) -> ok when
+ This::wxWindow(), Child::wxWindow().
removeChild(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ChildT,ref=ChildRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(ChildT,wxWindow),
wxe_util:cast(?wxWindow_RemoveChild,
<<ThisRef:32/?UI,ChildRef:32/?UI>>).
-%% @spec (This::wxWindow(), NewParent::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowreparent">external documentation</a>.
+-spec reparent(This, NewParent) -> boolean() when
+ This::wxWindow(), NewParent::wxWindow().
reparent(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=NewParentT,ref=NewParentRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(NewParentT,wxWindow),
wxe_util:call(?wxWindow_Reparent,
<<ThisRef:32/?UI,NewParentRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscreentoclient">external documentation</a>.
+-spec screenToClient(This) -> {X::integer(), Y::integer()} when
+ This::wxWindow().
screenToClient(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ScreenToClient_2,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Pt::{X::integer(),Y::integer()}) -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscreentoclient">external documentation</a>.
+-spec screenToClient(This, Pt) -> {X::integer(), Y::integer()} when
+ This::wxWindow(), Pt::{X::integer(), Y::integer()}.
screenToClient(#wx_ref{type=ThisT,ref=ThisRef},{PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ScreenToClient_1,
<<ThisRef:32/?UI,PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (This::wxWindow(), Lines::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscrolllines">external documentation</a>.
+-spec scrollLines(This, Lines) -> boolean() when
+ This::wxWindow(), Lines::integer().
scrollLines(#wx_ref{type=ThisT,ref=ThisRef},Lines)
when is_integer(Lines) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ScrollLines,
<<ThisRef:32/?UI,Lines:32/?UI>>).
-%% @spec (This::wxWindow(), Pages::integer()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscrollpages">external documentation</a>.
+-spec scrollPages(This, Pages) -> boolean() when
+ This::wxWindow(), Pages::integer().
scrollPages(#wx_ref{type=ThisT,ref=ThisRef},Pages)
when is_integer(Pages) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ScrollPages,
<<ThisRef:32/?UI,Pages:32/?UI>>).
-%% @spec (This::wxWindow(), Dx::integer(), Dy::integer()) -> ok
%% @equiv scrollWindow(This,Dx,Dy, [])
+-spec scrollWindow(This, Dx, Dy) -> ok when
+ This::wxWindow(), Dx::integer(), Dy::integer().
+
scrollWindow(This,Dx,Dy)
when is_record(This, wx_ref),is_integer(Dx),is_integer(Dy) ->
scrollWindow(This,Dx,Dy, []).
-%% @spec (This::wxWindow(), Dx::integer(), Dy::integer(), [Option]) -> ok
-%% Option = {rect, {X::integer(),Y::integer(),W::integer(),H::integer()}}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowscrollwindow">external documentation</a>.
+-spec scrollWindow(This, Dx, Dy, [Option]) -> ok when
+ This::wxWindow(), Dx::integer(), Dy::integer(),
+ Option :: {rect, {X::integer(), Y::integer(), W::integer(), H::integer()}}.
scrollWindow(#wx_ref{type=ThisT,ref=ThisRef},Dx,Dy, Options)
when is_integer(Dx),is_integer(Dy),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1098,57 +1244,61 @@ scrollWindow(#wx_ref{type=ThisT,ref=ThisRef},Dx,Dy, Options)
wxe_util:cast(?wxWindow_ScrollWindow,
<<ThisRef:32/?UI,Dx:32/?UI,Dy:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Accel::wxAcceleratorTable:wxAcceleratorTable()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetacceleratortable">external documentation</a>.
+-spec setAcceleratorTable(This, Accel) -> ok when
+ This::wxWindow(), Accel::wxAcceleratorTable:wxAcceleratorTable().
setAcceleratorTable(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=AccelT,ref=AccelRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(AccelT,wxAcceleratorTable),
wxe_util:cast(?wxWindow_SetAcceleratorTable,
<<ThisRef:32/?UI,AccelRef:32/?UI>>).
-%% @spec (This::wxWindow(), AutoLayout::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetautolayout">external documentation</a>.
+-spec setAutoLayout(This, AutoLayout) -> ok when
+ This::wxWindow(), AutoLayout::boolean().
setAutoLayout(#wx_ref{type=ThisT,ref=ThisRef},AutoLayout)
when is_boolean(AutoLayout) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetAutoLayout,
<<ThisRef:32/?UI,(wxe_util:from_bool(AutoLayout)):32/?UI>>).
-%% @spec (This::wxWindow(), Colour::wx:colour()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetbackgroundcolour">external documentation</a>.
+-spec setBackgroundColour(This, Colour) -> boolean() when
+ This::wxWindow(), Colour::wx:wx_colour().
setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_SetBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxWindow(), Style::WxBackgroundStyle) -> bool()
-%% WxBackgroundStyle = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetbackgroundstyle">external documentation</a>.
-%%<br /> WxBackgroundStyle is one of ?wxBG_STYLE_SYSTEM | ?wxBG_STYLE_COLOUR | ?wxBG_STYLE_CUSTOM
+%%<br /> Style = ?wxBG_STYLE_SYSTEM | ?wxBG_STYLE_COLOUR | ?wxBG_STYLE_CUSTOM
+-spec setBackgroundStyle(This, Style) -> boolean() when
+ This::wxWindow(), Style::wx:wx_enum().
setBackgroundStyle(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_SetBackgroundStyle,
<<ThisRef:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxWindow(), Caret::wxCaret:wxCaret()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetcaret">external documentation</a>.
+-spec setCaret(This, Caret) -> ok when
+ This::wxWindow(), Caret::wxCaret:wxCaret().
setCaret(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CaretT,ref=CaretRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(CaretT,wxCaret),
wxe_util:cast(?wxWindow_SetCaret,
<<ThisRef:32/?UI,CaretRef:32/?UI>>).
-%% @spec (This::wxWindow(),X::term()) -> ok
%% @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>
-%% </p>
-%% <p><c>
-%% setClientSize(This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setClientSize(This, Rect) -> ok when<br />
+%% This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.<br />
+%%
+-spec setClientSize(This, Size) -> ok when
+ This::wxWindow(), Size::{W::integer(), H::integer()};
+ (This, Rect) -> ok when
+ This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}.
setClientSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxWindow),
@@ -1160,118 +1310,133 @@ setClientSize(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH})
wxe_util:cast(?wxWindow_SetClientSize_1_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI>>).
-%% @spec (This::wxWindow(), Width::integer(), Height::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetclientsize">external documentation</a>.
+-spec setClientSize(This, Width, Height) -> ok when
+ This::wxWindow(), Width::integer(), Height::integer().
setClientSize(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetClientSize_2,
<<ThisRef:32/?UI,Width:32/?UI,Height:32/?UI>>).
-%% @spec (This::wxWindow(), Sizer::wxSizer:wxSizer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetcontainingsizer">external documentation</a>.
+-spec setContainingSizer(This, Sizer) -> ok when
+ This::wxWindow(), Sizer::wxSizer:wxSizer().
setContainingSizer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(SizerT,wxSizer),
wxe_util:cast(?wxWindow_SetContainingSizer,
<<ThisRef:32/?UI,SizerRef:32/?UI>>).
-%% @spec (This::wxWindow(), Cursor::wxCursor:wxCursor()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetcursor">external documentation</a>.
+-spec setCursor(This, Cursor) -> boolean() when
+ This::wxWindow(), Cursor::wxCursor:wxCursor().
setCursor(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CursorT,ref=CursorRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(CursorT,wxCursor),
wxe_util:call(?wxWindow_SetCursor,
<<ThisRef:32/?UI,CursorRef:32/?UI>>).
-%% @spec (This::wxWindow(), MaxSize::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetmaxsize">external documentation</a>.
+-spec setMaxSize(This, MaxSize) -> ok when
+ This::wxWindow(), MaxSize::{W::integer(), H::integer()}.
setMaxSize(#wx_ref{type=ThisT,ref=ThisRef},{MaxSizeW,MaxSizeH})
when is_integer(MaxSizeW),is_integer(MaxSizeH) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetMaxSize,
<<ThisRef:32/?UI,MaxSizeW:32/?UI,MaxSizeH:32/?UI>>).
-%% @spec (This::wxWindow(), MinSize::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetminsize">external documentation</a>.
+-spec setMinSize(This, MinSize) -> ok when
+ This::wxWindow(), MinSize::{W::integer(), H::integer()}.
setMinSize(#wx_ref{type=ThisT,ref=ThisRef},{MinSizeW,MinSizeH})
when is_integer(MinSizeW),is_integer(MinSizeH) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetMinSize,
<<ThisRef:32/?UI,MinSizeW:32/?UI,MinSizeH:32/?UI>>).
-%% @spec (This::wxWindow(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetownbackgroundcolour">external documentation</a>.
+-spec setOwnBackgroundColour(This, Colour) -> ok when
+ This::wxWindow(), Colour::wx:wx_colour().
setOwnBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetOwnBackgroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxWindow(), Font::wxFont:wxFont()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetownfont">external documentation</a>.
+-spec setOwnFont(This, Font) -> ok when
+ This::wxWindow(), Font::wxFont:wxFont().
setOwnFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(FontT,wxFont),
wxe_util:cast(?wxWindow_SetOwnFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxWindow(), Colour::wx:colour()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetownforegroundcolour">external documentation</a>.
+-spec setOwnForegroundColour(This, Colour) -> ok when
+ This::wxWindow(), Colour::wx:wx_colour().
setOwnForegroundColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetOwnForegroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxWindow(), DropTarget::wxDropTarget:wxDropTarget()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetdroptarget">external documentation</a>.
+-spec setDropTarget(This, DropTarget) -> ok when
+ This::wxWindow(), DropTarget::wx:wx_object().
setDropTarget(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DropTargetT,ref=DropTargetRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(DropTargetT,wxDropTarget),
wxe_util:cast(?wxWindow_SetDropTarget,
<<ThisRef:32/?UI,DropTargetRef:32/?UI>>).
-%% @spec (This::wxWindow(), ExStyle::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetextrastyle">external documentation</a>.
+-spec setExtraStyle(This, ExStyle) -> ok when
+ This::wxWindow(), ExStyle::integer().
setExtraStyle(#wx_ref{type=ThisT,ref=ThisRef},ExStyle)
when is_integer(ExStyle) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetExtraStyle,
<<ThisRef:32/?UI,ExStyle:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetfocus">external documentation</a>.
+-spec setFocus(This) -> ok when
+ This::wxWindow().
setFocus(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetFocus,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetfocusfromkbd">external documentation</a>.
+-spec setFocusFromKbd(This) -> ok when
+ This::wxWindow().
setFocusFromKbd(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetFocusFromKbd,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), Font::wxFont:wxFont()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetfont">external documentation</a>.
+-spec setFont(This, Font) -> boolean() when
+ This::wxWindow(), Font::wxFont:wxFont().
setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(FontT,wxFont),
wxe_util:call(?wxWindow_SetFont,
<<ThisRef:32/?UI,FontRef:32/?UI>>).
-%% @spec (This::wxWindow(), Colour::wx:colour()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetforegroundcolour">external documentation</a>.
+-spec setForegroundColour(This, Colour) -> boolean() when
+ This::wxWindow(), Colour::wx:wx_colour().
setForegroundColour(#wx_ref{type=ThisT,ref=ThisRef},Colour)
when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_SetForegroundColour,
<<ThisRef:32/?UI,(wxe_util:colour_bin(Colour)):16/binary>>).
-%% @spec (This::wxWindow(), Text::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsethelptext">external documentation</a>.
+-spec setHelpText(This, Text) -> ok when
+ This::wxWindow(), Text::unicode:chardata().
setHelpText(#wx_ref{type=ThisT,ref=ThisRef},Text)
when is_list(Text) ->
?CLASS(ThisT,wxWindow),
@@ -1279,16 +1444,18 @@ setHelpText(#wx_ref{type=ThisT,ref=ThisRef},Text)
wxe_util:cast(?wxWindow_SetHelpText,
<<ThisRef:32/?UI,(byte_size(Text_UC)):32/?UI,(Text_UC)/binary, 0:(((8- ((0+byte_size(Text_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxWindow(), Winid::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetid">external documentation</a>.
+-spec setId(This, Winid) -> ok when
+ This::wxWindow(), Winid::integer().
setId(#wx_ref{type=ThisT,ref=ThisRef},Winid)
when is_integer(Winid) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetId,
<<ThisRef:32/?UI,Winid:32/?UI>>).
-%% @spec (This::wxWindow(), Label::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetlabel">external documentation</a>.
+-spec setLabel(This, Label) -> ok when
+ This::wxWindow(), Label::unicode:chardata().
setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
when is_list(Label) ->
?CLASS(ThisT,wxWindow),
@@ -1296,8 +1463,9 @@ setLabel(#wx_ref{type=ThisT,ref=ThisRef},Label)
wxe_util:cast(?wxWindow_SetLabel,
<<ThisRef:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((0+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxWindow(), Name::string()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetname">external documentation</a>.
+-spec setName(This, Name) -> ok when
+ This::wxWindow(), Name::unicode:chardata().
setName(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxWindow),
@@ -1305,23 +1473,27 @@ setName(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:cast(?wxWindow_SetName,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxWindow(), Pal::wxPalette:wxPalette()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetpalette">external documentation</a>.
+-spec setPalette(This, Pal) -> ok when
+ This::wxWindow(), Pal::wxPalette:wxPalette().
setPalette(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PalT,ref=PalRef}) ->
?CLASS(ThisT,wxWindow),
?CLASS(PalT,wxPalette),
wxe_util:cast(?wxWindow_SetPalette,
<<ThisRef:32/?UI,PalRef:32/?UI>>).
-%% @spec (This::wxWindow(), Orient::integer(), Pos::integer(), ThumbVisible::integer(), Range::integer()) -> ok
%% @equiv setScrollbar(This,Orient,Pos,ThumbVisible,Range, [])
+-spec setScrollbar(This, Orient, Pos, ThumbVisible, Range) -> ok when
+ This::wxWindow(), Orient::integer(), Pos::integer(), ThumbVisible::integer(), Range::integer().
+
setScrollbar(This,Orient,Pos,ThumbVisible,Range)
when is_record(This, wx_ref),is_integer(Orient),is_integer(Pos),is_integer(ThumbVisible),is_integer(Range) ->
setScrollbar(This,Orient,Pos,ThumbVisible,Range, []).
-%% @spec (This::wxWindow(), Orient::integer(), Pos::integer(), ThumbVisible::integer(), Range::integer(), [Option]) -> ok
-%% Option = {refresh, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetscrollbar">external documentation</a>.
+-spec setScrollbar(This, Orient, Pos, ThumbVisible, Range, [Option]) -> ok when
+ This::wxWindow(), Orient::integer(), Pos::integer(), ThumbVisible::integer(), Range::integer(),
+ Option :: {refresh, boolean()}.
setScrollbar(#wx_ref{type=ThisT,ref=ThisRef},Orient,Pos,ThumbVisible,Range, Options)
when is_integer(Orient),is_integer(Pos),is_integer(ThumbVisible),is_integer(Range),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1331,15 +1503,18 @@ setScrollbar(#wx_ref{type=ThisT,ref=ThisRef},Orient,Pos,ThumbVisible,Range, Opti
wxe_util:cast(?wxWindow_SetScrollbar,
<<ThisRef:32/?UI,Orient:32/?UI,Pos:32/?UI,ThumbVisible:32/?UI,Range:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Orient::integer(), Pos::integer()) -> ok
%% @equiv setScrollPos(This,Orient,Pos, [])
+-spec setScrollPos(This, Orient, Pos) -> ok when
+ This::wxWindow(), Orient::integer(), Pos::integer().
+
setScrollPos(This,Orient,Pos)
when is_record(This, wx_ref),is_integer(Orient),is_integer(Pos) ->
setScrollPos(This,Orient,Pos, []).
-%% @spec (This::wxWindow(), Orient::integer(), Pos::integer(), [Option]) -> ok
-%% Option = {refresh, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetscrollpos">external documentation</a>.
+-spec setScrollPos(This, Orient, Pos, [Option]) -> ok when
+ This::wxWindow(), Orient::integer(), Pos::integer(),
+ Option :: {refresh, boolean()}.
setScrollPos(#wx_ref{type=ThisT,ref=ThisRef},Orient,Pos, Options)
when is_integer(Orient),is_integer(Pos),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1349,14 +1524,15 @@ setScrollPos(#wx_ref{type=ThisT,ref=ThisRef},Orient,Pos, Options)
wxe_util:cast(?wxWindow_SetScrollPos,
<<ThisRef:32/?UI,Orient:32/?UI,Pos:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(),X::term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsize">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setSize(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> setSize(This,Rect, []) </c></p>
-%% <p><c>
-%% setSize(This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setSize(This, Size) -> ok when<br />
+%% This::wxWindow(), Size::{W::integer(), H::integer()}.<br />
+%%
+-spec setSize(This, Rect) -> ok when
+ This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()};
+ (This, Size) -> ok when
+ This::wxWindow(), Size::{W::integer(), H::integer()}.
setSize(This,Rect={RectX,RectY,RectW,RectH})
when is_record(This, wx_ref),is_integer(RectX),is_integer(RectY),is_integer(RectW),is_integer(RectH) ->
@@ -1367,16 +1543,17 @@ setSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
wxe_util:cast(?wxWindow_SetSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxWindow(),X::integer()|term(),X::integer()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsize">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setSize(This::wxWindow(), Width::integer(), Height::integer()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setSize(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}, [Option]) -> ok </c>
-%%<br /> Option = {sizeFlags, integer()}
-%% </p>
+%% <br /> Also:<br />
+%% setSize(This, Rect, [Option]) -> ok when<br />
+%% This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()},<br />
+%% Option :: {sizeFlags, integer()}.<br />
+%%
+-spec setSize(This, Width, Height) -> ok when
+ This::wxWindow(), Width::integer(), Height::integer();
+ (This, Rect, [Option]) -> ok when
+ This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()},
+ Option :: {sizeFlags, integer()}.
setSize(#wx_ref{type=ThisT,ref=ThisRef},Width,Height)
when is_integer(Width),is_integer(Height) ->
?CLASS(ThisT,wxWindow),
@@ -1391,15 +1568,18 @@ setSize(#wx_ref{type=ThisT,ref=ThisRef},{RectX,RectY,RectW,RectH}, Options)
wxe_util:cast(?wxWindow_SetSize_2_1,
<<ThisRef:32/?UI,RectX:32/?UI,RectY:32/?UI,RectW:32/?UI,RectH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer()) -> ok
%% @equiv setSize(This,X,Y,Width,Height, [])
+-spec setSize(This, X, Y, Width, Height) -> ok when
+ This::wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer().
+
setSize(This,X,Y,Width,Height)
when is_record(This, wx_ref),is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height) ->
setSize(This,X,Y,Width,Height, []).
-%% @spec (This::wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer(), [Option]) -> ok
-%% Option = {sizeFlags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsize">external documentation</a>.
+-spec setSize(This, X, Y, Width, Height, [Option]) -> ok when
+ This::wxWindow(), X::integer(), Y::integer(), Width::integer(), Height::integer(),
+ Option :: {sizeFlags, integer()}.
setSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Width,Height, Options)
when is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1409,21 +1589,27 @@ setSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y,Width,Height, Options)
wxe_util:cast(?wxWindow_SetSize_5,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), MinSize::{W::integer(),H::integer()}) -> ok
%% @equiv setSizeHints(This,MinSize, [])
+-spec setSizeHints(This, MinSize) -> ok when
+ This::wxWindow(), MinSize::{W::integer(), H::integer()}.
+
setSizeHints(This,MinSize={MinSizeW,MinSizeH})
when is_record(This, wx_ref),is_integer(MinSizeW),is_integer(MinSizeH) ->
setSizeHints(This,MinSize, []).
-%% @spec (This::wxWindow(),X::integer()|term(),X::integer()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsizehints">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setSizeHints(This::wxWindow(), MinW::integer(), MinH::integer()) -> setSizeHints(This,MinW,MinH, []) </c></p>
-%% <p><c>
-%% setSizeHints(This::wxWindow(), MinSize::{W::integer(),H::integer()}, [Option]) -> ok </c>
-%%<br /> Option = {maxSize, {W::integer(),H::integer()}} | {incSize, {W::integer(),H::integer()}}
-%% </p>
+%% <br /> Also:<br />
+%% setSizeHints(This, MinSize, [Option]) -> ok when<br />
+%% This::wxWindow(), MinSize::{W::integer(), H::integer()},<br />
+%% Option :: {maxSize, {W::integer(), H::integer()}}<br />
+%% | {incSize, {W::integer(), H::integer()}}.<br />
+%%
+-spec setSizeHints(This, MinW, MinH) -> ok when
+ This::wxWindow(), MinW::integer(), MinH::integer();
+ (This, MinSize, [Option]) -> ok when
+ This::wxWindow(), MinSize::{W::integer(), H::integer()},
+ Option :: {maxSize, {W::integer(), H::integer()}}
+ | {incSize, {W::integer(), H::integer()}}.
setSizeHints(This,MinW,MinH)
when is_record(This, wx_ref),is_integer(MinW),is_integer(MinH) ->
@@ -1438,9 +1624,13 @@ setSizeHints(#wx_ref{type=ThisT,ref=ThisRef},{MinSizeW,MinSizeH}, Options)
wxe_util:cast(?wxWindow_SetSizeHints_2,
<<ThisRef:32/?UI,MinSizeW:32/?UI,MinSizeH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), MinW::integer(), MinH::integer(), [Option]) -> ok
-%% Option = {maxW, integer()} | {maxH, integer()} | {incW, integer()} | {incH, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsizehints">external documentation</a>.
+-spec setSizeHints(This, MinW, MinH, [Option]) -> ok when
+ This::wxWindow(), MinW::integer(), MinH::integer(),
+ Option :: {maxW, integer()}
+ | {maxH, integer()}
+ | {incW, integer()}
+ | {incH, integer()}.
setSizeHints(#wx_ref{type=ThisT,ref=ThisRef},MinW,MinH, Options)
when is_integer(MinW),is_integer(MinH),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1453,15 +1643,18 @@ setSizeHints(#wx_ref{type=ThisT,ref=ThisRef},MinW,MinH, Options)
wxe_util:cast(?wxWindow_SetSizeHints_3,
<<ThisRef:32/?UI,MinW:32/?UI,MinH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Sizer::wxSizer:wxSizer()) -> ok
%% @equiv setSizer(This,Sizer, [])
+-spec setSizer(This, Sizer) -> ok when
+ This::wxWindow(), Sizer::wxSizer:wxSizer().
+
setSizer(This,Sizer)
when is_record(This, wx_ref),is_record(Sizer, wx_ref) ->
setSizer(This,Sizer, []).
-%% @spec (This::wxWindow(), Sizer::wxSizer:wxSizer(), [Option]) -> ok
-%% Option = {deleteOld, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsizer">external documentation</a>.
+-spec setSizer(This, Sizer, [Option]) -> ok when
+ This::wxWindow(), Sizer::wxSizer:wxSizer(),
+ Option :: {deleteOld, boolean()}.
setSizer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1472,15 +1665,18 @@ setSizer(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}, Opti
wxe_util:cast(?wxWindow_SetSizer,
<<ThisRef:32/?UI,SizerRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxWindow(), Sizer::wxSizer:wxSizer()) -> ok
%% @equiv setSizerAndFit(This,Sizer, [])
+-spec setSizerAndFit(This, Sizer) -> ok when
+ This::wxWindow(), Sizer::wxSizer:wxSizer().
+
setSizerAndFit(This,Sizer)
when is_record(This, wx_ref),is_record(Sizer, wx_ref) ->
setSizerAndFit(This,Sizer, []).
-%% @spec (This::wxWindow(), Sizer::wxSizer:wxSizer(), [Option]) -> ok
-%% Option = {deleteOld, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetsizerandfit">external documentation</a>.
+-spec setSizerAndFit(This, Sizer, [Option]) -> ok when
+ This::wxWindow(), Sizer::wxSizer:wxSizer(),
+ Option :: {deleteOld, boolean()}.
setSizerAndFit(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1491,23 +1687,24 @@ setSizerAndFit(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=SizerT,ref=SizerRef}
wxe_util:cast(?wxWindow_SetSizerAndFit,
<<ThisRef:32/?UI,SizerRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxWindow(), EnableTheme::bool()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetthemeenabled">external documentation</a>.
+-spec setThemeEnabled(This, EnableTheme) -> ok when
+ This::wxWindow(), EnableTheme::boolean().
setThemeEnabled(#wx_ref{type=ThisT,ref=ThisRef},EnableTheme)
when is_boolean(EnableTheme) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetThemeEnabled,
<<ThisRef:32/?UI,(wxe_util:from_bool(EnableTheme)):32/?UI>>).
-%% @spec (This::wxWindow(),X::string()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsettooltip">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setToolTip(This::wxWindow(), Tip::string()) -> ok </c>
-%% </p>
-%% <p><c>
-%% setToolTip(This::wxWindow(), Tip::wxToolTip:wxToolTip()) -> ok </c>
-%% </p>
+%% <br /> Also:<br />
+%% setToolTip(This, Tip) -> ok when<br />
+%% This::wxWindow(), Tip::wxToolTip:wxToolTip().<br />
+%%
+-spec setToolTip(This, Tip) -> ok when
+ This::wxWindow(), Tip::unicode:chardata();
+ (This, Tip) -> ok when
+ This::wxWindow(), Tip::wxToolTip:wxToolTip().
setToolTip(#wx_ref{type=ThisT,ref=ThisRef},Tip)
when is_list(Tip) ->
?CLASS(ThisT,wxWindow),
@@ -1520,37 +1717,43 @@ setToolTip(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=TipT,ref=TipRef}) ->
wxe_util:cast(?wxWindow_SetToolTip_1_1,
<<ThisRef:32/?UI,TipRef:32/?UI>>).
-%% @spec (This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetvirtualsize">external documentation</a>.
+-spec setVirtualSize(This, Size) -> ok when
+ This::wxWindow(), Size::{W::integer(), H::integer()}.
setVirtualSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetVirtualSize_1,
<<ThisRef:32/?UI,SizeW:32/?UI,SizeH:32/?UI>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetvirtualsize">external documentation</a>.
+-spec setVirtualSize(This, X, Y) -> ok when
+ This::wxWindow(), X::integer(), Y::integer().
setVirtualSize(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetVirtualSize_2,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxWindow(), MinSize::{W::integer(),H::integer()}) -> ok
%% @equiv setVirtualSizeHints(This,MinSize, [])
+-spec setVirtualSizeHints(This, MinSize) -> ok when
+ This::wxWindow(), MinSize::{W::integer(), H::integer()}.
+
setVirtualSizeHints(This,MinSize={MinSizeW,MinSizeH})
when is_record(This, wx_ref),is_integer(MinSizeW),is_integer(MinSizeH) ->
setVirtualSizeHints(This,MinSize, []).
-%% @spec (This::wxWindow(),X::integer()|term(),X::integer()|term()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetvirtualsizehints">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% setVirtualSizeHints(This::wxWindow(), MinW::integer(), MinH::integer()) -> setVirtualSizeHints(This,MinW,MinH, []) </c></p>
-%% <p><c>
-%% setVirtualSizeHints(This::wxWindow(), MinSize::{W::integer(),H::integer()}, [Option]) -> ok </c>
-%%<br /> Option = {maxSize, {W::integer(),H::integer()}}
-%% </p>
+%% <br /> Also:<br />
+%% setVirtualSizeHints(This, MinSize, [Option]) -> ok when<br />
+%% This::wxWindow(), MinSize::{W::integer(), H::integer()},<br />
+%% Option :: {maxSize, {W::integer(), H::integer()}}.<br />
+%%
+-spec setVirtualSizeHints(This, MinW, MinH) -> ok when
+ This::wxWindow(), MinW::integer(), MinH::integer();
+ (This, MinSize, [Option]) -> ok when
+ This::wxWindow(), MinSize::{W::integer(), H::integer()},
+ Option :: {maxSize, {W::integer(), H::integer()}}.
setVirtualSizeHints(This,MinW,MinH)
when is_record(This, wx_ref),is_integer(MinW),is_integer(MinH) ->
@@ -1564,9 +1767,11 @@ setVirtualSizeHints(#wx_ref{type=ThisT,ref=ThisRef},{MinSizeW,MinSizeH}, Options
wxe_util:cast(?wxWindow_SetVirtualSizeHints_2,
<<ThisRef:32/?UI,MinSizeW:32/?UI,MinSizeH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), MinW::integer(), MinH::integer(), [Option]) -> ok
-%% Option = {maxW, integer()} | {maxH, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetvirtualsizehints">external documentation</a>.
+-spec setVirtualSizeHints(This, MinW, MinH, [Option]) -> ok when
+ This::wxWindow(), MinW::integer(), MinH::integer(),
+ Option :: {maxW, integer()}
+ | {maxH, integer()}.
setVirtualSizeHints(#wx_ref{type=ThisT,ref=ThisRef},MinW,MinH, Options)
when is_integer(MinW),is_integer(MinH),is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1577,48 +1782,54 @@ setVirtualSizeHints(#wx_ref{type=ThisT,ref=ThisRef},MinW,MinH, Options)
wxe_util:cast(?wxWindow_SetVirtualSizeHints_3,
<<ThisRef:32/?UI,MinW:32/?UI,MinH:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetwindowstyle">external documentation</a>.
+-spec setWindowStyle(This, Style) -> ok when
+ This::wxWindow(), Style::integer().
setWindowStyle(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetWindowStyle,
<<ThisRef:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxWindow(), Style::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetwindowstyleflag">external documentation</a>.
+-spec setWindowStyleFlag(This, Style) -> ok when
+ This::wxWindow(), Style::integer().
setWindowStyleFlag(#wx_ref{type=ThisT,ref=ThisRef},Style)
when is_integer(Style) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetWindowStyleFlag,
<<ThisRef:32/?UI,Style:32/?UI>>).
-%% @spec (This::wxWindow(), Variant::WxWindowVariant) -> ok
-%% WxWindowVariant = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetwindowvariant">external documentation</a>.
-%%<br /> WxWindowVariant is one of ?wxWINDOW_VARIANT_NORMAL | ?wxWINDOW_VARIANT_SMALL | ?wxWINDOW_VARIANT_MINI | ?wxWINDOW_VARIANT_LARGE | ?wxWINDOW_VARIANT_MAX
+%%<br /> Variant = ?wxWINDOW_VARIANT_NORMAL | ?wxWINDOW_VARIANT_SMALL | ?wxWINDOW_VARIANT_MINI | ?wxWINDOW_VARIANT_LARGE | ?wxWINDOW_VARIANT_MAX
+-spec setWindowVariant(This, Variant) -> ok when
+ This::wxWindow(), Variant::wx:wx_enum().
setWindowVariant(#wx_ref{type=ThisT,ref=ThisRef},Variant)
when is_integer(Variant) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_SetWindowVariant,
<<ThisRef:32/?UI,Variant:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowshouldinheritcolours">external documentation</a>.
+-spec shouldInheritColours(This) -> boolean() when
+ This::wxWindow().
shouldInheritColours(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_ShouldInheritColours,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @equiv show(This, [])
+-spec show(This) -> boolean() when
+ This::wxWindow().
+
show(This)
when is_record(This, wx_ref) ->
show(This, []).
-%% @spec (This::wxWindow(), [Option]) -> bool()
-%% Option = {show, bool()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowshow">external documentation</a>.
+-spec show(This, [Option]) -> boolean() when
+ This::wxWindow(),
+ Option :: {show, boolean()}.
show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1628,43 +1839,50 @@ show(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:call(?wxWindow_Show,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowthaw">external documentation</a>.
+-spec thaw(This) -> ok when
+ This::wxWindow().
thaw(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_Thaw,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowtransferdatafromwindow">external documentation</a>.
+-spec transferDataFromWindow(This) -> boolean() when
+ This::wxWindow().
transferDataFromWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_TransferDataFromWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowtransferdatatowindow">external documentation</a>.
+-spec transferDataToWindow(This) -> boolean() when
+ This::wxWindow().
transferDataToWindow(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_TransferDataToWindow,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowupdate">external documentation</a>.
+-spec update(This) -> ok when
+ This::wxWindow().
update(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_Update,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @equiv updateWindowUI(This, [])
+-spec updateWindowUI(This) -> ok when
+ This::wxWindow().
+
updateWindowUI(This)
when is_record(This, wx_ref) ->
updateWindowUI(This, []).
-%% @spec (This::wxWindow(), [Option]) -> ok
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowupdatewindowui">external documentation</a>.
+-spec updateWindowUI(This, [Option]) -> ok when
+ This::wxWindow(),
+ Option :: {flags, integer()}.
updateWindowUI(#wx_ref{type=ThisT,ref=ThisRef}, Options)
when is_list(Options) ->
?CLASS(ThisT,wxWindow),
@@ -1674,23 +1892,25 @@ updateWindowUI(#wx_ref{type=ThisT,ref=ThisRef}, Options)
wxe_util:cast(?wxWindow_UpdateWindowUI,
<<ThisRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxWindow()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowvalidate">external documentation</a>.
+-spec validate(This) -> boolean() when
+ This::wxWindow().
validate(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxWindow),
wxe_util:call(?wxWindow_Validate,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxWindow(), X::integer(), Y::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowwarppointer">external documentation</a>.
+-spec warpPointer(This, X, Y) -> ok when
+ This::wxWindow(), X::integer(), Y::integer().
warpPointer(#wx_ref{type=ThisT,ref=ThisRef},X,Y)
when is_integer(X),is_integer(Y) ->
?CLASS(ThisT,wxWindow),
wxe_util:cast(?wxWindow_WarpPointer,
<<ThisRef:32/?UI,X:32/?UI,Y:32/?UI>>).
-%% @spec (This::wxWindow()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxWindow()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxWindow),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wxWindowCreateEvent.erl b/lib/wx/src/gen/wxWindowCreateEvent.erl
index c8b3c74f81..f17d6011d9 100644
--- a/lib/wx/src/gen/wxWindowCreateEvent.erl
+++ b/lib/wx/src/gen/wxWindowCreateEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,11 +40,13 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxWindowCreateEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxWindowCreateEvent() :: wx:wx_object().
%% From wxCommandEvent
%% @hidden
setString(This,S) -> wxCommandEvent:setString(This,S).
diff --git a/lib/wx/src/gen/wxWindowDC.erl b/lib/wx/src/gen/wxWindowDC.erl
index 17cbd3d378..babb3c0e90 100644
--- a/lib/wx/src/gen/wxWindowDC.erl
+++ b/lib/wx/src/gen/wxWindowDC.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,10 +38,10 @@
drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
- getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/2,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
- getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/3,
- getPen/1,getPixel/3,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
@@ -52,25 +52,28 @@
setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
startPage/1]).
+-export_type([wxWindowDC/0]).
%% @hidden
parent_class(wxDC) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxWindowDC()
+-type wxWindowDC() :: wx:wx_object().
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindowdc.html#wxwindowdcwxwindowdc">external documentation</a>.
+-spec new() -> wxWindowDC().
new() ->
wxe_util:construct(?wxWindowDC_new_0,
<<>>).
-%% @spec (Win::wxWindow:wxWindow()) -> wxWindowDC()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindowdc.html#wxwindowdcwxwindowdc">external documentation</a>.
+-spec new(Win) -> wxWindowDC() when
+ Win::wxWindow:wxWindow().
new(#wx_ref{type=WinT,ref=WinRef}) ->
?CLASS(WinT,wxWindow),
wxe_util:construct(?wxWindowDC_new_1,
<<WinRef:32/?UI>>).
-%% @spec (This::wxWindowDC()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxWindowDC()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxWindowDC),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
@@ -157,11 +160,11 @@ getSize(This) -> wxDC:getSize(This).
%% @hidden
getPPI(This) -> wxDC:getPPI(This).
%% @hidden
-getPixel(This,Pt,Col) -> wxDC:getPixel(This,Pt,Col).
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
%% @hidden
getPen(This) -> wxDC:getPen(This).
%% @hidden
-getPartialTextExtents(This,Text,Widths) -> wxDC:getPartialTextExtents(This,Text,Widths).
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
%% @hidden
getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
%% @hidden
@@ -175,7 +178,7 @@ getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
%% @hidden
getFont(This) -> wxDC:getFont(This).
%% @hidden
-getClippingBox(This,Rect) -> wxDC:getClippingBox(This,Rect).
+getClippingBox(This) -> wxDC:getClippingBox(This).
%% @hidden
getCharWidth(This) -> wxDC:getCharWidth(This).
%% @hidden
diff --git a/lib/wx/src/gen/wxWindowDestroyEvent.erl b/lib/wx/src/gen/wxWindowDestroyEvent.erl
index e62700da4a..909f521d82 100644
--- a/lib/wx/src/gen/wxWindowDestroyEvent.erl
+++ b/lib/wx/src/gen/wxWindowDestroyEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,11 +40,13 @@
parent_class/1,resumePropagation/2,setInt/2,setString/2,shouldPropagate/1,
skip/1,skip/2,stopPropagation/1]).
+-export_type([wxWindowDestroyEvent/0]).
%% @hidden
parent_class(wxCommandEvent) -> true;
parent_class(wxEvent) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+-type wxWindowDestroyEvent() :: wx:wx_object().
%% From wxCommandEvent
%% @hidden
setString(This,S) -> wxCommandEvent:setString(This,S).
diff --git a/lib/wx/src/gen/wxXmlResource.erl b/lib/wx/src/gen/wxXmlResource.erl
index 2b69a49bd7..aa0cffb5a8 100644
--- a/lib/wx/src/gen/wxXmlResource.erl
+++ b/lib/wx/src/gen/wxXmlResource.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,17 +34,21 @@
%% inherited exports
-export([parent_class/1]).
+-export_type([wxXmlResource/0]).
%% @hidden
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
-%% @spec () -> wxXmlResource()
+-type wxXmlResource() :: wx:wx_object().
%% @equiv new([])
+-spec new() -> wxXmlResource().
+
new() ->
new([]).
-%% @spec ([Option]) -> wxXmlResource()
-%% Option = {flags, integer()} | {domain, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcewxxmlresource">external documentation</a>.
+-spec new([Option]) -> wxXmlResource() when
+ Option :: {flags, integer()}
+ | {domain, unicode:chardata()}.
new(Options)
when is_list(Options) ->
MOpts = fun({flags, Flags}, Acc) -> [<<1:32/?UI,Flags:32/?UI>>|Acc];
@@ -54,9 +58,11 @@ new(Options)
wxe_util:construct(?wxXmlResource_new_1,
<<BinOpt/binary>>).
-%% @spec (Filemask::string(), [Option]) -> wxXmlResource()
-%% Option = {flags, integer()} | {domain, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcewxxmlresource">external documentation</a>.
+-spec new(Filemask, [Option]) -> wxXmlResource() when
+ Filemask::unicode:chardata(),
+ Option :: {flags, integer()}
+ | {domain, unicode:chardata()}.
new(Filemask, Options)
when is_list(Filemask),is_list(Options) ->
Filemask_UC = unicode:characters_to_binary([Filemask,0]),
@@ -67,15 +73,18 @@ new(Filemask, Options)
wxe_util:construct(?wxXmlResource_new_2,
<<(byte_size(Filemask_UC)):32/?UI,(Filemask_UC)/binary, 0:(((8- ((4+byte_size(Filemask_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxXmlResource(), Name::string(), Control::wxWindow:wxWindow()) -> bool()
%% @equiv attachUnknownControl(This,Name,Control, [])
+-spec attachUnknownControl(This, Name, Control) -> boolean() when
+ This::wxXmlResource(), Name::unicode:chardata(), Control::wxWindow:wxWindow().
+
attachUnknownControl(This,Name,Control)
when is_record(This, wx_ref),is_list(Name),is_record(Control, wx_ref) ->
attachUnknownControl(This,Name,Control, []).
-%% @spec (This::wxXmlResource(), Name::string(), Control::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {parent, wxWindow:wxWindow()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceattachunknowncontrol">external documentation</a>.
+-spec attachUnknownControl(This, Name, Control, [Option]) -> boolean() when
+ This::wxXmlResource(), Name::unicode:chardata(), Control::wxWindow:wxWindow(),
+ Option :: {parent, wxWindow:wxWindow()}.
attachUnknownControl(#wx_ref{type=ThisT,ref=ThisRef},Name,#wx_ref{type=ControlT,ref=ControlRef}, Options)
when is_list(Name),is_list(Options) ->
?CLASS(ThisT,wxXmlResource),
@@ -87,50 +96,57 @@ attachUnknownControl(#wx_ref{type=ThisT,ref=ThisRef},Name,#wx_ref{type=ControlT,
wxe_util:call(?wxXmlResource_AttachUnknownControl,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8,ControlRef:32/?UI, 0:32,BinOpt/binary>>).
-%% @spec (This::wxXmlResource()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceclearhandlers">external documentation</a>.
+-spec clearHandlers(This) -> ok when
+ This::wxXmlResource().
clearHandlers(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxXmlResource),
wxe_util:cast(?wxXmlResource_ClearHandlers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxXmlResource(), Major::integer(), Minor::integer(), Release::integer(), Revision::integer()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcecompareversion">external documentation</a>.
+-spec compareVersion(This, Major, Minor, Release, Revision) -> integer() when
+ This::wxXmlResource(), Major::integer(), Minor::integer(), Release::integer(), Revision::integer().
compareVersion(#wx_ref{type=ThisT,ref=ThisRef},Major,Minor,Release,Revision)
when is_integer(Major),is_integer(Minor),is_integer(Release),is_integer(Revision) ->
?CLASS(ThisT,wxXmlResource),
wxe_util:call(?wxXmlResource_CompareVersion,
<<ThisRef:32/?UI,Major:32/?UI,Minor:32/?UI,Release:32/?UI,Revision:32/?UI>>).
-%% @spec () -> wxXmlResource()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceget">external documentation</a>.
+-spec get() -> wxXmlResource().
get() ->
wxe_util:call(?wxXmlResource_Get,
<<>>).
-%% @spec (This::wxXmlResource()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcegetflags">external documentation</a>.
+-spec getFlags(This) -> integer() when
+ This::wxXmlResource().
getFlags(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxXmlResource),
wxe_util:call(?wxXmlResource_GetFlags,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxXmlResource()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcegetversion">external documentation</a>.
+-spec getVersion(This) -> integer() when
+ This::wxXmlResource().
getVersion(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxXmlResource),
wxe_util:call(?wxXmlResource_GetVersion,
<<ThisRef:32/?UI>>).
-%% @spec (Str_id::[string()]) -> integer()
%% @equiv getXRCID(Str_id, [])
+-spec getXRCID(Str_id) -> integer() when
+ Str_id::[unicode:chardata()].
+
getXRCID(Str_id)
when is_list(Str_id) ->
getXRCID(Str_id, []).
-%% @spec (Str_id::[string()], [Option]) -> integer()
-%% Option = {value_if_not_found, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcegetxrcid">external documentation</a>.
+-spec getXRCID(Str_id, [Option]) -> integer() when
+ Str_id::[unicode:chardata()],
+ Option :: {value_if_not_found, integer()}.
getXRCID(Str_id, Options)
when is_list(Str_id),is_list(Options) ->
Str_id_UC = unicode:characters_to_binary([Str_id,0]),
@@ -140,15 +156,17 @@ getXRCID(Str_id, Options)
wxe_util:call(?wxXmlResource_GetXRCID,
<<(byte_size(Str_id_UC)):32/?UI,(Str_id_UC)/binary, 0:(((8- ((4+byte_size(Str_id_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec (This::wxXmlResource()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceinitallhandlers">external documentation</a>.
+-spec initAllHandlers(This) -> ok when
+ This::wxXmlResource().
initAllHandlers(#wx_ref{type=ThisT,ref=ThisRef}) ->
?CLASS(ThisT,wxXmlResource),
wxe_util:cast(?wxXmlResource_InitAllHandlers,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxXmlResource(), Filemask::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceload">external documentation</a>.
+-spec load(This, Filemask) -> boolean() when
+ This::wxXmlResource(), Filemask::unicode:chardata().
load(#wx_ref{type=ThisT,ref=ThisRef},Filemask)
when is_list(Filemask) ->
?CLASS(ThisT,wxXmlResource),
@@ -156,8 +174,9 @@ load(#wx_ref{type=ThisT,ref=ThisRef},Filemask)
wxe_util:call(?wxXmlResource_Load,
<<ThisRef:32/?UI,(byte_size(Filemask_UC)):32/?UI,(Filemask_UC)/binary, 0:(((8- ((0+byte_size(Filemask_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Name::string()) -> wxBitmap:wxBitmap()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadbitmap">external documentation</a>.
+-spec loadBitmap(This, Name) -> wxBitmap:wxBitmap() when
+ This::wxXmlResource(), Name::unicode:chardata().
loadBitmap(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -165,8 +184,9 @@ loadBitmap(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxXmlResource_LoadBitmap,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::string()) -> wxDialog:wxDialog()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloaddialog">external documentation</a>.
+-spec loadDialog(This, Parent, Name) -> wxDialog:wxDialog() when
+ This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadDialog(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -175,8 +195,9 @@ loadDialog(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},N
wxe_util:call(?wxXmlResource_LoadDialog_2,
<<ThisRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Dlg::wxDialog:wxDialog(), Parent::wxWindow:wxWindow(), Name::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloaddialog">external documentation</a>.
+-spec loadDialog(This, Dlg, Parent, Name) -> boolean() when
+ This::wxXmlResource(), Dlg::wxDialog:wxDialog(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadDialog(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DlgT,ref=DlgRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -186,8 +207,9 @@ loadDialog(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=DlgT,ref=DlgRef},#wx_ref
wxe_util:call(?wxXmlResource_LoadDialog_3,
<<ThisRef:32/?UI,DlgRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::string()) -> wxFrame:wxFrame()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadframe">external documentation</a>.
+-spec loadFrame(This, Parent, Name) -> wxFrame:wxFrame() when
+ This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -196,8 +218,9 @@ loadFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Na
wxe_util:call(?wxXmlResource_LoadFrame_2,
<<ThisRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Frame::wxFrame:wxFrame(), Parent::wxWindow:wxWindow(), Name::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadframe">external documentation</a>.
+-spec loadFrame(This, Frame, Parent, Name) -> boolean() when
+ This::wxXmlResource(), Frame::wxFrame:wxFrame(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -207,8 +230,9 @@ loadFrame(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FrameT,ref=FrameRef},#wx_
wxe_util:call(?wxXmlResource_LoadFrame_3,
<<ThisRef:32/?UI,FrameRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Name::string()) -> wxIcon:wxIcon()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadicon">external documentation</a>.
+-spec loadIcon(This, Name) -> wxIcon:wxIcon() when
+ This::wxXmlResource(), Name::unicode:chardata().
loadIcon(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -216,8 +240,9 @@ loadIcon(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxXmlResource_LoadIcon,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Name::string()) -> wxMenu:wxMenu()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadmenu">external documentation</a>.
+-spec loadMenu(This, Name) -> wxMenu:wxMenu() when
+ This::wxXmlResource(), Name::unicode:chardata().
loadMenu(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -225,8 +250,9 @@ loadMenu(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxXmlResource_LoadMenu,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Name::string()) -> wxMenuBar:wxMenuBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadmenubar">external documentation</a>.
+-spec loadMenuBar(This, Name) -> wxMenuBar:wxMenuBar() when
+ This::wxXmlResource(), Name::unicode:chardata().
loadMenuBar(#wx_ref{type=ThisT,ref=ThisRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -234,8 +260,9 @@ loadMenuBar(#wx_ref{type=ThisT,ref=ThisRef},Name)
wxe_util:call(?wxXmlResource_LoadMenuBar_1,
<<ThisRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::string()) -> wxMenuBar:wxMenuBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadmenubar">external documentation</a>.
+-spec loadMenuBar(This, Parent, Name) -> wxMenuBar:wxMenuBar() when
+ This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadMenuBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -244,8 +271,9 @@ loadMenuBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},
wxe_util:call(?wxXmlResource_LoadMenuBar_2,
<<ThisRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::string()) -> wxPanel:wxPanel()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadpanel">external documentation</a>.
+-spec loadPanel(This, Parent, Name) -> wxPanel:wxPanel() when
+ This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadPanel(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -254,8 +282,9 @@ loadPanel(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Na
wxe_util:call(?wxXmlResource_LoadPanel_2,
<<ThisRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Panel::wxPanel:wxPanel(), Parent::wxWindow:wxWindow(), Name::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadpanel">external documentation</a>.
+-spec loadPanel(This, Panel, Parent, Name) -> boolean() when
+ This::wxXmlResource(), Panel::wxPanel:wxPanel(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadPanel(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PanelT,ref=PanelRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -265,8 +294,9 @@ loadPanel(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=PanelT,ref=PanelRef},#wx_
wxe_util:call(?wxXmlResource_LoadPanel_3,
<<ThisRef:32/?UI,PanelRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((0+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::string()) -> wxToolBar:wxToolBar()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceloadtoolbar">external documentation</a>.
+-spec loadToolBar(This, Parent, Name) -> wxToolBar:wxToolBar() when
+ This::wxXmlResource(), Parent::wxWindow:wxWindow(), Name::unicode:chardata().
loadToolBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},Name)
when is_list(Name) ->
?CLASS(ThisT,wxXmlResource),
@@ -275,23 +305,26 @@ loadToolBar(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef},
wxe_util:call(?wxXmlResource_LoadToolBar,
<<ThisRef:32/?UI,ParentRef:32/?UI,(byte_size(Name_UC)):32/?UI,(Name_UC)/binary, 0:(((8- ((4+byte_size(Name_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (Res::wxXmlResource()) -> wxXmlResource()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceset">external documentation</a>.
+-spec set(Res) -> wxXmlResource() when
+ Res::wxXmlResource().
set(#wx_ref{type=ResT,ref=ResRef}) ->
?CLASS(ResT,wxXmlResource),
wxe_util:call(?wxXmlResource_Set,
<<ResRef:32/?UI>>).
-%% @spec (This::wxXmlResource(), Flags::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourcesetflags">external documentation</a>.
+-spec setFlags(This, Flags) -> ok when
+ This::wxXmlResource(), Flags::integer().
setFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags)
when is_integer(Flags) ->
?CLASS(ThisT,wxXmlResource),
wxe_util:cast(?wxXmlResource_SetFlags,
<<ThisRef:32/?UI,Flags:32/?UI>>).
-%% @spec (This::wxXmlResource(), Filename::string()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxxmlresource.html#wxxmlresourceunload">external documentation</a>.
+-spec unload(This, Filename) -> boolean() when
+ This::wxXmlResource(), Filename::unicode:chardata().
unload(#wx_ref{type=ThisT,ref=ThisRef},Filename)
when is_list(Filename) ->
?CLASS(ThisT,wxXmlResource),
@@ -318,8 +351,8 @@ xrcctrl(Window = #wx_ref{}, Name, Type) when is_list(Name), is_atom(Type) ->
Res = wxWindow:findWindow(Window,ID),
wx:typeCast(Res, Type).
-%% @spec (This::wxXmlResource()) -> ok
%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxXmlResource()) -> ok.
destroy(Obj=#wx_ref{type=Type}) ->
?CLASS(Type,wxXmlResource),
wxe_util:destroy(?DESTROY_OBJECT,Obj),
diff --git a/lib/wx/src/gen/wx_misc.erl b/lib/wx/src/gen/wx_misc.erl
index cf23d4cf8b..a2a39bdae7 100644
--- a/lib/wx/src/gen/wx_misc.erl
+++ b/lib/wx/src/gen/wx_misc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The 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,42 +30,44 @@
launchDefaultBrowser/2,newId/0,registerId/1,setDetectableAutoRepeat/1,
shell/0,shell/1,shutdown/1]).
-%% @spec (Key::WxKeyCode) -> bool()
-%% WxKeyCode = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetkeystate">external documentation</a>.
-%%<br /> WxKeyCode is one of ?WXK_BACK | ?WXK_TAB | ?WXK_RETURN | ?WXK_ESCAPE | ?WXK_SPACE | ?WXK_DELETE | ?WXK_START | ?WXK_LBUTTON | ?WXK_RBUTTON | ?WXK_CANCEL | ?WXK_MBUTTON | ?WXK_CLEAR | ?WXK_SHIFT | ?WXK_ALT | ?WXK_CONTROL | ?WXK_MENU | ?WXK_PAUSE | ?WXK_CAPITAL | ?WXK_END | ?WXK_HOME | ?WXK_LEFT | ?WXK_UP | ?WXK_RIGHT | ?WXK_DOWN | ?WXK_SELECT | ?WXK_PRINT | ?WXK_EXECUTE | ?WXK_SNAPSHOT | ?WXK_INSERT | ?WXK_HELP | ?WXK_NUMPAD0 | ?WXK_NUMPAD1 | ?WXK_NUMPAD2 | ?WXK_NUMPAD3 | ?WXK_NUMPAD4 | ?WXK_NUMPAD5 | ?WXK_NUMPAD6 | ?WXK_NUMPAD7 | ?WXK_NUMPAD8 | ?WXK_NUMPAD9 | ?WXK_MULTIPLY | ?WXK_ADD | ?WXK_SEPARATOR | ?WXK_SUBTRACT | ?WXK_DECIMAL | ?WXK_DIVIDE | ?WXK_F1 | ?WXK_F2 | ?WXK_F3 | ?WXK_F4 | ?WXK_F5 | ?WXK_F6 | ?WXK_F7 | ?WXK_F8 | ?WXK_F9 | ?WXK_F10 | ?WXK_F11 | ?WXK_F12 | ?WXK_F13 | ?WXK_F14 | ?WXK_F15 | ?WXK_F16 | ?WXK_F17 | ?WXK_F18 | ?WXK_F19 | ?WXK_F20 | ?WXK_F21 | ?WXK_F22 | ?WXK_F23 | ?WXK_F24 | ?WXK_NUMLOCK | ?WXK_SCROLL | ?WXK_PAGEUP | ?WXK_PAGEDOWN | ?WXK_NUMPAD_SPACE | ?WXK_NUMPAD_TAB | ?WXK_NUMPAD_ENTER | ?WXK_NUMPAD_F1 | ?WXK_NUMPAD_F2 | ?WXK_NUMPAD_F3 | ?WXK_NUMPAD_F4 | ?WXK_NUMPAD_HOME | ?WXK_NUMPAD_LEFT | ?WXK_NUMPAD_UP | ?WXK_NUMPAD_RIGHT | ?WXK_NUMPAD_DOWN | ?WXK_NUMPAD_PAGEUP | ?WXK_NUMPAD_PAGEDOWN | ?WXK_NUMPAD_END | ?WXK_NUMPAD_BEGIN | ?WXK_NUMPAD_INSERT | ?WXK_NUMPAD_DELETE | ?WXK_NUMPAD_EQUAL | ?WXK_NUMPAD_MULTIPLY | ?WXK_NUMPAD_ADD | ?WXK_NUMPAD_SEPARATOR | ?WXK_NUMPAD_SUBTRACT | ?WXK_NUMPAD_DECIMAL | ?WXK_NUMPAD_DIVIDE | ?WXK_WINDOWS_LEFT | ?WXK_WINDOWS_RIGHT | ?WXK_WINDOWS_MENU | ?WXK_COMMAND | ?WXK_SPECIAL1 | ?WXK_SPECIAL2 | ?WXK_SPECIAL3 | ?WXK_SPECIAL4 | ?WXK_SPECIAL5 | ?WXK_SPECIAL6 | ?WXK_SPECIAL7 | ?WXK_SPECIAL8 | ?WXK_SPECIAL9 | ?WXK_SPECIAL10 | ?WXK_SPECIAL11 | ?WXK_SPECIAL12 | ?WXK_SPECIAL13 | ?WXK_SPECIAL14 | ?WXK_SPECIAL15 | ?WXK_SPECIAL16 | ?WXK_SPECIAL17 | ?WXK_SPECIAL18 | ?WXK_SPECIAL19 | ?WXK_SPECIAL20
+%%<br /> Key = ?WXK_BACK | ?WXK_TAB | ?WXK_RETURN | ?WXK_ESCAPE | ?WXK_SPACE | ?WXK_DELETE | ?WXK_START | ?WXK_LBUTTON | ?WXK_RBUTTON | ?WXK_CANCEL | ?WXK_MBUTTON | ?WXK_CLEAR | ?WXK_SHIFT | ?WXK_ALT | ?WXK_CONTROL | ?WXK_MENU | ?WXK_PAUSE | ?WXK_CAPITAL | ?WXK_END | ?WXK_HOME | ?WXK_LEFT | ?WXK_UP | ?WXK_RIGHT | ?WXK_DOWN | ?WXK_SELECT | ?WXK_PRINT | ?WXK_EXECUTE | ?WXK_SNAPSHOT | ?WXK_INSERT | ?WXK_HELP | ?WXK_NUMPAD0 | ?WXK_NUMPAD1 | ?WXK_NUMPAD2 | ?WXK_NUMPAD3 | ?WXK_NUMPAD4 | ?WXK_NUMPAD5 | ?WXK_NUMPAD6 | ?WXK_NUMPAD7 | ?WXK_NUMPAD8 | ?WXK_NUMPAD9 | ?WXK_MULTIPLY | ?WXK_ADD | ?WXK_SEPARATOR | ?WXK_SUBTRACT | ?WXK_DECIMAL | ?WXK_DIVIDE | ?WXK_F1 | ?WXK_F2 | ?WXK_F3 | ?WXK_F4 | ?WXK_F5 | ?WXK_F6 | ?WXK_F7 | ?WXK_F8 | ?WXK_F9 | ?WXK_F10 | ?WXK_F11 | ?WXK_F12 | ?WXK_F13 | ?WXK_F14 | ?WXK_F15 | ?WXK_F16 | ?WXK_F17 | ?WXK_F18 | ?WXK_F19 | ?WXK_F20 | ?WXK_F21 | ?WXK_F22 | ?WXK_F23 | ?WXK_F24 | ?WXK_NUMLOCK | ?WXK_SCROLL | ?WXK_PAGEUP | ?WXK_PAGEDOWN | ?WXK_NUMPAD_SPACE | ?WXK_NUMPAD_TAB | ?WXK_NUMPAD_ENTER | ?WXK_NUMPAD_F1 | ?WXK_NUMPAD_F2 | ?WXK_NUMPAD_F3 | ?WXK_NUMPAD_F4 | ?WXK_NUMPAD_HOME | ?WXK_NUMPAD_LEFT | ?WXK_NUMPAD_UP | ?WXK_NUMPAD_RIGHT | ?WXK_NUMPAD_DOWN | ?WXK_NUMPAD_PAGEUP | ?WXK_NUMPAD_PAGEDOWN | ?WXK_NUMPAD_END | ?WXK_NUMPAD_BEGIN | ?WXK_NUMPAD_INSERT | ?WXK_NUMPAD_DELETE | ?WXK_NUMPAD_EQUAL | ?WXK_NUMPAD_MULTIPLY | ?WXK_NUMPAD_ADD | ?WXK_NUMPAD_SEPARATOR | ?WXK_NUMPAD_SUBTRACT | ?WXK_NUMPAD_DECIMAL | ?WXK_NUMPAD_DIVIDE | ?WXK_WINDOWS_LEFT | ?WXK_WINDOWS_RIGHT | ?WXK_WINDOWS_MENU | ?WXK_COMMAND | ?WXK_SPECIAL1 | ?WXK_SPECIAL2 | ?WXK_SPECIAL3 | ?WXK_SPECIAL4 | ?WXK_SPECIAL5 | ?WXK_SPECIAL6 | ?WXK_SPECIAL7 | ?WXK_SPECIAL8 | ?WXK_SPECIAL9 | ?WXK_SPECIAL10 | ?WXK_SPECIAL11 | ?WXK_SPECIAL12 | ?WXK_SPECIAL13 | ?WXK_SPECIAL14 | ?WXK_SPECIAL15 | ?WXK_SPECIAL16 | ?WXK_SPECIAL17 | ?WXK_SPECIAL18 | ?WXK_SPECIAL19 | ?WXK_SPECIAL20
+-spec getKeyState(Key) -> boolean() when
+ Key::wx:wx_enum().
getKeyState(Key)
when is_integer(Key) ->
wxe_util:call(?utils_wxGetKeyState,
<<Key:32/?UI>>).
-%% @spec () -> {X::integer(),Y::integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetmouseposition">external documentation</a>.
+-spec getMousePosition() -> {X::integer(), Y::integer()}.
getMousePosition() ->
wxe_util:call(?utils_wxGetMousePosition,
<<>>).
-%% @spec () -> wx:wxMouseState()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetmousestate">external documentation</a>.
+-spec getMouseState() -> wx:wx_wxMouseState().
getMouseState() ->
wxe_util:call(?utils_wxGetMouseState,
<<>>).
-%% @spec (Flag::bool()) -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxsetdetectableautorepeat">external documentation</a>.
+-spec setDetectableAutoRepeat(Flag) -> boolean() when
+ Flag::boolean().
setDetectableAutoRepeat(Flag)
when is_boolean(Flag) ->
wxe_util:call(?utils_wxSetDetectableAutoRepeat,
<<(wxe_util:from_bool(Flag)):32/?UI>>).
-%% @spec () -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxbell">external documentation</a>.
+-spec bell() -> ok.
bell() ->
wxe_util:cast(?utils_wxBell,
<<>>).
-%% @spec (Frame::wxFrame:wxFrame(), MenuString::string(), ItemString::string()) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxfindmenuitemid">external documentation</a>.
+-spec findMenuItemId(Frame, MenuString, ItemString) -> integer() when
+ Frame::wxFrame:wxFrame(), MenuString::unicode:chardata(), ItemString::unicode:chardata().
findMenuItemId(#wx_ref{type=FrameT,ref=FrameRef},MenuString,ItemString)
when is_list(MenuString),is_list(ItemString) ->
?CLASS(FrameT,wxFrame),
@@ -74,28 +76,31 @@ findMenuItemId(#wx_ref{type=FrameT,ref=FrameRef},MenuString,ItemString)
wxe_util:call(?utils_wxFindMenuItemId,
<<FrameRef:32/?UI,(byte_size(MenuString_UC)):32/?UI,(MenuString_UC)/binary, 0:(((8- ((0+byte_size(MenuString_UC)) band 16#7)) band 16#7))/unit:8,(byte_size(ItemString_UC)):32/?UI,(ItemString_UC)/binary, 0:(((8- ((4+byte_size(ItemString_UC)) band 16#7)) band 16#7))/unit:8>>).
-%% @spec (Pt::{X::integer(),Y::integer()}) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgenericfindwindowatpoint">external documentation</a>.
+-spec genericFindWindowAtPoint(Pt) -> wxWindow:wxWindow() when
+ Pt::{X::integer(), Y::integer()}.
genericFindWindowAtPoint({PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
wxe_util:call(?utils_wxGenericFindWindowAtPoint,
<<PtX:32/?UI,PtY:32/?UI>>).
-%% @spec (Pt::{X::integer(),Y::integer()}) -> wxWindow:wxWindow()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxfindwindowatpoint">external documentation</a>.
+-spec findWindowAtPoint(Pt) -> wxWindow:wxWindow() when
+ Pt::{X::integer(), Y::integer()}.
findWindowAtPoint({PtX,PtY})
when is_integer(PtX),is_integer(PtY) ->
wxe_util:call(?utils_wxFindWindowAtPoint,
<<PtX:32/?UI,PtY:32/?UI>>).
-%% @spec () -> ok
%% @equiv beginBusyCursor([])
+-spec beginBusyCursor() -> ok.
+
beginBusyCursor() ->
beginBusyCursor([]).
-%% @spec ([Option]) -> ok
-%% Option = {cursor, wxCursor:wxCursor()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxbeginbusycursor">external documentation</a>.
+-spec beginBusyCursor([Option]) -> ok when
+ Option :: {cursor, wxCursor:wxCursor()}.
beginBusyCursor(Options)
when is_list(Options) ->
MOpts = fun({cursor, #wx_ref{type=CursorT,ref=CursorRef}}, Acc) -> ?CLASS(CursorT,wxCursor),[<<1:32/?UI,CursorRef:32/?UI>>|Acc];
@@ -104,35 +109,36 @@ beginBusyCursor(Options)
wxe_util:cast(?utils_wxBeginBusyCursor,
<<BinOpt/binary>>).
-%% @spec () -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxendbusycursor">external documentation</a>.
+-spec endBusyCursor() -> ok.
endBusyCursor() ->
wxe_util:cast(?utils_wxEndBusyCursor,
<<>>).
-%% @spec () -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxisbusy">external documentation</a>.
+-spec isBusy() -> boolean().
isBusy() ->
wxe_util:call(?utils_wxIsBusy,
<<>>).
-%% @spec (WFlags::WxShutdownFlags) -> bool()
-%% WxShutdownFlags = integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxshutdown">external documentation</a>.
-%%<br /> WxShutdownFlags is one of ?wxSHUTDOWN_POWEROFF | ?wxSHUTDOWN_REBOOT
+%%<br /> WFlags = ?wxSHUTDOWN_POWEROFF | ?wxSHUTDOWN_REBOOT
+-spec shutdown(WFlags) -> boolean() when
+ WFlags::wx:wx_enum().
shutdown(WFlags)
when is_integer(WFlags) ->
wxe_util:call(?utils_wxShutdown,
<<WFlags:32/?UI>>).
-%% @spec () -> bool()
%% @equiv shell([])
+-spec shell() -> boolean().
+
shell() ->
shell([]).
-%% @spec ([Option]) -> bool()
-%% Option = {command, string()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxshell">external documentation</a>.
+-spec shell([Option]) -> boolean() when
+ Option :: {command, unicode:chardata()}.
shell(Options)
when is_list(Options) ->
MOpts = fun({command, Command}, Acc) -> Command_UC = unicode:characters_to_binary([Command,0]),[<<1:32/?UI,(byte_size(Command_UC)):32/?UI,(Command_UC)/binary, 0:(((8- ((0+byte_size(Command_UC)) band 16#7)) band 16#7))/unit:8>>|Acc];
@@ -141,15 +147,18 @@ shell(Options)
wxe_util:call(?utils_wxShell,
<<BinOpt/binary>>).
-%% @spec (Url::string()) -> bool()
%% @equiv launchDefaultBrowser(Url, [])
+-spec launchDefaultBrowser(Url) -> boolean() when
+ Url::unicode:chardata().
+
launchDefaultBrowser(Url)
when is_list(Url) ->
launchDefaultBrowser(Url, []).
-%% @spec (Url::string(), [Option]) -> bool()
-%% Option = {flags, integer()}
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxlaunchdefaultbrowser">external documentation</a>.
+-spec launchDefaultBrowser(Url, [Option]) -> boolean() when
+ Url::unicode:chardata(),
+ Option :: {flags, integer()}.
launchDefaultBrowser(Url, Options)
when is_list(Url),is_list(Options) ->
Url_UC = unicode:characters_to_binary([Url,0]),
@@ -159,57 +168,58 @@ launchDefaultBrowser(Url, Options)
wxe_util:call(?utils_wxLaunchDefaultBrowser,
<<(byte_size(Url_UC)):32/?UI,(Url_UC)/binary, 0:(((8- ((4+byte_size(Url_UC)) band 16#7)) band 16#7))/unit:8, BinOpt/binary>>).
-%% @spec () -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetemailaddress">external documentation</a>.
+-spec getEmailAddress() -> unicode:charlist().
getEmailAddress() ->
wxe_util:call(?utils_wxGetEmailAddress,
<<>>).
-%% @spec () -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetuserid">external documentation</a>.
+-spec getUserId() -> unicode:charlist().
getUserId() ->
wxe_util:call(?utils_wxGetUserId,
<<>>).
-%% @spec () -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgethomedir">external documentation</a>.
+-spec getHomeDir() -> unicode:charlist().
getHomeDir() ->
wxe_util:call(?utils_wxGetHomeDir,
<<>>).
-%% @spec () -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxnewid">external documentation</a>.
+-spec newId() -> integer().
newId() ->
wxe_util:call(?utils_wxNewId,
<<>>).
-%% @spec (Id::integer()) -> ok
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxregisterid">external documentation</a>.
+-spec registerId(Id) -> ok when
+ Id::integer().
registerId(Id)
when is_integer(Id) ->
wxe_util:cast(?utils_wxRegisterId,
<<Id:32/?UI>>).
-%% @spec () -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetcurrentid">external documentation</a>.
+-spec getCurrentId() -> integer().
getCurrentId() ->
wxe_util:call(?utils_wxGetCurrentId,
<<>>).
-%% @spec () -> string()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxgetosdescription">external documentation</a>.
+-spec getOsDescription() -> unicode:charlist().
getOsDescription() ->
wxe_util:call(?utils_wxGetOsDescription,
<<>>).
-%% @spec () -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxisplatformlittleendian">external documentation</a>.
+-spec isPlatformLittleEndian() -> boolean().
isPlatformLittleEndian() ->
wxe_util:call(?utils_wxIsPlatformLittleEndian,
<<>>).
-%% @spec () -> bool()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#wxisplatform64bit">external documentation</a>.
+-spec isPlatform64Bit() -> boolean().
isPlatform64Bit() ->
wxe_util:call(?utils_wxIsPlatform64Bit,
<<>>).
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index 960f67a1f6..297d99324a 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -563,2736 +563,2747 @@ wxdebug_table() ->
{662, {wxDC, getBrush, 0}},
{663, {wxDC, getCharHeight, 0}},
{664, {wxDC, getCharWidth, 0}},
- {665, {wxDC, getClippingBox, 1}},
- {666, {wxDC, getFont, 0}},
- {667, {wxDC, getLayoutDirection, 0}},
- {668, {wxDC, getLogicalFunction, 0}},
- {669, {wxDC, getMapMode, 0}},
- {670, {wxDC, getMultiLineTextExtent_4, 4}},
- {671, {wxDC, getMultiLineTextExtent_1, 1}},
- {672, {wxDC, getPartialTextExtents, 2}},
- {673, {wxDC, getPen, 0}},
- {674, {wxDC, getPixel, 2}},
- {675, {wxDC, getPPI, 0}},
- {677, {wxDC, getSize, 0}},
- {679, {wxDC, getSizeMM, 0}},
- {680, {wxDC, getTextBackground, 0}},
- {681, {wxDC, getTextExtent_4, 4}},
- {682, {wxDC, getTextExtent_1, 1}},
- {684, {wxDC, getTextForeground, 0}},
- {685, {wxDC, getUserScale, 2}},
- {686, {wxDC, gradientFillConcentric_3, 3}},
- {687, {wxDC, gradientFillConcentric_4, 4}},
- {688, {wxDC, gradientFillLinear, 4}},
- {689, {wxDC, logicalToDeviceX, 1}},
- {690, {wxDC, logicalToDeviceXRel, 1}},
- {691, {wxDC, logicalToDeviceY, 1}},
- {692, {wxDC, logicalToDeviceYRel, 1}},
- {693, {wxDC, maxX, 0}},
- {694, {wxDC, maxY, 0}},
- {695, {wxDC, minX, 0}},
- {696, {wxDC, minY, 0}},
- {697, {wxDC, isOk, 0}},
- {698, {wxDC, resetBoundingBox, 0}},
- {699, {wxDC, setAxisOrientation, 2}},
- {700, {wxDC, setBackground, 1}},
- {701, {wxDC, setBackgroundMode, 1}},
- {702, {wxDC, setBrush, 1}},
- {704, {wxDC, setClippingRegion_2, 2}},
- {705, {wxDC, setClippingRegion_1_1, 1}},
- {706, {wxDC, setClippingRegion_1_0, 1}},
- {707, {wxDC, setDeviceOrigin, 2}},
- {708, {wxDC, setFont, 1}},
- {709, {wxDC, setLayoutDirection, 1}},
- {710, {wxDC, setLogicalFunction, 1}},
- {711, {wxDC, setMapMode, 1}},
- {712, {wxDC, setPalette, 1}},
- {713, {wxDC, setPen, 1}},
- {714, {wxDC, setTextBackground, 1}},
- {715, {wxDC, setTextForeground, 1}},
- {716, {wxDC, setUserScale, 2}},
- {717, {wxDC, startDoc, 1}},
- {718, {wxDC, startPage, 0}},
- {719, {wxMirrorDC, new, 2}},
- {720, {wxMirrorDC, 'Destroy', undefined}},
- {721, {wxScreenDC, new, 0}},
- {722, {wxScreenDC, destruct, 0}},
- {723, {wxPostScriptDC, new_0, 0}},
- {724, {wxPostScriptDC, new_1, 1}},
- {725, {wxPostScriptDC, destruct, 0}},
- {726, {wxPostScriptDC, setResolution, 1}},
- {727, {wxPostScriptDC, getResolution, 0}},
- {728, {wxWindowDC, new_0, 0}},
- {729, {wxWindowDC, new_1, 1}},
- {730, {wxWindowDC, destruct, 0}},
- {731, {wxClientDC, new_0, 0}},
- {732, {wxClientDC, new_1, 1}},
- {733, {wxClientDC, 'Destroy', undefined}},
- {734, {wxPaintDC, new_0, 0}},
- {735, {wxPaintDC, new_1, 1}},
- {736, {wxPaintDC, 'Destroy', undefined}},
- {738, {wxMemoryDC, new_1_0, 1}},
- {739, {wxMemoryDC, new_1_1, 1}},
- {740, {wxMemoryDC, new_0, 0}},
- {742, {wxMemoryDC, destruct, 0}},
- {743, {wxMemoryDC, selectObject, 1}},
- {744, {wxMemoryDC, selectObjectAsSource, 1}},
- {745, {wxBufferedDC, new_0, 0}},
- {746, {wxBufferedDC, new_2, 2}},
- {747, {wxBufferedDC, new_3, 3}},
- {748, {wxBufferedDC, destruct, 0}},
- {749, {wxBufferedDC, init_2, 2}},
- {750, {wxBufferedDC, init_3, 3}},
- {751, {wxBufferedPaintDC, new_3, 3}},
- {752, {wxBufferedPaintDC, new_2, 2}},
- {753, {wxBufferedPaintDC, destruct, 0}},
- {754, {wxGraphicsObject, getRenderer, 0}},
- {755, {wxGraphicsObject, isNull, 0}},
- {756, {wxGraphicsContext, create_1_1, 1}},
- {757, {wxGraphicsContext, create_1_0, 1}},
- {758, {wxGraphicsContext, create_0, 0}},
- {759, {wxGraphicsContext, createPen, 1}},
- {760, {wxGraphicsContext, createBrush, 1}},
- {761, {wxGraphicsContext, createRadialGradientBrush, 7}},
- {762, {wxGraphicsContext, createLinearGradientBrush, 6}},
- {763, {wxGraphicsContext, createFont, 2}},
- {764, {wxGraphicsContext, createMatrix, 1}},
- {765, {wxGraphicsContext, createPath, 0}},
- {766, {wxGraphicsContext, clip_1, 1}},
- {767, {wxGraphicsContext, clip_4, 4}},
- {768, {wxGraphicsContext, resetClip, 0}},
- {769, {wxGraphicsContext, drawBitmap, 5}},
- {770, {wxGraphicsContext, drawEllipse, 4}},
- {771, {wxGraphicsContext, drawIcon, 5}},
- {772, {wxGraphicsContext, drawLines, 3}},
- {773, {wxGraphicsContext, drawPath, 2}},
- {774, {wxGraphicsContext, drawRectangle, 4}},
- {775, {wxGraphicsContext, drawRoundedRectangle, 5}},
- {776, {wxGraphicsContext, drawText_3, 3}},
- {777, {wxGraphicsContext, drawText_4_0, 4}},
- {778, {wxGraphicsContext, drawText_4_1, 4}},
- {779, {wxGraphicsContext, drawText_5, 5}},
- {780, {wxGraphicsContext, fillPath, 2}},
- {781, {wxGraphicsContext, strokePath, 1}},
- {782, {wxGraphicsContext, getNativeContext, 0}},
- {783, {wxGraphicsContext, getPartialTextExtents, 2}},
- {784, {wxGraphicsContext, getTextExtent, 5}},
- {785, {wxGraphicsContext, rotate, 1}},
- {786, {wxGraphicsContext, scale, 2}},
- {787, {wxGraphicsContext, translate, 2}},
- {788, {wxGraphicsContext, getTransform, 0}},
- {789, {wxGraphicsContext, setTransform, 1}},
- {790, {wxGraphicsContext, concatTransform, 1}},
- {791, {wxGraphicsContext, setBrush_1_1, 1}},
- {792, {wxGraphicsContext, setBrush_1_0, 1}},
- {793, {wxGraphicsContext, setFont_1, 1}},
- {794, {wxGraphicsContext, setFont_2, 2}},
- {795, {wxGraphicsContext, setPen_1_0, 1}},
- {796, {wxGraphicsContext, setPen_1_1, 1}},
- {797, {wxGraphicsContext, strokeLine, 4}},
- {798, {wxGraphicsContext, strokeLines_2, 2}},
- {799, {wxGraphicsContext, strokeLines_3, 3}},
- {800, {wxGraphicsMatrix, concat, 1}},
- {802, {wxGraphicsMatrix, get, 1}},
- {803, {wxGraphicsMatrix, getNativeMatrix, 0}},
- {804, {wxGraphicsMatrix, invert, 0}},
- {805, {wxGraphicsMatrix, isEqual, 1}},
- {807, {wxGraphicsMatrix, isIdentity, 0}},
- {808, {wxGraphicsMatrix, rotate, 1}},
- {809, {wxGraphicsMatrix, scale, 2}},
- {810, {wxGraphicsMatrix, translate, 2}},
- {811, {wxGraphicsMatrix, set, 1}},
- {812, {wxGraphicsMatrix, transformPoint, 2}},
- {813, {wxGraphicsMatrix, transformDistance, 2}},
- {814, {wxGraphicsPath, moveToPoint_2, 2}},
- {815, {wxGraphicsPath, moveToPoint_1, 1}},
- {816, {wxGraphicsPath, addArc_6, 6}},
- {817, {wxGraphicsPath, addArc_5, 5}},
- {818, {wxGraphicsPath, addArcToPoint, 5}},
- {819, {wxGraphicsPath, addCircle, 3}},
- {820, {wxGraphicsPath, addCurveToPoint_6, 6}},
- {821, {wxGraphicsPath, addCurveToPoint_3, 3}},
- {822, {wxGraphicsPath, addEllipse, 4}},
- {823, {wxGraphicsPath, addLineToPoint_2, 2}},
- {824, {wxGraphicsPath, addLineToPoint_1, 1}},
- {825, {wxGraphicsPath, addPath, 1}},
- {826, {wxGraphicsPath, addQuadCurveToPoint, 4}},
- {827, {wxGraphicsPath, addRectangle, 4}},
- {828, {wxGraphicsPath, addRoundedRectangle, 5}},
- {829, {wxGraphicsPath, closeSubpath, 0}},
- {830, {wxGraphicsPath, contains_3, 3}},
- {831, {wxGraphicsPath, contains_2, 2}},
- {833, {wxGraphicsPath, getBox, 0}},
- {835, {wxGraphicsPath, getCurrentPoint, 0}},
- {836, {wxGraphicsPath, transform, 1}},
- {837, {wxGraphicsRenderer, getDefaultRenderer, 0}},
- {838, {wxGraphicsRenderer, createContext_1_1, 1}},
- {839, {wxGraphicsRenderer, createContext_1_0, 1}},
- {840, {wxGraphicsRenderer, createPen, 1}},
- {841, {wxGraphicsRenderer, createBrush, 1}},
- {842, {wxGraphicsRenderer, createLinearGradientBrush, 6}},
- {843, {wxGraphicsRenderer, createRadialGradientBrush, 7}},
- {844, {wxGraphicsRenderer, createFont, 2}},
- {845, {wxGraphicsRenderer, createMatrix, 1}},
- {846, {wxGraphicsRenderer, createPath, 0}},
- {848, {wxMenuBar, new_1, 1}},
- {850, {wxMenuBar, new_0, 0}},
- {852, {wxMenuBar, destruct, 0}},
- {853, {wxMenuBar, append, 2}},
- {854, {wxMenuBar, check, 2}},
- {855, {wxMenuBar, enable_2, 2}},
- {856, {wxMenuBar, enable_1, 1}},
- {857, {wxMenuBar, enableTop, 2}},
- {858, {wxMenuBar, findMenu, 1}},
- {859, {wxMenuBar, findMenuItem, 2}},
- {860, {wxMenuBar, findItem, 2}},
- {861, {wxMenuBar, getHelpString, 1}},
- {862, {wxMenuBar, getLabel_1, 1}},
- {863, {wxMenuBar, getLabel_0, 0}},
- {864, {wxMenuBar, getLabelTop, 1}},
- {865, {wxMenuBar, getMenu, 1}},
- {866, {wxMenuBar, getMenuCount, 0}},
- {867, {wxMenuBar, insert, 3}},
- {868, {wxMenuBar, isChecked, 1}},
- {869, {wxMenuBar, isEnabled_1, 1}},
- {870, {wxMenuBar, isEnabled_0, 0}},
- {871, {wxMenuBar, remove, 1}},
- {872, {wxMenuBar, replace, 3}},
- {873, {wxMenuBar, setHelpString, 2}},
- {874, {wxMenuBar, setLabel_2, 2}},
- {875, {wxMenuBar, setLabel_1, 1}},
- {876, {wxMenuBar, setLabelTop, 2}},
- {877, {wxControl, getLabel, 0}},
- {878, {wxControl, setLabel, 1}},
- {879, {wxControlWithItems, append_1, 1}},
- {880, {wxControlWithItems, append_2, 2}},
- {881, {wxControlWithItems, appendStrings_1, 1}},
- {882, {wxControlWithItems, clear, 0}},
- {883, {wxControlWithItems, delete, 1}},
- {884, {wxControlWithItems, findString, 2}},
- {885, {wxControlWithItems, getClientData, 1}},
- {886, {wxControlWithItems, setClientData, 2}},
- {887, {wxControlWithItems, getCount, 0}},
- {888, {wxControlWithItems, getSelection, 0}},
- {889, {wxControlWithItems, getString, 1}},
- {890, {wxControlWithItems, getStringSelection, 0}},
- {891, {wxControlWithItems, insert_2, 2}},
- {892, {wxControlWithItems, insert_3, 3}},
- {893, {wxControlWithItems, isEmpty, 0}},
- {894, {wxControlWithItems, select, 1}},
- {895, {wxControlWithItems, setSelection, 1}},
- {896, {wxControlWithItems, setString, 2}},
- {897, {wxControlWithItems, setStringSelection, 1}},
- {900, {wxMenu, new_2, 2}},
- {901, {wxMenu, new_1, 1}},
- {903, {wxMenu, destruct, 0}},
- {904, {wxMenu, append_3, 3}},
- {905, {wxMenu, append_1, 1}},
- {906, {wxMenu, append_4_0, 4}},
- {907, {wxMenu, append_4_1, 4}},
- {908, {wxMenu, appendCheckItem, 3}},
- {909, {wxMenu, appendRadioItem, 3}},
- {910, {wxMenu, appendSeparator, 0}},
- {911, {wxMenu, break, 0}},
- {912, {wxMenu, check, 2}},
- {913, {wxMenu, delete_1_0, 1}},
- {914, {wxMenu, delete_1_1, 1}},
- {915, {wxMenu, destroy_1_0, 1}},
- {916, {wxMenu, destroy_1_1, 1}},
- {917, {wxMenu, enable, 2}},
- {918, {wxMenu, findItem_1, 1}},
- {919, {wxMenu, findItem_2, 2}},
- {920, {wxMenu, findItemByPosition, 1}},
- {921, {wxMenu, getHelpString, 1}},
- {922, {wxMenu, getLabel, 1}},
- {923, {wxMenu, getMenuItemCount, 0}},
- {924, {wxMenu, getMenuItems, 0}},
- {926, {wxMenu, getTitle, 0}},
- {927, {wxMenu, insert_2, 2}},
- {928, {wxMenu, insert_3, 3}},
- {929, {wxMenu, insert_5_1, 5}},
- {930, {wxMenu, insert_5_0, 5}},
- {931, {wxMenu, insertCheckItem, 4}},
- {932, {wxMenu, insertRadioItem, 4}},
- {933, {wxMenu, insertSeparator, 1}},
- {934, {wxMenu, isChecked, 1}},
- {935, {wxMenu, isEnabled, 1}},
- {936, {wxMenu, prepend_1, 1}},
- {937, {wxMenu, prepend_2, 2}},
- {938, {wxMenu, prepend_4_1, 4}},
- {939, {wxMenu, prepend_4_0, 4}},
- {940, {wxMenu, prependCheckItem, 3}},
- {941, {wxMenu, prependRadioItem, 3}},
- {942, {wxMenu, prependSeparator, 0}},
- {943, {wxMenu, remove_1_0, 1}},
- {944, {wxMenu, remove_1_1, 1}},
- {945, {wxMenu, setHelpString, 2}},
- {946, {wxMenu, setLabel, 2}},
- {947, {wxMenu, setTitle, 1}},
- {948, {wxMenuItem, new, 1}},
- {950, {wxMenuItem, destruct, 0}},
- {951, {wxMenuItem, check, 1}},
- {952, {wxMenuItem, enable, 1}},
- {953, {wxMenuItem, getBitmap, 0}},
- {954, {wxMenuItem, getHelp, 0}},
- {955, {wxMenuItem, getId, 0}},
- {956, {wxMenuItem, getKind, 0}},
- {957, {wxMenuItem, getLabel, 0}},
- {958, {wxMenuItem, getLabelFromText, 1}},
- {959, {wxMenuItem, getMenu, 0}},
- {960, {wxMenuItem, getText, 0}},
- {961, {wxMenuItem, getSubMenu, 0}},
- {962, {wxMenuItem, isCheckable, 0}},
- {963, {wxMenuItem, isChecked, 0}},
- {964, {wxMenuItem, isEnabled, 0}},
- {965, {wxMenuItem, isSeparator, 0}},
- {966, {wxMenuItem, isSubMenu, 0}},
- {967, {wxMenuItem, setBitmap, 1}},
- {968, {wxMenuItem, setHelp, 1}},
- {969, {wxMenuItem, setMenu, 1}},
- {970, {wxMenuItem, setSubMenu, 1}},
- {971, {wxMenuItem, setText, 1}},
- {972, {wxToolBar, addControl, 1}},
- {973, {wxToolBar, addSeparator, 0}},
- {974, {wxToolBar, addTool_5, 5}},
- {975, {wxToolBar, addTool_4_0, 4}},
- {976, {wxToolBar, addTool_1, 1}},
- {977, {wxToolBar, addTool_4_1, 4}},
- {978, {wxToolBar, addTool_3, 3}},
- {979, {wxToolBar, addTool_6, 6}},
- {980, {wxToolBar, addCheckTool, 4}},
- {981, {wxToolBar, addRadioTool, 4}},
- {982, {wxToolBar, deleteTool, 1}},
- {983, {wxToolBar, deleteToolByPos, 1}},
- {984, {wxToolBar, enableTool, 2}},
- {985, {wxToolBar, findById, 1}},
- {986, {wxToolBar, findControl, 1}},
- {987, {wxToolBar, findToolForPosition, 2}},
- {988, {wxToolBar, getToolSize, 0}},
- {989, {wxToolBar, getToolBitmapSize, 0}},
- {990, {wxToolBar, getMargins, 0}},
- {991, {wxToolBar, getToolEnabled, 1}},
- {992, {wxToolBar, getToolLongHelp, 1}},
- {993, {wxToolBar, getToolPacking, 0}},
- {994, {wxToolBar, getToolPos, 1}},
- {995, {wxToolBar, getToolSeparation, 0}},
- {996, {wxToolBar, getToolShortHelp, 1}},
- {997, {wxToolBar, getToolState, 1}},
- {998, {wxToolBar, insertControl, 2}},
- {999, {wxToolBar, insertSeparator, 1}},
- {1000, {wxToolBar, insertTool_5, 5}},
- {1001, {wxToolBar, insertTool_2, 2}},
- {1002, {wxToolBar, insertTool_4, 4}},
- {1003, {wxToolBar, realize, 0}},
- {1004, {wxToolBar, removeTool, 1}},
- {1005, {wxToolBar, setMargins, 2}},
- {1006, {wxToolBar, setToolBitmapSize, 1}},
- {1007, {wxToolBar, setToolLongHelp, 2}},
- {1008, {wxToolBar, setToolPacking, 1}},
- {1009, {wxToolBar, setToolShortHelp, 2}},
- {1010, {wxToolBar, setToolSeparation, 1}},
- {1011, {wxToolBar, toggleTool, 2}},
- {1013, {wxStatusBar, new_0, 0}},
- {1014, {wxStatusBar, new_2, 2}},
- {1016, {wxStatusBar, destruct, 0}},
- {1017, {wxStatusBar, create, 2}},
- {1018, {wxStatusBar, getFieldRect, 2}},
- {1019, {wxStatusBar, getFieldsCount, 0}},
- {1020, {wxStatusBar, getStatusText, 1}},
- {1021, {wxStatusBar, popStatusText, 1}},
- {1022, {wxStatusBar, pushStatusText, 2}},
- {1023, {wxStatusBar, setFieldsCount, 2}},
- {1024, {wxStatusBar, setMinHeight, 1}},
- {1025, {wxStatusBar, setStatusText, 2}},
- {1026, {wxStatusBar, setStatusWidths, 2}},
- {1027, {wxStatusBar, setStatusStyles, 2}},
- {1028, {wxBitmap, new_0, 0}},
- {1029, {wxBitmap, new_3, 3}},
- {1030, {wxBitmap, new_4, 4}},
- {1031, {wxBitmap, new_2_0, 2}},
- {1032, {wxBitmap, new_2_1, 2}},
- {1033, {wxBitmap, destruct, 0}},
- {1034, {wxBitmap, convertToImage, 0}},
- {1035, {wxBitmap, copyFromIcon, 1}},
- {1036, {wxBitmap, create, 3}},
- {1037, {wxBitmap, getDepth, 0}},
- {1038, {wxBitmap, getHeight, 0}},
- {1039, {wxBitmap, getPalette, 0}},
- {1040, {wxBitmap, getMask, 0}},
- {1041, {wxBitmap, getWidth, 0}},
- {1042, {wxBitmap, getSubBitmap, 1}},
- {1043, {wxBitmap, loadFile, 2}},
- {1044, {wxBitmap, ok, 0}},
- {1045, {wxBitmap, saveFile, 3}},
- {1046, {wxBitmap, setDepth, 1}},
- {1047, {wxBitmap, setHeight, 1}},
- {1048, {wxBitmap, setMask, 1}},
- {1049, {wxBitmap, setPalette, 1}},
- {1050, {wxBitmap, setWidth, 1}},
- {1051, {wxIcon, new_0, 0}},
- {1052, {wxIcon, new_2, 2}},
- {1053, {wxIcon, new_1, 1}},
- {1054, {wxIcon, copyFromBitmap, 1}},
- {1055, {wxIcon, 'Destroy', undefined}},
- {1056, {wxIconBundle, new_0, 0}},
- {1057, {wxIconBundle, new_2, 2}},
- {1058, {wxIconBundle, new_1_0, 1}},
- {1059, {wxIconBundle, new_1_1, 1}},
- {1060, {wxIconBundle, destruct, 0}},
- {1061, {wxIconBundle, addIcon_2, 2}},
- {1062, {wxIconBundle, addIcon_1, 1}},
- {1063, {wxIconBundle, getIcon_1_1, 1}},
- {1064, {wxIconBundle, getIcon_1_0, 1}},
- {1065, {wxCursor, new_0, 0}},
- {1066, {wxCursor, new_1_0, 1}},
- {1067, {wxCursor, new_1_1, 1}},
- {1068, {wxCursor, new_4, 4}},
- {1069, {wxCursor, destruct, 0}},
- {1070, {wxCursor, ok, 0}},
- {1071, {wxMask, new_0, 0}},
- {1072, {wxMask, new_2_1, 2}},
- {1073, {wxMask, new_2_0, 2}},
- {1074, {wxMask, new_1, 1}},
- {1075, {wxMask, destruct, 0}},
- {1076, {wxMask, create_2_1, 2}},
- {1077, {wxMask, create_2_0, 2}},
- {1078, {wxMask, create_1, 1}},
- {1079, {wxImage, new_0, 0}},
- {1080, {wxImage, new_3_0, 3}},
- {1081, {wxImage, new_4, 4}},
- {1082, {wxImage, new_5, 5}},
- {1083, {wxImage, new_2, 2}},
- {1084, {wxImage, new_3_1, 3}},
- {1085, {wxImage, blur, 1}},
- {1086, {wxImage, blurHorizontal, 1}},
- {1087, {wxImage, blurVertical, 1}},
- {1088, {wxImage, convertAlphaToMask, 1}},
- {1089, {wxImage, convertToGreyscale, 1}},
- {1090, {wxImage, convertToMono, 3}},
- {1091, {wxImage, copy, 0}},
- {1092, {wxImage, create_3, 3}},
- {1093, {wxImage, create_4, 4}},
- {1094, {wxImage, create_5, 5}},
- {1095, {wxImage, 'Destroy', 0}},
- {1096, {wxImage, findFirstUnusedColour, 4}},
- {1097, {wxImage, getImageExtWildcard, 0}},
- {1098, {wxImage, getAlpha_2, 2}},
- {1099, {wxImage, getAlpha_0, 0}},
- {1100, {wxImage, getBlue, 2}},
- {1101, {wxImage, getData, 0}},
- {1102, {wxImage, getGreen, 2}},
- {1103, {wxImage, getImageCount, 2}},
- {1104, {wxImage, getHeight, 0}},
- {1105, {wxImage, getMaskBlue, 0}},
- {1106, {wxImage, getMaskGreen, 0}},
- {1107, {wxImage, getMaskRed, 0}},
- {1108, {wxImage, getOrFindMaskColour, 3}},
- {1109, {wxImage, getPalette, 0}},
- {1110, {wxImage, getRed, 2}},
- {1111, {wxImage, getSubImage, 1}},
- {1112, {wxImage, getWidth, 0}},
- {1113, {wxImage, hasAlpha, 0}},
- {1114, {wxImage, hasMask, 0}},
- {1115, {wxImage, getOption, 1}},
- {1116, {wxImage, getOptionInt, 1}},
- {1117, {wxImage, hasOption, 1}},
- {1118, {wxImage, initAlpha, 0}},
- {1119, {wxImage, initStandardHandlers, 0}},
- {1120, {wxImage, isTransparent, 3}},
- {1121, {wxImage, loadFile_2, 2}},
- {1122, {wxImage, loadFile_3, 3}},
- {1123, {wxImage, ok, 0}},
- {1124, {wxImage, removeHandler, 1}},
- {1125, {wxImage, mirror, 1}},
- {1126, {wxImage, replace, 6}},
- {1127, {wxImage, rescale, 3}},
- {1128, {wxImage, resize, 3}},
- {1129, {wxImage, rotate, 3}},
- {1130, {wxImage, rotateHue, 1}},
- {1131, {wxImage, rotate90, 1}},
- {1132, {wxImage, saveFile_1, 1}},
- {1133, {wxImage, saveFile_2_0, 2}},
- {1134, {wxImage, saveFile_2_1, 2}},
- {1135, {wxImage, scale, 3}},
- {1136, {wxImage, size, 3}},
- {1137, {wxImage, setAlpha_3, 3}},
- {1138, {wxImage, setAlpha_2, 2}},
- {1139, {wxImage, setData_2, 2}},
- {1140, {wxImage, setData_4, 4}},
- {1141, {wxImage, setMask, 1}},
- {1142, {wxImage, setMaskColour, 3}},
- {1143, {wxImage, setMaskFromImage, 4}},
- {1144, {wxImage, setOption_2_1, 2}},
- {1145, {wxImage, setOption_2_0, 2}},
- {1146, {wxImage, setPalette, 1}},
- {1147, {wxImage, setRGB_5, 5}},
- {1148, {wxImage, setRGB_4, 4}},
- {1149, {wxImage, 'Destroy', undefined}},
- {1150, {wxBrush, new_0, 0}},
- {1151, {wxBrush, new_2, 2}},
- {1152, {wxBrush, new_1, 1}},
- {1154, {wxBrush, destruct, 0}},
- {1155, {wxBrush, getColour, 0}},
- {1156, {wxBrush, getStipple, 0}},
- {1157, {wxBrush, getStyle, 0}},
- {1158, {wxBrush, isHatch, 0}},
- {1159, {wxBrush, isOk, 0}},
- {1160, {wxBrush, setColour_1, 1}},
- {1161, {wxBrush, setColour_3, 3}},
- {1162, {wxBrush, setStipple, 1}},
- {1163, {wxBrush, setStyle, 1}},
- {1164, {wxPen, new_0, 0}},
- {1165, {wxPen, new_2, 2}},
- {1166, {wxPen, destruct, 0}},
- {1167, {wxPen, getCap, 0}},
- {1168, {wxPen, getColour, 0}},
- {1169, {wxPen, getJoin, 0}},
- {1170, {wxPen, getStyle, 0}},
- {1171, {wxPen, getWidth, 0}},
- {1172, {wxPen, isOk, 0}},
- {1173, {wxPen, setCap, 1}},
- {1174, {wxPen, setColour_1, 1}},
- {1175, {wxPen, setColour_3, 3}},
- {1176, {wxPen, setJoin, 1}},
- {1177, {wxPen, setStyle, 1}},
- {1178, {wxPen, setWidth, 1}},
- {1179, {wxRegion, new_0, 0}},
- {1180, {wxRegion, new_4, 4}},
- {1181, {wxRegion, new_2, 2}},
- {1182, {wxRegion, new_1_1, 1}},
- {1184, {wxRegion, new_1_0, 1}},
- {1186, {wxRegion, destruct, 0}},
- {1187, {wxRegion, clear, 0}},
- {1188, {wxRegion, contains_2, 2}},
- {1189, {wxRegion, contains_1_0, 1}},
- {1190, {wxRegion, contains_4, 4}},
- {1191, {wxRegion, contains_1_1, 1}},
- {1192, {wxRegion, convertToBitmap, 0}},
- {1193, {wxRegion, getBox, 0}},
- {1194, {wxRegion, intersect_4, 4}},
- {1195, {wxRegion, intersect_1_1, 1}},
- {1196, {wxRegion, intersect_1_0, 1}},
- {1197, {wxRegion, isEmpty, 0}},
- {1198, {wxRegion, subtract_4, 4}},
- {1199, {wxRegion, subtract_1_1, 1}},
- {1200, {wxRegion, subtract_1_0, 1}},
- {1201, {wxRegion, offset_2, 2}},
- {1202, {wxRegion, offset_1, 1}},
- {1203, {wxRegion, union_4, 4}},
- {1204, {wxRegion, union_1_2, 1}},
- {1205, {wxRegion, union_1_1, 1}},
- {1206, {wxRegion, union_1_0, 1}},
- {1207, {wxRegion, union_3, 3}},
- {1208, {wxRegion, xor_4, 4}},
- {1209, {wxRegion, xor_1_1, 1}},
- {1210, {wxRegion, xor_1_0, 1}},
- {1211, {wxAcceleratorTable, new_0, 0}},
- {1212, {wxAcceleratorTable, new_2, 2}},
- {1213, {wxAcceleratorTable, destruct, 0}},
- {1214, {wxAcceleratorTable, ok, 0}},
- {1215, {wxAcceleratorEntry, new_1_0, 1}},
- {1216, {wxAcceleratorEntry, new_1_1, 1}},
- {1217, {wxAcceleratorEntry, getCommand, 0}},
- {1218, {wxAcceleratorEntry, getFlags, 0}},
- {1219, {wxAcceleratorEntry, getKeyCode, 0}},
- {1220, {wxAcceleratorEntry, set, 4}},
- {1221, {wxAcceleratorEntry, 'Destroy', undefined}},
- {1226, {wxCaret, new_3, 3}},
- {1227, {wxCaret, new_2, 2}},
- {1229, {wxCaret, destruct, 0}},
- {1230, {wxCaret, create_3, 3}},
- {1231, {wxCaret, create_2, 2}},
- {1232, {wxCaret, getBlinkTime, 0}},
- {1234, {wxCaret, getPosition, 0}},
- {1236, {wxCaret, getSize, 0}},
- {1237, {wxCaret, getWindow, 0}},
- {1238, {wxCaret, hide, 0}},
- {1239, {wxCaret, isOk, 0}},
- {1240, {wxCaret, isVisible, 0}},
- {1241, {wxCaret, move_2, 2}},
- {1242, {wxCaret, move_1, 1}},
- {1243, {wxCaret, setBlinkTime, 1}},
- {1244, {wxCaret, setSize_2, 2}},
- {1245, {wxCaret, setSize_1, 1}},
- {1246, {wxCaret, show, 1}},
- {1247, {wxSizer, add_2_1, 2}},
- {1248, {wxSizer, add_2_0, 2}},
- {1249, {wxSizer, add_3, 3}},
- {1250, {wxSizer, add_2_3, 2}},
- {1251, {wxSizer, add_2_2, 2}},
- {1252, {wxSizer, addSpacer, 1}},
- {1253, {wxSizer, addStretchSpacer, 1}},
- {1254, {wxSizer, calcMin, 0}},
- {1255, {wxSizer, clear, 1}},
- {1256, {wxSizer, detach_1_2, 1}},
- {1257, {wxSizer, detach_1_1, 1}},
- {1258, {wxSizer, detach_1_0, 1}},
- {1259, {wxSizer, fit, 1}},
- {1260, {wxSizer, fitInside, 1}},
- {1261, {wxSizer, getChildren, 0}},
- {1262, {wxSizer, getItem_2_1, 2}},
- {1263, {wxSizer, getItem_2_0, 2}},
- {1264, {wxSizer, getItem_1, 1}},
- {1265, {wxSizer, getSize, 0}},
- {1266, {wxSizer, getPosition, 0}},
- {1267, {wxSizer, getMinSize, 0}},
- {1268, {wxSizer, hide_2_0, 2}},
- {1269, {wxSizer, hide_2_1, 2}},
- {1270, {wxSizer, hide_1, 1}},
- {1271, {wxSizer, insert_3_1, 3}},
- {1272, {wxSizer, insert_3_0, 3}},
- {1273, {wxSizer, insert_4, 4}},
- {1274, {wxSizer, insert_3_3, 3}},
- {1275, {wxSizer, insert_3_2, 3}},
- {1276, {wxSizer, insert_2, 2}},
- {1277, {wxSizer, insertSpacer, 2}},
- {1278, {wxSizer, insertStretchSpacer, 2}},
- {1279, {wxSizer, isShown_1_2, 1}},
- {1280, {wxSizer, isShown_1_1, 1}},
- {1281, {wxSizer, isShown_1_0, 1}},
- {1282, {wxSizer, layout, 0}},
- {1283, {wxSizer, prepend_2_1, 2}},
- {1284, {wxSizer, prepend_2_0, 2}},
- {1285, {wxSizer, prepend_3, 3}},
- {1286, {wxSizer, prepend_2_3, 2}},
- {1287, {wxSizer, prepend_2_2, 2}},
- {1288, {wxSizer, prepend_1, 1}},
- {1289, {wxSizer, prependSpacer, 1}},
- {1290, {wxSizer, prependStretchSpacer, 1}},
- {1291, {wxSizer, recalcSizes, 0}},
- {1292, {wxSizer, remove_1_1, 1}},
- {1293, {wxSizer, remove_1_0, 1}},
- {1294, {wxSizer, replace_3_1, 3}},
- {1295, {wxSizer, replace_3_0, 3}},
- {1296, {wxSizer, replace_2, 2}},
- {1297, {wxSizer, setDimension, 4}},
- {1298, {wxSizer, setMinSize_2, 2}},
- {1299, {wxSizer, setMinSize_1, 1}},
- {1300, {wxSizer, setItemMinSize_3_2, 3}},
- {1301, {wxSizer, setItemMinSize_2_2, 2}},
- {1302, {wxSizer, setItemMinSize_3_1, 3}},
- {1303, {wxSizer, setItemMinSize_2_1, 2}},
- {1304, {wxSizer, setItemMinSize_3_0, 3}},
- {1305, {wxSizer, setItemMinSize_2_0, 2}},
- {1306, {wxSizer, setSizeHints, 1}},
- {1307, {wxSizer, setVirtualSizeHints, 1}},
- {1308, {wxSizer, show_2_2, 2}},
- {1309, {wxSizer, show_2_1, 2}},
- {1310, {wxSizer, show_2_0, 2}},
- {1311, {wxSizer, show_1, 1}},
- {1312, {wxSizerFlags, new, 1}},
- {1313, {wxSizerFlags, align, 1}},
- {1314, {wxSizerFlags, border_2, 2}},
- {1315, {wxSizerFlags, border_1, 1}},
- {1316, {wxSizerFlags, center, 0}},
- {1317, {wxSizerFlags, centre, 0}},
- {1318, {wxSizerFlags, expand, 0}},
- {1319, {wxSizerFlags, left, 0}},
- {1320, {wxSizerFlags, proportion, 1}},
- {1321, {wxSizerFlags, right, 0}},
- {1322, {wxSizerFlags, 'Destroy', undefined}},
- {1323, {wxSizerItem, new_5_1, 5}},
- {1324, {wxSizerItem, new_2_1, 2}},
- {1325, {wxSizerItem, new_5_0, 5}},
- {1326, {wxSizerItem, new_2_0, 2}},
- {1327, {wxSizerItem, new_6, 6}},
- {1328, {wxSizerItem, new_3, 3}},
- {1329, {wxSizerItem, new_0, 0}},
- {1330, {wxSizerItem, destruct, 0}},
- {1331, {wxSizerItem, calcMin, 0}},
- {1332, {wxSizerItem, deleteWindows, 0}},
- {1333, {wxSizerItem, detachSizer, 0}},
- {1334, {wxSizerItem, getBorder, 0}},
- {1335, {wxSizerItem, getFlag, 0}},
- {1336, {wxSizerItem, getMinSize, 0}},
- {1337, {wxSizerItem, getPosition, 0}},
- {1338, {wxSizerItem, getProportion, 0}},
- {1339, {wxSizerItem, getRatio, 0}},
- {1340, {wxSizerItem, getRect, 0}},
- {1341, {wxSizerItem, getSize, 0}},
- {1342, {wxSizerItem, getSizer, 0}},
- {1343, {wxSizerItem, getSpacer, 0}},
- {1344, {wxSizerItem, getUserData, 0}},
- {1345, {wxSizerItem, getWindow, 0}},
- {1346, {wxSizerItem, isSizer, 0}},
- {1347, {wxSizerItem, isShown, 0}},
- {1348, {wxSizerItem, isSpacer, 0}},
- {1349, {wxSizerItem, isWindow, 0}},
- {1350, {wxSizerItem, setBorder, 1}},
- {1351, {wxSizerItem, setDimension, 2}},
- {1352, {wxSizerItem, setFlag, 1}},
- {1353, {wxSizerItem, setInitSize, 2}},
- {1354, {wxSizerItem, setMinSize_1, 1}},
- {1355, {wxSizerItem, setMinSize_2, 2}},
- {1356, {wxSizerItem, setProportion, 1}},
- {1357, {wxSizerItem, setRatio_2, 2}},
- {1358, {wxSizerItem, setRatio_1_1, 1}},
- {1359, {wxSizerItem, setRatio_1_0, 1}},
- {1360, {wxSizerItem, setSizer, 1}},
- {1361, {wxSizerItem, setSpacer_1, 1}},
- {1362, {wxSizerItem, setSpacer_2, 2}},
- {1363, {wxSizerItem, setWindow, 1}},
- {1364, {wxSizerItem, show, 1}},
- {1365, {wxBoxSizer, new, 1}},
- {1366, {wxBoxSizer, getOrientation, 0}},
- {1367, {wxBoxSizer, 'Destroy', undefined}},
- {1368, {wxStaticBoxSizer, new_2, 2}},
- {1369, {wxStaticBoxSizer, new_3, 3}},
- {1370, {wxStaticBoxSizer, getStaticBox, 0}},
- {1371, {wxStaticBoxSizer, 'Destroy', undefined}},
- {1372, {wxGridSizer, new_4, 4}},
- {1373, {wxGridSizer, new_2, 2}},
- {1374, {wxGridSizer, getCols, 0}},
- {1375, {wxGridSizer, getHGap, 0}},
- {1376, {wxGridSizer, getRows, 0}},
- {1377, {wxGridSizer, getVGap, 0}},
- {1378, {wxGridSizer, setCols, 1}},
- {1379, {wxGridSizer, setHGap, 1}},
- {1380, {wxGridSizer, setRows, 1}},
- {1381, {wxGridSizer, setVGap, 1}},
- {1382, {wxGridSizer, 'Destroy', undefined}},
- {1383, {wxFlexGridSizer, new_4, 4}},
- {1384, {wxFlexGridSizer, new_2, 2}},
- {1385, {wxFlexGridSizer, addGrowableCol, 2}},
- {1386, {wxFlexGridSizer, addGrowableRow, 2}},
- {1387, {wxFlexGridSizer, getFlexibleDirection, 0}},
- {1388, {wxFlexGridSizer, getNonFlexibleGrowMode, 0}},
- {1389, {wxFlexGridSizer, removeGrowableCol, 1}},
- {1390, {wxFlexGridSizer, removeGrowableRow, 1}},
- {1391, {wxFlexGridSizer, setFlexibleDirection, 1}},
- {1392, {wxFlexGridSizer, setNonFlexibleGrowMode, 1}},
- {1393, {wxFlexGridSizer, 'Destroy', undefined}},
- {1394, {wxGridBagSizer, new, 1}},
- {1395, {wxGridBagSizer, add_3_2, 3}},
- {1396, {wxGridBagSizer, add_3_1, 3}},
- {1397, {wxGridBagSizer, add_4, 4}},
- {1398, {wxGridBagSizer, add_1_0, 1}},
- {1399, {wxGridBagSizer, add_2_1, 2}},
- {1400, {wxGridBagSizer, add_2_0, 2}},
- {1401, {wxGridBagSizer, add_3_0, 3}},
- {1402, {wxGridBagSizer, add_1_1, 1}},
- {1403, {wxGridBagSizer, calcMin, 0}},
- {1404, {wxGridBagSizer, checkForIntersection_2, 2}},
- {1405, {wxGridBagSizer, checkForIntersection_3, 3}},
- {1406, {wxGridBagSizer, findItem_1_1, 1}},
- {1407, {wxGridBagSizer, findItem_1_0, 1}},
- {1408, {wxGridBagSizer, findItemAtPoint, 1}},
- {1409, {wxGridBagSizer, findItemAtPosition, 1}},
- {1410, {wxGridBagSizer, findItemWithData, 1}},
- {1411, {wxGridBagSizer, getCellSize, 2}},
- {1412, {wxGridBagSizer, getEmptyCellSize, 0}},
- {1413, {wxGridBagSizer, getItemPosition_1_2, 1}},
- {1414, {wxGridBagSizer, getItemPosition_1_1, 1}},
- {1415, {wxGridBagSizer, getItemPosition_1_0, 1}},
- {1416, {wxGridBagSizer, getItemSpan_1_2, 1}},
- {1417, {wxGridBagSizer, getItemSpan_1_1, 1}},
- {1418, {wxGridBagSizer, getItemSpan_1_0, 1}},
- {1419, {wxGridBagSizer, setEmptyCellSize, 1}},
- {1420, {wxGridBagSizer, setItemPosition_2_2, 2}},
- {1421, {wxGridBagSizer, setItemPosition_2_1, 2}},
- {1422, {wxGridBagSizer, setItemPosition_2_0, 2}},
- {1423, {wxGridBagSizer, setItemSpan_2_2, 2}},
- {1424, {wxGridBagSizer, setItemSpan_2_1, 2}},
- {1425, {wxGridBagSizer, setItemSpan_2_0, 2}},
- {1426, {wxGridBagSizer, 'Destroy', undefined}},
- {1427, {wxStdDialogButtonSizer, new, 0}},
- {1428, {wxStdDialogButtonSizer, addButton, 1}},
- {1429, {wxStdDialogButtonSizer, realize, 0}},
- {1430, {wxStdDialogButtonSizer, setAffirmativeButton, 1}},
- {1431, {wxStdDialogButtonSizer, setCancelButton, 1}},
- {1432, {wxStdDialogButtonSizer, setNegativeButton, 1}},
- {1433, {wxStdDialogButtonSizer, 'Destroy', undefined}},
- {1434, {wxFont, new_0, 0}},
- {1435, {wxFont, new_1, 1}},
- {1436, {wxFont, new_5, 5}},
- {1438, {wxFont, destruct, 0}},
- {1439, {wxFont, isFixedWidth, 0}},
- {1440, {wxFont, getDefaultEncoding, 0}},
- {1441, {wxFont, getFaceName, 0}},
- {1442, {wxFont, getFamily, 0}},
- {1443, {wxFont, getNativeFontInfoDesc, 0}},
- {1444, {wxFont, getNativeFontInfoUserDesc, 0}},
- {1445, {wxFont, getPointSize, 0}},
- {1446, {wxFont, getStyle, 0}},
- {1447, {wxFont, getUnderlined, 0}},
- {1448, {wxFont, getWeight, 0}},
- {1449, {wxFont, ok, 0}},
- {1450, {wxFont, setDefaultEncoding, 1}},
- {1451, {wxFont, setFaceName, 1}},
- {1452, {wxFont, setFamily, 1}},
- {1453, {wxFont, setPointSize, 1}},
- {1454, {wxFont, setStyle, 1}},
- {1455, {wxFont, setUnderlined, 1}},
- {1456, {wxFont, setWeight, 1}},
- {1457, {wxToolTip, enable, 1}},
- {1458, {wxToolTip, setDelay, 1}},
- {1459, {wxToolTip, new, 1}},
- {1460, {wxToolTip, setTip, 1}},
- {1461, {wxToolTip, getTip, 0}},
- {1462, {wxToolTip, getWindow, 0}},
- {1463, {wxToolTip, 'Destroy', undefined}},
- {1465, {wxButton, new_3, 3}},
- {1466, {wxButton, new_0, 0}},
- {1467, {wxButton, destruct, 0}},
- {1468, {wxButton, create, 3}},
- {1469, {wxButton, getDefaultSize, 0}},
- {1470, {wxButton, setDefault, 0}},
- {1471, {wxButton, setLabel, 1}},
- {1473, {wxBitmapButton, new_4, 4}},
- {1474, {wxBitmapButton, new_0, 0}},
- {1475, {wxBitmapButton, create, 4}},
- {1476, {wxBitmapButton, getBitmapDisabled, 0}},
- {1478, {wxBitmapButton, getBitmapFocus, 0}},
- {1480, {wxBitmapButton, getBitmapLabel, 0}},
- {1482, {wxBitmapButton, getBitmapSelected, 0}},
- {1484, {wxBitmapButton, setBitmapDisabled, 1}},
- {1485, {wxBitmapButton, setBitmapFocus, 1}},
- {1486, {wxBitmapButton, setBitmapLabel, 1}},
- {1487, {wxBitmapButton, setBitmapSelected, 1}},
- {1488, {wxBitmapButton, 'Destroy', undefined}},
- {1489, {wxToggleButton, new_0, 0}},
- {1490, {wxToggleButton, new_4, 4}},
- {1491, {wxToggleButton, create, 4}},
- {1492, {wxToggleButton, getValue, 0}},
- {1493, {wxToggleButton, setValue, 1}},
- {1494, {wxToggleButton, 'Destroy', undefined}},
- {1495, {wxCalendarCtrl, new_0, 0}},
- {1496, {wxCalendarCtrl, new_3, 3}},
- {1497, {wxCalendarCtrl, create, 3}},
- {1498, {wxCalendarCtrl, destruct, 0}},
- {1499, {wxCalendarCtrl, setDate, 1}},
- {1500, {wxCalendarCtrl, getDate, 0}},
- {1501, {wxCalendarCtrl, enableYearChange, 1}},
- {1502, {wxCalendarCtrl, enableMonthChange, 1}},
- {1503, {wxCalendarCtrl, enableHolidayDisplay, 1}},
- {1504, {wxCalendarCtrl, setHeaderColours, 2}},
- {1505, {wxCalendarCtrl, getHeaderColourFg, 0}},
- {1506, {wxCalendarCtrl, getHeaderColourBg, 0}},
- {1507, {wxCalendarCtrl, setHighlightColours, 2}},
- {1508, {wxCalendarCtrl, getHighlightColourFg, 0}},
- {1509, {wxCalendarCtrl, getHighlightColourBg, 0}},
- {1510, {wxCalendarCtrl, setHolidayColours, 2}},
- {1511, {wxCalendarCtrl, getHolidayColourFg, 0}},
- {1512, {wxCalendarCtrl, getHolidayColourBg, 0}},
- {1513, {wxCalendarCtrl, getAttr, 1}},
- {1514, {wxCalendarCtrl, setAttr, 2}},
- {1515, {wxCalendarCtrl, setHoliday, 1}},
- {1516, {wxCalendarCtrl, resetAttr, 1}},
- {1517, {wxCalendarCtrl, hitTest, 2}},
- {1518, {wxCalendarDateAttr, new_0, 0}},
- {1519, {wxCalendarDateAttr, new_2_1, 2}},
- {1520, {wxCalendarDateAttr, new_2_0, 2}},
- {1521, {wxCalendarDateAttr, setTextColour, 1}},
- {1522, {wxCalendarDateAttr, setBackgroundColour, 1}},
- {1523, {wxCalendarDateAttr, setBorderColour, 1}},
- {1524, {wxCalendarDateAttr, setFont, 1}},
- {1525, {wxCalendarDateAttr, setBorder, 1}},
- {1526, {wxCalendarDateAttr, setHoliday, 1}},
- {1527, {wxCalendarDateAttr, hasTextColour, 0}},
- {1528, {wxCalendarDateAttr, hasBackgroundColour, 0}},
- {1529, {wxCalendarDateAttr, hasBorderColour, 0}},
- {1530, {wxCalendarDateAttr, hasFont, 0}},
- {1531, {wxCalendarDateAttr, hasBorder, 0}},
- {1532, {wxCalendarDateAttr, isHoliday, 0}},
- {1533, {wxCalendarDateAttr, getTextColour, 0}},
- {1534, {wxCalendarDateAttr, getBackgroundColour, 0}},
- {1535, {wxCalendarDateAttr, getBorderColour, 0}},
- {1536, {wxCalendarDateAttr, getFont, 0}},
- {1537, {wxCalendarDateAttr, getBorder, 0}},
- {1538, {wxCalendarDateAttr, 'Destroy', undefined}},
- {1540, {wxCheckBox, new_4, 4}},
- {1541, {wxCheckBox, new_0, 0}},
- {1542, {wxCheckBox, create, 4}},
- {1543, {wxCheckBox, getValue, 0}},
- {1544, {wxCheckBox, get3StateValue, 0}},
- {1545, {wxCheckBox, is3rdStateAllowedForUser, 0}},
- {1546, {wxCheckBox, is3State, 0}},
- {1547, {wxCheckBox, isChecked, 0}},
- {1548, {wxCheckBox, setValue, 1}},
- {1549, {wxCheckBox, set3StateValue, 1}},
- {1550, {wxCheckBox, 'Destroy', undefined}},
- {1551, {wxCheckListBox, new_0, 0}},
- {1553, {wxCheckListBox, new_3, 3}},
- {1554, {wxCheckListBox, check, 2}},
- {1555, {wxCheckListBox, isChecked, 1}},
- {1556, {wxCheckListBox, 'Destroy', undefined}},
- {1559, {wxChoice, new_3, 3}},
- {1560, {wxChoice, new_0, 0}},
- {1562, {wxChoice, destruct, 0}},
- {1564, {wxChoice, create, 6}},
- {1565, {wxChoice, delete, 1}},
- {1566, {wxChoice, getColumns, 0}},
- {1567, {wxChoice, setColumns, 1}},
- {1568, {wxComboBox, new_0, 0}},
- {1570, {wxComboBox, new_3, 3}},
- {1571, {wxComboBox, destruct, 0}},
- {1573, {wxComboBox, create, 7}},
- {1574, {wxComboBox, canCopy, 0}},
- {1575, {wxComboBox, canCut, 0}},
- {1576, {wxComboBox, canPaste, 0}},
- {1577, {wxComboBox, canRedo, 0}},
- {1578, {wxComboBox, canUndo, 0}},
- {1579, {wxComboBox, copy, 0}},
- {1580, {wxComboBox, cut, 0}},
- {1581, {wxComboBox, getInsertionPoint, 0}},
- {1582, {wxComboBox, getLastPosition, 0}},
- {1583, {wxComboBox, getValue, 0}},
- {1584, {wxComboBox, paste, 0}},
- {1585, {wxComboBox, redo, 0}},
- {1586, {wxComboBox, replace, 3}},
- {1587, {wxComboBox, remove, 2}},
- {1588, {wxComboBox, setInsertionPoint, 1}},
- {1589, {wxComboBox, setInsertionPointEnd, 0}},
- {1590, {wxComboBox, setSelection_1, 1}},
- {1591, {wxComboBox, setSelection_2, 2}},
- {1592, {wxComboBox, setValue, 1}},
- {1593, {wxComboBox, undo, 0}},
- {1594, {wxGauge, new_0, 0}},
- {1595, {wxGauge, new_4, 4}},
- {1596, {wxGauge, create, 4}},
- {1597, {wxGauge, getBezelFace, 0}},
- {1598, {wxGauge, getRange, 0}},
- {1599, {wxGauge, getShadowWidth, 0}},
- {1600, {wxGauge, getValue, 0}},
- {1601, {wxGauge, isVertical, 0}},
- {1602, {wxGauge, setBezelFace, 1}},
- {1603, {wxGauge, setRange, 1}},
- {1604, {wxGauge, setShadowWidth, 1}},
- {1605, {wxGauge, setValue, 1}},
- {1606, {wxGauge, pulse, 0}},
- {1607, {wxGauge, 'Destroy', undefined}},
- {1608, {wxGenericDirCtrl, new_0, 0}},
- {1609, {wxGenericDirCtrl, new_2, 2}},
- {1610, {wxGenericDirCtrl, destruct, 0}},
- {1611, {wxGenericDirCtrl, create, 2}},
- {1612, {wxGenericDirCtrl, init, 0}},
- {1613, {wxGenericDirCtrl, collapseTree, 0}},
- {1614, {wxGenericDirCtrl, expandPath, 1}},
- {1615, {wxGenericDirCtrl, getDefaultPath, 0}},
- {1616, {wxGenericDirCtrl, getPath, 0}},
- {1617, {wxGenericDirCtrl, getFilePath, 0}},
- {1618, {wxGenericDirCtrl, getFilter, 0}},
- {1619, {wxGenericDirCtrl, getFilterIndex, 0}},
- {1620, {wxGenericDirCtrl, getRootId, 0}},
- {1621, {wxGenericDirCtrl, getTreeCtrl, 0}},
- {1622, {wxGenericDirCtrl, reCreateTree, 0}},
- {1623, {wxGenericDirCtrl, setDefaultPath, 1}},
- {1624, {wxGenericDirCtrl, setFilter, 1}},
- {1625, {wxGenericDirCtrl, setFilterIndex, 1}},
- {1626, {wxGenericDirCtrl, setPath, 1}},
- {1628, {wxStaticBox, new_4, 4}},
- {1629, {wxStaticBox, new_0, 0}},
- {1630, {wxStaticBox, create, 4}},
- {1631, {wxStaticBox, 'Destroy', undefined}},
- {1633, {wxStaticLine, new_2, 2}},
- {1634, {wxStaticLine, new_0, 0}},
- {1635, {wxStaticLine, create, 2}},
- {1636, {wxStaticLine, isVertical, 0}},
- {1637, {wxStaticLine, getDefaultSize, 0}},
- {1638, {wxStaticLine, 'Destroy', undefined}},
- {1641, {wxListBox, new_3, 3}},
- {1642, {wxListBox, new_0, 0}},
- {1644, {wxListBox, destruct, 0}},
- {1646, {wxListBox, create, 6}},
- {1647, {wxListBox, deselect, 1}},
- {1648, {wxListBox, getSelections, 1}},
- {1649, {wxListBox, insertItems, 2}},
- {1650, {wxListBox, isSelected, 1}},
- {1652, {wxListBox, set, 2}},
- {1653, {wxListBox, hitTest, 1}},
- {1654, {wxListBox, setFirstItem_1_0, 1}},
- {1655, {wxListBox, setFirstItem_1_1, 1}},
- {1656, {wxListCtrl, new_0, 0}},
- {1657, {wxListCtrl, new_2, 2}},
- {1658, {wxListCtrl, arrange, 1}},
- {1659, {wxListCtrl, assignImageList, 2}},
- {1660, {wxListCtrl, clearAll, 0}},
- {1661, {wxListCtrl, create, 2}},
- {1662, {wxListCtrl, deleteAllItems, 0}},
- {1663, {wxListCtrl, deleteColumn, 1}},
- {1664, {wxListCtrl, deleteItem, 1}},
- {1665, {wxListCtrl, editLabel, 1}},
- {1666, {wxListCtrl, ensureVisible, 1}},
- {1667, {wxListCtrl, findItem_3_0, 3}},
- {1668, {wxListCtrl, findItem_3_1, 3}},
- {1669, {wxListCtrl, getColumn, 2}},
- {1670, {wxListCtrl, getColumnCount, 0}},
- {1671, {wxListCtrl, getColumnWidth, 1}},
- {1672, {wxListCtrl, getCountPerPage, 0}},
- {1673, {wxListCtrl, getEditControl, 0}},
- {1674, {wxListCtrl, getImageList, 1}},
- {1675, {wxListCtrl, getItem, 1}},
- {1676, {wxListCtrl, getItemBackgroundColour, 1}},
- {1677, {wxListCtrl, getItemCount, 0}},
- {1678, {wxListCtrl, getItemData, 1}},
- {1679, {wxListCtrl, getItemFont, 1}},
- {1680, {wxListCtrl, getItemPosition, 2}},
- {1681, {wxListCtrl, getItemRect, 3}},
- {1682, {wxListCtrl, getItemSpacing, 0}},
- {1683, {wxListCtrl, getItemState, 2}},
- {1684, {wxListCtrl, getItemText, 1}},
- {1685, {wxListCtrl, getItemTextColour, 1}},
- {1686, {wxListCtrl, getNextItem, 2}},
- {1687, {wxListCtrl, getSelectedItemCount, 0}},
- {1688, {wxListCtrl, getTextColour, 0}},
- {1689, {wxListCtrl, getTopItem, 0}},
- {1690, {wxListCtrl, getViewRect, 0}},
- {1691, {wxListCtrl, hitTest, 2}},
- {1692, {wxListCtrl, insertColumn_2, 2}},
- {1693, {wxListCtrl, insertColumn_3, 3}},
- {1694, {wxListCtrl, insertItem_1, 1}},
- {1695, {wxListCtrl, insertItem_2_1, 2}},
- {1696, {wxListCtrl, insertItem_2_0, 2}},
- {1697, {wxListCtrl, insertItem_3, 3}},
- {1698, {wxListCtrl, refreshItem, 1}},
- {1699, {wxListCtrl, refreshItems, 2}},
- {1700, {wxListCtrl, scrollList, 2}},
- {1701, {wxListCtrl, setBackgroundColour, 1}},
- {1702, {wxListCtrl, setColumn, 2}},
- {1703, {wxListCtrl, setColumnWidth, 2}},
- {1704, {wxListCtrl, setImageList, 2}},
- {1705, {wxListCtrl, setItem_1, 1}},
- {1706, {wxListCtrl, setItem_4, 4}},
- {1707, {wxListCtrl, setItemBackgroundColour, 2}},
- {1708, {wxListCtrl, setItemCount, 1}},
- {1709, {wxListCtrl, setItemData, 2}},
- {1710, {wxListCtrl, setItemFont, 2}},
- {1711, {wxListCtrl, setItemImage, 3}},
- {1712, {wxListCtrl, setItemColumnImage, 3}},
- {1713, {wxListCtrl, setItemPosition, 2}},
- {1714, {wxListCtrl, setItemState, 3}},
- {1715, {wxListCtrl, setItemText, 2}},
- {1716, {wxListCtrl, setItemTextColour, 2}},
- {1717, {wxListCtrl, setSingleStyle, 2}},
- {1718, {wxListCtrl, setTextColour, 1}},
- {1719, {wxListCtrl, setWindowStyleFlag, 1}},
- {1720, {wxListCtrl, sortItems, 2}},
- {1721, {wxListCtrl, 'Destroy', undefined}},
- {1722, {wxListView, clearColumnImage, 1}},
- {1723, {wxListView, focus, 1}},
- {1724, {wxListView, getFirstSelected, 0}},
- {1725, {wxListView, getFocusedItem, 0}},
- {1726, {wxListView, getNextSelected, 1}},
- {1727, {wxListView, isSelected, 1}},
- {1728, {wxListView, select, 2}},
- {1729, {wxListView, setColumnImage, 2}},
- {1730, {wxListItem, new_0, 0}},
- {1731, {wxListItem, new_1, 1}},
- {1732, {wxListItem, destruct, 0}},
- {1733, {wxListItem, clear, 0}},
- {1734, {wxListItem, getAlign, 0}},
- {1735, {wxListItem, getBackgroundColour, 0}},
- {1736, {wxListItem, getColumn, 0}},
- {1737, {wxListItem, getFont, 0}},
- {1738, {wxListItem, getId, 0}},
- {1739, {wxListItem, getImage, 0}},
- {1740, {wxListItem, getMask, 0}},
- {1741, {wxListItem, getState, 0}},
- {1742, {wxListItem, getText, 0}},
- {1743, {wxListItem, getTextColour, 0}},
- {1744, {wxListItem, getWidth, 0}},
- {1745, {wxListItem, setAlign, 1}},
- {1746, {wxListItem, setBackgroundColour, 1}},
- {1747, {wxListItem, setColumn, 1}},
- {1748, {wxListItem, setFont, 1}},
- {1749, {wxListItem, setId, 1}},
- {1750, {wxListItem, setImage, 1}},
- {1751, {wxListItem, setMask, 1}},
- {1752, {wxListItem, setState, 1}},
- {1753, {wxListItem, setStateMask, 1}},
- {1754, {wxListItem, setText, 1}},
- {1755, {wxListItem, setTextColour, 1}},
- {1756, {wxListItem, setWidth, 1}},
- {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}},
+ {665, {wxDC, getClippingBox, 4}},
+ {667, {wxDC, getFont, 0}},
+ {668, {wxDC, getLayoutDirection, 0}},
+ {669, {wxDC, getLogicalFunction, 0}},
+ {670, {wxDC, getMapMode, 0}},
+ {671, {wxDC, getMultiLineTextExtent_4, 4}},
+ {672, {wxDC, getMultiLineTextExtent_1, 1}},
+ {673, {wxDC, getPartialTextExtents, 2}},
+ {674, {wxDC, getPen, 0}},
+ {675, {wxDC, getPixel, 2}},
+ {676, {wxDC, getPPI, 0}},
+ {678, {wxDC, getSize, 0}},
+ {680, {wxDC, getSizeMM, 0}},
+ {681, {wxDC, getTextBackground, 0}},
+ {682, {wxDC, getTextExtent_4, 4}},
+ {683, {wxDC, getTextExtent_1, 1}},
+ {685, {wxDC, getTextForeground, 0}},
+ {686, {wxDC, getUserScale, 2}},
+ {687, {wxDC, gradientFillConcentric_3, 3}},
+ {688, {wxDC, gradientFillConcentric_4, 4}},
+ {689, {wxDC, gradientFillLinear, 4}},
+ {690, {wxDC, logicalToDeviceX, 1}},
+ {691, {wxDC, logicalToDeviceXRel, 1}},
+ {692, {wxDC, logicalToDeviceY, 1}},
+ {693, {wxDC, logicalToDeviceYRel, 1}},
+ {694, {wxDC, maxX, 0}},
+ {695, {wxDC, maxY, 0}},
+ {696, {wxDC, minX, 0}},
+ {697, {wxDC, minY, 0}},
+ {698, {wxDC, isOk, 0}},
+ {699, {wxDC, resetBoundingBox, 0}},
+ {700, {wxDC, setAxisOrientation, 2}},
+ {701, {wxDC, setBackground, 1}},
+ {702, {wxDC, setBackgroundMode, 1}},
+ {703, {wxDC, setBrush, 1}},
+ {705, {wxDC, setClippingRegion_2, 2}},
+ {706, {wxDC, setClippingRegion_1_1, 1}},
+ {707, {wxDC, setClippingRegion_1_0, 1}},
+ {708, {wxDC, setDeviceOrigin, 2}},
+ {709, {wxDC, setFont, 1}},
+ {710, {wxDC, setLayoutDirection, 1}},
+ {711, {wxDC, setLogicalFunction, 1}},
+ {712, {wxDC, setMapMode, 1}},
+ {713, {wxDC, setPalette, 1}},
+ {714, {wxDC, setPen, 1}},
+ {715, {wxDC, setTextBackground, 1}},
+ {716, {wxDC, setTextForeground, 1}},
+ {717, {wxDC, setUserScale, 2}},
+ {718, {wxDC, startDoc, 1}},
+ {719, {wxDC, startPage, 0}},
+ {720, {wxMirrorDC, new, 2}},
+ {721, {wxMirrorDC, 'Destroy', undefined}},
+ {722, {wxScreenDC, new, 0}},
+ {723, {wxScreenDC, destruct, 0}},
+ {724, {wxPostScriptDC, new_0, 0}},
+ {725, {wxPostScriptDC, new_1, 1}},
+ {726, {wxPostScriptDC, destruct, 0}},
+ {727, {wxPostScriptDC, setResolution, 1}},
+ {728, {wxPostScriptDC, getResolution, 0}},
+ {729, {wxWindowDC, new_0, 0}},
+ {730, {wxWindowDC, new_1, 1}},
+ {731, {wxWindowDC, destruct, 0}},
+ {732, {wxClientDC, new_0, 0}},
+ {733, {wxClientDC, new_1, 1}},
+ {734, {wxClientDC, 'Destroy', undefined}},
+ {735, {wxPaintDC, new_0, 0}},
+ {736, {wxPaintDC, new_1, 1}},
+ {737, {wxPaintDC, 'Destroy', undefined}},
+ {739, {wxMemoryDC, new_1_0, 1}},
+ {740, {wxMemoryDC, new_1_1, 1}},
+ {741, {wxMemoryDC, new_0, 0}},
+ {743, {wxMemoryDC, destruct, 0}},
+ {744, {wxMemoryDC, selectObject, 1}},
+ {745, {wxMemoryDC, selectObjectAsSource, 1}},
+ {746, {wxBufferedDC, new_0, 0}},
+ {747, {wxBufferedDC, new_2, 2}},
+ {748, {wxBufferedDC, new_3, 3}},
+ {749, {wxBufferedDC, destruct, 0}},
+ {750, {wxBufferedDC, init_2, 2}},
+ {751, {wxBufferedDC, init_3, 3}},
+ {752, {wxBufferedPaintDC, new_3, 3}},
+ {753, {wxBufferedPaintDC, new_2, 2}},
+ {754, {wxBufferedPaintDC, destruct, 0}},
+ {755, {wxGraphicsObject, destruct, 0}},
+ {756, {wxGraphicsObject, getRenderer, 0}},
+ {757, {wxGraphicsObject, isNull, 0}},
+ {758, {wxGraphicsContext, destruct, 0}},
+ {759, {wxGraphicsContext, create_1_1, 1}},
+ {760, {wxGraphicsContext, create_1_0, 1}},
+ {761, {wxGraphicsContext, create_0, 0}},
+ {762, {wxGraphicsContext, createPen, 1}},
+ {763, {wxGraphicsContext, createBrush, 1}},
+ {764, {wxGraphicsContext, createRadialGradientBrush, 7}},
+ {765, {wxGraphicsContext, createLinearGradientBrush, 6}},
+ {766, {wxGraphicsContext, createFont, 2}},
+ {767, {wxGraphicsContext, createMatrix, 1}},
+ {768, {wxGraphicsContext, createPath, 0}},
+ {769, {wxGraphicsContext, clip_1, 1}},
+ {770, {wxGraphicsContext, clip_4, 4}},
+ {771, {wxGraphicsContext, resetClip, 0}},
+ {772, {wxGraphicsContext, drawBitmap, 5}},
+ {773, {wxGraphicsContext, drawEllipse, 4}},
+ {774, {wxGraphicsContext, drawIcon, 5}},
+ {775, {wxGraphicsContext, drawLines, 3}},
+ {776, {wxGraphicsContext, drawPath, 2}},
+ {777, {wxGraphicsContext, drawRectangle, 4}},
+ {778, {wxGraphicsContext, drawRoundedRectangle, 5}},
+ {779, {wxGraphicsContext, drawText_3, 3}},
+ {780, {wxGraphicsContext, drawText_4_0, 4}},
+ {781, {wxGraphicsContext, drawText_4_1, 4}},
+ {782, {wxGraphicsContext, drawText_5, 5}},
+ {783, {wxGraphicsContext, fillPath, 2}},
+ {784, {wxGraphicsContext, strokePath, 1}},
+ {785, {wxGraphicsContext, getPartialTextExtents, 2}},
+ {786, {wxGraphicsContext, getTextExtent, 5}},
+ {787, {wxGraphicsContext, rotate, 1}},
+ {788, {wxGraphicsContext, scale, 2}},
+ {789, {wxGraphicsContext, translate, 2}},
+ {790, {wxGraphicsContext, getTransform, 0}},
+ {791, {wxGraphicsContext, setTransform, 1}},
+ {792, {wxGraphicsContext, concatTransform, 1}},
+ {793, {wxGraphicsContext, setBrush_1_1, 1}},
+ {794, {wxGraphicsContext, setBrush_1_0, 1}},
+ {795, {wxGraphicsContext, setFont_1, 1}},
+ {796, {wxGraphicsContext, setFont_2, 2}},
+ {797, {wxGraphicsContext, setPen_1_0, 1}},
+ {798, {wxGraphicsContext, setPen_1_1, 1}},
+ {799, {wxGraphicsContext, strokeLine, 4}},
+ {800, {wxGraphicsContext, strokeLines, 2}},
+ {802, {wxGraphicsMatrix, concat, 1}},
+ {804, {wxGraphicsMatrix, get, 1}},
+ {805, {wxGraphicsMatrix, invert, 0}},
+ {806, {wxGraphicsMatrix, isEqual, 1}},
+ {808, {wxGraphicsMatrix, isIdentity, 0}},
+ {809, {wxGraphicsMatrix, rotate, 1}},
+ {810, {wxGraphicsMatrix, scale, 2}},
+ {811, {wxGraphicsMatrix, translate, 2}},
+ {812, {wxGraphicsMatrix, set, 1}},
+ {813, {wxGraphicsMatrix, transformPoint, 2}},
+ {814, {wxGraphicsMatrix, transformDistance, 2}},
+ {815, {wxGraphicsPath, moveToPoint_2, 2}},
+ {816, {wxGraphicsPath, moveToPoint_1, 1}},
+ {817, {wxGraphicsPath, addArc_6, 6}},
+ {818, {wxGraphicsPath, addArc_5, 5}},
+ {819, {wxGraphicsPath, addArcToPoint, 5}},
+ {820, {wxGraphicsPath, addCircle, 3}},
+ {821, {wxGraphicsPath, addCurveToPoint_6, 6}},
+ {822, {wxGraphicsPath, addCurveToPoint_3, 3}},
+ {823, {wxGraphicsPath, addEllipse, 4}},
+ {824, {wxGraphicsPath, addLineToPoint_2, 2}},
+ {825, {wxGraphicsPath, addLineToPoint_1, 1}},
+ {826, {wxGraphicsPath, addPath, 1}},
+ {827, {wxGraphicsPath, addQuadCurveToPoint, 4}},
+ {828, {wxGraphicsPath, addRectangle, 4}},
+ {829, {wxGraphicsPath, addRoundedRectangle, 5}},
+ {830, {wxGraphicsPath, closeSubpath, 0}},
+ {831, {wxGraphicsPath, contains_3, 3}},
+ {832, {wxGraphicsPath, contains_2, 2}},
+ {834, {wxGraphicsPath, getBox, 0}},
+ {836, {wxGraphicsPath, getCurrentPoint, 0}},
+ {837, {wxGraphicsPath, transform, 1}},
+ {838, {wxGraphicsRenderer, getDefaultRenderer, 0}},
+ {839, {wxGraphicsRenderer, createContext_1_1, 1}},
+ {840, {wxGraphicsRenderer, createContext_1_0, 1}},
+ {841, {wxGraphicsRenderer, createPen, 1}},
+ {842, {wxGraphicsRenderer, createBrush, 1}},
+ {843, {wxGraphicsRenderer, createLinearGradientBrush, 6}},
+ {844, {wxGraphicsRenderer, createRadialGradientBrush, 7}},
+ {845, {wxGraphicsRenderer, createFont, 2}},
+ {846, {wxGraphicsRenderer, createMatrix, 1}},
+ {847, {wxGraphicsRenderer, createPath, 0}},
+ {849, {wxMenuBar, new_1, 1}},
+ {851, {wxMenuBar, new_0, 0}},
+ {853, {wxMenuBar, destruct, 0}},
+ {854, {wxMenuBar, append, 2}},
+ {855, {wxMenuBar, check, 2}},
+ {856, {wxMenuBar, enable_2, 2}},
+ {857, {wxMenuBar, enable_1, 1}},
+ {858, {wxMenuBar, enableTop, 2}},
+ {859, {wxMenuBar, findMenu, 1}},
+ {860, {wxMenuBar, findMenuItem, 2}},
+ {861, {wxMenuBar, findItem, 2}},
+ {862, {wxMenuBar, getHelpString, 1}},
+ {863, {wxMenuBar, getLabel_1, 1}},
+ {864, {wxMenuBar, getLabel_0, 0}},
+ {865, {wxMenuBar, getLabelTop, 1}},
+ {866, {wxMenuBar, getMenu, 1}},
+ {867, {wxMenuBar, getMenuCount, 0}},
+ {868, {wxMenuBar, insert, 3}},
+ {869, {wxMenuBar, isChecked, 1}},
+ {870, {wxMenuBar, isEnabled_1, 1}},
+ {871, {wxMenuBar, isEnabled_0, 0}},
+ {872, {wxMenuBar, remove, 1}},
+ {873, {wxMenuBar, replace, 3}},
+ {874, {wxMenuBar, setHelpString, 2}},
+ {875, {wxMenuBar, setLabel_2, 2}},
+ {876, {wxMenuBar, setLabel_1, 1}},
+ {877, {wxMenuBar, setLabelTop, 2}},
+ {878, {wxControl, getLabel, 0}},
+ {879, {wxControl, setLabel, 1}},
+ {880, {wxControlWithItems, append_1, 1}},
+ {881, {wxControlWithItems, append_2, 2}},
+ {882, {wxControlWithItems, appendStrings_1, 1}},
+ {883, {wxControlWithItems, clear, 0}},
+ {884, {wxControlWithItems, delete, 1}},
+ {885, {wxControlWithItems, findString, 2}},
+ {886, {wxControlWithItems, getClientData, 1}},
+ {887, {wxControlWithItems, setClientData, 2}},
+ {888, {wxControlWithItems, getCount, 0}},
+ {889, {wxControlWithItems, getSelection, 0}},
+ {890, {wxControlWithItems, getString, 1}},
+ {891, {wxControlWithItems, getStringSelection, 0}},
+ {892, {wxControlWithItems, insert_2, 2}},
+ {893, {wxControlWithItems, insert_3, 3}},
+ {894, {wxControlWithItems, isEmpty, 0}},
+ {895, {wxControlWithItems, select, 1}},
+ {896, {wxControlWithItems, setSelection, 1}},
+ {897, {wxControlWithItems, setString, 2}},
+ {898, {wxControlWithItems, setStringSelection, 1}},
+ {901, {wxMenu, new_2, 2}},
+ {902, {wxMenu, new_1, 1}},
+ {904, {wxMenu, destruct, 0}},
+ {905, {wxMenu, append_3, 3}},
+ {906, {wxMenu, append_1, 1}},
+ {907, {wxMenu, append_4_0, 4}},
+ {908, {wxMenu, append_4_1, 4}},
+ {909, {wxMenu, appendCheckItem, 3}},
+ {910, {wxMenu, appendRadioItem, 3}},
+ {911, {wxMenu, appendSeparator, 0}},
+ {912, {wxMenu, break, 0}},
+ {913, {wxMenu, check, 2}},
+ {914, {wxMenu, delete_1_0, 1}},
+ {915, {wxMenu, delete_1_1, 1}},
+ {916, {wxMenu, destroy_1_0, 1}},
+ {917, {wxMenu, destroy_1_1, 1}},
+ {918, {wxMenu, enable, 2}},
+ {919, {wxMenu, findItem_1, 1}},
+ {920, {wxMenu, findItem_2, 2}},
+ {921, {wxMenu, findItemByPosition, 1}},
+ {922, {wxMenu, getHelpString, 1}},
+ {923, {wxMenu, getLabel, 1}},
+ {924, {wxMenu, getMenuItemCount, 0}},
+ {925, {wxMenu, getMenuItems, 0}},
+ {927, {wxMenu, getTitle, 0}},
+ {928, {wxMenu, insert_2, 2}},
+ {929, {wxMenu, insert_3, 3}},
+ {930, {wxMenu, insert_5_1, 5}},
+ {931, {wxMenu, insert_5_0, 5}},
+ {932, {wxMenu, insertCheckItem, 4}},
+ {933, {wxMenu, insertRadioItem, 4}},
+ {934, {wxMenu, insertSeparator, 1}},
+ {935, {wxMenu, isChecked, 1}},
+ {936, {wxMenu, isEnabled, 1}},
+ {937, {wxMenu, prepend_1, 1}},
+ {938, {wxMenu, prepend_2, 2}},
+ {939, {wxMenu, prepend_4_1, 4}},
+ {940, {wxMenu, prepend_4_0, 4}},
+ {941, {wxMenu, prependCheckItem, 3}},
+ {942, {wxMenu, prependRadioItem, 3}},
+ {943, {wxMenu, prependSeparator, 0}},
+ {944, {wxMenu, remove_1_0, 1}},
+ {945, {wxMenu, remove_1_1, 1}},
+ {946, {wxMenu, setHelpString, 2}},
+ {947, {wxMenu, setLabel, 2}},
+ {948, {wxMenu, setTitle, 1}},
+ {949, {wxMenuItem, new, 1}},
+ {951, {wxMenuItem, destruct, 0}},
+ {952, {wxMenuItem, check, 1}},
+ {953, {wxMenuItem, enable, 1}},
+ {954, {wxMenuItem, getBitmap, 0}},
+ {955, {wxMenuItem, getHelp, 0}},
+ {956, {wxMenuItem, getId, 0}},
+ {957, {wxMenuItem, getKind, 0}},
+ {958, {wxMenuItem, getLabel, 0}},
+ {959, {wxMenuItem, getLabelFromText, 1}},
+ {960, {wxMenuItem, getMenu, 0}},
+ {961, {wxMenuItem, getText, 0}},
+ {962, {wxMenuItem, getSubMenu, 0}},
+ {963, {wxMenuItem, isCheckable, 0}},
+ {964, {wxMenuItem, isChecked, 0}},
+ {965, {wxMenuItem, isEnabled, 0}},
+ {966, {wxMenuItem, isSeparator, 0}},
+ {967, {wxMenuItem, isSubMenu, 0}},
+ {968, {wxMenuItem, setBitmap, 1}},
+ {969, {wxMenuItem, setHelp, 1}},
+ {970, {wxMenuItem, setMenu, 1}},
+ {971, {wxMenuItem, setSubMenu, 1}},
+ {972, {wxMenuItem, setText, 1}},
+ {973, {wxToolBar, addControl, 1}},
+ {974, {wxToolBar, addSeparator, 0}},
+ {975, {wxToolBar, addTool_5, 5}},
+ {976, {wxToolBar, addTool_4_0, 4}},
+ {977, {wxToolBar, addTool_1, 1}},
+ {978, {wxToolBar, addTool_4_1, 4}},
+ {979, {wxToolBar, addTool_3, 3}},
+ {980, {wxToolBar, addTool_6, 6}},
+ {981, {wxToolBar, addCheckTool, 4}},
+ {982, {wxToolBar, addRadioTool, 4}},
+ {983, {wxToolBar, deleteTool, 1}},
+ {984, {wxToolBar, deleteToolByPos, 1}},
+ {985, {wxToolBar, enableTool, 2}},
+ {986, {wxToolBar, findById, 1}},
+ {987, {wxToolBar, findControl, 1}},
+ {988, {wxToolBar, findToolForPosition, 2}},
+ {989, {wxToolBar, getToolSize, 0}},
+ {990, {wxToolBar, getToolBitmapSize, 0}},
+ {991, {wxToolBar, getMargins, 0}},
+ {992, {wxToolBar, getToolEnabled, 1}},
+ {993, {wxToolBar, getToolLongHelp, 1}},
+ {994, {wxToolBar, getToolPacking, 0}},
+ {995, {wxToolBar, getToolPos, 1}},
+ {996, {wxToolBar, getToolSeparation, 0}},
+ {997, {wxToolBar, getToolShortHelp, 1}},
+ {998, {wxToolBar, getToolState, 1}},
+ {999, {wxToolBar, insertControl, 2}},
+ {1000, {wxToolBar, insertSeparator, 1}},
+ {1001, {wxToolBar, insertTool_5, 5}},
+ {1002, {wxToolBar, insertTool_2, 2}},
+ {1003, {wxToolBar, insertTool_4, 4}},
+ {1004, {wxToolBar, realize, 0}},
+ {1005, {wxToolBar, removeTool, 1}},
+ {1006, {wxToolBar, setMargins, 2}},
+ {1007, {wxToolBar, setToolBitmapSize, 1}},
+ {1008, {wxToolBar, setToolLongHelp, 2}},
+ {1009, {wxToolBar, setToolPacking, 1}},
+ {1010, {wxToolBar, setToolShortHelp, 2}},
+ {1011, {wxToolBar, setToolSeparation, 1}},
+ {1012, {wxToolBar, toggleTool, 2}},
+ {1014, {wxStatusBar, new_0, 0}},
+ {1015, {wxStatusBar, new_2, 2}},
+ {1017, {wxStatusBar, destruct, 0}},
+ {1018, {wxStatusBar, create, 2}},
+ {1019, {wxStatusBar, getFieldRect, 2}},
+ {1020, {wxStatusBar, getFieldsCount, 0}},
+ {1021, {wxStatusBar, getStatusText, 1}},
+ {1022, {wxStatusBar, popStatusText, 1}},
+ {1023, {wxStatusBar, pushStatusText, 2}},
+ {1024, {wxStatusBar, setFieldsCount, 2}},
+ {1025, {wxStatusBar, setMinHeight, 1}},
+ {1026, {wxStatusBar, setStatusText, 2}},
+ {1027, {wxStatusBar, setStatusWidths, 2}},
+ {1028, {wxStatusBar, setStatusStyles, 2}},
+ {1029, {wxBitmap, new_0, 0}},
+ {1030, {wxBitmap, new_3, 3}},
+ {1031, {wxBitmap, new_4, 4}},
+ {1032, {wxBitmap, new_2_0, 2}},
+ {1033, {wxBitmap, new_2_1, 2}},
+ {1034, {wxBitmap, destruct, 0}},
+ {1035, {wxBitmap, convertToImage, 0}},
+ {1036, {wxBitmap, copyFromIcon, 1}},
+ {1037, {wxBitmap, create, 3}},
+ {1038, {wxBitmap, getDepth, 0}},
+ {1039, {wxBitmap, getHeight, 0}},
+ {1040, {wxBitmap, getPalette, 0}},
+ {1041, {wxBitmap, getMask, 0}},
+ {1042, {wxBitmap, getWidth, 0}},
+ {1043, {wxBitmap, getSubBitmap, 1}},
+ {1044, {wxBitmap, loadFile, 2}},
+ {1045, {wxBitmap, ok, 0}},
+ {1046, {wxBitmap, saveFile, 3}},
+ {1047, {wxBitmap, setDepth, 1}},
+ {1048, {wxBitmap, setHeight, 1}},
+ {1049, {wxBitmap, setMask, 1}},
+ {1050, {wxBitmap, setPalette, 1}},
+ {1051, {wxBitmap, setWidth, 1}},
+ {1052, {wxIcon, new_0, 0}},
+ {1053, {wxIcon, new_2, 2}},
+ {1054, {wxIcon, new_1, 1}},
+ {1055, {wxIcon, copyFromBitmap, 1}},
+ {1056, {wxIcon, 'Destroy', undefined}},
+ {1057, {wxIconBundle, new_0, 0}},
+ {1058, {wxIconBundle, new_2, 2}},
+ {1059, {wxIconBundle, new_1_0, 1}},
+ {1060, {wxIconBundle, new_1_1, 1}},
+ {1061, {wxIconBundle, destruct, 0}},
+ {1062, {wxIconBundle, addIcon_2, 2}},
+ {1063, {wxIconBundle, addIcon_1, 1}},
+ {1064, {wxIconBundle, getIcon_1_1, 1}},
+ {1065, {wxIconBundle, getIcon_1_0, 1}},
+ {1066, {wxCursor, new_0, 0}},
+ {1067, {wxCursor, new_1_0, 1}},
+ {1068, {wxCursor, new_1_1, 1}},
+ {1069, {wxCursor, new_4, 4}},
+ {1070, {wxCursor, destruct, 0}},
+ {1071, {wxCursor, ok, 0}},
+ {1072, {wxMask, new_0, 0}},
+ {1073, {wxMask, new_2_1, 2}},
+ {1074, {wxMask, new_2_0, 2}},
+ {1075, {wxMask, new_1, 1}},
+ {1076, {wxMask, destruct, 0}},
+ {1077, {wxMask, create_2_1, 2}},
+ {1078, {wxMask, create_2_0, 2}},
+ {1079, {wxMask, create_1, 1}},
+ {1080, {wxImage, new_0, 0}},
+ {1081, {wxImage, new_3_0, 3}},
+ {1082, {wxImage, new_4, 4}},
+ {1083, {wxImage, new_5, 5}},
+ {1084, {wxImage, new_2, 2}},
+ {1085, {wxImage, new_3_1, 3}},
+ {1086, {wxImage, blur, 1}},
+ {1087, {wxImage, blurHorizontal, 1}},
+ {1088, {wxImage, blurVertical, 1}},
+ {1089, {wxImage, convertAlphaToMask, 1}},
+ {1090, {wxImage, convertToGreyscale, 1}},
+ {1091, {wxImage, convertToMono, 3}},
+ {1092, {wxImage, copy, 0}},
+ {1093, {wxImage, create_3, 3}},
+ {1094, {wxImage, create_4, 4}},
+ {1095, {wxImage, create_5, 5}},
+ {1096, {wxImage, 'Destroy', 0}},
+ {1097, {wxImage, findFirstUnusedColour, 4}},
+ {1098, {wxImage, getImageExtWildcard, 0}},
+ {1099, {wxImage, getAlpha_2, 2}},
+ {1100, {wxImage, getAlpha_0, 0}},
+ {1101, {wxImage, getBlue, 2}},
+ {1102, {wxImage, getData, 0}},
+ {1103, {wxImage, getGreen, 2}},
+ {1104, {wxImage, getImageCount, 2}},
+ {1105, {wxImage, getHeight, 0}},
+ {1106, {wxImage, getMaskBlue, 0}},
+ {1107, {wxImage, getMaskGreen, 0}},
+ {1108, {wxImage, getMaskRed, 0}},
+ {1109, {wxImage, getOrFindMaskColour, 3}},
+ {1110, {wxImage, getPalette, 0}},
+ {1111, {wxImage, getRed, 2}},
+ {1112, {wxImage, getSubImage, 1}},
+ {1113, {wxImage, getWidth, 0}},
+ {1114, {wxImage, hasAlpha, 0}},
+ {1115, {wxImage, hasMask, 0}},
+ {1116, {wxImage, getOption, 1}},
+ {1117, {wxImage, getOptionInt, 1}},
+ {1118, {wxImage, hasOption, 1}},
+ {1119, {wxImage, initAlpha, 0}},
+ {1120, {wxImage, initStandardHandlers, 0}},
+ {1121, {wxImage, isTransparent, 3}},
+ {1122, {wxImage, loadFile_2, 2}},
+ {1123, {wxImage, loadFile_3, 3}},
+ {1124, {wxImage, ok, 0}},
+ {1125, {wxImage, removeHandler, 1}},
+ {1126, {wxImage, mirror, 1}},
+ {1127, {wxImage, replace, 6}},
+ {1128, {wxImage, rescale, 3}},
+ {1129, {wxImage, resize, 3}},
+ {1130, {wxImage, rotate, 3}},
+ {1131, {wxImage, rotateHue, 1}},
+ {1132, {wxImage, rotate90, 1}},
+ {1133, {wxImage, saveFile_1, 1}},
+ {1134, {wxImage, saveFile_2_0, 2}},
+ {1135, {wxImage, saveFile_2_1, 2}},
+ {1136, {wxImage, scale, 3}},
+ {1137, {wxImage, size, 3}},
+ {1138, {wxImage, setAlpha_3, 3}},
+ {1139, {wxImage, setAlpha_2, 2}},
+ {1140, {wxImage, setData_2, 2}},
+ {1141, {wxImage, setData_4, 4}},
+ {1142, {wxImage, setMask, 1}},
+ {1143, {wxImage, setMaskColour, 3}},
+ {1144, {wxImage, setMaskFromImage, 4}},
+ {1145, {wxImage, setOption_2_1, 2}},
+ {1146, {wxImage, setOption_2_0, 2}},
+ {1147, {wxImage, setPalette, 1}},
+ {1148, {wxImage, setRGB_5, 5}},
+ {1149, {wxImage, setRGB_4, 4}},
+ {1150, {wxImage, 'Destroy', undefined}},
+ {1151, {wxBrush, new_0, 0}},
+ {1152, {wxBrush, new_2, 2}},
+ {1153, {wxBrush, new_1, 1}},
+ {1155, {wxBrush, destruct, 0}},
+ {1156, {wxBrush, getColour, 0}},
+ {1157, {wxBrush, getStipple, 0}},
+ {1158, {wxBrush, getStyle, 0}},
+ {1159, {wxBrush, isHatch, 0}},
+ {1160, {wxBrush, isOk, 0}},
+ {1161, {wxBrush, setColour_1, 1}},
+ {1162, {wxBrush, setColour_3, 3}},
+ {1163, {wxBrush, setStipple, 1}},
+ {1164, {wxBrush, setStyle, 1}},
+ {1165, {wxPen, new_0, 0}},
+ {1166, {wxPen, new_2, 2}},
+ {1167, {wxPen, destruct, 0}},
+ {1168, {wxPen, getCap, 0}},
+ {1169, {wxPen, getColour, 0}},
+ {1170, {wxPen, getJoin, 0}},
+ {1171, {wxPen, getStyle, 0}},
+ {1172, {wxPen, getWidth, 0}},
+ {1173, {wxPen, isOk, 0}},
+ {1174, {wxPen, setCap, 1}},
+ {1175, {wxPen, setColour_1, 1}},
+ {1176, {wxPen, setColour_3, 3}},
+ {1177, {wxPen, setJoin, 1}},
+ {1178, {wxPen, setStyle, 1}},
+ {1179, {wxPen, setWidth, 1}},
+ {1180, {wxRegion, new_0, 0}},
+ {1181, {wxRegion, new_4, 4}},
+ {1182, {wxRegion, new_2, 2}},
+ {1183, {wxRegion, new_1_1, 1}},
+ {1185, {wxRegion, new_1_0, 1}},
+ {1187, {wxRegion, destruct, 0}},
+ {1188, {wxRegion, clear, 0}},
+ {1189, {wxRegion, contains_2, 2}},
+ {1190, {wxRegion, contains_1_0, 1}},
+ {1191, {wxRegion, contains_4, 4}},
+ {1192, {wxRegion, contains_1_1, 1}},
+ {1193, {wxRegion, convertToBitmap, 0}},
+ {1194, {wxRegion, getBox, 0}},
+ {1195, {wxRegion, intersect_4, 4}},
+ {1196, {wxRegion, intersect_1_1, 1}},
+ {1197, {wxRegion, intersect_1_0, 1}},
+ {1198, {wxRegion, isEmpty, 0}},
+ {1199, {wxRegion, subtract_4, 4}},
+ {1200, {wxRegion, subtract_1_1, 1}},
+ {1201, {wxRegion, subtract_1_0, 1}},
+ {1202, {wxRegion, offset_2, 2}},
+ {1203, {wxRegion, offset_1, 1}},
+ {1204, {wxRegion, union_4, 4}},
+ {1205, {wxRegion, union_1_2, 1}},
+ {1206, {wxRegion, union_1_1, 1}},
+ {1207, {wxRegion, union_1_0, 1}},
+ {1208, {wxRegion, union_3, 3}},
+ {1209, {wxRegion, xor_4, 4}},
+ {1210, {wxRegion, xor_1_1, 1}},
+ {1211, {wxRegion, xor_1_0, 1}},
+ {1212, {wxAcceleratorTable, new_0, 0}},
+ {1213, {wxAcceleratorTable, new_2, 2}},
+ {1214, {wxAcceleratorTable, destruct, 0}},
+ {1215, {wxAcceleratorTable, ok, 0}},
+ {1216, {wxAcceleratorEntry, new_1_0, 1}},
+ {1217, {wxAcceleratorEntry, new_1_1, 1}},
+ {1218, {wxAcceleratorEntry, getCommand, 0}},
+ {1219, {wxAcceleratorEntry, getFlags, 0}},
+ {1220, {wxAcceleratorEntry, getKeyCode, 0}},
+ {1221, {wxAcceleratorEntry, set, 4}},
+ {1222, {wxAcceleratorEntry, 'Destroy', undefined}},
+ {1227, {wxCaret, new_3, 3}},
+ {1228, {wxCaret, new_2, 2}},
+ {1230, {wxCaret, destruct, 0}},
+ {1231, {wxCaret, create_3, 3}},
+ {1232, {wxCaret, create_2, 2}},
+ {1233, {wxCaret, getBlinkTime, 0}},
+ {1235, {wxCaret, getPosition, 0}},
+ {1237, {wxCaret, getSize, 0}},
+ {1238, {wxCaret, getWindow, 0}},
+ {1239, {wxCaret, hide, 0}},
+ {1240, {wxCaret, isOk, 0}},
+ {1241, {wxCaret, isVisible, 0}},
+ {1242, {wxCaret, move_2, 2}},
+ {1243, {wxCaret, move_1, 1}},
+ {1244, {wxCaret, setBlinkTime, 1}},
+ {1245, {wxCaret, setSize_2, 2}},
+ {1246, {wxCaret, setSize_1, 1}},
+ {1247, {wxCaret, show, 1}},
+ {1248, {wxSizer, add_2_1, 2}},
+ {1249, {wxSizer, add_2_0, 2}},
+ {1250, {wxSizer, add_3, 3}},
+ {1251, {wxSizer, add_2_3, 2}},
+ {1252, {wxSizer, add_2_2, 2}},
+ {1253, {wxSizer, addSpacer, 1}},
+ {1254, {wxSizer, addStretchSpacer, 1}},
+ {1255, {wxSizer, calcMin, 0}},
+ {1256, {wxSizer, clear, 1}},
+ {1257, {wxSizer, detach_1_2, 1}},
+ {1258, {wxSizer, detach_1_1, 1}},
+ {1259, {wxSizer, detach_1_0, 1}},
+ {1260, {wxSizer, fit, 1}},
+ {1261, {wxSizer, fitInside, 1}},
+ {1262, {wxSizer, getChildren, 0}},
+ {1263, {wxSizer, getItem_2_1, 2}},
+ {1264, {wxSizer, getItem_2_0, 2}},
+ {1265, {wxSizer, getItem_1, 1}},
+ {1266, {wxSizer, getSize, 0}},
+ {1267, {wxSizer, getPosition, 0}},
+ {1268, {wxSizer, getMinSize, 0}},
+ {1269, {wxSizer, hide_2_0, 2}},
+ {1270, {wxSizer, hide_2_1, 2}},
+ {1271, {wxSizer, hide_1, 1}},
+ {1272, {wxSizer, insert_3_1, 3}},
+ {1273, {wxSizer, insert_3_0, 3}},
+ {1274, {wxSizer, insert_4, 4}},
+ {1275, {wxSizer, insert_3_3, 3}},
+ {1276, {wxSizer, insert_3_2, 3}},
+ {1277, {wxSizer, insert_2, 2}},
+ {1278, {wxSizer, insertSpacer, 2}},
+ {1279, {wxSizer, insertStretchSpacer, 2}},
+ {1280, {wxSizer, isShown_1_2, 1}},
+ {1281, {wxSizer, isShown_1_1, 1}},
+ {1282, {wxSizer, isShown_1_0, 1}},
+ {1283, {wxSizer, layout, 0}},
+ {1284, {wxSizer, prepend_2_1, 2}},
+ {1285, {wxSizer, prepend_2_0, 2}},
+ {1286, {wxSizer, prepend_3, 3}},
+ {1287, {wxSizer, prepend_2_3, 2}},
+ {1288, {wxSizer, prepend_2_2, 2}},
+ {1289, {wxSizer, prepend_1, 1}},
+ {1290, {wxSizer, prependSpacer, 1}},
+ {1291, {wxSizer, prependStretchSpacer, 1}},
+ {1292, {wxSizer, recalcSizes, 0}},
+ {1293, {wxSizer, remove_1_1, 1}},
+ {1294, {wxSizer, remove_1_0, 1}},
+ {1295, {wxSizer, replace_3_1, 3}},
+ {1296, {wxSizer, replace_3_0, 3}},
+ {1297, {wxSizer, replace_2, 2}},
+ {1298, {wxSizer, setDimension, 4}},
+ {1299, {wxSizer, setMinSize_2, 2}},
+ {1300, {wxSizer, setMinSize_1, 1}},
+ {1301, {wxSizer, setItemMinSize_3_2, 3}},
+ {1302, {wxSizer, setItemMinSize_2_2, 2}},
+ {1303, {wxSizer, setItemMinSize_3_1, 3}},
+ {1304, {wxSizer, setItemMinSize_2_1, 2}},
+ {1305, {wxSizer, setItemMinSize_3_0, 3}},
+ {1306, {wxSizer, setItemMinSize_2_0, 2}},
+ {1307, {wxSizer, setSizeHints, 1}},
+ {1308, {wxSizer, setVirtualSizeHints, 1}},
+ {1309, {wxSizer, show_2_2, 2}},
+ {1310, {wxSizer, show_2_1, 2}},
+ {1311, {wxSizer, show_2_0, 2}},
+ {1312, {wxSizer, show_1, 1}},
+ {1313, {wxSizerFlags, new, 1}},
+ {1314, {wxSizerFlags, align, 1}},
+ {1315, {wxSizerFlags, border_2, 2}},
+ {1316, {wxSizerFlags, border_1, 1}},
+ {1317, {wxSizerFlags, center, 0}},
+ {1318, {wxSizerFlags, centre, 0}},
+ {1319, {wxSizerFlags, expand, 0}},
+ {1320, {wxSizerFlags, left, 0}},
+ {1321, {wxSizerFlags, proportion, 1}},
+ {1322, {wxSizerFlags, right, 0}},
+ {1323, {wxSizerFlags, 'Destroy', undefined}},
+ {1324, {wxSizerItem, new_5_1, 5}},
+ {1325, {wxSizerItem, new_2_1, 2}},
+ {1326, {wxSizerItem, new_5_0, 5}},
+ {1327, {wxSizerItem, new_2_0, 2}},
+ {1328, {wxSizerItem, new_6, 6}},
+ {1329, {wxSizerItem, new_3, 3}},
+ {1330, {wxSizerItem, new_0, 0}},
+ {1331, {wxSizerItem, destruct, 0}},
+ {1332, {wxSizerItem, calcMin, 0}},
+ {1333, {wxSizerItem, deleteWindows, 0}},
+ {1334, {wxSizerItem, detachSizer, 0}},
+ {1335, {wxSizerItem, getBorder, 0}},
+ {1336, {wxSizerItem, getFlag, 0}},
+ {1337, {wxSizerItem, getMinSize, 0}},
+ {1338, {wxSizerItem, getPosition, 0}},
+ {1339, {wxSizerItem, getProportion, 0}},
+ {1340, {wxSizerItem, getRatio, 0}},
+ {1341, {wxSizerItem, getRect, 0}},
+ {1342, {wxSizerItem, getSize, 0}},
+ {1343, {wxSizerItem, getSizer, 0}},
+ {1344, {wxSizerItem, getSpacer, 0}},
+ {1345, {wxSizerItem, getUserData, 0}},
+ {1346, {wxSizerItem, getWindow, 0}},
+ {1347, {wxSizerItem, isSizer, 0}},
+ {1348, {wxSizerItem, isShown, 0}},
+ {1349, {wxSizerItem, isSpacer, 0}},
+ {1350, {wxSizerItem, isWindow, 0}},
+ {1351, {wxSizerItem, setBorder, 1}},
+ {1352, {wxSizerItem, setDimension, 2}},
+ {1353, {wxSizerItem, setFlag, 1}},
+ {1354, {wxSizerItem, setInitSize, 2}},
+ {1355, {wxSizerItem, setMinSize_1, 1}},
+ {1356, {wxSizerItem, setMinSize_2, 2}},
+ {1357, {wxSizerItem, setProportion, 1}},
+ {1358, {wxSizerItem, setRatio_2, 2}},
+ {1359, {wxSizerItem, setRatio_1_1, 1}},
+ {1360, {wxSizerItem, setRatio_1_0, 1}},
+ {1361, {wxSizerItem, setSizer, 1}},
+ {1362, {wxSizerItem, setSpacer_1, 1}},
+ {1363, {wxSizerItem, setSpacer_2, 2}},
+ {1364, {wxSizerItem, setWindow, 1}},
+ {1365, {wxSizerItem, show, 1}},
+ {1366, {wxBoxSizer, new, 1}},
+ {1367, {wxBoxSizer, getOrientation, 0}},
+ {1368, {wxBoxSizer, 'Destroy', undefined}},
+ {1369, {wxStaticBoxSizer, new_2, 2}},
+ {1370, {wxStaticBoxSizer, new_3, 3}},
+ {1371, {wxStaticBoxSizer, getStaticBox, 0}},
+ {1372, {wxStaticBoxSizer, 'Destroy', undefined}},
+ {1373, {wxGridSizer, new_4, 4}},
+ {1374, {wxGridSizer, new_2, 2}},
+ {1375, {wxGridSizer, getCols, 0}},
+ {1376, {wxGridSizer, getHGap, 0}},
+ {1377, {wxGridSizer, getRows, 0}},
+ {1378, {wxGridSizer, getVGap, 0}},
+ {1379, {wxGridSizer, setCols, 1}},
+ {1380, {wxGridSizer, setHGap, 1}},
+ {1381, {wxGridSizer, setRows, 1}},
+ {1382, {wxGridSizer, setVGap, 1}},
+ {1383, {wxGridSizer, 'Destroy', undefined}},
+ {1384, {wxFlexGridSizer, new_4, 4}},
+ {1385, {wxFlexGridSizer, new_2, 2}},
+ {1386, {wxFlexGridSizer, addGrowableCol, 2}},
+ {1387, {wxFlexGridSizer, addGrowableRow, 2}},
+ {1388, {wxFlexGridSizer, getFlexibleDirection, 0}},
+ {1389, {wxFlexGridSizer, getNonFlexibleGrowMode, 0}},
+ {1390, {wxFlexGridSizer, removeGrowableCol, 1}},
+ {1391, {wxFlexGridSizer, removeGrowableRow, 1}},
+ {1392, {wxFlexGridSizer, setFlexibleDirection, 1}},
+ {1393, {wxFlexGridSizer, setNonFlexibleGrowMode, 1}},
+ {1394, {wxFlexGridSizer, 'Destroy', undefined}},
+ {1395, {wxGridBagSizer, new, 1}},
+ {1396, {wxGridBagSizer, add_3_2, 3}},
+ {1397, {wxGridBagSizer, add_3_1, 3}},
+ {1398, {wxGridBagSizer, add_4, 4}},
+ {1399, {wxGridBagSizer, add_1_0, 1}},
+ {1400, {wxGridBagSizer, add_2_1, 2}},
+ {1401, {wxGridBagSizer, add_2_0, 2}},
+ {1402, {wxGridBagSizer, add_3_0, 3}},
+ {1403, {wxGridBagSizer, add_1_1, 1}},
+ {1404, {wxGridBagSizer, calcMin, 0}},
+ {1405, {wxGridBagSizer, checkForIntersection_2, 2}},
+ {1406, {wxGridBagSizer, checkForIntersection_3, 3}},
+ {1407, {wxGridBagSizer, findItem_1_1, 1}},
+ {1408, {wxGridBagSizer, findItem_1_0, 1}},
+ {1409, {wxGridBagSizer, findItemAtPoint, 1}},
+ {1410, {wxGridBagSizer, findItemAtPosition, 1}},
+ {1411, {wxGridBagSizer, findItemWithData, 1}},
+ {1412, {wxGridBagSizer, getCellSize, 2}},
+ {1413, {wxGridBagSizer, getEmptyCellSize, 0}},
+ {1414, {wxGridBagSizer, getItemPosition_1_2, 1}},
+ {1415, {wxGridBagSizer, getItemPosition_1_1, 1}},
+ {1416, {wxGridBagSizer, getItemPosition_1_0, 1}},
+ {1417, {wxGridBagSizer, getItemSpan_1_2, 1}},
+ {1418, {wxGridBagSizer, getItemSpan_1_1, 1}},
+ {1419, {wxGridBagSizer, getItemSpan_1_0, 1}},
+ {1420, {wxGridBagSizer, setEmptyCellSize, 1}},
+ {1421, {wxGridBagSizer, setItemPosition_2_2, 2}},
+ {1422, {wxGridBagSizer, setItemPosition_2_1, 2}},
+ {1423, {wxGridBagSizer, setItemPosition_2_0, 2}},
+ {1424, {wxGridBagSizer, setItemSpan_2_2, 2}},
+ {1425, {wxGridBagSizer, setItemSpan_2_1, 2}},
+ {1426, {wxGridBagSizer, setItemSpan_2_0, 2}},
+ {1427, {wxGridBagSizer, 'Destroy', undefined}},
+ {1428, {wxStdDialogButtonSizer, new, 0}},
+ {1429, {wxStdDialogButtonSizer, addButton, 1}},
+ {1430, {wxStdDialogButtonSizer, realize, 0}},
+ {1431, {wxStdDialogButtonSizer, setAffirmativeButton, 1}},
+ {1432, {wxStdDialogButtonSizer, setCancelButton, 1}},
+ {1433, {wxStdDialogButtonSizer, setNegativeButton, 1}},
+ {1434, {wxStdDialogButtonSizer, 'Destroy', undefined}},
+ {1435, {wxFont, new_0, 0}},
+ {1436, {wxFont, new_1, 1}},
+ {1437, {wxFont, new_5, 5}},
+ {1439, {wxFont, destruct, 0}},
+ {1440, {wxFont, isFixedWidth, 0}},
+ {1441, {wxFont, getDefaultEncoding, 0}},
+ {1442, {wxFont, getFaceName, 0}},
+ {1443, {wxFont, getFamily, 0}},
+ {1444, {wxFont, getNativeFontInfoDesc, 0}},
+ {1445, {wxFont, getNativeFontInfoUserDesc, 0}},
+ {1446, {wxFont, getPointSize, 0}},
+ {1447, {wxFont, getStyle, 0}},
+ {1448, {wxFont, getUnderlined, 0}},
+ {1449, {wxFont, getWeight, 0}},
+ {1450, {wxFont, ok, 0}},
+ {1451, {wxFont, setDefaultEncoding, 1}},
+ {1452, {wxFont, setFaceName, 1}},
+ {1453, {wxFont, setFamily, 1}},
+ {1454, {wxFont, setPointSize, 1}},
+ {1455, {wxFont, setStyle, 1}},
+ {1456, {wxFont, setUnderlined, 1}},
+ {1457, {wxFont, setWeight, 1}},
+ {1458, {wxToolTip, enable, 1}},
+ {1459, {wxToolTip, setDelay, 1}},
+ {1460, {wxToolTip, new, 1}},
+ {1461, {wxToolTip, setTip, 1}},
+ {1462, {wxToolTip, getTip, 0}},
+ {1463, {wxToolTip, getWindow, 0}},
+ {1464, {wxToolTip, 'Destroy', undefined}},
+ {1466, {wxButton, new_3, 3}},
+ {1467, {wxButton, new_0, 0}},
+ {1468, {wxButton, destruct, 0}},
+ {1469, {wxButton, create, 3}},
+ {1470, {wxButton, getDefaultSize, 0}},
+ {1471, {wxButton, setDefault, 0}},
+ {1472, {wxButton, setLabel, 1}},
+ {1474, {wxBitmapButton, new_4, 4}},
+ {1475, {wxBitmapButton, new_0, 0}},
+ {1476, {wxBitmapButton, create, 4}},
+ {1477, {wxBitmapButton, getBitmapDisabled, 0}},
+ {1479, {wxBitmapButton, getBitmapFocus, 0}},
+ {1481, {wxBitmapButton, getBitmapLabel, 0}},
+ {1483, {wxBitmapButton, getBitmapSelected, 0}},
+ {1485, {wxBitmapButton, setBitmapDisabled, 1}},
+ {1486, {wxBitmapButton, setBitmapFocus, 1}},
+ {1487, {wxBitmapButton, setBitmapLabel, 1}},
+ {1488, {wxBitmapButton, setBitmapSelected, 1}},
+ {1489, {wxBitmapButton, 'Destroy', undefined}},
+ {1490, {wxToggleButton, new_0, 0}},
+ {1491, {wxToggleButton, new_4, 4}},
+ {1492, {wxToggleButton, create, 4}},
+ {1493, {wxToggleButton, getValue, 0}},
+ {1494, {wxToggleButton, setValue, 1}},
+ {1495, {wxToggleButton, 'Destroy', undefined}},
+ {1496, {wxCalendarCtrl, new_0, 0}},
+ {1497, {wxCalendarCtrl, new_3, 3}},
+ {1498, {wxCalendarCtrl, create, 3}},
+ {1499, {wxCalendarCtrl, destruct, 0}},
+ {1500, {wxCalendarCtrl, setDate, 1}},
+ {1501, {wxCalendarCtrl, getDate, 0}},
+ {1502, {wxCalendarCtrl, enableYearChange, 1}},
+ {1503, {wxCalendarCtrl, enableMonthChange, 1}},
+ {1504, {wxCalendarCtrl, enableHolidayDisplay, 1}},
+ {1505, {wxCalendarCtrl, setHeaderColours, 2}},
+ {1506, {wxCalendarCtrl, getHeaderColourFg, 0}},
+ {1507, {wxCalendarCtrl, getHeaderColourBg, 0}},
+ {1508, {wxCalendarCtrl, setHighlightColours, 2}},
+ {1509, {wxCalendarCtrl, getHighlightColourFg, 0}},
+ {1510, {wxCalendarCtrl, getHighlightColourBg, 0}},
+ {1511, {wxCalendarCtrl, setHolidayColours, 2}},
+ {1512, {wxCalendarCtrl, getHolidayColourFg, 0}},
+ {1513, {wxCalendarCtrl, getHolidayColourBg, 0}},
+ {1514, {wxCalendarCtrl, getAttr, 1}},
+ {1515, {wxCalendarCtrl, setAttr, 2}},
+ {1516, {wxCalendarCtrl, setHoliday, 1}},
+ {1517, {wxCalendarCtrl, resetAttr, 1}},
+ {1518, {wxCalendarCtrl, hitTest, 2}},
+ {1519, {wxCalendarDateAttr, new_0, 0}},
+ {1520, {wxCalendarDateAttr, new_2_1, 2}},
+ {1521, {wxCalendarDateAttr, new_2_0, 2}},
+ {1522, {wxCalendarDateAttr, setTextColour, 1}},
+ {1523, {wxCalendarDateAttr, setBackgroundColour, 1}},
+ {1524, {wxCalendarDateAttr, setBorderColour, 1}},
+ {1525, {wxCalendarDateAttr, setFont, 1}},
+ {1526, {wxCalendarDateAttr, setBorder, 1}},
+ {1527, {wxCalendarDateAttr, setHoliday, 1}},
+ {1528, {wxCalendarDateAttr, hasTextColour, 0}},
+ {1529, {wxCalendarDateAttr, hasBackgroundColour, 0}},
+ {1530, {wxCalendarDateAttr, hasBorderColour, 0}},
+ {1531, {wxCalendarDateAttr, hasFont, 0}},
+ {1532, {wxCalendarDateAttr, hasBorder, 0}},
+ {1533, {wxCalendarDateAttr, isHoliday, 0}},
+ {1534, {wxCalendarDateAttr, getTextColour, 0}},
+ {1535, {wxCalendarDateAttr, getBackgroundColour, 0}},
+ {1536, {wxCalendarDateAttr, getBorderColour, 0}},
+ {1537, {wxCalendarDateAttr, getFont, 0}},
+ {1538, {wxCalendarDateAttr, getBorder, 0}},
+ {1539, {wxCalendarDateAttr, 'Destroy', undefined}},
+ {1541, {wxCheckBox, new_4, 4}},
+ {1542, {wxCheckBox, new_0, 0}},
+ {1543, {wxCheckBox, create, 4}},
+ {1544, {wxCheckBox, getValue, 0}},
+ {1545, {wxCheckBox, get3StateValue, 0}},
+ {1546, {wxCheckBox, is3rdStateAllowedForUser, 0}},
+ {1547, {wxCheckBox, is3State, 0}},
+ {1548, {wxCheckBox, isChecked, 0}},
+ {1549, {wxCheckBox, setValue, 1}},
+ {1550, {wxCheckBox, set3StateValue, 1}},
+ {1551, {wxCheckBox, 'Destroy', undefined}},
+ {1552, {wxCheckListBox, new_0, 0}},
+ {1554, {wxCheckListBox, new_3, 3}},
+ {1555, {wxCheckListBox, check, 2}},
+ {1556, {wxCheckListBox, isChecked, 1}},
+ {1557, {wxCheckListBox, 'Destroy', undefined}},
+ {1560, {wxChoice, new_3, 3}},
+ {1561, {wxChoice, new_0, 0}},
+ {1563, {wxChoice, destruct, 0}},
+ {1565, {wxChoice, create, 6}},
+ {1566, {wxChoice, delete, 1}},
+ {1567, {wxChoice, getColumns, 0}},
+ {1568, {wxChoice, setColumns, 1}},
+ {1569, {wxComboBox, new_0, 0}},
+ {1571, {wxComboBox, new_3, 3}},
+ {1572, {wxComboBox, destruct, 0}},
+ {1574, {wxComboBox, create, 7}},
+ {1575, {wxComboBox, canCopy, 0}},
+ {1576, {wxComboBox, canCut, 0}},
+ {1577, {wxComboBox, canPaste, 0}},
+ {1578, {wxComboBox, canRedo, 0}},
+ {1579, {wxComboBox, canUndo, 0}},
+ {1580, {wxComboBox, copy, 0}},
+ {1581, {wxComboBox, cut, 0}},
+ {1582, {wxComboBox, getInsertionPoint, 0}},
+ {1583, {wxComboBox, getLastPosition, 0}},
+ {1584, {wxComboBox, getValue, 0}},
+ {1585, {wxComboBox, paste, 0}},
+ {1586, {wxComboBox, redo, 0}},
+ {1587, {wxComboBox, replace, 3}},
+ {1588, {wxComboBox, remove, 2}},
+ {1589, {wxComboBox, setInsertionPoint, 1}},
+ {1590, {wxComboBox, setInsertionPointEnd, 0}},
+ {1591, {wxComboBox, setSelection_1, 1}},
+ {1592, {wxComboBox, setSelection_2, 2}},
+ {1593, {wxComboBox, setValue, 1}},
+ {1594, {wxComboBox, undo, 0}},
+ {1595, {wxGauge, new_0, 0}},
+ {1596, {wxGauge, new_4, 4}},
+ {1597, {wxGauge, create, 4}},
+ {1598, {wxGauge, getBezelFace, 0}},
+ {1599, {wxGauge, getRange, 0}},
+ {1600, {wxGauge, getShadowWidth, 0}},
+ {1601, {wxGauge, getValue, 0}},
+ {1602, {wxGauge, isVertical, 0}},
+ {1603, {wxGauge, setBezelFace, 1}},
+ {1604, {wxGauge, setRange, 1}},
+ {1605, {wxGauge, setShadowWidth, 1}},
+ {1606, {wxGauge, setValue, 1}},
+ {1607, {wxGauge, pulse, 0}},
+ {1608, {wxGauge, 'Destroy', undefined}},
+ {1609, {wxGenericDirCtrl, new_0, 0}},
+ {1610, {wxGenericDirCtrl, new_2, 2}},
+ {1611, {wxGenericDirCtrl, destruct, 0}},
+ {1612, {wxGenericDirCtrl, create, 2}},
+ {1613, {wxGenericDirCtrl, init, 0}},
+ {1614, {wxGenericDirCtrl, collapseTree, 0}},
+ {1615, {wxGenericDirCtrl, expandPath, 1}},
+ {1616, {wxGenericDirCtrl, getDefaultPath, 0}},
+ {1617, {wxGenericDirCtrl, getPath, 0}},
+ {1618, {wxGenericDirCtrl, getFilePath, 0}},
+ {1619, {wxGenericDirCtrl, getFilter, 0}},
+ {1620, {wxGenericDirCtrl, getFilterIndex, 0}},
+ {1621, {wxGenericDirCtrl, getRootId, 0}},
+ {1622, {wxGenericDirCtrl, getTreeCtrl, 0}},
+ {1623, {wxGenericDirCtrl, reCreateTree, 0}},
+ {1624, {wxGenericDirCtrl, setDefaultPath, 1}},
+ {1625, {wxGenericDirCtrl, setFilter, 1}},
+ {1626, {wxGenericDirCtrl, setFilterIndex, 1}},
+ {1627, {wxGenericDirCtrl, setPath, 1}},
+ {1629, {wxStaticBox, new_4, 4}},
+ {1630, {wxStaticBox, new_0, 0}},
+ {1631, {wxStaticBox, create, 4}},
+ {1632, {wxStaticBox, 'Destroy', undefined}},
+ {1634, {wxStaticLine, new_2, 2}},
+ {1635, {wxStaticLine, new_0, 0}},
+ {1636, {wxStaticLine, create, 2}},
+ {1637, {wxStaticLine, isVertical, 0}},
+ {1638, {wxStaticLine, getDefaultSize, 0}},
+ {1639, {wxStaticLine, 'Destroy', undefined}},
+ {1642, {wxListBox, new_3, 3}},
+ {1643, {wxListBox, new_0, 0}},
+ {1645, {wxListBox, destruct, 0}},
+ {1647, {wxListBox, create, 6}},
+ {1648, {wxListBox, deselect, 1}},
+ {1649, {wxListBox, getSelections, 1}},
+ {1650, {wxListBox, insertItems, 2}},
+ {1651, {wxListBox, isSelected, 1}},
+ {1653, {wxListBox, set, 2}},
+ {1654, {wxListBox, hitTest, 1}},
+ {1655, {wxListBox, setFirstItem_1_0, 1}},
+ {1656, {wxListBox, setFirstItem_1_1, 1}},
+ {1657, {wxListCtrl, new_0, 0}},
+ {1658, {wxListCtrl, new_2, 2}},
+ {1659, {wxListCtrl, arrange, 1}},
+ {1660, {wxListCtrl, assignImageList, 2}},
+ {1661, {wxListCtrl, clearAll, 0}},
+ {1662, {wxListCtrl, create, 2}},
+ {1663, {wxListCtrl, deleteAllItems, 0}},
+ {1664, {wxListCtrl, deleteColumn, 1}},
+ {1665, {wxListCtrl, deleteItem, 1}},
+ {1666, {wxListCtrl, editLabel, 1}},
+ {1667, {wxListCtrl, ensureVisible, 1}},
+ {1668, {wxListCtrl, findItem_3_0, 3}},
+ {1669, {wxListCtrl, findItem_3_1, 3}},
+ {1670, {wxListCtrl, getColumn, 2}},
+ {1671, {wxListCtrl, getColumnCount, 0}},
+ {1672, {wxListCtrl, getColumnWidth, 1}},
+ {1673, {wxListCtrl, getCountPerPage, 0}},
+ {1674, {wxListCtrl, getEditControl, 0}},
+ {1675, {wxListCtrl, getImageList, 1}},
+ {1676, {wxListCtrl, getItem, 1}},
+ {1677, {wxListCtrl, getItemBackgroundColour, 1}},
+ {1678, {wxListCtrl, getItemCount, 0}},
+ {1679, {wxListCtrl, getItemData, 1}},
+ {1680, {wxListCtrl, getItemFont, 1}},
+ {1681, {wxListCtrl, getItemPosition, 2}},
+ {1682, {wxListCtrl, getItemRect, 3}},
+ {1683, {wxListCtrl, getItemSpacing, 0}},
+ {1684, {wxListCtrl, getItemState, 2}},
+ {1685, {wxListCtrl, getItemText, 1}},
+ {1686, {wxListCtrl, getItemTextColour, 1}},
+ {1687, {wxListCtrl, getNextItem, 2}},
+ {1688, {wxListCtrl, getSelectedItemCount, 0}},
+ {1689, {wxListCtrl, getTextColour, 0}},
+ {1690, {wxListCtrl, getTopItem, 0}},
+ {1691, {wxListCtrl, getViewRect, 0}},
+ {1692, {wxListCtrl, hitTest, 2}},
+ {1693, {wxListCtrl, insertColumn_2, 2}},
+ {1694, {wxListCtrl, insertColumn_3, 3}},
+ {1695, {wxListCtrl, insertItem_1, 1}},
+ {1696, {wxListCtrl, insertItem_2_1, 2}},
+ {1697, {wxListCtrl, insertItem_2_0, 2}},
+ {1698, {wxListCtrl, insertItem_3, 3}},
+ {1699, {wxListCtrl, refreshItem, 1}},
+ {1700, {wxListCtrl, refreshItems, 2}},
+ {1701, {wxListCtrl, scrollList, 2}},
+ {1702, {wxListCtrl, setBackgroundColour, 1}},
+ {1703, {wxListCtrl, setColumn, 2}},
+ {1704, {wxListCtrl, setColumnWidth, 2}},
+ {1705, {wxListCtrl, setImageList, 2}},
+ {1706, {wxListCtrl, setItem_1, 1}},
+ {1707, {wxListCtrl, setItem_4, 4}},
+ {1708, {wxListCtrl, setItemBackgroundColour, 2}},
+ {1709, {wxListCtrl, setItemCount, 1}},
+ {1710, {wxListCtrl, setItemData, 2}},
+ {1711, {wxListCtrl, setItemFont, 2}},
+ {1712, {wxListCtrl, setItemImage, 3}},
+ {1713, {wxListCtrl, setItemColumnImage, 3}},
+ {1714, {wxListCtrl, setItemPosition, 2}},
+ {1715, {wxListCtrl, setItemState, 3}},
+ {1716, {wxListCtrl, setItemText, 2}},
+ {1717, {wxListCtrl, setItemTextColour, 2}},
+ {1718, {wxListCtrl, setSingleStyle, 2}},
+ {1719, {wxListCtrl, setTextColour, 1}},
+ {1720, {wxListCtrl, setWindowStyleFlag, 1}},
+ {1721, {wxListCtrl, sortItems, 2}},
+ {1722, {wxListCtrl, 'Destroy', undefined}},
+ {1723, {wxListView, clearColumnImage, 1}},
+ {1724, {wxListView, focus, 1}},
+ {1725, {wxListView, getFirstSelected, 0}},
+ {1726, {wxListView, getFocusedItem, 0}},
+ {1727, {wxListView, getNextSelected, 1}},
+ {1728, {wxListView, isSelected, 1}},
+ {1729, {wxListView, select, 2}},
+ {1730, {wxListView, setColumnImage, 2}},
+ {1731, {wxListItem, new_0, 0}},
+ {1732, {wxListItem, new_1, 1}},
+ {1733, {wxListItem, destruct, 0}},
+ {1734, {wxListItem, clear, 0}},
+ {1735, {wxListItem, getAlign, 0}},
+ {1736, {wxListItem, getBackgroundColour, 0}},
+ {1737, {wxListItem, getColumn, 0}},
+ {1738, {wxListItem, getFont, 0}},
+ {1739, {wxListItem, getId, 0}},
+ {1740, {wxListItem, getImage, 0}},
+ {1741, {wxListItem, getMask, 0}},
+ {1742, {wxListItem, getState, 0}},
+ {1743, {wxListItem, getText, 0}},
+ {1744, {wxListItem, getTextColour, 0}},
+ {1745, {wxListItem, getWidth, 0}},
+ {1746, {wxListItem, setAlign, 1}},
+ {1747, {wxListItem, setBackgroundColour, 1}},
+ {1748, {wxListItem, setColumn, 1}},
+ {1749, {wxListItem, setFont, 1}},
+ {1750, {wxListItem, setId, 1}},
+ {1751, {wxListItem, setImage, 1}},
+ {1752, {wxListItem, setMask, 1}},
+ {1753, {wxListItem, setState, 1}},
+ {1754, {wxListItem, setStateMask, 1}},
+ {1755, {wxListItem, setText, 1}},
+ {1756, {wxListItem, setTextColour, 1}},
+ {1757, {wxListItem, setWidth, 1}},
+ {1758, {wxListItemAttr, new_0, 0}},
+ {1759, {wxListItemAttr, new_3, 3}},
+ {1760, {wxListItemAttr, getBackgroundColour, 0}},
+ {1761, {wxListItemAttr, getFont, 0}},
+ {1762, {wxListItemAttr, getTextColour, 0}},
+ {1763, {wxListItemAttr, hasBackgroundColour, 0}},
+ {1764, {wxListItemAttr, hasFont, 0}},
+ {1765, {wxListItemAttr, hasTextColour, 0}},
+ {1766, {wxListItemAttr, setBackgroundColour, 1}},
+ {1767, {wxListItemAttr, setFont, 1}},
+ {1768, {wxListItemAttr, setTextColour, 1}},
+ {1769, {wxListItemAttr, 'Destroy', undefined}},
+ {1770, {wxImageList, new_0, 0}},
+ {1771, {wxImageList, new_3, 3}},
+ {1772, {wxImageList, add_1, 1}},
+ {1773, {wxImageList, add_2_0, 2}},
+ {1774, {wxImageList, add_2_1, 2}},
+ {1775, {wxImageList, create, 3}},
+ {1777, {wxImageList, draw, 5}},
+ {1778, {wxImageList, getBitmap, 1}},
+ {1779, {wxImageList, getIcon, 1}},
+ {1780, {wxImageList, getImageCount, 0}},
+ {1781, {wxImageList, getSize, 3}},
+ {1782, {wxImageList, remove, 1}},
+ {1783, {wxImageList, removeAll, 0}},
+ {1784, {wxImageList, replace_2, 2}},
+ {1785, {wxImageList, replace_3, 3}},
+ {1786, {wxImageList, 'Destroy', undefined}},
+ {1787, {wxTextAttr, new_0, 0}},
+ {1788, {wxTextAttr, new_2, 2}},
+ {1789, {wxTextAttr, getAlignment, 0}},
+ {1790, {wxTextAttr, getBackgroundColour, 0}},
+ {1791, {wxTextAttr, getFont, 0}},
+ {1792, {wxTextAttr, getLeftIndent, 0}},
+ {1793, {wxTextAttr, getLeftSubIndent, 0}},
+ {1794, {wxTextAttr, getRightIndent, 0}},
+ {1795, {wxTextAttr, getTabs, 0}},
+ {1796, {wxTextAttr, getTextColour, 0}},
+ {1797, {wxTextAttr, hasBackgroundColour, 0}},
+ {1798, {wxTextAttr, hasFont, 0}},
+ {1799, {wxTextAttr, hasTextColour, 0}},
+ {1800, {wxTextAttr, getFlags, 0}},
+ {1801, {wxTextAttr, isDefault, 0}},
+ {1802, {wxTextAttr, setAlignment, 1}},
+ {1803, {wxTextAttr, setBackgroundColour, 1}},
+ {1804, {wxTextAttr, setFlags, 1}},
+ {1805, {wxTextAttr, setFont, 2}},
+ {1806, {wxTextAttr, setLeftIndent, 2}},
+ {1807, {wxTextAttr, setRightIndent, 1}},
+ {1808, {wxTextAttr, setTabs, 1}},
+ {1809, {wxTextAttr, setTextColour, 1}},
+ {1810, {wxTextAttr, 'Destroy', undefined}},
+ {1812, {wxTextCtrl, new_3, 3}},
+ {1813, {wxTextCtrl, new_0, 0}},
+ {1815, {wxTextCtrl, destruct, 0}},
+ {1816, {wxTextCtrl, appendText, 1}},
+ {1817, {wxTextCtrl, canCopy, 0}},
+ {1818, {wxTextCtrl, canCut, 0}},
+ {1819, {wxTextCtrl, canPaste, 0}},
+ {1820, {wxTextCtrl, canRedo, 0}},
+ {1821, {wxTextCtrl, canUndo, 0}},
+ {1822, {wxTextCtrl, clear, 0}},
+ {1823, {wxTextCtrl, copy, 0}},
+ {1824, {wxTextCtrl, create, 3}},
+ {1825, {wxTextCtrl, cut, 0}},
+ {1826, {wxTextCtrl, discardEdits, 0}},
+ {1827, {wxTextCtrl, emulateKeyPress, 1}},
+ {1828, {wxTextCtrl, getDefaultStyle, 0}},
+ {1829, {wxTextCtrl, getInsertionPoint, 0}},
+ {1830, {wxTextCtrl, getLastPosition, 0}},
+ {1831, {wxTextCtrl, getLineLength, 1}},
+ {1832, {wxTextCtrl, getLineText, 1}},
+ {1833, {wxTextCtrl, getNumberOfLines, 0}},
+ {1834, {wxTextCtrl, getRange, 2}},
+ {1835, {wxTextCtrl, getSelection, 2}},
+ {1836, {wxTextCtrl, getStringSelection, 0}},
+ {1837, {wxTextCtrl, getStyle, 2}},
+ {1838, {wxTextCtrl, getValue, 0}},
+ {1839, {wxTextCtrl, isEditable, 0}},
+ {1840, {wxTextCtrl, isModified, 0}},
+ {1841, {wxTextCtrl, isMultiLine, 0}},
+ {1842, {wxTextCtrl, isSingleLine, 0}},
+ {1843, {wxTextCtrl, loadFile, 2}},
+ {1844, {wxTextCtrl, markDirty, 0}},
+ {1845, {wxTextCtrl, paste, 0}},
+ {1846, {wxTextCtrl, positionToXY, 3}},
+ {1847, {wxTextCtrl, redo, 0}},
+ {1848, {wxTextCtrl, remove, 2}},
+ {1849, {wxTextCtrl, replace, 3}},
+ {1850, {wxTextCtrl, saveFile, 1}},
+ {1851, {wxTextCtrl, setDefaultStyle, 1}},
+ {1852, {wxTextCtrl, setEditable, 1}},
+ {1853, {wxTextCtrl, setInsertionPoint, 1}},
+ {1854, {wxTextCtrl, setInsertionPointEnd, 0}},
+ {1856, {wxTextCtrl, setMaxLength, 1}},
+ {1857, {wxTextCtrl, setSelection, 2}},
+ {1858, {wxTextCtrl, setStyle, 3}},
+ {1859, {wxTextCtrl, setValue, 1}},
+ {1860, {wxTextCtrl, showPosition, 1}},
+ {1861, {wxTextCtrl, undo, 0}},
+ {1862, {wxTextCtrl, writeText, 1}},
+ {1863, {wxTextCtrl, xYToPosition, 2}},
+ {1866, {wxNotebook, new_0, 0}},
+ {1867, {wxNotebook, new_3, 3}},
+ {1868, {wxNotebook, destruct, 0}},
+ {1869, {wxNotebook, addPage, 3}},
+ {1870, {wxNotebook, advanceSelection, 1}},
+ {1871, {wxNotebook, assignImageList, 1}},
+ {1872, {wxNotebook, create, 3}},
+ {1873, {wxNotebook, deleteAllPages, 0}},
+ {1874, {wxNotebook, deletePage, 1}},
+ {1875, {wxNotebook, removePage, 1}},
+ {1876, {wxNotebook, getCurrentPage, 0}},
+ {1877, {wxNotebook, getImageList, 0}},
+ {1879, {wxNotebook, getPage, 1}},
+ {1880, {wxNotebook, getPageCount, 0}},
+ {1881, {wxNotebook, getPageImage, 1}},
+ {1882, {wxNotebook, getPageText, 1}},
+ {1883, {wxNotebook, getRowCount, 0}},
+ {1884, {wxNotebook, getSelection, 0}},
+ {1885, {wxNotebook, getThemeBackgroundColour, 0}},
+ {1887, {wxNotebook, hitTest, 2}},
+ {1889, {wxNotebook, insertPage, 4}},
+ {1890, {wxNotebook, setImageList, 1}},
+ {1891, {wxNotebook, setPadding, 1}},
+ {1892, {wxNotebook, setPageSize, 1}},
+ {1893, {wxNotebook, setPageImage, 2}},
+ {1894, {wxNotebook, setPageText, 2}},
+ {1895, {wxNotebook, setSelection, 1}},
+ {1896, {wxNotebook, changeSelection, 1}},
+ {1897, {wxChoicebook, new_0, 0}},
+ {1898, {wxChoicebook, new_3, 3}},
+ {1899, {wxChoicebook, addPage, 3}},
+ {1900, {wxChoicebook, advanceSelection, 1}},
+ {1901, {wxChoicebook, assignImageList, 1}},
+ {1902, {wxChoicebook, create, 3}},
+ {1903, {wxChoicebook, deleteAllPages, 0}},
+ {1904, {wxChoicebook, deletePage, 1}},
+ {1905, {wxChoicebook, removePage, 1}},
+ {1906, {wxChoicebook, getCurrentPage, 0}},
+ {1907, {wxChoicebook, getImageList, 0}},
+ {1909, {wxChoicebook, getPage, 1}},
+ {1910, {wxChoicebook, getPageCount, 0}},
+ {1911, {wxChoicebook, getPageImage, 1}},
+ {1912, {wxChoicebook, getPageText, 1}},
+ {1913, {wxChoicebook, getSelection, 0}},
+ {1914, {wxChoicebook, hitTest, 2}},
+ {1915, {wxChoicebook, insertPage, 4}},
+ {1916, {wxChoicebook, setImageList, 1}},
+ {1917, {wxChoicebook, setPageSize, 1}},
+ {1918, {wxChoicebook, setPageImage, 2}},
+ {1919, {wxChoicebook, setPageText, 2}},
+ {1920, {wxChoicebook, setSelection, 1}},
+ {1921, {wxChoicebook, changeSelection, 1}},
+ {1922, {wxChoicebook, 'Destroy', undefined}},
+ {1923, {wxToolbook, new_0, 0}},
+ {1924, {wxToolbook, new_3, 3}},
+ {1925, {wxToolbook, addPage, 3}},
+ {1926, {wxToolbook, advanceSelection, 1}},
+ {1927, {wxToolbook, assignImageList, 1}},
+ {1928, {wxToolbook, create, 3}},
+ {1929, {wxToolbook, deleteAllPages, 0}},
+ {1930, {wxToolbook, deletePage, 1}},
+ {1931, {wxToolbook, removePage, 1}},
+ {1932, {wxToolbook, getCurrentPage, 0}},
+ {1933, {wxToolbook, getImageList, 0}},
+ {1935, {wxToolbook, getPage, 1}},
+ {1936, {wxToolbook, getPageCount, 0}},
+ {1937, {wxToolbook, getPageImage, 1}},
+ {1938, {wxToolbook, getPageText, 1}},
+ {1939, {wxToolbook, getSelection, 0}},
+ {1941, {wxToolbook, hitTest, 2}},
+ {1942, {wxToolbook, insertPage, 4}},
+ {1943, {wxToolbook, setImageList, 1}},
+ {1944, {wxToolbook, setPageSize, 1}},
+ {1945, {wxToolbook, setPageImage, 2}},
+ {1946, {wxToolbook, setPageText, 2}},
+ {1947, {wxToolbook, setSelection, 1}},
+ {1948, {wxToolbook, changeSelection, 1}},
+ {1949, {wxToolbook, 'Destroy', undefined}},
+ {1950, {wxListbook, new_0, 0}},
+ {1951, {wxListbook, new_3, 3}},
+ {1952, {wxListbook, addPage, 3}},
+ {1953, {wxListbook, advanceSelection, 1}},
+ {1954, {wxListbook, assignImageList, 1}},
+ {1955, {wxListbook, create, 3}},
+ {1956, {wxListbook, deleteAllPages, 0}},
+ {1957, {wxListbook, deletePage, 1}},
+ {1958, {wxListbook, removePage, 1}},
+ {1959, {wxListbook, getCurrentPage, 0}},
+ {1960, {wxListbook, getImageList, 0}},
+ {1962, {wxListbook, getPage, 1}},
+ {1963, {wxListbook, getPageCount, 0}},
+ {1964, {wxListbook, getPageImage, 1}},
+ {1965, {wxListbook, getPageText, 1}},
+ {1966, {wxListbook, getSelection, 0}},
+ {1968, {wxListbook, hitTest, 2}},
+ {1969, {wxListbook, insertPage, 4}},
+ {1970, {wxListbook, setImageList, 1}},
+ {1971, {wxListbook, setPageSize, 1}},
+ {1972, {wxListbook, setPageImage, 2}},
+ {1973, {wxListbook, setPageText, 2}},
+ {1974, {wxListbook, setSelection, 1}},
+ {1975, {wxListbook, changeSelection, 1}},
+ {1976, {wxListbook, 'Destroy', undefined}},
+ {1977, {wxTreebook, new_0, 0}},
+ {1978, {wxTreebook, new_3, 3}},
+ {1979, {wxTreebook, addPage, 3}},
+ {1980, {wxTreebook, advanceSelection, 1}},
+ {1981, {wxTreebook, assignImageList, 1}},
+ {1982, {wxTreebook, create, 3}},
+ {1983, {wxTreebook, deleteAllPages, 0}},
+ {1984, {wxTreebook, deletePage, 1}},
+ {1985, {wxTreebook, removePage, 1}},
+ {1986, {wxTreebook, getCurrentPage, 0}},
+ {1987, {wxTreebook, getImageList, 0}},
+ {1989, {wxTreebook, getPage, 1}},
+ {1990, {wxTreebook, getPageCount, 0}},
+ {1991, {wxTreebook, getPageImage, 1}},
+ {1992, {wxTreebook, getPageText, 1}},
+ {1993, {wxTreebook, getSelection, 0}},
+ {1994, {wxTreebook, expandNode, 2}},
+ {1995, {wxTreebook, isNodeExpanded, 1}},
+ {1997, {wxTreebook, hitTest, 2}},
+ {1998, {wxTreebook, insertPage, 4}},
+ {1999, {wxTreebook, insertSubPage, 4}},
+ {2000, {wxTreebook, setImageList, 1}},
+ {2001, {wxTreebook, setPageSize, 1}},
+ {2002, {wxTreebook, setPageImage, 2}},
+ {2003, {wxTreebook, setPageText, 2}},
+ {2004, {wxTreebook, setSelection, 1}},
+ {2005, {wxTreebook, changeSelection, 1}},
+ {2006, {wxTreebook, 'Destroy', undefined}},
+ {2009, {wxTreeCtrl, new_2, 2}},
+ {2010, {wxTreeCtrl, new_0, 0}},
+ {2012, {wxTreeCtrl, destruct, 0}},
+ {2013, {wxTreeCtrl, addRoot, 2}},
+ {2014, {wxTreeCtrl, appendItem, 3}},
+ {2015, {wxTreeCtrl, assignImageList, 1}},
+ {2016, {wxTreeCtrl, assignStateImageList, 1}},
+ {2017, {wxTreeCtrl, collapse, 1}},
+ {2018, {wxTreeCtrl, collapseAndReset, 1}},
+ {2019, {wxTreeCtrl, create, 2}},
+ {2020, {wxTreeCtrl, delete, 1}},
+ {2021, {wxTreeCtrl, deleteAllItems, 0}},
+ {2022, {wxTreeCtrl, deleteChildren, 1}},
+ {2023, {wxTreeCtrl, editLabel, 1}},
+ {2024, {wxTreeCtrl, ensureVisible, 1}},
+ {2025, {wxTreeCtrl, expand, 1}},
+ {2026, {wxTreeCtrl, getBoundingRect, 3}},
+ {2028, {wxTreeCtrl, getChildrenCount, 2}},
+ {2029, {wxTreeCtrl, getCount, 0}},
+ {2030, {wxTreeCtrl, getEditControl, 0}},
+ {2031, {wxTreeCtrl, getFirstChild, 2}},
+ {2032, {wxTreeCtrl, getNextChild, 2}},
+ {2033, {wxTreeCtrl, getFirstVisibleItem, 0}},
+ {2034, {wxTreeCtrl, getImageList, 0}},
+ {2035, {wxTreeCtrl, getIndent, 0}},
+ {2036, {wxTreeCtrl, getItemBackgroundColour, 1}},
+ {2037, {wxTreeCtrl, getItemData, 1}},
+ {2038, {wxTreeCtrl, getItemFont, 1}},
+ {2039, {wxTreeCtrl, getItemImage_1, 1}},
+ {2040, {wxTreeCtrl, getItemImage_2, 2}},
+ {2041, {wxTreeCtrl, getItemText, 1}},
+ {2042, {wxTreeCtrl, getItemTextColour, 1}},
+ {2043, {wxTreeCtrl, getLastChild, 1}},
+ {2044, {wxTreeCtrl, getNextSibling, 1}},
+ {2045, {wxTreeCtrl, getNextVisible, 1}},
+ {2046, {wxTreeCtrl, getItemParent, 1}},
+ {2047, {wxTreeCtrl, getPrevSibling, 1}},
+ {2048, {wxTreeCtrl, getPrevVisible, 1}},
+ {2049, {wxTreeCtrl, getRootItem, 0}},
+ {2050, {wxTreeCtrl, getSelection, 0}},
+ {2051, {wxTreeCtrl, getSelections, 1}},
+ {2052, {wxTreeCtrl, getStateImageList, 0}},
+ {2053, {wxTreeCtrl, hitTest, 1}},
+ {2055, {wxTreeCtrl, insertItem, 4}},
+ {2056, {wxTreeCtrl, isBold, 1}},
+ {2057, {wxTreeCtrl, isExpanded, 1}},
+ {2058, {wxTreeCtrl, isSelected, 1}},
+ {2059, {wxTreeCtrl, isVisible, 1}},
+ {2060, {wxTreeCtrl, itemHasChildren, 1}},
+ {2061, {wxTreeCtrl, prependItem, 3}},
+ {2062, {wxTreeCtrl, scrollTo, 1}},
+ {2063, {wxTreeCtrl, selectItem_1, 1}},
+ {2064, {wxTreeCtrl, selectItem_2, 2}},
+ {2065, {wxTreeCtrl, setIndent, 1}},
+ {2066, {wxTreeCtrl, setImageList, 1}},
+ {2067, {wxTreeCtrl, setItemBackgroundColour, 2}},
+ {2068, {wxTreeCtrl, setItemBold, 2}},
+ {2069, {wxTreeCtrl, setItemData, 2}},
+ {2070, {wxTreeCtrl, setItemDropHighlight, 2}},
+ {2071, {wxTreeCtrl, setItemFont, 2}},
+ {2072, {wxTreeCtrl, setItemHasChildren, 2}},
+ {2073, {wxTreeCtrl, setItemImage_2, 2}},
+ {2074, {wxTreeCtrl, setItemImage_3, 3}},
+ {2075, {wxTreeCtrl, setItemText, 2}},
+ {2076, {wxTreeCtrl, setItemTextColour, 2}},
+ {2077, {wxTreeCtrl, setStateImageList, 1}},
+ {2078, {wxTreeCtrl, setWindowStyle, 1}},
+ {2079, {wxTreeCtrl, sortChildren, 1}},
+ {2080, {wxTreeCtrl, toggle, 1}},
+ {2081, {wxTreeCtrl, toggleItemSelection, 1}},
+ {2082, {wxTreeCtrl, unselect, 0}},
+ {2083, {wxTreeCtrl, unselectAll, 0}},
+ {2084, {wxTreeCtrl, unselectItem, 1}},
+ {2085, {wxScrollBar, new_0, 0}},
+ {2086, {wxScrollBar, new_3, 3}},
+ {2087, {wxScrollBar, destruct, 0}},
+ {2088, {wxScrollBar, create, 3}},
+ {2089, {wxScrollBar, getRange, 0}},
+ {2090, {wxScrollBar, getPageSize, 0}},
+ {2091, {wxScrollBar, getThumbPosition, 0}},
+ {2092, {wxScrollBar, getThumbSize, 0}},
+ {2093, {wxScrollBar, setThumbPosition, 1}},
+ {2094, {wxScrollBar, setScrollbar, 5}},
+ {2096, {wxSpinButton, new_2, 2}},
+ {2097, {wxSpinButton, new_0, 0}},
+ {2098, {wxSpinButton, create, 2}},
+ {2099, {wxSpinButton, getMax, 0}},
+ {2100, {wxSpinButton, getMin, 0}},
+ {2101, {wxSpinButton, getValue, 0}},
+ {2102, {wxSpinButton, setRange, 2}},
+ {2103, {wxSpinButton, setValue, 1}},
+ {2104, {wxSpinButton, 'Destroy', undefined}},
+ {2105, {wxSpinCtrl, new_0, 0}},
+ {2106, {wxSpinCtrl, new_2, 2}},
+ {2108, {wxSpinCtrl, create, 2}},
+ {2111, {wxSpinCtrl, setValue_1_1, 1}},
+ {2112, {wxSpinCtrl, setValue_1_0, 1}},
+ {2114, {wxSpinCtrl, getValue, 0}},
+ {2116, {wxSpinCtrl, setRange, 2}},
+ {2117, {wxSpinCtrl, setSelection, 2}},
+ {2119, {wxSpinCtrl, getMin, 0}},
+ {2121, {wxSpinCtrl, getMax, 0}},
+ {2122, {wxSpinCtrl, 'Destroy', undefined}},
+ {2123, {wxStaticText, new_0, 0}},
+ {2124, {wxStaticText, new_4, 4}},
+ {2125, {wxStaticText, create, 4}},
+ {2126, {wxStaticText, getLabel, 0}},
+ {2127, {wxStaticText, setLabel, 1}},
+ {2128, {wxStaticText, wrap, 1}},
+ {2129, {wxStaticText, 'Destroy', undefined}},
+ {2130, {wxStaticBitmap, new_0, 0}},
+ {2131, {wxStaticBitmap, new_4, 4}},
+ {2132, {wxStaticBitmap, create, 4}},
+ {2133, {wxStaticBitmap, getBitmap, 0}},
+ {2134, {wxStaticBitmap, setBitmap, 1}},
+ {2135, {wxStaticBitmap, 'Destroy', undefined}},
+ {2136, {wxRadioBox, new, 7}},
+ {2138, {wxRadioBox, destruct, 0}},
+ {2139, {wxRadioBox, create, 7}},
+ {2140, {wxRadioBox, enable_2, 2}},
+ {2141, {wxRadioBox, enable_1, 1}},
+ {2142, {wxRadioBox, getSelection, 0}},
+ {2143, {wxRadioBox, getString, 1}},
+ {2144, {wxRadioBox, setSelection, 1}},
+ {2145, {wxRadioBox, show_2, 2}},
+ {2146, {wxRadioBox, show_1, 1}},
+ {2147, {wxRadioBox, getColumnCount, 0}},
+ {2148, {wxRadioBox, getItemHelpText, 1}},
+ {2149, {wxRadioBox, getItemToolTip, 1}},
+ {2151, {wxRadioBox, getItemFromPoint, 1}},
+ {2152, {wxRadioBox, getRowCount, 0}},
+ {2153, {wxRadioBox, isItemEnabled, 1}},
+ {2154, {wxRadioBox, isItemShown, 1}},
+ {2155, {wxRadioBox, setItemHelpText, 2}},
+ {2156, {wxRadioBox, setItemToolTip, 2}},
+ {2157, {wxRadioButton, new_0, 0}},
+ {2158, {wxRadioButton, new_4, 4}},
+ {2159, {wxRadioButton, create, 4}},
+ {2160, {wxRadioButton, getValue, 0}},
+ {2161, {wxRadioButton, setValue, 1}},
+ {2162, {wxRadioButton, 'Destroy', undefined}},
+ {2164, {wxSlider, new_6, 6}},
+ {2165, {wxSlider, new_0, 0}},
+ {2166, {wxSlider, create, 6}},
+ {2167, {wxSlider, getLineSize, 0}},
+ {2168, {wxSlider, getMax, 0}},
+ {2169, {wxSlider, getMin, 0}},
+ {2170, {wxSlider, getPageSize, 0}},
+ {2171, {wxSlider, getThumbLength, 0}},
+ {2172, {wxSlider, getValue, 0}},
+ {2173, {wxSlider, setLineSize, 1}},
+ {2174, {wxSlider, setPageSize, 1}},
+ {2175, {wxSlider, setRange, 2}},
+ {2176, {wxSlider, setThumbLength, 1}},
+ {2177, {wxSlider, setValue, 1}},
+ {2178, {wxSlider, 'Destroy', undefined}},
+ {2180, {wxDialog, new_4, 4}},
+ {2181, {wxDialog, new_0, 0}},
+ {2183, {wxDialog, destruct, 0}},
+ {2184, {wxDialog, create, 4}},
+ {2185, {wxDialog, createButtonSizer, 1}},
+ {2186, {wxDialog, createStdDialogButtonSizer, 1}},
+ {2187, {wxDialog, endModal, 1}},
+ {2188, {wxDialog, getAffirmativeId, 0}},
+ {2189, {wxDialog, getReturnCode, 0}},
+ {2190, {wxDialog, isModal, 0}},
+ {2191, {wxDialog, setAffirmativeId, 1}},
+ {2192, {wxDialog, setReturnCode, 1}},
+ {2193, {wxDialog, show, 1}},
+ {2194, {wxDialog, showModal, 0}},
+ {2195, {wxColourDialog, new_0, 0}},
+ {2196, {wxColourDialog, new_2, 2}},
+ {2197, {wxColourDialog, destruct, 0}},
+ {2198, {wxColourDialog, create, 2}},
+ {2199, {wxColourDialog, getColourData, 0}},
+ {2200, {wxColourData, new_0, 0}},
+ {2201, {wxColourData, new_1, 1}},
+ {2202, {wxColourData, destruct, 0}},
+ {2203, {wxColourData, getChooseFull, 0}},
+ {2204, {wxColourData, getColour, 0}},
+ {2206, {wxColourData, getCustomColour, 1}},
+ {2207, {wxColourData, setChooseFull, 1}},
+ {2208, {wxColourData, setColour, 1}},
+ {2209, {wxColourData, setCustomColour, 2}},
+ {2210, {wxPalette, new_0, 0}},
+ {2211, {wxPalette, new_4, 4}},
+ {2213, {wxPalette, destruct, 0}},
+ {2214, {wxPalette, create, 4}},
+ {2215, {wxPalette, getColoursCount, 0}},
+ {2216, {wxPalette, getPixel, 3}},
+ {2217, {wxPalette, getRGB, 4}},
+ {2218, {wxPalette, isOk, 0}},
+ {2222, {wxDirDialog, new, 2}},
+ {2223, {wxDirDialog, destruct, 0}},
+ {2224, {wxDirDialog, getPath, 0}},
+ {2225, {wxDirDialog, getMessage, 0}},
+ {2226, {wxDirDialog, setMessage, 1}},
+ {2227, {wxDirDialog, setPath, 1}},
+ {2231, {wxFileDialog, new, 2}},
+ {2232, {wxFileDialog, destruct, 0}},
+ {2233, {wxFileDialog, getDirectory, 0}},
+ {2234, {wxFileDialog, getFilename, 0}},
+ {2235, {wxFileDialog, getFilenames, 1}},
+ {2236, {wxFileDialog, getFilterIndex, 0}},
+ {2237, {wxFileDialog, getMessage, 0}},
+ {2238, {wxFileDialog, getPath, 0}},
+ {2239, {wxFileDialog, getPaths, 1}},
+ {2240, {wxFileDialog, getWildcard, 0}},
+ {2241, {wxFileDialog, setDirectory, 1}},
+ {2242, {wxFileDialog, setFilename, 1}},
+ {2243, {wxFileDialog, setFilterIndex, 1}},
+ {2244, {wxFileDialog, setMessage, 1}},
+ {2245, {wxFileDialog, setPath, 1}},
+ {2246, {wxFileDialog, setWildcard, 1}},
+ {2247, {wxPickerBase, setInternalMargin, 1}},
+ {2248, {wxPickerBase, getInternalMargin, 0}},
+ {2249, {wxPickerBase, setTextCtrlProportion, 1}},
+ {2250, {wxPickerBase, setPickerCtrlProportion, 1}},
+ {2251, {wxPickerBase, getTextCtrlProportion, 0}},
+ {2252, {wxPickerBase, getPickerCtrlProportion, 0}},
+ {2253, {wxPickerBase, hasTextCtrl, 0}},
+ {2254, {wxPickerBase, getTextCtrl, 0}},
+ {2255, {wxPickerBase, isTextCtrlGrowable, 0}},
+ {2256, {wxPickerBase, setPickerCtrlGrowable, 1}},
+ {2257, {wxPickerBase, setTextCtrlGrowable, 1}},
+ {2258, {wxPickerBase, isPickerCtrlGrowable, 0}},
+ {2259, {wxFilePickerCtrl, new_0, 0}},
+ {2260, {wxFilePickerCtrl, new_3, 3}},
+ {2261, {wxFilePickerCtrl, create, 3}},
+ {2262, {wxFilePickerCtrl, getPath, 0}},
+ {2263, {wxFilePickerCtrl, setPath, 1}},
+ {2264, {wxFilePickerCtrl, 'Destroy', undefined}},
+ {2265, {wxDirPickerCtrl, new_0, 0}},
+ {2266, {wxDirPickerCtrl, new_3, 3}},
+ {2267, {wxDirPickerCtrl, create, 3}},
+ {2268, {wxDirPickerCtrl, getPath, 0}},
+ {2269, {wxDirPickerCtrl, setPath, 1}},
+ {2270, {wxDirPickerCtrl, 'Destroy', undefined}},
+ {2271, {wxColourPickerCtrl, new_0, 0}},
+ {2272, {wxColourPickerCtrl, new_3, 3}},
+ {2273, {wxColourPickerCtrl, create, 3}},
+ {2274, {wxColourPickerCtrl, getColour, 0}},
+ {2275, {wxColourPickerCtrl, setColour_1_1, 1}},
+ {2276, {wxColourPickerCtrl, setColour_1_0, 1}},
+ {2277, {wxColourPickerCtrl, 'Destroy', undefined}},
+ {2278, {wxDatePickerCtrl, new_0, 0}},
+ {2279, {wxDatePickerCtrl, new_3, 3}},
+ {2280, {wxDatePickerCtrl, getRange, 2}},
+ {2281, {wxDatePickerCtrl, getValue, 0}},
+ {2282, {wxDatePickerCtrl, setRange, 2}},
+ {2283, {wxDatePickerCtrl, setValue, 1}},
+ {2284, {wxDatePickerCtrl, 'Destroy', undefined}},
+ {2285, {wxFontPickerCtrl, new_0, 0}},
+ {2286, {wxFontPickerCtrl, new_3, 3}},
+ {2287, {wxFontPickerCtrl, create, 3}},
+ {2288, {wxFontPickerCtrl, getSelectedFont, 0}},
+ {2289, {wxFontPickerCtrl, setSelectedFont, 1}},
+ {2290, {wxFontPickerCtrl, getMaxPointSize, 0}},
+ {2291, {wxFontPickerCtrl, setMaxPointSize, 1}},
+ {2292, {wxFontPickerCtrl, 'Destroy', undefined}},
+ {2295, {wxFindReplaceDialog, new_0, 0}},
+ {2296, {wxFindReplaceDialog, new_4, 4}},
+ {2297, {wxFindReplaceDialog, destruct, 0}},
+ {2298, {wxFindReplaceDialog, create, 4}},
+ {2299, {wxFindReplaceDialog, getData, 0}},
+ {2300, {wxFindReplaceData, new_0, 0}},
+ {2301, {wxFindReplaceData, new_1, 1}},
+ {2302, {wxFindReplaceData, getFindString, 0}},
+ {2303, {wxFindReplaceData, getReplaceString, 0}},
+ {2304, {wxFindReplaceData, getFlags, 0}},
+ {2305, {wxFindReplaceData, setFlags, 1}},
+ {2306, {wxFindReplaceData, setFindString, 1}},
+ {2307, {wxFindReplaceData, setReplaceString, 1}},
+ {2308, {wxFindReplaceData, 'Destroy', undefined}},
+ {2309, {wxMultiChoiceDialog, new_0, 0}},
+ {2311, {wxMultiChoiceDialog, new_5, 5}},
+ {2312, {wxMultiChoiceDialog, getSelections, 0}},
+ {2313, {wxMultiChoiceDialog, setSelections, 1}},
+ {2314, {wxMultiChoiceDialog, 'Destroy', undefined}},
+ {2315, {wxSingleChoiceDialog, new_0, 0}},
+ {2317, {wxSingleChoiceDialog, new_5, 5}},
+ {2318, {wxSingleChoiceDialog, getSelection, 0}},
+ {2319, {wxSingleChoiceDialog, getStringSelection, 0}},
+ {2320, {wxSingleChoiceDialog, setSelection, 1}},
+ {2321, {wxSingleChoiceDialog, 'Destroy', undefined}},
+ {2322, {wxTextEntryDialog, new, 3}},
+ {2323, {wxTextEntryDialog, getValue, 0}},
+ {2324, {wxTextEntryDialog, setValue, 1}},
+ {2325, {wxTextEntryDialog, 'Destroy', undefined}},
+ {2326, {wxPasswordEntryDialog, new, 3}},
+ {2327, {wxPasswordEntryDialog, 'Destroy', undefined}},
+ {2328, {wxFontData, new_0, 0}},
+ {2329, {wxFontData, new_1, 1}},
+ {2330, {wxFontData, destruct, 0}},
+ {2331, {wxFontData, enableEffects, 1}},
+ {2332, {wxFontData, getAllowSymbols, 0}},
+ {2333, {wxFontData, getColour, 0}},
+ {2334, {wxFontData, getChosenFont, 0}},
+ {2335, {wxFontData, getEnableEffects, 0}},
+ {2336, {wxFontData, getInitialFont, 0}},
+ {2337, {wxFontData, getShowHelp, 0}},
+ {2338, {wxFontData, setAllowSymbols, 1}},
+ {2339, {wxFontData, setChosenFont, 1}},
+ {2340, {wxFontData, setColour, 1}},
+ {2341, {wxFontData, setInitialFont, 1}},
+ {2342, {wxFontData, setRange, 2}},
+ {2343, {wxFontData, setShowHelp, 1}},
+ {2347, {wxFontDialog, new_0, 0}},
+ {2349, {wxFontDialog, new_2, 2}},
+ {2351, {wxFontDialog, create, 2}},
+ {2352, {wxFontDialog, getFontData, 0}},
+ {2354, {wxFontDialog, 'Destroy', undefined}},
+ {2355, {wxProgressDialog, new, 3}},
+ {2356, {wxProgressDialog, destruct, 0}},
+ {2357, {wxProgressDialog, resume, 0}},
+ {2358, {wxProgressDialog, update_2, 2}},
+ {2359, {wxProgressDialog, update_0, 0}},
+ {2360, {wxMessageDialog, new, 3}},
+ {2361, {wxMessageDialog, destruct, 0}},
+ {2362, {wxPageSetupDialog, new, 2}},
+ {2363, {wxPageSetupDialog, destruct, 0}},
+ {2364, {wxPageSetupDialog, getPageSetupData, 0}},
+ {2365, {wxPageSetupDialog, showModal, 0}},
+ {2366, {wxPageSetupDialogData, new_0, 0}},
+ {2367, {wxPageSetupDialogData, new_1_0, 1}},
+ {2368, {wxPageSetupDialogData, new_1_1, 1}},
+ {2369, {wxPageSetupDialogData, destruct, 0}},
+ {2370, {wxPageSetupDialogData, enableHelp, 1}},
+ {2371, {wxPageSetupDialogData, enableMargins, 1}},
+ {2372, {wxPageSetupDialogData, enableOrientation, 1}},
+ {2373, {wxPageSetupDialogData, enablePaper, 1}},
+ {2374, {wxPageSetupDialogData, enablePrinter, 1}},
+ {2375, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
+ {2376, {wxPageSetupDialogData, getEnableMargins, 0}},
+ {2377, {wxPageSetupDialogData, getEnableOrientation, 0}},
+ {2378, {wxPageSetupDialogData, getEnablePaper, 0}},
+ {2379, {wxPageSetupDialogData, getEnablePrinter, 0}},
+ {2380, {wxPageSetupDialogData, getEnableHelp, 0}},
+ {2381, {wxPageSetupDialogData, getDefaultInfo, 0}},
+ {2382, {wxPageSetupDialogData, getMarginTopLeft, 0}},
+ {2383, {wxPageSetupDialogData, getMarginBottomRight, 0}},
+ {2384, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
+ {2385, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
+ {2386, {wxPageSetupDialogData, getPaperId, 0}},
+ {2387, {wxPageSetupDialogData, getPaperSize, 0}},
+ {2389, {wxPageSetupDialogData, getPrintData, 0}},
+ {2390, {wxPageSetupDialogData, isOk, 0}},
+ {2391, {wxPageSetupDialogData, setDefaultInfo, 1}},
+ {2392, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
+ {2393, {wxPageSetupDialogData, setMarginTopLeft, 1}},
+ {2394, {wxPageSetupDialogData, setMarginBottomRight, 1}},
+ {2395, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
+ {2396, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
+ {2397, {wxPageSetupDialogData, setPaperId, 1}},
+ {2398, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
+ {2399, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
+ {2400, {wxPageSetupDialogData, setPrintData, 1}},
+ {2401, {wxPrintDialog, new_2_0, 2}},
+ {2402, {wxPrintDialog, new_2_1, 2}},
+ {2403, {wxPrintDialog, destruct, 0}},
+ {2404, {wxPrintDialog, getPrintDialogData, 0}},
+ {2405, {wxPrintDialog, getPrintDC, 0}},
+ {2406, {wxPrintDialogData, new_0, 0}},
+ {2407, {wxPrintDialogData, new_1_1, 1}},
+ {2408, {wxPrintDialogData, new_1_0, 1}},
+ {2409, {wxPrintDialogData, destruct, 0}},
+ {2410, {wxPrintDialogData, enableHelp, 1}},
+ {2411, {wxPrintDialogData, enablePageNumbers, 1}},
+ {2412, {wxPrintDialogData, enablePrintToFile, 1}},
+ {2413, {wxPrintDialogData, enableSelection, 1}},
+ {2414, {wxPrintDialogData, getAllPages, 0}},
+ {2415, {wxPrintDialogData, getCollate, 0}},
+ {2416, {wxPrintDialogData, getFromPage, 0}},
+ {2417, {wxPrintDialogData, getMaxPage, 0}},
+ {2418, {wxPrintDialogData, getMinPage, 0}},
+ {2419, {wxPrintDialogData, getNoCopies, 0}},
+ {2420, {wxPrintDialogData, getPrintData, 0}},
+ {2421, {wxPrintDialogData, getPrintToFile, 0}},
+ {2422, {wxPrintDialogData, getSelection, 0}},
+ {2423, {wxPrintDialogData, getToPage, 0}},
+ {2424, {wxPrintDialogData, isOk, 0}},
+ {2425, {wxPrintDialogData, setCollate, 1}},
+ {2426, {wxPrintDialogData, setFromPage, 1}},
+ {2427, {wxPrintDialogData, setMaxPage, 1}},
+ {2428, {wxPrintDialogData, setMinPage, 1}},
+ {2429, {wxPrintDialogData, setNoCopies, 1}},
+ {2430, {wxPrintDialogData, setPrintData, 1}},
+ {2431, {wxPrintDialogData, setPrintToFile, 1}},
+ {2432, {wxPrintDialogData, setSelection, 1}},
+ {2433, {wxPrintDialogData, setToPage, 1}},
+ {2434, {wxPrintData, new_0, 0}},
+ {2435, {wxPrintData, new_1, 1}},
+ {2436, {wxPrintData, destruct, 0}},
+ {2437, {wxPrintData, getCollate, 0}},
+ {2438, {wxPrintData, getBin, 0}},
+ {2439, {wxPrintData, getColour, 0}},
+ {2440, {wxPrintData, getDuplex, 0}},
+ {2441, {wxPrintData, getNoCopies, 0}},
+ {2442, {wxPrintData, getOrientation, 0}},
+ {2443, {wxPrintData, getPaperId, 0}},
+ {2444, {wxPrintData, getPrinterName, 0}},
+ {2445, {wxPrintData, getQuality, 0}},
+ {2446, {wxPrintData, isOk, 0}},
+ {2447, {wxPrintData, setBin, 1}},
+ {2448, {wxPrintData, setCollate, 1}},
+ {2449, {wxPrintData, setColour, 1}},
+ {2450, {wxPrintData, setDuplex, 1}},
+ {2451, {wxPrintData, setNoCopies, 1}},
+ {2452, {wxPrintData, setOrientation, 1}},
+ {2453, {wxPrintData, setPaperId, 1}},
+ {2454, {wxPrintData, setPrinterName, 1}},
+ {2455, {wxPrintData, setQuality, 1}},
+ {2458, {wxPrintPreview, new_2, 2}},
+ {2459, {wxPrintPreview, new_3, 3}},
+ {2461, {wxPrintPreview, destruct, 0}},
+ {2462, {wxPrintPreview, getCanvas, 0}},
+ {2463, {wxPrintPreview, getCurrentPage, 0}},
+ {2464, {wxPrintPreview, getFrame, 0}},
+ {2465, {wxPrintPreview, getMaxPage, 0}},
+ {2466, {wxPrintPreview, getMinPage, 0}},
+ {2467, {wxPrintPreview, getPrintout, 0}},
+ {2468, {wxPrintPreview, getPrintoutForPrinting, 0}},
+ {2469, {wxPrintPreview, isOk, 0}},
+ {2470, {wxPrintPreview, paintPage, 2}},
+ {2471, {wxPrintPreview, print, 1}},
+ {2472, {wxPrintPreview, renderPage, 1}},
+ {2473, {wxPrintPreview, setCanvas, 1}},
+ {2474, {wxPrintPreview, setCurrentPage, 1}},
+ {2475, {wxPrintPreview, setFrame, 1}},
+ {2476, {wxPrintPreview, setPrintout, 1}},
+ {2477, {wxPrintPreview, setZoom, 1}},
+ {2478, {wxPreviewFrame, new, 3}},
+ {2479, {wxPreviewFrame, destruct, 0}},
+ {2480, {wxPreviewFrame, createControlBar, 0}},
+ {2481, {wxPreviewFrame, createCanvas, 0}},
+ {2482, {wxPreviewFrame, initialize, 0}},
+ {2483, {wxPreviewFrame, onCloseWindow, 1}},
+ {2484, {wxPreviewControlBar, new, 4}},
+ {2485, {wxPreviewControlBar, destruct, 0}},
+ {2486, {wxPreviewControlBar, createButtons, 0}},
+ {2487, {wxPreviewControlBar, getPrintPreview, 0}},
+ {2488, {wxPreviewControlBar, getZoomControl, 0}},
+ {2489, {wxPreviewControlBar, setZoomControl, 1}},
+ {2491, {wxPrinter, new, 1}},
+ {2492, {wxPrinter, createAbortWindow, 2}},
+ {2493, {wxPrinter, getAbort, 0}},
+ {2494, {wxPrinter, getLastError, 0}},
+ {2495, {wxPrinter, getPrintDialogData, 0}},
+ {2496, {wxPrinter, print, 3}},
+ {2497, {wxPrinter, printDialog, 1}},
+ {2498, {wxPrinter, reportError, 3}},
+ {2499, {wxPrinter, setup, 1}},
+ {2500, {wxPrinter, 'Destroy', undefined}},
+ {2501, {wxXmlResource, new_1, 1}},
+ {2502, {wxXmlResource, new_2, 2}},
+ {2503, {wxXmlResource, destruct, 0}},
+ {2504, {wxXmlResource, attachUnknownControl, 3}},
+ {2505, {wxXmlResource, clearHandlers, 0}},
+ {2506, {wxXmlResource, compareVersion, 4}},
+ {2507, {wxXmlResource, get, 0}},
+ {2508, {wxXmlResource, getFlags, 0}},
+ {2509, {wxXmlResource, getVersion, 0}},
+ {2510, {wxXmlResource, getXRCID, 2}},
+ {2511, {wxXmlResource, initAllHandlers, 0}},
+ {2512, {wxXmlResource, load, 1}},
+ {2513, {wxXmlResource, loadBitmap, 1}},
+ {2514, {wxXmlResource, loadDialog_2, 2}},
+ {2515, {wxXmlResource, loadDialog_3, 3}},
+ {2516, {wxXmlResource, loadFrame_2, 2}},
+ {2517, {wxXmlResource, loadFrame_3, 3}},
+ {2518, {wxXmlResource, loadIcon, 1}},
+ {2519, {wxXmlResource, loadMenu, 1}},
+ {2520, {wxXmlResource, loadMenuBar_2, 2}},
+ {2521, {wxXmlResource, loadMenuBar_1, 1}},
+ {2522, {wxXmlResource, loadPanel_2, 2}},
+ {2523, {wxXmlResource, loadPanel_3, 3}},
+ {2524, {wxXmlResource, loadToolBar, 2}},
+ {2525, {wxXmlResource, set, 1}},
+ {2526, {wxXmlResource, setFlags, 1}},
+ {2527, {wxXmlResource, unload, 1}},
+ {2528, {wxXmlResource, xrcctrl, 3}},
+ {2529, {wxHtmlEasyPrinting, new, 1}},
+ {2530, {wxHtmlEasyPrinting, destruct, 0}},
+ {2531, {wxHtmlEasyPrinting, getPrintData, 0}},
+ {2532, {wxHtmlEasyPrinting, getPageSetupData, 0}},
+ {2533, {wxHtmlEasyPrinting, previewFile, 1}},
+ {2534, {wxHtmlEasyPrinting, previewText, 2}},
+ {2535, {wxHtmlEasyPrinting, printFile, 1}},
+ {2536, {wxHtmlEasyPrinting, printText, 2}},
+ {2537, {wxHtmlEasyPrinting, pageSetup, 0}},
+ {2538, {wxHtmlEasyPrinting, setFonts, 3}},
+ {2539, {wxHtmlEasyPrinting, setHeader, 2}},
+ {2540, {wxHtmlEasyPrinting, setFooter, 2}},
+ {2542, {wxGLCanvas, new_2, 2}},
+ {2543, {wxGLCanvas, new_3_1, 3}},
+ {2544, {wxGLCanvas, new_3_0, 3}},
+ {2545, {wxGLCanvas, getContext, 0}},
+ {2547, {wxGLCanvas, setCurrent, 0}},
+ {2548, {wxGLCanvas, swapBuffers, 0}},
+ {2549, {wxGLCanvas, 'Destroy', undefined}},
+ {2550, {wxAuiManager, new, 1}},
+ {2551, {wxAuiManager, destruct, 0}},
+ {2552, {wxAuiManager, addPane_2_1, 2}},
+ {2553, {wxAuiManager, addPane_3, 3}},
+ {2554, {wxAuiManager, addPane_2_0, 2}},
+ {2555, {wxAuiManager, detachPane, 1}},
+ {2556, {wxAuiManager, getAllPanes, 0}},
+ {2557, {wxAuiManager, getArtProvider, 0}},
+ {2558, {wxAuiManager, getDockSizeConstraint, 2}},
+ {2559, {wxAuiManager, getFlags, 0}},
+ {2560, {wxAuiManager, getManagedWindow, 0}},
+ {2561, {wxAuiManager, getManager, 1}},
+ {2562, {wxAuiManager, getPane_1_1, 1}},
+ {2563, {wxAuiManager, getPane_1_0, 1}},
+ {2564, {wxAuiManager, hideHint, 0}},
+ {2565, {wxAuiManager, insertPane, 3}},
+ {2566, {wxAuiManager, loadPaneInfo, 2}},
+ {2567, {wxAuiManager, loadPerspective, 2}},
+ {2568, {wxAuiManager, savePaneInfo, 1}},
+ {2569, {wxAuiManager, savePerspective, 0}},
+ {2570, {wxAuiManager, setArtProvider, 1}},
+ {2571, {wxAuiManager, setDockSizeConstraint, 2}},
+ {2572, {wxAuiManager, setFlags, 1}},
+ {2573, {wxAuiManager, setManagedWindow, 1}},
+ {2574, {wxAuiManager, showHint, 1}},
+ {2575, {wxAuiManager, unInit, 0}},
+ {2576, {wxAuiManager, update, 0}},
+ {2577, {wxAuiPaneInfo, new_0, 0}},
+ {2578, {wxAuiPaneInfo, new_1, 1}},
+ {2579, {wxAuiPaneInfo, destruct, 0}},
+ {2580, {wxAuiPaneInfo, bestSize_1, 1}},
+ {2581, {wxAuiPaneInfo, bestSize_2, 2}},
+ {2582, {wxAuiPaneInfo, bottom, 0}},
+ {2583, {wxAuiPaneInfo, bottomDockable, 1}},
+ {2584, {wxAuiPaneInfo, caption, 1}},
+ {2585, {wxAuiPaneInfo, captionVisible, 1}},
+ {2586, {wxAuiPaneInfo, centre, 0}},
+ {2587, {wxAuiPaneInfo, centrePane, 0}},
+ {2588, {wxAuiPaneInfo, closeButton, 1}},
+ {2589, {wxAuiPaneInfo, defaultPane, 0}},
+ {2590, {wxAuiPaneInfo, destroyOnClose, 1}},
+ {2591, {wxAuiPaneInfo, direction, 1}},
+ {2592, {wxAuiPaneInfo, dock, 0}},
+ {2593, {wxAuiPaneInfo, dockable, 1}},
+ {2594, {wxAuiPaneInfo, fixed, 0}},
+ {2595, {wxAuiPaneInfo, float, 0}},
+ {2596, {wxAuiPaneInfo, floatable, 1}},
+ {2597, {wxAuiPaneInfo, floatingPosition_1, 1}},
+ {2598, {wxAuiPaneInfo, floatingPosition_2, 2}},
+ {2599, {wxAuiPaneInfo, floatingSize_1, 1}},
+ {2600, {wxAuiPaneInfo, floatingSize_2, 2}},
+ {2601, {wxAuiPaneInfo, gripper, 1}},
+ {2602, {wxAuiPaneInfo, gripperTop, 1}},
+ {2603, {wxAuiPaneInfo, hasBorder, 0}},
+ {2604, {wxAuiPaneInfo, hasCaption, 0}},
+ {2605, {wxAuiPaneInfo, hasCloseButton, 0}},
+ {2606, {wxAuiPaneInfo, hasFlag, 1}},
+ {2607, {wxAuiPaneInfo, hasGripper, 0}},
+ {2608, {wxAuiPaneInfo, hasGripperTop, 0}},
+ {2609, {wxAuiPaneInfo, hasMaximizeButton, 0}},
+ {2610, {wxAuiPaneInfo, hasMinimizeButton, 0}},
+ {2611, {wxAuiPaneInfo, hasPinButton, 0}},
+ {2612, {wxAuiPaneInfo, hide, 0}},
+ {2613, {wxAuiPaneInfo, isBottomDockable, 0}},
+ {2614, {wxAuiPaneInfo, isDocked, 0}},
+ {2615, {wxAuiPaneInfo, isFixed, 0}},
+ {2616, {wxAuiPaneInfo, isFloatable, 0}},
+ {2617, {wxAuiPaneInfo, isFloating, 0}},
+ {2618, {wxAuiPaneInfo, isLeftDockable, 0}},
+ {2619, {wxAuiPaneInfo, isMovable, 0}},
+ {2620, {wxAuiPaneInfo, isOk, 0}},
+ {2621, {wxAuiPaneInfo, isResizable, 0}},
+ {2622, {wxAuiPaneInfo, isRightDockable, 0}},
+ {2623, {wxAuiPaneInfo, isShown, 0}},
+ {2624, {wxAuiPaneInfo, isToolbar, 0}},
+ {2625, {wxAuiPaneInfo, isTopDockable, 0}},
+ {2626, {wxAuiPaneInfo, layer, 1}},
+ {2627, {wxAuiPaneInfo, left, 0}},
+ {2628, {wxAuiPaneInfo, leftDockable, 1}},
+ {2629, {wxAuiPaneInfo, maxSize_1, 1}},
+ {2630, {wxAuiPaneInfo, maxSize_2, 2}},
+ {2631, {wxAuiPaneInfo, maximizeButton, 1}},
+ {2632, {wxAuiPaneInfo, minSize_1, 1}},
+ {2633, {wxAuiPaneInfo, minSize_2, 2}},
+ {2634, {wxAuiPaneInfo, minimizeButton, 1}},
+ {2635, {wxAuiPaneInfo, movable, 1}},
+ {2636, {wxAuiPaneInfo, name, 1}},
+ {2637, {wxAuiPaneInfo, paneBorder, 1}},
+ {2638, {wxAuiPaneInfo, pinButton, 1}},
+ {2639, {wxAuiPaneInfo, position, 1}},
+ {2640, {wxAuiPaneInfo, resizable, 1}},
+ {2641, {wxAuiPaneInfo, right, 0}},
+ {2642, {wxAuiPaneInfo, rightDockable, 1}},
+ {2643, {wxAuiPaneInfo, row, 1}},
+ {2644, {wxAuiPaneInfo, safeSet, 1}},
+ {2645, {wxAuiPaneInfo, setFlag, 2}},
+ {2646, {wxAuiPaneInfo, show, 1}},
+ {2647, {wxAuiPaneInfo, toolbarPane, 0}},
+ {2648, {wxAuiPaneInfo, top, 0}},
+ {2649, {wxAuiPaneInfo, topDockable, 1}},
+ {2650, {wxAuiPaneInfo, window, 1}},
+ {2651, {wxAuiNotebook, new_0, 0}},
+ {2652, {wxAuiNotebook, new_2, 2}},
+ {2653, {wxAuiNotebook, addPage, 3}},
+ {2654, {wxAuiNotebook, create, 2}},
+ {2655, {wxAuiNotebook, deletePage, 1}},
+ {2656, {wxAuiNotebook, getArtProvider, 0}},
+ {2657, {wxAuiNotebook, getPage, 1}},
+ {2658, {wxAuiNotebook, getPageBitmap, 1}},
+ {2659, {wxAuiNotebook, getPageCount, 0}},
+ {2660, {wxAuiNotebook, getPageIndex, 1}},
+ {2661, {wxAuiNotebook, getPageText, 1}},
+ {2662, {wxAuiNotebook, getSelection, 0}},
+ {2663, {wxAuiNotebook, insertPage, 4}},
+ {2664, {wxAuiNotebook, removePage, 1}},
+ {2665, {wxAuiNotebook, setArtProvider, 1}},
+ {2666, {wxAuiNotebook, setFont, 1}},
+ {2667, {wxAuiNotebook, setPageBitmap, 2}},
+ {2668, {wxAuiNotebook, setPageText, 2}},
+ {2669, {wxAuiNotebook, setSelection, 1}},
+ {2670, {wxAuiNotebook, setTabCtrlHeight, 1}},
+ {2671, {wxAuiNotebook, setUniformBitmapSize, 1}},
+ {2672, {wxAuiNotebook, 'Destroy', undefined}},
+ {2673, {wxMDIParentFrame, new_0, 0}},
+ {2674, {wxMDIParentFrame, new_4, 4}},
+ {2675, {wxMDIParentFrame, destruct, 0}},
+ {2676, {wxMDIParentFrame, activateNext, 0}},
+ {2677, {wxMDIParentFrame, activatePrevious, 0}},
+ {2678, {wxMDIParentFrame, arrangeIcons, 0}},
+ {2679, {wxMDIParentFrame, cascade, 0}},
+ {2680, {wxMDIParentFrame, create, 4}},
+ {2681, {wxMDIParentFrame, getActiveChild, 0}},
+ {2682, {wxMDIParentFrame, getClientWindow, 0}},
+ {2683, {wxMDIParentFrame, tile, 1}},
+ {2684, {wxMDIChildFrame, new_0, 0}},
+ {2685, {wxMDIChildFrame, new_4, 4}},
+ {2686, {wxMDIChildFrame, destruct, 0}},
+ {2687, {wxMDIChildFrame, activate, 0}},
+ {2688, {wxMDIChildFrame, create, 4}},
+ {2689, {wxMDIChildFrame, maximize, 1}},
+ {2690, {wxMDIChildFrame, restore, 0}},
+ {2691, {wxMDIClientWindow, new_0, 0}},
+ {2692, {wxMDIClientWindow, new_2, 2}},
+ {2693, {wxMDIClientWindow, destruct, 0}},
+ {2694, {wxMDIClientWindow, createClient, 2}},
+ {2695, {wxLayoutAlgorithm, new, 0}},
+ {2696, {wxLayoutAlgorithm, layoutFrame, 2}},
+ {2697, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
+ {2698, {wxLayoutAlgorithm, layoutWindow, 2}},
+ {2699, {wxLayoutAlgorithm, 'Destroy', undefined}},
+ {2700, {wxEvent, getId, 0}},
+ {2701, {wxEvent, getSkipped, 0}},
+ {2702, {wxEvent, getTimestamp, 0}},
+ {2703, {wxEvent, isCommandEvent, 0}},
+ {2704, {wxEvent, resumePropagation, 1}},
+ {2705, {wxEvent, shouldPropagate, 0}},
+ {2706, {wxEvent, skip, 1}},
+ {2707, {wxEvent, stopPropagation, 0}},
+ {2708, {wxCommandEvent, getClientData, 0}},
+ {2709, {wxCommandEvent, getExtraLong, 0}},
+ {2710, {wxCommandEvent, getInt, 0}},
+ {2711, {wxCommandEvent, getSelection, 0}},
+ {2712, {wxCommandEvent, getString, 0}},
+ {2713, {wxCommandEvent, isChecked, 0}},
+ {2714, {wxCommandEvent, isSelection, 0}},
+ {2715, {wxCommandEvent, setInt, 1}},
+ {2716, {wxCommandEvent, setString, 1}},
+ {2717, {wxScrollEvent, getOrientation, 0}},
+ {2718, {wxScrollEvent, getPosition, 0}},
+ {2719, {wxScrollWinEvent, getOrientation, 0}},
+ {2720, {wxScrollWinEvent, getPosition, 0}},
+ {2721, {wxMouseEvent, altDown, 0}},
+ {2722, {wxMouseEvent, button, 1}},
+ {2723, {wxMouseEvent, buttonDClick, 1}},
+ {2724, {wxMouseEvent, buttonDown, 1}},
+ {2725, {wxMouseEvent, buttonUp, 1}},
+ {2726, {wxMouseEvent, cmdDown, 0}},
+ {2727, {wxMouseEvent, controlDown, 0}},
+ {2728, {wxMouseEvent, dragging, 0}},
+ {2729, {wxMouseEvent, entering, 0}},
+ {2730, {wxMouseEvent, getButton, 0}},
+ {2733, {wxMouseEvent, getPosition, 0}},
+ {2734, {wxMouseEvent, getLogicalPosition, 1}},
+ {2735, {wxMouseEvent, getLinesPerAction, 0}},
+ {2736, {wxMouseEvent, getWheelRotation, 0}},
+ {2737, {wxMouseEvent, getWheelDelta, 0}},
+ {2738, {wxMouseEvent, getX, 0}},
+ {2739, {wxMouseEvent, getY, 0}},
+ {2740, {wxMouseEvent, isButton, 0}},
+ {2741, {wxMouseEvent, isPageScroll, 0}},
+ {2742, {wxMouseEvent, leaving, 0}},
+ {2743, {wxMouseEvent, leftDClick, 0}},
+ {2744, {wxMouseEvent, leftDown, 0}},
+ {2745, {wxMouseEvent, leftIsDown, 0}},
+ {2746, {wxMouseEvent, leftUp, 0}},
+ {2747, {wxMouseEvent, metaDown, 0}},
+ {2748, {wxMouseEvent, middleDClick, 0}},
+ {2749, {wxMouseEvent, middleDown, 0}},
+ {2750, {wxMouseEvent, middleIsDown, 0}},
+ {2751, {wxMouseEvent, middleUp, 0}},
+ {2752, {wxMouseEvent, moving, 0}},
+ {2753, {wxMouseEvent, rightDClick, 0}},
+ {2754, {wxMouseEvent, rightDown, 0}},
+ {2755, {wxMouseEvent, rightIsDown, 0}},
+ {2756, {wxMouseEvent, rightUp, 0}},
+ {2757, {wxMouseEvent, shiftDown, 0}},
+ {2758, {wxSetCursorEvent, getCursor, 0}},
+ {2759, {wxSetCursorEvent, getX, 0}},
+ {2760, {wxSetCursorEvent, getY, 0}},
+ {2761, {wxSetCursorEvent, hasCursor, 0}},
+ {2762, {wxSetCursorEvent, setCursor, 1}},
+ {2763, {wxKeyEvent, altDown, 0}},
+ {2764, {wxKeyEvent, cmdDown, 0}},
+ {2765, {wxKeyEvent, controlDown, 0}},
+ {2766, {wxKeyEvent, getKeyCode, 0}},
+ {2767, {wxKeyEvent, getModifiers, 0}},
+ {2770, {wxKeyEvent, getPosition, 0}},
+ {2771, {wxKeyEvent, getRawKeyCode, 0}},
+ {2772, {wxKeyEvent, getRawKeyFlags, 0}},
+ {2773, {wxKeyEvent, getUnicodeKey, 0}},
+ {2774, {wxKeyEvent, getX, 0}},
+ {2775, {wxKeyEvent, getY, 0}},
+ {2776, {wxKeyEvent, hasModifiers, 0}},
+ {2777, {wxKeyEvent, metaDown, 0}},
+ {2778, {wxKeyEvent, shiftDown, 0}},
+ {2779, {wxSizeEvent, getSize, 0}},
+ {2780, {wxMoveEvent, getPosition, 0}},
+ {2781, {wxEraseEvent, getDC, 0}},
+ {2782, {wxFocusEvent, getWindow, 0}},
+ {2783, {wxChildFocusEvent, getWindow, 0}},
+ {2784, {wxMenuEvent, getMenu, 0}},
+ {2785, {wxMenuEvent, getMenuId, 0}},
+ {2786, {wxMenuEvent, isPopup, 0}},
+ {2787, {wxCloseEvent, canVeto, 0}},
+ {2788, {wxCloseEvent, getLoggingOff, 0}},
+ {2789, {wxCloseEvent, setCanVeto, 1}},
+ {2790, {wxCloseEvent, setLoggingOff, 1}},
+ {2791, {wxCloseEvent, veto, 1}},
+ {2792, {wxShowEvent, setShow, 1}},
+ {2793, {wxShowEvent, getShow, 0}},
+ {2794, {wxIconizeEvent, iconized, 0}},
+ {2795, {wxJoystickEvent, buttonDown, 1}},
+ {2796, {wxJoystickEvent, buttonIsDown, 1}},
+ {2797, {wxJoystickEvent, buttonUp, 1}},
+ {2798, {wxJoystickEvent, getButtonChange, 0}},
+ {2799, {wxJoystickEvent, getButtonState, 0}},
+ {2800, {wxJoystickEvent, getJoystick, 0}},
+ {2801, {wxJoystickEvent, getPosition, 0}},
+ {2802, {wxJoystickEvent, getZPosition, 0}},
+ {2803, {wxJoystickEvent, isButton, 0}},
+ {2804, {wxJoystickEvent, isMove, 0}},
+ {2805, {wxJoystickEvent, isZMove, 0}},
+ {2806, {wxUpdateUIEvent, canUpdate, 1}},
+ {2807, {wxUpdateUIEvent, check, 1}},
+ {2808, {wxUpdateUIEvent, enable, 1}},
+ {2809, {wxUpdateUIEvent, show, 1}},
+ {2810, {wxUpdateUIEvent, getChecked, 0}},
+ {2811, {wxUpdateUIEvent, getEnabled, 0}},
+ {2812, {wxUpdateUIEvent, getShown, 0}},
+ {2813, {wxUpdateUIEvent, getSetChecked, 0}},
+ {2814, {wxUpdateUIEvent, getSetEnabled, 0}},
+ {2815, {wxUpdateUIEvent, getSetShown, 0}},
+ {2816, {wxUpdateUIEvent, getSetText, 0}},
+ {2817, {wxUpdateUIEvent, getText, 0}},
+ {2818, {wxUpdateUIEvent, getMode, 0}},
+ {2819, {wxUpdateUIEvent, getUpdateInterval, 0}},
+ {2820, {wxUpdateUIEvent, resetUpdateTime, 0}},
+ {2821, {wxUpdateUIEvent, setMode, 1}},
+ {2822, {wxUpdateUIEvent, setText, 1}},
+ {2823, {wxUpdateUIEvent, setUpdateInterval, 1}},
+ {2824, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
+ {2825, {wxPaletteChangedEvent, setChangedWindow, 1}},
+ {2826, {wxPaletteChangedEvent, getChangedWindow, 0}},
+ {2827, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
+ {2828, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
+ {2829, {wxNavigationKeyEvent, getDirection, 0}},
+ {2830, {wxNavigationKeyEvent, setDirection, 1}},
+ {2831, {wxNavigationKeyEvent, isWindowChange, 0}},
+ {2832, {wxNavigationKeyEvent, setWindowChange, 1}},
+ {2833, {wxNavigationKeyEvent, isFromTab, 0}},
+ {2834, {wxNavigationKeyEvent, setFromTab, 1}},
+ {2835, {wxNavigationKeyEvent, getCurrentFocus, 0}},
+ {2836, {wxNavigationKeyEvent, setCurrentFocus, 1}},
+ {2837, {wxHelpEvent, getOrigin, 0}},
+ {2838, {wxHelpEvent, getPosition, 0}},
+ {2839, {wxHelpEvent, setOrigin, 1}},
+ {2840, {wxHelpEvent, setPosition, 1}},
+ {2841, {wxContextMenuEvent, getPosition, 0}},
+ {2842, {wxContextMenuEvent, setPosition, 1}},
+ {2843, {wxIdleEvent, canSend, 1}},
+ {2844, {wxIdleEvent, getMode, 0}},
+ {2845, {wxIdleEvent, requestMore, 1}},
+ {2846, {wxIdleEvent, moreRequested, 0}},
+ {2847, {wxIdleEvent, setMode, 1}},
+ {2848, {wxGridEvent, altDown, 0}},
+ {2849, {wxGridEvent, controlDown, 0}},
+ {2850, {wxGridEvent, getCol, 0}},
+ {2851, {wxGridEvent, getPosition, 0}},
+ {2852, {wxGridEvent, getRow, 0}},
+ {2853, {wxGridEvent, metaDown, 0}},
+ {2854, {wxGridEvent, selecting, 0}},
+ {2855, {wxGridEvent, shiftDown, 0}},
+ {2856, {wxNotifyEvent, allow, 0}},
+ {2857, {wxNotifyEvent, isAllowed, 0}},
+ {2858, {wxNotifyEvent, veto, 0}},
+ {2859, {wxSashEvent, getEdge, 0}},
+ {2860, {wxSashEvent, getDragRect, 0}},
+ {2861, {wxSashEvent, getDragStatus, 0}},
+ {2862, {wxListEvent, getCacheFrom, 0}},
+ {2863, {wxListEvent, getCacheTo, 0}},
+ {2864, {wxListEvent, getKeyCode, 0}},
+ {2865, {wxListEvent, getIndex, 0}},
+ {2866, {wxListEvent, getColumn, 0}},
+ {2867, {wxListEvent, getPoint, 0}},
+ {2868, {wxListEvent, getLabel, 0}},
+ {2869, {wxListEvent, getText, 0}},
+ {2870, {wxListEvent, getImage, 0}},
+ {2871, {wxListEvent, getData, 0}},
+ {2872, {wxListEvent, getMask, 0}},
+ {2873, {wxListEvent, getItem, 0}},
+ {2874, {wxListEvent, isEditCancelled, 0}},
+ {2875, {wxDateEvent, getDate, 0}},
+ {2876, {wxCalendarEvent, getWeekDay, 0}},
+ {2877, {wxFileDirPickerEvent, getPath, 0}},
+ {2878, {wxColourPickerEvent, getColour, 0}},
+ {2879, {wxFontPickerEvent, getFont, 0}},
+ {2880, {wxStyledTextEvent, getPosition, 0}},
+ {2881, {wxStyledTextEvent, getKey, 0}},
+ {2882, {wxStyledTextEvent, getModifiers, 0}},
+ {2883, {wxStyledTextEvent, getModificationType, 0}},
+ {2884, {wxStyledTextEvent, getText, 0}},
+ {2885, {wxStyledTextEvent, getLength, 0}},
+ {2886, {wxStyledTextEvent, getLinesAdded, 0}},
+ {2887, {wxStyledTextEvent, getLine, 0}},
+ {2888, {wxStyledTextEvent, getFoldLevelNow, 0}},
+ {2889, {wxStyledTextEvent, getFoldLevelPrev, 0}},
+ {2890, {wxStyledTextEvent, getMargin, 0}},
+ {2891, {wxStyledTextEvent, getMessage, 0}},
+ {2892, {wxStyledTextEvent, getWParam, 0}},
+ {2893, {wxStyledTextEvent, getLParam, 0}},
+ {2894, {wxStyledTextEvent, getListType, 0}},
+ {2895, {wxStyledTextEvent, getX, 0}},
+ {2896, {wxStyledTextEvent, getY, 0}},
+ {2897, {wxStyledTextEvent, getDragText, 0}},
+ {2898, {wxStyledTextEvent, getDragAllowMove, 0}},
+ {2899, {wxStyledTextEvent, getDragResult, 0}},
+ {2900, {wxStyledTextEvent, getShift, 0}},
+ {2901, {wxStyledTextEvent, getControl, 0}},
+ {2902, {wxStyledTextEvent, getAlt, 0}},
+ {2903, {utils, getKeyState, 1}},
+ {2904, {utils, getMousePosition, 2}},
+ {2905, {utils, getMouseState, 0}},
+ {2906, {utils, setDetectableAutoRepeat, 1}},
+ {2907, {utils, bell, 0}},
+ {2908, {utils, findMenuItemId, 3}},
+ {2909, {utils, genericFindWindowAtPoint, 1}},
+ {2910, {utils, findWindowAtPoint, 1}},
+ {2911, {utils, beginBusyCursor, 1}},
+ {2912, {utils, endBusyCursor, 0}},
+ {2913, {utils, isBusy, 0}},
+ {2914, {utils, shutdown, 1}},
+ {2915, {utils, shell, 1}},
+ {2916, {utils, launchDefaultBrowser, 2}},
+ {2917, {utils, getEmailAddress, 0}},
+ {2918, {utils, getUserId, 0}},
+ {2919, {utils, getHomeDir, 0}},
+ {2920, {utils, newId, 0}},
+ {2921, {utils, registerId, 1}},
+ {2922, {utils, getCurrentId, 0}},
+ {2923, {utils, getOsDescription, 0}},
+ {2924, {utils, isPlatformLittleEndian, 0}},
+ {2925, {utils, isPlatform64Bit, 0}},
+ {2926, {wxPrintout, new, 1}},
+ {2927, {wxPrintout, destruct, 0}},
+ {2928, {wxPrintout, getDC, 0}},
+ {2929, {wxPrintout, getPageSizeMM, 2}},
+ {2930, {wxPrintout, getPageSizePixels, 2}},
+ {2931, {wxPrintout, getPaperRectPixels, 0}},
+ {2932, {wxPrintout, getPPIPrinter, 2}},
+ {2933, {wxPrintout, getPPIScreen, 2}},
+ {2934, {wxPrintout, getTitle, 0}},
+ {2935, {wxPrintout, isPreview, 0}},
+ {2936, {wxPrintout, fitThisSizeToPaper, 1}},
+ {2937, {wxPrintout, fitThisSizeToPage, 1}},
+ {2938, {wxPrintout, fitThisSizeToPageMargins, 2}},
+ {2939, {wxPrintout, mapScreenSizeToPaper, 0}},
+ {2940, {wxPrintout, mapScreenSizeToPage, 0}},
+ {2941, {wxPrintout, mapScreenSizeToPageMargins, 1}},
+ {2942, {wxPrintout, mapScreenSizeToDevice, 0}},
+ {2943, {wxPrintout, getLogicalPaperRect, 0}},
+ {2944, {wxPrintout, getLogicalPageRect, 0}},
+ {2945, {wxPrintout, getLogicalPageMarginsRect, 1}},
+ {2946, {wxPrintout, setLogicalOrigin, 2}},
+ {2947, {wxPrintout, offsetLogicalOrigin, 2}},
+ {2948, {wxStyledTextCtrl, new_2, 2}},
+ {2949, {wxStyledTextCtrl, new_0, 0}},
+ {2950, {wxStyledTextCtrl, destruct, 0}},
+ {2951, {wxStyledTextCtrl, create, 2}},
+ {2952, {wxStyledTextCtrl, addText, 1}},
+ {2953, {wxStyledTextCtrl, addStyledText, 1}},
+ {2954, {wxStyledTextCtrl, insertText, 2}},
+ {2955, {wxStyledTextCtrl, clearAll, 0}},
+ {2956, {wxStyledTextCtrl, clearDocumentStyle, 0}},
+ {2957, {wxStyledTextCtrl, getLength, 0}},
+ {2958, {wxStyledTextCtrl, getCharAt, 1}},
+ {2959, {wxStyledTextCtrl, getCurrentPos, 0}},
+ {2960, {wxStyledTextCtrl, getAnchor, 0}},
+ {2961, {wxStyledTextCtrl, getStyleAt, 1}},
+ {2962, {wxStyledTextCtrl, redo, 0}},
+ {2963, {wxStyledTextCtrl, setUndoCollection, 1}},
+ {2964, {wxStyledTextCtrl, selectAll, 0}},
+ {2965, {wxStyledTextCtrl, setSavePoint, 0}},
+ {2966, {wxStyledTextCtrl, getStyledText, 2}},
+ {2967, {wxStyledTextCtrl, canRedo, 0}},
+ {2968, {wxStyledTextCtrl, markerLineFromHandle, 1}},
+ {2969, {wxStyledTextCtrl, markerDeleteHandle, 1}},
+ {2970, {wxStyledTextCtrl, getUndoCollection, 0}},
+ {2971, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
+ {2972, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
+ {2973, {wxStyledTextCtrl, positionFromPoint, 1}},
+ {2974, {wxStyledTextCtrl, positionFromPointClose, 2}},
+ {2975, {wxStyledTextCtrl, gotoLine, 1}},
+ {2976, {wxStyledTextCtrl, gotoPos, 1}},
+ {2977, {wxStyledTextCtrl, setAnchor, 1}},
+ {2978, {wxStyledTextCtrl, getCurLine, 1}},
+ {2979, {wxStyledTextCtrl, getEndStyled, 0}},
+ {2980, {wxStyledTextCtrl, convertEOLs, 1}},
+ {2981, {wxStyledTextCtrl, getEOLMode, 0}},
+ {2982, {wxStyledTextCtrl, setEOLMode, 1}},
+ {2983, {wxStyledTextCtrl, startStyling, 2}},
+ {2984, {wxStyledTextCtrl, setStyling, 2}},
+ {2985, {wxStyledTextCtrl, getBufferedDraw, 0}},
+ {2986, {wxStyledTextCtrl, setBufferedDraw, 1}},
+ {2987, {wxStyledTextCtrl, setTabWidth, 1}},
+ {2988, {wxStyledTextCtrl, getTabWidth, 0}},
+ {2989, {wxStyledTextCtrl, setCodePage, 1}},
+ {2990, {wxStyledTextCtrl, markerDefine, 3}},
+ {2991, {wxStyledTextCtrl, markerSetForeground, 2}},
+ {2992, {wxStyledTextCtrl, markerSetBackground, 2}},
+ {2993, {wxStyledTextCtrl, markerAdd, 2}},
+ {2994, {wxStyledTextCtrl, markerDelete, 2}},
+ {2995, {wxStyledTextCtrl, markerDeleteAll, 1}},
+ {2996, {wxStyledTextCtrl, markerGet, 1}},
+ {2997, {wxStyledTextCtrl, markerNext, 2}},
+ {2998, {wxStyledTextCtrl, markerPrevious, 2}},
+ {2999, {wxStyledTextCtrl, markerDefineBitmap, 2}},
+ {3000, {wxStyledTextCtrl, markerAddSet, 2}},
+ {3001, {wxStyledTextCtrl, markerSetAlpha, 2}},
+ {3002, {wxStyledTextCtrl, setMarginType, 2}},
+ {3003, {wxStyledTextCtrl, getMarginType, 1}},
+ {3004, {wxStyledTextCtrl, setMarginWidth, 2}},
+ {3005, {wxStyledTextCtrl, getMarginWidth, 1}},
+ {3006, {wxStyledTextCtrl, setMarginMask, 2}},
+ {3007, {wxStyledTextCtrl, getMarginMask, 1}},
+ {3008, {wxStyledTextCtrl, setMarginSensitive, 2}},
+ {3009, {wxStyledTextCtrl, getMarginSensitive, 1}},
+ {3010, {wxStyledTextCtrl, styleClearAll, 0}},
+ {3011, {wxStyledTextCtrl, styleSetForeground, 2}},
+ {3012, {wxStyledTextCtrl, styleSetBackground, 2}},
+ {3013, {wxStyledTextCtrl, styleSetBold, 2}},
+ {3014, {wxStyledTextCtrl, styleSetItalic, 2}},
+ {3015, {wxStyledTextCtrl, styleSetSize, 2}},
+ {3016, {wxStyledTextCtrl, styleSetFaceName, 2}},
+ {3017, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
+ {3018, {wxStyledTextCtrl, styleResetDefault, 0}},
+ {3019, {wxStyledTextCtrl, styleSetUnderline, 2}},
+ {3020, {wxStyledTextCtrl, styleSetCase, 2}},
+ {3021, {wxStyledTextCtrl, styleSetHotSpot, 2}},
+ {3022, {wxStyledTextCtrl, setSelForeground, 2}},
+ {3023, {wxStyledTextCtrl, setSelBackground, 2}},
+ {3024, {wxStyledTextCtrl, getSelAlpha, 0}},
+ {3025, {wxStyledTextCtrl, setSelAlpha, 1}},
+ {3026, {wxStyledTextCtrl, setCaretForeground, 1}},
+ {3027, {wxStyledTextCtrl, cmdKeyAssign, 3}},
+ {3028, {wxStyledTextCtrl, cmdKeyClear, 2}},
+ {3029, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
+ {3030, {wxStyledTextCtrl, setStyleBytes, 2}},
+ {3031, {wxStyledTextCtrl, styleSetVisible, 2}},
+ {3032, {wxStyledTextCtrl, getCaretPeriod, 0}},
+ {3033, {wxStyledTextCtrl, setCaretPeriod, 1}},
+ {3034, {wxStyledTextCtrl, setWordChars, 1}},
+ {3035, {wxStyledTextCtrl, beginUndoAction, 0}},
+ {3036, {wxStyledTextCtrl, endUndoAction, 0}},
+ {3037, {wxStyledTextCtrl, indicatorSetStyle, 2}},
+ {3038, {wxStyledTextCtrl, indicatorGetStyle, 1}},
+ {3039, {wxStyledTextCtrl, indicatorSetForeground, 2}},
+ {3040, {wxStyledTextCtrl, indicatorGetForeground, 1}},
+ {3041, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
+ {3042, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
+ {3043, {wxStyledTextCtrl, getStyleBits, 0}},
+ {3044, {wxStyledTextCtrl, setLineState, 2}},
+ {3045, {wxStyledTextCtrl, getLineState, 1}},
+ {3046, {wxStyledTextCtrl, getMaxLineState, 0}},
+ {3047, {wxStyledTextCtrl, getCaretLineVisible, 0}},
+ {3048, {wxStyledTextCtrl, setCaretLineVisible, 1}},
+ {3049, {wxStyledTextCtrl, getCaretLineBackground, 0}},
+ {3050, {wxStyledTextCtrl, setCaretLineBackground, 1}},
+ {3051, {wxStyledTextCtrl, autoCompShow, 2}},
+ {3052, {wxStyledTextCtrl, autoCompCancel, 0}},
+ {3053, {wxStyledTextCtrl, autoCompActive, 0}},
+ {3054, {wxStyledTextCtrl, autoCompPosStart, 0}},
+ {3055, {wxStyledTextCtrl, autoCompComplete, 0}},
+ {3056, {wxStyledTextCtrl, autoCompStops, 1}},
+ {3057, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
+ {3058, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
+ {3059, {wxStyledTextCtrl, autoCompSelect, 1}},
+ {3060, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
+ {3061, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
+ {3062, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
+ {3063, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
+ {3064, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
+ {3065, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
+ {3066, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
+ {3067, {wxStyledTextCtrl, userListShow, 2}},
+ {3068, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
+ {3069, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
+ {3070, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
+ {3071, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
+ {3072, {wxStyledTextCtrl, registerImage, 2}},
+ {3073, {wxStyledTextCtrl, clearRegisteredImages, 0}},
+ {3074, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
+ {3075, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
+ {3076, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
+ {3077, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
+ {3078, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
+ {3079, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
+ {3080, {wxStyledTextCtrl, setIndent, 1}},
+ {3081, {wxStyledTextCtrl, getIndent, 0}},
+ {3082, {wxStyledTextCtrl, setUseTabs, 1}},
+ {3083, {wxStyledTextCtrl, getUseTabs, 0}},
+ {3084, {wxStyledTextCtrl, setLineIndentation, 2}},
+ {3085, {wxStyledTextCtrl, getLineIndentation, 1}},
+ {3086, {wxStyledTextCtrl, getLineIndentPosition, 1}},
+ {3087, {wxStyledTextCtrl, getColumn, 1}},
+ {3088, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
+ {3089, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
+ {3090, {wxStyledTextCtrl, setIndentationGuides, 1}},
+ {3091, {wxStyledTextCtrl, getIndentationGuides, 0}},
+ {3092, {wxStyledTextCtrl, setHighlightGuide, 1}},
+ {3093, {wxStyledTextCtrl, getHighlightGuide, 0}},
+ {3094, {wxStyledTextCtrl, getLineEndPosition, 1}},
+ {3095, {wxStyledTextCtrl, getCodePage, 0}},
+ {3096, {wxStyledTextCtrl, getCaretForeground, 0}},
+ {3097, {wxStyledTextCtrl, getReadOnly, 0}},
+ {3098, {wxStyledTextCtrl, setCurrentPos, 1}},
+ {3099, {wxStyledTextCtrl, setSelectionStart, 1}},
+ {3100, {wxStyledTextCtrl, getSelectionStart, 0}},
+ {3101, {wxStyledTextCtrl, setSelectionEnd, 1}},
+ {3102, {wxStyledTextCtrl, getSelectionEnd, 0}},
+ {3103, {wxStyledTextCtrl, setPrintMagnification, 1}},
+ {3104, {wxStyledTextCtrl, getPrintMagnification, 0}},
+ {3105, {wxStyledTextCtrl, setPrintColourMode, 1}},
+ {3106, {wxStyledTextCtrl, getPrintColourMode, 0}},
+ {3107, {wxStyledTextCtrl, findText, 4}},
+ {3108, {wxStyledTextCtrl, formatRange, 7}},
+ {3109, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
+ {3110, {wxStyledTextCtrl, getLine, 1}},
+ {3111, {wxStyledTextCtrl, getLineCount, 0}},
+ {3112, {wxStyledTextCtrl, setMarginLeft, 1}},
+ {3113, {wxStyledTextCtrl, getMarginLeft, 0}},
+ {3114, {wxStyledTextCtrl, setMarginRight, 1}},
+ {3115, {wxStyledTextCtrl, getMarginRight, 0}},
+ {3116, {wxStyledTextCtrl, getModify, 0}},
+ {3117, {wxStyledTextCtrl, setSelection, 2}},
+ {3118, {wxStyledTextCtrl, getSelectedText, 0}},
+ {3119, {wxStyledTextCtrl, getTextRange, 2}},
+ {3120, {wxStyledTextCtrl, hideSelection, 1}},
+ {3121, {wxStyledTextCtrl, lineFromPosition, 1}},
+ {3122, {wxStyledTextCtrl, positionFromLine, 1}},
+ {3123, {wxStyledTextCtrl, lineScroll, 2}},
+ {3124, {wxStyledTextCtrl, ensureCaretVisible, 0}},
+ {3125, {wxStyledTextCtrl, replaceSelection, 1}},
+ {3126, {wxStyledTextCtrl, setReadOnly, 1}},
+ {3127, {wxStyledTextCtrl, canPaste, 0}},
+ {3128, {wxStyledTextCtrl, canUndo, 0}},
+ {3129, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
+ {3130, {wxStyledTextCtrl, undo, 0}},
+ {3131, {wxStyledTextCtrl, cut, 0}},
+ {3132, {wxStyledTextCtrl, copy, 0}},
+ {3133, {wxStyledTextCtrl, paste, 0}},
+ {3134, {wxStyledTextCtrl, clear, 0}},
+ {3135, {wxStyledTextCtrl, setText, 1}},
+ {3136, {wxStyledTextCtrl, getText, 0}},
+ {3137, {wxStyledTextCtrl, getTextLength, 0}},
+ {3138, {wxStyledTextCtrl, getOvertype, 0}},
+ {3139, {wxStyledTextCtrl, setCaretWidth, 1}},
+ {3140, {wxStyledTextCtrl, getCaretWidth, 0}},
+ {3141, {wxStyledTextCtrl, setTargetStart, 1}},
+ {3142, {wxStyledTextCtrl, getTargetStart, 0}},
+ {3143, {wxStyledTextCtrl, setTargetEnd, 1}},
+ {3144, {wxStyledTextCtrl, getTargetEnd, 0}},
+ {3145, {wxStyledTextCtrl, replaceTarget, 1}},
+ {3146, {wxStyledTextCtrl, searchInTarget, 1}},
+ {3147, {wxStyledTextCtrl, setSearchFlags, 1}},
+ {3148, {wxStyledTextCtrl, getSearchFlags, 0}},
+ {3149, {wxStyledTextCtrl, callTipShow, 2}},
+ {3150, {wxStyledTextCtrl, callTipCancel, 0}},
+ {3151, {wxStyledTextCtrl, callTipActive, 0}},
+ {3152, {wxStyledTextCtrl, callTipPosAtStart, 0}},
+ {3153, {wxStyledTextCtrl, callTipSetHighlight, 2}},
+ {3154, {wxStyledTextCtrl, callTipSetBackground, 1}},
+ {3155, {wxStyledTextCtrl, callTipSetForeground, 1}},
+ {3156, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
+ {3157, {wxStyledTextCtrl, callTipUseStyle, 1}},
+ {3158, {wxStyledTextCtrl, visibleFromDocLine, 1}},
+ {3159, {wxStyledTextCtrl, docLineFromVisible, 1}},
+ {3160, {wxStyledTextCtrl, wrapCount, 1}},
+ {3161, {wxStyledTextCtrl, setFoldLevel, 2}},
+ {3162, {wxStyledTextCtrl, getFoldLevel, 1}},
+ {3163, {wxStyledTextCtrl, getLastChild, 2}},
+ {3164, {wxStyledTextCtrl, getFoldParent, 1}},
+ {3165, {wxStyledTextCtrl, showLines, 2}},
+ {3166, {wxStyledTextCtrl, hideLines, 2}},
+ {3167, {wxStyledTextCtrl, getLineVisible, 1}},
+ {3168, {wxStyledTextCtrl, setFoldExpanded, 2}},
+ {3169, {wxStyledTextCtrl, getFoldExpanded, 1}},
+ {3170, {wxStyledTextCtrl, toggleFold, 1}},
+ {3171, {wxStyledTextCtrl, ensureVisible, 1}},
+ {3172, {wxStyledTextCtrl, setFoldFlags, 1}},
+ {3173, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
+ {3174, {wxStyledTextCtrl, setTabIndents, 1}},
+ {3175, {wxStyledTextCtrl, getTabIndents, 0}},
+ {3176, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
+ {3177, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
+ {3178, {wxStyledTextCtrl, setMouseDwellTime, 1}},
+ {3179, {wxStyledTextCtrl, getMouseDwellTime, 0}},
+ {3180, {wxStyledTextCtrl, wordStartPosition, 2}},
+ {3181, {wxStyledTextCtrl, wordEndPosition, 2}},
+ {3182, {wxStyledTextCtrl, setWrapMode, 1}},
+ {3183, {wxStyledTextCtrl, getWrapMode, 0}},
+ {3184, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
+ {3185, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
+ {3186, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
+ {3187, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
+ {3188, {wxStyledTextCtrl, setWrapStartIndent, 1}},
+ {3189, {wxStyledTextCtrl, getWrapStartIndent, 0}},
+ {3190, {wxStyledTextCtrl, setLayoutCache, 1}},
+ {3191, {wxStyledTextCtrl, getLayoutCache, 0}},
+ {3192, {wxStyledTextCtrl, setScrollWidth, 1}},
+ {3193, {wxStyledTextCtrl, getScrollWidth, 0}},
+ {3194, {wxStyledTextCtrl, textWidth, 2}},
+ {3195, {wxStyledTextCtrl, getEndAtLastLine, 0}},
+ {3196, {wxStyledTextCtrl, textHeight, 1}},
+ {3197, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
+ {3198, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
+ {3199, {wxStyledTextCtrl, appendText, 1}},
+ {3200, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
+ {3201, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
+ {3202, {wxStyledTextCtrl, targetFromSelection, 0}},
+ {3203, {wxStyledTextCtrl, linesJoin, 0}},
+ {3204, {wxStyledTextCtrl, linesSplit, 1}},
+ {3205, {wxStyledTextCtrl, setFoldMarginColour, 2}},
+ {3206, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
+ {3207, {wxStyledTextCtrl, lineDown, 0}},
+ {3208, {wxStyledTextCtrl, lineDownExtend, 0}},
+ {3209, {wxStyledTextCtrl, lineUp, 0}},
+ {3210, {wxStyledTextCtrl, lineUpExtend, 0}},
+ {3211, {wxStyledTextCtrl, charLeft, 0}},
+ {3212, {wxStyledTextCtrl, charLeftExtend, 0}},
+ {3213, {wxStyledTextCtrl, charRight, 0}},
+ {3214, {wxStyledTextCtrl, charRightExtend, 0}},
+ {3215, {wxStyledTextCtrl, wordLeft, 0}},
+ {3216, {wxStyledTextCtrl, wordLeftExtend, 0}},
+ {3217, {wxStyledTextCtrl, wordRight, 0}},
+ {3218, {wxStyledTextCtrl, wordRightExtend, 0}},
+ {3219, {wxStyledTextCtrl, home, 0}},
+ {3220, {wxStyledTextCtrl, homeExtend, 0}},
+ {3221, {wxStyledTextCtrl, lineEnd, 0}},
+ {3222, {wxStyledTextCtrl, lineEndExtend, 0}},
+ {3223, {wxStyledTextCtrl, documentStart, 0}},
+ {3224, {wxStyledTextCtrl, documentStartExtend, 0}},
+ {3225, {wxStyledTextCtrl, documentEnd, 0}},
+ {3226, {wxStyledTextCtrl, documentEndExtend, 0}},
+ {3227, {wxStyledTextCtrl, pageUp, 0}},
+ {3228, {wxStyledTextCtrl, pageUpExtend, 0}},
+ {3229, {wxStyledTextCtrl, pageDown, 0}},
+ {3230, {wxStyledTextCtrl, pageDownExtend, 0}},
+ {3231, {wxStyledTextCtrl, editToggleOvertype, 0}},
+ {3232, {wxStyledTextCtrl, cancel, 0}},
+ {3233, {wxStyledTextCtrl, deleteBack, 0}},
+ {3234, {wxStyledTextCtrl, tab, 0}},
+ {3235, {wxStyledTextCtrl, backTab, 0}},
+ {3236, {wxStyledTextCtrl, newLine, 0}},
+ {3237, {wxStyledTextCtrl, formFeed, 0}},
+ {3238, {wxStyledTextCtrl, vCHome, 0}},
+ {3239, {wxStyledTextCtrl, vCHomeExtend, 0}},
+ {3240, {wxStyledTextCtrl, zoomIn, 0}},
+ {3241, {wxStyledTextCtrl, zoomOut, 0}},
+ {3242, {wxStyledTextCtrl, delWordLeft, 0}},
+ {3243, {wxStyledTextCtrl, delWordRight, 0}},
+ {3244, {wxStyledTextCtrl, lineCut, 0}},
+ {3245, {wxStyledTextCtrl, lineDelete, 0}},
+ {3246, {wxStyledTextCtrl, lineTranspose, 0}},
+ {3247, {wxStyledTextCtrl, lineDuplicate, 0}},
+ {3248, {wxStyledTextCtrl, lowerCase, 0}},
+ {3249, {wxStyledTextCtrl, upperCase, 0}},
+ {3250, {wxStyledTextCtrl, lineScrollDown, 0}},
+ {3251, {wxStyledTextCtrl, lineScrollUp, 0}},
+ {3252, {wxStyledTextCtrl, deleteBackNotLine, 0}},
+ {3253, {wxStyledTextCtrl, homeDisplay, 0}},
+ {3254, {wxStyledTextCtrl, homeDisplayExtend, 0}},
+ {3255, {wxStyledTextCtrl, lineEndDisplay, 0}},
+ {3256, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
+ {3257, {wxStyledTextCtrl, homeWrapExtend, 0}},
+ {3258, {wxStyledTextCtrl, lineEndWrap, 0}},
+ {3259, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
+ {3260, {wxStyledTextCtrl, vCHomeWrap, 0}},
+ {3261, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
+ {3262, {wxStyledTextCtrl, lineCopy, 0}},
+ {3263, {wxStyledTextCtrl, moveCaretInsideView, 0}},
+ {3264, {wxStyledTextCtrl, lineLength, 1}},
+ {3265, {wxStyledTextCtrl, braceHighlight, 2}},
+ {3266, {wxStyledTextCtrl, braceBadLight, 1}},
+ {3267, {wxStyledTextCtrl, braceMatch, 1}},
+ {3268, {wxStyledTextCtrl, getViewEOL, 0}},
+ {3269, {wxStyledTextCtrl, setViewEOL, 1}},
+ {3270, {wxStyledTextCtrl, setModEventMask, 1}},
+ {3271, {wxStyledTextCtrl, getEdgeColumn, 0}},
+ {3272, {wxStyledTextCtrl, setEdgeColumn, 1}},
+ {3273, {wxStyledTextCtrl, setEdgeMode, 1}},
+ {3274, {wxStyledTextCtrl, getEdgeMode, 0}},
+ {3275, {wxStyledTextCtrl, getEdgeColour, 0}},
+ {3276, {wxStyledTextCtrl, setEdgeColour, 1}},
+ {3277, {wxStyledTextCtrl, searchAnchor, 0}},
+ {3278, {wxStyledTextCtrl, searchNext, 2}},
+ {3279, {wxStyledTextCtrl, searchPrev, 2}},
+ {3280, {wxStyledTextCtrl, linesOnScreen, 0}},
+ {3281, {wxStyledTextCtrl, usePopUp, 1}},
+ {3282, {wxStyledTextCtrl, selectionIsRectangle, 0}},
+ {3283, {wxStyledTextCtrl, setZoom, 1}},
+ {3284, {wxStyledTextCtrl, getZoom, 0}},
+ {3285, {wxStyledTextCtrl, getModEventMask, 0}},
+ {3286, {wxStyledTextCtrl, setSTCFocus, 1}},
+ {3287, {wxStyledTextCtrl, getSTCFocus, 0}},
+ {3288, {wxStyledTextCtrl, setStatus, 1}},
+ {3289, {wxStyledTextCtrl, getStatus, 0}},
+ {3290, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
+ {3291, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
+ {3292, {wxStyledTextCtrl, setSTCCursor, 1}},
+ {3293, {wxStyledTextCtrl, getSTCCursor, 0}},
+ {3294, {wxStyledTextCtrl, setControlCharSymbol, 1}},
+ {3295, {wxStyledTextCtrl, getControlCharSymbol, 0}},
+ {3296, {wxStyledTextCtrl, wordPartLeft, 0}},
+ {3297, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
+ {3298, {wxStyledTextCtrl, wordPartRight, 0}},
+ {3299, {wxStyledTextCtrl, wordPartRightExtend, 0}},
+ {3300, {wxStyledTextCtrl, setVisiblePolicy, 2}},
+ {3301, {wxStyledTextCtrl, delLineLeft, 0}},
+ {3302, {wxStyledTextCtrl, delLineRight, 0}},
+ {3303, {wxStyledTextCtrl, getXOffset, 0}},
+ {3304, {wxStyledTextCtrl, chooseCaretX, 0}},
+ {3305, {wxStyledTextCtrl, setXCaretPolicy, 2}},
+ {3306, {wxStyledTextCtrl, setYCaretPolicy, 2}},
+ {3307, {wxStyledTextCtrl, getPrintWrapMode, 0}},
+ {3308, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
+ {3309, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
+ {3310, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
+ {3311, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
+ {3312, {wxStyledTextCtrl, paraDownExtend, 0}},
+ {3313, {wxStyledTextCtrl, paraUp, 0}},
+ {3314, {wxStyledTextCtrl, paraUpExtend, 0}},
+ {3315, {wxStyledTextCtrl, positionBefore, 1}},
+ {3316, {wxStyledTextCtrl, positionAfter, 1}},
+ {3317, {wxStyledTextCtrl, copyRange, 2}},
+ {3318, {wxStyledTextCtrl, copyText, 2}},
+ {3319, {wxStyledTextCtrl, setSelectionMode, 1}},
+ {3320, {wxStyledTextCtrl, getSelectionMode, 0}},
+ {3321, {wxStyledTextCtrl, lineDownRectExtend, 0}},
+ {3322, {wxStyledTextCtrl, lineUpRectExtend, 0}},
+ {3323, {wxStyledTextCtrl, charLeftRectExtend, 0}},
+ {3324, {wxStyledTextCtrl, charRightRectExtend, 0}},
+ {3325, {wxStyledTextCtrl, homeRectExtend, 0}},
+ {3326, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
+ {3327, {wxStyledTextCtrl, lineEndRectExtend, 0}},
+ {3328, {wxStyledTextCtrl, pageUpRectExtend, 0}},
+ {3329, {wxStyledTextCtrl, pageDownRectExtend, 0}},
+ {3330, {wxStyledTextCtrl, stutteredPageUp, 0}},
+ {3331, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
+ {3332, {wxStyledTextCtrl, stutteredPageDown, 0}},
+ {3333, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
+ {3334, {wxStyledTextCtrl, wordLeftEnd, 0}},
+ {3335, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
+ {3336, {wxStyledTextCtrl, wordRightEnd, 0}},
+ {3337, {wxStyledTextCtrl, wordRightEndExtend, 0}},
+ {3338, {wxStyledTextCtrl, setWhitespaceChars, 1}},
+ {3339, {wxStyledTextCtrl, setCharsDefault, 0}},
+ {3340, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
+ {3341, {wxStyledTextCtrl, allocate, 1}},
+ {3342, {wxStyledTextCtrl, findColumn, 2}},
+ {3343, {wxStyledTextCtrl, getCaretSticky, 0}},
+ {3344, {wxStyledTextCtrl, setCaretSticky, 1}},
+ {3345, {wxStyledTextCtrl, toggleCaretSticky, 0}},
+ {3346, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
+ {3347, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
+ {3348, {wxStyledTextCtrl, selectionDuplicate, 0}},
+ {3349, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
+ {3350, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
+ {3351, {wxStyledTextCtrl, startRecord, 0}},
+ {3352, {wxStyledTextCtrl, stopRecord, 0}},
+ {3353, {wxStyledTextCtrl, setLexer, 1}},
+ {3354, {wxStyledTextCtrl, getLexer, 0}},
+ {3355, {wxStyledTextCtrl, colourise, 2}},
+ {3356, {wxStyledTextCtrl, setProperty, 2}},
+ {3357, {wxStyledTextCtrl, setKeyWords, 2}},
+ {3358, {wxStyledTextCtrl, setLexerLanguage, 1}},
+ {3359, {wxStyledTextCtrl, getProperty, 1}},
+ {3360, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
+ {3361, {wxStyledTextCtrl, getCurrentLine, 0}},
+ {3362, {wxStyledTextCtrl, styleSetSpec, 2}},
+ {3363, {wxStyledTextCtrl, styleSetFont, 2}},
+ {3364, {wxStyledTextCtrl, styleSetFontAttr, 7}},
+ {3365, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
+ {3366, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
+ {3367, {wxStyledTextCtrl, cmdKeyExecute, 1}},
+ {3368, {wxStyledTextCtrl, setMargins, 2}},
+ {3369, {wxStyledTextCtrl, getSelection, 2}},
+ {3370, {wxStyledTextCtrl, pointFromPosition, 1}},
+ {3371, {wxStyledTextCtrl, scrollToLine, 1}},
+ {3372, {wxStyledTextCtrl, scrollToColumn, 1}},
+ {3373, {wxStyledTextCtrl, sendMsg, 2}},
+ {3374, {wxStyledTextCtrl, setVScrollBar, 1}},
+ {3375, {wxStyledTextCtrl, setHScrollBar, 1}},
+ {3376, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
+ {3377, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
+ {3378, {wxStyledTextCtrl, saveFile, 1}},
+ {3379, {wxStyledTextCtrl, loadFile, 1}},
+ {3380, {wxStyledTextCtrl, doDragOver, 3}},
+ {3381, {wxStyledTextCtrl, doDropText, 3}},
+ {3382, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
+ {3383, {wxStyledTextCtrl, addTextRaw, 1}},
+ {3384, {wxStyledTextCtrl, insertTextRaw, 2}},
+ {3385, {wxStyledTextCtrl, getCurLineRaw, 1}},
+ {3386, {wxStyledTextCtrl, getLineRaw, 1}},
+ {3387, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
+ {3388, {wxStyledTextCtrl, getTextRangeRaw, 2}},
+ {3389, {wxStyledTextCtrl, setTextRaw, 1}},
+ {3390, {wxStyledTextCtrl, getTextRaw, 0}},
+ {3391, {wxStyledTextCtrl, appendTextRaw, 1}},
+ {3392, {wxArtProvider, getBitmap, 2}},
+ {3393, {wxArtProvider, getIcon, 2}},
+ {3394, {wxTreeEvent, getKeyCode, 0}},
+ {3395, {wxTreeEvent, getItem, 0}},
+ {3396, {wxTreeEvent, getKeyEvent, 0}},
+ {3397, {wxTreeEvent, getLabel, 0}},
+ {3398, {wxTreeEvent, getOldItem, 0}},
+ {3399, {wxTreeEvent, getPoint, 0}},
+ {3400, {wxTreeEvent, isEditCancelled, 0}},
+ {3401, {wxTreeEvent, setToolTip, 1}},
+ {3402, {wxNotebookEvent, getOldSelection, 0}},
+ {3403, {wxNotebookEvent, getSelection, 0}},
+ {3404, {wxNotebookEvent, setOldSelection, 1}},
+ {3405, {wxNotebookEvent, setSelection, 1}},
+ {3406, {wxFileDataObject, new, 0}},
+ {3407, {wxFileDataObject, addFile, 1}},
+ {3408, {wxFileDataObject, getFilenames, 0}},
+ {3409, {wxFileDataObject, 'Destroy', undefined}},
+ {3410, {wxTextDataObject, new, 1}},
+ {3411, {wxTextDataObject, getTextLength, 0}},
+ {3412, {wxTextDataObject, getText, 0}},
+ {3413, {wxTextDataObject, setText, 1}},
+ {3414, {wxTextDataObject, 'Destroy', undefined}},
+ {3415, {wxBitmapDataObject, new_1_1, 1}},
+ {3416, {wxBitmapDataObject, new_1_0, 1}},
+ {3417, {wxBitmapDataObject, getBitmap, 0}},
+ {3418, {wxBitmapDataObject, setBitmap, 1}},
+ {3419, {wxBitmapDataObject, 'Destroy', undefined}},
+ {3421, {wxClipboard, new, 0}},
+ {3422, {wxClipboard, destruct, 0}},
+ {3423, {wxClipboard, addData, 1}},
+ {3424, {wxClipboard, clear, 0}},
+ {3425, {wxClipboard, close, 0}},
+ {3426, {wxClipboard, flush, 0}},
+ {3427, {wxClipboard, getData, 1}},
+ {3428, {wxClipboard, isOpened, 0}},
+ {3429, {wxClipboard, open, 0}},
+ {3430, {wxClipboard, setData, 1}},
+ {3432, {wxClipboard, usePrimarySelection, 1}},
+ {3433, {wxClipboard, isSupported, 1}},
+ {3434, {wxClipboard, get, 0}},
+ {3435, {wxSpinEvent, getPosition, 0}},
+ {3436, {wxSpinEvent, setPosition, 1}},
+ {3437, {wxSplitterWindow, new_0, 0}},
+ {3438, {wxSplitterWindow, new_2, 2}},
+ {3439, {wxSplitterWindow, destruct, 0}},
+ {3440, {wxSplitterWindow, create, 2}},
+ {3441, {wxSplitterWindow, getMinimumPaneSize, 0}},
+ {3442, {wxSplitterWindow, getSashGravity, 0}},
+ {3443, {wxSplitterWindow, getSashPosition, 0}},
+ {3444, {wxSplitterWindow, getSplitMode, 0}},
+ {3445, {wxSplitterWindow, getWindow1, 0}},
+ {3446, {wxSplitterWindow, getWindow2, 0}},
+ {3447, {wxSplitterWindow, initialize, 1}},
+ {3448, {wxSplitterWindow, isSplit, 0}},
+ {3449, {wxSplitterWindow, replaceWindow, 2}},
+ {3450, {wxSplitterWindow, setSashGravity, 1}},
+ {3451, {wxSplitterWindow, setSashPosition, 2}},
+ {3452, {wxSplitterWindow, setSashSize, 1}},
+ {3453, {wxSplitterWindow, setMinimumPaneSize, 1}},
+ {3454, {wxSplitterWindow, setSplitMode, 1}},
+ {3455, {wxSplitterWindow, splitHorizontally, 3}},
+ {3456, {wxSplitterWindow, splitVertically, 3}},
+ {3457, {wxSplitterWindow, unsplit, 1}},
+ {3458, {wxSplitterWindow, updateSize, 0}},
+ {3459, {wxSplitterEvent, getSashPosition, 0}},
+ {3460, {wxSplitterEvent, getX, 0}},
+ {3461, {wxSplitterEvent, getY, 0}},
+ {3462, {wxSplitterEvent, getWindowBeingRemoved, 0}},
+ {3463, {wxSplitterEvent, setSashPosition, 1}},
+ {3464, {wxHtmlWindow, new_0, 0}},
+ {3465, {wxHtmlWindow, new_2, 2}},
+ {3466, {wxHtmlWindow, appendToPage, 1}},
+ {3467, {wxHtmlWindow, getOpenedAnchor, 0}},
+ {3468, {wxHtmlWindow, getOpenedPage, 0}},
+ {3469, {wxHtmlWindow, getOpenedPageTitle, 0}},
+ {3470, {wxHtmlWindow, getRelatedFrame, 0}},
+ {3471, {wxHtmlWindow, historyBack, 0}},
+ {3472, {wxHtmlWindow, historyCanBack, 0}},
+ {3473, {wxHtmlWindow, historyCanForward, 0}},
+ {3474, {wxHtmlWindow, historyClear, 0}},
+ {3475, {wxHtmlWindow, historyForward, 0}},
+ {3476, {wxHtmlWindow, loadFile, 1}},
+ {3477, {wxHtmlWindow, loadPage, 1}},
+ {3478, {wxHtmlWindow, selectAll, 0}},
+ {3479, {wxHtmlWindow, selectionToText, 0}},
+ {3480, {wxHtmlWindow, selectLine, 1}},
+ {3481, {wxHtmlWindow, selectWord, 1}},
+ {3482, {wxHtmlWindow, setBorders, 1}},
+ {3483, {wxHtmlWindow, setFonts, 3}},
+ {3484, {wxHtmlWindow, setPage, 1}},
+ {3485, {wxHtmlWindow, setRelatedFrame, 2}},
+ {3486, {wxHtmlWindow, setRelatedStatusBar, 1}},
+ {3487, {wxHtmlWindow, toText, 0}},
+ {3488, {wxHtmlWindow, 'Destroy', undefined}},
+ {3489, {wxHtmlLinkEvent, getLinkInfo, 0}},
+ {3490, {wxSystemSettings, getColour, 1}},
+ {3491, {wxSystemSettings, getFont, 1}},
+ {3492, {wxSystemSettings, getMetric, 2}},
+ {3493, {wxSystemSettings, getScreenType, 0}},
+ {3494, {wxSystemOptions, getOption, 1}},
+ {3495, {wxSystemOptions, getOptionInt, 1}},
+ {3496, {wxSystemOptions, hasOption, 1}},
+ {3497, {wxSystemOptions, isFalse, 1}},
+ {3498, {wxSystemOptions, setOption_2_1, 2}},
+ {3499, {wxSystemOptions, setOption_2_0, 2}},
+ {3500, {wxAuiNotebookEvent, setSelection, 1}},
+ {3501, {wxAuiNotebookEvent, getSelection, 0}},
+ {3502, {wxAuiNotebookEvent, setOldSelection, 1}},
+ {3503, {wxAuiNotebookEvent, getOldSelection, 0}},
+ {3504, {wxAuiNotebookEvent, setDragSource, 1}},
+ {3505, {wxAuiNotebookEvent, getDragSource, 0}},
+ {3506, {wxAuiManagerEvent, setManager, 1}},
+ {3507, {wxAuiManagerEvent, getManager, 0}},
+ {3508, {wxAuiManagerEvent, setPane, 1}},
+ {3509, {wxAuiManagerEvent, getPane, 0}},
+ {3510, {wxAuiManagerEvent, setButton, 1}},
+ {3511, {wxAuiManagerEvent, getButton, 0}},
+ {3512, {wxAuiManagerEvent, setDC, 1}},
+ {3513, {wxAuiManagerEvent, getDC, 0}},
+ {3514, {wxAuiManagerEvent, veto, 1}},
+ {3515, {wxAuiManagerEvent, getVeto, 0}},
+ {3516, {wxAuiManagerEvent, setCanVeto, 1}},
+ {3517, {wxAuiManagerEvent, canVeto, 0}},
+ {3518, {wxLogNull, new, 0}},
+ {3519, {wxLogNull, 'Destroy', undefined}},
+ {3520, {wxTaskBarIcon, new, 0}},
+ {3521, {wxTaskBarIcon, destruct, 0}},
+ {3522, {wxTaskBarIcon, popupMenu, 1}},
+ {3523, {wxTaskBarIcon, removeIcon, 0}},
+ {3524, {wxTaskBarIcon, setIcon, 2}},
{-1, {mod, func, -1}}
].
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index af74caaa25..fe35cb1374 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -561,2732 +561,2743 @@
-define(wxDC_GetCharHeight, 663).
-define(wxDC_GetCharWidth, 664).
-define(wxDC_GetClippingBox, 665).
--define(wxDC_GetFont, 666).
--define(wxDC_GetLayoutDirection, 667).
--define(wxDC_GetLogicalFunction, 668).
--define(wxDC_GetMapMode, 669).
--define(wxDC_GetMultiLineTextExtent_4, 670).
--define(wxDC_GetMultiLineTextExtent_1, 671).
--define(wxDC_GetPartialTextExtents, 672).
--define(wxDC_GetPen, 673).
--define(wxDC_GetPixel, 674).
--define(wxDC_GetPPI, 675).
--define(wxDC_GetSize, 677).
--define(wxDC_GetSizeMM, 679).
--define(wxDC_GetTextBackground, 680).
--define(wxDC_GetTextExtent_4, 681).
--define(wxDC_GetTextExtent_1, 682).
--define(wxDC_GetTextForeground, 684).
--define(wxDC_GetUserScale, 685).
--define(wxDC_GradientFillConcentric_3, 686).
--define(wxDC_GradientFillConcentric_4, 687).
--define(wxDC_GradientFillLinear, 688).
--define(wxDC_LogicalToDeviceX, 689).
--define(wxDC_LogicalToDeviceXRel, 690).
--define(wxDC_LogicalToDeviceY, 691).
--define(wxDC_LogicalToDeviceYRel, 692).
--define(wxDC_MaxX, 693).
--define(wxDC_MaxY, 694).
--define(wxDC_MinX, 695).
--define(wxDC_MinY, 696).
--define(wxDC_IsOk, 697).
--define(wxDC_ResetBoundingBox, 698).
--define(wxDC_SetAxisOrientation, 699).
--define(wxDC_SetBackground, 700).
--define(wxDC_SetBackgroundMode, 701).
--define(wxDC_SetBrush, 702).
--define(wxDC_SetClippingRegion_2, 704).
--define(wxDC_SetClippingRegion_1_1, 705).
--define(wxDC_SetClippingRegion_1_0, 706).
--define(wxDC_SetDeviceOrigin, 707).
--define(wxDC_SetFont, 708).
--define(wxDC_SetLayoutDirection, 709).
--define(wxDC_SetLogicalFunction, 710).
--define(wxDC_SetMapMode, 711).
--define(wxDC_SetPalette, 712).
--define(wxDC_SetPen, 713).
--define(wxDC_SetTextBackground, 714).
--define(wxDC_SetTextForeground, 715).
--define(wxDC_SetUserScale, 716).
--define(wxDC_StartDoc, 717).
--define(wxDC_StartPage, 718).
--define(wxMirrorDC_new, 719).
--define(wxMirrorDC_destroy, 720).
--define(wxScreenDC_new, 721).
--define(wxScreenDC_destruct, 722).
--define(wxPostScriptDC_new_0, 723).
--define(wxPostScriptDC_new_1, 724).
--define(wxPostScriptDC_destruct, 725).
--define(wxPostScriptDC_SetResolution, 726).
--define(wxPostScriptDC_GetResolution, 727).
--define(wxWindowDC_new_0, 728).
--define(wxWindowDC_new_1, 729).
--define(wxWindowDC_destruct, 730).
--define(wxClientDC_new_0, 731).
--define(wxClientDC_new_1, 732).
--define(wxClientDC_destroy, 733).
--define(wxPaintDC_new_0, 734).
--define(wxPaintDC_new_1, 735).
--define(wxPaintDC_destroy, 736).
--define(wxMemoryDC_new_1_0, 738).
--define(wxMemoryDC_new_1_1, 739).
--define(wxMemoryDC_new_0, 740).
--define(wxMemoryDC_destruct, 742).
--define(wxMemoryDC_SelectObject, 743).
--define(wxMemoryDC_SelectObjectAsSource, 744).
--define(wxBufferedDC_new_0, 745).
--define(wxBufferedDC_new_2, 746).
--define(wxBufferedDC_new_3, 747).
--define(wxBufferedDC_destruct, 748).
--define(wxBufferedDC_Init_2, 749).
--define(wxBufferedDC_Init_3, 750).
--define(wxBufferedPaintDC_new_3, 751).
--define(wxBufferedPaintDC_new_2, 752).
--define(wxBufferedPaintDC_destruct, 753).
--define(wxGraphicsObject_GetRenderer, 754).
--define(wxGraphicsObject_IsNull, 755).
--define(wxGraphicsContext_Create_1_1, 756).
--define(wxGraphicsContext_Create_1_0, 757).
--define(wxGraphicsContext_Create_0, 758).
--define(wxGraphicsContext_CreatePen, 759).
--define(wxGraphicsContext_CreateBrush, 760).
--define(wxGraphicsContext_CreateRadialGradientBrush, 761).
--define(wxGraphicsContext_CreateLinearGradientBrush, 762).
--define(wxGraphicsContext_CreateFont, 763).
--define(wxGraphicsContext_CreateMatrix, 764).
--define(wxGraphicsContext_CreatePath, 765).
--define(wxGraphicsContext_Clip_1, 766).
--define(wxGraphicsContext_Clip_4, 767).
--define(wxGraphicsContext_ResetClip, 768).
--define(wxGraphicsContext_DrawBitmap, 769).
--define(wxGraphicsContext_DrawEllipse, 770).
--define(wxGraphicsContext_DrawIcon, 771).
--define(wxGraphicsContext_DrawLines, 772).
--define(wxGraphicsContext_DrawPath, 773).
--define(wxGraphicsContext_DrawRectangle, 774).
--define(wxGraphicsContext_DrawRoundedRectangle, 775).
--define(wxGraphicsContext_DrawText_3, 776).
--define(wxGraphicsContext_DrawText_4_0, 777).
--define(wxGraphicsContext_DrawText_4_1, 778).
--define(wxGraphicsContext_DrawText_5, 779).
--define(wxGraphicsContext_FillPath, 780).
--define(wxGraphicsContext_StrokePath, 781).
--define(wxGraphicsContext_GetNativeContext, 782).
--define(wxGraphicsContext_GetPartialTextExtents, 783).
--define(wxGraphicsContext_GetTextExtent, 784).
--define(wxGraphicsContext_Rotate, 785).
--define(wxGraphicsContext_Scale, 786).
--define(wxGraphicsContext_Translate, 787).
--define(wxGraphicsContext_GetTransform, 788).
--define(wxGraphicsContext_SetTransform, 789).
--define(wxGraphicsContext_ConcatTransform, 790).
--define(wxGraphicsContext_SetBrush_1_1, 791).
--define(wxGraphicsContext_SetBrush_1_0, 792).
--define(wxGraphicsContext_SetFont_1, 793).
--define(wxGraphicsContext_SetFont_2, 794).
--define(wxGraphicsContext_SetPen_1_0, 795).
--define(wxGraphicsContext_SetPen_1_1, 796).
--define(wxGraphicsContext_StrokeLine, 797).
--define(wxGraphicsContext_StrokeLines_2, 798).
--define(wxGraphicsContext_StrokeLines_3, 799).
--define(wxGraphicsMatrix_Concat, 800).
--define(wxGraphicsMatrix_Get, 802).
--define(wxGraphicsMatrix_GetNativeMatrix, 803).
--define(wxGraphicsMatrix_Invert, 804).
--define(wxGraphicsMatrix_IsEqual, 805).
--define(wxGraphicsMatrix_IsIdentity, 807).
--define(wxGraphicsMatrix_Rotate, 808).
--define(wxGraphicsMatrix_Scale, 809).
--define(wxGraphicsMatrix_Translate, 810).
--define(wxGraphicsMatrix_Set, 811).
--define(wxGraphicsMatrix_TransformPoint, 812).
--define(wxGraphicsMatrix_TransformDistance, 813).
--define(wxGraphicsPath_MoveToPoint_2, 814).
--define(wxGraphicsPath_MoveToPoint_1, 815).
--define(wxGraphicsPath_AddArc_6, 816).
--define(wxGraphicsPath_AddArc_5, 817).
--define(wxGraphicsPath_AddArcToPoint, 818).
--define(wxGraphicsPath_AddCircle, 819).
--define(wxGraphicsPath_AddCurveToPoint_6, 820).
--define(wxGraphicsPath_AddCurveToPoint_3, 821).
--define(wxGraphicsPath_AddEllipse, 822).
--define(wxGraphicsPath_AddLineToPoint_2, 823).
--define(wxGraphicsPath_AddLineToPoint_1, 824).
--define(wxGraphicsPath_AddPath, 825).
--define(wxGraphicsPath_AddQuadCurveToPoint, 826).
--define(wxGraphicsPath_AddRectangle, 827).
--define(wxGraphicsPath_AddRoundedRectangle, 828).
--define(wxGraphicsPath_CloseSubpath, 829).
--define(wxGraphicsPath_Contains_3, 830).
--define(wxGraphicsPath_Contains_2, 831).
--define(wxGraphicsPath_GetBox, 833).
--define(wxGraphicsPath_GetCurrentPoint, 835).
--define(wxGraphicsPath_Transform, 836).
--define(wxGraphicsRenderer_GetDefaultRenderer, 837).
--define(wxGraphicsRenderer_CreateContext_1_1, 838).
--define(wxGraphicsRenderer_CreateContext_1_0, 839).
--define(wxGraphicsRenderer_CreatePen, 840).
--define(wxGraphicsRenderer_CreateBrush, 841).
--define(wxGraphicsRenderer_CreateLinearGradientBrush, 842).
--define(wxGraphicsRenderer_CreateRadialGradientBrush, 843).
--define(wxGraphicsRenderer_CreateFont, 844).
--define(wxGraphicsRenderer_CreateMatrix, 845).
--define(wxGraphicsRenderer_CreatePath, 846).
--define(wxMenuBar_new_1, 848).
--define(wxMenuBar_new_0, 850).
--define(wxMenuBar_destruct, 852).
--define(wxMenuBar_Append, 853).
--define(wxMenuBar_Check, 854).
--define(wxMenuBar_Enable_2, 855).
--define(wxMenuBar_Enable_1, 856).
--define(wxMenuBar_EnableTop, 857).
--define(wxMenuBar_FindMenu, 858).
--define(wxMenuBar_FindMenuItem, 859).
--define(wxMenuBar_FindItem, 860).
--define(wxMenuBar_GetHelpString, 861).
--define(wxMenuBar_GetLabel_1, 862).
--define(wxMenuBar_GetLabel_0, 863).
--define(wxMenuBar_GetLabelTop, 864).
--define(wxMenuBar_GetMenu, 865).
--define(wxMenuBar_GetMenuCount, 866).
--define(wxMenuBar_Insert, 867).
--define(wxMenuBar_IsChecked, 868).
--define(wxMenuBar_IsEnabled_1, 869).
--define(wxMenuBar_IsEnabled_0, 870).
--define(wxMenuBar_Remove, 871).
--define(wxMenuBar_Replace, 872).
--define(wxMenuBar_SetHelpString, 873).
--define(wxMenuBar_SetLabel_2, 874).
--define(wxMenuBar_SetLabel_1, 875).
--define(wxMenuBar_SetLabelTop, 876).
--define(wxControl_GetLabel, 877).
--define(wxControl_SetLabel, 878).
--define(wxControlWithItems_Append_1, 879).
--define(wxControlWithItems_Append_2, 880).
--define(wxControlWithItems_appendStrings_1, 881).
--define(wxControlWithItems_Clear, 882).
--define(wxControlWithItems_Delete, 883).
--define(wxControlWithItems_FindString, 884).
--define(wxControlWithItems_getClientData, 885).
--define(wxControlWithItems_setClientData, 886).
--define(wxControlWithItems_GetCount, 887).
--define(wxControlWithItems_GetSelection, 888).
--define(wxControlWithItems_GetString, 889).
--define(wxControlWithItems_GetStringSelection, 890).
--define(wxControlWithItems_Insert_2, 891).
--define(wxControlWithItems_Insert_3, 892).
--define(wxControlWithItems_IsEmpty, 893).
--define(wxControlWithItems_Select, 894).
--define(wxControlWithItems_SetSelection, 895).
--define(wxControlWithItems_SetString, 896).
--define(wxControlWithItems_SetStringSelection, 897).
--define(wxMenu_new_2, 900).
--define(wxMenu_new_1, 901).
--define(wxMenu_destruct, 903).
--define(wxMenu_Append_3, 904).
--define(wxMenu_Append_1, 905).
--define(wxMenu_Append_4_0, 906).
--define(wxMenu_Append_4_1, 907).
--define(wxMenu_AppendCheckItem, 908).
--define(wxMenu_AppendRadioItem, 909).
--define(wxMenu_AppendSeparator, 910).
--define(wxMenu_Break, 911).
--define(wxMenu_Check, 912).
--define(wxMenu_Delete_1_0, 913).
--define(wxMenu_Delete_1_1, 914).
--define(wxMenu_Destroy_1_0, 915).
--define(wxMenu_Destroy_1_1, 916).
--define(wxMenu_Enable, 917).
--define(wxMenu_FindItem_1, 918).
--define(wxMenu_FindItem_2, 919).
--define(wxMenu_FindItemByPosition, 920).
--define(wxMenu_GetHelpString, 921).
--define(wxMenu_GetLabel, 922).
--define(wxMenu_GetMenuItemCount, 923).
--define(wxMenu_GetMenuItems, 924).
--define(wxMenu_GetTitle, 926).
--define(wxMenu_Insert_2, 927).
--define(wxMenu_Insert_3, 928).
--define(wxMenu_Insert_5_1, 929).
--define(wxMenu_Insert_5_0, 930).
--define(wxMenu_InsertCheckItem, 931).
--define(wxMenu_InsertRadioItem, 932).
--define(wxMenu_InsertSeparator, 933).
--define(wxMenu_IsChecked, 934).
--define(wxMenu_IsEnabled, 935).
--define(wxMenu_Prepend_1, 936).
--define(wxMenu_Prepend_2, 937).
--define(wxMenu_Prepend_4_1, 938).
--define(wxMenu_Prepend_4_0, 939).
--define(wxMenu_PrependCheckItem, 940).
--define(wxMenu_PrependRadioItem, 941).
--define(wxMenu_PrependSeparator, 942).
--define(wxMenu_Remove_1_0, 943).
--define(wxMenu_Remove_1_1, 944).
--define(wxMenu_SetHelpString, 945).
--define(wxMenu_SetLabel, 946).
--define(wxMenu_SetTitle, 947).
--define(wxMenuItem_new, 948).
--define(wxMenuItem_destruct, 950).
--define(wxMenuItem_Check, 951).
--define(wxMenuItem_Enable, 952).
--define(wxMenuItem_GetBitmap, 953).
--define(wxMenuItem_GetHelp, 954).
--define(wxMenuItem_GetId, 955).
--define(wxMenuItem_GetKind, 956).
--define(wxMenuItem_GetLabel, 957).
--define(wxMenuItem_GetLabelFromText, 958).
--define(wxMenuItem_GetMenu, 959).
--define(wxMenuItem_GetText, 960).
--define(wxMenuItem_GetSubMenu, 961).
--define(wxMenuItem_IsCheckable, 962).
--define(wxMenuItem_IsChecked, 963).
--define(wxMenuItem_IsEnabled, 964).
--define(wxMenuItem_IsSeparator, 965).
--define(wxMenuItem_IsSubMenu, 966).
--define(wxMenuItem_SetBitmap, 967).
--define(wxMenuItem_SetHelp, 968).
--define(wxMenuItem_SetMenu, 969).
--define(wxMenuItem_SetSubMenu, 970).
--define(wxMenuItem_SetText, 971).
--define(wxToolBar_AddControl, 972).
--define(wxToolBar_AddSeparator, 973).
--define(wxToolBar_AddTool_5, 974).
--define(wxToolBar_AddTool_4_0, 975).
--define(wxToolBar_AddTool_1, 976).
--define(wxToolBar_AddTool_4_1, 977).
--define(wxToolBar_AddTool_3, 978).
--define(wxToolBar_AddTool_6, 979).
--define(wxToolBar_AddCheckTool, 980).
--define(wxToolBar_AddRadioTool, 981).
--define(wxToolBar_DeleteTool, 982).
--define(wxToolBar_DeleteToolByPos, 983).
--define(wxToolBar_EnableTool, 984).
--define(wxToolBar_FindById, 985).
--define(wxToolBar_FindControl, 986).
--define(wxToolBar_FindToolForPosition, 987).
--define(wxToolBar_GetToolSize, 988).
--define(wxToolBar_GetToolBitmapSize, 989).
--define(wxToolBar_GetMargins, 990).
--define(wxToolBar_GetToolEnabled, 991).
--define(wxToolBar_GetToolLongHelp, 992).
--define(wxToolBar_GetToolPacking, 993).
--define(wxToolBar_GetToolPos, 994).
--define(wxToolBar_GetToolSeparation, 995).
--define(wxToolBar_GetToolShortHelp, 996).
--define(wxToolBar_GetToolState, 997).
--define(wxToolBar_InsertControl, 998).
--define(wxToolBar_InsertSeparator, 999).
--define(wxToolBar_InsertTool_5, 1000).
--define(wxToolBar_InsertTool_2, 1001).
--define(wxToolBar_InsertTool_4, 1002).
--define(wxToolBar_Realize, 1003).
--define(wxToolBar_RemoveTool, 1004).
--define(wxToolBar_SetMargins, 1005).
--define(wxToolBar_SetToolBitmapSize, 1006).
--define(wxToolBar_SetToolLongHelp, 1007).
--define(wxToolBar_SetToolPacking, 1008).
--define(wxToolBar_SetToolShortHelp, 1009).
--define(wxToolBar_SetToolSeparation, 1010).
--define(wxToolBar_ToggleTool, 1011).
--define(wxStatusBar_new_0, 1013).
--define(wxStatusBar_new_2, 1014).
--define(wxStatusBar_destruct, 1016).
--define(wxStatusBar_Create, 1017).
--define(wxStatusBar_GetFieldRect, 1018).
--define(wxStatusBar_GetFieldsCount, 1019).
--define(wxStatusBar_GetStatusText, 1020).
--define(wxStatusBar_PopStatusText, 1021).
--define(wxStatusBar_PushStatusText, 1022).
--define(wxStatusBar_SetFieldsCount, 1023).
--define(wxStatusBar_SetMinHeight, 1024).
--define(wxStatusBar_SetStatusText, 1025).
--define(wxStatusBar_SetStatusWidths, 1026).
--define(wxStatusBar_SetStatusStyles, 1027).
--define(wxBitmap_new_0, 1028).
--define(wxBitmap_new_3, 1029).
--define(wxBitmap_new_4, 1030).
--define(wxBitmap_new_2_0, 1031).
--define(wxBitmap_new_2_1, 1032).
--define(wxBitmap_destruct, 1033).
--define(wxBitmap_ConvertToImage, 1034).
--define(wxBitmap_CopyFromIcon, 1035).
--define(wxBitmap_Create, 1036).
--define(wxBitmap_GetDepth, 1037).
--define(wxBitmap_GetHeight, 1038).
--define(wxBitmap_GetPalette, 1039).
--define(wxBitmap_GetMask, 1040).
--define(wxBitmap_GetWidth, 1041).
--define(wxBitmap_GetSubBitmap, 1042).
--define(wxBitmap_LoadFile, 1043).
--define(wxBitmap_Ok, 1044).
--define(wxBitmap_SaveFile, 1045).
--define(wxBitmap_SetDepth, 1046).
--define(wxBitmap_SetHeight, 1047).
--define(wxBitmap_SetMask, 1048).
--define(wxBitmap_SetPalette, 1049).
--define(wxBitmap_SetWidth, 1050).
--define(wxIcon_new_0, 1051).
--define(wxIcon_new_2, 1052).
--define(wxIcon_new_1, 1053).
--define(wxIcon_CopyFromBitmap, 1054).
--define(wxIcon_destroy, 1055).
--define(wxIconBundle_new_0, 1056).
--define(wxIconBundle_new_2, 1057).
--define(wxIconBundle_new_1_0, 1058).
--define(wxIconBundle_new_1_1, 1059).
--define(wxIconBundle_destruct, 1060).
--define(wxIconBundle_AddIcon_2, 1061).
--define(wxIconBundle_AddIcon_1, 1062).
--define(wxIconBundle_GetIcon_1_1, 1063).
--define(wxIconBundle_GetIcon_1_0, 1064).
--define(wxCursor_new_0, 1065).
--define(wxCursor_new_1_0, 1066).
--define(wxCursor_new_1_1, 1067).
--define(wxCursor_new_4, 1068).
--define(wxCursor_destruct, 1069).
--define(wxCursor_Ok, 1070).
--define(wxMask_new_0, 1071).
--define(wxMask_new_2_1, 1072).
--define(wxMask_new_2_0, 1073).
--define(wxMask_new_1, 1074).
--define(wxMask_destruct, 1075).
--define(wxMask_Create_2_1, 1076).
--define(wxMask_Create_2_0, 1077).
--define(wxMask_Create_1, 1078).
--define(wxImage_new_0, 1079).
--define(wxImage_new_3_0, 1080).
--define(wxImage_new_4, 1081).
--define(wxImage_new_5, 1082).
--define(wxImage_new_2, 1083).
--define(wxImage_new_3_1, 1084).
--define(wxImage_Blur, 1085).
--define(wxImage_BlurHorizontal, 1086).
--define(wxImage_BlurVertical, 1087).
--define(wxImage_ConvertAlphaToMask, 1088).
--define(wxImage_ConvertToGreyscale, 1089).
--define(wxImage_ConvertToMono, 1090).
--define(wxImage_Copy, 1091).
--define(wxImage_Create_3, 1092).
--define(wxImage_Create_4, 1093).
--define(wxImage_Create_5, 1094).
--define(wxImage_Destroy, 1095).
--define(wxImage_FindFirstUnusedColour, 1096).
--define(wxImage_GetImageExtWildcard, 1097).
--define(wxImage_GetAlpha_2, 1098).
--define(wxImage_GetAlpha_0, 1099).
--define(wxImage_GetBlue, 1100).
--define(wxImage_GetData, 1101).
--define(wxImage_GetGreen, 1102).
--define(wxImage_GetImageCount, 1103).
--define(wxImage_GetHeight, 1104).
--define(wxImage_GetMaskBlue, 1105).
--define(wxImage_GetMaskGreen, 1106).
--define(wxImage_GetMaskRed, 1107).
--define(wxImage_GetOrFindMaskColour, 1108).
--define(wxImage_GetPalette, 1109).
--define(wxImage_GetRed, 1110).
--define(wxImage_GetSubImage, 1111).
--define(wxImage_GetWidth, 1112).
--define(wxImage_HasAlpha, 1113).
--define(wxImage_HasMask, 1114).
--define(wxImage_GetOption, 1115).
--define(wxImage_GetOptionInt, 1116).
--define(wxImage_HasOption, 1117).
--define(wxImage_InitAlpha, 1118).
--define(wxImage_InitStandardHandlers, 1119).
--define(wxImage_IsTransparent, 1120).
--define(wxImage_LoadFile_2, 1121).
--define(wxImage_LoadFile_3, 1122).
--define(wxImage_Ok, 1123).
--define(wxImage_RemoveHandler, 1124).
--define(wxImage_Mirror, 1125).
--define(wxImage_Replace, 1126).
--define(wxImage_Rescale, 1127).
--define(wxImage_Resize, 1128).
--define(wxImage_Rotate, 1129).
--define(wxImage_RotateHue, 1130).
--define(wxImage_Rotate90, 1131).
--define(wxImage_SaveFile_1, 1132).
--define(wxImage_SaveFile_2_0, 1133).
--define(wxImage_SaveFile_2_1, 1134).
--define(wxImage_Scale, 1135).
--define(wxImage_Size, 1136).
--define(wxImage_SetAlpha_3, 1137).
--define(wxImage_SetAlpha_2, 1138).
--define(wxImage_SetData_2, 1139).
--define(wxImage_SetData_4, 1140).
--define(wxImage_SetMask, 1141).
--define(wxImage_SetMaskColour, 1142).
--define(wxImage_SetMaskFromImage, 1143).
--define(wxImage_SetOption_2_1, 1144).
--define(wxImage_SetOption_2_0, 1145).
--define(wxImage_SetPalette, 1146).
--define(wxImage_SetRGB_5, 1147).
--define(wxImage_SetRGB_4, 1148).
--define(wxImage_destroy, 1149).
--define(wxBrush_new_0, 1150).
--define(wxBrush_new_2, 1151).
--define(wxBrush_new_1, 1152).
--define(wxBrush_destruct, 1154).
--define(wxBrush_GetColour, 1155).
--define(wxBrush_GetStipple, 1156).
--define(wxBrush_GetStyle, 1157).
--define(wxBrush_IsHatch, 1158).
--define(wxBrush_IsOk, 1159).
--define(wxBrush_SetColour_1, 1160).
--define(wxBrush_SetColour_3, 1161).
--define(wxBrush_SetStipple, 1162).
--define(wxBrush_SetStyle, 1163).
--define(wxPen_new_0, 1164).
--define(wxPen_new_2, 1165).
--define(wxPen_destruct, 1166).
--define(wxPen_GetCap, 1167).
--define(wxPen_GetColour, 1168).
--define(wxPen_GetJoin, 1169).
--define(wxPen_GetStyle, 1170).
--define(wxPen_GetWidth, 1171).
--define(wxPen_IsOk, 1172).
--define(wxPen_SetCap, 1173).
--define(wxPen_SetColour_1, 1174).
--define(wxPen_SetColour_3, 1175).
--define(wxPen_SetJoin, 1176).
--define(wxPen_SetStyle, 1177).
--define(wxPen_SetWidth, 1178).
--define(wxRegion_new_0, 1179).
--define(wxRegion_new_4, 1180).
--define(wxRegion_new_2, 1181).
--define(wxRegion_new_1_1, 1182).
--define(wxRegion_new_1_0, 1184).
--define(wxRegion_destruct, 1186).
--define(wxRegion_Clear, 1187).
--define(wxRegion_Contains_2, 1188).
--define(wxRegion_Contains_1_0, 1189).
--define(wxRegion_Contains_4, 1190).
--define(wxRegion_Contains_1_1, 1191).
--define(wxRegion_ConvertToBitmap, 1192).
--define(wxRegion_GetBox, 1193).
--define(wxRegion_Intersect_4, 1194).
--define(wxRegion_Intersect_1_1, 1195).
--define(wxRegion_Intersect_1_0, 1196).
--define(wxRegion_IsEmpty, 1197).
--define(wxRegion_Subtract_4, 1198).
--define(wxRegion_Subtract_1_1, 1199).
--define(wxRegion_Subtract_1_0, 1200).
--define(wxRegion_Offset_2, 1201).
--define(wxRegion_Offset_1, 1202).
--define(wxRegion_Union_4, 1203).
--define(wxRegion_Union_1_2, 1204).
--define(wxRegion_Union_1_1, 1205).
--define(wxRegion_Union_1_0, 1206).
--define(wxRegion_Union_3, 1207).
--define(wxRegion_Xor_4, 1208).
--define(wxRegion_Xor_1_1, 1209).
--define(wxRegion_Xor_1_0, 1210).
--define(wxAcceleratorTable_new_0, 1211).
--define(wxAcceleratorTable_new_2, 1212).
--define(wxAcceleratorTable_destruct, 1213).
--define(wxAcceleratorTable_Ok, 1214).
--define(wxAcceleratorEntry_new_1_0, 1215).
--define(wxAcceleratorEntry_new_1_1, 1216).
--define(wxAcceleratorEntry_GetCommand, 1217).
--define(wxAcceleratorEntry_GetFlags, 1218).
--define(wxAcceleratorEntry_GetKeyCode, 1219).
--define(wxAcceleratorEntry_Set, 1220).
--define(wxAcceleratorEntry_destroy, 1221).
--define(wxCaret_new_3, 1226).
--define(wxCaret_new_2, 1227).
--define(wxCaret_destruct, 1229).
--define(wxCaret_Create_3, 1230).
--define(wxCaret_Create_2, 1231).
--define(wxCaret_GetBlinkTime, 1232).
--define(wxCaret_GetPosition, 1234).
--define(wxCaret_GetSize, 1236).
--define(wxCaret_GetWindow, 1237).
--define(wxCaret_Hide, 1238).
--define(wxCaret_IsOk, 1239).
--define(wxCaret_IsVisible, 1240).
--define(wxCaret_Move_2, 1241).
--define(wxCaret_Move_1, 1242).
--define(wxCaret_SetBlinkTime, 1243).
--define(wxCaret_SetSize_2, 1244).
--define(wxCaret_SetSize_1, 1245).
--define(wxCaret_Show, 1246).
--define(wxSizer_Add_2_1, 1247).
--define(wxSizer_Add_2_0, 1248).
--define(wxSizer_Add_3, 1249).
--define(wxSizer_Add_2_3, 1250).
--define(wxSizer_Add_2_2, 1251).
--define(wxSizer_AddSpacer, 1252).
--define(wxSizer_AddStretchSpacer, 1253).
--define(wxSizer_CalcMin, 1254).
--define(wxSizer_Clear, 1255).
--define(wxSizer_Detach_1_2, 1256).
--define(wxSizer_Detach_1_1, 1257).
--define(wxSizer_Detach_1_0, 1258).
--define(wxSizer_Fit, 1259).
--define(wxSizer_FitInside, 1260).
--define(wxSizer_GetChildren, 1261).
--define(wxSizer_GetItem_2_1, 1262).
--define(wxSizer_GetItem_2_0, 1263).
--define(wxSizer_GetItem_1, 1264).
--define(wxSizer_GetSize, 1265).
--define(wxSizer_GetPosition, 1266).
--define(wxSizer_GetMinSize, 1267).
--define(wxSizer_Hide_2_0, 1268).
--define(wxSizer_Hide_2_1, 1269).
--define(wxSizer_Hide_1, 1270).
--define(wxSizer_Insert_3_1, 1271).
--define(wxSizer_Insert_3_0, 1272).
--define(wxSizer_Insert_4, 1273).
--define(wxSizer_Insert_3_3, 1274).
--define(wxSizer_Insert_3_2, 1275).
--define(wxSizer_Insert_2, 1276).
--define(wxSizer_InsertSpacer, 1277).
--define(wxSizer_InsertStretchSpacer, 1278).
--define(wxSizer_IsShown_1_2, 1279).
--define(wxSizer_IsShown_1_1, 1280).
--define(wxSizer_IsShown_1_0, 1281).
--define(wxSizer_Layout, 1282).
--define(wxSizer_Prepend_2_1, 1283).
--define(wxSizer_Prepend_2_0, 1284).
--define(wxSizer_Prepend_3, 1285).
--define(wxSizer_Prepend_2_3, 1286).
--define(wxSizer_Prepend_2_2, 1287).
--define(wxSizer_Prepend_1, 1288).
--define(wxSizer_PrependSpacer, 1289).
--define(wxSizer_PrependStretchSpacer, 1290).
--define(wxSizer_RecalcSizes, 1291).
--define(wxSizer_Remove_1_1, 1292).
--define(wxSizer_Remove_1_0, 1293).
--define(wxSizer_Replace_3_1, 1294).
--define(wxSizer_Replace_3_0, 1295).
--define(wxSizer_Replace_2, 1296).
--define(wxSizer_SetDimension, 1297).
--define(wxSizer_SetMinSize_2, 1298).
--define(wxSizer_SetMinSize_1, 1299).
--define(wxSizer_SetItemMinSize_3_2, 1300).
--define(wxSizer_SetItemMinSize_2_2, 1301).
--define(wxSizer_SetItemMinSize_3_1, 1302).
--define(wxSizer_SetItemMinSize_2_1, 1303).
--define(wxSizer_SetItemMinSize_3_0, 1304).
--define(wxSizer_SetItemMinSize_2_0, 1305).
--define(wxSizer_SetSizeHints, 1306).
--define(wxSizer_SetVirtualSizeHints, 1307).
--define(wxSizer_Show_2_2, 1308).
--define(wxSizer_Show_2_1, 1309).
--define(wxSizer_Show_2_0, 1310).
--define(wxSizer_Show_1, 1311).
--define(wxSizerFlags_new, 1312).
--define(wxSizerFlags_Align, 1313).
--define(wxSizerFlags_Border_2, 1314).
--define(wxSizerFlags_Border_1, 1315).
--define(wxSizerFlags_Center, 1316).
--define(wxSizerFlags_Centre, 1317).
--define(wxSizerFlags_Expand, 1318).
--define(wxSizerFlags_Left, 1319).
--define(wxSizerFlags_Proportion, 1320).
--define(wxSizerFlags_Right, 1321).
--define(wxSizerFlags_destroy, 1322).
--define(wxSizerItem_new_5_1, 1323).
--define(wxSizerItem_new_2_1, 1324).
--define(wxSizerItem_new_5_0, 1325).
--define(wxSizerItem_new_2_0, 1326).
--define(wxSizerItem_new_6, 1327).
--define(wxSizerItem_new_3, 1328).
--define(wxSizerItem_new_0, 1329).
--define(wxSizerItem_destruct, 1330).
--define(wxSizerItem_CalcMin, 1331).
--define(wxSizerItem_DeleteWindows, 1332).
--define(wxSizerItem_DetachSizer, 1333).
--define(wxSizerItem_GetBorder, 1334).
--define(wxSizerItem_GetFlag, 1335).
--define(wxSizerItem_GetMinSize, 1336).
--define(wxSizerItem_GetPosition, 1337).
--define(wxSizerItem_GetProportion, 1338).
--define(wxSizerItem_GetRatio, 1339).
--define(wxSizerItem_GetRect, 1340).
--define(wxSizerItem_GetSize, 1341).
--define(wxSizerItem_GetSizer, 1342).
--define(wxSizerItem_GetSpacer, 1343).
--define(wxSizerItem_GetUserData, 1344).
--define(wxSizerItem_GetWindow, 1345).
--define(wxSizerItem_IsSizer, 1346).
--define(wxSizerItem_IsShown, 1347).
--define(wxSizerItem_IsSpacer, 1348).
--define(wxSizerItem_IsWindow, 1349).
--define(wxSizerItem_SetBorder, 1350).
--define(wxSizerItem_SetDimension, 1351).
--define(wxSizerItem_SetFlag, 1352).
--define(wxSizerItem_SetInitSize, 1353).
--define(wxSizerItem_SetMinSize_1, 1354).
--define(wxSizerItem_SetMinSize_2, 1355).
--define(wxSizerItem_SetProportion, 1356).
--define(wxSizerItem_SetRatio_2, 1357).
--define(wxSizerItem_SetRatio_1_1, 1358).
--define(wxSizerItem_SetRatio_1_0, 1359).
--define(wxSizerItem_SetSizer, 1360).
--define(wxSizerItem_SetSpacer_1, 1361).
--define(wxSizerItem_SetSpacer_2, 1362).
--define(wxSizerItem_SetWindow, 1363).
--define(wxSizerItem_Show, 1364).
--define(wxBoxSizer_new, 1365).
--define(wxBoxSizer_GetOrientation, 1366).
--define(wxBoxSizer_destroy, 1367).
--define(wxStaticBoxSizer_new_2, 1368).
--define(wxStaticBoxSizer_new_3, 1369).
--define(wxStaticBoxSizer_GetStaticBox, 1370).
--define(wxStaticBoxSizer_destroy, 1371).
--define(wxGridSizer_new_4, 1372).
--define(wxGridSizer_new_2, 1373).
--define(wxGridSizer_GetCols, 1374).
--define(wxGridSizer_GetHGap, 1375).
--define(wxGridSizer_GetRows, 1376).
--define(wxGridSizer_GetVGap, 1377).
--define(wxGridSizer_SetCols, 1378).
--define(wxGridSizer_SetHGap, 1379).
--define(wxGridSizer_SetRows, 1380).
--define(wxGridSizer_SetVGap, 1381).
--define(wxGridSizer_destroy, 1382).
--define(wxFlexGridSizer_new_4, 1383).
--define(wxFlexGridSizer_new_2, 1384).
--define(wxFlexGridSizer_AddGrowableCol, 1385).
--define(wxFlexGridSizer_AddGrowableRow, 1386).
--define(wxFlexGridSizer_GetFlexibleDirection, 1387).
--define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1388).
--define(wxFlexGridSizer_RemoveGrowableCol, 1389).
--define(wxFlexGridSizer_RemoveGrowableRow, 1390).
--define(wxFlexGridSizer_SetFlexibleDirection, 1391).
--define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1392).
--define(wxFlexGridSizer_destroy, 1393).
--define(wxGridBagSizer_new, 1394).
--define(wxGridBagSizer_Add_3_2, 1395).
--define(wxGridBagSizer_Add_3_1, 1396).
--define(wxGridBagSizer_Add_4, 1397).
--define(wxGridBagSizer_Add_1_0, 1398).
--define(wxGridBagSizer_Add_2_1, 1399).
--define(wxGridBagSizer_Add_2_0, 1400).
--define(wxGridBagSizer_Add_3_0, 1401).
--define(wxGridBagSizer_Add_1_1, 1402).
--define(wxGridBagSizer_CalcMin, 1403).
--define(wxGridBagSizer_CheckForIntersection_2, 1404).
--define(wxGridBagSizer_CheckForIntersection_3, 1405).
--define(wxGridBagSizer_FindItem_1_1, 1406).
--define(wxGridBagSizer_FindItem_1_0, 1407).
--define(wxGridBagSizer_FindItemAtPoint, 1408).
--define(wxGridBagSizer_FindItemAtPosition, 1409).
--define(wxGridBagSizer_FindItemWithData, 1410).
--define(wxGridBagSizer_GetCellSize, 1411).
--define(wxGridBagSizer_GetEmptyCellSize, 1412).
--define(wxGridBagSizer_GetItemPosition_1_2, 1413).
--define(wxGridBagSizer_GetItemPosition_1_1, 1414).
--define(wxGridBagSizer_GetItemPosition_1_0, 1415).
--define(wxGridBagSizer_GetItemSpan_1_2, 1416).
--define(wxGridBagSizer_GetItemSpan_1_1, 1417).
--define(wxGridBagSizer_GetItemSpan_1_0, 1418).
--define(wxGridBagSizer_SetEmptyCellSize, 1419).
--define(wxGridBagSizer_SetItemPosition_2_2, 1420).
--define(wxGridBagSizer_SetItemPosition_2_1, 1421).
--define(wxGridBagSizer_SetItemPosition_2_0, 1422).
--define(wxGridBagSizer_SetItemSpan_2_2, 1423).
--define(wxGridBagSizer_SetItemSpan_2_1, 1424).
--define(wxGridBagSizer_SetItemSpan_2_0, 1425).
--define(wxGridBagSizer_destroy, 1426).
--define(wxStdDialogButtonSizer_new, 1427).
--define(wxStdDialogButtonSizer_AddButton, 1428).
--define(wxStdDialogButtonSizer_Realize, 1429).
--define(wxStdDialogButtonSizer_SetAffirmativeButton, 1430).
--define(wxStdDialogButtonSizer_SetCancelButton, 1431).
--define(wxStdDialogButtonSizer_SetNegativeButton, 1432).
--define(wxStdDialogButtonSizer_destroy, 1433).
--define(wxFont_new_0, 1434).
--define(wxFont_new_1, 1435).
--define(wxFont_new_5, 1436).
--define(wxFont_destruct, 1438).
--define(wxFont_IsFixedWidth, 1439).
--define(wxFont_GetDefaultEncoding, 1440).
--define(wxFont_GetFaceName, 1441).
--define(wxFont_GetFamily, 1442).
--define(wxFont_GetNativeFontInfoDesc, 1443).
--define(wxFont_GetNativeFontInfoUserDesc, 1444).
--define(wxFont_GetPointSize, 1445).
--define(wxFont_GetStyle, 1446).
--define(wxFont_GetUnderlined, 1447).
--define(wxFont_GetWeight, 1448).
--define(wxFont_Ok, 1449).
--define(wxFont_SetDefaultEncoding, 1450).
--define(wxFont_SetFaceName, 1451).
--define(wxFont_SetFamily, 1452).
--define(wxFont_SetPointSize, 1453).
--define(wxFont_SetStyle, 1454).
--define(wxFont_SetUnderlined, 1455).
--define(wxFont_SetWeight, 1456).
--define(wxToolTip_Enable, 1457).
--define(wxToolTip_SetDelay, 1458).
--define(wxToolTip_new, 1459).
--define(wxToolTip_SetTip, 1460).
--define(wxToolTip_GetTip, 1461).
--define(wxToolTip_GetWindow, 1462).
--define(wxToolTip_destroy, 1463).
--define(wxButton_new_3, 1465).
--define(wxButton_new_0, 1466).
--define(wxButton_destruct, 1467).
--define(wxButton_Create, 1468).
--define(wxButton_GetDefaultSize, 1469).
--define(wxButton_SetDefault, 1470).
--define(wxButton_SetLabel, 1471).
--define(wxBitmapButton_new_4, 1473).
--define(wxBitmapButton_new_0, 1474).
--define(wxBitmapButton_Create, 1475).
--define(wxBitmapButton_GetBitmapDisabled, 1476).
--define(wxBitmapButton_GetBitmapFocus, 1478).
--define(wxBitmapButton_GetBitmapLabel, 1480).
--define(wxBitmapButton_GetBitmapSelected, 1482).
--define(wxBitmapButton_SetBitmapDisabled, 1484).
--define(wxBitmapButton_SetBitmapFocus, 1485).
--define(wxBitmapButton_SetBitmapLabel, 1486).
--define(wxBitmapButton_SetBitmapSelected, 1487).
--define(wxBitmapButton_destroy, 1488).
--define(wxToggleButton_new_0, 1489).
--define(wxToggleButton_new_4, 1490).
--define(wxToggleButton_Create, 1491).
--define(wxToggleButton_GetValue, 1492).
--define(wxToggleButton_SetValue, 1493).
--define(wxToggleButton_destroy, 1494).
--define(wxCalendarCtrl_new_0, 1495).
--define(wxCalendarCtrl_new_3, 1496).
--define(wxCalendarCtrl_Create, 1497).
--define(wxCalendarCtrl_destruct, 1498).
--define(wxCalendarCtrl_SetDate, 1499).
--define(wxCalendarCtrl_GetDate, 1500).
--define(wxCalendarCtrl_EnableYearChange, 1501).
--define(wxCalendarCtrl_EnableMonthChange, 1502).
--define(wxCalendarCtrl_EnableHolidayDisplay, 1503).
--define(wxCalendarCtrl_SetHeaderColours, 1504).
--define(wxCalendarCtrl_GetHeaderColourFg, 1505).
--define(wxCalendarCtrl_GetHeaderColourBg, 1506).
--define(wxCalendarCtrl_SetHighlightColours, 1507).
--define(wxCalendarCtrl_GetHighlightColourFg, 1508).
--define(wxCalendarCtrl_GetHighlightColourBg, 1509).
--define(wxCalendarCtrl_SetHolidayColours, 1510).
--define(wxCalendarCtrl_GetHolidayColourFg, 1511).
--define(wxCalendarCtrl_GetHolidayColourBg, 1512).
--define(wxCalendarCtrl_GetAttr, 1513).
--define(wxCalendarCtrl_SetAttr, 1514).
--define(wxCalendarCtrl_SetHoliday, 1515).
--define(wxCalendarCtrl_ResetAttr, 1516).
--define(wxCalendarCtrl_HitTest, 1517).
--define(wxCalendarDateAttr_new_0, 1518).
--define(wxCalendarDateAttr_new_2_1, 1519).
--define(wxCalendarDateAttr_new_2_0, 1520).
--define(wxCalendarDateAttr_SetTextColour, 1521).
--define(wxCalendarDateAttr_SetBackgroundColour, 1522).
--define(wxCalendarDateAttr_SetBorderColour, 1523).
--define(wxCalendarDateAttr_SetFont, 1524).
--define(wxCalendarDateAttr_SetBorder, 1525).
--define(wxCalendarDateAttr_SetHoliday, 1526).
--define(wxCalendarDateAttr_HasTextColour, 1527).
--define(wxCalendarDateAttr_HasBackgroundColour, 1528).
--define(wxCalendarDateAttr_HasBorderColour, 1529).
--define(wxCalendarDateAttr_HasFont, 1530).
--define(wxCalendarDateAttr_HasBorder, 1531).
--define(wxCalendarDateAttr_IsHoliday, 1532).
--define(wxCalendarDateAttr_GetTextColour, 1533).
--define(wxCalendarDateAttr_GetBackgroundColour, 1534).
--define(wxCalendarDateAttr_GetBorderColour, 1535).
--define(wxCalendarDateAttr_GetFont, 1536).
--define(wxCalendarDateAttr_GetBorder, 1537).
--define(wxCalendarDateAttr_destroy, 1538).
--define(wxCheckBox_new_4, 1540).
--define(wxCheckBox_new_0, 1541).
--define(wxCheckBox_Create, 1542).
--define(wxCheckBox_GetValue, 1543).
--define(wxCheckBox_Get3StateValue, 1544).
--define(wxCheckBox_Is3rdStateAllowedForUser, 1545).
--define(wxCheckBox_Is3State, 1546).
--define(wxCheckBox_IsChecked, 1547).
--define(wxCheckBox_SetValue, 1548).
--define(wxCheckBox_Set3StateValue, 1549).
--define(wxCheckBox_destroy, 1550).
--define(wxCheckListBox_new_0, 1551).
--define(wxCheckListBox_new_3, 1553).
--define(wxCheckListBox_Check, 1554).
--define(wxCheckListBox_IsChecked, 1555).
--define(wxCheckListBox_destroy, 1556).
--define(wxChoice_new_3, 1559).
--define(wxChoice_new_0, 1560).
--define(wxChoice_destruct, 1562).
--define(wxChoice_Create, 1564).
--define(wxChoice_Delete, 1565).
--define(wxChoice_GetColumns, 1566).
--define(wxChoice_SetColumns, 1567).
--define(wxComboBox_new_0, 1568).
--define(wxComboBox_new_3, 1570).
--define(wxComboBox_destruct, 1571).
--define(wxComboBox_Create, 1573).
--define(wxComboBox_CanCopy, 1574).
--define(wxComboBox_CanCut, 1575).
--define(wxComboBox_CanPaste, 1576).
--define(wxComboBox_CanRedo, 1577).
--define(wxComboBox_CanUndo, 1578).
--define(wxComboBox_Copy, 1579).
--define(wxComboBox_Cut, 1580).
--define(wxComboBox_GetInsertionPoint, 1581).
--define(wxComboBox_GetLastPosition, 1582).
--define(wxComboBox_GetValue, 1583).
--define(wxComboBox_Paste, 1584).
--define(wxComboBox_Redo, 1585).
--define(wxComboBox_Replace, 1586).
--define(wxComboBox_Remove, 1587).
--define(wxComboBox_SetInsertionPoint, 1588).
--define(wxComboBox_SetInsertionPointEnd, 1589).
--define(wxComboBox_SetSelection_1, 1590).
--define(wxComboBox_SetSelection_2, 1591).
--define(wxComboBox_SetValue, 1592).
--define(wxComboBox_Undo, 1593).
--define(wxGauge_new_0, 1594).
--define(wxGauge_new_4, 1595).
--define(wxGauge_Create, 1596).
--define(wxGauge_GetBezelFace, 1597).
--define(wxGauge_GetRange, 1598).
--define(wxGauge_GetShadowWidth, 1599).
--define(wxGauge_GetValue, 1600).
--define(wxGauge_IsVertical, 1601).
--define(wxGauge_SetBezelFace, 1602).
--define(wxGauge_SetRange, 1603).
--define(wxGauge_SetShadowWidth, 1604).
--define(wxGauge_SetValue, 1605).
--define(wxGauge_Pulse, 1606).
--define(wxGauge_destroy, 1607).
--define(wxGenericDirCtrl_new_0, 1608).
--define(wxGenericDirCtrl_new_2, 1609).
--define(wxGenericDirCtrl_destruct, 1610).
--define(wxGenericDirCtrl_Create, 1611).
--define(wxGenericDirCtrl_Init, 1612).
--define(wxGenericDirCtrl_CollapseTree, 1613).
--define(wxGenericDirCtrl_ExpandPath, 1614).
--define(wxGenericDirCtrl_GetDefaultPath, 1615).
--define(wxGenericDirCtrl_GetPath, 1616).
--define(wxGenericDirCtrl_GetFilePath, 1617).
--define(wxGenericDirCtrl_GetFilter, 1618).
--define(wxGenericDirCtrl_GetFilterIndex, 1619).
--define(wxGenericDirCtrl_GetRootId, 1620).
--define(wxGenericDirCtrl_GetTreeCtrl, 1621).
--define(wxGenericDirCtrl_ReCreateTree, 1622).
--define(wxGenericDirCtrl_SetDefaultPath, 1623).
--define(wxGenericDirCtrl_SetFilter, 1624).
--define(wxGenericDirCtrl_SetFilterIndex, 1625).
--define(wxGenericDirCtrl_SetPath, 1626).
--define(wxStaticBox_new_4, 1628).
--define(wxStaticBox_new_0, 1629).
--define(wxStaticBox_Create, 1630).
--define(wxStaticBox_destroy, 1631).
--define(wxStaticLine_new_2, 1633).
--define(wxStaticLine_new_0, 1634).
--define(wxStaticLine_Create, 1635).
--define(wxStaticLine_IsVertical, 1636).
--define(wxStaticLine_GetDefaultSize, 1637).
--define(wxStaticLine_destroy, 1638).
--define(wxListBox_new_3, 1641).
--define(wxListBox_new_0, 1642).
--define(wxListBox_destruct, 1644).
--define(wxListBox_Create, 1646).
--define(wxListBox_Deselect, 1647).
--define(wxListBox_GetSelections, 1648).
--define(wxListBox_InsertItems, 1649).
--define(wxListBox_IsSelected, 1650).
--define(wxListBox_Set, 1652).
--define(wxListBox_HitTest, 1653).
--define(wxListBox_SetFirstItem_1_0, 1654).
--define(wxListBox_SetFirstItem_1_1, 1655).
--define(wxListCtrl_new_0, 1656).
--define(wxListCtrl_new_2, 1657).
--define(wxListCtrl_Arrange, 1658).
--define(wxListCtrl_AssignImageList, 1659).
--define(wxListCtrl_ClearAll, 1660).
--define(wxListCtrl_Create, 1661).
--define(wxListCtrl_DeleteAllItems, 1662).
--define(wxListCtrl_DeleteColumn, 1663).
--define(wxListCtrl_DeleteItem, 1664).
--define(wxListCtrl_EditLabel, 1665).
--define(wxListCtrl_EnsureVisible, 1666).
--define(wxListCtrl_FindItem_3_0, 1667).
--define(wxListCtrl_FindItem_3_1, 1668).
--define(wxListCtrl_GetColumn, 1669).
--define(wxListCtrl_GetColumnCount, 1670).
--define(wxListCtrl_GetColumnWidth, 1671).
--define(wxListCtrl_GetCountPerPage, 1672).
--define(wxListCtrl_GetEditControl, 1673).
--define(wxListCtrl_GetImageList, 1674).
--define(wxListCtrl_GetItem, 1675).
--define(wxListCtrl_GetItemBackgroundColour, 1676).
--define(wxListCtrl_GetItemCount, 1677).
--define(wxListCtrl_GetItemData, 1678).
--define(wxListCtrl_GetItemFont, 1679).
--define(wxListCtrl_GetItemPosition, 1680).
--define(wxListCtrl_GetItemRect, 1681).
--define(wxListCtrl_GetItemSpacing, 1682).
--define(wxListCtrl_GetItemState, 1683).
--define(wxListCtrl_GetItemText, 1684).
--define(wxListCtrl_GetItemTextColour, 1685).
--define(wxListCtrl_GetNextItem, 1686).
--define(wxListCtrl_GetSelectedItemCount, 1687).
--define(wxListCtrl_GetTextColour, 1688).
--define(wxListCtrl_GetTopItem, 1689).
--define(wxListCtrl_GetViewRect, 1690).
--define(wxListCtrl_HitTest, 1691).
--define(wxListCtrl_InsertColumn_2, 1692).
--define(wxListCtrl_InsertColumn_3, 1693).
--define(wxListCtrl_InsertItem_1, 1694).
--define(wxListCtrl_InsertItem_2_1, 1695).
--define(wxListCtrl_InsertItem_2_0, 1696).
--define(wxListCtrl_InsertItem_3, 1697).
--define(wxListCtrl_RefreshItem, 1698).
--define(wxListCtrl_RefreshItems, 1699).
--define(wxListCtrl_ScrollList, 1700).
--define(wxListCtrl_SetBackgroundColour, 1701).
--define(wxListCtrl_SetColumn, 1702).
--define(wxListCtrl_SetColumnWidth, 1703).
--define(wxListCtrl_SetImageList, 1704).
--define(wxListCtrl_SetItem_1, 1705).
--define(wxListCtrl_SetItem_4, 1706).
--define(wxListCtrl_SetItemBackgroundColour, 1707).
--define(wxListCtrl_SetItemCount, 1708).
--define(wxListCtrl_SetItemData, 1709).
--define(wxListCtrl_SetItemFont, 1710).
--define(wxListCtrl_SetItemImage, 1711).
--define(wxListCtrl_SetItemColumnImage, 1712).
--define(wxListCtrl_SetItemPosition, 1713).
--define(wxListCtrl_SetItemState, 1714).
--define(wxListCtrl_SetItemText, 1715).
--define(wxListCtrl_SetItemTextColour, 1716).
--define(wxListCtrl_SetSingleStyle, 1717).
--define(wxListCtrl_SetTextColour, 1718).
--define(wxListCtrl_SetWindowStyleFlag, 1719).
--define(wxListCtrl_SortItems, 1720).
--define(wxListCtrl_destroy, 1721).
--define(wxListView_ClearColumnImage, 1722).
--define(wxListView_Focus, 1723).
--define(wxListView_GetFirstSelected, 1724).
--define(wxListView_GetFocusedItem, 1725).
--define(wxListView_GetNextSelected, 1726).
--define(wxListView_IsSelected, 1727).
--define(wxListView_Select, 1728).
--define(wxListView_SetColumnImage, 1729).
--define(wxListItem_new_0, 1730).
--define(wxListItem_new_1, 1731).
--define(wxListItem_destruct, 1732).
--define(wxListItem_Clear, 1733).
--define(wxListItem_GetAlign, 1734).
--define(wxListItem_GetBackgroundColour, 1735).
--define(wxListItem_GetColumn, 1736).
--define(wxListItem_GetFont, 1737).
--define(wxListItem_GetId, 1738).
--define(wxListItem_GetImage, 1739).
--define(wxListItem_GetMask, 1740).
--define(wxListItem_GetState, 1741).
--define(wxListItem_GetText, 1742).
--define(wxListItem_GetTextColour, 1743).
--define(wxListItem_GetWidth, 1744).
--define(wxListItem_SetAlign, 1745).
--define(wxListItem_SetBackgroundColour, 1746).
--define(wxListItem_SetColumn, 1747).
--define(wxListItem_SetFont, 1748).
--define(wxListItem_SetId, 1749).
--define(wxListItem_SetImage, 1750).
--define(wxListItem_SetMask, 1751).
--define(wxListItem_SetState, 1752).
--define(wxListItem_SetStateMask, 1753).
--define(wxListItem_SetText, 1754).
--define(wxListItem_SetTextColour, 1755).
--define(wxListItem_SetWidth, 1756).
--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).
+-define(wxDC_GetFont, 667).
+-define(wxDC_GetLayoutDirection, 668).
+-define(wxDC_GetLogicalFunction, 669).
+-define(wxDC_GetMapMode, 670).
+-define(wxDC_GetMultiLineTextExtent_4, 671).
+-define(wxDC_GetMultiLineTextExtent_1, 672).
+-define(wxDC_GetPartialTextExtents, 673).
+-define(wxDC_GetPen, 674).
+-define(wxDC_GetPixel, 675).
+-define(wxDC_GetPPI, 676).
+-define(wxDC_GetSize, 678).
+-define(wxDC_GetSizeMM, 680).
+-define(wxDC_GetTextBackground, 681).
+-define(wxDC_GetTextExtent_4, 682).
+-define(wxDC_GetTextExtent_1, 683).
+-define(wxDC_GetTextForeground, 685).
+-define(wxDC_GetUserScale, 686).
+-define(wxDC_GradientFillConcentric_3, 687).
+-define(wxDC_GradientFillConcentric_4, 688).
+-define(wxDC_GradientFillLinear, 689).
+-define(wxDC_LogicalToDeviceX, 690).
+-define(wxDC_LogicalToDeviceXRel, 691).
+-define(wxDC_LogicalToDeviceY, 692).
+-define(wxDC_LogicalToDeviceYRel, 693).
+-define(wxDC_MaxX, 694).
+-define(wxDC_MaxY, 695).
+-define(wxDC_MinX, 696).
+-define(wxDC_MinY, 697).
+-define(wxDC_IsOk, 698).
+-define(wxDC_ResetBoundingBox, 699).
+-define(wxDC_SetAxisOrientation, 700).
+-define(wxDC_SetBackground, 701).
+-define(wxDC_SetBackgroundMode, 702).
+-define(wxDC_SetBrush, 703).
+-define(wxDC_SetClippingRegion_2, 705).
+-define(wxDC_SetClippingRegion_1_1, 706).
+-define(wxDC_SetClippingRegion_1_0, 707).
+-define(wxDC_SetDeviceOrigin, 708).
+-define(wxDC_SetFont, 709).
+-define(wxDC_SetLayoutDirection, 710).
+-define(wxDC_SetLogicalFunction, 711).
+-define(wxDC_SetMapMode, 712).
+-define(wxDC_SetPalette, 713).
+-define(wxDC_SetPen, 714).
+-define(wxDC_SetTextBackground, 715).
+-define(wxDC_SetTextForeground, 716).
+-define(wxDC_SetUserScale, 717).
+-define(wxDC_StartDoc, 718).
+-define(wxDC_StartPage, 719).
+-define(wxMirrorDC_new, 720).
+-define(wxMirrorDC_destroy, 721).
+-define(wxScreenDC_new, 722).
+-define(wxScreenDC_destruct, 723).
+-define(wxPostScriptDC_new_0, 724).
+-define(wxPostScriptDC_new_1, 725).
+-define(wxPostScriptDC_destruct, 726).
+-define(wxPostScriptDC_SetResolution, 727).
+-define(wxPostScriptDC_GetResolution, 728).
+-define(wxWindowDC_new_0, 729).
+-define(wxWindowDC_new_1, 730).
+-define(wxWindowDC_destruct, 731).
+-define(wxClientDC_new_0, 732).
+-define(wxClientDC_new_1, 733).
+-define(wxClientDC_destroy, 734).
+-define(wxPaintDC_new_0, 735).
+-define(wxPaintDC_new_1, 736).
+-define(wxPaintDC_destroy, 737).
+-define(wxMemoryDC_new_1_0, 739).
+-define(wxMemoryDC_new_1_1, 740).
+-define(wxMemoryDC_new_0, 741).
+-define(wxMemoryDC_destruct, 743).
+-define(wxMemoryDC_SelectObject, 744).
+-define(wxMemoryDC_SelectObjectAsSource, 745).
+-define(wxBufferedDC_new_0, 746).
+-define(wxBufferedDC_new_2, 747).
+-define(wxBufferedDC_new_3, 748).
+-define(wxBufferedDC_destruct, 749).
+-define(wxBufferedDC_Init_2, 750).
+-define(wxBufferedDC_Init_3, 751).
+-define(wxBufferedPaintDC_new_3, 752).
+-define(wxBufferedPaintDC_new_2, 753).
+-define(wxBufferedPaintDC_destruct, 754).
+-define(wxGraphicsObject_destruct, 755).
+-define(wxGraphicsObject_GetRenderer, 756).
+-define(wxGraphicsObject_IsNull, 757).
+-define(wxGraphicsContext_destruct, 758).
+-define(wxGraphicsContext_Create_1_1, 759).
+-define(wxGraphicsContext_Create_1_0, 760).
+-define(wxGraphicsContext_Create_0, 761).
+-define(wxGraphicsContext_CreatePen, 762).
+-define(wxGraphicsContext_CreateBrush, 763).
+-define(wxGraphicsContext_CreateRadialGradientBrush, 764).
+-define(wxGraphicsContext_CreateLinearGradientBrush, 765).
+-define(wxGraphicsContext_CreateFont, 766).
+-define(wxGraphicsContext_CreateMatrix, 767).
+-define(wxGraphicsContext_CreatePath, 768).
+-define(wxGraphicsContext_Clip_1, 769).
+-define(wxGraphicsContext_Clip_4, 770).
+-define(wxGraphicsContext_ResetClip, 771).
+-define(wxGraphicsContext_DrawBitmap, 772).
+-define(wxGraphicsContext_DrawEllipse, 773).
+-define(wxGraphicsContext_DrawIcon, 774).
+-define(wxGraphicsContext_DrawLines, 775).
+-define(wxGraphicsContext_DrawPath, 776).
+-define(wxGraphicsContext_DrawRectangle, 777).
+-define(wxGraphicsContext_DrawRoundedRectangle, 778).
+-define(wxGraphicsContext_DrawText_3, 779).
+-define(wxGraphicsContext_DrawText_4_0, 780).
+-define(wxGraphicsContext_DrawText_4_1, 781).
+-define(wxGraphicsContext_DrawText_5, 782).
+-define(wxGraphicsContext_FillPath, 783).
+-define(wxGraphicsContext_StrokePath, 784).
+-define(wxGraphicsContext_GetPartialTextExtents, 785).
+-define(wxGraphicsContext_GetTextExtent, 786).
+-define(wxGraphicsContext_Rotate, 787).
+-define(wxGraphicsContext_Scale, 788).
+-define(wxGraphicsContext_Translate, 789).
+-define(wxGraphicsContext_GetTransform, 790).
+-define(wxGraphicsContext_SetTransform, 791).
+-define(wxGraphicsContext_ConcatTransform, 792).
+-define(wxGraphicsContext_SetBrush_1_1, 793).
+-define(wxGraphicsContext_SetBrush_1_0, 794).
+-define(wxGraphicsContext_SetFont_1, 795).
+-define(wxGraphicsContext_SetFont_2, 796).
+-define(wxGraphicsContext_SetPen_1_0, 797).
+-define(wxGraphicsContext_SetPen_1_1, 798).
+-define(wxGraphicsContext_StrokeLine, 799).
+-define(wxGraphicsContext_StrokeLines, 800).
+-define(wxGraphicsMatrix_Concat, 802).
+-define(wxGraphicsMatrix_Get, 804).
+-define(wxGraphicsMatrix_Invert, 805).
+-define(wxGraphicsMatrix_IsEqual, 806).
+-define(wxGraphicsMatrix_IsIdentity, 808).
+-define(wxGraphicsMatrix_Rotate, 809).
+-define(wxGraphicsMatrix_Scale, 810).
+-define(wxGraphicsMatrix_Translate, 811).
+-define(wxGraphicsMatrix_Set, 812).
+-define(wxGraphicsMatrix_TransformPoint, 813).
+-define(wxGraphicsMatrix_TransformDistance, 814).
+-define(wxGraphicsPath_MoveToPoint_2, 815).
+-define(wxGraphicsPath_MoveToPoint_1, 816).
+-define(wxGraphicsPath_AddArc_6, 817).
+-define(wxGraphicsPath_AddArc_5, 818).
+-define(wxGraphicsPath_AddArcToPoint, 819).
+-define(wxGraphicsPath_AddCircle, 820).
+-define(wxGraphicsPath_AddCurveToPoint_6, 821).
+-define(wxGraphicsPath_AddCurveToPoint_3, 822).
+-define(wxGraphicsPath_AddEllipse, 823).
+-define(wxGraphicsPath_AddLineToPoint_2, 824).
+-define(wxGraphicsPath_AddLineToPoint_1, 825).
+-define(wxGraphicsPath_AddPath, 826).
+-define(wxGraphicsPath_AddQuadCurveToPoint, 827).
+-define(wxGraphicsPath_AddRectangle, 828).
+-define(wxGraphicsPath_AddRoundedRectangle, 829).
+-define(wxGraphicsPath_CloseSubpath, 830).
+-define(wxGraphicsPath_Contains_3, 831).
+-define(wxGraphicsPath_Contains_2, 832).
+-define(wxGraphicsPath_GetBox, 834).
+-define(wxGraphicsPath_GetCurrentPoint, 836).
+-define(wxGraphicsPath_Transform, 837).
+-define(wxGraphicsRenderer_GetDefaultRenderer, 838).
+-define(wxGraphicsRenderer_CreateContext_1_1, 839).
+-define(wxGraphicsRenderer_CreateContext_1_0, 840).
+-define(wxGraphicsRenderer_CreatePen, 841).
+-define(wxGraphicsRenderer_CreateBrush, 842).
+-define(wxGraphicsRenderer_CreateLinearGradientBrush, 843).
+-define(wxGraphicsRenderer_CreateRadialGradientBrush, 844).
+-define(wxGraphicsRenderer_CreateFont, 845).
+-define(wxGraphicsRenderer_CreateMatrix, 846).
+-define(wxGraphicsRenderer_CreatePath, 847).
+-define(wxMenuBar_new_1, 849).
+-define(wxMenuBar_new_0, 851).
+-define(wxMenuBar_destruct, 853).
+-define(wxMenuBar_Append, 854).
+-define(wxMenuBar_Check, 855).
+-define(wxMenuBar_Enable_2, 856).
+-define(wxMenuBar_Enable_1, 857).
+-define(wxMenuBar_EnableTop, 858).
+-define(wxMenuBar_FindMenu, 859).
+-define(wxMenuBar_FindMenuItem, 860).
+-define(wxMenuBar_FindItem, 861).
+-define(wxMenuBar_GetHelpString, 862).
+-define(wxMenuBar_GetLabel_1, 863).
+-define(wxMenuBar_GetLabel_0, 864).
+-define(wxMenuBar_GetLabelTop, 865).
+-define(wxMenuBar_GetMenu, 866).
+-define(wxMenuBar_GetMenuCount, 867).
+-define(wxMenuBar_Insert, 868).
+-define(wxMenuBar_IsChecked, 869).
+-define(wxMenuBar_IsEnabled_1, 870).
+-define(wxMenuBar_IsEnabled_0, 871).
+-define(wxMenuBar_Remove, 872).
+-define(wxMenuBar_Replace, 873).
+-define(wxMenuBar_SetHelpString, 874).
+-define(wxMenuBar_SetLabel_2, 875).
+-define(wxMenuBar_SetLabel_1, 876).
+-define(wxMenuBar_SetLabelTop, 877).
+-define(wxControl_GetLabel, 878).
+-define(wxControl_SetLabel, 879).
+-define(wxControlWithItems_Append_1, 880).
+-define(wxControlWithItems_Append_2, 881).
+-define(wxControlWithItems_appendStrings_1, 882).
+-define(wxControlWithItems_Clear, 883).
+-define(wxControlWithItems_Delete, 884).
+-define(wxControlWithItems_FindString, 885).
+-define(wxControlWithItems_getClientData, 886).
+-define(wxControlWithItems_setClientData, 887).
+-define(wxControlWithItems_GetCount, 888).
+-define(wxControlWithItems_GetSelection, 889).
+-define(wxControlWithItems_GetString, 890).
+-define(wxControlWithItems_GetStringSelection, 891).
+-define(wxControlWithItems_Insert_2, 892).
+-define(wxControlWithItems_Insert_3, 893).
+-define(wxControlWithItems_IsEmpty, 894).
+-define(wxControlWithItems_Select, 895).
+-define(wxControlWithItems_SetSelection, 896).
+-define(wxControlWithItems_SetString, 897).
+-define(wxControlWithItems_SetStringSelection, 898).
+-define(wxMenu_new_2, 901).
+-define(wxMenu_new_1, 902).
+-define(wxMenu_destruct, 904).
+-define(wxMenu_Append_3, 905).
+-define(wxMenu_Append_1, 906).
+-define(wxMenu_Append_4_0, 907).
+-define(wxMenu_Append_4_1, 908).
+-define(wxMenu_AppendCheckItem, 909).
+-define(wxMenu_AppendRadioItem, 910).
+-define(wxMenu_AppendSeparator, 911).
+-define(wxMenu_Break, 912).
+-define(wxMenu_Check, 913).
+-define(wxMenu_Delete_1_0, 914).
+-define(wxMenu_Delete_1_1, 915).
+-define(wxMenu_Destroy_1_0, 916).
+-define(wxMenu_Destroy_1_1, 917).
+-define(wxMenu_Enable, 918).
+-define(wxMenu_FindItem_1, 919).
+-define(wxMenu_FindItem_2, 920).
+-define(wxMenu_FindItemByPosition, 921).
+-define(wxMenu_GetHelpString, 922).
+-define(wxMenu_GetLabel, 923).
+-define(wxMenu_GetMenuItemCount, 924).
+-define(wxMenu_GetMenuItems, 925).
+-define(wxMenu_GetTitle, 927).
+-define(wxMenu_Insert_2, 928).
+-define(wxMenu_Insert_3, 929).
+-define(wxMenu_Insert_5_1, 930).
+-define(wxMenu_Insert_5_0, 931).
+-define(wxMenu_InsertCheckItem, 932).
+-define(wxMenu_InsertRadioItem, 933).
+-define(wxMenu_InsertSeparator, 934).
+-define(wxMenu_IsChecked, 935).
+-define(wxMenu_IsEnabled, 936).
+-define(wxMenu_Prepend_1, 937).
+-define(wxMenu_Prepend_2, 938).
+-define(wxMenu_Prepend_4_1, 939).
+-define(wxMenu_Prepend_4_0, 940).
+-define(wxMenu_PrependCheckItem, 941).
+-define(wxMenu_PrependRadioItem, 942).
+-define(wxMenu_PrependSeparator, 943).
+-define(wxMenu_Remove_1_0, 944).
+-define(wxMenu_Remove_1_1, 945).
+-define(wxMenu_SetHelpString, 946).
+-define(wxMenu_SetLabel, 947).
+-define(wxMenu_SetTitle, 948).
+-define(wxMenuItem_new, 949).
+-define(wxMenuItem_destruct, 951).
+-define(wxMenuItem_Check, 952).
+-define(wxMenuItem_Enable, 953).
+-define(wxMenuItem_GetBitmap, 954).
+-define(wxMenuItem_GetHelp, 955).
+-define(wxMenuItem_GetId, 956).
+-define(wxMenuItem_GetKind, 957).
+-define(wxMenuItem_GetLabel, 958).
+-define(wxMenuItem_GetLabelFromText, 959).
+-define(wxMenuItem_GetMenu, 960).
+-define(wxMenuItem_GetText, 961).
+-define(wxMenuItem_GetSubMenu, 962).
+-define(wxMenuItem_IsCheckable, 963).
+-define(wxMenuItem_IsChecked, 964).
+-define(wxMenuItem_IsEnabled, 965).
+-define(wxMenuItem_IsSeparator, 966).
+-define(wxMenuItem_IsSubMenu, 967).
+-define(wxMenuItem_SetBitmap, 968).
+-define(wxMenuItem_SetHelp, 969).
+-define(wxMenuItem_SetMenu, 970).
+-define(wxMenuItem_SetSubMenu, 971).
+-define(wxMenuItem_SetText, 972).
+-define(wxToolBar_AddControl, 973).
+-define(wxToolBar_AddSeparator, 974).
+-define(wxToolBar_AddTool_5, 975).
+-define(wxToolBar_AddTool_4_0, 976).
+-define(wxToolBar_AddTool_1, 977).
+-define(wxToolBar_AddTool_4_1, 978).
+-define(wxToolBar_AddTool_3, 979).
+-define(wxToolBar_AddTool_6, 980).
+-define(wxToolBar_AddCheckTool, 981).
+-define(wxToolBar_AddRadioTool, 982).
+-define(wxToolBar_DeleteTool, 983).
+-define(wxToolBar_DeleteToolByPos, 984).
+-define(wxToolBar_EnableTool, 985).
+-define(wxToolBar_FindById, 986).
+-define(wxToolBar_FindControl, 987).
+-define(wxToolBar_FindToolForPosition, 988).
+-define(wxToolBar_GetToolSize, 989).
+-define(wxToolBar_GetToolBitmapSize, 990).
+-define(wxToolBar_GetMargins, 991).
+-define(wxToolBar_GetToolEnabled, 992).
+-define(wxToolBar_GetToolLongHelp, 993).
+-define(wxToolBar_GetToolPacking, 994).
+-define(wxToolBar_GetToolPos, 995).
+-define(wxToolBar_GetToolSeparation, 996).
+-define(wxToolBar_GetToolShortHelp, 997).
+-define(wxToolBar_GetToolState, 998).
+-define(wxToolBar_InsertControl, 999).
+-define(wxToolBar_InsertSeparator, 1000).
+-define(wxToolBar_InsertTool_5, 1001).
+-define(wxToolBar_InsertTool_2, 1002).
+-define(wxToolBar_InsertTool_4, 1003).
+-define(wxToolBar_Realize, 1004).
+-define(wxToolBar_RemoveTool, 1005).
+-define(wxToolBar_SetMargins, 1006).
+-define(wxToolBar_SetToolBitmapSize, 1007).
+-define(wxToolBar_SetToolLongHelp, 1008).
+-define(wxToolBar_SetToolPacking, 1009).
+-define(wxToolBar_SetToolShortHelp, 1010).
+-define(wxToolBar_SetToolSeparation, 1011).
+-define(wxToolBar_ToggleTool, 1012).
+-define(wxStatusBar_new_0, 1014).
+-define(wxStatusBar_new_2, 1015).
+-define(wxStatusBar_destruct, 1017).
+-define(wxStatusBar_Create, 1018).
+-define(wxStatusBar_GetFieldRect, 1019).
+-define(wxStatusBar_GetFieldsCount, 1020).
+-define(wxStatusBar_GetStatusText, 1021).
+-define(wxStatusBar_PopStatusText, 1022).
+-define(wxStatusBar_PushStatusText, 1023).
+-define(wxStatusBar_SetFieldsCount, 1024).
+-define(wxStatusBar_SetMinHeight, 1025).
+-define(wxStatusBar_SetStatusText, 1026).
+-define(wxStatusBar_SetStatusWidths, 1027).
+-define(wxStatusBar_SetStatusStyles, 1028).
+-define(wxBitmap_new_0, 1029).
+-define(wxBitmap_new_3, 1030).
+-define(wxBitmap_new_4, 1031).
+-define(wxBitmap_new_2_0, 1032).
+-define(wxBitmap_new_2_1, 1033).
+-define(wxBitmap_destruct, 1034).
+-define(wxBitmap_ConvertToImage, 1035).
+-define(wxBitmap_CopyFromIcon, 1036).
+-define(wxBitmap_Create, 1037).
+-define(wxBitmap_GetDepth, 1038).
+-define(wxBitmap_GetHeight, 1039).
+-define(wxBitmap_GetPalette, 1040).
+-define(wxBitmap_GetMask, 1041).
+-define(wxBitmap_GetWidth, 1042).
+-define(wxBitmap_GetSubBitmap, 1043).
+-define(wxBitmap_LoadFile, 1044).
+-define(wxBitmap_Ok, 1045).
+-define(wxBitmap_SaveFile, 1046).
+-define(wxBitmap_SetDepth, 1047).
+-define(wxBitmap_SetHeight, 1048).
+-define(wxBitmap_SetMask, 1049).
+-define(wxBitmap_SetPalette, 1050).
+-define(wxBitmap_SetWidth, 1051).
+-define(wxIcon_new_0, 1052).
+-define(wxIcon_new_2, 1053).
+-define(wxIcon_new_1, 1054).
+-define(wxIcon_CopyFromBitmap, 1055).
+-define(wxIcon_destroy, 1056).
+-define(wxIconBundle_new_0, 1057).
+-define(wxIconBundle_new_2, 1058).
+-define(wxIconBundle_new_1_0, 1059).
+-define(wxIconBundle_new_1_1, 1060).
+-define(wxIconBundle_destruct, 1061).
+-define(wxIconBundle_AddIcon_2, 1062).
+-define(wxIconBundle_AddIcon_1, 1063).
+-define(wxIconBundle_GetIcon_1_1, 1064).
+-define(wxIconBundle_GetIcon_1_0, 1065).
+-define(wxCursor_new_0, 1066).
+-define(wxCursor_new_1_0, 1067).
+-define(wxCursor_new_1_1, 1068).
+-define(wxCursor_new_4, 1069).
+-define(wxCursor_destruct, 1070).
+-define(wxCursor_Ok, 1071).
+-define(wxMask_new_0, 1072).
+-define(wxMask_new_2_1, 1073).
+-define(wxMask_new_2_0, 1074).
+-define(wxMask_new_1, 1075).
+-define(wxMask_destruct, 1076).
+-define(wxMask_Create_2_1, 1077).
+-define(wxMask_Create_2_0, 1078).
+-define(wxMask_Create_1, 1079).
+-define(wxImage_new_0, 1080).
+-define(wxImage_new_3_0, 1081).
+-define(wxImage_new_4, 1082).
+-define(wxImage_new_5, 1083).
+-define(wxImage_new_2, 1084).
+-define(wxImage_new_3_1, 1085).
+-define(wxImage_Blur, 1086).
+-define(wxImage_BlurHorizontal, 1087).
+-define(wxImage_BlurVertical, 1088).
+-define(wxImage_ConvertAlphaToMask, 1089).
+-define(wxImage_ConvertToGreyscale, 1090).
+-define(wxImage_ConvertToMono, 1091).
+-define(wxImage_Copy, 1092).
+-define(wxImage_Create_3, 1093).
+-define(wxImage_Create_4, 1094).
+-define(wxImage_Create_5, 1095).
+-define(wxImage_Destroy, 1096).
+-define(wxImage_FindFirstUnusedColour, 1097).
+-define(wxImage_GetImageExtWildcard, 1098).
+-define(wxImage_GetAlpha_2, 1099).
+-define(wxImage_GetAlpha_0, 1100).
+-define(wxImage_GetBlue, 1101).
+-define(wxImage_GetData, 1102).
+-define(wxImage_GetGreen, 1103).
+-define(wxImage_GetImageCount, 1104).
+-define(wxImage_GetHeight, 1105).
+-define(wxImage_GetMaskBlue, 1106).
+-define(wxImage_GetMaskGreen, 1107).
+-define(wxImage_GetMaskRed, 1108).
+-define(wxImage_GetOrFindMaskColour, 1109).
+-define(wxImage_GetPalette, 1110).
+-define(wxImage_GetRed, 1111).
+-define(wxImage_GetSubImage, 1112).
+-define(wxImage_GetWidth, 1113).
+-define(wxImage_HasAlpha, 1114).
+-define(wxImage_HasMask, 1115).
+-define(wxImage_GetOption, 1116).
+-define(wxImage_GetOptionInt, 1117).
+-define(wxImage_HasOption, 1118).
+-define(wxImage_InitAlpha, 1119).
+-define(wxImage_InitStandardHandlers, 1120).
+-define(wxImage_IsTransparent, 1121).
+-define(wxImage_LoadFile_2, 1122).
+-define(wxImage_LoadFile_3, 1123).
+-define(wxImage_Ok, 1124).
+-define(wxImage_RemoveHandler, 1125).
+-define(wxImage_Mirror, 1126).
+-define(wxImage_Replace, 1127).
+-define(wxImage_Rescale, 1128).
+-define(wxImage_Resize, 1129).
+-define(wxImage_Rotate, 1130).
+-define(wxImage_RotateHue, 1131).
+-define(wxImage_Rotate90, 1132).
+-define(wxImage_SaveFile_1, 1133).
+-define(wxImage_SaveFile_2_0, 1134).
+-define(wxImage_SaveFile_2_1, 1135).
+-define(wxImage_Scale, 1136).
+-define(wxImage_Size, 1137).
+-define(wxImage_SetAlpha_3, 1138).
+-define(wxImage_SetAlpha_2, 1139).
+-define(wxImage_SetData_2, 1140).
+-define(wxImage_SetData_4, 1141).
+-define(wxImage_SetMask, 1142).
+-define(wxImage_SetMaskColour, 1143).
+-define(wxImage_SetMaskFromImage, 1144).
+-define(wxImage_SetOption_2_1, 1145).
+-define(wxImage_SetOption_2_0, 1146).
+-define(wxImage_SetPalette, 1147).
+-define(wxImage_SetRGB_5, 1148).
+-define(wxImage_SetRGB_4, 1149).
+-define(wxImage_destroy, 1150).
+-define(wxBrush_new_0, 1151).
+-define(wxBrush_new_2, 1152).
+-define(wxBrush_new_1, 1153).
+-define(wxBrush_destruct, 1155).
+-define(wxBrush_GetColour, 1156).
+-define(wxBrush_GetStipple, 1157).
+-define(wxBrush_GetStyle, 1158).
+-define(wxBrush_IsHatch, 1159).
+-define(wxBrush_IsOk, 1160).
+-define(wxBrush_SetColour_1, 1161).
+-define(wxBrush_SetColour_3, 1162).
+-define(wxBrush_SetStipple, 1163).
+-define(wxBrush_SetStyle, 1164).
+-define(wxPen_new_0, 1165).
+-define(wxPen_new_2, 1166).
+-define(wxPen_destruct, 1167).
+-define(wxPen_GetCap, 1168).
+-define(wxPen_GetColour, 1169).
+-define(wxPen_GetJoin, 1170).
+-define(wxPen_GetStyle, 1171).
+-define(wxPen_GetWidth, 1172).
+-define(wxPen_IsOk, 1173).
+-define(wxPen_SetCap, 1174).
+-define(wxPen_SetColour_1, 1175).
+-define(wxPen_SetColour_3, 1176).
+-define(wxPen_SetJoin, 1177).
+-define(wxPen_SetStyle, 1178).
+-define(wxPen_SetWidth, 1179).
+-define(wxRegion_new_0, 1180).
+-define(wxRegion_new_4, 1181).
+-define(wxRegion_new_2, 1182).
+-define(wxRegion_new_1_1, 1183).
+-define(wxRegion_new_1_0, 1185).
+-define(wxRegion_destruct, 1187).
+-define(wxRegion_Clear, 1188).
+-define(wxRegion_Contains_2, 1189).
+-define(wxRegion_Contains_1_0, 1190).
+-define(wxRegion_Contains_4, 1191).
+-define(wxRegion_Contains_1_1, 1192).
+-define(wxRegion_ConvertToBitmap, 1193).
+-define(wxRegion_GetBox, 1194).
+-define(wxRegion_Intersect_4, 1195).
+-define(wxRegion_Intersect_1_1, 1196).
+-define(wxRegion_Intersect_1_0, 1197).
+-define(wxRegion_IsEmpty, 1198).
+-define(wxRegion_Subtract_4, 1199).
+-define(wxRegion_Subtract_1_1, 1200).
+-define(wxRegion_Subtract_1_0, 1201).
+-define(wxRegion_Offset_2, 1202).
+-define(wxRegion_Offset_1, 1203).
+-define(wxRegion_Union_4, 1204).
+-define(wxRegion_Union_1_2, 1205).
+-define(wxRegion_Union_1_1, 1206).
+-define(wxRegion_Union_1_0, 1207).
+-define(wxRegion_Union_3, 1208).
+-define(wxRegion_Xor_4, 1209).
+-define(wxRegion_Xor_1_1, 1210).
+-define(wxRegion_Xor_1_0, 1211).
+-define(wxAcceleratorTable_new_0, 1212).
+-define(wxAcceleratorTable_new_2, 1213).
+-define(wxAcceleratorTable_destruct, 1214).
+-define(wxAcceleratorTable_Ok, 1215).
+-define(wxAcceleratorEntry_new_1_0, 1216).
+-define(wxAcceleratorEntry_new_1_1, 1217).
+-define(wxAcceleratorEntry_GetCommand, 1218).
+-define(wxAcceleratorEntry_GetFlags, 1219).
+-define(wxAcceleratorEntry_GetKeyCode, 1220).
+-define(wxAcceleratorEntry_Set, 1221).
+-define(wxAcceleratorEntry_destroy, 1222).
+-define(wxCaret_new_3, 1227).
+-define(wxCaret_new_2, 1228).
+-define(wxCaret_destruct, 1230).
+-define(wxCaret_Create_3, 1231).
+-define(wxCaret_Create_2, 1232).
+-define(wxCaret_GetBlinkTime, 1233).
+-define(wxCaret_GetPosition, 1235).
+-define(wxCaret_GetSize, 1237).
+-define(wxCaret_GetWindow, 1238).
+-define(wxCaret_Hide, 1239).
+-define(wxCaret_IsOk, 1240).
+-define(wxCaret_IsVisible, 1241).
+-define(wxCaret_Move_2, 1242).
+-define(wxCaret_Move_1, 1243).
+-define(wxCaret_SetBlinkTime, 1244).
+-define(wxCaret_SetSize_2, 1245).
+-define(wxCaret_SetSize_1, 1246).
+-define(wxCaret_Show, 1247).
+-define(wxSizer_Add_2_1, 1248).
+-define(wxSizer_Add_2_0, 1249).
+-define(wxSizer_Add_3, 1250).
+-define(wxSizer_Add_2_3, 1251).
+-define(wxSizer_Add_2_2, 1252).
+-define(wxSizer_AddSpacer, 1253).
+-define(wxSizer_AddStretchSpacer, 1254).
+-define(wxSizer_CalcMin, 1255).
+-define(wxSizer_Clear, 1256).
+-define(wxSizer_Detach_1_2, 1257).
+-define(wxSizer_Detach_1_1, 1258).
+-define(wxSizer_Detach_1_0, 1259).
+-define(wxSizer_Fit, 1260).
+-define(wxSizer_FitInside, 1261).
+-define(wxSizer_GetChildren, 1262).
+-define(wxSizer_GetItem_2_1, 1263).
+-define(wxSizer_GetItem_2_0, 1264).
+-define(wxSizer_GetItem_1, 1265).
+-define(wxSizer_GetSize, 1266).
+-define(wxSizer_GetPosition, 1267).
+-define(wxSizer_GetMinSize, 1268).
+-define(wxSizer_Hide_2_0, 1269).
+-define(wxSizer_Hide_2_1, 1270).
+-define(wxSizer_Hide_1, 1271).
+-define(wxSizer_Insert_3_1, 1272).
+-define(wxSizer_Insert_3_0, 1273).
+-define(wxSizer_Insert_4, 1274).
+-define(wxSizer_Insert_3_3, 1275).
+-define(wxSizer_Insert_3_2, 1276).
+-define(wxSizer_Insert_2, 1277).
+-define(wxSizer_InsertSpacer, 1278).
+-define(wxSizer_InsertStretchSpacer, 1279).
+-define(wxSizer_IsShown_1_2, 1280).
+-define(wxSizer_IsShown_1_1, 1281).
+-define(wxSizer_IsShown_1_0, 1282).
+-define(wxSizer_Layout, 1283).
+-define(wxSizer_Prepend_2_1, 1284).
+-define(wxSizer_Prepend_2_0, 1285).
+-define(wxSizer_Prepend_3, 1286).
+-define(wxSizer_Prepend_2_3, 1287).
+-define(wxSizer_Prepend_2_2, 1288).
+-define(wxSizer_Prepend_1, 1289).
+-define(wxSizer_PrependSpacer, 1290).
+-define(wxSizer_PrependStretchSpacer, 1291).
+-define(wxSizer_RecalcSizes, 1292).
+-define(wxSizer_Remove_1_1, 1293).
+-define(wxSizer_Remove_1_0, 1294).
+-define(wxSizer_Replace_3_1, 1295).
+-define(wxSizer_Replace_3_0, 1296).
+-define(wxSizer_Replace_2, 1297).
+-define(wxSizer_SetDimension, 1298).
+-define(wxSizer_SetMinSize_2, 1299).
+-define(wxSizer_SetMinSize_1, 1300).
+-define(wxSizer_SetItemMinSize_3_2, 1301).
+-define(wxSizer_SetItemMinSize_2_2, 1302).
+-define(wxSizer_SetItemMinSize_3_1, 1303).
+-define(wxSizer_SetItemMinSize_2_1, 1304).
+-define(wxSizer_SetItemMinSize_3_0, 1305).
+-define(wxSizer_SetItemMinSize_2_0, 1306).
+-define(wxSizer_SetSizeHints, 1307).
+-define(wxSizer_SetVirtualSizeHints, 1308).
+-define(wxSizer_Show_2_2, 1309).
+-define(wxSizer_Show_2_1, 1310).
+-define(wxSizer_Show_2_0, 1311).
+-define(wxSizer_Show_1, 1312).
+-define(wxSizerFlags_new, 1313).
+-define(wxSizerFlags_Align, 1314).
+-define(wxSizerFlags_Border_2, 1315).
+-define(wxSizerFlags_Border_1, 1316).
+-define(wxSizerFlags_Center, 1317).
+-define(wxSizerFlags_Centre, 1318).
+-define(wxSizerFlags_Expand, 1319).
+-define(wxSizerFlags_Left, 1320).
+-define(wxSizerFlags_Proportion, 1321).
+-define(wxSizerFlags_Right, 1322).
+-define(wxSizerFlags_destroy, 1323).
+-define(wxSizerItem_new_5_1, 1324).
+-define(wxSizerItem_new_2_1, 1325).
+-define(wxSizerItem_new_5_0, 1326).
+-define(wxSizerItem_new_2_0, 1327).
+-define(wxSizerItem_new_6, 1328).
+-define(wxSizerItem_new_3, 1329).
+-define(wxSizerItem_new_0, 1330).
+-define(wxSizerItem_destruct, 1331).
+-define(wxSizerItem_CalcMin, 1332).
+-define(wxSizerItem_DeleteWindows, 1333).
+-define(wxSizerItem_DetachSizer, 1334).
+-define(wxSizerItem_GetBorder, 1335).
+-define(wxSizerItem_GetFlag, 1336).
+-define(wxSizerItem_GetMinSize, 1337).
+-define(wxSizerItem_GetPosition, 1338).
+-define(wxSizerItem_GetProportion, 1339).
+-define(wxSizerItem_GetRatio, 1340).
+-define(wxSizerItem_GetRect, 1341).
+-define(wxSizerItem_GetSize, 1342).
+-define(wxSizerItem_GetSizer, 1343).
+-define(wxSizerItem_GetSpacer, 1344).
+-define(wxSizerItem_GetUserData, 1345).
+-define(wxSizerItem_GetWindow, 1346).
+-define(wxSizerItem_IsSizer, 1347).
+-define(wxSizerItem_IsShown, 1348).
+-define(wxSizerItem_IsSpacer, 1349).
+-define(wxSizerItem_IsWindow, 1350).
+-define(wxSizerItem_SetBorder, 1351).
+-define(wxSizerItem_SetDimension, 1352).
+-define(wxSizerItem_SetFlag, 1353).
+-define(wxSizerItem_SetInitSize, 1354).
+-define(wxSizerItem_SetMinSize_1, 1355).
+-define(wxSizerItem_SetMinSize_2, 1356).
+-define(wxSizerItem_SetProportion, 1357).
+-define(wxSizerItem_SetRatio_2, 1358).
+-define(wxSizerItem_SetRatio_1_1, 1359).
+-define(wxSizerItem_SetRatio_1_0, 1360).
+-define(wxSizerItem_SetSizer, 1361).
+-define(wxSizerItem_SetSpacer_1, 1362).
+-define(wxSizerItem_SetSpacer_2, 1363).
+-define(wxSizerItem_SetWindow, 1364).
+-define(wxSizerItem_Show, 1365).
+-define(wxBoxSizer_new, 1366).
+-define(wxBoxSizer_GetOrientation, 1367).
+-define(wxBoxSizer_destroy, 1368).
+-define(wxStaticBoxSizer_new_2, 1369).
+-define(wxStaticBoxSizer_new_3, 1370).
+-define(wxStaticBoxSizer_GetStaticBox, 1371).
+-define(wxStaticBoxSizer_destroy, 1372).
+-define(wxGridSizer_new_4, 1373).
+-define(wxGridSizer_new_2, 1374).
+-define(wxGridSizer_GetCols, 1375).
+-define(wxGridSizer_GetHGap, 1376).
+-define(wxGridSizer_GetRows, 1377).
+-define(wxGridSizer_GetVGap, 1378).
+-define(wxGridSizer_SetCols, 1379).
+-define(wxGridSizer_SetHGap, 1380).
+-define(wxGridSizer_SetRows, 1381).
+-define(wxGridSizer_SetVGap, 1382).
+-define(wxGridSizer_destroy, 1383).
+-define(wxFlexGridSizer_new_4, 1384).
+-define(wxFlexGridSizer_new_2, 1385).
+-define(wxFlexGridSizer_AddGrowableCol, 1386).
+-define(wxFlexGridSizer_AddGrowableRow, 1387).
+-define(wxFlexGridSizer_GetFlexibleDirection, 1388).
+-define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1389).
+-define(wxFlexGridSizer_RemoveGrowableCol, 1390).
+-define(wxFlexGridSizer_RemoveGrowableRow, 1391).
+-define(wxFlexGridSizer_SetFlexibleDirection, 1392).
+-define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1393).
+-define(wxFlexGridSizer_destroy, 1394).
+-define(wxGridBagSizer_new, 1395).
+-define(wxGridBagSizer_Add_3_2, 1396).
+-define(wxGridBagSizer_Add_3_1, 1397).
+-define(wxGridBagSizer_Add_4, 1398).
+-define(wxGridBagSizer_Add_1_0, 1399).
+-define(wxGridBagSizer_Add_2_1, 1400).
+-define(wxGridBagSizer_Add_2_0, 1401).
+-define(wxGridBagSizer_Add_3_0, 1402).
+-define(wxGridBagSizer_Add_1_1, 1403).
+-define(wxGridBagSizer_CalcMin, 1404).
+-define(wxGridBagSizer_CheckForIntersection_2, 1405).
+-define(wxGridBagSizer_CheckForIntersection_3, 1406).
+-define(wxGridBagSizer_FindItem_1_1, 1407).
+-define(wxGridBagSizer_FindItem_1_0, 1408).
+-define(wxGridBagSizer_FindItemAtPoint, 1409).
+-define(wxGridBagSizer_FindItemAtPosition, 1410).
+-define(wxGridBagSizer_FindItemWithData, 1411).
+-define(wxGridBagSizer_GetCellSize, 1412).
+-define(wxGridBagSizer_GetEmptyCellSize, 1413).
+-define(wxGridBagSizer_GetItemPosition_1_2, 1414).
+-define(wxGridBagSizer_GetItemPosition_1_1, 1415).
+-define(wxGridBagSizer_GetItemPosition_1_0, 1416).
+-define(wxGridBagSizer_GetItemSpan_1_2, 1417).
+-define(wxGridBagSizer_GetItemSpan_1_1, 1418).
+-define(wxGridBagSizer_GetItemSpan_1_0, 1419).
+-define(wxGridBagSizer_SetEmptyCellSize, 1420).
+-define(wxGridBagSizer_SetItemPosition_2_2, 1421).
+-define(wxGridBagSizer_SetItemPosition_2_1, 1422).
+-define(wxGridBagSizer_SetItemPosition_2_0, 1423).
+-define(wxGridBagSizer_SetItemSpan_2_2, 1424).
+-define(wxGridBagSizer_SetItemSpan_2_1, 1425).
+-define(wxGridBagSizer_SetItemSpan_2_0, 1426).
+-define(wxGridBagSizer_destroy, 1427).
+-define(wxStdDialogButtonSizer_new, 1428).
+-define(wxStdDialogButtonSizer_AddButton, 1429).
+-define(wxStdDialogButtonSizer_Realize, 1430).
+-define(wxStdDialogButtonSizer_SetAffirmativeButton, 1431).
+-define(wxStdDialogButtonSizer_SetCancelButton, 1432).
+-define(wxStdDialogButtonSizer_SetNegativeButton, 1433).
+-define(wxStdDialogButtonSizer_destroy, 1434).
+-define(wxFont_new_0, 1435).
+-define(wxFont_new_1, 1436).
+-define(wxFont_new_5, 1437).
+-define(wxFont_destruct, 1439).
+-define(wxFont_IsFixedWidth, 1440).
+-define(wxFont_GetDefaultEncoding, 1441).
+-define(wxFont_GetFaceName, 1442).
+-define(wxFont_GetFamily, 1443).
+-define(wxFont_GetNativeFontInfoDesc, 1444).
+-define(wxFont_GetNativeFontInfoUserDesc, 1445).
+-define(wxFont_GetPointSize, 1446).
+-define(wxFont_GetStyle, 1447).
+-define(wxFont_GetUnderlined, 1448).
+-define(wxFont_GetWeight, 1449).
+-define(wxFont_Ok, 1450).
+-define(wxFont_SetDefaultEncoding, 1451).
+-define(wxFont_SetFaceName, 1452).
+-define(wxFont_SetFamily, 1453).
+-define(wxFont_SetPointSize, 1454).
+-define(wxFont_SetStyle, 1455).
+-define(wxFont_SetUnderlined, 1456).
+-define(wxFont_SetWeight, 1457).
+-define(wxToolTip_Enable, 1458).
+-define(wxToolTip_SetDelay, 1459).
+-define(wxToolTip_new, 1460).
+-define(wxToolTip_SetTip, 1461).
+-define(wxToolTip_GetTip, 1462).
+-define(wxToolTip_GetWindow, 1463).
+-define(wxToolTip_destroy, 1464).
+-define(wxButton_new_3, 1466).
+-define(wxButton_new_0, 1467).
+-define(wxButton_destruct, 1468).
+-define(wxButton_Create, 1469).
+-define(wxButton_GetDefaultSize, 1470).
+-define(wxButton_SetDefault, 1471).
+-define(wxButton_SetLabel, 1472).
+-define(wxBitmapButton_new_4, 1474).
+-define(wxBitmapButton_new_0, 1475).
+-define(wxBitmapButton_Create, 1476).
+-define(wxBitmapButton_GetBitmapDisabled, 1477).
+-define(wxBitmapButton_GetBitmapFocus, 1479).
+-define(wxBitmapButton_GetBitmapLabel, 1481).
+-define(wxBitmapButton_GetBitmapSelected, 1483).
+-define(wxBitmapButton_SetBitmapDisabled, 1485).
+-define(wxBitmapButton_SetBitmapFocus, 1486).
+-define(wxBitmapButton_SetBitmapLabel, 1487).
+-define(wxBitmapButton_SetBitmapSelected, 1488).
+-define(wxBitmapButton_destroy, 1489).
+-define(wxToggleButton_new_0, 1490).
+-define(wxToggleButton_new_4, 1491).
+-define(wxToggleButton_Create, 1492).
+-define(wxToggleButton_GetValue, 1493).
+-define(wxToggleButton_SetValue, 1494).
+-define(wxToggleButton_destroy, 1495).
+-define(wxCalendarCtrl_new_0, 1496).
+-define(wxCalendarCtrl_new_3, 1497).
+-define(wxCalendarCtrl_Create, 1498).
+-define(wxCalendarCtrl_destruct, 1499).
+-define(wxCalendarCtrl_SetDate, 1500).
+-define(wxCalendarCtrl_GetDate, 1501).
+-define(wxCalendarCtrl_EnableYearChange, 1502).
+-define(wxCalendarCtrl_EnableMonthChange, 1503).
+-define(wxCalendarCtrl_EnableHolidayDisplay, 1504).
+-define(wxCalendarCtrl_SetHeaderColours, 1505).
+-define(wxCalendarCtrl_GetHeaderColourFg, 1506).
+-define(wxCalendarCtrl_GetHeaderColourBg, 1507).
+-define(wxCalendarCtrl_SetHighlightColours, 1508).
+-define(wxCalendarCtrl_GetHighlightColourFg, 1509).
+-define(wxCalendarCtrl_GetHighlightColourBg, 1510).
+-define(wxCalendarCtrl_SetHolidayColours, 1511).
+-define(wxCalendarCtrl_GetHolidayColourFg, 1512).
+-define(wxCalendarCtrl_GetHolidayColourBg, 1513).
+-define(wxCalendarCtrl_GetAttr, 1514).
+-define(wxCalendarCtrl_SetAttr, 1515).
+-define(wxCalendarCtrl_SetHoliday, 1516).
+-define(wxCalendarCtrl_ResetAttr, 1517).
+-define(wxCalendarCtrl_HitTest, 1518).
+-define(wxCalendarDateAttr_new_0, 1519).
+-define(wxCalendarDateAttr_new_2_1, 1520).
+-define(wxCalendarDateAttr_new_2_0, 1521).
+-define(wxCalendarDateAttr_SetTextColour, 1522).
+-define(wxCalendarDateAttr_SetBackgroundColour, 1523).
+-define(wxCalendarDateAttr_SetBorderColour, 1524).
+-define(wxCalendarDateAttr_SetFont, 1525).
+-define(wxCalendarDateAttr_SetBorder, 1526).
+-define(wxCalendarDateAttr_SetHoliday, 1527).
+-define(wxCalendarDateAttr_HasTextColour, 1528).
+-define(wxCalendarDateAttr_HasBackgroundColour, 1529).
+-define(wxCalendarDateAttr_HasBorderColour, 1530).
+-define(wxCalendarDateAttr_HasFont, 1531).
+-define(wxCalendarDateAttr_HasBorder, 1532).
+-define(wxCalendarDateAttr_IsHoliday, 1533).
+-define(wxCalendarDateAttr_GetTextColour, 1534).
+-define(wxCalendarDateAttr_GetBackgroundColour, 1535).
+-define(wxCalendarDateAttr_GetBorderColour, 1536).
+-define(wxCalendarDateAttr_GetFont, 1537).
+-define(wxCalendarDateAttr_GetBorder, 1538).
+-define(wxCalendarDateAttr_destroy, 1539).
+-define(wxCheckBox_new_4, 1541).
+-define(wxCheckBox_new_0, 1542).
+-define(wxCheckBox_Create, 1543).
+-define(wxCheckBox_GetValue, 1544).
+-define(wxCheckBox_Get3StateValue, 1545).
+-define(wxCheckBox_Is3rdStateAllowedForUser, 1546).
+-define(wxCheckBox_Is3State, 1547).
+-define(wxCheckBox_IsChecked, 1548).
+-define(wxCheckBox_SetValue, 1549).
+-define(wxCheckBox_Set3StateValue, 1550).
+-define(wxCheckBox_destroy, 1551).
+-define(wxCheckListBox_new_0, 1552).
+-define(wxCheckListBox_new_3, 1554).
+-define(wxCheckListBox_Check, 1555).
+-define(wxCheckListBox_IsChecked, 1556).
+-define(wxCheckListBox_destroy, 1557).
+-define(wxChoice_new_3, 1560).
+-define(wxChoice_new_0, 1561).
+-define(wxChoice_destruct, 1563).
+-define(wxChoice_Create, 1565).
+-define(wxChoice_Delete, 1566).
+-define(wxChoice_GetColumns, 1567).
+-define(wxChoice_SetColumns, 1568).
+-define(wxComboBox_new_0, 1569).
+-define(wxComboBox_new_3, 1571).
+-define(wxComboBox_destruct, 1572).
+-define(wxComboBox_Create, 1574).
+-define(wxComboBox_CanCopy, 1575).
+-define(wxComboBox_CanCut, 1576).
+-define(wxComboBox_CanPaste, 1577).
+-define(wxComboBox_CanRedo, 1578).
+-define(wxComboBox_CanUndo, 1579).
+-define(wxComboBox_Copy, 1580).
+-define(wxComboBox_Cut, 1581).
+-define(wxComboBox_GetInsertionPoint, 1582).
+-define(wxComboBox_GetLastPosition, 1583).
+-define(wxComboBox_GetValue, 1584).
+-define(wxComboBox_Paste, 1585).
+-define(wxComboBox_Redo, 1586).
+-define(wxComboBox_Replace, 1587).
+-define(wxComboBox_Remove, 1588).
+-define(wxComboBox_SetInsertionPoint, 1589).
+-define(wxComboBox_SetInsertionPointEnd, 1590).
+-define(wxComboBox_SetSelection_1, 1591).
+-define(wxComboBox_SetSelection_2, 1592).
+-define(wxComboBox_SetValue, 1593).
+-define(wxComboBox_Undo, 1594).
+-define(wxGauge_new_0, 1595).
+-define(wxGauge_new_4, 1596).
+-define(wxGauge_Create, 1597).
+-define(wxGauge_GetBezelFace, 1598).
+-define(wxGauge_GetRange, 1599).
+-define(wxGauge_GetShadowWidth, 1600).
+-define(wxGauge_GetValue, 1601).
+-define(wxGauge_IsVertical, 1602).
+-define(wxGauge_SetBezelFace, 1603).
+-define(wxGauge_SetRange, 1604).
+-define(wxGauge_SetShadowWidth, 1605).
+-define(wxGauge_SetValue, 1606).
+-define(wxGauge_Pulse, 1607).
+-define(wxGauge_destroy, 1608).
+-define(wxGenericDirCtrl_new_0, 1609).
+-define(wxGenericDirCtrl_new_2, 1610).
+-define(wxGenericDirCtrl_destruct, 1611).
+-define(wxGenericDirCtrl_Create, 1612).
+-define(wxGenericDirCtrl_Init, 1613).
+-define(wxGenericDirCtrl_CollapseTree, 1614).
+-define(wxGenericDirCtrl_ExpandPath, 1615).
+-define(wxGenericDirCtrl_GetDefaultPath, 1616).
+-define(wxGenericDirCtrl_GetPath, 1617).
+-define(wxGenericDirCtrl_GetFilePath, 1618).
+-define(wxGenericDirCtrl_GetFilter, 1619).
+-define(wxGenericDirCtrl_GetFilterIndex, 1620).
+-define(wxGenericDirCtrl_GetRootId, 1621).
+-define(wxGenericDirCtrl_GetTreeCtrl, 1622).
+-define(wxGenericDirCtrl_ReCreateTree, 1623).
+-define(wxGenericDirCtrl_SetDefaultPath, 1624).
+-define(wxGenericDirCtrl_SetFilter, 1625).
+-define(wxGenericDirCtrl_SetFilterIndex, 1626).
+-define(wxGenericDirCtrl_SetPath, 1627).
+-define(wxStaticBox_new_4, 1629).
+-define(wxStaticBox_new_0, 1630).
+-define(wxStaticBox_Create, 1631).
+-define(wxStaticBox_destroy, 1632).
+-define(wxStaticLine_new_2, 1634).
+-define(wxStaticLine_new_0, 1635).
+-define(wxStaticLine_Create, 1636).
+-define(wxStaticLine_IsVertical, 1637).
+-define(wxStaticLine_GetDefaultSize, 1638).
+-define(wxStaticLine_destroy, 1639).
+-define(wxListBox_new_3, 1642).
+-define(wxListBox_new_0, 1643).
+-define(wxListBox_destruct, 1645).
+-define(wxListBox_Create, 1647).
+-define(wxListBox_Deselect, 1648).
+-define(wxListBox_GetSelections, 1649).
+-define(wxListBox_InsertItems, 1650).
+-define(wxListBox_IsSelected, 1651).
+-define(wxListBox_Set, 1653).
+-define(wxListBox_HitTest, 1654).
+-define(wxListBox_SetFirstItem_1_0, 1655).
+-define(wxListBox_SetFirstItem_1_1, 1656).
+-define(wxListCtrl_new_0, 1657).
+-define(wxListCtrl_new_2, 1658).
+-define(wxListCtrl_Arrange, 1659).
+-define(wxListCtrl_AssignImageList, 1660).
+-define(wxListCtrl_ClearAll, 1661).
+-define(wxListCtrl_Create, 1662).
+-define(wxListCtrl_DeleteAllItems, 1663).
+-define(wxListCtrl_DeleteColumn, 1664).
+-define(wxListCtrl_DeleteItem, 1665).
+-define(wxListCtrl_EditLabel, 1666).
+-define(wxListCtrl_EnsureVisible, 1667).
+-define(wxListCtrl_FindItem_3_0, 1668).
+-define(wxListCtrl_FindItem_3_1, 1669).
+-define(wxListCtrl_GetColumn, 1670).
+-define(wxListCtrl_GetColumnCount, 1671).
+-define(wxListCtrl_GetColumnWidth, 1672).
+-define(wxListCtrl_GetCountPerPage, 1673).
+-define(wxListCtrl_GetEditControl, 1674).
+-define(wxListCtrl_GetImageList, 1675).
+-define(wxListCtrl_GetItem, 1676).
+-define(wxListCtrl_GetItemBackgroundColour, 1677).
+-define(wxListCtrl_GetItemCount, 1678).
+-define(wxListCtrl_GetItemData, 1679).
+-define(wxListCtrl_GetItemFont, 1680).
+-define(wxListCtrl_GetItemPosition, 1681).
+-define(wxListCtrl_GetItemRect, 1682).
+-define(wxListCtrl_GetItemSpacing, 1683).
+-define(wxListCtrl_GetItemState, 1684).
+-define(wxListCtrl_GetItemText, 1685).
+-define(wxListCtrl_GetItemTextColour, 1686).
+-define(wxListCtrl_GetNextItem, 1687).
+-define(wxListCtrl_GetSelectedItemCount, 1688).
+-define(wxListCtrl_GetTextColour, 1689).
+-define(wxListCtrl_GetTopItem, 1690).
+-define(wxListCtrl_GetViewRect, 1691).
+-define(wxListCtrl_HitTest, 1692).
+-define(wxListCtrl_InsertColumn_2, 1693).
+-define(wxListCtrl_InsertColumn_3, 1694).
+-define(wxListCtrl_InsertItem_1, 1695).
+-define(wxListCtrl_InsertItem_2_1, 1696).
+-define(wxListCtrl_InsertItem_2_0, 1697).
+-define(wxListCtrl_InsertItem_3, 1698).
+-define(wxListCtrl_RefreshItem, 1699).
+-define(wxListCtrl_RefreshItems, 1700).
+-define(wxListCtrl_ScrollList, 1701).
+-define(wxListCtrl_SetBackgroundColour, 1702).
+-define(wxListCtrl_SetColumn, 1703).
+-define(wxListCtrl_SetColumnWidth, 1704).
+-define(wxListCtrl_SetImageList, 1705).
+-define(wxListCtrl_SetItem_1, 1706).
+-define(wxListCtrl_SetItem_4, 1707).
+-define(wxListCtrl_SetItemBackgroundColour, 1708).
+-define(wxListCtrl_SetItemCount, 1709).
+-define(wxListCtrl_SetItemData, 1710).
+-define(wxListCtrl_SetItemFont, 1711).
+-define(wxListCtrl_SetItemImage, 1712).
+-define(wxListCtrl_SetItemColumnImage, 1713).
+-define(wxListCtrl_SetItemPosition, 1714).
+-define(wxListCtrl_SetItemState, 1715).
+-define(wxListCtrl_SetItemText, 1716).
+-define(wxListCtrl_SetItemTextColour, 1717).
+-define(wxListCtrl_SetSingleStyle, 1718).
+-define(wxListCtrl_SetTextColour, 1719).
+-define(wxListCtrl_SetWindowStyleFlag, 1720).
+-define(wxListCtrl_SortItems, 1721).
+-define(wxListCtrl_destroy, 1722).
+-define(wxListView_ClearColumnImage, 1723).
+-define(wxListView_Focus, 1724).
+-define(wxListView_GetFirstSelected, 1725).
+-define(wxListView_GetFocusedItem, 1726).
+-define(wxListView_GetNextSelected, 1727).
+-define(wxListView_IsSelected, 1728).
+-define(wxListView_Select, 1729).
+-define(wxListView_SetColumnImage, 1730).
+-define(wxListItem_new_0, 1731).
+-define(wxListItem_new_1, 1732).
+-define(wxListItem_destruct, 1733).
+-define(wxListItem_Clear, 1734).
+-define(wxListItem_GetAlign, 1735).
+-define(wxListItem_GetBackgroundColour, 1736).
+-define(wxListItem_GetColumn, 1737).
+-define(wxListItem_GetFont, 1738).
+-define(wxListItem_GetId, 1739).
+-define(wxListItem_GetImage, 1740).
+-define(wxListItem_GetMask, 1741).
+-define(wxListItem_GetState, 1742).
+-define(wxListItem_GetText, 1743).
+-define(wxListItem_GetTextColour, 1744).
+-define(wxListItem_GetWidth, 1745).
+-define(wxListItem_SetAlign, 1746).
+-define(wxListItem_SetBackgroundColour, 1747).
+-define(wxListItem_SetColumn, 1748).
+-define(wxListItem_SetFont, 1749).
+-define(wxListItem_SetId, 1750).
+-define(wxListItem_SetImage, 1751).
+-define(wxListItem_SetMask, 1752).
+-define(wxListItem_SetState, 1753).
+-define(wxListItem_SetStateMask, 1754).
+-define(wxListItem_SetText, 1755).
+-define(wxListItem_SetTextColour, 1756).
+-define(wxListItem_SetWidth, 1757).
+-define(wxListItemAttr_new_0, 1758).
+-define(wxListItemAttr_new_3, 1759).
+-define(wxListItemAttr_GetBackgroundColour, 1760).
+-define(wxListItemAttr_GetFont, 1761).
+-define(wxListItemAttr_GetTextColour, 1762).
+-define(wxListItemAttr_HasBackgroundColour, 1763).
+-define(wxListItemAttr_HasFont, 1764).
+-define(wxListItemAttr_HasTextColour, 1765).
+-define(wxListItemAttr_SetBackgroundColour, 1766).
+-define(wxListItemAttr_SetFont, 1767).
+-define(wxListItemAttr_SetTextColour, 1768).
+-define(wxListItemAttr_destroy, 1769).
+-define(wxImageList_new_0, 1770).
+-define(wxImageList_new_3, 1771).
+-define(wxImageList_Add_1, 1772).
+-define(wxImageList_Add_2_0, 1773).
+-define(wxImageList_Add_2_1, 1774).
+-define(wxImageList_Create, 1775).
+-define(wxImageList_Draw, 1777).
+-define(wxImageList_GetBitmap, 1778).
+-define(wxImageList_GetIcon, 1779).
+-define(wxImageList_GetImageCount, 1780).
+-define(wxImageList_GetSize, 1781).
+-define(wxImageList_Remove, 1782).
+-define(wxImageList_RemoveAll, 1783).
+-define(wxImageList_Replace_2, 1784).
+-define(wxImageList_Replace_3, 1785).
+-define(wxImageList_destroy, 1786).
+-define(wxTextAttr_new_0, 1787).
+-define(wxTextAttr_new_2, 1788).
+-define(wxTextAttr_GetAlignment, 1789).
+-define(wxTextAttr_GetBackgroundColour, 1790).
+-define(wxTextAttr_GetFont, 1791).
+-define(wxTextAttr_GetLeftIndent, 1792).
+-define(wxTextAttr_GetLeftSubIndent, 1793).
+-define(wxTextAttr_GetRightIndent, 1794).
+-define(wxTextAttr_GetTabs, 1795).
+-define(wxTextAttr_GetTextColour, 1796).
+-define(wxTextAttr_HasBackgroundColour, 1797).
+-define(wxTextAttr_HasFont, 1798).
+-define(wxTextAttr_HasTextColour, 1799).
+-define(wxTextAttr_GetFlags, 1800).
+-define(wxTextAttr_IsDefault, 1801).
+-define(wxTextAttr_SetAlignment, 1802).
+-define(wxTextAttr_SetBackgroundColour, 1803).
+-define(wxTextAttr_SetFlags, 1804).
+-define(wxTextAttr_SetFont, 1805).
+-define(wxTextAttr_SetLeftIndent, 1806).
+-define(wxTextAttr_SetRightIndent, 1807).
+-define(wxTextAttr_SetTabs, 1808).
+-define(wxTextAttr_SetTextColour, 1809).
+-define(wxTextAttr_destroy, 1810).
+-define(wxTextCtrl_new_3, 1812).
+-define(wxTextCtrl_new_0, 1813).
+-define(wxTextCtrl_destruct, 1815).
+-define(wxTextCtrl_AppendText, 1816).
+-define(wxTextCtrl_CanCopy, 1817).
+-define(wxTextCtrl_CanCut, 1818).
+-define(wxTextCtrl_CanPaste, 1819).
+-define(wxTextCtrl_CanRedo, 1820).
+-define(wxTextCtrl_CanUndo, 1821).
+-define(wxTextCtrl_Clear, 1822).
+-define(wxTextCtrl_Copy, 1823).
+-define(wxTextCtrl_Create, 1824).
+-define(wxTextCtrl_Cut, 1825).
+-define(wxTextCtrl_DiscardEdits, 1826).
+-define(wxTextCtrl_EmulateKeyPress, 1827).
+-define(wxTextCtrl_GetDefaultStyle, 1828).
+-define(wxTextCtrl_GetInsertionPoint, 1829).
+-define(wxTextCtrl_GetLastPosition, 1830).
+-define(wxTextCtrl_GetLineLength, 1831).
+-define(wxTextCtrl_GetLineText, 1832).
+-define(wxTextCtrl_GetNumberOfLines, 1833).
+-define(wxTextCtrl_GetRange, 1834).
+-define(wxTextCtrl_GetSelection, 1835).
+-define(wxTextCtrl_GetStringSelection, 1836).
+-define(wxTextCtrl_GetStyle, 1837).
+-define(wxTextCtrl_GetValue, 1838).
+-define(wxTextCtrl_IsEditable, 1839).
+-define(wxTextCtrl_IsModified, 1840).
+-define(wxTextCtrl_IsMultiLine, 1841).
+-define(wxTextCtrl_IsSingleLine, 1842).
+-define(wxTextCtrl_LoadFile, 1843).
+-define(wxTextCtrl_MarkDirty, 1844).
+-define(wxTextCtrl_Paste, 1845).
+-define(wxTextCtrl_PositionToXY, 1846).
+-define(wxTextCtrl_Redo, 1847).
+-define(wxTextCtrl_Remove, 1848).
+-define(wxTextCtrl_Replace, 1849).
+-define(wxTextCtrl_SaveFile, 1850).
+-define(wxTextCtrl_SetDefaultStyle, 1851).
+-define(wxTextCtrl_SetEditable, 1852).
+-define(wxTextCtrl_SetInsertionPoint, 1853).
+-define(wxTextCtrl_SetInsertionPointEnd, 1854).
+-define(wxTextCtrl_SetMaxLength, 1856).
+-define(wxTextCtrl_SetSelection, 1857).
+-define(wxTextCtrl_SetStyle, 1858).
+-define(wxTextCtrl_SetValue, 1859).
+-define(wxTextCtrl_ShowPosition, 1860).
+-define(wxTextCtrl_Undo, 1861).
+-define(wxTextCtrl_WriteText, 1862).
+-define(wxTextCtrl_XYToPosition, 1863).
+-define(wxNotebook_new_0, 1866).
+-define(wxNotebook_new_3, 1867).
+-define(wxNotebook_destruct, 1868).
+-define(wxNotebook_AddPage, 1869).
+-define(wxNotebook_AdvanceSelection, 1870).
+-define(wxNotebook_AssignImageList, 1871).
+-define(wxNotebook_Create, 1872).
+-define(wxNotebook_DeleteAllPages, 1873).
+-define(wxNotebook_DeletePage, 1874).
+-define(wxNotebook_RemovePage, 1875).
+-define(wxNotebook_GetCurrentPage, 1876).
+-define(wxNotebook_GetImageList, 1877).
+-define(wxNotebook_GetPage, 1879).
+-define(wxNotebook_GetPageCount, 1880).
+-define(wxNotebook_GetPageImage, 1881).
+-define(wxNotebook_GetPageText, 1882).
+-define(wxNotebook_GetRowCount, 1883).
+-define(wxNotebook_GetSelection, 1884).
+-define(wxNotebook_GetThemeBackgroundColour, 1885).
+-define(wxNotebook_HitTest, 1887).
+-define(wxNotebook_InsertPage, 1889).
+-define(wxNotebook_SetImageList, 1890).
+-define(wxNotebook_SetPadding, 1891).
+-define(wxNotebook_SetPageSize, 1892).
+-define(wxNotebook_SetPageImage, 1893).
+-define(wxNotebook_SetPageText, 1894).
+-define(wxNotebook_SetSelection, 1895).
+-define(wxNotebook_ChangeSelection, 1896).
+-define(wxChoicebook_new_0, 1897).
+-define(wxChoicebook_new_3, 1898).
+-define(wxChoicebook_AddPage, 1899).
+-define(wxChoicebook_AdvanceSelection, 1900).
+-define(wxChoicebook_AssignImageList, 1901).
+-define(wxChoicebook_Create, 1902).
+-define(wxChoicebook_DeleteAllPages, 1903).
+-define(wxChoicebook_DeletePage, 1904).
+-define(wxChoicebook_RemovePage, 1905).
+-define(wxChoicebook_GetCurrentPage, 1906).
+-define(wxChoicebook_GetImageList, 1907).
+-define(wxChoicebook_GetPage, 1909).
+-define(wxChoicebook_GetPageCount, 1910).
+-define(wxChoicebook_GetPageImage, 1911).
+-define(wxChoicebook_GetPageText, 1912).
+-define(wxChoicebook_GetSelection, 1913).
+-define(wxChoicebook_HitTest, 1914).
+-define(wxChoicebook_InsertPage, 1915).
+-define(wxChoicebook_SetImageList, 1916).
+-define(wxChoicebook_SetPageSize, 1917).
+-define(wxChoicebook_SetPageImage, 1918).
+-define(wxChoicebook_SetPageText, 1919).
+-define(wxChoicebook_SetSelection, 1920).
+-define(wxChoicebook_ChangeSelection, 1921).
+-define(wxChoicebook_destroy, 1922).
+-define(wxToolbook_new_0, 1923).
+-define(wxToolbook_new_3, 1924).
+-define(wxToolbook_AddPage, 1925).
+-define(wxToolbook_AdvanceSelection, 1926).
+-define(wxToolbook_AssignImageList, 1927).
+-define(wxToolbook_Create, 1928).
+-define(wxToolbook_DeleteAllPages, 1929).
+-define(wxToolbook_DeletePage, 1930).
+-define(wxToolbook_RemovePage, 1931).
+-define(wxToolbook_GetCurrentPage, 1932).
+-define(wxToolbook_GetImageList, 1933).
+-define(wxToolbook_GetPage, 1935).
+-define(wxToolbook_GetPageCount, 1936).
+-define(wxToolbook_GetPageImage, 1937).
+-define(wxToolbook_GetPageText, 1938).
+-define(wxToolbook_GetSelection, 1939).
+-define(wxToolbook_HitTest, 1941).
+-define(wxToolbook_InsertPage, 1942).
+-define(wxToolbook_SetImageList, 1943).
+-define(wxToolbook_SetPageSize, 1944).
+-define(wxToolbook_SetPageImage, 1945).
+-define(wxToolbook_SetPageText, 1946).
+-define(wxToolbook_SetSelection, 1947).
+-define(wxToolbook_ChangeSelection, 1948).
+-define(wxToolbook_destroy, 1949).
+-define(wxListbook_new_0, 1950).
+-define(wxListbook_new_3, 1951).
+-define(wxListbook_AddPage, 1952).
+-define(wxListbook_AdvanceSelection, 1953).
+-define(wxListbook_AssignImageList, 1954).
+-define(wxListbook_Create, 1955).
+-define(wxListbook_DeleteAllPages, 1956).
+-define(wxListbook_DeletePage, 1957).
+-define(wxListbook_RemovePage, 1958).
+-define(wxListbook_GetCurrentPage, 1959).
+-define(wxListbook_GetImageList, 1960).
+-define(wxListbook_GetPage, 1962).
+-define(wxListbook_GetPageCount, 1963).
+-define(wxListbook_GetPageImage, 1964).
+-define(wxListbook_GetPageText, 1965).
+-define(wxListbook_GetSelection, 1966).
+-define(wxListbook_HitTest, 1968).
+-define(wxListbook_InsertPage, 1969).
+-define(wxListbook_SetImageList, 1970).
+-define(wxListbook_SetPageSize, 1971).
+-define(wxListbook_SetPageImage, 1972).
+-define(wxListbook_SetPageText, 1973).
+-define(wxListbook_SetSelection, 1974).
+-define(wxListbook_ChangeSelection, 1975).
+-define(wxListbook_destroy, 1976).
+-define(wxTreebook_new_0, 1977).
+-define(wxTreebook_new_3, 1978).
+-define(wxTreebook_AddPage, 1979).
+-define(wxTreebook_AdvanceSelection, 1980).
+-define(wxTreebook_AssignImageList, 1981).
+-define(wxTreebook_Create, 1982).
+-define(wxTreebook_DeleteAllPages, 1983).
+-define(wxTreebook_DeletePage, 1984).
+-define(wxTreebook_RemovePage, 1985).
+-define(wxTreebook_GetCurrentPage, 1986).
+-define(wxTreebook_GetImageList, 1987).
+-define(wxTreebook_GetPage, 1989).
+-define(wxTreebook_GetPageCount, 1990).
+-define(wxTreebook_GetPageImage, 1991).
+-define(wxTreebook_GetPageText, 1992).
+-define(wxTreebook_GetSelection, 1993).
+-define(wxTreebook_ExpandNode, 1994).
+-define(wxTreebook_IsNodeExpanded, 1995).
+-define(wxTreebook_HitTest, 1997).
+-define(wxTreebook_InsertPage, 1998).
+-define(wxTreebook_InsertSubPage, 1999).
+-define(wxTreebook_SetImageList, 2000).
+-define(wxTreebook_SetPageSize, 2001).
+-define(wxTreebook_SetPageImage, 2002).
+-define(wxTreebook_SetPageText, 2003).
+-define(wxTreebook_SetSelection, 2004).
+-define(wxTreebook_ChangeSelection, 2005).
+-define(wxTreebook_destroy, 2006).
+-define(wxTreeCtrl_new_2, 2009).
+-define(wxTreeCtrl_new_0, 2010).
+-define(wxTreeCtrl_destruct, 2012).
+-define(wxTreeCtrl_AddRoot, 2013).
+-define(wxTreeCtrl_AppendItem, 2014).
+-define(wxTreeCtrl_AssignImageList, 2015).
+-define(wxTreeCtrl_AssignStateImageList, 2016).
+-define(wxTreeCtrl_Collapse, 2017).
+-define(wxTreeCtrl_CollapseAndReset, 2018).
+-define(wxTreeCtrl_Create, 2019).
+-define(wxTreeCtrl_Delete, 2020).
+-define(wxTreeCtrl_DeleteAllItems, 2021).
+-define(wxTreeCtrl_DeleteChildren, 2022).
+-define(wxTreeCtrl_EditLabel, 2023).
+-define(wxTreeCtrl_EnsureVisible, 2024).
+-define(wxTreeCtrl_Expand, 2025).
+-define(wxTreeCtrl_GetBoundingRect, 2026).
+-define(wxTreeCtrl_GetChildrenCount, 2028).
+-define(wxTreeCtrl_GetCount, 2029).
+-define(wxTreeCtrl_GetEditControl, 2030).
+-define(wxTreeCtrl_GetFirstChild, 2031).
+-define(wxTreeCtrl_GetNextChild, 2032).
+-define(wxTreeCtrl_GetFirstVisibleItem, 2033).
+-define(wxTreeCtrl_GetImageList, 2034).
+-define(wxTreeCtrl_GetIndent, 2035).
+-define(wxTreeCtrl_GetItemBackgroundColour, 2036).
+-define(wxTreeCtrl_GetItemData, 2037).
+-define(wxTreeCtrl_GetItemFont, 2038).
+-define(wxTreeCtrl_GetItemImage_1, 2039).
+-define(wxTreeCtrl_GetItemImage_2, 2040).
+-define(wxTreeCtrl_GetItemText, 2041).
+-define(wxTreeCtrl_GetItemTextColour, 2042).
+-define(wxTreeCtrl_GetLastChild, 2043).
+-define(wxTreeCtrl_GetNextSibling, 2044).
+-define(wxTreeCtrl_GetNextVisible, 2045).
+-define(wxTreeCtrl_GetItemParent, 2046).
+-define(wxTreeCtrl_GetPrevSibling, 2047).
+-define(wxTreeCtrl_GetPrevVisible, 2048).
+-define(wxTreeCtrl_GetRootItem, 2049).
+-define(wxTreeCtrl_GetSelection, 2050).
+-define(wxTreeCtrl_GetSelections, 2051).
+-define(wxTreeCtrl_GetStateImageList, 2052).
+-define(wxTreeCtrl_HitTest, 2053).
+-define(wxTreeCtrl_InsertItem, 2055).
+-define(wxTreeCtrl_IsBold, 2056).
+-define(wxTreeCtrl_IsExpanded, 2057).
+-define(wxTreeCtrl_IsSelected, 2058).
+-define(wxTreeCtrl_IsVisible, 2059).
+-define(wxTreeCtrl_ItemHasChildren, 2060).
+-define(wxTreeCtrl_PrependItem, 2061).
+-define(wxTreeCtrl_ScrollTo, 2062).
+-define(wxTreeCtrl_SelectItem_1, 2063).
+-define(wxTreeCtrl_SelectItem_2, 2064).
+-define(wxTreeCtrl_SetIndent, 2065).
+-define(wxTreeCtrl_SetImageList, 2066).
+-define(wxTreeCtrl_SetItemBackgroundColour, 2067).
+-define(wxTreeCtrl_SetItemBold, 2068).
+-define(wxTreeCtrl_SetItemData, 2069).
+-define(wxTreeCtrl_SetItemDropHighlight, 2070).
+-define(wxTreeCtrl_SetItemFont, 2071).
+-define(wxTreeCtrl_SetItemHasChildren, 2072).
+-define(wxTreeCtrl_SetItemImage_2, 2073).
+-define(wxTreeCtrl_SetItemImage_3, 2074).
+-define(wxTreeCtrl_SetItemText, 2075).
+-define(wxTreeCtrl_SetItemTextColour, 2076).
+-define(wxTreeCtrl_SetStateImageList, 2077).
+-define(wxTreeCtrl_SetWindowStyle, 2078).
+-define(wxTreeCtrl_SortChildren, 2079).
+-define(wxTreeCtrl_Toggle, 2080).
+-define(wxTreeCtrl_ToggleItemSelection, 2081).
+-define(wxTreeCtrl_Unselect, 2082).
+-define(wxTreeCtrl_UnselectAll, 2083).
+-define(wxTreeCtrl_UnselectItem, 2084).
+-define(wxScrollBar_new_0, 2085).
+-define(wxScrollBar_new_3, 2086).
+-define(wxScrollBar_destruct, 2087).
+-define(wxScrollBar_Create, 2088).
+-define(wxScrollBar_GetRange, 2089).
+-define(wxScrollBar_GetPageSize, 2090).
+-define(wxScrollBar_GetThumbPosition, 2091).
+-define(wxScrollBar_GetThumbSize, 2092).
+-define(wxScrollBar_SetThumbPosition, 2093).
+-define(wxScrollBar_SetScrollbar, 2094).
+-define(wxSpinButton_new_2, 2096).
+-define(wxSpinButton_new_0, 2097).
+-define(wxSpinButton_Create, 2098).
+-define(wxSpinButton_GetMax, 2099).
+-define(wxSpinButton_GetMin, 2100).
+-define(wxSpinButton_GetValue, 2101).
+-define(wxSpinButton_SetRange, 2102).
+-define(wxSpinButton_SetValue, 2103).
+-define(wxSpinButton_destroy, 2104).
+-define(wxSpinCtrl_new_0, 2105).
+-define(wxSpinCtrl_new_2, 2106).
+-define(wxSpinCtrl_Create, 2108).
+-define(wxSpinCtrl_SetValue_1_1, 2111).
+-define(wxSpinCtrl_SetValue_1_0, 2112).
+-define(wxSpinCtrl_GetValue, 2114).
+-define(wxSpinCtrl_SetRange, 2116).
+-define(wxSpinCtrl_SetSelection, 2117).
+-define(wxSpinCtrl_GetMin, 2119).
+-define(wxSpinCtrl_GetMax, 2121).
+-define(wxSpinCtrl_destroy, 2122).
+-define(wxStaticText_new_0, 2123).
+-define(wxStaticText_new_4, 2124).
+-define(wxStaticText_Create, 2125).
+-define(wxStaticText_GetLabel, 2126).
+-define(wxStaticText_SetLabel, 2127).
+-define(wxStaticText_Wrap, 2128).
+-define(wxStaticText_destroy, 2129).
+-define(wxStaticBitmap_new_0, 2130).
+-define(wxStaticBitmap_new_4, 2131).
+-define(wxStaticBitmap_Create, 2132).
+-define(wxStaticBitmap_GetBitmap, 2133).
+-define(wxStaticBitmap_SetBitmap, 2134).
+-define(wxStaticBitmap_destroy, 2135).
+-define(wxRadioBox_new, 2136).
+-define(wxRadioBox_destruct, 2138).
+-define(wxRadioBox_Create, 2139).
+-define(wxRadioBox_Enable_2, 2140).
+-define(wxRadioBox_Enable_1, 2141).
+-define(wxRadioBox_GetSelection, 2142).
+-define(wxRadioBox_GetString, 2143).
+-define(wxRadioBox_SetSelection, 2144).
+-define(wxRadioBox_Show_2, 2145).
+-define(wxRadioBox_Show_1, 2146).
+-define(wxRadioBox_GetColumnCount, 2147).
+-define(wxRadioBox_GetItemHelpText, 2148).
+-define(wxRadioBox_GetItemToolTip, 2149).
+-define(wxRadioBox_GetItemFromPoint, 2151).
+-define(wxRadioBox_GetRowCount, 2152).
+-define(wxRadioBox_IsItemEnabled, 2153).
+-define(wxRadioBox_IsItemShown, 2154).
+-define(wxRadioBox_SetItemHelpText, 2155).
+-define(wxRadioBox_SetItemToolTip, 2156).
+-define(wxRadioButton_new_0, 2157).
+-define(wxRadioButton_new_4, 2158).
+-define(wxRadioButton_Create, 2159).
+-define(wxRadioButton_GetValue, 2160).
+-define(wxRadioButton_SetValue, 2161).
+-define(wxRadioButton_destroy, 2162).
+-define(wxSlider_new_6, 2164).
+-define(wxSlider_new_0, 2165).
+-define(wxSlider_Create, 2166).
+-define(wxSlider_GetLineSize, 2167).
+-define(wxSlider_GetMax, 2168).
+-define(wxSlider_GetMin, 2169).
+-define(wxSlider_GetPageSize, 2170).
+-define(wxSlider_GetThumbLength, 2171).
+-define(wxSlider_GetValue, 2172).
+-define(wxSlider_SetLineSize, 2173).
+-define(wxSlider_SetPageSize, 2174).
+-define(wxSlider_SetRange, 2175).
+-define(wxSlider_SetThumbLength, 2176).
+-define(wxSlider_SetValue, 2177).
+-define(wxSlider_destroy, 2178).
+-define(wxDialog_new_4, 2180).
+-define(wxDialog_new_0, 2181).
+-define(wxDialog_destruct, 2183).
+-define(wxDialog_Create, 2184).
+-define(wxDialog_CreateButtonSizer, 2185).
+-define(wxDialog_CreateStdDialogButtonSizer, 2186).
+-define(wxDialog_EndModal, 2187).
+-define(wxDialog_GetAffirmativeId, 2188).
+-define(wxDialog_GetReturnCode, 2189).
+-define(wxDialog_IsModal, 2190).
+-define(wxDialog_SetAffirmativeId, 2191).
+-define(wxDialog_SetReturnCode, 2192).
+-define(wxDialog_Show, 2193).
+-define(wxDialog_ShowModal, 2194).
+-define(wxColourDialog_new_0, 2195).
+-define(wxColourDialog_new_2, 2196).
+-define(wxColourDialog_destruct, 2197).
+-define(wxColourDialog_Create, 2198).
+-define(wxColourDialog_GetColourData, 2199).
+-define(wxColourData_new_0, 2200).
+-define(wxColourData_new_1, 2201).
+-define(wxColourData_destruct, 2202).
+-define(wxColourData_GetChooseFull, 2203).
+-define(wxColourData_GetColour, 2204).
+-define(wxColourData_GetCustomColour, 2206).
+-define(wxColourData_SetChooseFull, 2207).
+-define(wxColourData_SetColour, 2208).
+-define(wxColourData_SetCustomColour, 2209).
+-define(wxPalette_new_0, 2210).
+-define(wxPalette_new_4, 2211).
+-define(wxPalette_destruct, 2213).
+-define(wxPalette_Create, 2214).
+-define(wxPalette_GetColoursCount, 2215).
+-define(wxPalette_GetPixel, 2216).
+-define(wxPalette_GetRGB, 2217).
+-define(wxPalette_IsOk, 2218).
+-define(wxDirDialog_new, 2222).
+-define(wxDirDialog_destruct, 2223).
+-define(wxDirDialog_GetPath, 2224).
+-define(wxDirDialog_GetMessage, 2225).
+-define(wxDirDialog_SetMessage, 2226).
+-define(wxDirDialog_SetPath, 2227).
+-define(wxFileDialog_new, 2231).
+-define(wxFileDialog_destruct, 2232).
+-define(wxFileDialog_GetDirectory, 2233).
+-define(wxFileDialog_GetFilename, 2234).
+-define(wxFileDialog_GetFilenames, 2235).
+-define(wxFileDialog_GetFilterIndex, 2236).
+-define(wxFileDialog_GetMessage, 2237).
+-define(wxFileDialog_GetPath, 2238).
+-define(wxFileDialog_GetPaths, 2239).
+-define(wxFileDialog_GetWildcard, 2240).
+-define(wxFileDialog_SetDirectory, 2241).
+-define(wxFileDialog_SetFilename, 2242).
+-define(wxFileDialog_SetFilterIndex, 2243).
+-define(wxFileDialog_SetMessage, 2244).
+-define(wxFileDialog_SetPath, 2245).
+-define(wxFileDialog_SetWildcard, 2246).
+-define(wxPickerBase_SetInternalMargin, 2247).
+-define(wxPickerBase_GetInternalMargin, 2248).
+-define(wxPickerBase_SetTextCtrlProportion, 2249).
+-define(wxPickerBase_SetPickerCtrlProportion, 2250).
+-define(wxPickerBase_GetTextCtrlProportion, 2251).
+-define(wxPickerBase_GetPickerCtrlProportion, 2252).
+-define(wxPickerBase_HasTextCtrl, 2253).
+-define(wxPickerBase_GetTextCtrl, 2254).
+-define(wxPickerBase_IsTextCtrlGrowable, 2255).
+-define(wxPickerBase_SetPickerCtrlGrowable, 2256).
+-define(wxPickerBase_SetTextCtrlGrowable, 2257).
+-define(wxPickerBase_IsPickerCtrlGrowable, 2258).
+-define(wxFilePickerCtrl_new_0, 2259).
+-define(wxFilePickerCtrl_new_3, 2260).
+-define(wxFilePickerCtrl_Create, 2261).
+-define(wxFilePickerCtrl_GetPath, 2262).
+-define(wxFilePickerCtrl_SetPath, 2263).
+-define(wxFilePickerCtrl_destroy, 2264).
+-define(wxDirPickerCtrl_new_0, 2265).
+-define(wxDirPickerCtrl_new_3, 2266).
+-define(wxDirPickerCtrl_Create, 2267).
+-define(wxDirPickerCtrl_GetPath, 2268).
+-define(wxDirPickerCtrl_SetPath, 2269).
+-define(wxDirPickerCtrl_destroy, 2270).
+-define(wxColourPickerCtrl_new_0, 2271).
+-define(wxColourPickerCtrl_new_3, 2272).
+-define(wxColourPickerCtrl_Create, 2273).
+-define(wxColourPickerCtrl_GetColour, 2274).
+-define(wxColourPickerCtrl_SetColour_1_1, 2275).
+-define(wxColourPickerCtrl_SetColour_1_0, 2276).
+-define(wxColourPickerCtrl_destroy, 2277).
+-define(wxDatePickerCtrl_new_0, 2278).
+-define(wxDatePickerCtrl_new_3, 2279).
+-define(wxDatePickerCtrl_GetRange, 2280).
+-define(wxDatePickerCtrl_GetValue, 2281).
+-define(wxDatePickerCtrl_SetRange, 2282).
+-define(wxDatePickerCtrl_SetValue, 2283).
+-define(wxDatePickerCtrl_destroy, 2284).
+-define(wxFontPickerCtrl_new_0, 2285).
+-define(wxFontPickerCtrl_new_3, 2286).
+-define(wxFontPickerCtrl_Create, 2287).
+-define(wxFontPickerCtrl_GetSelectedFont, 2288).
+-define(wxFontPickerCtrl_SetSelectedFont, 2289).
+-define(wxFontPickerCtrl_GetMaxPointSize, 2290).
+-define(wxFontPickerCtrl_SetMaxPointSize, 2291).
+-define(wxFontPickerCtrl_destroy, 2292).
+-define(wxFindReplaceDialog_new_0, 2295).
+-define(wxFindReplaceDialog_new_4, 2296).
+-define(wxFindReplaceDialog_destruct, 2297).
+-define(wxFindReplaceDialog_Create, 2298).
+-define(wxFindReplaceDialog_GetData, 2299).
+-define(wxFindReplaceData_new_0, 2300).
+-define(wxFindReplaceData_new_1, 2301).
+-define(wxFindReplaceData_GetFindString, 2302).
+-define(wxFindReplaceData_GetReplaceString, 2303).
+-define(wxFindReplaceData_GetFlags, 2304).
+-define(wxFindReplaceData_SetFlags, 2305).
+-define(wxFindReplaceData_SetFindString, 2306).
+-define(wxFindReplaceData_SetReplaceString, 2307).
+-define(wxFindReplaceData_destroy, 2308).
+-define(wxMultiChoiceDialog_new_0, 2309).
+-define(wxMultiChoiceDialog_new_5, 2311).
+-define(wxMultiChoiceDialog_GetSelections, 2312).
+-define(wxMultiChoiceDialog_SetSelections, 2313).
+-define(wxMultiChoiceDialog_destroy, 2314).
+-define(wxSingleChoiceDialog_new_0, 2315).
+-define(wxSingleChoiceDialog_new_5, 2317).
+-define(wxSingleChoiceDialog_GetSelection, 2318).
+-define(wxSingleChoiceDialog_GetStringSelection, 2319).
+-define(wxSingleChoiceDialog_SetSelection, 2320).
+-define(wxSingleChoiceDialog_destroy, 2321).
+-define(wxTextEntryDialog_new, 2322).
+-define(wxTextEntryDialog_GetValue, 2323).
+-define(wxTextEntryDialog_SetValue, 2324).
+-define(wxTextEntryDialog_destroy, 2325).
+-define(wxPasswordEntryDialog_new, 2326).
+-define(wxPasswordEntryDialog_destroy, 2327).
+-define(wxFontData_new_0, 2328).
+-define(wxFontData_new_1, 2329).
+-define(wxFontData_destruct, 2330).
+-define(wxFontData_EnableEffects, 2331).
+-define(wxFontData_GetAllowSymbols, 2332).
+-define(wxFontData_GetColour, 2333).
+-define(wxFontData_GetChosenFont, 2334).
+-define(wxFontData_GetEnableEffects, 2335).
+-define(wxFontData_GetInitialFont, 2336).
+-define(wxFontData_GetShowHelp, 2337).
+-define(wxFontData_SetAllowSymbols, 2338).
+-define(wxFontData_SetChosenFont, 2339).
+-define(wxFontData_SetColour, 2340).
+-define(wxFontData_SetInitialFont, 2341).
+-define(wxFontData_SetRange, 2342).
+-define(wxFontData_SetShowHelp, 2343).
+-define(wxFontDialog_new_0, 2347).
+-define(wxFontDialog_new_2, 2349).
+-define(wxFontDialog_Create, 2351).
+-define(wxFontDialog_GetFontData, 2352).
+-define(wxFontDialog_destroy, 2354).
+-define(wxProgressDialog_new, 2355).
+-define(wxProgressDialog_destruct, 2356).
+-define(wxProgressDialog_Resume, 2357).
+-define(wxProgressDialog_Update_2, 2358).
+-define(wxProgressDialog_Update_0, 2359).
+-define(wxMessageDialog_new, 2360).
+-define(wxMessageDialog_destruct, 2361).
+-define(wxPageSetupDialog_new, 2362).
+-define(wxPageSetupDialog_destruct, 2363).
+-define(wxPageSetupDialog_GetPageSetupData, 2364).
+-define(wxPageSetupDialog_ShowModal, 2365).
+-define(wxPageSetupDialogData_new_0, 2366).
+-define(wxPageSetupDialogData_new_1_0, 2367).
+-define(wxPageSetupDialogData_new_1_1, 2368).
+-define(wxPageSetupDialogData_destruct, 2369).
+-define(wxPageSetupDialogData_EnableHelp, 2370).
+-define(wxPageSetupDialogData_EnableMargins, 2371).
+-define(wxPageSetupDialogData_EnableOrientation, 2372).
+-define(wxPageSetupDialogData_EnablePaper, 2373).
+-define(wxPageSetupDialogData_EnablePrinter, 2374).
+-define(wxPageSetupDialogData_GetDefaultMinMargins, 2375).
+-define(wxPageSetupDialogData_GetEnableMargins, 2376).
+-define(wxPageSetupDialogData_GetEnableOrientation, 2377).
+-define(wxPageSetupDialogData_GetEnablePaper, 2378).
+-define(wxPageSetupDialogData_GetEnablePrinter, 2379).
+-define(wxPageSetupDialogData_GetEnableHelp, 2380).
+-define(wxPageSetupDialogData_GetDefaultInfo, 2381).
+-define(wxPageSetupDialogData_GetMarginTopLeft, 2382).
+-define(wxPageSetupDialogData_GetMarginBottomRight, 2383).
+-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2384).
+-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2385).
+-define(wxPageSetupDialogData_GetPaperId, 2386).
+-define(wxPageSetupDialogData_GetPaperSize, 2387).
+-define(wxPageSetupDialogData_GetPrintData, 2389).
+-define(wxPageSetupDialogData_IsOk, 2390).
+-define(wxPageSetupDialogData_SetDefaultInfo, 2391).
+-define(wxPageSetupDialogData_SetDefaultMinMargins, 2392).
+-define(wxPageSetupDialogData_SetMarginTopLeft, 2393).
+-define(wxPageSetupDialogData_SetMarginBottomRight, 2394).
+-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2395).
+-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2396).
+-define(wxPageSetupDialogData_SetPaperId, 2397).
+-define(wxPageSetupDialogData_SetPaperSize_1_1, 2398).
+-define(wxPageSetupDialogData_SetPaperSize_1_0, 2399).
+-define(wxPageSetupDialogData_SetPrintData, 2400).
+-define(wxPrintDialog_new_2_0, 2401).
+-define(wxPrintDialog_new_2_1, 2402).
+-define(wxPrintDialog_destruct, 2403).
+-define(wxPrintDialog_GetPrintDialogData, 2404).
+-define(wxPrintDialog_GetPrintDC, 2405).
+-define(wxPrintDialogData_new_0, 2406).
+-define(wxPrintDialogData_new_1_1, 2407).
+-define(wxPrintDialogData_new_1_0, 2408).
+-define(wxPrintDialogData_destruct, 2409).
+-define(wxPrintDialogData_EnableHelp, 2410).
+-define(wxPrintDialogData_EnablePageNumbers, 2411).
+-define(wxPrintDialogData_EnablePrintToFile, 2412).
+-define(wxPrintDialogData_EnableSelection, 2413).
+-define(wxPrintDialogData_GetAllPages, 2414).
+-define(wxPrintDialogData_GetCollate, 2415).
+-define(wxPrintDialogData_GetFromPage, 2416).
+-define(wxPrintDialogData_GetMaxPage, 2417).
+-define(wxPrintDialogData_GetMinPage, 2418).
+-define(wxPrintDialogData_GetNoCopies, 2419).
+-define(wxPrintDialogData_GetPrintData, 2420).
+-define(wxPrintDialogData_GetPrintToFile, 2421).
+-define(wxPrintDialogData_GetSelection, 2422).
+-define(wxPrintDialogData_GetToPage, 2423).
+-define(wxPrintDialogData_IsOk, 2424).
+-define(wxPrintDialogData_SetCollate, 2425).
+-define(wxPrintDialogData_SetFromPage, 2426).
+-define(wxPrintDialogData_SetMaxPage, 2427).
+-define(wxPrintDialogData_SetMinPage, 2428).
+-define(wxPrintDialogData_SetNoCopies, 2429).
+-define(wxPrintDialogData_SetPrintData, 2430).
+-define(wxPrintDialogData_SetPrintToFile, 2431).
+-define(wxPrintDialogData_SetSelection, 2432).
+-define(wxPrintDialogData_SetToPage, 2433).
+-define(wxPrintData_new_0, 2434).
+-define(wxPrintData_new_1, 2435).
+-define(wxPrintData_destruct, 2436).
+-define(wxPrintData_GetCollate, 2437).
+-define(wxPrintData_GetBin, 2438).
+-define(wxPrintData_GetColour, 2439).
+-define(wxPrintData_GetDuplex, 2440).
+-define(wxPrintData_GetNoCopies, 2441).
+-define(wxPrintData_GetOrientation, 2442).
+-define(wxPrintData_GetPaperId, 2443).
+-define(wxPrintData_GetPrinterName, 2444).
+-define(wxPrintData_GetQuality, 2445).
+-define(wxPrintData_IsOk, 2446).
+-define(wxPrintData_SetBin, 2447).
+-define(wxPrintData_SetCollate, 2448).
+-define(wxPrintData_SetColour, 2449).
+-define(wxPrintData_SetDuplex, 2450).
+-define(wxPrintData_SetNoCopies, 2451).
+-define(wxPrintData_SetOrientation, 2452).
+-define(wxPrintData_SetPaperId, 2453).
+-define(wxPrintData_SetPrinterName, 2454).
+-define(wxPrintData_SetQuality, 2455).
+-define(wxPrintPreview_new_2, 2458).
+-define(wxPrintPreview_new_3, 2459).
+-define(wxPrintPreview_destruct, 2461).
+-define(wxPrintPreview_GetCanvas, 2462).
+-define(wxPrintPreview_GetCurrentPage, 2463).
+-define(wxPrintPreview_GetFrame, 2464).
+-define(wxPrintPreview_GetMaxPage, 2465).
+-define(wxPrintPreview_GetMinPage, 2466).
+-define(wxPrintPreview_GetPrintout, 2467).
+-define(wxPrintPreview_GetPrintoutForPrinting, 2468).
+-define(wxPrintPreview_IsOk, 2469).
+-define(wxPrintPreview_PaintPage, 2470).
+-define(wxPrintPreview_Print, 2471).
+-define(wxPrintPreview_RenderPage, 2472).
+-define(wxPrintPreview_SetCanvas, 2473).
+-define(wxPrintPreview_SetCurrentPage, 2474).
+-define(wxPrintPreview_SetFrame, 2475).
+-define(wxPrintPreview_SetPrintout, 2476).
+-define(wxPrintPreview_SetZoom, 2477).
+-define(wxPreviewFrame_new, 2478).
+-define(wxPreviewFrame_destruct, 2479).
+-define(wxPreviewFrame_CreateControlBar, 2480).
+-define(wxPreviewFrame_CreateCanvas, 2481).
+-define(wxPreviewFrame_Initialize, 2482).
+-define(wxPreviewFrame_OnCloseWindow, 2483).
+-define(wxPreviewControlBar_new, 2484).
+-define(wxPreviewControlBar_destruct, 2485).
+-define(wxPreviewControlBar_CreateButtons, 2486).
+-define(wxPreviewControlBar_GetPrintPreview, 2487).
+-define(wxPreviewControlBar_GetZoomControl, 2488).
+-define(wxPreviewControlBar_SetZoomControl, 2489).
+-define(wxPrinter_new, 2491).
+-define(wxPrinter_CreateAbortWindow, 2492).
+-define(wxPrinter_GetAbort, 2493).
+-define(wxPrinter_GetLastError, 2494).
+-define(wxPrinter_GetPrintDialogData, 2495).
+-define(wxPrinter_Print, 2496).
+-define(wxPrinter_PrintDialog, 2497).
+-define(wxPrinter_ReportError, 2498).
+-define(wxPrinter_Setup, 2499).
+-define(wxPrinter_destroy, 2500).
+-define(wxXmlResource_new_1, 2501).
+-define(wxXmlResource_new_2, 2502).
+-define(wxXmlResource_destruct, 2503).
+-define(wxXmlResource_AttachUnknownControl, 2504).
+-define(wxXmlResource_ClearHandlers, 2505).
+-define(wxXmlResource_CompareVersion, 2506).
+-define(wxXmlResource_Get, 2507).
+-define(wxXmlResource_GetFlags, 2508).
+-define(wxXmlResource_GetVersion, 2509).
+-define(wxXmlResource_GetXRCID, 2510).
+-define(wxXmlResource_InitAllHandlers, 2511).
+-define(wxXmlResource_Load, 2512).
+-define(wxXmlResource_LoadBitmap, 2513).
+-define(wxXmlResource_LoadDialog_2, 2514).
+-define(wxXmlResource_LoadDialog_3, 2515).
+-define(wxXmlResource_LoadFrame_2, 2516).
+-define(wxXmlResource_LoadFrame_3, 2517).
+-define(wxXmlResource_LoadIcon, 2518).
+-define(wxXmlResource_LoadMenu, 2519).
+-define(wxXmlResource_LoadMenuBar_2, 2520).
+-define(wxXmlResource_LoadMenuBar_1, 2521).
+-define(wxXmlResource_LoadPanel_2, 2522).
+-define(wxXmlResource_LoadPanel_3, 2523).
+-define(wxXmlResource_LoadToolBar, 2524).
+-define(wxXmlResource_Set, 2525).
+-define(wxXmlResource_SetFlags, 2526).
+-define(wxXmlResource_Unload, 2527).
+-define(wxXmlResource_xrcctrl, 2528).
+-define(wxHtmlEasyPrinting_new, 2529).
+-define(wxHtmlEasyPrinting_destruct, 2530).
+-define(wxHtmlEasyPrinting_GetPrintData, 2531).
+-define(wxHtmlEasyPrinting_GetPageSetupData, 2532).
+-define(wxHtmlEasyPrinting_PreviewFile, 2533).
+-define(wxHtmlEasyPrinting_PreviewText, 2534).
+-define(wxHtmlEasyPrinting_PrintFile, 2535).
+-define(wxHtmlEasyPrinting_PrintText, 2536).
+-define(wxHtmlEasyPrinting_PageSetup, 2537).
+-define(wxHtmlEasyPrinting_SetFonts, 2538).
+-define(wxHtmlEasyPrinting_SetHeader, 2539).
+-define(wxHtmlEasyPrinting_SetFooter, 2540).
+-define(wxGLCanvas_new_2, 2542).
+-define(wxGLCanvas_new_3_1, 2543).
+-define(wxGLCanvas_new_3_0, 2544).
+-define(wxGLCanvas_GetContext, 2545).
+-define(wxGLCanvas_SetCurrent, 2547).
+-define(wxGLCanvas_SwapBuffers, 2548).
+-define(wxGLCanvas_destroy, 2549).
+-define(wxAuiManager_new, 2550).
+-define(wxAuiManager_destruct, 2551).
+-define(wxAuiManager_AddPane_2_1, 2552).
+-define(wxAuiManager_AddPane_3, 2553).
+-define(wxAuiManager_AddPane_2_0, 2554).
+-define(wxAuiManager_DetachPane, 2555).
+-define(wxAuiManager_GetAllPanes, 2556).
+-define(wxAuiManager_GetArtProvider, 2557).
+-define(wxAuiManager_GetDockSizeConstraint, 2558).
+-define(wxAuiManager_GetFlags, 2559).
+-define(wxAuiManager_GetManagedWindow, 2560).
+-define(wxAuiManager_GetManager, 2561).
+-define(wxAuiManager_GetPane_1_1, 2562).
+-define(wxAuiManager_GetPane_1_0, 2563).
+-define(wxAuiManager_HideHint, 2564).
+-define(wxAuiManager_InsertPane, 2565).
+-define(wxAuiManager_LoadPaneInfo, 2566).
+-define(wxAuiManager_LoadPerspective, 2567).
+-define(wxAuiManager_SavePaneInfo, 2568).
+-define(wxAuiManager_SavePerspective, 2569).
+-define(wxAuiManager_SetArtProvider, 2570).
+-define(wxAuiManager_SetDockSizeConstraint, 2571).
+-define(wxAuiManager_SetFlags, 2572).
+-define(wxAuiManager_SetManagedWindow, 2573).
+-define(wxAuiManager_ShowHint, 2574).
+-define(wxAuiManager_UnInit, 2575).
+-define(wxAuiManager_Update, 2576).
+-define(wxAuiPaneInfo_new_0, 2577).
+-define(wxAuiPaneInfo_new_1, 2578).
+-define(wxAuiPaneInfo_destruct, 2579).
+-define(wxAuiPaneInfo_BestSize_1, 2580).
+-define(wxAuiPaneInfo_BestSize_2, 2581).
+-define(wxAuiPaneInfo_Bottom, 2582).
+-define(wxAuiPaneInfo_BottomDockable, 2583).
+-define(wxAuiPaneInfo_Caption, 2584).
+-define(wxAuiPaneInfo_CaptionVisible, 2585).
+-define(wxAuiPaneInfo_Centre, 2586).
+-define(wxAuiPaneInfo_CentrePane, 2587).
+-define(wxAuiPaneInfo_CloseButton, 2588).
+-define(wxAuiPaneInfo_DefaultPane, 2589).
+-define(wxAuiPaneInfo_DestroyOnClose, 2590).
+-define(wxAuiPaneInfo_Direction, 2591).
+-define(wxAuiPaneInfo_Dock, 2592).
+-define(wxAuiPaneInfo_Dockable, 2593).
+-define(wxAuiPaneInfo_Fixed, 2594).
+-define(wxAuiPaneInfo_Float, 2595).
+-define(wxAuiPaneInfo_Floatable, 2596).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2597).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2598).
+-define(wxAuiPaneInfo_FloatingSize_1, 2599).
+-define(wxAuiPaneInfo_FloatingSize_2, 2600).
+-define(wxAuiPaneInfo_Gripper, 2601).
+-define(wxAuiPaneInfo_GripperTop, 2602).
+-define(wxAuiPaneInfo_HasBorder, 2603).
+-define(wxAuiPaneInfo_HasCaption, 2604).
+-define(wxAuiPaneInfo_HasCloseButton, 2605).
+-define(wxAuiPaneInfo_HasFlag, 2606).
+-define(wxAuiPaneInfo_HasGripper, 2607).
+-define(wxAuiPaneInfo_HasGripperTop, 2608).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2609).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2610).
+-define(wxAuiPaneInfo_HasPinButton, 2611).
+-define(wxAuiPaneInfo_Hide, 2612).
+-define(wxAuiPaneInfo_IsBottomDockable, 2613).
+-define(wxAuiPaneInfo_IsDocked, 2614).
+-define(wxAuiPaneInfo_IsFixed, 2615).
+-define(wxAuiPaneInfo_IsFloatable, 2616).
+-define(wxAuiPaneInfo_IsFloating, 2617).
+-define(wxAuiPaneInfo_IsLeftDockable, 2618).
+-define(wxAuiPaneInfo_IsMovable, 2619).
+-define(wxAuiPaneInfo_IsOk, 2620).
+-define(wxAuiPaneInfo_IsResizable, 2621).
+-define(wxAuiPaneInfo_IsRightDockable, 2622).
+-define(wxAuiPaneInfo_IsShown, 2623).
+-define(wxAuiPaneInfo_IsToolbar, 2624).
+-define(wxAuiPaneInfo_IsTopDockable, 2625).
+-define(wxAuiPaneInfo_Layer, 2626).
+-define(wxAuiPaneInfo_Left, 2627).
+-define(wxAuiPaneInfo_LeftDockable, 2628).
+-define(wxAuiPaneInfo_MaxSize_1, 2629).
+-define(wxAuiPaneInfo_MaxSize_2, 2630).
+-define(wxAuiPaneInfo_MaximizeButton, 2631).
+-define(wxAuiPaneInfo_MinSize_1, 2632).
+-define(wxAuiPaneInfo_MinSize_2, 2633).
+-define(wxAuiPaneInfo_MinimizeButton, 2634).
+-define(wxAuiPaneInfo_Movable, 2635).
+-define(wxAuiPaneInfo_Name, 2636).
+-define(wxAuiPaneInfo_PaneBorder, 2637).
+-define(wxAuiPaneInfo_PinButton, 2638).
+-define(wxAuiPaneInfo_Position, 2639).
+-define(wxAuiPaneInfo_Resizable, 2640).
+-define(wxAuiPaneInfo_Right, 2641).
+-define(wxAuiPaneInfo_RightDockable, 2642).
+-define(wxAuiPaneInfo_Row, 2643).
+-define(wxAuiPaneInfo_SafeSet, 2644).
+-define(wxAuiPaneInfo_SetFlag, 2645).
+-define(wxAuiPaneInfo_Show, 2646).
+-define(wxAuiPaneInfo_ToolbarPane, 2647).
+-define(wxAuiPaneInfo_Top, 2648).
+-define(wxAuiPaneInfo_TopDockable, 2649).
+-define(wxAuiPaneInfo_Window, 2650).
+-define(wxAuiNotebook_new_0, 2651).
+-define(wxAuiNotebook_new_2, 2652).
+-define(wxAuiNotebook_AddPage, 2653).
+-define(wxAuiNotebook_Create, 2654).
+-define(wxAuiNotebook_DeletePage, 2655).
+-define(wxAuiNotebook_GetArtProvider, 2656).
+-define(wxAuiNotebook_GetPage, 2657).
+-define(wxAuiNotebook_GetPageBitmap, 2658).
+-define(wxAuiNotebook_GetPageCount, 2659).
+-define(wxAuiNotebook_GetPageIndex, 2660).
+-define(wxAuiNotebook_GetPageText, 2661).
+-define(wxAuiNotebook_GetSelection, 2662).
+-define(wxAuiNotebook_InsertPage, 2663).
+-define(wxAuiNotebook_RemovePage, 2664).
+-define(wxAuiNotebook_SetArtProvider, 2665).
+-define(wxAuiNotebook_SetFont, 2666).
+-define(wxAuiNotebook_SetPageBitmap, 2667).
+-define(wxAuiNotebook_SetPageText, 2668).
+-define(wxAuiNotebook_SetSelection, 2669).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2670).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2671).
+-define(wxAuiNotebook_destroy, 2672).
+-define(wxMDIParentFrame_new_0, 2673).
+-define(wxMDIParentFrame_new_4, 2674).
+-define(wxMDIParentFrame_destruct, 2675).
+-define(wxMDIParentFrame_ActivateNext, 2676).
+-define(wxMDIParentFrame_ActivatePrevious, 2677).
+-define(wxMDIParentFrame_ArrangeIcons, 2678).
+-define(wxMDIParentFrame_Cascade, 2679).
+-define(wxMDIParentFrame_Create, 2680).
+-define(wxMDIParentFrame_GetActiveChild, 2681).
+-define(wxMDIParentFrame_GetClientWindow, 2682).
+-define(wxMDIParentFrame_Tile, 2683).
+-define(wxMDIChildFrame_new_0, 2684).
+-define(wxMDIChildFrame_new_4, 2685).
+-define(wxMDIChildFrame_destruct, 2686).
+-define(wxMDIChildFrame_Activate, 2687).
+-define(wxMDIChildFrame_Create, 2688).
+-define(wxMDIChildFrame_Maximize, 2689).
+-define(wxMDIChildFrame_Restore, 2690).
+-define(wxMDIClientWindow_new_0, 2691).
+-define(wxMDIClientWindow_new_2, 2692).
+-define(wxMDIClientWindow_destruct, 2693).
+-define(wxMDIClientWindow_CreateClient, 2694).
+-define(wxLayoutAlgorithm_new, 2695).
+-define(wxLayoutAlgorithm_LayoutFrame, 2696).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2697).
+-define(wxLayoutAlgorithm_LayoutWindow, 2698).
+-define(wxLayoutAlgorithm_destroy, 2699).
+-define(wxEvent_GetId, 2700).
+-define(wxEvent_GetSkipped, 2701).
+-define(wxEvent_GetTimestamp, 2702).
+-define(wxEvent_IsCommandEvent, 2703).
+-define(wxEvent_ResumePropagation, 2704).
+-define(wxEvent_ShouldPropagate, 2705).
+-define(wxEvent_Skip, 2706).
+-define(wxEvent_StopPropagation, 2707).
+-define(wxCommandEvent_getClientData, 2708).
+-define(wxCommandEvent_GetExtraLong, 2709).
+-define(wxCommandEvent_GetInt, 2710).
+-define(wxCommandEvent_GetSelection, 2711).
+-define(wxCommandEvent_GetString, 2712).
+-define(wxCommandEvent_IsChecked, 2713).
+-define(wxCommandEvent_IsSelection, 2714).
+-define(wxCommandEvent_SetInt, 2715).
+-define(wxCommandEvent_SetString, 2716).
+-define(wxScrollEvent_GetOrientation, 2717).
+-define(wxScrollEvent_GetPosition, 2718).
+-define(wxScrollWinEvent_GetOrientation, 2719).
+-define(wxScrollWinEvent_GetPosition, 2720).
+-define(wxMouseEvent_AltDown, 2721).
+-define(wxMouseEvent_Button, 2722).
+-define(wxMouseEvent_ButtonDClick, 2723).
+-define(wxMouseEvent_ButtonDown, 2724).
+-define(wxMouseEvent_ButtonUp, 2725).
+-define(wxMouseEvent_CmdDown, 2726).
+-define(wxMouseEvent_ControlDown, 2727).
+-define(wxMouseEvent_Dragging, 2728).
+-define(wxMouseEvent_Entering, 2729).
+-define(wxMouseEvent_GetButton, 2730).
+-define(wxMouseEvent_GetPosition, 2733).
+-define(wxMouseEvent_GetLogicalPosition, 2734).
+-define(wxMouseEvent_GetLinesPerAction, 2735).
+-define(wxMouseEvent_GetWheelRotation, 2736).
+-define(wxMouseEvent_GetWheelDelta, 2737).
+-define(wxMouseEvent_GetX, 2738).
+-define(wxMouseEvent_GetY, 2739).
+-define(wxMouseEvent_IsButton, 2740).
+-define(wxMouseEvent_IsPageScroll, 2741).
+-define(wxMouseEvent_Leaving, 2742).
+-define(wxMouseEvent_LeftDClick, 2743).
+-define(wxMouseEvent_LeftDown, 2744).
+-define(wxMouseEvent_LeftIsDown, 2745).
+-define(wxMouseEvent_LeftUp, 2746).
+-define(wxMouseEvent_MetaDown, 2747).
+-define(wxMouseEvent_MiddleDClick, 2748).
+-define(wxMouseEvent_MiddleDown, 2749).
+-define(wxMouseEvent_MiddleIsDown, 2750).
+-define(wxMouseEvent_MiddleUp, 2751).
+-define(wxMouseEvent_Moving, 2752).
+-define(wxMouseEvent_RightDClick, 2753).
+-define(wxMouseEvent_RightDown, 2754).
+-define(wxMouseEvent_RightIsDown, 2755).
+-define(wxMouseEvent_RightUp, 2756).
+-define(wxMouseEvent_ShiftDown, 2757).
+-define(wxSetCursorEvent_GetCursor, 2758).
+-define(wxSetCursorEvent_GetX, 2759).
+-define(wxSetCursorEvent_GetY, 2760).
+-define(wxSetCursorEvent_HasCursor, 2761).
+-define(wxSetCursorEvent_SetCursor, 2762).
+-define(wxKeyEvent_AltDown, 2763).
+-define(wxKeyEvent_CmdDown, 2764).
+-define(wxKeyEvent_ControlDown, 2765).
+-define(wxKeyEvent_GetKeyCode, 2766).
+-define(wxKeyEvent_GetModifiers, 2767).
+-define(wxKeyEvent_GetPosition, 2770).
+-define(wxKeyEvent_GetRawKeyCode, 2771).
+-define(wxKeyEvent_GetRawKeyFlags, 2772).
+-define(wxKeyEvent_GetUnicodeKey, 2773).
+-define(wxKeyEvent_GetX, 2774).
+-define(wxKeyEvent_GetY, 2775).
+-define(wxKeyEvent_HasModifiers, 2776).
+-define(wxKeyEvent_MetaDown, 2777).
+-define(wxKeyEvent_ShiftDown, 2778).
+-define(wxSizeEvent_GetSize, 2779).
+-define(wxMoveEvent_GetPosition, 2780).
+-define(wxEraseEvent_GetDC, 2781).
+-define(wxFocusEvent_GetWindow, 2782).
+-define(wxChildFocusEvent_GetWindow, 2783).
+-define(wxMenuEvent_GetMenu, 2784).
+-define(wxMenuEvent_GetMenuId, 2785).
+-define(wxMenuEvent_IsPopup, 2786).
+-define(wxCloseEvent_CanVeto, 2787).
+-define(wxCloseEvent_GetLoggingOff, 2788).
+-define(wxCloseEvent_SetCanVeto, 2789).
+-define(wxCloseEvent_SetLoggingOff, 2790).
+-define(wxCloseEvent_Veto, 2791).
+-define(wxShowEvent_SetShow, 2792).
+-define(wxShowEvent_GetShow, 2793).
+-define(wxIconizeEvent_Iconized, 2794).
+-define(wxJoystickEvent_ButtonDown, 2795).
+-define(wxJoystickEvent_ButtonIsDown, 2796).
+-define(wxJoystickEvent_ButtonUp, 2797).
+-define(wxJoystickEvent_GetButtonChange, 2798).
+-define(wxJoystickEvent_GetButtonState, 2799).
+-define(wxJoystickEvent_GetJoystick, 2800).
+-define(wxJoystickEvent_GetPosition, 2801).
+-define(wxJoystickEvent_GetZPosition, 2802).
+-define(wxJoystickEvent_IsButton, 2803).
+-define(wxJoystickEvent_IsMove, 2804).
+-define(wxJoystickEvent_IsZMove, 2805).
+-define(wxUpdateUIEvent_CanUpdate, 2806).
+-define(wxUpdateUIEvent_Check, 2807).
+-define(wxUpdateUIEvent_Enable, 2808).
+-define(wxUpdateUIEvent_Show, 2809).
+-define(wxUpdateUIEvent_GetChecked, 2810).
+-define(wxUpdateUIEvent_GetEnabled, 2811).
+-define(wxUpdateUIEvent_GetShown, 2812).
+-define(wxUpdateUIEvent_GetSetChecked, 2813).
+-define(wxUpdateUIEvent_GetSetEnabled, 2814).
+-define(wxUpdateUIEvent_GetSetShown, 2815).
+-define(wxUpdateUIEvent_GetSetText, 2816).
+-define(wxUpdateUIEvent_GetText, 2817).
+-define(wxUpdateUIEvent_GetMode, 2818).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2819).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2820).
+-define(wxUpdateUIEvent_SetMode, 2821).
+-define(wxUpdateUIEvent_SetText, 2822).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2823).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2824).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2825).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2826).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2827).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2828).
+-define(wxNavigationKeyEvent_GetDirection, 2829).
+-define(wxNavigationKeyEvent_SetDirection, 2830).
+-define(wxNavigationKeyEvent_IsWindowChange, 2831).
+-define(wxNavigationKeyEvent_SetWindowChange, 2832).
+-define(wxNavigationKeyEvent_IsFromTab, 2833).
+-define(wxNavigationKeyEvent_SetFromTab, 2834).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2835).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2836).
+-define(wxHelpEvent_GetOrigin, 2837).
+-define(wxHelpEvent_GetPosition, 2838).
+-define(wxHelpEvent_SetOrigin, 2839).
+-define(wxHelpEvent_SetPosition, 2840).
+-define(wxContextMenuEvent_GetPosition, 2841).
+-define(wxContextMenuEvent_SetPosition, 2842).
+-define(wxIdleEvent_CanSend, 2843).
+-define(wxIdleEvent_GetMode, 2844).
+-define(wxIdleEvent_RequestMore, 2845).
+-define(wxIdleEvent_MoreRequested, 2846).
+-define(wxIdleEvent_SetMode, 2847).
+-define(wxGridEvent_AltDown, 2848).
+-define(wxGridEvent_ControlDown, 2849).
+-define(wxGridEvent_GetCol, 2850).
+-define(wxGridEvent_GetPosition, 2851).
+-define(wxGridEvent_GetRow, 2852).
+-define(wxGridEvent_MetaDown, 2853).
+-define(wxGridEvent_Selecting, 2854).
+-define(wxGridEvent_ShiftDown, 2855).
+-define(wxNotifyEvent_Allow, 2856).
+-define(wxNotifyEvent_IsAllowed, 2857).
+-define(wxNotifyEvent_Veto, 2858).
+-define(wxSashEvent_GetEdge, 2859).
+-define(wxSashEvent_GetDragRect, 2860).
+-define(wxSashEvent_GetDragStatus, 2861).
+-define(wxListEvent_GetCacheFrom, 2862).
+-define(wxListEvent_GetCacheTo, 2863).
+-define(wxListEvent_GetKeyCode, 2864).
+-define(wxListEvent_GetIndex, 2865).
+-define(wxListEvent_GetColumn, 2866).
+-define(wxListEvent_GetPoint, 2867).
+-define(wxListEvent_GetLabel, 2868).
+-define(wxListEvent_GetText, 2869).
+-define(wxListEvent_GetImage, 2870).
+-define(wxListEvent_GetData, 2871).
+-define(wxListEvent_GetMask, 2872).
+-define(wxListEvent_GetItem, 2873).
+-define(wxListEvent_IsEditCancelled, 2874).
+-define(wxDateEvent_GetDate, 2875).
+-define(wxCalendarEvent_GetWeekDay, 2876).
+-define(wxFileDirPickerEvent_GetPath, 2877).
+-define(wxColourPickerEvent_GetColour, 2878).
+-define(wxFontPickerEvent_GetFont, 2879).
+-define(wxStyledTextEvent_GetPosition, 2880).
+-define(wxStyledTextEvent_GetKey, 2881).
+-define(wxStyledTextEvent_GetModifiers, 2882).
+-define(wxStyledTextEvent_GetModificationType, 2883).
+-define(wxStyledTextEvent_GetText, 2884).
+-define(wxStyledTextEvent_GetLength, 2885).
+-define(wxStyledTextEvent_GetLinesAdded, 2886).
+-define(wxStyledTextEvent_GetLine, 2887).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2888).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2889).
+-define(wxStyledTextEvent_GetMargin, 2890).
+-define(wxStyledTextEvent_GetMessage, 2891).
+-define(wxStyledTextEvent_GetWParam, 2892).
+-define(wxStyledTextEvent_GetLParam, 2893).
+-define(wxStyledTextEvent_GetListType, 2894).
+-define(wxStyledTextEvent_GetX, 2895).
+-define(wxStyledTextEvent_GetY, 2896).
+-define(wxStyledTextEvent_GetDragText, 2897).
+-define(wxStyledTextEvent_GetDragAllowMove, 2898).
+-define(wxStyledTextEvent_GetDragResult, 2899).
+-define(wxStyledTextEvent_GetShift, 2900).
+-define(wxStyledTextEvent_GetControl, 2901).
+-define(wxStyledTextEvent_GetAlt, 2902).
+-define(utils_wxGetKeyState, 2903).
+-define(utils_wxGetMousePosition, 2904).
+-define(utils_wxGetMouseState, 2905).
+-define(utils_wxSetDetectableAutoRepeat, 2906).
+-define(utils_wxBell, 2907).
+-define(utils_wxFindMenuItemId, 2908).
+-define(utils_wxGenericFindWindowAtPoint, 2909).
+-define(utils_wxFindWindowAtPoint, 2910).
+-define(utils_wxBeginBusyCursor, 2911).
+-define(utils_wxEndBusyCursor, 2912).
+-define(utils_wxIsBusy, 2913).
+-define(utils_wxShutdown, 2914).
+-define(utils_wxShell, 2915).
+-define(utils_wxLaunchDefaultBrowser, 2916).
+-define(utils_wxGetEmailAddress, 2917).
+-define(utils_wxGetUserId, 2918).
+-define(utils_wxGetHomeDir, 2919).
+-define(utils_wxNewId, 2920).
+-define(utils_wxRegisterId, 2921).
+-define(utils_wxGetCurrentId, 2922).
+-define(utils_wxGetOsDescription, 2923).
+-define(utils_wxIsPlatformLittleEndian, 2924).
+-define(utils_wxIsPlatform64Bit, 2925).
+-define(wxPrintout_new, 2926).
+-define(wxPrintout_destruct, 2927).
+-define(wxPrintout_GetDC, 2928).
+-define(wxPrintout_GetPageSizeMM, 2929).
+-define(wxPrintout_GetPageSizePixels, 2930).
+-define(wxPrintout_GetPaperRectPixels, 2931).
+-define(wxPrintout_GetPPIPrinter, 2932).
+-define(wxPrintout_GetPPIScreen, 2933).
+-define(wxPrintout_GetTitle, 2934).
+-define(wxPrintout_IsPreview, 2935).
+-define(wxPrintout_FitThisSizeToPaper, 2936).
+-define(wxPrintout_FitThisSizeToPage, 2937).
+-define(wxPrintout_FitThisSizeToPageMargins, 2938).
+-define(wxPrintout_MapScreenSizeToPaper, 2939).
+-define(wxPrintout_MapScreenSizeToPage, 2940).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2941).
+-define(wxPrintout_MapScreenSizeToDevice, 2942).
+-define(wxPrintout_GetLogicalPaperRect, 2943).
+-define(wxPrintout_GetLogicalPageRect, 2944).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2945).
+-define(wxPrintout_SetLogicalOrigin, 2946).
+-define(wxPrintout_OffsetLogicalOrigin, 2947).
+-define(wxStyledTextCtrl_new_2, 2948).
+-define(wxStyledTextCtrl_new_0, 2949).
+-define(wxStyledTextCtrl_destruct, 2950).
+-define(wxStyledTextCtrl_Create, 2951).
+-define(wxStyledTextCtrl_AddText, 2952).
+-define(wxStyledTextCtrl_AddStyledText, 2953).
+-define(wxStyledTextCtrl_InsertText, 2954).
+-define(wxStyledTextCtrl_ClearAll, 2955).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2956).
+-define(wxStyledTextCtrl_GetLength, 2957).
+-define(wxStyledTextCtrl_GetCharAt, 2958).
+-define(wxStyledTextCtrl_GetCurrentPos, 2959).
+-define(wxStyledTextCtrl_GetAnchor, 2960).
+-define(wxStyledTextCtrl_GetStyleAt, 2961).
+-define(wxStyledTextCtrl_Redo, 2962).
+-define(wxStyledTextCtrl_SetUndoCollection, 2963).
+-define(wxStyledTextCtrl_SelectAll, 2964).
+-define(wxStyledTextCtrl_SetSavePoint, 2965).
+-define(wxStyledTextCtrl_GetStyledText, 2966).
+-define(wxStyledTextCtrl_CanRedo, 2967).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2968).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2969).
+-define(wxStyledTextCtrl_GetUndoCollection, 2970).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2971).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 2972).
+-define(wxStyledTextCtrl_PositionFromPoint, 2973).
+-define(wxStyledTextCtrl_PositionFromPointClose, 2974).
+-define(wxStyledTextCtrl_GotoLine, 2975).
+-define(wxStyledTextCtrl_GotoPos, 2976).
+-define(wxStyledTextCtrl_SetAnchor, 2977).
+-define(wxStyledTextCtrl_GetCurLine, 2978).
+-define(wxStyledTextCtrl_GetEndStyled, 2979).
+-define(wxStyledTextCtrl_ConvertEOLs, 2980).
+-define(wxStyledTextCtrl_GetEOLMode, 2981).
+-define(wxStyledTextCtrl_SetEOLMode, 2982).
+-define(wxStyledTextCtrl_StartStyling, 2983).
+-define(wxStyledTextCtrl_SetStyling, 2984).
+-define(wxStyledTextCtrl_GetBufferedDraw, 2985).
+-define(wxStyledTextCtrl_SetBufferedDraw, 2986).
+-define(wxStyledTextCtrl_SetTabWidth, 2987).
+-define(wxStyledTextCtrl_GetTabWidth, 2988).
+-define(wxStyledTextCtrl_SetCodePage, 2989).
+-define(wxStyledTextCtrl_MarkerDefine, 2990).
+-define(wxStyledTextCtrl_MarkerSetForeground, 2991).
+-define(wxStyledTextCtrl_MarkerSetBackground, 2992).
+-define(wxStyledTextCtrl_MarkerAdd, 2993).
+-define(wxStyledTextCtrl_MarkerDelete, 2994).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 2995).
+-define(wxStyledTextCtrl_MarkerGet, 2996).
+-define(wxStyledTextCtrl_MarkerNext, 2997).
+-define(wxStyledTextCtrl_MarkerPrevious, 2998).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 2999).
+-define(wxStyledTextCtrl_MarkerAddSet, 3000).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 3001).
+-define(wxStyledTextCtrl_SetMarginType, 3002).
+-define(wxStyledTextCtrl_GetMarginType, 3003).
+-define(wxStyledTextCtrl_SetMarginWidth, 3004).
+-define(wxStyledTextCtrl_GetMarginWidth, 3005).
+-define(wxStyledTextCtrl_SetMarginMask, 3006).
+-define(wxStyledTextCtrl_GetMarginMask, 3007).
+-define(wxStyledTextCtrl_SetMarginSensitive, 3008).
+-define(wxStyledTextCtrl_GetMarginSensitive, 3009).
+-define(wxStyledTextCtrl_StyleClearAll, 3010).
+-define(wxStyledTextCtrl_StyleSetForeground, 3011).
+-define(wxStyledTextCtrl_StyleSetBackground, 3012).
+-define(wxStyledTextCtrl_StyleSetBold, 3013).
+-define(wxStyledTextCtrl_StyleSetItalic, 3014).
+-define(wxStyledTextCtrl_StyleSetSize, 3015).
+-define(wxStyledTextCtrl_StyleSetFaceName, 3016).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 3017).
+-define(wxStyledTextCtrl_StyleResetDefault, 3018).
+-define(wxStyledTextCtrl_StyleSetUnderline, 3019).
+-define(wxStyledTextCtrl_StyleSetCase, 3020).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3021).
+-define(wxStyledTextCtrl_SetSelForeground, 3022).
+-define(wxStyledTextCtrl_SetSelBackground, 3023).
+-define(wxStyledTextCtrl_GetSelAlpha, 3024).
+-define(wxStyledTextCtrl_SetSelAlpha, 3025).
+-define(wxStyledTextCtrl_SetCaretForeground, 3026).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3027).
+-define(wxStyledTextCtrl_CmdKeyClear, 3028).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3029).
+-define(wxStyledTextCtrl_SetStyleBytes, 3030).
+-define(wxStyledTextCtrl_StyleSetVisible, 3031).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3032).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3033).
+-define(wxStyledTextCtrl_SetWordChars, 3034).
+-define(wxStyledTextCtrl_BeginUndoAction, 3035).
+-define(wxStyledTextCtrl_EndUndoAction, 3036).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3037).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3038).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3039).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3040).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3041).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3042).
+-define(wxStyledTextCtrl_GetStyleBits, 3043).
+-define(wxStyledTextCtrl_SetLineState, 3044).
+-define(wxStyledTextCtrl_GetLineState, 3045).
+-define(wxStyledTextCtrl_GetMaxLineState, 3046).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3047).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3048).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3049).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3050).
+-define(wxStyledTextCtrl_AutoCompShow, 3051).
+-define(wxStyledTextCtrl_AutoCompCancel, 3052).
+-define(wxStyledTextCtrl_AutoCompActive, 3053).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3054).
+-define(wxStyledTextCtrl_AutoCompComplete, 3055).
+-define(wxStyledTextCtrl_AutoCompStops, 3056).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3057).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3058).
+-define(wxStyledTextCtrl_AutoCompSelect, 3059).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3060).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3061).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3062).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3063).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3064).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3065).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3066).
+-define(wxStyledTextCtrl_UserListShow, 3067).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3068).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3069).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3070).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3071).
+-define(wxStyledTextCtrl_RegisterImage, 3072).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3073).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3074).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3075).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3076).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3077).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3078).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3079).
+-define(wxStyledTextCtrl_SetIndent, 3080).
+-define(wxStyledTextCtrl_GetIndent, 3081).
+-define(wxStyledTextCtrl_SetUseTabs, 3082).
+-define(wxStyledTextCtrl_GetUseTabs, 3083).
+-define(wxStyledTextCtrl_SetLineIndentation, 3084).
+-define(wxStyledTextCtrl_GetLineIndentation, 3085).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3086).
+-define(wxStyledTextCtrl_GetColumn, 3087).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3088).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3089).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3090).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3091).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3092).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3093).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3094).
+-define(wxStyledTextCtrl_GetCodePage, 3095).
+-define(wxStyledTextCtrl_GetCaretForeground, 3096).
+-define(wxStyledTextCtrl_GetReadOnly, 3097).
+-define(wxStyledTextCtrl_SetCurrentPos, 3098).
+-define(wxStyledTextCtrl_SetSelectionStart, 3099).
+-define(wxStyledTextCtrl_GetSelectionStart, 3100).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3101).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3102).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3103).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3104).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3105).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3106).
+-define(wxStyledTextCtrl_FindText, 3107).
+-define(wxStyledTextCtrl_FormatRange, 3108).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3109).
+-define(wxStyledTextCtrl_GetLine, 3110).
+-define(wxStyledTextCtrl_GetLineCount, 3111).
+-define(wxStyledTextCtrl_SetMarginLeft, 3112).
+-define(wxStyledTextCtrl_GetMarginLeft, 3113).
+-define(wxStyledTextCtrl_SetMarginRight, 3114).
+-define(wxStyledTextCtrl_GetMarginRight, 3115).
+-define(wxStyledTextCtrl_GetModify, 3116).
+-define(wxStyledTextCtrl_SetSelection, 3117).
+-define(wxStyledTextCtrl_GetSelectedText, 3118).
+-define(wxStyledTextCtrl_GetTextRange, 3119).
+-define(wxStyledTextCtrl_HideSelection, 3120).
+-define(wxStyledTextCtrl_LineFromPosition, 3121).
+-define(wxStyledTextCtrl_PositionFromLine, 3122).
+-define(wxStyledTextCtrl_LineScroll, 3123).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3124).
+-define(wxStyledTextCtrl_ReplaceSelection, 3125).
+-define(wxStyledTextCtrl_SetReadOnly, 3126).
+-define(wxStyledTextCtrl_CanPaste, 3127).
+-define(wxStyledTextCtrl_CanUndo, 3128).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3129).
+-define(wxStyledTextCtrl_Undo, 3130).
+-define(wxStyledTextCtrl_Cut, 3131).
+-define(wxStyledTextCtrl_Copy, 3132).
+-define(wxStyledTextCtrl_Paste, 3133).
+-define(wxStyledTextCtrl_Clear, 3134).
+-define(wxStyledTextCtrl_SetText, 3135).
+-define(wxStyledTextCtrl_GetText, 3136).
+-define(wxStyledTextCtrl_GetTextLength, 3137).
+-define(wxStyledTextCtrl_GetOvertype, 3138).
+-define(wxStyledTextCtrl_SetCaretWidth, 3139).
+-define(wxStyledTextCtrl_GetCaretWidth, 3140).
+-define(wxStyledTextCtrl_SetTargetStart, 3141).
+-define(wxStyledTextCtrl_GetTargetStart, 3142).
+-define(wxStyledTextCtrl_SetTargetEnd, 3143).
+-define(wxStyledTextCtrl_GetTargetEnd, 3144).
+-define(wxStyledTextCtrl_ReplaceTarget, 3145).
+-define(wxStyledTextCtrl_SearchInTarget, 3146).
+-define(wxStyledTextCtrl_SetSearchFlags, 3147).
+-define(wxStyledTextCtrl_GetSearchFlags, 3148).
+-define(wxStyledTextCtrl_CallTipShow, 3149).
+-define(wxStyledTextCtrl_CallTipCancel, 3150).
+-define(wxStyledTextCtrl_CallTipActive, 3151).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3152).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3153).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3154).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3155).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3156).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3157).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3158).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3159).
+-define(wxStyledTextCtrl_WrapCount, 3160).
+-define(wxStyledTextCtrl_SetFoldLevel, 3161).
+-define(wxStyledTextCtrl_GetFoldLevel, 3162).
+-define(wxStyledTextCtrl_GetLastChild, 3163).
+-define(wxStyledTextCtrl_GetFoldParent, 3164).
+-define(wxStyledTextCtrl_ShowLines, 3165).
+-define(wxStyledTextCtrl_HideLines, 3166).
+-define(wxStyledTextCtrl_GetLineVisible, 3167).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3168).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3169).
+-define(wxStyledTextCtrl_ToggleFold, 3170).
+-define(wxStyledTextCtrl_EnsureVisible, 3171).
+-define(wxStyledTextCtrl_SetFoldFlags, 3172).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3173).
+-define(wxStyledTextCtrl_SetTabIndents, 3174).
+-define(wxStyledTextCtrl_GetTabIndents, 3175).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3176).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3177).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3178).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3179).
+-define(wxStyledTextCtrl_WordStartPosition, 3180).
+-define(wxStyledTextCtrl_WordEndPosition, 3181).
+-define(wxStyledTextCtrl_SetWrapMode, 3182).
+-define(wxStyledTextCtrl_GetWrapMode, 3183).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3184).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3185).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3186).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3187).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3188).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3189).
+-define(wxStyledTextCtrl_SetLayoutCache, 3190).
+-define(wxStyledTextCtrl_GetLayoutCache, 3191).
+-define(wxStyledTextCtrl_SetScrollWidth, 3192).
+-define(wxStyledTextCtrl_GetScrollWidth, 3193).
+-define(wxStyledTextCtrl_TextWidth, 3194).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3195).
+-define(wxStyledTextCtrl_TextHeight, 3196).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3197).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3198).
+-define(wxStyledTextCtrl_AppendText, 3199).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3200).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3201).
+-define(wxStyledTextCtrl_TargetFromSelection, 3202).
+-define(wxStyledTextCtrl_LinesJoin, 3203).
+-define(wxStyledTextCtrl_LinesSplit, 3204).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3205).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3206).
+-define(wxStyledTextCtrl_LineDown, 3207).
+-define(wxStyledTextCtrl_LineDownExtend, 3208).
+-define(wxStyledTextCtrl_LineUp, 3209).
+-define(wxStyledTextCtrl_LineUpExtend, 3210).
+-define(wxStyledTextCtrl_CharLeft, 3211).
+-define(wxStyledTextCtrl_CharLeftExtend, 3212).
+-define(wxStyledTextCtrl_CharRight, 3213).
+-define(wxStyledTextCtrl_CharRightExtend, 3214).
+-define(wxStyledTextCtrl_WordLeft, 3215).
+-define(wxStyledTextCtrl_WordLeftExtend, 3216).
+-define(wxStyledTextCtrl_WordRight, 3217).
+-define(wxStyledTextCtrl_WordRightExtend, 3218).
+-define(wxStyledTextCtrl_Home, 3219).
+-define(wxStyledTextCtrl_HomeExtend, 3220).
+-define(wxStyledTextCtrl_LineEnd, 3221).
+-define(wxStyledTextCtrl_LineEndExtend, 3222).
+-define(wxStyledTextCtrl_DocumentStart, 3223).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3224).
+-define(wxStyledTextCtrl_DocumentEnd, 3225).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3226).
+-define(wxStyledTextCtrl_PageUp, 3227).
+-define(wxStyledTextCtrl_PageUpExtend, 3228).
+-define(wxStyledTextCtrl_PageDown, 3229).
+-define(wxStyledTextCtrl_PageDownExtend, 3230).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3231).
+-define(wxStyledTextCtrl_Cancel, 3232).
+-define(wxStyledTextCtrl_DeleteBack, 3233).
+-define(wxStyledTextCtrl_Tab, 3234).
+-define(wxStyledTextCtrl_BackTab, 3235).
+-define(wxStyledTextCtrl_NewLine, 3236).
+-define(wxStyledTextCtrl_FormFeed, 3237).
+-define(wxStyledTextCtrl_VCHome, 3238).
+-define(wxStyledTextCtrl_VCHomeExtend, 3239).
+-define(wxStyledTextCtrl_ZoomIn, 3240).
+-define(wxStyledTextCtrl_ZoomOut, 3241).
+-define(wxStyledTextCtrl_DelWordLeft, 3242).
+-define(wxStyledTextCtrl_DelWordRight, 3243).
+-define(wxStyledTextCtrl_LineCut, 3244).
+-define(wxStyledTextCtrl_LineDelete, 3245).
+-define(wxStyledTextCtrl_LineTranspose, 3246).
+-define(wxStyledTextCtrl_LineDuplicate, 3247).
+-define(wxStyledTextCtrl_LowerCase, 3248).
+-define(wxStyledTextCtrl_UpperCase, 3249).
+-define(wxStyledTextCtrl_LineScrollDown, 3250).
+-define(wxStyledTextCtrl_LineScrollUp, 3251).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3252).
+-define(wxStyledTextCtrl_HomeDisplay, 3253).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3254).
+-define(wxStyledTextCtrl_LineEndDisplay, 3255).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3256).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3257).
+-define(wxStyledTextCtrl_LineEndWrap, 3258).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3259).
+-define(wxStyledTextCtrl_VCHomeWrap, 3260).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3261).
+-define(wxStyledTextCtrl_LineCopy, 3262).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3263).
+-define(wxStyledTextCtrl_LineLength, 3264).
+-define(wxStyledTextCtrl_BraceHighlight, 3265).
+-define(wxStyledTextCtrl_BraceBadLight, 3266).
+-define(wxStyledTextCtrl_BraceMatch, 3267).
+-define(wxStyledTextCtrl_GetViewEOL, 3268).
+-define(wxStyledTextCtrl_SetViewEOL, 3269).
+-define(wxStyledTextCtrl_SetModEventMask, 3270).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3271).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3272).
+-define(wxStyledTextCtrl_SetEdgeMode, 3273).
+-define(wxStyledTextCtrl_GetEdgeMode, 3274).
+-define(wxStyledTextCtrl_GetEdgeColour, 3275).
+-define(wxStyledTextCtrl_SetEdgeColour, 3276).
+-define(wxStyledTextCtrl_SearchAnchor, 3277).
+-define(wxStyledTextCtrl_SearchNext, 3278).
+-define(wxStyledTextCtrl_SearchPrev, 3279).
+-define(wxStyledTextCtrl_LinesOnScreen, 3280).
+-define(wxStyledTextCtrl_UsePopUp, 3281).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3282).
+-define(wxStyledTextCtrl_SetZoom, 3283).
+-define(wxStyledTextCtrl_GetZoom, 3284).
+-define(wxStyledTextCtrl_GetModEventMask, 3285).
+-define(wxStyledTextCtrl_SetSTCFocus, 3286).
+-define(wxStyledTextCtrl_GetSTCFocus, 3287).
+-define(wxStyledTextCtrl_SetStatus, 3288).
+-define(wxStyledTextCtrl_GetStatus, 3289).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3290).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3291).
+-define(wxStyledTextCtrl_SetSTCCursor, 3292).
+-define(wxStyledTextCtrl_GetSTCCursor, 3293).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3294).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3295).
+-define(wxStyledTextCtrl_WordPartLeft, 3296).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3297).
+-define(wxStyledTextCtrl_WordPartRight, 3298).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3299).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3300).
+-define(wxStyledTextCtrl_DelLineLeft, 3301).
+-define(wxStyledTextCtrl_DelLineRight, 3302).
+-define(wxStyledTextCtrl_GetXOffset, 3303).
+-define(wxStyledTextCtrl_ChooseCaretX, 3304).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3305).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3306).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3307).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3308).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3309).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3310).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3311).
+-define(wxStyledTextCtrl_ParaDownExtend, 3312).
+-define(wxStyledTextCtrl_ParaUp, 3313).
+-define(wxStyledTextCtrl_ParaUpExtend, 3314).
+-define(wxStyledTextCtrl_PositionBefore, 3315).
+-define(wxStyledTextCtrl_PositionAfter, 3316).
+-define(wxStyledTextCtrl_CopyRange, 3317).
+-define(wxStyledTextCtrl_CopyText, 3318).
+-define(wxStyledTextCtrl_SetSelectionMode, 3319).
+-define(wxStyledTextCtrl_GetSelectionMode, 3320).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3321).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3322).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3323).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3324).
+-define(wxStyledTextCtrl_HomeRectExtend, 3325).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3326).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3327).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3328).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3329).
+-define(wxStyledTextCtrl_StutteredPageUp, 3330).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3331).
+-define(wxStyledTextCtrl_StutteredPageDown, 3332).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3333).
+-define(wxStyledTextCtrl_WordLeftEnd, 3334).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3335).
+-define(wxStyledTextCtrl_WordRightEnd, 3336).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3337).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3338).
+-define(wxStyledTextCtrl_SetCharsDefault, 3339).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3340).
+-define(wxStyledTextCtrl_Allocate, 3341).
+-define(wxStyledTextCtrl_FindColumn, 3342).
+-define(wxStyledTextCtrl_GetCaretSticky, 3343).
+-define(wxStyledTextCtrl_SetCaretSticky, 3344).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3345).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3346).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3347).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3348).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3349).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3350).
+-define(wxStyledTextCtrl_StartRecord, 3351).
+-define(wxStyledTextCtrl_StopRecord, 3352).
+-define(wxStyledTextCtrl_SetLexer, 3353).
+-define(wxStyledTextCtrl_GetLexer, 3354).
+-define(wxStyledTextCtrl_Colourise, 3355).
+-define(wxStyledTextCtrl_SetProperty, 3356).
+-define(wxStyledTextCtrl_SetKeyWords, 3357).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3358).
+-define(wxStyledTextCtrl_GetProperty, 3359).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3360).
+-define(wxStyledTextCtrl_GetCurrentLine, 3361).
+-define(wxStyledTextCtrl_StyleSetSpec, 3362).
+-define(wxStyledTextCtrl_StyleSetFont, 3363).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3364).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3365).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3366).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3367).
+-define(wxStyledTextCtrl_SetMargins, 3368).
+-define(wxStyledTextCtrl_GetSelection, 3369).
+-define(wxStyledTextCtrl_PointFromPosition, 3370).
+-define(wxStyledTextCtrl_ScrollToLine, 3371).
+-define(wxStyledTextCtrl_ScrollToColumn, 3372).
+-define(wxStyledTextCtrl_SendMsg, 3373).
+-define(wxStyledTextCtrl_SetVScrollBar, 3374).
+-define(wxStyledTextCtrl_SetHScrollBar, 3375).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3376).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3377).
+-define(wxStyledTextCtrl_SaveFile, 3378).
+-define(wxStyledTextCtrl_LoadFile, 3379).
+-define(wxStyledTextCtrl_DoDragOver, 3380).
+-define(wxStyledTextCtrl_DoDropText, 3381).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3382).
+-define(wxStyledTextCtrl_AddTextRaw, 3383).
+-define(wxStyledTextCtrl_InsertTextRaw, 3384).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3385).
+-define(wxStyledTextCtrl_GetLineRaw, 3386).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3387).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3388).
+-define(wxStyledTextCtrl_SetTextRaw, 3389).
+-define(wxStyledTextCtrl_GetTextRaw, 3390).
+-define(wxStyledTextCtrl_AppendTextRaw, 3391).
+-define(wxArtProvider_GetBitmap, 3392).
+-define(wxArtProvider_GetIcon, 3393).
+-define(wxTreeEvent_GetKeyCode, 3394).
+-define(wxTreeEvent_GetItem, 3395).
+-define(wxTreeEvent_GetKeyEvent, 3396).
+-define(wxTreeEvent_GetLabel, 3397).
+-define(wxTreeEvent_GetOldItem, 3398).
+-define(wxTreeEvent_GetPoint, 3399).
+-define(wxTreeEvent_IsEditCancelled, 3400).
+-define(wxTreeEvent_SetToolTip, 3401).
+-define(wxNotebookEvent_GetOldSelection, 3402).
+-define(wxNotebookEvent_GetSelection, 3403).
+-define(wxNotebookEvent_SetOldSelection, 3404).
+-define(wxNotebookEvent_SetSelection, 3405).
+-define(wxFileDataObject_new, 3406).
+-define(wxFileDataObject_AddFile, 3407).
+-define(wxFileDataObject_GetFilenames, 3408).
+-define(wxFileDataObject_destroy, 3409).
+-define(wxTextDataObject_new, 3410).
+-define(wxTextDataObject_GetTextLength, 3411).
+-define(wxTextDataObject_GetText, 3412).
+-define(wxTextDataObject_SetText, 3413).
+-define(wxTextDataObject_destroy, 3414).
+-define(wxBitmapDataObject_new_1_1, 3415).
+-define(wxBitmapDataObject_new_1_0, 3416).
+-define(wxBitmapDataObject_GetBitmap, 3417).
+-define(wxBitmapDataObject_SetBitmap, 3418).
+-define(wxBitmapDataObject_destroy, 3419).
+-define(wxClipboard_new, 3421).
+-define(wxClipboard_destruct, 3422).
+-define(wxClipboard_AddData, 3423).
+-define(wxClipboard_Clear, 3424).
+-define(wxClipboard_Close, 3425).
+-define(wxClipboard_Flush, 3426).
+-define(wxClipboard_GetData, 3427).
+-define(wxClipboard_IsOpened, 3428).
+-define(wxClipboard_Open, 3429).
+-define(wxClipboard_SetData, 3430).
+-define(wxClipboard_UsePrimarySelection, 3432).
+-define(wxClipboard_IsSupported, 3433).
+-define(wxClipboard_Get, 3434).
+-define(wxSpinEvent_GetPosition, 3435).
+-define(wxSpinEvent_SetPosition, 3436).
+-define(wxSplitterWindow_new_0, 3437).
+-define(wxSplitterWindow_new_2, 3438).
+-define(wxSplitterWindow_destruct, 3439).
+-define(wxSplitterWindow_Create, 3440).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3441).
+-define(wxSplitterWindow_GetSashGravity, 3442).
+-define(wxSplitterWindow_GetSashPosition, 3443).
+-define(wxSplitterWindow_GetSplitMode, 3444).
+-define(wxSplitterWindow_GetWindow1, 3445).
+-define(wxSplitterWindow_GetWindow2, 3446).
+-define(wxSplitterWindow_Initialize, 3447).
+-define(wxSplitterWindow_IsSplit, 3448).
+-define(wxSplitterWindow_ReplaceWindow, 3449).
+-define(wxSplitterWindow_SetSashGravity, 3450).
+-define(wxSplitterWindow_SetSashPosition, 3451).
+-define(wxSplitterWindow_SetSashSize, 3452).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3453).
+-define(wxSplitterWindow_SetSplitMode, 3454).
+-define(wxSplitterWindow_SplitHorizontally, 3455).
+-define(wxSplitterWindow_SplitVertically, 3456).
+-define(wxSplitterWindow_Unsplit, 3457).
+-define(wxSplitterWindow_UpdateSize, 3458).
+-define(wxSplitterEvent_GetSashPosition, 3459).
+-define(wxSplitterEvent_GetX, 3460).
+-define(wxSplitterEvent_GetY, 3461).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3462).
+-define(wxSplitterEvent_SetSashPosition, 3463).
+-define(wxHtmlWindow_new_0, 3464).
+-define(wxHtmlWindow_new_2, 3465).
+-define(wxHtmlWindow_AppendToPage, 3466).
+-define(wxHtmlWindow_GetOpenedAnchor, 3467).
+-define(wxHtmlWindow_GetOpenedPage, 3468).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3469).
+-define(wxHtmlWindow_GetRelatedFrame, 3470).
+-define(wxHtmlWindow_HistoryBack, 3471).
+-define(wxHtmlWindow_HistoryCanBack, 3472).
+-define(wxHtmlWindow_HistoryCanForward, 3473).
+-define(wxHtmlWindow_HistoryClear, 3474).
+-define(wxHtmlWindow_HistoryForward, 3475).
+-define(wxHtmlWindow_LoadFile, 3476).
+-define(wxHtmlWindow_LoadPage, 3477).
+-define(wxHtmlWindow_SelectAll, 3478).
+-define(wxHtmlWindow_SelectionToText, 3479).
+-define(wxHtmlWindow_SelectLine, 3480).
+-define(wxHtmlWindow_SelectWord, 3481).
+-define(wxHtmlWindow_SetBorders, 3482).
+-define(wxHtmlWindow_SetFonts, 3483).
+-define(wxHtmlWindow_SetPage, 3484).
+-define(wxHtmlWindow_SetRelatedFrame, 3485).
+-define(wxHtmlWindow_SetRelatedStatusBar, 3486).
+-define(wxHtmlWindow_ToText, 3487).
+-define(wxHtmlWindow_destroy, 3488).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3489).
+-define(wxSystemSettings_GetColour, 3490).
+-define(wxSystemSettings_GetFont, 3491).
+-define(wxSystemSettings_GetMetric, 3492).
+-define(wxSystemSettings_GetScreenType, 3493).
+-define(wxSystemOptions_GetOption, 3494).
+-define(wxSystemOptions_GetOptionInt, 3495).
+-define(wxSystemOptions_HasOption, 3496).
+-define(wxSystemOptions_IsFalse, 3497).
+-define(wxSystemOptions_SetOption_2_1, 3498).
+-define(wxSystemOptions_SetOption_2_0, 3499).
+-define(wxAuiNotebookEvent_SetSelection, 3500).
+-define(wxAuiNotebookEvent_GetSelection, 3501).
+-define(wxAuiNotebookEvent_SetOldSelection, 3502).
+-define(wxAuiNotebookEvent_GetOldSelection, 3503).
+-define(wxAuiNotebookEvent_SetDragSource, 3504).
+-define(wxAuiNotebookEvent_GetDragSource, 3505).
+-define(wxAuiManagerEvent_SetManager, 3506).
+-define(wxAuiManagerEvent_GetManager, 3507).
+-define(wxAuiManagerEvent_SetPane, 3508).
+-define(wxAuiManagerEvent_GetPane, 3509).
+-define(wxAuiManagerEvent_SetButton, 3510).
+-define(wxAuiManagerEvent_GetButton, 3511).
+-define(wxAuiManagerEvent_SetDC, 3512).
+-define(wxAuiManagerEvent_GetDC, 3513).
+-define(wxAuiManagerEvent_Veto, 3514).
+-define(wxAuiManagerEvent_GetVeto, 3515).
+-define(wxAuiManagerEvent_SetCanVeto, 3516).
+-define(wxAuiManagerEvent_CanVeto, 3517).
+-define(wxLogNull_new, 3518).
+-define(wxLogNull_destroy, 3519).
+-define(wxTaskBarIcon_new, 3520).
+-define(wxTaskBarIcon_destruct, 3521).
+-define(wxTaskBarIcon_PopupMenu, 3522).
+-define(wxTaskBarIcon_RemoveIcon, 3523).
+-define(wxTaskBarIcon_SetIcon, 3524).
diff --git a/lib/wx/src/wx.erl b/lib/wx/src/wx.erl
index 9d76f3bc42..7d62305048 100644
--- a/lib/wx/src/wx.erl
+++ b/lib/wx/src/wx.erl
@@ -1,46 +1,46 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, 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 : wx.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 22 Feb 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
%% @doc A port of <a href="http://www.wxwidgets.org/">wxWidgets</a>.
-%%
+%%
%% This is the base api of <a href="http://www.wxwidgets.org/">wxWidgets</a>.
-%% This module contains functions for
+%% This module contains functions for
%% starting and stopping the wx-server, as well as other utility functions.
%%
%% wxWidgets is object oriented, and not functional. Thus, in wxErlang a
%% module represents a class, and the object created by this class
%% has an own type, wxCLASS(). This module represents the base
%% class, and all other wxMODULE's are sub-classes of this class.
-%%
-%% Objects of a class are created with wxCLASS:new(...) and destroyed with
+%%
+%% Objects of a class are created with wxCLASS:new(...) and destroyed with
%% wxCLASS:destroy(). Member functions are called with wxCLASS:member(Object, ...)
%% instead of as in C++ Object.member(...).
-%%
+%%
%% Sub class modules inherit (non static) functions from their parents.
%% The inherited functions are not documented in the sub-classes.
-%%
+%%
%% This erlang port of wxWidgets tries to be a one-to-one mapping with
%% the original wxWidgets library. Some things are different though,
%% as the optional arguments use property lists and can be in any
@@ -49,7 +49,7 @@
%%
%% The following classes are implemented directly as erlang types: <br />
%% wxPoint={x,y},wxSize={w,h},wxRect={x,y,w,h},wxColour={r,g,b [,a]},
-%% wxString={@link //stdlib/unicode:charlist()},
+%% wxString={@link //stdlib/unicode:chardata()},
%% wxGBPosition={r,c},wxGBSpan={rs,cs},wxGridCellCoords={r,c}.
%%
%% wxWidgets uses a process specific environment, which is created by
@@ -59,42 +59,50 @@
%%
%% Global (classless) functions are located in the wx_misc module.
-%% @type wxObject(). Opaque object
-%% @type wx_env(). Wx process environment
-%% @type wx_mem(). Wx memory area
-%% @type colour(). A 3 or 4 tuple: {R,G,B,A} or as argument {R,G,B} is also accepted
-%% where each colour channel is a an integer between 0-255.
-%% @type datetime(). {{Year,Month,Day}, {Hour,Minute,Second}} in local timezone.
-%% @type mouseState(). See #wxMouseState{} defined in wx.hrl
-
-
-module(wx).
-export([parent_class/1, new/0, new/1, destroy/0,
get_env/0,set_env/1, debug/1,
batch/1,foreach/2,map/2,foldl/3,foldr/3,
- getObjectType/1, typeCast/2,
+ getObjectType/1, typeCast/2,
null/0, is_null/1]).
-export([create_memory/1, get_memory_bin/1,
retain_memory/1, release_memory/1]).
-
-export([demo/0]).
+-export_type([wx_object/0, wx_env/0, wx_memory/0]).
+-export_type([wx_colour/0, wx_colour4/0, wx_datetime/0,
+ wx_enum/0, wx_wxMouseState/0, wx_wxHtmlLinkInfo/0]).
+
-include("wxe.hrl").
+-include("../include/wx.hrl").
+
+-type wx_object() :: #wx_ref{}. %% Opaque object reference
+-type wx_env() :: #wx_env{}. %% Opaque process environment
+-type wx_memory() :: binary() | #wx_mem{}. %% Opaque memory reference
+
+-type wx_colour4() :: {R::byte(),G::byte(),B::byte(), A::byte()}.
+-type wx_colour() :: {R::byte(),G::byte(),B::byte()} | wx_colour4().
+
+-type wx_datetime() :: {{Year::integer(),Month::integer(),Day::integer()},
+ {Hour::integer(),Minute::integer(),Second::integer()}}. %% In Local Timezone
+
+-type wx_wxMouseState() :: #wxMouseState{}. %% See #wxMouseState{} defined in wx.hrl
+-type wx_enum() :: integer(). %% Constant defined in wx.hrl
+-type wx_wxHtmlLinkInfo() :: #wxHtmlLinkInfo{}.
-%% @hidden
parent_class(_) -> true. %% Let the null pointers be sent down.
-%% @spec () -> wxObject()
%% @doc Starts a wx server.
+-spec new() -> wx_object().
new() ->
new([]).
-%% @spec ([Option]) -> wxObject()
-%% @doc Starts a wx server.
+%% @doc Starts a wx server.
%% Option may be {debug, Level}, see debug/1.
+-spec new([Option]) -> wx_object() when Option :: {debug, list() | atom()}.
new(Options) when is_list(Options) ->
#wx_env{port=Port} = wxe_server:start(),
put(opengl_port, Port),
@@ -102,130 +110,129 @@ new(Options) when is_list(Options) ->
debug(Debug),
null().
-%% @spec () -> ok
%% @doc Stops a wx server.
+-spec destroy() -> ok.
destroy() ->
wxe_server:stop(),
erase(?WXE_IDENTIFIER),
ok.
-%% @spec () -> wx_env()
%% @doc Gets this process's current wx environment.
%% Can be sent to other processes to allow them use this process wx environment.
%% @see set_env/1
+-spec get_env() -> wx_env().
get_env() ->
case get(?WXE_IDENTIFIER) of
undefined -> erlang:error({wxe,unknown_port});
Env = #wx_env{} -> Env
end.
-%% @spec (wx_env()) -> ok
%% @doc Sets the process wx environment, allows this process to use
%% another process wx environment.
+-spec set_env(wx_env()) -> ok.
set_env(#wx_env{sv=Pid, port=Port} = Env) ->
- put(?WXE_IDENTIFIER, Env),
+ put(?WXE_IDENTIFIER, Env),
put(opengl_port, Port),
%% wxe_util:cast(?REGISTER_PID, <<>>),
wxe_server:register_me(Pid),
ok.
-%% @spec () -> wxObject()
%% @doc Returns the null object
+-spec null() -> wx_object().
null() ->
#wx_ref{ref=0, type=wx}.
-%% @spec (wxObject()) -> boolean()
%% @doc Returns true if object is null, false otherwise
+-spec is_null(wx_object()) -> boolean().
is_null(#wx_ref{ref=NULL}) -> NULL =:= 0.
-%% @spec (wxObject()) -> atom()
%% @doc Returns the object type
+-spec getObjectType(wx_object()) -> atom().
getObjectType(#wx_ref{type=Type}) ->
Type.
-%% @spec (wxObject(), atom()) -> wxObject()
%% @doc Casts the object to class NewType.
-%% It is needed when using functions like wxWindow:findWindow/2, which
+%% It is needed when using functions like wxWindow:findWindow/2, which
%% returns a generic wxObject type.
+-spec typeCast(wx_object(), atom()) -> wx_object().
typeCast(Old=#wx_ref{}, NewType) when is_atom(NewType) ->
Old#wx_ref{type=NewType}.
-%% @spec (function()) -> term()
%% @doc Batches all <c>wx</c> commands
%% used in the fun. Improves performance of the command processing by
%% grabbing the wxWidgets thread so that no event processing will be
%% done before the complete batch of commands is invoked.
-%%
+%%
%% @see map/2
%% @see foreach/2
%% @see foldl/3
%% @see foldr/3
+-spec batch(function()) -> term().
batch(Fun) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try Fun()
- catch
+ catch
error:W -> erlang:exit({W, erlang:get_stacktrace()});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
- after
+ after
ok = wxe_util:cast(?BATCH_END, <<>>)
end.
-%% @spec (function(), list()) -> ok
-%% @doc Behaves like {@link //stdlib/lists:foreach/2} but batches wx commands. See {@link batch/1}.
+%% @doc Behaves like {@link //stdlib/lists:foreach/2} but batches wx commands. See {@link batch/1}.
+-spec foreach(function(), list()) -> ok.
foreach(Fun, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:foreach(Fun, List)
- catch
+ catch
error:W -> erlang:exit({W, erlang:get_stacktrace()});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
- after
+ after
ok = wxe_util:cast(?BATCH_END, <<>>)
end.
-%% @spec (function(), list()) -> list()
-%% @doc Behaves like {@link //stdlib/lists:map/2} but batches wx commands. See {@link batch/1}.
+%% @doc Behaves like {@link //stdlib/lists:map/2} but batches wx commands. See {@link batch/1}.
+-spec map(function(), list()) -> list().
map(Fun, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:map(Fun, List)
- catch
+ catch
error:W -> erlang:exit({W, erlang:get_stacktrace()});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
- after
+ after
ok = wxe_util:cast(?BATCH_END, <<>>)
end.
-%% @spec (function(), term(), list()) -> term()
-%% @doc Behaves like {@link //stdlib/lists:foldl/3} but batches wx commands. See {@link batch/1}.
+%% @doc Behaves like {@link //stdlib/lists:foldl/3} but batches wx commands. See {@link batch/1}.
+-spec foldl(function(), term(), list()) -> term().
foldl(Fun, Acc, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:foldl(Fun, Acc, List)
- catch
+ catch
error:W -> erlang:exit({W, erlang:get_stacktrace()});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
- after
+ after
ok = wxe_util:cast(?BATCH_END, <<>>)
end.
-%% @spec (function(), term(), list()) -> term()
-%% @doc Behaves like {@link //stdlib/lists:foldr/3} but batches wx commands. See {@link batch/1}.
+%% @doc Behaves like {@link //stdlib/lists:foldr/3} but batches wx commands. See {@link batch/1}.
+-spec foldr(function(), term(), list()) -> term().
foldr(Fun, Acc, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:foldr(Fun, Acc, List)
- catch
+ catch
error:W -> erlang:exit({W, erlang:get_stacktrace()});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
- after
+ after
ok = wxe_util:cast(?BATCH_END, <<>>)
end.
-define(MIN_BIN_SIZE, 64). %% Current emulator min off heap size
-%% @spec (integer()) -> wx_memory()
%% @doc Creates a memory area (of Size in bytes) which can be used by an external library (i.e. opengl).
%% It is up to the client to keep a reference to this object so it does
%% not get garbage collected by erlang while still in use by the external
@@ -233,22 +240,23 @@ foldr(Fun, Acc, List) ->
%%
%% This is far from erlang's intentional usage and can crash the erlang emulator.
%% Use it carefully.
+-spec create_memory(integer()) -> wx_memory().
create_memory(Size) when Size > ?MIN_BIN_SIZE ->
#wx_mem{bin = <<0:(Size*8)>>, size = Size};
create_memory(Size) ->
#wx_mem{bin = <<0:((?MIN_BIN_SIZE+1)*8)>>, size = Size}.
-%% @spec (wx_memory()) -> binary()
%% @doc Returns the memory area as a binary.
+-spec get_memory_bin(wx_memory()) -> binary().
get_memory_bin(#wx_mem{bin=Bin, size=Size}) when Size > ?MIN_BIN_SIZE ->
Bin;
get_memory_bin(#wx_mem{bin=Bin, size=Size}) ->
<<WithCorrectSize:Size/binary, _/binary>> = Bin,
WithCorrectSize.
-%% @spec (wx_memory()) -> ok
%% @doc Saves the memory from deletion until release_memory/1 is called.
%% If release_memory/1 is not called the memory will not be garbage collected.
+-spec retain_memory(wx_memory()) -> ok.
retain_memory(#wx_mem{bin=Bin}) ->
wxe_util:send_bin(Bin),
ok = wxe_util:cast(?WXE_BIN_INCR, <<>>);
@@ -260,30 +268,29 @@ retain_memory(Bin) when is_binary(Bin) ->
wxe_util:send_bin(Bin),
ok = wxe_util:cast(?WXE_BIN_INCR, <<>>).
+-spec release_memory(wx_memory()) -> ok.
release_memory(#wx_mem{bin=Bin}) ->
wxe_util:send_bin(Bin),
ok = wxe_util:cast(?WXE_BIN_DECR, <<>>);
release_memory(Bin) when is_binary(Bin) ->
wxe_util:send_bin(Bin),
ok = wxe_util:cast(?WXE_BIN_DECR, <<>>).
-
-
-
-%% @spec (Level::term()) -> ok
-%% Level = none | verbose | trace | driver | [Level]
-%% @doc Sets debug level. If debug level is verbose or trace
-%% each call is printed on console. If Level is driver each allocated
+%% @doc Sets debug level. If debug level is 'verbose' or 'trace'
+%% each call is printed on console. If Level is 'driver' each allocated
%% object and deletion is printed on the console.
+-spec debug(Level | [Level]) -> ok
+ when Level :: none | verbose | trace | driver | integer().
+
debug(none) -> debug(0);
debug(verbose) -> debug(1);
debug(trace) -> debug(2);
debug(driver) -> debug(16);
debug([]) -> debug(0);
-debug(List) when is_list(List) ->
- {Drv,Erl} =
- lists:foldl(fun(verbose, {Drv,_Erl}) ->
+debug(List) when is_list(List) ->
+ {Drv,Erl} =
+ lists:foldl(fun(verbose, {Drv,_Erl}) ->
{Drv,1};
(trace, {Drv,_Erl}) ->
{Drv,2};
@@ -295,28 +302,29 @@ debug(Level) when is_integer(Level) ->
case get(?WXE_IDENTIFIER) of
undefined -> erlang:error({wxe,unknown_port});
#wx_env{debug=Old} when Old =:= Level -> ok;
- Env = #wx_env{sv=Server, port=Port, debug=Old} ->
- if
+ Env = #wx_env{sv=Server, port=Port, debug=Old} ->
+ if
Old > 16, Level > 16 -> ok;
Old < 16, Level < 16 -> ok;
true ->
erlang:port_call(Port,?WXE_DEBUG_DRIVER, [Level bsr 4])
- end,
+ end,
put(?WXE_IDENTIFIER, Env#wx_env{debug=Level}),
wxe_server:set_debug(Server,Level),
ok
end.
-%% @spec () -> ok
%% @doc Starts a wxErlang demo if examples directory exists and is compiled
+-spec demo() -> ok | {error, atom()}.
demo() ->
Priv = code:priv_dir(wx),
Demo = filename:join([filename:dirname(Priv),examples,demo]),
Mod = list_to_atom("demo"), %% Fool xref tests
case file:set_cwd(Demo) of
- ok ->
- apply(Mod, start, []);
+ ok ->
+ apply(Mod, start, []),
+ ok;
_ ->
{error, no_demo_dir}
end.
-
+
diff --git a/lib/wx/src/wx_object.erl b/lib/wx/src/wx_object.erl
index 82c4cfbad5..80f8937656 100644
--- a/lib/wx/src/wx_object.erl
+++ b/lib/wx/src/wx_object.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
@@ -108,7 +108,38 @@
get_pid/1
]).
--export([behaviour_info/1]).
+%% -export([behaviour_info/1]).
+-callback init(Args :: term()) ->
+ {#wx_ref{}, State :: term()} | {#wx_ref{}, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_event(Request :: #wx{}, State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+-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()} | {error, Reason :: term()}.
+
%% System exports
-export([system_continue/3,
@@ -125,15 +156,15 @@
%%% API
%%%=========================================================================
%% @hidden
-behaviour_info(callbacks) ->
- [{init,1},
- {handle_call,3},
- {handle_info,2},
- {handle_event,2},
- {terminate,2},
- {code_change,3}];
-behaviour_info(_Other) ->
- undefined.
+%% behaviour_info(callbacks) ->
+%% [{init,1},
+%% {handle_call,3},
+%% {handle_info,2},
+%% {handle_event,2},
+%% {terminate,2},
+%% {code_change,3}];
+%% behaviour_info(_Other) ->
+%% undefined.
%% -----------------------------------------------------------------
@@ -226,9 +257,11 @@ call(Name, Request, Timeout) when is_atom(Name) orelse is_pid(Name) ->
%% Invokes handle_cast(Request, State) in the server
cast(#wx_ref{state=Pid}, Request) when is_pid(Pid) ->
- Pid ! {'$gen_cast',Request};
+ Pid ! {'$gen_cast',Request},
+ ok;
cast(Name, Request) when is_atom(Name) orelse is_pid(Name) ->
- Name ! {'$gen_cast',Request}.
+ Name ! {'$gen_cast',Request},
+ ok.
%% @spec (Ref::wxObject()) -> pid()
%% @doc Get the pid of the object handle.
@@ -258,9 +291,10 @@ init_it(Starter, self, Name, Mod, Args, Options) ->
init_it(Starter, self(), Name, Mod, Args, Options);
init_it(Starter, Parent, Name, Mod, Args, [WxEnv|Options]) ->
case WxEnv of
- undefined -> ok;
+ undefined -> ok;
_ -> wx:set_env(WxEnv)
end,
+ put('_wx_object_', {Mod,'_wx_init_'}),
Debug = debug_options(Name, Options),
case catch Mod:init(Args) of
{#wx_ref{} = Ref, State} ->
@@ -350,57 +384,16 @@ handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod) ->
{noreply, NState, Time1} ->
loop(Parent, Name, NState, Mod, Time1, []);
{stop, Reason, Reply, NState} ->
- {'EXIT', R} =
+ {'EXIT', R} =
(catch terminate(Reason, Name, Msg, Mod, NState, [])),
reply(From, Reply),
exit(R);
Other -> handle_common_reply(Other, Name, Msg, Mod, State, [])
end;
-
-handle_msg(Msg = {_,_,'_wx_invoke_cb_'}, Parent, Name, State, Mod) ->
- Reply = dispatch_cb(Msg, Mod, State),
- handle_no_reply(Reply, Parent, Name, Msg, Mod, State, []);
handle_msg(Msg, Parent, Name, State, Mod) ->
Reply = (catch dispatch(Msg, Mod, State)),
handle_no_reply(Reply, Parent, Name, Msg, Mod, State, []).
-%% @hidden
-dispatch_cb({{Msg=#wx{}, Obj=#wx_ref{}}, _, '_wx_invoke_cb_'}, Mod, State) ->
- Callback = fun() ->
- wxe_util:cast(?WXE_CB_START, <<>>),
- case Mod:handle_sync_event(Msg, Obj, State) of
- ok -> <<>>;
- noreply -> <<>>;
- Other ->
- Args = [Msg, Obj, State],
- MFA = {Mod, handle_sync_event, Args},
- exit({bad_return, Other, MFA})
- end
- end,
- wxe_server:invoke_callback(Callback),
- {noreply, State};
-dispatch_cb({Func, ArgList, '_wx_invoke_cb_'}, Mod, State) ->
- try %% This don't work yet....
- [#wx_ref{type=ThisClass}] = ArgList,
- case Mod:handle_overloaded(Func, ArgList, State) of
- {reply, CBReply, NState} ->
- ThisClass:send_return_value(Func, CBReply),
- {noreply, NState};
- {reply, CBReply, NState, Time1} ->
- ThisClass:send_return_value(Func, CBReply),
- {noreply, NState, Time1};
- {noreply, NState} ->
- ThisClass:send_return_value(Func, <<>>),
- {noreply, NState};
- {noreply, NState, Time1} ->
- ThisClass:send_return_value(Func, <<>>),
- {noreply, NState, Time1};
- Other -> Other
- end
- catch _Err:Reason ->
- %% Hopefully we can release the wx-thread with this
- wxe_util:cast(?WXE_CB_RETURN, <<>>),
- {'EXIT', {Reason, erlang:get_stacktrace()}}
- end.
+
%% @hidden
handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod, Debug) ->
case catch Mod:handle_call(Msg, From, State) of
@@ -426,9 +419,6 @@ handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod, Debug) ->
Other ->
handle_common_reply(Other, Name, Msg, Mod, State, Debug)
end;
-handle_msg(Msg = {_,_,'_wx_invoke_cb_'}, Parent, Name, State, Mod, Debug) ->
- Reply = dispatch_cb(Msg, Mod, State),
- handle_no_reply(Reply, Parent, Name, Msg, Mod, State, Debug);
handle_msg(Msg, Parent, Name, State, Mod, Debug) ->
Reply = (catch dispatch(Msg, Mod, State)),
handle_no_reply(Reply, Parent, Name, Msg, Mod, State, Debug).
diff --git a/lib/wx/src/wxe_master.erl b/lib/wx/src/wxe_master.erl
index 9efe59054c..ac6e4a56e6 100644
--- a/lib/wx/src/wxe_master.erl
+++ b/lib/wx/src/wxe_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -100,17 +100,10 @@ init([]) ->
case catch erlang:system_info(smp_support) of
true -> ok;
_ ->
- error_logger:format("WX ERROR: SMP emulator required", []),
+ error_logger:format("WX ERROR: SMP emulator required (start with erl -smp)", []),
erlang:error(not_smp)
end,
- case catch (erlang:system_info(version) >= "5.6.2") of
- true -> ok;
- _ -> %% Needs to be able to disable FPU exceptions.
- error_logger:format("WX ERROR: OTP R12B-2 or Emulator >= 5.6.2 required", []),
- erlang:error(wrong_version)
- end,
- %% io:format("Loading ~p @ ~p ~n", [DriverName,PrivDir]),
case os:type() of
{win32,_} -> %% Needed for mingwm10.dll
Path = os:getenv("PATH"),
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index 69e2189fac..6e982c97f6 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -221,7 +221,7 @@ handle_connect(Object, EvData, From, State0 = #state{users=Users}) ->
Evs = [#event{object=Object,callback=Callback, cb_handler=CBHandler}|Evs0],
User = User0#user{events=Evs, evt_handler=Handler},
State1 = State0#state{users=gb_trees:update(From, User, Users)},
- if is_function(Callback) ->
+ if is_function(Callback) orelse is_pid(Callback) ->
{FunId, State} = attach_fun(Callback,State1),
Res = wxEvtHandler:connect_impl(CBHandler,Object,
wxEvtHandler:replace_fun_with_id(EvData,FunId)),
@@ -229,6 +229,7 @@ handle_connect(Object, EvData, From, State0 = #state{users=Users}) ->
ok -> {reply,Res,State};
_Error -> {reply,Res,State0}
end;
+
true ->
Res = {call_impl, connect_cb, CBHandler},
{reply, Res, State1}
@@ -239,6 +240,8 @@ invoke_cb({{Ev=#wx{}, Ref=#wx_ref{}}, FunId,_}, _S) ->
case get(FunId) of
Fun when is_function(Fun) ->
invoke_callback(fun() -> Fun(Ev, Ref), <<>> end);
+ Pid when is_pid(Pid) -> %% wx_object sync event
+ invoke_callback(Pid, Ev, Ref);
Err ->
?log("Internal Error ~p~n",[Err])
end;
@@ -270,6 +273,44 @@ invoke_callback(Fun) ->
spawn(CB),
ok.
+invoke_callback(Pid, Ev, Ref) ->
+ Env = get(?WXE_IDENTIFIER),
+ CB = fun() ->
+ wx:set_env(Env),
+ wxe_util:cast(?WXE_CB_START, <<>>),
+ try
+ case get_wx_object_state(Pid) of
+ ignore ->
+ %% Ignore early events
+ wxEvent:skip(Ref);
+ {Mod, State} ->
+ case Mod:handle_sync_event(Ev, Ref, State) of
+ ok -> ok;
+ noreply -> ok;
+ Return -> exit({bad_return, Return})
+ end
+ end
+ catch _:Reason ->
+ wxEvent:skip(Ref),
+ ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n",
+ [Reason, erlang:get_stacktrace()])
+ end,
+ wxe_util:cast(?WXE_CB_RETURN, <<>>)
+ end,
+ spawn(CB),
+ ok.
+
+get_wx_object_state(Pid) ->
+ case process_info(Pid, dictionary) of
+ {dictionary, Dict} ->
+ case lists:keysearch('_wx_object_',1,Dict) of
+ {value, {'_wx_object_', {_Mod, '_wx_init_'}}} -> ignore;
+ {value, {'_wx_object_', Value}} -> Value;
+ _ -> ignore
+ end;
+ _ -> ignore
+ end.
+
new_evt_listener(State) ->
#wx_env{port=Port} = wx:get_env(),
_ = erlang:port_control(Port,98,<<>>),
diff --git a/lib/wx/test/Makefile b/lib/wx/test/Makefile
index cf51d7918f..836885a308 100644
--- a/lib/wx/test/Makefile
+++ b/lib/wx/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2011. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. All Rights Reserved.
#
# The 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,7 @@ PWD = $(shell pwd)
APPDIR = $(shell dirname $(PWD))
ERL_COMPILE_FLAGS = -pa $(APPDIR)/ebin
-Mods = wxt wx_test_lib \
+Mods = wxt wx_test_lib wx_obj_test \
wx_app_SUITE \
wx_basic_SUITE \
wx_event_SUITE \
@@ -48,23 +48,13 @@ clean:
docs:
-
-# Rules
-ifneq ($(INSIDE_ERLSRC),true)
-
-$(EBIN)/%.beam: $(ESRC)/%.erl
- $(ERLC) -W -bbeam $(ERL_FLAGS) $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
-
-else
RELSYSDIR = $(RELEASE_PATH)/wx_test
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
release_tests_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) wx.spec wx.cover wx_test_lib.hrl $(ErlSrc) $(ErlTargets) $(RELSYSDIR)
- $(INSTALL_SCRIPT) wxt $(RELSYSDIR)
+ $(INSTALL_DIR) "$(RELSYSDIR)"
+ $(INSTALL_DATA) wx.spec wx.cover wx_test_lib.hrl $(ErlSrc) $(ErlTargets) "$(RELSYSDIR)"
+ $(INSTALL_SCRIPT) wxt "$(RELSYSDIR)"
release_docs_spec:
-
-endif
diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl
index 9ad34248a9..46c72bb453 100644
--- a/lib/wx/test/wx_basic_SUITE.erl
+++ b/lib/wx/test/wx_basic_SUITE.erl
@@ -48,7 +48,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[create_window, several_apps, wx_api, wx_misc,
- data_types].
+ data_types, wx_object].
groups() ->
[].
@@ -298,3 +298,77 @@ data_types(_Config) ->
wxClientDC:destroy(CDC),
%%wx_test_lib:wx_destroy(Frame,Config).
wx:destroy().
+
+wx_object(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+wx_object(Config) ->
+ wx:new(),
+ Frame = ?mt(wxFrame, wx_obj_test:start([])),
+ timer:sleep(500),
+ ?m(ok, check_events(flush())),
+
+ Me = self(),
+ ?m({call, foobar, {Me, _}}, wx_object:call(Frame, foobar)),
+ ?m(ok, wx_object:cast(Frame, foobar2)),
+ ?m([{cast, foobar2}], flush()),
+ FramePid = wx_object:get_pid(Frame),
+ io:format("wx_object pid ~p~n",[FramePid]),
+ FramePid ! foo3,
+ ?m([{info, foo3}], flush()),
+
+ ?m(ok, wx_object:cast(Frame, fun(_) -> hehe end)),
+ ?m([{cast, hehe}], flush()),
+ wxWindow:refresh(Frame),
+ ?m([{sync_event, #wx{event=#wxPaint{}}, _}], flush()),
+ ?m(ok, wx_object:cast(Frame, fun(_) -> timer:sleep(200), slept end)),
+ %% The sleep above should not hinder the Paint event below
+ %% Which it did in my buggy handling of the sync_callback
+ wxWindow:refresh(Frame),
+ ?m([{sync_event, #wx{event=#wxPaint{}}, _}], flush()),
+ ?m([{cast, slept}], flush()),
+
+ Monitor = erlang:monitor(process, FramePid),
+ case proplists:get_value(user, Config, false) of
+ false ->
+ timer:sleep(100),
+ wxFrame:destroy(Frame);
+ true ->
+ timer:sleep(500),
+ ?m(ok, wxFrame:destroy(Frame));
+ _ ->
+ ?m(ok, wxEvtHandler:connect(Frame, close_window, [{skip,true}])),
+ wx_test_lib:wait_for_close()
+ end,
+ ?m(ok, receive
+ {'DOWN', Monitor, _, _, _} ->
+ ?m([{terminate, wx_deleted}], flush()),
+ ok
+ after 1000 ->
+ Msgs = flush(),
+ io:format("Error ~p Alive ~p~n",[Msgs, is_process_alive(FramePid)])
+ end),
+ catch wx:destroy(),
+ ok.
+
+check_events(Msgs) ->
+ check_events(Msgs, 0,0).
+
+check_events([{event, #wx{event=#wxSize{}}}|Rest], Async, Sync) ->
+ check_events(Rest, Async+1, Sync);
+check_events([{sync_event, #wx{event=#wxPaint{}}, Obj}|Rest], Async, Sync) ->
+ ?mt(wxPaintEvent, Obj),
+ check_events(Rest, Async, Sync+1);
+check_events([], Async, Sync) ->
+ case Async > 0 of %% Test sync explictly
+ true -> ok;
+ false -> {Async, Sync}
+ end.
+
+flush() ->
+ flush([], 500).
+
+flush(Acc, Wait) ->
+ receive
+ Msg -> flush([Msg|Acc], Wait div 10)
+ after Wait ->
+ lists:reverse(Acc)
+ end.
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index b75b0cc74e..6ed7243c5b 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[calendarCtrl, treeCtrl, notebook, staticBoxSizer,
clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual,
- radioBox, systemSettings].
+ radioBox, systemSettings, taskBarIcon].
groups() ->
[].
@@ -470,3 +470,15 @@ textCtrl(Config) ->
wxTextAttr:destroy(Attr),
wxWindow:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
+
+taskBarIcon(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+taskBarIcon(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
+ TBI = wxTaskBarIcon:new(),
+ Icon = wxIcon:new(filename:join(code:priv_dir(debugger), "erlang_bug.png")),
+ wxTaskBarIcon:setIcon(TBI, Icon, [{tooltip, "Testing wxTaskBarIcon"}]),
+ wxWindow:show(Frame),
+ wxTaskBarIcon:connect(TBI, taskbar_left_down, [{callback, fun(Ev,_) -> io:format("Left clicked: ~p~n",[Ev]) end}]),
+ wxTaskBarIcon:connect(TBI, taskbar_right_down, [{callback,fun(Ev,_) -> io:format("Right clicked: ~p~n",[Ev]) end}]),
+ wx_test_lib:wx_destroy(Frame,Config).
diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl
index 0d8dd4852e..8f364049b4 100644
--- a/lib/wx/test/wx_event_SUITE.erl
+++ b/lib/wx/test/wx_event_SUITE.erl
@@ -47,7 +47,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[connect, disconnect, connect_msg_20, connect_cb_20,
- mouse_on_grid, spin_event, connect_in_callback].
+ mouse_on_grid, spin_event, connect_in_callback, recursive].
groups() ->
[].
@@ -331,3 +331,35 @@ connect_in_callback(Config) ->
wx_test_lib:flush(),
wx_test_lib:wx_destroy(Frame, Config).
+
+%% Test that event callback which triggers another callback works
+%% i.e. the callback invoker in driver will recurse
+recursive(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+recursive(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Connect in callback"),
+ Panel = wxPanel:new(Frame, []),
+ Sz = wxBoxSizer:new(?wxVERTICAL),
+ ListBox = wxListBox:new(Panel, ?wxID_ANY, [{choices, ["foo", "bar", "baz"]}]),
+ wxSizer:add(Sz, ListBox, [{proportion, 1},{flag, ?wxEXPAND}]),
+ wxWindow:setSizer(Panel, Sz),
+ wxListBox:connect(ListBox, command_listbox_selected,
+ [{callback,
+ fun(#wx{event=#wxCommand{commandInt=Id}}, _) ->
+ io:format("Selected ~p~n",[Id])
+ end}]),
+ wxListBox:setSelection(ListBox, 0),
+ wxListBox:connect(ListBox, size,
+ [{callback,
+ fun(#wx{event=#wxSize{}}, _) ->
+ io:format("Size init ~n",[]),
+ case wxListBox:getCount(ListBox) > 0 of
+ true -> wxListBox:delete(ListBox, 0);
+ false -> ok
+ end,
+ io:format("Size done ~n",[])
+ end}]),
+ wxFrame:show(Frame),
+ wx_test_lib:flush(),
+
+ wx_test_lib:wx_destroy(Frame, Config).
diff --git a/lib/wx/test/wx_obj_test.erl b/lib/wx/test/wx_obj_test.erl
new file mode 100644
index 0000000000..b4d7640c7e
--- /dev/null
+++ b/lib/wx/test/wx_obj_test.erl
@@ -0,0 +1,86 @@
+%%
+%% %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(wx_obj_test).
+-include_lib("wx/include/wx.hrl").
+
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
+ handle_sync_event/3, handle_event/2, handle_cast/2]).
+
+-record(state, {frame, panel, opts}).
+
+start(Opts) ->
+ wx_object:start_link(?MODULE, [{parent, self()}, Opts], []).
+
+init(Opts) ->
+ put(parent_pid, proplists:get_value(parent, Opts)),
+ Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Test wx_object", [{size, {500, 400}}]),
+ Sz = wxBoxSizer:new(?wxHORIZONTAL),
+ Panel = wxPanel:new(Frame),
+ wxSizer:add(Sz, Panel, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxPanel:connect(Panel, size, [{skip, true}]),
+ wxPanel:connect(Panel, paint, [callback, {userData, proplists:get_value(parent, Opts)}]),
+ wxWindow:show(Frame),
+ {Frame, #state{frame=Frame, panel=Panel, opts=Opts}}.
+
+handle_sync_event(Event = #wx{obj=Panel}, WxEvent, #state{opts=Opts}) ->
+ DC=wxPaintDC:new(Panel), %% We must create & destroy paintDC, or call wxEvent:skip(WxEvent))
+ wxPaintDC:destroy(DC), %% in sync_event. Otherwise wx on windows keeps sending the events.
+ Pid = proplists:get_value(parent, Opts),
+ true = is_pid(Pid),
+ Pid ! {sync_event, Event, WxEvent},
+ ok.
+
+handle_event(Event, State = #state{opts=Opts}) ->
+ Pid = proplists:get_value(parent, Opts),
+ Pid ! {event, Event},
+ {noreply, State}.
+
+handle_call(What, From, State) when is_function(What) ->
+ Result = What(State),
+ {reply, {call, Result, From}, State};
+handle_call(What, From, State) ->
+ {reply, {call, What, From}, State}.
+
+handle_cast(What, State = #state{opts=Opts}) when is_function(What) ->
+ Result = What(State),
+ Pid = proplists:get_value(parent, Opts),
+ Pid ! {cast, Result},
+ {noreply, State};
+
+handle_cast(What, State = #state{opts=Opts}) ->
+ Pid = proplists:get_value(parent, Opts),
+ Pid ! {cast, What},
+ {noreply, State}.
+
+handle_info(What, State = #state{opts=Opts}) ->
+ Pid = proplists:get_value(parent, Opts),
+ Pid ! {info, What},
+ {noreply, State}.
+
+terminate(What, #state{opts=Opts}) ->
+ Pid = proplists:get_value(parent, Opts),
+ Pid ! {terminate, What},
+ ok.
+
+code_change(Ver1, Ver2, State = #state{opts=Opts}) ->
+ Pid = proplists:get_value(parent, Opts),
+ Pid ! {code_change, Ver1, Ver2},
+ State.
diff --git a/lib/wx/test/wx_test_lib.hrl b/lib/wx/test/wx_test_lib.hrl
index 34e1e9c6b8..820e8f0050 100644
--- a/lib/wx/test/wx_test_lib.hrl
+++ b/lib/wx/test/wx_test_lib.hrl
@@ -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
@@ -40,7 +40,6 @@
-define(m(ExpectedRes, Expr),
fun() ->
- {TeStFILe, TeSTLiNe} = {?FILE, ?LINE},
AcTuAlReS = (catch (Expr)),
case AcTuAlReS of
ExpectedRes ->
@@ -48,8 +47,8 @@
AcTuAlReS;
_ ->
wx_test_lib:error("Not Matching Actual result was:~n ~p ~n Expected ~s~n",
- [AcTuAlReS, ??ExpectedRes],
- TeStFILe,TeSTLiNe),
+ [AcTuAlReS, ??ExpectedRes],
+ ?FILE,?LINE),
AcTuAlReS
end
end()).
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 8685c633d4..719eb0daf0 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 0.99
+WX_VSN = 0.99.2
diff --git a/lib/xmerl/doc/examples/test_html.erl b/lib/xmerl/doc/examples/test_html.erl
index 3ca15f30f8..3ca15f30f8 100755..100644
--- a/lib/xmerl/doc/examples/test_html.erl
+++ b/lib/xmerl/doc/examples/test_html.erl
diff --git a/lib/xmerl/doc/examples/xml/test.xml b/lib/xmerl/doc/examples/xml/test.xml
index e803a83560..e803a83560 100755..100644
--- a/lib/xmerl/doc/examples/xml/test.xml
+++ b/lib/xmerl/doc/examples/xml/test.xml
diff --git a/lib/xmerl/doc/examples/xml/test2.xml b/lib/xmerl/doc/examples/xml/test2.xml
index 0cb11194fc..0cb11194fc 100755..100644
--- a/lib/xmerl/doc/examples/xml/test2.xml
+++ b/lib/xmerl/doc/examples/xml/test2.xml
diff --git a/lib/xmerl/doc/examples/xml/test3.xml b/lib/xmerl/doc/examples/xml/test3.xml
index dbdc1e62c2..dbdc1e62c2 100755..100644
--- a/lib/xmerl/doc/examples/xml/test3.xml
+++ b/lib/xmerl/doc/examples/xml/test3.xml
diff --git a/lib/xmerl/doc/examples/xml/test4.xml b/lib/xmerl/doc/examples/xml/test4.xml
index e9d85b8d8f..e9d85b8d8f 100755..100644
--- a/lib/xmerl/doc/examples/xml/test4.xml
+++ b/lib/xmerl/doc/examples/xml/test4.xml
diff --git a/lib/xmerl/doc/examples/xml/test5.xml b/lib/xmerl/doc/examples/xml/test5.xml
index e9d85b8d8f..e9d85b8d8f 100755..100644
--- a/lib/xmerl/doc/examples/xml/test5.xml
+++ b/lib/xmerl/doc/examples/xml/test5.xml
diff --git a/lib/xmerl/doc/examples/xml/testdtd.dtd b/lib/xmerl/doc/examples/xml/testdtd.dtd
index 2ce1c513a6..2ce1c513a6 100755..100644
--- a/lib/xmerl/doc/examples/xml/testdtd.dtd
+++ b/lib/xmerl/doc/examples/xml/testdtd.dtd
diff --git a/lib/xmerl/doc/examples/xml/xmerl.xml b/lib/xmerl/doc/examples/xml/xmerl.xml
index f02282dbef..f02282dbef 100755..100644
--- a/lib/xmerl/doc/examples/xml/xmerl.xml
+++ b/lib/xmerl/doc/examples/xml/xmerl.xml
diff --git a/lib/xmerl/doc/src/Makefile b/lib/xmerl/doc/src/Makefile
index 100a2feb0a..4de06249df 100644
--- a/lib/xmerl/doc/src/Makefile
+++ b/lib/xmerl/doc/src/Makefile
@@ -161,15 +161,15 @@ info:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
- $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(HTMLDIR)/* \
- $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(HTML_EXAMPLE_FILES) $(HTML_STYLESHEET_FILES) $(RELSYSDIR)/doc/html
- $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
- $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(EXAMPLE_FILES) $(HTML_EXAMPLE_FILES) $(HTML_STYLESHEET_FILES) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
diff --git a/lib/xmerl/doc/src/make.dep b/lib/xmerl/doc/src/make.dep
deleted file mode 100644
index 9c303fc41c..0000000000
--- a/lib/xmerl/doc/src/make.dep
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex ref_man.tex xmerl.tex xmerl_eventp.tex \
- xmerl_scan.tex xmerl_ug.tex xmerl_xpath.tex \
- xmerl_xs.tex xmerl_xsd.tex xmerl_sax_parser.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-book.tex: ref_man.xml
-
-xmerl_ug.tex: motorcycles.txt motorcycles2html.erl motorcycles_dtd.txt \
- new_motorcycles.txt new_motorcycles2.txt
-
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 15c42d6f6a..bd12e688d0 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -31,6 +31,175 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a continuation bug when a new block of bytes is
+ to be read during parsing of a default declaration. </p>
+ <p>
+ Own Id: OTP-10063 Aux Id: seq12049 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add missing spaces in xmerl doc (Thanks to Ricardo
+ Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9873</p>
+ </item>
+ <item>
+ <p> Fixed a continuation error in the sax parser and
+ added latin1 as recognized encoding (not only the
+ iso-8859 variants). </p>
+ <p>
+ Own Id: OTP-9961</p>
+ </item>
+ <item>
+ <p> Removed the unused file xmerl_xlink.hrl. Thanks to
+ Vlad Dumitrescu for informing us about it. </p>
+ <p>
+ Own Id: OTP-9965</p>
+ </item>
+ <item>
+ <p> xmerl couldn't handle comments inside a type
+ specification. </p>
+ <p>
+ Own Id: OTP-10023</p>
+ </item>
+ <item>
+ <p> Fix some small errors in the sax parser: error
+ message bug, removal of trailing blanks in DTD element
+ definitions and an documentation error of the startDTD
+ event in xmerl_sax_parser module. </p>
+ <p>
+ Own Id: OTP-10026</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix character check of non-characters due to change
+ in unicode module. </p>
+ <p>
+ Own Id: OTP-9670</p>
+ </item>
+ <item>
+ <p>
+ Treat , as special in xmerl_xpath_scan. (Thanks to Anneli
+ Cuss)</p>
+ <p>
+ Own Id: OTP-9753</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in namespace handling for attributes when the
+ <c>namespace_conformant</c> flag is set to true. </p>
+ <p>
+ Own Id: OTP-9821</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Updates to the xml scanner </p> <list> <item>
+ <p>xmerl_scan is now returning xmlComment records in the
+ output.<br/><br/> Functions <c>xmerl_scan:file/2</c> and
+ <c>xmerl_scan:string/2</c> now accepts a new option
+ <c>{comments, Flag}</c> for filtering of comments.<br/>
+ Default (<c>true</c>) is that <c>#xmlComment</c> records
+ are returned from the scanner and this flag should be set
+ to false if one don't want comments in the output. </p>
+ </item> <item> <p>Add <i>default_attrs</i>
+ option<br/><br/> When <i>default_attrs</i> is <c>true</c>
+ any attribute with a default value defined in the doctype
+ but not in the attribute axis of the currently scanned
+ element is added to it. </p> </item> <item> <p>Allow
+ whole documents to be returned<br/><br/> Functions
+ <c>xmerl_scan:file/2</c> and <c>xmerl_scan:string/2</c>
+ now accepts a new option <c>{document, true}</c> to
+ produce a whole document as a <c>xmlDocument</c> record
+ instead of just the root element node.<br/> This option
+ is the only way to get to the top-level comments and
+ processing instructions without hooking through the
+ customization functions. Those nodes are needed to
+ implement [Canonical XML][c14n-xml] support.<br/>
+ [c14n-xml]:
+ http://www.w3.org/TR/2008/PR-xml-c14n11-20080129/
+ <i>Canonical XML</i> </p> </item> <item><p>Parents and
+ namespace are tracked in <c>#xmlAttribute</c>
+ nodes</p></item> <item><p>Parents are tracked in
+ <c>#xmlPI</c> nodes</p></item> <item><p>Set <c>vsn</c>
+ field in <c>#xmlDecl</c> record</p></item> <item><p>Fix
+ namespace-conformance constraints<br/><br/> See
+ [Namespaces in XML 1.0 (Third Edition)][1]: The prefix
+ xml is by definition bound to the namespace name
+ http://www.w3.org/XML/1998/namespace. It MAY, but need
+ not, be declared, and MUST NOT be bound to any other
+ namespace name. Other prefixes MUST NOT be bound to this
+ namespace name, and it MUST NOT be declared as the
+ default namespace.<br/> The prefix xmlns is used only to
+ declare namespace bindings and is by definition bound to
+ the namespace name http://www.w3.org/2000/xmlns/. It MUST
+ NOT be declared . Other prefixes MUST NOT be bound to
+ this namespace name, and it MUST NOT be declared as the
+ default namespace. Element names MUST NOT have the prefix
+ xmlns.<br/> In XML documents conforming to this
+ specification, no tag may contain two attributes which
+ have identical names, or have qualified names with the
+ same local part and with prefixes which have been bound
+ to namespace names that are identical.<br/> [1]
+ http://www.w3.org/TR/REC-xml-names/ </p></item> </list>
+ <p> Updates of xmerl's Xpath functionality. </p> <list>
+ <item><p>Add <c>#xmlPI</c> support to
+ xmerl_xpath:write_node/1</p></item> <item><p>Fix
+ processing-instruction(name?)</p></item> <item><p>Fix
+ path filters, support more top-level primary
+ expressions</p></item> <item><p>Accumulate comments in
+ element nodes</p></item> <item><p>Implement namespace
+ axis<br/><br/> Namespace nodes are represented as
+ <c>#xmlNsNode</c> records. Now that the namespace axis is
+ correctly implemented, attributes nodes corresponding to
+ attributes that declare namespaces are ignored.<br/> See
+ [5.3 Attribute Nodes][xpath-5.3]:<br/> There are no
+ attribute nodes corresponding to attributes that declare
+ namespaces.<br/> [xpath-5.3]:
+ http://www.w3.org/TR/xpath/#attribute-nodes </p></item>
+ </list> <p> (Thanks to Anthony Ramine) </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9664</p>
+ </item>
+ <item>
+ <p>
+ Eliminate use of deprecated regexp module</p>
+ <p>
+ Own Id: OTP-9810</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.2.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/doc/src/part_notes.xml b/lib/xmerl/doc/src/part_notes.xml
index 827ffd90e9..b3c0597323 100755..100644
--- a/lib/xmerl/doc/src/part_notes.xml
+++ b/lib/xmerl/doc/src/part_notes.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/xmerl/doc/src/xmerl_sax_parser.xml b/lib/xmerl/doc/src/xmerl_sax_parser.xml
index 972023622e..eb22711a75 100644
--- a/lib/xmerl/doc/src/xmerl_sax_parser.xml
+++ b/lib/xmerl/doc/src/xmerl_sax_parser.xml
@@ -206,10 +206,15 @@
Report the end of a CDATA section.
</item>
- <tag><c>startDTD</c></tag>
+ <tag><c>{startDTD, Name, PublicId, SystemId}</c></tag>
<item>
Report the start of DTD declarations, it's reporting the start of the DOCTYPE declaration.
If the document has no DOCTYPE declaration, this event will not be sent.
+ <list>
+ <item><c>Name = string()</c></item>
+ <item><c>PublicId = string()</c></item>
+ <item><c>SystemId = string()</c></item>
+ </list>
</item>
<tag><c>endDTD</c></tag>
diff --git a/lib/xmerl/doc/src/xmerl_ug.xmlsrc b/lib/xmerl/doc/src/xmerl_ug.xmlsrc
index 6ee6707e53..8a0805020e 100644
--- a/lib/xmerl/doc/src/xmerl_ug.xmlsrc
+++ b/lib/xmerl/doc/src/xmerl_ug.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,9 +36,9 @@
<title>Features</title>
<p>The <em>xmerl</em> XML parser is able to parse XML documents
according to the XML 1.0 standard. As default it performs
- well-formed parsing,(syntax checks and checks of well-formed
+ well-formed parsing, (syntax checks and checks of well-formed
constraints). Optionally one can also use xmerl as a validating
- parser,(validate according to referenced DTD and validating
+ parser, (validate according to referenced DTD and validating
constraints). By means of for example the xmerl_xs module it is
possible to transform the parsed result to other formats,
e.g. text, HTML, XML etc.</p>
diff --git a/lib/xmerl/include/xmerl.hrl b/lib/xmerl/include/xmerl.hrl
index 7bb3f4de9b..331d1507a0 100755..100644
--- a/lib/xmerl/include/xmerl.hrl
+++ b/lib/xmerl/include/xmerl.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
@@ -61,10 +61,11 @@
}).
%% namespace node - i.e. a {Prefix, URI} pair
-%% TODO: these are not currently used?? /RC
-record(xmlNsNode,{
- prefix,
- uri = []
+ parents = [], % [{atom(),integer()}]
+ pos, % integer()
+ prefix, % string()
+ uri = [] % [] | atom()
}).
%% XML Element
@@ -103,9 +104,10 @@
%% processing instruction
-record(xmlPI,{
- name, % atom()
- pos, % integer()
- value % IOlist()
+ name, % atom()
+ parents = [], % [{atom(),integer()}]
+ pos, % integer()
+ value % IOlist()
}).
-record(xmlDocument,{
@@ -154,6 +156,9 @@
declarations = [], % [{Name, Attrs}]
doctype_name,
doctype_DTD = internal, % internal | DTDId
+ comments = true,
+ document = false,
+ default_attrs = false,
rules,
keep_rules = false, % delete (ets) tab if false
namespace_conformant = false, % true | false
diff --git a/lib/xmerl/include/xmerl_xlink.hrl b/lib/xmerl/include/xmerl_xlink.hrl
deleted file mode 100755
index 375e244c23..0000000000
--- a/lib/xmerl/include/xmerl_xlink.hrl
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-%% The following is a brief summary of the element types (columns) on
-%% which the global attributes are allowed:
-%%
-%% simple extended locator arc resource title
-%% type X X X X X X
-%% href X X
-%% role X X X X
-%% title X X X X
-%% show X X X
-%% actuate X X X
-%% from X
-%% to X
-%%
--record(xlink, {
- type, % simple | extended | locator | arc | resource | title
- href,
- role
- title,
- show,
- actuate,
- from,
- to
- }).
diff --git a/lib/xmerl/include/xmerl_xsd.hrl b/lib/xmerl/include/xmerl_xsd.hrl
index 6dad7d8ff0..644cc2e433 100644
--- a/lib/xmerl/include/xmerl_xsd.hrl
+++ b/lib/xmerl/include/xmerl_xsd.hrl
@@ -184,7 +184,7 @@
%% allowed for a schema.
%% chain, represents a series of ordered objects, some of whom may be
%% optional.
-%% alterantive, a collection of objects of which only one is choosen.
+%% alterantive, a collection of objects of which only one is chosen.
-record(chain,{
content,
occurance={1,1}
diff --git a/lib/xmerl/src/Makefile b/lib/xmerl/src/Makefile
index 7009b50f6c..ce1aa11fba 100644
--- a/lib/xmerl/src/Makefile
+++ b/lib/xmerl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+# Copyright Ericsson AB 2003-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -94,7 +94,6 @@ MODULES = $(EDOC_MODULES) \
HRL_FILES = \
../include/xmerl.hrl \
- ../include/xmerl_xlink.hrl \
../include/xmerl_xpath.hrl \
../include/xmerl_xsd.hrl
@@ -215,14 +214,14 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(APP_SRC) $(APPUP_SRC) $(RELSYSDIR)/src
- $(INSTALL_DATA) xmerl_xpath_parse.yrl $(RELSYSDIR)/src
- $(INSTALL_DATA) xmerl_b64Bin.yrl $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(APP_SRC) $(APPUP_SRC) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) xmerl_xpath_parse.yrl "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) xmerl_b64Bin.yrl "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
release_docs_spec:
diff --git a/lib/xmerl/src/xmerl.erl b/lib/xmerl/src/xmerl.erl
index 2332517988..3249094e78 100644
--- a/lib/xmerl/src/xmerl.erl
+++ b/lib/xmerl/src/xmerl.erl
@@ -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
diff --git a/lib/xmerl/src/xmerl_lib.erl b/lib/xmerl/src/xmerl_lib.erl
index 6402f1cbeb..aeb821f411 100644
--- a/lib/xmerl/src/xmerl_lib.erl
+++ b/lib/xmerl/src/xmerl_lib.erl
@@ -160,8 +160,9 @@ expand_element(E = #xmlText{}, Pos, Parents, Norm) ->
E#xmlText{pos = Pos,
parents = Parents,
value = expand_text(E#xmlText.value, Norm)};
-expand_element(E = #xmlPI{}, Pos, _Parents, Norm) ->
+expand_element(E = #xmlPI{}, Pos, Parents, Norm) ->
E#xmlPI{pos = Pos,
+ parents = Parents,
value = expand_text(E#xmlPI.value, Norm)};
expand_element(E = #xmlComment{}, Pos, Parents, Norm) ->
E#xmlComment{pos = Pos,
diff --git a/lib/xmerl/src/xmerl_sax_parser.erl b/lib/xmerl/src/xmerl_sax_parser.erl
index 45e2a928ac..5c006aada2 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -217,7 +217,7 @@ check_encoding_option(E) when E==utf8; E=={utf16,little}; E=={utf16,big};
check_encoding_option(utf16) ->
{utf16,big};
check_encoding_option(E) ->
- {error, io_lib:format("Charcter set ~p not supported", [E])}.
+ {error, io_lib:format("Character set ~p not supported", [E])}.
%%----------------------------------------------------------------------
%% Function: detect_charset(Xml, State)
@@ -279,6 +279,7 @@ convert_encoding(Enc) -> %% Just for 7,8 bit + utf8
case string:to_lower(Enc) of
"utf-8" -> utf8;
"us-ascii" -> utf8;
+ "latin1" -> latin1;
"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_sax_parser_base.erlsrc b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
index 3b9eaa309c..d38045f2a5 100644
--- a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
+++ b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
@@ -1,7 +1,7 @@
%%-*-erlang-*-
%% %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
@@ -39,6 +39,9 @@
%% Internal exports
%%----------------------------------------------------------------------
-export([
+ cf/3,
+ cf/4,
+ cf/5
]).
%%----------------------------------------------------------------------
@@ -152,16 +155,16 @@ parse_xml_decl(?BYTE_ORDER_MARK_2, State) ->
cf(?BYTE_ORDER_MARK_2, State, fun parse_xml_decl/2);
parse_xml_decl(?BYTE_ORDER_MARK_REST(Rest), State) ->
cf(Rest, State, fun parse_xml_decl/2);
-parse_xml_decl(?STRING("<"), State) ->
- cf(?STRING("<"), State, fun parse_xml_decl/2);
-parse_xml_decl(?STRING("<?"), State) ->
- cf(?STRING("<?"), State, fun parse_xml_decl/2);
-parse_xml_decl(?STRING("<?x"), State) ->
- cf(?STRING("<?x"), State, fun parse_xml_decl/2);
-parse_xml_decl(?STRING("<?xm"), State) ->
- cf(?STRING("<?xm"), State, fun parse_xml_decl/2);
-parse_xml_decl(?STRING("<?xml"), State) ->
- cf(?STRING("<?xml"), State, fun parse_xml_decl/2);
+parse_xml_decl(?STRING("<") = Bytes, State) ->
+ cf(Bytes, State, fun parse_xml_decl/2);
+parse_xml_decl(?STRING("<?") = Bytes, State) ->
+ cf(Bytes, State, fun parse_xml_decl/2);
+parse_xml_decl(?STRING("<?x") = Bytes, State) ->
+ cf(Bytes, State, fun parse_xml_decl/2);
+parse_xml_decl(?STRING("<?xm") = Bytes, State) ->
+ cf(Bytes, State, fun parse_xml_decl/2);
+parse_xml_decl(?STRING("<?xml") = Bytes, State) ->
+ cf(Bytes, State, fun parse_xml_decl/2);
parse_xml_decl(?STRING_REST("<?xml", Rest1), State) ->
parse_xml_decl_1(Rest1, State);
parse_xml_decl(Bytes, #xmerl_sax_parser_state{encoding=Enc} = State) when is_binary(Bytes) ->
@@ -201,8 +204,8 @@ parse_xml_decl_1(Bytes, State) ->
%%----------------------------------------------------------------------
parse_prolog(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_prolog/2);
-parse_prolog(?STRING("<"), State) ->
- cf(?STRING("<"), State, fun parse_prolog/2);
+parse_prolog(?STRING("<") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog/2);
parse_prolog(?STRING_REST("<?", Rest), State) ->
{Rest1, State1} = parse_pi(Rest, State),
parse_prolog(Rest1, State1);
@@ -220,18 +223,18 @@ parse_prolog(Bytes, State) ->
parse_prolog_1(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_prolog_1/2);
-parse_prolog_1(?STRING("D"), State) ->
- cf(?STRING("D"), State, fun parse_prolog_1/2);
-parse_prolog_1(?STRING("DO"), State) ->
- cf(?STRING("DO"), State, fun parse_prolog_1/2);
-parse_prolog_1(?STRING("DOC"), State) ->
- cf(?STRING("DOC"), State, fun parse_prolog_1/2);
-parse_prolog_1(?STRING("DOCT"), State) ->
- cf(?STRING("DOCT"), State, fun parse_prolog_1/2);
-parse_prolog_1(?STRING("DOCTY"), State) ->
- cf(?STRING("DOCTY"), State, fun parse_prolog_1/2);
-parse_prolog_1(?STRING("DOCTYP"), State) ->
- cf(?STRING("DOCTYP"), State, fun parse_prolog_1/2);
+parse_prolog_1(?STRING("D") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog_1/2);
+parse_prolog_1(?STRING("DO") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog_1/2);
+parse_prolog_1(?STRING("DOC") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog_1/2);
+parse_prolog_1(?STRING("DOCT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog_1/2);
+parse_prolog_1(?STRING("DOCTY") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog_1/2);
+parse_prolog_1(?STRING("DOCTYP") = Bytes, State) ->
+ cf(Bytes, State, fun parse_prolog_1/2);
parse_prolog_1(?STRING_REST("DOCTYPE", Rest), State) ->
{Rest1, State1} = parse_doctype(Rest, State),
State2 = event_callback(endDTD, State1),
@@ -509,10 +512,10 @@ parse_ns_name(Bytes, State, Prefix, Name) ->
%%----------------------------------------------------------------------
parse_pi_data(?STRING_EMPTY, State, Acc) ->
cf(?STRING_EMPTY, State, Acc, fun parse_pi_data/3);
-parse_pi_data(?STRING("?"), State, Acc) ->
- cf(?STRING("?"), State, Acc, fun parse_pi_data/3);
-parse_pi_data(?STRING("\r"), State, Acc) ->
- cf(?STRING("\r"), State, Acc, fun parse_pi_data/3);
+parse_pi_data(?STRING("?") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_pi_data/3);
+parse_pi_data(?STRING("\r") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_pi_data/3);
parse_pi_data(?STRING_REST("?>", Rest), State, Acc) ->
{lists:reverse(Acc), Rest, State};
parse_pi_data(?STRING_REST("\n", Rest), #xmerl_sax_parser_state{line_no=N} = State, Acc) ->
@@ -541,23 +544,23 @@ parse_pi_data(Bytes, State, Acc) ->
%%----------------------------------------------------------------------
parse_cdata(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_cdata/2);
-parse_cdata(?STRING("["), State) ->
- cf(?STRING("["), State, fun parse_cdata/2);
-parse_cdata(?STRING("[C"), State) ->
- cf(?STRING("[C"), State, fun parse_cdata/2);
-parse_cdata(?STRING("[CD"), State) ->
- cf(?STRING("[CD"), State, fun parse_cdata/2);
-parse_cdata(?STRING("[CDA"), State) ->
- cf(?STRING("[CDA"), State, fun parse_cdata/2);
-parse_cdata(?STRING("[CDAT"), State) ->
- cf(?STRING("[CDAT"), State, fun parse_cdata/2);
-parse_cdata(?STRING("[CDATA"), State) ->
- cf(?STRING("[CDATA"), State, fun parse_cdata/2);
-parse_cdata(?STRING_REST("[CDATA[", Rest), State) ->
- State1 = event_callback(startCDATA, State),
+parse_cdata(?STRING("[") = Bytes, State) ->
+ cf(Bytes, State, fun parse_cdata/2);
+parse_cdata(?STRING("[C") = Bytes, State) ->
+ cf(Bytes, State, fun parse_cdata/2);
+parse_cdata(?STRING("[CD") = Bytes, State) ->
+ cf(Bytes, State, fun parse_cdata/2);
+parse_cdata(?STRING("[CDA") = Bytes, State) ->
+ cf(Bytes, State, fun parse_cdata/2);
+parse_cdata(?STRING("[CDAT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_cdata/2);
+parse_cdata(?STRING("[CDATA") = Bytes, State) ->
+ cf(Bytes, State, fun parse_cdata/2);
+parse_cdata(?STRING_REST("[CDATA[", Rest), State) ->
+ State1 = event_callback(startCDATA, State),
parse_cdata(Rest, State1, []);
-parse_cdata(Bytes, State) ->
- unicode_incomplete_check([Bytes, State, fun parse_cdata/2],
+parse_cdata(Bytes, State) ->
+ unicode_incomplete_check([Bytes, State, fun parse_cdata/2],
"expecting comment or CDATA").
@@ -571,12 +574,12 @@ parse_cdata(Bytes, State) ->
%%----------------------------------------------------------------------
parse_cdata(?STRING_EMPTY, State, Acc) ->
cf(?STRING_EMPTY, State, Acc, fun parse_cdata/3);
-parse_cdata(?STRING("\r"), State, Acc) ->
- cf(?STRING("\r"), State, Acc, fun parse_cdata/3);
-parse_cdata(?STRING("]"), State, Acc) ->
- cf(?STRING("]"), State, Acc, fun parse_cdata/3);
-parse_cdata(?STRING("]]"), State, Acc) ->
- cf(?STRING("]]"), State, Acc, fun parse_cdata/3);
+parse_cdata(?STRING("\r") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_cdata/3);
+parse_cdata(?STRING("]") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_cdata/3);
+parse_cdata(?STRING("]]") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_cdata/3);
parse_cdata(?STRING_REST("]]>", Rest), State, Acc) ->
State1 = event_callback({characters, lists:reverse(Acc)}, State),
State2 = event_callback(endCDATA, State1),
@@ -607,12 +610,12 @@ parse_cdata(Bytes, State, Acc) ->
%%----------------------------------------------------------------------
parse_comment(?STRING_EMPTY, State, Acc) ->
cf(?STRING_EMPTY, State, Acc, fun parse_comment/3);
-parse_comment(?STRING("\r"), State, Acc) ->
- cf(?STRING("\r"), State, Acc, fun parse_comment/3);
-parse_comment(?STRING("-"), State, Acc) ->
- cf(?STRING("-"), State, Acc, fun parse_comment/3);
-parse_comment(?STRING("--"), State, Acc) ->
- cf(?STRING("--"), State, Acc, fun parse_comment/3);
+parse_comment(?STRING("\r") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_comment/3);
+parse_comment(?STRING("-") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_comment/3);
+parse_comment(?STRING("--") = Bytes, State, Acc) ->
+ cf(Bytes, State, Acc, fun parse_comment/3);
parse_comment(?STRING_REST("-->", Rest), State, Acc) ->
State1 = event_callback({comment, lists:reverse(Acc)}, State),
{Rest, State1};
@@ -710,8 +713,8 @@ parse_stag(Bytes, State) ->
%%----------------------------------------------------------------------
parse_attributes(?STRING_EMPTY, State, CurrentTag) ->
cf(?STRING_EMPTY, State, CurrentTag, fun parse_attributes/3);
-parse_attributes(?STRING("/"), State, CurrentTag) ->
- cf(?STRING("/"), State, CurrentTag, fun parse_attributes/3);
+parse_attributes(?STRING("/") = Bytes, State, CurrentTag) ->
+ cf(Bytes, State, CurrentTag, fun parse_attributes/3);
parse_attributes(?STRING_REST("/>", Rest), State, {Tag, AttList, NewNsList}) ->
CompleteNsList = NewNsList ++ State#xmerl_sax_parser_state.ns,
{Uri, LocalName, QName, Attributes} = fix_ns(Tag, AttList, CompleteNsList),
@@ -759,7 +762,7 @@ parse_attributes(?STRING_UNBOUND_REST(C, Rest), State, {Tag, AttList, NsList}) -
end
end;
false ->
- ?fatal_error(State, "Invalid start character in attribute name: " ++ C)
+ ?fatal_error(State, "Invalid start character in attribute name: " ++ [C])
end;
parse_attributes(Bytes, State, CurrentTag) ->
unicode_incomplete_check([Bytes, State, CurrentTag, fun parse_attributes/3],
@@ -908,20 +911,20 @@ parse_att_value(?STRING_EMPTY, State, undefined, Acc) ->
{Acc, [], State}; %% stop clause when parsing references
parse_att_value(?STRING_EMPTY, State, Stop, Acc) ->
cf(?STRING_EMPTY, State, Stop, Acc, fun parse_att_value/4);
-parse_att_value(?STRING("\r"), State, Stop, Acc) ->
- cf(?STRING("\r"), State, Stop, Acc, fun parse_att_value/4);
+parse_att_value(?STRING("\r") = Bytes, State, Stop, Acc) ->
+ cf(Bytes, State, Stop, Acc, fun parse_att_value/4);
parse_att_value(?STRING_REST("\n", Rest), #xmerl_sax_parser_state{line_no=N} = State, Stop, Acc) ->
parse_att_value(Rest,
- State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
+ State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
parse_att_value(?STRING_REST("\r\n", Rest), #xmerl_sax_parser_state{line_no=N} = State, Stop, Acc) ->
parse_att_value(Rest,
- State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
+ State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
parse_att_value(?STRING_REST("\r", Rest), #xmerl_sax_parser_state{line_no=N} = State, Stop, Acc) ->
parse_att_value(Rest,
- State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
+ State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
parse_att_value(?STRING_REST("\t", Rest), #xmerl_sax_parser_state{line_no=N} = State, Stop, Acc) ->
parse_att_value(Rest,
- State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
+ State#xmerl_sax_parser_state{line_no=N+1}, Stop, [?space |Acc]);
parse_att_value(?STRING_REST("&", Rest), State, Stop, Acc) ->
{Ref, Rest1, State1} = parse_reference(Rest, State, true),
case Ref of
@@ -944,14 +947,19 @@ parse_att_value(?STRING_REST("&", Rest), State, Stop, Acc) ->
{unparsed, Name, _} ->
?fatal_error(State1, "Unparsed entity reference in attribute value: " ++ Name)
end;
-parse_att_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
+parse_att_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
{lists:reverse(Acc), Rest, State};
-parse_att_value(?STRING_UNBOUND_REST($<, _Rest), State, _Stop, _Acc) ->
+parse_att_value(?STRING_UNBOUND_REST($<, _Rest), State, _Stop, _Acc) ->
?fatal_error(State, "< not allowed in attribute value");
-parse_att_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
- parse_att_value(Rest, State, Stop, [C|Acc]);
-parse_att_value(Bytes, State, Stop, Acc) ->
- unicode_incomplete_check([Bytes, State, Stop, Acc, fun parse_att_value/4],
+parse_att_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
+ if
+ ?is_char(C) ->
+ parse_att_value(Rest, State, Stop, [C|Acc]);
+ true ->
+ ?fatal_error(State, lists:flatten(io_lib:format("Bad character in attribute value: ~p", [C])))
+ end;
+parse_att_value(Bytes, State, Stop, Acc) ->
+ unicode_incomplete_check([Bytes, State, Stop, Acc, fun parse_att_value/4],
undefined).
@@ -1038,17 +1046,17 @@ parse_content(?STRING_EMPTY, State, Acc, IgnorableWS) ->
Other ->
throw(Other)
end;
-parse_content(?STRING("\r"), State, Acc, IgnorableWS) ->
- cf(?STRING("\r"), State, Acc, IgnorableWS, fun parse_content/4);
-parse_content(?STRING("<"), State, Acc, IgnorableWS) ->
- cf(?STRING("<"), State, Acc, IgnorableWS, fun parse_content/4);
+parse_content(?STRING("\r") = Bytes, State, Acc, IgnorableWS) ->
+ cf(Bytes, State, Acc, IgnorableWS, fun parse_content/4);
+parse_content(?STRING("<") = Bytes, State, Acc, IgnorableWS) ->
+ cf(Bytes, State, Acc, IgnorableWS, fun parse_content/4);
parse_content(?STRING_REST("</", Rest), State, Acc, IgnorableWS) ->
State1 = send_character_event(length(Acc), IgnorableWS, lists:reverse(Acc), State),
parse_etag(Rest, State1);
-parse_content(?STRING("<!"), State, _Acc, IgnorableWS) ->
- cf(?STRING("<!"), State, [], IgnorableWS, fun parse_content/4);
-parse_content(?STRING("<!-"), State, _Acc, IgnorableWS) ->
- cf(?STRING("<!-"), State, [], IgnorableWS, fun parse_content/4);
+parse_content(?STRING("<!") = Bytes, State, _Acc, IgnorableWS) ->
+ cf(Bytes, State, [], IgnorableWS, fun parse_content/4);
+parse_content(?STRING("<!-") = Bytes, State, _Acc, IgnorableWS) ->
+ cf(Bytes, State, [], IgnorableWS, fun parse_content/4);
parse_content(?STRING_REST("<!--", Rest), State, Acc, IgnorableWS) ->
State1 = send_character_event(length(Acc), IgnorableWS, lists:reverse(Acc), State),
{Rest1, State2} = parse_comment(Rest, State1, []),
@@ -1120,10 +1128,10 @@ parse_content(?STRING_UNBOUND_REST(C, Rest), State, Acc, _IgnorableWS) ->
?is_char(C) ->
parse_content(Rest, State, [C|Acc], false);
true ->
- ?fatal_error(State, "Bad character in content: " ++ C)
- end;
-parse_content(Bytes, State, Acc, IgnorableWS) ->
- unicode_incomplete_check([Bytes, State, Acc, IgnorableWS, fun parse_content/4],
+ ?fatal_error(State, lists:flatten(io_lib:format("Bad character in content: ~p", [C])))
+ end;
+parse_content(Bytes, State, Acc, IgnorableWS) ->
+ unicode_incomplete_check([Bytes, State, Acc, IgnorableWS, fun parse_content/4],
undefined).
@@ -1219,8 +1227,8 @@ whitespace(Bytes, #xmerl_sax_parser_state{encoding=Enc} = State, Acc) when is_bi
%%----------------------------------------------------------------------
parse_reference(?STRING_EMPTY, State, HaveToExist) ->
cf(?STRING_EMPTY, State, HaveToExist, fun parse_reference/3);
-parse_reference(?STRING("#"), State, HaveToExist) ->
- cf(?STRING("#"), State, HaveToExist, fun parse_reference/3);
+parse_reference(?STRING("#") = Bytes, State, HaveToExist) ->
+ cf(Bytes, State, HaveToExist, fun parse_reference/3);
parse_reference(?STRING_REST("#x", Rest), State, _HaveToExist) ->
{CharValue, RefString, Rest1, State1} = parse_hex(Rest, State, []),
if
@@ -1694,16 +1702,16 @@ parse_external_entity_1(?BYTE_ORDER_MARK_2, State) ->
cf(?BYTE_ORDER_MARK_2, State, fun parse_external_entity_1/2);
parse_external_entity_1(?BYTE_ORDER_MARK_REST(Rest), State) ->
parse_external_entity_1(Rest, State);
-parse_external_entity_1(?STRING("<"), State) ->
- cf(?STRING("<"), State, fun parse_external_entity_1/2);
-parse_external_entity_1(?STRING("<?"), State) ->
- cf(?STRING("<?"), State, fun parse_external_entity_1/2);
-parse_external_entity_1(?STRING("<?x"), State) ->
- cf(?STRING("<?x"), State, fun parse_external_entity_1/2);
-parse_external_entity_1(?STRING("<?xm"), State) ->
- cf(?STRING("<?xm"), State, fun parse_external_entity_1/2);
-parse_external_entity_1(?STRING("<?xml"), State) ->
- cf(?STRING("<?xml"), State, fun parse_external_entity_1/2);
+parse_external_entity_1(?STRING("<") = Bytes, State) ->
+ cf(Bytes, State, fun parse_external_entity_1/2);
+parse_external_entity_1(?STRING("<?") = Bytes, State) ->
+ cf(Bytes, State, fun parse_external_entity_1/2);
+parse_external_entity_1(?STRING("<?x") = Bytes, State) ->
+ cf(Bytes, State, fun parse_external_entity_1/2);
+parse_external_entity_1(?STRING("<?xm") = Bytes, State) ->
+ cf(Bytes, State, fun parse_external_entity_1/2);
+parse_external_entity_1(?STRING("<?xml") = Bytes, State) ->
+ cf(Bytes, State, fun parse_external_entity_1/2);
parse_external_entity_1(?STRING_REST("<?xml", Rest) = Bytes,
#xmerl_sax_parser_state{file_type=Type} = State) ->
{Rest1, State1} =
@@ -1773,29 +1781,29 @@ is_next_char_whitespace(Bytes, State) ->
%%----------------------------------------------------------------------
parse_external_id(?STRING_EMPTY, State, OptionalSystemId) ->
cf(?STRING_EMPTY, State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("S"), State,OptionalSystemId) ->
- cf(?STRING("S"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("SY"), State, OptionalSystemId) ->
- cf(?STRING("SY"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("SYS"), State, OptionalSystemId) ->
- cf(?STRING("SYS"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("SYST"), State, OptionalSystemId) ->
- cf(?STRING("SYST"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("SYSTE"), State, OptionalSystemId) ->
- cf(?STRING("SYSTE"), State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("S") = Bytes, State,OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("SY") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("SYS") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("SYST") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("SYSTE") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
parse_external_id(?STRING_REST("SYSTEM", Rest), State, _) ->
{SysId, Rest1, State1} = parse_system_id(Rest, State, false),
{"", SysId, Rest1, State1};
-parse_external_id(?STRING("P"), State, OptionalSystemId) ->
- cf(?STRING("P"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("PU"), State, OptionalSystemId) ->
- cf(?STRING("PU"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("PUB"), State, OptionalSystemId) ->
- cf(?STRING("PUB"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("PUBL"), State, OptionalSystemId) ->
- cf(?STRING("PUBL"), State, OptionalSystemId, fun parse_external_id/3);
-parse_external_id(?STRING("PUBLI"), State, OptionalSystemId) ->
- cf(?STRING("PUBLI"), State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("P") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("PU") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("PUB") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("PUBL") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
+parse_external_id(?STRING("PUBLI") = Bytes, State, OptionalSystemId) ->
+ cf(Bytes, State, OptionalSystemId, fun parse_external_id/3);
parse_external_id(?STRING_REST("PUBLIC", Rest), State, OptionalSystemId) ->
parse_public_id(Rest, State, OptionalSystemId);
parse_external_id(Bytes, State, OptionalSystemId) ->
@@ -1915,70 +1923,70 @@ parse_doctype_decl(Bytes, State) ->
parse_doctype_decl_1(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("E"), State) ->
- cf(?STRING("E"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("EL"), State) ->
- cf(?STRING("EL"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ELE"), State) ->
- cf(?STRING("ELE"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ELEM"), State) ->
- cf(?STRING("ELEM"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ELEME"), State) ->
- cf(?STRING("ELEME"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ELEMEN"), State) ->
- cf(?STRING("ELEMEN"), State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("E") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("EL") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ELE") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ELEM") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ELEME") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ELEMEN") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
parse_doctype_decl_1(?STRING_REST("ELEMENT", Rest), State) ->
{Rest1, State1} = parse_element_decl(Rest, State),
parse_doctype_decl(Rest1, State1);
-parse_doctype_decl_1(?STRING("A"), State) ->
- cf(?STRING("A"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("AT"), State) ->
- cf(?STRING("AT"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ATT"), State) ->
- cf(?STRING("ATT"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ATTL"), State) ->
- cf(?STRING("ATTL"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ATTLI"), State) ->
- cf(?STRING("ATTLI"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ATTLIS"), State) ->
- cf(?STRING("ATTLIS"), State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("A") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("AT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ATT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ATTL") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ATTLI") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ATTLIS") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
parse_doctype_decl_1(?STRING_REST("ATTLIST", Rest), State) ->
{Rest1, State1} = parse_att_list_decl(Rest, State),
parse_doctype_decl(Rest1, State1);
%% E clause not needed here because already taken care of above.
-parse_doctype_decl_1(?STRING("EN"), State) ->
- cf(?STRING("EN"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ENT"), State) ->
- cf(?STRING("ENT"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ENTI"), State) ->
- cf(?STRING("ENTI"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("ENTIT"), State) ->
- cf(?STRING("ENTIT"), State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("EN") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ENT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ENTI") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("ENTIT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
parse_doctype_decl_1(?STRING_REST("ENTITY", Rest), State) ->
{Rest1, State1} = parse_entity_decl(Rest, State),
parse_doctype_decl(Rest1, State1);
-parse_doctype_decl_1(?STRING("N"), State) ->
- cf(?STRING("N"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("NO"), State) ->
- cf(?STRING("NO"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("NOT"), State) ->
- cf(?STRING("NOT"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("NOTA"), State) ->
- cf(?STRING("NOTA"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("NOTAT"), State) ->
- cf(?STRING("NOTAT"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("NOTATI"), State) ->
- cf(?STRING("NOTATI"), State, fun parse_doctype_decl_1/2);
-parse_doctype_decl_1(?STRING("NOTATIO"), State) ->
- cf(?STRING("NOTATIO"), State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("N") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("NO") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("NOT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("NOTA") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("NOTAT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("NOTATI") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("NOTATIO") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
parse_doctype_decl_1(?STRING_REST("NOTATION", Rest), State) ->
{Rest1, State1} = parse_notation_decl(Rest, State),
parse_doctype_decl(Rest1, State1);
-parse_doctype_decl_1(?STRING("-"), State) ->
- cf(?STRING("-"), State, fun parse_doctype_decl_1/2);
+parse_doctype_decl_1(?STRING("-") = Bytes, State) ->
+ cf(Bytes, State, fun parse_doctype_decl_1/2);
parse_doctype_decl_1(?STRING_REST("--", Rest), State) ->
{Rest1, State1} = parse_comment(Rest, State, []),
parse_doctype_decl(Rest1, State1);
@@ -2049,14 +2057,18 @@ parse_element_content(Bytes, State) ->
parse_element_content_1(?STRING_EMPTY, State, Acc) ->
cf(?STRING_EMPTY, State, Acc, fun parse_element_content_1/3);
parse_element_content_1(?STRING_REST(">", Rest), State, Acc) ->
- {lists:reverse(Acc), Rest, State};
+ {lists:reverse(delete_leading_whitespace(Acc)), Rest, State};
parse_element_content_1(?STRING_UNBOUND_REST(C, Rest), State, Acc) ->
parse_element_content_1(Rest, State, [C|Acc]);
parse_element_content_1(Bytes, State, Acc) ->
unicode_incomplete_check([Bytes, State, Acc, fun parse_element_content_1/3],
undefined).
-
+delete_leading_whitespace([C |Acc]) when ?is_whitespace(C)->
+ delete_leading_whitespace(Acc);
+delete_leading_whitespace(Acc) ->
+ Acc.
+
%%----------------------------------------------------------------------
%% Function : parse_att_list_decl(Rest, State) -> Result
%% Parameters: Rest = string() | binary()
@@ -2252,52 +2264,52 @@ parse_default_decl(Bytes, State) ->
%%----------------------------------------------------------------------
parse_default_decl_1(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_default_decl_1/2);
-parse_default_decl_1(?STRING_REST("#", Rest), State) ->
- case Rest of
- ?STRING("R") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("RE") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("REQ") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("REQU") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("REQUI") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("REQUIR") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("REQUIRE") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING_REST("REQUIRED", Rest1) ->
+parse_default_decl_1(?STRING_REST("#", _Rest) = Bytes, State) ->
+ case Bytes of
+ ?STRING("#R") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#RE") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#REQ") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#REQU") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#REQUI") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#REQUIR") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#REQUIRE") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING_REST("#REQUIRED", Rest1) ->
{"#REQUIRED", undefined, Rest1, State};
- ?STRING("I") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("IM") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("IMP") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("IMPL") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("IMPLI") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("IMPLIE") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING_REST("IMPLIED", Rest1) ->
+ ?STRING("#I") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#IM") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#IMP") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#IMPL") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#IMPLI") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#IMPLIE") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING_REST("#IMPLIED", Rest1) ->
{"#IMPLIED", undefined, Rest1, State};
- ?STRING("F") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("FI") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("FIX") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING("FIXE") ->
- cf(Rest, State, fun parse_default_decl_1/2);
- ?STRING_REST("FIXED", Rest1) ->
+ ?STRING("#F") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#FI") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#FIX") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING("#FIXE") ->
+ cf(Bytes, State, fun parse_default_decl_1/2);
+ ?STRING_REST("#FIXED", Rest1) ->
parse_fixed(Rest1, State);
_ ->
- ?fatal_error(State, "REQUIRED, IMPLIED or FIXED expected")
+ ?fatal_error(State, "REQUIRED, IMPLIED or FIXED expected after #")
end;
parse_default_decl_1(?STRING_UNBOUND_REST(C, Rest), State) when C == $'; C == $" ->
{DefaultValue, Rest1, State1} = parse_att_value(Rest, State, C, []),
@@ -2522,11 +2534,16 @@ parse_entity_value(?STRING_REST("%", Rest), #xmerl_sax_parser_state{file_type=Ty
end
end;
-parse_entity_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
+parse_entity_value(?STRING_UNBOUND_REST(Stop, Rest), State, Stop, Acc) ->
{lists:reverse(Acc), Rest, State};
-parse_entity_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
- parse_entity_value(Rest, State, Stop, [C|Acc]);
-parse_entity_value(Bytes, State, Stop, Acc) ->
+parse_entity_value(?STRING_UNBOUND_REST(C, Rest), State, Stop, Acc) ->
+ if
+ ?is_char(C) ->
+ parse_entity_value(Rest, State, Stop, [C|Acc]);
+ true ->
+ ?fatal_error(State, lists:flatten(io_lib:format("Bad character in entity value: ~p", [C])))
+ end;
+parse_entity_value(Bytes, State, Stop, Acc) ->
unicode_incomplete_check([Bytes, State, Stop, Acc, fun parse_entity_value/4],
undefined).
@@ -2543,14 +2560,14 @@ parse_ndata_decl(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_ndata_decl/2);
parse_ndata_decl(?STRING_REST(">", Rest), State) ->
{undefined, Rest, State};
-parse_ndata_decl(?STRING("N") = Rest, State) ->
- cf(Rest, State, fun parse_ndata_decl/2);
-parse_ndata_decl(?STRING("ND") = Rest, State) ->
- cf(Rest, State, fun parse_ndata_decl/2);
-parse_ndata_decl(?STRING("NDA") = Rest, State) ->
- cf(Rest, State, fun parse_ndata_decl/2);
-parse_ndata_decl(?STRING("NDAT") = Rest, State) ->
- cf(Rest, State, fun parse_ndata_decl/2);
+parse_ndata_decl(?STRING("N") = Bytes, State) ->
+ cf(Bytes, State, fun parse_ndata_decl/2);
+parse_ndata_decl(?STRING("ND") = Bytes, State) ->
+ cf(Bytes, State, fun parse_ndata_decl/2);
+parse_ndata_decl(?STRING("NDA") = Bytes, State) ->
+ cf(Bytes, State, fun parse_ndata_decl/2);
+parse_ndata_decl(?STRING("NDAT") = Bytes, State) ->
+ cf(Bytes, State, fun parse_ndata_decl/2);
parse_ndata_decl(?STRING_REST("NDATA", Rest), State) ->
parse_ndata_decl_1(Rest, State);
parse_ndata_decl(Bytes, State) ->
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 25c6547497..05431a5fd2 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -20,8 +20,8 @@
%% Description : Simgle-pass XML scanner. See xmerl.hrl for data defs.
%% @doc This module is the interface to the XML parser, it handles XML 1.0.
-%% The XML parser is activated through
-%% <tt>xmerl_scan:string/[1,2]</tt> or
+%% The XML parser is activated through
+%% <tt>xmerl_scan:string/[1,2]</tt> or
%% <tt>xmerl_scan:file/[1,2]</tt>.
%% It returns records of the type defined in xmerl.hrl.
%% See also <a href="xmerl_examples.html">tutorial</a> on customization
@@ -79,15 +79,15 @@
%% <dt><code>{validation, Flag}</code></dt>
%% <dd>Controls whether to process as a validating XML parser:
%% 'off' (default) no validation, or validation 'dtd' by DTD or 'schema'
-%% by XML Schema. 'false' and 'true' options are obsolete
-%% (i.e. they may be removed in a future release), if used 'false'
+%% by XML Schema. 'false' and 'true' options are obsolete
+%% (i.e. they may be removed in a future release), if used 'false'
%% equals 'off' and 'true' equals 'dtd'.</dd>
%% <dt><code>{schemaLocation, [{Namespace,Link}|...]}</code></dt>
-%% <dd>Tells explicitly which XML Schema documents to use to validate
-%% the XML document. Used together with the
+%% <dd>Tells explicitly which XML Schema documents to use to validate
+%% the XML document. Used together with the
%% <code>{validation,schema}</code> option.</dd>
%% <dt><code>{quiet, Flag}</code></dt>
-%% <dd>Set to 'true' if xmerl should behave quietly and not output any
+%% <dd>Set to 'true' if xmerl should behave quietly and not output any
%% information to standard output (default 'false').</dd>
%% <dt><code>{doctype_DTD, DTD}</code></dt>
%% <dd>Allows to specify DTD name when it isn't available in the XML
@@ -100,7 +100,21 @@
%% <dd>Set default character set used (default UTF-8).
%% This character set is used only if not explicitly given by the XML
%% declaration. </dd>
+%% <dt><code>{document, Flag}</code></dt>
+%% <dd>Set to 'true' if xmerl should return a complete XML document
+%% as an xmlDocument record (default 'false').</dd>
+%% <dt><code>{comments, Flag}</code></dt>
+%% <dd>Set to 'false' if xmerl should skip comments otherwise they will
+%% be returned as xmlComment records (default 'true').</dd>
+%% <dt><code>{default_attrs, Flag}</code></dt>
+%% <dd>Set to 'true' if xmerl should add to elements missing attributes
+%% with a defined default value (default 'false').</dd>
%% </dl>
+%% @type document() = xmlElement() | xmlDocument(). <p>
+%% The document returned by <tt>xmerl_scan:string/[1,2]</tt> and
+%% <tt>xmerl_scan:file/[1,2]</tt>. The type of the returned record depends on
+%% the value of the document option passed to the function.
+%% </p>
-module(xmerl_scan).
@@ -224,7 +238,7 @@ cont_state(X, S=#xmerl_scanner{fun_states = FS}) ->
file(F) ->
file(F, []).
-%% @spec file(Filename::string(), Options::option_list()) -> {xmlElement(),Rest}
+%% @spec file(Filename::string(), Options::option_list()) -> {document(),Rest}
%% Rest = list()
%%% @doc Parse file containing an XML document
file(F, Options) ->
@@ -261,10 +275,10 @@ int_file_decl(F, Options,_ExtCharset) ->
%% @spec string(Text::list()) -> {xmlElement(),Rest}
%% Rest = list()
%% @equiv string(Test, [])
-string(Str) ->
+string(Str) ->
string(Str, []).
-%% @spec string(Text::list(),Options::option_list()) -> {xmlElement(),Rest}
+%% @spec string(Text::list(),Options::option_list()) -> {document(),Rest}
%% Rest = list()
%%% @doc Parse string containing an XML document
string(Str, Options) ->
@@ -292,7 +306,7 @@ int_string(Str, Options, XMLBase, FileName) ->
scan_document(Str2, S#xmerl_scanner{encoding="iso-10646-utf-1"});
{undefined,undefined,Str2} -> %% no auto detection
scan_document(Str2, S);
- {external,ExtCharset,Str2} ->
+ {external,ExtCharset,Str2} ->
%% no auto detection, ExtCharset is an explicitly provided
%% 7 bit,8 bit or utf-8 encoding
scan_document(Str2, S#xmerl_scanner{encoding=atom_to_list(ExtCharset)})
@@ -311,7 +325,7 @@ int_string_decl(Str, Options, XMLBase, FileName) ->
{external,ExtCharset,Str2} ->
scan_decl(Str2, S#xmerl_scanner{encoding=atom_to_list(ExtCharset)})
end.
-
+
initial_state0(Options,XMLBase) ->
@@ -372,7 +386,7 @@ initial_state([{line, L}|T], S) ->
initial_state(T, S#xmerl_scanner{line = L});
initial_state([{namespace_conformant, F}|T], S) when F==true; F==false ->
initial_state(T, S#xmerl_scanner{namespace_conformant = F});
-initial_state([{validation, F}|T], S)
+initial_state([{validation, F}|T], S)
when F==off; F==dtd; F==schema; F==true; F==false ->
initial_state(T, S#xmerl_scanner{validation = validation_value(F)});
initial_state([{schemaLocation, SL}|T], S) when is_list(SL) ->
@@ -381,6 +395,12 @@ initial_state([{quiet, F}|T], S) when F==true; F==false ->
initial_state(T, S#xmerl_scanner{quiet = F});
initial_state([{doctype_DTD,DTD}|T], S) ->
initial_state(T,S#xmerl_scanner{doctype_DTD = DTD});
+initial_state([{document, F}|T], S) when is_boolean(F) ->
+ initial_state(T,S#xmerl_scanner{document = F});
+initial_state([{comments, F}|T], S) when is_boolean(F) ->
+ initial_state(T,S#xmerl_scanner{comments = F});
+initial_state([{default_attrs, F}|T], S) when is_boolean(F) ->
+ initial_state(T,S#xmerl_scanner{default_attrs = F});
initial_state([{text_decl,Bool}|T], S) ->
initial_state(T,S#xmerl_scanner{text_decl=Bool});
initial_state([{environment,Env}|T], S) ->
@@ -402,7 +422,7 @@ validation_value(false) ->
validation_value(F) ->
F.
-%% Used for compacting (some) indentations.
+%% Used for compacting (some) indentations.
%% See also fast_accumulate_whitespace().
common_data() ->
{comdata(lists:duplicate(60, $\s), []),
@@ -445,7 +465,7 @@ event(_X, S) ->
%% where Pos' can be derived from X#xmlElement.pos, X#xmlText.pos, or
%% X#xmlAttribute.pos (whichever is the current object type.)
%% The acc/3 function is not allowed to redefine the type of object
-%% being defined, but _is_ allowed to either ignore it or split it
+%% being defined, but _is_ allowed to either ignore it or split it
%% into multiple objects (in which case {Acc',Pos',S'} should be returned.)
%% If {Acc',S'} is returned, Pos will be incremented by 1 by default.
%% Below is an example of an acceptable operation
@@ -468,10 +488,10 @@ fetch_URI(URI, S) ->
%% assume URI is a filename
Split = filename:split(URI),
Filename = fun([])->[];(X)->lists:last(X) end (Split),
- Fullname =
+ Fullname =
case Split of %% how about Windows systems?
["file:"|Name]-> %% absolute path, see RFC2396 sect 3
- %% file:/dtd_name
+ %% file:/dtd_name
filename:join(["/"|Name]);
["/"|Rest] when Rest /= [] ->
%% absolute path name
@@ -518,20 +538,21 @@ scan_document(Str0, S=#xmerl_scanner{event_fun = Event,
line = L, col = C,
environment=Env,
encoding=Charset,
+ document=Document,
validation=ValidateResult}) ->
S1 = Event(#xmerl_event{event = started,
line = L,
col = C,
data = document}, S),
-
+
%% Transform to given character set.
- %% Note that if another character set is given in the encoding
+ %% Note that if another character set is given in the encoding
%% attribute in a XML declaration that one will be used later
Str=if
Charset == "utf-8" ->
Str0;
- Charset=/=undefined -> % Default character set is UTF-8
- xmerl_ucs:to_unicode(Str0,list_to_atom(Charset));
+ Charset =/= undefined -> % Default character set is UTF-8
+ xmerl_ucs:to_unicode(Str0, list_to_atom(Charset));
true -> %% Charset is undefined if no external input is
%% given, and no auto detection of character
%% encoding was made.
@@ -539,63 +560,71 @@ scan_document(Str0, S=#xmerl_scanner{event_fun = Event,
end,
%% M1 = erlang:memory(),
%% io:format("Memory status before prolog: ~p~n",[M1]),
- {T1, S2} = scan_prolog(Str, S1, _StartPos = 1),
+ {Prolog, Pos, T1, S2} = scan_prolog(Str, S1, _StartPos = 1),
%% M2 = erlang:memory(),
%% io:format("Memory status after prolog: ~p~n",[M2]),
%%io:format("scan_document 2, prolog parsed~n",[]),
- T2 = scan_mandatory("<",T1,1,S2,expected_element_start_tag),
+ T2 = scan_mandatory("<", T1, 1, S2, expected_element_start_tag),
%% M3 = erlang:memory(),
%% io:format("Memory status before element: ~p~n",[M3]),
- {Res, T3, S3} =scan_element(T2,S2,_StartPos = 1),
+ {Res, T3, S3} = scan_element(T2,S2,Pos),
%% M4 = erlang:memory(),
%% io:format("Memory status after element: ~p~n",[M4]),
- {Tail, S4}=scan_misc(T3, S3, _StartPos = 1),
+ {Misc, _Pos1, Tail, S4}=scan_misc(T3, S3, Pos + 1),
%% M5 = erlang:memory(),
%% io:format("Memory status after misc: ~p~n",[M5]),
-
+
S5 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
line = S4#xmerl_scanner.line,
col = S4#xmerl_scanner.col,
data = document}, S4),
- {Res2,S6} = case validation_mode(ValidateResult) of
+ {Res2, S6} = case validation_mode(ValidateResult) of
off ->
- {Res,cleanup(S5)};
+ {Res, cleanup(S5)};
dtd when Env == element; Env == prolog ->
check_decl2(S5),
- case xmerl_validate:validate(S5,Res) of
- {'EXIT',{error,Reason}} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
- {'EXIT',Reason} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
- {error,Reason} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
- {error,Reason,_Next} ->
- S5b=cleanup(S5),
- ?fatal({failed_validation,Reason}, S5b);
+ case xmerl_validate:validate(S5, Res) of
+ {'EXIT', {error, Reason}} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
+ {'EXIT', Reason} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
+ {error, Reason} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
+ {error, Reason, _Next} ->
+ S5b = cleanup(S5),
+ ?fatal({failed_validation, Reason}, S5b);
_XML ->
- {Res,cleanup(S5)}
+ {Res, cleanup(S5)}
end;
schema ->
- case schemaLocations(Res,S5) of
- {ok,Schemas} ->
+ case schemaLocations(Res, S5) of
+ {ok, Schemas} ->
cleanup(S5),
%%io:format("Schemas: ~p~nRes: ~p~ninhertih_options(S): ~p~n",
%% [Schemas,Res,inherit_options(S5)]),
- XSDRes = xmerl_xsd:process_validate(Schemas,Res,
+ XSDRes = xmerl_xsd:process_validate(Schemas, Res,
inherit_options(S5)),
- handle_schema_result(XSDRes,S5);
+ handle_schema_result(XSDRes, S5);
_ ->
- {Res,cleanup(S5)}
+ {Res, cleanup(S5)}
end;
_ ->
- {Res,cleanup(S5)}
+ {Res, cleanup(S5)}
end,
- {Res2, Tail, S6}.
+ Res3 =
+ case Document of
+ true ->
+ Content = lists:reverse(Prolog, [Res2 | lists:reverse(Misc)]),
+ #xmlDocument{content = Content};
+ false ->
+ Res2
+ end,
+ {Res3, Tail, S6}.
scan_decl(Str, S=#xmerl_scanner{event_fun = Event,
@@ -607,13 +636,13 @@ scan_decl(Str, S=#xmerl_scanner{event_fun = Event,
line = L,
col = C,
data = document}, S),
-
+
case scan_prolog(Str, S1, _StartPos = 1) of
- {T2="<"++_, S2} ->
+ {_,_,T2="<"++_, S2} ->
{{S2#xmerl_scanner.user_state,T2},[],S2};
- {[], S2}->
+ {_,_,[], S2}->
{[],[],S2};
- {T2, S2} ->
+ {_,_,T2, S2} ->
{_,_,S3} = scan_content(T2,S2,[],_Attrs=[],S2#xmerl_scanner.space,
_Lang=[],_Parents=[],#xmlNamespace{}),
{T2,[],S3}
@@ -624,28 +653,31 @@ scan_decl(Str, S=#xmerl_scanner{event_fun = Event,
%%% prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
%%%
%% empty text declarations are handled by the first function clause.
-scan_prolog([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_prolog(T, S, Pos) ->
+ scan_prolog(T, S, Pos, []).
+scan_prolog([], S=#xmerl_scanner{continuation_fun = F}, Pos, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_prolog(MoreBytes, S1, Pos) end,
- fun(S1) -> {[], S1} end,
+ F(fun(MoreBytes, S1) -> scan_prolog(MoreBytes, S1, Pos, Acc) end,
+ fun(S1) -> {Acc, Pos, [], S1} end,
S);
-scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
- when ?whitespace(hd(T)) ->
- {Charset,T3, S3}=
+scan_prolog("<?xml"++T,
+ S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},
+ Pos,Acc) when ?whitespace(hd(T)) ->
+ {Charset, T3, S3} =
if
- Col==1,L==1,S0#xmerl_scanner.text_decl==true ->
+ Col==1,L==1,S0#xmerl_scanner.text_decl==true ->
?dbg("prolog(\"<?xml\")~n", []),
?bump_col(5),
{_,T1,S1} = mandatory_strip(T,S),
{Decl,T2, S2}=scan_text_decl(T1,S1),
Encoding=Decl#xmlDecl.encoding,
- {Encoding,T2, S2#xmerl_scanner{encoding=Encoding}};
- Col==1,L==1 ->
+ {Encoding, T2, S2#xmerl_scanner{encoding=Encoding}};
+ Col==1,L==1 ->
?dbg("prolog(\"<?xml\")~n", []),
?bump_col(5),
{Decl,T2, S2}=scan_xml_decl(T, S),
Encoding=Decl#xmlDecl.encoding,
- {Encoding,T2, S2#xmerl_scanner{encoding=Encoding}};
+ {Encoding, T2, S2#xmerl_scanner{encoding=Encoding}};
true ->
?fatal({xml_declaration_must_be_first_in_doc,Col,L},S0)
end,
@@ -659,7 +691,7 @@ scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
%% Now transform to declared character set.
if
Charset==Charset0 -> % Document already transformed to this charset!
- scan_prolog(T3, S3, Pos);
+ scan_prolog(T3, S3, Pos, Acc);
Charset0=/=undefined ->
%% For example may an external entity
%% have the BOM for utf-16 and the internal
@@ -668,17 +700,18 @@ scan_prolog("<?xml"++T,S0=#xmerl_scanner{encoding=Charset0,col=Col,line=L},Pos)
%% 'iso-10646-utf-1', and Charset will be 'utf-16', all
%% legal.
%%
- scan_prolog(T3,S3#xmerl_scanner{encoding=Charset0},Pos);
+ scan_prolog(T3,S3#xmerl_scanner{encoding=Charset0},Pos,Acc);
Charset == "utf-8" ->
- scan_prolog(T3, S3, Pos);
+ scan_prolog(T3, S3, Pos, Acc);
Charset=/=undefined -> % Document not previously transformed
T4=xmerl_ucs:to_unicode(T3,list_to_atom(Charset)),
- scan_prolog(T4, S3, Pos);
+ scan_prolog(T4, S3, Pos, Acc);
true -> % No encoding info given
- scan_prolog(T3, S3, Pos)
+ scan_prolog(T3, S3, Pos, Acc)
end;
-scan_prolog("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog,
- encoding=_Charset}, Pos) ->
+scan_prolog("<!DOCTYPE" ++ T,
+ S0=#xmerl_scanner{environment=prolog,encoding=_Charset},
+ Pos, Acc) ->
?dbg("prolog(\"<!DOCTYPE\")~n", []),
?bump_col(9),
%% If no known character set assume it is UTF-8
@@ -687,12 +720,15 @@ scan_prolog("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog,
true -> T
end,
{T2, S1} = scan_doctype(T1, S),
- scan_misc(T2, S1, Pos);
-scan_prolog(Str="%"++_T,S=#xmerl_scanner{environment={external,_}},_Pos) ->
- scan_ext_subset(Str,S);
-scan_prolog(Str, S0 = #xmerl_scanner{user_state=_US,encoding=_Charset},Pos) ->
+ scan_misc(T2, S1, Pos, Acc);
+scan_prolog(Str="%"++_T,S=#xmerl_scanner{environment={external,_}},
+ Pos,Acc) ->
+ {T, S1} = scan_ext_subset(Str,S),
+ {Acc, Pos, T, S1};
+scan_prolog(Str, S0 = #xmerl_scanner{user_state=_US,encoding=_Charset},
+ Pos,Acc) ->
?dbg("prolog(\"<\")~n", []),
-
+
%% Check for Comments, PI before possible DOCTYPE declaration
?bump_col(1),
%% If no known character set assume it is UTF-8
@@ -700,28 +736,30 @@ scan_prolog(Str, S0 = #xmerl_scanner{user_state=_US,encoding=_Charset},Pos) ->
%% Charset==undefined -> xmerl_ucs:to_unicode(Str,'utf-8');
true -> Str
end,
- {T1, S1}=scan_misc(T, S, Pos),
- scan_prolog2(T1,S1,Pos).
+ {Acc1, Pos1, T1, S1}=scan_misc(T, S, Pos, Acc),
+ scan_prolog2(T1,S1,Pos1,Acc1).
-scan_prolog2([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_prolog2([], S=#xmerl_scanner{continuation_fun = F}, Pos, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_prolog2(MoreBytes, S1, Pos) end,
- fun(S1) -> {[], S1} end,
+ F(fun(MoreBytes, S1) -> scan_prolog2(MoreBytes, S1, Pos, Acc) end,
+ fun(S1) -> {Acc, Pos, [], S1} end,
S);
-scan_prolog2("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog}, Pos) ->
+scan_prolog2("<!DOCTYPE" ++ T, S0=#xmerl_scanner{environment=prolog},
+ Pos, Acc) ->
?dbg("prolog(\"<!DOCTYPE\")~n", []),
?bump_col(9),
{T1, S1} = scan_doctype(T, S),
- scan_misc(T1, S1, Pos);
-scan_prolog2(Str = "<!" ++ _, S, _Pos) ->
+ scan_misc(T1, S1, Pos, Acc);
+scan_prolog2(Str = "<!" ++ _, S, Pos, Acc) ->
?dbg("prolog(\"<!\")~n", []),
%% In e.g. a DTD, we jump directly to markup declarations
- scan_ext_subset(Str, S);
-scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos) ->
+ {T, S1} = scan_ext_subset(Str, S),
+ {Acc, Pos, T, S1};
+scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos,Acc) ->
?dbg("prolog(\"<\")~n", []),
-
+
%% Here we consider the DTD provided by doctype_DTD option,
S1 =
case S0 of
@@ -733,7 +771,7 @@ scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos) ->
end,
%% Check for more Comments and PI after DOCTYPE declaration
% ?bump_col(1),
- scan_misc(Str, S1, Pos).
+ scan_misc(Str, S1, Pos, Acc).
@@ -743,26 +781,46 @@ scan_prolog2(Str, S0 = #xmerl_scanner{user_state=_US},Pos) ->
%% - Neither of Comment and PI are returned in the resulting parsed
%% structure.
%% - scan_misc/3 implements Misc* as that is how the rule is always used
-scan_misc([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_misc(T, S, Pos) ->
+ scan_misc(T, S, Pos, []).
+scan_misc([], S=#xmerl_scanner{continuation_fun = F}, Pos, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_misc(MoreBytes, S1, Pos) end,
- fun(S1) -> {[], S1} end,
+ F(fun(MoreBytes, S1) -> scan_misc(MoreBytes, S1, Pos, Acc) end,
+ fun(S1) -> {Acc, Pos, [], S1} end,
S);
-scan_misc("<!--" ++ T, S0, Pos) -> % Comment
+scan_misc("<!--" ++ T, S0=#xmerl_scanner{acc_fun = F, comments=CF}, Pos, Acc) -> % Comment
?bump_col(4),
- {_, T1, S1} = scan_comment(T, S, Pos, _Parents = [], _Lang = []),
- scan_misc(T1,S1,Pos);
-scan_misc("<?" ++ T, S0, Pos) -> % PI
+ {C, T1, S1} = scan_comment(T, S, Pos, _Parents = [], _Lang = []),
+ case CF of
+ true ->
+ {Acc2, Pos2, S3} =
+ case F(C, Acc, S1) of
+ {Acc1, S2} ->
+ {Acc1, Pos + 1, S2};
+ {Acc1, Pos1, S2} ->
+ {Acc1, Pos1, S2}
+ end,
+ scan_misc(T1, S3, Pos2, Acc2);
+ false ->
+ scan_misc(T1, S1, Pos, Acc)
+ end;
+scan_misc("<?" ++ T, S0=#xmerl_scanner{acc_fun = F}, Pos, Acc) -> % PI
?dbg("prolog(\"<?\")~n", []),
?bump_col(2),
- {_PI, T1, S1} = scan_pi(T, S, Pos),
- scan_misc(T1,S1,Pos);
-scan_misc(T=[H|_T], S, Pos) when ?whitespace(H) ->
+ {PI, T1, S1} = scan_pi(T, S, Pos, []),
+ {Acc2, Pos2, S3} = case F(PI, Acc, S1) of
+ {Acc1, S2} ->
+ {Acc1, Pos + 1, S2};
+ {Acc1, Pos1, S2} ->
+ {Acc1, Pos1, S2}
+ end,
+ scan_misc(T1,S3,Pos2,Acc2);
+scan_misc(T=[H|_T], S, Pos, Acc) when ?whitespace(H) ->
?dbg("prolog(whitespace)~n", []),
{_,T1,S1}=strip(T,S),
- scan_misc(T1,S1,Pos);
-scan_misc(T,S,_Pos) ->
- {T,S}.
+ scan_misc(T1,S1,Pos,Acc);
+scan_misc(T,S,Pos,Acc) ->
+ {Acc,Pos,T,S}.
cleanup(S=#xmerl_scanner{keep_rules = false,
@@ -780,7 +838,7 @@ scan_xml_decl(T, S) ->
{_,T1,S1} = mandatory_strip(T,S),
{T2,S2} =
case T1 of
- "version" ++ _T2 ->
+ "version" ++ _T2 ->
{_T2,S1#xmerl_scanner{col=S1#xmerl_scanner.col+7}};
_ -> ?fatal(expected_version_attribute,S1)
end,
@@ -789,7 +847,8 @@ scan_xml_decl(T, S) ->
Attr = #xmlAttribute{name = version,
parents = [{xml, _XMLPos = 1}],
value = Vsn},
- scan_xml_decl(T4, S4, #xmlDecl{attributes = [Attr]}).
+ scan_xml_decl(T4, S4, #xmlDecl{vsn = Vsn,
+ attributes = [Attr]}).
scan_xml_decl([], S=#xmerl_scanner{continuation_fun = F}, Decl) ->
?dbg("cont()...~n", []),
@@ -820,8 +879,8 @@ scan_xml_decl2("encoding" ++ T, S0 = #xmerl_scanner{event_fun = Event},
value = LowEncName},
Decl = Decl0#xmlDecl{encoding = LowEncName,
attributes = [Attr|Attrs]},
- S3 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
- line = S0#xmerl_scanner.line,
+ S3 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
+ line = S0#xmerl_scanner.line,
col = S0#xmerl_scanner.col,
data = Attr}, S2),
case T2 of
@@ -843,7 +902,7 @@ scan_xml_decl3("?>" ++ T, S0,Decl) ->
return_xml_decl(T,S,Decl);
scan_xml_decl3("standalone" ++ T,S0 = #xmerl_scanner{event_fun = Event},
Decl0 = #xmlDecl{attributes = Attrs}) ->
- %% [32] SDDecl
+ %% [32] SDDecl
?bump_col(10),
{T1, S1} = scan_eq(T, S),
{StValue,T2,S2}=scan_standalone_value(T1,S1),
@@ -852,8 +911,8 @@ scan_xml_decl3("standalone" ++ T,S0 = #xmerl_scanner{event_fun = Event},
value = StValue},
Decl = Decl0#xmlDecl{standalone = StValue,
attributes = [Attr|Attrs]},
- S3 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
- line = S0#xmerl_scanner.line,
+ S3 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
+ line = S0#xmerl_scanner.line,
col = S0#xmerl_scanner.col,
data = Attr}, S2),
{_,T3,S4} = strip(T2,S3),
@@ -874,7 +933,7 @@ return_xml_decl(T,S=#xmerl_scanner{hook_fun = _Hook,
%% {Ret, S3} = Hook(Decl, S2),
%% {Ret, T1, S3}.
{Decl, T1, S2}.
-
+
scan_standalone_value("'yes'" ++T,S0)->
?bump_col(5),
@@ -917,7 +976,7 @@ scan_text_decl(T,S=#xmerl_scanner{event_fun = Event}) ->
scan_text_decl(T5,S6,Decl).
scan_text_decl("?>"++T,S0 = #xmerl_scanner{hook_fun = _Hook,
- event_fun = Event},
+ event_fun = Event},
Decl0 = #xmlDecl{attributes = Attrs}) ->
?bump_col(2),
?strip1,
@@ -942,7 +1001,7 @@ scan_optional_version("version"++T,S0) ->
{#xmlDecl{attributes=[Attr]},T4,S4};
scan_optional_version(T,S) ->
{#xmlDecl{attributes=[]},T,S}.
-
+
%%%%%%% [81] EncName
@@ -951,7 +1010,7 @@ scan_enc_name([], S=#xmerl_scanner{continuation_fun = F}) ->
F(fun(MoreBytes, S1) -> scan_enc_name(MoreBytes, S1) end,
fun(S1) -> ?fatal(expected_encoding_name, S1) end,
S);
-scan_enc_name([H|T], S0) when H >= $"; H =< $' ->
+scan_enc_name([H|T], S0) when H >= $"; H =< $' ->
?bump_col(1),
scan_enc_name(T, S, H, []).
@@ -1004,7 +1063,7 @@ scan_xml_vsn([H|T], S) when H==$"; H==$'->
xml_vsn([], S=#xmerl_scanner{continuation_fun = F}, Delim, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> xml_vsn(MoreBytes, S1, Delim, Acc) end,
+ F(fun(MoreBytes, S1) -> xml_vsn(MoreBytes, S1, Delim, Acc) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
xml_vsn([H|T], S=#xmerl_scanner{col = C}, H, Acc) ->
@@ -1025,50 +1084,53 @@ xml_vsn([H|T], S=#xmerl_scanner{col = C}, Delim, Acc) ->
%%%%%%% [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
-scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Pos) ->
+scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Pos, Ps) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Pos) end,
+ F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Pos, Ps) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
-scan_pi(Str = [H1,H2,H3 | T],S0=#xmerl_scanner{line = L, col = C}, Pos)
+scan_pi(Str = [H1,H2,H3 | T],S0=#xmerl_scanner{line = L, col = C}, Pos, Ps)
when H1==$x;H1==$X ->
%% names beginning with [xX][mM][lL] are reserved for future use.
?bump_col(3),
- if
+ if
((H2==$m) or (H2==$M)) and
((H3==$l) or (H3==$L)) ->
- scan_wellknown_pi(T,S,Pos);
+ scan_wellknown_pi(T,S,Pos,Ps);
true ->
{Target, _NamespaceInfo, T1, S1} = scan_name(Str, S),
- scan_pi(T1, S1, Target, L, C, Pos, [])
+ scan_pi(T1, S1, Target, L, C, Pos, Ps, [])
end;
-scan_pi(Str, S=#xmerl_scanner{line = L, col = C}, Pos) ->
+scan_pi(Str, S=#xmerl_scanner{line = L, col = C}, Pos, Ps) ->
{Target, _NamespaceInfo, T1, S1} = scan_name(Str, S),
- scan_pi(T1, S1, Target, L, C, Pos,[]).
+ scan_pi(T1, S1, Target, L, C, Pos, Ps, []).
%%% More info on xml-stylesheet can be found at:
%%% "Associating Style Sheets with XML documents", Version 1.0,
%%% W3C Recommendation 29 June 1999 (http://www.w3.org/TR/xml-stylesheet/)
-scan_wellknown_pi("-stylesheet"++T, S0=#xmerl_scanner{line=L,col=C},Pos) ->
+scan_wellknown_pi("-stylesheet"++T, S0=#xmerl_scanner{line=L,col=C},Pos,Ps) ->
?dbg("prolog(\"<?xml-stylesheet\")~n", []),
?bump_col(16),
- scan_pi(T, S, "xml-stylesheet",L,C,Pos,[]);
-scan_wellknown_pi(Str,S,_Pos) ->
+ scan_pi(T, S, "xml-stylesheet",L,C,Pos,Ps,[]);
+scan_wellknown_pi(Str,S,_Pos,_Ps) ->
?fatal({invalid_target_name, lists:sublist(Str, 1, 10)}, S).
-scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Target,L, C, Pos, Acc) ->
+scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Target,
+ L, C, Pos, Ps, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Target, L, C, Pos, Acc) end,
+ F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Target,
+ L, C, Pos, Ps, Acc) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_pi("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
- event_fun = Event},
- Target, L, C, Pos, Acc) ->
+ event_fun = Event},
+ Target, L, C, Pos, Ps, Acc) ->
?bump_col(2),
PI = #xmlPI{name = Target,
+ parents = Ps,
pos = Pos,
value = lists:reverse(Acc)},
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
@@ -1077,22 +1139,25 @@ scan_pi("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
data = PI}, S),
{Ret, S2} = Hook(PI, S1),
{Ret, T, S2};
-scan_pi([H|T], S, Target, L, C, Pos, Acc) when ?whitespace(H) ->
+scan_pi([H|T], S, Target, L, C, Pos, Ps, Acc) when ?whitespace(H) ->
?strip1,
- scan_pi2(T1, S1, Target, L, C, Pos, Acc);
-scan_pi([H|_T],S,_Target, _L, _C, _Pos, _Acc) ->
+ scan_pi2(T1, S1, Target, L, C, Pos, Ps, Acc);
+scan_pi([H|_T],S,_Target, _L, _C, _Pos, _Ps, _Acc) ->
?fatal({expected_whitespace_OR_end_of_PI,{char,H}}, S).
-scan_pi2([], S=#xmerl_scanner{continuation_fun = F}, Target,L, C, Pos, Acc) ->
+scan_pi2([], S=#xmerl_scanner{continuation_fun = F}, Target,
+ L, C, Pos, Ps, Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_pi2(MoreBytes, S1, Target, L, C, Pos, Acc) end,
+ F(fun(MoreBytes, S1) -> scan_pi2(MoreBytes, S1, Target,
+ L, C, Pos, Ps, Acc) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_pi2("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
- event_fun = Event},
- Target, L, C, Pos, Acc) ->
+ event_fun = Event},
+ Target, L, C, Pos, Ps, Acc) ->
?bump_col(2),
PI = #xmlPI{name = Target,
+ parents = Ps,
pos = Pos,
value = lists:reverse(Acc)},
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
@@ -1101,14 +1166,14 @@ scan_pi2("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
data = PI}, S),
{Ret, S2} = Hook(PI, S1),
{Ret, T, S2};
-scan_pi2(Str, S0, Target, L, C, Pos, Acc) ->
+scan_pi2(Str, S0, Target, L, C, Pos, Ps, Acc) ->
?bump_col(1),
{Ch,T} = wfc_legal_char(Str,S),
- scan_pi2(T, S, Target, L, C, Pos, [Ch|Acc]).
+ scan_pi2(T, S, Target, L, C, Pos, Ps, [Ch|Acc]).
-%% [28] doctypedecl ::=
+%% [28] doctypedecl ::=
%% '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'
scan_doctype([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
@@ -1214,7 +1279,7 @@ fetch_DTD(undefined, S) ->
S;
% fetch_DTD(_,S=#xmerl_scanner{validation=false}) ->
% S;
-fetch_DTD(DTDSpec, S)->
+fetch_DTD(DTDSpec, S)->
case fetch_and_parse(DTDSpec,S,[{text_decl,true},
{environment,{external,subset}}]) of
NewS when is_record(NewS,xmerl_scanner) ->
@@ -1229,7 +1294,7 @@ fetch_and_parse(ExtSpec,S=#xmerl_scanner{fetch_fun=Fetch,
Options0) ->
RetS =
case Fetch(ExtSpec, S) of
- {ok, NewS} ->
+ {ok, NewS} ->
%% For backward compatibility only. This will be removed later!!
NewS;
{ok, not_fetched,NewS} ->
@@ -1294,7 +1359,7 @@ fetch_not_parse(ExtSpec,S=#xmerl_scanner{fetch_fun=Fetch}) ->
{ok, DataRet, NewS} ->
{String,LocationName} =
case DataRet of
- {file,F} ->
+ {file,F} ->
{get_file(F,S),F};
{string,Str} ->
{binary_to_list(Str),file_name_unknown};
@@ -1310,7 +1375,7 @@ fetch_not_parse(ExtSpec,S=#xmerl_scanner{fetch_fun=Fetch}) ->
get_file(F,S) ->
% io:format("get_file F=~p~n",[F]),
case file:read_file(F) of
- {ok,Bin} ->
+ {ok,Bin} ->
binary_to_list(Bin);
Err ->
?fatal({error_reading_file,F,Err},S)
@@ -1325,7 +1390,7 @@ check_decl(#xmerl_scanner{rules=Tab} = S) ->
check_notations(Tab,S),
check_elements(Tab,S), %% check also attribute defs for element
check_entities(Tab,S).
-
+
check_notations(Tab,S) ->
case ets:match(Tab,{{notation,'$1'},undeclared}) of
[[]] -> ok;
@@ -1374,7 +1439,7 @@ check_attributes([{N1,'ID',_,_,_}=Attr|Rest],S) ->
check_attributes([{_,{enumeration,_},_,_,_}=Attr|T],S) ->
vc_Enumeration(Attr,S),
check_attributes(T,S);
-check_attributes([{_,Ent,_,_,_}=Attr|T],S)
+check_attributes([{_,Ent,_,_,_}=Attr|T],S)
when Ent=='ENTITY';Ent=='ENTITIES' ->
vc_Entity_Name(Attr,S),
check_attributes(T,S);
@@ -1418,7 +1483,7 @@ scan_ext_subset([], S=#xmerl_scanner{continuation_fun = F}) ->
F(fun(MoreBytes, S1) -> scan_ext_subset(MoreBytes, S1) end,
fun(S1) -> {[], S1} end,
S);
-scan_ext_subset("%" ++ T, S0) ->
+scan_ext_subset("%" ++ T, S0) ->
%% DeclSep [28a]: WFC: PE Between Declarations.
%% The replacement text of a parameter entity reference in a
%% DeclSep must match the production extSubsetDecl.
@@ -1472,7 +1537,7 @@ scan_decl_sep(T,S) ->
% {" " ++ EntV2 ++ " ",_S3};
% ExpRef ->
% {ExpRef,S1}
-% end,
+% end,
% {_, T3, S3} = strip(ExpandedRef,S2),
% {_T4,S4} = scan_ext_subset(T3,S3),
% strip(T1,S4).
@@ -1558,7 +1623,7 @@ scan_include(T, S) ->
scan_include(T1, S1).
-%%%%%%% [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
+%%%%%%% [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
%%%%%%% NotationDecl | PI |Comment
%%%%%%% [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
@@ -1575,16 +1640,16 @@ scan_markup_decl("<!--" ++ T, S0) ->
scan_comment(T, S);
scan_markup_decl("<?" ++ T, S0) ->
?bump_col(2),
- {_PI, T1, S1} = scan_pi(T, S,_Pos=markup),
+ {_PI, T1, S1} = scan_pi(T, S,_Pos=markup,[]),
strip(T1, S1);
-scan_markup_decl("<!ELEMENT" ++ T,
+scan_markup_decl("<!ELEMENT" ++ T,
#xmerl_scanner{rules_read_fun = Read,
rules_write_fun = Write,
rules_delete_fun = Delete} = S0) ->
?bump_col(9),
{_,T1,S1} = mandatory_strip(T,S),
{Ename, _NamespaceInfo, T2, S2} = scan_name(T1, S1),
- Element =
+ Element =
case Read(elem_def, Ename, S2) of
El = #xmlElement{elementdef=Decl} when Decl =/= undeclared ->
case S2#xmerl_scanner.validation of
@@ -1625,7 +1690,7 @@ scan_markup_decl("<!NOTATION" ++ T, S0) ->
{_,T1,S1} = mandatory_strip(T,S),
{T2, S2} = scan_notation_decl(T1, S1),
strip(T2,S2);
-scan_markup_decl("<!ATTLIST" ++ T,
+scan_markup_decl("<!ATTLIST" ++ T,
#xmerl_scanner{rules_read_fun = Read,
rules_write_fun = Write,
rules_delete_fun= Delete} = S0) ->
@@ -1642,7 +1707,7 @@ scan_markup_decl("<!ATTLIST" ++ T,
%% internal DTD.
{#xmlElement{},update_attributes(Attributes,[])};
Edef = #xmlElement{attributes = OldAttrs} ->
- Delete(elem_def,Ename,S4),
+ Delete(elem_def,Ename,S4),
%% the slot in rules table must be empty so that the
%% later write has the assumed effect. Read maybe
%% should empty the table slot.
@@ -1661,7 +1726,7 @@ scan_element_completion(T,S) ->
update_attributes(NewAttrs, OldAttrs) ->
update_attributes1(NewAttrs,lists:reverse(OldAttrs)).
-update_attributes1([A = {Name,_Type,_DefaultV,_DefaultD,_Env}|Attrs],
+update_attributes1([A = {Name,_Type,_DefaultV,_DefaultD,_Env}|Attrs],
OldAttrs) ->
case lists:keymember(Name, 1, OldAttrs) of
true ->
@@ -1802,7 +1867,7 @@ scan_notation_type("|" ++ T, S0, Acc) ->
?strip3,
scan_notation_type(T3, S3, [Name | Acc]).
-%%% Validity constraint for NotationType:
+%%% Validity constraint for NotationType:
%%% The used notation names must be declared in the DTD, but they may
%%% be declared later.
notation_exists(Name, #xmerl_scanner{rules_read_fun = Read,
@@ -1931,7 +1996,7 @@ scan_entity_def(Str, S, EName) ->
{environment,{external,{entity,EName}}}]) of
{{_USret,Entity},_Tail,_Sx} ->
{Entity, external,T2, S2};
- {Entity,_Tail,Sx} ->
+ {Entity,_Tail,Sx} ->
OldRef=S2#xmerl_scanner.entity_references,
NewRef=Sx#xmerl_scanner.entity_references,
{Entity,external,T2,
@@ -1981,28 +2046,28 @@ scan_element(T, S, Pos) ->
scan_element(T, S=#xmerl_scanner{line=L,col=C},
Pos, SpaceDefault,Lang, Parents, NS) ->
{Name, NamespaceInfo, T1, S1} = scan_name(T, S),
- vc_Element_valid(Name,S),
+ vc_Element_valid(Name,NamespaceInfo,S),
?strip2,
- scan_element(T2, S2, Pos, Name, L, C, _Attrs = [],
- Lang, Parents, NamespaceInfo, NS,
+ scan_element(T2, S2, Pos, Name, L, C, _Attrs = [],
+ Lang, Parents, NamespaceInfo, NS,
SpaceDefault).
scan_element("/", S=#xmerl_scanner{continuation_fun = F},
- Pos, Name, StartL, StartC, Attrs, Lang, Parents,
+ Pos, Name, StartL, StartC, Attrs, Lang, Parents,
NSI, NS, SpaceDefault) ->
?dbg("trailing / detected~n", []),
- F(fun(MoreBytes, S1) -> scan_element("/" ++ MoreBytes, S1,
- Pos, Name, StartL, StartC, Attrs,
+ F(fun(MoreBytes, S1) -> scan_element("/" ++ MoreBytes, S1,
+ Pos, Name, StartL, StartC, Attrs,
Lang,Parents,NSI,NS,SpaceDefault) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
-scan_element([], S=#xmerl_scanner{continuation_fun = F},
- Pos, Name, StartL, StartC, Attrs, Lang, Parents,
+scan_element([], S=#xmerl_scanner{continuation_fun = F},
+ Pos, Name, StartL, StartC, Attrs, Lang, Parents,
NSI, NS, SpaceDefault) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_element(MoreBytes, S1,
- Pos, Name, StartL, StartC, Attrs,
+ F(fun(MoreBytes, S1) -> scan_element(MoreBytes, S1,
+ Pos, Name, StartL, StartC, Attrs,
Lang,Parents,NSI,NS,SpaceDefault) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
@@ -2010,13 +2075,14 @@ scan_element("/>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
event_fun = Event,
line = L, col = C,
xmlbase_cache=XMLBase}, Pos,
- Name, _StartL, _StartC, Attrs0, Lang, Parents, NSI,
+ Name, _StartL, _StartC, Attrs0, Lang, Parents, NSI,
Namespace, _SpaceDefault) ->
?bump_col(2),
Attrs = lists:reverse(Attrs0),
E=processed_whole_element(S, Pos, Name, Attrs, Lang, Parents,NSI,Namespace),
-
- wfc_unique_att_spec(Attrs,S),
+
+ #xmlElement{attributes = Attrs1} = E,
+ wfc_unique_att_spec(Attrs1,S),
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
line = L,
col = C,
@@ -2025,11 +2091,11 @@ scan_element("/>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
S2b=S2#xmerl_scanner{xmlbase=XMLBase},
{Ret, T, S2b};
scan_element(">", S=#xmerl_scanner{continuation_fun = F},
- Pos, Name, StartL, StartC, Attrs, Lang, Parents,
+ Pos, Name, StartL, StartC, Attrs, Lang, Parents,
NSI, NS, SpaceDefault) ->
?dbg("trailing > detected~n", []),
- F(fun(MoreBytes, S1) -> scan_element(">" ++ MoreBytes, S1,
- Pos, Name, StartL, StartC, Attrs,
+ F(fun(MoreBytes, S1) -> scan_element(">" ++ MoreBytes, S1,
+ Pos, Name, StartL, StartC, Attrs,
Lang,Parents,NSI,NS,SpaceDefault) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
@@ -2038,28 +2104,31 @@ scan_element(">" ++ T, S0 = #xmerl_scanner{event_fun = Event,
line = L, col = C,
xmlbase_cache=XMLBase,
space = SpaceOption},
- Pos, Name, StartL, StartC, Attrs0, Lang, Parents,
+ Pos, Name, StartL, StartC, Attrs0, Lang, Parents,
NSI, Namespace, SpaceDefault) ->
?bump_col(1),
Attrs = lists:reverse(Attrs0),
- wfc_unique_att_spec(Attrs,S),
- XMLSpace = case lists:keysearch('xml:space', #xmlAttribute.name, Attrs) of
+ E0=processed_whole_element(S,Pos,Name,Attrs,Lang,Parents,NSI,Namespace),
+
+ #xmlElement{attributes = Attrs1} = E0,
+ wfc_unique_att_spec(Attrs1,S),
+ XMLSpace = case lists:keysearch('xml:space', #xmlAttribute.name, Attrs1) of
false -> SpaceDefault;
{value, #xmlAttribute{value="default"}} -> SpaceOption;
{value, #xmlAttribute{value="preserve"}} -> preserve;
_ -> SpaceDefault
end,
-
- E0=processed_whole_element(S,Pos,Name,Attrs,Lang,Parents,NSI,Namespace),
+
+ E0=processed_whole_element(S,Pos,Name,Attrs1,Lang,Parents,NSI,Namespace),
S1 = #xmerl_scanner{} = Event(#xmerl_event{event = started,
line = StartL,
col = StartC,
data = E0}, S),
-
- {Content, T1, S2} = scan_content(T, S1, Name, Attrs, XMLSpace,
+
+ {Content, T1, S2} = scan_content(T, S1, Name, Attrs1, XMLSpace,
E0#xmlElement.language,
[{Name, Pos}|Parents], Namespace),
-
+
Element=E0#xmlElement{content=Content,
xmlbase=E0#xmlElement.xmlbase},
S3 = #xmerl_scanner{} = Event(#xmerl_event{event = ended,
@@ -2069,7 +2138,7 @@ scan_element(">" ++ T, S0 = #xmerl_scanner{event_fun = Event,
{Ret, S4} = Hook(Element, S3),
S4b=S4#xmerl_scanner{xmlbase=XMLBase},
{Ret, T1, S4b};
-scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
+scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
NSI, NS, SpaceDefault) ->
{AttName, NamespaceInfo, T1, S1} = scan_name(T, S),
{T2, S2} = scan_eq(T1, S1),
@@ -2078,26 +2147,27 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
%% check_default_value(S3,DefaultDecl,AttValue),
NewNS = check_namespace(AttName, NamespaceInfo, AttValue, NS),
{T3,S3} = wfc_whitespace_betw_attrs(T3a,S3a),
- ?strip4,
+ ?strip4,
AttrPos = case Attrs of
[] ->
1;
[#xmlAttribute{pos = P}|_] ->
P+1
end,
- Attr = #xmlAttribute{name = AttName,
+ Attr = #xmlAttribute{name = AttName,
+ parents = [{Name, Pos}|Parents],
pos = AttrPos,
language = Lang,
- namespace = NamespaceInfo,
+ nsinfo = NamespaceInfo,
value = AttValue,
normalized = IsNorm},
XMLBase=if
AttName=='xml:base' ->
resolve_relative_uri(AttValue,S4#xmerl_scanner.xmlbase);
- true ->
+ true ->
S4#xmerl_scanner.xmlbase
end,
-
+
#xmerl_scanner{event_fun = Event,
line = Line,
col = Col} = S4,
@@ -2107,9 +2177,17 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
data = Attr},
S4#xmerl_scanner{xmlbase=XMLBase,
xmlbase_cache=S#xmerl_scanner.xmlbase}),
- scan_element(T4, S5, Pos, Name, StartL, StartC, [Attr|Attrs],
+ scan_element(T4, S5, Pos, Name, StartL, StartC, [Attr|Attrs],
Lang, Parents, NSI, NewNS, SpaceDefault).
+get_default_attrs(S = #xmerl_scanner{rules_read_fun = Read}, ElemName) ->
+ case Read(elem_def, ElemName, S) of
+ #xmlElement{attributes = Attrs} ->
+ [ {AttName, AttValue} ||
+ {AttName, _, AttValue, _, _} <- Attrs, AttValue =/= no_value ];
+ _ -> []
+ end.
+
get_att_type(S=#xmerl_scanner{rules_read_fun=Read},AttName,ElemName) ->
case Read(elem_def,ElemName,S) of
#xmlElement{attributes = Attrs} ->
@@ -2135,11 +2213,28 @@ resolve_relative_uri(NewBase,CurrentBase) ->
processed_whole_element(S=#xmerl_scanner{hook_fun = _Hook,
xmlbase = XMLBase,
line = _L, col = _C,
- event_fun = _Event},
+ event_fun = _Event},
Pos, Name, Attrs, Lang, Parents, NSI, Namespace) ->
Language = check_language(Attrs, Lang),
- {ExpName, ExpAttrs} =
+ AllAttrs =
+ case S#xmerl_scanner.default_attrs of
+ true ->
+ [ #xmlAttribute{name = AttName,
+ parents = [{Name, Pos} | Parents],
+ language = Lang,
+ nsinfo = NSI,
+ namespace = Namespace,
+ value = AttValue,
+ normalized = true} ||
+ {AttName, AttValue} <- get_default_attrs(S, Name),
+ AttValue =/= no_value,
+ not lists:keymember(AttName, #xmlAttribute.name, Attrs) ];
+ false ->
+ Attrs
+ end,
+
+ {ExpName, ExpAttrs} =
case S#xmerl_scanner.namespace_conformant of
true ->
%% expand attribute names. We need to do this after having
@@ -2151,16 +2246,17 @@ processed_whole_element(S=#xmerl_scanner{hook_fun = _Hook,
%% should apply to those attributes as well.
%% Note that the default URI does not apply to attrbute names.
TempNamespace = Namespace#xmlNamespace{default = []},
- ExpAttrsX =
+ ExpAttrsX =
[A#xmlAttribute{
+ namespace=Namespace,
expanded_name=expanded_name(
- A#xmlAttribute.name,
- A#xmlAttribute.namespace,
+ A#xmlAttribute.name,
+ A#xmlAttribute.nsinfo,
% NSI,
- TempNamespace, S)} || A <- Attrs],
+ TempNamespace, S)} || A <- AllAttrs],
{expanded_name(Name, NSI, Namespace, S), ExpAttrsX};
false ->
- {Name, Attrs}
+ {Name, AllAttrs}
end,
#xmlElement{name = Name,
@@ -2184,7 +2280,7 @@ check_language([], Lang) ->
check_namespace(xmlns, _, Value, NS) ->
NS#xmlNamespace{default = list_to_atom(Value)};
-check_namespace(_, {"xmlns", Prefix}, Value,
+check_namespace(_, {"xmlns", Prefix}, Value,
NS = #xmlNamespace{nodes = Ns}) ->
NS#xmlNamespace{nodes = keyreplaceadd(
Prefix, 1, Ns, {Prefix, list_to_atom(Value)})};
@@ -2194,10 +2290,32 @@ check_namespace(_, _, _, NS) ->
expanded_name(Name, [], #xmlNamespace{default = []}, _S) ->
Name;
-expanded_name(Name, [], #xmlNamespace{default = URI}, _S) ->
- {URI, Name};
-expanded_name(_Name, {"xmlns", Local}, _NS, _S) -> % CHECK THIS /JB
- {"xmlns",Local};
+expanded_name(Name, [], #xmlNamespace{default = URI}, S) ->
+ case URI of
+ 'http://www.w3.org/XML/1998/namespace' ->
+ ?fatal(cannot_bind_default_namespace_to_xml_namespace_name, S);
+ 'http://www.w3.org/2000/xmlns/' ->
+ ?fatal(cannot_bind_default_namespace_to_xmlns_namespace_name, S);
+ _ ->
+ {URI, Name}
+ end;
+expanded_name(Name, N = {"xmlns", Local}, #xmlNamespace{nodes = Ns}, S) ->
+ {_, Value} = lists:keyfind(Local, 1, Ns),
+ case Name of
+ 'xmlns:xml' when Value =/= 'http://www.w3.org/XML/1998/namespace' ->
+ ?fatal({xml_prefix_cannot_be_redeclared, Value}, S);
+ 'xmlns:xmlns' ->
+ ?fatal({xmlns_prefix_cannot_be_declared, Value}, S);
+ _ ->
+ case Value of
+ 'http://www.w3.org/XML/1998/namespace' ->
+ ?fatal({cannot_bind_prefix_to_xml_namespace, Local}, S);
+ 'http://www.w3.org/2000/xmlns/' ->
+ ?fatal({cannot_bind_prefix_to_xmlns_namespace, Local}, S);
+ _ ->
+ N
+ end
+ end;
expanded_name(_Name, {Prefix, Local}, #xmlNamespace{nodes = Ns}, S) ->
case lists:keysearch(Prefix, 1, Ns) of
{value, {_, URI}} ->
@@ -2207,7 +2325,7 @@ expanded_name(_Name, {Prefix, Local}, #xmlNamespace{nodes = Ns}, S) ->
%% must be declared
?fatal({namespace_prefix_not_declared, Prefix}, S)
end.
-
+
@@ -2233,7 +2351,7 @@ scan_att_value("%"++T,S0=#xmerl_scanner{rules_read_fun=Read,
rules_delete_fun=Delete},AttType) ->
?bump_col(1),
{Name,T1,S1} = scan_pe_reference(T,S),
- {ExpandedRef,S2} =
+ {ExpandedRef,S2} =
case expand_pe_reference(Name,S1,in_literal) of
Tuple when is_tuple(Tuple) ->
%% {system,URI} or {public,URI}
@@ -2271,9 +2389,9 @@ scan_att_chars([H|T], S0, H, Acc, TmpAcc,AttType,IsNorm) -> % End quote
?bump_col(1),
check_att_default_val(S#xmerl_scanner.validation,TmpAcc,AttType,S),
{Acc2,S2,IsNorm2} =
- if
+ if
AttType == 'CDATA' -> {Acc,S,IsNorm};
- true ->
+ true ->
normalize(Acc,S,IsNorm)
end,
{lists:flatten(lists:reverse(Acc2)), T, S2,IsNorm2};
@@ -2328,7 +2446,7 @@ check_att_default_val(dtd,RevName,Ent,S) ->
check_att_default_val(_,_,_,_) ->
ok.
-check_att_default_val(Name,Ent,S=#xmerl_scanner{rules_write_fun=Write})
+check_att_default_val(Name,Ent,S=#xmerl_scanner{rules_write_fun=Write})
when Ent == 'ENTITY'; Ent == 'ENTITIES' ->
case xmerl_lib:is_letter(hd(Name)) of
true -> ok;
@@ -2389,28 +2507,28 @@ valid_Char(_,_,C,S) ->
%%%%%%% [43] content
scan_content(T, S, Name, Attrs, Space, Lang, Parents, NS) ->
- scan_content(T, S, _Pos = 1, Name, Attrs, Space,
+ scan_content(T, S, _Pos = 1, Name, Attrs, Space,
Lang, Parents, NS, _Acc = [],_MarkupDel=[]).
scan_content("<", S= #xmerl_scanner{continuation_fun = F},
Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,_) ->
?dbg("trailing < detected~n", []),
- F(fun(MoreBytes, S1) -> scan_content("<" ++ MoreBytes, S1,
- Pos, Name, Attrs,
+ F(fun(MoreBytes, S1) -> scan_content("<" ++ MoreBytes, S1,
+ Pos, Name, Attrs,
Space, Lang, Parents, NS, Acc,[]) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
-scan_content([], S=#xmerl_scanner{environment={external,{entity,_}}},
+scan_content([], S=#xmerl_scanner{environment={external,{entity,_}}},
_Pos, _Name, _Attrs, _Space, _Lang, _Parents, _NS, Acc,_) ->
{lists:reverse(Acc),[],S};
-scan_content([], S=#xmerl_scanner{environment=internal_parsed_entity},
+scan_content([], S=#xmerl_scanner{environment=internal_parsed_entity},
_Pos, _Name, _Attrs, _Space, _Lang, _Parents, _NS, Acc,_) ->
{lists:reverse(Acc),[],S};
-scan_content([], S=#xmerl_scanner{continuation_fun = F},
+scan_content([], S=#xmerl_scanner{continuation_fun = F},
Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,_) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_content(MoreBytes, S1,
- Pos, Name, Attrs,
+ F(fun(MoreBytes, S1) -> scan_content(MoreBytes, S1,
+ Pos, Name, Attrs,
Space, Lang, Parents, NS, Acc,[]) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
@@ -2427,10 +2545,10 @@ scan_content("</" ++ T, S0, _Pos, Name, _Attrs, _Space, _Lang,
case T2 of
">" ++ T3 ->
{lists:reverse(Acc), T3, S2};
- _ ->
+ _ ->
?fatal({error,{unexpected_end_of_STag}},S)
end;
-scan_content([$&|_T]=Str,
+scan_content([$&|_T]=Str,
#xmerl_scanner{environment={external,{entity,EName}}} = S0,
Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,_) ->
{_EntV,T1,S1}=scan_entity_value(Str,S0 ,[],EName,general),
@@ -2449,12 +2567,26 @@ scan_content("&" ++ T, S0, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]) -
_ ->
scan_content(string_to_char_set(S1#xmerl_scanner.encoding,ExpRef)++T1,S1,Pos,Name,Attrs,Space,Lang,Parents,NS,Acc,[])
end;
-scan_content("<!--" ++ T, S, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]) ->
- {_, T1, S1} = scan_comment(T, S, Pos, Parents, Lang),
- scan_content(T1, S1, Pos+1, Name, Attrs, Space, Lang, Parents, NS, Acc,[]);
+scan_content("<!--" ++ T, S0=#xmerl_scanner{acc_fun = F, comments=CF}, Pos, Name, Attrs, Space,
+ Lang, Parents, NS, Acc,[]) ->
+ ?bump_col(4),
+ {C, T1, S1} = scan_comment(T, S, Pos, Parents, Lang),
+ case CF of
+ true ->
+ {Acc2, Pos2, S3} =
+ case F(C, Acc, S1) of
+ {Acc1, S2} ->
+ {Acc1, Pos + 1, S2};
+ {Acc1, Pos1, S2} ->
+ {Acc1, Pos1, S2}
+ end,
+ scan_content(T1, S3, Pos2, Name, Attrs, Space, Lang, Parents, NS, Acc2,[]);
+ false ->
+ scan_content(T1, S1, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[])
+ end;
scan_content("<" ++ T, S0, Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]) ->
?bump_col(1),
- {Markup, T1, S1} =
+ {Markup, T1, S1} =
scan_content_markup(T, S, Pos, Name, Attrs, Space, Lang, Parents, NS),
AccF = S1#xmerl_scanner.acc_fun,
{NewAcc, NewPos, NewS} = case AccF(Markup, Acc, S1) of
@@ -2470,10 +2602,10 @@ scan_content([_H|T], S= #xmerl_scanner{environment={external,{entity,_}}},
%% Guess we have to scan the content to find any internal entity
%% references.
scan_content(T,S,Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,[]);
-scan_content(T, S=#xmerl_scanner{acc_fun = F,
+scan_content(T, S=#xmerl_scanner{acc_fun = F,
event_fun = Event,
hook_fun=Hook,
- line = _L},
+ line = _L},
Pos, Name, Attrs, Space, Lang, Parents, NS, Acc,MarkupDel) ->
Text0 = #xmlText{pos = Pos,
parents = Parents},
@@ -2496,7 +2628,7 @@ scan_content(T, S=#xmerl_scanner{acc_fun = F,
Parents, NS, NewAcc,[]).
-scan_content_markup([], S=#xmerl_scanner{continuation_fun = F},
+scan_content_markup([], S=#xmerl_scanner{continuation_fun = F},
Pos, Name, Attrs, Space, Lang, Parents, NS) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_content_markup(
@@ -2508,9 +2640,9 @@ scan_content_markup("![CDATA[" ++ T, S0, Pos, _Name, _Attrs,
_Space, _Lang, Parents, _NS) ->
?bump_col(8),
scan_cdata(T, S, Pos, Parents);
-scan_content_markup("?"++T,S0,Pos,_Name,_Attrs,_Space,_Lang,_Parents,_NS) ->
+scan_content_markup("?"++T,S0,Pos,_Name,_Attrs,_Space,_Lang,Parents,_NS) ->
?bump_col(1),
- scan_pi(T, S, Pos);
+ scan_pi(T, S, Pos, Parents);
scan_content_markup(T, S, Pos, _Name, _Attrs, Space, Lang, Parents, NS) ->
scan_element(T, S, Pos, Space, Lang, Parents, NS).
@@ -2521,21 +2653,21 @@ scan_char_data(T, S, Space,MUD) ->
scan_char_data([], S=#xmerl_scanner{environment={external,{entity,_}}},
_Space,_MUD, Acc) ->
-
+
{lists:reverse(Acc), [], S};
scan_char_data([], S=#xmerl_scanner{environment=internal_parsed_entity},
_Space, _MUD,Acc) ->
-
+
{lists:reverse(Acc), [], S};
scan_char_data([], S=#xmerl_scanner{continuation_fun = F}, Space, _MUD,Acc) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_char_data(MoreBytes,S1,Space,_MUD,Acc) end,
+ F(fun(MoreBytes, S1) -> scan_char_data(MoreBytes,S1,Space,_MUD,Acc) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_char_data([$&|T], S,Space,"&",Acc) ->
scan_char_data(T, S, Space,[], [$&|Acc]);
scan_char_data(T=[$&|_], S,_Space,_MUD,Acc) ->
-
+
{lists:reverse(Acc), T, S};
scan_char_data("]]>" ++ _T, S, _Space,_MUD, _Acc) ->
%% See Section 2.4: Especially:
@@ -2547,7 +2679,7 @@ scan_char_data("]]>" ++ _T, S, _Space,_MUD, _Acc) ->
scan_char_data([$<|T],S,Space,"<", Acc) ->
scan_char_data(T, S, Space,[], [$<|Acc]);
scan_char_data(T = [$<|_], S, _Space,_MUD,Acc) ->
-
+
{lists:reverse(Acc), T, S};
scan_char_data(T = [H|R], S, Space,MUD, Acc) when ?whitespace(H) ->
if
@@ -2640,7 +2772,7 @@ scan_reference(T, S) ->
%% ampersand is not recognized as an entity-reference delimiter.)"
%%
%% How to achieve this? My current approach is to insert the *strings* "&",
-%% "<", ">", "'", and "\"" instead of the characters. The processor will
+%% "<", ">", "'", and "\"" instead of the characters. The processor will
%% ignore them when performing multiple expansions. This means, for now, that
%% the character data output by the processor is (1-2 levels) deep.
%% At some suitable point, we should flatten these, so that application-level
@@ -2669,7 +2801,7 @@ scan_entity_ref("quot;" ++ T, S0) ->
scan_entity_ref(T, S) ->
{Name, _NamespaceInfo, T1, S1} = scan_name(T, S),
T2 = scan_mandatory(";",T1,1,S1,expected_entity_reference_semicolon),
-% ";" ++ T2 = T1,
+% ";" ++ T2 = T1,
S2 = S1,
Entity = expand_reference(Name, S2),
{Entity, T2, S2}.
@@ -2680,7 +2812,7 @@ scan_entity_ref(T, S) ->
scan_pe_reference(T, S) ->
{Name, _NamespaceInfo, T1, S1} = scan_name(T, S),
T2 = scan_mandatory(";",T1,1,S1,expected_parsed_entity_reference_semicolon),
-% ";" ++ T2 = T1,
+% ";" ++ T2 = T1,
{Name, T2, S1#xmerl_scanner{col = S1#xmerl_scanner.col+1}}.
expand_pe_reference(Name, #xmerl_scanner{rules_read_fun = Read} = S,WS) ->
@@ -2707,7 +2839,7 @@ expand_pe_reference(Name, #xmerl_scanner{rules_read_fun = Read} = S,WS) ->
% Result ->
% fetch_DTD(Result,S)
% end.
-
+
%%%%%%% [68] EntityReference
@@ -2786,15 +2918,15 @@ scan_eq(T, S) ->
%% scan_name/2
%%
-%% We perform some checks here to make sure that the names conform to
+%% We perform some checks here to make sure that the names conform to
%% the "Namespaces in XML" specification. This is an option.
-%%
+%%
%% Qualified Name:
%% [6] QName ::= (Prefix ':')? LocalPart
%% [7] Prefix ::= NCName
%% [8] LocalPart ::= NCName
%% [4] NCName ::= (Letter | '_') (NCNameChar)*
-%% [5] NCNameChar ::= Letter | Digit | '.' | '-' | '_'
+%% [5] NCNameChar ::= Letter | Digit | '.' | '-' | '_'
%% | CombiningChar | Extender
@@ -2808,9 +2940,9 @@ scan_eq(T, S) ->
%%
scan_name_no_colons(Str, S) ->
NSC = S#xmerl_scanner.namespace_conformant,
- case NSC of
+ case NSC of
true ->
- {Target, NSI, T1, S1} =
+ {Target, NSI, T1, S1} =
scan_name(Str,S#xmerl_scanner{namespace_conformant=no_colons}),
{Target,NSI,T1,S1#xmerl_scanner{namespace_conformant=NSC}};
false ->
@@ -2822,7 +2954,7 @@ scan_name_no_colons(Str, S) ->
%% [5] Name ::= (Letter | '_' | ':') (NameChar)*
scan_name([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_name(MoreBytes, S1) end,
+ F(fun(MoreBytes, S1) -> scan_name(MoreBytes, S1) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_name(Str = [$:|T], S0 = #xmerl_scanner{namespace_conformant = NSC}) ->
@@ -2885,15 +3017,15 @@ scan_nmtoken(Str, S) ->
{Ch,T} = to_ucs(S#xmerl_scanner.encoding,Str),
case xmerl_lib:is_namechar(Ch) of
true ->
- scan_nmtoken(T, S#xmerl_scanner{col = S#xmerl_scanner.col+1},
- _Acc = [Ch], _Prefix = [], _Local = [Ch],
+ scan_nmtoken(T, S#xmerl_scanner{col = S#xmerl_scanner.col+1},
+ _Acc = [Ch], _Prefix = [], _Local = [Ch],
_NamespaceConformant = false,isLatin1(Ch,true));
false ->
?fatal({invalid_nmtoken, lists:sublist(Str, 1, 6)}, S)
end.
-scan_nmtoken([], S=#xmerl_scanner{continuation_fun = F},
+scan_nmtoken([], S=#xmerl_scanner{continuation_fun = F},
Acc, Prefix, Local, NSC,IsLatin1) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_nmtoken(MoreBytes,S1,Acc,Prefix,Local,NSC,IsLatin1) end,
@@ -2907,16 +3039,16 @@ scan_nmtoken(Str = [H|_], S, Acc, Prefix, Local, _NSC,true) when ?whitespace(H)
NmString = lists:reverse(Acc),
{list_to_atom(NmString), namespace_info(Prefix, Local), Str, S};
scan_nmtoken(Str = [$:|_], S, Acc, [], _Local, no_colons,_IsLatin1) ->
- ?fatal({invalid_NCName,
+ ?fatal({invalid_NCName,
lists:sublist(lists:reverse(Acc) ++ Str, 1, 6)}, S);
scan_nmtoken([$:|T], S0, Acc, [], Local, NSC, IsLatin1) ->
?bump_col(1),
scan_nmtoken(T, S, [$:|Acc], lists:reverse(Local), [], NSC,IsLatin1);
scan_nmtoken(Str = [$:|_T], S, Acc, _Prefix, _Local, _NSC = true,_IsLatin1) ->
%% non-empty Prefix means that we've encountered a ":" already.
- %% Conformity with "Namespaces in XML" requires
+ %% Conformity with "Namespaces in XML" requires
%% at most one colon in a name
- ?fatal({invalid_NCName,
+ ?fatal({invalid_NCName,
lists:sublist(lists:reverse(Acc) ++ Str, 1, 6)}, S);
%% non-namechar also marks the end of a name
@@ -2949,7 +3081,7 @@ isLatin1(_,_) ->
scan_system_literal([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
- F(fun(MoreBytes, S1) -> scan_system_literal(MoreBytes, S1) end,
+ F(fun(MoreBytes, S1) -> scan_system_literal(MoreBytes, S1) end,
fun(S1) -> ?fatal(unexpected_end, S1) end,
S);
scan_system_literal("\"" ++ T, S) ->
@@ -2958,7 +3090,7 @@ scan_system_literal("'" ++ T, S) ->
scan_system_literal(T, S, $', []).
-scan_system_literal([], S=#xmerl_scanner{continuation_fun = F},
+scan_system_literal([], S=#xmerl_scanner{continuation_fun = F},
Delimiter, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_system_literal(MoreBytes,S1,Delimiter,Acc) end,
@@ -2971,7 +3103,7 @@ scan_system_literal("#"++_R, S, _H, _Acc) ->
?fatal(fragment_identifier_in_system_literal,S);
scan_system_literal(Str, S, Delimiter, Acc) ->
{Ch,T} = to_ucs(S#xmerl_scanner.encoding,Str),
- scan_system_literal(T, S#xmerl_scanner{col = S#xmerl_scanner.col+1},
+ scan_system_literal(T, S#xmerl_scanner{col = S#xmerl_scanner.col+1},
Delimiter, [Ch|Acc]).
@@ -2988,7 +3120,7 @@ scan_pubid_literal([H|_T], S) ->
?fatal({invalid_pubid_char, H}, S).
-scan_pubid_literal([], S=#xmerl_scanner{continuation_fun = F},
+scan_pubid_literal([], S=#xmerl_scanner{continuation_fun = F},
Delimiter, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pubid_literal(MoreBytes,S1,Delimiter,Acc) end,
@@ -3005,7 +3137,7 @@ scan_pubid_literal([H|T], S, Delimiter, Acc) ->
case is_pubid_char(H) of
true ->
scan_pubid_literal(
- T, S#xmerl_scanner{col = S#xmerl_scanner.col+1},
+ T, S#xmerl_scanner{col = S#xmerl_scanner.col+1},
Delimiter, [H|Acc]);
false ->
?fatal({invalid_pubid_char, H}, S)
@@ -3057,7 +3189,7 @@ scan_contentspec(_Str,S) ->
scan_elem_content(T, S) ->
scan_elem_content(T, S, _Context = children, _Mode = unknown, _Acc = []).
-scan_elem_content([], S=#xmerl_scanner{continuation_fun = F},
+scan_elem_content([], S=#xmerl_scanner{continuation_fun = F},
Context, Mode, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes,S1) -> scan_elem_content(MoreBytes,S1,Context,Mode,Acc) end,
@@ -3078,7 +3210,7 @@ scan_elem_content(")" ++ T, S0, Context, Mode0, Acc0) ->
% more names than '#PCDATA'
% and no '*'.
{'*', mixed,_} -> ok;
- {Other, mixed,_} ->
+ {Other, mixed,_} ->
?fatal({illegal_for_mixed_content, Other}, S1);
_ ->
ok
@@ -3087,7 +3219,7 @@ scan_elem_content(")" ++ T, S0, Context, Mode0, Acc0) ->
{format_elem_content({Occurrence, {Mode, Acc}}), T2, S2};
scan_elem_content("#PCDATA" ++ _T, S, not_mixed, _Mode, _Acc) ->
?fatal({error,{extra_set_of_parenthesis}},S);
-scan_elem_content("#PCDATA" ++ _T, S, _Cont, Mode, Acc)
+scan_elem_content("#PCDATA" ++ _T, S, _Cont, Mode, Acc)
when Mode==choice;Mode==seq;Acc/=[] ->
?fatal({error,{invalid_format_of_mixed_content}},S);
scan_elem_content("#PCDATA" ++ T, S0, _Context, Mode, Acc) ->
@@ -3130,7 +3262,7 @@ scan_elem_content2(T, S, Context, Mode, Acc) ->
{Occurrence, T2, S2} = scan_occurrence(T1, S1),
case {Occurrence, Context} of
{once, mixed} -> ok;
- {Other, mixed} ->
+ {Other, mixed} ->
?fatal({illegal_for_mixed_content, Other}, S1);
_ ->
ok
@@ -3176,17 +3308,17 @@ vc_Valid_Char(_AT,C,S) ->
-vc_ID_Attribute_Default(_,#xmerl_scanner{validation=Valid})
+vc_ID_Attribute_Default(_,#xmerl_scanner{validation=Valid})
when Valid /= dtd ->
- ok;
-vc_ID_Attribute_Default({_,'ID',_,Def,_},_S)
+ ok;
+vc_ID_Attribute_Default({_,'ID',_,Def,_},_S)
when Def=='#IMPLIED';Def=='#REQUIRED' ->
ok;
vc_ID_Attribute_Default({_,'ID',_,Def,_},S) ->
?fatal({error,{validity_constraint_error_ID_Attribute_Default,Def}},S).
-vc_Enumeration({_Name,{_,NameList},DefaultVal,_,_},S)
- when is_list(DefaultVal) ->
+vc_Enumeration({_Name,{_,NameList},DefaultVal,_,_},S)
+ when is_list(DefaultVal) ->
case lists:member(list_to_atom(DefaultVal),NameList) of
true ->
ok;
@@ -3209,12 +3341,12 @@ vc_Entity_Name({_,'ENTITIES',DefaultVal,_,_},S) when is_list(DefaultVal) ->
Read = S#xmerl_scanner.rules_read_fun,
NameListFun = fun([],Acc,_St,_Fun) ->
lists:reverse(Acc);
- (Str,Acc,St,Fun) ->
+ (Str,Acc,St,Fun) ->
{N,_,St2,Str2} = scan_name(Str,St),
Fun(Str2,[N|Acc],St2,Fun)
end,
NameList = NameListFun(DefaultVal,[],S,NameListFun),
- VcFun =
+ VcFun =
fun(X) ->
case Read(entity,X,S) of
{_,external,{_,{ndata,_}}} ->
@@ -3227,7 +3359,7 @@ vc_Entity_Name({_,'ENTITIES',_,_,_},_S) ->
ok.
vc_No_Duplicate_Types(#xmerl_scanner{validation=dtd} = S,mixed,Acc) ->
- CheckDupl =
+ CheckDupl =
fun([H|T],F) ->
case lists:member(H,T) of
true ->
@@ -3259,12 +3391,18 @@ mandatory_delimeter_wfc(T,S) ->
wfc_unique_att_spec([],_S) ->
ok;
-wfc_unique_att_spec([#xmlAttribute{name=N}|Atts],S) ->
+wfc_unique_att_spec([#xmlAttribute{name=N,expanded_name=EN}|Atts],S) ->
case lists:keymember(N,#xmlAttribute.name,Atts) of
true ->
?fatal({error,{unique_att_spec_required,N}},S);
_ ->
- wfc_unique_att_spec(Atts,S)
+ case S#xmerl_scanner.namespace_conformant andalso
+ lists:keymember(EN, #xmlAttribute.expanded_name, Atts) of
+ true ->
+ ?fatal({error,{unique_att_spec_required,EN}},S);
+ _ ->
+ wfc_unique_att_spec(Atts,S)
+ end
end.
wfc_legal_char(Chars,S) when is_list(Chars)->
@@ -3313,6 +3451,11 @@ wfc_Internal_parsed_entity(internal,Value,S) ->
wfc_Internal_parsed_entity(_,_,_) ->
ok.
+vc_Element_valid(_Name, {"xmlns", _},
+ S = #xmerl_scanner{namespace_conformant = true}) ->
+ ?fatal({error,{illegal_element_prefix,xmlns}},S);
+vc_Element_valid(Name, _, S) ->
+ vc_Element_valid(Name, S).
vc_Element_valid(_Name,#xmerl_scanner{environment=internal_parsed_entity}) ->
ok;
@@ -3379,7 +3522,7 @@ scan_notation_decl1("PUBLIC" ++ T, S0) ->
?strip3,
case T3 of
">" ++ _ ->
- {{public, PIDL}, T3,
+ {{public, PIDL}, T3,
S3#xmerl_scanner{col = S3#xmerl_scanner.col+1}};
_ ->
{SL, T4, S4} = scan_system_literal(T3, S3),
@@ -3430,7 +3573,7 @@ scan_entity_value([],S,
scan_entity_value([],S=#xmerl_scanner{validation=dtd},
no_delim,_Acc,PEName,_,_PENesting) ->
{{error,{failed_VC_Proper_Declaration_PE_Nesting,2,PEName}},[],S};
-scan_entity_value([], S=#xmerl_scanner{continuation_fun = F},
+scan_entity_value([], S=#xmerl_scanner{continuation_fun = F},
Delim, Acc, PEName,Namespace,PENesting) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) ->
@@ -3449,7 +3592,7 @@ scan_entity_value([Delim|T], S0,
scan_entity_value("%" ++ _T,S=#xmerl_scanner{environment=prolog},_,_,_,_,_) ->
?fatal({error,{wfc_PEs_In_Internal_Subset}},S);
% %% This is a PEdecl in an external entity
-% scan_entity_value([$%,WS|T], S0, Delim, Acc, PEName,Namespace,PENesting)
+% scan_entity_value([$%,WS|T], S0, Delim, Acc, PEName,Namespace,PENesting)
% when ?whitespace(WS) ->
% ?bump_col(2),
% scan_entity_value(T, S, Delim, [WS,$%|Acc], PEName,Namespace,PENesting);
@@ -3459,7 +3602,7 @@ scan_entity_value("%" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) ->
if PERefName == PEName,Namespace==parameter ->
?fatal({illegal_recursion_in_PE, PEName}, S1);
true ->
- {ExpandedRef,S2} =
+ {ExpandedRef,S2} =
case expand_pe_reference(PERefName, S1, in_literal) of
%% actually should pe ref be expanded as_PE but
%% handle whitespace explicitly in this case.
@@ -3467,7 +3610,7 @@ scan_entity_value("%" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) ->
%% {system,URI} or {public,URI}
%% Included in literal.
{ExpRef,Sx}=fetch_not_parse(Tuple,S1),
- {EntV, _, S5} =
+ {EntV, _, S5} =
scan_entity_value(ExpRef, Sx, no_delim,[],
PERefName,parameter,[]),
%% should do an update Write(parameter_entity)
@@ -3587,7 +3730,7 @@ scan_entity_value(")"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
scan_entity_value(T,S,Delim,[")"|Acc],PEName,NS,
pe_pop(")",PENesting,S));
scan_entity_value("\n"++T, S, Delim, Acc, PEName,Namespace,PENesting) ->
- scan_entity_value(T, S#xmerl_scanner{line=S#xmerl_scanner.line+1},
+ scan_entity_value(T, S#xmerl_scanner{line=S#xmerl_scanner.line+1},
Delim, ["\n"|Acc], PEName,Namespace,PENesting);
scan_entity_value(Str, S0, Delim, Acc, PEName,Namespace,PENesting) ->
{Ch,T} = to_ucs(S0#xmerl_scanner.encoding,Str),
@@ -3630,7 +3773,7 @@ save_refed_entity_name1(Name,PEName,
pe_push(Tok,Stack,_S) when Tok=="<!";Tok=="<?";Tok=="<!--";Tok=="<![";
Tok=="[";Tok=="<";Tok=="</";Tok=="(" ->
[Tok|Stack];
-pe_push(Tok,Stack,#xmerl_scanner{validation=dtd})
+pe_push(Tok,Stack,#xmerl_scanner{validation=dtd})
when Tok==")";Tok==">";Tok=="?>";Tok=="]]>";Tok=="-->";Tok=="/>"->
[Tok|Stack];
pe_push(_,Stack,_S) ->
@@ -3698,10 +3841,10 @@ scan_comment(Str,S=#xmerl_scanner{col=C,event_fun=Event}, Pos, Parents, Lang) ->
col = C,
pos = Pos,
data = Comment}, S),
-
+
scan_comment1(Str, S1, Pos, Comment, _Acc = []).
-scan_comment1([], S=#xmerl_scanner{continuation_fun = F},
+scan_comment1([], S=#xmerl_scanner{continuation_fun = F},
Pos, Comment, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_comment1(MoreBytes, S1, Pos, Comment, Acc) end,
@@ -3709,7 +3852,7 @@ scan_comment1([], S=#xmerl_scanner{continuation_fun = F},
S);
scan_comment1("-->" ++ T, S0 = #xmerl_scanner{col = C,
event_fun = Event,
- hook_fun = Hook},
+ hook_fun = Hook},
_Pos, Comment, Acc) ->
?bump_col(3),
Comment1 = Comment#xmlComment{value = lists:reverse(Acc)},
@@ -3817,9 +3960,9 @@ normalize(T,S,IsNorm) ->
end.
-%% Optimization:
+%% Optimization:
%% - avoid building list of spaces or tabs;
-%% - avoid reverse;
+%% - avoid reverse;
%% - compact two common indentation patterns.
%% Note: only to be called when a \n was found.
fast_accumulate_whitespace(" " ++ T, S, _) ->
@@ -3831,7 +3974,7 @@ fast_accumulate_whitespace("<"++_=R, S, _T) ->
{done, {element(3, CD), R, S#xmerl_scanner{col = 1, line = Line + 1}}};
fast_accumulate_whitespace(_, S, T) ->
accumulate_whitespace(T, S, []).
-
+
fast_acc_spaces(" " ++ T, S, N) ->
fast_acc_spaces(T, S, N + 1);
fast_acc_spaces(T, S, N) ->
@@ -3845,18 +3988,18 @@ fast_acc_tabs(T, S, N) ->
fast_acc_end(T, S, N, Col, C, CD_I) ->
#xmerl_scanner{common_data = CD, line = Line0} = S,
Line = Line0 + 1,
- try
+ try
$< = hd(T),
- {done,{element(N, element(CD_I, CD)), T,
+ {done,{element(N, element(CD_I, CD)), T,
S#xmerl_scanner{col = Col, line = Line}}}
- catch _:_ ->
+ catch _:_ ->
accumulate_whitespace(T, S, Line, Col, lists:duplicate(N, C)++"\n")
end.
-
+
%%% @spec accumulate_whitespace(T::string(),S::global_state(),
%%% atom(),Acc::string()) -> {Acc, T1, S1}
-%%%
+%%%
%%% @doc Function to accumulate and normalize whitespace.
accumulate_whitespace(T, S, preserve, Acc) ->
accumulate_whitespace(T, S, Acc);
@@ -3915,19 +4058,19 @@ schemaLocations(El,#xmerl_scanner{schemaLocation=SL}) ->
schemaLocations(El)
end.
-schemaLocations(#xmlElement{attributes=Atts,xmlbase=_Base}) ->
+schemaLocations(#xmlElement{attributes=Atts,xmlbase=_Base}) ->
Pred = fun(#xmlAttribute{name=schemaLocation}) -> false;
- (#xmlAttribute{namespace={_,"schemaLocation"}}) -> false;
+ (#xmlAttribute{nsinfo={_,"schemaLocation"}}) -> false;
(_) -> true
end,
case lists:dropwhile(Pred,Atts) of
[#xmlAttribute{value=Paths}|_] ->
-
+
case string:tokens(Paths," \n\t\r") of
L when length(L) > 0 ->
case length(L) rem 2 of
0 ->
- PairList =
+ PairList =
fun([],_Fun) ->
[];
([SLNS,SLLoc|Rest],Fun) ->
@@ -3997,7 +4140,7 @@ to_ucs(Encoding, Chars) when Encoding=="utf-8"; Encoding == undefined ->
utf8_2_ucs(Chars);
to_ucs(_,[C|Rest]) ->
{C,Rest}.
-
+
utf8_2_ucs([A,B,C,D|Rest]) when A band 16#f8 =:= 16#f0,
B band 16#c0 =:= 16#80,
C band 16#c0 =:= 16#80,
@@ -4086,7 +4229,7 @@ string_to_char_set(_,Str) ->
%% {{_,{_,Tot}},Tot110} when Tot > Tot110 ->
%% io:format("From ~p to ~p, total memory: ~p (~p)~n",[OldLine,Line,Tot,OldTot]),
%% Tot;
-%% {{_,{_,Tot}},_} ->
+%% {{_,{_,Tot}},_} ->
%% Tot
%% end,
%% put_total({NewTot,Line}).
diff --git a/lib/xmerl/src/xmerl_uri.erl b/lib/xmerl/src/xmerl_uri.erl
index a0c6f1c2a7..ed66dd78d4 100644
--- a/lib/xmerl/src/xmerl_uri.erl
+++ b/lib/xmerl/src/xmerl_uri.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -358,7 +358,7 @@ scan_host(C0) ->
%% Hex3=<?HEX;
%% Hex4=<?HEX ->
%% {C1,lists:reverse(lists:append(IPv6address))};
- {C1,Hostname,[A|_HostF]} ->
+ {C1,Hostname,[_A|_HostF]} ->
{C1,lists:reverse(lists:append(Hostname))}
%% _ ->
%% {error,no_host}
diff --git a/lib/xmerl/src/xmerl_validate.erl b/lib/xmerl/src/xmerl_validate.erl
index 893e23ca34..60f228474b 100644
--- a/lib/xmerl/src/xmerl_validate.erl
+++ b/lib/xmerl/src/xmerl_validate.erl
@@ -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
@@ -399,25 +399,28 @@ test_attribute_value(_Rule,Attr,_,_) ->
%% +type valid_contents([rule()],[xmlElement()])->
%% [xmlElement() | {error,???}.
-valid_contents(Rule,XMLS,Rules,S,WSActionMode)->
- case parse(Rule,XMLS,Rules,WSActionMode,S) of
- {XML_N,[]}->
- lists:flatten(XML_N);
- {_,[#xmlElement{name=Name}|_T]} ->
- exit({error,{element,Name,isnt_comprise_in_the_rule,Rule}});
- {_,[#xmlText{}=Txt|_T]} ->
- exit({error,{element,text,Txt,isnt_comprise_in_the_rule,Rule}});
- {error,Reason} ->
- {error,Reason};
- {error,Reason,N} ->
- {error,Reason,N}
+valid_contents(Rule, XMLS, Rules, S, WSActionMode)->
+ case parse(Rule, XMLS, Rules, WSActionMode, S) of
+ {error, Reason} ->
+ {error, Reason};
+ {error, Reason, N} ->
+ {error, Reason, N};
+ {XML_N, Rest} -> %The list may consist of xmlComment{} records
+ case lists:dropwhile(fun(X) when is_record(X, xmlComment) -> true; (_) -> false end, Rest) of
+ [] ->
+ lists:flatten(XML_N);
+ [#xmlElement{name=Name} |_T] ->
+ exit({error, {element, Name, isnt_comprise_in_the_rule, Rule}});
+ [#xmlText{} = Txt |_T] ->
+ exit({error, {element, text, Txt, isnt_comprise_in_the_rule, Rule}})
+ end
end.
-parse({'*',SubRule},XMLS,Rules,WSaction,S)->
- star(SubRule,XMLS,Rules,WSaction,[],S);
-parse({'+',SubRule},XMLS,Rules,WSaction,S) ->
- plus(SubRule,XMLS,Rules,WSaction,S);
-parse({choice,CHOICE},XMLS,Rules,WSaction,S)->
+parse({'*', SubRule}, XMLS, Rules, WSaction, S)->
+ star(SubRule, XMLS, Rules, WSaction, [], S);
+parse({'+',SubRule}, XMLS, Rules, WSaction, S) ->
+ plus(SubRule, XMLS, Rules, WSaction, S);
+parse({choice,CHOICE}, XMLS, Rules, WSaction, S)->
% case XMLS of
% [] ->
% io:format("~p~n",[{choice,CHOICE,[]}]);
@@ -426,47 +429,49 @@ parse({choice,CHOICE},XMLS,Rules,WSaction,S)->
% [#xmlText{value=V}|_] ->
% io:format("~p~n",[{choice,CHOICE,{text,V}}])
% end,
- choice(CHOICE,XMLS,Rules,WSaction,S);
-parse(empty,[],_Rules,_WSaction,_S) ->
- {[],[]};
-parse({'?',SubRule},XMLS,Rules,_WSaction,S)->
- question(SubRule,XMLS,Rules,S);
-parse({seq,List},XMLS,Rules,WSaction,S) ->
- seq(List,XMLS,Rules,WSaction,S);
-parse(El_Name,[#xmlElement{name=El_Name}=XML|T],Rules,_WSaction,S)
+ choice(CHOICE, XMLS, Rules, WSaction, S);
+parse(empty, [], _Rules, _WSaction, _S) ->
+ {[], []};
+parse({'?', SubRule}, XMLS, Rules, _WSaction, S)->
+ question(SubRule, XMLS, Rules, S);
+parse({seq,List}, XMLS, Rules, WSaction, S) ->
+ seq(List, XMLS, Rules, WSaction, S);
+parse(El_Name, [#xmlElement{name=El_Name} = XML |T], Rules, _WSaction, S)
when is_atom(El_Name)->
- case do_validation(read_rules(Rules,El_Name),XML,Rules,S) of
- {error,R} ->
+ case do_validation(read_rules(Rules, El_Name), XML, Rules, S) of
+ {error, R} ->
% {error,R};
exit(R);
- {error,R,_N}->
+ {error, R, _N}->
% {error,R,N};
exit(R);
XML_->
- {[XML_],T}
+ {[XML_], T}
end;
-parse(any,Cont,Rules,_WSaction,S) ->
- case catch parse_any(Cont,Rules,S) of
- Err = {error,_} -> Err;
- ValidContents -> {ValidContents,[]}
+parse(any, Cont, Rules, _WSaction, S) ->
+ case catch parse_any(Cont, Rules, S) of
+ Err = {error, _} -> Err;
+ ValidContents -> {ValidContents, []}
end;
-parse(El_Name,[#xmlElement{name=Name}|_T]=S,_Rules,_WSa,_S) when is_atom(El_Name)->
+parse(El_Name, [#xmlElement{name=Name} |_T] = XMLS, _Rules, _WSa, _S) when is_atom(El_Name) ->
{error,
- {element_seq_not_conform,{wait,El_Name},{is,Name}},
- {{next,S},{act,[]}} };
-parse(_El_Name,[#xmlPI{}=H|T],_Rules,_WSa,_S) ->
- {[H],T};
-parse('#PCDATA',XML,_Rules,_WSa,_S)->
+ {element_seq_not_conform,{wait, El_Name}, {is, Name}},
+ {{next, XMLS}, {act, []}}};
+parse(El_Name, [#xmlComment{} |T], Rules, WSa, S) ->
+ parse(El_Name, T, Rules, WSa, S);
+parse(_El_Name, [#xmlPI{} = H |T], _Rules, _WSa, _S) ->
+ {[H], T};
+parse('#PCDATA', XMLS, _Rules, _WSa, _S)->
%%% PCDATA it is 0 , 1 or more #xmlText{}.
- parse_pcdata(XML);
-parse(El_Name,[#xmlText{}|_T]=S,_Rules,_WSa,_S)->
+ parse_pcdata(XMLS);
+parse(El_Name, [#xmlText{}|_T] = XMLS, _Rules, _WSa, _S)->
{error,
- {text_in_place_of,El_Name},
- {{next,S},{act,[]}}};
-parse([],_,_,_,_) ->
- {error,no_rule};
-parse(Rule,[],_,_,_) ->
- {error,{no_xml_element,Rule}}.
+ {text_in_place_of, El_Name},
+ {{next, XMLS}, {act, []}}};
+parse([], _, _, _, _) ->
+ {error, no_rule};
+parse(Rule, [], _, _, _) ->
+ {error, {no_xml_element, Rule}}.
parse_any([],_Rules,_S) ->
[];
@@ -618,11 +623,15 @@ el_name(#xmlElement{name=Name})->
parse_pcdata([#xmlText{}=H|T])->
parse_pcdata(T,[H]);
+parse_pcdata([#xmlComment{}|T])->
+ parse_pcdata(T,[]);
parse_pcdata(H) ->
{[],H}.
parse_pcdata([#xmlText{}=H|T],Acc)->
parse_pcdata(T,Acc++[H]);
+parse_pcdata([#xmlComment{}|T],Acc)->
+ parse_pcdata(T,Acc);
parse_pcdata(H,Acc) ->
{Acc,H}.
diff --git a/lib/xmerl/src/xmerl_xpath.erl b/lib/xmerl/src/xmerl_xpath.erl
index db3d3ac2d6..b3301f2faf 100644
--- a/lib/xmerl/src/xmerl_xpath.erl
+++ b/lib/xmerl/src/xmerl_xpath.erl
@@ -41,18 +41,13 @@
% xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("parent::processing-instruction('foo')")).
%% </pre>
%%
-%% @type docEntity() =
+%% @type nodeEntity() =
%% xmlElement()
%% | xmlAttribute()
%% | xmlText()
%% | xmlPI()
%% | xmlComment()
-%% @type nodeEntity() =
-%% xmlElement()
-%% | xmlAttribute()
-%% | xmlText()
-%% | xmlPI()
-%% | xmlNamespace()
+%% | xmlNsNode()
%% | xmlDocument()
%% @type option_list(). <p>Options allows to customize the behaviour of the
%% XPath scanner.
@@ -303,6 +298,17 @@ write_node(#xmlNode{pos = Pos,
node = #xmlText{value = Txt,
parents = Ps}}) ->
{text, Pos, Txt, Ps};
+write_node(#xmlNode{pos = Pos,
+ node = #xmlComment{parents = Ps}}) ->
+ {comment, Pos, '', Ps};
+write_node(#xmlNode{pos = Pos,
+ node = #xmlPI{name = Name,
+ parents = Ps}}) ->
+ {processing_instruction, Pos, Name, Ps};
+write_node(#xmlNode{pos = Pos,
+ node = #xmlNsNode{parents = Ps,
+ prefix = Prefix}}) ->
+ {namespace, Pos, Prefix, Ps};
write_node(_) ->
other.
@@ -330,18 +336,16 @@ eval_path(rel, PathExpr, C = #xmlContext{}) ->
Context = C#xmlContext{nodeset = NodeSet},
S = #state{context = Context},
path_expr(PathExpr, S);
-eval_path(filter, {PathExpr, PredExpr}, C = #xmlContext{}) ->
+eval_path(filter, {PathExpr, {pred, Pred}}, C = #xmlContext{}) ->
S = #state{context = C},
- S1 = path_expr(PathExpr, S),
- pred_expr(PredExpr, S1).
+ S1 = match_expr(PathExpr, S),
+ eval_pred(Pred, S1).
-eval_primary_expr(FC = {function_call,_,_},S = #state{context = Context}) ->
+eval_primary_expr(PrimExpr, S = #state{context = Context}) ->
%% NewNodeSet = xmerl_xpath_pred:eval(FC, Context),
- NewNodeSet = xmerl_xpath_lib:eval(primary_expr, FC, Context),
+ NewNodeSet = xmerl_xpath_lib:eval(primary_expr, PrimExpr, Context),
NewContext = Context#xmlContext{nodeset = NewNodeSet},
- S#state{context = NewContext};
-eval_primary_expr(PrimExpr,_S) ->
- exit({primary_expression,{not_implemented, PrimExpr}}).
+ S#state{context = NewContext}.
%% axis(Axis,NodeTest,Context::xmlContext()) -> xmlContext()
@@ -384,8 +388,8 @@ axis1(preceding, Tok, N, Acc, Context) ->
match_preceding(Tok, N, Acc, Context);
axis1(attribute, Tok, N, Acc, Context) ->
match_attribute(Tok, N, Acc, Context);
-%axis1(namespace, Tok, N, Acc, Context) ->
-% match_namespace(Tok, N, Acc, Context);
+axis1(namespace, Tok, N, Acc, Context) ->
+ match_namespace(Tok, N, Acc, Context);
axis1(ancestor_or_self, Tok, N, Acc, Context) ->
match_ancestor_or_self(Tok, N, Acc, Context);
axis1(descendant_or_self, Tok, N, Acc, Context) ->
@@ -627,14 +631,58 @@ node_type(#xmlAttribute{}) -> attribute;
node_type(#xmlElement{}) -> element;
node_type(#xmlText{}) -> text;
node_type(#xmlPI{}) -> processing_instruction;
-node_type(#xmlNamespace{}) -> namespace;
+node_type(#xmlNsNode{}) -> namespace;
+node_type(#xmlComment{}) -> comment;
node_type(#xmlDocument{}) -> root_node.
%% "The namespace axis contains the namespace nodes of the context node;
%% the axis will be empty unless the context node is an element."
-%match_namespace(_Tok, _N, _Acc, _Context) ->
- %% TODO: IMPLEMENT NAMESPACE AXIS
-% erlang:fault(not_yet_implemented).
+match_namespace(Tok, N, Acc, Context) ->
+ case N#xmlNode.type of
+ element ->
+ #xmlNode{parents = Ps, node = E} = N,
+ #xmlElement{name = Name,
+ namespace = NS,
+ parents = EPs,
+ pos = Pos} = E,
+ #xmlNamespace{default = Default, nodes = NSPairs} = NS,
+ ThisEPs = [{Name, Pos}|EPs],
+ ThisPs = [N|Ps],
+ Acc0 =
+ case Default of
+ D when D =:= []; D =:= '' ->
+ {[], 1};
+ URI ->
+ DefaultNSNode = #xmlNsNode{parents = ThisEPs,
+ pos = 1,
+ prefix = [],
+ uri = URI},
+ Node = #xmlNode{type = namespace,
+ node = DefaultNSNode,
+ parents = ThisPs},
+ {[Node], 2}
+ end,
+ {Nodes, _I} =
+ lists:foldr(
+ fun ({Prefix, URI}, {AccX, I}) ->
+ NSNode = #xmlNsNode{parents = ThisEPs,
+ pos = I,
+ prefix = Prefix,
+ uri = URI},
+ ThisN = #xmlNode{pos = I,
+ type = namespace,
+ node = NSNode,
+ parents = ThisPs},
+ {[ThisN | AccX], I + 1}
+ end, Acc0, NSPairs),
+ lists:foldr(
+ fun (ThisN, AccX) ->
+ match_self(Tok, ThisN, AccX, Context)
+ end, Acc, Nodes);
+ _Other ->
+ %%[]
+ Acc
+ end.
update_nodeset(Context = #xmlContext{axis_type = AxisType}, NodeSet) ->
@@ -655,8 +703,15 @@ update_nodeset(Context = #xmlContext{axis_type = AxisType}, NodeSet) ->
node_test(F, N, Context) when is_function(F) ->
F(N, Context);
+node_test(_Test, #xmlNode{type=attribute,node=#xmlAttribute{name=xmlns}},
+ _Context) ->
+ false;
+node_test(_Test,
+ #xmlNode{type=attribute,node=#xmlAttribute{nsinfo={"xmlns",_Local}}},
+ _Context) ->
+ false;
node_test({wildcard, _}, #xmlNode{type=ElAt}, _Context)
- when ElAt==element; ElAt==attribute ->
+ when ElAt==element; ElAt==attribute; ElAt==namespace ->
true;
node_test({prefix_test, Prefix}, #xmlNode{node = N}, _Context) ->
case N of
@@ -720,6 +775,9 @@ node_test({name, {_Tag, Prefix, Local}},
[{_Tag, Prefix, Local}, write_node(NSNodes)]),
false
end;
+node_test({name, {_Tag, [], Local}},
+ #xmlNode{node = #xmlNsNode{prefix = Local}}, _Context) ->
+ true;
node_test({node_type, NT}, #xmlNode{node = N}, _Context) ->
case {NT, N} of
{text, #xmlText{}} ->
@@ -728,14 +786,18 @@ node_test({node_type, NT}, #xmlNode{node = N}, _Context) ->
true;
{attribute, #xmlAttribute{}} ->
true;
- {namespace, #xmlNamespace{}} ->
+ {namespace, #xmlNsNode{}} ->
+ true;
+ {comment, #xmlComment{}} ->
+ true;
+ {processing_instruction, #xmlPI{}} ->
true;
_ ->
false
end;
-node_test({processing_instruction, {literal, _, Name}},
- #xmlNode{node = {processing_instruction, Name, _Data}}, _Context) ->
- true;
+node_test({processing_instruction, Name1},
+ #xmlNode{node = #xmlPI{name = Name2}}, _Context) ->
+ Name1 == atom_to_list(Name2);
node_test(_Other, _N, _Context) ->
%io:format("node_test(~p, ~p) -> false.~n", [_Other, write_node(_N)]),
false.
diff --git a/lib/xmerl/src/xmerl_xpath_lib.erl b/lib/xmerl/src/xmerl_xpath_lib.erl
index cfd0e36667..b37bdc93f9 100644
--- a/lib/xmerl/src/xmerl_xpath_lib.erl
+++ b/lib/xmerl/src/xmerl_xpath_lib.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
@@ -49,5 +49,7 @@ primary_expr({function_call, F, Args}, C) ->
%% here, we should look up the function in the context provided
%% by the caller, but we haven't figured this out yet.
exit({not_a_core_function, F})
- end.
+ end;
+primary_expr(PrimExpr, _C) ->
+ exit({primary_expression, {not_implemented, PrimExpr}}).
diff --git a/lib/xmerl/src/xmerl_xpath_parse.yrl b/lib/xmerl/src/xmerl_xpath_parse.yrl
index 37576b9e61..381ea20193 100644
--- a/lib/xmerl/src/xmerl_xpath_parse.yrl
+++ b/lib/xmerl/src/xmerl_xpath_parse.yrl
@@ -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
@@ -144,6 +144,7 @@ Expect 2.
%% [7]
'NodeTest' -> 'NameTest' : '$1' .
'NodeTest' -> 'node_type' '(' ')' : {node_type, value('$1')} .
+'NodeTest' -> 'processing-instruction' '(' ')' : {node_type, value('$1')} .
'NodeTest' -> 'processing-instruction' '(' 'literal' ')'
: {processing_instruction, value('$3')} .
diff --git a/lib/xmerl/src/xmerl_xpath_pred.erl b/lib/xmerl/src/xmerl_xpath_pred.erl
index 451a09bee3..b94f3bb14d 100644
--- a/lib/xmerl/src/xmerl_xpath_pred.erl
+++ b/lib/xmerl/src/xmerl_xpath_pred.erl
@@ -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
@@ -337,6 +337,9 @@ local_name1([#xmlNode{type=element,node=El}|_]) ->
local_name1([#xmlNode{type=attribute,node=Att}|_]) ->
#xmlAttribute{name=Name,nsinfo=NSI} = Att,
local_name2(Name,NSI);
+local_name1([#xmlNode{type=namespace,node=N}|_]) ->
+ #xmlNsNode{prefix=Prefix} = N,
+ ?string(Prefix);
local_name1([#xmlElement{name = Name, nsinfo = NSI}|_]) ->
local_name2(Name,NSI).
local_name2(Name, NSI) ->
@@ -431,6 +434,9 @@ string_value(N=#xmlObj{}) ->
string_value(A=#xmlNode{type=attribute}) ->
#xmlAttribute{value=AttVal}=A#xmlNode.node,
?string(AttVal);
+string_value(N=#xmlNode{type=namespace}) ->
+ #xmlNsNode{uri=URI}=N#xmlNode.node,
+ ?string(atom_to_list(URI));
string_value(El=#xmlNode{type=element}) ->
#xmlElement{content=C} = El#xmlNode.node,
TextValue = fun(#xmlText{value=T},_Fun) -> T;
@@ -442,6 +448,9 @@ string_value(El=#xmlNode{type=element}) ->
string_value(T=#xmlNode{type=text}) ->
#xmlText{value=Txt} = T#xmlNode.node,
?string(Txt);
+string_value(T=#xmlNode{type=comment}) ->
+ #xmlComment{value=Txt} = T#xmlNode.node,
+ ?string(Txt);
string_value(infinity) -> ?string("Infinity");
string_value(neg_infinity) -> ?string("-Infinity");
string_value(A) when is_atom(A) ->
diff --git a/lib/xmerl/src/xmerl_xpath_scan.erl b/lib/xmerl/src/xmerl_xpath_scan.erl
index 10e2756e74..f0a5bd35a3 100644
--- a/lib/xmerl/src/xmerl_xpath_scan.erl
+++ b/lib/xmerl/src/xmerl_xpath_scan.erl
@@ -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
@@ -287,6 +287,7 @@ strip_ws(T) ->
special_token('@') -> true;
special_token('::') -> true;
+special_token(',') -> true;
special_token('(') -> true;
special_token('[') -> true;
special_token('/') -> true;
diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl
index dfdc6138ef..78d84d23a4 100644
--- a/lib/xmerl/src/xmerl_xsd.erl
+++ b/lib/xmerl/src/xmerl_xsd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -245,21 +245,27 @@ process_validate2({SE,_},Schema,Xml,Opts) ->
S4 = validation_options(S3,Opts),
validate3(Schema,Xml,S4).
-validate3(Schema,Xml,S=#xsd_state{errors=[]}) ->
- Ret = {_,S2} =
- case catch validate_xml(Xml,S) of
- {[XML2],[],Sx} ->
- {XML2,Sx};
- {XML2,[],Sx} ->
- {XML2,Sx};
- {_,UnValidated,Sx} ->
- {Xml,acc_errs(Sx,{error_path(UnValidated,Xml#xmlElement.name),?MODULE,
- {unvalidated_rest,UnValidated}})};
- _Err = {error,Reason} ->
- {Xml,acc_errs(S,Reason)};
- {'EXIT',Reason} ->
- {Xml,acc_errs(S,{error_path(Xml,Xml#xmlElement.name),?MODULE,
- {undefined,{internal_error,Reason}}})}
+validate3(Schema, Xml,S =#xsd_state{errors=[]}) ->
+ Ret = {_, S2} =
+ case catch validate_xml(Xml, S) of
+ _Err = {error, Reason} ->
+ {Xml, acc_errs(S, Reason)};
+ {'EXIT', Reason} ->
+ {Xml, acc_errs(S, {error_path(Xml, Xml#xmlElement.name), ?MODULE,
+ {undefined, {internal_error, Reason}}})};
+ {XML2, Rest, Sx} ->
+ case lists:dropwhile(fun(X) when is_record(X, xmlComment) -> true; (_) -> false end, Rest) of
+ [] ->
+ case XML2 of
+ [XML3] ->
+ {XML3,Sx};
+ XML3 ->
+ {XML3,Sx}
+ end;
+ UnValidated ->
+ {Xml,acc_errs(Sx,{error_path(UnValidated,Xml#xmlElement.name),?MODULE,
+ {unvalidated_rest,UnValidated}})}
+ end
end,
save_to_file(S2,filename:rootname(Schema)++".tab2"),
case S2#xsd_state.errors of
@@ -1950,7 +1956,7 @@ fetch_external_schema(Path,S) when is_list(Path) ->
{EXSD,S#xsd_state{schema_name=File}}
end;
{_,{string,String},_} -> %% this is for a user defined fetch fun that returns an xml document on string format.
- ?debug("scanning string: ~p~n",[File]),
+ ?debug("scanning string: ~p~n",[String]),
case xmerl_scan:string(String,S#xsd_state.xml_options) of
{error,Reason} ->
{error,acc_errs(S,{[],?MODULE,{parsing_external_schema_failed,Path,Reason}})};
@@ -2332,6 +2338,8 @@ complexity([]) ->
undefined;
complexity([#xmlText{}|T]) ->
complexity(T);
+complexity([#xmlComment{}|T]) ->
+ complexity(T);
complexity([H|T]) ->
case kind(H) of
simpleContent ->
@@ -2520,9 +2528,9 @@ check_element_type([],#schema_complex_type{name=_Name,block=_Bl,content=C},
{error,{error_path(Checked,undefined),?MODULE,
{empty_content_not_allowed,C}}}
end;
-check_element_type(C,{anyType,_},_Env,_Block,S,_Checked) ->
+check_element_type(C, {anyType, _}, _Env, _Block, S, _Checked) ->
%% permitt anything
- {C,[],S};
+ {lists:reverse(C), [], S};
check_element_type(XML=[#xmlText{}|_],Type=#schema_simple_type{},
_Env,_Block,S,_Checked) ->
@@ -2585,7 +2593,7 @@ check_element_type(XML=[XMLEl=#xmlElement{name=Name}|RestXML],
S6 = check_form(ElName,Name,XMLEl,
actual_form_value(CMEl#schema_element.form,
S5#xsd_state.elementFormDefault),
- S5),
+ S5),
%Step into content of XML element.
{Content,_,S7} =
case
@@ -2605,12 +2613,12 @@ check_element_type(XML=[XMLEl=#xmlElement{name=Name}|RestXML],
RestXML,
set_scope(S5#xsd_state.scope,set_num_el(S7,S6))};
true ->
- {error,{error_path(XMLEl,Name),?MODULE,
- {element_not_suitable_with_schema,ElName,S}}};
+ {error,{error_path(XMLEl, Name), ?MODULE,
+ {element_not_suitable_with_schema, ElName, S}}};
_ when S#xsd_state.num_el >= Min ->
%% it may be a match error or an optional element not
%% present
- {[],XML,S#xsd_state{num_el=0}};
+ {[], XML, S#xsd_state{num_el=0}};
_ ->
{error,{error_path(XMLEl,Name),?MODULE,
{element_not_suitable_with_schema,ElName,CMName,CMEl,S}}}
@@ -2645,7 +2653,7 @@ check_element_type(XML=[#xmlElement{}|_Rest],
check_element_type(XML=[E=#xmlElement{name=Name}|Rest],
Any={any,{Namespace,_Occ={Min,_},ProcessorContents}},Env,
_Block,S,_Checked) ->
- ?debug("check any: {any,{~p,~p,~p}}~n",[Namespace,Occ,ProcessorContents]),
+ ?debug("check any: {any,{~p,~p,~p}}~n",[Namespace,_Occ,ProcessorContents]),
%% ProcessorContents any of lax | strict | skip
%% lax: may validate if schema is found
%% strict: must validate
@@ -2710,8 +2718,11 @@ check_element_type([],CM,_Env,_Block,S,Checked) ->
{error,{error_path(Checked,undefined),?MODULE,
{empty_content_not_allowed,CM}}}
end;
+check_element_type([C = #xmlComment{} |Rest],CM,Env,Block,S,Checked) ->
+ check_element_type(Rest,CM,Env,Block,S,[C |Checked]);
check_element_type(XML,CM,_Env,_Block,S,_Checked) ->
{error,{error_path(XML,undefined),?MODULE,{match_failure,XML,CM,S}}}.
+
%% single xml content object and single schema object
check_text_type(XML=[#xmlText{}|_],optional_text,S) ->
% {XMLTxt,optional_text};
@@ -2730,7 +2741,7 @@ check_text_type([XMLTxt=#xmlText{}|_],CMEl,_S) ->
{cannot_contain_text,XMLTxt,CMEl}}}.
split_xmlText(XML) ->
- splitwith(fun(#xmlText{}) -> true;(_) -> false end,XML).
+ splitwith(fun(#xmlText{}) -> true;(#xmlComment{}) -> true;(_) -> false end,XML).
%% Sequence
check_sequence([T=#xmlText{}|Rest],Els,Occ,Env,S,Checked) ->
@@ -2773,6 +2784,8 @@ check_sequence(Seq=[_InstEl=#xmlElement{}|_],[El|Els],Occ={_Min,_Max},Env,S,Chec
count_num_el(set_num_el(S3,S2)),
Ret++Checked)
end;
+check_sequence([C = #xmlComment{} |Rest], Els, Occ, Env, S, Checked) ->
+ check_sequence(Rest,Els,Occ,Env,S,[C |Checked]);
check_sequence(Rest,[],_Occ,_Env,S,Checked) ->
{Checked,Rest,set_num_el(S,0)};
check_sequence([],Els,_Occ,_Env,S,Checked) ->
@@ -2869,6 +2882,8 @@ check_all(XML=[E=#xmlElement{name=Name}|RestXML],CM,Occ,Env,S,
{element_not_in_all,ElName,E,CM}},
check_all(RestXML,CM,Occ,Env,acc_errs(S,Err),[E|Checked],PrevXML)
end;
+check_all([C=#xmlComment{} |RestXML], CM, Occ, Env, S, Checked, XML) ->
+ check_all(RestXML, CM, Occ, Env, S, [C |Checked], XML);
check_all(XML,[],_,_,S,Checked,_) ->
{Checked,XML,S};
check_all([],CM,_Occ,_,S,Checked,_PrevXML) ->
@@ -2920,7 +2935,7 @@ check_target_namespace(XMLEl,S) ->
schemaLocations(El=#xmlElement{attributes=Atts},S) ->
Pred = fun(#xmlAttribute{name=schemaLocation}) -> false;
- (#xmlAttribute{namespace={_,"schemaLocation"}}) -> false;
+ (#xmlAttribute{nsinfo={_,"schemaLocation"}}) -> false;
(_) -> true
end,
case lists:dropwhile(Pred,Atts) of
diff --git a/lib/xmerl/test/Makefile b/lib/xmerl/test/Makefile
index 5a2a585841..1fdbb7ca0d 100644
--- a/lib/xmerl/test/Makefile
+++ b/lib/xmerl/test/Makefile
@@ -113,15 +113,15 @@ 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)
+ $(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/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl
index 94c38d4d48..55b6d1844c 100644
--- a/lib/xmerl/test/xmerl_SUITE.erl
+++ b/lib/xmerl/test/xmerl_SUITE.erl
@@ -58,7 +58,7 @@ groups() ->
{ticket_tests, [],
[ticket_5998, ticket_7211, ticket_7214, ticket_7430,
ticket_6873, ticket_7496, ticket_8156, ticket_8697,
- ticket_9411, ticket_9457]},
+ ticket_9411, ticket_9457, ticket_9664_schema, ticket_9664_dtd]},
{app_test, [], [{xmerl_app_test, all}]},
{appup_test, [], [{xmerl_appup_test, all}]}].
@@ -284,7 +284,7 @@ export(Config) ->
?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),
+ ?line {ok, B} = file:read_file(TestFile),
ok.
%%----------------------------------------------------------------------
@@ -609,6 +609,38 @@ ticket_9457_cont(Continue, Exception, GlobalState) ->
Exception(GlobalState)
end.
+
+ticket_9664_schema(suite) -> [];
+ticket_9664_schema(doc) ->
+ ["Test that comments are handled correct whith"];
+ticket_9664_schema(Config) ->
+
+ ?line {E, _} = xmerl_scan:file(filename:join([?config(data_dir, Config), misc,
+ "ticket_9664_schema.xml"]),[]),
+ ?line {ok, S} = xmerl_xsd:process_schema(filename:join([?config(data_dir, Config), misc,
+ "motorcycles.xsd"])),
+ ?line {E1, _} = xmerl_xsd:validate(E, S),
+
+ ?line {E1,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config), misc,
+ "motorcycles.xsd"]),E,[]),
+
+ ?line {E1,_} = xmerl_scan:file(filename:join([?config(data_dir,Config), misc,
+ "ticket_9664_schema.xml"]),
+ [{schemaLocation, [{"mc", "motorcycles.xsd"}]},
+ {validation, schema}]),
+ ok.
+
+ticket_9664_dtd(suite) -> [];
+ticket_9664_dtd(doc) ->
+ ["Test that comments are handled correct whith"];
+ticket_9664_dtd(Config) ->
+ ?line {E, _} = xmerl_scan:file(filename:join([?config(data_dir, Config), misc,
+ "ticket_9664_dtd.xml"]),[]),
+ ?line {E, _} = xmerl_scan:file(filename:join([?config(data_dir, Config), misc,
+ "ticket_9664_dtd.xml"]),[{validation, true}]),
+ ok.
+
+
%%======================================================================
%% Support Functions
%%======================================================================
diff --git a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
index fef7431845..ffc1d327a5 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
+++ b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
index 850b7f8135..7b6f1e95b3 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
@@ -210,7 +210,7 @@ ticket_7496() ->
?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}] =
+ ?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]),
diff --git a/lib/xmerl/test/xmerl_test_lib.erl b/lib/xmerl/test/xmerl_test_lib.erl
index a83956c076..e82ad283b2 100644
--- a/lib/xmerl/test/xmerl_test_lib.erl
+++ b/lib/xmerl/test/xmerl_test_lib.erl
@@ -87,6 +87,6 @@ keysearch_delete(Key,N,List) ->
%% 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.
+ Data = ?config(data_dir, Config),
+ Opts = [{return,list}],
+ re:replace(Data, "xmerl_sax_std_SUITE", "xmerl_std_SUITE", Opts).
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
index 057344cde8..057344cde8 100755..100644
--- a/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 82df8fdeef..599bc0b9d3 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.2.10
+XMERL_VSN = 1.3.2
diff --git a/lib/xmerl/xmerl.pub b/lib/xmerl/xmerl.pub
index 29a81bbde2..29a81bbde2 100755..100644
--- a/lib/xmerl/xmerl.pub
+++ b/lib/xmerl/xmerl.pub
diff --git a/make/otp.mk.in b/make/otp.mk.in
index 4dd309b6ec..756cc85443 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -4,7 +4,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2012. All Rights Reserved.
#
# The 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,12 @@ $(EBIN)/%.beam: $(EGEN)/%.erl
$(EBIN)/%.beam: $(ESRC)/%.erl
$(ERLC) $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
+ifeq ($(NATIVE_LIBS_ENABLED),yes)
+# Special rule for the HIPE bootstrap w/ native libs
+../boot_ebin/%.beam: $(ESRC)/%.erl
+ $(ERLC) $(ERL_COMPILE_FLAGS) -o../boot_ebin $<
+endif
+
.erl.beam:
$(ERLC) $(ERL_COMPILE_FLAGS) -o$(dir $@) $<
@@ -190,8 +196,6 @@ EMACS_COMPILE_OPTIONS=-q --no-site-file -batch -f batch-byte-compile
# ----------------------------------------------------
export VSN
-DOCSUPPORT = 1
-
TOPDOCDIR=../../../../doc
DOCDIR = ..
@@ -250,46 +254,46 @@ $(SPECDIR)/specs_%.xml: $(SPECS_ESRC)/%.erl
$(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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
ifneq ($(wildcard $(SPECDIR)),)
$(MAN3DIR)/%.3: %.xml $(SPECDIR)/specs_%.xml
date=`date +"%B %e %Y"`; \
specs_file=`pwd`/$(SPECDIR)/specs_$*.xml; \
- xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --stringparam specs_file "$$specs_file" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --stringparam specs_file "$$specs_file" --xinclude -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
else
$(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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
endif
# 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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/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 $<
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
.xmlsrc.xml:
diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk
index 7cd827b5af..fa87a4306a 100644
--- a/make/otp_release_targets.mk
+++ b/make/otp_release_targets.mk
@@ -42,7 +42,7 @@ $(HTMLDIR)/index.html: $(XML_FILES) $(SPECS_FILES)
--stringparam gendate "$$date" \
--stringparam appname "$(APPLICATION)" \
--stringparam appver "$(VSN)" \
- -path $(DOCGEN)/priv/docbuilder_dtd \
+ -path $(DOCGEN)/priv/dtd \
-path $(DOCGEN)/priv/dtd_html_entities \
$(DOCGEN)/priv/xsl/db_html.xsl book.xml
endif
@@ -52,7 +52,7 @@ $(HTMLDIR)/users_guide.html: $(XML_FILES)
$(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
+ -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_html.xsl book.xml
%.fo: $(XML_FILES) $(SPECS_FILES)
date=`date +"%B %e %Y"`; \
@@ -62,7 +62,7 @@ $(HTMLDIR)/users_guide.html: $(XML_FILES)
--stringparam appname "$(APPLICATION)" \
--stringparam appver "$(VSN)" \
--xinclude $(TOP_SPECS_PARAM) \
- -path $(DOCGEN)/priv/docbuilder_dtd \
+ -path $(DOCGEN)/priv/dtd \
-path $(DOCGEN)/priv/dtd_html_entities \
$(DOCGEN)/priv/xsl/db_pdf.xsl book.xml > $@
@@ -78,7 +78,7 @@ $(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) $(SPECS_FILES)
date=`date +"%B %e %Y"`; \
$(XSLTPROC) --stringparam docgen "$(DOCGEN)" \
--stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude $(TOP_SPECS_PARAM) \
- -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_eix.xsl book.xml > $@
+ -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_eix.xsl book.xml > $@
docs: $(HTMLDIR)/$(APPLICATION).eix
@@ -110,12 +110,12 @@ endif
ifeq ($(TESTROOT),)
release release_docs release_tests release_html:
- $(MAKE) $(MFLAGS) RELEASE_PATH=$(ERL_TOP)/release/$(TARGET) \
+ $(MAKE) $(MFLAGS) RELEASE_PATH="$(ERL_TOP)/release/$(TARGET)" \
$(TARGET_MAKEFILE) $@_spec
else
release release_docs release_tests release_html:
- $(MAKE) $(MFLAGS) RELEASE_PATH=$(TESTROOT) $(TARGET_MAKEFILE) $@_spec
+ $(MAKE) $(MFLAGS) RELEASE_PATH="$(TESTROOT)" $(TARGET_MAKEFILE) $@_spec
endif
diff --git a/make/otp_subdir.mk b/make/otp_subdir.mk
index 919eee52fc..07294c272d 100644
--- a/make/otp_subdir.mk
+++ b/make/otp_subdir.mk
@@ -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
diff --git a/make/run_make.mk b/make/run_make.mk
index b2be384aa3..b7a5a64847 100644
--- a/make/run_make.mk
+++ b/make/run_make.mk
@@ -27,10 +27,12 @@
include $(ERL_TOP)/make/target.mk
+.PHONY: valgrind
+
opt debug purify quantify purecov valgrind gcov gprof lcnt:
$(MAKE) -f $(TARGET)/Makefile TYPE=$@
-plain smp hybrid frag smp_frag:
+plain smp frag smp_frag:
$(MAKE) -f $(TARGET)/Makefile FLAVOR=$@
clean generate depend docs release release_spec release_docs release_docs_spec \
diff --git a/make/target.mk b/make/target.mk
index 06e895df90..4e13779461 100644
--- a/make/target.mk
+++ b/make/target.mk
@@ -1,3 +1,24 @@
+#
+# %CopyrightBegin%
+#
+# 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
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+# Ensure that the make variable TARGET is set
+#
+
ifeq ($(OVERRIDE_TARGET),)
ifeq ($(TARGET),)
@@ -31,3 +52,18 @@ endif
endif
+ifneq ($(TARGET),)
+ifneq ($(TARGET),win32)
+ifneq ($(findstring vxworks,$(TARGET)),vxworks)
+override TARGET := $(shell $(ERL_TOP)/erts/autoconf/config.sub $(TARGET))
+else
+endif
+else
+endif
+else
+endif
+
+ifeq ($(TARGET),)
+$(error Neither TARGET nor OVERRIDE_TARGET can be determined!)
+else
+endif
diff --git a/otp_build b/otp_build
index 44bbab22b5..1fee139666 100755
--- a/otp_build
+++ b/otp_build
@@ -51,7 +51,6 @@ usage ()
echo " release <target_dir> - creates a small release to <target_dir>"
echo " release [-a] <target_dir> - creates full release to <target_dir>"
echo " smp [-a] - build an Erlang system, smp flavor only"
- echo " hybrid [-a] - build an Erlang system, hybrid flavor only"
echo " tests <dir> - Build testsuites to <dir>"
echo ""
echo "These are for cleaning up an open source distribution"
@@ -65,8 +64,16 @@ usage ()
echo " installer_win32 <dir> - creates a windows installer from <dir>"
echo ""
echo "Before trying to build on windows, consider the following option"
- echo " env_win32 - echo environment settings for win32 with visual C++, use with eval"
+ echo " env_win32 [<arch>] - echo environment settings for win32 with visual C++, use with eval"
+ echo " The optional <arch> can be x64 for 64bit Windows 7"
+ echo " or x86 for 32bit Windows XP+"
+ echo " env_win64 - echo environment settings for win32 with visual C++, use with eval"
+ echo " Note that env_win32 x64 gives the same result, Windows 7 64bit"
echo " env_mingw32 - echo environment settings for win32 with MinGW, use with eval"
+ echo " - experimental!"
+ echo " env_msys64 - echo environment settings for win32 with visual C++ running "
+ echo " msys and mingw, use with eval"
+ echo " - experimental!"
echo ""
echo "Before trying to build for vxworks, consider the following option"
echo " env_vxworks <cpu> - echo environment settings for vxworks, use with eval"
@@ -76,7 +83,7 @@ usage ()
;;
git)
echo ""
- echo "update_primary - build and commit a new primary bootstrap"
+ echo "update_primary [--no-commit] - build and maybe commit a new primary bootstrap"
;;
esac
@@ -85,7 +92,7 @@ usage ()
;;
git)
echo ""
- echo "update_preloaded - build and commit the preloaded modules"
+ echo "update_preloaded [--no-commit] - build and maybe commit the preloaded modules"
;;
esac
}
@@ -174,9 +181,9 @@ set_config_flags ()
# the cross configuration have been moved here).
if target_contains linux; then
- XX=`echo $* | grep -v able-hipe`
+ XX=`echo $* | grep -v able-fp-exceptions`
if [ "$*" = "$XX" ]; then
- CONFIG_FLAGS="$CONFIG_FLAGS --disable-hipe"
+ CONFIG_FLAGS="$CONFIG_FLAGS --disable-fp-exceptions"
fi
fi
if target_contains "univel-sysv4"; then
@@ -255,9 +262,62 @@ create_lib_configure_in()
}
}
+find_sum()
+{
+ candidates="sum cksum md5sum sha1sum"
+ SUM_CMD="wc"
+ for x in $candidates; do
+ if (echo foo | $x > /dev/null 2>&1); then
+ SUM_CMD=$x
+ break
+ fi
+ done
+}
+
+chk_eq()
+{
+ master=$1
+ shift
+ slaves="$@"
+ master_sum=`$SUM_CMD $master | awk '{print $1}'`
+ for x in $slaves; do
+ s=`$SUM_CMD $x | awk '{print $1}'`
+ if test "$s" != "$master_sum"; then
+ echo "Error: $master and $x are not equal, make sure they are!" >&2
+ echo "Maybe you would want to:" >&2
+ echo "for x in $slaves; do cp $master \$x; done" >&2
+ echo "? Or something else is wrong." 2>&1
+ exit 2
+ fi
+ done
+}
+
+check_config_helpers ()
+{
+
+ aclocals="./aclocal.m4 ./lib/erl_interface/aclocal.m4 ./lib/odbc/aclocal.m4 ./lib/wx/aclocal.m4"
+ install_shs="./lib/common_test/priv/auxdir/install-sh ./lib/erl_interface/src/auxdir/install-sh ./lib/test_server/src/install-sh"
+ config_guesses="./lib/common_test/priv/auxdir/config.guess ./lib/erl_interface/src/auxdir/config.guess ./lib/test_server/src/config.guess"
+ config_subs="./lib/common_test/priv/auxdir/config.sub ./lib/erl_interface/src/auxdir/config.sub ./lib/test_server/src/config.sub"
+
+ aclocal_master="./erts/aclocal.m4"
+ install_sh_master="./erts/autoconf/install-sh"
+ config_guess_master="./erts/autoconf/config.guess"
+ config_sub_master="./erts/autoconf/config.sub"
+
+ find_sum
+
+ chk_eq $aclocal_master $aclocals
+ chk_eq $install_sh_master $install_shs
+ chk_eq $config_guess_master $config_guesses
+ chk_eq $config_sub_master $config_subs
+
+}
+
do_autoconf ()
{
create_lib_configure_in
+ check_config_helpers
if target_contains win32; then
# Select the correct autoconf on cygwin
@@ -324,16 +384,6 @@ do_autoconf ()
fi
}
-mk_targetdir ()
-{
- if [ ! -d $ERL_TOP/$TARGET ]; then
- echo "creating $ERL_TOP/$TARGET"
- mkdir $ERL_TOP/$TARGET
- else
- echo "existing $ERL_TOP/$TARGET is used"
- fi
-}
-
run_configure ()
{
cdir="$ERL_TOP"
@@ -491,6 +541,7 @@ maybe_copy_static_cache ()
{
if [ '!' -z "$OVERRIDE_CONFIG_CACHE_STATIC" ]; then
if [ '!' -z "$OVERRIDE_CONFIG_CACHE" ]; then
+ echo "Copying static configure cache $OVERRIDE_CONFIG_CACHE_STATIC to $OVERRIDE_CONFIG_CACHE"
cp -f "$OVERRIDE_CONFIG_CACHE_STATIC" "$OVERRIDE_CONFIG_CACHE"
fi
fi
@@ -499,7 +550,6 @@ maybe_copy_static_cache ()
do_configure ()
{
setup_make
- mk_targetdir
# Get `erl_build_tool_vars'
. "$ERL_TOP/erl-build-tool-vars.sh" || exit 1
@@ -513,7 +563,6 @@ do_configure ()
hide_vars OVERRIDE_TARGET TARGET
TARGET=$BUILDSYS
export TARGET
- mk_targetdir
set_config_flags "$@"
run_configure "$@"
restore_vars OVERRIDE_TARGET TARGET;;
@@ -743,7 +792,9 @@ echo_env_win32 ()
fi
done
IFS=$save_ifs
+ WIN32_WRAPPER_PATH="$ERL_TOP/erts/etc/win32/cygwin_tools/vc:$ERL_TOP/erts/etc/win32/cygwin_tools"
+
echo_setenv OVERRIDE_TARGET win32 ';'
echo_setenv CC cc.sh ';'
echo_setenv CXX cc.sh ';'
@@ -753,7 +804,8 @@ echo_env_win32 ()
echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/erts/autoconf/win32.config.cache.static" ';'
fi
echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win32.config.cache" ';'
- echo_setenv PATH "$ERL_TOP/erts/etc/win32/cygwin_tools/vc:$ERL_TOP/erts/etc/win32/cygwin_tools:$P3" ';'
+ echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
+ echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
echo_envinfo
}
@@ -815,6 +867,7 @@ echo_env_mingw32 ()
echo "needed for message file compilation: http://wine.sourceforge.net!!" >&2
return
fi
+ WIN32_WRAPPER_PATH="$ERL_TOP/erts/etc/win32/cygwin_tools/mingw:$ERL_TOP/erts/etc/win32/cygwin_tools"
echo_setenv OVERRIDE_TARGET win32 ';'
@@ -824,10 +877,184 @@ echo_env_mingw32 ()
echo_setenv CXX cc.sh ';'
echo_setenv AR ar.sh ';'
echo_setenv RANLIB true ';'
- echo_setenv PATH "$ERL_TOP/erts/etc/win32/cygwin_tools/mingw:$ERL_TOP/erts/etc/win32/cygwin_tools:$P3"
+ echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
+ echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
+ echo_envinfo
+}
+
+# N.B. In Erlang, and the build system, win32 means windows, so we keep
+# everything as terget win32, but add the CONFIG_SUBTYPE win64, which can
+# be handled by configure, setting WINDOWS_64BIT in headers and such
+echo_env_win64 ()
+{
+ #echo_envinfo
+ if [ X"$SHELL" = X"" ]; then
+ echo "You need to export the shell variable first," \
+ "for bourne-like shells, type:" >&2
+ echo 'export SHELL' >&2
+ echo "and for csh-like shells, type:" >&2
+ echo 'setenv SHELL $SHELL' >&2
+ echo " - then try again." >&2
+ exit 1
+ fi
+ echo_env_erltop
+ # Try to cope with paths containing unexpected things like stray
+ # mixed paths (c:/something/bin) and quotes. Only C and D drive
+ # handled.
+ CCYGPATH=`cygpath c:\\`
+ DCYGPATH=`cygpath d:\\`
+ P2=`echo :$PATH | \
+ sed "s,\",,g;s,:[cC]:,:$CCYGPATH,g;s,:[dD]:,:$DCYGPATH,g;s,^:,,"`
+ P3=""
+ save_ifs=$IFS
+ IFS=:
+ for p in $P2; do
+ if [ -d "$p" ]; then
+ C1="`(cygpath -d $p 2>/dev/null || cygpath -w $p)`" 2> /dev/null
+ C2=`cygpath "$C1" 2> /dev/null` 2> /dev/null
+ else
+ C2=""
+ fi
+ if [ ! -z "$C2" ]; then
+ if [ -z "$P3" ];then
+ P3="$C2"
+ else
+ P3="$P3:$C2"
+ fi
+ fi
+ done
+ IFS=$save_ifs
+ WIN32_WRAPPER_PATH="$ERL_TOP/erts/etc/win32/cygwin_tools/vc:$ERL_TOP/erts/etc/win32/cygwin_tools"
+
+
+ echo_setenv OVERRIDE_TARGET win32 ';'
+ echo_setenv CONFIG_SUBTYPE win64 ';'
+ echo_setenv CC cc.sh ';'
+ echo_setenv CXX cc.sh ';'
+ echo_setenv AR ar.sh ';'
+ echo_setenv RANLIB true ';'
+ if [ -f "$ERL_TOP/erts/autoconf/win64.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/erts/autoconf/win64.config.cache.static" ';'
+ fi
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win64.config.cache" ';'
+ echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
+ echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
echo_envinfo
}
+echo_env_msys32 ()
+{
+ #echo_envinfo
+ if [ X"$SHELL" = X"" ]; then
+ echo "You need to export the shell variable first," \
+ "for bourne-like shells, type:" >&2
+ echo 'export SHELL' >&2
+ echo "and for csh-like shells, type:" >&2
+ echo 'setenv SHELL $SHELL' >&2
+ echo " - then try again." >&2
+ exit 1
+ fi
+ echo_env_erltop
+ # Try to cope with paths containing unexpected things like stray
+ # mixed paths (c:/something/bin) and quotes. Only C and D drive
+ # handled.
+ P2=`echo :$PATH | \
+ sed "s,\",,g;s,:\([a-zA-Z]\):,:/\L\1,g;s,^:,,"`
+ P3=""
+ save_pwd=`pwd`
+ save_ifs=$IFS
+ IFS=:
+ for p in $P2; do
+ if [ -d "$p" ]; then
+ C1=`(cd "$p" && cmd //C "for %i in (".") do @echo %~fsi")`
+ C2=`echo "$C1" | sed 's,^\([a-zA-Z]\):\\\\,/\L\1/,;s,\\\\,/,g'`
+ else
+ C2=""
+ fi
+ if [ ! -z "$C2" ]; then
+ if [ -z "$P3" ];then
+ P3="$C2"
+ else
+ P3="$P3:$C2"
+ fi
+ fi
+ done
+ IFS=$save_ifs
+ WIN32_WRAPPER_PATH="$ERL_TOP/erts/etc/win32/msys_tools/vc:$ERL_TOP/erts/etc/win32/msys_tools"
+
+ echo_setenv OVERRIDE_TARGET win32 ';'
+ echo_setenv CC cc.sh ';'
+ echo_setenv CXX cc.sh ';'
+ echo_setenv AR ar.sh ';'
+ echo_setenv RANLIB true ';'
+ if [ -f "$ERL_TOP/erts/autoconf/win32.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/erts/autoconf/win32.config.cache.static" ';'
+ fi
+
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win32.config.cache" ';'
+ echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
+ echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
+ echo_envinfo
+}
+
+
+echo_env_msys64 ()
+{
+ #echo_envinfo
+ if [ X"$SHELL" = X"" ]; then
+ echo "You need to export the shell variable first," \
+ "for bourne-like shells, type:" >&2
+ echo 'export SHELL' >&2
+ echo "and for csh-like shells, type:" >&2
+ echo 'setenv SHELL $SHELL' >&2
+ echo " - then try again." >&2
+ exit 1
+ fi
+ echo_env_erltop
+ # Try to cope with paths containing unexpected things like stray
+ # mixed paths (c:/something/bin) and quotes. Only C and D drive
+ # handled.
+ P2=`echo :$PATH | \
+ sed "s,\",,g;s,:\([a-zA-Z]\):,:/\L\1,g;s,^:,,"`
+ P3=""
+ save_pwd=`pwd`
+ save_ifs=$IFS
+ IFS=:
+ for p in $P2; do
+ if [ -d "$p" ]; then
+ C1=`(cd "$p" && cmd //C "for %i in (".") do @echo %~fsi")`
+ C2=`echo "$C1" | sed 's,^\([a-zA-Z]\):\\\\,/\L\1/,;s,\\\\,/,g'`
+ else
+ C2=""
+ fi
+ if [ ! -z "$C2" ]; then
+ if [ -z "$P3" ];then
+ P3="$C2"
+ else
+ P3="$P3:$C2"
+ fi
+ fi
+ done
+ IFS=$save_ifs
+ WIN32_WRAPPER_PATH="$ERL_TOP/erts/etc/win32/msys_tools/vc:$ERL_TOP/erts/etc/win32/msys_tools"
+
+ echo_setenv OVERRIDE_TARGET win32 ';'
+ echo_setenv CONFIG_SUBTYPE win64 ';'
+ echo_setenv CC cc.sh ';'
+ echo_setenv CXX cc.sh ';'
+ echo_setenv AR ar.sh ';'
+ echo_setenv RANLIB true ';'
+ if [ -f "$ERL_TOP/erts/autoconf/win64.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/erts/autoconf/win64.config.cache.static" ';'
+ fi
+
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win64.config.cache" ';'
+ echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
+ echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
+ echo_envinfo
+}
+
+
lookup_prog_in_path ()
{
PROG=$1
@@ -866,33 +1093,61 @@ setup_make ()
fi
export MAKE
}
-
+
+get_do_commit ()
+{
+ if [ "x$1" = "x" ]; then
+ do_commit=true
+ elif [ "$1" = "--no-commit" ]; then
+ do_commit=false
+ else
+ echo "Unknown option '$1'" 1>&2
+ exit 1
+ fi
+}
+
do_primary_git ()
{
+ get_do_commit $1
setup_make
if [ "x$OVERRIDE_TARGET" != "x" -a "x$OVERRIDE_TARGET" != "xwin32" ]; then
do_primary_cross
else
$MAKE MAKE="$MAKE" BOOTSTRAP_ROOT=$BOOTSTRAP_ROOT TARGET=$TARGET primary_bootstrap || exit 1;
fi
- git add -A bootstrap/lib/kernel \
- bootstrap/lib/stdlib \
- bootstrap/lib/compiler \
- bootstrap/bin
- find bootstrap -name egen -o -name '*.script' -o \
- -name '*.app' -o -name '*.appup' |
+ if [ $do_commit = true ]; then
+ git add -A bootstrap/lib/kernel \
+ bootstrap/lib/stdlib \
+ bootstrap/lib/compiler \
+ bootstrap/bin
+ find bootstrap -name egen -o -name '*.script' -o \
+ -name '*.app' -o -name '*.appup' |
xargs git reset HEAD
- git commit --no-verify -m 'Update primary bootstrap'
+ git commit --no-verify -m 'Update primary bootstrap'
+ echo "Primary bootstrap updated and commited."
+ else
+ echo ""
+ echo "Primary bootstrap rebuilt. Use \"git add bootstrap/...\" to stage changed files."
+ echo ""
+ fi
}
do_update_prel_git ()
{
+ get_do_commit $1
setup_make
(cd $ERL_TOP/erts/preloaded/src && $MAKE MAKE="$MAKE" BOOTSTRAP_ROOT=$BOOTSTRAP_ROOT TARGET=$TARGET clean)
$MAKE MAKE="$MAKE" BOOTSTRAP_ROOT=$BOOTSTRAP_ROOT TARGET=$TARGET preloaded || exit 1
(cd $ERL_TOP/erts/preloaded/src && $MAKE MAKE="$MAKE" BOOTSTRAP_ROOT=$BOOTSTRAP_ROOT TARGET=$TARGET copy)
- git add -A $ERL_TOP/erts/preloaded/ebin/*.beam
- git commit -m 'Update preloaded modules'
+ if [ $do_commit = true ]; then
+ git add -A $ERL_TOP/erts/preloaded/ebin/*.beam
+ git commit -m 'Update preloaded modules'
+ echo "Preloaded updated and commited."
+ else
+ echo ""
+ echo "Preloaded rebuilt. Use \"git add erts/preloaded/ebin/...\" to stage changed beam files."
+ echo ""
+ fi
}
do_boot ()
@@ -1053,8 +1308,8 @@ cd $ERL_TOP
determine_version_controller
-# Unset ERL_FLAGS and ERL_<Release>_FLAGS to prevent, for instance,
-# a value of "-hybrid" to run the hybrid emulator during bootstrap.
+# Unset ERL_FLAGS and ERL_<Release>_FLAGS during bootstrap to
+# prevent potential problems
sys_vsn=`awk '/SYSTEM_VSN = / {print $3}' < erts/vsn.mk`
sys_erl_flags="ERL_${sys_vsn}_FLAGS"
unset ERL_FLAGS
@@ -1070,7 +1325,7 @@ BUILDSYS=$TARGET
case $TARGET in
*-cygwin)
if [ X"$BUILD_FOR_CYGWIN" = X"" ]; then
- if [ X"$OVERRIDE_TARGET" = X"" -a X"$1" != X"env_win32" -a X"$1" != X"env_mingw32" ];then
+ if [ X"$OVERRIDE_TARGET" = X"" -a X"$1" != X"env_win32" -a X"$1" != X"env_win64" -a X"$1" != X"env_mingw32" ];then
echo "Building for windows, you should do the " \
"following first:" >&2
echo 'eval `./otp_build env_win32`' >&2
@@ -1079,8 +1334,19 @@ case $TARGET in
exit 1
fi
fi;;
+ *-mingw32)
+ if [ X"$OVERRIDE_TARGET" = X"" -a X"$1" != X"env_win32" -a X"$1" != X"env_msys32" -a X"$1" != X"env_msys64" ];then
+ echo "Building for windows, you should do the " \
+ "following first:" >&2
+ echo 'eval `./otp_build env_win32`' >&2
+ echo 'or' >&2
+ echo 'eval `./otp_build env_win32 x64`' >&2
+ echo 'please note that there are backticks (``) in' \
+ 'the command'
+ exit 1
+ fi;;
*)
- ;;
+ ;;
esac
if [ ! -z "$OVERRIDE_TARGET" ]; then
@@ -1153,7 +1419,7 @@ case "$1" in
do_lazy_configure_target_clean;;
opt)
do_boot;;
- plain|smp|hybrid)
+ plain|smp)
if [ $minus_a_flag = false ]; then
TYPE=opt
fi;
@@ -1164,12 +1430,12 @@ case "$1" in
do_boot;;
update_primary)
case $version_controller in
- git) do_primary_git ;;
+ git) do_primary_git "$2";;
none) git_required ;;
esac ;;
update_preloaded)
case $version_controller in
- git) do_update_prel_git ;;
+ git) do_update_prel_git "$2";;
none) git_required ;;
esac ;;
primary)
@@ -1207,9 +1473,25 @@ case "$1" in
fi;
do_debuginfo_win32 "$2";;
env_win32)
- echo_env_win32;;
+ if [ x"$2" = x"x64" -o x"$2" = x"amd64" ]; then
+ if [ -x /usr/bin/msysinfo ]; then
+ echo_env_msys64
+ else
+ echo_env_win64
+ fi
+ else
+ if [ -x /usr/bin/msysinfo ]; then
+ echo_env_msys32
+ else
+ echo_env_win32
+ fi
+ fi;;
env_mingw32)
echo_env_mingw32;;
+ env_win64)
+ echo_env_win64;;
+ env_msys64)
+ echo_env_msys64;;
env_vxworks)
echo_env_vxworks "$2";;
env_cross)
diff --git a/system/COPYRIGHT b/system/COPYRIGHT
index 94e9795b16..7014f080d5 100644
--- a/system/COPYRIGHT
+++ b/system/COPYRIGHT
@@ -5,7 +5,7 @@ This software is subject to the following Copyrights and Licenses:
%CopyrightBegin%
-Copyright Ericsson AB 1997-2011. All Rights Reserved.
+Copyright Ericsson AB 1997-2012. All Rights Reserved.
The contents of this file are subject to the Erlang Public License,
Version 1.1, (the "License"); you may not use this file except in
@@ -245,3 +245,26 @@ terms specified in this license.
%% POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
+[eldap]
+
+Copyright (c) 2010, Torbjorn Tornkvist
+
+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
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+---------------------------------------------------------------------------
diff --git a/system/README b/system/README
index 234fc23dbd..b8ff18119d 100644
--- a/system/README
+++ b/system/README
@@ -1,7 +1,7 @@
-Erlang/OTP March 11, 2011
+Erlang/OTP December 8, 2011
-LAST MINUTE INFORMATION -- Release of Erlang 5.8.3/OTP R14B02
+Release of Erlang 5.9/OTP R15B
1. GENERAL
@@ -35,14 +35,15 @@ LAST MINUTE INFORMATION -- Release of Erlang 5.8.3/OTP R14B02
R11B-1). BEAM files from R10B or earlier are not supported.
To get the best performance, you should recompile your
- application code with the R14B02 compiler.
+ application code with the R15B compiler.
2. NOTES ABOUT THE SOLARIS VERSION
-------------------------------
-2.1 For the Sparc Solaris environment, Solaris8 (2.8) and above is
- supported. The emulator doesn't run on older Solaris versions.
+2.1 For the Sparc Solaris environment, Solaris10 (2.10) and above is
+ supported. The emulator runs on older Solaris 8 (2.8) versions
+ and above. Older Solaris versions are neither tested nor supported.
Also an Ultrasparc (sun4u architecture) is required.
@@ -61,7 +62,7 @@ LAST MINUTE INFORMATION -- Release of Erlang 5.8.3/OTP R14B02
4.1 The following linux distributions/version combinations are supported
and tested:
- Suse 9.4 x86, Suse 10.1 x86, Suse 10.1 x86_64
+ SuSE 10.1 x86, SuSE 10.1 x86_64, SuSE 11.0 x86, SuSE 11.0 x86_64
5. APPLICATIONS NOTES
------------------
diff --git a/system/doc/design_principles/Makefile b/system/doc/design_principles/Makefile
index ae951ba8d4..a9d4665ee4 100644
--- a/system/doc/design_principles/Makefile
+++ b/system/doc/design_principles/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
@@ -29,7 +29,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/design_principles
+RELSYSDIR = "$(RELEASE_PATH)/doc/design_principles"
# ----------------------------------------------------
# Target Specs
@@ -105,8 +105,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/design_principles/appup_cookbook.xml b/system/doc/design_principles/appup_cookbook.xml
index bc61578953..798b23d847 100644
--- a/system/doc/design_principles/appup_cookbook.xml
+++ b/system/doc/design_principles/appup_cookbook.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>
@@ -603,25 +603,60 @@ code_change(_OldVsn, State, port) ->
</section>
<section>
- <title>Emulator Restart</title>
- <p>If the emulator can or should be restarted, the very simple
- <c>.relup</c> file can be created manually:</p>
+ <title>Emulator Restart and Upgrade</title>
+ <p>There are two upgrade instructions that will restart the emulator:</p>
+ <taglist>
+ <tag><c>restart_new_emulator</c></tag>
+ <item>Intended for when erts, kernel, stdlib or sasl is
+ upgraded. It is automatically added when the relup file is
+ generated by <c>systools:make_relup/3,4</c>. It is executed
+ before all other upgrade instructions. See
+ <seealso marker="release_handling#restart_new_emulator_instr">Release
+ Handling</seealso> for more information about this
+ instruction.</item>
+ <tag><c>restart_emulator</c></tag>
+ <item>Used when a restart of the emulator is required after all
+ other upgrade instructions are executed. See
+ <seealso marker="release_handling#restart_emulator_instr">Release
+ Handling</seealso> for more information about this
+ instruction.</item>
+ </taglist>
+
+ <p>If an emulator restart is necessary and no upgrade instructions
+ are needed, i.e. if the restart itself is enough for the
+ upgraded applications to start running the new versions, a very
+ simple <c>.relup</c> file can be created manually:</p>
<code type="none">
{"B",
[{"A",
[],
- [restart_new_emulator]}],
+ [restart_emulator]}],
[{"A",
[],
- [restart_new_emulator]}]
+ [restart_emulator]}]
}.</code>
- <p>This way, the release handler framework with automatic packing
- and unpacking of release packages, automatic path updates etc. can
- be used without having to specify <c>.appup</c> files.</p>
- <p>If some transformation of persistent data, for example database
- contents, needs to be done before installing the new release
- version, instructions for this can be added to the <c>.relup</c>
- file as well.</p>
+ <p>In this case, the release handler framework with automatic
+ packing and unpacking of release packages, automatic path
+ updates etc. can be used without having to specify <c>.appup</c>
+ files.</p>
+ </section>
+
+ <section>
+ <title>Emulator Upgrade from pre OTP R15</title>
+ <p>From OTP R15, an emulator upgrade is performed by restarting
+ the emulator with new versions of the core applications
+ (<c>kernel</c>, <c>stdlib</c> and <c>sasl</c>) before loading code
+ and running upgrade instruction for other applications. For this
+ to work, the release to upgrade from must includes OTP R15 or
+ later. For the case where the release to upgrade from includes an
+ earlier emulator version, <c>systools:make_relup</c> will create a
+ backwards compatible relup file. This means that all upgrade
+ instructions will be executed before the emulator is
+ restarted. The new application code will therefore be loaded into
+ the old emulator. If the new code is compiled with the new
+ emulator, there might be cases where the beam format has changed
+ and beam files can not be loaded. To overcome this problem, the
+ new code should be compiled with the old emulator.</p>
</section>
</chapter>
diff --git a/system/doc/design_principles/make.dep b/system/doc/design_principles/make.dep
deleted file mode 100644
index 05dd2333fb..0000000000
--- a/system/doc/design_principles/make.dep
+++ /dev/null
@@ -1,31 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/gandalf/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: applications.tex appup_cookbook.tex book.tex \
- des_princ.tex distributed_applications.tex \
- events.tex fsm.tex gen_server_concepts.tex \
- included_applications.tex part.tex release_handling.tex \
- release_structure.tex spec_proc.tex sup_princ.tex
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: sup6.ps
-
-book.dvi: dist1.ps dist2.ps dist3.ps dist4.ps dist5.ps
-
-book.dvi: clientserver.ps
-
-book.dvi: inclappls.ps
-
-book.dvi: sup4.ps sup5.ps
-
diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml
index 1d62c242c0..4378b6599c 100644
--- a/system/doc/design_principles/release_handling.xml
+++ b/system/doc/design_principles/release_handling.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>
@@ -178,13 +178,13 @@
<marker id="instr"></marker>
<title>Release Handling Instructions</title>
<p>OTP supports a set of <em>release handling instructions</em>
- that is used when creating <c>.appup</c> files. The release
+ that are used when creating <c>.appup</c> files. The release
handler understands a subset of these, the <em>low-level</em>
instructions. To make it easier for the user, there are also a
number of <em>high-level</em> instructions, which are translated
to low-level instructions by <c>systools:make_relup</c>.</p>
<p>Here, some of the most frequently used instructions are
- described. The complete list of instructions is found in
+ described. The complete list of instructions can be found in
<c>appup(4)</c>.</p>
<p>First, some definitions:</p>
<taglist>
@@ -239,9 +239,10 @@
<p><c>update</c> with argument <c>supervisor</c> is used when
changing the start specification of a supervisor. See
<seealso marker="appup_cookbook#sup">Appup Cookbook</seealso>.</p>
- <p>The release handler finds the processes <em>using</em> a module
- to update by traversing the supervision tree of each running
- application and checking all the child specifications:</p>
+ <p>When a module is to be updated, the release handler finds
+ which processes that are <em>using</em> the module by
+ traversing the supervision tree of each running application
+ and checking all the child specifications:</p>
<code type="none">
{Id, StartFunc, Restart, Shutdown, Type, Modules}</code>
<p>A process is using a module if the name is listed in
@@ -265,8 +266,8 @@
<p>The instruction loads the module and is absolutely necessary
when running Erlang in embedded mode. It is not strictly
required when running Erlang in interactive (default) mode,
- since the code server automatically searches for and loads
- unloaded modules.</p>
+ since the code server then automatically searches for and
+ loads unloaded modules.</p>
<p>The opposite of <c>add_module</c> is <c>delete_module</c> which
unloads a module:</p>
<code type="none">
@@ -294,7 +295,7 @@
the modules are unloaded using a number of <c>delete_module</c>
instructions and then the application specification is unloaded
from the application controller.</p>
- <p>Instruction for removing an application:</p>
+ <p>Instruction for restarting an application:</p>
<code type="none">
{restart_application, Application}</code>
<p>Restarting an application means that the application is stopped
@@ -313,18 +314,35 @@
</section>
<section>
+ <marker id="restart_new_emulator_instr"></marker>
<title>restart_new_emulator (low-level)</title>
<p>This instruction is used when changing to a new emulator
- version, or if a system reboot is needed for some other reason.
- Requires that the system is started with heart beat
+ version, or when any of the core applications kernel, stdlib
+ or sasl is upgraded. If a system reboot is needed for some
+ other reason, the <c>restart_emulator</c> instruction should
+ be used instead.</p>
+ <p>Requires that the system is started with heart beat
monitoring, see <c>erl(1)</c> and <c>heart(3)</c>.</p>
- <p>When the release handler encounters the instruction, it shuts
- down the current emulator by calling <c>init:reboot()</c>, see
+ <p>The <c>restart_new_emulator</c> instruction shall always be
+ the very first instruction in a relup. If the relup is
+ generated by <c>systools:make_relup/3,4</c> this is
+ automatically ensured.</p>
+ <p>When the release handler encounters the instruction, it first
+ generates a temporary boot file, which starts the new versions
+ of the emulator and the core applications. Then it shuts down
+ the current emulator by calling <c>init:reboot()</c>, see
<c>init(3)</c>. All processes are terminated gracefully and
- the system can then be rebooted by the heart program, using
- the new release version. This new version must still be made
- permanent when the new emulator is up and running. Otherwise,
- the old version is used in case of a new system reboot.</p>
+ the system is rebooted by the heart program, using the
+ temporary boot file. After the reboot, the rest of the relup
+ instructions are executed. This is done as a part of the
+ temporary boot script.</p>
+ <p>An info report is written when the upgrade is completed. To
+ programatically find out if the upgrade is complete,
+ call <c>release_handler:which_releases(current)</c> and check
+ if it returns the expected (i.e. the new) release.</p>
+ <p>The new release version must be made permanent when the new
+ emulator is up and running. Otherwise, the old version will be
+ used in case of a new system reboot.</p>
<p>On UNIX, the release handler tells the heart program which
command to use to reboot the system. Note that the environment
variable <c>HEART_COMMAND</c>, normally used by the heart
@@ -333,6 +351,25 @@
by using the SASL configuration parameter <c>start_prg</c>, see
<c>sasl(6)</c>.</p>
</section>
+
+ <section>
+ <marker id="restart_emulator_instr"></marker>
+ <title>restart_emulator (low-level)</title>
+ <p>This instruction is not related to upgrades of erts or any of
+ the core applications. It can be used by any application to
+ force a restart of the emulator after all upgrade instructions
+ are executed.</p>
+ <p>There can only be one <c>restart_emulator</c> instruction in
+ a relup script, and it shall always be placed at the end. If
+ the relup is generated by <c>systools:make_relup/3,4</c> this
+ is automatically ensured.</p>
+ <p>When the release handler encounters the instruction, it shuts
+ down the emulator by calling <c>init:reboot()</c>, see
+ <c>init(3)</c>. All processes are terminated gracefully and
+ the system can then be rebooted by the heart program using the
+ new release version. No more upgrade instruction will be
+ executed after the restart.</p>
+ </section>
</section>
<section>
@@ -545,8 +582,8 @@ release_handler:remove_release(Vsn) => ok</code>
[].</code>
<p>2) Start the system as a simple target system. Note that in
reality, it should be started as an embedded system. However,
- using <c>erl</c> with the correct boot script and <c>.config</c>
- file is enough for illustration purposes:</p>
+ using <c>erl</c> with the correct boot script and config file is
+ enough for illustration purposes:</p>
<pre>
% <input>cd $ROOT</input>
% <input>bin/erl -boot $ROOT/releases/A/start -config $ROOT/releases/A/sys</input>
@@ -581,6 +618,7 @@ lib/ch_app-2/ebin/ch3.beam
releases/B/start.boot
releases/B/relup
releases/B/sys.config
+releases/B/ch_rel-2.rel
releases/ch_rel-2.rel</code>
<p>4) Copy the release package <c>ch_rel-2.tar.gz</c> to
the <c>$ROOT/releases</c> directory.</p>
diff --git a/system/doc/design_principles/release_structure.xml b/system/doc/design_principles/release_structure.xml
index 2e1daa611a..8aea0e1a10 100644
--- a/system/doc/design_principles/release_structure.xml
+++ b/system/doc/design_principles/release_structure.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>
@@ -61,12 +61,14 @@
{ApplicationN, AppVsnN}]}.</code>
<p>The file must be named <c>Rel.rel</c>, where <c>Rel</c> is a
unique name.</p>
- <p><c>Name</c>, <c>Vsn</c> and <c>Evsn</c> are strings.</p>
+ <p><c>Name</c>, <c>Vsn</c> and <c>EVsn</c> are strings.</p>
<p>Each <c>Application</c> (atom) and <c>AppVsn</c> (string) is
the name and version of an application included in the release.
- Note the the minimal release based on Erlang/OTP consists of
+ Note that the minimal release based on Erlang/OTP consists of
the <c>kernel</c> and <c>stdlib</c> applications, so these
applications must be included in the list.</p>
+ <p>If the release is to be upgraded, it must also include
+ the <c>sasl</c> application.</p>
<marker id="ch_rel"></marker>
<p>Example: We want to make a release of <c>ch_app</c> from
the <seealso marker="applications#ch_app">Applications</seealso>
@@ -173,6 +175,7 @@ lib/ch_app-1/ebin/ch_app.beam
lib/ch_app-1/ebin/ch_sup.beam
lib/ch_app-1/ebin/ch3.beam
releases/A/start.boot
+releases/A/ch_rel-1.rel
releases/ch_rel-1.rel</pre>
<p>Note that a new boot script was generated, without
the <c>local</c> option set, before the release package was made.
@@ -180,6 +183,17 @@ releases/ch_rel-1.rel</pre>
under <c>lib</c>. Also, we do not know where the release package
will be installed, so we do not want any hardcoded absolute paths
in the boot script here.</p>
+ <p>The release resource file <c>mysystem.rel</c> is duplicated in
+ the tar file. Originally, this file was only stored in
+ the <c>releases</c> directory in order to make it possible for
+ the <c>release_handler</c> to extract this file
+ separately. After unpacking the tar file, <c>release_handler</c>
+ would automatically copy the file
+ to <c>releases/FIRST</c>. However, sometimes the tar file is
+ unpacked without involving the <c>release_handler</c> (e.g. when
+ unpacking the first target system) and therefore the file is now
+ instead duplicated in the tar file so no manual copying is
+ necessary.</p>
<p>If a <c>relup</c> file and/or a system configuration file called
<c>sys.config</c> is found, these files are included in
the release package as well. See
diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index a1c862e004..f00de71a4c 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -108,7 +108,7 @@ ok
<list type="bulleted">
<item>be started in a way that makes the process fit into a
supervision tree,</item>
- <item>support the <c>sys</c><seealso marker="#debug">debug facilities</seealso>, and</item>
+ <item>support the <c>sys</c> <seealso marker="#debug">debug facilities</seealso>, and</item>
<item>take care of <seealso marker="#msg">system messages</seealso>.</item>
</list>
<p>System messages are messages with special meaning, used in
diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml
index 2748f21bbe..7ad007d3fd 100644
--- a/system/doc/design_principles/sup_princ.xml
+++ b/system/doc/design_principles/sup_princ.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2011</year>
+ <year>1997</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -136,7 +136,7 @@ init(...) ->
M = F = atom()
A = [term()]
Restart = permanent | transient | temporary
- Shutdown = brutal_kill | integer() &gt;=0 | infinity
+ Shutdown = brutal_kill | integer()>0 | infinity
Type = worker | supervisor
Modules = [Module] | dynamic
Module = atom()]]></code>
@@ -160,10 +160,13 @@ init(...) ->
be restarted.</p>
<list type="bulleted">
<item>A <c>permanent</c> child process is always restarted.</item>
- <item>A <c>temporary</c> child process is never restarted.</item>
+ <item>A <c>temporary</c> child process is never restarted
+ (not 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).</item>
<item>A <c>transient</c> child process is restarted only if it
terminates abnormally, i.e. with another exit reason than
- <c>normal</c>.</item>
+ <c>normal</c>, <c>shutdown</c> or <c>{shutdown,Term}</c>.</item>
</list>
</item>
<item>
@@ -181,8 +184,16 @@ init(...) ->
terminated using <c>exit(Child, kill)</c>.</item>
<item>If the child process is another supervisor, it should be
set to <c>infinity</c> to give the subtree enough time to
- shutdown.</item>
+ shutdown. It is also allowed to set it to <c>infinity</c>, if the
+ child process is a worker.</item>
</list>
+ <warning>
+ <p>Be careful by setting the <c>Shutdown</c> strategy to
+ <c>infinity</c> when the child process is a worker. Because, in this
+ situation, the termination of the supervision tree depends on the
+ child process, it must be implemented in a safe way and its cleanup
+ procedure must always return.</p>
+ </warning>
</item>
<item>
<p><c>Type</c> specifies if the child process is a supervisor or
@@ -341,6 +352,10 @@ call:start_link(id1)</code>
supervisor:terminate_child(Sup, Pid)</code>
<p>where <c>Sup</c> is the pid, or name, of the supervisor and
<c>Pid</c> is the pid of the child.</p>
+ <p>Because a <c>simple_one_for_one</c> supervisor could have many children,
+ it shuts them all down at same time. So, order in which they are stopped is
+ not defined. For the same reason, it could have an overhead with regards to
+ the <c>Shutdown</c> strategy.</p>
</section>
<section>
diff --git a/system/doc/efficiency_guide/Makefile b/system/doc/efficiency_guide/Makefile
index 2629285b42..1fd7b36453 100644
--- a/system/doc/efficiency_guide/Makefile
+++ b/system/doc/efficiency_guide/Makefile
@@ -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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/efficiency_guide
+RELSYSDIR = "$(RELEASE_PATH)/doc/efficiency_guide"
# ----------------------------------------------------
# Target Specs
@@ -106,8 +106,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/efficiency_guide/commoncaveats.xml b/system/doc/efficiency_guide/commoncaveats.xml
index 61d13636c0..ef0dee793d 100644
--- a/system/doc/efficiency_guide/commoncaveats.xml
+++ b/system/doc/efficiency_guide/commoncaveats.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,20 +33,6 @@
from a performance point of view.</p>
<section>
- <title>The regexp module</title>
-
- <p>The regular expression functions in the
- <seealso marker="stdlib:regexp">regexp</seealso>
- module are written in Erlang, not in C, and were
- meant for occasional use on small amounts of data,
- for instance for validation of configuration files
- when starting an application.</p>
-
- <p>Use the <seealso marker="stdlib:re">re</seealso> module
- (introduced in R13A) instead, especially in time-critical code.</p>
- </section>
-
- <section>
<title>The timer module</title>
<p>Creating timers using <seealso
diff --git a/system/doc/efficiency_guide/make.dep b/system/doc/efficiency_guide/make.dep
deleted file mode 100644
index afa3bd0516..0000000000
--- a/system/doc/efficiency_guide/make.dep
+++ /dev/null
@@ -1,16 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: advanced.tex binaryhandling.tex book.tex commoncaveats.tex \
- drivers.tex functions.tex introduction.tex listhandling.tex \
- myths.tex part.tex processes.tex profiling.tex \
- tablesDatabases.tex
-
diff --git a/system/doc/efficiency_guide/profiling.xml b/system/doc/efficiency_guide/profiling.xml
index 13165a0ede..cbb53c825e 100644
--- a/system/doc/efficiency_guide/profiling.xml
+++ b/system/doc/efficiency_guide/profiling.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2011</year>
+ <year>2001</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,9 +40,13 @@
<p>Erlang/OTP contains several tools to help finding bottlenecks.</p>
- <p><c>fprof</c> and <c>eprof</c> provide the most detailed information
- about where the time is spent, but they significantly slow downs the
- programs they profile.</p>
+ <p><c>fprof</c> provide the most detailed information
+ about where the time is spent, but it significantly slows down the
+ program it profiles.</p>
+
+ <p><c>eprof</c> provides time information of each function used
+ in the program. No callgraph is produced but <c>eprof</c> has
+ considerable less impact on the program profiled.</p>
<p>If the program is too big to be profiled by <c>fprof</c> or <c>eprof</c>,
<c>cover</c> and <c>cprof</c> could be used to locate parts of the
@@ -50,7 +54,7 @@
<c>eprof</c>.</p>
<p><c>cover</c> provides execution counts per line per process,
- with less overhead than <c>fprof/eprof</c>. Execution counts can
+ with less overhead than <c>fprof</c>. Execution counts can
with some caution be used to locate potential performance bottlenecks.
The most lightweight tool is <c>cprof</c>, but it only provides execution
counts on a function basis (for all processes, not per process).</p>
@@ -102,35 +106,45 @@
<section>
<title>fprof</title>
- <p><c>fprof</c> measures the execution time for each function,
+ <p>
+ <c>fprof</c> measures the execution time for each function,
both own time i.e how much time a function has used for its
own execution, and accumulated time i.e. including called
functions. The values are displayed per process. You also get
to know how many times each function has been
called. <c>fprof</c> is based on trace to file in order to
minimize runtime performance impact. Using fprof is just a
- matter of calling a few library functions, see fprof manual
- page under the application tools.</p>
- <p><c>fprof</c> was introduced in version R8 of Erlang/OTP. Its
- predecessor <c>eprof</c> that is based on the Erlang trace BIFs,
- is still available, see eprof manual page under the
- application tools. Eprof shows how much time has been used by
- each process, and in which function calls this time has been
- spent. Time is shown as percentage of total time, not as
- absolute time.</p>
+ matter of calling a few library functions, see
+ <seealso marker="tools:fprof">fprof</seealso>
+ manual page under the application tools.<c> fprof</c> was introduced in
+ version R8 of Erlang/OTP.
+ </p>
</section>
+ <section>
+ <title>eprof</title>
+ <p>
+ <c>eprof</c> is based on the Erlang trace_info BIFs. Eprof shows how much time has been used by
+ each process, and in which function calls this time has been
+ spent. Time is shown as percentage of total time and absolute time.
+ See <seealso marker="tools:eprof">eprof</seealso> for
+ additional information.
+ </p>
+ </section>
+
<section>
<title>cover</title>
- <p><c>cover</c>'s primary use is coverage analysis to verify
+ <p>
+ <c>cover</c>'s primary use is coverage analysis to verify
test cases, making sure all relevant code is covered.
<c>cover</c> counts how many times each executable line of
code is executed when a program is run. This is done on a per
module basis. Of course this information can be used to
determine what code is run very frequently and could therefore
be subject for optimization. Using cover is just a matter of
- calling a few library functions, see cover manual
- page under the application tools.</p>
+ calling a few library functions, see
+ <seealso marker="tools:cover">cover</seealso>
+ manual page under the application tools.</p>
</section>
<section>
@@ -139,8 +153,11 @@
<c>cover</c> regarding features. It counts how many times each
function is called when the program is run, on a per module
basis. <c>cprof</c> has a low performance degradation effect (versus
- <c>fprof</c> and <c>eprof</c>) and does not need to recompile
- any modules to profile (versus <c>cover</c>).</p>
+ <c>fprof</c>) and does not need to recompile
+ any modules to profile (versus <c>cover</c>).
+ See <seealso marker="tools:cprof">cprof</seealso> manual page for additional
+ information.
+ </p>
</section>
<section>
@@ -170,7 +187,7 @@
<cell align="left" valign="middle"><c>eprof </c></cell>
<cell align="left" valign="middle">per process/function to screen/file </cell>
<cell align="left" valign="middle">medium </cell>
- <cell align="left" valign="middle">significant slowdown </cell>
+ <cell align="left" valign="middle">small slowdown </cell>
<cell align="left" valign="middle">yes </cell>
<cell align="left" valign="middle">only total </cell>
<cell align="left" valign="middle">no </cell>
diff --git a/system/doc/embedded/Makefile b/system/doc/embedded/Makefile
index 70357efb1f..825fb23cfe 100644
--- a/system/doc/embedded/Makefile
+++ b/system/doc/embedded/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/embedded
+RELSYSDIR = "$(RELEASE_PATH)/doc/embedded"
# ----------------------------------------------------
# Target Specs
@@ -94,8 +94,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/embedded/make.dep b/system/doc/embedded/make.dep
deleted file mode 100644
index 9949a3ac96..0000000000
--- a/system/doc/embedded/make.dep
+++ /dev/null
@@ -1,14 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex embedded_nt.tex embedded_solaris.tex \
- part.tex vxworks.tex
-
diff --git a/system/doc/getting_started/Makefile b/system/doc/getting_started/Makefile
index 5d85ca2adc..972a51d3a5 100644
--- a/system/doc/getting_started/Makefile
+++ b/system/doc/getting_started/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/getting_started
+RELSYSDIR = "$(RELEASE_PATH)/doc/getting_started"
# ----------------------------------------------------
# Target Specs
@@ -93,8 +93,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/getting_started/make.dep b/system/doc/getting_started/make.dep
deleted file mode 100644
index 69b177f77c..0000000000
--- a/system/doc/getting_started/make.dep
+++ /dev/null
@@ -1,14 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex conc_prog.tex intro.tex part.tex \
- records_macros.tex robustness.tex seq_prog.tex
-
diff --git a/system/doc/installation_guide/Makefile b/system/doc/installation_guide/Makefile
index a47d77604d..4636650570 100644
--- a/system/doc/installation_guide/Makefile
+++ b/system/doc/installation_guide/Makefile
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/installation_guide
+RELSYSDIR = "$(RELEASE_PATH)/doc/installation_guide"
REDIRECT_HTML_RELSYSDIR = $(RELSYSDIR)/source
# ----------------------------------------------------
diff --git a/system/doc/installation_guide/make.dep b/system/doc/installation_guide/make.dep
deleted file mode 100644
index 3878f4ac9d..0000000000
--- a/system/doc/installation_guide/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex install-binary.tex part.tex verification.tex
-
diff --git a/system/doc/oam/Makefile b/system/doc/oam/Makefile
index 7732426ce6..f459f4349f 100644
--- a/system/doc/oam/Makefile
+++ b/system/doc/oam/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
@@ -29,7 +29,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/oam
+RELSYSDIR = "$(RELEASE_PATH)/doc/oam"
# ----------------------------------------------------
# Target Specs
diff --git a/system/doc/oam/make.dep b/system/doc/oam/make.dep
deleted file mode 100644
index 3694df9f1b..0000000000
--- a/system/doc/oam/make.dep
+++ /dev/null
@@ -1,26 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex oam_intro.tex part.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-oam_intro.tex: ../../../system/doc/definitions/term.defs
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: snmp_model_1.ps snmp_model_2.ps snmp_model_3.ps \
- terminology.ps
-
diff --git a/system/doc/programming_examples/Makefile b/system/doc/programming_examples/Makefile
index 8aeead9f6a..fcc51e3b18 100644
--- a/system/doc/programming_examples/Makefile
+++ b/system/doc/programming_examples/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/programming_examples
+RELSYSDIR = "$(RELEASE_PATH)/doc/programming_examples"
# ----------------------------------------------------
# Target Specs
diff --git a/system/doc/programming_examples/make.dep b/system/doc/programming_examples/make.dep
deleted file mode 100644
index b0655f56b3..0000000000
--- a/system/doc/programming_examples/make.dep
+++ /dev/null
@@ -1,20 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: bit_syntax.tex book.tex funs.tex list_comprehensions.tex \
- part.tex records.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-funs.tex: fun_test.erl funparse.erl funs1.erl
-
diff --git a/system/doc/reference_manual/Makefile b/system/doc/reference_manual/Makefile
index 2e1f8e71cb..87a477d14e 100644
--- a/system/doc/reference_manual/Makefile
+++ b/system/doc/reference_manual/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/reference_manual
+RELSYSDIR = "$(RELEASE_PATH)/doc/reference_manual"
# ----------------------------------------------------
# Target Specs
@@ -103,8 +103,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml
index f56e1ff408..0d2d7b2c2f 100644
--- a/system/doc/reference_manual/code_loading.xml
+++ b/system/doc/reference_manual/code_loading.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>
@@ -112,8 +112,8 @@ loop() ->
<c>code_switch</c> to it. The process then will make a fully
qualified call to <c>m:loop()</c> and change to current code.
Note that <c>m:loop/0</c> must be exported.</p>
- <p>For code replacement of funs to work, the tuple syntax
- <c>{Module,FunctionName}</c> must be used to represent the fun.</p>
+ <p>For code replacement of funs to work, the syntax
+ <c>fun Module:FunctionName/Arity</c> should be used.</p>
</section>
<section>
diff --git a/system/doc/reference_manual/distributed.xml b/system/doc/reference_manual/distributed.xml
index d0eac78404..bc55d14c90 100644
--- a/system/doc/reference_manual/distributed.xml
+++ b/system/doc/reference_manual/distributed.xml
@@ -176,11 +176,11 @@ dilbert@uab</pre>
</row>
<row>
<cell align="left" valign="middle"><c>is_alive()</c></cell>
- <cell align="left" valign="middle">Returns <c>true</c>if the runtime system is a node and can connect to other nodes, <c>false</c>otherwise.</cell>
+ <cell align="left" valign="middle">Returns <c>true</c> if the runtime system is a node and can connect to other nodes, <c>false</c> otherwise.</cell>
</row>
<row>
<cell align="left" valign="middle"><c>monitor_node(Node, true|false)</c></cell>
- <cell align="left" valign="middle">Monitor the status of <c>Node</c>. A message<c>{nodedown, Node}</c>is received if the connection to it is lost.</cell>
+ <cell align="left" valign="middle">Monitor the status of <c>Node</c>. A message<c>{nodedown, Node}</c> is received if the connection to it is lost.</cell>
</row>
<row>
<cell align="left" valign="middle"><c>node()</c></cell>
@@ -200,7 +200,7 @@ dilbert@uab</pre>
</row>
<row>
<cell align="left" valign="middle"><c>set_cookie(Node, Cookie)</c></cell>
- <cell align="left" valign="middle">Sets the magic cookie used when connecting to <c>Node</c>. If <c>Node</c>is the current node, <c>Cookie</c>will be used when connecting to all new nodes.</cell>
+ <cell align="left" valign="middle">Sets the magic cookie used when connecting to <c>Node</c>. If <c>Node</c> is the current node, <c>Cookie</c> will be used when connecting to all new nodes.</cell>
</row>
<row>
<cell align="left" valign="middle"><c>spawn[_link|_opt](Node, Fun)</c></cell>
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 497d7eb464..d564b20ca6 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2011</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -561,11 +561,15 @@ number &lt; atom &lt; reference &lt; fun &lt; port &lt; pid &lt; tuple &lt; list
<p>Lists are compared element by element. Tuples are ordered by
size, two tuples with the same size are compared element by
element.</p>
- <p>If one of the compared terms is an integer and the other a
- float, the integer is first converted into a float, unless the
- operator is one of =:= and =/=. If the integer is too big to fit
- in a float no conversion is done, but the order is determined by
- inspecting the sign of the numbers.</p>
+ <p>When comparing an integer to a float, the term with the lesser
+ precision will be converted into the other term's type, unless the
+ operator is one of =:= or =/=. A float is more precise than
+ an integer until all significant figures of the float are to the left of
+ the decimal point. This happens when the float is larger/smaller than
+ +/-9007199254740992.0. The conversion strategy is changed
+ depending on the size of the float because otherwise comparison of large
+ floats and integers would lose their transitivity.</p>
+
<p>Returns the Boolean value of the expression, <c>true</c> or
<c>false</c>.</p>
<p>Examples:</p>
@@ -681,7 +685,7 @@ Expr1 <input>op</input> Expr2</pre>
8> <input>2#10 bor 2#01.</input>
3
9> <input>a + 10.</input>
-** exception error: bad argument in an arithmetic expression
+** exception error: an error occurred when evaluating an arithmetic expression
in operator +/2
called as a + 10
10> <input>1 bsl (1 bsl 64).</input>
@@ -879,9 +883,8 @@ Ei = Value |
and UTF-32, respectively.</p>
<p>When constructing a segment of a <c>utf</c> type, <c>Value</c>
- must be an integer in one of the ranges 0..16#D7FF,
- 16#E000..16#FFFD, or 16#10000..16#10FFFF
- (i.e. a valid Unicode code point). Construction
+ must be an integer in the range 0..16#D7FF or
+ 16#E000....16#10FFFF. Construction
will fail with a <c>badarg</c> exception if <c>Value</c> is
outside the allowed ranges. The size of the resulting binary
segment depends on the type and/or <c>Value</c>. For <c>utf8</c>,
@@ -896,14 +899,13 @@ Ei = Value |
<c><![CDATA[<<$a/utf8,$b/utf8,$c/utf8>>]]></c>.</p>
<p>A successful match of a segment of a <c>utf</c> type results
- in an integer in one of the ranges 0..16#D7FF, 16#E000..16#FFFD,
- or 16#10000..16#10FFFF
- (i.e. a valid Unicode code point). The match will fail if returned value
+ in an integer in the range 0..16#D7FF or 16#E000..16#10FFFF.
+ The match will fail if returned value
would fall outside those ranges.</p>
<p>A segment of type <c>utf8</c> will match 1 to 4 bytes in the binary,
if the binary at the match position contains a valid UTF-8 sequence.
- (See RFC-2279 or the Unicode standard.)</p>
+ (See RFC-3629 or the Unicode standard.)</p>
<p>A segment of type <c>utf16</c> may match 2 or 4 bytes in the binary.
The match will fail if the binary at the match position does not contain
@@ -991,15 +993,19 @@ fun Module:Name/Arity</pre>
<pre>
fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end</pre>
<p>In <c>Module:Name/Arity</c>, <c>Module</c> and <c>Name</c> are atoms
- and <c>Arity</c> is an integer.
+ and <c>Arity</c> is an integer. Starting from the R15 release,
+ <c>Module</c>, <c>Name</c>, and <c>Arity</c> may also be variables.
A fun defined in this way will refer to the function <c>Name</c>
- with arity <c>Arity</c> in the <em>latest</em> version of module <c>Module</c>.
+ with arity <c>Arity</c> in the <em>latest</em> version of module
+ <c>Module</c>. A fun defined in this way will not be dependent on
+ the code for module in which it is defined.
</p>
<p>When applied to a number N of arguments, a tuple
<c>{Module,FunctionName}</c> is interpreted as a fun, referring
to the function <c>FunctionName</c> with arity N in the module
<c>Module</c>. The function must be exported.
- <em>This usage is deprecated.</em>
+ <em>This usage is deprecated.</em> Use <c>fun Module:Name/Arity</c>
+ instead.
See <seealso marker="#calls">Function Calls</seealso> for an example.</p>
<p>More examples can be found in <em>Programming Examples</em>.</p>
</section>
diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml
index 9dd5fc79bd..ef2db93f94 100644
--- a/system/doc/reference_manual/macros.xml
+++ b/system/doc/reference_manual/macros.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>
@@ -234,7 +234,7 @@ or
?TESTCALL(you:function(2,1)).</code>
<p>results in</p>
<code type="none">
-io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",m:myfunction(1,2)]),
+io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",myfunction(1,2)]),
io:format("Call ~s: ~w~n",["you : function ( 2 , 1 )",you:function(2,1)]).</code>
<p>That is, a trace output with both the function called and
the resulting value.</p>
diff --git a/system/doc/reference_manual/make.dep b/system/doc/reference_manual/make.dep
deleted file mode 100644
index 0e7687448c..0000000000
--- a/system/doc/reference_manual/make.dep
+++ /dev/null
@@ -1,16 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex code_loading.tex data_types.tex distributed.tex \
- errors.tex expressions.tex functions.tex introduction.tex \
- macros.tex modules.tex part.tex patterns.tex \
- ports.tex processes.tex records.tex
-
diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml
index 0dbc0ab56b..51c8157764 100644
--- a/system/doc/reference_manual/modules.xml
+++ b/system/doc/reference_manual/modules.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2010</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -114,6 +114,12 @@ fact(0) -> % |
<p>If this attribute is not specified, the version defaults
to the MD5 checksum of the module.</p>
</item>
+ <tag><c>-on_load(Function).</c></tag>
+ <item>
+ <p>Names a function that should be run automatically when a
+ module a loaded. See <seealso marker="code_loading#on_load">
+ code loading</seealso> for more information.</p>
+ </item>
</taglist>
</section>
@@ -180,7 +186,7 @@ fact(0) -> % |
<p>Read more in <seealso marker="typespec">Types and Function specifications</seealso>.
</p>
<p>
- The desciption is based on
+ The description is based on
<url href="http://www.erlang.org/eeps/eep-0008.html">EEP8 -
Types and function specifications</url>
which will not be further updated.
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index f08639f9a1..c3620f83f6 100755..100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2010</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/system/doc/system_architecture_intro/Makefile b/system/doc/system_architecture_intro/Makefile
index 8d677886b8..2de67473c1 100644
--- a/system/doc/system_architecture_intro/Makefile
+++ b/system/doc/system_architecture_intro/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/system_architecture_intro
+RELSYSDIR = "$(RELEASE_PATH)/doc/system_architecture_intro"
# ----------------------------------------------------
# Target Specs
@@ -88,8 +88,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/system_architecture_intro/make.dep b/system/doc/system_architecture_intro/make.dep
deleted file mode 100644
index 6b7bd860a0..0000000000
--- a/system/doc/system_architecture_intro/make.dep
+++ /dev/null
@@ -1,13 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex part.tex sys_arch_intro.tex
-
diff --git a/system/doc/system_principles/Makefile b/system/doc/system_principles/Makefile
index da109be211..4b7fc8f177 100644
--- a/system/doc/system_principles/Makefile
+++ b/system/doc/system_principles/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/system_principles
+RELSYSDIR = "$(RELEASE_PATH)/doc/system_principles"
# ----------------------------------------------------
# Target Specs
@@ -87,8 +87,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/system_principles/create_target.xml b/system/doc/system_principles/create_target.xml
deleted file mode 100644
index 7d9f4681b9..0000000000
--- a/system/doc/system_principles/create_target.xml
+++ /dev/null
@@ -1,497 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2009</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>Creating a First Target System</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2002-09-17</date>
- <rev>A</rev>
- <file>create_target.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>When creating a system using Erlang/OTP, the most simple way is
- to install Erlang/OTP somewhere, install the application specific
- code somewhere else, and then start the Erlang runtime system,
- making sure the code path includes the application specific code.</p>
- <p>Often it is not desirable to use an Erlang/OTP system as is. A
- developer may create new Erlang/OTP compliant applications for a
- particular purpose, and several original Erlang/OTP applications
- may be irrelevant for the purpose in question. Thus, there is a
- need to be able to create a new system based on a given
- Erlang/OTP system, where dispensable applications are removed,
- and a set of new applications that are included in the new
- system. Documentation and source code is irrelevant and is
- therefore not included in the new system.</p>
- <p>This chapter is about creating such a system, which we call a
- <em>target system</em>.</p>
- <p>In the following sections we consider creating target systems with
- different requirements of functionality:</p>
- <list type="bulleted">
- <item>a <em>basic target system</em> that can be started by
- calling the ordinary <c>erl</c> script, </item>
- <item>a <em>simple target system</em> where also code
- replacement in run-time can be performed, and</item>
- <item>an <em>embedded target system</em> where there is also
- support for logging output from the system to file for later
- inspection, and where the system can be started automatically
- at boot time. </item>
- </list>
- <p>We only consider the case when Erlang/OTP is running on a UNIX
- system.</p>
- <p>There is an example Erlang module <c>target_system.erl</c> that
- contains functions for creating and installing a target system.
- That module is used in the examples below. The source code of
- the module is listed at the end of this chapter.</p>
- </section>
-
- <section>
- <title>Creating a Target System</title>
- <p>It is assumed that you have a working Erlang/OTP system structured
- according to the OTP Design Principles.</p>
- <p><em>Step 1.</em> First create a <c>.rel</c> file (see
- <c>rel(4)</c>) that specifies the <c>erts</c> version
- and lists all applications that should be included in the new
- basic target system. An example is the following
- <c>mysystem.rel</c> file:</p>
- <code type="none">
-%% mysystem.rel
-{release,
- {"MYSYSTEM", "FIRST"},
- {erts, "5.1"},
- [{kernel, "2.7"},
- {stdlib, "1.10"},
- {sasl, "1.9.3"},
- {pea, "1.0"}]}. </code>
- <p>The listed applications are not only original Erlang/OTP
- applications but possibly also new applications that you have
- written yourself (here examplified by the application
- <c>pea</c>). </p>
- <p><em>Step 2.</em> From the directory where the <c>mysystem.rel</c>
- file reside, start the Erlang/OTP system:</p>
- <pre>
-os> <input>erl -pa /home/user/target_system/myapps/pea-1.0/ebin</input></pre>
- <p>where also the path to the <c>pea-1.0</c> ebin directory is
- provided. </p>
- <p><em>Step 3.</em> Now create the target system: </p>
- <pre>
-1> <input>target_system:create("mysystem").</input></pre>
- <p>The <c>target_system:create/1</c> function does the following:</p>
- <list type="ordered">
- <item>Reads the <c>mysystem.rel</c> file, and creates a new file
- <c>plain.rel</c> which is identical to former, except that it
- only lists the <c>kernel</c> and <c>stdlib</c> applications. </item>
- <item>From the <c>mysystem.rel</c> and <c>plain.rel</c> files
- creates the files <c>mysystem.script</c>,
- <c>mysystem.boot</c>, <c>plain.script</c>, and
- <c>plain.boot</c> through a call to
- <c>systools:make_script/2</c>.</item>
- <item>
- <p>Creates the file <c>mysystem.tar.gz</c> by a call to
- <c>systools:make_tar/2</c>. That file has the following
- contents:</p>
- <code type="none">
-erts-5.1/bin/
-releases/FIRST/start.boot
-releases/mysystem.rel
-lib/kernel-2.7/
-lib/stdlib-1.10/
-lib/sasl-1.9.3/
-lib/pea-1.0/ </code>
- <p>The file <c>releases/FIRST/start.boot</c> is a copy of our
- <c>mysystem.boot</c>, and a copy of the original
- <c>mysystem.rel</c> has been put in the <c>releases</c>
- directory.</p>
- </item>
- <item>Creates the temporary directory <c>tmp</c> and extracts the tar file
- <c>mysystem.tar.gz</c> into that directory. </item>
- <item>Deletes the <c>erl</c> and <c>start</c> files from
- <c>tmp/erts-5.1/bin</c>. XXX Why.</item>
- <item>Creates the directory <c>tmp/bin</c>.</item>
- <item>Copies the previously creates file <c>plain.boot</c> to
- <c>tmp/bin/start.boot</c>.</item>
- <item>Copies the files <c>epmd</c>, <c>run_erl</c>, and
- <c>to_erl</c> from the directory <c>tmp/erts-5.1/bin</c> to
- the directory <c>tmp/bin</c>.</item>
- <item>Creates the file <c>tmp/releases/start_erl.data</c> with the
- contents "5.1 FIRST".
- </item>
- <item>Recreates the file <c>mysystem.tar.gz</c> from the directories
- in the directory <c>tmp</c>, and removes <c>tmp</c>.</item>
- </list>
- </section>
-
- <section>
- <title>Installing a Target System</title>
- <p><em>Step 4.</em> Install the created target system in a
- suitable directory. </p>
- <pre>
-2> <input>target_system:install("mysystem", "/usr/local/erl-target").</input></pre>
- <p>The function <c>target_system:install/2</c> does the following:
- </p>
- <list type="ordered">
- <item>Extracts the tar file <c>mysystem.tar.gz</c> into the target
- directory <c>/usr/local/erl-target</c>.</item>
- <item>In the target directory reads the file <c>releases/start_erl.data</c>
- in order to find the Erlang runtime system version ("5.1").</item>
- <item>Substitutes <c>%FINAL_ROOTDIR%</c> and <c>%EMU%</c> for
- <c>/usr/local/erl-target</c> and <c>beam</c>, respectively, in
- the files <c>erl.src</c>, <c>start.src</c>, and
- <c>start_erl.src</c> of the target <c>erts-5.1/bin</c>
- directory, and puts the resulting files <c>erl</c>,
- <c>start</c>, and <c>run_erl</c> in the target <c>bin</c>
- directory.</item>
- <item>Finally the target <c>releases/RELEASES</c> file is created
- from data in the <c>releases/mysystem.rel</c> file.</item>
- </list>
- </section>
-
- <section>
- <title>Starting a Target System</title>
- <p>Now we have a target system that can be started in various ways.</p>
- <p>We start it as a <em>basic target system</em> by invoking</p>
- <pre>
-os> <input>/usr/local/erl-target/bin/erl</input></pre>
- <p>where only the <c>kernel</c> and <c>stdlib</c> applications are
- started, i.e. the system is started as an ordinary development
- system. There are only two files needed for all this to work:
- <c>bin/erl</c> file (obtained from <c>erts-5.1/bin/erl.src</c>)
- and the <c>bin/start.boot</c> file (a copy of <c>plain.boot</c>).</p>
- <p>We can also start a distributed system (requires <c>bin/epmd</c>).</p>
- <p>To start all applications specified in the original
- <c>mysystem.rel</c> file, use the <c>-boot</c> flag as follows:</p>
- <pre>
-os> <input>/usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FIRST/start</input></pre>
- <p>We start a <em>simple target system</em> as above. The only difference
- is that also the file <c>releases/RELEASES</c> is present for
- code replacement in run-time to work.</p>
- <p>To start an <em>embedded target system</em> the shell script
- <c>bin/start</c> is used. That shell script calls
- <c>bin/run_erl</c>, which in turn calls <c>bin/start_erl</c>
- (roughly, <c>start_erl</c> is an embedded variant of
- <c>erl</c>). </p>
- <p>The shell script <c>start</c> is only an example. You should
- edit it to suite your needs. Typically it is executed when the
- UNIX system boots.</p>
- <p><c>run_erl</c> is a wrapper that provides logging of output from
- the run-time system to file. It also provides a simple mechanism
- for attaching to the Erlang shell (<c>to_erl</c>).</p>
- <p><c>start_erl</c> requires the root directory
- (<c>"/usr/local/erl-target"</c>), the releases directory
- (<c>"/usr/local/erl-target/releases"</c>), and the location of
- the <c>start_erl.data</c> file. It reads the run-time system
- version (<c>"5.1"</c>) and release version (<c>"FIRST"</c>) from
- the <c>start_erl.data</c> file, starts the run-time system of the
- version found, and provides <c>-boot</c> flag specifying the boot
- file of the release version found
- (<c>"releases/FIRST/start.boot"</c>).</p>
- <p><c>start_erl</c> also assumes that there is <c>sys.config</c> in
- release version directory (<c>"releases/FIRST/sys.config</c>). That
- is the topic of the next section (see below).</p>
- <p>The <c>start_erl</c> shell script should normally not be
- altered by the user.</p>
- </section>
-
- <section>
- <title>System Configuration Parameters</title>
- <p>As was pointed out above <c>start_erl</c> requires a
- <c>sys.config</c> in the release version directory
- (<c>"releases/FIRST/sys.config"</c>). If there is no such a
- file, the system start will fail. Hence such a file has to
- added as well.</p>
- <p></p>
- <p>If you have system configuration data that are neither file
- location dependent nor site dependent, it may be convenient to
- create the <c>sys.config</c> early, so that it becomes a part of
- the target system tar file created by
- <c>target_system:create/1</c>. In fact, if you create, in the
- current directory, not only the <c>mysystem.rel</c> file, but
- also a <c>sys.config</c> file, that latter file will be tacitly
- put in the apropriate directory.</p>
- </section>
-
- <section>
- <title>Differences from the Install Script</title>
- <p>The above <c>install/2</c> procedure differs somewhat from that
- of the ordinary <c>Install</c> shell script. In fact, <c>create/1</c>
- makes the release package as complete as possible, and leave to the
- <c>install/2</c> procedure to finish by only considering location
- dependent files.</p>
- </section>
-
- <section>
- <title>Listing of target_system.erl</title>
- <code type="none"><![CDATA[
--module(target_system).
--include_lib("kernel/include/file.hrl").
--export([create/1, install/2]).
--define(BUFSIZE, 8192).
-
-%% Note: RelFileName below is the *stem* without trailing .rel,
-%% .script etc.
-%%
-
-%% create(RelFileName)
-%%
-create(RelFileName) ->
- RelFile = RelFileName ++ ".rel",
- io:fwrite("Reading file: \"~s\" ...~n", [RelFile]),
- {ok, [RelSpec]} = file:consult(RelFile),
- io:fwrite("Creating file: \"~s\" from \"~s\" ...~n",
- ["plain.rel", 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("plain.rel", [write]),
- io:fwrite(Fd, "~p.~n", [PlainRelSpec]),
- file:close(Fd),
-
- io:fwrite("Making \"plain.script\" and \"plain.boot\" files ...~n"),
- make_script("plain"),
-
- io:fwrite("Making \"~s.script\" and \"~s.boot\" files ...~n",
- [RelFileName, RelFileName]),
- make_script(RelFileName),
-
- TarFileName = io_lib:fwrite("~s.tar.gz", [RelFileName]),
- io:fwrite("Creating tar file \"~s\" ...~n", [TarFileName]),
- make_tar(RelFileName),
-
- io:fwrite("Creating directory \"tmp\" ...~n"),
- file:make_dir("tmp"),
-
- io:fwrite("Extracting \"~s\" into directory \"tmp\" ...~n", [TarFileName]),
- extract_tar(TarFileName, "tmp"),
-
- TmpBinDir = filename:join(["tmp", "bin"]),
- ErtsBinDir = filename:join(["tmp", "erts-" ++ ErtsVsn, "bin"]),
- io:fwrite("Deleting \"erl\" and \"start\" in directory \"~s\" ...~n",
- [ErtsBinDir]),
- file:delete(filename:join([ErtsBinDir, "erl"])),
- file:delete(filename:join([ErtsBinDir, "start"])),
-
- io:fwrite("Creating temporary directory \"~s\" ...~n", [TmpBinDir]),
- file:make_dir(TmpBinDir),
-
- io:fwrite("Copying file \"plain.boot\" to \"~s\" ...~n",
- [filename:join([TmpBinDir, "start.boot"])]),
- copy_file("plain.boot", filename:join([TmpBinDir, "start.boot"])),
-
- io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n"
- "\"~s\" to \"~s\" ...~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(["tmp", "releases", "start_erl.data"]),
- io:fwrite("Creating \"~s\" ...~n", [StartErlDataFile]),
- StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]),
- write_file(StartErlDataFile, StartErlData),
-
- io:fwrite("Recreating tar file \"~s\" from contents in directory "
- "\"tmp\" ...~n", [TarFileName]),
- {ok, Tar} = erl_tar:open(TarFileName, [write, compressed]),
- {ok, Cwd} = file:get_cwd(),
- file:set_cwd("tmp"),
- erl_tar:add(Tar, "bin", []),
- erl_tar:add(Tar, "erts-" ++ ErtsVsn, []),
- erl_tar:add(Tar, "releases", []),
- erl_tar:add(Tar, "lib", []),
- erl_tar:close(Tar),
- file:set_cwd(Cwd),
- io:fwrite("Removing directory \"tmp\" ...~n"),
- remove_dir_tree("tmp"),
- ok.
-
-
-install(RelFileName, RootDir) ->
- TarFile = RelFileName ++ ".tar.gz",
- io:fwrite("Extracting ~s ...~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)
-%%
-make_script(RelFileName) ->
- Opts = [no_module_tests],
- systools:make_script(RelFileName, Opts).
-
-%% make_tar(RelFileName)
-%%
-make_tar(RelFileName) ->
- RootDir = code:root_dir(),
- systools:make_tar(RelFileName, [{erts, RootDir}]).
-
-%% 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, InFd} = file:open(Src, [raw, binary, read]),
- {ok, OutFd} = file:open(Dest, [raw, binary, write]),
- do_copy_file(InFd, OutFd),
- file:close(InFd),
- file:close(OutFd),
- case lists:member(preserve, Opts) of
- true ->
- {ok, FileInfo} = file:read_file_info(Src),
- file:write_file_info(Dest, FileInfo);
- false ->
- ok
- end.
-
-do_copy_file(InFd, OutFd) ->
- case file:read(InFd, ?BUFSIZE) of
- {ok, Bin} ->
- file:write(OutFd, Bin),
- do_copy_file(InFd, OutFd);
- eof ->
- 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]),
- {ok, FileInfo} = file:read_file_info(FilePath),
- case FileInfo#file_info.type of
- directory ->
- {ok, DirFiles} = file:list_dir(FilePath),
- remove_all_files(FilePath, DirFiles),
- file:del_dir(FilePath);
- _ ->
- file:delete(FilePath)
- end
- end, Files).
- ]]></code>
- </section>
-</chapter>
-
diff --git a/system/doc/system_principles/create_target.xmlsrc b/system/doc/system_principles/create_target.xmlsrc
new file mode 100644
index 0000000000..bc2a76db47
--- /dev/null
+++ b/system/doc/system_principles/create_target.xmlsrc
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2002</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>Creating a First Target System</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2002-09-17</date>
+ <rev>A</rev>
+ <file>create_target.xml</file>
+ </header>
+
+ <section>
+ <title>Introduction</title>
+ <p>When creating a system using Erlang/OTP, the most simple way is
+ to install Erlang/OTP somewhere, install the application specific
+ code somewhere else, and then start the Erlang runtime system,
+ making sure the code path includes the application specific code.</p>
+ <p>Often it is not desirable to use an Erlang/OTP system as is. A
+ developer may create new Erlang/OTP compliant applications for a
+ particular purpose, and several original Erlang/OTP applications
+ may be irrelevant for the purpose in question. Thus, there is a
+ need to be able to create a new system based on a given
+ Erlang/OTP system, where dispensable applications are removed,
+ and a set of new applications are included. Documentation and
+ source code is irrelevant and is therefore not included in the
+ new system.</p>
+ <p>This chapter is about creating such a system, which we call a
+ <em>target system</em>.</p>
+ <p>In the following sections we consider creating target systems with
+ different requirements of functionality:</p>
+ <list type="bulleted">
+ <item>a <em>basic target system</em> that can be started by
+ calling the ordinary <c>erl</c> script, </item>
+ <item>a <em>simple target system</em> where also code
+ replacement in run-time can be performed, and</item>
+ <item>an <em>embedded target system</em> where there is also
+ support for logging output from the system to file for later
+ inspection, and where the system can be started automatically
+ at boot time. </item>
+ </list>
+ <p>We only consider the case when Erlang/OTP is running on a UNIX
+ system.</p>
+ <p>In the <c>sasl</c> application there is an example Erlang
+ module <c>target_system.erl</c> that contains functions for
+ creating and installing a target system. This module is used in
+ the examples below, and the source code of the module is listed
+ at the end of this chapter.</p>
+ </section>
+
+ <section>
+ <title>Creating a Target System</title>
+ <p>It is assumed that you have a working Erlang/OTP system structured
+ according to the OTP Design Principles.</p>
+ <p><em>Step 1.</em> First create a <c>.rel</c> file (see
+ <c>rel(4)</c>) that specifies the <c>erts</c> version
+ and lists all applications that should be included in the new
+ basic target system. An example is the following
+ <c>mysystem.rel</c> file:</p>
+ <code type="none">
+%% mysystem.rel
+{release,
+ {"MYSYSTEM", "FIRST"},
+ {erts, "5.1"},
+ [{kernel, "2.7"},
+ {stdlib, "1.10"},
+ {sasl, "1.9.3"},
+ {pea, "1.0"}]}. </code>
+ <p>The listed applications are not only original Erlang/OTP
+ applications but possibly also new applications that you have
+ written yourself (here examplified by the application
+ <c>pea</c>). </p>
+ <p><em>Step 2.</em> From the directory where the <c>mysystem.rel</c>
+ file reside, start the Erlang/OTP system:</p>
+ <pre>
+os> <input>erl -pa /home/user/target_system/myapps/pea-1.0/ebin</input></pre>
+ <p>where also the path to the <c>pea-1.0</c> ebin directory is
+ provided. </p>
+ <p><em>Step 3.</em> Now create the target system: </p>
+ <pre>
+1> <input>target_system:create("mysystem").</input></pre>
+ <p>The <c>target_system:create/1</c> function does the following:</p>
+ <list type="ordered">
+ <item>Reads the <c>mysystem.rel</c> file, and creates a new file
+ <c>plain.rel</c> which is identical to former, except that it
+ only lists the <c>kernel</c> and <c>stdlib</c> applications. </item>
+ <item>From the <c>mysystem.rel</c> and <c>plain.rel</c> files
+ creates the files <c>mysystem.script</c>,
+ <c>mysystem.boot</c>, <c>plain.script</c>, and
+ <c>plain.boot</c> through a call to
+ <c>systools:make_script/2</c>.</item>
+ <item>
+ <p>Creates the file <c>mysystem.tar.gz</c> by a call to
+ <c>systools:make_tar/2</c>. That file has the following
+ contents:</p>
+ <code type="none">
+erts-5.1/bin/
+releases/FIRST/start.boot
+releases/FIRST/mysystem.rel
+releases/mysystem.rel
+lib/kernel-2.7/
+lib/stdlib-1.10/
+lib/sasl-1.9.3/
+lib/pea-1.0/ </code>
+ <p>The file <c>releases/FIRST/start.boot</c> is a copy of our
+ <c>mysystem.boot</c></p>
+ <p>The release resource file <c>mysystem.rel</c> is duplicated
+ in the tar file. Originally, this file was only stored in
+ the <c>releases</c> directory in order to make it possible
+ for the <c>release_handler</c> to extract this file
+ separately. After unpacking the tar
+ file, <c>release_handler</c> would automatically copy the
+ file to <c>releases/FIRST</c>. However, sometimes the tar
+ file is unpacked without involving
+ the <c>release_handler</c> (e.g. when unpacking the first
+ target system) and therefore the file is now instead
+ duplicated in the tar file so no manual copying is
+ necessary.</p>
+ </item>
+ <item>Creates the temporary directory <c>tmp</c> and extracts the tar file
+ <c>mysystem.tar.gz</c> into that directory. </item>
+ <item>Deletes the <c>erl</c> and <c>start</c> files from
+ <c>tmp/erts-5.1/bin</c>. These files will be created again from
+ source when installing the release.</item>
+ <item>Creates the directory <c>tmp/bin</c>.</item>
+ <item>Copies the previously created file <c>plain.boot</c> to
+ <c>tmp/bin/start.boot</c>.</item>
+ <item>Copies the files <c>epmd</c>, <c>run_erl</c>, and
+ <c>to_erl</c> from the directory <c>tmp/erts-5.1/bin</c> to
+ the directory <c>tmp/bin</c>.</item>
+ <item>Creates the file <c>tmp/releases/start_erl.data</c> with
+ the contents "5.1 FIRST". This file is to be passed as data
+ file to the <c>start_erl</c> script.
+ </item>
+ <item>Recreates the file <c>mysystem.tar.gz</c> from the directories
+ in the directory <c>tmp</c>, and removes <c>tmp</c>.</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Installing a Target System</title>
+ <p><em>Step 4.</em> Install the created target system in a
+ suitable directory. </p>
+ <pre>
+2> <input>target_system:install("mysystem", "/usr/local/erl-target").</input></pre>
+ <p>The function <c>target_system:install/2</c> does the following:
+ </p>
+ <list type="ordered">
+ <item>Extracts the tar file <c>mysystem.tar.gz</c> into the target
+ directory <c>/usr/local/erl-target</c>.</item>
+ <item>In the target directory reads the file <c>releases/start_erl.data</c>
+ in order to find the Erlang runtime system version ("5.1").</item>
+ <item>Substitutes <c>%FINAL_ROOTDIR%</c> and <c>%EMU%</c> for
+ <c>/usr/local/erl-target</c> and <c>beam</c>, respectively, in
+ the files <c>erl.src</c>, <c>start.src</c>, and
+ <c>start_erl.src</c> of the target <c>erts-5.1/bin</c>
+ directory, and puts the resulting files <c>erl</c>,
+ <c>start</c>, and <c>run_erl</c> in the target <c>bin</c>
+ directory.</item>
+ <item>Finally the target <c>releases/RELEASES</c> file is created
+ from data in the <c>releases/mysystem.rel</c> file.</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Starting a Target System</title>
+ <p>Now we have a target system that can be started in various ways.</p>
+ <p>We start it as a <em>basic target system</em> by invoking</p>
+ <pre>
+os> <input>/usr/local/erl-target/bin/erl</input></pre>
+ <p>where only the <c>kernel</c> and <c>stdlib</c> applications are
+ started, i.e. the system is started as an ordinary development
+ system. There are only two files needed for all this to work:
+ <c>bin/erl</c> file (obtained from <c>erts-5.1/bin/erl.src</c>)
+ and the <c>bin/start.boot</c> file (a copy of <c>plain.boot</c>).</p>
+ <p>We can also start a distributed system (requires <c>bin/epmd</c>).</p>
+ <p>To start all applications specified in the original
+ <c>mysystem.rel</c> file, use the <c>-boot</c> flag as follows:</p>
+ <pre>
+os> <input>/usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FIRST/start</input></pre>
+ <p>We start a <em>simple target system</em> as above. The only difference
+ is that also the file <c>releases/RELEASES</c> is present for
+ code replacement in run-time to work.</p>
+ <p>To start an <em>embedded target system</em> the shell script
+ <c>bin/start</c> is used. That shell script calls
+ <c>bin/run_erl</c>, which in turn calls <c>bin/start_erl</c>
+ (roughly, <c>start_erl</c> is an embedded variant of
+ <c>erl</c>). </p>
+ <p>The shell script <c>start</c> is only an example. You should
+ edit it to suite your needs. Typically it is executed when the
+ UNIX system boots.</p>
+ <p><c>run_erl</c> is a wrapper that provides logging of output from
+ the run-time system to file. It also provides a simple mechanism
+ for attaching to the Erlang shell (<c>to_erl</c>).</p>
+ <p><c>start_erl</c> requires the root directory
+ (<c>"/usr/local/erl-target"</c>), the releases directory
+ (<c>"/usr/local/erl-target/releases"</c>), and the location of
+ the <c>start_erl.data</c> file. It reads the run-time system
+ version (<c>"5.1"</c>) and release version (<c>"FIRST"</c>) from
+ the <c>start_erl.data</c> file, starts the run-time system of the
+ version found, and provides <c>-boot</c> flag specifying the boot
+ file of the release version found
+ (<c>"releases/FIRST/start.boot"</c>).</p>
+ <p><c>start_erl</c> also assumes that there is <c>sys.config</c> in
+ release version directory (<c>"releases/FIRST/sys.config"</c>). That
+ is the topic of the next section (see below).</p>
+ <p>The <c>start_erl</c> shell script should normally not be
+ altered by the user.</p>
+ </section>
+
+ <section>
+ <title>System Configuration Parameters</title>
+ <p>As was pointed out above <c>start_erl</c> requires a
+ <c>sys.config</c> in the release version directory
+ (<c>"releases/FIRST/sys.config"</c>). If there is no such a
+ file, the system start will fail. Hence such a file has to
+ be added as well.</p>
+ <p></p>
+ <p>If you have system configuration data that are neither file
+ location dependent nor site dependent, it may be convenient to
+ create the <c>sys.config</c> early, so that it becomes a part of
+ the target system tar file created by
+ <c>target_system:create/1</c>. In fact, if you create, in the
+ current directory, not only the <c>mysystem.rel</c> file, but
+ also a <c>sys.config</c> file, that latter file will be tacitly
+ put in the apropriate directory.</p>
+ </section>
+
+ <section>
+ <title>Differences from the Install Script</title>
+ <p>The above <c>install/2</c> procedure differs somewhat from that
+ of the ordinary <c>Install</c> shell script. In fact, <c>create/1</c>
+ makes the release package as complete as possible, and leave to the
+ <c>install/2</c> procedure to finish by only considering location
+ dependent files.</p>
+ </section>
+
+ <section>
+ <title>Listing of target_system.erl</title>
+ <p>This module can also be found in the <c>examples</c> directory
+ of the <c>sasl</c> application.</p>
+ <codeinclude file="../../../lib/sasl/examples/src/target_system.erl" tag="%module" type="erl"></codeinclude>
+
+ </section>
+</chapter>
diff --git a/system/doc/system_principles/make.dep b/system/doc/system_principles/make.dep
deleted file mode 100644
index 28753ca5a0..0000000000
--- a/system/doc/system_principles/make.dep
+++ /dev/null
@@ -1,14 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex create_target.tex error_logging.tex \
- part.tex system_principles.tex
-
diff --git a/system/doc/top/Makefile b/system/doc/top/Makefile
index aac90fcaa4..bbdb4d7055 100644
--- a/system/doc/top/Makefile
+++ b/system/doc/top/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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc
+RELSYSDIR = "$(RELEASE_PATH)/doc"
GIF_FILES =
@@ -165,7 +165,7 @@ $(HTMLDIR)/highlights.html: highlights.xml
date=`date +"%B %e %Y"`; \
$(XSLTPROC) --output $(@) --stringparam docgen "$(DOCGEN)" --stringparam topdocdir "$(TOPDOCDIR)" \
--stringparam pdfdir "$(PDFREFDIR)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" \
- --stringparam appver "$(VSN)" -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities \
+ --stringparam appver "$(VSN)" -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_html_entities \
$(DOCGEN)/priv/xsl/db_html.xsl $<
@@ -173,7 +173,7 @@ $(HTMLDIR)/incompatible.html: incompatible.xml
date=`date +"%B %e %Y"`; \
$(XSLTPROC) --output $(@) --stringparam docgen "$(DOCGEN)" --stringparam topdocdir "$(TOPDOCDIR)" \
--stringparam pdfdir "$(PDFREFDIR)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" \
- --stringparam appver "$(VSN)" -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities \
+ --stringparam appver "$(VSN)" -path $(DOCGEN)/priv/dtd -path $(DOCGEN)/priv/dtd_html_entities \
$(DOCGEN)/priv/xsl/db_html.xsl $<
#--------------------------------------------------------------------------
@@ -233,8 +233,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
- $(INSTALL_DIR) $(RELEASE_PATH)
- $(INSTALL_DATA) $(INFO_FILES) $(RELEASE_PATH)
+ $(INSTALL_DIR) "$(RELEASE_PATH)"
+ $(INSTALL_DATA) $(INFO_FILES) "$(RELEASE_PATH)"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DIR) $(RELSYSDIR)/pdf
$(INSTALL_DATA) \
diff --git a/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl
index bb6a9a9f0a..1e2b8c86af 100644
--- a/system/doc/top/src/erl_html_tools.erl
+++ b/system/doc/top/src/erl_html_tools.erl
@@ -624,17 +624,9 @@ lines_to_key_value([Line | Lines]) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Extensions to the 'regexp' module.
+% Regular expression helpers.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% is_match(Ex, Re) ->
-%% case regexp:first_match(Ex, Re) of
-%% {match, _, _} ->
-%% true;
-%% nomatch ->
-%% false
-%% end.
-
%% -type gsub(String, RegExp, Fun, Acc) -> subres().
%% Substitute every match of the regular expression RegExp with the
%% string returned from the function Fun(Match, Acc). Accept pre-parsed
diff --git a/system/doc/tutorial/Makefile b/system/doc/tutorial/Makefile
index d48082484c..e9eb800e46 100644
--- a/system/doc/tutorial/Makefile
+++ b/system/doc/tutorial/Makefile
@@ -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
@@ -30,7 +30,7 @@ APPLICATION=otp-system-documentation
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/doc/tutorial
+RELSYSDIR = "$(RELEASE_PATH)/doc/tutorial"
# ----------------------------------------------------
# Target Specs
@@ -114,8 +114,8 @@ clean clean_docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
-# $(INSTALL_DIR) $(RELEASE_PATH)/pdf
-# $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+# $(INSTALL_DIR) "$(RELEASE_PATH)/pdf"
+# $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf"
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTMLDIR)/*.html \
$(RELSYSDIR)
diff --git a/system/doc/tutorial/c_portdriver.xmlsrc b/system/doc/tutorial/c_portdriver.xmlsrc
index f875fa80d2..09a89f792a 100644
--- a/system/doc/tutorial/c_portdriver.xmlsrc
+++ b/system/doc/tutorial/c_portdriver.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -68,8 +68,8 @@
start(SharedLib) ->
case erl_ddll:load_driver(".", SharedLib) of
ok -> ok;
-\011{error, already_loaded} -> ok;
-\011_ -> exit({error, could_not_load_driver})
+ {error, already_loaded} -> ok;
+ _ -> exit({error, could_not_load_driver})
end,
spawn(?MODULE, init, [SharedLib]).
@@ -102,7 +102,7 @@ loop(Port) ->
{call, Caller, Msg} ->
Port ! {self(), {command, encode(Msg)}},
receive
-\011 {Port, {data, Data}} ->
+ {Port, {data, Data}} ->
Caller ! {complex, decode(Data)}
end,
loop(Port)
diff --git a/system/doc/tutorial/make.dep b/system/doc/tutorial/make.dep
deleted file mode 100644
index e9f77ab439..0000000000
--- a/system/doc/tutorial/make.dep
+++ /dev/null
@@ -1,35 +0,0 @@
-# ----------------------------------------------------
-# >>>> Do not edit this file <<<<
-# This file was automaticly generated by
-# /home/otp/bin/docdepend
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# TeX files that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: book.tex c_port.tex c_portdriver.tex cnode.tex \
- erl_interface.tex example.tex introduction.tex \
- overview.tex part.tex
-
-# ----------------------------------------------------
-# Source inlined when transforming from source to LaTeX
-# ----------------------------------------------------
-
-c_port.tex: port.c
-
-c_portdriver.tex: port_driver.c
-
-cnode.tex: complex3.erl
-
-example.tex: complex.c
-
-# ----------------------------------------------------
-# Pictures that the DVI file depend on
-# ----------------------------------------------------
-
-book.dvi: port.ps
-
-book.dvi: port_driver.ps
-
diff --git a/xcomp/README.md b/xcomp/README.md
index 2d79107283..7217fea5fb 100644
--- a/xcomp/README.md
+++ b/xcomp/README.md
@@ -291,6 +291,38 @@ and then do the cross build of the system.
`otp_build release -a` will do the same as (5), and you will after this have
to do a manual install either by doing (6), or (7).
+Testing the cross compiled system
+--------------------------------------
+Some of the tests that come with erlang use native code to test. This means
+that when cross compiling erlang you also have to cross compile test suites
+in order to run tests on the target host. To do this you first have to release
+the tests as usual.
+
+ $ make release_tests
+
+or
+
+ $ ./otp_build tests
+
+The tests will be released into `$ERL_TOP/release/tests`. After releasing the
+tests you have to install the tests on the build machine. You supply the same
+xcomp file as to `./otp_build` in (9).
+
+ $ cd $ERL_TOP/release/tests/test_server/
+ $ $ERL_TOP/bootstrap/bin/erl -eval 'ts:install([{xcomp,"<FILE>"}])' -s ts compile_testcases -s init stop
+
+You should get a lot of printouts as the testcases are compiled. Once done you
+should copy the entire `$ERL_TOP/release/tests` folder to the cross host system.
+
+Then go to the cross host system and setup the erlang installed in (4) or (5)
+to be in your `$PATH`. Then go to what previously was
+`$ERL_TOP/release/tests/test_server` and issue the following command.
+
+ $ erl -s ts install -s ts run all_tests -s init stop
+
+The configure should be skipped and all tests should hopefully pass. For more
+details about how to use ts run `erl -s ts help -s init stop`
+
Currently Used Configuration Variables
--------------------------------------
@@ -430,6 +462,10 @@ When a variable has been set, no warning will be issued.
`configure` will fail unless this variable is set. Since no default
value is used, `configure` will try to figure this out automatically.
+* `erl_xcomp_double_middle` - `yes|no`. Defaults to `no`.
+ If `yes`, the target system must have doubles in "middle-endian" format. If
+ `no`, it has "regular" endianness.
+
* `erl_xcomp_clock_gettime_cpu_time` - `yes|no`. Defaults to `no`. If `yes`,
the target system must have a working `clock_gettime()` implementation
that can be used for retrieving process CPU time.
diff --git a/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf b/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
index f9fff0fa8e..287cb787d9 100644
--- a/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
+++ b/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
@@ -187,6 +187,15 @@ erl_xcomp_sysroot="$TILERA_ROOT/tile"
# value is used, `configure' will try to figure this out automatically.
#erl_xcomp_bigendian=
+# * `erl_xcomp_double_middle_endian` - `yes|no`. No default. If `yes`, the
+# target system must have doubles in "middle-endian" format. If
+# `no`, it has "regular" endianness. This can often be automatically
+# detected, but not always. If not automatically detected,
+# `configure` will fail unless this variable is set. Since no
+# default value is used, `configure` will try to figure this out
+# automatically.
+#erl_xcomp_double_middle_endian
+
# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
# the target system must have a working `clock_gettime()' implementation
# that can be used for retrieving process CPU time.
diff --git a/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf b/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
index f691c6cfd1..e86043f5c8 100644
--- a/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
+++ b/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2010. All Rights Reserved.
+## Copyright Ericsson AB 2010-2012. All Rights Reserved.
##
## The 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,7 @@ erl_xcomp_host=avr32-atmel-linux-gnu
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
# `configure' script.
-#erl_xcomp_configure_flags=
+erl_xcomp_configure_flags="--disable-hipe --disable-threads --disable-smp"
## -- Cross Compiler and Other Tools -------------------------------------------
@@ -73,7 +73,7 @@ erl_xcomp_host=avr32-atmel-linux-gnu
CC=avr32-linux-gcc
# * `CFLAGS' - C compiler flags.
-#CFLAGS=
+CFLAGS="-O -Dfinite=__finite"
# * `STATIC_CFLAGS' - Static C compiler flags.
#STATIC_CFLAGS=
@@ -190,6 +190,15 @@ erl_xcomp_sysroot="$ATMEL_SYSROOT_AVR32"
# value is used, `configure' will try to figure this out automatically.
#erl_xcomp_bigendian=
+# * `erl_xcomp_double_middle_endian` - `yes|no`. No default. If `yes`, the
+# target system must have doubles in "middle-endian" format. If
+# `no`, it has "regular" endianness. This can often be automatically
+# detected, but not always. If not automatically detected,
+# `configure` will fail unless this variable is set. Since no
+# default value is used, `configure` will try to figure this out
+# automatically.
+#erl_xcomp_double_middle_endian
+
# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
# the target system must have a working `clock_gettime()' implementation
# that can be used for retrieving process CPU time.
diff --git a/xcomp/erl-xcomp-mips-linux.conf b/xcomp/erl-xcomp-mips-linux.conf
index 3ac057bb4c..2195b7d6e9 100644
--- a/xcomp/erl-xcomp-mips-linux.conf
+++ b/xcomp/erl-xcomp-mips-linux.conf
@@ -187,6 +187,15 @@ CFLAGS=-Os
# value is used, `configure' will try to figure this out automatically.
#erl_xcomp_bigendian=
+# * `erl_xcomp_double_middle_endian` - `yes|no`. No default. If `yes`, the
+# target system must have doubles in "middle-endian" format. If
+# `no`, it has "regular" endianness. This can often be automatically
+# detected, but not always. If not automatically detected,
+# `configure` will fail unless this variable is set. Since no
+# default value is used, `configure` will try to figure this out
+# automatically.
+#erl_xcomp_double_middle_endian
+
# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
# the target system must have a working `clock_gettime()' implementation
# that can be used for retrieving process CPU time.
diff --git a/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf b/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf
new file mode 100644
index 0000000000..735c986486
--- /dev/null
+++ b/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf
@@ -0,0 +1,258 @@
+## -*-shell-script-*-
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2009-2010. All Rights Reserved.
+##
+## The contents of this file are subject to the Erlang Public License,
+## Version 1.1, (the "License"); you may not use this file except in
+## compliance with the License. You should have received a copy of the
+## Erlang Public License along with this software. If not, it can be
+## retrieved online at http://www.erlang.org/.
+##
+## Software distributed under the License is distributed on an "AS IS"
+## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+## the License for the specific language governing rights and limitations
+## under the License.
+##
+## %CopyrightEnd%
+##
+## File: erl-xcomp.conf.template
+## Author: Rickard Green
+##
+## -----------------------------------------------------------------------------
+## When cross compiling Erlang/OTP using `otp_build', copy this file and set
+## the variables needed below. Then pass the path to the copy of this file as
+## an argument to `otp_build' in the configure stage:
+## `otp_build configure --xcomp-conf=<FILE>'
+## -----------------------------------------------------------------------------
+
+## Note that you cannot define arbitrary variables in a cross compilation
+## configuration file. Only the ones listed below will be guaranteed to be
+## visible throughout the whole execution of all `configure' scripts. Other
+## variables needs to be defined as arguments to `configure' or exported in
+## the environment.
+
+## -- Variables for `otp_build' Only -------------------------------------------
+
+## Variables in this section are only used, when configuring Erlang/OTP for
+## cross compilation using `$ERL_TOP/otp_build configure'.
+
+## *NOTE*! These variables currently have *no* effect if you configure using
+## the `configure' script directly.
+
+# * `erl_xcomp_build' - The build system used. This value will be passed as
+# `--build=$erl_xcomp_build' argument to the `configure' script. It does
+# not have to be a full `CPU-VENDOR-OS' triplet, but can be. The full
+# `CPU-VENDOR-OS' triplet will be created by
+# `$ERL_TOP/erts/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
+# the build system will be guessed using
+# `$ERL_TOP/erts/autoconf/config.guess'.
+erl_xcomp_build=guess
+
+# * `erl_xcomp_host' - Cross host/target system to build for. This value will
+# be passed as `--host=$erl_xcomp_host' argument to the `configure' script.
+# It does not have to be a full `CPU-VENDOR-OS' triplet, but can be. The
+# full `CPU-VENDOR-OS' triplet will be created by
+# `$ERL_TOP/erts/autoconf/config.sub $erl_xcomp_host'.
+erl_xcomp_host=powerpc-dso-linux-gnu
+
+# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
+# `configure' script.
+erl_xcomp_configure_flags=--without-termcap
+
+## -- Cross Compiler and Other Tools -------------------------------------------
+
+## If the cross compilation tools are prefixed by `<HOST>-' you probably do
+## not need to set these variables (where `<HOST>' is what has been passed as
+## `--host=<HOST>' argument to `configure').
+
+## All variables in this section can also be used when native compiling.
+
+# * `CC' - C compiler.
+CC=powerpc-dso-linux-gnu-gcc
+
+# * `CFLAGS' - C compiler flags.
+#CFLAGS=
+
+# * `STATIC_CFLAGS' - Static C compiler flags.
+#STATIC_CFLAGS=
+
+# * `CFLAG_RUNTIME_LIBRARY_PATH' - This flag should set runtime library
+# search path for the shared libraries. Note that this actually is a
+# linker flag, but it needs to be passed via the compiler.
+#CFLAG_RUNTIME_LIBRARY_PATH=
+
+# * `CPP' - C pre-processor.
+#CPP=
+
+# * `CPPFLAGS' - C pre-processor flags.
+#CPPFLAGS=
+
+# * `CXX' - C++ compiler.
+CXX=powerpc-dso-linux-gnu-g++
+
+# * `CXXFLAGS' - C++ compiler flags.
+#CXXFLAGS=
+
+# * `LD' - Linker.
+LD=powerpc-dso-linux-gnu-ld
+
+# * `LDFLAGS' - Linker flags.
+#LDFLAGS=
+
+# * `LIBS' - Libraries.
+#LIBS=
+
+## -- *D*ynamic *E*rlang *D*river Linking --
+
+## *NOTE*! Either set all or none of the `DED_LD*' variables.
+
+# * `DED_LD' - Linker for Dynamically loaded Erlang Drivers.
+#DED_LD=
+
+# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
+#DED_LDFLAGS=
+
+# * `DED_LD_FLAG_RUNTIME_LIBRARY_PATH' - This flag should set runtime library
+# search path for shared libraries when linking with `DED_LD'.
+#DED_LD_FLAG_RUNTIME_LIBRARY_PATH=
+
+## -- Large File Support --
+
+## *NOTE*! Either set all or none of the `LFS_*' variables.
+
+# * `LFS_CFLAGS' - Large file support C compiler flags.
+#LFS_CFLAGS=
+
+# * `LFS_LDFLAGS' - Large file support linker flags.
+#LFS_LDFLAGS=
+
+# * `LFS_LIBS' - Large file support libraries.
+#LFS_LIBS=
+
+## -- Other Tools --
+
+# * `RANLIB' - `ranlib' archive index tool.
+RANLIB=powerpc-dso-linux-gnu-ranlib
+
+# * `AR' - `ar' archiving tool.
+AR=powerpc-dso-linux-gnu-ar
+
+# * `GETCONF' - `getconf' system configuration inspection tool. `getconf' is
+# currently used for finding out large file support flags to use, and
+# on Linux systems for finding out if we have an NPTL thread library or
+# not.
+#GETCONF=
+
+## -- Cross System Root Locations ----------------------------------------------
+
+# * `erl_xcomp_sysroot' - The absolute path to the system root of the cross
+# compilation environment. Currently, the `crypto', `odbc', `ssh' and
+# `ssl' applications need the system root. These applications will be
+# skipped if the system root has not been set. The system root might be
+# needed for other things too. If this is the case and the system root
+# has not been set, `configure' will fail and request you to set it.
+erl_xcomp_sysroot="$DSO_SYSROOT_POWERPC"
+
+# * `erl_xcomp_isysroot' - The absolute path to the system root for includes
+# of the cross compilation environment. If not set, this value defaults
+# to `$erl_xcomp_sysroot', i.e., only set this value if the include system
+# root path is not the same as the system root path.
+#erl_xcomp_isysroot=
+
+## -- Optional Feature, and Bug Tests ------------------------------------------
+
+## These tests cannot (always) be done automatically when cross compiling. You
+## usually do not need to set these variables. Only set these if you really
+## know what you are doing.
+
+## Note that some of these values will override results of tests performed
+## by `configure', and some will not be used until `configure' is sure that
+## it cannot figure the result out.
+
+## The `configure' script will issue a warning when a default value is used.
+## When a variable has been set, no warning will be issued.
+
+# * `erl_xcomp_after_morecore_hook' - `yes|no'. Defaults to `no'. If `yes',
+# the target system must have a working `__after_morecore_hook' that can be
+# used for tracking used `malloc()' implementations core memory usage.
+# This is currently only used by unsupported features.
+erl_xcomp_after_morecore_hook=yes
+
+# * `erl_xcomp_bigendian' - `yes|no'. No default. If `yes', the target system
+# must be big endian. If `no', little endian. This can often be
+# automatically detected, but not always. If not automatically detected,
+# `configure' will fail unless this variable is set. Since no default
+# value is used, `configure' will try to figure this out automatically.
+#erl_xcomp_bigendian=
+
+# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
+# the target system must have a working `clock_gettime()' implementation
+# that can be used for retrieving process CPU time.
+#erl_xcomp_clock_gettime_cpu_time=
+
+# * `erl_xcomp_getaddrinfo' - `yes|no'. Defaults to `no'. If `yes', the target
+# system must have a working `getaddrinfo()' implementation that can
+# handle both IPv4 and IPv6.
+erl_xcomp_getaddrinfo=yes
+
+# * `erl_xcomp_gethrvtime_procfs_ioctl' - `yes|no'. Defaults to `no'. If `yes',
+# the target system must have a working `gethrvtime()' implementation and
+# is used with procfs `ioctl()'.
+#erl_xcomp_gethrvtime_procfs_ioctl=
+
+# * `erl_xcomp_dlsym_brk_wrappers' - `yes|no'. Defaults to `no'. If `yes', the
+# target system must have a working `dlsym(RTLD_NEXT, <S>)' implementation
+# that can be used on `brk' and `sbrk' symbols used by the `malloc()'
+# implementation in use, and by this track the `malloc()' implementations
+# core memory usage. This is currently only used by unsupported features.
+#erl_xcomp_dlsym_brk_wrappers=
+
+# * `erl_xcomp_kqueue' - `yes|no'. Defaults to `no'. If `yes', the target
+# system must have a working `kqueue()' implementation that returns a file
+# descriptor which can be used by `poll()' and/or `select()'. If `no' and
+# the target system has not got `epoll()' or `/dev/poll', the kernel-poll
+# feature will be disabled.
+#erl_xcomp_kqueue=
+
+# * `erl_xcomp_linux_clock_gettime_correction' - `yes|no'. Defaults to `yes' on
+# Linux; otherwise, `no'. If `yes', `clock_gettime(CLOCK_MONOTONIC, _)' on
+# the target system must work. This variable is recommended to be set to
+# `no' on Linux systems with kernel versions less than 2.6.
+#erl_xcomp_linux_clock_gettime_correction=
+
+# * `erl_xcomp_linux_nptl' - `yes|no'. Defaults to `yes' on Linux; otherwise,
+# `no'. If `yes', the target system must have NPTL (Native POSIX Thread
+# Library). Older Linux systems have LinuxThreads instead of NPTL (Linux
+# kernel versions typically less than 2.6).
+#erl_xcomp_linux_nptl=
+
+# * `erl_xcomp_linux_usable_sigaltstack' - `yes|no'. Defaults to `yes' on Linux;
+# otherwise, `no'. If `yes', `sigaltstack()' must be usable on the target
+# system. `sigaltstack()' on Linux kernel versions less than 2.4 are
+# broken.
+#erl_xcomp_linux_usable_sigaltstack=
+
+# * `erl_xcomp_linux_usable_sigusrx' - `yes|no'. Defaults to `yes'. If `yes',
+# the `SIGUSR1' and `SIGUSR2' signals must be usable by the ERTS. Old
+# LinuxThreads thread libraries (Linux kernel versions typically less than
+# 2.2) used these signals and made them unusable by the ERTS.
+#erl_xcomp_linux_usable_sigusrx=
+
+# * `erl_xcomp_poll' - `yes|no'. Defaults to `no' on Darwin/MacOSX; otherwise,
+# `yes'. If `yes', the target system must have a working `poll()'
+# implementation that also can handle devices. If `no', `select()' will be
+# used instead of `poll()'.
+#erl_xcomp_poll=
+
+# * `erl_xcomp_putenv_copy' - `yes|no'. Defaults to `no'. If `yes', the target
+# system must have a `putenv()' implementation that stores a copy of the
+# key/value pair.
+#erl_xcomp_putenv_copy=
+
+# * `erl_xcomp_reliable_fpe' - `yes|no'. Defaults to `no'. If `yes', the target
+# system must have reliable floating point exceptions.
+#erl_xcomp_reliable_fpe=
+
+## -----------------------------------------------------------------------------
diff --git a/xcomp/erl-xcomp-vars.sh b/xcomp/erl-xcomp-vars.sh
index d9972eb3db..168b25262a 100644
--- a/xcomp/erl-xcomp-vars.sh
+++ b/xcomp/erl-xcomp-vars.sh
@@ -26,4 +26,4 @@
# and precious variables in $ERL_TOP/erts/aclocal.m4.
#
-erl_xcomp_vars="erl_xcomp_sysroot erl_xcomp_isysroot erl_xcomp_bigendian erl_xcomp_linux_clock_gettime_correction erl_xcomp_linux_nptl erl_xcomp_linux_usable_sigusrx erl_xcomp_linux_usable_sigaltstack erl_xcomp_poll erl_xcomp_kqueue erl_xcomp_putenv_copy erl_xcomp_reliable_fpe erl_xcomp_getaddrinfo erl_xcomp_gethrvtime_procfs_ioctl erl_xcomp_clock_gettime_cpu_time erl_xcomp_after_morecore_hook erl_xcomp_dlsym_brk_wrappers"
+erl_xcomp_vars="erl_xcomp_sysroot erl_xcomp_isysroot erl_xcomp_bigendian erl_xcomp_double_middle_endian erl_xcomp_linux_clock_gettime_correction erl_xcomp_linux_nptl erl_xcomp_linux_usable_sigusrx erl_xcomp_linux_usable_sigaltstack erl_xcomp_poll erl_xcomp_kqueue erl_xcomp_putenv_copy erl_xcomp_reliable_fpe erl_xcomp_getaddrinfo erl_xcomp_gethrvtime_procfs_ioctl erl_xcomp_clock_gettime_cpu_time erl_xcomp_after_morecore_hook erl_xcomp_dlsym_brk_wrappers"
diff --git a/xcomp/erl-xcomp-vxworks_ppc32.conf b/xcomp/erl-xcomp-vxworks_ppc32.conf
index ed8305ea93..bea4b3e374 100644
--- a/xcomp/erl-xcomp-vxworks_ppc32.conf
+++ b/xcomp/erl-xcomp-vxworks_ppc32.conf
@@ -187,6 +187,15 @@ AR="$WIND_BASE/gnu/3.4.4-vxworks-6.3/$WIND_HOST_TYPE/bin/arppc"
# value is used, `configure' will try to figure this out automatically.
erl_xcomp_bigendian=yes
+# * `erl_xcomp_double_middle_endian` - `yes|no`. No default. If `yes`, the
+# target system must have doubles in "middle-endian" format. If
+# `no`, it has "regular" endianness. This can often be automatically
+# detected, but not always. If not automatically detected,
+# `configure` will fail unless this variable is set. Since no
+# default value is used, `configure` will try to figure this out
+# automatically.
+#erl_xcomp_double_middle_endian
+
# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
# the target system must have a working `clock_gettime()' implementation
# that can be used for retrieving process CPU time.
diff --git a/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf b/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
index f645ddbd96..de9118ae30 100644
--- a/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
+++ b/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
@@ -187,6 +187,15 @@ erl_xcomp_after_morecore_hook=yes
# value is used, `configure' will try to figure this out automatically.
#erl_xcomp_bigendian=
+# * `erl_xcomp_double_middle_endian` - `yes|no`. No default. If `yes`, the
+# target system must have doubles in "middle-endian" format. If
+# `no`, it has "regular" endianness. This can often be automatically
+# detected, but not always. If not automatically detected,
+# `configure` will fail unless this variable is set. Since no
+# default value is used, `configure` will try to figure this out
+# automatically.
+#erl_xcomp_double_middle_endian
+
# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
# the target system must have a working `clock_gettime()' implementation
# that can be used for retrieving process CPU time.
diff --git a/xcomp/erl-xcomp.conf.template b/xcomp/erl-xcomp.conf.template
index eb331ffe92..c215f0fb13 100644
--- a/xcomp/erl-xcomp.conf.template
+++ b/xcomp/erl-xcomp.conf.template
@@ -187,6 +187,15 @@
# value is used, `configure' will try to figure this out automatically.
#erl_xcomp_bigendian=
+# * `erl_xcomp_double_middle` - `yes|no`. No default. If `yes`, the
+# target system must have doubles in "middle-endian" format. If
+# `no`, it has "regular" endianness. This can often be automatically
+# detected, but not always. If not automatically detected,
+# `configure` will fail unless this variable is set. Since no
+# default value is used, `configure` will try to figure this out
+# automatically.
+#erl_xcomp_double_middle_endian
+
# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
# the target system must have a working `clock_gettime()' implementation
# that can be used for retrieving process CPU time.